From 9e0e20904a21088172afed30c0d226490cab6113 Mon Sep 17 00:00:00 2001 From: Marc Fiuczynski Date: Tue, 29 Mar 2005 19:35:05 +0000 Subject: [PATCH] ckrm-E17 --- CREDITS | 176 +- Documentation/00-INDEX | 54 +- Documentation/CodingStyle | 4 +- Documentation/DMA-API.txt | 81 +- Documentation/DocBook/Makefile | 19 +- Documentation/DocBook/deviceiobook.tmpl | 103 +- Documentation/DocBook/gadget.tmpl | 245 +- Documentation/DocBook/kernel-api.tmpl | 5 + Documentation/DocBook/kernel-hacking.tmpl | 6 +- Documentation/DocBook/libata.tmpl | 192 +- Documentation/DocBook/procfs-guide.tmpl | 4 +- Documentation/DocBook/usb.tmpl | 1 + Documentation/DocBook/videobook.tmpl | 14 +- Documentation/IO-mapping.txt | 7 +- Documentation/IPMI.txt | 30 + Documentation/RCU/listRCU.txt | 2 +- Documentation/arm/Booting | 4 + Documentation/arm/IXP2000 | 10 +- Documentation/arm/IXP4xx | 11 +- Documentation/arm/README | 4 +- .../arm/Samsung-S3C24XX/EB2410ITX.txt | 24 +- .../arm/Samsung-S3C24XX/Overview.txt | 19 +- Documentation/arm/Sharp-LH/IOBarrier | 33 +- Documentation/block/as-iosched.txt | 2 +- Documentation/block/biodoc.txt | 3 +- Documentation/block/deadline-iosched.txt | 2 +- Documentation/cachetlb.txt | 4 - Documentation/cdrom/00-INDEX | 2 + Documentation/cdrom/cdrom-standard.tex | 12 +- Documentation/ckrm/ckrm_basics | 12 +- Documentation/ckrm/core_usage | 10 +- Documentation/computone.txt | 15 +- Documentation/cpqarray.txt | 54 +- Documentation/cpu-freq/user-guide.txt | 1 + Documentation/crypto/api-intro.txt | 7 + Documentation/devices.txt | 150 +- Documentation/digiepca.txt | 26 +- Documentation/dnotify.txt | 6 + Documentation/driver-model/bus.txt | 74 +- Documentation/dvb/avermedia.txt | 26 +- Documentation/dvb/cards.txt | 18 +- Documentation/dvb/contributors.txt | 2 + Documentation/dvb/readme.txt | 13 +- Documentation/dvb/ttusb-dec.txt | 40 +- Documentation/fb/matroxfb.txt | 7 + Documentation/fb/vesafb.txt | 7 +- Documentation/filesystems/Locking | 41 +- Documentation/filesystems/devfs/ChangeLog | 2 +- Documentation/filesystems/devfs/README | 47 - Documentation/filesystems/ext2.txt | 40 +- Documentation/filesystems/ext3.txt | 72 +- Documentation/filesystems/ntfs.txt | 213 +- Documentation/filesystems/proc.txt | 129 +- Documentation/filesystems/tmpfs.txt | 12 +- Documentation/filesystems/ufs.txt | 15 +- Documentation/filesystems/vfs.txt | 199 +- Documentation/filesystems/xfs.txt | 29 +- .../firmware_sample_firmware_class.c | 3 +- Documentation/firmware_class/hotplug-script | 4 +- Documentation/floppy.txt | 48 +- Documentation/ftape.txt | 96 +- Documentation/hw_random.txt | 69 - Documentation/i2c/dev-interface | 4 +- Documentation/i2c/sysfs-interface | 34 +- Documentation/i2c/writing-clients | 74 +- Documentation/i386/zero-page.txt | 3 +- Documentation/ide.txt | 11 +- Documentation/input/joystick-parport.txt | 13 +- Documentation/ioctl-number.txt | 1 + Documentation/kbuild/makefiles.txt | 183 +- Documentation/kbuild/modules.txt | 487 +- Documentation/kernel-parameters.txt | 187 +- Documentation/laptop-mode.txt | 2 +- Documentation/md.txt | 23 +- Documentation/memory.txt | 6 +- Documentation/networking/e100.txt | 138 +- Documentation/networking/e1000.txt | 217 +- Documentation/networking/ip-sysctl.txt | 11 + Documentation/networking/ixgb.txt | 37 +- Documentation/networking/netdevices.txt | 13 + Documentation/nmi_watchdog.txt | 14 + Documentation/parisc/registers | 23 +- Documentation/pci.txt | 32 +- Documentation/pm.txt | 8 +- Documentation/power/pci.txt | 51 +- Documentation/power/swsusp.txt | 104 +- Documentation/power/video.txt | 11 +- Documentation/powerpc/hvcs.txt | 39 +- Documentation/powerpc/mpc52xx.txt | 11 +- Documentation/ramdisk.txt | 141 +- Documentation/rocket.txt | 108 +- Documentation/s390/s390dbf.txt | 55 +- Documentation/sched-domains.txt | 27 +- Documentation/scsi/ChangeLog.megaraid | 265 +- Documentation/scsi/scsi_mid_low_api.txt | 306 +- Documentation/scsi/sym53c8xx_2.txt | 358 +- Documentation/sonypi.txt | 62 +- .../sound/alsa/ALSA-Configuration.txt | 45 +- .../sound/alsa/DocBook/alsa-driver-api.tmpl | 1 - .../alsa/DocBook/writing-an-alsa-driver.tmpl | 499 +- Documentation/sound/alsa/Joystick.txt | 10 +- Documentation/sound/oss/README.modules | 5 +- Documentation/sysctl/kernel.txt | 22 +- Documentation/sysctl/vm.txt | 4 +- Documentation/time_interpolators.txt | 23 +- Documentation/tipar.txt | 26 +- Documentation/tty.txt | 7 +- Documentation/usb/error-codes.txt | 43 +- Documentation/usb/silverlink.txt | 6 +- Documentation/usb/sn9c102.txt | 266 +- Documentation/usb/usb-serial.txt | 56 + Documentation/usb/w9968cf.txt | 51 +- Documentation/video4linux/meye.txt | 38 +- Documentation/vm/overcommit-accounting | 11 +- Documentation/watchdog/pcwd-watchdog.txt | 3 +- Documentation/x86_64/boot-options.txt | 40 +- MAINTAINERS | 268 +- Makefile | 383 +- arch/alpha/Kconfig | 108 +- arch/alpha/Makefile | 16 +- arch/alpha/boot/Makefile | 2 +- arch/alpha/boot/bootloader.lds | 1 + arch/alpha/boot/bootp.c | 19 +- arch/alpha/boot/bootpz.c | 25 +- arch/alpha/boot/head.S | 21 + arch/alpha/boot/misc.c | 12 - arch/alpha/defconfig | 140 +- arch/alpha/kernel/Makefile | 4 +- arch/alpha/kernel/alpha_ksyms.c | 61 +- arch/alpha/kernel/console.c | 2 +- arch/alpha/kernel/core_cia.c | 4 +- arch/alpha/kernel/core_irongate.c | 20 +- arch/alpha/kernel/core_marvel.c | 227 +- arch/alpha/kernel/core_titan.c | 50 +- arch/alpha/kernel/err_titan.c | 2 +- arch/alpha/kernel/irq.c | 46 +- arch/alpha/kernel/irq_impl.h | 29 - arch/alpha/kernel/machvec_impl.h | 101 +- arch/alpha/kernel/osf_sys.c | 142 +- arch/alpha/kernel/pci-noop.c | 75 +- arch/alpha/kernel/pci.c | 69 +- arch/alpha/kernel/pci_impl.h | 1 - arch/alpha/kernel/pci_iommu.c | 39 + arch/alpha/kernel/process.c | 3 +- arch/alpha/kernel/ptrace.c | 21 +- arch/alpha/kernel/signal.c | 43 +- arch/alpha/kernel/smp.c | 23 +- arch/alpha/kernel/srmcons.c | 41 +- arch/alpha/kernel/sys_alcor.c | 8 +- arch/alpha/kernel/sys_cabriolet.c | 7 +- arch/alpha/kernel/sys_dp264.c | 15 +- arch/alpha/kernel/sys_eb64p.c | 4 +- arch/alpha/kernel/sys_eiger.c | 3 +- arch/alpha/kernel/sys_jensen.c | 3 - arch/alpha/kernel/sys_marvel.c | 3 +- arch/alpha/kernel/sys_miata.c | 1 - arch/alpha/kernel/sys_mikasa.c | 4 +- arch/alpha/kernel/sys_nautilus.c | 3 +- arch/alpha/kernel/sys_noritake.c | 4 +- arch/alpha/kernel/sys_rawhide.c | 1 - arch/alpha/kernel/sys_ruffian.c | 1 - arch/alpha/kernel/sys_rx164.c | 3 +- arch/alpha/kernel/sys_sable.c | 3 - arch/alpha/kernel/sys_sio.c | 5 - arch/alpha/kernel/sys_sx164.c | 3 +- arch/alpha/kernel/sys_takara.c | 1 - arch/alpha/kernel/sys_titan.c | 20 +- arch/alpha/kernel/sys_wildfire.c | 3 +- arch/alpha/kernel/systbls.S | 1 + arch/alpha/kernel/time.c | 9 +- arch/alpha/kernel/traps.c | 4 +- arch/alpha/kernel/vmlinux.lds.S | 6 +- arch/alpha/lib/Makefile | 1 - arch/alpha/lib/csum_partial_copy.c | 11 +- arch/alpha/lib/dec_and_lock.c | 8 +- arch/alpha/mm/fault.c | 2 +- arch/alpha/mm/numa.c | 2 +- arch/arm/Kconfig | 335 +- arch/arm/Kconfig.debug | 5 +- arch/arm/Makefile | 63 +- arch/arm/boot/Makefile | 76 +- arch/arm/boot/compressed/Makefile | 16 +- arch/arm/boot/compressed/head-sa1100.S | 36 +- arch/arm/boot/compressed/head-xscale.S | 31 +- arch/arm/boot/compressed/head.S | 47 + arch/arm/boot/compressed/misc.c | 24 +- arch/arm/common/Makefile | 2 + arch/arm/common/amba.c | 2 +- arch/arm/common/dmabounce.c | 34 +- arch/arm/common/locomo.c | 23 +- arch/arm/common/sa1111.c | 42 +- arch/arm/common/time-acorn.c | 33 +- arch/arm/configs/bast_defconfig | 179 +- arch/arm/configs/ebsa110_defconfig | 1 - arch/arm/configs/ep80219_defconfig | 88 +- arch/arm/configs/integrator_defconfig | 768 +- arch/arm/configs/iq31244_defconfig | 86 +- arch/arm/configs/iq80321_defconfig | 479 +- arch/arm/configs/iq80331_defconfig | 86 +- arch/arm/configs/ixp4xx_defconfig | 1 - arch/arm/configs/pleb_defconfig | 676 +- arch/arm/configs/s3c2410_defconfig | 141 +- arch/arm/configs/versatile_defconfig | 12 +- arch/arm/kernel/Makefile | 7 +- arch/arm/kernel/apm.c | 362 +- arch/arm/kernel/armksyms.c | 100 +- arch/arm/kernel/asm-offsets.c | 18 +- arch/arm/kernel/bios32.c | 65 +- arch/arm/kernel/calls.S | 9 +- arch/arm/kernel/debug.S | 126 +- arch/arm/kernel/ecard.c | 123 +- arch/arm/kernel/entry-armv.S | 224 +- arch/arm/kernel/fiq.c | 33 +- arch/arm/kernel/head.S | 109 +- arch/arm/kernel/io.c | 6 +- arch/arm/kernel/irq.c | 67 +- arch/arm/kernel/module.c | 13 + arch/arm/kernel/process.c | 8 + arch/arm/kernel/ptrace.c | 9 +- arch/arm/kernel/semaphore.c | 8 +- arch/arm/kernel/setup.c | 34 +- arch/arm/kernel/signal.c | 191 +- arch/arm/kernel/sys_arm.c | 29 +- arch/arm/kernel/time.c | 144 +- arch/arm/kernel/traps.c | 29 +- arch/arm/kernel/vmlinux.lds.S | 39 +- arch/arm/lib/Makefile | 6 +- arch/arm/lib/csumpartial.S | 3 +- arch/arm/lib/csumpartialcopygeneric.S | 3 +- arch/arm/lib/delay.S | 13 +- arch/arm/lib/getuser.S | 63 +- arch/arm/lib/io-writesl.S | 57 +- arch/arm/lib/longlong.h | 1 - arch/arm/lib/putuser.S | 61 +- arch/arm/mach-clps711x/autcpu12.c | 6 +- arch/arm/mach-clps711x/cdb89712.c | 14 +- arch/arm/mach-clps711x/ceiva.c | 5 +- arch/arm/mach-clps711x/clep7312.c | 6 +- arch/arm/mach-clps711x/edb7211-arch.c | 6 +- arch/arm/mach-clps711x/fortunet.c | 6 +- arch/arm/mach-clps711x/p720t.c | 6 +- arch/arm/mach-clps711x/time.c | 10 +- arch/arm/mach-clps7500/core.c | 65 +- arch/arm/mach-ebsa110/core.c | 51 +- arch/arm/mach-ebsa110/io.c | 58 +- arch/arm/mach-epxa10db/arch.c | 35 +- arch/arm/mach-epxa10db/time.c | 7 +- arch/arm/mach-footbridge/Kconfig | 23 + arch/arm/mach-footbridge/Makefile | 13 +- arch/arm/mach-footbridge/cats-hw.c | 30 + arch/arm/mach-footbridge/netwinder-hw.c | 48 +- arch/arm/mach-footbridge/time.c | 122 +- arch/arm/mach-h720x/Kconfig | 4 + arch/arm/mach-h720x/cpu-h7201.c | 17 +- arch/arm/mach-h720x/cpu-h7202.c | 59 +- arch/arm/mach-h720x/h7201-eval.c | 7 +- arch/arm/mach-h720x/h7202-eval.c | 8 +- arch/arm/mach-imx/generic.h | 4 +- arch/arm/mach-imx/mx1ads.c | 2 +- arch/arm/mach-imx/time.c | 16 +- arch/arm/mach-integrator/clock.c | 9 +- arch/arm/mach-integrator/core.c | 11 +- arch/arm/mach-integrator/cpu.c | 8 +- arch/arm/mach-integrator/impd1.c | 191 + arch/arm/mach-integrator/integrator_ap.c | 11 +- arch/arm/mach-integrator/integrator_cp.c | 87 +- arch/arm/mach-iop3xx/Kconfig | 61 +- arch/arm/mach-iop3xx/Makefile | 21 +- arch/arm/mach-iop3xx/common.c | 1 - arch/arm/mach-iop3xx/iop321-irq.c | 3 +- arch/arm/mach-iop3xx/iop321-pci.c | 64 +- arch/arm/mach-iop3xx/iop321-setup.c | 75 +- arch/arm/mach-iop3xx/iop321-time.c | 42 +- arch/arm/mach-iop3xx/iop331-setup.c | 5 +- arch/arm/mach-iop3xx/iop331-time.c | 62 +- arch/arm/mach-iop3xx/iq80321-pci.c | 83 +- arch/arm/mach-ixp2000/core.c | 58 +- arch/arm/mach-ixp2000/enp2611.c | 12 +- arch/arm/mach-ixp2000/ixdp2400.c | 12 +- arch/arm/mach-ixp2000/ixdp2800.c | 12 +- arch/arm/mach-ixp2000/ixdp2x00.c | 9 +- arch/arm/mach-ixp2000/ixdp2x01.c | 49 +- arch/arm/mach-ixp2000/pci.c | 8 +- arch/arm/mach-ixp4xx/Kconfig | 7 + arch/arm/mach-ixp4xx/Makefile | 1 + arch/arm/mach-ixp4xx/common-pci.c | 31 +- arch/arm/mach-ixp4xx/common.c | 19 +- arch/arm/mach-ixp4xx/coyote-setup.c | 37 +- arch/arm/mach-ixp4xx/ixdp425-setup.c | 6 +- arch/arm/mach-ixp4xx/prpmc1100-setup.c | 2 +- arch/arm/mach-lh7a40x/arch-kev7a400.c | 8 +- arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 25 +- arch/arm/mach-lh7a40x/time.c | 18 +- arch/arm/mach-omap/Kconfig | 65 +- arch/arm/mach-omap/Makefile | 12 +- arch/arm/mach-omap/board-generic.c | 61 +- arch/arm/mach-omap/board-h2.c | 22 +- arch/arm/mach-omap/board-h3.c | 15 +- arch/arm/mach-omap/board-innovator.c | 82 +- arch/arm/mach-omap/board-osk.c | 22 +- arch/arm/mach-omap/board-perseus2.c | 17 +- arch/arm/mach-omap/common.c | 450 +- arch/arm/mach-omap/common.h | 7 +- arch/arm/mach-omap/dma.c | 536 +- arch/arm/mach-omap/fpga.c | 30 +- arch/arm/mach-omap/gpio.c | 30 +- arch/arm/mach-omap/irq.c | 20 +- arch/arm/mach-omap/leds.c | 9 +- arch/arm/mach-omap/leds.h | 2 +- arch/arm/mach-omap/mcbsp.c | 32 +- arch/arm/mach-omap/mux.c | 60 +- arch/arm/mach-omap/ocpi.c | 16 +- arch/arm/mach-omap/time.c | 229 +- arch/arm/mach-omap/usb.c | 116 +- arch/arm/mach-pxa/Kconfig | 7 +- arch/arm/mach-pxa/dma.c | 1 + arch/arm/mach-pxa/generic.c | 13 +- arch/arm/mach-pxa/generic.h | 4 +- arch/arm/mach-pxa/idp.c | 5 +- arch/arm/mach-pxa/irq.c | 103 +- arch/arm/mach-pxa/leds-lubbock.c | 1 + arch/arm/mach-pxa/leds-mainstone.c | 1 + arch/arm/mach-pxa/lubbock.c | 21 +- arch/arm/mach-pxa/mainstone.c | 61 +- arch/arm/mach-pxa/pm.c | 35 +- arch/arm/mach-pxa/pxa25x.c | 1 + arch/arm/mach-pxa/pxa27x.c | 45 + arch/arm/mach-pxa/sleep.S | 43 +- arch/arm/mach-pxa/time.c | 44 +- arch/arm/mach-rpc/riscpc.c | 101 +- arch/arm/mach-s3c2410/Kconfig | 90 +- arch/arm/mach-s3c2410/Makefile | 29 +- arch/arm/mach-s3c2410/clock.c | 193 +- arch/arm/mach-s3c2410/clock.h | 29 +- arch/arm/mach-s3c2410/cpu.c | 50 +- arch/arm/mach-s3c2410/cpu.h | 18 + arch/arm/mach-s3c2410/devs.c | 6 + arch/arm/mach-s3c2410/dma.c | 99 +- arch/arm/mach-s3c2410/gpio.c | 135 +- arch/arm/mach-s3c2410/irq.c | 283 +- arch/arm/mach-s3c2410/mach-bast.c | 138 +- arch/arm/mach-s3c2410/mach-h1940.c | 58 +- arch/arm/mach-s3c2410/mach-smdk2410.c | 35 +- arch/arm/mach-s3c2410/mach-vr1000.c | 93 +- arch/arm/mach-s3c2410/s3c2410.c | 120 +- arch/arm/mach-s3c2410/s3c2410.h | 24 +- arch/arm/mach-s3c2410/s3c2440-dsc.c | 7 +- arch/arm/mach-s3c2410/s3c2440.c | 145 +- arch/arm/mach-s3c2410/s3c2440.h | 7 +- arch/arm/mach-s3c2410/time.c | 147 +- arch/arm/mach-s3c2410/usb-simtec.c | 20 +- arch/arm/mach-sa1100/Kconfig | 174 +- arch/arm/mach-sa1100/Makefile | 46 +- arch/arm/mach-sa1100/assabet.c | 120 +- arch/arm/mach-sa1100/badge4.c | 47 +- arch/arm/mach-sa1100/cerf.c | 64 +- arch/arm/mach-sa1100/collie.c | 52 +- arch/arm/mach-sa1100/cpu-sa1100.c | 4 +- arch/arm/mach-sa1100/cpu-sa1110.c | 4 +- arch/arm/mach-sa1100/generic.c | 59 +- arch/arm/mach-sa1100/generic.h | 13 +- arch/arm/mach-sa1100/h3600.c | 107 +- arch/arm/mach-sa1100/hackkit.c | 70 +- arch/arm/mach-sa1100/jornada720.c | 2 +- arch/arm/mach-sa1100/lart.c | 4 +- arch/arm/mach-sa1100/leds-simpad.c | 7 +- arch/arm/mach-sa1100/neponset.c | 23 +- arch/arm/mach-sa1100/pleb.c | 121 +- arch/arm/mach-sa1100/pm.c | 35 +- arch/arm/mach-sa1100/shannon.c | 40 +- arch/arm/mach-sa1100/simpad.c | 151 +- arch/arm/mach-sa1100/sleep.S | 4 +- arch/arm/mach-sa1100/time.c | 44 +- arch/arm/mach-shark/core.c | 51 +- arch/arm/mach-versatile/Makefile | 2 + arch/arm/mach-versatile/clock.c | 11 +- arch/arm/mach-versatile/clock.h | 6 +- arch/arm/mach-versatile/core.c | 385 +- arch/arm/mm/Kconfig | 31 +- arch/arm/mm/Makefile | 3 +- arch/arm/mm/abort-ev5tj.S | 1 - arch/arm/mm/cache-v3.S | 14 + arch/arm/mm/cache-v4.S | 14 + arch/arm/mm/cache-v4wb.S | 14 + arch/arm/mm/cache-v4wt.S | 14 + arch/arm/mm/cache-v6.S | 17 + arch/arm/mm/consistent.c | 30 +- arch/arm/mm/copypage-v6.c | 93 +- arch/arm/mm/fault-armv.c | 67 +- arch/arm/mm/init.c | 21 +- arch/arm/mm/ioremap.c | 6 +- arch/arm/mm/mm-armv.c | 69 +- arch/arm/mm/proc-arm1020.S | 14 + arch/arm/mm/proc-arm1020e.S | 15 +- arch/arm/mm/proc-arm1022.S | 16 +- arch/arm/mm/proc-arm1026.S | 15 +- arch/arm/mm/proc-arm720.S | 4 +- arch/arm/mm/proc-arm920.S | 14 + arch/arm/mm/proc-arm922.S | 14 + arch/arm/mm/proc-arm925.S | 14 + arch/arm/mm/proc-arm926.S | 16 +- arch/arm/mm/proc-syms.c | 8 +- arch/arm/mm/proc-v6.S | 19 +- arch/arm/mm/proc-xscale.S | 126 +- arch/arm/nwfpe/double_cpdo.c | 8 + arch/arm/nwfpe/fpa11_cpdt.c | 10 + arch/arm/oprofile/op_model_xscale.c | 29 +- arch/arm/tools/mach-types | 79 +- arch/arm/vfp/vfp.h | 11 + arch/arm/vfp/vfpdouble.c | 10 +- arch/arm/vfp/vfphw.S | 5 + arch/arm/vfp/vfpsingle.c | 6 +- arch/arm26/Kconfig | 117 +- arch/arm26/Makefile | 4 +- arch/arm26/boot/Makefile | 4 +- arch/arm26/kernel/Makefile | 2 +- arch/arm26/kernel/armksyms.c | 98 +- arch/arm26/kernel/irq.c | 6 +- arch/arm26/kernel/ptrace.c | 9 +- arch/arm26/kernel/signal.c | 4 +- arch/arm26/kernel/sys_arm.c | 2 +- arch/arm26/kernel/time.c | 27 +- arch/arm26/kernel/vmlinux-arm26-xip.lds.in | 3 - arch/arm26/kernel/vmlinux-arm26.lds.in | 3 - arch/arm26/machine/dma.c | 2 +- arch/arm26/machine/small_page.c | 2 +- arch/arm26/mm/init.c | 6 +- arch/cris/Kconfig | 56 +- arch/cris/Kconfig.debug | 27 +- arch/cris/Makefile | 10 +- arch/cris/arch-v10/drivers/Kconfig | 39 +- arch/cris/arch-v10/drivers/Makefile | 4 - arch/cris/arch-v10/drivers/axisflashmap.c | 61 +- arch/cris/arch-v10/drivers/ds1302.c | 5 +- arch/cris/arch-v10/drivers/gpio.c | 5 +- arch/cris/arch-v10/drivers/i2c.c | 18 +- arch/cris/arch-v10/drivers/pcf8563.c | 4 +- arch/cris/arch-v10/kernel/Makefile | 3 +- arch/cris/arch-v10/kernel/debugport.c | 468 +- arch/cris/arch-v10/kernel/entry.S | 139 +- arch/cris/arch-v10/kernel/irq.c | 33 +- arch/cris/arch-v10/kernel/kgdb.c | 7 +- arch/cris/arch-v10/kernel/process.c | 26 +- arch/cris/arch-v10/kernel/ptrace.c | 55 +- arch/cris/arch-v10/kernel/signal.c | 36 +- arch/cris/arch-v10/kernel/time.c | 6 +- arch/cris/arch-v10/mm/fault.c | 104 +- arch/cris/arch-v10/mm/init.c | 2 +- arch/cris/arch-v10/mm/tlb.c | 20 +- arch/cris/arch-v10/vmlinux.lds.S | 4 +- arch/cris/kernel/Makefile | 2 +- arch/cris/kernel/crisksyms.c | 5 +- arch/cris/kernel/irq.c | 10 +- arch/h8300/Kconfig | 75 +- arch/h8300/kernel/Makefile | 2 +- arch/h8300/kernel/asm-offsets.c | 2 +- arch/h8300/kernel/h8300_ksyms.c | 59 +- arch/h8300/kernel/ints.c | 2 +- arch/h8300/kernel/process.c | 2 +- arch/h8300/kernel/ptrace.c | 17 +- arch/h8300/kernel/setup.c | 2 +- arch/h8300/kernel/signal.c | 428 +- arch/h8300/kernel/time.c | 26 +- arch/h8300/kernel/vmlinux.lds.S | 149 +- arch/h8300/lib/checksum.c | 1 + arch/h8300/platform/h8300h/entry.S | 6 +- arch/h8300/platform/h8300h/generic/timer.c | 4 +- arch/h8300/platform/h8s/edosk2674/crt0_rom.S | 2 +- arch/h8300/platform/h8s/entry.S | 6 +- arch/h8300/platform/h8s/ints.c | 2 +- arch/i386/Kconfig | 181 +- arch/i386/Kconfig.debug | 12 - arch/i386/Makefile | 36 +- arch/i386/boot/Makefile | 4 +- arch/i386/boot/setup.S | 2 +- arch/i386/boot/video.S | 40 +- arch/i386/crypto/aes-i586-asm.S | 325 +- arch/i386/defconfig | 1 + arch/i386/kernel/Makefile | 10 +- arch/i386/kernel/acpi/Makefile | 1 + arch/i386/kernel/acpi/boot.c | 87 +- arch/i386/kernel/acpi/sleep.c | 7 +- arch/i386/kernel/acpi/wakeup.S | 25 + arch/i386/kernel/apic.c | 158 +- arch/i386/kernel/apm.c | 63 +- arch/i386/kernel/asm-offsets.c | 1 + arch/i386/kernel/cpu/Makefile | 2 +- arch/i386/kernel/cpu/centaur.c | 27 +- arch/i386/kernel/cpu/common.c | 23 +- arch/i386/kernel/cpu/cpufreq/Kconfig | 119 +- arch/i386/kernel/cpu/cpufreq/Makefile | 33 +- arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | 20 +- arch/i386/kernel/cpu/cpufreq/longhaul.c | 333 +- arch/i386/kernel/cpu/cpufreq/longrun.c | 55 +- arch/i386/kernel/cpu/cpufreq/p4-clockmod.c | 57 +- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 102 +- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 138 +- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 8 +- .../kernel/cpu/cpufreq/speedstep-centrino.c | 321 +- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 196 +- arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 51 +- arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 82 +- arch/i386/kernel/cpu/cyrix.c | 11 +- arch/i386/kernel/cpu/intel.c | 129 +- arch/i386/kernel/cpu/mcheck/k7.c | 3 +- arch/i386/kernel/cpu/mcheck/mce.c | 4 +- arch/i386/kernel/cpu/mcheck/mce.h | 2 +- arch/i386/kernel/cpu/mcheck/non-fatal.c | 1 + arch/i386/kernel/cpu/mcheck/p4.c | 9 +- arch/i386/kernel/cpu/mcheck/p5.c | 3 +- arch/i386/kernel/cpu/mcheck/p6.c | 3 +- arch/i386/kernel/cpu/mcheck/winchip.c | 3 +- arch/i386/kernel/cpu/mtrr/main.c | 32 +- arch/i386/kernel/cpu/mtrr/mtrr.h | 1 - arch/i386/kernel/cpu/nexgen.c | 2 +- arch/i386/kernel/cpu/proc.c | 8 +- arch/i386/kernel/cpu/transmeta.c | 23 +- arch/i386/kernel/dmi_scan.c | 157 +- arch/i386/kernel/doublefault.c | 2 +- arch/i386/kernel/entry.S | 103 +- arch/i386/kernel/head.S | 3 - arch/i386/kernel/i386_ksyms.c | 30 +- arch/i386/kernel/i387.c | 15 - arch/i386/kernel/i8259.c | 74 +- arch/i386/kernel/init_task.c | 7 +- arch/i386/kernel/io_apic.c | 210 +- arch/i386/kernel/ioport.c | 36 +- arch/i386/kernel/irq.c | 1186 +- arch/i386/kernel/kprobes.c | 37 +- arch/i386/kernel/ldt.c | 9 +- arch/i386/kernel/microcode.c | 32 +- arch/i386/kernel/mpparse.c | 24 +- arch/i386/kernel/nmi.c | 76 +- arch/i386/kernel/numaq.c | 1 + arch/i386/kernel/pci-dma.c | 111 +- arch/i386/kernel/process.c | 118 +- arch/i386/kernel/ptrace.c | 98 +- arch/i386/kernel/reboot.c | 15 +- arch/i386/kernel/scx200.c | 67 +- arch/i386/kernel/semaphore.c | 18 +- arch/i386/kernel/setup.c | 43 +- arch/i386/kernel/signal.c | 99 +- arch/i386/kernel/smp.c | 29 +- arch/i386/kernel/smpboot.c | 277 +- arch/i386/kernel/srat.c | 1 + arch/i386/kernel/sysenter.c | 8 +- arch/i386/kernel/time.c | 59 +- arch/i386/kernel/time_hpet.c | 79 +- arch/i386/kernel/timers/common.c | 1 + arch/i386/kernel/timers/timer.c | 16 +- arch/i386/kernel/timers/timer_cyclone.c | 8 +- arch/i386/kernel/timers/timer_hpet.c | 8 +- arch/i386/kernel/timers/timer_none.c | 6 - arch/i386/kernel/timers/timer_pit.c | 56 +- arch/i386/kernel/timers/timer_pm.c | 7 +- arch/i386/kernel/timers/timer_tsc.c | 25 +- arch/i386/kernel/traps.c | 284 +- arch/i386/kernel/vm86.c | 15 +- arch/i386/kernel/vmlinux.lds.S | 7 +- arch/i386/kernel/vsyscall-sysenter.S | 2 +- arch/i386/lib/dec_and_lock.c | 2 +- arch/i386/lib/memcpy.c | 6 +- arch/i386/lib/mmx.c | 2 +- arch/i386/lib/usercopy.c | 2 + arch/i386/mach-default/topology.c | 1 + arch/i386/mach-es7000/es7000.h | 2 +- arch/i386/mach-es7000/es7000plat.c | 44 +- arch/i386/mach-generic/bigsmp.c | 28 +- arch/i386/mach-voyager/voyager_basic.c | 2 +- arch/i386/mach-voyager/voyager_smp.c | 82 +- arch/i386/math-emu/fpu_proto.h | 1 - arch/i386/mm/Makefile | 2 +- arch/i386/mm/discontig.c | 26 +- arch/i386/mm/fault.c | 16 +- arch/i386/mm/hugetlbpage.c | 141 + arch/i386/mm/init.c | 9 +- arch/i386/mm/ioremap.c | 22 +- arch/i386/mm/mmap.c | 8 +- arch/i386/mm/pageattr.c | 3 +- arch/i386/mm/pgtable.c | 8 +- arch/i386/oprofile/op_model_athlon.c | 4 +- arch/i386/oprofile/op_model_p4.c | 40 +- arch/i386/oprofile/op_model_ppro.c | 4 +- arch/i386/pci/acpi.c | 30 +- arch/i386/pci/common.c | 6 +- arch/i386/pci/fixup.c | 256 +- arch/i386/pci/i386.c | 20 +- arch/i386/pci/irq.c | 43 +- arch/i386/pci/mmconfig.c | 21 +- arch/i386/pci/numa.c | 5 +- arch/i386/pci/pcbios.c | 2 +- arch/i386/power/Makefile | 1 - arch/i386/power/cpu.c | 6 +- arch/i386/power/swsusp.S | 76 +- arch/ia64/Kconfig | 127 +- arch/ia64/Makefile | 25 +- arch/ia64/configs/bigsur_defconfig | 73 +- arch/ia64/configs/sn2_defconfig | 101 +- arch/ia64/configs/tiger_defconfig | 59 +- arch/ia64/configs/zx1_defconfig | 662 +- arch/ia64/defconfig | 655 +- arch/ia64/hp/common/sba_iommu.c | 93 +- arch/ia64/hp/sim/simeth.c | 2 +- arch/ia64/hp/sim/simserial.c | 74 +- arch/ia64/ia32/binfmt_elf32.c | 65 +- arch/ia64/ia32/elfcore32.h | 15 +- arch/ia64/ia32/ia32_entry.S | 24 +- arch/ia64/ia32/ia32_ldt.c | 25 +- arch/ia64/ia32/ia32_signal.c | 182 +- arch/ia64/ia32/ia32_support.c | 38 +- arch/ia64/ia32/ia32priv.h | 23 +- arch/ia64/ia32/sys_ia32.c | 349 +- arch/ia64/kernel/Makefile | 14 +- arch/ia64/kernel/acpi-ext.c | 2 +- arch/ia64/kernel/acpi.c | 86 +- arch/ia64/kernel/asm-offsets.c | 30 +- arch/ia64/kernel/cyclone.c | 62 +- arch/ia64/kernel/efi.c | 43 +- arch/ia64/kernel/entry.S | 14 +- arch/ia64/kernel/fsys.S | 367 +- arch/ia64/kernel/head.S | 3 +- arch/ia64/kernel/iosapic.c | 78 +- arch/ia64/kernel/irq.c | 59 +- arch/ia64/kernel/irq_ia64.c | 9 +- arch/ia64/kernel/ivt.S | 31 +- arch/ia64/kernel/mca.c | 46 +- arch/ia64/kernel/mca_asm.S | 3 +- arch/ia64/kernel/minstate.h | 6 +- arch/ia64/kernel/module.c | 20 +- arch/ia64/kernel/palinfo.c | 4 +- arch/ia64/kernel/patch.c | 26 +- arch/ia64/kernel/perfmon.c | 179 +- arch/ia64/kernel/process.c | 42 +- arch/ia64/kernel/ptrace.c | 142 +- arch/ia64/kernel/sal.c | 38 + arch/ia64/kernel/salinfo.c | 13 +- arch/ia64/kernel/setup.c | 56 +- arch/ia64/kernel/sigframe.h | 2 +- arch/ia64/kernel/signal.c | 100 +- arch/ia64/kernel/smp.c | 12 +- arch/ia64/kernel/smpboot.c | 32 +- arch/ia64/kernel/sys_ia64.c | 6 +- arch/ia64/kernel/time.c | 243 +- arch/ia64/kernel/traps.c | 27 +- arch/ia64/kernel/unaligned.c | 18 +- arch/ia64/kernel/unwind.c | 124 +- arch/ia64/kernel/vmlinux.lds.S | 7 +- arch/ia64/lib/bitop.c | 2 +- arch/ia64/lib/csum_partial_copy.c | 12 +- arch/ia64/lib/dec_and_lock.c | 4 +- arch/ia64/lib/io.c | 29 +- arch/ia64/lib/swiotlb.c | 130 +- arch/ia64/mm/contig.c | 17 +- arch/ia64/mm/discontig.c | 67 +- arch/ia64/mm/extable.c | 2 +- arch/ia64/mm/fault.c | 8 +- arch/ia64/mm/init.c | 40 +- arch/ia64/mm/numa.c | 2 +- arch/ia64/mm/tlb.c | 2 +- arch/ia64/oprofile/Kconfig | 4 + arch/ia64/oprofile/Makefile | 1 + arch/ia64/oprofile/init.c | 9 +- arch/ia64/pci/pci.c | 140 +- arch/ia64/sn/Makefile | 6 +- arch/ia64/sn/kernel/Makefile | 3 +- arch/ia64/sn/kernel/bte.c | 129 +- arch/ia64/sn/kernel/idle.c | 12 +- arch/ia64/sn/kernel/irq.c | 518 +- arch/ia64/sn/kernel/mca.c | 43 +- arch/ia64/sn/kernel/setup.c | 396 +- arch/ia64/sn/kernel/sn2/Makefile | 2 +- arch/ia64/sn/kernel/sn2/io.c | 60 +- arch/ia64/sn/kernel/sn2/prominfo_proc.c | 256 +- arch/ia64/sn/kernel/sn2/ptc_deadlock.S | 4 +- arch/ia64/sn/kernel/sn2/sn2_smp.c | 131 +- arch/ia64/sn/kernel/sn2/sn_hwperf.c | 119 +- arch/ia64/sn/kernel/sn2/sn_proc_fs.c | 189 +- arch/ia64/sn/kernel/sn2/timer.c | 55 +- arch/ia64/sn/kernel/sn2/timer_interrupt.c | 15 +- arch/m32r/Kconfig | 98 +- arch/m32r/Makefile | 5 +- arch/m32r/boot/compressed/Makefile | 7 +- arch/m32r/boot/compressed/head.S | 96 +- arch/m32r/boot/compressed/m32r_sio.c | 24 +- arch/m32r/boot/compressed/misc.c | 53 +- arch/m32r/boot/compressed/vmlinux.lds.S | 16 +- arch/m32r/boot/compressed/vmlinux.scr | 6 +- arch/m32r/boot/setup.S | 2 +- arch/m32r/defconfig | 152 +- arch/m32r/kernel/io_m32700ut.c | 149 +- arch/m32r/kernel/io_mappi.c | 194 +- arch/m32r/kernel/io_mappi2.c | 233 +- arch/m32r/kernel/io_oaks32r.c | 66 +- arch/m32r/kernel/io_opsput.c | 131 +- arch/m32r/kernel/io_usrv.c | 6 +- arch/m32r/kernel/irq.c | 2 +- arch/m32r/kernel/process.c | 7 +- arch/m32r/kernel/ptrace.c | 2 +- arch/m32r/kernel/setup_m32700ut.c | 4 +- arch/m32r/kernel/setup_mappi.c | 2 +- arch/m32r/kernel/setup_mappi2.c | 2 +- arch/m32r/kernel/setup_opsput.c | 4 +- arch/m32r/kernel/smpboot.c | 4 +- arch/m32r/kernel/sys_m32r.c | 4 +- arch/m32r/kernel/time.c | 21 +- arch/m32r/lib/delay.c | 2 +- arch/m32r/lib/memset.S | 17 +- arch/m32r/m32700ut/defconfig.m32700ut.smp | 130 +- arch/m32r/m32700ut/defconfig.m32700ut.up | 130 +- arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB | 14 +- arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB | 24 +- arch/m32r/mappi/defconfig.nommu | 109 +- arch/m32r/mappi/defconfig.smp | 104 +- arch/m32r/mappi/defconfig.up | 104 +- arch/m32r/mappi/dot.gdbinit | 16 +- arch/m32r/mappi/dot.gdbinit.nommu | 6 +- arch/m32r/mappi/dot.gdbinit.smp | 12 +- arch/m32r/mm/init.c | 2 +- arch/m32r/oaks32r/defconfig.nommu | 93 +- arch/m32r/oaks32r/dot.gdbinit.nommu | 15 +- arch/m32r/opsput/defconfig.opsput | 114 +- arch/m32r/opsput/dot.gdbinit | 76 +- arch/m68k/Kconfig | 64 +- arch/m68k/Makefile | 2 +- arch/m68k/atari/hades-pci.c | 2 +- arch/m68k/defconfig | 580 +- arch/m68k/hp300/config.c | 265 +- arch/m68k/hp300/ints.c | 9 +- arch/m68k/hp300/reboot.S | 21 +- arch/m68k/hp300/time.c | 13 +- arch/m68k/kernel/Makefile | 2 +- arch/m68k/kernel/bios32.c | 11 +- arch/m68k/kernel/entry.S | 47 + arch/m68k/kernel/head.S | 194 +- arch/m68k/kernel/m68k_ksyms.c | 25 +- arch/m68k/kernel/process.c | 2 +- arch/m68k/kernel/ptrace.c | 9 +- arch/m68k/kernel/setup.c | 25 +- arch/m68k/kernel/signal.c | 8 +- arch/m68k/kernel/time.c | 25 +- arch/m68k/kernel/vmlinux-std.lds | 7 +- arch/m68k/kernel/vmlinux-sun3.lds | 7 +- arch/m68k/kernel/vmlinux.lds.S | 6 +- arch/m68k/mm/memory.c | 2 +- arch/m68k/mm/motorola.c | 2 +- arch/m68k/mm/sun3mmu.c | 1 - arch/m68k/q40/config.c | 1 - arch/m68k/q40/q40ints.c | 3 +- arch/m68k/sun3/Makefile | 3 +- arch/m68k/sun3/mmu_emu.c | 5 +- arch/m68k/sun3/sun3dvma.c | 1 + arch/m68k/sun3/sun3ints.c | 4 + arch/m68k/sun3x/config.c | 3 +- arch/m68knommu/Kconfig | 184 +- arch/m68knommu/Makefile | 17 +- arch/m68knommu/defconfig | 6 +- arch/m68knommu/kernel/Makefile | 2 +- arch/m68knommu/kernel/asm-offsets.c | 2 +- arch/m68knommu/kernel/comempci.c | 2 - arch/m68knommu/kernel/m68k_ksyms.c | 49 +- arch/m68knommu/kernel/module.c | 35 +- arch/m68knommu/kernel/process.c | 2 +- arch/m68knommu/kernel/ptrace.c | 15 +- arch/m68knommu/kernel/setup.c | 9 +- arch/m68knommu/kernel/signal.c | 159 +- arch/m68knommu/kernel/syscalltable.S | 70 +- arch/m68knommu/kernel/time.c | 26 +- arch/m68knommu/kernel/vmlinux.lds.S | 32 +- arch/m68knommu/lib/Makefile | 2 +- arch/m68knommu/mm/init.c | 1 - arch/m68knommu/mm/memory.c | 1 - .../platform/5206e/MOTOROLA/crt0_ram.S | 30 +- arch/m68knommu/platform/5206e/config.c | 1 - arch/m68knommu/platform/5249/config.c | 1 - arch/m68knommu/platform/5272/config.c | 7 +- arch/m68knommu/platform/5307/Makefile | 2 + arch/m68knommu/platform/5307/config.c | 1 - arch/m68knommu/platform/5307/timers.c | 13 +- arch/m68knommu/platform/5307/vectors.c | 2 +- arch/m68knommu/platform/5407/config.c | 1 - arch/mips/Kconfig | 286 +- arch/mips/Makefile | 298 +- arch/mips/arc/identify.c | 2 +- arch/mips/arc/misc.c | 2 +- arch/mips/au1000/common/Makefile | 9 +- arch/mips/au1000/common/au1xxx_irqmap.c | 48 +- arch/mips/au1000/common/cputable.c | 1 + arch/mips/au1000/common/dbdma.c | 145 +- arch/mips/au1000/common/dma.c | 6 + arch/mips/au1000/common/irq.c | 18 +- arch/mips/au1000/common/pci.c | 8 +- arch/mips/au1000/common/puts.c | 2 +- arch/mips/au1000/common/reset.c | 15 +- arch/mips/au1000/common/setup.c | 83 +- arch/mips/au1000/common/time.c | 18 +- arch/mips/au1000/common/usbdev.c | 7 +- arch/mips/au1000/csb250/irqmap.c | 2 +- arch/mips/au1000/db1x00/board_setup.c | 6 + arch/mips/au1000/db1x00/irqmap.c | 2 +- arch/mips/au1000/db1x00/mirage_ts.c | 2 +- arch/mips/au1000/hydrogen3/board_setup.c | 4 + arch/mips/au1000/hydrogen3/irqmap.c | 2 +- arch/mips/au1000/mtx-1/irqmap.c | 2 +- arch/mips/au1000/pb1000/board_setup.c | 4 + arch/mips/au1000/pb1000/irqmap.c | 2 +- arch/mips/au1000/pb1100/board_setup.c | 10 +- arch/mips/au1000/pb1100/irqmap.c | 4 +- arch/mips/au1000/pb1500/board_setup.c | 6 + arch/mips/au1000/pb1500/irqmap.c | 2 +- arch/mips/au1000/pb1550/board_setup.c | 6 + arch/mips/au1000/pb1550/irqmap.c | 2 +- arch/mips/au1000/xxs1500/board_setup.c | 6 + arch/mips/au1000/xxs1500/irqmap.c | 2 +- arch/mips/boot/Makefile | 18 +- arch/mips/boot/addinitrd.c | 9 +- arch/mips/cobalt/irq.c | 2 +- arch/mips/cobalt/setup.c | 3 +- arch/mips/configs/atlas_defconfig | 68 +- arch/mips/configs/capcella_defconfig | 64 +- arch/mips/configs/cobalt_defconfig | 63 +- arch/mips/configs/db1000_defconfig | 101 +- arch/mips/configs/db1100_defconfig | 101 +- arch/mips/configs/db1500_defconfig | 290 +- arch/mips/configs/ddb5476_defconfig | 65 +- arch/mips/configs/ddb5477_defconfig | 64 +- arch/mips/configs/decstation_defconfig | 67 +- arch/mips/configs/e55_defconfig | 65 +- arch/mips/configs/ev64120_defconfig | 64 +- arch/mips/configs/ev96100_defconfig | 66 +- arch/mips/configs/ip22_defconfig | 148 +- arch/mips/configs/ip27_defconfig | 149 +- arch/mips/configs/ip32_defconfig | 68 +- arch/mips/configs/it8172_defconfig | 83 +- arch/mips/configs/ivr_defconfig | 64 +- arch/mips/configs/jaguar-atx_defconfig | 68 +- arch/mips/configs/jmr3927_defconfig | 66 +- arch/mips/configs/lasat200_defconfig | 79 +- arch/mips/configs/malta_defconfig | 65 +- arch/mips/configs/mpc30x_defconfig | 69 +- arch/mips/configs/ocelot_c_defconfig | 63 +- arch/mips/configs/ocelot_defconfig | 65 +- arch/mips/configs/ocelot_g_defconfig | 61 +- arch/mips/configs/osprey_defconfig | 65 +- arch/mips/configs/pb1100_defconfig | 196 +- arch/mips/configs/pb1500_defconfig | 105 +- arch/mips/configs/pb1550_defconfig | 102 +- arch/mips/configs/rm200_defconfig | 158 +- arch/mips/configs/sb1250-swarm_defconfig | 77 +- arch/mips/configs/sead_defconfig | 62 +- arch/mips/configs/tb0226_defconfig | 71 +- arch/mips/configs/tb0229_defconfig | 63 +- arch/mips/configs/workpad_defconfig | 65 +- arch/mips/configs/yosemite_defconfig | 79 +- arch/mips/ddb5xxx/common/Makefile | 2 +- arch/mips/ddb5xxx/ddb5074/irq.c | 10 +- arch/mips/ddb5xxx/ddb5074/nile4_pic.c | 2 - arch/mips/ddb5xxx/ddb5074/setup.c | 7 - arch/mips/ddb5xxx/ddb5476/irq.c | 2 +- arch/mips/ddb5xxx/ddb5476/setup.c | 8 - arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c | 5 +- arch/mips/ddb5xxx/ddb5477/irq.c | 5 +- arch/mips/ddb5xxx/ddb5477/irq_5477.c | 4 +- arch/mips/ddb5xxx/ddb5477/setup.c | 6 +- arch/mips/dec/boot/decstation.c | 7 - arch/mips/dec/setup.c | 12 +- arch/mips/defconfig | 148 +- arch/mips/galileo-boards/ev96100/irq.c | 3 +- arch/mips/galileo-boards/ev96100/time.c | 3 + arch/mips/gt64120/common/time.c | 4 +- arch/mips/gt64120/ev64120/irq.c | 4 +- arch/mips/gt64120/momenco_ocelot/dbg_io.c | 2 +- arch/mips/gt64120/momenco_ocelot/irq.c | 11 +- arch/mips/ite-boards/generic/irq.c | 17 +- arch/mips/jazz/irq.c | 9 +- arch/mips/jazz/jazzdma.c | 12 + arch/mips/jazz/reset.c | 2 - arch/mips/jmr3927/rbhma3100/irq.c | 24 +- arch/mips/jmr3927/rbhma3100/setup.c | 6 - arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/cpu-bugs64.c | 5 +- arch/mips/kernel/cpu-probe.c | 1 + arch/mips/kernel/entry.S | 5 + arch/mips/kernel/gdb-stub.c | 2 + arch/mips/kernel/genex.S | 20 +- arch/mips/kernel/head.S | 54 +- arch/mips/kernel/i8259.c | 4 +- arch/mips/kernel/ioctl32.c | 6 + arch/mips/kernel/irixelf.c | 47 +- arch/mips/kernel/irixsig.c | 31 +- arch/mips/kernel/irq-mv6434x.c | 2 +- arch/mips/kernel/irq.c | 884 +- arch/mips/kernel/mips_ksyms.c | 44 +- arch/mips/kernel/process.c | 57 +- arch/mips/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace32.c | 2 +- arch/mips/kernel/r4k_switch.S | 37 +- arch/mips/kernel/scall32-o32.S | 19 +- arch/mips/kernel/scall64-64.S | 43 +- arch/mips/kernel/scall64-n32.S | 29 +- arch/mips/kernel/scall64-o32.S | 680 +- arch/mips/kernel/semaphore.c | 72 +- arch/mips/kernel/setup.c | 142 +- arch/mips/kernel/signal.c | 65 +- arch/mips/kernel/signal32.c | 101 +- arch/mips/kernel/signal_n32.c | 6 +- arch/mips/kernel/smp.c | 25 +- arch/mips/kernel/syscall.c | 11 +- arch/mips/kernel/sysirix.c | 45 +- arch/mips/kernel/time.c | 56 +- arch/mips/kernel/traps.c | 37 +- arch/mips/kernel/vmlinux.lds.S | 16 +- arch/mips/lasat/interrupt.c | 6 +- arch/mips/lasat/setup.c | 2 +- arch/mips/lib-64/dump_tlb.c | 2 +- arch/mips/lib/csum_partial_copy.c | 4 +- arch/mips/lib/dec_and_lock.c | 4 +- arch/mips/lib/strlen_user.S | 3 +- arch/mips/lib/strnlen_user.S | 3 +- arch/mips/math-emu/cp1emu.c | 6 +- arch/mips/mips-boards/atlas/atlas_int.c | 14 +- arch/mips/mips-boards/atlas/atlas_setup.c | 2 +- arch/mips/mips-boards/generic/init.c | 4 +- arch/mips/mips-boards/generic/memory.c | 2 +- arch/mips/mips-boards/generic/pci.c | 3 +- arch/mips/mips-boards/generic/time.c | 1 - arch/mips/mips-boards/malta/malta_int.c | 18 +- arch/mips/mips-boards/malta/malta_setup.c | 44 +- arch/mips/mips-boards/sead/sead_int.c | 3 +- arch/mips/mips-boards/sead/sead_setup.c | 2 +- arch/mips/mm/Makefile | 25 +- arch/mips/mm/c-r3k.c | 4 +- arch/mips/mm/c-r4k.c | 151 +- arch/mips/mm/c-sb1.c | 40 +- arch/mips/mm/c-tx39.c | 4 +- arch/mips/mm/fault.c | 1 - arch/mips/mm/ioremap.c | 18 +- arch/mips/mm/pg-r4k.c | 4 +- arch/mips/mm/pgtable-64.c | 21 - arch/mips/mm/tlb-andes.c | 24 +- arch/mips/mm/tlb-r3k.c | 6 +- arch/mips/mm/tlb-r4k.c | 33 +- arch/mips/mm/tlb-r8k.c | 7 +- arch/mips/mm/tlb-sb1.c | 29 +- arch/mips/mm/tlbex32-r3k.S | 30 - arch/mips/mm/tlbex32-r4k.S | 268 +- arch/mips/momentum/jaguar_atx/irq.c | 3 +- arch/mips/momentum/jaguar_atx/prom.c | 4 +- arch/mips/momentum/jaguar_atx/setup.c | 3 +- arch/mips/momentum/ocelot_c/dbg_io.c | 2 +- arch/mips/momentum/ocelot_c/irq.c | 11 +- arch/mips/momentum/ocelot_c/prom.c | 6 +- arch/mips/momentum/ocelot_g/dbg_io.c | 2 +- arch/mips/momentum/ocelot_g/gt-irq.c | 4 +- arch/mips/momentum/ocelot_g/irq.c | 11 +- arch/mips/pci/Makefile | 4 +- arch/mips/pci/fixup-atlas.c | 16 +- arch/mips/pci/fixup-au1000.c | 10 +- arch/mips/pci/fixup-capcella.c | 8 +- arch/mips/pci/fixup-cobalt.c | 18 +- arch/mips/pci/fixup-ddb5074.c | 7 +- arch/mips/pci/fixup-ddb5477.c | 16 +- arch/mips/pci/fixup-ev96100.c | 6 + arch/mips/pci/fixup-ip32.c | 9 +- arch/mips/pci/fixup-ite8172g.c | 6 + arch/mips/pci/fixup-ivr.c | 6 + arch/mips/pci/fixup-jaguar.c | 11 +- arch/mips/pci/fixup-jmr3927.c | 6 + arch/mips/pci/fixup-malta.c | 16 +- arch/mips/pci/fixup-mpc30x.c | 8 +- arch/mips/pci/fixup-ocelot-c.c | 8 +- arch/mips/pci/fixup-ocelot-g.c | 8 +- arch/mips/pci/fixup-rbtx4927.c | 113 +- arch/mips/pci/fixup-sni.c | 11 +- arch/mips/pci/fixup-tb0219.c | 8 +- arch/mips/pci/fixup-tb0226.c | 8 +- arch/mips/pci/fixup-yosemite.c | 8 +- arch/mips/pci/ops-au1000.c | 16 +- arch/mips/pci/ops-it8172.c | 3 +- arch/mips/pci/ops-titan.c | 23 +- arch/mips/pci/ops-tx3927.c | 2 +- arch/mips/pci/ops-tx4927.c | 265 +- arch/mips/pci/pci-ddb5074.c | 7 +- arch/mips/pci/pci-ddb5476.c | 7 +- arch/mips/pci/pci-ddb5477.c | 9 +- arch/mips/pci/pci-ev96100.c | 4 +- arch/mips/pci/pci-ip27.c | 325 +- arch/mips/pci/pci-ip32.c | 2 +- arch/mips/pci/pci-jmr3927.c | 2 +- arch/mips/pci/pci-lasat.c | 10 +- arch/mips/pci/pci-ocelot-c.c | 3 +- arch/mips/pci/pci-ocelot-g.c | 3 +- arch/mips/pci/pci-sb1250.c | 29 +- arch/mips/pci/pci-vr41xx.c | 2 +- arch/mips/pci/pci-yosemite.c | 31 +- arch/mips/pci/pci.c | 6 +- arch/mips/pmc-sierra/yosemite/Makefile | 1 + arch/mips/pmc-sierra/yosemite/dbg_io.c | 2 +- arch/mips/pmc-sierra/yosemite/ht.c | 5 - arch/mips/pmc-sierra/yosemite/irq-handler.S | 26 +- arch/mips/pmc-sierra/yosemite/irq.c | 11 +- arch/mips/pmc-sierra/yosemite/prom.c | 18 +- arch/mips/pmc-sierra/yosemite/py-console.c | 7 - arch/mips/pmc-sierra/yosemite/setup.c | 4 +- arch/mips/pmc-sierra/yosemite/smp.c | 288 +- arch/mips/sgi-ip22/ip22-berr.c | 2 +- arch/mips/sgi-ip22/ip22-int.c | 3 +- arch/mips/sgi-ip22/ip22-setup.c | 24 +- arch/mips/sgi-ip27/ip27-hubio.c | 5 +- arch/mips/sgi-ip27/ip27-init.c | 372 +- arch/mips/sgi-ip27/ip27-irq.c | 104 +- arch/mips/sgi-ip27/ip27-klnuma.c | 4 +- arch/mips/sgi-ip27/ip27-memory.c | 349 +- arch/mips/sgi-ip27/ip27-smp.c | 7 - arch/mips/sgi-ip27/ip27-timer.c | 2 - arch/mips/sgi-ip32/crime.c | 34 +- arch/mips/sgi-ip32/ip32-irq.c | 69 +- arch/mips/sgi-ip32/ip32-reset.c | 16 +- arch/mips/sgi-ip32/ip32-setup.c | 8 +- arch/mips/sibyte/cfe/setup.c | 63 +- arch/mips/sibyte/cfe/smp.c | 11 +- arch/mips/sibyte/sb1250/irq.c | 25 +- arch/mips/sibyte/sb1250/irq_handler.S | 4 +- arch/mips/sibyte/sb1250/prom.c | 18 +- arch/mips/sibyte/swarm/setup.c | 4 +- arch/mips/sni/irq.c | 3 +- arch/mips/sni/setup.c | 3 +- arch/mips/tx4927/common/Makefile | 1 + arch/mips/tx4927/common/tx4927_irq.c | 124 +- arch/mips/tx4927/common/tx4927_setup.c | 11 +- .../toshiba_rbtx4927/toshiba_rbtx4927_irq.c | 13 +- .../toshiba_rbtx4927/toshiba_rbtx4927_prom.c | 9 + .../toshiba_rbtx4927/toshiba_rbtx4927_setup.c | 237 +- arch/mips/vr4181/common/irq.c | 12 +- arch/mips/vr41xx/common/giu.c | 7 +- arch/mips/vr41xx/common/icu.c | 227 +- arch/mips/vr41xx/common/serial.c | 4 +- arch/mips/vr41xx/common/vrc4173.c | 93 + arch/parisc/Kconfig | 70 +- arch/parisc/Makefile | 17 +- arch/parisc/configs/a500_defconfig | 38 +- arch/parisc/hpux/fs.c | 5 +- arch/parisc/kernel/Makefile | 7 +- arch/parisc/kernel/asm-offsets.c | 8 +- arch/parisc/kernel/cache.c | 26 +- arch/parisc/kernel/entry.S | 122 +- arch/parisc/kernel/firmware.c | 2 +- arch/parisc/kernel/hardware.c | 2 +- arch/parisc/kernel/head.S | 220 +- arch/parisc/kernel/pacache.S | 6 +- arch/parisc/kernel/parisc_ksyms.c | 14 +- arch/parisc/kernel/pci-dma.c | 4 + arch/parisc/kernel/pci.c | 9 - arch/parisc/kernel/pdc_cons.c | 13 + arch/parisc/kernel/perf_asm.S | 854 +- arch/parisc/kernel/perf_images.h | 1 + arch/parisc/kernel/process.c | 7 +- arch/parisc/kernel/ptrace.c | 13 +- arch/parisc/kernel/real2.S | 4 +- arch/parisc/kernel/signal.c | 31 +- arch/parisc/kernel/smp.c | 37 +- arch/parisc/kernel/sys_parisc.c | 8 + arch/parisc/kernel/sys_parisc32.c | 5 +- arch/parisc/kernel/syscall.S | 373 +- arch/parisc/kernel/syscall_table.S | 63 +- arch/parisc/kernel/time.c | 42 +- arch/parisc/kernel/traps.c | 123 +- arch/parisc/kernel/unaligned.c | 185 +- arch/parisc/kernel/unwind.c | 118 +- arch/parisc/kernel/vmlinux.lds.S | 4 +- arch/parisc/lib/Makefile | 2 +- arch/parisc/lib/bitops.c | 24 +- arch/parisc/lib/checksum.c | 40 +- arch/parisc/lib/debuglocks.c | 73 +- arch/parisc/lib/lusercopy.S | 161 +- arch/parisc/mm/fault.c | 15 +- arch/parisc/mm/init.c | 21 +- arch/ppc/4xx_io/serial_sicc.c | 71 +- arch/ppc/8260_io/enet.c | 2 +- arch/ppc/8260_io/fcc_enet.c | 6 +- arch/ppc/8xx_io/Kconfig | 66 +- arch/ppc/8xx_io/Makefile | 2 +- arch/ppc/8xx_io/commproc.c | 267 +- arch/ppc/8xx_io/enet.c | 12 +- arch/ppc/8xx_io/fec.c | 6 +- arch/ppc/8xx_io/micropatch.c | 145 +- arch/ppc/Kconfig | 172 +- arch/ppc/Kconfig.debug | 14 +- arch/ppc/Makefile | 34 +- arch/ppc/amiga/config.c | 3 - arch/ppc/boot/Makefile | 4 +- arch/ppc/boot/common/misc-common.c | 30 +- arch/ppc/boot/common/ns16550.c | 6 +- arch/ppc/boot/common/serial_stub.c | 5 - arch/ppc/boot/common/util.S | 18 +- arch/ppc/boot/include/nonstdio.h | 2 + arch/ppc/boot/lib/Makefile | 19 +- arch/ppc/boot/openfirmware/coffmain.c | 1 - arch/ppc/boot/openfirmware/common.c | 106 +- arch/ppc/boot/openfirmware/misc.S | 2 +- arch/ppc/boot/simple/Makefile | 9 +- arch/ppc/boot/simple/embed_config.c | 33 +- arch/ppc/boot/simple/misc-embedded.c | 11 +- arch/ppc/boot/simple/misc-prep.c | 1 + arch/ppc/boot/simple/misc-spruce.c | 3 - arch/ppc/boot/simple/misc.c | 16 +- arch/ppc/boot/simple/mpc52xx_tty.c | 1 + arch/ppc/boot/simple/relocate.S | 6 +- arch/ppc/boot/utils/mkbugboot.c | 14 +- arch/ppc/boot/utils/mktree.c | 4 + arch/ppc/configs/FADS_defconfig | 24 +- arch/ppc/configs/IVMS8_defconfig | 21 +- arch/ppc/configs/SM850_defconfig | 27 +- arch/ppc/configs/SPD823TS_defconfig | 24 +- arch/ppc/configs/TQM823L_defconfig | 24 +- arch/ppc/configs/TQM850L_defconfig | 24 +- arch/ppc/configs/TQM860L_defconfig | 23 +- arch/ppc/configs/bseip_defconfig | 23 +- arch/ppc/configs/mbx_defconfig | 24 +- arch/ppc/configs/mvme5100_defconfig | 448 +- arch/ppc/configs/rpxcllf_defconfig | 295 +- arch/ppc/configs/rpxlite_defconfig | 291 +- arch/ppc/kernel/Makefile | 4 +- arch/ppc/kernel/align.c | 163 +- arch/ppc/kernel/asm-offsets.c | 7 + arch/ppc/kernel/bitops.c | 2 +- arch/ppc/kernel/cpu_setup_6xx.S | 42 +- arch/ppc/kernel/cpu_setup_power4.S | 8 +- arch/ppc/kernel/cputable.c | 1349 +- arch/ppc/kernel/dma-mapping.c | 4 +- arch/ppc/kernel/entry.S | 4 +- arch/ppc/kernel/head.S | 16 +- arch/ppc/kernel/head_44x.S | 295 +- arch/ppc/kernel/head_4xx.S | 46 +- arch/ppc/kernel/head_8xx.S | 546 +- arch/ppc/kernel/head_booke.h | 66 + arch/ppc/kernel/head_e500.S | 294 +- arch/ppc/kernel/idle.c | 34 + arch/ppc/kernel/idle_6xx.S | 6 +- arch/ppc/kernel/idle_power4.S | 2 +- arch/ppc/kernel/irq.c | 563 +- arch/ppc/kernel/misc.S | 36 +- arch/ppc/kernel/pci.c | 93 +- arch/ppc/kernel/ppc-stub.c | 20 +- arch/ppc/kernel/ppc_htab.c | 35 +- arch/ppc/kernel/ppc_ksyms.c | 16 +- arch/ppc/kernel/process.c | 28 +- arch/ppc/kernel/ptrace.c | 11 +- arch/ppc/kernel/setup.c | 12 +- arch/ppc/kernel/signal.c | 47 +- arch/ppc/kernel/smp.c | 10 +- arch/ppc/kernel/softemu8xx.c | 2 +- arch/ppc/kernel/time.c | 46 +- arch/ppc/kernel/traps.c | 75 +- arch/ppc/kernel/vector.S | 4 +- arch/ppc/kernel/vmlinux.lds.S | 4 +- arch/ppc/lib/checksum.S | 12 +- arch/ppc/lib/dec_and_lock.c | 4 +- arch/ppc/lib/rheap.c | 9 +- arch/ppc/math-emu/op-common.h | 1 - arch/ppc/mm/44x_mmu.c | 14 +- arch/ppc/mm/4xx_mmu.c | 5 + arch/ppc/mm/init.c | 5 + arch/ppc/mm/pgtable.c | 25 +- arch/ppc/platforms/4xx/Kconfig | 22 +- arch/ppc/platforms/4xx/Makefile | 2 + arch/ppc/platforms/4xx/ebony.c | 196 +- arch/ppc/platforms/4xx/ebony.h | 18 +- arch/ppc/platforms/4xx/ocotea.c | 328 +- arch/ppc/platforms/4xx/ocotea.h | 15 +- arch/ppc/platforms/85xx/mpc8540_ads.c | 4 - arch/ppc/platforms/85xx/mpc8555.c | 7 + arch/ppc/platforms/85xx/mpc8560_ads.c | 14 +- arch/ppc/platforms/85xx/mpc85xx_ads_common.c | 3 +- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 22 +- arch/ppc/platforms/85xx/sbc8560.c | 3 - arch/ppc/platforms/85xx/sbc85xx.c | 3 +- arch/ppc/platforms/Makefile | 8 +- arch/ppc/platforms/adir_pic.c | 20 +- arch/ppc/platforms/chrp_pci.c | 2 +- arch/ppc/platforms/chrp_setup.c | 19 +- arch/ppc/platforms/chrp_smp.c | 1 - arch/ppc/platforms/est8260.h | 3 + arch/ppc/platforms/gemini_pci.c | 2 +- arch/ppc/platforms/k2.c | 7 +- arch/ppc/platforms/lite5200.c | 55 +- arch/ppc/platforms/lopec.c | 3 +- arch/ppc/platforms/mcpn765.c | 13 +- arch/ppc/platforms/mcpn765.h | 50 +- arch/ppc/platforms/mpc5200.c | 24 + arch/ppc/platforms/mvme5100.c | 2 +- arch/ppc/platforms/mvme5100.h | 25 +- arch/ppc/platforms/pcore.c | 7 +- arch/ppc/platforms/pmac_cpufreq.c | 41 +- arch/ppc/platforms/pmac_feature.c | 18 +- arch/ppc/platforms/pmac_pci.c | 27 +- arch/ppc/platforms/pmac_pic.c | 40 +- arch/ppc/platforms/pmac_setup.c | 5 +- arch/ppc/platforms/pmac_smp.c | 11 +- arch/ppc/platforms/pmac_time.c | 2 +- arch/ppc/platforms/powerpmc250.h | 18 +- arch/ppc/platforms/pplus.c | 11 +- arch/ppc/platforms/pq2ads.h | 4 + arch/ppc/platforms/prep_pci.c | 195 +- arch/ppc/platforms/prep_setup.c | 218 +- arch/ppc/platforms/prpmc750.c | 7 +- arch/ppc/platforms/prpmc750.h | 26 +- arch/ppc/platforms/prpmc800.c | 4 - arch/ppc/platforms/prpmc800.h | 28 +- arch/ppc/platforms/residual.c | 133 +- arch/ppc/platforms/rpx8260.h | 7 + arch/ppc/platforms/rpxclassic.h | 1 - arch/ppc/platforms/rpxlite.h | 1 - arch/ppc/platforms/sandpoint.c | 139 +- arch/ppc/platforms/sbc82xx.c | 70 +- arch/ppc/platforms/sbc82xx.h | 4 + arch/ppc/platforms/spruce.c | 5 - arch/ppc/platforms/tqm8260.h | 4 + arch/ppc/platforms/tqm8260_setup.c | 41 +- arch/ppc/platforms/tqm8xx.h | 2 - arch/ppc/syslib/Makefile | 15 +- arch/ppc/syslib/cpm2_pic.c | 25 +- arch/ppc/syslib/cpm2_pic.h | 8 +- arch/ppc/syslib/gen550_dbg.c | 4 +- arch/ppc/syslib/gen550_kgdb.c | 6 +- arch/ppc/syslib/hawk_common.c | 32 + arch/ppc/syslib/i8259.c | 10 +- arch/ppc/syslib/ibm440gx_common.c | 72 +- arch/ppc/syslib/ibm440gx_common.h | 5 +- arch/ppc/syslib/ibm44x_common.c | 149 +- arch/ppc/syslib/ibm44x_common.h | 8 +- arch/ppc/syslib/indirect_pci.c | 15 +- arch/ppc/syslib/m8260_pci.h | 1 + arch/ppc/syslib/m8260_setup.c | 85 +- arch/ppc/syslib/m8xx_setup.c | 71 +- arch/ppc/syslib/mpc10x_common.c | 13 +- arch/ppc/syslib/mpc52xx_pic.c | 22 +- arch/ppc/syslib/mpc52xx_setup.c | 42 +- arch/ppc/syslib/open_pic.c | 36 +- arch/ppc/syslib/open_pic2.c | 2 +- arch/ppc/syslib/ppc405_pci.c | 4 +- arch/ppc/syslib/ppc4xx_dma.c | 2 +- arch/ppc/syslib/ppc4xx_pic.c | 2 +- arch/ppc/syslib/ppc4xx_setup.c | 50 +- arch/ppc/syslib/ppc85xx_setup.c | 4 +- arch/ppc/syslib/ppc8xx_pic.c | 121 +- arch/ppc/syslib/prom.c | 2 +- arch/ppc/syslib/prom_init.c | 26 +- arch/ppc/syslib/todc_time.c | 15 +- arch/ppc/xmon/start.c | 6 +- arch/ppc/xmon/xmon.c | 2 +- arch/ppc64/Kconfig | 178 +- arch/ppc64/Kconfig.debug | 12 - arch/ppc64/Makefile | 22 +- arch/ppc64/boot/Makefile | 39 +- arch/ppc64/boot/main.c | 170 +- arch/ppc64/boot/zImage.lds | 12 +- arch/ppc64/configs/g5_defconfig | 197 +- arch/ppc64/configs/iSeries_defconfig | 109 +- arch/ppc64/configs/pSeries_defconfig | 263 +- arch/ppc64/kernel/ItLpQueue.c | 2 +- arch/ppc64/kernel/LparData.c | 7 +- arch/ppc64/kernel/Makefile | 34 +- arch/ppc64/kernel/asm-offsets.c | 20 +- arch/ppc64/kernel/bitops.c | 2 +- arch/ppc64/kernel/btext.c | 231 +- arch/ppc64/kernel/cpu_setup_power4.S | 9 + arch/ppc64/kernel/dma.c | 20 + arch/ppc64/kernel/eeh.c | 577 +- arch/ppc64/kernel/entry.S | 49 +- arch/ppc64/kernel/head.S | 340 +- arch/ppc64/kernel/hvconsole.c | 66 +- arch/ppc64/kernel/hvcserver.c | 86 +- arch/ppc64/kernel/i8259.c | 20 +- arch/ppc64/kernel/i8259.h | 4 +- arch/ppc64/kernel/iSeries_htab.c | 2 + arch/ppc64/kernel/iSeries_iommu.c | 89 +- arch/ppc64/kernel/iSeries_irq.c | 1 + arch/ppc64/kernel/iSeries_pci.c | 245 +- arch/ppc64/kernel/iSeries_pci_reset.c | 3 +- arch/ppc64/kernel/iSeries_proc.c | 1 + arch/ppc64/kernel/iSeries_setup.c | 187 +- arch/ppc64/kernel/iSeries_setup.h | 4 - arch/ppc64/kernel/idle.c | 228 +- arch/ppc64/kernel/idle_power4.S | 2 +- arch/ppc64/kernel/ioctl32.c | 2 - arch/ppc64/kernel/iomap.c | 7 + arch/ppc64/kernel/iommu.c | 61 +- arch/ppc64/kernel/irq.c | 560 +- arch/ppc64/kernel/lmb.c | 65 +- arch/ppc64/kernel/lparcfg.c | 252 +- arch/ppc64/kernel/mf.c | 1120 +- arch/ppc64/kernel/misc.S | 163 +- arch/ppc64/kernel/nvram.c | 18 +- arch/ppc64/kernel/pSeries_iommu.c | 216 +- arch/ppc64/kernel/pSeries_lpar.c | 320 +- arch/ppc64/kernel/pSeries_pci.c | 723 +- arch/ppc64/kernel/pSeries_setup.c | 220 +- arch/ppc64/kernel/pacaData.c | 37 +- arch/ppc64/kernel/pci.c | 614 +- arch/ppc64/kernel/pci.h | 19 +- arch/ppc64/kernel/pci_dn.c | 91 +- arch/ppc64/kernel/pci_iommu.c | 11 +- arch/ppc64/kernel/pmac.h | 1 - arch/ppc64/kernel/pmac_feature.c | 11 +- arch/ppc64/kernel/pmac_low_i2c.c | 46 +- arch/ppc64/kernel/pmac_pci.c | 143 +- arch/ppc64/kernel/pmac_setup.c | 345 +- arch/ppc64/kernel/pmac_smp.c | 201 +- arch/ppc64/kernel/pmac_time.c | 2 +- arch/ppc64/kernel/ppc_ksyms.c | 17 +- arch/ppc64/kernel/proc_ppc64.c | 36 +- arch/ppc64/kernel/process.c | 36 +- arch/ppc64/kernel/prom.c | 2474 +-- arch/ppc64/kernel/prom_init.c | 118 +- arch/ppc64/kernel/ptrace.c | 5 +- arch/ppc64/kernel/ptrace32.c | 2 +- arch/ppc64/kernel/ras.c | 10 +- arch/ppc64/kernel/rtas-proc.c | 4 +- arch/ppc64/kernel/rtas.c | 128 +- arch/ppc64/kernel/rtas_flash.c | 4 +- arch/ppc64/kernel/rtasd.c | 165 +- arch/ppc64/kernel/rtc.c | 27 +- arch/ppc64/kernel/setup.c | 1143 +- arch/ppc64/kernel/signal.c | 70 +- arch/ppc64/kernel/signal32.c | 97 +- arch/ppc64/kernel/smp.c | 777 +- arch/ppc64/kernel/sys_ppc32.c | 59 +- arch/ppc64/kernel/sysfs.c | 95 +- arch/ppc64/kernel/time.c | 123 +- arch/ppc64/kernel/traps.c | 241 +- arch/ppc64/kernel/u3_iommu.c | 8 +- arch/ppc64/kernel/udbg.c | 166 +- arch/ppc64/kernel/vecemu.c | 2 +- arch/ppc64/kernel/vector.S | 4 +- arch/ppc64/kernel/vio.c | 23 +- arch/ppc64/kernel/viopath.c | 6 +- arch/ppc64/kernel/vmlinux.lds.S | 12 +- arch/ppc64/kernel/xics.c | 56 +- arch/ppc64/lib/Makefile | 1 + arch/ppc64/lib/checksum.S | 14 +- arch/ppc64/lib/dec_and_lock.c | 4 +- arch/ppc64/lib/locks.c | 226 +- arch/ppc64/mm/Makefile | 4 +- arch/ppc64/mm/hash_low.S | 16 +- arch/ppc64/mm/hash_native.c | 46 +- arch/ppc64/mm/hash_utils.c | 105 +- arch/ppc64/mm/hugetlbpage.c | 524 +- arch/ppc64/mm/imalloc.c | 77 +- arch/ppc64/mm/init.c | 253 +- arch/ppc64/mm/mmap.c | 13 +- arch/ppc64/mm/numa.c | 378 +- arch/ppc64/mm/slb.c | 85 +- arch/ppc64/mm/slb_low.S | 99 +- arch/ppc64/mm/tlb.c | 2 +- arch/ppc64/oprofile/common.c | 26 +- arch/ppc64/oprofile/op_impl.h | 16 +- arch/ppc64/oprofile/op_model_power4.c | 77 +- arch/ppc64/oprofile/op_model_rs64.c | 6 +- arch/ppc64/xmon/start.c | 4 +- arch/ppc64/xmon/xmon.c | 192 +- arch/s390/Kconfig | 187 +- arch/s390/Makefile | 46 +- arch/s390/appldata/appldata_mem.c | 8 +- arch/s390/boot/Makefile | 2 +- arch/s390/defconfig | 73 +- arch/s390/kernel/Makefile | 4 +- arch/s390/kernel/asm-offsets.c | 6 + arch/s390/kernel/binfmt_elf32.c | 29 +- arch/s390/kernel/compat_exec.c | 10 +- arch/s390/kernel/compat_linux.c | 7 +- arch/s390/kernel/compat_signal.c | 45 +- arch/s390/kernel/compat_wrapper.S | 16 +- arch/s390/kernel/cpcmd.c | 23 +- arch/s390/kernel/debug.c | 90 +- arch/s390/kernel/ebcdic.c | 12 +- arch/s390/kernel/entry.S | 106 +- arch/s390/kernel/entry64.S | 110 +- arch/s390/kernel/head.S | 6 +- arch/s390/kernel/head64.S | 6 +- arch/s390/kernel/irq.c | 2 +- arch/s390/kernel/process.c | 100 +- arch/s390/kernel/profile.c | 41 +- arch/s390/kernel/ptrace.c | 7 +- arch/s390/kernel/s390_ext.c | 1 + arch/s390/kernel/s390_ksyms.c | 21 +- arch/s390/kernel/setup.c | 51 +- arch/s390/kernel/signal.c | 25 +- arch/s390/kernel/smp.c | 30 +- arch/s390/kernel/syscalls.S | 3 +- arch/s390/kernel/time.c | 53 +- arch/s390/kernel/traps.c | 188 +- arch/s390/kernel/vmlinux.lds.S | 4 +- arch/s390/kernel/vtime.c | 2 +- arch/s390/lib/string.c | 34 +- arch/s390/mm/Makefile | 2 +- arch/s390/mm/extmem.c | 904 +- arch/s390/mm/fault.c | 8 +- arch/s390/mm/mmap.c | 4 +- arch/sh/Kconfig | 255 +- arch/sh/Makefile | 67 +- arch/sh/boards/bigsur/irq.c | 2 +- arch/sh/boards/bigsur/setup.c | 2 +- arch/sh/boards/dreamcast/setup.c | 16 +- arch/sh/boards/harp/setup.c | 35 + arch/sh/boards/mpc1211/pci.c | 9 +- arch/sh/boards/overdrive/galileo.c | 8 +- arch/sh/boards/overdrive/pcidma.c | 2 +- arch/sh/boards/renesas/rts7751r2d/mach.c | 4 +- arch/sh/boards/se/770x/irq.c | 31 +- arch/sh/boards/se/770x/mach.c | 2 + arch/sh/boards/se/7751/io.c | 2 +- arch/sh/boards/se/7751/pci.c | 2 +- arch/sh/boot/compressed/Makefile | 2 +- arch/sh/cchips/voyagergx/consistent.c | 18 +- arch/sh/configs/rts7751r2d_defconfig | 445 +- arch/sh/configs/se7751_defconfig | 1 + arch/sh/drivers/dma/dma-api.c | 6 +- arch/sh/drivers/dma/dma-g2.c | 88 +- arch/sh/drivers/dma/dma-pvr2.c | 34 +- arch/sh/drivers/pci/Makefile | 2 +- arch/sh/drivers/pci/dma-dreamcast.c | 22 +- arch/sh/drivers/pci/fixups-dreamcast.c | 8 +- arch/sh/drivers/pci/fixups-rts7751r2d.c | 21 +- arch/sh/drivers/pci/ops-rts7751r2d.c | 7 +- arch/sh/drivers/pci/pci-auto.c | 2 + arch/sh/drivers/pci/pci-sh7751.c | 16 +- arch/sh/drivers/pci/pci-st40.c | 284 +- arch/sh/drivers/pci/pci-st40.h | 70 + arch/sh/drivers/pci/pci.c | 2 + arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/cpu/init.c | 10 +- arch/sh/kernel/cpu/irq_imask.c | 2 +- arch/sh/kernel/cpu/irq_ipr.c | 10 +- arch/sh/kernel/cpu/sh2/Makefile | 2 + arch/sh/kernel/cpu/sh3/Makefile | 2 +- arch/sh/kernel/cpu/sh4/Makefile | 3 +- arch/sh/kernel/cpu/sh4/ex.S | 70 +- arch/sh/kernel/cpu/sh4/irq_intc2.c | 153 +- arch/sh/kernel/cpu/sh4/sq.c | 31 +- arch/sh/kernel/early_printk.c | 4 +- arch/sh/kernel/entry.S | 6 + arch/sh/kernel/irq.c | 10 +- arch/sh/kernel/process.c | 18 +- arch/sh/kernel/ptrace.c | 2 +- arch/sh/kernel/setup.c | 3 +- arch/sh/kernel/sh_bios.c | 3 +- arch/sh/kernel/sh_ksyms.c | 17 +- arch/sh/kernel/signal.c | 31 +- arch/sh/kernel/smp.c | 10 +- arch/sh/kernel/time.c | 288 +- arch/sh/kernel/traps.c | 4 +- arch/sh/kernel/vmlinux.lds.S | 4 +- arch/sh/lib/Makefile | 8 +- arch/sh/mm/Makefile | 2 + arch/sh/mm/cache-sh2.c | 24 +- arch/sh/mm/cache-sh3.c | 75 +- arch/sh/mm/cache-sh4.c | 129 +- arch/sh/mm/consistent.c | 4 + arch/sh/mm/extable.c | 3 +- arch/sh/mm/fault-nommu.c | 1 - arch/sh/mm/fault.c | 1 - arch/sh/mm/init.c | 6 +- arch/sh/mm/ioremap.c | 3 +- arch/sh/mm/tlb-sh3.c | 11 +- arch/sh/mm/tlb-sh4.c | 1 - arch/sh/oprofile/Makefile | 2 +- arch/sh/ramdisk/Makefile | 5 +- arch/sh/tools/Makefile | 5 +- arch/sh/tools/mach-types | 4 + arch/sh64/Kconfig | 50 +- arch/sh64/boot/compressed/Makefile | 6 +- arch/sh64/kernel/irq.c | 8 +- arch/sh64/kernel/irq_intc.c | 6 +- arch/sh64/kernel/pci_sh5.c | 9 +- arch/sh64/kernel/process.c | 12 +- arch/sh64/kernel/ptrace.c | 9 +- arch/sh64/kernel/sh_ksyms.c | 29 +- arch/sh64/kernel/signal.c | 8 +- arch/sh64/kernel/time.c | 37 +- arch/sh64/kernel/vmlinux.lds.S | 4 +- arch/sh64/mm/fault.c | 1 - arch/sh64/mm/init.c | 4 +- arch/sh64/mm/tlbmiss.c | 1 - arch/sparc/Kconfig | 109 +- arch/sparc/Makefile | 2 +- arch/sparc/boot/Makefile | 42 +- arch/sparc/kernel/Makefile | 2 +- arch/sparc/kernel/apc.c | 8 +- arch/sparc/kernel/auxio.c | 4 +- arch/sparc/kernel/ebus.c | 6 +- arch/sparc/kernel/entry.S | 10 +- arch/sparc/kernel/init_task.c | 2 +- arch/sparc/kernel/ioport.c | 24 +- arch/sparc/kernel/irq.c | 1 - arch/sparc/kernel/pcic.c | 13 +- arch/sparc/kernel/pmc.c | 8 +- arch/sparc/kernel/process.c | 13 +- arch/sparc/kernel/ptrace.c | 9 +- arch/sparc/kernel/setup.c | 1 - arch/sparc/kernel/signal.c | 39 +- arch/sparc/kernel/smp.c | 1 - arch/sparc/kernel/sparc_ksyms.c | 8 +- arch/sparc/kernel/sun4d_smp.c | 18 +- arch/sparc/kernel/sun4m_smp.c | 18 +- arch/sparc/kernel/sys_sunos.c | 2 +- arch/sparc/kernel/systbls.S | 5 +- arch/sparc/kernel/time.c | 61 +- arch/sparc/kernel/vmlinux.lds.S | 4 +- arch/sparc/lib/bitext.c | 2 +- arch/sparc/mm/generic.c | 2 +- arch/sparc/mm/io-unit.c | 2 +- arch/sparc/mm/iommu.c | 1 + arch/sparc/mm/srmmu.c | 3 +- arch/sparc/mm/sun4c.c | 4 +- arch/sparc64/Kconfig | 126 +- arch/sparc64/Makefile | 8 +- arch/sparc64/boot/Makefile | 2 +- arch/sparc64/defconfig | 227 +- arch/sparc64/kernel/Makefile | 3 +- arch/sparc64/kernel/auxio.c | 11 +- arch/sparc64/kernel/binfmt_aout32.c | 6 +- arch/sparc64/kernel/binfmt_elf32.c | 6 +- arch/sparc64/kernel/chmc.c | 2 +- arch/sparc64/kernel/entry.S | 4 +- arch/sparc64/kernel/etrap.S | 301 +- arch/sparc64/kernel/head.S | 5 +- arch/sparc64/kernel/irq.c | 20 +- arch/sparc64/kernel/isa.c | 2 +- arch/sparc64/kernel/kprobes.c | 29 +- arch/sparc64/kernel/pci.c | 10 +- arch/sparc64/kernel/pci_common.c | 122 +- arch/sparc64/kernel/pci_impl.h | 1 - arch/sparc64/kernel/pci_iommu.c | 63 +- arch/sparc64/kernel/pci_psycho.c | 28 +- arch/sparc64/kernel/pci_sabre.c | 25 +- arch/sparc64/kernel/pci_schizo.c | 24 +- arch/sparc64/kernel/power.c | 11 +- arch/sparc64/kernel/process.c | 6 +- arch/sparc64/kernel/ptrace.c | 9 +- arch/sparc64/kernel/setup.c | 1 - arch/sparc64/kernel/signal.c | 39 +- arch/sparc64/kernel/signal32.c | 137 +- arch/sparc64/kernel/smp.c | 24 +- arch/sparc64/kernel/sparc64_ksyms.c | 42 +- arch/sparc64/kernel/sys32.S | 8 +- arch/sparc64/kernel/sys_sparc32.c | 40 +- arch/sparc64/kernel/sys_sunos32.c | 2 +- arch/sparc64/kernel/systbls.S | 20 +- arch/sparc64/kernel/time.c | 193 +- arch/sparc64/kernel/trampoline.S | 85 +- arch/sparc64/kernel/traps.c | 141 +- arch/sparc64/kernel/ttable.S | 2 +- arch/sparc64/kernel/unaligned.c | 2 +- arch/sparc64/kernel/vmlinux.lds.S | 4 +- arch/sparc64/lib/Makefile | 13 +- arch/sparc64/lib/PeeCeeI.c | 12 +- arch/sparc64/lib/U3copy_from_user.S | 424 +- arch/sparc64/lib/U3copy_to_user.S | 424 +- arch/sparc64/lib/U3memcpy.S | 331 +- arch/sparc64/lib/atomic.S | 9 +- arch/sparc64/lib/bitops.S | 44 +- arch/sparc64/lib/copy_page.S | 3 + arch/sparc64/lib/debuglocks.c | 2 +- arch/sparc64/lib/dec_and_lock.S | 4 +- arch/sparc64/lib/find_bit.c | 2 +- arch/sparc64/lib/ipcsum.S | 6 +- arch/sparc64/lib/strlen.S | 6 +- arch/sparc64/lib/strncmp.S | 7 +- arch/sparc64/lib/strncpy_from_user.S | 4 +- arch/sparc64/lib/xor.S | 28 +- arch/sparc64/mm/fault.c | 33 +- arch/sparc64/mm/generic.c | 17 +- arch/sparc64/mm/init.c | 20 +- arch/sparc64/solaris/entry64.S | 2 +- arch/sparc64/solaris/fs.c | 16 +- arch/sparc64/solaris/misc.c | 69 +- arch/sparc64/solaris/systbl.S | 16 + arch/um/Kconfig | 172 +- arch/um/Kconfig_block | 39 +- arch/um/Kconfig_char | 56 +- arch/um/Kconfig_net | 72 +- arch/um/Makefile | 182 +- arch/um/Makefile-i386 | 43 +- arch/um/Makefile-skas | 9 +- arch/um/Makefile-tt | 3 +- arch/um/config.release | 1 - arch/um/defconfig | 352 +- arch/um/drivers/Makefile | 18 +- arch/um/drivers/chan_kern.c | 67 +- arch/um/drivers/chan_user.c | 122 +- arch/um/drivers/cow.h | 16 +- arch/um/drivers/cow_user.c | 48 +- arch/um/drivers/daemon_user.c | 26 +- arch/um/drivers/fd.c | 20 +- arch/um/drivers/harddog_user.c | 62 +- arch/um/drivers/hostaudio_kern.c | 145 +- arch/um/drivers/line.c | 170 +- arch/um/drivers/mcast_user.c | 16 +- arch/um/drivers/mconsole_kern.c | 220 +- arch/um/drivers/mconsole_user.c | 25 +- arch/um/drivers/mmapper_kern.c | 9 +- arch/um/drivers/net_kern.c | 124 +- arch/um/drivers/net_user.c | 49 +- arch/um/drivers/null.c | 1 - arch/um/drivers/port_kern.c | 18 +- arch/um/drivers/port_user.c | 50 +- arch/um/drivers/pty.c | 45 +- arch/um/drivers/slip_user.c | 75 +- arch/um/drivers/slirp_user.c | 23 +- arch/um/drivers/ssl.c | 55 +- arch/um/drivers/stdio_console.c | 66 +- arch/um/drivers/tty.c | 15 +- arch/um/drivers/ubd_kern.c | 658 +- arch/um/drivers/ubd_user.c | 498 +- arch/um/drivers/xterm.c | 37 +- arch/um/drivers/xterm_kern.c | 13 +- arch/um/include/2_5compat.h | 14 - arch/um/include/frame_kern.h | 6 +- arch/um/include/irq_kern.h | 4 +- arch/um/include/irq_user.h | 3 +- arch/um/include/kern_util.h | 14 +- arch/um/include/line.h | 7 +- arch/um/include/mconsole.h | 6 +- arch/um/include/mem.h | 15 +- arch/um/include/mem_kern.h | 2 +- arch/um/include/mem_user.h | 32 +- arch/um/include/mode.h | 4 +- arch/um/include/mode_kern.h | 4 +- arch/um/include/os.h | 56 +- arch/um/include/ptrace_user.h | 11 + arch/um/include/signal_user.h | 2 + arch/um/include/skas_ptrace.h | 2 +- arch/um/include/syscall_user.h | 2 +- arch/um/include/sysdep-i386/checksum.h | 4 +- arch/um/include/sysdep-i386/frame_user.h | 28 +- arch/um/include/sysdep-i386/sigcontext.h | 4 +- arch/um/include/sysdep-i386/syscalls.h | 59 +- arch/um/include/time_user.h | 1 + arch/um/include/ubd_user.h | 9 +- arch/um/include/um_mmu.h | 4 +- arch/um/include/um_uaccess.h | 55 +- arch/um/include/user.h | 3 + arch/um/include/user_util.h | 13 +- arch/um/kernel/Makefile | 57 +- arch/um/kernel/config.c.in | 4 +- arch/um/kernel/dyn.lds.S | 2 + arch/um/kernel/exec_kern.c | 21 +- arch/um/kernel/frame.c | 19 +- arch/um/kernel/frame_kern.c | 29 +- arch/um/kernel/helper.c | 62 +- arch/um/kernel/init_task.c | 17 +- arch/um/kernel/initrd_user.c | 13 +- arch/um/kernel/irq.c | 754 +- arch/um/kernel/irq_user.c | 53 +- arch/um/kernel/ksyms.c | 60 +- arch/um/kernel/main.c | 7 +- arch/um/kernel/mem.c | 657 +- arch/um/kernel/mem_user.c | 269 +- arch/um/kernel/physmem.c | 130 +- arch/um/kernel/process.c | 153 +- arch/um/kernel/process_kern.c | 139 +- arch/um/kernel/ptrace.c | 51 +- arch/um/kernel/reboot.c | 2 + arch/um/kernel/sigio_kern.c | 21 +- arch/um/kernel/sigio_user.c | 106 +- arch/um/kernel/signal_kern.c | 215 +- arch/um/kernel/signal_user.c | 16 +- arch/um/kernel/skas/Makefile | 18 +- arch/um/kernel/skas/exec_kern.c | 2 +- arch/um/kernel/skas/include/skas.h | 5 +- arch/um/kernel/skas/mem_user.c | 32 +- arch/um/kernel/skas/mmu.c | 8 +- arch/um/kernel/skas/process.c | 190 +- arch/um/kernel/skas/process_kern.c | 68 +- arch/um/kernel/skas/sys-i386/Makefile | 2 - arch/um/kernel/skas/sys-i386/sigcontext.c | 15 +- arch/um/kernel/skas/syscall_kern.c | 3 +- arch/um/kernel/skas/syscall_user.c | 11 +- arch/um/kernel/skas/tlb.c | 2 +- arch/um/kernel/skas/trap_user.c | 9 +- arch/um/kernel/skas/uaccess.c | 71 +- arch/um/kernel/skas/util/Makefile | 12 +- arch/um/kernel/skas/util/mk_ptregs.c | 1 + arch/um/kernel/smp.c | 112 +- arch/um/kernel/sys_call_table.c | 685 +- arch/um/kernel/syscall_kern.c | 81 +- arch/um/kernel/syscall_user.c | 4 +- arch/um/kernel/sysrq.c | 28 +- arch/um/kernel/tempfile.c | 7 +- arch/um/kernel/time.c | 41 +- arch/um/kernel/time_kern.c | 89 +- arch/um/kernel/trap_kern.c | 51 +- arch/um/kernel/trap_user.c | 20 +- arch/um/kernel/tt/Makefile | 14 +- arch/um/kernel/tt/exec_kern.c | 13 +- arch/um/kernel/tt/exec_user.c | 9 +- arch/um/kernel/tt/include/tt.h | 4 +- arch/um/kernel/tt/mem.c | 2 +- arch/um/kernel/tt/mem_user.c | 7 +- arch/um/kernel/tt/process_kern.c | 157 +- arch/um/kernel/tt/ptproxy/Makefile | 2 - arch/um/kernel/tt/ptproxy/proxy.c | 29 +- arch/um/kernel/tt/ptproxy/sysdep.c | 1 + arch/um/kernel/tt/ptproxy/wait.c | 12 +- arch/um/kernel/tt/sys-i386/Makefile | 2 - arch/um/kernel/tt/syscall_kern.c | 8 +- arch/um/kernel/tt/syscall_user.c | 19 +- arch/um/kernel/tt/tlb.c | 1 + arch/um/kernel/tt/tracer.c | 42 +- arch/um/kernel/tt/trap_user.c | 16 +- arch/um/kernel/tt/uaccess.c | 10 +- arch/um/kernel/tt/uaccess_user.c | 24 +- arch/um/kernel/tt/unmap.c | 3 - arch/um/kernel/tty_log.c | 138 +- arch/um/kernel/uaccess_user.c | 4 +- arch/um/kernel/um_arch.c | 101 +- arch/um/kernel/umid.c | 88 +- arch/um/kernel/uml.lds.S | 2 + arch/um/kernel/user_util.c | 65 +- arch/um/os-Linux/Makefile | 8 +- arch/um/os-Linux/drivers/ethertap_kern.c | 1 - arch/um/os-Linux/drivers/ethertap_user.c | 58 +- arch/um/os-Linux/drivers/tuntap_user.c | 60 +- arch/um/os-Linux/file.c | 464 +- arch/um/os-Linux/process.c | 84 +- arch/um/os-Linux/tty.c | 10 +- arch/um/os-Linux/user_syms.c | 4 +- arch/um/sys-i386/Makefile | 30 +- arch/um/sys-i386/bugs.c | 147 +- arch/um/sys-i386/fault.c | 16 +- arch/um/sys-i386/ldt.c | 2 + arch/um/sys-i386/ptrace.c | 6 +- arch/um/sys-i386/ptrace_user.c | 9 +- arch/um/sys-i386/syscalls.c | 22 + arch/um/sys-i386/sysrq.c | 5 + arch/um/sys-i386/util/Makefile | 19 +- arch/um/sys-i386/util/mk_sc.c | 1 + arch/um/sys-ia64/Makefile | 15 +- arch/um/sys-ppc/Makefile | 11 +- arch/um/util/Makefile | 27 +- arch/um/util/mk_constants_kern.c | 4 + arch/v850/Kconfig | 32 +- arch/v850/kernel/Makefile | 2 +- arch/v850/kernel/asm-consts.c | 2 +- arch/v850/kernel/fpga85e2c.c | 2 +- arch/v850/kernel/irq.c | 6 +- arch/v850/kernel/memcons.c | 3 +- arch/v850/kernel/ptrace.c | 23 +- arch/v850/kernel/rte_mb_a_pci.c | 4 +- arch/v850/kernel/setup.c | 4 +- arch/v850/kernel/signal.c | 22 +- arch/v850/kernel/simcons.c | 2 +- arch/v850/kernel/time.c | 26 +- arch/v850/kernel/v850_ksyms.c | 53 +- arch/v850/kernel/vmlinux.lds.S | 8 +- arch/x86_64/Kconfig | 184 +- arch/x86_64/Kconfig.debug | 22 +- arch/x86_64/Makefile | 11 +- arch/x86_64/boot/Makefile | 3 +- arch/x86_64/boot/compressed/Makefile | 2 +- arch/x86_64/boot/video.S | 86 +- arch/x86_64/defconfig | 107 +- arch/x86_64/ia32/ia32_aout.c | 7 +- arch/x86_64/ia32/ia32_binfmt.c | 23 +- arch/x86_64/ia32/ia32_ioctl.c | 15 - arch/x86_64/ia32/ia32_signal.c | 64 +- arch/x86_64/ia32/ia32entry.S | 66 +- arch/x86_64/ia32/ptrace32.c | 9 +- arch/x86_64/ia32/sys_ia32.c | 302 +- arch/x86_64/ia32/syscall32.c | 27 +- arch/x86_64/kernel/Makefile | 16 +- arch/x86_64/kernel/aperture.c | 23 +- arch/x86_64/kernel/apic.c | 132 +- arch/x86_64/kernel/asm-offsets.c | 2 +- arch/x86_64/kernel/cpufreq/Kconfig | 84 +- arch/x86_64/kernel/cpufreq/Makefile | 12 +- arch/x86_64/kernel/early_printk.c | 21 +- arch/x86_64/kernel/entry.S | 21 +- arch/x86_64/kernel/head.S | 12 + arch/x86_64/kernel/head64.c | 6 + arch/x86_64/kernel/i8259.c | 57 +- arch/x86_64/kernel/init_task.c | 3 +- arch/x86_64/kernel/io_apic.c | 363 +- arch/x86_64/kernel/ioport.c | 40 +- arch/x86_64/kernel/irq.c | 872 +- arch/x86_64/kernel/ldt.c | 10 +- arch/x86_64/kernel/mce.c | 137 +- arch/x86_64/kernel/mpparse.c | 14 +- arch/x86_64/kernel/msr.c | 325 +- arch/x86_64/kernel/nmi.c | 67 +- arch/x86_64/kernel/pci-dma.c | 21 +- arch/x86_64/kernel/pci-gart.c | 311 +- arch/x86_64/kernel/pci-nommu.c | 62 +- arch/x86_64/kernel/process.c | 95 +- arch/x86_64/kernel/ptrace.c | 25 +- arch/x86_64/kernel/setup.c | 204 +- arch/x86_64/kernel/setup64.c | 80 +- arch/x86_64/kernel/signal.c | 62 +- arch/x86_64/kernel/smp.c | 166 +- arch/x86_64/kernel/smpboot.c | 35 +- arch/x86_64/kernel/suspend.c | 2 +- arch/x86_64/kernel/suspend_asm.S | 82 +- arch/x86_64/kernel/time.c | 323 +- arch/x86_64/kernel/traps.c | 145 +- arch/x86_64/kernel/vmlinux.lds.S | 39 +- arch/x86_64/kernel/vsyscall.c | 15 +- arch/x86_64/kernel/x8664_ksyms.c | 96 +- arch/x86_64/lib/Makefile | 2 +- arch/x86_64/lib/bitops.c | 2 +- arch/x86_64/lib/bitstr.c | 5 +- arch/x86_64/lib/copy_user.S | 16 +- arch/x86_64/lib/csum-wrappers.c | 2 + arch/x86_64/lib/dec_and_lock.c | 2 +- arch/x86_64/lib/memmove.c | 16 +- arch/x86_64/lib/usercopy.c | 2 + arch/x86_64/mm/fault.c | 105 +- arch/x86_64/mm/init.c | 27 +- arch/x86_64/mm/ioremap.c | 12 +- arch/x86_64/mm/k8topology.c | 5 +- arch/x86_64/mm/numa.c | 69 +- arch/x86_64/pci/Makefile | 4 +- arch/x86_64/pci/mmconfig.c | 10 +- crypto/Kconfig | 32 +- crypto/Makefile | 2 + crypto/aes.c | 14 +- crypto/api.c | 6 +- crypto/arc4.c | 4 +- crypto/blowfish.c | 8 +- crypto/internal.h | 1 - crypto/scatterwalk.c | 2 +- crypto/serpent.c | 105 +- crypto/sha256.c | 10 +- crypto/sha512.c | 31 +- crypto/tcrypt.c | 45 +- crypto/tcrypt.h | 557 +- crypto/tea.c | 2 +- crypto/twofish.c | 4 +- drivers/Kconfig | 2 + drivers/Makefile | 15 +- drivers/acorn/block/fd1772.c | 2 +- drivers/acpi/Kconfig | 55 + drivers/acpi/Makefile | 6 +- drivers/acpi/ac.c | 8 +- drivers/acpi/asus_acpi.c | 184 +- drivers/acpi/battery.c | 205 +- drivers/acpi/blacklist.c | 58 +- drivers/acpi/bus.c | 64 +- drivers/acpi/button.c | 17 +- drivers/acpi/debug.c | 105 +- drivers/acpi/dispatcher/dsmethod.c | 70 +- drivers/acpi/dispatcher/dsmthdat.c | 32 +- drivers/acpi/dispatcher/dsopcode.c | 7 +- drivers/acpi/dispatcher/dsutils.c | 55 +- drivers/acpi/dispatcher/dswexec.c | 45 +- drivers/acpi/dispatcher/dswload.c | 24 + drivers/acpi/dispatcher/dswstate.c | 29 +- drivers/acpi/ec.c | 76 +- drivers/acpi/events/evevent.c | 12 +- drivers/acpi/events/evgpe.c | 394 +- drivers/acpi/events/evgpeblk.c | 179 +- drivers/acpi/events/evmisc.c | 45 +- drivers/acpi/events/evregion.c | 388 +- drivers/acpi/events/evrgnini.c | 12 +- drivers/acpi/events/evxface.c | 247 +- drivers/acpi/events/evxfevnt.c | 188 +- drivers/acpi/events/evxfregn.c | 207 +- drivers/acpi/executer/exconfig.c | 47 +- drivers/acpi/executer/exconvrt.c | 359 +- drivers/acpi/executer/exdump.c | 225 +- drivers/acpi/executer/exfldio.c | 200 +- drivers/acpi/executer/exmisc.c | 464 +- drivers/acpi/executer/exmutex.c | 46 +- drivers/acpi/executer/exoparg1.c | 211 +- drivers/acpi/executer/exoparg2.c | 168 +- drivers/acpi/executer/exprep.c | 1 + drivers/acpi/executer/exregion.c | 2 +- drivers/acpi/executer/exresolv.c | 68 +- drivers/acpi/executer/exresop.c | 16 +- drivers/acpi/executer/exstore.c | 54 +- drivers/acpi/executer/exsystem.c | 5 +- drivers/acpi/executer/exutils.c | 18 +- drivers/acpi/fan.c | 50 +- drivers/acpi/hardware/Makefile | 4 +- drivers/acpi/hardware/hwgpe.c | 344 +- drivers/acpi/hardware/hwregs.c | 142 +- drivers/acpi/hardware/hwsleep.c | 64 +- drivers/acpi/hardware/hwtimer.c | 50 +- drivers/acpi/motherboard.c | 4 +- drivers/acpi/namespace/Makefile | 4 +- drivers/acpi/namespace/nsaccess.c | 18 +- drivers/acpi/namespace/nsalloc.c | 10 +- drivers/acpi/namespace/nsdump.c | 65 +- drivers/acpi/namespace/nsdumpdv.c | 11 +- drivers/acpi/namespace/nseval.c | 178 +- drivers/acpi/namespace/nsinit.c | 69 +- drivers/acpi/namespace/nsload.c | 15 +- drivers/acpi/namespace/nsnames.c | 9 +- drivers/acpi/namespace/nsparse.c | 5 +- drivers/acpi/namespace/nssearch.c | 49 +- drivers/acpi/namespace/nsutils.c | 56 +- drivers/acpi/namespace/nswalk.c | 4 +- drivers/acpi/namespace/nsxfeval.c | 59 +- drivers/acpi/namespace/nsxfname.c | 8 +- drivers/acpi/namespace/nsxfobj.c | 5 +- drivers/acpi/numa.c | 16 +- drivers/acpi/osl.c | 149 +- drivers/acpi/parser/psopcode.c | 35 +- drivers/acpi/parser/psparse.c | 189 +- drivers/acpi/parser/pstree.c | 4 +- drivers/acpi/parser/psutils.c | 27 +- drivers/acpi/parser/psxface.c | 51 +- drivers/acpi/pci_bind.c | 2 + drivers/acpi/pci_irq.c | 43 +- drivers/acpi/pci_link.c | 129 +- drivers/acpi/pci_root.c | 2 + drivers/acpi/power.c | 82 +- drivers/acpi/processor.c | 309 +- drivers/acpi/resources/Makefile | 4 +- drivers/acpi/resources/rscalc.c | 112 +- drivers/acpi/resources/rsutils.c | 10 +- drivers/acpi/resources/rsxface.c | 13 +- drivers/acpi/scan.c | 208 +- drivers/acpi/sleep/Makefile | 2 +- drivers/acpi/sleep/main.c | 41 +- drivers/acpi/sleep/poweroff.c | 2 + drivers/acpi/sleep/proc.c | 88 +- drivers/acpi/sleep/sleep.h | 4 + drivers/acpi/sleep/wakeup.c | 32 +- drivers/acpi/system.c | 45 +- drivers/acpi/tables.c | 4 +- drivers/acpi/tables/tbconvrt.c | 56 +- drivers/acpi/tables/tbget.c | 3 + drivers/acpi/tables/tbinstal.c | 3 +- drivers/acpi/tables/tbutils.c | 3 +- drivers/acpi/tables/tbxface.c | 7 +- drivers/acpi/tables/tbxfroot.c | 234 +- drivers/acpi/thermal.c | 104 +- drivers/acpi/utilities/utalloc.c | 36 +- drivers/acpi/utilities/utcopy.c | 27 +- drivers/acpi/utilities/utdebug.c | 7 + drivers/acpi/utilities/utdelete.c | 9 +- drivers/acpi/utilities/uteval.c | 18 +- drivers/acpi/utilities/utglobal.c | 91 +- drivers/acpi/utilities/utmath.c | 43 +- drivers/acpi/utilities/utmisc.c | 105 +- drivers/acpi/utilities/utobject.c | 60 +- drivers/acpi/utilities/utxface.c | 47 +- drivers/acpi/utils.c | 6 +- drivers/atm/Makefile | 4 +- drivers/atm/ambassador.c | 182 +- drivers/atm/ambassador.h | 2 +- drivers/atm/atmtcp.c | 42 +- drivers/atm/eni.c | 94 +- drivers/atm/eni.h | 20 +- drivers/atm/firestream.c | 74 +- drivers/atm/firestream.h | 2 +- drivers/atm/fore200e.c | 87 +- drivers/atm/fore200e.h | 34 +- drivers/atm/he.c | 39 +- drivers/atm/he.h | 2 +- drivers/atm/horizon.c | 342 +- drivers/atm/horizon.h | 2 +- drivers/atm/idt77252.c | 108 +- drivers/atm/idt77252.h | 4 +- drivers/atm/iphase.c | 94 +- drivers/atm/iphase.h | 24 +- drivers/atm/lanai.c | 20 +- drivers/atm/nicstar.c | 7 +- drivers/atm/nicstar.h | 2 +- drivers/atm/nicstarmac.c | 2 +- drivers/atm/nicstarmac.h | 2 +- drivers/atm/zatm.c | 102 +- drivers/base/Kconfig | 2 +- drivers/base/bus.c | 200 +- drivers/base/class.c | 83 +- drivers/base/class_simple.c | 2 +- drivers/base/core.c | 54 +- drivers/base/cpu.c | 2 + drivers/base/driver.c | 16 +- drivers/base/firmware.c | 4 +- drivers/base/firmware_class.c | 20 +- drivers/base/node.c | 13 +- drivers/base/platform.c | 16 +- drivers/base/power/main.c | 13 +- drivers/base/power/power.h | 5 + drivers/base/power/resume.c | 20 +- drivers/base/power/suspend.c | 48 +- drivers/base/sys.c | 16 +- drivers/block/DAC960.c | 44 +- drivers/block/DAC960.h | 188 +- drivers/block/Kconfig | 82 +- drivers/block/Kconfig.iosched | 13 +- drivers/block/Makefile | 2 + drivers/block/amiflop.c | 20 +- drivers/block/as-iosched.c | 122 +- drivers/block/cciss.c | 166 +- drivers/block/cciss.h | 6 +- drivers/block/cciss_scsi.c | 53 +- drivers/block/cfq-iosched.c | 1510 +- drivers/block/cpqarray.c | 32 +- drivers/block/cpqarray.h | 2 +- drivers/block/deadline-iosched.c | 136 +- drivers/block/elevator.c | 385 +- drivers/block/floppy.c | 28 +- drivers/block/genhd.c | 50 +- drivers/block/ioctl.c | 3 +- drivers/block/ll_rw_blk.c | 778 +- drivers/block/loop.c | 4 +- drivers/block/nbd.c | 39 +- drivers/block/noop-iosched.c | 33 +- drivers/block/paride/paride.c | 4 +- drivers/block/paride/paride.h | 2 - drivers/block/paride/pg.c | 2 +- drivers/block/rd.c | 32 +- drivers/block/scsi_ioctl.c | 50 +- drivers/block/swim3.c | 50 +- drivers/block/sx8.c | 96 +- drivers/block/ub.c | 234 +- drivers/block/umem.c | 16 +- drivers/block/viodasd.c | 2 +- drivers/block/xd.c | 20 +- drivers/block/z2ram.c | 2 +- drivers/bluetooth/bcm203x.c | 3 +- drivers/bluetooth/bfusb.c | 4 +- drivers/bluetooth/bluecard_cs.c | 34 +- drivers/bluetooth/bt3c_cs.c | 48 +- drivers/bluetooth/btuart_cs.c | 33 +- drivers/bluetooth/dtl1_cs.c | 33 +- drivers/bluetooth/hci_ldisc.c | 12 +- drivers/bluetooth/hci_usb.c | 43 +- drivers/bluetooth/hci_usb.h | 7 - drivers/bluetooth/hci_vhci.c | 4 +- drivers/cdrom/Makefile | 1 + drivers/cdrom/cdrom.c | 279 +- drivers/cdrom/cdu31a.c | 406 +- drivers/cdrom/cdu31a.h | 4 +- drivers/cdrom/mcd.c | 7 +- drivers/cdrom/sbpcd.c | 9 +- drivers/cdrom/viocd.c | 119 +- drivers/char/Kconfig | 75 +- drivers/char/Makefile | 11 +- drivers/char/agp/Kconfig | 4 +- drivers/char/agp/agp.h | 2 +- drivers/char/agp/amd-k7-agp.c | 31 +- drivers/char/agp/amd64-agp.c | 8 +- drivers/char/agp/ati-agp.c | 31 +- drivers/char/agp/frontend.c | 8 +- drivers/char/agp/generic.c | 16 +- drivers/char/agp/hp-agp.c | 16 +- drivers/char/agp/intel-agp.c | 139 +- drivers/char/agp/intel-mch-agp.c | 10 +- drivers/char/agp/nvidia-agp.c | 25 +- drivers/char/agp/sis-agp.c | 10 +- drivers/char/agp/sworks-agp.c | 43 +- drivers/char/agp/via-agp.c | 33 +- drivers/char/amiserial.c | 113 +- drivers/char/applicom.c | 30 +- drivers/char/cyclades.c | 730 +- drivers/char/drm/Kconfig | 27 +- drivers/char/drm/Makefile | 2 + drivers/char/drm/drmP.h | 233 +- drivers/char/drm/drm_agpsupport.h | 5 +- drivers/char/drm/drm_bufs.h | 137 +- drivers/char/drm/drm_context.h | 20 +- drivers/char/drm/drm_dma.h | 53 +- drivers/char/drm/drm_drv.h | 535 +- drivers/char/drm/drm_fops.h | 22 +- drivers/char/drm/drm_ioctl.h | 6 +- drivers/char/drm/drm_irq.h | 81 +- drivers/char/drm/drm_memory.h | 38 +- drivers/char/drm/drm_memory_debug.h | 2 +- drivers/char/drm/drm_os_linux.h | 42 +- drivers/char/drm/drm_pciids.h | 8 + drivers/char/drm/drm_scatter.h | 6 + drivers/char/drm/drm_vm.h | 48 +- drivers/char/drm/ffb.h | 4 - drivers/char/drm/ffb_context.c | 30 +- drivers/char/drm/ffb_drv.c | 214 +- drivers/char/drm/ffb_drv.h | 10 + drivers/char/drm/gamma.h | 39 +- drivers/char/drm/gamma_context.h | 4 +- drivers/char/drm/gamma_dma.c | 78 +- drivers/char/drm/gamma_drv.c | 1 + drivers/char/drm/gamma_drv.h | 5 +- drivers/char/drm/i810.h | 47 - drivers/char/drm/i810_dma.c | 55 +- drivers/char/drm/i810_drv.c | 17 +- drivers/char/drm/i810_drv.h | 1 - drivers/char/drm/i830.h | 50 - drivers/char/drm/i830_dma.c | 66 +- drivers/char/drm/i830_drv.c | 18 +- drivers/char/drm/i830_drv.h | 5 +- drivers/char/drm/i830_irq.c | 12 +- drivers/char/drm/mga.h | 35 - drivers/char/drm/mga_dma.c | 59 +- drivers/char/drm/mga_drv.c | 17 +- drivers/char/drm/mga_drv.h | 6 + drivers/char/drm/mga_irq.c | 4 +- drivers/char/drm/r128.h | 45 - drivers/char/drm/r128_cce.c | 45 +- drivers/char/drm/r128_drv.c | 18 +- drivers/char/drm/r128_drv.h | 7 +- drivers/char/drm/r128_irq.c | 4 +- drivers/char/drm/r128_state.c | 36 +- drivers/char/drm/radeon.h | 61 - drivers/char/drm/radeon_cp.c | 54 +- drivers/char/drm/radeon_drv.c | 18 +- drivers/char/drm/radeon_drv.h | 9 +- drivers/char/drm/radeon_irq.c | 4 +- drivers/char/drm/radeon_mem.c | 8 +- drivers/char/drm/radeon_state.c | 83 +- drivers/char/drm/sis.h | 17 - drivers/char/drm/sis_drv.c | 16 +- drivers/char/drm/sis_drv.h | 2 - drivers/char/drm/sis_mm.c | 18 +- drivers/char/drm/tdfx.h | 2 - drivers/char/drm/tdfx_drv.c | 20 +- drivers/char/ds1620.c | 3 +- drivers/char/dsp56k.c | 14 +- drivers/char/dtlk.c | 19 +- drivers/char/ec3104_keyb.c | 4 +- drivers/char/efirtc.c | 19 +- drivers/char/epca.c | 205 +- drivers/char/epca.h | 2 +- drivers/char/esp.c | 116 +- drivers/char/ftape/lowlevel/fdc-io.c | 2 +- drivers/char/ftape/lowlevel/ftape-calibr.c | 71 +- drivers/char/ftape/lowlevel/ftape-ctl.c | 7 +- drivers/char/ftape/lowlevel/ftape-init.c | 31 +- drivers/char/ftape/lowlevel/ftape-io.c | 20 +- drivers/char/ftape/zftape/zftape-buffers.c | 4 +- drivers/char/generic_serial.c | 134 +- drivers/char/hpet.c | 184 +- drivers/char/hvc_console.c | 720 +- drivers/char/hvcs.c | 471 +- drivers/char/hvsi.c | 141 +- drivers/char/hw_random.c | 4 +- drivers/char/i8k.c | 16 +- drivers/char/ip2.c | 6 +- drivers/char/ip2/ip2types.h | 3 + drivers/char/ip2main.c | 22 +- drivers/char/ipmi/Kconfig | 7 + drivers/char/ipmi/Makefile | 1 + drivers/char/ipmi/ipmi_bt_sm.c | 2 +- drivers/char/ipmi/ipmi_devintf.c | 2 +- drivers/char/ipmi/ipmi_kcs_sm.c | 2 +- drivers/char/ipmi/ipmi_msghandler.c | 58 +- drivers/char/ipmi/ipmi_si_intf.c | 385 +- drivers/char/ipmi/ipmi_si_sm.h | 3 + drivers/char/ipmi/ipmi_smic_sm.c | 2 +- drivers/char/ipmi/ipmi_watchdog.c | 71 +- drivers/char/isicom.c | 60 +- drivers/char/istallion.c | 106 +- drivers/char/keyboard.c | 33 +- drivers/char/lcd.c | 4 +- drivers/char/lp.c | 4 +- drivers/char/mem.c | 29 +- drivers/char/mmtimer.c | 543 +- drivers/char/moxa.c | 153 +- drivers/char/mwave/3780i.c | 2 +- drivers/char/mxser.c | 2723 ++-- drivers/char/n_hdlc.c | 24 +- drivers/char/n_r3964.c | 15 +- drivers/char/n_tty.c | 414 +- drivers/char/nwflash.c | 21 +- drivers/char/pcmcia/synclink_cs.c | 662 +- drivers/char/pcxx.c | 111 +- drivers/char/pty.c | 220 +- drivers/char/qtronix.c | 2 +- drivers/char/random.c | 276 +- drivers/char/rio/linux_compat.h | 2 +- drivers/char/rio/rio_linux.c | 18 +- drivers/char/riscom8.c | 86 +- drivers/char/rocket.c | 120 +- drivers/char/rocket_int.h | 4 - drivers/char/selection.c | 14 +- drivers/char/ser_a2232.c | 5 +- drivers/char/serial167.c | 120 +- drivers/char/serial_tx3912.c | 5 +- drivers/char/snsc.c | 26 +- drivers/char/sonypi.c | 897 +- drivers/char/sonypi.h | 136 +- drivers/char/specialix.c | 91 +- drivers/char/stallion.c | 61 +- drivers/char/sx.c | 86 +- drivers/char/sx.h | 4 +- drivers/char/synclink.c | 744 +- drivers/char/synclinkmp.c | 819 +- drivers/char/sysrq.c | 59 +- drivers/char/tipar.c | 2 +- drivers/char/tpqic02.c | 3 +- drivers/char/tty_io.c | 914 +- drivers/char/tty_ioctl.c | 67 +- drivers/char/viocons.c | 189 +- drivers/char/viotape.c | 2 +- drivers/char/vme_scc.c | 8 +- drivers/char/vt.c | 112 +- drivers/char/vt_ioctl.c | 3 +- drivers/char/watchdog/Kconfig | 36 + drivers/char/watchdog/Makefile | 2 + drivers/char/watchdog/cpu5wdt.c | 3 +- drivers/char/watchdog/i8xx_tco.c | 15 +- drivers/char/watchdog/ib700wdt.c | 1 + drivers/char/watchdog/indydog.c | 1 + drivers/char/watchdog/ixp2000_wdt.c | 2 +- drivers/char/watchdog/ixp4xx_wdt.c | 5 +- drivers/char/watchdog/machzwd.c | 1 + drivers/char/watchdog/mixcomwd.c | 1 + drivers/char/watchdog/pcwd.c | 3 +- drivers/char/watchdog/sa1100_wdt.c | 5 + drivers/char/watchdog/sc1200wdt.c | 1 + drivers/char/watchdog/sc520_wdt.c | 2 +- drivers/char/watchdog/scx200_wdt.c | 13 +- drivers/char/watchdog/wdt285.c | 1 + drivers/char/watchdog/wdt977.c | 1 + drivers/char/watchdog/wdt_pci.c | 2 +- drivers/cpufreq/Kconfig | 57 +- drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq.c | 463 +- drivers/cpufreq/cpufreq_ondemand.c | 52 +- drivers/cpufreq/cpufreq_performance.c | 4 + drivers/cpufreq/cpufreq_powersave.c | 3 + drivers/cpufreq/cpufreq_userspace.c | 76 +- drivers/cpufreq/freq_table.c | 23 +- drivers/cpufreq/proc_intf.c | 17 + drivers/dio/Makefile | 2 +- drivers/dio/dio.c | 321 +- drivers/eisa/eisa-bus.c | 4 +- drivers/fc4/soc.c | 10 +- drivers/fc4/soc.h | 22 +- drivers/fc4/socal.c | 16 +- drivers/fc4/socal.h | 8 +- drivers/firmware/Kconfig | 11 +- drivers/firmware/edd.c | 8 +- drivers/firmware/efivars.c | 2 +- drivers/firmware/pcdp.c | 138 +- drivers/i2c/Makefile | 3 + drivers/i2c/algos/Kconfig | 11 + drivers/i2c/algos/Makefile | 1 + drivers/i2c/algos/i2c-algo-bit.c | 4 +- drivers/i2c/algos/i2c-algo-ite.c | 22 +- drivers/i2c/algos/i2c-algo-pca.c | 4 +- drivers/i2c/algos/i2c-algo-pcf.c | 12 +- drivers/i2c/busses/Kconfig | 84 +- drivers/i2c/busses/Makefile | 6 + drivers/i2c/busses/i2c-ali1535.c | 8 +- drivers/i2c/busses/i2c-ali1563.c | 6 +- drivers/i2c/busses/i2c-ali15x3.c | 10 +- drivers/i2c/busses/i2c-amd756.c | 62 +- drivers/i2c/busses/i2c-amd8111.c | 18 +- drivers/i2c/busses/i2c-elektor.c | 46 +- drivers/i2c/busses/i2c-hydra.c | 6 +- drivers/i2c/busses/i2c-i801.c | 10 +- drivers/i2c/busses/i2c-i810.c | 8 +- drivers/i2c/busses/i2c-ibm_iic.c | 60 +- drivers/i2c/busses/i2c-ibm_iic.h | 2 +- drivers/i2c/busses/i2c-ite.c | 55 +- drivers/i2c/busses/i2c-keywest.c | 17 +- drivers/i2c/busses/i2c-keywest.h | 6 +- drivers/i2c/busses/i2c-mpc.c | 7 +- drivers/i2c/busses/i2c-nforce2.c | 26 +- drivers/i2c/busses/i2c-parport-light.c | 4 +- drivers/i2c/busses/i2c-parport.h | 2 +- drivers/i2c/busses/i2c-piix4.c | 6 +- drivers/i2c/busses/i2c-prosavage.c | 16 +- drivers/i2c/busses/i2c-savage4.c | 8 +- drivers/i2c/busses/i2c-sis5595.c | 10 +- drivers/i2c/busses/i2c-sis630.c | 21 +- drivers/i2c/busses/i2c-sis96x.c | 6 +- drivers/i2c/busses/i2c-via.c | 6 +- drivers/i2c/busses/i2c-viapro.c | 12 +- drivers/i2c/busses/i2c-voodoo3.c | 8 +- drivers/i2c/busses/scx200_acb.c | 22 +- drivers/i2c/busses/scx200_i2c.c | 14 +- drivers/i2c/chips/Kconfig | 75 +- drivers/i2c/chips/Makefile | 7 + drivers/i2c/chips/adm1021.c | 13 +- drivers/i2c/chips/adm1025.c | 22 +- drivers/i2c/chips/adm1031.c | 52 +- drivers/i2c/chips/asb100.c | 32 +- drivers/i2c/chips/ds1621.c | 9 +- drivers/i2c/chips/eeprom.c | 9 +- drivers/i2c/chips/fscher.c | 4 +- drivers/i2c/chips/gl518sm.c | 10 +- drivers/i2c/chips/it87.c | 116 +- drivers/i2c/chips/lm75.c | 7 +- drivers/i2c/chips/lm77.c | 6 +- drivers/i2c/chips/lm78.c | 51 +- drivers/i2c/chips/lm80.c | 12 +- drivers/i2c/chips/lm83.c | 43 +- drivers/i2c/chips/lm85.c | 513 +- drivers/i2c/chips/lm90.c | 47 +- drivers/i2c/chips/max1619.c | 13 +- drivers/i2c/chips/pcf8574.c | 8 +- drivers/i2c/chips/pcf8591.c | 9 +- drivers/i2c/chips/rtc8564.c | 4 +- drivers/i2c/chips/smsc47m1.c | 87 +- drivers/i2c/chips/via686a.c | 38 +- drivers/i2c/chips/w83627hf.c | 40 +- drivers/i2c/chips/w83781d.c | 95 +- drivers/i2c/chips/w83l785ts.c | 11 +- drivers/i2c/i2c-core.c | 106 +- drivers/i2c/i2c-dev.c | 2 +- drivers/i2c/i2c-sensor-detect.c | 79 +- drivers/ide/Kconfig | 47 +- drivers/ide/Makefile | 1 + drivers/ide/arm/Makefile | 1 + drivers/ide/arm/icside.c | 443 +- drivers/ide/arm/rapide.c | 85 +- drivers/ide/ide-cd.c | 82 +- drivers/ide/ide-cd.h | 6 +- drivers/ide/ide-default.c | 2 +- drivers/ide/ide-disk.c | 588 +- drivers/ide/ide-dma.c | 247 +- drivers/ide/ide-floppy.c | 53 +- drivers/ide/ide-io.c | 363 +- drivers/ide/ide-iops.c | 56 +- drivers/ide/ide-lib.c | 8 +- drivers/ide/ide-probe.c | 114 +- drivers/ide/ide-proc.c | 326 +- drivers/ide/ide-tape.c | 86 +- drivers/ide/ide-taskfile.c | 398 +- drivers/ide/ide.c | 301 +- drivers/ide/legacy/Makefile | 2 - drivers/ide/legacy/ali14xx.c | 2 + drivers/ide/legacy/dtc2278.c | 2 + drivers/ide/legacy/hd.c | 8 +- drivers/ide/legacy/ht6560b.c | 2 + drivers/ide/legacy/ide-cs.c | 8 +- drivers/ide/legacy/qd65xx.c | 9 +- drivers/ide/legacy/qd65xx.h | 8 +- drivers/ide/legacy/umc8672.c | 2 + drivers/ide/pci/aec62xx.c | 193 +- drivers/ide/pci/aec62xx.h | 13 +- drivers/ide/pci/alim15x3.c | 34 +- drivers/ide/pci/amd74xx.c | 5 +- drivers/ide/pci/atiixp.c | 155 +- drivers/ide/pci/cmd640.c | 6 +- drivers/ide/pci/cmd64x.c | 53 +- drivers/ide/pci/cmd64x.h | 4 - drivers/ide/pci/cs5520.c | 87 +- drivers/ide/pci/cs5530.c | 59 - drivers/ide/pci/cy82c693.c | 4 +- drivers/ide/pci/generic.c | 6 +- drivers/ide/pci/hpt34x.c | 125 +- drivers/ide/pci/hpt366.c | 128 +- drivers/ide/pci/hpt366.h | 40 +- drivers/ide/pci/it8172.c | 36 +- drivers/ide/pci/ns87415.c | 103 +- drivers/ide/pci/opti621.c | 2 +- drivers/ide/pci/pdc202xx_new.c | 163 +- drivers/ide/pci/pdc202xx_new.h | 2 - drivers/ide/pci/pdc202xx_old.c | 191 +- drivers/ide/pci/pdc202xx_old.h | 108 - drivers/ide/pci/piix.c | 204 +- drivers/ide/pci/piix.h | 4 - drivers/ide/pci/rz1000.c | 4 +- drivers/ide/pci/sc1200.c | 71 +- drivers/ide/pci/serverworks.c | 206 +- drivers/ide/pci/serverworks.h | 4 +- drivers/ide/pci/sgiioc4.c | 115 +- drivers/ide/pci/siimage.c | 148 +- drivers/ide/pci/sis5513.c | 46 +- drivers/ide/pci/sl82c105.c | 10 +- drivers/ide/pci/slc90e66.c | 148 +- drivers/ide/pci/triflex.c | 89 +- drivers/ide/pci/trm290.c | 101 +- drivers/ide/pci/via82cxxx.c | 2 +- drivers/ide/ppc/pmac.c | 295 +- drivers/ide/setup-pci.c | 65 +- drivers/ieee1394/eth1394.c | 100 +- drivers/ieee1394/eth1394.h | 7 + drivers/ieee1394/nodemgr.c | 13 +- drivers/ieee1394/ohci1394.c | 12 +- drivers/ieee1394/ohci1394.h | 2 +- drivers/ieee1394/pcilynx.c | 2 +- drivers/ieee1394/pcilynx.h | 8 +- drivers/ieee1394/sbp2.c | 11 +- drivers/ieee1394/sbp2.h | 18 +- drivers/ieee1394/video1394.c | 2 +- drivers/input/evdev.c | 4 +- drivers/input/gameport/cs461x.c | 2 +- drivers/input/gameport/emu10k1-gp.c | 5 +- drivers/input/gameport/fm801-gp.c | 4 +- drivers/input/gameport/vortex.c | 6 +- drivers/input/input.c | 2 +- drivers/input/joydev.c | 10 +- drivers/input/joystick/Kconfig | 4 +- drivers/input/joystick/amijoy.c | 3 +- drivers/input/joystick/analog.c | 2 +- drivers/input/joystick/db9.c | 6 +- drivers/input/joystick/gamecon.c | 200 +- drivers/input/joystick/grip_mp.c | 3 +- drivers/input/joystick/iforce/iforce-main.c | 4 +- drivers/input/joystick/iforce/iforce-serio.c | 18 +- drivers/input/joystick/iforce/iforce.h | 2 +- drivers/input/joystick/magellan.c | 24 +- drivers/input/joystick/spaceball.c | 24 +- drivers/input/joystick/spaceorb.c | 24 +- drivers/input/joystick/stinger.c | 24 +- drivers/input/joystick/tmdc.c | 2 +- drivers/input/joystick/turbografx.c | 6 +- drivers/input/joystick/twidjoy.c | 20 +- drivers/input/joystick/warrior.c | 24 +- drivers/input/keyboard/atkbd.c | 285 +- drivers/input/keyboard/lkkbd.c | 24 +- drivers/input/keyboard/newtonkbd.c | 24 +- drivers/input/keyboard/sunkbd.c | 24 +- drivers/input/keyboard/xtkbd.c | 24 +- drivers/input/misc/Kconfig | 2 +- drivers/input/misc/uinput.c | 3 + drivers/input/mouse/Kconfig | 8 +- drivers/input/mouse/logips2pp.c | 2 +- drivers/input/mouse/pc110pad.c | 21 +- drivers/input/mouse/psmouse-base.c | 312 +- drivers/input/mouse/psmouse.h | 40 +- drivers/input/mouse/sermouse.c | 24 +- drivers/input/mouse/synaptics.c | 54 +- drivers/input/mouse/vsxxxaa.c | 24 +- drivers/input/mousedev.c | 241 +- drivers/input/serio/Kconfig | 18 +- drivers/input/serio/Makefile | 1 + drivers/input/serio/ambakmi.c | 44 +- drivers/input/serio/ct82c710.c | 104 +- drivers/input/serio/gscps2.c | 64 +- drivers/input/serio/i8042-io.h | 42 +- drivers/input/serio/i8042-sparcio.h | 8 +- drivers/input/serio/i8042.c | 392 +- drivers/input/serio/i8042.h | 7 + drivers/input/serio/maceps2.c | 86 +- drivers/input/serio/parkbd.c | 48 +- drivers/input/serio/pcips2.c | 54 +- drivers/input/serio/q40kbd.c | 119 +- drivers/input/serio/rpckbd.c | 50 +- drivers/input/serio/sa1111ps2.c | 41 +- drivers/input/serio/serio.c | 571 +- drivers/input/serio/serport.c | 51 +- drivers/input/touchscreen/gunze.c | 24 +- drivers/input/touchscreen/h3600_ts_input.c | 24 +- drivers/input/tsdev.c | 309 +- drivers/isdn/act2000/act2000_isa.c | 16 +- drivers/isdn/capi/capi.c | 116 +- drivers/isdn/capi/capidrv.c | 18 +- drivers/isdn/capi/kcapi.c | 35 +- drivers/isdn/divert/divert_init.c | 19 +- drivers/isdn/divert/divert_procfs.c | 20 +- drivers/isdn/divert/isdn_divert.c | 101 +- drivers/isdn/divert/isdn_divert.h | 2 + drivers/isdn/hardware/avm/Kconfig | 12 +- drivers/isdn/hardware/avm/b1.c | 8 +- drivers/isdn/hardware/avm/b1dma.c | 2 - drivers/isdn/hardware/avm/c4.c | 11 +- drivers/isdn/hardware/avm/t1isa.c | 7 +- drivers/isdn/hardware/eicon/capifunc.c | 47 +- drivers/isdn/hardware/eicon/capifunc.h | 4 +- drivers/isdn/hardware/eicon/debug.c | 488 +- drivers/isdn/hardware/eicon/debug_if.h | 6 + drivers/isdn/hardware/eicon/debuglib.h | 6 +- drivers/isdn/hardware/eicon/di.c | 22 +- drivers/isdn/hardware/eicon/diddfunc.c | 4 +- drivers/isdn/hardware/eicon/diva_didd.c | 10 +- drivers/isdn/hardware/eicon/diva_pci.h | 4 +- drivers/isdn/hardware/eicon/divamnt.c | 236 +- drivers/isdn/hardware/eicon/divasfunc.c | 12 +- drivers/isdn/hardware/eicon/divasmain.c | 22 +- drivers/isdn/hardware/eicon/divasync.h | 21 +- drivers/isdn/hardware/eicon/idifunc.c | 4 +- drivers/isdn/hardware/eicon/io.c | 114 +- drivers/isdn/hardware/eicon/io.h | 69 +- drivers/isdn/hardware/eicon/maintidi.c | 61 +- drivers/isdn/hardware/eicon/maintidi.h | 4 +- drivers/isdn/hardware/eicon/message.c | 788 +- drivers/isdn/hardware/eicon/mntfunc.c | 103 +- drivers/isdn/hardware/eicon/os_4bri.c | 34 +- drivers/isdn/hardware/eicon/os_bri.c | 23 +- drivers/isdn/hardware/eicon/os_pri.c | 61 +- drivers/isdn/hardware/eicon/pc.h | 87 + drivers/isdn/hardware/eicon/platform.h | 71 +- drivers/isdn/hardware/eicon/s_4bri.c | 66 +- drivers/isdn/hardware/eicon/s_bri.c | 22 +- drivers/isdn/hardware/eicon/s_pri.c | 34 +- drivers/isdn/hardware/eicon/xdi_adapter.h | 2 +- drivers/isdn/hisax/amd7930_fn.c | 4 +- drivers/isdn/hisax/avm_pci.c | 106 +- drivers/isdn/hisax/bkm_a4t.c | 4 +- drivers/isdn/hisax/bkm_a8.c | 4 +- drivers/isdn/hisax/config.c | 3 +- drivers/isdn/hisax/diva.c | 2 +- drivers/isdn/hisax/elsa.c | 5 +- drivers/isdn/hisax/enternow_pci.c | 2 +- drivers/isdn/hisax/gazel.c | 2 +- drivers/isdn/hisax/hfc_pci.c | 7 +- drivers/isdn/hisax/hfc_sx.c | 6 +- drivers/isdn/hisax/hfcscard.c | 3 +- drivers/isdn/hisax/hisax.h | 6 +- drivers/isdn/hisax/hisax_fcpcipnp.c | 14 +- drivers/isdn/hisax/isurf.c | 5 +- drivers/isdn/hisax/niccy.c | 2 +- drivers/isdn/hisax/nj_s.c | 2 +- drivers/isdn/hisax/nj_u.c | 4 +- drivers/isdn/hisax/sedlbauer.c | 2 +- drivers/isdn/hisax/st5481_usb.c | 3 - drivers/isdn/hisax/teles0.c | 31 +- drivers/isdn/hisax/telespci.c | 24 +- drivers/isdn/hisax/w6692.c | 2 +- drivers/isdn/hysdn/boardergo.c | 7 +- drivers/isdn/hysdn/hycapi.c | 3 - drivers/isdn/hysdn/hysdn_sched.c | 7 +- drivers/isdn/i4l/Kconfig | 2 +- drivers/isdn/i4l/isdn_bsdcomp.c | 4 +- drivers/isdn/i4l/isdn_net.c | 2 +- drivers/isdn/i4l/isdn_tty.c | 70 +- drivers/isdn/i4l/isdn_x25iface.c | 16 +- drivers/isdn/icn/icn.c | 15 +- drivers/isdn/icn/icn.h | 3 +- drivers/isdn/isdnloop/isdnloop.c | 3 + drivers/isdn/pcbit/drv.c | 2 +- drivers/isdn/sc/card.h | 7 +- drivers/isdn/sc/hardware.h | 3 - drivers/isdn/sc/init.c | 10 +- drivers/isdn/tpam/tpam.h | 25 +- drivers/isdn/tpam/tpam_commands.c | 78 +- drivers/isdn/tpam/tpam_main.c | 63 +- drivers/isdn/tpam/tpam_memory.c | 38 +- drivers/isdn/tpam/tpam_nco.c | 34 +- drivers/isdn/tpam/tpam_queues.c | 49 +- drivers/macintosh/adbhid.c | 146 +- drivers/macintosh/ans-lcd.c | 6 +- drivers/macintosh/macio-adb.c | 7 +- drivers/macintosh/macserial.c | 83 +- drivers/macintosh/mediabay.c | 25 +- drivers/macintosh/therm_adt746x.c | 342 +- drivers/macintosh/therm_pm72.c | 577 +- drivers/macintosh/therm_pm72.h | 50 +- drivers/macintosh/therm_windtunnel.c | 11 +- drivers/macintosh/via-cuda.c | 4 +- drivers/macintosh/via-pmu.c | 46 +- drivers/md/Kconfig | 27 + drivers/md/Makefile | 4 +- drivers/md/dm-crypt.c | 322 +- drivers/md/dm-io.c | 2 +- drivers/md/dm-ioctl.c | 95 +- drivers/md/dm-log.c | 110 +- drivers/md/dm-log.h | 6 + drivers/md/dm-raid1.c | 29 +- drivers/md/dm-stripe.c | 9 +- drivers/md/dm-table.c | 36 +- drivers/md/dm-target.c | 5 +- drivers/md/dm.c | 220 +- drivers/md/dm.h | 9 + drivers/md/linear.c | 50 +- drivers/md/md.c | 257 +- drivers/md/multipath.c | 124 +- drivers/md/raid0.c | 26 +- drivers/md/raid1.c | 210 +- drivers/md/raid10.c | 99 +- drivers/md/raid5.c | 91 +- drivers/md/raid6main.c | 109 +- drivers/media/Kconfig | 15 +- drivers/media/common/ir-common.c | 12 +- drivers/media/common/saa7146_core.c | 193 +- drivers/media/common/saa7146_fops.c | 68 +- drivers/media/common/saa7146_hlp.c | 38 +- drivers/media/common/saa7146_i2c.c | 31 +- drivers/media/common/saa7146_vbi.c | 29 +- drivers/media/common/saa7146_video.c | 46 +- drivers/media/dvb/Kconfig | 20 +- drivers/media/dvb/Makefile | 3 +- drivers/media/dvb/b2c2/Kconfig | 18 +- drivers/media/dvb/b2c2/Makefile | 5 +- drivers/media/dvb/b2c2/skystar2.c | 419 +- drivers/media/dvb/bt8xx/Kconfig | 9 +- drivers/media/dvb/bt8xx/Makefile | 2 +- drivers/media/dvb/bt8xx/bt878.c | 67 +- drivers/media/dvb/bt8xx/bt878.h | 13 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 655 +- drivers/media/dvb/bt8xx/dvb-bt8xx.h | 11 +- drivers/media/dvb/dvb-core/Makefile | 4 +- drivers/media/dvb/dvb-core/dmxdev.c | 21 +- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 532 +- drivers/media/dvb/dvb-core/dvb_ca_en50221.h | 8 +- drivers/media/dvb/dvb-core/dvb_demux.c | 23 +- drivers/media/dvb/dvb-core/dvb_filter.c | 14 +- drivers/media/dvb/dvb-core/dvb_frontend.c | 888 +- drivers/media/dvb/dvb-core/dvb_frontend.h | 178 +- drivers/media/dvb/dvb-core/dvb_net.c | 520 +- drivers/media/dvb/dvb-core/dvbdev.c | 111 +- drivers/media/dvb/dvb-core/dvbdev.h | 12 + drivers/media/dvb/frontends/Kconfig | 225 +- drivers/media/dvb/frontends/Makefile | 16 +- drivers/media/dvb/frontends/at76c651.c | 498 +- drivers/media/dvb/frontends/cx24110.c | 625 +- drivers/media/dvb/frontends/dvb_dummy_fe.c | 322 +- drivers/media/dvb/frontends/mt312.c | 699 +- drivers/media/dvb/frontends/mt312.h | 159 +- drivers/media/dvb/frontends/nxt6000.c | 628 +- drivers/media/dvb/frontends/nxt6000.h | 285 +- drivers/media/dvb/frontends/sp887x.c | 616 +- drivers/media/dvb/frontends/stv0299.c | 1365 +- drivers/media/dvb/frontends/tda1004x.c | 1748 +- drivers/media/dvb/frontends/ves1820.c | 672 +- drivers/media/dvb/frontends/ves1x93.c | 592 +- drivers/media/dvb/ttpci/Kconfig | 34 +- drivers/media/dvb/ttpci/Makefile | 4 +- drivers/media/dvb/ttpci/av7110.c | 1081 +- drivers/media/dvb/ttpci/av7110.h | 49 +- drivers/media/dvb/ttpci/av7110_av.c | 73 +- drivers/media/dvb/ttpci/av7110_ca.c | 34 +- drivers/media/dvb/ttpci/av7110_hw.c | 459 +- drivers/media/dvb/ttpci/av7110_hw.h | 31 +- drivers/media/dvb/ttpci/av7110_ir.c | 17 +- drivers/media/dvb/ttpci/av7110_v4l.c | 210 +- drivers/media/dvb/ttpci/budget-av.c | 764 +- drivers/media/dvb/ttpci/budget-ci.c | 641 +- drivers/media/dvb/ttpci/budget-core.c | 173 +- drivers/media/dvb/ttpci/budget-patch.c | 262 +- drivers/media/dvb/ttpci/budget.c | 411 +- drivers/media/dvb/ttpci/budget.h | 36 +- drivers/media/dvb/ttpci/ttpci-eeprom.c | 23 +- drivers/media/dvb/ttpci/ttpci-eeprom.h | 5 +- drivers/media/dvb/ttusb-budget/Kconfig | 4 + drivers/media/dvb/ttusb-budget/Makefile | 2 +- .../media/dvb/ttusb-budget/dvb-ttusb-budget.c | 469 +- .../dvb/ttusb-budget/dvb-ttusb-dspbootcode.h | 2 +- drivers/media/dvb/ttusb-dec/Kconfig | 8 +- drivers/media/dvb/ttusb-dec/Makefile | 2 +- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 364 +- drivers/media/radio/miropcm20-rds.c | 4 +- drivers/media/radio/radio-aimslab.c | 7 +- drivers/media/radio/radio-cadet.c | 6 +- drivers/media/radio/radio-maestro.c | 54 +- drivers/media/radio/radio-maxiradio.c | 9 +- drivers/media/radio/radio-sf16fmi.c | 6 +- drivers/media/radio/radio-sf16fmr2.c | 15 +- drivers/media/video/Kconfig | 53 +- drivers/media/video/Makefile | 5 + drivers/media/video/adv7175.c | 28 + drivers/media/video/bt848.h | 10 +- drivers/media/video/btcx-risc.c | 8 +- drivers/media/video/btcx-risc.h | 4 +- drivers/media/video/bttv-cards.c | 593 +- drivers/media/video/bttv-driver.c | 359 +- drivers/media/video/bttv-gpio.c | 28 +- drivers/media/video/bttv-i2c.c | 96 +- drivers/media/video/bttv-if.c | 14 +- drivers/media/video/bttv-risc.c | 70 +- drivers/media/video/bttv-vbi.c | 47 +- drivers/media/video/bttv.h | 28 +- drivers/media/video/bttvp.h | 22 +- drivers/media/video/bw-qcam.c | 17 +- drivers/media/video/c-qcam.c | 6 +- drivers/media/video/cpia.c | 84 +- drivers/media/video/cx88/Makefile | 12 +- drivers/media/video/cx88/cx88-cards.c | 389 +- drivers/media/video/cx88/cx88-core.c | 743 +- drivers/media/video/cx88/cx88-i2c.c | 169 +- drivers/media/video/cx88/cx88-reg.h | 80 +- drivers/media/video/cx88/cx88-tvaudio.c | 196 +- drivers/media/video/cx88/cx88-vbi.c | 64 +- drivers/media/video/cx88/cx88-video.c | 990 +- drivers/media/video/cx88/cx88.h | 297 +- drivers/media/video/dpc7146.c | 11 +- drivers/media/video/hexium_gemini.c | 9 +- drivers/media/video/hexium_orion.c | 9 +- drivers/media/video/ir-kbd-gpio.c | 107 +- drivers/media/video/ir-kbd-i2c.c | 47 +- drivers/media/video/meye.c | 1629 +- drivers/media/video/meye.h | 57 +- drivers/media/video/msp3400.c | 1058 +- drivers/media/video/msp3400.h | 22 + drivers/media/video/mxb.c | 19 +- .../media/video/ovcamchip/ovcamchip_core.c | 7 +- drivers/media/video/planb.c | 9 +- drivers/media/video/pms.c | 16 +- drivers/media/video/saa5249.c | 3 +- drivers/media/video/saa7111.c | 4 +- drivers/media/video/saa7134/Makefile | 6 +- drivers/media/video/saa7134/saa6752hs.c | 107 +- drivers/media/video/saa7134/saa7134-cards.c | 399 +- drivers/media/video/saa7134/saa7134-core.c | 269 +- drivers/media/video/saa7134/saa7134-i2c.c | 45 +- drivers/media/video/saa7134/saa7134-input.c | 69 +- drivers/media/video/saa7134/saa7134-oss.c | 28 +- drivers/media/video/saa7134/saa7134-reg.h | 2 + drivers/media/video/saa7134/saa7134-ts.c | 362 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 84 +- drivers/media/video/saa7134/saa7134-vbi.c | 37 +- drivers/media/video/saa7134/saa7134-video.c | 206 +- drivers/media/video/saa7134/saa7134.h | 104 +- drivers/media/video/saa7146.h | 6 +- drivers/media/video/tda7432.c | 92 +- drivers/media/video/tda9840.c | 305 +- drivers/media/video/tda9875.c | 43 +- drivers/media/video/tda9887.c | 121 +- drivers/media/video/tea6415c.c | 227 +- drivers/media/video/tea6420.c | 171 +- drivers/media/video/tuner.c | 246 +- drivers/media/video/tvaudio.c | 112 +- drivers/media/video/tvmixer.c | 20 +- drivers/media/video/v4l1-compat.c | 38 +- drivers/media/video/v4l2-common.c | 16 +- drivers/media/video/video-buf.c | 178 +- drivers/media/video/videocodec.c | 5 - drivers/media/video/videodev.c | 2 +- drivers/media/video/zoran.h | 6 +- drivers/media/video/zoran_device.c | 3 +- drivers/media/video/zoran_driver.c | 46 +- drivers/media/video/zr36120.c | 15 +- drivers/message/fusion/Kconfig | 35 +- drivers/message/fusion/Makefile | 3 +- drivers/message/fusion/mptbase.c | 1255 +- drivers/message/fusion/mptbase.h | 356 +- drivers/message/fusion/mptctl.c | 177 +- drivers/message/fusion/mptlan.c | 154 +- drivers/message/fusion/mptscsih.c | 2606 +-- drivers/message/fusion/mptscsih.h | 11 +- drivers/message/i2o/Makefile | 1 + drivers/message/i2o/debug.c | 292 +- drivers/message/i2o/device.c | 54 +- drivers/message/i2o/driver.c | 37 +- drivers/message/i2o/exec-osm.c | 71 +- drivers/message/i2o/i2o_block.c | 2329 ++- drivers/message/i2o/i2o_config.c | 1438 +- drivers/message/i2o/i2o_proc.c | 4039 ++--- drivers/message/i2o/i2o_scsi.c | 1414 +- drivers/message/i2o/iop.c | 111 +- drivers/message/i2o/pci.c | 19 +- drivers/misc/ibmasm/ibmasm.h | 2 +- drivers/misc/ibmasm/ibmasmfs.c | 17 +- drivers/misc/ibmasm/lowlevel.c | 2 +- drivers/misc/ibmasm/lowlevel.h | 30 +- drivers/misc/ibmasm/module.c | 20 +- drivers/misc/ibmasm/uart.c | 2 +- drivers/mmc/Kconfig | 11 + drivers/mmc/Makefile | 1 + drivers/mmc/mmc_block.c | 3 + drivers/mmc/mmc_queue.c | 24 +- drivers/mmc/mmc_queue.h | 1 + drivers/mmc/mmci.c | 14 +- drivers/mmc/mmci.h | 10 +- drivers/mmc/pxamci.c | 112 +- drivers/mmc/pxamci.h | 30 + drivers/mtd/chips/cfi_cmdset_0001.c | 489 +- drivers/mtd/chips/cfi_cmdset_0002.c | 506 +- drivers/mtd/chips/cfi_cmdset_0020.c | 4 +- drivers/mtd/chips/cfi_probe.c | 46 +- drivers/mtd/chips/cfi_util.c | 102 +- drivers/mtd/chips/chipreg.c | 4 +- drivers/mtd/chips/gen_probe.c | 12 +- drivers/mtd/chips/jedec_probe.c | 184 +- drivers/mtd/chips/map_absent.c | 4 +- drivers/mtd/chips/map_ram.c | 4 +- drivers/mtd/chips/map_rom.c | 8 +- drivers/mtd/cmdlinepart.c | 4 +- drivers/mtd/devices/Kconfig | 6 +- drivers/mtd/devices/blkmtd.c | 12 +- drivers/mtd/devices/doc2000.c | 44 +- drivers/mtd/devices/doc2001.c | 28 +- drivers/mtd/devices/doc2001plus.c | 40 +- drivers/mtd/devices/docprobe.c | 6 +- drivers/mtd/devices/mtdram.c | 8 +- drivers/mtd/devices/phram.c | 14 +- drivers/mtd/devices/pmc551.c | 4 +- drivers/mtd/devices/slram.c | 32 +- drivers/mtd/ftl.c | 16 +- drivers/mtd/inftlcore.c | 10 +- drivers/mtd/inftlmount.c | 8 +- drivers/mtd/maps/Kconfig | 69 +- drivers/mtd/maps/Makefile | 7 +- drivers/mtd/maps/amd76xrom.c | 385 +- drivers/mtd/maps/arctic-mtd.c | 4 +- drivers/mtd/maps/autcpu12-nvram.c | 6 +- drivers/mtd/maps/beech-mtd.c | 4 +- drivers/mtd/maps/cdb89712.c | 8 +- drivers/mtd/maps/ceiva.c | 4 +- drivers/mtd/maps/cfi_flagadm.c | 4 +- drivers/mtd/maps/cstm_mips_ixx.c | 4 +- drivers/mtd/maps/db1550-flash.c | 13 +- drivers/mtd/maps/db1x00-flash.c | 21 +- drivers/mtd/maps/dbox2-flash.c | 4 +- drivers/mtd/maps/dc21285.c | 54 +- drivers/mtd/maps/dilnetpc.c | 12 +- drivers/mtd/maps/dmv182.c | 5 +- drivers/mtd/maps/ebony.c | 27 +- drivers/mtd/maps/edb7312.c | 5 +- drivers/mtd/maps/elan-104nc.c | 10 +- drivers/mtd/maps/epxa10db-flash.c | 4 +- drivers/mtd/maps/fortunet.c | 6 +- drivers/mtd/maps/h720x-flash.c | 4 +- drivers/mtd/maps/ichxrom.c | 496 +- drivers/mtd/maps/impa7.c | 5 +- drivers/mtd/maps/integrator-flash.c | 8 +- drivers/mtd/maps/iq80310.c | 4 +- drivers/mtd/maps/ixp2000.c | 53 +- drivers/mtd/maps/ixp4xx.c | 31 +- drivers/mtd/maps/l440gx.c | 14 +- drivers/mtd/maps/lasat.c | 4 +- drivers/mtd/maps/lubbock-flash.c | 10 +- drivers/mtd/maps/mbx860.c | 4 +- drivers/mtd/maps/mpc1211.c | 4 +- drivers/mtd/maps/netsc520.c | 10 +- drivers/mtd/maps/nettel.c | 11 +- drivers/mtd/maps/ocelot.c | 6 +- drivers/mtd/maps/omap-toto-flash.c | 4 +- drivers/mtd/maps/pb1550-flash.c | 5 +- drivers/mtd/maps/pb1xxx-flash.c | 5 +- drivers/mtd/maps/pci.c | 6 +- drivers/mtd/maps/physmap.c | 10 +- drivers/mtd/maps/pnc2000.c | 8 +- drivers/mtd/maps/redwood.c | 5 +- drivers/mtd/maps/rpxlite.c | 4 +- drivers/mtd/maps/sa1100-flash.c | 1512 +- drivers/mtd/maps/sbc_gxx.c | 12 +- drivers/mtd/maps/sc520cdp.c | 16 +- drivers/mtd/maps/scb2_flash.c | 8 +- drivers/mtd/maps/scx200_docflash.c | 10 +- drivers/mtd/maps/solutionengine.c | 6 +- drivers/mtd/maps/sun_uflash.c | 5 +- drivers/mtd/maps/tqm8xxl.c | 10 +- drivers/mtd/maps/uclinux.c | 5 +- drivers/mtd/maps/wr_sbc82xx_flash.c | 4 +- drivers/mtd/mtd_blkdevs.c | 12 +- drivers/mtd/mtdblock.c | 6 +- drivers/mtd/mtdblock_ro.c | 4 +- drivers/mtd/mtdchar.c | 12 +- drivers/mtd/mtdcore.c | 4 +- drivers/mtd/mtdpart.c | 4 +- drivers/mtd/nand/Kconfig | 49 +- drivers/mtd/nand/Makefile | 5 +- drivers/mtd/nand/au1550nd.c | 423 +- drivers/mtd/nand/autcpu12.c | 16 +- drivers/mtd/nand/diskonchip.c | 260 +- drivers/mtd/nand/edb7312.c | 37 +- drivers/mtd/nand/nand_base.c | 147 +- drivers/mtd/nand/nand_bbt.c | 5 +- drivers/mtd/nand/ppchameleonevb.c | 60 +- drivers/mtd/nand/spia.c | 31 +- drivers/mtd/nand/toto.c | 24 +- drivers/mtd/nand/tx4925ndfmc.c | 30 +- drivers/mtd/nand/tx4938ndfmc.c | 22 +- drivers/mtd/nftlcore.c | 10 +- drivers/mtd/nftlmount.c | 13 +- drivers/net/3c501.c | 2 +- drivers/net/3c505.c | 2 +- drivers/net/3c507.c | 4 +- drivers/net/3c509.c | 153 +- drivers/net/3c515.c | 2 +- drivers/net/3c523.c | 2 +- drivers/net/3c527.c | 15 +- drivers/net/3c59x.c | 107 +- drivers/net/7990.c | 164 +- drivers/net/7990.h | 12 +- drivers/net/8139cp.c | 16 +- drivers/net/8139too.c | 84 +- drivers/net/82596.c | 4 +- drivers/net/8390.c | 50 +- drivers/net/8390.h | 12 +- drivers/net/Kconfig | 213 +- drivers/net/Makefile | 6 + drivers/net/Space.c | 3 - drivers/net/a2065.c | 2 +- drivers/net/acenic.c | 311 +- drivers/net/acenic.h | 25 +- drivers/net/acenic_firmware.h | 2 +- drivers/net/amd8111e.c | 504 +- drivers/net/amd8111e.h | 6 +- drivers/net/appletalk/cops.c | 2 +- drivers/net/appletalk/ltpc.c | 2 +- drivers/net/arcnet/arc-rimi.c | 12 +- drivers/net/arcnet/arcnet.c | 3 +- drivers/net/arcnet/com90xx.c | 4 +- drivers/net/ariadne.c | 2 +- drivers/net/arm/am79c961a.c | 15 +- drivers/net/arm/ether1.c | 2 +- drivers/net/arm/ether3.c | 2 +- drivers/net/arm/etherh.c | 167 +- drivers/net/at1700.c | 2 +- drivers/net/atari_bionet.c | 2 +- drivers/net/atari_pamsnet.c | 2 +- drivers/net/atarilance.c | 4 +- drivers/net/atp.c | 2 +- drivers/net/au1000_eth.c | 2 +- drivers/net/b44.c | 335 +- drivers/net/b44.h | 119 +- drivers/net/bagetlance.c | 2 +- drivers/net/bonding/bond_alb.c | 2 +- drivers/net/bonding/bond_main.c | 18 +- drivers/net/bonding/bonding.h | 4 +- drivers/net/bsd_comp.c | 4 +- drivers/net/cs89x0.c | 31 +- drivers/net/cs89x0.h | 19 +- drivers/net/declance.c | 9 - drivers/net/defxx.c | 168 +- drivers/net/defxx.h | 2 +- drivers/net/depca.c | 12 +- drivers/net/dgrs.c | 6 +- drivers/net/dl2k.c | 267 +- drivers/net/dl2k.h | 4 +- drivers/net/dummy.c | 4 +- drivers/net/e100.c | 156 +- drivers/net/e1000/e1000.h | 27 +- drivers/net/e1000/e1000_ethtool.c | 159 +- drivers/net/e1000/e1000_hw.c | 144 +- drivers/net/e1000/e1000_hw.h | 5 +- drivers/net/e1000/e1000_main.c | 559 +- drivers/net/e1000/e1000_osdep.h | 6 + drivers/net/e1000/e1000_param.c | 213 +- drivers/net/eepro.c | 2 +- drivers/net/eepro100.c | 163 +- drivers/net/eexpress.c | 2 +- drivers/net/epic100.c | 434 +- drivers/net/eql.c | 26 +- drivers/net/eth16i.c | 2 +- drivers/net/ethertap.c | 2 +- drivers/net/ewrk3.c | 326 +- drivers/net/fealnx.c | 2 +- drivers/net/fec.c | 501 +- drivers/net/fec.h | 6 +- drivers/net/fec_8xx/fec_8xx-netta.c | 2 +- drivers/net/fec_8xx/fec_main.c | 2 +- drivers/net/fec_8xx/fec_mii.c | 2 +- drivers/net/fmv18x.c | 2 +- drivers/net/forcedeth.c | 267 +- drivers/net/gianfar.c | 584 +- drivers/net/gianfar.h | 46 +- drivers/net/gianfar_ethtool.c | 221 +- drivers/net/gianfar_phy.c | 899 +- drivers/net/gianfar_phy.h | 295 +- drivers/net/gt96100eth.c | 121 +- drivers/net/hamachi.c | 166 +- drivers/net/hamradio/6pack.c | 32 +- drivers/net/hamradio/baycom_par.c | 2 +- drivers/net/hamradio/bpqether.c | 2 +- drivers/net/hamradio/dmascc.c | 291 +- drivers/net/hamradio/hdlcdrv.c | 2 +- drivers/net/hamradio/mkiss.c | 10 +- drivers/net/hamradio/scc.c | 2 +- drivers/net/hamradio/yam.c | 2 +- drivers/net/hp100.c | 27 +- drivers/net/hplance.c | 185 +- drivers/net/hplance.h | 15 +- drivers/net/hydra.c | 2 +- drivers/net/ibm_emac/ibm_emac.h | 32 +- drivers/net/ibm_emac/ibm_emac_core.c | 97 +- drivers/net/ibm_emac/ibm_emac_core.h | 2 +- drivers/net/ibm_emac/ibm_emac_mal.c | 4 - drivers/net/ibm_emac/ibm_emac_mal.h | 1 + drivers/net/ibmlana.c | 11 +- drivers/net/ibmveth.c | 33 +- drivers/net/ibmveth.h | 2 + drivers/net/ioc3-eth.c | 4 +- drivers/net/irda/au1k_ir.c | 2 +- drivers/net/irda/irda-usb.c | 23 +- drivers/net/irda/irport.c | 2 +- drivers/net/irda/irtty-sir.c | 9 +- drivers/net/irda/nsc-ircc.c | 5 +- drivers/net/irda/sa1100_ir.c | 129 +- drivers/net/irda/stir4200.c | 48 +- drivers/net/irda/via-ircc.c | 536 +- drivers/net/irda/via-ircc.h | 19 +- drivers/net/irda/vlsi_ir.c | 4 +- drivers/net/irda/vlsi_ir.h | 1 - drivers/net/isa-skeleton.c | 2 +- drivers/net/iseries_veth.c | 87 +- drivers/net/ixgb/ixgb.h | 3 +- drivers/net/ixgb/ixgb_ethtool.c | 500 +- drivers/net/ixgb/ixgb_hw.h | 2 +- drivers/net/ixgb/ixgb_main.c | 171 +- drivers/net/jazzsonic.c | 2 +- drivers/net/lance.c | 2 +- drivers/net/lasi_82596.c | 6 +- drivers/net/loopback.c | 13 + drivers/net/lp486e.c | 2 +- drivers/net/mac8390.c | 6 +- drivers/net/mac89x0.c | 4 +- drivers/net/macsonic.c | 2 +- drivers/net/meth.c | 26 - drivers/net/mv643xx_eth.c | 2 +- drivers/net/mvme147.c | 22 +- drivers/net/myri_sbus.c | 71 +- drivers/net/myri_sbus.h | 17 +- drivers/net/natsemi.c | 555 +- drivers/net/ne.c | 30 +- drivers/net/ne2.c | 2 +- drivers/net/ne2k-pci.c | 31 + drivers/net/net_init.c | 341 - drivers/net/ni5010.c | 2 +- drivers/net/ni52.c | 2 +- drivers/net/ni65.c | 2 +- drivers/net/ns83820.c | 190 +- drivers/net/pci-skeleton.c | 7 +- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/axnet_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/smc91c92_cs.c | 181 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/net/pcnet32.c | 22 +- drivers/net/plip.c | 4 +- drivers/net/ppp_async.c | 39 +- drivers/net/ppp_deflate.c | 4 +- drivers/net/ppp_generic.c | 27 +- drivers/net/ppp_synctty.c | 19 +- drivers/net/pppoe.c | 4 +- drivers/net/r8169.c | 670 +- drivers/net/rrunner.c | 118 +- drivers/net/rrunner.h | 6 +- drivers/net/s2io.c | 28 +- drivers/net/s2io.h | 1 - drivers/net/sb1000.c | 2 +- drivers/net/sb1250-mac.c | 2 +- drivers/net/seeq8005.c | 2 +- drivers/net/sgiseeq.c | 2 +- drivers/net/sis900.c | 285 +- drivers/net/sk98lin/h/skdrv1st.h | 4 +- drivers/net/sk98lin/h/skdrv2nd.h | 58 +- drivers/net/sk98lin/skaddr.c | 4 +- drivers/net/sk98lin/skge.c | 750 +- drivers/net/sk_g16.c | 2 +- drivers/net/sk_mca.c | 11 +- drivers/net/skfp/hwmtm.c | 3 +- drivers/net/skfp/skfddi.c | 22 +- drivers/net/slip.c | 71 +- drivers/net/smc9194.c | 257 +- drivers/net/smc91x.c | 510 +- drivers/net/smc91x.h | 134 +- drivers/net/starfire.c | 211 +- drivers/net/sun3_82586.c | 2 +- drivers/net/sun3lance.c | 2 +- drivers/net/sunbmac.c | 42 +- drivers/net/sunbmac.h | 8 +- drivers/net/sundance.c | 191 +- drivers/net/sungem.c | 254 +- drivers/net/sungem.h | 7 +- drivers/net/sunhme.c | 89 +- drivers/net/sunhme.h | 14 +- drivers/net/sunlance.c | 66 +- drivers/net/sunqe.c | 16 +- drivers/net/sunqe.h | 6 +- drivers/net/tc35815.c | 2 +- drivers/net/tg3.c | 1046 +- drivers/net/tg3.h | 19 +- drivers/net/tokenring/3c359.c | 2 +- drivers/net/tokenring/Kconfig | 3 +- drivers/net/tokenring/abyss.c | 9 +- drivers/net/tokenring/ibmtr.c | 2 +- drivers/net/tokenring/lanstreamer.c | 4 +- drivers/net/tokenring/olympic.c | 120 +- drivers/net/tokenring/olympic.h | 4 +- drivers/net/tokenring/smctr.c | 2 +- drivers/net/tokenring/tms380tr.c | 2 +- drivers/net/tokenring/tmspci.c | 9 +- drivers/net/tulip/21142.c | 62 +- drivers/net/tulip/Kconfig | 4 +- drivers/net/tulip/de2104x.c | 11 +- drivers/net/tulip/de4x5.c | 20 +- drivers/net/tulip/dmfe.c | 33 +- drivers/net/tulip/eeprom.c | 25 +- drivers/net/tulip/interrupt.c | 76 +- drivers/net/tulip/media.c | 117 +- drivers/net/tulip/pnic.c | 53 +- drivers/net/tulip/pnic2.c | 48 +- drivers/net/tulip/timer.c | 17 +- drivers/net/tulip/tulip.h | 46 +- drivers/net/tulip/tulip_core.c | 255 +- drivers/net/tulip/winbond-840.c | 256 +- drivers/net/tulip/xircom_cb.c | 18 +- drivers/net/tulip/xircom_tulip_cb.c | 207 +- drivers/net/typhoon.c | 322 +- drivers/net/via-rhine.c | 745 +- drivers/net/via-velocity.c | 702 +- drivers/net/via-velocity.h | 32 +- drivers/net/wan/c101.c | 2 +- drivers/net/wan/cosa.c | 2 +- drivers/net/wan/cycx_drv.c | 37 +- drivers/net/wan/cycx_main.c | 5 +- drivers/net/wan/cycx_x25.c | 18 +- drivers/net/wan/dlci.c | 2 +- drivers/net/wan/dscc4.c | 102 +- drivers/net/wan/farsync.c | 50 +- drivers/net/wan/hd6457x.c | 28 +- drivers/net/wan/hdlc_x25.c | 14 +- drivers/net/wan/lapbether.c | 20 +- drivers/net/wan/lmc/lmc_debug.c | 2 +- drivers/net/wan/lmc/lmc_main.c | 11 +- drivers/net/wan/lmc/lmc_media.c | 2 +- drivers/net/wan/lmc/lmc_proto.c | 2 +- drivers/net/wan/n2.c | 2 +- drivers/net/wan/pc300.h | 26 +- drivers/net/wan/pc300_drv.c | 206 +- drivers/net/wan/pc300_tty.c | 112 +- drivers/net/wan/pci200syn.c | 10 +- drivers/net/wan/sbni.c | 6 +- drivers/net/wan/sdla.c | 2 +- drivers/net/wan/sdla_chdlc.c | 83 +- drivers/net/wan/sdla_fr.c | 4 +- drivers/net/wan/sdladrv.c | 6 +- drivers/net/wan/sdlamain.c | 2 +- drivers/net/wan/syncppp.c | 8 +- drivers/net/wan/wanxl.c | 8 +- drivers/net/wan/x25_asy.c | 24 +- drivers/net/wireless/airo.c | 194 +- drivers/net/wireless/airport.c | 52 +- drivers/net/wireless/arlan.h | 2 +- drivers/net/wireless/atmel.c | 9 +- drivers/net/wireless/atmel_cs.c | 5 +- drivers/net/wireless/hermes.c | 12 +- drivers/net/wireless/hermes.h | 133 +- drivers/net/wireless/hermes_rid.h | 99 +- drivers/net/wireless/ieee802_11.h | 1 - drivers/net/wireless/netwave_cs.c | 14 +- drivers/net/wireless/orinoco.c | 2805 ++-- drivers/net/wireless/orinoco.h | 36 +- drivers/net/wireless/orinoco_cs.c | 70 +- drivers/net/wireless/orinoco_pci.c | 52 +- drivers/net/wireless/orinoco_plx.c | 204 +- drivers/net/wireless/orinoco_tmd.c | 56 +- drivers/net/wireless/prism54/isl_38xx.c | 27 +- drivers/net/wireless/prism54/isl_38xx.h | 18 +- drivers/net/wireless/prism54/isl_ioctl.c | 644 +- drivers/net/wireless/prism54/isl_ioctl.h | 2 + drivers/net/wireless/prism54/isl_oid.h | 9 + drivers/net/wireless/prism54/islpci_dev.c | 57 +- drivers/net/wireless/prism54/islpci_dev.h | 7 +- drivers/net/wireless/prism54/islpci_eth.c | 5 +- drivers/net/wireless/prism54/islpci_hotplug.c | 7 +- drivers/net/wireless/prism54/islpci_mgt.c | 5 +- drivers/net/wireless/prism54/islpci_mgt.h | 2 - drivers/net/wireless/prism54/oid_mgt.c | 126 +- drivers/net/wireless/prism54/oid_mgt.h | 5 +- drivers/net/wireless/ray_cs.c | 157 +- drivers/net/wireless/ray_cs.h | 6 +- drivers/net/wireless/strip.c | 31 +- drivers/net/wireless/wavelan.c | 30 +- drivers/net/wireless/wavelan.p.h | 5 +- drivers/net/wireless/wavelan_cs.c | 181 +- drivers/net/wireless/wavelan_cs.p.h | 5 +- drivers/net/wireless/wl3501_cs.c | 53 +- drivers/net/yellowfin.c | 257 +- drivers/net/znet.c | 4 +- drivers/oprofile/buffer_sync.c | 279 +- drivers/oprofile/buffer_sync.h | 3 + drivers/oprofile/cpu_buffer.c | 101 +- drivers/oprofile/cpu_buffer.h | 11 +- drivers/oprofile/oprofile_stats.c | 13 +- drivers/oprofile/oprofilefs.c | 14 +- drivers/oprofile/timer_int.c | 15 +- drivers/parisc/lasi.c | 2 +- drivers/parisc/lba_pci.c | 362 +- drivers/parisc/power.c | 8 +- drivers/parisc/sba_iommu.c | 155 +- drivers/parisc/superio.c | 80 +- drivers/parport/Kconfig | 2 +- drivers/parport/daisy.c | 155 +- drivers/parport/ieee1284.c | 4 +- drivers/parport/parport_pc.c | 311 +- drivers/parport/parport_sunbpp.c | 30 +- drivers/parport/probe.c | 1 - drivers/parport/procfs.c | 3 - drivers/parport/share.c | 1 - drivers/pci/Makefile | 10 +- drivers/pci/bus.c | 31 +- drivers/pci/hotplug/Kconfig | 12 + drivers/pci/hotplug/Makefile | 2 +- drivers/pci/hotplug/acpiphp.h | 16 + drivers/pci/hotplug/acpiphp_core.c | 127 +- drivers/pci/hotplug/acpiphp_glue.c | 18 +- drivers/pci/hotplug/acpiphp_ibm.c | 101 +- drivers/pci/hotplug/cpci_hotplug_core.c | 18 +- drivers/pci/hotplug/cpcihp_generic.c | 14 +- drivers/pci/hotplug/cpcihp_zt5550.c | 19 +- drivers/pci/hotplug/cpqphp.h | 9 +- drivers/pci/hotplug/cpqphp_core.c | 42 +- drivers/pci/hotplug/cpqphp_ctrl.c | 4 +- drivers/pci/hotplug/cpqphp_nvram.c | 14 +- drivers/pci/hotplug/cpqphp_nvram.h | 12 +- drivers/pci/hotplug/cpqphp_pci.c | 14 +- drivers/pci/hotplug/fakephp.c | 128 +- drivers/pci/hotplug/ibmphp.h | 6 - drivers/pci/hotplug/ibmphp_core.c | 14 +- drivers/pci/hotplug/ibmphp_ebda.c | 4 +- drivers/pci/hotplug/ibmphp_hpc.c | 48 +- drivers/pci/hotplug/pci_hotplug_core.c | 4 +- drivers/pci/hotplug/pciehp.h | 35 +- drivers/pci/hotplug/pciehp_core.c | 28 +- drivers/pci/hotplug/pciehp_ctrl.c | 385 +- drivers/pci/hotplug/pciehp_hpc.c | 43 +- drivers/pci/hotplug/pciehp_pci.c | 8 + drivers/pci/hotplug/pciehprm_acpi.c | 43 +- drivers/pci/hotplug/pcihp_skeleton.c | 2 +- drivers/pci/hotplug/rpadlpar_core.c | 170 +- drivers/pci/hotplug/rpaphp.h | 4 +- drivers/pci/hotplug/rpaphp_core.c | 155 +- drivers/pci/hotplug/rpaphp_pci.c | 116 +- drivers/pci/hotplug/rpaphp_slot.c | 23 +- drivers/pci/hotplug/rpaphp_vio.c | 4 +- drivers/pci/hotplug/shpchp.h | 9 +- drivers/pci/hotplug/shpchp_core.c | 10 +- drivers/pci/hotplug/shpchp_ctrl.c | 485 +- drivers/pci/hotplug/shpchp_hpc.c | 17 +- drivers/pci/hotplug/shpchprm_acpi.c | 6 +- drivers/pci/msi.c | 20 +- drivers/pci/msi.h | 2 +- drivers/pci/pci-driver.c | 86 +- drivers/pci/pci-sysfs.c | 130 +- drivers/pci/pci.c | 59 +- drivers/pci/pci.h | 27 +- drivers/pci/pci.ids | 572 +- drivers/pci/probe.c | 80 +- drivers/pci/proc.c | 5 +- drivers/pci/quirks.c | 648 +- drivers/pci/remove.c | 22 +- drivers/pci/search.c | 77 +- drivers/pci/setup-bus.c | 13 +- drivers/pci/setup-irq.c | 2 +- drivers/pci/setup-res.c | 2 +- drivers/pci/syscall.c | 7 +- drivers/pcmcia/Kconfig | 111 +- drivers/pcmcia/Makefile | 28 +- drivers/pcmcia/au1000_generic.c | 15 +- drivers/pcmcia/bulkmem.c | 534 +- drivers/pcmcia/cardbus.c | 2 +- drivers/pcmcia/cistpl.c | 98 +- drivers/pcmcia/cs.c | 205 +- drivers/pcmcia/cs_internal.h | 38 +- drivers/pcmcia/ds.c | 74 +- drivers/pcmcia/hd64465_ss.c | 11 +- drivers/pcmcia/i82092.c | 20 +- drivers/pcmcia/i82365.c | 21 +- drivers/pcmcia/o2micro.h | 19 +- drivers/pcmcia/pd6729.c | 14 +- drivers/pcmcia/pxa2xx_base.c | 40 +- drivers/pcmcia/pxa2xx_lubbock.c | 34 +- drivers/pcmcia/pxa2xx_mainstone.c | 24 + drivers/pcmcia/rsrc_mgr.c | 79 +- drivers/pcmcia/sa1100_generic.c | 21 - drivers/pcmcia/sa1100_h3600.c | 4 +- drivers/pcmcia/sa1100_simpad.c | 4 +- drivers/pcmcia/sa1111_generic.c | 15 - drivers/pcmcia/soc_common.c | 14 +- drivers/pcmcia/tcic.c | 16 +- drivers/pcmcia/yenta_socket.c | 36 +- drivers/pcmcia/yenta_socket.h | 4 +- drivers/pnp/Kconfig | 4 +- drivers/pnp/Makefile | 1 + drivers/pnp/interface.c | 16 +- drivers/pnp/isapnp/Kconfig | 2 +- drivers/pnp/isapnp/core.c | 8 +- drivers/pnp/manager.c | 10 +- drivers/pnp/pnpbios/Kconfig | 3 +- drivers/pnp/pnpbios/bioscalls.c | 16 +- drivers/pnp/pnpbios/core.c | 20 +- drivers/pnp/pnpbios/proc.c | 8 +- drivers/pnp/pnpbios/rsparser.c | 16 +- drivers/pnp/quirks.c | 7 +- drivers/pnp/resource.c | 9 +- drivers/pnp/system.c | 6 +- drivers/s390/Kconfig | 19 + drivers/s390/block/dasd.c | 23 +- drivers/s390/block/dasd_3990_erp.c | 19 +- drivers/s390/block/dasd_devmap.c | 185 +- drivers/s390/block/dasd_diag.c | 18 +- drivers/s390/block/dasd_eckd.c | 81 +- drivers/s390/block/dasd_fba.c | 59 +- drivers/s390/block/dasd_int.h | 6 +- drivers/s390/block/dcssblk.c | 224 +- drivers/s390/block/xpram.c | 3 +- drivers/s390/char/Makefile | 4 + drivers/s390/char/con3215.c | 35 +- drivers/s390/char/con3270.c | 9 +- drivers/s390/char/raw3270.c | 38 +- drivers/s390/char/sclp.c | 43 +- drivers/s390/char/sclp_tty.c | 35 +- drivers/s390/char/sclp_vt220.c | 33 +- drivers/s390/char/tape_block.c | 4 +- drivers/s390/char/tty3270.c | 35 +- drivers/s390/cio/blacklist.c | 4 +- drivers/s390/cio/ccwgroup.c | 16 +- drivers/s390/cio/cio.c | 15 +- drivers/s390/cio/cmf.c | 95 +- drivers/s390/cio/css.c | 11 +- drivers/s390/cio/css.h | 4 + drivers/s390/cio/device.c | 127 +- drivers/s390/cio/device_fsm.c | 38 +- drivers/s390/cio/device_id.c | 4 +- drivers/s390/cio/qdio.c | 24 +- drivers/s390/crypto/Makefile | 2 +- drivers/s390/crypto/z90common.h | 75 +- drivers/s390/crypto/z90crypt.h | 81 +- drivers/s390/crypto/z90hardware.c | 289 +- drivers/s390/crypto/z90main.c | 668 +- drivers/s390/net/ctcdbug.h | 6 +- drivers/s390/net/ctcmain.c | 24 +- drivers/s390/net/ctctty.c | 24 +- drivers/s390/net/iucv.c | 8 +- drivers/s390/net/iucv.h | 7 +- drivers/s390/net/lcs.c | 458 +- drivers/s390/net/lcs.h | 18 +- drivers/s390/net/netiucv.c | 2 +- drivers/s390/net/qeth.h | 74 +- drivers/s390/net/qeth_main.c | 912 +- drivers/s390/net/qeth_mpc.h | 39 +- drivers/s390/net/qeth_sys.c | 137 +- drivers/s390/s390mach.h | 4 - drivers/s390/scsi/zfcp_aux.c | 636 +- drivers/s390/scsi/zfcp_ccw.c | 5 +- drivers/s390/scsi/zfcp_def.h | 309 +- drivers/s390/scsi/zfcp_erp.c | 702 +- drivers/s390/scsi/zfcp_ext.h | 39 +- drivers/s390/scsi/zfcp_fsf.c | 730 +- drivers/s390/scsi/zfcp_fsf.h | 28 +- drivers/s390/scsi/zfcp_qdio.c | 3 +- drivers/s390/scsi/zfcp_scsi.c | 116 +- drivers/s390/scsi/zfcp_sysfs_adapter.c | 46 +- drivers/s390/scsi/zfcp_sysfs_driver.c | 7 +- drivers/s390/scsi/zfcp_sysfs_port.c | 42 +- drivers/s390/scsi/zfcp_sysfs_unit.c | 40 +- drivers/sbus/char/aurora.c | 80 +- drivers/sbus/char/bbc_envctrl.c | 5 +- drivers/sbus/char/bbc_i2c.c | 8 +- drivers/sbus/char/bpp.c | 16 +- drivers/sbus/char/cpwatchdog.c | 90 +- drivers/sbus/char/display7seg.c | 6 +- drivers/sbus/char/envctrl.c | 65 +- drivers/sbus/char/flash.c | 7 +- drivers/sbus/char/jsflash.c | 2 +- drivers/sbus/char/riowatchdog.c | 6 +- drivers/sbus/dvma.c | 11 - drivers/scsi/3w-9xxx.c | 1 + drivers/scsi/3w-9xxx.h | 10 +- drivers/scsi/3w-xxxx.c | 4333 ++--- drivers/scsi/3w-xxxx.h | 151 +- drivers/scsi/53c700.c | 88 +- drivers/scsi/53c700.h | 11 +- drivers/scsi/BusLogic.c | 6459 ++++---- drivers/scsi/BusLogic.h | 1498 +- drivers/scsi/Kconfig | 84 +- drivers/scsi/Makefile | 8 +- drivers/scsi/NCR5380.c | 285 +- drivers/scsi/NCR5380.h | 3 +- drivers/scsi/NCR53C9x.c | 16 +- drivers/scsi/NCR53c406a.c | 13 +- drivers/scsi/NCR_D700.c | 25 +- drivers/scsi/NCR_Q720.c | 39 +- drivers/scsi/aacraid/README | 14 +- drivers/scsi/aacraid/aachba.c | 563 +- drivers/scsi/aacraid/aacraid.h | 200 +- drivers/scsi/aacraid/commctrl.c | 2 +- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/linit.c | 251 +- drivers/scsi/aacraid/rkt.c | 131 +- drivers/scsi/aacraid/rx.c | 98 +- drivers/scsi/aacraid/sa.c | 66 +- drivers/scsi/advansys.c | 23 +- drivers/scsi/advansys.h | 26 - drivers/scsi/aha152x.c | 9 +- drivers/scsi/aha1542.c | 10 +- drivers/scsi/aha1542.h | 10 +- drivers/scsi/ahci.c | 21 +- drivers/scsi/aic7xxx/Kconfig.aic79xx | 2 +- drivers/scsi/aic7xxx/Kconfig.aic7xxx | 2 +- drivers/scsi/aic7xxx/aic7770_osm.c | 4 +- drivers/scsi/aic7xxx/aic79xx.h | 8 +- drivers/scsi/aic7xxx/aic79xx.reg | 2 +- drivers/scsi/aic7xxx/aic79xx_core.c | 15 +- drivers/scsi/aic7xxx/aic79xx_inline.h | 10 +- drivers/scsi/aic7xxx/aic79xx_osm.c | 155 +- drivers/scsi/aic7xxx/aic79xx_osm.h | 84 +- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 159 +- drivers/scsi/aic7xxx/aic79xx_pci.c | 61 +- drivers/scsi/aic7xxx/aic7xxx.h | 12 +- drivers/scsi/aic7xxx/aic7xxx_core.c | 9 +- drivers/scsi/aic7xxx/aic7xxx_osm.c | 122 +- drivers/scsi/aic7xxx/aic7xxx_osm.h | 83 +- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 124 +- drivers/scsi/aic7xxx/aic7xxx_pci.c | 87 +- drivers/scsi/aic7xxx/aicasm/Makefile | 6 +- drivers/scsi/aic7xxx/aiclib.h | 39 + drivers/scsi/aic7xxx/cam.h | 6 - drivers/scsi/aic7xxx_old.c | 29 +- drivers/scsi/arm/acornscsi.c | 2 +- drivers/scsi/arm/arxescsi.c | 19 +- drivers/scsi/arm/cumana_1.c | 1 + drivers/scsi/arm/cumana_2.c | 19 +- drivers/scsi/arm/ecoscsi.c | 1 + drivers/scsi/arm/eesox.c | 49 +- drivers/scsi/arm/fas216.c | 6 +- drivers/scsi/arm/oak.c | 1 + drivers/scsi/arm/powertec.c | 19 +- drivers/scsi/ata_piix.c | 214 +- drivers/scsi/atari_scsi.c | 2 +- drivers/scsi/atp870u.c | 8 +- drivers/scsi/cpqfcTScontrol.c | 1 - drivers/scsi/cpqfcTSinit.c | 53 +- drivers/scsi/dc395x.c | 109 +- drivers/scsi/dec_esp.c | 2 +- drivers/scsi/dmx3191d.c | 215 +- drivers/scsi/dpt_i2o.c | 52 +- drivers/scsi/dpti.h | 20 +- drivers/scsi/dtc.c | 50 +- drivers/scsi/dtc.h | 34 +- drivers/scsi/eata.c | 240 +- drivers/scsi/eata_pio.c | 5 +- drivers/scsi/esp.h | 4 +- drivers/scsi/fd_mcs.c | 11 +- drivers/scsi/fdomain.c | 233 +- drivers/scsi/g_NCR5380.c | 6 +- drivers/scsi/gdth.c | 120 +- drivers/scsi/gdth.h | 2 +- drivers/scsi/hosts.c | 36 +- drivers/scsi/ibmvscsi/rpa_vscsi.c | 2 +- drivers/scsi/ide-scsi.c | 175 +- drivers/scsi/imm.c | 6 +- drivers/scsi/ipr.c | 280 +- drivers/scsi/ipr.h | 46 +- drivers/scsi/ips.c | 168 +- drivers/scsi/ips.h | 63 +- drivers/scsi/jazz_esp.c | 2 +- drivers/scsi/lasi700.c | 20 +- drivers/scsi/libata-core.c | 1543 +- drivers/scsi/libata-scsi.c | 516 +- drivers/scsi/libata.h | 10 +- drivers/scsi/mac53c94.c | 24 +- drivers/scsi/mac_esp.c | 2 +- drivers/scsi/mac_scsi.c | 1 + drivers/scsi/mca_53c9x.c | 16 +- drivers/scsi/megaraid.c | 38 +- drivers/scsi/megaraid/megaraid_ioctl.h | 8 +- drivers/scsi/megaraid/megaraid_mbox.c | 26 +- drivers/scsi/megaraid/megaraid_mbox.h | 6 +- drivers/scsi/megaraid/megaraid_mm.c | 102 +- drivers/scsi/megaraid/megaraid_mm.h | 5 +- drivers/scsi/mesh.c | 122 +- drivers/scsi/ncr53c8xx.c | 1356 +- drivers/scsi/ncr53c8xx.h | 10 +- drivers/scsi/nsp32.c | 137 +- drivers/scsi/nsp32.h | 9 +- drivers/scsi/osst.c | 80 +- drivers/scsi/osst.h | 4 +- drivers/scsi/pas16.c | 5 +- drivers/scsi/pcmcia/aha152x_stub.c | 2 +- drivers/scsi/pcmcia/nsp_cs.c | 6 +- drivers/scsi/pcmcia/qlogic_stub.c | 2 +- drivers/scsi/pcmcia/sym53c500_cs.c | 9 +- drivers/scsi/psi240i.c | 37 - drivers/scsi/ql12160_fw.h | 22 +- drivers/scsi/ql1280_fw.h | 22 +- drivers/scsi/qla1280.c | 1131 +- drivers/scsi/qla1280.h | 61 +- drivers/scsi/qla2xxx/ql2100.c | 1 + drivers/scsi/qla2xxx/ql2200.c | 1 + drivers/scsi/qla2xxx/ql2300.c | 1 + drivers/scsi/qla2xxx/ql2300_fw.c | 13378 ++++++++-------- drivers/scsi/qla2xxx/ql2322.c | 1 + drivers/scsi/qla2xxx/ql2322_fw.c | 12001 +++++++------- drivers/scsi/qla2xxx/ql6312.c | 1 + drivers/scsi/qla2xxx/ql6312_fw.c | 12741 +++++++-------- drivers/scsi/qla2xxx/ql6322.c | 1 + drivers/scsi/qla2xxx/ql6322_fw.c | 11193 ++++++------- drivers/scsi/qla2xxx/qla_dbg.c | 94 +- drivers/scsi/qla2xxx/qla_def.h | 37 +- drivers/scsi/qla2xxx/qla_gbl.h | 3 +- drivers/scsi/qla2xxx/qla_init.c | 240 +- drivers/scsi/qla2xxx/qla_inline.h | 15 +- drivers/scsi/qla2xxx/qla_iocb.c | 21 +- drivers/scsi/qla2xxx/qla_isr.c | 283 +- drivers/scsi/qla2xxx/qla_mbx.c | 41 +- drivers/scsi/qla2xxx/qla_os.c | 467 +- drivers/scsi/qla2xxx/qla_rscn.c | 57 +- drivers/scsi/qla2xxx/qla_sup.c | 22 +- drivers/scsi/qla2xxx/qla_version.h | 4 +- drivers/scsi/qlogicfc.c | 8 +- drivers/scsi/qlogicfc_asm.c | 10 +- drivers/scsi/qlogicisp.c | 17 +- drivers/scsi/qlogicpti.c | 2 +- drivers/scsi/qlogicpti.h | 4 +- drivers/scsi/sata_nv.c | 147 +- drivers/scsi/sata_promise.c | 148 +- drivers/scsi/sata_sil.c | 31 +- drivers/scsi/sata_sis.c | 70 +- drivers/scsi/sata_svw.c | 85 +- drivers/scsi/sata_sx4.c | 190 +- drivers/scsi/sata_uli.c | 8 +- drivers/scsi/sata_via.c | 57 +- drivers/scsi/sata_vsc.c | 24 +- drivers/scsi/scsi.c | 58 +- drivers/scsi/scsi_debug.c | 125 +- drivers/scsi/scsi_devinfo.c | 26 +- drivers/scsi/scsi_error.c | 139 +- drivers/scsi/scsi_ioctl.c | 72 +- drivers/scsi/scsi_lib.c | 252 +- drivers/scsi/scsi_module.c | 1 - drivers/scsi/scsi_priv.h | 23 +- drivers/scsi/scsi_scan.c | 339 +- drivers/scsi/scsi_syms.c | 4 +- drivers/scsi/scsi_sysfs.c | 200 +- drivers/scsi/scsi_transport_fc.c | 474 +- drivers/scsi/scsi_transport_spi.c | 268 +- drivers/scsi/scsicam.c | 9 +- drivers/scsi/sd.c | 203 +- drivers/scsi/seagate.c | 86 +- drivers/scsi/sg.c | 78 +- drivers/scsi/sim710.c | 19 +- drivers/scsi/sr.c | 21 +- drivers/scsi/sr_ioctl.c | 15 +- drivers/scsi/st.c | 459 +- drivers/scsi/st.h | 30 +- drivers/scsi/sun3_scsi.c | 10 +- drivers/scsi/sun3_scsi_vme.c | 10 +- drivers/scsi/sun3x_esp.c | 2 +- drivers/scsi/sym53c416.c | 8 +- drivers/scsi/sym53c8xx_2/sym53c8xx.h | 82 +- drivers/scsi/sym53c8xx_2/sym_conf.h | 35 +- drivers/scsi/sym53c8xx_2/sym_defs.h | 138 +- drivers/scsi/sym53c8xx_2/sym_fw.c | 37 +- drivers/scsi/sym53c8xx_2/sym_fw.h | 35 +- drivers/scsi/sym53c8xx_2/sym_fw1.h | 35 +- drivers/scsi/sym53c8xx_2/sym_fw2.h | 35 +- drivers/scsi/sym53c8xx_2/sym_glue.c | 814 +- drivers/scsi/sym53c8xx_2/sym_glue.h | 84 +- drivers/scsi/sym53c8xx_2/sym_hipd.c | 278 +- drivers/scsi/sym53c8xx_2/sym_hipd.h | 81 +- drivers/scsi/sym53c8xx_2/sym_malloc.c | 35 +- drivers/scsi/sym53c8xx_2/sym_misc.c | 157 +- drivers/scsi/sym53c8xx_2/sym_misc.h | 35 +- drivers/scsi/sym53c8xx_2/sym_nvram.c | 51 +- drivers/scsi/sym53c8xx_2/sym_nvram.h | 35 +- drivers/scsi/sym53c8xx_comm.h | 358 +- drivers/scsi/sym53c8xx_defs.h | 39 +- drivers/scsi/t128.c | 72 +- drivers/scsi/t128.h | 14 +- drivers/scsi/tmscsim.c | 3189 ++-- drivers/scsi/tmscsim.h | 103 +- drivers/scsi/u14-34f.c | 70 +- drivers/scsi/ultrastor.c | 2 +- drivers/scsi/wd33c93.c | 2 +- drivers/scsi/wd7000.c | 60 +- drivers/scsi/zalon.c | 7 +- drivers/serial/21285.c | 33 +- drivers/serial/68328serial.c | 37 +- drivers/serial/68360serial.c | 40 +- drivers/serial/8250.c | 1084 +- drivers/serial/8250.h | 30 +- drivers/serial/8250_acorn.c | 60 +- drivers/serial/8250_acpi.c | 74 +- drivers/serial/8250_gsc.c | 47 +- drivers/serial/8250_pci.c | 162 +- drivers/serial/8250_pnp.c | 35 +- drivers/serial/Kconfig | 69 +- drivers/serial/Makefile | 6 + drivers/serial/amba-pl010.c | 66 +- drivers/serial/amba-pl011.c | 52 +- drivers/serial/au1x00_uart.c | 15 - drivers/serial/bast_sio.c | 31 +- drivers/serial/clps711x.c | 28 +- drivers/serial/cpm_uart/cpm_uart.h | 9 +- drivers/serial/cpm_uart/cpm_uart_core.c | 15 + drivers/serial/cpm_uart/cpm_uart_cpm1.c | 23 +- drivers/serial/dz.c | 27 +- drivers/serial/icom.c | 8 +- drivers/serial/mcfserial.c | 48 +- drivers/serial/pmac_zilog.c | 82 +- drivers/serial/pmac_zilog.h | 9 +- drivers/serial/pxa.c | 48 +- drivers/serial/s3c2410.c | 1464 +- drivers/serial/sa1100.c | 27 +- drivers/serial/serial_core.c | 167 +- drivers/serial/serial_cs.c | 74 +- drivers/serial/serial_lh7a40x.c | 59 +- drivers/serial/sh-sci.c | 72 +- drivers/serial/sh-sci.h | 76 +- drivers/serial/sn_console.c | 353 +- drivers/serial/sunsab.c | 44 +- drivers/serial/sunsu.c | 106 +- drivers/serial/sunzilog.c | 153 +- drivers/serial/uart00.c | 27 +- drivers/tc/zs.c | 59 +- drivers/telephony/ixj.c | 53 +- drivers/telephony/ixj.h | 4 +- drivers/telephony/ixj_pcmcia.c | 2 +- drivers/usb/Kconfig | 4 +- drivers/usb/Makefile | 6 +- drivers/usb/atm/speedtch.c | 3 + drivers/usb/atm/usb_atm.c | 30 +- drivers/usb/atm/usb_atm.h | 1 - drivers/usb/class/Kconfig | 3 +- drivers/usb/class/audio.c | 55 +- drivers/usb/class/bluetty.c | 44 +- drivers/usb/class/cdc-acm.c | 84 +- drivers/usb/class/cdc-acm.h | 3 +- drivers/usb/class/usb-midi.c | 39 +- drivers/usb/class/usblp.c | 34 +- drivers/usb/core/Kconfig | 37 + drivers/usb/core/config.c | 7 +- drivers/usb/core/devices.c | 21 +- drivers/usb/core/devio.c | 78 +- drivers/usb/core/hcd-pci.c | 161 +- drivers/usb/core/hcd.c | 181 +- drivers/usb/core/hcd.h | 20 +- drivers/usb/core/hub.c | 1122 +- drivers/usb/core/hub.h | 14 +- drivers/usb/core/inode.c | 143 +- drivers/usb/core/message.c | 159 +- drivers/usb/core/sysfs.c | 64 +- drivers/usb/core/urb.c | 27 +- drivers/usb/core/usb.c | 274 +- drivers/usb/core/usb.h | 26 +- drivers/usb/gadget/Kconfig | 58 +- drivers/usb/gadget/Makefile | 4 +- drivers/usb/gadget/dummy_hcd.c | 458 +- drivers/usb/gadget/ether.c | 148 +- drivers/usb/gadget/file_storage.c | 244 +- drivers/usb/gadget/gadget_chips.h | 18 + drivers/usb/gadget/goku_udc.c | 165 +- drivers/usb/gadget/goku_udc.h | 8 +- drivers/usb/gadget/inode.c | 151 +- drivers/usb/gadget/lh7a40x_udc.c | 7 +- drivers/usb/gadget/net2280.c | 134 +- drivers/usb/gadget/net2280.h | 31 +- drivers/usb/gadget/omap_udc.c | 469 +- drivers/usb/gadget/omap_udc.h | 17 +- drivers/usb/gadget/pxa2xx_udc.c | 24 +- drivers/usb/gadget/rndis.c | 57 +- drivers/usb/gadget/serial.c | 1139 +- drivers/usb/gadget/zero.c | 19 +- drivers/usb/host/Kconfig | 41 +- drivers/usb/host/Makefile | 4 +- drivers/usb/host/ehci-dbg.c | 60 +- drivers/usb/host/ehci-hcd.c | 285 +- drivers/usb/host/ehci-hub.c | 89 +- drivers/usb/host/ehci-mem.c | 13 +- drivers/usb/host/ehci-q.c | 156 +- drivers/usb/host/ehci-sched.c | 45 +- drivers/usb/host/ehci.h | 88 +- drivers/usb/host/ohci-dbg.c | 136 +- drivers/usb/host/ohci-hcd.c | 350 +- drivers/usb/host/ohci-hub.c | 306 +- drivers/usb/host/ohci-lh7a404.c | 40 +- drivers/usb/host/ohci-mem.c | 9 +- drivers/usb/host/ohci-omap.c | 585 +- drivers/usb/host/ohci-pci.c | 65 +- drivers/usb/host/ohci-q.c | 161 +- drivers/usb/host/ohci-sa1111.c | 35 +- drivers/usb/host/ohci.h | 289 +- drivers/usb/host/uhci-debug.c | 11 - drivers/usb/host/uhci-hcd.c | 337 +- drivers/usb/host/uhci-hcd.h | 34 +- drivers/usb/host/uhci-hub.c | 148 +- drivers/usb/image/Kconfig | 7 +- drivers/usb/image/hpusbscsi.c | 12 +- drivers/usb/image/mdc800.c | 18 +- drivers/usb/image/microtek.c | 21 +- drivers/usb/image/microtek.h | 1 + drivers/usb/input/Kconfig | 14 +- drivers/usb/input/aiptek.c | 24 +- drivers/usb/input/ati_remote.c | 16 +- drivers/usb/input/hid-core.c | 187 +- drivers/usb/input/hiddev.c | 35 +- drivers/usb/input/kbtab.c | 15 +- drivers/usb/input/mtouchusb.c | 4 +- drivers/usb/input/pid.c | 2 +- drivers/usb/input/powermate.c | 4 +- drivers/usb/input/touchkitusb.c | 23 +- drivers/usb/input/usbkbd.c | 4 +- drivers/usb/input/usbmouse.c | 4 +- drivers/usb/input/wacom.c | 18 +- drivers/usb/input/xpad.c | 4 +- drivers/usb/media/Kconfig | 48 +- drivers/usb/media/Makefile | 4 +- drivers/usb/media/dabusb.c | 11 +- drivers/usb/media/dsbr100.c | 2 +- drivers/usb/media/ibmcam.c | 30 +- drivers/usb/media/konicawc.c | 29 +- drivers/usb/media/ov511.c | 97 +- drivers/usb/media/se401.c | 28 +- drivers/usb/media/sn9c102.h | 31 +- drivers/usb/media/sn9c102_core.c | 554 +- drivers/usb/media/sn9c102_pas106b.c | 157 +- drivers/usb/media/sn9c102_pas202bcb.c | 110 +- drivers/usb/media/sn9c102_sensor.h | 197 +- drivers/usb/media/sn9c102_tas5110c1b.c | 74 +- drivers/usb/media/sn9c102_tas5130d1b.c | 106 +- drivers/usb/media/stv680.c | 35 +- drivers/usb/media/ultracam.c | 16 +- drivers/usb/media/usbvideo.c | 104 +- drivers/usb/media/vicam.c | 14 +- drivers/usb/media/w9968cf.c | 69 +- drivers/usb/media/w9968cf.h | 2 +- drivers/usb/misc/Kconfig | 14 +- drivers/usb/misc/Makefile | 4 +- drivers/usb/misc/auerswald.c | 26 +- drivers/usb/misc/legousbtower.c | 69 +- drivers/usb/misc/phidgetservo.c | 16 +- drivers/usb/misc/rio500.c | 14 +- drivers/usb/misc/tiglusb.c | 62 +- drivers/usb/misc/tiglusb.h | 8 +- drivers/usb/misc/usbtest.c | 37 +- drivers/usb/misc/uss720.c | 4 +- drivers/usb/net/Kconfig | 33 +- drivers/usb/net/catc.c | 136 +- drivers/usb/net/kaweth.c | 192 +- drivers/usb/net/pegasus.c | 333 +- drivers/usb/net/rtl8150.c | 200 +- drivers/usb/net/usbnet.c | 124 +- drivers/usb/serial/Kconfig | 25 + drivers/usb/serial/Makefile | 2 + drivers/usb/serial/belkin_sa.c | 9 +- drivers/usb/serial/bus.c | 1 + drivers/usb/serial/console.c | 4 +- drivers/usb/serial/cyberjack.c | 54 +- drivers/usb/serial/digi_acceleport.c | 44 +- drivers/usb/serial/empeg.c | 24 +- drivers/usb/serial/ftdi_sio.c | 174 +- drivers/usb/serial/ftdi_sio.h | 32 + drivers/usb/serial/generic.c | 14 +- drivers/usb/serial/io_edgeport.c | 317 +- drivers/usb/serial/io_edgeport.h | 4 +- drivers/usb/serial/io_fw_boot.h | 6 +- drivers/usb/serial/io_fw_boot2.h | 6 +- drivers/usb/serial/io_fw_down.h | 1974 +-- drivers/usb/serial/io_fw_down2.h | 6 +- drivers/usb/serial/io_fw_down3.h | 1532 +- drivers/usb/serial/io_tables.h | 76 +- drivers/usb/serial/io_ti.c | 846 +- drivers/usb/serial/io_usbvend.h | 379 +- drivers/usb/serial/ipaq.c | 523 +- drivers/usb/serial/ipaq.h | 74 - drivers/usb/serial/ir-usb.c | 17 +- drivers/usb/serial/keyspan.c | 11 +- drivers/usb/serial/keyspan.h | 1 - drivers/usb/serial/keyspan_pda.c | 27 +- drivers/usb/serial/kl5kusb105.c | 27 +- drivers/usb/serial/kobil_sct.c | 26 +- drivers/usb/serial/mct_u232.c | 26 +- drivers/usb/serial/omninet.c | 19 +- drivers/usb/serial/pl2303.c | 426 +- drivers/usb/serial/pl2303.h | 11 +- drivers/usb/serial/safe_serial.c | 9 +- drivers/usb/serial/usb-serial.c | 426 +- drivers/usb/serial/usb-serial.h | 21 +- drivers/usb/serial/visor.c | 103 +- drivers/usb/serial/whiteheat.c | 24 +- drivers/usb/storage/Kconfig | 15 +- drivers/usb/storage/datafab.c | 25 +- drivers/usb/storage/datafab.h | 2 +- drivers/usb/storage/debug.c | 8 +- drivers/usb/storage/debug.h | 6 +- drivers/usb/storage/dpcm.c | 6 +- drivers/usb/storage/dpcm.h | 2 +- drivers/usb/storage/freecom.c | 26 +- drivers/usb/storage/freecom.h | 2 +- drivers/usb/storage/isd200.c | 100 +- drivers/usb/storage/isd200.h | 2 +- drivers/usb/storage/jumpshot.c | 24 +- drivers/usb/storage/jumpshot.h | 2 +- drivers/usb/storage/protocol.c | 74 +- drivers/usb/storage/protocol.h | 20 +- drivers/usb/storage/scsiglue.c | 144 +- drivers/usb/storage/scsiglue.h | 8 +- drivers/usb/storage/sddr09.c | 27 +- drivers/usb/storage/sddr09.h | 2 +- drivers/usb/storage/sddr55.c | 48 +- drivers/usb/storage/sddr55.h | 2 +- drivers/usb/storage/shuttle_usbat.c | 42 +- drivers/usb/storage/shuttle_usbat.h | 2 +- drivers/usb/storage/transport.c | 69 +- drivers/usb/storage/transport.h | 19 +- drivers/usb/storage/unusual_devs.h | 200 +- drivers/usb/storage/usb.c | 122 +- drivers/usb/storage/usb.h | 24 +- drivers/usb/usb-skeleton.c | 622 +- drivers/video/68328fb.c | 25 +- drivers/video/Kconfig | 146 +- drivers/video/Makefile | 127 +- drivers/video/acornfb.c | 31 +- drivers/video/amifb.c | 63 +- drivers/video/asiliantfb.c | 10 +- drivers/video/aty/Makefile | 4 +- drivers/video/aty/ati_ids.h | 1 + drivers/video/aty/aty128fb.c | 55 +- drivers/video/aty/atyfb.h | 209 +- drivers/video/aty/atyfb_base.c | 3613 +++-- drivers/video/aty/mach64_accel.c | 212 +- drivers/video/aty/mach64_ct.c | 733 +- drivers/video/aty/mach64_cursor.c | 297 +- drivers/video/aty/mach64_gx.c | 20 +- drivers/video/aty/radeon_base.c | 510 +- drivers/video/aty/radeon_monitor.c | 72 +- drivers/video/aty/radeon_pm.c | 10 +- drivers/video/aty/radeonfb.h | 10 +- drivers/video/aty/xlinit.c | 68 +- drivers/video/bw2.c | 38 +- drivers/video/cfbcopyarea.c | 13 +- drivers/video/cfbfillrect.c | 16 +- drivers/video/cfbimgblt.c | 32 +- drivers/video/cg14.c | 68 +- drivers/video/cg3.c | 48 +- drivers/video/cg6.c | 65 +- drivers/video/chipsfb.c | 9 +- drivers/video/cirrusfb.c | 60 +- drivers/video/clps711xfb.c | 7 +- drivers/video/console/Kconfig | 7 +- drivers/video/console/Makefile | 3 +- drivers/video/console/fbcon.c | 1513 +- drivers/video/console/fbcon.h | 52 +- drivers/video/console/font_6x11.c | 2252 +-- drivers/video/console/vgacon.c | 4 +- drivers/video/controlfb.c | 28 +- drivers/video/cyber2000fb.c | 32 +- drivers/video/cyber2000fb.h | 4 +- drivers/video/dnfb.c | 8 + drivers/video/epson1355fb.c | 1015 +- drivers/video/fbmem.c | 899 +- drivers/video/fbmon.c | 113 +- drivers/video/fbsysfs.c | 2 + drivers/video/ffb.c | 166 +- drivers/video/fm2fb.c | 20 +- drivers/video/g364fb.c | 6 +- drivers/video/gbefb.c | 22 +- drivers/video/hgafb.c | 61 +- drivers/video/hitfb.c | 8 +- drivers/video/hpfb.c | 402 +- drivers/video/i810/i810.h | 7 +- drivers/video/i810/i810_accel.c | 14 +- drivers/video/i810/i810_dvt.c | 14 +- drivers/video/i810/i810_gtf.c | 3 +- drivers/video/i810/i810_main.c | 345 +- drivers/video/igafb.c | 11 +- drivers/video/imsttfb.c | 38 +- drivers/video/kyro/STG4000InitDevice.c | 4 +- drivers/video/kyro/STG4000Interface.h | 26 +- drivers/video/kyro/STG4000OverlayDevice.c | 10 +- drivers/video/kyro/STG4000Ramdac.c | 8 +- drivers/video/kyro/STG4000Reg.h | 4 +- drivers/video/kyro/STG4000VTG.c | 8 +- drivers/video/kyro/fbdev.c | 15 +- drivers/video/leo.c | 52 +- drivers/video/macfb.c | 11 +- drivers/video/matrox/matroxfb_accel.c | 22 +- drivers/video/matrox/matroxfb_base.c | 57 +- drivers/video/matrox/matroxfb_base.h | 150 +- drivers/video/matrox/matroxfb_crtc2.c | 10 +- drivers/video/matrox/matroxfb_crtc2.h | 3 +- drivers/video/matrox/matroxfb_misc.c | 12 +- drivers/video/maxinefb.c | 7 +- drivers/video/modedb.c | 308 +- drivers/video/neofb.c | 544 +- drivers/video/offb.c | 111 +- drivers/video/p9100.c | 33 +- drivers/video/platinumfb.c | 39 +- drivers/video/pm2fb.c | 69 +- drivers/video/pmag-ba-fb.c | 6 +- drivers/video/pmagb-b-fb.c | 6 +- drivers/video/pvr2fb.c | 12 +- drivers/video/pxafb.c | 74 +- drivers/video/q40fb.c | 6 +- drivers/video/radeonfb.c | 72 +- drivers/video/riva/fbdev.c | 885 +- drivers/video/riva/nv_driver.c | 163 +- drivers/video/riva/riva_hw.c | 581 +- drivers/video/riva/riva_hw.h | 87 +- drivers/video/riva/rivafb-i2c.c | 36 +- drivers/video/riva/rivafb.h | 10 +- drivers/video/sa1100fb.c | 325 +- drivers/video/sbuslib.c | 2 +- drivers/video/sgivwfb.c | 139 +- drivers/video/sis/sis.h | 14 +- drivers/video/sis/sis_main.c | 63 +- drivers/video/sis/sis_main.h | 2 +- drivers/video/skeletonfb.c | 35 +- drivers/video/softcursor.c | 75 +- drivers/video/sstfb.c | 47 +- drivers/video/stifb.c | 39 +- drivers/video/tcx.c | 50 +- drivers/video/tdfxfb.c | 175 +- drivers/video/tgafb.c | 70 +- drivers/video/tridentfb.c | 45 +- drivers/video/tx3912fb.c | 13 +- drivers/video/valkyriefb.c | 56 +- drivers/video/vesafb.c | 140 +- drivers/video/vfb.c | 13 +- drivers/video/vga16fb.c | 49 +- drivers/video/vgastate.c | 12 +- drivers/w1/Kconfig | 26 + drivers/w1/Makefile | 11 + drivers/w1/dscore.c | 53 +- drivers/w1/dscore.h | 34 +- drivers/w1/matrox_w1.c | 15 +- drivers/w1/w1.c | 299 +- drivers/w1/w1.h | 21 + drivers/w1/w1_family.c | 21 +- drivers/w1/w1_family.h | 2 +- drivers/w1/w1_int.c | 43 +- drivers/w1/w1_int.h | 2 +- drivers/w1/w1_io.c | 69 +- drivers/w1/w1_io.h | 3 + drivers/w1/w1_netlink.c | 11 + drivers/w1/w1_netlink.h | 15 +- drivers/w1/w1_therm.c | 118 +- drivers/zorro/Makefile | 2 +- drivers/zorro/zorro.c | 2 +- fs/Kconfig | 90 +- fs/Makefile | 15 +- fs/adfs/adfs.h | 11 +- fs/adfs/dir.c | 3 +- fs/adfs/dir_f.c | 16 +- fs/adfs/dir_fplus.h | 28 +- fs/adfs/inode.c | 11 +- fs/adfs/map.c | 10 +- fs/adfs/super.c | 12 +- fs/affs/amigaffs.c | 26 +- fs/affs/bitmap.c | 44 +- fs/affs/inode.c | 11 +- fs/affs/namei.c | 2 +- fs/affs/super.c | 8 +- fs/afs/cmservice.c | 2 +- fs/afs/dir.c | 16 +- fs/afs/fsclient.c | 6 +- fs/afs/inode.c | 5 +- fs/afs/main.c | 9 +- fs/afs/mntpt.c | 16 +- fs/afs/vlclient.c | 17 +- fs/afs/vlclient.h | 3 - fs/afs/vlocation.c | 3 +- fs/afs/vnode.c | 6 +- fs/afs/volume.h | 1 - fs/aio.c | 672 +- fs/autofs/inode.c | 2 +- fs/autofs/root.c | 10 +- fs/autofs4/autofs_i.h | 1 - fs/autofs4/expire.c | 8 +- fs/autofs4/inode.c | 2 +- fs/autofs4/root.c | 24 +- fs/befs/befs.h | 1 - fs/befs/debug.c | 2 + fs/befs/linuxvfs.c | 18 +- fs/bfs/inode.c | 9 +- fs/binfmt_aout.c | 31 +- fs/binfmt_elf.c | 200 +- fs/binfmt_flat.c | 2 +- fs/bio.c | 152 +- fs/block_dev.c | 25 +- fs/buffer.c | 198 +- fs/char_dev.c | 54 +- fs/cifs/AUTHORS | 5 +- fs/cifs/CHANGES | 58 +- fs/cifs/Makefile | 2 +- fs/cifs/README | 82 +- fs/cifs/TODO | 34 +- fs/cifs/asn1.c | 27 +- fs/cifs/cifs_debug.c | 33 +- fs/cifs/cifs_fs_sb.h | 6 +- fs/cifs/cifsencrypt.c | 14 +- fs/cifs/cifsfs.c | 151 +- fs/cifs/cifsfs.h | 9 +- fs/cifs/cifsglob.h | 47 +- fs/cifs/cifspdu.h | 1162 +- fs/cifs/cifsproto.h | 17 +- fs/cifs/cifssmb.c | 1798 ++- fs/cifs/connect.c | 613 +- fs/cifs/dir.c | 3 - fs/cifs/fcntl.c | 54 +- fs/cifs/file.c | 464 +- fs/cifs/inode.c | 81 +- fs/cifs/link.c | 50 +- fs/cifs/misc.c | 104 +- fs/cifs/netmisc.c | 22 +- fs/cifs/ntlmssp.h | 26 +- fs/cifs/smberr.h | 1 + fs/cifs/transport.c | 212 +- fs/cifs/xattr.c | 109 +- fs/coda/coda_linux.c | 2 +- fs/coda/file.c | 18 + fs/coda/inode.c | 2 +- fs/coda/psdev.c | 2 +- fs/coda/sysctl.c | 2 +- fs/coda/upcall.c | 10 +- fs/compat.c | 164 +- fs/compat_ioctl.c | 22 +- fs/dcache.c | 139 +- fs/dcookies.c | 1 + fs/devfs/base.c | 3 +- fs/devfs/util.c | 2 +- fs/devpts/Makefile | 1 - fs/devpts/inode.c | 42 +- fs/devpts/xattr_security.c | 29 +- fs/direct-io.c | 120 +- fs/dquot.c | 19 +- fs/efs/inode.c | 4 +- fs/efs/namei.c | 33 + fs/efs/super.c | 23 +- fs/eventpoll.c | 8 +- fs/exec.c | 274 +- fs/exportfs/expfs.c | 22 +- fs/ext2/acl.c | 111 +- fs/ext2/acl.h | 15 +- fs/ext2/balloc.c | 4 +- fs/ext2/dir.c | 14 +- fs/ext2/ext2.h | 8 +- fs/ext2/file.c | 8 +- fs/ext2/ialloc.c | 4 +- fs/ext2/inode.c | 51 +- fs/ext2/namei.c | 19 +- fs/ext2/super.c | 151 +- fs/ext2/symlink.c | 16 +- fs/ext2/xattr.c | 276 +- fs/ext2/xattr.h | 48 +- fs/ext2/xattr_security.c | 11 +- fs/ext2/xattr_trusted.c | 11 +- fs/ext2/xattr_user.c | 27 +- fs/ext3/Makefile | 2 +- fs/ext3/acl.c | 111 +- fs/ext3/acl.h | 12 +- fs/ext3/balloc.c | 824 +- fs/ext3/file.c | 14 +- fs/ext3/fsync.c | 4 - fs/ext3/ialloc.c | 20 +- fs/ext3/inode.c | 201 +- fs/ext3/ioctl.c | 69 + fs/ext3/namei.c | 55 +- fs/ext3/resize.c | 180 +- fs/ext3/super.c | 238 +- fs/ext3/symlink.c | 16 +- fs/ext3/xattr.c | 271 +- fs/ext3/xattr.h | 48 +- fs/ext3/xattr_security.c | 14 +- fs/ext3/xattr_trusted.c | 13 +- fs/ext3/xattr_user.c | 13 +- fs/fat/cache.c | 380 +- fs/fat/dir.c | 187 +- fs/fat/fatfs_syms.c | 18 +- fs/fat/file.c | 6 - fs/fat/inode.c | 203 +- fs/fat/misc.c | 18 +- fs/fcntl.c | 39 +- fs/file.c | 7 +- fs/file_table.c | 53 +- fs/filesystems.c | 1 + fs/freevxfs/vxfs_extern.h | 2 +- fs/freevxfs/vxfs_inode.c | 11 +- fs/freevxfs/vxfs_super.c | 2 +- fs/fs-writeback.c | 53 +- fs/hfs/Makefile | 2 +- fs/hfs/bfind.c | 3 +- fs/hfs/bitmap.c | 35 +- fs/hfs/bnode.c | 10 +- fs/hfs/brec.c | 8 +- fs/hfs/btree.c | 10 +- fs/hfs/btree.h | 28 +- fs/hfs/catalog.c | 2 +- fs/hfs/dir.c | 3 + fs/hfs/extent.c | 16 +- fs/hfs/hfs.h | 134 +- fs/hfs/hfs_fs.h | 23 +- fs/hfs/inode.c | 65 +- fs/hfs/mdb.c | 12 +- fs/hfs/part_tbl.c | 20 +- fs/hfs/super.c | 10 +- fs/hfsplus/bfind.c | 3 +- fs/hfsplus/bitmap.c | 33 +- fs/hfsplus/bnode.c | 12 +- fs/hfsplus/brec.c | 8 +- fs/hfsplus/btree.c | 10 +- fs/hfsplus/catalog.c | 8 +- fs/hfsplus/extents.c | 14 +- fs/hfsplus/hfsplus_fs.h | 9 +- fs/hfsplus/hfsplus_raw.h | 172 +- fs/hfsplus/inode.c | 46 +- fs/hfsplus/ioctl.c | 106 + fs/hfsplus/part_tbl.c | 20 +- fs/hfsplus/super.c | 15 +- fs/hfsplus/wrapper.c | 10 +- fs/hostfs/Makefile | 4 +- fs/hostfs/hostfs.h | 22 +- fs/hostfs/hostfs_kern.c | 126 +- fs/hostfs/hostfs_user.c | 62 +- fs/hpfs/super.c | 2 +- fs/hppfs/Makefile | 4 +- fs/hppfs/hppfs_kern.c | 92 +- fs/hugetlbfs/inode.c | 55 +- fs/inode.c | 78 +- fs/ioctl.c | 1 + fs/isofs/compress.c | 4 +- fs/isofs/inode.c | 3 +- fs/isofs/rock.c | 18 +- fs/jbd/checkpoint.c | 1 - fs/jbd/commit.c | 76 +- fs/jbd/journal.c | 63 +- fs/jbd/recovery.c | 32 +- fs/jbd/revoke.c | 13 +- fs/jbd/transaction.c | 47 +- fs/jffs2/compr.c | 9 +- fs/jffs2/dir.c | 3 +- fs/jffs2/erase.c | 2 +- fs/jffs2/gc.c | 19 +- fs/jffs2/nodelist.c | 11 +- fs/jffs2/nodelist.h | 15 +- fs/jffs2/nodemgmt.c | 55 +- fs/jffs2/readinode.c | 4 +- fs/jffs2/scan.c | 8 +- fs/jffs2/super.c | 18 +- fs/jffs2/wbuf.c | 8 +- fs/jffs2/write.c | 6 +- fs/jfs/acl.c | 94 +- fs/jfs/inode.c | 22 +- fs/jfs/jfs_dinode.h | 28 +- fs/jfs/jfs_dmap.c | 10 +- fs/jfs/jfs_dmap.h | 75 +- fs/jfs/jfs_dtree.c | 91 +- fs/jfs/jfs_dtree.h | 18 +- fs/jfs/jfs_extent.c | 26 +- fs/jfs/jfs_imap.c | 92 +- fs/jfs/jfs_imap.h | 74 +- fs/jfs/jfs_incore.h | 2 +- fs/jfs/jfs_inode.c | 14 +- fs/jfs/jfs_logmgr.c | 10 +- fs/jfs/jfs_logmgr.h | 96 +- fs/jfs/jfs_metapage.c | 11 +- fs/jfs/jfs_mount.c | 5 +- fs/jfs/jfs_superblock.h | 32 +- fs/jfs/jfs_txnmgr.c | 7 +- fs/jfs/jfs_types.h | 16 +- fs/jfs/jfs_unicode.c | 2 +- fs/jfs/jfs_unicode.h | 32 +- fs/jfs/jfs_xattr.h | 4 +- fs/jfs/jfs_xtree.c | 123 +- fs/jfs/jfs_xtree.h | 14 +- fs/jfs/namei.c | 39 +- fs/jfs/resize.c | 5 +- fs/jfs/super.c | 8 +- fs/jfs/xattr.c | 51 +- fs/libfs.c | 79 +- fs/lockd/Makefile | 2 +- fs/lockd/clntlock.c | 4 +- fs/lockd/clntproc.c | 176 +- fs/lockd/host.c | 24 +- fs/lockd/mon.c | 4 +- fs/lockd/svc.c | 13 +- fs/lockd/svc4proc.c | 11 +- fs/lockd/svclock.c | 66 +- fs/lockd/svcproc.c | 11 +- fs/lockd/svcsubs.c | 10 +- fs/lockd/xdr.c | 49 +- fs/lockd/xdr4.c | 10 +- fs/locks.c | 401 +- fs/mbcache.c | 33 - fs/minix/bitmap.c | 25 +- fs/minix/inode.c | 7 +- fs/minix/itree_common.c | 2 +- fs/mpage.c | 33 +- fs/msdos/namei.c | 4 +- fs/namei.c | 109 +- fs/namespace.c | 40 +- fs/ncpfs/dir.c | 30 +- fs/ncpfs/file.c | 21 +- fs/ncpfs/inode.c | 35 +- fs/ncpfs/ioctl.c | 4 +- fs/ncpfs/mmap.c | 10 +- fs/ncpfs/ncplib_kernel.c | 192 +- fs/ncpfs/ncplib_kernel.h | 42 +- fs/ncpfs/sock.c | 2 +- fs/ncpfs/symlink.c | 15 +- fs/nfs/Makefile | 3 +- fs/nfs/dir.c | 146 +- fs/nfs/direct.c | 49 +- fs/nfs/file.c | 147 +- fs/nfs/inode.c | 382 +- fs/nfs/mount_clnt.c | 2 - fs/nfs/nfs2xdr.c | 70 +- fs/nfs/nfs3proc.c | 111 +- fs/nfs/nfs3xdr.c | 48 +- fs/nfs/nfs4proc.c | 1272 +- fs/nfs/nfs4state.c | 371 +- fs/nfs/nfs4xdr.c | 563 +- fs/nfs/pagelist.c | 62 +- fs/nfs/proc.c | 63 +- fs/nfs/read.c | 62 +- fs/nfs/symlink.c | 75 +- fs/nfs/write.c | 170 +- fs/nfsctl.c | 1 + fs/nfsd/Makefile | 3 +- fs/nfsd/export.c | 5 + fs/nfsd/lockd.c | 11 +- fs/nfsd/nfs3proc.c | 12 +- fs/nfsd/nfs3xdr.c | 10 +- fs/nfsd/nfs4proc.c | 70 +- fs/nfsd/nfs4state.c | 433 +- fs/nfsd/nfs4xdr.c | 164 +- fs/nfsd/nfsctl.c | 96 +- fs/nfsd/nfsfh.c | 91 +- fs/nfsd/nfsproc.c | 5 +- fs/nfsd/nfssvc.c | 3 +- fs/nfsd/vfs.c | 285 +- fs/nls/nls_cp932.c | 43 +- fs/ntfs/ChangeLog | 337 +- fs/ntfs/Makefile | 8 +- fs/ntfs/aops.c | 1319 +- fs/ntfs/attrib.c | 1846 +-- fs/ntfs/attrib.h | 62 +- fs/ntfs/bitmap.c | 1 + fs/ntfs/collate.c | 23 +- fs/ntfs/collate.h | 12 +- fs/ntfs/compress.c | 44 +- fs/ntfs/debug.c | 30 +- fs/ntfs/debug.h | 8 +- fs/ntfs/dir.c | 257 +- fs/ntfs/dir.h | 2 + fs/ntfs/endian.h | 72 +- fs/ntfs/file.c | 106 +- fs/ntfs/index.c | 117 +- fs/ntfs/index.h | 8 +- fs/ntfs/inode.c | 902 +- fs/ntfs/inode.h | 44 +- fs/ntfs/layout.h | 844 +- fs/ntfs/lcnalloc.c | 11 +- fs/ntfs/lcnalloc.h | 29 + fs/ntfs/logfile.c | 73 +- fs/ntfs/logfile.h | 76 +- fs/ntfs/malloc.h | 1 + fs/ntfs/mft.c | 2601 ++- fs/ntfs/mft.h | 15 +- fs/ntfs/mst.c | 23 +- fs/ntfs/namei.c | 73 +- fs/ntfs/ntfs.h | 82 +- fs/ntfs/quota.c | 10 +- fs/ntfs/super.c | 435 +- fs/ntfs/time.h | 6 +- fs/ntfs/types.h | 42 +- fs/ntfs/unistr.c | 14 +- fs/ntfs/upcase.c | 4 +- fs/ntfs/volume.h | 22 +- fs/open.c | 3 +- fs/openpromfs/inode.c | 48 +- fs/partitions/Kconfig | 33 +- fs/partitions/acorn.c | 42 +- fs/partitions/amiga.c | 42 +- fs/partitions/atari.h | 4 +- fs/partitions/check.c | 21 +- fs/partitions/devfs.c | 2 +- fs/partitions/efi.c | 258 +- fs/partitions/efi.h | 36 +- fs/partitions/ldm.c | 16 +- fs/partitions/ldm.h | 6 +- fs/partitions/mac.h | 36 +- fs/partitions/msdos.c | 4 + fs/partitions/osf.c | 46 +- fs/partitions/sgi.c | 32 +- fs/partitions/sun.c | 33 +- fs/pipe.c | 4 +- fs/posix_acl.c | 42 - fs/proc/array.c | 142 +- fs/proc/base.c | 163 +- fs/proc/generic.c | 2 +- fs/proc/inode.c | 2 +- fs/proc/proc_misc.c | 84 +- fs/proc/proc_tty.c | 14 +- fs/proc/root.c | 10 +- fs/proc/task_mmu.c | 61 +- fs/proc/task_nommu.c | 8 +- fs/qnx4/bitmap.c | 3 +- fs/qnx4/inode.c | 11 +- fs/quota.c | 1 + fs/quota_v1.c | 4 +- fs/quota_v2.c | 10 +- fs/ramfs/inode.c | 8 +- fs/rcfs/dir.c | 45 +- fs/rcfs/inode.c | 44 +- fs/rcfs/magic.c | 131 +- fs/rcfs/rootdir.c | 54 +- fs/rcfs/socket_fs.c | 14 +- fs/rcfs/super.c | 96 +- fs/rcfs/tc_magic.c | 11 +- fs/read_write.c | 2 +- fs/readdir.c | 1 + fs/reiserfs/bitmap.c | 30 +- fs/reiserfs/dir.c | 11 +- fs/reiserfs/do_balan.c | 2 +- fs/reiserfs/file.c | 140 +- fs/reiserfs/fix_node.c | 6 +- fs/reiserfs/ibalance.c | 8 +- fs/reiserfs/inode.c | 203 +- fs/reiserfs/item_ops.c | 10 +- fs/reiserfs/journal.c | 1219 +- fs/reiserfs/namei.c | 161 +- fs/reiserfs/objectid.c | 2 + fs/reiserfs/prints.c | 53 +- fs/reiserfs/procfs.c | 2 +- fs/reiserfs/resize.c | 26 +- fs/reiserfs/stree.c | 85 +- fs/reiserfs/super.c | 202 +- fs/reiserfs/tail_conversion.c | 3 + fs/reiserfs/xattr.c | 21 +- fs/reiserfs/xattr_acl.c | 28 +- fs/reiserfs/xattr_security.c | 10 +- fs/reiserfs/xattr_trusted.c | 10 +- fs/reiserfs/xattr_user.c | 10 +- fs/romfs/inode.c | 33 +- fs/select.c | 22 +- fs/smbfs/inode.c | 25 +- fs/smbfs/proc.c | 48 +- fs/smbfs/proto.h | 2 +- fs/smbfs/request.c | 6 +- fs/stat.c | 1 + fs/super.c | 44 +- fs/sysfs/bin.c | 46 +- fs/sysfs/dir.c | 372 +- fs/sysfs/file.c | 96 +- fs/sysfs/group.c | 8 +- fs/sysfs/inode.c | 97 +- fs/sysfs/mount.c | 12 +- fs/sysfs/symlink.c | 103 +- fs/sysfs/sysfs.h | 75 +- fs/sysv/CHANGES | 2 +- fs/sysv/ChangeLog | 12 +- fs/sysv/balloc.c | 31 +- fs/sysv/ialloc.c | 2 +- fs/sysv/inode.c | 5 +- fs/sysv/itree.c | 36 +- fs/sysv/super.c | 36 +- fs/sysv/sysv.h | 72 +- fs/udf/balloc.c | 24 +- fs/udf/dir.c | 4 +- fs/udf/directory.c | 16 +- fs/udf/ecma_167.h | 294 +- fs/udf/file.c | 22 +- fs/udf/fsync.c | 4 +- fs/udf/inode.c | 114 +- fs/udf/lowlevel.c | 6 - fs/udf/misc.c | 14 +- fs/udf/namei.c | 36 +- fs/udf/osta_udf.h | 86 +- fs/udf/partition.c | 12 +- fs/udf/super.c | 59 +- fs/udf/truncate.c | 14 +- fs/udf/udfdecl.h | 35 +- fs/udf/udfend.h | 22 +- fs/udf/udftime.c | 8 +- fs/ufs/balloc.c | 35 +- fs/ufs/cylinder.c | 2 +- fs/ufs/dir.c | 10 +- fs/ufs/ialloc.c | 2 +- fs/ufs/inode.c | 26 +- fs/ufs/namei.c | 4 +- fs/ufs/super.c | 26 +- fs/ufs/swab.h | 72 +- fs/ufs/truncate.c | 16 +- fs/ufs/util.c | 53 + fs/ufs/util.h | 40 +- fs/umsdos/inode.c | 6 +- fs/vfat/namei.c | 40 +- fs/xattr.c | 131 + fs/xfs/Makefile | 3 +- fs/xfs/linux-2.6/kmem.c | 15 +- fs/xfs/linux-2.6/kmem.h | 2 +- fs/xfs/linux-2.6/xfs_aops.c | 74 +- fs/xfs/linux-2.6/xfs_buf.c | 178 +- fs/xfs/linux-2.6/xfs_buf.h | 41 +- fs/xfs/linux-2.6/xfs_file.c | 50 +- fs/xfs/linux-2.6/xfs_fs_subr.h | 1 - fs/xfs/linux-2.6/xfs_globals.c | 2 + fs/xfs/linux-2.6/xfs_ioctl.c | 135 +- fs/xfs/linux-2.6/xfs_iops.c | 30 +- fs/xfs/linux-2.6/xfs_iops.h | 2 +- fs/xfs/linux-2.6/xfs_linux.h | 3 + fs/xfs/linux-2.6/xfs_lrw.c | 291 +- fs/xfs/linux-2.6/xfs_lrw.h | 6 +- fs/xfs/linux-2.6/xfs_stats.c | 4 +- fs/xfs/linux-2.6/xfs_super.c | 223 +- fs/xfs/linux-2.6/xfs_sysctl.c | 12 +- fs/xfs/linux-2.6/xfs_sysctl.h | 4 + fs/xfs/linux-2.6/xfs_vfs.c | 2 + fs/xfs/linux-2.6/xfs_vfs.h | 21 +- fs/xfs/linux-2.6/xfs_vnode.c | 66 +- fs/xfs/linux-2.6/xfs_vnode.h | 16 +- fs/xfs/quota/xfs_dquot.c | 108 +- fs/xfs/quota/xfs_dquot.h | 2 + fs/xfs/quota/xfs_qm.c | 108 +- fs/xfs/quota/xfs_qm.h | 15 +- fs/xfs/quota/xfs_qm_bhv.c | 20 +- fs/xfs/quota/xfs_qm_stats.c | 4 +- fs/xfs/quota/xfs_qm_syscalls.c | 52 +- fs/xfs/quota/xfs_trans_dquot.c | 41 +- fs/xfs/support/ktrace.c | 9 +- fs/xfs/support/move.c | 8 +- fs/xfs/xfs_acl.h | 4 +- fs/xfs/xfs_alloc.c | 38 +- fs/xfs/xfs_alloc_btree.c | 2 +- fs/xfs/xfs_attr.c | 33 +- fs/xfs/xfs_attr_leaf.h | 1 - fs/xfs/xfs_bmap.c | 75 +- fs/xfs/xfs_bmap.h | 2 +- fs/xfs/xfs_bmap_btree.c | 2 +- fs/xfs/xfs_bmap_btree.h | 11 +- fs/xfs/xfs_buf_item.c | 2 - fs/xfs/xfs_da_btree.c | 2 +- fs/xfs/xfs_dfrag.c | 2 +- fs/xfs/xfs_dfrag.h | 2 +- fs/xfs/xfs_dinode.h | 12 + fs/xfs/xfs_dir2_trace.c | 2 +- fs/xfs/xfs_fs.h | 60 +- fs/xfs/xfs_fsops.c | 20 +- fs/xfs/xfs_iget.c | 54 +- fs/xfs/xfs_inode.c | 63 +- fs/xfs/xfs_inode.h | 7 +- fs/xfs/xfs_iomap.c | 100 +- fs/xfs/xfs_iomap.h | 5 +- fs/xfs/xfs_itable.c | 14 +- fs/xfs/xfs_itable.h | 10 +- fs/xfs/xfs_log.c | 108 +- fs/xfs/xfs_log_priv.h | 6 +- fs/xfs/xfs_log_recover.c | 30 +- fs/xfs/xfs_mount.c | 48 +- fs/xfs/xfs_mount.h | 10 +- fs/xfs/xfs_quota.h | 18 +- fs/xfs/xfs_rtalloc.c | 32 +- fs/xfs/xfs_sb.h | 6 +- fs/xfs/xfs_trans.c | 5 +- fs/xfs/xfs_trans.h | 2 +- fs/xfs/xfs_trans_inode.c | 9 +- fs/xfs/xfs_trans_item.c | 2 +- fs/xfs/xfs_types.h | 2 +- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_vfsops.c | 120 +- fs/xfs/xfs_vnodeops.c | 116 +- include/acpi/acconfig.h | 25 +- include/acpi/acdebug.h | 13 +- include/acpi/acdisasm.h | 15 + include/acpi/acdispat.h | 11 +- include/acpi/acevents.h | 54 +- include/acpi/acexcep.h | 8 +- include/acpi/acglobal.h | 48 +- include/acpi/achware.h | 41 +- include/acpi/acinterp.h | 57 +- include/acpi/aclocal.h | 41 +- include/acpi/acmacros.h | 33 +- include/acpi/acnamesp.h | 28 +- include/acpi/acobject.h | 18 +- include/acpi/acparser.h | 8 +- include/acpi/acpi_bus.h | 32 +- include/acpi/acpi_drivers.h | 58 +- include/acpi/acpiosxf.h | 34 +- include/acpi/acpixf.h | 39 +- include/acpi/acresrc.h | 4 + include/acpi/acstruct.h | 23 +- include/acpi/actables.h | 2 + include/acpi/actbl.h | 31 +- include/acpi/actbl2.h | 90 +- include/acpi/actypes.h | 95 +- include/acpi/acutils.h | 26 +- include/acpi/amlcode.h | 50 +- include/acpi/amlresrc.h | 4 +- include/acpi/platform/acenv.h | 18 +- include/acpi/platform/aclinux.h | 2 - include/acpi/processor.h | 10 +- include/asm-alpha/a.out.h | 2 +- include/asm-alpha/bitops.h | 5 +- include/asm-alpha/bug.h | 12 +- include/asm-alpha/cache.h | 2 +- include/asm-alpha/compiler.h | 16 +- include/asm-alpha/core_apecs.h | 224 +- include/asm-alpha/core_cia.h | 303 +- include/asm-alpha/core_irongate.h | 134 +- include/asm-alpha/core_lca.h | 223 +- include/asm-alpha/core_marvel.h | 243 +- include/asm-alpha/core_mcpcia.h | 267 +- include/asm-alpha/core_polaris.h | 146 +- include/asm-alpha/core_t2.h | 110 +- include/asm-alpha/core_titan.h | 146 +- include/asm-alpha/core_tsunami.h | 149 +- include/asm-alpha/core_wildfire.h | 149 +- include/asm-alpha/dma-mapping.h | 64 +- include/asm-alpha/errno.h | 5 + include/asm-alpha/hardirq.h | 62 - include/asm-alpha/io.h | 697 +- include/asm-alpha/jensen.h | 99 +- include/asm-alpha/machvec.h | 42 +- include/asm-alpha/mmu_context.h | 1 + include/asm-alpha/mmzone.h | 4 +- include/asm-alpha/page.h | 1 + include/asm-alpha/pci.h | 4 +- include/asm-alpha/pgtable.h | 8 +- include/asm-alpha/ptrace.h | 1 + include/asm-alpha/resource.h | 2 +- include/asm-alpha/semaphore.h | 23 +- include/asm-alpha/socket.h | 16 - include/asm-alpha/spinlock.h | 27 +- include/asm-alpha/sysinfo.h | 1 + include/asm-alpha/system.h | 6 +- include/asm-alpha/thread_info.h | 2 +- include/asm-alpha/tlbflush.h | 3 +- include/asm-alpha/topology.h | 3 - include/asm-alpha/uaccess.h | 6 +- include/asm-alpha/unistd.h | 5 +- include/asm-alpha/vga.h | 18 +- include/asm-arm/apm.h | 49 +- include/asm-arm/arch-cl7500/uncompress.h | 2 +- include/asm-arm/arch-clps711x/io.h | 6 +- include/asm-arm/arch-clps711x/time.h | 3 + include/asm-arm/arch-clps711x/uncompress.h | 2 +- include/asm-arm/arch-ebsa110/io.h | 14 +- include/asm-arm/arch-ebsa110/param.h | 2 +- include/asm-arm/arch-ebsa110/uncompress.h | 2 +- include/asm-arm/arch-ebsa285/io.h | 20 +- include/asm-arm/arch-ebsa285/uncompress.h | 2 +- include/asm-arm/arch-epxa10db/io.h | 2 +- include/asm-arm/arch-epxa10db/uncompress.h | 2 +- include/asm-arm/arch-h720x/io.h | 4 +- include/asm-arm/arch-imx/io.h | 4 +- include/asm-arm/arch-integrator/io.h | 6 +- include/asm-arm/arch-integrator/platform.h | 4 - include/asm-arm/arch-integrator/uncompress.h | 2 +- include/asm-arm/arch-iop3xx/dma.h | 103 +- include/asm-arm/arch-iop3xx/hardware.h | 51 +- include/asm-arm/arch-iop3xx/io.h | 6 +- include/asm-arm/arch-iop3xx/iop321-irqs.h | 26 +- include/asm-arm/arch-iop3xx/iop321.h | 95 +- include/asm-arm/arch-iop3xx/iq80321.h | 32 +- include/asm-arm/arch-iop3xx/irqs.h | 18 +- include/asm-arm/arch-iop3xx/memory.h | 26 +- include/asm-arm/arch-iop3xx/param.h | 2 +- include/asm-arm/arch-iop3xx/system.h | 10 +- include/asm-arm/arch-iop3xx/timex.h | 16 +- include/asm-arm/arch-iop3xx/uncompress.h | 36 +- include/asm-arm/arch-iop3xx/vmalloc.h | 1 + include/asm-arm/arch-ixp2000/dma.h | 2 +- include/asm-arm/arch-ixp2000/io.h | 4 +- include/asm-arm/arch-ixp2000/irqs.h | 30 +- include/asm-arm/arch-ixp2000/ixdp2x00.h | 2 +- include/asm-arm/arch-ixp2000/ixdp2x01.h | 4 + include/asm-arm/arch-ixp2000/ixp2000-regs.h | 10 +- include/asm-arm/arch-ixp2000/platform.h | 7 +- include/asm-arm/arch-ixp2000/system.h | 2 +- include/asm-arm/arch-ixp4xx/io.h | 30 +- include/asm-arm/arch-ixp4xx/ixp4xx-regs.h | 2 +- include/asm-arm/arch-ixp4xx/platform.h | 4 +- include/asm-arm/arch-ixp4xx/uncompress.h | 2 +- include/asm-arm/arch-l7200/io.h | 6 +- include/asm-arm/arch-l7200/param.h | 2 +- include/asm-arm/arch-l7200/time.h | 3 + include/asm-arm/arch-l7200/uncompress.h | 2 +- include/asm-arm/arch-lh7a40x/io.h | 6 +- include/asm-arm/arch-lh7a40x/timex.h | 1 - include/asm-arm/arch-lh7a40x/uncompress.h | 2 +- include/asm-arm/arch-omap/board-h2.h | 14 + include/asm-arm/arch-omap/board-h3.h | 28 +- include/asm-arm/arch-omap/board-innovator.h | 131 +- include/asm-arm/arch-omap/board-perseus2.h | 57 +- include/asm-arm/arch-omap/board.h | 96 +- include/asm-arm/arch-omap/dma.h | 28 +- include/asm-arm/arch-omap/fpga.h | 159 +- include/asm-arm/arch-omap/hardware.h | 80 +- include/asm-arm/arch-omap/io.h | 6 +- include/asm-arm/arch-omap/irqs.h | 22 +- include/asm-arm/arch-omap/mcbsp.h | 2 +- include/asm-arm/arch-omap/memory.h | 4 +- include/asm-arm/arch-omap/mux.h | 71 +- include/asm-arm/arch-omap/omap1510.h | 19 +- include/asm-arm/arch-omap/omap730.h | 6 - include/asm-arm/arch-omap/pm.h | 259 +- include/asm-arm/arch-omap/timex.h | 4 +- include/asm-arm/arch-omap/uncompress.h | 29 +- include/asm-arm/arch-pxa/dma.h | 2 +- include/asm-arm/arch-pxa/hardware.h | 9 +- include/asm-arm/arch-pxa/io.h | 6 +- include/asm-arm/arch-pxa/irqs.h | 54 +- include/asm-arm/arch-pxa/pxa-regs.h | 245 +- include/asm-arm/arch-pxa/system.h | 1 + include/asm-arm/arch-pxa/uncompress.h | 2 +- include/asm-arm/arch-rpc/io.h | 36 +- include/asm-arm/arch-rpc/uncompress.h | 6 +- include/asm-arm/arch-s3c2410/bast-cpld.h | 35 +- include/asm-arm/arch-s3c2410/bast-irq.h | 3 +- include/asm-arm/arch-s3c2410/dma.h | 353 +- include/asm-arm/arch-s3c2410/hardware.h | 41 +- include/asm-arm/arch-s3c2410/param.h | 2 +- include/asm-arm/arch-s3c2410/regs-clock.h | 58 +- include/asm-arm/arch-s3c2410/regs-dsc.h | 32 +- include/asm-arm/arch-s3c2410/regs-gpio.h | 54 +- include/asm-arm/arch-s3c2410/regs-iic.h | 16 +- include/asm-arm/arch-s3c2410/regs-lcd.h | 14 +- include/asm-arm/arch-s3c2410/regs-rtc.h | 2 + include/asm-arm/arch-s3c2410/regs-sdi.h | 20 +- include/asm-arm/arch-s3c2410/regs-serial.h | 99 +- include/asm-arm/arch-s3c2410/regs-timer.h | 2 + include/asm-arm/arch-s3c2410/regs-udc.h | 7 +- include/asm-arm/arch-s3c2410/regs-watchdog.h | 1 + include/asm-arm/arch-s3c2410/system.h | 32 +- include/asm-arm/arch-s3c2410/timex.h | 7 +- include/asm-arm/arch-s3c2410/uncompress.h | 33 +- include/asm-arm/arch-sa1100/ide.h | 75 +- include/asm-arm/arch-sa1100/io.h | 6 +- include/asm-arm/arch-sa1100/irqs.h | 9 +- include/asm-arm/arch-sa1100/system.h | 9 - include/asm-arm/arch-sa1100/timex.h | 1 - include/asm-arm/arch-sa1100/uncompress.h | 2 +- include/asm-arm/arch-shark/io.h | 2 +- include/asm-arm/arch-shark/uncompress.h | 2 +- include/asm-arm/arch-versatile/hardware.h | 2 +- include/asm-arm/arch-versatile/io.h | 6 +- include/asm-arm/arch-versatile/platform.h | 28 +- include/asm-arm/arch-versatile/timex.h | 2 +- include/asm-arm/arch-versatile/uncompress.h | 2 +- include/asm-arm/atomic.h | 56 +- include/asm-arm/bitops.h | 4 +- include/asm-arm/bug.h | 14 +- include/asm-arm/cacheflush.h | 91 +- include/asm-arm/checksum.h | 2 +- include/asm-arm/delay.h | 30 +- include/asm-arm/ecard.h | 1 + include/asm-arm/elf.h | 27 + include/asm-arm/fpstate.h | 19 +- include/asm-arm/hardirq.h | 63 +- include/asm-arm/hardware.h | 9 - include/asm-arm/hardware/amba_clcd.h | 4 +- include/asm-arm/hardware/clock.h | 8 +- include/asm-arm/ide.h | 4 - include/asm-arm/io.h | 72 +- include/asm-arm/irq.h | 3 +- include/asm-arm/mach/arch.h | 6 +- include/asm-arm/mach/flash.h | 19 +- include/asm-arm/mach/irq.h | 17 - include/asm-arm/mach/map.h | 6 +- include/asm-arm/mach/mmc.h | 1 - include/asm-arm/mach/pci.h | 8 +- include/asm-arm/mach/time.h | 42 +- include/asm-arm/memory.h | 21 +- include/asm-arm/mmu_context.h | 11 +- include/asm-arm/page.h | 10 +- include/asm-arm/param.h | 11 +- include/asm-arm/pgtable.h | 2 +- include/asm-arm/posix_types.h | 8 +- include/asm-arm/procinfo.h | 6 +- include/asm-arm/ptrace.h | 6 + include/asm-arm/resource.h | 2 +- include/asm-arm/semaphore.h | 30 +- include/asm-arm/serial.h | 6 +- include/asm-arm/setup.h | 2 - include/asm-arm/socket.h | 16 - include/asm-arm/system.h | 37 +- include/asm-arm/thread_info.h | 35 +- include/asm-arm/tlbflush.h | 4 +- include/asm-arm/uaccess.h | 37 +- include/asm-arm/unistd.h | 52 +- include/asm-arm26/atomic.h | 21 + include/asm-arm26/bug.h | 17 +- include/asm-arm26/hardirq.h | 50 - include/asm-arm26/io.h | 2 + include/asm-arm26/pgtable.h | 2 +- include/asm-arm26/ptrace.h | 1 + include/asm-arm26/resource.h | 2 +- include/asm-arm26/semaphore.h | 37 +- include/asm-arm26/socket.h | 16 - include/asm-arm26/uaccess.h | 3 + include/asm-cris/arch-v10/ptrace.h | 1 + include/asm-cris/bug.h | 19 +- include/asm-cris/hardirq.h | 57 - include/asm-cris/io.h | 2 + include/asm-cris/resource.h | 2 +- include/asm-cris/semaphore.h | 33 +- include/asm-cris/socket.h | 15 - include/asm-cris/uaccess.h | 2 + include/asm-generic/dma-mapping-broken.h | 2 +- include/asm-generic/errno.h | 5 + include/asm-generic/ide_iops.h | 8 +- include/asm-generic/local.h | 2 +- include/asm-generic/pci.h | 7 + include/asm-generic/pgtable.h | 8 + include/asm-generic/siginfo.h | 1 + include/asm-generic/topology.h | 5 - include/asm-generic/vmlinux.lds.h | 28 + include/asm-h8300/bitops.h | 10 +- include/asm-h8300/bug.h | 19 +- include/asm-h8300/delay.h | 7 +- include/asm-h8300/hardirq.h | 61 - include/asm-h8300/io.h | 25 +- include/asm-h8300/pgtable.h | 3 +- include/asm-h8300/ptrace.h | 1 + include/asm-h8300/resource.h | 2 +- include/asm-h8300/semaphore.h | 33 +- include/asm-h8300/sigcontext.h | 2 + include/asm-h8300/signal.h | 2 + include/asm-h8300/socket.h | 16 - include/asm-h8300/system.h | 3 +- include/asm-h8300/timex.h | 4 - include/asm-h8300/uaccess.h | 2 + include/asm-h8300/ucontext.h | 13 +- include/asm-h8300/unistd.h | 1 + include/asm-i386/acpi.h | 20 +- include/asm-i386/apic.h | 36 +- include/asm-i386/atomic.h | 42 + include/asm-i386/bitops.h | 12 +- include/asm-i386/bug.h | 14 +- include/asm-i386/checksum.h | 7 +- include/asm-i386/cpu.h | 1 + include/asm-i386/cpufeature.h | 13 +- include/asm-i386/desc.h | 10 +- include/asm-i386/dma-mapping.h | 13 +- include/asm-i386/elf.h | 2 +- include/asm-i386/fixmap.h | 21 +- include/asm-i386/hardirq.h | 84 +- include/asm-i386/hpet.h | 1 + include/asm-i386/hw_irq.h | 56 +- include/asm-i386/i387.h | 2 - include/asm-i386/io.h | 97 +- include/asm-i386/io_apic.h | 6 +- include/asm-i386/irq.h | 33 +- include/asm-i386/kprobes.h | 7 + include/asm-i386/linkage.h | 4 + include/asm-i386/mach-bigsmp/mach_ipi.h | 2 +- include/asm-i386/mach-default/do_timer.h | 5 +- include/asm-i386/mach-default/mach_ipi.h | 4 +- include/asm-i386/mach-es7000/mach_ipi.h | 2 +- include/asm-i386/mach-es7000/mach_mpparse.h | 3 +- include/asm-i386/mach-es7000/mach_mpspec.h | 2 +- include/asm-i386/mach-numaq/mach_ipi.h | 2 +- include/asm-i386/mach-summit/mach_apic.h | 8 +- include/asm-i386/mach-summit/mach_ipi.h | 2 +- include/asm-i386/mach-summit/mach_mpparse.h | 3 + include/asm-i386/mach-visws/do_timer.h | 5 +- include/asm-i386/mach-visws/mach_apic.h | 1 + include/asm-i386/mach-voyager/do_timer.h | 3 + include/asm-i386/mmu_context.h | 12 +- include/asm-i386/module.h | 2 + include/asm-i386/mpspec.h | 2 +- include/asm-i386/mtrr.h | 2 - include/asm-i386/node.h | 1 + include/asm-i386/page.h | 12 +- include/asm-i386/pgtable-2level.h | 7 + include/asm-i386/pgtable-3level.h | 8 + include/asm-i386/pgtable.h | 10 +- include/asm-i386/processor.h | 24 +- include/asm-i386/ptrace.h | 5 + include/asm-i386/resource.h | 2 +- include/asm-i386/rwlock.h | 32 +- include/asm-i386/semaphore.h | 74 +- include/asm-i386/setup.h | 2 +- include/asm-i386/smp.h | 1 + include/asm-i386/socket.h | 16 - include/asm-i386/spinlock.h | 18 +- include/asm-i386/suspend.h | 3 + include/asm-i386/system.h | 4 +- include/asm-i386/thread_info.h | 12 +- include/asm-i386/timer.h | 21 +- include/asm-i386/timex.h | 17 +- include/asm-i386/tlbflush.h | 2 +- include/asm-i386/topology.h | 23 +- include/asm-i386/uaccess.h | 42 +- include/asm-i386/unistd.h | 15 +- include/asm-ia64/acpi.h | 4 +- include/asm-ia64/bug.h | 13 +- include/asm-ia64/compat.h | 8 +- include/asm-ia64/delay.h | 2 +- include/asm-ia64/dma-mapping.h | 2 +- include/asm-ia64/elf.h | 6 +- include/asm-ia64/gcc_intrin.h | 24 +- include/asm-ia64/hardirq.h | 69 +- include/asm-ia64/hw_irq.h | 2 - include/asm-ia64/ia32.h | 4 +- include/asm-ia64/io.h | 119 +- include/asm-ia64/iosapic.h | 11 +- include/asm-ia64/machvec.h | 23 +- include/asm-ia64/machvec_init.h | 1 + include/asm-ia64/machvec_sn2.h | 4 +- include/asm-ia64/mca.h | 7 + include/asm-ia64/mca_asm.h | 3 - include/asm-ia64/mmu_context.h | 51 +- include/asm-ia64/mmzone.h | 6 - include/asm-ia64/numa.h | 2 +- include/asm-ia64/page.h | 18 +- include/asm-ia64/pal.h | 2 +- include/asm-ia64/pci.h | 11 +- include/asm-ia64/pgtable.h | 24 +- include/asm-ia64/processor.h | 15 +- include/asm-ia64/ptrace.h | 17 +- include/asm-ia64/resource.h | 2 +- include/asm-ia64/sal.h | 12 +- include/asm-ia64/semaphore.h | 30 +- include/asm-ia64/siginfo.h | 2 +- include/asm-ia64/signal.h | 4 +- include/asm-ia64/smp.h | 8 +- include/asm-ia64/sn/addrs.h | 311 +- include/asm-ia64/sn/arch.h | 21 +- include/asm-ia64/sn/bte.h | 4 +- include/asm-ia64/sn/clksupport.h | 30 +- include/asm-ia64/sn/fetchop.h | 2 +- include/asm-ia64/sn/geo.h | 131 +- include/asm-ia64/sn/intr.h | 49 +- include/asm-ia64/sn/io.h | 286 +- include/asm-ia64/sn/klconfig.h | 480 +- include/asm-ia64/sn/leds.h | 8 +- include/asm-ia64/sn/module.h | 131 +- include/asm-ia64/sn/nodepda.h | 69 +- include/asm-ia64/sn/pda.h | 5 +- include/asm-ia64/sn/router.h | 51 +- include/asm-ia64/sn/rw_mmr.h | 2 +- include/asm-ia64/sn/shub_mmr.h | 205 + include/asm-ia64/sn/simulator.h | 8 +- include/asm-ia64/sn/sn2/sn_hwperf.h | 10 +- include/asm-ia64/sn/sn_cpuid.h | 88 +- include/asm-ia64/sn/sn_fru.h | 2 +- include/asm-ia64/sn/sn_sal.h | 283 +- include/asm-ia64/sn/sndrv.h | 14 +- include/asm-ia64/sn/types.h | 4 +- include/asm-ia64/socket.h | 16 - include/asm-ia64/spinlock.h | 4 +- include/asm-ia64/system.h | 4 +- include/asm-ia64/thread_info.h | 8 - include/asm-ia64/tlb.h | 1 + include/asm-ia64/tlbflush.h | 7 +- include/asm-ia64/topology.h | 42 +- include/asm-ia64/uaccess.h | 120 +- include/asm-ia64/unistd.h | 10 +- include/asm-m32r/elf.h | 41 +- include/asm-m32r/hardirq.h | 22 - include/asm-m32r/ide.h | 2 +- include/asm-m32r/io.h | 13 +- include/asm-m32r/m32102.h | 112 +- include/asm-m32r/pgtable.h | 3 +- include/asm-m32r/processor.h | 30 +- include/asm-m32r/rtc.h | 2 +- include/asm-m32r/termbits.h | 1 + include/asm-m32r/topology.h | 5 - include/asm-m68k/atomic.h | 2 + include/asm-m68k/blinken.h | 15 +- include/asm-m68k/bootinfo.h | 7 + include/asm-m68k/bug.h | 17 +- include/asm-m68k/cacheflush.h | 12 +- include/asm-m68k/hardirq.h | 57 - include/asm-m68k/io.h | 19 + include/asm-m68k/mc146818rtc.h | 2 + include/asm-m68k/pgtable.h | 3 +- include/asm-m68k/ptrace.h | 1 + include/asm-m68k/resource.h | 2 +- include/asm-m68k/semaphore.h | 33 +- include/asm-m68k/setup.h | 2 +- include/asm-m68k/socket.h | 16 - include/asm-m68k/system.h | 2 +- include/asm-m68k/timex.h | 4 - include/asm-m68k/tlbflush.h | 2 + include/asm-m68k/uaccess.h | 3 + include/asm-m68k/unistd.h | 48 +- include/asm-m68knommu/bug.h | 22 +- include/asm-m68knommu/checksum.h | 2 + include/asm-m68knommu/coldfire.h | 10 +- include/asm-m68knommu/delay.h | 55 +- include/asm-m68knommu/hardirq.h | 67 - include/asm-m68knommu/io.h | 2 + include/asm-m68knommu/mcfdma.h | 2 +- include/asm-m68knommu/mcfpit.h | 2 +- include/asm-m68knommu/mcfsim.h | 9 +- include/asm-m68knommu/mcfuart.h | 2 +- include/asm-m68knommu/page_offset.h | 4 - include/asm-m68knommu/param.h | 33 +- include/asm-m68knommu/pgtable.h | 3 +- include/asm-m68knommu/ptrace.h | 1 + include/asm-m68knommu/semaphore.h | 33 +- include/asm-m68knommu/system.h | 13 + include/asm-m68knommu/thread_info.h | 12 +- include/asm-m68knommu/uaccess.h | 2 + include/asm-m68knommu/unistd.h | 73 +- include/asm-mips/addrspace.h | 61 +- include/asm-mips/asmmacro-32.h | 6 +- include/asm-mips/asmmacro-64.h | 18 + include/asm-mips/atomic.h | 631 +- include/asm-mips/bitops.h | 568 +- include/asm-mips/bootinfo.h | 2 + include/asm-mips/bug.h | 10 +- include/asm-mips/checksum.h | 1 + include/asm-mips/compat.h | 6 +- include/asm-mips/cpu-features.h | 15 +- include/asm-mips/debug.h | 3 +- include/asm-mips/delay.h | 8 +- include/asm-mips/div64.h | 7 +- include/asm-mips/dma-mapping.h | 9 +- include/asm-mips/errno.h | 4 + include/asm-mips/fixmap.h | 1 - include/asm-mips/gdb-stub.h | 1 + include/asm-mips/hardirq.h | 81 +- include/asm-mips/hazards.h | 2 +- include/asm-mips/hw_irq.h | 2 - include/asm-mips/ide.h | 12 - include/asm-mips/io.h | 76 +- include/asm-mips/ip32/crime.h | 214 +- include/asm-mips/ip32/mace.h | 153 +- include/asm-mips/irq.h | 30 +- include/asm-mips/jazz.h | 2 + include/asm-mips/mach-atlas/mc146818rtc.h | 2 +- include/asm-mips/mach-au1x00/au1000.h | 322 +- include/asm-mips/mach-db1x00/db1x00.h | 34 +- include/asm-mips/mach-generic/floppy.h | 1 - include/asm-mips/mach-generic/ide.h | 21 +- include/asm-mips/mach-generic/mangle-port.h | 3 +- include/asm-mips/mach-generic/spaces.h | 4 +- include/asm-mips/mach-ip27/mangle-port.h | 3 +- include/asm-mips/mach-ip27/mmzone.h | 27 + include/asm-mips/mach-ip27/spaces.h | 6 +- include/asm-mips/mach-ip27/topology.h | 30 +- include/asm-mips/mach-ip32/mangle-port.h | 2 + .../asm-mips/mach-ja/cpu-feature-overrides.h | 6 + .../mach-yosemite/cpu-feature-overrides.h | 6 + include/asm-mips/marvell.h | 1 - include/asm-mips/mipsregs.h | 7 + include/asm-mips/mmu_context.h | 10 +- include/asm-mips/mmzone.h | 3 - include/asm-mips/numnodes.h | 2 +- include/asm-mips/page.h | 17 +- include/asm-mips/pci.h | 65 + include/asm-mips/pci/bridge.h | 7 +- include/asm-mips/pgtable-32.h | 22 + include/asm-mips/pgtable-64.h | 19 +- include/asm-mips/pgtable-bits.h | 33 +- include/asm-mips/pgtable.h | 133 +- include/asm-mips/posix_types.h | 8 +- include/asm-mips/processor.h | 72 +- include/asm-mips/ptrace.h | 3 + include/asm-mips/r4kcache.h | 2 +- include/asm-mips/resource.h | 2 +- include/asm-mips/semaphore.h | 36 +- include/asm-mips/serial.h | 105 +- include/asm-mips/sgi/ioc.h | 2 +- include/asm-mips/sgiarcs.h | 4 +- include/asm-mips/siginfo.h | 122 +- include/asm-mips/sim.h | 5 +- include/asm-mips/smp.h | 7 +- include/asm-mips/sn/hub.h | 19 - include/asm-mips/sn/mapped_kernel.h | 2 - include/asm-mips/sn/sn_private.h | 2 - include/asm-mips/socket.h | 45 +- include/asm-mips/spinlock.h | 259 +- include/asm-mips/stackframe.h | 2 +- include/asm-mips/statfs.h | 32 +- include/asm-mips/system.h | 362 +- include/asm-mips/thread_info.h | 2 +- include/asm-mips/titan_dep.h | 40 +- include/asm-mips/tx4927/tx4927.h | 18 +- include/asm-mips/uaccess.h | 221 +- include/asm-mips/unistd.h | 92 +- include/asm-mips/vr41xx/vrc4173.h | 106 + include/asm-mips/war.h | 11 + include/asm-parisc/assembly.h | 17 +- include/asm-parisc/atomic.h | 54 +- include/asm-parisc/bitops.h | 24 +- include/asm-parisc/bug.h | 23 +- include/asm-parisc/cacheflush.h | 12 +- include/asm-parisc/errno.h | 4 + include/asm-parisc/hardirq.h | 63 - include/asm-parisc/io.h | 2 + include/asm-parisc/pci.h | 36 +- include/asm-parisc/pdc.h | 1 + include/asm-parisc/pgtable.h | 3 +- include/asm-parisc/posix_types.h | 2 +- include/asm-parisc/ptrace.h | 4 +- include/asm-parisc/resource.h | 2 +- include/asm-parisc/semaphore.h | 31 +- include/asm-parisc/socket.h | 14 - include/asm-parisc/spinlock.h | 42 +- include/asm-parisc/string.h | 10 + include/asm-parisc/superio.h | 1 - include/asm-parisc/system.h | 24 +- include/asm-parisc/thread_info.h | 15 +- include/asm-parisc/tlbflush.h | 8 + include/asm-parisc/uaccess.h | 180 +- include/asm-parisc/unistd.h | 38 +- include/asm-ppc/8xx_immap.h | 234 +- include/asm-ppc/bug.h | 7 +- include/asm-ppc/checksum.h | 2 +- include/asm-ppc/commproc.h | 69 +- include/asm-ppc/cputable.h | 6 + include/asm-ppc/dma-mapping.h | 1 - include/asm-ppc/fsl_ocp.h | 2 +- include/asm-ppc/hardirq.h | 89 +- include/asm-ppc/hw_irq.h | 1 - include/asm-ppc/ibm44x.h | 4 +- include/asm-ppc/ibm4xx.h | 4 + include/asm-ppc/ide.h | 8 +- include/asm-ppc/immap_cpm2.h | 2 +- include/asm-ppc/io.h | 368 +- include/asm-ppc/irq.h | 26 +- include/asm-ppc/machdep.h | 1 + include/asm-ppc/mpc52xx.h | 374 +- include/asm-ppc/mpc52xx_psc.h | 162 +- include/asm-ppc/mpc8260.h | 4 + include/asm-ppc/mpc85xx.h | 3 + include/asm-ppc/mpc8xx.h | 6 +- include/asm-ppc/ocp_ids.h | 1 + include/asm-ppc/open_pic.h | 4 +- include/asm-ppc/pci-bridge.h | 2 + include/asm-ppc/pgtable.h | 3 +- include/asm-ppc/pmac_feature.h | 6 +- include/asm-ppc/ppcboot.h | 36 +- include/asm-ppc/ptrace.h | 6 + include/asm-ppc/reg_booke.h | 10 +- include/asm-ppc/residual.h | 16 + include/asm-ppc/resource.h | 2 +- include/asm-ppc/semaphore.h | 36 +- include/asm-ppc/serial.h | 12 +- include/asm-ppc/socket.h | 16 - include/asm-ppc/thread_info.h | 12 +- include/asm-ppc/time.h | 3 +- include/asm-ppc/timex.h | 4 - include/asm-ppc/uaccess.h | 2 + include/asm-ppc/unistd.h | 5 +- include/asm-ppc64/bitops.h | 88 +- include/asm-ppc64/btext.h | 19 +- include/asm-ppc64/bug.h | 8 +- include/asm-ppc64/checksum.h | 4 +- include/asm-ppc64/dma-mapping.h | 1 - include/asm-ppc64/eeh.h | 273 +- include/asm-ppc64/floppy.h | 1 + include/asm-ppc64/hardirq.h | 90 +- include/asm-ppc64/hvcall.h | 8 +- include/asm-ppc64/hvconsole.h | 18 +- include/asm-ppc64/hvcserver.h | 25 +- include/asm-ppc64/iSeries/iSeries_io.h | 18 +- include/asm-ppc64/iSeries/mf.h | 41 +- include/asm-ppc64/ide.h | 2 +- include/asm-ppc64/io.h | 151 +- include/asm-ppc64/iommu.h | 22 +- include/asm-ppc64/irq.h | 20 +- include/asm-ppc64/lmb.h | 10 +- include/asm-ppc64/machdep.h | 16 +- include/asm-ppc64/memory.h | 10 - include/asm-ppc64/mmu.h | 245 +- include/asm-ppc64/mmu_context.h | 218 +- include/asm-ppc64/mmzone.h | 4 +- include/asm-ppc64/naca.h | 3 - include/asm-ppc64/paca.h | 31 +- include/asm-ppc64/page.h | 27 +- include/asm-ppc64/pci-bridge.h | 43 +- include/asm-ppc64/pci.h | 13 +- include/asm-ppc64/pgalloc.h | 1 + include/asm-ppc64/pgtable.h | 62 +- include/asm-ppc64/plpar_wrappers.h | 8 +- include/asm-ppc64/ppc32.h | 30 +- include/asm-ppc64/processor.h | 59 +- include/asm-ppc64/prom.h | 100 +- include/asm-ppc64/ptrace-common.h | 2 + include/asm-ppc64/ptrace.h | 8 +- include/asm-ppc64/resource.h | 2 +- include/asm-ppc64/rtas.h | 145 +- include/asm-ppc64/semaphore.h | 36 +- include/asm-ppc64/serial.h | 111 +- include/asm-ppc64/smp.h | 41 +- include/asm-ppc64/socket.h | 16 - include/asm-ppc64/spinlock.h | 278 +- include/asm-ppc64/system.h | 3 + include/asm-ppc64/systemcfg.h | 49 +- include/asm-ppc64/thread_info.h | 4 +- include/asm-ppc64/timex.h | 4 - include/asm-ppc64/tlb.h | 17 +- include/asm-ppc64/topology.h | 21 +- include/asm-ppc64/uaccess.h | 6 + include/asm-ppc64/udbg.h | 4 +- include/asm-ppc64/unistd.h | 29 +- include/asm-s390/bug.h | 19 +- include/asm-s390/debug.h | 2 + include/asm-s390/dma-mapping.h | 13 +- include/asm-s390/elf.h | 11 +- include/asm-s390/extmem.h | 23 +- include/asm-s390/hardirq.h | 64 +- include/asm-s390/idals.h | 2 +- include/asm-s390/io.h | 2 + include/asm-s390/irq.h | 2 +- include/asm-s390/lowcore.h | 8 +- include/asm-s390/page.h | 19 + include/asm-s390/pgtable.h | 23 +- include/asm-s390/processor.h | 21 + include/asm-s390/ptrace.h | 1 + include/asm-s390/resource.h | 2 +- include/asm-s390/siginfo.h | 71 - include/asm-s390/socket.h | 16 - include/asm-s390/thread_info.h | 38 +- include/asm-s390/timer.h | 2 - include/asm-s390/timex.h | 4 - include/asm-s390/uaccess.h | 6 + include/asm-s390/unistd.h | 3 +- include/asm-sh/adc.h | 3 +- include/asm-sh/addrspace.h | 2 + include/asm-sh/bitops.h | 4 +- include/asm-sh/bug.h | 17 +- include/asm-sh/bugs.h | 4 +- include/asm-sh/cache.h | 5 +- include/asm-sh/cacheflush.h | 14 +- include/asm-sh/checksum.h | 3 +- include/asm-sh/cpu-sh3/cache.h | 7 + include/asm-sh/cpu-sh3/cacheflush.h | 42 + include/asm-sh/cpu-sh4/freq.h | 4 + include/asm-sh/dma-mapping.h | 45 +- include/asm-sh/dma.h | 2 + include/asm-sh/freq.h | 3 +- include/asm-sh/hardirq.h | 62 +- include/asm-sh/io.h | 2 + include/asm-sh/irq.h | 25 +- include/asm-sh/machvec.h | 2 +- include/asm-sh/mmu_context.h | 2 + include/asm-sh/page.h | 8 +- include/asm-sh/pgtable.h | 7 +- include/asm-sh/processor.h | 4 + include/asm-sh/ptrace.h | 9 + include/asm-sh/resource.h | 2 +- include/asm-sh/rtc.h | 3 +- include/asm-sh/se/se.h | 8 + include/asm-sh/semaphore.h | 35 +- include/asm-sh/shmparam.h | 2 + include/asm-sh/socket.h | 16 - include/asm-sh/system.h | 1 - include/asm-sh/thread_info.h | 10 - include/asm-sh/timex.h | 4 - include/asm-sh/uaccess.h | 4 + include/asm-sh/ubc.h | 3 +- include/asm-sh/unistd.h | 8 +- include/asm-sh/user.h | 2 - include/asm-sh/watchdog.h | 3 +- include/asm-sh64/cacheflush.h | 14 +- include/asm-sh64/dma-mapping.h | 1 - include/asm-sh64/io.h | 5 + include/asm-sh64/pgtable.h | 3 +- include/asm-sh64/ptrace.h | 1 + include/asm-sh64/semaphore.h | 35 +- include/asm-sh64/uaccess.h | 3 + include/asm-sparc/atomic.h | 1 + include/asm-sparc/bug.h | 17 +- include/asm-sparc/cacheflush.h | 10 +- include/asm-sparc/dma-mapping.h | 1 - include/asm-sparc/dma.h | 2 +- include/asm-sparc/elf.h | 2 +- include/asm-sparc/errno.h | 5 + include/asm-sparc/fbio.h | 6 +- include/asm-sparc/hardirq.h | 62 - include/asm-sparc/io.h | 182 +- include/asm-sparc/mostek.h | 7 +- include/asm-sparc/processor.h | 2 + include/asm-sparc/ptrace.h | 1 + include/asm-sparc/resource.h | 2 +- include/asm-sparc/semaphore.h | 36 +- include/asm-sparc/sigcontext.h | 17 +- include/asm-sparc/signal.h | 8 +- include/asm-sparc/socket.h | 16 - include/asm-sparc/timex.h | 4 - include/asm-sparc/uaccess.h | 3 + include/asm-sparc/unistd.h | 17 +- include/asm-sparc/vaddrs.h | 4 +- include/asm-sparc64/atomic.h | 6 + include/asm-sparc64/bitops.h | 35 +- include/asm-sparc64/bug.h | 19 +- include/asm-sparc64/cacheflush.h | 11 +- include/asm-sparc64/checksum.h | 37 +- include/asm-sparc64/delay.h | 69 +- include/asm-sparc64/dma.h | 2 +- include/asm-sparc64/ebus.h | 2 +- include/asm-sparc64/elf.h | 4 +- include/asm-sparc64/errno.h | 5 + include/asm-sparc64/hardirq.h | 62 - include/asm-sparc64/ide.h | 12 +- include/asm-sparc64/io.h | 176 +- include/asm-sparc64/kdebug.h | 49 +- include/asm-sparc64/kprobes.h | 6 + include/asm-sparc64/parport.h | 6 +- include/asm-sparc64/pbm.h | 9 + include/asm-sparc64/pci.h | 5 + include/asm-sparc64/ptrace.h | 5 + include/asm-sparc64/resource.h | 2 +- include/asm-sparc64/sigcontext.h | 12 - include/asm-sparc64/siginfo.h | 54 +- include/asm-sparc64/socket.h | 16 - include/asm-sparc64/spinlock.h | 180 +- include/asm-sparc64/string.h | 109 +- include/asm-sparc64/timex.h | 4 - include/asm-sparc64/ttable.h | 6 + include/asm-sparc64/uaccess.h | 63 +- include/asm-sparc64/unistd.h | 18 +- include/asm-sparc64/vga.h | 3 + include/asm-um/archparam-i386.h | 89 +- include/asm-um/atomic.h | 5 + include/asm-um/bug.h | 28 +- include/asm-um/common.lds.S | 52 +- include/asm-um/current.h | 11 +- include/asm-um/dma-mapping.h | 122 +- include/asm-um/elf.h | 13 + include/asm-um/fixmap.h | 8 + include/asm-um/hardirq.h | 28 +- include/asm-um/irq.h | 18 - include/asm-um/mmu_context.h | 4 +- include/asm-um/page.h | 34 +- include/asm-um/pgtable.h | 118 +- include/asm-um/processor-generic.h | 47 +- include/asm-um/processor-i386.h | 11 +- include/asm-um/ptrace-generic.h | 4 +- include/asm-um/smp.h | 6 +- include/asm-um/spinlock.h | 4 - include/asm-um/system-generic.h | 9 +- include/asm-um/system-i386.h | 31 - include/asm-um/thread_info.h | 17 +- include/asm-um/timex.h | 2 - include/asm-um/uaccess.h | 7 +- include/asm-um/unistd.h | 15 +- include/asm-v850/bug.h | 12 +- include/asm-v850/hardirq.h | 61 - include/asm-v850/io.h | 9 +- include/asm-v850/posix_types.h | 4 +- include/asm-v850/ptrace.h | 1 + include/asm-v850/resource.h | 2 +- include/asm-v850/socket.h | 16 - include/asm-v850/timex.h | 4 - include/asm-v850/uaccess.h | 3 + include/asm-x86_64/acpi.h | 9 + include/asm-x86_64/apic.h | 30 +- include/asm-x86_64/apicdef.h | 38 +- include/asm-x86_64/atomic.h | 185 + include/asm-x86_64/bitops.h | 143 +- include/asm-x86_64/bootsetup.h | 2 +- include/asm-x86_64/bug.h | 25 +- include/asm-x86_64/compat.h | 2 +- include/asm-x86_64/cpufeature.h | 17 +- include/asm-x86_64/desc.h | 6 +- include/asm-x86_64/dma-mapping.h | 134 +- include/asm-x86_64/elf.h | 12 + include/asm-x86_64/hardirq.h | 99 +- include/asm-x86_64/hpet.h | 4 + include/asm-x86_64/hw_irq.h | 37 +- include/asm-x86_64/i387.h | 24 +- include/asm-x86_64/ia32.h | 10 +- include/asm-x86_64/ia32_unistd.h | 3 +- include/asm-x86_64/io.h | 138 +- include/asm-x86_64/io_apic.h | 2 +- include/asm-x86_64/irq.h | 7 +- include/asm-x86_64/kdebug.h | 3 +- include/asm-x86_64/mpspec.h | 9 +- include/asm-x86_64/msi.h | 4 +- include/asm-x86_64/mtrr.h | 2 - include/asm-x86_64/nmi.h | 6 + include/asm-x86_64/numa.h | 2 + include/asm-x86_64/page.h | 12 +- include/asm-x86_64/pci.h | 253 +- include/asm-x86_64/pgtable.h | 3 +- include/asm-x86_64/processor.h | 18 +- include/asm-x86_64/proto.h | 6 +- include/asm-x86_64/ptrace.h | 1 + include/asm-x86_64/resource.h | 2 +- include/asm-x86_64/semaphore.h | 35 +- include/asm-x86_64/smp.h | 53 +- include/asm-x86_64/socket.h | 16 - include/asm-x86_64/spinlock.h | 4 +- include/asm-x86_64/swiotlb.h | 4 + include/asm-x86_64/system.h | 12 +- include/asm-x86_64/thread_info.h | 2 +- include/asm-x86_64/timex.h | 4 - include/asm-x86_64/topology.h | 33 +- include/asm-x86_64/uaccess.h | 8 +- include/asm-x86_64/unistd.h | 4 +- include/asm-x86_64/vsyscall.h | 6 +- include/linux/acct.h | 23 +- include/linux/acpi.h | 34 +- include/linux/adfs_fs.h | 16 +- include/linux/adfs_fs_i.h | 2 +- include/linux/adfs_fs_sb.h | 2 +- include/linux/affs_fs.h | 3 +- include/linux/affs_hardblocks.h | 14 +- include/linux/aio.h | 28 +- include/linux/amigaffs.h | 112 +- include/linux/arcdevice.h | 2 +- include/linux/ata.h | 71 +- include/linux/atalk.h | 29 +- include/linux/atm.h | 3 + include/linux/atmdev.h | 5 +- include/linux/atmsvc.h | 7 +- include/linux/bio.h | 10 + include/linux/bitmap.h | 3 + include/linux/bitops.h | 4 +- include/linux/blkdev.h | 91 +- include/linux/bootmem.h | 3 + include/linux/buffer_head.h | 40 +- include/linux/byteorder/big_endian.h | 118 +- include/linux/byteorder/generic.h | 8 +- include/linux/byteorder/little_endian.h | 118 +- include/linux/cdev.h | 2 - include/linux/cdrom.h | 7 +- include/linux/ckrm_ce.h | 40 +- include/linux/ckrm_rc.h | 182 +- include/linux/ckrm_tc.h | 41 +- include/linux/ckrm_tsk.h | 9 +- include/linux/coda.h | 10 +- include/linux/compat.h | 14 + include/linux/compat_ioctl.h | 35 +- include/linux/compiler-gcc+.h | 6 +- include/linux/compiler-gcc3.h | 12 +- include/linux/compiler.h | 25 +- include/linux/cpu.h | 2 +- include/linux/cpufreq.h | 34 +- include/linux/cpumask.h | 5 +- include/linux/crbce.h | 3 +- include/linux/crc-ccitt.h | 2 + include/linux/cyclades.h | 10 +- include/linux/cyclomx.h | 2 +- include/linux/cycx_drv.h | 6 +- include/linux/dcache.h | 7 +- include/linux/delay.h | 6 + include/linux/device-mapper.h | 4 + include/linux/device.h | 15 +- include/linux/dio.h | 188 +- include/linux/divert.h | 2 + include/linux/dm-ioctl.h | 21 +- include/linux/dma-mapping.h | 30 + include/linux/dnotify.h | 46 +- include/linux/dqblk_xfs.h | 63 +- include/linux/dvb/frontend.h | 11 +- include/linux/dvb/osd.h | 32 + include/linux/eeprom.h | 4 +- include/linux/efi.h | 2 +- include/linux/efs_dir.h | 4 +- include/linux/efs_fs.h | 5 +- include/linux/efs_fs_i.h | 24 +- include/linux/efs_fs_sb.h | 52 +- include/linux/efs_vh.h | 20 +- include/linux/elevator.h | 64 +- include/linux/elf.h | 7 +- include/linux/err.h | 4 +- include/linux/errno.h | 1 + include/linux/ext2_fs.h | 144 +- include/linux/ext3_fs.h | 230 +- include/linux/ext3_fs_i.h | 29 +- include/linux/ext3_fs_sb.h | 7 +- include/linux/ext3_jbd.h | 7 +- include/linux/fb.h | 287 +- include/linux/filter.h | 8 + include/linux/fs.h | 155 +- include/linux/gen_stats.h | 5 + include/linux/generic_serial.h | 2 +- include/linux/genhd.h | 139 +- include/linux/gfp.h | 5 + include/linux/hardirq.h | 42 + include/linux/hdlc.h | 8 +- include/linux/hdreg.h | 31 +- include/linux/hiddev.h | 8 +- include/linux/highmem.h | 4 + include/linux/highuid.h | 8 +- include/linux/hpet.h | 5 +- include/linux/i2c-id.h | 4 + include/linux/i2c-sensor.h | 36 - include/linux/i2c-vid.h | 39 +- include/linux/i2c.h | 20 +- include/linux/i2o-dev.h | 262 +- include/linux/i2o.h | 780 +- include/linux/icmp.h | 2 + include/linux/ide.h | 201 +- include/linux/idr.h | 2 +- include/linux/if_bridge.h | 2 +- include/linux/if_ether.h | 14 +- include/linux/if_fddi.h | 36 +- include/linux/if_ppp.h | 2 +- include/linux/if_tr.h | 9 + include/linux/if_vlan.h | 16 +- include/linux/inet.h | 2 + include/linux/inetdevice.h | 23 +- include/linux/init_task.h | 2 +- include/linux/input.h | 24 + include/linux/interrupt.h | 31 +- include/linux/ioctl32.h | 25 +- include/linux/ioport.h | 5 + include/linux/ip6_tunnel.h | 2 + include/linux/ipmi.h | 8 +- include/linux/ipmi_msgdefs.h | 2 +- include/linux/ipv6.h | 11 +- include/linux/ipv6_route.h | 3 +- include/linux/irq.h | 18 +- include/linux/isicom.h | 1 - include/linux/iso_fs.h | 12 +- include/linux/jbd.h | 84 +- include/linux/jffs2_fs_i.h | 3 +- include/linux/jiffies.h | 384 +- include/linux/kallsyms.h | 10 + include/linux/kernel.h | 12 +- include/linux/kmod.h | 5 +- include/linux/kobject.h | 29 +- include/linux/kprobes.h | 5 +- include/linux/kref.h | 14 +- include/linux/libata.h | 134 +- include/linux/linkage.h | 4 + include/linux/list.h | 44 +- include/linux/lockd/bind.h | 2 +- include/linux/lockd/debug.h | 9 + include/linux/lockd/lockd.h | 23 +- include/linux/lockd/xdr.h | 10 +- include/linux/mbcache.h | 2 - include/linux/mc146818rtc.h | 4 +- include/linux/mempolicy.h | 9 +- include/linux/meye.h | 17 +- include/linux/mii.h | 3 +- include/linux/miscdevice.h | 1 + include/linux/mm.h | 142 +- include/linux/mman.h | 3 + include/linux/mmc/mmc.h | 5 +- include/linux/mmzone.h | 80 +- include/linux/module.h | 101 +- include/linux/moduleparam.h | 28 +- include/linux/mount.h | 2 + include/linux/msdos_fs.h | 70 +- include/linux/msdos_fs_i.h | 12 +- include/linux/msdos_fs_sb.h | 15 +- include/linux/mtd/cfi.h | 58 +- include/linux/mtd/doc2000.h | 8 +- include/linux/mtd/gen_probe.h | 2 +- include/linux/mtd/map.h | 22 +- include/linux/mtd/nand.h | 20 +- include/linux/mtd/partitions.h | 3 +- include/linux/ncp.h | 92 +- include/linux/ncp_fs.h | 10 +- include/linux/ncp_fs_i.h | 8 +- include/linux/ncp_no.h | 26 +- include/linux/net.h | 31 +- include/linux/netdevice.h | 47 +- include/linux/netfilter.h | 10 +- include/linux/netfilter_bridge/ebt_802_3.h | 9 + include/linux/netfilter_ipv4/ip_conntrack.h | 69 +- .../linux/netfilter_ipv4/ip_conntrack_core.h | 32 +- .../linux/netfilter_ipv4/ip_conntrack_ftp.h | 5 - .../linux/netfilter_ipv4/ip_conntrack_irc.h | 5 - .../netfilter_ipv4/ip_conntrack_protocol.h | 43 +- .../linux/netfilter_ipv4/ip_conntrack_tcp.h | 37 +- .../linux/netfilter_ipv4/ip_conntrack_tuple.h | 6 + include/linux/netfilter_ipv4/ip_nat.h | 15 +- include/linux/netfilter_ipv4/ip_nat_core.h | 6 - include/linux/netfilter_ipv4/ip_nat_helper.h | 8 +- .../linux/netfilter_ipv4/ip_nat_protocol.h | 18 +- include/linux/netfilter_ipv4/ip_tables.h | 10 +- include/linux/netfilter_ipv6.h | 2 + include/linux/netfilter_ipv6/ip6_tables.h | 16 +- include/linux/netlink.h | 9 +- include/linux/nfs.h | 17 + include/linux/nfs4.h | 63 +- include/linux/nfs_fs.h | 116 +- include/linux/nfs_fs_i.h | 4 +- include/linux/nfs_fs_sb.h | 1 + include/linux/nfs_page.h | 37 +- include/linux/nfs_xdr.h | 76 +- include/linux/nfsd/nfsd.h | 13 +- include/linux/nfsd/state.h | 18 +- include/linux/nfsd/xdr4.h | 7 +- include/linux/nls.h | 25 + include/linux/node.h | 1 - include/linux/notifier.h | 14 +- include/linux/page-flags.h | 10 +- include/linux/pagemap.h | 1 + include/linux/pagevec.h | 7 +- include/linux/parport.h | 13 - include/linux/parport_pc.h | 17 + include/linux/pci.h | 102 +- include/linux/pci_ids.h | 63 +- include/linux/percpu.h | 26 +- include/linux/personality.h | 12 +- include/linux/pfkeyv2.h | 1 + include/linux/pid.h | 43 +- include/linux/pkt_cls.h | 8 +- include/linux/pkt_sched.h | 52 +- include/linux/pm.h | 42 +- include/linux/pnp.h | 4 +- include/linux/poll.h | 8 +- include/linux/posix-timers.h | 38 +- include/linux/posix_acl.h | 1 - include/linux/prctl.h | 1 + include/linux/prio_tree.h | 12 + include/linux/proc_fs.h | 14 +- include/linux/profile.h | 76 +- include/linux/ptrace.h | 1 + include/linux/quota.h | 1 - include/linux/quotaio_v2.h | 44 +- include/linux/raid/linear.h | 4 +- include/linux/raid/md.h | 4 +- include/linux/raid/md_k.h | 16 +- include/linux/raid/md_p.h | 4 +- include/linux/raid/multipath.h | 3 +- include/linux/raid/raid1.h | 1 + include/linux/random.h | 4 - include/linux/rbtree.h | 4 +- include/linux/rcfs.h | 28 +- include/linux/rcupdate.h | 160 +- include/linux/reiserfs_fs.h | 123 +- include/linux/reiserfs_fs_i.h | 2 +- include/linux/reiserfs_fs_sb.h | 47 +- include/linux/resource.h | 6 + include/linux/rmap.h | 19 +- include/linux/romfs_fs.h | 18 +- include/linux/rtnetlink.h | 153 +- include/linux/sched.h | 530 +- include/linux/sctp.h | 6 +- include/linux/security.h | 114 +- include/linux/serial.h | 2 + include/linux/serial_core.h | 28 +- include/linux/serial_reg.h | 279 +- include/linux/serio.h | 66 +- include/linux/shm.h | 2 + include/linux/shmem_fs.h | 14 +- include/linux/signal.h | 2 +- include/linux/skbuff.h | 43 +- include/linux/slab.h | 17 +- include/linux/smb_fs.h | 2 +- include/linux/smb_mount.h | 5 +- include/linux/smp_lock.h | 62 +- include/linux/socket.h | 5 +- include/linux/sonypi.h | 41 +- include/linux/spinlock.h | 303 +- include/linux/stddef.h | 6 + include/linux/sunrpc/auth_gss.h | 2 - include/linux/sunrpc/cache.h | 5 +- include/linux/sunrpc/gss_asn1.h | 1 - include/linux/sunrpc/sched.h | 2 + include/linux/sunrpc/svc.h | 10 + include/linux/suspend.h | 20 - include/linux/swap.h | 24 +- include/linux/swapops.h | 3 +- include/linux/syscalls.h | 25 +- include/linux/sysctl.h | 17 + include/linux/sysfs.h | 19 + include/linux/sysrq.h | 46 +- include/linux/sysv_fs.h | 131 +- include/linux/taskdelays.h | 25 + include/linux/tcp.h | 66 +- include/linux/threads.h | 2 +- include/linux/ticable.h | 2 + include/linux/time.h | 269 +- include/linux/times.h | 54 +- include/linux/timex.h | 182 +- include/linux/topology.h | 74 +- include/linux/tty.h | 42 +- include/linux/tty_driver.h | 6 +- include/linux/tty_ldisc.h | 12 +- include/linux/types.h | 15 + include/linux/udf_fs_i.h | 2 +- include/linux/ufs_fs.h | 539 +- include/linux/ufs_fs_i.h | 4 +- include/linux/umem.h | 14 +- include/linux/usb.h | 42 +- include/linux/usb_ch9.h | 8 +- include/linux/usb_gadget.h | 6 - include/linux/usbdevice_fs.h | 35 - include/linux/videodev.h | 16 +- include/linux/videodev2.h | 18 +- include/linux/vt_kern.h | 2 +- include/linux/wait.h | 131 +- include/linux/wireless.h | 64 +- include/linux/workqueue.h | 2 + include/linux/writeback.h | 32 +- include/linux/xattr.h | 16 + include/linux/xfrm.h | 1 + include/math-emu/op-common.h | 6 +- include/media/audiochip.h | 2 +- include/media/id.h | 1 - include/media/ir-common.h | 2 + include/media/saa6752hs.h | 6 +- include/media/saa7146.h | 12 +- include/media/saa7146_vv.h | 7 +- include/media/tuner.h | 25 +- include/media/video-buf.h | 64 +- include/mtd/mtd-abi.h | 7 +- include/net/addrconf.h | 7 +- include/net/af_unix.h | 7 +- include/net/bluetooth/bluetooth.h | 1 + include/net/bluetooth/hci.h | 42 +- include/net/bluetooth/hci_core.h | 78 +- include/net/bluetooth/l2cap.h | 2 + include/net/dn_neigh.h | 1 - include/net/dn_nsp.h | 2 +- include/net/dst.h | 17 +- include/net/gen_stats.h | 3 + include/net/if_inet6.h | 2 + include/net/inet_ecn.h | 43 +- include/net/ip.h | 5 +- include/net/ip6_fib.h | 1 + include/net/ip6_route.h | 16 +- include/net/ip_fib.h | 39 +- include/net/ip_vs.h | 4 +- include/net/ipcomp.h | 3 +- include/net/ipv6.h | 13 +- include/net/irda/ircomm_tty_attach.h | 1 - include/net/irda/irias_object.h | 3 +- include/net/irda/irlmp.h | 3 +- include/net/irda/timer.h | 10 +- include/net/iw_handler.h | 57 +- include/net/llc_pdu.h | 10 +- include/net/ndisc.h | 5 + include/net/neighbour.h | 106 +- include/net/pkt_act.h | 22 +- include/net/pkt_cls.h | 278 +- include/net/pkt_sched.h | 277 +- include/net/route.h | 5 - include/net/sctp/sctp.h | 9 +- include/net/sctp/structs.h | 6 + include/net/sctp/ulpevent.h | 3 + include/net/sctp/user.h | 6 +- include/net/sock.h | 41 +- include/net/tc_act/tc_gact.h | 2 +- include/net/tcp.h | 427 +- include/net/tcp_ecn.h | 2 +- include/net/udp.h | 2 + include/net/xfrm.h | 122 +- include/pcmcia/bulkmem.h | 148 - include/pcmcia/cistpl.h | 10 +- include/pcmcia/cs.h | 15 +- include/pcmcia/cs_types.h | 3 - include/pcmcia/ss.h | 14 +- include/rxrpc/call.h | 6 +- include/rxrpc/connection.h | 12 +- include/rxrpc/packet.h | 26 +- include/rxrpc/peer.h | 2 +- include/rxrpc/rxrpc.h | 9 +- include/rxrpc/transport.h | 2 - include/rxrpc/types.h | 2 + include/scsi/scsi.h | 29 +- include/scsi/scsi_device.h | 76 +- include/scsi/scsi_devinfo.h | 2 + include/scsi/scsi_driver.h | 1 + include/scsi/scsi_eh.h | 36 +- include/scsi/scsi_host.h | 21 +- include/scsi/scsi_ioctl.h | 2 + include/scsi/scsi_transport.h | 24 +- include/scsi/scsi_transport_fc.h | 61 +- include/scsi/scsi_transport_spi.h | 95 +- include/sound/ac97_codec.h | 59 +- include/sound/asequencer.h | 4 +- include/sound/asound.h | 1 - include/sound/control.h | 3 +- include/sound/core.h | 27 +- include/sound/cs46xx.h | 23 +- include/sound/driver.h | 2 - include/sound/emu10k1.h | 88 +- include/sound/es1688.h | 2 - include/sound/hdsp.h | 14 +- include/sound/info.h | 5 +- include/sound/initval.h | 33 - include/sound/memalloc.h | 21 +- include/sound/opl3.h | 5 + include/sound/pcm.h | 62 +- include/sound/pcm_oss.h | 10 +- include/sound/seq_kernel.h | 15 +- include/sound/soundfont.h | 1 + include/sound/timer.h | 3 +- include/sound/trident.h | 1 - include/sound/version.h | 4 +- include/sound/vx_core.h | 8 + include/sound/ymfpci.h | 3 +- include/video/kyro.h | 2 +- include/video/mach64.h | 351 +- include/video/neomagic.h | 7 +- include/video/radeon.h | 3 +- include/video/sstfb.h | 11 +- include/video/tdfx.h | 3 +- include/video/tgafb.h | 6 +- include/video/vga.h | 46 +- init/Kconfig | 211 +- init/do_mounts.c | 5 +- init/do_mounts_devfs.c | 1 - init/do_mounts_rd.c | 37 +- init/initramfs.c | 12 +- init/main.c | 163 +- ipc/mqueue.c | 14 +- ipc/msg.c | 249 +- ipc/sem.c | 101 +- ipc/shm.c | 60 +- ipc/util.c | 183 +- ipc/util.h | 25 +- kernel/Makefile | 8 +- kernel/acct.c | 35 +- kernel/audit.c | 15 +- kernel/auditsc.c | 9 +- kernel/capability.c | 7 +- kernel/ckrm/Makefile | 11 +- kernel/ckrm/ckrm.c | 284 +- kernel/ckrm/ckrm_listenaq.c | 37 +- kernel/ckrm/ckrm_numtasks.c | 163 +- kernel/ckrm/ckrm_tc.c | 3 + kernel/ckrm/ckrmutils.c | 67 +- kernel/ckrm/rbce/rbce_fs.c | 2 +- kernel/ckrm/rbce/rbcemod.c | 27 +- kernel/ckrm/rbce/rbcemod_ext.c | 4 +- kernel/compat.c | 201 +- kernel/cpu.c | 49 +- kernel/exec_domain.c | 122 +- kernel/exit.c | 537 +- kernel/fork.c | 364 +- kernel/futex.c | 27 +- kernel/itimer.c | 1 + kernel/kallsyms.c | 194 +- kernel/kmod.c | 27 +- kernel/kprobes.c | 6 +- kernel/module.c | 228 +- kernel/panic.c | 54 +- kernel/params.c | 405 +- kernel/pid.c | 236 +- kernel/posix-timers.c | 159 +- kernel/power/Kconfig | 61 +- kernel/power/Makefile | 7 +- kernel/power/console.c | 3 + kernel/power/disk.c | 127 +- kernel/power/main.c | 31 +- kernel/power/pm.c | 31 - kernel/power/power.h | 19 +- kernel/power/poweroff.c | 2 +- kernel/power/process.c | 8 +- kernel/power/swsusp.c | 1404 +- kernel/printk.c | 39 +- kernel/profile.c | 536 +- kernel/ptrace.c | 83 +- kernel/rcupdate.c | 313 +- kernel/resource.c | 24 +- kernel/sched.c | 2887 ++-- kernel/signal.c | 390 +- kernel/softirq.c | 23 +- kernel/stop_machine.c | 7 +- kernel/sys.c | 309 +- kernel/sysctl.c | 79 +- kernel/time.c | 117 +- kernel/timer.c | 191 +- kernel/user.c | 20 +- kernel/workqueue.c | 22 +- lib/Kconfig | 18 + lib/Kconfig.debug | 37 +- lib/Makefile | 16 +- lib/bitmap.c | 84 +- lib/dec_and_lock.c | 4 +- lib/idr.c | 189 +- lib/inflate.c | 40 +- lib/iomap.c | 8 +- lib/kobject.c | 179 +- lib/kref.c | 29 +- lib/parser.c | 1 + lib/radix-tree.c | 6 +- lib/rbtree.c | 13 + lib/rwsem.c | 8 +- lib/zlib_inflate/Makefile | 2 +- lib/zlib_inflate/infblock.c | 2 +- lib/zlib_inflate/inflate.c | 143 - lib/zlib_inflate/inftrees.c | 34 +- lib/zlib_inflate/inftrees.h | 1 + mm/Makefile | 7 +- mm/bootmem.c | 35 +- mm/fadvise.c | 1 + mm/filemap.c | 580 +- mm/fremap.c | 5 +- mm/highmem.c | 26 +- mm/hugetlb.c | 6 +- mm/madvise.c | 1 + mm/memory.c | 91 +- mm/mempolicy.c | 139 +- mm/mempool.c | 1 + mm/mincore.c | 1 + mm/mlock.c | 73 +- mm/mmap.c | 231 +- mm/mprotect.c | 15 +- mm/mremap.c | 12 +- mm/msync.c | 1 + mm/nommu.c | 32 +- mm/oom_kill.c | 23 +- mm/page-writeback.c | 12 +- mm/page_alloc.c | 416 +- mm/prio_tree.c | 71 +- mm/readahead.c | 42 +- mm/rmap.c | 314 +- mm/shmem.c | 586 +- mm/slab.c | 446 +- mm/swap_state.c | 4 +- mm/swapfile.c | 75 +- mm/thrash.c | 10 +- mm/tiny-shmem.c | 2 - mm/truncate.c | 13 +- mm/vmalloc.c | 27 +- mm/vmscan.c | 115 +- net/802/fc.c | 32 + net/802/fddi.c | 41 + net/802/hippi.c | 89 + net/802/tr.c | 38 + net/8021q/vlan.c | 92 +- net/8021q/vlan.h | 2 + net/8021q/vlan_dev.c | 48 +- net/Kconfig | 35 +- net/Makefile | 6 +- net/appletalk/Makefile | 3 +- net/appletalk/atalk_proc.c | 13 - net/appletalk/ddp.c | 19 +- net/appletalk/sysctl_net_atalk.c | 18 +- net/atm/br2684.c | 2 +- net/atm/clip.c | 319 +- net/atm/common.c | 5 +- net/atm/common.h | 11 - net/atm/ipcommon.h | 3 - net/atm/lec.h | 1 - net/atm/mpc.c | 11 +- net/atm/mpoa_proc.c | 2 +- net/atm/signaling.c | 23 +- net/atm/svc.c | 142 +- net/ax25/af_ax25.c | 21 +- net/ax25/ax25_in.c | 1 - net/ax25/ax25_route.c | 16 - net/bluetooth/af_bluetooth.c | 8 +- net/bluetooth/bnep/core.c | 2 +- net/bluetooth/cmtp/capi.c | 1 - net/bluetooth/hci_conn.c | 31 +- net/bluetooth/hci_core.c | 50 +- net/bluetooth/hci_event.c | 97 +- net/bluetooth/hci_sock.c | 14 +- net/bluetooth/hci_sysfs.c | 15 +- net/bluetooth/l2cap.c | 220 +- net/bluetooth/lib.c | 6 +- net/bluetooth/rfcomm/sock.c | 15 +- net/bluetooth/rfcomm/tty.c | 14 +- net/bridge/br_if.c | 4 +- net/bridge/br_input.c | 62 +- net/bridge/br_netfilter.c | 449 +- net/bridge/br_notify.c | 4 +- net/bridge/br_private.h | 2 +- net/bridge/netfilter/ebt_802_3.c | 2 +- net/bridge/netfilter/ebt_among.c | 61 +- net/bridge/netfilter/ebt_arp.c | 55 +- net/bridge/netfilter/ebt_arpreply.c | 34 +- net/bridge/netfilter/ebt_dnat.c | 3 +- net/bridge/netfilter/ebt_ip.c | 33 +- net/bridge/netfilter/ebt_log.c | 66 +- net/bridge/netfilter/ebt_redirect.c | 7 +- net/bridge/netfilter/ebt_snat.c | 3 +- net/bridge/netfilter/ebt_stp.c | 22 +- net/bridge/netfilter/ebt_vlan.c | 16 +- net/bridge/netfilter/ebtables.c | 12 +- net/compat.c | 22 +- net/core/Makefile | 2 +- net/core/dev.c | 410 +- net/core/dev_mcast.c | 2 +- net/core/dst.c | 7 +- net/core/dv.c | 7 +- net/core/ethtool.c | 31 +- net/core/filter.c | 21 +- net/core/gen_estimator.c | 46 + net/core/gen_stats.c | 91 +- net/core/link_watch.c | 2 +- net/core/neighbour.c | 916 +- net/core/net-sysfs.c | 12 +- net/core/netfilter.c | 37 +- net/core/netpoll.c | 88 +- net/core/pktgen.c | 125 +- net/core/rtnetlink.c | 157 +- net/core/scm.c | 4 +- net/core/skbuff.c | 12 +- net/core/sock.c | 62 +- net/core/utils.c | 112 +- net/core/wireless.c | 215 +- net/decnet/Kconfig | 11 - net/decnet/af_decnet.c | 8 +- net/decnet/dn_dev.c | 188 +- net/decnet/dn_neigh.c | 226 +- net/decnet/dn_nsp_in.c | 1 + net/decnet/dn_nsp_out.c | 4 +- net/decnet/dn_route.c | 70 +- net/econet/af_econet.c | 12 +- net/ethernet/eth.c | 67 +- net/ipv4/Kconfig | 61 +- net/ipv4/Makefile | 7 +- net/ipv4/af_inet.c | 144 +- net/ipv4/ah4.c | 17 +- net/ipv4/arp.c | 249 +- net/ipv4/devinet.c | 112 +- net/ipv4/esp4.c | 55 +- net/ipv4/fib_frontend.c | 6 +- net/ipv4/fib_hash.c | 843 +- net/ipv4/fib_rules.c | 27 +- net/ipv4/fib_semantics.c | 411 +- net/ipv4/icmp.c | 50 +- net/ipv4/igmp.c | 102 +- net/ipv4/ip_fragment.c | 54 +- net/ipv4/ip_gre.c | 33 +- net/ipv4/ip_input.c | 3 +- net/ipv4/ip_options.c | 2 + net/ipv4/ip_output.c | 120 +- net/ipv4/ip_sockglue.c | 5 +- net/ipv4/ipcomp.c | 221 +- net/ipv4/ipconfig.c | 20 +- net/ipv4/ipip.c | 14 +- net/ipv4/ipvs/ip_vs_conn.c | 8 +- net/ipv4/ipvs/ip_vs_core.c | 118 +- net/ipv4/ipvs/ip_vs_ctl.c | 41 +- net/ipv4/ipvs/ip_vs_ftp.c | 3 +- net/ipv4/ipvs/ip_vs_lblc.c | 2 +- net/ipv4/ipvs/ip_vs_lblcr.c | 4 +- net/ipv4/ipvs/ip_vs_proto.c | 42 +- net/ipv4/ipvs/ip_vs_proto_ah.c | 9 +- net/ipv4/ipvs/ip_vs_proto_esp.c | 9 +- net/ipv4/ipvs/ip_vs_proto_icmp.c | 35 +- net/ipv4/ipvs/ip_vs_proto_tcp.c | 44 +- net/ipv4/ipvs/ip_vs_proto_udp.c | 42 +- net/ipv4/ipvs/ip_vs_sync.c | 28 +- net/ipv4/ipvs/ip_vs_xmit.c | 30 +- net/ipv4/netfilter/Kconfig | 288 +- net/ipv4/netfilter/Makefile | 15 +- net/ipv4/netfilter/arp_tables.c | 24 +- net/ipv4/netfilter/ip_conntrack_amanda.c | 5 +- net/ipv4/netfilter/ip_conntrack_core.c | 419 +- net/ipv4/netfilter/ip_conntrack_ftp.c | 47 +- net/ipv4/netfilter/ip_conntrack_irc.c | 51 +- .../netfilter/ip_conntrack_proto_generic.c | 28 +- net/ipv4/netfilter/ip_conntrack_proto_icmp.c | 187 +- net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 1059 +- net/ipv4/netfilter/ip_conntrack_proto_udp.c | 96 +- net/ipv4/netfilter/ip_conntrack_standalone.c | 495 +- net/ipv4/netfilter/ip_conntrack_tftp.c | 20 +- net/ipv4/netfilter/ip_fw_compat.c | 2 +- net/ipv4/netfilter/ip_fw_compat_masq.c | 11 +- net/ipv4/netfilter/ip_nat_core.c | 174 +- net/ipv4/netfilter/ip_nat_ftp.c | 52 +- net/ipv4/netfilter/ip_nat_helper.c | 30 +- net/ipv4/netfilter/ip_nat_irc.c | 45 +- net/ipv4/netfilter/ip_nat_proto_icmp.c | 6 +- net/ipv4/netfilter/ip_nat_proto_tcp.c | 10 +- net/ipv4/netfilter/ip_nat_proto_udp.c | 10 +- net/ipv4/netfilter/ip_nat_proto_unknown.c | 6 +- net/ipv4/netfilter/ip_nat_rule.c | 7 +- net/ipv4/netfilter/ip_nat_snmp_basic.c | 6 +- net/ipv4/netfilter/ip_nat_standalone.c | 29 +- net/ipv4/netfilter/ip_nat_tftp.c | 35 +- net/ipv4/netfilter/ip_queue.c | 13 +- net/ipv4/netfilter/ip_tables.c | 79 +- net/ipv4/netfilter/ipchains_core.c | 44 +- net/ipv4/netfilter/ipfwadm_core.c | 44 +- net/ipv4/netfilter/ipt_ECN.c | 31 +- net/ipv4/netfilter/ipt_LOG.c | 170 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 93 +- net/ipv4/netfilter/ipt_NOTRACK.c | 3 +- net/ipv4/netfilter/ipt_REJECT.c | 73 +- net/ipv4/netfilter/ipt_ULOG.c | 41 +- net/ipv4/netfilter/ipt_ah.c | 11 +- net/ipv4/netfilter/ipt_conntrack.c | 2 +- net/ipv4/netfilter/ipt_ecn.c | 17 +- net/ipv4/netfilter/ipt_esp.c | 11 +- net/ipv4/netfilter/ipt_helper.c | 1 + net/ipv4/netfilter/ipt_mac.c | 2 +- net/ipv4/netfilter/ipt_multiport.c | 19 +- net/ipv4/netfilter/ipt_recent.c | 13 +- net/ipv4/netfilter/ipt_state.c | 4 +- net/ipv4/netfilter/ipt_tcpmss.c | 42 +- net/ipv4/netfilter/iptable_filter.c | 7 +- net/ipv4/proc.c | 2 +- net/ipv4/raw.c | 55 +- net/ipv4/route.c | 179 +- net/ipv4/sysctl_net_ipv4.c | 12 +- net/ipv4/tcp.c | 254 +- net/ipv4/tcp_diag.c | 406 +- net/ipv4/tcp_input.c | 406 +- net/ipv4/tcp_ipv4.c | 65 +- net/ipv4/tcp_minisocks.c | 30 +- net/ipv4/tcp_output.c | 328 +- net/ipv4/tcp_timer.c | 39 +- net/ipv4/udp.c | 51 +- net/ipv4/xfrm4_input.c | 8 +- net/ipv4/xfrm4_output.c | 12 +- net/ipv4/xfrm4_policy.c | 21 +- net/ipv4/xfrm4_tunnel.c | 14 +- net/ipv6/Kconfig | 17 +- net/ipv6/Makefile | 3 +- net/ipv6/addrconf.c | 336 +- net/ipv6/af_inet6.c | 184 +- net/ipv6/ah6.c | 29 +- net/ipv6/anycast.c | 75 +- net/ipv6/datagram.c | 19 +- net/ipv6/esp6.c | 52 +- net/ipv6/exthdrs.c | 3 + net/ipv6/exthdrs_core.c | 27 +- net/ipv6/icmp.c | 25 +- net/ipv6/ip6_fib.c | 31 +- net/ipv6/ip6_flowlabel.c | 5 +- net/ipv6/ip6_input.c | 3 +- net/ipv6/ip6_output.c | 121 +- net/ipv6/ip6_tunnel.c | 28 +- net/ipv6/ipcomp6.c | 229 +- net/ipv6/ipv6_syms.c | 4 - net/ipv6/mcast.c | 73 +- net/ipv6/ndisc.c | 164 +- net/ipv6/netfilter/Kconfig | 9 + net/ipv6/netfilter/Makefile | 1 + net/ipv6/netfilter/ip6_queue.c | 15 +- net/ipv6/netfilter/ip6_tables.c | 254 +- net/ipv6/netfilter/ip6t_LOG.c | 282 +- net/ipv6/netfilter/ip6t_MARK.c | 2 +- net/ipv6/netfilter/ip6t_ah.c | 269 +- net/ipv6/netfilter/ip6t_dst.c | 103 +- net/ipv6/netfilter/ip6t_esp.c | 91 +- net/ipv6/netfilter/ip6t_eui64.c | 11 +- net/ipv6/netfilter/ip6t_frag.c | 111 +- net/ipv6/netfilter/ip6t_hbh.c | 101 +- net/ipv6/netfilter/ip6t_hl.c | 2 +- net/ipv6/netfilter/ip6t_ipv6header.c | 33 +- net/ipv6/netfilter/ip6t_length.c | 3 +- net/ipv6/netfilter/ip6t_limit.c | 3 +- net/ipv6/netfilter/ip6t_mac.c | 5 +- net/ipv6/netfilter/ip6t_mark.c | 3 +- net/ipv6/netfilter/ip6t_multiport.c | 39 +- net/ipv6/netfilter/ip6t_owner.c | 3 +- net/ipv6/netfilter/ip6t_physdev.c | 3 +- net/ipv6/netfilter/ip6t_rt.c | 124 +- net/ipv6/netfilter/ip6table_filter.c | 3 +- net/ipv6/raw.c | 71 +- net/ipv6/reassembly.c | 49 +- net/ipv6/route.c | 247 +- net/ipv6/sit.c | 16 +- net/ipv6/tcp_ipv6.c | 144 +- net/ipv6/udp.c | 27 +- net/ipv6/xfrm6_input.c | 21 +- net/ipv6/xfrm6_output.c | 22 +- net/ipv6/xfrm6_policy.c | 32 +- net/ipv6/xfrm6_state.c | 6 +- net/ipv6/xfrm6_tunnel.c | 72 +- net/ipx/af_ipx.c | 2 + net/irda/af_irda.c | 2 +- net/irda/ircomm/ircomm_tty.c | 28 +- net/irda/ircomm/ircomm_tty_attach.c | 186 +- net/irda/irias_object.c | 18 +- net/irda/irlan/irlan_client.c | 4 +- net/irda/irlan/irlan_common.c | 7 +- net/irda/irlan/irlan_eth.c | 10 +- net/irda/irlan/irlan_provider.c | 2 +- net/irda/irlap_event.c | 38 +- net/irda/irlmp.c | 108 +- net/irda/irmod.c | 2 +- net/irda/irnet/irnet_ppp.c | 1 + net/irda/irqueue.c | 8 +- net/irda/qos.c | 11 - net/irda/timer.c | 21 +- net/key/af_key.c | 24 +- net/llc/af_llc.c | 1 - net/llc/llc_input.c | 2 +- net/llc/llc_output.c | 7 +- net/netlink/af_netlink.c | 526 +- net/netlink/netlink_dev.c | 2 +- net/netrom/af_netrom.c | 2 - net/netrom/nr_route.c | 2 +- net/packet/af_packet.c | 40 +- net/rose/af_rose.c | 2 - net/rxrpc/call.c | 65 +- net/rxrpc/connection.c | 37 +- net/rxrpc/main.c | 2 +- net/rxrpc/peer.c | 4 +- net/rxrpc/rxrpc_syms.c | 15 - net/rxrpc/transport.c | 12 +- net/sched/Kconfig | 39 +- net/sched/Makefile | 9 +- net/sched/act_api.c | 78 +- net/sched/cls_api.c | 37 +- net/sched/cls_fw.c | 372 +- net/sched/cls_route.c | 60 +- net/sched/cls_rsvp.c | 5 +- net/sched/cls_rsvp.h | 54 +- net/sched/cls_rsvp6.c | 5 +- net/sched/cls_tcindex.c | 56 +- net/sched/cls_u32.c | 171 +- net/sched/estimator.c | 12 +- net/sched/gact.c | 42 +- net/sched/police.c | 67 +- net/sched/sch_api.c | 193 +- net/sched/sch_atm.c | 42 +- net/sched/sch_cbq.c | 147 +- net/sched/sch_dsmark.c | 11 +- net/sched/sch_fifo.c | 28 +- net/sched/sch_generic.c | 122 +- net/sched/sch_gred.c | 29 +- net/sched/sch_hfsc.c | 422 +- net/sched/sch_htb.c | 78 +- net/sched/sch_ingress.c | 30 +- net/sched/sch_netem.c | 870 +- net/sched/sch_prio.c | 13 +- net/sched/sch_red.c | 62 +- net/sched/sch_sfq.c | 17 +- net/sched/sch_tbf.c | 20 +- net/sched/sch_teql.c | 12 +- net/sctp/associola.c | 15 +- net/sctp/endpointola.c | 2 +- net/sctp/ipv6.c | 35 +- net/sctp/outqueue.c | 25 +- net/sctp/protocol.c | 52 +- net/sctp/sm_make_chunk.c | 31 + net/sctp/sm_statefuns.c | 59 + net/sctp/socket.c | 87 +- net/sctp/transport.c | 27 +- net/sctp/ulpevent.c | 42 +- net/socket.c | 6 +- net/sunrpc/auth_gss/Makefile | 4 + net/sunrpc/auth_gss/auth_gss.c | 4 +- net/sunrpc/auth_gss/gss_generic_token.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 2 - net/sunrpc/cache.c | 5 +- net/sunrpc/clnt.c | 41 +- net/sunrpc/rpc_pipe.c | 6 +- net/sunrpc/sched.c | 4 +- net/sunrpc/sunrpc_syms.c | 1 + net/sunrpc/svc.c | 9 +- net/sunrpc/svcauth.c | 62 +- net/sunrpc/svcauth_unix.c | 40 +- net/sunrpc/xprt.c | 8 +- net/unix/af_unix.c | 52 +- net/wanrouter/af_wanpipe.c | 1 - net/x25/af_x25.c | 3 +- net/x25/x25_dev.c | 4 +- net/x25/x25_proc.c | 7 +- net/xfrm/Kconfig | 4 - net/xfrm/xfrm_export.c | 11 - net/xfrm/xfrm_policy.c | 62 +- net/xfrm/xfrm_state.c | 60 +- net/xfrm/xfrm_user.c | 68 +- scripts/Makefile | 17 +- scripts/Makefile.build | 124 +- scripts/Makefile.clean | 46 +- scripts/Makefile.lib | 79 +- scripts/Makefile.modinst | 7 +- scripts/Makefile.modpost | 6 +- scripts/basic/Makefile | 4 +- scripts/basic/docproc.c | 33 +- scripts/basic/fixdep.c | 29 +- scripts/basic/split-include.c | 2 +- scripts/binoffset.c | 12 +- scripts/checkstack.pl | 3 + scripts/conmakehash.c | 2 +- scripts/genksyms/Makefile | 4 +- scripts/genksyms/genksyms.c | 15 + scripts/kallsyms.c | 577 +- scripts/kconfig/Makefile | 24 +- scripts/kconfig/conf.c | 6 +- scripts/kconfig/confdata.c | 31 +- scripts/kconfig/gconf.c | 5 +- scripts/kconfig/lkc.h | 3 - scripts/kconfig/mconf.c | 165 +- scripts/kconfig/menu.c | 1 - scripts/kconfig/symbol.c | 2 +- scripts/kconfig/zconf.tab.c_shipped | 2 + scripts/kconfig/zconf.y | 2 + scripts/kernel-doc | 188 +- scripts/lxdialog/Makefile | 8 +- scripts/lxdialog/dialog.h | 3 + scripts/lxdialog/menubox.c | 9 + scripts/mksysmap | 2 +- scripts/mod/Makefile | 4 +- scripts/mod/file2alias.c | 19 +- scripts/mod/modpost.c | 115 +- scripts/mod/modpost.h | 12 +- scripts/mod/sumversion.c | 98 +- scripts/package/Makefile | 6 +- scripts/package/builddeb | 2 +- scripts/package/mkspec | 20 +- scripts/patch-kernel | 113 +- scripts/reference_init.pl | 3 + scripts/ver_linux | 7 +- security/Kconfig | 44 +- security/Makefile | 2 + security/capability.c | 1 + security/commoncap.c | 42 +- security/dummy.c | 21 +- security/security.c | 80 +- security/selinux/Kconfig | 15 + security/selinux/hooks.c | 291 +- security/selinux/include/avc.h | 1 - security/selinux/include/netif.h | 11 +- security/selinux/include/objsec.h | 1 - security/selinux/netif.c | 120 +- security/selinux/selinuxfs.c | 275 +- security/selinux/ss/avtab.c | 17 +- security/selinux/ss/avtab.h | 3 + security/selinux/ss/policydb.h | 1 - security/selinux/ss/services.c | 3 + security/selinux/ss/sidtab.c | 21 +- sound/Kconfig | 2 +- sound/arm/Kconfig | 9 +- sound/arm/sa11xx-uda1341.c | 19 +- sound/core/Kconfig | 75 +- sound/core/control.c | 51 +- sound/core/device.c | 4 +- sound/core/hwdep.c | 40 +- sound/core/info.c | 70 +- sound/core/info_oss.c | 12 - sound/core/init.c | 9 +- sound/core/ioctl32/hwdep32.c | 2 +- sound/core/ioctl32/ioctl32.c | 10 +- sound/core/ioctl32/ioctl32.h | 6 +- sound/core/ioctl32/pcm32.c | 150 +- sound/core/memalloc.c | 421 +- sound/core/memory.c | 84 +- sound/core/oss/mixer_oss.c | 53 +- sound/core/oss/pcm_oss.c | 67 +- sound/core/oss/pcm_plugin.c | 133 +- sound/core/oss/pcm_plugin.h | 2 +- sound/core/oss/route.c | 2 +- sound/core/pcm.c | 26 +- sound/core/pcm_lib.c | 78 +- sound/core/pcm_memory.c | 122 +- sound/core/pcm_misc.c | 711 +- sound/core/pcm_native.c | 1014 +- sound/core/pcm_timer.c | 13 +- sound/core/rawmidi.c | 67 +- sound/core/seq/Makefile | 58 +- sound/core/seq/instr/Makefile | 34 +- sound/core/seq/instr/ainstr_fm.c | 2 - sound/core/seq/instr/ainstr_gf1.c | 4 +- sound/core/seq/instr/ainstr_iw.c | 8 +- sound/core/seq/instr/ainstr_simple.c | 2 - sound/core/seq/oss/seq_oss.c | 23 +- sound/core/seq/oss/seq_oss_init.c | 4 +- sound/core/seq/oss/seq_oss_ioctl.c | 74 +- sound/core/seq/oss/seq_oss_midi.c | 2 +- sound/core/seq/oss/seq_oss_readq.c | 49 +- sound/core/seq/oss/seq_oss_readq.h | 9 +- sound/core/seq/oss/seq_oss_rw.c | 116 +- sound/core/seq/oss/seq_oss_synth.c | 8 +- sound/core/seq/oss/seq_oss_timer.c | 4 +- sound/core/seq/oss/seq_oss_writeq.c | 2 +- sound/core/seq/seq.c | 24 +- sound/core/seq/seq_clientmgr.c | 85 +- sound/core/seq/seq_device.c | 46 +- sound/core/seq/seq_dummy.c | 29 +- sound/core/seq/seq_fifo.c | 2 +- sound/core/seq/seq_instr.c | 11 +- sound/core/seq/seq_memory.c | 6 +- sound/core/seq/seq_midi.c | 10 +- sound/core/seq/seq_midi_emul.c | 2 - sound/core/seq/seq_midi_event.c | 2 +- sound/core/seq/seq_ports.c | 4 +- sound/core/seq/seq_prioq.c | 2 +- sound/core/seq/seq_queue.c | 2 +- sound/core/seq/seq_timer.c | 2 +- sound/core/seq/seq_virmidi.c | 46 +- sound/core/sgbuf.c | 11 +- sound/core/sound.c | 42 +- sound/core/timer.c | 67 +- sound/drivers/Kconfig | 48 +- sound/drivers/dummy.c | 117 +- sound/drivers/mpu401/mpu401.c | 34 +- sound/drivers/mpu401/mpu401_uart.c | 26 +- sound/drivers/mtpav.c | 16 +- sound/drivers/opl3/opl3_lib.c | 148 +- sound/drivers/opl3/opl3_midi.c | 14 +- sound/drivers/opl3/opl3_oss.c | 16 +- sound/drivers/opl3/opl3_seq.c | 9 +- sound/drivers/opl3/opl3_synth.c | 6 +- sound/drivers/opl4/Makefile | 2 +- sound/drivers/opl4/opl4_lib.c | 59 +- sound/drivers/opl4/opl4_local.h | 1 - sound/drivers/opl4/opl4_mixer.c | 12 +- sound/drivers/opl4/opl4_proc.c | 8 +- sound/drivers/opl4/opl4_seq.c | 10 +- sound/drivers/opl4/opl4_synth.c | 35 +- sound/drivers/serial-u16550.c | 57 +- sound/drivers/virmidi.c | 18 +- sound/drivers/vx/vx_core.c | 11 +- sound/drivers/vx/vx_hwdep.c | 4 +- sound/drivers/vx/vx_mixer.c | 53 +- sound/drivers/vx/vx_pcm.c | 37 +- sound/drivers/vx/vx_uer.c | 15 +- sound/i2c/cs8427.c | 26 +- sound/i2c/i2c.c | 10 +- sound/i2c/l3/uda1341.c | 24 +- sound/i2c/other/ak4117.c | 10 +- sound/i2c/other/ak4xxx-adda.c | 12 +- sound/i2c/tea6330t.c | 14 +- sound/isa/Kconfig | 197 +- sound/isa/ad1816a/ad1816a.c | 36 +- sound/isa/ad1816a/ad1816a_lib.c | 18 +- sound/isa/ad1848/ad1848.c | 27 +- sound/isa/ad1848/ad1848_lib.c | 16 +- sound/isa/als100.c | 36 +- sound/isa/azt2320.c | 39 +- sound/isa/cmi8330.c | 41 +- sound/isa/cs423x/cs4231.c | 33 +- sound/isa/cs423x/cs4231_lib.c | 22 +- sound/isa/cs423x/cs4236.c | 47 +- sound/isa/cs423x/cs4236_lib.c | 26 +- sound/isa/dt019x.c | 33 +- sound/isa/es1688/es1688.c | 28 +- sound/isa/es1688/es1688_lib.c | 15 +- sound/isa/es18xx.c | 57 +- sound/isa/gus/Makefile | 6 +- sound/isa/gus/gus_dram.c | 10 +- sound/isa/gus/gus_instr.c | 18 +- sound/isa/gus/gus_irq.c | 4 +- sound/isa/gus/gus_main.c | 10 +- sound/isa/gus/gus_mem.c | 2 +- sound/isa/gus/gus_mem_proc.c | 12 +- sound/isa/gus/gus_mixer.c | 10 +- sound/isa/gus/gus_pcm.c | 38 +- sound/isa/gus/gus_synth.c | 2 +- sound/isa/gus/gus_timer.c | 6 +- sound/isa/gus/gus_uart.c | 12 +- sound/isa/gus/gusclassic.c | 34 +- sound/isa/gus/gusextreme.c | 46 +- sound/isa/gus/gusmax.c | 34 +- sound/isa/gus/interwave.c | 87 +- sound/isa/opl3sa2.c | 66 +- sound/isa/opti9xx/opti92x-ad1848.c | 57 +- sound/isa/sb/emu8000.c | 18 +- sound/isa/sb/emu8000_callback.c | 20 +- sound/isa/sb/emu8000_local.h | 2 - sound/isa/sb/emu8000_patch.c | 2 +- sound/isa/sb/emu8000_pcm.c | 4 +- sound/isa/sb/emu8000_synth.c | 1 - sound/isa/sb/es968.c | 26 +- sound/isa/sb/sb16.c | 50 +- sound/isa/sb/sb16_csp.c | 17 +- sound/isa/sb/sb16_main.c | 18 +- sound/isa/sb/sb8.c | 26 +- sound/isa/sb/sb8_main.c | 2 - sound/isa/sb/sb8_midi.c | 16 +- sound/isa/sb/sb_common.c | 9 +- sound/isa/sb/sb_mixer.c | 2 - sound/isa/sgalaxy.c | 24 +- sound/isa/sscape.c | 37 +- sound/isa/wavefront/wavefront.c | 48 +- sound/isa/wavefront/wavefront_fx.c | 54 +- sound/isa/wavefront/wavefront_synth.c | 6 + sound/oss/Kconfig | 11 +- sound/oss/Makefile | 2 +- sound/oss/aci.c | 3 +- sound/oss/aci.h | 1 - sound/oss/ad1848.c | 56 +- sound/oss/ad1848.h | 8 +- sound/oss/ad1889.c | 124 +- sound/oss/ad1889.h | 8 +- sound/oss/ali5455.c | 18 +- sound/oss/au1000.c | 7 +- sound/oss/audio.c | 4 +- sound/oss/audio_syms.c | 3 - sound/oss/awe_wave.c | 4 +- sound/oss/btaudio.c | 6 +- sound/oss/cmpci.c | 89 +- sound/oss/cs4232.c | 46 +- sound/oss/cs4232.h | 2 - sound/oss/cs4281/cs4281m.c | 14 +- sound/oss/cs46xx.c | 34 +- sound/oss/dev_table.c | 4 +- sound/oss/dev_table.h | 1 - sound/oss/dmabuf.c | 2 +- sound/oss/dmasound/Kconfig | 2 +- sound/oss/dmasound/dmasound_awacs.c | 35 +- sound/oss/emu10k1/midi.c | 3 +- sound/oss/es1370.c | 10 +- sound/oss/es1371.c | 14 +- sound/oss/esssolo1.c | 12 +- sound/oss/forte.c | 11 +- sound/oss/gus_card.c | 24 +- sound/oss/gus_wave.c | 14 +- sound/oss/harmony.c | 138 +- sound/oss/i810_audio.c | 37 +- sound/oss/ite8172.c | 7 +- sound/oss/kahlua.c | 6 +- sound/oss/mad16.c | 220 +- sound/oss/maestro.c | 6 +- sound/oss/maestro3.c | 7 +- sound/oss/maui.c | 63 +- sound/oss/mpu401.c | 26 +- sound/oss/mpu401.h | 2 +- sound/oss/msnd.c | 135 +- sound/oss/msnd.h | 27 +- sound/oss/msnd_pinnacle.c | 210 +- sound/oss/nec_vrc5477.c | 1 - sound/oss/nm256.h | 10 +- sound/oss/nm256_audio.c | 2 +- sound/oss/opl3sa.c | 59 +- sound/oss/opl3sa2.c | 59 +- sound/oss/pss.c | 142 +- sound/oss/rme96xx.c | 8 +- sound/oss/sb_card.c | 9 +- sound/oss/sb_common.c | 24 +- sound/oss/sgalaxy.c | 42 +- sound/oss/sonicvibes.c | 6 +- sound/oss/sound_calls.h | 1 - sound/oss/sound_syms.c | 3 - sound/oss/soundcard.c | 8 +- sound/oss/sscape.c | 215 +- sound/oss/swarm_cs4297a.c | 2 +- sound/oss/trident.c | 12 +- sound/oss/trix.c | 221 +- sound/oss/v_midi.c | 5 +- sound/oss/via82cxxx_audio.c | 8 +- sound/oss/waveartist.c | 6 +- sound/oss/wavfront.c | 6 +- sound/oss/wf_midi.c | 5 +- sound/oss/ymfpci.c | 5 +- sound/oss/ymfpci.h | 2 +- sound/parisc/Kconfig | 9 +- sound/parisc/harmony.c | 95 +- sound/pci/Kconfig | 282 +- sound/pci/Makefile | 2 + sound/pci/ac97/Makefile | 7 +- sound/pci/ac97/ac97_codec.c | 536 +- sound/pci/ac97/ac97_id.h | 10 + sound/pci/ac97/ac97_local.h | 21 +- sound/pci/ac97/ac97_patch.c | 391 +- sound/pci/ac97/ac97_patch.h | 2 + sound/pci/ac97/ac97_pcm.c | 167 +- sound/pci/ac97/ac97_proc.c | 24 +- sound/pci/ac97/ak4531_codec.c | 26 +- sound/pci/ali5451/ali5451.c | 94 +- sound/pci/als4000.c | 78 +- sound/pci/atiixp.c | 153 +- sound/pci/atiixp_modem.c | 18 +- sound/pci/au88x0/au88x0.c | 29 +- sound/pci/au88x0/au88x0.h | 4 +- sound/pci/au88x0/au88x0_a3d.c | 14 +- sound/pci/au88x0/au88x0_core.c | 2 +- sound/pci/au88x0/au88x0_eq.c | 196 +- sound/pci/au88x0/au88x0_game.c | 2 +- sound/pci/au88x0/au88x0_mixer.c | 13 +- sound/pci/au88x0/au88x0_mpu401.c | 2 +- sound/pci/au88x0/au88x0_pcm.c | 7 +- sound/pci/au88x0/au88x0_xtalk.c | 6 + sound/pci/au88x0/au88x0_xtalk.h | 3 +- sound/pci/azt3328.c | 131 +- sound/pci/bt87x.c | 125 +- sound/pci/cmipci.c | 251 +- sound/pci/cs4281.c | 209 +- sound/pci/cs46xx/cs46xx.c | 22 +- sound/pci/cs46xx/cs46xx_lib.c | 465 +- sound/pci/cs46xx/cs46xx_lib.h | 2 - sound/pci/cs46xx/dsp_spos.c | 55 +- sound/pci/cs46xx/dsp_spos_scb_lib.c | 6 +- sound/pci/emu10k1/emu10k1.c | 38 +- sound/pci/emu10k1/emu10k1_callback.c | 16 +- sound/pci/emu10k1/emu10k1_main.c | 64 +- sound/pci/emu10k1/emu10k1_patch.c | 4 +- sound/pci/emu10k1/emu10k1_synth.c | 4 +- sound/pci/emu10k1/emufx.c | 416 +- sound/pci/emu10k1/emumixer.c | 21 +- sound/pci/emu10k1/emupcm.c | 330 +- sound/pci/emu10k1/emuproc.c | 156 +- sound/pci/emu10k1/io.c | 4 +- sound/pci/emu10k1/irq.c | 2 +- sound/pci/emu10k1/memory.c | 14 +- sound/pci/ens1370.c | 188 +- sound/pci/es1938.c | 239 +- sound/pci/es1968.c | 286 +- sound/pci/fm801.c | 94 +- sound/pci/ice1712/Makefile | 2 +- sound/pci/ice1712/ak4xxx.c | 1 - sound/pci/ice1712/aureon.c | 961 +- sound/pci/ice1712/aureon.h | 5 + sound/pci/ice1712/delta.c | 17 +- sound/pci/ice1712/delta.h | 4 +- sound/pci/ice1712/ews.c | 85 +- sound/pci/ice1712/ews.h | 4 +- sound/pci/ice1712/hoontech.c | 164 +- sound/pci/ice1712/ice1712.c | 203 +- sound/pci/ice1712/ice1712.h | 30 +- sound/pci/ice1712/ice1724.c | 399 +- sound/pci/ice1712/revo.c | 4 +- sound/pci/intel8x0.c | 607 +- sound/pci/intel8x0m.c | 232 +- sound/pci/korg1212/korg1212.c | 368 +- sound/pci/maestro3.c | 118 +- sound/pci/mixart/mixart.c | 142 +- sound/pci/mixart/mixart.h | 3 +- sound/pci/mixart/mixart_core.c | 4 +- sound/pci/mixart/mixart_hwdep.c | 4 +- sound/pci/mixart/mixart_mixer.c | 2 - sound/pci/nm256/nm256.c | 198 +- sound/pci/rme32.c | 884 +- sound/pci/rme96.c | 397 +- sound/pci/rme9652/hdsp.c | 744 +- sound/pci/rme9652/rme9652.c | 329 +- sound/pci/sonicvibes.c | 148 +- sound/pci/trident/trident.c | 19 +- sound/pci/trident/trident_main.c | 173 +- sound/pci/trident/trident_memory.c | 14 +- sound/pci/trident/trident_synth.c | 33 +- sound/pci/via82xx.c | 253 +- sound/pci/vx222/vx222.c | 58 +- sound/pci/vx222/vx222.h | 2 +- sound/pci/vx222/vx222_ops.c | 2 - sound/pci/ymfpci/ymfpci.c | 25 +- sound/pci/ymfpci/ymfpci_main.c | 196 +- sound/pcmcia/Kconfig | 18 +- sound/pcmcia/pdaudiocf/pdaudiocf.c | 25 +- sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 12 +- sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | 4 +- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 4 +- sound/pcmcia/vx/vx_entry.c | 10 +- sound/pcmcia/vx/vxp_mixer.c | 2 - sound/pcmcia/vx/vxp_ops.c | 2 - sound/pcmcia/vx/vxpocket.c | 18 +- sound/ppc/Kconfig | 10 +- sound/ppc/Makefile | 2 +- sound/ppc/awacs.c | 35 +- sound/ppc/burgundy.c | 6 +- sound/ppc/daca.c | 30 +- sound/ppc/pmac.c | 120 +- sound/ppc/pmac.h | 26 +- sound/ppc/powermac.c | 24 +- sound/ppc/tumbler.c | 118 +- sound/sparc/amd7930.c | 31 +- sound/sparc/cs4231.c | 60 +- sound/synth/emux/emux.c | 6 +- sound/synth/emux/emux_effect.c | 2 +- sound/synth/emux/emux_hwdep.c | 2 +- sound/synth/emux/emux_nrpn.c | 18 +- sound/synth/emux/emux_oss.c | 14 +- sound/synth/emux/emux_proc.c | 2 +- sound/synth/emux/emux_seq.c | 20 +- sound/synth/emux/emux_synth.c | 12 +- sound/synth/emux/soundfont.c | 60 +- sound/synth/util_mem.c | 2 +- sound/usb/Kconfig | 21 +- sound/usb/Makefile | 8 +- sound/usb/usbaudio.c | 223 +- sound/usb/usbaudio.h | 12 +- sound/usb/usbmidi.c | 90 +- sound/usb/usbmixer.c | 62 +- sound/usb/usbmixer_maps.c | 11 +- sound/usb/usbquirks.h | 156 +- sound/usb/usx2y/usbusx2y.c | 17 +- sound/usb/usx2y/usbusx2yaudio.c | 36 +- usr/Makefile | 20 +- usr/gen_init_cpio.c | 242 +- 6511 files changed, 284771 insertions(+), 236848 deletions(-) diff --git a/CREDITS b/CREDITS index cc0cffd96..ef7dd2206 100644 --- a/CREDITS +++ b/CREDITS @@ -46,13 +46,11 @@ D: Various kernel patches S: United Kingdom N: Werner Almesberger -E: werner.almesberger@epfl.ch +E: werner@almesberger.net +W: http://www.almesberger.net/ D: dosfs, LILO, some fd features, ATM, various other hacks here and there -S: Ecole Polytechnique Federale de Lausanne -S: DSC ICA -S: INN (Ecublens) -S: CH-1015 Lausanne -S: Switzerland +S: Buenos Aires +S: Argentina N: Tim Alpaerts E: tim_alpaerts@toyota-motor-europe.com @@ -281,6 +279,11 @@ S: Code 930.5, Goddard Space Flight Center S: Greenbelt, Maryland 20771 S: USA +N: Adam Belay +E: ambx1@neo.rr.com +D: Linux Plug and Play Support +S: USA + N: Daniele Bellucci E: bellucda@tiscali.it D: Various Janitor work. @@ -492,6 +495,14 @@ E: m@mbsks.franken.de D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver S: Germany +N: Adrian Bunk +E: bunk@stusta.de +P: 1024D/4F12B400 B29C E71E FE19 6755 5C8A 84D4 99FC EA98 4F12 B400 +D: misc kernel hacking and testing +S: Grasmeierstrasse 11 +S: 80805 Muenchen +S: Germany + N: Ray Burr E: ryb@nightmare.com D: Original author of Amiga FFS filesystem @@ -513,6 +524,14 @@ S: 25-29 St Giles S: Oxford S: United Kingdom +N: Luiz Fernando N. Capitulino +E: lcapitulino@terra.com.br +E: lcapitulino@prefeitura.sp.gov.br +W: http://www.telecentros.sp.gov.br +D: Little fixes and a lot of janitorial work +S: E-GOV Telecentros SP +S: Brazil + N: Remy Card E: Remy.Card@masi.ibp.fr E: Remy.Card@linux.org @@ -625,6 +644,14 @@ E: nconway.list@ukaea.org.uk D: Assorted sched/mm titbits S: Oxfordshire, UK. +N: Kees Cook +E: kees@outflux.net +W: http://outflux.net/ +P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30 1975 1FFF 4BA9 1706 3E6D +D: Minor updates to SCSI code for the Communications type +S: (ask for current address) +S: USA + N: Mark Corner E: mcorner@umich.edu W: http://www.eecs.umich.edu/~mcorner/ @@ -639,14 +666,6 @@ D: Kernel module SMART utilities S: Santa Cruz, California S: USA -N: Kees Cook -E: kees@outflux.net -W: http://outflux.net/ -P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30 1975 1FFF 4BA9 1706 3E6D -D: Minor updates to SCSI code for the Communications type -S: (ask for current address) -S: USA - N: Alan Cox W: http://www.linux.org.uk/diary/ D: Linux Networking (0.99.10->2.0.29) @@ -735,6 +754,12 @@ S: Schimmelsrain 1 S: D-69231 Rauenberg S: Germany +N: Jean Delvare +E: khali@linux-fr.org +W: http://khali.linux-fr.org/ +D: Several hardware monitoring drivers +S: France + N: Peter Denison E: peterd@pnd-pc.demon.co.uk W: http://www.pnd-pc.demon.co.uk/promise/ @@ -754,7 +779,7 @@ W: http://luxik.cdi.cz/~devik/qos/ D: HTB qdisc and random networking hacks N: Alex deVries -E: adevries@thepuffingroup.com +E: alex@onefishtwo.ca D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux. S: 41.5 William Street S: Ottawa, Ontario @@ -905,6 +930,10 @@ S: Brevia 1043 S: S-114 79 Stockholm S: Sweden +N: David Engebretsen +E: engebret@us.ibm.com +D: Linux port to 64-bit PowerPC architecture + N: Michael Engel E: engel@unix-ag.org D: DECstation framebuffer drivers @@ -1049,6 +1078,12 @@ S: R. Tocantins, 89 - Cristo Rei S: 80050-430 - Curitiba - Paraná S: Brazil +N: Kumar Gala +E: kumar.gala@freescale.com +D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support +S: Austin, Texas 78729 +S: USA + N: Nigel Gamble E: nigel@nrg.org D: Interrupt-driven printer driver @@ -1060,12 +1095,6 @@ S: USA N: Jeff Garzik E: jgarzik@pobox.com -N: Kumar Gala -E: kumar.gala@freescale.com -D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support -S: Austin, Texas 78729 -S: USA - N: Jacques Gelinas E: jacques@solucorp.qc.ca D: Author of the Umsdos file system @@ -1563,10 +1592,37 @@ D: Backport/Forwardport merge monkey. D: Various Janitor work. S: United Kingdom +N: Martin Josfsson +E: gandalf@wlug.westbo.se +P: 1024D/F6B6D3B1 7610 7CED 5C34 4AA6 DBA2 8BE1 5A6D AF95 F6B6 D3B1 +D: netfilter: SAME target +D: netfilter: helper target +D: netfilter: various other hacks +S: Ronneby +S: Sweden + N: Ani Joshi E: ajoshi@shell.unixbox.com D: fbdev hacking +N: Jesper Juhl +E: juhl-lkml@dif.dk +D: Various small janitor fixes, cleanups etc. +S: Lemnosvej 1, 3.tv +S: 2300 Copenhagen S +S: Denmark + +N: Jozsef Kadlecsik +E: kadlec@blackhole.kfki.hu +P: 1024D/470DB964 4CB3 1A05 713E 9BF7 FAC5 5809 DD8C B7B1 470D B964 +D: netfilter: TCP window tracking code +D: netfilter: raw table +D: netfilter: iprange match +D: netfilter: new logging interfaces +D: netfilter: various other hacks +S: Tata +S: Hungary + N: Bernhard Kaindl E: bkaindl@netway.at E: edv@bartelt.via.at @@ -1818,11 +1874,6 @@ S: Sindlovy Dvory 117 S: 370 01 Ceske Budejovice S: Czech Republic -N: Adam Belay -E: ambx1@neo.rr.com -D: Linux Plug and Play Support -S: USA - N: Bas Laarhoven E: sjml@xs4all.nl D: Loadable modules and ftape driver @@ -1954,12 +2005,6 @@ S: 8786 Niwot Road S: Niwot, Colorado 80503 S: USA -N: Pete Popov -E: pete_popov@yahoo.com -D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging -S: San Jose, CA 95134 -S: USA - N: Robert M. Love E: rml@tech9.net E: rml@novell.com @@ -2127,6 +2172,16 @@ D: OV511 driver S: (address available on request) S: USA +N: Patrick McHardy +E: kaber@trash.net +P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80 +D: netfilter: endless number of bugfixes +D: netfilter: CLASSIFY target +D: netfilter: addrtype match +D: tc: HFSC scheduler +S: Freiburg +S: Germany + N: Mike McLagan E: mike.mclagan@linux.org W: http://www.invlogic.com/~mmclagan @@ -2214,14 +2269,13 @@ S: 7546 JA Enschede S: Netherlands N: David S. Miller -E: davem@redhat.com +E: davem@davemloft.net D: Sparc and blue box hacker D: Vger Linux mailing list co-maintainer D: Linux Emacs elf/qmagic support + other libc/gcc things D: Yee bore de yee bore! ;-) -S: 750 N. Shoreline Blvd. -S: Apt. #111 -S: Mountain View, California 94043 +S: 575 Harrison St. #103 +S: San Francisco, CA 94105 S: USA N: Rick Miller @@ -2570,6 +2624,7 @@ N: Nicolas Pitre E: nico@cam.org D: StrongARM SA1100 support integrator & hacker D: Xscale PXA architecture +D: unified SMC 91C9x/91C11x ethernet driver (smc91x) S: Montreal, Quebec, Canada N: Ken Pizzini @@ -2582,6 +2637,12 @@ P: 1024D/EDBB6147 7B36 0E07 04BC 11DC A7A0 D3F7 7185 9E7A EDBB 6147 D: sonypi, meye drivers, mct_u232 usb serial hacks S: Paris, France +N: Pete Popov +E: pete_popov@yahoo.com +D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging +S: San Jose, CA 95134 +S: USA + N: Matt Porter E: mporter@kernel.crashing.org D: Motorola PowerPC PReP support @@ -2709,7 +2770,7 @@ N: Luca Risolia E: luca.risolia@studio.unibo.it P: 1024D/FCE635A4 88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4 D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chips -D: V4L2 driver for SN9C10[12] PC Camera Controllers +D: V4L2 driver for SN9C10x PC Camera Controllers S: Via Liberta' 41/A S: Osio Sotto, 24046, Bergamo S: Italy @@ -2797,7 +2858,7 @@ S: Germany N: Paul `Rusty' Russell E: rusty@rustcorp.com.au -W: http://www.samba.org/netfilter +W: http://ozlabs.org/~rusty D: Ruggedly handsome. D: netfilter, ipchains with Michael Neuling. S: 52 Moore St @@ -2821,7 +2882,6 @@ S: I/3 Walter St S: Wellington S: New Zealand - N: Sampo Saaristo E: sambo@cs.tut.fi D: Co-author of Multi-Protocol Over ATM (MPOA) @@ -2838,6 +2898,9 @@ S: Markusstrasse 18 S: 8006 Zuerich S: Switzerland +N: Manuel Estrada Sainz +D: Firmware loader (request_firmware) + N: Wayne Salamon E: wsalamon@tislabs.com E: wsalamon@nai.com @@ -3289,14 +3352,6 @@ S: Chudenicka 8 S: 10200 Prague 10, Hostivar S: Czech Republic -N: James R. Van Zandt -E: jrv@vanzandt.mv.com -P: 1024/E298966D F0 37 4F FD E5 7E C5 E6 F1 A0 1E 22 6F 46 DA 0C -D: Author and maintainer of the Double Talk speech synthesizer driver -S: 27 Spencer Drive -S: Nashua, New Hampshire 03062 -S: USA - N: Heikki Vatiainen E: hessu@cs.tut.fi D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks @@ -3387,6 +3442,18 @@ S: UC Berkeley S: Berkeley, CA 94720-1776 S: USA +N: Harald Welte +E: laforge@netfilter.org +P: 1024D/30F48BFF DBDE 6912 8831 9A53 879B 9190 5DA5 C655 30F4 8BFF +W: http://gnumonks.org/users/laforge +D: netfilter: new nat helper infrastructure +D: netfilter: ULOG, ECN, DSCP target +D: netfilter: TTL match +D: netfilter: IPv6 mangle table +D: netfilter: various other hacks +S: Berlin +S: Germany + N: Bill Wendling E: wendling@ganymede.isdn.uiuc.edu W: http://www.ncsa.uiuc.edu/~wendling/ @@ -3578,6 +3645,14 @@ S: ARCO Tower 1-8-1 Shimomeguro Meguro-ku S: Tokyo 153 S: Japan +N: James R. Van Zandt +E: jrv@vanzandt.mv.com +P: 1024/E298966D F0 37 4F FD E5 7E C5 E6 F1 A0 1E 22 6F 46 DA 0C +D: Author and maintainer of the Double Talk speech synthesizer driver +S: 27 Spencer Drive +S: Nashua, New Hampshire 03062 +S: USA + N: Orest Zborowski E: orestz@eskimo.com D: XFree86 and kernel development @@ -3619,13 +3694,6 @@ D: MD driver D: EISA/sysfs subsystem S: France -N: Luiz Fernando N. Capitulino -E: lcapitulino@terra.com.br -E: lcapitulino@prefeitura.sp.gov.br -W: http://www.telecentros.sp.gov.br -D: Little fixes and a lot of janitorial work -S: E-GOV Telecentros SP -S: Brazil # Don't add your name here, unless you really _are_ after Marc # alphabetically. Leonard used to be very proud of being the diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 008c5471f..a8c19aa34 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -20,6 +20,8 @@ Changes - list of changes that break older software packages. CodingStyle - how the boss likes the C code in the kernel to look. +DMA-API.txt + - DMA API, pci_ API & extensions for non-consistent memory machines. DMA-mapping.txt - info for PCI drivers using DMA portably across all platforms. DocBook/ @@ -30,8 +32,12 @@ IPMI.txt - info on Linux Intelligent Platform Management Interface (IPMI) Driver. IRQ-affinity.txt - how to select which CPU(s) handle which interrupt events on SMP. +ManagementStyle + - how to (attempt to) manage kernel hackers. MSI-HOWTO.txt - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ. +RCU/ + - directory with info on RCU (read-copy update). README.DAC960 - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux. README.moxa @@ -46,8 +52,6 @@ VGA-softcursor.txt - how to change your VGA cursor from a blinking underscore. arm/ - directory with info about Linux on the ARM architecture. -as-iosched.txt - - info on anticipatory IO scheduler. basic_profiling.txt - basic instructions for those who wants to profile Linux kernel. binfmt_misc.txt @@ -60,20 +64,24 @@ cciss.txt - info, major/minor #'s for Compaq's SMART Array Controllers. cdrom/ - directory with information on the CD-ROM drivers that Linux has. +cli-sti-removal.txt + - cli()/sti() removal guide. computone.txt - info on Computone Intelliport II/Plus Multiport Serial Driver. cpqarray.txt - info on using Compaq's SMART2 Intelligent Disk Array Controllers. -cpufreq/ +cpu-freq/ - info on CPU frequency and voltage scaling. cris/ - directory with info about Linux on CRIS architecture. +crypto/ + - directory with info on the Crypto API. debugging-modules.txt - some notes on debugging modules after Linux 2.6.3. +device-mapper/ + - directory with info on Device Mapper. devices.txt - plain ASCII listing of all the nodes in /dev/ with major minor #'s. -digiboard.txt - - info on the Digiboard PC/X{i,e,eve} multiport boards. digiepca.txt - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. dnotify.txt @@ -92,6 +100,8 @@ fb/ - directory with info on the frame buffer graphics abstraction layer. filesystems/ - directory with info on the various filesystems that Linux supports. +firmware_class/ + - request_firmware() hotplug interface info. floppy.txt - notes and driver options for the floppy disk driver. ftape.txt @@ -100,10 +110,14 @@ hayes-esp.txt - info on using the Hayes ESP serial driver. highuid.txt - notes on the change from 16 bit to 32 bit user/group IDs. +hpet.txt + - High Precision Event Timer Driver for Linux. hw_random.txt - info on Linux support for random number generator in i8xx chipsets. i2c/ - directory with info about the I2C bus/protocol (2 wire, kHz speed). +i2o/ + - directory with info about the Linux I2O subsystem. i386/ - directory with info about Linux on Intel 32 bit architecture. ia64/ @@ -114,6 +128,8 @@ initrd.txt - how to use the RAM disk as an initial/temporary root filesystem. input/ - info on Linux input device support. +io_ordering.txt + - info on ordering I/O writes to memory-mapped addresses. ioctl-number.txt - how to implement and register device/driver ioctl calls. iostats.txt @@ -134,6 +150,8 @@ kernel-parameters.txt - summary listing of command line / boot prompt args for the kernel. kobject.txt - info of the kobject infrastructure of the Linux kernel. +laptop-mode.txt + - How to conserve battery power using laptop-mode. ldm.txt - a brief description of LDM (Windows Dynamic Disks). locks.txt @@ -158,8 +176,8 @@ mips/ - directory with info about Linux on MIPS architecture. mkdev.cciss - script to make /dev entries for SMART controllers (see cciss.txt). -mkdev.ida - - script to make /dev entries for Intelligent Disk Array Controllers. +mono.txt + - how to execute Mono-based .NET binaries with the help of BINFMT_MISC. moxa-smartio - info on installing/using Moxa multiport serial driver. mtrr.txt @@ -172,6 +190,8 @@ nfsroot.txt - short guide on setting up a diskless box with NFS root filesystem. nmi_watchdog.txt - info on NMI watchdog for SMP systems. +numastat.txt + - info on how to read Numa policy hit/miss statistics in sysfs. oops-tracing.txt - how to decode those nasty internal kernel error dump messages. paride.txt @@ -199,17 +219,25 @@ ramdisk.txt riscom8.txt - notes on using the RISCom/8 multi-port serial driver. rocket.txt - - info on installing/using the Comtrol RocketPort multiport serial driver. + - info on the Comtrol RocketPort multiport serial driver. rpc-cache.txt - introduction to the caching mechanisms in the sunrpc layer. rtc.txt - notes on how to use the Real Time Clock (aka CMOS clock) driver. s390/ - directory with info on using Linux on the IBM S390. +sched-coding.txt + - reference for various scheduler-related methods in the O(1) scheduler. sched-design.txt - goals, design and implementation of the Linux O(1) scheduler. +sched-domains.txt + - information on scheduling domains. +sched-stats.txt + - information on schedstats (Linux Scheduler Statistics). scsi/ - directory with info on Linux scsi support. +serial/ + - directory with info on the low level serial API. serial-console.txt - how to set up Linux with a serial line console as the default. sgi-visws.txt @@ -242,14 +270,24 @@ sysrq.txt - info on the magic SysRq key. telephony/ - directory with info on telephony (e.g. voice over IP) support. +time_interpolators.txt + - info on time interpolators. +tipar.txt + - information about Parallel link cable for Texas Instruments handhelds. +tty.txt + - guide to the locking policies of the tty layer. unicode.txt - info on the Unicode character/font mapping used in Linux. +uml/ + - directory with infomation about User Mode Linux. usb/ - directory with info regarding the Universal Serial Bus. video4linux/ - directory with info regarding video/TV/radio cards and linux. vm/ - directory with info on the Linux vm code. +voyager.txt + - guide to running Linux on the Voyager architecture. watchdog/ - how to auto-reboot Linux if it has "fallen and can't get up". ;-) x86_64/ diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 7b256c12a..f25b3953f 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -356,10 +356,10 @@ Generally, inline functions are preferable to macros resembling functions. Macros with multiple statements should be enclosed in a do - while block: -#define macrofun(a,b,c) \ +#define macrofun(a, b, c) \ do { \ if (a == 5) \ - do_this(b,c); \ + do_this(b, c); \ } while (0) Things to avoid when using macros: diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 11caa2d64..6ee3cd613 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -160,7 +160,7 @@ pci_set_dma_mask(struct pci_device *dev, u64 mask) Checks to see if the mask is possible and updates the device parameters if it is. -Returns: 1 if successful and 0 if not +Returns: 0 if successful and a negative error if not. u64 dma_get_required_mask(struct device *dev) @@ -444,4 +444,83 @@ dma_alloc_noncoherent(), starting at virtual address vaddr and continuing on for size. Again, you *must* observe the cache line boundaries when doing this. +int +dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, + dma_addr_t device_addr, size_t size, int + flags) + + +Declare region of memory to be handed out by dma_alloc_coherent when +it's asked for coherent memory for this device. + +bus_addr is the physical address to which the memory is currently +assigned in the bus responding region (this will be used by the +platform to perform the mapping) + +device_addr is the physical address the device needs to be programmed +with actually to address this memory (this will be handed out as the +dma_addr_t in dma_alloc_coherent()) + +size is the size of the area (must be multiples of PAGE_SIZE). + +flags can be or'd together and are + +DMA_MEMORY_MAP - request that the memory returned from +dma_alloc_coherent() be directly writeable. + +DMA_MEMORY_IO - request that the memory returned from +dma_alloc_coherent() be addressable using read/write/memcpy_toio etc. + +One or both of these flags must be present + +DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by +dma_alloc_coherent of any child devices of this one (for memory residing +on a bridge). + +DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions. +Do not allow dma_alloc_coherent() to fall back to system memory when +it's out of memory in the declared region. + +The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and +must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO +if only DMA_MEMORY_MAP were passed in) for success or zero for +failure. + +Note, for DMA_MEMORY_IO returns, all subsequent memory returned by +dma_alloc_coherent() may no longer be accessed directly, but instead +must be accessed using the correct bus functions. If your driver +isn't prepared to handle this contingency, it should not specify +DMA_MEMORY_IO in the input flags. + +As a simplification for the platforms, only *one* such region of +memory may be declared per device. + +For reasons of efficiency, most platforms choose to track the declared +region only at the granularity of a page. For smaller allocations, +you should use the dma_pool() API. + +void +dma_release_declared_memory(struct device *dev) + +Remove the memory region previously declared from the system. This +API performs *no* in-use checking for this region and will return +unconditionally having removed all the required structures. It is the +drivers job to ensure that no parts of this memory region are +currently in use. + +void * +dma_mark_declared_memory_occupied(struct device *dev, + dma_addr_t device_addr, size_t size) + +This is used to occupy specific regions of the declared space +(dma_alloc_coherent() will hand out the first free region it finds). + +device_addr is the *device* address of the region requested + +size is the size (and should be a page sized multiple). + +The return value will be either a pointer to the processor virtual +address of the memory, or an error (via PTR_ERR()) if any part of the +region is occupied. + diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index bf212c021..fc50b1073 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -8,10 +8,10 @@ DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \ kernel-hacking.sgml kernel-locking.sgml via-audio.sgml \ - mousedrivers.sgml deviceiobook.sgml procfs-guide.sgml \ - tulip-user.sgml writing_usb_driver.sgml scsidrivers.sgml \ - sis900.sgml kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \ - gadget.sgml libata.sgml + deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \ + writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \ + kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \ + gadget.sgml libata.sgml mtdnand.sgml librs.sgml ### # The build process is as follows (targets): @@ -58,14 +58,14 @@ MAKEMAN = $(PERL) $(srctree)/scripts/makeman # The following rules are used to generate the .sgml documentation # required to generate the final targets. (ps, pdf, html). quiet_cmd_docproc = DOCPROC $@ - cmd_docproc = $(DOCPROC) doc $< >$@ + cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@ define rule_docproc set -e; \ $(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))';) \ $(cmd_$(1)); \ ( \ echo 'cmd_$@ := $(cmd_$(1))'; \ - echo $@: `$(DOCPROC) depend $<`; \ + echo $@: `SRCTREE=$(srctree) $(DOCPROC) depend $<`; \ ) > $(dir $@).$(notdir $@).cmd endef @@ -129,6 +129,9 @@ quiet_cmd_db2html = DB2HTML $@ # Rule to generate man files - output is placed in the man subdirectory %.9: %.sgml +ifneq ($(KBUILD_SRC),) + $(Q)mkdir -p $(objtree)/Documentation/DocBook/man +endif $(SPLITMAN) $< $(objtree)/Documentation/DocBook/man "$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)" $(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $< @@ -185,9 +188,7 @@ clean-files := $(DOCBOOKS) \ $(patsubst %.sgml, %.9, $(DOCBOOKS)) \ $(C-procfs-example) -ifneq ($(wildcard $(patsubst %.html,%,$(HTML))),) -clean-rule := rm -rf $(wildcard $(patsubst %.html,%,$(HTML))) -endif +clean-dirs := $(patsubst %.sgml,%,$(DOCBOOKS)) #man put files in man subdir - traverse down subdir- := man/ diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl index d3f418384..0d1da8cbd 100644 --- a/Documentation/DocBook/deviceiobook.tmpl +++ b/Documentation/DocBook/deviceiobook.tmpl @@ -147,8 +147,7 @@ compiler is not permitted to reorder the I/O sequence. When the ordering can be compiler optimised, you can use __readb and friends to indicate the relaxed ordering. Use - this with care. The rmb provides a read memory - barrier. The wmb provides a write memory barrier. + this with care. @@ -159,19 +158,113 @@ asynchronously. A driver author must issue a read from the same device to ensure that writes have occurred in the specific cases the author cares. This kind of property cannot be hidden from driver - writers in the API. + writers in the API. In some cases, the read used to flush the device + may be expected to fail (if the card is resetting, for example). In + that case, the read should be done from config space, which is + guaranteed to soft-fail if the card doesn't respond. + + + + The following is an example of flushing a write to a device when + the driver would like to ensure the write's effects are visible prior + to continuing execution. + + + +static inline void +qla1280_disable_intrs(struct scsi_qla_host *ha) +{ + struct device_reg *reg; + + reg = ha->iobase; + /* disable risc and host interrupts */ + WRT_REG_WORD(&reg->ictrl, 0); + /* + * The following read will ensure that the above write + * has been received by the device before we return from this + * function. + */ + RD_REG_WORD(&reg->ictrl); + ha->flags.ints_enabled = 0; +} + + + + In addition to write posting, on some large multiprocessing systems + (e.g. SGI Challenge, Origin and Altix machines) posted writes won't + be strongly ordered coming from different CPUs. Thus it's important + to properly protect parts of your driver that do memory-mapped writes + with locks and use the mmiowb to make sure they + arrive in the order intended. Issuing a regular readX + will also ensure write ordering, but should only be used + when the driver has to be sure that the write has actually arrived + at the device (not that it's simply ordered with respect to other + writes), since a full readX is a relatively + expensive operation. + + + + Generally, one should use mmiowb prior to + releasing a spinlock that protects regions using writeb + or similar functions that aren't surrounded by + readb calls, which will ensure ordering and flushing. The + following pseudocode illustrates what might occur if write ordering + isn't guaranteed via mmiowb or one of the + readX functions. + + + +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: writel(newval2, ring_ptr); +CPU B: ... +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + + + + In the case above, newval2 could be written to ring_ptr before + newval. Fixing it is easy though: + + + +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: mmiowb(); /* ensure no other writes beat us to the device */ +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: writel(newval2, ring_ptr); +CPU B: ... +CPU B: mmiowb(); +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + + + + See tg3.c for a real world example of how to use mmiowb + PCI ordering rules also guarantee that PIO read responses arrive - after any outstanding DMA writes on that bus, since for some devices + after any outstanding DMA writes from that bus, since for some devices the result of a readb call may signal to the driver that a DMA transaction is complete. In many cases, however, the driver may want to indicate that the next readb call has no relation to any previous DMA writes performed by the device. The driver can use readb_relaxed for these cases, although only - some platforms will honor the relaxed semantics. + some platforms will honor the relaxed semantics. Using the relaxed + read functions will provide significant performance benefits on + platforms that support it. The qla2xxx driver provides examples + of how to use readX_relaxed. In many cases, + a majority of the driver's readX calls can + safely be converted to readX_relaxed calls, since + only a few will indicate or depend on DMA completion. diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl index f07e73a41..0c28a966c 100644 --- a/Documentation/DocBook/gadget.tmpl +++ b/Documentation/DocBook/gadget.tmpl @@ -2,8 +2,8 @@ USB Gadget API for Linux - 02 June 2003 - 02 June 2003 + 20 August 2004 + 20 August 2004 @@ -34,7 +34,7 @@ - 2003 + 2003-2004 David Brownell @@ -73,9 +73,13 @@ a number of important problems, including: composite devices, and alternate interface settings. + USB "On-The-Go" (OTG) support, in conjunction + with updates to the Linux-USB host side. + Sharing data structures and API models with the - Linux-USB host side API. This looks forward to USB "On-The-Go" - (OTG) and similar more-symmetric frameworks. + Linux-USB host side API. This helps the OTG support, and + looks forward to more-symmetric frameworks (where the same + I/O model is used by both host and device side drivers). Minimalist, so it's easier to support new device controller hardware. I/O processing doesn't imply large @@ -153,6 +157,7 @@ with the lowest level (which directly handles hardware). the SA-11x0 or PXA-25x UDC (found within many PDAs), and a variety of other products. + @@ -162,10 +167,14 @@ with the lowest level (which directly handles hardware). The lower boundary of this driver implements hardware-neutral USB functions, using calls to the controller driver. Because such hardware varies widely in capabilities and restrictions, - the gadget driver is normally configured at compile time + and is used in embedded environments where space is at a premium, + the gadget driver is often configured at compile time to work with endpoints supported by one particular controller. Gadget drivers may be portable to several different controllers, using conditional compilation. + (Recent kernels substantially simplify the work involved in + supporting new hardware, by autoconfiguring + endpoints automatically for many bulk-oriented drivers.) Gadget driver responsibilities include: @@ -178,8 +187,9 @@ with the lowest level (which directly handles hardware). altsettings, including enabling and configuring endpoints handling life cycle events, such as managing - bindings - to hardware, and disconnection from the USB host. + bindings to hardware, + USB suspend/resume, remote wakeup, + and disconnection from the USB host. managing IN and OUT transfers on all currently enabled endpoints @@ -244,15 +254,38 @@ with the lowest level (which directly handles hardware). -Over time, reusable utilities should evolve to help make some -gadget driver tasks simpler. An example of particular interest +OTG-capable systems will also need to include a standard Linux-USB +host side stack, +with usbcore, +one or more Host Controller Drivers (HCDs), +USB Device Drivers to support +the OTG "Targeted Peripheral List", +and so forth. +There will also be an OTG Controller Driver, +which is visible to gadget and device driver developers only indirectly. +That helps the host and device side USB controllers implement the +two new OTG protocols (HNP and SRP). +Roles switch (host to peripheral, or vice versa) using HNP +during USB suspend processing, and SRP can be viewed as a +more battery-friendly kind of device wakeup protocol. + + +Over time, reusable utilities are evolving to help make some +gadget driver tasks simpler. +For example, building configuration descriptors from vectors of +descriptors for the configurations interfaces and endpoints is +now automated, and many drivers now use autoconfiguration to +choose hardware endpoints and initialize their descriptors. + +A potential example of particular interest is code implementing standard USB-IF protocols for HID, networking, storage, or audio classes. Some developers are interested in KDB or KGDB hooks, to let target hardware be remotely debugged. Most such USB protocol code doesn't need to be hardware-specific, any more than network protocols like X11, HTTP, or NFS are. -Such interface drivers might be combined, to support composite devices. +Such gadget-side interface drivers should eventually be combined, +to implement composite devices. @@ -284,7 +317,7 @@ data types and functions are described here. However, docproc does not understand all the C constructs that are used, so some relevant information is likely omitted from what you are reading. -One example of such information is several per-request flags. +One example of such information is endpoint autoconfiguration. You'll have to read the header file, and use example source code (such as that for "Gadget Zero"), to fully understand the API. @@ -292,7 +325,7 @@ code (such as that for "Gadget Zero"), to fully understand the API. The part of the API implementing some basic driver capabilities is specific to the version of the Linux kernel that's in use. -The 2.5 kernel includes a driver model +The 2.6 kernel includes a driver model framework that has no analogue on earlier kernels; so those parts of the gadget API are not fully portable. (They are implemented on 2.4 kernels, but in a different way.) @@ -308,17 +341,21 @@ There are significant hardware features, such as device-to-device DMA that would be added using hardware-specific APIs. -This API expects drivers to use conditional compilation to handle -endpoint capabilities of different hardware. -Those tend to have arbitrary restrictions, relating to +This API allows drivers to use conditional compilation to handle +endpoint capabilities of different hardware, but doesn't require that. +Hardware tends to have arbitrary restrictions, relating to transfer types, addressing, packet sizes, buffering, and availability. As a rule, such differences only matter for "endpoint zero" logic that handles device configuration and management. -The API only supports limited run-time +The API supports limited run-time detection of capabilities, through naming conventions for endpoints. -Although a gadget driver could scan the endpoints available to it and -choose to map those capabilities onto driver functionality in some way, -few drivers will want to reconfigure themselves at run-time. +Many drivers will be able to at least partially autoconfigure +themselves. +In particular, driver init sections will often have endpoint +autoconfiguration logic that scans the hardware's list of endpoints +to find ones matching the driver requirements +(relying on those conventions), to eliminate some of the most +common reasons for conditional compilation. Like the Linux-USB host side API, this API exposes @@ -355,10 +392,14 @@ and so on. At this point the device is logically in the USB ch9 initial state ("attached"), drawing no power and not usable (since it does not yet support enumeration). +Any host should not see the device, since it's not +activated the data line pullup used by the host to +detect a device, even if VBUS power is available. Register a gadget driver that implements some higher level -device function. That will then bind() to a usb_gadget. +device function. That will then bind() to a usb_gadget, which +activates the data line pullup sometime after detecting VBUS. The hardware driver can now start enumerating. @@ -373,6 +414,8 @@ based both on what the bus interface hardware provides and on the functionality being implemented. That can involve alternate settings or configurations, unless the hardware prevents such operation. +For OTG devices, each configuration descriptor includes +an OTG descriptor. The gadget driver handles the last step of enumeration, @@ -381,13 +424,18 @@ It enables all endpoints used in that configuration, with all interfaces in their default settings. That involves using a list of the hardware's endpoints, enabling each endpoint according to its descriptor. +It may also involve using usb_gadget_vbus_draw +to let more power be drawn from VBUS, as allowed by that configuration. +For OTG devices, setting a configuration may also involve reporting +HNP capabilities through a user interface. Do real work and perform data transfers, possibly involving changes to interface settings or switching to new configurations, until the device is disconnect()ed from the host. Queue any number of transfer requests to each endpoint. -The drivers then go back to step 3 (above). +It may be suspended and resumed several times before being disconnected. +On disconnect, the drivers go back to step 3 (above). When the gadget driver module is being unloaded, @@ -399,7 +447,9 @@ driver be unloaded. Drivers will normally be arranged so that just loading the gadget driver module (or statically linking it into a Linux kernel) -allows the peripheral device to be enumerated. +allows the peripheral device to be enumerated, but some drivers +will defer enumeration until some higher level component (like +a user mode daemon) enables it. Note that at this lowest level there are no policies about how ep0 configuration logic is implemented, except that it should obey USB specifications. @@ -410,6 +460,18 @@ or understanding that composite devices might happen to be built by integrating reusable components. +Note that the lifecycle above can be slightly different +for OTG devices. +Other than providing an additional OTG descriptor in each +configuration, only the HNP-related differences are particularly +visible to driver code. +They involve reporting requirements during the SET_CONFIGURATION +request, and the option to invoke HNP during some suspend callbacks. +Also, SRP changes the semantics of +usb_gadget_wakeup +slightly. + + USB 2.0 Chapter 9 Types and Constants @@ -418,9 +480,9 @@ be built by integrating reusable components. rely on common USB structures and constants defined in the <linux/usb_ch9.h> -header file, which is standard in Linux 2.5 kernels. +header file, which is standard in Linux 2.6 kernels. These are the same types and constants used by host -side drivers. +side drivers (and usbcore). !Iinclude/linux/usb_ch9.h @@ -451,26 +513,38 @@ USB peripheral controller drivers. The core API is sufficient for writing a USB Gadget Driver, but some optional utilities are provided to simplify common tasks. +These utilities include endpoint autoconfiguration. !Edrivers/usb/gadget/usbstring.c !Edrivers/usb/gadget/config.c + Peripheral Controller Drivers -The first hardware supporting this API is the NetChip 2280 +The first hardware supporting this API was the NetChip 2280 controller, which supports USB 2.0 high speed and is based on PCI. This is the net2280 driver module. -The driver supports Linux kernel versions 2.4 and 2.5; +The driver supports Linux kernel versions 2.4 and 2.6; contact NetChip Technologies for development boards and product information. -For users of Intel's PXA 2xx series processors, -a pxa2xx_udc driver is available. +Other hardware working in the "gadget" framework includes: +Intel's PXA 25x and IXP42x series processors +(pxa2xx_udc), +Toshiba TC86c001 "Goku-S" (goku_udc), +Renesas SH7705/7727 (sh_udc), +MediaQ 11xx (mq11xx_udc), +Hynix HMS30C7202 (h7202_udc), +National 9303/4 (n9604_udc), +Texas Instruments OMAP (omap_udc), +Sharp LH7A40x (lh7a40x_udc), +and more. +Most of those are full speed controllers. At this writing, there are people at work on drivers in @@ -526,6 +600,15 @@ subset of CDC Ethernet. to avoid creating problems.) +Support for Microsoft's RNDIS +protocol has been contributed by Pengutronix and Auerswald GmbH. +This is like CDC Ethernet, but it runs on more slightly USB hardware +(but less than the CDC subset). +However, its main claim to fame is being able to connect directly to +recent versions of Windows, using drivers that Microsoft bundles +and supports, making it much simpler to network with Windows. + + There is also support for user mode gadget drivers, using gadgetfs. This provides a User Mode API that presents @@ -535,6 +618,10 @@ Familiar tools like GDB and pthreads can be used to develop and debug user mode drivers, so that once a robust controller driver is available many applications for it won't require new kernel mode software. +Linux 2.6 Async I/O (AIO) +support is available, so that user mode software +can stream data with only slightly more overhead +than a kernel driver. There's a USB Mass Storage class driver, which provides @@ -548,6 +635,16 @@ storage class specification, using transparent SCSI commands to access the data from the backing store. +There's a "serial line" driver, useful for TTY style +operation over USB. +The latest version of that driver supports CDC ACM style +operation, like a USB modem, and so on most hardware it can +interoperate easily with MS-Windows. +One interesting use of that driver is in boot firmware (like a BIOS), +which can sometimes use that model with very small systems without +real serial lines. + + Support for other kinds of gadget is expected to be developed and contributed over time, as this driver framework evolves. @@ -555,6 +652,96 @@ over time, as this driver framework evolves. +USB On-The-GO (OTG) + +USB OTG support on Linux 2.6 was initially developed +by Texas Instruments for +OMAP 16xx and 17xx +series processors. +Other OTG systems should work in similar ways, but the +hardware level details could be very different. + + +Systems need specialized hardware support to implement OTG, +notably including a special Mini-AB jack +and associated transciever to support Dual-Role +operation: +they can act either as a host, using the standard +Linux-USB host side driver stack, +or as a peripheral, using this "gadget" framework. +To do that, the system software relies on small additions +to those programming interfaces, +and on a new internal component (here called an "OTG Controller") +affecting which driver stack connects to the OTG port. +In each role, the system can re-use the existing pool of +hardware-neutral drivers, layered on top of the controller +driver interfaces (usb_bus or +usb_gadget). +Such drivers need at most minor changes, and most of the calls +added to support OTG can also benefit non-OTG products. + + + + Gadget drivers test the is_otg + flag, and use it to determine whether or not to include + an OTG descriptor in each of their configurations. + + Gadget drivers may need changes to support the + two new OTG protocols, exposed in new gadget attributes + such as b_hnp_enable flag. + HNP support should be reported through a user interface + (two LEDs could suffice), and is triggered in some cases + when the host suspends the peripheral. + SRP support can be user-initiated just like remote wakeup, + probably by pressing the same button. + + On the host side, USB device drivers need + to be taught to trigger HNP at appropriate moments, using + usb_suspend_device(). + That also conserves battery power, which is useful even + for non-OTG configurations. + + Also on the host side, a driver must support the + OTG "Targeted Peripheral List". That's just a whitelist, + used to reject peripherals not supported with a given + Linux OTG host. + This whitelist is product-specific; + each product must modify otg_whitelist.h + to match its interoperability specification. + + + Non-OTG Linux hosts, like PCs and workstations, + normally have some solution for adding drivers, so that + peripherals that aren't recognized can eventually be supported. + That approach is unreasonable for consumer products that may + never have their firmware upgraded, and where it's usually + unrealistic to expect traditional PC/workstation/server kinds + of support model to work. + For example, it's often impractical to change device firmware + once the product has been distributed, so driver bugs can't + normally be fixed if they're found after shipment. + + + + +Additional changes are needed below those hardware-neutral +usb_bus and usb_gadget +driver interfaces; those aren't discussed here in any detail. +Those affect the hardware-specific code for each USB Host or Peripheral +controller, and how the HCD initializes (since OTG can be active only +on a single port). +They also involve what may be called an OTG Controller +Driver, managing the OTG transceiver and the OTG state +machine logic as well as much of the root hub behavior for the +OTG port. +The OTG controller driver needs to activate and deactivate USB +controllers depending on the relevant device role. +Some related changes were needed inside usbcore, so that it +can identify OTG-capable devices and respond appropriately +to HNP or SRP protocols. + + + Socket Filter !Enet/core/filter.c + Generic Network Statistics +!Iinclude/linux/gen_stats.h +!Enet/core/gen_stats.c +!Enet/core/gen_estimator.c + diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index 0424c92f5..1e8219d85 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -145,7 +145,7 @@ In user context, the current pointer (indicating the task we are currently executing) is valid, and in_interrupt() - (include/asm/hardirq.h) is false + (include/linux/interrupt.h) is false . @@ -241,7 +241,7 @@ You can tell you are in a softirq (or bottom half, or tasklet) using the in_softirq() macro - (include/asm/hardirq.h). + (include/linux/interrupt.h). @@ -888,7 +888,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress)); The second class of atomic operations is atomic bit operations on a long, defined in - include/asm/bitops.h. These + include/linux/bitops.h. These operations generally take a pointer to the bit pattern, and a bit number: 0 is the least significant bit. set_bit(), clear_bit() diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index ac0d5fc0a..92a405a0e 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -61,6 +61,196 @@ + + libata Driver API + + struct ata_port_operations + + +void (*port_disable) (struct ata_port *); + + + + Called from ata_bus_probe() and ata_bus_reset() error paths, + as well as when unregistering from the SCSI module (rmmod, hot + unplug). + + + +void (*dev_config) (struct ata_port *, struct ata_device *); + + + + Called after IDENTIFY [PACKET] DEVICE is issued to each device + found. Typically used to apply device-specific fixups prior to + issue of SET FEATURES - XFER MODE, and prior to operation. + + + +void (*set_piomode) (struct ata_port *, struct ata_device *); +void (*set_dmamode) (struct ata_port *, struct ata_device *); +void (*post_set_mode) (struct ata_port *ap); + + + + Hooks called prior to the issue of SET FEATURES - XFER MODE + command. dev->pio_mode is guaranteed to be valid when + ->set_piomode() is called, and dev->dma_mode is guaranteed to be + valid when ->set_dmamode() is called. ->post_set_mode() is + called unconditionally, after the SET FEATURES - XFER MODE + command completes successfully. + + + + ->set_piomode() is always called (if present), but + ->set_dma_mode() is only called if DMA is possible. + + + +void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); +void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); + + + + ->tf_load() is called to load the given taskfile into hardware + registers / DMA buffers. ->tf_read() is called to read the + hardware registers / DMA buffers, to obtain the current set of + taskfile register values. + + + +void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); + + + + causes an ATA command, previously loaded with + ->tf_load(), to be initiated in hardware. + + + +u8 (*check_status)(struct ata_port *ap); +void (*dev_select)(struct ata_port *ap, unsigned int device); + + + + Reads the Status ATA shadow register from hardware. On some + hardware, this has the side effect of clearing the interrupt + condition. + + + +void (*dev_select)(struct ata_port *ap, unsigned int device); + + + + Issues the low-level hardware command(s) that causes one of N + hardware devices to be considered 'selected' (active and + available for use) on the ATA bus. + + + +void (*phy_reset) (struct ata_port *ap); + + + + The very first step in the probe phase. Actions vary depending + on the bus type, typically. After waking up the device and probing + for device presence (PATA and SATA), typically a soft reset + (SRST) will be performed. Drivers typically use the helper + functions ata_bus_reset() or sata_phy_reset() for this hook. + + + +void (*bmdma_setup) (struct ata_queued_cmd *qc); +void (*bmdma_start) (struct ata_queued_cmd *qc); + + + + When setting up an IDE BMDMA transaction, these hooks arm + (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA + engine. + + + +void (*qc_prep) (struct ata_queued_cmd *qc); +int (*qc_issue) (struct ata_queued_cmd *qc); + + + + Higher-level hooks, these two hooks can potentially supercede + several of the above taskfile/DMA engine hooks. ->qc_prep is + called after the buffers have been DMA-mapped, and is typically + used to populate the hardware's DMA scatter-gather table. + Most drivers use the standard ata_qc_prep() helper function, but + more advanced drivers roll their own. + + + ->qc_issue is used to make a command active, once the hardware + and S/G tables have been prepared. IDE BMDMA drivers use the + helper function ata_qc_issue_prot() for taskfile protocol-based + dispatch. More advanced drivers roll their own ->qc_issue + implementation, using this as the "issue new ATA command to + hardware" hook. + + + +void (*eng_timeout) (struct ata_port *ap); + + + + This is a high level error handling function, called from the + error handling thread, when a command times out. + + + +irqreturn_t (*irq_handler)(int, void *, struct pt_regs *); +void (*irq_clear) (struct ata_port *); + + + + ->irq_handler is the interrupt handling routine registered with + the system, by libata. ->irq_clear is called during probe just + before the interrupt handler is registered, to be sure hardware + is quiet. + + + +u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg); +void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, + u32 val); + + + + Read and write standard SATA phy registers. Currently only used + if ->phy_reset hook called the sata_phy_reset() helper function. + + + +int (*port_start) (struct ata_port *ap); +void (*port_stop) (struct ata_port *ap); +void (*host_stop) (struct ata_host_set *host_set); + + + + ->port_start() is called just after the data structures for each + port are initialized. Typically this is used to alloc per-port + DMA buffers / tables / rings, enable DMA engines, and similar + tasks. + + + ->host_stop() is called when the rmmod or hot unplug process + begins. The hook must stop all hardware interrupts, DMA + engines, etc. + + + ->port_stop() is called after ->host_stop(). It's sole function + is to release DMA/memory resources, now that they are no longer + actively being used. + + + + + libata Library !Edrivers/scsi/libata-core.c @@ -83,7 +273,7 @@ - ata_sil Internals + sata_sil Internals !Idrivers/scsi/sata_sil.c diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl index 669b0466a..34206230c 100644 --- a/Documentation/DocBook/procfs-guide.tmpl +++ b/Documentation/DocBook/procfs-guide.tmpl @@ -100,8 +100,8 @@ I'd like to thank Jeff Garzik jgarzik@pobox.com and Alexander Viro - viro@math.psu.edu for their input, Tim Waugh - twaugh@redhat.com for his viro@parcelfarce.linux.theplanet.co.uk for their input, + Tim Waugh twaugh@redhat.com for his Selfdocbook, and Marc Joosen marcj@historia.et.tudelft.nl for proofreading. diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl index 52e4fd691..0f0c3a33b 100644 --- a/Documentation/DocBook/usb.tmpl +++ b/Documentation/DocBook/usb.tmpl @@ -251,6 +251,7 @@ !Edrivers/usb/core/message.c !Edrivers/usb/core/file.c !Edrivers/usb/core/usb.c +!Edrivers/usb/core/hub.c Host Controller APIs diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl index 45243eeb2..2c92b1836 100644 --- a/Documentation/DocBook/videobook.tmpl +++ b/Documentation/DocBook/videobook.tmpl @@ -731,13 +731,14 @@ static int io = 0x300; static int io = -1; +#endif MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("A driver for an imaginary radio card."); -MODULE_PARM(io, "i"); +module_param(io, int, 0444); MODULE_PARM_DESC(io, "I/O address of the card."); -int init_module(void) +static int __init init(void) { if(io==-1) { @@ -748,25 +749,26 @@ int init_module(void) return myradio_init(NULL); } -void cleanup_module(void) +static void __exit cleanup(void) { video_unregister_device(&my_radio); release_region(io, MY_IO_SIZE); } -#endif +module_init(init); +module_exit(cleanup); In this example we set the IO base by default if the driver is compiled into - the kernel where you cannot pass a parameter. For the module we require the + the kernel: you can still set it using "my_radio.irq" if this file is called my_radio.c. For the module we require the user sets the parameter. We set io to a nonsense port (-1) so that we can tell if the user supplied an io parameter or not. We use MODULE_ defines to give an author for the card driver and a description. We also use them to declare that io is an integer and it is the - address of the card. + address of the card, and can be read by anyone from sysfs. The clean-up routine unregisters the video_device we registered, and frees diff --git a/Documentation/IO-mapping.txt b/Documentation/IO-mapping.txt index ddc817346..86edb61bd 100644 --- a/Documentation/IO-mapping.txt +++ b/Documentation/IO-mapping.txt @@ -119,9 +119,10 @@ you can't use it from the bus master. So why do we care about the physical address at all? We do need the physical address in some cases, it's just not very often in normal code. The physical address is needed if you use memory mappings, for example, because the -"remap_page_range()" mm function wants the physical address of the memory to -be remapped (the memory management layer doesn't know about devices outside -the CPU, so it shouldn't need to know about "bus addresses" etc). +"remap_pfn_range()" mm function wants the physical address of the memory to +be remapped as measured in units of pages, a.k.a. the pfn (the memory +management layer doesn't know about devices outside the CPU, so it +shouldn't need to know about "bus addresses" etc). NOTE NOTE NOTE! The above is only one part of the whole equation. The above only talks about "real memory", that is, CPU memory (RAM). diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index 583eb0d58..d6dcb2769 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt @@ -340,6 +340,8 @@ You can change this at module load time (for a module) with: modprobe ipmi_si.o type=,.... ports=,... addrs=,... irqs=,... trydefaults=[0|1] + regspacings=,,... regsizes=,,... + regshifts=,,... Each of these except si_trydefaults is a list, the first item for the first interface, second item for the second interface, etc. @@ -361,12 +363,35 @@ si_trydefaults sets whether the standard IPMI interface at 0xca2 and any interfaces specified by ACPE are tried. By default, the driver tries it, set this value to zero to turn this off. +The next three parameters have to do with register layout. The +registers used by the interfaces may not appear at successive +locations and they may not be in 8-bit registers. These parameters +allow the layout of the data in the registers to be more precisely +specified. + +The regspacings parameter give the number of bytes between successive +register start addresses. For instance, if the regspacing is set to 4 +and the start address is 0xca2, then the address for the second +register would be 0xca6. This defaults to 1. + +The regsizes parameter gives the size of a register, in bytes. The +data used by IPMI is 8-bits wide, but it may be inside a larger +register. This parameter allows the read and write type to specified. +It may be 1, 2, 4, or 8. The default is 1. + +Since the register size may be larger than 32 bits, the IPMI data may not +be in the lower 8 bits. The regshifts parameter give the amount to shift +the data to get to the actual IPMI data. + When compiled into the kernel, the addresses can be specified on the kernel command line as: ipmi_si.type=,... ipmi_si.ports=,... ipmi_si.addrs=,... ipmi_si.irqs=,... ipmi_si.trydefaults=[0|1] + ipmi_si.regspacings=,,... + ipmi_si.regsizes=,,... + ipmi_si.regshifts=,,... It works the same as the module parameters of the same names. @@ -496,3 +521,8 @@ start a 120 timer if it is running to make sure the reboot occurs. Note that if you use the NMI preaction for the watchdog, you MUST NOT use nmi watchdog mode 1. If you use the NMI watchdog, you must use mode 2. + +Once you open the watchdog timer, you must write a 'V' character to the +device to close it, or the timer will not stop. This is a new semantic +for the driver, but makes it consistent with the rest of the watchdog +drivers in Linux. diff --git a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt index 46950afda..bda6ead69 100644 --- a/Documentation/RCU/listRCU.txt +++ b/Documentation/RCU/listRCU.txt @@ -82,7 +82,7 @@ lock might be used as follows for deletion and insertion: list_for_each_entry(e, list, list) { if (!audit_compare_rule(rule, &e->rule)) { list_del(&e->list); - call_rcu(&e->rcu, audit_free_rule, e); + write_unlock(&auditsc_lock); return 0; } } diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index a851d039a..fad566bb0 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting @@ -118,6 +118,10 @@ to store page tables. The recommended placement is 32KiB into RAM. In either case, the following conditions must be met: +- Quiesce all DMA capable devicess so that memory does not get + corrupted by bogus network packets or disk data. This will save + you many hours of debug. + - CPU register settings r0 = 0, r1 = machine type number discovered in (3) above. diff --git a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000 index 48ba502fa..969f16593 100644 --- a/Documentation/arm/IXP2000 +++ b/Documentation/arm/IXP2000 @@ -18,7 +18,7 @@ http://developer.intel.com/design/network/products/npfamily/ixp2xxx.htm 2. Linux Support -Linux currently supports the following features on the IXP2000 NPUS: +Linux currently supports the following features on the IXP2000 NPUs: - On-chip serial - PCI @@ -30,10 +30,10 @@ That is about all we can support under Linux ATM b/c the core networking components of the chip are accessed via Intel's closed source SDK. Please contact Intel directly on issues with using those. There is also a mailing list run by some folks at Princeton University that might -be of helpful: https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx +be of help: https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx WHATEVER YOU DO, DO NOT POST EMAIL TO THE LINUX-ARM OR LINUX-ARM-KERNEL -MAILINNG LISTS REGARDING THE INTEL SDK. +MAILING LISTS REGARDING THE INTEL SDK. 3. Supported Platforms @@ -47,12 +47,12 @@ MAILINNG LISTS REGARDING THE INTEL SDK. - The IXP2000 platforms ususally have rather complex PCI bus topologies with large memory space requirements. In addition, b/c of the way the - Intel SDK is designed, devices are enumerated in a vert specific + Intel SDK is designed, devices are enumerated in a very specific way. B/c of this this, we use "pci=firmware" option in the kernel command line so that we do not re-enumerate the bus. - IXDP2x01 systems have variable clock tick rates that we cannot determine - via HW registers. The "ixdp2x01_clk=XXX" cmd line options allows you + via HW registers. The "ixdp2x01_clk=XXX" cmd line options allow you to pass the clock rate to the board port. 5. Thanks diff --git a/Documentation/arm/IXP4xx b/Documentation/arm/IXP4xx index d86d818a4..2e1590b42 100644 --- a/Documentation/arm/IXP4xx +++ b/Documentation/arm/IXP4xx @@ -122,6 +122,15 @@ http://developer.intel.com/design/network/products/npfamily/ixdp425.htm also known as the Richfield board. It contains 4 PCI slots, 16MB of flash, two 10/100 ports and one ADSL port. +Intel IXDPG425 Development Platform + + This is basically and ADI Coyote board with a NEC EHCI controller + added. One issue with this board is that the mini-PCI slots only + have the 3.3v line connected, so you can't use a PCI to mini-PCI + adapter with an E100 card. So to NFS root you need to use either + the CSR or a WiFi card and a ramdisk that BOOTPs and then does + a pivot_root to NFS. + Motorola PrPMC1100 Processor Mezanine Card http://www.fountainsys.com/datasheet/PrPMC1100.pdf @@ -152,4 +161,4 @@ Robert E. Ranslam ------------------------------------------------------------------------- -Last Update: 5/13/2004 +Last Update: 11/16/2004 diff --git a/Documentation/arm/README b/Documentation/arm/README index 1dd5d6cb7..a6f718e90 100644 --- a/Documentation/arm/README +++ b/Documentation/arm/README @@ -163,9 +163,9 @@ CONFIG_MACH_ and CONFIG_ARCH_ -Kernel entry (head-armv.S) +Kernel entry (head.S) -------------------------- - The initial entry into the kernel is via head-armv.S, which uses machine + The initial entry into the kernel is via head.S, which uses machine independent code. The machine is selected by the value of 'r1' on entry, which must be kept unique. diff --git a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt index 831b98c73..000e3d7a7 100644 --- a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt +++ b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt @@ -15,7 +15,7 @@ Configuration ------------- To set the default configuration, use `make bast_defconfig` which - supports the commonly used features of this board + supports the commonly used features of this board. Support @@ -23,15 +23,23 @@ Support Official support information can be found on the Simtec Electronics website, at the product page http://www.simtec.co.uk/products/EB2410ITX/ - and http://www.simtec.co.uk/products/EB2410ITX/resources.html + + Useful links: + + - Resources Page http://www.simtec.co.uk/products/EB2410ITX/resources.html + + - Board FAQ at http://www.simtec.co.uk/products/EB2410ITX/faq.html + + - Bootloader info http://www.simtec.co.uk/products/SWABLE/resources.html + and FAQ http://www.simtec.co.uk/products/SWABLE/faq.html MTD --- - The NAND and NOR onboard are currently supported in the linux-mtd cvs, - and are awaiting merge in the mainline. see the linux-mtd project at - http://www.linux-mtd.infradead.org/ for more information. + The NAND and NOR support has been merged from the linux-mtd project. + Any prolbems, see http://www.linux-mtd.infradead.org/ for more + information or up-to-date versions of linux-mtd. IDE @@ -41,4 +49,10 @@ IDE changing speed of devices, PIO Mode 4 capable drives should be used. +Maintainers +----------- + + This board is maintained by Simtec Electronics. + + (c) 2004 Ben Dooks, Simtec Electronics diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt index aa3f83aa2..b8ba49250 100644 --- a/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt @@ -48,9 +48,9 @@ Machines NAND ---- - The current kernels do not have direct support for the NAND - controller, the latest linux-mtd CVS has support for this. - See http://www.linux-mtd.infradead.org/ + The current kernels now have support for the s3c2410 NAND + controller. If there are any problems the latest linux-mtd + CVS can be found from http://www.linux-mtd.infradead.org/ Serial @@ -84,12 +84,21 @@ Clock Management Port Contributors ----------------- - Ben Dooks + Ben Dooks (BJD) Vincent Sanders Herbert Potzl - Arnaud Patard + Arnaud Patard (RTP) Roc Wu + Klaus Fetscher + Dimitry Andric +Document Changes +---------------- + + 05 Sep 2004 - BJD - Added Document Changes section + 05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors + 25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors + 25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge Document Author --------------- diff --git a/Documentation/arm/Sharp-LH/IOBarrier b/Documentation/arm/Sharp-LH/IOBarrier index bf34e046e..c0d885367 100644 --- a/Documentation/arm/Sharp-LH/IOBarrier +++ b/Documentation/arm/Sharp-LH/IOBarrier @@ -5,7 +5,7 @@ Due to an unfortunate oversight when the Card Engines were designed, the signals that control access to some peripherals, most notably the SMC91C9111 ethernet controller, are not properly handled. -The symptom is that back to back IO with the peripheral returns +The symptom is that some back to back IO with the peripheral returns unreliable data. With the SMC chip, you'll see errors about the bank register being 'screwed'. @@ -13,20 +13,33 @@ The cause is that the AEN signal to the SMC chip does not transition for every memory access. It is driven through the CPLD from the CS7 line of the CPU's static memory controller which is optimized to eliminate unnecessary transitions. Yet, the SMC requires a transition -for every access. The Sharp website has more information on the -effect of this power conservation feature on peripheral interfacing. +for every write access. The Sharp website has more information about +the effect this power-conserving feature has on peripheral +interfacing. -The solution is to follow every access to the SMC chip with an access -to another memory region that will force the CPU to release the chip -select line. Note that it is important to guarantee that the access -will force the CPU off-chip. We map a page of SDRAM as if it were an -uncacheable IO device and read from it after every SMC IO operation. +The solution is to follow every write access to the SMC chip with an +access to another memory region that will force the CPU to release the +chip select line. It is important to guarantee that this access +forces the CPU off-chip. We map a page of SDRAM as if it were an +uncacheable IO device and read from it after every SMC IO write +operation. SMC IO BARRIER IO -You might be tempted to believe that we must access another device +Only this sequence is important. It does not matter that there is no +BARRIER IO before the access to the SMC chip because the AEN latch +only needs occurs after the SMC IO write cycle. The routines that +implement this work-around make an additional concession which is to +disable interrupts during the IO sequence. Other hardware devices +(the LogicPD CPLD) have registers in the same the physical memory +region as the SMC chip. An interrupt might allow an access to one of +those registers while SMC IO is being performed. + +You might be tempted to think that we have to access another device attached to the static memory controller, but the empirical evidence indicates that this is not so. Mapping 0x00000000 (flash) and 0xc0000000 (SDRAM) appear to have the same effect. Using SDRAM seems -to be faster. +to be faster. Choosing to access an undecoded memory region is not +desirable as there is no way to know how that chip select will be used +in the future. diff --git a/Documentation/block/as-iosched.txt b/Documentation/block/as-iosched.txt index fd763cc48..6f47332c8 100644 --- a/Documentation/block/as-iosched.txt +++ b/Documentation/block/as-iosched.txt @@ -132,7 +132,7 @@ a combination of IO behavior from all those devices. Tuning the anticipatory IO scheduler ------------------------------------ When using 'as', the anticipatory IO scheduler there are 5 parameters under -/sys/block/*/iosched/. All are units of milliseconds. +/sys/block/*/queue/iosched/. All are units of milliseconds. The parameters are: * read_expire diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index f24dbcaca..6dd274d7e 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -1172,8 +1172,7 @@ PIO drivers (or drivers that need to revert to PIO transfer once in a while (IDE for example)), where the CPU is doing the actual data transfer a virtual mapping is needed. If the driver supports highmem I/O, (Sec 1.1, (ii) ) it needs to use __bio_kmap_atomic and bio_kmap_irq to -temporarily map a bio into the virtual address space. See how IDE handles -this with ide_map_buffer. +temporarily map a bio into the virtual address space. 8. Prior/Related/Impacted patches diff --git a/Documentation/block/deadline-iosched.txt b/Documentation/block/deadline-iosched.txt index 2b1318600..c918b3a60 100644 --- a/Documentation/block/deadline-iosched.txt +++ b/Documentation/block/deadline-iosched.txt @@ -9,7 +9,7 @@ Each io queue has a set of io scheduler tunables associated with it. These tunables control how the io scheduler works. You can find these entries in: -/sys/block//iosched +/sys/block//queue/iosched assuming that you have sysfs mounted on /sys. If you don't have sysfs mounted, you can do so by typing: diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index 26bb2b405..9e2f988a8 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt @@ -354,10 +354,6 @@ maps this page at its virtual address. of arbitrary user pages (f.e. for ptrace()) it will use these two routines. - The page has been kmap()'d, and flush_cache_page() has - just been called for the user mapping of this page (if - necessary). - Any necessary cache flushing or other coherency operations that need to occur should happen here. If the processor's instruction cache does not snoop cpu stores, it is very diff --git a/Documentation/cdrom/00-INDEX b/Documentation/cdrom/00-INDEX index eae689667..916dafe29 100644 --- a/Documentation/cdrom/00-INDEX +++ b/Documentation/cdrom/00-INDEX @@ -22,6 +22,8 @@ mcdx - info on improved Mitsumi CD-ROM driver. optcd - info on the Optics Storage 8000 AT CD-ROM driver +packet-writing.txt + - Info on the CDRW packet writing module sbpcd - info on the SoundBlaster/Panasonic CD-ROM interface driver. sjcd diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex index 0a51967fe..92f94e597 100644 --- a/Documentation/cdrom/cdrom-standard.tex +++ b/Documentation/cdrom/cdrom-standard.tex @@ -360,13 +360,11 @@ up the disc, etc. % and device-use count \subsection{$Void\ release(struct\ cdrom_device_info * cdi)$} -In case of module support, a single call $MOD_DEC_USE_COUNT$ should be -coded here. Possibly other device-specific actions should be taken -such as spinning down the device. However, strategic actions such as -ejection of the tray, or unlocking the door, should be left over to -the general routine $cdrom_release()$. Also, the invalidation of the -allocated buffers in the VFS is taken care of by the routine in -\cdromc. This is the only function returning type $void$. + +Device-specific actions should be taken such as spinning down the device. +However, strategic actions such as ejection of the tray, or unlocking +the door, should be left over to the general routine $cdrom_release()$. +This is the only function returning type $void$. \subsection{$Int\ drive_status(struct\ cdrom_device_info * cdi, int\ slot_nr)$} \label{drive status} diff --git a/Documentation/ckrm/ckrm_basics b/Documentation/ckrm/ckrm_basics index cfd9a9256..6602c59b0 100644 --- a/Documentation/ckrm/ckrm_basics +++ b/Documentation/ckrm/ckrm_basics @@ -33,12 +33,16 @@ shares: allows to change the shares of different resources managed by the class stats: allows to see the statistics associated with each resources managed by the class -target: allows to assign a task to a class. If a CE is present, assigning - a task to a class through this interface will prevent CE from - reassigning the task to any class during reclassification. -members: allows to see which tasks has been assigned to a class +target: obsolete. functionality moved to 'members' file. +members: allows to assign a task to a class and to see which tasks has + been assigned to a class. + If a CE is present, assigning a task to a class through this + interface will prevent CE from reassigning the task to any class + during reclassification. config: allow to view and modify configuration information of different resources in a class. +reclassify: When CE is present, allows a task to be reclassified by CE. In + the absence of CE, this file provides no functionality. Resource allocations for a class is controlled by the parameters: diff --git a/Documentation/ckrm/core_usage b/Documentation/ckrm/core_usage index 6b5d808c3..f5004602c 100644 --- a/Documentation/ckrm/core_usage +++ b/Documentation/ckrm/core_usage @@ -9,7 +9,7 @@ Usage of CKRM without a classification engine creates a socketclass named s1 The newly created class directory is automatically populated by magic files -shares, stats, members, target and config. +shares, stats, members, config and reclassify. 2. View default shares @@ -34,11 +34,11 @@ shares, stats, members, target and config. 4. Reclassify a task (listening socket) - write the pid of the process to the destination class' target file - # echo 1004 > /rcfs/taskclass/c1/target + write the pid of the process to the destination class' members file + # echo 1004 > /rcfs/taskclass/c1/members - write the "\" string to the destination class' target file - # echo "0.0.0.0\32770" > /rcfs/taskclass/c1/target + write the "\" string to the destination class' members file + # echo "0.0.0.0\32770" > /rcfs/taskclass/c1/members 5. Get a list of tasks (sockets) assigned to a taskclass (socketclass) diff --git a/Documentation/computone.txt b/Documentation/computone.txt index ea2b5d3e3..b1cf59b84 100644 --- a/Documentation/computone.txt +++ b/Documentation/computone.txt @@ -1,3 +1,13 @@ +NOTE: This is an unmaintained driver. It is not guaranteed to work due to +changes made in the tty layer in 2.6. If you wish to take over maintenance of +this driver, contact Michael Warfield . + +Changelog: +---------- +11-01-2001: Original Document + +10-29-2004: Minor misspelling & format fix, update status of driver. + James Nelson Computone Intelliport II/Plus Multiport Serial Driver ----------------------------------------------------- @@ -146,7 +156,7 @@ selects polled mode). If no base addresses are specified the defaults in ip2.c are used. If you are autoloading the driver module with kerneld or kmod the base addresses and interrupt number must also be set in ip2.c and recompile or just insert and options line in /etc/modprobe.conf or both. -The options line is equivalent to the command line and takes precidence over +The options line is equivalent to the command line and takes precedence over what is in ip2.c. /etc/modprobe.conf sample: @@ -166,7 +176,8 @@ The equivalent for the kernel command line (in lilo.conf): Note: Both io and irq should be updated to reflect YOUR system. An "io" - address of 1 or 2 indicates a PCI or EISA card in the board table. The PCI or EISA irq will be assigned automatically. + address of 1 or 2 indicates a PCI or EISA card in the board table. + The PCI or EISA irq will be assigned automatically. Specifying an invalid or in-use irq will default the driver into running in polled mode for that card. If all irq entries are 0 then diff --git a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt index d0e185f7c..c7154e20e 100644 --- a/Documentation/cpqarray.txt +++ b/Documentation/cpqarray.txt @@ -26,31 +26,13 @@ unable to test against these cards: * IDA-2 * IAES -Installing: ------------ - -You need to build a new kernel to use this device, even if you want to -use a loadable module. - -Apply the patch to a 2.2.x kernel: - -# cd linux -# patch -p1 + + +1999 : Original Document diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index 5e6391ca9..7fedc00c3 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -65,6 +65,7 @@ Intel Pentium 4, Intel Xeon Intel Pentium M (Centrino) National Semiconductors Geode GX Transmeta Crusoe +Transmeta Efficeon VIA Cyrix 3 / C3 various processors on some ACPI 2.0-compatible systems [*] diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt index 1df474c4e..fa0c8b974 100644 --- a/Documentation/crypto/api-intro.txt +++ b/Documentation/crypto/api-intro.txt @@ -227,6 +227,13 @@ TEA/XTEA algorithm contributors: Khazad algorithm contributors: Aaron Grothe +Whirlpool algorithm contributors: + Aaron Grothe + Jean-Luc Cooke + +Anubis algorithm contributors: + Aaron Grothe + Generic scatterwalk code by Adam J. Richter Please send any credits updates or corrections to: diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 954e49636..f115145e5 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -1,9 +1,9 @@ LINUX ALLOCATED DEVICES - Maintained by John Cagle + Maintained by Torben Mathiasen - Last revised: 15 March 2004 + Last revised: 04 August 2004 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -410,6 +410,7 @@ Your cooperation is appreciated. 199 = /dev/scanners/cuecat :CueCat barcode scanner 200 = /dev/net/tun TAP/TUN network device 201 = /dev/button/gulpb Transmeta GULP-B buttons + 202 = /dev/emd/ctl Enhanced Metadisk RAID (EMD) control 204 = /dev/video/em8300 EM8300 DVD decoder control 205 = /dev/video/em8300_mv EM8300 DVD decoder video 206 = /dev/video/em8300_ma EM8300 DVD decoder audio @@ -1682,11 +1683,16 @@ Your cooperation is appreciated. 1 = /dev/dcxx1 Second capture card ... - 94 block Inverse NAND Flash Translation Layer - 0 = /dev/inftla First INFTL layer - 16 = /dev/inftlb Second INFTL layer + 94 block IBM S/390 DASD block storage + 0 = /dev/dasda First DASD device, major + 1 = /dev/dasda1 First DASD device, block 1 + 2 = /dev/dasda2 First DASD device, block 2 + 3 = /dev/dasda3 First DASD device, block 3 + 4 = /dev/dasdb Second DASD device, major + 5 = /dev/dasdb1 Second DASD device, block 1 + 6 = /dev/dasdb2 Second DASD device, block 2 + 7 = /dev/dasdb3 Second DASD device, block 3 ... - 240 = /dev/inftlp 16th INTFL layer 95 char IP filter 0 = /dev/ipl Filter control device/log file @@ -1695,15 +1701,9 @@ Your cooperation is appreciated. 3 = /dev/ipauth Authentication control device/log file ... - 95 block IBM S/390 DASD block storage - 0 = /dev/dasd0 First DASD device, major - 1 = /dev/dasd0a First DASD device, block 1 - 2 = /dev/dasd0b First DASD device, block 2 - 3 = /dev/dasd0c First DASD device, block 3 - 4 = /dev/dasd1 Second DASD device, major - 5 = /dev/dasd1a Second DASD device, block 1 - 6 = /dev/dasd1b Second DASD device, block 2 - 7 = /dev/dasd1c Second DASD device, block 3 + 95 block IBM S/390 VM/ESA minidisk + 0 = /dev/msd0 First VM/ESA minidisk + 1 = /dev/msd1 Second VM/ESA minidisk ... 96 char Parallel port ATAPI tape devices @@ -1714,10 +1714,11 @@ Your cooperation is appreciated. 129 = /dev/npt1 Second p.p. ATAPI tape, no rewind ... - 96 block IBM S/390 VM/ESA minidisk - 0 = /dev/msd0 First VM/ESA minidisk - 1 = /dev/msd1 Second VM/ESA minidisk + 96 block Inverse NAND Flash Translation Layer + 0 = /dev/inftla First INFTL layer + 16 = /dev/inftlb Second INFTL layer ... + 240 = /dev/inftlp 16th INTFL layer 97 char Parallel port generic ATAPI interface 0 = /dev/pg0 First parallel port ATAPI device @@ -1796,14 +1797,15 @@ Your cooperation is appreciated. partitions is 15. 103 char Arla network file system - 0 = /dev/xfs0 Arla XFS + 0 = /dev/nnpfs0 First NNPFS device + 1 = /dev/nnpfs1 Second NNPFS device Arla is a free clone of the Andrew File System, AFS. - Any resemblance with the Swedish milk producer is - coincidental. For more information about the project, - write to or subscribe - to the arla announce mailing list by sending a mail to - . + The NNPFS device gives user mode filesystem + implementations a kernel presence for caching and easy + mounting. For more information about the project, + write to or see + http://www.stacken.kth.se/project/arla/ 103 block Audit device 0 = /dev/audit Audit device @@ -2060,12 +2062,10 @@ Your cooperation is appreciated. device names. For example, /dev/hda5 would become /dev/evms/hda5. -118 char Solidum ??? - 0 = /dev/solnp0 - 1 = /dev/solnp1 - ... - 128 = /dev/solnpctl0 - 129 = /dev/solnpctl1 +118 char IBM Cryptographic Accelerator + 0 = /dev/ica Virtual interface to all IBM Crypto Accelerators + 1 = /dev/ica0 IBMCA Device 0 + 2 = /dev/ica1 IBMCA Device 1 ... 119 char VMware virtual network control @@ -2310,6 +2310,11 @@ Your cooperation is appreciated. 1 = /dev/aureal1 Second Aureal Vortex ... +147 block Distributed Replicated Block Device (DRBD) + 0 = /dev/drbd0 First DRBD device + 1 = /dev/drbd1 Second DRBD device + ... + 148 char Technology Concepts serial card 0 = /dev/ttyT0 First TCL port 1 = /dev/ttyT1 Second TCL port @@ -2346,6 +2351,22 @@ Your cooperation is appreciated. ... 15 = /dev/spi15 Sixteenth SPI device on the bus +153 block Enhanced Metadisk RAID (EMD) storage units + 0 = /dev/emd/0 First unit + 1 = /dev/emd/0p1 Partition 1 on First unit + 2 = /dev/emd/0p2 Partition 2 on First unit + ... + 15 = /dev/emd/0p15 Partition 15 on First unit + + 16 = /dev/emd/1 Second unit + 32 = /dev/emd/2 Third unit + ... + 240 = /dev/emd/15 Sixteenth unit + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + 154 char Specialix RIO serial card 0 = /dev/ttySR0 First RIO port ... @@ -2371,23 +2392,24 @@ Your cooperation is appreciated. 1 = /dev/gfax1 GammaLink channel 1 ... -159 RESERVED +159 char RESERVED +159 block RESERVED 160 char General Purpose Instrument Bus (GPIB) 0 = /dev/gpib0 First GPIB bus 1 = /dev/gpib1 Second GPIB bus ... -160 block Promise SX8 8-port SATA Disks on First Controller - 0 = /dev/sx8/0 SATA disk 0 whole disk - 1 = /dev/sx8/0p1 SATA disk 0 partition 1 +160 block Carmel 8-port SATA Disks on First Controller + 0 = /dev/carmel/0 SATA disk 0 whole disk + 1 = /dev/carmel/0p1 SATA disk 0 partition 1 ... - 31 = /dev/sx8/0p31 SATA disk 0 partition 31 + 31 = /dev/carmel/0p31 SATA disk 0 partition 31 - 32 = /dev/sx8/1 SATA disk 1 whole disk - 64 = /dev/sx8/2 SATA disk 2 whole disk + 32 = /dev/carmel/1 SATA disk 1 whole disk + 64 = /dev/carmel/2 SATA disk 2 whole disk ... - 224 = /dev/sx8/7 SATA disk 7 whole disk + 224 = /dev/carmel/7 SATA disk 7 whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on @@ -2401,16 +2423,16 @@ Your cooperation is appreciated. 17 = /dev/irlpt1 Second IrLPT device ... -161 block Promise SX8 8-port SATA Disks on Second Controller - 0 = /dev/sx8/8 SATA disk 8 whole disk - 1 = /dev/sx8/8p1 SATA disk 8 partition 1 +161 block Carmel 8-port SATA Disks on Second Controller + 0 = /dev/carmel/8 SATA disk 8 whole disk + 1 = /dev/carmel/8p1 SATA disk 8 partition 1 ... - 31 = /dev/sx8/8p31 SATA disk 8 partition 31 + 31 = /dev/carmel/8p31 SATA disk 8 partition 31 - 32 = /dev/sx8/9 SATA disk 9 whole disk - 64 = /dev/sx8/10 SATA disk 10 whole disk + 32 = /dev/carmel/9 SATA disk 9 whole disk + 64 = /dev/carmel/10 SATA disk 10 whole disk ... - 224 = /dev/sx8/15 SATA disk 15 whole disk + 224 = /dev/carmel/15 SATA disk 15 whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on @@ -2524,12 +2546,7 @@ Your cooperation is appreciated. 0 = /dev/usb/lp0 First USB printer ... 15 = /dev/usb/lp15 16th USB printer - 16 = /dev/usb/mouse0 First USB mouse - ... - 31 = /dev/usb/mouse15 16th USB mouse - 32 = /dev/usb/ez0 First USB firmware loader - ... - 47 = /dev/usb/ez15 16th USB firmware loader + 32 = /dev/usb/mdc800 MDC800 USB camera 48 = /dev/usb/scanner0 First USB scanner ... 63 = /dev/usb/scanner15 16th USB scanner @@ -2537,6 +2554,22 @@ Your cooperation is appreciated. 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) + 96 = /dev/usb/hiddev0 1st USB HID device + ... + 111 = /dev/usb/hiddev15 16th USB HID device + 112 = /dev/usb/auer0 1st auerswald ISDN device + ... + 127 = /dev/usb/auer15 16th auerswald ISDN device + 128 = /dev/usb/brlvgr0 First Braille Voyager device + ... + 131 = /dev/usb/brlvgr3 Fourth Braille Voyager device + 144 = /dev/usb/lcd USB LCD device + 160 = /dev/usb/legousbtower0 1st USB Legotower device + ... + 175 = /dev/usb/legousbtower15 16th USB Legotower device + 240 = /dev/usb/dabusb0 First daubusb device + ... + 243 = /dev/usb/dabusb3 Fourth dabusb device 181 char Conrad Electronic parallel port radio clocks 0 = /dev/pcfclock0 First Conrad radio clock @@ -2720,6 +2753,15 @@ Your cooperation is appreciated. ... 39 = /dev/ttyDB7 DataBooster serial port 7 40 = /dev/ttySG0 SGI Altix console port + 41 = /dev/ttySMX0 Motorola i.MX - port 0 + 42 = /dev/ttySMX1 Motorola i.MX - port 1 + 43 = /dev/ttySMX2 Motorola i.MX - port 2 + 44 = /dev/ttyMM0 Marvell MPSC - port 0 + 45 = /dev/ttyMM1 Marvell MPSC - port 1 + 46 = /dev/ttyCPM0 PPC CPM (SCC or SMC) - port 0 + ... + 49 = /dev/ttyCPM5 PPC CPM (SCC or SMC) - port 5 + 205 char Low-density serial ports (alternate device) 0 = /dev/culu0 Callout device for ttyLU0 @@ -2745,6 +2787,12 @@ Your cooperation is appreciated. ... 39 = /dev/cudb7 Callout device for ttyDB7 40 = /dev/cusg0 Callout device for ttySG0 + 41 = /dev/ttySMX0 Callout device for ttySMX0 + 42 = /dev/ttySMX1 Callout device for ttySMX1 + 43 = /dev/ttySMX2 Callout device for ttySMX2 + 46 = /dev/cucpm0 Callout device for ttyCPM0 + ... + 49 = /dev/cucpm5 Callout device for ttyCPM5 206 char OnStream SC-x0 tape devices 0 = /dev/osst0 First OnStream SCSI tape, mode 0 diff --git a/Documentation/digiepca.txt b/Documentation/digiepca.txt index 01c4adc59..88820fe38 100644 --- a/Documentation/digiepca.txt +++ b/Documentation/digiepca.txt @@ -1,3 +1,11 @@ +NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at +http://www.digi.com for PCI cards. They no longer maintain this driver, +and have no 2.6 driver for ISA cards. + +This driver requires a number of user-space tools. They can be aquired from +http://www.digi.com, but only works with 2.4 kernels. + + The Digi Intl. epca driver. ---------------------------- The Digi Intl. epca driver for Linux supports the following boards: @@ -64,9 +72,6 @@ drivers/char/README.epca for more details. Note, this driver REQUIRES that digiDload be executed prior to it being used. Failure to do this will result in an ENODEV error. -The latest version of the tool package is available at: -ftp://ftp.dgii.com/drivers/linux/released/async/ - Documentation: -------------- Complete documentation for this product may be found in the tool package. @@ -74,14 +79,8 @@ Complete documentation for this product may be found in the tool package. Sources of information and support: ----------------------------------- Digi Intl. support site for this product: --> digilnux@dgii.com -Related information and information concerning other drivers supporting -Digi Intl. products: - --> FTP: ftp://dgii.com --> Webpage: http://www.dgii.com --> Webpage: http://lameter.com/digi +-> http://www.digi.com Acknowledgments: ---------------- @@ -90,3 +89,10 @@ supporting the original public domain DigiBoard driver Copyright (C) 1994,1995 Troy De Jongh. Many thanks to Christoph Lameter (christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored and contributed to the original document. + +Changelog: +---------- +10-29-04: Update status of driver, remove dead links in document + James Nelson + +2000 (?) Original Document diff --git a/Documentation/dnotify.txt b/Documentation/dnotify.txt index 3434cb3d1..6984fca60 100644 --- a/Documentation/dnotify.txt +++ b/Documentation/dnotify.txt @@ -54,6 +54,12 @@ directory "b". Also, files that are unlinked, will still cause notifications in the last directory that they were linked to. +Configuration +------------- + +Dnotify is controlled via the CONFIG_DNOTIFY configuration option. When +disabled, fcntl(fd, F_NOTIFY, ...) will return -EINVAL. + Example ------- diff --git a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt index 70685dde3..dd62c7b80 100644 --- a/Documentation/driver-model/bus.txt +++ b/Documentation/driver-model/bus.txt @@ -5,20 +5,21 @@ Definition ~~~~~~~~~~ struct bus_type { - char * name; - rwlock_t lock; - atomic_t refcount; + char * name; - struct list_head node; - struct list_head devices; - struct list_head drivers; + struct subsystem subsys; + struct kset drivers; + struct kset devices; - struct driver_dir_entry dir; - struct driver_dir_entry device_dir; - struct driver_dir_entry driver_dir; + struct bus_attribute * bus_attrs; + struct device_attribute * dev_attrs; + struct driver_attribute * drv_attrs; - int (*match) (struct device * dev, struct device_driver * drv); - struct device (*add) (struct device * parent, char * bus_id); + int (*match)(struct device * dev, struct device_driver * drv); + int (*hotplug) (struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); + int (*suspend)(struct device * dev, u32 state); + int (*resume)(struct device * dev); }; int bus_register(struct bus_type * bus); @@ -47,7 +48,7 @@ Registration When a bus driver is initialized, it calls bus_register. This initializes the rest of the fields in the bus object and inserts it into a global list of bus types. Once the bus object is registered, -the fields in it (e.g. the rwlock_t) are usable by the bus driver. +the fields in it are usable by the bus driver. Callbacks @@ -71,40 +72,6 @@ When a driver is registered with the bus, the bus's list of devices is iterated over, and the match callback is called for each device that does not have a driver associated with it. -add(): Adding a child device -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The add callback is available to notify the bus about a child device -at a particular location. - -The parent parameter is the parent device of the child to be added. If -parent == NULL, the bus should add the device as a child of a default -parent device or as a child of the root. This policy decision is up to -the bus driver. - -The format of the bus_id field should be consistent with the format of -the bus_id field of the rest of the devices on the bus. This requires -the caller to know the format. - -On return, the bus driver should return a pointer to the device that -was created. If the device was not created, the bus driver should -return an appropriate error code. Refer to include/linux/err.h for -helper functions to encode errors. Some sample code: - -struct device * pci_bus_add(struct device * parent, char * bus_id) -{ - ... - /* the device already exists */ - return ERR_PTR(-EEXIST); - ... -} - -The caller can check the return value using IS_ERR(): - - struct device * newdev = pci_bus_type.add(parent,bus_id); - if (IS_ERR(newdev)) { - ... - } Device and Driver Lists @@ -118,10 +85,11 @@ necessary. The LDM core provides helper functions for iterating over each list. -int bus_for_each_dev(struct bus_type * bus, void * data, - int (*callback)(struct device * dev, void * data)); -int bus_for_each_drv(struct bus_type * bus, void * data, - int (*callback)(struct device_driver * drv, void * data)); +int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, + int (*fn)(struct device *, void *)); + +int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, + void * data, int (*fn)(struct device_driver *, void *)); These helpers iterate over the respective list, and call the callback for each device or driver in the list. All list accesses are @@ -168,9 +136,9 @@ hierarchy: Exporting Attributes ~~~~~~~~~~~~~~~~~~~~ struct bus_attribute { - struct attribute attr; - ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off); + struct attribute attr; + ssize_t (*show)(struct bus_type *, char * buf); + ssize_t (*store)(struct bus_type *, const char * buf, size_t count); }; Bus drivers can export attributes using the BUS_ATTR macro that works diff --git a/Documentation/dvb/avermedia.txt b/Documentation/dvb/avermedia.txt index 5d8dbdada..09020ebd2 100644 --- a/Documentation/dvb/avermedia.txt +++ b/Documentation/dvb/avermedia.txt @@ -6,7 +6,6 @@ HOWTO: Get An Avermedia DVB-T working under Linux Assumptions and Introduction The Avermedia DVB-T Getting the card going - Getting the Firmware Receiving DVB-T in Australia Known Limitations Further Update @@ -149,28 +148,9 @@ Getting the card going to start accessing the card with utilities such as scan, tzap, dvbstream etc. - The current version of the frontend module sp887x.o, contains - no firmware drivers?, so the first time you open it with a DVB - utility the driver will try to download some initial firmware - to the card. You will need to download this firmware from the - web, or copy it from an installation of the Windows drivers - that probably came with your card, before you can use it. - - The default Linux filesystem location for this firmware is - /usr/lib/hotplug/firmware/sc_main.mc . - _________________________________________________________ - -Getting the Firmware - - As the firmware for the card is no longer contained within the - driver, it is necessary to extract it from the windows - drivers. - - The Windows drivers for the Avermedia DVB-T can be obtained - from: http://babyurl.com/H3U970 and you can get an application - to extract the firmware from: - http://www.kyz.uklinux.net/cabextract.php. - _________________________________________________________ + The frontend module sp887x.o, requires an external firmware. + Please use the command "get_dvb_firmware sp887x" to download + it. Then copy it to /usr/lib/hotplug/firmware. Receiving DVB-T in Australia diff --git a/Documentation/dvb/cards.txt b/Documentation/dvb/cards.txt index 695f174d8..efdc4ee9d 100644 --- a/Documentation/dvb/cards.txt +++ b/Documentation/dvb/cards.txt @@ -38,6 +38,7 @@ o Frontends drivers: Comtech DVBT-6k07 (SP5730 PLL) (NxtWave Communications NXT6000 demodulator) - sp887x : Microtune 7202D + - dib3000mb : DiBcom 3000-MB demodulator DVB-S/C/T: - dst : TwinHan DST Frontend @@ -49,7 +50,7 @@ o Cards based on the Phillips saa7146 multimedia PCI bridge chip: - "budget" cards (i.e. without hardware MPEG decoder): - Technotrend Budget / Hauppauge WinTV-Nova PCI Cards - SATELCO Multimedia PCI - - KNC1 DVB-S + - KNC1 DVB-S, Typhoon DVB-S, Terratec Cinergy 1200 DVB-S (no CI support) - Typhoon DVB-S budget - Fujitsu-Siemens Activy DVB-S budget card @@ -66,4 +67,19 @@ o Technotrend / Hauppauge DVB USB devices: - Nova USB - DEC 2000-T, 3000-S, 2540-T +o DiBcom DVB-T USB based devices: + - Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device + - HAMA DVB-T USB device + - CTS Portable (Chinese Television System) + - KWorld V-Stream XPERT DTV DVB-T USB + - JetWay DTV DVB-T USB + - ADSTech Instant TV DVB-T USB + - Ultima Electronic/Artec T1 USB TVBOX (AN2135 and AN2235) + - Compro Videomate DVB-U2000 - DVB-T USB + - Grandtec USB DVB-T + - Avermedia AverTV DVBT USB + - DiBcom USB DVB-T reference device (non-public) + - Yakumo DVB-T mobile USB2.0 + - DiBcom USB2.0 DVB-T reference device (non-public) + o Experimental support for the analog module of the Siemens DVB-C PCI card diff --git a/Documentation/dvb/contributors.txt b/Documentation/dvb/contributors.txt index 12026e933..dd40ad665 100644 --- a/Documentation/dvb/contributors.txt +++ b/Documentation/dvb/contributors.txt @@ -69,6 +69,8 @@ Andreas 'randy' Weinberger Kenneth Aafløy for adding support for Typhoon DVB-S budget card +Ernst Peinlich + for tuning/DiSEqC support for the DEC 3000-s (If you think you should be in this list, but you are not, drop a line to the DVB mailing list) diff --git a/Documentation/dvb/readme.txt b/Documentation/dvb/readme.txt index 720aa8ce0..a60c27d43 100644 --- a/Documentation/dvb/readme.txt +++ b/Documentation/dvb/readme.txt @@ -28,9 +28,9 @@ is the who-is-who of DVB development "faq.txt" contains frequently asked questions and their answers. -"firmware.txt" -contains informations for required external firmware -files and where to get them. +"get_dvb_firmware" +script to download and extract firmware for those devices +that require it. "ttusb-dec.txt" contains detailed informations about the @@ -41,4 +41,11 @@ contains detailed installation instructions for the various bt8xx based "budget" DVB cards (Nebula, Pinnacle PCTV, Twinhan DST) +"README.dibusb" +contains detailed information about adapters +based on DiBcom reference design. + +"udev.txt" +how to get DVB and udev up and running. + Good luck and have fun! diff --git a/Documentation/dvb/ttusb-dec.txt b/Documentation/dvb/ttusb-dec.txt index 4a547fba7..5c1e984c2 100644 --- a/Documentation/dvb/ttusb-dec.txt +++ b/Documentation/dvb/ttusb-dec.txt @@ -6,6 +6,8 @@ Driver Status Supported: DEC2000-t + DEC2450-t + DEC3000-s Linux Kernels 2.4 and 2.6 Video Streaming Audio Streaming @@ -13,52 +15,30 @@ Supported: Channel Zapping Hotplug firmware loader under 2.6 kernels -In Progress: - DEC2540-t - DEC3000-s - To Do: Tuner status information DVB network interface Streaming video PC->DEC + Conax support for 2450-t Getting the Firmware -------------------- -The firmware can be found in the software update zip files on this page: -http://www.hauppauge.de/sw_dec.htm - -The firmwares are named as follows: -DEC2000-t: STB_PC_T.bin -DEC2540-t: STB_PC_X.bin -DEC3000-s: STB_PC_S.bin - -Note that firmwares since version 2.16 beta2 for the DEC2000-t give the device -the USB ID of the DEC3000-s. The driver copes with this. - -Instructions follow for retrieving version 2.16 of the firmware: - -wget http://hauppauge.lightpath.net/de/dec216.exe -unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_T.bin -unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_X.bin -unzip -j dec216.exe software/OEM/STB/App/Boot/STB_PC_S.bin +To download the firmware, use the following commands: +"get_dvb_firmware dec2000t" +"get_dvb_firmware dec2540t" +"get_dvb_firmware dec3000s" Compilation Notes for 2.4 kernels --------------------------------- For 2.4 kernels the firmware for the DECs is compiled into the driver itself. -The firmwares are expected to be in the build-2.4 directory at compilation -time. -mv STB_PC_T.bin build-2.4/dvb-ttusb-dec-2000t.fw -mv STB_PC_X.bin build-2.4/dvb-ttusb-dec-2540t.fw -mv STB_PC_S.bin build-2.4/dvb-ttusb-dec-3000s.fw +Copy the three files downloaded above into the build-2.4 directory. Hotplug Firmware Loading for 2.6 kernels ---------------------------------------- For 2.6 kernels the firmware is loaded at the point that the driver module is -loaded. See Documentation/dvb/firmware.txt for more information. +loaded. See linux/Documentation/dvb/firmware.txt for more information. -mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t.fw -mv STB_PC_X.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2540t.fw -mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s.fw +Copy the three files downloaded above into the /usr/lib/hotplug/firmware directory. diff --git a/Documentation/fb/matroxfb.txt b/Documentation/fb/matroxfb.txt index 621e3b3e4..ad7a67707 100644 --- a/Documentation/fb/matroxfb.txt +++ b/Documentation/fb/matroxfb.txt @@ -223,6 +223,13 @@ dfp:X - use settings X for digital flat panel interface. X is number from selects who is source of display clocks, whether G400, or panel. Default value is now read back from hardware - so you should specify this value only if you are also using `init' parameter. +outputs:XYZ - set mapping between CRTC and outputs. Each letter can have value + of 0 (for no CRTC), 1 (CRTC1) or 2 (CRTC2), and first letter corresponds + to primary analog output, second letter to the secondary analog output + and third letter to the DVI output. Default setting is 100 for + cards below G400 or G400 without DFP, 101 for G400 with DFP, and + 111 for G450 and G550. You can set mapping only on first card, + use matroxset for setting up other devices. vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table above for detailed explanation. Default is 640x480x8bpp if driver has 8bpp support. Otherwise first available of 640x350x4bpp, diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt index 36beb54f1..814e2f56a 100644 --- a/Documentation/fb/vesafb.txt +++ b/Documentation/fb/vesafb.txt @@ -146,11 +146,16 @@ pmipal Use the protected mode interface for palette changes. mtrr setup memory type range registers for the vesafb framebuffer. -vram:n remap 'n' MiB of video RAM. If 0 or not specified, remap memory +vremap:n + remap 'n' MiB of video RAM. If 0 or not specified, remap memory according to video mode. (2.5.66 patch/idea by Antonino Daplas reversed to give override possibility (allocate more fb memory than the kernel would) to 2.4 by tmb@iki.fi) +vtotal:n + if the video BIOS of your card incorrectly determines the total + amount of video RAM, use this option to override the BIOS (in MiB). + Have fun! Gerd diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 1c465edd2..570ef5db0 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -90,7 +90,7 @@ prototypes: void (*destroy_inode)(struct inode *); void (*read_inode) (struct inode *); void (*dirty_inode) (struct inode *); - void (*write_inode) (struct inode *, int); + int (*write_inode) (struct inode *, int); void (*put_inode) (struct inode *); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); @@ -276,21 +276,40 @@ foo_get_block(). It's an overkill, since block bitmaps can be protected by internal fs locking and real critical areas are much smaller than the areas filesystems protect now. ---------------------------- file_lock ------------------------------------ +----------------------- file_lock_operations ------------------------------ prototypes: - void (*fl_notify)(struct file_lock *); /* unblock callback */ void (*fl_insert)(struct file_lock *); /* lock insertion callback */ void (*fl_remove)(struct file_lock *); /* lock removal callback */ + void (*fl_copy_lock)(struct file_lock *, struct file_lock *); + void (*fl_release_private)(struct file_lock *); + + +locking rules: + BKL may block +fl_insert: yes no +fl_remove: yes no +fl_copy_lock: yes no +fl_release_private: yes yes + +----------------------- lock_manager_operations --------------------------- +prototypes: + int (*fl_compare_owner)(struct file_lock *, struct file_lock *); + void (*fl_notify)(struct file_lock *); /* unblock callback */ + void (*fl_copy_lock)(struct file_lock *, struct file_lock *); + void (*fl_release_private)(struct file_lock *); + void (*fl_break)(struct file_lock *); /* break_lease callback */ locking rules: - BKL may block -fl_notify: yes no -fl_insert: yes no -fl_remove: yes no - Currently only NLM provides instances of this class. None of the + BKL may block +fl_compare_owner: yes no +fl_notify: yes no +fl_copy_lock: yes no +fl_release_private: yes yes +fl_break: yes no + + Currently only NFSD and NLM provide instances of this class. None of the them block. If you have out-of-tree instances - please, show up. Locking in that area will change. - --------------------------- buffer_head ----------------------------------- prototypes: void (*b_end_io)(struct buffer_head *bh, int uptodate); @@ -298,8 +317,8 @@ prototypes: locking rules: called from interrupts. In other words, extreme care is needed here. bh is locked, but that's all warranties we have here. Currently only RAID1, -highmem and fs/buffer.c are providing these. Block devices call this method -upon the IO completion. +highmem, fs/buffer.c, and fs/ntfs/aops.c are providing these. Block devices +call this method upon the IO completion. --------------------------- block_device_operations ----------------------- prototypes: diff --git a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog index 12583144e..e5aba5246 100644 --- a/Documentation/filesystems/devfs/ChangeLog +++ b/Documentation/filesystems/devfs/ChangeLog @@ -1632,7 +1632,7 @@ Changes for patch v177 - Fixed bugs in handling symlinks: could leak or cause Oops - Cleaned up directory handling by separating fops - Thanks to Alexander Viro + Thanks to Alexander Viro =============================================================================== Changes for patch v178 diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README index 3ef858266..54366ecc2 100644 --- a/Documentation/filesystems/devfs/README +++ b/Documentation/filesystems/devfs/README @@ -1349,47 +1349,6 @@ This will cause devfsd to create (and destroy) symbolic links which point to the kernel-supplied names. -SCSI Host Probing Issues - -Devfs allows you to identify SCSI discs based in part on SCSI host -numbers. If you have only one SCSI host (card) in your computer, then -clearly it will be given host number 0. Life is not always that easy -is you have multiple SCSI hosts. Unfortunately, it can sometimes be -difficult to guess what the probing order of SCSI hosts is. You need -to know the probe order before you can use device names. To make this -easy, there is a kernel boot parameter called "scsihosts". This allows -you to specify the probe order for different types of SCSI hosts. The -syntax of this parameter is: - -scsihosts=:::...: - -where ,,..., are the names -of drivers used in the /proc filesystem. For example: - - scsihosts=aha1542:ppa:aha1542::ncr53c7xx - - -means that devices connected to - -- first aha1542 controller - will be /dev/scsi/host0/bus#/target#/lun# -- first parallel port ZIP - will be /dev/scsi/host1/bus#/target#/lun# -- second aha1542 controller - will be /dev/scsi/host2/bus#/target#/lun# -- first NCR53C7xx controller - will be /dev/scsi/host4/bus#/target#/lun# -- any extra controller - will be /dev/scsi/host5/bus#/target#/lun#, - /dev/scsi/host6/bus#/target#/lun#, etc -- if any of above controllers will not be found - the reserved names will - not be used by any other device. -- /dev/scsi/host3/bus#/target#/lun# names will never be used - - -You can use ',' instead of ':' as the separator character if you -wish. I have used the devfsd naming scheme -here. - -Note that this scheme does not address the SCSI host order if you have -multiple cards of the same type (such as NCR53c8xx). In this case you -need to use the driver-specific boot parameters to control this. - ----------------------------------------------------------------------------- @@ -1952,12 +1911,6 @@ explores the SCSI subsystem and how it interacts with devfs Douglas Gilbert has written another useful document at -http://www.torque.net/scsi/scsihosts.html which -discusses the scsihosts= boot option - - -Douglas Gilbert has written yet another useful document at - http://www.torque.net/scsi/SCSI-2.4-HOWTO/ which discusses the Linux SCSI subsystem in 2.4. diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt index 02968c532..b5cb9110c 100644 --- a/Documentation/filesystems/ext2.txt +++ b/Documentation/filesystems/ext2.txt @@ -11,30 +11,53 @@ for NetBSD, FreeBSD, the GNU HURD, Windows 95/98/NT, OS/2 and RISC OS. Options ======= -When mounting an ext2 filesystem, the following options are accepted. -Defaults are marked with (*). +Most defaults are determined by the filesystem superblock, and can be +set using tune2fs(8). Kernel-determined defaults are indicated by (*). bsddf (*) Makes `df' act like BSD. minixdf Makes `df' act like Minix. +check Check block and inode bitmaps at mount time + (requires CONFIG_EXT2_CHECK). check=none, nocheck (*) Don't do extra checking of bitmaps on mount (check=normal and check=strict options removed) debug Extra debugging information is sent to the kernel syslog. Useful for developers. -errors=continue (*) Keep going on a filesystem error. +errors=continue Keep going on a filesystem error. errors=remount-ro Remount the filesystem read-only on an error. errors=panic Panic and halt the machine if an error occurs. grpid, bsdgroups Give objects the same group ID as their parent. -nogrpid, sysvgroups (*) New objects have the group ID of their creator. +nogrpid, sysvgroups New objects have the group ID of their creator. + +nouid32 Use 16-bit UIDs and GIDs. + +oldalloc Enable the old block allocator. Orlov should + have better performance, we'd like to get some + feedback if it's the contrary for you. +orlov (*) Use the Orlov block allocator. + (See http://lwn.net/Articles/14633/ and + http://lwn.net/Articles/14446/.) resuid=n The user ID which may use the reserved blocks. -resgid=n The group ID which may use the reserved blocks. +resgid=n The group ID which may use the reserved blocks. sb=n Use alternate superblock at this location. +user_xattr Enable "user." POSIX Extended Attributes + (requires CONFIG_EXT2_FS_XATTR). + See also http://acl.bestbits.at +nouser_xattr Don't support "user." extended attributes. + +acl Enable POSIX Access Control Lists support + (requires CONFIG_EXT2_FS_POSIX_ACL). + See also http://acl.bestbits.at +noacl Don't support POSIX ACLs. + +nobh Do not attach buffer_heads to file pagecache. + grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. @@ -336,9 +359,8 @@ and are copied into the filesystem. If a transaction is incomplete at the time of the crash, then there is no guarantee of consistency for the blocks in that transaction so they are discarded (which means any filesystem changes they represent are also lost). - -The ext3 code is currently (Apr 2001) available for 2.2 kernels only, -and not yet available for 2.4 kernels. +Check Documentation/filesystems/ext3.txt if you want to read more about +ext3 and journaling. References ========== @@ -349,8 +371,6 @@ Design & Implementation http://e2fsprogs.sourceforge.net/ext2intro.html Journaling (ext3) ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/ Hashed Directories http://kernelnewbies.org/~phillips/htree/ Filesystem Resizing http://ext2resize.sourceforge.net/ -Extended Attributes & -Access Control Lists http://acl.bestbits.at/ Compression (*) http://www.netspace.net.au/~reiter/e2compr/ Implementations for: diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt index ff220afb1..9ab7f446f 100644 --- a/Documentation/filesystems/ext3.txt +++ b/Documentation/filesystems/ext3.txt @@ -22,6 +22,63 @@ journal=inum When a journal already exists, this option is the inode which will represent the ext3 file system's journal file. +noload Don't load the journal on mounting. + +data=journal All data are committed into the journal prior + to being written into the main file system. + +data=ordered (*) All data are forced directly out to the main file + system prior to its metadata being committed to + the journal. + +data=writeback Data ordering is not preserved, data may be + written into the main file system after its + metadata has been committed to the journal. + +commit=nrsec (*) Ext3 can be told to sync all its data and metadata + every 'nrsec' seconds. The default value is 5 seconds. + This means that if you lose your power, you will lose, + as much, the latest 5 seconds of work (your filesystem + will not be damaged though, thanks to journaling). This + default value (or any low value) will hurt performance, + but it's good for data-safety. Setting it to 0 will + have the same effect than leaving the default 5 sec. + Setting it to very large values will improve + performance. + +barrier=1 This enables/disables barriers. barrier=0 disables it, + barrier=1 enables it. + +orlov (*) This enables the new Orlov block allocator. It's enabled + by default. + +oldalloc This disables the Orlov block allocator and enables the + old block allocator. Orlov should have better performance, + we'd like to get some feedback if it's the contrary for + you. + +user_xattr (*) Enables POSIX Extended Attributes. It's enabled by + default, however you need to confifure its support + (CONFIG_EXT3_FS_XATTR). This is neccesary if you want + to use POSIX Acces Control Lists support. You can visit + http://acl.bestbits.at to know more about POSIX Extended + attributes. + +nouser_xattr Disables POSIX Extended Attributes. + +acl (*) Enables POSIX Access Control Lists support. This is + enabled by default, however you need to configure + its support (CONFIG_EXT3_FS_POSIX_ACL). If you want + to know more about ACLs visit http://acl.bestbits.at + +noacl This option disables POSIX Access Control List support. + +reservation + +noreservation + +resize= + bsddf (*) Make 'df' act like BSD. minixdf Make 'df' act like Minix. @@ -30,8 +87,6 @@ nocheck debug Extra debugging information is sent to syslog. -noload Don't load the journal on mounting. - errors=remount-ro(*) Remount the filesystem read-only on an error. errors=continue Keep going on a filesystem error. errors=panic Panic and halt the machine if an error occurs. @@ -48,17 +103,6 @@ resuid=n The user ID which may use the reserved blocks. sb=n Use alternate superblock at this location. -data=journal All data are committed into the journal prior - to being written into the main file system. - -data=ordered (*) All data are forced directly out to the main file - system prior to its metadata being committed to - the journal. - -data=writeback Data ordering is not preserved, data may be - written into the main file system after its - metadata has been committed to the journal. - quota Quota options are currently silently ignored. noquota (see fs/ext3/super.c, line 594) grpquota @@ -114,7 +158,7 @@ Compatibility ------------- Ext2 partitions can be easily convert to ext3, with `tune2fs -j `. - Ext3 is fully compatible with Ext2. Ext3 partitions can easily be +Ext3 is fully compatible with Ext2. Ext3 partitions can easily be mounted as Ext2. External Tools diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 200862dd6..f89b440fa 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -10,8 +10,10 @@ Table of contents - Features - Supported mount options - Known bugs and (mis-)features -- Using Software RAID with NTFS -- Limitiations when using the MD driver +- Using NTFS volume and stripe sets + - The Device-Mapper driver + - The Software RAID / MD driver + - Limitiations when using the MD driver - ChangeLog @@ -30,7 +32,7 @@ fault-tolerance, encryption or journalling) and very limited, but safe, write support. For fault tolerance and raid support (i.e. volume and stripe sets), you can -use the kernel's Software RAID / MD driver. See section "Using Software RAID +use the kernel's Software RAID / MD driver. See section "Using Software RAID with NTFS" for details. @@ -64,14 +66,18 @@ Features time find . -type f -exec md5sum "{}" \; run three times in sequence with each driver (after a reboot) on a 1.4GiB NTFS partition, showed the new driver to be 20% faster in total time elapsed - (from 9:43 minutes on average down to 7:53). The time spent in user space + (from 9:43 minutes on average down to 7:53). The time spent in user space was unchanged but the time spent in the kernel was decreased by a factor of 2.5 (from 85 CPU seconds down to 33). -- The driver does not support short file names in general. For backwards +- The driver does not support short file names in general. For backwards compatibility, we implement access to files using their short file names if - they exist. The driver will not create short file names however, and a rename - will discard any existing short file name. + they exist. The driver will not create short file names however, and a + rename will discard any existing short file name. - The new driver supports exporting of mounted NTFS volumes via NFS. +- The new driver supports async io (aio). +- The new driver supports fsync(2), fdatasync(2), and msync(2). +- The new driver supports readv(2) and writev(2). +- The new driver supports access time updates (including mtime and ctime). Supported mount options @@ -195,11 +201,161 @@ Please send bug reports/comments/feedback/abuse to the Linux-NTFS development list at sourceforge: linux-ntfs-dev@lists.sourceforge.net -Using Software RAID with NTFS -============================= +Using NTFS volume and stripe sets +================================= + +For support of volume and stripe sets, you can either use the kernel's +Device-Mapper driver or the kernel's Software RAID / MD driver. The former is +the recommended one to use for linear raid. But the latter is required for +raid level 5. For striping and mirroring, either driver should work fine. + + +The Device-Mapper driver +------------------------ + +You will need to create a table of the components of the volume/stripe set and +how they fit together and load this into the kernel using the dmsetup utility +(see man 8 dmsetup). + +Linear volume sets, i.e. linear raid, has been tested and works fine. Even +though untested, there is no reason why stripe sets, i.e. raid level 0, and +mirrors, i.e. raid level 1 should not work, too. Stripes with parity, i.e. +raid level 5, unfortunately cannot work yet because the current version of the +Device-Mapper driver does not support raid level 5. You may be able to use the +Software RAID / MD driver for raid level 5, see the next section for details. + +To create the table describing your volume you will need to know each of its +components and their sizes in sectors, i.e. multiples of 512-byte blocks. + +For NT4 fault tolerant volumes you can obtain the sizes using fdisk. So for +example if one of your partitions is /dev/hda2 you would do: + +$ fdisk -ul /dev/hda + +Disk /dev/hda: 81.9 GB, 81964302336 bytes +255 heads, 63 sectors/track, 9964 cylinders, total 160086528 sectors +Units = sectors of 1 * 512 = 512 bytes + + Device Boot Start End Blocks Id System + /dev/hda1 * 63 4209029 2104483+ 83 Linux + /dev/hda2 4209030 37768814 16779892+ 86 NTFS + /dev/hda3 37768815 46170809 4200997+ 83 Linux + +And you would know that /dev/hda2 has a size of 37768814 - 4209030 + 1 = +33559785 sectors. + +For Win2k and later dynamic disks, you can for example use the ldminfo utility +which is part of the Linux LDM tools (the latest version at the time of +writing is linux-ldm-0.0.8.tar.bz2). You can download it from: + http://linux-ntfs.sourceforge.net/downloads.html +Simply extract the downloaded archive (tar xvjf linux-ldm-0.0.8.tar.bz2), go +into it (cd linux-ldm-0.0.8) and change to the test directory (cd test). You +will find the precompiled (i386) ldminfo utility there. NOTE: You will not be +able to compile this yourself easily so use the binary version! + +Then you would use ldminfo in dump mode to obtain the necessary information: + +$ ./ldminfo --dump /dev/hda + +This would dump the LDM database found on /dev/hda which describes all of your +dynamic disks and all the volumes on them. At the bottom you will see the +VOLUME DEFINITIONS section which is all you really need. You may need to look +further above to determine which of the disks in the volume definitions is +which device in Linux. Hint: Run ldminfo on each of your dynamic disks and +look at the Disk Id close to the top of the output for each (the PRIVATE HEADER +section). You can then find these Disk Ids in the VBLK DATABASE section in the + components where you will get the LDM Name for the disk that is found in +the VOLUME DEFINITIONS section. + +Note you will also need to enable the LDM driver in the Linux kernel. If your +distribution did not enable it, you will need to recompile the kernel with it +enabled. This will create the LDM partitions on each device at boot time. You +would then use those devices (for /dev/hda they would be /dev/hda1, 2, 3, etc) +in the Device-Mapper table. + +You can also bypass using the LDM driver by using the main device (e.g. +/dev/hda) and then using the offsets of the LDM partitions into this device as +the "Start sector of device" when creating the table. Once again ldminfo would +give you the correct information to do this. + +Assuming you know all your devices and their sizes things are easy. + +For a linear raid the table would look like this (note all values are in +512-byte sectors): + +--- cut here --- +# Offset into Size of this Raid type Device Start sector +# volume device of device +0 1028161 linear /dev/hda1 0 +1028161 3903762 linear /dev/hdb2 0 +4931923 2103211 linear /dev/hdc1 0 +--- cut here --- -For support of volume and stripe sets, use the kernel's Software RAID / MD -driver and set up your /etc/raidtab appropriately (see man 5 raidtab). +For a striped volume, i.e. raid level 0, you will need to know the chunk size +you used when creating the volume. Windows uses 64kiB as the default, so it +will probably be this unless you changes the defaults when creating the array. + +For a raid level 0 the table would look like this (note all values are in +512-byte sectors): + +--- cut here --- +# Offset Size Raid Number Chunk 1st Start 2nd Start +# into of the type of size Device in Device in +# volume volume stripes device device +0 2056320 striped 2 128 /dev/hda1 0 /dev/hdb1 0 +--- cut here --- + +If there are more than two devices, just add each of them to the end of the +line. + +Finally, for a mirrored volume, i.e. raid level 1, the table would look like +this (note all values are in 512-byte sectors): + +--- cut here --- +# Ofs Size Raid Log Number Region Should Number Source Start Taget Start +# in of the type type of log size sync? of Device in Device in +# vol volume params mirrors Device Device +0 2056320 mirror core 2 16 nosync 2 /dev/hda1 0 /dev/hdb1 0 +--- cut here --- + +If you are mirroring to multiple devices you can specify further targets at the +end of the line. + +Note the "Should sync?" parameter "nosync" means that the two mirrors are +already in sync which will be the case on a clean shutdown of Windows. If the +mirrors are not clean, you can specify the "sync" option instead of "nosync" +and the Device-Mapper driver will then copy the entirey of the "Source Device" +to the "Target Device" or if you specified multipled target devices to all of +them. + +Once you have your table, save it in a file somewhere (e.g. /etc/ntfsvolume1), +and hand it over to dmsetup to work with, like so: + +$ dmsetup create myvolume1 /etc/ntfsvolume1 + +You can obviously replace "myvolume1" with whatever name you like. + +If it all worked, you will now have the device /dev/device-mapper/myvolume1 +which you can then just use as an argument to the mount command as usual to +mount the ntfs volume. For example: + +$ mount -t ntfs -o ro /dev/device-mapper/myvolume1 /mnt/myvol1 + +(You need to create the directory /mnt/myvol1 first and of course you can use +anything you like instead of /mnt/myvol1 as long as it is an existing +directory.) + +It is advisable to do the mount read-only to see if the volume has been setup +correctly to avoid the possibility of causing damage to the data on the ntfs +volume. + + +The Software RAID / MD driver +----------------------------- + +An alternative to using the Device-Mapper driver is to use the kernel's +Software RAID / MD driver. For which you need to set up your /etc/raidtab +appropriately (see man 5 raidtab). Linear volume sets, i.e. linear raid, as well as stripe sets, i.e. raid level 0, have been tested and work fine (though see section "Limitiations when using @@ -254,8 +410,8 @@ setup correctly to avoid the possibility of causing damage to the data on the ntfs volume. -Limitiations when using the MD driver -===================================== +Limitiations when using the Software RAID / MD driver +----------------------------------------------------- Using the md driver will not work properly if any of your NTFS partitions have an odd number of sectors. This is especially important for linear raid as all @@ -267,12 +423,43 @@ apparent when you try to use the volume again under Windows. So when using linear raid, make sure that all your partitions have an even number of sectors BEFORE attempting to use it. You have been warned! +Even better is to simply use the Device-Mapper for linear raid and then you do +not have this problem with odd numbers of sectors. + ChangeLog ========= Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. +2.1.22: + - Improve handling of ntfs volumes with errors. + - Fix various bugs and race conditions. +2.1.21: + - Fix several race conditions and various other bugs. + - Many internal cleanups, code reorganization, optimizations, and mft + and index record writing code rewritten to fit in with the changes. + - Update Documentation/filesystems/ntfs.txt with instructions on how to + use the Device-Mapper driver with NTFS ftdisk/LDM raid. +2.1.20: + - Fix two stupid bugs introduced in 2.1.18 release. +2.1.19: + - Minor bugfix in handling of the default upcase table. + - Many internal cleanups and improvements. Many thanks to Linus + Torvalds and Al Viro for the help and advice with the sparse + annotations and cleanups. +2.1.18: + - Fix scheduling latencies at mount time. (Ingo Molnar) + - Fix endianness bug in a little traversed portion of the attribute + lookup code. +2.1.17: + - Fix bugs in mount time error code paths. +2.1.16: + - Implement access time updates (including mtime and ctime). + - Implement fsync(2), fdatasync(2), and msync(2) system calls. + - Enable the readv(2) and writev(2) system calls. + - Enable access via the asynchronous io (aio) API by adding support for + the aio_read(3) and aio_write(3) functions. 2.1.15: - Invalidate quotas when (re)mounting read-write. NOTE: This now only leave user space journalling on the side. (See diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 9d626596d..2c3fc3a27 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -55,7 +55,7 @@ This work is based on the 2.2.* kernel version and the upcoming 2.4.*. I'm afraid it's still far from complete, but we hope it will be useful. As far as we know, it is the first 'all-in-one' document about the /proc file system. It is focused on the Intel x86 hardware, so if you are looking for PPC, ARM, -SPARC, APX, etc., features, you probably won't find what you are looking for. +SPARC, AXP, etc., features, you probably won't find what you are looking for. It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But additions and patches are welcome and will be added to this document if you mail them to Bodo. @@ -169,16 +169,18 @@ information. The statm file contains more detailed information about the process memory usage. Its seven fields are explained in Table 1-2. -Table 1-2: Contents of the statm files +Table 1-2: Contents of the statm files (as of 2.6.8-rc3) .............................................................................. - File Content - size total program size - resident size of memory portions - shared number of pages that are shared - trs number of pages that are 'code' - drs number of pages of data/stack - lrs number of pages of library - dt number of dirty pages + Field Content + size total program size (pages) (same as VmSize in status) + resident size of memory portions (pages) (same as VmRSS in status) + shared number of pages that are shared (i.e. backed by a file) + trs number of pages that are 'code' (not including libs; broken, + includes data segment) + lrs number of pages of library (always 0 on 2.6) + drs number of pages of data/stack (including libs; broken, + includes library text) + dt number of dirty pages (always 0 on 2.6) .............................................................................. 1.2 Kernel data @@ -348,22 +350,6 @@ available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE available in ZONE_NORMAL, etc... - -1.3 IDE devices in /proc/ide ----------------------------- - -The subdirectory /proc/ide contains information about all IDE devices of which -the kernel is aware. There is one subdirectory for each IDE controller, the -file drivers and a link for each IDE device, pointing to the device directory -in the controller specific subtree. - -The file drivers contains general information about the drivers used for the -IDE devices: - - > cat /proc/ide/drivers - ide-cdrom version 4.53 - ide-disk version 1.08 - .............................................................................. meminfo: @@ -392,9 +378,9 @@ Dirty: 968 kB Writeback: 0 kB Mapped: 280372 kB Slab: 684068 kB -Committed_AS: 1576424 kB +CommitLimit: 7669796 kB +Committed_AS: 100056 kB PageTables: 24448 kB -ReverseMaps: 1080904 VmallocTotal: 112216 kB VmallocUsed: 428 kB VmallocChunk: 111088 kB @@ -432,26 +418,54 @@ VmallocChunk: 111088 kB Writeback: Memory which is actively being written back to the disk Mapped: files which have been mmaped, such as libraries Slab: in-kernel data structures cache -Committed_AS: An estimate of how much RAM you would need to make a - 99.99% guarantee that there never is OOM (out of memory) - for this workload. Normally the kernel will overcommit - memory. That means, say you do a 1GB malloc, nothing - happens, really. Only when you start USING that malloc - memory you will get real memory on demand, and just as - much as you use. So you sort of take a mortgage and hope - the bank doesn't go bust. Other cases might include when - you mmap a file that's shared only when you write to it - and you get a private copy of that data. While it normally - is shared between processes. The Committed_AS is a - guesstimate of how much RAM/swap you would need - worst-case. + CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'), + this is the total amount of memory currently available to + be allocated on the system. This limit is only adhered to + if strict overcommit accounting is enabled (mode 2 in + 'vm.overcommit_memory'). + The CommitLimit is calculated with the following formula: + CommitLimit = ('vm.overcommit_ratio' * Physical RAM) + Swap + For example, on a system with 1G of physical RAM and 7G + of swap with a `vm.overcommit_ratio` of 30 it would + yield a CommitLimit of 7.3G. + For more details, see the memory overcommit documentation + in vm/overcommit-accounting. +Committed_AS: The amount of memory presently allocated on the system. + The committed memory is a sum of all of the memory which + has been allocated by processes, even if it has not been + "used" by them as of yet. A process which malloc()'s 1G + of memory, but only touches 300M of it will only show up + as using 300M of memory even if it has the address space + allocated for the entire 1G. This 1G is memory which has + been "committed" to by the VM and can be used at any time + by the allocating application. With strict overcommit + enabled on the system (mode 2 in 'vm.overcommit_memory'), + allocations which would exceed the CommitLimit (detailed + above) will not be permitted. This is useful if one needs + to guarantee that processes will not fail due to lack of + memory once that memory has been successfully allocated. PageTables: amount of memory dedicated to the lowest level of page tables. - ReverseMaps: number of reverse mappings performed VmallocTotal: total size of vmalloc memory area VmallocUsed: amount of vmalloc area which is used VmallocChunk: largest contigious block of vmalloc area which is free + +1.3 IDE devices in /proc/ide +---------------------------- + +The subdirectory /proc/ide contains information about all IDE devices of which +the kernel is aware. There is one subdirectory for each IDE controller, the +file drivers and a link for each IDE device, pointing to the device directory +in the controller specific subtree. + +The file drivers contains general information about the drivers used for the +IDE devices: + + > cat /proc/ide/drivers + ide-cdrom version 4.53 + ide-disk version 1.08 + More detailed information can be found in the controller specific subdirectories. These are named ide0, ide1 and so on. Each of these directories contains the files shown in table 1-4. @@ -1109,6 +1123,23 @@ modprobe The location where the modprobe binary is located. The kernel uses this program to load modules on demand. +unknown_nmi_panic +----------------- + +The value in this file affects behavior of handling NMI. When the value is +non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel +debugging information is displayed on console. + +NMI switch that most IA32 servers have fires unknown NMI up, for example. +If a system hangs up, try pressing the NMI switch. + +[NOTE] + This function and oprofile share a NMI callback. Therefore this function + cannot be enabled when oprofile is activated. + And NMI watchdog will be disabled when the value in this file is set to + non-zero. + + 2.4 /proc/sys/vm - The virtual memory subsystem ----------------------------------------------- @@ -1157,6 +1188,12 @@ for writeout by the pdflush daemons. It is expressed in 100'ths of a second. Data which has been dirty in-memory for longer than this interval will be written out next time a pdflush daemon wakes up. +legacy_va_layout +---------------- + +If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel +will use the legacy (2.4) layout for all processes. + lower_zone_protection --------------------- @@ -1244,6 +1281,14 @@ block_dump block_dump enables block I/O debugging when set to a nonzero value. More information on block I/O debugging is in Documentation/laptop-mode.txt. +swap_token_timeout +------------------ + +This file contains valid hold time of swap out protection token. The Linux +VM has token based thrashing control mechanism and uses the token to prevent +unnecessary page faults in thrashing situation. The unit of the value is +second. The value would be useful to tune thrashing behavior. + 2.5 /proc/sys/dev - Device specific parameters ---------------------------------------------- diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt index 177edbea9..417e3095f 100644 --- a/Documentation/filesystems/tmpfs.txt +++ b/Documentation/filesystems/tmpfs.txt @@ -62,13 +62,21 @@ size: The limit of allocated bytes for this tmpfs instance. The since the OOM handler will not be able to free that memory. nr_blocks: The same as size, but in blocks of PAGE_CACHE_SIZE. nr_inodes: The maximum number of inodes for this instance. The default - is half of the number of your physical RAM pages. + is half of the number of your physical RAM pages, or (on a + a machine with highmem) the number of lowmem RAM pages, + whichever is the lower. These parameters accept a suffix k, m or g for kilo, mega and giga and can be changed on remount. The size parameter also accepts a suffix % to limit this tmpfs instance to that percentage of your physical RAM: the default, when neither size nor nr_blocks is specified, is size=50% +If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks +nor inodes will be limited in that instance. It is generally unwise to +mount with such options, since it allows any user with write access to +use up all the memory on the machine; but enhances the scalability of +that instance in a system with many cpus making intensive use of it. + To specify the initial root directory you can use the following mount options: @@ -89,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root. Author: Christoph Rohland , 1.12.01 Updated: - Hugh Dickins , 01 April 2003 + Hugh Dickins , 01 September 2004 diff --git a/Documentation/filesystems/ufs.txt b/Documentation/filesystems/ufs.txt index bdedb9fff..2b5a56a6a 100644 --- a/Documentation/filesystems/ufs.txt +++ b/Documentation/filesystems/ufs.txt @@ -15,13 +15,15 @@ ufstype=type_of_ufs ufs manually by mount option ufstype. Possible values are: old old format of ufs - default value, supported os read-only + default value, supported as read-only 44bsd used in FreeBSD, NetBSD, OpenBSD - supported os read-write + supported as read-write + + ufs2 used in FreeBSD 5.x + supported as read-only - ufs2 used in FreeBSD 5.x - supported os read-only + 5xbsd synonym for ufs2 sun used in SunOS (Solaris) supported as read-write @@ -29,6 +31,9 @@ ufstype=type_of_ufs sunx86 used in SunOS for Intel (Solarisx86) supported as read-write + hp used in HP-UX + supported as read-only + nextstep used in NextStep supported as read-only @@ -46,7 +51,7 @@ POSSIBLE PROBLEMS ================= There is still bug in reallocation of fragment, in file fs/ufs/balloc.c, -line 364. But it seem working on current buffer cache configuration. +line 364. But it seems working on current buffer cache configuration. BUG REPORTS diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 9557ea184..3f318dd44 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -44,7 +44,7 @@ Opening a File The VFS implements the open(2), stat(2), chmod(2) and similar system calls. The pathname argument is used by the VFS to search through the directory entry cache (dentry cache or "dcache"). This provides a very -fast lookup mechanism to translate a pathname (filename) into a +fast look-up mechanism to translate a pathname (filename) into a specific dentry. An individual dentry usually has a pointer to an inode. Inodes are the @@ -64,7 +64,7 @@ resolve your pathname into a dentry, the VFS may have to resort to creating dentries along the way, and then loading the inode. This is done by looking up the inode. -To lookup an inode (usually read from disc) requires that the VFS +To look up an inode (usually read from disc) requires that the VFS calls the lookup() method of the parent directory inode. This method is installed by the specific filesystem implementation that the inode lives in. There will be more on this later. @@ -176,7 +176,7 @@ filesystem. As of kernel 2.1.99, the following members are defined: struct super_operations { void (*read_inode) (struct inode *); - void (*write_inode) (struct inode *, int); + int (*write_inode) (struct inode *, int); void (*put_inode) (struct inode *); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); @@ -286,7 +286,7 @@ otherwise noted. dentry). Here you will probably call d_instantiate() with the dentry and the newly created inode - lookup: called when the VFS needs to lookup an inode in a parent + lookup: called when the VFS needs to look up an inode in a parent directory. The name to look for is found in the dentry. This method must call d_add() to insert the found inode into the dentry. The "i_count" field in the inode structure should be @@ -405,7 +405,10 @@ from device node to device driver (this is an unofficial kernel patch). -struct dentry_operations
+Directory Entry Cache (dcache)
+------------------------------ + +struct dentry_operations ======================== This describes how a filesystem can overload the standard dentry @@ -425,7 +428,7 @@ struct dentry_operations { }; d_revalidate: called when the VFS needs to revalidate a dentry. This - is called whenever a name lookup finds a dentry in the + is called whenever a name look-up finds a dentry in the dcache. Most filesystems leave this as NULL, because all their dentries in the dcache are valid @@ -448,6 +451,9 @@ Each dentry has a pointer to its parent dentry, as well as a hash list of child dentries. Child dentries are basically like files in a directory. +Directory Entry Cache APIs +-------------------------- + There are a number of functions defined which permit a filesystem to manipulate dentries: @@ -482,3 +488,184 @@ manipulate dentries: pointer is NULL, the dentry is called a "negative dentry". This function is commonly called when an inode is created for an existing negative dentry + + d_lookup: look up a dentry given its parent and path name component + It looks up the child of that given name from the dcache + hash table. If it is found, the reference count is incremented + and the dentry is returned. The caller must use d_put() + to free the dentry when it finishes using it. + + +RCU-based dcache locking model +------------------------------ + +On many workloads, the most common operation on dcache is +to look up a dentry, given a parent dentry and the name +of the child. Typically, for every open(), stat() etc., +the dentry corresponding to the pathname will be looked +up by walking the tree starting with the first component +of the pathname and using that dentry along with the next +component to look up the next level and so on. Since it +is a frequent operation for workloads like multiuser +environments and webservers, it is important to optimize +this path. + +Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus +in every component during path look-up. Since 2.5.10 onwards, +fastwalk algorithm changed this by holding the dcache_lock +at the beginning and walking as many cached path component +dentries as possible. This signficantly decreases the number +of acquisition of dcache_lock. However it also increases the +lock hold time signficantly and affects performance in large +SMP machines. Since 2.5.62 kernel, dcache has been using +a new locking model that uses RCU to make dcache look-up +lock-free. + +The current dcache locking model is not very different from the existing +dcache locking model. Prior to 2.5.62 kernel, dcache_lock +protected the hash chain, d_child, d_alias, d_lru lists as well +as d_inode and several other things like mount look-up. RCU-based +changes affect only the way the hash chain is protected. For everything +else the dcache_lock must be taken for both traversing as well as +updating. The hash chain updations too take the dcache_lock. +The significant change is the way d_lookup traverses the hash chain, +it doesn't acquire the dcache_lock for this and rely on RCU to +ensure that the dentry has not been *freed*. + + +Dcache locking details +---------------------- +For many multi-user workloads, open() and stat() on files are +very frequently occurring operations. Both involve walking +of path names to find the dentry corresponding to the +concerned file. In 2.4 kernel, dcache_lock was held +during look-up of each path component. Contention and +cacheline bouncing of this global lock caused significant +scalability problems. With the introduction of RCU +in linux kernel, this was worked around by making +the look-up of path components during path walking lock-free. + + +Safe lock-free look-up of dcache hash table +=========================================== + +Dcache is a complex data structure with the hash table entries +also linked together in other lists. In 2.4 kernel, dcache_lock +protected all the lists. We applied RCU only on hash chain +walking. The rest of the lists are still protected by dcache_lock. +Some of the important changes are : + +1. The deletion from hash chain is done using hlist_del_rcu() macro which + doesn't initialize next pointer of the deleted dentry and this + allows us to walk safely lock-free while a deletion is happening. + +2. Insertion of a dentry into the hash table is done using + hlist_add_head_rcu() which take care of ordering the writes - + the writes to the dentry must be visible before the dentry + is inserted. This works in conjuction with hlist_for_each_rcu() + while walking the hash chain. The only requirement is that + all initialization to the dentry must be done before hlist_add_head_rcu() + since we don't have dcache_lock protection while traversing + the hash chain. This isn't different from the existing code. + +3. The dentry looked up without holding dcache_lock by cannot be + returned for walking if it is unhashed. It then may have a NULL + d_inode or other bogosity since RCU doesn't protect the other + fields in the dentry. We therefore use a flag DCACHE_UNHASHED to + indicate unhashed dentries and use this in conjunction with a + per-dentry lock (d_lock). Once looked up without the dcache_lock, + we acquire the per-dentry lock (d_lock) and check if the + dentry is unhashed. If so, the look-up is failed. If not, the + reference count of the dentry is increased and the dentry is returned. + +4. Once a dentry is looked up, it must be ensured during the path + walk for that component it doesn't go away. In pre-2.5.10 code, + this was done holding a reference to the dentry. dcache_rcu does + the same. In some sense, dcache_rcu path walking looks like + the pre-2.5.10 version. + +5. All dentry hash chain updations must take the dcache_lock as well as + the per-dentry lock in that order. dput() does this to ensure + that a dentry that has just been looked up in another CPU + doesn't get deleted before dget() can be done on it. + +6. There are several ways to do reference counting of RCU protected + objects. One such example is in ipv4 route cache where + deferred freeing (using call_rcu()) is done as soon as + the reference count goes to zero. This cannot be done in + the case of dentries because tearing down of dentries + require blocking (dentry_iput()) which isn't supported from + RCU callbacks. Instead, tearing down of dentries happen + synchronously in dput(), but actual freeing happens later + when RCU grace period is over. This allows safe lock-free + walking of the hash chains, but a matched dentry may have + been partially torn down. The checking of DCACHE_UNHASHED + flag with d_lock held detects such dentries and prevents + them from being returned from look-up. + + +Maintaining POSIX rename semantics +================================== + +Since look-up of dentries is lock-free, it can race against +a concurrent rename operation. For example, during rename +of file A to B, look-up of either A or B must succeed. +So, if look-up of B happens after A has been removed from the +hash chain but not added to the new hash chain, it may fail. +Also, a comparison while the name is being written concurrently +by a rename may result in false positive matches violating +rename semantics. Issues related to race with rename are +handled as described below : + +1. Look-up can be done in two ways - d_lookup() which is safe + from simultaneous renames and __d_lookup() which is not. + If __d_lookup() fails, it must be followed up by a d_lookup() + to correctly determine whether a dentry is in the hash table + or not. d_lookup() protects look-ups using a sequence + lock (rename_lock). + +2. The name associated with a dentry (d_name) may be changed if + a rename is allowed to happen simultaneously. To avoid memcmp() + in __d_lookup() go out of bounds due to a rename and false + positive comparison, the name comparison is done while holding the + per-dentry lock. This prevents concurrent renames during this + operation. + +3. Hash table walking during look-up may move to a different bucket as + the current dentry is moved to a different bucket due to rename. + But we use hlists in dcache hash table and they are null-terminated. + So, even if a dentry moves to a different bucket, hash chain + walk will terminate. [with a list_head list, it may not since + termination is when the list_head in the original bucket is reached]. + Since we redo the d_parent check and compare name while holding + d_lock, lock-free look-up will not race against d_move(). + +4. There can be a theoritical race when a dentry keeps coming back + to original bucket due to double moves. Due to this look-up may + consider that it has never moved and can end up in a infinite loop. + But this is not any worse that theoritical livelocks we already + have in the kernel. + + +Important guidelines for filesystem developers related to dcache_rcu +==================================================================== + +1. Existing dcache interfaces (pre-2.5.62) exported to filesystem + don't change. Only dcache internal implementation changes. However + filesystems *must not* delete from the dentry hash chains directly + using the list macros like allowed earlier. They must use dcache + APIs like d_drop() or __d_drop() depending on the situation. + +2. d_flags is now protected by a per-dentry lock (d_lock). All + access to d_flags must be protected by it. + +3. For a hashed dentry, checking of d_count needs to be protected + by d_lock. + + +Papers and other documentation on dcache locking +================================================ + +1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124). + +2. http://lse.sourceforge.net/locking/dcache/dcache.html diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt index 934254098..c7d5d0c70 100644 --- a/Documentation/filesystems/xfs.txt +++ b/Documentation/filesystems/xfs.txt @@ -120,12 +120,18 @@ The following sysctls are available for the XFS filesystem: fs.xfs.stats_clear (Min: 0 Default: 0 Max: 1) Setting this to "1" clears accumulated XFS statistics - in /proc/fs/xfs/stat. It then immediately reset to "0". - - fs.xfs.sync_interval (Min: HZ Default: 30*HZ Max: 60*HZ) - The interval at which the xfssyncd thread for xfs filesystems - flushes metadata out to disk. This thread will flush log - activity out, and do some processing on unlinked inodes + in /proc/fs/xfs/stat. It then immediately resets to "0". + + fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000) + The interval at which the xfssyncd thread flushes metadata + out to disk. This thread will flush log activity out, and + do some processing on unlinked inodes. + + fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) + The interval at which xfsbufd scans the dirty metadata buffers list. + + fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) + The age at which xfsbufd flushes dirty metadata buffers to disk. fs.xfs.error_level (Min: 0 Default: 3 Max: 11) A volume knob for error reporting when internal errors occur. @@ -180,14 +186,3 @@ The following sysctls are available for the XFS filesystem: Setting this to "1" will cause the "noatime" flag set by the chattr(1) command on a directory to be inherited by files in that directory. - - vm.pagebuf.stats_clear (Min: 0 Default: 0 Max: 1) - Setting this to "1" clears accumulated pagebuf statistics - in /proc/fs/pagebuf/stat. It then immediately reset to "0". - - vm.pagebuf.flush_age (Min: 1*HZ Default: 15*HZ Max: 300*HZ) - The age at which dirty metadata buffers are flushed to disk - - vm.pagebuf.flush_int (Min: HZ/2 Default: HZ Max: 30*HZ) - The interval at which the list of dirty metadata buffers is - scanned. diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c index 037c0bed9..09eab2f1b 100644 --- a/Documentation/firmware_class/firmware_sample_firmware_class.c +++ b/Documentation/firmware_class/firmware_sample_firmware_class.c @@ -14,9 +14,8 @@ #include #include #include -#include +#include -#include "linux/firmware.h" MODULE_AUTHOR("Manuel Estrada Sainz "); MODULE_DESCRIPTION("Hackish sample for using firmware class directly"); diff --git a/Documentation/firmware_class/hotplug-script b/Documentation/firmware_class/hotplug-script index d6608e024..1990130f2 100644 --- a/Documentation/firmware_class/hotplug-script +++ b/Documentation/firmware_class/hotplug-script @@ -7,10 +7,10 @@ HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ echo 1 > /sys/$DEVPATH/loading -cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data +cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data echo 0 > /sys/$DEVPATH/loading # To cancel the load in case of error: # -# echo -1 > /sysfs/$DEVPATH/loading +# echo -1 > /sys/$DEVPATH/loading # diff --git a/Documentation/floppy.txt b/Documentation/floppy.txt index 99d3ad3b3..6fb10fcd8 100644 --- a/Documentation/floppy.txt +++ b/Documentation/floppy.txt @@ -13,15 +13,20 @@ LILO configuration options (Thinkpad users, read this) The floppy driver is configured using the 'floppy=' option in lilo. This option can be typed at the boot prompt, or entered in the lilo configuration file. - Example: If your kernel is called linux-2.2.13, type the following line + + Example: If your kernel is called linux-2.6.9, type the following line at the lilo boot prompt (if you have a thinkpad): - linux-2.2.13 floppy=thinkpad + + linux-2.6.9 floppy=thinkpad + You may also enter the following line in /etc/lilo.conf, in the description -of linux-2.2.13: +of linux-2.6.9: + append = "floppy=thinkpad" Several floppy related options may be given, example: - linux-2.2.13 floppy=daring floppy=two_fdc + + linux-2.6.9 floppy=daring floppy=two_fdc append = "floppy=daring floppy=two_fdc" If you give options both in the lilo config file and on the boot @@ -29,17 +34,25 @@ prompt, the option strings of both places are concatenated, the boot prompt options coming last. That's why there are also options to restore the default behavior. + +Module configuration options +============================ + If you use the floppy driver as a module, use the following syntax: - insmod floppy +modprobe floppy Example: - insmod floppy daring two_fdc + modprobe floppy omnibook messages + + If you need certain options enabled every time you load the floppy driver, +you can put: + + options floppy omnibook messages + +in /etc/modprobe.conf. - Some versions of insmod are buggy in one way or another. If you have -any problems (options not being passed correctly, segfaults during -insmod), first check whether there is a more recent version. - The floppy related options include: + The floppy driver related options are: floppy=asus_pci Sets the bit mask to allow only units 0 and 1. (default) @@ -99,7 +112,7 @@ insmod), first check whether there is a more recent version. master arbitration error" messages from your Ethernet card (or from other devices) while accessing the floppy. - floppy=fifo + floppy=usefifo Enables the FIFO. (default) floppy=,fifo_depth @@ -110,6 +123,7 @@ insmod), first check whether there is a more recent version. lower, the interrupt latency should be lower too (faster processor). The benefit of a lower threshold is less interrupts. + To tune the fifo threshold, switch on over/underrun messages using 'floppycontrol --messages'. Then access a floppy disk. If you get a huge amount of "Over/Underrun - retrying" @@ -120,6 +134,7 @@ insmod), first check whether there is a more recent version. fifo values without rebooting the machine for each test. Note that you need to do 'floppycontrol --messages' every time you re-insert the module. + Usually, tuning the fifo threshold should not be needed, as the default (0xa) is reasonable. @@ -128,6 +143,7 @@ insmod), first check whether there is a more recent version. you have more than two floppy drives (only two can be described in the physical CMOS), or if your BIOS uses non-standard CMOS types. The CMOS types are: + 0 - Use the value of the physical CMOS 1 - 5 1/4 DD 2 - 5 1/4 HD @@ -136,6 +152,7 @@ insmod), first check whether there is a more recent version. 5 - 3 1/2 ED 6 - 3 1/2 ED 16 - unknown or not installed + (Note: there are two valid types for ED drives. This is because 5 was initially chosen to represent floppy *tapes*, and 6 for ED drives. AMI ignored this, and used 5 for ED drives. That's why the floppy @@ -188,7 +205,6 @@ insmod), first check whether there is a more recent version. in some more extreme cases." - Supporting utilities and additional documentation: ================================================== @@ -219,3 +235,11 @@ sure to mention also the type of the filesystem in the subject line. Be sure to read the FAQ before mailing/posting any bug reports! Alain + +Changelog +========= + +10-30-2004 : Cleanup, updating, add reference to module configuration. + James Nelson + +6-3-2000 : Original Document diff --git a/Documentation/ftape.txt b/Documentation/ftape.txt index 9cc814a55..7d8bb3384 100644 --- a/Documentation/ftape.txt +++ b/Documentation/ftape.txt @@ -2,26 +2,21 @@ Intro ===== This file describes some issues involved when using the "ftape" -floppy tape device driver that comes with the Linux kernel. This -document deals with ftape-3.04 and later. Please read the section -"Changes" for the most striking differences between version 3.04 and -2.08; the latter was the version of ftape delivered with the kernel -until kernel version 2.0.30 and 2.1.57. ftape-3.x developed as the -re-unification of ftape-2.x and zftape. zftape was developed in -parallel with the stock ftape-2.x driver sharing the same hardware -support but providing an enhanced file system interface. zftape also -provided user transparent block-wise on-the-fly compression (regard it -as a feature or bug of zftape). +floppy tape device driver that comes with the Linux kernel. ftape has a home page at -http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape +http://ftape.dot-heine.de/ which contains further information about ftape. Please cross check this WWW address against the address given (if any) in the MAINTAINERS file located in the top level directory of the Linux kernel source tree. +NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work. +If you are interested in taking over maintenance, contact Claus-Justus Heine +, the former maintainer. + Contents ======== @@ -31,9 +26,8 @@ A. Changes 1. Goal 2. I/O Block Size 3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape) - 4. MTBSF - backspace over file mark and position at its EOT side - 5. Formatting - 6. Interchanging cartridges with other operating systems + 4. Formatting + 5. Interchanging cartridges with other operating systems B. Debugging Output 1. Introduction @@ -58,7 +52,7 @@ changed. Up to date documentation as well as recent development versions of ftape and useful links to related topics can be found at the ftape home page at -http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape +http://ftape.dot-heine.de/ ******************************************************************************* @@ -70,7 +64,7 @@ A. Changes The goal of all that incompatibilities was to give ftape an interface that resembles the interface provided by SCSI tape drives as close as possible. Thus any Unix backup program that is known to work - with SCSI tape drives should also work with ftape-3.04 and above. + with SCSI tape drives should also work. The concept of a fixed block size for read/write transfers is rather unrelated to this SCSI tape compatibility at the file system @@ -81,14 +75,8 @@ A. Changes 2. I/O Block Size ~~~~~~~~~~~~~~ - The probably most striking difference between ftape-2.x and - ftape-3.x with the zftape file system interface is the concept of a - fixed block size: data must be written to or read from the tape in - multiples of a fixed block size. The block size defaults to 10k - which is the default block size of GNU tar. While this is quite - usual for SCSI tapes (block size of 32k?) and the QIC-150 driver - `./drivers/char/tpqic02.c' ftape-2.x allowed data to be written in - arbitrary portions to the tape. + The block size defaults to 10k which is the default block size of + GNU tar. The block size can be tuned either during kernel configuration or at runtime with the MTIOCTOP ioctl using the MTSETBLK operation @@ -109,53 +97,41 @@ A. Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ zftape (the file system interface of ftape-3.x) denies write access to the tape cartridge when it isn't positioned either at BOT or - EOD. This inconvenience has been introduced as it was reported that - the former behavior of ftape-2.x which allowed write access at - arbitrary locations already has caused data loss with some backup - programs. - -4. MTBSF - backspace over file mark and position at its EOT side - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ftape-2.x didn't handle the MTBSF tape operation correctly. A MTBSF - call (i.e. "mt -f /dev/nqft0 bsf #COUNT") should space over #COUNT - file marks and then position at the EOT tape side of the file - mark. This has to be taken literally, i.e. "mt -f /dev/nqft0 bsf 1" - should simply position at the start of the current volume. - -5. Formatting + EOD. + +4. Formatting ~~~~~~~~~~ - ftape-3.x DOES support formatting of floppy tape cartridges. You - need the `ftformat' program that is shipped with the modules version - of ftape-3.x. Please get the latest version of ftape from + ftape DOES support formatting of floppy tape cartridges. You need the + `ftformat' program that is shipped with the modules version of ftape. + Please get the latest version of ftape from ftp://sunsite.unc.edu/pub/Linux/kernel/tapes or from the ftape home page at - http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape + http://ftape.dot-heine.de/ `ftformat' is contained in the `./contrib/' subdirectory of that separate ftape package. -6. Interchanging cartridges with other operating systems +5. Interchanging cartridges with other operating systems ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The internal emulation of Unix tape device file marks has changed - completely. ftape-3.x now uses the volume table segment as specified + completely. ftape now uses the volume table segment as specified by the QIC-40/80/3010/3020/113 standards to emulate file marks. As a consequence there is limited support to interchange cartridges with other operating systems. To be more precise: ftape will detect volumes written by other OS's programs and other OS's programs will detect volumes written by - ftape-3.x. + ftape. However, it isn't possible to extract the data dumped to the tape - by some MSDOG program with ftape-3.x. This exceeds the scope of a + by some MSDOS program with ftape. This exceeds the scope of a kernel device driver. If you need such functionality, then go ahead - and write a user space utility that is able to do - that. ftape-3.x/zftape already provides all kernel level support - necessary to do that. + and write a user space utility that is able to do that. ftape already + provides all kernel level support necessary to do that. ******************************************************************************* @@ -200,7 +176,7 @@ B. Debugging Output ii) trim the debugging output at module load time with - insmod ftape.o ft_tracing=#DBGLVL + modprobe ftape ft_tracing=#DBGLVL Of course, this applies only if you have configured ftape to be compiled as a module. @@ -240,7 +216,7 @@ C. Boot and load time configuration 2. Module load time parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Module parameters can be specified either directly when invoking - the program 'insmod' at the shell prompt: + the program 'modprobe' at the shell prompt: modprobe ftape ft_tracing=4 @@ -277,6 +253,12 @@ C. Boot and load time configuration line documentation provided during that kernel configuration process. + ft_probe_fc10 is set to a non-zero value if you wish for ftape to + probe for a Colorado FC-10 or FC-20 controller. + + ft_mach2 is set to a non-zero value if you wish for ftape to probe + for a Mountain MACH-2 controller. + module | kernel command line -----------------------|---------------------- ft_fdc_base=BASE | ftape=BASE,ioport @@ -316,10 +298,10 @@ D. Support and contacts page to query for the most recent documentation, related work and development versions of ftape. + Changelog: + ========== + +~1996: Original Document - LocalWords: ftape Linux zftape http www rwth aachen LBFM claus EOD config - LocalWords: datarate LocalWords BOT MTBSF EOT HOWTO QIC tpqic menuconfig - LocalWords: MTIOCTOP MTSETBLK mt dev qft setblk BLKSZ bsf zftape's xconfig - LocalWords: nqft ftformat ftp sunsite unc edu contrib ft MSDOG fdc - LocalWords: dma setdensity DBGLVL insmod lilo LI nux ader conf txt - LocalWords: modprobe IRQ BOOL ioport irq fc mach THR +10-24-2004: General cleanup and updating, noting additional module options. + James Nelson diff --git a/Documentation/hw_random.txt b/Documentation/hw_random.txt index 20be482b6..bb58c36b5 100644 --- a/Documentation/hw_random.txt +++ b/Documentation/hw_random.txt @@ -67,72 +67,3 @@ Driver details: Special thanks to Matt Sottek. I did the "guts", he did the "brains" and all the testing. - -Change history: - - Version 1.0.0: - * Merge Intel, AMD, VIA RNG drivers into one. - Further changelog in BitKeeper. - - Version 0.9.8: - * Support other i8xx chipsets by adding 82801E detection - * 82801DB detection is the same as for 82801CA. - - Version 0.9.7: - * Support other i8xx chipsets too (by adding 82801BA(M) and - 82801CA(M) detection) - - Version 0.9.6: - * Internal driver cleanups, prep for 1.0.0 release. - - Version 0.9.5: - * Rip out entropy injection via timer. It never ever worked, - and a better solution (rngd) is now available. - - Version 0.9.4: - * Fix: Remove request_mem_region - * Fix: Horrible bugs in FIPS calculation and test execution - - Version 0.9.3: - * Clean up rng_read a bit. - * Update i810_rng driver Web site URL. - * Increase default timer interval to 4 samples per second. - * Abort if mem region is not available. - * BSS zero-initialization cleanup. - * Call misc_register() from rng_init_one. - * Fix O_NONBLOCK to occur before we schedule. - - Version 0.9.2: - * Simplify open blocking logic - - Version 0.9.1: - * Support i815 chipsets too (Matt Sottek) - * Fix reference counting when statically compiled (prumpf) - * Rewrite rng_dev_read (prumpf) - * Make module races less likely (prumpf) - * Small miscellaneous bug fixes (prumpf) - * Use pci table for PCI id list - - Version 0.9.0: - * Don't register a pci_driver, because we are really - using PCI bridge vendor/device ids, and someone - may want to register a driver for the bridge. (bug fix) - * Don't let the usage count go negative (bug fix) - * Clean up spinlocks (bug fix) - * Enable PCI device, if necessary (bug fix) - * iounmap on module unload (bug fix) - * If RNG chrdev is already in use when open(2) is called, - sleep until it is available. - * Remove redundant globals rng_allocated, rng_use_count - * Convert numeric globals to unsigned - * Module unload cleanup - - Version 0.6.2: - * Clean up spinlocks. Since we don't have any interrupts - to worry about, but we do have a timer to worry about, - we use spin_lock_bh everywhere except the timer function - itself. - * Fix module load/unload. - * Fix timer function and h/w enable/disable logic - * New timer interval sysctl - * Clean up sysctl names diff --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface index 4fe882cb4..09d6cda2a 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface @@ -3,7 +3,7 @@ possible to access all devices on an adapter from userspace, through the /dev interface. You need to load module i2c-dev for this. Each registered i2c adapter gets a number, counting from 0. You can -examine /proc/bus/i2c to see what number corresponds to which adapter. +examine /sys/class/i2c-dev/ to see what number corresponds to which adapter. I2C device files are character device files with major device number 89 and a minor device number corresponding to the number assigned as explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., @@ -19,7 +19,7 @@ Yes, I know, you should never include kernel header files, but until glibc knows about i2c, there is not much choice. Now, you have to decide which adapter you want to access. You should -inspect /proc/bus/i2c to decide this. Adapter numbers are assigned +inspect /sys/class/i2c-dev/ to decide this. Adapter numbers are assigned somewhat dynamically, so you can not even assume /dev/i2c-0 is the first adapter. diff --git a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface index f651de487..346400519 100644 --- a/Documentation/i2c/sysfs-interface +++ b/Documentation/i2c/sysfs-interface @@ -104,7 +104,7 @@ in[0-8]_input Voltage input value. in7_* varies in8_* varies -in0_ref CPU core reference voltage. +cpu[0-1]_vid CPU core reference voltage. Unit: millivolt Read only. Not always correct. @@ -135,18 +135,44 @@ fan[1-3]_div Fan divisor. Note that this is actually an internal clock divisor, which affects the measurable speed range, not the read value. -fan[1-3]_pwm Pulse width modulation fan control. +******* +* PWM * +******* + +pwm[1-3] Pulse width modulation fan control. Integer value in the range 0 to 255 Read/Write 255 is max or 100%. -fan[1-3]_pwm_enable +pwm[1-3]_enable Switch PWM on and off. Not always present even if fan*_pwm is. 0 to turn off - 1 to turn on + 1 to turn on in manual mode + 2 to turn on in automatic mode Read/Write +pwm[1-*]_auto_channels_temp + Select which temperature channels affect this PWM output in + auto mode. Bitfield, 1 is temp1, 2 is temp2, 4 is temp3 etc... + Which values are possible depend on the chip used. + +pwm[1-*]_auto_point[1-*]_pwm +pwm[1-*]_auto_point[1-*]_temp +pwm[1-*]_auto_point[1-*]_temp_hyst + Define the PWM vs temperature curve. Number of trip points is + chip-dependent. Use this for chips which associate trip points + to PWM output channels. + +OR + +temp[1-*]_auto_point[1-*]_pwm +temp[1-*]_auto_point[1-*]_temp +temp[1-*]_auto_point[1-*]_temp_hyst + Define the PWM vs temperature curve. Number of trip points is + chip-dependent. Use this for chips which associate trip points + to temperature channels. + **************** * Temperatures * diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index a45421284..011e92094 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -24,22 +24,24 @@ all clients from it. Remember, a driver structure contains general access routines, a client structure specific information like the actual I2C address. - static struct i2c_driver foo_driver = { - .owner = THIS_MODULE, - .name = "Foo version 2.3 driver", - .id = I2C_DRIVERID_FOO, /* usually from i2c-id.h */ - .flags = I2C_DF_NOTIFY, - .attach_adapter = &foo_attach_adapter, - .detach_client = &foo_detach_client, - .command = &foo_command /* may be NULL */ - } +static struct i2c_driver foo_driver = { + .owner = THIS_MODULE, + .name = "Foo version 2.3 driver", + .id = I2C_DRIVERID_FOO, /* from i2c-id.h, optional */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = &foo_attach_adapter, + .detach_client = &foo_detach_client, + .command = &foo_command /* may be NULL */ +} The name can be chosen freely, and may be upto 40 characters long. Please use something descriptive here. -The id should be a unique ID. The range 0xf000 to 0xffff is reserved for -local use, and you can use one of those until you start distributing the -driver. Before you do that, contact the i2c authors to get your own ID(s). +If used, the id should be a unique ID. The range 0xf000 to 0xffff is +reserved for local use, and you can use one of those until you start +distributing the driver, at which time you should contact the i2c authors +to get your own ID(s). Note that most of the time you don't need an ID +at all so you can just omit it. Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This means that your driver will be notified when new adapters are found. @@ -569,7 +571,7 @@ the driver module is usually enough. have to be cleaned up! */ static int __initdata foo_initialized = 0; - int __init foo_init(void) + static int __init foo_init(void) { int res; printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE); @@ -583,41 +585,27 @@ the driver module is usually enough. return 0; } - int __init foo_cleanup(void) + void foo_cleanup(void) { - int res; if (foo_initialized == 1) { if ((res = i2c_del_driver(&foo_driver))) { printk("foo: Driver registration failed, module not removed.\n"); - return res; + return; } foo_initialized --; } - return 0; } - #ifdef MODULE - /* Substitute your own name and email address */ MODULE_AUTHOR("Frodo Looijaard " MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); - int init_module(void) - { - return foo_init(); - } - - int cleanup_module(void) - { - return foo_cleanup(); - } - - #endif /* def MODULE */ + module_init(foo_init); + module_exit(foo_cleanup); Note that some functions are marked by `__init', and some data structures -by `__init_data'. If this driver is compiled as part of the kernel (instead -of as a module), those functions and structures can be removed after -kernel booting is completed. +by `__init_data'. Hose functions and structures can be removed after +kernel booting (or module loading) is completed. Command function ================ @@ -688,14 +676,26 @@ SMBus communication extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_write_word_data(struct i2c_client * client, u8 command, u16 value); - extern s32 i2c_smbus_process_call(struct i2c_client * client, - u8 command, u16 value); - extern s32 i2c_smbus_read_block_data(struct i2c_client * client, - u8 command, u8 *values); extern s32 i2c_smbus_write_block_data(struct i2c_client * client, u8 command, u8 length, u8 *values); +These ones were removed in Linux 2.6.10 because they had no users, but could +be added back later if needed: + + extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, + u8 command, u8 *values); + extern s32 i2c_smbus_read_block_data(struct i2c_client * client, + u8 command, u8 *values); + extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, + u8 command, u8 length, + u8 *values); + extern s32 i2c_smbus_process_call(struct i2c_client * client, + u8 command, u16 value); + extern s32 i2c_smbus_block_process_call(struct i2c_client *client, + u8 command, u8 length, + u8 *values) + All these transactions return -1 on failure. The 'write' transactions return 0 on success; the 'read' transactions return the read value, except for read_block, which returns the number of values read. The block buffers diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt index bbdf7261e..30badb4e3 100644 --- a/Documentation/i386/zero-page.txt +++ b/Documentation/i386/zero-page.txt @@ -28,7 +28,8 @@ Offset Type Description 0xa0 16 bytes System description table truncated to 16 bytes. ( struct sys_desc_table_struct ) - 0xb0 - 0x1c3 Free. Add more parameters here if you really need them. + 0xb0 - 0x13f Free. Add more parameters here if you really need them. + 0x140- 0x1be EDID_INFO Video mode setup 0x1c4 unsigned long EFI system table pointer 0x1c8 unsigned long EFI memory descriptor size diff --git a/Documentation/ide.txt b/Documentation/ide.txt index 58853a4ef..12c7a2fd6 100644 --- a/Documentation/ide.txt +++ b/Documentation/ide.txt @@ -248,13 +248,6 @@ Summary of ide driver parameters for kernel command line allowing ide-floppy, ide-tape, and ide-cdrom|writers to use ide-scsi emulation on a device specific option. - "hdx=stroke" : Should you have a system w/ an AWARD Bios and your - drives are larger than 32GB and it will not boot, - one is required to perform a few OEM operations first. - The option is called "stroke" because it allows one - to "soft clip" the drive to work around a barrier - limit. - "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, where "xx" is between 20 and 66 inclusive, used when tuning chipset PIO modes. @@ -304,7 +297,7 @@ Summary of ide driver parameters for kernel command line "ide=reverse" : formerly called to pci sub-system, but now local. -The following are valid ONLY on ide0 (except dc4030), which usually corresponds +The following are valid ONLY on ide0, which usually corresponds to the first ATA interface found on the particular host, and the defaults for the base,ctl ports must not be altered. @@ -315,7 +308,7 @@ the base,ctl ports must not be altered. "ide0=qd65xx" : probe/support qd65xx interface "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439/M1443/M1445) "ide0=umc8672" : probe/support umc8672 chipsets - "idex=dc4030" : probe/support Promise DC4030VL interface + "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt index b8d92c008..88a011c9f 100644 --- a/Documentation/input/joystick-parport.txt +++ b/Documentation/input/joystick-parport.txt @@ -335,6 +335,7 @@ controller (compatible with DirectPadPro): * Analog PSX Pad (red mode) * Analog PSX Pad (green mode) * PSX Rumble Pad + * PSX DDR Pad 2.4 Sega ~~~~~~~~ @@ -452,14 +453,22 @@ uses the following kernel/module command line: 5 | Multisystem 2-button joystick 6 | N64 pad 7 | Sony PSX controller + 8 | Sony PSX DDR controller - The exact type of the PSX controller type is autoprobed, so you must have -your controller plugged in before initializing. + The exact type of the PSX controller type is autoprobed when used so +hot swapping should work (but is not recomended). Should you want to use more than one of parallel ports at once, you can use gamecon.map2 and gamecon.map3 as additional command line parameters for two more parallel ports. + There are two options specific to PSX driver portion. gamecon.psx_delay sets +the command delay when talking to the controllers. The default of 25 should +work but you can try lowering it for better performace. If your pads don't +respond try raising it untill they work. Setting the type to 8 allows the +driver to be used with Dance Dance Revolution or similar games. Arrow keys are +registered as key presses instead of X and Y axes. + 3.2 db9.c ~~~~~~~~~ Apart from making an interface, there is nothing difficult on using the diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 2be1218a6..bd7a19777 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -117,6 +117,7 @@ Code Seq# Include File Comments 'c' 00-7F linux/comstats.h conflict! 'c' 00-7F linux/coda.h conflict! +'d' 00-FF linux/char/drm/drm/h conflict! 'd' 00-1F linux/devfs_fs.h conflict! 'd' 00-DF linux/video_decoder.h conflict! 'd' F0-FF linux/digi1.h diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index ec8177616..2616a58a5 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -6,7 +6,7 @@ This document describes the Linux kernel Makefiles. === 1 Overview === 2 Who does what - === 3 The kbuild Makefiles + === 3 The kbuild files --- 3.1 Goal definitions --- 3.2 Built-in object goals - obj-y --- 3.3 Loadable module goals - obj-m @@ -25,6 +25,7 @@ This document describes the Linux kernel Makefiles. --- 4.4 Using C++ for host programs --- 4.5 Controlling compiler options for host programs --- 4.6 When host programs are actually built + --- 4.7 Using hostprogs-$(CONFIG_FOO) === 5 Kbuild clean infrastructure @@ -36,6 +37,8 @@ This document describes the Linux kernel Makefiles. --- 6.5 Building non-kbuild targets --- 6.6 Commands useful for building a boot image --- 6.7 Custom kbuild commands + --- 6.8 Preprocessing linker scripts + --- 6.9 $(CC) support functions === 7 Kbuild Variables === 8 Makefile language @@ -98,11 +101,14 @@ These people need to know about all aspects of the kernel Makefiles. This document is aimed towards normal developers and arch developers. -=== 3 The kbuild Makefiles +=== 3 The kbuild files Most Makefiles within the kernel are kbuild Makefiles that use the kbuild infrastructure. This chapter introduce the syntax used in the kbuild makefiles. +The preferred name for the kbuild files is 'Kbuild' but 'Makefile' will +continue to be supported. All new developmen is expected to use the +Kbuild filename. Section 3.1 "Goal definitions" is a quick intro, further chapters provide more details, with real examples. @@ -387,7 +393,7 @@ compilation stage. Two steps are required in order to use a host executable. The first step is to tell kbuild that a host program exists. This is -done utilising the variable host-prog. +done utilising the variable hostprogs-y. The second step is to add an explicit dependency to the executable. This can be done in two ways. Either add the dependency in a rule, @@ -402,7 +408,7 @@ Both possibilities are described in the following. built on the build host. Example: - host-progs := bin2hex + hostprogs-y := bin2hex Kbuild assumes in the above example that bin2hex is made from a single c-source file named bin2hex.c located in the same directory as @@ -418,7 +424,7 @@ Both possibilities are described in the following. Example: #scripts/lxdialog/Makefile - host-progs := lxdialog + hostprogs-y := lxdialog lxdialog-objs := checklist.o lxdialog.o Objects with extension .o are compiled from the corresponding .c @@ -438,7 +444,7 @@ Both possibilities are described in the following. Example: #scripts/kconfig/Makefile - host-progs := conf + hostprogs-y := conf conf-objs := conf.o libkconfig.so libkconfig-objs := expr.o type.o @@ -457,7 +463,7 @@ Both possibilities are described in the following. Example: #scripts/kconfig/Makefile - host-progs := qconf + hostprogs-y := qconf qconf-cxxobjs := qconf.o In the example above the executable is composed of the C++ file @@ -468,7 +474,7 @@ Both possibilities are described in the following. Example: #scripts/kconfig/Makefile - host-progs := qconf + hostprogs-y := qconf qconf-cxxobjs := qconf.o qconf-objs := check.o @@ -509,7 +515,7 @@ Both possibilities are described in the following. Example: #drivers/pci/Makefile - host-progs := gen-devlist + hostprogs-y := gen-devlist $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist ( cd $(obj); ./gen-devlist ) < $< @@ -524,18 +530,32 @@ Both possibilities are described in the following. Example: #scripts/lxdialog/Makefile - host-progs := lxdialog - always := $(host-progs) + hostprogs-y := lxdialog + always := $(hostprogs-y) This will tell kbuild to build lxdialog even if not referenced in any rule. +--- 4.7 Using hostprogs-$(CONFIG_FOO) + + A typcal pattern in a Kbuild file lok like this: + + Example: + #scripts/Makefile + hostprogs-$(CONFIG_KALLSYMS) += kallsyms + + Kbuild knows about both 'y' for built-in and 'm' for module. + So if a config symbol evaluate to 'm', kbuild will still build + the binary. In other words Kbuild handle hostprogs-m exactly + like hostprogs-y. But only hostprogs-y is recommend used + when no CONFIG symbol are involved. + === 5 Kbuild clean infrastructure "make clean" deletes most generated files in the src tree where the kernel is compiled. This includes generated files such as host programs. -Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and -$(targets). They are all deleted during "make clean". +Kbuild knows targets listed in $(hostprogs-y), $(hostprogs-m), $(always), +$(extra-y) and $(targets). They are all deleted during "make clean". Files matching the patterns "*.[oas]", "*.ko", plus some additional files generated by kbuild are deleted all over the kernel src tree when "make clean" is executed. @@ -547,8 +567,17 @@ Additional files can be specified in kbuild makefiles by use of $(clean-files). clean-files := devlist.h classlist.h When executing "make clean", the two files "devlist.h classlist.h" will -be deleted. Kbuild knows that files specified by $(clean-files) are -located in the same directory as the makefile. +be deleted. Kbuild will assume files to be in same relative directory as the +Makefile except if an absolute path is specified (path starting with '/'). + +To delete a directory hirachy use: + Example: + #scripts/package/Makefile + clean-dirs := $(objtree)/debian/ + +This will delete the directory debian, including all subdirectories. +Kbuild will assume the directories to be in the same relative path as the +Makefile if no absolute path is specified (path does not start with '/'). Usually kbuild descends down in subdirectories due to "obj-* := dir/", but in the architecture makefiles where the kbuild infrastructure @@ -638,15 +667,6 @@ When kbuild executes the following steps are followed (roughly): #arch/i386/Makefile LDFLAGS_vmlinux := -e stext - LDFLAGS_BLOB Options for $(LD) when linking the initramfs blob - - The image used for initramfs is made during the build process. - LDFLAGS_BLOB is used to specify additional flags to be used when - creating the initramfs_data.o file. - Example: - #arch/i386/Makefile - LDFLAGS_BLOB := --format binary --oformat elf32-i386 - OBJCOPYFLAGS objcopy flags When $(call if_changed,objcopy) is used to translate a .o file, @@ -690,15 +710,17 @@ When kbuild executes the following steps are followed (roughly): probe supported options: #arch/i386/Makefile - check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc \ - /dev/null\ > /dev/null 2>&1; then echo "$(1)"; \ - else echo "$(2)"; fi) - cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,\ - -march=c3,-march=i486) - CFLAGS += $(cflags-y) + ... + cflags-$(CONFIG_MPENTIUMII) += $(call cc-option,\ + -march=pentium2,-march=i686) + ... + # Disable unit-at-a-time mode ... + CFLAGS += $(call cc-option,-fno-unit-at-a-time) + ... + - The above examples both utilise the trick that a config option expands + The first examples utilises the trick that a config option expands to 'y' when selected. CFLAGS_KERNEL $(CC) options specific for built-in @@ -914,6 +936,105 @@ When kbuild executes the following steps are followed (roughly): will be displayed with "make KBUILD_VERBOSE=0". +--- 6.8 Preprocessing linker scripts + + When the vmlinux image is build the linker script: + arch/$(ARCH)/kernel/vmlinux.lds is used. + The script is a preprocessed variant of the file vmlinux.lds.S + located in the same directory. + kbuild knows .lds file and includes a rule *lds.S -> *lds. + + Example: + #arch/i386/kernel/Makefile + always := vmlinux.lds + + #Makefile + export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) + + The assigment to $(always) is used to tell kbuild to build the + target: vmlinux.lds. + The assignment to $(CPPFLAGS_vmlinux.lds) tell kbuild to use the + specified options when building the target vmlinux.lds. + + When building the *.lds target kbuild used the variakles: + CPPFLAGS : Set in top-level Makefile + EXTRA_CPPFLAGS : May be set in the kbuild makefile + CPPFLAGS_$(@F) : Target specific flags. + Note that the full filename is used in this + assignment. + + The kbuild infrastructure for *lds file are used in several + architecture specific files. + + +--- 6.9 $(CC) support functions + + The kernel may be build with several different versions of + $(CC), each supporting a unique set of features and options. + kbuild provide basic support to check for valid options for $(CC). + $(CC) is useally the gcc compiler, but other alternatives are + available. + + cc-option + cc-option is used to check if $(CC) support a given option, and not + supported to use an optional second option. + + Example: + #arch/i386/Makefile + cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586) + + In the above example cflags-y will be assigned the option + -march=pentium-mmx if supported by $(CC), otherwise -march-i586. + The second argument to cc-option is optional, and if omitted + cflags-y will be assigned no value if first option is not supported. + + cc-option-yn + cc-option-yn is used to check if gcc supports a given option + and return 'y' if supported, otherwise 'n'. + + Example: + #arch/ppc/Makefile + biarch := $(call cc-option-yn, -m32) + aflags-$(biarch) += -a32 + cflags-$(biarch) += -m32 + + In the above example $(biarch) is set to y if $(CC) supports the -m32 + option. When $(biarch) equals to y the expanded variables $(aflags-y) + and $(cflags-y) will be assigned the values -a32 and -m32. + + cc-option-align + gcc version >= 3.0 shifted type of options used to speify + alignment of functions, loops etc. $(cc-option-align) whrn used + as prefix to the align options will select the right prefix: + gcc < 3.00 + cc-option-align = -malign + gcc >= 3.00 + cc-option-align = -falign + + Example: + CFLAGS += $(cc-option-align)-functions=4 + + In the above example the option -falign-functions=4 is used for + gcc >= 3.00. For gcc < 3.00 -malign-functions=4 is used. + + cc-version + cc-version return a numerical version of the $(CC) compiler version. + The format is where both are two digits. So for example + gcc 3.41 would return 0341. + cc-version is useful when a specific $(CC) version is faulty in one + area, for example the -mregparm=3 were broken in some gcc version + even though the option was accepted by gcc. + + Example: + #arch/i386/Makefile + GCC_VERSION := $(call cc-version) + cflags-y += $(shell \ + if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) + + In the above example -mregparm=3 is only used for gcc version greater + than or equal to gcc 3.0. + + === 7 Kbuild Variables The top Makefile exports the following variables: diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt index b8933206f..c91caf7eb 100644 --- a/Documentation/kbuild/modules.txt +++ b/Documentation/kbuild/modules.txt @@ -1,68 +1,419 @@ -For now this is a raw copy from the old Documentation/kbuild/modules.txt, -which was removed in 2.6.0-test5. -The information herein is correct but not complete. - -Installing modules in a non-standard location ---------------------------------------------- -When the modules needs to be installed under another directory -the INSTALL_MOD_PATH can be used to prefix "/lib/modules" as seen -in the following example: - -make INSTALL_MOD_PATH=/frodo modules_install - -This will install the modules in the directory /frodo/lib/modules. -/frodo can be a NFS mounted filesystem on another machine, allowing -out-of-the-box support for installation on remote machines. - - -Compiling modules outside the official kernel ---------------------------------------------- - -Often modules are developed outside the official kernel. To keep up -with changes in the build system the most portable way to compile a -module outside the kernel is to use the kernel build system, -kbuild. Use the following command-line: - -make -C path/to/kernel/src M=$PWD modules - -This requires that a makefile exits made in accordance to -Documentation/kbuild/makefiles.txt. Read that file for more details on -the build system. - -The following is a short summary of how to write your Makefile to get -you up and running fast. Assuming your module will be called -yourmodule.ko, your code should be in yourmodule.c and your Makefile -should include - -obj-m := yourmodule.o - -If the code for your module is in multiple files that need to be -linked, you need to tell the build system which files to compile. In -the case of multiple files, none of these files can be named -yourmodule.c because doing so would cause a problem with the linking -step. Assuming your code exists in file1.c, file2.c, and file3.c and -you want to build yourmodule.ko from them, your Makefile should -include - -obj-m := yourmodule.o -yourmodule-objs := file1.o file2.o file3.o - -Now for a final example to put it all together. Assuming the -KERNEL_SOURCE environment variable is set to the directory where you -compiled the kernel, a simple Makefile that builds yourmodule.ko as -described above would look like - -# Tells the build system to build yourmodule.ko. -obj-m := yourmodule.o - -# Tells the build system to build these object files and link them as -# yourmodule.o, before building yourmodule.ko. This line can be left -# out if all the code for your module is in one file, yourmodule.c. If -# you are using multiple files, none of these files can be named -# yourmodule.c. -yourmodule-objs := file1.o file2.o file3.o - -# Invokes the kernel build system to come back to the current -# directory and build yourmodule.ko. -default: - make -C ${KERNEL_SOURCE} M=`pwd` modules + +In this document you will find information about: +- how to build external modules +- how to make your module use kbuild infrastructure +- how kbuild will install a kernel +- how to install modules in a non-standard location + +=== Table of Contents + + === 1 Introduction + === 2 How to build external modules + --- 2.1 Building external modules + --- 2.2 Available targets + --- 2.3 Available options + --- 2.4 Preparing the kernel tree for module build + === 3. Example commands + === 4. Creating a kbuild file for an external module + === 5. Include files + --- 5.1 How to include files from the kernel include dir + --- 5.2 External modules using an include/ dir + === 6. Module installation + --- 6.1 INSTALL_MOD_PATH + --- 6.2 INSTALL_MOD_DIR + === 7. Module versioning + === 8. Tips & Tricks + --- 8.1 Testing for CONFIG_FOO_BAR + + + +=== 1. Introduction + +kbuild includes functionality for building modules both +within the kernel source tree and outside the kernel source tree. +The latter is usually referred to as external modules and is used +both during development and for modules that are not planned to be +included in the kernel tree. + +What is covered within this file is mainly information to authors +of modules. The author of an external modules should supply +a makefile that hides most of the complexity so one only has to type +'make' to buld the module. A complete example will be present in +chapter ¤. Creating a kbuild file for an external module". + + +=== 2. How to build external modules + +kbuild offers functionality to build external modules, with the +prerequisite that there is a pre-built kernel available with full source. +A subset of the targets available when building the kernel is available +when building an external module. + +--- 2.1 Building external modules + + Use the following command to build an external module: + + make -C M=`pwd` + + For the running kernel use: + make -C /lib/modules/`uname -r`/build M=`pwd` + + For the above command to succeed the kernel must have been built with + modules enabled. + + To install the modules that were just built: + + make -C M=`pwd` modules_install + + More complex examples later, the above should get you going. + +--- 2.2 Available targets + + $KDIR refers to path to kernel source top-level directory + + make -C $KDIR M=`pwd` + Will build the module(s) located in current directory. + All output files will be located in the same directory + as the module source. + No attempts are made to update the kernel source, and it is + a precondition that a successful make has been executed + for the kernel. + + make -C $KDIR M=`pwd` modules + The modules target is implied when no target is given. + Same functionality as if no target was specified. + See description above. + + make -C $KDIR M=$PWD modules_install + Install the external module(s). + Installation default is in /lib/modules//extra, + but may be prefixed with INSTALL_MOD_PATH - see separate chater. + + make -C $KDIR M=$PWD clean + Remove all generated files for the module - the kernel + source directory is not moddified. + + make -C $KDIR M=`pwd` help + help will list the available target when building external + modules. + +--- 2.3 Available options: + + $KDIR refer to path to kernel src + + make -C $KDIR + Used to specify where to find the kernel source. + '$KDIR' represent the directory where the kernel source is. + Make will actually change directory to the specified directory + when executed but change back when finished. + + make -C $KDIR M=`pwd` + M= is used to tell kbuild that an external module is + being built. + The option given to M= is the directory where the external + module (kbuild file) is located. + When an external module is being built only a subset of the + usual targets are available. + + make -C $KDIR SUBDIRS=`pwd` + Same as M=. The SUBDIRS= syntax is kept for backwards + compatibility. + +--- 2.4 Preparing the kernel tree for module build + + To make sure the kernel contains the information required to + build external modules the target 'modules_prepare' must be used. + 'module_prepare' solely exists as a simple way to prepare + a kernel for building external modules. + Note: modules_prepare will not build Module.symvers even if + CONFIG_MODULEVERSIONING is set. + Therefore a full kernel build needs to be executed to make + module versioning work. + + +=== 3. Example commands + +This example shows the actual commands to be executed when building +an external module for the currently running kernel. +In the example below the distribution is supposed to use the +facility to locate output files for a kernel compile in a different +directory than the kernel source - but the examples will also work +when the source and the output files are mixed in the same directory. + +# Kernel source +/lib/modules//source -> /usr/src/linux- + +# Output from kernel compile +/lib/modules//build -> /usr/src/linux--up + +Change to the directory where the kbuild file is located and execute +the following commands to build the module: + + cd /home/user/src/module + make -C /usr/src/`uname -r`/source \ + O=/lib/modules/`uname-r`/build \ + M=`pwd` + +Then to install the module use the following command: + + make -C /usr/src/`uname -r`/source \ + O=/lib/modules/`uname-r`/build \ + M=`pwd` \ + modules_install + +If one looks closely you will see that this is the same commands as +listed before - with the directories spelled out. + +The above are rather long commands, and the following chapter +lists a few tricks to make it all easier. + + +=== 4. Creating a kbuild file for an external module + +kbuild is the build system for the kernel, and external modules +must use kbuild to stay compatible with changes in the build system +and to pick up the right flags to gcc etc. + +The kbuild file used as input shall follow the syntax described +in Documentation/kbuild/makefiles.txt. This chapter will introduce a few +more tricks to be used when dealing with external modules. + +In the following a Makefile will be created for a module with the +following files: + 8123_if.c + 8123_if.h + 8123_pci.c + 8123_bin.o_shipped <= Binary blob + +--- 4.1 Shared Makefile for module and kernel + + An external module always includes a wrapper Makefile supporting + building the module using 'make' with no arguments. + The Makefile provided will most likely include additional + functionality such as test targets etc. and this part shall + be filtered away from kbuild since it may impact kbuild if + name clashes occurs. + + Example 1: + --> filename: Makefile + ifneq ($(KERNELRELEASE),) + # kbuild part of makefile + obj-m := 8123.o + 8123-y := 8123_if.o 8123_pci.o 8123_bin.o + + else + # Normal Makefile + + KERNELDIR := /lib/modules/`uname -r`/build + all:: + $(MAKE) -C $KERNELDIR M=`pwd` $@ + + # Module specific targets + genbin: + echo "X" > 8123_bini.o_shipped + + endif + + In example 1 the check for KERNELRELEASE is used to separate + the two parts of the Makefile. kbuild will only see the two + assignments whereas make will see everything except the two + kbuild assignments. + + In recent versions of the kernel, kbuild will look for a file named + Kbuild and as second option look for a file named Makefile. + Utilising the Kbuild file makes us split up the Makefile in example 1 + into two files as shown in example 2: + + Example 2: + --> filename: Kbuild + obj-m := 8123.o + 8123-y := 8123_if.o 8123_pci.o 8123_bin.o + + --> filename: Makefile + KERNELDIR := /lib/modules/`uname -r`/build + all:: + $(MAKE) -C $KERNELDIR M=`pwd` $@ + + # Module specific targets + genbin: + echo "X" > 8123_bin_shipped + + + In example 2 we are down to two fairly simple files and for simple + files as used in this example the split is questionable. But some + external modules use Makefiles of several hundred lines and here it + really pays off to separate the kbuild part from the rest. + Example 3 shows a backward compatible version. + + Example 3: + --> filename: Kbuild + obj-m := 8123.o + 8123-y := 8123_if.o 8123_pci.o 8123_bin.o + + --> filename: Makefile + ifneq ($(KERNELRELEASE),) + include Kbuild + else + # Normal Makefile + + KERNELDIR := /lib/modules/`uname -r`/build + all:: + $(MAKE) -C $KERNELDIR M=`pwd` $@ + + # Module specific targets + genbin: + echo "X" > 8123_bin_shipped + + endif + + The trick here is to include the Kbuild file from Makefile so + if an older version of kbuild picks up the Makefile the Kbuild + file will be included. + +--- 4.2 Binary blobs included in a module + + Some external modules needs to include a .o as a blob. kbuild + has support for this, but requires the blob file to be named + _shipped. In our example the blob is named + 8123_bin.o_shipped and when the kbuild rules kick in the file + 8123_bin.o is created as a simple copy off the 8213_bin.o_shipped file + with the _shipped part stripped of the filename. + This allows the 8123_bin.o filename to be used in the assignment to + the module. + + Example 4: + obj-m := 8123.o + 8123-y := 8123_if.o 8123_pci.o 8123_bin.o + + In example 4 there is no distinction between the ordinary .c/.h files + and the binary file. But kbuild will pick up different rules to create + the .o file. + + +=== 5. Include files + +Include files are a necessity when a .c file uses something from another .c +files (not strictly in the sense of .c but if good programming practice is +used). Any module that consist of more than one .c file will have a .h file +for one of the .c files. +- If the .h file only describes a module internal interface then the .h file + shall be placed in the same directory as the .c files. +- If the .h files describe an interface used by other parts of the kernel + located in different directories, the .h files shall be located in + include/linux/ or other include/ directories as appropriate. + +One exception for this rule is larger subsystems that have their own directory +under include/ such as include/scsi. Another exception is arch-specific +.h files which are located under include/asm-$(ARCH)/*. + +External modules have a tendency to locate include files in a separate include/ +directory and therefore needs to deal with this in their kbuild file. + +--- 5.1 How to include files from the kernel include dir + + When a module needs to include a file from include/linux/ then one + just uses: + + #include + + kbuild will make sure to add options to gcc so the relevant + directories are searched. + Likewise for .h files placed in the same directory as the .c file. + + #include "8123_if.h" + + will do the job. + +--- 5.2 External modules using an include/ dir + + External modules often locate their .h files in a separate include/ + directory although this is not usual kernel style. When an external + module uses an include/ dir then kbuild needs to be told so. + The trick here is to use either EXTRA_CFLAGS (take effect for all .c + files) or CFLAGS_$F.o (take effect only for a single file). + + In our example if we move 8123_if.h to a subdirectory named include/ + the resulting Kbuild file would look like: + + --> filename: Kbuild + obj-m := 8123.o + + EXTRA_CFLAGS := -Iinclude + 8123-y := 8123_if.o 8123_pci.o 8123_bin.o + + Note that in the assingment there is no space between -I and the path. + This is a kbuild limitation and no space must be present. + + +=== 6. Module installation + +Modules which are included in the kernel is installed in the directory: + + /lib/modules/$(KERNELRELEASE)/kernel + +External modules are installed in the directory: + + /lib/modules/$(KERNELRELEASE)/extra + +--- 6.1 INSTALL_MOD_PATH + + Above are the default directories, but as always some level of + customization is possible. One can prefix the path using the variable + INSTALL_MOD_PATH: + + $ make INSTALL_MOD_PATH=/frodo modules_install + => Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel + + INSTALL_MOD_PATH may be set as an ordinary shell variable or as in the + example above be specified on the commandline when calling make. + INSTALL_MOD_PATH has effect both when installing modules included in + the kernel as well as when installing external modules. + +--- 6.2 INSTALL_MOD_DIR + + When installing external modules they are default installed in a + directory under /lib/modules/$(KERNELRELEASE)/extra, but one may wish + to locate modules for a specific functionality in a separate + directory. For this purpose one can use INSTALL_MOD_DIR to specify an + alternative name than 'extra'. + + $ make INSTALL_MOD_DIR=gandalf -C KERNELDIR \ + M=`pwd` modules_install + => Install dir: /lib/modules/$(KERNELRELEASE)/gandalf + + +=== 7. Module versioning + +Module versioning are enabled by the CONFIG_MODVERSIONS tag. + +Module versioning is used as a simple ABI consistency check. The Module +versioning creates a CRC value of the full prototype for an exported symbol and +when a module is loaded/used then the CRC values contained in the kernel are +compared with similar values in the module. If they are not equal then the +kernel refuses to load the module. + +During a kernel build a file named Module.symvers will be generated. This +file includes the symbol version of all symbols within the kernel. If the +Module.symvers file is saved from the last full kernel compile one does not +have to do a full kernel compile to build a module version's compatible module. + +=== 8. Tips & Tricks + +--- 8.1 Testing for CONFIG_FOO_BAR + + Modules often needs to check for certain CONFIG_ options to decide if + a specific feature shall be included in the module. When kbuild is used + this is done by referencing the CONFIG_ variable directly. + + #fs/ext2/Makefile + obj-$(CONFIG_EXT2_FS) += ext2.o + + ext2-y := balloc.o bitmap.o dir.o + ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o + + External modules have traditionally used grep to check for specific + CONFIG_ settings directly in .config. This usage is broken. + As introduced before external modules shall use kbuild when building + and therefore can use the same methods as in-kernel modules when testing + for CONFIG_ definitions. + diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 13839bd74..d133c4307 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -53,6 +53,7 @@ restrictions referred to are that the relevant option is valid if: NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. PARIDE The ParIDE subsystem is enabled. + PARISC The PA-RISC architecture is enabled. PCI PCI bus support is enabled. PCMCIA The PCMCIA subsystem is enabled. PNP Plug & Play support is enabled. @@ -97,9 +98,6 @@ running once the system is up. See header of drivers/scsi/53c7xx.c. See also Documentation/scsi/ncr53c7xx.txt. - 98busmouse.irq= [HW,MOUSE] PC-9801 Bus Mouse Driver - Format: , default is 13 - acpi= [HW,ACPI] Advanced Configuration and Power Interface Format: { force | off | ht | strict } force -- enable ACPI if default was off @@ -138,6 +136,20 @@ running once the system is up. Recognize and ignore IRQ0/pin2 Interrupt Override. For broken nForce2 BIOS resulting in XT-PIC timer. + acpi_dbg_layer= [HW,ACPI] + Format: + Each bit of the indicates an acpi debug layer, + 1: enable, 0: disable. It is useful for boot time + debugging. After system has booted up, it can be set + via /proc/acpi/debug_layer. + + acpi_dbg_level= [HW,ACPI] + Format: + Each bit of the indicates an acpi debug level, + 1: enable, 0: disable. It is useful for boot time + debugging. After system has booted up, it can be set + via /proc/acpi/debug_level. + ad1816= [HW,OSS] Format: ,,, See also Documentation/sound/oss/AD1816. @@ -189,6 +201,11 @@ running once the system is up. Disable APC CPU standby support. SPARCstation-Fox does not play well with APC CPU idle - disable it if you have APC and your system crashes randomly. + + apic= [APIC,i386] Change the output verbosity whilst booting + Format: { quiet (default) | verbose | debug } + Change the amount of debugging information output + when initialising the APIC and IO-APIC components. apm= [APM] Advanced Power Management See header of arch/i386/kernel/apm.c. @@ -295,8 +312,24 @@ running once the system is up. condev= [HW,S390] console device conmode= - console= [KNL] Output console - Console device and comm spec (speed, control, parity). + console= [KNL] Output console device and options. + + tty Use the virtual console device . + + ttyS[,options] + Use the specified serial port. The options are of + the form "bbbbpn", where "bbbb" is the baud rate, + "p" is parity ("n", "o", or "e"), and "n" is bits. + Default is "9600n8". + + See also Documentation/serial-console.txt. + + uart,io,[,options] + uart,mmio,[,options] + Start an early, polled-mode console on the 8250/16550 + UART at the specified I/O port or MMIO address, + switching to the matching ttyS device later. The + options are the same as for ttyS, above. cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver Format: ,,,[,] @@ -378,7 +411,7 @@ running once the system is up. eicon= [HW,ISDN] Format: ,, - eisa_irq_edge= [PARISC] + eisa_irq_edge= [PARISC,HW] See header of drivers/parisc/eisa.c. elanfreq= [IA-32] @@ -387,7 +420,8 @@ running once the system is up. elevator= [IOSCHED] Format: {"as"|"cfq"|"deadline"|"noop"} - See Documentation/as-iosched.txt for details + See Documentation/block/as-iosched.txt + and Documentation/block/deadline-iosched.txt for details. es1370= [HW,OSS] Format: [,] @@ -448,6 +482,11 @@ running once the system is up. hd?= [HW] (E)IDE subsystem hd?lun= See Documentation/ide.txt. + highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact + size of . This works even on boxes that have no + highmem otherwise. This also works to reduce highmem + size on bigger boxes. + hisax= [HW,ISDN] See Documentation/isdn/README.HiSax. @@ -467,16 +506,26 @@ running once the system is up. i810= [HW,DRM] + i8k.force [HW] Activate i8k driver even if SMM BIOS signature + does not match list of supported models. + i8k.power_status + [HW] Report power status in /proc/i8k + (disabled by default) + i8k.restricted [HW] Allow controlling fans only if SYS_ADMIN + capability is set. + ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter See Documentation/mca.txt. icn= [HW,ISDN] Format: [,[,[,]]] + ide= [HW] (E)IDE subsystem + Format: ide=nodma or ide=doubler or ide=reverse + See Documentation/ide.txt. + ide?= [HW] (E)IDE subsystem - Config (iomem/irq), tuning or debugging - (serialize,reset,no{dma,tune,probe}) or chipset - specific parameters. + Format: ide?=noprobe or chipset specific parameters. See Documentation/ide.txt. idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed @@ -523,6 +572,18 @@ running once the system is up. isapnp= [ISAPNP] Format: , , , + isolcpus= [KNL,SMP] Isolate CPUs from the general scheduler. + Format: , ..., + This option can be used to specify one or more CPUs + to isolate from the general SMP balancing and scheduling + algorithms. The only way to move a process onto or off + an "isolated" CPU is via the CPU affinity syscalls. + + This option is the preferred way to isolate CPUs. The + alternative - manually setting the CPU mask of all tasks + in the system can cause problems and suboptimal load + balancer performance. + isp16= [HW,CD] Format: ,,, @@ -574,6 +635,20 @@ running once the system is up. so, the driver will manage that printer. See also header of drivers/char/lp.c. + lpj=n [KNL] + Sets loops_per_jiffy to given constant, thus avoiding + time-consuming boot-time autodetection (up to 250 ms per + CPU). 0 enables autodetection (default). To determine + the correct value for your kernel, boot with normal + autodetection and see what value is printed. Note that + on SMP systems the preset will be applied to all CPUs, + which is likely to cause problems if your CPUs need + significantly divergent settings. An incorrect value + will cause delays in the kernel to be wrong, leading to + unpredictable I/O errors and other breakage. Although + unlikely, in the extreme case this might damage your + hardware. + ltpc= [NET] Format: ,, @@ -596,9 +671,10 @@ running once the system is up. maxcpus= [SMP] Maximum number of processors that an SMP kernel should make use of - max_scsi_luns= [SCSI] + max_luns= [SCSI] Maximum number of LUNs to probe + Should be between 1 and 2^32-1. - max_scsi_report_luns= + max_report_luns= [SCSI] Maximum number of LUNs received Should be between 1 and 16384. @@ -623,6 +699,9 @@ running once the system is up. mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory Amount of memory to be used when the kernel is not able to see the whole system memory or for test. + [IA-32] Use together with memmap= to avoid physical + address space collisions. Without memmap= PCI devices + could be placed at addresses belonging to unused RAM. mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel memory. @@ -645,11 +724,17 @@ running once the system is up. [KNL,ACPI] Mark specific memory as reserved. Region of memory to be used, from ss to ss+nn. - meye= [HW] Set MotionEye Camera parameters + meye.*= [HW] Set MotionEye Camera parameters See Documentation/video4linux/meye.txt. mga= [HW,DRM] + mousedev.tap_time= + [MOUSE] Maximum time between finger touching and + leaving touchpad surface for touch to be considered + a tap and be reported as a left button click (for + touchpads working in absolute mode only). + Format: mousedev.xres= [MOUSE] Horizontal screen resolution, used for devices reporting absolute coordinates, such as tablets mousedev.yres= [MOUSE] Vertical screen resolution, used for devices @@ -701,26 +786,27 @@ running once the system is up. noalign [KNL,ARM] - noapic [SMP,APIC] Tells the kernel not to make use of any - APIC that may be present on the system. + noapic [SMP,APIC] Tells the kernel to not make use of any + IOAPICs that may be present in the system. noasync [HW,M68K] Disables async and sync negotiation for all devices. + nobats [PPC] Do not use BATs for mapping kernel lowmem + on "Classic" PPC cores. + nocache [ARM] nodisconnect [HW,SCSI,M68K] Disables SCSI disconnects. noexec [IA-64] - noexec [i386] + noexec [i386, x86_64] noexec=on: enable non-executable mappings (default) noexec=off: disable nn-executable mappings nofxsr [BUGS=IA-32] - nohighio [BUGS=IA-32] Disable highmem block I/O. - nohlt [BUGS=ARM] no-hlt [BUGS=IA-32] Tells the kernel that the hlt @@ -739,8 +825,13 @@ running once the system is up. nolapic [IA-32,APIC] Do not enable or use the local APIC. + noltlbs [PPC] Do not use large page/tlb entries for kernel + lowmem mapping on PPC40x. + nomce [IA-32] Machine Check Exception + noresidual [PPC] Don't use residual data on PReP machines. + noresume [SWSUSP] Disables resume and restore original swap space. no-scroll [VGA] Disables scrollback. @@ -796,6 +887,16 @@ running once the system is up. order they are specified on the command line, starting with parport0. + parport_init_mode= + [HW,PPT] Configure VIA parallel port to + operate in specific mode. This is + necessary on Pegasos computer where + firmware has no options for setting up + parallel port mode and sets it to + spp. Currently this function knows + 686a and 8231 chips. + Format: [spp|ps2|epp|ecp|ecpepp] + pas2= [HW,OSS] Format: ,,,,,,, @@ -851,12 +952,28 @@ running once the system is up. enabled. noacpi [IA-32] Do not use ACPI for IRQ routing or for PCI scanning. + routeirq Do IRQ routing for all PCI devices. + This is normally done in pci_enable_device(), + so this option is a temporary workaround + for broken drivers that don't call it. + + firmware [ARM] Do not re-enumerate the bus but + instead just use the configuration + from the bootloader. This is currently + used on IXP2000 systems where the + bus has to be configured a certain way + for adjunct CPUs. pcmv= [HW,PCMCIA] BadgePAD 4 pd. [PARIDE] See Documentation/paride.txt. + pdcchassis= [PARISC,HW] Disable/Enable PDC Chassis Status codes at + boot time. + Format: { 0 | 1 } + See arch/parisc/kernel/pdc_chassis.c + pf. [PARIDE] See Documentation/paride.txt. @@ -887,7 +1004,14 @@ running once the system is up. Ranges are in pairs (memory base and size). profile= [KNL] Enable kernel profiling via /proc/profile - (param: profile step/bucket size as a power of 2) + { schedule | } + (param: schedule - profile schedule points} + (param: profile step/bucket size as a power of 2 for + statistical time based profiling) + + processor.max_cstate= [HW, ACPI] + Limit processor to maximum C-state + max_cstate=9 overrides any DMI blacklist limit. prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk before loading. @@ -930,10 +1054,6 @@ running once the system is up. New name for the ramdisk parameter. See Documentation/ramdisk.txt. - ramdisk_start= [RAM] Starting block of RAM disk image (so you can - place it after the kernel image on a boot floppy). - See Documentation/ramdisk.txt. - reboot= [BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode Format: [,[,...]] See arch/*/kernel/reboot.c. @@ -989,8 +1109,6 @@ running once the system is up. scsi_logging= [SCSI] - scsihosts= [SCSI] - serialnumber [BUGS=IA-32] sf16fm= [HW] SF16FMI radio driver for Linux @@ -1148,17 +1266,12 @@ running once the system is up. sonycd535= [HW,CD] Format: [,] - sonypi= [HW] Sony Programmable I/O Control Device driver - Format: ,,,,, + sonypi.*= [HW] Sony Programmable I/O Control Device driver + See Documentation/sonypi.txt specialix= [HW,SERIAL] Specialix multi-serial port adapter See Documentation/specialix.txt. - speedstep_coppermine= - [HW,IA-32] Take CPU in your notebook as SpeedStep-capable - See comment before function speedstep_setup() in - arch/i386/kernel/cpu/cpufreq/speedstep.c. - spia_io_base= [HW,MTD] spia_fio_base= spia_pedr= @@ -1173,7 +1286,7 @@ running once the system is up. st0x= [HW,SCSI] See header of drivers/scsi/seagate.c. - sti= [HW] + sti= [PARISC,HW] Format: Set the STI (builtin display/keyboard on the HP-PARISC machines) console (graphic card) which should be used @@ -1240,6 +1353,8 @@ running once the system is up. uart6850= [HW,OSS] Format: , + + usb-handoff [HW] Enable early USB BIOS -> OS handoff video= [FB] Frame buffer configuration See Documentation/fb/modedb.txt. @@ -1250,6 +1365,12 @@ running once the system is up. This is actually a boot loader parameter; the value is passed to the kernel using a special protocol. + vmalloc=nn[KMG] [KNL,BOOT] forces the vmalloc area to have an exact + size of . This can be used to increase the + minimum size (128MB on x86). It can also be used to + decrease the size and leave more room for directly + mapped kernel RAM. + vmhalt= [KNL,S390] vmpoff= [KNL,S390] diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt index 065e59cbb..dc4e810af 100644 --- a/Documentation/laptop-mode.txt +++ b/Documentation/laptop-mode.txt @@ -249,7 +249,7 @@ MINIMUM_BATTERY_MINUTES=10 # playing. #READAHEAD=4096 -# Shall we remount journaled fs. with appropiate commit interval? (1=yes) +# Shall we remount journaled fs. with appropriate commit interval? (1=yes) #DO_REMOUNTS=1 # And shall we add the "noatime" option to that as well? (1=yes) diff --git a/Documentation/md.txt b/Documentation/md.txt index 3fb3b1ef1..e2b536992 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -45,7 +45,8 @@ Boot time autodetection of RAID arrays When md is compiled into the kernel (not as module), partitions of type 0xfd are scanned and automatically assembled into RAID arrays. This autodetection may be suppressed with the kernel parameter -"raid=noautodetect". +"raid=noautodetect". As of kernel 2.6.9, only drives with a type 0 +superblock can be autodetected and run at boot time. The kernel parameter "raid=partitionable" (or "raid=part") means that all auto-detected arrays are assembled as partitionable. @@ -55,13 +56,13 @@ Superblock formats ------------------ The md driver can support a variety of different superblock formats. -(It doesn't yet, but it can) +Currently, it supports superblock formats "0.90.0" and the "md-1" format +introduced in the 2.5 development series. -The kernel does *NOT* autodetect which format superblock is being -used. It must be told. +The kernel will autodetect which format superblock is being used. Superblock format '0' is treated differently to others for legacy -reasons. +reasons - it is the original superblock format. General Rules - apply for all superblock formats @@ -69,6 +70,7 @@ General Rules - apply for all superblock formats An array is 'created' by writing appropriate superblocks to all devices. + It is 'assembled' by associating each of these devices with an particular md virtual device. Once it is completely assembled, it can be accessed. @@ -76,10 +78,10 @@ be accessed. An array should be created by a user-space tool. This will write superblocks to all devices. It will usually mark the array as 'unclean', or with some devices missing so that the kernel md driver -can create approrpriate redundancy (copying in raid1, parity +can create appropriate redundancy (copying in raid1, parity calculation in raid4/5). -When an array is assembled, it is first initialised with the +When an array is assembled, it is first initialized with the SET_ARRAY_INFO ioctl. This contains, in particular, a major and minor version number. The major version number selects which superblock format is to be used. The minor number might be used to tune handling @@ -101,15 +103,16 @@ array using HOT_REMOVE_DISK. Specific Rules that apply to format-0 super block arrays, and - arrays with no superblock (non-persistant). + arrays with no superblock (non-persistent). ------------------------------------------------------------- An array can be 'created' by describing the array (level, chunksize etc) in a SET_ARRAY_INFO ioctl. This must has major_version==0 and raid_disks != 0. -Then uninitialised devices can be added with ADD_NEW_DISK. The + +Then uninitialized devices can be added with ADD_NEW_DISK. The structure passed to ADD_NEW_DISK must specify the state of the device and it's role in the array. -One started with RUN_ARRAY, uninitialised spares can be added with +Once started with RUN_ARRAY, uninitialized spares can be added with HOT_ADD_DISK. diff --git a/Documentation/memory.txt b/Documentation/memory.txt index 7af1709e8..2b3dedd39 100644 --- a/Documentation/memory.txt +++ b/Documentation/memory.txt @@ -21,6 +21,8 @@ systems. All of these problems can be addressed with the "mem=XXXM" boot option (where XXX is the size of RAM to use in megabytes). It can also tell Linux to use less memory than is actually installed. +If you use "mem=" on a machine with PCI, consider using "memmap=" to avoid +physical address space collisions. See the documentation of your boot loader (LILO, loadlin, etc.) about how to pass options to the kernel. @@ -44,7 +46,9 @@ Try: * Disabling the cache from the BIOS. * Try passing the "mem=4M" option to the kernel to limit - Linux to using a very small amount of memory. + Linux to using a very small amount of memory. Use "memmap="-option + together with "mem=" on systems with PCI to avoid physical address + space collisions. Other tricks: diff --git a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt index 0b2b7051a..e4b6c7afc 100644 --- a/Documentation/networking/e100.txt +++ b/Documentation/networking/e100.txt @@ -1,14 +1,16 @@ Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters ============================================================== -March 15, 2004 +September 13, 2004 Contents ======== - In This Release -- Supported Adapters +- Identifying Your Adapter +- Driver Configuration Parameters +- Additional Configurations - Support @@ -16,26 +18,140 @@ In This Release =============== This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of -Adapters, version 3.x.x. This driver includes support for Itanium(TM)-based -systems. +Adapters, version 3.2.x. This driver includes support for Itanium(TM)2 and +EM64T systems. -Supported Adapters -================== - -To verify that your adapter is supported, find the board ID number on the -adapter. Look for a label that has a barcode and a number in the format -A12345-001. Match this to the list of numbers above. +Identifying Your Adapter +======================== For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: http://support.intel.com/support/network/adapter/pro100/21397.htm -For the latest Intel PRO/100 network driver for Linux, see: +For the latest Intel network drivers for Linux, refer to the following +website. In the search field, enter your adapter name or type, or use the +networking link on the left to search for your adapter: http://downloadfinder.intel.com/scripts-df/support_intel.asp +Driver Configuration Parameters +=============================== + +The default value for each parameter is generally the recommended setting, +unless otherwise noted. + +Rx Descriptors: Number of receive descriptors. A receive descriptor is a data + structure that describes a receive buffer and its attributes to the network + controller. The data in the descriptor is used by the controller to write + data from the controller to host memory. In the 3.0.x driver the valid + range for this parameter is 64-256. The default value is 64. This parameter + can be changed using the command + + ethtool -G eth? rx n, where n is the number of desired rx descriptors. + +Tx Descriptors: Number of transmit descriptors. A transmit descriptor is a + data structure that describes a transmit buffer and its attributes to the + network controller. The data in the descriptor is used by the controller to + read data from the host memory to the controller. In the 3.0.x driver the + valid range for this parameter is 64-256. The default value is 64. This + parameter can be changed using the command + + ethtool -G eth? tx n, where n is the number of desired tx descriptors. + +Speed/Duplex: The driver auto-negotiates the link speed and duplex settings by + default. Ethtool can be used as follows to force speed/duplex. + + ethtool -s eth? autoneg off speed {10|100} duplex {full|half} + + NOTE: setting the speed/duplex to incorrect values will cause the link to + fail. + +Event Log Message Level: The driver uses the message level flag to log events + to syslog. The message level can be set at driver load time. It can also be + set using the command + + ethtool -s eth? msglvl n + +Additional Configurations +========================= + + Configuring the Driver on Different Distributions + ------------------------------------------------- + + Configuring a network driver to load properly when the system is started is + distribution dependent. Typically, the configuration process involves adding + an alias line to /etc/modules.conf as well as editing other system startup + scripts and/or configuration files. Many popular Linux distributions ship + with tools to make these changes for you. To learn the proper way to + configure a network device for your system, refer to your distribution + documentation. If during this process you are asked for the driver or module + name, the name for the Linux Base Driver for the Intel PRO/100 Family of + Adapters is e100. + + As an example, if you install the e100 driver for two PRO/100 adapters + (eth0 and eth1), add the following to modules.conf: + + alias eth0 e100 + alias eth1 e100 + + Viewing Link Messages + --------------------- + In order to see link messages and other Intel driver information on your + console, you must set the dmesg level up to six. This can be done by + entering the following on the command line before loading the e100 driver: + + dmesg -n 8 + + If you wish to see all messages issued by the driver, including debug + messages, set the dmesg level to eight. + + NOTE: This setting is not saved across reboots. + + Ethtool + ------- + + The driver utilizes the ethtool interface for driver configuration and + diagnostics, as well as displaying statistical information. Ethtool + version 1.6 or later is required for this functionality. + + The latest release of ethtool can be found at: + http://sf.net/projects/gkernel. + + After ethtool is installed, ethtool-copy.h must be copied and renamed to + ethtool.h in your kernel source tree at /include/linux. + Backup the original ethtool.h as needed before copying. The driver then + must be recompiled in order to take advantage of the latest ethtool + features. + + NOTE: This driver uses mii support from the kernel. As a result, when + there is no link, ethtool will report speed/duplex to be 10/half. + + NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support + for a more complete ethtool feature set can be enabled by upgrading + ethtool to ethtool-1.8.1. + + Enabling Wake on LAN* (WoL) + --------------------------- + WoL is provided through the Ethtool* utility. Ethtool is included with Red + Hat* 8.0. For other Linux distributions, download and install Ethtool from + the following website: http://sourceforge.net/projects/gkernel. + + For instructions on enabling WoL with Ethtool, refer to the Ethtool man + page. + + WoL will be enabled on the system during the next shut down or reboot. For + this driver version, in order to enable WoL, the e100 driver must be + loaded when shutting down or rebooting the system. + + NAPI + ---- + + NAPI (Rx polling mode) is supported in the e100 driver. NAPI is enabled + or disabled based on the configuration of the kernel. + + See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI. Support ======= diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt index 9b2329f99..794c92542 100644 --- a/Documentation/networking/e1000.txt +++ b/Documentation/networking/e1000.txt @@ -1,14 +1,14 @@ Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters =============================================================== -January 8, 2003 +September 13, 2004 Contents ======== - In This Release -- Supported Adapters +- Identifying Your Adapter - Command Line Parameters - Speed and Duplex Configuration - Additional Configurations @@ -20,63 +20,29 @@ In This Release =============== This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family -of Adapters, version 5.0.x. This driver includes support for -Itanium(TM)-based systems. +of Adapters, version 5.x.x. This driver includes support for Itanium(TM)2 +and EM64T systems. +For questions related to hardware requirements, refer to the documentation +supplied with your Intel PRO/1000 adapter. All hardware requirements listed +apply to use with Linux. Native VLANs are now available with supported kernels. - -Supported Adapters -================== - -The following Intel network adapters are compatible with the drivers in this -release: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - - 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, 717037-xxx - - 82543 PRO/1000 F Server Adapter 738640-xxx, A38888-xxx - - 82543 PRO/1000 T Server Adapter A19845-xxx, A33948-xxx - - 82544 PRO/1000 XT Server Adapter A51580-xxx - - 82544 PRO/1000 XF Server Adapter A50484-xxx - - 82544 PRO/1000 T Desktop Adapter A62947-xxx - - 82540 PRO/1000 MT Desktop Adapter A78408-xxx - 82541 C91016-xxx - - 82545 PRO/1000 MT Server Adapter A92165-xxx - - 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx - - 82545 PRO/1000 MF Server Adapter A91622-xxx - - 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx - - 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx - - - -To verify your Intel adapter is supported, find the board ID number on the -adapter. Look for a label that has a barcode and a number in the format -A12345-001. Match this to the list of numbers above. +Identifying Your Adapter +======================== For more information on how to identify your adapter, go to the Adapter & Driver ID Guide at: http://support.intel.com/support/network/adapter/pro100/21397.htm -For the latest Intel network drivers for Linux, refer to the following +For the latest Intel network drivers for Linux, refer to the following +website. In the search field, enter your adapter name or type, or use the +networking link on the left to search for your adapter: http://downloadfinder.intel.com/scripts-df/support_intel.asp - Command Line Parameters ======================= @@ -92,27 +58,39 @@ For example, with two PRO/1000 PCI adapters, entering: insmod e1000 TxDescriptors=80,128 -loads the e1000 driver with 80 TX resources for the first adapter and 128 TX -resources for the second adapter. +loads the e1000 driver with 80 TX descriptors for the first adapter and 128 TX +descriptors for the second adapter. The default value for each parameter is generally the recommended setting, -unless otherwise noted. +unless otherwise noted. Also, if the driver is statically built into the +kernel, the driver is loaded with the default values for all the parameters. +Ethtool can be used to change some of the parameters at runtime. + + NOTES: For more information about the AutoNeg, Duplex, and Speed + parameters, see the "Speed and Duplex Configuration" section in + this document. -For more information about the AutoNeg, Duplex, and Speed parameters, see the -"Speed and Duplex Configuration" section in this document. + For more information about the InterruptThrottleRate, RxIntDelay, + TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay parameters, see the + application note at: + http://www.intel.com/design/network/applnots/ap450.htm + A descriptor describes a data buffer and attributes related to the + data buffer. This information is accessed by the hardware. AutoNeg (adapters using copper connections only) Valid Range: 0x01-0x0F, 0x20-0x2F Default Value: 0x2F This parameter is a bit mask that specifies which speed and duplex settings the board advertises. When this parameter is used, the Speed and - Duplex parameters must not be specified. + Duplex parameters must not be specified. + NOTE: Refer to the Speed and Duplex section of this readme for more + information on the AutoNeg parameter. Duplex (adapters using copper connections only) Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full) Default Value: 0 - Defines the direction in which data is allowed to flow. Can by either one + Defines the direction in which data is allowed to flow. Can be either one or two-directional. If both Duplex and the link partner are set to auto- negotiate, the board auto-detects the correct duplex. If the link partner is forced (either full or half), Duplex defaults to half-duplex. @@ -125,22 +103,46 @@ Default: Read flow control settings from the EEPROM InterruptThrottleRate Valid Range: 100-100000 (0=off, 1=dynamic) -Default Value: 1 +Default Value: 8000 This value represents the maximum number of interrupts per second the controller generates. InterruptThrottleRate is another setting used in interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust InterruptThrottleRate based on the current traffic load. +Un-supported Adapters: InterruptThrottleRate is NOT supported by 82542, 82543 + or 82544-based adapters. NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and RxAbsIntDelay parameters. In other words, minimizing the receive and/or transmit absolute delays does not force the controller to generate more interrupts than what the Interrupt Throttle Rate allows. + CAUTION: If you are using the Intel PRO/1000 CT Network Connection + (controller 82547), setting InterruptThrottleRate to a value + greater than 75,000, may hang (stop transmitting) adapters under + certain network conditions. If this occurs a NETDEV WATCHDOG + message is logged in the system event log. In addition, the + controller is automatically reset, restoring the network + connection. To eliminate the potential for the hang, ensure + that InterruptThrottleRate is set no greater than 75,000 and is + not set to 0. + NOTE: When e1000 is loaded with default settings and multiple adapters are + in use simultaneously, the CPU utilization may increase non-linearly. + In order to limit the CPU utilization without impacting the overall + throughput, we recommend that you load the driver as follows: + + insmod e1000.o InterruptThrottleRate=3000,3000,3000 + + This sets the InterruptThrottleRate to 3000 interrupts/sec for the + first, second, and third instances of the driver. The range of 2000 to + 3000 interrupts per second works on a majority of systems and is a + good starting point, but the optimal value will be platform-specific. + If CPU utilization is not a concern, use RX_POLLING (NAPI) and default + driver settings. RxDescriptors Valid Range: 80-256 for 82542 and 82543-based adapters - 80-4096 for 82540, 82544, 82545, and 82546-based adapters -Default Value: 80 + 80-4096 for all other supported adapters +Default Value: 256 This value is the number of receive descriptors allocated by the driver. Increasing this value allows the driver to buffer more incoming packets. Each descriptor is 16 bytes. A receive buffer is also allocated for each @@ -149,6 +151,9 @@ Default Value: 80 NOTE: MTU designates the frame size. It only needs to be set for Jumbo Frames. + NOTE: Depending on the available system resources, the request for a + higher number of receive descriptors may be denied. In this case, + use a lower number. RxIntDelay Valid Range: 0-65535 (0=off) @@ -168,11 +173,11 @@ Default Value: 0 restoring the network connection. To eliminate the potential for the hang ensure that RxIntDelay is set to 0. -RxAbsIntDelay (82540, 82545, and 82546-based adapters only) +RxAbsIntDelay (82540, 82545 and later adapters only) Valid Range: 0-65535 (0=off) Default Value: 128 This value, in units of 1.024 microseconds, limits the delay in which a - transmit interrupt is generated. Useful only if RxIntDelay is non-zero, + receive interrupt is generated. Useful only if RxIntDelay is non-zero, this value ensures that an interrupt is generated after the initial packet is received within the set amount of time. Proper tuning, along with RxIntDelay, may improve traffic throughput in specific network @@ -188,12 +193,16 @@ Default Value: 0 (auto-negotiate at all supported speeds) TxDescriptors Valid Range: 80-256 for 82542 and 82543-based adapters - 80-4096 for 82540, 82544, 82545, and 82546-based adapters + 80-4096 for all other supported adapters Default Value: 256 This value is the number of transmit descriptors allocated by the driver. Increasing this value allows the driver to queue more transmits. Each descriptor is 16 bytes. + NOTE: Depending on the available system resources, the request for a + higher number of transmit descriptors may be denied. In this case, + use a lower number. + TxIntDelay Valid Range: 0-65535 (0=off) Default Value: 64 @@ -203,7 +212,7 @@ Default Value: 64 system is reporting dropped transmits, this value may be set too high causing the driver to run out of available transmit descriptors. -TxAbsIntDelay (82540, 82545, and 82546-based adapters only) +TxAbsIntDelay (82540, 82545 and later adapters only) Valid Range: 0-65535 (0=off) Default Value: 64 This value, in units of 1.024 microseconds, limits the delay in which a @@ -219,7 +228,6 @@ Default Value: 1 A value of '1' indicates that the driver should enable IP checksum offload for received packets (both UDP and TCP) to the adapter hardware. - Speed and Duplex Configuration ============================== @@ -251,6 +259,10 @@ Bit 7 6 5 4 3 2 1 0 Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10 Duplex Full Full Half Full Half +For example to limit the negotiated speed/duplex on the interface to 10 Mbps +Half or Full duplex, set AutoNeg to 0x02: + insmod e1000 AutoNeg=0x02 + Note that setting AutoNeg does not guarantee that the board will link at the highest specified speed or duplex mode, but the board will link at the highest possible speed/duplex of the link partner IF the link partner is also @@ -261,6 +273,38 @@ adapter MUST be forced to the same speed/duplex. Additional Configurations ========================= + Configuring the Driver on Different Distributions + ------------------------------------------------- + + Configuring a network driver to load properly when the system is started is + distribution dependent. Typically, the configuration process involves adding + an alias line to /etc/modules.conf as well as editing other system startup + scripts and/or configuration files. Many popular Linux distributions ship + with tools to make these changes for you. To learn the proper way to + configure a network device for your system, refer to your distribution + documentation. If during this process you are asked for the driver or module + name, the name for the Linux Base Driver for the Intel PRO/1000 Family of + Adapters is e1000. + + As an example, if you install the e1000 driver for two PRO/1000 adapters + (eth0 and eth1) and set the speed and duplex to 10full and 100half, add the + following to modules.conf: + + alias eth0 e1000 + alias eth1 e1000 + options e1000 Speed=10,100 Duplex=2,1 + + Viewing Link Messages + --------------------- + + Link messages will not be displayed to the console if the distribution is + restricting system messages. In order to see network driver link messages on + your console, set dmesg to eight by entering the following: + + dmesg -n 8 + + NOTE: This setting is not saved across reboots. + Jumbo Frames ------------ @@ -278,6 +322,51 @@ Additional Configurations 10 or 100 Mbps may result in poor performance or loss of link. + NOTE: MTU designates the frame size. To enable Jumbo Frames, increase the + MTU size on the interface beyond 1500. + + Ethtool + ------- + + The driver utilizes the ethtool interface for driver configuration and + diagnostics, as well as displaying statistical information. Ethtool + version 1.6 or later is required for this functionality. + + The latest release of ethtool can be found from + http://sf.net/projects/gkernel. After ethtool is installed, + ethtool-copy.h must be copied and renamed to ethtool.h in your kernel + source tree at /include/linux. Backup the original + ethtool.h as needed before copying. The driver then must be recompiled + in order to take advantage of the latest ethtool features. + + NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support + for a more complete ethtool feature set can be enabled by upgrading + ethtool to ethtool-1.8.1. + + Enabling Wake on LAN* (WoL) + --------------------------- + + WoL is configured through the Ethtool* utility. Ethtool is included with + all versions of Red Hat after Red Hat 7.2. For other Linux distributions, + download and install Ethtool from the following website: + http://sourceforge.net/projects/gkernel. + + For instructions on enabling WoL with Ethtool, refer to the website listed + above. + + WoL will be enabled on the system during the next shut down or reboot. + For this driver version, in order to enable WoL, the e1000 driver must be + loaded when shutting down or rebooting the system. + + NAPI + ---- + + NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled + or disabled based on the configuration of the kernel. + + See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI. + + Known Issues ============ @@ -285,9 +374,9 @@ Known Issues ------------------------------- Memory allocation failures have been observed on Linux systems with 64 MB - of RAM or less that are running Jumbo Frames. If you are using Jumbo - Frames, your system may require more than the advertised minimum - requirement of 64 MB of system memory. + of RAM or less that are running Jumbo Frames. If you are using Jumbo Frames, + your system may require more than the advertised minimum requirement of 64 MB + of system memory. Support diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 10304b436..a2c893a74 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -355,6 +355,12 @@ tcp_default_win_scale - INTEGER conections. Default: 7 +tcp_tso_win_divisor - INTEGER + This allows control over what percentage of the congestion window + can be consumed by a single TSO frame. + The setting of this parameter is a choice between burstiness and + building larger TSO frames. + Default: 8 tcp_frto - BOOLEAN Enables F-RTO, an enhanced recovery algorithm for TCP retransmission @@ -837,6 +843,11 @@ bridge-nf-call-iptables - BOOLEAN 0 : disable this. Default: 1 +bridge-nf-call-ip6tables - BOOLEAN + 1 : pass bridged IPv6 traffic to ip6tables' chains. + 0 : disable this. + Default: 1 + bridge-nf-filter-vlan-tagged - BOOLEAN 1 : pass bridged vlan-tagged ARP/IP traffic to arptables/iptables. 0 : disable this. diff --git a/Documentation/networking/ixgb.txt b/Documentation/networking/ixgb.txt index 993090c41..c62d588ed 100644 --- a/Documentation/networking/ixgb.txt +++ b/Documentation/networking/ixgb.txt @@ -1,14 +1,14 @@ Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters ================================================================ -January 06, 2003 +September 13, 2004 Contents ======== - In This Release -- Supported Adapters +- Identifying Your Adapter - Command Line Parameters - Improving Performance - Support @@ -18,36 +18,23 @@ In This Release =============== This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family -of Adapters, version 1.0.x. This driver is intended for 2.4.x kernels; it is -known to build properly on 2.4.x kernels through 2.4.18. Intel focused -testing on Intel architectures running kernels 2.4.18. This driver includes -support for Itanium(TM)-based systems. +of Adapters, version 1.0.x. This driver includes support for Itanium(TM)2 and +EM64T systems. For questions related to hardware requirements, refer to the documentation supplied with your Intel PRO/10GbE adapter. All hardware requirements listed apply to use with Linux. - -Supported Adapters -================== - -The following Intel network adapters are compatible with the drivers in this -release: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - - 82597EX Intel(R) PRO/10GbE LR Server Adapter A82505-xxx - +Identifying Your Adapter +======================== To verify your Intel adapter is supported, find the board ID number on the adapter. Look for a label that has a barcode and a number in the format -A12345-001. Match this to the list of numbers above. +A12345-001. -For more information on how to identify your adapter, go to the Adapter & -Driver ID Guide at: +Use the above information and the Adapter & Driver ID Guide at: - http://support.intel.com/support/network/adapter/pro100/21397.htm + http://support.intel.com/support/network/adapter/pro100/21397.htm For the latest Intel network drivers for Linux, go to: @@ -72,8 +59,9 @@ loads the ixgb driver with 80 TX resources for the first adapter and 128 TX resources for the second adapter. The default value for each parameter is generally the recommended setting, -unless otherwise noted. - +unless otherwise noted. Also, if the driver is statically built into the +kernel, the driver is loaded with the default values for all the parameters. +Ethtool can be used to change some of the parameters at runtime. FlowControl Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx) @@ -125,7 +113,6 @@ Default Value: 1 offload for transmitted packets (both UDP and TCP) to the adapter hardware. - Improving Performance ===================== diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 8c456edb6..1509f3aff 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -43,8 +43,21 @@ dev->get_stats: dev->hard_start_xmit: Synchronization: dev->xmit_lock spinlock. + When the driver sets NETIF_F_LLTX in dev->features this will be + called without holding xmit_lock. In this case the driver + has to lock by itself when needed. It is recommended to use a try lock + for this and return -1 when the spin lock fails. + The locking there should also properly protect against + set_multicast_list Context: BHs disabled Notes: netif_queue_stopped() is guaranteed false + Return codes: + o NETDEV_TX_OK everything ok. + o NETDEV_TX_BUSY Cannot transmit packet, try later + Usually a bug, means queue start/stop flow control is broken in + the driver. Note: the driver must NOT put the skb in its DMA ring. + o NETDEV_TX_LOCKED Locking failed, please retry quickly. + Only valid when NETIF_F_LLTX is set. dev->tx_timeout: Synchronization: dev->xmit_lock spinlock. diff --git a/Documentation/nmi_watchdog.txt b/Documentation/nmi_watchdog.txt index 6cad46e8a..c025a4561 100644 --- a/Documentation/nmi_watchdog.txt +++ b/Documentation/nmi_watchdog.txt @@ -54,6 +54,20 @@ then the system has crashed so hard (eg. hardware-wise) that either it cannot even accept NMI interrupts, or the crash has made the kernel unable to print messages. +Be aware that when using local APIC, the frequency of NMI interrupts +it generates, depends on the system load. The local APIC NMI watchdog, +lacking a better source, uses the "cycles unhalted" event. As you may +guess it doesn't tick when the CPU is in the halted state (which happens +when the system is idle), but if your system locks up on anything but the +"hlt" processor instruction, the watchdog will trigger very soon as the +"cycles unhalted" event will happen every clock tick. If it locks up on +"hlt", then you are out of luck -- the event will not happen at all and the +watchdog won't trigger. This is a shortcoming of the local APIC watchdog +-- unfortunately there is no "clock ticks" event that would work all the +time. The I/O APIC watchdog is driven externally and has no such shortcoming. +But its NMI frequency is much higher, resulting in a more significant hit +to the overall system performance. + NOTE: starting with 2.4.2-ac18 the NMI-oopser is disabled by default, you have to enable it with a boot time parameter. Prior to 2.4.2-ac18 the NMI-oopser is enabled unconditionally on x86 SMP boxes. diff --git a/Documentation/parisc/registers b/Documentation/parisc/registers index 08b9f558d..dd3caddd1 100644 --- a/Documentation/parisc/registers +++ b/Documentation/parisc/registers @@ -35,8 +35,8 @@ CR31 (TR 7) Temporary register, used in various places SR0 temporary space register SR4-SR7 set to 0 SR1 temporary space register -SR2 unused -SR3 used for userspace accesses (current process)* +SR2 kernel should not clobber this +SR3 used for userspace accesses (current process) Space Registers (user mode) @@ -78,13 +78,8 @@ Shadow Registers used by interruption handler code TOC enable bit 1 ========================================================================= -Info from John Marvin: - -From: "John Marvin" -To: randolf@tausq.org -Subject: Re: parisc asm questions - -[...] +Register usage notes, originally from John Marvin, with some additional +notes from Randolph Chung. For the general registers: @@ -111,9 +106,10 @@ that you should be aware of: don't care about the values that were passed in anymore. r28,r29: are ret0 and ret1. They are what you pass return values - in. r28 is the primary return. I'm not sure I remember - under what circumstances stuff is returned in r29 (millicode - perhaps). + in. r28 is the primary return. When returning small structures + r29 may also be used to pass data back to the caller. + + r30: stack pointer r31: the ble instruction puts the return pointer in here. @@ -123,6 +119,3 @@ r3-r18,r27,r30 need to be saved and restored. r3-r18 are just used to make references to global variables easier. r30 is the stack pointer. -John - - diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 411947638..b0676d114 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -25,6 +25,7 @@ on (either the old or the new way), it needs to perform the following steps: Discover resources (addresses and IRQ numbers) provided by the device Allocate these resources Communicate with the device + Disable the device Most of these topics are covered by the following sections, for the rest look at , it's hopefully well commented. @@ -140,30 +141,28 @@ for PCI devices manually using the following constructs: Searching by vendor and device ID: struct pci_dev *dev = NULL; - while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev)) + while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev)) configure_device(dev); Searching by class ID (iterate in a similar way): - pci_find_class(CLASS_ID, dev) + pci_get_class(CLASS_ID, dev) Searching by both vendor/device and subsystem vendor/device ID: - pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev). + pci_get_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev). You can use the constant PCI_ANY_ID as a wildcard replacement for VENDOR_ID or DEVICE_ID. This allows searching for any device from a specific vendor, for example. -Note that these functions are not hotplug-safe. Their hotplug-safe -replacements are pci_get_device(), pci_get_class() and pci_get_subsys(). -They increment the reference count on the pci_dev that they return. -You must eventually (possibly at module unload) decrement the reference -count on these devices by calling pci_dev_put(). + These functions are hotplug-safe. They increment the reference count on +the pci_dev that they return. You must eventually (possibly at module unload) +decrement the reference count on these devices by calling pci_dev_put(). -3. Enabling devices -~~~~~~~~~~~~~~~~~~~ +3. Enabling and disabling devices +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Before you do anything with the device you've found, you need to enable it by calling pci_enable_device() which enables I/O and memory regions of the device, allocates an IRQ if necessary, assigns missing resources if @@ -180,6 +179,12 @@ and also ensures that the cache line size register is set correctly. Make sure to check the return value of pci_set_mwi(), not all architectures may support Memory-Write-Invalidate. + If your driver decides to stop using the device (e.g., there was an +error while setting it up or the driver module is being unloaded), it +should call pci_disable_device() to deallocate any IRQ resources, disable +PCI bus-mastering, etc. You should not do anything with the device after +calling pci_disable_device(). + 4. How to access PCI config space ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can use pci_(read|write)_config_(byte|word|dword) to access the config @@ -268,11 +273,12 @@ pci_present() of PCI subsystem when trying to talk to it. devices just return NULL. pcibios_(read|write)_* Superseded by their pci_(read|write)_* counterparts. -pcibios_find_* Superseded by their pci_find_* counterparts. -pci_for_each_dev() Superseded by pci_find_device() +pcibios_find_* Superseded by their pci_get_* counterparts. +pci_for_each_dev() Superseded by pci_get_device() pci_for_each_dev_reverse() Superseded by pci_find_device_reverse() pci_for_each_bus() Superseded by pci_find_next_bus() pci_find_device() Superseded by pci_get_device() pci_find_subsys() Superseded by pci_get_subsys() -pcibios_find_class() Superseded by pci_find_class() +pcibios_find_class() Superseded by pci_get_class() +pci_find_class() Superseded by pci_get_class() pci_(read|write)_*_nodev() Superseded by pci_bus_(read|write)_*() diff --git a/Documentation/pm.txt b/Documentation/pm.txt index 483d2a5d1..008ac7d2d 100644 --- a/Documentation/pm.txt +++ b/Documentation/pm.txt @@ -36,8 +36,8 @@ system the associated daemon will exit gracefully. apmd: http://worldvisions.ca/~apenwarr/apmd/ acpid: http://acpid.sf.net/ -Driver Interface ----------------- +Driver Interface -- OBSOLETE, DO NOT USE! +----------------************************* If you are writing a new driver or maintaining an old driver, it should include power management support. Without power management support, a single driver may prevent a system with power management @@ -262,8 +262,8 @@ Q: Who do I contact for additional information about ACPI Development mailing list: acpi-devel@lists.sourceforge.net -System Interface ----------------- +System Interface -- OBSOLETE, DO NOT USE! +----------------************************* If you are providing new power management support to Linux (ie. adding support for something like APM or ACPI), you should communicate with drivers through the existing generic power diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index 972c7c74b..c85428e7a 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -5,6 +5,7 @@ PCI Power Management An overview of the concepts and the related functions in the Linux kernel Patrick Mochel +(and others) --------------------------------------------------------------------------- @@ -31,10 +32,15 @@ The PCI PM spec defines 4 operating states for devices (D0 - D3) and for buses the higher the number, the longer the latency is for the device to return to an operational state (D0). +There are actually two D3 states. When someone talks about D3, they usually +mean D3hot, which corresponds to an ACPI D2 state (power is reduced, the +device may lose some context). But they may also mean D3cold, which is an +ACPI D3 state (power is fully off, all state was discarded); or both. + Bus power management is not covered in this version of this document. -Note that all PCI devices support D0 and D3 by default, regardless of whether or -not they implement any of the PCI PM spec. +Note that all PCI devices support D0 and D3cold by default, regardless of +whether or not they implement any of the PCI PM spec. The possible state transitions that a device can undergo are: @@ -204,15 +210,16 @@ if (dev->driver && dev->driver->suspend) dev->driver->suspend(dev,state); A driver uses this function to actually transition the device into a low power -state. This may include disabling I/O, memory and bus-mastering, as well as -physically transitioning the device to a lower power state. +state. This should include disabling I/O, IRQs, and bus-mastering, as well as +physically transitioning the device to a lower power state; it may also include +calls to pci_enable_wake(). Bus mastering may be disabled by doing: pci_disable_device(dev); For devices that support the PCI PM Spec, this may be used to set the device's -power state: +power state to match the suspend() parameter: pci_set_power_state(dev,state); @@ -223,7 +230,7 @@ The driver should be sure to track the current state of the device, as it may obviate the need for some operations. The driver should update the current_state field in its pci_dev structure in -this function. +this function, except for PM-capable devices when pci_set_power_state is used. resume ------ @@ -237,16 +244,28 @@ The resume callback may be called from any power state, and is always meant to transition the device to the D0 state. The driver is responsible for reenabling any features of the device that had -been disabled during previous suspend calls and restoring all state that was -saved in previous save_state calls. +been disabled during previous suspend calls, such as IRQs and bus mastering, +as well as calling pci_restore_state(). + +If the device is currently in D3, it may need to be reinitialized in resume(). + + * Some types of devices, like bus controllers, will preserve context in D3hot + (using Vcc power). Their drivers will often want to avoid re-initializing + them after re-entering D0 (perhaps to avoid resetting downstream devices). + + * Other kinds of devices in D3hot will discard device context as part of a + soft reset when re-entering the D0 state. + + * Devices resuming from D3cold always go through a power-on reset. Some + device context can also be preserved using Vaux power. + + * Some systems hide D3cold resume paths from drivers. For example, on PCs + the resume path for suspend-to-disk often runs BIOS powerup code, which + will sometimes re-initialize the device. -If the device is currently in D3, it must be completely reinitialized, as it -must be assumed that the device has lost all of its context (even that of its -PCI config space). For almost all current drivers, this means that the -initialization code that the driver does at boot must be separated out and -called again from the resume callback. Note that some values for the device may -not have to be probed for this time around if they are saved before entering the -low power state. +To handle resets during D3 to D0 transitions, it may be convenient to share +device initialization code between probe() and resume(). Device parameters +can also be saved before the driver suspends into D3, avoiding re-probe. If the device supports the PCI PM Spec, it can use this to physically transition the device to D0: @@ -263,7 +282,7 @@ The driver should take note of the state that it is resuming from in order to ensure correct (and speedy) operation. The driver should update the current_state field in its pci_dev structure in -this function. +this function, except for PM-capable devices when pci_set_power_state is used. enable_wake diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 5cdab4c55..3b7172df0 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -15,28 +15,16 @@ From kernel/suspend.c: * If you change kernel command line between suspend and resume... * ...prepare for nasty fsck or worse. * - * (*) pm interface support is needed to make it safe. + * (*) suspend/resume support is needed to make it safe. You need to append resume=/dev/your_swap_partition to kernel command -line. Then you suspend by echo 4 > /proc/acpi/sleep. +line. Then you suspend by -Pavel's unreliable guide to swsusp mess -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +echo shutdown > /sys/power/disk; echo disk > /sys/power/state -There are currently two versions of swap suspend in the kernel, the old -"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's" -version in kernel/power/pmdisk.c. They provide the same functionality; -the old version looks ugly but was tested, while the new version looks -nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep -calls the old version, echo disk > /sys/power/state calls the new one. +. If you feel ACPI works pretty well on your system, you might try -[In the future, when the new version is stable enough, two things can -happen: - -* the new version is moved into swsusp.c, and swsusp is renamed to swap - suspend (Pavel prefers this) - -* pmdisk is kept as is and swsusp.c is removed from the kernel] +echo platform > /sys/power/disk; echo disk > /sys/power/state @@ -52,51 +40,24 @@ saves the state of the machine to a filesystem or to a partition and switches to standby mode. Later resuming the machine the saved state is loaded back to ram and the machine can continue its work. It has two real benefits. First we save ourselves the time machine goes down and later boots up, energy costs -real high when running from batteries. The other gain is that we don't have to +are real high when running from batteries. The other gain is that we don't have to interrupt our programs so processes that are calculating something for a long time shouldn't need to be written interruptible. -Using the code - -You have two ways to use this code. The first one is is with a patched -SysVinit (my patch is against 2.76 and available at my home page). You -might call 'swsusp' or 'shutdown -z
@@ -956,7 +941,7 @@ After allocating a card instance via snd_card_new() (with NULL on the 4th arg), call - snd_magic_kcalloc(). + kcalloc(). @@ -965,13 +950,10 @@ mychip_t *chip; card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); ..... - chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL); + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); ]]> - - Once when the record is allocated via snd_magic stuff, you - can use magic-cast for the void pointer. @@ -1002,21 +984,6 @@ - - Also, you need to define a magic-value for mychip_t. - - - - - - - (the detail will be described in the - - next subsection). - - Next, initialize the fields, and register this chip record as a low-level device with a specified @@ -1045,8 +1012,7 @@ device_data, - return -ENXIO); + mychip_t *chip = device->device_data; return snd_mychip_free(chip); } ]]> @@ -1056,126 +1022,6 @@ where snd_mychip_free() is the real destructor.
- -
- Not a magic but a logic - - Now, you might have a question: What is the advantage of the - second method? Obviously, it looks far more complicated. - - As I wrote many times, the second method allows a - magic-cast for mychip_t. If you - have a void pointer (such as - pcm->private_data), the pointer type - is unknown at the compile time, and you cannot know even if a - wrong pointer type is passed. The compiler would accept - it. The magic-cast checks the pointer type at the runtime (and - whether it's a null pointer, too). Hence, the cast will be - much safer and good for debugging. - - - - As you have already seen, allocation with a magic-header can - be done via snd_magic_kmalloc() or - snd_magic_kcalloc(). - - - - - - - - The difference of these two functions is whether the area is - zero-cleared (kcalloc) or not - (kmalloc). - - - - The first argument of the allocator is the type of the - record. The magic-constant has to be defined for this type - beforehand. In this case, we'll need to define - mychip_t_magic, for example, as already - seen, - - - - - - - - The value is arbitrary but should be unique. - This is usually defined in - <include/sndmagic.h> or - <include/amagic.h> for alsa-driver tree, - but you may define it locally in the code at the early - development stage, since changing - sndmagic.h will lead to the recompilation - of the whole driver codes. - - - - The second argument is the extra-data length. It is usually - zero. The third argument is the flags to be passed to kernel - memory allocator, GFP_XXX. Normally, - GFP_KERNEL is passed. - - - - For casting a pointer, use - snd_magic_cast() macro: - - - - - - - - where source_pointer is the pointer to - be casted (e.g. pcm->private_data), and - action is the action to do if the cast - fails (e.g. return -EINVAL). - - - - For releasing the magic-allocated data, you need to call - snd_magic_kfree() function instead of - kfree(). - - - - - - - - - - If you call kfree() for the - magic-allocated value, it will lead to memory leaks. - When the ALSA drivers are compiled with - CONFIG_SND_DEBUG_MEMORY kernel config (or - configured with ), the - non-matching free will be checked and you'll see warning - messages. - - - - If you are 100% sure that your code is bug-free, you can - compile the driver without - CONFIG_SND_DEBUG_MEMORY kernel config, - so that the magic-allocator and the magic-cast will be - replaced to the normal kmalloc and cast. - -
@@ -1238,8 +1084,6 @@ struct pci_dev *pci; unsigned long port; - struct resource *res_port; - int irq; }; @@ -1248,16 +1092,13 @@ // disable hardware here if any // (not implemented in this document) - // release the i/o port - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } // release the irq if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); + // release the i/o ports + pci_release_regions(chip->pci); // release the data - snd_magic_kfree(chip); + kfree(chip); return 0; } @@ -1283,7 +1124,7 @@ return -ENXIO; } - chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL); + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -1293,18 +1134,16 @@ chip->irq = -1; // (1) PCI resource allocation - chip->port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 8, - "My Chip")) == NULL) { - snd_mychip_free(chip); - printk(KERN_ERR "cannot allocate the port\n"); - return -EBUSY; + if ((err = pci_request_regions(pci, "My Chip")) < 0) { + kfree(chip); + return err; } + chip->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_mychip_interrupt, SA_INTERRUPT|SA_SHIRQ, "My Chip", (void *)chip)) { + printk(KERN_ERR "cannot grab irq %d\n", pci->irq); snd_mychip_free(chip); - printk(KERN_ERR "cannot grab irq\n"); return -EBUSY; } chip->irq = pci->irq; @@ -1420,8 +1259,6 @@ snd_card_t *card; unsigned long port; - struct resource *res_port; - int irq; }; ]]> @@ -1436,7 +1273,7 @@ need to initialize this number as -1 before actual allocation, since irq 0 is valid. The port address and its resource pointer can be initialized as null by - snd_magic_kcalloc() automatically, so you + kcalloc() automatically, so you don't have to take care of resetting them. @@ -1446,14 +1283,11 @@ port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 8, - "My Chip")) == NULL) { - printk(KERN_ERR "cannot allocate the port 0x%lx\n", - chip->port); - snd_mychip_free(chip); - return -EBUSY; + if ((err = pci_request_regions(pci, "My Chip")) < 0) { + kfree(chip); + return err; } + chip->port = pci_resource_start(pci, 0); ]]> @@ -1477,8 +1311,8 @@ if (request_irq(pci->irq, snd_mychip_interrupt, SA_INTERRUPT|SA_SHIRQ, "My Chip", (void *)chip)) { - snd_mychip_free(chip); printk(KERN_ERR "cannot grab irq %d\n", pci->irq); + snd_mychip_free(chip); return -EBUSY; } chip->irq = pci->irq; @@ -1517,16 +1351,13 @@ static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return); + mychip_t *chip = dev_id; .... return IRQ_HANDLED; } ]]> - - Again the magic-cast is used here to get the correct pointer - from the second argument. @@ -1538,7 +1369,45 @@ For releasing the resources, check-and-release - method is a safer way. For the i/o port, do like this: + method is a safer way. For the interrupt, do like this: + + + +irq >= 0) + free_irq(chip->irq, (void *)chip); +]]> + + + + Since the irq number can start from 0, you should initialize + chip->irq with a negative value (e.g. -1), so that you can + check the validity of the irq number as above. + + + + When you requested I/O ports or memory regions via + pci_request_region() or + pci_request_regions() like this example, + release the resource(s) using the corresponding function, + pci_release_region() or + pci_release_regions(). + + + +pci); +]]> + + + + + + When you requested manually via request_region() + or request_mem_region, you can release it via + release_resource(). Suppose that you keep + the resource pointer returned from request_region() + in chip->res_port, the release procedure looks like below: @@ -1550,10 +1419,8 @@ ]]> - - - As you can see, the i/o resource pointer is also to be freed + As you can see, the resource pointer is also to be freed via kfree_nocheck() after release_resource() is called. You cannot use kfree() here, because on ALSA, @@ -1567,35 +1434,19 @@ - For releasing the interrupt, do like this: - - - -irq >= 0) - free_irq(chip->irq, (void *)chip); -]]> - - - And finally, release the chip-specific record. - The chip instance is freed via - snd_magic_kfree(). Please use this function - for the object allocated by - snd_magic_kmalloc(). If you free it with - kfree(), it won't work properly and will - result in the memory leak. Also, again, remember that you cannot + Again, remember that you cannot set __devexit prefix for this destructor. @@ -1628,8 +1479,7 @@ struct snd_mychip { .... unsigned long iobase_phys; - unsigned long iobase_virt; - struct resource *res_iobase; + void __iomem *iobase_virt; }; ]]> @@ -1640,15 +1490,13 @@ iobase_phys = pci_resource_start(pci, 0); - chip->iobase_virt = (unsigned long) - ioremap_nocache(chip->iobase_phys, 512); - if ((chip->res_port = request_mem_region(chip->iobase_phys, 512, - "My Chip")) == NULL) { - printk(KERN_ERR "cannot allocate the memory region\n"); - snd_mychip_free(chip); - return -EBUSY; + if ((err = pci_request_regions(pci, "My Chip")) < 0) { + kfree(chip); + return err; } + chip->iobase_phys = pci_resource_start(pci, 0); + chip->iobase_virt = ioremap_nocache(chip->iobase_phys, + pci_resource_len(pci, 0)); ]]> @@ -1662,11 +1510,9 @@ { .... if (chip->iobase_virt) - iounmap((void *)chip->iobase_virt); - if (chip->res_iobase) { - release_resource(chip->res_iobase); - kfree_nocheck(chip->res_iobase); - } + iounmap(chip->iobase_virt); + .... + pci_release_regions(chip->pci); .... } ]]> @@ -1857,9 +1703,6 @@ #include .... - #define chip_t mychip_t - .... - /* hardware definition */ static snd_pcm_hardware_t snd_mychip_playback_hw = { .info = (SNDRV_PCM_INFO_MMAP | @@ -2224,8 +2067,7 @@ private_data, return); + mychip_t *chip = snd_pcm_chip(pcm); // free your own data kfree(chip->my_private_pcm_data); // do what you like else... @@ -2653,8 +2495,11 @@ struct _snd_pcm_runtime { done in the open callback. - Since it's a void pointer, you should use magic-kmalloc and - magic-cast for such an object. + Don't mix this with pcm->private_data. + The pcm->private_data usually points the + chip instance assigned statically at the creation of PCM, while the + runtime->private_data points a dynamic + data created at the PCM open callback. @@ -2663,7 +2508,7 @@ struct _snd_pcm_runtime { { my_pcm_data_t *data; .... - data = snd_magic_kmalloc(my_pcm_data_t, 0, GFP_KERNEL); + data = kmalloc(sizeof(*data), GFP_KERNEL); substream->runtime->private_data = data; .... } @@ -2710,8 +2555,6 @@ struct _snd_pcm_runtime { - - - It's expanded with a magic-cast, so the cast-error is - automatically checked. You should define chip_t at - the beginning of the code, since this will be referred in many - places of pcm and control interfaces. + The macro reads substream->private_data, + which is a copy of pcm->private_data. + You can override the former if you need to assign different data + records per PCM substream. For example, cmi8330 driver assigns + different private_data for playback and capture directions, + because it uses two different codecs (SB- and AD-compatible) for + different directions.
@@ -2803,7 +2647,7 @@ struct _snd_pcm_runtime { static int snd_xxx_close(snd_pcm_substream_t *substream) { .... - snd_magic_kfree(substream->runtime->private_data); + kfree(substream->runtime->private_data); .... } ]]> @@ -2887,10 +2731,10 @@ struct _snd_pcm_runtime { Another note is that this callback is non-atomic (schedulable). This is important, because the - prepare callback + trigger callback is atomic (non-schedulable). That is, mutex or any - schedule-related functions are available only in - hw_params callback. + schedule-related functions are not available in + trigger callback. Please see the subsection Atomicity for details. @@ -2956,7 +2800,8 @@ struct _snd_pcm_runtime { - As mentioned above, this callback is atomic. + Note that this callback became non-atomic since the recent version. + You can use schedule-related fucntions safely in this callback now. @@ -3041,7 +2886,12 @@ struct _snd_pcm_runtime { - This callback is also atomic. + As mentioned, this callback is atomic. You cannot call + the function going to sleep. + The trigger callback should be as minimal as possible, + just really triggering the DMA. The other stuff should be + initialized hw_params and prepare callbacks properly + beforehand.
@@ -3176,7 +3026,7 @@ struct _snd_pcm_runtime { static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return); + mychip_t *chip = dev_id; spin_lock(&chip->lock); .... if (pcm_irq_invoked(chip)) { @@ -3220,7 +3070,7 @@ struct _snd_pcm_runtime { static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return); + mychip_t *chip = dev_id; spin_lock(&chip->lock); .... if (pcm_irq_invoked(chip)) { @@ -3287,7 +3137,7 @@ struct _snd_pcm_runtime { As already seen, some pcm callbacks are atomic and some are not. For example, hw_params callback is - non-atomic, while prepare callback is + non-atomic, while trigger callback is atomic. This means, the latter is called already in a spinlock held by the PCM middle layer. Please take this atomicity into account when you use a spinlock or a semaphore in the callbacks. @@ -3298,7 +3148,7 @@ struct _snd_pcm_runtime { schedule or go to sleep. The semaphore and mutex do sleep, and hence they cannot be used inside the atomic callbacks - (e.g. prepare callback). + (e.g. trigger callback). For taking a certain delay in such a callback, please use udelay() or mdelay(). @@ -3325,7 +3175,7 @@ struct _snd_pcm_runtime { static unsigned int rates[] = {4000, 10000, 22050, 44100}; static snd_pcm_hw_constraint_list_t constraints_rates = { - .count = sizeof(rates) / sizeof(rates[0]), + .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, }; @@ -3988,8 +3838,7 @@ struct _snd_pcm_runtime { static unsigned short snd_mychip_ac97_read(ac97_t *ac97, unsigned short reg) { - mychip_t *chip = snd_magic_cast(mychip_t, - ac97->private_data, return 0); + mychip_t *chip = ac97->private_data; .... // read a register value here from the codec return the_register_value; @@ -3998,26 +3847,26 @@ struct _snd_pcm_runtime { static void snd_mychip_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) { - mychip_t *chip = snd_magic_cast(mychip_t, - ac97->private_data, return 0); + mychip_t *chip = ac97->private_data; .... // write the given register value to the codec } static int snd_mychip_ac97(mychip_t *chip) { - ac97_bus_t bus, *pbus; - ac97_t ac97; + ac97_bus_t *bus; + ac97_template_t ac97; int err; + static ac97_bus_ops_t ops = { + .write = snd_mychip_ac97_write, + .read = snd_mychip_ac97_read, + }; - memset(&bus, 0, sizeof(bus)); - bus.write = snd_mychip_ac97_write; - bus.read = snd_mychip_ac97_read; - if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0) + if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - return snd_ac97_mixer(pbus, &ac97, &chip->ac97); + return snd_ac97_mixer(bus, &ac97, &chip->ac97); } ]]> @@ -4030,18 +3879,18 @@ struct _snd_pcm_runtime { Constructor For creating an ac97 instance, first call snd_ac97_bus - with ac97_bus_t record including callback functions. + with an ac97_bus_ops_t record with callback functions. @@ -4050,13 +3899,13 @@ struct _snd_pcm_runtime { - And then call snd_ac97_mixer() with an ac97_t + And then call snd_ac97_mixer() with an ac97_template_t record together with the bus pointer created above. private_data, return 0); + mychip_t *chip = ac97->private_data; .... return the_register_value; } @@ -4211,8 +4059,8 @@ struct _snd_pcm_runtime { Also, there is a function to change the sample rate (of a certain register such as - AC97_PCM_FRONT_DAC_RATE) when VRA is - supported by the codec: + AC97_PCM_FRONT_DAC_RATE) when VRA or + DRA is supported by the codec: snd_ac97_set_rate(). @@ -4241,7 +4089,7 @@ struct _snd_pcm_runtime { On some chip, the clock of the codec isn't 48000 but using a PCI clock (to save a quartz!). In this case, change the field - ac97->clock to the corresponding + bus->clock to the corresponding value. For example, intel8x0 and es1968 drivers have the auto-measurement function of the clock. @@ -4375,7 +4223,7 @@ struct _snd_pcm_runtime { private_data, ); + mpu = rmidi->private_data; ]]> @@ -4492,7 +4340,39 @@ struct _snd_pcm_runtime { - If this function returns successfully with 0, then create a + When the accessing to the hardware requires special method + instead of the standard I/O access, you can create opl3 instance + separately with snd_opl3_new(). + + + + + + + + + + Then set command, + private_data and + private_free for the private + access function, the private data and the destructor. + The l_port and r_port are not necessarily set. Only the + command must be set properly. You can retrieve the data + from opl3->private_data field. + + + + After creating the opl3 instance via snd_opl3_new(), + call snd_opl3_init() to initialize the chip to the + proper state. Note that snd_opl3_create() always + calls it internally. + + + + If the opl3 instance is created successfully, then create a hwdep device for this opl3. @@ -4546,16 +4426,15 @@ struct _snd_pcm_runtime { You can then pass any pointer value to the - private_data. Again, it should be a - magic-allocated record, so that the cast can be checked more - safely. If you assign a private data, you should define the + private_data. + If you assign a private data, you should define the destructor, too. The destructor function is set to private_free field. private_data = p; hw->private_free = mydata_free; ]]> @@ -4569,9 +4448,8 @@ struct _snd_pcm_runtime { private_data, return); - snd_magic_kfree(p); + mydata_t *p = hw->private_data; + kfree(p); } ]]> @@ -5097,8 +4975,7 @@ struct _snd_pcm_runtime { static void my_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) { - chip_t *cm = snd_magic_cast(mychip_t, - entry->private_data, return); + chip_t *chip = entry->private_data; snd_iprintf(buffer, "This is my chip!\n"); snd_iprintf(buffer, "Port = %ld\n", chip->port); @@ -5267,8 +5144,7 @@ struct _snd_pcm_runtime { static int mychip_suspend(snd_card_t *card, unsigned int state) { // (1) - mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, - return -ENXIO); + mychip_t *chip = card->pm_private_data; // (2) snd_pcm_suspend_all(chip->pcm); // (3) @@ -5310,8 +5186,7 @@ struct _snd_pcm_runtime { static void mychip_resume(mychip_t *chip) { // (1) - mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, - return -ENXIO); + mychip_t *chip = card->pm_private_data; // (2) pci_enable_device(chip->pci); // (3) @@ -5428,19 +5303,7 @@ struct _snd_pcm_runtime { The module parameters must be declared with the standard module_param()(), module_param_array()() and - MODULE_PARM_DESC() macros. The ALSA provides - an additional macro, MODULE_PARM_SYNTAX(), - for describing its syntax. The strings will be written to - /lib/modules/XXX/modules.generic_string - file. - - - - For convenience, the typical string arguments given to - MODULE_PARM_SYNTAX() are defined in - <sound/initval.h>, such as - SNDRV_ID_DESC or - SNDRV_ENABLED. + MODULE_PARM_DESC() macros. @@ -5454,13 +5317,10 @@ struct _snd_pcm_runtime { static int boot_devs; module_param_array(index, int, boot_devs, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); - MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); module_param_array(id, charp, boot_devs, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); - MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); module_param_array(enable, bool, boot_devs, 0444); MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); ]]> @@ -5479,9 +5339,8 @@ struct _snd_pcm_runtime { @@ -5636,14 +5495,14 @@ struct _snd_pcm_runtime { SND_TOPDIR=../.. endif - include $(TOPDIR)/toplevel.config - include $(TOPDIR)/Makefile.conf + include $(SND_TOPDIR)/toplevel.config + include $(SND_TOPDIR)/Makefile.conf snd-xyz-objs := xyz.o abc.o def.o obj-$(CONFIG_SND_XYZ) += snd-xyz.o - include $(TOPDIR)/Rules.make + include $(SND_TOPDIR)/Rules.make ]]> diff --git a/Documentation/sound/alsa/Joystick.txt b/Documentation/sound/alsa/Joystick.txt index dcc6c85e1..ccda41b10 100644 --- a/Documentation/sound/alsa/Joystick.txt +++ b/Documentation/sound/alsa/Joystick.txt @@ -49,17 +49,15 @@ The following PCI drivers support the joystick natively. cs46xx N/A N/A es1938 N/A N/A es1968 joystick 0 = disable (default), 1 = enable - intel8x0(*1)joystick 0 = disable (default), 1 = enable sonicvibes N/A N/A trident N/A N/A - via82xx(*2) joystick 0 = disable (default), 1 = enable + via82xx(*1) joystick 0 = disable (default), 1 = enable ymfpci joystick_port 0 = disable (default), 1 = auto-detect, - manual: 0x201, 0x202, 0x204, 0x205(*3) + manual: 0x201, 0x202, 0x204, 0x205(*2) --------------------------------------------------------------------------- - *1) not all chips support joystick - *2) VIA686A/B only - *3) With YMF744/754 chips, the port address can be chosen arbitrarily + *1) VIA686A/B only + *2) With YMF744/754 chips, the port address can be chosen arbitrarily The following drivers don't support gameport natively, but there are additional modules. Load the corresponding module to add the gameport diff --git a/Documentation/sound/oss/README.modules b/Documentation/sound/oss/README.modules index 0e6c92d61..e691d74e1 100644 --- a/Documentation/sound/oss/README.modules +++ b/Documentation/sound/oss/README.modules @@ -59,8 +59,9 @@ sound.o # The sound driver uart401.o # Used by sb, maybe other cards Whichever card you have, try feeding it the options that would be the -default if you were making the driver wired, not as modules. You can look -at the init_module() code for the card to see what args are expected. +default if you were making the driver wired, not as modules. You can +look at function referred to by module_init() for the card to see what +args are expected. Note that at present there is no way to configure the io, irq and other parameters for the modular drivers as one does for the wired drivers.. One diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 9a193fc86..351591769 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -23,7 +23,6 @@ show up in /proc/sys/kernel: - dentry-state - domainname - hostname -- htab-reclaim [ PPC only ] - hotplug - java-appletviewer [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ] @@ -54,7 +53,6 @@ show up in /proc/sys/kernel: - tainted - threads-max - version -- zero-paged [ PPC only ] ============================================================== @@ -133,8 +131,8 @@ domainname and hostname, i.e.: # echo "darkstar" > /proc/sys/kernel/hostname # echo "mydomain" > /proc/sys/kernel/domainname has the same effect as -# hostname "darkstar" > /proc/sys/kernel/hostname -# domainname "mydomain" > /proc/sys/kernel/domainname +# hostname "darkstar" +# domainname "mydomain" Note, however, that the classic darkstar.frop.org has the hostname "darkstar" and DNS (Internet Domain Name Server) @@ -145,14 +143,6 @@ see the hostname(1) man page. ============================================================== -htab-reclaim: (PPC only) - -Setting this to a non-zero value, the PowerPC htab -(see Documentation/powerpc/ppc_htab.txt) is pruned -each time the system hits the idle loop. - -============================================================== - hotplug: Path for the hotplug policy agent. @@ -322,11 +312,3 @@ can be ORed together: Set by modutils >= 2.4.9 and module-init-tools. 4 - Unsafe SMP processors: SMP with CPUs not designed for SMP. -============================================================== - -zero-paged: (PPC only) - -When enabled (non-zero), Linux-PPC will pre-zero pages in -the idle loop, possibly speeding up get_free_pages. Since -this only affects what the idle loop is doing, you should -enable this and see if anything changes. diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index b0349d8aa..2f1aae32a 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -31,7 +31,7 @@ Currently, these files are in /proc/sys/vm: dirty_ratio, dirty_background_ratio, dirty_expire_centisecs, dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode, -block_dump: +block_dump, swap_token_timeout: See Documentation/filesystems/proc.txt @@ -47,7 +47,7 @@ of free memory left when userspace requests more memory. When this flag is 1, the kernel pretends there is always enough memory until it actually runs out. -When this flag is 2, the kernel uses a "strict overcommit" +When this flag is 2, the kernel uses a "never overcommit" policy that attempts to prevent any overcommit of memory. This feature can be very useful because there are a lot of diff --git a/Documentation/time_interpolators.txt b/Documentation/time_interpolators.txt index d9fefd5f4..e3b60854f 100644 --- a/Documentation/time_interpolators.txt +++ b/Documentation/time_interpolators.txt @@ -9,32 +9,33 @@ The architecture specific code typically provides gettimeofday and settimeofday under Linux. The time interpolator provides both if an arch defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick operations and call the necessary functions to advance the clock. + With the time interpolator a standardized interface exists for time -interpolation between ticks which also allows the determination -of time in a hardware independent way. The provided logic is highly scalable +interpolation between ticks. The provided logic is highly scalable and has been tested in SMP situations of up to 512 CPUs. If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code -(or the device drivers - like HPET) must register time interpolators. +(or the device drivers - like HPET) may register time interpolators. These are typically defined in the following way: -static struct time_interpolator my_interpolator; +static struct time_interpolator my_interpolator { + .frequency = MY_FREQUENCY, + .source = TIME_SOURCE_MMIO32, + .shift = 8, /* scaling for higher accuracy */ + .drift = -1, /* Unknown drift */ + .jitter = 0 /* time source is stable */ +}; void time_init(void) { .... /* Initialization of the timer *. - my_interpolator.frequency = MY_FREQUENCY; - my_interpolator.source = TIME_SOURCE_MMIO32; my_interpolator.address = &my_timer; - my_interpolator.shift = 32; /* increase accuracy of scaling */ - my_interpolator.drift = -1; /* Unknown */ - my_interpolator.jitter = 0; /* A stable time source */ register_time_interpolator(&my_interpolator); .... } -For more details see include/linux/timex.h. +For more details see include/linux/timex.h and kernel/timer.c. -Christoph Lameter , September 8, 2004 +Christoph Lameter , October 31, 2004 diff --git a/Documentation/tipar.txt b/Documentation/tipar.txt index 773b9a248..67133baef 100644 --- a/Documentation/tipar.txt +++ b/Documentation/tipar.txt @@ -4,7 +4,7 @@ Author: Romain Lievin -Homepage: http://lpg.ticalc.org/prj_dev +Homepage: http://lpg.ticalc.org/prj_tidev/index.html INTRODUCTION: @@ -12,31 +12,30 @@ INTRODUCTION: This is a driver for the very common home-made parallel link cable, a cable designed for connecting TI8x/9x graphing calculators (handhelds) to a computer or workstation (Alpha, Sparc). Given that driver is built on parport, the -parallel port abstraction layer, this driver is independent of the platform. +parallel port abstraction layer, this driver is architecture-independent. It can also be used with another device plugged on the same port (such as a -ZIP drive). I have a 100MB ZIP and both of them work fine ! +ZIP drive). I have a 100MB ZIP and both of them work fine! If you need more information, please visit the 'TI drivers' homepage at the URL above. WHAT YOU NEED: -A TI calculator of course and a program capable to communicate with your -calculator. -TiLP will work for sure (since I am his developer !). yal92 may be able to use +A TI calculator and a program capable of communicating with your calculator. + +TiLP will work for sure (since I am its developer!). yal92 may be able to use it by changing tidev for tipar (may require some hacking...). HOW TO USE IT: You must have first compiled parport support (CONFIG_PARPORT_DEV): either compiled in your kernel, either as a module. -This driver supports the new device hierarchy (devfs). -Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX): +Next, (as root): modprobe parport - insmod tipar.o + modprobe tipar If it is not already there (it usually is), create the device: @@ -47,14 +46,14 @@ If it is not already there (it usually is), create the device: You will have to set permissions on this device to allow you to read/write from it: - chmod 666 /dev/tipar? + chmod 666 /dev/tipar[0..2] Now you are ready to run a linking program such as TiLP. Be sure to configure it properly (RTFM). MODULE PARAMETERS: - You can set these with: insmod tipar NAME=VALUE + You can set these with: modprobe tipar NAME=VALUE There is currently no way to set these on a per-cable basis. NAME: timeout @@ -66,11 +65,12 @@ MODULE PARAMETERS: NAME: delay TYPE: integer DEFAULT: 10 - DESC: Inter-bit delay in micro-seconds. An lower value gives an higher data + DESC: Inter-bit delay in micro-seconds. A lower value gives an higher data rate but makes transmission less reliable. These parameters can be changed at run time by any program via ioctl(2) calls -as listed in ./include/linux/ticable.h +as listed in ./include/linux/ticable.h. + Rather than write 50 pages describing the ioctl() and so on, it is perhaps more useful you look at ticables library (dev_link.c) that demonstrates how to use them, and demonstrates the features of the driver. This is diff --git a/Documentation/tty.txt b/Documentation/tty.txt index a49605642..5f6dc1267 100644 --- a/Documentation/tty.txt +++ b/Documentation/tty.txt @@ -49,10 +49,9 @@ open() - Called when the line discipline is attached to discipline for this tty will occur until it completes successfully. Can sleep. -write() - A process is writing data from user space - through the line discipline. Multiple write calls - are serialized by the tty layer for the ldisc. May - sleep. +write() - A process is writing data through the line + discipline. Multiple write calls are serialized + by the tty layer for the ldisc. May sleep. flush_buffer() - May be called at any point between open and close. diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt index 64ade120d..09754b7d2 100644 --- a/Documentation/usb/error-codes.txt +++ b/Documentation/usb/error-codes.txt @@ -1,11 +1,12 @@ -Revised: 2002-Feb-09. +Revised: 2004-Oct-21 This is the documentation of (hopefully) all possible error codes (and their interpretation) that can be returned from usbcore. Some of them are returned by the Host Controller Drivers (HCDs), which device drivers only see through usbcore. As a rule, all the HCDs should -behave the same except for transfer speed dependent behaviors. +behave the same except for transfer speed dependent behaviors and the +way certain faults are reported. ************************************************************************** @@ -26,29 +27,35 @@ USB-specific: of urb. (treat as a host controller bug.) -EINVAL a) Invalid transfer type specified (or not supported) - b) Invalid interrupt interval (0<=n<256) - c) more than one interrupt packet requested + b) Invalid or unsupported periodic transfer interval + c) ISO: attempted to change transfer interval d) ISO: number_of_packets is < 0 + e) various other cases -EAGAIN a) specified ISO start frame too early b) (using ISO-ASAP) too much scheduled for the future wait some time and try again. --EFBIG too much ISO frames requested (currently uhci>900) +-EFBIG Host controller driver can't schedule that many ISO frames. -EPIPE Specified endpoint is stalled. For non-control endpoints, reset this status with usb_clear_halt(). --EMSGSIZE endpoint message size is zero, do interface/alternate setting +-EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable + in the current interface altsetting. + (b) ISO packet is biger than endpoint maxpacket + (c) requested data transfer size is invalid (negative) --ENOSPC The host controller's bandwidth is already consumed and - this request would push it past its allowed limit. +-ENOSPC This request would overcommit the usb bandwidth reserved + for periodic transfers (interrupt, isochronous). --ESHUTDOWN The host controller has been disabled due to some +-ESHUTDOWN The device or host controller has been disabled due to some problem that could not be worked around. -EPERM Submission failed because urb->reject was set. +-EHOSTUNREACH URB was rejected because the device is suspended. + ************************************************************************** * Error codes returned by in urb->status * @@ -71,14 +78,14 @@ one or more packets could finish before an error stops further endpoint I/O. -EINPROGRESS URB still pending, no results yet (That is, if drivers see this it's a bug.) --EPROTO (*) a) bitstuff error +-EPROTO (*, **) a) bitstuff error b) no response packet received within the prescribed bus turn-around time c) unknown USB error --EILSEQ (*) CRC mismatch +-EILSEQ (*, **) CRC mismatch --EPIPE Endpoint stalled. For non-control endpoints, +-EPIPE (**) Endpoint stalled. For non-control endpoints, reset this status with usb_clear_halt(). -ECOMM During an IN transfer, the host controller @@ -97,7 +104,7 @@ one or more packets could finish before an error stops further endpoint I/O. specified buffer, and URB_SHORT_NOT_OK was set in urb->transfer_flags. --ETIMEDOUT transfer timed out, NAK +-ETIMEDOUT (**) transfer timed out, NAK -ENODEV Device was removed. Often preceded by a burst of other errors, since the hub driver does't detect @@ -110,13 +117,19 @@ one or more packets could finish before an error stops further endpoint I/O. -ECONNRESET URB was asynchronously unlinked by usb_unlink_urb --ESHUTDOWN The host controller has been disabled due to some - problem that could not be worked around. +-ESHUTDOWN The device or host controller has been disabled due + to some problem that could not be worked around, + such as a physical disconnect. (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate hardware problems such as bad devices (including firmware) or cables. +(**) This is also one of several codes that different kinds of host +controller use to to indicate a transfer has failed because of device +disconnect. In the interval before the hub driver starts disconnect +processing, devices may receive such fault reports for every request. + ************************************************************************** diff --git a/Documentation/usb/silverlink.txt b/Documentation/usb/silverlink.txt index d720415eb..81cbb52dc 100644 --- a/Documentation/usb/silverlink.txt +++ b/Documentation/usb/silverlink.txt @@ -1,5 +1,6 @@ ------------------------------------------------------------------------- Readme for Linux device driver for the Texas Instruments SilverLink cable +and direct USB cable provided by some TI's handhelds. ------------------------------------------------------------------------- Author: Romain Liévin & Julien Blache @@ -9,7 +10,8 @@ INTRODUCTION: This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable designed by TI for connecting their TI8x/9x calculators to a computer -(PC or Mac usually). +(PC or Mac usually). It has been extended to support the USB port offered by +some latest TI handhelds (TI84+ and TI89 Titanium). If you need more information, please visit the 'SilverLink drivers' homepage at the above URL. @@ -73,4 +75,4 @@ this driver but he better knows the Mac OS-X driver. CREDITS: The code is based on dabusb.c, printer.c and scanner.c ! -The driver has been developed independently of Texas Instruments. +The driver has been developed independently of Texas Instruments Inc. diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt index 65018c8c9..18ceabdb3 100644 --- a/Documentation/usb/sn9c102.txt +++ b/Documentation/usb/sn9c102.txt @@ -1,7 +1,7 @@ - SN9C10[12] PC Camera Controllers + SN9C10x PC Camera Controllers Driver for Linux - ================================ + ============================= - Documentation - @@ -9,28 +9,32 @@ Index ===== 1. Copyright -2. License -3. Overview -4. Module dependencies -5. Module loading -6. Module parameters -7. Device control through "sysfs" -8. Supported devices -9. How to add support for new image sensors -10. Note for V4L2 developers -11. Contact information -12. Credits +2. Disclaimer +3. License +4. Overview +5. Driver installation +6. Module loading +7. Module parameters +8. Optional device control through "sysfs" +9. Supported devices +10. How to add support for new image sensors +11. Notes for V4L2 application developers +12. Contact information +13. Credits 1. Copyright ============ Copyright (C) 2004 by Luca Risolia + +2. Disclaimer +============= SONiX is a trademark of SONiX Technology Company Limited, inc. -This driver is not sponsored or developed by SONiX. +This software is not sponsored or developed by SONiX. -2. License +3. License ========== 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 @@ -47,28 +51,52 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -3. Overview +4. Overview =========== -This driver attempts to support the video streaming capabilities of the devices -mounting the SONiX SN9C101 or SONiX SN9C102 PC Camera Controllers. +This driver attempts to support the video and audio streaming capabilities of +the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 (or SUI-102) PC +Camera Controllers. -- It's worth to note that SONiX has never collaborated with me during the -development of this project, despite of several requests for enough detailed +It's worth to note that SONiX has never collaborated with the author during the +development of this project, despite several requests for enough detailed specifications of the register tables, compression engine and video data format -of the above chips - - -Up to 64 cameras can be handled at the same time. They can be connected and -disconnected from the host many times without turning off the computer, if -your system supports the hotplug facility. +of the above chips. The driver relies on the Video4Linux2 and USB core modules. It has been designed to run properly on SMP systems as well. -The latest version of the SN9C10[12] driver can be found at the following URL: -http://go.lamarinapunto.com/ - - -4. Module dependencies +The latest version of the SN9C10x driver can be found at the following URL: +http://www.linux-projects.org/ + +Some of the features of the driver are: + +- full compliance with the Video4Linux2 API (see also "Notes for V4L2 + application developers" paragraph); +- available mmap or read/poll methods for video streaming through isochronous + data transfers; +- automatic detection of image sensor; +- support for any window resolutions and optional panning within the maximum + pixel area of image sensor; +- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both + directions (see "Notes for V4L2 application developers" paragraph); +- two different video formats for uncompressed or compressed data (see also + "Notes for V4L2 application developers" paragraph); +- full support for the capabilities of many of the possible image sensors that + can be connected to the SN9C10x bridges, including, for istance, red, green, + blue and global gain adjustments and exposure (see "Supported devices" + paragraph for details); +- use of default color settings for sunlight conditions; +- dynamic I/O interface for both SN9C10x and image sensor control (see + "Optional device control through 'sysfs'" paragraph); +- dynamic driver control thanks to various module parameters (see "Module + parameters" paragraph); +- up to 64 cameras can be handled at the same time; they can be connected and + disconnected from the host many times without turning off the computer, if + your system supports hotplugging; +- no known bugs. + + +5. Module dependencies ====================== For it to work properly, the driver needs kernel support for Video4Linux and USB. @@ -100,7 +128,7 @@ And finally: CONFIG_USB_SN9C102=m -5. Module loading +6. Module loading ================= To use the driver, it is necessary to load the "sn9c102" module into memory after every other module required: "videodev", "usbcore" and, depending on @@ -108,7 +136,6 @@ the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". Loading can be done as shown below: - [root@localhost home]# modprobe usbcore [root@localhost home]# modprobe sn9c102 At this point the devices should be recognized. You can invoke "dmesg" to @@ -117,17 +144,17 @@ analyze kernel messages and verify that the loading process has gone well: [user@localhost home]$ dmesg -6. Module parameters +7. Module parameters ==================== Module parameters are listed below: ------------------------------------------------------------------------------- Name: video_nr -Type: int array (min = 0, max = 32) +Type: int array (min = 0, max = 64) Syntax: <-1|n[,...]> Description: Specify V4L2 minor mode number: -1 = use next available n = use minor number n - You can specify up to 32 cameras this way. + You can specify up to 64 cameras this way. For example: video_nr=-1,2,-1 would assign minor number 2 to the second recognized camera and use auto for the first one and for every @@ -142,27 +169,30 @@ Description: Debugging information level, from 0 to 3: 1 = critical errors 2 = significant informations 3 = more verbose messages - Level 3 is useful for testing only, when just one device - is used. + Level 3 is useful for testing only, when only one device + is used. It also shows some more informations about the + hardware being detected. This parameter can be changed at + runtime thanks to the /sys filesystem. Default: 2 ------------------------------------------------------------------------------- -7. Device control through "sysfs" -================================= -It is possible to read and write both the SN9C10[12] and the image sensor +8. Optional device control through "sysfs" +========================================== +It is possible to read and write both the SN9C10x and the image sensor registers by using the "sysfs" filesystem interface. -Every time a supported device is recognized, read-only files named "redblue" -and "green" are created in the /sys/class/video4linux/videoX directory. You can -set the red, blue and green channel's gain by writing the desired value to -them. The value may range from 0 to 15 for each channel; this means that -"redblue" accepts 8-bit values, where the low 4 bits are reserved for red and -the others for blue. +Every time a supported device is recognized, a write-only file named "green" is +created in the /sys/class/video4linux/videoX directory. You can set the green +channel's gain by writing the desired value to it. The value may range from 0 +to 15 for SN9C101 or SN9C102 bridges, from 0 to 127 for SN9C103 bridges. +Similarly, only for SN9C103 controllers, blue and red gain control files are +available in the same directory, for which accepted values may range from 0 to +127. There are other four entries in the directory above for each registered camera: "reg", "val", "i2c_reg" and "i2c_val". The first two files control the -SN9C10[12] bridge, while the other two control the sensor chip. "reg" and +SN9C10x bridge, while the other two control the sensor chip. "reg" and "i2c_reg" hold the values of the current register index where the following reading/writing operations are addressed at through "val" and "i2c_val". Their use is not intended for end-users, unless you know what you are doing. Note @@ -171,94 +201,146 @@ support the standard I2C protocol. Also, remember that you must be logged in as root before writing to them. As an example, suppose we were to want to read the value contained in the -register number 1 of the sensor register table - which usually is the product +register number 1 of the sensor register table - which is usually the product identifier - of the camera registered as "/dev/video0": [root@localhost #] cd /sys/class/video4linux/video0 [root@localhost #] echo 1 > i2c_reg [root@localhost #] cat i2c_val -Now let's set the green gain's register of the SN9C10[12] chip to 2: +Note that "cat" will fail if sensor registers cannot be read. + +Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2: [root@localhost #] echo 0x11 > reg [root@localhost #] echo 2 > val -Note that the SN9C10[12] always returns 0 when some of its registers are read. +Note that the SN9C10x always returns 0 when some of its registers are read. To avoid race conditions, all the I/O accesses to the files are serialized. -8. Supported devices +9. Supported devices ==================== -- I won't mention any of the names of the companies as well as their products -here. They have never collaborated with me, so no advertising - +None of the names of the companies as well as their products will be mentioned +here. They have never collaborated with the author, so no advertising. From the point of view of a driver, what unambiguously identify a device are its vendor and product USB identifiers. Below is a list of known identifiers of -devices mounting the SN9C10[12] PC camera controllers: +devices mounting the SN9C10x PC camera controllers: Vendor ID Product ID --------- ---------- -0xc45 0x6001 -0xc45 0x6005 -0xc45 0x6009 -0xc45 0x600d -0xc45 0x6024 -0xc45 0x6025 -0xc45 0x6028 -0xc45 0x6029 -0xc45 0x602a -0xc45 0x602c -0xc45 0x8001 - -The list above does NOT imply that all those devices work with this driver: up -until now only the ones that mount the following image sensors are supported. -Kernel messages will always tell you whether this is the case: +0x0c45 0x6001 +0x0c45 0x6005 +0x0c45 0x6009 +0x0c45 0x600d +0x0c45 0x6024 +0x0c45 0x6025 +0x0c45 0x6028 +0x0c45 0x6029 +0x0c45 0x602a +0x0c45 0x602b +0x0c45 0x602c +0x0c45 0x6030 +0x0c45 0x6080 +0x0c45 0x6082 +0x0c45 0x6083 +0x0c45 0x6088 +0x0c45 0x608a +0x0c45 0x608b +0x0c45 0x608c +0x0c45 0x608e +0x0c45 0x608f +0x0c45 0x60a0 +0x0c45 0x60a2 +0x0c45 0x60a3 +0x0c45 0x60a8 +0x0c45 0x60aa +0x0c45 0x60ab +0x0c45 0x60ac +0x0c45 0x60ae +0x0c45 0x60af +0x0c45 0x60b0 +0x0c45 0x60b2 +0x0c45 0x60b3 +0x0c45 0x60b8 +0x0c45 0x60ba +0x0c45 0x60bb +0x0c45 0x60bc +0x0c45 0x60be + +The list above does not imply that all those devices work with this driver: up +until now only the ones that mount the following image sensors are supported; +kernel messages will always tell you whether this is the case: Model Manufacturer ----- ------------ PAS106B PixArt Imaging Inc. +PAS202BCB PixArt Imaging Inc. TAS5110C1B Taiwan Advanced Sensor Corporation TAS5130D1B Taiwan Advanced Sensor Corporation +All the available control settings of each image sensor are supported through +the V4L2 interface. + If you think your camera is based on the above hardware and is not actually listed in the above table, you may try to add the specific USB VendorID and ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h"; then compile, load the module again and look at the kernel output. -If this works, please send an email to me reporting the kernel messages, so -that I will add a new entry in the list of supported devices. +If this works, please send an email to the author reporting the kernel +messages, so that a new entry in the list of supported devices can be added. Donations of new models for further testing and support would be much -appreciated. I won't add official support for hardware that I don't actually -have. +appreciated. Non-available hardware won't be supported by the author of this +driver. -9. How to add support for new image sensors -=========================================== +10. How to add support for new image sensors +============================================ It should be easy to write code for new sensors by using the small API that I have created for this purpose, which is present in "sn9c102_sensor.h" (documentation is included there). As an example, have a look at the code in "sn9c102_pas106b.c", which uses the mentioned interface. -At the moment, not yet supported image sensors are: PAS202B (VGA), -HV7131[D|E1] (VGA), MI03 (VGA), OV7620 (VGA). +At the moment, possible unsupported image sensors are: HV7131x series (VGA), +MI03x series (VGA), OV7620 (VGA), OV7630 (VGA), CIS-VF10 (VGA). -10. Note for V4L2 developers -============================ +11. Notes for V4L2 application developers +========================================= This driver follows the V4L2 API specifications. In particular, it enforces two rules: -1) Exactly one I/O method, either "mmap" or "read", is associated with each +- exactly one I/O method, either "mmap" or "read", is associated with each file descriptor. Once it is selected, the application must close and reopen the -device to switch to the other I/O method. - -2) Previously mapped buffer memory must always be unmapped before calling any -of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case, -the same number of buffers as before will be allocated again to match the size -of the new video frames, so you have to map them again before any I/O attempts. - - -11. Contact information +device to switch to the other I/O method; + +- previously mapped buffer memory must always be unmapped before calling any +of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same +number of buffers as before will be allocated again to match the size of the +new video frames, so you have to map the buffers again before any I/O attempts +on them. + +Consistently with the hardware limits, this driver also supports image +downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions. +However, the V4L2 API specifications don't correctly define how the scaling +factor can be chosen arbitrarily by the "negotiation" of the "source" and +"target" rectangles. To work around this flaw, we have added the convention +that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the +scaling factor is restored to 1. + +This driver supports two different video formats: the first one is the "8-bit +Sequential Bayer" format and can be used to obtain uncompressed video data +from the device through the current I/O method, while the second one provides +"raw" compressed video data (without the initial and final frame headers). The +compression quality may vary from 0 to 1 and can be selected or queried thanks +to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum +flexibility, the default active video format depends on how the image sensor +being used is initialized (as described in the documentation of the API for the +image sensors supplied by this driver). + + +12. Contact information ======================= I may be contacted by e-mail at . @@ -267,10 +349,12 @@ My public 1024-bit key should be available at any keyserver; the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. -12. Credits +13. Credits =========== I would thank the following persons: - Stefano Mozzi, who donated 45 EU; - Luca Capello for the donation of a webcam; -- Mizuno Takafumi for the donation of a webcam. +- Mizuno Takafumi for the donation of a webcam; +- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB + image sensor. diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index d431f19f7..f001cd93b 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -211,6 +211,62 @@ ZyXEL omni.net lcd plus ISDN TA azummo@towertech.it +Cypress M8 CY4601 Family Serial Driver + + This driver was in most part developed by Neil "koyama" Whelchel. It + has been improved since that previous form to support dynamic serial + line settings and improved line handling. The driver is for the most + part stable and has been tested on an smp machine. (dual p2) + + Chipsets supported under CY4601 family: + + CY7C63723, CY7C63742, CY7C63743, CY7C64013 + + Devices supported: + + -DeLorme's USB Earthmate (SiRF Star II lp arch) + -Cypress HID->COM RS232 adapter + + Note: Cypress Semiconductor claims no affiliation with the + the hid->com device. + + Most devices using chipsets under the CY4601 family should + work with the driver. As long as they stay true to the CY4601 + usbserial specification. + + Technical notes: + + The Earthmate starts out at 4800 8N1 by default... the driver will + upon start init to this setting. usbserial core provides the rest + of the termios settings, along with some custom termios so that the + output is in proper format and parsable. + + The device can be put into sirf mode by issuing NMEA command: + $PSRF100,,,,,*CHECKSUM + $PSRF100,0,9600,8,1,0*0C + + It should then be sufficient to change the port termios to match this + to begin communicating. + + As far as I can tell it supports pretty much every sirf command as + documented online available with firmware 2.31, with some unknown + message ids. + + The hid->com adapter can run at a maximum baud of 115200bps. Please note + that the device has trouble or is incapable of raising line voltage properly. + It will be fine with null modem links, as long as you do not try to link two + together without hacking the adapter to set the line high. + + The driver is smp safe. Performance with the driver is rather low when using + it for transfering files. This is being worked on, but I would be willing to + accept patches. An urb queue or packet buffer would likely fit the bill here. + + If you have any questions, problems, patches, feature requests, etc. you can + contact me here via email: + dignome@gmail.com + (your problems/patches can alternately be submitted to usb-devel) + + Digi AccelePort Driver This driver supports the Digi AccelePort USB 2 and 4 devices, 2 port diff --git a/Documentation/usb/w9968cf.txt b/Documentation/usb/w9968cf.txt index f52d65e55..18a47738d 100644 --- a/Documentation/usb/w9968cf.txt +++ b/Documentation/usb/w9968cf.txt @@ -8,26 +8,30 @@ Index ===== -1. Copyright -2. License -3. Overview -4. Supported devices -5. Module dependencies -6. Module loading -7. Module paramaters -8. Contact information -9. Credits +1. Copyright +2. Disclaimer +3. License +4. Overview +5. Supported devices +6. Module dependencies +7. Module loading +8. Module paramaters +9. Contact information +10. Credits 1. Copyright ============ Copyright (C) 2002-2004 by Luca Risolia + +2. Disclaimer +============= Winbond is a trademark of Winbond Electronics Corporation. -This driver is not sponsored or developed by Winbond. +This software is not sponsored or developed by Winbond. -2. License +3. License ========== 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 @@ -44,7 +48,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -3. Overview +4. Overview =========== This driver supports the video streaming capabilities of the devices mounting Winbond W9967CF and Winbond W9968CF JPEG USB Dual Mode Camera Chips. OV681 @@ -57,7 +61,7 @@ decoding, up-scaling and colour conversions. Once the driver is installed, every time an application tries to open a recognized device, "w9968cf" checks the presence of the "w9968cf-vpp" module and loads it automatically by default. -Please keep in mind that official kernels do NOT include the second module for +Please keep in mind that official kernels do not include the second module for performance purposes. However it is always recommended to download and install the latest and complete release of the driver, replacing the existing one, if present: it will be still even possible not to load the "w9968cf-vpp" module at @@ -65,7 +69,7 @@ all, if you ever want to. Another important missing feature of the version in the official Linux 2.4 kernels is the writeable /proc filesystem interface. The latest and full-featured version of the W996[87]CF driver can be found at: -http://go.lamarinapunto.com/ . Please refer to the documentation included in +http://www.linux-projects.org. Please refer to the documentation included in that package, if you are going to use it. Up to 32 cameras can be handled at the same time. They can be connected and @@ -83,7 +87,7 @@ will be automatically loaded by default (provided that the kernel has been compiled with the automatic module loading option). -4. Supported devices +5. Supported devices ==================== At the moment, known W996[87]CF and OV681 based devices are: - Aroma Digi Pen VGA Dual Mode ADG-5000 (unknown image sensor) @@ -99,11 +103,9 @@ At the moment, known W996[87]CF and OV681 based devices are: If you know any other W996[87]CF or OV681 based cameras, please contact me. -The list above does NOT imply that all those devices work with this driver: up +The list above does not imply that all those devices work with this driver: up until now only webcams that have an image sensor supported by the "ovcamchip" -module work. -For a list of supported image sensors, please visit the author's homepage on -this module: http://alpha.dyndns.org/ov511/ +module work. Kernel messages will always tell you whether this is case. Possible external microcontrollers of those webcams are not supported: this means that still images cannot be downloaded from the device memory. @@ -113,7 +115,7 @@ Furthermore, it's worth to note that I was only able to run tests on my additional testing and full support, would be much appreciated. -5. Module dependencies +6. Module dependencies ====================== For it to work properly, the driver needs kernel support for Video4Linux, USB and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not @@ -157,7 +159,7 @@ And finally: CONFIG_USB_W9968CF=m -6. Module loading +7. Module loading ================= To use the driver, it is necessary to load the "w9968cf" module into memory after every other module required. @@ -166,6 +168,7 @@ Loading can be done this way, from root: [root@localhost home]# modprobe usbcore [root@localhost home]# modprobe i2c-core + [root@localhost home]# modprobe videodev [root@localhost home]# modprobe w9968cf At this point the pertinent devices should be recognized: "dmesg" can be used @@ -181,7 +184,7 @@ explanation about them and which syntax to use, it is recommended to run the [root@locahost home]# modinfo w9968cf -7. Module parameters +8. Module parameters ==================== Module parameters are listed below: ------------------------------------------------------------------------------- @@ -452,7 +455,7 @@ Default: 0 ------------------------------------------------------------------------------- -8. Contact information +9. Contact information ====================== I may be contacted by e-mail at . @@ -461,7 +464,7 @@ My public 1024-bit key should be available at your keyserver; the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. -9. Credits +10. Credits ========== The development would not have proceed much further without having looked at the source code of other drivers and without the help of several persons; in diff --git a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt index 5adcd2502..2137da975 100644 --- a/Documentation/video4linux/meye.txt +++ b/Documentation/video4linux/meye.txt @@ -1,12 +1,12 @@ Vaio Picturebook Motion Eye Camera Driver Readme ------------------------------------------------ - Copyright (C) 2001-2003 Stelian Pop + Copyright (C) 2001-2004 Stelian Pop Copyright (C) 2001-2002 Alcôve Copyright (C) 2000 Andrew Tridgell This driver enable the use of video4linux compatible applications with the -Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O -Control Device" driver (which can be found in the "Character drivers" +Motion Eye camera. This driver requires the "Sony Vaio Programmable I/O +Control Device" driver (which can be found in the "Character drivers" section of the kernel configuration utility) to be compiled and installed (using its "camera=1" parameter). @@ -24,7 +24,7 @@ This driver supports the 'second' version of the MotionEye camera :) The first version was connected directly on the video bus of the Neomagic video card and is unsupported. -The second one, made by Kawasaki Steel is fully supported by this +The second one, made by Kawasaki Steel is fully supported by this driver (PCI vendor/device is 0x136b/0xff01) The third one, present in recent (more or less last year) Picturebooks @@ -41,13 +41,12 @@ little information if any is available for this camera Driver options: --------------- -Several options can be passed to the meye driver, either by adding them -to /etc/modprobe.conf file, when the driver is compiled as a module, or -by adding the following to the kernel command line (in your bootloader): +Several options can be passed to the meye driver using the standard +module argument syntax (= when passing the option to the +module or meye.= on the kernel boot line when meye is +statically linked into the kernel). Those options are: - meye=gbuffers[,gbufsize[,video_nr]] - -where: + forcev4l1: force use of V4L1 API instead of V4L2 gbuffers: number of capture buffers, default is 2 (32 max) @@ -81,8 +80,9 @@ Usage: Private API: ------------ - The driver supports frame grabbing with the video4linux API, so - all video4linux tools (like xawtv) should work with this driver. + The driver supports frame grabbing with the video4linux API + (either v4l1 or v4l2), so all video4linux tools (like xawtv) + should work with this driver. Besides the video4linux interface, the driver has a private interface for accessing the Motion Eye extended parameters (camera sharpness, @@ -116,7 +116,7 @@ Private API: MEYEIOC_STILLJCAPT Takes a snapshot in an uncompressed or compressed jpeg format. This ioctl blocks until the snapshot is done and returns (for - jpeg snapshot) the size of the image. The image data is + jpeg snapshot) the size of the image. The image data is available from the first mmap'ed buffer. Look at the 'motioneye' application code for an actual example. @@ -124,13 +124,7 @@ Private API: Bugs / Todo: ------------ - - overlay output is not supported (although the camera is capable of). - (it should not be too hard to to it, provided we found how...) - - - mjpeg hardware playback doesn't work (depends on overlay...) + - the driver could be much cleaned up by removing the v4l1 support. + However, this means all v4l1-only applications will stop working. - - rewrite the driver to use some common video4linux API for snapshot - and mjpeg capture. Unfortunately, video4linux1 does not permit it, - the BUZ API seems to be targeted to TV cards only. The video4linux 2 - API may be an option, if it goes into the kernel (maybe 2.5 - material ?). + - 'motioneye' still uses the meye private v4l1 API extensions. diff --git a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting index e0fd0b8f0..21c7b1f8f 100644 --- a/Documentation/vm/overcommit-accounting +++ b/Documentation/vm/overcommit-accounting @@ -1,4 +1,4 @@ -The Linux kernel supports three overcommit handling modes +The Linux kernel supports the following overcommit handling modes 0 - Heuristic overcommit handling. Obvious overcommits of address space are refused. Used for a typical system. It @@ -7,10 +7,10 @@ The Linux kernel supports three overcommit handling modes allocate slighly more memory in this mode. This is the default. -1 - No overcommit handling. Appropriate for some scientific +1 - Always overcommit. Appropriate for some scientific applications. -2 - (NEW) strict overcommit. The total address space commit +2 - Don't overcommit. The total address space commit for the system is not permitted to exceed swap + a configurable percentage (default is 50) of physical RAM. Depending on the percentage you use, in most situations @@ -22,12 +22,15 @@ The overcommit policy is set via the sysctl `vm.overcommit_memory'. The overcommit percentage is set via `vm.overcommit_ratio'. +The current overcommit limit and amount committed are viewable in +/proc/meminfo as CommitLimit and Committed_AS respectively. + Gotchas ------- The C language stack growth does an implicit mremap. If you want absolute guarantees and run close to the edge you MUST mmap your stack for the -largest size you think you will need. For typical stack usage is does +largest size you think you will need. For typical stack usage this does not matter much but it's a corner case if you really really care In mode 2 the MAP_NORESERVE flag is ignored. diff --git a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt index a586667aa..12187a33e 100644 --- a/Documentation/watchdog/pcwd-watchdog.txt +++ b/Documentation/watchdog/pcwd-watchdog.txt @@ -35,7 +35,8 @@ #include #include #include -#include +#include +#include int fd; diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index d78f8dbf9..d12607071 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -87,22 +87,8 @@ Non Executable Mappings noexec=on|off - on Enable + on Enable(default) off Disable - noforce (default) Don't enable by default for heap/stack/data, - but allow PROT_EXEC to be effective - - noexec32=opt{,opt} - - Control the no exec default for 32bit processes. - Requires noexec=on or noexec=noforce to be effective. - - Valid options: - all,on Heap,stack,data is non executable. - off (default) Heap,stack,data is executable - stack Stack is non executable, heap/data is. - force Don't imply PROT_EXEC for PROT_READ - compat (default) Imply PROT_EXEC for PROT_READ SMP @@ -136,17 +122,25 @@ PCI IOMMU - iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,soft] + iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] + [,forcesac][,fullflush][,nomerge][,noaperture] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. off don't use the IOMMU leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) memaper[=order] allocate an own aperture over RAM with size 32MB^order. noforce don't force IOMMU usage. Default. - force Force IOMMU - soft Use software bounce buffering for non 32bit IO. Default on Intel - machines. - - swiotlb=pages - - Prereserve that many 4K pages for the software IO bounce buffering. + force Force IOMMU. + merge Do SG merging. Implies force (experimental) + nomerge Don't do SG merging. + forcesac For SAC mode for masks <40bits (experimental) + fullflush Flush IOMMU on each allocation (default) + nofullflush Don't use IOMMU fullflush + allowed overwrite iommu off workarounds for specific chipsets. + soft Use software bounce buffering (default for Intel machines) + noaperture Don't touch the aperture for AGP. + + swiotlb=pages[,force] + + pages Prereserve that many 128K pages for the software IO bounce buffering. + force Force all IO through the software TLB. diff --git a/MAINTAINERS b/MAINTAINERS index c8c25df43..d3dc9555c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -169,7 +169,7 @@ ACI MIXER DRIVER P: Robert Siemer M: Robert.Siemer@gmx.de L: linux-sound@vger.kernel.org -W: http://www.uni-karlsruhe.de/~Robert.Siemer/Private/ +W: http://www.stud.uni-karlsruhe.de/~uh1b/ S: Maintained ACP/MWAVE MODEM @@ -195,8 +195,14 @@ S: Maintained AD1816 SOUND DRIVER P: Thorsten Knabe -W: http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html -W: http://www.tu-darmstadt.de/~tek01/projects/linux.html +M: Thorsten Knabe +W: http://linux.thorsten-knabe.de +S: Maintained + +ADM1025 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com S: Maintained ADT746X FAN DRIVER @@ -281,6 +287,12 @@ P: Dave Gilbert M: linux@treblig.org S: Maintained +ARM/PLEB SUPPORT +P: Peter Chubb +M: pleb@gelato.unsw.edu.au +W: http://www.disy.cse.unsw.edu.au/Hardware/PLEB +S: Maintained + ARM/PT DIGITAL BOARD PORT P: Stefan Eletzhofer M: stefan.eletzhofer@eletztrick.de @@ -525,10 +537,9 @@ S: Supported COMPUTONE INTELLIPORT MULTIPORT CARD P: Michael H. Warfield M: Michael H. Warfield -W: http://www.computone.com/ W: http://www.wittsend.com/computone.html L: linux-computone@lazuli.wittsend.com -S: Supported +S: Orphaned COSA/SRP SYNC SERIAL DRIVER P: Jan "Yenya" Kasprzak @@ -553,8 +564,8 @@ W: http://sourceforge.net/projects/cramfs/ S: Orphan CRIS PORT -P: Bjorn Wesen -M: bjornw@axis.com +P: Mikael Starvik +M: starvik@axis.com L: dev-etrax@axis.com W: http://developer.axis.com S: Maintained @@ -563,7 +574,7 @@ CRYPTO API P: James Morris M: jmorris@redhat.com P: David S. Miller -M: davem@redhat.com +M: davem@davemloft.net W http://samba.org/~jamesm/crypto/ L: linux-kernel@vger.kernel.org S: Maintained @@ -621,12 +632,14 @@ DC390/AM53C974 SCSI driver P: Kurt Garloff M: garloff@suse.de W: http://www.garloff.de/kurt/linux/dc390/ +P: Guennadi Liakhovetski +M: g.liakhovetski@gmx.de S: Maintained DECnet NETWORK LAYER -P: Steven Whitehouse -M: SteveW@ACM.org -W: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html +P: Patrick Caulfield +M: patrick@tykepenguin.com +W: http://linux-decnet.sourceforge.net L: linux-decnet-user@lists.sourceforge.net S: Maintained @@ -648,8 +661,9 @@ W: http://sources.redhat.com/dm S: Maintained DEVICE NUMBER REGISTRY -P: John Cagle +P: Torben Mathiasen M: device@lanana.org +W: http://lanana.org/docs/device-list/index.html L: linux-kernel@vger.kernel.org S: Maintained @@ -661,7 +675,7 @@ P: Digi International, Inc M: Eng.Linux@digi.com L: Eng.Linux@digi.com W: http://www.digi.com -S: Maintained +S: Orphaned DIGI RIGHTSWITCH NETWORK DRIVER P: Rick Richardson @@ -674,7 +688,7 @@ P: Christoph Lameter M: christoph@lameter.com W: http://www.digi.com L: digilnux@digi.com -S: Orphaned +S: Obsolete DIRECTORY NOTIFICATION P: Stephen Rothwell @@ -762,12 +776,17 @@ M: saw@saw.sw.com.sg S: Maintained EMU10K1 SOUND DRIVER -P: Rui Sousa -M: rui.p.m.sousa@clix.pt +P: James Courtier-Dutton +M: James@superbug.demon.co.uk L: emu10k1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/emu10k1/ S: Maintained +EPSON 1355 FRAMEBUFFER DRIVER +P: Christopher Hoover +M: ch@murgatroid.com, ch@hpl.hp.com +S: Maintained + ETHEREXPRESS-16 NETWORK DRIVER P: Philip Blundell M: Philip.Blundell@pobox.com @@ -792,7 +811,7 @@ S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@digeo.com, adilger@clusterfs.com +M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com L: ext3-users@redhat.com S: Maintained @@ -804,11 +823,11 @@ W: http://www.farsite.co.uk/ S: Supported FRAMEBUFFER LAYER -P: James Simmons, Geert Uytterhoeven -M: jsimmons@infradead.org, geert@linux-m68k.org +P: Antonino Daplas +M: adaplas@pol.net L: linux-fbdev-devel@lists.sourceforge.net W: http://linux-fbdev.sourceforge.net/ -S: Supported +S: Maintained FILE LOCKING (flock() and fcntl()/lockf()) P: Matthew Wilcox @@ -818,14 +837,12 @@ S: Maintained FILESYSTEMS (VFS and infrastructure) P: Alexander Viro -M: viro@math.psu.edu +M: viro@parcelfarce.linux.theplanet.co.uk S: Maintained FIRMWARE LOADER (request_firmware) -P: Manuel Estrada Sainz -M: ranty@debian.org L: linux-kernel@vger.kernel.org -S: Maintained +S: Orphan FPU EMULATOR P: Bill Metzenthen @@ -846,11 +863,9 @@ W: ftp://ftp.openlinux.org/pub/people/hch/vxfs S: Maintained FTAPE/QIC-117 -P: Claus-Justus Heine -M: claus@momo.math.rwth-aachen.de L: linux-tape@vger.kernel.org -W: http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape/ -S: Maintained +W: http://sourceforge.net/projects/ftape +S: Orphan FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) P: Rik Faith @@ -905,18 +920,18 @@ L: linux-hippi@sunsite.dk S: Maintained HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA -P: Chase Maupin -M: chase.maupin@hp.com +P: Chirag Kantharia +M: chirag.kantharia@hp.com L: iss_storagedev@hp.com S: Maintained HEWLETT-PACKARD SMART2 RAID DRIVER -P: Francis Wiran -M: francis.wiran@hp.com +P: Chirag Kantharia +M: chirag.kantharia@hp.com L: iss_storagedev@hp.com S: Maintained -HEWLETT-PACKARD SMART CISS RAID DRIVER +HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) P: Mike Miller M: mike.miller@hp.com L: iss_storagedev@hp.com @@ -935,7 +950,7 @@ S: Maintained HPUSBSCSI P: Oliver Neukum -M: drivers@neukum.org +M: oliver@neukum.name S: Maintained I2C AND SENSORS DRIVERS @@ -947,6 +962,12 @@ L: sensors@stimpy.netroedge.com W: http://www.lm-sensors.nu/ S: Maintained +I2O +P: Markus Lidel +M: markus.lidel@shadowconnect.com +W: http://i2o.shadowconnect.com/ +S: Maintained + i386 BOOT CODE P: Riley H. Williams M: Riley@Williams.Name @@ -1060,6 +1081,19 @@ M: lethal@chaoticdreams.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained +INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS +P: Vojtech Pavlik +M: vojtech@suse.cz +L: linux-input@atrey.karlin.mff.cuni.cz +L: linux-joystick@atrey.karlin.mff.cuni.cz +S: Maintained + +INTEL 810/815 FRAMEBUFFER DRIVER +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained + INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT P: Ingo Molnar M: mingo@redhat.com @@ -1081,8 +1115,8 @@ P: John Ronciak M: john.ronciak@intel.com P: Ganesh Venkatesan M: ganesh.venkatesan@intel.com -P: Scott Feldman -M: scott.feldman@intel.com +P: Jesse Brandeburg +M: jesse.brandeburg@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1178,13 +1212,6 @@ L: jfs-discussion@oss.software.ibm.com W: http://oss.software.ibm.com/jfs/ S: Supported -JOYSTICK DRIVER -P: Vojtech Pavlik -M: vojtech@suse.cz -L: linux-joystick@atrey.karlin.mff.cuni.cz -W: http://www.suse.cz/development/joystick/ -S: Maintained - KCONFIG P: Roman Zippel M: zippel@linux-m68k.org @@ -1226,6 +1253,12 @@ W: http://nfs.sourceforge.net/ W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/ S: Maintained +KERNEL EVENT LAYER (KOBJECT_UEVENT) +P: Robert Love +M: rml@novell.com +L: linux-kernel@vger.kernel.org +S: Maintained + LANMEDIA WAN CARD DRIVER P: Andrew Stanley-Jones M: asj@lanmedia.com @@ -1266,35 +1299,45 @@ S: Maintained LINUX FOR POWERPC P: Paul Mackerras M: paulus@samba.org -W: http://www.fsmlabs.com/linuxppcbk.html +W: http://www.penguinppc.org/ +L: linuxppc-dev@ozlabs.org S: Supported LINUX FOR POWER MACINTOSH P: Benjamin Herrenschmidt M: benh@kernel.crashing.org -W: http://www.linuxppc.org/ -L: linuxppc-dev@lists.linuxppc.org +W: http://www.penguinppc.org/ +L: linuxppc-dev@ozlabs.org +S: Maintained + +LINUX FOR POWERPC EMBEDDED MPC52XX +P: Sylvain Munaut +M: tnt@246tNt.com +W: http://www.246tNt.com/mpc52xx/ +W: http://www.penguinppc.org/ +L: linuxppc-dev@ozlabs.org +L: linuxppc-embedded@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED PPC4XX P: Matt Porter M: mporter@kernel.crashing.org W: http://www.penguinppc.org/ -L: linuxppc-embedded@lists.linuxppc.org +L: linuxppc-embedded@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED PPC8XX AND BOOT CODE P: Tom Rini M: trini@kernel.crashing.org W: http://www.penguinppc.org/ -L: linuxppc-embedded@lists.linuxppc.org +L: linuxppc-embedded@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED PPC85XX P: Kumar Gala M: kumar.gala@freescale.com W: http://www.penguinppc.org/ -L: linuxppc-embedded@lists.linuxppc.org +L: linuxppc-embedded@ozlabs.org S: Maintained LLC (802.2) @@ -1303,12 +1346,14 @@ M: acme@conectiva.com.br S: Maintained LINUX FOR 64BIT POWERPC -P: David Engebretsen (stable kernel) -M: engebret@us.ibm.com -P: Anton Blanchard (development kernel) +P: Paul Mackerras +M: paulus@samba.org +M: paulus@au.ibm.com +P: Anton Blanchard +M: anton@samba.org M: anton@au.ibm.com W: http://linuxppc64.org -L: linuxppc64-dev@lists.linuxppc.org +L: linuxppc64-dev@ozlabs.org S: Supported LINUX SECURITY MODULE (LSM) FRAMEWORK @@ -1318,6 +1363,18 @@ L: linux-security-module@wirex.com W: http://lsm.immunix.org S: Supported +LM83 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Maintained + +LM90 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Maintained + LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks) P: Richard Russon (FlatCap) M: ldm@flatcap.org @@ -1389,7 +1446,7 @@ S: Maintained MICROTEK X6 SCANNER P: Oliver Neukum -M: drivers@neukum.org +M: oliver@neukum.name S: Maintained MIPS @@ -1400,11 +1457,8 @@ L: linux-mips@linux-mips.org S: Maintained MISCELLANEOUS MCA-SUPPORT -P: David Weinehall -M: Project MCA Team -M: David Weinehall -W: http://www.acc.umu.se/~tao/ -W: http://www.acc.umu.se/~mcalinux/ +P: James Bottomley +M: jejb@steeleye.com L: linux-kernel@vger.kernel.org S: Maintained @@ -1481,7 +1535,7 @@ S: Maintained NETWORK DEVICE DRIVERS P: Andrew Morton -M: akpm@digeo.com +M: akpm@osdl.org P: Jeff Garzik M: jgarzik@pobox.com L: linux-net@vger.kernel.org @@ -1495,7 +1549,7 @@ S: Maintained NETWORKING [IPv4/IPv6] P: David S. Miller -M: davem@redhat.com +M: davem@davemloft.net P: Alexey Kuznetsov M: kuznet@ms2.inr.ac.ru P: Pekka Savola (ipv6) @@ -1509,6 +1563,14 @@ M: kaber@coreworks.de L: netdev@oss.sgi.com S: Maintained +IPVS +P: Wensong Zhang +M: wensong@linux-vs.org +P: Julian Anastasov +M: ja@ssi.bg +L: lvs-users@linuxvirtualserver.org +S: Maintained + NFS CLIENT P: Trond Myklebust M: trond.myklebust@fys.uio.no @@ -1586,6 +1648,8 @@ L: oprofile-list@lists.sf.net S: Maintained ORINOCO DRIVER +P: Pavel Roskin +M: proski@gnu.org P: David Gibson M: hermes@gibson.dropbear.id.au W: http://www.ozlabs.org/people/dgibson/dldwd @@ -1600,14 +1664,14 @@ P: David Campbell M: campbell@torque.net P: Andrea Arcangeli M: andrea@e-mind.com -L: linux-parport@torque.net +L: linux-parport@lists.infradead.org W: http://people.redhat.com/twaugh/parport/ S: Maintained PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES P: Tim Waugh M: tim@cyberelk.net -L: linux-parport@torque.net +L: linux-parport@lists.infradead.org W: http://www.torque.net/linux-pp.html S: Maintained @@ -1667,6 +1731,12 @@ M: tsbogend@alpha.franken.de L: linux-net@vger.kernel.org S: Maintained +PHRAM MTD DRIVER +P: Jörn Engel +M: joern@wh.fh-wedel.de +L: linux-mtd@lists.infradead.org +S: Maintained + POSIX CLOCKS and TIMERS P: George Anzinger M: george@mvista.com @@ -1702,12 +1772,25 @@ L: kpreempt-tech@lists.sourceforge.net W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel S: Supported +PRISM54 WIRELESS DRIVER +P: Prism54 Development Team +M: prism54-private@prism54.org +L: netdev@oss.sgi.com +W: http://prism54.org +S: Maintained + PROMISE DC4030 CACHING DISK CONTROLLER DRIVER P: Peter Denison M: promise@pnd-pc.demon.co.uk W: http://www.pnd-pc.demon.co.uk/promise/ S: Maintained +PXA2xx SUPPORT +P: Nicolas Pitre +M: nico@cam.org +L: linux-arm-kernel@lists.arm.linux.org.uk +S: Maintained + QNX4 FILESYSTEM P: Anders Larsen M: al@alarsen.net @@ -1784,12 +1867,6 @@ M: michael@mihu.de W: http://www.mihu.de/linux/saa7146 S: Maintained -SA1100 SUPPORT -P: Nicolas Pitre -M: nico@cam.org -L: linux-arm@lists.arm.linux.org.uk -S: Maintained - SBPCD CDROM DRIVER P: Eberhard Moenkeberg M: emoenke@gwdg.de @@ -1895,6 +1972,12 @@ M: thomas@winischhofer.net W: http://www.winischhofer.net/linuxsisvga.shtml S: Maintained +SMSC47M1 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Odd Fixes + SMB FILESYSTEM P: Urban Widmark M: urban@teststation.com @@ -1902,6 +1985,11 @@ W: http://samba.org/ L: samba@samba.org S: Maintained +SMC91x ETHERNET DRIVER +P: Nicolas Pitre +M: nico@cam.org +S: Maintained + SNA NETWORK LAYER P: Jay Schulist M: jschlst@samba.org @@ -1945,7 +2033,7 @@ S: Maintained UltraSPARC (sparc64): P: David S. Miller -M: davem@redhat.com +M: davem@davemloft.net P: Eddie C. Dost M: ecd@skynet.be P: Jakub Jelinek @@ -2137,8 +2225,8 @@ W: http://www.kernel.dk S: Maintained USB ACM DRIVER -P: Vojtech Pavlik -M: vojtech@suse.cz +P: Oliver Neukum +M: oliver@neukum.name L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained @@ -2165,12 +2253,11 @@ M: dbrownell@users.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained -USB HID/HIDBP/INPUT DRIVERS +USB HID/HIDBP DRIVERS P: Vojtech Pavlik M: vojtech@suse.cz L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net -W: http://www.suse.cz/development/input/ S: Maintained USB HUB DRIVER @@ -2182,7 +2269,7 @@ S: Maintained USB KAWASAKI LSI DRIVER P: Oliver Neukum -M: drivers@neukum.org +M: oliver@neukum.name L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained @@ -2264,6 +2351,15 @@ L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB SERIAL CYPRESS M8 DRIVER +P: Lonnie Mendez +M: dignome@gmail.com +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained +W: http://geocities.com/i0xox0i +W: http://firstlight.net/cvs + USB SERIAL CYBERJACK PINPAD/E-COM DRIVER L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net @@ -2299,6 +2395,13 @@ L: linux-usb-devel@lists.sourceforge.net W: http://www.connecttech.com S: Supported +USB SN9C10x DRIVER +P: Luca Risolia +M: luca.risolia@studio.unibo.it +L: linux-usb-devel@lists.sourceforge.net +W: http://www.linux-projects.org +S: Maintained + USB SUBSYSTEM P: Greg Kroah-Hartman M: greg@kroah.com @@ -2324,7 +2427,7 @@ USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb-devel@lists.sourceforge.net -W: http://go.lamarinapunto.com +W: http://www.linux-projects.org S: Maintained USER-MODE LINUX @@ -2392,6 +2495,19 @@ M: johnpol@2ka.mipt.ru L: sensors@stimpy.netroedge.com S: Maintained +W83L51xD SD/MMC CARD INTERFACE DRIVER +P: Pierre Ossman +M: drzeus-wbsd@drzeus.cx +L: wbsd-devel@list.drzeus.cx +W: http://projects.drzeus.cx/wbsd +S: Maintained + +W83L785TS HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Odd Fixes + WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC) P: Nenad Corbic M: ncorbic@sangoma.com diff --git a/Makefile b/Makefile index 86d8af58a..2d6b9c0c4 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 -SUBLEVEL = 8 -EXTRAVERSION = .1 -NAME=Zonked Quokka +SUBLEVEL = 10 +EXTRAVERSION = +NAME=Woozy Numbat # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -102,7 +102,7 @@ ifneq ($(KBUILD_OUTPUT),) # check that the output directory actually exists saved-output := $(KBUILD_OUTPUT) KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) -$(if $(wildcard $(KBUILD_OUTPUT)),, \ +$(if $(KBUILD_OUTPUT),, \ $(error output directory "$(saved-output)" does not exist)) .PHONY: $(MAKECMDGOALS) @@ -141,7 +141,25 @@ VPATH := $(srctree) export srctree objtree VPATH TOPDIR -KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) +nullstring := +space := $(nullstring) # end of line + +# Take the contents of any files called localversion* and the config +# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be +# careful not to include files twice if building in the source +# directory. LOCALVERSION from the command line override all of this + +ifeq ($(objtree),$(srctree)) +localversion-files := $(wildcard $(srctree)/localversion*) +else +localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*) +endif + +LOCALVERSION = $(subst $(space),, \ + $(shell cat /dev/null $(localversion-files:%~=)) \ + $(patsubst "%",%,$(CONFIG_LOCALVERSION))) + +KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION) # SUBARCH tells the usermode build what the underlying arch is. That is set # first, and if a usermode build is happening, the "ARCH=um" on the command @@ -256,9 +274,37 @@ ifneq ($(findstring s,$(MAKEFLAGS)),) quiet=silent_ endif -check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) +export quiet Q KBUILD_VERBOSE + +###### +# cc support functions to be used (only) in arch/$(ARCH)/Makefile +# See documentation in Documentation/kbuild/makefiles.txt + +# cc-option +# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586) + +cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) + +# For backward compatibility +check_gcc = $(warning check_gcc is deprecated - use cc-option) \ + $(call cc-option, $(1),$(2)) + +# cc-option-yn +# Usage: flag := $(call gcc-option-yn, -march=winchip-c6) +cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) + +# cc-option-align +# Prefix align with either -falign or -malign +cc-option-align = $(subst -functions=0,,\ + $(call cc-option,-falign-functions=0,-malign-functions=0)) + +# cc-version +# Usage gcc-ver := $(call cc-version $(CC)) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ + $(if $(1), $(1), $(CC))) -export quiet Q KBUILD_VERBOSE check_gcc # Look for make include files relative to root of kernel src MAKEFLAGS += --include-dir=$(srctree) @@ -285,6 +331,7 @@ DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms PERL = perl CHECK = sparse +CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ MODFLAGS = -DMODULE CFLAGS_MODULE = $(MODFLAGS) AFLAGS_MODULE = $(MODFLAGS) @@ -294,19 +341,23 @@ AFLAGS_KERNEL = NOSTDINC_FLAGS = -nostdinc -iwithprefix include -CPPFLAGS := -D__KERNEL__ -Iinclude \ - $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) +# Use LINUXINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +LINUXINCLUDE := -Iinclude \ + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) + +CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ -export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ - CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ +export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \ + ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ - HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK + HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS -export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS +export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE @@ -333,6 +384,18 @@ RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CV scripts_basic: $(Q)$(MAKE) $(build)=scripts/basic +.PHONY: outputmakefile +# outputmakefile generate a Makefile to be placed in output directory, if +# using a seperate output directory. This allows convinient use +# of make in output directory +outputmakefile: + $(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \ + $(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ + $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \ + > $(objtree)/Makefile; \ + echo ' GEN $(objtree)/Makefile'; \ + fi + # To make sure we do not include .config for any of the *config targets # catch them early, and hand them over to scripts/kconfig/Makefile # It is allowed to specify more targets when calling make, including @@ -377,9 +440,15 @@ ifeq ($(config-targets),1) # *config targets only - make sure prerequisites are updated, and descend # in scripts/kconfig to make the *config target -config: scripts_basic FORCE +# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed. +# KBUILD_DEFCONFIG may point out an alternative default configuration +# used for 'make defconfig' +include $(srctree)/arch/$(ARCH)/Makefile +export KBUILD_DEFCONFIG + +config: scripts_basic outputmakefile FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ -%config: scripts_basic FORCE +%config: scripts_basic outputmakefile FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ else @@ -428,15 +497,6 @@ else include/linux/autoconf.h: ; endif -include $(srctree)/arch/$(ARCH)/Makefile - -# Default kernel image to build when no specific target is given. -# KBUILD_IMAGE may be overruled on the commandline or -# set in the environment -# Also any assingments in arch/$(ARCH)/Makefiel take precedence over -# this default value -export KBUILD_IMAGE ?= vmlinux - # The all: target is the default when no target is given on the # command line. # This allow a user to issue only 'make' to build a kernel including modules @@ -449,7 +509,16 @@ else CFLAGS += -O2 endif -ifndef CONFIG_FRAME_POINTER +#Add align options if CONFIG_CC_* is not equal to 0 +add-align = $(if $(filter-out 0,$($(1))),$(cc-option-align)$(2)=$($(1))) +CFLAGS += $(call add-align,CONFIG_CC_ALIGN_FUNCTIONS,-functions) +CFLAGS += $(call add-align,CONFIG_CC_ALIGN_LABELS,-labels) +CFLAGS += $(call add-align,CONFIG_CC_ALIGN_LOOPS,-loops) +CFLAGS += $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps) + +ifdef CONFIG_FRAME_POINTER +CFLAGS += -fno-omit-frame-pointer +else CFLAGS += -fomit-frame-pointer endif @@ -457,8 +526,17 @@ ifdef CONFIG_DEBUG_INFO CFLAGS += -g endif +include $(srctree)/arch/$(ARCH)/Makefile + # warn about C99 declaration after statement -CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,) +CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) + +# Default kernel image to build when no specific target is given. +# KBUILD_IMAGE may be overruled on the commandline or +# set in the environment +# Also any assingments in arch/$(ARCH)/Makefiel take precedence over +# this default value +export KBUILD_IMAGE ?= vmlinux # # INSTALL_PATH specifies where to place the updated kernel and system map @@ -499,67 +577,93 @@ libs-y := $(libs-y1) $(libs-y2) # Build vmlinux # --------------------------------------------------------------------------- +# vmlinux is build from the objects selected by $(vmlinux-init) and +# $(vmlinux-main). Most are built-in.o files from top-level directories +# in the kernel tree, others are specified in arch/$(ARCH)Makefile. +# Ordering when linking is important, and $(vmlinux-init) must be first. +# +# vmlinux +# ^ +# | +# +-< $(vmlinux-init) +# | +--< init/version.o + more +# | +# +--< $(vmlinux-main) +# | +--< driver/built-in.o mm/built-in.o + more +# | +# +-< kallsyms.o (see description in CONFIG_KALLSYMS section) +# +# vmlinux version (uname -v) cannot be updated during normal +# descending-into-subdirs phase since we do not yet know if we need to +# update vmlinux. +# Therefore this step is delayed until just before final link of vmlinux - +# except in the kallsyms case where it is done just before adding the +# symbols to the kernel. +# +# System.map is generated to document addresses of all kernel symbols + +vmlinux-init := $(head-y) $(init-y) +vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) +vmlinux-all := $(vmlinux-init) $(vmlinux-main) +vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds + +# Rule to link vmlinux - also used during CONFIG_KALLSYMS +# May be overridden by arch/$(ARCH)/Makefile +quiet_cmd_vmlinux__ ?= LD $@ + cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \ + -T $(vmlinux-lds) $(vmlinux-init) \ + --start-group $(vmlinux-main) --end-group \ + $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^) + +# Generate new vmlinux version +quiet_cmd_vmlinux_version = GEN .version + cmd_vmlinux_version = set -e; \ + . $(srctree)/scripts/mkversion > .tmp_version; \ + mv -f .tmp_version .version; \ + $(MAKE) $(build)=init + +# Generate System.map +quiet_cmd_sysmap = SYSMAP + cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap + +# Link of vmlinux +# If CONFIG_KALLSYMS is set .version is already updated +# Generate System.map and verify that the content is consistent -# This is a bit tricky: If we need to relink vmlinux, we want -# the version number incremented, which means recompile init/version.o -# and relink init/init.o. However, we cannot do this during the -# normal descending-into-subdirs phase, since at that time -# we cannot yet know if we will need to relink vmlinux. -# So we descend into init/ inside the rule for vmlinux again. -head-y += $(HEAD) -vmlinux-objs := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(net-y) - -quiet_cmd_vmlinux__ = LD $@ -define cmd_vmlinux__ - $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) $(head-y) $(init-y) \ - --start-group \ - $(core-y) \ - $(libs-y) \ - $(drivers-y) \ - $(net-y) \ - --end-group \ - $(filter .tmp_kallsyms%,$^) \ - -o $@ -endef +define rule_vmlinux__ + $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version)) -# set -e makes the rule exit immediately on error + $(call cmd,vmlinux__) + $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd -define rule_vmlinux__ - +set -e; \ - $(if $(filter .tmp_kallsyms%,$^),, \ - echo ' GEN .version'; \ - . $(srctree)/scripts/mkversion > .tmp_version; \ - mv -f .tmp_version .version; \ - $(MAKE) $(build)=init; \ - ) \ - $(if $($(quiet)cmd_vmlinux__), \ - echo ' $($(quiet)cmd_vmlinux__)' &&) \ - $(cmd_vmlinux__); \ - echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd + $(Q)$(if $($(quiet)cmd_sysmap), \ + echo ' $($(quiet)cmd_sysmap) System.map' &&) \ + $(cmd_sysmap) $@ System.map; \ + if [ $$? -ne 0 ]; then \ + rm -f $@; \ + /bin/false; \ + fi; + $(verify_kallsyms) endef -do_system_map = $(NM) $(1) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(2) - -LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s - -# Generate section listing all symbols and add it into vmlinux -# It's a three stage process: -# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is -# empty -# Running kallsyms on that gives us .tmp_kallsyms1.o with -# the right size -# o .tmp_vmlinux2 now has a __kallsyms section of the right size, -# but due to the added section, some addresses have shifted -# From here, we generate a correct .tmp_kallsyms2.o -# o The correct .tmp_kallsyms2.o is linked into the final vmlinux. -# o Verify that the System.map from vmlinux matches the map from -# .tmp_vmlinux2, just in case we did not generate kallsyms correctly. -# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using -# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a -# temporary bypass to allow the kernel to be built while the -# maintainers work out what went wrong with kallsyms. ifdef CONFIG_KALLSYMS +# Generate section listing all symbols and add it into vmlinux $(kallsyms.o) +# It's a three stage process: +# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is +# empty +# Running kallsyms on that gives us .tmp_kallsyms1.o with +# the right size - vmlinux version (uname -v) is updated during this step +# o .tmp_vmlinux2 now has a __kallsyms section of the right size, +# but due to the added section, some addresses have shifted. +# From here, we generate a correct .tmp_kallsyms2.o +# o The correct .tmp_kallsyms2.o is linked into the final vmlinux. +# o Verify that the System.map from vmlinux matches the map from +# .tmp_vmlinux2, just in case we did not generate kallsyms correctly. +# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using +# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a +# temporary bypass to allow the kernel to be built while the +# maintainers work out what went wrong with kallsyms. ifdef CONFIG_KALLSYMS_EXTRA_PASS last_kallsyms := 3 @@ -569,47 +673,58 @@ endif kallsyms.o := .tmp_kallsyms$(last_kallsyms).o -define rule_verify_kallsyms - @$(call do_system_map, .tmp_vmlinux$(last_kallsyms), .tmp_System.map) - @cmp -s System.map .tmp_System.map || \ - (echo Inconsistent kallsyms data, try setting CONFIG_KALLSYMS_EXTRA_PASS ; rm .tmp_kallsyms* ; false) +define verify_kallsyms + $(Q)$(if $($(quiet)cmd_sysmap), \ + echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \ + $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map + $(Q)cmp -s System.map .tmp_System.map || \ + (echo Inconsistent kallsyms data; \ + echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \ + rm .tmp_kallsyms* ; /bin/false ) endef +# Update vmlinux version before link +# Use + in front of this rule to silent warning about make -j1 +cmd_ksym_ld = $(cmd_vmlinux__) +define rule_ksym_ld + +$(call cmd,vmlinux_version) + $(call cmd,vmlinux__) + $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd +endef + +# Generate .S file with all kernel symbols quiet_cmd_kallsyms = KSYM $@ -cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) $(foreach x,$(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ + cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \ + $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE $(call if_changed_dep,as_o_S) -.tmp_kallsyms%.S: .tmp_vmlinux% +.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS) $(call cmd,kallsyms) -.tmp_vmlinux1: $(vmlinux-objs) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE - $(call if_changed_rule,vmlinux__) +# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version +.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE + $(call if_changed_rule,ksym_ld) -.tmp_vmlinux2: $(vmlinux-objs) .tmp_kallsyms1.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE - $(call if_changed_rule,vmlinux__) +.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE + $(call if_changed,vmlinux__) -.tmp_vmlinux3: $(vmlinux-objs) .tmp_kallsyms2.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE - $(call if_changed_rule,vmlinux__) +.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE + $(call if_changed,vmlinux__) -endif +# Needs to visit scripts/ before $(KALLSYMS) can be used. +$(KALLSYMS): scripts ; -# Finally the vmlinux rule +endif # ifdef CONFIG_KALLSYMS -define rule_vmlinux - $(rule_vmlinux__); \ - $(call do_system_map, $@, System.map) - $(rule_verify_kallsyms) -endef - -vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE - $(call if_changed_rule,vmlinux) - -# The actual objects are generated when descending, -# make sure no implicit rule kicks in +# vmlinux image - including updated kernel symbols +vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE + $(call if_changed_rule,vmlinux__) -$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ; +# The actual objects are generated when descending, +# make sure no implicit rule kicks in +$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; # Handle descending into subdirectories listed in $(vmlinux-dirs) # Preset locale variables to speed up the build process. Limit locale @@ -628,22 +743,12 @@ $(vmlinux-dirs): prepare-all scripts .PHONY: prepare-all prepare prepare0 prepare1 prepare2 -# prepare 2 generate Makefile to be placed in output directory, if -# using a seperate output directory. This allows convinient use -# of make in output directory -prepare2: - $(Q)if [ ! $(srctree) -ef $(objtree) ]; then \ - $(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ - $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \ - > $(objtree)/Makefile; \ - fi - -# prepare1 is used to check if we are building in a separate output directory, +# prepare2 is used to check if we are building in a separate output directory, # and if so do: # 1) Check that make has not been executed in the kernel src $(srctree) # 2) Create the include2 directory, used for the second asm symlink -prepare1: prepare2 +prepare2: ifneq ($(KBUILD_SRC),) @echo ' Using $(srctree) as source for kernel' $(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \ @@ -655,6 +760,9 @@ ifneq ($(KBUILD_SRC),) $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm endif +# prepare1 creates a makefile if using a separate output directory +prepare1: prepare2 outputmakefile + prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER ifneq ($(KBUILD_MODULES),) $(Q)rm -rf $(MODVERDIR) @@ -667,7 +775,7 @@ prepare-all: prepare0 prepare # Leave this as default for preprocessing vmlinux.lds.S, which is now # done in arch/$(ARCH)/kernel/Makefile -export AFLAGS_vmlinux.lds.o += -P -C -U$(ARCH) +export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) # Single targets # --------------------------------------------------------------------------- @@ -706,8 +814,8 @@ include/config/MARKER: include/linux/autoconf.h # Generate some files # --------------------------------------------------------------------------- -# version.h changes when $(KERNELRELEASE) etc change, as defined in -# this Makefile +# KERNELRELEASE can change from a few different places, meaning version.h +# needs to be updated, so this check is forced on all builds uts_len := 64 @@ -722,7 +830,7 @@ define filechk_version.h ) endef -include/linux/version.h: Makefile +include/linux/version.h: $(srctree)/Makefile FORCE $(call filechk,version.h) # --------------------------------------------------------------------------- @@ -922,7 +1030,13 @@ help: @echo ' rpm - Build a kernel as an RPM package' @echo ' tags/TAGS - Generate tags file for editors' @echo ' cscope - Generate cscope index' + @echo '' + @echo 'Static analysers' + @echo ' buildcheck - List dangling references to vmlinux discarded sections' + @echo ' and init sections from non-init sections' @echo ' checkstack - Generate a list of stack hogs' + @echo ' namespacecheck - Name space analysis on compiled kernel' + @echo '' @echo 'Kernel packaging:' @$(MAKE) -f $(package-dir)/Makefile help @echo '' @@ -940,7 +1054,8 @@ help: @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' @echo ' make O=dir [targets] Locate all output files in "dir", including .config' - @echo ' make C=1 [targets] Check all c source with checker tool' + @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK (sparse)' @echo '' @echo 'Execute "make" or "make all" to build all targets marked with [*] ' @echo 'For further info see the ./README file' @@ -1081,8 +1196,11 @@ versioncheck: | xargs $(PERL) -w scripts/checkversion.pl buildcheck: - $(PERL) scripts/reference_discarded.pl - $(PERL) scripts/reference_init.pl + $(PERL) $(srctree)/scripts/reference_discarded.pl + $(PERL) $(srctree)/scripts/reference_init.pl + +namespacecheck: + $(PERL) $(srctree)/scripts/namespace.pl endif #ifeq ($(config-targets),1) endif #ifeq ($(mixed-targets),1) @@ -1119,13 +1237,22 @@ ifneq ($(cmd_files),) include $(cmd_files) endif +# Execute command and generate cmd file +if_changed = $(if $(strip $? \ + $(filter-out $(cmd_$(1)),$(cmd_$@))\ + $(filter-out $(cmd_$@),$(cmd_$(1)))),\ + @set -e; \ + $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \ + $(cmd_$(1)); \ + echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd) + + # execute the command and also postprocess generated .d dependencies # file - if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\ $(filter-out $(cmd_$(1)),$(cmd_$@))\ $(filter-out $(cmd_$@),$(cmd_$(1)))),\ - @set -e; \ + $(Q)set -e; \ $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \ $(cmd_$(1)); \ scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \ @@ -1139,7 +1266,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\ if_changed_rule = $(if $(strip $? \ $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\ $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\ - @$(rule_$(1))) + $(Q)$(rule_$(1))) # If quiet is set, only print short version of command diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index e1f20ca1c..e2d54f5cf 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -32,6 +32,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default n + source "init/Kconfig" @@ -462,11 +466,6 @@ config ALPHA_SRM If unsure, say N. -config EARLY_PRINTK - bool - depends on ALPHA_GENERIC || ALPHA_SRM - default y - config EISA bool depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE @@ -593,104 +592,7 @@ source "fs/Kconfig" source "arch/alpha/oprofile/Kconfig" -menu "Kernel hacking" - -config ALPHA_LEGACY_START_ADDRESS - bool "Legacy kernel start address" - depends on ALPHA_GENERIC - default n - ---help--- - The 2.4 kernel changed the kernel start address from 0x310000 - to 0x810000 to make room for the Wildfire's larger SRM console. - Recent consoles on Titan and Marvel machines also require the - extra room. - - 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. - - Say Y if you have a broken bootloader. Say N if you do not, or if - you wish to run on Wildfire, Titan, or Marvel. - -config ALPHA_LEGACY_START_ADDRESS - bool - depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE - default y - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config MATHEMU - tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP - default y if !DEBUG_KERNEL || SMP - help - This option is required for IEEE compliant floating point arithmetic - on the Alpha. The only time you would ever not say Y is to say M in - order to debug the code. Say Y unless you know what you are doing. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_RWLOCK - bool "Read-write spinlock debugging" - depends on DEBUG_KERNEL - help - If you say Y here then read-write lock processing will count how many - times it has tried to get the lock and issue an error message after - too many attempts. If you suspect a rwlock problem or a kernel - hacker asks for this option then say Y. Otherwise say N. - -config DEBUG_SEMAPHORE - bool "Semaphore debugging" - depends on DEBUG_KERNEL - help - If you say Y here then semaphore processing will issue lots of - verbose debugging messages. If you suspect a semaphore problem or a - kernel hacker asks for this option then say Y. Otherwise say N. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -endmenu +source "arch/alpha/Kconfig.debug" source "security/Kconfig" diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 0337f5f0d..22ebfb2be 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -11,7 +11,7 @@ NM := $(NM) -B LDFLAGS_vmlinux := -static -N #-relax -CHECK := $(CHECK) -D__alpha__=1 +CHECKFLAGS += -D__alpha__ -m64 cflags-y := -pipe -mno-fp-regs -ffixed-8 # Determine if we can use the BWX instructions with GAS. @@ -22,15 +22,11 @@ $(error The assembler '$(AS)' does not support the BWX instruction) endif # Determine if GCC understands the -mcpu= option. -have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) - -have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) - -have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) - -have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) - -have_msmall_data := $(shell if $(CC) -msmall-data -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) +have_mcpu := $(call cc-option-yn, -mcpu=ev5) +have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56) +have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6) +have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67) +have_msmall_data := $(call cc-option-yn, -msmall-data) cflags-$(have_msmall_data) += -msmall-data diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile index e30945095..e1ae14cd2 100644 --- a/arch/alpha/boot/Makefile +++ b/arch/alpha/boot/Makefile @@ -8,7 +8,7 @@ # Copyright (C) 1994 by Linus Torvalds # -host-progs := tools/mkbb tools/objstrip +hostprogs-y := tools/mkbb tools/objstrip targets := vmlinux.gz vmlinux \ vmlinux.nh tools/lxboot tools/bootlx tools/bootph \ tools/bootpzh bootloader bootpheader bootpzheader diff --git a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds index 6643ae256..31c081ce1 100644 --- a/arch/alpha/boot/bootloader.lds +++ b/arch/alpha/boot/bootloader.lds @@ -1,5 +1,6 @@ OUTPUT_FORMAT("elf64-alpha") ENTRY(__start) +printk = srm_printk; SECTIONS { . = 0x20000000; diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c index f5ab2a4cb..ec53c28e3 100644 --- a/arch/alpha/boot/bootp.c +++ b/arch/alpha/boot/bootp.c @@ -26,6 +26,8 @@ extern unsigned long switch_to_osf_pal(unsigned long nr, struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, unsigned long *vptb); +extern void move_stack(unsigned long new_stack); + struct hwrpb_struct *hwrpb = INIT_HWRPB; static struct pcb_struct pcb_va[1]; @@ -118,12 +120,10 @@ static inline void runkernel(void) { __asm__ __volatile__( - "bis %1,%1,$30\n\t" "bis %0,%0,$27\n\t" "jmp ($27)" : /* no outputs: it doesn't even return */ - : "r" (START_ADDR), - "r" (PAGE_SIZE + INIT_STACK)); + : "r" (START_ADDR)); } extern char _end; @@ -147,9 +147,7 @@ start_kernel(void) */ static long nbytes; static char envval[256] __attribute__((aligned(8))); -#ifdef INITRD_IMAGE_SIZE static unsigned long initrd_start; -#endif srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n"); if (INIT_HWRPB->pagesize != 8192) { @@ -164,13 +162,20 @@ start_kernel(void) } pal_init(); -#ifdef INITRD_IMAGE_SIZE /* The initrd must be page-aligned. See below for the cause of the magic number 5. */ - initrd_start = ((START_ADDR + 5*KERNEL_SIZE) | (PAGE_SIZE-1)) + 1; + initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) | + (PAGE_SIZE-1)) + 1; +#ifdef INITRD_IMAGE_SIZE srm_printk("Initrd positioned at %#lx\n", initrd_start); #endif + /* + * Move the stack to a safe place to ensure it won't be + * overwritten by kernel image. + */ + move_stack(initrd_start - PAGE_SIZE); + nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval)); if (nbytes < 0 || nbytes >= sizeof(envval)) { nbytes = 0; diff --git a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c index e0d808f4e..a6657f2cf 100644 --- a/arch/alpha/boot/bootpz.c +++ b/arch/alpha/boot/bootpz.c @@ -41,9 +41,6 @@ #undef DEBUG_ADDRESSES #undef DEBUG_LAST_STEPS -#define DEBUG_SP(x) \ - {register long sp asm("30"); srm_printk("%s (sp=%lx)\n", x, sp);} - extern unsigned long switch_to_osf_pal(unsigned long nr, struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa, unsigned long *vptb); @@ -51,6 +48,8 @@ extern unsigned long switch_to_osf_pal(unsigned long nr, extern int decompress_kernel(void* destination, void *source, size_t ksize, size_t kzsize); +extern void move_stack(unsigned long new_stack); + struct hwrpb_struct *hwrpb = INIT_HWRPB; static struct pcb_struct pcb_va[1]; @@ -163,12 +162,10 @@ static inline void runkernel(void) { __asm__ __volatile__( - "bis %1,%1,$30\n\t" "bis %0,%0,$27\n\t" "jmp ($27)" : /* no outputs: it doesn't even return */ - : "r" (START_ADDR), - "r" (PAGE_SIZE + INIT_STACK)); + : "r" (START_ADDR)); } /* Must record the SP (it is virtual) on entry, so we can make sure @@ -253,7 +250,9 @@ extern char _end; for "bootmem" anyway. */ #define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END) -#define K_INITRD_START NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE) +/* Reserve one page below INITRD for the new stack. */ +#define K_INITRD_START \ + NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE) #define K_COPY_IMAGE_END \ (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE) #define K_COPY_IMAGE_SIZE \ @@ -419,8 +418,7 @@ start_kernel(void) initrd_image_start, INITRD_IMAGE_SIZE); #endif - memcpy((void *)initrd_image_start, - (void *)V_INITRD_START, + memcpy((void *)initrd_image_start, (void *)V_INITRD_START, INITRD_IMAGE_SIZE); #endif /* INITRD_IMAGE_SIZE */ @@ -436,9 +434,14 @@ start_kernel(void) K_KERNEL_IMAGE_START, (unsigned)KERNEL_SIZE); #endif + /* + * Move the stack to a safe place to ensure it won't be + * overwritten by kernel image. + */ + move_stack(initrd_image_start - PAGE_SIZE); + memcpy((void *)K_KERNEL_IMAGE_START, - (void *)uncompressed_image_start, - KERNEL_SIZE); + (void *)uncompressed_image_start, KERNEL_SIZE); } /* Clear the zero page, then move the argument list in. */ diff --git a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S index e3159d69d..f3d98089b 100644 --- a/arch/alpha/boot/head.S +++ b/arch/alpha/boot/head.S @@ -100,3 +100,24 @@ halt: .prologue 0 call_pal PAL_halt .end halt + +/* $16 - new stack page */ + .align 3 + .globl move_stack + .ent move_stack +move_stack: + .prologue 0 + lda $0, 0x1fff($31) + and $0, $30, $1 /* Stack offset */ + or $1, $16, $16 /* New stack pointer */ + mov $30, $1 + mov $16, $2 +1: ldq $3, 0($1) /* Move the stack */ + addq $1, 8, $1 + stq $3, 0($2) + and $0, $1, $4 + addq $2, 8, $2 + bne $4, 1b + mov $16, $30 + ret ($26) + .end move_stack diff --git a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c index b8119502f..1d65adf56 100644 --- a/arch/alpha/boot/misc.c +++ b/arch/alpha/boot/misc.c @@ -205,15 +205,3 @@ decompress_kernel(void *output_start, /* puts(" done, booting the kernel.\n"); */ return output_ptr; } - -/* dummy-up printk */ -asmlinkage int printk(const char *fmt, ...) -{ - va_list args; - long ret; - - va_start(args, fmt); - ret = srm_printk(fmt, args); - va_end(args); - return ret; -} diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index da929a2ae..6ac8d4a7d 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -1,38 +1,48 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.9-rc2 +# Sat Sep 25 15:38:35 2004 # CONFIG_ALPHA=y CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_ISA_DMA=y +# CONFIG_GENERIC_IOMAP is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -84,7 +94,6 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_ALPHA_CORE_AGP=y CONFIG_ALPHA_BROKEN_IRQ_MASK=y -CONFIG_EARLY_PRINTK=y CONFIG_EISA=y # CONFIG_SMP is not set # CONFIG_DISCONTIGMEM is not set @@ -108,6 +117,8 @@ CONFIG_BINFMT_ELF=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # @@ -130,7 +141,6 @@ CONFIG_PNP=y # Protocols # CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set # # Block devices @@ -144,7 +154,7 @@ CONFIG_BLK_DEV_FD=y CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set # @@ -157,9 +167,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -181,7 +191,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set @@ -203,6 +212,7 @@ CONFIG_BLK_DEV_CY82C693=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set @@ -229,7 +239,6 @@ CONFIG_BLK_DEV_SR_VENDOR=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -243,6 +252,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA1542 is not set @@ -252,18 +262,16 @@ CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 CONFIG_AIC7XXX_RESET_DELAY_MS=5000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set # CONFIG_AIC7XXX_DEBUG_ENABLE is not set CONFIG_AIC7XXX_DEBUG_MASK=0 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA 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 @@ -276,6 +284,7 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set @@ -320,6 +329,7 @@ CONFIG_SCSI_QLA2XXX=y # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -342,19 +352,17 @@ CONFIG_IP_MULTICAST=y # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -CONFIG_INET_ECN=y # CONFIG_SYN_COOKIES is not set CONFIG_INET_AH=m CONFIG_INET_ESP=m # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set # # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -362,6 +370,8 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m # CONFIG_IP_NF_TFTP is not set @@ -386,8 +396,15 @@ CONFIG_IP_NF_IPTABLES=m # CONFIG_IP_NF_MATCH_STATE is not set # CONFIG_IP_NF_MATCH_CONNTRACK is not set # CONFIG_IP_NF_MATCH_OWNER is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +# CONFIG_IP_NF_MATCH_SCTP is not set +# CONFIG_IP_NF_MATCH_COMMENT is not set CONFIG_IP_NF_FILTER=m # CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_LOG is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +# CONFIG_IP_NF_TARGET_TCPMSS is not set CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -399,9 +416,7 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m # CONFIG_IP_NF_MANGLE is not set -# CONFIG_IP_NF_TARGET_LOG is not set -# CONFIG_IP_NF_TARGET_ULOG is not set -# CONFIG_IP_NF_TARGET_TCPMSS is not set +# CONFIG_IP_NF_RAW is not set # CONFIG_IP_NF_ARPTABLES is not set CONFIG_IP_NF_COMPAT_IPCHAINS=y CONFIG_XFRM=y @@ -410,10 +425,11 @@ CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -428,17 +444,18 @@ CONFIG_VLAN_8021Q=m # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -446,6 +463,11 @@ CONFIG_DUMMY=m # CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + # # Ethernet (10 or 100Mbit) # @@ -506,6 +528,7 @@ CONFIG_NET_PCI=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_NET_POCKET is not set # @@ -518,7 +541,6 @@ CONFIG_NET_PCI=y # CONFIG_HAMACHI is not set CONFIG_YELLOWFIN=y # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -526,45 +548,29 @@ CONFIG_YELLOWFIN=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -603,6 +609,7 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -648,7 +655,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -677,6 +683,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -728,6 +739,7 @@ CONFIG_EXT2_FS=y CONFIG_REISERFS_FS=m # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set # CONFIG_JFS_FS is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set @@ -750,6 +762,8 @@ CONFIG_ISO9660_FS=y CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -757,6 +771,7 @@ CONFIG_VFAT_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y @@ -796,11 +811,11 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=m # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -838,6 +853,7 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -861,15 +877,16 @@ CONFIG_NLS_CODEPAGE_437=y # # Kernel hacking # -CONFIG_ALPHA_LEGACY_START_ADDRESS=y CONFIG_DEBUG_KERNEL=y -CONFIG_MATHEMU=y -# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_INFO=y +CONFIG_EARLY_PRINTK=y # CONFIG_DEBUG_RWLOCK is not set # CONFIG_DEBUG_SEMAPHORE is not set -CONFIG_DEBUG_INFO=y +CONFIG_ALPHA_LEGACY_START_ADDRESS=y +CONFIG_MATHEMU=y # # Security options @@ -887,6 +904,7 @@ CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WHIRLPOOL is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set @@ -894,11 +912,17 @@ CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_AES is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_TEST is not set # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 73202af82..ab6fa54b3 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -2,13 +2,13 @@ # Makefile for the linux kernel. # -extra-y := head.o vmlinux.lds.s +extra-y := head.o vmlinux.lds EXTRA_AFLAGS := $(CFLAGS) EXTRA_CFLAGS := -Werror -Wno-sign-compare obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \ - alpha_ksyms.o systbls.o err_common.o + alpha_ksyms.o systbls.o err_common.o io.o obj-$(CONFIG_VGA_HOSE) += console.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index c901914a3..64ba44928 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -67,36 +68,6 @@ EXPORT_SYMBOL(alpha_using_srm); #endif /* CONFIG_ALPHA_GENERIC */ /* platform dependent support */ -EXPORT_SYMBOL(_inb); -EXPORT_SYMBOL(_inw); -EXPORT_SYMBOL(_inl); -EXPORT_SYMBOL(_outb); -EXPORT_SYMBOL(_outw); -EXPORT_SYMBOL(_outl); -EXPORT_SYMBOL(_readb); -EXPORT_SYMBOL(_readw); -EXPORT_SYMBOL(_readl); -EXPORT_SYMBOL(_writeb); -EXPORT_SYMBOL(_writew); -EXPORT_SYMBOL(_writel); -EXPORT_SYMBOL(___raw_readb); -EXPORT_SYMBOL(___raw_readw); -EXPORT_SYMBOL(___raw_readl); -EXPORT_SYMBOL(___raw_readq); -EXPORT_SYMBOL(___raw_writeb); -EXPORT_SYMBOL(___raw_writew); -EXPORT_SYMBOL(___raw_writel); -EXPORT_SYMBOL(___raw_writeq); -EXPORT_SYMBOL(_memcpy_fromio); -EXPORT_SYMBOL(_memcpy_toio); -EXPORT_SYMBOL(_memset_c_io); -EXPORT_SYMBOL(scr_memcpyw); -EXPORT_SYMBOL(insb); -EXPORT_SYMBOL(insw); -EXPORT_SYMBOL(insl); -EXPORT_SYMBOL(outsb); -EXPORT_SYMBOL(outsw); -EXPORT_SYMBOL(outsl); EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcpy); @@ -136,7 +107,9 @@ EXPORT_SYMBOL(pci_dac_dma_supported); EXPORT_SYMBOL(pci_dac_page_to_dma); EXPORT_SYMBOL(pci_dac_dma_to_page); EXPORT_SYMBOL(pci_dac_dma_to_offset); +EXPORT_SYMBOL(alpha_gendev_to_pci); #endif +EXPORT_SYMBOL(dma_set_mask); EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_elf_thread); @@ -183,8 +156,8 @@ EXPORT_SYMBOL(__min_ipl); /* * The following are specially called from the uaccess assembly stubs. */ -EXPORT_SYMBOL_NOVERS(__copy_user); -EXPORT_SYMBOL_NOVERS(__do_clear_user); +EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(__do_clear_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__strnlen_user); @@ -212,7 +185,7 @@ EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(smp_num_cpus); EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(smp_call_function_on_cpu); -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #ifdef CONFIG_DEBUG_SPINLOCK EXPORT_SYMBOL(_raw_spin_unlock); EXPORT_SYMBOL(debug_spin_lock); @@ -243,17 +216,17 @@ EXPORT_SYMBOL(rtc_lock); */ # undef memcpy # undef memset -EXPORT_SYMBOL_NOVERS(__divl); -EXPORT_SYMBOL_NOVERS(__divlu); -EXPORT_SYMBOL_NOVERS(__divq); -EXPORT_SYMBOL_NOVERS(__divqu); -EXPORT_SYMBOL_NOVERS(__reml); -EXPORT_SYMBOL_NOVERS(__remlu); -EXPORT_SYMBOL_NOVERS(__remq); -EXPORT_SYMBOL_NOVERS(__remqu); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memchr); +EXPORT_SYMBOL(__divl); +EXPORT_SYMBOL(__divlu); +EXPORT_SYMBOL(__divq); +EXPORT_SYMBOL(__divqu); +EXPORT_SYMBOL(__reml); +EXPORT_SYMBOL(__remlu); +EXPORT_SYMBOL(__remq); +EXPORT_SYMBOL(__remqu); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(get_wchan); diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c index 254ab65d3..cb3e739fb 100644 --- a/arch/alpha/kernel/console.c +++ b/arch/alpha/kernel/console.c @@ -47,7 +47,7 @@ locate_and_init_vga(void *(*sel_func)(void *, void *)) if (!sel_func) sel_func = (void *)default_vga_hose_select; - for(dev=NULL; (dev=pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) { + for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) { if (!hose) hose = dev->sysdata; else hose = sel_func(hose, dev->sysdata); } diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c index f5245ab2f..fd5630643 100644 --- a/arch/alpha/kernel/core_cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -282,7 +282,7 @@ void cia_pci_tbi_try2(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) { - unsigned long bus_addr; + void __iomem *bus_addr; int ctrl; /* Put the chip into PCI loopback mode. */ @@ -351,7 +351,7 @@ verify_tb_operation(void) struct pci_iommu_arena *arena = pci_isa_hose->sg_isa; int ctrl, addr0, tag0, pte0, data0; int temp, use_tbia_try2 = 0; - unsigned long bus_addr; + void __iomem *bus_addr; /* pyxis -- tbia is broken */ if (pci_isa_hose->dense_io_base) diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c index 50b7dd3d5..138d497d1 100644 --- a/arch/alpha/kernel/core_irongate.c +++ b/arch/alpha/kernel/core_irongate.c @@ -310,7 +310,7 @@ irongate_init_arch(void) #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) #define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)]) -unsigned long +void __iomem * irongate_ioremap(unsigned long addr, unsigned long size) { struct vm_struct *area; @@ -320,7 +320,7 @@ irongate_ioremap(unsigned long addr, unsigned long size) unsigned long gart_bus_addr; if (!alpha_agpgart_size) - return addr + IRONGATE_MEM; + return (void __iomem *)(addr + IRONGATE_MEM); gart_bus_addr = (unsigned long)IRONGATE0->bar0 & PCI_BASE_ADDRESS_MEM_MASK; @@ -339,7 +339,7 @@ irongate_ioremap(unsigned long addr, unsigned long size) /* * Not found - assume legacy ioremap */ - return addr + IRONGATE_MEM; + return (void __iomem *)(addr + IRONGATE_MEM); } while(0); mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 & @@ -353,7 +353,7 @@ irongate_ioremap(unsigned long addr, unsigned long size) if (addr & ~PAGE_MASK) { printk("AGP ioremap failed... addr not page aligned (0x%lx)\n", addr); - return addr + IRONGATE_MEM; + return (void __iomem *)(addr + IRONGATE_MEM); } last = addr + size - 1; size = PAGE_ALIGN(last) - addr; @@ -378,7 +378,7 @@ irongate_ioremap(unsigned long addr, unsigned long size) * Map it */ area = get_vm_area(size, VM_IOREMAP); - if (!area) return (unsigned long)NULL; + if (!area) return NULL; for(baddr = addr, vaddr = (unsigned long)area->addr; baddr <= last; @@ -391,7 +391,7 @@ irongate_ioremap(unsigned long addr, unsigned long size) pte, PAGE_SIZE, 0)) { printk("AGP ioremap: FAILED to map...\n"); vfree(area->addr); - return (unsigned long)NULL; + return NULL; } } @@ -402,13 +402,15 @@ irongate_ioremap(unsigned long addr, unsigned long size) printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n", addr, size, vaddr); #endif - return vaddr; + return (void __iomem *)vaddr; } void -irongate_iounmap(unsigned long addr) +irongate_iounmap(volatile void __iomem *xaddr) { + unsigned long addr = (unsigned long) xaddr; if (((long)addr >> 41) == -2) return; /* kseg map, nothing to do */ - if (addr) return vfree((void *)(PAGE_MASK & addr)); + if (addr) + return vfree((void *)(PAGE_MASK & addr)); } diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c index 9bde638e8..bb4fe0498 100644 --- a/arch/alpha/kernel/core_marvel.c +++ b/arch/alpha/kernel/core_marvel.c @@ -610,11 +610,84 @@ marvel_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) csrs->POx_SG_TBIA.csr; } + + +/* + * RTC Support + */ +struct marvel_rtc_access_info { + unsigned long function; + unsigned long index; + unsigned long data; +}; + +static void +__marvel_access_rtc(void *info) +{ + struct marvel_rtc_access_info *rtc_access = info; + + register unsigned long __r0 __asm__("$0"); + register unsigned long __r16 __asm__("$16") = rtc_access->function; + register unsigned long __r17 __asm__("$17") = rtc_access->index; + register unsigned long __r18 __asm__("$18") = rtc_access->data; + + __asm__ __volatile__( + "call_pal %4 # cserve rtc" + : "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0) + : "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18) + : "$1", "$22", "$23", "$24", "$25"); + + rtc_access->data = __r0; +} + +static u8 +__marvel_rtc_io(u8 b, unsigned long addr, int write) +{ + static u8 index = 0; + + struct marvel_rtc_access_info rtc_access; + u8 ret = 0; + + switch(addr) { + case 0x70: /* RTC_PORT(0) */ + if (write) index = b; + ret = index; + break; + + case 0x71: /* RTC_PORT(1) */ + rtc_access.index = index; + rtc_access.data = BCD_TO_BIN(b); + rtc_access.function = 0x48 + !write; /* GET/PUT_TOY */ + +#ifdef CONFIG_SMP + if (smp_processor_id() != boot_cpuid) + smp_call_function_on_cpu(__marvel_access_rtc, + &rtc_access, 1, 1, + cpumask_of_cpu(boot_cpuid)); + else + __marvel_access_rtc(&rtc_access); +#else + __marvel_access_rtc(&rtc_access); +#endif + ret = BIN_TO_BCD(rtc_access.data); + break; + + default: + printk(KERN_WARNING "Illegal RTC port %lx\n", addr); + break; + } + + return ret; +} + /* * IO map support. */ -unsigned long + +#define __marvel_is_mem_vga(a) (((a) >= 0xa0000) && ((a) <= 0xc0000)) + +void __iomem * marvel_ioremap(unsigned long addr, unsigned long size) { struct pci_controller *hose; @@ -633,8 +706,6 @@ marvel_ioremap(unsigned long addr, unsigned long size) } #endif - if (!marvel_is_ioaddr(addr)) return 0UL; - /* * Find the hose. */ @@ -643,7 +714,7 @@ marvel_ioremap(unsigned long addr, unsigned long size) break; } if (!hose) - return 0UL; + return NULL; /* * We have the hose - calculate the bus limits. @@ -655,15 +726,17 @@ marvel_ioremap(unsigned long addr, unsigned long size) * Is it direct-mapped? */ if ((baddr >= __direct_map_base) && - ((baddr + size - 1) < __direct_map_base + __direct_map_size)) - return IDENT_ADDR | (baddr - __direct_map_base); + ((baddr + size - 1) < __direct_map_base + __direct_map_size)) { + addr = IDENT_ADDR | (baddr - __direct_map_base); + return (void __iomem *) addr; + } /* * Check the scatter-gather arena. */ if (hose->sg_pci && baddr >= (unsigned long)hose->sg_pci->dma_base && - last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){ + last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size) { /* * Adjust the limits (mappings must be page aligned) @@ -677,7 +750,9 @@ marvel_ioremap(unsigned long addr, unsigned long size) * Map it. */ area = get_vm_area(size, VM_IOREMAP); - if (!area) return (unsigned long)NULL; + if (!area) + return NULL; + ptes = hose->sg_pci->ptes; for (vaddr = (unsigned long)area->addr; baddr <= last; @@ -686,7 +761,7 @@ marvel_ioremap(unsigned long addr, unsigned long size) if (!(pfn & 1)) { printk("ioremap failed... pte not valid...\n"); vfree(area->addr); - return 0UL; + return NULL; } pfn >>= 1; /* make it a true pfn */ @@ -695,7 +770,7 @@ marvel_ioremap(unsigned long addr, unsigned long size) PAGE_SIZE, 0)) { printk("FAILED to map...\n"); vfree(area->addr); - return 0UL; + return NULL; } } @@ -703,101 +778,81 @@ marvel_ioremap(unsigned long addr, unsigned long size) vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK); - return vaddr; + return (void __iomem *) vaddr; } - /* - * Not found - assume legacy ioremap. - */ - return addr; + return NULL; } void -marvel_iounmap(unsigned long addr) +marvel_iounmap(volatile void __iomem *xaddr) { - if (((long)addr >> 41) == -2) - return; /* kseg map, nothing to do */ - if (addr) + unsigned long addr = (unsigned long) xaddr; + if (addr >= VMALLOC_START) vfree((void *)(PAGE_MASK & addr)); } -#ifndef CONFIG_ALPHA_GENERIC -EXPORT_SYMBOL(marvel_ioremap); -EXPORT_SYMBOL(marvel_iounmap); -#endif - - -/* - * RTC Support - */ -struct marvel_rtc_access_info { - unsigned long function; - unsigned long index; - unsigned long data; -}; - -static void -__marvel_access_rtc(void *info) +int +marvel_is_mmio(const volatile void __iomem *xaddr) { - struct marvel_rtc_access_info *rtc_access = info; - - register unsigned long __r0 __asm__("$0"); - register unsigned long __r16 __asm__("$16") = rtc_access->function; - register unsigned long __r17 __asm__("$17") = rtc_access->index; - register unsigned long __r18 __asm__("$18") = rtc_access->data; - - __asm__ __volatile__( - "call_pal %4 # cserve rtc" - : "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0) - : "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18) - : "$1", "$22", "$23", "$24", "$25"); + unsigned long addr = (unsigned long) xaddr; - rtc_access->data = __r0; + if (addr >= VMALLOC_START) + return 1; + else + return (addr & 0xFF000000UL) == 0; } -u8 -__marvel_rtc_io(int write, u8 b, unsigned long addr) -{ - struct marvel_rtc_access_info rtc_access = {0, }; - static u8 index = 0; - u8 ret = 0; - - switch(addr) { - case 0x70: /* RTC_PORT(0) */ - if (write) index = b; - ret = index; - break; +#define __marvel_is_port_vga(a) \ + (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3)) +#define __marvel_is_port_kbd(a) (((a) == 0x60) || ((a) == 0x64)) +#define __marvel_is_port_rtc(a) (((a) == 0x70) || ((a) == 0x71)) - case 0x71: /* RTC_PORT(1) */ - rtc_access.index = index; - rtc_access.data = BCD_TO_BIN(b); - rtc_access.function = 0x49; /* GET_TOY */ - if (write) rtc_access.function = 0x48; /* PUT_TOY */ - -#ifdef CONFIG_SMP - if (smp_processor_id() != boot_cpuid) - smp_call_function_on_cpu(__marvel_access_rtc, - &rtc_access, - 1, /* retry */ - 1, /* wait */ - 1UL << boot_cpuid); - else - __marvel_access_rtc(&rtc_access); -#else - __marvel_access_rtc(&rtc_access); +void __iomem *marvel_ioportmap (unsigned long addr) +{ + if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr)) + ; +#ifdef CONFIG_VGA_HOSE + else if (__marvel_is_port_vga (addr) && pci_vga_hose) + addr += pci_vga_hose->io_space->start; #endif - ret = BIN_TO_BCD(rtc_access.data); - - break; + else + return NULL; + return (void __iomem *)addr; +} - default: - printk(KERN_WARNING "Illegal RTC port %lx\n", addr); - break; - } +unsigned int +marvel_ioread8(void __iomem *xaddr) +{ + unsigned long addr = (unsigned long) xaddr; + if (__marvel_is_port_kbd(addr)) + return 0; + else if (__marvel_is_port_rtc(addr)) + return __marvel_rtc_io(0, addr, 0); + else + return __kernel_ldbu(*(vucp)addr); +} - return ret; +void +marvel_iowrite8(u8 b, void __iomem *xaddr) +{ + unsigned long addr = (unsigned long) xaddr; + if (__marvel_is_port_kbd(addr)) + return; + else if (__marvel_is_port_rtc(addr)) + __marvel_rtc_io(b, addr, 1); + else + __kernel_stb(b, *(vucp)addr); } +#ifndef CONFIG_ALPHA_GENERIC +EXPORT_SYMBOL(marvel_ioremap); +EXPORT_SYMBOL(marvel_iounmap); +EXPORT_SYMBOL(marvel_is_mmio); +EXPORT_SYMBOL(marvel_ioportmap); +EXPORT_SYMBOL(marvel_ioread8); +EXPORT_SYMBOL(marvel_iowrite8); +#endif /* * NUMA Support diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c index 3ddec9a87..3662fef7d 100644 --- a/arch/alpha/kernel/core_titan.c +++ b/arch/alpha/kernel/core_titan.c @@ -461,7 +461,8 @@ titan_kill_arch(int mode) /* * IO map support. */ -unsigned long + +void __iomem * titan_ioremap(unsigned long addr, unsigned long size) { int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT; @@ -487,15 +488,19 @@ titan_ioremap(unsigned long addr, unsigned long size) * Find the hose. */ for (hose = hose_head; hose; hose = hose->next) - if (hose->index == h) break; - if (!hose) return (unsigned long)NULL; + if (hose->index == h) + break; + if (!hose) + return NULL; /* * Is it direct-mapped? */ if ((baddr >= __direct_map_base) && - ((baddr + size - 1) < __direct_map_base + __direct_map_size)) - return addr - __direct_map_base + TITAN_MEM_BIAS; + ((baddr + size - 1) < __direct_map_base + __direct_map_size)) { + vaddr = addr - __direct_map_base + TITAN_MEM_BIAS; + return (void __iomem *) vaddr; + } /* * Check the scatter-gather arena. @@ -516,7 +521,9 @@ titan_ioremap(unsigned long addr, unsigned long size) * Map it */ area = get_vm_area(size, VM_IOREMAP); - if (!area) return (unsigned long)NULL; + if (!area) + return NULL; + ptes = hose->sg_pci->ptes; for (vaddr = (unsigned long)area->addr; baddr <= last; @@ -525,7 +532,7 @@ titan_ioremap(unsigned long addr, unsigned long size) if (!(pfn & 1)) { printk("ioremap failed... pte not valid...\n"); vfree(area->addr); - return (unsigned long)NULL; + return NULL; } pfn >>= 1; /* make it a true pfn */ @@ -534,35 +541,42 @@ titan_ioremap(unsigned long addr, unsigned long size) PAGE_SIZE, 0)) { printk("FAILED to map...\n"); vfree(area->addr); - return (unsigned long)NULL; + return NULL; } } flush_tlb_all(); vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK); - return vaddr; + return (void __iomem *) vaddr; } - /* - * Not found - assume legacy ioremap. - */ - return addr + TITAN_MEM_BIAS; - + return NULL; } void -titan_iounmap(unsigned long addr) +titan_iounmap(volatile void __iomem *xaddr) { - if (((long)addr >> 41) == -2) - return; /* kseg map, nothing to do */ - if (addr) + unsigned long addr = (unsigned long) xaddr; + if (addr >= VMALLOC_START) vfree((void *)(PAGE_MASK & addr)); } +int +titan_is_mmio(const volatile void __iomem *xaddr) +{ + unsigned long addr = (unsigned long) xaddr; + + if (addr >= VMALLOC_START) + return 1; + else + return (addr & 0x100000000UL) == 0; +} + #ifndef CONFIG_ALPHA_GENERIC EXPORT_SYMBOL(titan_ioremap); EXPORT_SYMBOL(titan_iounmap); +EXPORT_SYMBOL(titan_is_mmio); #endif /* diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index 897ea1a15..7e6720d45 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c @@ -177,7 +177,7 @@ titan_parse_p_perror(int which, int port, u64 perror, int print) #define TITAN__PCHIP_PERROR__CMD__S (52) #define TITAN__PCHIP_PERROR__CMD__M (0x0f) #define TITAN__PCHIP_PERROR__ADDR__S (14) -#define TITAN__PCHIP_PERROR__ADDR__M (0x1ffffffff) +#define TITAN__PCHIP_PERROR__ADDR__M (0x1fffffffful) if (!(perror & TITAN__PCHIP_PERROR__ERRMASK)) return MCHK_DISPOSITION_UNKNOWN_ERROR; diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index ee987528a..b6114f5c0 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -25,10 +25,11 @@ #include #include #include +#include +#include #include #include -#include #include /* @@ -83,6 +84,7 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ + int ret; do { if (!(action->flags & SA_INTERRUPT)) @@ -90,8 +92,9 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs, else local_irq_disable(); - status |= action->flags; - action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) @@ -288,31 +291,6 @@ irq_affinity_write_proc(struct file *file, const char __user *buffer, return full_count; } -static int -prof_cpu_mask_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int -prof_cpu_mask_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned long full_count = count, err; - cpumask_t new_value, *mask = (cpumask_t *)data; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} #endif /* CONFIG_SMP */ #define MAX_NAMELEN 10 @@ -350,14 +328,9 @@ register_irq_proc (unsigned int irq) #endif } -unsigned long prof_cpu_mask = ~0UL; - void init_irq_proc (void) { -#ifdef CONFIG_SMP - struct proc_dir_entry *entry; -#endif int i; /* create /proc/irq */ @@ -365,12 +338,7 @@ init_irq_proc (void) #ifdef CONFIG_SMP /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; + create_prof_cpu_mask(root_irq_dir); #endif /* diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h index d626a8be9..f201d8ffc 100644 --- a/arch/alpha/kernel/irq_impl.h +++ b/arch/alpha/kernel/irq_impl.h @@ -40,32 +40,3 @@ extern struct hw_interrupt_type i8259a_irq_type; extern void init_i8259a_irqs(void); extern void handle_irq(int irq, struct pt_regs * regs); - -extern unsigned long prof_cpu_mask; - -static inline void -alpha_do_profile(unsigned long pc) -{ - extern char _stext; - - if (!prof_buffer) - return; - - /* - * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. - * (default is all CPUs.) - */ - if (!((1<>= prof_shift; - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - atomic_inc((atomic_t *)&prof_buffer[pc]); -} diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h index 348597bdb..4959b7a3e 100644 --- a/arch/alpha/kernel/machvec_impl.h +++ b/arch/alpha/kernel/machvec_impl.h @@ -44,56 +44,60 @@ #define DO_DEFAULT_RTC rtc_port: 0x70 #define DO_EV4_MMU \ - max_asn: EV4_MAX_ASN, \ - mv_switch_mm: ev4_switch_mm, \ - mv_activate_mm: ev4_activate_mm, \ - mv_flush_tlb_current: ev4_flush_tlb_current, \ - mv_flush_tlb_current_page: ev4_flush_tlb_current_page + .max_asn = EV4_MAX_ASN, \ + .mv_switch_mm = ev4_switch_mm, \ + .mv_activate_mm = ev4_activate_mm, \ + .mv_flush_tlb_current = ev4_flush_tlb_current, \ + .mv_flush_tlb_current_page = ev4_flush_tlb_current_page #define DO_EV5_MMU \ - max_asn: EV5_MAX_ASN, \ - mv_switch_mm: ev5_switch_mm, \ - mv_activate_mm: ev5_activate_mm, \ - mv_flush_tlb_current: ev5_flush_tlb_current, \ - mv_flush_tlb_current_page: ev5_flush_tlb_current_page + .max_asn = EV5_MAX_ASN, \ + .mv_switch_mm = ev5_switch_mm, \ + .mv_activate_mm = ev5_activate_mm, \ + .mv_flush_tlb_current = ev5_flush_tlb_current, \ + .mv_flush_tlb_current_page = ev5_flush_tlb_current_page #define DO_EV6_MMU \ - max_asn: EV6_MAX_ASN, \ - mv_switch_mm: ev5_switch_mm, \ - mv_activate_mm: ev5_activate_mm, \ - mv_flush_tlb_current: ev5_flush_tlb_current, \ - mv_flush_tlb_current_page: ev5_flush_tlb_current_page + .max_asn = EV6_MAX_ASN, \ + .mv_switch_mm = ev5_switch_mm, \ + .mv_activate_mm = ev5_activate_mm, \ + .mv_flush_tlb_current = ev5_flush_tlb_current, \ + .mv_flush_tlb_current_page = ev5_flush_tlb_current_page #define DO_EV7_MMU \ - max_asn: EV6_MAX_ASN, \ - mv_switch_mm: ev5_switch_mm, \ - mv_activate_mm: ev5_activate_mm, \ - mv_flush_tlb_current: ev5_flush_tlb_current, \ - mv_flush_tlb_current_page: ev5_flush_tlb_current_page + .max_asn = EV6_MAX_ASN, \ + .mv_switch_mm = ev5_switch_mm, \ + .mv_activate_mm = ev5_activate_mm, \ + .mv_flush_tlb_current = ev5_flush_tlb_current, \ + .mv_flush_tlb_current_page = ev5_flush_tlb_current_page #define IO_LITE(UP,low) \ - hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \ - iack_sc: CAT(UP,_IACK_SC), \ - mv_inb: CAT(low,_inb), \ - mv_inw: CAT(low,_inw), \ - mv_inl: CAT(low,_inl), \ - mv_outb: CAT(low,_outb), \ - mv_outw: CAT(low,_outw), \ - mv_outl: CAT(low,_outl), \ - mv_readb: CAT(low,_readb), \ - mv_readw: CAT(low,_readw), \ - mv_readl: CAT(low,_readl), \ - mv_readq: CAT(low,_readq), \ - mv_writeb: CAT(low,_writeb), \ - mv_writew: CAT(low,_writew), \ - mv_writel: CAT(low,_writel), \ - mv_writeq: CAT(low,_writeq), \ - mv_ioremap: CAT(low,_ioremap), \ - mv_iounmap: CAT(low,_iounmap) \ + .hae_register = (unsigned long *) CAT(UP,_HAE_ADDRESS), \ + .iack_sc = CAT(UP,_IACK_SC), \ + .mv_ioread8 = CAT(low,_ioread8), \ + .mv_ioread16 = CAT(low,_ioread16), \ + .mv_ioread32 = CAT(low,_ioread32), \ + .mv_iowrite8 = CAT(low,_iowrite8), \ + .mv_iowrite16 = CAT(low,_iowrite16), \ + .mv_iowrite32 = CAT(low,_iowrite32), \ + .mv_readb = CAT(low,_readb), \ + .mv_readw = CAT(low,_readw), \ + .mv_readl = CAT(low,_readl), \ + .mv_readq = CAT(low,_readq), \ + .mv_writeb = CAT(low,_writeb), \ + .mv_writew = CAT(low,_writew), \ + .mv_writel = CAT(low,_writel), \ + .mv_writeq = CAT(low,_writeq), \ + .mv_ioportmap = CAT(low,_ioportmap), \ + .mv_ioremap = CAT(low,_ioremap), \ + .mv_iounmap = CAT(low,_iounmap), \ + .mv_is_ioaddr = CAT(low,_is_ioaddr), \ + .mv_is_mmio = CAT(low,_is_mmio) \ #define IO(UP,low) \ IO_LITE(UP,low), \ - pci_ops: &CAT(low,_pci_ops) + .pci_ops = &CAT(low,_pci_ops), \ + .mv_pci_tbi = CAT(low,_pci_tbi) #define DO_APECS_IO IO(APECS,apecs) #define DO_CIA_IO IO(CIA,cia) @@ -108,23 +112,8 @@ #define DO_WILDFIRE_IO IO(WILDFIRE,wildfire) #define DO_PYXIS_IO IO_LITE(CIA,cia_bwx), \ - pci_ops: &CAT(cia,_pci_ops) - -#define BUS(which) \ - mv_is_ioaddr: CAT(which,_is_ioaddr), \ - mv_pci_tbi: CAT(which,_pci_tbi) - -#define DO_APECS_BUS BUS(apecs) -#define DO_CIA_BUS BUS(cia) -#define DO_IRONGATE_BUS BUS(irongate) -#define DO_LCA_BUS BUS(lca) -#define DO_MARVEL_BUS BUS(marvel) -#define DO_MCPCIA_BUS BUS(mcpcia) -#define DO_POLARIS_BUS BUS(polaris) -#define DO_T2_BUS BUS(t2) -#define DO_TSUNAMI_BUS BUS(tsunami) -#define DO_TITAN_BUS BUS(titan) -#define DO_WILDFIRE_BUS BUS(wildfire) + .pci_ops = &cia_pci_ops, \ + .mv_pci_tbi = cia_pci_tbi /* * In a GENERIC kernel, we have lots of these vectors floating about, diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 4761ed9a4..dcad8d31d 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -91,8 +91,8 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len, * braindamage (it can't really handle filesystems where the directory * offset differences aren't the same as "d_reclen"). */ -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+3) & ~3) +#define NAME_OFFSET offsetof (struct osf_dirent, d_name) +#define ROUND_UP(x) (((x)+3) & ~3) struct osf_dirent { unsigned int d_ino; @@ -114,7 +114,7 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, { struct osf_dirent __user *dirent; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; - unsigned int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1); buf->error = -EINVAL; /* only used if we fail */ if (reclen > buf->count) @@ -723,7 +723,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, { switch (op) { case SSI_IEEE_FP_CONTROL: { - unsigned long swcr, fpcr, fex; + unsigned long swcr, fpcr; + unsigned int *state; /* * Alpha Architecture Handbook 4.7.7.3: @@ -732,22 +733,42 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, * set in the trap shadow of a software-complete insn. */ - /* Update softare trap enable bits. */ if (get_user(swcr, (unsigned long __user *)buffer)) return -EFAULT; - current_thread_info()->ieee_state - = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK) - | (swcr & IEEE_SW_MASK)); + state = ¤t_thread_info()->ieee_state; + + /* Update softare trap enable bits. */ + *state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK); + + /* Update the real fpcr. */ + fpcr = rdfpcr() & FPCR_DYN_MASK; + fpcr |= ieee_swcr_to_fpcr(swcr); + wrfpcr(fpcr); + + return 0; + } + + case SSI_IEEE_RAISE_EXCEPTION: { + unsigned long exc, swcr, fpcr, fex; + unsigned int *state; + + if (get_user(exc, (unsigned long __user *)buffer)) + return -EFAULT; + state = ¤t_thread_info()->ieee_state; + exc &= IEEE_STATUS_MASK; + + /* Update softare trap enable bits. */ + swcr = (*state & IEEE_SW_MASK) | exc; + *state |= exc; /* Update the real fpcr. */ fpcr = rdfpcr(); - fpcr &= FPCR_DYN_MASK; fpcr |= ieee_swcr_to_fpcr(swcr); wrfpcr(fpcr); - /* If any exceptions are now unmasked, send a signal. */ - fex = ((swcr & IEEE_STATUS_MASK) - >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr; + /* If any exceptions set by this call, and are unmasked, + send a signal. Old exceptions are not signaled. */ + fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr; if (fex) { siginfo_t info; int si_code = 0; @@ -765,7 +786,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, info.si_addr = NULL; /* FIXME */ send_sig_info(SIGFPE, &info, current); } - return 0; } @@ -969,7 +989,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, fd_set_bits fds; char *bits; size_t size; - unsigned long timeout; + long timeout; int ret; timeout = MAX_SCHEDULE_TIMEOUT; @@ -1033,9 +1053,10 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, ret = 0; } - set_fd_set(n, inp->fds_bits, fds.res_in); - set_fd_set(n, outp->fds_bits, fds.res_out); - set_fd_set(n, exp->fds_bits, fds.res_ex); + if (set_fd_set(n, inp->fds_bits, fds.res_in) || + set_fd_set(n, outp->fds_bits, fds.res_out) || + set_fd_set(n, exp->fds_bits, fds.res_ex)) + ret = -EFAULT; out: kfree(bits); @@ -1079,64 +1100,57 @@ osf_getrusage(int who, struct rusage32 __user *ru) r.ru_majflt = current->maj_flt; break; case RUSAGE_CHILDREN: - jiffies_to_timeval32(current->cutime, &r.ru_utime); - jiffies_to_timeval32(current->cstime, &r.ru_stime); - r.ru_minflt = current->cmin_flt; - r.ru_majflt = current->cmaj_flt; - break; - default: - jiffies_to_timeval32(current->utime + current->cutime, - &r.ru_utime); - jiffies_to_timeval32(current->stime + current->cstime, - &r.ru_stime); - r.ru_minflt = current->min_flt + current->cmin_flt; - r.ru_majflt = current->maj_flt + current->cmaj_flt; + jiffies_to_timeval32(current->signal->cutime, &r.ru_utime); + jiffies_to_timeval32(current->signal->cstime, &r.ru_stime); + r.ru_minflt = current->signal->cmin_flt; + r.ru_majflt = current->signal->cmaj_flt; break; } return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; } -asmlinkage int -osf_wait4(pid_t pid, int __user *ustatus, int options, struct rusage32 __user *ur) +asmlinkage long +osf_wait4(pid_t pid, int __user *ustatus, int options, + struct rusage32 __user *ur) { - if (!ur) { + struct rusage r; + long ret, err; + mm_segment_t old_fs; + + if (!ur) return sys_wait4(pid, ustatus, options, NULL); - } else { - struct rusage r; - int ret, status; - mm_segment_t old_fs = get_fs(); + + old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = sys_wait4(pid, &status, options, &r); - set_fs (old_fs); + set_fs (KERNEL_DS); + ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r); + set_fs (old_fs); - if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) - return -EFAULT; - __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); - __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); - __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); - __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec); - __put_user(r.ru_maxrss, &ur->ru_maxrss); - __put_user(r.ru_ixrss, &ur->ru_ixrss); - __put_user(r.ru_idrss, &ur->ru_idrss); - __put_user(r.ru_isrss, &ur->ru_isrss); - __put_user(r.ru_minflt, &ur->ru_minflt); - __put_user(r.ru_majflt, &ur->ru_majflt); - __put_user(r.ru_nswap, &ur->ru_nswap); - __put_user(r.ru_inblock, &ur->ru_inblock); - __put_user(r.ru_oublock, &ur->ru_oublock); - __put_user(r.ru_msgsnd, &ur->ru_msgsnd); - __put_user(r.ru_msgrcv, &ur->ru_msgrcv); - __put_user(r.ru_nsignals, &ur->ru_nsignals); - __put_user(r.ru_nvcsw, &ur->ru_nvcsw); - if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw)) - return -EFAULT; + if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) + return -EFAULT; - if (ustatus && put_user(status, ustatus)) - return -EFAULT; - return ret; - } + err = 0; + err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); + err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); + err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); + err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec); + err |= __put_user(r.ru_maxrss, &ur->ru_maxrss); + err |= __put_user(r.ru_ixrss, &ur->ru_ixrss); + err |= __put_user(r.ru_idrss, &ur->ru_idrss); + err |= __put_user(r.ru_isrss, &ur->ru_isrss); + err |= __put_user(r.ru_minflt, &ur->ru_minflt); + err |= __put_user(r.ru_majflt, &ur->ru_majflt); + err |= __put_user(r.ru_nswap, &ur->ru_nswap); + err |= __put_user(r.ru_inblock, &ur->ru_inblock); + err |= __put_user(r.ru_oublock, &ur->ru_oublock); + err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd); + err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv); + err |= __put_user(r.ru_nsignals, &ur->ru_nsignals); + err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw); + err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw); + + return err ? err : ret; } /* diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index b8a7e3ff8..582a3519f 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include "proto.h" @@ -101,41 +103,112 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn, else return -ENODEV; } -/* stubs for the routines in pci_iommu.c */ + +/* Stubs for the routines in pci_iommu.c: */ + void * pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) { return NULL; } + void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, dma_addr_t dma_addr) { } + dma_addr_t pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int direction) { return (dma_addr_t) 0; } + void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, int direction) { } + int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction) { return 0; } + void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction) { } + int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) { return 0; } + +/* Generic DMA mapping functions: */ + +void * +dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, int gfp) +{ + void *ret; + + if (!dev || *dev->dma_mask >= 0xffffffffUL) + gfp &= ~GFP_DMA; + ret = (void *)__get_free_pages(gfp, get_order(size)); + if (ret) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +EXPORT_SYMBOL(dma_alloc_coherent); + +int +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + int i; + + for (i = 0; i < nents; i++ ) { + void *va; + + BUG_ON(!sg[i].page); + va = page_address(sg[i].page) + sg[i].offset; + sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va); + sg_dma_len(sg + i) = sg[i].length; + } + + return nents; +} + +EXPORT_SYMBOL(dma_map_sg); + +int +dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +{ +} + +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1e3abbb5c..1f36bbd0e 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -67,6 +67,7 @@ quirk_isa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_ISA << 8; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge); static void __init quirk_cypress(struct pci_dev *dev) @@ -100,6 +101,7 @@ quirk_cypress(struct pci_dev *dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress); /* Called for each device after PCI setup is done. */ static void __init @@ -112,17 +114,10 @@ pcibios_fixup_final(struct pci_dev *dev) isa_bridge = dev; } } +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final); -struct pci_fixup pcibios_fixups[] __initdata = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, - quirk_isa_bridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, - quirk_cypress }, - { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, - pcibios_fixup_final }, - { 0 } -}; - +/* Just declaring that the power-of-ten prefixes are actually the + power-of-two ones doesn't make it true :) */ #define KB 1024 #define MB (1024*KB) #define GB (1024*MB) @@ -232,7 +227,7 @@ pdev_save_srm_config(struct pci_dev *dev) tmp->next = srm_saved_configs; tmp->dev = dev; - pci_save_state(dev, tmp->regs); + pci_save_state(dev); srm_saved_configs = tmp; } @@ -248,7 +243,7 @@ pci_restore_srm_config(void) /* Restore SRM config. */ for (tmp = srm_saved_configs; tmp; tmp = tmp->next) { - pci_restore_state(tmp->dev, tmp->regs); + pci_restore_state(tmp->dev); } } #endif @@ -285,7 +280,6 @@ pcibios_fixup_bus(struct pci_bus *bus) /* Propagate hose info into the subordinate devices. */ struct pci_controller *hose = bus->sysdata; - struct list_head *ln; struct pci_dev *dev = bus->self; if (!dev) { @@ -309,9 +303,7 @@ pcibios_fixup_bus(struct pci_bus *bus) pcibios_fixup_device_resources(dev, bus); } - for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { - struct pci_dev *dev = pci_dev_b(ln); - + list_for_each_entry(dev, &bus->devices, bus_list) { pdev_save_srm_config(dev); if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) pcibios_fixup_device_resources(dev, bus); @@ -408,11 +400,10 @@ pcibios_set_master(struct pci_dev *dev) static void __init pcibios_claim_one_bus(struct pci_bus *b) { - struct list_head *ld; + struct pci_dev *dev; struct pci_bus *child_bus; - for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { - struct pci_dev *dev = pci_dev_b(ld); + list_for_each_entry(dev, &b->devices, bus_list) { int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -431,12 +422,10 @@ pcibios_claim_one_bus(struct pci_bus *b) static void __init pcibios_claim_console_setup(void) { - struct list_head *lb; + struct pci_bus *b; - for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) { - struct pci_bus *b = pci_bus_b(lb); + list_for_each_entry(b, &pci_root_buses, node) pcibios_claim_one_bus(b); - } } void __init @@ -536,3 +525,37 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn) return -EOPNOTSUPP; } + +/* Create an __iomem token from a PCI BAR. Copied from lib/iomap.c with + no changes, since we don't want the other things in that object file. */ + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len || !start) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) { + /* Not checking IORESOURCE_CACHEABLE because alpha does + not distinguish between ioremap and ioremap_nocache. */ + return ioremap(start, len); + } + return NULL; +} + +/* Destroy that token. Not copied from lib/iomap.c. */ + +void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +{ + if (__is_mmio(addr)) + iounmap(addr); +} + +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h index 54fb8f178..f8b74995a 100644 --- a/arch/alpha/kernel/pci_impl.h +++ b/arch/alpha/kernel/pci_impl.h @@ -166,7 +166,6 @@ struct pdev_srm_saved_conf { struct pdev_srm_saved_conf *next; struct pci_dev *dev; - u32 regs[16]; }; extern void pci_restore_srm_config(void); diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index b47c35679..7cb23f12e 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -930,3 +930,42 @@ pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr) { return (dma_addr & ~PAGE_MASK); } + + +/* Helper for generic DMA-mapping functions. */ + +struct pci_dev * +alpha_gendev_to_pci(struct device *dev) +{ + if (dev && dev->bus == &pci_bus_type) + return to_pci_dev(dev); + + /* Assume that non-PCI devices asking for DMA are either ISA or EISA, + BUG() otherwise. */ + BUG_ON(!isa_bridge); + + /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA + bridge is bus master then). */ + if (!dev || !dev->dma_mask || !*dev->dma_mask) + return isa_bridge; + + /* For EISA bus masters, return isa_bridge (it might have smaller + dma_mask due to wiring limitations). */ + if (*dev->dma_mask >= isa_bridge->dma_mask) + return isa_bridge; + + /* This assumes ISA bus master with dma_mask 0xffffff. */ + return NULL; +} + +int +dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || + !pci_dma_supported(alpha_gendev_to_pci(dev), mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 6fd854655..4933f3ce5 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -246,8 +246,7 @@ alpha_clone(unsigned long clone_flags, unsigned long usp, if (!usp) usp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tid, child_tid); + return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid); } int diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index aa654cc85..d00583161 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -91,15 +91,15 @@ static int regoff[] = { PT_REG( pc) }; -static long zero; +static unsigned long zero; /* * Get address of register REGNO in task TASK. */ -static long * +static unsigned long * get_reg_addr(struct task_struct * task, unsigned long regno) { - long *addr; + unsigned long *addr; if (regno == 30) { addr = &task->thread_info->pcb.usp; @@ -109,7 +109,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno) zero = 0; addr = &zero; } else { - addr = (long *)((long)task->thread_info + regoff[regno]); + addr = (void *)task->thread_info + regoff[regno]; } return addr; } @@ -117,7 +117,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno) /* * Get contents of register REGNO in task TASK. */ -static long +static unsigned long get_reg(struct task_struct * task, unsigned long regno) { /* Special hack for fpcr -- combine hardware and software bits. */ @@ -135,7 +135,7 @@ get_reg(struct task_struct * task, unsigned long regno) * Write contents of register REGNO in task TASK. */ static int -put_reg(struct task_struct *task, unsigned long regno, long data) +put_reg(struct task_struct *task, unsigned long regno, unsigned long data) { if (regno == 63) { task->thread_info->ieee_state @@ -168,11 +168,11 @@ int ptrace_set_bpt(struct task_struct * child) { int displ, i, res, reg_b, nsaved = 0; - u32 insn, op_code; + unsigned int insn, op_code; unsigned long pc; pc = get_reg(child, REG_PC); - res = read_int(child, pc, &insn); + res = read_int(child, pc, (int *) &insn); if (res < 0) return res; @@ -203,7 +203,8 @@ ptrace_set_bpt(struct task_struct * child) /* install breakpoints: */ for (i = 0; i < nsaved; ++i) { - res = read_int(child, child->thread_info->bpt_addr[i], &insn); + res = read_int(child, child->thread_info->bpt_addr[i], + (int *) &insn); if (res < 0) return res; child->thread_info->bpt_insn[i] = insn; @@ -354,7 +355,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, */ case PTRACE_KILL: ret = 0; - if (child->state == TASK_ZOMBIE) + if (child->exit_state == EXIT_ZOMBIE) break; child->exit_code = SIGKILL; /* make sure single-step breakpoint is gone. */ diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index dd1d9195c..974329cf0 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -19,8 +19,8 @@ #include #include #include +#include -#include #include #include #include @@ -145,7 +145,7 @@ sys_rt_sigaction(int sig, const struct sigaction __user *act, * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int -do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw) +do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) { sigset_t oldset; @@ -156,17 +156,22 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + /* Indicate EINTR on return from any possible signal handler, + which will not come back through here, but via sigreturn. */ + regs->r0 = EINTR; + regs->r19 = 1; + while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&oldset, reg, sw, 0, 0)) + if (do_signal(&oldset, regs, sw, 0, 0)) return -EINTR; } } asmlinkage int do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, - struct pt_regs *reg, struct switch_stack *sw) + struct pt_regs *regs, struct switch_stack *sw) { sigset_t oldset, set; @@ -183,10 +188,15 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + /* Indicate EINTR on return from any possible signal handler, + which will not come back through here, but via sigreturn. */ + regs->r0 = EINTR; + regs->r19 = 1; + while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&oldset, reg, sw, 0, 0)) + if (do_signal(&oldset, regs, sw, 0, 0)) return -EINTR; } } @@ -218,6 +228,12 @@ struct rt_sigframe unsigned int retcode[3]; }; +/* If this changes, userland unwinders that Know Things about our signal + frame will break. Do not undertake lightly. It also implies an ABI + change wrt the size of siginfo_t, which may cause some pain. */ +extern char compile_time_assert + [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1]; + #define INSN_MOV_R30_R16 0x47fe0410 #define INSN_LDI_R0 0x201f0000 #define INSN_CALLSYS 0x00000083 @@ -469,9 +485,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void @@ -533,9 +547,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } @@ -608,21 +620,20 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, siginfo_t info; int signr; unsigned long single_stepping = ptrace_cancel_bpt(current); + struct k_sigaction ka; if (!oldset) oldset = ¤t->blocked; /* This lets the debugger run, ... */ - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* ... so re-check the single stepping. */ single_stepping |= ptrace_cancel_bpt(current); if (signr > 0) { /* Whee! Actually deliver the signal. */ - struct k_sigaction *ka = ¤t->sighand->action[signr-1]; - - if (r0) syscall_restart(r0, r19, regs, ka); - handle_signal(signr, ka, &info, oldset, regs, sw); + if (r0) syscall_restart(r0, r19, regs, &ka); + handle_signal(signr, &ka, &info, oldset, regs, sw); if (single_stepping) ptrace_set_bpt(current); /* re-set bpt */ return 1; diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 3a4c9d6e2..04a4d366b 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -32,10 +34,8 @@ #include #include -#include #include #include -#include #include #include @@ -411,15 +411,6 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) return 0; } -static struct task_struct * __init -fork_by_hand(void) -{ - /* Don't care about the contents of regs since we'll never - reschedule the forked task. */ - struct pt_regs regs; - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Bring one cpu online. */ @@ -435,15 +426,10 @@ smp_boot_one_cpu(int cpuid) the other task-y sort of data structures set up like we wish. We can't use kernel_thread since we must avoid rescheduling the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpuid); - wake_up_forked_process(idle); - - init_idle(idle, cpuid); - unhash_process(idle); - DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", cpuid, idle->state, idle->flags)); @@ -613,8 +599,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs) struct cpuinfo_alpha *data = &cpu_data[cpu]; /* Record kernel PC. */ - if (!user) - alpha_do_profile(regs->pc); + profile_tick(CPU_PROFILING, regs); if (!--data->prof_counter) { /* We need to make like a normal interrupt -- otherwise diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index 1a9b4c645..631240245 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c @@ -91,15 +91,15 @@ srmcons_receive_chars(unsigned long data) /* called with callback_lock held */ static int -srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count) +srmcons_do_write(struct tty_struct *tty, const char *buf, int count) { - unsigned char *str_cr = "\r"; + static char str_cr[1] = "\r"; long c, remaining = count; srmcons_result result; - unsigned char *cur; + char *cur; int need_cr; - for (cur = (unsigned char *)buf; remaining > 0; ) { + for (cur = (char *)buf; remaining > 0; ) { need_cr = 0; /* * Break it up into reasonable size chunks to allow a chance @@ -132,42 +132,13 @@ srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count) } static int -srmcons_write(struct tty_struct *tty, int from_user, +srmcons_write(struct tty_struct *tty, const unsigned char *buf, int count) { unsigned long flags; - if (from_user) { - unsigned char tmp[512]; - int ret = 0; - size_t c; - - while ((c = count) > 0) { - if (c > sizeof(tmp)) - c = sizeof(tmp); - - c -= copy_from_user(tmp, buf, c); - - if (!c) { - printk("%s: EFAULT (count %d)\n", - __FUNCTION__, count); - return -EFAULT; - } - - spin_lock_irqsave(&srmcons_callback_lock, flags); - srmcons_do_write(tty, tmp, c); - spin_unlock_irqrestore(&srmcons_callback_lock, flags); - - buf += c; - count -= c; - ret += c; - } - - return ret; - } - spin_lock_irqsave(&srmcons_callback_lock, flags); - srmcons_do_write(tty, buf, count); + srmcons_do_write(tty, (const char *) buf, count); spin_unlock_irqrestore(&srmcons_callback_lock, flags); return count; diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c index bf2cfa1b0..145dcde14 100644 --- a/arch/alpha/kernel/sys_alcor.c +++ b/arch/alpha/kernel/sys_alcor.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -274,7 +274,6 @@ struct alpha_machine_vector alcor_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, @@ -292,7 +291,7 @@ struct alpha_machine_vector alcor_mv __initmv = { .pci_swizzle = common_swizzle, .sys = { .cia = { - .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS + .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS }} }; ALIAS_MV(alcor) @@ -302,7 +301,6 @@ struct alpha_machine_vector xlt_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, @@ -320,7 +318,7 @@ struct alpha_machine_vector xlt_mv __initmv = { .pci_swizzle = common_swizzle, .sys = { .cia = { - .gru_int_req_bits = XLT_GRU_INT_REQ_BITS + .gru_int_req_bits = XLT_GRU_INT_REQ_BITS }} }; diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c index 568feb8b1..8e3374d34 100644 --- a/arch/alpha/kernel/sys_cabriolet.c +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -327,7 +327,6 @@ struct alpha_machine_vector cabriolet_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - DO_APECS_BUS, .machine_check = apecs_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -354,7 +353,6 @@ struct alpha_machine_vector eb164_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -380,7 +378,6 @@ struct alpha_machine_vector eb66p_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, - DO_LCA_BUS, .machine_check = lca_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -405,7 +402,6 @@ struct alpha_machine_vector lx164_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -432,7 +428,6 @@ struct alpha_machine_vector pc164_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 119501849..6e334292b 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -19,12 +19,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -71,10 +71,10 @@ tsunami_update_irq_hw(unsigned long mask) dim1 = &cchip->dim1.csr; dim2 = &cchip->dim2.csr; dim3 = &cchip->dim3.csr; - if (cpu_possible(0)) dim0 = &dummy; - if (cpu_possible(1)) dim1 = &dummy; - if (cpu_possible(2)) dim2 = &dummy; - if (cpu_possible(3)) dim3 = &dummy; + if (!cpu_possible(0)) dim0 = &dummy; + if (!cpu_possible(1)) dim1 = &dummy; + if (!cpu_possible(2)) dim2 = &dummy; + if (!cpu_possible(3)) dim3 = &dummy; *dim0 = mask0; *dim1 = mask1; @@ -569,7 +569,6 @@ struct alpha_machine_vector dp264_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -594,7 +593,6 @@ struct alpha_machine_vector monet_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -618,7 +616,6 @@ struct alpha_machine_vector webbrick_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -642,7 +639,6 @@ struct alpha_machine_vector clipper_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -671,7 +667,6 @@ struct alpha_machine_vector shark_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c index 035af0b47..61a79c354 100644 --- a/arch/alpha/kernel/sys_eb64p.c +++ b/arch/alpha/kernel/sys_eb64p.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -212,7 +212,6 @@ struct alpha_machine_vector eb64p_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - DO_APECS_BUS, .machine_check = apecs_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -238,7 +237,6 @@ struct alpha_machine_vector eb66_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, - DO_LCA_BUS, .machine_check = lca_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c index c6cbf4780..bd6e5f0e4 100644 --- a/arch/alpha/kernel/sys_eiger.c +++ b/arch/alpha/kernel/sys_eiger.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -222,7 +222,6 @@ struct alpha_machine_vector eiger_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TSUNAMI_IO, - DO_TSUNAMI_BUS, .machine_check = tsunami_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index ed6ce2f31..fcabb7c96 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c @@ -249,8 +249,6 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs) printk(KERN_CRIT "Machine check\n"); } -#define jensen_pci_tbi ((void*)0) - /* * The System Vector @@ -260,7 +258,6 @@ struct alpha_machine_vector jensen_mv __initmv = { .vector_name = "Jensen", DO_EV4_MMU, IO_LITE(JENSEN,jensen), - BUS(jensen), .machine_check = jensen_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .rtc_port = 0x170, diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c index 561122bea..804727853 100644 --- a/arch/alpha/kernel/sys_marvel.c +++ b/arch/alpha/kernel/sys_marvel.c @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -471,7 +471,6 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = { DO_EV7_MMU, DO_DEFAULT_RTC, DO_MARVEL_IO, - DO_MARVEL_BUS, .machine_check = marvel_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c index a8cd711e8..61ac56f8e 100644 --- a/arch/alpha/kernel/sys_miata.c +++ b/arch/alpha/kernel/sys_miata.c @@ -269,7 +269,6 @@ struct alpha_machine_vector miata_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c index 57ed49d57..d78a0daa6 100644 --- a/arch/alpha/kernel/sys_mikasa.c +++ b/arch/alpha/kernel/sys_mikasa.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -221,7 +221,6 @@ struct alpha_machine_vector mikasa_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - DO_APECS_BUS, .machine_check = mikasa_apecs_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -246,7 +245,6 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index fcf04ed3b..c0d696efe 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -32,12 +32,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -250,7 +250,6 @@ struct alpha_machine_vector nautilus_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_IRONGATE_IO, - DO_IRONGATE_BUS, .machine_check = nautilus_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c index e974cdbe6..65061f5d7 100644 --- a/arch/alpha/kernel/sys_noritake.c +++ b/arch/alpha/kernel/sys_noritake.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -303,7 +303,6 @@ struct alpha_machine_vector noritake_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - DO_APECS_BUS, .machine_check = noritake_apecs_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, @@ -328,7 +327,6 @@ struct alpha_machine_vector noritake_primo_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c index 0724393a4..38d32bc3e 100644 --- a/arch/alpha/kernel/sys_rawhide.c +++ b/arch/alpha/kernel/sys_rawhide.c @@ -250,7 +250,6 @@ struct alpha_machine_vector rawhide_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_MCPCIA_IO, - DO_MCPCIA_BUS, .machine_check = mcpcia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c index ccabcb1e3..78c30decf 100644 --- a/arch/alpha/kernel/sys_ruffian.c +++ b/arch/alpha/kernel/sys_ruffian.c @@ -220,7 +220,6 @@ struct alpha_machine_vector ruffian_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c index 3dcbd2717..584042430 100644 --- a/arch/alpha/kernel/sys_rx164.c +++ b/arch/alpha/kernel/sys_rx164.c @@ -14,12 +14,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -201,7 +201,6 @@ struct alpha_machine_vector rx164_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_POLARIS_IO, - DO_POLARIS_BUS, .machine_check = polaris_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c index e129e0e80..17423dd8c 100644 --- a/arch/alpha/kernel/sys_sable.c +++ b/arch/alpha/kernel/sys_sable.c @@ -566,7 +566,6 @@ struct alpha_machine_vector sable_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_T2_IO, - DO_T2_BUS, .machine_check = t2_machine_check, .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, @@ -599,7 +598,6 @@ struct alpha_machine_vector sable_gamma_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_T2_IO, - DO_T2_BUS, .machine_check = t2_machine_check, .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, @@ -631,7 +629,6 @@ struct alpha_machine_vector lynx_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_T2_IO, - DO_T2_BUS, .machine_check = t2_machine_check, .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS, .min_io_address = EISA_DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c index 177e1275d..47df48a6d 100644 --- a/arch/alpha/kernel/sys_sio.c +++ b/arch/alpha/kernel/sys_sio.c @@ -288,7 +288,6 @@ struct alpha_machine_vector alphabook1_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, - DO_LCA_BUS, .machine_check = lca_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -319,7 +318,6 @@ struct alpha_machine_vector avanti_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - DO_APECS_BUS, .machine_check = apecs_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -349,7 +347,6 @@ struct alpha_machine_vector noname_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, - DO_LCA_BUS, .machine_check = lca_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -388,7 +385,6 @@ struct alpha_machine_vector p2k_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_LCA_IO, - DO_LCA_BUS, .machine_check = lca_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -418,7 +414,6 @@ struct alpha_machine_vector xl_mv __initmv = { DO_EV4_MMU, DO_DEFAULT_RTC, DO_APECS_IO, - BUS(apecs), .machine_check = apecs_machine_check, .max_isa_dma_address = ALPHA_XL_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c index d8f771a98..94ad68b7c 100644 --- a/arch/alpha/kernel/sys_sx164.c +++ b/arch/alpha/kernel/sys_sx164.c @@ -14,12 +14,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -158,7 +158,6 @@ struct alpha_machine_vector sx164_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_PYXIS_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c index 126c433a6..7955bdfc2 100644 --- a/arch/alpha/kernel/sys_takara.c +++ b/arch/alpha/kernel/sys_takara.c @@ -277,7 +277,6 @@ struct alpha_machine_vector takara_mv __initmv = { DO_EV5_MMU, DO_DEFAULT_RTC, DO_CIA_IO, - DO_CIA_BUS, .machine_check = cia_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c index 1114bf7ec..147058fae 100644 --- a/arch/alpha/kernel/sys_titan.c +++ b/arch/alpha/kernel/sys_titan.c @@ -19,12 +19,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask) register int bcpu = boot_cpuid; #ifdef CONFIG_SMP - register unsigned long cpm = cpu_present_mask; + cpumask_t cpm = cpu_present_mask; volatile unsigned long *dim0, *dim1, *dim2, *dim3; unsigned long mask0, mask1, mask2, mask3, dummy; @@ -85,10 +85,10 @@ titan_update_irq_hw(unsigned long mask) dim1 = &cchip->dim1.csr; dim2 = &cchip->dim2.csr; dim3 = &cchip->dim3.csr; - if ((cpm & 1) == 0) dim0 = &dummy; - if ((cpm & 2) == 0) dim1 = &dummy; - if ((cpm & 4) == 0) dim2 = &dummy; - if ((cpm & 8) == 0) dim3 = &dummy; + if (!cpu_isset(0, cpm)) dim0 = &dummy; + if (!cpu_isset(1, cpm)) dim1 = &dummy; + if (!cpu_isset(2, cpm)) dim2 = &dummy; + if (!cpu_isset(3, cpm)) dim3 = &dummy; *dim0 = mask0; *dim1 = mask1; @@ -145,12 +145,12 @@ titan_end_irq(unsigned int irq) } static void -titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity) +titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity) { int cpu; for (cpu = 0; cpu < 4; cpu++) { - if (affinity & (1UL << cpu)) + if (cpu_isset(cpu, affinity)) titan_cpu_irq_affinity[cpu] |= 1UL << irq; else titan_cpu_irq_affinity[cpu] &= ~(1UL << irq); @@ -159,7 +159,7 @@ titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity) } static void -titan_set_irq_affinity(unsigned int irq, unsigned long affinity) +titan_set_irq_affinity(unsigned int irq, cpumask_t affinity) { spin_lock(&titan_irq_lock); titan_cpu_set_irq_affinity(irq - 16, affinity); @@ -369,7 +369,6 @@ struct alpha_machine_vector titan_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TITAN_IO, - DO_TITAN_BUS, .machine_check = titan_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, @@ -397,7 +396,6 @@ struct alpha_machine_vector privateer_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_TITAN_IO, - DO_TITAN_BUS, .machine_check = privateer_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c index 35b0f4c6f..57be09676 100644 --- a/arch/alpha/kernel/sys_wildfire.c +++ b/arch/alpha/kernel/sys_wildfire.c @@ -12,12 +12,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -337,7 +337,6 @@ struct alpha_machine_vector wildfire_mv __initmv = { DO_EV6_MMU, DO_DEFAULT_RTC, DO_WILDFIRE_IO, - DO_WILDFIRE_BUS, .machine_check = wildfire_machine_check, .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, .min_io_address = DEFAULT_IO_BASE, diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 7caf209d6..faab8c2a0 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -457,6 +457,7 @@ sys_call_table: .quad sys_mq_timedreceive /* 435 */ .quad sys_mq_notify .quad sys_mq_getsetattr + .quad sys_waitid .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 711124368..e74677115 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -118,8 +119,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs) #ifndef CONFIG_SMP /* Not SMP, do kernel PC profiling here. */ - if (!user_mode(regs)) - alpha_do_profile(regs->pc); + profile_tick(CPU_PROFILING, regs); #endif write_seqlock(&xtime_lock); @@ -138,6 +138,9 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs) while (nticks > 0) { do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif nticks--; } @@ -366,7 +369,7 @@ time_init(void) BCD_TO_BIN(year); } - /* PC-like is standard; used for year < 20 || year >= 70 */ + /* PC-like is standard; used for year >= 70 */ epoch = 1900; if (year < 20) epoch = 2000; diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 2248735b8..fd7bd17cc 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -65,6 +65,8 @@ dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx %s\n", regs->pc, regs->r26, regs->ps, print_tainted()); + print_symbol("pc is at %s\n", regs->pc); + print_symbol("ra is at %s\n", regs->r26 ); printk("v0 = %016lx t0 = %016lx t1 = %016lx\n", regs->r0, regs->r1, regs->r2); printk("t2 = %016lx t3 = %016lx t4 = %016lx\n", @@ -109,7 +111,7 @@ dik_show_code(unsigned int *pc) printk("Code:"); for (i = -6; i < 2; i++) { unsigned int insn; - if (__get_user(insn, pc+i)) + if (__get_user(insn, (unsigned int __user *)pc + i)) break; printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>'); } diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index d159b8f0d..0922e0785 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -18,6 +18,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } :kernel @@ -45,11 +46,6 @@ SECTIONS .init.setup : { *(.init.setup) } __setup_end = .; - . = ALIGN(8); - __start___param = .; - __param : { *(__param) } - __stop___param = .; - . = ALIGN(8); __initcall_start = .; .initcall.init : { diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index a62309953..21cf624d7 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -17,7 +17,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ $(ev6-y)memset.o \ $(ev6-y)memcpy.o \ memmove.o \ - io.o \ checksum.o \ csum_partial_copy.o \ $(ev67-y)strlen.o \ diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index 3e0da493b..a37948f30 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -193,7 +193,8 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, * This is slightly less fun than the above.. */ static inline unsigned long -csum_partial_cfu_src_aligned(const unsigned long *src, unsigned long *dst, +csum_partial_cfu_src_aligned(const unsigned long __user *src, + unsigned long *dst, unsigned long doff, long len, unsigned long checksum, unsigned long partial_dest, @@ -250,7 +251,8 @@ out: * look at this too closely, you'll go blind. */ static inline unsigned long -csum_partial_cfu_unaligned(const unsigned long * src, unsigned long * dst, +csum_partial_cfu_unaligned(const unsigned long __user * src, + unsigned long * dst, unsigned long soff, unsigned long doff, long len, unsigned long checksum, unsigned long partial_dest, @@ -372,7 +374,7 @@ unsigned int csum_partial_copy_from_user(const char __user *src, char *dst, int len, unsigned int sum, int *errp) { - if (!access_ok(src, len, VERIFY_READ)) { + if (!access_ok(VERIFY_READ, src, len)) { *errp = -EFAULT; memset(dst, 0, len); return sum; @@ -382,7 +384,8 @@ csum_partial_copy_from_user(const char __user *src, char *dst, int len, } unsigned int -csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum) +csum_partial_copy_nocheck(const char __user *src, char *dst, int len, + unsigned int sum) { return do_csum_partial_copy_from_user(src, dst, len, sum, NULL); } diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c index 5fc130388..6ae2500a9 100644 --- a/arch/alpha/lib/dec_and_lock.c +++ b/arch/alpha/lib/dec_and_lock.c @@ -9,10 +9,10 @@ #include asm (".text \n\ - .global atomic_dec_and_lock \n\ - .ent atomic_dec_and_lock \n\ + .global _atomic_dec_and_lock \n\ + .ent _atomic_dec_and_lock \n\ .align 4 \n\ -atomic_dec_and_lock: \n\ +_atomic_dec_and_lock: \n\ .prologue 0 \n\ 1: ldl_l $1, 0($16) \n\ subl $1, 1, $1 \n\ @@ -28,7 +28,7 @@ atomic_dec_and_lock: \n\ .subsection 2 \n\ 4: br 1b \n\ .previous \n\ - .end atomic_dec_and_lock"); + .end _atomic_dec_and_lock"); static int __attribute_used__ atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock) diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index a0b969ddf..64ace5a9c 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -98,7 +98,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, by ignoring such an instruction. */ if (cause == 0) { unsigned int insn; - __get_user(insn, (unsigned int *)regs->pc); + __get_user(insn, (unsigned int __user *)regs->pc); if ((insn >> 21 & 0x1f) == 0x1f && /* ldq ldl ldt lds ldg ldf ldwu ldbu */ (1ul << (insn >> 26) & 0x30f00001400ul)) { diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index 31a3f6343..a839578e9 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -313,7 +313,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = dma_local_pfn; zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn; } - free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL); + free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL); } /* Initialize the kernel's ZERO_PGE. */ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 43adecf6a..da2c65c9b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -63,8 +63,11 @@ config GENERIC_BUST_SPINLOCK config GENERIC_ISA_DMA bool -source "init/Kconfig" +config GENERIC_IOMAP + bool + default y +source "init/Kconfig" menu "System Type" @@ -80,6 +83,8 @@ config ARCH_CLPS711X config ARCH_CO285 bool "Co-EBSA285" + select FOOTBRIDGE + select FOOTBRIDGE_ADDIN config ARCH_EBSA110 bool "EBSA-110" @@ -98,6 +103,7 @@ config ARCH_CAMELOT config ARCH_FOOTBRIDGE bool "FootBridge" + select FOOTBRIDGE config ARCH_INTEGRATOR bool "Integrator" @@ -108,6 +114,9 @@ config ARCH_IOP3XX config ARCH_IXP4XX bool "IXP4xx-based" +config ARCH_IXP2000 + bool "IXP2400/2800-based" + config ARCH_L7200 bool "LinkUp-L7200" help @@ -153,10 +162,18 @@ config ARCH_LH7A40X config ARCH_OMAP bool "TI OMAP" -config ARCH_VERSATILE_PB - bool "Versatile PB" +config ARCH_VERSATILE + bool "Versatile" help - This enables support for ARM Ltd Versatile PB board. + This enables support for ARM Ltd Versatile board. + +config ARCH_IMX + bool "IMX" + +config ARCH_H720X + bool "Hynix-HMS720x-based" + help + This enables support for systems based on the Hynix HMS720x endchoice @@ -172,6 +189,8 @@ source "arch/arm/mach-iop3xx/Kconfig" source "arch/arm/mach-ixp4xx/Kconfig" +source "arch/arm/mach-ixp2000/Kconfig" + source "arch/arm/mach-pxa/Kconfig" source "arch/arm/mach-sa1100/Kconfig" @@ -182,6 +201,12 @@ source "arch/arm/mach-s3c2410/Kconfig" source "arch/arm/mach-lh7a40x/Kconfig" +source "arch/arm/mach-imx/Kconfig" + +source "arch/arm/mach-h720x/Kconfig" + +source "arch/arm/mach-versatile/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool @@ -193,28 +218,6 @@ config TIMER_ACORN depends on ARCH_ACORN || ARCH_CLPS7500 default y -##################################################################### -# Footbridge support -config FOOTBRIDGE - bool - depends on ARCH_CO285 || ARCH_FOOTBRIDGE - default y - -config FOOTBRIDGE_HOST - bool - depends on ARCH_CATS || ARCH_EBSA285_HOST || ARCH_NETWINDER || ARCH_PERSONAL_SERVER - default y - -config FOOTBRIDGE_ADDIN - bool - depends on ARCH_CO285 || ARCH_EBSA285_ADDIN - default y - -config ARCH_EBSA285 - bool - depends on ARCH_EBSA285_HOST || ARCH_EBSA285_ADDIN - default y - ##################################################################### # SA1111 support config SA1111 @@ -247,7 +250,6 @@ config XSCALE_PMU endmenu - menu "General setup" # Select various configuration options depending on the machine type @@ -264,7 +266,7 @@ config DISCONTIGMEM # Now handle the bus types config PCI bool "PCI support" if ARCH_INTEGRATOR_AP - default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX + default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000 help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside @@ -287,14 +289,19 @@ config ICST525 depends on ARCH_INTEGRATOR default y +config ICST307 + bool + depends on ARCH_VERSATILE + default y + config ARM_AMBA bool - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB + depends on ARCH_INTEGRATOR || ARCH_VERSATILE default y config ISA bool - depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 + depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS default y help Find out whether you have ISA slots on your motherboard. ISA is the @@ -310,58 +317,98 @@ config ISA_DMA config FIQ bool - depends on ARCH_ACORN || ARCH_L7200 || ARCH_LH7A400 + depends on ARCH_ACORN || ARCH_L7200 default y # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. -config ZBOOT_ROM - bool "Compressed boot loader in ROM/flash" - help - Say Y here if you intend to execute your compressed kernel image (zImage) - directly from ROM or flash. If unsure, say N. - config ZBOOT_ROM_TEXT hex "Compressed ROM boot loader base address" default "0" help - The base address for zImage. Unless you have special requirements, you - should not change this value. + The physical address at which the ROM-able zImage is to be + placed in the target. Platforms which normally make use of + ROM-able zImage formats normally set this to a suitable + value in their defconfig file. + + If ZBOOT_ROM is not enabled, this has no effect. config ZBOOT_ROM_BSS hex "Compressed ROM boot loader BSS address" default "0" help - The base address of 64KiB of read/write memory, which must be available - while the decompressor is running. Unless you have special requirements, - you should not change this value. + The base address of 64KiB of read/write memory in the target + for the ROM-able zImage, which must be available while the + decompressor is running. Platforms which normally make use of + ROM-able zImage formats normally set this to a suitable + value in their defconfig file. + + If ZBOOT_ROM is not enabled, this has no effect. + +config ZBOOT_ROM + bool "Compressed boot loader in ROM/flash" + depends on ZBOOT_ROM_TEXT != ZBOOT_ROM_BSS + help + Say Y here if you intend to execute your compressed kernel image + (zImage) directly from ROM or flash. If unsure, say N. -config CPU_FREQ - bool "Support CPU clock change (EXPERIMENTAL)" - depends on (ARCH_SA1100 || ARCH_INTEGRATOR) && EXPERIMENTAL +config XIP_KERNEL + bool "Kernel Execute-In-Place from ROM" + depends on !ZBOOT_ROM help - CPU clock scaling allows you to change the clock speed of the - running CPU on the fly. This is a nice method to save battery power, - because the lower the clock speed, the less power the CPU - consumes. Note that this driver doesn't automatically change the CPU - clock speed, you need some userland tools (which still have to be - written) to implement the policy. If you don't understand what this - is all about, it's safe to say 'N'. + Execute-In-Place allows the kernel to run from non-volatile storage + directly addressable by the CPU, such as NOR flash. This saves RAM + space since the text section of the kernel is not loaded from flash + to RAM. Read-write sections, such as the data section and stack, + are still copied to RAM. The XIP kernel is not compressed since + it has to run directly from flash, so it will take more space to + store it. The flash address used to link the kernel object files, + and for storing it, is configuration dependent. Therefore, if you + say Y here, you must know the proper physical address where to + store the kernel image depending on your own flash memory usage. + Also note that the make target becomes "make xipImage" rather than + "make zImage" or "make Image". The final kernel binary to put in + ROM memory will be arch/arm/boot/xipImage. -# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor + If unsure, say N. + +config XIP_PHYS_ADDR + hex "XIP Kernel Physical Location" + depends on XIP_KERNEL + default "0x00080000" + help + This is the physical address in your flash memory the kernel will + be linked for and stored to. This address is dependent on your + own flash usage. + + Please note that, if you're using MTD, you must use a flash chip + that is NOT handled by MTD or the flash will be turned into non + data mode for status and query purposes which will instantaneously + crash the kernel. + + MTD can however be used with a XIP kernel on the same flash chip + but only if the flash memory supports multiple partitions in + hardware, like with the Intel K3 flash parts, and only if the + kernel is not stored within the firrst hardware partition of the + chip. + + In any case, make sure that MTD support is configured out for + the first attempt. + +if (ARCH_SA1100 || ARCH_INTEGRATOR) + +source "drivers/cpufreq/Kconfig" config CPU_FREQ_SA1100 bool - depends on CPU_FREQ && SA1100_LART + depends on CPU_FREQ && (SA1100_LART || SA1100_PLEB) default y - select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_SA1110 bool depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) default y - select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_INTEGRATOR tristate "CPUfreq driver for ARM Integrator CPUs" @@ -374,10 +421,6 @@ config CPU_FREQ_INTEGRATOR If in doubt, say Y. -if (CPU_FREQ_INTEGRATOR) || (CPU_FREQ_SA1110) || (CPU_FREQ_SA1100) - -source "drivers/cpufreq/Kconfig" - endif source "drivers/pci/Kconfig" @@ -399,7 +442,7 @@ config FPE_NWFPE config FPE_NWFPE_XP bool "Support extended precision" - depends on FPE_NWFPE + depends on FPE_NWFPE && !CPU_BIG_ENDIAN help Say Y to include 80-bit support in the kernel floating-point emulator. Otherwise, only 32 and 64-bit support is compiled in. @@ -425,6 +468,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" + depends on CPU_V6 || CPU_ARM926T help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. @@ -552,7 +596,7 @@ config CMDLINE config LEDS bool "Timer and CPU usage LEDs" - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. @@ -565,8 +609,8 @@ config LEDS system, but the driver will do nothing. config LEDS_TIMER - bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) - depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB + bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX) + depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX default y if ARCH_EBSA110 help If you say Y here, one of the system LEDs (the green one on the @@ -581,7 +625,7 @@ config LEDS_TIMER config LEDS_CPU bool "CPU usage LED" - depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB) + depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX) help If you say Y here, the red LED will be used to give a good real time indication of CPU usage, by lighting whenever the idle task @@ -661,169 +705,12 @@ source "drivers/misc/Kconfig" source "drivers/usb/Kconfig" +source "drivers/mmc/Kconfig" -menu "Kernel hacking" - -# RMK wants arm kernels compiled with frame pointers so hardwire this to y. -# If you know what you are doing and are willing to live without stack -# traces, you can get a slightly smaller kernel by setting this option to -# n, but then RMK will have to kill you ;). -config FRAME_POINTER - bool - default y - help - If you say N here, the resulting kernel will be slightly smaller and - faster. However, when a problem occurs with the kernel, the - information that is reported is severely limited. Most people - should say Y here. - -config DEBUG_USER - bool "Verbose user fault messages" - help - When a user program crashes due to an exception, the kernel can - print a brief message explaining what the problem was. This is - sometimes helpful for debugging but serves no purpose on a - production system. Most people should say N here. - - In addition, you need to pass user_debug=N on the kernel command - line to enable this feature. N consists of the sum of: - - 1 - undefined instruction events - 2 - system calls - 4 - invalid data aborts - 8 - SIGSEGV faults - 16 - SIGBUS faults - -config DEBUG_INFO - bool "Include GDB debugging information in kernel binary" - help - Say Y here to include source-level debugging information in the - `vmlinux' binary image. This is handy if you want to use gdb or - addr2line to debug the kernel. It has no impact on the in-memory - footprint of the running kernel but it can increase the amount of - time and disk space needed for compilation of the kernel. If in - doubt say N. - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_WAITQ - bool "Wait queue debugging" - depends on DEBUG_KERNEL - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting (adds 70K)" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_ERRORS - bool "Verbose kernel error messages" - depends on DEBUG_KERNEL - help - This option controls verbose debugging information which can be - printed when the kernel detects an internal error. This debugging - information is useful to kernel hackers when tracking down problems, - but mostly meaningless to other people. It's safe to say Y unless - you are concerned with the code size or don't want to see these - messages. - -# These options are only for real kernel hackers who want to get their hands dirty. -config DEBUG_LL - bool "Kernel low-level debugging functions" - depends on DEBUG_KERNEL - help - Say Y here to include definitions of printascii, printchar, printhex - in the kernel. This is helpful if you are debugging code that - executes before the console is initialized. - -config DEBUG_ICEDCC - bool "Kernel low-level debugging via EmbeddedICE DCC channel" - depends on DEBUG_LL - help - Say Y here if you want the debug print routines to direct their - output to the EmbeddedICE macrocell's DCC channel using - co-processor 14. This is known to work on the ARM9 style ICE - channel. - - It does include a timeout to ensure that the system does not - totally freeze when there is nothing connected to read. - -config DEBUG_DC21285_PORT - bool "Kernel low-level debugging messages via footbridge serial port" - depends on DEBUG_LL && FOOTBRIDGE - help - 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. - -config DEBUG_CLPS711X_UART2 - bool "Kernel low-level debugging messages via UART2" - depends on DEBUG_LL && ARCH_CLPS711X - help - 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. - -config DEBUG_S3C2410_PORT - depends on DEBUG_LL && ARCH_S3C2410 - bool "Kernel low-level debugging messages via S3C2410 UART" - help - Say Y here if you want debug print routines to go to one of the - S3C2410 internal UARTs. The chosen UART must have been configured - before it is used. - -config DEBUG_S3C2410_UART - depends on DEBUG_LL && ARCH_S3C2410 - int "S3C2410 UART to use for low-level debug" - default "0" - help - Choice for UART for kernel low-level using S3C2410 UARTS, - should be between zero and two. The port must have been - initalised by the boot-loader before use. - -endmenu +source "arch/arm/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 266f46ca0..27542c0f9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -104,7 +104,7 @@ config DEBUG_S3C2410_PORT before it is used. config DEBUG_S3C2410_UART - depends on DEBUG_LL && ARCH_S3C2410 + depends on ARCH_S3C2410 int "S3C2410 UART to use for low-level debug" default "0" help @@ -112,4 +112,7 @@ config DEBUG_S3C2410_UART should be between zero and two. The port must have been initalised by the boot-loader before use. + The uncompressor code port configuration is now handled + by CONFIG_S3C2410_LOWLEVEL_UART_PORT. + endmenu diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 8b34b0d8a..8b9760b93 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -8,12 +8,15 @@ # Copyright (C) 1995-2001 by Russell King LDFLAGS_vmlinux :=-p --no-undefined -X -LDFLAGS_BLOB :=--format binary -AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) +CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) OBJCOPYFLAGS :=-O binary -R .note -R .comment -S GZFLAGS :=-9 #CFLAGS +=-pipe +# Do not use arch/arm/defconfig - it's always outdated. +# Select a platform tht is kept up-to-date +KBUILD_DEFCONFIG := versatile_defconfig + ifeq ($(CONFIG_FRAME_POINTER),y) CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog endif @@ -36,8 +39,8 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call check_gcc,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) -arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4) +arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4) arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 @@ -51,18 +54,17 @@ tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 -tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_V6) :=-mtune=strongarm # Need -Uarm for gcc < 3.x -CFLAGS +=-mapcs-32 $(arch-y) $(tune-y) $(call check_gcc,-malignment-traps,-mshort-load-bytes) -msoft-float -Wa,-mno-fpu -Uarm -AFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu +CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) +CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm +AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float -CHECK := $(CHECK) -D__arm__=1 +CHECKFLAGS += -D__arm__ #Default value -DATAADDR := . - head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o textaddr-y := 0xC0008000 @@ -90,10 +92,13 @@ textaddr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 machine-$(CONFIG_ARCH_IOP3XX) := iop3xx machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx + machine-$(CONFIG_ARCH_IXP2000) := ixp2000 machine-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x - machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile + machine-$(CONFIG_ARCH_VERSATILE) := versatile + machine-$(CONFIG_ARCH_IMX) := imx + machine-$(CONFIG_ARCH_H720X) := h720x ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. @@ -103,12 +108,27 @@ export CFLAGS_3c589_cs.o endif TEXTADDR := $(textaddr-y) +ifeq ($(CONFIG_XIP_KERNEL),y) + DATAADDR := $(TEXTADDR) + xipaddr-$(CONFIG_ARCH_CO285) := 0x5f000000 + xipaddr-y ?= 0xbf000000 + # Replace phys addr with virt addr while keeping offset from base. + TEXTADDR := $(shell echo $(CONFIG_XIP_PHYS_ADDR) $(xipaddr-y) | \ + awk --non-decimal-data '/[:xdigit:]/ \ + { printf("0x%x\n", and($$1, 0x000fffff) + $$2) }' ) +endif + ifeq ($(incdir-y),) incdir-y := $(machine-y) endif INCDIR := arch-$(incdir-y) +ifneq ($(machine-y),) +MACHINE := arch/arm/mach-$(machine-y)/ +else +MACHINE := +endif -export TEXTADDR GZFLAGS +export TEXTADDR DATAADDR GZFLAGS # Do we have FASTFPE? FASTFPE :=arch/arm/fastfpe @@ -118,9 +138,7 @@ endif # If we have a machine-specific directory, then include it in the build. core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ -ifneq ($(machine-y),) -core-y += arch/arm/mach-$(machine-y)/ -endif +core-y += $(MACHINE) core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) core-$(CONFIG_VFP) += arch/arm/vfp/ @@ -132,7 +150,11 @@ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ libs-y += arch/arm/lib/ # Default target when executing plain make +ifeq ($(CONFIG_XIP_KERNEL),y) +all: xipImage +else all: zImage +endif boot := arch/arm/boot @@ -159,11 +181,11 @@ maketools: include/asm-arm/constants.h include/linux/version.h FORCE # Convert bzImage to zImage bzImage: zImage -zImage Image bootpImage uImage: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +zImage Image xipImage bootpImage uImage: vmlinux + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ zinstall install: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $@ + $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h \ include/asm-arm/arch include/asm-arm/.arch @@ -173,8 +195,8 @@ archclean: $(Q)$(MAKE) $(clean)=$(boot) # My testing targets (bypasses dependencies) -bp:; $(Q)$(MAKE) $(build)=$(boot) $(boot)/bootpImage -i zi:; $(Q)$(MAKE) $(build)=$(boot) $@ +bp:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage +i zi:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/asm-arm/.arch @@ -185,6 +207,7 @@ include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s define archhelp echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' + echo '* xipImage - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)' echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=)' echo ' install - Install uncompressed kernel' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index c247afdd7..937a353bc 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -10,66 +10,38 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh +ifneq ($(MACHINE),) +include $(srctree)/$(MACHINE)/Makefile.boot +endif + # Note: the following conditions must always be true: # ZRELADDR == virt_to_phys(TEXTADDR) -# PARAMS_PHYS must be with 4MB of ZRELADDR +# PARAMS_PHYS must be within 4MB of ZRELADDR # INITRD_PHYS must be in RAM - - zreladdr-$(CONFIG_ARCH_RPC) := 0x10008000 -params_phys-$(CONFIG_ARCH_RPC) := 0x10000100 -initrd_phys-$(CONFIG_ARCH_RPC) := 0x18000000 - zreladdr-$(CONFIG_ARCH_CLPS7500) := 0x10008000 - zreladdr-$(CONFIG_ARCH_CLPS7500) := 0x10008000 - zreladdr-$(CONFIG_ARCH_EBSA110) := 0x00008000 -params_phys-$(CONFIG_ARCH_EBSA110) := 0x00000400 -initrd_phys-$(CONFIG_ARCH_EBSA110) := 0x00800000 - ztextaddr-$(CONFIG_ARCH_SHARK) := 0x08508000 - zreladdr-$(CONFIG_ARCH_SHARK) := 0x08008000 - zreladdr-$(CONFIG_FOOTBRIDGE) := 0x00008000 -params_phys-$(CONFIG_FOOTBRIDGE) := 0x00000100 -initrd_phys-$(CONFIG_FOOTBRIDGE) := 0x00800000 - zreladdr-$(CONFIG_ARCH_INTEGRATOR) := 0x00008000 -params_phys-$(CONFIG_ARCH_INTEGRATOR) := 0x00000100 -initrd_phys-$(CONFIG_ARCH_INTEGRATOR) := 0x00800000 - zreladdr-$(CONFIG_ARCH_CAMELOT) := 0x00008000 - zreladdr-$(CONFIG_ARCH_NEXUSPCI) := 0x40008000 - zreladdr-$(CONFIG_ARCH_L7200) := 0xf0008000 -# The standard locations for stuff on CLPS711x type processors - zreladdr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000 -params_phys-$(CONFIG_ARCH_CLPS711X) := 0xc0000100 -# Should probably have some agreement on these... -initrd_phys-$(CONFIG_ARCH_P720T) := 0xc0400000 -initrd_phys-$(CONFIG_ARCH_CDB89712) := 0x00700000 - zreladdr-$(CONFIG_ARCH_SA1100) := 0xc0008000 -ifeq ($(CONFIG_ARCH_SA1100),y) - zreladdr-$(CONFIG_SA1111) := 0xc0208000 -endif -params_phys-$(CONFIG_ARCH_SA1100) := 0xc0000100 -initrd_phys-$(CONFIG_ARCH_SA1100) := 0xc0800000 - zreladdr-$(CONFIG_ARCH_PXA) := 0xa0008000 - zreladdr-$(CONFIG_ARCH_IOP3XX) := 0xa0008000 -params_phys-$(CONFIG_ARCH_IOP3XX) := 0xa0000100 - zreladdr-$(CONFIG_ARCH_IXP4XX) := 0x00008000 -params-phys-$(CONFIG_ARCH_IXP4XX) := 0x00000100 - zreladdr-$(CONFIG_ARCH_OMAP) := 0x10008000 -params_phys-$(CONFIG_ARCH_OMAP) := 0x10000100 -initrd_phys-$(CONFIG_ARCH_OMAP) := 0x10800000 - zreladdr-$(CONFIG_ARCH_LH7A40X) := 0xc0008000 -params_phys-$(CONFIG_ARCH_LH7A40X) := 0xc0000100 -initrd_phys-$(CONFIG_ARCH_LH7A40X) := 0xc4000000 - zreladdr-$(CONFIG_ARCH_S3C2410) := 0x30008000 -params_phys-$(CONFIG_ARCH_S3C2410) := 0x30000100 - zreladdr-$(CONFIG_ARCH_VERSATILE_PB) := 0x00008000 -params_phys-$(CONFIG_ARCH_VERSATILE_PB) := 0x00000100 -initrd_phys-$(CONFIG_ARCH_VERSATILE_PB) := 0x00800000 - ZRELADDR := $(zreladdr-y) PARAMS_PHYS := $(params_phys-y) INITRD_PHYS := $(initrd_phys-y) export ZRELADDR INITRD_PHYS PARAMS_PHYS -targets := Image zImage bootpImage uImage +targets := Image zImage xipImage bootpImage uImage + +ifeq ($(CONFIG_XIP_KERNEL),y) + +$(obj)/xipImage: vmlinux FORCE + $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))' + +$(obj)/Image $(obj)/zImage: FORCE + @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)' + @echo 'Only the xipImage target is available in this case' + @false + +else + +$(obj)/xipImage: FORCE + @echo 'Kernel not configured for XIP (CONFIG_XIP_KERNEL!=y)' + @false $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) @@ -82,6 +54,8 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @echo ' Kernel: $@ is ready' +endif + quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ -C none -a $(ZRELADDR) -e $(ZRELADDR) \ diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 951fbf6e8..55fcbb7af 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -8,11 +8,13 @@ HEAD = head.o OBJS = misc.o FONTC = drivers/video/console/font_acorn_8x8.c +FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o) + # # Architecture dependencies # ifeq ($(CONFIG_ARCH_ACORN),y) -OBJS += ll_char_wr.o font.o +OBJS += ll_char_wr.o $(FONT) endif ifeq ($(CONFIG_ARCH_SHARK),y) @@ -38,9 +40,6 @@ endif ifeq ($(CONFIG_ARCH_SA1100),y) OBJS += head-sa1100.o -ifeq ($(CONFIG_SA1100_NANOENGINE),y) - OBJS += hw-bse.o -endif endif ifeq ($(CONFIG_CPU_XSCALE),y) @@ -51,6 +50,10 @@ ifeq ($(CONFIG_DEBUG_ICEDCC),y) OBJS += ice-dcc.o endif +ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) +OBJS += big-endian.o +endif + # # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly @@ -66,7 +69,7 @@ endif SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ -targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o \ +targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ head.o misc.o $(OBJS) EXTRA_CFLAGS := -fpic EXTRA_AFLAGS := @@ -98,8 +101,7 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE $(obj)/piggy.o: $(obj)/piggy.gz FORCE -CFLAGS_font.o := -Dstatic= -$(obj)/font.o: $(FONTC) +CFLAGS_font_acorn_8x8.o := -Dstatic= $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config @sed "$(SEDFLAGS)" < $< > $@ diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S index 26f7f77cb..5aefffd46 100644 --- a/arch/arm/boot/compressed/head-sa1100.S +++ b/arch/arm/boot/compressed/head-sa1100.S @@ -16,47 +16,13 @@ __SA1100_start: @ Preserve r8/r7 i.e. kernel entry values - -#if defined(CONFIG_SA1100_GRAPHICSCLIENT) && !defined(CONFIG_ANGELBOOT) - mov r7, #MACH_TYPE_GRAPHICSCLIENT - mov r8, #0 -#endif -#if defined(CONFIG_SA1100_GRAPHICSMASTER) && !defined(CONFIG_ANGELBOOT) - mov r7, #MACH_TYPE_GRAPHICSMASTER - mov r8, #0 -#endif -#if defined(CONFIG_SA1100_ADSBITSY) && !defined(CONFIG_ANGELBOOT) - mov r7, #MACH_TYPE_ADSBITSY - mov r8, #0 -#endif - #ifdef CONFIG_SA1100_COLLIE mov r7, #MACH_TYPE_COLLIE #endif -#ifdef CONFIG_SA1100_PFS168 - @ REVISIT_PFS168: Temporary until firmware updated to use assigned machine number - mov r7, #MACH_TYPE_PFS168 -#endif #ifdef CONFIG_SA1100_SIMPAD @ UNTIL we've something like an open bootldr - mov r7, #MACH_TYPE_SIMPAD @should be 87 + mov r7, #MACH_TYPE_SIMPAD @should be 87 #endif - -#ifdef CONFIG_SA1100_VICTOR - teq r7, #MACH_TYPE_VICTOR - bne 10f - - @ Copy cmdline to 0xc0000000 - mov r1, #0xc0000000 - cmp r0, #0 - moveq r2, #0 -1: ldrneb r2, [r0], #1 - cmpne r2, #0 - strb r2, [r1], #1 - bne 1b -10: -#endif - mrc p15, 0, r0, c1, c0, 0 @ read control reg ands r0, r0, #0x0d beq 99f diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index f9194499e..637e63773 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -35,11 +35,19 @@ __XScale_start: mcr p15, 0, r0, c1, c0, 0 #ifdef CONFIG_ARCH_IQ80321 - orr pc, pc, #PHYS_OFFSET @ jump to physical memory if we are not there. - nop mov r7, #MACH_TYPE_IQ80321 #endif +#ifdef CONFIG_ARCH_IQ31244 + mov r7, #(MACH_TYPE_IQ31244 & 0xff) + orr r7, r7, #(MACH_TYPE_IQ31244 & 0xff00) +#endif + +#ifdef CONFIG_ARCH_IQ80331 + mov r7, #(MACH_TYPE_IQ80331 & 0xff) + orr r7, r7, #(MACH_TYPE_IQ80331 & 0xff00) +#endif + #ifdef CONFIG_ARCH_LUBBOCK mov r7, #MACH_TYPE_LUBBOCK #endif @@ -48,22 +56,3 @@ __XScale_start: mov r7, #MACH_TYPE_COTULLA_IDP #endif -#ifdef CONFIG_ARCH_IQ80310 - /* - * Crank the CPU up to 733MHz - */ - mov r1, #9 - mcr p14, 0, r1, c6, c0, 0 - - /* - * Disable ECC error notification - * At some point, we should add an ECC handler to Linux - */ - mov r1, #0x1500 - mov r0, #0x4 - str r0, [r1, #0x34] - - mov r7, #MACH_TYPE_IQ80310 -#endif - - diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index b47032c2d..c0e7aff3d 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -79,6 +79,14 @@ .endm .macro writeb, rb str \rb, [r3, #0] +#elif defined(CONFIG_ARCH_IXP2000) + .macro loadsp, rb + mov \rb, #0xc0000000 + orr \rb, \rb, #0x00030000 + .endm + .macro writeb, rb + str \rb, [r3, #0] + .endm #elif defined(CONFIG_ARCH_LH7A40X) .macro loadsp, rb ldr \rb, =0x80000700 @ UART2 UARTBASE @@ -100,6 +108,23 @@ .macro writeb, rb strb \rb, [r3] .endm +#elif defined(CONFIG_ARCH_IOP331) + .macro loadsp, rb + mov \rb, #0xff000000 + orr \rb, \rb, #0x00ff0000 + orr \rb, \rb, #0x0000f700 @ location of the UART + .endm + .macro writeb, rb + str \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_S3C2410) + .macro loadsp, rb + mov \rb, #0x50000000 + add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT + .endm + .macro writeb, rb + strb \rb, [r3, #0x20] + .endm #else #error no serial architecture defined #endif @@ -332,6 +357,14 @@ LC0: .word LC0 @ r1 LC1: .word reloc_end - reloc_start .size LC0, . - LC0 +#ifdef CONFIG_ARCH_RPC + .globl params +params: ldr r0, =params_phys + mov pc, lr + .ltorg + .align +#endif + /* * Turn on the cache. We need to setup some page tables so that we * can have both the I and D caches on. @@ -568,6 +601,12 @@ proc_types: b __armv4_cache_off b __armv4_cache_flush + .word 0x00070000 @ ARMv6 + .word 0x000f0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv6_cache_flush + .word 0 @ unrecognised type .word 0 mov pc, lr @@ -627,6 +666,14 @@ cache_clean_flush: mov r3, #16 b call_cache_fn +__armv6_cache_flush: + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D + mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB + mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + __armv4_cache_flush: mov r2, #64*1024 @ default: 32K dcache size (*2) mov r11, #32 @ default: 32 byte line size diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index ebcac6cfb..23434b567 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -23,17 +23,17 @@ unsigned int __machine_arch_type; #include #ifdef STANDALONE_DEBUG -#define puts printf +#define putstr printf #endif #ifdef CONFIG_DEBUG_ICEDCC -#define puts icedcc_puts +#define putstr icedcc_putstr #define putc icedcc_putc extern void idedcc_putc(int ch); static void -icedcc_puts(const char *ptr) +icedcc_putstr(const char *ptr) { for (; *ptr != '\0'; ptr++) { icedcc_putc(*ptr); @@ -191,7 +191,7 @@ static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); -static void puts(const char *); +static void putstr(const char *); extern int end; static ulg free_mem_ptr; @@ -280,14 +280,14 @@ void flush_window(void) bytes_out += (ulg)outcnt; output_ptr += (ulg)outcnt; outcnt = 0; - puts("."); + putstr("."); } static void error(char *x) { - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System halted"); while(1); /* Halt */ } @@ -306,9 +306,9 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, arch_decomp_setup(); makecrc(); - puts("Uncompressing Linux..."); + putstr("Uncompressing Linux..."); gunzip(); - puts(" done, booting the kernel.\n"); + putstr(" done, booting the kernel.\n"); return output_ptr; } #else @@ -320,9 +320,9 @@ int main() output_data = output_buffer; makecrc(); - puts("Uncompressing Linux..."); + putstr("Uncompressing Linux..."); gunzip(); - puts("done.\n"); + putstr("done.\n"); return 0; } #endif diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 50808a4e0..5b9f9eddd 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -2,8 +2,10 @@ # Makefile for the linux kernel. # +obj-y += rtctime.o obj-$(CONFIG_ARM_AMBA) += amba.o obj-$(CONFIG_ICST525) += icst525.o +obj-$(CONFIG_ICST307) += icst307.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c index f7ddb16e9..b5f5c6d2c 100644 --- a/arch/arm/common/amba.c +++ b/arch/arm/common/amba.c @@ -194,7 +194,7 @@ amba_attr(resource, "\t%08lx\t%08lx\t%08lx\n", int amba_device_register(struct amba_device *dev, struct resource *parent) { u32 pid, cid; - void *tmp; + void __iomem *tmp; int i, ret; dev->dev.release = amba_device_release; diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index c3a87663b..5797b1b10 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -121,9 +121,9 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, DO_STATS ( device_info->total_allocs++ ); buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); - if (buf == 0) { + if (buf == NULL) { dev_warn(dev, "%s: kmalloc failed\n", __func__); - return 0; + return NULL; } if (size <= device_info->small_buffer_size) { @@ -137,16 +137,16 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, DO_STATS ( device_info->lbp_allocs++ ); } else { - pool = 0; + pool = NULL; safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC); } - if (safe == 0) { + if (safe == NULL) { dev_warn(device_info->dev, "%s: could not alloc dma memory (size=%d)\n", __func__, size); kfree(buf); - return 0; + return NULL; } #ifdef STATS @@ -216,27 +216,33 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) { - dma_addr_t dma_addr; struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); + dma_addr_t dma_addr; + int needs_bounce = 0; if (device_info) DO_STATS ( device_info->map_op_count++ ); + dma_addr = virt_to_dma(dev, ptr); + if (dev->dma_mask) { + unsigned long mask = *dev->dma_mask; unsigned long limit; - limit = (*dev->dma_mask + 1) & ~(*dev->dma_mask); - if (limit && (size > limit)) { - dev_err(dev, "DMA mapping too big " - "(requested %#x mask %#Lx)\n", - size, *dev->dma_mask); + limit = (mask + 1) & ~mask; + if (limit && size > limit) { + dev_err(dev, "DMA mapping too big (requested %#x " + "mask %#Lx)\n", size, *dev->dma_mask); return ~0; } - } - dma_addr = virt_to_dma(dev, ptr); + /* + * Figure out if we need to bounce from the DMA mask. + */ + needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask; + } - if (device_info && dma_needs_bounce(dev, dma_addr, size)) { + if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) { struct safe_buffer *buf; buf = alloc_safe_buffer(device_info, ptr, size, dir); diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 46550ddde..b86e288c6 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -609,17 +609,15 @@ static void __locomo_remove(struct locomo *lchip) static int locomo_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - struct resource *mem = NULL, *irq = NULL; - int i; - - for (i = 0; i < pdev->num_resources; i++) { - if (pdev->resource[i].flags & IORESOURCE_MEM) - mem = &pdev->resource[i]; - if (pdev->resource[i].flags & IORESOURCE_IRQ) - irq = &pdev->resource[i]; - } + struct resource *mem; + int irq; - return __locomo_probe(dev, mem, irq ? irq->start : NO_IRQ); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -EINVAL; + irq = platform_get_irq(pdev, 0); + + return __locomo_probe(dev, mem, irq); } static int locomo_remove(struct device *dev) @@ -629,9 +627,6 @@ static int locomo_remove(struct device *dev) if (lchip) { __locomo_remove(lchip); dev_set_drvdata(dev, NULL); - - kfree(dev->saved_state); - dev->saved_state = NULL; } return 0; @@ -756,7 +751,7 @@ module_exit(locomo_exit); MODULE_DESCRIPTION("Sharp LoCoMo core driver"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("John Lenz "); +MODULE_AUTHOR("John Lenz "); EXPORT_SYMBOL(locomo_driver_register); EXPORT_SYMBOL(locomo_driver_unregister); diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 18ba42e69..9525e804b 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -35,6 +35,10 @@ #include +#ifdef CONFIG_ARCH_PXA +#include +#endif + extern void __init sa1110_mb_enable(void); /* @@ -761,9 +765,6 @@ static void __sa1111_remove(struct sa1111 *sachip) */ int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) { - unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr); - u32 dma_mask = *dev->dma_mask; - /* * Section 4.6 of the "Intel StrongARM SA-1111 Development Module * User's Guide" mentions that jumpers R51 and R52 control the @@ -771,14 +772,8 @@ int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) * SDRAM bank 1 on Neponset). The default configuration selects * Assabet, so any address in bank 1 is necessarily invalid. */ - if ((machine_is_assabet() || machine_is_pfs168()) && - (addr >= 0xc8000000 || (addr + size) >= 0xc8000000)) - return 1; - - /* - * Check to see if either the start or end are illegal. - */ - return ((addr & ~dma_mask)) || ((addr + size - 1) & ~dma_mask); + return ((machine_is_assabet() || machine_is_pfs168()) && + (addr >= 0xc8000000 || (addr + size) >= 0xc8000000)); } struct sa1111_save_data { @@ -802,6 +797,8 @@ struct sa1111_save_data { unsigned int wakeen1; }; +#ifdef CONFIG_PM + static int sa1111_suspend(struct device *dev, u32 state, u32 level) { struct sa1111 *sachip = dev_get_drvdata(dev); @@ -813,11 +810,10 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level) if (level != SUSPEND_DISABLE) return 0; - dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); - if (!dev->saved_state) + save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); + if (!save) return -ENOMEM; - - save = (struct sa1111_save_data *)dev->saved_state; + dev->power.saved_state = save; spin_lock_irqsave(&sachip->lock, flags); @@ -875,7 +871,7 @@ static int sa1111_resume(struct device *dev, u32 level) if (level != RESUME_ENABLE) return 0; - save = (struct sa1111_save_data *)dev->saved_state; + save = (struct sa1111_save_data *)dev->power.saved_state; if (!save) return 0; @@ -920,12 +916,18 @@ static int sa1111_resume(struct device *dev, u32 level) spin_unlock_irqrestore(&sachip->lock, flags); - dev->saved_state = NULL; + dev->power.saved_state = NULL; kfree(save); return 0; } +#else /* !CONFIG_PM */ +#define sa1111_resume NULL +#define sa1111_suspend NULL +#endif /* !CONFIG_PM */ + + static int sa1111_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -948,8 +950,10 @@ static int sa1111_remove(struct device *dev) __sa1111_remove(sachip); dev_set_drvdata(dev, NULL); - kfree(dev->saved_state); - dev->saved_state = NULL; +#ifdef CONFIG_PM + kfree(dev->power.saved_state); + dev->power.saved_state = NULL; +#endif } return 0; diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c index eb0628296..486add853 100644 --- a/arch/arm/common/time-acorn.c +++ b/arch/arm/common/time-acorn.c @@ -15,6 +15,7 @@ */ #include #include +#include #include #include @@ -22,7 +23,7 @@ #include -static unsigned long ioctime_gettimeoffset(void) +unsigned long ioc_timer_gettimeoffset(void) { unsigned int count1, count2, status; long offset; @@ -62,6 +63,34 @@ void __init ioctime_init(void) ioc_writeb(LATCH & 255, IOC_T0LTCHL); ioc_writeb(LATCH >> 8, IOC_T0LTCHH); ioc_writeb(0, IOC_T0GO); +} + +static irqreturn_t +ioc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; +} + +static struct irqaction ioc_timer_irq = { + .name = "timer", + .flags = SA_INTERRUPT, + .handler = ioc_timer_interrupt +}; - gettimeoffset = ioctime_gettimeoffset; +/* + * Set up timer interrupt. + */ +static void __init ioc_timer_init(void) +{ + ioctime_init(); + setup_irq(IRQ_TIMER, &ioc_timer_irq); } + +struct sys_timer ioc_timer = { + .init = ioc_timer_init, + .offset = ioc_timer_gettimeoffset, +}; + diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig index 45deb459d..dc986cace 100644 --- a/arch/arm/configs/bast_defconfig +++ b/arch/arm/configs/bast_defconfig @@ -1,31 +1,35 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Mon Nov 15 15:32:48 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set -CONFIG_STANDALONE=y CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_BUF_SHIFT=16 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -33,11 +37,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,6 +52,7 @@ CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -60,6 +67,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -68,15 +76,28 @@ CONFIG_ARCH_S3C2410=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # -# S3C2410 Implementations +# S3C24XX Implementations # CONFIG_ARCH_BAST=y # CONFIG_ARCH_H1940 is not set # CONFIG_ARCH_SMDK2410 is not set CONFIG_MACH_VR1000=y +# CONFIG_MACH_RX3715 is not set +CONFIG_CPU_S3C2410=y + +# +# S3C2410 Setup +# +CONFIG_S3C2410_DMA=y +# CONFIG_S3C2410_DMA_DEBUG is not set +# CONFIG_S3C2410_PM_DEBUG is not set +# CONFIG_S3C2410_PM_CHECK is not set +CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 # # Processor Type @@ -86,6 +107,7 @@ CONFIG_CPU_ARM920T=y CONFIG_CPU_32v4=y CONFIG_CPU_ABRT_EV4T=y CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y @@ -103,14 +125,14 @@ CONFIG_CPU_TLB_V4WBI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # # At least one math emulation must be selected # CONFIG_FPE_NWFPE=y -CONFIG_FPE_NWFPE_XP=y +# CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -118,13 +140,13 @@ CONFIG_BINFMT_AOUT=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set -# CONFIG_PM is not set +CONFIG_PM=y # CONFIG_PREEMPT is not set +CONFIG_APM=y # CONFIG_ARTHUR is not set -CONFIG_S3C2410_DMA=y -# CONFIG_S3C2410_DMA_DEBUG is not set CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0" CONFIG_ALIGNMENT_TRAP=y @@ -132,10 +154,7 @@ CONFIG_ALIGNMENT_TRAP=y # Parallel port support # CONFIG_PARPORT=y -CONFIG_PARPORT_PC=y -CONFIG_PARPORT_PC_CML1=y -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y +# CONFIG_PARPORT_PC is not set # CONFIG_PARPORT_ARC is not set CONFIG_PARPORT_OTHER=y CONFIG_PARPORT_1284=y @@ -145,8 +164,13 @@ CONFIG_PARPORT_1284=y # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set +CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set # # User Modules And Translation Layers @@ -161,12 +185,23 @@ CONFIG_MTD_BLOCK=y # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +CONFIG_MTD_MAP_BANK_WIDTH_16=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set @@ -179,11 +214,15 @@ CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +CONFIG_MTD_BAST=y +CONFIG_MTD_BAST_MAXSIZE=4 # # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -197,7 +236,13 @@ CONFIG_MTD_CFI_INTELEXT=y # # NAND Flash Device Drivers # -# CONFIG_MTD_NAND is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_S3C2410=y +# CONFIG_MTD_NAND_S3C2410_DEBUG is not set +# CONFIG_MTD_NAND_S3C2410_HWECC is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set # # Plug and Play support @@ -214,6 +259,16 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -246,6 +301,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -265,7 +323,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -338,13 +395,13 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=m # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y # CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDE_BAST=y # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -395,16 +452,16 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set @@ -431,8 +488,6 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_DIGI is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set @@ -459,7 +514,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_S3C2410=y CONFIG_SERIAL_S3C2410_CONSOLE=y -# CONFIG_SERIAL_BAST_SIO is not set +CONFIG_SERIAL_BAST_SIO=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y @@ -469,7 +524,6 @@ CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=y # CONFIG_TIPAR is not set -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -479,18 +533,23 @@ CONFIG_PPDEV=y # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_S3C2410_WATCHDOG=y # CONFIG_NVRAM is not set -CONFIG_RTC=y +# CONFIG_RTC is not set +CONFIG_S3C2410_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -505,35 +564,42 @@ CONFIG_I2C_CHARDEV=m # CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support # -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_SCx200_ACB is not set +CONFIG_I2C_S3C2410=y +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support # CONFIG_I2C_SENSOR=m # CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set CONFIG_SENSORS_LM78=m # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set CONFIG_SENSORS_LM85=m +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -578,6 +644,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -621,9 +688,14 @@ CONFIG_RAMFS=y # CONFIG_EFS_FS is not set CONFIG_JFFS_FS=y CONFIG_JFFS_FS_VERBOSE=0 +# CONFIG_JFFS_PROC_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 # CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -644,6 +716,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -654,13 +727,7 @@ CONFIG_SUNRPC=y # Partition Types # CONFIG_PARTITION_ADVANCED=y -CONFIG_ACORN_PARTITION=y -CONFIG_ACORN_PARTITION_CUMANA=y -CONFIG_ACORN_PARTITION_EESOX=y -CONFIG_ACORN_PARTITION_ICS=y -CONFIG_ACORN_PARTITION_ADFS=y -CONFIG_ACORN_PARTITION_POWERTEC=y -CONFIG_ACORN_PARTITION_RISCIX=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 @@ -729,13 +796,14 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Graphics support # CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -756,24 +824,34 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_INFO=y CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set @@ -783,6 +861,7 @@ CONFIG_DEBUG_S3C2410_UART=0 # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig index 2b1f60fdb..68f4047fc 100644 --- a/arch/arm/configs/ebsa110_defconfig +++ b/arch/arm/configs/ebsa110_defconfig @@ -176,7 +176,6 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_FWMARK=y CONFIG_IP_ROUTE_NAT=y # CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_TOS is not set CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y # CONFIG_IP_PNP_DHCP is not set diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig index fc4dbc248..e2c992637 100644 --- a/arch/arm/configs/ep80219_defconfig +++ b/arch/arm/configs/ep80219_defconfig @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 17:03:41 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +29,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,7 +76,9 @@ CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ CONFIG_PCI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_PCI_NAMES=y CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -148,8 +160,8 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -191,7 +203,10 @@ CONFIG_MTD_CFI_UTIL=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -232,8 +247,19 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -243,9 +269,11 @@ CONFIG_BLK_DEV_MD=y # CONFIG_MD_LINEAR is not set CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -280,6 +308,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -299,7 +330,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -362,7 +392,6 @@ CONFIG_E100_NAPI=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -375,6 +404,7 @@ CONFIG_E100_NAPI=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # @@ -449,7 +479,8 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -458,6 +489,7 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -519,7 +551,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -554,7 +585,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -567,7 +597,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -575,7 +604,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -590,6 +618,7 @@ CONFIG_I2C_CHARDEV=y # # CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -612,9 +641,11 @@ CONFIG_I2C_IOP3XX=y # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support @@ -622,20 +653,25 @@ CONFIG_I2C_IOP3XX=y # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -685,6 +721,7 @@ CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -709,6 +746,7 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -754,6 +792,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -799,7 +838,6 @@ CONFIG_MSDOS_PARTITION=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -815,23 +853,35 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 8e2413266..5efaeef3e 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -1,139 +1,167 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Mon Dec 20 16:08:21 2004 # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set CONFIG_ARCH_INTEGRATOR=y +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_CLPS711X is not set - -# -# Archimedes/A5000 Implementations -# +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # -# Archimedes/A5000 Implementations (select only ONE) +# Integrator Options # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set - -# -# SA11x0 Implementations -# -# CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_BITSY is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set -# CONFIG_SA1100_PLEB is not set -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set - -# -# CLPS711X/EP721X Implementations -# -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set +CONFIG_ARCH_INTEGRATOR_AP=y +# CONFIG_ARCH_INTEGRATOR_CP is not set +# CONFIG_INTEGRATOR_IMPD1 is not set # # Processor Type # -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set +CONFIG_CPU_32=y CONFIG_CPU_ARM720T=y CONFIG_CPU_ARM920T=y -CONFIG_CPU_ARM920_CPU_IDLE=y -CONFIG_CPU_ARM920_I_CACHE_ON=y -CONFIG_CPU_ARM920_D_CACHE_ON=y -# CONFIG_CPU_ARM920_WRITETHROUGH is not set +# CONFIG_CPU_ARM926T is not set # CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set -# CONFIG_CPU_SA1100 is not set -# CONFIG_DISCONTIGMEM is not set +# CONFIG_CPU_ARM1022 is not set +# CONFIG_CPU_ARM1026 is not set +# CONFIG_CPU_V6 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_ABRT_LV4T=y +CONFIG_CPU_CACHE_V4=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set # # General setup # -CONFIG_PCI_INTEGRATOR=y CONFIG_PCI=y -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -CONFIG_CPU_CLOCK=y +CONFIG_ICST525=y +CONFIG_ARM_AMBA=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_24_API is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_INTEGRATOR=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y + +# +# At least one math emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set CONFIG_PM=y +# CONFIG_PREEMPT is not set +# CONFIG_APM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=1f03 mem=32M" +CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -150,8 +178,9 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_BOOTLDR_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_AFS_PARTS=y # @@ -161,259 +190,264 @@ CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y -# CONFIG_MTD_CFI_VIRTUAL_ER is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_NOSWAP=y # CONFIG_MTD_CFI_BE_BYTE_SWAP is not set # CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LART_BIT_SWAP is not set # CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set -# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_ABSENT is not set # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set -# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -CONFIG_MTD_ARMFLASH=y +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_EDB7312 is not set # # Self-contained MTD device drivers # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers # # CONFIG_MTD_NAND is not set -# CONFIG_MTD_NAND_SPIA is not set # -# Plug and Play configuration +# Plug and Play support # -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # 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_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -# CONFIG_RTNETLINK is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set -CONFIG_INET_ECN=y +# CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_NETFILTER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 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_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set -# CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL 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_AT1700 is not set -# CONFIG_DEPCA is not set +# CONFIG_SMC91X is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH 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_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -CONFIG_EEPRO100_PM=y -# CONFIG_LNE390 is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_E100_NAPI 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_HAPPYMEAL is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO 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 - -# -# Amateur Radio support +# Wireless LAN (non-hamradio) # -# CONFIG_HAMRADIO is not set +# CONFIG_NET_RADIO is not set # -# IrDA (infrared) support +# Wan interfaces # -# CONFIG_IRDA is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # -# ATA/IDE/MFM/RLL support +# SCSI device support # -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_SCSI is not set # -# SCSI support +# Fusion MPT device support # -# CONFIG_SCSI is not set # # IEEE 1394 (FireWire) support @@ -424,11 +458,6 @@ CONFIG_EEPRO100_PM=y # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem @@ -436,62 +465,85 @@ CONFIG_EEPRO100_PM=y # CONFIG_ISDN is not set # -# Input core support +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers # -# CONFIG_INPUT is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -# CONFIG_SERIAL_SA1100 is not set -# CONFIG_SERIAL_SA1100_CONSOLE is not set -CONFIG_SERIAL_AMBA=y -CONFIG_SERIAL_AMBA_CONSOLE=y -CONFIG_SERIAL_INTEGRATOR=y -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support +# Serial drivers # -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set +# CONFIG_SERIAL_8250 is not set # -# Joysticks +# Non-8250 serial port support # -# CONFIG_JOYSTICK is not set +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_DTLK is not set @@ -501,85 +553,114 @@ CONFIG_PSMOUSE=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -CONFIG_MINIX_FS=y +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=y -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # 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=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y -CONFIG_SUNRPC=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS 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_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -590,71 +671,134 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# 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_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_EFI_PARTITION is not set + +# +# Native Language Support +# # CONFIG_NLS is not set # -# Console drivers +# Profiling support # -CONFIG_KMI_KEYB=y -CONFIG_KMI_MOUSE=y -CONFIG_PC_KEYMAP=y -CONFIG_VGA_CONSOLE=y -CONFIG_FB=y +# CONFIG_PROFILING is not set # -# Frame-buffer support +# Graphics support # CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set -# CONFIG_FB_ACORN is not set -# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_ARMCLCD is not set # CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_SA1100 is not set -# CONFIG_FB_E1355 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G450=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_MULTIHEAD=y +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set # # Sound # # CONFIG_SOUND is not set +# +# Misc devices +# + # # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig index 64ebb89b6..89c0eb224 100644 --- a/arch/arm/configs/iq31244_defconfig +++ b/arch/arm/configs/iq31244_defconfig @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:58:36 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +29,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,7 +76,9 @@ CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ CONFIG_PCI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_PCI_NAMES=y CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -148,8 +160,8 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -191,7 +203,10 @@ CONFIG_MTD_CFI_UTIL=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -232,8 +247,19 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -243,9 +269,11 @@ CONFIG_BLK_DEV_MD=y # CONFIG_MD_LINEAR is not set CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -280,6 +308,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -299,7 +330,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -418,7 +448,8 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -427,6 +458,7 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -488,7 +520,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -523,7 +554,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -536,7 +566,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -544,7 +573,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -559,6 +587,7 @@ CONFIG_I2C_CHARDEV=y # # CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -581,9 +610,11 @@ CONFIG_I2C_IOP3XX=y # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support @@ -591,20 +622,25 @@ CONFIG_I2C_IOP3XX=y # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -654,6 +690,7 @@ CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -678,6 +715,7 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -723,6 +761,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -768,7 +807,6 @@ CONFIG_MSDOS_PARTITION=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -784,23 +822,35 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_KERNEL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig index c9afe2458..f3e08188f 100644 --- a/arch/arm/configs/iq80321_defconfig +++ b/arch/arm/configs/iq80321_defconfig @@ -1,101 +1,102 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:48:43 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ADIFCC is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # -# CLPS711X/EP721X Implementations -# - -# -# Epxa10db -# - -# -# Footbridge Implementations +# IOP3xx Implementation Options # # -# IOP3xx Implementation Options +# IOP3xx Platform Types # -# CONFIG_ARCH_IQ80310 is not set CONFIG_ARCH_IQ80321=y -# CONFIG_ARCH_IOP310 is not set +# CONFIG_ARCH_IQ31244 is not set +# CONFIG_ARCH_IQ80331 is not set +# CONFIG_ARCH_EP80219 is not set CONFIG_ARCH_IOP321=y +# CONFIG_ARCH_IOP331 is not set # # IOP3xx Chipset Features # -# CONFIG_IOP3XX_AAU is not set -# CONFIG_IOP3XX_DMA is not set -# CONFIG_IOP3XX_MU is not set -# CONFIG_IOP3XX_PMON is not set - -# -# ADIFCC Implementation Options -# - -# -# ADI Board Types -# - -# -# Intel PXA250/210 Implementations -# - -# -# SA11x0 Implementations -# # # Processor Type @@ -103,6 +104,10 @@ CONFIG_ARCH_IOP321=y CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_MINICACHE=y # # Processor Features @@ -117,14 +122,9 @@ CONFIG_PCI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set # # At least one math emulation must be selected @@ -132,11 +132,15 @@ CONFIG_PCI_NAMES=y CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_PM is not set # CONFIG_PREEMPT is not set # CONFIG_ARTHUR is not set @@ -156,6 +160,8 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -175,19 +181,32 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xf0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=1 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -196,6 +215,7 @@ CONFIG_MTD_CFI_INTELEXT=y # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -214,7 +234,6 @@ CONFIG_MTD_CFI_INTELEXT=y # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -226,9 +245,21 @@ CONFIG_MTD_CFI_INTELEXT=y # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -243,14 +274,13 @@ CONFIG_NET=y # # Networking options # -# CONFIG_PACKET is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y # CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y # CONFIG_IP_PNP_DHCP is not set @@ -258,102 +288,65 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_SMC91X is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_DGRS is not set -CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PIO is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO 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_NET_ETHERNET is not set # # Ethernet (1000 Mbit) @@ -373,96 +366,33 @@ CONFIG_E1000_NAPI=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set # -# Token Ring devices (depends on LLC=y) +# Wireless LAN (non-hamradio) # -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ATA/ATAPI/MFM/RLL support # -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_IDEPCI_SHARE_IRQ is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -CONFIG_BLK_DEV_CMD64X=y -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_SL82C105 is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDE is not set # # SCSI device support @@ -470,7 +400,11 @@ CONFIG_IDEDMA_AUTO=y # CONFIG_SCSI is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set @@ -482,16 +416,24 @@ CONFIG_IDEDMA_AUTO=y # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Input device support # -# CONFIG_INPUT is not set +CONFIG_INPUT=y # # Userland interfaces # +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set # # Input I/O drivers @@ -503,10 +445,18 @@ CONFIG_SOUND_GAMEPORT=y # # Input Device Drivers # +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -514,41 +464,17 @@ CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # # Non-8250 serial port support # -# CONFIG_SERIAL_DZ is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# L3 serial bus support -# -# CONFIG_L3 is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # # IPMI @@ -561,7 +487,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -569,57 +494,47 @@ CONFIG_UNIX98_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=y # -# Video For Linux -# -# CONFIG_VIDEO_PROC_FS is not set - -# -# Video Adapters +# I2C support # -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_I2C is not set # -# Radio Adapters +# Multimedia devices # -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set +# CONFIG_VIDEO_DEV is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set -# CONFIG_VIDEO_BTCX is not set # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -632,17 +547,20 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -651,6 +569,7 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -658,6 +577,10 @@ CONFIG_RAMFS=y CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 # CONFIG_JFFS2_FS_NAND is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -669,19 +592,24 @@ CONFIG_JFFS2_FS_DEBUG=0 # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -699,17 +627,32 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + # # Graphics support # # CONFIG_FB is not set +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + # # Sound # @@ -720,44 +663,38 @@ CONFIG_MSDOS_PARTITION=y # # -# Multimedia Capabilities Port drivers +# USB support # -# CONFIG_MCP is not set +# CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # -# Console Switches +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information # -# CONFIG_SWITCHES is not set # -# USB support +# USB Gadget Support # -# CONFIG_USB is not set # CONFIG_USB_GADGET is not set # -# Bluetooth support +# MMC/SD Card support # -# CONFIG_BT is not set +# CONFIG_MMC is not set # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_INFO is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_LL=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -768,6 +705,8 @@ CONFIG_DEBUG_LL=y # # Library routines # -# CONFIG_CRC32 is not set +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig index 9adbf9b09..b744add80 100644 --- a/arch/arm/configs/iq80331_defconfig +++ b/arch/arm/configs/iq80331_defconfig @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 15 16:43:39 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,6 +19,7 @@ CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,6 +29,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -32,11 +37,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,6 +53,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -60,6 +68,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_INTEGRATOR is not set CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -68,7 +77,9 @@ CONFIG_ARCH_IOP3XX=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # IOP3xx Implementation Options @@ -94,6 +105,7 @@ CONFIG_CPU_32=y CONFIG_CPU_XSCALE=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_MINICACHE=y @@ -110,6 +122,7 @@ CONFIG_PCI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y @@ -119,7 +132,6 @@ CONFIG_PCI_NAMES=y CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -149,8 +161,8 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_CMDLINE_PARTS is not set # CONFIG_MTD_AFS_PARTS is not set @@ -196,7 +208,10 @@ CONFIG_MTD_CFI_UTIL=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xc0000000 +CONFIG_MTD_PHYSMAP_LEN=0x00800000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=1 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -237,8 +252,19 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -248,9 +274,11 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set @@ -285,6 +313,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -304,7 +335,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -423,7 +453,8 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -432,6 +463,7 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -493,7 +525,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -528,7 +559,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -541,7 +571,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -549,7 +578,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -590,6 +618,7 @@ CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -614,6 +643,7 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -653,6 +683,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -698,7 +729,6 @@ CONFIG_MSDOS_PARTITION=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -714,30 +744,44 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index 1933c7027..7b821f811 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -308,7 +308,6 @@ CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_FWMARK=y CONFIG_IP_ROUTE_NAT=y CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig index d9389a2a5..ca2cb5af5 100644 --- a/arch/arm/configs/pleb_defconfig +++ b/arch/arm/configs/pleb_defconfig @@ -1,132 +1,159 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Wed Nov 24 15:12:32 2004 # CONFIG_ARM=y -# CONFIG_EISA is not set -# CONFIG_SBUS is not set -# CONFIG_MCA is not set +CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_OBSOLETE is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_SHMEM is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_TINY_SHMEM=y # # Loadable module support # CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ARCA5K is not set # CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_CAMELOT is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y -# CONFIG_ARCH_CLPS711X is not set - -# -# Archimedes/A5000 Implementations -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set - -# -# Footbridge Implementations -# -# CONFIG_ARCH_CATS is not set -# CONFIG_ARCH_PERSONAL_SERVER is not set -# CONFIG_ARCH_EBSA285_ADDIN is not set -# CONFIG_ARCH_EBSA285_HOST is not set -# CONFIG_ARCH_NETWINDER is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # # SA11x0 Implementations # # CONFIG_SA1100_ASSABET is not set -# CONFIG_ASSABET_NEPONSET is not set -# CONFIG_SA1100_BRUTUS is not set # CONFIG_SA1100_CERF is not set -# CONFIG_SA1100_BITSY is not set -# CONFIG_SA1100_EXTENEX1 is not set -# CONFIG_SA1100_FLEXANET is not set -# CONFIG_SA1100_FREEBIRD is not set -# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_COLLIE is not set +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_BADGE4 is not set # CONFIG_SA1100_JORNADA720 is not set -# CONFIG_SA1100_HUW_WEBPANEL is not set -# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_HACKKIT is not set # CONFIG_SA1100_LART is not set -# CONFIG_SA1100_NANOENGINE is not set -# CONFIG_SA1100_OMNIMETER is not set -# CONFIG_SA1100_PANGOLIN is not set CONFIG_SA1100_PLEB=y -# CONFIG_SA1100_SHERMAN is not set -# CONFIG_SA1100_PFS168 is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_XP860 is not set -# CONFIG_SA1100_YOPY is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SSP is not set # CONFIG_SA1100_USB is not set -# CONFIG_SA1100_USB_NETLINK is not set -# CONFIG_SA1100_USB_CHAR is not set # -# CLPS711X/EP721X Implementations +# Processor Type # -# CONFIG_ARCH_P720T is not set -# CONFIG_ARCH_ACORN is not set -# CONFIG_FOOTBRIDGE is not set -# CONFIG_FOOTBRIDGE_HOST is not set -# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -# CONFIG_CPU_32v3 is not set -CONFIG_CPU_32v4=y -# CONFIG_CPU_ARM610 is not set -# CONFIG_CPU_ARM710 is not set -# CONFIG_CPU_ARM720T is not set -# CONFIG_CPU_ARM920T is not set -# CONFIG_CPU_ARM1020 is not set -# CONFIG_CPU_SA110 is not set CONFIG_CPU_SA1100=y -CONFIG_DISCONTIGMEM=y -# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4=y +CONFIG_CPU_CACHE_V4WB=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WB=y +CONFIG_CPU_MINICACHE=y + +# +# Processor Features +# # # General setup # -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_DISCONTIGMEM=y +CONFIG_ISA=y +# CONFIG_ZBOOT_ROM is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set CONFIG_CPU_FREQ=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_SA1100=y + +# +# At least one math emulation must be selected +# CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # CONFIG_PM is not set -# CONFIG_APM is not set +# CONFIG_PREEMPT is not set # CONFIG_ARTHUR is not set CONFIG_CMDLINE="console=ttySA0,9600 mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0400000,4M" -# CONFIG_PFS168_CMDLINE is not set # CONFIG_LEDS is not set CONFIG_ALIGNMENT_TRAP=y @@ -138,56 +165,73 @@ CONFIG_ALIGNMENT_TRAP=y # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # -# CONFIG_MTD_CFI is not set -# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set -# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_ABSENT is not set # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_SUN_UFLASH is not set -# CONFIG_MTD_NORA is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_RPXLITE is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_SA1100 is not set -# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set -# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set -# CONFIG_MTD_DC21285 is not set -# CONFIG_MTD_IQ80310 is not set -# CONFIG_MTD_DBOX2 is not set -# CONFIG_MTD_CSTM_MIPS_IXX is not set -# CONFIG_MTD_CFI_FLAGADM is not set # CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_OCELOT is not set +CONFIG_MTD_SA1100=y +# CONFIG_MTD_EDB7312 is not set # # Self-contained MTD device drivers # -# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -195,155 +239,175 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_MTD_NAND is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set -# CONFIG_ISAPNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set # # 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_BLK_DEV_LVM is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # -CONFIG_PACKET=m +CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set +# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set 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=y +# CONFIG_ARPD is not set CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 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_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set # # Ethernet (10 or 100Mbit) # -# CONFIG_NET_ETHERNET is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +CONFIG_SMC91X=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_ACENIC_OMIT_TIGON_I is not set -# CONFIG_MYRI_SBUS 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) +# Ethernet (10000 Mbit) # -# 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 + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # -# Amateur Radio support +# ATA/ATAPI/MFM/RLL support # -# CONFIG_HAMRADIO is not set +# CONFIG_IDE is not set # -# IrDA (infrared) support +# SCSI device support # -# CONFIG_IRDA is not set +# CONFIG_SCSI is not set # -# ATA/IDE/MFM/RLL support +# Fusion MPT device support # -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# IEEE 1394 (FireWire) support # -# CONFIG_SCSI is not set # # I2O device support # -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # ISDN subsystem @@ -351,183 +415,285 @@ CONFIG_DUMMY=m # CONFIG_ISDN is not set # -# Input core support +# Input device support # # CONFIG_INPUT is not set +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# + # # Character devices # # CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_21285 is not set -# CONFIG_SERIAL_21285_OLD is not set -# CONFIG_SERIAL_21285_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -# CONFIG_SERIAL_SA1100_OLD is not set -CONFIG_SERIAL_SA1100_CONSOLE=y -CONFIG_SA1100_DEFAULT_BAUDRATE=9600 -# CONFIG_SERIAL_AMBA is not set -# CONFIG_SERIAL_AMBA_CONSOLE is not set -# CONFIG_SERIAL_CLPS711X is not set -# CONFIG_SERIAL_CLPS711X_CONSOLE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_UCB1200 is not set -# CONFIG_TOUCHSCREEN_UCB1200 is not set -# CONFIG_AUDIO_UCB1200 is not set -# CONFIG_ADC_UCB1200 is not set -# CONFIG_TOUCHSCREEN_BITSY is not set -CONFIG_PROFILER=y -# CONFIG_PFS168_SPI is not set -# CONFIG_PFS168_DTMF is not set -# CONFIG_PFS168_MISC is not set # -# I2C support +# Serial drivers # -# CONFIG_I2C is not set +# CONFIG_SERIAL_8250 is not set # -# Mice +# Non-8250 serial port support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # -# Joysticks +# IPMI # -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_SA1100_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # 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 is not set -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +CONFIG_NFS_DIRECTIO=y # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS 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_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set + +# +# Native Language Support +# +CONFIG_NLS=y +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_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII 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 + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Graphics support +# +# CONFIG_FB is not set # # Sound # # CONFIG_SOUND is not set +# +# Misc devices +# + # # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set # -# Bluetooth support +# USB Gadget Support # -# CONFIG_BT is not set +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set # # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y -# CONFIG_NO_PGT_CACHE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_DC21285_PORT is not set -# CONFIG_DEBUG_CLPS711X_UART2 is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index d9e45878f..907ec6a2c 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,10 +1,13 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Mon Nov 15 15:29:42 2004 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -17,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,6 +29,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=16 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -32,11 +37,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,6 +52,7 @@ CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -59,6 +67,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set @@ -67,15 +76,29 @@ CONFIG_ARCH_S3C2410=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE_PB is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set # -# S3C2410 Implementations +# S3C24XX Implementations # CONFIG_ARCH_BAST=y CONFIG_ARCH_H1940=y CONFIG_ARCH_SMDK2410=y CONFIG_MACH_VR1000=y +CONFIG_MACH_RX3715=y +CONFIG_CPU_S3C2410=y +CONFIG_CPU_S3C2440=y + +# +# S3C2410 Setup +# +CONFIG_S3C2410_DMA=y +# CONFIG_S3C2410_DMA_DEBUG is not set +# CONFIG_S3C2410_PM_DEBUG is not set +# CONFIG_S3C2410_PM_CHECK is not set +CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 # # Processor Type @@ -85,6 +108,7 @@ CONFIG_CPU_ARM920T=y CONFIG_CPU_32v4=y CONFIG_CPU_ABRT_EV4T=y CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y @@ -102,14 +126,14 @@ CONFIG_CPU_TLB_V4WBI=y # CONFIG_ZBOOT_ROM is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +# CONFIG_XIP_KERNEL is not set # # At least one math emulation must be selected # CONFIG_FPE_NWFPE=y -CONFIG_FPE_NWFPE_XP=y +# CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set @@ -120,8 +144,9 @@ CONFIG_BINFMT_AOUT=y CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set -# CONFIG_PM is not set +CONFIG_PM=y # CONFIG_PREEMPT is not set +CONFIG_APM=y # CONFIG_ARTHUR is not set CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0" CONFIG_ALIGNMENT_TRAP=y @@ -130,10 +155,7 @@ CONFIG_ALIGNMENT_TRAP=y # Parallel port support # CONFIG_PARPORT=y -CONFIG_PARPORT_PC=y -CONFIG_PARPORT_PC_CML1=y -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y +# CONFIG_PARPORT_PC is not set # CONFIG_PARPORT_ARC is not set CONFIG_PARPORT_OTHER=y CONFIG_PARPORT_1284=y @@ -143,8 +165,13 @@ CONFIG_PARPORT_1284=y # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set +CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set # # User Modules And Translation Layers @@ -159,14 +186,14 @@ CONFIG_MTD_BLOCK=y # RAM/ROM/Flash chip drivers # CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set CONFIG_MTD_MAP_BANK_WIDTH_1=y CONFIG_MTD_MAP_BANK_WIDTH_2=y CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_16=y # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set CONFIG_MTD_CFI_I1=y CONFIG_MTD_CFI_I2=y @@ -188,6 +215,9 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_IMPA7 is not set +CONFIG_MTD_BAST=y +CONFIG_MTD_BAST_MAXSIZE=4 # # Self-contained MTD device drivers @@ -207,7 +237,13 @@ CONFIG_MTD_CFI_UTIL=y # # NAND Flash Device Drivers # -# CONFIG_MTD_NAND is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_S3C2410=y +# CONFIG_MTD_NAND_S3C2410_DEBUG is not set +# CONFIG_MTD_NAND_S3C2410_HWECC is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set # # Plug and Play support @@ -224,6 +260,16 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # Multi-device support (RAID and LVM) @@ -256,6 +302,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -275,7 +324,6 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -348,13 +396,13 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_IDEFLOPPY=m # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y # CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDE_BAST=y # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -405,10 +453,10 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -477,7 +525,6 @@ CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=y # CONFIG_TIPAR is not set -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -487,16 +534,23 @@ CONFIG_PPDEV=y # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_S3C2410_WATCHDOG=y # CONFIG_NVRAM is not set -CONFIG_RTC=y +# CONFIG_RTC is not set +CONFIG_S3C2410_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -511,16 +565,17 @@ CONFIG_I2C_CHARDEV=m # CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support # -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_SCx200_ACB is not set +CONFIG_I2C_S3C2410=y +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support @@ -534,14 +589,18 @@ CONFIG_I2C_SENSOR=m # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set CONFIG_SENSORS_LM75=m # CONFIG_SENSORS_LM77 is not set CONFIG_SENSORS_LM78=m # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set CONFIG_SENSORS_LM85=m +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -586,6 +645,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -601,6 +661,8 @@ CONFIG_ROMFS_FS=y CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -655,6 +717,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -734,13 +797,14 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Graphics support # CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -761,24 +825,34 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support # # CONFIG_USB_GADGET is not set +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + # # Kernel hacking # -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_INFO=y CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set @@ -788,6 +862,7 @@ CONFIG_DEBUG_S3C2410_UART=0 # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index b5e260236..e98f061a8 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -65,7 +65,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_OMAP is not set -CONFIG_ARCH_VERSATILE_PB=y +CONFIG_ARCH_VERSATILE=y # # CLPS711X/EP721X Implementations @@ -109,6 +109,12 @@ CONFIG_ARCH_VERSATILE_PB=y # S3C2410 Implementations # +# +# Versatile platform type +# +CONFIG_ARCH_VERSATILE_PB=y +# CONFIG_MACH_VERSATILE_AB is not set + # # Processor Type # @@ -144,8 +150,8 @@ CONFIG_ZBOOT_ROM_BSS=0x0 # # At least one math emulation must be selected # -# CONFIG_FPE_NWFPE is not set -CONFIG_FPE_FASTFPE=y +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 1a85e39d7..7c56c5589 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) +AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) # Object file lists. @@ -19,6 +19,9 @@ obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o +obj-$(CONFIG_IWMMXT) += iwmmxt.o +AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt + ifneq ($(CONFIG_ARCH_EBSA110),y) obj-y += io.o endif @@ -26,7 +29,7 @@ endif head-y := head.o obj-$(CONFIG_DEBUG_LL) += debug.o -extra-y := $(head-y) init_task.o vmlinux.lds.s +extra-y := $(head-y) init_task.o vmlinux.lds # Spell out some dependencies that aren't automatically figured out $(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c index a64f78def..70aade05b 100644 --- a/arch/arm/kernel/apm.c +++ b/arch/arm/kernel/apm.c @@ -46,7 +46,13 @@ /* * Maximum number of events stored */ -#define APM_MAX_EVENTS 20 +#define APM_MAX_EVENTS 16 + +struct apm_queue { + unsigned int event_head; + unsigned int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; /* * The per-file APM data @@ -54,27 +60,25 @@ struct apm_user { struct list_head list; - int suser: 1; - int writer: 1; - int reader: 1; - int suspend_wait: 1; - int suspend_result; - - int suspends_pending; - int standbys_pending; - unsigned int suspends_read; - unsigned int standbys_read; + unsigned int suser: 1; + unsigned int writer: 1; + unsigned int reader: 1; - int event_head; - int event_tail; - apm_event_t events[APM_MAX_EVENTS]; + int suspend_result; + unsigned int suspend_state; +#define SUSPEND_NONE 0 /* no suspend pending */ +#define SUSPEND_PENDING 1 /* suspend pending read */ +#define SUSPEND_READ 2 /* suspend read, pending ack */ +#define SUSPEND_ACKED 3 /* suspend acked */ +#define SUSPEND_DONE 4 /* suspend completed */ + + struct apm_queue queue; }; /* * Local variables */ static int suspends_pending; -static int standbys_pending; static int apm_disabled; static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); @@ -83,14 +87,19 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); /* * This is a list of everyone who has opened /dev/apm_bios */ -static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_RWSEM(user_list_lock); static LIST_HEAD(apm_user_list); /* - * The kapmd info. + * kapmd info. kapmd provides us a process context to handle + * "APM" events within - specifically necessary if we're going + * to be suspending the system. */ -static struct task_struct *kapmd; +static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); static DECLARE_COMPLETION(kapmd_exit); +static spinlock_t kapmd_queue_lock = SPIN_LOCK_UNLOCKED; +static struct apm_queue kapmd_queue; + static const char driver_version[] = "1.13"; /* no spaces */ @@ -102,19 +111,6 @@ static const char driver_version[] = "1.13"; /* no spaces */ */ static void __apm_get_power_status(struct apm_power_info *info) { -#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600) - extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *, - u_char *, u_short *); - - if (machine_is_h3600()) { - int dx; - h3600_apm_get_power_status(&info->ac_line_status, - &info->battery_status, &info->battery_flag, - &info->battery_life, &dx); - info->time = dx & 0x7fff; - info->units = dx & 0x8000 ? 0 : 1; - } -#endif } /* @@ -123,65 +119,71 @@ static void __apm_get_power_status(struct apm_power_info *info) void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; EXPORT_SYMBOL(apm_get_power_status); -static int queue_empty(struct apm_user *as) + +/* + * APM event queue management. + */ +static inline int queue_empty(struct apm_queue *q) { - return as->event_head == as->event_tail; + return q->event_head == q->event_tail; } -static apm_event_t get_queued_event(struct apm_user *as) +static inline apm_event_t queue_get_event(struct apm_queue *q) { - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; - return as->events[as->event_tail]; + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + return q->events[q->event_tail]; } -static void queue_event_one_user(struct apm_user *as, apm_event_t event) +static void queue_add_event(struct apm_queue *q, apm_event_t event) { - as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; - if (as->event_head == as->event_tail) { + q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; + if (q->event_head == q->event_tail) { static int notified; if (notified++ == 0) printk(KERN_ERR "apm: an event queue overflowed\n"); - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; } - as->events[as->event_head] = event; - - if (!as->suser || !as->writer) - return; - - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - as->suspends_pending++; - suspends_pending++; - break; + q->events[q->event_head] = event; +} - case APM_SYS_STANDBY: - case APM_USER_STANDBY: - as->standbys_pending++; - standbys_pending++; - break; +static void queue_event_one_user(struct apm_user *as, apm_event_t event) +{ + if (as->suser && as->writer) { + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + /* + * If this user already has a suspend pending, + * don't queue another one. + */ + if (as->suspend_state != SUSPEND_NONE) + return; + + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + break; + } } + queue_add_event(&as->queue, event); } static void queue_event(apm_event_t event, struct apm_user *sender) { - struct list_head *l; - - spin_lock(&user_list_lock); - list_for_each(l, &apm_user_list) { - struct apm_user *as = list_entry(l, struct apm_user, list); + struct apm_user *as; + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { if (as != sender && as->reader) queue_event_one_user(as, event); } - spin_unlock(&user_list_lock); + up_read(&user_list_lock); wake_up_interruptible(&apm_waitqueue); } -static int apm_suspend(void) +static void apm_suspend(void) { - struct list_head *l; + struct apm_user *as; int err = pm_suspend(PM_SUSPEND_MEM); /* @@ -193,52 +195,39 @@ static int apm_suspend(void) /* * Finally, wake up anyone who is sleeping on the suspend. */ - spin_lock(&user_list_lock); - list_for_each(l, &apm_user_list) { - struct apm_user *as = list_entry(l, struct apm_user, list); - + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { as->suspend_result = err; - as->suspend_wait = 0; + as->suspend_state = SUSPEND_DONE; } - spin_unlock(&user_list_lock); + up_read(&user_list_lock); - wake_up_interruptible(&apm_suspend_waitqueue); - return err; + wake_up(&apm_suspend_waitqueue); } static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) { struct apm_user *as = fp->private_data; apm_event_t event; - int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK; + int i = count, ret = 0; if (count < sizeof(apm_event_t)) return -EINVAL; - if (queue_empty(as) && nonblock) + if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) return -EAGAIN; - wait_event_interruptible(apm_waitqueue, !queue_empty(as)); + wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); - while ((i >= sizeof(event)) && !queue_empty(as)) { - event = get_queued_event(as); - printk(" apm_read: event=%d\n", event); + while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { + event = queue_get_event(&as->queue); ret = -EFAULT; if (copy_to_user(buf, &event, sizeof(event))) break; - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - as->suspends_read++; - break; - - case APM_SYS_STANDBY: - case APM_USER_STANDBY: - as->standbys_read++; - break; - } + if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) + as->suspend_state = SUSPEND_READ; buf += sizeof(event); i -= sizeof(event); @@ -252,10 +241,10 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t static unsigned int apm_poll(struct file *fp, poll_table * wait) { - struct apm_user * as = fp->private_data; + struct apm_user *as = fp->private_data; poll_wait(fp, &apm_waitqueue, wait); - return queue_empty(as) ? 0 : POLLIN | POLLRDNORM; + return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; } /* @@ -272,43 +261,65 @@ static int apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { struct apm_user *as = filp->private_data; + unsigned long flags; int err = -EINVAL; if (!as->suser || !as->writer) return -EPERM; switch (cmd) { - case APM_IOC_STANDBY: - break; - case APM_IOC_SUSPEND: - /* - * If we read a suspend command from /dev/apm_bios, - * then the corresponding APM_IOC_SUSPEND ioctl is - * interpreted as an acknowledge. - */ - if (as->suspends_read > 0) { - as->suspends_read--; - as->suspends_pending--; + as->suspend_result = -EINTR; + + if (as->suspend_state == SUSPEND_READ) { + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + as->suspend_state = SUSPEND_ACKED; suspends_pending--; } else { + /* + * Otherwise it is a request to suspend the system. + * Queue an event for all readers, and expect an + * acknowledge from all writers who haven't already + * acknowledged. + */ queue_event(APM_USER_SUSPEND, as); } /* - * If there are outstanding suspend requests for other - * people on /dev/apm_bios, we must sleep for them. - * Last one to bed turns the lights out. + * If there are no further acknowledges required, suspend + * the system. */ - if (suspends_pending > 0) { - as->suspend_wait = 1; - err = wait_event_interruptible(apm_suspend_waitqueue, - as->suspend_wait == 0); - if (err == 0) - err = as->suspend_result; - } else { - err = apm_suspend(); - } + if (suspends_pending == 0) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there are + * pending acknowledges, we wait here for them. + * + * Note that we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + /* + * Note: do not allow a thread which is acking the suspend + * to escape until the resume is complete. + */ + if (as->suspend_state == SUSPEND_ACKED) + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + else + wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + + current->flags = flags; + err = as->suspend_result; + as->suspend_state = SUSPEND_NONE; break; } @@ -320,24 +331,19 @@ static int apm_release(struct inode * inode, struct file * filp) struct apm_user *as = filp->private_data; filp->private_data = NULL; - spin_lock(&user_list_lock); + down_write(&user_list_lock); list_del(&as->list); - spin_unlock(&user_list_lock); + up_write(&user_list_lock); /* * We are now unhooked from the chain. As far as new * events are concerned, we no longer exist. However, we - * need to balance standbys_pending and suspends_pending, - * which means the possibility of sleeping. + * need to balance suspends_pending, which means the + * possibility of sleeping. */ - if (as->standbys_pending > 0) { - standbys_pending -= as->standbys_pending; -// if (standbys_pending <= 0) -// standby(); - } - if (as->suspends_pending > 0) { - suspends_pending -= as->suspends_pending; - if (suspends_pending <= 0) + if (as->suspend_state != SUSPEND_NONE) { + suspends_pending -= 1; + if (suspends_pending == 0) apm_suspend(); } @@ -364,9 +370,9 @@ static int apm_open(struct inode * inode, struct file * filp) as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; - spin_lock(&user_list_lock); + down_write(&user_list_lock); list_add(&as->list, &apm_user_list); - spin_unlock(&user_list_lock); + up_write(&user_list_lock); filp->private_data = as; } @@ -438,7 +444,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length) info.ac_line_status = 0xff; info.battery_status = 0xff; info.battery_flag = 0xff; - info.battery_life = 255; + info.battery_life = -1; info.time = -1; info.units = -1; @@ -461,34 +467,53 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length) } #endif -#if 0 -static int kapmd(void *startup) +static int kapmd(void *arg) { - struct task_struct *tsk = current; + daemonize("kapmd"); + current->flags |= PF_NOFREEZE; - daemonize(); - strcpy(tsk->comm, "kapmd"); - kapmd = tsk; + do { + apm_event_t event; - spin_lock_irq(&tsk->sigmask_lock); - siginitsetinv(&tsk->blocked, sigmask(SIGQUIT)); - recalc_sigpending(tsk); - spin_unlock_irq(&tsk->sigmask_lock); + wait_event_interruptible(kapmd_wait, + !queue_empty(&kapmd_queue) || !pm_active); - complete((struct completion *)startup); + if (!pm_active) + break; - do { - set_task_state(tsk, TASK_INTERRUPTIBLE); - schedule(); - } while (!signal_pending(tsk)); + spin_lock_irq(&kapmd_queue_lock); + event = 0; + if (!queue_empty(&kapmd_queue)) + event = queue_get_event(&kapmd_queue); + spin_unlock_irq(&kapmd_queue_lock); + + switch (event) { + case 0: + break; + + case APM_LOW_BATTERY: + case APM_POWER_STATUS_CHANGE: + queue_event(event, NULL); + break; + + case APM_USER_SUSPEND: + case APM_SYS_SUSPEND: + queue_event(event, NULL); + if (suspends_pending == 0) + apm_suspend(); + break; + + case APM_CRITICAL_SUSPEND: + apm_suspend(); + break; + } + } while (1); complete_and_exit(&kapmd_exit, 0); } -#endif static int __init apm_init(void) { -// struct completion startup = COMPLETION_INITIALIZER(startup); int ret; if (apm_disabled) { @@ -501,22 +526,24 @@ static int __init apm_init(void) return -EINVAL; } -// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES); -// if (ret) -// return ret; -// wait_for_completion(&startup); - pm_active = 1; + ret = kernel_thread(kapmd, NULL, CLONE_KERNEL); + if (ret < 0) { + pm_active = 0; + return ret; + } + #ifdef CONFIG_PROC_FS create_proc_info_entry("apm", 0, NULL, apm_get_info); #endif ret = misc_register(&apm_device); if (ret != 0) { - pm_active = 0; remove_proc_entry("apm", NULL); - send_sig(SIGQUIT, kapmd, 1); + + pm_active = 0; + wake_up(&kapmd_wait); wait_for_completion(&kapmd_exit); } @@ -527,9 +554,10 @@ static void __exit apm_exit(void) { misc_deregister(&apm_device); remove_proc_entry("apm", NULL); + pm_active = 0; -// send_sig(SIGQUIT, kapmd, 1); -// wait_for_completion(&kapmd_exit); + wake_up(&kapmd_wait); + wait_for_completion(&kapmd_exit); } module_init(apm_init); @@ -556,3 +584,27 @@ static int __init apm_setup(char *str) __setup("apm=", apm_setup); #endif + +/** + * apm_queue_event - queue an APM event for kapmd + * @event: APM event + * + * Queue an APM event for kapmd to process and ultimately take the + * appropriate action. Only a subset of events are handled: + * %APM_LOW_BATTERY + * %APM_POWER_STATUS_CHANGE + * %APM_USER_SUSPEND + * %APM_SYS_SUSPEND + * %APM_CRITICAL_SUSPEND + */ +void apm_queue_event(apm_event_t event) +{ + unsigned long flags; + + spin_lock_irqsave(&kapmd_queue_lock, flags); + queue_add_event(&kapmd_queue, event); + spin_unlock_irqrestore(&kapmd_queue_lock, flags); + + wake_up_interruptible(&kapmd_wait); +} +EXPORT_SYMBOL(apm_queue_event); diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 43f0c6694..4c38bd8bc 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -57,10 +57,11 @@ EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter); EXPORT_SYMBOL_ALIAS(fp_printk,printk); EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig); -EXPORT_SYMBOL_NOVERS(__backtrace); +EXPORT_SYMBOL(__backtrace); /* platform dependent support */ -EXPORT_SYMBOL(udelay); +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__const_udelay); /* networking */ EXPORT_SYMBOL(csum_partial); @@ -69,43 +70,44 @@ EXPORT_SYMBOL(__csum_ipv6_magic); /* io */ #ifndef __raw_readsb -EXPORT_SYMBOL_NOVERS(__raw_readsb); +EXPORT_SYMBOL(__raw_readsb); #endif #ifndef __raw_readsw -EXPORT_SYMBOL_NOVERS(__raw_readsw); +EXPORT_SYMBOL(__raw_readsw); #endif #ifndef __raw_readsl -EXPORT_SYMBOL_NOVERS(__raw_readsl); +EXPORT_SYMBOL(__raw_readsl); #endif #ifndef __raw_writesb -EXPORT_SYMBOL_NOVERS(__raw_writesb); +EXPORT_SYMBOL(__raw_writesb); #endif #ifndef __raw_writesw -EXPORT_SYMBOL_NOVERS(__raw_writesw); +EXPORT_SYMBOL(__raw_writesw); #endif #ifndef __raw_writesl -EXPORT_SYMBOL_NOVERS(__raw_writesl); +EXPORT_SYMBOL(__raw_writesl); #endif /* string / mem functions */ -EXPORT_SYMBOL_NOVERS(strcpy); -EXPORT_SYMBOL_NOVERS(strncpy); -EXPORT_SYMBOL_NOVERS(strcat); -EXPORT_SYMBOL_NOVERS(strncat); -EXPORT_SYMBOL_NOVERS(strcmp); -EXPORT_SYMBOL_NOVERS(strncmp); -EXPORT_SYMBOL_NOVERS(strchr); -EXPORT_SYMBOL_NOVERS(strlen); -EXPORT_SYMBOL_NOVERS(strnlen); -EXPORT_SYMBOL_NOVERS(strpbrk); -EXPORT_SYMBOL_NOVERS(strrchr); -EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(__memzero); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memchr); +EXPORT_SYMBOL(__memzero); /* user mem (segment) */ EXPORT_SYMBOL(__arch_copy_from_user); @@ -114,30 +116,30 @@ EXPORT_SYMBOL(__arch_clear_user); EXPORT_SYMBOL(__arch_strnlen_user); EXPORT_SYMBOL(__arch_strncpy_from_user); -EXPORT_SYMBOL_NOVERS(__get_user_1); -EXPORT_SYMBOL_NOVERS(__get_user_2); -EXPORT_SYMBOL_NOVERS(__get_user_4); -EXPORT_SYMBOL_NOVERS(__get_user_8); +EXPORT_SYMBOL(__get_user_1); +EXPORT_SYMBOL(__get_user_2); +EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__get_user_8); -EXPORT_SYMBOL_NOVERS(__put_user_1); -EXPORT_SYMBOL_NOVERS(__put_user_2); -EXPORT_SYMBOL_NOVERS(__put_user_4); -EXPORT_SYMBOL_NOVERS(__put_user_8); +EXPORT_SYMBOL(__put_user_1); +EXPORT_SYMBOL(__put_user_2); +EXPORT_SYMBOL(__put_user_4); +EXPORT_SYMBOL(__put_user_8); /* gcc lib functions */ -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__divsi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(__modsi3); -EXPORT_SYMBOL_NOVERS(__muldi3); -EXPORT_SYMBOL_NOVERS(__ucmpdi2); -EXPORT_SYMBOL_NOVERS(__udivdi3); -EXPORT_SYMBOL_NOVERS(__umoddi3); -EXPORT_SYMBOL_NOVERS(__udivmoddi4); -EXPORT_SYMBOL_NOVERS(__udivsi3); -EXPORT_SYMBOL_NOVERS(__umodsi3); -EXPORT_SYMBOL_NOVERS(__do_div64); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__muldi3); +EXPORT_SYMBOL(__ucmpdi2); +EXPORT_SYMBOL(__udivdi3); +EXPORT_SYMBOL(__umoddi3); +EXPORT_SYMBOL(__udivmoddi4); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umodsi3); +EXPORT_SYMBOL(__do_div64); /* bitops */ EXPORT_SYMBOL(_set_bit_le); @@ -148,6 +150,8 @@ EXPORT_SYMBOL(_change_bit_le); EXPORT_SYMBOL(_test_and_change_bit_le); EXPORT_SYMBOL(_find_first_zero_bit_le); EXPORT_SYMBOL(_find_next_zero_bit_le); +EXPORT_SYMBOL(_find_first_bit_le); +EXPORT_SYMBOL(_find_next_bit_le); #ifdef __ARMEB__ EXPORT_SYMBOL(_set_bit_be); @@ -158,6 +162,8 @@ EXPORT_SYMBOL(_change_bit_be); EXPORT_SYMBOL(_test_and_change_bit_be); EXPORT_SYMBOL(_find_first_zero_bit_be); EXPORT_SYMBOL(_find_next_zero_bit_be); +EXPORT_SYMBOL(_find_first_bit_be); +EXPORT_SYMBOL(_find_next_bit_be); #endif /* syscalls */ diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index c54132421..93525fdf2 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include /* * Make sure that the compiler and target are compatible. @@ -48,16 +50,30 @@ int main(void) { DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); + DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); + DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); + DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); + DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); + DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); + DEFINE(TI_IWMMXT_STATE, (offsetof(struct thread_info, fpstate)+4)&~7); + BLANK(); #if __LINUX_ARM_ARCH__ >= 6 DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); -#endif BLANK(); +#endif DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); BLANK(); DEFINE(VM_EXEC, VM_EXEC); BLANK(); DEFINE(PAGE_SZ, PAGE_SIZE); + DEFINE(VIRT_OFFSET, PAGE_OFFSET); BLANK(); DEFINE(SYS_ERROR0, 0x9f0000); BLANK(); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 927711c48..ad26e98f1 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -17,6 +17,7 @@ #include static int debug_pci; +static int use_firmware; /* * We can't use pci_find_device() here since we are @@ -128,12 +129,14 @@ static void __devinit pci_fixup_83c553(struct pci_dev *dev) pci_write_config_word(dev, 0x44, 0xb000); outb(0x08, 0x4d1); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553); static void __devinit pci_fixup_unassign(struct pci_dev *dev) { dev->resource[0].end -= dev->resource[0].start; dev->resource[0].start = 0; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, pci_fixup_unassign); /* * Prevent the PCI layer from seeing the resources allocated to this device @@ -154,6 +157,7 @@ static void __devinit pci_fixup_dec21285(struct pci_dev *dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_dec21285); /* * Same as above. The PrPMC800 carrier board for the PrPMC1100 @@ -178,6 +182,7 @@ static void __devinit pci_fixup_prpmc1100(struct pci_dev *dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP4XX, pci_fixup_prpmc1100); /* * PCI IDE controllers use non-standard I/O port decoding, respect it. @@ -198,6 +203,7 @@ static void __devinit pci_fixup_ide_bases(struct pci_dev *dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); /* * Put the DEC21142 to sleep @@ -206,6 +212,7 @@ static void __devinit pci_fixup_dec21142(struct pci_dev *dev) { pci_write_config_dword(dev, 0x40, 0x80000000); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, pci_fixup_dec21142); /* * The CY82C693 needs some rather major fixups to ensure that it does @@ -271,38 +278,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev) pci_write_config_byte(dev, 0x45, 0x03); } } - -struct pci_fixup pcibios_fixups[] = { - { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, - pci_fixup_cy82c693 - }, { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, - pci_fixup_dec21142 - }, { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, - pci_fixup_dec21285 - }, { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, - pci_fixup_83c553 - }, { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, - pci_fixup_unassign - }, { - PCI_FIXUP_HEADER, - PCI_ANY_ID, PCI_ANY_ID, - pci_fixup_ide_bases - }, { - PCI_FIXUP_HEADER, - PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP4XX, - pci_fixup_prpmc1100 - }, { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) { @@ -596,15 +572,17 @@ void __init pci_common_init(struct hw_pci *hw) list_for_each_entry(sys, &hw->buses, node) { struct pci_bus *bus = sys->bus; - /* - * Size the bridge windows. - */ - pci_bus_size_bridges(bus); + if (!use_firmware) { + /* + * Size the bridge windows. + */ + pci_bus_size_bridges(bus); - /* - * Assign resources. - */ - pci_bus_assign_resources(bus); + /* + * Assign resources. + */ + pci_bus_assign_resources(bus); + } /* * Tell drivers about devices found. @@ -618,6 +596,9 @@ char * __init pcibios_setup(char *str) if (!strcmp(str, "debug")) { debug_pci = 1; return NULL; + } else if (!strcmp(str, "firmware")) { + use_firmware = 1; + return NULL; } return str; } @@ -700,7 +681,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, if (mmap_state == pci_mmap_io) { return -EINVAL; } else { - phys = root->mem_offset + (vma->vm_pgoff << PAGE_SHIFT); + phys = vma->vm_pgoff + (root->mem_offset >> PAGE_SHIFT); } /* @@ -709,7 +690,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_page_range(vma, vma->vm_start, phys, + if (remap_pfn_range(vma, vma->vm_start, phys, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 3da0b8091..d868099d1 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -1,7 +1,7 @@ /* * linux/arch/arm/kernel/calls.S * - * Copyright (C) 1995-2003 Russell King + * Copyright (C) 1995-2004 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -288,6 +288,13 @@ __syscall_start: .long sys_pciconfig_iobase .long sys_pciconfig_read .long sys_pciconfig_write + .long sys_mq_open +/* 275 */ .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive + .long sys_mq_notify + .long sys_mq_getsetattr +/* 280 */ .long sys_waitid __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 822dbde5a..78146b6c3 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -411,10 +411,16 @@ .macro addruart,rx mov \rx, #0xfe000000 @ physical -#ifdef CONFIG_ARCH_IQ80310 - orr \rx, \rx, #0x00810000 @ location of the UART -#elif defined(CONFIG_ARCH_IQ80321) +#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244) orr \rx, \rx, #0x00800000 @ location of the UART +#elif defined(CONFIG_ARCH_IOP331) + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x000fe000 @ Physical Base + movne \rx, #0 + orr \rx, \rx, #0xfe000000 + orr \rx, \rx, #0x00f00000 @ Virtual Base + orr \rx, \rx, #0x00001700 @ location of the UART #else #error Unknown IOP3XX implementation #endif @@ -432,7 +438,7 @@ .endm .macro waituart,rd,rx -#ifndef CONFIG_ARCH_IQ80321 +#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331) 1001: ldrb \rd, [\rx, #0x6] tst \rd, #0x10 beq 1001b @@ -464,6 +470,36 @@ .macro busyuart,rd,rx .endm +#elif defined(CONFIG_ARCH_IXP2000) + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0xc0000000 @ Physical base + movne \rx, #0xfe000000 @ virtual base + orrne \rx, \rx, #0x00f00000 + orr \rx, \rx, #0x00030000 +#ifdef __ARMEB__ + orr \rx, \rx, #0x00000003 +#endif + .endm + + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x14] + tst \rd, #0x20 + beq 1002b + .endm + + .macro waituart,rd,rx + nop + nop + nop + .endm + #elif defined(CONFIG_ARCH_OMAP) .macro addruart,rx @@ -502,6 +538,9 @@ #elif defined(CONFIG_ARCH_S3C2410) #include #include +#include +#define S3C2410_UART1_OFF (0x4000) +#define SHIFT_2440TXF (14-9) .macro addruart, rx mrc p15, 0, \rx, c1, c0 @@ -523,7 +562,17 @@ beq 1001f @ @ FIFO enabled... 1003: + mrc p15, 0, \rd, c1, c0 + tst \rd, #1 + addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) + addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART) + bic \rd, \rd, #0xff000 + ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + and \rd, \rd, #0x00ff0000 + teq \rd, #0x00440000 @ is it 2440? + ldr \rd, [ \rx, # S3C2410_UFSTAT ] + moveq \rd, \rd, lsr #SHIFT_2440TXF tst \rd, #S3C2410_UFSTAT_TXFULL bne 1003b b 1002f @@ -544,8 +593,19 @@ beq 1001f @ @ FIFO enabled... 1003: + mrc p15, 0, \rd, c1, c0 + tst \rd, #1 + addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART) + addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART) + bic \rd, \rd, #0xff000 + ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + and \rd, \rd, #0x00ff0000 + teq \rd, #0x00440000 @ is it 2440? + ldr \rd, [ \rx, # S3C2410_UFSTAT ] - ands \rd, \rd, #15< @@ -615,6 +675,60 @@ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy bne 1001b .endm + +#elif defined(CONFIG_ARCH_IMX) + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x00000000 @ physical + movne \rx, #0xe0000000 @ virtual + orr \rx, \rx, #0x00200000 + orr \rx, \rx, #0x00006000 @ UART1 offset + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x40] @ TXDATA + .endm + + .macro waituart,rd,rx + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #0x98] @ SR2 + tst \rd, #1 << 3 @ TXDC + beq 1002b @ wait until transmit done + .endm + +#elif defined(CONFIG_ARCH_H720X) + + .equ io_virt, IO_BASE + .equ io_phys, IO_START + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #io_phys @ physical base address + movne \rx, #io_virt @ virtual address + add \rx, \rx, #0x00020000 @ UART1 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0x0] @ UARTDR + + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x18] @ UARTFLG + tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full + bne 1001b + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x18] @ UARTFLG + tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy + bne 1001b + .endm #else #error Unknown architecture #endif diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index d3dafbf4f..3f6b4b529 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -53,18 +54,14 @@ #define HAVE_EXPMASK #endif -enum req { - req_readbytes, - req_reset -}; - struct ecard_request { - enum req req; + void (*fn)(struct ecard_request *); ecard_t *ec; unsigned int address; unsigned int length; unsigned int use_loader; void *buffer; + struct completion *complete; }; struct expcard_blacklist { @@ -129,15 +126,14 @@ slot_to_ecard(unsigned int slot) #define POD_INT_ADDR(x) ((volatile unsigned char *)\ ((BUS_ADDR((x)) - IO_BASE) + IO_START)) -static inline void ecard_task_reset(struct ecard_request *req) +static void ecard_task_reset(struct ecard_request *req) { struct expansion_card *ec = req->ec; if (ec->loader) ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader); } -static void -ecard_task_readbytes(struct ecard_request *req) +static void ecard_task_readbytes(struct ecard_request *req) { unsigned char *buf = (unsigned char *)req->buffer; volatile unsigned char *base_addr = @@ -206,26 +202,9 @@ ecard_task_readbytes(struct ecard_request *req) } -static void ecard_do_request(struct ecard_request *req) -{ - switch (req->req) { - case req_readbytes: - ecard_task_readbytes(req); - break; - - case req_reset: - ecard_task_reset(req); - break; - } -} - -#include - -static pid_t ecard_pid; -static wait_queue_head_t ecard_wait; +static DECLARE_WAIT_QUEUE_HEAD(ecard_wait); static struct ecard_request *ecard_req; - -static DECLARE_COMPLETION(ecard_completion); +static DECLARE_MUTEX(ecard_sem); /* * Set up the expansion card daemon's page tables. @@ -282,8 +261,6 @@ static int ecard_init_mm(void) static int ecard_task(void * unused) { - struct task_struct *tsk = current; - daemonize("kecardd"); /* @@ -298,17 +275,13 @@ ecard_task(void * unused) while (1) { struct ecard_request *req; - do { - req = xchg(&ecard_req, NULL); - - if (req == NULL) { - sigemptyset(&tsk->pending.signal); - interruptible_sleep_on(&ecard_wait); - } - } while (req == NULL); + wait_event_interruptible(ecard_wait, ecard_req != NULL); - ecard_do_request(req); - complete(&ecard_completion); + req = xchg(&ecard_req, NULL); + if (req != NULL) { + req->fn(req); + complete(req->complete); + } } } @@ -318,25 +291,21 @@ ecard_task(void * unused) * FIXME: The test here is not sufficient to detect if the * kcardd is running. */ -static void -ecard_call(struct ecard_request *req) +static void ecard_call(struct ecard_request *req) { - /* - * Make sure we have a context that is able to sleep. - */ - if (current == &init_task || in_interrupt()) - BUG(); + DECLARE_COMPLETION(completion); - if (ecard_pid <= 0) - ecard_pid = kernel_thread(ecard_task, NULL, CLONE_KERNEL); + req->complete = &completion; + down(&ecard_sem); ecard_req = req; wake_up(&ecard_wait); /* * Now wait for kecardd to run. */ - wait_for_completion(&ecard_completion); + wait_for_completion(&completion); + up(&ecard_sem); } /* ======================= Mid-level card control ===================== */ @@ -346,7 +315,7 @@ ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) { struct ecard_request req; - req.req = req_readbytes; + req.fn = ecard_task_readbytes; req.ec = ec; req.address = off; req.length = len; @@ -534,27 +503,33 @@ void ecard_disablefiq(unsigned int fiqnr) } } -static void -ecard_dump_irq_state(ecard_t *ec) +static void ecard_dump_irq_state(void) { - printk(" %d: %sclaimed, ", - ec->slot_no, - ec->claimed ? "" : "not "); - - if (ec->ops && ec->ops->irqpending && - ec->ops != &ecard_default_ops) - printk("irq %spending\n", - ec->ops->irqpending(ec) ? "" : "not "); - else - printk("irqaddr %p, mask = %02X, status = %02X\n", - ec->irqaddr, ec->irqmask, *ec->irqaddr); + ecard_t *ec; + + printk("Expansion card IRQ state:\n"); + + for (ec = cards; ec; ec = ec->next) { + if (ec->slot_no == 8) + continue; + + printk(" %d: %sclaimed, ", + ec->slot_no, ec->claimed ? "" : "not "); + + if (ec->ops && ec->ops->irqpending && + ec->ops != &ecard_default_ops) + printk("irq %spending\n", + ec->ops->irqpending(ec) ? "" : "not "); + else + printk("irqaddr %p, mask = %02X, status = %02X\n", + ec->irqaddr, ec->irqmask, *ec->irqaddr); + } } static void ecard_check_lockup(struct irqdesc *desc) { static unsigned long last; static int lockup; - ecard_t *ec; /* * If the timer interrupt has not run since the last million @@ -572,11 +547,7 @@ static void ecard_check_lockup(struct irqdesc *desc) "disabling all expansion card interrupts\n"); desc->chip->mask(IRQ_EXPANSIONCARD); - - printk("Expansion card IRQ state:\n"); - - for (ec = cards; ec; ec = ec->next) - ecard_dump_irq_state(ec); + ecard_dump_irq_state(); } } else lockup = 0; @@ -588,6 +559,7 @@ static void ecard_check_lockup(struct irqdesc *desc) if (!last || time_after(jiffies, last + 5*HZ)) { last = jiffies; printk(KERN_WARNING "Unrecognised interrupt from backplane\n"); + ecard_dump_irq_state(); } } @@ -1066,9 +1038,14 @@ nomem: */ static int __init ecard_init(void) { - int slot, irqhw; + int slot, irqhw, ret; - init_waitqueue_head(&ecard_wait); + ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL); + if (ret < 0) { + printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n", + ret); + return ret; + } printk("Probing expansion cards\n"); @@ -1151,7 +1128,7 @@ static void ecard_drv_shutdown(struct device *dev) if (drv->shutdown) drv->shutdown(ec); ecard_release(ec); - req.req = req_reset; + req.fn = ecard_task_reset; req.ec = ec; ecard_call(&req); } diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7fe5c2d39..44cd34784 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -464,7 +464,7 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm -#elif defined(CONFIG_ARCH_VERSATILE_PB) +#elif defined(CONFIG_ARCH_VERSATILE) .macro disable_fiq .endm @@ -562,40 +562,6 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm -#elif defined(CONFIG_ARCH_IOP310) - - .macro disable_fiq - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC - mrc p13, 0, \base, c0, c0, 0 @ get INTCTL - - tst \irqstat, #(1<<29) @ if INTSRC_BI - tstne \base, #(1<<3) @ and INTCTL_BM - movne \irqnr, #IRQ_XS80200_BCU - bne 1001f - - tst \irqstat, #(1<<28) @ if INTSRC_PI - tstne \base, #(1<<2) @ and INTCTL_PM - movne \irqnr, #IRQ_XS80200_PMU - bne 1001f - - tst \irqstat, #(1<<31) @ if INTSRC_FI - tstne \base, #(1<<0) @ and INTCTL_FM - movne \irqnr, #IRQ_XS80200_EXTFIQ - bne 1001f - - tst \irqstat, #(1<<30) @ if INTSRC_II - tstne \base, #(1<<1) @ and INTCTL_IM - movne \irqnr, #IRQ_XS80200_EXTIRQ - -1001: - .endm - - .macro irq_prio_table - .endm - #elif defined(CONFIG_ARCH_IOP321) .macro disable_fiq .endm @@ -618,6 +584,39 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_IOP331) + .macro disable_fiq + .endm + + /* + * Note: only deal with normal interrupts, not FIQ + */ + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \irqnr, #0 + mrc p6, 0, \irqstat, c4, c0, 0 @ Read IINTSRC0 + cmp \irqstat, #0 + bne 1002f + mrc p6, 0, \irqstat, c5, c0, 0 @ Read IINTSRC1 + cmp \irqstat, #0 + beq 1001f + clz \irqnr, \irqstat +/* + * mov \base, #31 + * subs \irqnr,\base,\irqnr + */ + rsbs \irqnr,\irqnr,#31 @ recommend by RMK + add \irqnr,\irqnr,#IRQ_IOP331_XINT8 + b 1001f +1002: clz \irqnr, \irqstat + mov \base, #31 + subs \irqnr,\base,\irqnr + add \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT +1001: + .endm + + .macro irq_prio_table + .endm + #elif defined(CONFIG_ARCH_PXA) .macro disable_fiq @@ -645,6 +644,60 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_IXP2000) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + mov \irqnr, #0x0 @clear out irqnr as default + mov \base, #0xfe000000 + orr \base, \base, #0x00ff0000 + orr \base, \base, #0x0000a000 + orr \base, \base, #0x08 + ldr \irqstat, [\base] @ get interrupts + mov \tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000 + orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000 + orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00 + orr \tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff + and \irqstat, \irqstat, \tmp + + cmp \irqstat, #0 + beq 1001f + + clz \irqnr, \irqstat + mov \base, #31 + subs \irqnr, \base, \irqnr + + /* + * We handle PCIA and PCIB here so we don't have an + * extra layer of code just to check these two bits. + */ + cmp \irqnr, #IRQ_IXP2000_PCI + bne 1001f + + mov \base, #0xfe000000 + orr \base, \base, #0x00fd0000 + orr \base, \base, #0x0000e100 + orr \base, \base, #0x00000058 + ldr \irqstat, [\base] + + mov \tmp, #(1<<26) + tst \irqstat, \tmp + movne \irqnr, #IRQ_IXP2000_PCIA + bne 1001f + + mov \tmp, #(1<<27) + tst \irqstat, \tmp + movne \irqnr, #IRQ_IXP2000_PCIB + +1001: + .endm + + .macro irq_prio_table + .endm + #elif defined (CONFIG_ARCH_IXP4XX) .macro disable_fiq @@ -884,6 +937,82 @@ ENTRY(soft_irq_mask) .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_IMX) + + .macro disable_fiq + .endm +#define AITC_NIVECSR 0x40 + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE) + @ Load offset & priority of the highest priority + @ interrupt pending. + ldr \irqnr, [\irqstat, #AITC_NIVECSR] + @ Shift off the priority leaving the offset or + @ "interrupt number" + mov \irqnr, \irqnr, lsr #16 + ldr \irqstat, =1 @ dummy compare + ldr \base, =0xFFFF // invalid interrupt + cmp \irqnr, \base + bne 1001f + ldr \irqstat, =0 +1001: + tst \irqstat, #1 @ to make the condition code = TRUE + .endm + + .macro irq_prio_table + .endm + +#elif defined(CONFIG_ARCH_H720X) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202) + @ we could use the id register on H7202, but this is not + @ properly updated when we come back from asm_do_irq + @ without a previous return from interrupt + @ (see loops below in irq_svc, irq_usr) + @ We see unmasked pending ints only, as the masked pending ints + @ are not visible here + + mov \base, #0xf0000000 @ base register + orr \base, \base, #0x24000 @ irqbase + ldr \irqstat, [\base, #0x04] @ get interrupt status +#if defined (CONFIG_CPU_H7201) + ldr \tmp, =0x001fffff +#else + mvn \tmp, #0xc0000000 +#endif + and \irqstat, \irqstat, \tmp @ mask out unused ints + mov \irqnr, #0 + + mov \tmp, #0xff00 + orr \tmp, \tmp, #0xff + tst \irqstat, \tmp + addeq \irqnr, \irqnr, #16 + moveq \irqstat, \irqstat, lsr #16 + tst \irqstat, #255 + addeq \irqnr, \irqnr, #8 + moveq \irqstat, \irqstat, lsr #8 + tst \irqstat, #15 + addeq \irqnr, \irqnr, #4 + moveq \irqstat, \irqstat, lsr #4 + tst \irqstat, #3 + addeq \irqnr, \irqnr, #2 + moveq \irqstat, \irqstat, lsr #2 + tst \irqstat, #1 + addeq \irqnr, \irqnr, #1 + moveq \irqstat, \irqstat, lsr #1 + tst \irqstat, #1 @ bit 0 should be set + .endm + + .macro irq_prio_table + .endm + +#else +#error hynix processor selection missmatch +#endif #else #error Unknown architecture #endif @@ -1174,7 +1303,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go * r0 - instruction opcode. * r10 - this threads thread_info structure. */ -call_fpe: enable_irq r10 @ Enable interrupts +call_fpe: tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) and r8, r0, #0x0f000000 @ mask out op-code bits @@ -1186,6 +1315,14 @@ call_fpe: enable_irq r10 @ Enable interrupts mov r7, #1 add r6, r10, #TI_USED_CP strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] +#ifdef CONFIG_IWMMXT + @ Test if we need to give access to iWMMXt coprocessors + ldr r5, [r10, #TI_FLAGS] + rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only + movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) + bcs iwmmxt_task_enable +#endif + enable_irq r7 add pc, pc, r8, lsr #6 mov r0, r0 @@ -1264,7 +1401,11 @@ ENTRY(ret_from_exception) ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_CPU_DOMAIN]! - stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack + stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack +#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) + mra r4, r5, acc0 + stmia ip, {r4, r5} +#endif mcr p15, 0, r3, c3, c0, 0 @ Set domain register #ifdef CONFIG_VFP @ Always disable VFP so we can lazily save/restore the old @@ -1272,6 +1413,13 @@ ENTRY(__switch_to) VFPFMRX r4, FPEXC bic r4, r4, #FPEXC_ENABLE VFPFMXR FPEXC, r4 +#endif +#if defined(CONFIG_IWMMXT) + bl iwmmxt_task_switch +#elif defined(CONFIG_CPU_XSCALE) + add r4, r2, #40 @ cpu_context_save->extra + ldmib r4, {r4, r5} + mar acc0, r4, r5 #endif ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously @@ -1509,6 +1657,8 @@ __stubs_end: ENTRY(__trap_init) stmfd sp!, {r4 - r6, lr} + mov r0, #0xff000000 + orr r0, r0, #0x00ff0000 @ high vectors position adr r1, .LCvectors @ set up the vectors ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 6f7938162..894de5af4 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -46,32 +46,16 @@ #include #include -#define FIQ_VECTOR (vectors_base() + 0x1c) - static unsigned long no_fiq_insn; -static inline void unprotect_page_0(void) -{ - modify_domain(DOMAIN_USER, DOMAIN_MANAGER); -} - -static inline void protect_page_0(void) -{ - modify_domain(DOMAIN_USER, DOMAIN_CLIENT); -} - /* Default reacquire function * - we always relinquish FIQ control * - we always reacquire FIQ control */ static int fiq_def_op(void *ref, int relinquish) { - if (!relinquish) { - unprotect_page_0(); - *(unsigned long *)FIQ_VECTOR = no_fiq_insn; - protect_page_0(); - flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + 4); - } + if (!relinquish) + set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); return 0; } @@ -93,12 +77,10 @@ int show_fiq_list(struct seq_file *p, void *v) void set_fiq_handler(void *start, unsigned int length) { - unprotect_page_0(); - - memcpy((void *)FIQ_VECTOR, start, length); - - protect_page_0(); - flush_icache_range(FIQ_VECTOR, FIQ_VECTOR + length); + memcpy((void *)0xffff001c, start, length); + flush_icache_range(0xffff001c, 0xffff001c + length); + if (!vectors_high()) + flush_icache_range(0x1c, 0x1c + length); } /* @@ -198,6 +180,5 @@ EXPORT_SYMBOL(disable_fiq); void __init init_FIQ(void) { - no_fiq_insn = *(unsigned long *)FIQ_VECTOR; - set_fs(get_fs()); + no_fiq_insn = *(unsigned long *)0xffff001c; } diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 6958a8b3f..946c50c2a 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -1,5 +1,5 @@ /* - * linux/arch/arm/kernel/head-armv.S + * linux/arch/arm/kernel/head.S * * Copyright (C) 1994-2002 Russell King * @@ -19,17 +19,16 @@ #include #include +#ifndef CONFIG_XIP_KERNEL /* * We place the page tables 16K below TEXTADDR. Therefore, we must make sure * that TEXTADDR is correctly set. Currently, we expect the least significant * 16 bits to be 0x8000, but we could probably relax this restriction to - * TEXTADDR > PAGE_OFFSET + 0x4000 + * TEXTADDR >= PAGE_OFFSET + 0x4000 * * Note that swapper_pg_dir is the virtual address of the page tables, and * pgtbl gives us a position-independent reference to these tables. We can * do this because stext == TEXTADDR - * - * swapper_pg_dir, pgtbl and krnladr are all closely related. */ #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 @@ -38,19 +37,35 @@ .globl swapper_pg_dir .equ swapper_pg_dir, TEXTADDR - 0x4000 - .macro pgtbl, reg - adr \reg, stext - sub \reg, \reg, #0x4000 + .macro pgtbl, rd, phys + adr \rd, stext + sub \rd, \rd, #0x4000 .endm - +#else /* - * Since the page table is closely related to the kernel start address, we - * can convert the page table base address to the base address of the section - * containing both. + * XIP Kernel: + * + * We place the page tables 16K below DATAADDR. Therefore, we must make sure + * that DATAADDR is correctly set. Currently, we expect the least significant + * 16 bits to be 0x8000, but we could probably relax this restriction to + * DATAADDR >= PAGE_OFFSET + 0x4000 + * + * Note that pgtbl is meant to return the physical address of swapper_pg_dir. + * We can't make it relative to the kernel position in this case since + * the kernel can physically be anywhere. */ - .macro krnladr, rd, pgtable - bic \rd, \pgtable, #0x000ff000 +#if (DATAADDR & 0xffff) != 0x8000 +#error DATAADDR must start at 0xXXXX8000 +#endif + + .globl swapper_pg_dir + .equ swapper_pg_dir, DATAADDR - 0x4000 + + .macro pgtbl, rd, phys + ldr \rd, =((DATAADDR - 0x4000) - VIRT_OFFSET) + add \rd, \rd, \phys .endm +#endif /* * Kernel startup entry point. @@ -99,6 +114,8 @@ ENTRY(stext) .type __switch_data, %object __switch_data: .long __mmap_switched + .long __data_loc @ r2 + .long __data_start @ r3 .long __bss_start @ r4 .long _end @ r5 .long processor_id @ r6 @@ -136,12 +153,20 @@ __turn_mmu_on: */ .align 5 __mmap_switched: - adr r3, __switch_data + 4 - ldmia r3, {r4, r5, r6, r7, r8, sp} + adr r2, __switch_data + 4 + ldmia r2, {r2, r3, r4, r5, r6, r7, r8, sp} + + cmp r2, r3 @ Copy data segment if needed +1: cmpne r3, r4 + ldrne fp, [r2], #4 + strne fp, [r3], #4 + bne 1b + mov fp, #0 @ Clear BSS (and zero fp) 1: cmp r4, r5 strcc fp, [r4],#4 bcc 1b + str r9, [r6] @ Save processor ID str r1, [r7] @ Save machine type bic r2, r0, #2 @ Clear 'A' bit @@ -156,16 +181,13 @@ __mmap_switched: * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * We only map in 4MB of RAM, which should be sufficient in - * all cases. - * * r5 = physical address of start of RAM * r6 = physical IO address * r7 = byte offset into page tables for IO * r8 = page table flags */ __create_page_tables: - pgtbl r4 @ page table address + pgtbl r4, r5 @ page table address /* * Clear the 16K level 1 swapper page table @@ -183,28 +205,50 @@ __create_page_tables: /* * Create identity mapping for first MB of kernel to * cater for the MMU enable. This identity mapping - * will be removed by paging_init() + * will be removed by paging_init(). We use our current program + * counter to determine corresponding section base address. */ - krnladr r2, r4 @ start of kernel - add r3, r8, r2 @ flags + kernel base - str r3, [r4, r2, lsr #18] @ identity mapping + mov r2, pc, lsr #20 @ start of kernel section + add r3, r8, r2, lsl #20 @ flags + kernel base + str r3, [r4, r2, lsl #2] @ identity mapping /* * Now setup the pagetables for our kernel direct * mapped region. We round TEXTADDR down to the - * nearest megabyte boundary. + * nearest megabyte boundary. It is assumed that + * the kernel fits within 4 contigous 1MB sections. */ - add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel - bic r2, r3, #0x00f00000 - str r2, [r0] @ PAGE_OFFSET + 0MB - add r0, r0, #(TEXTADDR & 0x00f00000) >> 18 - str r3, [r0], #4 @ KERNEL + 0MB + add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel + str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]! add r3, r3, #1 << 20 - str r3, [r0], #4 @ KERNEL + 1MB + str r3, [r0, #4]! @ KERNEL + 1MB add r3, r3, #1 << 20 - str r3, [r0], #4 @ KERNEL + 2MB + str r3, [r0, #4]! @ KERNEL + 2MB add r3, r3, #1 << 20 - str r3, [r0], #4 @ KERNEL + 3MB + str r3, [r0, #4] @ KERNEL + 3MB + + /* + * Then map first 1MB of ram in case it contains our boot params. + */ + add r0, r4, #VIRT_OFFSET >> 18 + add r2, r5, r8 + str r2, [r0] + +#ifdef CONFIG_XIP_KERNEL + /* + * Map some ram to cover our .data and .bss areas. + * Mapping 3MB should be plenty. + */ + sub r3, r4, r5 + mov r3, r3, lsr #20 + add r0, r0, r3, lsl #2 + add r2, r2, r3, lsl #20 + str r2, [r0], #4 + add r2, r2, #(1 << 20) + str r2, [r0], #4 + add r2, r2, #(1 << 20) + str r2, [r0] +#endif bic r8, r8, #0x0c @ turn off cacheable @ and bufferable bits @@ -255,6 +299,7 @@ __create_page_tables: str r3, [r0] #endif mov pc, lr + .ltorg diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index 9e8868bc5..6c20c1188 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -7,7 +7,7 @@ * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void _memcpy_fromio(void *to, unsigned long from, size_t count) +void _memcpy_fromio(void *to, void __iomem *from, size_t count) { unsigned char *t = to; while (count) { @@ -22,7 +22,7 @@ void _memcpy_fromio(void *to, unsigned long from, size_t count) * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void _memcpy_toio(unsigned long to, const void *from, size_t count) +void _memcpy_toio(void __iomem *to, const void *from, size_t count) { const unsigned char *f = from; while (count) { @@ -37,7 +37,7 @@ void _memcpy_toio(unsigned long to, const void *from, size_t count) * "memset" on IO memory space. * This needs to be optimized. */ -void _memset_io(unsigned long dst, int c, size_t count) +void _memset_io(void __iomem *dst, int c, size_t count) { while (count) { count--; diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 68636bd7c..5b35e76c3 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -46,6 +46,7 @@ */ #define MAX_IRQ_CNT 100000 +static int noirqdebug; static volatile unsigned long irq_err_count; static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(irq_pending); @@ -85,7 +86,7 @@ static struct irqdesc bad_irq_desc = { }; /** - * disable_irq - disable an irq and wait for completion + * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable * * Disable the selected interrupt line. Enables and disables @@ -93,7 +94,7 @@ static struct irqdesc bad_irq_desc = { * * This function may be called from IRQ context. */ -void disable_irq(unsigned int irq) +void disable_irq_nosync(unsigned int irq) { struct irqdesc *desc = irq_desc + irq; unsigned long flags; @@ -103,6 +104,28 @@ void disable_irq(unsigned int irq) list_del_init(&desc->pend); spin_unlock_irqrestore(&irq_controller_lock, flags); } +EXPORT_SYMBOL(disable_irq_nosync); + +/** + * disable_irq - disable an irq and wait for completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Enables and disables + * are nested. This functions 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. + */ +void disable_irq(unsigned int irq) +{ + struct irqdesc *desc = irq_desc + irq; + + disable_irq_nosync(irq); + if (desc->action) + synchronize_irq(irq); +} EXPORT_SYMBOL(disable_irq); /** @@ -174,17 +197,30 @@ EXPORT_SYMBOL(disable_irq_wake); int show_interrupts(struct seq_file *p, void *v) { - int i = *(loff_t *) v; + int i = *(loff_t *) v, cpu; struct irqaction * action; unsigned long flags; + if (i == 0) { + char cpuname[12]; + + seq_printf(p, " "); + for_each_present_cpu(cpu) { + sprintf(cpuname, "CPU%d", cpu); + seq_printf(p, " %10s", cpuname); + } + seq_putc(p, '\n'); + } + if (i < NR_IRQS) { spin_lock_irqsave(&irq_controller_lock, flags); action = irq_desc[i].action; if (!action) goto unlock; - seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); + seq_printf(p, "%3d: ", i); + for_each_present_cpu(cpu) + seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); @@ -235,7 +271,7 @@ report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int static int count = 100; struct irqaction *action; - if (!count) + if (!count || noirqdebug) return; count--; @@ -261,7 +297,7 @@ static int __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) { unsigned int status; - int retval = 0; + int ret, retval = 0; spin_unlock(&irq_controller_lock); @@ -270,8 +306,10 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) status = 0; do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; + retval |= ret; action = action->next; } while (action); @@ -338,7 +376,6 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) do { struct irqaction *action; - int ret; action = desc->action; if (!action) @@ -349,9 +386,7 @@ do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) desc->chip->unmask(irq); } - ret = __do_irq(irq, action, regs); - if (ret != IRQ_HANDLED) - report_bad_irq(irq, regs, desc, ret); + __do_irq(irq, action, regs); } while (desc->pending && !desc->disable_depth); desc->running = 0; @@ -861,3 +896,11 @@ void __init init_IRQ(void) init_arch_irq(); init_dma(); } + +static int __init noirqdebug_setup(char *str) +{ + noirqdebug = 1; + return 1; +} + +__setup("noirqdebug", noirqdebug_setup); diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index a16951f49..eb9240e9a 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -9,6 +9,7 @@ * * Module allocation method suggested by Andi Kleen. */ +#include #include #include #include @@ -19,6 +20,18 @@ #include +#ifdef CONFIG_XIP_KERNEL +/* + * The XIP kernel text is mapped in the module area for modules and + * some other stuff to work without any indirect relocations. + * MODULE_START is redefined here and not in asm/memory.h to avoid + * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. + */ +extern void _etext; +#undef MODULE_START +#define MODULE_START (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK) +#endif + void *module_alloc(unsigned long size) { struct vm_struct *area; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 56498dbf7..9eb28f865 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -97,6 +97,8 @@ void default_idle(void) */ void cpu_idle(void) { + local_fiq_enable(); + /* endless idle loop with no priority at all */ while (1) { void (*idle)(void) = pm_idle; @@ -313,6 +315,9 @@ void flush_thread(void) memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); +#if defined(CONFIG_IWMMXT) + iwmmxt_task_release(thread); +#endif fp_init(&thread->fpstate); #if defined(CONFIG_VFP) vfp_flush_thread(&thread->vfpstate); @@ -324,6 +329,9 @@ void release_thread(struct task_struct *dead_task) #if defined(CONFIG_VFP) vfp_release_thread(&dead_task->thread_info->vfpstate); #endif +#if defined(CONFIG_IWMMXT) + iwmmxt_task_release(dead_task->thread_info); +#endif } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index d4195fd5b..c82f70b5d 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -677,7 +677,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat /* make sure single-step breakpoint is gone. */ child->ptrace &= ~PT_SINGLESTEP; ptrace_cancel_bpt(child); - if (child->state != TASK_ZOMBIE) { + if (child->exit_state != EXIT_ZOMBIE) { child->exit_code = SIGKILL; wake_up_process(child); } @@ -792,11 +792,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index 9ce72332e..c232d3777 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -214,7 +214,7 @@ __up_wakeup: \n\ ldmfd sp!, {r0 - r3, pc} \n\ "); -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_interruptible_failed); -EXPORT_SYMBOL_NOVERS(__down_trylock_failed); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_interruptible_failed); +EXPORT_SYMBOL(__down_trylock_failed); +EXPORT_SYMBOL(__up_wakeup); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 835010c55..a78ccd76e 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -57,10 +57,9 @@ extern unsigned int mem_fclk_21285; extern void paging_init(struct meminfo *, struct machine_desc *desc); extern void convert_to_tag_list(struct tag *tags); extern void squash_mem_tags(struct tag *tag); -extern void bootmem_init(struct meminfo *); extern void reboot_setup(char *str); extern int root_mountflags; -extern int _stext, _text, _etext, _edata, _end; +extern void _stext, _text, _etext, __data_start, _edata, _end; unsigned int processor_id; unsigned int __machine_arch_type; @@ -114,7 +113,7 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', ' */ static struct resource mem_res[] = { { "Video RAM", 0, 0, IORESOURCE_MEM }, - { "Kernel code", 0, 0, IORESOURCE_MEM }, + { "Kernel text", 0, 0, IORESOURCE_MEM }, { "Kernel data", 0, 0, IORESOURCE_MEM } }; @@ -133,21 +132,21 @@ static struct resource io_res[] = { #define lp2 io_res[2] static const char *cache_types[16] = { - "VIVT write-through", - "VIVT write-back", - "VIVT write-back", + "write-through", + "write-back", + "write-back", "undefined 3", "undefined 4", "undefined 5", - "VIVT write-back", - "VIVT write-back", + "write-back", + "write-back", "undefined 8", "undefined 9", "undefined 10", "undefined 11", "undefined 12", "undefined 13", - "VIPT write-back", + "write-back", "undefined 15", }; @@ -237,7 +236,8 @@ static void __init dump_cpu_info(void) unsigned int info = read_cpuid(CPUID_CACHETYPE); if (info != processor_id) { - printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]); + printk("CPU: D %s %s cache\n", cache_is_vivt() ? "VIVT" : "VIPT", + cache_types[CACHE_TYPE(info)]); if (CACHE_S(info)) { dump_cache("CPU: I cache", CACHE_ISIZE(info)); dump_cache("CPU: D cache", CACHE_DSIZE(info)); @@ -256,7 +256,7 @@ int cpu_architecture(void) } else if ((processor_id & 0x0000f000) == 0x00007000) { cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3; } else { - cpu_arch = (processor_id >> 16) & 15; + cpu_arch = (processor_id >> 16) & 7; if (cpu_arch) cpu_arch += CPU_ARCH_ARMv3; } @@ -448,10 +448,10 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) struct resource *res; int i; - kernel_code.start = __virt_to_phys(init_mm.start_code); - kernel_code.end = __virt_to_phys(init_mm.end_code - 1); - kernel_data.start = __virt_to_phys(init_mm.end_code); - kernel_data.end = __virt_to_phys(init_mm.brk - 1); + kernel_code.start = virt_to_phys(&_text); + kernel_code.end = virt_to_phys(&_etext - 1); + kernel_data.start = virt_to_phys(&__data_start); + kernel_data.end = virt_to_phys(&_end - 1); for (i = 0; i < mi->nr_banks; i++) { unsigned long virt_start, virt_end; @@ -720,7 +720,6 @@ void __init setup_arch(char **cmdline_p) memcpy(saved_command_line, from, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(cmdline_p, from); - bootmem_init(&meminfo); paging_init(&meminfo, mdesc); request_standard_resources(&meminfo, mdesc); @@ -728,7 +727,7 @@ void __init setup_arch(char **cmdline_p) * Set up various architecture-specific pointers */ init_arch_irq = mdesc->init_irq; - init_arch_time = mdesc->init_time; + system_timer = mdesc->timer; init_machine = mdesc->init_machine; #ifdef CONFIG_VT @@ -758,6 +757,7 @@ static const char *hwcap_str[] = { "fpa", "vfp", "edsp", + "java", NULL }; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index d214e8d49..c1ff9e200 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -126,27 +126,145 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, return ret; } +#ifdef CONFIG_IWMMXT + +/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ +#define IWMMXT_STORAGE_SIZE (0x98 + 8) +#define IWMMXT_MAGIC0 0x12ef842a +#define IWMMXT_MAGIC1 0x1c07ca71 + +struct iwmmxt_sigframe { + unsigned long magic0; + unsigned long magic1; + unsigned long storage[0x98/4]; +}; + +static int page_present(struct mm_struct *mm, void __user *uptr, int wr) +{ + unsigned long addr = (unsigned long)uptr; + pgd_t *pgd = pgd_offset(mm, addr); + if (pgd_present(*pgd)) { + pmd_t *pmd = pmd_offset(pgd, addr); + if (pmd_present(*pmd)) { + pte_t *pte = pte_offset_map(pmd, addr); + return (pte_present(*pte) && (!wr || pte_write(*pte))); + } + } + return 0; +} + +static int copy_locked(void __user *uptr, void *kptr, size_t size, int write, + void (*copyfn)(void *, void __user *)) +{ + unsigned char v, __user *userptr = uptr; + int err = 0; + + do { + struct mm_struct *mm; + + if (write) { + __put_user_error(0, userptr, err); + __put_user_error(0, userptr + size - 1, err); + } else { + __get_user_error(v, userptr, err); + __get_user_error(v, userptr + size - 1, err); + } + + if (err) + break; + + mm = current->mm; + spin_lock(&mm->page_table_lock); + if (page_present(mm, userptr, write) && + page_present(mm, userptr + size - 1, write)) { + copyfn(kptr, uptr); + } else + err = 1; + spin_unlock(&mm->page_table_lock); + } while (err); + + return err; +} + +static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) +{ + int err = 0; + + /* the iWMMXt context must be 64 bit aligned */ + WARN_ON((unsigned long)frame & 7); + + __put_user_error(IWMMXT_MAGIC0, &frame->magic0, err); + __put_user_error(IWMMXT_MAGIC1, &frame->magic1, err); + + /* + * iwmmxt_task_copy() doesn't check user permissions. + * Let's do a dummy write on the upper boundary to ensure + * access to user mem is OK all way up. + */ + err |= copy_locked(&frame->storage, current_thread_info(), + sizeof(frame->storage), 1, iwmmxt_task_copy); + return err; +} + +static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) +{ + unsigned long magic0, magic1; + int err = 0; + + /* the iWMMXt context is 64 bit aligned */ + WARN_ON((unsigned long)frame & 7); + + /* + * Validate iWMMXt context signature. + * Also, iwmmxt_task_restore() doesn't check user permissions. + * Let's do a dummy write on the upper boundary to ensure + * access to user mem is OK all way up. + */ + __get_user_error(magic0, &frame->magic0, err); + __get_user_error(magic1, &frame->magic1, err); + if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1) + err = copy_locked(&frame->storage, current_thread_info(), + sizeof(frame->storage), 0, iwmmxt_task_restore); + return err; +} + +#endif + /* - * Do a signal return; undo the signal stack. + * Auxiliary signal frame. This saves stuff like FP state. + * The layout of this structure is not part of the user ABI. */ -struct sigframe -{ +struct aux_sigframe { +#ifdef CONFIG_IWMMXT + struct iwmmxt_sigframe iwmmxt; +#endif +#ifdef CONFIG_VFP + union vfp_state vfp; +#endif +}; + +/* + * Do a signal return; undo the signal stack. These are aligned to 64-bit. + */ +struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; unsigned long retcode; + struct aux_sigframe aux __attribute__((aligned(8))); }; -struct rt_sigframe -{ +struct rt_sigframe { struct siginfo __user *pinfo; void __user *puc; struct siginfo info; struct ucontext uc; unsigned long retcode; + struct aux_sigframe aux __attribute__((aligned(8))); }; static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, + struct aux_sigframe __user *aux) { int err = 0; @@ -170,6 +288,15 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= !valid_user_regs(regs); +#ifdef CONFIG_IWMMXT + if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) + err |= restore_iwmmxt_context(&aux->iwmmxt); +#endif +#ifdef CONFIG_VFP +// if (err == 0) +// err |= vfp_restore_state(&aux->vfp); +#endif + return err; } @@ -205,7 +332,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->sc)) + if (restore_sigcontext(regs, &frame->sc, &frame->aux)) goto badframe; /* Send SIGTRAP if we're single-stepping */ @@ -250,7 +377,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux)) goto badframe; if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) @@ -270,7 +397,7 @@ badframe: } static int -setup_sigcontext(struct sigcontext __user *sc, /*struct _fpstate *fpstate,*/ +setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux, struct pt_regs *regs, unsigned long mask) { int err = 0; @@ -298,6 +425,15 @@ setup_sigcontext(struct sigcontext __user *sc, /*struct _fpstate *fpstate,*/ __put_user_error(current->thread.address, &sc->fault_address, err); __put_user_error(mask, &sc->oldmask, err); +#ifdef CONFIG_IWMMXT + if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) + err |= preserve_iwmmxt_context(&aux->iwmmxt); +#endif +#ifdef CONFIG_VFP +// if (err == 0) +// err |= vfp_save_state(&aux->vfp); +#endif + return err; } @@ -305,6 +441,7 @@ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) { unsigned long sp = regs->ARM_sp; + void __user *frame; /* * This is the X/Open sanctioned signal stack switching. @@ -315,7 +452,15 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) /* * ATPCS B01 mandates 8-byte alignment */ - return (void __user *)((sp - framesize) & ~7); + frame = (void __user *)((sp - framesize) & ~7); + + /* + * Check that we can actually write to the signal frame. + */ + if (!access_ok(VERIFY_WRITE, frame, framesize)) + frame = NULL; + + return frame; } static int @@ -384,10 +529,10 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); int err = 0; - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + if (!frame) return 1; - err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); + err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]); if (_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], @@ -408,7 +553,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, stack_t stack; int err = 0; - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + if (!frame) return 1; __put_user_error(&frame->info, &frame->pinfo, err); @@ -424,7 +569,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, stack.ss_size = current->sas_ss_size; err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); - err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ + err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -454,12 +599,12 @@ static inline void restart_syscall(struct pt_regs *regs) * OK, we're invoking a handler */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, int syscall) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; - struct k_sigaction *ka = &tsk->sighand->action[sig-1]; int usig = sig; int ret; @@ -514,15 +659,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, spin_unlock_irq(&tsk->sighand->siglock); } - if (ret == 0) { - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + if (ret == 0) return; - } - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, tsk); + force_sigsegv(sig, tsk); } /* @@ -536,6 +676,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, */ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -556,9 +697,9 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (current->ptrace & PT_SINGLESTEP) ptrace_cancel_bpt(current); - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs, syscall); + handle_signal(signr, &ka, &info, oldset, regs, syscall); if (current->ptrace & PT_SINGLESTEP) ptrace_set_bpt(current); return 1; diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index fb26b3bf9..154099aef 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -51,6 +51,13 @@ asmlinkage int sys_pipe(unsigned long __user *fildes) return error; } +/* + * This is the lowest virtual address we can permit any user space + * mapping to be mapped at. This is particularly important for + * non-high vector CPUs. + */ +#define MIN_MAP_ADDR (PAGE_SIZE) + /* common code for old and new mmaps */ inline long do_mmap2( unsigned long addr, unsigned long len, @@ -62,11 +69,7 @@ inline long do_mmap2( flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - /* - * If we are doing a fixed mapping, and address < PAGE_SIZE, - * then deny it. - */ - if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0) + if (flags & MAP_FIXED && addr < MIN_MAP_ADDR) goto out; error = -EBADF; @@ -119,12 +122,7 @@ sys_arm_mremap(unsigned long addr, unsigned long old_len, { unsigned long ret = -EINVAL; - /* - * If we are doing a fixed mapping, and address < PAGE_SIZE, - * then deny it. - */ - if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE && - vectors_base() == 0) + if (flags & MREMAP_FIXED && new_addr < MIN_MAP_ADDR) goto out; down_write(¤t->mm->mmap_sem); @@ -217,11 +215,8 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third, return ret; return put_user(raddr, (ulong __user *)third); } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - return do_shmat(first, (char __user *) ptr, - second, (ulong __user *) third); + case 1: /* Of course, we don't support iBCS2! */ + return -EINVAL; } case SHMDT: return sys_shmdt ((char __user *)ptr); @@ -257,7 +252,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } asmlinkage int sys_vfork(struct pt_regs *regs) diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index efcb44a9e..a46efa25f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -33,13 +33,18 @@ #include #include #include - +#include #include u64 jiffies_64 = INITIAL_JIFFIES; EXPORT_SYMBOL(jiffies_64); +/* + * Our system timer. + */ +struct sys_timer *system_timer; + extern unsigned long wall_jiffies; /* this needs a better home */ @@ -52,6 +57,20 @@ EXPORT_SYMBOL(rtc_lock); /* change this if you have some constant time drift */ #define USECS_PER_JIFFY (1000000/HZ) +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long fp, pc = instruction_pointer(regs); + + if (in_lock_functions(pc)) { + fp = thread_saved_fp(current); + pc = pc_pointer(((unsigned long *)fp)[-1]); + } + + return pc; +} +EXPORT_SYMBOL(profile_pc); +#endif /* * hook for setting the RTC's idea of the current time. @@ -63,12 +82,6 @@ static unsigned long dummy_gettimeoffset(void) return 0; } -/* - * hook for getting the time offset. Note that it is - * always called with interrupts disabled. - */ -unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset; - /* * Scheduler clock - returns current time in nanosec units. * This is the default implementation. Sub-architecture @@ -79,31 +92,6 @@ unsigned long long __attribute__((weak)) sched_clock(void) return (unsigned long long)jiffies * (1000000000 / HZ); } -/* - * Handle kernel profile stuff... - */ -static inline void do_profile(struct pt_regs *regs) -{ - - profile_hook(regs); - - if (!user_mode(regs) && - prof_buffer && - current->pid) { - unsigned long pc = instruction_pointer(regs); - extern int _stext; - - pc -= (unsigned long)&_stext; - - pc >>= prof_shift; - - if (pc >= prof_len) - pc = prof_len - 1; - - prof_buffer[pc] += 1; - } -} - static unsigned long next_rtc_update; /* @@ -258,7 +246,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = gettimeoffset(); + usec = system_timer->offset(); lost = jiffies - wall_jiffies; if (lost) @@ -295,7 +283,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * done, and then undo it! */ - nsec -= gettimeoffset() * NSEC_PER_USEC; + nsec -= system_timer->offset() * NSEC_PER_USEC; nsec -= (jiffies - wall_jiffies) * TICK_NSEC; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); @@ -315,18 +303,100 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); +/** + * save_time_delta - Save the offset between system time and RTC time + * @delta: pointer to timespec to store delta + * @rtc: pointer to timespec for current RTC time + * + * Return a delta between the system time and the RTC time, such + * that system time can be restored later with restore_time_delta() + */ +void save_time_delta(struct timespec *delta, struct timespec *rtc) +{ + set_normalized_timespec(delta, + xtime.tv_sec - rtc->tv_sec, + xtime.tv_nsec - rtc->tv_nsec); +} +EXPORT_SYMBOL(save_time_delta); + +/** + * restore_time_delta - Restore the current system time + * @delta: delta returned by save_time_delta() + * @rtc: pointer to timespec for current RTC time + */ +void restore_time_delta(struct timespec *delta, struct timespec *rtc) +{ + struct timespec ts; + + set_normalized_timespec(&ts, + delta->tv_sec + rtc->tv_sec, + delta->tv_nsec + rtc->tv_nsec); + + do_settimeofday(&ts); +} +EXPORT_SYMBOL(restore_time_delta); + +/* + * Kernel system timer support. + */ void timer_tick(struct pt_regs *regs) { - do_profile(regs); + profile_tick(CPU_PROFILING, regs); do_leds(); do_set_rtc(); do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif +} + +#ifdef CONFIG_PM +static int timer_suspend(struct sys_device *dev, u32 state) +{ + struct sys_timer *timer = container_of(dev, struct sys_timer, dev); + + if (timer->suspend != NULL) + timer->suspend(); + + return 0; +} + +static int timer_resume(struct sys_device *dev) +{ + struct sys_timer *timer = container_of(dev, struct sys_timer, dev); + + if (timer->resume != NULL) + timer->resume(); + + return 0; +} +#else +#define timer_suspend NULL +#define timer_resume NULL +#endif + +static struct sysdev_class timer_sysclass = { + set_kset_name("timer"), + .suspend = timer_suspend, + .resume = timer_resume, +}; + +static int __init timer_init_sysfs(void) +{ + int ret = sysdev_class_register(&timer_sysclass); + if (ret == 0) { + system_timer->dev.cls = &timer_sysclass; + ret = sysdev_register(&system_timer->dev); + } + return ret; } -void (*init_arch_time)(void); +device_initcall(timer_init_sysfs); void __init time_init(void) { - init_arch_time(); + if (system_timer->offset == NULL) + system_timer->offset = dummy_gettimeoffset; + system_timer->init(); } diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index e5c7f285b..b80f8cee7 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -328,20 +328,11 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs) */ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) { - unsigned int vectors = vectors_base(); - console_verbose(); printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n", handler[reason], processor_modes[proc_mode]); - /* - * Dump out the vectors and stub routines. Maybe a better solution - * would be to dump them out only if we detect that they are corrupted. - */ - dump_mem(KERN_CRIT "Vectors: ", vectors, vectors + 0x40); - dump_mem(KERN_CRIT "Stubs: ", vectors + 0x200, vectors + 0x4b8); - die("Oops - bad mode", regs, 0); local_irq_disable(); panic("bad mode"); @@ -381,7 +372,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) { struct vm_area_struct *vma; - if (end < start) + if (end < start || flags) return; vma = find_vma(current->active_mm, start); @@ -391,7 +382,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) if (end > vma->vm_end) end = vma->vm_end; - flush_cache_range(vma, start, end); + flush_cache_user_range(vma, start, end); } } @@ -537,7 +528,7 @@ EXPORT_SYMBOL(__bug); void __readwrite_bug(const char *fn) { - printk("%s called, but not implemented", fn); + printk("%s called, but not implemented\n", fn); BUG(); } EXPORT_SYMBOL(__readwrite_bug); @@ -562,7 +553,7 @@ asmlinkage void __div0(void) printk("Division by zero in kernel.\n"); dump_stack(); } -EXPORT_SYMBOL_NOVERS(__div0); +EXPORT_SYMBOL(__div0); void abort(void) { @@ -575,13 +566,9 @@ EXPORT_SYMBOL(abort); void __init trap_init(void) { - extern void __trap_init(unsigned long); - unsigned long base = vectors_base(); - - __trap_init(base); - flush_icache_range(base, base + PAGE_SIZE); - if (base != 0) - printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n", - base); + extern void __trap_init(void); + + __trap_init(); + flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index a5db0ddca..b885d32d1 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -4,6 +4,7 @@ */ #include +#include OUTPUT_ARCH(arm) ENTRY(stext) @@ -17,7 +18,6 @@ SECTIONS . = TEXTADDR; .init : { /* Init code and data */ _stext = .; - __init_begin = .; _sinittext = .; *(.init.text) _einittext = .; @@ -30,7 +30,6 @@ SECTIONS __tagtable_begin = .; *(.taglist) __tagtable_end = .; - *(.init.data) . = ALIGN(16); __setup_start = .; *(.init.setup) @@ -38,9 +37,6 @@ SECTIONS __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) @@ -60,8 +56,16 @@ SECTIONS __initramfs_start = .; usr/built-in.o(.init.ramfs) __initramfs_end = .; + . = ALIGN(64); + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; +#ifndef CONFIG_XIP_KERNEL + __init_begin = _stext; + *(.init.data) . = ALIGN(4096); __init_end = .; +#endif } /DISCARD/ : { /* Exit code and data */ @@ -74,6 +78,7 @@ SECTIONS _text = .; /* Text and read-only data */ *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) *(.rodata) @@ -81,8 +86,6 @@ SECTIONS *(.glue_7) *(.glue_7t) *(.got) /* Global offset table */ - - _etext = .; /* End of text section */ } . = ALIGN(16); @@ -94,15 +97,33 @@ SECTIONS RODATA + _etext = .; /* End of text and rodata section */ + +#ifdef CONFIG_XIP_KERNEL + __data_loc = ALIGN(4); /* location in binary */ + . = DATAADDR; +#else . = ALIGN(8192); + __data_loc = .; +#endif + + .data : AT(__data_loc) { + __data_start = .; /* address in memory */ - .data : { /* * first, the init task union, aligned * to an 8192 byte boundary. */ *(.init.task) +#ifdef CONFIG_XIP_KERNEL + . = ALIGN(4096); + __init_begin = .; + *(.init.data) + . = ALIGN(4096); + __init_end = .; +#endif + . = ALIGN(4096); __nosave_begin = .; *(.data.nosave) @@ -128,7 +149,7 @@ SECTIONS __bss_start = .; /* BSS */ *(.bss) *(COMMON) - _end = . ; + _end = .; } /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 007a5a012..c0e65833f 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -12,12 +12,12 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ testclearbit.o testsetbit.o uaccess.o getuser.o \ putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ ucmpdi2.o udivdi3.o lib1funcs.o div64.o \ - io-readsb.o io-writesb.o io-writesl.o + io-readsb.o io-writesb.o io-readsl.o io-writesl.o ifeq ($(CONFIG_CPU_32v3),y) - lib-y += io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o + lib-y += io-readsw-armv3.o io-writesw-armv3.o else - lib-y += io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o + lib-y += io-readsw-armv4.o io-writesw-armv4.o endif lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S index c5515f3be..cb5e3708f 100644 --- a/arch/arm/lib/csumpartial.S +++ b/arch/arm/lib/csumpartial.S @@ -73,8 +73,7 @@ td3 .req lr .done: adc r0, sum, #0 @ collect up the last carry ldr td0, [sp], #4 tst td0, #1 @ check buffer alignment - movne td0, r0, lsl #8 @ rotate checksum by 8 bits - orrne r0, td0, r0, lsr #24 + movne r0, r0, ror #8 @ rotate checksum by 8 bits ldr pc, [sp], #4 @ return .not_aligned: tst buf, #1 @ odd address diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S index b18b89715..d3a2f4667 100644 --- a/arch/arm/lib/csumpartialcopygeneric.S +++ b/arch/arm/lib/csumpartialcopygeneric.S @@ -160,8 +160,7 @@ FN_ENTRY .done: adc r0, sum, #0 ldr sum, [sp, #0] @ dst tst sum, #1 - movne sum, r0, lsl #8 - orrne r0, sum, r0, lsr #24 + movne r0, r0, ror #8 load_regs ea .src_not_aligned: diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S index 67cbd8697..3c7f7e675 100644 --- a/arch/arm/lib/delay.S +++ b/arch/arm/lib/delay.S @@ -16,15 +16,16 @@ LC0: .word loops_per_jiffy /* * 0 <= r0 <= 2000 */ -ENTRY(udelay) +ENTRY(__udelay) mov r2, #0x6800 orr r2, r2, #0x00db - mul r1, r0, r2 + mul r0, r2, r0 +ENTRY(__const_udelay) @ 0 <= r0 <= 0x01ffffff ldr r2, LC0 - ldr r2, [r2] - mov r1, r1, lsr #11 - mov r2, r2, lsr #11 - mul r0, r1, r2 + ldr r2, [r2] @ max = 0x0fffffff + mov r0, r0, lsr #11 @ max = 0x00003fff + mov r2, r2, lsr #11 @ max = 0x0003ffff + mul r0, r2, r0 @ max = 2^32-1 movs r0, r0, lsr #6 RETINSTR(moveq,pc,lr) diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index cf3920459..64aa6f4fe 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -17,7 +17,7 @@ * * Inputs: r0 contains the address * Outputs: r0 is the error code - * r1, r2 contains the zero-extended value + * r2, r3 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see include/asm-arm/uaccess.h @@ -32,64 +32,39 @@ .global __get_user_1 __get_user_1: - bic r1, sp, #0x1f00 - bic r1, r1, #0x00ff - ldr r1, [r1, #TI_ADDR_LIMIT] - sub r1, r1, #1 - cmp r0, r1 -1: ldrlsbt r1, [r0] - movls r0, #0 - movls pc, lr - b __get_user_bad +1: ldrbt r2, [r0] + mov r0, #0 + mov pc, lr .global __get_user_2 __get_user_2: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TI_ADDR_LIMIT] - sub r2, r2, #2 - cmp r0, r2 -2: ldrlsbt r1, [r0], #1 -3: ldrlsbt r2, [r0] +2: ldrbt r2, [r0], #1 +3: ldrbt r3, [r0] #ifndef __ARMEB__ - orrls r1, r1, r2, lsl #8 + orr r2, r2, r3, lsl #8 #else - orrls r1, r2, r1, lsl #8 + orr r2, r3, r2, lsl #8 #endif - movls r0, #0 - movls pc, lr - b __get_user_bad + mov r0, #0 + mov pc, lr .global __get_user_4 __get_user_4: - bic r1, sp, #0x1f00 - bic r1, r1, #0x00ff - ldr r1, [r1, #TI_ADDR_LIMIT] - sub r1, r1, #4 - cmp r0, r1 -4: ldrlst r1, [r0] - movls r0, #0 - movls pc, lr - b __get_user_bad +4: ldrt r2, [r0] + mov r0, #0 + mov pc, lr .global __get_user_8 __get_user_8: - bic r2, sp, #0x1f00 - bic r2, r2, #0x00ff - ldr r2, [r2, #TI_ADDR_LIMIT] - sub r2, r2, #8 - cmp r0, r2 -5: ldrlst r1, [r0], #4 -6: ldrlst r2, [r0] - movls r0, #0 - movls pc, lr - - /* fall through */ +5: ldrt r2, [r0], #4 +6: ldrt r3, [r0] + mov r0, #0 + mov pc, lr __get_user_bad_8: - mov r2, #0 + mov r3, #0 __get_user_bad: - mov r1, #0 + mov r2, #0 mov r0, #-EFAULT mov pc, lr diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S index 20b3ee2ef..f8f14dd22 100644 --- a/arch/arm/lib/io-writesl.S +++ b/arch/arm/lib/io-writesl.S @@ -9,53 +9,58 @@ */ #include #include -#include ENTRY(__raw_writesl) teq r2, #0 @ do we have to check for the zero len? moveq pc, lr ands ip, r1, #3 - bne 2f + bne 3f - tst r2, #1 - ldrne r3, [r1], #4 - strne r3, [r0, #0] -1: subs r2, r2, #2 - ldrcs r3, [r1], #4 - ldrcs ip, [r1], #4 + subs r2, r2, #4 + bmi 2f + stmfd sp!, {r4, lr} +1: ldmia r1!, {r3, r4, ip, lr} + subs r2, r2, #4 + str r3, [r0, #0] + str r4, [r0, #0] + str ip, [r0, #0] + str lr, [r0, #0] + bpl 1b + ldmfd sp!, {r4, lr} +2: movs r2, r2, lsl #31 + ldmcsia r1!, {r3, ip} strcs r3, [r0, #0] + ldrne r3, [r1, #0] strcs ip, [r0, #0] - bcs 1b + strne r3, [r0, #0] mov pc, lr -2: bic r1, r1, #3 - cmp ip, #2 +3: bic r1, r1, #3 ldr r3, [r1], #4 - bgt 4f + cmp ip, #2 blt 5f + bgt 6f -3: mov ip, r3, lsr #16 +4: mov ip, r3, pull #16 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, lsl #16 - str ip, [r0, #0] - bne 3b + orr ip, ip, r3, push #16 + str ip, [r0] + bne 4b mov pc, lr -4: mov ip, r3, lsr #24 +5: mov ip, r3, pull #8 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, lsl #8 - str ip, [r0, #0] - bne 4b + orr ip, ip, r3, push #24 + str ip, [r0] + bne 5b mov pc, lr -5: mov ip, r3, lsr #8 +6: mov ip, r3, pull #24 ldr r3, [r1], #4 subs r2, r2, #1 - orr ip, ip, r3, lsl #24 - str ip, [r0, #0] - bne 5b + orr ip, ip, r3, push #8 + str ip, [r0] + bne 6b mov pc, lr - - diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h index 05ec1abd6..179eea4ed 100644 --- a/arch/arm/lib/longlong.h +++ b/arch/arm/lib/longlong.h @@ -161,7 +161,6 @@ #define UDIV_NEEDS_NORMALIZATION 1 #define udiv_qrnnd __udiv_qrnnd_c -extern const UQItype __clz_tab[]; #define count_leading_zeros(count, x) \ do { \ USItype __xr = (x); \ diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 293de2d2c..b09398d95 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -16,7 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address - * r1, r2 contains the value + * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted * @@ -32,60 +32,35 @@ .global __put_user_1 __put_user_1: - bic ip, sp, #0x1f00 - bic ip, ip, #0x00ff - ldr ip, [ip, #TI_ADDR_LIMIT] - sub ip, ip, #1 - cmp r0, ip -1: strlsbt r1, [r0] - movls r0, #0 - movls pc, lr - b __put_user_bad +1: strbt r2, [r0] + mov r0, #0 + mov pc, lr .global __put_user_2 __put_user_2: - bic ip, sp, #0x1f00 - bic ip, ip, #0x00ff - ldr ip, [ip, #TI_ADDR_LIMIT] - sub ip, ip, #2 - cmp r0, ip - movls ip, r1, lsr #8 + mov ip, r2, lsr #8 #ifndef __ARMEB__ -2: strlsbt r1, [r0], #1 -3: strlsbt ip, [r0] +2: strbt r2, [r0], #1 +3: strbt ip, [r0] #else -2: strlsbt ip, [r0], #1 -3: strlsbt r1, [r0] +2: strbt ip, [r0], #1 +3: strbt r2, [r0] #endif - movls r0, #0 - movls pc, lr - b __put_user_bad + mov r0, #0 + mov pc, lr .global __put_user_4 __put_user_4: - bic ip, sp, #0x1f00 - bic ip, ip, #0x00ff - ldr ip, [ip, #TI_ADDR_LIMIT] - sub ip, ip, #4 - cmp r0, ip -4: strlst r1, [r0] - movls r0, #0 - movls pc, lr - b __put_user_bad +4: strt r2, [r0] + mov r0, #0 + mov pc, lr .global __put_user_8 __put_user_8: - bic ip, sp, #0x1f00 - bic ip, ip, #0x00ff - ldr ip, [ip, #TI_ADDR_LIMIT] - sub ip, ip, #8 - cmp r0, ip -5: strlst r1, [r0], #4 -6: strlst r2, [r0] - movls r0, #0 - movls pc, lr - - /* fall through */ +5: strt r2, [r0], #4 +6: strt r3, [r0] + mov r0, #0 + mov pc, lr __put_user_bad: mov r0, #-EFAULT diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c index e8a4d998b..c106704a2 100644 --- a/arch/arm/mach-clps711x/autcpu12.c +++ b/arch/arm/mach-clps711x/autcpu12.c @@ -35,9 +35,7 @@ #include #include -extern void clps711x_map_io(void); -extern void clps711x_init_irq(void); -extern void clps711x_init_time(void); +#include "common.h" /* * The on-chip registers are given a size of 1MB so that a section can @@ -66,6 +64,6 @@ MACHINE_START(AUTCPU12, "autronix autcpu12") BOOT_PARAMS(0xc0020000) MAPIO(autcpu12_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c index 870d4e4e8..7664f9cf8 100644 --- a/arch/arm/mach-clps711x/cdb89712.c +++ b/arch/arm/mach-clps711x/cdb89712.c @@ -32,9 +32,7 @@ #include #include -extern void clps711x_init_irq(void); -extern void clps711x_map_io(void); -extern void clps711x_init_time(void); +#include "common.h" /* * Map the CS89712 Ethernet port. That should be moved to the @@ -56,13 +54,5 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712") BOOT_PARAMS(0xc0000100) MAPIO(cdb89712_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END - -static int cdb89712_hw_init(void) -{ - return 0; -} - -__initcall(cdb89712_hw_init); - diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c index 44d4e5b8d..e4093be3c 100644 --- a/arch/arm/mach-clps711x/ceiva.c +++ b/arch/arm/mach-clps711x/ceiva.c @@ -34,8 +34,7 @@ #include -extern void clps711x_init_irq(void); -extern void clps711x_init_time(void); +#include "common.h" static struct map_desc ceiva_io_desc[] __initdata = { /* virtual, physical, length, type */ @@ -59,5 +58,5 @@ MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame") BOOT_PARAMS(0xc0000100) MAPIO(ceiva_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c index 14fb9788c..9ca21cb48 100644 --- a/arch/arm/mach-clps711x/clep7312.c +++ b/arch/arm/mach-clps711x/clep7312.c @@ -23,9 +23,7 @@ #include #include -extern void clps711x_init_irq(void); -extern void clps711x_map_io(void); -extern void clps711x_init_time(void); +#include "common.h" static void __init fixup_clep7312(struct machine_desc *desc, struct tag *tags, @@ -45,6 +43,6 @@ MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") FIXUP(fixup_clep7312) MAPIO(clps711x_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c index 11aa05c24..c6c46324a 100644 --- a/arch/arm/mach-clps711x/edb7211-arch.c +++ b/arch/arm/mach-clps711x/edb7211-arch.c @@ -25,9 +25,9 @@ #include #include -extern void clps711x_init_irq(void); +#include "common.h" + extern void edb7211_map_io(void); -extern void clps711x_init_time(void); static void __init fixup_edb7211(struct machine_desc *desc, struct tag *tags, @@ -57,5 +57,5 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") FIXUP(fixup_edb7211) MAPIO(edb7211_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index 7a4ba27df..c1c5b8e01 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -31,9 +31,7 @@ #include -extern void clps711x_map_io(void); -extern void clps711x_init_irq(void); -extern void clps711x_init_time(void); +#include "common.h" struct meminfo memmap = { .nr_banks = 1, @@ -83,5 +81,5 @@ MACHINE_START(FORTUNET, "ARM-FortuNet") FIXUP(fortunet_fixup) MAPIO(clps711x_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index eb75ae667..29269df05 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -34,9 +34,7 @@ #include #include -extern void clps711x_init_irq(void); -extern void clps711x_map_io(void); -extern void clps711x_init_time(void); +#include "common.h" /* * Map the P720T system PLD. It occupies two address spaces: @@ -87,7 +85,7 @@ MACHINE_START(P720T, "ARM-Prospector720T") FIXUP(fixup_p720t) MAPIO(p720t_map_io) INITIRQ(clps711x_init_irq) - INITTIME(clps711x_init_time) + .timer = &clps711x_timer, MACHINE_END static int p720t_hw_init(void) diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c index 58da84eff..383d4e0c6 100644 --- a/arch/arm/mach-clps711x/time.c +++ b/arch/arm/mach-clps711x/time.c @@ -49,7 +49,9 @@ static unsigned long clps711x_gettimeoffset(void) static irqreturn_t p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); timer_tick(regs); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -59,7 +61,7 @@ static struct irqaction clps711x_timer_irq = { .handler = p720t_timer_interrupt }; -void __init clps711x_init_time(void) +static void __init clps711x_timer_init(void) { struct timespec tv; unsigned int syscon; @@ -71,9 +73,13 @@ void __init clps711x_init_time(void) clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */ setup_irq(IRQ_TC2OI, &clps711x_timer_irq); - gettimeoffset = clps711x_gettimeoffset; tv.tv_nsec = 0; tv.tv_sec = clps_readl(RTCDR); do_settimeofday(&tv); } + +struct sys_timer clps711x_timer = { + .init = clps711x_timer_init, + .offset = clps711x_gettimeoffset, +}; diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index 11fa530af..1b37ac188 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -267,10 +268,13 @@ static void __init clps7500_map_io(void) } extern void ioctime_init(void); +extern unsigned long ioc_timer_gettimeoffset(void); static irqreturn_t clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + timer_tick(regs); /* Why not using do_leds interface?? */ @@ -283,6 +287,9 @@ clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) *((volatile unsigned int *)LED_ADDRESS) = state; } } + + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -295,18 +302,72 @@ static struct irqaction clps7500_timer_irq = { /* * Set up timer interrupt. */ -void __init clps7500_init_time(void) +static void __init clps7500_timer_init(void) { ioctime_init(); setup_irq(IRQ_TIMER, &clps7500_timer_irq); } +static struct clps7500_timer = { + .init = clps7500_timer_init, + .offset = ioc_timer_gettimeoffset, +}; + +static struct plat_serial8250_port serial_platform_data[] = { + { + .mapbase = 0x03010fe0, + .irq = 10, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST, + }, + { + .mapbase = 0x03010be0, + .irq = 0, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST, + }, + { + .iobase = ISASLOT_IO + 0x2e8, + .irq = 41, + .uartclk = 1843200, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .iobase = ISASLOT_IO + 0x3e8, + .irq = 40, + .uartclk = 1843200, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static int __init clps7500_init(void) +{ + return platform_register_device(&serial_device); +} + MACHINE_START(CLPS7500, "CL-PS7500") MAINTAINER("Philip Blundell") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) MAPIO(clps7500_map_io) INITIRQ(clps7500_init_irq) - INITTIME(clps7500_init_time) + .timer = &clps7500_timer, MACHINE_END diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 07c556392..ef362d449 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -151,6 +152,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 count; + write_seqlock(&xtime_lock); + /* latch and read timer 1 */ __raw_writeb(0x40, PIT_CTRL); count = __raw_readb(PIT_T1); @@ -163,6 +166,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -175,7 +180,7 @@ static struct irqaction ebsa110_timer_irq = { /* * Set up timer interrupt. */ -static void __init ebsa110_init_time(void) +static void __init ebsa110_timer_init(void) { /* * Timer 1, mode 2, LSB/MSB @@ -184,11 +189,49 @@ static void __init ebsa110_init_time(void) __raw_writeb(COUNT & 0xff, PIT_T1); __raw_writeb(COUNT >> 8, PIT_T1); - gettimeoffset = ebsa110_gettimeoffset; - setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq); } +static struct sys_timer ebsa110_timer = { + .init = ebsa110_timer_init, + .offset = ebsa110_gettimeoffset, +}; + +static struct plat_serial8250_port serial_platform_data[] = { + { + .iobase = 0x3f8, + .irq = 1, + .uartclk = 1843200, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .iobase = 0x2f8, + .irq = 2, + .uartclk = 1843200, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static int __init ebsa110_init(void) +{ + return platform_device_register(&serial_device); +} + +arch_initcall(ebsa110_init); + MACHINE_START(EBSA110, "EBSA110") MAINTAINER("Russell King") BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000) @@ -198,5 +241,5 @@ MACHINE_START(EBSA110, "EBSA110") SOFT_REBOOT MAPIO(ebsa110_map_io) INITIRQ(ebsa110_init_irq) - INITTIME(ebsa110_init_time) + .timer = &ebsa110_timer, MACHINE_END diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c index 9205e65fe..f5181ed48 100644 --- a/arch/arm/mach-ebsa110/io.c +++ b/arch/arm/mach-ebsa110/io.c @@ -27,9 +27,9 @@ #include #include -static u32 __isamem_convert_addr(void *addr) +static void __iomem *__isamem_convert_addr(void __iomem *addr) { - u32 ret, a = (u32) addr; + u32 ret, a = (u32 __force) addr; /* * The PCMCIA controller is wired up as follows: @@ -53,41 +53,43 @@ static u32 __isamem_convert_addr(void *addr) ret += 0xe8000000; if ((a & 0x20000) == (a & 0x40000) >> 1) - return ret; + return (void __iomem *)ret; BUG(); - return 0; + return NULL; } /* * read[bwl] and write[bwl] */ -u8 __readb(void *addr) +u8 __readb(void __iomem *addr) { - u32 ret, a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); + u32 ret; - if ((int)addr & 1) + if ((unsigned long)addr & 1) ret = __raw_readl(a); else ret = __raw_readb(a); return ret; } -u16 __readw(void *addr) +u16 __readw(void __iomem *addr) { - u32 a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); - if ((int)addr & 1) + if ((unsigned long)addr & 1) BUG(); return __raw_readw(a); } -u32 __readl(void *addr) +u32 __readl(void __iomem *addr) { - u32 ret, a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); + u32 ret; - if ((int)addr & 3) + if ((unsigned long)addr & 3) BUG(); ret = __raw_readw(a); @@ -99,31 +101,31 @@ EXPORT_SYMBOL(__readb); EXPORT_SYMBOL(__readw); EXPORT_SYMBOL(__readl); -void __writeb(u8 val, void *addr) +void __writeb(u8 val, void __iomem *addr) { - u32 a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); - if ((int)addr & 1) + if ((unsigned long)addr & 1) __raw_writel(val, a); else __raw_writeb(val, a); } -void __writew(u16 val, void *addr) +void __writew(u16 val, void __iomem *addr) { - u32 a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); - if ((int)addr & 1) + if ((unsigned long)addr & 1) BUG(); __raw_writew(val, a); } -void __writel(u32 val, void *addr) +void __writel(u32 val, void __iomem *addr) { - u32 a = __isamem_convert_addr(addr); + void __iomem *a = __isamem_convert_addr(addr); - if ((int)addr & 3) + if ((unsigned long)addr & 3) BUG(); __raw_writew(val, a); @@ -153,7 +155,7 @@ u8 __inb8(unsigned int port) if (SUPERIO_PORT(port)) ret = __raw_readb(ISAIO_BASE + (port << 2)); else { - u32 a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -180,7 +182,7 @@ u8 __inb16(unsigned int port) if (SUPERIO_PORT(port)) ret = __raw_readb(ISAIO_BASE + (port << 2)); else { - u32 a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -200,7 +202,7 @@ u16 __inw(unsigned int port) if (SUPERIO_PORT(port)) ret = __raw_readw(ISAIO_BASE + (port << 2)); else { - u32 a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -218,7 +220,7 @@ u16 __inw(unsigned int port) */ u32 __inl(unsigned int port) { - u32 a; + void __iomem *a; if (SUPERIO_PORT(port) || port & 3) BUG(); @@ -241,7 +243,7 @@ void __outb8(u8 val, unsigned int port) if (SUPERIO_PORT(port)) __raw_writeb(val, ISAIO_BASE + (port << 2)); else { - u32 a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does @@ -261,7 +263,7 @@ void __outb16(u8 val, unsigned int port) if (SUPERIO_PORT(port)) __raw_writeb(val, ISAIO_BASE + (port << 2)); else { - u32 a = ISAIO_BASE + ((port & ~1) << 1); + void __iomem *a = ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c index ae9f7c864..1b40340e8 100644 --- a/arch/arm/mach-epxa10db/arch.c +++ b/arch/arm/mach-epxa10db/arch.c @@ -20,6 +20,7 @@ */ #include #include +#include #include #include @@ -27,15 +28,45 @@ #include +static struct plat_serial8250_port serial_platform_data[] = { + { + .iobase = 0x3f8, + .irq = IRQ_UARTINT0, +#error FIXME + .uartclk = 0, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .iobase = 0x2f8, + .irq = IRQ_UARTINT1, +#error FIXME + .uartclk = 0, + .regshift = 0, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + extern void epxa10db_map_io(void); extern void epxa10db_init_irq(void); -extern void epxa10db_init_time(void); +extern struct sys_timer epxa10db_timer; MACHINE_START(CAMELOT, "Altera Epxa10db") MAINTAINER("Altera Corporation") BOOT_MEM(0x00000000, 0x7fffc000, 0xffffc000) MAPIO(epxa10db_map_io) INITIRQ(epxa10db_init_irq) - INITTIME(epxa10db_init_time) + .timer = &epxa10db_timer, MACHINE_END diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c index 7d72a433d..1b991f3cc 100644 --- a/arch/arm/mach-epxa10db/time.c +++ b/arch/arm/mach-epxa10db/time.c @@ -43,11 +43,13 @@ __initcall(epxa10db_rtc_init); static irqreturn_t epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); // ...clear the interrupt *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK; timer_tick(regs); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -61,7 +63,7 @@ static struct irqaction epxa10db_timer_irq = { /* * Set up timer interrupt, and return the current time in seconds. */ -void __init epxa10db_init_time(void) +static void __init epxa10db_timer_init(void) { /* Start the timer */ *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200); @@ -71,3 +73,6 @@ void __init epxa10db_init_time(void) setup_irq(IRQ_TIMER0, &epxa10db_timer_irq); } +struct sys_timer epxa10db_timer = { + .init = epxa10db_timer_init, +}; diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig index 1eaea0b87..fc3250d09 100644 --- a/arch/arm/mach-footbridge/Kconfig +++ b/arch/arm/mach-footbridge/Kconfig @@ -4,6 +4,7 @@ menu "Footbridge Implementations" config ARCH_CATS bool "CATS" + select FOOTBRIDGE_HOST help Say Y here if you intend to run this kernel on the CATS. @@ -11,6 +12,7 @@ config ARCH_CATS config ARCH_PERSONAL_SERVER bool "Compaq Personal Server" + select FOOTBRIDGE_HOST ---help--- Say Y here if you intend to run this kernel on the Compaq Personal Server. @@ -28,6 +30,8 @@ config ARCH_PERSONAL_SERVER config ARCH_EBSA285_ADDIN bool "EBSA285 (addin mode)" + select ARCH_EBSA285 + select FOOTBRIDGE_ADDIN help Say Y here if you intend to run this kernel on the EBSA285 card in addin mode. @@ -36,6 +40,8 @@ config ARCH_EBSA285_ADDIN config ARCH_EBSA285_HOST bool "EBSA285 (host mode)" + select ARCH_EBSA285 + select FOOTBRIDGE_HOST help Say Y here if you intend to run this kernel on the EBSA285 card in host ("central function") mode. @@ -44,6 +50,7 @@ config ARCH_EBSA285_HOST config ARCH_NETWINDER bool "NetWinder" + select FOOTBRIDGE_HOST help Say Y here if you intend to run this kernel on the Rebel.COM NetWinder. Information about this machine can be found at: @@ -54,4 +61,20 @@ config ARCH_NETWINDER endmenu +# Footbridge support +config FOOTBRIDGE + bool + +# Footbridge in host mode +config FOOTBRIDGE_HOST + bool + +# Footbridge in addin mode +config FOOTBRIDGE_ADDIN + bool + +# EBSA285 board in either host or addin mode +config ARCH_EBSA285 + bool + endif diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile index e0a289052..0694ad6b6 100644 --- a/arch/arm/mach-footbridge/Makefile +++ b/arch/arm/mach-footbridge/Makefile @@ -4,13 +4,13 @@ # Object file lists. -obj-y := arch.o dc21285.o dma.o irq.o isa-irq.o mm.o time.o +obj-y := common.o dc21285.o dma.o isa-irq.o time.o obj-m := obj-n := obj- := pci-$(CONFIG_ARCH_CATS) += cats-pci.o -pci-$(CONFIG_ARCH_EBSA285) += ebsa285-pci.o +pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o @@ -18,8 +18,13 @@ leds-$(CONFIG_ARCH_CO285) += ebsa285-leds.o leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o -obj-$(CONFIG_ARCH_CATS) += cats-hw.o -obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o +obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o +obj-$(CONFIG_ARCH_CO285) += co285.o dc21285-timer.o +obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o +obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o +obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o obj-$(CONFIG_PCI) +=$(pci-y) obj-$(CONFIG_LEDS) +=$(leds-y) + +obj-$(CONFIG_ISA) += isa.o diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 0aec69fb0..f94d176c3 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -9,8 +9,14 @@ #include #include +#include #include #include +#include + +#include + +#include "common.h" #define CFG_PORT 0x370 #define INDEX_PORT (CFG_PORT) @@ -62,3 +68,27 @@ static int __init cats_hw_init(void) } __initcall(cats_hw_init); + +/* + * CATS uses soft-reboot by default, since + * hard reboots fail on early boards. + */ +static void __init +fixup_cats(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + ORIG_VIDEO_LINES = 25; + ORIG_VIDEO_POINTS = 16; + ORIG_Y = 24; +} + +MACHINE_START(CATS, "Chalice-CATS") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + SOFT_REBOOT + FIXUP(fixup_cats) + MAPIO(footbridge_map_io) + INITIRQ(footbridge_init_irq) + .timer = &isa_timer, +MACHINE_END diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index c81775b1a..5ec9ea989 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -12,9 +12,15 @@ #include #include +#include #include #include #include +#include + +#include + +#include "common.h" #define IRDA_IO_BASE 0x180 #define GP1_IO_BASE 0x338 @@ -52,7 +58,7 @@ static inline void wb977_ww(int reg, int val) outb(reg, 0x370); outb(val >> 8, 0x371); outb(reg + 1, 0x370); - outb(val, 0x371); + outb(val & 255, 0x371); } #define wb977_device_select(dev) wb977_wb(0x07, dev) @@ -482,7 +488,7 @@ static inline void rwa010_waveartist_init(int base, int irq, int dma) WRITE_RWA(7, 0); dprintk("WaveArtist base: "); - WRITE_RWA(0x61, base); + WRITE_RWA(0x61, base & 255); i = inb(0x203); WRITE_RWA(0x60, base >> 8); @@ -504,7 +510,7 @@ static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, i WRITE_RWA(7, 1); dprintk("SoundBlaster base: "); - WRITE_RWA(0x61, sb_base); + WRITE_RWA(0x61, sb_base & 255); i = inb(0x203); WRITE_RWA(0x60, sb_base >> 8); @@ -519,7 +525,7 @@ static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, i dprintk("%d (%d)\n", inb(0x203), dma); dprintk("AdLib base: "); - WRITE_RWA(0x63, al_base); + WRITE_RWA(0x63, al_base & 255); i = inb(0x203); WRITE_RWA(0x62, al_base >> 8); @@ -618,3 +624,37 @@ static int __init nw_hw_init(void) } __initcall(nw_hw_init); + +/* + * Older NeTTroms either do not provide a parameters + * page, or they don't supply correct information in + * the parameter page. + */ +static void __init +fixup_netwinder(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ +#ifdef CONFIG_ISAPNP + extern int isapnp_disable; + + /* + * We must not use the kernels ISAPnP code + * on the NetWinder - it will reset the settings + * for the WaveArtist chip and render it inoperable. + */ + isapnp_disable = 1; +#endif +} + +MACHINE_START(NETWINDER, "Rebel-NetWinder") + MAINTAINER("Russell King/Rebel.com") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + VIDEO(0x000a0000, 0x000bffff) + DISABLE_PARPORT(0) + DISABLE_PARPORT(2) + FIXUP(fixup_netwinder) + MAPIO(footbridge_map_io) + INITIRQ(footbridge_init_irq) + .timer = &isa_timer, +MACHINE_END diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c index e9f5708b4..2c64a0b05 100644 --- a/arch/arm/mach-footbridge/time.c +++ b/arch/arm/mach-footbridge/time.c @@ -19,75 +19,18 @@ #include #include -#include #include #include #include -#include - #include -#include -#include -#include #include -#include #include +#include "common.h" static int rtc_base; -#define mSEC_10_from_14 ((14318180 + 100) / 200) - -static unsigned long isa_gettimeoffset(void) -{ - int count; - - static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - /* timer count may underflow right here */ - outb_p(0x00, 0x43); /* latch the count ASAP */ - - count = inb_p(0x40); /* read the latched count */ - - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; - - count |= inb_p(0x40) << 8; - - /* Detect timer underflows. If we haven't had a timer tick since - the last time we were called, and time is apparently going - backwards, the counter must have wrapped during this routine. */ - if ((jiffies_t == jiffies_p) && (count > count_p)) - count -= (mSEC_10_from_14/6); - else - jiffies_p = jiffies_t; - - count_p = count; - - count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000); - count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6); - - return count; -} - -static irqreturn_t -isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - timer_tick(regs); - - return IRQ_HANDLED; -} - static unsigned long __init get_isa_cmos_time(void) { unsigned int year, mon, day, hour, min, sec; @@ -133,8 +76,7 @@ static unsigned long __init get_isa_cmos_time(void) return mktime(year, mon, day, hour, min, sec); } -static int -set_isa_cmos_time(void) +static int set_isa_cmos_time(void) { int retval = 0; int real_seconds, real_minutes, cmos_minutes; @@ -186,34 +128,7 @@ set_isa_cmos_time(void) return retval; } - -static unsigned long timer1_latch; - -static unsigned long timer1_gettimeoffset (void) -{ - unsigned long value = timer1_latch - *CSR_TIMER1_VALUE; - - return ((tick_nsec / 1000) * value) / timer1_latch; -} - -static irqreturn_t -timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - *CSR_TIMER1_CLR = 0; - - timer_tick(regs); - - return IRQ_HANDLED; -} - -static struct irqaction footbridge_timer_irq = { - .flags = SA_INTERRUPT -}; - -/* - * Set up timer interrupt. - */ -void __init footbridge_init_time(void) +void __init isa_rtc_init(void) { if (machine_is_co285() || machine_is_personal_server()) @@ -262,35 +177,4 @@ void __init footbridge_init_time(void) } else rtc_base = 0; } - - if (machine_is_ebsa285() || - machine_is_co285() || - machine_is_personal_server()) { - gettimeoffset = timer1_gettimeoffset; - - timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); - - *CSR_TIMER1_CLR = 0; - *CSR_TIMER1_LOAD = timer1_latch; - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; - - footbridge_timer_irq.name = "Timer1 Timer Tick"; - footbridge_timer_irq.handler = timer1_interrupt; - - setup_irq(IRQ_TIMER1, &footbridge_timer_irq); - - } else { - /* enable PIT timer */ - /* set for periodic (4) and LSB/MSB write (0x30) */ - outb(0x34, 0x43); - outb((mSEC_10_from_14/6) & 0xFF, 0x40); - outb((mSEC_10_from_14/6) >> 8, 0x40); - - gettimeoffset = isa_gettimeoffset; - - footbridge_timer_irq.name = "ISA Timer Tick"; - footbridge_timer_irq.handler = isa_timer_interrupt; - - setup_irq(IRQ_ISA_TIMER, &footbridge_timer_irq); - } } diff --git a/arch/arm/mach-h720x/Kconfig b/arch/arm/mach-h720x/Kconfig index 44a303d40..5890fa85f 100644 --- a/arch/arm/mach-h720x/Kconfig +++ b/arch/arm/mach-h720x/Kconfig @@ -1,3 +1,5 @@ +if ARCH_H720X + menu "h720x Implementations" config ARCH_H7201 @@ -25,3 +27,5 @@ config CPU_H7202 bool help Select code specific to h7202 variants + +endif diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c index 30f4d6118..743656881 100644 --- a/arch/arm/mach-h720x/cpu-h7201.c +++ b/arch/arm/mach-h720x/cpu-h7201.c @@ -22,18 +22,20 @@ #include #include #include - -extern unsigned long h720x_gettimeoffset(void); -extern void __init h720x_init_irq (void); - +#include "common.h" /* * Timer interrupt handler */ static irqreturn_t h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); timer_tick(regs); + + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -48,8 +50,6 @@ static struct irqaction h7201_timer_irq = { */ void __init h7201_init_time(void) { - gettimeoffset = h720x_gettimeoffset; - CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START; @@ -57,3 +57,8 @@ void __init h7201_init_time(void) setup_irq(IRQ_TIMER0, &h7201_timer_irq); } + +struct sys_timer h7201_timer = { + .init = h7201_init_time, + .offset = h720x_gettimeoffset, +}; diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index ee7abcd29..4b6968eb2 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include "common.h" static struct resource h7202ps2_resources[] = { [0] = { @@ -44,13 +46,55 @@ static struct platform_device h7202ps2_device = { .resource = h7202ps2_resources, }; +static struct plat_serial8250_port serial_platform_data[] = { + { + .membase = SERIAL0_BASE, + .irq = IRQ_UART0, + .uartclk = 2*1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .membase = SERIAL1_BASE, + .irq = IRQ_UART1, + .uartclk = 2*1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .membase = SERIAL2_BASE, + .irq = IRQ_UART2, + .uartclk = 2*1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .membase = SERIAL3_BASE, + .irq = IRQ_UART3, + .uartclk = 2*1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + static struct platform_device *devices[] __initdata = { &h7202ps2_device, + &serial_device, }; -extern unsigned long h720x_gettimeoffset(void); -extern void __init h720x_init_irq (void); - /* Although we have two interrupt lines for the timers, we only have one * status register which clears all pending timer interrupts on reading. So * we have to handle all timer interrupts in one place. @@ -64,7 +108,9 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc, mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); if ( mask & TSTAT_T0INT ) { + write_seqlock(&xtime_lock); timer_tick(regs); + write_sequnlock(&xtime_lock); if( mask == TSTAT_T0INT ) return; } @@ -128,8 +174,6 @@ static struct irqaction h7202_timer_irq = { */ void __init h7202_init_time(void) { - gettimeoffset = h720x_gettimeoffset; - CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET; CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START; @@ -138,6 +182,11 @@ void __init h7202_init_time(void) setup_irq(IRQ_TIMER0, &h7202_timer_irq); } +struct sys_timer h7202_timer = { + .init = h7202_init_time, + .offset = h720x_gettimeoffset, +}; + void __init h7202_init_irq (void) { int irq; diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c index d2208c1e5..9b24b9b0d 100644 --- a/arch/arm/mach-h720x/h7201-eval.c +++ b/arch/arm/mach-h720x/h7201-eval.c @@ -27,10 +27,7 @@ #include #include #include - -extern void h720x_init_irq (void); -extern void h7201_init_time(void); -extern void __init h720x_map_io(void); +#include "common.h" MACHINE_START(H7201, "Hynix GMS30C7201") MAINTAINER("Robert Schwebel, Pengutronix") @@ -38,5 +35,5 @@ MACHINE_START(H7201, "Hynix GMS30C7201") BOOT_PARAMS(0xc0001000) MAPIO(h720x_map_io) INITIRQ(h720x_init_irq) - INITTIME(h7201_init_time) + .timer = &h7201_timer, MACHINE_END diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c index 939873197..3456a00d5 100644 --- a/arch/arm/mach-h720x/h7202-eval.c +++ b/arch/arm/mach-h720x/h7202-eval.c @@ -27,11 +27,7 @@ #include #include #include - -extern void __init init_hw_h7202(void); -extern void __init h7202_init_irq (void); -extern void __init h7202_init_time(void); -extern void __init h720x_map_io(void); +#include "common.h" static struct resource cirrus_resources[] = { [0] = { @@ -80,6 +76,6 @@ MACHINE_START(H7202, "Hynix HMS30C7202") BOOT_PARAMS(0x40000100) MAPIO(h720x_map_io) INITIRQ(h7202_init_irq) - INITTIME(h7202_init_time) + .timer = &h7202_timer, INIT_MACHINE(init_eval_h7202) MACHINE_END diff --git a/arch/arm/mach-imx/generic.h b/arch/arm/mach-imx/generic.h index 31e1911b1..e91003e4b 100644 --- a/arch/arm/mach-imx/generic.h +++ b/arch/arm/mach-imx/generic.h @@ -11,4 +11,6 @@ extern void __init imx_map_io(void); extern void __init imx_init_irq(void); -extern void __init imx_init_time(void); + +struct sys_timer; +extern struct sys_timer imx_timer; diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c index bd92b909a..625dd01c2 100644 --- a/arch/arm/mach-imx/mx1ads.c +++ b/arch/arm/mach-imx/mx1ads.c @@ -83,6 +83,6 @@ MACHINE_START(MX1ADS, "Motorola MX1ADS") BOOT_PARAMS(0x08000100) MAPIO(mx1ads_map_io) INITIRQ(imx_init_irq) - INITTIME(imx_init_time) + .timer = &imx_timer, INIT_MACHINE(mx1ads_init) MACHINE_END diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index ac7cab9b0..11f1e56c3 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -28,8 +28,7 @@ * Returns number of us since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() */ -static unsigned long -imx_gettimeoffset(void) +static unsigned long imx_gettimeoffset(void) { unsigned long ticks; @@ -59,11 +58,15 @@ imx_gettimeoffset(void) static irqreturn_t imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + /* clear the interrupt */ if (IMX_TSTAT(TIMER_BASE)) IMX_TSTAT(TIMER_BASE) = 0; timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -76,8 +79,7 @@ static struct irqaction imx_timer_irq = { /* * Set up timer interrupt, and return the current time in seconds. */ -void __init -imx_init_time(void) +static void __init imx_timer_init(void) { /* * Initialise to a known state (all timers off, and timing reset) @@ -91,5 +93,9 @@ imx_init_time(void) * Make irqs happen for the system timer */ setup_irq(TIM1_INT, &imx_timer_irq); - gettimeoffset = imx_gettimeoffset; } + +struct sys_timer imx_timer = { + .init = imx_timer_init, + .offset = imx_gettimeoffset, +}; diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index 6af3715ad..56200594d 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -76,7 +76,10 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - return rate; + struct icst525_vco vco; + + vco = icst525_khz_to_vco(clk->params, rate / 1000); + return icst525_khz(clk->params, vco) * 1000; } EXPORT_SYMBOL(clk_round_rate); @@ -86,8 +89,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst525_vco vco; - vco = icst525_khz_to_vco(clk->params, rate); - clk->rate = icst525_khz(clk->params, vco); + vco = icst525_khz_to_vco(clk->params, rate / 1000); + clk->rate = icst525_khz(clk->params, vco) * 1000; printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", clk->name, vco.s, vco.r, vco.v); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 7f6df02cf..eb16dea60 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -24,6 +24,8 @@ #include #include +#include "common.h" + static struct amba_device rtc_device = { .dev = { .bus_id = "mb:15", @@ -163,15 +165,13 @@ typedef struct TimerStruct { unsigned long TimerClear; } TimerStruct_t; -extern unsigned long (*gettimeoffset)(void); - static unsigned long timer_reload; /* * Returns number of ms since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() */ -static unsigned long integrator_gettimeoffset(void) +unsigned long integrator_gettimeoffset(void) { volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE; unsigned long ticks1, ticks2, status; @@ -214,11 +214,15 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; + write_seqlock(&xtime_lock); + // ...clear the interrupt timer1->TimerClear = 1; timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -264,5 +268,4 @@ void __init integrator_time_init(unsigned long reload, unsigned int ctrl) * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); - gettimeoffset = integrator_gettimeoffset; } diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index e2a07deda..71c58bff3 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -79,7 +79,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - unsigned long cpus_allowed; + cpumask_t cpus_allowed; int cpu = policy->cpu; struct icst525_vco vco; struct cpufreq_freqs freqs; @@ -94,7 +94,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, * Bind to the specified CPU. When this call returns, * we should be running on the right CPU. */ - set_cpus_allowed(current, 1 << cpu); + set_cpus_allowed(current, cpumask_of_cpu(cpu)); BUG_ON(cpu != smp_processor_id()); /* get current setting */ @@ -154,14 +154,14 @@ static int integrator_set_target(struct cpufreq_policy *policy, static unsigned int integrator_get(unsigned int cpu) { - unsigned long cpus_allowed; + cpumask_t cpus_allowed; unsigned int current_freq; u_int cm_osc; struct icst525_vco vco; cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, 1 << cpu); + set_cpus_allowed(current, cpumask_of_cpu(cpu)); BUG_ON(cpu != smp_processor_id()); /* detect memory etc. */ diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index e776e8a8d..0859557e7 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -87,10 +88,198 @@ void impd1_tweak_control(struct device *dev, u32 mask, u32 val) EXPORT_SYMBOL(impd1_tweak_control); +/* + * CLCD support + */ +#define PANEL PROSPECTOR + +#define LTM10C209 1 +#define PROSPECTOR 2 +#define SVGA 3 +#define VGA 4 + +#if PANEL == VGA +#define PANELTYPE vga +static struct clcd_panel vga = { + .mode = { + .name = "VGA", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = 39721, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .connector = IMPD1_CTRL_DISP_VGA, + .bpp = 16, + .grayscale = 0, +}; + +#elif PANEL == SVGA +#define PANELTYPE svga +static struct clcd_panel svga = { + .mode = { + .name = "SVGA", + .refresh = 0, + .xres = 800, + .yres = 600, + .pixclock = 27778, + .left_margin = 20, + .right_margin = 20, + .upper_margin = 5, + .lower_margin = 5, + .hsync_len = 164, + .vsync_len = 62, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .connector = IMPD1_CTRL_DISP_VGA, + .bpp = 16, + .grayscale = 0, +}; + +#elif PANEL == PROSPECTOR +#define PANELTYPE prospector +static struct clcd_panel prospector = { + .mode = { + .name = "PROSPECTOR", + .refresh = 0, + .xres = 640, + .yres = 480, + .pixclock = 40000, + .left_margin = 33, + .right_margin = 64, + .upper_margin = 36, + .lower_margin = 7, + .hsync_len = 64, + .vsync_len = 25, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .fixedtimings = 1, + .connector = IMPD1_CTRL_DISP_LCD, + .bpp = 16, + .grayscale = 0, +}; + +#elif PANEL == LTM10C209 +#define PANELTYPE ltm10c209 +/* + * Untested. + */ +static struct clcd_panel ltm10c209 = { + .mode = { + .name = "LTM10C209", + .refresh = 0, + .xres = 640, + .yres = 480, + .pixclock = 40000, + .left_margin = 20, + .right_margin = 20, + .upper_margin = 19, + .lower_margin = 19, + .hsync_len = 20, + .vsync_len = 10, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .fixedtimings = 1, + .connector = IMPD1_CTRL_DISP_LCD, + .bpp = 16, + .grayscale = 0, +}; +#endif + +/* + * Disable all display connectors on the interface module. + */ +static void impd1fb_clcd_disable(struct clcd_fb *fb) +{ + impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0); +} + +/* + * Enable the relevant connector on the interface module. + */ +static void impd1fb_clcd_enable(struct clcd_fb *fb) +{ + impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, + fb->panel->connector | IMPD1_CTRL_DISP_ENABLE); +} + +static int impd1fb_clcd_setup(struct clcd_fb *fb) +{ + unsigned long framebase = fb->dev->res.start + 0x01000000; + unsigned long framesize = SZ_1M; + int ret = 0; + + fb->panel = &PANELTYPE; + + if (!request_mem_region(framebase, framesize, "clcd framebuffer")) { + printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n"); + return -EBUSY; + } + + fb->fb.screen_base = ioremap(framebase, framesize); + if (!fb->fb.screen_base) { + printk(KERN_ERR "IM-PD1: unable to map framebuffer\n"); + ret = -ENOMEM; + goto free_buffer; + } + + fb->fb.fix.smem_start = framebase; + fb->fb.fix.smem_len = framesize; + + return 0; + + free_buffer: + release_mem_region(framebase, framesize); + return ret; +} + +static void impd1fb_clcd_remove(struct clcd_fb *fb) +{ + iounmap(fb->fb.screen_base); + release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len); +} + +static struct clcd_board impd1_clcd_data = { + .name = "IM-PD/1", + .check = clcdfb_check, + .decode = clcdfb_decode, + .disable = impd1fb_clcd_disable, + .enable = impd1fb_clcd_enable, + .setup = impd1fb_clcd_setup, + .remove = impd1fb_clcd_remove, +}; + struct impd1_device { unsigned long offset; unsigned int irq[2]; unsigned int id; + void *platform_data; }; static struct impd1_device impd1_devs[] = { @@ -133,6 +322,7 @@ static struct impd1_device impd1_devs[] = { .offset = 0x01000000, .irq = { 11 }, .id = 0x00041110, + .platform_data = &impd1_clcd_data, } }; @@ -202,6 +392,7 @@ static int impd1_probe(struct lm_device *dev) d->irq[0] = dev->irq; d->irq[1] = dev->irq; d->periphid = idev->id; + d->dev.platform_data = idev->platform_data; ret = amba_device_register(d, &dev->resource); if (ret) { diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index b07e39d21..ad667711d 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -40,7 +40,9 @@ #include #include #include +#include +#include "common.h" /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx @@ -281,17 +283,22 @@ static void __init ap_init(void) } } -static void ap_time_init(void) +static void __init ap_init_timer(void) { integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0); } +static struct sys_timer ap_timer = { + .init = ap_init_timer, + .offset = integrator_gettimeoffset, +}; + MACHINE_START(INTEGRATOR, "ARM-Integrator") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x16000000, 0xf1600000) BOOT_PARAMS(0x00000100) MAPIO(ap_map_io) INITIRQ(ap_init_irq) - INITTIME(ap_time_init) + .timer = &ap_timer, INIT_MACHINE(ap_init) MACHINE_END diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index e56fcb1ea..19809bba4 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -23,8 +24,10 @@ #include #include #include +#include #include +#include #include #include @@ -32,7 +35,9 @@ #include #include #include +#include +#include "common.h" #include "clock.h" #define INTCP_PA_MMC_BASE 0x1c000000 @@ -382,10 +387,83 @@ static struct amba_device aaci_device = { .periphid = 0, }; + +/* + * CLCD support + */ +static struct clcd_panel vga = { + .mode = { + .name = "VGA", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = 39721, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .bpp = 16, + .grayscale = 0, +}; + +/* + * Ensure VGA is selected. + */ +static void cp_clcd_enable(struct clcd_fb *fb) +{ + cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA); +} + +static unsigned long framesize = SZ_1M; + +static int cp_clcd_setup(struct clcd_fb *fb) +{ + dma_addr_t dma; + + fb->panel = &vga; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = framesize; + + return 0; +} + +static void cp_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +static struct clcd_board clcd_data = { + .name = "Integrator/CP", + .check = clcdfb_check, + .decode = clcdfb_decode, + .enable = cp_clcd_enable, + .setup = cp_clcd_setup, + .remove = cp_clcd_remove, +}; + static struct amba_device clcd_device = { .dev = { .bus_id = "mb:c0", .coherent_dma_mask = ~0, + .platform_data = &clcd_data, }, .res = { .start = INTCP_PA_CLCD_BASE, @@ -420,17 +498,22 @@ static void __init intcp_init(void) #define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ -static void __init intcp_init_time(void) +static void __init intcp_timer_init(void) { integrator_time_init(1000000 / HZ, TIMER_CTRL_IE); } +static struct sys_timer cp_timer = { + .init = intcp_timer_init, + .offset = integrator_gettimeoffset, +}; + MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") BOOT_MEM(0x00000000, 0x16000000, 0xf1600000) BOOT_PARAMS(0x00000100) MAPIO(intcp_map_io) INITIRQ(intcp_init_irq) - INITTIME(intcp_init_time) + .timer = &cp_timer, INIT_MACHINE(intcp_init) MACHINE_END diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig index 6a388e273..019b1bf25 100644 --- a/arch/arm/mach-iop3xx/Kconfig +++ b/arch/arm/mach-iop3xx/Kconfig @@ -2,53 +2,48 @@ if ARCH_IOP3XX menu "IOP3xx Implementation Options" -choice - prompt "IOP3xx System Type" - default ARCH_IQ80310 - -config ARCH_IQ80310 - bool "IQ80310" - help - Say Y here if you want to run your kernel on the Intel IQ80310 - evaluation kit for the IOP310 chipset. +comment "IOP3xx Platform Types" config ARCH_IQ80321 - bool "IQ80321" + bool "Enable support for IQ80321" + select ARCH_IOP321 help Say Y here if you want to run your kernel on the Intel IQ80321 evaluation kit for the IOP321 chipset. -endchoice -# Which IOP variant are we running? -config ARCH_IOP310 - bool - default ARCH_IQ80310 +config ARCH_IQ31244 + bool "Enable support for IQ31244" + select ARCH_IOP321 help - The IQ80310 uses the IOP310 variant. + Say Y here if you want to run your kernel on the Intel IQ31244 + evaluation kit for the IOP321 chipset. + +config ARCH_IQ80331 + bool "Enable support for IQ80331" + select ARCH_IOP331 + help + Say Y here if you want to run your kernel on the Intel IQ80331 + evaluation kit for the IOP331 chipset. + +config ARCH_EP80219 + bool "Enable support for EP80219" + select ARCH_IOP321 + select ARCH_IQ31244 +# Which IOP variant are we running? config ARCH_IOP321 bool - default ARCH_IQ80321 help The IQ80321 uses the IOP321 variant. + The IQ31244 and EP80219 uses the IOP321 variant. -comment "IOP3xx Chipset Features" - -config IOP3XX_AAU - bool "Support Intel IOP3xx Application Accelerator Unit (EXPERIMENTAL)" - depends on EXPERIMENTAL - -config IOP3XX_DMA - bool "Support Intel IOP3xx DMA (EXPERIMENTAL)" - depends on EXPERIMENTAL - -config IOP3XX_MU - bool "Support Intel IOP3xx Messaging Unit (EXPERIMENTAL)" - depends on EXPERIMENTAL +config ARCH_IOP331 + bool + default ARCH_IQ80331 + help + The IQ80331 uses the IOP331 variant. -config IOP3XX_PMON - bool "Support Intel IOP3xx Performance Monitor (EXPERIMENTAL)" - depends on EXPERIMENTAL +comment "IOP3xx Chipset Features" endmenu diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile index a6d1cf98b..e633dd9f4 100644 --- a/arch/arm/mach-iop3xx/Makefile +++ b/arch/arm/mach-iop3xx/Makefile @@ -4,27 +4,18 @@ # Object file lists. -obj-y := arch.o +obj-y := common.o obj-m := obj-n := obj- := -obj-$(CONFIG_ARCH_IOP310) += xs80200-irq.o iop310-irq.o iop310-pci.o mm.o +obj-$(CONFIG_ARCH_IOP321) += iop321-setup.o iop321-irq.o iop321-pci.o iop321-time.o -obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o +obj-$(CONFIG_ARCH_IOP331) += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o -obj-$(CONFIG_ARCH_IOP321) += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o +obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o -obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o +obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o -ifeq ($(CONFIG_ARCH_IQ80310),y) - ifneq ($(CONFIG_XSCALE_PMU_TIMER),y) - obj-y += iq80310-time.o - endif -endif - -obj-$(CONFIG_IOP3XX_AAU) += aau.o -obj-$(CONFIG_IOP3XX_DMA) += dma.o -obj-$(CONFIG_IOP3XX_MU) += message.o -obj-$(CONFIG_IOP3XX_PMON) += pmon.o +obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c index c0bbe5a18..bda7394ec 100644 --- a/arch/arm/mach-iop3xx/common.c +++ b/arch/arm/mach-iop3xx/common.c @@ -28,7 +28,6 @@ unsigned long iop3xx_pcibios_min_mem = 0; * Default power-off for EP80219 */ #include -#include static inline void ep80219_send_to_pic(__u8 c) { } diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c index 472faf582..d42aae6ae 100644 --- a/arch/arm/mach-iop3xx/iop321-irq.c +++ b/arch/arm/mach-iop3xx/iop321-irq.c @@ -81,7 +81,8 @@ void __init iop321_init_irq(void) intctl_write(0); // disable all interrupts intstr_write(0); // treat all as IRQ - if(machine_is_iq80321()) // all interrupts are inputs to chip + if(machine_is_iq80321() || + machine_is_iq31244()) // all interrupts are inputs to chip *IOP321_PCIIRSR = 0x0f; for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++) diff --git a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c index 3ae69a1ff..8fdfc3a8f 100644 --- a/arch/arm/mach-iop3xx/iop321-pci.c +++ b/arch/arm/mach-iop3xx/iop321-pci.c @@ -44,7 +44,7 @@ static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where) u32 addr; if (sys->busnr == bus->number) - addr = 1 << (PCI_SLOT(devfn) + 16); + addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); else addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; @@ -158,6 +158,8 @@ iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where, : "r" (value), "r" (addr), "r" (IOP321_OCCAR), "r" (IOP321_OCCDR)); } + + return PCIBIOS_SUCCESSFUL; } static struct pci_ops iop321_ops = { @@ -193,53 +195,16 @@ struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys) return pci_scan_bus(sys->busnr, &iop321_ops, sys); } -/* - * Setup the system data for controller 'nr'. Return 0 if none found, - * 1 if found, or negative error. - */ -int iop321_setup(int nr, struct pci_sys_data *sys) -{ - struct resource *res; - - if (nr >= 1) - return 0; - - res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL); - if (!res) - panic("PCI: unable to alloc resources"); - - memset(res, 0, sizeof(struct resource) * 2); - - switch (nr) { - case 0: - res[0].start = IOP321_PCI_IO_BASE + 0x6e000000; - res[0].end = IOP321_PCI_IO_BASE + IOP321_PCI_IO_SIZE-1 + 0x6e000000; - res[0].name = "PCI IO Primary"; - res[0].flags = IORESOURCE_IO; - - res[1].start = IOP321_PCI_MEM_BASE; - res[1].end = IOP321_PCI_MEM_BASE + IOP321_PCI_MEM_SIZE; - res[1].name = "PCI Memory Primary"; - res[1].flags = IORESOURCE_MEM; - break; - } - - request_resource(&ioport_resource, &res[0]); - request_resource(&iomem_resource, &res[1]); - - sys->resource[0] = &res[0]; - sys->resource[1] = &res[1]; - sys->resource[2] = NULL; - sys->io_offset = 0x6e000000; - - return 1; -} - - - - void iop321_init(void) { +#if CONFIG_ARCH_EP80219 + *IOP321_ATUCR = 0x2; + *IOP321_OIOWTVR = 0x90000000; + *IOP321_IABAR0 = 0x00000004; + *IOP321_IABAR2 = 0xa000000c; + *IOP321_IALR2 = 0xe0000000; +#endif + DBG("PCI: Intel 80321 PCI init code.\n"); DBG("\tATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD); DBG("\tATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n", @@ -251,7 +216,12 @@ void iop321_init(void) DBG("\tATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n", *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2); DBG("\tATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n", *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3); +#if 0 + hook_fault_code(4, iop321_pci_abort, SIGBUS, "external abort on linefetch"); + hook_fault_code(6, iop321_pci_abort, SIGBUS, "external abort on linefetch"); + hook_fault_code(8, iop321_pci_abort, SIGBUS, "external abort on non-linefetch"); + hook_fault_code(10, iop321_pci_abort, SIGBUS, "external abort on non-linefetch"); +#endif hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort"); - } diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c index e92f77fbb..12e4a787b 100644 --- a/arch/arm/mach-iop3xx/iop321-setup.c +++ b/arch/arm/mach-iop3xx/iop321-setup.c @@ -9,11 +9,21 @@ * published by the Free Software Foundation. * */ +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -21,41 +31,80 @@ #include #include +#define IOP321_UART_XTAL 1843200 + +/* + * Standard IO mapping for all IOP321 based systems + */ +static struct map_desc iop321_std_desc[] __initdata = { + /* virtual physical length type */ + + /* mem mapped registers */ + { IOP321_VIRT_MEM_BASE, IOP321_PHY_MEM_BASE, 0x00002000, MT_DEVICE }, + + /* PCI IO space */ + { 0xfe000000, 0x90000000, 0x00020000, MT_DEVICE } +}; + +#ifdef CONFIG_ARCH_IQ80321 +#define UARTBASE IQ80321_UART +#define IRQ_UART IRQ_IQ80321_UART +#endif + +#ifdef CONFIG_ARCH_IQ31244 +#define UARTBASE IQ31244_UART +#define IRQ_UART IRQ_IQ31244_UART +#endif + +static struct uart_port iop321_serial_ports[] = { + { + .membase = (char*)(UARTBASE), + .mapbase = (UARTBASE), + .irq = IRQ_UART, + .flags = UPF_SKIP_TEST, + .iotype = UPIO_MEM, + .regshift = 0, + .uartclk = IOP321_UART_XTAL, + .line = 0, + .type = PORT_16550A, + .fifosize = 16 + } +}; + +void __init iop321_map_io(void) +{ + iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc)); + early_serial_setup(&iop321_serial_ports[0]); +} + #ifdef CONFIG_ARCH_IQ80321 extern void iq80321_map_io(void); -extern void iop321_init_irq(void); +extern struct sys_timer iop321_timer; extern void iop321_init_time(void); #endif #ifdef CONFIG_ARCH_IQ31244 extern void iq31244_map_io(void); -extern void iop321_init_irq(void); +extern struct sys_timer iop321_timer; extern void iop321_init_time(void); #endif -static void __init -fixup_iop321(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) -{ -} - #if defined(CONFIG_ARCH_IQ80321) MACHINE_START(IQ80321, "Intel IQ80321") MAINTAINER("Intel Corporation") - BOOT_MEM(PHYS_OFFSET, IQ80321_UART, 0xfe800000) - FIXUP(fixup_iop321) + BOOT_MEM(PHYS_OFFSET, IQ80321_UART, IQ80321_UART) MAPIO(iq80321_map_io) INITIRQ(iop321_init_irq) - INITTIME(iop321_init_time) + .timer = &iop321_timer, BOOT_PARAMS(0xa0000100) MACHINE_END #elif defined(CONFIG_ARCH_IQ31244) - MACHINE_START(IQ31244, "Intel IQ31244") +MACHINE_START(IQ31244, "Intel IQ31244") MAINTAINER("Intel Corp.") BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART) MAPIO(iq31244_map_io) INITIRQ(iop321_init_irq) - INITTIME(iop321_init_time) + .timer = &iop321_timer, BOOT_PARAMS(0xa0000100) MACHINE_END #else diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c index be36c7069..9b7dd64d1 100644 --- a/arch/arm/mach-iop3xx/iop321-time.c +++ b/arch/arm/mach-iop3xx/iop321-time.c @@ -5,7 +5,7 @@ * * Author: Deepak Saxena * - * Copyright 2002 MontaVista Software Inc. + * Copyright 2002-2003 MontaVista Software 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 @@ -23,17 +23,23 @@ #include #include #include - +#include #include #include +#define IOP321_TIME_SYNC 0 + +static inline unsigned long get_elapsed(void) +{ + return LATCH - *IOP321_TU_TCR0; +} + static unsigned long iop321_gettimeoffset(void) { unsigned long elapsed, usec; + u32 tisr1, tisr2; /* - * FIXME: Implement what is described in this comment. - * * If an interrupt was pending before we read the timer, * we've already wrapped. Factor this into the time. * If an interrupt was pending after we read the timer, @@ -42,12 +48,19 @@ static unsigned long iop321_gettimeoffset(void) * be sure its value is after the wrap. */ - elapsed = *IOP321_TU_TCR0; + asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1)); + elapsed = get_elapsed(); + asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2)); + + if(tisr1 & 1) + elapsed += LATCH; + else if (tisr2 & 1) + elapsed = LATCH + get_elapsed(); /* * Now convert them to usec. */ - usec = (unsigned long)((LATCH - elapsed) * (tick_nsec / 1000)) / LATCH; + usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; return usec; } @@ -57,14 +70,16 @@ iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 tisr; - asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); + write_seqlock(&xtime_lock); + asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); tisr |= 1; - asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr)); timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -74,14 +89,10 @@ static struct irqaction iop321_timer_irq = { .flags = SA_INTERRUPT }; -extern int setup_arm_irq(int, struct irqaction*); - -void __init iop321_init_time(void) +static void __init iop321_timer_init(void) { u32 timer_ctl; - u32 latch = LATCH; - gettimeoffset = iop321_gettimeoffset; setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq); timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD | @@ -92,4 +103,7 @@ void __init iop321_init_time(void) asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl)); } - +struct sys_timer iop321_timer = { + .init = &iop321_timer_init, + .offset = iop321_gettimeoffset, +}; diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c index 681e1ce78..6cb68f3e8 100644 --- a/arch/arm/mach-iop3xx/iop331-setup.c +++ b/arch/arm/mach-iop3xx/iop331-setup.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -81,7 +80,7 @@ void __init iop331_map_io(void) #ifdef CONFIG_ARCH_IQ80331 extern void iop331_init_irq(void); -extern void iop331_init_time(void); +extern struct sys_timer iop331_timer; extern void iq80331_map_io(void); #endif @@ -92,7 +91,7 @@ MACHINE_START(IQ80331, "Intel IQ80331") //BOOT_MEM(PHYS_OFFSET, IQ80331_UART0_VIRT, IQ80331_UART0_PHYS) MAPIO(iq80331_map_io) INITIRQ(iop331_init_irq) - INITTIME(iop331_init_time) + .timer = &iop331_timer, BOOT_PARAMS(0x0100) MACHINE_END #else diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c index c90a0c9bd..e01696769 100644 --- a/arch/arm/mach-iop3xx/iop331-time.c +++ b/arch/arm/mach-iop3xx/iop331-time.c @@ -27,13 +27,9 @@ #include #include -#undef IOP331_TIME_SYNC - -static unsigned long iop331_latch; - static inline unsigned long get_elapsed(void) { - return iop331_latch - *IOP331_TU_TCR0; + return LATCH - *IOP331_TU_TCR0; } static unsigned long iop331_gettimeoffset(void) @@ -55,14 +51,14 @@ static unsigned long iop331_gettimeoffset(void) asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2)); if(tisr1 & 1) - elapsed += iop331_latch; + elapsed += LATCH; else if (tisr2 & 1) - elapsed = iop331_latch + get_elapsed(); + elapsed = LATCH + get_elapsed(); /* * Now convert them to usec. */ - usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop331_latch; + usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; return usec; } @@ -71,36 +67,16 @@ static irqreturn_t iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 tisr; -#ifdef IOP331_TIME_SYNC - u32 passed; -#define TM_THRESH (iop331_latch*2) -#endif - asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); + write_seqlock(&xtime_lock); + asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr)); tisr |= 1; - asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr)); -#ifdef IOP331_TIME_SYNC - passed = 0xffffffff - *IOP331_TU_TCR1; - - do - { - do_timer(regs); - if(passed < TM_THRESH) - break; - if(passed > iop331_latch) - passed -= iop331_latch; - else - passed = 0; - } while(1); - - asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff)); -#else - do_timer(regs); -#endif + timer_tick(regs); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -110,32 +86,22 @@ static struct irqaction iop331_timer_irq = { .flags = SA_INTERRUPT }; -extern int setup_arm_irq(int, struct irqaction*); - -void __init iop331_init_time(void) +static void __init iop331_timer_init(void) { u32 timer_ctl; - iop331_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ; - gettimeoffset = iop331_gettimeoffset; setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq); timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD | IOP331_TMR_RATIO_1_1; - asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop331_latch)); + asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH)); asm volatile("mcr p6, 0, %0, c0, c1, 0" : : "r" (timer_ctl)); -#ifdef IOP331_TIME_SYNC - /* Setup second timer */ - /* setup counter */ - timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | - IOP331_TMR_RATIO_1_1; - asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff)); - /* setup control */ - asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl)); -#endif } - +struct sys_timer iop331_timer = { + .init = iop331_timer_init, + .offset = iop331_gettimeoffset, +}; diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c index 7dce5dfa6..5d9624863 100644 --- a/arch/arm/mach-iop3xx/iq80321-pci.c +++ b/arch/arm/mach-iop3xx/iq80321-pci.c @@ -38,37 +38,79 @@ #define INTE IRQ_IQ80321_I82544 -typedef u8 irq_table[4]; - -static irq_table pci_irq_table[] = { - /* - * PCI IDSEL/INTPIN->INTLINE - * A B C D - */ - {INTE, INTE, INTE, INTE}, /* Gig-E */ - {INTD, INTC, INTD, INTA}, /* Unused */ - {INTC, INTD, INTA, INTB}, /* PCI-X Slot */ -}; - static inline int __init iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) { + static int pci_irq_table[][4] = { + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + {INTE, INTE, INTE, INTE}, /* Gig-E */ + {-1, -1, -1, -1}, /* Unused */ + {INTC, INTD, INTA, INTB}, /* PCI-X Slot */ + {-1, -1, -1, -1}, + }; + BUG_ON(pin < 1 || pin > 4); - return PCI_IRQ_TABLE_LOOKUP(2, 3); +// return PCI_IRQ_TABLE_LOOKUP(4, 7); + return pci_irq_table[idsel%4][pin-1]; } static int iq80321_setup(int nr, struct pci_sys_data *sys) { - switch (nr) { - case 0: - sys->map_irq = iq80321_map_irq; - break; - default: + struct resource *res; + + if(nr != 0) return 0; - } - return iop321_setup(nr, sys); + res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("PCI: unable to alloc resources"); + + memset(res, 0, sizeof(struct resource) * 2); + + res[0].start = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_OFFSET; + res[0].end = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_SIZE - 1 + IQ80321_PCI_IO_OFFSET; + res[0].name = "IQ80321 PCI I/O Space"; + res[0].flags = IORESOURCE_IO; + + res[1].start = IQ80321_PCI_MEM_BASE; + res[1].end = IQ80321_PCI_MEM_BASE + IQ80321_PCI_MEM_SIZE; + res[1].name = "IQ80321 PCI Memory Space"; + res[1].flags = IORESOURCE_MEM; + + request_resource(&ioport_resource, &res[0]); + request_resource(&iomem_resource, &res[1]); + + /* + * Since the IQ80321 is a slave card on a PCI backplane, + * it uses BAR1 to reserve a portion of PCI memory space for + * use with the private devices on the secondary bus + * (GigE and PCI-X slot). We read BAR1 and configure + * our outbound translation windows to target that + * address range and assign all devices in that + * address range. W/O this, certain BIOSes will fail + * to boot as the IQ80321 claims addresses that are + * in use by other devices. + * + * Note that the same cannot be done with I/O space, + * so hopefully the host will stick to the lower 64K for + * PCI I/O and leave us alone. + */ + sys->mem_offset = IQ80321_PCI_MEM_BASE - + (*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK); + + sys->resource[0] = &res[0]; + sys->resource[1] = &res[1]; + sys->resource[2] = NULL; + sys->io_offset = IQ80321_PCI_IO_OFFSET; + + iop3xx_pcibios_min_io = IQ80321_PCI_IO_BASE; + iop3xx_pcibios_min_mem = IQ80321_PCI_MEM_BASE; + + return 1; } static void iq80321_preinit(void) @@ -82,6 +124,7 @@ static struct hw_pci iq80321_pci __initdata = { .setup = iq80321_setup, .scan = iop321_scan_bus, .preinit = iq80321_preinit, + .map_irq = iq80321_map_irq }; static int __init iq80321_pci_init(void) diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 2d6633751..0b5970308 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -9,7 +9,7 @@ * * Based on work Copyright (C) 2002-2003 Intel Corporation * - * This file is licensed under the terms of the GNU General Public + * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ @@ -33,10 +33,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -170,7 +168,7 @@ void __init ixp2000_map_io(void) static unsigned ticks_per_jiffy; static unsigned ticks_per_usec; -static unsigned long ixp2000_gettimeoffset (void) +unsigned long ixp2000_gettimeoffset (void) { unsigned long elapsed; @@ -182,11 +180,15 @@ static unsigned long ixp2000_gettimeoffset (void) static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + /* clear timer 1 */ ixp2000_reg_write(IXP2000_T1_CLR, 1); timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -198,8 +200,6 @@ static struct irqaction ixp2000_timer_irq = { void __init ixp2000_init_time(unsigned long tick_rate) { - gettimeoffset = ixp2000_gettimeoffset; - ixp2000_reg_write(IXP2000_T1_CLR, 0); ixp2000_reg_write(IXP2000_T2_CLR, 0); @@ -309,41 +309,6 @@ static struct irqchip ixp2000_pci_irq_chip = { .unmask = ixp2000_pci_irq_unmask }; -/* - * Error interrupts. These are used extensively by the microengine drivers - */ -static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - int i; - unsigned long status = *IXP2000_IRQ_ERR_STATUS; - - - for (i = 0; i <= 12; i++) { - if (status & (1 << i)) { - desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; - desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); - } - } -} - -static void ixp2000_err_irq_mask(unsigned int irq) -{ - ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR, - (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); -} - -static void ixp2000_err_irq_unmask(unsigned int irq) -{ - ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET, - (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); -} - -static struct irqchip ixp2000_err_irq_chip = { - .ack = ixp2000_err_irq_mask, - .mask = ixp2000_err_irq_mask, - .unmask = ixp2000_err_irq_unmask -}; - static void ixp2000_irq_mask(unsigned int irq) { ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq)); @@ -387,7 +352,7 @@ void __init ixp2000_init_irq(void) * we mark the reserved IRQs as invalid. This makes * our mask/unmask code much simpler. */ - for (irq = IRQ_IXP2000_SWI; irq <= IRQ_IXP2000_THDB3; irq++) { + for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { if((1 << irq) & IXP2000_VALID_IRQ_MASK) { set_irq_chip(irq, &ixp2000_irq_chip); set_irq_handler(irq, do_level_IRQ); @@ -409,18 +374,11 @@ void __init ixp2000_init_irq(void) /* * Enable PCI irq */ - *(IXP2000_IRQ_ENABLE_SET) = (1 << IRQ_IXP2000_PCI); + ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI)); for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) { set_irq_chip(irq, &ixp2000_pci_irq_chip); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, IRQF_VALID); } - - for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) { - set_irq_chip(irq, &ixp2000_err_irq_chip); - set_irq_handler(irq, do_level_IRQ); - set_irq_flags(irq, IRQF_VALID); - } - set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler); } diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c index a6e30d079..af894f4cc 100644 --- a/arch/arm/mach-ixp2000/enp2611.c +++ b/arch/arm/mach-ixp2000/enp2611.c @@ -26,9 +26,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -55,11 +52,16 @@ /************************************************************************* * ENP-2611 timer tick configuration *************************************************************************/ -static void __init enp2611_init_time(void) +static void __init enp2611_timer_init(void) { ixp2000_init_time(50 * 1000 * 1000); } +static struct enp2611_timer = { + .init = enp2611_timer_init, + .offset = ixp2000_gettimeoffset, +}; + /************************************************************************* * ENP-2611 PCI @@ -202,7 +204,7 @@ MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board") BOOT_PARAMS(0x00000100) MAPIO(ixp2000_map_io) INITIRQ(ixp2000_init_irq) - INITTIME(enp2611_init_time) + .timer = &enp2611_timer, INIT_MACHINE(enp2611_init_machine) MACHINE_END #endif diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c index 39ef558df..cd98116e1 100644 --- a/arch/arm/mach-ixp2000/ixdp2400.c +++ b/arch/arm/mach-ixp2000/ixdp2400.c @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -48,7 +45,7 @@ /************************************************************************* * IXDP2400 timer tick *************************************************************************/ -static void __init ixdp2400_init_time(void) +static void __init ixdp2400_timer_init(void) { int numerator, denominator; int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8}; @@ -59,6 +56,11 @@ static void __init ixdp2400_init_time(void) ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2); } +static struct timer ixdp2400_timer = { + .init = ixdp2400_timer_init, + .offset = ixp2000_gettimeoffset, +}; + /************************************************************************* * IXDP2400 PCI *************************************************************************/ @@ -171,7 +173,7 @@ MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform") BOOT_PARAMS(0x00000100) MAPIO(ixdp2x00_map_io) INITIRQ(ixdp2400_init_irq) - INITTIME(ixdp2400_init_time) + .timer = &ixdp2400_timer, INIT_MACHINE(ixdp2x00_init_machine) MACHINE_END diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c index 285eaf016..49334b485 100644 --- a/arch/arm/mach-ixp2000/ixdp2800.c +++ b/arch/arm/mach-ixp2000/ixdp2800.c @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -55,11 +52,16 @@ void ixdp2400_init_irq(void) * IXDP2800 timer tick *************************************************************************/ -static void __init ixdp2800_init_time(void) +static void __init ixdp2800_timer_init(void) { ixp2000_init_time(50000000); } +static struct sys_timer ixdp2800_timer = { + .init = ixdp2800_timer_init, + .offset = ixp2000_gettimeoffset, +}; + /************************************************************************* * IXDP2800 PCI *************************************************************************/ @@ -172,7 +174,7 @@ MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform") BOOT_PARAMS(0x00000100) MAPIO(ixdp2x00_map_io) INITIRQ(ixdp2800_init_irq) - INITTIME(ixdp2800_init_time) + .timer = &ixdp2800_timer, INIT_MACHINE(ixdp2x00_init_machine) MACHINE_END diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c index cda60b74c..5df9992b7 100644 --- a/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/arch/arm/mach-ixp2000/ixdp2x00.c @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -197,7 +194,7 @@ void __init ixdp2x00_map_io(void) * Linux is a common design in telecom systems. The problem is that instead * of all the devices being controlled by a single host, different * devices are controlles by different NPUs on the same bus, leading to - * multiple hosts on the bus.i The exact bus layout looks like: + * multiple hosts on the bus. The exact bus layout looks like: * * Bus 0 * Master NPU <-------------------+-------------------> Slave NPU @@ -213,9 +210,9 @@ void __init ixdp2x00_map_io(void) * ... Dev PMC Media Eth0 Eth1 ... * * The master controlls all but Eth1, which is controlled by the - * slave. What this measn is that the both the master and the slave + * slave. What this means is that the both the master and the slave * have to scan the bus, but only one of them can enumerate the bus. - * In addition, after the bus is scaned, each kernel must remove + * In addition, after the bus is scanned, each kernel must remove * the device(s) it does not control from the PCI dev list otherwise * a driver on each NPU will try to manage it and we will have horrible * conflicts. Oh..and the slave NPU needs to see the master NPU diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 176114aad..0e919bbf9 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -54,12 +51,14 @@ *************************************************************************/ static void ixdp2x01_irq_mask(unsigned int irq) { - *IXDP2X01_INT_MASK_SET_REG = IXP2000_BOARD_IRQ_MASK(irq); + ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, + IXP2000_BOARD_IRQ_MASK(irq)); } static void ixdp2x01_irq_unmask(unsigned int irq) { - *IXDP2X01_INT_MASK_CLR_REG = IXP2000_BOARD_IRQ_MASK(irq); + ixp2000_reg_write(IXDP2X01_INT_MASK_CLR_REG, + IXP2000_BOARD_IRQ_MASK(irq)); } static u32 valid_irq_mask; @@ -114,8 +113,8 @@ void __init ixdp2x01_init_irq(void) valid_irq_mask = IXDP2801_VALID_IRQ_MASK; /* Mask all interrupts from CPLD, disable simulation */ - *IXDP2X01_INT_MASK_SET_REG = 0xffffffff; - *IXDP2X01_INT_SIM_REG = 0; + ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff); + ixp2000_reg_write(IXDP2X01_INT_SIM_REG, 0); for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) { if (irq & valid_irq_mask) { @@ -193,7 +192,7 @@ static int __init ixdp2x01_clock_setup(char *str) __setup("ixdp2x01_clock=", ixdp2x01_clock_setup); -static void __init ixdp2x01_init_time(void) +static void __init ixdp2x01_timer_init(void) { if (!ixdp2x01_clock) ixdp2x01_clock = 50000000; @@ -201,6 +200,11 @@ static void __init ixdp2x01_init_time(void) ixp2000_init_time(ixdp2x01_clock); } +static struct sys_timer ixdp2x01_timer = { + .init = ixdp2x01_timer_init, + .offset = ixp2000_gettimeoffset, +}; + /************************************************************************* * IXDP2x01 PCI *************************************************************************/ @@ -312,8 +316,8 @@ static struct flash_platform_data ixdp2x01_flash_platform_data = { static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs) { - *IXDP2X01_CPLD_FLASH_REG = - ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN); + ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG, + ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN)); return (ofs & IXDP2X01_FLASH_WINDOW_MASK); } @@ -338,14 +342,29 @@ static struct platform_device ixdp2x01_flash = { .resource = &ixdp2x01_flash_resource, }; +static struct ixp2000_i2c_pins ixdp2x01_i2c_gpio_pins = { + .sda_pin = IXDP2X01_GPIO_SDA, + .scl_pin = IXDP2X01_GPIO_SCL, +}; + +static struct platform_device ixdp2x01_i2c_controller = { + .name = "IXP2000-I2C", + .id = 0, + .dev = { + .platform_data = &ixdp2x01_i2c_gpio_pins, + }, + .num_resources = 0 +}; + static struct platform_device *ixdp2x01_devices[] __initdata = { - &ixdp2x01_flash + &ixdp2x01_flash, + &ixdp2x01_i2c_controller }; static void __init ixdp2x01_init_machine(void) { - *IXDP2X01_CPLD_FLASH_REG = - (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN); + ixp2000_reg_write(IXDP2X01_CPLD_FLASH_REG, + (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN)); ixdp2x01_flash_data.nr_banks = ((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1); @@ -361,7 +380,7 @@ MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform") BOOT_PARAMS(0x00000100) MAPIO(ixdp2x01_map_io) INITIRQ(ixdp2x01_init_irq) - INITTIME(ixdp2x01_init_time) + .timer = &ixdp2x01_timer, INIT_MACHINE(ixdp2x01_init_machine) MACHINE_END #endif @@ -373,7 +392,7 @@ MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") BOOT_PARAMS(0x00000100) MAPIO(ixdp2x01_map_io) INITIRQ(ixdp2x01_init_irq) - INITTIME(ixdp2x01_init_time) + .timer = &ixdp2x01_timer, INIT_MACHINE(ixdp2x01_init_machine) MACHINE_END #endif diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c index d08cebe00..7e6c588db 100644 --- a/arch/arm/mach-ixp2000/pci.c +++ b/arch/arm/mach-ixp2000/pci.c @@ -148,13 +148,13 @@ int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_re cli(); temp = *(IXP2000_PCI_CONTROL); if (temp & ((1 << 8) | (1 << 5))) { - *(IXP2000_PCI_CONTROL) = temp; + ixp2000_reg_write(IXP2000_PCI_CONTROL, temp); } temp = *(IXP2000_PCI_CMDSTAT); if (temp & (1 << 29)) { while (temp & (1 << 29)) { - *(IXP2000_PCI_CMDSTAT) = temp; + ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); temp = *(IXP2000_PCI_CMDSTAT); } } @@ -178,13 +178,13 @@ clear_master_aborts(void) cli(); temp = *(IXP2000_PCI_CONTROL); if (temp & ((1 << 8) | (1 << 5))) { - *(IXP2000_PCI_CONTROL) = temp; + ixp2000_reg_write(IXP2000_PCI_CONTROL, temp); } temp = *(IXP2000_PCI_CMDSTAT); if (temp & (1 << 29)) { while (temp & (1 << 29)) { - *(IXP2000_PCI_CMDSTAT) = temp; + ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); temp = *(IXP2000_PCI_CMDSTAT); } } diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 46b72e106..79bf95ee6 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -29,6 +29,13 @@ config ARCH_IXDP425 IXDP425 Development Platform (Also known as Richfield). For more information on this platform, see Documentation/arm/IXP4xx. +config MACH_IXDPG425 + bool "IXDPG425" + help + Say 'Y' here if you want your kernel to support Intel's + IXDPG425 Development Platform (Also known as Montajade). + For more information on this platform, see Documentation/arm/IXP4xx. + # # IXCDP1100 is the exact same HW as IXDP425, but with a different machine # number from the bootloader due to marketing monkeys, so we just enable it diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index f656397f8..465e6f4cd 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile @@ -5,6 +5,7 @@ obj-y += common.o common-pci.o obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o +obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o obj-$(CONFIG_ARCH_PRPMC1100) += prpmc1100-pci.o prpmc1100-setup.o diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 664521892..69486bde9 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -33,7 +33,6 @@ #include #include #include -#include /* @@ -239,9 +238,10 @@ static u32 byte_lane_enable_bits(u32 n, int size) return 0xffffffff; } -static int read_config(u8 bus_num, u16 devfn, int where, int size, u32 *value) +static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { u32 n, byte_enables, addr, data; + u8 bus_num = bus->number; pr_debug("read_config from %d size %d dev %d:%d:%d\n", where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); @@ -261,9 +261,10 @@ static int read_config(u8 bus_num, u16 devfn, int where, int size, u32 *value) return PCIBIOS_SUCCESSFUL; } -static int write_config(u8 bus_num, u16 devfn, int where, int size, u32 value) +static int ixp4xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { u32 n, byte_enables, addr, data; + u8 bus_num = bus->number; pr_debug("write_config_byte %#x to %d size %d dev %d:%d:%d\n", value, where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); @@ -281,31 +282,11 @@ static int write_config(u8 bus_num, u16 devfn, int where, int size, u32 value) return PCIBIOS_SUCCESSFUL; } -/* - * Generalized PCI config access functions. - */ -static int ixp4xx_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *value) -{ - if (bus->number && !PCI_SLOT(devfn)) - return local_read_config(where, size, value); - return read_config(bus->number, devfn, where, size, value); -} - -static int ixp4xx_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) -{ - if (bus->number && !PCI_SLOT(devfn)) - return local_write_config(where, size, value); - return write_config(bus->number, devfn, where, size, value); -} - struct pci_ops ixp4xx_ops = { - .read = ixp4xx_read_config, - .write = ixp4xx_write_config, + .read = ixp4xx_pci_read_config, + .write = ixp4xx_pci_write_config, }; - /* * PCI abort handler */ diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index a4edbe0eb..3e24140ed 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -207,7 +207,7 @@ void __init ixp4xx_init_irq(void) static unsigned volatile last_jiffy_time; -#define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC) +#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) /* IRQs are disabled before entering here from do_gettimeofday() */ static unsigned long ixp4xx_gettimeoffset(void) @@ -221,16 +221,20 @@ static unsigned long ixp4xx_gettimeoffset(void) static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; /* * Catch up with the real idea of time */ - do { + while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { timer_tick(regs); last_jiffy_time += LATCH; - } while((*IXP4XX_OSTS - last_jiffy_time) > LATCH); + } + + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -241,10 +245,8 @@ static struct irqaction ixp4xx_timer_irq = { .handler = ixp4xx_timer_interrupt }; -void __init ixp4xx_init_time(void) +static void __init ixp4xx_timer_init(void) { - gettimeoffset = ixp4xx_gettimeoffset; - /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; @@ -259,4 +261,7 @@ void __init ixp4xx_init_time(void) setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); } - +struct sys_timer ixp4xx_timer = { + .init = ixp4xx_timer_init, + .offset = ixp4xx_gettimeoffset, +}; diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 03ad0b718..a4b54430f 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ixp4xx/coyote-setup.c * - * ADI Engineering Coyote board-setup + * Board setup for ADI Engineering and IXDGP425 boards * * Copyright (C) 2003-2004 MontaVista Software, Inc. * @@ -30,7 +30,7 @@ #endif /* - * Only one serial port is connected on the Coyote. + * Only one serial port is connected on the Coyote & IXDPG425 */ static struct uart_port coyote_serial_port = { .membase = (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET), @@ -47,6 +47,13 @@ static struct uart_port coyote_serial_port = { void __init coyote_map_io(void) { + if (machine_is_ixdpg425()) { + coyote_serial_port.membase = + (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET); + coyote_serial_port.mapbase = IXP4XX_UART1_BASE_PHYS; + coyote_serial_port.irq = IRQ_IXP4XX_UART1; + } + early_serial_setup(&coyote_serial_port); ixp4xx_map_io(); @@ -79,17 +86,39 @@ static struct platform_device *coyote_devices[] __initdata = { static void __init coyote_init(void) { + *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; + *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; + platform_add_devices(&coyote_devices, ARRAY_SIZE(coyote_devices)); } -MACHINE_START(ADI_COYOTE, "ADI Engineering IXP4XX Coyote Development Platform") +#ifdef CONFIG_ARCH_ADI_COYOTE +MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") MAINTAINER("MontaVista Software, Inc.") BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(coyote_map_io) INITIRQ(ixp4xx_init_irq) - INITTIME(ixp4xx_init_time) + .timer = &ixp4xx_timer, BOOT_PARAMS(0x0100) INIT_MACHINE(coyote_init) MACHINE_END +#endif + +/* + * IXDPG425 is identical to Coyote except for which serial port + * is connected. + */ +#ifdef CONFIG_MACH_IXDPG425 +MACHINE_START(IXDPG425, "Intel IXDPG425") + MAINTAINER("MontaVista Software, Inc.") + BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS, + IXP4XX_PERIPHERAL_BASE_VIRT) + MAPIO(coyote_map_io) + INITIRQ(ixp4xx_init_irq) + .timer = &ixp4xx_timer, + BOOT_PARAMS(0x0100) + INIT_MACHINE(coyote_init) +MACHINE_END +#endif diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index dbcaa464b..9c299f92a 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -117,7 +117,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) - INITTIME(ixp4xx_init_time) + .timer = &ixp4xx_timer, BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END @@ -128,7 +128,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) - INITTIME(ixp4xx_init_time) + .timer = &ixp4xx_timer, BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END @@ -146,7 +146,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(ixdp425_map_io) INITIRQ(ixp4xx_init_irq) - INITTIME(ixp4xx_init_time) + .timer = &ixp4xx_timer, BOOT_PARAMS(0x0100) INIT_MACHINE(ixdp425_init) MACHINE_END diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c index 01e98fda0..199e454d1 100644 --- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c +++ b/arch/arm/mach-ixp4xx/prpmc1100-setup.c @@ -88,7 +88,7 @@ MACHINE_START(PRPMC1100, "Motorola PrPMC1100") IXP4XX_PERIPHERAL_BASE_VIRT) MAPIO(prpmc1100_map_io) INITIRQ(ixp4xx_init_irq) - INITTIME(ixp4xx_init_time) + .timer = &ixp4xx_timer, BOOT_PARAMS(0x0100) INIT_MACHINE(prpmc1100_init) MACHINE_END diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c index 6fa2a981e..be5d17fe9 100644 --- a/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -11,21 +11,19 @@ #include #include #include +#include #include #include #include #include -#include /* io_p2v() */ #include #include #include -#include +#include "common.h" /* This function calls the board specific IRQ initialization function. */ -extern void lh7a400_init_irq (void); -extern void lh7a40x_init_time (void); static struct map_desc kev7a400_io_desc[] __initdata = { { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE }, @@ -109,5 +107,5 @@ MACHINE_START (KEV7A400, "Sharp KEV7a400") BOOT_PARAMS (0xc0000100) MAPIO (kev7a400_map_io) INITIRQ (lh7a400_init_irq) - INITTIME (lh7a40x_init_time) + .timer = &lh7a40x_timer, MACHINE_END diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 9e0bf6c18..06373b295 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -11,17 +11,17 @@ #include #include #include +#include #include #include #include #include -#include /* io_p2v() */ #include #include #include -#include +#include "common.h" static struct resource smc91x_resources[] = { [0] = { @@ -45,7 +45,6 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -#if 0 static struct resource lh7a40x_usbclient_resources[] = { [0] = { .start = USB_PHYS, @@ -53,8 +52,8 @@ static struct resource lh7a40x_usbclient_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_USB, - .end = IRQ_USB, + .start = IRQ_USBINTR, + .end = IRQ_USBINTR, .flags = IORESOURCE_IRQ, }, }; @@ -62,7 +61,7 @@ static struct resource lh7a40x_usbclient_resources[] = { static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL; static struct platform_device lh7a40x_usbclient_device = { - .name = "lh7a40x-udc", + .name = "lh7a40x_udc", .id = 0, .dev = { .dma_mask = &lh7a40x_usbclient_dma_mask, @@ -71,7 +70,6 @@ static struct platform_device lh7a40x_usbclient_device = { .num_resources = ARRAY_SIZE (lh7a40x_usbclient_resources), .resource = lh7a40x_usbclient_resources, }; -#endif #if defined (CONFIG_ARCH_LH7A404) @@ -105,8 +103,7 @@ static struct platform_device lh7a404_usbhost_device = { static struct platform_device *lpd7a40x_devs[] __initdata = { &smc91x_device, -/* &lh7a40x_usbclient_device, */ - + &lh7a40x_usbclient_device, #if defined (CONFIG_ARCH_LH7A404) &lh7a404_usbhost_device, #endif @@ -264,16 +261,13 @@ lpd7a400_map_io(void) #ifdef CONFIG_MACH_LPD7A400 -extern void lh7a400_init_irq (void); -extern void lh7a40x_init_time (void); - MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10") MAINTAINER ("Marc Singer") BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000)) BOOT_PARAMS (0xc0000100) MAPIO (lpd7a400_map_io) INITIRQ (lh7a400_init_irq) - INITTIME (lh7a40x_init_time) + .timer = &lh7a40x_timer, INIT_MACHINE (lpd7a40x_init) MACHINE_END @@ -281,16 +275,13 @@ MACHINE_END #ifdef CONFIG_MACH_LPD7A404 -extern void lh7a404_init_irq (void); -extern void lh7a40x_init_time (void); - MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") MAINTAINER ("Marc Singer") BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000)) BOOT_PARAMS (0xc0000100) MAPIO (lpd7a400_map_io) INITIRQ (lh7a404_init_irq) - INITTIME (lh7a40x_init_time) + .timer = &lh7a40x_timer, INIT_MACHINE (lpd7a40x_init) MACHINE_END diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c index 61ada24c7..51e1c814b 100644 --- a/arch/arm/mach-lh7a40x/time.c +++ b/arch/arm/mach-lh7a40x/time.c @@ -20,14 +20,15 @@ #include #include +#include "common.h" #if HZ < 100 -# define TIMER_CONTROL TIMER_CONTROL1 -# define TIMER_LOAD TIMER_LOAD1 +# define TIMER_CONTROL TIMER_CONTROL2 +# define TIMER_LOAD TIMER_LOAD2 # define TIMER_CONSTANT (508469/HZ) # define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ) -# define TIMER_EOI TIMER_EOI1 -# define TIMER_IRQ IRQ_T1UI +# define TIMER_EOI TIMER_EOI2 +# define TIMER_IRQ IRQ_T2UI #else # define TIMER_CONTROL TIMER_CONTROL3 # define TIMER_LOAD TIMER_LOAD3 @@ -40,9 +41,13 @@ static irqreturn_t lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); + TIMER_EOI = 0; timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -52,7 +57,7 @@ static struct irqaction lh7a40x_timer_irq = { .handler = lh7a40x_timer_interrupt }; -void __init lh7a40x_init_time(void) +static void __init lh7a40x_timer_init(void) { /* Stop/disable all timers */ TIMER_CONTROL1 = 0; @@ -65,3 +70,6 @@ void __init lh7a40x_init_time(void) TIMER_CONTROL = TIMER_MODE; } +struct sys_timer lh7a40x_timer = { + .init = &lh7a40x_timer_init, +}; diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig index 9fb70d5dc..f8d265d70 100644 --- a/arch/arm/mach-omap/Kconfig +++ b/arch/arm/mach-omap/Kconfig @@ -5,58 +5,56 @@ menu "TI OMAP Implementations" comment "OMAP Core Type" config ARCH_OMAP730 + depends on ARCH_OMAP bool "OMAP730 Based System" - select CPU_ARM926T + select ARCH_OMAP_OTG config ARCH_OMAP1510 + depends on ARCH_OMAP default y bool "OMAP1510 Based System" - select CPU_ARM925T - select CPU_DCACHE_WRITETHROUGH -config ARCH_OMAP1610 - bool "OMAP1610 Based System" - select CPU_ARM926T +config ARCH_OMAP16XX + depends on ARCH_OMAP + bool "OMAP16XX Based System" + select ARCH_OMAP_OTG -config ARCH_OMAP5912 - bool "OMAP5912 Based System" - select CPU_ARM926T +config ARCH_OMAP_OTG + bool comment "OMAP Board Type" config MACH_OMAP_INNOVATOR bool "TI Innovator" - default y - depends on ARCH_OMAP1510 || ARCH_OMAP1610 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX help TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. config MACH_OMAP_H2 bool "TI H2 Support" - depends on ARCH_OMAP1610 - select MACH_OMAP_INNOVATOR + depends on ARCH_OMAP16XX help - TI OMAP 1610 H2 board support. Say Y here if you have such + TI OMAP 1610/1611B H2 board support. Say Y here if you have such a board. config MACH_OMAP_H3 bool "TI H3 Support" - depends on ARCH_OMAP1610 + depends on ARCH_OMAP16XX help - TI OMAP 1610 H3 board support. Say Y here if you have such + TI OMAP 1710 H3 board support. Say Y here if you have such a board. config MACH_OMAP_H4 bool "TI H4 Support" - depends on ARCH_OMAP1610 + depends on ARCH_OMAP16XX help TI OMAP 1610 H4 board support. Say Y here if you have such a board. config MACH_OMAP_OSK bool "TI OSK Support" - depends on ARCH_OMAP5912 + depends on ARCH_OMAP16XX help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. @@ -64,19 +62,16 @@ config MACH_OMAP_OSK config MACH_OMAP_PERSEUS2 bool "TI Perseus2" depends on ARCH_OMAP730 - select LEDS - select LEDS_TIMER - select LEDS_CPU help Support for TI OMAP 730 Perseus2 board. Say Y here if you have such a board. config MACH_OMAP_GENERIC bool "Generic OMAP board" - depends on ARCH_OMAP1510 || ARCH_OMAP1610 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX help - Support for generic OMAP-1510 or 1610 board with no - FPGA. Can be used as template for porting Linux to + Support for generic OMAP-1510, 1610 or 1710 board with + no FPGA. Can be used as template for porting Linux to custom OMAP boards. Say Y here if you have a custom board. @@ -84,6 +79,7 @@ comment "OMAP Feature Selections" #config OMAP_BOOT_TAG # bool "OMAP bootloader information passing" +# depends on ARCH_OMAP # default n # help # Say Y, if you have a bootloader which passes information @@ -91,6 +87,7 @@ comment "OMAP Feature Selections" config OMAP_MUX bool "OMAP multiplexing support" + depends on ARCH_OMAP default y help Pin multiplexing support for OMAP boards. If your bootloader @@ -106,8 +103,18 @@ config OMAP_MUX_DEBUG This is useful if you want to find out the correct values of the multiplexing registers. +config OMAP_MUX_WARNINGS + bool "Warn about pins the bootloader didn't set up" + depends on OMAP_MUX + default y + help + Choose Y here to warn whenever driver initialization logic needs + to change the pin multiplexing setup. When there are no warnings + printed, it's safe to deselect OMAP_MUX for your product. + choice prompt "Low-level debug console UART" + depends on ARCH_OMAP default OMAP_LL_DEBUG_UART1 config OMAP_LL_DEBUG_UART1 @@ -129,7 +136,7 @@ config OMAP_ARM_195MHZ config OMAP_ARM_192MHZ bool "OMAP ARM 192 MHz CPU" - depends on ARCH_OMAP1610 || ARCH_OMAP5912 + depends on ARCH_OMAP16XX help Enable 192MHz clock for OMAP CPU. If unsure, say N. @@ -141,26 +148,26 @@ config OMAP_ARM_182MHZ config OMAP_ARM_168MHZ bool "OMAP ARM 168 MHz CPU" - depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 || ARCH_OMAP5912 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730 help Enable 168MHz clock for OMAP CPU. If unsure, say N. config OMAP_ARM_120MHZ bool "OMAP ARM 120 MHz CPU" - depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730 help Enable 120MHz clock for OMAP CPU. If unsure, say N. config OMAP_ARM_60MHZ bool "OMAP ARM 60 MHz CPU" - depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730 default y help Enable 60MHz clock for OMAP CPU. If unsure, say Y. config OMAP_ARM_30MHZ bool "OMAP ARM 30 MHz CPU" - depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 + depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730 help Enable 30MHz clock for OMAP CPU. If unsure, say N. diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 5fcb1e5c7..2a6c49542 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -3,25 +3,27 @@ # # Common support -obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o +obj-y := common.o time.o irq.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o obj-m := obj-n := obj- := led-y := leds.o # Specific board support +obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o +obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o -# OCPI interconnect support for 1610 and 5912 -obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o -obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o +# OCPI interconnect support for 1710, 1610 and 5912 +obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # LEDs support +led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o -led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o +led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o obj-$(CONFIG_LEDS) += $(led-y) # Power Management diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c index 447046b24..586bc1271 100644 --- a/arch/arm/mach-omap/board-generic.c +++ b/arch/arm/mach-omap/board-generic.c @@ -22,31 +22,44 @@ #include #include -#include #include #include +#include +#include +#include #include "common.h" +static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; + static void __init omap_generic_init_irq(void) { omap_init_irq(); } -/* - * Muxes the serial ports on - */ -static void __init omap_early_serial_init(void) -{ - omap_cfg_reg(UART1_TX); - omap_cfg_reg(UART1_RTS); +/* assume no Mini-AB port */ - omap_cfg_reg(UART2_TX); - omap_cfg_reg(UART2_RTS); +#ifdef CONFIG_ARCH_OMAP1510 +static struct omap_usb_config generic1510_usb_config __initdata = { + .register_host = 1, + .register_dev = 1, + .hmc_mode = 16, + .pins[0] = 3, +}; +#endif - omap_cfg_reg(UART3_TX); - omap_cfg_reg(UART3_RX); -} +#if defined(CONFIG_ARCH_OMAP16XX) +static struct omap_usb_config generic1610_usb_config __initdata = { + .register_host = 1, + .register_dev = 1, + .hmc_mode = 16, + .pins[0] = 6, +}; +#endif + +static struct omap_board_config_kernel generic_config[] = { + { OMAP_TAG_USB, NULL }, +}; static void __init omap_generic_init(void) { @@ -55,9 +68,19 @@ static void __init omap_generic_init(void) * You have to mux them off in device drivers later on * if not needed. */ +#ifdef CONFIG_ARCH_OMAP1510 if (cpu_is_omap1510()) { - omap_early_serial_init(); + generic_config[0].data = &generic1510_usb_config; } +#endif +#if defined(CONFIG_ARCH_OMAP16XX) + if (!cpu_is_omap1510()) { + generic_config[0].data = &generic1610_usb_config; + } +#endif + omap_board_config = generic_config; + omap_board_config_size = ARRAY_SIZE(generic_config); + omap_serial_init(generic_serial_ports); } static void __init omap_generic_map_io(void) @@ -65,18 +88,12 @@ static void __init omap_generic_map_io(void) omap_map_io(); } -static void __init omap_generic_init_time(void) -{ - omap_init_time(); -} - -MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710") +MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") MAINTAINER("Tony Lindgren ") BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000) BOOT_PARAMS(0x10000100) MAPIO(omap_generic_map_io) INITIRQ(omap_generic_init_irq) INIT_MACHINE(omap_generic_init) - INITTIME(omap_generic_init_time) + .timer = &omap_timer, MACHINE_END - diff --git a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c index 1441089d9..f273b8d1c 100644 --- a/arch/arm/mach-omap/board-h2.c +++ b/arch/arm/mach-omap/board-h2.c @@ -32,16 +32,11 @@ #include #include #include +#include #include "common.h" -extern void __init omap_init_time(void); - -static struct map_desc h2_io_desc[] __initdata = { -{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE }, -{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE, - MT_DEVICE }, -}; +static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; static struct resource h2_smc91x_resources[] = { [0] = { @@ -80,15 +75,22 @@ static struct omap_usb_config h2_usb_config __initdata = { .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback) #elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */ + /* needs OTG cable, or NONSTANDARD (B-to-MiniB) */ .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled #endif .pins[1] = 3, }; +static struct omap_mmc_config h2_mmc_config __initdata = { + .mmc_blocks = 1, + .mmc1_power_pin = -1, /* tps65010 gpio3 */ + .mmc1_switch_pin = OMAP_MPUIO(1), +}; + static struct omap_board_config_kernel h2_config[] = { { OMAP_TAG_USB, &h2_usb_config }, + { OMAP_TAG_MMC, &h2_mmc_config }, }; static void __init h2_init(void) @@ -101,7 +103,7 @@ static void __init h2_init(void) static void __init h2_map_io(void) { omap_map_io(); - iotable_init(h2_io_desc, ARRAY_SIZE(h2_io_desc)); + omap_serial_init(h2_serial_ports); } MACHINE_START(OMAP_H2, "TI-H2") @@ -111,5 +113,5 @@ MACHINE_START(OMAP_H2, "TI-H2") MAPIO(h2_map_io) INITIRQ(h2_init_irq) INIT_MACHINE(h2_init) - INITTIME(omap_init_time) + .timer = &omap_timer, MACHINE_END diff --git a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c index d573b0cdf..301f22727 100644 --- a/arch/arm/mach-omap/board-h3.c +++ b/arch/arm/mach-omap/board-h3.c @@ -30,15 +30,17 @@ #include #include #include -#include "common.h" +#include -extern void __init omap_init_time(void); +#include "common.h" void h3_init_irq(void) { omap_init_irq(); } +static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; + static struct resource smc91x_resources[] = { [0] = { .start = OMAP1710_ETHR_START, /* Physical */ @@ -68,15 +70,10 @@ static void __init h3_init(void) (void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static struct map_desc h3_io_desc[] __initdata = { -{ OMAP1710_ETHR_BASE, OMAP1710_ETHR_START, OMAP1710_ETHR_SIZE, MT_DEVICE }, -{ OMAP_NOR_FLASH_BASE, OMAP_NOR_FLASH_START, OMAP_NOR_FLASH_SIZE, MT_DEVICE }, -}; - static void __init h3_map_io(void) { omap_map_io(); - iotable_init(h3_io_desc, ARRAY_SIZE(h3_io_desc)); + omap_serial_init(h3_serial_ports); } MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") @@ -86,5 +83,5 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") MAPIO(h3_map_io) INITIRQ(h3_init_irq) INIT_MACHINE(h3_init) - INITTIME(omap_init_time) + .timer = &omap_timer, MACHINE_END diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c index 6ef4d8dcf..1ad7a4aaf 100644 --- a/arch/arm/mach-omap/board-innovator.c +++ b/arch/arm/mach-omap/board-innovator.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "common.h" @@ -42,6 +44,8 @@ static struct map_desc innovator1510_io_desc[] __initdata = { MT_DEVICE }, }; +static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; + static struct resource innovator1510_smc91x_resources[] = { [0] = { .start = OMAP1510_FPGA_ETHR_START, /* Physical */ @@ -49,8 +53,8 @@ static struct resource innovator1510_smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = INT_ETHER, - .end = INT_ETHER, + .start = OMAP1510_INT_ETHER, + .end = OMAP1510_INT_ETHER, .flags = IORESOURCE_IRQ, }, }; @@ -68,18 +72,12 @@ static struct platform_device *innovator1510_devices[] __initdata = { #endif /* CONFIG_ARCH_OMAP1510 */ -#ifdef CONFIG_ARCH_OMAP1610 - -static struct map_desc innovator1610_io_desc[] __initdata = { -{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE }, -{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE, - MT_DEVICE }, -}; +#ifdef CONFIG_ARCH_OMAP16XX static struct resource innovator1610_smc91x_resources[] = { [0] = { - .start = OMAP1610_ETHR_START, /* Physical */ - .end = OMAP1610_ETHR_START + SZ_4K, + .start = INNOVATOR1610_ETHR_START, /* Physical */ + .end = INNOVATOR1610_ETHR_START + SZ_4K, .flags = IORESOURCE_MEM, }, [1] = { @@ -100,7 +98,7 @@ static struct platform_device *innovator1610_devices[] __initdata = { &innovator1610_smc91x_device, }; -#endif /* CONFIG_ARCH_OMAP1610 */ +#endif /* CONFIG_ARCH_OMAP16XX */ void innovator_init_irq(void) { @@ -108,11 +106,46 @@ void innovator_init_irq(void) #ifdef CONFIG_ARCH_OMAP1510 if (cpu_is_omap1510()) { omap_gpio_init(); - fpga_init_irq(); + omap1510_fpga_init_irq(); } #endif } +#ifdef CONFIG_ARCH_OMAP1510 +static struct omap_usb_config innovator1510_usb_config __initdata = { + /* for bundled non-standard host and peripheral cables */ + .hmc_mode = 4, + + .register_host = 1, + .pins[1] = 6, + .pins[2] = 6, /* Conflicts with UART2 */ + + .register_dev = 1, + .pins[0] = 2, +}; +#endif + +#ifdef CONFIG_ARCH_OMAP16XX +static struct omap_usb_config h2_usb_config __initdata = { + /* usb1 has a Mini-AB port and external isp1301 transceiver */ + .otg = 2, + +#ifdef CONFIG_USB_GADGET_OMAP + .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled + // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback) +#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */ + .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled +#endif + + .pins[1] = 3, +}; +#endif + +static struct omap_board_config_kernel innovator_config[] = { + { OMAP_TAG_USB, NULL }, +}; + static void __init innovator_init(void) { #ifdef CONFIG_ARCH_OMAP1510 @@ -120,11 +153,22 @@ static void __init innovator_init(void) platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); } #endif -#ifdef CONFIG_ARCH_OMAP1610 - if (cpu_is_omap1610()) { +#ifdef CONFIG_ARCH_OMAP16XX + if (!cpu_is_omap1510()) { platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices)); } #endif + +#ifdef CONFIG_ARCH_OMAP1510 + if (cpu_is_omap1510()) + innovator_config[0].data = &innovator1510_usb_config; +#endif +#ifdef CONFIG_ARCH_OMAP16XX + if (cpu_is_omap1610()) + innovator_config[0].data = &h2_usb_config; +#endif + omap_board_config = innovator_config; + omap_board_config_size = ARRAY_SIZE(innovator_config); } static void __init innovator_map_io(void) @@ -143,11 +187,7 @@ static void __init innovator_map_io(void) fpga_read(OMAP1510_FPGA_BOARD_REV)); } #endif -#ifdef CONFIG_ARCH_OMAP1610 - if (cpu_is_omap1610()) { - iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc)); - } -#endif + omap_serial_init(innovator_serial_ports); } MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") @@ -156,6 +196,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") BOOT_PARAMS(0x10000100) MAPIO(innovator_map_io) INITIRQ(innovator_init_irq) - INITTIME(omap_init_time) INIT_MACHINE(innovator_init) + .timer = &omap_timer, MACHINE_END diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c index 16ecd6be5..d7a20ca6e 100644 --- a/arch/arm/mach-omap/board-osk.c +++ b/arch/arm/mach-omap/board-osk.c @@ -38,15 +38,18 @@ #include #include #include +#include +#include #include "common.h" static struct map_desc osk5912_io_desc[] __initdata = { -{ OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE }, { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE, MT_DEVICE }, }; +static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; + static struct resource osk5912_smc91x_resources[] = { [0] = { .start = OMAP_OSK_ETHR_START, /* Physical */ @@ -76,16 +79,29 @@ void osk_init_irq(void) omap_init_irq(); } +static struct omap_usb_config osk_usb_config __initdata = { + /* has usb host and device, but no Mini-AB port */ + .register_host = 1, + .hmc_mode = 16, + .pins[0] = 2, +}; + +static struct omap_board_config_kernel osk_config[] = { + { OMAP_TAG_USB, &osk_usb_config }, +}; + static void __init osk_init(void) { platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); + omap_board_config = osk_config; + omap_board_config_size = ARRAY_SIZE(osk_config); } static void __init osk_map_io(void) { omap_map_io(); iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc)); - + omap_serial_init(osk_serial_ports); } MACHINE_START(OMAP_OSK, "TI-OSK") @@ -94,6 +110,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK") BOOT_PARAMS(0x10000100) MAPIO(osk_map_io) INITIRQ(osk_init_irq) - INITTIME(omap_init_time) INIT_MACHINE(osk_init) + .timer = &omap_timer, MACHINE_END diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c index 8015d10fc..17a936422 100644 --- a/arch/arm/mach-omap/board-perseus2.c +++ b/arch/arm/mach-omap/board-perseus2.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "common.h" @@ -33,17 +35,19 @@ void omap_perseus2_init_irq(void) static struct resource smc91x_resources[] = { [0] = { - .start = OMAP730_FPGA_ETHR_START, /* Physical */ - .end = OMAP730_FPGA_ETHR_START + SZ_4K, + .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ + .end = H2P2_DBG_FPGA_ETHR_START + SZ_4K, .flags = IORESOURCE_MEM, }, [1] = { - .start = 0, + .start = INT_730_MPU_EXT_NIRQ, .end = 0, - .flags = INT_ETHER, + .flags = IORESOURCE_IRQ, }, }; +static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0}; + static struct platform_device smc91x_device = { .name = "smc91x", .id = 0, @@ -62,7 +66,7 @@ static void __init omap_perseus2_init(void) /* Only FPGA needs to be mapped here. All others are done with ioremap */ static struct map_desc omap_perseus2_io_desc[] __initdata = { - {OMAP730_FPGA_BASE, OMAP730_FPGA_START, OMAP730_FPGA_SIZE, + {H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE, MT_DEVICE}, }; @@ -103,6 +107,7 @@ static void __init omap_perseus2_map_io(void) * It is used as the Ethernet controller interrupt */ omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); + omap_serial_init(p2_serial_ports); } MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") @@ -111,6 +116,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") BOOT_PARAMS(0x10000100) MAPIO(omap_perseus2_map_io) INITIRQ(omap_perseus2_init_irq) - INITTIME(omap_init_time) INIT_MACHINE(omap_perseus2_init) + .timer = &omap_timer, MACHINE_END diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c index 43aaa1c6c..91d9caa95 100644 --- a/arch/arm/mach-omap/common.c +++ b/arch/arm/mach-omap/common.c @@ -14,65 +14,195 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include -#include -#include +#include #include +#include + +#include +#include +#include +#include + + +#include "clock.h" + +#define DEBUG 1 + +struct omap_id { + u16 jtag_id; /* Used to determine OMAP type */ + u8 die_rev; /* Processor revision */ + u32 omap_id; /* OMAP revision */ + u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */ +}; + +/* Register values to detect the OMAP version */ +static struct omap_id omap_ids[] __initdata = { + { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100}, + { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300}, + { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000}, + { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000}, + { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000}, + { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00}, + { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00}, + { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, + { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00}, + { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000}, + { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00}, + { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00}, + { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300}, + { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300}, + { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300}, + { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000}, + { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000}, + { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000}, +}; /* - * ---------------------------------------------------------------------------- - * OMAP revision check - * - * Since we use the cpu_is_omapnnnn() macros, there's a chance that a board - * switches to an updated core. We want to print out the OMAP revision early. - * - * We use the system_serial registers for the revision information so we - * can see it in /proc/cpuinfo. - * - * If the OMAP detection gets more complicated, we may want to expand this - * to store the OMAP version and replace the current cpu_is_omapnnnn() macros. - * - * ---------------------------------------------------------------------------- + * Get OMAP type from PROD_ID. + * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM. + * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense. + * Undocumented register in TEST BLOCK is used as fallback; This seems to + * work on 1510, 1610 & 1710. The official way hopefully will work in future + * processors. + */ +static u16 __init omap_get_jtag_id(void) +{ + u32 prod_id, omap_id; + + prod_id = omap_readl(OMAP_PRODUCTION_ID_1); + omap_id = omap_readl(OMAP32_ID_1); + + /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */ + if (((prod_id >> 20) == 0) || (prod_id == omap_id)) + prod_id = 0; + else + prod_id &= 0xffff; + + if (prod_id) + return prod_id; + + /* Use OMAP32_ID_1 as fallback */ + prod_id = ((omap_id >> 12) & 0xffff); + + return prod_id; +} + +/* + * Get OMAP revision from DIE_REV. + * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID. + * Undocumented register in the TEST BLOCK is used as fallback. + * REVISIT: This does not seem to work on 1510 */ +static u8 __init omap_get_die_rev(void) +{ + u32 die_rev; + + die_rev = omap_readl(OMAP_DIE_ID_1); + + /* Check for broken OMAP_DIE_ID on early 1710 */ + if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id()) + die_rev = 0; + + die_rev = (die_rev >> 17) & 0xf; + if (die_rev) + return die_rev; + + die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf; + + return die_rev; +} + static void __init omap_check_revision(void) { - system_serial_high = omap_readl(OMAP_ID_BASE); - system_serial_low = OMAP_ID_REG; - system_rev = (OMAP_ID_REG >> ID_SHIFT) & ID_MASK; - - printk("OMAP revision: %d.%d (0x%08x) id: 0x%08x detected as OMAP-", - (system_serial_high >> 20) & 0xf, - (system_serial_high >> 16) & 0xf, - system_serial_high, system_serial_low); - - switch (system_rev) { - case OMAP_ID_730: - printk("730\n"); - system_rev = 0x730; - break; - case OMAP_ID_1510: - printk("1510\n"); - system_rev = 0x1510; + int i; + u16 jtag_id; + u8 die_rev; + u32 omap_id; + u8 cpu_type; + + jtag_id = omap_get_jtag_id(); + die_rev = omap_get_die_rev(); + omap_id = omap_readl(OMAP32_ID_0); + +#ifdef DEBUG + printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0)); + printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n", + omap_readl(OMAP_DIE_ID_1), + (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf); + printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0)); + printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n", + omap_readl(OMAP_PRODUCTION_ID_1), + omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff); + printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0)); + printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1)); + printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev); +#endif + + system_serial_high = omap_readl(OMAP_DIE_ID_0); + system_serial_low = omap_readl(OMAP_DIE_ID_1); + + /* First check only the major version in a safe way */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == (omap_ids[i].jtag_id)) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Check if we can find the die revision */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Finally check also the omap_id */ + for (i = 0; i < ARRAY_SIZE(omap_ids); i++) { + if (jtag_id == omap_ids[i].jtag_id + && die_rev == omap_ids[i].die_rev + && omap_id == omap_ids[i].omap_id) { + system_rev = omap_ids[i].type; + break; + } + } + + /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */ + cpu_type = system_rev >> 24; + + switch (cpu_type) { + case 0x07: + system_rev |= 0x07; break; - case OMAP_ID_1610: - printk("1610\n"); - system_rev = 0x1610; + case 0x15: + system_rev |= 0x15; break; - case OMAP_ID_1710: - printk("1710\n"); - system_rev = 0x1710; + case 0x16: + case 0x17: + system_rev |= 0x16; break; - case OMAP_ID_5912: - printk("5912/1611B\n"); - system_rev = 0x5912; + case 0x24: + system_rev |= 0x24; break; default: - printk("unknown, please add support!\n"); + printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type); } + + printk("OMAP%04x", system_rev >> 16); + if ((system_rev >> 8) & 0xff) + printk("%x", (system_rev >> 8) & 0xff); + printk(" revision %i handled as %02xxx id: %08x%08x\n", + die_rev, system_rev & 0xff, system_serial_low, + system_serial_high); } /* @@ -104,25 +234,23 @@ static struct map_desc omap1510_io_desc[] __initdata = { }; #endif -#ifdef CONFIG_ARCH_OMAP1610 +#if defined(CONFIG_ARCH_OMAP16XX) static struct map_desc omap1610_io_desc[] __initdata = { - { OMAP1610_DSP_BASE, OMAP1610_DSP_START, OMAP1610_DSP_SIZE, MT_DEVICE }, - { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE }, - { OMAP1610_SRAM_BASE, OMAP1610_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE } + { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, + { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, + { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE } }; -#endif -#ifdef CONFIG_ARCH_OMAP5912 static struct map_desc omap5912_io_desc[] __initdata = { - { OMAP5912_DSP_BASE, OMAP5912_DSP_START, OMAP5912_DSP_SIZE, MT_DEVICE }, - { OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE }, + { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, + { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, /* * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped. * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte * can be used. */ - { OMAP5912_SRAM_BASE, OMAP5912_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE } + { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE } }; #endif @@ -137,6 +265,9 @@ static void __init _omap_map_io(void) iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc)); omap_check_revision(); + /* clear BM to canonicalize CS0 (not CS3) at 0000:0000 */ + omap_writel(omap_readl(EMIFS_CONFIG) & 0x0d, EMIFS_CONFIG); + #ifdef CONFIG_ARCH_OMAP730 if (cpu_is_omap730()) { iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); @@ -147,12 +278,10 @@ static void __init _omap_map_io(void) iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); } #endif -#ifdef CONFIG_ARCH_OMAP1610 - if (cpu_is_omap1610()) { +#if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap1610() || cpu_is_omap1710()) { iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc)); } -#endif -#ifdef CONFIG_ARCH_OMAP5912 if (cpu_is_omap5912()) { iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc)); } @@ -166,7 +295,7 @@ static void __init _omap_map_io(void) /* Must init clocks early to assure that timer interrupt works */ - init_ck(); + clk_init(); } /* @@ -178,46 +307,223 @@ void omap_map_io(void) _omap_map_io(); } +static inline unsigned int omap_serial_in(struct plat_serial8250_port *up, + int offset) +{ + offset <<= up->regshift; + return (unsigned int)__raw_readb(up->membase + offset); +} + +static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset, + int value) +{ + offset <<= p->regshift; + __raw_writeb(value, p->membase + offset); +} + +/* + * Internal UARTs need to be initialized for the 8250 autoconfig to work + * properly. + */ +static void __init omap_serial_reset(struct plat_serial8250_port *p) +{ + omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */ + omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */ + + if (!cpu_is_omap1510()) { + omap_serial_outp(p, UART_OMAP_SYSC, 0x01); + while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01)); + } +} + +static struct plat_serial8250_port serial_platform_data[] = { + { + .membase = (char*)IO_ADDRESS(OMAP_UART1_BASE), + .mapbase = (unsigned long)OMAP_UART1_BASE, + .irq = INT_UART1, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, + { + .membase = (char*)IO_ADDRESS(OMAP_UART2_BASE), + .mapbase = (unsigned long)OMAP_UART2_BASE, + .irq = INT_UART2, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, + { + .membase = (char*)IO_ADDRESS(OMAP_UART3_BASE), + .mapbase = (unsigned long)OMAP_UART3_BASE, + .irq = INT_UART3, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +/* + * Note that on Innovator-1510 UART2 pins conflict with USB2. + * By default UART2 does not work on Innovator-1510 if you have + * USB OHCI enabled. To use UART2, you must disable USB2 first. + */ +void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS]) +{ + int i; + + if (cpu_is_omap730()) { + serial_platform_data[0].regshift = 0; + serial_platform_data[1].regshift = 0; + serial_platform_data[0].irq = INT_730_UART_MODEM_1; + serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2; + } + + if (cpu_is_omap1510()) { + serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16; + serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16; + serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16; + } + + for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { + unsigned char reg; + + if (ports[i] == 0) { + serial_platform_data[i].membase = 0; + serial_platform_data[i].mapbase = 0; + continue; + } + + switch (i) { + case 0: + if (cpu_is_omap1510()) { + omap_cfg_reg(UART1_TX); + omap_cfg_reg(UART1_RTS); + if (machine_is_omap_innovator()) { + reg = fpga_read(OMAP1510_FPGA_POWER); + reg |= OMAP1510_FPGA_PCR_COM1_EN; + fpga_write(reg, OMAP1510_FPGA_POWER); + udelay(10); + } + } + break; + case 1: + if (cpu_is_omap1510()) { + omap_cfg_reg(UART2_TX); + omap_cfg_reg(UART2_RTS); + if (machine_is_omap_innovator()) { + reg = fpga_read(OMAP1510_FPGA_POWER); + reg |= OMAP1510_FPGA_PCR_COM2_EN; + fpga_write(reg, OMAP1510_FPGA_POWER); + udelay(10); + } + } + break; + case 2: + if (cpu_is_omap1510()) { + omap_cfg_reg(UART3_TX); + omap_cfg_reg(UART3_RX); + } + break; + } + omap_serial_reset(&serial_platform_data[i]); + } +} + +static int __init omap_init(void) +{ + return platform_device_register(&serial_device); +} +arch_initcall(omap_init); + +#define NO_LENGTH_CHECK 0xffffffff + extern int omap_bootloader_tag_len; extern u8 omap_bootloader_tag[]; -const void *__omap_get_per_info(u16 tag, size_t len) +struct omap_board_config_kernel *omap_board_config; +int omap_board_config_size = 0; + +static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) { - struct omap_board_info_entry *info = NULL; + struct omap_board_config_kernel *kinfo = NULL; + int i; #ifdef CONFIG_OMAP_BOOT_TAG + struct omap_board_config_entry *info = NULL; + if (omap_bootloader_tag_len > 4) - info = (struct omap_board_info_entry *) omap_bootloader_tag; + info = (struct omap_board_config_entry *) omap_bootloader_tag; while (info != NULL) { u8 *next; - if (info->tag == tag) - break; + if (info->tag == tag) { + if (skip == 0) + break; + skip--; + } next = (u8 *) info + sizeof(*info) + info->len; if (next >= omap_bootloader_tag + omap_bootloader_tag_len) info = NULL; else - info = (struct omap_board_info_entry *) next; + info = (struct omap_board_config_entry *) next; + } + if (info != NULL) { + /* Check the length as a lame attempt to check for + * binary inconsistancy. */ + if (len != NO_LENGTH_CHECK && info->len != len) { + printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n", + tag, len, info->len); + return NULL; + } + if (len_out != NULL) + *len_out = info->len; + return info->data; } #endif - if (info == NULL) - return NULL; - if (info->len != len) { - printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n", - tag, len, info->len); - return NULL; + /* Try to find the config from the board-specific structures + * in the kernel. */ + for (i = 0; i < omap_board_config_size; i++) { + if (omap_board_config[i].tag == tag) { + kinfo = &omap_board_config[i]; + break; + } } + if (kinfo == NULL) + return NULL; + return kinfo->data; +} - return info->data; +const void *__omap_get_config(u16 tag, size_t len, int nr) +{ + return get_config(tag, len, nr, NULL); +} +EXPORT_SYMBOL(__omap_get_config); + +const void *omap_get_var_config(u16 tag, size_t *len) +{ + return get_config(tag, NO_LENGTH_CHECK, 0, len); } -EXPORT_SYMBOL(__omap_get_per_info); +EXPORT_SYMBOL(omap_get_var_config); static int __init omap_add_serial_console(void) { - const struct omap_uart_info *info; + const struct omap_uart_config *info; - info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info); + info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); if (info != NULL && info->console_uart) { static char speed[11], *opt = NULL; diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h index 96dcb3c53..9f62858c0 100644 --- a/arch/arm/mach-omap/common.h +++ b/arch/arm/mach-omap/common.h @@ -27,9 +27,10 @@ #ifndef __ARCH_ARM_MACH_OMAP_COMMON_H #define __ARCH_ARM_MACH_OMAP_COMMON_H +struct sys_timer; + extern void omap_map_io(void); -extern void omap_init_time(void); +extern struct sys_timer omap_timer; +extern void omap_serial_init(int ports[]); #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ - - diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c index 385b4d1cc..4c3d7c27d 100644 --- a/arch/arm/mach-omap/dma.c +++ b/arch/arm/mach-omap/dma.c @@ -4,6 +4,8 @@ * Copyright (C) 2003 Nokia Corporation * Author: Juha Yrjölä * DMA channel linking for 1610 by Samuel Ortiz + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak * * Support functions for the OMAP internal DMA channels. * @@ -26,6 +28,8 @@ #include #include +#include + #define OMAP_DMA_ACTIVE 0x01 #define OMAP_DMA_CCR_EN (1 << 7) @@ -87,6 +91,34 @@ static void clear_lch_regs(int lch) omap_writew(0, lch_base + i); } +void omap_set_dma_priority(int dst_port, int priority) +{ + unsigned long reg; + u32 l; + + switch (dst_port) { + case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ + reg = OMAP_TC_OCPT1_PRIOR; + break; + case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */ + reg = OMAP_TC_OCPT2_PRIOR; + break; + case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */ + reg = OMAP_TC_EMIFF_PRIOR; + break; + case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */ + reg = OMAP_TC_EMIFS_PRIOR; + break; + default: + BUG(); + return; + } + l = omap_readl(reg); + l &= ~(0xf << 8); + l |= (priority & 0xf) << 8; + omap_writel(l, reg); +} + void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, int frame_count, int sync_mode) { @@ -113,51 +145,38 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, omap_writew(frame_count, OMAP_DMA_CFN(lch)); } -void omap_set_dma_constant_fill(int lch, u32 color) +void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) { u16 w; -#ifdef CONFIG_DEBUG_KERNEL - if (omap_dma_in_1510_mode) { - printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode."); - BUG(); - return; - } -#endif - w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03; - w |= 0x01; - omap_writew(w, OMAP_DMA_CCR2(lch)); + BUG_ON(omap_dma_in_1510_mode()); - omap_writew((u16)color, OMAP_DMA_COLOR_L(lch)); - omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch)); - - w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f; - w |= 1; /* Channel type G */ - omap_writew(w, OMAP_DMA_LCH_CTRL(lch)); -} - -void omap_set_dma_transparent_copy(int lch, u32 color) -{ - u16 w; - -#ifdef CONFIG_DEBUG_KERNEL - if (omap_dma_in_1510_mode) { - printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode."); + w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03; + switch (mode) { + case OMAP_DMA_CONSTANT_FILL: + w |= 0x01; + break; + case OMAP_DMA_TRANSPARENT_COPY: + w |= 0x02; + break; + case OMAP_DMA_COLOR_DIS: + break; + default: BUG(); } -#endif - w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03; - w |= 0x02; omap_writew(w, OMAP_DMA_CCR2(lch)); - omap_writew((u16)color, OMAP_DMA_COLOR_L(lch)); - omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch)); - w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f; - w |= 1; /* Channel type G */ + /* Default is channel type 2D */ + if (mode) { + omap_writew((u16)color, OMAP_DMA_COLOR_L(lch)); + omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch)); + w |= 1; /* Channel type G */ + } omap_writew(w, OMAP_DMA_LCH_CTRL(lch)); } + void omap_set_dma_src_params(int lch, int src_port, int src_amode, unsigned long src_start) { @@ -192,22 +211,24 @@ void omap_set_dma_src_data_pack(int lch, int enable) omap_writew(w, OMAP_DMA_CSDP(lch)); } -void omap_set_dma_src_burst_mode(int lch, int burst_mode) +void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { u16 w; w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7); switch (burst_mode) { + case OMAP_DMA_DATA_BURST_DIS: + break; case OMAP_DMA_DATA_BURST_4: w |= (0x01 << 7); break; case OMAP_DMA_DATA_BURST_8: - w |= (0x03 << 7); - break; + /* not supported by current hardware + * w |= (0x03 << 7); + * fall through + */ default: - printk(KERN_ERR "Invalid DMA burst mode\n"); BUG(); - return; } omap_writew(w, OMAP_DMA_CSDP(lch)); } @@ -246,12 +267,14 @@ void omap_set_dma_dest_data_pack(int lch, int enable) omap_writew(w, OMAP_DMA_CSDP(lch)); } -void omap_set_dma_dest_burst_mode(int lch, int burst_mode) +void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { u16 w; w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14); switch (burst_mode) { + case OMAP_DMA_DATA_BURST_DIS: + break; case OMAP_DMA_DATA_BURST_4: w |= (0x01 << 14); break; @@ -266,46 +289,78 @@ void omap_set_dma_dest_burst_mode(int lch, int burst_mode) omap_writew(w, OMAP_DMA_CSDP(lch)); } -void omap_start_dma(int lch) +static inline void init_intr(int lch) { u16 w; - if (!omap_dma_in_1510_mode()) { - int next_lch; - - next_lch = dma_chan[lch].next_lch; - - /* Enable the queue, if needed so. */ - if (next_lch != -1) { - /* Clear the STOP_LNK bits */ - w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); - w &= ~(1 << 14); - omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); - w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch)); - w &= ~(1 << 14); - omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch)); - - /* And set the ENABLE_LNK bits */ - omap_writew(next_lch | (1 << 15), - OMAP_DMA_CLNK_CTRL(lch)); - /* The loop case */ - if (dma_chan[next_lch].next_lch == lch) - omap_writew(lch | (1 << 15), - OMAP_DMA_CLNK_CTRL(next_lch)); - - /* Read CSR to make sure it's cleared. */ - w = omap_readw(OMAP_DMA_CSR(next_lch)); - /* Enable some nice interrupts. */ - omap_writew(dma_chan[next_lch].enabled_irqs, - OMAP_DMA_CICR(next_lch)); - dma_chan[next_lch].flags |= OMAP_DMA_ACTIVE; - } - } - /* Read CSR to make sure it's cleared. */ w = omap_readw(OMAP_DMA_CSR(lch)); /* Enable some nice interrupts. */ omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch)); + dma_chan[lch].flags |= OMAP_DMA_ACTIVE; +} + +static inline void enable_lnk(int lch) +{ + u16 w; + + /* Clear the STOP_LNK bits */ + w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); + w &= ~(1 << 14); + omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); + + /* And set the ENABLE_LNK bits */ + if (dma_chan[lch].next_lch != -1) + omap_writew(dma_chan[lch].next_lch | (1 << 15), + OMAP_DMA_CLNK_CTRL(lch)); +} + +static inline void disable_lnk(int lch) +{ + u16 w; + + /* Disable interrupts */ + omap_writew(0, OMAP_DMA_CICR(lch)); + + /* Set the STOP_LNK bit */ + w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); + w |= (1 << 14); + w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); + + dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; +} + +void omap_start_dma(int lch) +{ + u16 w; + + if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { + int next_lch, cur_lch; + char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; + + dma_chan_link_map[lch] = 1; + /* Set the link register of the first channel */ + enable_lnk(lch); + + memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); + cur_lch = dma_chan[lch].next_lch; + do { + next_lch = dma_chan[cur_lch].next_lch; + + /* The loop case: we've been here already */ + if (dma_chan_link_map[cur_lch]) + break; + /* Mark the current channel */ + dma_chan_link_map[cur_lch] = 1; + + enable_lnk(cur_lch); + init_intr(cur_lch); + + cur_lch = next_lch; + } while (next_lch != -1); + } + + init_intr(lch); w = omap_readw(OMAP_DMA_CCR(lch)); w |= OMAP_DMA_CCR_EN; @@ -316,37 +371,34 @@ void omap_start_dma(int lch) void omap_stop_dma(int lch) { u16 w; - int next_lch; - /* Disable all interrupts on the channel */ - omap_writew(0, OMAP_DMA_CICR(lch)); + if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { + int next_lch, cur_lch = lch; + char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT]; - if (omap_dma_in_1510_mode()) { - w = omap_readw(OMAP_DMA_CCR(lch)); - w &= ~OMAP_DMA_CCR_EN; - omap_writew(w, OMAP_DMA_CCR(lch)); - dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; - return; - } + memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); + do { + /* The loop case: we've been here already */ + if (dma_chan_link_map[cur_lch]) + break; + /* Mark the current channel */ + dma_chan_link_map[cur_lch] = 1; - next_lch = dma_chan[lch].next_lch; + disable_lnk(cur_lch); - /* - * According to thw HW spec, enabling the STOP_LNK bit - * resets the CCR_EN bit at the same time. - */ - w = omap_readw(OMAP_DMA_CLNK_CTRL(lch)); - w |= (1 << 14); - w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch)); - dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; + next_lch = dma_chan[cur_lch].next_lch; + cur_lch = next_lch; + } while (next_lch != -1); - if (next_lch != -1) { - omap_writew(0, OMAP_DMA_CICR(next_lch)); - w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch)); - w |= (1 << 14); - w = omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch)); - dma_chan[next_lch].flags &= ~OMAP_DMA_ACTIVE; + return; } + /* Disable all interrupts on the channel */ + omap_writew(0, OMAP_DMA_CICR(lch)); + + w = omap_readw(OMAP_DMA_CCR(lch)); + w &= ~OMAP_DMA_CCR_EN; + omap_writew(w, OMAP_DMA_CCR(lch)); + dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } void omap_enable_dma_irq(int lch, u16 bits) @@ -445,7 +497,7 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->data = data; chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; - if (cpu_is_omap1610() || cpu_is_omap5912()) { + if (cpu_is_omap16xx() || cpu_is_omap730()) { /* If the sync device is set, configure it dynamically. */ if (dev_id != 0) { set_gdma_dev(free_ch + 1, dev_id); @@ -533,7 +585,6 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue) } dma_chan[lch_head].next_lch = -1; - dma_chan[lch_queue].next_lch = -1; } @@ -543,8 +594,15 @@ static struct lcd_dma_info { void (* callback)(u16 status, void *data); void *cb_data; + int active; unsigned long addr, size; int rotate, data_type, xres, yres; + int vxres; + int mirror; + int xscale, yscale; + int ext_ctrl; + int src_port; + int single_transfer; } lcd_dma; void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, @@ -556,14 +614,70 @@ void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, lcd_dma.yres = fb_yres; } +void omap_set_lcd_dma_src_port(int port) +{ + lcd_dma.src_port = port; +} + +void omap_set_lcd_dma_ext_controller(int external) +{ + lcd_dma.ext_ctrl = external; +} + +void omap_set_lcd_dma_single_transfer(int single) +{ + lcd_dma.single_transfer = single; +} + + +void omap_set_lcd_dma_b1_rotation(int rotate) +{ + if (omap_dma_in_1510_mode()) { + printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); + BUG(); + return; + } + lcd_dma.rotate = rotate; +} + +void omap_set_lcd_dma_b1_mirror(int mirror) +{ + if (omap_dma_in_1510_mode()) { + printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.mirror = mirror; +} + +void omap_set_lcd_dma_b1_vxres(unsigned long vxres) +{ + if (omap_dma_in_1510_mode()) { + printk(KERN_ERR "DMA virtual resulotion is not supported " + "in 1510 mode\n"); + BUG(); + } + lcd_dma.vxres = vxres; +} + +void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) +{ + if (omap_dma_in_1510_mode()) { + printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.xscale = xscale; + lcd_dma.yscale = yscale; +} + static void set_b1_regs(void) { unsigned long top, bottom; int es; - u16 w, en, fn; - s16 ei; - s32 fi; - u32 l; + u16 w; + unsigned long en, fn; + long ei, fi; + unsigned long vxres; + unsigned int xscale, yscale; switch (lcd_dma.data_type) { case OMAP_DMA_DATA_TYPE_S8: @@ -580,25 +694,81 @@ static void set_b1_regs(void) return; } - if (lcd_dma.rotate == 0) { - top = lcd_dma.addr; - bottom = lcd_dma.addr + (lcd_dma.xres * lcd_dma.yres - 1) * es; - /* 1510 DMA requires the bottom address to be 2 more than the - * actual last memory access location. */ - if (omap_dma_in_1510_mode() && - lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) - bottom += 2; + vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; + xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; + yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; + BUG_ON(vxres < lcd_dma.xres); +#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es) +#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) + switch (lcd_dma.rotate) { + case 0: + if (!lcd_dma.mirror) { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + /* 1510 DMA requires the bottom address to be 2 more + * than the actual last memory access location. */ + if (omap_dma_in_1510_mode() && + lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) + bottom += 2; + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); + } en = lcd_dma.xres; fn = lcd_dma.yres; - ei = 0; - fi = 0; - } else { - top = lcd_dma.addr + (lcd_dma.xres - 1) * es; - bottom = lcd_dma.addr + (lcd_dma.yres - 1) * lcd_dma.xres * es; + break; + case 90: + if (!lcd_dma.mirror) { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); + } en = lcd_dma.yres; fn = lcd_dma.xres; - ei = (lcd_dma.xres - 1) * es + 1; - fi = -(lcd_dma.xres * (lcd_dma.yres - 1) + 2) * 2 + 1; + break; + case 180: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); + } else { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); + } + en = lcd_dma.xres; + fn = lcd_dma.yres; + break; + case 270: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); + } else { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); + } + en = lcd_dma.yres; + fn = lcd_dma.xres; + break; + default: + BUG(); + return; /* Supress warning about uninitialized vars */ } if (omap_dma_in_1510_mode()) { @@ -624,33 +794,50 @@ static void set_b1_regs(void) w |= lcd_dma.data_type; omap_writew(w, OMAP1610_DMA_LCD_CSDP); - if (!lcd_dma.rotate) + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + /* Always set the source port as SDRAM for now*/ + w &= ~(0x03 << 6); + if (lcd_dma.ext_ctrl) + w |= 1 << 8; + else + w &= ~(1 << 8); + if (lcd_dma.callback != NULL) + w |= 1 << 1; /* Block interrupt enable */ + else + w &= ~(1 << 1); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + + if (!(lcd_dma.rotate || lcd_dma.mirror || + lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) return; - /* Rotation stuff */ - l = omap_readw(OMAP1610_DMA_LCD_CSDP); - /* Disable burst access */ - l &= ~(0x03 << 7); - omap_writew(l, OMAP1610_DMA_LCD_CSDP); - - l = omap_readw(OMAP1610_DMA_LCD_CCR); + w = omap_readw(OMAP1610_DMA_LCD_CCR); /* Set the double-indexed addressing mode */ - l |= (0x03 << 12); - omap_writew(l, OMAP1610_DMA_LCD_CCR); + w |= (0x03 << 12); + omap_writew(w, OMAP1610_DMA_LCD_CCR); omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); } -void omap_set_lcd_dma_b1_rotation(int rotate) +static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { - if (omap_dma_in_1510_mode()) { - printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); - BUG(); - return; + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + if (unlikely(!(w & (1 << 3)))) { + printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); + return IRQ_NONE; } - lcd_dma.rotate = rotate; + /* Ack the IRQ */ + w |= (1 << 3); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + lcd_dma.active = 0; + if (lcd_dma.callback != NULL) + lcd_dma.callback(w, lcd_dma.cb_data); + + return IRQ_HANDLED; } int omap_request_lcd_dma(void (* callback)(u16 status, void *data), @@ -667,6 +854,15 @@ int omap_request_lcd_dma(void (* callback)(u16 status, void *data), spin_unlock_irq(&lcd_dma.lock); lcd_dma.callback = callback; lcd_dma.cb_data = data; + lcd_dma.active = 0; + lcd_dma.single_transfer = 0; + lcd_dma.rotate = 0; + lcd_dma.vxres = 0; + lcd_dma.mirror = 0; + lcd_dma.xscale = 0; + lcd_dma.yscale = 0; + lcd_dma.ext_ctrl = 0; + lcd_dma.src_port = 0; return 0; } @@ -686,23 +882,53 @@ void omap_free_lcd_dma(void) spin_unlock(&lcd_dma.lock); } -void omap_start_lcd_dma(void) +void omap_enable_lcd_dma(void) +{ + u16 w; + + /* Set the Enable bit only if an external controller is + * connected. Otherwise the OMAP internal controller will + * start the transfer when it gets enabled. + */ + if (enable_1510_mode || !lcd_dma.ext_ctrl) + return; + w = omap_readw(OMAP1610_DMA_LCD_CCR); + w |= 1 << 7; + omap_writew(w, OMAP1610_DMA_LCD_CCR); + lcd_dma.active = 1; +} + +void omap_setup_lcd_dma(void) { + BUG_ON(lcd_dma.active); if (!enable_1510_mode) { /* Set some reasonable defaults */ + omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); - omap_writew(0x5740, OMAP1610_DMA_LCD_CCR); } set_b1_regs(); - if (!enable_1510_mode) - omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) | 1, OMAP1610_DMA_LCD_CCR); + if (!enable_1510_mode) { + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + /* If DMA was already active set the end_prog bit to have + * the programmed register set loaded into the active + * register set. + */ + w |= 1 << 11; /* End_prog */ + if (!lcd_dma.single_transfer) + w |= (3 << 8); /* Auto_init, repeat */ + omap_writew(w, OMAP1610_DMA_LCD_CCR); + } } void omap_stop_lcd_dma(void) { - if (!enable_1510_mode) - omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR); + lcd_dma.active = 0; + if (!enable_1510_mode && lcd_dma.ext_ctrl) + omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~(1 << 7), + OMAP1610_DMA_LCD_CCR); } static int __init omap_init_dma(void) @@ -713,7 +939,7 @@ static int __init omap_init_dma(void) printk(KERN_INFO "DMA support for OMAP1510 initialized\n"); dma_chan_count = 9; enable_1510_mode = 1; - } else if (cpu_is_omap1610() || cpu_is_omap5912()) { + } else if (cpu_is_omap16xx() || cpu_is_omap730()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", omap_readw(OMAP_DMA_HW_ID)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", @@ -728,7 +954,7 @@ static int __init omap_init_dma(void) w = omap_readw(OMAP_DMA_GSCR); w |= 1 << 3; omap_writew(w, OMAP_DMA_GSCR); - dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT; + dma_chan_count = 16; } else dma_chan_count = 9; } else { @@ -762,19 +988,30 @@ static int __init omap_init_dma(void) return r; } } - + r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL); + if (r != 0) { + int i; + + printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r); + for (i = 0; i < dma_chan_count; i++) + free_irq(dma_irq[i], (void *) (i + 1)); + return r; + } return 0; } arch_initcall(omap_init_dma); + +EXPORT_SYMBOL(omap_set_dma_priority); EXPORT_SYMBOL(omap_request_dma); EXPORT_SYMBOL(omap_free_dma); EXPORT_SYMBOL(omap_start_dma); EXPORT_SYMBOL(omap_stop_dma); +EXPORT_SYMBOL(omap_enable_dma_irq); +EXPORT_SYMBOL(omap_disable_dma_irq); EXPORT_SYMBOL(omap_set_dma_transfer_params); -EXPORT_SYMBOL(omap_set_dma_constant_fill); -EXPORT_SYMBOL(omap_set_dma_transparent_copy); +EXPORT_SYMBOL(omap_set_dma_color_mode); EXPORT_SYMBOL(omap_set_dma_src_params); EXPORT_SYMBOL(omap_set_dma_src_index); @@ -791,7 +1028,14 @@ EXPORT_SYMBOL(omap_dma_unlink_lch); EXPORT_SYMBOL(omap_request_lcd_dma); EXPORT_SYMBOL(omap_free_lcd_dma); -EXPORT_SYMBOL(omap_start_lcd_dma); +EXPORT_SYMBOL(omap_enable_lcd_dma); +EXPORT_SYMBOL(omap_setup_lcd_dma); EXPORT_SYMBOL(omap_stop_lcd_dma); EXPORT_SYMBOL(omap_set_lcd_dma_b1); +EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); +EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); +EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); +EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); +EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); + diff --git a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c index d9246b1dc..f0ce5c12a 100644 --- a/arch/arm/mach-omap/fpga.c +++ b/arch/arm/mach-omap/fpga.c @@ -31,19 +31,9 @@ #include #include -unsigned char fpga_read(int reg) -{ - return __raw_readb(reg); -} - -void fpga_write(unsigned char val, int reg) -{ - __raw_writeb(val, reg); -} - static void fpga_mask_irq(unsigned int irq) { - irq -= IH_FPGA_BASE; + irq -= OMAP1510_IH_FPGA_BASE; if (irq < 8) __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) @@ -76,7 +66,7 @@ static void fpga_ack_irq(unsigned int irq) static void fpga_unmask_irq(unsigned int irq) { - irq -= IH_FPGA_BASE; + irq -= OMAP1510_IH_FPGA_BASE; if (irq < 8) __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)), @@ -114,8 +104,8 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc, break; } - for (fpga_irq = IH_FPGA_BASE; - (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; + for (fpga_irq = OMAP1510_IH_FPGA_BASE; + (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { d = irq_desc + fpga_irq; @@ -162,7 +152,7 @@ static struct irqchip omap_fpga_irq = { * interrupts at the interrupt controller via disable_irq/enable_irq * could pose a problem. */ -void fpga_init_irq(void) +void omap1510_fpga_init_irq(void) { int i; @@ -170,9 +160,9 @@ void fpga_init_irq(void) __raw_writeb(0, OMAP1510_FPGA_IMR_HI); __raw_writeb(0, INNOVATOR_FPGA_IMR2); - for (i = IH_FPGA_BASE; i < (IH_FPGA_BASE + NR_FPGA_IRQS); i++) { + for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) { - if (i == INT_FPGA_TS) { + if (i == OMAP1510_INT_FPGA_TS) { /* * The touchscreen interrupt is level-sensitive, so * we'll use the regular mask_ack routine for it. @@ -201,9 +191,7 @@ void fpga_init_irq(void) omap_request_gpio(13); omap_set_gpio_direction(13, 1); omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE); - set_irq_chained_handler(INT_FPGA, innovator_fpga_IRQ_demux); + set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux); } -EXPORT_SYMBOL(fpga_init_irq); -EXPORT_SYMBOL(fpga_read); -EXPORT_SYMBOL(fpga_write); +EXPORT_SYMBOL(omap1510_fpga_init_irq); diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c index 2f052a959..e66dcf6ff 100644 --- a/arch/arm/mach-omap/gpio.c +++ b/arch/arm/mach-omap/gpio.c @@ -94,7 +94,7 @@ struct gpio_bank { #define METHOD_GPIO_1610 2 #define METHOD_GPIO_730 3 -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) +#if defined(CONFIG_ARCH_OMAP16XX) static struct gpio_bank gpio_bank_1610[5] = { { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO}, { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 }, @@ -113,7 +113,7 @@ static struct gpio_bank gpio_bank_1510[2] = { #ifdef CONFIG_ARCH_OMAP730 static struct gpio_bank gpio_bank_730[7] = { - { OMAP_MPUIO_BASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, + { OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, { OMAP730_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 }, { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 }, @@ -135,8 +135,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) return &gpio_bank[1]; } #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) - if (cpu_is_omap1610() || cpu_is_omap5912()) { +#if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap16xx()) { if (OMAP_GPIO_IS_MPUIO(gpio)) return &gpio_bank[0]; return &gpio_bank[1 + (gpio >> 4)]; @@ -172,8 +172,8 @@ static inline int gpio_valid(int gpio) if (cpu_is_omap1510() && gpio < 16) return 0; #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) - if ((cpu_is_omap1610() || cpu_is_omap5912()) && gpio < 64) +#if defined(CONFIG_ARCH_OMAP16XX) + if ((cpu_is_omap16xx()) && gpio < 64) return 0; #endif #ifdef CONFIG_ARCH_OMAP730 @@ -554,7 +554,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, if (bank->method == METHOD_GPIO_1510) isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS; #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) +#if defined(CONFIG_ARCH_OMAP16XX) if (bank->method == METHOD_GPIO_1610) isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1; #endif @@ -588,7 +588,7 @@ static void gpio_ack_irq(unsigned int irq) if (bank->method == METHOD_GPIO_1510) __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS); #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) +#if defined(CONFIG_ARCH_OMAP16XX) if (bank->method == METHOD_GPIO_1610) __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1); #endif @@ -629,7 +629,7 @@ static void mpuio_mask_irq(unsigned int irq) unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); struct gpio_bank *bank = get_gpio_bank(gpio); - _set_gpio_irqenable(bank, gpio, 0); + _set_gpio_irqenable(bank, get_gpio_index(gpio), 0); } static void mpuio_unmask_irq(unsigned int irq) @@ -637,7 +637,7 @@ static void mpuio_unmask_irq(unsigned int irq) unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE); struct gpio_bank *bank = get_gpio_bank(gpio); - _set_gpio_irqenable(bank, gpio, 1); + _set_gpio_irqenable(bank, get_gpio_index(gpio), 1); } static struct irqchip gpio_irq_chip = { @@ -668,8 +668,8 @@ static int __init _omap_gpio_init(void) gpio_bank = gpio_bank_1510; } #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) - if (cpu_is_omap1610() || cpu_is_omap5912()) { +#if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap16xx()) { int rev; gpio_bank_count = 5; @@ -702,7 +702,7 @@ static int __init _omap_gpio_init(void) __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); } #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) +#if defined(CONFIG_ARCH_OMAP16XX) if (bank->method == METHOD_GPIO_1610) { __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1); __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); @@ -722,7 +722,7 @@ static int __init _omap_gpio_init(void) set_irq_chip(j, &mpuio_irq_chip); else set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, do_level_IRQ); + set_irq_handler(j, do_edge_IRQ); set_irq_flags(j, IRQF_VALID); } set_irq_chained_handler(bank->irq, gpio_irq_handler); @@ -731,7 +731,7 @@ static int __init _omap_gpio_init(void) /* Enable system clock for GPIO module. * The CAM_CLK_CTRL *is* really the right place. */ - if (cpu_is_omap1610()) + if (cpu_is_omap1610() || cpu_is_omap1710()) omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL); return 0; diff --git a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c index 18da117f6..f01c99266 100644 --- a/arch/arm/mach-omap/irq.c +++ b/arch/arm/mach-omap/irq.c @@ -140,10 +140,11 @@ static struct omap_irq_bank omap1510_irq_banks[] = { }; #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) +#if defined(CONFIG_ARCH_OMAP16XX) + static struct omap_irq_bank omap1610_irq_banks[] = { { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f }, - { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfffff7ff }, + { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd }, { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xfffff7ff }, { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff }, }; @@ -171,8 +172,8 @@ void __init omap_init_irq(void) irq_bank_count = ARRAY_SIZE(omap1510_irq_banks); } #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) - if (cpu_is_omap1610() || cpu_is_omap5912()) { +#if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap16xx()) { irq_banks = omap1610_irq_banks; irq_bank_count = ARRAY_SIZE(omap1610_irq_banks); } @@ -190,6 +191,11 @@ void __init omap_init_irq(void) irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET); irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET); + /* Enable interrupts in global mask */ + if (cpu_is_omap730()) { + irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET); + } + /* Install the interrupt handlers for each bank */ for (i = 0; i < irq_bank_count; i++) { for (j = i * 32; j < (i + 1) * 32; j++) { @@ -205,5 +211,9 @@ void __init omap_init_irq(void) } /* Unmask level 2 handler */ - omap_unmask_irq(INT_IH2_IRQ); + if (cpu_is_omap730()) { + omap_unmask_irq(INT_730_IH2_IRQ); + } else { + omap_unmask_irq(INT_IH2_IRQ); + } } diff --git a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c index e3f378b4a..b6d0c7203 100644 --- a/arch/arm/mach-omap/leds.c +++ b/arch/arm/mach-omap/leds.c @@ -3,6 +3,7 @@ * * OMAP LEDs dispatcher */ +#include #include #include @@ -11,17 +12,17 @@ #include "leds.h" static int __init -omap1510_leds_init(void) +omap_leds_init(void) { if (machine_is_omap_innovator()) leds_event = innovator_leds_event; - else if (machine_is_omap_perseus2()) { - leds_event = perseus2_leds_event; + else if (machine_is_omap_h2() || machine_is_omap_perseus2()) { + leds_event = h2p2_dbg_leds_event; } leds_event(led_start); return 0; } -__initcall(omap1510_leds_init); +__initcall(omap_leds_init); diff --git a/arch/arm/mach-omap/leds.h b/arch/arm/mach-omap/leds.h index ba2eb59d1..7571e2d63 100644 --- a/arch/arm/mach-omap/leds.h +++ b/arch/arm/mach-omap/leds.h @@ -1,2 +1,2 @@ extern void innovator_leds_event(led_event_t evt); -extern void perseus2_leds_event(led_event_t evt); +extern void h2p2_dbg_leds_event(led_event_t evt); diff --git a/arch/arm/mach-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c index d334395f1..7c4ad7713 100644 --- a/arch/arm/mach-omap/mcbsp.c +++ b/arch/arm/mach-omap/mcbsp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,8 @@ #include #include +#include + #ifdef CONFIG_MCBSP_DEBUG #define DBG(x...) printk(x) #else @@ -61,6 +64,8 @@ struct omap_mcbsp { }; static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; +static struct clk *mcbsp_dsp_ck = 0; +static struct clk *mcbsp_api_ck = 0; static void omap_mcbsp_dump_reg(u8 id) @@ -153,8 +158,8 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1); OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2); OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1); - OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2); - OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1); + OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2); + OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); } @@ -181,6 +186,7 @@ static int omap_mcbsp_check(unsigned int id) return -1; } +#define EN_XORPCK 1 #define DSP_RSTCT2 0xe1008014 static void omap_mcbsp_dsp_request(void) @@ -188,10 +194,8 @@ static void omap_mcbsp_dsp_request(void) if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) { omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)), ARM_RSTCT1); - omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK), - ARM_CKCTL); - omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)), - ARM_IDLECT2); + clk_enable(mcbsp_dsp_ck); + clk_enable(mcbsp_api_ck); /* enable 12MHz clock to mcbsp 1 & 3 */ __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK), @@ -588,7 +592,7 @@ static const struct omap_mcbsp_info mcbsp_1510[] = { }; #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) +#if defined(CONFIG_ARCH_OMAP16XX) static const struct omap_mcbsp_info mcbsp_1610[] = { [0] = { .virt_base = OMAP1610_MCBSP1_BASE, .dma_rx_sync = OMAP_DMA_MCBSP1_RX, @@ -614,6 +618,18 @@ static int __init omap_mcbsp_init(void) static const struct omap_mcbsp_info *mcbsp_info; printk("Initializing OMAP McBSP system\n"); + + mcbsp_dsp_ck = clk_get(0, "dsp_ck"); + if (IS_ERR(mcbsp_dsp_ck)) { + printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); + return PTR_ERR(mcbsp_dsp_ck); + } + mcbsp_api_ck = clk_get(0, "api_ck"); + if (IS_ERR(mcbsp_dsp_ck)) { + printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n"); + return PTR_ERR(mcbsp_api_ck); + } + #ifdef CONFIG_ARCH_OMAP730 if (cpu_is_omap730()) { mcbsp_info = mcbsp_730; @@ -626,7 +642,7 @@ static int __init omap_mcbsp_init(void) mcbsp_count = ARRAY_SIZE(mcbsp_1510); } #endif -#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) +#if defined(CONFIG_ARCH_OMAP16XX) if (cpu_is_omap1610() || cpu_is_omap1710()) { mcbsp_info = mcbsp_1610; mcbsp_count = ARRAY_SIZE(mcbsp_1610); diff --git a/arch/arm/mach-omap/mux.c b/arch/arm/mach-omap/mux.c index 70665dfaf..e3771397b 100644 --- a/arch/arm/mach-omap/mux.c +++ b/arch/arm/mach-omap/mux.c @@ -32,18 +32,26 @@ #define __MUX_C__ #include +#ifdef CONFIG_OMAP_MUX + /* * Sets the Omap MUX and PULL_DWN registers based on the table */ -int omap_cfg_reg(const reg_cfg_t reg_cfg) +int __init_or_module +omap_cfg_reg(const reg_cfg_t reg_cfg) { -#ifdef CONFIG_OMAP_MUX static spinlock_t mux_spin_lock = SPIN_LOCK_UNLOCKED; unsigned long flags; reg_cfg_set *cfg; unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0, pull_orig = 0, pull = 0; + unsigned int mask, warn = 0; + + if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) { + printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg); + return -EINVAL; + } cfg = ®_cfg_table[reg_cfg]; @@ -56,12 +64,20 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg) /* Check the mux register in question */ if (cfg->mux_reg) { + unsigned tmp1, tmp2; + reg_orig = omap_readl(cfg->mux_reg); /* The mux registers always seem to be 3 bits long */ - reg = reg_orig & ~(0x7 << cfg->mask_offset); + mask = (0x7 << cfg->mask_offset); + tmp1 = reg_orig & mask; + reg = reg_orig & ~mask; + + tmp2 = (cfg->mask << cfg->mask_offset); + reg |= tmp2; - reg |= (cfg->mask << cfg->mask_offset); + if (tmp1 != tmp2) + warn = 1; omap_writel(reg, cfg->mux_reg); } @@ -70,12 +86,18 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg) if (!cpu_is_omap1510()) { if (cfg->pu_pd_reg && cfg->pull_val) { pu_pd_orig = omap_readl(cfg->pu_pd_reg); + mask = 1 << cfg->pull_bit; + if (cfg->pu_pd_val) { + if (!(pu_pd_orig & mask)) + warn = 1; /* Use pull up */ - pu_pd = pu_pd_orig | (1 << cfg->pull_bit); + pu_pd = pu_pd_orig | mask; } else { + if (pu_pd_orig & mask) + warn = 1; /* Use pull down */ - pu_pd = pu_pd_orig & ~(1 << cfg->pull_bit); + pu_pd = pu_pd_orig & ~mask; } omap_writel(pu_pd, cfg->pu_pd_reg); } @@ -84,21 +106,32 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg) /* Check for an associated pull down register */ if (cfg->pull_reg) { pull_orig = omap_readl(cfg->pull_reg); + mask = 1 << cfg->pull_bit; if (cfg->pull_val) { + if (pull_orig & mask) + warn = 1; /* Low bit = pull enabled */ - pull = pull_orig & ~(1 << cfg->pull_bit); + pull = pull_orig & ~mask; } else { + if (!(pull_orig & mask)) + warn = 1; /* High bit = pull disabled */ - pull = pull_orig | (1 << cfg->pull_bit); + pull = pull_orig | mask; } omap_writel(pull, cfg->pull_reg); } + if (warn) { +#ifdef CONFIG_OMAP_MUX_WARNINGS + printk(KERN_WARNING "MUX: initialized %s\n", cfg->name); +#endif + } + #ifdef CONFIG_OMAP_MUX_DEBUG - if (cfg->debug) { - printk("Omap: Setting register %s\n", cfg->name); + if (cfg->debug || warn) { + printk("MUX: Setting register %s\n", cfg->name); printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg); @@ -118,8 +151,13 @@ int omap_cfg_reg(const reg_cfg_t reg_cfg) spin_unlock_irqrestore(&mux_spin_lock, flags); -#endif +#ifdef CONFIG_OMAP_MUX_ERRORS + return warn ? -ETXTBSY : 0; +#else return 0; +#endif } EXPORT_SYMBOL(omap_cfg_reg); + +#endif /* CONFIG_OMAP_MUX */ diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c index 944c29418..e27041ffe 100644 --- a/arch/arm/mach-omap/ocpi.c +++ b/arch/arm/mach-omap/ocpi.c @@ -59,20 +59,12 @@ int ocpi_enable(void) /* Make sure there's clock for OCPI */ -#ifdef CONFIG_ARCH_OMAP1610 - if (cpu_is_omap1610()) { - val = omap_readl(OMAP1610_ARM_IDLECT3); +#if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap1610() || cpu_is_omap1710()) { + val = omap_readl(OMAP16XX_ARM_IDLECT3); val |= EN_OCPI_CK; val &= ~IDLOCPI_ARM; - omap_writel(val, OMAP1610_ARM_IDLECT3); - } -#endif -#ifdef CONFIG_ARCH_OMAP5912 - if (cpu_is_omap5912()) { - val = omap_readl(OMAP5912_ARM_IDLECT3); - val |= EN_OCPI_CK; - val &= ~IDLOCPI_ARM; - omap_writel(val, OMAP5912_ARM_IDLECT3); + omap_writel(val, OMAP16XX_ARM_IDLECT3); } #endif /* Enable access for OHCI in OCPI */ diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c index cb3c5d6f7..f673eeedd 100644 --- a/arch/arm/mach-omap/time.c +++ b/arch/arm/mach-omap/time.c @@ -1,8 +1,14 @@ /* - * arch/arm/mach-omap/time.c + * linux/arch/arm/mach-omap/time.c * - * OMAP Timer Tick + * OMAP Timers * + * Copyright (C) 2004 Nokia Corporation + * Partial timer rewrite and additional VST timer support by + * Tony Lindgen and + * Tuukka Tikkanen + * + * MPU timer code based on the older MPU timer code for OMAP * Copyright (C) 2000 RidgeRun, Inc. * Author: Greg Lonnon * @@ -33,6 +39,7 @@ #include #include #include +#include #include #include @@ -41,177 +48,135 @@ #include #include #include -#include - -#ifndef __instrument -#define __instrument -#define __noinstrument __attribute__ ((no_instrument_function)) -#endif -typedef struct { - u32 cntl; /* CNTL_TIMER, R/W */ - u32 load_tim; /* LOAD_TIM, W */ - u32 read_tim; /* READ_TIM, R */ -} mputimer_regs_t; - -#define mputimer_base(n) \ - ((volatile mputimer_regs_t*)IO_ADDRESS(OMAP_MPUTIMER_BASE + \ - (n)*OMAP_MPUTIMER_OFFSET)) - -static inline unsigned long timer32k_read(int reg) { - unsigned long val; - val = omap_readw(reg + OMAP_32kHz_TIMER_BASE); - return val; -} -static inline void timer32k_write(int reg,int val) { - omap_writew(val, reg + OMAP_32kHz_TIMER_BASE); -} +struct sys_timer omap_timer; /* - * How long is the timer interval? 100 HZ, right... - * IRQ rate = (TVR + 1) / 32768 seconds - * TVR = 32768 * IRQ_RATE -1 - * IRQ_RATE = 1/100 - * TVR = 326 + * --------------------------------------------------------------------------- + * MPU timer + * --------------------------------------------------------------------------- */ -#define TIMER32k_PERIOD 326 -//#define TIMER32k_PERIOD 0x7ff +#define OMAP_MPU_TIMER1_BASE (0xfffec500) +#define OMAP_MPU_TIMER2_BASE (0xfffec600) +#define OMAP_MPU_TIMER3_BASE (0xfffec700) +#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE +#define OMAP_MPU_TIMER_OFFSET 0x100 -static inline void start_timer32k(void) { - timer32k_write(TIMER32k_CR, - TIMER32k_TSS | TIMER32k_TRB | - TIMER32k_INT | TIMER32k_ARL); -} +#define MPU_TIMER_FREE (1 << 6) +#define MPU_TIMER_CLOCK_ENABLE (1 << 5) +#define MPU_TIMER_AR (1 << 1) +#define MPU_TIMER_ST (1 << 0) -#ifdef CONFIG_MACH_OMAP_PERSEUS2 /* - * After programming PTV with 0 and setting the MPUTIM_CLOCK_ENABLE - * (external clock enable) bit, the timer count rate is 6.5 MHz (13 - * MHZ input/2). !! The divider by 2 is undocumented !! + * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs + * will break. On P2, the timer count rate is 6.5 MHz after programming PTV + * with 0. This divides the 13MHz input by 2, and is undocumented. */ -#define MPUTICKS_PER_SEC (13000000/2) -#else -/* - * After programming PTV with 0, the timer count rate is 6 MHz. - * WARNING! this must be an even number, or machinecycles_to_usecs - * below will break. +#ifdef CONFIG_MACH_OMAP_PERSEUS2 +/* REVISIT: This ifdef construct should be replaced by a query to clock + * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz. */ -#define MPUTICKS_PER_SEC (12000000/2) +#define MPU_TICKS_PER_SEC (13000000 / 2) +#else +#define MPU_TICKS_PER_SEC (12000000 / 2) #endif -static int mputimer_started[3] = {0,0,0}; +#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1) -static inline void __noinstrument start_mputimer(int n, - unsigned long load_val) -{ - volatile mputimer_regs_t* timer = mputimer_base(n); - - mputimer_started[n] = 0; - timer->cntl = MPUTIM_CLOCK_ENABLE; - udelay(1); - - timer->load_tim = load_val; - udelay(1); - timer->cntl = (MPUTIM_CLOCK_ENABLE | MPUTIM_AR | MPUTIM_ST); - mputimer_started[n] = 1; -} +typedef struct { + u32 cntl; /* CNTL_TIMER, R/W */ + u32 load_tim; /* LOAD_TIM, W */ + u32 read_tim; /* READ_TIM, R */ +} omap_mpu_timer_regs_t; -static inline unsigned long __noinstrument -read_mputimer(int n) -{ - volatile mputimer_regs_t* timer = mputimer_base(n); - return (mputimer_started[n] ? timer->read_tim : 0); -} +#define omap_mpu_timer_base(n) \ +((volatile omap_mpu_timer_regs_t*)IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ + (n)*OMAP_MPU_TIMER_OFFSET)) -void __noinstrument start_mputimer1(unsigned long load_val) -{ - start_mputimer(0, load_val); -} -void __noinstrument start_mputimer2(unsigned long load_val) +static inline unsigned long omap_mpu_timer_read(int nr) { - start_mputimer(1, load_val); -} -void __noinstrument start_mputimer3(unsigned long load_val) -{ - start_mputimer(2, load_val); + volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); + return timer->read_tim; } -unsigned long __noinstrument read_mputimer1(void) -{ - return read_mputimer(0); -} -unsigned long __noinstrument read_mputimer2(void) -{ - return read_mputimer(1); -} -unsigned long __noinstrument read_mputimer3(void) +static inline void omap_mpu_timer_start(int nr, unsigned long load_val) { - return read_mputimer(2); -} + volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); -unsigned long __noinstrument do_getmachinecycles(void) -{ - return 0 - read_mputimer(0); + timer->cntl = MPU_TIMER_CLOCK_ENABLE; + udelay(1); + timer->load_tim = load_val; + udelay(1); + timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST); } -unsigned long __noinstrument machinecycles_to_usecs(unsigned long mputicks) +unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks) { /* Round up to nearest usec */ - return ((mputicks * 1000) / (MPUTICKS_PER_SEC / 2 / 1000) + 1) >> 1; + return ((nr_ticks * 1000) / (MPU_TICKS_PER_SEC / 2 / 1000) + 1) >> 1; } /* - * This marks the time of the last system timer interrupt - * that was *processed by the ISR* (timer 2). + * Last processed system timer interrupt */ -static unsigned long systimer_mark; +static unsigned long omap_mpu_timer_last = 0; -static unsigned long omap_gettimeoffset(void) +/* + * Returns elapsed usecs since last system timer interrupt + */ +static unsigned long omap_mpu_timer_gettimeoffset(void) { - /* Return elapsed usecs since last system timer ISR */ - return machinecycles_to_usecs(do_getmachinecycles() - systimer_mark); + unsigned long now = 0 - omap_mpu_timer_read(0); + unsigned long elapsed = now - omap_mpu_timer_last; + + return omap_mpu_timer_ticks_to_usecs(elapsed); } -static irqreturn_t -omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +/* + * Elapsed time between interrupts is calculated using timer0. + * Latency during the interrupt is calculated using timer1. + * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz). + */ +static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { - unsigned long now, ilatency; - - /* - * Mark the time at which the timer interrupt ocurred using - * timer1. We need to remove interrupt latency, which we can - * retrieve from the current system timer2 counter. Both the - * offset timer1 and the system timer2 are counting at 6MHz, - * so we're ok. - */ - now = 0 - read_mputimer1(); - ilatency = MPUTICKS_PER_SEC / 100 - read_mputimer2(); - systimer_mark = now - ilatency; + unsigned long now, latency; + write_seqlock(&xtime_lock); + now = 0 - omap_mpu_timer_read(0); + latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1); + omap_mpu_timer_last = now - latency; timer_tick(regs); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } -static struct irqaction omap_timer_irq = { - .name = "OMAP Timer Tick", +static struct irqaction omap_mpu_timer_irq = { + .name = "mpu timer", .flags = SA_INTERRUPT, - .handler = omap_timer_interrupt + .handler = omap_mpu_timer_interrupt }; -void __init omap_init_time(void) +static __init void omap_init_mpu_timer(void) { - /* Since we don't call request_irq, we must init the structure */ - gettimeoffset = omap_gettimeoffset; - -#ifdef OMAP1510_USE_32KHZ_TIMER - timer32k_write(TIMER32k_CR, 0x0); - timer32k_write(TIMER32k_TVR,TIMER32k_PERIOD); - setup_irq(INT_OS_32kHz_TIMER, &omap_timer_irq); - start_timer32k(); -#else - setup_irq(INT_TIMER2, &omap_timer_irq); - start_mputimer2(MPUTICKS_PER_SEC / 100 - 1); -#endif + omap_timer.offset = omap_mpu_timer_gettimeoffset; + setup_irq(INT_TIMER2, &omap_mpu_timer_irq); + omap_mpu_timer_start(0, 0xffffffff); + omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD); } +/* + * --------------------------------------------------------------------------- + * Timer initialization + * --------------------------------------------------------------------------- + */ +void __init omap_timer_init(void) +{ + omap_init_mpu_timer(); +} + +struct sys_timer omap_timer = { + .init = omap_timer_init, + .offset = NULL, /* Initialized later */ +}; diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c index f3451d269..4eeabe4fe 100644 --- a/arch/arm/mach-omap/usb.c +++ b/arch/arm/mach-omap/usb.c @@ -48,8 +48,10 @@ */ /* TESTED ON: - * - 1611B H2 (with usb1 mini-AB) - * - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS) + * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables + * - 1510 Innovator UDC with bundled usb0 cable + * - 1510 Innovator OHCI with bundled usb1/usb2 cable + * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS * - 1710 custom development board using alternate pin group */ @@ -92,7 +94,10 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) u32 syscon1 = 0; if (nwires == 0) { - USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3); + if (!cpu_is_omap15xx()) { + /* pulldown D+/D- */ + USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); + } return 0; } @@ -101,36 +106,30 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) * USB0_VP and USB0_VM are always set on 1510, there's no muxing * available for them. */ - if (nwires >= 2 && !cpu_is_omap1510()) { + if (nwires >= 2 && !cpu_is_omap15xx()) { omap_cfg_reg(AA9_USB0_VP); omap_cfg_reg(R9_USB0_VM); } + if (is_device) + omap_cfg_reg(W4_USB_PUEN); /* internal transceiver */ if (nwires == 2) { - if (cpu_is_omap1510()) { - /* This works for OHCI on 1510-Innovator, nothing to mux */ + if (cpu_is_omap15xx()) { + /* This works for OHCI on 1510-Innovator */ return 0; } -#if 0 /* NOTE: host OR device mode for now, no OTG */ - USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4); + USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4); if (is_device) { - omap_cfg_reg(W4_USB_PUEN); omap_cfg_reg(R18_1510_USB_GPIO0); // omap_cfg_reg(USB0_VBUS); - // omap_cfg_reg(USB0_PUEN); // USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7 - // when USB0_PUEN is needed } else /* host mode needs D+ and D- pulldowns */ USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); + return 3 << 16; -#else - /* FIXME: 1610 needs to return the right value here */ - printk(KERN_ERR "usb0 internal transceiver, nyet\n"); - return 0; -#endif } /* alternate pin config, external transceiver */ @@ -170,7 +169,7 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; if (nwires == 0) return 0; @@ -178,11 +177,11 @@ static u32 __init omap_usb1_init(unsigned nwires) /* external transceiver */ omap_cfg_reg(USB1_TXD); omap_cfg_reg(USB1_TXEN); - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { omap_cfg_reg(USB1_SEO); omap_cfg_reg(USB1_SPEED); // SUSP - } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) { + } else if (cpu_is_omap16xx()) { omap_cfg_reg(W13_1610_USB1_SE0); omap_cfg_reg(R13_1610_USB1_SPEED); // SUSP @@ -203,7 +202,8 @@ static u32 __init omap_usb1_init(unsigned nwires) syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; + if (!cpu_is_omap15xx()) + USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -216,31 +216,32 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - if (alt_pingroup) + if (alt_pingroup || nwires == 0) return 0; - if (nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; if (nwires == 0) return 0; /* external transceiver */ - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_TXD); omap_cfg_reg(USB2_TXEN); omap_cfg_reg(USB2_SEO); if (nwires != 3) omap_cfg_reg(USB2_RCV); - } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) { + /* there is no USB2_SPEED */ + } else if (cpu_is_omap16xx()) { omap_cfg_reg(V6_USB2_TXD); omap_cfg_reg(W9_USB2_TXEN); omap_cfg_reg(W5_USB2_SE0); if (nwires != 3) omap_cfg_reg(Y5_USB2_RCV); + // FIXME omap_cfg_reg(USB2_SPEED); } else { pr_debug("usb unrecognized\n"); } // omap_cfg_reg(USB2_SUSP); - // FIXME omap_cfg_reg(USB2_SPEED); switch (nwires) { case 3: @@ -251,14 +252,14 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) break; case 6: syscon1 = 3; - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); omap_cfg_reg(USB2_VM); } else { omap_cfg_reg(AA9_USB2_VP); omap_cfg_reg(R9_USB2_VM); + USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; } - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -337,7 +338,7 @@ static struct platform_device ohci_device = { .dev = { .release = usb_release, .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0x0fffffff, + .coherent_dma_mask = 0xffffffff, }, .num_resources = ARRAY_SIZE(ohci_resources), .resource = ohci_resources, @@ -375,7 +376,11 @@ static struct platform_device otg_device = { // FIXME correct answer depends on hmc_mode, // as does any nonzero value for config->otg port number +#ifdef CONFIG_USB_GADGET_OMAP +#define is_usb0_device(config) 1 +#else #define is_usb0_device(config) 0 +#endif /*-------------------------------------------------------------------------*/ @@ -420,7 +425,7 @@ omap_otg_init(struct omap_usb_config *config) if (alt_pingroup) printk(", usb2 alt %d wires", config->pins[2]); else if (config->pins[0]) - printk(", usb0 %d wires%s", config->pins[2], + printk(", usb0 %d wires%s", config->pins[0], is_usb0_device(config) ? " (dev)" : ""); if (config->pins[1]) printk(", usb1 %d wires", config->pins[1]); @@ -477,6 +482,19 @@ static inline void omap_otg_init(struct omap_usb_config *config) {} #ifdef CONFIG_ARCH_OMAP1510 +#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ) +#define SOFT_UDC_REQ (1 << 4) +#define SOFT_DPLL_REQ (1 << 0) + +#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL) +#define DPLL_IOB (1 << 13) +#define DPLL_PLL_ENABLE (1 << 4) +#define DPLL_LOCK (1 << 0) + +#define ULPD_APLL_CTRL_REG __REG16(ULPD_APLL_CTRL) +#define APLL_NDPLL_SWITCH (1 << 0) + + static void __init omap_1510_usb_init(struct omap_usb_config *config) { int status; @@ -490,16 +508,43 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config) val |= (config->hmc_mode << 1); omap_writel(val, MOD_CONF_CTRL_0); - // FIXME this has a UDC controller too + printk("USB: hmc %d", config->hmc_mode); + if (config->pins[0]) + printk(", usb0 %d wires%s", config->pins[0], + is_usb0_device(config) ? " (dev)" : ""); + if (config->pins[1]) + printk(", usb1 %d wires", config->pins[1]); + if (config->pins[2]) + printk(", usb2 %d wires", config->pins[2]); + printk("\n"); + + /* use DPLL for 48 MHz function clock */ + pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG, + ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG); + ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH; + ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE; + ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ; + while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK)) + cpu_relax(); + +#ifdef CONFIG_USB_GADGET_OMAP + if (config->register_dev) { + udc_device.dev.platform_data = config; + status = platform_device_register(&udc_device); + if (status) + pr_debug("can't register UDC device, %d\n", status); + /* udc driver gates 48MHz by D+ pullup */ + } +#endif #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - if (config->otg || config->register_host) { + if (config->register_host) { ohci_device.dev.platform_data = config; status = platform_device_register(&ohci_device); if (status) pr_debug("can't register OHCI device, %d\n", status); + /* hcd explicitly gates 48MHz */ } - // FIXME completely untested ... #endif } @@ -524,12 +569,9 @@ omap_usb_init(void) } platform_data = *config; - if (cpu_is_omap730() - || cpu_is_omap1610() - || cpu_is_omap1710() - || cpu_is_omap5912()) + if (cpu_is_omap730() || cpu_is_omap16xx()) omap_otg_init(&platform_data); - else if (cpu_is_omap1510()) + else if (cpu_is_omap15xx()) omap_1510_usb_init(&platform_data); else { printk(KERN_ERR "USB: No init for your chip yet\n"); diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index d394f6957..bb28824d8 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -12,7 +12,7 @@ config ARCH_LUBBOCK config MACH_MAINSTONE bool "Intel HCDDBBVA0 Development Platform" select PXA27x - #select IWMMXT + select IWMMXT config ARCH_PXA_IDP bool "Accelent Xscale IDP" @@ -32,4 +32,9 @@ config PXA27x help Select code specific to PXA27x variants +config IWMMXT + bool + help + Enable support for iWMMXt + endif diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index 3096fa7c5..458112b21 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -23,6 +23,7 @@ #include #include +#include static struct dma_channel { char *name; diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 80f3535e0..3fe020210 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -30,8 +30,10 @@ #include #include +#include #include #include +#include #include "generic.h" @@ -47,6 +49,10 @@ void pxa_gpio_mode(int gpio_mode) int gafr; local_irq_save(flags); + if (gpio_mode & GPIO_DFLT_LOW) + GPCR(gpio) = GPIO_bit(gpio); + else if (gpio_mode & GPIO_DFLT_HIGH) + GPSR(gpio) = GPIO_bit(gpio); if (gpio_mode & GPIO_MD_MASK_DIR) GPDR(gpio) |= GPIO_bit(gpio); else @@ -128,6 +134,11 @@ static struct platform_device pxamci_device = { .resource = pxamci_resources, }; +void __init pxa_set_mci_info(struct pxamci_platform_data *info) +{ + pxamci_device.dev.platform_data = info; +} + static struct pxa2xx_udc_mach_info pxa_udc_info; @@ -135,7 +146,6 @@ void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info) { memcpy(&pxa_udc_info, info, sizeof *info); } -EXPORT_SYMBOL(pxa_set_udc_info); static struct resource pxa2xx_udc_resources[] = { [0] = { @@ -169,7 +179,6 @@ void __init set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info) { memcpy(&pxa_fb_info,hard_pxa_fb_info,sizeof(struct pxafb_mach_info)); } -EXPORT_SYMBOL(set_pxa_fb_info); static struct resource pxafb_resources[] = { [0] = { diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index f542ef4e7..e54a8dd63 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -9,9 +9,11 @@ * published by the Free Software Foundation. */ +struct sys_timer; + +extern struct sys_timer pxa_timer; extern void __init pxa_map_io(void); extern void __init pxa_init_irq(void); -extern void __init pxa_init_time(void); extern unsigned int get_clk_frequency_khz(int info); diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index db53cd571..4333a0f19 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -27,6 +27,7 @@ #include #include +#include #include #include "generic.h" @@ -100,7 +101,7 @@ static void __init idp_map_io(void) pxa_map_io(); iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc)); - set_irq_type(IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE); + set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE); // serial ports 2 & 3 pxa_gpio_mode(GPIO42_BTRXD_MD); @@ -118,6 +119,6 @@ MACHINE_START(PXA_IDP, "Accelent Xscale IDP") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(idp_map_io) INITIRQ(idp_init_irq) - INITTIME(pxa_init_time) + .timer = &pxa_timer, INIT_MACHINE(idp_init) MACHINE_END diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index c771e4376..a676a8657 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -20,39 +20,64 @@ #include #include #include +#include #include "generic.h" /* - * This is for IRQs known as PXA_IRQ([8...31]). + * This is for peripheral IRQs internal to the PXA chip. */ -static void pxa_mask_irq(unsigned int irq) +static void pxa_mask_low_irq(unsigned int irq) { ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); } -static void pxa_unmask_irq(unsigned int irq) +static void pxa_unmask_low_irq(unsigned int irq) { ICMR |= (1 << (irq + PXA_IRQ_SKIP)); } -static struct irqchip pxa_internal_chip = { - .ack = pxa_mask_irq, - .mask = pxa_mask_irq, - .unmask = pxa_unmask_irq, +static struct irqchip pxa_internal_chip_low = { + .ack = pxa_mask_low_irq, + .mask = pxa_mask_low_irq, + .unmask = pxa_unmask_low_irq, }; +#if PXA_INTERNAL_IRQS > 32 + +/* + * This is for the second set of internal IRQs as found on the PXA27x. + */ + +static void pxa_mask_high_irq(unsigned int irq) +{ + ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP)); +} + +static void pxa_unmask_high_irq(unsigned int irq) +{ + ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP)); +} + +static struct irqchip pxa_internal_chip_high = { + .ack = pxa_mask_high_irq, + .mask = pxa_mask_high_irq, + .unmask = pxa_unmask_high_irq, +}; + +#endif + /* * PXA GPIO edge detection for IRQs: * IRQs are generated on Falling-Edge, Rising-Edge, or both. * Use this instead of directly setting GRER/GFER. */ -static long GPIO_IRQ_rising_edge[3]; -static long GPIO_IRQ_falling_edge[3]; -static long GPIO_IRQ_mask[3]; +static long GPIO_IRQ_rising_edge[4]; +static long GPIO_IRQ_falling_edge[4]; +static long GPIO_IRQ_mask[4]; static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) { @@ -106,13 +131,13 @@ static void pxa_ack_low_gpio(unsigned int irq) static struct irqchip pxa_low_gpio_chip = { .ack = pxa_ack_low_gpio, - .mask = pxa_mask_irq, - .unmask = pxa_unmask_irq, + .mask = pxa_mask_low_irq, + .unmask = pxa_unmask_low_irq, .type = pxa_gpio_irq_type, }; /* - * Demux handler for GPIO 2-80 edge detect interrupts + * Demux handler for GPIO>=2 edge detect interrupts */ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc, @@ -169,6 +194,23 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc, } while (mask); loop = 1; } + +#if PXA_LAST_GPIO >= 96 + mask = GEDR3; + if (mask) { + GEDR3 = mask; + irq = IRQ_GPIO(96); + desc = irq_desc + irq; + do { + if (mask & 1) + desc->handle(irq, desc, regs); + irq++; + desc++; + mask >>= 1; + } while (mask); + loop = 1; + } +#endif } while (loop); } @@ -214,12 +256,25 @@ void __init pxa_init_irq(void) ICLR = 0; /* clear all GPIO edge detects */ - GFER0 = GFER1 = GFER2 = 0; - GRER0 = GRER1 = GRER2 = 0; + GFER0 = 0; + GFER1 = 0; + GFER2 = 0; + GRER0 = 0; + GRER1 = 0; + GRER2 = 0; GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; +#ifdef CONFIG_PXA27x + /* And similarly for the extra regs on the PXA27x */ + ICMR2 = 0; + ICLR2 = 0; + GFER3 = 0; + GRER3 = 0; + GEDR3 = GEDR3; +#endif + /* only unmasked interrupts kick us out of idle */ ICCR = 1; @@ -227,10 +282,18 @@ void __init pxa_init_irq(void) GPIO_IRQ_mask[0] = 3; for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { - set_irq_chip(irq, &pxa_internal_chip); + set_irq_chip(irq, &pxa_internal_chip_low); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + +#if PXA_INTERNAL_IRQS > 32 + for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) { + set_irq_chip(irq, &pxa_internal_chip_high); set_irq_handler(irq, do_level_IRQ); set_irq_flags(irq, IRQF_VALID); } +#endif for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { set_irq_chip(irq, &pxa_low_gpio_chip); @@ -238,13 +301,13 @@ void __init pxa_init_irq(void) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) { + for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) { set_irq_chip(irq, &pxa_muxed_gpio_chip); set_irq_handler(irq, do_edge_IRQ); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - /* Install handler for GPIO 2-80 edge detect interrupts */ - set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip); - set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler); + /* Install handler for GPIO>=2 edge detect interrupts */ + set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); + set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); } diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c index 0e083b34e..05cf56059 100644 --- a/arch/arm/mach-pxa/leds-lubbock.c +++ b/arch/arm/mach-pxa/leds-lubbock.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "leds.h" diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c index 8403f6780..bbd3f87a9 100644 --- a/arch/arm/mach-pxa/leds-mainstone.c +++ b/arch/arm/mach-pxa/leds-mainstone.c @@ -17,6 +17,7 @@ #include #include +#include #include #include "leds.h" diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 28c9677a9..87fd729c3 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -29,14 +29,18 @@ #include #include +#include #include #include #include +#include #include #include "generic.h" +#define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080) + void lubbock_set_misc_wr(unsigned int mask, unsigned int set) { unsigned long flags; @@ -180,10 +184,25 @@ static struct pxafb_mach_info sharp_lm8v31 __initdata = { .lccr3 = LCCR3_PCP | LCCR3_Acb(255), }; +static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data) +{ + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + + return 0; +} + +static struct pxamci_platform_data lubbock_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = lubbock_mci_init, +}; + static void __init lubbock_init(void) { pxa_set_udc_info(&udc_info); set_pxa_fb_info(&sharp_lm8v31); + pxa_set_mci_info(&lubbock_mci_platform_data); (void) platform_add_devices(devices, ARRAY_SIZE(devices)); } @@ -220,6 +239,6 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(lubbock_map_io) INITIRQ(lubbock_init_irq) - INITTIME(pxa_init_time) + .timer = &pxa_timer, INIT_MACHINE(lubbock_init) MACHINE_END diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 155b5950e..2c8d7c826 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -31,8 +31,10 @@ #include #include +#include #include #include +#include #include "generic.h" @@ -169,6 +171,61 @@ static struct pxafb_mach_info toshiba_ltm035a776c __initdata = { .pxafb_backlight_power = mainstone_backlight_power, }; +static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* + * setup GPIO for PXA27x MMC controller + */ + pxa_gpio_mode(GPIO32_MMCCLK_MD); + pxa_gpio_mode(GPIO112_MMCCMD_MD); + pxa_gpio_mode(GPIO92_MMCDAT0_MD); + pxa_gpio_mode(GPIO109_MMCDAT1_MD); + pxa_gpio_mode(GPIO110_MMCDAT2_MD); + pxa_gpio_mode(GPIO111_MMCDAT3_MD); + + /* make sure SD/Memory Stick multiplexer's signals + * are routed to MMC controller + */ + MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL; + + err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, SA_INTERRUPT, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + return 0; +} + +static void mainstone_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + printk(KERN_DEBUG "%s: on\n", __FUNCTION__); + MST_MSCWR1 |= MST_MSCWR1_MMC_ON; + MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL; + } else { + printk(KERN_DEBUG "%s: off\n", __FUNCTION__); + MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON; + } +} + +static void mainstone_mci_exit(struct device *dev, void *data) +{ + free_irq(MAINSTONE_MMC_IRQ, data); +} + +static struct pxamci_platform_data mainstone_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = mainstone_mci_init, + .setpower = mainstone_mci_setpower, + .exit = mainstone_mci_exit, +}; + static void __init mainstone_init(void) { platform_device_register(&smc91x_device); @@ -179,6 +236,8 @@ static void __init mainstone_init(void) set_pxa_fb_info(&toshiba_ltm04c380k); else set_pxa_fb_info(&toshiba_ltm035a776c); + + pxa_set_mci_info(&mainstone_mci_platform_data); } @@ -197,6 +256,6 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000)) MAPIO(mainstone_map_io) INITIRQ(mainstone_init_irq) - INITTIME(pxa_init_time) + .timer = &pxa_timer, INIT_MACHINE(mainstone_init) MACHINE_END diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 245e25b08..901ee6880 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include /* @@ -45,9 +47,6 @@ extern void pxa_cpu_resume(void); */ enum { SLEEP_SAVE_START = 0, - SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, - SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, - SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, @@ -64,26 +63,20 @@ enum { SLEEP_SAVE_START = 0, }; -static int pxa_pm_enter(u32 state) +static int pxa_pm_enter(suspend_state_t state) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; - unsigned long delta; + struct timespec delta, rtc; int i; if (state != PM_SUSPEND_MEM) return -EINVAL; /* preserve current time */ - delta = xtime.tv_sec - RCNR; - - /* save vital registers */ - SAVE(OSCR); - SAVE(OSMR0); - SAVE(OSMR1); - SAVE(OSMR2); - SAVE(OSMR3); - SAVE(OIER); + rtc.tv_sec = RCNR; + rtc.tv_nsec = 0; + save_time_delta(&delta, &rtc); SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); @@ -145,13 +138,6 @@ static int pxa_pm_enter(u32 state) PSSR = PSSR_RDH | PSSR_PH; - RESTORE(OSMR0); - RESTORE(OSMR1); - RESTORE(OSMR2); - RESTORE(OSMR3); - RESTORE(OSCR); - RESTORE(OIER); - RESTORE(CKEN); ICLR = 0; @@ -159,7 +145,8 @@ static int pxa_pm_enter(u32 state) RESTORE(ICMR); /* restore current time */ - xtime.tv_sec = RCNR + delta; + rtc.tv_sec = RCNR; + restore_time_delta(&delta, &rtc); #ifdef DEBUG printk(KERN_DEBUG "*** made it back from resume\n"); @@ -176,7 +163,7 @@ unsigned long sleep_phys_sp(void *sp) /* * Called after processes are frozen, but before we shut down devices. */ -static int pxa_pm_prepare(u32 state) +static int pxa_pm_prepare(suspend_state_t state) { return 0; } @@ -184,7 +171,7 @@ static int pxa_pm_prepare(u32 state) /* * Called after devices are re-setup, but before processes are thawed. */ -static int pxa_pm_finish(u32 state) +static int pxa_pm_finish(suspend_state_t state) { return 0; } diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 41150917f..e887b7175 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -22,6 +22,7 @@ #include #include +#include #include "generic.h" diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index b1573c837..7e863afef 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -16,8 +16,11 @@ #include #include #include +#include #include +#include +#include #include "generic.h" @@ -116,3 +119,45 @@ unsigned int get_lcdclk_frequency_10khz(void) EXPORT_SYMBOL(get_clk_frequency_khz); EXPORT_SYMBOL(get_memclk_frequency_10khz); EXPORT_SYMBOL(get_lcdclk_frequency_10khz); + + +/* + * device registration specific to PXA27x. + */ + +static u64 pxa27x_dmamask = 0xffffffffUL; + +static struct resource pxa27x_ohci_resources[] = { + [0] = { + .start = 0x4C000000, + .end = 0x4C00ff6f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USBH1, + .end = IRQ_USBH1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ohci_device = { + .name = "pxa27x-ohci", + .id = -1, + .dev = { + .dma_mask = &pxa27x_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(pxa27x_ohci_resources), + .resource = pxa27x_ohci_resources, +}; + +static struct platform_device *devices[] __initdata = { + &ohci_device, +}; + +static int __init pxa27x_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(pxa27x_init); diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 189263939..be00614f5 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -16,6 +16,8 @@ #include #include +#include + .text /* @@ -64,6 +66,37 @@ ENTRY(pxa_cpu_suspend) @ prepare pointer to physical address 0 (virtual mapping in generic.c) mov r2, #UNCACHED_PHYS_0 + @ Intel PXA255 Specification Update notes problems + @ about suspending with PXBus operating above 133MHz + @ (see Errata 31, GPIO output signals, ... unpredictable in sleep + @ + @ We keep the change-down close to the actual suspend on SDRAM + @ as possible to eliminate messing about with the refresh clock + @ as the system will restore with the original speed settings + @ + @ Ben Dooks, 13-Sep-2004 + + ldr r6, =CCCR + ldr r8, [r6] @ keep original value for resume + + @ ensure x1 for run and turbo mode with memory clock + bic r7, r8, #CCCR_M_MASK | CCCR_N_MASK + orr r7, r7, #(1<<5) | (2<<7) + + @ check that the memory frequency is within limits + and r14, r7, #CCCR_L_MASK + teq r14, #1 + bicne r7, r7, #CCCR_L_MASK + orrne r7, r7, #1 @@ 99.53MHz + + @ get ready for the change + @ note, since we are making turbo=run, do not remove the turbo + @ as this may cause non-turbo mode on resume + mrc p14, 0, r0, c6, c0, 0 + bic r0, r0, #2 @ clear change bit + mcr p14, 0, r0, c6, c0, 0 + orr r0, r0, #2 @ initiate change bit + @ align execution to a cache line b 1f @@ -74,6 +107,13 @@ ENTRY(pxa_cpu_suspend) @ All needed values are now in registers. @ These last instructions should be in cache + @ initiate the frequency change... + str r7, [r6] + mcr p14, 0, r0, c6, c0, 0 + + @ restore the original cpu speed value for resume + str r8, [r6] + @ put SDRAM into self-refresh str r5, [r4] @@ -83,8 +123,7 @@ ENTRY(pxa_cpu_suspend) @ enter sleep mode mcr p14, 0, r1, c7, c0, 0 -20: nop - b 20b @ loop waiting for sleep +20: b 20b @ loop waiting for sleep /* * cpu_pxa_resume() diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 7e8923563..473fb6173 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -27,6 +27,7 @@ #include #include #include +#include static inline unsigned long pxa_get_rtc_time(void) @@ -74,6 +75,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int next_match; + write_seqlock(&xtime_lock); + /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time accuracy. * IRQs are disabled inside the loop to ensure coherence between @@ -95,6 +98,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) next_match = (OSMR0 += LATCH); } while( (signed long)(next_match - OSCR) <= 8 ); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -104,11 +109,10 @@ static struct irqaction pxa_timer_irq = { .handler = pxa_timer_interrupt }; -void __init pxa_init_time(void) +static void __init pxa_timer_init(void) { struct timespec tv; - gettimeoffset = pxa_gettimeoffset; set_rtc = pxa_set_rtc; tv.tv_nsec = 0; @@ -122,3 +126,39 @@ void __init pxa_init_time(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_PM +static unsigned long osmr[4], oier; + +static void pxa_timer_suspend(void) +{ + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; +} + +static void pxa_timer_resume(void) +{ + OSMR0 = osmr[0]; + OSMR1 = osmr[1]; + OSMR2 = osmr[2]; + OSMR3 = osmr[3]; + OIER = oier; + + /* + * OSMR0 is the system timer: make sure OSCR is sufficiently behind + */ + OSCR = OSMR0 - LATCH; +} +#else +#define pxa_timer_suspend NULL +#define pxa_timer_resume NULL +#endif + +struct sys_timer pxa_timer = { + .init = pxa_timer_init, + .suspend = pxa_timer_suspend, + .resume = pxa_timer_resume, + .offset = pxa_gettimeoffset, +}; diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index d5a1a3af2..2f60dea2a 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #include #include @@ -66,11 +67,11 @@ __tagtable(ATAG_ACORN, parse_tag_acorn); static struct map_desc rpc_io_desc[] __initdata = { { SCREEN_BASE, SCREEN_START, 2*1048576, MT_DEVICE }, /* VRAM */ - { IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */ + { IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */ { EASI_BASE, EASI_START, EASI_SIZE, MT_DEVICE } /* EASI space */ }; -void __init rpc_map_io(void) +static void __init rpc_map_io(void) { iotable_init(rpc_io_desc, ARRAY_SIZE(rpc_io_desc)); @@ -85,31 +86,87 @@ void __init rpc_map_io(void) elf_hwcap &= ~HWCAP_HALF; } -static irqreturn_t -rpc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - timer_tick(regs); +static struct resource acornfb_resources[] = { + { /* VIDC */ + .start = 0x03400000, + .end = 0x035fffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_VSYNCPULSE, + .end = IRQ_VSYNCPULSE, + .flags = IORESOURCE_IRQ, + }, +}; - return IRQ_HANDLED; -} +static struct platform_device acornfb_device = { + .name = "acornfb", + .id = -1, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(acornfb_resources), + .resource = acornfb_resources, +}; -static struct irqaction rpc_timer_irq = { - .name = "RiscPC Timer Tick", - .flags = SA_INTERRUPT, - .handler = rpc_timer_interrupt +static struct resource iomd_resources[] = { + { + .start = 0x03200000, + .end = 0x0320ffff, + .flags = IORESOURCE_MEM, + }, }; -/* - * Set up timer interrupt. - */ -void __init rpc_init_time(void) -{ - extern void ioctime_init(void); - ioctime_init(); +static struct platform_device iomd_device = { + .name = "iomd", + .id = -1, + .num_resources = ARRAY_SIZE(iomd_resources), + .resource = iomd_resources, +}; + +static struct platform_device kbd_device = { + .name = "kart", + .id = -1, + .dev = { + .parent = &iomd_device.dev, + }, +}; - setup_irq(IRQ_TIMER, &rpc_timer_irq); +static struct plat_serial8250_port serial_platform_data[] = { + { + .mapbase = 0x03010fe0, + .irq = 10, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static struct platform_device *devs[] __initdata = { + &iomd_device, + &kbd_device, + &serial_device, + &acornfb_device, +}; + +static int __init rpc_init(void) +{ + return platform_add_devices(devs, ARRAY_SIZE(devs)); } +arch_initcall(rpc_init); + +extern struct sys_timer ioc_timer; + MACHINE_START(RISCPC, "Acorn-RiscPC") MAINTAINER("Russell King") BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) @@ -118,5 +175,5 @@ MACHINE_START(RISCPC, "Acorn-RiscPC") DISABLE_PARPORT(1) MAPIO(rpc_map_io) INITIRQ(rpc_init_irq) - INITTIME(rpc_init_time) + .timer = &ioc_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 40e78bc44..40604ed09 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -1,9 +1,10 @@ if ARCH_S3C2410 -menu "S3C2410 Implementations" +menu "S3C24XX Implementations" config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" + select CPU_S3C2410 help Say Y here if you are using the Simtec Electronics EB2410ITX development board (also known as BAST) @@ -12,24 +13,111 @@ config ARCH_BAST config ARCH_H1940 bool "IPAQ H1940" + select CPU_S3C2410 help Say Y here if you are using the HP IPAQ H1940 + . config ARCH_SMDK2410 bool "SMDK2410/A9M2410" + select CPU_S3C2410 help Say Y here if you are using the SMDK2410 or the derived module A9M2410 config MACH_VR1000 bool "Thorcom VR1000" + select CPU_S3C2410 help Say Y here if you are using the Thorcom VR1000 board. This linux port is currently being maintained by Simtec, on behalf of Thorcom. Any queries, please contact Thorcom first. +config MACH_RX3715 + bool "HP iPAQ rx3715" + select CPU_S3C2440 + help + Say Y here if you are using the HP iPAQ rx3715. + + See http://www.handhelds.org/projects/rx3715.html for more + information on this project + endmenu +config CPU_S3C2410 + bool + depends on ARCH_S3C2410 + help + Support for S3C2410 and S3C2410A family from the S3C24XX line + of Samsung Mobile CPUs. + +config CPU_S3C2440 + bool + depends on ARCH_S3C2410 + help + Support for S3C2440 Samsung Mobile CPU based systems. + +comment "S3C2410 Setup" + +config S3C2410_DMA + bool "S3C2410 DMA support" + depends on ARCH_S3C2410 + help + S3C2410 DMA support. This is needed for drivers like sound which + use the S3C2410's DMA system to move data to and from the + peripheral blocks. + +config S3C2410_DMA_DEBUG + bool "S3C2410 DMA support debug" + depends on ARCH_S3C2410 && S3C2410_DMA + help + Enable debugging output for the DMA code. This option sends info + to the kernel log, at priority KERN_DEBUG. + + Note, it is easy to create and fill the log buffer in a small + amount of time, as well as using an significant percantage of + the CPU time doing so. + + +config S3C2410_PM_DEBUG + bool "S3C2410 PM Suspend debug" + depends on ARCH_S3C2410 && PM + help + Say Y here if you want verbose debugging from the PM Suspend and + Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt` + for more information. + +config S3C2410_PM_CHECK + bool "S3C2410 PM Suspend Memory CRC" + depends on ARCH_S3C2410 && PM && CRC32 + help + Enable the PM code's memory area checksum over sleep. This option + will generate CRCs of all blocks of memory, and store them before + going to sleep. The blocks are then checked on resume for any + errors. + +config S3C2410_PM_CHECK_CHUNKSIZE + int "S3C2410 PM Suspend CRC Chunksize (KiB)" + depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK + default 64 + help + Set the chunksize in Kilobytes of the CRC for checking memory + corruption over suspend and resume. A smaller value will mean that + the CRC data block will take more memory, but wil identify any + faults with better precision. + +config S3C2410_LOWLEVEL_UART_PORT + int "S3C2410 UART to use for low-level messages" + default 0 + help + Choice of which UART port to use for the low-level messages, + such as the `Uncompressing...` at start time. The value of + this configuration should be between zero and two. The port + must have been initalised by the boot-loader before use. + + Note, this does not affect the port used by the debug messages, + which is a seperate configuration. + endif diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 476c6ca78..aa8b30874 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -1,19 +1,32 @@ + # # Makefile for the linux kernel. # # Object file lists. -obj-y := s3c2410.o irq.o time.o gpio.o +obj-y := cpu.o irq.o time.o gpio.o clock.o devs.o obj-m := obj-n := obj- := -obj-$(CONFIG_ARCH_BAST) += mach-bast.o -obj-$(CONFIG_MACH_H1940) += mach-h1940.o -obj-$(CONFIG_ARCH_H1940) += mach-h1940.o -obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o -obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o +# S3C2410 support files + +obj-$(CONFIG_CPU_S3C2410) += s3c2410.o +obj-$(CONFIG_S3C2410_DMA) += dma.o + +# Power Management support + +obj-$(CONFIG_PM) += pm.o sleep.o + +# S3C2440 support + +obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o + +# machine specific support -#obj-$(CONFIG_PCI) +=$(pci-y) -#obj-$(CONFIG_LEDS) +=$(leds-y) +obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o +obj-$(CONFIG_ARCH_H1940) += mach-h1940.o +obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o +obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o +obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index a12ade71b..107c12abc 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,12 @@ #include "clock.h" +/* clock information */ + +unsigned long s3c24xx_xtal = 12*1000*1000; /* default 12MHz */ +unsigned long s3c24xx_fclk; +unsigned long s3c24xx_hclk; +unsigned long s3c24xx_pclk; static LIST_HEAD(clocks); static DECLARE_MUTEX(clocks_sem); @@ -53,7 +60,7 @@ static DECLARE_MUTEX(clocks_sem); /* old functions */ -void s3c2410_clk_enable(unsigned int clocks, unsigned int enable) +void inline s3c2410_clk_enable(unsigned int clocks, unsigned int enable) { unsigned long clkcon; unsigned long flags; @@ -66,11 +73,26 @@ void s3c2410_clk_enable(unsigned int clocks, unsigned int enable) if (enable) clkcon |= clocks; + /* ensure none of the special function bits set */ + clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); + __raw_writel(clkcon, S3C2410_CLKCON); local_irq_restore(flags); } +/* enable and disable calls for use with the clk struct */ + +static int clk_null_enable(struct clk *clk, int enable) +{ + return 0; +} + +int s3c2410_clkcon_enable(struct clk *clk, int enable) +{ + s3c2410_clk_enable(clk->ctrlbit, enable); + return 0; +} /* Clock API calls */ @@ -78,17 +100,35 @@ struct clk *clk_get(struct device *dev, const char *id) { struct clk *p; struct clk *clk = ERR_PTR(-ENOENT); + int idno; + + idno = (dev == NULL) ? -1 : to_platform_device(dev)->id; down(&clocks_sem); + list_for_each_entry(p, &clocks, list) { - if (strcmp(id, p->name) == 0 && + if (p->id == idno && + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } } - up(&clocks_sem); + /* check for the case where a device was supplied, but the + * clock that was being searched for is not device specific */ + + if (IS_ERR(clk)) { + list_for_each_entry(p, &clocks, list) { + if (p->id == -1 && strcmp(id, p->name) == 0 && + try_module_get(p->owner)) { + clk = p; + break; + } + } + } + + up(&clocks_sem); return clk; } @@ -99,15 +139,16 @@ void clk_put(struct clk *clk) int clk_enable(struct clk *clk) { - if (clk->ctrlbit != 0) - s3c2410_clk_enable(clk->ctrlbit, 1); + if (IS_ERR(clk)) + return -EINVAL; - return 0; + return (clk->enable)(clk, 1); } void clk_disable(struct clk *clk) { - s3c2410_clk_enable(clk->ctrlbit, 0); + if (!IS_ERR(clk)) + (clk->enable)(clk, 0); } @@ -125,8 +166,14 @@ void clk_unuse(struct clk *clk) unsigned long clk_get_rate(struct clk *clk) { - if (clk->parent != NULL) - return clk->parent->rate; + if (IS_ERR(clk)) + return 0; + + if (clk->rate != 0) + return clk->rate; + + while (clk->parent != NULL && clk->rate == 0) + clk = clk->parent; return clk->rate; } @@ -160,90 +207,151 @@ EXPORT_SYMBOL(clk_get_parent); /* base clocks */ static struct clk clk_f = { - .name = "fclk", - .rate = 0, - .parent = NULL, - .ctrlbit = 0 + .name = "fclk", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, }; static struct clk clk_h = { - .name = "hclk", - .rate = 0, - .parent = NULL, - .ctrlbit = 0 + .name = "hclk", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, }; static struct clk clk_p = { - .name = "pclk", - .rate = 0, - .parent = NULL, - .ctrlbit = 0 + .name = "pclk", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, }; +/* clocks that could be registered by external code */ + +struct clk s3c24xx_dclk0 = { + .name = "dclk0", + .id = -1, +}; + +struct clk s3c24xx_dclk1 = { + .name = "dclk1", + .id = -1, +}; + +struct clk s3c24xx_clkout0 = { + .name = "clkout0", + .id = -1, +}; + +struct clk s3c24xx_clkout1 = { + .name = "clkout1", + .id = -1, +}; + +struct clk s3c24xx_uclk = { + .name = "uclk", + .id = -1, +}; + + /* clock definitions */ static struct clk init_clocks[] = { { .name = "nand", + .id = -1, .parent = &clk_h, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_NAND }, { .name = "lcd", + .id = -1, .parent = &clk_h, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_LCDC }, { .name = "usb-host", + .id = -1, .parent = &clk_h, - .ctrlbit = S3C2410_CLKCON_USBH + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBH }, { .name = "usb-device", + .id = -1, .parent = &clk_h, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_USBD }, { .name = "timers", .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_PWMT }, { .name = "sdi", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_SDI }, - { .name = "uart0", + { .name = "uart", + .id = 0, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_UART0 }, - { .name = "uart1", + { .name = "uart", + .id = 1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_UART1 }, - { .name = "uart2", + { .name = "uart", + .id = 2, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_UART2 }, { .name = "gpio", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_GPIO }, { .name = "rtc", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_RTC }, { .name = "adc", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_ADC }, { .name = "i2c", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_IIC }, { .name = "iis", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_IIS }, { .name = "spi", + .id = -1, .parent = &clk_p, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2410_CLKCON_SPI }, { .name = "watchdog", + .id = -1, .parent = &clk_p, .ctrlbit = 0 } @@ -256,6 +364,9 @@ int s3c2410_register_clock(struct clk *clk) clk->owner = THIS_MODULE; atomic_set(&clk->used, 0); + if (clk->enable == NULL) + clk->enable = clk_null_enable; + /* add to the list of available clocks */ down(&clocks_sem); @@ -267,7 +378,7 @@ int s3c2410_register_clock(struct clk *clk) /* initalise all the clocks */ -static int __init s3c2410_init_clocks(void) +int __init s3c2410_init_clocks(void) { struct clk *clkp = init_clocks; int ptr; @@ -277,12 +388,29 @@ static int __init s3c2410_init_clocks(void) /* initialise the main system clocks */ - clk_h.rate = s3c2410_hclk; - clk_p.rate = s3c2410_pclk; - clk_f.rate = s3c2410_fclk; - - /* set the enabled clocks to a minimal (known) state */ - __raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON); + clk_h.rate = s3c24xx_hclk; + clk_p.rate = s3c24xx_pclk; + clk_f.rate = s3c24xx_fclk; + + /* it looks like just setting the register here is not good + * enough, and causes the odd hang at initial boot time, so + * do all of them indivdually. + * + * I think disabling the LCD clock if the LCD is active is + * very dangerous, and therefore the bootloader should be + * careful to not enable the LCD clock if it is not needed. + * + * and of course, this looks neater + */ + + s3c2410_clk_enable(S3C2410_CLKCON_NAND, 0); + s3c2410_clk_enable(S3C2410_CLKCON_USBH, 0); + s3c2410_clk_enable(S3C2410_CLKCON_USBD, 0); + s3c2410_clk_enable(S3C2410_CLKCON_ADC, 0); + s3c2410_clk_enable(S3C2410_CLKCON_IIC, 0); + s3c2410_clk_enable(S3C2410_CLKCON_SPI, 0); + + /* assume uart clocks are correctly setup */ /* register our clocks */ @@ -306,5 +434,4 @@ static int __init s3c2410_init_clocks(void) return 0; } -arch_initcall(s3c2410_init_clocks); diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index 4c7b94e87..f66d901ad 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h @@ -2,7 +2,7 @@ * linux/arch/arm/mach-s3c2410/clock.h * * Copyright (c) 2004 Simtec Electronics - * Written by Ben Dooks, + * Written by Ben Dooks, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,7 +14,34 @@ struct clk { struct module *owner; struct clk *parent; const char *name; + int id; atomic_t used; unsigned long rate; unsigned long ctrlbit; + int (*enable)(struct clk *, int enable); }; + +/* other clocks which may be registered by board support */ + +extern struct clk s3c24xx_dclk0; +extern struct clk s3c24xx_dclk1; +extern struct clk s3c24xx_clkout0; +extern struct clk s3c24xx_clkout1; +extern struct clk s3c24xx_uclk; + +/* processor clock settings, in Hz */ + +extern unsigned long s3c24xx_xtal; +extern unsigned long s3c24xx_pclk; +extern unsigned long s3c24xx_hclk; +extern unsigned long s3c24xx_fclk; + +/* exports for arch/arm/mach-s3c2410 + * + * Please DO NOT use these outside of arch/arm/mach-s3c2410 +*/ + +extern int s3c2410_clkcon_enable(struct clk *clk, int enable); +extern int s3c2410_register_clock(struct clk *clk); +extern int s3c2410_init_clocks(void); + diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c index 42eec7912..f55701776 100644 --- a/arch/arm/mach-s3c2410/cpu.c +++ b/arch/arm/mach-s3c2410/cpu.c @@ -38,6 +38,7 @@ #include #include "cpu.h" +#include "clock.h" #include "s3c2410.h" #include "s3c2440.h" @@ -65,7 +66,7 @@ static struct cpu_table cpu_ids[] __initdata = { .name = name_s3c2410 }, { - .idcode = 0x3241002, + .idcode = 0x32410002, .idmask = 0xffffffff, .map_io = s3c2410_map_io, .init = s3c2410_init, @@ -104,7 +105,7 @@ s3c_lookup_cpu(unsigned long idcode) int count; tab = cpu_ids; - for (count = 0; count < ARRAY_SIZE(cpu_ids); count++) { + for (count = 0; count < ARRAY_SIZE(cpu_ids); count++, tab++) { if ((idcode & tab->idmask) == tab->idcode) return tab; } @@ -112,6 +113,26 @@ s3c_lookup_cpu(unsigned long idcode) return NULL; } +/* board information */ + +static struct s3c24xx_board *board; + +void s3c24xx_set_board(struct s3c24xx_board *b) +{ + int i; + + board = b; + + if (b->clocks_count != 0) { + struct clk **ptr = b->clocks;; + + for (i = b->clocks_count; i > 0; i--, ptr++) + s3c2410_register_clock(*ptr); + } +} + +/* cpu information */ + static struct cpu_table *cpu; void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) @@ -141,12 +162,35 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) static int __init s3c_arch_init(void) { + int ret; + // do the correct init for cpu if (cpu == NULL) panic("s3c_arch_init: NULL cpu\n"); - return (cpu->init)(); + ret = (cpu->init)(); + if (ret != 0) + return ret; + + if (board != NULL) { + struct platform_device **ptr = board->devices; + int i; + + for (i = 0; i < board->devices_count; i++, ptr++) { + ret = platform_device_register(*ptr); + + if (ret) { + printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr); + } + } + + /* mask any error, we may not need all these board + * devices */ + ret = 0; + } + + return ret; } arch_initcall(s3c_arch_init); diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index b0053d76d..e0996d54e 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -11,6 +11,7 @@ * * Modifications: * 24-Aug-2004 BJD Start of generic S3C24XX support + * 18-Oct-2004 BJD Moved board struct into this file */ #define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE } @@ -39,3 +40,20 @@ extern void s3c2440_map_io(struct map_desc *mach_desc, int size); extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); +/* the board structure is used at first initialsation time + * to get info such as the devices to register for this + * board. This is done because platfrom_add_devices() cannot + * be called from the map_io entry. +*/ + +struct s3c24xx_board { + struct platform_device **devices; + unsigned int devices_count; + + struct clk **clocks; + unsigned int clocks_count; +}; + +extern void s3c24xx_set_board(struct s3c24xx_board *board); + + diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c index 7cf560cae..b1826df99 100644 --- a/arch/arm/mach-s3c2410/devs.c +++ b/arch/arm/mach-s3c2410/devs.c @@ -32,8 +32,14 @@ #include #include +#include + #include "devs.h" +/* Serial port registrations */ + +struct platform_device *s3c24xx_uart_devs[3]; + /* USB Host Controller */ static struct resource s3c_usb_resource[] = { diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 819e5af16..a382023a0 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-bast/dma.c * * (c) 2003,2004 Simtec Electronics - * Ben Dooks + * Ben Dooks * * S3C2410 DMA core * @@ -12,6 +12,9 @@ * published by the Free Software Foundation. * * Changelog: + * 18-Nov-2004 BJD Removed error for loading onto stopped channel + * 10-Nov-2004 BJD Ensure all external symbols exported for modules + * 10-Nov-2004 BJD Use sys_device and sysdev_class for power management * 08-Aug-2004 BJD Apply rmk's suggestions * 21-Jul-2004 BJD Ported to linux 2.6 * 12-Jul-2004 BJD Finished re-write and change of API @@ -38,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +56,7 @@ #include /* io map for dma */ -static void *dma_base; +static void __iomem *dma_base; /* dma channel state information */ s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; @@ -490,10 +494,6 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, } else if (chan->state == S3C2410_DMA_IDLE) { if (chan->flags & S3C2410_DMAF_AUTOSTART) { s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START); - } else { - printk(KERN_DEBUG "dma%d: cannot load onto stopped channel'n", chan->number); - local_irq_restore(flags); - return -EINVAL; } } @@ -501,6 +501,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, return 0; } +EXPORT_SYMBOL(s3c2410_dma_enqueue); + static inline void s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) { @@ -648,6 +650,9 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) break; + case S3C2410_DMALOAD_1LOADED_1RUNNING: + goto no_load; + default: printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n", chan->number, chan->load_state); @@ -668,6 +673,7 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) } } + no_load: return IRQ_HANDLED; } @@ -736,6 +742,8 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client, return 0; } +EXPORT_SYMBOL(s3c2410_dma_request); + /* s3c2410_dma_free * * release the given channel back to the system, will stop and flush @@ -780,6 +788,8 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) return 0; } +EXPORT_SYMBOL(s3c2410_dma_free); + static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) { unsigned long tmp; @@ -886,6 +896,7 @@ s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op) return -ENOENT; /* unknown, don't bother */ } +EXPORT_SYMBOL(s3c2410_dma_ctrl); /* DMA configuration for each channel * @@ -941,6 +952,7 @@ int s3c2410_dma_config(dmach_t channel, return 0; } +EXPORT_SYMBOL(s3c2410_dma_config); int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) { @@ -955,6 +967,9 @@ int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) return 0; } +EXPORT_SYMBOL(s3c2410_dma_setflags); + + /* do we need to protect the settings of the fields from * irq? */ @@ -972,6 +987,8 @@ int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) return 0; } +EXPORT_SYMBOL(s3c2410_dma_set_opfn); + int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) { s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; @@ -985,6 +1002,8 @@ int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) return 0; } +EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); + /* s3c2410_dma_devconfig * * configure the dma source/destination hardware type and address @@ -1042,12 +1061,57 @@ int s3c2410_dma_devconfig(int channel, return -EINVAL; } +EXPORT_SYMBOL(s3c2410_dma_devconfig); + +/* system device class */ + +#ifdef CONFIG_PM + +static int s3c2410_dma_suspend(struct sys_device *dev, u32 state) +{ + s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev); + + printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); + + if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) { + /* the dma channel is still working, which is probably + * a bad thing to do over suspend/resume. We stop the + * channel and assume that the client is either going to + * retry after resume, or that it is broken. + */ + + printk(KERN_INFO "dma: stopping channel %d due to suspend\n", + cp->number); + + s3c2410_dma_dostop(cp); + } + + return 0; +} + +static int s3c2410_dma_resume(struct sys_device *dev) +{ + return 0; +} + +#else +#define s3c2410_dma_suspend NULL +#define s3c2410_dma_resume NULL +#endif /* CONFIG_PM */ + +static struct sysdev_class dma_sysclass = { + set_kset_name("s3c24xx-dma"), + .suspend = s3c2410_dma_suspend, + .resume = s3c2410_dma_resume, +}; + /* initialisation code */ static int __init s3c2410_init_dma(void) { - int channel; s3c2410_dma_chan_t *cp; + int channel; + int ret; printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n"); @@ -1057,6 +1121,12 @@ static int __init s3c2410_init_dma(void) return -ENOMEM; } + ret = sysdev_class_register(&dma_sysclass); + if (ret != 0) { + printk(KERN_ERR "dma sysclass registration failed\n"); + goto err; + } + for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) { cp = &s3c2410_chans[channel]; @@ -1065,7 +1135,7 @@ static int __init s3c2410_init_dma(void) /* dma channel irqs are in order.. */ cp->number = channel; cp->irq = channel + IRQ_DMA0; - cp->regs = (unsigned long)dma_base + (channel*0x40); + cp->regs = dma_base + (channel*0x40); /* point current stats somewhere */ cp->stats = &cp->stats_store; @@ -1075,11 +1145,22 @@ static int __init s3c2410_init_dma(void) cp->load_timeout = 1<<18; - printk("DMA channel %d at %08lx, irq %d\n", + /* register system device */ + + cp->dev.cls = &dma_sysclass; + cp->dev.id = channel; + ret = sysdev_register(&cp->dev); + + printk("DMA channel %d at %p, irq %d\n", cp->number, cp->regs, cp->irq); } return 0; + + err: + iounmap(dma_base); + dma_base = NULL; + return ret; } __initcall(s3c2410_init_dma); diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c index 450b132af..129f29dbd 100644 --- a/arch/arm/mach-s3c2410/gpio.c +++ b/arch/arm/mach-s3c2410/gpio.c @@ -19,6 +19,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * Changelog + * 13-Sep-2004 BJD Implemented change of MISCCR + * 14-Sep-2004 BJD Added getpin call + * 14-Sep-2004 BJD Fixed bug in setpin() call + * 30-Sep-2004 BJD Fixed cfgpin() mask bug + * 01-Oct-2004 BJD Added getcfg() to get pin configuration + * 01-Oct-2004 BJD Fixed mask bug in pullup() call + * 01-Oct-2004 BJD Added getirq() to turn pin into irqno + * 04-Oct-2004 BJD Added irq filter controls for GPIO + * 05-Nov-2004 BJD EXPORT_SYMBOL() added for all code */ @@ -36,23 +46,20 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) { unsigned long base = S3C2410_GPIO_BASE(pin); - unsigned long shift = 1; - unsigned long mask = 3; + unsigned long mask; unsigned long con; unsigned long flags; if (pin < S3C2410_GPIO_BANKB) { - shift = 0; - mask = 1; + mask = 1 << S3C2410_GPIO_OFFSET(pin); + } else { + mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; } - mask <<= S3C2410_GPIO_OFFSET(pin); - local_irq_save(flags); - con = __raw_readl(base + 0x00); - - con &= mask << shift; + con = __raw_readl(base + 0x00); + con &= ~mask; con |= function; __raw_writel(con, base + 0x00); @@ -60,6 +67,24 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) local_irq_restore(flags); } +EXPORT_SYMBOL(s3c2410_gpio_cfgpin); + +unsigned int s3c2410_gpio_getcfg(unsigned int pin) +{ + unsigned long base = S3C2410_GPIO_BASE(pin); + unsigned long mask; + + if (pin < S3C2410_GPIO_BANKB) { + mask = 1 << S3C2410_GPIO_OFFSET(pin); + } else { + mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; + } + + return __raw_readl(base) & mask; +} + +EXPORT_SYMBOL(s3c2410_gpio_getcfg); + void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) { unsigned long base = S3C2410_GPIO_BASE(pin); @@ -73,13 +98,15 @@ void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) local_irq_save(flags); up = __raw_readl(base + 0x08); - up &= 1 << offs; + up &= ~(1L << offs); up |= to << offs; __raw_writel(up, base + 0x08); local_irq_restore(flags); } +EXPORT_SYMBOL(s3c2410_gpio_pullup); + void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) { unsigned long base = S3C2410_GPIO_BASE(pin); @@ -90,9 +117,95 @@ void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) local_irq_save(flags); dat = __raw_readl(base + 0x04); - dat &= 1 << offs; + dat &= ~(1 << offs); dat |= to << offs; __raw_writel(dat, base + 0x04); local_irq_restore(flags); } + +EXPORT_SYMBOL(s3c2410_gpio_setpin); + +unsigned int s3c2410_gpio_getpin(unsigned int pin) +{ + unsigned long base = S3C2410_GPIO_BASE(pin); + unsigned long offs = S3C2410_GPIO_OFFSET(pin); + + return __raw_readl(base + 0x04) & (1<< offs); +} + +EXPORT_SYMBOL(s3c2410_gpio_getpin); + +unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) +{ + unsigned long flags; + unsigned long misccr; + + local_irq_save(flags); + misccr = __raw_readl(S3C2410_MISCCR); + misccr &= ~clear; + misccr ^= change; + __raw_writel(misccr, S3C2410_MISCCR); + local_irq_restore(flags); + + return misccr; +} + +EXPORT_SYMBOL(s3c2410_modify_misccr); + +int s3c2410_gpio_getirq(unsigned int pin) +{ + if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23) + return -1; /* not valid interrupts */ + + if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) + return -1; /* not valid pin */ + + if (pin < S3C2410_GPF4) + return (pin - S3C2410_GPF0) + IRQ_EINT0; + + if (pin < S3C2410_GPG0) + return (pin - S3C2410_GPF4) + IRQ_EINT4; + + return (pin - S3C2410_GPG0) + IRQ_EINT8; +} + +EXPORT_SYMBOL(s3c2410_gpio_getirq); + +int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, + unsigned int config) +{ + unsigned long reg = S3C2410_EINFLT0; + unsigned long flags; + unsigned long val; + + if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15) + return -1; + + config &= 0xff; + + pin -= S3C2410_GPG8_EINT16; + reg += pin & ~3; + + local_irq_save(flags); + + /* update filter width and clock source */ + + val = __raw_readl(reg); + val &= ~(0xff << ((pin & 3) * 8)); + val |= config << ((pin & 3) * 8); + __raw_writel(val, reg); + + /* update filter enable */ + + val = __raw_readl(S3C2410_EXTINT2); + val &= ~(1 << ((pin * 4) + 3)); + val |= on << ((pin * 4) + 3); + __raw_writel(val, S3C2410_EXTINT2); + + local_irq_restore(flags); + + return 0; +} + +EXPORT_SYMBOL(s3c2410_gpio_irqfilter); diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 878b9740d..a8a48f743 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s3c2410/irq.c * - * Copyright (c) 2003 Simtec Electronics - * Ben Dooks + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks * * 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 @@ -17,8 +17,29 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - */ - + * Changelog: + * + * 22-Jul-2004 Ben Dooks + * Fixed compile warnings + * + * 22-Jul-2004 Roc Wu + * Fixed s3c_extirq_type + * + * 21-Jul-2004 Arnaud Patard (Rtp) + * Addition of ADC/TC demux + * + * 04-Oct-2004 Klaus Fetscher + * Fix for set_irq_type() on low EINT numbers + * + * 05-Oct-2004 Ben Dooks + * Tidy up KF's patch and sort out new release + * + * 05-Oct-2004 Ben Dooks + * Add support for power management controls + * + * 04-Nov-2004 Ben Dooks + * Fix standard IRQ wake for EINT0..4 and RTC +*/ #include #include @@ -34,15 +55,75 @@ #include #include -#include +#include -#if 0 -#include -#endif +#include "pm.h" #define irqdbf(x...) #define irqdbf2(x...) +#define EXTINT_OFF (IRQ_EINT4 - 4) + +/* wakeup irq control */ + +#ifdef CONFIG_PM + +/* state for IRQs over sleep */ + +/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources + * + * set bit to 1 in allow bitfield to enable the wakeup settings on it +*/ + +unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; +unsigned long s3c_irqwake_intmask = 0xffffffffL; +unsigned long s3c_irqwake_eintallow = 0x0000fff0L; +unsigned long s3c_irqwake_eintmask = 0xffffffffL; + +static int +s3c_irq_wake(unsigned int irqno, unsigned int state) +{ + unsigned long irqbit = 1 << (irqno - IRQ_EINT0); + + if (!(s3c_irqwake_intallow & irqbit)) + return -ENOENT; + + printk(KERN_INFO "wake %s for irq %d\n", + state ? "enabled" : "disabled", irqno); + + if (!state) + s3c_irqwake_intmask |= irqbit; + else + s3c_irqwake_intmask &= ~irqbit; + + return 0; +} + +static int +s3c_irqext_wake(unsigned int irqno, unsigned int state) +{ + unsigned long bit = 1L << (irqno - EXTINT_OFF); + + if (!(s3c_irqwake_eintallow & bit)) + return -ENOENT; + + printk(KERN_INFO "wake %s for irq %d\n", + state ? "enabled" : "disabled", irqno); + + if (!state) + s3c_irqwake_eintmask |= bit; + else + s3c_irqwake_eintmask &= ~bit; + + return 0; +} + +#else +#define s3c_irqext_wake NULL +#define s3c_irq_wake NULL +#endif + + static void s3c_irq_mask(unsigned int irqno) { @@ -96,21 +177,21 @@ s3c_irq_unmask(unsigned int irqno) static struct irqchip s3c_irq_level_chip = { .ack = s3c_irq_maskack, .mask = s3c_irq_mask, - .unmask = s3c_irq_unmask + .unmask = s3c_irq_unmask, + .wake = s3c_irq_wake }; static struct irqchip s3c_irq_chip = { .ack = s3c_irq_ack, .mask = s3c_irq_mask, - .unmask = s3c_irq_unmask + .unmask = s3c_irq_unmask, + .wake = s3c_irq_wake }; /* S3C2410_EINTMASK * S3C2410_EINTPEND */ -#define EXTINT_OFF (IRQ_EINT4 - 4) - static void s3c_irqext_mask(unsigned int irqno) { @@ -177,12 +258,84 @@ s3c_irqext_unmask(unsigned int irqno) s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23); } -/* todo - put type handler in here */ - static int s3c_irqext_type(unsigned int irq, unsigned int type) { - irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type); + unsigned long extint_reg; + unsigned long gpcon_reg; + unsigned long gpcon_offset, extint_offset; + unsigned long newvalue = 0, value; + + if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) + { + gpcon_reg = S3C2410_GPFCON; + extint_reg = S3C2410_EXTINT0; + gpcon_offset = (irq - IRQ_EINT0) * 2; + extint_offset = (irq - IRQ_EINT0) * 4; + } + else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) + { + gpcon_reg = S3C2410_GPFCON; + extint_reg = S3C2410_EXTINT0; + gpcon_offset = (irq - (EXTINT_OFF)) * 2; + extint_offset = (irq - (EXTINT_OFF)) * 4; + } + else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) + { + gpcon_reg = S3C2410_GPGCON; + extint_reg = S3C2410_EXTINT1; + gpcon_offset = (irq - IRQ_EINT8) * 2; + extint_offset = (irq - IRQ_EINT8) * 4; + } + else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23)) + { + gpcon_reg = S3C2410_GPGCON; + extint_reg = S3C2410_EXTINT2; + gpcon_offset = (irq - IRQ_EINT8) * 2; + extint_offset = (irq - IRQ_EINT16) * 4; + } else + return -1; + + /* Set the GPIO to external interrupt mode */ + value = __raw_readl(gpcon_reg); + value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); + __raw_writel(value, gpcon_reg); + + /* Set the external interrupt to pointed trigger type */ + switch (type) + { + case IRQT_NOEDGE: + printk(KERN_WARNING "No edge setting!\n"); + break; + + case IRQT_RISING: + newvalue = S3C2410_EXTINT_RISEEDGE; + break; + + case IRQT_FALLING: + newvalue = S3C2410_EXTINT_FALLEDGE; + break; + + case IRQT_BOTHEDGE: + newvalue = S3C2410_EXTINT_BOTHEDGE; + break; + + case IRQT_LOW: + newvalue = S3C2410_EXTINT_LOWLEV; + break; + + case IRQT_HIGH: + newvalue = S3C2410_EXTINT_HILEV; + break; + + default: + printk(KERN_ERR "No such irq type %d", type); + return -1; + } + + value = __raw_readl(extint_reg); + value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset); + __raw_writel(value, extint_reg); return 0; } @@ -191,7 +344,16 @@ static struct irqchip s3c_irqext_chip = { .mask = s3c_irqext_mask, .unmask = s3c_irqext_unmask, .ack = s3c_irqext_ack, - .type = s3c_irqext_type + .type = s3c_irqext_type, + .wake = s3c_irqext_wake +}; + +static struct irqchip s3c_irq_eint0t4 = { + .ack = s3c_irq_ack, + .mask = s3c_irq_mask, + .unmask = s3c_irq_unmask, + .wake = s3c_irq_wake, + .type = s3c_irqext_type, }; /* mask values for the parent registers for each of the interrupt types */ @@ -368,37 +530,37 @@ static struct irqchip s3c_irq_adc = { .ack = s3c_irq_adc_ack, }; -#if 0 -/* LCD (todo) */ - -static void -s3c_irq_lcd_mask(unsigned int irqno) +/* irq demux for adc */ +static void s3c_irq_demux_adc(unsigned int irq, + struct irqdesc *desc, + struct pt_regs *regs) { + unsigned int subsrc, submsk; + unsigned int offset = 9; + struct irqdesc *mydesc; -} - -static void -s3c_irq_lcd_unmask(unsigned int irqno) -{ + /* read the current pending interrupts, and the mask + * for what it is available */ -} + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); -static void -s3c_irq_lcd_ack(unsigned int irqno) -{ + subsrc &= ~submsk; + subsrc >>= offset; + subsrc &= 3; + if (subsrc != 0) { + if (subsrc & 1) { + mydesc = irq_desc + IRQ_TC; + mydesc->handle( IRQ_TC, mydesc, regs); + } + if (subsrc & 2) { + mydesc = irq_desc + IRQ_ADC; + mydesc->handle(IRQ_ADC, mydesc, regs); + } + } } -static struct irqchip s3c_irq_lcd = { - .mask = s3c_irq_lcd_mask, - .unmask = s3c_irq_lcd_unmask, - .ack = s3c_irq_lcd_ack, -}; -#endif - -/* irq demux */ - - static void s3c_irq_demux_uart(unsigned int start, struct pt_regs *regs) { @@ -466,11 +628,15 @@ s3c_irq_demux_uart2(unsigned int irq, s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs); } - +/* s3c2410_init_irq + * + * Initialise S3C2410 IRQ system +*/ void __init s3c2410_init_irq(void) { unsigned long pend; + unsigned long last; int irqno; int i; @@ -478,48 +644,51 @@ void __init s3c2410_init_irq(void) /* first, clear all interrupts pending... */ + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_EINTPEND); - if (pend == 0) + + if (pend == 0 || pend == last) break; + __raw_writel(pend, S3C2410_EINTPEND); printk("irq: clearing pending ext status %08x\n", (int)pend); + last = pend; } + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_INTPND); - if (pend == 0) + + if (pend == 0 || pend == last) break; + __raw_writel(pend, S3C2410_SRCPND); __raw_writel(pend, S3C2410_INTPND); printk("irq: clearing pending status %08x\n", (int)pend); + last = pend; } + last = 0; for (i = 0; i < 4; i++) { pend = __raw_readl(S3C2410_SUBSRCPND); - if (pend == 0) + if (pend == 0 || pend == last) break; printk("irq: clearing subpending status %08x\n", (int)pend); __raw_writel(pend, S3C2410_SUBSRCPND); + last = pend; } /* register the main interrupts */ irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); - for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) { + for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { /* set all the s3c2410 internal irqs */ switch (irqno) { - - case IRQ_EINT4t7: - case IRQ_EINT8t23: - /* these are already dealt with, so should never - * appear */ - break; - /* deal with the special IRQs (cascaded) */ case IRQ_UART0: @@ -549,12 +718,18 @@ void __init s3c2410_init_irq(void) set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); - //set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_); - //set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_); + set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); /* external interrupts */ + for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { + irqdbf("registering irq %d (ext int)\n", irqno); + set_irq_chip(irqno, &s3c_irq_eint0t4); + set_irq_handler(irqno, do_edge_IRQ); + set_irq_flags(irqno, IRQF_VALID); + } + for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { irqdbf("registering irq %d (extended s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irqext_chip); diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 2268ab3c7..7e6257c86 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/mach-bast.c * - * Copyright (c) 2003 Simtec Electronics + * Copyright (c) 2003,2004 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -10,11 +10,16 @@ * published by the Free Software Foundation. * * Modifications: + * 14-Sep-2004 BJD USB power control + * 20-Aug-2004 BJD Added s3c2410_board struct + * 18-Aug-2004 BJD Added platform devices from default set * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL * 05-Sep-2003 BJD Moved to v2.6 kernel * 06-Jan-2003 BJD Updates for * 18-Jan-2003 BJD Added serial port configuration + * 05-Oct-2004 BJD Power management code + * 04-Nov-2004 BJD Updated serial port clocks */ #include @@ -23,12 +28,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -37,8 +44,17 @@ //#include #include +#include +#include #include "s3c2410.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "usb-simtec.h" +#include "pm.h" + +#define COPYRIGHT ", (c) 2004 Simtec Electronics" /* macros for virtual address mods for the io space entries */ #define VA_C5(item) ((item) + BAST_VAM_CS5) @@ -139,62 +155,156 @@ static struct map_desc bast_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -/* base baud rate for all our UARTs */ -static unsigned long bast_serial_clock = 24*1000*1000; +static struct s3c24xx_uart_clksrc bast_serial_clocks[] = { + [0] = { + .name = "uclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, + [1] = { + .name = "pclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0. + } +}; + static struct s3c2410_uartcfg bast_uartcfgs[] = { [0] = { .hwport = 0, .flags = 0, - .clock = &bast_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = bast_serial_clocks, + .clocks_size = ARRAY_SIZE(bast_serial_clocks) }, [1] = { .hwport = 1, .flags = 0, - .clock = &bast_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = bast_serial_clocks, + .clocks_size = ARRAY_SIZE(bast_serial_clocks) }, /* port 2 is not actually used */ [2] = { .hwport = 2, .flags = 0, - .clock = &bast_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = bast_serial_clocks, + .clocks_size = ARRAY_SIZE(bast_serial_clocks) } }; +/* NOR Flash on BAST board */ + +static struct resource bast_nor_resource[] = { + [0] = { + .start = S3C2410_CS1 + 0x4000000, + .end = S3C2410_CS1 + 0x4000000 + (32*1024*1024) - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device bast_device_nor = { + .name = "bast-nor", + .id = -1, + .num_resources = ARRAY_SIZE(bast_nor_resource), + .resource = bast_nor_resource, +}; + +/* Standard BAST devices */ + +static struct platform_device *bast_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, + &s3c_device_rtc, + &bast_device_nor +}; + +static struct clk *bast_clocks[] = { + &s3c24xx_dclk0, + &s3c24xx_dclk1, + &s3c24xx_clkout0, + &s3c24xx_clkout1, + &s3c24xx_uclk, +}; + +static struct s3c24xx_board bast_board __initdata = { + .devices = bast_devices, + .devices_count = ARRAY_SIZE(bast_devices), + .clocks = bast_clocks, + .clocks_count = ARRAY_SIZE(bast_clocks) +}; void __init bast_map_io(void) { - s3c2410_map_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); - s3c2410_uartcfgs = bast_uartcfgs; + /* initialise the clocks */ + + s3c24xx_dclk0.parent = NULL; + s3c24xx_dclk0.rate = 12*1000*1000; + + s3c24xx_dclk1.parent = NULL; + s3c24xx_dclk1.rate = 24*1000*1000; + + s3c24xx_clkout0.parent = &s3c24xx_dclk0; + s3c24xx_clkout1.parent = &s3c24xx_dclk1; + + s3c24xx_uclk.parent = &s3c24xx_clkout1; + + s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); + s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); + s3c24xx_set_board(&bast_board); + usb_simtec_init(); } void __init bast_init_irq(void) { - //llprintk("bast_init_irq:\n"); - s3c2410_init_irq(); - } -void __init bast_init_time(void) +#ifdef CONFIG_PM + +/* bast_init_machine + * + * enable the power management functions for the EB2410ITX +*/ + +static __init void bast_init_machine(void) { - s3c2410_init_time(); + unsigned long gstatus4; + + printk(KERN_INFO "BAST Power Manangement" COPYRIGHT "\n"); + + gstatus4 = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30; + gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28; + gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK); + + __raw_writel(gstatus4, S3C2410_GSTATUS4); + + s3c2410_pm_init(); } +#else +#define bast_init_machine NULL +#endif + + MACHINE_START(BAST, "Simtec-BAST") MAINTAINER("Ben Dooks ") BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(bast_map_io) INITIRQ(bast_init_irq) - INITTIME(bast_init_time) + .init_machine = bast_init_machine, + .timer = &s3c2410_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 0a9ba135b..8d0f08450 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -1,6 +1,6 @@ -/* linux/arch/arm/mach-s3c2410/mach-ipaq.c +/* linux/arch/arm/mach-s3c2410/mach-h1940.c * - * Copyright (c) 2003 Simtec Electronics + * Copyright (c) 2003,2004 Simtec Electronics * Ben Dooks * * http://www.handhelds.org/projects/h1940.html @@ -16,6 +16,10 @@ * 06-Jan-2003 BJD Updates for * 18-Jan-2003 BJD Added serial port configuration * 17-Feb-2003 BJD Copied to mach-ipaq.c + * 21-Aug-2004 BJD Added struct s3c2410_board + * 04-Sep-2004 BJD Changed uart init, renamed ipaq_ -> h1940_ + * 18-Oct-2004 BJD Updated new board structure name + * 04-Nov-2004 BJD Change for new serial clock */ #include @@ -38,9 +42,14 @@ //#include #include +#include + #include "s3c2410.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" -static struct map_desc ipaq_iodesc[] __initdata = { +static struct map_desc h1940_iodesc[] __initdata = { /* nothing here yet */ }; @@ -48,11 +57,10 @@ static struct map_desc ipaq_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg ipaq_uartcfgs[] = { +static struct s3c2410_uartcfg h1940_uartcfgs[] = { [0] = { .hwport = 0, .flags = 0, - .clock = &s3c2410_pclk, .ucon = 0x3c5, .ulcon = 0x03, .ufcon = 0x51, @@ -60,7 +68,6 @@ static struct s3c2410_uartcfg ipaq_uartcfgs[] = { [1] = { .hwport = 1, .flags = 0, - .clock = &s3c2410_pclk, .ucon = 0x245, .ulcon = 0x03, .ufcon = 0x00, @@ -69,7 +76,7 @@ static struct s3c2410_uartcfg ipaq_uartcfgs[] = { [2] = { .hwport = 2, .flags = 0, - .clock = &s3c2410_pclk, + .uart_flags = UPF_CONS_FLOW, .ucon = 0x3c5, .ulcon = 0x43, .ufcon = 0x51, @@ -77,30 +84,39 @@ static struct s3c2410_uartcfg ipaq_uartcfgs[] = { }; -void __init ipaq_map_io(void) -{ - s3c2410_map_io(ipaq_iodesc, ARRAY_SIZE(ipaq_iodesc)); - s3c2410_uartcfgs = ipaq_uartcfgs; -} -void __init ipaq_init_irq(void) -{ - //llprintk("ipaq_init_irq:\n"); - s3c2410_init_irq(); +static struct platform_device *h1940_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; +static struct s3c24xx_board h1940_board __initdata = { + .devices = h1940_devices, + .devices_count = ARRAY_SIZE(h1940_devices) +}; + +void __init h1940_map_io(void) +{ + s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); + s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); + s3c24xx_set_board(&h1940_board); } -void __init ipaq_init_time(void) +void __init h1940_init_irq(void) { - s3c2410_init_time(); + s3c2410_init_irq(); + } MACHINE_START(H1940, "IPAQ-H1940") MAINTAINER("Ben Dooks ") BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART) BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) - MAPIO(ipaq_map_io) - INITIRQ(ipaq_init_irq) - INITTIME(ipaq_init_time) + MAPIO(h1940_map_io) + INITIRQ(h1940_init_irq) + .timer = &s3c2410_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index bfadbd425..61c3879f6 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -47,7 +47,8 @@ #include #include "s3c2410.h" - +#include "devs.h" +#include "cpu.h" static struct map_desc smdk2410_iodesc[] __initdata = { /* nothing here yet */ @@ -57,14 +58,10 @@ static struct map_desc smdk2410_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -/* base baud rate for all our UARTs */ -static unsigned long smdk2410_serial_clock = 24*1000*1000; - static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { [0] = { .hwport = 0, .flags = 0, - .clock = &smdk2410_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, @@ -72,7 +69,6 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { [1] = { .hwport = 1, .flags = 0, - .clock = &smdk2410_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, @@ -80,18 +76,30 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { [2] = { .hwport = 2, .flags = 0, - .clock = &smdk2410_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, } }; +static struct platform_device *smdk2410_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c24xx_board smdk2410_board __initdata = { + .devices = smdk2410_devices, + .devices_count = ARRAY_SIZE(smdk2410_devices) +}; void __init smdk2410_map_io(void) { - s3c2410_map_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); - s3c2410_uartcfgs = smdk2410_uartcfgs; + s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); + s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); + s3c24xx_set_board(&smdk2410_board); } void __init smdk2410_init_irq(void) @@ -99,11 +107,6 @@ void __init smdk2410_init_irq(void) s3c2410_init_irq(); } -void __init smdk2410_init_time(void) -{ - s3c2410_init_time(); -} - MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch * to SMDK2410 */ MAINTAINER("Jonas Dietsche") @@ -111,5 +114,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(smdk2410_map_io) INITIRQ(smdk2410_init_irq) - INITTIME(smdk2410_init_time) + .timer = &s3c2410_timer, MACHINE_END + + diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index aae341c69..4079af11a 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -11,14 +11,13 @@ * published by the Free Software Foundation. * * Modifications: + * 14-Sep-2004 BJD USB Power control + * 04-Sep-2004 BJD Added new uart init, and io init + * 21-Aug-2004 BJD Added struct s3c2410_board * 06-Aug-2004 BJD Fixed call to time initialisation - * 12-Jul-2004 BJD Renamed machine - * 16-May-2003 BJD Created initial version - * 16-Aug-2003 BJD Fixed header files and copyright, added URL - * 05-Sep-2003 BJD Moved to v2.6 kernel - * 06-Jan-2003 BJD Updates for - * 18-Jan-2003 BJD Added serial port configuration * 05-Apr-2004 BJD Copied to make mach-vr1000.c + * 18-Oct-2004 BJD Updated board struct + * 04-Nov-2004 BJD Clock and serial configuration update */ #include @@ -44,6 +43,10 @@ #include #include "s3c2410.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "usb-simtec.h" /* macros for virtual address mods for the io space entries */ #define VA_C5(item) ((item) + BAST_VAM_CS5) @@ -112,55 +115,103 @@ static struct map_desc vr1000_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -/* base baud rate for all our UARTs */ -static unsigned long vr1000_serial_clock = 3692307; +/* uart clock source(s) */ + +static struct s3c24xx_uart_clksrc vr1000_serial_clocks[] = { + [0] = { + .name = "uclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0, + }, + [1] = { + .name = "pclk", + .divisor = 1, + .min_baud = 0, + .max_baud = 0. + } +}; static struct s3c2410_uartcfg vr1000_uartcfgs[] = { [0] = { .hwport = 0, .flags = 0, - .clock = &vr1000_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = vr1000_serial_clocks, + .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), }, [1] = { .hwport = 1, .flags = 0, - .clock = &vr1000_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = vr1000_serial_clocks, + .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), }, /* port 2 is not actually used */ [2] = { .hwport = 2, .flags = 0, - .clock = &vr1000_serial_clock, .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, + .clocks = vr1000_serial_clocks, + .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), + } }; +static struct platform_device *vr1000_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct clk *vr1000_clocks[] = { + &s3c24xx_dclk0, + &s3c24xx_dclk1, + &s3c24xx_clkout0, + &s3c24xx_clkout1, + &s3c24xx_uclk, +}; + +static struct s3c24xx_board vr1000_board __initdata = { + .devices = vr1000_devices, + .devices_count = ARRAY_SIZE(vr1000_devices), + .clocks = vr1000_clocks, + .clocks_count = ARRAY_SIZE(vr1000_clocks), +}; + void __init vr1000_map_io(void) { - s3c2410_map_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); - s3c2410_uartcfgs = vr1000_uartcfgs; -} + /* initialise clock sources */ -void __init vr1000_init_irq(void) -{ - //llprintk("vr1000init_irq:\n"); + s3c24xx_dclk0.parent = NULL; + s3c24xx_dclk0.rate = 12*1000*1000; - s3c2410_init_irq(); + s3c24xx_dclk1.parent = NULL; + s3c24xx_dclk1.rate = 3692307; + + s3c24xx_clkout0.parent = &s3c24xx_dclk0; + s3c24xx_clkout1.parent = &s3c24xx_dclk1; + + s3c24xx_uclk.parent = &s3c24xx_clkout1; + s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); + s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); + s3c24xx_set_board(&vr1000_board); + usb_simtec_init(); } -void __init vr1000_init_time(void) +void __init vr1000_init_irq(void) { - s3c2410_init_time(); + s3c2410_init_irq(); } MACHINE_START(VR1000, "Thorcom-VR1000") @@ -169,5 +220,5 @@ MACHINE_START(VR1000, "Thorcom-VR1000") BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(vr1000_map_io) INITIRQ(vr1000_init_irq) - INITTIME(vr1000_init_time) + .timer = &s3c2410_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index bfd843cef..66a34913c 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -1,7 +1,7 @@ /* linux/arch/arm/mach-s3c2410/s3c2410.c * - * Copyright (c) 2003 Simtec Electronics - * Ben Dooks + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ * @@ -13,7 +13,10 @@ * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL * 05-Sep-2003 BJD Moved to kernel v2.6 - * 18-Jan-2003 BJD Added serial port configuration + * 18-Jan-2004 BJD Added serial port configuration + * 21-Aug-2004 BJD Added new struct s3c2410_board handler + * 28-Sep-2004 BJD Updates for new serial port bits + * 04-Nov-2004 BJD Updated UART configuration process */ #include @@ -35,45 +38,22 @@ #include #include -int s3c2410_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ - -/* serial port setup */ - -struct s3c2410_uartcfg *s3c2410_uartcfgs; - -/* clock info */ +#include "s3c2410.h" +#include "cpu.h" +#include "clock.h" -unsigned long s3c2410_fclk; -unsigned long s3c2410_hclk; -unsigned long s3c2410_pclk; - -#ifndef MHZ -#define MHZ (1000*1000) -#endif - -#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000) +int s3c2410_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ -#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE } +/* Initial IO mappings */ static struct map_desc s3c2410_iodesc[] __initdata = { - IODESC_ENT(IRQ), - IODESC_ENT(MEMCTRL), - IODESC_ENT(USBHOST), - IODESC_ENT(DMA), - IODESC_ENT(CLKPWR), - IODESC_ENT(LCD), - IODESC_ENT(NAND), - IODESC_ENT(UART), - IODESC_ENT(TIMER), - IODESC_ENT(USBDEV), - IODESC_ENT(WATCHDOG), - IODESC_ENT(IIC), - IODESC_ENT(IIS), - IODESC_ENT(GPIO), - IODESC_ENT(RTC), - IODESC_ENT(ADC), - IODESC_ENT(SPI), - IODESC_ENT(SDI) + IODESC_ENT(USBHOST), + IODESC_ENT(CLKPWR), + IODESC_ENT(LCD), + IODESC_ENT(UART), + IODESC_ENT(TIMER), + IODESC_ENT(ADC), + IODESC_ENT(WATCHDOG) }; static struct resource s3c_uart0_resource[] = { @@ -146,45 +126,75 @@ static struct platform_device *uart_devices[] __initdata = { &s3c_uart2 }; -void __init s3c2410_map_io(struct map_desc *mach_desc, int size) +/* store our uart devices for the serial driver console */ +struct platform_device *s3c2410_uart_devices[3]; + +static int s3c2410_uart_count = 0; + +/* uart registration process */ + +void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + struct platform_device *platdev; + int uart; + + for (uart = 0; uart < no; uart++, cfg++) { + platdev = uart_devices[cfg->hwport]; + + s3c24xx_uart_devs[uart] = platdev; + platdev->dev.platform_data = cfg; + } + + s3c2410_uart_count = uart; +} + +/* s3c2410_map_io + * + * register the standard cpu IO areas, and any passed in from the + * machine specific initialisation. + * + * this function also sets the initial clock frequencies from the + * settings passed in +*/ + +void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size) { unsigned long tmp; /* register our io-tables */ iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); - iotable_init(mach_desc, size); + iotable_init(mach_desc, mach_size); /* now we've got our machine bits initialised, work out what * clocks we've got */ - s3c2410_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), 12*MHZ); + s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), + s3c24xx_xtal); tmp = __raw_readl(S3C2410_CLKDIVN); - //printk("tmp=%08x, fclk=%d\n", tmp, s3c2410_fclk); /* work out clock scalings */ - s3c2410_hclk = s3c2410_fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); - s3c2410_pclk = s3c2410_hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); + s3c24xx_hclk = s3c24xx_fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); + s3c24xx_pclk = s3c24xx_hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); /* print brieft summary of clocks, etc */ printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(s3c2410_fclk), print_mhz(s3c2410_hclk), - print_mhz(s3c2410_pclk)); -} + print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk), + print_mhz(s3c24xx_pclk)); + /* initialise the clocks here, to allow other things like the + * console to use them + */ -static int __init s3c2410_init(void) -{ - int ret; + s3c2410_init_clocks(); +} +int __init s3c2410_init(void) +{ printk("S3C2410: Initialising architecture\n"); - ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices)); - - return ret; + return platform_add_devices(s3c24xx_uart_devs, s3c2410_uart_count); } - -arch_initcall(s3c2410_init); diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index 862a7c86d..93395637d 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -1,8 +1,30 @@ +/* arch/arm/mach-s3c2410/s3c2410.h + * + * Copyright (c) 2004 Simtec Electronics + * Ben Dooks + * + * Header file for s3c2410 machine directory + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 18-Aug-2004 BJD Created initial version + * 20-Aug-2004 BJD Added s3c2410_board struct + * 04-Sep-2004 BJD Added s3c2410_init_uarts() call + * 17-Oct-2004 BJD Moved board out to cpu +*/ +struct s3c2410_uartcfg; extern void s3c2410_map_io(struct map_desc *, int count); +extern void s3c2410_init_uarts(struct s3c2410_uartcfg *, int no); + extern void s3c2410_init_irq(void); -extern void s3c2410_init_time(void); +struct sys_timer; +extern struct sys_timer s3c2410_timer; +extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c index fb3078379..bc11fbfb2 100644 --- a/arch/arm/mach-s3c2410/s3c2440-dsc.c +++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c @@ -11,15 +11,14 @@ * * Modifications: * 29-Aug-2004 BJD Start of drive-strength control + * 09-Nov-2004 BJD Added symbol export */ #include #include #include -#include -#include #include -#include +#include #include #include @@ -55,3 +54,5 @@ int s3c2440_set_dsc(unsigned int pin, unsigned int value) local_irq_restore(flags); return 0; } + +EXPORT_SYMBOL(s3c2440_set_dsc); diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c index f4bb10c58..7e50eb9d0 100644 --- a/arch/arm/mach-s3c2410/s3c2440.c +++ b/arch/arm/mach-s3c2410/s3c2440.c @@ -10,7 +10,12 @@ * published by the Free Software Foundation. * * Modifications: - * 24-Aug-2004 BJD Start of s3c2440 support + * 24-Aug-2004 BJD Start of s3c2440 support + * 12-Oct-2004 BJD Moved clock info out to clock.c + * 01-Nov-2004 BJD Fixed clock build code + * 09-Nov-2004 BJD Added sysdev for power management + * 04-Nov-2004 BJD New serial registration + * 15-Nov-2004 BJD Rename the i2c device for the s3c2440 */ #include @@ -20,6 +25,7 @@ #include #include #include +#include #include #include @@ -28,24 +34,25 @@ #include #include #include +#include #include #include +#include +#include +#include #include "s3c2440.h" +#include "clock.h" +#include "devs.h" #include "cpu.h" +#include "pm.h" int s3c2440_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ /* clock info */ - -unsigned long s3c2440_baseclk = 12*1000*1000; /* assume base is 12MHz */ unsigned long s3c2440_hdiv; -unsigned long s3c2440_fclk; -unsigned long s3c2440_hclk; -unsigned long s3c2440_pclk; - static struct map_desc s3c2440_iodesc[] __initdata = { IODESC_ENT(USBHOST), IODESC_ENT(CLKPWR), @@ -124,9 +131,79 @@ static struct platform_device *uart_devices[] __initdata = { &s3c_uart2 }; +/* uart initialisation */ + +static int __initdata s3c2440_uart_count; + +void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + struct platform_device *platdev; + int uart; + + for (uart = 0; uart < no; uart++, cfg++) { + platdev = uart_devices[cfg->hwport]; + + s3c24xx_uart_devs[uart] = platdev; + platdev->dev.platform_data = cfg; + } + + s3c2440_uart_count = uart; +} + +/* s3c2440 specific clock sources */ + +static struct clk s3c2440_clk_cam = { + .name = "camera", + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2440_CLKCON_CAMERA +}; + +static struct clk s3c2440_clk_ac97 = { + .name = "ac97", + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2440_CLKCON_CAMERA +}; + +#ifdef CONFIG_PM + +struct sleep_save s3c2440_sleep[] = { + SAVE_ITEM(S3C2440_DSC0), + SAVE_ITEM(S3C2440_DSC1), + SAVE_ITEM(S3C2440_GPJDAT), + SAVE_ITEM(S3C2440_GPJCON), + SAVE_ITEM(S3C2440_GPJUP) +}; + +static int s3c2440_suspend(struct sys_device *dev, u32 state) +{ + s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep)); + return 0; +} + +static int s3c2440_resume(struct sys_device *dev) +{ + s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep)); + return 0; +} + +#else +#define s3c2440_suspend NULL +#define s3c2440_resume NULL +#endif + +static struct sysdev_class s3c2440_sysclass = { + set_kset_name("s3c2440-core"), + .suspend = s3c2440_suspend, + .resume = s3c2440_resume +}; + +static struct sys_device s3c2440_sysdev = { + .cls = &s3c2440_sysclass, +}; + void __init s3c2440_map_io(struct map_desc *mach_desc, int size) { - unsigned long tmp; + unsigned long clkdiv; unsigned long camdiv; /* register our io-tables */ @@ -137,15 +214,15 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size) /* now we've got our machine bits initialised, work out what * clocks we've got */ - s3c2440_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), - s3c2440_baseclk); + s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), + s3c24xx_xtal) * 2; - tmp = __raw_readl(S3C2410_CLKDIVN); + clkdiv = __raw_readl(S3C2410_CLKDIVN); camdiv = __raw_readl(S3C2440_CAMDIVN); /* work out clock scalings */ - switch (tmp & S3C2440_CLKDIVN_HDIVN_MASK) { + switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { case S3C2440_CLKDIVN_HDIVN_1: s3c2440_hdiv = 1; break; @@ -159,21 +236,40 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size) break; case S3C2440_CLKDIVN_HDIVN_3_6: - s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 6 : 3; + s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; break; } - s3c2440_hclk = s3c2440_fclk / s3c2440_hdiv; - s3c2440_pclk = s3c2440_hclk / ((tmp & S3C2440_CLKDIVN_PDIVN) ? 2 : 1); + s3c24xx_hclk = s3c24xx_fclk / s3c2440_hdiv; + s3c24xx_pclk = s3c24xx_hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); /* print brieft summary of clocks, etc */ printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(s3c2440_fclk), print_mhz(s3c2440_hclk), - print_mhz(s3c2440_pclk)); -} + print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk), + print_mhz(s3c24xx_pclk)); + + /* initialise the clocks here, to allow other things like the + * console to use them, and to add new ones after the initialisation + */ + + s3c2410_init_clocks(); + + /* add s3c2440 specific clocks */ + + s3c2440_clk_cam.parent = clk_get(NULL, "hclk"); + s3c2440_clk_ac97.parent = clk_get(NULL, "pclk"); + s3c2410_register_clock(&s3c2440_clk_ac97); + s3c2410_register_clock(&s3c2440_clk_cam); + clk_disable(&s3c2440_clk_ac97); + clk_disable(&s3c2440_clk_cam); + + /* rename any peripherals used differing from the s3c2410 */ + + s3c_device_i2c.name = "s3c2440-i2c"; +} int __init s3c2440_init(void) { @@ -181,12 +277,15 @@ int __init s3c2440_init(void) printk("S3C2440: Initialising architecture\n"); - ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices)); - if (ret) - return ret; + ret = sysdev_class_register(&s3c2440_sysclass); + if (ret == 0) + ret = sysdev_register(&s3c2440_sysdev); - // todo: board specific inits? + if (ret != 0) + printk(KERN_ERR "failed to register sysdev for s3c2440\n"); + + if (ret == 0) + ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count); return ret; } - diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h index bf49a66d5..f2c9234c1 100644 --- a/arch/arm/mach-s3c2410/s3c2440.h +++ b/arch/arm/mach-s3c2410/s3c2440.h @@ -10,9 +10,14 @@ * published by the Free Software Foundation. * * Modifications: - * 24-Aug-2004 BJD Start of S3C2440 CPU support + * 24-Aug-2004 BJD Start of S3C2440 CPU support + * 04-Nov-2004 BJD Added s3c2440_init_uarts() */ +struct s3c2410_uartcfg; + extern void s3c2440_init_irq(void); extern void s3c2440_init_time(void); + +extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no); diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c index 62d89d98c..ccd160443 100644 --- a/arch/arm/mach-s3c2410/time.c +++ b/arch/arm/mach-s3c2410/time.c @@ -1,7 +1,7 @@ -/* linux/include/asm-arm/arch-s3c2410/time.h +/* linux/arch/arm/mach-s3c2410/time.c * - * Copyright (C) 2003 Simtec Electronics - * Ben Dooks, + * Copyright (C) 2003,2004 Simtec Electronics + * Ben Dooks, * * 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 @@ -31,40 +31,92 @@ #include #include #include +#include #include +#include "clock.h" + static unsigned long timer_startval; -static unsigned long timer_ticks_usec; +static unsigned long timer_usec_ticks; -#ifdef CONFIG_S3C2410_RTC -extern void s3c2410_rtc_check(); -#endif +#define TIMER_USEC_SHIFT 16 -/* with an 12MHz clock, we get 12 ticks per-usec - */ +/* we use the shifted arithmetic to work out the ratio of timer ticks + * to usecs, as often the peripheral clock is not a nice even multiple + * of 1MHz. + * + * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok + * for the current HZ value of 200 without producing overflows. + * + * Original patch by Dimitry Andric, updated by Ben Dooks +*/ + + +/* timer_mask_usec_ticks + * + * given a clock and divisor, make the value to pass into timer_ticks_to_usec + * to scale the ticks into usecs +*/ + +static inline unsigned long +timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk) +{ + unsigned long den = pclk / 1000; + return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den; +} + +/* timer_ticks_to_usec + * + * convert timer ticks to usec. +*/ + +static inline unsigned long timer_ticks_to_usec(unsigned long ticks) +{ + unsigned long res; + + res = ticks * timer_usec_ticks; + res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */ + + return res >> TIMER_USEC_SHIFT; +} /*** * Returns microsecond since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() * IRQs are disabled before entering here from do_gettimeofday() */ + +#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0)) + static unsigned long s3c2410_gettimeoffset (void) { unsigned long tdone; - unsigned long usec; + unsigned long irqpend; + unsigned long tval; /* work out how many ticks have gone since last timer interrupt */ - tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4)); + tval = __raw_readl(S3C2410_TCNTO(4)); + tdone = timer_startval - tval; + + /* check to see if there is an interrupt pending */ - /* currently, tcnt is in 12MHz units, but this may change - * for non-bast machines... - */ + irqpend = __raw_readl(S3C2410_SRCPND); + if (irqpend & SRCPND_TIMER4) { + /* re-read the timer, and try and fix up for the missed + * interrupt. Note, the interrupt may go off before the + * timer has re-loaded from wrapping. + */ - usec = tdone / timer_ticks_usec; + tval = __raw_readl(S3C2410_TCNTO(4)); + tdone = timer_startval - tval; - return usec; + if (tval != 0) + tdone += timer_startval; + } + + return timer_ticks_to_usec(tdone); } @@ -74,13 +126,14 @@ static unsigned long s3c2410_gettimeoffset (void) static irqreturn_t s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); timer_tick(regs); - + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } static struct irqaction s3c2410_timer_irq = { - .name = "S32410 Timer Tick", + .name = "S3C2410 Timer Tick", .flags = SA_INTERRUPT, .handler = s3c2410_timer_interrupt }; @@ -91,15 +144,13 @@ static struct irqaction s3c2410_timer_irq = { * Currently we only use timer4, as it is the only timer which has no * other function that can be exploited externally */ -void __init s3c2410_init_time (void) +static void s3c2410_timer_setup (void) { unsigned long tcon; unsigned long tcnt; unsigned long tcfg1; unsigned long tcfg0; - gettimeoffset = s3c2410_gettimeoffset; - tcnt = 0xffff; /* default value for tcnt */ /* read the current timer configuration bits */ @@ -111,23 +162,25 @@ void __init s3c2410_init_time (void) /* configure the system for whichever machine is in use */ if (machine_is_bast() || machine_is_vr1000()) { - timer_ticks_usec = 12; /* timer is at 12MHz */ - tcnt = (timer_ticks_usec * (1000*1000)) / HZ; - } + /* timer is at 12MHz, scaler is 1 */ + timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); + tcnt = 12000000 / HZ; + + tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; + tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; + } else { + /* for the h1940 (and others), we use the pclk from the core + * to generate the timer values. since values around 50 to + * 70MHz are not values we can directly generate the timer + * value from, we need to pre-scale and divide before using it. + * + * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz + * (8.45 ticks per usec) + */ - /* for the h1940, we use the pclk from the core to generate - * the timer values. since 67.5MHz is not a value we can directly - * generate the timer value from, we need to pre-scale and - * divied before using it. - * - * overall divsior to get 200Hz is 337500 - * we can fit tcnt if we pre-scale by 6, producing a tick rate - * of 11.25MHz, and a tcnt of 56250. - */ + /* this is used as default if no other timer can be found */ - if (machine_is_h1940() || machine_is_smdk2410() ) { - timer_ticks_usec = s3c2410_pclk / (1000*1000); - timer_ticks_usec /= 6; + timer_usec_ticks = timer_mask_usec_ticks(6, s3c24xx_pclk); tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; @@ -135,12 +188,15 @@ void __init s3c2410_init_time (void) tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; - tcnt = (s3c2410_pclk / 6) / HZ; + tcnt = (s3c24xx_pclk / 6) / HZ; } + /* timers reload after counting zero, so reduce the count by 1 */ - printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n", - tcon, tcnt, tcfg0, tcfg1); + tcnt--; + + printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n", + tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks); /* check to see if timer is within 16bit range... */ if (tcnt > 0xffff) { @@ -164,13 +220,20 @@ void __init s3c2410_init_time (void) __raw_writel(tcnt, S3C2410_TCNTB(4)); __raw_writel(tcnt, S3C2410_TCMPB(4)); - setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); - /* start the timer running */ tcon |= S3C2410_TCON_T4START; tcon &= ~S3C2410_TCON_T4MANUALUPD; __raw_writel(tcon, S3C2410_TCON); } +static void __init s3c2410_timer_init (void) +{ + s3c2410_timer_setup(); + setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); +} - +struct sys_timer s3c2410_timer = { + .init = s3c2410_timer_init, + .offset = s3c2410_gettimeoffset, + .resume = s3c2410_timer_setup +}; diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index b8f8ded4b..7f2b61362 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -13,6 +13,7 @@ * * Modifications: * 14-Sep-2004 BJD Created + * 18-Oct-2004 BJD Cleanups, and added code to report OC cleared */ #define DEBUG @@ -51,10 +52,8 @@ usb_simtec_powercontrol(int port, int to) { pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to); - if (port == 1) { + if (port == 1) s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1); - pr_debug("GPBDAT now %08x\n", __raw_readl(S3C2410_GPBDAT)); - } } static irqreturn_t @@ -67,6 +66,7 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs) s3c2410_report_oc(info, 3); } else { pr_debug("usb_simtec: over-current irq (oc cleared)\n"); + s3c2410_report_oc(info, 0); } return IRQ_HANDLED; @@ -77,16 +77,15 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) int ret; if (on) { - pr_debug("claiming usb overccurent\n"); ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT, - "usb-oc", info); + "USB Over-current", info); if (ret != 0) { printk(KERN_ERR "failed to request usb oc irq\n"); } set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE); } else { - free_irq(IRQ_USBOC, NULL); + free_irq(IRQ_USBOC, info); } } @@ -110,14 +109,5 @@ int usb_simtec_init(void) s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP); s3c2410_gpio_setpin(S3C2410_GPB4, 1); - - pr_debug("GPB: CON=%08x, DAT=%08x\n", - __raw_readl(S3C2410_GPBCON), __raw_readl(S3C2410_GPBDAT)); - - if (0) { - s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, - S3C2410_MISCCR_USBDEV); - } - return 0; } diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index b586220d7..aa7d1c792 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -16,21 +16,6 @@ config ASSABET_NEPONSET Microprocessor Development Board (Assabet) with the SA-1111 Development Board (Nepon). -config SA1100_ADSBITSY - bool "ADS Bitsy" - help - Say Y here if you are using Applied Data Systems Intel(R) - StrongARM(R) 1110 based Bitsy, 3 x 5 inches in size, Compaq - IPAQ - - like platform. See - for more - information. - -config SA1100_BRUTUS - bool "Brutus" - help - Say Y here if you are using the Intel(R) StrongARM(R) SA-1100 - Microprocessor Development Board (also known as the Brutus). - config SA1100_CERF bool "CerfBoard" help @@ -98,44 +83,6 @@ config SA1100_H3XXX depends on SA1100_H3100 || SA1100_H3600 || SA1100_H3800 default y -#dep_bool ' Consus' CONFIG_SA1100_CONSUS $CONFIG_ARCH_SA1100 -#dep_bool ' Empeg' CONFIG_SA1100_EMPEG $CONFIG_ARCH_SA1100 -config SA1100_EXTENEX1 - bool "Extenex HandHeld Theater (Squashtail)" - -config SA1100_EXTENEX1_16MB - bool "Support 16 MB of DRAM (not just 8)" - depends on SA1100_EXTENEX1 - -config SA1100_FLEXANET - bool "FlexaNet" - help - Say Y here if you intend to run this kernel on the FlexaNet - handheld instruments. Information about this machine can be - found at: . - -config SA1100_FREEBIRD - bool "FreeBird-v1.1" - help - Support the FreeBird board used in Coventive embedded products. See - Documentation/arm/SA1100/Freebird for more. - -config SA1100_GRAPHICSCLIENT - bool "GraphicsClient Plus" - help - Say Y here if you are using an Applied Data Systems Intel(R) - StrongARM(R) SA-1100 based Graphics Client SBC. See - for information on this system. - -config SA1100_GRAPHICSMASTER - bool "GraphicsMaster" - help - Say Y here if you are using an Applied Data Systems Intel(R) - StrongARM(R) SA-1100 based Graphics Master SBC with SA-1111 - StrongARM companion chip. See - for information - on this system. - config SA1100_BADGE4 bool "HP Labs BadgePAD 4" help @@ -155,21 +102,6 @@ config SA1100_HACKKIT Say Y here to support the HackKit Core CPU Board ; -config SA1100_HUW_WEBPANEL - bool "HuW WebPanel" - help - Say Y here to support the HuW Webpanel produced by Hoeft & Wessel - AG. English-language website is at - ; credits and build instructions - at Documentation/arm/SA1100/HUW_WEBPANEL. - -config SA1100_ITSY - bool "Itsy" - help - Say Y here if you are using the Compaq Itsy experimental pocket - computer. See for - more information. - config SA1100_LART bool "LART" help @@ -177,47 +109,14 @@ config SA1100_LART (also known as the LART). See for information on the LART. -config SA1100_NANOENGINE - bool "nanoEngine" - help - The nanoEngine is a StrongARM 1110-based single board computer - from Bright Star Engineering. More information is available at: - . - - Say Y if configuring for a nanoEngine. - Say N otherwise. - -config SA1100_OMNIMETER - bool "OmniMeter" - help - Say Y here if you are using the inhand electronics OmniMeter. See - for details. - -config SA1100_PANGOLIN - bool "Pangolin" - help - 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. - config SA1100_PLEB bool "PLEB" help - Say Y here if you are using a Portable Linux Embedded Board - (also known as PLEB). See + Say Y here if you are using version 1 of the Portable Linux + Embedded Board (also known as PLEB). + See for more information. -config SA1100_PT_SYSTEM3 - bool "PT System 3" - help - Say Y here if you intend to build a kernel suitable to run on - a Pruftechnik Digital Board. For more information see - - config SA1100_SHANNON bool "Shannon" help @@ -226,15 +125,6 @@ config SA1100_SHANNON platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots, and a telco interface. -config SA1100_SHERMAN - bool "Sherman" - help - Say Y here to support the Blazie Engineering `Sherman' StrongARM - 1110-based SBC, used primarily in assistance products for the - visually impaired. The company is now Freedom Scientific, with - a website at . The Sherman - product, however, appears to have been discontinued. - config SA1100_SIMPAD bool "Simpad" help @@ -245,53 +135,6 @@ config SA1100_SIMPAD like CL4 in additional it has a PCMCIA-Slot. For more information visit or . -config SA1100_PFS168 - bool "Tulsa" - help - The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based - computer which includes the SA-1111 Microprocessor Companion Chip and other - custom I/O designed to add connectivity and multimedia features for vending - and business machine applications. Say Y here if you require support for - this target. - -config SA1100_VICTOR - bool "Victor" - help - Say Y here if you are using a Visu Aide Intel(R) StrongARM(R) - SA-1100 based Victor Digital Talking Book Reader. See - for information on - this system. - -config SA1100_XP860 - bool "XP860" - help - :: Config help missing :: - :: 06 August 2002 :: - -config SA1100_YOPY - bool "Yopy" - help - Say Y here to support the Yopy PDA. Product information at - . See Documentation/arm/SA1100/Yopy - for more. - -config SA1100_STORK - bool "Stork" - help - Say Y here if you intend to run this kernel on the Stork - handheld computer. - -#config SA1100_TRIZEPS -# bool "Trizeps" -# help -# :: write me :: - -#config TRIZEPS_MFTB2 -# bool "MFTB2" -# depends on SA1100_TRIZEPS -# help -# :: write me :: - config SA1100_SSP tristate "Generic PIO SSP" help @@ -300,17 +143,6 @@ config SA1100_SSP other devices, eg for BadgePAD 4 sensor support, or Jornada 720 touchscreen support. -config SA1100_USB - tristate "SA1100 USB function support" - -config SA1100_USB_NETLINK - tristate "Support for SA11x0 USB network link function" - depends on SA1100_USB - -config SA1100_USB_CHAR - tristate "Support for SA11x0 USB character device emulation" - depends on SA1100_USB - config H3600_SLEEVE tristate "Compaq iPAQ Handheld sleeve support" depends on SA1100_H3600 diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 898f27891..e4a4a3e8a 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -13,9 +13,6 @@ obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o # Specific board support -obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o -led-$(CONFIG_SA1100_ADSBITSY) += leds-adsbitsy.o - obj-$(CONFIG_SA1100_ASSABET) += assabet.o led-$(CONFIG_SA1100_ASSABET) += leds-assabet.o obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o @@ -23,68 +20,27 @@ obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o obj-$(CONFIG_SA1100_BADGE4) += badge4.o led-$(CONFIG_SA1100_BADGE4) += leds-badge4.o -obj-$(CONFIG_SA1100_BRUTUS) += brutus.o -led-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o - obj-$(CONFIG_SA1100_CERF) += cerf.o led-$(CONFIG_SA1100_CERF) += leds-cerf.o obj-$(CONFIG_SA1100_COLLIE) += collie.o -obj-$(CONFIG_SA1100_EMPEG) += empeg.o - -obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o -led-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o - -obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o -obj-$(CONFIG_SA1100_GRAPHICSCLIENT) += graphicsclient.o -led-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o - -obj-$(CONFIG_SA1100_GRAPHICSMASTER) += graphicsmaster.o -led-$(CONFIG_SA1100_GRAPHICSMASTER) += leds-graphicsmaster.o - obj-$(CONFIG_SA1100_H3600) += h3600.o obj-$(CONFIG_SA1100_HACKKIT) += hackkit.o led-$(CONFIG_SA1100_HACKKIT) += leds-hackkit.o -obj-$(CONFIG_SA1100_HUW_WEBPANEL) += huw_webpanel.o - -obj-$(CONFIG_SA1100_ITSY) += itsy.o - obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o obj-$(CONFIG_SA1100_LART) += lart.o led-$(CONFIG_SA1100_LART) += leds-lart.o -obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o - -obj-$(CONFIG_SA1100_OMNIMETER) += omnimeter.o - -obj-$(CONFIG_SA1100_PANGOLIN) += pangolin.o - -obj-$(CONFIG_SA1100_PFS168) += pfs168.o -led-$(CONFIG_SA1100_PFS168) += leds-pfs168.o - obj-$(CONFIG_SA1100_PLEB) += pleb.o -obj-$(CONFIG_SA1100_PT_SYSTEM3) += system3.o -led-$(CONFIG_SA1100_PT_SYSTEM3) += leds-system3.o - obj-$(CONFIG_SA1100_SHANNON) += shannon.o -obj-$(CONFIG_SA1100_SHERMAN) += sherman.o - obj-$(CONFIG_SA1100_SIMPAD) += simpad.o -led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o - -obj-$(CONFIG_SA1100_STORK) += stork.o - -obj-$(CONFIG_SA1100_TRIZEPS) += trizeps.o - -obj-$(CONFIG_SA1100_XP860) += xp860.o - -obj-$(CONFIG_SA1100_YOPY) += yopy.o +led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o # LEDs support obj-$(CONFIG_LEDS) += $(led-y) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index e5098cf9c..a3003b867 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -9,16 +9,17 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - #include #include #include -#include #include -#include #include +#include #include +#include +#include #include +#include #include #include @@ -29,6 +30,8 @@ #include #include +#include +#include #include #include #include @@ -92,6 +95,109 @@ static void assabet_lcd_power(int on) ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); } + +/* + * Assabet flash support code. + */ + +#ifdef ASSABET_REV_4 +/* + * Phase 4 Assabet has two 28F160B3 flash parts in bank 0: + */ +static struct mtd_partition assabet_partitions[] = { + { + .name = "bootloader", + .size = 0x00020000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "bootloader params", + .size = 0x00020000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "jffs", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; +#else +/* + * Phase 5 Assabet has two 28F128J3A flash parts in bank 0: + */ +static struct mtd_partition assabet_partitions[] = { + { + .name = "bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "bootloader params", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "jffs", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; +#endif + +static struct flash_platform_data assabet_flash_data = { + .map_name = "cfi_probe", + .parts = assabet_partitions, + .nr_parts = ARRAY_SIZE(assabet_partitions), +}; + +static struct resource assabet_flash_resources[] = { + { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = SA1100_CS1_PHYS, + .end = SA1100_CS1_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, + } +}; + + +/* + * Assabet IrDA support code. + */ + +static int assabet_irda_set_power(struct device *dev, unsigned int state) +{ + static unsigned int bcr_state[4] = { + ASSABET_BCR_IRDA_MD0, + ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0, + ASSABET_BCR_IRDA_MD1, + 0 + }; + + if (state < 4) { + state = bcr_state[state]; + ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1| + ASSABET_BCR_IRDA_MD0)); + ASSABET_BCR_set(state); + } + return 0; +} + +static void assabet_irda_set_speed(struct device *dev, unsigned int speed) +{ + if (speed < 4000000) + ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); + else + ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); +} + +static struct irda_platform_data assabet_irda_data = { + .set_power = assabet_irda_set_power, + .set_speed = assabet_irda_set_speed, +}; + static void __init assabet_init(void) { /* @@ -136,6 +242,10 @@ static void __init assabet_init(void) "hasn't been configured in the kernel\n" ); #endif } + + sa11x0_set_flash_data(&assabet_flash_data, assabet_flash_resources, + ARRAY_SIZE(assabet_flash_resources)); + sa11x0_set_irda_data(&assabet_irda_data); } /* @@ -324,6 +434,6 @@ MACHINE_START(ASSABET, "Intel-Assabet") FIXUP(fixup_assabet) MAPIO(assabet_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) - INIT_MACHINE(assabet_init) + .timer = &sa1100_timer, + .init_machine = assabet_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index cef71047c..0e66ec02c 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -27,6 +29,7 @@ #include #include +#include #include #include #include @@ -80,6 +83,45 @@ static int __init badge4_sa1111_init(void) } +/* + * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit) + * Eight 4 KiW Parameter Bottom Blocks (64 KiB) + * Sixty-three 32 KiW Main Blocks (4032 Ki b) + * + * + * + * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit) + * Eight 4 KiW Parameter Bottom Blocks (64 KiB) + * One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b) + */ +static struct mtd_partition badge4_partitions[] = { + { + .name = "BLOB boot loader", + .offset = 0, + .size = 0x0000A000 + }, { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = 0x00006000 + }, { + .name = "root", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL + } +}; + +static struct flash_platform_data badge4_flash_data = { + .map_name = "cfi_probe", + .parts = badge4_partitions, + .nr_parts = ARRAY_SIZE(badge4_partitions), +}; + +static struct resource badge4_flash_resource = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, +}; + static int five_v_on __initdata = 0; static int __init five_v_on_setup(char *ignore) @@ -170,6 +212,9 @@ static int __init badge4_init(void) /* maybe turn on 5v0 from the start */ badge4_set_5V(BADGE4_5V_INITIALLY, five_v_on); + sa11x0_set_flash_data(badge4_flash_data, badge4_flash_resources, + ARRAY_SIZE(badge4_flash_resources); + return 0; } @@ -245,5 +290,5 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") BOOT_PARAMS(0xc0000100) MAPIO(badge4_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, MACHINE_END diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 2c4c05013..f8edde5e7 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -22,6 +24,7 @@ #include #include +#include #include #include @@ -47,6 +50,48 @@ static struct platform_device *cerf_devices[] __initdata = { &cerfuart2_device, }; +#ifdef CONFIG_SA1100_CERF_FLASH_32MB +# define CERF_FLASH_SIZE 0x02000000 +#elif defined CONFIG_SA1100_CERF_FLASH_16MB +# define CERF_FLASH_SIZE 0x01000000 +#elif defined CONFIG_SA1100_CERF_FLASH_8MB +# define CERF_FLASH_SIZE 0x00800000 +#else +# error "Undefined flash size for CERF" +#endif + +static struct mtd_partition cerf_partitions[] = { + { + .name = "Bootloader", + .size = 0x00020000, + .offset = 0x00000000, + }, { + .name = "Params", + .size = 0x00040000, + .offset = 0x00020000, + }, { + .name = "Kernel", + .size = 0x00100000, + .offset = 0x00060000, + }, { + .name = "Filesystem", + .size = CERF_FLASH_SIZE-0x00160000, + .offset = 0x00160000, + } +}; + +static struct flash_platform_data cerf_flash_data = { + .map_name = "cfi_probe", + .parts = cerf_partitions, + .nr_parts = ARRAY_SIZE(cerf_partitions), +}; + +static struct resource cerf_flash_resource = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + static void __init cerf_init_irq(void) { sa1100_init_irq(); @@ -71,26 +116,17 @@ static void __init cerf_map_io(void) GPDR |= CERF_GPIO_CF_RESET; } -static int __init cerf_init(void) +static void __init cerf_init(void) { - int ret; - - if (!machine_is_cerf()) - return -ENODEV; - - ret = platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); - if (ret < 0) - return ret; - - return 0; + platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); + sa11x0_set_flash_data(&cerf_flash_data, &cerf_flash_resource, 1); } -arch_initcall(cerf_init); - MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") MAINTAINER("support@intrinsyc.com") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(cerf_map_io) INITIRQ(cerf_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = cerf_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 23bf73ef8..a85faf750 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -31,6 +33,7 @@ #include #include +#include #include #include @@ -89,6 +92,48 @@ static struct platform_device *devices[] __initdata = { &locomo_device, }; +static struct mtd_partition collie_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x000C0000, + .mask_flags = MTD_WRITEABLE + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000, + }, { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = 0x00e20000, + } +}; + +static void collie_set_vpp(int vpp) +{ + COLLIE_SCP_REG_GPCR |= COLLIE_SCP_VPEN; + if (vpp) { + COLLIE_SCP_REG_GPWR |= COLLIE_SCP_VPEN; + } else { + COLLIE_SCP_REG_GPWR &= ~COLLIE_SCP_VPEN; + } +} + +static struct flash_platform_data collie_flash_data = { + .map_name = "cfi_probe", + .set_vpp = collie_set_vpp, + .parts = collie_partitions, + .nr_parts = ARRAY_SIZE(collie_partitions), +}; + +static struct resource collie_flash_resources[] = { + { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, + } +}; + static void __init collie_init(void) { int ret = 0; @@ -121,6 +166,9 @@ static void __init collie_init(void) if (ret) { printk(KERN_WARNING "collie: Unable to register LoCoMo device\n"); } + + sa11x0_set_flash_data(&collie_flash_data, collie_flash_resources, + ARRAY_SIZE(collie_flash_resources)); } static struct map_desc collie_io_desc[] __initdata = { @@ -140,6 +188,6 @@ MACHINE_START(COLLIE, "Sharp-Collie") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(collie_map_io) INITIRQ(sa1100_init_irq) - INIT_MACHINE(collie_init) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = collie_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index be5dd86f4..6435b2e48 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -230,9 +230,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) } static struct cpufreq_driver sa1100_driver = { - .flags = CPUFREQ_STICKY | - CPUFREQ_PANIC_OUTOFSYNC | - CPUFREQ_PANIC_RESUME_OUTOFSYNC, + .flags = CPUFREQ_STICKY, .verify = sa11x0_verify_speed, .target = sa1100_target, .get = sa11x0_getspeed, diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 62a4dbcce..8d2a89a2e 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -329,9 +329,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) } static struct cpufreq_driver sa1110_driver = { - .flags = CPUFREQ_STICKY | - CPUFREQ_PANIC_OUTOFSYNC | - CPUFREQ_PANIC_RESUME_OUTOFSYNC, + .flags = CPUFREQ_STICKY, .verify = sa11x0_verify_speed, .target = sa1110_target, .get = sa11x0_getspeed, diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 4fe5a5a4a..95ae217be 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -161,7 +161,7 @@ static u64 sa11x0udc_dma_mask = 0xffffffffUL; static struct platform_device sa11x0udc_device = { .name = "sa11x0-udc", - .id = 0, + .id = -1, .dev = { .dma_mask = &sa11x0udc_dma_mask, .coherent_dma_mask = 0xffffffff, @@ -212,7 +212,7 @@ static u64 sa11x0mcp_dma_mask = 0xffffffffUL; static struct platform_device sa11x0mcp_device = { .name = "sa11x0-mcp", - .id = 0, + .id = -1, .dev = { .dma_mask = &sa11x0mcp_dma_mask, .coherent_dma_mask = 0xffffffff, @@ -233,7 +233,7 @@ static u64 sa11x0ssp_dma_mask = 0xffffffffUL; static struct platform_device sa11x0ssp_device = { .name = "sa11x0-ssp", - .id = 0, + .id = -1, .dev = { .dma_mask = &sa11x0ssp_dma_mask, .coherent_dma_mask = 0xffffffff, @@ -257,7 +257,7 @@ static struct resource sa11x0fb_resources[] = { static struct platform_device sa11x0fb_device = { .name = "sa11x0-fb", - .id = 0, + .id = -1, .dev = { .coherent_dma_mask = 0xffffffff, }, @@ -267,9 +267,54 @@ static struct platform_device sa11x0fb_device = { static struct platform_device sa11x0pcmcia_device = { .name = "sa11x0-pcmcia", - .id = 0, + .id = -1, }; +static struct platform_device sa11x0mtd_device = { + .name = "flash", + .id = -1, +}; + +void sa11x0_set_flash_data(struct flash_platform_data *flash, + struct resource *res, int nr) +{ + sa11x0mtd_device.dev.platform_data = flash; + sa11x0mtd_device.resource = res; + sa11x0mtd_device.num_resources = nr; +} + +static struct resource sa11x0ir_resources[] = { + { + .start = __PREG(Ser2UTCR0), + .end = __PREG(Ser2UTCR0) + 0x24 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = __PREG(Ser2HSCR0), + .end = __PREG(Ser2HSCR0) + 0x1c - 1, + .flags = IORESOURCE_MEM, + }, { + .start = __PREG(Ser2HSCR2), + .end = __PREG(Ser2HSCR2) + 0x04 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_Ser2ICP, + .end = IRQ_Ser2ICP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device sa11x0ir_device = { + .name = "sa11x0-ir", + .id = -1, + .num_resources = ARRAY_SIZE(sa11x0ir_resources), + .resource = sa11x0ir_resources, +}; + +void sa11x0_set_irda_data(struct irda_platform_data *irda) +{ + sa11x0ir_device.dev.platform_data = irda; +} + static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0udc_device, &sa11x0uart1_device, @@ -278,12 +323,16 @@ static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0ssp_device, &sa11x0pcmcia_device, &sa11x0fb_device, + &sa11x0mtd_device, }; static int __init sa1100_init(void) { pm_power_off = sa1100_power_off; + if (sa11x0ir_device.dev.platform_data) + platform_device_register(&sa11x0ir_device); + return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices)); } diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 04bcfeb3b..bfe41da99 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -4,9 +4,11 @@ * Author: Nicolas Pitre */ +struct sys_timer; + +extern struct sys_timer sa1100_timer; extern void __init sa1100_map_io(void); extern void __init sa1100_init_irq(void); -extern void __init sa1100_init_time(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ @@ -25,3 +27,12 @@ extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(unsigned int cpu); extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); + +struct flash_platform_data; +struct resource; + +extern void sa11x0_set_flash_data(struct flash_platform_data *flash, + struct resource *res, int nr); + +struct irda_platform_data; +void sa11x0_set_irda_data(struct irda_platform_data *irda); diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 54ab44452..9788d3aef 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include @@ -34,6 +37,8 @@ #include #include +#include +#include #include #include @@ -52,6 +57,99 @@ struct ipaq_model_ops ipaq_model_ops; EXPORT_SYMBOL(ipaq_model_ops); +static struct mtd_partition h3xxx_partitions[] = { + { + .name = "H3XXX boot firmware", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { +#ifdef CONFIG_MTD_2PARTS_IPAQ + .name = "H3XXX root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = 0x00040000, +#else + .name = "H3XXX kernel", + .size = 0x00080000, + .offset = 0x00040000, + }, { + .name = "H3XXX params", + .size = 0x00040000, + .offset = 0x000C0000, + }, { +#ifdef CONFIG_JFFS2_FS + .name = "H3XXX root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = 0x00100000, +#else + .name = "H3XXX initrd", + .size = 0x00100000, + .offset = 0x00100000, + }, { + .name = "H3XXX root cramfs", + .size = 0x00300000, + .offset = 0x00200000, + }, { + .name = "H3XXX usr cramfs", + .size = 0x00800000, + .offset = 0x00500000, + }, { + .name = "H3XXX usr local", + .size = MTDPART_SIZ_FULL, + .offset = 0x00d00000, +#endif +#endif + } +}; + +static void h3xxx_set_vpp(int vpp) +{ + assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp); +} + +static struct flash_platform_data h3xxx_flash_data = { + .map_name = "cfi_probe", + .set_vpp = h3xxx_set_vpp, + .parts = h3xxx_partitions, + .nr_parts = ARRAY_SIZE(h3xxx_partitions), +}; + +static struct resource h3xxx_flash_resource = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +/* + * This turns the IRDA power on or off on the Compaq H3600 + */ +static int h3600_irda_set_power(struct device *dev, unsigned int state) +{ + assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state ); + + return 0; +} + +static void h3600_irda_set_speed(struct device *dev, int speed) +{ + if (speed < 4000000) { + clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); + } else { + set_h3600_egpio(IPAQ_EGPIO_IR_FSEL); + } +} + +static struct irda_platform_data h3600_irda_data = { + .set_power = h3600_irda_set_power, + .set_speed = h3600_irda_set_speed, +}; + +static void h3xxx_mach_init(void) +{ + sa11x0_set_flash_data(&h3xxx_flash_data, &h3xxx_flash_resource, 1); + sa11x0_set_irda_data(&h3600_irda_data); +} + /* * low-level UART features */ @@ -286,7 +384,8 @@ MACHINE_START(H3100, "Compaq iPAQ H3100") BOOT_PARAMS(0xc0000100) MAPIO(h3100_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = h3xxx_mach_init, MACHINE_END #endif /* CONFIG_SA1100_H3100 */ @@ -401,7 +500,8 @@ MACHINE_START(H3600, "Compaq iPAQ H3600") BOOT_PARAMS(0xc0000100) MAPIO(h3600_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = h3xxx_mach_init, MACHINE_END #endif /* CONFIG_SA1100_H3600 */ @@ -785,7 +885,8 @@ MACHINE_START(H3800, "Compaq iPAQ H3800") BOOT_PARAMS(0xc0000100) MAPIO(h3800_map_io) INITIRQ(h3800_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = h3xxx_mach_init, MACHINE_END #endif /* CONFIG_SA1100_H3800 */ diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index e24be9716..570841779 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -28,6 +30,7 @@ #include #include +#include #include #include #include @@ -39,8 +42,6 @@ */ /* init funcs */ -static int __init hackkit_init(void); -static void __init hackkit_init_irq(void); static void __init hackkit_map_io(void); static u_int hackkit_get_mctrl(struct uart_port *port); @@ -83,11 +84,6 @@ static void __init hackkit_map_io(void) Ser1SDCR0 |= SDCR0_SUS; } -static void __init hackkit_init_irq(void) -{ - /* none used yet */ -} - /** * hackkit_uart_pm - powermgmt callback function for system 3 UART * @port: uart port structure @@ -144,35 +140,61 @@ static u_int hackkit_get_mctrl(struct uart_port *port) return ret; } -static int __init hackkit_init(void) -{ - int ret = 0; - - if ( !machine_is_hackkit() ) { - ret = -EINVAL; - goto DONE; +static struct mtd_partition hackkit_partitions[] = { + { + .name = "BLOB", + .size = 0x00040000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "config", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "kernel", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "initrd", + .size = 0x00180000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "rootfs", + .size = 0x700000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "data", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } +}; + +static struct flash_platform_data hackkit_flash_data = { + .map_name = "cfi_probe", + .parts = hackkit_partitions, + .nr_parts = ARRAY_SIZE(hackkit_partitions), +}; - hackkit_init_irq(); +static struct resource hackkit_flash_resource = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_32M, + .flags = IORESOURCE_MEM, +}; - ret = 0; -DONE: - return ret; +static void __init hackkit_init(void) +{ + sa11x0_set_flash_data(&hackkit_flash_data, &hackkit_flash_resource, 1); } /********************************************************************** * Exported Functions */ -/********************************************************************** - * kernel magic macros - */ -arch_initcall(hackkit_init); - MACHINE_START(HACKKIT, "HackKit Cpu Board") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) MAPIO(hackkit_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = hackkit_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 8943e816a..6be78291a 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -101,5 +101,5 @@ MACHINE_START(JORNADA720, "HP Jornada 720") BOOT_PARAMS(0xc0000100) MAPIO(jornada720_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, MACHINE_END diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 34ab20118..51c08ccfb 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -17,6 +17,8 @@ #include "generic.h" +#warning "include/asm/arch-sa1100/ide.h needs fixing for lart" + static struct map_desc lart_io_desc[] __initdata = { /* virtual physical length type */ { 0xe8000000, 0x00000000, 0x00400000, MT_DEVICE }, /* main flash memory */ @@ -43,5 +45,5 @@ MACHINE_START(LART, "LART") BOOT_PARAMS(0xc0000100) MAPIO(lart_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, MACHINE_END diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c index da426bcd1..6a27a2d32 100644 --- a/arch/arm/mach-sa1100/leds-simpad.c +++ b/arch/arm/mach-sa1100/leds-simpad.c @@ -28,11 +28,7 @@ extern void clear_cs3_bit(int value); void simpad_leds_event(led_event_t evt) { - unsigned long flags; - - //local_irq_save(flags); - - switch (evt) + switch (evt) { case led_start: hw_led_state = LED_GREEN; @@ -101,6 +97,5 @@ void simpad_leds_event(led_event_t evt) set_cs3_bit(LED2_ON); else clear_cs3_bit(LED2_ON); - //local_irq_restore(flags); } diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index a747fd0bd..a23142995 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -173,6 +173,8 @@ static int neponset_probe(struct device *dev) return 0; } +#ifdef CONFIG_PM + /* * LDM power management. */ @@ -184,12 +186,12 @@ static int neponset_suspend(struct device *dev, u32 state, u32 level) if (level == SUSPEND_SAVE_STATE || level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) { - if (!dev->saved_state) - dev->saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); - if (!dev->saved_state) + if (!dev->power.saved_state) + dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); + if (!dev->power.saved_state) return -ENOMEM; - *(unsigned int *)dev->saved_state = NCR_0; + *(unsigned int *)dev->power.saved_state = NCR_0; } return 0; @@ -198,16 +200,21 @@ static int neponset_suspend(struct device *dev, u32 state, u32 level) static int neponset_resume(struct device *dev, u32 level) { if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) { - if (dev->saved_state) { - NCR_0 = *(unsigned int *)dev->saved_state; - kfree(dev->saved_state); - dev->saved_state = NULL; + if (dev->power.saved_state) { + NCR_0 = *(unsigned int *)dev->power.saved_state; + kfree(dev->power.saved_state); + dev->power.saved_state = NULL; } } return 0; } +#else +#define neponset_suspend NULL +#define neponset_resume NULL +#endif + static struct device_driver neponset_device_driver = { .name = "neponset", .bus = &platform_bus_type, diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index 2cdfef622..5606bd71b 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -5,31 +5,150 @@ #include #include #include +#include +#include + +#include #include +#include #include +#include #include #include +#include #include +#include #include "generic.h" + +/* + * Ethernet IRQ mappings + */ + +#define PLEB_ETH0_P (0x20000300) /* Ethernet 0 in PCMCIA0 IO */ +#define PLEB_ETH0_V (0xf6000300) + +#define GPIO_ETH0_IRQ GPIO_GPIO(21) +#define GPIO_ETH0_EN GPIO_GPIO(26) + +#define IRQ_GPIO_ETH0_IRQ IRQ_GPIO21 + +static struct resource smc91x_resources[] = { + [0] = { + .start = PLEB_ETH0_P, + .end = PLEB_ETH0_P | 0x03ffffff, + .flags = IORESOURCE_MEM, + }, +#if 0 /* Autoprobe instead, to get rising/falling edge characteristic right */ + [1] = { + .start = IRQ_GPIO_ETH0_IRQ, + .end = IRQ_GPIO_ETH0_IRQ, + .flags = IORESOURCE_IRQ, + }, +#endif +}; + + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static struct platform_device *devices[] __initdata = { + &smc91x_device, +}; + + +/* + * Pleb's memory map + * has flash memory (typically 4 or 8 meg) selected by + * the two SA1100 lowest chip select outputs. + */ +static struct resource pleb_flash_resources[] = { + [0] = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_8M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = SA1100_CS1_PHYS, + .end = SA1100_CS1_PHYS + SZ_8M - 1, + .flags = IORESOURCE_MEM, + } +}; + + +static struct mtd_partition pleb_partitions[] = { + { + .name = "blob", + .offset = 0, + .size = 0x00020000, + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0x000e0000, + }, { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = 0x00300000, + } +}; + + +static struct flash_platform_data pleb_flash_data = { + .map_name = "cfi_probe", + .parts = pleb_partitions, + .nr_parts = ARRAY_SIZE(pleb_partitions), +}; + + +static void __init pleb_init(void) +{ + sa11x0_set_flash_data(&pleb_flash_data, pleb_flash_resources, + ARRAY_SIZE(pleb_flash_resources)); + + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + + static void __init pleb_map_io(void) { sa1100_map_io(); sa1100_register_uart(0, 3); sa1100_register_uart(1, 1); + GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD); GPDR |= GPIO_UART_TXD; GPDR &= ~GPIO_UART_RXD; PPAR |= PPAR_UPR; + + /* + * Fix expansion memory timing for network card + */ + MECR = ((2<<10) | (2<<5) | (2<<0)); + + /* + * Enable the SMC ethernet controller + */ + GPDR |= GPIO_ETH0_EN; /* set to output */ + GPCR = GPIO_ETH0_EN; /* clear MCLK (enable smc) */ + + GPDR &= ~GPIO_ETH0_IRQ; + + set_irq_type(GPIO_ETH0_IRQ, IRQT_FALLING); } MACHINE_START(PLEB, "PLEB") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) MAPIO(pleb_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = pleb_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 2532b7f80..379ea5e39 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -30,6 +30,7 @@ #include #include #include +#include extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_resume(void); @@ -44,9 +45,6 @@ extern void sa1100_cpu_resume(void); */ enum { SLEEP_SAVE_SP = 0, - SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, - SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, - SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, @@ -56,26 +54,21 @@ enum { SLEEP_SAVE_SP = 0, }; -static int sa11x0_pm_enter(u32 state) +static int sa11x0_pm_enter(suspend_state_t state) { - unsigned long sleep_save[SLEEP_SAVE_SIZE]; - unsigned long delta, gpio; + unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; + struct timespec delta, rtc; if (state != PM_SUSPEND_MEM) return -EINVAL; /* preserve current time */ - delta = xtime.tv_sec - RCNR; + rtc.tv_sec = RCNR; + rtc.tv_nsec = 0; + save_time_delta(&delta, &rtc); gpio = GPLR; /* save vital registers */ - SAVE(OSCR); - SAVE(OSMR0); - SAVE(OSMR1); - SAVE(OSMR2); - SAVE(OSMR3); - SAVE(OIER); - SAVE(GPDR); SAVE(GAFR); @@ -127,15 +120,9 @@ static int sa11x0_pm_enter(u32 state) */ PSSR = PSSR_PH; - RESTORE(OSMR0); - RESTORE(OSMR1); - RESTORE(OSMR2); - RESTORE(OSMR3); - RESTORE(OSCR); - RESTORE(OIER); - /* restore current time */ - xtime.tv_sec = RCNR + delta; + rtc.tv_sec = RCNR; + restore_time_delta(&delta, &rtc); return 0; } @@ -148,7 +135,7 @@ unsigned long sleep_phys_sp(void *sp) /* * Called after processes are frozen, but before we shut down devices. */ -static int sa11x0_pm_prepare(u32 state) +static int sa11x0_pm_prepare(suspend_state_t state) { return 0; } @@ -156,7 +143,7 @@ static int sa11x0_pm_prepare(u32 state) /* * Called after devices are re-setup, but before processes are thawed. */ -static int sa11x0_pm_finish(u32 state) +static int sa11x0_pm_finish(suspend_state_t state) { return 0; } diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 8bec82676..66fe6fdf0 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -5,18 +5,55 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include #include #include "generic.h" +static struct mtd_partition shannon_partitions[] = { + { + .name = "BLOB boot loader", + .offset = 0, + .size = 0x20000 + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0xe0000 + }, + { + .name = "initrd", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL + } +}; + +static struct flash_platform_data shannon_flash_data = { + .map_name = "cfi_probe", + .parts = shannon_partitions, + .nr_parts = ARRAY_SIZE(shannon_partitions), +}; + +static struct resource shannon_flash_resource = { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_4M - 1, + .flags = IORESOURCE_MEM, +}; + +static void __init shannon_init(void) +{ + sa11x0_set_flash_data(&shannon_flash_data, shannon_flash_resource, 1); +} static void __init shannon_map_io(void) { @@ -41,5 +78,6 @@ MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") BOOT_PARAMS(0xc0000100) MAPIO(shannon_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, + .init_machine = shannon_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index b73ec2e18..8d113d629 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include #include @@ -17,10 +20,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -83,6 +86,45 @@ static struct sa1100_port_fns simpad_port_fns __initdata = { .pm = simpad_uart_pm, }; + +static struct mtd_partition simpad_partitions[] = { + { + .name = "SIMpad boot firmware", + .size = 0x00080000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "SIMpad kernel", + .size = 0x0010000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "SIMpad root jffs2", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct flash_platform_data simpad_flash_data = { + .map_name = "cfi_probe", + .parts = simpad_partitions, + .nr_parts = ARRAY_SIZE(simpad_partitions), +}; + + +static struct resource simpad_flash_resources [] = { + { + .start = SA1100_CS0_PHYS, + .end = SA1100_CS0_PHYS + SZ_16M -1, + .flags = IORESOURCE_MEM, + }, { + .start = SA1100_CS1_PHYS, + .end = SA1100_CS1_PHYS + SZ_16M -1, + .flags = IORESOURCE_MEM, + } +}; + + + static void __init simpad_map_io(void) { sa1100_map_io(); @@ -113,85 +155,10 @@ static void __init simpad_map_io(void) PCFR = 0; PSDR = 0; - -} - -#ifdef CONFIG_PROC_FS - -static char* name[]={ - "VCC_5V_EN", - "VCC_3V_EN", - "EN1", - "EN0", - "DISPLAY_ON", - "PCMCIA_BUFF_DIS", - "MQ_RESET", - "PCMCIA_RESET", - "DECT_POWER_ON", - "IRDA_SD", - "RS232_ON", - "SD_MEDIAQ", - "LED2_ON", - "IRDA_MODE", - "ENABLE_5V", - "RESET_SIMCARD" -}; - -static int proc_cs3_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - int len, i; - - p += sprintf(p, "Chipselect3 : %x\n", (uint)cs3_shadow); - for (i = 0; i <= 15; i++) { - if(cs3_shadow & (1<read_proc = proc_cs3_read; - proc_cs3->write_proc = (void*)proc_cs3_write; - } -#endif - - - - return 0; -} - -arch_initcall(cs3_init); - static void simpad_power_off(void) { local_irq_disable(); // was cli @@ -216,9 +183,31 @@ static void simpad_power_off(void) } + +/* + * MediaQ Video Device + */ +static struct platform_device simpad_mq200fb = { + .name = "simpad-mq200", + .id = 0, +}; + +static struct platform_device *devices[] __initdata = { + &simpad_mq200fb +}; + + + static int __init simpad_init(void) { - set_power_off_handler( simpad_power_off ); + int ret; + + pm_power_off = simpad_power_off; + + ret = platform_add_devices(devices, ARRAY_SIZE(devices)); + if(ret) + printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device"); + return 0; } @@ -226,10 +215,10 @@ arch_initcall(simpad_init); MACHINE_START(SIMPAD, "Simpad") - MAINTAINER("Juergen Messerer") + MAINTAINER("Holger Freyther") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) MAPIO(simpad_map_io) INITIRQ(sa1100_init_irq) - INITTIME(sa1100_init_time) + .timer = &sa1100_timer, MACHINE_END diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 03b8af5e0..2fa1e289d 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -70,12 +70,12 @@ ENTRY(sa1100_cpu_suspend) @ delay 90us and set CPU PLL to lowest speed @ fixes resume problem on high speed SA1110 mov r0, #90 - bl udelay + bl __udelay ldr r0, =PPCR mov r1, #0 str r1, [r0] mov r0, #90 - bl udelay + bl __udelay /* * SA1110 SDRAM controller workaround. register values: diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 1c3d082f8..19b0c0fd6 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -84,12 +84,16 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int next_match; + write_seqlock(&xtime_lock); + do { timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); } while ((signed long)(next_match - OSCR) <= 0); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -99,11 +103,10 @@ static struct irqaction sa1100_timer_irq = { .handler = sa1100_timer_interrupt }; -void __init sa1100_init_time(void) +static void __init sa1100_timer_init(void) { struct timespec tv; - gettimeoffset = sa1100_gettimeoffset; set_rtc = sa1100_set_rtc; tv.tv_nsec = 0; @@ -117,3 +120,40 @@ void __init sa1100_init_time(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_PM +unsigned long osmr[4], oier; + +static void sa1100_timer_suspend(void) +{ + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; +} + +static void sa1100_timer_resume(void) +{ + OSSR = 0x0f; + OSMR0 = osmr[0]; + OSMR1 = osmr[1]; + OSMR2 = osmr[2]; + OSMR3 = osmr[3]; + OIER = oier; + + /* + * OSMR0 is the system timer: make sure OSCR is sufficiently behind + */ + OSCR = OSMR0 - LATCH; +} +#else +#define sa1100_timer_suspend NULL +#define sa1100_timer_resume NULL +#endif + +struct sys_timer sa1100_timer = { + .init = sa1100_timer_init, + .suspend = sa1100_timer_suspend, + .resume = sa1100_timer_resume, + .offset = sa1100_gettimeoffset, +}; diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index e4ae68889..81881e922 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,46 @@ #include #include +static struct plat_serial8250_port serial_platform_data[] = { + { + .iobase = 0x3f8, + .irq = 4, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { + .iobase = 0x2f8, + .irq = 3, + .uartclk = 1843200, + .regshift = 2, + .iotype = UPIO_PORT, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + { }, +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; + +static int __init shark_init(void) +{ + int ret; + + if (machine_is_shark()) + ret = platform_device_register(&serial_device); + + return ret; +} + +arch_initcall(shark_init); + extern void shark_init_irq(void); static struct map_desc shark_io_desc[] __initdata = { @@ -35,8 +76,9 @@ static void __init shark_map_io(void) static irqreturn_t shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + write_seqlock(&xtime_lock); timer_tick(regs); - + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -49,7 +91,7 @@ static struct irqaction shark_timer_irq = { /* * Set up timer interrupt, and return the current time in seconds. */ -void __init shark_init_time(void) +static void __init shark_timer_init(void) { unsigned long flags; @@ -60,6 +102,9 @@ void __init shark_init_time(void) setup_irq(IRQ_TIMER, &shark_timer_irq); } +static struct sys_timer shark_timer = { + .init = shark_timer_init, +}; MACHINE_START(SHARK, "Shark") MAINTAINER("Alexander Schulz") @@ -67,5 +112,5 @@ MACHINE_START(SHARK, "Shark") BOOT_PARAMS(0x08003000) MAPIO(shark_map_io) INITIRQ(shark_init_irq) - INITTIME(shark_init_time) + .timer = &shark_timer, MACHINE_END diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile index ff886e33e..5d6088377 100644 --- a/arch/arm/mach-versatile/Makefile +++ b/arch/arm/mach-versatile/Makefile @@ -3,3 +3,5 @@ # obj-y := core.o clock.o +obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o +obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index a13253692..48025c2b9 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include "clock.h" @@ -83,12 +83,12 @@ EXPORT_SYMBOL(clk_round_rate); int clk_set_rate(struct clk *clk, unsigned long rate) { int ret = -EIO; -#if 0 // Not yet + if (clk->setvco) { - struct icst525_vco vco; + struct icst307_vco vco; - vco = icst525_khz_to_vco(clk->params, rate); - clk->rate = icst525_khz(clk->params, vco); + vco = icst307_khz_to_vco(clk->params, rate / 1000); + clk->rate = icst307_khz(clk->params, vco) * 1000; printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n", clk->name, vco.s, vco.r, vco.v); @@ -96,7 +96,6 @@ int clk_set_rate(struct clk *clk, unsigned long rate) clk->setvco(clk, vco); ret = 0; } -#endif return ret; } EXPORT_SYMBOL(clk_set_rate); diff --git a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h index 12e68ecde..8b0b61dd1 100644 --- a/arch/arm/mach-versatile/clock.h +++ b/arch/arm/mach-versatile/clock.h @@ -9,16 +9,16 @@ * published by the Free Software Foundation. */ struct module; -struct icst525_params; +struct icst307_params; struct clk { struct list_head node; unsigned long rate; struct module *owner; const char *name; - const struct icst525_params *params; + const struct icst307_params *params; void *data; - void (*setvco)(struct clk *, struct icst525_vco vco); + void (*setvco)(struct clk *, struct icst307_vco vco); }; int clk_register(struct clk *clk); diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 285ca9abb..2e71ad683 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -31,15 +32,18 @@ #include #include #include +#include +#include #include #include #include #include #include -#ifdef CONFIG_MMC #include -#endif + +#include "core.h" +#include "clock.h" /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx @@ -109,19 +113,17 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) #if 1 #define IRQ_MMCI0A IRQ_VICSOURCE22 -#define IRQ_MMCI1A IRQ_VICSOURCE23 #define IRQ_AACI IRQ_VICSOURCE24 #define IRQ_ETH IRQ_VICSOURCE25 #define PIC_MASK 0xFFD00000 #else #define IRQ_MMCI0A IRQ_SIC_MMCI0A -#define IRQ_MMCI1A IRQ_SIC_MMCI1A #define IRQ_AACI IRQ_SIC_AACI #define IRQ_ETH IRQ_SIC_ETH #define PIC_MASK 0 #endif -static void __init versatile_init_irq(void) +void __init versatile_init_irq(void) { unsigned int i, value; @@ -187,6 +189,10 @@ static struct map_desc versatile_io_desc[] __initdata = { { IO_ADDRESS(VERSATILE_SIC_BASE), VERSATILE_SIC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(VERSATILE_VIC_BASE), VERSATILE_VIC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(VERSATILE_SCTL_BASE), VERSATILE_SCTL_BASE, SZ_4K * 9, MT_DEVICE }, +#ifdef CONFIG_MACH_VERSATILE_AB + { IO_ADDRESS(VERSATILE_GPIO0_BASE), VERSATILE_GPIO0_BASE, SZ_4K, MT_DEVICE }, + { IO_ADDRESS(VERSATILE_IB2_BASE), VERSATILE_IB2_BASE, SZ_64M, MT_DEVICE }, +#endif #ifdef CONFIG_DEBUG_LL { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE }, #endif @@ -198,7 +204,7 @@ static struct map_desc versatile_io_desc[] __initdata = { #endif }; -static void __init versatile_map_io(void) +void __init versatile_map_io(void) { iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc)); } @@ -206,7 +212,7 @@ static void __init versatile_map_io(void) #define VERSATILE_REFCOUNTER (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) /* - * This is the VersatilePB sched_clock implementation. This has + * This is the Versatile sched_clock implementation. This has * a resolution of 41.7ns, and a maximum value of about 179s. */ unsigned long long sched_clock(void) @@ -300,8 +306,7 @@ static struct platform_device smc91x_device = { #define VERSATILE_SYSMCI (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) -#ifdef CONFIG_MMC -static unsigned int mmc_status(struct device *dev) +unsigned int mmc_status(struct device *dev) { struct amba_device *adev = container_of(dev, struct amba_device, dev); u32 mask; @@ -319,29 +324,295 @@ static struct mmc_platform_data mmc0_plat_data = { .status = mmc_status, }; -static struct mmc_platform_data mmc1_plat_data = { - .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .status = mmc_status, +/* + * Clock handling + */ +static const struct icst307_params versatile_oscvco_params = { + .ref = 24000, + .vco_max = 200000, + .vd_min = 4 + 8, + .vd_max = 511 + 8, + .rd_min = 1 + 2, + .rd_max = 127 + 2, }; + +static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) +{ + unsigned long sys_lock = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; +#if defined(CONFIG_ARCH_VERSATILE_PB) + unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET; +#elif defined(CONFIG_MACH_VERSATILE_AB) + unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET; +#endif + u32 val; + + val = readl(sys_osc) & ~0x7ffff; + val |= vco.v | (vco.r << 9) | (vco.s << 16); + + writel(0xa05f, sys_lock); + writel(val, sys_osc); + writel(0, sys_lock); +} + +static struct clk versatile_clcd_clk = { + .name = "CLCDCLK", + .params = &versatile_oscvco_params, + .setvco = versatile_oscvco_set, +}; + +/* + * CLCD support. + */ +#define SYS_CLCD_MODE_MASK (3 << 0) +#define SYS_CLCD_MODE_888 (0 << 0) +#define SYS_CLCD_MODE_5551 (1 << 0) +#define SYS_CLCD_MODE_565_RLSB (2 << 0) +#define SYS_CLCD_MODE_565_BLSB (3 << 0) +#define SYS_CLCD_NLCDIOON (1 << 2) +#define SYS_CLCD_VDDPOSSWITCH (1 << 3) +#define SYS_CLCD_PWR3V5SWITCH (1 << 4) +#define SYS_CLCD_ID_MASK (0x1f << 8) +#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8) +#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8) +#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8) +#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) +#define SYS_CLCD_ID_VGA (0x1f << 8) + +static struct clcd_panel vga = { + .mode = { + .name = "VGA", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = 39721, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +static struct clcd_panel sanyo_3_8_in = { + .mode = { + .name = "Sanyo QVGA", + .refresh = 116, + .xres = 320, + .yres = 240, + .pixclock = 100000, + .left_margin = 6, + .right_margin = 6, + .upper_margin = 5, + .lower_margin = 5, + .hsync_len = 6, + .vsync_len = 6, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +static struct clcd_panel sanyo_2_5_in = { + .mode = { + .name = "Sanyo QVGA Portrait", + .refresh = 116, + .xres = 240, + .yres = 320, + .pixclock = 100000, + .left_margin = 20, + .right_margin = 10, + .upper_margin = 2, + .lower_margin = 2, + .hsync_len = 10, + .vsync_len = 2, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +static struct clcd_panel epson_2_2_in = { + .mode = { + .name = "Epson QCIF", + .refresh = 390, + .xres = 176, + .yres = 220, + .pixclock = 62500, + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 0, + .hsync_len = 3, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +/* + * Detect which LCD panel is connected, and return the appropriate + * clcd_panel structure. Note: we do not have any information on + * the required timings for the 8.4in panel, so we presently assume + * VGA timings. + */ +static struct clcd_panel *versatile_clcd_panel(void) +{ + unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + struct clcd_panel *panel = &vga; + u32 val; + + val = readl(sys_clcd) & SYS_CLCD_ID_MASK; + if (val == SYS_CLCD_ID_SANYO_3_8) + panel = &sanyo_3_8_in; + else if (val == SYS_CLCD_ID_SANYO_2_5) + panel = &sanyo_2_5_in; + else if (val == SYS_CLCD_ID_EPSON_2_2) + panel = &epson_2_2_in; + else if (val == SYS_CLCD_ID_VGA) + panel = &vga; + else { + printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n", + val); + panel = &vga; + } + + return panel; +} + +/* + * Disable all display connectors on the interface module. + */ +static void versatile_clcd_disable(struct clcd_fb *fb) +{ + unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + u32 val; + + val = readl(sys_clcd); + val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; + writel(val, sys_clcd); + +#ifdef CONFIG_MACH_VERSATILE_AB + /* + * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off + */ + if (fb->panel == &sanyo_2_5_in) { + unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL); + unsigned long ctrl; + + ctrl = readl(versatile_ib2_ctrl); + ctrl &= ~0x01; + writel(ctrl, versatile_ib2_ctrl); + } #endif +} + +/* + * Enable the relevant connector on the interface module. + */ +static void versatile_clcd_enable(struct clcd_fb *fb) +{ + unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + u32 val; + + val = readl(sys_clcd); + val &= ~SYS_CLCD_MODE_MASK; + + switch (fb->fb.var.green.length) { + case 5: + val |= SYS_CLCD_MODE_5551; + break; + case 6: + val |= SYS_CLCD_MODE_565_BLSB; + break; + case 8: + val |= SYS_CLCD_MODE_888; + break; + } -#define AMBA_DEVICE(name,busid,base,plat) \ -static struct amba_device name##_device = { \ - .dev = { \ - .coherent_dma_mask = ~0, \ - .bus_id = busid, \ - .platform_data = plat, \ - }, \ - .res = { \ - .start = VERSATILE_##base##_BASE, \ - .end = (VERSATILE_##base##_BASE) + SZ_4K - 1,\ - .flags = IORESOURCE_MEM, \ - }, \ - .dma_mask = ~0, \ - .irq = base##_IRQ, \ - /* .dma = base##_DMA,*/ \ + /* + * Set the MUX + */ + writel(val, sys_clcd); + + /* + * And now enable the PSUs + */ + val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; + writel(val, sys_clcd); + +#ifdef CONFIG_MACH_VERSATILE_AB + /* + * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on + */ + if (fb->panel == &sanyo_2_5_in) { + unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL); + unsigned long ctrl; + + ctrl = readl(versatile_ib2_ctrl); + ctrl |= 0x01; + writel(ctrl, versatile_ib2_ctrl); + } +#endif } +static unsigned long framesize = SZ_1M; + +static int versatile_clcd_setup(struct clcd_fb *fb) +{ + dma_addr_t dma; + + fb->panel = versatile_clcd_panel(); + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = framesize; + + return 0; +} + +static void versatile_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +static struct clcd_board clcd_plat_data = { + .name = "Versatile", + .check = clcdfb_check, + .decode = clcdfb_decode, + .disable = versatile_clcd_disable, + .enable = versatile_clcd_enable, + .setup = versatile_clcd_setup, + .remove = versatile_clcd_remove, +}; + #define AACI_IRQ { IRQ_AACI, NO_IRQ } #define AACI_DMA { 0x80, 0x81 } #define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B } @@ -350,12 +621,6 @@ static struct amba_device name##_device = { \ #define KMI0_DMA { 0, 0 } #define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ } #define KMI1_DMA { 0, 0 } -#define UART3_IRQ { IRQ_SIC_UART3, NO_IRQ } -#define UART3_DMA { 0x86, 0x87 } -#define SCI1_IRQ { IRQ_SIC_SCI3, NO_IRQ } -#define SCI1_DMA { 0x88, 0x89 } -#define MMCI1_IRQ { IRQ_MMCI1A, IRQ_SIC_MMCI1B } -#define MMCI1_DMA { 0x85, 0 } /* * These devices are connected directly to the multi-layer AHB switch @@ -380,10 +645,6 @@ static struct amba_device name##_device = { \ #define GPIO0_DMA { 0, 0 } #define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ } #define GPIO1_DMA { 0, 0 } -#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } -#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } #define RTC_IRQ { IRQ_RTCINT, NO_IRQ } #define RTC_DMA { 0, 0 } @@ -403,28 +664,19 @@ static struct amba_device name##_device = { \ /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); -#ifdef CONFIG_MMC AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &mmc0_plat_data); -#endif AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL); AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL); -AMBA_DEVICE(uart3, "fpga:09", UART3, NULL); -AMBA_DEVICE(sci1, "fpga:0a", SCI1, NULL); -#ifdef CONFIG_MMC -AMBA_DEVICE(mmc1, "fpga:0b", MMCI1, &mmc1_plat_data); -#endif /* DevChip Primecells */ AMBA_DEVICE(smc, "dev:00", SMC, NULL); AMBA_DEVICE(mpmc, "dev:10", MPMC, NULL); -AMBA_DEVICE(clcd, "dev:20", CLCD, NULL); +AMBA_DEVICE(clcd, "dev:20", CLCD, &clcd_plat_data); AMBA_DEVICE(dmac, "dev:30", DMAC, NULL); AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL); AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL); AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL); AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL); -AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL); -AMBA_DEVICE(gpio3, "dev:e7", GPIO3, NULL); AMBA_DEVICE(rtc, "dev:e8", RTC, NULL); AMBA_DEVICE(sci0, "dev:f0", SCI, NULL); AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); @@ -437,7 +689,6 @@ static struct amba_device *amba_devs[] __initdata = { &uart0_device, &uart1_device, &uart2_device, - &uart3_device, &smc_device, &mpmc_device, &clcd_device, @@ -445,23 +696,16 @@ static struct amba_device *amba_devs[] __initdata = { &wdog_device, &gpio0_device, &gpio1_device, - &gpio2_device, - &gpio3_device, &rtc_device, &sci0_device, &ssp0_device, &aaci_device, -#ifdef CONFIG_MMC &mmc0_device, -#endif &kmi0_device, &kmi1_device, - &sci1_device, -#ifdef CONFIG_MMC - &mmc1_device, -#endif }; +#ifdef CONFIG_LEDS #define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) static void versatile_leds_event(led_event_t ledevt) @@ -496,11 +740,14 @@ static void versatile_leds_event(led_event_t ledevt) writel(val, VA_LEDS_BASE); local_irq_restore(flags); } +#endif /* CONFIG_LEDS */ -static void __init versatile_init(void) +void __init versatile_init(void) { int i; + clk_register(&versatile_clcd_clk); + platform_device_register(&versatile_flash_device); platform_device_register(&smc91x_device); @@ -509,7 +756,9 @@ static void __init versatile_init(void) amba_device_register(d, &iomem_resource); } +#ifdef CONFIG_LEDS leds_event = versatile_leds_event; +#endif } /* @@ -551,8 +800,6 @@ typedef struct TimerStruct { unsigned long TimerClear; } TimerStruct_t; -extern unsigned long (*gettimeoffset)(void); - /* * Returns number of ms since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() @@ -601,11 +848,15 @@ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_re { volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; + write_seqlock(&xtime_lock); + // ...clear the interrupt timer0->TimerClear = 1; timer_tick(regs); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -618,7 +869,7 @@ static struct irqaction versatile_timer_irq = { /* * Set up timer interrupt, and return the current time in seconds. */ -void __init versatile_init_time(void) +static void __init versatile_timer_init(void) { volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; @@ -650,15 +901,9 @@ void __init versatile_init_time(void) * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); - gettimeoffset = versatile_gettimeoffset; } -MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") - MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd") - BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000) - BOOT_PARAMS(0x00000100) - MAPIO(versatile_map_io) - INITIRQ(versatile_init_irq) - INITTIME(versatile_init_time) - INIT_MACHINE(versatile_init) -MACHINE_END +struct sys_timer versatile_timer = { + .init = versatile_timer_init, + .offset = versatile_gettimeoffset, +}; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 545a548b1..787daaa3a 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -14,6 +14,7 @@ config CPU_ARM610 depends on ARCH_RPC select CPU_32v3 select CPU_CACHE_V3 + select CPU_CACHE_VIVT select CPU_COPY_V3 select CPU_TLB_V3 help @@ -29,6 +30,7 @@ config CPU_ARM710 default y if ARCH_CLPS7500 select CPU_32v3 select CPU_CACHE_V3 + select CPU_CACHE_VIVT select CPU_COPY_V3 select CPU_TLB_V3 help @@ -43,10 +45,11 @@ config CPU_ARM710 # ARM720T config CPU_ARM720T bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR - default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 + default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X select CPU_32v4 select CPU_ABRT_LV4T select CPU_CACHE_V4 + select CPU_CACHE_VIVT select CPU_COPY_V4WT select CPU_TLB_V4WT help @@ -59,11 +62,12 @@ config CPU_ARM720T # ARM920T config CPU_ARM920T bool "Support ARM920T processor" if !ARCH_S3C2410 - depends on ARCH_INTEGRATOR || ARCH_S3C2410 + depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX default y if ARCH_S3C2410 select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI help @@ -84,6 +88,7 @@ config CPU_ARM922T select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI help @@ -102,6 +107,7 @@ config CPU_ARM925T select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI help @@ -115,10 +121,11 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" if ARCH_INTEGRATOR - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912 - default y if ARCH_VERSATILE_PB + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB select CPU_32v5 select CPU_ABRT_EV5TJ + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI help @@ -136,6 +143,7 @@ config CPU_ARM1020 select CPU_32v5 select CPU_ABRT_EV4T select CPU_CACHE_V4WT + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI help @@ -152,6 +160,7 @@ config CPU_ARM1020E select CPU_32v5 select CPU_ABRT_EV4T select CPU_CACHE_V4WT + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WBI depends on n @@ -162,6 +171,7 @@ config CPU_ARM1022 depends on ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T + select CPU_CACHE_VIVT select CPU_COPY_V4WB # can probably do better select CPU_TLB_V4WBI help @@ -178,6 +188,7 @@ config CPU_ARM1026 depends on ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10 + select CPU_CACHE_VIVT select CPU_COPY_V4WB # can probably do better select CPU_TLB_V4WBI help @@ -195,6 +206,7 @@ config CPU_SA110 select CPU_32v4 if !ARCH_RPC select CPU_ABRT_EV4 select CPU_CACHE_V4WB + select CPU_CACHE_VIVT select CPU_COPY_V4WB select CPU_TLB_V4WB help @@ -214,16 +226,18 @@ config CPU_SA1100 select CPU_32v4 select CPU_ABRT_EV4 select CPU_CACHE_V4WB + select CPU_CACHE_VIVT select CPU_TLB_V4WB select CPU_MINICACHE # XScale config CPU_XSCALE bool - depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX + depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000 default y select CPU_32v5 select CPU_ABRT_EV5T + select CPU_CACHE_VIVT select CPU_TLB_V4WBI select CPU_MINICACHE @@ -234,6 +248,7 @@ config CPU_V6 select CPU_32v6 select CPU_ABRT_EV6 select CPU_CACHE_V6 + select CPU_CACHE_VIPT select CPU_COPY_V6 select CPU_TLB_V6 @@ -286,6 +301,12 @@ config CPU_CACHE_V4WB config CPU_CACHE_V6 bool +config CPU_CACHE_VIVT + bool + +config CPU_CACHE_VIPT + bool + # The copy-page model config CPU_COPY_V3 bool diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index fc764e17e..ccf316c11 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -3,7 +3,8 @@ # obj-y := consistent.o extable.o fault-armv.o \ - fault.o init.o ioremap.o mmap.o mm-armv.o + fault.o flush.o init.o ioremap.o mmap.o \ + mm-armv.o obj-$(CONFIG_MODULES) += proc-syms.o diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S index 922e05a4d..fd0584a92 100644 --- a/arch/arm/mm/abort-ev5tj.S +++ b/arch/arm/mm/abort-ev5tj.S @@ -23,7 +23,6 @@ ENTRY(v5tj_early_abort) mrc p15, 0, r0, c6, c0, 0 @ get FAR bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR tst r3, #PSR_J_BIT @ Java? - orrne r1, r1, #1 << 11 @ always assume write movne pc, lr tst r3, #PSR_T_BIT @ Thumb? ldrneh r3, [r2] @ read aborted thumb instruction diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index 6659439f6..e1994788c 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -57,6 +57,19 @@ ENTRY(v3_flush_user_cache_range) * - end - virtual end address */ ENTRY(v3_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v3_coherent_user_range) mov pc, lr /* @@ -116,6 +129,7 @@ ENTRY(v3_cache_fns) .long v3_flush_user_cache_all .long v3_flush_user_cache_range .long v3_coherent_kern_range + .long v3_coherent_user_range .long v3_flush_kern_dcache_page .long v3_dma_inv_range .long v3_dma_clean_range diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index bbc822f16..b8ad5d58e 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -59,6 +59,19 @@ ENTRY(v4_flush_user_cache_range) * - end - virtual end address */ ENTRY(v4_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4_coherent_user_range) mov pc, lr /* @@ -118,6 +131,7 @@ ENTRY(v4_cache_fns) .long v4_flush_user_cache_all .long v4_flush_user_cache_range .long v4_coherent_kern_range + .long v4_coherent_user_range .long v4_flush_kern_dcache_page .long v4_dma_inv_range .long v4_dma_clean_range diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 4f7c918e6..5c4055b62 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -121,6 +121,19 @@ ENTRY(v4wb_flush_kern_dcache_page) * - end - virtual end address */ ENTRY(v4wb_coherent_kern_range) + /* fall through */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wb_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry @@ -195,6 +208,7 @@ ENTRY(v4wb_cache_fns) .long v4wb_flush_user_cache_all .long v4wb_flush_user_cache_range .long v4wb_coherent_kern_range + .long v4wb_coherent_user_range .long v4wb_flush_kern_dcache_page .long v4wb_dma_inv_range .long v4wb_dma_clean_range diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 61c9fc60f..9bcabd86c 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -97,6 +97,19 @@ ENTRY(v4wt_flush_user_cache_range) * - end - virtual end address */ ENTRY(v4wt_coherent_kern_range) + /* FALLTRHOUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(v4wt_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry add r0, r0, #CACHE_DLINESIZE @@ -167,6 +180,7 @@ ENTRY(v4wt_cache_fns) .long v4wt_flush_user_cache_all .long v4wt_flush_user_cache_range .long v4wt_coherent_kern_range + .long v4wt_coherent_user_range .long v4wt_flush_kern_dcache_page .long v4wt_dma_inv_range .long v4wt_dma_clean_range diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 336aa0e40..85c10a71e 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -75,6 +75,22 @@ ENTRY(v6_flush_user_cache_range) * - the Icache does not read data from the write buffer */ ENTRY(v6_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * v6_coherent_user_range(start,end) + * + * Ensure that the I and D caches are coherent within specified + * region. This is typically used when code has been written to + * a memory region, and will be executed. + * + * - start - virtual start address of region + * - end - virtual end address of region + * + * It is assumed that: + * - the Icache does not read data from the write buffer + */ +ENTRY(v6_coherent_user_range) bic r0, r0, #CACHE_LINE_SIZE - 1 1: #ifdef HARVARD_CACHE @@ -203,6 +219,7 @@ ENTRY(v6_cache_fns) .long v6_flush_user_cache_all .long v6_flush_user_cache_range .long v6_coherent_kern_range + .long v6_coherent_user_range .long v6_flush_kern_dcache_page .long v6_dma_inv_range .long v6_dma_clean_range diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index f9b8fe2c7..57b0be2ab 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -138,7 +138,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, struct page *page; struct vm_region *c; unsigned long order; - u64 mask = 0x00ffffff, limit; /* ISA default */ + u64 mask = ISA_DMA_THRESHOLD, limit; if (!consistent_pte) { printk(KERN_ERR "%s: not initialised\n", __func__); @@ -148,19 +148,34 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, if (dev) { mask = dev->coherent_dma_mask; + + /* + * Sanity check the DMA mask - it must be non-zero, and + * must be able to be satisfied by a DMA allocation. + */ if (mask == 0) { dev_warn(dev, "coherent DMA mask is unset\n"); - return NULL; + goto no_page; + } + + if ((~mask) & ISA_DMA_THRESHOLD) { + dev_warn(dev, "coherent DMA mask %#llx is smaller " + "than system GFP_DMA mask %#llx\n", + mask, (unsigned long long)ISA_DMA_THRESHOLD); + goto no_page; } } + /* + * Sanity check the allocation size. + */ size = PAGE_ALIGN(size); limit = (mask + 1) & ~mask; - if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) { - printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n", - size, mask); - *handle = ~0; - return NULL; + if ((limit && size >= limit) || + size >= (CONSISTENT_END - CONSISTENT_BASE)) { + printk(KERN_WARNING "coherent allocation too big " + "(requested %#x mask %#llx)\n", size, mask); + goto no_page; } order = get_order(size); @@ -221,6 +236,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp, if (page) __free_pages(page, order); no_page: + *handle = ~0; return NULL; } diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index e6a139ee2..76dcfc9ba 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -15,6 +15,7 @@ #include #include #include +#include #if SHMLBA > 16384 #error FIX ME @@ -31,14 +32,46 @@ static spinlock_t v6_lock = SPIN_LOCK_UNLOCKED; #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) +/* + * Copy the user page. No aliasing to deal with so we can just + * attack the kernel's existing mapping of these pages. + */ +void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr) +{ + copy_page(kto, kfrom); +} + +/* + * Clear the user page. No aliasing to deal with so we can just + * attack the kernel's existing mapping of this page. + */ +void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr) +{ + clear_page(kaddr); +} + /* * Copy the page, taking account of the cache colour. */ -void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) +void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr) { unsigned int offset = DCACHE_COLOUR(vaddr); unsigned long from, to; + /* + * Discard data in the kernel mapping for the new page. + * FIXME: needs this MCRR to be supported. + */ + __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" + : + : "r" (kto), + "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES) + : "cc"); + + /* + * Now copy the page using the same cache colour as the + * pages ultimate destination. + */ spin_lock(&v6_lock); set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); @@ -55,11 +88,30 @@ void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) spin_unlock(&v6_lock); } -void v6_clear_user_page(void *kaddr, unsigned long vaddr) +/* + * Clear the user page. We need to deal with the aliasing issues, + * so remap the kernel page into the same cache colour as the user + * page. + */ +void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) { unsigned int offset = DCACHE_COLOUR(vaddr); unsigned long to = to_address + (offset << PAGE_SHIFT); + /* + * Discard data in the kernel mapping for the new page + * FIXME: needs this MCRR to be supported. + */ + __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" + : + : "r" (kaddr), + "r" ((unsigned long)kaddr + PAGE_SIZE - L1_CACHE_BYTES) + : "cc"); + + /* + * Now clear the page using the same cache colour as + * the pages ultimate destination. + */ spin_lock(&v6_lock); set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); @@ -70,26 +122,31 @@ void v6_clear_user_page(void *kaddr, unsigned long vaddr) } struct cpu_user_fns v6_user_fns __initdata = { - .cpu_clear_user_page = v6_clear_user_page, - .cpu_copy_user_page = v6_copy_user_page, + .cpu_clear_user_page = v6_clear_user_page_nonaliasing, + .cpu_copy_user_page = v6_copy_user_page_nonaliasing, }; static int __init v6_userpage_init(void) { - pgd_t *pgd; - pmd_t *pmd; - - pgd = pgd_offset_k(from_address); - pmd = pmd_alloc(&init_mm, pgd, from_address); - if (!pmd) - BUG(); - from_pte = pte_alloc_kernel(&init_mm, pmd, from_address); - if (!from_pte) - BUG(); - - to_pte = pte_alloc_kernel(&init_mm, pmd, to_address); - if (!to_pte) - BUG(); + if (cache_is_vipt_aliasing()) { + pgd_t *pgd; + pmd_t *pmd; + + pgd = pgd_offset_k(from_address); + pmd = pmd_alloc(&init_mm, pgd, from_address); + if (!pmd) + BUG(); + from_pte = pte_alloc_kernel(&init_mm, pmd, from_address); + if (!from_pte) + BUG(); + + to_pte = pte_alloc_kernel(&init_mm, pmd, to_address); + if (!to_pte) + BUG(); + + cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing; + cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing; + } return 0; } diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index d03940c1b..5f0a79094 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -76,59 +76,12 @@ no_pmd: return 0; } -static void __flush_dcache_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - struct mm_struct *mm = current->active_mm; - struct vm_area_struct *mpnt = NULL; - struct prio_tree_iter iter; - unsigned long offset; - pgoff_t pgoff; - - __cpuc_flush_dcache_page(page_address(page)); - - if (!mapping) - return; - - /* - * With a VIVT cache, we need to also write back - * and invalidate any user data. - */ - pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - - flush_dcache_mmap_lock(mapping); - while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, - &iter, pgoff, pgoff)) != NULL) { - /* - * If this VMA is not in our MM, we can ignore it. - */ - if (mpnt->vm_mm != mm) - continue; - if (!(mpnt->vm_flags & VM_MAYSHARE)) - continue; - offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; - flush_cache_page(mpnt, mpnt->vm_start + offset); - } - flush_dcache_mmap_unlock(mapping); -} - -void flush_dcache_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - - if (mapping && !mapping_mapped(mapping)) - set_bit(PG_dcache_dirty, &page->flags); - else - __flush_dcache_page(page); -} -EXPORT_SYMBOL(flush_dcache_page); - static void make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) { struct address_space *mapping = page_mapping(page); struct mm_struct *mm = vma->vm_mm; - struct vm_area_struct *mpnt = NULL; + struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; pgoff_t pgoff; @@ -145,8 +98,7 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, * cache coherency. */ flush_dcache_mmap_lock(mapping); - while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, - &iter, pgoff, pgoff)) != NULL) { + vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) { /* * If this VMA is not in our MM, we can ignore it. * Note that we intentionally mask out the VMA @@ -190,10 +142,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) if (page_mapping(page)) { int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - if (dirty) + if (dirty) { + /* + * This is our first userspace mapping of this page. + * Ensure that the physical page is coherent with + * the kernel mapping. + * + * FIXME: only need to do this on VIVT and aliasing + * VIPT cache architectures. We can do that + * by choosing whether to set this bit... + */ __cpuc_flush_dcache_page(page_address(page)); + } - make_coherent(vma, addr, page, dirty); + if (cache_is_vivt()) + make_coherent(vma, addr, page, dirty); } } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 060fea2e1..51f3be19e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern char _stext, _text, _etext, _end, __init_begin, __init_end; +extern void _stext, _text, _etext, __data_start, _end, __init_begin, __init_end; extern unsigned long phys_initrd_start; extern unsigned long phys_initrd_size; @@ -281,7 +282,11 @@ static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot * Register the kernel text and data with bootmem. * Note that this can only be in node 0. */ +#ifdef CONFIG_XIP_KERNEL + reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start); +#else reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext); +#endif /* * Reserve the page tables. These are already in use, @@ -344,7 +349,7 @@ static inline void free_bootmem_node_bank(int node, struct meminfo *mi) * Initialise the bootmem allocator for all nodes. This is called * early during the architecture specific initialisation. */ -void __init bootmem_init(struct meminfo *mi) +static void __init bootmem_init(struct meminfo *mi) { struct node_info node_info[MAX_NUMNODES], *np = node_info; unsigned int bootmap_pages, bootmap_pfn, map_pg; @@ -412,9 +417,7 @@ void __init bootmem_init(struct meminfo *mi) } #endif - if (map_pg != bootmap_pfn + bootmap_pages) - BUG(); - + BUG_ON(map_pg != bootmap_pfn + bootmap_pages); } /* @@ -426,6 +429,8 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) void *zero_page; int node; + bootmem_init(mi); + memcpy(&meminfo, mi, sizeof(meminfo)); /* @@ -495,7 +500,7 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) */ arch_adjust_zones(node, zone_size, zhole_size); - free_area_init_node(node, pgdat, NULL, zone_size, + free_area_init_node(node, pgdat, zone_size, bdata->node_boot_start >> PAGE_SHIFT, zhole_size); } @@ -539,7 +544,7 @@ void __init mem_init(void) int i, node; codepages = &_etext - &_text; - datapages = &_end - &_etext; + datapages = &_end - &__data_start; initpages = &__init_end - &__init_begin; #ifndef CONFIG_DISCONTIGMEM @@ -590,7 +595,7 @@ void __init mem_init(void) * anywhere without overcommit, so turn * it on by default. */ - sysctl_overcommit_memory = 1; + sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; } } diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index e2daf066e..49a57b9f0 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -130,7 +130,7 @@ remap_area_pages(unsigned long start, unsigned long phys_addr, * 'flags' are the extra L_PTE_ flags that you want to specify for this * mapping. See include/asm-arm/proc-armv/pgtable.h for more information. */ -void * +void __iomem * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags, unsigned long align) { @@ -161,11 +161,11 @@ __ioremap(unsigned long phys_addr, size_t size, unsigned long flags, vfree(addr); return NULL; } - return (void *) (offset + (char *)addr); + return (void __iomem *) (offset + (char *)addr); } EXPORT_SYMBOL(__ioremap); -void __iounmap(void *addr) +void __iounmap(void __iomem *addr) { vfree((void *) (PAGE_MASK & (unsigned long) addr)); } diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 50c2c0f8d..9150033e8 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -158,7 +158,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) init_pgd = pgd_offset_k(0); - if (vectors_base() == 0) { + if (!vectors_high()) { /* * This lock is here just to satisfy pmd_alloc and pte_lock */ @@ -317,15 +317,25 @@ static struct mem_types mem_types[] __initdata = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_MINICACHE, .domain = DOMAIN_KERNEL, }, - [MT_VECTORS] = { + [MT_LOW_VECTORS] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_EXEC, .prot_l1 = PMD_TYPE_TABLE, .domain = DOMAIN_USER, }, + [MT_HIGH_VECTORS] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_EXEC, + .prot_l1 = PMD_TYPE_TABLE, + .domain = DOMAIN_USER, + }, [MT_MEMORY] = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, + }, + [MT_ROM] = { + .prot_sect = PMD_TYPE_SECT, + .domain = DOMAIN_KERNEL, } }; @@ -353,12 +363,12 @@ static void __init build_mem_type_table(void) } if (cpu_arch <= CPU_ARCH_ARMv5) { - mem_types[MT_DEVICE].prot_l1 |= PMD_BIT4; - mem_types[MT_DEVICE].prot_sect |= PMD_BIT4; - mem_types[MT_CACHECLEAN].prot_sect |= PMD_BIT4; - mem_types[MT_MINICLEAN].prot_sect |= PMD_BIT4; - mem_types[MT_VECTORS].prot_l1 |= PMD_BIT4; - mem_types[MT_MEMORY].prot_sect |= PMD_BIT4; + for (i = 0; i < ARRAY_SIZE(mem_types); i++) { + if (mem_types[i].prot_l1) + mem_types[i].prot_l1 |= PMD_BIT4; + if (mem_types[i].prot_sect) + mem_types[i].prot_sect |= PMD_BIT4; + } } /* @@ -370,6 +380,7 @@ static void __init build_mem_type_table(void) * kernel memory mapping. */ mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; + mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; /* * Mark cache clean areas read only from SVC mode * and no access from userspace. @@ -381,14 +392,18 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; if (cpu_arch >= CPU_ARCH_ARMv5) { - mem_types[MT_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; + mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; + mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; } else { - mem_types[MT_VECTORS].prot_pte |= cp->pte; + mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte; + mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte; mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); } - mem_types[MT_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_ROM].prot_sect |= cp->pmd; for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); @@ -413,6 +428,8 @@ static void __init build_mem_type_table(void) ecc_mask ? "en" : "dis", cp->policy); } +#define vectors_base() (vectors_high() ? 0xffff0000 : 0) + /* * Create the page directory entries and any necessary * page tables for the mapping specified by `md'. We @@ -426,14 +443,14 @@ static void __init create_mapping(struct map_desc *md) pgprot_t prot_pte; long off; - if (md->virtual != vectors_base() && md->virtual < PAGE_OFFSET) { + if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { printk(KERN_WARNING "BUG: not creating mapping for " "0x%08lx at 0x%08lx in user region\n", md->physical, md->virtual); return; } - if (md->type == MT_DEVICE && + if ((md->type == MT_DEVICE || md->type == MT_ROM) && md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " "overlaps vmalloc space\n", @@ -508,6 +525,8 @@ void setup_mm_for_reboot(char mode) } } +extern void _stext, _etext; + /* * Setup initial mappings. We use the page we allocated for zero page to hold * the mappings, which will get overwritten by the vectors in traps_init(). @@ -523,6 +542,14 @@ void __init memtable_init(struct meminfo *mi) init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE); +#ifdef CONFIG_XIP_KERNEL + p->physical = CONFIG_XIP_PHYS_ADDR & PMD_MASK; + p->virtual = (unsigned long)&_stext & PMD_MASK; + p->length = ((unsigned long)&_etext - p->virtual + ~PMD_MASK) & PMD_MASK; + p->type = MT_ROM; + p ++; +#endif + for (i = 0; i < mi->nr_banks; i++) { if (mi->bank[i].size == 0) continue; @@ -570,16 +597,22 @@ void __init memtable_init(struct meminfo *mi) } while (address != 0); /* - * Create a mapping for the machine vectors at virtual address 0 - * or 0xffff0000. We should always try the high mapping. + * Create a mapping for the machine vectors at the high-vectors + * location (0xffff0000). If we aren't using high-vectors, also + * create a mapping at the low-vectors virtual address. */ init_maps->physical = virt_to_phys(init_maps); - init_maps->virtual = vectors_base(); + init_maps->virtual = 0xffff0000; init_maps->length = PAGE_SIZE; - init_maps->type = MT_VECTORS; - + init_maps->type = MT_HIGH_VECTORS; create_mapping(init_maps); + if (!vectors_high()) { + init_maps->virtual = 0; + init_maps->type = MT_LOW_VECTORS; + create_mapping(init_maps); + } + flush_cache_all(); flush_tlb_all(); } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 7fe21a95d..1267ab586 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -196,6 +196,19 @@ ENTRY(arm1020_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm1020_coherent_kern_range) + /* FALLTRHOUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm1020_coherent_user_range) mov ip, #0 bic r0, r0, #CACHE_DLINESIZE - 1 mcr p15, 0, ip, c7, c10, 4 @@ -317,6 +330,7 @@ ENTRY(arm1020_cache_fns) .long arm1020_flush_user_cache_all .long arm1020_flush_user_cache_range .long arm1020_coherent_kern_range + .long arm1020_coherent_user_range .long arm1020_flush_kern_dcache_page .long arm1020_dma_inv_range .long arm1020_dma_clean_range diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 0332c3e69..947790dd3 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -193,6 +193,18 @@ ENTRY(arm1020e_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm1020e_coherent_kern_range) + /* FALLTHROUGH */ +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm1020e_coherent_user_range) mov ip, #0 bic r0, r0, #CACHE_DLINESIZE - 1 1: @@ -304,6 +316,7 @@ ENTRY(arm1020e_cache_fns) .long arm1020e_flush_user_cache_all .long arm1020e_flush_user_cache_range .long arm1020e_coherent_kern_range + .long arm1020e_coherent_user_range .long arm1020e_flush_kern_dcache_page .long arm1020e_dma_inv_range .long arm1020e_dma_clean_range @@ -495,7 +508,7 @@ __arm1020e_proc_info: b __arm1020e_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP .long cpu_arm1020e_name .long arm1020e_processor_functions .long v4wbi_tlb_fns diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 35a5c2f00..7c8426384 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -180,6 +180,19 @@ ENTRY(arm1022_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm1022_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm1022_coherent_user_range) mov ip, #0 bic r0, r0, #CACHE_DLINESIZE - 1 1: @@ -291,6 +304,7 @@ ENTRY(arm1022_cache_fns) .long arm1022_flush_user_cache_all .long arm1022_flush_user_cache_range .long arm1022_coherent_kern_range + .long arm1022_coherent_user_range .long arm1022_flush_kern_dcache_page .long arm1022_dma_inv_range .long arm1022_dma_clean_range @@ -475,7 +489,7 @@ __arm1022_proc_info: b __arm1022_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP .long cpu_arm1022_name .long arm1022_processor_functions .long v4wbi_tlb_fns diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 0009f2d27..38a06cb1e 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -175,6 +175,18 @@ ENTRY(arm1026_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm1026_coherent_kern_range) + /* FALLTHROUGH */ +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm1026_coherent_user_range) mov ip, #0 bic r0, r0, #CACHE_DLINESIZE - 1 1: @@ -286,6 +298,7 @@ ENTRY(arm1026_cache_fns) .long arm1026_flush_user_cache_all .long arm1026_flush_user_cache_range .long arm1026_coherent_kern_range + .long arm1026_coherent_user_range .long arm1026_flush_kern_dcache_page .long arm1026_dma_inv_range .long arm1026_dma_clean_range @@ -471,7 +484,7 @@ __arm1026_proc_info: b __arm1026_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA .long cpu_arm1026_name .long arm1026_processor_functions .long v4wbi_tlb_fns diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index 3bddde053..272d45e6a 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -138,7 +138,7 @@ __arm710_setup: mov r0, #0 bic r0, r0, #0x0e00 @ ..V. ..RS BLDP WCAM orr r0, r0, #0x0100 @ .... .... .111 .... (old) orr r0, r0, #0x003d @ .... ..01 ..11 1101 (new) - mov pc, lr @ __ret (head-armv.S) + mov pc, lr @ __ret (head.S) .size __arm710_setup, . - __arm710_setup .type __arm720_setup, #function @@ -153,7 +153,7 @@ __arm720_setup: mov r0, #0 bic r0, r0, #0x0e00 @ ..V. ..RS BLDP WCAM orr r0, r0, #0x2100 @ .... .... .111 .... (old) orr r0, r0, #0x003d @ ..1. ..01 ..11 1101 (new) - mov pc, lr @ __ret (head-armv.S) + mov pc, lr @ __ret (head.S) .size __arm720_setup, . - __arm720_setup __INITDATA diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 3922a8213..8c9204a7c 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -182,6 +182,19 @@ ENTRY(arm920_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm920_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm920_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry @@ -277,6 +290,7 @@ ENTRY(arm920_cache_fns) .long arm920_flush_user_cache_all .long arm920_flush_user_cache_range .long arm920_coherent_kern_range + .long arm920_coherent_user_range .long arm920_flush_kern_dcache_page .long arm920_dma_inv_range .long arm920_dma_clean_range diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 86065117c..13e65cb8a 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -184,6 +184,19 @@ ENTRY(arm922_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm922_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm922_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry @@ -279,6 +292,7 @@ ENTRY(arm922_cache_fns) .long arm922_flush_user_cache_all .long arm922_flush_user_cache_range .long arm922_coherent_kern_range + .long arm922_coherent_user_range .long arm922_flush_kern_dcache_page .long arm922_dma_inv_range .long arm922_dma_clean_range diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 917eb5e16..e8b3ff1fb 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -225,6 +225,19 @@ ENTRY(arm925_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm925_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm925_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry @@ -329,6 +342,7 @@ ENTRY(arm925_cache_fns) .long arm925_flush_user_cache_all .long arm925_flush_user_cache_range .long arm925_coherent_kern_range + .long arm925_coherent_user_range .long arm925_flush_kern_dcache_page .long arm925_dma_inv_range .long arm925_dma_clean_range diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 9b098e05c..5631c8bbd 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -185,6 +185,19 @@ ENTRY(arm926_flush_user_cache_range) * - end - virtual end address */ ENTRY(arm926_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm926_coherent_user_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry @@ -289,6 +302,7 @@ ENTRY(arm926_cache_fns) .long arm926_flush_user_cache_all .long arm926_flush_user_cache_range .long arm926_coherent_kern_range + .long arm926_coherent_user_range .long arm926_flush_kern_dcache_page .long arm926_dma_inv_range .long arm926_dma_clean_range @@ -473,7 +487,7 @@ __arm926_proc_info: b __arm926_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA .long cpu_arm926_name .long arm926_processor_functions .long v4wbi_tlb_fns diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c index 8df666f8d..6c5f0fe57 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -22,10 +22,10 @@ EXPORT_SYMBOL(processor); #endif #ifndef MULTI_CACHE -EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all); -EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all); -EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range); -EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range); +EXPORT_SYMBOL(__cpuc_flush_kern_all); +EXPORT_SYMBOL(__cpuc_flush_user_all); +EXPORT_SYMBOL(__cpuc_flush_user_range); +EXPORT_SYMBOL(__cpuc_coherent_kern_range); #else EXPORT_SYMBOL(cpu_cache); #endif diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index c22cc3601..fa3a5dd42 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -189,12 +189,10 @@ cpu_v6_name: * - cache type register is implemented */ __v6_setup: - mrc p15, 0, r10, c0, c0, 1 @ read cache type register - tst r10, #1 << 24 @ Harvard cache? mov r10, #0 - mcrne p15, 0, r10, c7, c14, 0 @ clean+invalidate D cache - mcrne p15, 0, r10, c7, c5, 0 @ invalidate I cache - mcreq p15, 0, r10, c7, c15, 0 @ clean+invalidate cache + mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D cache + mcr p15, 0, r10, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r10, c7, c15, 0 @ clean+invalidate cache mcr p15, 0, r10, c7, c10, 4 @ drain write buffer mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r10, c2, c0, 2 @ TTB control register @@ -203,6 +201,11 @@ __v6_setup: mov r10, #0x1f @ domains 0, 1 = manager mcr p15, 0, r10, c3, c0, 0 @ load domain access register mrc p15, 0, r0, c1, c0, 0 @ read control register +#ifdef CONFIG_VFP + mrc p15, 0, r10, c1, c0, 2 + orr r10, r10, #(3 << 20) + mcr p15, 0, r10, c1, c0, 2 @ Enable full access to VFP +#endif ldr r10, cr1_clear @ get mask for bits to clear bic r0, r0, r10 @ clear bits them ldr r10, cr1_set @ get mask for bits to set @@ -252,13 +255,13 @@ cpu_elf_name: */ .type __v6_proc_info, #object __v6_proc_info: - .long 0x00070000 - .long 0x00ff0000 + .long 0x0007b000 + .long 0x0007f000 .long 0x00000c0e b __v6_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP | HWCAP_HALF | HWCAP_FAST_MULT | HWCAP_VFP + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA .long cpu_v6_name .long v6_processor_functions .long v6wbi_tlb_fns diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 2652d141f..495167ca2 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -241,6 +241,22 @@ ENTRY(xscale_flush_user_cache_range) * it also trashes the mini I-cache used by JTAG debuggers. */ ENTRY(xscale_coherent_kern_range) + /* FALLTHROUGH */ + +/* + * coherent_user_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + * + * Note: single I-cache line invalidation isn't used here since + * it also trashes the mini I-cache used by JTAG debuggers. + */ +ENTRY(xscale_coherent_user_range) bic r0, r0, #CACHELINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHELINESIZE @@ -341,6 +357,7 @@ ENTRY(xscale_cache_fns) .long xscale_flush_user_cache_all .long xscale_flush_user_cache_range .long xscale_coherent_kern_range + .long xscale_coherent_user_range .long xscale_flush_kern_dcache_page .long xscale_dma_inv_range .long xscale_dma_clean_range @@ -585,7 +602,12 @@ __xscale_setup: mcr p15, 0, r4, c2, c0, 0 @ load page table pointer mov r0, #0x1f @ Domains 0, 1 = client mcr p15, 0, r0, c3, c0, 0 @ load domain access register - mov r0, #1 @ Allow access to CP0 and CP13 +#ifdef CONFIG_IWMMXT + mov r0, #0 @ initially disallow access to CP0/CP1 +#else + mov r0, #1 @ Allow access to CP0 +#endif + orr r0, r0, #1 << 6 @ cp6 for IOP3xx and Bulverde orr r0, r0, #1 << 13 @ Its undefined whether this mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes mrc p15, 0, r0, c1, c0, 0 @ get control register @@ -632,10 +654,15 @@ cpu_80200_name: .asciz "XScale-80200" .size cpu_80200_name, . - cpu_80200_name - .type cpu_80321_name, #object -cpu_80321_name: - .asciz "XScale-IOP80321" - .size cpu_80321_name, . - cpu_80321_name + .type cpu_8032x_name, #object +cpu_8032x_name: + .asciz "XScale-IOP8032x Family" + .size cpu_8032x_name, . - cpu_8032x_name + + .type cpu_8033x_name, #object +cpu_8033x_name: + .asciz "XScale-IOP8033x Family" + .size cpu_8033x_name, . - cpu_8033x_name .type cpu_pxa250_name, #object cpu_pxa250_name: @@ -652,6 +679,21 @@ cpu_ixp42x_name: .asciz "XScale-IXP42x Family" .size cpu_ixp42x_name, . - cpu_ixp42x_name + .type cpu_ixp46x_name, #object +cpu_ixp46x_name: + .asciz "XScale-IXP46x Family" + .size cpu_ixp46x_name, . - cpu_ixp46x_name + + .type cpu_ixp2400_name, #object +cpu_ixp2400_name: + .asciz "XScale-IXP2400" + .size cpu_ixp2400_name, . - cpu_ixp2400_name + + .type cpu_ixp2800_name, #object +cpu_ixp2800_name: + .asciz "XScale-IXP2800" + .size cpu_ixp2800_name, . - cpu_ixp2800_name + .type cpu_pxa255_name, #object cpu_pxa255_name: .asciz "XScale-PXA255" @@ -682,21 +724,37 @@ __80200_proc_info: .long xscale_cache_fns .size __80200_proc_info, . - __80200_proc_info - .type __80321_proc_info,#object -__80321_proc_info: + .type __8032x_proc_info,#object +__8032x_proc_info: .long 0x69052420 - .long 0xfffff7e0 + .long 0xfffff5e0 @ mask should accomodate IOP80219 also .long 0x00000c0e b __xscale_setup .long cpu_arch_name .long cpu_elf_name .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_80321_name + .long cpu_8032x_name .long xscale_processor_functions .long v4wbi_tlb_fns .long xscale_mc_user_fns .long xscale_cache_fns - .size __80321_proc_info, . - __80321_proc_info + .size __8032x_proc_info, . - __8032x_proc_info + + .type __8033x_proc_info,#object +__8033x_proc_info: + .long 0x69054090 + .long 0xffffffb0 + .long 0x00000c0e + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_8033x_name + .long xscale_processor_functions + .long v4wbi_tlb_fns + .long xscale_mc_user_fns + .long xscale_cache_fns + .size __8033x_proc_info, . - __8033x_proc_info .type __pxa250_proc_info,#object __pxa250_proc_info: @@ -730,6 +788,38 @@ __pxa210_proc_info: .long xscale_cache_fns .size __pxa210_proc_info, . - __pxa210_proc_info + .type __ixp2400_proc_info, #object +__ixp2400_proc_info: + .long 0x69054190 + .long 0xfffffff0 + .long 0x00000c0e + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_ixp2400_name + .long xscale_processor_functions + .long v4wbi_tlb_fns + .long xscale_mc_user_fns + .long xscale_cache_fns + .size __ixp2400_proc_info, . - __ixp2400_proc_info + + .type __ixp2800_proc_info, #object +__ixp2800_proc_info: + .long 0x690541a0 + .long 0xfffffff0 + .long 0x00000c0e + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_ixp2800_name + .long xscale_processor_functions + .long v4wbi_tlb_fns + .long xscale_mc_user_fns + .long xscale_cache_fns + .size __ixp2800_proc_info, . - __ixp2800_proc_info + .type __ixp42x_proc_info, #object __ixp42x_proc_info: .long 0x690541c0 @@ -746,6 +836,22 @@ __ixp42x_proc_info: .long xscale_cache_fns .size __ixp42x_proc_info, . - __ixp42x_proc_info + .type __ixp46x_proc_info, #object +__ixp46x_proc_info: + .long 0x69054200 + .long 0xffffff00 + .long 0x00000c0e + b __xscale_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP + .long cpu_ixp46x_name + .long xscale_processor_functions + .long v4wbi_tlb_fns + .long xscale_mc_user_fns + .long xscale_cache_fns + .size __ixp46x_proc_info, . - __ixp46x_proc_info + .type __pxa255_proc_info,#object __pxa255_proc_info: .long 0x69052d00 diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c index a1dc5eec0..7ffd8cb9b 100644 --- a/arch/arm/nwfpe/double_cpdo.c +++ b/arch/arm/nwfpe/double_cpdo.c @@ -75,7 +75,11 @@ static float64 float64_mnf(float64 rFm) union float64_components u; u.f64 = rFm; +#ifdef __ARMEB__ + u.i[0] ^= 0x80000000; +#else u.i[1] ^= 0x80000000; +#endif return u.f64; } @@ -85,7 +89,11 @@ static float64 float64_abs(float64 rFm) union float64_components u; u.f64 = rFm; +#ifdef __ARMEB__ + u.i[0] &= 0x7fffffff; +#else u.i[1] &= 0x7fffffff; +#endif return u.f64; } diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index 2ad457558..95fb63fa9 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -42,8 +42,13 @@ static inline void loadDouble(const unsigned int Fn, const unsigned int __user * unsigned int *p; p = (unsigned int *) &fpa11->fpreg[Fn].fDouble; fpa11->fType[Fn] = typeDouble; +#ifdef __ARMEB__ + get_user(p[0], &pMem[0]); /* sign & exponent */ + get_user(p[1], &pMem[1]); +#else get_user(p[0], &pMem[1]); get_user(p[1], &pMem[0]); /* sign & exponent */ +#endif } #ifdef CONFIG_FPE_NWFPE_XP @@ -140,8 +145,13 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) val.f = fpa11->fpreg[Fn].fDouble; } +#ifdef __ARMEB__ + put_user(val.i[0], &pMem[0]); /* msw */ + put_user(val.i[1], &pMem[1]); /* lsw */ +#else put_user(val.i[1], &pMem[0]); /* msw */ put_user(val.i[0], &pMem[1]); /* lsw */ +#endif } #ifdef CONFIG_FPE_NWFPE_XP diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c index 284874be3..447653df1 100644 --- a/arch/arm/oprofile/op_model_xscale.c +++ b/arch/arm/oprofile/op_model_xscale.c @@ -7,7 +7,7 @@ * @remark Copyright 2004 Dave Jiang * @remark Copyright 2004 Intel Corporation * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 Oprofile Authors + * @remark Copyright 2004 OProfile Authors * * @remark Read the file COPYING * @@ -30,6 +30,7 @@ #define PMN_RESET 0x002 /* Reset event counters */ #define CCNT_RESET 0x004 /* Reset clock counter */ #define PMU_RESET (CCNT_RESET | PMN_RESET) +#define PMU_CNT64 0x008 /* Make CCNT count every 64th cycle */ /* TODO do runtime detection */ #ifdef CONFIG_ARCH_IOP310 @@ -125,12 +126,15 @@ static struct pmu_type *pmu; static void write_pmnc(u32 val) { - /* upper 4bits and 7, 11 are write-as-0 */ - val &= 0xffff77f; - if (pmu->id == PMU_XSC1) + if (pmu->id == PMU_XSC1) { + /* upper 4bits and 7, 11 are write-as-0 */ + val &= 0xffff77f; __asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val)); - else + } else { + /* bits 4-23 are write-as-0, 24-31 are write ignored */ + val &= 0xf; __asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val)); + } } static u32 read_pmnc(void) @@ -139,8 +143,11 @@ static u32 read_pmnc(void) if (pmu->id == PMU_XSC1) __asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val)); - else + else { __asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val)); + /* bits 1-2 and 4-23 are read-unpredictable */ + val &= 0xff000009; + } return val; } @@ -249,7 +256,7 @@ static int xscale_setup_ctrs(void) int i; for (i = CCNT; i < MAX_COUNTERS; i++) { - if (counter_config[i].event) + if (counter_config[i].enabled) continue; counter_config[i].event = EVT_UNUSED; @@ -336,7 +343,7 @@ static void inline __xsc2_check_ctrs(void) static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs) { - unsigned long eip = instruction_pointer(regs); + unsigned long pc = profile_pc(regs); int i, is_kernel = !user_mode(regs); u32 pmnc; @@ -350,7 +357,7 @@ static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs continue; write_counter(i, -(u32)results[i].reset_counter); - oprofile_add_sample(eip, is_kernel, i, smp_processor_id()); + oprofile_add_sample(pc, is_kernel, i, smp_processor_id()); results[i].ovf--; } @@ -386,8 +393,10 @@ static int xscale_pmu_start(void) if (pmu->id == PMU_XSC1) pmnc |= pmu->int_enable; - else + else { __asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable)); + pmnc &= ~PMU_CNT64; + } pmnc |= PMU_ENABLE; write_pmnc(pmnc); diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index d2ce22372..82bdef299 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Fri Jul 2 11:58:36 2004 +# Last update: Sun Nov 7 13:20:41 2004 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -519,7 +519,7 @@ scb9328 MACH_SCB9328 SCB9328 508 omap_h3 MACH_OMAP_H3 OMAP_H3 509 omap_h4 MACH_OMAP_H4 OMAP_H4 510 n10 MACH_N10 N10 511 -montajade MACH_MONTAJADE MONTAJADE 512 +montejade MACH_MONTAJADE MONTAJADE 512 sg560 MACH_SG560 SG560 513 dp1000 MACH_DP1000 DP1000 514 omap_osk MACH_OMAP_OSK OMAP_OSK 515 @@ -559,3 +559,78 @@ lpc2294 MACH_LPC2294 LPC2294 548 switchgrass MACH_SWITCHGRASS SWITCHGRASS 549 ens_cmu MACH_ENS_CMU ENS_CMU 550 mm6_sdb MACH_MM6_SDB MM6_SDB 551 +saturn MACH_SATURN SATURN 552 +argonplusevb MACH_ARGONPLUSEVB ARGONPLUSEVB 553 +scma11evb MACH_SCMA11EVB SCMA11EVB 554 +smdk2800 MACH_SMDK2800 SMDK2800 555 +mtwilson MACH_MTWILSON MTWILSON 556 +ziti MACH_ZITI ZITI 557 +grandfather MACH_GRANDFATHER GRANDFATHER 558 +tengine MACH_TENGINE TENGINE 559 +s3c2460 MACH_S3C2460 S3C2460 560 +pdm MACH_PDM PDM 561 +h4700 MACH_H4700 H4700 562 +h6300 MACH_H6300 H6300 563 +rz1700 MACH_RZ1700 RZ1700 564 +a716 MACH_A716 A716 565 +estk2440a MACH_ESTK2440A ESTK2440A 566 +atwixp425 MACH_ATWIXP425 ATWIXP425 567 +csb336 MACH_CSB336 CSB336 568 +rirm2 MACH_RIRM2 RIRM2 569 +cx23518 MACH_CX23518 CX23518 570 +cx2351x MACH_CX2351X CX2351X 571 +computime MACH_COMPUTIME COMPUTIME 572 +izarus MACH_IZARUS IZARUS 573 +pxa_rts MACH_RTS RTS 574 +se5100 MACH_SE5100 SE5100 575 +s3c2510 MACH_S3C2510 S3C2510 576 +csb437tl MACH_CSB437TL CSB437TL 577 +slauson MACH_SLAUSON SLAUSON 578 +pearlriver MACH_PEARLRIVER PEARLRIVER 579 +tdc_p210 MACH_TDC_P210 TDC_P210 580 +sg580 MACH_SG580 SG580 581 +wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582 +ipd MACH_IPD IPD 583 +pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584 +xaeniax MACH_XAENIAX XAENIAX 585 +somn4250 MACH_SOMN4250 SOMN4250 586 +pleb2 MACH_PLEB2 PLEB2 587 +cornwallis MACH_CORNWALLIS CORNWALLIS 588 +gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589 +chaffee MACH_CHAFFEE CHAFFEE 590 +rms101 MACH_RMS101 RMS101 591 +rx3715 MACH_RX3715 RX3715 592 +swift MACH_SWIFT SWIFT 593 +roverp7 MACH_ROVERP7 ROVERP7 594 +pr818s MACH_PR818S PR818S 595 +trxpro MACH_TRXPRO TRXPRO 596 +nslu2 MACH_NSLU2 NSLU2 597 +e400 MACH_E400 E400 598 +trab MACH_TRAB TRAB 599 +cmc_pu2 MACH_CMC_PU2 CMC_PU2 600 +fulcrum MACH_FULCRUM FULCRUM 601 +netgate42x MACH_NETGATE42X NETGATE42X 602 +str710 MACH_STR710 STR710 603 +ixdpg425 MACH_IXDPG425 IXDPG425 604 +tomtomgo MACH_TOMTOMGO TOMTOMGO 605 +versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606 +edb9307 MACH_EDB9307 EDB9307 607 +sg565 MACH_SG565 SG565 608 +lpd79524 MACH_LPD79524 LPD79524 609 +lpd79525 MACH_LPD79525 LPD79525 610 +rms100 MACH_RMS100 RMS100 611 +kb9200 MACH_KB9200 KB9200 612 +sx1 MACH_SX1 SX1 613 +hms39c7092 MACH_HMS39C7092 HMS39C7092 614 +armadillo MACH_ARMADILLO ARMADILLO 615 +ipcu MACH_IPCU IPCU 616 +loox720 MACH_LOOX720 LOOX720 617 +ixdp465 MACH_IXDP465 IXDP465 618 +ixdp2351 MACH_IXDP2351 IXDP2351 619 +adsvix MACH_ADSVIX ADSVIX 620 +dm270 MACH_DM270 DM270 621 +socltplus MACH_SOCLTPLUS SOCLTPLUS 622 +ecia MACH_ECIA ECIA 623 +cm4008 MACH_CM4008 CM4008 624 +p2001 MACH_P2001 P2001 625 +twister MACH_TWISTER TWISTER 626 diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index 98e0f526e..55a02bc99 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -249,6 +249,12 @@ struct vfp_double { u64 significand; }; +/* + * VFP_REG_ZERO is a special register number for vfp_get_double + * which returns (double)0.0. This is useful for the compare with + * zero instructions. + */ +#define VFP_REG_ZERO 16 extern u64 vfp_get_double(unsigned int reg); extern void vfp_put_double(unsigned int reg, u64 val); @@ -331,3 +337,8 @@ extern u32 vfp_get_sys(unsigned int reg); extern void vfp_put_sys(unsigned int reg, u32 val); u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); + +/* + * A special flag to tell the normalisation code not to normalise. + */ +#define VFP_NAN_FLAG 0x100 diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 54649c1ee..fa3053e84 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -31,7 +31,7 @@ * =========================================================================== */ #include -#include +#include #include #include @@ -195,7 +195,7 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce dd, d, exceptions); vfp_put_double(dd, d); } - return exceptions; + return exceptions & ~VFP_NAN_FLAG; } /* @@ -240,7 +240,7 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, /* * If one was a signalling NAN, raise invalid operation. */ - return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100; + return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; } /* @@ -427,12 +427,12 @@ static u32 vfp_double_fcmpe(int dd, int unused, int dm, u32 fpscr) static u32 vfp_double_fcmpz(int dd, int unused, int dm, u32 fpscr) { - return vfp_compare(dd, 0, -1, fpscr); + return vfp_compare(dd, 0, VFP_REG_ZERO, fpscr); } static u32 vfp_double_fcmpez(int dd, int unused, int dm, u32 fpscr) { - return vfp_compare(dd, 1, -1, fpscr); + return vfp_compare(dd, 1, VFP_REG_ZERO, fpscr); } static u32 vfp_double_fcvts(int sd, int unused, int dm, u32 fpscr) diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index ad3626103..0dcfa8a78 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -199,6 +199,11 @@ vfp_get_double: mov pc, lr .endr + @ virtual register 16 for compare with zero + mov r0, #0 + mov r1, #0 + mov pc, lr + .globl vfp_put_double vfp_put_double: mov r0, r0, lsr #1 diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index 92aa84127..6849fe35c 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c @@ -31,7 +31,7 @@ * =========================================================================== */ #include -#include +#include #include #include @@ -201,7 +201,7 @@ u32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exce vfp_put_float(sd, d); } - return exceptions; + return exceptions & ~VFP_NAN_FLAG; } /* @@ -246,7 +246,7 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, /* * If one was a signalling NAN, raise invalid operation. */ - return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : 0x100; + return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; } diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig index ce96fd34b..d51376a09 100644 --- a/arch/arm26/Kconfig +++ b/arch/arm26/Kconfig @@ -62,7 +62,7 @@ config ARCH_ARC bool "Archimedes" help Say Y to support the Acorn Archimedes. - + The Acorn Archimedes was an personal computer based on an 8MHz ARM2 processor, released in 1987. It supported up to 16MB of RAM in later models and floppy, harddisc, ethernet etc. @@ -71,7 +71,7 @@ config ARCH_A5K bool "A5000" help 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 @@ -214,118 +214,7 @@ source "drivers/misc/Kconfig" source "drivers/usb/Kconfig" -menu "Kernel hacking" - -# RMK wants arm kernels compiled with frame pointers so hardwire this to y. -# If you know what you are doing and are willing to live without stack -# traces, you can get a slightly smaller kernel by setting this option to -# n, but then RMK will have to kill you ;). -config FRAME_POINTER - bool - default y - help - If you say N here, the resulting kernel will be slightly smaller and - faster. However, when a problem occurs with the kernel, the - information that is reported is severely limited. Most people - should say Y here. - -config DEBUG_USER - bool "Verbose user fault messages" - help - When a user program crashes due to an exception, the kernel can - print a brief message explaining what the problem was. This is - sometimes helpful for debugging but serves no purpose on a - production system. Most people should say N here. - -config DEBUG_INFO - bool "Include GDB debugging information in kernel binary" - help - Say Y here to include source-level debugging information in the - `vmlinux' binary image. This is handy if you want to use gdb or - addr2line to debug the kernel. It has no impact on the in-memory - footprint of the running kernel but it can increase the amount of - time and disk space needed for compilation of the kernel. If in - doubt say N. - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_WAITQ - bool "Wait queue debugging" - depends on DEBUG_KERNEL - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting (adds 70K)" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_ERRORS - bool "Verbose kernel error messages" - depends on DEBUG_KERNEL - help - This option controls verbose debugging information which can be - printed when the kernel detects an internal error. This debugging - information is useful to kernel hackers when tracking down problems, - but mostly meaningless to other people. It's safe to say Y unless - you are concerned with the code size or don't want to see these - messages. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -# These options are only for real kernel hackers who want to get their hands dirty. -config DEBUG_LL - bool "Kernel low-level debugging functions" - depends on DEBUG_KERNEL - help - Say Y here to include definitions of printascii, printchar, printhex - in the kernel. This is helpful if you are debugging code that - executes before the console is initialized. - -endmenu +source "arch/arm26/Kconfig.debug" source "security/Kconfig" diff --git a/arch/arm26/Makefile b/arch/arm26/Makefile index 3b0294a8d..631c20aef 100644 --- a/arch/arm26/Makefile +++ b/arch/arm26/Makefile @@ -8,8 +8,7 @@ # Copyright (C) 1995-2001 by Russell King LDFLAGS_vmlinux :=-p -X -LDFLAGS_BLOB :=--format binary -AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) +CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR) OBJCOPYFLAGS :=-O binary -R .note -R .comment -S GZFLAGS :=-9 @@ -28,7 +27,6 @@ CFLAGS +=-mapcs-26 -mcpu=arm3 -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uar AFLAGS +=-mapcs-26 -mcpu=arm3 -mno-fpu -msoft-float -Wa,-mno-fpu head-y := arch/arm26/machine/head.o arch/arm26/kernel/init_task.o -LDFLAGS_BLOB += --oformat elf32-littlearm ifeq ($(CONFIG_XIP_KERNEL),y) TEXTADDR := 0x03880000 diff --git a/arch/arm26/boot/Makefile b/arch/arm26/boot/Makefile index 3d992e597..004dd81f9 100644 --- a/arch/arm26/boot/Makefile +++ b/arch/arm26/boot/Makefile @@ -67,12 +67,12 @@ initrd: install: $(obj)/Image $(CONFIG_SHELL) $(obj)/install.sh \ - $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \ + $(KERNELRELEASE) \ $(obj)/Image System.map "$(INSTALL_PATH)" zinstall: $(obj)/zImage $(CONFIG_SHELL) $(obj)/install.sh \ - $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \ + $(KERNELRELEASE) \ $(obj)/zImage System.map "$(INSTALL_PATH)" subdir- := compressed diff --git a/arch/arm26/kernel/Makefile b/arch/arm26/kernel/Makefile index 7e10b557c..e2e5503f7 100644 --- a/arch/arm26/kernel/Makefile +++ b/arch/arm26/kernel/Makefile @@ -14,5 +14,5 @@ obj-y := compat.o dma.o entry.o irq.o \ obj-$(CONFIG_FIQ) += fiq.o obj-$(CONFIG_MODULES) += armksyms.o -extra-y := init_task.o vmlinux.lds.s +extra-y := init_task.o vmlinux.lds diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c index c540f22f9..bd6c30669 100644 --- a/arch/arm26/kernel/armksyms.c +++ b/arch/arm26/kernel/armksyms.c @@ -95,7 +95,7 @@ EXPORT_SYMBOL(ret_from_exception); EXPORT_SYMBOL(kd_mksound); #endif -EXPORT_SYMBOL_NOVERS(__do_softirq); +EXPORT_SYMBOL(__do_softirq); /* platform dependent support */ EXPORT_SYMBOL(dump_thread); @@ -125,71 +125,71 @@ EXPORT_SYMBOL(__csum_ipv6_magic); /* io */ #ifndef __raw_readsb -EXPORT_SYMBOL_NOVERS(__raw_readsb); +EXPORT_SYMBOL(__raw_readsb); #endif #ifndef __raw_readsw -EXPORT_SYMBOL_NOVERS(__raw_readsw); +EXPORT_SYMBOL(__raw_readsw); #endif #ifndef __raw_readsl -EXPORT_SYMBOL_NOVERS(__raw_readsl); +EXPORT_SYMBOL(__raw_readsl); #endif #ifndef __raw_writesb -EXPORT_SYMBOL_NOVERS(__raw_writesb); +EXPORT_SYMBOL(__raw_writesb); #endif #ifndef __raw_writesw -EXPORT_SYMBOL_NOVERS(__raw_writesw); +EXPORT_SYMBOL(__raw_writesw); #endif #ifndef __raw_writesl -EXPORT_SYMBOL_NOVERS(__raw_writesl); +EXPORT_SYMBOL(__raw_writesl); #endif /* string / mem functions */ -EXPORT_SYMBOL_NOVERS(strcpy); -EXPORT_SYMBOL_NOVERS(strncpy); -EXPORT_SYMBOL_NOVERS(strcat); -EXPORT_SYMBOL_NOVERS(strncat); -EXPORT_SYMBOL_NOVERS(strcmp); -EXPORT_SYMBOL_NOVERS(strncmp); -EXPORT_SYMBOL_NOVERS(strchr); -EXPORT_SYMBOL_NOVERS(strlen); -EXPORT_SYMBOL_NOVERS(strnlen); -EXPORT_SYMBOL_NOVERS(strpbrk); -EXPORT_SYMBOL_NOVERS(strrchr); -EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(__memzero); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(__memzero); /* user mem (segment) */ EXPORT_SYMBOL(uaccess_kernel); EXPORT_SYMBOL(uaccess_user); -EXPORT_SYMBOL_NOVERS(__get_user_1); -EXPORT_SYMBOL_NOVERS(__get_user_2); -EXPORT_SYMBOL_NOVERS(__get_user_4); -EXPORT_SYMBOL_NOVERS(__get_user_8); +EXPORT_SYMBOL(__get_user_1); +EXPORT_SYMBOL(__get_user_2); +EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__get_user_8); -EXPORT_SYMBOL_NOVERS(__put_user_1); -EXPORT_SYMBOL_NOVERS(__put_user_2); -EXPORT_SYMBOL_NOVERS(__put_user_4); -EXPORT_SYMBOL_NOVERS(__put_user_8); +EXPORT_SYMBOL(__put_user_1); +EXPORT_SYMBOL(__put_user_2); +EXPORT_SYMBOL(__put_user_4); +EXPORT_SYMBOL(__put_user_8); /* gcc lib functions */ -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__divsi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(__modsi3); -EXPORT_SYMBOL_NOVERS(__muldi3); -EXPORT_SYMBOL_NOVERS(__ucmpdi2); -EXPORT_SYMBOL_NOVERS(__udivdi3); -EXPORT_SYMBOL_NOVERS(__umoddi3); -EXPORT_SYMBOL_NOVERS(__udivmoddi4); -EXPORT_SYMBOL_NOVERS(__udivsi3); -EXPORT_SYMBOL_NOVERS(__umodsi3); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__muldi3); +EXPORT_SYMBOL(__ucmpdi2); +EXPORT_SYMBOL(__udivdi3); +EXPORT_SYMBOL(__umoddi3); +EXPORT_SYMBOL(__udivmoddi4); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umodsi3); /* bitops */ EXPORT_SYMBOL(_set_bit_le); @@ -214,10 +214,10 @@ EXPORT_SYMBOL(sys_exit); EXPORT_SYMBOL(sys_wait4); /* semaphores */ -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_interruptible_failed); -EXPORT_SYMBOL_NOVERS(__down_trylock_failed); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_interruptible_failed); +EXPORT_SYMBOL(__down_trylock_failed); +EXPORT_SYMBOL(__up_wakeup); EXPORT_SYMBOL(get_wchan); diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index 7869d1b22..be2ebeaa8 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -187,6 +187,7 @@ static void __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) { unsigned int status; + int ret; spin_unlock(&irq_controller_lock); if (!(action->flags & SA_INTERRUPT)) @@ -194,8 +195,9 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) status = 0; do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; action = action->next; } while (action); diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 57b9fb1e2..8597ab357 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -614,7 +614,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat /* make sure single-step breakpoint is gone. */ child->ptrace &= ~PT_SINGLESTEP; ptrace_cancel_bpt(child); - if (child->state != TASK_ZOMBIE) { + if (child->exit_state != EXIT_ZOMBIE) { child->exit_code = SIGKILL; wake_up_process(child); } @@ -729,11 +729,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c index 16cf7db5c..bf05f1537 100644 --- a/arch/arm26/kernel/signal.c +++ b/arch/arm26/kernel/signal.c @@ -465,9 +465,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, return; } - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, tsk); + force_sigsegv(sig, tsk); } /* diff --git a/arch/arm26/kernel/sys_arm.c b/arch/arm26/kernel/sys_arm.c index 0d1cdd503..431f9f85e 100644 --- a/arch/arm26/kernel/sys_arm.c +++ b/arch/arm26/kernel/sys_arm.c @@ -256,7 +256,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } asmlinkage int sys_vfork(struct pt_regs *regs) diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c index af2905a1f..a7a18c4b2 100644 --- a/arch/arm26/kernel/time.c +++ b/arch/arm26/kernel/time.c @@ -67,28 +67,6 @@ static unsigned long dummy_gettimeoffset(void) */ unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset; -/* - * Handle kernel profile stuff... - */ -static inline void do_profile(struct pt_regs *regs) -{ - if (!user_mode(regs) && - prof_buffer && - current->pid) { - unsigned long pc = instruction_pointer(regs); - extern int _stext; - - pc -= (unsigned long)&_stext; - - pc >>= prof_shift; - - if (pc >= prof_len) - pc = prof_len - 1; - - prof_buffer[pc] += 1; - } -} - static unsigned long next_rtc_update; /* @@ -188,8 +166,11 @@ EXPORT_SYMBOL(do_settimeofday); static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif do_set_rtc(); //FIME - EVERY timer IRQ? - do_profile(regs); + profile_tick(CPU_PROFILING, regs); return IRQ_HANDLED; //FIXME - is this right? } diff --git a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in index 61eedf0bc..cbbda2766 100644 --- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in +++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in @@ -34,9 +34,6 @@ SECTIONS __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff --git a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in index 2393f3805..128eb9195 100644 --- a/arch/arm26/kernel/vmlinux-arm26.lds.in +++ b/arch/arm26/kernel/vmlinux-arm26.lds.in @@ -35,9 +35,6 @@ SECTIONS __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff --git a/arch/arm26/machine/dma.c b/arch/arm26/machine/dma.c index 44090c40c..0d8ea1992 100644 --- a/arch/arm26/machine/dma.c +++ b/arch/arm26/machine/dma.c @@ -47,7 +47,7 @@ static void arc_floppy_data_enable_dma(dmach_t channel, dma_t *dma) &fdc1772_dma_read_end - &fdc1772_dma_read); fdc1772_setupdma(dma->buf.length, dma->buf.__address); /* Sets data pointer up */ enable_fiq(FIQ_FLOPPYDATA); - loacl_irq_restore(flags); + local_irq_restore(flags); } break; diff --git a/arch/arm26/machine/small_page.c b/arch/arm26/machine/small_page.c index 3cbeffa01..78e9198c2 100644 --- a/arch/arm26/machine/small_page.c +++ b/arch/arm26/machine/small_page.c @@ -24,8 +24,8 @@ #include #include #include +#include -#include #include #define PEDANTIC diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c index ad41cebe2..17f7dc3e9 100644 --- a/arch/arm26/mm/init.c +++ b/arch/arm26/mm/init.c @@ -305,8 +305,8 @@ void __init paging_init(struct meminfo *mi) (bdata->node_boot_start >> PAGE_SHIFT); if (!zone_size[0]) BUG(); - - free_area_init_node(0, pgdat, 0, zone_size, + pgdat->node_mem_map = NULL; + free_area_init_node(0, pgdat, zone_size, bdata->node_boot_start >> PAGE_SHIFT, zhole_size); mem_map = NODE_DATA(0)->node_mem_map; @@ -376,7 +376,7 @@ void __init mem_init(void) * Turn on overcommit on tiny machines */ if (PAGE_SIZE >= 16384 && num_physpages <= 128) { - sysctl_overcommit_memory = 1; + sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; printk("Turning on overcommit\n"); } } diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 481edcadc..81a4a9c18 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -20,8 +20,11 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool -source "init/Kconfig" +config CRIS + bool + default y +source "init/Kconfig" menu "General setup" @@ -51,7 +54,7 @@ config ETRAX_FAST_TIMER bool "Enable ETRAX fast timer API" help This options enables the API to a fast timer implementation using - timer1 to get sub jiffie resolution timers (primarily one-shot + timer1 to get sub jiffie resolution timers (primarily one-shot timers). This is needed if CONFIG_ETRAX_SERIAL_FAST_TIMER is enabled. @@ -69,7 +72,6 @@ config PREEMPT endmenu - menu "Hardware setup" choice @@ -96,7 +98,7 @@ endchoice config ETRAX_ARCH_V10 bool default y if ETRAX100LX || ETRAX100LX_V2 - default n if !(ETRAX100LX || ETRAX100LX_V2) + default n if !(ETRAX100LX || ETRAX100LX_V2) config ETRAX_DRAM_SIZE int "DRAM size (dec, in MB)" @@ -165,54 +167,10 @@ source "sound/Kconfig" source "drivers/usb/Kconfig" - -menu "Kernel hacking" - -#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -config PROFILE - bool "Kernel profiling support" - -config PROFILE_SHIFT - int "Profile shift count" - depends on PROFILE - default "2" - -config ETRAX_KGDB - bool "Use kernel GDB debugger" - ---help--- - 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! - - -config DEBUG_INFO - bool "Compile the kernel with debug info" - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -endmenu +source "arch/cris/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/cris/Kconfig.debug b/arch/cris/Kconfig.debug index 9864aade2..f42918bf2 100644 --- a/arch/cris/Kconfig.debug +++ b/arch/cris/Kconfig.debug @@ -1,15 +1,11 @@ menu "Kernel hacking" -source "lib/Kconfig.debug" - #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -config PROFILE +config PROFILING bool "Kernel profiling support" -config PROFILE_SHIFT - int "Profile shift count" - depends on PROFILE - default "2" +config SYSTEM_PROFILER + bool "System profiling support" config ETRAX_KGDB bool "Use kernel GDB debugger" @@ -25,4 +21,21 @@ config ETRAX_KGDB didn't before). The kernel halts when it boots, waiting for gdb if this option is turned on! + +config DEBUG_INFO + bool "Compile the kernel with debug info" + help + If you say Y here the resulting kernel image will include + debugging info resulting in a larger kernel image. + Say Y here only if you plan to use gdb to debug the kernel. + If you don't debug the kernel, you can say N. + +config FRAME_POINTER + bool "Compile the kernel with frame pointers" + help + If you say Y here the resulting kernel image will be slightly larger + and slower, but it will give very useful debugging information. + If you don't debug the kernel, you can say N, but we may not be able + to solve problems without frame pointers. + endmenu diff --git a/arch/cris/Makefile b/arch/cris/Makefile index 30585a70c..9d28fa856 100644 --- a/arch/cris/Makefile +++ b/arch/cris/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.20 2004/05/14 14:35:58 orjanf Exp $ +# $Id: Makefile,v 1.23 2004/10/19 13:07:34 starvik Exp $ # cris/Makefile # # This file is included by the global makefile so that you can add your own @@ -24,12 +24,10 @@ SARCH := endif LD = $(CROSS_COMPILE)ld -mcrislinux -LDFLAGS_BLOB := --format binary --oformat elf32-cris \ - -T arch/cris/$(SARCH)/output_arch.ld OBJCOPYFLAGS := -O binary -R .note -R .comment -S -AFLAGS_vmlinux.lds.o = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) +CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) AFLAGS += -mlinux CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe @@ -39,7 +37,7 @@ CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g CFLAGS += -fno-omit-frame-pointer endif -HEAD := arch/$(ARCH)/$(SARCH)/kernel/head.o +head-y := arch/$(ARCH)/$(SARCH)/kernel/head.o LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a) @@ -82,7 +80,7 @@ compressed: zImage archmrproper: archclean: $(Q)$(MAKE) $(clean)=arch/$(ARCH)/boot - rm -f timage vmlinux.bin cramfs.img + rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img rm -rf $(LD_SCRIPT).tmp prepare: arch/$(ARCH)/.links include/asm-$(ARCH)/.arch \ diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 482ac6659..f77b987a4 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -549,44 +549,17 @@ config ETRAX_RS485_DISABLE_RECEIVER config ETRAX_IDE bool "ATA/IDE support" + select IDE + select BLK_DEV_IDE + select BLK_DEV_IDEDISK + select BLK_DEV_IDECD + select BLK_DEV_IDEDMA + select DMA_NONPCI help Enable this to get support for ATA/IDE. You can't use parallell ports or SCSI ports at the same time. -# here we should add the CONFIG_'s necessary to enable the basic -# general ide drivers so the common case does not need to go -# into that config submenu. enable disk and CD support. others -# need to go fiddle in the submenu.. -config IDE - tristate - depends on ETRAX_IDE - default y - -config BLK_DEV_IDE - tristate - depends on ETRAX_IDE - default y - -config BLK_DEV_IDEDISK - tristate - depends on ETRAX_IDE - default y - -config BLK_DEV_IDECD - tristate - depends on ETRAX_IDE - default y - -config BLK_DEV_IDEDMA - bool - depends on ETRAX_IDE - default y - -config DMA_NONPCI - bool - depends on ETRAX_IDE - default y config ETRAX_IDE_DELAY int "Delay for drives to regain consciousness" diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile index 7036fc050..20258e36f 100644 --- a/arch/cris/arch-v10/drivers/Makefile +++ b/arch/cris/arch-v10/drivers/Makefile @@ -2,15 +2,11 @@ # Makefile for Etrax-specific drivers # -obj-$(CONFIG_ETRAX_ETHERNET) += ethernet.o -obj-$(CONFIG_ETRAX_SERIAL) += serial.o obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o obj-$(CONFIG_ETRAX_I2C) += i2c.o obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o obj-$(CONFIG_ETRAX_GPIO) += gpio.o obj-$(CONFIG_ETRAX_DS1302) += ds1302.o obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o -obj-$(CONFIG_ETRAX_IDE) += ide.o -obj-$(CONFIG_ETRAX_USB_HOST) += usb-host.o diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index 3277019e3..fb7d4855e 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c @@ -11,6 +11,9 @@ * partition split defined below. * * $Log: axisflashmap.c,v $ + * Revision 1.10 2004/08/16 12:37:22 starvik + * Merge of Linux 2.6.8 + * * Revision 1.8 2004/05/14 07:58:03 starvik * Merge of changes from 2.4 * @@ -153,6 +156,14 @@ #define FLASH_CACHED_ADDR KSEG_F #endif +#if CONFIG_ETRAX_FLASH_BUSWIDTH==1 +#define flash_data __u8 +#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 +#define flash_data __u16 +#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 +#define flash_data __u16 +#endif + /* From head.S */ extern unsigned long romfs_start, romfs_length, romfs_in_flash; @@ -161,19 +172,11 @@ struct mtd_info* axisflash_mtd = NULL; /* Map driver functions. */ -static __u8 flash_read8(struct map_info *map, unsigned long ofs) -{ - return *(__u8 *)(map->map_priv_1 + ofs); -} - -static __u16 flash_read16(struct map_info *map, unsigned long ofs) +static map_word flash_read(struct map_info *map, unsigned long ofs) { - return *(__u16 *)(map->map_priv_1 + ofs); -} - -static __u32 flash_read32(struct map_info *map, unsigned long ofs) -{ - return *(volatile unsigned int *)(map->map_priv_1 + ofs); + map_word tmp; + tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs); + return tmp; } static void flash_copy_from(struct map_info *map, void *to, @@ -182,19 +185,9 @@ static void flash_copy_from(struct map_info *map, void *to, memcpy(to, (void *)(map->map_priv_1 + from), len); } -static void flash_write8(struct map_info *map, __u8 d, unsigned long adr) -{ - *(__u8 *)(map->map_priv_1 + adr) = d; -} - -static void flash_write16(struct map_info *map, __u16 d, unsigned long adr) -{ - *(__u16 *)(map->map_priv_1 + adr) = d; -} - -static void flash_write32(struct map_info *map, __u32 d, unsigned long adr) +static void flash_write(struct map_info *map, map_word d, unsigned long adr) { - *(__u32 *)(map->map_priv_1 + adr) = d; + *(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0]; } /* @@ -215,14 +208,10 @@ static void flash_write32(struct map_info *map, __u32 d, unsigned long adr) static struct map_info map_cse0 = { .name = "cse0", .size = MEM_CSE0_SIZE, - .buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH, - .read8 = flash_read8, - .read16 = flash_read16, - .read32 = flash_read32, + .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, + .read = flash_read, .copy_from = flash_copy_from, - .write8 = flash_write8, - .write16 = flash_write16, - .write32 = flash_write32, + .write = flash_write, .map_priv_1 = FLASH_UNCACHED_ADDR }; @@ -235,14 +224,10 @@ static struct map_info map_cse0 = { static struct map_info map_cse1 = { .name = "cse1", .size = MEM_CSE1_SIZE, - .buswidth = CONFIG_ETRAX_FLASH_BUSWIDTH, - .read8 = flash_read8, - .read16 = flash_read16, - .read32 = flash_read32, + .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, + .read = flash_read, .copy_from = flash_copy_from, - .write8 = flash_write8, - .write16 = flash_write16, - .write32 = flash_write32, + .write = flash_write, .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE }; diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c index 78a200afa..fba530fcf 100644 --- a/arch/cris/arch-v10/drivers/ds1302.c +++ b/arch/cris/arch-v10/drivers/ds1302.c @@ -7,6 +7,9 @@ *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init *! *! $Log: ds1302.c,v $ +*! Revision 1.14 2004/08/24 06:48:43 starvik +*! Whitespace cleanup +*! *! Revision 1.13 2004/05/28 09:26:59 starvik *! Modified I2C initialization to work in 2.6. *! @@ -123,7 +126,7 @@ *! *! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN *! -*! $Id: ds1302.c,v 1.13 2004/05/28 09:26:59 starvik Exp $ +*! $Id: ds1302.c,v 1.14 2004/08/24 06:48:43 starvik Exp $ *! *!***************************************************************************/ diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index 167291073..50548a234 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -1,4 +1,4 @@ -/* $Id: gpio.c,v 1.11 2004/05/14 07:58:03 starvik Exp $ +/* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 starvik Exp $ * * Etrax general port I/O device * @@ -9,6 +9,9 @@ * Johan Adolfsson (read/set directions, write, port G) * * $Log: gpio.c,v $ + * Revision 1.12 2004/08/24 07:19:59 starvik + * Whitespace cleanup + * * Revision 1.11 2004/05/14 07:58:03 starvik * Merge of changes from 2.4 * diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 52a299d89..8bbe233ba 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -12,6 +12,12 @@ *! don't use PB_I2C if DS1302 uses same bits, *! use PB. *! $Log: i2c.c,v $ +*! Revision 1.9 2004/08/24 06:49:14 starvik +*! Whitespace cleanup +*! +*! Revision 1.8 2004/06/08 08:48:26 starvik +*! Removed unused code +*! *! Revision 1.7 2004/05/28 09:26:59 starvik *! Modified I2C initialization to work in 2.6. *! @@ -69,7 +75,7 @@ *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN *! *!***************************************************************************/ -/* $Id: i2c.c,v 1.7 2004/05/28 09:26:59 starvik Exp $ */ +/* $Id: i2c.c,v 1.9 2004/08/24 06:49:14 starvik Exp $ */ /****************** INCLUDE FILES SECTION ***********************************/ @@ -110,14 +116,6 @@ static const char i2c_name[] = "i2c"; #define I2C_DATA_HIGH 1 #define I2C_DATA_LOW 0 -#if 0 -/* TODO: fix this so the CONFIG_ETRAX_I2C_USES... is set in Config.in instead */ -#if defined(CONFIG_DS1302) && (CONFIG_DS1302_SDABIT==0) && \ - (CONFIG_DS1302_SCLBIT == 1) -#define CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C -#endif -#endif - #ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C /* Use PB and not PB_I2C */ #ifndef CONFIG_ETRAX_I2C_DATA_PORT @@ -441,7 +439,7 @@ i2c_sendack(void) */ i2c_data(I2C_DATA_HIGH); i2c_delay(CLOCK_LOW_TIME); - + i2c_dir_in(); } diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index 8cf5f620e..b3dfdf7b8 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -15,7 +15,7 @@ * * Author: Tobias Anderberg . * - * $Id: pcf8563.c,v 1.4 2004/05/28 09:26:59 starvik Exp $ + * $Id: pcf8563.c,v 1.8 2004/08/24 06:42:51 starvik Exp $ */ #include @@ -40,7 +40,7 @@ #define PCF8563_MAJOR 121 /* Local major number. */ #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ #define PCF8563_NAME "PCF8563" -#define DRIVER_VERSION "$Revision: 1.4 $" +#define DRIVER_VERSION "$Revision: 1.8 $" /* I2C bus slave registers. */ #define RTC_I2C_READ 0xa3 diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile index 20a56080a..52761603b 100644 --- a/arch/cris/arch-v10/kernel/Makefile +++ b/arch/cris/arch-v10/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 2003/07/04 12:57:13 tobiasa Exp $ +# $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $ # # Makefile for the linux kernel. # @@ -11,6 +11,7 @@ obj-y := entry.o traps.o shadows.o debugport.o irq.o \ obj-$(CONFIG_ETRAX_KGDB) += kgdb.o obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o +obj-$(CONFIG_MODULES) += crisksyms.o clean: diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c index d80269f6f..6cf069e5e 100644 --- a/arch/cris/arch-v10/kernel/debugport.c +++ b/arch/cris/arch-v10/kernel/debugport.c @@ -12,6 +12,21 @@ * init_etrax_debug() * * $Log: debugport.c,v $ + * Revision 1.19 2004/10/21 07:26:16 starvik + * Made it possible to specify console settings on kernel command line. + * + * Revision 1.18 2004/10/19 13:07:37 starvik + * Merge of Linux 2.6.9 + * + * Revision 1.17 2004/09/29 10:33:46 starvik + * Resolved a dealock when printing debug from kernel. + * + * Revision 1.16 2004/08/24 06:12:19 starvik + * Whitespace cleanup + * + * Revision 1.15 2004/08/16 12:37:19 starvik + * Merge of Linux 2.6.8 + * * Revision 1.14 2004/05/17 13:11:29 starvik * Disable DMA until real serial driver is up * @@ -73,111 +88,275 @@ #include #include /* Get SIMCOUT. */ -/* Which serial-port is our debug port ? */ - -#if defined(CONFIG_ETRAX_DEBUG_PORT0) || defined(CONFIG_ETRAX_DEBUG_PORT_NULL) -#define DEBUG_PORT_IDX 0 -#define DEBUG_OCMD R_DMA_CH6_CMD -#define DEBUG_FIRST R_DMA_CH6_FIRST -#define DEBUG_OCLRINT R_DMA_CH6_CLR_INTR -#define DEBUG_STATUS R_DMA_CH6_STATUS -#define DEBUG_READ R_SERIAL0_READ -#define DEBUG_WRITE R_SERIAL0_TR_DATA -#define DEBUG_TR_CTRL R_SERIAL0_TR_CTRL -#define DEBUG_REC_CTRL R_SERIAL0_REC_CTRL -#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser0_data, set) -#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma6_descr, clr) -#endif +struct dbg_port +{ + unsigned int index; + const volatile unsigned* read; + volatile char* write; + volatile unsigned* xoff; + volatile char* baud; + volatile char* tr_ctrl; + volatile char* rec_ctrl; + unsigned long irq; + unsigned int started; + unsigned long baudrate; + unsigned char parity; + unsigned int bits; +}; -#ifdef CONFIG_ETRAX_DEBUG_PORT1 -#define DEBUG_PORT_IDX 1 -#define DEBUG_OCMD R_DMA_CH8_CMD -#define DEBUG_FIRST R_DMA_CH8_FIRST -#define DEBUG_OCLRINT R_DMA_CH8_CLR_INTR -#define DEBUG_STATUS R_DMA_CH8_STATUS -#define DEBUG_READ R_SERIAL1_READ -#define DEBUG_WRITE R_SERIAL1_TR_DATA -#define DEBUG_TR_CTRL R_SERIAL1_TR_CTRL -#define DEBUG_REC_CTRL R_SERIAL1_REC_CTRL -#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser1_data, set) -#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma8_descr, clr) -#endif +struct dbg_port ports[]= +{ + { + 0, + R_SERIAL0_READ, + R_SERIAL0_TR_DATA, + R_SERIAL0_XOFF, + R_SERIAL0_BAUD, + R_SERIAL0_TR_CTRL, + R_SERIAL0_REC_CTRL, + IO_STATE(R_IRQ_MASK1_SET, ser0_data, set) + }, + { + 1, + R_SERIAL1_READ, + R_SERIAL1_TR_DATA, + R_SERIAL1_XOFF, + R_SERIAL1_BAUD, + R_SERIAL1_TR_CTRL, + R_SERIAL1_REC_CTRL, + IO_STATE(R_IRQ_MASK1_SET, ser1_data, set) + }, + { + 2, + R_SERIAL2_READ, + R_SERIAL2_TR_DATA, + R_SERIAL2_XOFF, + R_SERIAL2_BAUD, + R_SERIAL2_TR_CTRL, + R_SERIAL2_REC_CTRL, + IO_STATE(R_IRQ_MASK1_SET, ser2_data, set) + }, + { + 3, + R_SERIAL3_READ, + R_SERIAL3_TR_DATA, + R_SERIAL3_XOFF, + R_SERIAL3_BAUD, + R_SERIAL3_TR_CTRL, + R_SERIAL3_REC_CTRL, + IO_STATE(R_IRQ_MASK1_SET, ser3_data, set) + } +}; -#ifdef CONFIG_ETRAX_DEBUG_PORT2 -#define DEBUG_PORT_IDX 2 -#define DEBUG_OCMD R_DMA_CH2_CMD -#define DEBUG_FIRST R_DMA_CH2_FIRST -#define DEBUG_OCLRINT R_DMA_CH2_CLR_INTR -#define DEBUG_STATUS R_DMA_CH2_STATUS -#define DEBUG_READ R_SERIAL2_READ -#define DEBUG_WRITE R_SERIAL2_TR_DATA -#define DEBUG_TR_CTRL R_SERIAL2_TR_CTRL -#define DEBUG_REC_CTRL R_SERIAL2_REC_CTRL -#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser2_data, set) -#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma2_descr, clr) -#endif +static struct tty_driver *serial_driver; -#ifdef CONFIG_ETRAX_DEBUG_PORT3 -#define DEBUG_PORT_IDX 3 -#define DEBUG_OCMD R_DMA_CH4_CMD -#define DEBUG_FIRST R_DMA_CH4_FIRST -#define DEBUG_OCLRINT R_DMA_CH4_CLR_INTR -#define DEBUG_STATUS R_DMA_CH4_STATUS -#define DEBUG_READ R_SERIAL3_READ -#define DEBUG_WRITE R_SERIAL3_TR_DATA -#define DEBUG_TR_CTRL R_SERIAL3_TR_CTRL -#define DEBUG_REC_CTRL R_SERIAL3_REC_CTRL -#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser3_data, set) -#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma4_descr, clr) +struct dbg_port* port = +#if defined(CONFIG_ETRAX_DEBUG_PORT0) + &ports[0]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT1) + &ports[1]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT2) + &ports[2]; +#elif defined(CONFIG_ETRAX_DEBUG_PORT3) + &ports[3]; +#else + NULL; #endif +/* Used by serial.c to register a debug_write_function so that the normal + * serial driver is used for kernel debug output + */ +typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); -#define MIN_SIZE 32 /* Size that triggers the FIFO to flush characters to interface */ +debugport_write_function debug_write_function = NULL; -static struct tty_driver *serial_driver; +static void +start_port(void) +{ + unsigned long rec_ctrl = 0; + unsigned long tr_ctrl = 0; -typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); + if (!port) + return; -debugport_write_function debug_write_function = NULL; + if (port->started) + return; + port->started = 1; + + if (port->index == 0) + { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); + } + else if (port->index == 1) + { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); + } + else if (port->index == 2) + { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser2, select); + } + else + { + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); + genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1); + genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser3, select); + } + + *R_GEN_CONFIG = genconfig_shadow; + + *port->xoff = + IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) | + IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) | + IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0); + + switch (port->baudrate) + { + case 0: + case 115200: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); + break; + case 1200: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz); + break; + case 2400: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz); + break; + case 4800: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz); + break; + case 9600: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz); + break; + case 19200: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz); + break; + case 38400: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz); + break; + case 57600: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz); + break; + default: + *port->baud = + IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | + IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); + break; + } + + if (port->parity == 'E') { + rec_ctrl = + IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | + IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); + tr_ctrl = + IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | + IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); + } else if (port->parity == 'O') { + rec_ctrl = + IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) | + IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); + tr_ctrl = + IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd) | + IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); + } else { + rec_ctrl = + IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | + IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, disable); + tr_ctrl = + IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | + IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable); + } + + if (port->bits == 7) + { + rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); + tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); + } + else + { + rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit); + tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit); + } + + *port->rec_ctrl = + IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) | + IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) | + IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) | + IO_STATE(R_SERIAL0_REC_CTRL, sampling, middle) | + IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) | + rec_ctrl; + + *port->tr_ctrl = + IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) | + IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) | + IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) | + IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, one_bit) | + IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, normal) | + tr_ctrl; +} static void console_write_direct(struct console *co, const char *buf, unsigned int len) { int i; + unsigned long flags; + local_irq_save(flags); /* Send data */ for (i = 0; i < len; i++) { /* Wait until transmitter is ready and send.*/ - while(!(*DEBUG_READ & IO_MASK(R_SERIAL0_READ, tr_ready))); - *DEBUG_WRITE = buf[i]; + while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) + ; + *port->write = buf[i]; } + local_irq_restore(flags); } -static void +static void console_write(struct console *co, const char *buf, unsigned int len) { - unsigned long flags; -#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL - /* no debug printout at all */ - return; -#endif + if (!port) + return; #ifdef CONFIG_SVINTO_SIM /* no use to simulate the serial debug output */ - SIMCOUT(buf,len); + SIMCOUT(buf, len); return; #endif + start_port(); + #ifdef CONFIG_ETRAX_KGDB /* kgdb needs to output debug info using the gdb protocol */ putDebugString(buf, len); return; #endif - local_irq_save(flags); if (debug_write_function) - if (debug_write_function(co->index, buf, len)) - return; - console_write_direct(co, buf, len); - local_irq_restore(flags); + debug_write_function(co->index, buf, len); + else + console_write_direct(co, buf, len); } /* legacy function */ @@ -194,10 +373,10 @@ int getDebugChar(void) { unsigned long readval; - + do { - readval = *DEBUG_READ; - } while(!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); + readval = *port->read; + } while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); return (readval & IO_MASK(R_SERIAL0_READ, data_in)); } @@ -207,9 +386,9 @@ getDebugChar(void) void putDebugChar(int val) { - while(!(*DEBUG_READ & IO_MASK(R_SERIAL0_READ, tr_ready))) ; -; - *DEBUG_WRITE = val; + while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) + ; + *port->write = val; } /* Enable irq for receiving chars on the debug port, used by kgdb */ @@ -217,68 +396,127 @@ putDebugChar(int val) void enableDebugIRQ(void) { - *R_IRQ_MASK1_SET = DEBUG_IRQ; + *R_IRQ_MASK1_SET = port->irq; /* use R_VECT_MASK directly, since we really bypass Linux normal * IRQ handling in kgdb anyway, we don't need to use enable_irq */ *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - *DEBUG_REC_CTRL = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); + *port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); } static struct tty_driver* -console_device(struct console *c, int *index) +etrax_console_device(struct console* co, int *index) { - *index = c->index; return serial_driver; } -static int __init +static int __init console_setup(struct console *co, char *options) { - return 0; + char* s; + + if (options) { + port = &ports[co->index]; + port->baudrate = 115200; + port->parity = 'N'; + port->bits = 8; + port->baudrate = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) port->parity = *s++; + if (*s) port->bits = *s++ - '0'; + port->started = 0; + start_port(); + } + return 0; } static struct console sercons = { - .name = "ttyS", - .write = console_write, - .read = NULL, - .device = console_device, - .unblank = NULL, - .setup = console_setup, - .flags = CON_PRINTBUFFER, - .index = DEBUG_PORT_IDX, - .cflag = 0, - .next = NULL + name : "ttyS", + write: console_write, + read : NULL, + device : etrax_console_device, + unblank : NULL, + setup : console_setup, + flags : CON_PRINTBUFFER, + index : -1, + cflag : 0, + next : NULL +}; +static struct console sercons0 = { + name : "ttyS", + write: console_write, + read : NULL, + device : etrax_console_device, + unblank : NULL, + setup : console_setup, + flags : CON_PRINTBUFFER, + index : 0, + cflag : 0, + next : NULL }; +static struct console sercons1 = { + name : "ttyS", + write: console_write, + read : NULL, + device : etrax_console_device, + unblank : NULL, + setup : console_setup, + flags : CON_PRINTBUFFER, + index : 1, + cflag : 0, + next : NULL +}; +static struct console sercons2 = { + name : "ttyS", + write: console_write, + read : NULL, + device : etrax_console_device, + unblank : NULL, + setup : console_setup, + flags : CON_PRINTBUFFER, + index : 2, + cflag : 0, + next : NULL +}; +static struct console sercons3 = { + name : "ttyS", + write: console_write, + read : NULL, + device : etrax_console_device, + unblank : NULL, + setup : console_setup, + flags : CON_PRINTBUFFER, + index : 3, + cflag : 0, + next : NULL +}; /* * Register console (for printk's etc) */ -void __init +int __init init_etrax_debug(void) { -#if CONFIG_ETRAX_DEBUG_PORT_NULL - return; -#endif - -#if DEBUG_PORT_IDX == 0 - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); -#elif DEBUG_PORT_IDX == 1 - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); -#elif DEBUG_PORT_IDX == 2 - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); -#elif DEBUG_PORT_IDX == 3 - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); -#endif - *R_GEN_CONFIG = genconfig_shadow; - - register_console(&sercons); + static int first = 1; + + if (!first) { + if (!port) { + register_console(&sercons0); + register_console(&sercons1); + register_console(&sercons2); + register_console(&sercons3); + unregister_console(&sercons); + } + return 0; + } + first = 0; + if (port) + register_console(&sercons); + return 0; } int __init @@ -289,3 +527,5 @@ init_console(void) return -ENOMEM; return 0; } + +__initcall(init_etrax_debug); diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index ddd947d1c..1bc44f481 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.18 2004/05/11 12:28:25 starvik Exp $ +/* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $ * * linux/arch/cris/entry.S * @@ -7,6 +7,23 @@ * Authors: Bjorn Wesen (bjornw@axis.com) * * $Log: entry.S,v $ + * Revision 1.23 2004/10/19 13:07:37 starvik + * Merge of Linux 2.6.9 + * + * Revision 1.22 2004/06/21 10:29:55 starvik + * Merge of Linux 2.6.7 + * + * Revision 1.21 2004/06/09 05:30:27 starvik + * Clean up multiple interrupt handling. + * Prevent interrupts from interrupting each other. + * Handle all active interrupts. + * + * Revision 1.20 2004/06/08 08:55:32 starvik + * Removed unused code + * + * Revision 1.19 2004/06/04 11:56:15 starvik + * Implemented page table lookup for refills in assembler for improved performance. + * * Revision 1.18 2004/05/11 12:28:25 starvik * Merge of Linux 2.6.6 * @@ -238,7 +255,9 @@ #include #include #include - +#include +#include + ;; functions exported from this file .globl system_call @@ -539,11 +558,63 @@ resume: ;; It needs to stack the CPU status and overall is different ;; from the other interrupt handlers. -mmu_bus_fault: - sbfs [$sp=$sp-16] ; push the internal CPU status +mmu_bus_fault: + ;; For refills we try to do a quick page table lookup. If it is + ;; a real fault we let the mm subsystem handle it. + ;; the first longword in the sbfs frame was the interrupted PC ;; which fits nicely with the "IRP" slot in pt_regs normally used to - ;; contain the return address. used by Oops to print kernel errors.. + ;; contain the return address. used by Oops to print kernel errors. + sbfs [$sp=$sp-16] ; push the internal CPU status + push $dccr + di + subq 2*4, $sp + movem $r1, [$sp] + move.d [R_MMU_CAUSE], $r1 + ;; ETRAX 100LX TR89 bugfix: if the second half of an unaligned + ;; write causes a MMU-fault, it will not be restarted correctly. + ;; This could happen if a write crosses a page-boundary and the + ;; second page is not yet COW'ed or even loaded. The workaround + ;; is to clear the unaligned bit in the CPU status record, so + ;; that the CPU will rerun both the first and second halves of + ;; the instruction. This will not have any sideeffects unless + ;; the first half goes to any device or memory that can't be + ;; written twice, and which is mapped through the MMU. + ;; + ;; We only need to do this for writes. + btstq 8, $r1 ; Write access? + bpl 1f + nop + move.d [$sp+16], $r0 ; Clear unaligned bit in csrinstr + and.d ~(1<<5), $r0 + move.d $r0, [$sp+16] +1: btstq 12, $r1 ; Refill? + bpl 2f + lsrq PMD_SHIFT, $r1 ; Get PMD index into PGD (bit 24-31) + move.d [current_pgd], $r0 ; PGD for the current process + move.d [$r0+$r1.d], $r0 ; Get PMD + beq 2f + nop + and.w PAGE_MASK, $r0 ; Remove PMD flags + move.d [R_MMU_CAUSE], $r1 + lsrq PAGE_SHIFT, $r1 + and.d 0x7ff, $r1 ; Get PTE index into PMD (bit 13-24) + move.d [$r0+$r1.d], $r1 ; Get PTE + beq 2f + nop + ;; Store in TLB + move.d $r1, [R_TLB_LO] + ;; Return + movem [$sp+], $r1 + pop $dccr + rbf [$sp+] ; return by popping the CPU status + +2: ; PMD or PTE missing, let the mm subsystem fix it up. + movem [$sp+], $r1 + pop $dccr + + ; Ok, not that easy, pass it on to the mm subsystem + ; The MMU status record is now on the stack push $srp ; make a stackframe similar to pt_regs push $dccr push $mof @@ -556,7 +627,7 @@ mmu_bus_fault: move.d $sp, $r10 ; pt_regs argument to handle_mmu_bus_fault - jsr handle_mmu_bus_fault ; in arch/cris/mm/fault.c + jsr handle_mmu_bus_fault ; in arch/cris/arch-v10/mm/fault.c ;; now we need to return through the normal path, we cannot just ;; do the RBFexit since we might have killed off the running @@ -569,48 +640,20 @@ mmu_bus_fault: nop ;; special handlers for breakpoint and NMI -#if 0 -hwbreakpoint: - push $dccr - di - push $r10 - push $r11 - push $r12 - push $r13 - clearf b - move $brp,$r11 - move.d [hw_bp_msg],$r10 - jsr printk - setf b - pop $r13 - pop $r12 - pop $r11 - pop $r10 - pop $dccr - retb - nop -#else hwbreakpoint: push $dccr di -#if 1 push $r10 push $r11 move.d [hw_bp_trig_ptr],$r10 - move.d [$r10],$r11 - cmp.d 42,$r11 - beq 1f - nop move $brp,$r11 move.d $r11,[$r10+] move.d $r10,[hw_bp_trig_ptr] 1: pop $r11 pop $r10 -#endif pop $dccr retb nop -#endif IRQ1_interrupt: @@ -719,29 +762,23 @@ multiple_interrupt: push $r10 ; push orig_r10 clear.d [$sp=$sp-4] ; frametype == 0, normal frame - move.d irq_shortcuts + 8, $r1 moveq 2, $r2 ; first bit we care about is the timer0 irq move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq + move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs 1: btst $r2, $r0 ; check for the irq given by bit r2 - bmi _do_shortcut ; actually do the shortcut - nop + bpl 2f + move.d $r2, $r10 ; First argument to do_IRQ + move.d $sp, $r11 ; second argument to do_IRQ + jsr do_IRQ +2: addq 1, $r2 ; next vector bit - addq 4, $r1 ; next vector cmp.b 32, $r2 bne 1b ; process all irq's up to and including number 31 - nop + moveq 0, $r9 ; make ret_from_intr realise we came from an ir - ;; strange, we didn't get any set vector bits.. oh well, just return - - ba _Rexit - nop - -_do_shortcut: - test.d [$r1] - beq _Rexit - nop - jump [$r1] ; jump to the irq handlers shortcut + move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs + jump ret_from_intr do_sigtrap: ;; @@ -1079,7 +1116,9 @@ sys_call_table: .long sys_mq_timedreceive /* 280 */ .long sys_mq_notify .long sys_mq_getsetattr - + .long sys_ni_syscall /* reserved for kexec */ + .long sys_waitid + /* * NOTE!! This doesn't have to be exact - we just have * to make sure we have _enough_ of the "sys_ni_syscall" diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c index c5e6348ab..b2f16d6fc 100644 --- a/arch/cris/arch-v10/kernel/irq.c +++ b/arch/cris/arch-v10/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.1 2002/12/11 15:42:02 starvik Exp $ +/* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $ * * linux/arch/cris/kernel/irq.c * @@ -23,12 +23,8 @@ irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq pro */ void -set_int_vector(int n, irqvectptr addr, irqvectptr saddr) +set_int_vector(int n, irqvectptr addr) { - /* remember the shortcut entry point, after the prologue */ - - irq_shortcuts[n] = saddr; - etrax_irv->v[n + 0x20] = (irqvectptr)addr; } @@ -106,17 +102,6 @@ static void (*interrupt[NR_IRQS])(void) = { IRQ31_interrupt }; -static void (*sinterrupt[NR_IRQS])(void) = { - NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt, - sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt, - sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt, - sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL, - sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt, - sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt, - sIRQ24_interrupt, sIRQ25_interrupt, NULL, NULL, NULL, NULL, NULL, - sIRQ31_interrupt -}; - static void (*bad_interrupt[NR_IRQS])(void) = { NULL, NULL, NULL, bad_IRQ3_interrupt, @@ -137,12 +122,12 @@ static void (*bad_interrupt[NR_IRQS])(void) = { void arch_setup_irq(int irq) { - set_int_vector(irq, interrupt[irq], sinterrupt[irq]); + set_int_vector(irq, interrupt[irq]); } void arch_free_irq(int irq) { - set_int_vector(irq, bad_interrupt[irq], 0); + set_int_vector(irq, bad_interrupt[irq]); } void weird_irq(void); @@ -187,20 +172,20 @@ init_IRQ(void) /* set all etrax irq's to the bad handlers */ for (i = 2; i < NR_IRQS; i++) - set_int_vector(i, bad_interrupt[i], 0); + set_int_vector(i, bad_interrupt[i]); /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ - set_int_vector(15, multiple_interrupt, 0); + set_int_vector(15, multiple_interrupt); /* 0 and 1 which are special breakpoint/NMI traps */ - set_int_vector(0, hwbreakpoint, 0); - set_int_vector(1, IRQ1_interrupt, 0); + set_int_vector(0, hwbreakpoint); + set_int_vector(1, IRQ1_interrupt); /* and irq 14 which is the mmu bus fault handler */ - set_int_vector(14, mmu_bus_fault, 0); + set_int_vector(14, mmu_bus_fault); /* setup the system-call trap, which is reached by BREAK 13 */ diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c index 4e5d50d28..7d368c877 100644 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ b/arch/cris/arch-v10/kernel/kgdb.c @@ -18,6 +18,9 @@ *! Jul 21 1999 Bjorn Wesen eLinux port *! *! $Log: kgdb.c,v $ +*! Revision 1.5 2004/10/07 13:59:08 starvik +*! Corrected call to set_int_vector +*! *! Revision 1.4 2003/04/09 05:20:44 starvik *! Merge of Linux 2.5.67 *! @@ -68,7 +71,7 @@ *! *!--------------------------------------------------------------------------- *! -*! $Id: kgdb.c,v 1.4 2003/04/09 05:20:44 starvik Exp $ +*! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $ *! *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN *! @@ -1557,7 +1560,7 @@ kgdb_init(void) /* could initialize debug port as well but it's done in head.S already... */ /* breakpoint handler is now set in irq.c */ - set_int_vector(8, kgdb_handle_serial, 0); + set_int_vector(8, kgdb_handle_serial); enableDebugIRQ(); } diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 8aba42472..87ff37790 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.6 2004/05/11 12:28:25 starvik Exp $ +/* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $ * * linux/arch/cris/kernel/process.c * @@ -34,6 +34,15 @@ void default_idle(void) #endif } +/* + * Free current thread data structures etc.. + */ + +void exit_thread(void) +{ + /* Nothing needs to be done. */ +} + /* if the watchdog is enabled, we can simply disable interrupts and go * into an eternal loop, and the watchdog will reset the CPU after 0.1s * if on the other hand the watchdog wasn't enabled, we just enable it and wait @@ -123,7 +132,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, *childregs = *regs; /* struct copy of pt_regs */ p->set_child_tid = p->clear_child_tid = NULL; - + childregs->r10 = 0; /* child returns 0 after a fork/clone */ /* put the switch stack right below the pt_regs */ @@ -180,7 +189,7 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, { if (!newusp) newusp = rdusp(); - return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid); + return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); } /* vfork is a system call in i386 because of register-pressure - maybe @@ -214,13 +223,6 @@ asmlinkage int sys_execve(const char *fname, char **argv, char **envp, return error; } -/* - * These bracket the sleeping functions.. - */ - -#define first_sched ((unsigned long)__sched_text_start) -#define last_sched ((unsigned long)__sched_text_end) - unsigned long get_wchan(struct task_struct *p) { #if 0 @@ -241,8 +243,8 @@ unsigned long get_wchan(struct task_struct *p) if (ebp < stack_page || ebp > 8184+stack_page) return 0; eip = *(unsigned long *) (ebp+4); - if (eip < first_sched || eip >= last_sched) - return eip; + if (!in_sched_functions(eip)) + return eip; ebp = *(unsigned long *) ebp; } while (count++ < 16); #endif diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 39dcc3c72..da15db8ae 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -23,8 +23,37 @@ */ #define DCCR_MASK 0x0000001f /* XNZVC */ -extern inline long get_reg(struct task_struct *, unsigned int); -extern inline long put_reg(struct task_struct *, unsigned int, unsigned long); +/* + * Get contents of register REGNO in task TASK. + */ +inline long get_reg(struct task_struct *task, unsigned int regno) +{ + /* USP is a special case, it's not in the pt_regs struct but + * in the tasks thread struct + */ + + if (regno == PT_USP) + return task->thread.usp; + else if (regno < PT_MAX) + return ((unsigned long *)user_regs(task->thread_info))[regno]; + else + return 0; +} + +/* + * Write contents of register REGNO in task TASK. + */ +inline int put_reg(struct task_struct *task, unsigned int regno, + unsigned long data) +{ + if (regno == PT_USP) + task->thread.usp = data; + else if (regno < PT_MAX) + ((unsigned long *)user_regs(task->thread_info))[regno] = data; + else + return -1; + return 0; +} /* * Called by kernel/ptrace.c when detaching. @@ -50,6 +79,7 @@ sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret; + unsigned long __user *datap = (unsigned long __user *)data; lock_kernel(); ret = -EPERM; @@ -85,17 +115,8 @@ sys_ptrace(long request, long pid, long addr, long data) goto out_tsk; } - ret = -ESRCH; - - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } - - if (child->parent != current) + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) goto out_tsk; switch (request) { @@ -111,7 +132,7 @@ sys_ptrace(long request, long pid, long addr, long data) if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp,datap); break; } @@ -124,7 +145,7 @@ sys_ptrace(long request, long pid, long addr, long data) break; tmp = get_reg(child, addr >> 2); - ret = put_user(tmp, (unsigned long *)data); + ret = put_user(tmp, datap); break; } @@ -222,7 +243,7 @@ sys_ptrace(long request, long pid, long addr, long data) for (i = 0; i <= PT_MAX; i++) { tmp = get_reg(child, i); - if (put_user(tmp, (unsigned long *) data)) { + if (put_user(tmp, datap)) { ret = -EFAULT; goto out_tsk; } @@ -240,7 +261,7 @@ sys_ptrace(long request, long pid, long addr, long data) unsigned long tmp; for (i = 0; i <= PT_MAX; i++) { - if (get_user(tmp, (unsigned long *) data)) { + if (get_user(tmp, datap)) { ret = -EFAULT; goto out_tsk; } diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 8db985e29..97b7af26a 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -264,7 +264,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, { struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp(); sigset_t set; - stack_t st; /* * Since we stacked the signal on a dword boundary, @@ -288,11 +287,8 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT) goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack(&st, NULL, rdusp()); return regs->r10; @@ -388,9 +384,9 @@ static void setup_frame(int sig, struct k_sigaction *ka, /* trampoline - the desired return ip is the retcode itself */ return_ip = (unsigned long)&frame->retcode; /* This is movu.w __NR_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short *)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2)); - err |= __put_user(0xe93d, (short *)(frame->retcode+4)); + err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); + err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2)); + err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); } if (err) @@ -409,9 +405,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -450,9 +444,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* trampoline - the desired return ip is the retcode itself */ return_ip = (unsigned long)&frame->retcode; /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short *)(frame->retcode+0)); - err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode+2)); - err |= __put_user(0xe93d, (short *)(frame->retcode+4)); + err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); + err |= __put_user(__NR_rt_sigreturn, (short __user*)(frame->retcode+2)); + err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); } if (err) @@ -475,9 +469,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -486,10 +478,9 @@ give_sigsegv: extern inline void handle_signal(int canrestart, unsigned long sig, - siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) + siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Are we from a system call? */ if (canrestart) { /* If so, check system call restarting.. */ @@ -551,6 +542,7 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -564,10 +556,10 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, signr, &info, oldset, regs); + handle_signal(canrestart, signr, &info, &ka, oldset, regs); return 1; } diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index 298e86a01..6b7b4e080 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.3 2004/06/01 05:38:42 starvik Exp $ +/* $Id: time.c,v 1.5 2004/09/29 06:12:46 starvik Exp $ * * linux/arch/cris/arch-v10/kernel/time.c * @@ -200,6 +200,8 @@ static long last_rtc_update = 0; //static unsigned short myjiff; /* used by our debug routine print_timestamp */ +extern void cris_do_profile(struct pt_regs *regs); + static inline irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -228,6 +230,8 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) do_timer(regs); + cris_do_profile(regs); /* Save profiling information */ + /* * If we have an externally synchronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be diff --git a/arch/cris/arch-v10/mm/fault.c b/arch/cris/arch-v10/mm/fault.c index 0c6bac018..6805cdb25 100644 --- a/arch/cris/arch-v10/mm/fault.c +++ b/arch/cris/arch-v10/mm/fault.c @@ -40,23 +40,25 @@ void handle_mmu_bus_fault(struct pt_regs *regs) { int cause; -#ifdef DEBUG int select; +#ifdef DEBUG int index; int page_id; int acc, inv; #endif - int miss, we, writeac; + pgd_t* pgd = (pgd_t*)current_pgd; pmd_t *pmd; pte_t pte; + int miss, we, writeac; unsigned long address; + unsigned long flags; cause = *R_MMU_CAUSE; address = cause & PAGE_MASK; /* get faulting address */ + select = *R_TLB_SELECT; #ifdef DEBUG - select = *R_TLB_SELECT; page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause); acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause); inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause); @@ -66,85 +68,31 @@ handle_mmu_bus_fault(struct pt_regs *regs) we = IO_EXTRACT(R_MMU_CAUSE, we_excp, cause); writeac = IO_EXTRACT(R_MMU_CAUSE, wr_rd, cause); - /* ETRAX 100LX TR89 bugfix: if the second half of an unaligned - * write causes a MMU-fault, it will not be restarted correctly. - * This could happen if a write crosses a page-boundary and the - * second page is not yet COW'ed or even loaded. The workaround - * is to clear the unaligned bit in the CPU status record, so - * that the CPU will rerun both the first and second halves of - * the instruction. This will not have any sideeffects unless - * the first half goes to any device or memory that can't be - * written twice, and which is mapped through the MMU. - * - * We only need to do this for writes. - */ - - if(writeac) - regs->csrinstr &= ~(1 << 5); - D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n", regs->irp, address, miss, inv, we, acc, index, page_id)); - /* for a miss, we need to reload the TLB entry */ - - if (miss) { - /* see if the pte exists at all - * refer through current_pgd, dont use mm->pgd - */ - - pmd = (pmd_t *)(current_pgd + pgd_index(address)); - if (pmd_none(*pmd)) { - do_page_fault(address, regs, 0, writeac); - return; - } - if (pmd_bad(*pmd)) { - printk("bad pgdir entry 0x%lx at 0x%p\n", *(unsigned long*)pmd, pmd); - pmd_clear(pmd); - return; - } - pte = *pte_offset_kernel(pmd, address); - if (!pte_present(pte)) { - do_page_fault(address, regs, 0, writeac); - return; - } - -#ifdef DEBUG - printk(" found pte %lx pg %p ", pte_val(pte), pte_page(pte)); - if (pte_val(pte) & _PAGE_SILENT_WRITE) - printk("Silent-W "); - if (pte_val(pte) & _PAGE_KERNEL) - printk("Kernel "); - if (pte_val(pte) & _PAGE_SILENT_READ) - printk("Silent-R "); - if (pte_val(pte) & _PAGE_GLOBAL) - printk("Global "); - if (pte_val(pte) & _PAGE_PRESENT) - printk("Present "); - if (pte_val(pte) & _PAGE_ACCESSED) - printk("Accessed "); - if (pte_val(pte) & _PAGE_MODIFIED) - printk("Modified "); - if (pte_val(pte) & _PAGE_READ) - printk("Readable "); - if (pte_val(pte) & _PAGE_WRITE) - printk("Writeable "); - printk("\n"); -#endif - - /* load up the chosen TLB entry - * this assumes the pte format is the same as the TLB_LO layout. - * - * the write to R_TLB_LO also writes the vpn and page_id fields from - * R_MMU_CAUSE, which we in this case obviously want to keep - */ - - *R_TLB_LO = pte_val(pte); - - return; - } - /* leave it to the MM system fault handler */ - do_page_fault(address, regs, 1, we); + if (miss) + do_page_fault(address, regs, 0, writeac); + else + do_page_fault(address, regs, 1, we); + + /* Reload TLB with new entry to avoid an extra miss exception. + * do_page_fault may have flushed the TLB so we have to restore + * the MMU registers. + */ + local_save_flags(flags); + local_irq_disable(); + pmd = (pmd_t *)(pgd + pgd_index(address)); + if (pmd_none(*pmd)) + return; + pte = *pte_offset_kernel(pmd, address); + if (!pte_present(pte)) + return; + *R_TLB_SELECT = select; + *R_TLB_HI = cause; + *R_TLB_LO = pte_val(pte); + local_irq_restore(flags); } /* Called from arch/cris/mm/fault.c to find fixup code. */ diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c index df03dea5b..720b9c156 100644 --- a/arch/cris/arch-v10/mm/init.c +++ b/arch/cris/arch-v10/mm/init.c @@ -183,7 +183,7 @@ paging_init(void) * mem_map page array. */ - free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); + free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); mem_map = contig_page_data.node_mem_map; } diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c index 62fd0143c..9d06125ff 100644 --- a/arch/cris/arch-v10/mm/tlb.c +++ b/arch/cris/arch-v10/mm/tlb.c @@ -65,7 +65,7 @@ void flush_tlb_mm(struct mm_struct *mm) { int i; - int page_id = mm->context; + int page_id = mm->context.page_id; unsigned long flags; D(printk("tlb: flush mm context %d (%p)\n", page_id, mm)); @@ -103,7 +103,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { struct mm_struct *mm = vma->vm_mm; - int page_id = mm->context; + int page_id = mm->context.page_id; int i; unsigned long flags; @@ -147,7 +147,7 @@ flush_tlb_range(struct vm_area_struct *vma, unsigned long end) { struct mm_struct *mm = vma->vm_mm; - int page_id = mm->context; + int page_id = mm->context.page_id; int i; unsigned long flags; @@ -208,6 +208,18 @@ dump_tlb_all(void) } #endif +/* + * Initialize the context related info for a new mm_struct + * instance. + */ + +int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + mm->context.page_id = NO_CONTEXT; + return 0; +} + /* called in schedule() just before actually doing the switch_to */ void @@ -231,6 +243,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, D(printk("switching mmu_context to %d (%p)\n", next->context, next)); - *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context); + *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context.page_id); } diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S index 6b73a2c0d..71ba736be 100644 --- a/arch/cris/arch-v10/vmlinux.lds.S +++ b/arch/cris/arch-v10/vmlinux.lds.S @@ -26,6 +26,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.text.__*) } @@ -64,9 +65,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; .initcall.init : { __initcall_start = .; *(.initcall1.init); diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile index 7c071a765..1546a0e74 100644 --- a/arch/cris/kernel/Makefile +++ b/arch/cris/kernel/Makefile @@ -3,7 +3,7 @@ # Makefile for the linux kernel. # -extra-y := vmlinux.lds.s +extra-y := vmlinux.lds obj-y := process.o traps.o irq.o ptrace.o setup.o \ time.o sys_cris.o semaphore.o diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 6ded633f8..7141bbecd 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -91,8 +90,8 @@ EXPORT_SYMBOL(prepare_rx_descriptor); #undef memset extern void * memset(void *, int, __kernel_size_t); extern void * memcpy(void *, const void *, __kernel_size_t); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); #ifdef CONFIG_ETRAX_FAST_TIMER /* Fast timer functions */ diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 94d702790..2a9ed1806 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -36,9 +36,9 @@ #include #include #include +#include #include -#include /* Defined in arch specific irq.c */ extern void arch_setup_irq(int irq); @@ -125,7 +125,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { struct irqaction *action; int do_random, cpu; - int retval = 0; + int ret, retval = 0; cpu = smp_processor_id(); irq_enter(); @@ -137,8 +137,10 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) local_irq_enable(); do_random = 0; do { - do_random |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + do_random |= action->flags; + retval |= ret; action = action->next; } while (action); diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 8497cfb80..62bb7ba4c 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig @@ -176,86 +176,15 @@ source "drivers/serial/Kconfig" source "drivers/i2c/Kconfig" source "drivers/usb/Kconfig" - + endmenu source "fs/Kconfig" -menu "Kernel hacking" - -config FULLDEBUG - bool "Full Symbolic/Source Debugging support" - help - Enable debugging symbols on kernel build. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - Enables console device to interprent special characters as - commands to dump state information. - -config HIGHPROFILE - bool "Use fast second timer for profiling" - help - Use a fast secondary clock to produce profiling information. - -config NO_KERNEL_MSG - bool "Suppress Kernel BUG Messages" - help - Do not output any debug BUG messages within the kernel. - -config GDB_MAGICPRINT - bool "Message Output for GDB MagicPrint service" - depends on (H8300H_SIM || H8S_SIM) - help - kernel messages output useing MagicPrint service from GDB - -config SYSCALL_PRINT - bool "SystemCall trace print" - help - outout history of systemcall - -config GDB_DEBUG - bool "Use gdb stub" - depends on (!H8300H_SIM && !H8S_SIM) - help - gdb stub exception support - -config CONFIG_SH_STANDARD_BIOS - bool "Use gdb protocol serial console" - depends on (!H8300H_SIM && !H8S_SIM) - help - serial console output using GDB protocol. - Require eCos/RedBoot - -config DEFAULT_CMDLINE - bool "Use buildin commandline" - default n - help - buildin kernel commandline enabled. - -config KERNEL_COMMAND - string "Buildin commmand string" - depends on DEFAULT_CMDLINE - help - buildin kernel commandline strings. - -config BLKDEV_RESERVE - bool "BLKDEV Reserved Memory" - default n - help - Reserved BLKDEV area. - -config CONFIG_BLKDEV_RESERVE_ADDRESS - hex 'start address' - depends on BLKDEV_RESERVE - help - BLKDEV start address. -endmenu +source "arch/h8300/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile index 1f4ef89b5..71b6131e9 100644 --- a/arch/h8300/kernel/Makefile +++ b/arch/h8300/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -extra-y := vmlinux.lds.s +extra-y := vmlinux.lds obj-y := process.o traps.o ptrace.o ints.o \ sys_h8300.o time.o semaphore.o signal.o \ diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c index 5e50c0893..b78b82ad2 100644 --- a/arch/h8300/kernel/asm-offsets.c +++ b/arch/h8300/kernel/asm-offsets.c @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include #define DEFINE(sym, val) \ diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c index ca8578fed..5a6302331 100644 --- a/arch/h8300/kernel/h8300_ksyms.c +++ b/arch/h8300/kernel/h8300_ksyms.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -50,13 +49,13 @@ EXPORT_SYMBOL(csum_partial_copy); explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ -//EXPORT_SYMBOL_NOVERS(__ashrdi3); -//EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memmove); +//EXPORT_SYMBOL(__ashrdi3); +//EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(get_wchan); @@ -85,29 +84,29 @@ extern void __umoddi3(void); extern void __umodsi3(void); /* gcc lib functions */ -EXPORT_SYMBOL_NOVERS(__gcc_bcmp); -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__cmpdi2); -EXPORT_SYMBOL_NOVERS(__divdi3); -EXPORT_SYMBOL_NOVERS(__divsi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(__moddi3); -EXPORT_SYMBOL_NOVERS(__modsi3); -EXPORT_SYMBOL_NOVERS(__muldi3); -EXPORT_SYMBOL_NOVERS(__mulsi3); -EXPORT_SYMBOL_NOVERS(__negdi2); -EXPORT_SYMBOL_NOVERS(__ucmpdi2); -EXPORT_SYMBOL_NOVERS(__udivdi3); -EXPORT_SYMBOL_NOVERS(__udivmoddi4); -EXPORT_SYMBOL_NOVERS(__udivsi3); -EXPORT_SYMBOL_NOVERS(__umoddi3); -EXPORT_SYMBOL_NOVERS(__umodsi3); +EXPORT_SYMBOL(__gcc_bcmp); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__cmpdi2); +EXPORT_SYMBOL(__divdi3); +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__moddi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__muldi3); +EXPORT_SYMBOL(__mulsi3); +EXPORT_SYMBOL(__negdi2); +EXPORT_SYMBOL(__ucmpdi2); +EXPORT_SYMBOL(__udivdi3); +EXPORT_SYMBOL(__udivmoddi4); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umoddi3); +EXPORT_SYMBOL(__umodsi3); #ifdef MAGIC_ROM_PTR -EXPORT_SYMBOL_NOVERS(is_in_rom); +EXPORT_SYMBOL(is_in_rom); #endif -EXPORT_SYMBOL_NOVERS(h8300_reserved_gpio); -EXPORT_SYMBOL_NOVERS(h8300_free_gpio); -EXPORT_SYMBOL_NOVERS(h8300_set_gpio_dir); +EXPORT_SYMBOL(h8300_reserved_gpio); +EXPORT_SYMBOL(h8300_free_gpio); +EXPORT_SYMBOL(h8300_set_gpio_dir); diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c index 7246e29ea..edb3c4170 100644 --- a/arch/h8300/kernel/ints.c +++ b/arch/h8300/kernel/ints.c @@ -22,13 +22,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include /* diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index d7c058d64..134aec1c6 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -189,7 +189,7 @@ asmlinkage int h8300_clone(struct pt_regs *regs) newsp = regs->er2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 5905ceeaa..5f19d774a 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -89,13 +89,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_attach(child); goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } ret = ptrace_check_attach(child, request == PTRACE_KILL); if (ret < 0) goto out_tsk; @@ -114,7 +107,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { - unsigned long tmp; + unsigned long tmp = 0; if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { ret = -EIO; @@ -199,7 +192,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; h8300_disable_trace(child); @@ -270,10 +263,8 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index 2742e5389..f469d9160 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c @@ -218,7 +218,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "BogoMips:\t%lu.%02lu\n" "Calibration:\t%lu loops\n", cpu,mode, - clockfreq/100,clockfreq%100, + clockfreq/1000,clockfreq%1000, (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, (loops_per_jiffy*HZ)); diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 17c83890c..962d4305a 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,7 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -68,7 +69,7 @@ asmlinkage int do_sigsuspend(struct pt_regs *regs) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal(regs, &saveset)) return -EINTR; } } @@ -98,7 +99,7 @@ do_rt_sigsuspend(struct pt_regs *regs) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal(regs, &saveset)) return -EINTR; } } @@ -161,6 +162,7 @@ struct sigframe unsigned char retcode[8]; unsigned long extramask[_NSIG_WORDS-1]; struct sigcontext sc; + int sig; } __attribute__((aligned(2),packed)); struct rt_sigframe @@ -172,73 +174,44 @@ struct rt_sigframe #endif long dummy_pc; char *pretcode; + struct siginfo *pinfo; + void *puc; unsigned char retcode[8]; struct siginfo info; struct ucontext uc; + int sig; } __attribute__((aligned(2),packed)); static inline int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, +restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, int *pd0) { - struct sigcontext context; int err = 0; - - /* get previous context */ - if (copy_from_user(&context, usc, sizeof(context))) - goto badframe; - - /* restore passed registers */ - regs->er1 = context.sc_er1; - regs->er2 = context.sc_er2; - regs->er3 = context.sc_er3; - regs->er5 = context.sc_er5; - regs->ccr = (regs->ccr & 0x10)|(context.sc_ccr & 0xef); - regs->pc = context.sc_pc; + unsigned int ccr; + unsigned int usp; + unsigned int er0; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + +#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r) /* restore passed registers */ + COPY(er1); + COPY(er2); + COPY(er3); + COPY(er5); + COPY(pc); + ccr = regs->ccr & 0x10; + COPY(ccr); +#undef COPY + regs->ccr &= 0xef; + regs->ccr |= ccr; regs->orig_er0 = -1; /* disable syscall checks */ - wrusp(context.sc_usp); - - *pd0 = context.sc_er0; - return err; - -badframe: - return 1; -} - -static inline int -rt_restore_ucontext(struct pt_regs *regs, struct ucontext *uc, int *pd0) -{ - int temp; - greg_t *gregs = uc->uc_mcontext.gregs; - unsigned long usp; - int err; - - err = __get_user(temp, &uc->uc_mcontext.version); - if (temp != MCONTEXT_VERSION) - goto badframe; - /* restore passed registers */ - err |= __get_user(regs->er0, &gregs[0]); - err |= __get_user(regs->er1, &gregs[1]); - err |= __get_user(regs->er2, &gregs[2]); - err |= __get_user(regs->er3, &gregs[3]); - err |= __get_user(regs->er4, &gregs[4]); - err |= __get_user(regs->er5, &gregs[5]); - err |= __get_user(regs->er6, &gregs[6]); - err |= __get_user(usp, &gregs[7]); + err |= __get_user(usp, &usc->sc_usp); wrusp(usp); - err |= __get_user(regs->pc, &gregs[8]); - err |= __get_user(temp, &gregs[9]); - regs->ccr = (regs->ccr & 0x10) | (temp & 0xef); - regs->orig_er0 = -1; /* disable syscall checks */ - if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) - goto badframe; - - *pd0 = regs->er0; + err |= __get_user(er0, &usc->sc_er0); + *pd0 = er0; return err; - -badframe: - return 1; } asmlinkage int do_sigreturn(unsigned long __unused,...) @@ -263,7 +236,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->sc, frame + 1, &er0)) + if (restore_sigcontext(regs, &frame->sc, &er0)) goto badframe; return er0; @@ -291,8 +264,12 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...) recalc_sigpending(); spin_lock_irq(¤t->sighand->siglock); - if (rt_restore_ucontext(regs, &frame->uc, &er0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) goto badframe; + + if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) + goto badframe; + return er0; badframe: @@ -300,36 +277,23 @@ badframe: return 0; } -static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, +static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask) { - sc->sc_mask = mask; - sc->sc_usp = rdusp(); - sc->sc_er0 = regs->er0; - sc->sc_er1 = regs->er1; - sc->sc_er2 = regs->er2; - sc->sc_er3 = regs->er3; - sc->sc_er5 = regs->er5; - sc->sc_ccr = regs->ccr; - sc->sc_pc = regs->pc; -} - -static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) -{ - greg_t *gregs = uc->uc_mcontext.gregs; int err = 0; - err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); - err |= __put_user(regs->er0, &gregs[0]); - err |= __put_user(regs->er1, &gregs[1]); - err |= __put_user(regs->er2, &gregs[2]); - err |= __put_user(regs->er3, &gregs[3]); - err |= __put_user(regs->er4, &gregs[4]); - err |= __put_user(regs->er5, &gregs[5]); - err |= __put_user(regs->er6, &gregs[6]); - err |= __put_user(rdusp(), &gregs[7]); - err |= __put_user(regs->pc, &gregs[8]); - err |= __put_user(regs->ccr, &gregs[9]); + err |= __put_user(regs->er0, &sc->sc_er0); + err |= __put_user(regs->er1, &sc->sc_er1); + err |= __put_user(regs->er2, &sc->sc_er2); + err |= __put_user(regs->er3, &sc->sc_er3); + err |= __put_user(regs->er4, &sc->sc_er4); + err |= __put_user(regs->er5, &sc->sc_er5); + err |= __put_user(regs->er6, &sc->sc_er6); + err |= __put_user(rdusp(), &sc->sc_usp); + err |= __put_user(regs->pc, &sc->sc_pc); + err |= __put_user(regs->ccr, &sc->sc_ccr); + err |= __put_user(mask, &sc->sc_mask); + return err; } @@ -353,26 +317,48 @@ static void setup_frame (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { struct sigframe *frame; - struct sigcontext context; int err = 0; + int usig; + unsigned char *ret; frame = get_sigframe(ka, regs, sizeof(*frame)); - if (_NSIG_WORDS > 1) + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(usig, &frame->sig); + if (err) + goto give_sigsegv; + + err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); + if (err) + goto give_sigsegv; + + if (_NSIG_WORDS > 1) { err |= copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); + if (err) + goto give_sigsegv; + } - setup_sigcontext(&context, regs, set->sig[0]); - err |= copy_to_user (&frame->sc, &context, sizeof(context)); + ret = frame->retcode; + if (ka->sa.sa_flags & SA_RESTORER) + ret = (unsigned char *)(ka->sa.sa_restorer); + else { + /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ + err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), + (unsigned long *)(frame->retcode + 0)); + err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); + } /* Set up to return from userspace. */ - err |= __put_user(frame->retcode, &frame->pretcode); - - /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ - err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), - (unsigned long *)(frame->retcode + 0)); - err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); - + err |= __put_user(ret, &frame->pretcode); if (err) goto give_sigsegv; @@ -391,9 +377,7 @@ static void setup_frame (int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, @@ -401,10 +385,29 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, { struct rt_sigframe *frame; int err = 0; + int usig; + unsigned char *ret; frame = get_sigframe(ka, regs, sizeof(*frame)); + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(usig, &frame->sig); + if (err) + goto give_sigsegv; + + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); @@ -414,16 +417,22 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= rt_setup_ucontext(&frame->uc, regs); + err |= setup_sigcontext(&frame->uc.uc_mcontext, 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. */ - err |= __put_user(frame->retcode, &frame->pretcode); - - /* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */ - err != __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff), - (long *)(frame->retcode + 0)); - err |= __put_user(0x5700, (short *)(frame->retcode + 4)); + ret = frame->retcode; + if (ka->sa.sa_flags & SA_RESTORER) + ret = (unsigned char *)(ka->sa.sa_restorer); + else { + /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ + err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), + (unsigned long *)(frame->retcode + 0)); + err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); + } + err |= __put_user(ret, &frame->pretcode); if (err) goto give_sigsegv; @@ -443,46 +452,35 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); -} - -static inline void -handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) -{ - switch (regs->er0) { - case -ERESTARTNOHAND: - if (!has_handler) - goto do_restart; - regs->er0 = -EINTR; - break; - - case -ERESTARTSYS: - if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { - regs->er0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - do_restart: - regs->er0 = regs->orig_er0; - regs->pc -= 2; - break; - } + force_sigsegv(sig, current); } /* * OK, we're invoking a handler */ static void -handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) { /* are we from a system call? */ - if (regs->orig_er0 >= 0) - /* If so, check system call restarting.. */ - handle_restart(regs, ka, 1); + if (regs->orig_er0 >= 0) { + switch (regs->er0) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + regs->er0 = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->er0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + regs->er0 = regs->orig_er0; + regs->pc -= 2; + } + } /* set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) @@ -490,9 +488,6 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -506,137 +501,52 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. - * - * Note that we go through the signals twice: once to check the signals - * that the kernel can handle, and then we build all the user-level signal - * handling stack-frames in one go after that. */ -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; - struct k_sigaction *ka; + int signr; + struct k_sigaction ka; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if ((regs->ccr & 0x10)) + return 1; + + if (current->flags & PF_FREEZE) { + refrigerator(0); + goto no_signal; + } current->thread.esp0 = (unsigned long) regs; if (!oldset) oldset = ¤t->blocked; - for (;;) { - int signr; - - signr = get_signal_to_deliver(&info, regs, NULL); - - if (!signr) - break; - - if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { - current->exit_code = signr; - current->state = TASK_STOPPED; - - /* Did we come from a system call? */ - if (regs->orig_er0 >= 0) { - /* Restart the system call the same way as - if the process were not traced. */ - struct k_sigaction *ka = - ¤t->sighand->action[signr-1]; - int has_handler = - (ka->sa.sa_handler != SIG_IGN && - ka->sa.sa_handler != SIG_DFL); - handle_restart(regs, ka, has_handler); - } - notify_parent(current, SIGCHLD); - schedule(); - - /* We're back. Did the debugger cancel the sig? */ - if (!(signr = current->exit_code)) { - discard_frame: - continue; - } - current->exit_code = 0; - - /* The debugger continued. Ignore SIGSTOP. */ - if (signr == SIGSTOP) - goto discard_frame; - - /* Update the siginfo structure. Is this good? */ - if (signr != info.si_signo) { - info.si_signo = signr; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->parent->pid; - info.si_uid = current->parent->uid; - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(¤t->blocked, signr)) { - send_sig_info(signr, &info, current); - continue; - } - } - - ka = ¤t->sighand->action[signr-1]; - if (ka->sa.sa_handler == SIG_IGN) { - if (signr != SIGCHLD) - continue; - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; - continue; - } - - if (ka->sa.sa_handler == SIG_DFL) { - int exit_code = signr; - - if (current->pid == 1) - continue; - - switch (signr) { - case SIGCONT: case SIGCHLD: - case SIGWINCH: case SIGURG: - continue; - - case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(process_group(current))) - continue; - /* FALLTHRU */ - - case SIGSTOP: { - struct sighand_struct *sig; - current->state = TASK_STOPPED; - current->exit_code = signr; - sig = current->parent->sighand; - if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags -& SA_NOCLDSTOP)) - notify_parent(current, SIGCHLD); - schedule(); - continue; - } - - case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGIOT: case SIGFPE: case SIGSEGV: - case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: - if (do_coredump(signr, exit_code, regs)) - exit_code |= 0x80; - /* FALLTHRU */ - - default: - sigaddset(¤t->pending.signal, signr); - recalc_sigpending(); - current->flags |= PF_SIGNALED; - do_exit(exit_code); - /* NOTREACHED */ - } - } - + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, ka, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } - + no_signal: /* Did we come from a system call? */ - if (regs->orig_er0 >= 0) + if (regs->orig_er0 >= 0) { /* Restart the system call - no handlers present */ - handle_restart(regs, NULL, 0); - + if (regs->er0 == -ERESTARTNOHAND || + regs->er0 == -ERESTARTSYS || + regs->er0 == -ERESTARTNOINTR) { + regs->er0 = regs->orig_er0; + regs->pc -= 2; + } + if (regs->er0 == -ERESTART_RESTARTBLOCK){ + regs->er0 = __NR_restart_syscall; + regs->pc -= 2; + } + } return 0; } diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c index 87e284901..8a6002183 100644 --- a/arch/h8300/kernel/time.c +++ b/arch/h8300/kernel/time.c @@ -36,24 +36,6 @@ u64 jiffies_64; EXPORT_SYMBOL(jiffies_64); -static inline void do_profile (unsigned long pc) -{ - if (prof_buffer && current->pid) { - extern int _stext; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - if (pc < prof_len) - ++prof_buffer[pc]; - else - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - ++prof_buffer[prof_len-1]; - } -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -64,10 +46,10 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) platform_timer_eoi(); do_timer(regs); - - if (!user_mode(regs)) - do_profile(regs->pc); - +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + profile_tick(CPU_PROFILING, regs); } void time_init(void) diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index 7a6009cf2..17fa11da1 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S @@ -1,60 +1,48 @@ #define VMLINUX_SYMBOL(_sym_) _##_sym_ #include -#include #include +/* target memory map */ #ifdef CONFIG_H8300H_GENERIC -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8300h/generic/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8300h/generic/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x400000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x400000 #endif #ifdef CONFIG_H8300H_AKI3068NET -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8300h/aki3068net/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8300h/aki3068net/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x080000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x200000 #endif #ifdef CONFIG_H8300H_H8MAX -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8300h/h8max/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8300h/h8max/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x080000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x200000 #endif #ifdef CONFIG_H8300H_SIM -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8300h/generic/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8300h/generic/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x400000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x400000 #endif #ifdef CONFIG_H8S_SIM -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8s/generic/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8s/generic/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x400000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x800000 #endif #ifdef CONFIG_H8S_EDOSK2674 -#ifdef CONFIG_ROMKERNEL -#include "../platform/h8s/edosk2674/rom.ld" -#endif -#ifdef CONFIG_RAMKERNEL -#include "../platform/h8s/edosk2674/ram.ld" -#endif +#define ROMTOP 0x000000 +#define ROMSIZE 0x400000 +#define RAMTOP 0x400000 +#define RAMSIZE 0x800000 #endif #if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM) @@ -63,71 +51,51 @@ INPUT(romfs.o) _jiffies = _jiffies_64 + 4; +ENTRY(__start) + SECTIONS { #if defined(CONFIG_ROMKERNEL) + . = ROMTOP; .vectors : { __vector = . ; *(.vectors*) - } > vector -#endif -#if defined(CONFIG_RAMKERNEL) - .bootvec : + } +#else + . = RAMTOP; + .bootvec : { *(.bootvec) - } > ram + } #endif .text : { #if defined(CONFIG_ROMKERNEL) - *(.int_redirect) + *(.int_redirect) #endif __stext = . ; *(.text) SCHED_TEXT - . = ALIGN(0x4) ; - *(.exit.text) - *(.text.*) - . = ALIGN(0x4) ; - *(.exitcall.exit) - . = ALIGN(0x4) ; - *(.kstrtab) - . = ALIGN(0x4) ; - *(.rodata*) + LOCK_TEXT + __etext = . ; . = ALIGN(16); /* Exception table */ ___start___ex_table = .; *(__ex_table) ___stop___ex_table = .; + } - ___start___ksymtab = .; /* Kernel symbol table */ - *(__ksymtab) - ___stop___ksymtab = .; - - ___start___ksymtab_gpl = .; /* Kernel symbol table: GPL-only symbols */ - - *(__ksymtab_gpl) - ___stop___ksymtab_gpl = .; - - ___start___kcrctab = .; /* Kernel symbol table: Normal symbols */ - *(__kcrctab) - ___stop___kcrctab = .; - - ___start___kcrctab_gpl = .; /* Kernel symbol table: GPL-only symbols */ - *(__kcrctab_gpl) - ___stop___kcrctab_gpl = .; - - *(__ksymtab_strings) /* Kernel symbol table: strings */ - - . = ALIGN(0x4) ; - __etext = . ; + RODATA #if defined(CONFIG_ROMKERNEL) - } > rom + SECURITY_INIT #endif -#if defined(CONFIG_RAMKERNEL) - } > ram + ROEND = .; +#if defined(CONFIG_ROMKERNEL) + . = RAMTOP; + .data : AT(ROEND) +#else + .data : #endif - .data : AT( ADDR(.text)+SIZEOF(.text)) { __sdata = . ; ___data_start = . ; @@ -150,9 +118,6 @@ SECTIONS *(.init.setup) . = ALIGN(0x4) ; ___setup_end = .; - ___start___param = .; - *(__param) - ___stop___param = .; ___initcall_start = .; *(.initcall1.init) *(.initcall2.init) @@ -165,6 +130,8 @@ SECTIONS ___con_initcall_start = .; *(.con_initcall.init) ___con_initcall_end = .; + *(.exit.text) + *(.exit.data) . = ALIGN(4); ___initramfs_start = .; *(.init.ramfs) @@ -172,14 +139,11 @@ SECTIONS . = ALIGN(0x4) ; ___init_end = .; __edata = . ; - } > ram - __begin_data = LOADADDR(.data) ; -#if defined(CONFIG_ROMKERNEL) - .erom : - { - __erom = . ; - } > erom + } +#if defined(CONFIG_RAMKERNEL) + SECURITY_INIT #endif + __begin_data = LOADADDR(.data); .bss : { . = ALIGN(0x4) ; @@ -191,15 +155,18 @@ SECTIONS __ebss = . ; __end = . ; __ramstart = .; - } > ram + } + /DISCARD/ : { + *(.exitcall.exit) + } .romfs : { *(.romfs*) - } > ram + } + . = RAMTOP+RAMSIZE; .dummy : { COMMAND_START = . - 0x200 ; __ramend = . ; - } > eram + } } - diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c index 6691d0b93..5aa688d92 100644 --- a/arch/h8300/lib/checksum.c +++ b/arch/h8300/lib/checksum.c @@ -32,6 +32,7 @@ of the assembly has to go. */ #include +#include static inline unsigned short from32to16(unsigned long x) { diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S index bd0cf695b..2052dbb94 100644 --- a/arch/h8300/platform/h8300h/entry.S +++ b/arch/h8300/platform/h8300h/entry.S @@ -247,9 +247,9 @@ SYMBOL_NAME_LABEL(ret_from_interrupt) mov.l @(TI_FLAGS:16,er4),er1 btst #TIF_NEED_RESCHED,r1l bne SYMBOL_NAME(reschedule):16 - mov.l sp,er1 - subs #4,er1 /* adjust retpc */ - mov.l er2,er0 + mov.l sp,er0 + subs #4,er0 /* adjust retpc */ + mov.l er2,er1 jsr @SYMBOL_NAME(do_signal) #if defined(CONFIG_PREEMPT) bra done:8 /* userspace thoru */ diff --git a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c index ffc0349b7..6590f89e5 100644 --- a/arch/h8300/platform/h8300h/generic/timer.c +++ b/arch/h8300/platform/h8300h/generic/timer.c @@ -32,7 +32,7 @@ #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ -int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) +void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { /* setup 8bit timer ch2 */ ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */ @@ -69,7 +69,7 @@ void platform_timer_eoi(void) #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */ -int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) +void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { *(unsigned short *)GRA= H8300_TIMER_FREQ / HZ; /* set interval */ *(unsigned short *)TCNT=0; /* clear counter */ diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S index 09007786e..65748bf18 100644 --- a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S +++ b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S @@ -181,7 +181,7 @@ __command_line: .long __start .long __start vector = 2 - .rept 126-1 + .rept 126 .long _interrupt_redirect_table+vector*4 vector = vector + 1 .endr diff --git a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S index 68e5cae80..a7a53c84c 100644 --- a/arch/h8300/platform/h8s/entry.S +++ b/arch/h8300/platform/h8s/entry.S @@ -244,9 +244,9 @@ SYMBOL_NAME_LABEL(ret_from_interrupt) mov.l @(TI_FLAGS:16,er4),er1 btst #TIF_NEED_RESCHED,r1l bne SYMBOL_NAME(reschedule):16 - mov.l sp,er1 - subs #4,er1 /* adjust retpc */ - mov.l er2,er0 + mov.l sp,er0 + subs #4,er0 /* adjust retpc */ + mov.l er2,er1 jsr @SYMBOL_NAME(do_signal) #if defined(CONFIG_PREEMPT) bra done:8 /* userspace thoru */ diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c index bbefac403..5441cdd12 100644 --- a/arch/h8300/platform/h8s/ints.c +++ b/arch/h8300/platform/h8s/ints.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index af9750136..402a71fd1 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -29,8 +29,11 @@ config GENERIC_ISA_DMA bool default y -source "init/Kconfig" +config GENERIC_IOMAP + bool + default y +source "init/Kconfig" menu "Processor type and features" @@ -55,20 +58,20 @@ config X86_ELAN config X86_VOYAGER bool "Voyager (NCR)" help - Voyager is a MCA based 32 way capable SMP architecture proprietary - to NCR Corp. Machine classes 345x/35xx/4100/51xx are voyager based. - + Voyager is an MCA-based 32-way capable SMP architecture proprietary + to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based. + *** WARNING *** - + If you do not specifically know you have a Voyager based machine, - say N here otherwise the kernel you build will not be bootable. + say N here, otherwise the kernel you build will not be bootable. config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" select DISCONTIGMEM select NUMA help - This option is used for getting Linux to run on a (IBM/Sequent) NUMA + This option is used for getting Linux to run on a (IBM/Sequent) NUMA multiquad box. This changes the way that processors are bootstrapped, and uses Clustered Logical APIC addressing mode instead of Flat Logical. You will need a new lynxer.elf file to flash your firmware with - send @@ -115,8 +118,8 @@ config X86_ES7000 depends on SMP help Support for Unisys ES7000 systems. Say 'Y' here if this kernel is - supposed to run on an IA32-based Unisys ES7000 system. - Only choose this option if you have such a system, otherwise you + supposed to run on an IA32-based Unisys ES7000 system. + Only choose this option if you have such a system, otherwise you should say N here. endchoice @@ -176,6 +179,7 @@ config M386 - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). - "Crusoe" for the Transmeta Crusoe series. + - "Efficeon" for the Transmeta Efficeon series. - "Winchip-C6" for original IDT Winchip. - "Winchip-2" for IDT Winchip 2. - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. @@ -196,7 +200,7 @@ config M586 bool "586/K5/5x86/6x86/6x86MX" help Select this for an 586 or 686 series processor such as the AMD K5, - the Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not + the Cyrix 5x86, 6x86 and 6x86MX. This choice does not assume the RDTSC (Read Time Stamp Counter) instruction. config M586TSC @@ -278,6 +282,11 @@ config MCRUSOE like a 586 with TSC, and sets some GCC optimization flags (like a Pentium Pro with no alignment requirements). +config MEFFICEON + bool "Efficeon" + help + Select this for a Transmeta Efficeon processor. + config MWINCHIPC6 bool "Winchip-C6" help @@ -322,7 +331,7 @@ config MVIAC3_2 endchoice config X86_GENERIC - bool "Generic x86 support" + bool "Generic x86 support" help Instead of just including optimizations for the selected x86 variant (e.g. PII, Crusoe or Athlon), include some more @@ -351,7 +360,7 @@ config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC default "4" if X86_ELAN || M486 || M386 - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK @@ -401,17 +410,17 @@ config X86_ALIGNMENT_16 config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON default y config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 + depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON default y config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON default y config X86_USE_3DNOW @@ -546,7 +555,7 @@ config X86_IO_APIC config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ default y config X86_MCE @@ -581,7 +590,7 @@ config X86_MCE_NONFATAL config X86_MCE_P4THERMAL bool "check for P4 thermal throttling interrupt." - depends on X86_MCE && (X86_UP_APIC || SMP) + depends on X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS help Enabling this feature will cause a message to be printed when the P4 enters thermal throttling. @@ -876,7 +885,7 @@ source kernel/power/Kconfig source "drivers/acpi/Kconfig" menu "APM (Advanced Power Management) BIOS Support" -depends on PM +depends on PM && !X86_VISWS config APM tristate "APM (Advanced Power Management) BIOS support" @@ -1027,7 +1036,6 @@ source "arch/i386/kernel/cpu/cpufreq/Kconfig" endmenu - menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" config X86_VISWS_APIC @@ -1105,7 +1113,7 @@ config PCI_DIRECT config PCI_MMCONFIG bool - depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY) + depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI)) select ACPI_BOOT default y @@ -1158,7 +1166,7 @@ config SCx200 tristate "NatSemi SCx200 support" depends on !X86_VOYAGER help - This provides basic support for the National Semiconductor SCx200 + This provides basic support for the National Semiconductor SCx200 processor. Right now this is just a driver for the GPIO pins. If you don't know what to do here, say N. @@ -1172,7 +1180,6 @@ source "drivers/pci/hotplug/Kconfig" endmenu - menu "Executable file formats" source "fs/Kconfig.binfmt" @@ -1185,137 +1192,25 @@ source "fs/Kconfig" source "arch/i386/oprofile/Kconfig" +source "arch/i386/Kconfig.debug" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config EARLY_PRINTK - bool "Early printk" if EMBEDDED - default y - help - Write kernel log output directly into the VGA buffer or to a serial - port. - - This is useful for kernel debugging when your machine crashes very - early before the console code is initialized. For normal operation - it is not recommended because it looks ugly and doesn't cooperate - with klogd/syslogd or the X server. You should normally N here, - unless you want to debug such a crash. - -config DEBUG_STACKOVERFLOW - bool "Check for stack overflows" - depends on DEBUG_KERNEL - -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_PAGEALLOC - bool "Page alloc debugging" - depends on DEBUG_KERNEL - help - Unmap pages from the kernel linear mapping after free_pages(). - This results in a large slowdown, but helps to find certain types - of memory corruptions. - -config DEBUG_HIGHMEM - bool "Highmem debugging" - depends on DEBUG_KERNEL && HIGHMEM - help - This options enables addition error checking for high memory systems. - Disable for production systems. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. +source "security/Kconfig" -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. +source "crypto/Kconfig" -config 4KSTACKS - bool "Use 4Kb for kernel stacks instead of 8Kb" - help - If you say Y here the kernel will use a 4Kb stacksize for the - kernel stack attached to each process/thread. This facilitates - running more threads on a system and also reduces the pressure - on the VM subsystem for higher order allocations. This option - will also use IRQ stacks to compensate for the reduced stackspace. +source "lib/Kconfig" -config X86_FIND_SMP_CONFIG +# +# Use the generic interrupt handling code in kernel/irq/: +# +config GENERIC_HARDIRQS bool - depends on X86_LOCAL_APIC || X86_VOYAGER default y -config X86_MPPARSE +config GENERIC_IRQ_PROBE bool - depends on X86_LOCAL_APIC && !X86_VISWS default y -endmenu - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" - config X86_SMP bool depends on SMP && !X86_VOYAGER diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index cf069b721..ffb664225 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -55,18 +55,6 @@ config 4KSTACKS on the VM subsystem for higher order allocations. This option will also use IRQ stacks to compensate for the reduced stackspace. -config SCHEDSTATS - bool "Collect scheduler statistics" - depends on DEBUG_KERNEL && PROC_FS - help - If you say Y here, additional code will be inserted into the - scheduler and related routines to collect statistics about - scheduler behavior and provide them in /proc/schedstat. These - stats may be useful for both tuning and debugging the scheduler - If you aren't debugging the scheduler or trying to tune a specific - application, you can say N to avoid the very slight overhead - this adds. - config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 1e446b234..8be151e67 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -18,48 +18,48 @@ LDFLAGS := -m elf_i386 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -CHECK := $(CHECK) -D__i386__=1 +CHECKFLAGS += -D__i386__ CFLAGS += -pipe -msoft-float # prevent gcc from keeping the stack 16 byte aligned -CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,) - -align := $(subst -functions=0,,$(call check_gcc,-falign-functions=0,-malign-functions=0)) +CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) +align := $(cc-option-align) cflags-$(CONFIG_M386) += -march=i386 cflags-$(CONFIG_M486) += -march=i486 cflags-$(CONFIG_M586) += -march=i586 cflags-$(CONFIG_M586TSC) += -march=i586 -cflags-$(CONFIG_M586MMX) += $(call check_gcc,-march=pentium-mmx,-march=i586) +cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586) cflags-$(CONFIG_M686) += -march=i686 -cflags-$(CONFIG_MPENTIUMII) += $(call check_gcc,-march=pentium2,-march=i686) -cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686) -cflags-$(CONFIG_MPENTIUMM) += $(call check_gcc,-march=pentium3,-march=i686) -cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686) +cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call cc-option,-mtune=pentium2) +cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call cc-option,-mtune=pentium3) +cflags-$(CONFIG_MPENTIUMM) += -march=i686 $(call cc-option,-mtune=pentium3) +cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call cc-option,-mtune=pentium4) cflags-$(CONFIG_MK6) += -march=k6 # Please note, that patches that add -march=athlon-xp and friends are pointless. # They make zero difference whatsosever to performance at this time. -cflags-$(CONFIG_MK7) += $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4) -cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,$(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4)) +cflags-$(CONFIG_MK7) += $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4) +cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)) cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 -cflags-$(CONFIG_MWINCHIPC6) += $(call check_gcc,-march=winchip-c6,-march=i586) -cflags-$(CONFIG_MWINCHIP2) += $(call check_gcc,-march=winchip2,-march=i586) -cflags-$(CONFIG_MWINCHIP3D) += $(call check_gcc,-march=winchip2,-march=i586) -cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 -cflags-$(CONFIG_MVIAC3_2) += $(call check_gcc,-march=c3-2,-march=i686) +cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call cc-option,-mtune=pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 +cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) +cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) +cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) +cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 +cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) # AMD Elan support cflags-$(CONFIG_X86_ELAN) += -march=i486 # -mregparm=3 works ok on gcc-3.0 and later # -GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) +GCC_VERSION := $(call cc-version) cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) # Disable unit-at-a-time mode, it makes gcc use a lot more stack # due to the lack of sharing of stacklots. -CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) +CFLAGS += $(call cc-option,-fno-unit-at-a-time) CFLAGS += $(cflags-y) diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index d70853d99..aa7064a75 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -29,9 +29,9 @@ targets := vmlinux.bin bootsect bootsect.o setup setup.o \ zImage bzImage subdir- := compressed -host-progs := tools/build +hostprogs-y := tools/build -HOSTCFLAGS_build.o := -Iinclude +HOSTCFLAGS_build.o := $(LINUXINCLUDE) # --------------------------------------------------------------------------- diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index d606d0687..5623e821f 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -156,7 +156,7 @@ cmd_line_ptr: .long 0 # (Header version 0x0202 or later) # can be located anywhere in # low memory 0x10000 or higher. -ramdisk_max: .long (MAXMEM-1) & 0x7fffffff +ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff # (Header version 0x0203 or later) # The highest safe address for # the contents of an initrd diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 7e2c665e6..925d3f5a3 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -232,6 +232,41 @@ mopar_gr: xorl %eax, %eax movw 18(%di), %ax movl %eax, %fs:(PARAM_LFB_SIZE) + +# switching the DAC to 8-bit is for <= 8 bpp only + movw %fs:(PARAM_LFB_DEPTH), %ax + cmpw $8, %ax + jg dac_done + +# get DAC switching capability + xorl %eax, %eax + movb 10(%di), %al + testb $1, %al + jz dac_set + +# attempt to switch DAC to 8-bit + movw $0x4f08, %ax + movw $0x0800, %bx + int $0x10 + cmpw $0x004f, %ax + jne dac_set + movb %bh, dac_size # store actual DAC size + +dac_set: +# set color size to DAC size + movb dac_size, %al + movb %al, %fs:(PARAM_LFB_COLORS+0) + movb %al, %fs:(PARAM_LFB_COLORS+2) + movb %al, %fs:(PARAM_LFB_COLORS+4) + movb %al, %fs:(PARAM_LFB_COLORS+6) + +# set color offsets to 0 + movb $0, %fs:(PARAM_LFB_COLORS+1) + movb $0, %fs:(PARAM_LFB_COLORS+3) + movb $0, %fs:(PARAM_LFB_COLORS+5) + movb $0, %fs:(PARAM_LFB_COLORS+7) + +dac_done: # get protected mode interface informations movw $0x4f0a, %ax xorw %bx, %bx @@ -1901,7 +1936,7 @@ store_edid: movl $0x13131313, %eax # memset block with 0x13 movw $32, %cx - movw $0x440, %di + movw $0x140, %di cld rep stosl @@ -1910,7 +1945,7 @@ store_edid: movw $0x01, %bx movw $0x00, %cx movw $0x01, %dx - movw $0x440, %di + movw $0x140, %di int $0x10 popw %di # restore all registers @@ -1929,6 +1964,7 @@ scanning: .byte 0 # Performing mode scan do_restore: .byte 0 # Screen contents altered during mode change svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +dac_size: .byte 6 # DAC bit depth # Status messages keymsg: .ascii "Press to see video modes available, " diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S index e8a04713d..7b73c67cb 100644 --- a/arch/i386/crypto/aes-i586-asm.S +++ b/arch/i386/crypto/aes-i586-asm.S @@ -61,7 +61,6 @@ #define r3 edx #define r4 esi #define r5 edi -#define r6 ebp #define eaxl al #define eaxh ah @@ -84,60 +83,63 @@ // output registers r0, r1, r4 or r5. // Parameters: +// table table base address // %1 out_state[0] // %2 out_state[1] // %3 out_state[2] // %4 out_state[3] -// %5 table base address -// %6 input register for the round (destroyed) -// %7 scratch register for the round - -#define do_col(a1, a2, a3, a4, a5, a6, a7) \ - movzx %l(a6),%a7; \ - xor a5(,%a7,4),%a1; \ - movzx %h(a6),%a7; \ - shr $16,%a6; \ - xor a5+tlen(,%a7,4),%a2; \ - movzx %l(a6),%a7; \ - movzx %h(a6),%a6; \ - xor a5+2*tlen(,%a7,4),%a3; \ - xor a5+3*tlen(,%a6,4),%a4; +// idx input register for the round (destroyed) +// tmp scratch register for the round +// sched key schedule + +#define do_col(table, a1,a2,a3,a4, idx, tmp) \ + movzx %l(idx),%tmp; \ + xor table(,%tmp,4),%a1; \ + movzx %h(idx),%tmp; \ + shr $16,%idx; \ + xor table+tlen(,%tmp,4),%a2; \ + movzx %l(idx),%tmp; \ + movzx %h(idx),%idx; \ + xor table+2*tlen(,%tmp,4),%a3; \ + xor table+3*tlen(,%idx,4),%a4; // initialise output registers from the key schedule - -#define do_fcol(a1, a2, a3, a4, a5, a6, a7, a8) \ - mov 0 a8,%a1; \ - movzx %l(a6),%a7; \ - mov 12 a8,%a2; \ - xor a5(,%a7,4),%a1; \ - mov 4 a8,%a4; \ - movzx %h(a6),%a7; \ - shr $16,%a6; \ - xor a5+tlen(,%a7,4),%a2; \ - movzx %l(a6),%a7; \ - movzx %h(a6),%a6; \ - xor a5+3*tlen(,%a6,4),%a4; \ - mov %a3,%a6; \ - mov 8 a8,%a3; \ - xor a5+2*tlen(,%a7,4),%a3; +// NB1: original value of a3 is in idx on exit +// NB2: original values of a1,a2,a4 aren't used +#define do_fcol(table, a1,a2,a3,a4, idx, tmp, sched) \ + mov 0 sched,%a1; \ + movzx %l(idx),%tmp; \ + mov 12 sched,%a2; \ + xor table(,%tmp,4),%a1; \ + mov 4 sched,%a4; \ + movzx %h(idx),%tmp; \ + shr $16,%idx; \ + xor table+tlen(,%tmp,4),%a2; \ + movzx %l(idx),%tmp; \ + movzx %h(idx),%idx; \ + xor table+3*tlen(,%idx,4),%a4; \ + mov %a3,%idx; \ + mov 8 sched,%a3; \ + xor table+2*tlen(,%tmp,4),%a3; // initialise output registers from the key schedule - -#define do_icol(a1, a2, a3, a4, a5, a6, a7, a8) \ - mov 0 a8,%a1; \ - movzx %l(a6),%a7; \ - mov 4 a8,%a2; \ - xor a5(,%a7,4),%a1; \ - mov 12 a8,%a4; \ - movzx %h(a6),%a7; \ - shr $16,%a6; \ - xor a5+tlen(,%a7,4),%a2; \ - movzx %l(a6),%a7; \ - movzx %h(a6),%a6; \ - xor a5+3*tlen(,%a6,4),%a4; \ - mov %a3,%a6; \ - mov 8 a8,%a3; \ - xor a5+2*tlen(,%a7,4),%a3; +// NB1: original value of a3 is in idx on exit +// NB2: original values of a1,a2,a4 aren't used +#define do_icol(table, a1,a2,a3,a4, idx, tmp, sched) \ + mov 0 sched,%a1; \ + movzx %l(idx),%tmp; \ + mov 4 sched,%a2; \ + xor table(,%tmp,4),%a1; \ + mov 12 sched,%a4; \ + movzx %h(idx),%tmp; \ + shr $16,%idx; \ + xor table+tlen(,%tmp,4),%a2; \ + movzx %l(idx),%tmp; \ + movzx %h(idx),%idx; \ + xor table+3*tlen(,%idx,4),%a4; \ + mov %a3,%idx; \ + mov 8 sched,%a3; \ + xor table+2*tlen(,%tmp,4),%a3; // original Gladman had conditional saves to MMX regs. @@ -147,44 +149,75 @@ #define restore(a1, a2) \ mov 4*a2(%esp),%a1 -// This macro performs a forward encryption cycle. It is entered with -// the first previous round column values in r0, r1, r4 and r5 and -// exits with the final values in the same registers, using the MMX -// registers mm0-mm1 or the stack for temporary storage - -// mov current column values into the MMX registers -#define fwd_rnd(arg, table) \ - /* mov current column values into the MMX registers */ \ - mov %r0,%r2; \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_fcol(r0,r5,r4,r1,table, r2,r3, arg); \ - do_col (r4,r1,r0,r5,table, r2,r3); \ - restore(r2,0); \ - do_col (r1,r0,r5,r4,table, r2,r3); \ - restore(r2,1); \ - do_col (r5,r4,r1,r0,table, r2,r3); - -// This macro performs an inverse encryption cycle. It is entered with -// the first previous round column values in r0, r1, r4 and r5 and -// exits with the final values in the same registers, using the MMX -// registers mm0-mm1 or the stack for temporary storage - -#define inv_rnd(arg, table) \ - /* mov current column values into the MMX registers */ \ - mov %r0,%r2; \ - save (0,r1); \ - save (1,r5); \ - \ - /* compute new column values */ \ - do_icol(r0,r1,r4,r5, table, r2,r3, arg); \ - do_col (r4,r5,r0,r1, table, r2,r3); \ - restore(r2,0); \ - do_col (r1,r4,r5,r0, table, r2,r3); \ - restore(r2,1); \ - do_col (r5,r0,r1,r4, table, r2,r3); +// These macros perform a forward encryption cycle. They are entered with +// the first previous round column values in r0,r1,r4,r5 and +// exit with the final values in the same registers, using stack +// for temporary storage. + +// round column values +// on entry: r0,r1,r4,r5 +// on exit: r2,r1,r4,r5 +#define fwd_rnd1(arg, table) \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_fcol(table, r2,r5,r4,r1, r0,r3, arg); /* idx=r0 */ \ + do_col (table, r4,r1,r2,r5, r0,r3); /* idx=r4 */ \ + restore(r0,0); \ + do_col (table, r1,r2,r5,r4, r0,r3); /* idx=r1 */ \ + restore(r0,1); \ + do_col (table, r5,r4,r1,r2, r0,r3); /* idx=r5 */ + +// round column values +// on entry: r2,r1,r4,r5 +// on exit: r0,r1,r4,r5 +#define fwd_rnd2(arg, table) \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_fcol(table, r0,r5,r4,r1, r2,r3, arg); /* idx=r2 */ \ + do_col (table, r4,r1,r0,r5, r2,r3); /* idx=r4 */ \ + restore(r2,0); \ + do_col (table, r1,r0,r5,r4, r2,r3); /* idx=r1 */ \ + restore(r2,1); \ + do_col (table, r5,r4,r1,r0, r2,r3); /* idx=r5 */ + +// These macros performs an inverse encryption cycle. They are entered with +// the first previous round column values in r0,r1,r4,r5 and +// exit with the final values in the same registers, using stack +// for temporary storage + +// round column values +// on entry: r0,r1,r4,r5 +// on exit: r2,r1,r4,r5 +#define inv_rnd1(arg, table) \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_icol(table, r2,r1,r4,r5, r0,r3, arg); /* idx=r0 */ \ + do_col (table, r4,r5,r2,r1, r0,r3); /* idx=r4 */ \ + restore(r0,0); \ + do_col (table, r1,r4,r5,r2, r0,r3); /* idx=r1 */ \ + restore(r0,1); \ + do_col (table, r5,r2,r1,r4, r0,r3); /* idx=r5 */ + +// round column values +// on entry: r2,r1,r4,r5 +// on exit: r0,r1,r4,r5 +#define inv_rnd2(arg, table) \ + save (0,r1); \ + save (1,r5); \ + \ + /* compute new column values */ \ + do_icol(table, r0,r1,r4,r5, r2,r3, arg); /* idx=r2 */ \ + do_col (table, r4,r5,r0,r1, r2,r3); /* idx=r4 */ \ + restore(r2,0); \ + do_col (table, r1,r4,r5,r0, r2,r3); /* idx=r1 */ \ + restore(r2,1); \ + do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */ // AES (Rijndael) Encryption Subroutine @@ -198,7 +231,6 @@ aes_enc_blk: push %ebp mov ctx(%esp),%ebp // pointer to context - xor %eax,%eax // CAUTION: the order and the values used in these assigns // rely on the register mappings @@ -208,7 +240,9 @@ aes_enc_blk: push %esi mov nrnd(%ebp),%r3 // number of rounds push %edi - lea ekey(%ebp),%r6 // key pointer +#if ekey != 0 + lea ekey(%ebp),%ebp // key pointer +#endif // input four columns and xor in first round key @@ -216,47 +250,47 @@ aes_enc_blk: mov 4(%r2),%r1 mov 8(%r2),%r4 mov 12(%r2),%r5 - xor (%r6),%r0 - xor 4(%r6),%r1 - xor 8(%r6),%r4 - xor 12(%r6),%r5 + xor (%ebp),%r0 + xor 4(%ebp),%r1 + xor 8(%ebp),%r4 + xor 12(%ebp),%r5 sub $8,%esp // space for register saves on stack - add $16,%r6 // increment to next round key + add $16,%ebp // increment to next round key sub $10,%r3 je 4f // 10 rounds for 128-bit key - add $32,%r6 + add $32,%ebp sub $2,%r3 je 3f // 12 rounds for 128-bit key - add $32,%r6 - -2: fwd_rnd( -64(%r6) ,ft_tab) // 14 rounds for 128-bit key - fwd_rnd( -48(%r6) ,ft_tab) -3: fwd_rnd( -32(%r6) ,ft_tab) // 12 rounds for 128-bit key - fwd_rnd( -16(%r6) ,ft_tab) -4: fwd_rnd( (%r6) ,ft_tab) // 10 rounds for 128-bit key - fwd_rnd( +16(%r6) ,ft_tab) - fwd_rnd( +32(%r6) ,ft_tab) - fwd_rnd( +48(%r6) ,ft_tab) - fwd_rnd( +64(%r6) ,ft_tab) - fwd_rnd( +80(%r6) ,ft_tab) - fwd_rnd( +96(%r6) ,ft_tab) - fwd_rnd(+112(%r6) ,ft_tab) - fwd_rnd(+128(%r6) ,ft_tab) - fwd_rnd(+144(%r6) ,fl_tab) // last round uses a different table + add $32,%ebp + +2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 128-bit key + fwd_rnd2( -48(%ebp) ,ft_tab) +3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 128-bit key + fwd_rnd2( -16(%ebp) ,ft_tab) +4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key + fwd_rnd2( +16(%ebp) ,ft_tab) + fwd_rnd1( +32(%ebp) ,ft_tab) + fwd_rnd2( +48(%ebp) ,ft_tab) + fwd_rnd1( +64(%ebp) ,ft_tab) + fwd_rnd2( +80(%ebp) ,ft_tab) + fwd_rnd1( +96(%ebp) ,ft_tab) + fwd_rnd2(+112(%ebp) ,ft_tab) + fwd_rnd1(+128(%ebp) ,ft_tab) + fwd_rnd2(+144(%ebp) ,fl_tab) // last round uses a different table // move final values to the output array. CAUTION: the // order of these assigns rely on the register mappings add $8,%esp - mov out_blk+12(%esp),%r6 - mov %r5,12(%r6) + mov out_blk+12(%esp),%ebp + mov %r5,12(%ebp) pop %edi - mov %r4,8(%r6) + mov %r4,8(%ebp) pop %esi - mov %r1,4(%r6) + mov %r1,4(%ebp) pop %ebx - mov %r0,(%r6) + mov %r0,(%ebp) pop %ebp mov $1,%eax ret @@ -273,7 +307,6 @@ aes_enc_blk: aes_dec_blk: push %ebp mov ctx(%esp),%ebp // pointer to context - xor %eax,%eax // CAUTION: the order and the values used in these assigns // rely on the register mappings @@ -283,10 +316,12 @@ aes_dec_blk: push %esi mov nrnd(%ebp),%r3 // number of rounds push %edi - lea dkey(%ebp),%r6 // key pointer +#if dkey != 0 + lea dkey(%ebp),%ebp // key pointer +#endif mov %r3,%r0 shl $4,%r0 - add %r0,%r6 + add %r0,%ebp // input four columns and xor in first round key @@ -294,47 +329,47 @@ aes_dec_blk: mov 4(%r2),%r1 mov 8(%r2),%r4 mov 12(%r2),%r5 - xor (%r6),%r0 - xor 4(%r6),%r1 - xor 8(%r6),%r4 - xor 12(%r6),%r5 + xor (%ebp),%r0 + xor 4(%ebp),%r1 + xor 8(%ebp),%r4 + xor 12(%ebp),%r5 - sub $8,%esp // space for register saves on stack - sub $16,%r6 // increment to next round key + sub $8,%esp // space for register saves on stack + sub $16,%ebp // increment to next round key sub $10,%r3 je 4f // 10 rounds for 128-bit key - sub $32,%r6 + sub $32,%ebp sub $2,%r3 je 3f // 12 rounds for 128-bit key - sub $32,%r6 - -2: inv_rnd( +64(%r6), it_tab) // 14 rounds for 128-bit key - inv_rnd( +48(%r6), it_tab) -3: inv_rnd( +32(%r6), it_tab) // 12 rounds for 128-bit key - inv_rnd( +16(%r6), it_tab) -4: inv_rnd( (%r6), it_tab) // 10 rounds for 128-bit key - inv_rnd( -16(%r6), it_tab) - inv_rnd( -32(%r6), it_tab) - inv_rnd( -48(%r6), it_tab) - inv_rnd( -64(%r6), it_tab) - inv_rnd( -80(%r6), it_tab) - inv_rnd( -96(%r6), it_tab) - inv_rnd(-112(%r6), it_tab) - inv_rnd(-128(%r6), it_tab) - inv_rnd(-144(%r6), il_tab) // last round uses a different table + sub $32,%ebp + +2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 128-bit key + inv_rnd2( +48(%ebp), it_tab) +3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 128-bit key + inv_rnd2( +16(%ebp), it_tab) +4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key + inv_rnd2( -16(%ebp), it_tab) + inv_rnd1( -32(%ebp), it_tab) + inv_rnd2( -48(%ebp), it_tab) + inv_rnd1( -64(%ebp), it_tab) + inv_rnd2( -80(%ebp), it_tab) + inv_rnd1( -96(%ebp), it_tab) + inv_rnd2(-112(%ebp), it_tab) + inv_rnd1(-128(%ebp), it_tab) + inv_rnd2(-144(%ebp), il_tab) // last round uses a different table // move final values to the output array. CAUTION: the // order of these assigns rely on the register mappings add $8,%esp - mov out_blk+12(%esp),%r6 - mov %r5,12(%r6) + mov out_blk+12(%esp),%ebp + mov %r5,12(%ebp) pop %edi - mov %r4,8(%r6) + mov %r4,8(%ebp) pop %esi - mov %r1,4(%r6) + mov %r1,4(%ebp) pop %ebx - mov %r0,(%r6) + mov %r0,(%ebp) pop %ebp mov $1,%eax ret diff --git a/arch/i386/defconfig b/arch/i386/defconfig index aed3bc298..1a0ba2c4d 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -71,6 +71,7 @@ CONFIG_MPENTIUM4=y # CONFIG_MK7 is not set # CONFIG_MK8 is not set # CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set # CONFIG_MWINCHIPC6 is not set # CONFIG_MWINCHIP2 is not set # CONFIG_MWINCHIP3D is not set diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 00cc32e33..711a5249f 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -2,12 +2,12 @@ # Makefile for the linux kernel. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ - ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ + ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \ - doublefault.o + doublefault.o quirks.o obj-y += cpu/ obj-y += timers/ @@ -25,6 +25,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o +obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_MODULES) += module.o obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o @@ -41,12 +42,15 @@ obj-$(CONFIG_SCx200) += scx200.o # Note: kbuild does not track this dependency due to usage of .incbin $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so) +targets += vsyscall.lds # The DSO images are built using a special linker script. quiet_cmd_syscall = SYSCALL $@ cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ +export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH) + vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags) SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile index 2cf76a941..ee75cb286 100644 --- a/arch/i386/kernel/acpi/Makefile +++ b/arch/i386/kernel/acpi/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_ACPI_BOOT) := boot.o +obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index e54aefaa8..06976cc8e 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -40,7 +40,7 @@ #ifdef CONFIG_X86_64 static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { } -static inline void clustered_apic_check(void) { } +extern void __init clustered_apic_check(void); static inline int ioapic_setup_disabled(void) { return 0; } #include @@ -71,6 +71,7 @@ int acpi_ht __initdata = 1; /* enable HT */ int acpi_lapic; int acpi_ioapic; int acpi_strict; +EXPORT_SYMBOL(acpi_strict); acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; @@ -84,6 +85,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; #warning ACPI uses CMPXCHG, i486 and later hardware #endif +#define MAX_MADT_ENTRIES 256 +u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = + { [0 ... MAX_MADT_ENTRIES-1] = 0xff }; +EXPORT_SYMBOL(x86_acpiid_to_apicid); + /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -225,6 +231,8 @@ acpi_parse_lapic ( if (processor->flags.enabled == 0) return 0; + x86_acpiid_to_apicid[processor->acpi_id] = processor->id; + mp_register_lapic ( processor->id, /* APIC ID */ processor->flags.enabled); /* Enabled? */ @@ -401,28 +409,38 @@ acpi_parse_nmi_src ( void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) { - unsigned char mask = 1 << (irq & 7); - unsigned int port = 0x4d0 + (irq >> 3); - unsigned char val = inb(port); + unsigned int mask = 1 << irq; + unsigned int old, new; - - printk(PREFIX "IRQ%d SCI:", irq); - if (!(val & mask)) { - printk(" Edge"); + /* Real old ELCR mask */ + old = inb(0x4d0) | (inb(0x4d1) << 8); - if (trigger == 3) { - printk(" set to Level"); - outb(val | mask, port); - } - } else { - printk(" Level"); + /* + * If we use ACPI to set PCI irq's, then we should clear ELCR + * since we will set it correctly as we enable the PCI irq + * routing. + */ + new = acpi_noirq ? old : 0; - if (trigger == 1) { - printk(" set to Edge"); - outb(val & ~mask, port); - } + /* + * Update SCI information in the ELCR, it isn't in the PCI + * routing tables.. + */ + switch (trigger) { + case 1: /* Edge - clear */ + new &= ~mask; + break; + case 3: /* Level - set */ + new |= mask; + break; } - printk(" Trigger.\n"); + + if (old == new) + return; + + printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old); + outb(new, 0x4d0); + outb(new >> 8, 0x4d1); } @@ -442,31 +460,26 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) { unsigned int irq; + unsigned int plat_gsi = gsi; #ifdef CONFIG_PCI /* * Make sure all (legacy) PCI IRQs are set as level-triggered. */ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { - static u16 irq_mask; extern void eisa_set_level_irq(unsigned int irq); - if (edge_level == ACPI_LEVEL_SENSITIVE) { - if ((gsi < 16) && !((1 << gsi) & irq_mask)) { - Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi); - irq_mask |= (1 << gsi); + if (edge_level == ACPI_LEVEL_SENSITIVE) eisa_set_level_irq(gsi); - } - } } #endif #ifdef CONFIG_X86_IO_APIC if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { - mp_register_gsi(gsi, edge_level, active_high_low); + plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low); } #endif - acpi_gsi_to_irq(gsi, &irq); + acpi_gsi_to_irq(plat_gsi, &irq); return irq; } EXPORT_SYMBOL(acpi_register_gsi); @@ -740,7 +753,7 @@ acpi_process_madt(void) int count, error; count = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (count == 1) { + if (count >= 1) { /* * Parse MADT LAPIC entries @@ -815,6 +828,10 @@ acpi_boot_init (void) return error; } +#ifdef __i386__ + check_acpi_pci(); +#endif + acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); /* @@ -822,9 +839,15 @@ acpi_boot_init (void) */ error = acpi_blacklisted(); if (error) { - printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); - disable_acpi(); - return error; + extern int acpi_force; + + if (acpi_force) { + printk(KERN_WARNING PREFIX "acpi=force override\n"); + } else { + printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); + disable_acpi(); + return error; + } } /* diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index 92fd1760a..be4df5548 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c @@ -56,7 +56,7 @@ int acpi_save_state_disk (void) } /* - * acpi_restore_state + * acpi_restore_state - undo effects of acpi_save_state_mem */ void acpi_restore_state_mem (void) { @@ -77,10 +77,7 @@ void __init acpi_reserve_bootmem(void) printk(KERN_ERR "ACPI: Wakeup code way too big, S3 disabled.\n"); return; } -#ifdef CONFIG_X86_PAE - printk(KERN_ERR "ACPI: S3 and PAE do not like each other for now, S3 disabled.\n"); - return; -#endif + acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); if (!acpi_wakeup_address) printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index 2c5de1d7f..c63ba5826 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S @@ -59,6 +59,14 @@ wakeup_code: movl $swapper_pg_dir-__PAGE_OFFSET, %eax movl %eax, %cr3 + testl $1, real_efer_save_restore - wakeup_code + jz 4f + # restore efer setting + movl real_save_efer_edx - wakeup_code, %edx + movl real_save_efer_eax - wakeup_code, %eax + mov $0xc0000080, %ecx + wrmsr +4: # make sure %cr4 is set correctly (features, etc) movl real_save_cr4 - wakeup_code, %eax movl %eax, %cr4 @@ -89,6 +97,9 @@ real_save_cr4: .long 0 real_magic: .long 0 video_mode: .long 0 video_flags: .long 0 +real_efer_save_restore: .long 0 +real_save_efer_edx: .long 0 +real_save_efer_eax: .long 0 bogus_real_magic: movw $0x0e00 + 'B', %fs:(0x12) @@ -223,6 +234,20 @@ ENTRY(acpi_copy_wakeup_routine) sldt saved_ldt str saved_tss + movl nx_enabled, %edx + movl %edx, real_efer_save_restore - wakeup_start (%eax) + testl $1, real_efer_save_restore - wakeup_start (%eax) + jz 2f + # save efer setting + pushl %eax + movl %eax, %ebx + mov $0xc0000080, %ecx + rdmsr + movl %edx, real_save_efer_edx - wakeup_start (%ebx) + movl %eax, real_save_efer_eax - wakeup_start (%ebx) + popl %eax +2: + movl %cr3, %edx movl %edx, real_save_cr3 - wakeup_start (%eax) movl %cr4, %edx diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index ecf2b632f..df8900b1f 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -39,8 +39,32 @@ #include "io_ports.h" +/* + * Debug level + */ +int apic_verbosity; + + static void apic_pm_activate(void); +/* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves. + */ +void ack_bad_irq(unsigned int irq) +{ + printk("unexpected IRQ trap at vector %02x\n", irq); + /* + * Currently unexpected vectors happen only on SMP and APIC. + * We _must_ ack these because every local APIC has only N + * irq slots per priority level, and a 'hanging, unacked' IRQ + * holds up an irq slot - in excessive cases (when multiple + * unexpected vectors occur) that might lock up the APIC + * completely. + */ + ack_APIC_irq(); +} + void __init apic_intr_init(void) { #ifdef CONFIG_SMP @@ -85,7 +109,7 @@ int get_physical_broadcast(void) unsigned int lvr, version; lvr = apic_read(APIC_LVR); version = GET_APIC_VERSION(lvr); - if (version >= 0x14) + if (!APIC_INTEGRATED(version) || version >= 0x14) return 0xff; else return 0xf; @@ -173,7 +197,8 @@ void __init connect_bsp_APIC(void) * PIC mode, enable APIC mode in the IMCR, i.e. * connect BSP's local APIC to INT and NMI lines. */ - printk("leaving PIC mode, enabling APIC mode.\n"); + apic_printk(APIC_VERBOSE, "leaving PIC mode, " + "enabling APIC mode.\n"); outb(0x70, 0x22); outb(0x01, 0x23); } @@ -189,7 +214,8 @@ void disconnect_bsp_APIC(void) * interrupts, including IPIs, won't work beyond * this point! The only exception are INIT IPIs. */ - printk("disabling APIC mode, entering PIC mode.\n"); + apic_printk(APIC_VERBOSE, "disabling APIC mode, " + "entering PIC mode.\n"); outb(0x70, 0x22); outb(0x00, 0x23); } @@ -230,10 +256,10 @@ int __init verify_local_APIC(void) * The version register is read-only in a real APIC. */ reg0 = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg0); + apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0); apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); reg1 = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg1); + apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1); /* * The two version reads above should print the same @@ -257,7 +283,7 @@ int __init verify_local_APIC(void) * The ID register is read/write in a real APIC. */ reg0 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg0); + apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); /* * The next two are just to see if we have sane values. @@ -265,21 +291,25 @@ int __init verify_local_APIC(void) * compatibility mode, but most boxes are anymore. */ reg0 = apic_read(APIC_LVT0); - Dprintk("Getting LVT0: %x\n", reg0); + apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0); reg1 = apic_read(APIC_LVT1); - Dprintk("Getting LVT1: %x\n", reg1); + apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1); return 1; } void __init sync_Arb_IDs(void) { + /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ + unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + if (ver >= 0x14) /* P4 or higher */ + return; /* * Wait for idle. */ apic_wait_icr_idle(); - Dprintk("Synchronizing Arb IDs.\n"); + apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } @@ -335,7 +365,7 @@ void __init init_bsp_APIC(void) void __init setup_local_APIC (void) { - unsigned long value, ver, maxlvt; + unsigned long oldvalue, value, ver, maxlvt; /* Pound the ESR really hard over the head with a big hammer - mbligh */ if (esr_disable) { @@ -427,10 +457,12 @@ void __init setup_local_APIC (void) value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; if (!smp_processor_id() && (pic_mode || !value)) { value = APIC_DM_EXTINT; - printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); + apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", + smp_processor_id()); } else { value = APIC_DM_EXTINT | APIC_LVT_MASKED; - printk("masked ExtINT on CPU#%d\n", smp_processor_id()); + apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", + smp_processor_id()); } apic_write_around(APIC_LVT0, value); @@ -449,8 +481,7 @@ void __init setup_local_APIC (void) maxlvt = get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - printk("ESR value before enabling vector: %08lx\n", value); + oldvalue = apic_read(APIC_ESR); value = ERROR_APIC_VECTOR; // enables sending errors apic_write_around(APIC_LVTERR, value); @@ -460,7 +491,10 @@ void __init setup_local_APIC (void) if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - printk("ESR value after enabling vector: %08lx\n", value); + if (value != oldvalue) + apic_printk(APIC_VERBOSE, "ESR value before enabling " + "vector: 0x%08lx after: 0x%08lx\n", + oldvalue, value); } else { if (esr_disable) /* @@ -479,12 +513,25 @@ void __init setup_local_APIC (void) apic_pm_activate(); } +/* + * If Linux enabled the LAPIC against the BIOS default + * disable it down before re-entering the BIOS on shutdown. + * Otherwise the BIOS may get confused and not power-off. + */ +void +lapic_shutdown() +{ + if (!cpu_has_apic || !enabled_via_apicbase) + return; + + local_irq_disable(); + disable_local_APIC(); + local_irq_enable(); +} + #ifdef CONFIG_PM static struct { - /* 'active' is true if the local APIC was enabled by us and - not the BIOS; this signifies that we are also responsible - for disabling it before entering apm/acpi suspend */ int active; /* r/w apic fields */ unsigned int apic_id; @@ -572,6 +619,10 @@ static int lapic_resume(struct sys_device *dev) return 0; } +/* + * This device has no shutdown method - fully functioning local APICs + * are needed on every CPU up until machine_halt/restart/poweroff. + */ static struct sysdev_class lapic_sysclass = { set_kset_name("lapic"), @@ -635,12 +686,27 @@ static int __init lapic_enable(char *str) } __setup("lapic", lapic_enable); +static int __init apic_set_verbosity(char *str) +{ + if (strcmp("debug", str) == 0) + apic_verbosity = APIC_DEBUG; + else if (strcmp("verbose", str) == 0) + apic_verbosity = APIC_VERBOSE; + else + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug", str); + + return 0; +} + +__setup("apic=", apic_set_verbosity); + static int __init detect_init_APIC (void) { u32 h, l, features; extern void get_cpu_vendor(struct cpuinfo_x86*); - /* Disabled by DMI scan or kernel option? */ + /* Disabled by kernel option? */ if (enable_local_apic < 0) return -1; @@ -654,8 +720,7 @@ static int __init detect_init_APIC (void) break; goto no_apic; case X86_VENDOR_INTEL: - if (boot_cpu_data.x86 == 6 || - (boot_cpu_data.x86 == 15 && (cpu_has_apic || enable_local_apic > 0)) || + if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 || (boot_cpu_data.x86 == 5 && cpu_has_apic)) break; goto no_apic; @@ -664,10 +729,20 @@ static int __init detect_init_APIC (void) } if (!cpu_has_apic) { + /* + * Over-ride BIOS and try to enable the local + * APIC only if "lapic" specified. + */ + if (enable_local_apic <= 0) { + printk("Local APIC disabled by BIOS -- " + "you can enable it with \"lapic\"\n"); + return -1; + } /* * Some BIOSes disable the local APIC in the * APIC_BASE MSR. This can only be done in - * software for Intel P6 and AMD K7 (Model > 1). + * software for Intel P6 or later and AMD K7 + * (Model > 1) or later. */ rdmsr(MSR_IA32_APICBASE, l, h); if (!(l & MSR_IA32_APICBASE_ENABLE)) { @@ -725,7 +800,8 @@ void __init init_apic_mappings(void) apic_phys = mp_lapic_addr; set_fixmap_nocache(FIX_APIC_BASE, apic_phys); - Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); + printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE, + apic_phys); /* * Fetch the APIC ID of the BSP in case we have a @@ -743,20 +819,23 @@ void __init init_apic_mappings(void) if (smp_found_config) { ioapic_phys = mp_ioapics[i].mpc_apicaddr; if (!ioapic_phys) { - printk(KERN_ERR "WARNING: bogus zero IO-APIC address found in MPTABLE, disabling IO/APIC support!\n"); - + printk(KERN_ERR + "WARNING: bogus zero IO-APIC " + "address found in MPTABLE, " + "disabling IO/APIC support!\n"); smp_found_config = 0; skip_ioapic_setup = 1; goto fake_ioapic_page; } } else { fake_ioapic_page: - ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); + ioapic_phys = (unsigned long) + alloc_bootmem_pages(PAGE_SIZE); ioapic_phys = __pa(ioapic_phys); } set_fixmap_nocache(idx, ioapic_phys); - Dprintk("mapped IOAPIC to %08lx (%08lx)\n", - __fix_to_virt(idx), ioapic_phys); + printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n", + __fix_to_virt(idx), ioapic_phys); idx++; } } @@ -894,7 +973,7 @@ int __init calibrate_APIC_clock(void) int i; const int LOOPS = HZ/10; - printk("calibrating APIC timer ...\n"); + apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n"); /* * Put whatever arbitrary (but long enough) timeout @@ -939,11 +1018,13 @@ int __init calibrate_APIC_clock(void) result = (tt1-tt2)*APIC_DIVISOR/LOOPS; if (cpu_has_tsc) - printk("..... CPU clock speed is %ld.%04ld MHz.\n", + apic_printk(APIC_VERBOSE, "..... CPU clock speed is " + "%ld.%04ld MHz.\n", ((long)(t2-t1)/LOOPS)/(1000000/HZ), ((long)(t2-t1)/LOOPS)%(1000000/HZ)); - printk("..... host bus clock speed is %ld.%04ld MHz.\n", + apic_printk(APIC_VERBOSE, "..... host bus clock speed is " + "%ld.%04ld MHz.\n", result/(1000000/HZ), result%(1000000/HZ)); @@ -954,7 +1035,7 @@ static unsigned int calibration_result; void __init setup_boot_APIC_clock(void) { - printk("Using local APIC timer interrupts.\n"); + apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"); using_apic_timer = 1; local_irq_disable(); @@ -1039,8 +1120,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) { int cpu = smp_processor_id(); - x86_do_profile(regs); - + profile_tick(CPU_PROFILING, regs); if (--per_cpu(prof_counter, cpu) <= 0) { /* * The multiplier may have changed since the last time we got @@ -1086,7 +1166,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs) * interrupt as well. Thus we cannot inline the local irq ... ] */ -void smp_apic_timer_interrupt(struct pt_regs regs) +fastcall void smp_apic_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -1106,14 +1186,14 @@ void smp_apic_timer_interrupt(struct pt_regs regs) * interrupt lock, which is the WrongThing (tm) to do. */ irq_enter(); - smp_local_timer_interrupt(®s); + smp_local_timer_interrupt(regs); irq_exit(); } /* * This interrupt should _never_ happen with our APIC/SMP architecture */ -asmlinkage void smp_spurious_interrupt(void) +fastcall void smp_spurious_interrupt(struct pt_regs *regs) { unsigned long v; @@ -1137,7 +1217,7 @@ asmlinkage void smp_spurious_interrupt(void) * This interrupt should never happen with our APIC/SMP architecture */ -asmlinkage void smp_error_interrupt(void) +fastcall void smp_error_interrupt(struct pt_regs *regs) { unsigned long v, v1; @@ -1159,7 +1239,7 @@ asmlinkage void smp_error_interrupt(void) 6: Received illegal vector 7: Illegal register address */ - printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n", + printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n", smp_processor_id(), v , v1); irq_exit(); } diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 3b1ef4bcb..904217f53 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -601,8 +601,8 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, cpus = apm_save_cpus(); cpu = get_cpu(); - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; + save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8]; + per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc; local_save_flags(flags); APM_DO_CLI; @@ -610,7 +610,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); APM_DO_RESTORE_SEGS; local_irq_restore(flags); - cpu_gdt_table[cpu][0x40 / 8] = save_desc_40; + per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); @@ -644,8 +644,8 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) cpus = apm_save_cpus(); cpu = get_cpu(); - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; + save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8]; + per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc; local_save_flags(flags); APM_DO_CLI; @@ -653,7 +653,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); APM_DO_RESTORE_SEGS; local_irq_restore(flags); - cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40; + __get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40; put_cpu(); apm_restore_cpus(cpus); return error; @@ -2271,10 +2271,12 @@ static int __init apm_init(void) } if ((num_online_cpus() > 1) && !power_off && !smp) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + apm_info.disabled = 1; return -ENODEV; } if (PM_IS_ACTIVE()) { printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + apm_info.disabled = 1; return -ENODEV; } pm_active = 1; @@ -2292,35 +2294,35 @@ static int __init apm_init(void) apm_bios_entry.segment = APM_CS; for (i = 0; i < NR_CPUS; i++) { - set_base(cpu_gdt_table[i][APM_CS >> 3], + set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3], __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(cpu_gdt_table[i][APM_CS_16 >> 3], + set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(cpu_gdt_table[i][APM_DS >> 3], + set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); #ifndef APM_RELAX_SEGMENTS if (apm_info.bios.version == 0x100) { #endif /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1); + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1); /* For some unknown machine. */ - _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1); + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1); /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1); + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1); #ifndef APM_RELAX_SEGMENTS } else { - _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], (apm_info.bios.cseg_len - 1) & 0xffff); - _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], (apm_info.bios.cseg_16_len - 1) & 0xffff); - _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], (apm_info.bios.dseg_len - 1) & 0xffff); /* workaround for broken BIOSes */ if (apm_info.bios.cseg_len <= apm_info.bios.offset) - _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 -1); + _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1); if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */ /* for the BIOS that assumes granularity = 1 */ - cpu_gdt_table[i][APM_DS >> 3].b |= 0x800000; + per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000; printk(KERN_NOTICE "apm: we set the granularity of dseg.\n"); } } @@ -2360,8 +2362,15 @@ static void __exit apm_exit(void) { int error; - if (set_pm_idle) + if (set_pm_idle) { pm_idle = original_pm_idle; + /* + * We are about to unload the current idle thread pm callback + * (pm_idle), Wait for all processors to update cached/local + * copies of pm_idle before proceeding. + */ + synchronize_kernel(); + } if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) && (apm_info.connection_version > 0x0100)) { error = apm_engage_power_management(APM_DEVICE_ALL, 0); @@ -2384,27 +2393,27 @@ module_exit(apm_exit); MODULE_AUTHOR("Stephen Rothwell"); MODULE_DESCRIPTION("Advanced Power Management"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Enable debug mode"); -MODULE_PARM(power_off, "i"); +module_param(power_off, bool, 0444); MODULE_PARM_DESC(power_off, "Enable power off"); -MODULE_PARM(bounce_interval, "i"); +module_param(bounce_interval, int, 0444); MODULE_PARM_DESC(bounce_interval, "Set the number of ticks to ignore suspend bounces"); -MODULE_PARM(allow_ints, "i"); +module_param(allow_ints, bool, 0444); MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls"); -MODULE_PARM(broken_psr, "i"); +module_param(broken_psr, bool, 0444); MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call"); -MODULE_PARM(realmode_power_off, "i"); +module_param(realmode_power_off, bool, 0444); MODULE_PARM_DESC(realmode_power_off, "Switch to real mode before powering off"); -MODULE_PARM(idle_threshold, "i"); +module_param(idle_threshold, int, 0444); MODULE_PARM_DESC(idle_threshold, "System idle percentage above which to make APM BIOS idle calls"); -MODULE_PARM(idle_period, "i"); +module_param(idle_period, int, 0444); MODULE_PARM_DESC(idle_period, "Period (in sec/100) over which to caculate the idle percentage"); -MODULE_PARM(smp, "i"); +module_param(smp, bool, 0444); MODULE_PARM_DESC(smp, "Set this to enable APM use on an SMP platform. Use with caution on older systems"); MODULE_ALIAS_MISCDEV(APM_MINOR_DEV); diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index 6248bf257..38d82e380 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c @@ -62,4 +62,5 @@ void foo(void) sizeof(struct tss_struct)); DEFINE(PAGE_SIZE_asm, PAGE_SIZE); + DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL)); } diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile index bcc15802e..010aecfff 100644 --- a/arch/i386/kernel/cpu/Makefile +++ b/arch/i386/kernel/cpu/Makefile @@ -8,7 +8,7 @@ obj-y += amd.o obj-y += cyrix.o obj-y += centaur.o obj-y += transmeta.o -obj-y += intel.o +obj-y += intel.o intel_cacheinfo.o obj-y += rise.o obj-y += nexgen.o obj-y += umc.o diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c index e85f4827e..394814e57 100644 --- a/arch/i386/kernel/cpu/centaur.c +++ b/arch/i386/kernel/cpu/centaur.c @@ -286,23 +286,20 @@ static void __init init_c3(struct cpuinfo_x86 *c) c->x86_capability[5] = cpuid_edx(0xC0000001); } - switch (c->x86_model) { - case 6 ... 8: /* Cyrix III family */ - rdmsr (MSR_VIA_FCR, lo, hi); - lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ - wrmsr (MSR_VIA_FCR, lo, hi); - - set_bit(X86_FEATURE_CX8, c->x86_capability); - set_bit(X86_FEATURE_3DNOW, c->x86_capability); + /* Cyrix III family needs CX8 & PGE explicity enabled. */ + if (c->x86_model >=6 && c->x86_model <= 9) { + rdmsr (MSR_VIA_FCR, lo, hi); + lo |= (1<<1 | 1<<7); + wrmsr (MSR_VIA_FCR, lo, hi); + set_bit(X86_FEATURE_CX8, c->x86_capability); + } - /* fall through */ + /* Before Nehemiah, the C3's had 3dNOW! */ + if (c->x86_model >=6 && c->x86_model <9) + set_bit(X86_FEATURE_3DNOW, c->x86_capability); - case 9: /* Nehemiah */ - default: - get_model_name(c); - display_cacheinfo(c); - break; - } + get_model_name(c); + display_cacheinfo(c); } static void __init init_centaur(struct cpuinfo_x86 *c) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 30e25e357..89dc79a65 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include #include @@ -11,6 +13,9 @@ #include "cpu.h" +DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); +EXPORT_PER_CPU_SYMBOL(cpu_gdt_table); + static int cachesize_override __initdata = -1; static int disable_x86_fxsr __initdata = 0; static int disable_x86_serial_nr __initdata = 1; @@ -501,7 +506,7 @@ void __init early_cpu_init(void) void __init cpu_init (void) { int cpu = smp_processor_id(); - struct tss_struct * t = init_tss + cpu; + struct tss_struct * t = &per_cpu(init_tss, cpu); struct thread_struct *thread = ¤t->thread; if (test_and_set_bit(cpu, &cpu_initialized)) { @@ -523,15 +528,17 @@ void __init cpu_init (void) * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ - if (cpu) { - memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE); - cpu_gdt_descr[cpu].size = GDT_SIZE - 1; - cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu]; - } + memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table, + GDT_SIZE); + cpu_gdt_descr[cpu].size = GDT_SIZE - 1; + cpu_gdt_descr[cpu].address = + (unsigned long)&per_cpu(cpu_gdt_table, cpu); + /* * Set up the per-thread TLS descriptor cache: */ - memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8); + memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu), + GDT_ENTRY_TLS_ENTRIES * 8); __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu])); __asm__ __volatile__("lidt %0" : : "m" (idt_descr)); @@ -552,13 +559,11 @@ void __init cpu_init (void) load_esp0(t, thread); set_tss_desc(cpu,t); - cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); load_LDT(&init_mm.context); /* Set up doublefault TSS pointer in the GDT */ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); - cpu_gdt_table[cpu][GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff; /* Clear %fs and %gs. */ asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs"); diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index d285dc1ba..32bcd8eba 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig @@ -4,18 +4,6 @@ menu "CPU Frequency scaling" -config CPU_FREQ - bool "CPU Frequency scaling" - help - Clock scaling allows you to change the clock speed of CPUs on the - fly. This is a nice method to save battery power on notebooks, - because the lower the clock speed, the less power the CPU consumes. - - For more information, take a look at - or at - - If in doubt, say N. - source "drivers/cpufreq/Kconfig" config CPU_FREQ_TABLE @@ -42,16 +30,6 @@ config X86_ACPI_CPUFREQ If in doubt, say N. -config X86_ACPI_CPUFREQ_PROC_INTF - bool "/proc/acpi/processor/../performance interface (deprecated)" - depends on X86_ACPI_CPUFREQ && PROC_FS - help - This enables the deprecated /proc/acpi/processor/../performance - interface. While it is helpful for debugging, the generic, - cross-architecture cpufreq interfaces should be used. - - If in doubt, say N. - config ELAN_CPUFREQ tristate "AMD Elan" depends on CPU_FREQ_TABLE && X86_ELAN @@ -88,9 +66,14 @@ config X86_POWERNOW_K7 If in doubt, say N. +config X86_POWERNOW_K7_ACPI + bool + depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y")) + default y + config X86_POWERNOW_K8 tristate "AMD Opteron/Athlon64 PowerNow!" - depends on CPU_FREQ && EXPERIMENTAL + depends on CPU_FREQ_TABLE && EXPERIMENTAL help This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors. @@ -98,6 +81,11 @@ config X86_POWERNOW_K8 If in doubt, say N. +config X86_POWERNOW_K8_ACPI + bool + depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y")) + default y + config X86_GX_SUSPMOD tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" depends on CPU_FREQ @@ -112,29 +100,40 @@ config X86_GX_SUSPMOD config X86_SPEEDSTEP_CENTRINO tristate "Intel Enhanced SpeedStep" depends on CPU_FREQ_TABLE + select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI) help This adds the CPUFreq driver for Enhanced SpeedStep enabled - mobile CPUs. This means Intel Pentium M (Centrino) CPUs. + mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, + you also need to say Y to "Use ACPI tables to decode..." below + [which might imply enabling ACPI] if you want to use this driver + on non-Banias CPUs. For details, take a look at . If in doubt, say N. -config X86_SPEEDSTEP_CENTRINO_TABLE - bool - depends on X86_SPEEDSTEP_CENTRINO - default y - config X86_SPEEDSTEP_CENTRINO_ACPI - bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "Use ACPI tables to decode valid frequency/voltage pairs" + depends on X86_SPEEDSTEP_CENTRINO depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y")) + default y help Use primarily the information provided in the BIOS ACPI tables - to determine valid CPU frequency and voltage pairings. + to determine valid CPU frequency and voltage pairings. It is + required for the driver to work on non-Banias CPUs. If in doubt, say Y. +config X86_SPEEDSTEP_CENTRINO_TABLE + bool "Built-in tables for Banias CPUs" + depends on X86_SPEEDSTEP_CENTRINO + default y + help + Use built-in tables for Banias CPUs if ACPI encoding + is not available. + + If in doubt, say N. + config X86_SPEEDSTEP_ICH tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" depends on CPU_FREQ_TABLE @@ -171,27 +170,23 @@ config X86_P4_CLOCKMOD If in doubt, say N. -config X86_SPEEDSTEP_LIB - tristate - depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) - default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) - -config X86_SPEEDSTEP_RELAXED_CAP_CHECK - bool "Relaxed speedstep capability checks" - depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH) +config X86_CPUFREQ_NFORCE2 + tristate "nVidia nForce2 FSB changing" + depends on CPU_FREQ && EXPERIMENTAL help - Don't perform all checks for a speedstep capable system which would - normally be done. Some ancient or strange systems, though speedstep - capable, don't always indicate that they are speedstep capable. This - option let's the probing code bypass some of those checks if the - parameter "relaxed_check=1" is passed to the module. + This adds the CPUFreq driver for FSB changing on nVidia nForce2 + plattforms. + + For details, take a look at . + + If in doubt, say N. config X86_LONGRUN tristate "Transmeta LongRun" depends on CPU_FREQ help - This adds the CPUFreq driver for Transmeta Crusoe processors which - support LongRun. + This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors + which support LongRun. For details, take a look at . @@ -209,4 +204,34 @@ config X86_LONGHAUL If in doubt, say N. +comment "shared options" + depends on CPU_FREQ + +config X86_ACPI_CPUFREQ_PROC_INTF + bool "/proc/acpi/processor/../performance interface (deprecated)" + depends on PROC_FS + depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI + help + This enables the deprecated /proc/acpi/processor/../performance + interface. While it is helpful for debugging, the generic, + cross-architecture cpufreq interfaces should be used. + + If in doubt, say N. + +config X86_SPEEDSTEP_LIB + tristate + depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) + default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) + +config X86_SPEEDSTEP_RELAXED_CAP_CHECK + bool "Relaxed speedstep capability checks" + depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH) + help + Don't perform all checks for a speedstep capable system which would + normally be done. Some ancient or strange systems, though speedstep + capable, don't always indicate that they are speedstep capable. This + option lets the probing code bypass some of those checks if the + parameter "relaxed_check=1" is passed to the module. + + endmenu diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile index 2dad46e11..a922e97ae 100644 --- a/arch/i386/kernel/cpu/cpufreq/Makefile +++ b/arch/i386/kernel/cpu/cpufreq/Makefile @@ -1,19 +1,14 @@ -obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o -obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o -obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o -obj-$(CONFIG_X86_LONGHAUL) += longhaul.o -obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o -obj-$(CONFIG_X86_LONGRUN) += longrun.o -obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o -obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o -obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o -obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o -obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o -obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o -obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o - -ifdef CONFIG_X86_ACPI_CPUFREQ - ifdef CONFIG_ACPI_DEBUG - EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT - endif -endif +obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o +obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o +obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +obj-$(CONFIG_X86_LONGHAUL) += longhaul.o +obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o +obj-$(CONFIG_X86_LONGRUN) += longrun.o +obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o +obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o +obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o +obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index fefaf45a0..3faa0ddb6 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -141,17 +141,7 @@ module_param (max_duration, int, 0444); #define POLICY_MIN_DIV 20 -/* DEBUG - * Define it if you want verbose debug output - */ - -#define SUSPMOD_DEBUG 1 - -#ifdef SUSPMOD_DEBUG -#define dprintk(msg...) printk(KERN_DEBUG "cpufreq:" msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "gx-suspmod", msg) /** * we can detect a core multipiler from dir0_lsb @@ -194,18 +184,18 @@ static __init struct pci_dev *gx_detect_chipset(void) /* check if CPU is a MediaGX or a Geode. */ if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) && (current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { - printk(KERN_INFO "gx-suspmod: error: no MediaGX/Geode processor found!\n"); + dprintk("error: no MediaGX/Geode processor found!\n"); return NULL; } /* detect which companion chip is used */ - while ((gx_pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) { + while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) { if ((pci_match_device (gx_chipset_tbl, gx_pci)) != NULL) { return gx_pci; } } - dprintk(KERN_INFO "gx-suspmod: error: no supported chipset found!\n"); + dprintk("error: no supported chipset found!\n"); return NULL; } @@ -297,6 +287,7 @@ static void gx_set_cpuspeed(unsigned int khz) case PCI_DEVICE_ID_CYRIX_5520: case PCI_DEVICE_ID_CYRIX_5510: suscfg = gx_params->pci_suscfg | SUSMOD; + break; default: local_irq_restore(flags); dprintk("fatal: try to set unknown chipset.\n"); @@ -498,6 +489,7 @@ static int __init cpufreq_gx_init(void) static void __exit cpufreq_gx_exit(void) { cpufreq_unregister_driver(&gx_suspmod_driver); + pci_dev_put(gx_params->cs55x0); kfree(gx_params); } diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 57c0377b4..ab0f9f5aa 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -5,14 +5,19 @@ * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by VIA. * - * VIA have currently 2 different versions of Longhaul. + * VIA have currently 3 different versions of Longhaul. * Version 1 (Longhaul) uses the BCR2 MSR at 0x1147. - * It is present only in Samuel 1, Samuel 2 and Ezra. - * Version 2 (Powersaver) uses the POWERSAVER MSR at 0x110a. - * It is present in Ezra-T, Nehemiah and above. - * In addition to scaling multiplier, it can also scale voltage. - * There is provision for scaling FSB too, but this doesn't work - * too well in practice. + * It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0. + * Version 2 of longhaul is the same as v1, but adds voltage scaling. + * Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C) + * voltage scaling support has currently been disabled in this driver + * until we have code that gets it right. + * Version 3 of longhaul got renamed to Powersaver and redesigned + * to use the POWERSAVER MSR at 0x110a. + * It is present in Ezra-T (C5M), Nehemiah (C5X) and above. + * It's pretty much the same feature wise to longhaul v2, though + * there is provision for scaling FSB too, but this doesn't work + * too well in practice so we don't even try to use this. * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* */ @@ -33,6 +38,17 @@ #define PFX "longhaul: " +#define TYPE_LONGHAUL_V1 1 +#define TYPE_LONGHAUL_V2 2 +#define TYPE_POWERSAVER 3 + +#define CPU_SAMUEL 1 +#define CPU_SAMUEL2 2 +#define CPU_EZRA 3 +#define CPU_EZRA_T 4 +#define CPU_NEHEMIAH 5 + +static int cpu_model; static unsigned int numscales=16, numvscales; static unsigned int fsb; static int minvid, maxvid; @@ -42,21 +58,9 @@ static int vrmrev; /* Module parameters */ static int dont_scale_voltage; -static int debug; - -static void dprintk(const char *fmt, ...) -{ - char s[256]; - va_list args; - if (debug == 0) - return; - va_start(args, fmt); - vsprintf(s, fmt, args); - printk(s); - va_end(args); -} +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) #define __hlt() __asm__ __volatile__("hlt": : :"memory") @@ -69,8 +73,25 @@ static unsigned int highest_speed, lowest_speed; /* kHz */ static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; +#ifdef CONFIG_CPU_FREQ_DEBUG +static char speedbuffer[8]; + +static char *print_speed(int speed) +{ + if (speed > 1000) { + if (speed%1000 == 0) + sprintf (speedbuffer, "%dGHz", speed/1000); + else + sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100); + } else + sprintf (speedbuffer, "%dMHz", speed); + + return speedbuffer; +} +#endif + -static unsigned int calc_speed(int mult, int fsb) +static unsigned int calc_speed(int mult) { int khz; khz = (mult/10)*fsb; @@ -87,7 +108,7 @@ static int longhaul_get_cpu_mult(void) rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; - if (longhaul_version==2 || longhaul_version==3) { + if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) { if (lo & (1<<27)) invalue+=16; } @@ -95,11 +116,45 @@ static int longhaul_get_cpu_mult(void) } +static void do_powersaver(union msr_longhaul *longhaul, + unsigned int clock_ratio_index) +{ + int version; + + switch (cpu_model) { + case CPU_EZRA_T: + version = 3; + break; + case CPU_NEHEMIAH: + version = 0xf; + break; + default: + return; + } + + rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); + longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf; + longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; + longhaul->bits.EnableSoftBusRatio = 1; + longhaul->bits.RevisionKey = 0; + local_irq_disable(); + wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); + local_irq_enable(); + __hlt(); + + rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); + longhaul->bits.EnableSoftBusRatio = 0; + longhaul->bits.RevisionKey = version; + local_irq_disable(); + wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); + local_irq_enable(); +} + /** * longhaul_set_cpu_frequency() * @clock_ratio_index : bitpattern of the new multiplier. * - * Sets a new clock ratio, and -if applicable- a new Front Side Bus + * Sets a new clock ratio. */ static void longhaul_setstate(unsigned int clock_ratio_index) @@ -108,79 +163,71 @@ static void longhaul_setstate(unsigned int clock_ratio_index) struct cpufreq_freqs freqs; union msr_longhaul longhaul; union msr_bcr2 bcr2; + static unsigned int old_ratio=-1; + + if (old_ratio == clock_ratio_index) + return; + old_ratio = clock_ratio_index; mult = clock_ratio[clock_ratio_index]; if (mult == -1) return; - speed = calc_speed (mult, fsb); + speed = calc_speed(mult); if ((speed > highest_speed) || (speed < lowest_speed)) return; - freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb); + freqs.old = calc_speed(longhaul_get_cpu_mult()); freqs.new = speed; freqs.cpu = 0; /* longhaul.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10); + dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", + fsb, mult/10, mult%10, print_speed(speed/1000)); switch (longhaul_version) { - case 1: + + /* + * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B]) + * Software controlled multipliers only. + * + * *NB* Until we get voltage scaling working v1 & v2 are the same code. + * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C] + */ + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: rdmsrl (MSR_VIA_BCR2, bcr2.val); /* Enable software clock multiplier */ bcr2.bits.ESOFTBF = 1; bcr2.bits.CLOCKMUL = clock_ratio_index; + local_irq_disable(); wrmsrl (MSR_VIA_BCR2, bcr2.val); + local_irq_enable(); __hlt(); /* Disable software clock multiplier */ rdmsrl (MSR_VIA_BCR2, bcr2.val); bcr2.bits.ESOFTBF = 0; + local_irq_disable(); wrmsrl (MSR_VIA_BCR2, bcr2.val); + local_irq_enable(); break; /* - * Powersaver. (Ezra-T [C5M], Nehemiah [C5N]) + * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N]) * We can scale voltage with this too, but that's currently * disabled until we come up with a decent 'match freq to voltage' * algorithm. - * We also need to do the voltage/freq setting in order depending - * on the direction of scaling (like we do in powernow-k7.c) - * Ezra-T was alleged to do FSB scaling too, but it never worked in practice. + * When we add voltage scaling, we will also need to do the + * voltage/freq setting in order depending on the direction + * of scaling (like we do in powernow-k7.c) + * Nehemiah can do FSB scaling too, but this has never been proven + * to work in practice. */ - case 2: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; - longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; - longhaul.bits.EnableSoftBusRatio = 1; - /* We must program the revision key only with values we - * know about, not blindly copy it from 0:3 */ - longhaul.bits.RevisionKey = 3; /* SoftVID & SoftBSEL */ - wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); - __hlt(); - - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.EnableSoftBusRatio = 0; - longhaul.bits.RevisionKey = 3; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); - break; - case 3: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; - longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; - longhaul.bits.EnableSoftBusRatio = 1; - - longhaul.bits.RevisionKey = 0x0; - - wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); - __hlt(); - - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.EnableSoftBusRatio = 0; - longhaul.bits.RevisionKey = 0xf; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); + case TYPE_POWERSAVER: + do_powersaver(&longhaul, clock_ratio_index); break; } @@ -230,7 +277,6 @@ static int guess_fsb(void) static int __init longhaul_get_ranges(void) { - struct cpuinfo_x86 *c = cpu_data; unsigned long invalue; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, @@ -242,58 +288,66 @@ static int __init longhaul_get_ranges(void) unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 }; switch (longhaul_version) { - case 1: + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: /* Ugh, Longhaul v1 didn't have the min/max MSRs. Assume min=3.0x & max = whatever we booted at. */ minmult = 30; maxmult = longhaul_get_cpu_mult(); rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; - if (c->x86_model==6) + if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2) fsb = eblcr_fsb_table_v1[invalue]; else fsb = guess_fsb(); break; - case 2: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - - invalue = longhaul.bits.MaxMHzBR; - if (longhaul.bits.MaxMHzBR4) - invalue += 16; - maxmult=multipliers[invalue]; - - invalue = longhaul.bits.MinMHzBR; - if (longhaul.bits.MinMHzBR4 == 1) - minmult = 30; - else - minmult = multipliers[invalue]; - - fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; - break; + case TYPE_POWERSAVER: + /* Ezra-T */ + if (cpu_model==CPU_EZRA_T) { + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + invalue = longhaul.bits.MaxMHzBR; + if (longhaul.bits.MaxMHzBR4) + invalue += 16; + maxmult=multipliers[invalue]; + + invalue = longhaul.bits.MinMHzBR; + if (longhaul.bits.MinMHzBR4 == 1) + minmult = 30; + else + minmult = multipliers[invalue]; + fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; + break; + } - case 3: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - - /* - * TODO: This code works, but raises a lot of questions. - * - Some Nehemiah's seem to have broken Min/MaxMHzBR's. - * We get around this by using a hardcoded multiplier of 5.0x - * for the minimimum speed, and the speed we booted up at for the max. - * This is done in longhaul_get_cpu_mult() by reading the EBLCR register. - * - According to some VIA documentation EBLCR is only - * in pre-Nehemiah C3s. How this still works is a mystery. - * We're possibly using something undocumented and unsupported, - * But it works, so we don't grumble. - */ - minmult=50; - maxmult=longhaul_get_cpu_mult(); - - fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; - break; + /* Nehemiah */ + if (cpu_model==CPU_NEHEMIAH) { + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + + /* + * TODO: This code works, but raises a lot of questions. + * - Some Nehemiah's seem to have broken Min/MaxMHzBR's. + * We get around this by using a hardcoded multiplier of 4.0x + * for the minimimum speed, and the speed we booted up at for the max. + * This is done in longhaul_get_cpu_mult() by reading the EBLCR register. + * - According to some VIA documentation EBLCR is only + * in pre-Nehemiah C3s. How this still works is a mystery. + * We're possibly using something undocumented and unsupported, + * But it works, so we don't grumble. + */ + minmult=40; + maxmult=longhaul_get_cpu_mult(); + + /* Starting with the 1.2GHz parts, theres a 200MHz bus. */ + if ((cpu_khz/1000) > 1200) + fsb = 200; + else + fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; + break; + } } - dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", + dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n", minmult/10, minmult%10, maxmult/10, maxmult%10); if (fsb == -1) { @@ -301,10 +355,11 @@ static int __init longhaul_get_ranges(void) return -EINVAL; } - highest_speed = calc_speed (maxmult, fsb); - lowest_speed = calc_speed (minmult,fsb); - dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", - fsb, lowest_speed/1000, highest_speed/1000); + highest_speed = calc_speed(maxmult); + lowest_speed = calc_speed(minmult); + dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb, + print_speed(lowest_speed/1000), + print_speed(highest_speed/1000)); if (lowest_speed == highest_speed) { printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n"); @@ -327,7 +382,7 @@ static int __init longhaul_get_ranges(void) continue; if (ratio > maxmult || ratio < minmult) continue; - longhaul_table[k].frequency = calc_speed (ratio, fsb); + longhaul_table[k].frequency = calc_speed(ratio); longhaul_table[k].index = j; k++; } @@ -370,11 +425,11 @@ static void __init longhaul_setup_voltagescaling(void) } if (vrmrev==0) { - dprintk (KERN_INFO PFX "VRM 8.5 : "); + dprintk ("VRM 8.5 \n"); memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; } else { - dprintk (KERN_INFO PFX "Mobile VRM : "); + dprintk ("Mobile VRM \n"); memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5; } @@ -403,8 +458,7 @@ static int longhaul_verify(struct cpufreq_policy *policy) static int longhaul_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int target_freq, unsigned int relation) { unsigned int table_index = 0; unsigned int new_clock_ratio = 0; @@ -419,13 +473,15 @@ static int longhaul_target(struct cpufreq_policy *policy, return 0; } + static unsigned int longhaul_get(unsigned int cpu) { if (cpu) return 0; - return (calc_speed (longhaul_get_cpu_mult(), fsb)); + return calc_speed(longhaul_get_cpu_mult()); } + static int __init longhaul_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; @@ -434,26 +490,31 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) switch (c->x86_model) { case 6: + cpu_model = CPU_SAMUEL; cpuname = "C3 'Samuel' [C5A]"; - longhaul_version=1; + longhaul_version = TYPE_LONGHAUL_V1; memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); break; - case 7: /* C5B / C5C */ - longhaul_version=1; + case 7: + longhaul_version = TYPE_LONGHAUL_V1; switch (c->x86_mask) { case 0: + cpu_model = CPU_SAMUEL2; cpuname = "C3 'Samuel 2' [C5B]"; /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */ memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); break; case 1 ... 15: - if (c->x86_mask < 8) + if (c->x86_mask < 8) { + cpu_model = CPU_SAMUEL2; cpuname = "C3 'Samuel 2' [C5B]"; - else + } else { + cpu_model = CPU_EZRA; cpuname = "C3 'Ezra' [C5C]"; + } memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); break; @@ -461,15 +522,17 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) break; case 8: + cpu_model = CPU_EZRA_T; cpuname = "C3 'Ezra-T' [C5M]"; - longhaul_version=2; + longhaul_version = TYPE_POWERSAVER; numscales=32; memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio)); memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr)); break; case 9: - longhaul_version=3; + cpu_model = CPU_NEHEMIAH; + longhaul_version = TYPE_POWERSAVER; numscales=32; switch (c->x86_mask) { case 0 ... 1: @@ -495,19 +558,28 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) break; } - printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", - cpuname, longhaul_version); + printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname); + switch (longhaul_version) { + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: + printk ("Longhaul v%d supported.\n", longhaul_version); + break; + case TYPE_POWERSAVER: + printk ("Powersaver supported.\n"); + break; + }; ret = longhaul_get_ranges(); if (ret != 0) return ret; - if ((longhaul_version==2) && (dont_scale_voltage==0)) + if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && + (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); + policy->cur = calc_speed(longhaul_get_cpu_mult()); ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); if (ret) @@ -540,6 +612,7 @@ static struct cpufreq_driver longhaul_driver = { .attr = longhaul_attr, }; + static int __init longhaul_init(void) { struct cpuinfo_x86 *c = cpu_data; @@ -557,16 +630,17 @@ static int __init longhaul_init(void) return -ENODEV; } + static void __exit longhaul_exit(void) { int i=0; - unsigned int new_clock_ratio; - - while (clock_ratio[i] != maxmult) - i++; - new_clock_ratio = longhaul_table[i].index & 0xFF; - longhaul_setstate(new_clock_ratio); + for (i=0; i < numscales; i++) { + if (clock_ratio[i] == maxmult) { + longhaul_setstate(i); + break; + } + } cpufreq_unregister_driver(&longhaul_driver); kfree(longhaul_table); @@ -575,9 +649,6 @@ static void __exit longhaul_exit(void) module_param (dont_scale_voltage, int, 0644); MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); -module_param (debug, int, 0644); -MODULE_PARM_DESC(debug, "Dump debugging information."); - MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); MODULE_LICENSE ("GPL"); diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c index c04c99bba..e3868de4d 100644 --- a/arch/i386/kernel/cpu/cpufreq/longrun.c +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c @@ -7,7 +7,7 @@ */ #include -#include +#include #include #include #include @@ -16,10 +16,12 @@ #include #include +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longrun", msg) + static struct cpufreq_driver longrun_driver; /** - * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz + * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz * values into per cent values. In TMTA microcode, the following is valid: * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq) */ @@ -38,22 +40,24 @@ static void __init longrun_get_policy(struct cpufreq_policy *policy) u32 msr_lo, msr_hi; rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi); + dprintk("longrun flags are %x - %x\n", msr_lo, msr_hi); if (msr_lo & 0x01) policy->policy = CPUFREQ_POLICY_PERFORMANCE; else policy->policy = CPUFREQ_POLICY_POWERSAVE; - + rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi); + dprintk("longrun ctrl is %x - %x\n", msr_lo, msr_hi); msr_lo &= 0x0000007F; msr_hi &= 0x0000007F; - + if ( longrun_high_freq <= longrun_low_freq ) { /* Assume degenerate Longrun table */ policy->min = policy->max = longrun_high_freq; } else { - policy->min = longrun_low_freq + msr_lo * + policy->min = longrun_low_freq + msr_lo * ((longrun_high_freq - longrun_low_freq) / 100); - policy->max = longrun_low_freq + msr_hi * + policy->max = longrun_low_freq + msr_hi * ((longrun_high_freq - longrun_low_freq) / 100); } policy->cpu = 0; @@ -79,9 +83,9 @@ static int longrun_set_policy(struct cpufreq_policy *policy) /* Assume degenerate Longrun table */ pctg_lo = pctg_hi = 100; } else { - pctg_lo = (policy->min - longrun_low_freq) / + pctg_lo = (policy->min - longrun_low_freq) / ((longrun_high_freq - longrun_low_freq) / 100); - pctg_hi = (policy->max - longrun_low_freq) / + pctg_hi = (policy->max - longrun_low_freq) / ((longrun_high_freq - longrun_low_freq) / 100); } @@ -118,7 +122,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy) * longrun_verify_poliy - verifies a new CPUFreq policy * @policy: the policy to verify * - * Validates a new CPUFreq policy. This function has to be called with + * Validates a new CPUFreq policy. This function has to be called with * cpufreq_driver locked. */ static int longrun_verify_policy(struct cpufreq_policy *policy) @@ -127,8 +131,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy) return -EINVAL; policy->cpu = 0; - cpufreq_verify_within_limits(policy, - policy->cpuinfo.min_freq, + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && @@ -146,6 +150,7 @@ static unsigned int longrun_get(unsigned int cpu) return 0; cpuid(0x80860007, &eax, &ebx, &ecx, &edx); + dprintk("cpuid eax is %u\n", eax); return (eax * 1000); } @@ -160,7 +165,7 @@ static unsigned int longrun_get(unsigned int cpu) * TMTA rules: * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq) */ -static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, +static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, unsigned int *high_freq) { u32 msr_lo, msr_hi; @@ -174,9 +179,9 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, if (cpu_has(c, X86_FEATURE_LRTI)) { /* if the LongRun Table Interface is present, the - * detection is a bit easier: + * detection is a bit easier: * For minimum frequency, read out the maximum - * level (msr_hi), write that into "currently + * level (msr_hi), write that into "currently * selected level", and read out the frequency. * For maximum frequency, read out level zero. */ @@ -191,6 +196,8 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, rdmsr(MSR_TMTA_LRTI_VOLT_MHZ, msr_lo, msr_hi); *high_freq = msr_lo * 1000; /* to kHz */ + dprintk("longrun table interface told %u - %u kHz\n", *low_freq, *high_freq); + if (*low_freq > *high_freq) *low_freq = *high_freq; return 0; @@ -199,6 +206,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, /* set the upper border to the value determined during TSC init */ *high_freq = (cpu_khz / 1000); *high_freq = *high_freq * 1000; + dprintk("high frequency is %u kHz\n", *high_freq); /* get current borders */ rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi); @@ -223,8 +231,9 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, cpuid(0x80860007, &eax, &ebx, &ecx, &edx); /* restore values */ - wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi); + wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi); } + dprintk("percentage is %u %%, freq is %u MHz\n", ecx, eax); /* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq) * eqals @@ -237,9 +246,11 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, if ((ecx > 95) || (ecx == 0) || (eax < ebx)) return -EIO; - edx = (eax - ebx) / (100 - ecx); + edx = (eax - ebx) / (100 - ecx); *low_freq = edx * 1000; /* back to kHz */ + dprintk("low frequency is %u kHz\n", *low_freq); + if (*low_freq > *high_freq) *low_freq = *high_freq; @@ -249,7 +260,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, static int __init longrun_cpu_init(struct cpufreq_policy *policy) { - int result = 0; + int result = 0; /* capability check */ if (policy->cpu != 0) @@ -265,15 +276,15 @@ static int __init longrun_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.max_freq = longrun_high_freq; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; longrun_get_policy(policy); - + return 0; } static struct cpufreq_driver longrun_driver = { .flags = CPUFREQ_CONST_LOOPS, - .verify = longrun_verify_policy, - .setpolicy = longrun_set_policy, + .verify = longrun_verify_policy, + .setpolicy = longrun_set_policy, .get = longrun_get, .init = longrun_cpu_init, .name = "longrun", @@ -290,7 +301,7 @@ static int __init longrun_init(void) { struct cpuinfo_x86 *c = cpu_data; - if (c->x86_vendor != X86_VENDOR_TRANSMETA || + if (c->x86_vendor != X86_VENDOR_TRANSMETA || !cpu_has(c, X86_FEATURE_LONGRUN)) return -ENODEV; @@ -308,7 +319,7 @@ static void __exit longrun_exit(void) MODULE_AUTHOR ("Dominik Brodowski "); -MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe processors."); +MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe and Efficeon processors."); MODULE_LICENSE ("GPL"); module_init(longrun_init); diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index fa01a95bb..18596a15b 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -36,6 +36,7 @@ #include "speedstep-lib.h" #define PFX "p4-clockmod: " +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "p4-clockmod", msg) /* * Duty Cycle (3bits), note DC_DISABLE is not specified in @@ -62,20 +63,20 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) return -EINVAL; rdmsr(MSR_IA32_THERM_STATUS, l, h); -#if 0 + if (l & 0x01) - printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); -#endif + dprintk("CPU#%d currently thermal throttled\n", cpu); + if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT)) newstate = DC_38PT; rdmsr(MSR_IA32_THERM_CONTROL, l, h); if (newstate == DC_DISABLE) { - /* printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); */ + dprintk("CPU#%d disabling modulation\n", cpu); wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { - /* printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", - cpu, ((125 * newstate) / 10)); */ + dprintk("CPU#%d setting duty cycle to %d%%\n", + cpu, ((125 * newstate) / 10)); /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle @@ -110,7 +111,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, { unsigned int newstate = DC_RESV; struct cpufreq_freqs freqs; - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; int i; if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate)) @@ -122,18 +123,8 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, if (freqs.new == freqs.old) return 0; - /* switch to physical CPU where state is to be changed*/ - cpus_allowed = current->cpus_allowed; - - /* only run on CPU to be set, or on its sibling */ -#ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); -#endif - /* notifiers */ - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } @@ -141,7 +132,9 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software * Developer's Manual, Volume 3 */ - for_each_cpu_mask(i, affected_cpu_map) { + cpus_allowed = current->cpus_allowed; + + for_each_cpu_mask(i, policy->cpus) { cpumask_t this_cpu = cpumask_of_cpu(i); set_cpus_allowed(current, this_cpu); @@ -152,7 +145,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy, set_cpus_allowed(current, cpus_allowed); /* notifiers */ - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -184,7 +177,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) "The speedstep_centrino module offers voltage scaling" " in addition of frequency scaling. You should use " "that instead of p4-clockmod, if possible.\n"); - /* on P-4s, the TSC runs with constant frequency independent wether + /* on P-4s, the TSC runs with constant frequency independent whether * throttling is active or not. */ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); @@ -195,7 +188,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) return 0; } - /* on P-4s, the TSC runs with constant frequency independent wether + /* on P-4s, the TSC runs with constant frequency independent whether * throttling is active or not. */ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; @@ -219,6 +212,10 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) int cpuid = 0; unsigned int i; +#ifdef CONFIG_SMP + policy->cpus = cpu_sibling_map[policy->cpu]; +#endif + /* Errata workaround */ cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask; switch (cpuid) { @@ -227,6 +224,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) case 0x0f11: case 0x0f12: has_N44_O17_errata[policy->cpu] = 1; + dprintk("has errata -- disabling low frequencies\n"); } /* get max frequency */ @@ -260,14 +258,13 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) static unsigned int cpufreq_p4_get(unsigned int cpu) { - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; u32 l, h; cpus_allowed = current->cpus_allowed; - affected_cpu_map = cpumask_of_cpu(cpu); - set_cpus_allowed(current, affected_cpu_map); - BUG_ON(!cpu_isset(smp_processor_id(), affected_cpu_map)); + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + BUG_ON(smp_processor_id() != cpu); rdmsr(MSR_IA32_THERM_CONTROL, l, h); @@ -305,6 +302,7 @@ static struct cpufreq_driver p4clockmod_driver = { static int __init cpufreq_p4_init(void) { struct cpuinfo_x86 *c = cpu_data; + int ret; /* * THERM_CONTROL is architectural for IA32 now, so @@ -317,9 +315,11 @@ static int __init cpufreq_p4_init(void) !test_bit(X86_FEATURE_ACC, c->x86_capability)) return -ENODEV; - printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); + ret = cpufreq_register_driver(&p4clockmod_driver); + if (!ret) + printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n"); - return cpufreq_register_driver(&p4clockmod_driver); + return (ret); } @@ -335,4 +335,3 @@ MODULE_LICENSE ("GPL"); late_initcall(cpufreq_p4_init); module_exit(cpufreq_p4_exit); - diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 18d30ab9a..f88227760 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -6,8 +6,6 @@ * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. * - * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* - * * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt. * - We cli/sti on stepping A0 CPUs around the FID/VID transition. * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect. @@ -29,21 +27,13 @@ #include #include -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K7_ACPI #include #include #endif #include "powernow-k7.h" -#define DEBUG - -#ifdef DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif - #define PFX "powernow: " @@ -64,7 +54,7 @@ struct pst_s { u8 numpstates; }; -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K7_ACPI union powernow_acpi_control_t { struct { unsigned long fid:5, @@ -76,6 +66,7 @@ union powernow_acpi_control_t { }; #endif +#ifdef CONFIG_CPU_FREQ_DEBUG /* divide by 1000 to get VID. */ static int mobile_vid_table[32] = { 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, @@ -83,6 +74,7 @@ static int mobile_vid_table[32] = { 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, 1075, 1050, 1024, 1000, 975, 950, 925, 0, }; +#endif /* divide by 10 to get FID. */ static int fid_codes[32] = { @@ -109,6 +101,8 @@ static unsigned int fsb; static unsigned int latency; static char have_a0; +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k7", msg) + static int check_fsb(unsigned int fsbspeed) { int delta; @@ -190,15 +184,12 @@ static int get_ranges (unsigned char *pst) speed = powernow_table[j].frequency; if ((fid_codes[fid] % 10)==5) { -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K7_ACPI if (have_a0 == 1) powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID; #endif } - dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid, - fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000); - if (speed < minimum_speed) minimum_speed = speed; if (speed > maximum_speed) @@ -206,8 +197,12 @@ static int get_ranges (unsigned char *pst) vid = *pst++; powernow_table[j].index |= (vid << 8); /* upper 8 bits */ - dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000, - mobile_vid_table[vid]%1000); + + dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " + "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, + fid_codes[fid] % 10, speed/1000, vid, + mobile_vid_table[vid]/1000, + mobile_vid_table[vid]%1000); } powernow_table[number_scales].frequency = CPUFREQ_TABLE_END; powernow_table[number_scales].index = 0; @@ -285,7 +280,7 @@ static void change_speed (unsigned int index) change_VID(vid); change_FID(fid); } - + if (have_a0 == 1) local_irq_enable(); @@ -294,9 +289,9 @@ static void change_speed (unsigned int index) } -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K7_ACPI -struct acpi_processor_performance *acpi_processor_perf; +static struct acpi_processor_performance *acpi_processor_perf; static int powernow_acpi_init(void) { @@ -355,7 +350,7 @@ static int powernow_acpi_init(void) unsigned int speed; pc.val = (unsigned long) acpi_processor_perf->states[i].control; - dprintk (KERN_INFO PFX "acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", + dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", i, (u32) acpi_processor_perf->states[i].core_frequency, (u32) acpi_processor_perf->states[i].power, @@ -377,10 +372,11 @@ static int powernow_acpi_init(void) powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; } - dprintk (KERN_INFO PFX " FID: 0x%x (%d.%dx [%dMHz])\t", fid, - fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000); - dprintk ("VID: 0x%x (%d.%03dV)\n", vid, mobile_vid_table[vid]/1000, - mobile_vid_table[vid]%1000); + dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " + "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, + fid_codes[fid] % 10, speed/1000, vid, + mobile_vid_table[vid]/1000, + mobile_vid_table[vid]%1000); if (latency < pc.bits.sgtc) latency = pc.bits.sgtc; @@ -394,6 +390,9 @@ static int powernow_acpi_init(void) powernow_table[i].frequency = CPUFREQ_TABLE_END; powernow_table[i].index = 0; + /* notify BIOS that we exist */ + acpi_processor_notify_smm(THIS_MODULE); + return 0; err2: @@ -430,21 +429,20 @@ static int powernow_decode_bios (int maxfid, int startvid) p = phys_to_virt(i); if (memcmp(p, "AMDK7PNOW!", 10) == 0){ - dprintk (KERN_INFO PFX "Found PSB header at %p\n", p); + dprintk ("Found PSB header at %p\n", p); psb = (struct psb_s *) p; - dprintk (KERN_INFO PFX "Table version: 0x%x\n", psb->tableversion); + dprintk ("Table version: 0x%x\n", psb->tableversion); if (psb->tableversion != 0x12) { printk (KERN_INFO PFX "Sorry, only v1.2 tables supported right now\n"); return -ENODEV; } - dprintk (KERN_INFO PFX "Flags: 0x%x (", psb->flags); + dprintk ("Flags: 0x%x\n", psb->flags); if ((psb->flags & 1)==0) { - dprintk ("Mobile"); + dprintk ("Mobile voltage regulator\n"); } else { - dprintk ("Desktop"); + dprintk ("Desktop voltage regulator\n"); } - dprintk (" voltage regulator)\n"); latency = psb->settlingtime; if (latency < 100) { @@ -452,8 +450,8 @@ static int powernow_decode_bios (int maxfid, int startvid) "Should be at least 100. Correcting.\n", latency); latency = 100; } - dprintk (KERN_INFO PFX "Settling Time: %d microseconds.\n", psb->settlingtime); - dprintk (KERN_INFO PFX "Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst); + dprintk ("Settling Time: %d microseconds.\n", psb->settlingtime); + dprintk ("Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst); p += sizeof (struct psb_s); @@ -466,11 +464,9 @@ static int powernow_decode_bios (int maxfid, int startvid) if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) && (maxfid==pst->maxfid) && (startvid==pst->startvid)) { - dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst); - dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid); - dprintk ("fsb: %d\t", pst->fsbspeed); - dprintk ("maxFID: 0x%x\t", pst->maxfid); - dprintk ("startvid: 0x%x\n", pst->startvid); + dprintk ("PST:%d (@%p)\n", i, pst); + dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n", + pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid); ret = get_ranges ((char *) pst + sizeof (struct pst_s)); return ret; @@ -591,14 +587,14 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val); /* A K7 with powernow technology is set to max frequency by BIOS */ - fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID]; + fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID]; if (!fsb) { printk(KERN_WARNING PFX "can not determine bus frequency\n"); return -EINVAL; } - dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); + dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000); - if (dmi_check_system(powernow_dmi_table) || acpi_force) { + if (dmi_check_system(powernow_dmi_table) || acpi_force) { printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n"); result = powernow_acpi_init(); } else { @@ -628,7 +624,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = 20 * latency / fsb; + policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); policy->cur = powernow_get(0); @@ -648,14 +644,14 @@ static struct freq_attr* powernow_table_attr[] = { }; static struct cpufreq_driver powernow_driver = { - .verify = powernow_verify, - .target = powernow_target, - .get = powernow_get, - .init = powernow_cpu_init, - .exit = powernow_cpu_exit, - .name = "powernow-k7", - .owner = THIS_MODULE, - .attr = powernow_table_attr, + .verify = powernow_verify, + .target = powernow_target, + .get = powernow_get, + .init = powernow_cpu_init, + .exit = powernow_cpu_exit, + .name = "powernow-k7", + .owner = THIS_MODULE, + .attr = powernow_table_attr, }; static int __init powernow_init (void) @@ -668,7 +664,7 @@ static int __init powernow_init (void) static void __exit powernow_exit (void) { -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K7_ACPI if (acpi_processor_perf) { acpi_processor_unregister_performance(acpi_processor_perf, 0); kfree(acpi_processor_perf); @@ -680,7 +676,7 @@ static void __exit powernow_exit (void) } module_param(acpi_force, int, 0444); -MODULE_PARM_DESC(acpi_force, "Force ACPI to be used"); +MODULE_PARM_DESC(acpi_force, "Force ACPI to be used."); MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors."); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 05ed9025e..9b6ec758c 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -32,14 +32,14 @@ #include #include -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K8_ACPI #include #include #endif #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.00.09b" +#define VERSION "version 1.00.09e" #include "powernow-k8.h" /* serialize freq changes */ @@ -136,7 +136,7 @@ static void fidvid_msr_init(void) fid = lo & MSR_S_LO_CURRENT_FID; lo = fid | (vid << MSR_C_LO_VID_SHIFT); hi = MSR_C_HI_STP_GNT_BENIGN; - dprintk(PFX "cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi); + dprintk("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi); wrmsr(MSR_FIDVID_CTL, lo, hi); } @@ -154,7 +154,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid) lo = fid | (data->currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID; - dprintk(KERN_DEBUG PFX "writing fid 0x%x, lo 0x%x, hi 0x%x\n", + dprintk("writing fid 0x%x, lo 0x%x, hi 0x%x\n", fid, lo, data->plllock * PLL_LOCK_CONVERSION); wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION); @@ -192,7 +192,7 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid) lo = data->currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID; - dprintk(KERN_DEBUG PFX "writing vid 0x%x, lo 0x%x, hi 0x%x\n", + dprintk("writing vid 0x%x, lo 0x%x, hi 0x%x\n", vid, lo, STOP_GRANT_5NS); wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); @@ -255,7 +255,7 @@ static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 req return 1; } - dprintk(KERN_INFO PFX "transitioned (cpu%d): new fid 0x%x, vid 0x%x\n", + dprintk("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n", smp_processor_id(), data->currfid, data->currvid); return 0; @@ -267,13 +267,12 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid u32 rvosteps = data->rvo; u32 savefid = data->currfid; - dprintk(KERN_DEBUG PFX - "ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", + dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n", smp_processor_id(), data->currfid, data->currvid, reqvid, data->rvo); while (data->currvid > reqvid) { - dprintk(KERN_DEBUG PFX "ph1: curr 0x%x, req vid 0x%x\n", + dprintk("ph1: curr 0x%x, req vid 0x%x\n", data->currvid, reqvid); if (decrease_vid_code_by_step(data, reqvid, data->vidmvs)) return 1; @@ -283,8 +282,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid if (data->currvid == 0) { rvosteps = 0; } else { - dprintk(KERN_DEBUG PFX - "ph1: changing vid for rvo, req 0x%x\n", + dprintk("ph1: changing vid for rvo, req 0x%x\n", data->currvid - 1); if (decrease_vid_code_by_step(data, data->currvid - 1, 1)) return 1; @@ -300,7 +298,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid return 1; } - dprintk(KERN_DEBUG PFX "ph1 complete, currfid 0x%x, currvid 0x%x\n", + dprintk("ph1 complete, currfid 0x%x, currvid 0x%x\n", data->currfid, data->currvid); return 0; @@ -325,8 +323,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) return 0; } - dprintk(KERN_DEBUG PFX - "ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n", + dprintk("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n", smp_processor_id(), data->currfid, data->currvid, reqfid); @@ -376,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) return 1; } - dprintk(KERN_DEBUG PFX "ph2 complete, currfid 0x%x, currvid 0x%x\n", + dprintk("ph2 complete, currfid 0x%x, currvid 0x%x\n", data->currfid, data->currvid); return 0; @@ -388,7 +385,7 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi u32 savefid = data->currfid; u32 savereqvid = reqvid; - dprintk(KERN_DEBUG PFX "ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n", + dprintk("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n", smp_processor_id(), data->currfid, data->currvid); @@ -415,17 +412,17 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi return 1; if (savereqvid != data->currvid) { - dprintk(KERN_ERR PFX "ph3 failed, currvid 0x%x\n", data->currvid); + dprintk("ph3 failed, currvid 0x%x\n", data->currvid); return 1; } if (savefid != data->currfid) { - dprintk(KERN_ERR PFX "ph3 failed, currfid changed 0x%x\n", + dprintk("ph3 failed, currfid changed 0x%x\n", data->currfid); return 1; } - dprintk(KERN_DEBUG PFX "ph3 complete, currfid 0x%x, currvid 0x%x\n", + dprintk("ph3 complete, currfid 0x%x, currvid 0x%x\n", data->currfid, data->currvid); return 0; @@ -577,7 +574,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, return -EIO; } - dprintk(KERN_INFO PFX "cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); + dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); data->powernow_table = powernow_table; print_basics(data); @@ -585,7 +582,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid)) return 0; - dprintk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n"); + dprintk("currfid/vid do not match PST, ignoring\n"); return 0; } @@ -596,6 +593,8 @@ static int find_psb_table(struct powernow_k8_data *data) unsigned int i; u32 mvs; u8 maxvid; + u32 cpst = 0; + u32 thiscpuid; for (i = 0xc0000; i < 0xffff0; i += 0x10) { /* Scan BIOS looking for the signature. */ @@ -605,48 +604,55 @@ static int find_psb_table(struct powernow_k8_data *data) if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0) continue; - dprintk(KERN_DEBUG PFX "found PSB header at 0x%p\n", psb); + dprintk("found PSB header at 0x%p\n", psb); - dprintk(KERN_DEBUG PFX "table vers: 0x%x\n", psb->tableversion); + dprintk("table vers: 0x%x\n", psb->tableversion); if (psb->tableversion != PSB_VERSION_1_4) { printk(KERN_INFO BFX "PSB table is not v1.4\n"); return -ENODEV; } - dprintk(KERN_DEBUG PFX "flags: 0x%x\n", psb->flags1); + dprintk("flags: 0x%x\n", psb->flags1); if (psb->flags1) { printk(KERN_ERR BFX "unknown flags\n"); return -ENODEV; } data->vstable = psb->voltagestabilizationtime; - dprintk(KERN_INFO PFX "voltage stabilization time: %d(*20us)\n", data->vstable); + dprintk("voltage stabilization time: %d(*20us)\n", data->vstable); - dprintk(KERN_DEBUG PFX "flags2: 0x%x\n", psb->flags2); + dprintk("flags2: 0x%x\n", psb->flags2); data->rvo = psb->flags2 & 3; data->irt = ((psb->flags2) >> 2) & 3; mvs = ((psb->flags2) >> 4) & 3; data->vidmvs = 1 << mvs; data->batps = ((psb->flags2) >> 6) & 3; - dprintk(KERN_INFO PFX "ramp voltage offset: %d\n", data->rvo); - dprintk(KERN_INFO PFX "isochronous relief time: %d\n", data->irt); - dprintk(KERN_INFO PFX "maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs); + dprintk("ramp voltage offset: %d\n", data->rvo); + dprintk("isochronous relief time: %d\n", data->irt); + dprintk("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs); - dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst); - if (psb->numpst != 1) { + dprintk("numpst: 0x%x\n", psb->numpst); + cpst = psb->numpst; + if ((psb->cpuid == 0x00000fc0) || (psb->cpuid == 0x00000fe0) ){ + thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); + if ((thiscpuid == 0x00000fc0) || (thiscpuid == 0x00000fe0) ) { + cpst = 1; + } + } + if (cpst != 1) { printk(KERN_ERR BFX "numpst must be 1\n"); return -ENODEV; } data->plllock = psb->plllocktime; - dprintk(KERN_INFO PFX "plllocktime: 0x%x (units 1us)\n", psb->plllocktime); - dprintk(KERN_INFO PFX "maxfid: 0x%x\n", psb->maxfid); - dprintk(KERN_INFO PFX "maxvid: 0x%x\n", psb->maxvid); + dprintk("plllocktime: 0x%x (units 1us)\n", psb->plllocktime); + dprintk("maxfid: 0x%x\n", psb->maxfid); + dprintk("maxvid: 0x%x\n", psb->maxvid); maxvid = psb->maxvid; data->numps = psb->numpstates; - dprintk(KERN_INFO PFX "numpstates: 0x%x\n", data->numps); + dprintk("numpstates: 0x%x\n", data->numps); return fill_powernow_table(data, (struct pst_s *)(psb+1), maxvid); } /* @@ -664,7 +670,7 @@ static int find_psb_table(struct powernow_k8_data *data) return -ENODEV; } -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K8_ACPI static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { if (!data->acpi_data.state_count) @@ -684,19 +690,21 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) struct cpufreq_frequency_table *powernow_table; if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { - dprintk(KERN_DEBUG PFX "register performance failed\n"); + dprintk("register performance failed\n"); return -EIO; } /* verify the data contained in the ACPI structures */ if (data->acpi_data.state_count <= 1) { - dprintk(KERN_DEBUG PFX "No ACPI P-States\n"); + dprintk("No ACPI P-States\n"); goto err_out; } if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { - dprintk(KERN_DEBUG PFX "Invalid control/status registers\n"); + dprintk("Invalid control/status registers (%x - %x)\n", + data->acpi_data.control_register.space_id, + data->acpi_data.status_register.space_id); goto err_out; } @@ -704,7 +712,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1)), GFP_KERNEL); if (!powernow_table) { - dprintk(KERN_ERR PFX "powernow_table memory alloc failure\n"); + dprintk("powernow_table memory alloc failure\n"); goto err_out; } @@ -712,7 +720,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) u32 fid = data->acpi_data.states[i].control & FID_MASK; u32 vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; - dprintk(KERN_INFO PFX " %d : fid 0x%x, vid 0x%x\n", i, fid, vid); + dprintk(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); powernow_table[i].index = fid; /* lower 8 bits */ powernow_table[i].index |= (vid << 8); /* upper 8 bits */ @@ -721,14 +729,14 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* verify frequency is OK */ if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) || (powernow_table[i].frequency < (MIN_FREQ * 1000))) { - dprintk(KERN_INFO PFX "invalid freq %u kHz, ignoring\n", powernow_table[i].frequency); + dprintk("invalid freq %u kHz, ignoring\n", powernow_table[i].frequency); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; } /* verify voltage is OK - BIOSs are using "off" to indicate invalid */ if (vid == 0x1f) { - dprintk(KERN_INFO PFX "invalid vid %u, ignoring\n", vid); + dprintk("invalid vid %u, ignoring\n", vid); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; } @@ -744,7 +752,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) goto err_out_mem; } - dprintk(KERN_INFO PFX "double low frequency table entry, ignoring it.\n"); + dprintk("double low frequency table entry, ignoring it.\n"); powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; continue; } else @@ -768,6 +776,10 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) data->numps = data->acpi_data.state_count; print_basics(data); powernow_k8_acpi_pst_values(data, 0); + + /* notify BIOS that we exist */ + acpi_processor_notify_smm(THIS_MODULE); + return 0; err_out_mem: @@ -802,8 +814,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde int res; struct cpufreq_freqs freqs; - dprintk(KERN_DEBUG PFX "cpu %d transition to index %u\n", - smp_processor_id(), index ); + dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); /* fid are the lower 8 bits of the index we stored into * the cpufreq frequency table in find_psb_table, vid are @@ -813,28 +824,25 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde fid = data->powernow_table[index].index & 0xFF; vid = (data->powernow_table[index].index & 0xFF00) >> 8; - dprintk(KERN_DEBUG PFX "table matched fid 0x%x, giving vid 0x%x\n", - fid, vid); + dprintk("table matched fid 0x%x, giving vid 0x%x\n", fid, vid); if (query_current_values_with_pending_wait(data)) return 1; if ((data->currvid == vid) && (data->currfid == fid)) { - dprintk(KERN_DEBUG PFX - "target matches current values (fid 0x%x, vid 0x%x)\n", + dprintk("target matches current values (fid 0x%x, vid 0x%x)\n", fid, vid); return 0; } if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { - printk(KERN_ERR PFX - "ignoring illegal change in lo freq table-%x to 0x%x\n", + printk("ignoring illegal change in lo freq table-%x to 0x%x\n", data->currfid, fid); return 1; } - dprintk(KERN_DEBUG PFX "cpu %d, changing to fid 0x%x, vid 0x%x\n", - smp_processor_id(), fid, vid); + dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n", + smp_processor_id(), fid, vid); freqs.cpu = data->cpu; @@ -877,7 +885,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi goto err_out; } - dprintk(KERN_DEBUG PFX "targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", + dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) { @@ -885,7 +893,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi goto err_out; } - dprintk(KERN_DEBUG PFX "targ: curr fid 0x%x, vid 0x%x\n", + dprintk("targ: curr fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); if ((checkvid != data->currvid) || (checkfid != data->currfid)) { @@ -948,13 +956,13 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) * an UP version, and is deprecated by AMD. */ - if (pol->cpu != 0) { - printk(KERN_ERR PFX "init not cpu 0\n"); + if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { + printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n"); kfree(data); return -ENODEV; } - if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { - printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n"); + if (pol->cpu != 0) { + printk(KERN_ERR PFX "init not cpu 0\n"); kfree(data); return -ENODEV; } @@ -997,7 +1005,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) + (3 * (1 << data->irt) * 10)) * 1000; pol->cur = find_khz_freq_from_fid(data->currfid); - dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur); + dprintk("policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) { @@ -1009,7 +1017,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); - printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n", + printk("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); powernow_data[pol->cpu] = data; @@ -1024,7 +1032,7 @@ err_out: return -ENODEV; } -static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol) +static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol) { struct powernow_k8_data *data = powernow_data[pol->cpu]; @@ -1076,7 +1084,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = { .verify = powernowk8_verify, .target = powernowk8_target, .init = powernowk8_cpu_init, - .exit = powernowk8_cpu_exit, + .exit = __devexit_p(powernowk8_cpu_exit), .get = powernowk8_get, .name = "powernow-k8", .owner = THIS_MODULE, @@ -1107,7 +1115,7 @@ static int __init powernowk8_init(void) /* driver entry point for term */ static void __exit powernowk8_exit(void) { - dprintk(KERN_INFO PFX "exit\n"); + dprintk("exit\n"); cpufreq_unregister_driver(&cpufreq_amd64_driver); } diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 500f28d27..72fdcbf1f 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -29,7 +29,7 @@ struct powernow_k8_data { * frequency is in kHz */ struct cpufreq_frequency_table *powernow_table; -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) +#ifdef CONFIG_X86_POWERNOW_K8_ACPI /* the acpi table needs to be kept. it's only available if ACPI was * used to determine valid frequency/vid/fid states */ struct acpi_processor_performance acpi_data; @@ -168,11 +168,7 @@ struct pst_s { u8 vid; }; -#ifdef DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg) static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid); static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index ea9173812..07955b744 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -10,7 +10,7 @@ * Copyright (C) 2003 Jeremy Fitzhardinge * * WARNING WARNING WARNING - * + * * This driver manipulates the PERF_CTL MSR, which is only somewhat * documented. While it seems to work on my laptop, it has not been * tested anywhere else, and it may not work for you, do strange @@ -23,6 +23,11 @@ #include #include +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI +#include +#include +#endif + #include #include #include @@ -30,35 +35,30 @@ #define PFX "speedstep-centrino: " #define MAINTAINER "Jeremy Fitzhardinge " -/*#define CENTRINO_DEBUG*/ +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) -#ifdef CENTRINO_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif struct cpu_id { __u8 x86; /* CPU family */ - __u8 x86_vendor; /* CPU vendor */ __u8 x86_model; /* model */ __u8 x86_mask; /* stepping */ }; -static const struct cpu_id cpu_id_banias = { - .x86_vendor = X86_VENDOR_INTEL, - .x86 = 6, - .x86_model = 9, - .x86_mask = 5, +enum { + CPU_BANIAS, + CPU_DOTHAN_A1, + CPU_DOTHAN_A2, + CPU_DOTHAN_B0, }; -static const struct cpu_id cpu_id_dothan_a1 = { - .x86_vendor = X86_VENDOR_INTEL, - .x86 = 6, - .x86_model = 13, - .x86_mask = 1, +static const struct cpu_id cpu_ids[] = { + [CPU_BANIAS] = { 6, 9, 5 }, + [CPU_DOTHAN_A1] = { 6, 13, 1 }, + [CPU_DOTHAN_A2] = { 6, 13, 2 }, + [CPU_DOTHAN_B0] = { 6, 13, 6 }, }; +#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) struct cpu_model { @@ -68,10 +68,11 @@ struct cpu_model struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ }; -static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x); +static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x); /* Operating points for current CPU */ static struct cpu_model *centrino_model; +static const struct cpu_id *centrino_cpu; #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE @@ -84,7 +85,7 @@ static struct cpu_model *centrino_model; .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ } -/* +/* * These voltage tables were derived from the Intel Pentium M * datasheet, document 25261202.pdf, Table 5. I have verified they * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium @@ -103,9 +104,9 @@ static struct cpufreq_frequency_table banias_900[] = /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */ static struct cpufreq_frequency_table banias_1000[] = { - OP(600, 844), - OP(800, 972), - OP(900, 988), + OP(600, 844), + OP(800, 972), + OP(900, 988), OP(1000, 1004), { .frequency = CPUFREQ_TABLE_END } }; @@ -135,7 +136,7 @@ static struct cpufreq_frequency_table banias_1200[] = }; /* Intel Pentium M processor 1.30GHz (Banias) */ -static struct cpufreq_frequency_table banias_1300[] = +static struct cpufreq_frequency_table banias_1300[] = { OP( 600, 956), OP( 800, 1260), @@ -146,7 +147,7 @@ static struct cpufreq_frequency_table banias_1300[] = }; /* Intel Pentium M processor 1.40GHz (Banias) */ -static struct cpufreq_frequency_table banias_1400[] = +static struct cpufreq_frequency_table banias_1400[] = { OP( 600, 956), OP( 800, 1180), @@ -157,7 +158,7 @@ static struct cpufreq_frequency_table banias_1400[] = }; /* Intel Pentium M processor 1.50GHz (Banias) */ -static struct cpufreq_frequency_table banias_1500[] = +static struct cpufreq_frequency_table banias_1500[] = { OP( 600, 956), OP( 800, 1116), @@ -169,7 +170,7 @@ static struct cpufreq_frequency_table banias_1500[] = }; /* Intel Pentium M processor 1.60GHz (Banias) */ -static struct cpufreq_frequency_table banias_1600[] = +static struct cpufreq_frequency_table banias_1600[] = { OP( 600, 956), OP( 800, 1036), @@ -199,13 +200,13 @@ static struct cpufreq_frequency_table banias_1700[] = .max_freq = (max)*1000, \ .op_points = banias_##max, \ } -#define BANIAS(max) _BANIAS(&cpu_id_banias, max, #max) +#define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max) /* CPU models, their operating frequency range, and freq/voltage operating points */ -static struct cpu_model models[] = +static struct cpu_model models[] = { - _BANIAS(&cpu_id_banias, 900, " 900"), + _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"), BANIAS(1000), BANIAS(1100), BANIAS(1200), @@ -214,6 +215,12 @@ static struct cpu_model models[] = BANIAS(1500), BANIAS(1600), BANIAS(1700), + + /* NULL model_name is a wildcard */ + { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, + { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, + { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, + { NULL, } }; #undef _BANIAS @@ -224,20 +231,33 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; struct cpu_model *model; - for(model = models; model->model_name != NULL; model++) - if ((strcmp(cpu->x86_model_id, model->model_name) == 0) && - (!centrino_verify_cpu_id(cpu, model->cpu_id))) + for(model = models; model->cpu_id != NULL; model++) + if (centrino_verify_cpu_id(cpu, model->cpu_id) && + (model->model_name == NULL || + strcmp(cpu->x86_model_id, model->model_name) == 0)) break; - if (model->model_name == NULL) { + + if (model->cpu_id == NULL) { + /* No match at all */ printk(KERN_INFO PFX "no support for CPU model \"%s\": " "send /proc/cpuinfo to " MAINTAINER "\n", cpu->x86_model_id); return -ENOENT; } + if (model->op_points == NULL) { + /* Matched a non-match */ + printk(KERN_INFO PFX "no table support for CPU model \"%s\": \n", + cpu->x86_model_id); +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI + printk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); +#endif + return -ENOENT; + } + centrino_model = model; - - printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n", + + dprintk("found \"%s\": max frequency: %dkHz\n", model->model_name, model->max_freq); return 0; @@ -247,31 +267,56 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ -static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x) +static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x) { if ((c->x86 == x->x86) && - (c->x86_vendor == x->x86_vendor) && (c->x86_model == x->x86_model) && (c->x86_mask == x->x86_mask)) - return 0; - return -ENODEV; + return 1; + return 0; } -/* Extract clock in kHz from PERF_CTL value */ +/* To be called only after centrino_model is initialized */ static unsigned extract_clock(unsigned msr) { - msr = (msr >> 8) & 0xff; - return msr * 100000; + int i; + + /* + * Extract clock in kHz from PERF_CTL value + * for centrino, as some DSDTs are buggy. + * Ideally, this can be done using the acpi_data structure. + */ + if ((centrino_cpu == &cpu_ids[CPU_BANIAS]) || + (centrino_cpu == &cpu_ids[CPU_DOTHAN_A1]) || + (centrino_cpu == &cpu_ids[CPU_DOTHAN_B0])) { + msr = (msr >> 8) & 0xff; + return msr * 100000; + } + + if ((!centrino_model) || (!centrino_model->op_points)) + return 0; + + msr &= 0xffff; + for (i=0;centrino_model->op_points[i].frequency != CPUFREQ_TABLE_END; i++) { + if (msr == centrino_model->op_points[i].index) + return centrino_model->op_points[i].frequency; + } + return 0; } /* Return the current CPU frequency in kHz */ static unsigned int get_cur_freq(unsigned int cpu) { unsigned l, h; - if (cpu) + cpumask_t saved_mask; + + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (smp_processor_id() != cpu) return 0; rdmsr(MSR_IA32_PERF_STATUS, l, h); + set_cpus_allowed(current, saved_mask); return extract_clock(l); } @@ -280,13 +325,8 @@ static unsigned int get_cur_freq(unsigned int cpu) static struct acpi_processor_performance p; -#include -#include - -#define ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP 0x1 - /* - * centrino_cpu_init_acpi - register with ACPI P-States library + * centrino_cpu_init_acpi - register with ACPI P-States library * * Register with the ACPI P-States library (part of drivers/acpi/processor.c) * in order to determine correct frequency and voltage pairings by reading @@ -296,55 +336,59 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { union acpi_object arg0 = {ACPI_TYPE_BUFFER}; u32 arg0_buf[3]; - struct acpi_object_list arg_list = {1, &arg0}; + struct acpi_object_list arg_list = {1, &arg0}; unsigned long cur_freq; int result = 0, i; /* _PDC settings */ - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0] = ACPI_PDC_REVISION_ID; - arg0_buf[1] = 1; - arg0_buf[2] = ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP; + arg0.buffer.length = 12; + arg0.buffer.pointer = (u8 *) arg0_buf; + arg0_buf[0] = ACPI_PDC_REVISION_ID; + arg0_buf[1] = 1; + arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR; p.pdc = &arg_list; /* register with ACPI core */ - if (acpi_processor_register_performance(&p, 0)) - return -EIO; + if (acpi_processor_register_performance(&p, policy->cpu)) { + printk(KERN_INFO PFX "obtaining ACPI data failed\n"); + return -EIO; + } /* verify the acpi_data */ if (p.state_count <= 1) { - printk(KERN_DEBUG "No P-States\n"); - result = -ENODEV; - goto err_unreg; - } + dprintk("No P-States\n"); + result = -ENODEV; + goto err_unreg; + } if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { - printk(KERN_DEBUG "Invalid control/status registers\n"); + dprintk("Invalid control/status registers (%x - %x)\n", + p.control_register.space_id, p.status_register.space_id); result = -EIO; goto err_unreg; } for (i=0; i p.states[0].core_frequency) { + dprintk("P%u has larger frequency (%u) than P0 (%u), skipping\n", i, + p.states[i].core_frequency, p.states[0].core_frequency); + p.states[i].core_frequency = 0; + continue; } } @@ -357,29 +401,55 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) centrino_model->model_name=NULL; centrino_model->max_freq = p.states[0].core_frequency * 1000; - centrino_model->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * + centrino_model->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * (p.state_count + 1), GFP_KERNEL); if (!centrino_model->op_points) { result = -ENOMEM; goto err_kfree; } - cur_freq = get_cur_freq(0); - for (i=0; iop_points[i].index = p.states[i].control; centrino_model->op_points[i].frequency = p.states[i].core_frequency * 1000; + dprintk("adding state %i with frequency %u and control value %04x\n", + i, centrino_model->op_points[i].frequency, centrino_model->op_points[i].index); + } + centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END; + + cur_freq = get_cur_freq(policy->cpu); + + for (i=0; iop_points[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } + + if (extract_clock(centrino_model->op_points[i].index) != + (centrino_model->op_points[i].frequency)) { + dprintk("Invalid encoded frequency (%u vs. %u)\n", + extract_clock(centrino_model->op_points[i].index), + centrino_model->op_points[i].frequency); + result = -EINVAL; + goto err_kfree_all; + } + if (cur_freq == centrino_model->op_points[i].frequency) p.state = i; } - centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END; + + /* notify BIOS that we exist */ + acpi_processor_notify_smm(THIS_MODULE); return 0; + err_kfree_all: + kfree(centrino_model->op_points); err_kfree: kfree(centrino_model); err_unreg: - acpi_processor_unregister_performance(&p, 0); + acpi_processor_unregister_performance(&p, policy->cpu); + printk(KERN_INFO PFX "invalid ACPI data\n"); return (result); } #else @@ -392,21 +462,30 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) unsigned freq; unsigned l, h; int ret; + int i; - if (policy->cpu != 0) + /* Only Intel makes Enhanced Speedstep-capable CPUs */ + if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; - if (!cpu_has(cpu, X86_FEATURE_EST)) - return -ENODEV; + for (i = 0; i < N_IDS; i++) + if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) + break; - if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) && - (centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) { - printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: " - "send /proc/cpuinfo to " MAINTAINER "\n"); - return -ENODEV; - } + if (i != N_IDS) + centrino_cpu = &cpu_ids[i]; if (centrino_cpu_init_acpi(policy)) { + if (policy->cpu != 0) + return -ENODEV; + + if (!centrino_cpu) { + printk(KERN_INFO PFX "found unsupported CPU with " + "Enhanced SpeedStep: send /proc/cpuinfo to " + MAINTAINER "\n"); + return -ENODEV; + } + if (centrino_cpu_init_table(policy)) { return -ENODEV; } @@ -415,11 +494,12 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) /* Check to see if Enhanced SpeedStep is enabled, and try to enable it if not. */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); - + if (!(l & (1<<16))) { l |= (1<<16); + dprintk("trying to enable Enhanced SpeedStep (%x)\n", l); wrmsr(MSR_IA32_MISC_ENABLE, l, h); - + /* check to see if it stuck */ rdmsr(MSR_IA32_MISC_ENABLE, l, h); if (!(l & (1<<16))) { @@ -428,15 +508,14 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) } } - freq = get_cur_freq(0); + freq = get_cur_freq(policy->cpu); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ policy->cur = freq; - dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n", - policy->policy, policy->cur); - + dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur); + ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points); if (ret) return (ret); @@ -455,7 +534,8 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI if (!centrino_model->model_name) { - acpi_processor_unregister_performance(&p, 0); + dprintk("unregistering and freeing ACPI data\n"); + acpi_processor_unregister_performance(&p, policy->cpu); kfree(centrino_model->op_points); kfree(centrino_model); } @@ -493,52 +573,61 @@ static int centrino_target (struct cpufreq_policy *policy, unsigned int newstate = 0; unsigned int msr, oldmsr, h; struct cpufreq_freqs freqs; + cpumask_t saved_mask; + int retval; if (centrino_model == NULL) return -ENODEV; + /* + * Support for SMP systems. + * Make sure we are running on the CPU that wants to change frequency + */ + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, policy->cpus); + if (smp_processor_id() != policy->cpu) { + dprintk("couldn't limit to CPUs in this domain\n"); + return(-EAGAIN); + } + if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq, - relation, &newstate)) - return -EINVAL; + relation, &newstate)) { + retval = -EINVAL; + goto migrate_end; + } msr = centrino_model->op_points[newstate].index; rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); - if (msr == (oldmsr & 0xffff)) - return 0; + if (msr == (oldmsr & 0xffff)) { + retval = 0; + dprintk("no change needed - msr was and needs to be %x\n", oldmsr); + goto migrate_end; + } - /* Hm, old frequency can either be the last value we put in - PERF_CTL, or whatever it is now. The trouble is that TM2 - can change it behind our back, which means we never get to - see the speed change. Reading back the current speed would - tell us something happened, but it may leave the things on - the notifier chain confused; we therefore stick to using - the last programmed speed rather than the current speed for - "old". - - TODO: work out how the TCC interrupts work, and try to - catch the CPU changing things under us. - */ - freqs.cpu = 0; + freqs.cpu = policy->cpu; freqs.old = extract_clock(oldmsr); freqs.new = extract_clock(msr); - - dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n", + + dprintk("target=%dkHz old=%d new=%d msr=%04x\n", target_freq, freqs.old, freqs.new, msr); - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); /* all but 16 LSB are "reserved", so treat them with care */ oldmsr &= ~0xffff; msr &= 0xffff; oldmsr |= msr; - + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return 0; + retval = 0; +migrate_end: + set_cpus_allowed(current, saved_mask); + return (retval); } static struct freq_attr* centrino_attr[] = { @@ -547,12 +636,12 @@ static struct freq_attr* centrino_attr[] = { }; static struct cpufreq_driver centrino_driver = { - .name = "centrino", /* should be speedstep-centrino, + .name = "centrino", /* should be speedstep-centrino, but there's a 16 char limit */ .init = centrino_cpu_init, .exit = centrino_cpu_exit, - .verify = centrino_verify, - .target = centrino_target, + .verify = centrino_verify, + .target = centrino_target, .get = get_cur_freq, .attr = centrino_attr, .owner = THIS_MODULE, diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 93b70f0dc..5b7d18a06 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -7,7 +7,7 @@ * for chipsets ICH2-M and ICH3-M. * * Many thanks to Ducrot Bruno for finding and fixing the last - * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler + * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler * for extensive testing. * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* @@ -19,7 +19,7 @@ *********************************************************************/ #include -#include +#include #include #include #include @@ -29,68 +29,58 @@ /* speedstep_chipset: - * It is necessary to know which chipset is used. As accesses to - * this device occur at various places in this module, we need a + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a * static struct pci_dev * pointing to that device. */ -static struct pci_dev *speedstep_chipset_dev; +static struct pci_dev *speedstep_chipset_dev; /* speedstep_processor */ -static unsigned int speedstep_processor = 0; +static unsigned int speedstep_processor = 0; -/* +/* * There are only two frequency states for each processor. Values * are in kHz for the time being. */ static struct cpufreq_frequency_table speedstep_freqs[] = { - {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_HIGH, 0}, {SPEEDSTEP_LOW, 0}, {0, CPUFREQ_TABLE_END}, }; -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg) /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * - * Tries to change the SpeedStep state. + * Tries to change the SpeedStep state. */ static void speedstep_set_state (unsigned int state) { - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; if (!speedstep_chipset_dev || (state > 0x1)) return; /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + if (!(pmbase & 0x01)) { + printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); return; } pmbase &= 0xFFFFFFFE; if (!pmbase) { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); return; } @@ -100,13 +90,13 @@ static void speedstep_set_state (unsigned int state) /* read state */ value = inb(pmbase + 0x50); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); /* write new state */ value &= 0xFE; value |= state; - dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + dprintk("writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); /* Disable bus master arbitration */ pm2_blk = inb(pmbase + 0x20); @@ -126,10 +116,10 @@ static void speedstep_set_state (unsigned int state) /* Enable IRQs */ local_irq_restore(flags); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk("read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); if (state == (value & 0x1)) { - dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000)); + dprintk("change to %u MHz succeeded\n", (speedstep_get_processor_frequency(speedstep_processor) / 1000)); } else { printk (KERN_ERR "cpufreq: change failed - I/O error\n"); } @@ -146,18 +136,16 @@ static void speedstep_set_state (unsigned int state) */ static int speedstep_activate (void) { - u16 value = 0; + u16 value = 0; if (!speedstep_chipset_dev) return -EINVAL; - pci_read_config_word(speedstep_chipset_dev, - 0x00A0, &value); + pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value); if (!(value & 0x08)) { value |= 0x08; - dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); - pci_write_config_word(speedstep_chipset_dev, - 0x00A0, value); + dprintk("activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, 0x00A0, value); } return 0; @@ -167,23 +155,23 @@ static int speedstep_activate (void) /** * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic * - * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to - * the LPC bridge / PM module which contains all power-management + * Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to + * the LPC bridge / PM module which contains all power-management * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected * chipset, or zero on failure. */ static unsigned int speedstep_detect_chipset (void) { - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801DB_12, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, NULL); if (speedstep_chipset_dev) return 4; /* 4-M */ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801CA_12, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, NULL); @@ -191,20 +179,20 @@ static unsigned int speedstep_detect_chipset (void) return 3; /* 3-M */ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + speedstep_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, NULL); if (speedstep_chipset_dev) { /* speedstep.c causes lockups on Dell Inspirons 8000 and - * 8100 which use a pretty old revision of the 82815 + * 8100 which use a pretty old revision of the 82815 * host brige. Abort on these systems. */ - static struct pci_dev *hostbridge; - u8 rev = 0; + static struct pci_dev *hostbridge; + u8 rev = 0; - hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, + hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_MC, PCI_ANY_ID, PCI_ANY_ID, @@ -212,20 +200,39 @@ static unsigned int speedstep_detect_chipset (void) if (!hostbridge) return 2; /* 2-M */ - + pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); if (rev < 5) { - dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); + dprintk("hostbridge does not support speedstep\n"); speedstep_chipset_dev = NULL; + pci_dev_put(hostbridge); return 0; } + pci_dev_put(hostbridge); return 2; /* 2-M */ } return 0; } +static unsigned int _speedstep_get(cpumask_t cpus) +{ + unsigned int speed; + cpumask_t cpus_allowed; + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, cpus); + speed = speedstep_get_processor_frequency(speedstep_processor); + set_cpus_allowed(current, cpus_allowed); + dprintk("detected %u kHz as current frequency\n", speed); + return speed; +} + +static unsigned int speedstep_get(unsigned int cpu) +{ + return _speedstep_get(cpumask_of_cpu(cpu)); +} /** * speedstep_target - set a new CPUFreq policy @@ -239,45 +246,40 @@ static int speedstep_target (struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - unsigned int newstate = 0; + unsigned int newstate = 0; struct cpufreq_freqs freqs; - cpumask_t cpus_allowed, affected_cpu_map; + cpumask_t cpus_allowed; int i; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; + freqs.old = _speedstep_get(policy->cpus); + freqs.new = speedstep_freqs[newstate].frequency; + freqs.cpu = policy->cpu; + + dprintk("transiting from %u to %u kHz\n", freqs.old, freqs.new); + /* no transition necessary */ if (freqs.old == freqs.new) return 0; - freqs.old = speedstep_get_processor_frequency(speedstep_processor); - freqs.new = speedstep_freqs[newstate].frequency; - freqs.cpu = policy->cpu; - cpus_allowed = current->cpus_allowed; - /* only run on CPU to be set, or on its sibling */ -#ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); -#endif - - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } /* switch to physical CPU where state is to be changed */ - set_cpus_allowed(current, affected_cpu_map); + set_cpus_allowed(current, policy->cpus); speedstep_set_state(newstate); /* allow to be run on all CPUs */ set_cpus_allowed(current, cpus_allowed); - for_each_cpu_mask(i, affected_cpu_map) { + for_each_cpu_mask(i, policy->cpus) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } @@ -301,41 +303,33 @@ static int speedstep_verify (struct cpufreq_policy *policy) static int speedstep_cpu_init(struct cpufreq_policy *policy) { - int result = 0; - unsigned int speed; - cpumask_t cpus_allowed,affected_cpu_map; - - - /* capability check */ - if (policy->cpu != 0) /* FIXME: better support for SMT in cpufreq core. Up until then, it's better to register only one CPU */ - return -ENODEV; + int result = 0; + unsigned int speed; + cpumask_t cpus_allowed; /* only run on CPU to be set, or on its sibling */ - cpus_allowed = current->cpus_allowed; #ifdef CONFIG_SMP - affected_cpu_map = cpu_sibling_map[policy->cpu]; -#else - affected_cpu_map = cpumask_of_cpu(policy->cpu); + policy->cpus = cpu_sibling_map[policy->cpu]; #endif - set_cpus_allowed(current, affected_cpu_map); + + cpus_allowed = current->cpus_allowed; + set_cpus_allowed(current, policy->cpus); /* detect low and high frequency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_set_state); - if (result) { - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed(current, cpus_allowed); + if (result) return result; - } /* get current speed setting */ - speed = speedstep_get_processor_frequency(speedstep_processor); - set_cpus_allowed(current, cpus_allowed); + speed = _speedstep_get(policy->cpus); if (!speed) return -EIO; - dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + dprintk("currently at %s speed setting - %i MHz\n", (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", (speed / 1000)); @@ -360,11 +354,6 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy) return 0; } -static unsigned int speedstep_get(unsigned int cpu) -{ - return speedstep_get_processor_frequency(speedstep_processor); -} - static struct freq_attr* speedstep_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -372,14 +361,14 @@ static struct freq_attr* speedstep_attr[] = { static struct cpufreq_driver speedstep_driver = { - .name = "speedstep-ich", - .verify = speedstep_verify, - .target = speedstep_target, - .init = speedstep_cpu_init, - .exit = speedstep_cpu_exit, - .get = speedstep_get, - .owner = THIS_MODULE, - .attr = speedstep_attr, + .name = "speedstep-ich", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, + .exit = speedstep_cpu_exit, + .get = speedstep_get, + .owner = THIS_MODULE, + .attr = speedstep_attr, }; @@ -394,18 +383,22 @@ static int __init speedstep_init(void) { /* detect processor */ speedstep_processor = speedstep_detect_processor(); - if (!speedstep_processor) + if (!speedstep_processor) { + dprintk("Intel(R) SpeedStep(TM) capable processor not found\n"); return -ENODEV; + } /* detect chipset */ if (!speedstep_detect_chipset()) { - printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); + dprintk("Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); return -ENODEV; } /* activate speedstep support */ - if (speedstep_activate()) + if (speedstep_activate()) { + pci_dev_put(speedstep_chipset_dev); return -EINVAL; + } return cpufreq_register_driver(&speedstep_driver); } @@ -418,6 +411,7 @@ static int __init speedstep_init(void) */ static void __exit speedstep_exit(void) { + pci_dev_put(speedstep_chipset_dev); cpufreq_unregister_driver(&speedstep_driver); } diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index 82f7c0220..a477ae1d3 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -19,17 +19,7 @@ #include #include "speedstep-lib.h" - -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-lib", msg) #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK static int relaxed_check = 0; @@ -83,7 +73,7 @@ static unsigned int pentium3_get_frequency (unsigned int processor) /* read MSR 0x2a - we only need the low 32 bits */ rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk(KERN_DEBUG "speedstep-lib: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); + dprintk("P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); msr_tmp = msr_lo; /* decode the FSB */ @@ -96,9 +86,10 @@ static unsigned int pentium3_get_frequency (unsigned int processor) } /* decode the multiplier */ - if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) + if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) { + dprintk("workaround for early PIIIs\n"); msr_lo &= 0x03c00000; - else + } else msr_lo &= 0x0bc00000; msr_lo >>= 22; while (msr_lo != msr_decode_mult[j].bitmap) { @@ -107,6 +98,8 @@ static unsigned int pentium3_get_frequency (unsigned int processor) j++; } + dprintk("speed is %u\n", (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100)); + return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); } @@ -116,7 +109,7 @@ static unsigned int pentiumM_get_frequency(void) u32 msr_lo, msr_tmp; rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk(KERN_DEBUG "speedstep-lib: PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); + dprintk("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); /* see table B-2 of 24547212.pdf */ if (msr_lo & 0x00040000) { @@ -125,7 +118,7 @@ static unsigned int pentiumM_get_frequency(void) } msr_tmp = (msr_lo >> 22) & 0x1f; - dprintk(KERN_DEBUG "speedstep-lib: bits 22-26 are 0x%x\n", msr_tmp); + dprintk("bits 22-26 are 0x%x, speed is %u\n", msr_tmp, (msr_tmp * 100 * 1000)); return (msr_tmp * 100 * 1000); } @@ -139,7 +132,7 @@ static unsigned int pentium4_get_frequency(void) rdmsr(0x2c, msr_lo, msr_hi); - dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + dprintk("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); /* decode the FSB: see IA-32 Intel (C) Architecture Software * Developer's Manual, Volume 3: System Prgramming Guide, @@ -169,7 +162,7 @@ static unsigned int pentium4_get_frequency(void) /* Multiplier. */ mult = msr_lo >> 24; - dprintk(KERN_DEBUG "speedstep-lib: P4 - FSB %u kHz; Multiplier %u\n", fsb, mult); + dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult)); return (fsb * mult); } @@ -204,6 +197,8 @@ unsigned int speedstep_detect_processor (void) struct cpuinfo_x86 *c = cpu_data; u32 ebx, msr_lo, msr_hi; + dprintk("x86: %x, model: %x\n", c->x86, c->x86_model); + if ((c->x86_vendor != X86_VENDOR_INTEL) || ((c->x86 != 6) && (c->x86 != 0xF))) return 0; @@ -217,7 +212,7 @@ unsigned int speedstep_detect_processor (void) ebx = cpuid_ebx(0x00000001); ebx &= 0x000000FF; - dprintk(KERN_INFO "ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask); + dprintk("ebx value is %x, x86_mask is %x\n", ebx, c->x86_mask); switch (c->x86_mask) { case 4: @@ -269,6 +264,7 @@ unsigned int speedstep_detect_processor (void) /* cpuid_ebx(1) is 0x04 for desktop PIII, 0x06 for mobile PIII-M */ ebx = cpuid_ebx(0x00000001); + dprintk("ebx is %x\n", ebx); ebx &= 0x000000FF; @@ -286,7 +282,7 @@ unsigned int speedstep_detect_processor (void) /* all mobile PIII Coppermines have FSB 100 MHz * ==> sort out a few desktop PIIIs. */ rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); + dprintk("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); msr_lo &= 0x00c0000; if (msr_lo != 0x0080000) return 0; @@ -298,11 +294,12 @@ unsigned int speedstep_detect_processor (void) * bit 56 or 57 is set */ rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); + dprintk("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); if ((msr_hi & (1<<18)) && (relaxed_check ? 1 : (msr_hi & (3<<24)))) { - if (c->x86_mask == 0x01) + if (c->x86_mask == 0x01) { + dprintk("early PIII version\n"); return SPEEDSTEP_PROCESSOR_PIII_C_EARLY; - else + } else return SPEEDSTEP_PROCESSOR_PIII_C; } @@ -329,10 +326,14 @@ unsigned int speedstep_get_freqs(unsigned int processor, if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) return -EINVAL; + dprintk("trying to determine both speeds\n"); + /* get current speed */ prev_speed = speedstep_get_processor_frequency(processor); if (!prev_speed) return -EIO; + + dprintk("previous seped is %u\n", prev_speed); local_irq_save(flags); @@ -344,6 +345,8 @@ unsigned int speedstep_get_freqs(unsigned int processor, goto out; } + dprintk("low seped is %u\n", *low_speed); + /* switch to high state */ set_state(SPEEDSTEP_HIGH); *high_speed = speedstep_get_processor_frequency(processor); @@ -352,6 +355,8 @@ unsigned int speedstep_get_freqs(unsigned int processor, goto out; } + dprintk("high seped is %u\n", *high_speed); + if (*low_speed == *high_speed) { ret = -ENODEV; goto out; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 6aa31cd5a..79440b3f0 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -24,8 +24,6 @@ #include "speedstep-lib.h" -#define PFX "speedstep-smi: " - /* speedstep system management interface port/command. * * These parameters are got from IST-SMI BIOS call. @@ -58,16 +56,7 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { * of DMA activity going on? */ #define SMI_TRIES 5 -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-smi", msg) /** * speedstep_smi_ownership @@ -81,12 +70,16 @@ static int speedstep_smi_ownership (void) command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); magic = virt_to_phys(magic_data); + dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port); + __asm__ __volatile__( "out %%al, (%%dx)\n" : "=D" (result) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic) ); + dprintk("result is %x\n", result); + return result; } @@ -101,20 +94,31 @@ static int speedstep_smi_ownership (void) */ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) { - u32 command, result, edi, high_mhz, low_mhz; + u32 command, result = 0, edi, high_mhz, low_mhz; u32 state=0; u32 function = GET_SPEEDSTEP_FREQS; - if (!(ist_info.event & 0xFFFF)) + if (!(ist_info.event & 0xFFFF)) { + dprintk("bug #1422 -- can't read freqs from BIOS\n", result); return -ENODEV; + } command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port); + __asm__ __volatile__("movl $0, %%edi\n" "out %%al, (%%dx)\n" : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi) : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) ); + + dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz); + + /* abort if results are obviously incorrect... */ + if ((high_mhz + low_mhz) < 600) + return -EINVAL; + *high = high_mhz * 1000; *low = low_mhz * 1000; @@ -133,15 +137,20 @@ static int speedstep_get_state (void) command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port); + __asm__ __volatile__("movl $0, %%edi\n" "out %%al, (%%dx)\n" : "=a" (result), "=b" (state), "=D" (edi) : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) ); + dprintk("state is %x, result is %x\n", state, result); + return (state & 1); } + /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) @@ -162,9 +171,11 @@ static void speedstep_set_state (unsigned int state) command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + dprintk("trying to set frequency to state %u with command %x at port %x\n", state, command, smi_port); + do { if (retry) { - dprintk(KERN_INFO "cpufreq: retry %u, previous result %u\n", retry, result); + dprintk("retry %u, previous result %u, waiting...\n", retry, result); mdelay(retry * 50); } retry++; @@ -180,7 +191,7 @@ static void speedstep_set_state (unsigned int state) local_irq_restore(flags); if (new_state == state) { - dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (freqs.new / 1000), retry, result); + dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result); } else { printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result); } @@ -245,7 +256,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) result = speedstep_smi_ownership(); if (result) { - dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n"); + dprintk("fails in aquiring ownership of a SMI interface.\n"); return -EINVAL; } @@ -254,30 +265,24 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) &speedstep_freqs[SPEEDSTEP_HIGH].frequency); if (result) { /* fall back to speedstep_lib.c dection mechanism: try both states out */ - dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n"); - if (!speedstep_processor) - speedstep_processor = speedstep_detect_processor(); - - if (!speedstep_processor) - return -ENODEV; - + dprintk("could not detect low and high frequencies by SMI call.\n"); result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, &speedstep_set_state); if (result) { - dprintk(KERN_INFO PFX "could not detect two different speeds -- aborting.\n"); + dprintk("could not detect two different speeds -- aborting.\n"); return result; } else - dprintk(KERN_INFO PFX "workaround worked.\n"); + dprintk("workaround worked.\n"); } /* get current speed setting */ state = speedstep_get_state(); speed = speedstep_freqs[state].frequency; - dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + dprintk("currently at %s speed setting - %i MHz\n", (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", (speed / 1000)); @@ -305,10 +310,6 @@ static unsigned int speedstep_get(unsigned int cpu) { if (cpu) return -ENODEV; - if (!speedstep_processor) - speedstep_processor = speedstep_detect_processor(); - if (!speedstep_processor) - return 0; return speedstep_get_processor_frequency(speedstep_processor); } @@ -318,7 +319,7 @@ static int speedstep_resume(struct cpufreq_policy *policy) int result = speedstep_smi_ownership(); if (result) - dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n"); + dprintk("fails in re-aquiring ownership of a SMI interface.\n"); return result; } @@ -349,14 +350,23 @@ static struct cpufreq_driver speedstep_driver = { */ static int __init speedstep_init(void) { - struct cpuinfo_x86 *c = cpu_data; + speedstep_processor = speedstep_detect_processor(); + + switch (speedstep_processor) { + case SPEEDSTEP_PROCESSOR_PIII_T: + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: + break; + default: + speedstep_processor = 0; + } - if (c->x86_vendor != X86_VENDOR_INTEL) { - printk (KERN_INFO PFX "No Intel CPU detected.\n"); + if (!speedstep_processor) { + dprintk ("No supported Intel CPU detected.\n"); return -ENODEV; } - dprintk(KERN_DEBUG PFX "signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n", + dprintk("signature:0x%.8lx, command:0x%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n", ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level); diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index 55df60a43..98b85b604 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -187,6 +187,14 @@ static void __init geode_configure(void) } +#ifdef CONFIG_PCI +static struct pci_device_id cyrix_55x0[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) }, + { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) }, + { }, +}; +#endif + static void __init init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; @@ -274,8 +282,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) /* * The 5510/5520 companion chips have a funky PIT. */ - if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) || - pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL)) + if (pci_dev_present(cyrix_55x0)) pit_latch_buggy = 1; /* GXm supports extended cpuid levels 'ala' AMD */ diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 09acdd76b..eb145ed88 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -56,59 +56,6 @@ int __init ppro_with_ram_bug(void) return 0; } -#define LVL_1_INST 1 -#define LVL_1_DATA 2 -#define LVL_2 3 -#define LVL_3 4 -#define LVL_TRACE 5 - -struct _cache_table -{ - unsigned char descriptor; - char cache_type; - short size; -}; - -/* all the cache descriptor types we care about (no TLB or trace cache entries) */ -static struct _cache_table cache_table[] __initdata = -{ - { 0x06, LVL_1_INST, 8 }, - { 0x08, LVL_1_INST, 16 }, - { 0x0a, LVL_1_DATA, 8 }, - { 0x0c, LVL_1_DATA, 16 }, - { 0x22, LVL_3, 512 }, - { 0x23, LVL_3, 1024 }, - { 0x25, LVL_3, 2048 }, - { 0x29, LVL_3, 4096 }, - { 0x2c, LVL_1_DATA, 32 }, - { 0x30, LVL_1_INST, 32 }, - { 0x39, LVL_2, 128 }, - { 0x3b, LVL_2, 128 }, - { 0x3c, LVL_2, 256 }, - { 0x41, LVL_2, 128 }, - { 0x42, LVL_2, 256 }, - { 0x43, LVL_2, 512 }, - { 0x44, LVL_2, 1024 }, - { 0x45, LVL_2, 2048 }, - { 0x60, LVL_1_DATA, 16 }, - { 0x66, LVL_1_DATA, 8 }, - { 0x67, LVL_1_DATA, 16 }, - { 0x68, LVL_1_DATA, 32 }, - { 0x70, LVL_TRACE, 12 }, - { 0x71, LVL_TRACE, 16 }, - { 0x72, LVL_TRACE, 32 }, - { 0x79, LVL_2, 128 }, - { 0x7a, LVL_2, 256 }, - { 0x7b, LVL_2, 512 }, - { 0x7c, LVL_2, 1024 }, - { 0x82, LVL_2, 256 }, - { 0x83, LVL_2, 512 }, - { 0x84, LVL_2, 1024 }, - { 0x85, LVL_2, 2048 }, - { 0x86, LVL_2, 512 }, - { 0x87, LVL_2, 1024 }, - { 0x00, 0, 0} -}; /* * P4 Xeon errata 037 workaround. @@ -132,8 +79,8 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c) static void __init init_intel(struct cpuinfo_x86 *c) { + unsigned int l2 = 0; char *p = NULL; - unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ #ifdef CONFIG_X86_F00F_BUG /* @@ -155,79 +102,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) #endif select_idle_routine(c); - if (c->cpuid_level > 1) { - /* supports eax=2 call */ - int i, j, n; - int regs[4]; - unsigned char *dp = (unsigned char *)regs; - - /* Number of times to iterate */ - n = cpuid_eax(2) & 0xFF; - - for ( i = 0 ; i < n ; i++ ) { - cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); - - /* If bit 31 is set, this is an unknown format */ - for ( j = 0 ; j < 3 ; j++ ) { - if ( regs[j] < 0 ) regs[j] = 0; - } - - /* Byte 0 is level count, not a descriptor */ - for ( j = 1 ; j < 16 ; j++ ) { - unsigned char des = dp[j]; - unsigned char k = 0; - - /* look up this descriptor in the table */ - while (cache_table[k].descriptor != 0) - { - if (cache_table[k].descriptor == des) { - switch (cache_table[k].cache_type) { - case LVL_1_INST: - l1i += cache_table[k].size; - break; - case LVL_1_DATA: - l1d += cache_table[k].size; - break; - case LVL_2: - l2 += cache_table[k].size; - break; - case LVL_3: - l3 += cache_table[k].size; - break; - case LVL_TRACE: - trace += cache_table[k].size; - break; - } - - break; - } - - k++; - } - } - } - - if ( trace ) - printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); - else if ( l1i ) - printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); - if ( l1d ) - printk(", L1 D cache: %dK\n", l1d); - else - printk("\n"); - if ( l2 ) - printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); - if ( l3 ) - printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); - - /* - * This assumes the L3 cache is shared; it typically lives in - * the northbridge. The L1 caches are included by the L2 - * cache, and so should not be included for the purpose of - * SMP switching weights. - */ - c->x86_cache_size = l2 ? l2 : (l1i+l1d); - } + l2 = init_intel_cacheinfo(c); /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index 304bf420f..8df52e86c 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c @@ -18,7 +18,7 @@ #include "mce.h" /* Machine Check Handler For AMD Athlon/Duron */ -static asmlinkage void k7_machine_check(struct pt_regs * regs, long error_code) +static fastcall void k7_machine_check(struct pt_regs * regs, long error_code) { int recover=1; u32 alow, ahigh, high, low; @@ -54,6 +54,7 @@ static asmlinkage void k7_machine_check(struct pt_regs * regs, long error_code) wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); /* Serialize */ wmb(); + add_taint(TAINT_MACHINE_CHECK); } } diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 207f10d58..bf6d1aefa 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c @@ -22,13 +22,13 @@ int nr_mce_banks; EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ /* Handle unconfigured int18 (should never happen) */ -static asmlinkage void unexpected_machine_check(struct pt_regs * regs, long error_code) +static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_code) { printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id()); } /* Call the installed machine check handler for this CPU setup. */ -void asmlinkage (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; +void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; /* This has to be run for each processor */ void __init mcheck_init(struct cpuinfo_x86 *c) diff --git a/arch/i386/kernel/cpu/mcheck/mce.h b/arch/i386/kernel/cpu/mcheck/mce.h index b097a7ccc..dc2416dfe 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.h +++ b/arch/i386/kernel/cpu/mcheck/mce.h @@ -7,7 +7,7 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c); void winchip_mcheck_init(struct cpuinfo_x86 *c); /* Call the installed machine check handler for this CPU setup. */ -extern asmlinkage void (*machine_check_vector)(struct pt_regs *, long error_code); +extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code); extern int mce_disabled __initdata; extern int nr_mce_banks; diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c index a1664bb15..7864ddfcc 100644 --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -48,6 +48,7 @@ static void mce_checkregs (void *info) /* Serialize */ wmb(); + add_taint(TAINT_MACHINE_CHECK); } } } diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index b31fc006f..8b16ceb92 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -40,6 +40,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs) { printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n", smp_processor_id()); + add_taint(TAINT_MACHINE_CHECK); } /* P4/Xeon Thermal transition interrupt handler */ @@ -60,6 +61,7 @@ static void intel_thermal_interrupt(struct pt_regs *regs) printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu); printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n", cpu); + add_taint(TAINT_MACHINE_CHECK); } else { printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); } @@ -68,10 +70,10 @@ static void intel_thermal_interrupt(struct pt_regs *regs) /* Thermal interrupt handler for this CPU setup */ static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; -asmlinkage void smp_thermal_interrupt(struct pt_regs regs) +fastcall void smp_thermal_interrupt(struct pt_regs *regs) { irq_enter(); - vendor_thermal_interrupt(®s); + vendor_thermal_interrupt(regs); irq_exit(); } @@ -157,7 +159,7 @@ done: return mce_num_extended_msrs; } -static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_code) +static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) { int recover=1; u32 alow, ahigh, high, low; @@ -222,6 +224,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod wrmsr(msr, 0UL, 0UL); /* Serialize */ wmb(); + add_taint(TAINT_MACHINE_CHECK); } } mcgstl &= ~(1<<2); diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c index c92cd661c..c45a1b485 100644 --- a/arch/i386/kernel/cpu/mcheck/p5.c +++ b/arch/i386/kernel/cpu/mcheck/p5.c @@ -17,7 +17,7 @@ #include "mce.h" /* Machine check handler for Pentium class Intel */ -static asmlinkage void pentium_machine_check(struct pt_regs * regs, long error_code) +static fastcall void pentium_machine_check(struct pt_regs * regs, long error_code) { u32 loaddr, hi, lotype; rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); @@ -25,6 +25,7 @@ static asmlinkage void pentium_machine_check(struct pt_regs * regs, long error_c printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype); if(lotype&(1<<5)) printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id()); + add_taint(TAINT_MACHINE_CHECK); } /* Set up machine check reporting for processors with Intel style MCE */ diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index d63e9578c..46640f8c2 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c @@ -17,7 +17,7 @@ #include "mce.h" /* Machine Check Handler For PII/PIII */ -static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_code) +static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) { int recover=1; u32 alow, ahigh, high, low; @@ -72,6 +72,7 @@ static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_cod wrmsr (msr, 0UL, 0UL); /* Serialize */ wmb(); + add_taint(TAINT_MACHINE_CHECK); } } mcgstl &= ~(1<<2); diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c index ddb579da4..753fa7acb 100644 --- a/arch/i386/kernel/cpu/mcheck/winchip.c +++ b/arch/i386/kernel/cpu/mcheck/winchip.c @@ -16,9 +16,10 @@ #include "mce.h" /* Machine check handler for WinChip C6 */ -static asmlinkage void winchip_machine_check(struct pt_regs * regs, long error_code) +static fastcall void winchip_machine_check(struct pt_regs * regs, long error_code) { printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); + add_taint(TAINT_MACHINE_CHECK); } /* Set up machine check reporting on the Winchip C6 series */ diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 959f57378..f9efeeb81 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -77,22 +77,24 @@ static int have_wrcomb(void) { struct pci_dev *dev; - if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) { + if ((dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) { /* ServerWorks LE chipsets have problems with write-combining Don't allow it and leave room for other chipsets to be tagged */ if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS && dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) { printk(KERN_INFO "mtrr: Serverworks LE detected. Write-combining disabled.\n"); + pci_dev_put(dev); return 0; } /* Intel 450NX errata # 23. Non ascending cachline evictions to write combining memory may resulting in data corruption */ if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82451NX) - { + dev->device == PCI_DEVICE_ID_INTEL_82451NX) { printk(KERN_INFO "mtrr: Intel 450NX MMC detected. Write-combining disabled.\n"); + pci_dev_put(dev); return 0; } + pci_dev_put(dev); } return (mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0); } @@ -147,10 +149,8 @@ static void ipi_handler(void *info) local_irq_save(flags); atomic_dec(&data->count); - while(!atomic_read(&data->gate)) { + while(!atomic_read(&data->gate)) cpu_relax(); - barrier(); - } /* The master has cleared me to execute */ if (data->smp_reg != ~0U) @@ -160,10 +160,9 @@ static void ipi_handler(void *info) mtrr_if->set_all(); atomic_dec(&data->count); - while(atomic_read(&data->gate)) { + while(atomic_read(&data->gate)) cpu_relax(); - barrier(); - } + atomic_dec(&data->count); local_irq_restore(flags); } @@ -228,10 +227,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, local_irq_save(flags); - while(atomic_read(&data.count)) { + while(atomic_read(&data.count)) cpu_relax(); - barrier(); - } + /* ok, reset count and toggle gate */ atomic_set(&data.count, num_booting_cpus() - 1); atomic_set(&data.gate,1); @@ -248,10 +246,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, mtrr_if->set(reg,base,size,type); /* wait for the others */ - while(atomic_read(&data.count)) { + while(atomic_read(&data.count)) cpu_relax(); - barrier(); - } + atomic_set(&data.count, num_booting_cpus() - 1); atomic_set(&data.gate,0); @@ -259,10 +256,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, * Wait here for everyone to have seen the gate change * So we're the last ones to touch 'data' */ - while(atomic_read(&data.count)) { + while(atomic_read(&data.count)) cpu_relax(); - barrier(); - } + local_irq_restore(flags); } diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h index fee8b5ccc..0d10c115d 100644 --- a/arch/i386/kernel/cpu/mtrr/mtrr.h +++ b/arch/i386/kernel/cpu/mtrr/mtrr.h @@ -52,7 +52,6 @@ struct mtrr_ops { }; extern int generic_get_free_region(unsigned long base, unsigned long size); -extern void generic_init_secondary(void); extern int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type); diff --git a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c index 4c44e973b..30898a260 100644 --- a/arch/i386/kernel/cpu/nexgen.c +++ b/arch/i386/kernel/cpu/nexgen.c @@ -32,7 +32,7 @@ static void __init init_nexgen(struct cpuinfo_x86 * c) c->x86_cache_size = 256; /* A few had 1 MB... */ } -static void nexgen_identify(struct cpuinfo_x86 * c) +static void __init nexgen_identify(struct cpuinfo_x86 * c) { /* Detect NexGen with old hypercode */ if ( deep_magic_nexgen_probe() ) { diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 423429491..4ba834c44 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -25,7 +25,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", /* AMD-defined */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", @@ -44,8 +44,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", - "est", NULL, "cid", NULL, NULL, NULL, NULL, NULL, + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -88,7 +88,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_X86_HT - if (cpu_has_ht) { + if (smp_num_siblings > 1) { extern int phys_proc_id[NR_CPUS]; seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); seq_printf(m, "siblings\t: %d\n", smp_num_siblings); diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index 4bb3c5633..f57e5ee94 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -8,7 +8,7 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) { unsigned int cap_mask, uk, max, dummy; unsigned int cms_rev1, cms_rev2; - unsigned int cpu_rev, cpu_freq, cpu_flags; + unsigned int cpu_rev, cpu_freq, cpu_flags, new_cpu_rev; char cpu_info[65]; get_model_name(c); /* Same as AMD/Cyrix */ @@ -16,17 +16,24 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) /* Print CMS and CPU revision */ max = cpuid_eax(0x80860000); + cpu_rev = 0; if ( max >= 0x80860001 ) { cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); - printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n", - (cpu_rev >> 24) & 0xff, - (cpu_rev >> 16) & 0xff, - (cpu_rev >> 8) & 0xff, - cpu_rev & 0xff, - cpu_freq); + if (cpu_rev != 0x02000000) { + printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n", + (cpu_rev >> 24) & 0xff, + (cpu_rev >> 16) & 0xff, + (cpu_rev >> 8) & 0xff, + cpu_rev & 0xff, + cpu_freq); + } } if ( max >= 0x80860002 ) { - cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy); + cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy); + if (cpu_rev == 0x02000000) { + printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n", + new_cpu_rev, cpu_freq); + } printk(KERN_INFO "CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n", (cms_rev1 >> 24) & 0xff, (cms_rev1 >> 16) & 0xff, diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c index d2d2610f2..58406634b 100644 --- a/arch/i386/kernel/dmi_scan.c +++ b/arch/i386/kernel/dmi_scan.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -162,27 +162,6 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) #define NO_MATCH { DMI_NONE, NULL} #define MATCH DMI_MATCH -/* - * Some machines, usually laptops, can't handle an enabled local APIC. - * The symptoms include hangs or reboots when suspending or resuming, - * attaching or detaching the power cord, or entering BIOS setup screens - * through magic key sequences. - */ -static int __init local_apic_kills_bios(struct dmi_blacklist *d) -{ -#ifdef CONFIG_X86_LOCAL_APIC - extern int enable_local_apic; - if (enable_local_apic == 0) { - enable_local_apic = -1; - printk(KERN_WARNING "%s with broken BIOS detected. " - "Refusing to enable the local APIC.\n", - d->ident); - } -#endif - return 0; -} - - /* * Toshiba keyboard likes to repeat keys when they are not repeated. */ @@ -235,20 +214,6 @@ static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) } return 0; } - -/* - * early nForce2 reference BIOS shipped with a - * bogus ACPI IRQ0 -> pin2 interrupt override -- ignore it - */ -static __init int ignore_timer_override(struct dmi_blacklist *d) -{ - extern int acpi_skip_timer_override; - printk(KERN_NOTICE "%s detected: BIOS IRQ0 pin2 override" - " will be ignored\n", d->ident); - - acpi_skip_timer_override = 1; - return 0; -} #endif #ifdef CONFIG_ACPI_PCI @@ -284,32 +249,6 @@ static __init int disable_acpi_pci(struct dmi_blacklist *d) static __initdata struct dmi_blacklist dmi_blacklist[]={ - /* Machines which have problems handling enabled local APICs */ - - { local_apic_kills_bios, "Dell Inspiron", { - MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "Inspiron"), - NO_MATCH, NO_MATCH - } }, - - { local_apic_kills_bios, "Dell Latitude", { - MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - MATCH(DMI_PRODUCT_NAME, "Latitude"), - NO_MATCH, NO_MATCH - } }, - - { local_apic_kills_bios, "IBM Thinkpad T20", { - MATCH(DMI_BOARD_VENDOR, "IBM"), - MATCH(DMI_BOARD_NAME, "264741U"), - NO_MATCH, NO_MATCH - } }, - - { local_apic_kills_bios, "ASUS L3C", { - MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - MATCH(DMI_BOARD_NAME, "P4_L3C"), - 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 @@ -355,21 +294,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), NO_MATCH, NO_MATCH }}, - { force_acpi_ht, "Compaq ProLiant DL380 G2", { - MATCH(DMI_SYS_VENDOR, "Compaq"), - MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"), - NO_MATCH, NO_MATCH }}, - - { force_acpi_ht, "Compaq ProLiant ML530 G2", { - MATCH(DMI_SYS_VENDOR, "Compaq"), - MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"), - NO_MATCH, NO_MATCH }}, - - { force_acpi_ht, "Compaq ProLiant ML350 G3", { - MATCH(DMI_SYS_VENDOR, "Compaq"), - MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"), - NO_MATCH, NO_MATCH }}, - { force_acpi_ht, "Compaq Workstation W8000", { MATCH(DMI_SYS_VENDOR, "Compaq"), MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), @@ -415,48 +339,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"), NO_MATCH, NO_MATCH }}, - /* - * Systems with nForce2 BIOS timer override bug - * nVidia claims all nForce have timer on pin0, - * and applying this workaround is a NOP on fixed BIOS, - * so prospects are good for replacing these entries - * with something to key of chipset PCI-ID. - */ - { ignore_timer_override, "Abit NF7-S v2", { - MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), - MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"), - MATCH(DMI_BIOS_VERSION, "6.00 PG"), - MATCH(DMI_BIOS_DATE, "03/24/2004") }}, - - { ignore_timer_override, "Asus A7N8X v2", { - MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - MATCH(DMI_BOARD_NAME, "A7N8X2.0"), - MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"), - MATCH(DMI_BIOS_DATE, "10/06/2003") }}, - - { ignore_timer_override, "Asus A7N8X-X", { - MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - MATCH(DMI_BOARD_NAME, "A7N8X-X"), - MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"), - MATCH(DMI_BIOS_DATE, "2/3/2004") }}, - - { ignore_timer_override, "MSI K7N2-Delta", { - MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), - MATCH(DMI_BOARD_NAME, "MS-6570"), - MATCH(DMI_BIOS_VERSION, "6.00 PG"), - MATCH(DMI_BIOS_DATE, "03/29/2004") }}, - - { ignore_timer_override, "Shuttle SN41G2", { - MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"), - MATCH(DMI_BOARD_NAME, "FN41"), - MATCH(DMI_BIOS_VERSION, "6.00 PG"), - MATCH(DMI_BIOS_DATE, "01/14/2004") }}, - - { ignore_timer_override, "Shuttle AN35N", { - MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"), - MATCH(DMI_BOARD_NAME, "AN35"), - MATCH(DMI_BIOS_VERSION, "6.00 PG"), - MATCH(DMI_BIOS_DATE, "12/05/2003") }}, #endif // CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_PCI @@ -490,41 +372,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ { NULL, } }; - - -/* - * Walk the blacklist table running matching functions until someone - * returns 1 or we hit the end. - */ - - -static __init void dmi_check_blacklist(void) -{ -#ifdef CONFIG_ACPI_BOOT -#define ACPI_BLACKLIST_CUTOFF_YEAR 2001 - - if (dmi_ident[DMI_BIOS_DATE]) { - char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); - if (s) { - int year, disable = 0; - s++; - year = simple_strtoul(s,NULL,0); - if (year >= 1000) - disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; - else if (year < 1 || (year > 90 && year <= 99)) - disable = 1; - if (disable && !acpi_force) { - printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s); - printk(KERN_NOTICE "You can enable it with acpi=force\n"); - disable_acpi(); - } - } - } -#endif - dmi_check_system(dmi_blacklist); -} - - /* * Process a DMI table entry. Right now all we care about are the BIOS @@ -582,7 +429,7 @@ void __init dmi_scan_machine(void) { int err = dmi_iterate(dmi_decode); if(err == 0) - dmi_check_blacklist(); + dmi_check_system(dmi_blacklist); else printk(KERN_INFO "DMI not present.\n"); } diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c index 6b4a8f3cc..789af3e9f 100644 --- a/arch/i386/kernel/doublefault.c +++ b/arch/i386/kernel/doublefault.c @@ -13,7 +13,7 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) -#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000) +#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) static void doublefault_fn(void) { diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 7b6856363..2935c9403 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -131,7 +131,7 @@ VM_MASK = 0x00020000 movl $(__USER_DS), %edx; \ movl %edx, %ds; \ movl %edx, %es; \ - pushl $11; \ + movl $11,%eax; \ call do_exit; \ .previous; \ .section __ex_table,"a";\ @@ -140,40 +140,6 @@ VM_MASK = 0x00020000 .previous - -ENTRY(lcall7) - pushfl # We get a different stack layout with call - # gates, which has to be cleaned up later.. - pushl %eax - SAVE_ALL - movl %esp, %ebp - pushl %ebp - pushl $0x7 -do_lcall: - movl EIP(%ebp), %eax # due to call gates, this is eflags, not eip.. - movl CS(%ebp), %edx # this is eip.. - movl EFLAGS(%ebp), %ecx # and this is cs.. - movl %eax,EFLAGS(%ebp) # - movl %edx,EIP(%ebp) # Now we move them to their "normal" places - movl %ecx,CS(%ebp) # - GET_THREAD_INFO_WITH_ESP(%ebp) # GET_THREAD_INFO - movl TI_exec_domain(%ebp), %edx # Get the execution domain - call *EXEC_DOMAIN_handler(%edx) # Call the handler for the domain - addl $4, %esp - popl %eax - jmp resume_userspace - -ENTRY(lcall27) - pushfl # We get a different stack layout with call - # gates, which has to be cleaned up later.. - pushl %eax - SAVE_ALL - movl %esp, %ebp - pushl %ebp - pushl $0x27 - jmp do_lcall - - ENTRY(ret_from_fork) pushl %eax call schedule_tail @@ -221,8 +187,8 @@ need_resched: movl $PREEMPT_ACTIVE,TI_preempt_count(%ebp) sti call schedule - movl $0,TI_preempt_count(%ebp) cli + movl $0,TI_preempt_count(%ebp) jmp need_resched #endif @@ -255,11 +221,11 @@ sysenter_past_esp: pushl %eax SAVE_ALL GET_THREAD_INFO(%ebp) - cmpl $(nr_syscalls), %eax - jae syscall_badsys testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz syscall_trace_entry + cmpl $(nr_syscalls), %eax + jae syscall_badsys call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) cli @@ -269,6 +235,7 @@ sysenter_past_esp: /* if something modifies registers it must also disable sysexit */ movl EIP(%esp), %edx movl OLDESP(%esp), %ecx + xorl %ebp,%ebp sti sysexit @@ -278,11 +245,11 @@ ENTRY(system_call) pushl %eax # save orig_eax SAVE_ALL GET_THREAD_INFO(%ebp) - cmpl $(nr_syscalls), %eax - jae syscall_badsys # system call tracing in operation testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz syscall_trace_entry + cmpl $(nr_syscalls), %eax + jae syscall_badsys syscall_call: call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) # store the return value @@ -325,8 +292,8 @@ work_notifysig: # deal with pending signals and ALIGN work_notifysig_v86: - pushl %ecx - call save_v86_state + pushl %ecx # save ti_flags for do_notify_resume + call save_v86_state # %eax contains pt_regs pointer popl %ecx movl %eax, %esp xorl %edx, %edx @@ -348,7 +315,7 @@ syscall_trace_entry: # perform syscall exit tracing ALIGN syscall_exit_work: - testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT), %cl + testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz work_pending sti # could let do_syscall_trace() call # schedule() instead @@ -393,6 +360,7 @@ vector=vector+1 ALIGN common_interrupt: SAVE_ALL + movl %esp,%eax call do_IRQ jmp ret_from_intr @@ -400,7 +368,8 @@ common_interrupt: ENTRY(name) \ pushl $nr-256; \ SAVE_ALL \ - call smp_/**/name; \ + movl %esp,%eax; \ + call smp_/**/name; \ jmp ret_from_intr; /* The include is where all of the SMP etc. interrupts come from */ @@ -423,18 +392,15 @@ error_code: pushl %ebx cld movl %es, %ecx - movl ORIG_EAX(%esp), %esi # get the error code movl ES(%esp), %edi # get the function address + movl ORIG_EAX(%esp), %edx # get the error code movl %eax, ORIG_EAX(%esp) movl %ecx, ES(%esp) - movl %esp, %edx - pushl %esi # push the error code - pushl %edx # push the pt_regs pointer - movl $(__USER_DS), %edx - movl %edx, %ds - movl %edx, %es + movl $(__USER_DS), %ecx + movl %ecx, %ds + movl %ecx, %es + movl %esp,%eax # pt_regs pointer call *%edi - addl $8, %esp jmp ret_from_exception ENTRY(coprocessor_error) @@ -489,9 +455,14 @@ ENTRY(debug) jne debug_stack_correct FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn) debug_stack_correct: - pushl $0 - pushl $do_debug - jmp error_code + pushl $-1 # mark this as an int + SAVE_ALL + xorl %edx,%edx # error code 0 + movl %esp,%eax # pt_regs pointer + call do_debug + testl %eax,%eax + jnz restore_all + jmp ret_from_exception /* * NMI is doubly nasty. It can happen _while_ we're handling @@ -518,11 +489,9 @@ ENTRY(nmi) nmi_stack_correct: pushl %eax SAVE_ALL - movl %esp, %edx - pushl $0 - pushl %edx + xorl %edx,%edx # zero error code + movl %esp,%eax # pt_regs pointer call do_nmi - addl $8, %esp RESTORE_ALL nmi_stack_fixup: @@ -540,9 +509,14 @@ nmi_debug_stack_fixup: jmp nmi_stack_correct ENTRY(int3) - pushl $0 - pushl $do_int3 - jmp error_code + pushl $-1 # mark this as an int + SAVE_ALL + xorl %edx,%edx # zero error code + movl %esp,%eax # pt_regs pointer + call do_int3 + testl %eax,%eax + jnz restore_all + jmp ret_from_exception ENTRY(overflow) pushl $0 @@ -886,5 +860,10 @@ ENTRY(sys_call_table) .long sys_mq_notify .long sys_mq_getsetattr .long sys_ni_syscall /* reserved for kexec */ + .long sys_waitid + .long sys_ni_syscall /* 285 */ /* available */ + .long sys_add_key + .long sys_request_key + .long sys_keyctl syscall_table_size=(.-sys_call_table) diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 69bad9bd0..95fe2fdf4 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -521,6 +521,3 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ -#ifdef CONFIG_SMP - .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */ -#endif diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 064d6fb8a..5e6f450d0 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include extern void dump_thread(struct pt_regs *, struct user *); extern spinlock_t rtc_lock; @@ -71,14 +71,10 @@ EXPORT_SYMBOL(xquad_portio); #endif EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(dump_extended_fpu); EXPORT_SYMBOL_GPL(kernel_fpu_begin); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(ioremap_nocache); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(pm_idle); @@ -87,10 +83,10 @@ EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(cpu_khz); EXPORT_SYMBOL(apm_info); -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); -EXPORT_SYMBOL_NOVERS(__down_failed_trylock); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_failed_interruptible); +EXPORT_SYMBOL(__down_failed_trylock); +EXPORT_SYMBOL(__up_wakeup); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); /* Delay loops */ @@ -99,9 +95,9 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(__const_udelay); -EXPORT_SYMBOL_NOVERS(__get_user_1); -EXPORT_SYMBOL_NOVERS(__get_user_2); -EXPORT_SYMBOL_NOVERS(__get_user_4); +EXPORT_SYMBOL(__get_user_1); +EXPORT_SYMBOL(__get_user_2); +EXPORT_SYMBOL(__get_user_4); EXPORT_SYMBOL(strpbrk); EXPORT_SYMBOL(strstr); @@ -142,11 +138,10 @@ EXPORT_SYMBOL(cpu_sibling_map); EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_callout_map); -EXPORT_SYMBOL_NOVERS(__write_lock_failed); -EXPORT_SYMBOL_NOVERS(__read_lock_failed); +EXPORT_SYMBOL(__write_lock_failed); +EXPORT_SYMBOL(__read_lock_failed); /* Global SMP stuff */ -EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(smp_call_function); /* TLB flushing */ @@ -175,10 +170,11 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback); #undef memcmp extern int memcmp(const void *,const void *,__kernel_size_t); -EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(register_die_notifier); #ifdef CONFIG_HAVE_DEC_LOCK -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif EXPORT_SYMBOL(__PAGE_KERNEL); diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index 3da92c23d..073366a48 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -519,21 +519,6 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu ) return fpvalid; } -int dump_extended_fpu( struct pt_regs *regs, struct user_fxsr_struct *fpu ) -{ - int fpvalid; - struct task_struct *tsk = current; - - fpvalid = tsk->used_math && cpu_has_fxsr; - if ( fpvalid ) { - unlazy_fpu( tsk ); - memcpy( fpu, &tsk->thread.i387.fxsave, - sizeof(struct user_fxsr_struct) ); - } - - return fpvalid; -} - int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) { int fpvalid = tsk->used_math; diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 97653d20f..686a95bd0 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -4,19 +4,20 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include #include #include #include #include -#include +#include #include #include #include @@ -225,7 +226,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", irq); + printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } atomic_inc(&irq_err_count); @@ -238,14 +239,39 @@ spurious_8259A_irq: } } +static char irq_trigger[2]; +/** + * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ + */ +static void restore_ELCR(char *trigger) +{ + outb(trigger[0], 0x4d0); + outb(trigger[1], 0x4d1); +} + +static void save_ELCR(char *trigger) +{ + /* IRQ 0,1,2,8,13 are marked as reserved */ + trigger[0] = inb(0x4d0) & 0xF8; + trigger[1] = inb(0x4d1) & 0xDE; +} + static int i8259A_resume(struct sys_device *dev) { init_8259A(0); + restore_ELCR(irq_trigger); + return 0; +} + +static int i8259A_suspend(struct sys_device *dev, u32 state) +{ + save_ELCR(irq_trigger); return 0; } static struct sysdev_class i8259_sysdev_class = { set_kset_name("i8259"), + .suspend = i8259A_suspend, .resume = i8259A_resume, }; @@ -362,46 +388,6 @@ void __init init_ISA_irqs (void) } } -static void setup_timer(void) -{ - extern spinlock_t i8253_lock; - unsigned long flags; - - spin_lock_irqsave(&i8253_lock, flags); - outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ - udelay(10); - outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ - udelay(10); - outb(LATCH >> 8 , PIT_CH0); /* MSB */ - spin_unlock_irqrestore(&i8253_lock, flags); -} - -static int timer_resume(struct sys_device *dev) -{ - setup_timer(); - return 0; -} - -static struct sysdev_class timer_sysclass = { - set_kset_name("timer"), - .resume = timer_resume, -}; - -static struct sys_device device_timer = { - .id = 0, - .cls = &timer_sysclass, -}; - -static int __init init_timer_sysfs(void) -{ - int error = sysdev_class_register(&timer_sysclass); - if (!error) - error = sysdev_register(&device_timer); - return error; -} - -device_initcall(init_timer_sysfs); - void __init init_IRQ(void) { int i; @@ -431,7 +417,7 @@ void __init init_IRQ(void) * Set the clock to HZ Hz, we already have a valid * vector now: */ - setup_timer(); + setup_pit_timer(); /* * External FPU? Set up irq13 if so, for diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index 5e1897649..9caa8e8db 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c @@ -40,10 +40,7 @@ EXPORT_SYMBOL(init_task); /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, - * no more per-task TSS's. The TSS size is kept cacheline-aligned - * so they are allowed to end up in the .data.cacheline_aligned - * section. Since TSS's are completely CPU-local, we want them - * on exact cacheline boundaries, to eliminate cacheline ping-pong. + * no more per-task TSS's. */ -struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS }; +DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS; diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index a40687e7c..771a35d97 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,9 @@ #include "io_ports.h" +int (*ioapic_renumber_irq)(int ioapic, int irq); +atomic_t irq_mis_count; + static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; /* @@ -85,7 +89,7 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static void __init add_pin_to_irq(unsigned int irq, int apic, int pin) +static void add_pin_to_irq(unsigned int irq, int apic, int pin) { static int first_free_entry = NR_IRQS; struct irq_pin_list *entry = irq_2_pin + irq; @@ -254,8 +258,6 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) # define Dprintk(x...) # endif -extern cpumask_t irq_affinity[NR_IRQS]; - cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS]; #define IRQBALANCE_CHECK_ARCH -999 @@ -635,7 +637,7 @@ failed: return 0; } -static int __init irqbalance_disable(char *str) +int __init irqbalance_disable(char *str) { irqbalance_disabled = 1; return 0; @@ -652,7 +654,7 @@ static inline void move_irq(int irq) } } -__initcall(balanced_irq_init); +late_initcall(balanced_irq_init); #else /* !CONFIG_IRQBALANCE */ static inline void move_irq(int irq) { } @@ -705,13 +707,15 @@ static int __init ioapic_pirq_setup(char *str) pirq_entries[i] = -1; pirqs_enabled = 1; - printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n"); + apic_printk(APIC_VERBOSE, KERN_INFO + "PIRQ redirection, working around broken MP-BIOS.\n"); max = MAX_PIRQS; if (ints[0] < MAX_PIRQS) max = ints[0]; for (i = 0; i < max; i++) { - printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); + apic_printk(APIC_VERBOSE, KERN_DEBUG + "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); /* * PIRQs are mapped upside down, usually. */ @@ -725,7 +729,7 @@ __setup("pirq=", ioapic_pirq_setup); /* * Find the IRQ entry number of a certain pin. */ -static int __init find_irq_entry(int apic, int pin, int type) +static int find_irq_entry(int apic, int pin, int type) { int i; @@ -742,7 +746,7 @@ static int __init find_irq_entry(int apic, int pin, int type) /* * Find the pin to which IRQ[irq] (ISA) is connected */ -static int __init find_isa_irq_pin(int irq, int type) +static int find_isa_irq_pin(int irq, int type) { int i; @@ -772,8 +776,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) { int apic, i, best_guess = -1; - Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", - bus, slot, pin); + apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, " + "slot:%d, pin:%d.\n", bus, slot, pin); if (mp_bus_id_to_pci_bus[bus] == -1) { printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); return -1; @@ -835,13 +839,14 @@ void __init setup_ioapic_dest(void) /* * EISA Edge/Level control register, ELCR */ -static int __init EISA_ELCR(unsigned int irq) +static int EISA_ELCR(unsigned int irq) { if (irq < 16) { unsigned int port = 0x4d0 + (irq >> 3); return (inb(port) >> (irq & 7)) & 1; } - printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq); + apic_printk(APIC_VERBOSE, KERN_INFO + "Broken MPtable reports ISA irq %d\n", irq); return 0; } @@ -951,7 +956,7 @@ static int __init MPBIOS_polarity(int idx) return polarity; } -static int __init MPBIOS_trigger(int idx) +static int MPBIOS_trigger(int idx) { int bus = mp_irqs[idx].mpc_srcbus; int trigger; @@ -1065,8 +1070,13 @@ static int pin_2_irq(int idx, int apic, int pin) while (i < apic) irq += nr_ioapic_registers[i++]; irq += pin; - if ((!apic) && (irq < 16)) - irq += 16; + + /* + * For MPS mode, so far only needed by ES7000 platform + */ + if (ioapic_renumber_irq) + irq = ioapic_renumber_irq(apic, irq); + break; } default: @@ -1083,10 +1093,12 @@ static int pin_2_irq(int idx, int apic, int pin) if ((pin >= 16) && (pin <= 23)) { if (pirq_entries[pin-16] != -1) { if (!pirq_entries[pin-16]) { - printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16); + apic_printk(APIC_VERBOSE, KERN_DEBUG + "disabling PIRQ%d\n", pin-16); } else { irq = pirq_entries[pin-16]; - printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n", + apic_printk(APIC_VERBOSE, KERN_DEBUG + "using PIRQ%d -> IRQ %d\n", pin-16, irq); } } @@ -1114,11 +1126,7 @@ static inline int IO_APIC_irq_trigger(int irq) /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; -#ifdef CONFIG_PCI_MSI int assign_irq_vector(int irq) -#else -int __init assign_irq_vector(int irq) -#endif { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; @@ -1176,7 +1184,7 @@ void __init setup_IO_APIC_irqs(void) int apic, pin, idx, irq, first_notcon = 1, vector; unsigned long flags; - printk(KERN_DEBUG "init IO_APIC IRQs\n"); + apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); for (apic = 0; apic < nr_ioapics; apic++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { @@ -1195,10 +1203,14 @@ void __init setup_IO_APIC_irqs(void) idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { if (first_notcon) { - printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); + apic_printk(APIC_VERBOSE, KERN_DEBUG + " IO-APIC (apicid-pin) %d-%d", + mp_ioapics[apic].mpc_apicid, + pin); first_notcon = 0; } else - printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin); + apic_printk(APIC_VERBOSE, ", %d-%d", + mp_ioapics[apic].mpc_apicid, pin); continue; } @@ -1239,7 +1251,7 @@ void __init setup_IO_APIC_irqs(void) } if (!first_notcon) - printk(" not connected.\n"); + apic_printk(APIC_VERBOSE, " not connected.\n"); } /* @@ -1299,6 +1311,9 @@ void __init print_IO_APIC(void) union IO_APIC_reg_03 reg_03; unsigned long flags; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", @@ -1441,6 +1456,9 @@ static void print_APIC_bitfield (int base) unsigned int v; int i, j; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); for (i = 0; i < 8; i++) { v = apic_read(base + i*0x10); @@ -1458,6 +1476,9 @@ void /*__init*/ print_local_APIC(void * dummy) { unsigned int v, ver, maxlvt; + if (apic_verbosity == APIC_QUIET) + return; + printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); @@ -1545,6 +1566,9 @@ void /*__init*/ print_PIC(void) unsigned int v; unsigned long flags; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "\nprinting PIC contents\n"); spin_lock_irqsave(&i8259A_lock, flags); @@ -1680,7 +1704,9 @@ static void __init setup_ioapic_ids_from_mpc(void) } else { physid_mask_t tmp; tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid); - printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid); + apic_printk(APIC_VERBOSE, "Setting %d in the " + "phys_id_present_map\n", + mp_ioapics[apic].mpc_apicid); physids_or(phys_id_present_map, phys_id_present_map, tmp); } @@ -1699,8 +1725,9 @@ static void __init setup_ioapic_ids_from_mpc(void) * Read the right value from the MPC table and * write it into the ID register. */ - printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", - mp_ioapics[apic].mpc_apicid); + apic_printk(APIC_VERBOSE, KERN_INFO + "...changing IO-APIC physical APIC ID to %d ...", + mp_ioapics[apic].mpc_apicid); reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; spin_lock_irqsave(&ioapic_lock, flags); @@ -1714,9 +1741,9 @@ static void __init setup_ioapic_ids_from_mpc(void) reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); + printk("could not set ID!\n"); else - printk(" ok.\n"); + apic_printk(APIC_VERBOSE, " ok.\n"); } } #else @@ -1858,9 +1885,7 @@ static void end_level_ioapic_irq (unsigned int irq) ack_APIC_irq(); if (!(v & (1 << (i & 0x1f)))) { -#ifdef APIC_MISMATCH_DEBUG atomic_inc(&irq_mis_count); -#endif spin_lock(&ioapic_lock); __mask_and_edge_IO_APIC_irq(irq); __unmask_and_level_IO_APIC_irq(irq); @@ -2031,11 +2056,11 @@ static void setup_nmi (void) * is from Maciej W. Rozycki - so we do not have to EOI from * the NMI handler or the timer interrupt. */ - printk(KERN_INFO "activating NMI Watchdog ..."); + apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ..."); on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1); - printk(" done.\n"); + apic_printk(APIC_VERBOSE, " done.\n"); } /* @@ -2212,7 +2237,8 @@ static inline void check_timer(void) return; } printk(" failed :(.\n"); - panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); + panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " + "report. Then try booting with the 'noapic' option"); } /* @@ -2262,6 +2288,98 @@ static int __init io_apic_bug_finalize(void) late_initcall(io_apic_bug_finalize); +struct sysfs_ioapic_data { + struct sys_device dev; + struct IO_APIC_route_entry entry[0]; +}; +static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS]; + +static int ioapic_suspend(struct sys_device *dev, u32 state) +{ + struct IO_APIC_route_entry *entry; + struct sysfs_ioapic_data *data; + unsigned long flags; + int i; + + data = container_of(dev, struct sysfs_ioapic_data, dev); + entry = data->entry; + spin_lock_irqsave(&ioapic_lock, flags); + for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { + *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i); + *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i); + } + spin_unlock_irqrestore(&ioapic_lock, flags); + + return 0; +} + +static int ioapic_resume(struct sys_device *dev) +{ + struct IO_APIC_route_entry *entry; + struct sysfs_ioapic_data *data; + unsigned long flags; + union IO_APIC_reg_00 reg_00; + int i; + + data = container_of(dev, struct sysfs_ioapic_data, dev); + entry = data->entry; + + spin_lock_irqsave(&ioapic_lock, flags); + reg_00.raw = io_apic_read(dev->id, 0); + if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) { + reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; + io_apic_write(dev->id, 0, reg_00.raw); + } + for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { + io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1)); + io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0)); + } + spin_unlock_irqrestore(&ioapic_lock, flags); + + return 0; +} + +static struct sysdev_class ioapic_sysdev_class = { + set_kset_name("ioapic"), + .suspend = ioapic_suspend, + .resume = ioapic_resume, +}; + +static int __init ioapic_init_sysfs(void) +{ + struct sys_device * dev; + int i, size, error = 0; + + error = sysdev_class_register(&ioapic_sysdev_class); + if (error) + return error; + + for (i = 0; i < nr_ioapics; i++ ) { + size = sizeof(struct sys_device) + nr_ioapic_registers[i] + * sizeof(struct IO_APIC_route_entry); + mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL); + if (!mp_ioapic_data[i]) { + printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); + continue; + } + memset(mp_ioapic_data[i], 0, size); + dev = &mp_ioapic_data[i]->dev; + dev->id = i; + dev->cls = &ioapic_sysdev_class; + error = sysdev_register(dev); + if (error) { + kfree(mp_ioapic_data[i]); + mp_ioapic_data[i] = NULL; + printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); + continue; + } + } + + return 0; +} + +device_initcall(ioapic_init_sysfs); + /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration -------------------------------------------------------------------------- */ @@ -2334,7 +2452,8 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); } - printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + apic_printk(APIC_VERBOSE, KERN_INFO + "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); return apic_id; } @@ -2400,19 +2519,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a entry.vector = assign_irq_vector(irq); - Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " - "IRQ %d Mode:%i Active:%i)\n", ioapic, - mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); - - if (use_pci_vector() && !platform_legacy_irq(irq)) - irq = IO_APIC_VECTOR(irq); - if (edge_level) { - irq_desc[irq].handler = &ioapic_level_type; - } else { - irq_desc[irq].handler = &ioapic_edge_type; - } + apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry " + "(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic, + mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, + edge_level, active_high_low); - set_intr_gate(entry.vector, interrupt[irq]); + ioapic_register_intr(irq, entry.vector, edge_level); if (!ioapic && (irq < 16)) disable_8259A_irq(irq); diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index 3346657c3..8b2516039 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -56,6 +56,7 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex */ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) { + unsigned long i, max_long, bytes, bytes_updated; struct thread_struct * t = ¤t->thread; struct tss_struct * tss; unsigned long *bitmap; @@ -81,16 +82,37 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) /* * do it in the per-thread copy and in the TSS ... + * + * Disable preemption via get_cpu() - we must not switch away + * because the ->io_bitmap_max value must match the bitmap + * contents: */ + tss = &per_cpu(init_tss, get_cpu()); + set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); - tss = init_tss + get_cpu(); - if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */ - set_bitmap(tss->io_bitmap, from, num, !turn_on); - } else { - memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES); - tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */ - } + + /* + * Search for a (possibly new) maximum. This is simple and stupid, + * to keep it obviously correct: + */ + max_long = 0; + for (i = 0; i < IO_BITMAP_LONGS; i++) + if (t->io_bitmap_ptr[i] != ~0UL) + max_long = i; + + bytes = (max_long + 1) * sizeof(long); + bytes_updated = max(bytes, t->io_bitmap_max); + + t->io_bitmap_max = bytes; + + /* + * Sets the lazy trigger so that the next I/O operation will + * reload the correct bitmap. + */ + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; + put_cpu(); + return 0; } diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 355dc0eca..3d4e56312 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -3,435 +3,58 @@ * * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. + * This file contains the lowest level x86-specific interrupt + * entry, irq-stacks and irq statistics code. All the remaining + * irq logic is done by the generic kernel/irq/ code and + * by the x86-specific irq controller code. (e.g. i8259.c and + * io_apic.c.) */ -/* - * (mostly architecture independent, will move to kernel/irq.c in 2.5.) - * - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include -#include +#include #include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -/* - * Controller mappings for all interrupt sources: - */ -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - } -}; - -static void register_irq_proc (unsigned int irq); - -/* - * per-CPU IRQ handling stacks - */ -#ifdef CONFIG_4KSTACKS -union irq_ctx *hardirq_ctx[NR_CPUS]; -union irq_ctx *softirq_ctx[NR_CPUS]; -#endif - -/* - * Special irq handlers. - */ - -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ return IRQ_NONE; } -/* - * Generic no controller code - */ - -static void enable_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } -static void disable_none(unsigned int irq) { } -static void ack_none(unsigned int irq) -{ +#ifndef CONFIG_X86_LOCAL_APIC /* * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves, it doesn't deserve - * a generic callback i think. + * each architecture has to answer this themselves. */ -#ifdef CONFIG_X86 +void ack_bad_irq(unsigned int irq) +{ printk("unexpected IRQ trap at vector %02x\n", irq); -#ifdef CONFIG_X86_LOCAL_APIC - /* - * Currently unexpected vectors happen only on SMP and APIC. - * We _must_ ack these because every local APIC has only N - * irq slots per priority level, and a 'hanging, unacked' IRQ - * holds up an irq slot - in excessive cases (when multiple - * unexpected vectors occur) that might lock up the APIC - * completely. - */ - ack_APIC_irq(); -#endif -#endif } - -/* startup is the same as "enable", shutdown is same as "disable" */ -#define shutdown_none disable_none -#define end_none enable_none - -struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none -}; - -atomic_t irq_err_count; -#if defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) -atomic_t irq_mis_count; #endif +#ifdef CONFIG_4KSTACKS /* - * Generic, controller-independent functions: + * per-CPU IRQ handling contexts (thread information and stack) */ +union irq_ctx { + struct thread_info tinfo; + u32 stack[THREAD_SIZE/sizeof(u32)]; +}; -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - unsigned long flags; - - if (i == 0) { - seq_printf(p, " "); - for (j=0; jtypename); - seq_printf(p, " %s", action->name); - - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - - seq_putc(p, '\n'); -skip: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) { - seq_printf(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", nmi_count(j)); - seq_putc(p, '\n'); -#ifdef CONFIG_X86_LOCAL_APIC - seq_printf(p, "LOC: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); - seq_putc(p, '\n'); -#endif - seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); -#if defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) - seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); -#endif - } - return 0; -} - - - - -#ifdef CONFIG_SMP -inline void synchronize_irq(unsigned int irq) -{ - while (irq_desc[irq].status & IRQ_INPROGRESS) - cpu_relax(); -} +static union irq_ctx *hardirq_ctx[NR_CPUS]; +static union irq_ctx *softirq_ctx[NR_CPUS]; #endif -/* - * This should really return information about whether - * we should do bottom half handling etc. Right now we - * end up _always_ checking the bottom half, which is a - * waste of time and is not what some drivers would - * prefer. - */ -asmlinkage int handle_IRQ_event(unsigned int irq, - struct pt_regs *regs, struct irqaction *action) -{ - int status = 1; /* Force the "do bottom halves" bit */ - int retval = 0; - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - return retval; -} - -static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - struct irqaction *action; - - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { - printk(KERN_ERR "irq event %d: bogus return value %x\n", - irq, action_ret); - } else { - printk(KERN_ERR "irq %d: nobody cared!\n", irq); - } - dump_stack(); - printk(KERN_ERR "handlers:\n"); - action = desc->action; - do { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); - action = action->next; - } while (action); -} - -static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - static int count = 100; - - if (count) { - count--; - __report_bad_irq(irq, desc, action_ret); - } -} - -static int noirqdebug; - -static int __init noirqdebug_setup(char *str) -{ - noirqdebug = 1; - printk("IRQ lockup detection disabled\n"); - return 1; -} - -__setup("noirqdebug", noirqdebug_setup); - -/* - * If 99,900 of the previous 100,000 interrupts have not been handled then - * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to - * turn the IRQ off. - * - * (The other 100-of-100,000 interrupts may have been a correctly-functioning - * device sharing an IRQ with the failing one) - * - * Called under desc->lock - */ -static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - if (action_ret != IRQ_HANDLED) { - desc->irqs_unhandled++; - if (action_ret != IRQ_NONE) - report_bad_irq(irq, desc, action_ret); - } - - desc->irq_count++; - if (desc->irq_count < 100000) - return; - - desc->irq_count = 0; - if (desc->irqs_unhandled > 99900) { - /* - * The interrupt is stuck - */ - __report_bad_irq(irq, desc, action_ret); - /* - * Now kill the IRQ - */ - printk(KERN_EMERG "Disabling IRQ #%d\n", irq); - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - desc->irqs_unhandled = 0; -} - -/* - * 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. - */ - -inline void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/** - * 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. - */ - -void disable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} - -/** - * 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. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ -asmlinkage unsigned int do_IRQ(struct pt_regs regs) +fastcall unsigned int do_IRQ(struct pt_regs *regs) { - /* - * We ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * 0 return value means that this irq is already being - * handled by some other CPU. (or is disabled) - */ - int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code */ - irq_desc_t *desc = irq_desc + irq; - struct irqaction * action; - unsigned int status; + /* high bits used in ret_from_ code */ + int irq = regs->orig_eax & 0xff; +#ifdef CONFIG_4KSTACKS + union irq_ctx *curctx, *irqctx; + u32 *isp; +#endif irq_enter(); - #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than 1KB free? */ { @@ -446,682 +69,54 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs) } } #endif - kstat_this_cpu.irqs[irq]++; - spin_lock(&desc->lock); - desc->handler->ack(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - status |= IRQ_PENDING; /* we _want_ to handle it */ - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { - action = desc->action; - status &= ~IRQ_PENDING; /* we commit to handling */ - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; +#ifdef CONFIG_4KSTACKS - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (unlikely(!action)) - goto out; + curctx = (union irq_ctx *) current_thread_info(); + irqctx = hardirq_ctx[smp_processor_id()]; /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. + * this is where we switch to the IRQ stack. However, if we are + * already using the IRQ stack (because we interrupted a hardirq + * handler) we can't do that and just have to keep using the + * current stack (which is the irq stack already after all) */ -#ifdef CONFIG_4KSTACKS - - for (;;) { - irqreturn_t action_ret; - u32 *isp; - union irq_ctx * curctx; - union irq_ctx * irqctx; - - curctx = (union irq_ctx *) current_thread_info(); - irqctx = hardirq_ctx[smp_processor_id()]; - - spin_unlock(&desc->lock); + if (curctx != irqctx) { + int arg1, arg2, ebx; - /* - * this is where we switch to the IRQ stack. However, if we are already using - * the IRQ stack (because we interrupted a hardirq handler) we can't do that - * and just have to keep using the current stack (which is the irq stack already - * after all) - */ - - if (curctx == irqctx) - action_ret = handle_IRQ_event(irq, ®s, action); - else { - /* build the stack frame on the IRQ stack */ - isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); - irqctx->tinfo.task = curctx->tinfo.task; - irqctx->tinfo.previous_esp = current_stack_pointer(); - - *--isp = (u32) action; - *--isp = (u32) ®s; - *--isp = (u32) irq; - - asm volatile( - " xchgl %%ebx,%%esp \n" - " call handle_IRQ_event \n" - " xchgl %%ebx,%%esp \n" - : "=a"(action_ret) - : "b"(isp) - : "memory", "cc", "edx", "ecx" - ); - - - } - spin_lock(&desc->lock); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); - if (curctx != irqctx) - irqctx->tinfo.task = NULL; - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } - -#else - - for (;;) { - irqreturn_t action_ret; - - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, ®s, action); + /* build the stack frame on the IRQ stack */ + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); + irqctx->tinfo.task = curctx->tinfo.task; + irqctx->tinfo.previous_esp = current_stack_pointer; - spin_lock(&desc->lock); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } + asm volatile( + " xchgl %%ebx,%%esp \n" + " call __do_IRQ \n" + " movl %%ebx,%%esp \n" + : "=a" (arg1), "=d" (arg2), "=b" (ebx) + : "0" (irq), "1" (regs), "2" (isp) + : "memory", "cc", "ecx" + ); + } else #endif - desc->status &= ~IRQ_INPROGRESS; - -out: - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - desc->handler->end(irq); - spin_unlock(&desc->lock); + __do_IRQ(irq, regs); irq_exit(); return 1; } -int can_request_irq(unsigned int irq, unsigned long irqflags) -{ - struct irqaction *action; - - if (irq >= NR_IRQS) - return 0; - action = irq_desc[irq].action; - if (action) { - if (irqflags & action->flags & SA_SHIRQ) - action = NULL; - } - return !action; -} - -/** - * 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 - * - */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction * action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); - } -#endif - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_ATOMIC); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * 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 must not be called from interrupt context. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - desc->handler->shutdown(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; - } -} - -EXPORT_SYMBOL(free_irq); - -/* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that - * comes in on to an unassigned handler will get stuck - * with "IRQ_WAITING" cleared and the interrupt - * disabled. - */ - -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. - * - */ - -unsigned long probe_irq_on(void) -{ - unsigned int i; - irq_desc_t *desc; - unsigned long val; - unsigned long delay; - - down(&probe_sem); - /* - * something may have generated an irq long ago and we want to - * flush such a longstanding irq before considering it as spurious. - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!irq_desc[i].action) - irq_desc[i].handler->startup(i); - spin_unlock_irq(&desc->lock); - } - - /* Wait for longstanding interrupts to trigger. */ - for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ barrier(); - - /* - * enable any unassigned irqs - * (we must startup again here because if a longstanding irq - * happened in the previous stage, it may have masked itself) - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!desc->action) { - desc->status |= IRQ_AUTODETECT | IRQ_WAITING; - if (desc->handler->startup(i)) - desc->status |= IRQ_PENDING; - } - spin_unlock_irq(&desc->lock); - } - - /* - * Wait for spurious interrupts to trigger - */ - for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ barrier(); - - /* - * Now filter out any obviously spurious interrupts - */ - val = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - /* It triggered already - consider it spurious. */ - if (!(status & IRQ_WAITING)) { - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } else - if (i < 32) - val |= 1 << i; - } - spin_unlock_irq(&desc->lock); - } - - return val; -} - -EXPORT_SYMBOL(probe_irq_on); - -/* - * 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. - */ -unsigned int probe_irq_mask(unsigned long val) -{ - int i; - unsigned int mask; - - mask = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (i < 16 && !(status & IRQ_WAITING)) - mask |= 1 << i; - - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - return mask & val; -} - -/* - * 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. - */ - -int probe_irq_off(unsigned long val) -{ - int i, irq_found, nr_irqs; - - nr_irqs = 0; - irq_found = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = i; - nr_irqs++; - } - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - if (nr_irqs > 1) - irq_found = -irq_found; - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - unsigned long flags; - struct irqaction *old, **p; - irq_desc_t *desc = irq_desc + irq; - - if (desc->handler == &no_irq_type) - return -ENOSYS; - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - desc->handler->startup(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - register_irq_proc(irq); - return 0; -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; - -#ifdef CONFIG_SMP - -static struct proc_dir_entry *smp_affinity_entry[NR_IRQS]; - -cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; - -static int irq_affinity_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int irq_affinity_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (long)data, full_count = count, err; - cpumask_t new_value, tmp; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - /* - * 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. - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; - - irq_affinity[irq] = new_value; - irq_desc[irq].handler->set_affinity(irq, - cpumask_of_cpu(first_cpu(new_value))); - - return full_count; -} - -#endif - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data; - unsigned long full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || - irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef 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; - } - - smp_affinity_entry[irq] = entry; - } -#endif -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); -} - - #ifdef CONFIG_4KSTACKS + /* * These should really be __section__(".bss.page_aligned") as well, but * gcc's 3.0 and earlier don't handle that correctly. */ -static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); -static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); +static char softirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); + +static char hardirq_stack[NR_CPUS * THREAD_SIZE] + __attribute__((__aligned__(THREAD_SIZE))); /* * allocate per-cpu stacks for hardirq and for softirq processing @@ -1173,12 +168,11 @@ asmlinkage void do_softirq(void) curctx = current_thread_info(); irqctx = softirq_ctx[smp_processor_id()]; irqctx->tinfo.task = curctx->task; - irqctx->tinfo.previous_esp = current_stack_pointer(); + irqctx->tinfo.previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); - asm volatile( " xchgl %%ebx,%%esp \n" " call __do_softirq \n" @@ -1194,3 +188,71 @@ asmlinkage void do_softirq(void) EXPORT_SYMBOL(do_softirq); #endif + +/* + * Interrupt statistics: + */ + +atomic_t irq_err_count; + +/* + * /proc/interrupts printing: + */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *) v, j; + struct irqaction * action; + unsigned long flags; + + if (i == 0) { + seq_printf(p, " "); + for (j=0; jtypename); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + seq_printf(p, "%10u ", nmi_count(j)); + seq_putc(p, '\n'); +#ifdef CONFIG_X86_LOCAL_APIC + seq_printf(p, "LOC: "); + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + seq_printf(p, "%10u ", + irq_stat[j].apic_timer_irqs); + seq_putc(p, '\n'); +#endif + seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); +#if defined(CONFIG_X86_IO_APIC) + seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); +#endif + } + return 0; +} diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 4d066cc30..b9eb1a95b 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -42,6 +42,7 @@ static struct pt_regs jprobe_saved_regs; static long *jprobe_saved_esp; /* copy of the kernel stack at the probe fire time */ static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; +void jprobe_return_end(void); /* * returns non-zero if opcode modifies the interrupt flag. @@ -58,9 +59,14 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode) return 0; } -void arch_prepare_kprobe(struct kprobe *p) +int arch_prepare_kprobe(struct kprobe *p) +{ + memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + return 0; +} + +void arch_remove_kprobe(struct kprobe *p) { - memcpy(p->insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); } static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) @@ -73,7 +79,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { regs->eflags |= TF_MASK; regs->eflags &= ~IF_MASK; - regs->eip = (unsigned long)&p->insn; + regs->eip = (unsigned long)&p->ainsn.insn; } /* @@ -111,6 +117,11 @@ static inline int kprobe_handler(struct pt_regs *regs) p = get_kprobe(addr); if (!p) { unlock_kprobes(); + if (regs->eflags & VM_MASK) { + /* We are in virtual-8086 mode. Return 0 */ + goto no_kprobe; + } + if (*addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right @@ -153,7 +164,7 @@ static inline int kprobe_handler(struct pt_regs *regs) * instruction. To avoid the SMP problems that can occur when we * temporarily put back the original opcode to single-step, we * single-stepped a copy of the instruction. The address of this - * copy is p->insn. + * copy is p->ainsn.insn. * * This function prepares to return from the post-single-step * interrupt. We have to fix up the stack as follows: @@ -173,10 +184,10 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; - unsigned long copy_eip = (unsigned long)&p->insn; + unsigned long copy_eip = (unsigned long)&p->ainsn.insn; unsigned long orig_eip = (unsigned long)p->addr; - switch (p->insn[0]) { + switch (p->ainsn.insn[0]) { case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); *tos |= kprobe_old_eflags; @@ -185,13 +196,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs) *tos = orig_eip + (*tos - copy_eip); break; case 0xff: - if ((p->insn[1] & 0x30) == 0x10) { + if ((p->ainsn.insn[1] & 0x30) == 0x10) { /* call absolute, indirect */ /* Fix return addr; eip is correct. */ next_eip = regs->eip; *tos = orig_eip + (*tos - copy_eip); - } else if (((p->insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ - ((p->insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ + } else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ + ((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ /* eip is correct. */ next_eip = regs->eip; } @@ -315,12 +326,12 @@ void jprobe_return(void) { preempt_enable_no_resched(); asm volatile (" xchgl %%ebx,%%esp \n" - " int3 \n"::"b" + " int3 \n" + " .globl jprobe_return_end \n" + " jprobe_return_end: \n" + " nop \n"::"b" (jprobe_saved_esp):"memory"); } -void jprobe_return_end(void) -{ -}; int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c index 038d30034..bb50afbee 100644 --- a/arch/i386/kernel/ldt.c +++ b/arch/i386/kernel/ldt.c @@ -142,12 +142,17 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) err = -EFAULT; up(&mm->context.sem); if (err < 0) - return err; + goto error_return; if (size != bytecount) { /* zero-fill the rest */ - clear_user(ptr+size, bytecount-size); + if (clear_user(ptr+size, bytecount-size) != 0) { + err = -EFAULT; + goto error_return; + } } return bytecount; +error_return: + return err; } static int read_default_ldt(void __user * ptr, unsigned long bytecount) diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 12ccd65bd..4de753804 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -69,7 +69,8 @@ * Thanks to Stuart Swales for pointing out this bug. */ - +//#define DEBUG /* pr_debug */ +#include #include #include #include @@ -88,12 +89,6 @@ MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); #define MICROCODE_VERSION "1.14" -#define MICRO_DEBUG 0 -#if MICRO_DEBUG -#define dprintk(x...) printk(KERN_INFO x) -#else -#define dprintk(x...) -#endif #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ @@ -172,7 +167,7 @@ static void collect_cpu_info (void *unused) __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); /* get the current revision from MSR 0x8B */ rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); - dprintk("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", + pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", uci->sig, uci->pf, uci->rev); } @@ -180,22 +175,22 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - dprintk("Microcode Found.\n"); - dprintk(" Header Revision 0x%x\n", mc_header->hdrver); - dprintk(" Loader Revision 0x%x\n", mc_header->ldrver); - dprintk(" Revision 0x%x \n", mc_header->rev); - dprintk(" Date %x/%x/%x\n", + pr_debug("Microcode Found.\n"); + pr_debug(" Header Revision 0x%x\n", mc_header->hdrver); + pr_debug(" Loader Revision 0x%x\n", mc_header->ldrver); + pr_debug(" Revision 0x%x \n", mc_header->rev); + pr_debug(" Date %x/%x/%x\n", ((mc_header->date >> 24 ) & 0xff), ((mc_header->date >> 16 ) & 0xff), (mc_header->date & 0xFFFF)); - dprintk(" Signature 0x%x\n", sig); - dprintk(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n", + pr_debug(" Signature 0x%x\n", sig); + pr_debug(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n", ((sig >> 12) & 0x3), ((sig >> 8) & 0xf), ((sig >> 4) & 0xf), ((sig & 0xf))); - dprintk(" Processor Flags 0x%x\n", pf); - dprintk(" Checksum 0x%x\n", cksum); + pr_debug(" Processor Flags 0x%x\n", pf); + pr_debug(" Checksum 0x%x\n", cksum); if (mc_header->rev < uci->rev) { printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" @@ -209,7 +204,7 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he goto out; } - dprintk("microcode: CPU%d found a matching microcode update with " + pr_debug("microcode: CPU%d found a matching microcode update with " " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); uci->cksum = cksum; uci->pf = pf; /* keep the original mc pf for cksum calculation */ @@ -485,6 +480,7 @@ static struct file_operations microcode_fops = { static struct miscdevice microcode_dev = { .minor = MICROCODE_MINOR, .name = "microcode", + .devfs_name = "cpu/microcode", .fops = µcode_fops, }; diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 41cb82604..0c8026c2c 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -808,7 +808,6 @@ void __init find_smp_config (void) smp_scan_config(address, 0x400); } - /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ @@ -996,6 +995,12 @@ void __init mp_config_acpi_legacy_irqs (void) mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); + /* + * ES7000 has no legacy identity mappings + */ + if (es7000_plat) + return; + /* * Locate the IOAPIC that manages the ISA IRQs (0-15). */ @@ -1049,9 +1054,7 @@ void __init mp_config_acpi_legacy_irqs (void) } } -int (*platform_rename_gsi)(int ioapic, int gsi); - -void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) +int mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { int ioapic = -1; int ioapic_pin = 0; @@ -1060,19 +1063,19 @@ void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) #ifdef CONFIG_ACPI_BUS /* Don't set up the ACPI SCI because it's already set up */ if (acpi_fadt.sci_int == gsi) - return; + return gsi; #endif ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); - return; + return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - if (platform_rename_gsi) - gsi = platform_rename_gsi(ioapic, gsi); + if (ioapic_renumber_irq) + gsi = ioapic_renumber_irq(ioapic, gsi); /* * Avoid pin reprogramming. PRTs typically include entries @@ -1085,12 +1088,12 @@ void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); - return; + return gsi; } if ((1< #include #include +#include #include #include #include #include +#include "mach_traps.h" + unsigned int nmi_watchdog = NMI_NONE; +extern int unknown_nmi_panic; static unsigned int nmi_hz = HZ; static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ static unsigned int nmi_p4_cccr_val; @@ -376,7 +380,13 @@ static int setup_p4_watchdog(void) clear_msr_range(0x3F1, 2); /* MSR 0x3F0 seems to have a default value of 0xFC00, but current docs doesn't fully define it, so leave it alone for now. */ - clear_msr_range(0x3A0, 31); + if (boot_cpu_data.x86_model >= 0x3) { + /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */ + clear_msr_range(0x3A0, 26); + clear_msr_range(0x3BC, 3); + } else { + clear_msr_range(0x3A0, 31); + } clear_msr_range(0x3C0, 6); clear_msr_range(0x3C8, 6); clear_msr_range(0x3E0, 2); @@ -426,8 +436,6 @@ void setup_apic_nmi_watchdog (void) nmi_active = 1; } -static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; - /* * the best way to detect whether a CPU has a 'hard lockup' problem * is to check it's local APIC timer IRQ counts. If they are not @@ -459,6 +467,8 @@ void touch_nmi_watchdog (void) alert_counter[i] = 0; } +extern void die_nmi(struct pt_regs *, const char *msg); + void nmi_watchdog_tick (struct pt_regs * regs) { @@ -477,21 +487,8 @@ void nmi_watchdog_tick (struct pt_regs * regs) * wait a few IRQs (5 seconds) before doing the oops ... */ alert_counter[cpu]++; - if (alert_counter[cpu] == 5*nmi_hz) { - spin_lock(&nmi_print_lock); - /* - * We are in trouble anyway, lets at least try - * to get a message out. - */ - bust_spinlocks(1); - printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip); - show_registers(regs); - printk("console shuts up ...\n"); - console_silent(); - spin_unlock(&nmi_print_lock); - bust_spinlocks(0); - do_exit(SIGSEGV); - } + if (alert_counter[cpu] == 5*nmi_hz) + die_nmi(regs, "NMI Watchdog detected LOCKUP"); } else { last_irq_sums[cpu] = sum; alert_counter[cpu] = 0; @@ -518,6 +515,49 @@ void nmi_watchdog_tick (struct pt_regs * regs) } } +#ifdef CONFIG_SYSCTL + +static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) +{ + unsigned char reason = get_nmi_reason(); + char buf[64]; + + if (!(reason & 0xc0)) { + sprintf(buf, "NMI received for unknown reason %02x\n", reason); + die_nmi(regs, buf); + } + return 0; +} + +/* + * proc handler for /proc/sys/kernel/unknown_nmi_panic + */ +int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file, + void __user *buffer, size_t *length, loff_t *ppos) +{ + int old_state; + + old_state = unknown_nmi_panic; + proc_dointvec(table, write, file, buffer, length, ppos); + if (!!old_state == !!unknown_nmi_panic) + return 0; + + if (unknown_nmi_panic) { + if (reserve_lapic_nmi() < 0) { + unknown_nmi_panic = 0; + return -EBUSY; + } else { + set_nmi_callback(unknown_nmi_panic_callback); + } + } else { + release_lapic_nmi(); + unset_nmi_callback(); + } + return 0; +} + +#endif + EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(reserve_lapic_nmi); diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c index ed41eebf0..38c762dab 100644 --- a/arch/i386/kernel/numaq.c +++ b/arch/i386/kernel/numaq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include /* These are needed before the pgdat's are created */ diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c index 10dc6b79d..982fe8c2b 100644 --- a/arch/i386/kernel/pci-dma.c +++ b/arch/i386/kernel/pci-dma.c @@ -13,17 +13,40 @@ #include #include +struct dma_coherent_mem { + void *virt_base; + u32 device_base; + int size; + int flags; + unsigned long *bitmap; +}; + void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int gfp) { void *ret; + struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; + int order = get_order(size); /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + if (mem) { + int page = bitmap_find_free_region(mem->bitmap, mem->size, + order); + if (page >= 0) { + *dma_handle = mem->device_base + (page << PAGE_SHIFT); + ret = mem->virt_base + (page << PAGE_SHIFT); + memset(ret, 0, size); + return ret; + } + if (mem->flags & DMA_MEMORY_EXCLUSIVE) + return NULL; + } + if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); + ret = (void *)__get_free_pages(gfp, order); if (ret != NULL) { memset(ret, 0, size); @@ -35,5 +58,89 @@ void *dma_alloc_coherent(struct device *dev, size_t size, void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { - free_pages((unsigned long)vaddr, get_order(size)); + struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; + int order = get_order(size); + + if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { + int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; + + bitmap_release_region(mem->bitmap, page, order); + } else + free_pages((unsigned long)vaddr, order); +} + +int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, + dma_addr_t device_addr, size_t size, int flags) +{ + void __iomem *mem_base; + int pages = size >> PAGE_SHIFT; + int bitmap_size = (pages + 31)/32; + + if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) + goto out; + if (!size) + goto out; + if (dev->dma_mem) + goto out; + + /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ + + mem_base = ioremap(bus_addr, size); + if (!mem_base) + goto out; + + dev->dma_mem = kmalloc(GFP_KERNEL, sizeof(struct dma_coherent_mem)); + if (!dev->dma_mem) + goto out; + memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem)); + dev->dma_mem->bitmap = kmalloc(GFP_KERNEL, bitmap_size); + if (!dev->dma_mem->bitmap) + goto free1_out; + memset(dev->dma_mem->bitmap, 0, bitmap_size); + + dev->dma_mem->virt_base = mem_base; + dev->dma_mem->device_base = device_addr; + dev->dma_mem->size = pages; + dev->dma_mem->flags = flags; + + if (flags & DMA_MEMORY_MAP) + return DMA_MEMORY_MAP; + + return DMA_MEMORY_IO; + + free1_out: + kfree(dev->dma_mem->bitmap); + out: + return 0; +} +EXPORT_SYMBOL(dma_declare_coherent_memory); + +void dma_release_declared_memory(struct device *dev) +{ + struct dma_coherent_mem *mem = dev->dma_mem; + + if(!mem) + return; + dev->dma_mem = NULL; + kfree(mem->bitmap); + kfree(mem); +} +EXPORT_SYMBOL(dma_release_declared_memory); + +void *dma_mark_declared_memory_occupied(struct device *dev, + dma_addr_t device_addr, size_t size) +{ + struct dma_coherent_mem *mem = dev->dma_mem; + int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT; + int pos, err; + + if (!mem) + return ERR_PTR(-EINVAL); + + pos = (device_addr - mem->device_base) >> PAGE_SHIFT; + err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); + if (err != 0) + return ERR_PTR(err); + return mem->virt_base + (pos << PAGE_SHIFT); } +EXPORT_SYMBOL(dma_mark_declared_memory_occupied); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 75b200985..7efce8e4c 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -57,6 +57,9 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); int hlt_counter; +unsigned long boot_option_idle_override = 0; +EXPORT_SYMBOL(boot_option_idle_override); + /* * Return saved PC of a blocked thread. */ @@ -96,6 +99,8 @@ void default_idle(void) safe_halt(); else local_irq_enable(); + } else { + cpu_relax(); } } @@ -142,13 +147,21 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); + idle = pm_idle; if (!idle) idle = default_idle; irq_stat[smp_processor_id()].idle_timestamp = jiffies; idle(); + rcu_read_unlock(); } schedule(); } @@ -183,18 +196,13 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c) printk("monitor/mwait feature present.\n"); /* * Skip, if setup has overridden idle. - * Also, take care of system with asymmetric CPUs. - * Use, mwait_idle only if all cpus support it. - * If not, we fallback to default_idle() + * One CPU supports mwait => All CPUs supports mwait */ if (!pm_idle) { printk("using mwait in idle threads.\n"); pm_idle = mwait_idle; } - return; } - pm_idle = default_idle; - return; } static int __init idle_setup (char *str) @@ -211,6 +219,7 @@ static int __init idle_setup (char *str) pm_idle = default_idle; } + boot_option_idle_override = 1; return 1; } @@ -227,7 +236,8 @@ void show_regs(struct pt_regs * regs) if (regs->xcs & 3) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); - printk(" EFLAGS: %08lx %s (%s)\n",regs->eflags, print_tainted(),UTS_RELEASE); + printk(" EFLAGS: %08lx %s (%s)\n", + regs->eflags, print_tainted(), system_utsname.release); printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", regs->eax,regs->ebx,regs->ecx,regs->edx); printk("ESI: %08lx EDI: %08lx EBP: %08lx", @@ -294,13 +304,22 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) void exit_thread(void) { struct task_struct *tsk = current; + struct thread_struct *t = &tsk->thread; /* The process may have allocated an io port bitmap... nuke it. */ - if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) { + if (unlikely(NULL != t->io_bitmap_ptr)) { int cpu = get_cpu(); - struct tss_struct *tss = init_tss + cpu; - kfree(tsk->thread.io_bitmap_ptr); - tsk->thread.io_bitmap_ptr = NULL; + struct tss_struct *tss = &per_cpu(init_tss, cpu); + + kfree(t->io_bitmap_ptr); + t->io_bitmap_ptr = NULL; + /* + * Careful, clear this in the TSS too: + */ + memset(tss->io_bitmap, 0xff, tss->io_bitmap_max); + t->io_bitmap_max = 0; + tss->io_bitmap_owner = NULL; + tss->io_bitmap_max = 0; tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; put_cpu(); } @@ -332,7 +351,7 @@ void release_thread(struct task_struct *dead_task) } } - release_x86_irqs(dead_task); + release_vm86_irqs(dead_task); } /* @@ -356,7 +375,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, *childregs = *regs; childregs->eax = 0; childregs->esp = esp; - p->set_child_tid = p->clear_child_tid = NULL; p->thread.esp = (unsigned long) childregs; p->thread.esp0 = (unsigned long) (childregs+1); @@ -369,8 +387,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, tsk = current; if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) { p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); - if (!p->thread.io_bitmap_ptr) + if (!p->thread.io_bitmap_ptr) { + p->thread.io_bitmap_max = 0; return -ENOMEM; + } memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, IO_BITMAP_BYTES); } @@ -401,8 +421,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, err = 0; out: - if (err && p->thread.io_bitmap_ptr) + if (err && p->thread.io_bitmap_ptr) { kfree(p->thread.io_bitmap_ptr); + p->thread.io_bitmap_max = 0; + } return err; } @@ -467,6 +489,37 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) return 1; } +static inline void +handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) +{ + if (!next->io_bitmap_ptr) { + /* + * Disable the bitmap via an invalid offset. We still cache + * the previous bitmap owner and the IO bitmap contents: + */ + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; + return; + } + if (likely(next == tss->io_bitmap_owner)) { + /* + * Previous owner of the bitmap (hence the bitmap content) + * matches the next task, we dont have to do anything but + * to set a valid offset in the TSS: + */ + tss->io_bitmap_base = IO_BITMAP_OFFSET; + return; + } + /* + * Lazy TSS's I/O bitmap copy. We set an invalid offset here + * and we let the task to get a GPF in case an I/O instruction + * is performed. The handler of the GPF will verify that the + * faulting task has a valid I/O bitmap and, it true, does the + * real copy and restart the instruction. This will save us + * redundant copies when the currently switched task does not + * perform any I/O during its timeslice. + */ + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; +} /* * This special macro can be used to load a debugging register */ @@ -507,7 +560,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); - struct tss_struct *tss = init_tss + cpu; + struct tss_struct *tss = &per_cpu(init_tss, cpu); /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ @@ -551,28 +604,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas loaddebug(next, 7); } - if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { - if (next->io_bitmap_ptr) { - /* - * 4 cachelines copy ... not good, but not that - * bad either. Anyone got something better? - * This only affects processes which use ioperm(). - * [Putting the TSSs into 4k-tlb mapped regions - * and playing VM tricks to switch the IO bitmap - * is not really acceptable.] - */ - memcpy(tss->io_bitmap, next->io_bitmap_ptr, - IO_BITMAP_BYTES); - tss->io_bitmap_base = IO_BITMAP_OFFSET; - } else - /* - * a bitmap offset pointing outside of the TSS limit - * causes a nicely controllable SIGSEGV if a process - * tries to use a port IO instruction. The first - * sys_ioperm() call sets up the bitmap properly. - */ - tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; - } + if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) + handle_io_bitmap(next, tss); + return prev_p; } @@ -593,7 +627,7 @@ asmlinkage int sys_clone(struct pt_regs regs) child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } /* @@ -628,7 +662,9 @@ asmlinkage int sys_execve(struct pt_regs regs) (char __user * __user *) regs.edx, ®s); if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); /* Make sure we don't return using sysenter.. */ set_thread_flag(TIF_IRET); } diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 0cf2f1187..2aede9894 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -138,6 +138,28 @@ static unsigned long getreg(struct task_struct *child, return retval; } +static void set_singlestep(struct task_struct *child) +{ + long eflags; + + set_tsk_thread_flag(child, TIF_SINGLESTEP); + eflags = get_stack_long(child, EFL_OFFSET); + put_stack_long(child, EFL_OFFSET, eflags | TRAP_FLAG); + child->ptrace |= PT_DTRACE; +} + +static void clear_singlestep(struct task_struct *child) +{ + if (child->ptrace & PT_DTRACE) { + long eflags; + + clear_tsk_thread_flag(child, TIF_SINGLESTEP); + eflags = get_stack_long(child, EFL_OFFSET); + put_stack_long(child, EFL_OFFSET, eflags & ~TRAP_FLAG); + child->ptrace &= ~PT_DTRACE; + } +} + /* * Called by kernel/ptrace.c when detaching.. * @@ -145,10 +167,7 @@ static unsigned long getreg(struct task_struct *child, */ void ptrace_disable(struct task_struct *child) { - long tmp; - - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); + clear_singlestep(child); } /* @@ -343,6 +362,36 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if(addr < (long) &dummy->u_debugreg[4] && ((unsigned long) data) >= TASK_SIZE-3) break; + /* Sanity-check data. Take one half-byte at once with + * check = (val >> (16 + 4*i)) & 0xf. It contains the + * R/Wi and LENi bits; bits 0 and 1 are R/Wi, and bits + * 2 and 3 are LENi. Given a list of invalid values, + * we do mask |= 1 << invalid_value, so that + * (mask >> check) & 1 is a correct test for invalid + * values. + * + * R/Wi contains the type of the breakpoint / + * watchpoint, LENi contains the length of the watched + * data in the watchpoint case. + * + * The invalid values are: + * - LENi == 0x10 (undefined), so mask |= 0x0f00. + * - R/Wi == 0x10 (break on I/O reads or writes), so + * mask |= 0x4444. + * - R/Wi == 0x00 && LENi != 0x00, so we have mask |= + * 0x1110. + * + * Finally, mask = 0x0f00 | 0x4444 | 0x1110 == 0x5f54. + * + * See the Intel Manual "System Programming Guide", + * 15.2.4 + * + * Note that LENi == 0x10 is defined on x86_64 in long + * mode (i.e. even for 32-bit userspace software, but + * 64-bit kernel), so the x86_64 mask value is 0x5454. + * See the AMD manual no. 24593 (AMD64 System + * Programming)*/ + if(addr == (long) &dummy->u_debugreg[7]) { data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) @@ -357,10 +406,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - long tmp; - + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: /* restart after signal. */ ret = -EIO; if ((unsigned long) data > _NSIG) break; @@ -371,52 +418,38 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } child->exit_code = data; - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET,tmp); + /* make sure the single step bit is not set. */ + clear_singlestep(child); wake_up_process(child); ret = 0; break; - } /* * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - long tmp; - + case PTRACE_KILL: ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); + clear_singlestep(child); wake_up_process(child); break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long tmp; + case PTRACE_SINGLESTEP: /* set the trap flag. */ ret = -EIO; if ((unsigned long) data > _NSIG) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); + set_singlestep(child); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); ret = 0; break; - } case PTRACE_DETACH: /* detach a process that was attached. */ @@ -535,14 +568,15 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit) audit_syscall_exit(current, regs->eax); } - if (!test_thread_flag(TIF_SYSCALL_TRACE)) + if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SINGLESTEP)) return; if (!(current->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && + !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 06974254c..dd06362cd 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -137,7 +137,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { { } }; -static int reboot_init(void) +static int __init reboot_init(void) { dmi_check_system(reboot_dmi_table); return 0; @@ -331,13 +331,10 @@ void machine_restart(char * __unused) * other OSs see a clean IRQ state. */ smp_send_stop(); -#elif defined(CONFIG_X86_LOCAL_APIC) - if (cpu_has_apic) { - local_irq_disable(); - disable_local_APIC(); - local_irq_enable(); - } -#endif +#endif /* CONFIG_SMP */ + + lapic_shutdown(); + #ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif @@ -373,6 +370,8 @@ EXPORT_SYMBOL(machine_halt); void machine_power_off(void) { + lapic_shutdown(); + if (efi_enabled) efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); if (pm_power_off) diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c index 1cde4145c..df3342e3b 100644 --- a/arch/i386/kernel/scx200.c +++ b/arch/i386/kernel/scx200.c @@ -22,9 +22,47 @@ MODULE_LICENSE("GPL"); unsigned scx200_gpio_base = 0; long scx200_gpio_shadow[2]; +static struct pci_device_id scx200_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, + { }, +}; +MODULE_DEVICE_TABLE(pci,scx200_tbl); + +static int __devinit scx200_probe(struct pci_dev *, const struct pci_device_id *); + +static struct pci_driver scx200_pci_driver = { + .name = "scx200", + .id_table = scx200_tbl, + .probe = scx200_probe, +}; + spinlock_t scx200_gpio_lock = SPIN_LOCK_UNLOCKED; static spinlock_t scx200_gpio_config_lock = SPIN_LOCK_UNLOCKED; +static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int bank; + unsigned base; + + base = pci_resource_start(pdev, 0); + printk(KERN_INFO NAME ": GPIO base 0x%x\n", base); + + if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) { + printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n"); + return -EBUSY; + } + + scx200_gpio_base = base; + + /* read the current values driven on the GPIO signals */ + for (bank = 0; bank < 2; ++bank) + scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank); + + return 0; + +} + u32 scx200_gpio_configure(int index, u32 mask, u32 bits) { u32 config, new_config; @@ -77,39 +115,14 @@ void scx200_gpio_dump(unsigned index) int __init scx200_init(void) { - struct pci_dev *bridge; - int bank; - unsigned base; - printk(KERN_INFO NAME ": NatSemi SCx200 Driver\n"); - if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SCx200_BRIDGE, - NULL)) == NULL - && (bridge = pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SC1100_BRIDGE, - NULL)) == NULL) - return -ENODEV; - - base = pci_resource_start(bridge, 0); - printk(KERN_INFO NAME ": GPIO base 0x%x\n", base); - - if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) { - printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n"); - return -EBUSY; - } - - scx200_gpio_base = base; - - /* read the current values driven on the GPIO signals */ - for (bank = 0; bank < 2; ++bank) - scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank); - - return 0; + return pci_module_init(&scx200_pci_driver); } void __exit scx200_cleanup(void) { + pci_unregister_driver(&scx200_pci_driver); release_region(scx200_gpio_base, SCx200_GPIO_SIZE); } diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c index 073912cfc..be61aa8af 100644 --- a/arch/i386/kernel/semaphore.c +++ b/arch/i386/kernel/semaphore.c @@ -49,12 +49,12 @@ * we cannot lose wakeup events. */ -asmlinkage void __up(struct semaphore *sem) +fastcall void __up(struct semaphore *sem) { wake_up(&sem->wait); } -asmlinkage void __sched __down(struct semaphore * sem) +fastcall void __sched __down(struct semaphore * sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); @@ -91,7 +91,7 @@ asmlinkage void __sched __down(struct semaphore * sem) tsk->state = TASK_RUNNING; } -asmlinkage int __sched __down_interruptible(struct semaphore * sem) +fastcall int __sched __down_interruptible(struct semaphore * sem) { int retval = 0; struct task_struct *tsk = current; @@ -154,7 +154,7 @@ asmlinkage int __sched __down_interruptible(struct semaphore * sem) * single "cmpxchg" without failure cases, * but then it wouldn't work on a 386. */ -asmlinkage int __down_trylock(struct semaphore * sem) +fastcall int __down_trylock(struct semaphore * sem) { int sleepers; unsigned long flags; @@ -183,9 +183,9 @@ asmlinkage int __down_trylock(struct semaphore * sem) * need to convert that sequence back into the C sequence when * there is contention on the semaphore. * - * %ecx contains the semaphore pointer on entry. Save the C-clobbered - * registers (%eax, %edx and %ecx) except %eax when used as a return - * value.. + * %eax contains the semaphore pointer on entry. Save the C-clobbered + * registers (%eax, %edx and %ecx) except %eax whish is either a return + * value or just clobbered.. */ asm( ".section .sched.text\n" @@ -196,13 +196,11 @@ asm( "pushl %ebp\n\t" "movl %esp,%ebp\n\t" #endif - "pushl %eax\n\t" "pushl %edx\n\t" "pushl %ecx\n\t" "call __down\n\t" "popl %ecx\n\t" "popl %edx\n\t" - "popl %eax\n\t" #if defined(CONFIG_FRAME_POINTER) "movl %ebp,%esp\n\t" "popl %ebp\n\t" @@ -257,13 +255,11 @@ asm( ".align 4\n" ".globl __up_wakeup\n" "__up_wakeup:\n\t" - "pushl %eax\n\t" "pushl %edx\n\t" "pushl %ecx\n\t" "call __up\n\t" "popl %ecx\n\t" "popl %edx\n\t" - "popl %eax\n\t" "ret" ); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 375fd0761..19827c0c5 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -49,6 +49,7 @@ #include #include #include "setup_arch_pre.h" +#include /* This value is set up by the early boot code to point to the value immediately after the boot time page tables. It contains a *physical* @@ -218,9 +219,14 @@ static struct resource standard_io_resources[] = { { .end = 0x0021, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { - .name = "timer", + .name = "timer0", .start = 0x0040, - .end = 0x005f, + .end = 0x0043, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "timer1", + .start = 0x0050, + .end = 0x0053, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "keyboard", @@ -809,6 +815,14 @@ static void __init parse_cmdline_early (char ** cmdline_p) if (c == ' ' && !memcmp(from, "highmem=", 8)) highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT; + /* + * vmalloc=size forces the vmalloc area to be exactly 'size' + * bytes. This can be used to increase (or decrease) the + * vmalloc area - the default is 128m. + */ + if (c == ' ' && !memcmp(from, "vmalloc=", 8)) + __VMALLOC_RESERVE = memparse(from+8, &from); + c = *(from++); if (!c) break; @@ -991,6 +1005,17 @@ static void __init register_bootmem_low_pages(unsigned long max_low_pfn) } } +/* + * workaround for Dell systems that neglect to reserve EBDA + */ +static void __init reserve_ebda_region(void) +{ + unsigned int addr; + addr = get_bios_ebda(); + if (addr) + reserve_bootmem(addr, PAGE_SIZE); +} + static unsigned long __init setup_memory(void) { unsigned long bootmap_size, start_pfn, max_low_pfn; @@ -1037,6 +1062,9 @@ static unsigned long __init setup_memory(void) */ reserve_bootmem(0, PAGE_SIZE); + /* reserve EBDA region, it's a 4K region */ + reserve_ebda_region(); + /* could be an AMD 768MPX chipset. Reserve a page before VGA to prevent PCI prefetch into it (errata #56). Usually the page is reserved anyways, unless you have no PS/2 mouse plugged in. */ @@ -1335,7 +1363,12 @@ void __init setup_arch(char **cmdline_p) /* * NOTE: before this point _nobody_ is allowed to allocate - * any memory using the bootmem allocator. + * any memory using the bootmem allocator. Although the + * alloctor is now initialised only the first 8Mb of the kernel + * virtual address space has been mapped. All allocations before + * paging_init() has completed must use the alloc_bootmem_low_pages() + * variant (which allocates DMA'able memory) and care must be taken + * not to exceed the 8Mb limit. */ #ifdef CONFIG_SMP @@ -1343,6 +1376,10 @@ void __init setup_arch(char **cmdline_p) #endif paging_init(); + /* + * NOTE: at this point the bootmem allocator is fully available. + */ + #ifdef CONFIG_EARLY_PRINTK { char *s = strstr(*cmdline_p, "earlyprintk="); diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 57e88b625..061e56811 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -269,6 +270,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, struct pt_regs *regs, unsigned long mask) { int tmp, err = 0; + unsigned long eflags; tmp = 0; __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); @@ -290,7 +292,16 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, err |= __put_user(current->thread.error_code, &sc->err); err |= __put_user(regs->eip, &sc->eip); err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs); - err |= __put_user(regs->eflags, &sc->eflags); + + /* + * Iff TF was set because the program is being single-stepped by a + * debugger, don't save that information on the signal stack.. We + * don't want debugging to change state. + */ + eflags = regs->eflags; + if (current->ptrace & PT_DTRACE) + eflags &= ~TF_MASK; + err |= __put_user(eflags, &sc->eflags); err |= __put_user(regs->esp, &sc->esp_at_signal); err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss); @@ -345,18 +356,20 @@ static void setup_frame(int sig, struct k_sigaction *ka, void __user *restorer; struct sigframe __user *frame; int err = 0; + int usig; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - err |= __put_user((current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(usig, &frame->sig); if (err) goto give_sigsegv; @@ -395,13 +408,27 @@ static void setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; + regs->eax = (unsigned long) sig; + regs->edx = (unsigned long) 0; + regs->ecx = (unsigned long) 0; set_fs(USER_DS); regs->xds = __USER_DS; regs->xes = __USER_DS; regs->xss = __USER_DS; regs->xcs = __USER_CS; - regs->eflags &= ~TF_MASK; + + /* + * Clear TF when entering the signal handler, but + * notify any tracer that was single-stepping it. + * The tracer may want to single-step inside the + * handler too. + */ + if (regs->eflags & TF_MASK) { + regs->eflags &= ~TF_MASK; + if (current->ptrace & PT_DTRACE) + ptrace_notify(SIGTRAP); + } #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -411,9 +438,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -422,18 +447,20 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer; struct rt_sigframe __user *frame; int err = 0; + int usig; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - err |= __put_user((current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig), - &frame->sig); + usig = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(usig, &frame->sig); err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); @@ -476,13 +503,27 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; regs->eip = (unsigned long) ka->sa.sa_handler; + regs->eax = (unsigned long) usig; + regs->edx = (unsigned long) &frame->info; + regs->ecx = (unsigned long) &frame->uc; set_fs(USER_DS); regs->xds = __USER_DS; regs->xes = __USER_DS; regs->xss = __USER_DS; regs->xcs = __USER_CS; - regs->eflags &= ~TF_MASK; + + /* + * Clear TF when entering the signal handler, but + * notify any tracer that was single-stepping it. + * The tracer may want to single-step inside the + * handler too. + */ + if (regs->eflags & TF_MASK) { + regs->eflags &= ~TF_MASK; + if (current->ptrace & PT_DTRACE) + ptrace_notify(SIGTRAP); + } #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -492,9 +533,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -502,11 +541,9 @@ give_sigsegv: */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Are we from a system call? */ if (regs->orig_eax >= 0) { /* If so, check system call restarting.. */ @@ -534,9 +571,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -555,6 +589,7 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -573,17 +608,19 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will * have been cleared if the watchpoint triggered * inside the kernel. */ - __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7])); + if (unlikely(current->thread.debugreg[7])) { + __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7])); + } /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index bb5960134..d575f4b4b 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -22,7 +22,6 @@ #include #include -#include #include /* @@ -104,7 +103,7 @@ * about nothing of note with C stepping upwards. */ -struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0, }}; +DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, }; /* * the following functions deal with sending IPIs between CPUs. @@ -122,7 +121,7 @@ static inline int __prepare_ICR2 (unsigned int mask) return SET_APIC_DEST_FIELD(mask); } -inline void __send_IPI_shortcut(unsigned int shortcut, int vector) +void __send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -157,7 +156,7 @@ void fastcall send_IPI_self(int vector) /* * This is only used on smaller machines. */ -inline void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) +void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) { unsigned long mask = cpus_addr(cpumask)[0]; unsigned long cfg; @@ -230,6 +229,8 @@ inline void send_IPI_mask_sequence(cpumask_t mask, int vector) local_irq_restore(flags); } +#include /* must come after the send_IPI functions above for inlining */ + /* * Smarter SMP flushing macros. * c/o Linus Torvalds. @@ -255,9 +256,9 @@ static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED; */ static inline void leave_mm (unsigned long cpu) { - if (cpu_tlbstate[cpu].state == TLBSTATE_OK) + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) BUG(); - cpu_clear(cpu, cpu_tlbstate[cpu].active_mm->cpu_vm_mask); + cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask); load_cr3(swapper_pg_dir); } @@ -307,7 +308,7 @@ static inline void leave_mm (unsigned long cpu) * 2) Leave the mm if we are in the lazy tlb mode. */ -asmlinkage void smp_invalidate_interrupt (void) +fastcall void smp_invalidate_interrupt(struct pt_regs *regs) { unsigned long cpu; @@ -324,8 +325,8 @@ asmlinkage void smp_invalidate_interrupt (void) * BUG(); */ - if (flush_mm == cpu_tlbstate[cpu].active_mm) { - if (cpu_tlbstate[cpu].state == TLBSTATE_OK) { + if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) { + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) { if (flush_va == FLUSH_ALL) local_flush_tlb(); else @@ -457,7 +458,7 @@ static void do_flush_tlb_all(void* info) unsigned long cpu = smp_processor_id(); __flush_tlb_all(); - if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY) + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY) leave_mm(cpu); } @@ -537,11 +538,11 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, /* Wait for response */ while (atomic_read(&data.started) != cpus) - barrier(); + cpu_relax(); if (wait) while (atomic_read(&data.finished) != cpus) - barrier(); + cpu_relax(); spin_unlock(&call_lock); return 0; @@ -578,12 +579,12 @@ void smp_send_stop(void) * all the work is done automatically when * we return from the interrupt. */ -asmlinkage void smp_reschedule_interrupt(void) +fastcall void smp_reschedule_interrupt(struct pt_regs *regs) { ack_APIC_irq(); } -asmlinkage void smp_call_function_interrupt(void) +fastcall void smp_call_function_interrupt(struct pt_regs *regs) { void (*func) (void *info) = call_data->func; void *info = call_data->info; diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 1a9b08190..016a07067 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -17,7 +17,7 @@ * Fixes * Felix Koop : NR_CPUS used properly * Jose Renau : Handle single CPU case. - * Alan Cox : By repeated request 8) - Total BogoMIP report. + * Alan Cox : By repeated request 8) - Total BogoMIPS report. * Greg Wright : Fix for kernel stacks panic. * Erich Boleyn : MP v1.4 and additional changes. * Matthias Sattler : Changes for 2.1 kernel map. @@ -72,6 +72,10 @@ static cpumask_t smp_commenced_mask; /* Per CPU bogomips and other parameters */ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; +u8 x86_cpu_to_apicid[NR_CPUS] = + { [0 ... NR_CPUS-1] = 0xff }; +EXPORT_SYMBOL(x86_cpu_to_apicid); + /* Set when the idlers are all forked */ int smp_threads_ready; @@ -187,34 +191,6 @@ static unsigned long long tsc_values[NR_CPUS]; #define NR_LOOPS 5 -/* - * accurate 64-bit/32-bit division, expanded to 32-bit divisions and 64-bit - * multiplication. Not terribly optimized but we need it at boot time only - * anyway. - * - * result == a / b - * == (a1 + a2*(2^32)) / b - * == a1/b + a2*(2^32/b) - * == a1/b + a2*((2^32-1)/b) + a2/b + (a2*((2^32-1) % b))/b - * ^---- (this multiplication can overflow) - */ - -static unsigned long long __init div64 (unsigned long long a, unsigned long b0) -{ - unsigned int a1, a2; - unsigned long long res; - - a1 = ((unsigned int*)&a)[0]; - a2 = ((unsigned int*)&a)[1]; - - res = a1/b0 + - (unsigned long long)a2 * (unsigned long long)(0xffffffff/b0) + - a2 / b0 + - (a2 * (0xffffffff % b0)) / b0; - - return res; -} - static void __init synchronize_tsc_bp (void) { int i; @@ -224,7 +200,7 @@ static void __init synchronize_tsc_bp (void) unsigned long one_usec; int buggy = 0; - printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus()); + printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus()); /* convert from kcyc/sec to cyc/usec */ one_usec = cpu_khz / 1000; @@ -279,7 +255,8 @@ static void __init synchronize_tsc_bp (void) sum += t0; } } - avg = div64(sum, num_booting_cpus()); + avg = sum; + do_div(avg, num_booting_cpus()); sum = 0; for (i = 0; i < NR_CPUS; i++) { @@ -297,18 +274,18 @@ static void __init synchronize_tsc_bp (void) buggy = 1; printk("\n"); } - realdelta = div64(delta, one_usec); + realdelta = delta; + do_div(realdelta, one_usec); if (tsc_values[i] < avg) realdelta = -realdelta; - printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n", i, realdelta); + printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta); } sum += delta; } if (!buggy) printk("passed.\n"); - ; } static void __init synchronize_tsc_ap (void) @@ -492,16 +469,6 @@ extern struct { unsigned short ss; } stack_start; -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #ifdef CONFIG_NUMA /* which logical CPUs are on which nodes */ @@ -797,21 +764,10 @@ static int __init do_boot_cpu(int apicid) * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(idle); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - - unhash_process(idle); - /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); @@ -875,6 +831,7 @@ static int __init do_boot_cpu(int apicid) inquire_remote_apic(apicid); } } + x86_cpu_to_apicid[cpu] = apicid; if (boot_error) { /* Try to put things back the way they were before ... */ unmap_cpu_to_logical_apicid(cpu); @@ -957,6 +914,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); + x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; current_thread_info()->cpu = 0; smp_tune_scheduling(); @@ -1132,213 +1090,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) synchronize_tsc_bp(); } -#ifdef CONFIG_SCHED_SMT -#ifdef CONFIG_NUMA -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static struct sched_group sched_group_nodes[MAX_NUMNODES]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -static DEFINE_PER_CPU(struct sched_domain, node_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - struct sched_domain *node_domain = &per_cpu(node_domains, i); - int node = cpu_to_node(i); - cpumask_t nodemask = node_to_cpumask(node); - - *cpu_domain = SD_SIBLING_INIT; - cpu_domain->span = cpu_sibling_map[i]; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = nodemask; - phys_domain->parent = node_domain; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - - *node_domain = SD_NODE_INIT; - node_domain->span = cpu_possible_map; - node_domain->groups = &sched_group_nodes[cpu_to_node(i)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpu->cpumask = CPU_MASK_NONE; - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - for (i = 0; i < MAX_NUMNODES; i++) { - int j; - cpumask_t nodemask; - struct sched_group *node = &sched_group_nodes[i]; - cpumask_t node_cpumask = node_to_cpumask(i); - - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu_mask(j, nodemask) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); - struct sched_group *cpu = &sched_group_phys[j]; - - if (j != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* - * Make each extra sibling increase power by 10% of - * the basic CPU. This is very arbitrary. - */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - node->cpu_power += cpu->cpu_power; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - /* Set up nodes */ - first = last = NULL; - for (i = 0; i < MAX_NUMNODES; i++) { - struct sched_group *cpu = &sched_group_nodes[i]; - cpumask_t nodemask; - cpumask_t node_cpumask = node_to_cpumask(i); - - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - cpu->cpumask = nodemask; - /* ->cpu_power already setup */ - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#else /* !CONFIG_NUMA */ -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - - *cpu_domain = SD_SIBLING_INIT; - cpu_domain->span = cpu_sibling_map[i]; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = cpu_possible_map; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_group *cpu = &sched_group_phys[i]; - - if (i != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* See SMT+NUMA setup for comment */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_SCHED_SMT */ - /* These are wrappers to interface to the new boot process. Someone who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ void __init smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index e80cd8e41..bb55e0d51 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c @@ -28,6 +28,7 @@ #include #include #include +#include #include /* diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index 0daa404f5..960d8bd13 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(void); void enable_sep_cpu(void *info) { int cpu = get_cpu(); - struct tss_struct *tss = init_tss + cpu; + struct tss_struct *tss = &per_cpu(init_tss, cpu); tss->ss1 = __KERNEL_CS; tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; @@ -43,18 +43,18 @@ extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; static int __init sysenter_setup(void) { - unsigned long page = get_zeroed_page(GFP_ATOMIC); + void *page = (void *)get_zeroed_page(GFP_ATOMIC); __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC); if (!boot_cpu_has(X86_FEATURE_SEP)) { - memcpy((void *) page, + memcpy(page, &vsyscall_int80_start, &vsyscall_int80_end - &vsyscall_int80_start); return 0; } - memcpy((void *) page, + memcpy(page, &vsyscall_sysenter_start, &vsyscall_sysenter_end - &vsyscall_sysenter_start); diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index f8dcf5d68..a4ec0f26b 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -200,6 +200,18 @@ unsigned long long monotonic_clock(void) } EXPORT_SYMBOL(monotonic_clock); +#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER) +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + + if (in_lock_functions(pc)) + return *(unsigned long *)(regs->ebp + 4); + + return pc; +} +EXPORT_SYMBOL(profile_pc); +#endif /* * timer_interrupt() needs to keep up the real-time clock, @@ -307,46 +319,57 @@ unsigned long get_cmos_time(void) return retval; } -static long clock_cmos_diff; +static long clock_cmos_diff, sleep_start; -static int time_suspend(struct sys_device *dev, u32 state) +static int timer_suspend(struct sys_device *dev, u32 state) { /* * Estimate time zone so that set_time can update the clock */ clock_cmos_diff = -get_cmos_time(); clock_cmos_diff += get_seconds(); + sleep_start = get_cmos_time(); return 0; } -static int time_resume(struct sys_device *dev) +static int timer_resume(struct sys_device *dev) { - unsigned long sec = get_cmos_time() + clock_cmos_diff; - write_seqlock_irq(&xtime_lock); + unsigned long flags; + unsigned long sec; + unsigned long sleep_length; + +#ifdef CONFIG_HPET_TIMER + if (is_hpet_enabled()) + hpet_reenable(); +#endif + sec = get_cmos_time() + clock_cmos_diff; + sleep_length = get_cmos_time() - sleep_start; + write_seqlock_irqsave(&xtime_lock, flags); xtime.tv_sec = sec; xtime.tv_nsec = 0; - write_sequnlock_irq(&xtime_lock); + write_sequnlock_irqrestore(&xtime_lock, flags); + jiffies += sleep_length * HZ; return 0; } -static struct sysdev_class pit_sysclass = { - .resume = time_resume, - .suspend = time_suspend, - set_kset_name("pit"), +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), }; /* XXX this driverfs stuff should probably go elsewhere later -john */ -static struct sys_device device_i8253 = { +static struct sys_device device_timer = { .id = 0, - .cls = &pit_sysclass, + .cls = &timer_sysclass, }; static int time_init_device(void) { - int error = sysdev_class_register(&pit_sysclass); + int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sysdev_register(&device_i8253); + error = sysdev_register(&device_timer); return error; } @@ -358,9 +381,9 @@ extern void (*late_time_init)(void); void __init hpet_time_init(void) { xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); if (hpet_enable() >= 0) { printk("Using HPET for base-timer\n"); @@ -386,9 +409,9 @@ void __init time_init(void) } #endif xtime.tv_sec = get_cmos_time(); - wall_to_monotonic.tv_sec = -xtime.tv_sec; xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); cur_timer = select_timer(); printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c index 0ec677d9e..0bc3acdee 100644 --- a/arch/i386/kernel/time_hpet.c +++ b/arch/i386/kernel/time_hpet.c @@ -29,7 +29,7 @@ unsigned long hpet_address; /* hpet memory map physical address */ static int use_hpet; /* can be used for runtime check of hpet */ static int boot_hpet_disable; /* boottime override for HPET timer */ -static unsigned long hpet_virt_address; /* hpet kernel virtual address */ +static void __iomem * hpet_virt_address; /* hpet kernel virtual address */ #define FSEC_TO_USEC (1000000000UL) @@ -60,13 +60,46 @@ void __init wait_hpet_tick(void) } #endif +static int hpet_timer_stop_set_go(unsigned long tick) +{ + unsigned int cfg; + + /* + * Stop the timers and reset the main counter. + */ + cfg = hpet_readl(HPET_CFG); + cfg &= ~HPET_CFG_ENABLE; + hpet_writel(cfg, HPET_CFG); + hpet_writel(0, HPET_COUNTER); + hpet_writel(0, HPET_COUNTER + 4); + + /* + * Set up timer 0, as periodic with first interrupt to happen at + * hpet_tick, and period also hpet_tick. + */ + cfg = hpet_readl(HPET_T0_CFG); + cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | + HPET_TN_SETVAL | HPET_TN_32BIT; + hpet_writel(cfg, HPET_T0_CFG); + hpet_writel(tick, HPET_T0_CMP); + + /* + * Go! + */ + cfg = hpet_readl(HPET_CFG); + cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; + hpet_writel(cfg, HPET_CFG); + + return 0; +} + /* * Check whether HPET was found by ACPI boot parse. If yes setup HPET * counter 0 for kernel base timer. */ int __init hpet_enable(void) { - unsigned int cfg, id; + unsigned int id; unsigned long tick_fsec_low, tick_fsec_high; /* tick in femto sec */ unsigned long hpet_tick_rem; @@ -76,8 +109,7 @@ int __init hpet_enable(void) if (!hpet_address) { return -1; } - hpet_virt_address = (unsigned long) ioremap_nocache(hpet_address, - HPET_MMAP_SIZE); + hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); /* * Read the period, compute tick and quotient. */ @@ -109,31 +141,8 @@ int __init hpet_enable(void) if (hpet_tick_rem > (hpet_period >> 1)) hpet_tick++; /* rounding the result */ - /* - * Stop the timers and reset the main counter. - */ - cfg = hpet_readl(HPET_CFG); - cfg &= ~HPET_CFG_ENABLE; - hpet_writel(cfg, HPET_CFG); - hpet_writel(0, HPET_COUNTER); - hpet_writel(0, HPET_COUNTER + 4); - - /* - * Set up timer 0, as periodic with first interrupt to happen at - * hpet_tick, and period also hpet_tick. - */ - cfg = hpet_readl(HPET_T0_CFG); - cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | - HPET_TN_SETVAL | HPET_TN_32BIT; - hpet_writel(cfg, HPET_T0_CFG); - hpet_writel(hpet_tick, HPET_T0_CMP); - - /* - * Go! - */ - cfg = hpet_readl(HPET_CFG); - cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY; - hpet_writel(cfg, HPET_CFG); + if (hpet_timer_stop_set_go(hpet_tick)) + return -1; use_hpet = 1; @@ -152,6 +161,7 @@ int __init hpet_enable(void) * Register with driver. * Timer0 and Timer1 is used by platform. */ + hd.hd_phys_address = hpet_address; hd.hd_address = hpet_virt_address; hd.hd_nirqs = ntimer; hd.hd_flags = HPET_DATA_PLATFORM; @@ -162,11 +172,11 @@ int __init hpet_enable(void) hd.hd_irq[0] = HPET_LEGACY_8254; hd.hd_irq[1] = HPET_LEGACY_RTC; if (ntimer > 2) { - struct hpet *hpet; - struct hpet_timer *timer; + struct hpet __iomem *hpet; + struct hpet_timer __iomem *timer; int i; - hpet = (struct hpet *) hpet_virt_address; + hpet = hpet_virt_address; for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer; timer++, i++) @@ -186,6 +196,11 @@ int __init hpet_enable(void) return 0; } +int hpet_reenable(void) +{ + return hpet_timer_stop_set_go(hpet_tick); +} + int is_hpet_enabled(void) { return use_hpet; diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c index 7271b0615..f7f90005e 100644 --- a/arch/i386/kernel/timers/common.c +++ b/arch/i386/kernel/timers/common.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c index 0526fc198..a3d6a2880 100644 --- a/arch/i386/kernel/timers/timer.c +++ b/arch/i386/kernel/timers/timer.c @@ -12,18 +12,18 @@ */ #endif /* list of timers, ordered by preference, NULL terminated */ -static struct timer_opts* timers[] = { +static struct init_timer_opts* __initdata timers[] = { #ifdef CONFIG_X86_CYCLONE_TIMER - &timer_cyclone, + &timer_cyclone_init, #endif #ifdef CONFIG_HPET_TIMER - &timer_hpet, + &timer_hpet_init, #endif #ifdef CONFIG_X86_PM_TIMER - &timer_pmtmr, + &timer_pmtmr_init, #endif - &timer_tsc, - &timer_pit, + &timer_tsc_init, + &timer_pit_init, NULL, }; @@ -49,7 +49,7 @@ void clock_fallback(void) /* iterates through the list of timers, returning the first * one that initializes successfully. */ -struct timer_opts* select_timer(void) +struct timer_opts* __init select_timer(void) { int i = 0; @@ -57,7 +57,7 @@ struct timer_opts* select_timer(void) while (timers[i]) { if (timers[i]->init) if (timers[i]->init(clock_override) == 0) - return timers[i]; + return timers[i]->opts; ++i; } diff --git a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c index 34f1f3d1c..f6f1206a1 100644 --- a/arch/i386/kernel/timers/timer_cyclone.c +++ b/arch/i386/kernel/timers/timer_cyclone.c @@ -245,11 +245,15 @@ static void delay_cyclone(unsigned long loops) /************************************************************/ /* cyclone timer_opts struct */ -struct timer_opts timer_cyclone = { +static struct timer_opts timer_cyclone = { .name = "cyclone", - .init = init_cyclone, .mark_offset = mark_offset_cyclone, .get_offset = get_offset_cyclone, .monotonic_clock = monotonic_clock_cyclone, .delay = delay_cyclone, }; + +struct init_timer_opts __initdata timer_cyclone_init = { + .init = init_cyclone, + .opts = &timer_cyclone, +}; diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c index 15035a563..56d8fc1ea 100644 --- a/arch/i386/kernel/timers/timer_hpet.c +++ b/arch/i386/kernel/timers/timer_hpet.c @@ -177,11 +177,15 @@ static int __init init_hpet(char* override) /************************************************************/ /* tsc timer_opts struct */ -struct timer_opts timer_hpet = { +static struct timer_opts timer_hpet = { .name = "hpet", - .init = init_hpet, .mark_offset = mark_offset_hpet, .get_offset = get_offset_hpet, .monotonic_clock = monotonic_clock_hpet, .delay = delay_hpet, }; + +struct init_timer_opts __initdata timer_hpet_init = { + .init = init_hpet, + .opts = &timer_hpet, +}; diff --git a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c index 394a75250..4ea2f414d 100644 --- a/arch/i386/kernel/timers/timer_none.c +++ b/arch/i386/kernel/timers/timer_none.c @@ -1,11 +1,6 @@ #include #include -static int __init init_none(char* override) -{ - return 0; -} - static void mark_offset_none(void) { /* nothing needed */ @@ -37,7 +32,6 @@ static void delay_none(unsigned long loops) /* none timer_opts struct */ struct timer_opts timer_none = { .name = "none", - .init = init_none, .mark_offset = mark_offset_none, .get_offset = get_offset_none, .monotonic_clock = monotonic_clock_none, diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c index 7ddbf1c76..967d5453c 100644 --- a/arch/i386/kernel/timers/timer_pit.c +++ b/arch/i386/kernel/timers/timer_pit.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -149,10 +152,55 @@ static unsigned long get_offset_pit(void) /* tsc timer_opts struct */ struct timer_opts timer_pit = { - .name = "pit", - .init = init_pit, - .mark_offset = mark_offset_pit, - .get_offset = get_offset_pit, + .name = "pit", + .mark_offset = mark_offset_pit, + .get_offset = get_offset_pit, .monotonic_clock = monotonic_clock_pit, .delay = delay_pit, }; + +struct init_timer_opts __initdata timer_pit_init = { + .init = init_pit, + .opts = &timer_pit, +}; + +void setup_pit_timer(void) +{ + extern spinlock_t i8253_lock; + unsigned long flags; + + spin_lock_irqsave(&i8253_lock, flags); + outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ + udelay(10); + outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ + udelay(10); + outb(LATCH >> 8 , PIT_CH0); /* MSB */ + spin_unlock_irqrestore(&i8253_lock, flags); +} + +static int timer_resume(struct sys_device *dev) +{ + setup_pit_timer(); + return 0; +} + +static struct sysdev_class timer_sysclass = { + set_kset_name("timer_pit"), + .resume = timer_resume, +}; + +static struct sys_device device_timer = { + .id = 0, + .cls = &timer_sysclass, +}; + +static int __init init_timer_sysfs(void) +{ + int error = sysdev_class_register(&timer_sysclass); + if (!error) + error = sysdev_register(&device_timer); + return error; +} + +device_initcall(init_timer_sysfs); + diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c index 737a0219d..d77f22030 100644 --- a/arch/i386/kernel/timers/timer_pm.c +++ b/arch/i386/kernel/timers/timer_pm.c @@ -240,15 +240,18 @@ static unsigned long get_offset_pmtmr(void) /* acpi timer_opts struct */ -struct timer_opts timer_pmtmr = { +static struct timer_opts timer_pmtmr = { .name = "pmtmr", - .init = init_pmtmr, .mark_offset = mark_offset_pmtmr, .get_offset = get_offset_pmtmr, .monotonic_clock = monotonic_clock_pmtmr, .delay = delay_pmtmr, }; +struct init_timer_opts __initdata timer_pmtmr_init = { + .init = init_pmtmr, + .opts = &timer_pmtmr, +}; MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dominik Brodowski "); diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index a1e3f6f96..a685994e5 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -28,7 +28,7 @@ #ifdef CONFIG_HPET_TIMER static unsigned long hpet_usec_quotient; static unsigned long hpet_last; -struct timer_opts timer_tsc; +static struct timer_opts timer_tsc; #endif static inline void cpufreq_delayed_get(void); @@ -265,7 +265,8 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, { struct cpufreq_freqs *freq = data; - write_seqlock_irq(&xtime_lock); + if (val != CPUFREQ_RESUMECHANGE) + write_seqlock_irq(&xtime_lock); if (!ref_freq) { ref_freq = freq->old; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; @@ -291,7 +292,9 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, } #endif } - write_sequnlock_irq(&xtime_lock); + + if (val != CPUFREQ_RESUMECHANGE) + write_sequnlock_irq(&xtime_lock); return 0; } @@ -543,11 +546,15 @@ __setup("notsc", tsc_setup); /************************************************************/ /* tsc timer_opts struct */ -struct timer_opts timer_tsc = { - .name = "tsc", - .init = init_tsc, - .mark_offset = mark_offset_tsc, - .get_offset = get_offset_tsc, - .monotonic_clock = monotonic_clock_tsc, +static struct timer_opts timer_tsc = { + .name = "tsc", + .mark_offset = mark_offset_tsc, + .get_offset = get_offset_tsc, + .monotonic_clock = monotonic_clock_tsc, .delay = delay_tsc, }; + +struct init_timer_opts __initdata timer_tsc_init = { + .init = init_tsc, + .opts = &timer_tsc, +}; diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index a3daea013..76b4e7a69 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -25,7 +25,8 @@ #include #include #include -#include +#include +#include #ifdef CONFIG_EISA #include @@ -48,6 +49,7 @@ #include #include +#include #include #include @@ -55,8 +57,6 @@ #include "mach_traps.h" asmlinkage int system_call(void); -asmlinkage void lcall7(void); -asmlinkage void lcall27(void); struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }; @@ -92,37 +92,40 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; +struct notifier_block *i386die_chain; +static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED; -static int valid_stack_ptr(struct task_struct *task, void *p) +int register_die_notifier(struct notifier_block *nb) { - if (p <= (void *)task->thread_info) - return 0; - if (kstack_end(p)) - return 0; - return 1; + int err = 0; + unsigned long flags; + spin_lock_irqsave(&die_notifier_lock, flags); + err = notifier_chain_register(&i386die_chain, nb); + spin_unlock_irqrestore(&die_notifier_lock, flags); + return err; } -#ifdef CONFIG_FRAME_POINTER -static void print_context_stack(struct task_struct *task, unsigned long *stack, - unsigned long ebp) +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +{ + return p > (void *)tinfo && + p < (void *)tinfo + THREAD_SIZE - 3; +} + +static inline unsigned long print_context_stack(struct thread_info *tinfo, + unsigned long *stack, unsigned long ebp) { unsigned long addr; - while (valid_stack_ptr(task, (void *)ebp)) { +#ifdef CONFIG_FRAME_POINTER + while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); printk(" [<%08lx>] ", addr); print_symbol("%s", addr); printk("\n"); ebp = *(unsigned long *)ebp; } -} #else -static void print_context_stack(struct task_struct *task, unsigned long *stack, - unsigned long ebp) -{ - unsigned long addr; - - while (!kstack_end(stack)) { + while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; if (__kernel_text_address(addr)) { printk(" [<%08lx>]", addr); @@ -130,8 +133,9 @@ static void print_context_stack(struct task_struct *task, unsigned long *stack, printk("\n"); } } -} #endif + return ebp; +} void show_trace(struct task_struct *task, unsigned long * stack) { @@ -140,11 +144,6 @@ void show_trace(struct task_struct *task, unsigned long * stack) if (!task) task = current; - if (!valid_stack_ptr(task, stack)) { - printk("Stack pointer is garbage, not printing trace\n"); - return; - } - if (task == current) { /* Grab ebp right from our regs */ asm ("movl %%ebp, %0" : "=r" (ebp) : ); @@ -157,7 +156,7 @@ void show_trace(struct task_struct *task, unsigned long * stack) struct thread_info *context; context = (struct thread_info *) ((unsigned long)stack & (~(THREAD_SIZE - 1))); - print_context_stack(task, stack, ebp); + ebp = print_context_stack(context, stack, ebp); stack = (unsigned long*)context->previous_esp; if (!stack) break; @@ -216,10 +215,10 @@ void show_registers(struct pt_regs *regs) ss = regs->xss & 0xffff; } print_modules(); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx" + printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx" " (%s) \n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, - print_tainted(), regs->eflags, UTS_RELEASE); + print_tainted(), regs->eflags, system_utsname.release); print_symbol("EIP is at %s\n", regs->eip); printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); @@ -234,23 +233,25 @@ void show_registers(struct pt_regs *regs) * time of the fault.. */ if (in_kernel) { + u8 *eip; printk("\nStack: "); show_stack(NULL, (unsigned long*)esp); printk("Code: "); - if(regs->eip < PAGE_OFFSET) - goto bad; - for(i=0;i<20;i++) - { + eip = (u8 *)regs->eip - 43; + for (i = 0; i < 64; i++, eip++) { unsigned char c; - if(__get_user(c, &((unsigned char*)regs->eip)[i])) { -bad: + + if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) { printk(" Bad EIP value."); break; } - printk("%02x ", c); + if (eip == (u8 *)regs->eip) + printk("<%02x> ", c); + else + printk("%02x ", c); } } printk("\n"); @@ -292,35 +293,53 @@ bug: printk("Kernel BUG\n"); } -spinlock_t die_lock = SPIN_LOCK_UNLOCKED; - void die(const char * str, struct pt_regs * regs, long err) { + static struct { + spinlock_t lock; + u32 lock_owner; + int lock_owner_depth; + } die = { + .lock = SPIN_LOCK_UNLOCKED, + .lock_owner = -1, + .lock_owner_depth = 0 + }; static int die_counter; - int nl = 0; - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - handle_BUG(regs); - printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); + 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); + } + + if (++die.lock_owner_depth < 3) { + int nl = 0; + handle_BUG(regs); + printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT - printk("PREEMPT "); - nl = 1; + printk("PREEMPT "); + nl = 1; #endif #ifdef CONFIG_SMP - printk("SMP "); - nl = 1; + printk("SMP "); + nl = 1; #endif #ifdef CONFIG_DEBUG_PAGEALLOC - printk("DEBUG_PAGEALLOC"); - nl = 1; + printk("DEBUG_PAGEALLOC"); + nl = 1; #endif - if (nl) - printk("\n"); - show_registers(regs); + if (nl) + printk("\n"); + notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); + show_registers(regs); + } else + printk(KERN_ERR "Recursive die() failure, output suppressed\n"); + bust_spinlocks(0); - spin_unlock_irq(&die_lock); + die.lock_owner = -1; + spin_unlock_irq(&die.lock); if (in_interrupt()) panic("Fatal exception in interrupt"); @@ -339,16 +358,7 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e die(str, regs, err); } -static inline unsigned long get_cr2(void) -{ - unsigned long address; - - /* get the address */ - __asm__("movl %%cr2,%0":"=r" (address)); - return address; -} - -static inline void do_trap(int trapnr, int signr, char *str, int vm86, +static void do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs * regs, long error_code, siginfo_t *info) { if (regs->eflags & VM_MASK) { @@ -385,41 +395,55 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86, } #define DO_ERROR(trapnr, signr, str, name) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +fastcall void do_##name(struct pt_regs * regs, long error_code) \ { \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ + return; \ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ } #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +fastcall void do_##name(struct pt_regs * regs, long error_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ info.si_errno = 0; \ info.si_code = sicode; \ info.si_addr = (void __user *)siaddr; \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ + return; \ do_trap(trapnr, signr, str, 0, regs, error_code, &info); \ } #define DO_VM86_ERROR(trapnr, signr, str, name) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +fastcall void do_##name(struct pt_regs * regs, long error_code) \ { \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ + return; \ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ } #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ -asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ +fastcall void do_##name(struct pt_regs * regs, long error_code) \ { \ siginfo_t info; \ info.si_signo = signr; \ info.si_errno = 0; \ info.si_code = sicode; \ info.si_addr = (void __user *)siaddr; \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ + return; \ do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ } DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) +#ifndef CONFIG_KPROBES DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) +#endif DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) @@ -427,13 +451,40 @@ DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR(12, SIGBUS, "stack segment", stack_segment) -DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) +DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) -asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) +fastcall void do_general_protection(struct pt_regs * regs, long error_code) { - if (regs->eflags & X86_EFLAGS_IF) - local_irq_enable(); - + int cpu = get_cpu(); + struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct thread_struct *thread = ¤t->thread; + + /* + * Perform the lazy TSS's I/O bitmap copy. If the TSS has an + * invalid offset set (the LAZY one) and the faulting thread has + * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS + * and we set the offset field correctly. Then we let the CPU to + * restart the faulting instruction. + */ + if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && + thread->io_bitmap_ptr) { + memcpy(tss->io_bitmap, thread->io_bitmap_ptr, + thread->io_bitmap_max); + /* + * If the previously set map was extending to higher ports + * than the current one, pad extra space with 0xff (no access). + */ + if (thread->io_bitmap_max < tss->io_bitmap_max) + memset((char *) tss->io_bitmap + + thread->io_bitmap_max, 0xff, + tss->io_bitmap_max - thread->io_bitmap_max); + tss->io_bitmap_max = thread->io_bitmap_max; + tss->io_bitmap_base = IO_BITMAP_OFFSET; + put_cpu(); + return; + } + put_cpu(); + if (regs->eflags & VM_MASK) goto gp_in_vm86; @@ -451,8 +502,12 @@ gp_in_vm86: return; gp_in_kernel: - if (!fixup_exception(regs)) + if (!fixup_exception(regs)) { + if (notify_die(DIE_GPF, "general protection fault", regs, + error_code, 13, SIGSEGV) == NOTIFY_STOP) + return; die("general protection fault", regs, error_code); + } } static void mem_parity_error(unsigned char reason, struct pt_regs * regs) @@ -496,11 +551,39 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) printk("Do you have a strange power saving mode enabled?\n"); } +static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; + +void die_nmi (struct pt_regs *regs, const char *msg) +{ + spin_lock(&nmi_print_lock); + /* + * We are in trouble anyway, lets at least try + * to get a message out. + */ + bust_spinlocks(1); + printk(msg); + printk(" on CPU%d, eip %08lx, registers:\n", + smp_processor_id(), regs->eip); + show_registers(regs); + printk("console shuts up ...\n"); + console_silent(); + spin_unlock(&nmi_print_lock); + bust_spinlocks(0); + do_exit(SIGSEGV); +} + static void default_do_nmi(struct pt_regs * regs) { - unsigned char reason = get_nmi_reason(); + unsigned char reason = 0; + + /* Only the BSP gets external NMIs from the system. */ + if (!smp_processor_id()) + reason = get_nmi_reason(); if (!(reason & 0xc0)) { + if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) + == NOTIFY_STOP) + return; #ifdef CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, @@ -514,6 +597,8 @@ static void default_do_nmi(struct pt_regs * regs) unknown_nmi_error(reason, regs); return; } + if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) + return; if (reason & 0x80) mem_parity_error(reason, regs); if (reason & 0x40) @@ -532,7 +617,7 @@ static int dummy_nmi_callback(struct pt_regs * regs, int cpu) static nmi_callback_t nmi_callback = dummy_nmi_callback; -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +fastcall void do_nmi(struct pt_regs * regs, long error_code) { int cpu; @@ -557,6 +642,20 @@ void unset_nmi_callback(void) nmi_callback = dummy_nmi_callback; } +#ifdef CONFIG_KPROBES +fastcall int do_int3(struct pt_regs *regs, long error_code) +{ + if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) + == NOTIFY_STOP) + return 1; + /* This is an interrupt gate, because kprobes wants interrupts + disabled. Normal trap handlers don't. */ + restore_interrupts(regs); + do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL); + return 0; +} +#endif + /* * Our handling of the processor debug registers is non-trivial. * We do not clear them on entry and exit from the kernel. Therefore @@ -579,7 +678,7 @@ void unset_nmi_callback(void) * find every occurrence of the TF bit that could be saved away even * by user code) */ -asmlinkage void do_debug(struct pt_regs * regs, long error_code) +fastcall void do_debug(struct pt_regs * regs, long error_code) { unsigned int condition; struct task_struct *tsk = current; @@ -587,6 +686,9 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code) __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); + if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, + SIGTRAP) == NOTIFY_STOP) + return; /* It's safe to allow irq's after DR6 has been saved */ if (regs->eflags & X86_EFLAGS_IF) local_irq_enable(); @@ -715,7 +817,7 @@ void math_error(void __user *eip) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) +fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code) { ignore_fpu_irq = 1; math_error((void __user *)regs->eip); @@ -769,7 +871,7 @@ void simd_math_error(void __user *eip) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs, +fastcall void do_simd_coprocessor_error(struct pt_regs * regs, long error_code) { if (cpu_has_xmm) { @@ -793,7 +895,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs, } } -asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, +fastcall void do_spurious_interrupt_bug(struct pt_regs * regs, long error_code) { #if 0 @@ -875,6 +977,14 @@ void set_intr_gate(unsigned int n, void *addr) _set_gate(idt_table+n,14,0,addr,__KERNEL_CS); } +/* + * This routine sets up an interrupt gate at directory privilege level 3. + */ +static inline void set_system_intr_gate(unsigned int n, void *addr) +{ + _set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS); +} + static void __init set_trap_gate(unsigned int n, void *addr) { _set_gate(idt_table+n,15,0,addr,__KERNEL_CS); @@ -885,11 +995,6 @@ static void __init set_system_gate(unsigned int n, void *addr) _set_gate(idt_table+n,15,3,addr,__KERNEL_CS); } -static void __init set_call_gate(void *a, void *addr) -{ - _set_gate(a,12,3,addr,__KERNEL_CS); -} - static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) { _set_gate(idt_table+n,5,0,0,(gdt_entry<<3)); @@ -911,7 +1016,7 @@ void __init trap_init(void) set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); - set_system_gate(3,&int3); /* int3-5 can be called from all */ + set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ set_system_gate(4,&overflow); set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); @@ -933,13 +1038,6 @@ void __init trap_init(void) set_system_gate(SYSCALL_VECTOR,&system_call); - /* - * default LDT is a single-entry callgate to lcall7 for iBCS - * and a callgate to lcall27 for Solaris/x86 binaries - */ - set_call_gate(&default_ldt[0],lcall7); - set_call_gate(&default_ldt[4],lcall27); - /* * Should be a barrier for any external CPU state. */ diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 4484e47a7..80b302689 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -121,7 +121,7 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) do_exit(SIGSEGV); } - tss = init_tss + get_cpu(); + tss = &per_cpu(init_tss, get_cpu()); current->thread.esp0 = current->thread.saved_esp0; current->thread.sysenter_cs = __KERNEL_CS; load_esp0(tss, ¤t->thread); @@ -303,7 +303,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs)); asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs)); - tss = init_tss + get_cpu(); + tss = &per_cpu(init_tss, get_cpu()); tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; if (cpu_has_sep) tsk->thread.sysenter_cs = 0; @@ -723,7 +723,14 @@ static irqreturn_t irq_handler(int intno, void *dev_id, struct pt_regs * regs) irqbits |= irq_bit; if (vm86_irqs[intno].sig) send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1); - /* else user will poll for IRQs */ + spin_unlock_irqrestore(&irqbits_lock, flags); + /* + * IRQ will be re-enabled when user asks for the irq (whether + * polling or as a result of the signal) + */ + disable_irq(intno); + return IRQ_HANDLED; + out: spin_unlock_irqrestore(&irqbits_lock, flags); return IRQ_NONE; @@ -741,7 +748,7 @@ static inline void free_vm86_irq(int irqnumber) spin_unlock_irqrestore(&irqbits_lock, flags); } -void release_x86_irqs(struct task_struct *task) +void release_vm86_irqs(struct task_struct *task) { int i; for (i = FIRST_VM86_IRQ ; i <= LAST_VM86_IRQ; i++) diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 829f1c91d..e0512cc8b 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -4,6 +4,7 @@ #include #include +#include OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) @@ -11,12 +12,13 @@ ENTRY(startup_32) jiffies = jiffies_64; SECTIONS { - . = 0xC0000000 + 0x100000; + . = __PAGE_OFFSET + 0x100000; /* read-only */ _text = .; /* Text and read-only data */ .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 @@ -66,9 +68,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/i386/kernel/vsyscall-sysenter.S b/arch/i386/kernel/vsyscall-sysenter.S index cb54c01bd..4daefb2ec 100644 --- a/arch/i386/kernel/vsyscall-sysenter.S +++ b/arch/i386/kernel/vsyscall-sysenter.S @@ -84,7 +84,7 @@ SYSENTER_RETURN: .byte 0x04 /* DW_CFA_advance_loc4 */ .long .Lpop_ebp-.Lenter_kernel .byte 0x0e /* DW_CFA_def_cfa_offset */ - .byte 0x12 /* RA at offset 12 now */ + .byte 0x0c /* RA at offset 12 now */ .byte 0xc5 /* DW_CFA_restore %ebp */ .byte 0x04 /* DW_CFA_advance_loc4 */ .long .Lpop_edx-.Lpop_ebp diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c index ffd486900..ab43394dc 100644 --- a/arch/i386/lib/dec_and_lock.c +++ b/arch/i386/lib/dec_and_lock.c @@ -10,7 +10,7 @@ #include #include -int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; diff --git a/arch/i386/lib/memcpy.c b/arch/i386/lib/memcpy.c index ad16efa52..891b2359d 100644 --- a/arch/i386/lib/memcpy.c +++ b/arch/i386/lib/memcpy.c @@ -13,13 +13,13 @@ void *memcpy(void *to, const void *from, size_t n) return __memcpy(to, from, n); #endif } -EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL(memcpy); void *memset(void *s, int c, size_t count) { return __memset(s, c, count); } -EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL(memset); void *memmove(void *dest, const void *src, size_t n) { @@ -41,4 +41,4 @@ void *memmove(void *dest, const void *src, size_t n) } return dest; } -EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL(memmove); diff --git a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c index d6fc84f37..01f8b1a2c 100644 --- a/arch/i386/lib/mmx.c +++ b/arch/i386/lib/mmx.c @@ -2,9 +2,9 @@ #include #include #include +#include #include -#include /* diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index e1bcec2b5..3347c47b0 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -31,6 +31,7 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon #define __do_strncpy_from_user(dst,src,count,res) \ do { \ int __d0, __d1, __d2; \ + might_sleep(); \ __asm__ __volatile__( \ " testl %1,%1\n" \ " jz 2f\n" \ @@ -119,6 +120,7 @@ strncpy_from_user(char *dst, const char __user *src, long count) #define __do_clear_user(addr,size) \ do { \ int __d0; \ + might_sleep(); \ __asm__ __volatile__( \ "0: rep; stosl\n" \ " movl %2,%0\n" \ diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c index c70547a7e..37bfa9144 100644 --- a/arch/i386/mach-default/topology.c +++ b/arch/i386/mach-default/topology.c @@ -27,6 +27,7 @@ */ #include #include +#include #include struct i386_cpu cpu_devices[NR_CPUS]; diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h index 1cb878fc5..70691f0c4 100644 --- a/arch/i386/mach-es7000/es7000.h +++ b/arch/i386/mach-es7000/es7000.h @@ -29,7 +29,7 @@ #define MIP_BUSY 1 #define MIP_SPIN 0xf0000 -#define MIP_VALID 0x0100000000000000 +#define MIP_VALID 0x0100000000000000ULL #define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) #define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c index 784576c53..9707a9e45 100644 --- a/arch/i386/mach-es7000/es7000plat.c +++ b/arch/i386/mach-es7000/es7000plat.c @@ -51,28 +51,30 @@ struct mip_reg *host_reg; int mip_port; unsigned long mip_addr, host_addr; -static int __init +#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT)) + +/* + * GSI override for ES7000 platforms. + */ + +static unsigned int base; + +static int es7000_rename_gsi(int ioapic, int gsi) { - if (ioapic) - return gsi; - else { - if (gsi == 0) - return 13; - if (gsi == 1) - return 16; - if (gsi == 4) - return 17; - if (gsi == 6) - return 18; - if (gsi == 7) - return 19; - if (gsi == 8) - return 20; - return gsi; - } + if (!base) { + int i; + for (i = 0; i < nr_ioapics; i++) + base += nr_ioapic_registers[i]; + } + + if (!ioapic && (gsi < 16)) + gsi += base; + return gsi; } +#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT) + /* * Parse the OEM Table */ @@ -137,7 +139,7 @@ parse_unisys_oem (char *oemptr, int oem_entries) } else { printk("\nEnabling ES7000 specific features...\n"); es7000_plat = 1; - platform_rename_gsi = es7000_rename_gsi; + ioapic_renumber_irq = es7000_rename_gsi; } return es7000_plat; } @@ -193,7 +195,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length) } } } - printk("ES7000: did not find Unisys ACPI OEM table!\n"); + Dprintk("ES7000: did not find Unisys ACPI OEM table!\n"); return -1; } @@ -237,7 +239,7 @@ es7000_mip_write(struct mip_reg *mip_reg) } status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000) >> 48; + (unsigned long long)0xffff0000000000ULL) >> 48; mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & (unsigned long long)~MIP_VALID); return status; diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c index f599d8564..25883b44f 100644 --- a/arch/i386/mach-generic/bigsmp.c +++ b/arch/i386/mach-generic/bigsmp.c @@ -13,15 +13,41 @@ #include #include #include +#include #include #include #include #include -int dmi_bigsmp; /* can be set by dmi scanners */ +static int dmi_bigsmp; /* can be set by dmi scanners */ + +static __init int hp_ht_bigsmp(struct dmi_system_id *d) +{ +#ifdef CONFIG_X86_GENERICARCH + printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident); + dmi_bigsmp = 1; +#endif + return 0; +} + + +static struct dmi_system_id __initdata bigsmp_dmi_table[] = { + { hp_ht_bigsmp, "HP ProLiant DL760 G2", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P44-"), + }}, + + { hp_ht_bigsmp, "HP ProLiant DL740", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P47-"), + }}, + { } +}; + static __init int probe_bigsmp(void) { + dmi_check_system(bigsmp_dmi_table); return dmi_bigsmp; } diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c index 61a481423..ab33293aa 100644 --- a/arch/i386/mach-voyager/voyager_basic.c +++ b/arch/i386/mach-voyager/voyager_basic.c @@ -53,7 +53,7 @@ voyager_dump(int dummy1, struct pt_regs *dummy2, struct tty_struct *dummy3) static struct sysrq_key_op sysrq_voyager_dump_op = { .handler = voyager_dump, .help_msg = "Voyager", - .action_msg = "Dump Voyager Status\n", + .action_msg = "Dump Voyager Status", }; #endif diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 90c918f11..f0eb9c5a7 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -35,7 +35,7 @@ int reboot_smp = 0; /* TLB state -- visible externally, indexed physically */ -struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0 }}; +DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; /* CPU IRQ affinity -- set to all ones initially */ static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = ~0UL }; @@ -523,15 +523,6 @@ start_secondary(void *unused) return cpu_idle(); } -static struct task_struct * __init -fork_by_hand(void) -{ - struct pt_regs regs; - /* don't care about the eip and regs settings since we'll - * never reschedule the forked task. */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* Routine to kick start the given CPU and wait for it to report ready * (or timeout in startup). When this routine returns, the requested @@ -587,16 +578,10 @@ do_boot_cpu(__u8 cpu) hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF; cpucount++; - idle = fork_by_hand(); + idle = fork_idle(cpu); if(IS_ERR(idle)) panic("failed fork for CPU%d", cpu); - - wake_up_forked_process(idle); - - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - unhash_process(idle); /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; @@ -800,8 +785,8 @@ initialize_secondary(void) * System interrupts occur because some problem was detected on the * various busses. To find out what you have to probe all the * hardware via the CAT bus. FIXME: At the moment we do nothing. */ -asmlinkage void -smp_vic_sys_interrupt(void) +fastcall void +smp_vic_sys_interrupt(struct pt_regs *regs) { ack_CPI(VIC_SYS_INT); printk("Voyager SYSTEM INTERRUPT\n"); @@ -810,8 +795,8 @@ smp_vic_sys_interrupt(void) /* Handle a voyager CMN_INT; These interrupts occur either because of * a system status change or because a single bit memory error * occurred. FIXME: At the moment, ignore all this. */ -asmlinkage void -smp_vic_cmn_interrupt(void) +fastcall void +smp_vic_cmn_interrupt(struct pt_regs *regs) { static __u8 in_cmn_int = 0; static spinlock_t cmn_int_lock = SPIN_LOCK_UNLOCKED; @@ -839,7 +824,7 @@ smp_vic_cmn_interrupt(void) /* * Reschedule call back. Nothing to do, all the work is done * automatically when we return from the interrupt. */ -asmlinkage void +static void smp_reschedule_interrupt(void) { /* do nothing */ @@ -860,9 +845,9 @@ static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED; static inline void leave_mm (unsigned long cpu) { - if (cpu_tlbstate[cpu].state == TLBSTATE_OK) + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) BUG(); - cpu_clear(cpu, cpu_tlbstate[cpu].active_mm->cpu_vm_mask); + cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask); load_cr3(swapper_pg_dir); } @@ -870,7 +855,7 @@ leave_mm (unsigned long cpu) /* * Invalidate call-back */ -asmlinkage void +static void smp_invalidate_interrupt(void) { __u8 cpu = smp_processor_id(); @@ -883,8 +868,8 @@ smp_invalidate_interrupt(void) smp_processor_id())); */ - if (flush_mm == cpu_tlbstate[cpu].active_mm) { - if (cpu_tlbstate[cpu].state == TLBSTATE_OK) { + if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) { + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) { if (flush_va == FLUSH_ALL) local_flush_tlb(); else @@ -1004,7 +989,7 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) } /* enable the requested IRQs */ -asmlinkage void +static void smp_enable_irq_interrupt(void) { __u8 irq; @@ -1053,7 +1038,7 @@ static struct call_data_struct * call_data; * previously set up. This is used to schedule a function for * execution on all CPU's - set up the function then broadcast a * function_interrupt CPI to come here on each CPU */ -asmlinkage void +static void smp_call_function_interrupt(void) { void (*func) (void *info) = call_data->func; @@ -1148,50 +1133,50 @@ smp_call_function (void (*func) (void *info), void *info, int retry, * no local APIC, so I can't do this * * This function is currently a placeholder and is unused in the code */ -asmlinkage void -smp_apic_timer_interrupt(struct pt_regs regs) +fastcall void +smp_apic_timer_interrupt(struct pt_regs *regs) { - wrapper_smp_local_timer_interrupt(®s); + wrapper_smp_local_timer_interrupt(regs); } /* All of the QUAD interrupt GATES */ -asmlinkage void -smp_qic_timer_interrupt(struct pt_regs regs) +fastcall void +smp_qic_timer_interrupt(struct pt_regs *regs) { ack_QIC_CPI(QIC_TIMER_CPI); - wrapper_smp_local_timer_interrupt(®s); + wrapper_smp_local_timer_interrupt(regs); } -asmlinkage void -smp_qic_invalidate_interrupt(void) +fastcall void +smp_qic_invalidate_interrupt(struct pt_regs *regs) { ack_QIC_CPI(QIC_INVALIDATE_CPI); smp_invalidate_interrupt(); } -asmlinkage void -smp_qic_reschedule_interrupt(void) +fastcall void +smp_qic_reschedule_interrupt(struct pt_regs *regs) { ack_QIC_CPI(QIC_RESCHEDULE_CPI); smp_reschedule_interrupt(); } -asmlinkage void -smp_qic_enable_irq_interrupt(void) +fastcall void +smp_qic_enable_irq_interrupt(struct pt_regs *regs) { ack_QIC_CPI(QIC_ENABLE_IRQ_CPI); smp_enable_irq_interrupt(); } -asmlinkage void -smp_qic_call_function_interrupt(void) +fastcall void +smp_qic_call_function_interrupt(struct pt_regs *regs) { ack_QIC_CPI(QIC_CALL_FUNCTION_CPI); smp_call_function_interrupt(); } -asmlinkage void -smp_vic_cpi_interrupt(struct pt_regs regs) +fastcall void +smp_vic_cpi_interrupt(struct pt_regs *regs) { __u8 cpu = smp_processor_id(); @@ -1201,7 +1186,7 @@ smp_vic_cpi_interrupt(struct pt_regs regs) ack_VIC_CPI(VIC_CPI_LEVEL0); if(test_and_clear_bit(VIC_TIMER_CPI, &vic_cpi_mailbox[cpu])) - wrapper_smp_local_timer_interrupt(®s); + wrapper_smp_local_timer_interrupt(regs); if(test_and_clear_bit(VIC_INVALIDATE_CPI, &vic_cpi_mailbox[cpu])) smp_invalidate_interrupt(); if(test_and_clear_bit(VIC_RESCHEDULE_CPI, &vic_cpi_mailbox[cpu])) @@ -1218,7 +1203,7 @@ do_flush_tlb_all(void* info) unsigned long cpu = smp_processor_id(); __flush_tlb_all(); - if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY) + if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY) leave_mm(cpu); } @@ -1302,8 +1287,7 @@ smp_local_timer_interrupt(struct pt_regs * regs) int cpu = smp_processor_id(); long weight; - x86_do_profile(regs); - + profile_tick(CPU_PROFILING, regs); if (--per_cpu(prof_counter, cpu) <= 0) { /* * The multiplier may have changed since the last time we got diff --git a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h index a8618dfd6..a9fe07c9b 100644 --- a/arch/i386/math-emu/fpu_proto.h +++ b/arch/i386/math-emu/fpu_proto.h @@ -69,7 +69,6 @@ extern int isNaN(FPU_REG const *ptr); extern void FPU_pop(void); extern int FPU_empty_i(int stnr); extern int FPU_stackoverflow(FPU_REG **st_new_ptr); -extern void FPU_sync_tags(void); extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr); extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag); extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag); diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile index 87dd63c98..fc3272506 100644 --- a/arch/i386/mm/Makefile +++ b/arch/i386/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux i386-specific parts of the memory manager. # -obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o +obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o obj-$(CONFIG_DISCONTIGMEM) += discontig.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index 569e08e5b..33b81da92 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include +#include struct pglist_data *node_data[MAX_NUMNODES]; bootmem_data_t node0_bdata; @@ -219,6 +221,17 @@ static unsigned long calculate_numa_remap_pages(void) return reserve_pages; } +/* + * workaround for Dell systems that neglect to reserve EBDA + */ +static void __init reserve_ebda_region_node(void) +{ + unsigned int addr; + addr = get_bios_ebda(); + if (addr) + reserve_bootmem_node(NODE_DATA(0), addr, PAGE_SIZE); +} + unsigned long __init setup_memory(void) { int nid; @@ -318,6 +331,9 @@ unsigned long __init setup_memory(void) */ reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE); + /* reserve EBDA region, it's a 4K region */ + reserve_ebda_region_node(); + #ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. @@ -402,15 +418,15 @@ void __init zone_sizes_init(void) * remapped KVA area - mbligh */ if (!nid) - free_area_init_node(nid, NODE_DATA(nid), 0, - zones_size, start, zholes_size); + free_area_init_node(nid, NODE_DATA(nid), + zones_size, start, zholes_size); else { unsigned long lmem_map; lmem_map = (unsigned long)node_remap_start_vaddr[nid]; lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1; lmem_map &= PAGE_MASK; - free_area_init_node(nid, NODE_DATA(nid), - (struct page *)lmem_map, zones_size, + NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map; + free_area_init_node(nid, NODE_DATA(nid), zones_size, start, zholes_size); } } @@ -452,7 +468,7 @@ void __init set_max_mapnr_init(void) if (high0->spanned_pages > 0) highmem_start_page = high0->zone_mem_map; else - highmem_start_page = pfn_to_page(max_low_pfn+1); + highmem_start_page = pfn_to_page(max_low_pfn - 1) + 1; num_physpages = highend_pfn; #else num_physpages = max_low_pfn; diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index debed4754..f714896ff 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -24,8 +24,8 @@ #include #include -#include #include +#include extern void die(const char *,struct pt_regs *,long); @@ -107,7 +107,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs, desc = (void *)desc + (seg & ~7); } else { /* Must disable preemption while reading the GDT. */ - desc = (u32 *)&cpu_gdt_table[get_cpu()]; + desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu()); desc = (void *)desc + (seg & ~7); } @@ -201,7 +201,7 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr, return 0; } -asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); +fastcall void do_invalid_op(struct pt_regs *, unsigned long); /* * This routine handles page faults. It determines the address, @@ -213,7 +213,7 @@ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; @@ -226,6 +226,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + SIGSEGV) == NOTIFY_STOP) + return; /* It's safe to allow irq's after cr2 has been saved */ if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); @@ -513,12 +516,13 @@ vmalloc_fault: * an interrupt in the middle of a task switch.. */ int index = pgd_index(address); + unsigned long pgd_paddr; pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; pte_t *pte_k; - asm("movl %%cr3,%0":"=r" (pgd)); - pgd = index + (pgd_t *)__va(pgd); + asm("movl %%cr3,%0":"=r" (pgd_paddr)); + pgd = index + (pgd_t *)__va(pgd_paddr); pgd_k = init_mm.pgd + index; if (!pgd_present(*pgd_k)) diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index 7e4b12121..c0d07dbe8 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -247,6 +247,7 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) page = pmd_page(*pmd); pmd_clear(pmd); + mm->nr_ptes--; dec_page_state(nr_page_table_pages); page_cache_release(page); } @@ -281,3 +282,143 @@ out: spin_unlock(&mm->page_table_lock); return ret; } + +/* x86_64 also uses this file */ + +#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA +static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start_addr; + + start_addr = mm->free_area_cache; + +full_search: + addr = ALIGN(start_addr, HPAGE_SIZE); + + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) { + /* + * Start a new search - just in case we missed + * some holes. + */ + if (start_addr != TASK_UNMAPPED_BASE) { + start_addr = TASK_UNMAPPED_BASE; + goto full_search; + } + return -ENOMEM; + } + if (!vma || addr + len <= vma->vm_start) { + mm->free_area_cache = addr + len; + return addr; + } + addr = ALIGN(vma->vm_end, HPAGE_SIZE); + } +} + +static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, + unsigned long addr0, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma, *prev_vma; + unsigned long base = mm->mmap_base, addr = addr0; + int first_time = 1; + + /* don't allow allocations above current base */ + if (mm->free_area_cache > base) + mm->free_area_cache = base; + +try_again: + /* make sure it can fit in the remaining address space */ + if (mm->free_area_cache < len) + goto fail; + + /* either no address requested or cant fit in requested address hole */ + addr = (mm->free_area_cache - len) & HPAGE_MASK; + do { + /* + * Lookup failure means no vma is above this address, + * i.e. return with success: + */ + if (!(vma = find_vma_prev(mm, addr, &prev_vma))) + return addr; + + /* + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ + if (addr + len <= vma->vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + else + /* pull free_area_cache down to the first hole */ + if (mm->free_area_cache == vma->vm_end) + mm->free_area_cache = vma->vm_start; + + /* try just below the current vma->vm_start */ + addr = (vma->vm_start - len) & HPAGE_MASK; + } while (len <= vma->vm_start); + +fail: + /* + * if hint left us with no space for the requested + * mapping then try again: + */ + if (first_time) { + mm->free_area_cache = base; + first_time = 0; + goto try_again; + } + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + mm->free_area_cache = TASK_UNMAPPED_BASE; + addr = hugetlb_get_unmapped_area_bottomup(file, addr0, + len, pgoff, flags); + + /* + * Restore the topdown base: + */ + mm->free_area_cache = base; + + return addr; +} + +unsigned long +hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + + if (len & ~HPAGE_MASK) + return -EINVAL; + if (len > TASK_SIZE) + return -ENOMEM; + + if (addr) { + addr = ALIGN(addr, HPAGE_SIZE); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + if (mm->get_unmapped_area == arch_get_unmapped_area) + return hugetlb_get_unmapped_area_bottomup(file, addr, len, + pgoff, flags); + else + return hugetlb_get_unmapped_area_topdown(file, addr, len, + pgoff, flags); +} + +#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ + diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index a8bd0544a..73bed3db4 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -40,10 +40,12 @@ #include #include +unsigned int __VMALLOC_RESERVE = 128 << 20; + DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); unsigned long highstart_pfn, highend_pfn; -static int do_test_wp_bit(void); +static int noinline do_test_wp_bit(void); /* * Creates a middle page table and puts a pointer to it in the @@ -436,8 +438,8 @@ static int __init noexec_setup(char *str) __setup("noexec=", noexec_setup); -#ifdef CONFIG_X86_PAE int nx_enabled = 0; +#ifdef CONFIG_X86_PAE static void __init set_nx(void) { @@ -671,7 +673,7 @@ void __init pgtable_cache_init(void) * This function cannot be __init, since exceptions don't work in that * section. Put this after the callers, so that it cannot be inlined. */ -static int do_test_wp_bit(void) +static int noinline do_test_wp_bit(void) { char tmp_reg; int flag; @@ -702,6 +704,7 @@ void free_initmem(void) for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); set_page_count(virt_to_page(addr), 1); + memset((void *)addr, 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; } diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c index 7b11be028..aee0bb1f4 100644 --- a/arch/i386/mm/ioremap.c +++ b/arch/i386/mm/ioremap.c @@ -110,9 +110,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) { - void * addr; + void __iomem * addr; struct vm_struct * area; unsigned long offset, last_addr; @@ -125,7 +125,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag * Don't remap the low PCI/ISA area, it's always mapped.. */ if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); + return (void __iomem *) phys_to_virt(phys_addr); /* * Don't allow anybody to remap normal RAM that we're using.. @@ -156,12 +156,12 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag if (!area) return NULL; area->phys_addr = phys_addr; - addr = area->addr; + addr = (void __iomem *) area->addr; if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vunmap(addr); + vunmap((void __force *) addr); return NULL; } - return (void *) (offset + (char *)addr); + return (void __iomem *) (offset + (char __iomem *)addr); } @@ -187,10 +187,10 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag * Must be freed with iounmap. */ -void *ioremap_nocache (unsigned long phys_addr, unsigned long size) +void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) { unsigned long last_addr; - void *p = __ioremap(phys_addr, size, _PAGE_PCD); + void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD); if (!p) return p; @@ -221,12 +221,12 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size) return p; } -void iounmap(void *addr) +void iounmap(volatile void __iomem *addr) { struct vm_struct *p; - if (addr <= high_memory) + if ((void __force *) addr <= high_memory) return; - p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr)); + p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); if (!p) { printk("__iounmap: bad address %p\n", addr); return; diff --git a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c index f88a6c88d..c5e0d0119 100644 --- a/arch/i386/mm/mmap.c +++ b/arch/i386/mm/mmap.c @@ -37,7 +37,7 @@ static inline unsigned long mmap_base(struct mm_struct *mm) { - unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; if (gap < MIN_GAP) gap = MIN_GAP; @@ -57,15 +57,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm) * Fall back to the standard layout if the personality * bit is set, or if the expected stack growth is unlimited: */ - if (sysctl_legacy_va_layout || (current->personality & ADDR_COMPAT_LAYOUT) || - current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + if (sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(mm); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 8eb95be7d..33bbf2baa 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -114,7 +114,7 @@ __change_page_attr(struct page *page, pgprot_t prot) kpte = lookup_address(address); if (!kpte) return -EINVAL; - kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); + kpte_page = virt_to_page(kpte); if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { if ((pte_val(*kpte) & _PAGE_PSE) == 0) { pte_t old = *kpte; @@ -208,7 +208,6 @@ void kernel_map_pages(struct page *page, int numpages, int enable) */ __flush_tlb_all(); } -EXPORT_SYMBOL(kernel_map_pages); #endif EXPORT_SYMBOL(change_page_attr); diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 137d18db7..0cac3b6bf 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c @@ -165,10 +165,8 @@ void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags) * against pageattr.c; it is the unique case in which a valid change * of kernel pagetables can't be lazily synchronized by vmalloc faults. * vmalloc faults work because attached pagetables are never freed. - * If the locking proves to be non-performant, a ticketing scheme with - * checks at dup_mmap(), exec(), and other mmlist addition points - * could be used. The locking scheme was chosen on the basis of - * manfred's recommendations and having no core impact whatsoever. + * The locking scheme was chosen on the basis of manfred's + * recommendations and having no core impact whatsoever. * -- wli */ spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED; @@ -235,7 +233,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL); if (!pmd) goto out_oom; - set_pgd(&pgd[i], __pgd(1 + __pa((u64)((u32)pmd)))); + set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); } return pgd; diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c index 5f6cc84ab..0d4e00f42 100644 --- a/arch/i386/oprofile/op_model_athlon.c +++ b/arch/i386/oprofile/op_model_athlon.c @@ -70,7 +70,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs) /* enable active counters */ for (i = 0; i < NUM_COUNTERS; ++i) { - if (counter_config[i].event) { + if (counter_config[i].enabled) { reset_value[i] = counter_config[i].count; CTR_WRITE(counter_config[i].count, msrs, i); @@ -96,7 +96,7 @@ static int athlon_check_ctrs(unsigned int const cpu, { unsigned int low, high; int i; - unsigned long eip = instruction_pointer(regs); + unsigned long eip = profile_pc(regs); int is_kernel = !user_mode(regs); for (i = 0 ; i < NUM_COUNTERS; ++i) { diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c index e92eaed25..1b3626df5 100644 --- a/arch/i386/oprofile/op_model_p4.c +++ b/arch/i386/oprofile/op_model_p4.c @@ -419,9 +419,28 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) msrs->controls[i].addr = addr; } - /* 43 ESCR registers in three discontiguous group */ + /* 43 ESCR registers in three or four discontiguous group */ for (addr = MSR_P4_BSU_ESCR0 + stag; - addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { + addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1 + * to avoid special case in nmi_{save|restore}_registers() */ + if (boot_cpu_data.x86_model >= 0x3) { + for (addr = MSR_P4_BSU_ESCR0 + stag; + addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + } else { + for (addr = MSR_P4_IQ_ESCR0 + stag; + addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + } + + for (addr = MSR_P4_RAT_ESCR0 + stag; + addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { msrs->controls[i].addr = addr; } @@ -553,7 +572,18 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) /* clear all escrs (including those outside our concern) */ for (addr = MSR_P4_BSU_ESCR0 + stag; - addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { + addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) { + wrmsr(addr, 0, 0); + } + + /* On older models clear also MSR_P4_IQ_ESCR0/1 */ + if (boot_cpu_data.x86_model < 0x3) { + wrmsr(MSR_P4_IQ_ESCR0, 0, 0); + wrmsr(MSR_P4_IQ_ESCR1, 0, 0); + } + + for (addr = MSR_P4_RAT_ESCR0 + stag; + addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { wrmsr(addr, 0, 0); } @@ -578,7 +608,7 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs) /* setup all counters */ for (i = 0 ; i < num_counters ; ++i) { - if (counter_config[i].event) { + if (counter_config[i].enabled) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); @@ -595,7 +625,7 @@ static int p4_check_ctrs(unsigned int const cpu, { unsigned long ctr, low, high, stag, real; int i; - unsigned long eip = instruction_pointer(regs); + unsigned long eip = profile_pc(regs); int is_kernel = !user_mode(regs); stag = get_stagger(); diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c index 21578b26d..0cc80654d 100644 --- a/arch/i386/oprofile/op_model_ppro.c +++ b/arch/i386/oprofile/op_model_ppro.c @@ -67,7 +67,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs) /* enable active counters */ for (i = 0; i < NUM_COUNTERS; ++i) { - if (counter_config[i].event) { + if (counter_config[i].enabled) { reset_value[i] = counter_config[i].count; CTR_WRITE(counter_config[i].count, msrs, i); @@ -91,7 +91,7 @@ static int ppro_check_ctrs(unsigned int const cpu, { unsigned int low, high; int i; - unsigned long eip = instruction_pointer(regs); + unsigned long eip = profile_pc(regs); int is_kernel = !user_mode(regs); for (i = 0 ; i < NUM_COUNTERS; ++i) { diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index 86ce01655..0c0a16972 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c @@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do return pcibios_scan_root(busnum); } +extern int pci_routeirq; static int __init pci_acpi_init(void) { struct pci_dev *dev = NULL; @@ -30,14 +31,27 @@ static int __init pci_acpi_init(void) pcibios_scanned++; pcibios_enable_irq = acpi_pci_irq_enable; - /* - * PCI IRQ routing is set up by pci_enable_device(), but we - * also do it here in case there are still broken drivers that - * don't use pci_enable_device(). - */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - acpi_pci_irq_enable(dev); - + if (pci_routeirq) { + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n"); + printk(KERN_INFO "** was specified. If this was required to make a driver work,\n"); + printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n"); + printk(KERN_INFO "** so I can fix the driver.\n"); + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + } else { + printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n"); + printk(KERN_INFO "** causes a device to stop working, it is probably because the\n"); + printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n"); + printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n"); + printk(KERN_INFO "** behavior. If this argument makes the device work again,\n"); + printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n"); + printk(KERN_INFO "** so I can fix the driver.\n"); + } #ifdef CONFIG_X86_IO_APIC if (acpi_ioapic) print_IO_APIC(); diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 383827d92..4008b6c9a 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -23,6 +23,7 @@ extern void pcibios_sort(void); unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; +int pci_routeirq; int pcibios_last_bus = -1; struct pci_bus *pci_root_bus = NULL; struct pci_raw_ops *raw_pci_ops; @@ -70,7 +71,7 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) int i; DBG("PCI: Scanning for ghost devices on bus %d\n", b->number); - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { + list_for_each(ln, &b->devices) { d = pci_dev_b(ln); if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) seen_host_bridge++; @@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str) } else if (!strcmp(str, "assign-busses")) { pci_probe |= PCI_ASSIGN_ALL_BUSSES; return NULL; + } else if (!strcmp(str, "routeirq")) { + pci_routeirq = 1; + return NULL; } return str; } diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index a8b1954ae..f5a345118 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -29,6 +29,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d) } pcibios_last_bus = -1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); static void __devinit pci_fixup_i450gx(struct pci_dev *d) { @@ -42,6 +43,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d) pci_scan_bus(busno, &pci_root_ops, NULL); pcibios_last_bus = -1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); static void __devinit pci_fixup_umc_ide(struct pci_dev *d) { @@ -55,6 +57,7 @@ static void __devinit pci_fixup_umc_ide(struct pci_dev *d) for(i=0; i<4; i++) d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide); static void __devinit pci_fixup_ncr53c810(struct pci_dev *d) { @@ -67,6 +70,7 @@ static void __devinit pci_fixup_ncr53c810(struct pci_dev *d) d->class = PCI_CLASS_STORAGE_SCSI << 8; } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); static void __devinit pci_fixup_ide_bases(struct pci_dev *d) { @@ -86,6 +90,7 @@ static void __devinit pci_fixup_ide_bases(struct pci_dev *d) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); static void __devinit pci_fixup_ide_trash(struct pci_dev *d) { @@ -108,6 +113,10 @@ static void __devinit pci_fixup_ide_trash(struct pci_dev *d) for(i=0; i<4; i++) d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash); static void __devinit pci_fixup_latency(struct pci_dev *d) { @@ -118,6 +127,8 @@ static void __devinit pci_fixup_latency(struct pci_dev *d) DBG("PCI: Setting max latency to 32\n"); pcibios_max_latency = 32; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency); static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) { @@ -126,6 +137,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) */ d->irq = 9; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi); /* * Addresses issues with problems in the memory write queue timer in @@ -179,6 +191,10 @@ static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d) pci_write_config_byte(d, where, v); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug); /* * For some reasons Intel decided that certain parts of their @@ -195,6 +211,7 @@ static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev) (dev->device & 0xff00) == 0x2400) dev->transparent = 1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge); /* * Fixup for C1 Halt Disconnect problem on nForce2 systems. @@ -236,115 +253,134 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) pci_write_config_dword(dev, 0x6c, fixed_val); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); -struct pci_fixup pcibios_fixups[] = { - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82451NX, - .hook = pci_fixup_i450nx - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82454GX, - .hook = pci_fixup_i450gx - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_UMC, - .device = PCI_DEVICE_ID_UMC_UM8886BF, - .hook = pci_fixup_umc_ide - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5513, - .hook = pci_fixup_ide_trash - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .hook = pci_fixup_ide_bases - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5597, - .hook = pci_fixup_latency - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5598, - .hook = pci_fixup_latency - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371AB_3, - .hook = pci_fixup_piix4_acpi - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_10, - .hook = pci_fixup_ide_trash - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_11, - .hook = pci_fixup_ide_trash - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_9, - .hook = pci_fixup_ide_trash - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8363_0, - .hook = pci_fixup_via_northbridge_bug - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8622, - .hook = pci_fixup_via_northbridge_bug - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8361, - .hook = pci_fixup_via_northbridge_bug - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8367_0, - .hook = pci_fixup_via_northbridge_bug - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_NCR, - .device = PCI_DEVICE_ID_NCR_53C810, - .hook = pci_fixup_ncr53c810 - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_ANY_ID, - .hook = pci_fixup_transparent_bridge - }, - { - .pass = PCI_FIXUP_HEADER, - .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_DEVICE_ID_NVIDIA_NFORCE2, - .hook = pci_fixup_nforce2 - }, - { .pass = 0 } +/* Max PCI Express root ports */ +#define MAX_PCIEROOT 6 +static int quirk_aspm_offset[MAX_PCIEROOT << 3]; + +#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b) + +static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) +{ + return raw_pci_ops->read(0, bus->number, devfn, where, size, value); +} + +/* + * Replace the original pci bus ops for write with a new one that will filter + * the request to insure ASPM cannot be enabled. + */ +static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +{ + u8 offset; + + offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)]; + + if ((offset) && (where == offset)) + value = value & 0xfffffffc; + + return raw_pci_ops->write(0, bus->number, devfn, where, size, value); +} + +struct pci_ops quirk_pcie_aspm_ops = { + .read = quirk_pcie_aspm_read, + .write = quirk_pcie_aspm_write, }; + +/* + * Prevents PCI Express ASPM (Active State Power Management) being enabled. + * + * Save the register offset, where the ASPM control bits are located, + * for each PCI Express device that is in the device list of + * the root port in an array for fast indexing. Replace the bus ops + * with the modified one. + */ +void pcie_rootport_aspm_quirk(struct pci_dev *pdev) +{ + int cap_base, i; + struct pci_bus *pbus; + struct pci_dev *dev; + + if ((pbus = pdev->subordinate) == NULL) + return; + + /* + * Check if the DID of pdev matches one of the six root ports. This + * check is needed in the case this function is called directly by the + * hot-plug driver. + */ + if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) || + (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1)) + return; + + if (list_empty(&pbus->devices)) { + /* + * If no device is attached to the root port at power-up or + * after hot-remove, the pbus->devices is empty and this code + * will set the offsets to zero and the bus ops to parent's bus + * ops, which is unmodified. + */ + for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i) + quirk_aspm_offset[i] = 0; + + pbus->ops = pbus->parent->ops; + } else { + /* + * If devices are attached to the root port at power-up or + * after hot-add, the code loops through the device list of + * each root port to save the register offsets and replace the + * bus ops. + */ + list_for_each_entry(dev, &pbus->devices, bus_list) { + /* There are 0 to 8 devices attached to this bus */ + cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP); + quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10; + } + pbus->ops = &quirk_pcie_aspm_ops; + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); + +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + * + */static void __devinit pci_fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 l; + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l); + if (!(l & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 2ebc7c672..7a7b35a37 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -96,15 +96,13 @@ pcibios_align_resource(void *data, struct resource *res, static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) { - struct list_head *ln; struct pci_bus *bus; struct pci_dev *dev; int idx; struct resource *r, *pr; /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); + list_for_each_entry(bus, bus_list, node) { if ((dev = bus->self)) { for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { r = &dev->resource[idx]; @@ -126,7 +124,7 @@ static void __init pcibios_allocate_resources(int pass) u16 command; struct resource *r, *pr; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_read_config_word(dev, PCI_COMMAND, &command); for(idx = 0; idx < 6; idx++) { r = &dev->resource[idx]; @@ -164,13 +162,13 @@ static void __init pcibios_allocate_resources(int pass) } } -static void __init pcibios_assign_resources(void) +static int __init pcibios_assign_resources(void) { struct pci_dev *dev = NULL; int idx; struct resource *r; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { int class = dev->class >> 8; /* Don't touch classless devices and host bridges */ @@ -204,6 +202,7 @@ static void __init pcibios_assign_resources(void) pci_assign_resource(dev, PCI_ROM_RESOURCE); } } + return 0; } void __init pcibios_resource_survey(void) @@ -212,9 +211,14 @@ void __init pcibios_resource_survey(void) pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); - pcibios_assign_resources(); } +/** + * called in fs_initcall (one below subsys_initcall), + * give a chance for motherboard reserve resources + */ +fs_initcall(pcibios_assign_resources); + int pcibios_enable_resources(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; @@ -291,7 +295,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, /* Write-combine setting is ignored, it is changed via the mtrr * interfaces on this platform. */ - if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 6aa9e5fcf..18a394c0f 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci.h" @@ -127,8 +128,15 @@ void eisa_set_level_irq(unsigned int irq) { unsigned char mask = 1 << (irq & 7); unsigned int port = 0x4d0 + (irq >> 3); - unsigned char val = inb(port); + unsigned char val; + static u16 eisa_irq_mask; + if (irq >= 16 || (1 << irq) & eisa_irq_mask) + return; + + eisa_irq_mask |= (1 << irq); + printk("PCI: setting IRQ %u as level-triggered\n", irq); + val = inb(port); if (!(val & mask)) { DBG(" -> edge"); outb(val | mask, port); @@ -452,14 +460,16 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, #endif - static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { + static struct pci_device_id pirq_440gx[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, + { }, + }; + /* 440GX has a proprietary PIRQ router -- don't use it */ - if ( pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_0, NULL) || - pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82443GX_2, NULL)) + if (pci_dev_present(pirq_440gx)) return 0; switch(device) @@ -804,7 +814,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev)); /* Update IRQ for all devices with the same pirq value */ - while ((dev2 = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { + while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); if (!pin) continue; @@ -838,7 +848,7 @@ static void __init pcibios_fixup_irqs(void) u8 pin; DBG("PCI: IRQ fixup\n"); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { /* * If the BIOS has set an out of range IRQ number, just ignore it. * Also keep track of which IRQ's are already in use. @@ -854,7 +864,7 @@ static void __init pcibios_fixup_irqs(void) } dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); #ifdef CONFIG_X86_IO_APIC /* @@ -989,13 +999,24 @@ static int __init pcibios_irq_init(void) subsys_initcall(pcibios_irq_init); -void pcibios_penalize_isa_irq(int irq) +static void pirq_penalize_isa_irq(int irq) { /* * If any ISAPnP device reports an IRQ in its list of possible * IRQ's, we try to avoid assigning it to PCI devices. */ - pirq_penalty[irq] += 100; + if (irq < 16) + pirq_penalty[irq] += 100; +} + +void pcibios_penalize_isa_irq(int irq) +{ +#ifdef CONFIG_ACPI_PCI + if (!acpi_noirq) + acpi_penalize_isa_irq(irq); + else +#endif + pirq_penalize_isa_irq(irq); } int pirq_enable_irq(struct pci_dev *dev) diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 0b95fc46d..504fb18fe 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -1,3 +1,10 @@ +/* + * Copyright (C) 2004 Matthew Wilcox + * Copyright (C) 2004 Intel Corp. + * + * This code is released under the GNU General Public License version 2. + */ + /* * mmconfig.c - Low-level direct PCI config space access via MMCONFIG */ @@ -9,7 +16,7 @@ /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ u32 pci_mmcfg_base_addr; -#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG)) +#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) /* The base address of the last MMCONFIG device accessed */ static u32 mmcfg_last_accessed_device; @@ -23,7 +30,7 @@ static inline void pci_exp_set_dev_base(int bus, int devfn) u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); if (dev_base != mmcfg_last_accessed_device) { mmcfg_last_accessed_device = dev_base; - set_fixmap(FIX_PCIE_MCFG, dev_base); + set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); } } @@ -78,9 +85,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va break; } - /* Dummy read to flush PCI write */ - readl(mmcfg_virt_addr); - spin_unlock_irqrestore(&pci_config_lock, flags); return 0; @@ -98,6 +102,13 @@ static int __init pci_mmcfg_init(void) if (!pci_mmcfg_base_addr) goto out; + /* Kludge for now. Don't use mmconfig on AMD systems because + those have some busses where mmconfig doesn't work, + and we don't parse ACPI MCFG well enough to handle that. + Remove when proper handling is added. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + goto out; + printk(KERN_INFO "PCI: Using MMCONFIG\n"); raw_pci_ops = &pci_mmcfg; pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c index d77450067..c8046737b 100644 --- a/arch/i386/pci/numa.c +++ b/arch/i386/pci/numa.c @@ -100,10 +100,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d) } pcibios_last_bus = -1; } - -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); static int __init pci_numa_init(void) { diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 700188d0f..50fc1f31e 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -365,7 +365,7 @@ void __devinit pcibios_sort(void) idx = found = 0; while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) { idx++; - for (ln=pci_devices.next; ln != &pci_devices; ln=ln->next) { + list_for_each(ln, &pci_devices) { d = pci_dev_g(ln); if (d->bus->number == bus && d->devfn == devfn) { list_del(&d->global_list); diff --git a/arch/i386/power/Makefile b/arch/i386/power/Makefile index 2e1c9ab34..8cfa4e8a7 100644 --- a/arch/i386/power/Makefile +++ b/arch/i386/power/Makefile @@ -1,3 +1,2 @@ obj-$(CONFIG_PM) += cpu.o -obj-$(CONFIG_PM_DISK) += pmdisk.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index d58d30777..adb50ba2a 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -83,10 +83,10 @@ do_fpu_end(void) static void fix_processor_context(void) { int cpu = smp_processor_id(); - struct tss_struct * t = init_tss + cpu; + struct tss_struct * t = &per_cpu(init_tss, cpu); set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ - cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; + per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); /* This does ltr */ load_LDT(¤t->active_mm->context); /* This does lldt */ @@ -148,6 +148,6 @@ void restore_processor_state(void) __restore_processor_state(&saved_context); } - +/* Needed by apm.c */ EXPORT_SYMBOL(save_processor_state); EXPORT_SYMBOL(restore_processor_state); diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S index 8e4a7baca..6e6335f89 100644 --- a/arch/i386/power/swsusp.S +++ b/arch/i386/power/swsusp.S @@ -15,83 +15,47 @@ .text -ENTRY(do_magic) - pushl %ebx - cmpl $0,8(%esp) - jne resume - call do_magic_suspend_1 - call save_processor_state +ENTRY(swsusp_arch_suspend) movl %esp, saved_context_esp - movl %eax, saved_context_eax movl %ebx, saved_context_ebx - movl %ecx, saved_context_ecx - movl %edx, saved_context_edx movl %ebp, saved_context_ebp movl %esi, saved_context_esi movl %edi, saved_context_edi pushfl ; popl saved_context_eflags - call do_magic_suspend_2 - popl %ebx + call swsusp_save ret -resume: +ENTRY(swsusp_arch_resume) movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx movl %ecx,%cr3 - call do_magic_resume_1 - movl $0,loop - cmpl $0,nr_copy_pages - je copy_done -copy_loop: - movl $0,loop2 + movl pagedir_nosave, %ebx + xorl %eax, %eax + xorl %edx, %edx .p2align 4,,7 -copy_one_page: - movl pagedir_nosave,%ecx - movl loop,%eax - movl loop2,%edx - sall $4,%eax - movl 4(%ecx,%eax),%ebx - movl (%ecx,%eax),%eax - movb (%edx,%eax),%al - movb %al,(%edx,%ebx) - movl loop2,%eax - leal 1(%eax),%edx - movl %edx,loop2 - movl %edx,%eax - cmpl $4095,%eax - jbe copy_one_page - movl loop,%eax - leal 1(%eax),%edx - movl %edx,loop - movl %edx,%eax - cmpl nr_copy_pages,%eax - jb copy_loop +copy_loop: + movl 4(%ebx,%edx),%edi + movl (%ebx,%edx),%esi + + movl $1024, %ecx + rep + movsl -copy_done: - movl $__USER_DS,%eax + incl %eax + addl $16, %edx + cmpl nr_copy_pages,%eax + jb copy_loop + .p2align 4,,7 - movw %ax, %ds - movw %ax, %es movl saved_context_esp, %esp movl saved_context_ebp, %ebp - movl saved_context_eax, %eax movl saved_context_ebx, %ebx - movl saved_context_ecx, %ecx - movl saved_context_edx, %edx movl saved_context_esi, %esi movl saved_context_edi, %edi - call restore_processor_state + pushl saved_context_eflags ; popfl - call do_magic_resume_2 - popl %ebx + call swsusp_restore ret - - .section .data.nosave -loop: - .quad 0 -loop2: - .quad 0 - .previous diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 72b48fb29..98da6394e 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -38,6 +38,10 @@ config EFI bool default y +config GENERIC_IOMAP + bool + default y + choice prompt "System type" default IA64_GENERIC @@ -72,6 +76,12 @@ config IA64_HP_ZX1 config IA64_SGI_SN2 bool "SGI-SN2" + help + Selecting this option will optimize the kernel for use on sn2 based + systems, but the resulting kernel binary will not run on other + types of ia64 systems. If you have an SGI Altix system, it's safe + to select this option. If in doubt, select ia64 generic support + instead. config IA64_HP_SIM bool "Ski-simulator" @@ -270,6 +280,9 @@ config COMPAT depends on IA32_SUPPORT default y +config IA64_MCA_RECOVERY + tristate "MCA recovery from errors other than TLB." + config PERFMON bool "Performance monitor support" help @@ -372,119 +385,7 @@ source "arch/ia64/hp/sim/Kconfig" source "arch/ia64/oprofile/Kconfig" -menu "Kernel hacking" - -choice - prompt "Physical memory granularity" - default IA64_GRANULE_64MB - -config IA64_GRANULE_16MB - bool "16MB" - help - IA-64 identity-mapped regions use a large page size called "granules". - - Select "16MB" for a small granule size. - Select "64MB" for a large granule size. This is the current default. - -config IA64_GRANULE_64MB - bool "64MB" - depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2) - -endchoice - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config IA64_PRINT_HAZARDS - bool "Print possible IA-64 dependency violations to console" - depends on DEBUG_KERNEL - help - Selecting this option prints more information for Illegal Dependency - Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW), - or Write-after-Read (WAR) 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. - -config DISABLE_VHPT - bool "Disable VHPT" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config IA64_DEBUG_CMPXCHG - bool "Turn on compare-and-exchange bug checking (slow!)" - depends on DEBUG_KERNEL - help - Selecting this option turns on bug checking for the IA-64 - compare-and-exchange instructions. This is slow! Itaniums - from step B3 or later don't have this problem. If you're unsure, - select N. - -config IA64_DEBUG_IRQ - bool "Turn on irq debug checks (slow!)" - depends on DEBUG_KERNEL - help - Selecting this option turns on bug checking for the IA-64 irq_save - and restore instructions. It's useful for tracking down spinlock - problems, but slow! If you're unsure, select N. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y -endmenu +source "arch/ia64/Kconfig.debug" source "security/Kconfig" diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index f2ca1e231..2932ac71b 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -13,6 +13,8 @@ READELF := $(CROSS_COMPILE)readelf export AWK +CHECKFLAGS += -m64 -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__ + OBJCOPYFLAGS := --strip-all LDFLAGS_vmlinux := -static LDFLAGS_MODULE += -T $(srctree)/arch/ia64/module.lds @@ -20,14 +22,12 @@ AFLAGS_KERNEL := -mconstant-gp EXTRA := cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ - -falign-functions=32 -frename-registers + -falign-functions=32 -frename-registers -fno-optimize-sibling-calls CFLAGS_KERNEL := -mconstant-gp -GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') -GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') - -GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) -CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP) $(READELF)) +GCC_VERSION := $(call cc-version) +GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)") +CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") ifeq ($(GAS_STATUS),buggy) $(error Sorry, you need a newer version of the assember, one that is built from \ @@ -37,16 +37,13 @@ $(error Sorry, you need a newer version of the assember, one that is built from ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz) endif -ifeq ($(GCC_VERSION),2) +ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),) $(error Sorry, your compiler is too old. GCC v2.96 is known to generate bad code.) endif -ifeq ($(GCC_VERSION),3) - ifeq ($(GCC_MINOR_VERSION),4) -# Workaround Itanium 1 bugs in gcc 3.4. -# cflags-$(CONFIG_ITANIUM) += -mtune=merced +ifeq ($(GCC_VERSION),0304) + cflags-$(CONFIG_ITANIUM) += -mtune=merced cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley - endif endif cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC) += -mb-step @@ -85,7 +82,9 @@ unwcheck: vmlinux archclean: $(Q)$(MAKE) $(clean)=$(boot) -CLEAN_FILES += include/asm-ia64/.offsets.h.stamp include/asm-ia64/offsets.h vmlinux.gz bootloader +CLEAN_FILES += include/asm-ia64/.offsets.h.stamp vmlinux.gz bootloader + +MRPROPER_FILES += include/asm-ia64/offsets.h prepare: include/asm-ia64/offsets.h diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig index f16fd2e14..74756c015 100644 --- a/arch/ia64/configs/bigsur_defconfig +++ b/arch/ia64/configs/bigsur_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.9-rc2 -# Tue Sep 28 13:26:53 2004 +# Linux kernel version: 2.6.10-rc2 +# Mon Nov 29 13:27:48 2004 # # @@ -9,6 +9,7 @@ # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup @@ -22,6 +23,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=16 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -29,12 +31,12 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set # @@ -45,6 +47,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -84,6 +87,7 @@ CONFIG_PREEMPT=y CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +# CONFIG_IA64_MCA_RECOVERY is not set CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y @@ -107,9 +111,11 @@ CONFIG_ACPI=y CONFIG_ACPI_BOOT=y CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m CONFIG_ACPI_FAN=m CONFIG_ACPI_PROCESSOR=m CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y @@ -131,9 +137,13 @@ CONFIG_PCI_NAMES=y # CONFIG_HOTPLUG_PCI is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set # # Device Drivers @@ -160,6 +170,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # +# CONFIG_PNP is not set # # Block devices @@ -175,6 +186,16 @@ CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -193,7 +214,6 @@ CONFIG_BLK_DEV_IDECD=m CONFIG_BLK_DEV_IDEFLOPPY=m # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -282,12 +302,14 @@ CONFIG_SCSI_SPI_ATTRS=m # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR 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_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -311,6 +333,7 @@ CONFIG_MD_RAID10=m CONFIG_MD_RAID5=m CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m @@ -357,6 +380,8 @@ CONFIG_INET=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -376,7 +401,6 @@ CONFIG_INET=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -437,7 +461,6 @@ CONFIG_EEPRO100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -450,6 +473,7 @@ CONFIG_EEPRO100=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # @@ -549,7 +573,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_ACPI is not set +CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y @@ -627,6 +651,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set @@ -644,14 +669,17 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set @@ -773,7 +801,7 @@ CONFIG_SND_CS4281=m # CONFIG_SND_VX222 is not set # -# ALSA USB devices +# USB devices # # CONFIG_SND_USB_AUDIO is not set # CONFIG_SND_USB_USX2Y is not set @@ -797,6 +825,8 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -826,7 +856,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_JUMPSHOT is not set # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=m CONFIG_USB_HIDINPUT=y @@ -864,7 +894,7 @@ CONFIG_USB_HIDDEV=y # # -# USB Network adaptors +# USB Network Adapters # # CONFIG_USB_CATC is not set # CONFIG_USB_KAWETH is not set @@ -893,9 +923,14 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # @@ -925,6 +960,7 @@ CONFIG_XFS_POSIX_ACL=y # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -957,6 +993,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -1087,9 +1124,11 @@ CONFIG_OPROFILE=y # CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_IA64_GRANULE_16MB is not set CONFIG_IA64_GRANULE_64MB=y @@ -1102,6 +1141,7 @@ CONFIG_SYSVIPC_COMPAT=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -1115,7 +1155,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WHIRLPOOL is not set +# CONFIG_CRYPTO_WP512 is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set @@ -1126,6 +1166,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 2797cb4eb..d62ec979b 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1 +# Mon Nov 1 14:35:44 2004 # # @@ -7,11 +9,12 @@ # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -20,6 +23,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -27,11 +31,13 @@ CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -41,6 +47,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -53,6 +60,7 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_TIME_INTERPOLATION=y CONFIG_EFI=y +CONFIG_GENERIC_IOMAP=y # CONFIG_IA64_GENERIC is not set # CONFIG_IA64_DIG is not set # CONFIG_IA64_HP_ZX1 is not set @@ -75,10 +83,11 @@ CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=512 # CONFIG_HOTPLUG_CPU is not set -# CONFIG_PREEMPT is not set +CONFIG_PREEMPT=y CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y @@ -104,6 +113,7 @@ CONFIG_ACPI_INTERPRETER=y # CONFIG_ACPI_FAN is not set # CONFIG_ACPI_PROCESSOR is not set CONFIG_ACPI_NUMA=y +CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y @@ -115,7 +125,7 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -# CONFIG_PCI_USE_VECTOR is not set +# CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y @@ -131,9 +141,13 @@ CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_SGI=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set # # Device Drivers @@ -142,6 +156,7 @@ CONFIG_HOTPLUG_PCI_SGI=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set @@ -171,9 +186,20 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -185,13 +211,13 @@ CONFIG_BLK_DEV_IDE=y # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_IDEDISK is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -206,7 +232,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -273,8 +298,10 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set # CONFIG_SCSI_SATA_SVW is not set # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_NV is not set @@ -282,6 +309,7 @@ CONFIG_SCSI_SATA=y # CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set # CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set # CONFIG_SCSI_SATA_VIA is not set CONFIG_SCSI_SATA_VITESSE=y # CONFIG_SCSI_BUSLOGIC is not set @@ -291,12 +319,14 @@ CONFIG_SCSI_SATA_VITESSE=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR 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_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set CONFIG_SCSI_QLA22XX=y @@ -316,6 +346,7 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=y @@ -329,8 +360,7 @@ CONFIG_DM_ZERO=m # Fusion MPT device support # CONFIG_FUSION=y -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m +CONFIG_FUSION_MAX_SGE=128 CONFIG_FUSION_CTL=m # @@ -368,11 +398,13 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set # CONFIG_NETFILTER is not set @@ -392,7 +424,6 @@ CONFIG_IPV6=m # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -527,6 +558,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_STALDRV is not set +CONFIG_SGI_SNSC=y # # Serial drivers @@ -537,11 +569,11 @@ CONFIG_SERIAL_NONSTANDARD=y # Non-8250 serial port support # CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -566,6 +598,7 @@ CONFIG_EFI_RTC=y CONFIG_RAW_DRIVER=m # CONFIG_HPET is not set CONFIG_MAX_RAW_DEVS=256 +CONFIG_MMTIMER=y # # I2C support @@ -600,7 +633,6 @@ CONFIG_MAX_RAW_DEVS=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -620,6 +652,9 @@ CONFIG_USB=m # CONFIG_USB_DEVICEFS is not set # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -639,7 +674,7 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_STORAGE is not set # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=m CONFIG_USB_HIDINPUT=y @@ -706,8 +741,13 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # @@ -716,7 +756,7 @@ CONFIG_USB_HIDINPUT=y # # File systems # -CONFIG_EXT2_FS=m +CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y @@ -746,6 +786,7 @@ CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -777,6 +818,8 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -791,7 +834,6 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -816,10 +858,12 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set # CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -906,23 +950,26 @@ CONFIG_ZLIB_DEFLATE=m # # Kernel hacking # -CONFIG_IA64_GRANULE_16MB=y -# CONFIG_IA64_GRANULE_64MB is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_IA64_PRINT_HAZARDS is not set -# CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_DEBUG_INFO=y CONFIG_SYSVIPC_COMPAT=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -936,6 +983,7 @@ CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set @@ -945,6 +993,7 @@ CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index ce9412586..2af017461 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.9-rc2 -# Tue Sep 28 09:03:25 2004 +# Linux kernel version: 2.6.10-rc1 +# Tue Nov 2 11:35:10 2004 # # @@ -9,6 +9,7 @@ # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup @@ -22,6 +23,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set @@ -30,12 +32,12 @@ CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set # @@ -46,6 +48,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -83,6 +86,7 @@ CONFIG_HOTPLUG_CPU=y CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y @@ -109,6 +113,7 @@ CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m CONFIG_ACPI_PROCESSOR=m CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y @@ -136,9 +141,13 @@ CONFIG_HOTPLUG_PCI_ACPI=m # CONFIG_HOTPLUG_PCI_SHPC is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set # # Device Drivers @@ -180,6 +189,16 @@ CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -198,7 +217,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=m # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -288,6 +306,7 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 @@ -299,6 +318,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 CONFIG_SCSI_QLOGIC_FC=y # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y CONFIG_SCSI_QLA21XX=m CONFIG_SCSI_QLA22XX=m @@ -371,6 +391,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -390,7 +411,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -463,7 +483,6 @@ CONFIG_E100=m # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -477,6 +496,7 @@ CONFIG_E1000=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # @@ -691,6 +711,8 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -720,7 +742,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_JUMPSHOT is not set # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y @@ -781,9 +803,14 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # @@ -819,6 +846,7 @@ CONFIG_XFS_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -852,6 +880,8 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -983,9 +1013,11 @@ CONFIG_CRC32=y # CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_IA64_GRANULE_16MB=y # CONFIG_IA64_GRANULE_64MB is not set @@ -998,6 +1030,7 @@ CONFIG_SYSVIPC_COMPAT=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -1011,7 +1044,7 @@ CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WHIRLPOOL is not set +# CONFIG_CRYPTO_WP512 is not set CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index e9eda7323..7ef08d376 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.9-rc2-aegl +# Mon Sep 27 19:03:13 2004 # # @@ -7,33 +9,45 @@ # CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set -CONFIG_STANDALONE=y CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=17 CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set # # Processor type and features @@ -44,54 +58,53 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_TIME_INTERPOLATION=y CONFIG_EFI=y -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y +CONFIG_GENERIC_IOMAP=y # CONFIG_IA64_GENERIC is not set # CONFIG_IA64_DIG is not set CONFIG_IA64_HP_ZX1=y # CONFIG_IA64_SGI_SN2 is not set # CONFIG_IA64_HP_SIM is not set +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_ACPI=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_KERNEL_CONFIG=y CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set # CONFIG_NUMA is not set CONFIG_VIRTUAL_MEM_MAP=y -CONFIG_IA64_MCA=y # CONFIG_IA64_CYCLONE is not set -CONFIG_PM=y CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=18 -# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set -# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set -CONFIG_HUGETLB_PAGE_SIZE_64MB=y -# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set -CONFIG_IA64_PAL_IDLE=y CONFIG_SMP=y CONFIG_NR_CPUS=16 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y + +# +# Firmware Drivers +# CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y +# +# Power management and ACPI +# +CONFIG_PM=y +CONFIG_ACPI=y + # # ACPI (Advanced Configuration and Power Interface) Support # CONFIG_ACPI_BOOT=y +CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y @@ -101,8 +114,13 @@ CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y + +# +# Bus options (PCI, PCMCIA) +# CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y @@ -112,6 +130,7 @@ CONFIG_PCI_NAMES=y CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set # CONFIG_HOTPLUG_PCI_CPCI is not set # CONFIG_HOTPLUG_PCI_PCIE is not set # CONFIG_HOTPLUG_PCI_SHPC is not set @@ -122,20 +141,27 @@ CONFIG_HOTPLUG_PCI_ACPI=y # CONFIG_PCMCIA is not set # -# Parallel port support +# Device Drivers # -# CONFIG_PARPORT is not set # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set # # Memory Technology Devices (MTD) # # CONFIG_MTD is not set +# +# Parallel port support +# +# CONFIG_PARPORT is not set + # # Plug and Play support # @@ -143,7 +169,6 @@ CONFIG_HOTPLUG_PCI_ACPI=y # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -151,10 +176,11 @@ CONFIG_HOTPLUG_PCI_ACPI=y CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support @@ -165,9 +191,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -187,7 +213,6 @@ CONFIG_BLK_DEV_GENERIC=y CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set # CONFIG_IDEDMA_PCI_AUTO is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -208,32 +233,12 @@ CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -CONFIG_FUSION=y -CONFIG_FUSION_BOOT=y -CONFIG_FUSION_MAX_SGE=40 - # # SCSI device support # @@ -254,21 +259,28 @@ CONFIG_CHR_DEV_SG=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set + # # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_ADVANSYS is not set -CONFIG_SCSI_MEGARAID=y +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set @@ -285,6 +297,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set @@ -301,6 +314,28 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_CTL is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + # # Networking support # @@ -322,19 +357,17 @@ CONFIG_IP_MULTICAST=y # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set # # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -353,10 +386,11 @@ CONFIG_IP_NF_ARPTABLES=y # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -371,21 +405,27 @@ CONFIG_IPV6_SCTP__=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # 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) @@ -429,6 +469,7 @@ CONFIG_E100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -441,7 +482,6 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set CONFIG_TIGON3=y @@ -449,47 +489,39 @@ CONFIG_TIGON3=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +# CONFIG_S2IO is not set # # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set # -# Amateur Radio support +# Wireless LAN (non-hamradio) # -# CONFIG_HAMRADIO is not set +# CONFIG_NET_RADIO is not set # -# IrDA (infrared) support +# Wan interfaces # -# CONFIG_IRDA is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # -# Bluetooth support +# ISDN subsystem # -# CONFIG_BT is not set +# CONFIG_ISDN is not set # -# ISDN subsystem +# Telephony Support # -# CONFIG_ISDN is not set +# CONFIG_PHONE is not set # # Input device support @@ -518,6 +550,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -541,7 +574,6 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_HCDP=y CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_NR_UARTS=8 CONFIG_SERIAL_8250_EXTENDED=y @@ -559,12 +591,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - # # IPMI # @@ -575,8 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_GEN_RTC is not set CONFIG_EFI_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -585,7 +609,6 @@ CONFIG_EFI_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set CONFIG_AGP=y CONFIG_AGP_HP_ZX1=y CONFIG_DRM=y @@ -596,6 +619,7 @@ CONFIG_DRM_RADEON=y # CONFIG_DRM_MGA is not set # CONFIG_DRM_SIS is not set # CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set # # I2C support @@ -608,11 +632,13 @@ CONFIG_I2C_CHARDEV=y # CONFIG_I2C_ALGOBIT=y CONFIG_I2C_ALGOPCF=y +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support # # CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set @@ -630,29 +656,55 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # -# I2C Hardware Sensors Chip support +# Hardware Sensors Chip support # # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set + +# +# Other I2C Chip support +# +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set # CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + # # Multimedia devices # @@ -663,6 +715,167 @@ CONFIG_I2C_ALGOPCF=y # # CONFIG_DVB is not set +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_DEBUG=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_UHCI_HCD=y + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT 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_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETSERVO is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + # # File systems # @@ -693,6 +906,7 @@ CONFIG_ISO9660_FS=y CONFIG_JOLIET=y # CONFIG_ZISOFS is not set CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -700,6 +914,8 @@ CONFIG_UDF_FS=y CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -707,6 +923,7 @@ CONFIG_VFAT_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y @@ -747,11 +964,12 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -769,7 +987,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -803,6 +1020,7 @@ CONFIG_NLS_CODEPAGE_874=y CONFIG_NLS_ISO8859_8=y # CONFIG_NLS_CODEPAGE_1250 is not set CONFIG_NLS_CODEPAGE_1251=y +# CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_2=y CONFIG_NLS_ISO8859_3=y @@ -818,227 +1036,12 @@ CONFIG_NLS_KOI8_R=y CONFIG_NLS_KOI8_U=y CONFIG_NLS_UTF8=y -# -# Graphics support -# -CONFIG_FB=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set -CONFIG_FB_RADEON=y -CONFIG_FB_RADEON_I2C=y -CONFIG_FB_RADEON_DEBUG=y -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_PCI_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=y -CONFIG_SND_SEQUENCER=y -# CONFIG_SND_SEQ_DUMMY is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_VIRMIDI is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# PCI devices -# -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_YMFPCI is not set -# CONFIG_SND_ALS4000 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_MAESTRO3 is not set -CONFIG_SND_FM801=y -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VX222 is not set - -# -# ALSA USB devices -# -# CONFIG_SND_USB_AUDIO is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set -CONFIG_USB_BANDWIDTH=y -# CONFIG_USB_DYNAMIC_MINORS is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_UHCI_HCD=y - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH_TTY is not set -# CONFIG_USB_MIDI is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -CONFIG_USB_STORAGE=y -# 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_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_XPAD is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set # # Profiling support @@ -1048,18 +1051,19 @@ CONFIG_CRC32=y # # Kernel hacking # -CONFIG_IA64_GRANULE_16MB=y -# CONFIG_IA64_GRANULE_64MB is not set 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 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +CONFIG_IA64_PRINT_HAZARDS=y +# CONFIG_DISABLE_VHPT is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set -# CONFIG_DEBUG_INFO is not set +CONFIG_SYSVIPC_COMPAT=y # # Security options @@ -1069,4 +1073,26 @@ CONFIG_MAGIC_SYSRQ=y # # Cryptographic options # -# CONFIG_CRYPTO is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WHIRLPOOL is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index b63441d85..c7fc9df17 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -1,50 +1,54 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1 +# Tue Nov 2 11:47:56 2004 # # # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -# CONFIG_STANDALONE is not set -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y +CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y -CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=16 +CONFIG_LOG_BUF_SHIFT=20 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support # CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -57,9 +61,10 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_TIME_INTERPOLATION=y CONFIG_EFI=y -# CONFIG_IA64_GENERIC is not set +CONFIG_GENERIC_IOMAP=y +CONFIG_IA64_GENERIC=y # CONFIG_IA64_DIG is not set -CONFIG_IA64_HP_ZX1=y +# CONFIG_IA64_HP_ZX1 is not set # CONFIG_IA64_SGI_SN2 is not set # CONFIG_IA64_HP_SIM is not set # CONFIG_ITANIUM is not set @@ -69,18 +74,20 @@ CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 -# CONFIG_NUMA is not set +CONFIG_NUMA=y CONFIG_VIRTUAL_MEM_MAP=y -# CONFIG_IA64_CYCLONE is not set +CONFIG_DISCONTIGMEM=y +CONFIG_IA64_CYCLONE=y CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y -CONFIG_NR_CPUS=16 -# CONFIG_HOTPLUG_CPU is not set +CONFIG_NR_CPUS=512 +CONFIG_HOTPLUG_CPU=y # CONFIG_PREEMPT is not set CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y @@ -90,7 +97,7 @@ CONFIG_IA64_PALINFO=y CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y +CONFIG_BINFMT_MISC=m # # Power management and ACPI @@ -103,10 +110,12 @@ CONFIG_ACPI=y # CONFIG_ACPI_BOOT=y CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y @@ -118,19 +127,29 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -# CONFIG_PCI_USE_VECTOR is not set +# CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y # # PCI Hotplug Support # -# CONFIG_HOTPLUG_PCI is not set +CONFIG_HOTPLUG_PCI=m +# CONFIG_HOTPLUG_PCI_FAKE is not set +CONFIG_HOTPLUG_PCI_ACPI=m +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set # # Device Drivers @@ -139,6 +158,7 @@ CONFIG_PCI_NAMES=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set @@ -164,13 +184,23 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -183,20 +213,19 @@ CONFIG_BLK_DEV_IDE=y # # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_MULTI_MODE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=m +CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=m -CONFIG_IDE_TASK_IOCTL=y -CONFIG_IDE_TASKFILE_IO=y +# CONFIG_IDE_TASK_IOCTL is not set # # IDE chipset support/bugfixes # -# CONFIG_IDE_GENERIC is not set +CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set @@ -204,7 +233,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -216,12 +244,13 @@ CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set +CONFIG_BLK_DEV_PIIX=y # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_BLK_DEV_PDC202XX_NEW is not set # CONFIG_BLK_DEV_SVWKS is not set -CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SGIIOC4=y +# CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set @@ -241,24 +270,24 @@ CONFIG_SCSI_PROC_FS=y # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -CONFIG_CHR_DEV_OSST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_ST=m +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set # # SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_FC_ATTRS=y # # SCSI low-level drivers @@ -268,13 +297,12 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set -CONFIG_SCSI_AIC7XXX_OLD=y +# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set -CONFIG_SCSI_MEGARAID=y +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set @@ -289,16 +317,16 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set +CONFIG_SCSI_QLOGIC_FC=y +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m # CONFIG_SCSI_QLA6312 is not set # CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set @@ -313,21 +341,21 @@ CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=m -# CONFIG_MD_RAID6 is not set +CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m -# CONFIG_DM_CRYPT is not set -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # # Fusion MPT device support # CONFIG_FUSION=y CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set # CONFIG_FUSION_CTL is not set # @@ -350,7 +378,7 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set +CONFIG_NETLINK_DEV=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -360,31 +388,15 @@ CONFIG_IP_MULTICAST=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y # CONFIG_IPV6 is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -CONFIG_IP_NF_ARPTABLES=y -# CONFIG_IP_NF_ARPFILTER is not set -# CONFIG_IP_NF_ARP_MANGLE is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) @@ -402,7 +414,6 @@ CONFIG_IP_NF_ARPTABLES=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -414,16 +425,19 @@ CONFIG_IP_NF_ARPTABLES=y # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set CONFIG_NETDEVICES=y -CONFIG_DUMMY=y -CONFIG_BONDING=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # ARCnet devices @@ -434,7 +448,7 @@ CONFIG_BONDING=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MII=y +CONFIG_MII=m # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -442,7 +456,15 @@ CONFIG_MII=y # # Tulip family network device support # -# CONFIG_NET_TULIP is not set +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_NAPI is not set +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set # CONFIG_HP100 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set @@ -451,9 +473,10 @@ CONFIG_NET_PCI=y # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set -CONFIG_EEPRO100=y +CONFIG_EEPRO100=m # CONFIG_EEPRO100_PIO is not set -# CONFIG_E100 is not set +CONFIG_E100=m +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -463,7 +486,6 @@ CONFIG_EEPRO100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -477,6 +499,7 @@ CONFIG_E1000=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # @@ -505,7 +528,7 @@ CONFIG_TIGON3=y # CONFIG_SLIP is not set # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set +CONFIG_NETCONSOLE=y # # ISDN subsystem @@ -529,27 +552,42 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=y +# CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set # # Input I/O drivers # -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y +CONFIG_GAMEPORT=m +CONFIG_SOUND_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -560,7 +598,14 @@ CONFIG_SERIO=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_STALDRV is not set +CONFIG_SGI_SNSC=y # # Serial drivers @@ -568,28 +613,27 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_ACPI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_SGI_L1_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI # -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_PANIC_STRING=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_WATCHDOG=m +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards @@ -604,90 +648,26 @@ CONFIG_EFI_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set CONFIG_AGP=m +CONFIG_AGP_I460=m CONFIG_AGP_HP_ZX1=m CONFIG_DRM=y -# CONFIG_DRM_TDFX is not set -# CONFIG_DRM_GAMMA is not set -# CONFIG_DRM_R128 is not set +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m CONFIG_DRM_RADEON=m -# CONFIG_DRM_MGA is not set -# CONFIG_DRM_SIS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HPET is not set +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_RAW_DRIVER=m +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +CONFIG_HPET_MMAP=y +CONFIG_MAX_RAW_DEVS=256 +CONFIG_MMTIMER=y # # I2C support # -CONFIG_I2C=y -# CONFIG_I2C_CHARDEV is not set - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_ISA is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set - -# -# Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_I2C is not set # # Dallas's 1-wire bus @@ -711,53 +691,18 @@ CONFIG_I2C_ALGOBIT=y # # Graphics support # -CONFIG_FB=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -CONFIG_FB_RIVA=m -CONFIG_FB_RIVA_I2C=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set -CONFIG_FB_RADEON=m -CONFIG_FB_RADEON_I2C=y -# CONFIG_FB_RADEON_DEBUG is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB is not set # # Console display driver support # CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y # # Sound # -CONFIG_SOUND=y +CONFIG_SOUND=m # # Advanced Linux Sound Architecture @@ -768,11 +713,12 @@ CONFIG_SND_PCM=m CONFIG_SND_HWDEP=m CONFIG_SND_RAWMIDI=m CONFIG_SND_SEQUENCER=m -# CONFIG_SND_SEQ_DUMMY is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set -# CONFIG_SND_SEQUENCER_OSS is not set -# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_VERBOSE_PRINTK=y # CONFIG_SND_DEBUG is not set # @@ -780,11 +726,11 @@ CONFIG_SND_SEQUENCER=m # CONFIG_SND_MPU401_UART=m CONFIG_SND_OPL3_LIB=m -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_VIRMIDI is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m # # PCI devices @@ -792,14 +738,16 @@ CONFIG_SND_OPL3_LIB=m CONFIG_SND_AC97_CODEC=m # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set # CONFIG_SND_AU8830 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_EMU10K1 is not set +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS4281=m +CONFIG_SND_EMU10K1=m # CONFIG_SND_KORG1212 is not set # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set @@ -827,9 +775,10 @@ CONFIG_SND_FM801=m # CONFIG_SND_VX222 is not set # -# ALSA USB devices +# USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_USX2Y is not set # # Open Sound System @@ -839,24 +788,28 @@ CONFIG_SND_FM801=m # # USB support # -CONFIG_USB=y +CONFIG_USB=m # CONFIG_USB_DEBUG is not set # # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y -CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers # -CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_UHCI_HCD=m # # USB Device Class drivers @@ -866,15 +819,31 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_MIDI is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set -# CONFIG_USB_STORAGE is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT 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_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set # -# USB Human Interface Devices (HID) +# USB HID Boot Protocol drivers # -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set # CONFIG_USB_KBTAB is not set @@ -930,9 +899,14 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # @@ -943,42 +917,55 @@ CONFIG_USB_HIDDEV=y # CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +# CONFIG_XFS_POSIX_ACL is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y -# CONFIG_AUTOFS4_FS is not set +CONFIG_AUTOFS4_FS=y # # CD-ROM/DVD Filesystems # -CONFIG_ISO9660_FS=y +CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_ZISOFS is not set -CONFIG_UDF_FS=y +CONFIG_UDF_FS=m CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set # # Pseudo filesystems @@ -989,6 +976,8 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -1003,7 +992,6 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -1014,22 +1002,28 @@ CONFIG_RAMFS=y # # Network File Systems # -CONFIG_NFS_FS=y +CONFIG_NFS_FS=m CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_NFS_DIRECTIO=y -CONFIG_NFSD=y +CONFIG_NFSD=m CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=y -CONFIG_RPCSEC_GSS_KRB5=y -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1049,7 +1043,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set +CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set CONFIG_EFI_PARTITION=y @@ -1060,43 +1054,43 @@ CONFIG_EFI_PARTITION=y CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y -# 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_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +# CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y -# 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 +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m # # Library routines @@ -1105,6 +1099,13 @@ CONFIG_NLS_ISO8859_1=y CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +# +# HP Simulator drivers +# +# CONFIG_HP_SIMETH is not set +# CONFIG_HP_SIMSERIAL is not set +# CONFIG_HP_SIMSCSI is not set + # # Profiling support # @@ -1113,24 +1114,26 @@ CONFIG_CRC32=y # # Kernel hacking # -CONFIG_IA64_GRANULE_16MB=y -# CONFIG_IA64_GRANULE_64MB is not set CONFIG_DEBUG_KERNEL=y -CONFIG_IA64_PRINT_HAZARDS=y -# CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_IA64_EARLY_PRINTK_VGA is not set +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_DEBUG_INFO=y CONFIG_SYSVIPC_COMPAT=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -1140,11 +1143,12 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set -CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_WP512 is not set +CONFIG_CRYPTO_DES=m # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set @@ -1153,6 +1157,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index 5333e6190..472d376b4 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -33,13 +33,14 @@ #include #include #include +#include +#include /* hweight64() */ #include /* ia64_get_itc() */ #include #include /* PAGE_OFFSET */ #include #include /* wmb() */ -#include /* hweight64() */ #include @@ -191,7 +192,7 @@ static unsigned long iovp_shift; static unsigned long iovp_mask; struct ioc { - void *ioc_hpa; /* I/O MMU base address */ + void __iomem *ioc_hpa; /* I/O MMU base address */ char *res_map; /* resource map, bit == pdir entry */ u64 *pdir_base; /* physical base address */ unsigned long ibase; /* pdir IOV Space base */ @@ -203,6 +204,9 @@ struct ioc { /* clearing pdir to prevent races with allocations. */ unsigned int res_bitshift; /* from the RIGHT! */ unsigned int res_size; /* size of resource map in bytes */ +#ifdef CONFIG_NUMA + unsigned int node; /* node where this IOC lives */ +#endif #if DELAYED_RESOURCE_CNT > 0 spinlock_t saved_lock; /* may want to try to get this on a separate cacheline */ /* than res_lock for bigger systems. */ @@ -475,7 +479,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) * purges IOTLB entries in power-of-two sizes, so we also * allocate IOVA space in power-of-two sizes. */ - bits_wanted = 1UL << get_iovp_order(bits_wanted << PAGE_SHIFT); + bits_wanted = 1UL << get_iovp_order(bits_wanted << iovp_shift); if (likely(bits_wanted == 1)) { unsigned int bitshiftcnt; @@ -684,7 +688,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) unsigned long m; /* Round up to power-of-two size: see AR2305 note above */ - bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << PAGE_SHIFT); + bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << iovp_shift); for (; bits_not_wanted > 0 ; res_ptr++) { if (unlikely(bits_not_wanted > BITS_PER_LONG)) { @@ -1057,7 +1061,24 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int struct ioc *ioc; void *addr; + ioc = GET_IOC(dev); + ASSERT(ioc); + +#ifdef CONFIG_NUMA + { + struct page *page; + page = alloc_pages_node(ioc->node == MAX_NUMNODES ? + numa_node_id() : ioc->node, flags, + get_order(size)); + + if (unlikely(!page)) + return NULL; + + addr = page_address(page); + } +#else addr = (void *) __get_free_pages(flags, get_order(size)); +#endif if (unlikely(!addr)) return NULL; @@ -1081,8 +1102,6 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int * If device can't bypass or bypass is disabled, pass the 32bit fake * device to map single to get an iova mapping. */ - ioc = GET_IOC(dev); - ASSERT(ioc); *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); return addr; @@ -1135,7 +1154,7 @@ sba_fill_pdir( { struct scatterlist *dma_sg = startsg; /* pointer to current DMA */ int n_mappings = 0; - u64 *pdirp = 0; + u64 *pdirp = NULL; unsigned long dma_offset = 0; dma_sg--; @@ -1799,6 +1818,10 @@ ioc_show(struct seq_file *s, void *v) seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); +#ifdef CONFIG_NUMA + if (ioc->node != MAX_NUMNODES) + seq_printf(s, "NUMA node : %d\n", ioc->node); +#endif seq_printf(s, "IOVA size : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024)); seq_printf(s, "IOVA page size : %ld kb\n", iovp_size/1024); @@ -1853,7 +1876,7 @@ ioc_proc_init(void) { struct proc_dir_entry *dir, *entry; - dir = proc_mkdir("bus/mckinley", 0); + dir = proc_mkdir("bus/mckinley", NULL); if (!dir) return; @@ -1899,6 +1922,58 @@ sba_connect_bus(struct pci_bus *bus) printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number); } +#ifdef CONFIG_NUMA +static void __init +sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle) +{ + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; + acpi_handle phandle; + unsigned int node; + + ioc->node = MAX_NUMNODES; + + /* + * Check for a _PXM on this node first. We don't typically see + * one here, so we'll end up getting it from the parent. + */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) { + if (ACPI_FAILURE(acpi_get_parent(handle, &phandle))) + return; + + /* Reset the acpi buffer */ + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL, + &buffer))) + return; + } + + if (!buffer.length || !buffer.pointer) + return; + + obj = buffer.pointer; + + if (obj->type != ACPI_TYPE_INTEGER || + obj->integer.value >= MAX_PXM_DOMAINS) { + acpi_os_free(buffer.pointer); + return; + } + + node = pxm_to_nid_map[obj->integer.value]; + acpi_os_free(buffer.pointer); + + if (node >= MAX_NUMNODES || !node_online(node)) + return; + + ioc->node = node; + return; +} +#else +#define sba_map_ioc_to_node(ioc, handle) +#endif + static int __init acpi_sba_ioc_add(struct acpi_device *device) { @@ -1941,6 +2016,8 @@ acpi_sba_ioc_add(struct acpi_device *device) if (!ioc) return 1; + /* setup NUMA node association */ + sba_map_ioc_to_node(ioc, device->handle); return 0; } diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 3c9c3072b..45d69f4d3 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 381277884..786e70718 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -50,10 +50,6 @@ #define _INLINE_ inline #endif -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) #define SSC_GETCHAR 21 @@ -275,7 +271,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) * Then from the beginning of the buffer until necessary */ - count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), + count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE), SERIAL_XMIT_SIZE - info->xmit.tail); console->write(console, info->xmit.buf+info->xmit.tail, count); @@ -305,7 +301,7 @@ static void rs_flush_chars(struct tty_struct *tty) } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -314,58 +310,22 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit.buf || !tmp_buf) return 0; - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - - local_irq_save(flags); - { - c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - } - local_irq_restore(flags); - - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - local_irq_save(flags); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; + local_irq_save(flags); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; } - local_irq_restore(flags); + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; } + local_irq_restore(flags); /* * Hey, we transmit directly from here in our case */ @@ -1055,7 +1015,7 @@ simrs_init (void) ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); } - printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n", + printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n", state->line, state->port, state->irq, uart_config[state->type].name); diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index 9618f6282..ca468cd95 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -48,6 +48,7 @@ static void elf32_set_personality (void); extern struct page *ia32_shared_page[]; extern unsigned long *ia32_gdt; +extern struct page *ia32_gate_page; struct page * ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type) @@ -59,10 +60,25 @@ ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int return pg; } +struct page * +ia32_install_gate_page (struct vm_area_struct *vma, unsigned long address, int *type) +{ + struct page *pg = ia32_gate_page; + get_page(pg); + if (type) + *type = VM_FAULT_MINOR; + return pg; +} + + static struct vm_operations_struct ia32_shared_page_vm_ops = { .nopage = ia32_install_shared_page }; +static struct vm_operations_struct ia32_gate_page_vm_ops = { + .nopage = ia32_install_gate_page +}; + void ia64_elf32_init (struct pt_regs *regs) { @@ -84,7 +100,38 @@ ia64_elf32_init (struct pt_regs *regs) vma->vm_ops = &ia32_shared_page_vm_ops; down_write(¤t->mm->mmap_sem); { - insert_vm_struct(current->mm, vma); + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } + } + up_write(¤t->mm->mmap_sem); + } + + /* + * When user stack is not executable, push sigreturn code to stack makes + * segmentation fault raised when returning to kernel. So now sigreturn + * code is locked in specific gate page, which is pointed by pretcode + * when setup_frame_ia32 + */ + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + if (vma) { + memset(vma, 0, sizeof(*vma)); + vma->vm_mm = current->mm; + vma->vm_start = IA32_GATE_OFFSET; + vma->vm_end = vma->vm_start + PAGE_SIZE; + vma->vm_page_prot = PAGE_COPY_EXEC; + vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC + | VM_MAYEXEC | VM_RESERVED; + vma->vm_ops = &ia32_gate_page_vm_ops; + down_write(¤t->mm->mmap_sem); + { + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } } up_write(¤t->mm->mmap_sem); } @@ -103,7 +150,11 @@ ia64_elf32_init (struct pt_regs *regs) vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE; down_write(¤t->mm->mmap_sem); { - insert_vm_struct(current->mm, vma); + if (insert_vm_struct(current->mm, vma)) { + kmem_cache_free(vm_area_cachep, vma); + up_write(¤t->mm->mmap_sem); + return; + } } up_write(¤t->mm->mmap_sem); } @@ -151,7 +202,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -186,8 +237,12 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)? PAGE_COPY_EXEC: PAGE_COPY; - insert_vm_struct(current->mm, mpnt); - current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + if ((ret = insert_vm_struct(current->mm, mpnt))) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } + current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h index 36f8d42e3..31fbbcd6d 100644 --- a/arch/ia64/ia32/elfcore32.h +++ b/arch/ia64/ia32/elfcore32.h @@ -9,6 +9,7 @@ #define _ELFCORE32_H_ #include +#include #define USE_ELF_CORE_DUMP 1 @@ -103,11 +104,15 @@ static inline int elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu) { struct ia32_user_i387_struct *fpstate = (void*)fpu; + mm_segment_t old_fs; if (!tsk->used_math) return 0; - - save_ia32_fpstate(tsk, fpstate); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate); + set_fs(old_fs); return 1; } @@ -117,11 +122,15 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu) { struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu; + mm_segment_t old_fs; if (!tsk->used_math) return 0; - save_ia32_fpxstate(tsk, fpxstate); + old_fs = get_fs(); + set_fs(KERNEL_DS); + save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate); + set_fs(old_fs); return 1; } diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index fa3ac962a..cd9094232 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -41,7 +41,7 @@ ENTRY(ia32_clone) zxt4 out1=in1 // newsp mov out3=16 // stacksize (compensates for 16-byte scratch area) adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags zxt4 out4=in2 // out4 = parent_tidptr zxt4 out5=in4 // out5 = child_tidptr br.call.sptk.many rp=do_fork @@ -311,7 +311,7 @@ ia32_syscall_table: data8 sys_ni_syscall /* old profil syscall holder */ data8 compat_sys_statfs data8 compat_sys_fstatfs /* 100 */ - data8 sys32_ioperm + data8 sys_ni_syscall /* ioperm */ data8 compat_sys_socketcall data8 sys_syslog data8 compat_sys_setitimer @@ -320,7 +320,7 @@ ia32_syscall_table: data8 compat_sys_newlstat data8 compat_sys_newfstat data8 sys_ni_syscall - data8 sys32_iopl /* 110 */ + data8 sys_ni_syscall /* iopl */ /* 110 */ data8 sys_vhangup data8 sys_ni_syscall /* used to be sys_idle */ data8 sys_ni_syscall @@ -470,16 +470,16 @@ ia32_syscall_table: data8 sys_remap_file_pages data8 sys_set_tid_address data8 sys32_timer_create - data8 compat_timer_settime /* 260 */ - data8 compat_timer_gettime + data8 compat_sys_timer_settime /* 260 */ + data8 compat_sys_timer_gettime data8 sys_timer_getoverrun data8 sys_timer_delete - data8 compat_clock_settime - data8 compat_clock_gettime /* 265 */ - data8 compat_clock_getres - data8 compat_clock_nanosleep - data8 compat_statfs64 - data8 compat_fstatfs64 + data8 compat_sys_clock_settime + data8 compat_sys_clock_gettime /* 265 */ + data8 compat_sys_clock_getres + data8 compat_sys_clock_nanosleep + data8 compat_sys_statfs64 + data8 compat_sys_fstatfs64 data8 sys_tgkill /* 270 */ data8 compat_sys_utimes data8 sys32_fadvise64_64 @@ -493,6 +493,8 @@ ia32_syscall_table: data8 compat_sys_mq_timedreceive /* 280 */ data8 compat_sys_mq_notify data8 compat_sys_mq_getsetattr + data8 sys_ni_syscall /* reserved for kexec */ + data8 sys32_waitid // guard against failures to increase IA32_NR_syscalls .org ia32_syscall_table + 8*IA32_NR_syscalls diff --git a/arch/ia64/ia32/ia32_ldt.c b/arch/ia64/ia32/ia32_ldt.c index 4cc8242de..a152738c7 100644 --- a/arch/ia64/ia32/ia32_ldt.c +++ b/arch/ia64/ia32/ia32_ldt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Hewlett-Packard Co + * Copyright (C) 2001, 2004 Hewlett-Packard Co * David Mosberger-Tang * * Adapted from arch/i386/kernel/ldt.c @@ -17,25 +17,24 @@ #include "ia32priv.h" -#define P(p) ((void *) (unsigned long) (p)) - /* * read_ldt() is not really atomic - this is not a problem since synchronization of reads * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic, * to protect the security checks done on new descriptors. */ static int -read_ldt (void *ptr, unsigned long bytecount) +read_ldt (void __user *ptr, unsigned long bytecount) { - char *src, *dst, buf[256]; /* temporary buffer (don't overflow kernel stack!) */ unsigned long bytes_left, n; + char __user *src, *dst; + char buf[256]; /* temporary buffer (don't overflow kernel stack!) */ if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE) bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE; bytes_left = bytecount; - src = (void *) IA32_LDT_OFFSET; + src = (void __user *) IA32_LDT_OFFSET; dst = ptr; while (bytes_left) { @@ -61,7 +60,7 @@ read_ldt (void *ptr, unsigned long bytecount) } static int -read_default_ldt (void * ptr, unsigned long bytecount) +read_default_ldt (void __user * ptr, unsigned long bytecount) { unsigned long size; int err; @@ -80,7 +79,7 @@ read_default_ldt (void * ptr, unsigned long bytecount) } static int -write_ldt (void * ptr, unsigned long bytecount, int oldmode) +write_ldt (void __user * ptr, unsigned long bytecount, int oldmode) { struct ia32_user_desc ldt_info; __u64 entry; @@ -120,7 +119,7 @@ write_ldt (void * ptr, unsigned long bytecount, int oldmode) * memory, but we still need to guard against out-of-memory, hence we must use * put_user(). */ - ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number); + ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number); ia32_load_segment_descriptors(current); return ret; } @@ -132,16 +131,16 @@ sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount) switch (func) { case 0: - ret = read_ldt(P(ptr), bytecount); + ret = read_ldt(compat_ptr(ptr), bytecount); break; case 1: - ret = write_ldt(P(ptr), bytecount, 1); + ret = write_ldt(compat_ptr(ptr), bytecount, 1); break; case 2: - ret = read_default_ldt(P(ptr), bytecount); + ret = read_default_ldt(compat_ptr(ptr), bytecount); break; case 0x11: - ret = write_ldt(P(ptr), bytecount, 0); + ret = write_ldt(compat_ptr(ptr), bytecount, 0); break; } return ret; diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 793ec3f76..7f2fc2704 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -66,7 +66,7 @@ struct rt_sigframe_ia32 }; int -copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from) +copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from) { unsigned long tmp; int err; @@ -78,10 +78,10 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from) err |= __get_user(to->si_errno, &from->si_errno); err |= __get_user(to->si_code, &from->si_code); - if (from->si_code < 0) + if (to->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { + switch (to->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); @@ -92,7 +92,7 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from) break; case __SI_FAULT >> 16: err |= __get_user(tmp, &from->si_addr); - to->si_addr = (void *) tmp; + to->si_addr = (void __user *) tmp; break; case __SI_POLL >> 16: err |= __get_user(to->si_band, &from->si_band); @@ -110,7 +110,7 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from) } int -copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from) +copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from) { unsigned int addr; int err; @@ -141,7 +141,8 @@ copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from) err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_FAULT >> 16: - err |= __put_user((long)from->si_addr, &to->si_addr); + /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */ + err |= __put_user(from->_sifields._pad[0], &to->si_addr); break; case __SI_POLL >> 16: err |= __put_user(from->si_band, &to->si_band); @@ -202,7 +203,7 @@ copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from) */ static int -save_ia32_fpstate_live (struct _fpstate_ia32 *save) +save_ia32_fpstate_live (struct _fpstate_ia32 __user *save) { struct task_struct *tsk = current; struct pt_regs *ptp; @@ -310,7 +311,7 @@ save_ia32_fpstate_live (struct _fpstate_ia32 *save) } static int -restore_ia32_fpstate_live (struct _fpstate_ia32 *save) +restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save) { struct task_struct *tsk = current; struct pt_regs *ptp; @@ -339,37 +340,37 @@ restore_ia32_fpstate_live (struct _fpstate_ia32 *save) fir = ia64_getreg(_IA64_REG_AR_FIR); fdr = ia64_getreg(_IA64_REG_AR_FDR); - __get_user(mxcsr, (unsigned int *)&save->mxcsr); + __get_user(mxcsr, (unsigned int __user *)&save->mxcsr); /* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */ - __get_user(lo, (unsigned int *)&save->cw); + __get_user(lo, (unsigned int __user *)&save->cw); num64 = mxcsr & 0xff10; num64 = (num64 << 32) | (lo & 0x1f3f); - fcr = (fcr & (~0xff1000001f3f)) | num64; + fcr = (fcr & (~0xff1000001f3fUL)) | num64; /* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ - __get_user(lo, (unsigned int *)&save->sw); + __get_user(lo, (unsigned int __user *)&save->sw); /* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */ if ( !(lo & 0x7f) ) lo &= (~0x8080); - __get_user(hi, (unsigned int *)&save->tag); + __get_user(hi, (unsigned int __user *)&save->tag); num64 = mxcsr & 0x3f; num64 = (num64 << 16) | (hi & 0xffff); num64 = (num64 << 16) | (lo & 0xffff); - fsr = (fsr & (~0x3fffffffff)) | num64; + fsr = (fsr & (~0x3fffffffffUL)) | num64; /* setting bits 0..47 with cssel and ipoff */ - __get_user(lo, (unsigned int *)&save->ipoff); - __get_user(hi, (unsigned int *)&save->cssel); + __get_user(lo, (unsigned int __user *)&save->ipoff); + __get_user(hi, (unsigned int __user *)&save->cssel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; - fir = (fir & (~0xffffffffffff)) | num64; + fir = (fir & (~0xffffffffffffUL)) | num64; /* setting bits 0..47 with datasel and dataoff */ - __get_user(lo, (unsigned int *)&save->dataoff); - __get_user(hi, (unsigned int *)&save->datasel); + __get_user(lo, (unsigned int __user *)&save->dataoff); + __get_user(hi, (unsigned int __user *)&save->datasel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; - fdr = (fdr & (~0xffffffffffff)) | num64; + fdr = (fdr & (~0xffffffffffffUL)) | num64; ia64_setreg(_IA64_REG_AR_FSR, fsr); ia64_setreg(_IA64_REG_AR_FCR, fcr); @@ -452,8 +453,8 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); } -asmlinkage long -ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigscratch *scr) +long +__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) { extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); sigset_t oldset, set; @@ -461,10 +462,7 @@ ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigsc 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)) + if (memcpy(&set.sig, &sset->sig, sigsetsize)) return -EFAULT; sigdelsetmask(&set, ~_BLOCKABLE); @@ -491,10 +489,24 @@ ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigsc } } +asmlinkage long +ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr) +{ + compat_sigset_t set; + + if (sigsetsize > sizeof(compat_sigset_t)) + return -EINVAL; + + if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) + return -EFAULT; + + return __ia32_rt_sigsuspend(&set, sigsetsize, scr); +} + asmlinkage long ia32_sigsuspend (unsigned int mask, struct sigscratch *scr) { - return ia32_rt_sigsuspend((compat_sigset_t *)&mask, sizeof(mask), scr); + return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr); } asmlinkage long @@ -512,8 +524,8 @@ sys32_signal (int sig, unsigned int handler) } asmlinkage long -sys32_rt_sigaction (int sig, struct sigaction32 *act, - struct sigaction32 *oact, unsigned int sigsetsize) +sys32_rt_sigaction (int sig, struct sigaction32 __user *act, + struct sigaction32 __user *oact, unsigned int sigsetsize) { struct k_sigaction new_ka, old_ka; unsigned int handler, restorer; @@ -547,7 +559,8 @@ sys32_rt_sigaction (int sig, struct sigaction32 *act, asmlinkage long -sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize) +sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, + unsigned int sigsetsize) { mm_segment_t old_fs = get_fs(); sigset_t s; @@ -562,7 +575,9 @@ sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsi return -EFAULT; } set_fs(KERNEL_DS); - ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s)); + ret = sys_rt_sigprocmask(how, + set ? (sigset_t __user *) &s : NULL, + oset ? (sigset_t __user *) &s : NULL, sizeof(s)); set_fs(old_fs); if (ret) return ret; @@ -574,10 +589,9 @@ sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsi } asmlinkage long -sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo, - struct compat_timespec *uts, unsigned int sigsetsize) +sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo, + struct compat_timespec __user *uts, unsigned int sigsetsize) { - extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *); mm_segment_t old_fs = get_fs(); struct timespec t; siginfo_t info; @@ -589,8 +603,10 @@ sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo, if (uts && get_compat_timespec(&t, uts)) return -EFAULT; set_fs(KERNEL_DS); - ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, - sigsetsize); + ret = sys_rt_sigtimedwait((sigset_t __user *) &s, + uinfo ? (siginfo_t __user *) &info : NULL, + uts ? (struct timespec __user *) &t : NULL, + sigsetsize); set_fs(old_fs); if (ret >= 0 && uinfo) { if (copy_siginfo_to_user32(uinfo, &info)) @@ -600,7 +616,7 @@ sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo, } asmlinkage long -sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo) +sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo) { mm_segment_t old_fs = get_fs(); siginfo_t info; @@ -609,13 +625,13 @@ sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo) if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs(KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, &info); + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs(old_fs); return ret; } asmlinkage long -sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) +sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) { struct k_sigaction new_ka, old_ka; unsigned int handler, restorer; @@ -648,7 +664,7 @@ sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *o } static int -setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate, +setup_sigcontext_ia32 (struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate, struct pt_regs *regs, unsigned long mask) { int err = 0; @@ -657,10 +673,10 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc))) return -EFAULT; - 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->r16 >> 32) & 0xffff, (unsigned int __user *)&sc->fs); + err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int __user *)&sc->gs); + err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int __user *)&sc->es); + err |= __put_user(regs->r16 & 0xffff, (unsigned int __user *)&sc->ds); err |= __put_user(regs->r15, &sc->edi); err |= __put_user(regs->r14, &sc->esi); err |= __put_user(regs->r13, &sc->ebp); @@ -674,14 +690,14 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate err |= __put_user(current->tss.error_code, &sc->err); #endif err |= __put_user(regs->cr_iip, &sc->eip); - err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs); + err |= __put_user(regs->r17 & 0xffff, (unsigned int __user *)&sc->cs); /* * `eflags' is in an ar register for this context */ flag = ia64_getreg(_IA64_REG_AR_EFLAG); 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); + err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int __user *)&sc->ss); if ( save_ia32_fpstate_live(fpstate) < 0 ) err = -EFAULT; @@ -705,7 +721,7 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate } 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 __user *sc, int *peax) { unsigned int err = 0; @@ -775,10 +791,10 @@ restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int * } { - struct _fpstate_ia32 *buf = NULL; + struct _fpstate_ia32 __user *buf = NULL; u32 fpstate_ptr; err |= get_user(fpstate_ptr, &(sc->fpstate)); - buf = (struct _fpstate_ia32 *)(u64)fpstate_ptr; + buf = compat_ptr(fpstate_ptr); if (buf) { err |= restore_ia32_fpstate_live(buf); } @@ -808,7 +824,7 @@ restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int * /* * Determine which stack to use.. */ -static inline void * +static inline void __user * get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) { unsigned long esp; @@ -823,14 +839,14 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) } /* Legacy stack switching not supported */ - return (void *)((esp - frame_size) & -8ul); + return (void __user *)((esp - frame_size) & -8ul); } static int setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { struct exec_domain *ed = current_thread_info()->exec_domain; - struct sigframe_ia32 *frame; + struct sigframe_ia32 __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -853,14 +869,19 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs 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)); + /* Pointing to restorer in ia32 gate page */ + err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode); } + /* This is popl %eax ; movl $,%eax ; int $0x80 + * and there for historical reasons only. + * See arch/i386/kernel/signal.c + */ + + err |= __put_user(0xb858, (short __user *)(frame->retcode+0)); + err |= __put_user(__IA32_NR_sigreturn, (int __user *)(frame->retcode+2)); + err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); + if (err) goto give_sigsegv; @@ -882,9 +903,7 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return 0; } @@ -893,7 +912,8 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { struct exec_domain *ed = current_thread_info()->exec_domain; - struct rt_sigframe_ia32 *frame; + compat_uptr_t pinfo, puc; + struct rt_sigframe_ia32 __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -903,8 +923,11 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user((ed && ed->signal_invmap && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig); - err |= __put_user((long)&frame->info, &frame->pinfo); - err |= __put_user((long)&frame->uc, &frame->puc); + + pinfo = (long __user) &frame->info; + puc = (long __user) &frame->uc; + err |= __put_user(pinfo, &frame->pinfo); + err |= __put_user(puc, &frame->puc); err |= copy_siginfo_to_user32(&frame->info, info); /* Create the ucontext. */ @@ -924,13 +947,19 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, 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)); + /* Pointing to rt_restorer in ia32 gate page */ + err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode); } + /* This is movl $,%eax ; int $0x80 + * and there for historical reasons only. + * See arch/i386/kernel/signal.c + */ + + err |= __put_user(0xb8, (char __user *)(frame->retcode+0)); + err |= __put_user(__IA32_NR_rt_sigreturn, (int __user *)(frame->retcode+1)); + err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); + if (err) goto give_sigsegv; @@ -952,9 +981,7 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return 0; } @@ -975,7 +1002,7 @@ sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int { struct pt_regs *regs = (struct pt_regs *) &stack; unsigned long esp = (unsigned int) regs->r12; - struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8); + struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(esp - 8); sigset_t set; int eax; @@ -989,7 +1016,7 @@ sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - current->blocked = (sigset_t) set; + current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); @@ -1008,9 +1035,8 @@ sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, { 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); + struct rt_sigframe_ia32 __user *frame = (struct rt_sigframe_ia32 __user *)(esp - 4); sigset_t set; - stack_t st; int eax; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) @@ -1027,11 +1053,9 @@ sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, 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); + do_sigaltstack((stack_t __user *) &frame->uc.uc_stack, NULL, esp); return eax; diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index 4b43f1753..4f630043b 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -33,6 +33,7 @@ struct exec_domain ia32_exec_domain; struct page *ia32_shared_page[NR_CPUS]; unsigned long *ia32_boot_gdt; unsigned long *cpu_gdt_table[NR_CPUS]; +struct page *ia32_gate_page; static unsigned long load_desc (u16 selector) @@ -75,7 +76,7 @@ ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs) struct ia32_user_desc info; int idx; - if (copy_from_user(&info, (void *)(childregs->r14 & 0xffffffff), sizeof(info))) + if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info))) return -EFAULT; if (LDT_empty(&info)) return -EINVAL; @@ -145,6 +146,9 @@ ia32_gdt_init (void) int cpu = smp_processor_id(); ia32_shared_page[cpu] = alloc_page(GFP_KERNEL); + if (!ia32_shared_page[cpu]) + panic("failed to allocate ia32_shared_page[%d]\n", cpu); + cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]); /* Copy from the boot cpu's GDT */ @@ -155,23 +159,26 @@ ia32_gdt_init (void) /* * Setup IA32 GDT and TSS */ -void +static void ia32_boot_gdt_init (void) { unsigned long ldt_size; ia32_shared_page[0] = alloc_page(GFP_KERNEL); + if (!ia32_shared_page[0]) + panic("failed to allocate ia32_shared_page[0]\n"); + ia32_boot_gdt = page_address(ia32_shared_page[0]); cpu_gdt_table[0] = ia32_boot_gdt; /* CS descriptor in IA-32 (scrambled) format */ ia32_boot_gdt[__USER_CS >> 3] - = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT, + = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT, 0xb, 1, 3, 1, 1, 1, 1); /* DS descriptor in IA-32 (scrambled) format */ ia32_boot_gdt[__USER_DS >> 3] - = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT, + = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT, 0x3, 1, 3, 1, 1, 1, 1); ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE); @@ -181,6 +188,27 @@ ia32_boot_gdt_init (void) 0x2, 0, 3, 1, 1, 1, 0); } +static void +ia32_gate_page_init(void) +{ + unsigned long *sr; + + ia32_gate_page = alloc_page(GFP_KERNEL); + sr = page_address(ia32_gate_page); + /* This is popl %eax ; movl $,%eax ; int $0x80 */ + *sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48); + + /* This is movl $,%eax ; int $0x80 */ + *sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40); +} + +void +ia32_mem_init(void) +{ + ia32_boot_gdt_init(); + ia32_gate_page_init(); +} + /* * Handle bad IA32 interrupt via syscall */ @@ -195,7 +223,7 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs) siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */ siginfo.si_flags = 0; siginfo.si_isr = 0; - siginfo.si_addr = 0; + siginfo.si_addr = NULL; siginfo.si_imm = 0; siginfo.si_code = TRAP_BRKPT; force_sig_info(SIGTRAP, &siginfo, current); diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index ba875e0bb..8012513e0 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -168,6 +168,9 @@ struct ia32_user_fxsr_struct { #define IA32_SA_HANDLER(ka) ((unsigned long) (ka)->sa.sa_handler & 0xffffffff) #define IA32_SA_RESTORER(ka) ((unsigned long) (ka)->sa.sa_handler >> 32) +#define __IA32_NR_sigreturn 119 +#define __IA32_NR_rt_sigreturn 173 + struct sigaction32 { unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */ unsigned int sa_flags; @@ -324,14 +327,16 @@ struct old_linux32_dirent { #define IA32_PAGE_OFFSET 0xc0000000 #define IA32_STACK_TOP IA32_PAGE_OFFSET +#define IA32_GATE_OFFSET IA32_PAGE_OFFSET +#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE /* * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can * access them. */ -#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET) -#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE) -#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE) +#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE) +#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE) +#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE) #define ELF_EXEC_PAGESIZE IA32_PAGE_SIZE @@ -356,7 +361,7 @@ void ia64_elf32_init(struct pt_regs *regs); /* This macro yields a string that ld.so will use to load implementation specific libraries for optimization. Not terribly relevant until we have real hardware to play with... */ -#define ELF_PLATFORM 0 +#define ELF_PLATFORM NULL #ifdef __KERNEL__ # define SET_PERSONALITY(EX,IBCS2) \ @@ -434,7 +439,7 @@ void ia64_elf32_init(struct pt_regs *regs); | ((((sd) >> IA32_SEG_DB) & 0x1) << SEG_DB) \ | ((((sd) >> IA32_SEG_G) & 0x1) << SEG_G)) -#define IA32_IOBASE 0x2000000000000000 /* Virtual address for I/O space */ +#define IA32_IOBASE 0x2000000000000000UL /* Virtual address for I/O space */ #define IA32_CR0 0x80000001 /* Enable PG and PE bits */ #define IA32_CR4 0x600 /* MMXEX and FXSR on */ @@ -551,8 +556,12 @@ struct user_regs_struct32 { }; /* Prototypes for use in elfcore32.h */ -extern int save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save); -extern int save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save); +extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *); +extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *); + +/* Prototypes for use in sys_ia32.c */ +int copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from); +int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from); #endif /* !CONFIG_IA32_SUPPORT */ diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index a97402c01..1b653dadb 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -70,10 +70,7 @@ # define DBG(fmt...) #endif -#define A(__x) ((unsigned long)(__x)) -#define AA(__x) ((unsigned long)(__x)) #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define OFFSET4K(a) ((a) & 0xfff) #define PAGE_START(addr) ((addr) & PAGE_MASK) @@ -82,9 +79,6 @@ #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid)) #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid)) -extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long, - unsigned long, unsigned long); - /* * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore * while doing so. @@ -93,7 +87,8 @@ extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsig static DECLARE_MUTEX(ia32_mmap_sem); asmlinkage long -sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs) +sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, + struct pt_regs *regs) { long error; char *filename; @@ -128,7 +123,7 @@ sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp return error; } -int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf) +int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) { int err; @@ -199,7 +194,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro /* Optimize the case where the old mmap and the new mmap are both anonymous */ if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) { - if (clear_user((void *) start, end - start)) { + if (clear_user((void __user *) start, end - start)) { ret = -EFAULT; goto out; } @@ -211,11 +206,11 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro return -ENOMEM; if (old_prot) - copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE); + copy_from_user(page, (void __user *) PAGE_START(start), PAGE_SIZE); down_write(¤t->mm->mmap_sem); { - ret = do_mmap(0, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE, + ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE, flags | MAP_FIXED | MAP_ANONYMOUS, 0); } up_write(¤t->mm->mmap_sem); @@ -226,9 +221,10 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro if (old_prot) { /* copy back the old page contents. */ if (offset_in_page(start)) - copy_to_user((void *) PAGE_START(start), page, offset_in_page(start)); + copy_to_user((void __user *) PAGE_START(start), page, + offset_in_page(start)); if (offset_in_page(end)) - copy_to_user((void *) end, page + offset_in_page(end), + copy_to_user((void __user *) end, page + offset_in_page(end), PAGE_SIZE - offset_in_page(end)); } @@ -236,7 +232,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro /* 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)) + || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0)) { ret = -EINVAL; goto out; @@ -266,9 +262,9 @@ ia32_init_pp_list(void) if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) return p; - p->pp_head = 0; + p->pp_head = NULL; p->ppl_rb = RB_ROOT; - p->pp_hint = 0; + p->pp_hint = NULL; atomic_set(&p->pp_count, 1); return p; } @@ -825,7 +821,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro 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, + ret = do_mmap(NULL, pstart, pend - pstart, prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE), flags | MAP_FIXED | MAP_ANONYMOUS, 0); } @@ -838,7 +834,8 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro /* 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)) + || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff) + < 0)) { sys_munmap(pstart, pend - pstart); return -EINVAL; @@ -927,7 +924,7 @@ struct mmap_arg_struct { }; asmlinkage long -sys32_mmap (struct mmap_arg_struct *arg) +sys32_mmap (struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; struct file *file = NULL; @@ -1140,7 +1137,7 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, } asmlinkage long -sys32_pipe (int *fd) +sys32_pipe (int __user *fd) { int retval; int fds[2]; @@ -1155,14 +1152,14 @@ sys32_pipe (int *fd) } static inline long -get_tv32 (struct timeval *o, struct compat_timeval *i) +get_tv32 (struct timeval *o, struct compat_timeval __user *i) { return (!access_ok(VERIFY_READ, i, sizeof(*i)) || (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec))); } static inline long -put_tv32 (struct compat_timeval *o, struct timeval *i) +put_tv32 (struct compat_timeval __user *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec))); @@ -1192,7 +1189,7 @@ sys32_alarm (unsigned int seconds) extern struct timezone sys_tz; asmlinkage long -sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz) +sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz) { if (tv) { struct timeval ktv; @@ -1208,7 +1205,7 @@ sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz) } asmlinkage long -sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz) +sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz) { struct timeval ktv; struct timespec kts; @@ -1229,14 +1226,14 @@ sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz) } struct getdents32_callback { - struct compat_dirent * current_dir; - struct compat_dirent * previous; + struct compat_dirent __user *current_dir; + struct compat_dirent __user *previous; int count; int error; }; struct readdir32_callback { - struct old_linux32_dirent * dirent; + struct old_linux32_dirent __user * dirent; int count; }; @@ -1244,9 +1241,9 @@ static int filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { - struct compat_dirent * dirent; + struct compat_dirent __user * dirent; struct getdents32_callback * buf = (struct getdents32_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); + int reclen = ROUND_UP(offsetof(struct compat_dirent, d_name) + namlen + 1, 4); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) @@ -1263,17 +1260,17 @@ filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, || copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) return -EFAULT; - dirent = (struct compat_dirent *) ((char *) dirent + reclen); + dirent = (struct compat_dirent __user *) ((char __user *) dirent + reclen); buf->current_dir = dirent; buf->count -= reclen; return 0; } asmlinkage long -sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count) +sys32_getdents (unsigned int fd, struct compat_dirent __user *dirent, unsigned int count) { struct file * file; - struct compat_dirent * lastdirent; + struct compat_dirent __user * lastdirent; struct getdents32_callback buf; int error; @@ -1310,7 +1307,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t unsigned int d_type) { struct readdir32_callback * buf = (struct readdir32_callback *) __buf; - struct old_linux32_dirent * dirent; + struct old_linux32_dirent __user * dirent; if (buf->count) return -EINVAL; @@ -1326,7 +1323,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t } asmlinkage long -sys32_readdir (unsigned int fd, void *dirent, unsigned int count) +sys32_readdir (unsigned int fd, void __user *dirent, unsigned int count) { int error; struct file * file; @@ -1357,7 +1354,7 @@ struct sel_arg_struct { }; asmlinkage long -sys32_old_select (struct sel_arg_struct *arg) +sys32_old_select (struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -1434,7 +1431,7 @@ sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) * so we have to implement this system call here. */ asmlinkage long -sys32_time (int *tloc) +sys32_time (int __user *tloc) { int i; struct timeval tv; @@ -1564,8 +1561,8 @@ putreg (struct task_struct *child, int regno, unsigned int value) } static void -put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, - int tos) +put_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp, + struct switch_stack *swp, int tos) { struct _fpreg_ia32 *f; char buf[32]; @@ -1597,8 +1594,8 @@ put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switc } static void -get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, - int tos) +get_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp, + struct switch_stack *swp, int tos) { if ((regno += tos) >= 8) @@ -1627,7 +1624,7 @@ get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switc } int -save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save) +save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save) { struct switch_stack *swp; struct pt_regs *ptp; @@ -1656,7 +1653,7 @@ save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save) } static int -restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save) +restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save) { struct switch_stack *swp; struct pt_regs *ptp; @@ -1666,15 +1663,15 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *sav if (!access_ok(VERIFY_READ, save, sizeof(*save))) return(-EFAULT); - __get_user(num32, (unsigned int *)&save->cwd); + __get_user(num32, (unsigned int __user *)&save->cwd); tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f); - __get_user(fsrlo, (unsigned int *)&save->swd); - __get_user(fsrhi, (unsigned int *)&save->twd); + __get_user(fsrlo, (unsigned int __user *)&save->swd); + __get_user(fsrhi, (unsigned int __user *)&save->twd); num32 = (fsrhi << 16) | fsrlo; tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int *)&save->fip); + __get_user(num32, (unsigned int __user *)&save->fip); tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int *)&save->foo); + __get_user(num32, (unsigned int __user *)&save->foo); tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32; /* @@ -1689,7 +1686,7 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *sav } int -save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save) +save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save) { struct switch_stack *swp; struct pt_regs *ptp; @@ -1715,7 +1712,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save) ptp = ia64_task_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) - put_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos); + put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f); __put_user(mxcsr & 0xffff, &save->mxcsr); @@ -1728,7 +1725,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save) } static int -restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save) +restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save) { struct switch_stack *swp; struct pt_regs *ptp; @@ -1741,15 +1738,15 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *sa if (!access_ok(VERIFY_READ, save, sizeof(*save))) return(-EFAULT); - __get_user(num32, (unsigned int *)&save->cwd); + __get_user(num32, (unsigned int __user *)&save->cwd); tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f); - __get_user(fsrlo, (unsigned int *)&save->swd); - __get_user(fsrhi, (unsigned int *)&save->twd); + __get_user(fsrlo, (unsigned int __user *)&save->swd); + __get_user(fsrhi, (unsigned int __user *)&save->twd); num32 = (fsrhi << 16) | fsrlo; tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int *)&save->fip); + __get_user(num32, (unsigned int __user *)&save->fip); tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int *)&save->foo); + __get_user(num32, (unsigned int __user *)&save->foo); tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32; /* @@ -1759,13 +1756,13 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *sa ptp = ia64_task_regs(tsk); tos = (tsk->thread.fsr >> 11) & 7; for (i = 0; i < 8; i++) - get_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos); + get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); - __get_user(mxcsr, (unsigned int *)&save->mxcsr); + __get_user(mxcsr, (unsigned int __user *)&save->mxcsr); num64 = mxcsr & 0xff10; - tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000)) | (num64<<32); + tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000UL)) | (num64<<32); num64 = mxcsr & 0x3f; - tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000)) | (num64<<32); + tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000UL)) | (num64<<32); for (i = 0; i < 8; i++) { copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32)); @@ -1823,7 +1820,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, case PTRACE_PEEKDATA: /* read word at location addr */ ret = ia32_peek(regs, child, addr, &value); if (ret == 0) - ret = put_user(value, (unsigned int *) A(data)); + ret = put_user(value, (unsigned int __user *) compat_ptr(data)); else ret = -EIO; goto out_tsk; @@ -1839,7 +1836,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, break; tmp = getreg(child, addr); - if (!put_user(tmp, (unsigned int *) A(data))) + if (!put_user(tmp, (unsigned int __user *) compat_ptr(data))) ret = 0; break; @@ -1853,24 +1850,24 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, break; case IA32_PTRACE_GETREGS: - if (!access_ok(VERIFY_WRITE, (int *) A(data), 17*sizeof(int))) { + if (!access_ok(VERIFY_WRITE, compat_ptr(data), 17*sizeof(int))) { ret = -EIO; break; } for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { - put_user(getreg(child, i), (unsigned int *) A(data)); + put_user(getreg(child, i), (unsigned int __user *) compat_ptr(data)); data += sizeof(int); } ret = 0; break; case IA32_PTRACE_SETREGS: - if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) { + if (!access_ok(VERIFY_READ, compat_ptr(data), 17*sizeof(int))) { ret = -EIO; break; } for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { - get_user(tmp, (unsigned int *) A(data)); + get_user(tmp, (unsigned int __user *) compat_ptr(data)); putreg(child, i, tmp); data += sizeof(int); } @@ -1878,19 +1875,23 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, break; case IA32_PTRACE_GETFPREGS: - ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data)); + ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct __user *) + compat_ptr(data)); break; case IA32_PTRACE_GETFPXREGS: - ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data)); + ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *) + compat_ptr(data)); break; case IA32_PTRACE_SETFPREGS: - ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data)); + ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct __user *) + compat_ptr(data)); break; case IA32_PTRACE_SETFPXREGS: - ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data)); + ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *) + compat_ptr(data)); break; case PTRACE_SYSCALL: /* continue, stop after next syscall */ @@ -1913,73 +1914,6 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, return ret; } -/* - * The IA64 maps 4 I/O ports for each 4K page - */ -#define IOLEN ((65536 / 4) * 4096) - -asmlinkage long -sys32_iopl (int level) -{ - extern unsigned long ia64_iobase; - int fd; - struct file * file; - unsigned int old; - unsigned long addr; - mm_segment_t old_fs = get_fs (); - - if (level != 3) - return(-EINVAL); - /* Trying to gain more privileges? */ - old = ia64_getreg(_IA64_REG_AR_EFLAG); - if ((unsigned int) level > ((old >> 12) & 3)) { - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - } - set_fs(KERNEL_DS); - fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0); - set_fs(old_fs); - if (fd < 0) - return fd; - file = fget(fd); - if (file == NULL) { - sys_close(fd); - return(-EFAULT); - } - - down_write(¤t->mm->mmap_sem); - addr = do_mmap_pgoff(file, IA32_IOBASE, - IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED, - (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); - - if (addr >= 0) { - old = (old & ~0x3000) | (level << 12); - ia64_setreg(_IA64_REG_AR_EFLAG, old); - } - - fput(file); - sys_close(fd); - return 0; -} - -asmlinkage long -sys32_ioperm (unsigned int from, unsigned int num, int on) -{ - - /* - * Since IA64 doesn't have permission bits we'd have to go to - * a lot of trouble to simulate them in software. There's - * no point, only trusted programs can make this call so we'll - * just turn it into an iopl call and let the process have - * access to all I/O ports. - * - * XXX proper ioperm() support should be emulated by - * manipulating the page protections... - */ - return sys32_iopl(3); -} - typedef struct { unsigned int ss_sp; unsigned int ss_flags; @@ -1987,7 +1921,7 @@ typedef struct { } ia32_stack_t; asmlinkage long -sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32, +sys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack) { struct pt_regs *pt = (struct pt_regs *) &stack; @@ -1999,9 +1933,9 @@ sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32, if (uss32) { if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t))) return -EFAULT; - uss.ss_sp = (void *) (long) buf32.ss_sp; + uss.ss_sp = (void __user *) (long) buf32.ss_sp; uss.ss_flags = buf32.ss_flags; - /* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the + /* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the check and set it to the user requested value later */ if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) { ret = -ENOMEM; @@ -2010,14 +1944,15 @@ sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32, uss.ss_size = MINSIGSTKSZ; } set_fs(KERNEL_DS); - ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12); - current->sas_ss_size = buf32.ss_size; + ret = do_sigaltstack(uss32 ? (stack_t __user *) &uss : NULL, + (stack_t __user *) &uoss, pt->r12); + current->sas_ss_size = buf32.ss_size; set_fs(old_fs); out: if (ret < 0) return(ret); if (uoss32) { - buf32.ss_sp = (long) uoss.ss_sp; + buf32.ss_sp = (long __user) uoss.ss_sp; buf32.ss_flags = uoss.ss_flags; buf32.ss_size = uoss.ss_size; if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t))) @@ -2056,14 +1991,14 @@ struct sysctl32 { }; asmlinkage long -sys32_sysctl (struct sysctl32 *args) +sys32_sysctl (struct sysctl32 __user *args) { #ifdef CONFIG_SYSCTL struct sysctl32 a32; mm_segment_t old_fs = get_fs (); - void *oldvalp, *newvalp; + void __user *oldvalp, *newvalp; size_t oldlen; - int *namep; + int __user *namep; long ret; if (copy_from_user(&a32, args, sizeof(a32))) @@ -2076,11 +2011,11 @@ sys32_sysctl (struct sysctl32 *args) * addresses, we KNOW that access_ok() will always succeed, so this is an * expensive NOP, but so what... */ - namep = (int *) A(a32.name); - oldvalp = (void *) A(a32.oldval); - newvalp = (void *) A(a32.newval); + namep = (int __user *) compat_ptr(a32.name); + oldvalp = compat_ptr(a32.oldval); + newvalp = compat_ptr(a32.newval); - if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp))) + if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp))) || !access_ok(VERIFY_WRITE, namep, 0) || !access_ok(VERIFY_WRITE, oldvalp, 0) || !access_ok(VERIFY_WRITE, newvalp, 0)) @@ -2088,11 +2023,12 @@ sys32_sysctl (struct sysctl32 *args) set_fs(KERNEL_DS); lock_kernel(); - ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen); + ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen, + newvalp, (size_t) a32.newlen); unlock_kernel(); set_fs(old_fs); - if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp))) + if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp))) return -EFAULT; return ret; @@ -2102,7 +2038,7 @@ sys32_sysctl (struct sysctl32 *args) } asmlinkage long -sys32_newuname (struct new_utsname *name) +sys32_newuname (struct new_utsname __user *name) { int ret = sys_newuname(name); @@ -2113,14 +2049,14 @@ sys32_newuname (struct new_utsname *name) } asmlinkage long -sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid) +sys32_getresuid16 (u16 __user *ruid, u16 __user *euid, u16 __user *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); + ret = sys_getresuid((uid_t __user *) &a, (uid_t __user *) &b, (uid_t __user *) &c); set_fs(old_fs); if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid)) @@ -2129,14 +2065,14 @@ sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid) } asmlinkage long -sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid) +sys32_getresgid16 (u16 __user *rgid, u16 __user *egid, u16 __user *sgid) { gid_t a, b, c; int ret; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); - ret = sys_getresgid(&a, &b, &c); + ret = sys_getresgid((gid_t __user *) &a, (gid_t __user *) &b, (gid_t __user *) &c); set_fs(old_fs); if (ret) @@ -2153,7 +2089,7 @@ sys32_lseek (unsigned int fd, int offset, unsigned int whence) } static int -groups16_to_user(short *grouplist, struct group_info *group_info) +groups16_to_user(short __user *grouplist, struct group_info *group_info) { int i; short group; @@ -2168,7 +2104,7 @@ groups16_to_user(short *grouplist, struct group_info *group_info) } static int -groups16_from_user(struct group_info *group_info, short *grouplist) +groups16_from_user(struct group_info *group_info, short __user *grouplist) { int i; short group; @@ -2183,7 +2119,7 @@ groups16_from_user(struct group_info *group_info, short *grouplist) } asmlinkage long -sys32_getgroups16 (int gidsetsize, short *grouplist) +sys32_getgroups16 (int gidsetsize, short __user *grouplist) { int i; @@ -2208,7 +2144,7 @@ out: } asmlinkage long -sys32_setgroups16 (int gidsetsize, short *grouplist) +sys32_setgroups16 (int gidsetsize, short __user *grouplist) { struct group_info *group_info; int retval; @@ -2236,7 +2172,7 @@ sys32_setgroups16 (int gidsetsize, short *grouplist) asmlinkage long sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi) { - return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo); + return sys_truncate(compat_ptr(path), ((unsigned long) len_hi << 32) | len_lo); } asmlinkage long @@ -2246,7 +2182,7 @@ sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi) } static int -putstat64 (struct stat64 *ubuf, struct kstat *kbuf) +putstat64 (struct stat64 __user *ubuf, struct kstat *kbuf) { int err; u64 hdev; @@ -2255,8 +2191,8 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf) return -EFAULT; hdev = huge_encode_dev(kbuf->dev); - err = __put_user(hdev, (u32*)&ubuf->st_dev); - err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1); + err = __put_user(hdev, (u32 __user*)&ubuf->st_dev); + err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_dev) + 1); err |= __put_user(kbuf->ino, &ubuf->__st_ino); err |= __put_user(kbuf->ino, &ubuf->st_ino_lo); err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi); @@ -2265,8 +2201,8 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf) err |= __put_user(kbuf->uid, &ubuf->st_uid); err |= __put_user(kbuf->gid, &ubuf->st_gid); hdev = huge_encode_dev(kbuf->rdev); - err = __put_user(hdev, (u32*)&ubuf->st_rdev); - err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1); + err = __put_user(hdev, (u32 __user*)&ubuf->st_rdev); + err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_rdev) + 1); err |= __put_user(kbuf->size, &ubuf->st_size_lo); err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi); err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime); @@ -2281,7 +2217,7 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf) } asmlinkage long -sys32_stat64 (char *filename, struct stat64 *statbuf) +sys32_stat64 (char __user *filename, struct stat64 __user *statbuf) { struct kstat s; long ret = vfs_stat(filename, &s); @@ -2291,7 +2227,7 @@ sys32_stat64 (char *filename, struct stat64 *statbuf) } asmlinkage long -sys32_lstat64 (char *filename, struct stat64 *statbuf) +sys32_lstat64 (char __user *filename, struct stat64 __user *statbuf) { struct kstat s; long ret = vfs_lstat(filename, &s); @@ -2301,7 +2237,7 @@ sys32_lstat64 (char *filename, struct stat64 *statbuf) } asmlinkage long -sys32_fstat64 (unsigned int fd, struct stat64 *statbuf) +sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf) { struct kstat s; long ret = vfs_fstat(fd, &s); @@ -2328,7 +2264,7 @@ struct sysinfo32 { }; asmlinkage long -sys32_sysinfo (struct sysinfo32 *info) +sys32_sysinfo (struct sysinfo32 __user *info) { struct sysinfo s; long ret, err; @@ -2336,7 +2272,7 @@ sys32_sysinfo (struct sysinfo32 *info) mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); - ret = sys_sysinfo(&s); + ret = sys_sysinfo((struct sysinfo __user *) &s); set_fs(old_fs); /* Check to see if any memory value is too large for 32-bit and * scale down if needed. @@ -2379,14 +2315,14 @@ sys32_sysinfo (struct sysinfo32 *info) } asmlinkage long -sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval) +sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval) { mm_segment_t old_fs = get_fs(); struct timespec t; long ret; set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, &t); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); set_fs(old_fs); if (put_compat_timespec(&t, interval)) return -EFAULT; @@ -2394,19 +2330,19 @@ sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval) } asmlinkage long -sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) +sys32_pread (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long -sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) +sys32_pwrite (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long -sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count) +sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count) { mm_segment_t old_fs = get_fs(); long ret; @@ -2416,7 +2352,7 @@ sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count) return -EFAULT; set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count); set_fs(old_fs); if (!ret && offset && put_user(of, offset)) @@ -2447,7 +2383,7 @@ sys32_brk (unsigned int brk) obrk = mm->brk; ret = sys_brk(brk); if (ret < obrk) - clear_user((void *) ret, PAGE_ALIGN(ret) - ret); + clear_user(compat_ptr(ret), PAGE_ALIGN(ret) - ret); return ret; } @@ -2455,7 +2391,7 @@ sys32_brk (unsigned int brk) * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag. */ asmlinkage long -sys32_open (const char * filename, int flags, int mode) +sys32_open (const char __user * filename, int flags, int mode) { char * tmp; int fd, error; @@ -2487,10 +2423,10 @@ struct epoll_event32 { u32 events; u32 data[2]; -}; +}; asmlinkage long -sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event) +sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event) { mm_segment_t old_fs = get_fs(); struct epoll_event event64; @@ -2508,14 +2444,14 @@ sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event) event64.data |= (u64)data_halfword << 32; set_fs(KERNEL_DS); - error = sys_epoll_ctl(epfd, op, fd, &event64); + error = sys_epoll_ctl(epfd, op, fd, (struct epoll_event __user *) &event64); set_fs(old_fs); return error; } asmlinkage long -sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents, +sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, int timeout) { struct epoll_event *events64 = NULL; @@ -2533,8 +2469,8 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents, maxevents * sizeof(struct epoll_event32)))) return error; - /* - * Allocate space for the intermediate copy. If the space needed + /* + * Allocate space for the intermediate copy. If the space needed * is large enough to cause kmalloc to fail, then try again with * __get_free_pages. */ @@ -2543,14 +2479,15 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents, if (events64 == NULL) { events64 = (struct epoll_event *) __get_free_pages(GFP_KERNEL, get_order(size)); - if (events64 == NULL) + if (events64 == NULL) return -ENOMEM; do_free_pages = 1; } /* Do the system call */ set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/ - numevents = sys_epoll_wait(epfd, events64, maxevents, timeout); + numevents = sys_epoll_wait(epfd, (struct epoll_event __user *) events64, + maxevents, timeout); set_fs(old_fs); /* Don't modify userspace memory if we're returning an error */ @@ -2593,7 +2530,7 @@ get_free_idx (void) * Set a given TLS descriptor: */ asmlinkage int -sys32_set_thread_area (struct ia32_user_desc *u_info) +sys32_set_thread_area (struct ia32_user_desc __user *u_info) { struct thread_struct *t = ¤t->thread; struct ia32_user_desc info; @@ -2654,7 +2591,7 @@ sys32_set_thread_area (struct ia32_user_desc *u_info) #define GET_USEABLE(desc) (((desc)->b >> 20) & 1) asmlinkage int -sys32_get_thread_area (struct ia32_user_desc *u_info) +sys32_get_thread_area (struct ia32_user_desc __user *u_info) { struct ia32_user_desc info; struct desc_struct *desc; @@ -2682,12 +2619,8 @@ sys32_get_thread_area (struct ia32_user_desc *u_info) return 0; } -extern asmlinkage long -sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, - timer_t * created_timer_id); - asmlinkage long -sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id) +sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) { struct sigevent se; mm_segment_t oldfs; @@ -2710,7 +2643,7 @@ sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id) oldfs = get_fs(); set_fs(KERNEL_DS); - err = sys_timer_create(clock, &se, &t); + err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t); set_fs(oldfs); if (!err) @@ -2728,6 +2661,32 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, advice); } +asmlinkage long sys32_waitid(int which, compat_pid_t pid, + siginfo_t32 __user *uinfo, int options, + struct compat_rusage __user *uru) +{ + siginfo_t info; + struct rusage ru; + long ret; + mm_segment_t old_fs = get_fs(); + + info.si_signo = 0; + set_fs (KERNEL_DS); + ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options, + uru ? &ru : NULL); + set_fs (old_fs); + + if (ret < 0 || info.si_signo == 0) + return ret; + + if (uru && (ret = put_compat_rusage(&ru, uru))) + return ret; + + BUG_ON(info.si_code & __SI_MASK); + info.si_code |= __SI_CHLD; + return copy_siginfo_to_user32(uinfo, &info); +} + #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid) diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 7d1e2f3d4..fbf5caca4 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ @@ -14,32 +14,34 @@ obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_SMP) += smp.o smpboot.o +obj-$(CONFIG_SMP) += smp.o smpboot.o domain.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o obj-$(CONFIG_IA64_CYCLONE) += cyclone.o +obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o +mca_recovery-y += mca_drv.o mca_drv_asm.o # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o -extra-y += gate.so gate-syms.o gate.lds.s gate.o +extra-y += gate.so gate-syms.o gate.lds gate.o # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state. CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 -AFLAGS_gate.lds.o += -P -C -U$(ARCH) +CPPFLAGS_gate.lds := -P -C -U$(ARCH) quiet_cmd_gate = GATE $@ cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 -$(obj)/gate.so: $(obj)/gate.lds.s $(obj)/gate.o FORCE +$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE $(call if_changed,gate) $(obj)/built-in.o: $(obj)/gate-syms.o $(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o GATECFLAGS_gate-syms.o = -r -$(obj)/gate-syms.o: $(src)/gate.lds.s $(obj)/gate.o FORCE +$(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE $(call if_changed,gate) # gate-data.o contains the gate DSO image as data in section .data.gate. diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c index b70f6de25..2623df5e2 100644 --- a/arch/ia64/kernel/acpi-ext.c +++ b/arch/ia64/kernel/acpi-ext.c @@ -62,7 +62,7 @@ acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id, struct acpi_vendor_info info; info.descriptor = id; - info.data = 0; + info.data = NULL; acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info); if (!info.data) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index cf61f3e2a..fb010358a 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -61,10 +62,16 @@ void (*pm_idle) (void); EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); +EXPORT_SYMBOL(pm_power_off); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; +#define MAX_SAPICS 256 +u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = + { [0 ... MAX_SAPICS - 1] = -1 }; +EXPORT_SYMBOL(ia64_acpiid_to_sapicid); + const char * acpi_get_sysname (void) { @@ -172,8 +179,8 @@ acpi_parse_lapic_addr_ovr ( return -EINVAL; if (lapic->address) { - iounmap((void *) ipi_base_addr); - ipi_base_addr = (unsigned long) ioremap(lapic->address, 0); + iounmap(ipi_base_addr); + ipi_base_addr = ioremap(lapic->address, 0); } return 0; } @@ -193,6 +200,7 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end) #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid; #endif + ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid; ++available_cpus; } @@ -329,9 +337,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) /* Get base address of IPI Message Block */ if (acpi_madt->lapic_address) - ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); + ipi_base_addr = ioremap(acpi_madt->lapic_address, 0); - printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); + printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr); acpi_madt_oem_check(acpi_madt->header.oem_id, acpi_madt->header.oem_table_id); @@ -430,8 +438,9 @@ acpi_numa_arch_fixup (void) { int i, j, node_from, node_to; - /* If there's no SRAT, fix the phys_id */ + /* If there's no SRAT, fix the phys_id and mark node 0 online */ if (srat_num_cpus == 0) { + node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } @@ -643,4 +652,71 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq) return 0; } +#ifdef CONFIG_NUMA +acpi_status __init +acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) +{ + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; + struct acpi_table_iosapic *iosapic; + unsigned int gsi_base; + int node; + + /* Only care about objects w/ a method that returns the MADT */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + return AE_OK; + + if (!buffer.length || !buffer.pointer) + return AE_OK; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*iosapic)) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer; + + if (iosapic->header.type != ACPI_MADT_IOSAPIC) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + gsi_base = iosapic->global_irq_base; + + acpi_os_free(buffer.pointer); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + /* + * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell + * us which node to associate this with. + */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) + return AE_OK; + + if (!buffer.length || !buffer.pointer) + return AE_OK; + + obj = buffer.pointer; + + if (obj->type != ACPI_TYPE_INTEGER || + obj->integer.value >= MAX_PXM_DOMAINS) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + node = pxm_to_nid_map[obj->integer.value]; + acpi_os_free(buffer.pointer); + + if (node >= MAX_NUMNODES || !node_online(node) || + cpus_empty(node_to_cpumask(node))) + return AE_OK; + + /* We know a gsi to node mapping! */ + map_iosapic_to_node(gsi_base, node); + return AE_OK; +} +#endif /* CONFIG_NUMA */ #endif /* CONFIG_ACPI_BOOT */ diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index f166571ec..e0a50bf62 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -34,6 +34,11 @@ void foo(void) BLANK(); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); + + BLANK(); + DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked)); DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid)); DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader)); @@ -188,18 +193,10 @@ void foo(void) DEFINE(IA64_CLONE_VM, CLONE_VM); BLANK(); - /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */ - DEFINE(IA64_CPUINFO_ITM_DELTA_OFFSET, offsetof (struct cpuinfo_ia64, itm_delta)); - DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next)); DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc)); DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec)); - DEFINE(CLONE_IDLETASK_BIT, 12); -#if CLONE_IDLETASK != (1 << 12) -# error "CLONE_IDLETASK_BIT incorrect, please fix" -#endif - DEFINE(CLONE_SETTLS_BIT, 19); #if CLONE_SETTLS != (1<<19) # error "CLONE_SETTLS_BIT incorrect, please fix" @@ -207,5 +204,22 @@ void foo(void) BLANK(); DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info)); + /* used by head.S */ + DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc)); + BLANK(); + /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */ + DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr)); + DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source)); + DEFINE(IA64_TIME_INTERPOLATOR_SHIFT_OFFSET, offsetof (struct time_interpolator, shift)); + DEFINE(IA64_TIME_INTERPOLATOR_NSEC_OFFSET, offsetof (struct time_interpolator, nsec_per_cyc)); + DEFINE(IA64_TIME_INTERPOLATOR_OFFSET_OFFSET, offsetof (struct time_interpolator, offset)); + DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle)); + DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter)); + DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter)); + DEFINE(IA64_TIME_INTERPOLATOR_MASK_OFFSET, offsetof (struct time_interpolator, mask)); + DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU); + DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64); + DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32); + DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec)); } diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index 19300e958..768c7e469 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -1,6 +1,8 @@ +#include #include #include #include +#include /* IBM Summit (EXA) Cyclone counter code*/ #define CYCLONE_CBAR_ADDR 0xFEB00CD0 @@ -15,64 +17,13 @@ void __init cyclone_setup(void) use_cyclone = 1; } -static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ -static u32 last_update_cyclone; - -static unsigned long offset_base; - -static unsigned long get_offset_cyclone(void) -{ - u32 now; - unsigned long offset; - - /* Read the cyclone timer */ - now = readl(cyclone_timer); - /* .. relative to previous update*/ - offset = now - last_update_cyclone; - - /* convert cyclone ticks to nanoseconds */ - offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; - - /* our adjusted time in nanoseconds */ - return offset_base + offset; -} - -static void update_cyclone(long delta_nsec) -{ - u32 now; - unsigned long offset; - - /* Read the cyclone timer */ - now = readl(cyclone_timer); - /* .. relative to previous update*/ - offset = now - last_update_cyclone; - - /* convert cyclone ticks to nanoseconds */ - offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; - - offset += offset_base; - - /* Be careful about signed/unsigned comparisons here: */ - if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) - offset_base = offset - delta_nsec; - else - offset_base = 0; - - last_update_cyclone = now; -} - -static void reset_cyclone(void) -{ - offset_base = 0; - last_update_cyclone = readl(cyclone_timer); -} struct time_interpolator cyclone_interpolator = { - .get_offset = get_offset_cyclone, - .update = update_cyclone, - .reset = reset_cyclone, + .source = TIME_SOURCE_MMIO64, + .shift = 16, .frequency = CYCLONE_TIMER_FREQ, .drift = -100, + .mask = (1LL << 40) - 1 }; int __init init_cyclone_clock(void) @@ -81,6 +32,7 @@ int __init init_cyclone_clock(void) u64 base; /* saved cyclone base address */ u64 offset; /* offset from pageaddr to cyclone_timer register */ int i; + u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ if (!use_cyclone) return -ENODEV; @@ -148,7 +100,7 @@ int __init init_cyclone_clock(void) } } /* initialize last tick */ - last_update_cyclone = readl(cyclone_timer); + cyclone_interpolator.addr = cyclone_timer; register_time_interpolator(&cyclone_interpolator); return 0; diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index e1e7d91c9..cbe558580 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,7 @@ static efi_status_t \ prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ { \ struct ia64_fpreg fr[6]; \ - efi_time_cap_t *atc = 0; \ + efi_time_cap_t *atc = NULL; \ efi_status_t ret; \ \ if (tc) \ @@ -91,7 +92,7 @@ static efi_status_t \ prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ { \ struct ia64_fpreg fr[6]; \ - efi_time_t *atm = 0; \ + efi_time_t *atm = NULL; \ efi_status_t ret; \ \ if (tm) \ @@ -109,7 +110,7 @@ prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ unsigned long *data_size, void *data) \ { \ struct ia64_fpreg fr[6]; \ - u32 *aattr = 0; \ + u32 *aattr = NULL; \ efi_status_t ret; \ \ if (attr) \ @@ -172,7 +173,7 @@ prefix##_reset_system (int reset_type, efi_status_t status, \ unsigned long data_size, efi_char16_t *data) \ { \ struct ia64_fpreg fr[6]; \ - efi_char16_t *adata = 0; \ + efi_char16_t *adata = NULL; \ \ if (data) \ adata = adjust_arg(data); \ @@ -214,7 +215,7 @@ efi_gettimeofday (struct timespec *ts) efi_time_t tm; memset(ts, 0, sizeof(ts)); - if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS) + if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) return; ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); @@ -324,12 +325,12 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) * [granule_addr - first_non_wb_addr) is guaranteed to * be contiguous WB memory. */ - granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1); + granule_addr = GRANULEROUNDDOWN(md->phys_addr); first_non_wb_addr = max(first_non_wb_addr, granule_addr); if (first_non_wb_addr < md->phys_addr) { trim_bottom(md, granule_addr + IA64_GRANULE_SIZE); - granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1); + granule_addr = GRANULEROUNDDOWN(md->phys_addr); first_non_wb_addr = max(first_non_wb_addr, granule_addr); } @@ -343,22 +344,36 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) break; /* non-WB or hole */ } - last_granule_addr = first_non_wb_addr & ~(IA64_GRANULE_SIZE - 1); + last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr); if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) trim_top(md, last_granule_addr); if (is_available_memory(md)) { - if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > max_addr) { - if (md->phys_addr > max_addr) + if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) { + if (md->phys_addr >= max_addr) continue; md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT; + first_non_wb_addr = max_addr; } if (total_mem >= mem_limit) continue; + + if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) { + unsigned long limit_addr = md->phys_addr; + + limit_addr += mem_limit - total_mem; + limit_addr = GRANULEROUNDDOWN(limit_addr); + + if (md->phys_addr > limit_addr) + continue; + + md->num_pages = (limit_addr - md->phys_addr) >> + EFI_PAGE_SHIFT; + first_non_wb_addr = max_addr = md->phys_addr + + (md->num_pages << EFI_PAGE_SHIFT); + } total_mem += (md->num_pages << EFI_PAGE_SHIFT); - if (total_mem > mem_limit) - md->num_pages -= ((total_mem - mem_limit) >> EFI_PAGE_SHIFT); if (md->num_pages == 0) continue; @@ -493,13 +508,13 @@ efi_init (void) for (cp = saved_command_line; *cp; ) { if (memcmp(cp, "mem=", 4) == 0) { cp += 4; - mem_limit = memparse(cp, &end) - 2; + mem_limit = memparse(cp, &end); if (end != cp) break; cp = end; } else if (memcmp(cp, "max_addr=", 9) == 0) { cp += 9; - max_addr = memparse(cp, &end) - 1; + max_addr = GRANULEROUNDDOWN(memparse(cp, &end)); if (end != cp) break; cp = end; diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 52576c34c..391420734 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -128,7 +128,7 @@ GLOBAL_ENTRY(sys_clone2) (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags br.call.sptk.many rp=do_fork .ret1: .restore sp adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack @@ -157,7 +157,7 @@ GLOBAL_ENTRY(sys_clone) (p6) st8 [r2]=in4 // store TLS in r13 (tp) mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags br.call.sptk.many rp=do_fork .ret2: .restore sp adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack @@ -1526,11 +1526,11 @@ sys_call_table: data8 sys_mq_notify data8 sys_mq_getsetattr data8 sys_ni_syscall // reserved for kexec_load - data8 sys_ni_syscall - data8 sys_ni_syscall // 1270 - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall + data8 sys_ni_syscall // reserved for vserver + data8 sys_waitid // 1270 + data8 sys_add_key + data8 sys_request_key + data8 sys_keyctl data8 sys_ni_syscall data8 sys_ni_syscall // 1275 data8 sys_ni_syscall diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 0f8e5b5fd..b48f5c3af 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -8,6 +8,8 @@ * 18-Feb-03 louisk Implement fsys_gettimeofday(). * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more, * probably broke it along the way... ;-) + * 13-Jul-04 clameter Implement fsys_clock_gettime and revise fsys_gettimeofday to make + * it capable of using memory based clocks without falling back to C code. */ #include @@ -144,195 +146,208 @@ ENTRY(fsys_set_tid_address) END(fsys_set_tid_address) /* - * Note 1: This routine uses floating-point registers, but only with registers that - * operate on integers. Because of that, we don't need to set ar.fpsr to the - * kernel default value. - * - * Note 2: For now, we will assume that all CPUs run at the same clock-frequency. - * If that wasn't the case, we would have to disable preemption (e.g., - * by disabling interrupts) between reading the ITC and reading - * local_cpu_data->nsec_per_cyc. - * - * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector, - * we ought to either skip the ITC-based interpolation or run an ntp-like - * daemon to keep the ITCs from drifting too far apart. + * Ensure that the time interpolator structure is compatible with the asm code */ +#if IA64_TIME_INTERPOLATOR_SOURCE_OFFSET !=0 || IA64_TIME_INTERPOLATOR_SHIFT_OFFSET != 2 \ + || IA64_TIME_INTERPOLATOR_JITTER_OFFSET != 3 || IA64_TIME_INTERPOLATOR_NSEC_OFFSET != 4 +#error fsys_gettimeofday incompatible with changes to struct time_interpolator +#endif +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 +#define CLOCK_DIVIDE_BY_1000 0x4000 +#define CLOCK_ADD_MONOTONIC 0x8000 ENTRY(fsys_gettimeofday) .prologue .altrp b6 .body - add r9=TI_FLAGS+IA64_TASK_SIZE,r16 - addl r3=THIS_CPU(cpu_info),r0 - -#ifdef CONFIG_SMP - movl r10=__per_cpu_offset - movl r2=sal_platform_features - ;; - - ld8 r2=[r2] - movl r19=xtime // xtime is a timespec struct - - ld8 r10=[r10] // r10 <- __per_cpu_offset[0] - addl r21=THIS_CPU(cpu_info),r0 - ;; - add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id) - tbit.nz p8,p0 = r2, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT -(p8) br.spnt.many fsys_fallback_syscall -#else - ;; - mov r10=r3 - movl r19=xtime // xtime is a timespec struct -#endif - ld4 r9=[r9] - movl r17=xtime_lock - ;; - - // r32, r33 should contain the 2 args of gettimeofday - adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10 - mov r2=-1 - tnat.nz p6,p7=r32 // guard against NaT args - ;; - - adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10 -(p7) tnat.nz p6,p0=r33 -(p6) br.cond.spnt.few .fail_einval - - adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3 - movl r24=2361183241434822607 // for division hack (only for / 1000) - ;; - - ldf8 f7=[r10] // f7 now contains itm_delta - setf.sig f11=r2 - adds r10=8, r32 - - adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19 // r20 = &xtime->tv_nsec - movl r26=jiffies - - setf.sig f9=r24 // f9 is used for division hack - movl r27=wall_jiffies - - and r9=TIF_ALLWORK_MASK,r9 - movl r25=last_nsec_offset - ;; - - /* - * Verify that we have permission to write to struct timeval. Note: - * Another thread might unmap the mapping before we actually get - * to store the result. That's OK as long as the stores are also - * protect by EX(). - */ -EX(.fail_efault, probe.w.fault r32, 3) // this must come _after_ NaT-check -EX(.fail_efault, probe.w.fault r10, 3) // this must come _after_ NaT-check - nop 0 - - ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value - cmp.ne p8, p0=0, r9 -(p8) br.spnt.many fsys_fallback_syscall - ;; -.retry: // *** seq = read_seqbegin(&xtime_lock); *** - ld4.acq r23=[r17] // since &xtime_lock == &xtime_lock->sequence - ld8 r14=[r25] // r14 (old) = last_nsec_offset - - ld8 r28=[r26] // r28 = jiffies - ld8 r29=[r27] // r29 = wall_jiffies - ;; - - ldf8 f8=[r21] // f8 now contains itm_next - mov.m r31=ar.itc // put time stamp into r31 (ITC) == now - sub r28=r29, r28, 1 // r28 now contains "-(lost + 1)" - ;; - - ld8 r2=[r19] // r2 = sec = xtime.tv_sec - ld8 r29=[r20] // r29 = nsec = xtime.tv_nsec - tbit.nz p9, p10=r23, 0 // p9 <- is_odd(r23), p10 <- is_even(r23) - - setf.sig f6=r28 // f6 <- -(lost + 1) (6 cyc) - ;; - + mov r31 = r32 + tnat.nz p6,p0 = r33 // guard against NaT argument +(p6) br.cond.spnt.few .fail_einval + mov r30 = CLOCK_DIVIDE_BY_1000 + ;; +.gettime: + // Register map + // Incoming r31 = pointer to address where to place result + // r30 = flags determining how time is processed + // r2,r3 = temp r4-r7 preserved + // r8 = result nanoseconds + // r9 = result seconds + // r10 = temporary storage for clock difference + // r11 = preserved: saved ar.pfs + // r12 = preserved: memory stack + // r13 = preserved: thread pointer + // r14 = address of mask / mask + // r15 = preserved: system call number + // r16 = preserved: current task pointer + // r17 = wall to monotonic use + // r18 = time_interpolator->offset + // r19 = address of wall_to_monotonic + // r20 = pointer to struct time_interpolator / pointer to time_interpolator->address + // r21 = shift factor + // r22 = address of time interpolator->last_counter + // r23 = address of time_interpolator->last_cycle + // r24 = adress of time_interpolator->offset + // r25 = last_cycle value + // r26 = last_counter value + // r27 = pointer to xtime + // r28 = sequence number at the beginning of critcal section + // r29 = address of seqlock + // r30 = time processing flags / memory address + // r31 = pointer to result + // Predicates + // p6,p7 short term use + // p8 = timesource ar.itc + // p9 = timesource mmio64 + // p10 = timesource mmio32 + // p11 = timesource not to be handled by asm code + // p12 = memory time source ( = p9 | p10) + // p13 = do cmpxchg with time_interpolator_last_cycle + // p14 = Divide by 1000 + // p15 = Add monotonic + // + // Note that instructions are optimized for McKinley. McKinley can process two + // bundles simultaneously and therefore we continuously try to feed the CPU + // two bundles and then a stop. + tnat.nz p6,p0 = r31 // branch deferred since it does not fit into bundle structure + mov pr = r30,0xc000 // Set predicates according to function + add r2 = TI_FLAGS+IA64_TASK_SIZE,r16 + movl r20 = time_interpolator + ;; + ld8 r20 = [r20] // get pointer to time_interpolator structure + movl r29 = xtime_lock + ld4 r2 = [r2] // process work pending flags + movl r27 = xtime + ;; // only one bundle here + ld8 r21 = [r20] // first quad with control information + and r2 = TIF_ALLWORK_MASK,r2 +(p6) br.cond.spnt.few .fail_einval // deferred branch + ;; + add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20 + extr r3 = r21,32,32 // time_interpolator->nsec_per_cyc + extr r8 = r21,0,16 // time_interpolator->source + cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled +(p6) br.cond.spnt.many fsys_fallback_syscall + ;; + cmp.eq p8,p12 = 0,r8 // Check for cpu timer + cmp.eq p9,p0 = 1,r8 // MMIO64 ? + extr r2 = r21,24,8 // time_interpolator->jitter + cmp.eq p10,p0 = 2,r8 // MMIO32 ? + cmp.ltu p11,p0 = 2,r8 // function or other clock +(p11) br.cond.spnt.many fsys_fallback_syscall + ;; + setf.sig f7 = r3 // Setup for scaling of counter +(p15) movl r19 = wall_to_monotonic +(p12) ld8 r30 = [r10] + cmp.ne p13,p0 = r2,r0 // need jitter compensation? + extr r21 = r21,16,8 // shift factor + ;; +.time_redo: + .pred.rel.mutex p8,p9,p10 + ld4.acq r28 = [r29] // xtime_lock.sequence. Must come first for locking purposes +(p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! + add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20 +(p9) ld8 r2 = [r30] // readq(ti->address). Could also have latency issues.. +(p10) ld4 r2 = [r30] // readw(ti->address) +(p13) add r23 = IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET,r20 + ;; // could be removed by moving the last add upward + ld8 r26 = [r22] // time_interpolator->last_counter +(p13) ld8 r25 = [r23] // time interpolator->last_cycle + add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20 +(p15) ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET + ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET + add r14 = IA64_TIME_INTERPOLATOR_MASK_OFFSET, r20 + ;; + ld8 r18 = [r24] // time_interpolator->offset + ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET // xtime.tv_nsec +(p13) sub r3 = r25,r2 // Diff needed before comparison (thanks davidm) + ;; + ld8 r14 = [r14] // time_interpolator->mask +(p13) cmp.gt.unc p6,p7 = r3,r0 // check if it is less than last. p6,p7 cleared + sub r10 = r2,r26 // current_counter - last_counter + ;; +(p6) sub r10 = r25,r26 // time we got was less than last_cycle +(p7) mov ar.ccv = r25 // more than last_cycle. Prep for cmpxchg + ;; + and r10 = r10,r14 // Apply mask + ;; + setf.sig f8 = r10 + nop.i 123 + ;; +(p7) cmpxchg8.rel r3 = [r23],r2,ar.ccv +EX(.fail_efault, probe.w.fault r31, 3) // This takes 5 cycles and we have spare time + xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter) +(p15) add r9 = r9,r17 // Add wall to monotonic.secs to result secs + ;; +(p15) ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET +(p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful redo + // simulate tbit.nz.or p7,p0 = r28,0 + and r28 = ~1,r28 // Make sequence even to force retry if odd + getf.sig r2 = f8 mf - xma.l f8=f6, f7, f8 // f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next (5 cyc) - nop 0 - - setf.sig f12=r31 // f12 <- ITC (6 cyc) - // *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; *** - ld4 r24=[r17] // r24 = xtime_lock->sequence (re-read) - nop 0 - ;; - - xma.l f8=f11, f8, f12 // f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick) - nop 0 - ;; - - getf.sig r18=f8 // r18 <- (now - last_tick) - xmpy.l f8=f8, f10 // f8 <- elapsed_cycles*nsec_per_cyc (5 cyc) - add r3=r29, r14 // r3 = (nsec + old) - ;; - - cmp.lt p7, p8=r18, r0 // if now < last_tick, set p7 = 1, p8 = 0 - getf.sig r18=f8 // r18 = elapsed_cycles*nsec_per_cyc (6 cyc) - nop 0 - ;; - -(p10) cmp.ne p9, p0=r23, r24 // if xtime_lock->sequence != seq, set p9 - shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT // r18 <- offset -(p9) br.spnt.many .retry - ;; - - mov ar.ccv=r14 // ar.ccv = old (1 cyc) - cmp.leu p7, p8=r18, r14 // if (offset <= old), set p7 = 1, p8 = 0 - ;; - -(p8) cmpxchg8.rel r24=[r25], r18, ar.ccv // compare-and-exchange (atomic!) -(p8) add r3=r29, r18 // r3 = (nsec + offset) - ;; - shr.u r3=r3, 3 // initiate dividing r3 by 1000 - ;; - setf.sig f8=r3 // (6 cyc) - mov r10=1000000 // r10 = 1000000 - ;; -(p8) cmp.ne.unc p9, p0=r24, r14 - xmpy.hu f6=f8, f9 // (5 cyc) -(p9) br.spnt.many .retry - ;; - - getf.sig r3=f6 // (6 cyc) - ;; - shr.u r3=r3, 4 // end of division, r3 is divided by 1000 (=usec) - ;; - -1: cmp.geu p7, p0=r3, r10 // while (usec >= 1000000) - ;; -(p7) sub r3=r3, r10 // usec -= 1000000 -(p7) adds r2=1, r2 // ++sec -(p7) br.spnt.many 1b - - // finally: r2 = sec, r3 = usec -EX(.fail_efault, st8 [r32]=r2) - adds r9=8, r32 - mov r8=r0 // success - ;; -EX(.fail_efault, st8 [r9]=r3) // store them in the timeval struct - mov r10=0 + add r8 = r8,r18 // Add time interpolator offset + ;; + ld4 r10 = [r29] // xtime_lock.sequence +(p15) add r8 = r8, r17 // Add monotonic.nsecs to nsecs + shr.u r2 = r2,r21 + ;; // overloaded 3 bundles! + // End critical section. + add r8 = r8,r2 // Add xtime.nsecs + cmp4.ne.or p7,p0 = r28,r10 +(p7) br.cond.dpnt.few .time_redo // sequence number changed ? + // Now r8=tv->tv_nsec and r9=tv->tv_sec + mov r10 = r0 + movl r2 = 1000000000 + add r23 = IA64_TIMESPEC_TV_NSEC_OFFSET, r31 +(p14) movl r3 = 2361183241434822607 // Prep for / 1000 hack + ;; +.time_normalize: + mov r21 = r8 + cmp.ge p6,p0 = r8,r2 +(p14) shr.u r20 = r8, 3 // We can repeat this if necessary just wasting some time + ;; +(p14) setf.sig f8 = r20 +(p6) sub r8 = r8,r2 +(p6) add r9 = 1,r9 // two nops before the branch. +(p14) setf.sig f7 = r3 // Chances for repeats are 1 in 10000 for gettod +(p6) br.cond.dpnt.few .time_normalize + ;; + // Divided by 8 though shift. Now divide by 125 + // The compiler was able to do that with a multiply + // and a shift and we do the same +EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles +(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it... + ;; + mov r8 = r0 +(p14) getf.sig r2 = f8 + ;; +(p14) shr.u r21 = r2, 4 + ;; +EX(.fail_efault, st8 [r31] = r9) +EX(.fail_efault, st8 [r23] = r21) FSYS_RETURN - /* - * Note: We are NOT clearing the scratch registers here. Since the only things - * in those registers are time-related variables and some addresses (which - * can be obtained from System.map), none of this should be security-sensitive - * and we should be fine. - */ - .fail_einval: - mov r8=EINVAL // r8 = EINVAL - mov r10=-1 // r10 = -1 + mov r8 = EINVAL + mov r10 = -1 FSYS_RETURN - .fail_efault: - mov r8=EFAULT // r8 = EFAULT - mov r10=-1 // r10 = -1 + mov r8 = EFAULT + mov r10 = -1 FSYS_RETURN END(fsys_gettimeofday) +ENTRY(fsys_clock_gettime) + .prologue + .altrp b6 + .body + cmp4.ltu p6, p0 = CLOCK_MONOTONIC, r32 + // Fallback if this is not CLOCK_REALTIME or CLOCK_MONOTONIC +(p6) br.spnt.few fsys_fallback_syscall + mov r31 = r33 + shl r30 = r32,15 + br.many .gettime +END(fsys_clock_gettime) + /* * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize). */ @@ -838,7 +853,7 @@ fsyscall_table: data8 0 // timer_getoverrun data8 0 // timer_delete data8 0 // clock_settime - data8 0 // clock_gettime + data8 fsys_clock_gettime // clock_gettime data8 0 // clock_getres // 1255 data8 0 // clock_nanosleep data8 0 // fstatfs64 diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 032defb0f..0e821d0c3 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -781,8 +781,7 @@ GLOBAL_ENTRY(ia64_switch_mode_virt) // going to virtual // - for code addresses, set upper bits of addr to KERNEL_START - // - for stack addresses, set upper 3 bits to 0xe.... Dont change any of the - // lower bits since we want it to stay identity mapped + // - for stack addresses, copy from input argument movl r18=KERNEL_START dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index f032ea1b3..c5b15ddaf 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -104,7 +104,7 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ static struct iosapic_intr_info { - char *addr; /* base address of IOSAPIC */ + char __iomem *addr; /* base address of IOSAPIC */ u32 low32; /* current value of low word of Redirection table entry */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ @@ -114,9 +114,12 @@ static struct iosapic_intr_info { } iosapic_intr_info[IA64_NUM_VECTORS]; static struct iosapic { - char *addr; /* base address of IOSAPIC */ + char __iomem *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */ +#ifdef CONFIG_NUMA + unsigned short node; /* numa node association via pxm */ +#endif } iosapic_lists[NR_IOSAPICS]; static int num_iosapic; @@ -176,7 +179,7 @@ set_rte (unsigned int vector, unsigned int dest, int mask) { unsigned long pol, trigger, dmode, flags; u32 low32, high32; - char *addr; + char __iomem *addr; int rte_index; char redir; @@ -234,7 +237,7 @@ static void mask_irq (unsigned int irq) { unsigned long flags; - char *addr; + char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -258,7 +261,7 @@ static void unmask_irq (unsigned int irq) { unsigned long flags; - char *addr; + char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -284,7 +287,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) unsigned long flags; u32 high32, low32; int dest, rte_index; - char *addr; + char __iomem *addr; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; ia64_vector vec; @@ -409,7 +412,7 @@ struct hw_interrupt_type irq_type_iosapic_edge = { }; unsigned int -iosapic_version (char *addr) +iosapic_version (char __iomem *addr) { /* * IOSAPIC Version Register return 32 bit structure like: @@ -454,7 +457,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, int rte_index; int index; unsigned long gsi_base; - char *iosapic_address; + void __iomem *iosapic_address; index = find_iosapic(gsi); if (index < 0) { @@ -488,7 +491,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, } static unsigned int -get_target_cpu (void) +get_target_cpu (unsigned int gsi, int vector) { #ifdef CONFIG_SMP static int cpu = -1; @@ -507,6 +510,39 @@ get_target_cpu (void) if (!cpu_online(smp_processor_id())) return hard_smp_processor_id(); +#ifdef CONFIG_NUMA + { + int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0; + cpumask_t cpu_mask; + + iosapic_index = find_iosapic(gsi); + if (iosapic_index < 0 || + iosapic_lists[iosapic_index].node == MAX_NUMNODES) + goto skip_numa_setup; + + cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node); + + for_each_cpu_mask(numa_cpu, cpu_mask) { + if (!cpu_online(numa_cpu)) + cpu_clear(numa_cpu, cpu_mask); + } + + num_cpus = cpus_weight(cpu_mask); + + if (!num_cpus) + goto skip_numa_setup; + + /* Use vector assigment to distribute across cpus in node */ + cpu_index = vector % num_cpus; + + for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) + numa_cpu = next_cpu(numa_cpu, cpu_mask); + + if (numa_cpu != NR_CPUS) + return cpu_physical_id(numa_cpu); + } +skip_numa_setup: +#endif /* * Otherwise, round-robin interrupt vectors across all the * processors. (It'd be nice if we could be smarter in the @@ -550,7 +586,7 @@ iosapic_register_intr (unsigned int gsi, } vector = assign_irq_vector(AUTO_ASSIGN); - dest = get_target_cpu(); + dest = get_target_cpu(gsi, vector); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); } @@ -665,7 +701,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) { int num_rte; unsigned int isa_irq, ver; - char *addr; + char __iomem *addr; addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); @@ -680,6 +716,9 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) iosapic_lists[num_iosapic].addr = addr; iosapic_lists[num_iosapic].gsi_base = gsi_base; iosapic_lists[num_iosapic].num_rte = num_rte; +#ifdef CONFIG_NUMA + iosapic_lists[num_iosapic].node = MAX_NUMNODES; +#endif num_iosapic++; if ((gsi_base == 0) && pcat_compat) { @@ -692,3 +731,20 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } + +#ifdef CONFIG_NUMA +void __init +map_iosapic_to_node(unsigned int gsi_base, int node) +{ + int index; + + index = find_iosapic(gsi_base); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", + __FUNCTION__, gsi_base); + return; + } + iosapic_lists[index].node = node; + return; +} +#endif diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 9ec161c63..f48673e97 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -43,13 +43,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -84,11 +84,13 @@ irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = { } }; +#ifdef CONFIG_SMP /* * This is updated when the user sets irq affinity via /proc */ cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)]; +#endif #ifdef CONFIG_IA64_GENERIC irq_desc_t * __ia64_irq_desc (unsigned int irq) @@ -213,11 +215,6 @@ int show_interrupts(struct seq_file *p, void *v) skip: spin_unlock_irqrestore(&idesc->lock, flags); } else if (i == NR_IRQS) { - seq_puts(p, "NMI: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", nmi_count(j)); - seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_puts(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) @@ -255,14 +252,16 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ - int retval = 0; + int ret, retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; + retval |= ret; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) @@ -962,7 +961,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, return len; } -static int irq_affinity_write_proc (struct file *file, const char *buffer, +static int irq_affinity_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { unsigned int irq = (unsigned long) data; @@ -1137,31 +1136,6 @@ void fixup_irqs(void) } #endif -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data; - unsigned long full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - #define MAX_NAMELEN 10 static void register_irq_proc (unsigned int irq) @@ -1196,26 +1170,15 @@ static void register_irq_proc (unsigned int irq) #endif } -cpumask_t prof_cpu_mask = CPU_MASK_ALL; - void init_irq_proc (void) { - struct proc_dir_entry *entry; int i; /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); + root_irq_dir = proc_mkdir("irq", NULL); /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; + create_prof_cpu_mask(root_irq_dir); /* * Create entries for all existing IRQs. diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index e853159b8..946df2d55 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -30,8 +30,8 @@ #include #include #include +#include -#include #include #include #include @@ -47,7 +47,8 @@ #define IRQ_DEBUG 0 /* default base addr of IPI table */ -unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR); +void __iomem *ipi_base_addr = ((void __iomem *) + (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); /* * Legacy IRQ to IA-64 vector translation table. @@ -254,7 +255,7 @@ init_IRQ (void) void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) { - unsigned long ipi_addr; + void __iomem *ipi_addr; unsigned long ipi_data; unsigned long phys_cpu_id; @@ -269,7 +270,7 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) */ ipi_data = (delivery_mode << 8) | (vector & 0xff); - ipi_addr = ipi_base_addr | (phys_cpu_id << 4) | ((redirect & 1) << 3); + ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3)); writeq(ipi_data, ipi_addr); } diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 0834c7bcb..888e97caf 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -852,7 +852,7 @@ GLOBAL_ENTRY(ia64_syscall_setup) add r17=PT(R11),r1 // initialize second base pointer ;; alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable - st8 [r16]=r29,PT(CR_IFS)-PT(CR_IPSR) // save cr.ipsr + st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr tnat.nz p8,p0=in0 st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11 @@ -860,31 +860,31 @@ GLOBAL_ENTRY(ia64_syscall_setup) (pKStk) mov r18=r0 // make sure r18 isn't NaT ;; + st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip mov r28=b0 // save b0 (2 cyc) -(p8) mov in0=-1 ;; - st8 [r16]=r0,PT(AR_PFS)-PT(CR_IFS) // clear cr.ifs st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat -(p9) mov in1=-1 + dep r19=0,r19,38,26 // clear all bits but 0..37 [I0] +(p8) mov in0=-1 ;; - st8 [r16]=r26,PT(AR_RNAT)-PT(AR_PFS) // save ar.pfs + st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc - tnat.nz p10,p0=in2 +(p9) mov in1=-1 (pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8 tbit.nz p15,p0=r29,IA64_PSR_I_BIT - tnat.nz p11,p0=in3 + tnat.nz p10,p0=in2 ;; (pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field (pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field + tnat.nz p11,p0=in3 + ;; (p10) mov in2=-1 - + tnat.nz p12,p0=in4 // [I0] (p11) mov in3=-1 - tnat.nz p12,p0=in4 - tnat.nz p13,p0=in5 ;; (pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat (pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore @@ -892,28 +892,29 @@ GLOBAL_ENTRY(ia64_syscall_setup) ;; st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates st8 [r17]=r28,PT(R1)-PT(B0) // save b0 -(p12) mov in4=-1 + tnat.nz p13,p0=in5 // [I0] ;; st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 -(p13) mov in5=-1 +(p12) mov in4=-1 ;; .mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12 .mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13 - tnat.nz p14,p0=in6 +(p13) mov in5=-1 ;; st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr st8.spill [r17]=r15 // save r15 - tnat.nz p8,p0=in7 + tnat.nz p14,p0=in6 ;; stf8 [r16]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) -(p14) mov in6=-1 + tnat.nz p8,p0=in7 mov r13=r2 // establish `current' movl r1=__gp // establish kernel global pointer ;; +(p14) mov in6=-1 (p8) mov in7=-1 tnat.nz p9,p0=r15 diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 9c5104cc5..662bf2133 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -82,11 +82,6 @@ # define IA64_MCA_DEBUG(fmt...) #endif -typedef struct ia64_fptr { - unsigned long fp; - unsigned long gp; -} ia64_fptr_t; - /* Used by mca_asm.S */ ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state; ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state; @@ -598,7 +593,7 @@ ia64_mca_cmc_vector_disable (void *dummy) { cmcv_reg_t cmcv; - cmcv = (cmcv_reg_t)ia64_getreg(_IA64_REG_CR_CMCV); + cmcv.cmcv_regval = ia64_getreg(_IA64_REG_CR_CMCV); cmcv.cmcv_mask = 1; /* Mask/disable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval); @@ -625,7 +620,7 @@ ia64_mca_cmc_vector_enable (void *dummy) { cmcv_reg_t cmcv; - cmcv = (cmcv_reg_t)ia64_getreg(_IA64_REG_CR_CMCV); + cmcv.cmcv_regval = ia64_getreg(_IA64_REG_CR_CMCV); cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval); @@ -691,6 +686,7 @@ ia64_mca_wakeup_ipi_wait(void) irr = ia64_getreg(_IA64_REG_CR_IRR3); break; } + cpu_relax(); } while (!(irr & (1UL << irr_bit))) ; } @@ -831,6 +827,31 @@ ia64_return_to_sal_check(int recover) } +/* Function pointer for extra MCA recovery */ +int (*ia64_mca_ucmc_extension) + (void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*) + = NULL; + +int +ia64_reg_MCA_extension(void *fn) +{ + if (ia64_mca_ucmc_extension) + return 1; + + ia64_mca_ucmc_extension = fn; + return 0; +} + +void +ia64_unreg_MCA_extension(void) +{ + if (ia64_mca_ucmc_extension) + ia64_mca_ucmc_extension = NULL; +} + +EXPORT_SYMBOL(ia64_reg_MCA_extension); +EXPORT_SYMBOL(ia64_unreg_MCA_extension); + /* * ia64_mca_ucmc_handler * @@ -852,11 +873,20 @@ ia64_mca_ucmc_handler(void) { pal_processor_state_info_t *psp = (pal_processor_state_info_t *) &ia64_sal_to_os_handoff_state.proc_state_param; - int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc); + int recover; /* Get the MCA error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); + /* TLB error is only exist in this SAL error record */ + recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc)) + /* other error recovery */ + || (ia64_mca_ucmc_extension + && ia64_mca_ucmc_extension( + IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA), + &ia64_sal_to_os_handoff_state, + &ia64_os_to_sal_handoff_state)); + /* * Wakeup all the processors which are spinning in the rendezvous * loop. diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index b5026aa81..3cef5349d 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -868,7 +868,7 @@ end_os_mca_restore: GLOBAL_ENTRY(ia64_monarch_init_handler) - + .prologue // stash the information the SAL passed to os SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2) ;; @@ -907,6 +907,7 @@ IVirtual_Switch: adds out0=16,sp // out0 = pointer to pt_regs ;; DO_SAVE_SWITCH_STACK + .body adds out1=16,sp // out0 = pointer to switch_stack br.call.sptk.many rp=ia64_init_handler diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index 540301f6e..b1460dcc3 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h @@ -54,8 +54,7 @@ (pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ #define MINSTATE_END_SAVE_MIN_PHYS \ - or r12=r12,r14; /* make sp a kernel virtual address */ \ - or r13=r13,r14; /* make `current' a kernel virtual address */ \ + dep r12=-1,r12,61,3; /* make sp a kernel virtual address */ \ ;; #ifdef MINSTATE_VIRT @@ -65,7 +64,7 @@ #endif #ifdef MINSTATE_PHYS -# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; dep reg=0,reg,61,3 +# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; tpa reg=reg # define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS # define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS #endif @@ -172,7 +171,6 @@ ;; \ .mem.offset 0,0; st8.spill [r16]=r15,16; \ .mem.offset 8,0; st8.spill [r17]=r14,16; \ - dep r14=-1,r0,61,3; \ ;; \ .mem.offset 0,0; st8.spill [r16]=r2,16; \ .mem.offset 8,0; st8.spill [r17]=r3,16; \ diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 2ee61a213..febc091c2 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -195,10 +195,10 @@ apply_imm22 (struct module *mod, struct insn *insn, uint64_t val) printk(KERN_ERR "%s: value %li out of IMM22 range\n", mod->name, (int64_t)val); return 0; } - ia64_patch((u64) insn, 0x01fffcfe000, ( ((val & 0x200000) << 15) /* bit 21 -> 36 */ - | ((val & 0x1f0000) << 6) /* bit 16 -> 22 */ - | ((val & 0x00ff80) << 20) /* bit 7 -> 27 */ - | ((val & 0x00007f) << 13) /* bit 0 -> 13 */)); + ia64_patch((u64) insn, 0x01fffcfe000UL, ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */ + | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */ + | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */ + | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */)); return 1; } @@ -209,8 +209,8 @@ apply_imm21b (struct module *mod, struct insn *insn, uint64_t val) printk(KERN_ERR "%s: value %li out of IMM21b range\n", mod->name, (int64_t)val); return 0; } - ia64_patch((u64) insn, 0x11ffffe000, ( ((val & 0x100000) << 16) /* bit 20 -> 36 */ - | ((val & 0x0fffff) << 13) /* bit 0 -> 13 */)); + ia64_patch((u64) insn, 0x11ffffe000UL, ( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */ + | ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */)); return 1; } @@ -253,9 +253,9 @@ plt_target (struct plt_entry *plt) long off; b0 = b[0]; b1 = b[1]; - off = ( ((b1 & 0x00fffff000000000) >> 36) /* imm20b -> bit 0 */ - | ((b0 >> 48) << 20) | ((b1 & 0x7fffff) << 36) /* imm39 -> bit 20 */ - | ((b1 & 0x0800000000000000) << 0)); /* i -> bit 59 */ + off = ( ((b1 & 0x00fffff000000000UL) >> 36) /* imm20b -> bit 0 */ + | ((b0 >> 48) << 20) | ((b1 & 0x7fffffUL) << 36) /* imm39 -> bit 20 */ + | ((b1 & 0x0800000000000000UL) << 0)); /* i -> bit 59 */ return (long) plt->bundle[1] + 16*off; } @@ -739,7 +739,7 @@ do_reloc (struct module *mod, uint8_t r_type, Elf64_Sym *sym, uint64_t addend, if (gp_addressable(mod, val)) { /* turn "ld8" into "mov": */ DEBUGP("%s: patching ld8 at %p to mov\n", __FUNCTION__, location); - ia64_patch((u64) location, 0x1fff80fe000, 0x10000000000); + ia64_patch((u64) location, 0x1fff80fe000UL, 0x10000000000UL); } return 0; diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 3cbe961ed..25e7c8344 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -446,7 +446,7 @@ register_info(char *page) "RSE stacked physical registers : %ld\n" "RSE load/store hints : %ld (%s)\n", phys_stacked, hints.ph_data, - hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)"); + hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)"); if (ia64_pal_debug_info(&iregs, &dregs)) return 0; @@ -479,7 +479,7 @@ static const char *proc_features[]={ "Enable CMCI promotion", "Enable MCA to BINIT promotion", "Enable MCA promotion", - "Enable BEER promotion" + "Enable BERR promotion" }; diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index ef04f5df0..367804a60 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c @@ -65,21 +65,21 @@ void ia64_patch_imm64 (u64 insn_addr, u64 val) { ia64_patch(insn_addr, - 0x01fffefe000, ( ((val & 0x8000000000000000) >> 27) /* bit 63 -> 36 */ - | ((val & 0x0000000000200000) << 0) /* bit 21 -> 21 */ - | ((val & 0x00000000001f0000) << 6) /* bit 16 -> 22 */ - | ((val & 0x000000000000ff80) << 20) /* bit 7 -> 27 */ - | ((val & 0x000000000000007f) << 13) /* bit 0 -> 13 */)); - ia64_patch(insn_addr - 1, 0x1ffffffffff, val >> 22); + 0x01fffefe000UL, ( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */ + | ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */ + | ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */ + | ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */ + | ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */)); + ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22); } void ia64_patch_imm60 (u64 insn_addr, u64 val) { ia64_patch(insn_addr, - 0x011ffffe000, ( ((val & 0x0800000000000000) >> 23) /* bit 59 -> 36 */ - | ((val & 0x00000000000fffff) << 13) /* bit 0 -> 13 */)); - ia64_patch(insn_addr - 1, 0x1fffffffffc, val >> 18); + 0x011ffffe000UL, ( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */ + | ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */)); + ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18); } /* @@ -130,10 +130,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) while (offp < (s32 *) end) { wp = (u64 *) ia64_imva((char *) offp + *offp); - wp[0] = 0x0000000100000000; /* nop.m 0; nop.i 0; nop.i 0 */ - wp[1] = 0x0004000000000200; - wp[2] = 0x0000000100000011; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */ - wp[3] = 0x0084006880000200; + wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */ + wp[1] = 0x0004000000000200UL; + wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */ + wp[3] = 0x0084006880000200UL; ia64_fc(wp); ia64_fc(wp + 2); ++offp; } diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 3a6ebc736..a141ecbd4 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -38,8 +38,8 @@ #include #include #include +#include -#include #include #include #include @@ -572,12 +572,6 @@ pfm_unreserve_page(unsigned long a) ClearPageReserved(vmalloc_to_page((void*)a)); } -static inline int -pfm_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot) -{ - return remap_page_range(vma, from, phys_addr, size, prot); -} - static inline unsigned long pfm_protect_ctx_ctxsw(pfm_context_t *x) { @@ -805,18 +799,6 @@ pfm_reset_msgq(pfm_context_t *ctx) DPRINT(("ctx=%p msgq reset\n", ctx)); } - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long -pfm_kvirt_to_pa(unsigned long adr) -{ - __u64 pa = ia64_tpa(adr); - return pa; -} - static void * pfm_rvmalloc(unsigned long size) { @@ -1513,7 +1495,7 @@ exit_pfm_fs(void) } static ssize_t -pfm_read(struct file *filp, char *buf, size_t size, loff_t *ppos) +pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { pfm_context_t *ctx; pfm_msg_t *msg; @@ -1606,7 +1588,7 @@ abort: } static ssize_t -pfm_write(struct file *file, const char *ubuf, +pfm_write(struct file *file, const char __user *ubuf, size_t size, loff_t *ppos) { DPRINT(("pfm_write called\n")); @@ -1656,7 +1638,7 @@ pfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned lon } /* - * context is locked when coming here and interrupts are disabled + * interrupt cannot be masked when coming here */ static inline int pfm_do_fasync(int fd, struct file *filp, pfm_context_t *ctx, int on) @@ -1678,7 +1660,6 @@ static int pfm_fasync(int fd, struct file *filp, int on) { pfm_context_t *ctx; - unsigned long flags; int ret; if (PFM_IS_FILE(filp) == 0) { @@ -1691,19 +1672,21 @@ pfm_fasync(int fd, struct file *filp, int on) printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", current->pid); return -EBADF; } - - - PROTECT_CTX(ctx, flags); - + /* + * we cannot mask interrupts during this call because this may + * may go to sleep if memory is not readily avalaible. + * + * We are protected from the conetxt disappearing by the get_fd()/put_fd() + * done in caller. Serialization of this function is ensured by caller. + */ ret = pfm_do_fasync(fd, filp, ctx, on); + DPRINT(("pfm_fasync called on ctx_fd=%d on=%d async_queue=%p ret=%d\n", fd, on, ctx->ctx_async_queue, ret)); - UNPROTECT_CTX(ctx, flags); - return ret; } @@ -2015,7 +1998,7 @@ pfm_close(struct inode *inode, struct file *filp) /* * XXX: check for signals : - * - ok of explicit close + * - ok for explicit close * - not ok when coming from exit_files() */ schedule(); @@ -2227,6 +2210,15 @@ out: static void pfm_free_fd(int fd, struct file *file) { + struct files_struct *files = current->files; + + /* + * there ie no fd_uninstall(), so we do it here + */ + spin_lock(&files->file_lock); + files->fd[fd] = NULL; + spin_unlock(&files->file_lock); + if (file) put_filp(file); put_unused_fd(fd); } @@ -2234,14 +2226,14 @@ pfm_free_fd(int fd, struct file *file) static int pfm_remap_buffer(struct vm_area_struct *vma, unsigned long buf, unsigned long addr, unsigned long size) { - unsigned long page; - DPRINT(("CPU%d buf=0x%lx addr=0x%lx size=%ld\n", smp_processor_id(), buf, addr, size)); while (size > 0) { - page = pfm_kvirt_to_pa(buf); + unsigned long pfn = ia64_tpa(buf) >> PAGE_SHIFT; - if (pfm_remap_page_range(vma, addr, page, PAGE_SIZE, PAGE_READONLY)) return -ENOMEM; + + if (remap_pfn_range(vma, addr, pfn, PAGE_SIZE, PAGE_READONLY)) + return -ENOMEM; addr += PAGE_SIZE; buf += PAGE_SIZE; @@ -2277,7 +2269,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon * if ((mm->total_vm << PAGE_SHIFT) + len> task->rlim[RLIMIT_AS].rlim_cur) * return -ENOMEM; */ - if (size > task->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN; + if (size > task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) + return -ENOMEM; /* * We do the easy to undo allocations first. @@ -2302,10 +2295,6 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon /* * partially initialize the vma for the sampling buffer - * - * The VM_DONTCOPY flag is very important as it ensures that the mapping - * will never be inherited for any child process (via fork()) which is always - * what we want. */ vma->vm_mm = mm; vma->vm_flags = VM_READ| VM_MAYREAD |VM_RESERVED; @@ -2335,6 +2324,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon goto error; } vma->vm_end = vma->vm_start + size; + vma->vm_pgoff = vma->vm_start >> PAGE_SHIFT; DPRINT(("aligned size=%ld, hdr=%p mapped @0x%lx\n", size, ctx->ctx_smpl_hdr, vma->vm_start)); @@ -2352,7 +2342,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon insert_vm_struct(mm, vma); mm->total_vm += size >> PAGE_SHIFT; - + vm_stat_account(vma); up_write(&task->mm->mmap_sem); /* @@ -2582,7 +2572,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task) return -EINVAL; } - if (task->state == TASK_ZOMBIE) { + if (task->exit_state == EXIT_ZOMBIE) { DPRINT(("cannot attach to zombie task [%d]\n", task->pid)); return -EBUSY; } @@ -2592,7 +2582,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task) */ if (task == current) return 0; - if (task->state != TASK_STOPPED) { + if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) { DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task->pid, task->state)); return -EBUSY; } @@ -2659,8 +2649,10 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg ctx = pfm_context_alloc(); if (!ctx) goto error; - req->ctx_fd = ctx->ctx_fd = pfm_alloc_fd(&filp); - if (req->ctx_fd < 0) goto error_file; + ret = pfm_alloc_fd(&filp); + if (ret < 0) goto error_file; + + req->ctx_fd = ctx->ctx_fd = ret; /* * attach context to file @@ -3065,11 +3057,12 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) #endif } - DPRINT(("pmc[%u]=0x%lx loaded=%d access_pmu=%d all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n", + DPRINT(("pmc[%u]=0x%lx ld=%d apmu=%d flags=0x%x all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n", cnum, value, is_loaded, can_access_pmu, + flags, ctx->ctx_all_pmcs[0], ctx->ctx_used_pmds[0], ctx->ctx_pmds[cnum].eventid, @@ -3245,8 +3238,8 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) } } - DPRINT(("pmd[%u]=0x%lx loaded=%d access_pmu=%d, hw_value=0x%lx ctx_pmd=0x%lx short_reset=0x%lx " - "long_reset=0x%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx reload_pmds=0x%lx all_pmds=0x%lx ovfl_regs=0x%lx\n", + DPRINT(("pmd[%u]=0x%lx ld=%d apmu=%d, hw_value=0x%lx ctx_pmd=0x%lx short_reset=0x%lx " + "long_reset=0x%lx notify=%c seed=0x%lx mask=0x%lx used_pmds=0x%lx reset_pmds=0x%lx reload_pmds=0x%lx all_pmds=0x%lx ovfl_regs=0x%lx\n", cnum, value, is_loaded, @@ -3256,6 +3249,8 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) ctx->ctx_pmds[cnum].short_reset, ctx->ctx_pmds[cnum].long_reset, PMC_OVFL_NOTIFY(ctx, cnum) ? 'Y':'N', + ctx->ctx_pmds[cnum].seed, + ctx->ctx_pmds[cnum].mask, ctx->ctx_used_pmds[0], ctx->ctx_pmds[cnum].reset_pmds[0], ctx->ctx_reload_pmds[0], @@ -3333,7 +3328,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) } expert_mode = pfm_sysctl.expert_mode; - DPRINT(("loaded=%d access_pmu=%d ctx_state=%d\n", + DPRINT(("ld=%d apmu=%d ctx_state=%d\n", is_loaded, can_access_pmu, state)); @@ -3873,7 +3868,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_ ctx->ctx_ibrs[rnum] = dbreg.val; - DPRINT(("write ibr%u=0x%lx used_ibrs=0x%x is_loaded=%d access_pmu=%d\n", + DPRINT(("write ibr%u=0x%lx used_ibrs=0x%x ld=%d apmu=%d\n", rnum, dbreg.val, ctx->ctx_used_ibrs[0], is_loaded, can_access_pmu)); } else { CTX_USED_DBR(ctx, rnum); @@ -3884,7 +3879,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_ } ctx->ctx_dbrs[rnum] = dbreg.val; - DPRINT(("write dbr%u=0x%lx used_dbrs=0x%x is_loaded=%d access_pmu=%d\n", + DPRINT(("write dbr%u=0x%lx used_dbrs=0x%x ld=%d apmu=%d\n", rnum, dbreg.val, ctx->ctx_used_dbrs[0], is_loaded, can_access_pmu)); } } @@ -3985,7 +3980,10 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) state = ctx->ctx_state; is_system = ctx->ctx_fl_system; - if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL; + /* + * context must be attached to issue the stop command (includes LOADED,MASKED,ZOMBIE) + */ + if (state == PFM_CTX_UNLOADED) return -EINVAL; /* * In system wide and when the context is loaded, access can only happen @@ -4741,7 +4739,7 @@ recheck: * the task must be stopped. */ if (PFM_CMD_STOPPED(cmd)) { - if (task->state != TASK_STOPPED) { + if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) { DPRINT(("[%d] task not in stopped state\n", task->pid)); return -EBUSY; } @@ -4782,7 +4780,7 @@ recheck: * system-call entry point (must return long) */ asmlinkage long -sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, long arg7, +sys_perfmonctl (int fd, int cmd, void __user *arg, int count, long arg5, long arg6, long arg7, long arg8, long stack) { struct pt_regs *regs = (struct pt_regs *)&stack; @@ -4980,26 +4978,14 @@ pfm_resume_after_ovfl(pfm_context_t *ctx, unsigned long ovfl_regs, struct pt_reg static void pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs) { - if (ctx->ctx_fl_system) { - printk(KERN_ERR "perfmon: pfm_context_force_terminate [%d] is system-wide\n", current->pid); - return; - } - /* - * we stop the whole thing, we do no need to flush - * we know we WERE masked - */ - pfm_clear_psr_up(); - ia64_psr(regs)->up = 0; - ia64_psr(regs)->sp = 1; + int ret; - /* - * disconnect the task from the context and vice-versa - */ - current->thread.pfm_context = NULL; - current->thread.flags &= ~IA64_THREAD_PM_VALID; - ctx->ctx_task = NULL; + DPRINT(("entering for [%d]\n", current->pid)); - DPRINT(("context terminated\n")); + ret = pfm_context_unload(ctx, NULL, 0, regs); + if (ret) { + printk(KERN_ERR "pfm_context_force_terminate: [%d] unloaded failed with %d\n", current->pid, ret); + } /* * and wakeup controlling task, indicating we are now disconnected @@ -5059,6 +5045,18 @@ pfm_handle_work(void) UNPROTECT_CTX(ctx, flags); + /* + * pfm_handle_work() is currently called with interrupts disabled. + * The down_interruptible call may sleep, therefore we + * must re-enable interrupts to avoid deadlocks. It is + * safe to do so because this function is called ONLY + * when returning to user level (PUStk=1), in which case + * there is no risk of kernel stack overflow due to deep + * interrupt nesting. + */ + BUG_ON(flags & IA64_PSR_I); + local_irq_enable(); + DPRINT(("before block sleeping\n")); /* @@ -5069,6 +5067,12 @@ pfm_handle_work(void) DPRINT(("after block sleeping ret=%d\n", ret)); + /* + * disable interrupts to restore state we had upon entering + * this function + */ + local_irq_disable(); + PROTECT_CTX(ctx, flags); /* @@ -5354,9 +5358,8 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str if (ovfl_notify == 0) reset_pmds = ovfl_pmds; } - DPRINT(("ovfl_pmds=0x%lx reset_pmds=0x%lx\n", - ovfl_pmds, - reset_pmds)); + DPRINT_ovfl(("ovfl_pmds=0x%lx reset_pmds=0x%lx\n", ovfl_pmds, reset_pmds)); + /* * reset the requested PMD registers using the short reset values */ @@ -5856,14 +5859,6 @@ pfm_save_regs(struct task_struct *task) return; } - /* - * sanity check - */ - if (ctx->ctx_last_activation != GET_ACTIVATION()) { - pfm_unprotect_ctx_ctxsw(ctx, flags); - return; - } - /* * save current PSR: needed because we modify it */ @@ -6312,15 +6307,15 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) */ is_self = ctx->ctx_task == task ? 1 : 0; -#ifdef CONFIG_SMP - if (task == current) { -#else /* - * in UP, the state can still be in the registers + * can access PMU is task is the owner of the PMU state on the current CPU + * or if we are running on the CPU bound to the context in system-wide mode + * (that is not necessarily the task the context is attached to in this mode). + * In system-wide we always have can_access_pmu true because a task running on an + * invalid processor is flagged earlier in the call stack (see pfm_stop). */ - if (task == current || GET_PMU_OWNER() == task) { -#endif - can_access_pmu = 1; + can_access_pmu = (GET_PMU_OWNER() == task) || (ctx->ctx_fl_system && ctx->ctx_cpu == smp_processor_id()); + if (can_access_pmu) { /* * Mark the PMU as not owned * This will cause the interrupt handler to do nothing in case an overflow @@ -6330,6 +6325,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) * on. */ SET_PMU_OWNER(NULL, NULL); + DPRINT(("releasing ownership\n")); /* * read current overflow status: @@ -6358,6 +6354,9 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) * XXX: sampling situation is not taken into account here */ mask2 = ctx->ctx_used_pmds[0]; + + DPRINT(("is_self=%d ovfl_val=0x%lx mask2=0x%lx\n", is_self, ovfl_val, mask2)); + for (i = 0; mask2; i++, mask2>>=1) { /* skip non used pmds */ @@ -6396,7 +6395,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) } } - DPRINT(("[%d] is_self=%d ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, is_self, i, val, pmd_val)); + DPRINT(("[%d] ctx_pmd[%d]=0x%lx pmd_val=0x%lx\n", task->pid, i, val, pmd_val)); if (is_self) task->thread.pmds[i] = pmd_val; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 842c95b8a..078075f7b 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -47,6 +47,8 @@ void (*ia64_mark_idle)(int); +unsigned long boot_option_idle_override = 0; +EXPORT_SYMBOL(boot_option_idle_override); void ia64_do_show_stack (struct unw_frame_info *info, void *arg) @@ -74,12 +76,12 @@ void show_stack (struct task_struct *task, unsigned long *sp) { if (!task) - unw_init_running(ia64_do_show_stack, 0); + unw_init_running(ia64_do_show_stack, NULL); else { struct unw_frame_info info; unw_init_from_blocked_task(&info, task); - ia64_do_show_stack(&info, 0); + ia64_do_show_stack(&info, NULL); } } @@ -138,7 +140,7 @@ show_regs (struct pt_regs *regs) ndirty = (regs->loadrs >> 19); bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty); for (i = 0; i < sof; ++i) { - get_user(val, ia64_rse_skip_regs(bsp, i)); + get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i)); printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val, ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); } @@ -185,6 +187,8 @@ default_idle (void) while (!need_resched()) if (pal_halt && !pmu_active) safe_halt(); + else + cpu_relax(); } #ifdef CONFIG_HOTPLUG_CPU @@ -228,18 +232,26 @@ cpu_idle (void *unused) /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - #ifdef CONFIG_SMP if (!need_resched()) min_xtp(); #endif while (!need_resched()) { + void (*idle)(void); + if (mark_idle) (*mark_idle)(1); + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); + idle = pm_idle; + if (!idle) + idle = default_idle; (*idle)(); + rcu_read_unlock(); } if (mark_idle) @@ -602,16 +614,18 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) } asmlinkage long -sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs) +sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp, + struct pt_regs *regs) { + char *fname; int error; - filename = getname(filename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) + fname = getname(filename); + error = PTR_ERR(fname); + if (IS_ERR(fname)) goto out; - error = do_execve(filename, argv, envp, regs); - putname(filename); + error = do_execve(fname, argv, envp, regs); + putname(fname); out: return error; } @@ -743,7 +757,7 @@ cpu_halt (void) void machine_restart (char *restart_cmd) { - (*efi.reset_system)(EFI_RESET_WARM, 0, 0, 0); + (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); } EXPORT_SYMBOL(machine_restart); diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 56ce1d458..817caef5e 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1,7 +1,7 @@ /* * Kernel support for the ptrace() and syscall tracing interfaces. * - * Copyright (C) 1999-2003 Hewlett-Packard Co + * Copyright (C) 1999-2004 Hewlett-Packard Co * David Mosberger-Tang * * Derived from the x86 and Alpha versions. Most of the code in here @@ -152,7 +152,7 @@ ia64_increment_ip (struct pt_regs *regs) ri = 0; regs->cr_iip += 16; } else if (ri == 2) { - get_user(w0, (char *) regs->cr_iip + 0); + get_user(w0, (char __user *) regs->cr_iip + 0); if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) { /* * rfi'ing to slot 2 of an MLX bundle causes @@ -174,7 +174,7 @@ ia64_decrement_ip (struct pt_regs *regs) if (ia64_psr(regs)->ri == 0) { regs->cr_iip -= 16; ri = 2; - get_user(w0, (char *) regs->cr_iip + 0); + get_user(w0, (char __user *) regs->cr_iip + 0); if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) { /* * rfi'ing to slot 2 of an MLX bundle causes @@ -304,7 +304,6 @@ put_rnat (struct task_struct *task, struct switch_stack *sw, long num_regs, nbits; struct pt_regs *pt; unsigned long cfm, *urbs_kargs; - struct unw_frame_info info; pt = ia64_task_regs(task); kbsp = (unsigned long *) sw->ar_bspstore; @@ -316,11 +315,8 @@ put_rnat (struct task_struct *task, struct switch_stack *sw, * If entered via syscall, don't allow user to set rnat bits * for syscall args. */ - unw_init_from_blocked_task(&info,task); - if (unw_unwind_to_user(&info) == 0) { - unw_get_cfm(&info,&cfm); - urbs_kargs = ia64_rse_skip_regs(urbs_end,-(cfm & 0x7f)); - } + cfm = pt->cr_ifs; + urbs_kargs = ia64_rse_skip_regs(urbs_end, -(cfm & 0x7f)); } if (urbs_kargs >= urnat_addr) @@ -480,27 +476,18 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned unsigned long ia64_get_user_rbs_end (struct task_struct *child, struct pt_regs *pt, unsigned long *cfmp) { - unsigned long *krbs, *bspstore, cfm; - struct unw_frame_info info; + unsigned long *krbs, *bspstore, cfm = pt->cr_ifs; long ndirty; krbs = (unsigned long *) child + IA64_RBS_OFFSET/8; bspstore = (unsigned long *) pt->ar_bspstore; ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); - cfm = pt->cr_ifs & ~(1UL << 63); - if (in_syscall(pt)) { - /* - * If bit 63 of cr.ifs is cleared, the kernel was entered via a system - * call and we need to recover the CFM that existed on entry to the - * kernel by unwinding the kernel stack. - */ - unw_init_from_blocked_task(&info, child); - if (unw_unwind_to_user(&info) == 0) { - unw_get_cfm(&info, &cfm); - ndirty += (cfm & 0x7f); - } - } + if (in_syscall(pt)) + ndirty += (cfm & 0x7f); + else + cfm &= ~(1UL << 63); /* clear valid bit */ + if (cfmp) *cfmp = cfm; return (unsigned long) ia64_rse_skip_regs(bspstore, ndirty); @@ -833,7 +820,7 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data case PT_CFM: urbs_end = ia64_get_user_rbs_end(child, pt, &cfm); if (write_access) { - if (((cfm ^ *data) & 0x3fffffffffU) != 0) { + if (((cfm ^ *data) & 0x3fffffffffUL) != 0) { if (ia64_sync_user_rbs(child, sw, pt->ar_bspstore, urbs_end) < 0) return -1; @@ -997,12 +984,14 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data } static long -ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) +ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) { + unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val; + struct unw_frame_info info; + struct ia64_fpreg fpval; struct switch_stack *sw; struct pt_regs *pt; long ret, retval; - struct unw_frame_info info; char nat = 0; int i; @@ -1023,12 +1012,21 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) return -EIO; } + if (access_uarea(child, PT_CR_IPSR, &psr, 0) < 0 + || access_uarea(child, PT_AR_EC, &ec, 0) < 0 + || access_uarea(child, PT_AR_LC, &lc, 0) < 0 + || access_uarea(child, PT_AR_RNAT, &rnat, 0) < 0 + || access_uarea(child, PT_AR_BSP, &bsp, 0) < 0 + || access_uarea(child, PT_CFM, &cfm, 0) + || access_uarea(child, PT_NAT_BITS, &nat_bits, 0)) + return -EIO; + retval = 0; /* control regs */ retval |= __put_user(pt->cr_iip, &ppr->cr_iip); - retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 0); + retval |= __put_user(psr, &ppr->cr_ipsr); /* app regs */ @@ -1039,11 +1037,11 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) retval |= __put_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]); retval |= __put_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]); - retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 0); - retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 0); - retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 0); - retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 0); - retval |= access_uarea(child, PT_CFM, &ppr->cfm, 0); + retval |= __put_user(ec, &ppr->ar[PT_AUR_EC]); + retval |= __put_user(lc, &ppr->ar[PT_AUR_LC]); + retval |= __put_user(rnat, &ppr->ar[PT_AUR_RNAT]); + retval |= __put_user(bsp, &ppr->ar[PT_AUR_BSP]); + retval |= __put_user(cfm, &ppr->cfm); /* gr1-gr3 */ @@ -1053,7 +1051,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* gr4-gr7 */ for (i = 4; i < 8; i++) { - retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 0); + if (unw_access_gr(&info, i, &val, &nat, 0) < 0) + return -EIO; + retval |= __put_user(val, &ppr->gr[i]); } /* gr8-gr11 */ @@ -1077,7 +1077,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* b1-b5 */ for (i = 1; i < 6; i++) { - retval |= unw_access_br(&info, i, &ppr->br[i], 0); + if (unw_access_br(&info, i, &val, 0) < 0) + return -EIO; + __put_user(val, &ppr->br[i]); } /* b6-b7 */ @@ -1088,8 +1090,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* fr2-fr5 */ for (i = 2; i < 6; i++) { - retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0); - retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0); + if (unw_get_fr(&info, i, &fpval) < 0) + return -EIO; + retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval)); } /* fr6-fr11 */ @@ -1103,8 +1106,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* fr16-fr31 */ for (i = 16; i < 32; i++) { - retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0); - retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0); + if (unw_get_fr(&info, i, &fpval) < 0) + return -EIO; + retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval)); } /* fph */ @@ -1118,22 +1122,25 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* nat bits */ - retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 0); + retval |= __put_user(nat_bits, &ppr->nat); ret = retval ? -EIO : 0; return ret; } static long -ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) +ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) { + unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0; + struct unw_frame_info info; struct switch_stack *sw; + struct ia64_fpreg fpval; struct pt_regs *pt; long ret, retval; - struct unw_frame_info info; - char nat = 0; int i; + memset(&fpval, 0, sizeof(fpval)); + retval = verify_area(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)); if (retval != 0) { return -EIO; @@ -1156,7 +1163,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* control regs */ retval |= __get_user(pt->cr_iip, &ppr->cr_iip); - retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 1); + retval |= __get_user(psr, &ppr->cr_ipsr); /* app regs */ @@ -1167,11 +1174,11 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]); retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]); - retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 1); - retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 1); - retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 1); - retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 1); - retval |= access_uarea(child, PT_CFM, &ppr->cfm, 1); + retval |= __get_user(ec, &ppr->ar[PT_AUR_EC]); + retval |= __get_user(lc, &ppr->ar[PT_AUR_LC]); + retval |= __get_user(rnat, &ppr->ar[PT_AUR_RNAT]); + retval |= __get_user(bsp, &ppr->ar[PT_AUR_BSP]); + retval |= __get_user(cfm, &ppr->cfm); /* gr1-gr3 */ @@ -1181,11 +1188,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* gr4-gr7 */ for (i = 4; i < 8; i++) { - long ret = unw_get_gr(&info, i, &ppr->gr[i], &nat); - if (ret < 0) { - return ret; - } - retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 1); + retval |= __get_user(val, &ppr->gr[i]); + if (unw_set_gr(&info, i, val, 0) < 0) /* NaT bit will be set via PT_NAT_BITS */ + return -EIO; } /* gr8-gr11 */ @@ -1209,7 +1214,8 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* b1-b5 */ for (i = 1; i < 6; i++) { - retval |= unw_access_br(&info, i, &ppr->br[i], 1); + retval |= __get_user(val, &ppr->br[i]); + unw_set_br(&info, i, val); } /* b6-b7 */ @@ -1220,8 +1226,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* fr2-fr5 */ for (i = 2; i < 6; i++) { - retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1); - retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1); + retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval)); + if (unw_set_fr(&info, i, fpval) < 0) + return -EIO; } /* fr6-fr11 */ @@ -1235,8 +1242,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* fr16-fr31 */ for (i = 16; i < 32; i++) { - retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1); - retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1); + retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval)); + if (unw_set_fr(&info, i, fpval) < 0) + return -EIO; } /* fph */ @@ -1250,7 +1258,15 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr) /* nat bits */ - retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 1); + retval |= __get_user(nat_bits, &ppr->nat); + + retval |= access_uarea(child, PT_CR_IPSR, &psr, 1); + retval |= access_uarea(child, PT_AR_EC, &ec, 1); + retval |= access_uarea(child, PT_AR_LC, &lc, 1); + retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1); + retval |= access_uarea(child, PT_AR_BSP, &bsp, 1); + retval |= access_uarea(child, PT_CFM, &cfm, 1); + retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1); ret = retval ? -EIO : 0; return ret; @@ -1393,7 +1409,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, * sigkill. Perhaps it should be put in the status * that it wants to exit. */ - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ goto out_tsk; child->exit_code = SIGKILL; @@ -1429,11 +1445,11 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, goto out_tsk; case PTRACE_GETREGS: - ret = ptrace_getregs(child, (struct pt_all_user_regs*) data); + ret = ptrace_getregs(child, (struct pt_all_user_regs __user *) data); goto out_tsk; case PTRACE_SETREGS: - ret = ptrace_setregs(child, (struct pt_all_user_regs*) data); + ret = ptrace_setregs(child, (struct pt_all_user_regs __user *) data); goto out_tsk; default: diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index dcbc07ec3..3ec0d2d22 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -262,3 +263,40 @@ ia64_sal_init (struct ia64_sal_systab *systab) p += SAL_DESC_SIZE(*p); } } + +int +ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, + u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7) +{ + if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) + return -1; + SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return 0; +} +EXPORT_SYMBOL(ia64_sal_oemcall); + +int +ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, + u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, + u64 arg7) +{ + if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) + return -1; + SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, + arg7); + return 0; +} +EXPORT_SYMBOL(ia64_sal_oemcall_nolock); + +int +ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc, + u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, + u64 arg6, u64 arg7) +{ + if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) + return -1; + SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, + arg7); + return 0; +} +EXPORT_SYMBOL(ia64_sal_oemcall_reentrant); diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index a0420ae4d..500e1050c 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -268,7 +268,7 @@ salinfo_event_open(struct inode *inode, struct file *file) } static ssize_t -salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); @@ -417,11 +417,16 @@ retry: if (!data->saved_num) call_on_cpu(cpu, salinfo_log_read_cpu, data); - data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA; + if (!data->log_size) { + data->state = STATE_NO_DATA; + clear_bit(cpu, &data->cpu_event); + } else { + data->state = STATE_LOG_RECORD; + } } static ssize_t -salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); @@ -478,7 +483,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) } static ssize_t -salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 8aff39de1..7b2033bf0 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -258,25 +258,6 @@ io_port_init (void) num_io_spaces = 1; } -#ifdef CONFIG_SERIAL_8250_CONSOLE -static void __init -setup_serial_legacy (void) -{ - struct uart_port port; - unsigned int i, iobase[] = {0x3f8, 0x2f8}; - - printk(KERN_INFO "Registering legacy COM ports for serial console\n"); - memset(&port, 0, sizeof(port)); - port.iotype = SERIAL_IO_PORT; - port.uartclk = BASE_BAUD * 16; - for (i = 0; i < ARRAY_SIZE(iobase); i++) { - port.line = i; - port.iobase = iobase[i]; - early_serial_setup(&port); - } -} -#endif - /** * early_console_setup - setup debugging console * @@ -287,19 +268,36 @@ setup_serial_legacy (void) * Returns non-zero if a console couldn't be setup. */ static inline int __init -early_console_setup (void) +early_console_setup (char *cmdline) { #ifdef CONFIG_SERIAL_SGI_L1_CONSOLE { extern int sn_serial_console_early_setup(void); - if(!sn_serial_console_early_setup()) + if (!sn_serial_console_early_setup()) return 0; } #endif +#ifdef CONFIG_EFI_PCDP + if (!efi_setup_pcdp_console(cmdline)) + return 0; +#endif +#ifdef CONFIG_SERIAL_8250_CONSOLE + if (!early_serial_console_init(cmdline)) + return 0; +#endif return -1; } +static inline void +mark_bsp_online (void) +{ +#ifdef CONFIG_SMP + /* If we register an early console, allow CPU 0 to printk */ + cpu_set(smp_processor_id(), cpu_online_map); +#endif +} + void __init setup_arch (char **cmdline_p) { @@ -317,11 +315,8 @@ setup_arch (char **cmdline_p) machvec_init(acpi_get_sysname()); #endif -#ifdef CONFIG_SMP - /* If we register an early console, allow CPU 0 to printk */ - if (!early_console_setup()) - cpu_set(smp_processor_id(), cpu_online_map); -#endif + if (early_console_setup(*cmdline_p) == 0) + mark_bsp_online(); #ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */ @@ -349,13 +344,6 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_ACPI_BOOT acpi_boot_init(); #endif -#ifdef CONFIG_EFI_PCDP - efi_setup_pcdp_console(*cmdline_p); -#endif -#ifdef CONFIG_SERIAL_8250_CONSOLE - if (!efi.hcdp) - setup_serial_legacy(); -#endif #ifdef CONFIG_VT if (!conswitchp) { @@ -680,7 +668,7 @@ cpu_init (void) break; } - if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) { + if (ia64_pal_rse_info(&num_phys_stacked, NULL) != 0) { printk(KERN_WARNING "cpu_init: PAL RSE info failed; assuming 96 physical " "stacked regs\n"); num_phys_stacked = 96; diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h index 55e527527..37b986cb8 100644 --- a/arch/ia64/kernel/sigframe.h +++ b/arch/ia64/kernel/sigframe.h @@ -17,7 +17,7 @@ struct sigframe { * End of architected state. */ - void *handler; /* pointer to the plabel of the signal handler */ + void __user *handler; /* pointer to the plabel of the signal handler */ struct siginfo info; struct sigcontext sc; }; diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 5a609295a..62fcc7bd4 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -1,7 +1,7 @@ /* * Architecture-specific signal handling support. * - * Copyright (C) 1999-2003 Hewlett-Packard Co + * Copyright (C) 1999-2004 Hewlett-Packard Co * David Mosberger-Tang * * Derived from i386 and Alpha versions. @@ -43,7 +43,7 @@ #endif long -ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr) +ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) { sigset_t oldset, set; @@ -84,7 +84,7 @@ ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr) } asmlinkage long -sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long arg4, +sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack) { struct pt_regs *pt = (struct pt_regs *) &stack; @@ -93,7 +93,7 @@ sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long a } static long -restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr) +restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) { unsigned long ip, flags, nat, um, cfm; long err; @@ -155,7 +155,7 @@ restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr) } int -copy_siginfo_to_user (siginfo_t *to, siginfo_t *from) +copy_siginfo_to_user (siginfo_t __user *to, siginfo_t *from) { if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t))) return -EFAULT; @@ -211,12 +211,12 @@ long ia64_rt_sigreturn (struct sigscratch *scr) { extern char ia64_strace_leave_kernel, ia64_leave_kernel; - struct sigcontext *sc; + struct sigcontext __user *sc; struct siginfo si; sigset_t set; long retval; - sc = &((struct sigframe *) (scr->pt.r12 + 16))->sc; + sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc; /* * When we return to the previously executing context, r8 and r10 have already @@ -260,7 +260,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) * It is more difficult to avoid calling this function than to * call it and ignore errors. */ - do_sigaltstack(&sc->sc_stack, 0, scr->pt.r12); + do_sigaltstack(&sc->sc_stack, NULL, scr->pt.r12); return retval; give_sigsegv: @@ -281,7 +281,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) * trampoline starts. Everything else is done at the user-level. */ static long -setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) +setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr) { unsigned long flags = 0, ifs, cfm, nat; long err; @@ -290,12 +290,10 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) if (on_sig_stack((unsigned long) sc)) flags |= IA64_SC_FLAG_ONSTACK; - if ((ifs & (1UL << 63)) == 0) { - /* if cr_ifs isn't valid, we got here through a syscall */ + if ((ifs & (1UL << 63)) == 0) + /* if cr_ifs doesn't have the valid bit set, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; - cfm = scr->ar_pfs & ((1UL << 38) - 1); - } else - cfm = ifs & ((1UL << 38) - 1); + cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; @@ -335,7 +333,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */ err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ err |= __put_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */ - err |= __copy_to_user(&scr->pt.ar_csd, &sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */ + err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */ err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8); /* r2-r3 */ err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ } @@ -351,21 +349,50 @@ rbs_on_sig_stack (unsigned long bsp) return (bsp - current->sas_ss_sp < current->sas_ss_size); } +static long +force_sigsegv_info (int sig, void __user *addr) +{ + unsigned long flags; + struct siginfo si; + + if (sig == SIGSEGV) { + /* + * Acquiring siglock around the sa_handler-update is almost + * certainly overkill, but this isn't a + * performance-critical path and I'd rather play it safe + * here than having to debug a nasty race if and when + * something changes in kernel/signal.c that would make it + * no longer safe to modify sa_handler without holding the + * lock. + */ + spin_lock_irqsave(¤t->sighand->siglock, flags); + current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + } + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SI_KERNEL; + si.si_pid = current->pid; + si.si_uid = current->uid; + si.si_addr = addr; + force_sig_info(SIGSEGV, &si, current); + return 0; +} + static long setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr) { extern char __kernel_sigtramp[]; unsigned long tramp_addr, new_rbs = 0; - struct sigframe *frame; - struct siginfo si; + struct sigframe __user *frame; long err; - frame = (void *) scr->pt.r12; + frame = (void __user *) scr->pt.r12; tramp_addr = (unsigned long) __kernel_sigtramp; if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) { - frame = (void *) ((current->sas_ss_sp + current->sas_ss_size) - & ~(STACK_ALIGN - 1)); + frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size) + & ~(STACK_ALIGN - 1)); /* * We need to check for the register stack being on the signal stack * separately, because it's switched separately (memory stack is switched @@ -374,10 +401,10 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); } - frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); + frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return force_sigsegv_info(sig, frame); err = __put_user(sig, &frame->arg0); err |= __put_user(&frame->info, &frame->arg1); @@ -393,8 +420,8 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags); err |= setup_sigcontext(&frame->sc, set, scr); - if (err) - goto give_sigsegv; + if (unlikely(err)) + return force_sigsegv_info(sig, frame); scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ @@ -422,18 +449,6 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler); #endif return 1; - - give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - si.si_signo = SIGSEGV; - si.si_errno = 0; - si.si_code = SI_KERNEL; - si.si_pid = current->pid; - si.si_uid = current->uid; - si.si_addr = frame; - force_sig_info(SIGSEGV, &si, current); - return 0; } static long @@ -449,9 +464,6 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse if (!setup_frame(sig, ka, info, oldset, scr)) return 0; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); { @@ -471,7 +483,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { - struct k_sigaction *ka; + struct k_sigaction ka; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; @@ -493,7 +505,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) * need to push through a forced SIGSEGV. */ while (1) { - int signr = get_signal_to_deliver(&info, &scr->pt, NULL); + int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL); /* * get_signal_to_deliver() may have run a debugger (via notify_parent()) @@ -520,8 +532,6 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) if (signr <= 0) break; - ka = ¤t->sighand->action[signr - 1]; - if (unlikely(restart)) { switch (errno) { case ERESTART_RESTARTBLOCK: @@ -531,7 +541,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) break; case ERESTARTSYS: - if ((ka->sa.sa_flags & SA_RESTART) == 0) { + if ((ka.sa.sa_flags & SA_RESTART) == 0) { scr->pt.r8 = ERR_CODE(EINTR); /* note: scr->pt.r10 is already -1 */ break; @@ -550,7 +560,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) * Whee! Actually deliver the signal. If the delivery failed, we need to * continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, ka, &info, oldset, scr)) + if (handle_signal(signr, &ka, &info, oldset, scr)) return 1; } diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index 99f008853..4534b9618 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -29,9 +29,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -225,7 +225,7 @@ smp_send_reschedule (int cpu) void smp_flush_tlb_all (void) { - on_each_cpu((void (*)(void *))local_flush_tlb_all, 0, 1, 1); + on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1); } EXPORT_SYMBOL(smp_flush_tlb_all); @@ -290,11 +290,11 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int /* Wait for response */ while (atomic_read(&data.started) != cpus) - barrier(); + cpu_relax(); if (wait) while (atomic_read(&data.finished) != cpus) - barrier(); + cpu_relax(); call_data = NULL; spin_unlock_bh(&call_lock); @@ -349,11 +349,11 @@ smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wai /* Wait for response */ while (atomic_read(&data.started) != cpus) - barrier(); + cpu_relax(); if (wait) while (atomic_read(&data.finished) != cpus) - barrier(); + cpu_relax(); call_data = NULL; spin_unlock(&call_lock); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 9a0f79233..0a0bf9751 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -29,9 +29,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -356,19 +356,15 @@ start_secondary (void *unused) return cpu_idle(); } -static struct task_struct * __devinit -fork_by_hand (void) +struct pt_regs * __devinit idle_regs(struct pt_regs *regs) { - /* - * Don't care about the IP and regs settings since we'll never reschedule the - * forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL); + return NULL; } struct create_idle { struct task_struct *idle; struct completion done; + int cpu; }; void @@ -376,7 +372,7 @@ do_fork_idle(void *_c_idle) { struct create_idle *c_idle = _c_idle; - c_idle->idle = fork_by_hand(); + c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); } @@ -384,10 +380,11 @@ static int __devinit do_boot_cpu (int sapicid, int cpu) { int timeout; - struct create_idle c_idle; + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER(c_idle.done), + }; DECLARE_WORK(work, do_fork_idle, &c_idle); - - init_completion(&c_idle.done); /* * We can't use kernel_thread since we must avoid to reschedule the child. */ @@ -400,16 +397,6 @@ do_boot_cpu (int sapicid, int cpu) if (IS_ERR(c_idle.idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(c_idle.idle); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(c_idle.idle, cpu); - - unhash_process(c_idle.idle); - task_for_booting_cpu = c_idle.idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); @@ -719,3 +706,4 @@ init_smp_config(void) printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret)); } + diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index eddde6018..73d6773d5 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -93,7 +93,7 @@ sys_getpagesize (void) } asmlinkage unsigned long -ia64_shmat (int shmid, void *shmaddr, int shmflg) +ia64_shmat (int shmid, void __user *shmaddr, int shmflg) { unsigned long raddr; int retval; @@ -138,7 +138,7 @@ ia64_brk (unsigned long brk) goto out; /* Check against rlimit.. */ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim) goto out; @@ -183,7 +183,7 @@ static inline unsigned long do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) { unsigned long roff; - struct file *file = 0; + struct file *file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index e33bcb661..f67183116 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -45,193 +45,12 @@ EXPORT_SYMBOL(last_cli_ip); #endif -static void -itc_reset (void) -{ -} - -/* - * Adjust for the fact that xtime has been advanced by delta_nsec (may be negative and/or - * larger than NSEC_PER_SEC. - */ -static void -itc_update (long delta_nsec) -{ -} - -/* - * Return the number of nano-seconds that elapsed since the last - * update to jiffy. It is quite possible that the timer interrupt - * will interrupt this and result in a race for any of jiffies, - * wall_jiffies or itm_next. Thus, the xtime_lock must be at least - * read synchronised when calling this routine (see do_gettimeofday() - * below for an example). - */ -unsigned long -itc_get_offset (void) -{ - unsigned long elapsed_cycles, lost = jiffies - wall_jiffies; - unsigned long now = ia64_get_itc(), last_tick; - - last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next - - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta); - - elapsed_cycles = now - last_tick; - return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; -} - static struct time_interpolator itc_interpolator = { - .get_offset = itc_get_offset, - .update = itc_update, - .reset = itc_reset + .shift = 16, + .mask = 0xffffffffffffffffLL, + .source = TIME_SOURCE_CPU }; -int -do_settimeofday (struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - { - /* - * This is revolting. We need to set "xtime" correctly. However, the value - * in this location is the value at the most recent update of wall time. - * Discover what correction gettimeofday would have done, and then undo - * it! - */ - nsec -= time_interpolator_get_offset(); - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - time_interpolator_reset(); - } - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - -void -do_gettimeofday (struct timeval *tv) -{ - unsigned long seq, nsec, usec, sec, old, offset; - - while (1) { - seq = read_seqbegin(&xtime_lock); - { - old = last_nsec_offset; - offset = time_interpolator_get_offset(); - sec = xtime.tv_sec; - nsec = xtime.tv_nsec; - } - if (unlikely(read_seqretry(&xtime_lock, seq))) - continue; - /* - * Ensure that for any pair of causally ordered gettimeofday() calls, time - * never goes backwards (even when ITC on different CPUs are not perfectly - * synchronized). (A pair of concurrent calls to gettimeofday() is by - * definition non-causal and hence it makes no sense to talk about - * time-continuity for such calls.) - * - * Doing this in a lock-free and race-free manner is tricky. Here is why - * it works (most of the time): read_seqretry() just succeeded, which - * implies we calculated a consistent (valid) value for "offset". If the - * cmpxchg() below succeeds, we further know that last_nsec_offset still - * has the same value as at the beginning of the loop, so there was - * presumably no timer-tick or other updates to last_nsec_offset in the - * meantime. This isn't 100% true though: there _is_ a possibility of a - * timer-tick occurring right right after read_seqretry() and then getting - * zero or more other readers which will set last_nsec_offset to the same - * value as the one we read at the beginning of the loop. If this - * happens, we'll end up returning a slightly newer time than we ought to - * (the jump forward is at most "offset" nano-seconds). There is no - * danger of causing time to go backwards, though, so we are safe in that - * sense. We could make the probability of this unlucky case occurring - * arbitrarily small by encoding a version number in last_nsec_offset, but - * even without versioning, the probability of this unlucky case should be - * so small that we won't worry about it. - */ - if (offset <= old) { - offset = old; - break; - } else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old)) - break; - - /* someone else beat us to updating last_nsec_offset; try again */ - } - - usec = (nsec + offset) / 1000; - - while (unlikely(usec >= USEC_PER_SEC)) { - usec -= USEC_PER_SEC; - ++sec; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -/* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ -static inline void -ia64_do_profile (struct pt_regs * regs) -{ - unsigned long ip, slot; - extern cpumask_t prof_cpu_mask; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; - - ip = instruction_pointer(regs); - /* Conserve space in histogram by encoding slot bits in address - * bits 2 and 3 rather than bits 0 and 1. - */ - slot = ip & 3; - ip = (ip & ~3UL) + 4*slot; - - /* - * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. - * (default is all CPUs.) - */ - if (!cpu_isset(smp_processor_id(), prof_cpu_mask)) - return; - - ip -= (unsigned long) &_stext; - ip >>= prof_shift; - /* - * Don't ignore out-of-bounds IP values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (ip > prof_len-1) - ip = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[ip]); -} - static irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { @@ -249,17 +68,11 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n", ia64_get_itc(), new_itm); - ia64_do_profile(regs); + profile_tick(CPU_PROFILING, regs); while (1) { -#ifdef CONFIG_SMP - /* - * For UP, this is done in do_timer(). Weird, but - * fixing that would require updates to all - * platforms. - */ update_process_times(user_mode(regs)); -#endif + new_itm += local_cpu_data->itm_delta; if (smp_processor_id() == TIME_KEEPER_ID) { @@ -323,6 +136,18 @@ ia64_cpu_local_tick (void) ia64_set_itm(local_cpu_data->itm_next); } +static int nojitter; + +static int __init nojitter_setup(char *str) +{ + nojitter = 1; + printk("Jitter checking for ITC timers disabled\n"); + return 1; +} + +__setup("nojitter", nojitter_setup); + + void __devinit ia64_init_itm (void) { @@ -340,7 +165,7 @@ ia64_init_itm (void) if (status != 0) { printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status)); } else { - status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio); + status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio); if (status != 0) printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status); } @@ -365,17 +190,20 @@ ia64_init_itm (void) itc_ratio.den = 1; /* avoid division by zero */ itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den; - if (platform_base_drift != -1) - itc_drift = platform_base_drift*itc_ratio.num/itc_ratio.den; - else - itc_drift = -1; local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ; - printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " - "ITC freq=%lu.%03luMHz+/-%ldppm\n", smp_processor_id(), + printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, " + "ITC freq=%lu.%03luMHz", smp_processor_id(), platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000, - itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000, - itc_drift); + itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000); + + if (platform_base_drift != -1) { + itc_drift = platform_base_drift*itc_ratio.num/itc_ratio.den; + printk("+/-%ldppm\n", itc_drift); + } else { + itc_drift = -1; + printk("\n"); + } local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; @@ -386,6 +214,19 @@ ia64_init_itm (void) if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { itc_interpolator.frequency = local_cpu_data->itc_freq; itc_interpolator.drift = itc_drift; +#ifdef CONFIG_SMP + /* On IA64 in an SMP configuration ITCs are never accurately synchronized. + * Jitter compensation requires a cmpxchg which may limit + * the scalability of the syscalls for retrieving time. + * The ITC synchronization is usually successful to within a few + * ITC ticks but this is not a sure thing. If you need to improve + * timer performance in SMP situations then boot the kernel with the + * "nojitter" option. However, doing so may result in time fluctuating (maybe + * even going backward) if the ITC offsets between the individual CPUs + * are too large. + */ + if (!nojitter) itc_interpolator.jitter = 1; +#endif register_time_interpolator(&itc_interpolator); } diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index f89913135..3dd9b1dc7 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -14,9 +14,9 @@ #include #include /* For unblank_screen() */ #include /* for EXPORT_SYMBOL */ +#include #include -#include #include #include #include @@ -112,7 +112,7 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) int sig, code; /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_imm = break_num; siginfo.si_flags = 0; /* clear __ISR_VALID */ siginfo.si_isr = 0; @@ -282,7 +282,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) fault_ip = regs->cr_iip; if (!fp_fault && (ia64_psr(regs)->ri == 0)) fault_ip -= 16; - if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle))) + if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle))) return -1; if (jiffies - last_time > 5*HZ) @@ -312,7 +312,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; siginfo.si_code = __SI_FAULT; /* default code */ - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); if (isr & 0x11) { siginfo.si_code = FPE_FLTINV; } else if (isr & 0x22) { @@ -336,7 +336,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; siginfo.si_code = __SI_FAULT; /* default code */ - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); if (isr & 0x880) { siginfo.si_code = FPE_FLTOVF; } else if (isr & 0x1100) { @@ -383,7 +383,7 @@ ia64_illegal_op_fault (unsigned long ec, unsigned long arg1, unsigned long arg2, memset(&si, 0, sizeof(si)); si.si_signo = SIGILL; si.si_code = ILL_ILLOPC; - si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + si.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); force_sig_info(SIGILL, &si, current); rv.fkt = 0; return rv; @@ -445,18 +445,18 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 26: /* NaT Consumption */ if (user_mode(regs)) { - void *addr; + void __user *addr; if (((isr >> 4) & 0xf) == 2) { /* NaT page consumption */ sig = SIGSEGV; code = SEGV_ACCERR; - addr = (void *) ifa; + addr = (void __user *) ifa; } else { /* register NaT consumption */ sig = SIGILL; code = ILL_ILLOPN; - addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); } siginfo.si_signo = sig; siginfo.si_code = code; @@ -477,7 +477,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, siginfo.si_signo = SIGILL; siginfo.si_code = ILL_ILLOPN; siginfo.si_errno = 0; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_imm = vector; siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; @@ -524,7 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, } siginfo.si_signo = SIGTRAP; siginfo.si_errno = 0; - siginfo.si_addr = (void *) ifa; + siginfo.si_addr = (void __user *) ifa; siginfo.si_imm = 0; siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; @@ -538,7 +538,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; siginfo.si_code = FPE_FLTINV; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; siginfo.si_imm = 0; @@ -565,7 +565,8 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, siginfo.si_flags = 0; siginfo.si_isr = 0; siginfo.si_imm = 0; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = (void __user *) + (regs->cr_iip + ia64_psr(regs)->ri); force_sig_info(SIGILL, &siginfo, current); return; } diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index b1a68e436..46dad0d21 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -760,7 +760,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) return -1; } /* this assumes little-endian byte-order: */ - if (copy_from_user(&val, (void *) ifa, len)) + if (copy_from_user(&val, (void __user *) ifa, len)) return -1; setreg(ld.r1, val, 0, regs); @@ -869,7 +869,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) * * extract the value to be stored */ - getreg(ld.imm, &r2, 0, regs); + getreg(ld.imm, &r2, NULL, regs); /* * we rely on the macros in unaligned.h for now i.e., @@ -887,7 +887,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) } /* this assumes little-endian byte-order: */ - if (copy_to_user((void *) ifa, &r2, len)) + if (copy_to_user((void __user *) ifa, &r2, len)) return -1; /* @@ -1036,8 +1036,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs * This assumes little-endian byte-order. Note that there is no "ldfpe" * instruction: */ - if (copy_from_user(&fpr_init[0], (void *) ifa, len) - || copy_from_user(&fpr_init[1], (void *) (ifa + len), len)) + if (copy_from_user(&fpr_init[0], (void __user *) ifa, len) + || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len)) return -1; DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz); @@ -1138,7 +1138,7 @@ emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) * See comments in ldX for descriptions on how the various loads are handled. */ if (ld.x6_op != 0x2) { - if (copy_from_user(&fpr_init, (void *) ifa, len)) + if (copy_from_user(&fpr_init, (void __user *) ifa, len)) return -1; DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); @@ -1230,7 +1230,7 @@ emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) DDUMP("fpr_init =", &fpr_init, len); DDUMP("fpr_final =", &fpr_final, len); - if (copy_to_user((void *) ifa, &fpr_final, len)) + if (copy_to_user((void __user *) ifa, &fpr_final, len)) return -1; /* @@ -1351,7 +1351,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n", regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it); - if (__copy_from_user(bundle, (void *) regs->cr_iip, 16)) + if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16)) goto failure; /* @@ -1496,7 +1496,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) si.si_signo = SIGBUS; si.si_errno = 0; si.si_code = BUS_ADRALN; - si.si_addr = (void *) ifa; + si.si_addr = (void __user *) ifa; si.si_flags = 0; si.si_isr = 0; si.si_imm = 0; diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index 769d880df..050ae0554 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -47,7 +47,6 @@ #include "entry.h" #include "unwind_i.h" -#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define p5 5 #define UNW_LOG_CACHE_SIZE 7 /* each unw_script is ~256 bytes in size */ @@ -447,7 +446,7 @@ EXPORT_SYMBOL(unw_access_br); int unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write) { - struct ia64_fpreg *addr = 0; + struct ia64_fpreg *addr = NULL; struct pt_regs *pt; if ((unsigned) (regnum - 2) >= 126) { @@ -843,7 +842,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave } sr->gr_save_loc = grsave; sr->any_spills = 0; - sr->imask = 0; + sr->imask = NULL; sr->spill_offset = 0x10; /* default to psp+16 */ } } @@ -963,13 +962,13 @@ static inline void desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr) { set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE, - sr->region_start + MIN((int)t, sr->region_len - 1), 16*size); + sr->region_start + min_t(int, t, sr->region_len - 1), 16*size); } static inline void desc_mem_stack_v (unw_word t, struct unw_state_record *sr) { - sr->curr.reg[UNW_REG_PSP].when = sr->region_start + MIN((int)t, sr->region_len - 1); + sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1); } static inline void @@ -1005,7 +1004,7 @@ desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr) if (reg->where == UNW_WHERE_NONE) reg->where = UNW_WHERE_GR_SAVE; - reg->when = sr->region_start + MIN((int)t, sr->region_len - 1); + reg->when = sr->region_start + min_t(int, t, sr->region_len - 1); } static inline void @@ -1073,7 +1072,7 @@ desc_label_state (unw_word label, struct unw_state_record *sr) static inline int desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr) { - if (sr->when_target <= sr->region_start + MIN((int)t, sr->region_len - 1)) + if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1)) return 0; if (qp > 0) { if ((sr->pr_val & (1UL << qp)) == 0) @@ -1114,7 +1113,7 @@ desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned ch r = sr->curr.reg + decode_abreg(abreg, 0); r->where = where; - r->when = sr->region_start + MIN((int)t, sr->region_len - 1); + r->when = sr->region_start + min_t(int, t, sr->region_len - 1); r->val = (ytreg & 0x7f); } @@ -1129,7 +1128,7 @@ desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word r = sr->curr.reg + decode_abreg(abreg, 1); r->where = UNW_WHERE_PSPREL; - r->when = sr->region_start + MIN((int)t, sr->region_len - 1); + r->when = sr->region_start + min_t(int, t, sr->region_len - 1); r->val = 0x10 - 4*pspoff; } @@ -1144,7 +1143,7 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word r = sr->curr.reg + decode_abreg(abreg, 1); r->where = UNW_WHERE_SPREL; - r->when = sr->region_start + MIN((int)t, sr->region_len - 1); + r->when = sr->region_start + min_t(int, t, sr->region_len - 1); r->val = 4*spoff; } @@ -1206,7 +1205,7 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word static inline unw_hash_index_t hash (unsigned long ip) { -# define hashmagic 0x9e3779b97f4a7c16 /* based on (sqrt(5)/2-1)*2^64 */ +# define hashmagic 0x9e3779b97f4a7c16UL /* based on (sqrt(5)/2-1)*2^64 */ return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE); #undef hashmagic @@ -1231,7 +1230,7 @@ script_lookup (struct unw_frame_info *info) unsigned long ip, pr; if (UNW_DEBUG_ON(0)) - return 0; /* Always regenerate scripts in debug mode */ + return NULL; /* Always regenerate scripts in debug mode */ STAT(++unw.stat.cache.lookups); @@ -1245,7 +1244,7 @@ script_lookup (struct unw_frame_info *info) index = unw.hash[hash(ip)]; if (index >= UNW_CACHE_SIZE) - return 0; + return NULL; script = unw.cache + index; while (1) { @@ -1256,7 +1255,7 @@ script_lookup (struct unw_frame_info *info) return script; } if (script->coll_chain >= UNW_HASH_SIZE) - return 0; + return NULL; script = unw.cache + script->coll_chain; STAT(++unw.stat.cache.collision_chain_traversals); } @@ -1270,7 +1269,6 @@ script_new (unsigned long ip) { struct unw_script *script, *prev, *tmp; unw_hash_index_t index; - unsigned long flags; unsigned short head; STAT(++unw.stat.script.news); @@ -1279,13 +1277,9 @@ script_new (unsigned long ip) * Can't (easily) use cmpxchg() here because of ABA problem * that is intrinsic in cmpxchg()... */ - spin_lock_irqsave(&unw.lock, flags); - { - head = unw.lru_head; - script = unw.cache + head; - unw.lru_head = script->lru_chain; - } - spin_unlock(&unw.lock); + head = unw.lru_head; + script = unw.cache + head; + unw.lru_head = script->lru_chain; /* * We'd deadlock here if we interrupted a thread that is holding a read lock on @@ -1296,43 +1290,39 @@ script_new (unsigned long ip) if (!write_trylock(&script->lock)) return NULL; - spin_lock(&unw.lock); - { - /* re-insert script at the tail of the LRU chain: */ - unw.cache[unw.lru_tail].lru_chain = head; - unw.lru_tail = head; - - /* remove the old script from the hash table (if it's there): */ - if (script->ip) { - index = hash(script->ip); - tmp = unw.cache + unw.hash[index]; - prev = 0; - while (1) { - if (tmp == script) { - if (prev) - prev->coll_chain = tmp->coll_chain; - else - unw.hash[index] = tmp->coll_chain; - break; - } else - prev = tmp; - if (tmp->coll_chain >= UNW_CACHE_SIZE) - /* old script wasn't in the hash-table */ - break; - tmp = unw.cache + tmp->coll_chain; - } + /* re-insert script at the tail of the LRU chain: */ + unw.cache[unw.lru_tail].lru_chain = head; + unw.lru_tail = head; + + /* remove the old script from the hash table (if it's there): */ + if (script->ip) { + index = hash(script->ip); + tmp = unw.cache + unw.hash[index]; + prev = NULL; + while (1) { + if (tmp == script) { + if (prev) + prev->coll_chain = tmp->coll_chain; + else + unw.hash[index] = tmp->coll_chain; + break; + } else + prev = tmp; + if (tmp->coll_chain >= UNW_CACHE_SIZE) + /* old script wasn't in the hash-table */ + break; + tmp = unw.cache + tmp->coll_chain; } + } - /* enter new script in the hash table */ - index = hash(ip); - script->coll_chain = unw.hash[index]; - unw.hash[index] = script - unw.cache; + /* enter new script in the hash table */ + index = hash(ip); + script->coll_chain = unw.hash[index]; + unw.hash[index] = script - unw.cache; - script->ip = ip; /* set new IP while we're holding the locks */ + script->ip = ip; /* set new IP while we're holding the locks */ - STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions); - } - spin_unlock_irqrestore(&unw.lock, flags); + STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions); script->flags = 0; script->hint = 0; @@ -1511,7 +1501,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script) static inline const struct unw_table_entry * lookup (struct unw_table *table, unsigned long rel_ip) { - const struct unw_table_entry *e = 0; + const struct unw_table_entry *e = NULL; unsigned long lo, hi, mid; /* do a binary search for right entry: */ @@ -1537,8 +1527,8 @@ lookup (struct unw_table *table, unsigned long rel_ip) static inline struct unw_script * build_script (struct unw_frame_info *info) { - const struct unw_table_entry *e = 0; - struct unw_script *script = 0; + const struct unw_table_entry *e = NULL; + struct unw_script *script = NULL; struct unw_labeled_state *ls, *next; unsigned long ip = info->ip; struct unw_state_record sr; @@ -1563,7 +1553,7 @@ build_script (struct unw_frame_info *info) if (!script) { UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__); STAT(unw.stat.script.build_time += ia64_get_itc() - start); - return 0; + return NULL; } unw.cache[info->prev_script].hint = script - unw.cache; @@ -1831,19 +1821,22 @@ find_save_locs (struct unw_frame_info *info) { int have_write_lock = 0; struct unw_script *scr; + unsigned long flags = 0; if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { /* don't let obviously bad addresses pollute the cache */ /* FIXME: should really be level 0 but it occurs too often. KAO */ UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip); - info->rp_loc = 0; + info->rp_loc = NULL; return -1; } scr = script_lookup(info); if (!scr) { + spin_lock_irqsave(&unw.lock, flags); scr = build_script(info); if (!scr) { + spin_unlock_irqrestore(&unw.lock, flags); UNW_DPRINT(0, "unwind.%s: failed to locate/build unwind script for ip %lx\n", __FUNCTION__, info->ip); @@ -1856,9 +1849,10 @@ find_save_locs (struct unw_frame_info *info) run_script(scr, info); - if (have_write_lock) + if (have_write_lock) { write_unlock(&scr->lock); - else + spin_unlock_irqrestore(&unw.lock, flags); + } else read_unlock(&scr->lock); return 0; } @@ -2093,12 +2087,12 @@ unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned lon if (end - start <= 0) { UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n", __FUNCTION__); - return 0; + return NULL; } table = kmalloc(sizeof(*table), GFP_USER); if (!table) - return 0; + return NULL; init_unwind_table(table, name, segment_base, gp, table_start, table_end); @@ -2300,7 +2294,7 @@ unw_init (void) * EFAULT BUF points outside your accessible address space. */ asmlinkage long -sys_getunwind (void *buf, size_t buf_size) +sys_getunwind (void __user *buf, size_t buf_size) { if (buf && buf_size >= unw.gate_table_size) if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0) diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 57912212b..b9f0db4c1 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -42,6 +42,7 @@ SECTIONS *(.text.ivt) *(.text) SCHED_TEXT + LOCK_TEXT *(.gnu.linkonce.t*) } .text2 : AT(ADDR(.text2) - LOAD_OFFSET) @@ -135,12 +136,6 @@ SECTIONS *(.init.setup) __setup_end = .; } - __param : AT(ADDR(__param) - LOAD_OFFSET) - { - __start___param = .; - *(__param) - __stop___param = .; - } .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { __initcall_start = .; diff --git a/arch/ia64/lib/bitop.c b/arch/ia64/lib/bitop.c index 1c6ee49fd..d509e204c 100644 --- a/arch/ia64/lib/bitop.c +++ b/arch/ia64/lib/bitop.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include /* * Find next zero bit in a bitmap reasonably efficiently.. diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c index 269dcc2cb..ca7ba1e9c 100644 --- a/arch/ia64/lib/csum_partial_copy.c +++ b/arch/ia64/lib/csum_partial_copy.c @@ -1,7 +1,7 @@ /* * Network Checksum & Copy routine * - * Copyright (C) 1999, 2003 Hewlett-Packard Co + * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co * Stephane Eranian * * Most of the code has been imported from Linux/Alpha @@ -105,7 +105,7 @@ out: extern unsigned long do_csum(const unsigned char *, long); static unsigned int -do_csum_partial_copy_from_user (const char *src, char *dst, int len, +do_csum_partial_copy_from_user (const char __user *src, char *dst, int len, unsigned int psum, int *errp) { unsigned long result; @@ -129,10 +129,10 @@ do_csum_partial_copy_from_user (const char *src, char *dst, int len, } unsigned int -csum_partial_copy_from_user(const char *src, char *dst, int len, - unsigned int sum, int *errp) +csum_partial_copy_from_user (const char __user *src, char *dst, int len, + unsigned int sum, int *errp) { - if (!access_ok(src, len, VERIFY_READ)) { + if (!access_ok(VERIFY_READ, src, len)) { *errp = -EFAULT; memset(dst, 0, len); return sum; @@ -142,7 +142,7 @@ csum_partial_copy_from_user(const char *src, char *dst, int len, } unsigned int -csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum) +csum_partial_copy_nocheck(const char __user *src, char *dst, int len, unsigned int sum) { return do_csum_partial_copy_from_user(src, dst, len, sum, NULL); } diff --git a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c index 46bdc0490..c7ce92f96 100644 --- a/arch/ia64/lib/dec_and_lock.c +++ b/arch/ia64/lib/dec_and_lock.c @@ -19,7 +19,7 @@ * acquiring the spinlock first. */ int -atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) +_atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) { int old, new; @@ -39,4 +39,4 @@ atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) return 0; } -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c index 90f0f3061..5b48cc5f3 100644 --- a/arch/ia64/lib/io.c +++ b/arch/ia64/lib/io.c @@ -9,7 +9,7 @@ * This needs to be optimized. */ void -__ia64_memcpy_fromio (void *to, unsigned long from, long count) +__ia64_memcpy_fromio (void *to, volatile void __iomem *from, long count) { char *dst = to; @@ -25,7 +25,7 @@ EXPORT_SYMBOL(__ia64_memcpy_fromio); * This needs to be optimized. */ void -__ia64_memcpy_toio (unsigned long to, void *from, long count) +__ia64_memcpy_toio (volatile void __iomem *to, void *from, long count) { char *src = from; @@ -41,7 +41,7 @@ EXPORT_SYMBOL(__ia64_memcpy_toio); * This needs to be optimized. */ void -__ia64_memset_c_io (unsigned long dst, unsigned long c, long count) +__ia64_memset_c_io (volatile void __iomem *dst, unsigned long c, long count) { unsigned char ch = (char)(c & 0xff); @@ -73,6 +73,7 @@ EXPORT_SYMBOL(__ia64_memset_c_io); #undef __ia64_writew #undef __ia64_writel #undef __ia64_writeq +#undef __ia64_mmiowb unsigned int __ia64_inb (unsigned long port) @@ -111,51 +112,57 @@ __ia64_outl (unsigned int val, unsigned long port) } unsigned char -__ia64_readb (void *addr) +__ia64_readb (void __iomem *addr) { return ___ia64_readb (addr); } unsigned short -__ia64_readw (void *addr) +__ia64_readw (void __iomem *addr) { return ___ia64_readw (addr); } unsigned int -__ia64_readl (void *addr) +__ia64_readl (void __iomem *addr) { return ___ia64_readl (addr); } unsigned long -__ia64_readq (void *addr) +__ia64_readq (void __iomem *addr) { return ___ia64_readq (addr); } unsigned char -__ia64_readb_relaxed (void *addr) +__ia64_readb_relaxed (void __iomem *addr) { return ___ia64_readb (addr); } unsigned short -__ia64_readw_relaxed (void *addr) +__ia64_readw_relaxed (void __iomem *addr) { return ___ia64_readw (addr); } unsigned int -__ia64_readl_relaxed (void *addr) +__ia64_readl_relaxed (void __iomem *addr) { return ___ia64_readl (addr); } unsigned long -__ia64_readq_relaxed (void *addr) +__ia64_readq_relaxed (void __iomem *addr) { return ___ia64_readq (addr); } +void +__ia64_mmiowb(void) +{ + ___ia64_mmiowb(); +} + #endif /* CONFIG_IA64_GENERIC */ diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c index 781e23e66..b7467a989 100644 --- a/arch/ia64/lib/swiotlb.c +++ b/arch/ia64/lib/swiotlb.c @@ -11,6 +11,7 @@ * 03/05/07 davidm Switch from PCI-DMA to generic device DMA API. * 00/12/13 davidm Rename to swiotlb.c and add mark_clean() to avoid * unnecessary i-cache flushing. + * 04/07/.. ak Better overflow handling. Assorted fixes. */ #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include @@ -46,6 +48,8 @@ */ #define IO_TLB_SHIFT 11 +int swiotlb_force; + /* * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single_*, to see * if the memory was in fact allocated by this API. @@ -55,8 +59,16 @@ static char *io_tlb_start, *io_tlb_end; /* * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end. * This is command line adjustable via setup_io_tlb_npages. + * Default to 64MB. + */ +static unsigned long io_tlb_nslabs = 32768; + +/* + * When the IOMMU overflows we return a fallback buffer. This sets the size. */ -static unsigned long io_tlb_nslabs = 1024; +static unsigned long io_tlb_overflow = 32*1024; + +void *io_tlb_overflow_buffer; /* * This is a free list describing the number of free entries available from each index @@ -78,15 +90,19 @@ static spinlock_t io_tlb_lock = SPIN_LOCK_UNLOCKED; static int __init setup_io_tlb_npages (char *str) { - io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT); - - /* avoid tail segment of size < IO_TLB_SEGSIZE */ - io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); - + if (isdigit(*str)) { + io_tlb_nslabs = simple_strtoul(str, &str, 0) << (PAGE_SHIFT - IO_TLB_SHIFT); + /* avoid tail segment of size < IO_TLB_SEGSIZE */ + io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); + } + if (*str == ',') + ++str; + if (!strcmp(str, "force")) + swiotlb_force = 1; return 1; } __setup("swiotlb=", setup_io_tlb_npages); - +/* make io_tlb_overflow tunable too? */ /* * Statically reserve bounce buffer space and initialize bounce buffer data structures for @@ -102,7 +118,7 @@ swiotlb_init (void) */ io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); if (!io_tlb_start) - BUG(); + panic("Cannot allocate SWIOTLB buffer"); io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); /* @@ -115,11 +131,23 @@ swiotlb_init (void) io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); io_tlb_index = 0; io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); - - printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n", - (void *) io_tlb_start, (void *) io_tlb_end); + + /* + * Get the overflow emergency buffer + */ + io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); + printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", + virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end)); } +static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr) +{ + dma_addr_t mask = 0xffffffff; + if (hwdev && hwdev->dma_mask) + mask = *hwdev->dma_mask; + return (addr & ~mask) != 0; +} + /* * Allocates bounce buffer and returns its kernel virtual address. */ @@ -184,11 +212,8 @@ map_single (struct device *hwdev, char *buffer, size_t size, int dir) index = 0; } while (index != wrap); - /* - * XXX What is a suitable recovery mechanism here? We cannot - * sleep because we are called from with in interrupts! - */ - panic("map_single: could not allocate software IO TLB (%ld bytes)", size); + spin_unlock_irqrestore(&io_tlb_lock, flags); + return NULL; } found: spin_unlock_irqrestore(&io_tlb_lock, flags); @@ -280,12 +305,19 @@ swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handl flags |= GFP_DMA; ret = (void *)__get_free_pages(flags, get_order(size)); - if (!ret) - return NULL; + if (!ret) { + /* DMA_FROM_DEVICE is to avoid the memcpy in map_single */ + dma_addr_t handle; + handle = swiotlb_map_single(NULL, NULL, size, DMA_FROM_DEVICE); + if (dma_mapping_error(handle)) + return NULL; + + ret = phys_to_virt(handle); + } memset(ret, 0, size); dev_addr = virt_to_phys(ret); - if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + if (address_needs_mapping(hwdev,dev_addr)) panic("swiotlb_alloc_consistent: allocated memory is out of range for device"); *dma_handle = dev_addr; return ret; @@ -294,9 +326,36 @@ swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handl void swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - free_pages((unsigned long) vaddr, get_order(size)); + if (!(vaddr >= (void *)io_tlb_start + && vaddr < (void *)io_tlb_end)) + free_pages((unsigned long) vaddr, get_order(size)); + else + /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ + swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); } +static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) +{ + /* + * Ran out of IOMMU space for this operation. This is very bad. + * Unfortunately the drivers cannot handle this operation properly. + * unless they check for pci_dma_mapping_error (most don't) + * When the mapping is small enough return a static buffer to limit + * the damage, or panic when the transfer is too big. + */ + + printk(KERN_ERR + "PCI-DMA: Out of SW-IOMMU space for %lu bytes at device %s\n", + size, dev ? dev->bus_id : "?"); + + if (size > io_tlb_overflow && do_panic) { + if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) + panic("PCI-DMA: Memory would be corrupted\n"); + if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) + panic("PCI-DMA: Random memory would be DMAed\n"); + } +} + /* * Map a single buffer of the indicated size for DMA in streaming mode. The PCI address * to use is returned. @@ -308,13 +367,14 @@ dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir) { unsigned long dev_addr = virt_to_phys(ptr); + void *map; if (dir == DMA_NONE) BUG(); /* * Check if the PCI device can DMA to ptr... if so, just return ptr */ - if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0) + if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) /* * Device is bit capable of DMA'ing to the buffer... just return the PCI * address of ptr @@ -324,12 +384,18 @@ swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir) /* * get a bounce buffer: */ - dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir)); + map = map_single(hwdev, ptr, size, dir); + if (!map) { + swiotlb_full(hwdev, size, dir, 1); + map = io_tlb_overflow_buffer; + } + + dev_addr = virt_to_phys(map); /* * Ensure that the address returned is DMA'ble: */ - if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + if (address_needs_mapping(hwdev, dev_addr)) panic("map_single: bounce buffer is not DMA'ble"); return dev_addr; @@ -437,9 +503,17 @@ swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int di for (i = 0; i < nelems; i++, sg++) { addr = SG_ENT_VIRT_ADDRESS(sg); dev_addr = virt_to_phys(addr); - if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) - sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir); - else + if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) { + sg->dma_address = (dma_addr_t) virt_to_phys(map_single(hwdev, addr, sg->length, dir)); + if (!sg->dma_address) { + /* Don't panic here, we expect pci_map_sg users + to do proper error handling. */ + swiotlb_full(hwdev, sg->length, dir, 0); + swiotlb_unmap_sg(hwdev, sg - i, i, dir); + sg[0].dma_length = 0; + return 0; + } + } else sg->dma_address = dev_addr; sg->dma_length = sg->length; } @@ -460,7 +534,7 @@ swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir); + unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir); else if (dir == DMA_FROM_DEVICE) mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); } @@ -501,7 +575,7 @@ swiotlb_sync_sg_for_device (struct device *hwdev, struct scatterlist *sg, int ne int swiotlb_dma_mapping_error (dma_addr_t dma_addr) { - return 0; + return (dma_addr == virt_to_phys(io_tlb_overflow_buffer)); } /* diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index c0f8f4a3e..0f905a637 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -116,19 +116,19 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg) range_start = max(start, free_start); range_end = min(end, rsvd_region[i].start & PAGE_MASK); + free_start = PAGE_ALIGN(rsvd_region[i].end); + if (range_end <= range_start) continue; /* skip over empty range */ - if (range_end - range_start >= needed) { + if (range_end - range_start >= needed) { bootmap_start = __pa(range_start); - return 1; /* done */ + return -1; /* done */ } /* nothing more available in this segment */ if (range_end == end) return 0; - - free_start = PAGE_ALIGN(rsvd_region[i].end); } return 0; } @@ -267,9 +267,8 @@ paging_init (void) efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); if (max_gap < LARGE_GAP) { vmem_map = (struct page *) 0; - free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, + free_area_init_node(0, &contig_page_data, zones_size, 0, zholes_size); - mem_map = contig_page_data.node_mem_map; } else { unsigned long map_size; @@ -278,12 +277,12 @@ paging_init (void) map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); vmalloc_end -= map_size; vmem_map = (struct page *) vmalloc_end; - efi_memmap_walk(create_mem_map_page_table, 0); + efi_memmap_walk(create_mem_map_page_table, NULL); - free_area_init_node(0, &contig_page_data, vmem_map, zones_size, + mem_map = contig_page_data.node_mem_map = vmem_map; + free_area_init_node(0, &contig_page_data, zones_size, 0, zholes_size); - mem_map = contig_page_data.node_mem_map; printk("Virtual mem_map starts at 0x%p\n", mem_map); } #else /* !CONFIG_VIRTUAL_MEM_MAP */ diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 23a9490fc..343a86092 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -53,11 +54,12 @@ static struct early_node_data mem_data[NR_NODES] __initdata; static void __init reassign_cpu_only_nodes(void) { struct node_memblk_s *p; - int i, j, k, nnode, nid, cpu, cpunid; + int i, j, k, nnode, nid, cpu, cpunid, pxm; u8 cslit, slit; static DECLARE_BITMAP(nodes_with_mem, NR_NODES) __initdata; static u8 numa_slit_fix[MAX_NUMNODES * MAX_NUMNODES] __initdata; static int node_flip[NR_NODES] __initdata; + static int old_nid_map[NR_CPUS] __initdata; for (nnode = 0, p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++) if (!test_bit(p->nid, (void *) nodes_with_mem)) { @@ -104,9 +106,14 @@ static void __init reassign_cpu_only_nodes(void) for (cpu = 0; cpu < NR_CPUS; cpu++) if (node_cpuid[cpu].nid == i) { - /* For nodes not being reassigned just fix the cpu's nid. */ + /* + * For nodes not being reassigned just + * fix the cpu's nid and reverse pxm map + */ if (cpunid < numnodes) { - node_cpuid[cpu].nid = cpunid; + pxm = nid_to_pxm_map[i]; + pxm_to_nid_map[pxm] = + node_cpuid[cpu].nid = cpunid; continue; } @@ -126,6 +133,8 @@ static void __init reassign_cpu_only_nodes(void) } } + /* save old nid map so we can update the pxm */ + old_nid_map[cpu] = node_cpuid[cpu].nid; node_cpuid[cpu].nid = k; } } @@ -134,14 +143,19 @@ static void __init reassign_cpu_only_nodes(void) * Fixup temporary nid values for CPU-only nodes. */ for (cpu = 0; cpu < NR_CPUS; cpu++) - if (node_cpuid[cpu].nid == (numnodes + numnodes)) - node_cpuid[cpu].nid = nnode - 1; - else - for (i = 0; i < nnode; i++) - if (node_flip[i] == (node_cpuid[cpu].nid - numnodes)) { - node_cpuid[cpu].nid = i; - break; - } + if (node_cpuid[cpu].nid == (numnodes + numnodes)) { + pxm = nid_to_pxm_map[old_nid_map[cpu]]; + pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = nnode - 1; + } else { + for (i = 0; i < nnode; i++) { + if (node_flip[i] != (node_cpuid[cpu].nid - numnodes)) + continue; + + pxm = nid_to_pxm_map[old_nid_map[cpu]]; + pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = i; + break; + } + } /* * Fix numa_slit by compressing from larger @@ -492,14 +506,17 @@ void *per_cpu_init(void) */ void show_mem(void) { - int i, reserved = 0; - int shared = 0, cached = 0; + int i, total_reserved = 0; + int total_shared = 0, total_cached = 0; + unsigned long total_present = 0; pg_data_t *pgdat; printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); for_each_pgdat(pgdat) { + unsigned long present = pgdat->node_present_pages; + int shared = 0, cached = 0, reserved = 0; printk("Node ID: %d\n", pgdat->node_id); for(i = 0; i < pgdat->node_spanned_pages; i++) { if (!ia64_pfn_valid(pgdat->node_start_pfn+i)) @@ -511,11 +528,19 @@ void show_mem(void) else if (page_count(pgdat->node_mem_map+i)) shared += page_count(pgdat->node_mem_map+i)-1; } - printk("\t%ld pages of RAM\n", pgdat->node_present_pages); + total_present += present; + total_reserved += reserved; + total_cached += cached; + total_shared += shared; + printk("\t%ld pages of RAM\n", present); printk("\t%d reserved pages\n", reserved); printk("\t%d pages shared\n", shared); printk("\t%d pages swap cached\n", cached); } + printk("%ld pages of RAM\n", total_present); + printk("%d reserved pages\n", total_reserved); + printk("%d pages shared\n", total_shared); + printk("%d pages swap cached\n", total_cached); printk("Total of %ld pages in page table cache\n", pgtable_cache_size); printk("%d free buffer pages\n", nr_free_buffer_pages()); } @@ -577,7 +602,7 @@ void call_pernode_memory(unsigned long start, unsigned long len, void *arg) * for each piece of usable memory and will setup these values for each node. * Very similar to build_maps(). */ -static int count_node_pages(unsigned long start, unsigned long len, int node) +static __init int count_node_pages(unsigned long start, unsigned long len, int node) { unsigned long end = start + len; @@ -602,17 +627,15 @@ static int count_node_pages(unsigned long start, unsigned long len, int node) * paging_init() sets up the page tables for each node of the system and frees * the bootmem allocator memory for general use. */ -void paging_init(void) +void __init paging_init(void) { unsigned long max_dma; unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; - unsigned long max_gap, pfn_offset = 0; + unsigned long pfn_offset = 0; int node; max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; - max_gap = 0; - efi_memmap_walk(find_largest_hole, &max_gap); /* so min() will work in count_node_pages */ for (node = 0; node < numnodes; node++) @@ -658,14 +681,14 @@ void paging_init(void) PAGE_ALIGN(max_low_pfn * sizeof(struct page)); vmem_map = (struct page *) vmalloc_end; - efi_memmap_walk(create_mem_map_page_table, 0); + efi_memmap_walk(create_mem_map_page_table, NULL); printk("Virtual mem_map starts at 0x%p\n", vmem_map); } pfn_offset = mem_data[node].min_pfn; - free_area_init_node(node, NODE_DATA(node), - vmem_map + pfn_offset, zones_size, + NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset; + free_area_init_node(node, NODE_DATA(node), zones_size, pfn_offset, zholes_size); } diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 2353cc795..99edfed31 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c @@ -77,7 +77,7 @@ search_extable (const struct exception_table_entry *first, else last = mid - 1; } - return 0; + return NULL; } void diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index d823ff897..9e4b5c2df 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -14,7 +14,6 @@ #include #include #include -#include extern void die (char *, struct pt_regs *, long); @@ -33,13 +32,14 @@ expand_backing_store (struct vm_area_struct *vma, unsigned long address) unsigned long grow; grow = PAGE_SIZE >> PAGE_SHIFT; - if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur - || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)) + if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur + || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->signal->rlim[RLIMIT_AS].rlim_cur)) return -ENOMEM; vma->vm_end += PAGE_SIZE; vma->vm_mm->total_vm += grow; if (vma->vm_flags & VM_LOCKED) vma->vm_mm->locked_vm += grow; + __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow); return 0; } @@ -196,7 +196,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re si.si_signo = signal; si.si_errno = 0; si.si_code = code; - si.si_addr = (void *) address; + si.si_addr = (void __user *) address; si.si_isr = isr; si.si_flags = __ISR_VALID; force_sig_info(signal, &si, current); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 3ab0b37e0..a28351534 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -67,9 +67,9 @@ check_pgt_cache (void) if (pgtable_cache_size > (u64) high) { do { if (pgd_quicklist) - free_page((unsigned long)pgd_alloc_one_fast(0)); + free_page((unsigned long)pgd_alloc_one_fast(NULL)); if (pmd_quicklist) - free_page((unsigned long)pmd_alloc_one_fast(0, 0)); + free_page((unsigned long)pmd_alloc_one_fast(NULL, 0)); } while (pgtable_cache_size > (u64) low); } preempt_enable(); @@ -98,7 +98,7 @@ update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, pte_t pte) inline void ia64_set_rbs_bot (void) { - unsigned long stack_size = current->rlim[RLIMIT_STACK].rlim_max & -16; + unsigned long stack_size = current->signal->rlim[RLIMIT_STACK].rlim_max & -16; if (stack_size > MAX_USER_STACK_SIZE) stack_size = MAX_USER_STACK_SIZE; @@ -131,7 +131,13 @@ ia64_init_addr_space (void) vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7]; vma->vm_flags = VM_DATA_DEFAULT_FLAGS | VM_GROWSUP; - insert_vm_struct(current->mm, vma); + down_write(¤t->mm->mmap_sem); + if (insert_vm_struct(current->mm, vma)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return; + } + up_write(¤t->mm->mmap_sem); } /* map NaT-page at address zero to speed up speculative dereferencing of NULL: */ @@ -143,7 +149,13 @@ ia64_init_addr_space (void) vma->vm_end = PAGE_SIZE; vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT); vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED; - insert_vm_struct(current->mm, vma); + down_write(¤t->mm->mmap_sem); + if (insert_vm_struct(current->mm, vma)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return; + } + up_write(¤t->mm->mmap_sem); } } } @@ -429,20 +441,22 @@ virtual_memmap_init (u64 start, u64 end, void *arg) / sizeof(struct page)); if (map_start < map_end) - memmap_init_zone(map_start, (unsigned long) (map_end - map_start), + memmap_init_zone((unsigned long)(map_end - map_start), args->nid, args->zone, page_to_pfn(map_start)); return 0; } void -memmap_init (struct page *start, unsigned long size, int nid, - unsigned long zone, unsigned long start_pfn) +memmap_init (unsigned long size, int nid, unsigned long zone, + unsigned long start_pfn) { if (!vmem_map) - memmap_init_zone(start, size, nid, zone, start_pfn); + memmap_init_zone(size, nid, zone, start_pfn); else { + struct page *start; struct memmap_init_callback_data args; + start = pfn_to_page(start_pfn); args.start = start; args.end = start + size; args.nid = nid; @@ -458,9 +472,9 @@ ia64_pfn_valid (unsigned long pfn) char byte; struct page *pg = pfn_to_page(pfn); - return (__get_user(byte, (char *) pg) == 0) + return (__get_user(byte, (char __user *) pg) == 0) && ((((u64)pg & PAGE_MASK) == (((u64)(pg + 1) - 1) & PAGE_MASK)) - || (__get_user(byte, (char *) (pg + 1) - 1) == 0)); + || (__get_user(byte, (char __user *) (pg + 1) - 1) == 0)); } EXPORT_SYMBOL(ia64_pfn_valid); @@ -585,6 +599,6 @@ mem_init (void) setup_gate(); #ifdef CONFIG_IA32_SUPPORT - ia32_boot_gdt_init(); + ia32_mem_init(); #endif } diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c index ef2dbcfda..9e5eee13a 100644 --- a/arch/ia64/mm/numa.c +++ b/arch/ia64/mm/numa.c @@ -70,7 +70,7 @@ static int __init topology_init(void) memset(sysfs_cpus, 0, sizeof(struct cpu) * NR_CPUS); for (i = 0; i < numnodes; i++) - if ((err = register_node(&sysfs_nodes[i], i, 0))) + if ((err = register_node(&sysfs_nodes[i], i, NULL))) goto out; for (i = 0; i < NR_CPUS; i++) diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index dc15aa01c..0c5cb3c61 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -176,7 +176,7 @@ ia64_tlb_init (void) if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) { printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;" "defaulting to architected purge page-sizes.\n", status); - purge.mask = 0x115557000; + purge.mask = 0x115557000UL; } purge.max_bits = ia64_fls(purge.mask); diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig index bfac82f3e..56e6f614b 100644 --- a/arch/ia64/oprofile/Kconfig +++ b/arch/ia64/oprofile/Kconfig @@ -16,6 +16,10 @@ config OPROFILE whole system, include the kernel, kernel modules, libraries, and applications. + Due to firmware bugs, you may need to use the "nohalt" boot + option if you're using OProfile with the hardware performance + counters. + If unsure, say N. endmenu diff --git a/arch/ia64/oprofile/Makefile b/arch/ia64/oprofile/Makefile index 06e7c81ea..29aeef4f6 100644 --- a/arch/ia64/oprofile/Makefile +++ b/arch/ia64/oprofile/Makefile @@ -7,3 +7,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) oprofile-y := $(DRIVER_OBJS) init.o +oprofile-$(CONFIG_PERFMON) += perfmon.o diff --git a/arch/ia64/oprofile/init.c b/arch/ia64/oprofile/init.c index 558561d6d..6d0c132b0 100644 --- a/arch/ia64/oprofile/init.c +++ b/arch/ia64/oprofile/init.c @@ -12,14 +12,21 @@ #include #include -extern void timer_init(struct oprofile_operations ** ops); +extern int perfmon_init(struct oprofile_operations ** ops); +extern void perfmon_exit(void); int __init oprofile_arch_init(struct oprofile_operations ** ops) { +#ifdef CONFIG_PERFMON + return perfmon_init(ops); +#endif return -ENODEV; } void oprofile_arch_exit(void) { +#ifdef CONFIG_PERFMON + perfmon_exit(); +#endif } diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 82204f1bd..d64c1575c 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -46,7 +46,7 @@ #define DBG(x...) #endif -struct pci_fixup pcibios_fixups[1]; +static int pci_routeirq; /* * Low-level SAL-based PCI configuration access functions. Note that SAL @@ -126,7 +126,7 @@ pci_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val devfn, where, size, value); } -static struct pci_ops pci_root_ops = { +struct pci_ops pci_root_ops = { .read = pci_read, .write = pci_write, }; @@ -138,13 +138,33 @@ pci_acpi_init (void) printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - /* - * PCI IRQ routing is set up by pci_enable_device(), but we - * also do it here in case there are still broken drivers that - * don't use pci_enable_device(). - */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - acpi_pci_irq_enable(dev); +#ifdef CONFIG_NUMA +extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**); + + acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL); +#endif + + if (pci_routeirq) { + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n"); + printk(KERN_INFO "** was specified. If this was required to make a driver work,\n"); + printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n"); + printk(KERN_INFO "** so I can fix the driver.\n"); + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + } else { + printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n"); + printk(KERN_INFO "** causes a device to stop working, it is probably because the\n"); + printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n"); + printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n"); + printk(KERN_INFO "** behavior. If this argument makes the device work again,\n"); + printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n"); + printk(KERN_INFO "** so I can fix the driver.\n"); + } return 0; } @@ -272,7 +292,7 @@ add_window (struct acpi_resource *res, void *data) return AE_OK; window = &info->controller->window[info->controller->windows++]; - window->resource.flags |= flags; + window->resource.flags = flags; window->resource.start = addr.min_address_range; window->resource.end = addr.max_address_range; window->offset = offset; @@ -325,33 +345,65 @@ out1: return NULL; } -void __init -pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus) +void pcibios_resource_to_bus(struct pci_dev *dev, + struct pci_bus_region *region, struct resource *res) { struct pci_controller *controller = PCI_CONTROLLER(dev); - struct pci_window *window; - int i, j; + unsigned long offset = 0; + int i; + + for (i = 0; i < controller->windows; i++) { + struct pci_window *window = &controller->window[i]; + if (!(window->resource.flags & res->flags)) + continue; + if (window->resource.start > res->start - window->offset) + continue; + if (window->resource.end < res->end - window->offset) + continue; + offset = window->offset; + break; + } + + region->start = res->start - offset; + region->end = res->end - offset; +} + +void pcibios_bus_to_resource(struct pci_dev *dev, + struct resource *res, struct pci_bus_region *region) +{ + struct pci_controller *controller = PCI_CONTROLLER(dev); + unsigned long offset = 0; + int i; + + for (i = 0; i < controller->windows; i++) { + struct pci_window *window = &controller->window[i]; + if (!(window->resource.flags & res->flags)) + continue; + if (window->resource.start > region->start) + continue; + if (window->resource.end < region->end) + continue; + offset = window->offset; + break; + } + + res->start = region->start + offset; + res->end = region->end + offset; +} + +static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +{ + struct pci_bus_region region; + int i; int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \ - PCI_ROM_RESOURCE : PCI_NUM_RESOURCES; + PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES; for (i = 0; i < limit; i++) { - if (!dev->resource[i].start) + if (!dev->resource[i].flags) continue; - -#define contains(win, res) ((res)->start >= (win)->start && \ - (res)->end <= (win)->end) - - for (j = 0; j < controller->windows; j++) { - window = &controller->window[j]; - if (((dev->resource[i].flags & IORESOURCE_MEM && - window->resource.flags & IORESOURCE_MEM) || - (dev->resource[i].flags & IORESOURCE_IO && - window->resource.flags & IORESOURCE_IO)) && - contains(&window->resource, &dev->resource[i])) { - dev->resource[i].start += window->offset; - dev->resource[i].end += window->offset; - } - } + region.start = dev->resource[i].start; + region.end = dev->resource[i].end; + pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); pci_claim_resource(dev, i); } } @@ -362,10 +414,10 @@ pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus) void __devinit pcibios_fixup_bus (struct pci_bus *b) { - struct list_head *ln; + struct pci_dev *dev; - for (ln = b->devices.next; ln != &b->devices; ln = ln->next) - pcibios_fixup_device_resources(pci_dev_b(ln), b); + list_for_each_entry(dev, &b->devices, bus_list) + pcibios_fixup_device_resources(dev); return; } @@ -440,6 +492,8 @@ pcibios_align_resource (void *data, struct resource *res, char * __init pcibios_setup (char *str) { + if (!strcmp(str, "routeirq")) + pci_routeirq = 1; return NULL; } @@ -448,21 +502,21 @@ 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. + * 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. + * 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. + * 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); @@ -471,7 +525,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, else vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff --git a/arch/ia64/sn/Makefile b/arch/ia64/sn/Makefile index d28f1a0ca..a269f6d84 100644 --- a/arch/ia64/sn/Makefile +++ b/arch/ia64/sn/Makefile @@ -4,9 +4,11 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 2003 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (C) 2004 Silicon Graphics, Inc. All Rights Reserved. # # Makefile for the sn ia64 subplatform # -obj-y += kernel/ io/ +CPPFLAGS += -I$(srctree)/arch/ia64/sn/include + +obj-y += kernel/ pci/ diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile index 1e610ac2b..6c7f4d9e8 100644 --- a/arch/ia64/sn/kernel/Makefile +++ b/arch/ia64/sn/kernel/Makefile @@ -7,5 +7,6 @@ # Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. # -obj-y += probe.o setup.o bte.o irq.o mca.o idle.o sn2/ +obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \ + huberror.o io_init.o iomv.o klconflib.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index e040fc3c4..a9954bba1 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -8,14 +8,14 @@ #include #include -#include #include #include #include #include #include -#include +#include "shubio.h" #include +#include #include #include @@ -30,8 +30,7 @@ /* two interfaces on two btes */ #define MAX_INTERFACES_TO_TRY 4 -static struct bteinfo_s * -bte_if_on_node(nasid_t nasid, int interface) +static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface) { nodepda_t *tmp_nodepda; @@ -40,13 +39,11 @@ bte_if_on_node(nasid_t nasid, int interface) } - /************************************************************************ * Block Transfer Engine copy related functions. * ***********************************************************************/ - /* * bte_copy(src, dest, len, mode, notification) * @@ -66,17 +63,17 @@ bte_if_on_node(nasid_t nasid, int interface) * NOTE: This function requires src, dest, and len to * be cacheline aligned. */ -bte_result_t -bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) +bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) { u64 transfer_size; u64 transfer_stat; struct bteinfo_s *bte; bte_result_t bte_status; unsigned long irq_flags; + unsigned long itc_end = 0; struct bteinfo_s *btes_to_try[MAX_INTERFACES_TO_TRY]; int bte_if_index; - + int bte_pri, bte_sec; BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n", src, dest, len, mode, notification)); @@ -85,34 +82,44 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) return BTE_SUCCESS; } - ASSERT(!((len & L1_CACHE_MASK) || - (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK))); - ASSERT(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)); + BUG_ON((len & L1_CACHE_MASK) || + (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK)); + BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT))); + + /* CPU 0 (per node) tries bte0 first, CPU 1 try bte1 first */ + if (cpuid_to_subnode(smp_processor_id()) == 0) { + bte_pri = 0; + bte_sec = 1; + } else { + bte_pri = 1; + bte_sec = 0; + } if (mode & BTE_USE_DEST) { /* try remote then local */ - btes_to_try[0] = bte_if_on_node(NASID_GET(dest), 0); - btes_to_try[1] = bte_if_on_node(NASID_GET(dest), 1); + btes_to_try[0] = bte_if_on_node(NASID_GET(dest), bte_pri); + btes_to_try[1] = bte_if_on_node(NASID_GET(dest), bte_sec); if (mode & BTE_USE_ANY) { - btes_to_try[2] = bte_if_on_node(get_nasid(), 0); - btes_to_try[3] = bte_if_on_node(get_nasid(), 1); + btes_to_try[2] = bte_if_on_node(get_nasid(), bte_pri); + btes_to_try[3] = bte_if_on_node(get_nasid(), bte_sec); } else { btes_to_try[2] = NULL; btes_to_try[3] = NULL; } } else { /* try local then remote */ - btes_to_try[0] = bte_if_on_node(get_nasid(), 0); - btes_to_try[1] = bte_if_on_node(get_nasid(), 1); + btes_to_try[0] = bte_if_on_node(get_nasid(), bte_pri); + btes_to_try[1] = bte_if_on_node(get_nasid(), bte_sec); if (mode & BTE_USE_ANY) { - btes_to_try[2] = bte_if_on_node(NASID_GET(dest), 0); - btes_to_try[3] = bte_if_on_node(NASID_GET(dest), 1); + btes_to_try[2] = bte_if_on_node(NASID_GET(dest), bte_pri); + btes_to_try[3] = bte_if_on_node(NASID_GET(dest), bte_sec); } else { btes_to_try[2] = NULL; btes_to_try[3] = NULL; } } +retry_bteop: do { local_irq_save(irq_flags); @@ -127,16 +134,16 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) } if (spin_trylock(&bte->spinlock)) { - if ((*bte->most_rcnt_na & BTE_ACTIVE) || + if (!(*bte->most_rcnt_na & BTE_WORD_AVAILABLE) || (BTE_LNSTAT_LOAD(bte) & BTE_ACTIVE)) { /* Got the lock but BTE still busy */ spin_unlock(&bte->spinlock); - bte = NULL; } else { /* we got the lock and it's not busy */ break; } } + bte = NULL; } if (bte != NULL) { @@ -150,7 +157,6 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) } } while (1); - if (notification == NULL) { /* User does not want to be notified. */ bte->most_rcnt_na = &bte->notify; @@ -162,7 +168,7 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK); /* Initialize the notification to a known value. */ - *bte->most_rcnt_na = -1L; + *bte->most_rcnt_na = BTE_WORD_BUSY; /* Set the status reg busy bit and transfer length */ BTE_PRINTKV(("IBLS = 0x%lx\n", IBLS_BUSY | transfer_size)); @@ -175,42 +181,53 @@ bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) BTE_DEST_STORE(bte, TO_PHYS(dest)); /* Set the notification register */ - BTE_PRINTKV(("IBNA = 0x%lx)\n", + BTE_PRINTKV(("IBNA = 0x%lx)\n", TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)))); - BTE_NOTIF_STORE(bte, TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))); - + BTE_NOTIF_STORE(bte, + TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))); /* Initiate the transfer */ BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode))); BTE_CTRL_STORE(bte, BTE_VALID_MODE(mode)); - spin_unlock_irqrestore(&bte->spinlock, irq_flags); + itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec); + spin_unlock_irqrestore(&bte->spinlock, irq_flags); if (notification != NULL) { return BTE_SUCCESS; } - while ((transfer_stat = *bte->most_rcnt_na) == -1UL) { + while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) { + if (ia64_get_itc() > itc_end) { + BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n", + NASID_GET(bte->bte_base_addr), bte->bte_num, + BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na) ); + bte->bte_error_count++; + bte->bh_error = IBLS_ERROR; + bte_error_handler((unsigned long)NODEPDA(bte->bte_cnode)); + *bte->most_rcnt_na = BTE_WORD_AVAILABLE; + goto retry_bteop; + } } - BTE_PRINTKV((" Delay Done. IBLS = 0x%lx, most_rcnt_na = 0x%lx\n", - BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na)); + BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na)); if (transfer_stat & IBLS_ERROR) { bte_status = transfer_stat & ~IBLS_ERROR; - *bte->most_rcnt_na = 0L; } else { bte_status = BTE_SUCCESS; } + *bte->most_rcnt_na = BTE_WORD_AVAILABLE; + BTE_PRINTK(("Returning status is 0x%lx and most_rcnt_na is 0x%lx\n", - BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na)); + BTE_LNSTAT_LOAD(bte), *bte->most_rcnt_na)); return bte_status; } -EXPORT_SYMBOL(bte_copy); +EXPORT_SYMBOL(bte_copy); /* * bte_unaligned_copy(src, dest, len, mode) @@ -228,8 +245,7 @@ EXPORT_SYMBOL(bte_copy); * NOTE: If the source, dest, and len are all cache line aligned, * then it would be _FAR_ preferrable to use bte_copy instead. */ -bte_result_t -bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) +bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) { int destFirstCacheOffset; u64 headBteSource; @@ -254,7 +270,7 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) if (bteBlock_unaligned == NULL) { return BTEFAIL_NOTAVAIL; } - bteBlock = (char *) L1_CACHE_ALIGN((u64) bteBlock_unaligned); + bteBlock = (char *)L1_CACHE_ALIGN((u64) bteBlock_unaligned); headBcopySrcOffset = src & L1_CACHE_MASK; destFirstCacheOffset = dest & L1_CACHE_MASK; @@ -302,15 +318,13 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) } if (len > headBcopyLen) { - footBcopyLen = - (len - headBcopyLen) & L1_CACHE_MASK; + footBcopyLen = (len - headBcopyLen) & L1_CACHE_MASK; footBteLen = L1_CACHE_BYTES; footBteSource = src + len - footBcopyLen; footBcopyDest = dest + len - footBcopyLen; - if (footBcopyDest == - (headBcopyDest + headBcopyLen)) { + if (footBcopyDest == (headBcopyDest + headBcopyLen)) { /* * We have two contigous bcopy * blocks. Merge them. @@ -326,9 +340,8 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) return rv; } - memcpy(__va(footBcopyDest), - (char *) bteBlock, footBcopyLen); + (char *)bteBlock, footBcopyLen); } } else { footBcopyLen = 0; @@ -350,7 +363,6 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) } } else { - /* * The transfer is not symetric, we will * allocate a buffer large enough for all the @@ -361,8 +373,7 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) /* Add the leader from source */ headBteLen = len + (src & L1_CACHE_MASK); /* Add the trailing bytes from footer. */ - headBteLen += - L1_CACHE_BYTES - (headBteLen & L1_CACHE_MASK); + headBteLen += L1_CACHE_BYTES - (headBteLen & L1_CACHE_MASK); headBteSource = src & ~L1_CACHE_MASK; headBcopySrcOffset = src & L1_CACHE_MASK; headBcopyDest = dest; @@ -371,40 +382,37 @@ bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode) if (headBcopyLen > 0) { rv = bte_copy(headBteSource, - ia64_tpa((unsigned long)bteBlock), headBteLen, mode, NULL); + ia64_tpa((unsigned long)bteBlock), headBteLen, + mode, NULL); if (rv != BTE_SUCCESS) { kfree(bteBlock_unaligned); return rv; } - memcpy(__va(headBcopyDest), ((char *) bteBlock + - headBcopySrcOffset), - headBcopyLen); + memcpy(__va(headBcopyDest), ((char *)bteBlock + + headBcopySrcOffset), headBcopyLen); } kfree(bteBlock_unaligned); return BTE_SUCCESS; } -EXPORT_SYMBOL(bte_unaligned_copy); +EXPORT_SYMBOL(bte_unaligned_copy); /************************************************************************ * Block Transfer Engine initialization functions. * ***********************************************************************/ - /* * bte_init_node(nodepda, cnode) * * Initialize the nodepda structure with BTE base addresses and * spinlocks. */ -void -bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) +void bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) { int i; - /* * Indicate that all the block transfer engines on this node * are available. @@ -418,12 +426,13 @@ bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) spin_lock_init(&mynodepda->bte_recovery_lock); init_timer(&mynodepda->bte_recovery_timer); mynodepda->bte_recovery_timer.function = bte_error_handler; - mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda; + mynodepda->bte_recovery_timer.data = (unsigned long)mynodepda; for (i = 0; i < BTES_PER_NODE; i++) { - (u64) mynodepda->bte_if[i].bte_base_addr = - REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), - (i == 0 ? IIO_IBLS0 : IIO_IBLS1)); + /* Which link status register should we use? */ + unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1); + mynodepda->bte_if[i].bte_base_addr = (u64 *) + REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status); /* * Initialize the notification and spinlock @@ -431,7 +440,7 @@ bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode) */ mynodepda->bte_if[i].most_rcnt_na = &(mynodepda->bte_if[i].notify); - mynodepda->bte_if[i].notify = 0L; + mynodepda->bte_if[i].notify = BTE_WORD_AVAILABLE; spin_lock_init(&mynodepda->bte_if[i].spinlock); mynodepda->bte_if[i].bte_cnode = cnode; diff --git a/arch/ia64/sn/kernel/idle.c b/arch/ia64/sn/kernel/idle.c index 65e6e3f77..49d178f02 100644 --- a/arch/ia64/sn/kernel/idle.c +++ b/arch/ia64/sn/kernel/idle.c @@ -3,14 +3,13 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved. */ -#include #include -#include -void snidle(int state) { +void snidle(int state) +{ if (state) { if (pda->idle_flag == 0) { /* @@ -19,11 +18,6 @@ void snidle(int state) { set_led_bits(0, LED_CPU_ACTIVITY); } -#ifdef CONFIG_IA64_SGI_SN_SIM - if (IS_RUNNING_ON_SIMULATOR()) - SIMULATOR_SLEEP(); -#endif - pda->idle_flag = 1; } else { /* diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 6bcf70ea1..1e262c032 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,97 +5,83 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. */ -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include -#include -#include -#include -#include -#include +#include "xtalk/xwidgetdev.h" +#include "pci/pcibus_provider_defs.h" +#include "pci/pcidev.h" +#include "pci/pcibr_provider.h" +#include +#include static void force_interrupt(int irq); -extern void pcibr_force_interrupt(pcibr_intr_t intr); -extern int sn_force_interrupt_flag; -struct irq_desc * sn_irq_desc(unsigned int irq); -extern cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; - -struct sn_intr_list_t { - struct sn_intr_list_t *next; - pcibr_intr_t intr; -}; +static void register_intr_pda(struct sn_irq_info *sn_irq_info); +static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); -static struct sn_intr_list_t *sn_intr_list[NR_IRQS]; +extern int sn_force_interrupt_flag; +extern int sn_ioif_inited; +struct sn_irq_info **sn_irq; +static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, + u64 sn_irq_info, + int req_irq, nasid_t req_nasid, + int req_slice) +{ + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, + (u64) SAL_INTR_ALLOC, (u64) local_nasid, + (u64) local_widget, (u64) sn_irq_info, (u64) req_irq, + (u64) req_nasid, (u64) req_slice); + return ret_stuff.status; +} -static unsigned int -sn_startup_irq(unsigned int irq) +static inline void sn_intr_free(nasid_t local_nasid, int local_widget, + struct sn_irq_info *sn_irq_info) { - return(0); + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, + (u64) SAL_INTR_FREE, (u64) local_nasid, + (u64) local_widget, (u64) sn_irq_info->irq_irq, + (u64) sn_irq_info->irq_cookie, 0, 0); } -static void -sn_shutdown_irq(unsigned int irq) +static unsigned int sn_startup_irq(unsigned int irq) { + return 0; } -static void -sn_disable_irq(unsigned int irq) +static void sn_shutdown_irq(unsigned int irq) { } -static void -sn_enable_irq(unsigned int irq) +static void sn_disable_irq(unsigned int irq) { } -static inline void sn_move_irq(int irq) +static void sn_enable_irq(unsigned int irq) { - /* note - we hold desc->lock */ - cpumask_t tmp; - irq_desc_t *desc = irq_descp(irq); - - if (!cpus_empty(pending_irq_cpumask[irq])) { - cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); - if (unlikely(!cpus_empty(tmp))) { - desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); - } - cpus_clear(pending_irq_cpumask[irq]); - } } -static void -sn_ack_irq(unsigned int irq) +static void sn_ack_irq(unsigned int irq) { - unsigned long event_occurred, mask = 0; + uint64_t event_occurred, mask = 0; int nasid; irq = irq & 0xff; - nasid = smp_physical_node_id(); - event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) ); + nasid = get_nasid(); + event_occurred = + HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED)); if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) { mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT); } @@ -108,63 +94,102 @@ sn_ack_irq(unsigned int irq) if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) { mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT); } - HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), mask ); + HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), + mask); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); - sn_move_irq(irq); + + move_irq(irq); } -static void -sn_end_irq(unsigned int irq) +static void sn_end_irq(unsigned int irq) { int nasid; int ivec; - unsigned long event_occurred; - irq_desc_t *desc = sn_irq_desc(irq); - unsigned int status = desc->status; + uint64_t event_occurred; ivec = irq & 0xff; if (ivec == SGI_UART_VECTOR) { - nasid = smp_physical_node_id(); - event_occurred = HUB_L( (unsigned long *)GLOBAL_MMR_ADDR(nasid,SH_EVENT_OCCURRED) ); - // If the UART bit is set here, we may have received an interrupt from the - // UART that the driver missed. To make sure, we IPI ourselves to force us - // to look again. + nasid = get_nasid(); + event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR + (nasid, SH_EVENT_OCCURRED)); + /* If the UART bit is set here, we may have received an + * interrupt from the UART that the driver missed. To + * make sure, we IPI ourselves to force us to look again. + */ if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) { - platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0); + platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, + IA64_IPI_DM_INT, 0); } } __clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs); if (sn_force_interrupt_flag) - if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) - force_interrupt(irq); + force_interrupt(irq); } -static void -sn_set_affinity_irq(unsigned int irq, cpumask_t mask) +static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) { -#ifdef CONFIG_SMP - int redir = 0; - int cpu; - struct sn_intr_list_t *p = sn_intr_list[irq]; - pcibr_intr_t intr; - extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu); - extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu); - - if (p == NULL) - return; - - intr = p->intr; - - if (intr == NULL) - return; - - cpu = first_cpu(mask); - sn_shub_redirect_intr(intr, cpu); - irq = irq & 0xff; /* strip off redirect bit, if someone stuck it on. */ - (void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir); -#endif /* CONFIG_SMP */ -} + struct sn_irq_info *sn_irq_info = sn_irq[irq]; + struct sn_irq_info *tmp_sn_irq_info; + int cpuid, cpuphys; + nasid_t t_nasid; /* nasid to target */ + int t_slice; /* slice to target */ + + /* allocate a temp sn_irq_info struct to get new target info */ + tmp_sn_irq_info = kmalloc(sizeof(*tmp_sn_irq_info), GFP_KERNEL); + if (!tmp_sn_irq_info) + return; + + cpuid = first_cpu(mask); + cpuphys = cpu_physical_id(cpuid); + t_nasid = cpuid_to_nasid(cpuid); + t_slice = cpuid_to_slice(cpuid); + + while (sn_irq_info) { + int status; + int local_widget; + uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; + nasid_t local_nasid = NASID_GET(bridge); + + if (!bridge) + break; /* irq is not a device interrupt */ + + if (local_nasid & 1) + local_widget = TIO_SWIN_WIDGETNUM(bridge); + else + local_widget = SWIN_WIDGETNUM(bridge); + + /* Free the old PROM sn_irq_info structure */ + sn_intr_free(local_nasid, local_widget, sn_irq_info); + + /* allocate a new PROM sn_irq_info struct */ + status = sn_intr_alloc(local_nasid, local_widget, + __pa(tmp_sn_irq_info), irq, t_nasid, + t_slice); + + if (status == 0) { + /* Update kernels sn_irq_info with new target info */ + unregister_intr_pda(sn_irq_info); + sn_irq_info->irq_cpuid = cpuid; + sn_irq_info->irq_nasid = t_nasid; + sn_irq_info->irq_slice = t_slice; + sn_irq_info->irq_xtalkaddr = + tmp_sn_irq_info->irq_xtalkaddr; + sn_irq_info->irq_cookie = tmp_sn_irq_info->irq_cookie; + register_intr_pda(sn_irq_info); + + if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type)) { + pcibr_change_devices_irq(sn_irq_info); + } + sn_irq_info = sn_irq_info->irq_next; + + set_irq_affinity_info((irq & 0xff), cpuphys, 0); + } else { + break; /* snp_affinity failed the intr_alloc */ + } + } + kfree(tmp_sn_irq_info); +} struct hw_interrupt_type irq_type_sn = { "SN hub", @@ -172,208 +197,243 @@ struct hw_interrupt_type irq_type_sn = { sn_shutdown_irq, sn_enable_irq, sn_disable_irq, - sn_ack_irq, + sn_ack_irq, sn_end_irq, sn_set_affinity_irq }; - -struct irq_desc * -sn_irq_desc(unsigned int irq) +struct irq_desc *sn_irq_desc(unsigned int irq) { - - irq = SN_IVEC_FROM_IRQ(irq); - - return(_irq_desc + irq); + return (_irq_desc + irq); } -u8 -sn_irq_to_vector(unsigned int irq) +u8 sn_irq_to_vector(unsigned int irq) { - return(irq); + return irq; } -unsigned int -sn_local_vector_to_irq(u8 vector) +unsigned int sn_local_vector_to_irq(u8 vector) { return (CPU_VECTOR_TO_IRQ(smp_processor_id(), vector)); } -void -sn_irq_init (void) +void sn_irq_init(void) { int i; irq_desc_t *base_desc = _irq_desc; - for (i=0; ibi_cpu; + int irq = sn_irq_info->irq_irq; + int cpu = sn_irq_info->irq_cpuid; if (pdacpu(cpu)->sn_last_irq < irq) { pdacpu(cpu)->sn_last_irq = irq; } - if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq; - if (!p) panic("Could not allocate memory for sn_intr_list_t\n"); - if ((list = sn_intr_list[irq])) { - while (list->next) list = list->next; - list->next = p; - p->next = NULL; - p->intr = intr; - } else { - sn_intr_list[irq] = p; - p->next = NULL; - p->intr = intr; + + if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { + pdacpu(cpu)->sn_first_irq = irq; } } -void -unregister_pcibr_intr(int irq, pcibr_intr_t intr) +static void unregister_intr_pda(struct sn_irq_info *sn_irq_info) { - - struct sn_intr_list_t **prev, *curr; - int cpu = intr->bi_cpu; - int i; - - if (sn_intr_list[irq] == NULL) - return; - - prev = &sn_intr_list[irq]; - curr = sn_intr_list[irq]; - while (curr) { - if (curr->intr == intr) { - *prev = curr->next; - break; + int irq = sn_irq_info->irq_irq; + int cpu = sn_irq_info->irq_cpuid; + struct sn_irq_info *tmp_irq_info; + int i, foundmatch; + + if (pdacpu(cpu)->sn_last_irq == irq) { + foundmatch = 0; + for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) { + tmp_irq_info = sn_irq[i]; + while (tmp_irq_info) { + if (tmp_irq_info->irq_cpuid == cpu) { + foundmatch++; + break; + } + tmp_irq_info = tmp_irq_info->irq_next; + } + if (foundmatch) { + break; + } } - prev = &curr->next; - curr = curr->next; + pdacpu(cpu)->sn_last_irq = i; } - if (curr) - kfree(curr); - - if (!sn_intr_list[irq]) { - if (pdacpu(cpu)->sn_last_irq == irq) { - for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) - if (sn_intr_list[i]) + if (pdacpu(cpu)->sn_first_irq == irq) { + foundmatch = 0; + for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) { + tmp_irq_info = sn_irq[i]; + while (tmp_irq_info) { + if (tmp_irq_info->irq_cpuid == cpu) { + foundmatch++; break; - pdacpu(cpu)->sn_last_irq = i; + } + tmp_irq_info = tmp_irq_info->irq_next; + } + if (foundmatch) { + break; + } } + pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i); + } +} - if (pdacpu(cpu)->sn_first_irq == irq) { - pdacpu(cpu)->sn_first_irq = 0; - for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) - if (sn_intr_list[i]) - pdacpu(cpu)->sn_first_irq = i; - } +struct sn_irq_info *sn_irq_alloc(nasid_t local_nasid, int local_widget, int irq, + nasid_t nasid, int slice) +{ + struct sn_irq_info *sn_irq_info; + int status; + + sn_irq_info = kmalloc(sizeof(*sn_irq_info), GFP_KERNEL); + if (sn_irq_info == NULL) + return NULL; + + memset(sn_irq_info, 0x0, sizeof(*sn_irq_info)); + + status = + sn_intr_alloc(local_nasid, local_widget, __pa(sn_irq_info), irq, + nasid, slice); + + if (status) { + kfree(sn_irq_info); + return NULL; + } else { + return sn_irq_info; } +} + +void sn_irq_free(struct sn_irq_info *sn_irq_info) +{ + uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; + nasid_t local_nasid = NASID_GET(bridge); + int local_widget; + if (local_nasid & 1) /* tio check */ + local_widget = TIO_SWIN_WIDGETNUM(bridge); + else + local_widget = SWIN_WIDGETNUM(bridge); + + sn_intr_free(local_nasid, local_widget, sn_irq_info); + + kfree(sn_irq_info); } -void -force_polled_int(void) +void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) { - int i; - struct sn_intr_list_t *p; + nasid_t nasid = sn_irq_info->irq_nasid; + int slice = sn_irq_info->irq_slice; + int cpu = nasid_slice_to_cpuid(nasid, slice); - for (i=0; iintr){ - pcibr_force_interrupt(p->intr); - } - p = p->next; - } - } + sn_irq_info->irq_cpuid = cpu; + sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev); + + /* link it into the sn_irq[irq] list */ + sn_irq_info->irq_next = sn_irq[sn_irq_info->irq_irq]; + sn_irq[sn_irq_info->irq_irq] = sn_irq_info; + + (void)register_intr_pda(sn_irq_info); } -static void -force_interrupt(int irq) +static void force_interrupt(int irq) { - struct sn_intr_list_t *p = sn_intr_list[irq]; + struct sn_irq_info *sn_irq_info; - while (p) { - if (p->intr) { - pcibr_force_interrupt(p->intr); + if (!sn_ioif_inited) + return; + sn_irq_info = sn_irq[irq]; + while (sn_irq_info) { + if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && + (sn_irq_info->irq_bridge != NULL)) { + pcibr_force_interrupt(sn_irq_info); } - p = p->next; + sn_irq_info = sn_irq_info->irq_next; } } /* -Check for lost interrupts. If the PIC int_status reg. says that -an interrupt has been sent, but not handled, and the interrupt -is not pending in either the cpu irr regs or in the soft irr regs, -and the interrupt is not in service, then the interrupt may have -been lost. Force an interrupt on that pin. It is possible that -the interrupt is in flight, so we may generate a spurious interrupt, -but we should never miss a real lost interrupt. -*/ - -static void -sn_check_intr(int irq, pcibr_intr_t intr) + * Check for lost interrupts. If the PIC int_status reg. says that + * an interrupt has been sent, but not handled, and the interrupt + * is not pending in either the cpu irr regs or in the soft irr regs, + * and the interrupt is not in service, then the interrupt may have + * been lost. Force an interrupt on that pin. It is possible that + * the interrupt is in flight, so we may generate a spurious interrupt, + * but we should never miss a real lost interrupt. + */ +static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) { - unsigned long regval; + uint64_t regval; int irr_reg_num; int irr_bit; - unsigned long irr_reg; + uint64_t irr_reg; + struct pcidev_info *pcidev_info; + struct pcibus_info *pcibus_info; + + pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + if (!pcidev_info) + return; + pcibus_info = + (struct pcibus_info *)pcidev_info->pdi_host_pcidev_info-> + pdi_pcibus_info; + regval = pcireg_intr_status_get(pcibus_info); - regval = pcireg_intr_status_get(intr->bi_soft); irr_reg_num = irq_to_vector(irq) / 64; irr_bit = irq_to_vector(irq) % 64; switch (irr_reg_num) { - case 0: - irr_reg = ia64_getreg(_IA64_REG_CR_IRR0); - break; - case 1: - irr_reg = ia64_getreg(_IA64_REG_CR_IRR1); - break; - case 2: - irr_reg = ia64_getreg(_IA64_REG_CR_IRR2); - break; - case 3: - irr_reg = ia64_getreg(_IA64_REG_CR_IRR3); - break; + case 0: + irr_reg = ia64_getreg(_IA64_REG_CR_IRR0); + break; + case 1: + irr_reg = ia64_getreg(_IA64_REG_CR_IRR1); + break; + case 2: + irr_reg = ia64_getreg(_IA64_REG_CR_IRR2); + break; + case 3: + irr_reg = ia64_getreg(_IA64_REG_CR_IRR3); + break; } - if (!test_bit(irr_bit, &irr_reg) ) { - if (!test_bit(irq, pda->sn_soft_irr) ) { - if (!test_bit(irq, pda->sn_in_service_ivecs) ) { + if (!test_bit(irr_bit, &irr_reg)) { + if (!test_bit(irq, pda->sn_soft_irr)) { + if (!test_bit(irq, pda->sn_in_service_ivecs)) { regval &= 0xff; - if (intr->bi_ibits & regval & intr->bi_last_intr) { - regval &= ~(intr->bi_ibits & regval); - pcibr_force_interrupt(intr); + if (sn_irq_info->irq_int_bit & regval & + sn_irq_info->irq_last_intr) { + regval &= + ~(sn_irq_info-> + irq_int_bit & regval); + pcibr_force_interrupt(sn_irq_info); } } } } - intr->bi_last_intr = regval; + sn_irq_info->irq_last_intr = regval; } -void -sn_lb_int_war_check(void) +void sn_lb_int_war_check(void) { int i; - if (pda->sn_first_irq == 0) return; - for (i=pda->sn_first_irq; - i <= pda->sn_last_irq; i++) { - struct sn_intr_list_t *p = sn_intr_list[i]; - if (p == NULL) { - continue; - } - while (p) { - sn_check_intr(i, p->intr); - p = p->next; + if (!sn_ioif_inited || pda->sn_first_irq == 0) + return; + for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { + struct sn_irq_info *sn_irq_info = sn_irq[i]; + while (sn_irq_info) { + /* Only call for PCI bridges that are fully initialized. */ + if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && + (sn_irq_info->irq_bridge != NULL)) { + sn_check_intr(i, sn_irq_info); } + sn_irq_info = sn_irq_info->irq_next; + } } } diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 3b313e0a3..857774bb2 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c @@ -10,13 +10,10 @@ #include #include #include -#include #include #include #include - - /* * Interval for calling SAL to poll for errors that do NOT cause error * interrupts. SAL will raise a CPEI if any errors are present that @@ -24,7 +21,6 @@ */ #define CPEI_INTERVAL (5*HZ) - struct timer_list sn_cpei_timer; void sn_init_cpei_timer(void); @@ -42,8 +38,7 @@ static u64 *sn_oemdata_size, sn_oemdata_bufsize; * info for platform errors. buf is appended to sn_oemdata, resizing as * required. */ -static int -print_hook(const char *fmt, ...) +static int print_hook(const char *fmt, ...) { char buf[400]; int len; @@ -55,7 +50,8 @@ print_hook(const char *fmt, ...) while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) { u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000); if (!newbuf) { - printk(KERN_ERR "%s: unable to extend sn_oemdata\n", __FUNCTION__); + printk(KERN_ERR "%s: unable to extend sn_oemdata\n", + __FUNCTION__); return 0; } memcpy(newbuf, *sn_oemdata, *sn_oemdata_size); @@ -67,9 +63,7 @@ print_hook(const char *fmt, ...) return 0; } - -static void -sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) +static void sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) { /* * this function's sole purpose is to call SAL when we receive @@ -82,16 +76,13 @@ sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) ia64_sn_plat_cpei_handler(); } - -static void -sn_cpei_timer_handler(unsigned long dummy) +static void sn_cpei_timer_handler(unsigned long dummy) { sn_cpei_handler(-1, NULL, NULL); mod_timer(&sn_cpei_timer, jiffies + CPEI_INTERVAL); } -void -sn_init_cpei_timer(void) +void sn_init_cpei_timer(void) { init_timer(&sn_cpei_timer); sn_cpei_timer.expires = jiffies + CPEI_INTERVAL; @@ -100,16 +91,14 @@ sn_init_cpei_timer(void) } static int -sn_platform_plat_specific_err_print(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size) +sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, + u64 * oemdata_size) { - sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header; - if (!psei->valid.oem_data) - return 0; down(&sn_oemdata_mutex); sn_oemdata = oemdata; sn_oemdata_size = oemdata_size; sn_oemdata_bufsize = 0; - ia64_sn_plat_specific_err_print(print_hook, (char *)psei); + ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header); up(&sn_oemdata_mutex); return 0; } @@ -120,13 +109,21 @@ sn_platform_plat_specific_err_print(const u8 *sect_header, u8 **oemdata, u64 *oe int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size) { efi_guid_t guid = *(efi_guid_t *)sect_header; + int valid = 0; *oemdata_size = 0; vfree(*oemdata); *oemdata = NULL; - if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0 || - efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) + if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) { + sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header; + valid = psei->valid.oem_data; + } else if (efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) { + sal_log_mem_dev_err_info_t *mdei = (sal_log_mem_dev_err_info_t *)sect_header; + valid = mdei->valid.oem_data; + } + if (valid) return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size); - return 0; + else + return 0; } static int __init sn_salinfo_init(void) diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index d3830e338..c92b4b443 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All rights reserved. */ #include @@ -34,63 +34,59 @@ #include #include #include -#include -#include #include #include #include #include #include -#include #include +#include "shub.h" #include #include +#include #include #include -#include +#include +#include "xtalk/xwidgetdev.h" +#include "xtalk/hubdev.h" +#include + DEFINE_PER_CPU(struct pda_s, pda_percpu); -#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */ +#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */ + +lboard_t *root_lboard[MAX_COMPACT_NODES]; + +extern void bte_init_node(nodepda_t *, cnodeid_t); -extern void bte_init_node (nodepda_t *, cnodeid_t); extern void sn_timer_init(void); extern unsigned long last_time_offset; -extern void init_platform_hubinfo(nodepda_t **nodepdaindr); -extern void (*ia64_mark_idle)(int); +extern void (*ia64_mark_idle) (int); extern void snidle(int); extern unsigned char acpi_kbd_controller_present; +unsigned long sn_rtc_cycles_per_second; -unsigned long sn_rtc_cycles_per_second; +EXPORT_SYMBOL(sn_rtc_cycles_per_second); partid_t sn_partid = -1; +EXPORT_SYMBOL(sn_partid); char sn_system_serial_number_string[128]; +EXPORT_SYMBOL(sn_system_serial_number_string); u64 sn_partition_serial_number; +EXPORT_SYMBOL(sn_partition_serial_number); short physical_node_map[MAX_PHYSNODE_ID]; EXPORT_SYMBOL(physical_node_map); -int numionodes; -/* - * This is the address of the RRegs in the HSpace of the global - * master. It is used by a hack in serial.c (serial_[in|out], - * printk.c (early_printk), and kdb_io.c to put console output on that - * node's Bedrock UART. It is initialized here to 0, so that - * early_printk won't try to access the UART before - * master_node_bedrock_address is properly calculated. - */ -u64 master_node_bedrock_address; +int numionodes; static void sn_init_pdas(char **); static void scan_for_ionodes(void); - -static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; - -irqpda_t *irqpdaindr; - +static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; /* * The format of "screen_info" is strange, and due to early i386-setup @@ -98,14 +94,14 @@ irqpda_t *irqpdaindr; * VGA color display. */ struct screen_info sn_screen_info = { - .orig_x = 0, - .orig_y = 0, - .orig_video_mode = 3, - .orig_video_cols = 80, - .orig_video_ega_bx = 3, - .orig_video_lines = 25, - .orig_video_isVGA = 1, - .orig_video_points = 16 + .orig_x = 0, + .orig_y = 0, + .orig_video_mode = 3, + .orig_video_cols = 80, + .orig_video_ega_bx = 3, + .orig_video_lines = 25, + .orig_video_isVGA = 1, + .orig_video_points = 16 }; /* @@ -117,11 +113,24 @@ struct screen_info sn_screen_info = { * is sufficient (the IDE driver will autodetect the drive geometry). */ #ifdef CONFIG_IA64_GENERIC -extern char drive_info[4*16]; +extern char drive_info[4 * 16]; #else -char drive_info[4*16]; +char drive_info[4 * 16]; #endif +/* + * Get nasid of current cpu early in boot before nodepda is initialized + */ +static int +boot_get_nasid(void) +{ + int nasid; + + if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL)) + BUG(); + return nasid; +} + /* * This routine can only be used during init, since * smp_boot_data is an init data structure. @@ -131,8 +140,7 @@ char drive_info[4*16]; * may not be initialized yet. */ -static int __init -pxm_to_nasid(int pxm) +static int __init pxm_to_nasid(int pxm) { int i; int nid; @@ -145,6 +153,7 @@ pxm_to_nasid(int pxm) } return -1; } + /** * early_sn_setup - early setup routine for SN platforms * @@ -152,16 +161,15 @@ pxm_to_nasid(int pxm) * for bringup. See start_kernel() in init/main.c. */ -void __init -early_sn_setup(void) +void __init early_sn_setup(void) { - void ia64_sal_handler_init (void *entry_point, void *gpval); - efi_system_table_t *efi_systab; - efi_config_table_t *config_tables; - struct ia64_sal_systab *sal_systab; - struct ia64_sal_desc_entry_point *ep; - char *p; - int i; + void ia64_sal_handler_init(void *entry_point, void *gpval); + efi_system_table_t *efi_systab; + efi_config_table_t *config_tables; + struct ia64_sal_systab *sal_systab; + struct ia64_sal_desc_entry_point *ep; + char *p; + int i; /* * Parse enough of the SAL tables to locate the SAL entry point. Since, console @@ -170,81 +178,57 @@ early_sn_setup(void) * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c. * Any changes to those file may have to be made hereas well. */ - efi_systab = (efi_system_table_t*)__va(ia64_boot_param->efi_systab); + efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab); config_tables = __va(efi_systab->tables); for (i = 0; i < efi_systab->nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { + if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == + 0) { sal_systab = __va(config_tables[i].table); - p = (char*)(sal_systab+1); + p = (char *)(sal_systab + 1); for (i = 0; i < sal_systab->entry_count; i++) { if (*p == SAL_DESC_ENTRY_POINT) { - ep = (struct ia64_sal_desc_entry_point *) p; - ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); + ep = (struct ia64_sal_desc_entry_point + *)p; + ia64_sal_handler_init(__va + (ep->sal_proc), + __va(ep->gp)); break; } p += SAL_DESC_SIZE(*p); } } } - - if ( IS_RUNNING_ON_SIMULATOR() ) { - master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0); - printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lx\n", master_node_bedrock_address); - } } extern int platform_intr_list[]; extern nasid_t master_nasid; static int shub_1_1_found __initdata; - /* * sn_check_for_wars * * Set flag for enabling shub specific wars */ -static inline int __init -is_shub_1_1(int nasid) +static inline int __init is_shub_1_1(int nasid) { unsigned long id; - int rev; + int rev; id = REMOTE_HUB_L(nasid, SH_SHUB_ID); - rev = (id & SH_SHUB_ID_REVISION_MASK) >> SH_SHUB_ID_REVISION_SHFT; + rev = (id & SH_SHUB_ID_REVISION_MASK) >> SH_SHUB_ID_REVISION_SHFT; return rev <= 2; } -static void __init -sn_check_for_wars(void) +static void __init sn_check_for_wars(void) { - int cnode; + int cnode; - for (cnode=0; cnode< numnodes; cnode++) + for (cnode = 0; cnode < numnodes; cnode++) if (is_shub_1_1(cnodeid_to_nasid(cnode))) shub_1_1_found = 1; } -/** - * sn_set_error_handling_features - Tell the SN prom how to handle certain - * error types. - */ -static void __init -sn_set_error_handling_features(void) -{ - u64 ret; - u64 sn_ehf_bits[7]; /* see ia64_sn_set_error_handling_features */ - memset(sn_ehf_bits, 0, sizeof(sn_ehf_bits)); -#define EHF(x) __set_bit(SN_SAL_EHF_ ## x, sn_ehf_bits) - EHF(MCA_SLV_TO_OS_INIT_SLV); - EHF(NO_RZ_TLBC); - // Uncomment once Jesse's code goes in - EHF(NO_RZ_IO_READ); -#undef EHF - ret = ia64_sn_set_error_handling_features(sn_ehf_bits); - if (ret) - printk(KERN_ERR "%s: failed, return code %ld\n", __FUNCTION__, ret); -} - /** * sn_setup - SN platform setup routine * @cmdline_p: kernel command line @@ -253,15 +237,12 @@ sn_set_error_handling_features(void) * the RTC frequency (via a SAL call), initializing secondary CPUs, and * setting up per-node data areas. The console is also initialized here. */ -void __init -sn_setup(char **cmdline_p) +void __init sn_setup(char **cmdline_p) { long status, ticks_per_sec, drift; int pxm; int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); - extern nasid_t snia_get_master_baseio_nasid(void); extern void sn_cpu_init(void); - extern nasid_t snia_get_console_nasid(void); /* * If the generic code has enabled vga console support - lets @@ -276,17 +257,17 @@ sn_setup(char **cmdline_p) conswitchp = &dummy_con; #else conswitchp = NULL; -#endif /* CONFIG_DUMMY_CONSOLE */ +#endif /* CONFIG_DUMMY_CONSOLE */ } -#endif /* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */ +#endif /* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */ MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY; memset(physical_node_map, -1, sizeof(physical_node_map)); - for (pxm=0; pxmcnodeid_to_nasid_table, -1, sizeof(pda->cnodeid_to_nasid_table)); - for (cnode=0; cnodecnodeid_to_nasid_table[cnode] = pxm_to_nasid(nid_to_pxm_map[cnode]); + memset(pda->cnodeid_to_nasid_table, -1, + sizeof(pda->cnodeid_to_nasid_table)); + for (cnode = 0; cnode < numnodes; cnode++) + pda->cnodeid_to_nasid_table[cnode] = + pxm_to_nasid(nid_to_pxm_map[cnode]); numionodes = numnodes; scan_for_ionodes(); - /* - * Allocate & initalize the nodepda for each node. - */ - for (cnode=0; cnode < numnodes; cnode++) { - nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t)); + /* + * Allocate & initalize the nodepda for each node. + */ + for (cnode = 0; cnode < numnodes; cnode++) { + nodepdaindr[cnode] = + alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t)); memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); - } + memset(nodepdaindr[cnode]->phys_cpuid, -1, + sizeof(nodepdaindr[cnode]->phys_cpuid)); + } /* - * Now copy the array of nodepda pointers to each nodepda. + * Allocate & initialize nodepda for TIOs. For now, put them on node 0. */ - for (cnode=0; cnode < numionodes; cnode++) - memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr)); + for (cnode = numnodes; cnode < numionodes; cnode++) { + nodepdaindr[cnode] = + alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t)); + memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); + } + /* + * Now copy the array of nodepda pointers to each nodepda. + */ + for (cnode = 0; cnode < numionodes; cnode++) + memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, + sizeof(nodepdaindr)); /* * Set up IO related platform-dependent nodepda fields. @@ -409,8 +386,15 @@ sn_init_pdas(char **cmdline_p) * in nodepda. */ for (cnode = 0; cnode < numnodes; cnode++) { - init_platform_nodepda(nodepdaindr[cnode], cnode); - bte_init_node (nodepdaindr[cnode], cnode); + bte_init_node(nodepdaindr[cnode], cnode); + } + + /* + * Initialize the per node hubdev. This includes IO Nodes and + * headless/memless nodes. + */ + for (cnode = 0; cnode < numionodes; cnode++) { + hubdev_init_node(nodepdaindr[cnode], cnode); } } @@ -423,15 +407,16 @@ sn_init_pdas(char **cmdline_p) * Also sets up a few fields in the nodepda. Also known as * platform_cpu_init() by the ia64 machvec code. */ -void __init -sn_cpu_init(void) +void __init sn_cpu_init(void) { - int cpuid; - int cpuphyid; - int nasid; - int slice; - int cnode; - static int wars_have_been_checked; + int cpuid; + int cpuphyid; + int nasid; + int subnode; + int slice; + int cnode; + int i; + static int wars_have_been_checked; /* * The boot cpu makes this call again after platform initialization is @@ -441,22 +426,34 @@ sn_cpu_init(void) return; cpuid = smp_processor_id(); - cpuphyid = ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff); - nasid = cpu_physical_id_to_nasid(cpuphyid); + cpuphyid = get_sapicid(); + + if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice)) + BUG(); + + for (i=0; i < NR_NODES; i++) { + if (nodepdaindr[i]) { + nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid; + nodepdaindr[i]->phys_cpuid[cpuid].slice = slice; + nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode; + } + } + cnode = nasid_to_cnodeid(nasid); - slice = cpu_physical_id_to_slice(cpuphyid); memset(pda, 0, sizeof(pda)); pda->p_nodepda = nodepdaindr[cnode]; - pda->led_address = (typeof(pda->led_address)) (LED0 + (slice<led_address = + (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT)); pda->led_state = LED_ALWAYS_SET; - pda->hb_count = HZ/2; + pda->hb_count = HZ / 2; pda->hb_state = 0; pda->idle_flag = 0; - if (cpuid != 0){ - memcpy(pda->cnodeid_to_nasid_table, pdacpu(0)->cnodeid_to_nasid_table, - sizeof(pda->cnodeid_to_nasid_table)); + if (cpuid != 0) { + memcpy(pda->cnodeid_to_nasid_table, + pdacpu(0)->cnodeid_to_nasid_table, + sizeof(pda->cnodeid_to_nasid_table)); } /* @@ -470,30 +467,27 @@ sn_cpu_init(void) wars_have_been_checked = 1; } pda->shub_1_1_found = shub_1_1_found; - /* * We must use different memory allocators for first cpu (bootmem * allocator) than for the other cpus (regular allocator). */ - if (cpuid == 0) - irqpdaindr = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t)); - - memset(irqpdaindr, 0, sizeof(irqpda_t)); - irqpdaindr->irq_flags[SGI_PCIBR_ERROR] = SN2_IRQ_SHARED; - irqpdaindr->irq_flags[SGI_PCIBR_ERROR] |= SN2_IRQ_RESERVED; - irqpdaindr->irq_flags[SGI_II_ERROR] = SN2_IRQ_SHARED; - irqpdaindr->irq_flags[SGI_II_ERROR] |= SN2_IRQ_RESERVED; - pda->pio_write_status_addr = (volatile unsigned long *) - LOCAL_MMR_ADDR((slice < 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1 ) ); + LOCAL_MMR_ADDR((slice < + 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1)); pda->mem_write_status_addr = (volatile u64 *) - LOCAL_MMR_ADDR((slice < 2 ? SH_MEMORY_WRITE_STATUS_0 : SH_MEMORY_WRITE_STATUS_1 ) ); + LOCAL_MMR_ADDR((slice < + 2 ? SH_MEMORY_WRITE_STATUS_0 : + SH_MEMORY_WRITE_STATUS_1)); if (local_node_data->active_cpu_count++ == 0) { - int buddy_nasid; - buddy_nasid = cnodeid_to_nasid(numa_node_id() == numnodes-1 ? 0 : numa_node_id()+ 1); - pda->pio_shub_war_cam_addr = (volatile unsigned long*)GLOBAL_MMR_ADDR(nasid, SH_PI_CAM_CONTROL); + int buddy_nasid; + buddy_nasid = + cnodeid_to_nasid(numa_node_id() == + numnodes - 1 ? 0 : numa_node_id() + 1); + pda->pio_shub_war_cam_addr = + (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, + SH_PI_CAM_CONTROL); } } @@ -502,48 +496,53 @@ sn_cpu_init(void) * physical_node_map and the pda and increment numionodes. */ -static void __init -scan_for_ionodes(void) +static void __init scan_for_ionodes(void) { int nasid = 0; lboard_t *brd; /* Setup ionodes with memory */ - for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) { + for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { u64 klgraph_header; cnodeid_t cnodeid; - if (physical_node_map[nasid] == -1) + if (physical_node_map[nasid] == -1) continue; klgraph_header = cnodeid = -1; klgraph_header = ia64_sn_get_klconfig_addr(nasid); if (klgraph_header <= 0) { - if ( IS_RUNNING_ON_SIMULATOR() ) + if (IS_RUNNING_ON_SIMULATOR()) continue; - BUG(); /* All nodes must have klconfig tables! */ + BUG(); /* All nodes must have klconfig tables! */ } cnodeid = nasid_to_cnodeid(nasid); root_lboard[cnodeid] = (lboard_t *) - NODE_OFFSET_TO_LBOARD( (nasid), - ((kl_config_hdr_t *)(klgraph_header))-> - ch_board_info); + NODE_OFFSET_TO_LBOARD((nasid), + ((kl_config_hdr_t + *) (klgraph_header))-> + ch_board_info); } /* Scan headless/memless IO Nodes. */ - for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) { + for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { /* if there's no nasid, don't try to read the klconfig on the node */ - if (physical_node_map[nasid] == -1) continue; - brd = find_lboard_any((lboard_t *)root_lboard[nasid_to_cnodeid(nasid)], KLTYPE_SNIA); + if (physical_node_map[nasid] == -1) + continue; + brd = find_lboard_any((lboard_t *) + root_lboard[nasid_to_cnodeid(nasid)], + KLTYPE_SNIA); if (brd) { - brd = KLCF_NEXT_ANY(brd); /* Skip this node's lboard */ + brd = KLCF_NEXT_ANY(brd); /* Skip this node's lboard */ if (!brd) continue; } brd = find_lboard_any(brd, KLTYPE_SNIA); + while (brd) { - pda->cnodeid_to_nasid_table[numionodes] = brd->brd_nasid; + pda->cnodeid_to_nasid_table[numionodes] = + brd->brd_nasid; physical_node_map[brd->brd_nasid] = numionodes; root_lboard[numionodes] = brd; numionodes++; @@ -554,4 +553,39 @@ scan_for_ionodes(void) brd = find_lboard_any(brd, KLTYPE_SNIA); } } + + /* Scan for TIO nodes. */ + for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid += 2) { + /* if there's no nasid, don't try to read the klconfig on the node */ + if (physical_node_map[nasid] == -1) + continue; + brd = find_lboard_any((lboard_t *) + root_lboard[nasid_to_cnodeid(nasid)], + KLTYPE_TIO); + while (brd) { + pda->cnodeid_to_nasid_table[numionodes] = + brd->brd_nasid; + physical_node_map[brd->brd_nasid] = numionodes; + root_lboard[numionodes] = brd; + numionodes++; + brd = KLCF_NEXT_ANY(brd); + if (!brd) + break; + + brd = find_lboard_any(brd, KLTYPE_TIO); + } + } + +} + +int +nasid_slice_to_cpuid(int nasid, int slice) +{ + long cpu; + + for (cpu=0; cpu < NR_CPUS; cpu++) + if (nodepda->phys_cpuid[cpu].nasid == nasid && nodepda->phys_cpuid[cpu].slice == slice) + return cpu; + + return -1; } diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 0143b8182..170bde454 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile @@ -10,4 +10,4 @@ # obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ - prominfo_proc.o timer.o timer_interrupt.o + prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/arch/ia64/sn/kernel/sn2/io.c b/arch/ia64/sn/kernel/sn2/io.c index 37b4190b7..a12c0586d 100644 --- a/arch/ia64/sn/kernel/sn2/io.c +++ b/arch/ia64/sn/kernel/sn2/io.c @@ -9,7 +9,7 @@ * we wrap the inlines from asm/ia64/sn/sn2/io.h here. */ -#include +#include #ifdef CONFIG_IA64_GENERIC @@ -28,88 +28,74 @@ #undef __sn_readl_relaxed #undef __sn_readq_relaxed -unsigned int -__sn_inb (unsigned long port) +unsigned int __sn_inb(unsigned long port) { return ___sn_inb(port); } -unsigned int -__sn_inw (unsigned long port) +unsigned int __sn_inw(unsigned long port) { return ___sn_inw(port); } -unsigned int -__sn_inl (unsigned long port) +unsigned int __sn_inl(unsigned long port) { return ___sn_inl(port); } -void -__sn_outb (unsigned char val, unsigned long port) +void __sn_outb(unsigned char val, unsigned long port) { ___sn_outb(val, port); } -void -__sn_outw (unsigned short val, unsigned long port) +void __sn_outw(unsigned short val, unsigned long port) { ___sn_outw(val, port); } -void -__sn_outl (unsigned int val, unsigned long port) +void __sn_outl(unsigned int val, unsigned long port) { ___sn_outl(val, port); } -unsigned char -__sn_readb (void *addr) +unsigned char __sn_readb(void __iomem *addr) { - return ___sn_readb (addr); + return ___sn_readb(addr); } -unsigned short -__sn_readw (void *addr) +unsigned short __sn_readw(void __iomem *addr) { - return ___sn_readw (addr); + return ___sn_readw(addr); } -unsigned int -__sn_readl (void *addr) +unsigned int __sn_readl(void __iomem *addr) { - return ___sn_readl (addr); + return ___sn_readl(addr); } -unsigned long -__sn_readq (void *addr) +unsigned long __sn_readq(void __iomem *addr) { - return ___sn_readq (addr); + return ___sn_readq(addr); } -unsigned char -__sn_readb_relaxed (void *addr) +unsigned char __sn_readb_relaxed(void __iomem *addr) { - return ___sn_readb_relaxed (addr); + return ___sn_readb_relaxed(addr); } -unsigned short -__sn_readw_relaxed (void *addr) +unsigned short __sn_readw_relaxed(void __iomem *addr) { - return ___sn_readw_relaxed (addr); + return ___sn_readw_relaxed(addr); } -unsigned int -__sn_readl_relaxed (void *addr) +unsigned int __sn_readl_relaxed(void __iomem *addr) { - return ___sn_readl_relaxed (addr); + return ___sn_readl_relaxed(addr); } -unsigned long -__sn_readq_relaxed (void *addr) +unsigned long __sn_readq_relaxed(void __iomem *addr) { - return ___sn_readq_relaxed (addr); + return ___sn_readq_relaxed(addr); } #endif diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index bcc938b28..fd569e702 100644 --- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c +++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c @@ -3,10 +3,10 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All Rights Reserved. * * Module to export the system's Firmware Interface Tables, including - * PROM revision numbers, in /proc + * PROM revision numbers and banners, in /proc */ #include #include @@ -14,41 +14,14 @@ #include #include #include -#include -#include - -/* to lookup nasids */ +#include #include +#include MODULE_DESCRIPTION("PROM version reporting for /proc"); MODULE_AUTHOR("Chad Talbott"); MODULE_LICENSE("GPL"); -#undef DEBUG_PROMINFO - -#define TRACE_PROMINFO - -#if defined(DEBUG_PROMINFO) -# define DPRINTK(x...) printk(KERN_DEBUG x) -#else -# define DPRINTK(x...) -#endif - -#if defined(TRACE_PROMINFO) && defined(DEBUG_PROMINFO) -# if defined(__GNUC__) -# define TRACE() printk(KERN_DEBUG "%s:%d:%s\n", \ - __FILE__, __LINE__, __FUNCTION__) -# else -# define TRACE() printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__) -# endif -#else -# define TRACE() -#endif - -/* Sub-regions determined by bits in Node Offset */ -#define LB_PROM_SPACE 0x0000000700000000ul /* Local LB PROM */ - -#define FIT_SIGNATURE 0x2020205f5449465ful /* Standard Intel FIT entry types */ #define FIT_ENTRY_FIT_HEADER 0x00 /* FIT header entry */ #define FIT_ENTRY_PAL_B 0x01 /* PAL_B entry */ @@ -81,37 +54,30 @@ MODULE_LICENSE("GPL"); #define FIT_TYPE(q) \ ((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK) -#define FIT_ENTRY(type, maj, min, size) \ - ((((unsigned long)(maj) & FIT_MAJOR_MASK) << FIT_MAJOR_SHIFT) | \ - (((unsigned long)(min) & FIT_MINOR_MASK) << FIT_MINOR_SHIFT) | \ - (((unsigned long)(type) & FIT_TYPE_MASK) << FIT_TYPE_SHIFT) | \ - (size)) - struct fit_type_map_t { - unsigned char type; - const char *name; + unsigned char type; + const char *name; }; static const struct fit_type_map_t fit_entry_types[] = { - { FIT_ENTRY_FIT_HEADER, "FIT Header" }, - { FIT_ENTRY_PAL_A_GEN, "Generic PAL_A" }, - { FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A" }, - { FIT_ENTRY_PAL_A, "PAL_A" }, - { FIT_ENTRY_PAL_B, "PAL_B" }, - { FIT_ENTRY_SAL_A, "SAL_A" }, - { FIT_ENTRY_SAL_B, "SAL_B" }, - { FIT_ENTRY_SALRUNTIME, "SAL runtime" }, - { FIT_ENTRY_EFI, "EFI" }, - { FIT_ENTRY_VMLINUX, "Embedded Linux" }, - { FIT_ENTRY_FPSWA, "Embedded FPSWA" }, - { FIT_ENTRY_UNUSED, "Unused" }, - { 0xff, "Error" }, + {FIT_ENTRY_FIT_HEADER, "FIT Header"}, + {FIT_ENTRY_PAL_A_GEN, "Generic PAL_A"}, + {FIT_ENTRY_PAL_A_PROC, "Processor-specific PAL_A"}, + {FIT_ENTRY_PAL_A, "PAL_A"}, + {FIT_ENTRY_PAL_B, "PAL_B"}, + {FIT_ENTRY_SAL_A, "SAL_A"}, + {FIT_ENTRY_SAL_B, "SAL_B"}, + {FIT_ENTRY_SALRUNTIME, "SAL runtime"}, + {FIT_ENTRY_EFI, "EFI"}, + {FIT_ENTRY_VMLINUX, "Embedded Linux"}, + {FIT_ENTRY_FPSWA, "Embedded FPSWA"}, + {FIT_ENTRY_UNUSED, "Unused"}, + {0xff, "Error"}, }; -static const char * -fit_type_name(unsigned char type) +static const char *fit_type_name(unsigned char type) { - struct fit_type_map_t const*mapp; + struct fit_type_map_t const *mapp; for (mapp = fit_entry_types; mapp->type != 0xff; mapp++) if (type == mapp->type) @@ -125,32 +91,34 @@ fit_type_name(unsigned char type) return "Unknown type"; } -/* These two routines read the FIT table directly from the FLASH PROM - * on a specific node. The PROM can only be accessed using aligned 64 - * bit reads, so we do that and then shift and mask the result to get - * at each field. - */ static int -dump_fit_entry(char *page, unsigned long *fentry) +get_fit_entry(unsigned long nasid, int index, unsigned long *fentry, + char *banner, int banlen) { - unsigned long q1, q2; - unsigned type; + return ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen); +} - TRACE(); - q1 = readq(fentry); - q2 = readq(fentry + 1); - type = FIT_TYPE(q2); +/* + * These two routines display the FIT table for each node. + */ +static int dump_fit_entry(char *page, unsigned long *fentry) +{ + unsigned type; + + type = FIT_TYPE(fentry[1]); return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n", type, fit_type_name(type), - FIT_MAJOR(q2), FIT_MINOR(q2), - q1, + FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]), + fentry[0], /* mult by sixteen to get size in bytes */ - (unsigned)q2 * 16); + (unsigned)(fentry[1] & 0xffffff) * 16); } -/* We assume that the fit table will be small enough that we can print + +/* + * We assume that the fit table will be small enough that we can print * the whole thing into one page. (This is true for our default 16kB * pages -- each entry is about 60 chars wide when printed.) I read * somewhere that the maximum size of the FIT is 128 entries, so we're @@ -158,55 +126,47 @@ dump_fit_entry(char *page, unsigned long *fentry) * anyway). */ static int -dump_fit(char *page, unsigned long *fit) +dump_fit(char *page, unsigned long nasid) { - unsigned long qw; - int nentries; - int fentry; + unsigned long fentry[2]; + int index; char *p; - TRACE(); - - DPRINTK("dumping fit from %p\n", (void *)fit); - - qw = readq(fit); - DPRINTK("FIT signature: %016lx (%.8s)\n", qw, (char *)&qw); - if (qw != FIT_SIGNATURE) - printk(KERN_WARNING "Unrecognized FIT signature"); - - qw = readq(fit + 1); - nentries = (unsigned)qw; - DPRINTK("number of fit entries: %u\n", nentries); - /* check that we won't overflow the page -- see comment above */ - BUG_ON(nentries * 60 > PAGE_SIZE); - p = page; - for (fentry = 0; fentry < nentries; fentry++) - /* each FIT entry is two 64 bit words */ - p += dump_fit_entry(p, fit + 2 * fentry); + for (index=0;;index++) { + BUG_ON(index * 60 > PAGE_SIZE); + if (get_fit_entry(nasid, index, fentry, NULL, 0)) + break; + p += dump_fit_entry(p, fentry); + } return p - page; } static int -dump_version(char *page, unsigned long *fit) +dump_version(char *page, unsigned long nasid) { - int nentries; - int fentry; - unsigned long qw; + unsigned long fentry[2]; + char banner[128]; + int index; + int len; + + for (index = 0; ; index++) { + if (get_fit_entry(nasid, index, fentry, banner, + sizeof(banner))) + return 0; + if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A) + break; + } - TRACE(); + len = sprintf(page, "%x.%02x\n", FIT_MAJOR(fentry[1]), + FIT_MINOR(fentry[1])); + page += len; - nentries = (unsigned)readq(fit + 1); - BUG_ON(nentries * 60 > PAGE_SIZE); + if (banner[0]) + len += snprintf(page, PAGE_SIZE-len, "%s\n", banner); - for (fentry = 0; fentry < nentries; fentry++) { - qw = readq(fit + 2 * fentry + 1); - if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A) - return sprintf(page, "%x.%02x\n", - FIT_MAJOR(qw), FIT_MINOR(qw)); - } - return 0; + return len; } /* same as in proc_misc.c */ @@ -214,11 +174,14 @@ static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) { - if (len <= off+count) *eof = 1; + if (len <= off + count) + *eof = 1; *start = page + off; len -= off; - if (len>count) len = count; - if (len<0) len = 0; + if (len > count) + len = count; + if (len < 0) + len = 0; return len; } @@ -228,8 +191,8 @@ read_version_entry(char *page, char **start, off_t off, int count, int *eof, { int len = 0; - /* data holds the pointer to this node's FIT */ - len = dump_version(page, (unsigned long *)data); + /* data holds the NASID of the node */ + len = dump_version(page, (unsigned long)data); len = proc_calc_metrics(page, start, off, count, eof, len); return len; } @@ -240,56 +203,13 @@ read_fit_entry(char *page, char **start, off_t off, int count, int *eof, { int len = 0; - /* data holds the pointer to this node's FIT */ - len = dump_fit(page, (unsigned long *)data); + /* data holds the NASID of the node */ + len = dump_fit(page, (unsigned long)data); len = proc_calc_metrics(page, start, off, count, eof, len); return len; } -/* this is a fake FIT that's used on the medusa simulator which - * doesn't usually run a complete PROM. - */ -#ifdef CONFIG_IA64_SGI_SN_SIM -static unsigned long fakefit[] = { - /* this is all we need to satisfy the code below */ - FIT_SIGNATURE, - FIT_ENTRY(FIT_ENTRY_FIT_HEADER, 0x02, 0x60, 2), - /* dump something arbitrary for - * /proc/sgi_prominfo/nodeX/version */ - 0xbadbeef00fa3ef17ul, - FIT_ENTRY(FIT_ENTRY_SAL_A, 0, 0x99, 0x100) -}; -#endif - -static unsigned long * -lookup_fit(int nasid) -{ - unsigned long *fitp; - unsigned long fit_paddr; - unsigned long *fit_vaddr; - -#ifdef CONFIG_IA64_SGI_SN_SIM - if (IS_RUNNING_ON_SIMULATOR()) - return fakefit; -#endif - - fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32); - DPRINTK("pointer to fit at %p\n", (void *)fitp); - fit_paddr = readq(fitp); - DPRINTK("fit pointer contains %lx\n", fit_paddr); - /* snag just the node-relative offset */ - fit_paddr &= ~0ul >> (63-35); - /* the pointer to the FIT is relative to IA-64 compatibility - * space. However, the PROM is mapped at a different offset - * in MMR space (both local and global) - */ - fit_paddr += 0x700000000; - fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr); - DPRINTK("fit at %p\n", (void *)fit_vaddr); - return fit_vaddr; -} - /* module entry points */ int __init prominfo_init(void); void __exit prominfo_exit(void); @@ -302,23 +222,17 @@ static struct proc_dir_entry *sgi_prominfo_entry; #define NODE_NAME_LEN 11 -int __init -prominfo_init(void) +int __init prominfo_init(void) { struct proc_dir_entry **entp; struct proc_dir_entry *p; cnodeid_t cnodeid; - nasid_t nasid; + unsigned long nasid; char name[NODE_NAME_LEN]; if (!ia64_platform_is("sn2")) return 0; - TRACE(); - - DPRINTK("running on cpu %d\n", smp_processor_id()); - DPRINTK("numnodes %d\n", numnodes); - proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *), GFP_KERNEL); @@ -332,12 +246,12 @@ prominfo_init(void) nasid = cnodeid_to_nasid(cnodeid); p = create_proc_read_entry( "fit", 0, *entp, read_fit_entry, - lookup_fit(nasid)); + (void *)nasid); if (p) p->owner = THIS_MODULE; p = create_proc_read_entry( "version", 0, *entp, read_version_entry, - lookup_fit(nasid)); + (void *)nasid); if (p) p->owner = THIS_MODULE; } @@ -345,18 +259,14 @@ prominfo_init(void) return 0; } -void __exit -prominfo_exit(void) +void __exit prominfo_exit(void) { struct proc_dir_entry **entp; unsigned cnodeid; char name[NODE_NAME_LEN]; - TRACE(); - for (cnodeid = 0, entp = proc_entries; - cnodeid < numnodes; - cnodeid++, entp++) { + cnodeid < numnodes; cnodeid++, entp++) { remove_proc_entry("fit", *entp); remove_proc_entry("version", *entp); sprintf(name, "node%d", cnodeid); diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S index 4bd638dc0..9cb2d7906 100644 --- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S +++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S @@ -3,10 +3,10 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. */ -#include +#include #define ZEROVAL 0x3f // "zero" value for outstanding PIO requests #define DEADLOCKBIT SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 3ee7c10af..0d425f7a8 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -29,46 +29,41 @@ #include #include #include -#include #include #include #include +#include #include -#include +#include #include #include void sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1); - static spinlock_t sn2_global_ptc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; static unsigned long sn2_ptc_deadlock_count; - -static inline unsigned long -wait_piowc(void) +static inline unsigned long wait_piowc(void) { volatile unsigned long *piows; - unsigned long ws; + unsigned long ws; piows = pda->pio_write_status_addr; do { ia64_mfa(); - } while (((ws = *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != - SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK); + } while (((ws = + *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != + SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK); return ws; } - -void -sn_tlb_migrate_finish(struct mm_struct *mm) +void sn_tlb_migrate_finish(struct mm_struct *mm) { if (mm == current->mm) flush_tlb_mm(mm); } - /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range * @start: start of virtual address range @@ -90,13 +85,14 @@ sn_tlb_migrate_finish(struct mm_struct *mm) */ void -sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) +sn2_global_tlb_purge(unsigned long start, unsigned long end, + unsigned long nbits) { - int i, cnode, mynasid, cpu, lcpu=0, nasid, flushed=0; - volatile unsigned long *ptc0, *ptc1; - unsigned long flags=0, data0, data1; - struct mm_struct *mm=current->active_mm; - short nasids[NR_NODES], nix; + int i, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; + volatile unsigned long *ptc0, *ptc1; + unsigned long flags = 0, data0, data1; + struct mm_struct *mm = current->active_mm; + short nasids[NR_NODES], nix; DECLARE_BITMAP(nodes_flushed, NR_NODES); bitmap_zero(nodes_flushed, NR_NODES); @@ -114,7 +110,7 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit if (likely(i == 1 && lcpu == smp_processor_id())) { do { - ia64_ptcl(start, nbits<<2); + ia64_ptcl(start, nbits << 2); start += (1UL << nbits); } while (start < end); ia64_srlz_i(); @@ -128,42 +124,42 @@ sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbit return; } - nix = 0; - for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; - cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) + for (cnode = find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; + cnode = find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) nasids[nix++] = cnodeid_to_nasid(cnode); + data0 = (1UL << SH_PTC_0_A_SHFT) | + (nbits << SH_PTC_0_PS_SHFT) | + ((ia64_get_rr(start) >> 8) << SH_PTC_0_RID_SHFT) | + (1UL << SH_PTC_0_START_SHFT); - data0 = (1UL<>8)<pio_write_status_addr; + ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0); + ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1); + piows = (long *)pda->pio_write_status_addr; mycnode = numa_node_id(); @@ -210,6 +206,7 @@ sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1) /** * sn_send_IPI_phys - send an IPI to a Nasid and slice + * @nasid: nasid to receive the interrupt (may be outside partition) * @physid: physical cpuid to receive the interrupt. * @vector: command to send * @delivery_mode: delivery mechanism @@ -224,34 +221,31 @@ sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1) * %IA64_IPI_DM_NMI - pend an NMI * %IA64_IPI_DM_INIT - pend an INIT interrupt */ -void -sn_send_IPI_phys(long physid, int vector, int delivery_mode) +void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode) { - long nasid, slice, val; - unsigned long flags=0; - volatile long *p; - - nasid = cpu_physical_id_to_nasid(physid); - slice = cpu_physical_id_to_slice(physid); + long val; + unsigned long flags = 0; + volatile long *p; - p = (long*)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT); - val = (1UL< #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include static void *sn_hwperf_salheap = NULL; static int sn_hwperf_obj_cnt = 0; @@ -80,21 +83,26 @@ out: static int sn_hwperf_geoid_to_cnode(char *location) { int cnode; - int mod, slot, slab; - int cmod, cslot, cslab; + geoid_t geoid; + moduleid_t module_id; + char type; + int rack, slot, slab; + int this_rack, this_slot, this_slab; - if (sscanf(location, "%03dc%02d#%d", &mod, &slot, &slab) != 3) + if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4) return -1; - for (cnode = 0; cnode < numnodes; cnode++) { - /* XXX: need a better way than this ... */ - if (sscanf(NODEPDA(cnode)->hwg_node_name, - "hw/module/%03dc%02d/slab/%d", &cmod, &cslot, &cslab) == 3) { - if (mod == cmod && slot == cslot && slab == cslab) - break; - } + + for (cnode = 0; cnode < numionodes; cnode++) { + geoid = cnodeid_get_geoid(cnode); + module_id = geo_module(geoid); + this_rack = MODULE_GET_RACK(module_id); + this_slot = MODULE_GET_BPOS(module_id); + this_slab = geo_slab(geoid); + if (rack == this_rack && slot == this_slot && slab == this_slab) + break; } - return cnode < numnodes ? cnode : -1; + return cnode < numionodes ? cnode : -1; } static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) @@ -113,52 +121,35 @@ static int sn_hwperf_generic_ordinal(struct sn_hwperf_object_info *obj, for (ordinal=0, p=objs; p != obj; p++) { if (SN_HWPERF_FOREIGN(p)) continue; - if (p->location[3] == obj->location[3]) + if (SN_HWPERF_SAME_OBJTYPE(p, obj)) ordinal++; } return ordinal; } -#ifndef MODULE_IOBRICK -/* this will be available when ioif TIO support is added */ -#define MODULE_IOBRICK (MODULE_OPUSBRICK+1) -#endif +static const char *slabname_node = "node"; /* SHub asic */ +static const char *slabname_ionode = "ionode"; /* TIO asic */ +static const char *slabname_router = "router"; /* NL3R or NL4R */ +static const char *slabname_other = "other"; /* unknown asic */ -static const char *sn_hwperf_get_brickname(struct sn_hwperf_object_info *obj, - struct sn_hwperf_object_info *objs, int *ordinal) +static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj, + struct sn_hwperf_object_info *objs, int *ordinal) { - int i; - const char *objtype = NULL; + int isnode; + const char *slabname = slabname_other; - for (i=0; i < MAX_BRICK_TYPES; i++) { - if (brick_types[i] != obj->location[3]) - continue; - switch (i) { - case MODULE_CBRICK: - objtype = "node"; - *ordinal = sn_hwperf_obj_to_cnode(obj); /* cnodeid */ - break; - - case MODULE_RBRICK: - objtype = "router"; - *ordinal = sn_hwperf_generic_ordinal(obj, objs); - break; - - case MODULE_IOBRICK: - objtype = "ionode"; - *ordinal = sn_hwperf_generic_ordinal(obj, objs); - break; - } - break; + if ((isnode = SN_HWPERF_IS_NODE(obj)) || SN_HWPERF_IS_IONODE(obj)) { + slabname = isnode ? slabname_node : slabname_ionode; + *ordinal = sn_hwperf_obj_to_cnode(obj); } - - if (i == MAX_BRICK_TYPES) { - objtype = "other"; + else { *ordinal = sn_hwperf_generic_ordinal(obj, objs); + if (SN_HWPERF_IS_ROUTER(obj)) + slabname = slabname_router; } - return objtype; + return slabname; } static int sn_topology_show(struct seq_file *s, void *d) @@ -168,7 +159,7 @@ static int sn_topology_show(struct seq_file *s, void *d) int e; int i; int j; - const char *brickname; + const char *slabname; int ordinal; cpumask_t cpumask; char slice; @@ -194,22 +185,22 @@ static int sn_topology_show(struct seq_file *s, void *d) obj->name[i] = '_'; } - brickname = sn_hwperf_get_brickname(obj, objs, &ordinal); - seq_printf(s, "%s %d %s %s asic %s", brickname, ordinal, obj->location, + slabname = sn_hwperf_get_slabname(obj, objs, &ordinal); + seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, obj->sn_hwp_this_part ? "local" : "shared", obj->name); - if (obj->location[3] != 'c') + if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) seq_putc(s, '\n'); else { seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal)); - for (i=0; i < numnodes; i++) { + for (i=0; i < numionodes; i++) { seq_printf(s, i ? ":%d" : ", dist %d", node_distance(ordinal, i)); } seq_putc(s, '\n'); /* - * CPUs on this node + * CPUs on this node, if any */ cpumask = node_to_cpumask(ordinal); for_each_online_cpu(i) { @@ -253,11 +244,16 @@ static int sn_topology_show(struct seq_file *s, void *d) break; } } - if (i >= sn_hwperf_obj_cnt) - continue; seq_printf(s, "numalink %d %s-%d", ordinal+pt, obj->location, ptdata[pt].port); + if (i >= sn_hwperf_obj_cnt) { + /* no connection */ + seq_puts(s, " local endpoint disconnected" + ", protocol unknown\n"); + continue; + } + if (obj->sn_hwp_this_part && p->sn_hwp_this_part) /* both ends local to this partition */ seq_puts(s, " local"); @@ -276,9 +272,8 @@ static int sn_topology_show(struct seq_file *s, void *d) */ seq_printf(s, " endpoint %s-%d, protocol %s\n", p->location, ptdata[pt].conn_port, - strcmp(obj->name, "NL3Router") == 0 || - strcmp(p->name, "NL3Router") == 0 ? - "LLP3" : "LLP4"); + (SN_HWPERF_IS_NL3ROUTER(obj) || + SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4"); } vfree(ptdata); } @@ -405,7 +400,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) r = -EINVAL; goto error; } - r = copy_from_user(&a, (const void *)arg, + r = copy_from_user(&a, (const void __user *)arg, sizeof(struct sn_hwperf_ioctl_args)); if (r != 0) { r = -EFAULT; @@ -426,7 +421,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) } if (op & SN_HWPERF_OP_MEM_COPYIN) { - r = copy_from_user(p, (const void *)a.ptr, a.sz); + r = copy_from_user(p, (const void __user *)a.ptr, a.sz); if (r != 0) { r = -EFAULT; goto error; @@ -473,7 +468,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) case SN_HWPERF_GET_NODE_NASID: if (a.sz != sizeof(u64) || - (node = a.arg) < 0 || node >= numnodes) { + (node = a.arg) < 0 || node >= numionodes) { r = -EINVAL; goto error; } @@ -526,7 +521,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) } if (op & SN_HWPERF_OP_MEM_COPYOUT) { - r = copy_to_user((void *)a.ptr, p, a.sz); + r = copy_to_user((void __user *)a.ptr, p, a.sz); if (r != 0) { r = -EFAULT; goto error; diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index 14840791a..6a80fca80 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c @@ -3,74 +3,47 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. */ #include #include #ifdef CONFIG_PROC_FS #include -#include +#include #include - -static int partition_id_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) { - - return sprintf(page, "%d\n", sn_local_partid()); +static int partition_id_show(struct seq_file *s, void *p) +{ + seq_printf(s, "%d\n", sn_local_partid()); + return 0; } -static struct proc_dir_entry * sgi_proc_dir; - -void -register_sn_partition_id(void) { - struct proc_dir_entry *entry; - - if (!sgi_proc_dir) { - sgi_proc_dir = proc_mkdir("sgi_sn", 0); - } - entry = create_proc_entry("partition_id", 0444, sgi_proc_dir); - if (entry) { - entry->nlink = 1; - entry->data = 0; - entry->read_proc = partition_id_read_proc; - entry->write_proc = NULL; - } +static int partition_id_open(struct inode *inode, struct file *file) +{ + return single_open(file, partition_id_show, NULL); } -static int -system_serial_number_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) { - return sprintf(page, "%s\n", sn_system_serial_number()); +static int system_serial_number_show(struct seq_file *s, void *p) +{ + seq_printf(s, "%s\n", sn_system_serial_number()); + return 0; } -static int -licenseID_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) { - return sprintf(page, "0x%lx\n",sn_partition_serial_number_val()); +static int system_serial_number_open(struct inode *inode, struct file *file) +{ + return single_open(file, system_serial_number_show, NULL); } -void -register_sn_serial_numbers(void) { - struct proc_dir_entry *entry; +static int licenseID_show(struct seq_file *s, void *p) +{ + seq_printf(s, "0x%lx\n", sn_partition_serial_number_val()); + return 0; +} - if (!sgi_proc_dir) { - sgi_proc_dir = proc_mkdir("sgi_sn", 0); - } - entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir); - if (entry) { - entry->nlink = 1; - entry->data = 0; - entry->read_proc = system_serial_number_read_proc; - entry->write_proc = NULL; - } - entry = create_proc_entry("licenseID", 0444, sgi_proc_dir); - if (entry) { - entry->nlink = 1; - entry->data = 0; - entry->read_proc = licenseID_read_proc; - entry->write_proc = NULL; - } +static int licenseID_open(struct inode *inode, struct file *file) +{ + return single_open(file, licenseID_show, NULL); } /* @@ -81,48 +54,96 @@ register_sn_serial_numbers(void) { */ int sn_force_interrupt_flag = 1; -static int -sn_force_interrupt_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) { - if (sn_force_interrupt_flag) { - return sprintf(page, "Force interrupt is enabled\n"); - } - return sprintf(page, "Force interrupt is disabled\n"); +static int sn_force_interrupt_show(struct seq_file *s, void *p) +{ + seq_printf(s, "Force interrupt is %s\n", + sn_force_interrupt_flag ? "enabled" : "disabled"); + return 0; } -static int -sn_force_interrupt_write_proc(struct file *file, const char *buffer, - unsigned long count, void *data) +static ssize_t sn_force_interrupt_write_proc(struct file *file, + const char __user *buffer, size_t count, loff_t *data) { - if (*buffer == '0') { - sn_force_interrupt_flag = 0; - } else { - sn_force_interrupt_flag = 1; - } - return 1; + char val; + + if (copy_from_user(&val, buffer, 1)) + return -EFAULT; + + sn_force_interrupt_flag = (val == '0') ? 0 : 1; + return count; } -void -register_sn_force_interrupt(void) { - struct proc_dir_entry *entry; +static int sn_force_interrupt_open(struct inode *inode, struct file *file) +{ + return single_open(file, sn_force_interrupt_show, NULL); +} - if (!sgi_proc_dir) { - sgi_proc_dir = proc_mkdir("sgi_sn", 0); - } - entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir); - if (entry) { - entry->nlink = 1; - entry->data = 0; - entry->read_proc = sn_force_interrupt_read_proc; - entry->write_proc = sn_force_interrupt_write_proc; +static int coherence_id_show(struct seq_file *s, void *p) +{ + seq_printf(s, "%d\n", partition_coherence_id()); + + return 0; +} + +static int coherence_id_open(struct inode *inode, struct file *file) +{ + return single_open(file, coherence_id_show, NULL); +} + +static struct proc_dir_entry *sn_procfs_create_entry( + const char *name, struct proc_dir_entry *parent, + int (*openfunc)(struct inode *, struct file *), + int (*releasefunc)(struct inode *, struct file *)) +{ + struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); + + if (e) { + e->proc_fops = (struct file_operations *)kmalloc( + sizeof(struct file_operations), GFP_KERNEL); + if (e->proc_fops) { + memset(e->proc_fops, 0, sizeof(struct file_operations)); + e->proc_fops->open = openfunc; + e->proc_fops->read = seq_read; + e->proc_fops->llseek = seq_lseek; + e->proc_fops->release = releasefunc; + } } + + return e; } -void -register_sn_procfs(void) { - register_sn_partition_id(); - register_sn_serial_numbers(); - register_sn_force_interrupt(); +/* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */ +extern int sn_topology_open(struct inode *, struct file *); +extern int sn_topology_release(struct inode *, struct file *); + +void register_sn_procfs(void) +{ + static struct proc_dir_entry *sgi_proc_dir = NULL; + struct proc_dir_entry *e; + + BUG_ON(sgi_proc_dir != NULL); + if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) + return; + + sn_procfs_create_entry("partition_id", sgi_proc_dir, + partition_id_open, single_release); + + sn_procfs_create_entry("system_serial_number", sgi_proc_dir, + system_serial_number_open, single_release); + + sn_procfs_create_entry("licenseID", sgi_proc_dir, + licenseID_open, single_release); + + e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, + sn_force_interrupt_open, single_release); + if (e) + e->proc_fops->write = sn_force_interrupt_write_proc; + + sn_procfs_create_entry("coherence_id", sgi_proc_dir, + coherence_id_open, single_release); + + sn_procfs_create_entry("sn_topology", sgi_proc_dir, + sn_topology_open, sn_topology_release); } #endif /* CONFIG_PROC_FS */ diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index 57844feea..8f6d49b45 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -15,62 +15,23 @@ #include #include +#include "shub.h" #include +#include #include - extern unsigned long sn_rtc_cycles_per_second; -static volatile unsigned long last_wall_rtc; - -static unsigned long rtc_offset; /* updated only when xtime write-lock is held! */ -static long rtc_nsecs_per_cycle; -static long rtc_per_timer_tick; - -static unsigned long -getoffset(void) -{ - return rtc_offset + (GET_RTC_COUNTER() - last_wall_rtc)*rtc_nsecs_per_cycle; -} - - -static void -update(long delta_nsec) -{ - unsigned long rtc_counter = GET_RTC_COUNTER(); - unsigned long offset = rtc_offset + (rtc_counter - last_wall_rtc)*rtc_nsecs_per_cycle; - - /* Be careful about signed/unsigned comparisons here: */ - if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) - rtc_offset = offset - delta_nsec; - else - rtc_offset = 0; - last_wall_rtc = rtc_counter; -} - - -static void -reset(void) -{ - rtc_offset = 0; - last_wall_rtc = GET_RTC_COUNTER(); -} - static struct time_interpolator sn2_interpolator = { - .get_offset = getoffset, - .update = update, - .reset = reset + .drift = -1, + .shift = 10, + .mask = (1LL << 55) - 1, + .source = TIME_SOURCE_MMIO64, + .addr = RTC_COUNTER_ADDR }; -void __init -sn_timer_init(void) +void __init sn_timer_init(void) { sn2_interpolator.frequency = sn_rtc_cycles_per_second; - sn2_interpolator.drift = -1; /* unknown */ register_time_interpolator(&sn2_interpolator); - - rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ; - rtc_nsecs_per_cycle = 1000000000 / sn_rtc_cycles_per_second; - - last_wall_rtc = GET_RTC_COUNTER(); } diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c index dd2c28413..a432b9345 100644 --- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c +++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c @@ -34,26 +34,27 @@ #include #include +#include "shub.h" #include extern void sn_lb_int_war_check(void); -extern irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); #define SN_LB_INT_WAR_INTERVAL 100 -void -sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* LED blinking */ if (!pda->hb_count--) { - pda->hb_count = HZ/2; - set_led_bits(pda->hb_state ^= LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT); + pda->hb_count = HZ / 2; + set_led_bits(pda->hb_state ^= + LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT); } if (enable_shub_wars_1_1()) { /* Bugfix code for SHUB 1.1 */ - if (pda->pio_shub_war_cam_addr) - *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; + if (pda->pio_shub_war_cam_addr) + *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; } if (pda->sn_lb_int_war_ticks == 0) sn_lb_int_war_check(); diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index bacc0b298..65d1194f9 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -3,7 +3,7 @@ # see Documentation/kbuild/kconfig-language.txt. # -mainmenu "Linux Kernel Configuration" +mainmenu "Linux/M32R Kernel Configuration" config M32R bool @@ -20,6 +20,10 @@ config GENERIC_ISA_DMA bool default y +#config GENERIC_HARDIRQS +# bool +# default y + source "init/Kconfig" @@ -189,6 +193,10 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config GENERIC_CALIBRATE_DELAY + bool + default y + config PREEMPT bool "Preemptible Kernel" help @@ -346,96 +354,10 @@ source "fs/Kconfig" source "arch/m32r/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_STACKOVERFLOW - bool "Check for stack overflows" - depends on DEBUG_KERNEL - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_IOVIRT - bool "Memory mapped I/O debugging" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_PAGEALLOC - bool "Page alloc debugging" - depends on DEBUG_KERNEL - help - Unmap pages from the kernel linear mapping after free_pages(). - This results in a large slowdown, but helps to find certain types - of memory corruptions. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -endmenu +source "arch/m32r/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile index 63ea62a5d..dd4418d84 100644 --- a/arch/m32r/Makefile +++ b/arch/m32r/Makefile @@ -5,7 +5,6 @@ LDFLAGS := OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -e startup_32 -LDFLAGS_BLOB := --format binary --oformat elf32-m32r CFLAGS += -pipe -fno-schedule-insns CFLAGS_KERNEL += -mmodel=medium @@ -42,6 +41,8 @@ boot := arch/m32r/boot .PHONY: zImage +all: zImage + zImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ @@ -51,5 +52,5 @@ archclean: $(Q)$(MAKE) $(clean)=$(boot) define archhelp - @echo ' zImage - Compressed kernel image (arch/m32r/boot/zImage)' + echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' endef diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile index a8f130d5e..994c9aa04 100644 --- a/arch/m32r/boot/compressed/Makefile +++ b/arch/m32r/boot/compressed/Makefile @@ -5,10 +5,10 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \ - m32r-sio.o piggy.o vmlinux.lds + piggy.o vmlinux.lds EXTRA_AFLAGS := -traditional -OBJECTS = $(obj)/head.o $(obj)/misc.o $(obj)/m32r_sio.o +OBJECTS = $(obj)/head.o $(obj)/misc.o # # IMAGE_OFFSET is the load offset of the compression loader @@ -28,8 +28,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.S FORCE - $(CPP) $(EXTRA_AFLAGS) -C -P -I include $< >$@ +CFLAGS_misc.o += -fpic LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T OBJCOPYFLAGS += -R .empty_zero_page diff --git a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S index 28de481bd..10b928ed0 100644 --- a/arch/m32r/boot/compressed/head.S +++ b/arch/m32r/boot/compressed/head.S @@ -13,20 +13,62 @@ #include #include + /* + * This code can be loaded anywhere, as long as output will not + * overlap it. + * + * NOTE: This head.S should *NOT* be compiled with -fpic. + * + */ + .global startup + .global __bss_start, _ebss, end, zimage_data, zimage_len __ALIGN startup: ldi r0, #0x0000 /* SPI, disable EI */ mvtc r0, psw + ldi r12, #-8 + bl 1f + .fillinsn +1: + seth r1, #high(CONFIG_MEMORY_START + 0x00400000) /* Start address */ + add r12, r14 /* Real address */ + sub r12, r1 /* difference */ + + .global got_len + seth r3, #high(_GLOBAL_OFFSET_TABLE_+8) + or3 r3, r3, #low(_GLOBAL_OFFSET_TABLE_+12) + add r3, r14 + + /* Update the contents of global offset table */ + ldi r1, #low(got_len) + srli r1, #2 + beqz r1, 2f + .fillinsn +1: + ld r2, @r3 + add r2, r12 + st r2, @r3 + addi r3, #4 + addi r1, #-1 + bnez r1, 1b + .fillinsn +2: + /* XXX: resolve plt */ + /* * Clear BSS first so that there are no surprises... */ #ifdef CONFIG_ISA_DUAL_ISSUE + seth r2, #high(__bss_start) + or3 r2, r2, #low(__bss_start) + add r2, r12 + seth r3, #high(_ebss) + or3 r3, r3, #low(_ebss) + add r3, r12 + sub r3, r2 - LDIMM (r2, __bss_start) - LDIMM (r3, _end) - sub r3, r2 ; BSS size in bytes ; R4 = BSS size in longwords (rounded down) mv r4, r3 || ldi r1, #0 srli r4, #4 || addi r2, #-4 @@ -52,10 +94,13 @@ startup: .Lendloop2: #else /* not CONFIG_ISA_DUAL_ISSUE */ - - LDIMM (r2, __bss_start) - LDIMM (r3, _end) - sub r3, r2 ; BSS size in bytes + seth r2, #high(__bss_start) + or3 r2, r2, #low(__bss_start) + add r2, r12 + seth r3, #high(_ebss) + or3 r3, r3, #low(_ebss) + add r3, r12 + sub r3, r2 mv r4, r3 srli r4, #2 ; R4 = BSS size in longwords (rounded down) ldi r1, #0 ; clear R1 for longwords store @@ -66,27 +111,29 @@ startup: addi r4, #-1 ; decrement count bnez r4, .Lloop1 ; go do some more .Lendloop1: - and3 r4, r3, #3 ; get no. of remaining BSS bytes to clear - addi r2, #4 ; account for pre-inc store - beqz r4, .Lendloop2 ; any more to go? -.Lloop2: - stb r1, @r2 ; yep, zero out another byte - addi r2, #1 ; bump address - addi r4, #-1 ; decrement count - bnez r4, .Lloop2 ; go do some more -.Lendloop2: #endif /* not CONFIG_ISA_DUAL_ISSUE */ - seth r0, #shigh(stack_start) - ld sp, @(r0, low(stack_start)) /* set stack point */ + seth r1, #high(end) + or3 r1, r1, #low(end) + add r1, r12 + mv sp, r1 /* * decompress the kernel */ + mv r0, sp + srli r0, 31 /* MMU is ON or OFF */ + seth r1, #high(zimage_data) + or3 r1, r1, #low(zimage_data) + add r1, r12 + seth r2, #high(zimage_len) + or3 r2, r2, #low(zimage_len) + mv r3, sp + bl decompress_kernel -#if defined(CONFIG_CHIP_M32700) +#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_VDEC2) /* Cache flush */ ldi r0, -1 ldi r1, 0xd0 ; invalidate i-cache, copy back d-cache @@ -94,9 +141,14 @@ startup: #else #error "put your cache flush function, please" #endif - seth r0, #high(CONFIG_MEMORY_START) - or3 r0, r0, #0x2000 - jmp r0 + + mv r0, sp + srli r0, 31 /* MMU is ON or OFF */ + slli r0, 31 + or3 r0, r0, #0x2000 + seth r1, #high(CONFIG_MEMORY_START) + or r0, r1 + jmp r0 .balign 512 fake_headers_as_bzImage: diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c index 469c4dce5..bdfd1c283 100644 --- a/arch/m32r/boot/compressed/m32r_sio.c +++ b/arch/m32r/boot/compressed/m32r_sio.c @@ -6,12 +6,10 @@ */ #include -#include -#include -void putc(char c); +static void putc(char c); -int puts(const char *s) +static int puts(const char *s) { char c; while ((c = *s++)) putc(c); @@ -19,6 +17,9 @@ int puts(const char *s) } #if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) +#include +#include + #define USE_FPGA_MAP 0 #if USE_FPGA_MAP @@ -35,7 +36,7 @@ int puts(const char *s) #define BOOT_SIO0TXB PLD_ESIO0TXB #endif -void putc(char c) +static void putc(char c) { while ((*BOOT_SIO0STS & 0x3) != 0x3) ; @@ -46,8 +47,17 @@ void putc(char c) *BOOT_SIO0TXB = c; } #else -void putc(char c) +#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14) +#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30) + +static void putc(char c) { - /* do nothing */ + + while ((*SIO0STS & 0x1) == 0) ; + if (c == '\n') { + *SIO0TXB = '\r'; + while ((*SIO0STS & 0x1) == 0) ; + } + *SIO0TXB = c; } #endif diff --git a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c index 4661d38d9..70fa79900 100644 --- a/arch/m32r/boot/compressed/misc.c +++ b/arch/m32r/boot/compressed/misc.c @@ -8,8 +8,6 @@ * * Adapted for SH by Stuart Menefy, Aug 1999 * - * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000 - * * 2003-02-12: Support M32R by Takeo Takahashi * This is based on arch/sh/boot/compressed/misc.c. */ @@ -38,9 +36,9 @@ typedef unsigned long ulg; static uch *inbuf; /* input buffer */ static uch window[WSIZE]; /* Sliding window buffer */ -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ /* gzip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ @@ -76,24 +74,18 @@ static void error(char *m); static void gzip_mark(void **); static void gzip_release(void **); -extern char input_data[]; -extern int input_len; +static unsigned char *input_data; +static int input_len; -static long bytes_out; +static long bytes_out = 0; static uch *output_data; -static unsigned long output_ptr; +static unsigned long output_ptr = 0; +#include "m32r_sio.c" static void *malloc(int size); static void free(void *where); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -extern int puts(const char *); -extern int _text; /* Defined in vmlinux.lds.S */ -extern int _end; static unsigned long free_mem_ptr; static unsigned long free_mem_end_ptr; @@ -105,8 +97,8 @@ static void *malloc(int size) { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr == 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr == 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -114,7 +106,7 @@ static void *malloc(int size) free_mem_ptr += size; if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); + error("Out of memory"); return p; } @@ -159,7 +151,7 @@ void* memcpy(void* __dest, __const void* __src, static int fill_inbuf(void) { if (insize != 0) { - error("ran out of input data\n"); + error("ran out of input data"); } inbuf = input_data; @@ -199,25 +191,20 @@ static void error(char *x) while(1); /* Halt */ } -#define STACK_SIZE (4096) -long user_stack [STACK_SIZE]; -long* stack_start = &user_stack[STACK_SIZE]; - /* return decompressed size */ -long decompress_kernel(void) +void +decompress_kernel(int mmu_on, unsigned char *zimage_data, + unsigned int zimage_len, unsigned long heap) { - insize = 0; - inptr = 0; - bytes_out = 0; - outcnt = 0; - output_data = 0; - output_ptr = CONFIG_MEMORY_START + 0x2000; - free_mem_ptr = (unsigned long)&_end; + output_data = (unsigned char *)CONFIG_MEMORY_START + 0x2000 + + (mmu_on ? 0x80000000 : 0); + free_mem_ptr = heap; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + input_data = zimage_data; + input_len = zimage_len; makecrc(); puts("Uncompressing Linux... "); gunzip(); puts("Ok, booting the kernel.\n"); - return bytes_out; } diff --git a/arch/m32r/boot/compressed/vmlinux.lds.S b/arch/m32r/boot/compressed/vmlinux.lds.S index 20a9e9450..a18431759 100644 --- a/arch/m32r/boot/compressed/vmlinux.lds.S +++ b/arch/m32r/boot/compressed/vmlinux.lds.S @@ -8,16 +8,24 @@ SECTIONS _text = .; .text : { *(.text) } = 0 - .rodata : { *(.rodata) } + .rodata : { *(.rodata) *(.rodata.*) } _etext = .; - . = ALIGN(32) + (. & (32 - 1)); + . = ALIGN(32 / 8); .data : { *(.data) } + . = ALIGN(32 / 8); + _got = .; + .got : { *(.got) _egot = .; *(.got.*) } _edata = .; . = ALIGN(32 / 8); __bss_start = .; - .bss : { *(.bss) } + .bss : { *(.bss) *(.sbss) } . = ALIGN(32 / 8); - _end = . ; + _ebss = .; + . = ALIGN(4096); + . += 4096; + end = . ; + + got_len = (_egot - _got); } diff --git a/arch/m32r/boot/compressed/vmlinux.scr b/arch/m32r/boot/compressed/vmlinux.scr index a08490360..924c7992c 100644 --- a/arch/m32r/boot/compressed/vmlinux.scr +++ b/arch/m32r/boot/compressed/vmlinux.scr @@ -1,9 +1,9 @@ SECTIONS { .data : { - input_len = .; - LONG(input_data_end - input_data) input_data = .; + zimage_data = .; *(.data) - input_data_end = .; + zimage_data_end = .; } + zimage_len = zimage_data_end - zimage_data; } diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S index 9be591710..1b95a8b8d 100644 --- a/arch/m32r/boot/setup.S +++ b/arch/m32r/boot/setup.S @@ -24,7 +24,7 @@ #define CPU_PARAMS boot_cpu_data #define M32R_MCICAR 0xfffffff0 #define M32R_MCDCAR 0xfffffff4 -#define M32R_MCCR 0xfffffffc +#define M32R_MCCR 0xfffffffc #define M32R_BSCR0 0xffffffd2 ;BSEL diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig index 984701b73..eeaad52c2 100644 --- a/arch/m32r/defconfig +++ b/arch/m32r/defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:49 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -11,10 +13,12 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +51,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -77,22 +85,6 @@ CONFIG_PREEMPT=y # CONFIG_HAVE_DEC_LOCK is not set # CONFIG_SMP is not set -# -# M32R drivers -# -# CONFIG_M32RPCC is not set -CONFIG_M32R_CFC=y -CONFIG_M32700UT_CFC=y -CONFIG_CFC_NUM=1 -# CONFIG_MTD_M32R is not set -CONFIG_M32R_SMC91111=y -CONFIG_M32700UT_DS1302=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -100,11 +92,20 @@ CONFIG_M32700UT_DS1302=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +# CONFIG_M32R_PCC is not set +CONFIG_M32R_CFC=y +CONFIG_M32R_CFC_NUM=1 # # PCI Hotplug Support @@ -151,6 +152,16 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -170,7 +181,6 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -213,9 +223,8 @@ CONFIG_SCSI_MULTI_LUN=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -271,6 +280,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -290,7 +302,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -307,7 +318,50 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_NE2000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -342,6 +396,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -355,7 +410,9 @@ CONFIG_SERIO_SERPORT=y # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -368,13 +425,12 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_M32R_SIO is not set +CONFIG_SERIAL_M32R_SIO=y +CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_SERIAL_M32R_PLDSIO=y -CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -387,6 +443,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set +CONFIG_DS1302=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -429,8 +486,8 @@ CONFIG_VIDEO_DEV=y # Video Adapters # # CONFIG_VIDEO_CPIA is not set -CONFIG_M32R_AR=y -CONFIG_M32R_AR_VGA=y +CONFIG_VIDEO_M32R_AR=y +CONFIG_VIDEO_M32R_AR_M64278=y # # Radio Adapters @@ -445,7 +502,28 @@ CONFIG_M32R_AR_VGA=y # # Graphics support # -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y # # Sound @@ -455,6 +533,8 @@ CONFIG_M32R_AR_VGA=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -482,6 +562,7 @@ CONFIG_REISERFS_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -515,6 +596,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -549,6 +631,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -620,6 +703,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c index 501b75581..371ba904e 100644 --- a/arch/m32r/kernel/io_m32700ut.c +++ b/arch/m32r/kernel/io_m32700ut.c @@ -1,5 +1,5 @@ /* - * linux/arch/m32r/kernel/io_mappi.c + * linux/arch/m32r/kernel/io_m32700ut.c * * Typical I/O routines for M32700UT board. * @@ -9,7 +9,6 @@ * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this * archive for more details. - * */ #include @@ -32,16 +31,16 @@ extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); #endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ -#define PORT2ADDR(port) _port2addr(port) -#define PORT2ADDR_USB(port) _port2addr_usb(port) +#define PORT2ADDR(port) _port2addr(port) +#define PORT2ADDR_USB(port) _port2addr_usb(port) -static __inline__ void *_port2addr(unsigned long port) +static inline void *_port2addr(unsigned long port) { return (void *)(port + NONCACHE_OFFSET); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) -static __inline__ void *__port2addr_ata(unsigned long port) +static inline void *__port2addr_ata(unsigned long port) { static int dummy_reg; @@ -67,16 +66,16 @@ static __inline__ void *__port2addr_ata(unsigned long port) */ #define LAN_IOSTART 0x300 #define LAN_IOEND 0x320 -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x10000000); } -static __inline__ void *_port2addr_usb(unsigned long port) +static inline void *_port2addr_usb(unsigned long port) { - return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000); + return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000); } -static __inline__ void delay(void) +static inline void delay(void) { __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); } @@ -87,29 +86,30 @@ static __inline__ void delay(void) #define PORT2ADDR_NE(port) _port2addr_ne(port) -static __inline__ unsigned char _ne_inb(void *portp) +static inline unsigned char _ne_inb(void *portp) { return *(volatile unsigned char *)portp; } -static __inline__ unsigned short _ne_inw(void *portp) +static inline unsigned short _ne_inw(void *portp) { return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); } -static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count) +static inline void _ne_insb(void *portp, void *addr, unsigned long count) { unsigned char *buf = (unsigned char *)addr; - while (count--) *buf++ = _ne_inb(portp); + while (count--) + *buf++ = _ne_inb(portp); } -static __inline__ void _ne_outb(unsigned char b, void *portp) +static inline void _ne_outb(unsigned char b, void *portp) { *(volatile unsigned char *)portp = b; } -static __inline__ void _ne_outw(unsigned short w, void *portp) +static inline void _ne_outw(unsigned short w, void *portp) { *(volatile unsigned short *)portp = cpu_to_le16(w); } @@ -126,9 +126,9 @@ unsigned char _inb(unsigned long port) #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif @@ -146,13 +146,13 @@ unsigned short _inw(unsigned long port) #endif #if defined(CONFIG_USB) else if(port >= 0x340 && port < 0x3a0) - return *(volatile unsigned short *)PORT2ADDR_USB(port); + return *(volatile unsigned short *)PORT2ADDR_USB(port); #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif return *(volatile unsigned short *)PORT2ADDR(port); @@ -162,9 +162,9 @@ unsigned long _inl(unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned long l; - pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); - return l; + unsigned long l; + pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); + return l; } else #endif return *(volatile unsigned long *)PORT2ADDR(port); @@ -184,9 +184,9 @@ unsigned char _inb_p(unsigned long port) #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif v = *(volatile unsigned char *)PORT2ADDR(port); @@ -208,15 +208,15 @@ unsigned short _inw_p(unsigned long port) } else #endif #if defined(CONFIG_USB) - if(port >= 0x340 && port < 0x3a0) - return *(volatile unsigned short *)PORT2ADDR_USB(port); + if(port >= 0x340 && port < 0x3a0) + return *(volatile unsigned short *)PORT2ADDR_USB(port); else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif v = *(volatile unsigned short *)PORT2ADDR(port); @@ -246,7 +246,7 @@ void _outb(unsigned char b, unsigned long port) #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -264,12 +264,12 @@ void _outw(unsigned short w, unsigned long port) #endif #if defined(CONFIG_USB) if(port >= 0x340 && port < 0x3a0) - *(volatile unsigned short *)PORT2ADDR_USB(port) = w; + *(volatile unsigned short *)PORT2ADDR_USB(port) = w; else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -279,7 +279,7 @@ void _outl(unsigned long l, unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); + pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); } else #endif *(volatile unsigned long *)PORT2ADDR(port) = l; @@ -297,7 +297,7 @@ void _outb_p(unsigned char b, unsigned long port) #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -316,13 +316,13 @@ void _outw_p(unsigned short w, unsigned long port) } else #endif #if defined(CONFIG_USB) - if(port >= 0x340 && port < 0x3a0) - *(volatile unsigned short *)PORT2ADDR_USB(port) = w; + if(port >= 0x340 && port < 0x3a0) + *(volatile unsigned short *)PORT2ADDR_USB(port) = w; else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -336,7 +336,7 @@ void _outl_p(unsigned long l, unsigned long port) delay(); } -void _insb(unsigned int port, void * addr, unsigned long count) +void _insb(unsigned int port, void *addr, unsigned long count) { if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_insb(PORT2ADDR_NE(port), addr, count); @@ -344,22 +344,25 @@ void _insb(unsigned int port, void * addr, unsigned long count) else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { unsigned char *buf = addr; unsigned char *portp = __port2addr_ata(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); } #endif else { unsigned char *buf = addr; unsigned char *portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } -void _insw(unsigned int port, void * addr, unsigned long count) +void _insw(unsigned int port, void *addr, unsigned long count) { unsigned short *buf = addr; unsigned short *portp; @@ -370,55 +373,64 @@ void _insw(unsigned int port, void * addr, unsigned long count) * from the DATA_REG. Do not swap the data. */ portp = PORT2ADDR_NE(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { portp = __port2addr_ata(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; #endif } else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } -void _insl(unsigned int port, void * addr, unsigned long count) +void _insl(unsigned int port, void *addr, unsigned long count) { unsigned long *buf = addr; unsigned long *portp; portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned long *)portp; + while (count--) + *buf++ = *(volatile unsigned long *)portp; } -void _outsb(unsigned int port, const void * addr, unsigned long count) +void _outsb(unsigned int port, const void *addr, unsigned long count) { const unsigned char *buf = addr; unsigned char *portp; if (port >= LAN_IOSTART && port < LAN_IOEND) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outb(*buf++, portp); + while (count--) + _ne_outb(*buf++, portp); #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { portp = __port2addr_ata(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; } } -void _outsw(unsigned int port, const void * addr, unsigned long count) +void _outsw(unsigned int port, const void *addr, unsigned long count) { const unsigned short *buf = addr; unsigned short *portp; @@ -429,27 +441,32 @@ void _outsw(unsigned int port, const void * addr, unsigned long count) * into the DATA_REG. Do not swap the data. */ portp = PORT2ADDR_NE(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { portp = __port2addr_ata(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; } } -void _outsl(unsigned int port, const void * addr, unsigned long count) +void _outsl(unsigned int port, const void *addr, unsigned long count) { const unsigned long *buf = addr; unsigned char *portp; portp = PORT2ADDR(port); - while(count--) *(volatile unsigned long *)portp = *buf++; + while (count--) + *(volatile unsigned long *)portp = *buf++; } diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c index 74aeca636..85688ffb5 100644 --- a/arch/m32r/kernel/io_mappi.c +++ b/arch/m32r/kernel/io_mappi.c @@ -7,15 +7,13 @@ * Hitoshi Yamamoto */ -/* $Id: io_mappi.c,v 1.9 2003/12/02 07:18:08 fujiwara Exp $ */ - #include #include #include #include #include -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) #include #define M32R_PCC_IOMAP_SIZE 0x1000 @@ -27,21 +25,21 @@ extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int); extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int); -#endif /* CONFIG_PCMCIA && CONFIG_M32RPCC */ +#endif /* CONFIG_PCMCIA && CONFIG_M32R_PCC */ #define PORT2ADDR(port) _port2addr(port) -static __inline__ void *_port2addr(unsigned long port) +static inline void *_port2addr(unsigned long port) { return (void *)(port + NONCACHE_OFFSET); } -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)((port<<1) + NONCACHE_OFFSET + 0x0C000000); } -static __inline__ void delay(void) +static inline void delay(void) { __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); } @@ -52,12 +50,12 @@ static __inline__ void delay(void) #define PORT2ADDR_NE(port) _port2addr_ne(port) -static __inline__ unsigned char _ne_inb(void *portp) +static inline unsigned char _ne_inb(void *portp) { return (unsigned char) *(volatile unsigned short *)portp; } -static __inline__ unsigned short _ne_inw(void *portp) +static inline unsigned short _ne_inw(void *portp) { unsigned short tmp; @@ -65,12 +63,12 @@ static __inline__ unsigned short _ne_inw(void *portp) return le16_to_cpu(tmp); } -static __inline__ void _ne_outb(unsigned char b, void *portp) +static inline void _ne_outb(unsigned char b, void *portp) { *(volatile unsigned short *)portp = (unsigned short)b; } -static __inline__ void _ne_outw(unsigned short w, void *portp) +static inline void _ne_outw(unsigned short w, void *portp) { *(volatile unsigned short *)portp = cpu_to_le16(w); } @@ -80,15 +78,15 @@ unsigned char _inb(unsigned long port) if (port >= 0x300 && port < 0x320) return _ne_inb(PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread(0, port, &b, sizeof(b), 1, 0); + return b; } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - unsigned char b; - pcc_ioread(1, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread(1, port, &b, sizeof(b), 1, 0); + return b; } else #endif @@ -100,15 +98,15 @@ unsigned short _inw(unsigned long port) if (port >= 0x300 && port < 0x320) return _ne_inw(PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread(0, port, &w, sizeof(w), 1, 0); + return w; } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - unsigned short w; - pcc_ioread(1, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread(1, port, &w, sizeof(w), 1, 0); + return w; } else #endif return *(volatile unsigned short *)PORT2ADDR(port); @@ -116,15 +114,15 @@ unsigned short _inw(unsigned long port) unsigned long _inl(unsigned long port) { -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned long l; - pcc_ioread(0, port, &l, sizeof(l), 1, 0); - return l; + unsigned long l; + pcc_ioread(0, port, &l, sizeof(l), 1, 0); + return l; } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - unsigned short l; - pcc_ioread(1, port, &l, sizeof(l), 1, 0); - return l; + unsigned short l; + pcc_ioread(1, port, &l, sizeof(l), 1, 0); + return l; } else #endif return *(volatile unsigned long *)PORT2ADDR(port); @@ -137,15 +135,15 @@ unsigned char _inb_p(unsigned long port) if (port >= 0x300 && port < 0x320) v = _ne_inb(PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread(0, port, &b, sizeof(b), 1, 0); + return b; } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - unsigned char b; - pcc_ioread(1, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread(1, port, &b, sizeof(b), 1, 0); + return b; } else #endif v = *(volatile unsigned char *)PORT2ADDR(port); @@ -161,15 +159,15 @@ unsigned short _inw_p(unsigned long port) if (port >= 0x300 && port < 0x320) v = _ne_inw(PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread(0, port, &w, sizeof(w), 1, 0); + return w; } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - unsigned short w; - pcc_ioread(1, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread(1, port, &w, sizeof(w), 1, 0); + return w; } else #endif v = *(volatile unsigned short *)PORT2ADDR(port); @@ -192,11 +190,11 @@ void _outb(unsigned char b, unsigned long port) if (port >= 0x300 && port < 0x320) _ne_outb(b, PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite(0, port, &b, sizeof(b), 1, 0); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, &b, sizeof(b), 1, 0); + pcc_iowrite(1, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -207,11 +205,11 @@ void _outw(unsigned short w, unsigned long port) if (port >= 0x300 && port < 0x320) _ne_outw(w, PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite(0, port, &w, sizeof(w), 1, 0); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, &w, sizeof(w), 1, 0); + pcc_iowrite(1, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -219,11 +217,11 @@ void _outw(unsigned short w, unsigned long port) void _outl(unsigned long l, unsigned long port) { -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, &l, sizeof(l), 1, 0); + pcc_iowrite(0, port, &l, sizeof(l), 1, 0); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, &l, sizeof(l), 1, 0); + pcc_iowrite(1, port, &l, sizeof(l), 1, 0); } else #endif *(volatile unsigned long *)PORT2ADDR(port) = l; @@ -234,11 +232,11 @@ void _outb_p(unsigned char b, unsigned long port) if (port >= 0x300 && port < 0x320) _ne_outb(b, PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite(0, port, &b, sizeof(b), 1, 0); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, &b, sizeof(b), 1, 0); + pcc_iowrite(1, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -251,11 +249,11 @@ void _outw_p(unsigned short w, unsigned long port) if (port >= 0x300 && port < 0x320) _ne_outw(w, PORT2ADDR_NE(port)); else -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite(0, port, &w, sizeof(w), 1, 0); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, &w, sizeof(w), 1, 0); + pcc_iowrite(1, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -269,100 +267,118 @@ void _outl_p(unsigned long l, unsigned long port) delay(); } -void _insb(unsigned int port, void * addr, unsigned long count) +void _insb(unsigned int port, void *addr, unsigned long count) { unsigned short *buf = addr; unsigned short *portp; if (port >= 0x300 && port < 0x320){ portp = PORT2ADDR_NE(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) + while (count--) + *buf++ = *(volatile unsigned char *)portp; +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread(0, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_ioread(0, port, (void *)addr, sizeof(unsigned char), + count, 1); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_ioread(1, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_ioread(1, port, (void *)addr, sizeof(unsigned char), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } -void _insw(unsigned int port, void * addr, unsigned long count) +void _insw(unsigned int port, void *addr, unsigned long count) { unsigned short *buf = addr; unsigned short *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) *buf++ = _ne_inw(portp); -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) + while (count--) + *buf++ = _ne_inw(portp); +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread(0, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_ioread(0, port, (void *)addr, sizeof(unsigned short), + count, 1); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_ioread(1, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_ioread(1, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } -void _insl(unsigned int port, void * addr, unsigned long count) +void _insl(unsigned int port, void *addr, unsigned long count) { unsigned long *buf = addr; unsigned long *portp; portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned long *)portp; + while (count--) + *buf++ = *(volatile unsigned long *)portp; } -void _outsb(unsigned int port, const void * addr, unsigned long count) +void _outsb(unsigned int port, const void *addr, unsigned long count) { const unsigned char *buf = addr; unsigned char *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outb(*buf++, portp); -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) + while (count--) + _ne_outb(*buf++, portp); +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char), + count, 1); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; } } -void _outsw(unsigned int port, const void * addr, unsigned long count) +void _outsw(unsigned int port, const void *addr, unsigned long count) { const unsigned short *buf = addr; unsigned short *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outw(*buf++, portp); -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC) + while (count--) + _ne_outw(*buf++, portp); +#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short), + count, 1); } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) { - pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; } } -void _outsl(unsigned int port, const void * addr, unsigned long count) +void _outsl(unsigned int port, const void *addr, unsigned long count) { const unsigned long *buf = addr; unsigned char *portp; portp = PORT2ADDR(port); - while(count--) *(volatile unsigned long *)portp = *buf++; + while (count--) + *(volatile unsigned long *)portp = *buf++; } diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c index 7705fb0bb..4182cd4f9 100644 --- a/arch/m32r/kernel/io_mappi2.c +++ b/arch/m32r/kernel/io_mappi2.c @@ -4,15 +4,14 @@ * Typical I/O routines for Mappi2 board. * * Copyright (c) 2001-2003 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Mamoru Sakugawa + * Hitoshi Yamamoto, Mamoru Sakugawa */ -/* $Id:$ */ - #include #include #include #include +#include #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) #include @@ -32,29 +31,50 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); #define PORT2ADDR_NE(port) _port2addr_ne(port) #define PORT2ADDR_USB(port) _port2addr_usb(port) -static __inline__ void *_port2addr(unsigned long port) +static inline void *_port2addr(unsigned long port) { return (void *)(port + NONCACHE_OFFSET); } #define LAN_IOSTART 0x300 #define LAN_IOEND 0x320 + +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +static inline void *__port2addr_ata(unsigned long port) +{ + static int dummy_reg; + + switch (port) { + case 0x1f0: return (void *)0xac002000; + case 0x1f1: return (void *)0xac012800; + case 0x1f2: return (void *)0xac012002; + case 0x1f3: return (void *)0xac012802; + case 0x1f4: return (void *)0xac012004; + case 0x1f5: return (void *)0xac012804; + case 0x1f6: return (void *)0xac012006; + case 0x1f7: return (void *)0xac012806; + case 0x3f6: return (void *)0xac01200e; + default: return (void *)&dummy_reg; + } +} +#endif + #ifdef CONFIG_CHIP_OPSP -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x10000000); } #else -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x04000000); } #endif -static __inline__ void *_port2addr_usb(unsigned long port) +static inline void *_port2addr_usb(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x14000000); } -static __inline__ void delay(void) +static inline void delay(void) { __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); } @@ -63,51 +83,48 @@ static __inline__ void delay(void) * NIC I/O function */ -static __inline__ unsigned char _ne_inb(void *portp) +static inline unsigned char _ne_inb(void *portp) { return (unsigned char) *(volatile unsigned char *)portp; } -static __inline__ unsigned short _ne_inw(void *portp) +static inline unsigned short _ne_inw(void *portp) { -#if 1 /* byte swap */ - unsigned short tmp,tmp2; - tmp = *(volatile unsigned short *)portp; - tmp2 = (tmp>>8|tmp<<8); - return tmp2; -#else - return *(volatile unsigned short *)portp; -#endif + return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); } -static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count) +static inline void _ne_insb(void *portp, void * addr, unsigned long count) { - unsigned short tmp; unsigned char *buf = addr; - tmp = *(volatile unsigned char *)portp; - while (count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } -static __inline__ void _ne_outb(unsigned char b, void *portp) +static inline void _ne_outb(unsigned char b, void *portp) { *(volatile unsigned char *)portp = (unsigned char)b; } -static __inline__ void _ne_outw(unsigned short w, void *portp) +static inline void _ne_outw(unsigned short w, void *portp) { - *(volatile unsigned short *)portp = (w>>8|w<<8); + *(volatile unsigned short *)portp = cpu_to_le16(w); } unsigned char _inb(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inb(PORT2ADDR_NE(port)); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned char *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif @@ -118,16 +135,21 @@ unsigned short _inw(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inw(PORT2ADDR_NE(port)); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned short *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_USB) - else if (port >= 0x340 && port < 0x3a0) - return *(volatile unsigned short *)PORT2ADDR_USB(port); + else if (port >= 0x340 && port < 0x3a0) + return *(volatile unsigned short *)PORT2ADDR_USB(port); #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif return *(volatile unsigned short *)PORT2ADDR(port); @@ -137,9 +159,9 @@ unsigned long _inl(unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned long l; - pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); - return l; + unsigned long l; + pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); + return l; } else #endif return *(volatile unsigned long *)PORT2ADDR(port); @@ -149,14 +171,19 @@ unsigned char _inb_p(unsigned long port) { unsigned char v; - if (port >= 0x300 && port < 0x320) + if (port >= LAN_IOSTART && port < LAN_IOEND) v = _ne_inb(PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned char *)__port2addr_ata(port); + } else +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif v = *(volatile unsigned char *)PORT2ADDR(port); @@ -169,19 +196,24 @@ unsigned short _inw_p(unsigned long port) { unsigned short v; - if (port >= 0x300 && port < 0x320) + if (port >= LAN_IOSTART && port < LAN_IOEND) v = _ne_inw(PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned short *)__port2addr_ata(port); + } else +#endif #if defined(CONFIG_USB) - if (port >= 0x340 && port < 0x3a0) + if (port >= 0x340 && port < 0x3a0) v = *(volatile unsigned short *)PORT2ADDR_USB(port); - else + else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif v = *(volatile unsigned short *)PORT2ADDR(port); @@ -204,9 +236,14 @@ void _outb(unsigned char b, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outb(b, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned char *)__port2addr_ata(port) = b; + } else +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -217,14 +254,19 @@ void _outw(unsigned short w, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outw(w, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned short *)__port2addr_ata(port) = w; + } else +#endif #if defined(CONFIG_USB) - if (port >= 0x340 && port < 0x3a0) - *(volatile unsigned short *)PORT2ADDR_USB(port) = w; + if (port >= 0x340 && port < 0x3a0) + *(volatile unsigned short *)PORT2ADDR_USB(port) = w; else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -234,7 +276,7 @@ void _outl(unsigned long l, unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); + pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); } else #endif *(volatile unsigned long *)PORT2ADDR(port) = l; @@ -245,9 +287,14 @@ void _outb_p(unsigned char b, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outb(b, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned char *)__port2addr_ata(port) = b; + } else +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -260,6 +307,11 @@ void _outw_p(unsigned short w, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outw(w, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned short *)__port2addr_ata(port) = w; + } else +#endif #if defined(CONFIG_USB) if (port >= 0x340 && port < 0x3a0) *(volatile unsigned short *)PORT2ADDR_USB(port) = w; @@ -267,7 +319,7 @@ void _outw_p(unsigned short w, unsigned long port) #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -285,15 +337,25 @@ void _insb(unsigned int port, void * addr, unsigned long count) { if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_insb(PORT2ADDR_NE(port), addr, count); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + unsigned char *buf = addr; + unsigned char *portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned char *)portp; + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); } #endif else { unsigned char *buf = addr; unsigned char *portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } @@ -302,16 +364,25 @@ void _insw(unsigned int port, void * addr, unsigned long count) unsigned short *buf = addr; unsigned short *portp; - if (port >= LAN_IOSTART && port < LAN_IOEND) + if (port >= LAN_IOSTART && port < LAN_IOEND) { portp = PORT2ADDR_NE(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); +#endif +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; #endif } else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } @@ -321,7 +392,8 @@ void _insl(unsigned int port, void * addr, unsigned long count) unsigned long *portp; portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned long *)portp; + while (count--) + *buf++ = *(volatile unsigned long *)portp; } void _outsb(unsigned int port, const void * addr, unsigned long count) @@ -329,16 +401,25 @@ void _outsb(unsigned int port, const void * addr, unsigned long count) const unsigned char *buf = addr; unsigned char *portp; - if (port >= LAN_IOSTART && port < LAN_IOEND) + if (port >= LAN_IOSTART && port < LAN_IOEND) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outb(*buf++, portp); + while (count--) + _ne_outb(*buf++, portp); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned char *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; } } @@ -347,16 +428,25 @@ void _outsw(unsigned int port, const void * addr, unsigned long count) const unsigned short *buf = addr; unsigned short *portp; - if (port >= LAN_IOSTART && port < LAN_IOEND) + if (port >= LAN_IOSTART && port < LAN_IOEND) { portp = PORT2ADDR_NE(port); - while (count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; } } @@ -366,5 +456,6 @@ void _outsl(unsigned int port, const void * addr, unsigned long count) unsigned char *portp; portp = PORT2ADDR(port); - while(count--) *(volatile unsigned long *)portp = *buf++; + while (count--) + *(volatile unsigned long *)portp = *buf++; } diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c index 7fcbf2047..286964794 100644 --- a/arch/m32r/kernel/io_oaks32r.c +++ b/arch/m32r/kernel/io_oaks32r.c @@ -4,11 +4,9 @@ * Typical I/O routines for OAKS32R board. * * Copyright (c) 2001-2004 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Mamoru Sakugawa + * Hitoshi Yamamoto, Mamoru Sakugawa */ -/* $Id$ */ - #include #include #include @@ -16,17 +14,17 @@ #define PORT2ADDR(port) _port2addr(port) -static __inline__ void *_port2addr(unsigned long port) +static inline void *_port2addr(unsigned long port) { return (void *)(port + NONCACHE_OFFSET); } -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)((port<<1) + NONCACHE_OFFSET + 0x02000000); } -static __inline__ void delay(void) +static inline void delay(void) { __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); } @@ -37,12 +35,12 @@ static __inline__ void delay(void) #define PORT2ADDR_NE(port) _port2addr_ne(port) -static __inline__ unsigned char _ne_inb(void *portp) +static inline unsigned char _ne_inb(void *portp) { return *(volatile unsigned char *)(portp+1); } -static __inline__ unsigned short _ne_inw(void *portp) +static inline unsigned short _ne_inw(void *portp) { unsigned short tmp; @@ -51,21 +49,22 @@ static __inline__ unsigned short _ne_inw(void *portp) return tmp; } -static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count) +static inline void _ne_insb(void *portp, void *addr, unsigned long count) { unsigned char *buf = addr; - while (count--) *buf++ = *(volatile unsigned char *)(portp+1); + while (count--) + *buf++ = *(volatile unsigned char *)(portp+1); } -static __inline__ void _ne_outb(unsigned char b, void *portp) +static inline void _ne_outb(unsigned char b, void *portp) { *(volatile unsigned char *)(portp+1) = b; } -static __inline__ void _ne_outw(unsigned short w, void *portp) +static inline void _ne_outw(unsigned short w, void *portp) { - *(volatile unsigned short *)portp = (w >> 8); - *(volatile unsigned short *)(portp+2) = (w & 0xff); + *(volatile unsigned short *)portp = (w >> 8); + *(volatile unsigned short *)(portp+2) = (w & 0xff); } unsigned char _inb(unsigned long port) @@ -171,73 +170,82 @@ void _outl_p(unsigned long l, unsigned long port) delay(); } -void _insb(unsigned int port, void * addr, unsigned long count) +void _insb(unsigned int port, void *addr, unsigned long count) { if (port >= 0x300 && port < 0x320) _ne_insb(PORT2ADDR_NE(port), addr, count); else { unsigned char *buf = addr; unsigned char *portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } -void _insw(unsigned int port, void * addr, unsigned long count) +void _insw(unsigned int port, void *addr, unsigned long count) { unsigned short *buf = addr; unsigned short *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) *buf++ = _ne_inw(portp); + while (count--) + *buf++ = _ne_inw(portp); } else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } -void _insl(unsigned int port, void * addr, unsigned long count) +void _insl(unsigned int port, void *addr, unsigned long count) { unsigned long *buf = addr; unsigned long *portp; portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned long *)portp; + while (count--) + *buf++ = *(volatile unsigned long *)portp; } -void _outsb(unsigned int port, const void * addr, unsigned long count) +void _outsb(unsigned int port, const void *addr, unsigned long count) { const unsigned char *buf = addr; unsigned char *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outb(*buf++, portp); + while (count--) + _ne_outb(*buf++, portp); } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; } } -void _outsw(unsigned int port, const void * addr, unsigned long count) +void _outsw(unsigned int port, const void *addr, unsigned long count) { const unsigned short *buf = addr; unsigned short *portp; if (port >= 0x300 && port < 0x320) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outw(*buf++, portp); + while (count--) + _ne_outw(*buf++, portp); } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; } } -void _outsl(unsigned int port, const void * addr, unsigned long count) +void _outsl(unsigned int port, const void *addr, unsigned long count) { const unsigned long *buf = addr; unsigned char *portp; portp = PORT2ADDR(port); - while(count--) *(volatile unsigned long *)portp = *buf++; + while (count--) + *(volatile unsigned long *)portp = *buf++; } diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c index 642376e3b..aaf42f9f7 100644 --- a/arch/m32r/kernel/io_opsput.c +++ b/arch/m32r/kernel/io_opsput.c @@ -9,7 +9,6 @@ * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this * archive for more details. - * */ #include @@ -35,7 +34,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); #define PORT2ADDR(port) _port2addr(port) #define PORT2ADDR_USB(port) _port2addr_usb(port) -static __inline__ void *_port2addr(unsigned long port) +static inline void *_port2addr(unsigned long port) { return (void *)(port + NONCACHE_OFFSET); } @@ -47,16 +46,16 @@ static __inline__ void *_port2addr(unsigned long port) */ #define LAN_IOSTART 0x300 #define LAN_IOEND 0x320 -static __inline__ void *_port2addr_ne(unsigned long port) +static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + NONCACHE_OFFSET + 0x10000000); } -static __inline__ void *_port2addr_usb(unsigned long port) +static inline void *_port2addr_usb(unsigned long port) { - return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000); + return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000); } -static __inline__ void delay(void) +static inline void delay(void) { __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); } @@ -67,29 +66,30 @@ static __inline__ void delay(void) #define PORT2ADDR_NE(port) _port2addr_ne(port) -static __inline__ unsigned char _ne_inb(void *portp) +static inline unsigned char _ne_inb(void *portp) { return *(volatile unsigned char *)portp; } -static __inline__ unsigned short _ne_inw(void *portp) +static inline unsigned short _ne_inw(void *portp) { return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); } -static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count) +static inline void _ne_insb(void *portp, void *addr, unsigned long count) { unsigned char *buf = (unsigned char *)addr; - while (count--) *buf++ = _ne_inb(portp); + while (count--) + *buf++ = _ne_inb(portp); } -static __inline__ void _ne_outb(unsigned char b, void *portp) +static inline void _ne_outb(unsigned char b, void *portp) { *(volatile unsigned char *)portp = b; } -static __inline__ void _ne_outw(unsigned short w, void *portp) +static inline void _ne_outw(unsigned short w, void *portp) { *(volatile unsigned short *)portp = cpu_to_le16(w); } @@ -101,9 +101,9 @@ unsigned char _inb(unsigned long port) #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif @@ -116,14 +116,14 @@ unsigned short _inw(unsigned long port) return _ne_inw(PORT2ADDR_NE(port)); #if defined(CONFIG_USB) else if(port >= 0x340 && port < 0x3a0) - return *(volatile unsigned short *)PORT2ADDR_USB(port); + return *(volatile unsigned short *)PORT2ADDR_USB(port); #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif return *(volatile unsigned short *)PORT2ADDR(port); @@ -133,9 +133,9 @@ unsigned long _inl(unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned long l; - pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); - return l; + unsigned long l; + pcc_ioread_word(0, port, &l, sizeof(l), 1, 0); + return l; } else #endif return *(volatile unsigned long *)PORT2ADDR(port); @@ -150,9 +150,9 @@ unsigned char _inb_p(unsigned long port) else #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned char b; - pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); - return b; + unsigned char b; + pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0); + return b; } else #endif v = *(volatile unsigned char *)PORT2ADDR(port); @@ -169,16 +169,16 @@ unsigned short _inw_p(unsigned long port) v = _ne_inw(PORT2ADDR_NE(port)); else #if defined(CONFIG_USB) - if(port >= 0x340 && port < 0x3a0) - return *(volatile unsigned short *)PORT2ADDR_USB(port); + if(port >= 0x340 && port < 0x3a0) + return *(volatile unsigned short *)PORT2ADDR_USB(port); else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - unsigned short w; - pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); - return w; + unsigned short w; + pcc_ioread_word(0, port, &w, sizeof(w), 1, 0); + return w; } else #endif v = *(volatile unsigned short *)PORT2ADDR(port); @@ -203,7 +203,7 @@ void _outb(unsigned char b, unsigned long port) else #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -216,13 +216,13 @@ void _outw(unsigned short w, unsigned long port) else #if defined(CONFIG_USB) if(port >= 0x340 && port < 0x3a0) - *(volatile unsigned short *)PORT2ADDR_USB(port) = w; + *(volatile unsigned short *)PORT2ADDR_USB(port) = w; else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -232,7 +232,7 @@ void _outl(unsigned long l, unsigned long port) { #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); + pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0); } else #endif *(volatile unsigned long *)PORT2ADDR(port) = l; @@ -245,7 +245,7 @@ void _outb_p(unsigned char b, unsigned long port) else #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); + pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); } else #endif *(volatile unsigned char *)PORT2ADDR(port) = b; @@ -259,14 +259,14 @@ void _outw_p(unsigned short w, unsigned long port) _ne_outw(w, PORT2ADDR_NE(port)); else #if defined(CONFIG_USB) - if(port >= 0x340 && port < 0x3a0) - *(volatile unsigned short *)PORT2ADDR_USB(port) = w; + if(port >= 0x340 && port < 0x3a0) + *(volatile unsigned short *)PORT2ADDR_USB(port) = w; else #endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); + pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0); } else #endif *(volatile unsigned short *)PORT2ADDR(port) = w; @@ -280,23 +280,25 @@ void _outl_p(unsigned long l, unsigned long port) delay(); } -void _insb(unsigned int port, void * addr, unsigned long count) +void _insb(unsigned int port, void *addr, unsigned long count) { if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_insb(PORT2ADDR_NE(port), addr, count); #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { + pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); } #endif else { unsigned char *buf = addr; unsigned char *portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } -void _insw(unsigned int port, void * addr, unsigned long count) +void _insw(unsigned int port, void *addr, unsigned long count) { unsigned short *buf = addr; unsigned short *portp; @@ -307,45 +309,52 @@ void _insw(unsigned int port, void * addr, unsigned long count) * from the DATA_REG. Do not swap the data. */ portp = PORT2ADDR_NE(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } -void _insl(unsigned int port, void * addr, unsigned long count) +void _insl(unsigned int port, void *addr, unsigned long count) { unsigned long *buf = addr; unsigned long *portp; portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned long *)portp; + while (count--) + *buf++ = *(volatile unsigned long *)portp; } -void _outsb(unsigned int port, const void * addr, unsigned long count) +void _outsb(unsigned int port, const void *addr, unsigned long count) { const unsigned char *buf = addr; unsigned char *portp; if (port >= LAN_IOSTART && port < LAN_IOEND) { portp = PORT2ADDR_NE(port); - while (count--) _ne_outb(*buf++, portp); + while (count--) + _ne_outb(*buf++, portp); #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1); + pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned char *)portp = *buf++; + while (count--) + *(volatile unsigned char *)portp = *buf++; } } -void _outsw(unsigned int port, const void * addr, unsigned long count) +void _outsw(unsigned int port, const void *addr, unsigned long count) { const unsigned short *buf = addr; unsigned short *portp; @@ -356,22 +365,26 @@ void _outsw(unsigned int port, const void * addr, unsigned long count) * into the DATA_REG. Do not swap the data. */ portp = PORT2ADDR_NE(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); + pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), + count, 1); #endif } else { portp = PORT2ADDR(port); - while(count--) *(volatile unsigned short *)portp = *buf++; + while (count--) + *(volatile unsigned short *)portp = *buf++; } } -void _outsl(unsigned int port, const void * addr, unsigned long count) +void _outsl(unsigned int port, const void *addr, unsigned long count) { const unsigned long *buf = addr; unsigned char *portp; portp = PORT2ADDR(port); - while(count--) *(volatile unsigned long *)portp = *buf++; + while (count--) + *(volatile unsigned long *)portp = *buf++; } diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c index cc77ced9f..27928a0b9 100644 --- a/arch/m32r/kernel/io_usrv.c +++ b/arch/m32r/kernel/io_usrv.c @@ -178,7 +178,8 @@ void _insb(unsigned int port, void * addr, unsigned long count) else { unsigned char *buf = addr; unsigned char *portp = PORT2ADDR(port); - while(count--) *buf++ = *(volatile unsigned char *)portp; + while (count--) + *buf++ = *(volatile unsigned char *)portp; } } @@ -192,7 +193,8 @@ void _insw(unsigned int port, void * addr, unsigned long count) 1); else { portp = PORT2ADDR(port); - while (count--) *buf++ = *(volatile unsigned short *)portp; + while (count--) + *buf++ = *(volatile unsigned short *)portp; } } diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c index ba1357733..74ab2ec74 100644 --- a/arch/m32r/kernel/irq.c +++ b/arch/m32r/kernel/irq.c @@ -42,12 +42,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 9e7de27a8..4723ce656 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -247,8 +247,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long spu, unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE; extern void ret_from_fork(void); - tsk->set_child_tid = tsk->clear_child_tid = NULL; - /* Copy registers */ sp -= sizeof (struct pt_regs); childregs = (struct pt_regs *)sp; @@ -335,8 +333,11 @@ asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, c goto out; error = do_execve(filename, uargv, uenvp, ®s); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: return error; diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index ab4137a33..6d58f972b 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -713,7 +713,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) ret = 0; unregister_all_debug_traps(child); invalidate_cache(); - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c index 5d0780b8b..488aa87ba 100644 --- a/arch/m32r/kernel/setup_m32700ut.c +++ b/arch/m32r/kernel/setup_m32700ut.c @@ -435,7 +435,7 @@ void __init init_IRQ(void) icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01; enable_m32700ut_irq(M32R_IRQ_INT2); -//#if defined(CONFIG_M32R_AR_VGA) +//#if defined(CONFIG_VIDEO_M32R_AR) /* * INT3# is used for AR */ @@ -445,7 +445,7 @@ void __init init_IRQ(void) irq_desc[M32R_IRQ_INT3].depth = 1; icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10; disable_m32700ut_irq(M32R_IRQ_INT3); -//#endif /* CONFIG_M32R_ARV */ +//#endif /* CONFIG_VIDEO_M32R_AR */ } #define LAN_IOSTART 0x300 diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c index 523cee330..1e74110f0 100644 --- a/arch/m32r/kernel/setup_mappi.c +++ b/arch/m32r/kernel/setup_mappi.c @@ -140,7 +140,7 @@ void __init init_IRQ(void) disable_mappi_irq(M32R_IRQ_SIO1_S); #endif /* CONFIG_SERIAL_M32R_SIO */ -#if defined(CONFIG_M32RPCC) +#if defined(CONFIG_M32R_PCC) /* INT1 : pccard0 interrupt */ irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED; irq_desc[M32R_IRQ_INT1].handler = &mappi_irq_type; diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c index 92eb06e85..1904d465a 100644 --- a/arch/m32r/kernel/setup_mappi2.c +++ b/arch/m32r/kernel/setup_mappi2.c @@ -151,7 +151,6 @@ void __init init_IRQ(void) disable_mappi2_irq(M32R_IRQ_INT1); #endif /* CONFIG_USB */ -#if defined(CONFIG_M32R_CFC) /* ICUCR40: CFC IREQ */ irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED; irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type; @@ -161,6 +160,7 @@ void __init init_IRQ(void) icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01; disable_mappi2_irq(PLD_IRQ_CFIREQ); +#if defined(CONFIG_M32R_CFC) /* ICUCR41: CFC Insert */ irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED; irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi2_irq_type; diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c index 17a4d3e52..84315e344 100644 --- a/arch/m32r/kernel/setup_opsput.c +++ b/arch/m32r/kernel/setup_opsput.c @@ -439,7 +439,7 @@ void __init init_IRQ(void) icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01; enable_opsput_irq(M32R_IRQ_INT2); -//#if defined(CONFIG_M32R_AR_VGA) +//#if defined(CONFIG_VIDEO_M32R_AR) /* * INT3# is used for AR */ @@ -449,7 +449,7 @@ void __init init_IRQ(void) irq_desc[M32R_IRQ_INT3].depth = 1; icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10; disable_opsput_irq(M32R_IRQ_INT3); -//#endif /* CONFIG_M32R_ARV */ +//#endif /* CONFIG_VIDEO_M32R_AR */ } #define LAN_IOSTART 0x300 diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 6ac4f705e..e80a6d58f 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -433,7 +433,7 @@ int __init start_secondary(void *unused) cpu_init(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) - rep_nop(); + cpu_relax(); smp_online(); @@ -482,7 +482,7 @@ static void __init smp_callin(void) /* Has the boot CPU finished it's STARTUP sequence ? */ if (cpu_isset(cpu_id, cpu_callout_map)) break; - rep_nop(); + cpu_relax(); } if (!time_before(jiffies, timeout)) { diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index f34fa19ac..435619e43 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -57,10 +57,10 @@ asmlinkage int sys_tas(int *addr) if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) return -EFAULT; - spin_lock(&tas_lock); + _raw_spin_lock(&tas_lock); oldval = *addr; *addr = 1; - spin_unlock(&tas_lock); + _raw_spin_unlock(&tas_lock); return oldval; } diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 25a31668f..3c4707280 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -193,7 +193,7 @@ EXPORT_SYMBOL(do_settimeofday); * BUG: This routine does not handle hour overflow properly; it just * sets the minutes. Usually you won't notice until after reboot! */ -static __inline__ int set_rtc_mmss(unsigned long nowtime) +static inline int set_rtc_mmss(unsigned long nowtime) { return 0; } @@ -205,11 +205,17 @@ static long last_rtc_update = 0; * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static __inline__ void do_timer_interrupt(int irq, void *dev_id, - struct pt_regs * regs) +static inline void +do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { +#ifndef CONFIG_SMP + profile_tick(CPU_PROFILING, regs); +#endif do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif /* * If we have an externally synchronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be @@ -241,10 +247,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) do_timer_interrupt(irq, NULL, regs); write_sequnlock(&xtime_lock); -#ifndef CONFIG_SMP - profile_tick(CPU_PROFILING, regs); -#endif - return IRQ_HANDLED; } @@ -273,8 +275,8 @@ void __init time_init(void) xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - wall_to_monotonic.tv_sec = -xtime.tv_sec; - wall_to_monotonic.tv_nsec = -xtime.tv_nsec; + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ @@ -314,4 +316,3 @@ unsigned long long sched_clock(void) { return (unsigned long long)jiffies * (1000000000 / HZ); } - diff --git a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c index 7afe66e9d..fb29632c7 100644 --- a/arch/m32r/lib/delay.c +++ b/arch/m32r/lib/delay.c @@ -51,7 +51,7 @@ void __delay(unsigned long loops) "addi %0, #-1 \n\t" "bgtz %0, 1b \n\t" " .fillinsn \n\t" - "2:i \n\t" + "2: \n\t" : "+r" (loops) : "r" (0) ); diff --git a/arch/m32r/lib/memset.S b/arch/m32r/lib/memset.S index 7fe94b6c6..6e26df120 100644 --- a/arch/m32r/lib/memset.S +++ b/arch/m32r/lib/memset.S @@ -70,16 +70,18 @@ qword_set_loop: st r1, @+r4 bnc qword_set_loop || cmpz r2 jc r14 -word_set_wrap: +set_remainder: cmpui r2, #4 - bc byte_set + bc byte_set_wrap1 addi r2, #-4 bra word_set_loop byte_set_wrap: addi r2, #4 - addi r4, #4 || cmpz r2 + cmpz r2 jc r14 +byte_set_wrap1: + addi r4, #4 #if defined(CONFIG_ISA_M32R2) byte_set: addi r2, #-1 || stb r1, @r4+ @@ -153,18 +155,19 @@ qword_set_loop: st r1, @+r4 st r1, @+r4 bnc qword_set_loop - bnez r2, word_set_wrap + bnez r2, set_remainder jmp r14 -word_set_wrap: +set_remainder: cmpui r2, #4 - bc byte_set + bc byte_set_wrap1 addi r2, #-4 bra word_set_loop byte_set_wrap: addi r2, #4 - addi r4, #4 beqz r2, end_memset +byte_set_wrap1: + addi r4, #4 byte_set: addi r2, #-1 stb r1, @r4 diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp index df7f9d01b..940b65139 100644 --- a/arch/m32r/m32700ut/defconfig.m32700ut.smp +++ b/arch/m32r/m32700ut/defconfig.m32700ut.smp @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:45 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -10,10 +12,12 @@ CONFIG_GENERIC_ISA_DMA=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -23,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -43,6 +50,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -80,22 +88,6 @@ CONFIG_CHIP_M32700_TS1=y CONFIG_NR_CPUS=2 # CONFIG_NUMA is not set -# -# M32R drivers -# -# CONFIG_M32RPCC is not set -CONFIG_M32R_CFC=y -CONFIG_M32700UT_CFC=y -CONFIG_CFC_NUM=1 -# CONFIG_MTD_M32R is not set -CONFIG_M32R_SMC91111=y -CONFIG_M32700UT_DS1302=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -103,11 +95,20 @@ CONFIG_M32700UT_DS1302=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +# CONFIG_M32R_PCC is not set +CONFIG_M32R_CFC=y +CONFIG_M32R_CFC_NUM=1 # # PCI Hotplug Support @@ -154,6 +155,16 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -173,7 +184,6 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -216,9 +226,8 @@ CONFIG_SCSI_MULTI_LUN=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -274,6 +283,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -293,7 +305,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -310,7 +321,50 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_NE2000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -345,6 +399,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -373,13 +428,12 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_M32R_SIO is not set +CONFIG_SERIAL_M32R_SIO=y +CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_SERIAL_M32R_PLDSIO=y -CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -392,6 +446,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set +CONFIG_DS1302=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -434,8 +489,8 @@ CONFIG_VIDEO_DEV=y # Video Adapters # # CONFIG_VIDEO_CPIA is not set -CONFIG_M32R_AR=y -CONFIG_M32R_AR_VGA=y +CONFIG_VIDEO_M32R_AR=y +CONFIG_VIDEO_M32R_AR_M64278=y # # Radio Adapters @@ -451,14 +506,14 @@ CONFIG_M32R_AR_VGA=y # Graphics support # CONFIG_FB=y -CONFIG_FB_EPSON_S1D13806=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y # CONFIG_FONTS is not set @@ -472,7 +527,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_M32R_CLUT224=y # # Sound @@ -482,6 +536,8 @@ CONFIG_LOGO_M32R_CLUT224=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -509,6 +565,7 @@ CONFIG_REISERFS_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -542,6 +599,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -576,6 +634,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -647,6 +706,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up index 5a9da73fb..eeaad52c2 100644 --- a/arch/m32r/m32700ut/defconfig.m32700ut.up +++ b/arch/m32r/m32700ut/defconfig.m32700ut.up @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:49 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -11,10 +13,12 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +51,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -77,22 +85,6 @@ CONFIG_PREEMPT=y # CONFIG_HAVE_DEC_LOCK is not set # CONFIG_SMP is not set -# -# M32R drivers -# -# CONFIG_M32RPCC is not set -CONFIG_M32R_CFC=y -CONFIG_M32700UT_CFC=y -CONFIG_CFC_NUM=1 -# CONFIG_MTD_M32R is not set -CONFIG_M32R_SMC91111=y -CONFIG_M32700UT_DS1302=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -100,11 +92,20 @@ CONFIG_M32700UT_DS1302=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +# CONFIG_M32R_PCC is not set +CONFIG_M32R_CFC=y +CONFIG_M32R_CFC_NUM=1 # # PCI Hotplug Support @@ -151,6 +152,16 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -170,7 +181,6 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -213,9 +223,8 @@ CONFIG_SCSI_MULTI_LUN=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -271,6 +280,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -290,7 +302,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -307,7 +318,50 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_NE2000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -342,6 +396,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -370,13 +425,12 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_M32R_SIO is not set +CONFIG_SERIAL_M32R_SIO=y +CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_SERIAL_M32R_PLDSIO=y -CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -389,6 +443,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set +CONFIG_DS1302=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -431,8 +486,8 @@ CONFIG_VIDEO_DEV=y # Video Adapters # # CONFIG_VIDEO_CPIA is not set -CONFIG_M32R_AR=y -CONFIG_M32R_AR_VGA=y +CONFIG_VIDEO_M32R_AR=y +CONFIG_VIDEO_M32R_AR_M64278=y # # Radio Adapters @@ -448,14 +503,14 @@ CONFIG_M32R_AR_VGA=y # Graphics support # CONFIG_FB=y -CONFIG_FB_EPSON_S1D13806=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y # CONFIG_FONTS is not set @@ -469,7 +524,6 @@ CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_M32R_CLUT224=y # # Sound @@ -479,6 +533,8 @@ CONFIG_LOGO_M32R_CLUT224=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -506,6 +562,7 @@ CONFIG_REISERFS_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -539,6 +596,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -573,6 +631,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -644,6 +703,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB b/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB index fa79cd9fb..525dab469 100644 --- a/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB +++ b/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB @@ -1,5 +1,5 @@ # .gdbinit file -# $Id: dot.gdbinit_200MHz_16MB,v 1.1 2004/08/17 02:58:11 takata Exp $ +# $Id: dot.gdbinit_200MHz_16MB,v 1.2 2004/10/20 03:02:27 fujiwara Exp $ #----- # NOTE: this file is generated by a script, "gen_gdbinit.pl". # (Please type "gen_gdbinit.pl --help" and check the help message). @@ -178,11 +178,11 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x08002000 + set $param = (void*)0x08001000 # INITRD_START - set *(unsigned long *)($param + 0x0010) = 0x082a0000 +# set *(unsigned long *)($param + 0x0010) = 0x08300000 # INITRD_SIZE - set *(unsigned long *)($param + 0x0014) = 0x00000000 +# set *(unsigned long *)($param + 0x0014) = 0x00000000 # M32R_CPUCLK set *(unsigned long *)($param + 0x0018) = 0d200000000 # M32R_BUSCLK @@ -191,15 +191,15 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0" + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0" end # Boot define boot set_kernel_parameters set $fp = 0 - set $pc = 0x08001000 - set *(unsigned char *)0xffffffff = 0x03 + set $pc = 0x08002000 +# set *(unsigned char *)0xffffffff = 0x03 si c end diff --git a/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB b/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB index 4df06e1d9..aa503657a 100644 --- a/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB +++ b/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB @@ -1,5 +1,5 @@ # .gdbinit file -# $Id: dot.gdbinit_300MHz_32MB,v 1.1 2004/08/17 02:58:11 takata Exp $ +# $Id: dot.gdbinit_300MHz_32MB,v 1.2 2004/10/20 03:02:27 fujiwara Exp $ #----- # NOTE: this file is generated by a script, "gen_gdbinit.pl". # (Please type "gen_gdbinit.pl --help" and check the help message). @@ -42,8 +42,8 @@ define sdram_init set *(unsigned long *)0x00ef602c = 0x00000020 # Ch0-TR set *(unsigned long *)0x00ef6028 = 0x00051502 - # Ch0-ADR (size:16MB) - set *(unsigned long *)0x00ef6020 = 0x08000002 + # Ch0-ADR (size:32MB) + set *(unsigned long *)0x00ef6020 = 0x08000003 # AutoRef On set *(unsigned long *)0x00ef6004 = 0x00010e24 # Access enable @@ -51,7 +51,7 @@ define sdram_init end document sdram_init SDRAM controller initialization - 0x08000000 - 0x08ffffff (16MB) + 0x08000000 - 0x09ffffff (32MB) end # Initialize BSEL3 for UT-CFC @@ -161,8 +161,8 @@ define setup shell sleep 0.1 clock_init shell sleep 0.1 - # SDRAM: 16MB - set *(unsigned long *)0x00ef6020 = 0x08000002 + # SDRAM: 32MB + set *(unsigned long *)0x00ef6020 = 0x08000003 cfc_init # USB set *(unsigned short *)0xb0301000 = 0x100 @@ -178,11 +178,11 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x08002000 + set $param = (void*)0x08001000 # INITRD_START - set *(unsigned long *)($param + 0x0010) = 0x082a0000 +# set *(unsigned long *)($param + 0x0010) = 0x08300000 # INITRD_SIZE - set *(unsigned long *)($param + 0x0014) = 0x00000000 +# set *(unsigned long *)($param + 0x0014) = 0x00000000 # M32R_CPUCLK set *(unsigned long *)($param + 0x0018) = 0d300000000 # M32R_BUSCLK @@ -191,15 +191,15 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0" + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=32M \0" end # Boot define boot set_kernel_parameters set $fp = 0 - set $pc = 0x08001000 - set *(unsigned char *)0xffffffff = 0x03 + set $pc = 0x08002000 +# set *(unsigned char *)0xffffffff = 0x03 si c end diff --git a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu index cae54bf18..429293ec6 100644 --- a/arch/m32r/mappi/defconfig.nommu +++ b/arch/m32r/mappi/defconfig.nommu @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:51 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -11,10 +13,12 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" # CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -22,17 +26,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -42,6 +49,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -75,17 +83,6 @@ CONFIG_PREEMPT=y # CONFIG_HAVE_DEC_LOCK is not set # CONFIG_SMP is not set -# -# M32R drivers -# -# CONFIG_M32RPCC is not set -CONFIG_M32R_NE2000=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -93,9 +90,18 @@ CONFIG_M32R_NE2000=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set +# CONFIG_TCIC is not set +CONFIG_M32R_PCC=y # # PCI Hotplug Support @@ -144,6 +150,16 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -199,6 +215,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -218,7 +237,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -235,7 +253,48 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set +CONFIG_NE2000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -270,6 +329,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -302,7 +362,6 @@ CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -323,6 +382,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_AGP is not set # CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set # CONFIG_RAW_DRIVER is not set # @@ -362,6 +426,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -381,6 +447,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -443,6 +510,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -514,6 +582,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp index b0fe57100..0bd354d87 100644 --- a/arch/m32r/mappi/defconfig.smp +++ b/arch/m32r/mappi/defconfig.smp @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:53 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -12,10 +14,12 @@ CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +51,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -83,17 +91,6 @@ CONFIG_CHIP_M32700_TS1=y CONFIG_NR_CPUS=2 # CONFIG_NUMA is not set -# -# M32R drivers -# -CONFIG_M32RPCC=y -CONFIG_M32R_NE2000=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -101,11 +98,18 @@ CONFIG_M32R_NE2000=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +CONFIG_M32R_PCC=y # # PCI Hotplug Support @@ -213,6 +217,16 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -231,7 +245,6 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -291,6 +304,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -310,7 +326,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -327,7 +342,48 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set +CONFIG_NE2000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -365,6 +421,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -397,7 +454,6 @@ CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -462,6 +518,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -481,6 +539,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -513,6 +572,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -558,6 +618,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -629,6 +690,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up index b4ab5ff29..a117915a9 100644 --- a/arch/m32r/mappi/defconfig.up +++ b/arch/m32r/mappi/defconfig.up @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:08:55 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -12,10 +14,12 @@ CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +51,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -79,17 +87,6 @@ CONFIG_PREEMPT=y # CONFIG_HAVE_DEC_LOCK is not set # CONFIG_SMP is not set -# -# M32R drivers -# -CONFIG_M32RPCC=y -CONFIG_M32R_NE2000=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -97,11 +94,18 @@ CONFIG_M32R_NE2000=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +CONFIG_M32R_PCC=y # # PCI Hotplug Support @@ -209,6 +213,16 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -227,7 +241,6 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -287,6 +300,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -306,7 +322,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -323,7 +338,48 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set +CONFIG_NE2000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -361,6 +417,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -393,7 +450,6 @@ CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -458,6 +514,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -477,6 +535,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -509,6 +568,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -554,6 +614,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -625,6 +686,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/mappi/dot.gdbinit b/arch/m32r/mappi/dot.gdbinit index ea566b691..7a1d29386 100644 --- a/arch/m32r/mappi/dot.gdbinit +++ b/arch/m32r/mappi/dot.gdbinit @@ -1,9 +1,9 @@ # .gdbinit file -# $Id$ +# $Id: dot.gdbinit.mappi,v 1.4 2004/10/20 02:24:37 takata Exp $ #----- # NOTE: this file is generated by a script, "gen_gdbinit.pl". # (Please type "gen_gdbinit.pl --help" and check the help message). -# $ Id: gen_gdbinit.pl,v 1.8 2004/02/27 07:08:32 takata Exp $ +# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $ #----- # target platform: mappi @@ -192,11 +192,11 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x08002000 + set $param = (void*)0x08001000 # INITRD_START - set *(unsigned long *)($param + 0x0010) = 0x082a0000 +# set *(unsigned long *)($param + 0x0010) = 0x08300000 # INITRD_SIZE - set *(unsigned long *)($param + 0x0014) = 0x00000000 +# set *(unsigned long *)($param + 0x0014) = 0x00000000 # M32R_CPUCLK set *(unsigned long *)($param + 0x0018) = 0d360000000 # M32R_BUSCLK @@ -205,14 +205,14 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" end # Boot define boot set_kernel_parameters set $fp = 0 - set $pc=0x08001000 + set $pc = 0x08002000 si c end @@ -236,7 +236,7 @@ sdireset file vmlinux target m32rsdi setup -#load_module +#load_modules #set_breakpoints #boot diff --git a/arch/m32r/mappi/dot.gdbinit.nommu b/arch/m32r/mappi/dot.gdbinit.nommu index 1ca03f872..297536cf6 100644 --- a/arch/m32r/mappi/dot.gdbinit.nommu +++ b/arch/m32r/mappi/dot.gdbinit.nommu @@ -192,7 +192,7 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x00002000 + set $param = (void*)0x00001000 # INITRD_START #set *(unsigned long *)($param + 0x0010) = 0x082a0000 # INITRD_SIZE @@ -205,14 +205,14 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.bbox-httpd nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.bbox-httpd nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" end # Boot define boot set_kernel_parameters set $fp = 0 - set $pc=0x00001000 + set $pc=0x00002000 set *(long *)0xfffffff4=0x8080 # b load_flat_binary # set *(unsigned char *)0x08001003=0x63 diff --git a/arch/m32r/mappi/dot.gdbinit.smp b/arch/m32r/mappi/dot.gdbinit.smp index db0274fef..171489a44 100644 --- a/arch/m32r/mappi/dot.gdbinit.smp +++ b/arch/m32r/mappi/dot.gdbinit.smp @@ -269,11 +269,11 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x08002000 + set $param = (void*)0x08001000 # INITRD_START # set *(unsigned long *)($param + 0x0010) = 0x082a0000 # INITRD_SIZE - set *(unsigned long *)($param + 0x0014) = 0x00000000 +# set *(unsigned long *)($param + 0x0014) = 0x00000000 # M32R_CPUCLK set *(unsigned long *)($param + 0x0018) = 0d160000000 # set *(unsigned long *)($param + 0x0018) = 0d80000000 @@ -284,14 +284,14 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=tty1 console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" + set {char[0x200]}($param + 0x100) = "console=tty1 console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" # set {char[0x200]}($param + 0x100) = "console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" end # Boot define boot set_kernel_parameters - set $pc=0x08001000 + set $pc=0x08002000 set *(unsigned char *)0x08001003=0x03 si c @@ -309,7 +309,7 @@ define boot_mp set *(unsigned long *)0x00eff2f8 = 0x2 x 0x00eff2f8 - set $pc=0x08001000 + set $pc=0x08002000 si c end @@ -320,7 +320,7 @@ end ## Boot UP define boot_up set_kernel_parameters - set $pc=0x08001000 + set $pc=0x08002000 si c end diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index a290e3793..b6a5aacea 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu index 816b53ee7..2239a9b9d 100644 --- a/arch/m32r/oaks32r/defconfig.nommu +++ b/arch/m32r/oaks32r/defconfig.nommu @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:09:00 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -11,10 +13,12 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" # CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -22,16 +26,19 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -41,6 +48,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -70,16 +78,6 @@ CONFIG_PREEMPT=y # CONFIG_HAVE_DEC_LOCK is not set # CONFIG_SMP is not set -# -# M32R drivers -# -CONFIG_M32R_NE2000=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -87,9 +85,13 @@ CONFIG_M32R_NE2000=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PC-card bridges # -# CONFIG_PCMCIA is not set # # PCI Hotplug Support @@ -138,6 +140,16 @@ CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -193,6 +205,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -212,7 +227,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -229,7 +243,43 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set +CONFIG_NE2000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -264,6 +314,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -296,7 +347,6 @@ CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -356,6 +406,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -375,6 +427,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -435,6 +488,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -506,6 +560,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/oaks32r/dot.gdbinit.nommu b/arch/m32r/oaks32r/dot.gdbinit.nommu index 48420f7e8..d481d972b 100644 --- a/arch/m32r/oaks32r/dot.gdbinit.nommu +++ b/arch/m32r/oaks32r/dot.gdbinit.nommu @@ -1,9 +1,9 @@ # .gdbinit file -# $Id: dot.gdbinit.oaks32r,v 1.2 2004/04/15 02:33:14 takata Exp $ +# $Id: dot.gdbinit.oaks32r,v 1.4 2004/10/20 02:24:37 takata Exp $ #----- # NOTE: this file is generated by a script, "gen_gdbinit.pl". # (Please type "gen_gdbinit.pl --help" and check the help message). -# $ Id: gen_gdbinit.pl,v 1.10 2004/04/15 02:10:45 takata Exp $ +# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $ #----- # target platform: oaks32r @@ -103,11 +103,11 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x01002000 + set $param = (void*)0x01001000 # INITRD_START - set *(unsigned long *)($param + 0x0010) = 0x00000000 +# set *(unsigned long *)($param + 0x0010) = 0x00000000 # INITRD_SIZE - set *(unsigned long *)($param + 0x0014) = 0x00000000 +# set *(unsigned long *)($param + 0x0014) = 0x00000000 # M32R_CPUCLK set *(unsigned long *)($param + 0x0018) = 0d66666667 # M32R_BUSCLK @@ -116,15 +116,14 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 -# set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.busybox.flat nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0" end # Boot define boot set_kernel_parameters set $fp = 0 - set $pc = 0x01001000 + set $pc = 0x01002000 si c end diff --git a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput index 07eae9601..4c80a037a 100644 --- a/arch/m32r/opsput/defconfig.opsput +++ b/arch/m32r/opsput/defconfig.opsput @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk21 +# Fri Nov 12 16:09:02 2004 # CONFIG_M32R=y CONFIG_UID16=y @@ -15,6 +17,7 @@ CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set # CONFIG_FUTEX is not set # CONFIG_EPOLL is not set -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +50,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -76,18 +83,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_PREEMPT is not set # CONFIG_SMP is not set -# -# M32R drivers -# -# CONFIG_M32R_CFC is not set -CONFIG_M32R_SMC91111=y -CONFIG_M32700UT_DS1302=y - -# -# Power management options (ACPI, APM) -# -# CONFIG_PM is not set - # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # @@ -95,11 +90,19 @@ CONFIG_M32700UT_DS1302=y # CONFIG_ISA is not set # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=y +CONFIG_PCCARD=y # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=y + +# +# PC-card bridges +# # CONFIG_TCIC is not set +CONFIG_M32R_CFC=y +CONFIG_M32R_CFC_NUM=1 # # PCI Hotplug Support @@ -147,6 +150,16 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -185,9 +198,8 @@ CONFIG_SCSI_MULTI_LUN=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -243,6 +255,9 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set @@ -262,7 +277,6 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -279,7 +293,50 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_NETDEVICES is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_NE2000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -314,6 +371,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -340,13 +398,12 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_M32R_SIO is not set +CONFIG_SERIAL_M32R_SIO=y +CONFIG_SERIAL_M32R_SIO_CONSOLE=y CONFIG_SERIAL_M32R_PLDSIO=y -CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -359,6 +416,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set +CONFIG_DS1302=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -411,6 +469,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -438,6 +498,7 @@ CONFIG_REISERFS_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -471,6 +532,7 @@ CONFIG_DEVFS_MOUNT=y # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -505,6 +567,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -583,6 +646,7 @@ CONFIG_DEBUG_INFO=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/m32r/opsput/dot.gdbinit b/arch/m32r/opsput/dot.gdbinit index 9883f001d..b7e6c6640 100644 --- a/arch/m32r/opsput/dot.gdbinit +++ b/arch/m32r/opsput/dot.gdbinit @@ -7,6 +7,39 @@ set radix 0d16 set height 0 debug_chaos +# clk xin:cpu:bus=1:8:1 +define clock_init_on_181 + set *(unsigned long *)0x00ef400c = 0x2 + set *(unsigned long *)0x00ef4004 = 0x1 + shell sleep 0.1 + set *(unsigned long *)0x00ef4000 = 0x101 +end +# clk xin:cpu:bus=1:8:2 +define clock_init_on_182 + set *(unsigned long *)0x00ef400c = 0x1 + set *(unsigned long *)0x00ef4004 = 0x1 + shell sleep 0.1 + set *(unsigned long *)0x00ef4000 = 0x101 +end + +# clk xin:cpu:bus=1:8:4 +define clock_init_on_184 + set *(unsigned long *)0x00ef400c = 0x0 + set *(unsigned long *)0x00ef4004 = 0x1 + shell sleep 0.1 + set *(unsigned long *)0x00ef4000 = 0x101 +end + +# clk xin:cpu:bus=1:1:1 +define clock_init_off + shell sleep 0.1 + set *(unsigned long *)0x00ef4000 = 0x0 + shell sleep 0.1 + set *(unsigned long *)0x00ef4004 = 0x0 + shell sleep 0.1 + set *(unsigned long *)0x00ef400c = 0x0 +end + define tlb_init set $tlbbase = 0xfe000000 set *(unsigned long *)($tlbbase + 0x04) = 0x0 @@ -83,7 +116,7 @@ end # Set kernel parameters define set_kernel_parameters - set $param = (void*)0x88002000 + set $param = (void*)0x88001000 # INITRD_START # set *(unsigned long *)($param + 0x0010) = 0x08300000 # INITRD_SIZE @@ -97,7 +130,7 @@ define set_kernel_parameters # M32R_TIMER_DIVIDE set *(unsigned long *)($param + 0x0020) = 0d128 - set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x\ + set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x console=tty1 \ root=/dev/nfsroot \ nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6 \ nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \ @@ -106,16 +139,11 @@ end define boot set_kernel_parameters - set $pc=0x88001000 + set $pc=0x88002000 set $fp=0 set $evb=0x88000000 - # I/D-Cache ON - -# IPI -# set *(long *)0x00eff2f8 = 0x2 - set $fp=0 -# set *(unsigned long *)0xa0ef4000 = 0x100 si + c end # Show TLB entries @@ -151,11 +179,29 @@ define show_regs printf "EVB[%08lx]\n",$evb end +define restart + sdireset + sdireset + en 1 + set $pc=0x0 + c + tlb_init + setup + load_modules + boot +end + define setup debug_chaos +# Clock +# shell sleep 0.1 +# clock_init_off +# shell sleep 1 +# clock_init_on_182 +# shell sleep 0.1 +# SDRAM set *(unsigned long *)0xa0ef6004 = 0x0001053f set *(unsigned long *)0xa0ef6028 = 0x00031102 -# set *(unsigned long *)0xa0ef400c = 0x2 end sdireset @@ -165,16 +211,8 @@ target m32rsdi set $pc=0x0 b *0x30000 c +dis 1 setup tlb_init load_modules -#set *(long *)0xa0ef4000=0x101 -#set *(long *)0xa0ef400c=0x002 - boot -#b tme_handler -b *0x88000020 - - - - diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 1fa88d5f3..567a46b1c 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -21,12 +21,10 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool - mainmenu "Linux/68k Kernel Configuration" source "init/Kconfig" - menu "Platform dependent setup" config EISA @@ -187,17 +185,19 @@ config BVME6000 drivers for SCSI, Ethernet and serial ports later on. config HP300 - bool "HP9000/300 support" + bool "HP9000/300 and HP9000/400 support" depends on !MMU_SUN3 help - This option enables support for the HP9000/300 series of - workstations. Support for these machines is still very experimental. - If you plan to try to use the kernel on such a machine say Y here. + This option enables support for the HP9000/300 and HP9000/400 series + of workstations. Support for these machines is still somewhat + experimental. If you plan to try to use the kernel on such a machine + say Y here. Everybody else says N. config DIO bool "DIO bus support" depends on HP300 + default y help Say Y here to enable support for the "DIO" expansion bus used in HP300 machines. If you are using such a system you almost certainly @@ -355,7 +355,6 @@ config 060_WRITETHROUGH endmenu - menu "General setup" source "fs/Kconfig.binfmt" @@ -447,7 +446,6 @@ endmenu source "drivers/Kconfig" - menu "Character devices" config ATARI_MFPSER @@ -586,11 +584,18 @@ config ADB_KEYBOARD config HPDCA tristate "HP DCA serial support" - depends on DIO + depends on DIO && SERIAL_8250 help If you want to use the internal "DCA" serial ports on an HP300 machine, say Y here. +config HPAPCI + tristate "HP APCI serial support" + depends on HP300 && SERIAL_8250 && EXPERIMENTAL + help + If you want to use the internal "APCI" serial ports on an HP400 + machine, say Y here. + config MVME147_SCC bool "SCC support for MVME147 serial ports" depends on MVME147 @@ -627,7 +632,7 @@ config DN_SERIAL config SERIAL_CONSOLE bool "Support for serial port console" - depends on (AMIGA || ATARI || MAC || HP300 || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || HPDCA=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL) + depends on (AMIGA || ATARI || MAC || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL) ---help--- If you say Y here, it will be possible to use a serial port as the system console (the system console is the device which receives all @@ -652,47 +657,10 @@ endmenu source "fs/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting" - depends on DEBUG_KERNEL - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -endmenu +source "arch/m68k/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index bc79771e8..466e7407a 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -28,7 +28,7 @@ ifdef CONFIG_SUN3 LDFLAGS_vmlinux = -N endif -CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include) +CHECKFLAGS += -D__mc68000__ # without -fno-strength-reduce the 53c7xx.c driver fails ;-( CFLAGS += -pipe -fno-strength-reduce -ffixed-a2 diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c index 151726c04..8888debf7 100644 --- a/arch/m68k/atari/hades-pci.c +++ b/arch/m68k/atari/hades-pci.c @@ -311,7 +311,7 @@ static void __init hades_fixup(int pci_modify) * Go through all devices, fixing up irqs as we see fit: */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) { diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig index 367125a02..89628d8d9 100644 --- a/arch/m68k/defconfig +++ b/arch/m68k/defconfig @@ -1,28 +1,63 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3-m68k +# Sun Dec 5 14:21:41 2004 # +CONFIG_M68K=y +CONFIG_MMU=y CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set # # Platform dependent setup # -# CONFIG_ISA is not set -# CONFIG_PCMCIA is not set +# CONFIG_SUN3 is not set CONFIG_AMIGA=y # CONFIG_ATARI is not set -# CONFIG_HADES is not set -# CONFIG_PCI is not set # CONFIG_MAC is not set # CONFIG_APOLLO is not set # CONFIG_VME is not set # CONFIG_HP300 is not set # CONFIG_SUN3X is not set -# CONFIG_SUN3 is not set # CONFIG_Q40 is not set # @@ -32,114 +67,89 @@ CONFIG_M68020=y CONFIG_M68030=y CONFIG_M68040=y # CONFIG_M68060 is not set +CONFIG_MMU_MOTOROLA=y # CONFIG_M68KFPU_EMU is not set # CONFIG_ADVANCED is not set # # General setup # -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_MISC is not set CONFIG_ZORRO=y # CONFIG_AMIGA_PCMCIA is not set # CONFIG_HEARTBEAT is not set CONFIG_PROC_HARDWARE=y -# CONFIG_PARPORT is not set -# CONFIG_PRINTER is not set +# CONFIG_ZORRO_NAMES is not set # -# Loadable module support +# Device Drivers # -# CONFIG_MODULES is not set # -# Block devices +# Generic Driver Options # -# CONFIG_BLK_DEV_FD is not set -CONFIG_AMIGA_FLOPPY=y -# CONFIG_AMIGA_Z2RAM is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # -# Networking options +# Memory Technology Devices (MTD) # -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -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_IP_ROUTER is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set -# CONFIG_SYN_COOKIES is not set +# CONFIG_MTD is not set # -# (it is safe to leave these untouched) +# Parallel port support # -# CONFIG_SKB_LARGE is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_PARPORT is not set # +# Plug and Play support # + # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set -# CONFIG_LLC is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set +# Block devices +# +CONFIG_AMIGA_FLOPPY=y +# CONFIG_AMIGA_Z2RAM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set # -# QoS and/or fair queueing +# IO Schedulers # -# CONFIG_NET_SCHED is not set +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y -CONFIG_ST_EXTRA_DEVS=2 +# CONFIG_CHR_DEV_OSST is not set CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 # CONFIG_CHR_DEV_SG is not set # @@ -149,11 +159,18 @@ CONFIG_SR_EXTRA_DEVS=2 CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set + # # SCSI low-level drivers # +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set CONFIG_A3000_SCSI=y -# CONFIG_A4000T_SCSI is not set CONFIG_A2091_SCSI=y CONFIG_GVP11_SCSI=y # CONFIG_CYBERSTORM_SCSI is not set @@ -161,107 +178,389 @@ CONFIG_GVP11_SCSI=y # CONFIG_BLZ2060_SCSI is not set # CONFIG_BLZ1230_SCSI is not set # CONFIG_FASTLANE_SCSI is not set -# CONFIG_A4091_SCSI is not set -# CONFIG_WARPENGINE_SCSI is not set -# CONFIG_BLZ603EPLUS_SCSI is not set # CONFIG_OKTAGON_SCSI is not set # -# Network device support +# Multi-device support (RAID and LVM) # +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +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_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set -# CONFIG_SLIP is not set -# CONFIG_PPP is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_ARIADNE is not set -# CONFIG_ZORRO8390 is not set -# CONFIG_A2065 is not set -# CONFIG_HYDRA is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_RAW is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_AMIGA is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_AMIGA is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_BUSMOUSE=y -CONFIG_AMIGA_BUILTIN_SERIAL=y -# CONFIG_GVPIOEXT is not set -# CONFIG_GVPIOEXT_LP is not set -# CONFIG_GVPIOEXT_PLIP is not set -# CONFIG_MULTIFACE_III_TTY is not set -# CONFIG_SUN3X_ZS is not set -# CONFIG_SUN_KEYBOARD is not set -# CONFIG_SUN_MOUSE is not set -# CONFIG_SBUS is not set -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_USERIAL is not set -# CONFIG_WATCHDOG is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_A2232 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set # -# Sound support +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +CONFIG_FB_AMIGA=y +CONFIG_FB_AMIGA_OCS=y +CONFIG_FB_AMIGA_ECS=y +CONFIG_FB_AMIGA_AGA=y +# CONFIG_FB_FM2 is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound # # CONFIG_SOUND is not set +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# Character devices +# +CONFIG_AMIGA_BUILTIN_SERIAL=y +# CONFIG_MULTIFACE_III_TTY is not set +# CONFIG_GVPIOEXT is not set +# CONFIG_SERIAL_CONSOLE is not set + # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_VFAT_FS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -CONFIG_MINIX_FS=y -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set # # Network File Systems # -# CONFIG_CODA_FS is not set CONFIG_NFS_FS=y -# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set -CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_AMIGA_PARTITION=y -CONFIG_NLS=y +CONFIG_MSDOS_PARTITION=y # # Native Language Support # +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -277,7 +576,15 @@ CONFIG_NLS_CODEPAGE_437=y # 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_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -285,44 +592,33 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_ISO8859_5 is not set # CONFIG_NLS_ISO8859_6 is not set # CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 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 +# Kernel hacking # -CONFIG_FB=y +# CONFIG_DEBUG_KERNEL is not set # -# Frame-buffer support +# Security options # -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set -CONFIG_FB_AMIGA=y -CONFIG_FB_AMIGA_OCS=y -CONFIG_FB_AMIGA_ECS=y -CONFIG_FB_AMIGA_AGA=y -# CONFIG_FB_CYBER is not set -# CONFIG_FB_VIRGE is not set -# CONFIG_FB_RETINAZ3 is not set -# CONFIG_FB_FM2 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=y -CONFIG_FBCON_AFB=y -CONFIG_FBCON_ILBM=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_FONT_PEARL_8x8=y +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set # -# Kernel hacking +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines # -# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index 31dcf1a39..a0b854f3f 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -8,55 +8,272 @@ */ #include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include +#include + +#include #include #include -#include /* hwreg_present() */ +#include /* readb() and writeb() */ +#include +#include #include "ints.h" #include "time.h" +unsigned long hp300_model; +unsigned long hp300_uart_scode = -1; +unsigned char ledstate; + +static char s_hp330[] __initdata = "330"; +static char s_hp340[] __initdata = "340"; +static char s_hp345[] __initdata = "345"; +static char s_hp360[] __initdata = "360"; +static char s_hp370[] __initdata = "370"; +static char s_hp375[] __initdata = "375"; +static char s_hp380[] __initdata = "380"; +static char s_hp385[] __initdata = "385"; +static char s_hp400[] __initdata = "400"; +static char s_hp425t[] __initdata = "425t"; +static char s_hp425s[] __initdata = "425s"; +static char s_hp425e[] __initdata = "425e"; +static char s_hp433t[] __initdata = "433t"; +static char s_hp433s[] __initdata = "433s"; +static char *hp300_models[] __initdata = { + [HP_320] = NULL, + [HP_330] = s_hp330, + [HP_340] = s_hp340, + [HP_345] = s_hp345, + [HP_350] = NULL, + [HP_360] = s_hp360, + [HP_370] = s_hp370, + [HP_375] = s_hp375, + [HP_380] = s_hp380, + [HP_385] = s_hp385, + [HP_400] = s_hp400, + [HP_425T] = s_hp425t, + [HP_425S] = s_hp425s, + [HP_425E] = s_hp425e, + [HP_433T] = s_hp433t, + [HP_433S] = s_hp433s, +}; + +static char hp300_model_name[13] = "HP9000/"; + extern void hp300_reset(void); extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *); extern int show_hp300_interrupts(struct seq_file *, void *); +#ifdef CONFIG_SERIAL_8250_CONSOLE +extern int hp300_setup_serial_console(void) __init; +#endif + +int __init hp300_parse_bootinfo(const struct bi_record *record) +{ + int unknown = 0; + const unsigned long *data = record->data; + + switch (record->tag) { + case BI_HP300_MODEL: + hp300_model = *data; + break; + + case BI_HP300_UART_SCODE: + hp300_uart_scode = *data; + break; + + case BI_HP300_UART_ADDR: + /* serial port address: ignored here */ + break; + + default: + unknown = 1; + } + + return unknown; +} #ifdef CONFIG_HEARTBEAT static void hp300_pulse(int x) { - if (x) - blinken_leds(0xfe); - else - blinken_leds(0xff); + if (x) + blinken_leds(0x10, 0); + else + blinken_leds(0, 0x10); } #endif static void hp300_get_model(char *model) { - strcpy(model, "HP9000/300"); + strcpy(model, hp300_model_name); +} + +#define RTCBASE 0xf0420000 +#define RTC_DATA 0x1 +#define RTC_CMD 0x3 + +#define RTC_BUSY 0x02 +#define RTC_DATA_RDY 0x01 + +#define rtc_busy() (in_8(RTCBASE + RTC_CMD) & RTC_BUSY) +#define rtc_data_available() (in_8(RTCBASE + RTC_CMD) & RTC_DATA_RDY) +#define rtc_status() (in_8(RTCBASE + RTC_CMD)) +#define rtc_command(x) out_8(RTCBASE + RTC_CMD, (x)) +#define rtc_read_data() (in_8(RTCBASE + RTC_DATA)) +#define rtc_write_data(x) out_8(RTCBASE + RTC_DATA, (x)) + +#define RTC_SETREG 0xe0 +#define RTC_WRITEREG 0xc2 +#define RTC_READREG 0xc3 + +#define RTC_REG_SEC2 0 +#define RTC_REG_SEC1 1 +#define RTC_REG_MIN2 2 +#define RTC_REG_MIN1 3 +#define RTC_REG_HOUR2 4 +#define RTC_REG_HOUR1 5 +#define RTC_REG_WDAY 6 +#define RTC_REG_DAY2 7 +#define RTC_REG_DAY1 8 +#define RTC_REG_MON2 9 +#define RTC_REG_MON1 10 +#define RTC_REG_YEAR2 11 +#define RTC_REG_YEAR1 12 + +#define RTC_HOUR1_24HMODE 0x8 + +#define RTC_STAT_MASK 0xf0 +#define RTC_STAT_RDY 0x40 + +static inline unsigned char hp300_rtc_read(unsigned char reg) +{ + unsigned char s, ret; + unsigned long flags; + + local_irq_save(flags); + + while (rtc_busy()); + rtc_command(RTC_SETREG); + while (rtc_busy()); + rtc_write_data(reg); + while (rtc_busy()); + rtc_command(RTC_READREG); + + do { + while (!rtc_data_available()); + s = rtc_status(); + ret = rtc_read_data(); + } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY); + + local_irq_restore(flags); + + return ret; +} + +static inline unsigned char hp300_rtc_write(unsigned char reg, + unsigned char val) +{ + unsigned char s, ret; + unsigned long flags; + + local_irq_save(flags); + + while (rtc_busy()); + rtc_command(RTC_SETREG); + while (rtc_busy()); + rtc_write_data((val << 4) | reg); + while (rtc_busy()); + rtc_command(RTC_WRITEREG); + while (rtc_busy()); + rtc_command(RTC_READREG); + + do { + while (!rtc_data_available()); + s = rtc_status(); + ret = rtc_read_data(); + } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY); + + local_irq_restore(flags); + + return ret; +} + +static int hp300_hwclk(int op, struct rtc_time *t) +{ + if (!op) { /* read */ + t->tm_sec = hp300_rtc_read(RTC_REG_SEC1) * 10 + + hp300_rtc_read(RTC_REG_SEC2); + t->tm_min = hp300_rtc_read(RTC_REG_MIN1) * 10 + + hp300_rtc_read(RTC_REG_MIN2); + t->tm_hour = (hp300_rtc_read(RTC_REG_HOUR1) & 3) * 10 + + hp300_rtc_read(RTC_REG_HOUR2); + t->tm_wday = -1; + t->tm_mday = hp300_rtc_read(RTC_REG_DAY1) * 10 + + hp300_rtc_read(RTC_REG_DAY2); + t->tm_mon = hp300_rtc_read(RTC_REG_MON1) * 10 + + hp300_rtc_read(RTC_REG_MON2) - 1; + t->tm_year = hp300_rtc_read(RTC_REG_YEAR1) * 10 + + hp300_rtc_read(RTC_REG_YEAR2); + if (t->tm_year <= 69) + t->tm_year += 100; + } else { + hp300_rtc_write(RTC_REG_SEC1, t->tm_sec / 10); + hp300_rtc_write(RTC_REG_SEC2, t->tm_sec % 10); + hp300_rtc_write(RTC_REG_MIN1, t->tm_min / 10); + hp300_rtc_write(RTC_REG_MIN2, t->tm_min % 10); + hp300_rtc_write(RTC_REG_HOUR1, + ((t->tm_hour / 10) & 3) | RTC_HOUR1_24HMODE); + hp300_rtc_write(RTC_REG_HOUR2, t->tm_hour % 10); + hp300_rtc_write(RTC_REG_DAY1, t->tm_mday / 10); + hp300_rtc_write(RTC_REG_DAY2, t->tm_mday % 10); + hp300_rtc_write(RTC_REG_MON1, (t->tm_mon + 1) / 10); + hp300_rtc_write(RTC_REG_MON2, (t->tm_mon + 1) % 10); + if (t->tm_year >= 100) + t->tm_year -= 100; + hp300_rtc_write(RTC_REG_YEAR1, t->tm_year / 10); + hp300_rtc_write(RTC_REG_YEAR2, t->tm_year % 10); + } + + return 0; +} + +static unsigned int hp300_get_ss(void) +{ + return hp300_rtc_read(RTC_REG_SEC1) * 10 + + hp300_rtc_read(RTC_REG_SEC2); } void __init config_hp300(void) { - mach_sched_init = hp300_sched_init; - mach_init_IRQ = hp300_init_IRQ; - mach_request_irq = hp300_request_irq; - mach_free_irq = hp300_free_irq; - mach_get_model = hp300_get_model; - mach_get_irq_list = show_hp300_interrupts; - mach_gettimeoffset = hp300_gettimeoffset; - mach_default_handler = &hp300_default_handler; - mach_reset = hp300_reset; + mach_sched_init = hp300_sched_init; + mach_init_IRQ = hp300_init_IRQ; + mach_request_irq = hp300_request_irq; + mach_free_irq = hp300_free_irq; + mach_get_model = hp300_get_model; + mach_get_irq_list = show_hp300_interrupts; + mach_gettimeoffset = hp300_gettimeoffset; + mach_default_handler = &hp300_default_handler; + mach_hwclk = hp300_hwclk; + mach_get_ss = hp300_get_ss; + mach_reset = hp300_reset; #ifdef CONFIG_HEARTBEAT - mach_heartbeat = hp300_pulse; + mach_heartbeat = hp300_pulse; #endif #ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; + conswitchp = &dummy_con; +#endif + mach_max_dma_address = 0xffffffff; + + if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) { + printk(KERN_INFO "Detected HP9000 model %s\n", hp300_models[hp300_model-HP_320]); + strcat(hp300_model_name, hp300_models[hp300_model-HP_320]); + } + else { + panic("Unknown HP9000 Model"); + } +#ifdef CONFIG_SERIAL_8250_CONSOLE + hp300_setup_serial_console(); #endif - mach_max_dma_address = 0xffffffff; } diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c index 9fe4a9605..0c5bb403e 100644 --- a/arch/m68k/hp300/ints.c +++ b/arch/m68k/hp300/ints.c @@ -57,14 +57,21 @@ static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp) return IRQ_HANDLED; } +static irqreturn_t hp300_badint(int irq, void *dev_id, struct pt_regs *fp) +{ + num_spurious += 1; + return IRQ_NONE; +} + irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - [0] = hp300_int_handler, + [0] = hp300_badint, [1] = hp300_int_handler, [2] = hp300_int_handler, [3] = hp300_int_handler, [4] = hp300_int_handler, [5] = hp300_int_handler, [6] = hp300_int_handler, + [7] = hp300_int_handler }; /* dev_id had better be unique to each handler because it's the only way we have diff --git a/arch/m68k/hp300/reboot.S b/arch/m68k/hp300/reboot.S index aaecdbda2..52eb852e6 100644 --- a/arch/m68k/hp300/reboot.S +++ b/arch/m68k/hp300/reboot.S @@ -13,23 +13,4 @@ .globl hp300_reset hp300_reset: - .chip 68030 - oriw #0x0700,%sr /* cli() */ - movel hp300_phys_ram_base, %d1 - movel #0, %d0 - movec %d0, %vbr /* reset vector table */ - lea zero, %a0 - lea 1f, %a1 - add %d1, %a0 - add %d1, %a1 - pmove %tc, %a0@ - bclr #7, %a0@ - pmove %a0@, %tc /* goodbye MMU */ - jmp %a1@ -1: movel #0x808, %d0 - movec %d0, %cacr /* cache off */ - moveb #0, 0x1ffff - movel #0x1a4, %a0 - jmp %a0@ - -zero: .quad 0 + jmp hp300_reset diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index deb65b4d0..8da5b1b31 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "ints.h" /* Clock hardware definitions */ @@ -38,11 +39,13 @@ static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long tmp; - irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id; - in_8(CLOCKBASE + CLKSR); - asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); - return vector(irq, NULL, regs); + unsigned long tmp; + irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id; + in_8(CLOCKBASE + CLKSR); + asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); + /* Turn off the network and SCSI leds */ + blinken_leds(0, 0xe0); + return vector(irq, NULL, regs); } unsigned long hp300_gettimeoffset(void) diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 081a6747c..458925c47 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -7,7 +7,7 @@ ifndef CONFIG_SUN3 else extra-y := sun3-head.o endif -extra-y += vmlinux.lds.s +extra-y += vmlinux.lds obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c index be2f7e616..a901685eb 100644 --- a/arch/m68k/kernel/bios32.c +++ b/arch/m68k/kernel/bios32.c @@ -46,8 +46,6 @@ #define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) -#define MAX(val1, val2) (((val1) > (val2)) ? val1 : val2) - /* * Offsets relative to the I/O and memory base addresses from where resources * are allocated. @@ -77,11 +75,6 @@ static int disable_pci_burst; /* If set do not allow PCI bursts. */ static unsigned int io_base; static unsigned int mem_base; -struct pci_fixup pcibios_fixups[] = -{ - { 0 } -}; - /* * static void disable_dev(struct pci_dev *dev) * @@ -176,7 +169,7 @@ static void __init layout_dev(struct pci_dev *dev) * Align to multiple of size of minimum base. */ - alignto = MAX(0x040, size) ; + alignto = max_t(unsigned int, 0x040, size); base = ALIGN(io_base, alignto); io_base = base + size; pci_write_config_dword(dev, reg, base | PCI_BASE_ADDRESS_SPACE_IO); @@ -219,7 +212,7 @@ static void __init layout_dev(struct pci_dev *dev) * Align to multiple of size of minimum base. */ - alignto = MAX(0x1000, size) ; + alignto = max_t(unsigned int, 0x1000, size); base = ALIGN(mem_base, alignto); mem_base = base + size; pci_write_config_dword(dev, reg, base); diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 59ee17ab5..e964015a3 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -663,3 +663,50 @@ sys_call_table: .long sys_lremovexattr .long sys_fremovexattr .long sys_futex /* 235 */ + .long sys_sendfile64 + .long sys_mincore + .long sys_madvise + .long sys_fcntl64 + .long sys_readahead /* 240 */ + .long sys_io_setup + .long sys_io_destroy + .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel /* 245 */ + .long sys_fadvise64 + .long sys_exit_group + .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl /* 250 */ + .long sys_epoll_wait + .long sys_remap_file_pages + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime /* 255 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 260 */ + .long sys_clock_getres + .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 265 */ + .long sys_utimes + .long sys_fadvise64_64 + .long sys_mbind + .long sys_get_mempolicy + .long sys_set_mempolicy /* 270 */ + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive + .long sys_mq_notify /* 275 */ + .long sys_mq_getsetattr + .long sys_waitid + .long sys_ni_syscall /* for sys_vserver */ + .long sys_add_key + .long sys_request_key /* 280 */ + .long sys_keyctl + diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index b1e5ae099..7cd6de17c 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -24,6 +24,7 @@ ** 1998/08/30 David Kilzer: Added support for font_desc structures ** for linux-2.1.115 ** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) +** 2004/05/13 Kars de Jong: Finalised HP300 support ** ** This file is subject to the terms and conditions of the GNU General Public ** License. See the file README.legal in the main directory of this archive @@ -313,9 +314,6 @@ #ifdef CONFIG_Q40 .globl q40_mem_cptr #endif -#ifdef CONFIG_HP300 -.globl hp300_phys_ram_base -#endif CPUTYPE_040 = 1 /* indicates an 040 */ CPUTYPE_060 = 2 /* indicates an 060 */ @@ -467,7 +465,7 @@ func_define mmu_get_ptr_table_entry,2 func_define mmu_get_page_table_entry,2 func_define mmu_print func_define get_new_page -#ifdef CONFIG_HP300 +#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) func_define set_leds #endif @@ -594,6 +592,7 @@ ENTRY(_stext) .long MACH_BVME6000, BVME6000_BOOTI_VERSION .long MACH_MAC, MAC_BOOTI_VERSION .long MACH_Q40, Q40_BOOTI_VERSION + .long MACH_HP300, HP300_BOOTI_VERSION .long 0 1: jra __start @@ -605,65 +604,6 @@ ENTRY(_start) jra __start __INIT ENTRY(__start) - -#ifdef CONFIG_HP300 -/* This is a hack. The HP NetBSD bootloader loads us at an arbitrary - address (apparently 0xff002000 in practice) which is not good if we need - to be able to map this to VA 0x1000. We could do it with pagetables but - a better solution seems to be to relocate the kernel in physical memory - before we start. - - So, we copy the entire kernel image (code+data+bss) down to the 16MB - boundary that marks the start of RAM. This is slightly tricky because - we must not overwrite the copying code itself. :-) */ - -/* 15/5/98. The start address of physical RAM changes depending on how much - RAM is present. This is actually a blessing in disguise as it provides - a way for us to work out the RAM size rather than hardwiring it. */ - - lea %pc@(_start),%a0 - movel %a0,%d6 - and #0xffff0000, %d6 - lea %pc@(hp300_phys_ram_base),%a0 - movel %d6, %a0@ - movel %pc@(L(custom)),%a3 - moveb #0xfe,%d7 - moveb %d7,%a3@(0x1ffff) - lea %pc@(Lcopystart),%a0 - lea %pc@(Lcopyend),%a1 - movel %d6,%a2 /* Start of physical RAM */ -1: moveb %a0@+,%d0 - moveb %d0,%a2@+ - cmpl %a0,%a1 - jbne 1b - movel %d6,%a2 - moveb #0xfd,%d7 - moveb %d7,%a3@(0x1ffff) - lea %pc@(_stext),%a0 - lea %pc@(_end),%a1 - jmp %a2@ - -Lcopystart: - moveb #0xf7,%d7 - moveb %d7,%a3@(0x1ffff) - movel %d6,%a2 /* Start of kernel */ - add #0x1000,%a2 -1: moveb %a0@+,%d0 - moveb %d0,%a2@+ - cmpl %a0,%a1 - jbne 1b - moveb #0,%d7 - moveb %d7,%a3@(0x1ffff) - movel %d6,%a0 - addl #Lstart1,%a0 - jmp %a0@ -Lcopyend: - -Lstart1: - moveb #0x3f,%d7 - moveb %d7,%a3@(0x1ffff) -#endif /* CONFIG_HP300 */ - /* * Setup initial stack pointer */ @@ -672,8 +612,6 @@ Lstart1: /* * Record the CPU and machine type. */ - -#ifndef CONFIG_HP300 get_bi_record BI_MACHTYPE lea %pc@(m68k_machtype),%a1 movel %a0@,%a1@ @@ -689,23 +627,8 @@ Lstart1: get_bi_record BI_CPUTYPE lea %pc@(m68k_cputype),%a1 movel %a0@,%a1@ -#else /* CONFIG_HP300 */ - /* FIXME HP300 doesn't use bootinfo yet */ - movel #MACH_HP300,%d4 - lea %pc@(m68k_machtype),%a0 - movel %d4,%a0@ - movel #FPU_68881,%d0 - lea %pc@(m68k_fputype),%a0 - movel %d0,%a0@ - movel #MMU_68030,%d0 - lea %pc@(m68k_mmutype),%a0 - movel %d0,%a0@ - movel #CPU_68030,%d0 - lea %pc@(m68k_cputype),%a0 - movel %d0,%a0@ - leds(0x1) -#endif /* CONFIG_HP300 */ + leds 0x1 #ifdef CONFIG_MAC /* @@ -956,6 +879,26 @@ L(gvtdone): #endif +#ifdef CONFIG_HP300 + is_not_hp300(L(nothp)) + + /* Get the address of the UART for serial debugging */ + get_bi_record BI_HP300_UART_ADDR + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(L(uartbase)),%a0 + movel %d3,%a0@ + get_bi_record BI_HP300_UART_SCODE + tstl %d0 + jbmi 1f + movel %a0@,%d3 + lea %pc@(L(uart_scode)),%a0 + movel %d3,%a0@ +1: +L(nothp): +#endif + /* * Initialize serial port */ @@ -979,9 +922,7 @@ L(nocon): putc '\n' putc 'A' -#ifdef CONFIG_HP300 - leds(0x2) -#endif /* CONFIG_HP300 */ + leds 0x2 dputn %pc@(L(cputype)) dputn %pc@(m68k_supervisor_cachemode) dputn %pc@(m68k_pgtable_cachemode) @@ -1124,16 +1065,30 @@ L(notq40): #ifdef CONFIG_HP300 is_not_hp300(L(nothp300)) -/* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx) - by mapping 32MB from 0xf0xxxxxx -> 0x00xxxxxx) using an 030 early - termination page descriptor. The ROM mapping is needed because the LEDs - are mapped there too. */ + /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx) + * by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx). + * The ROM mapping is needed because the LEDs are mapped there too. + */ + is_040(1f) + + /* + * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000 + */ mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030 -L(nothp300): + jbra L(mmu_init_done) -#endif +1: + /* + * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000 + */ + mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S + + jbra L(mmu_init_done) + +L(nothp300): +#endif /* CONFIG_HP300 */ #ifdef CONFIG_MVME147 @@ -1480,15 +1435,23 @@ L(mmu_fixup_done): #ifdef CONFIG_HP300 is_not_hp300(1f) /* - * Fix up the custom register to point to the new location of the LEDs. + * Fix up the iobase register to point to the new location of the LEDs. */ - movel #0xf0000000,L(custom) + movel #0xf0000000,L(iobase) /* * Energise the FPU and caches. */ + is_040(1f) movel #0x60,0xf05f400c -1: + jbra 2f + + /* + * 040: slightly different, apparently. + */ +1: movew #0,0xf05f400e + movew #0x64,0xf05f400e +2: #endif #ifdef CONFIG_SUN3X @@ -1585,7 +1548,6 @@ func_start get_bi_record,%d1 movel ARG1,%d0 lea %pc@(_end),%a0 -#ifndef CONFIG_HP300 1: tstw %a0@(BIR_TAG) jeq 3f cmpw %a0@(BIR_TAG),%d0 @@ -1599,7 +1561,6 @@ func_start get_bi_record,%d1 3: moveq #-1,%d0 lea %a0@(BIR_SIZE),%a0 4: -#endif /* CONFIG_HP300 */ func_return get_bi_record @@ -3013,6 +2974,10 @@ L(serial_init_not_mac): /* We count on the PROM initializing SIO1 */ #endif +#ifdef CONFIG_HP300 +/* We count on the boot loader initialising the UART */ +#endif + L(serial_init_done): func_return serial_init @@ -3205,9 +3170,31 @@ func_start serial_putc,%d0/%d1/%a0/%a1 1: moveb %a1@(LSRB0),%d0 andb #0x4,%d0 beq 1b + jbra L(serial_putc_done) 2: #endif +#ifdef CONFIG_HP300 + is_not_hp300(3f) + movl %pc@(L(iobase)),%a1 + addl %pc@(L(uartbase)),%a1 + movel %pc@(L(uart_scode)),%d1 /* Check the scode */ + jmi 3f /* Unset? Exit */ + cmpi #256,%d1 /* APCI scode? */ + jeq 2f +1: moveb %a1@(DCALSR),%d1 /* Output to DCA */ + andb #0x20,%d1 + beq 1b + moveb %d0,%a1@(DCADATA) + jbra L(serial_putc_done) +2: moveb %a1@(APCILSR),%d1 /* Output to APCI */ + andb #0x20,%d1 + beq 2b + moveb %d0,%a1@(APCIDATA) + jbra L(serial_putc_done) +3: +#endif + L(serial_putc_done): func_return serial_putc @@ -3295,7 +3282,7 @@ func_start set_leds,%d0/%a0 movel ARG1,%d0 #ifdef CONFIG_HP300 is_not_hp300(1f) - movel %pc@(L(custom)),%a0 + movel %pc@(L(iobase)),%a0 moveb %d0,%a0@(0x1ffff) jra 2f #endif @@ -3829,10 +3816,6 @@ L(showtest): __INITDATA .align 4 -#ifdef CONFIG_HP300 -hp300_phys_ram_base: -#endif - #if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \ defined(CONFIG_HP300) || defined(CONFIG_APOLLO) L(custom): @@ -3924,6 +3907,17 @@ LTHRB0 = 0x10416 LCPUCTRL = 0x10100 #endif +#if defined(CONFIG_HP300) +DCADATA = 0x11 +DCALSR = 0x1b +APCIDATA = 0x00 +APCILSR = 0x14 +L(uartbase): + .long 0 +L(uart_scode): + .long -1 +#endif + __FINIT .data .align 4 diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index b069b0c84..fe837e31a 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -16,7 +16,6 @@ #include #include #include -#include asmlinkage long long __ashldi3 (long long, int); asmlinkage long long __ashrdi3 (long long, int); @@ -72,18 +71,18 @@ EXPORT_SYMBOL(vme_brdtype); explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(__muldi3); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); -EXPORT_SYMBOL_NOVERS(__down_failed_trylock); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_failed_interruptible); +EXPORT_SYMBOL(__down_failed_trylock); +EXPORT_SYMBOL(__up_wakeup); EXPORT_SYMBOL(get_wchan); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index b426ab55a..93b043e2a 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -232,7 +232,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) child_tidptr = (int *)regs->d4; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 12e4acdfd..0beb53333 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -277,7 +277,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ @@ -379,11 +379,8 @@ asmlinkage void syscall_trace(void) if (!current->thread.work.delayed_trace && !current->thread.work.syscall_trace) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index 1d2563e11..d6ca99242 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -109,6 +109,7 @@ extern int q40_parse_bootinfo(const struct bi_record *); extern int bvme6000_parse_bootinfo(const struct bi_record *); extern int mvme16x_parse_bootinfo(const struct bi_record *); extern int mvme147_parse_bootinfo(const struct bi_record *); +extern int hp300_parse_bootinfo(const struct bi_record *); extern void config_amiga(void); extern void config_atari(void); @@ -175,6 +176,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) unknown = mvme16x_parse_bootinfo(record); else if (MACH_IS_MVME147) unknown = mvme147_parse_bootinfo(record); + else if (MACH_IS_HP300) + unknown = hp300_parse_bootinfo(record); else unknown = 1; } @@ -204,20 +207,8 @@ void __init setup_arch(char **cmdline_p) int i; char *p, *q; - if (!MACH_IS_HP300) { - /* The bootinfo is located right after the kernel bss */ - m68k_parse_bootinfo((const struct bi_record *)&_end); - } else { - /* FIXME HP300 doesn't use bootinfo yet */ - extern unsigned long hp300_phys_ram_base; - unsigned long hp300_mem_size = 0xffffffff-hp300_phys_ram_base; - m68k_cputype = CPU_68030; - m68k_fputype = FPU_68882; - m68k_memory[0].addr = hp300_phys_ram_base; - /* 0.5M fudge factor */ - m68k_memory[0].size = hp300_mem_size-512*1024; - m68k_num_memory++; - } + /* The bootinfo is located right after the kernel bss */ + m68k_parse_bootinfo((const struct bi_record *)&_end); if (CPU_IS_040) m68k_is040or060 = 4; @@ -352,7 +343,7 @@ void __init setup_arch(char **cmdline_p) #ifndef CONFIG_SUN3 startmem= m68k_memory[0].addr; endmem = startmem + m68k_memory[0].size; - high_memory = PAGE_OFFSET; + high_memory = (void *)PAGE_OFFSET; for (i = 0; i < m68k_num_memory; i++) { m68k_memory[i].size &= MASK_256K; if (m68k_memory[i].addr < startmem) @@ -550,7 +541,5 @@ void check_bugs(void) "emulation project\n" ); panic( "no FPU" ); } - -#endif /* CONFIG_SUN3 */ - +#endif /* !CONFIG_M68KFPU_EMU */ } diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index c37c4dbb8..4a319bdef 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -842,9 +842,7 @@ adjust_stack: return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } @@ -925,9 +923,7 @@ adjust_stack: return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index d85616f14..e47e19588 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -38,24 +38,6 @@ static inline int set_rtc_mmss(unsigned long nowtime) return -1; } -static inline void do_profile (unsigned long pc) -{ - if (prof_buffer && current->pid) { - extern int _stext; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - if (pc < prof_len) - ++prof_buffer[pc]; - else - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - ++prof_buffer[prof_len-1]; - } -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -63,9 +45,10 @@ static inline void do_profile (unsigned long pc) static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) { do_timer(regs); - - if (!user_mode(regs)) - do_profile(regs->pc); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + profile_tick(CPU_PROFILING, regs); #ifdef CONFIG_HEARTBEAT /* use power LED as a heartbeat instead -- much more useful diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index b0a5cd53d..e58654f3f 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -15,7 +15,7 @@ SECTIONS SCHED_TEXT *(.fixup) *(.gnu.warning) - } = 0x4e75 + } :text = 0x4e75 . = ALIGN(16); /* Exception table */ __start___ex_table = .; @@ -34,7 +34,7 @@ SECTIONS .bss : { *(.bss) } /* BSS */ . = ALIGN(16); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } + .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data _edata = .; /* End of data section */ @@ -51,9 +51,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 12931b324..cc37e8d3c 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -16,7 +16,7 @@ SECTIONS SCHED_TEXT *(.fixup) *(.gnu.warning) - } = 0x4e75 + } :text = 0x4e75 RODATA _etext = .; /* End of text section */ @@ -28,7 +28,7 @@ SECTIONS __start___ex_table = .; *(__ex_table) __stop___ex_table = .; - } + } :data /* End of data goes *here* so that freeing init code works properly. */ _edata = .; @@ -45,9 +45,6 @@ __init_begin = .; __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S index 48e85d1d9..497b924f3 100644 --- a/arch/m68k/kernel/vmlinux.lds.S +++ b/arch/m68k/kernel/vmlinux.lds.S @@ -1,5 +1,9 @@ #include - +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS (7); + data PT_LOAD FLAGS (7); +} #ifdef CONFIG_SUN3 #include "vmlinux-sun3.lds" #else diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 09985ae7f..1453a6013 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -77,7 +77,7 @@ pmd_t *get_pointer_table (void) ptable_desc *new; if (!(page = (void *)get_zeroed_page(GFP_KERNEL))) - return 0; + return NULL; flush_tlb_kernel_page(page); nocache_page(page); diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index e58d9e362..d855fec26 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -258,7 +258,7 @@ void __init paging_init(void) printk ("before free_area_init\n"); #endif zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ? - mach_max_dma_address : (unsigned long)high_memory); + (mach_max_dma_address+1) : (unsigned long)high_memory); zones_size[1] = (unsigned long)high_memory - zones_size[0]; zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT; diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c index 256c5eeb5..a47be196a 100644 --- a/arch/m68k/mm/sun3mmu.c +++ b/arch/m68k/mm/sun3mmu.c @@ -7,7 +7,6 @@ * */ -#include #include #include #include diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 0b5730cd9..02b626bae 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 541897351..f8ecc2664 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -11,7 +11,6 @@ * */ -#include #include #include #include @@ -19,12 +18,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/arch/m68k/sun3/Makefile b/arch/m68k/sun3/Makefile index de3867d02..4d4f0695d 100644 --- a/arch/m68k/sun3/Makefile +++ b/arch/m68k/sun3/Makefile @@ -4,5 +4,4 @@ obj-y := sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o idprom.o -obj-$(CONFIG_SUN3) += config.o mmu_emu.o leds.o dvma.o \ - intersil.o +obj-$(CONFIG_SUN3) += config.o mmu_emu.o leds.o dvma.o intersil.o diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c index 0d9876190..7a0e3a220 100644 --- a/arch/m68k/sun3/mmu_emu.c +++ b/arch/m68k/sun3/mmu_emu.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -21,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -46,6 +47,8 @@ extern void prom_reboot (char *) __attribute__ ((__noreturn__)); */ unsigned long vmalloc_end; +EXPORT_SYMBOL(vmalloc_end); + unsigned long pmeg_vaddr[PMEGS_NUM]; unsigned char pmeg_alloc[PMEGS_NUM]; unsigned char pmeg_ctx[PMEGS_NUM]; diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c index 47e677d0d..f04a1d25f 100644 --- a/arch/m68k/sun3/sun3dvma.c +++ b/arch/m68k/sun3/sun3dvma.c @@ -6,6 +6,7 @@ * Contains common routines for sun3/sun3x DVMA management. */ +#include #include #include #include diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index bca65bd06..e62a033cd 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -6,6 +6,7 @@ * for more details. */ +#include #include #include #include @@ -85,6 +86,9 @@ static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp) intersil_clear(); #endif do_timer(fp); +#ifndef CONFIG_SMP + update_process_times(user_mode(fp)); +#endif if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20)) sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160) /20]); diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c index 756d6277f..0ef547f54 100644 --- a/arch/m68k/sun3x/config.c +++ b/arch/m68k/sun3x/config.c @@ -6,6 +6,7 @@ * based on code from Oliver Jowett */ +#include #include #include #include @@ -70,7 +71,7 @@ void __init config_sun3x(void) mach_get_model = sun3_get_model; mach_get_hardware_list = sun3x_get_hardware_list; -#if defined(CONFIG_DUMMY_CONSOLE) +#ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index f11317725..6b9713898 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -5,6 +5,10 @@ mainmenu "uClinux/68k (w/o MMU) Kernel Configuration" +config M68KNOMMU + bool + default y + config MMU bool default n @@ -25,7 +29,6 @@ config RWSEM_XCHGADD_ALGORITHM bool default n - source "init/Kconfig" menu "Processor type and features" @@ -69,15 +72,20 @@ config M5249 help Motorola ColdFire 5249 processor support. +config M527x + bool "MCF527x" + help + Freescale (Motorola) ColdFire 5270/5271/5274/5275 processor support. + config M5272 bool "MCF5272" help Motorola ColdFire 5272 processor support. -config M5282 - bool "MCF5282" +config M528x + bool "MCF528x" help - Motorola ColdFire 5282 processor support. + Motorola ColdFire 5280/5282 processor support. config M5307 bool "MCF5307" @@ -93,7 +101,7 @@ endchoice config COLDFIRE bool - depends on (M5206 || M5206e || M5249 || M5272 || M5282 || M5307 || M5407) + depends on (M5206 || M5206e || M5249 || M527x || M5272 || M528x || M5307 || M5407) default y choice @@ -114,82 +122,97 @@ config CLOCK_AUTO config CLOCK_11MHz bool "11MHz" help - Select an 11MHz CPU clock frequency. + Select a 11MHz CPU clock frequency. config CLOCK_16MHz bool "16MHz" help - Select an 16MHz CPU clock frequency. + Select a 16MHz CPU clock frequency. config CLOCK_20MHz bool "20MHz" help - Select an 20MHz CPU clock frequency. + Select a 20MHz CPU clock frequency. config CLOCK_24MHz bool "24MHz" help - Select an 24MHz CPU clock frequency. + Select a 24MHz CPU clock frequency. config CLOCK_25MHz bool "25MHz" help - Select an 25MHz CPU clock frequency. + Select a 25MHz CPU clock frequency. config CLOCK_33MHz bool "33MHz" help - Select an 33MHz CPU clock frequency. + Select a 33MHz CPU clock frequency. config CLOCK_40MHz bool "40MHz" help - Select an 40MHz CPU clock frequency. + Select a 40MHz CPU clock frequency. config CLOCK_45MHz bool "45MHz" help - Select an 45MHz CPU clock frequency. + Select a 45MHz CPU clock frequency. config CLOCK_48MHz bool "48MHz" help - Select an 48MHz CPU clock frequency. + Select a 48MHz CPU clock frequency. config CLOCK_50MHz bool "50MHz" help - Select an 50MHz CPU clock frequency. + Select a 50MHz CPU clock frequency. config CLOCK_54MHz bool "54MHz" help - Select an 54MHz CPU clock frequency. + Select a 54MHz CPU clock frequency. config CLOCK_60MHz bool "60MHz" help - Select an 60MHz CPU clock frequency. + Select a 60MHz CPU clock frequency. config CLOCK_64MHz bool "64MHz" help - Select an 64MHz CPU clock frequency. + Select a 64MHz CPU clock frequency. config CLOCK_66MHz bool "66MHz" help - Select an 66MHz CPU clock frequency. + Select a 66MHz CPU clock frequency. config CLOCK_70MHz bool "70MHz" help - Select an 70MHz CPU clock frequency. + Select a 70MHz CPU clock frequency. + +config CLOCK_100MHz + bool "100MHz" + help + Select a 100MHz CPU clock frequency. config CLOCK_140MHz bool "140MHz" help - Select an 140MHz CPU clock frequency. + Select a 140MHz CPU clock frequency. + +config CLOCK_150MHz + bool "150MHz" + help + Select a 150MHz CPU clock frequency. + +config CLOCK_166MHz + bool "166MHz" + help + Select a 166MHz CPU clock frequency. endchoice @@ -281,6 +304,18 @@ config M5249C3 help Support for the Motorola M5249C3 board. +config M5271EVB + bool "Freescale (Motorola) M5271EVB board support" + depends on M527x + help + Support for the Freescale (Motorola) M5271EVB board. + +config M5275EVB + bool "Freescale (Motorola) M5275EVB board support" + depends on M527x + help + Support for the Freescale (Motorola) M5275EVB board. + config M5272C3 bool "Motorola M5272C3 board support" depends on M5272 @@ -293,15 +328,21 @@ config COBRA5272 help Support for the senTec COBRA5272 board. -config M5282C3 - bool "Motorola M5282C3 board support" - depends on M5282 +config M5275EVB + bool "Freescale (Motorola) M5275EVB board support" + depends on M527x + help + Support for the Freescale (Motorola) M5275EVB board. + +config M5282EVB + bool "Motorola M5282EVB board support" + depends on M528x help - Support for the Motorola M5282C3 board. + Support for the Motorola M5282EVB board. config COBRA5282 bool "senTec COBRA5282 board support" - depends on M5282 + depends on M528x help Support for the senTec COBRA5282 board. @@ -341,6 +382,18 @@ config CLEOPATRA help Support for the Feith Cleopatra boards. +config CANCam + bool "Feith CANCam board support" + depends on M5272 + help + Support for the Feith CANCam board. + +config SCALES + bool "Feith SCALES board support" + depends on M5272 + help + Support for the Feith SCALES board. + config NETtel bool "SecureEdge/NETtel board support" depends on (M5206e || M5272 || M5307) @@ -353,6 +406,12 @@ config SNAPGEAR help Special additional support for SnapGear router boards. +config CPU16B + bool "Sneha Technologies S.L. Sarasvati board support" + depends on M5272 + help + Support for the SNEHA CPU16B board. + config ROMFS_FROM_ROM bool " ROMFS image not RAM resident" depends on (NETtel || SNAPGEAR) @@ -373,13 +432,23 @@ config ARNEWSH config MOTOROLA bool default y - depends on (M5206eC3 || M5249C3 || M5272C3 || M5282C3 || M5307C3 || M5407C3) + depends on (M5206eC3 || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) + +config HW_FEITH + bool + default y + depends on (CLEOPATRA || CANCam || SCALES) config senTec bool default y depends on (COBRA5272 || COBRA5282) +config SNEHA + bool + default y + depends on CPU16B + config LARGE_ALLOCS bool "Allow allocating large blocks (> 1MB) of memory" help @@ -388,7 +457,7 @@ config LARGE_ALLOCS a lot of RAM, and you need to able to allocate very large contiguous chunks. If unsure, say N. -choice +choice prompt "RAM size" default AUTO @@ -421,7 +490,7 @@ config RAM32MB endchoice -choice +choice prompt "RAM bus width" default RAMAUTOBIT @@ -472,7 +541,6 @@ endchoice endmenu - menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" config PCI @@ -511,64 +579,10 @@ source "drivers/Kconfig" source "fs/Kconfig" -menu "Kernel hacking" - -config FULLDEBUG - bool "Full Symbolic/Source Debugging support" - help - Enable debuging symbols on kernel build. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - Enables console device to interpret special characters as - commands to dump state information. - -config HIGHPROFILE - bool "Use fast second timer for profiling" - depends on COLDFIRE - help - Use a fast secondary clock to produce profiling information. - -config BOOTPARAM - bool 'Compiled-in Kernel Boot Parameter' - -config BOOTPARAM_STRING - string 'Kernel Boot Parameter' - default 'console=ttyS0,19200' - depends on BOOTPARAM - -config DUMPTOFLASH - bool "Panic/Dump to FLASH" - depends on COLDFIRE - help - Dump any panic of trap output into a flash memory segment - for later analysis. - -config NO_KERNEL_MSG - bool "Suppress Kernel BUG Messages" - help - Do not output any debug BUG messages within the kernel. - -config BDM_DISABLE - bool "Disable BDM signals" - depends on (EXPERIMENTAL && COLDFIRE) - help - Disable the ColdFire CPU's BDM signals. - -endmenu +source "arch/m68knommu/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index e6be8b778..2524de272 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -15,8 +15,9 @@ platform-$(CONFIG_M68360) := 68360 platform-$(CONFIG_M5206) := 5206 platform-$(CONFIG_M5206e) := 5206e platform-$(CONFIG_M5249) := 5249 +platform-$(CONFIG_M527x) := 527x platform-$(CONFIG_M5272) := 5272 -platform-$(CONFIG_M5282) := 5282 +platform-$(CONFIG_M528x) := 528x platform-$(CONFIG_M5307) := 5307 platform-$(CONFIG_M5407) := 5407 PLATFORM := $(platform-y) @@ -28,12 +29,16 @@ board-$(CONFIG_UCQUICC) := uCquicc board-$(CONFIG_DRAGEN2) := de2 board-$(CONFIG_ARNEWSH) := ARNEWSH board-$(CONFIG_MOTOROLA) := MOTOROLA +board-$(CONFIG_M5271EVB) := M5271EVB +board-$(CONFIG_M5275EVB) := M5275EVB +board-$(CONFIG_M5282EVB) := M5282EVB board-$(CONFIG_ELITE) := eLITE board-$(CONFIG_eLIA) := eLIA board-$(CONFIG_NETtel) := NETtel board-$(CONFIG_SECUREEDGEMP3) := MP3 board-$(CONFIG_CLEOPATRA) := CLEOPATRA -board-$(CONFIG_senTec) := senTec +board-$(CONFIG_senTec) := senTec +board-$(CONFIG_SNEHA) := SNEHA BOARD := $(board-y) model-$(CONFIG_RAMKERNEL) := ram @@ -50,8 +55,9 @@ MODEL := $(model-y) cpuclass-$(CONFIG_M5206) := 5307 cpuclass-$(CONFIG_M5206e) := 5307 cpuclass-$(CONFIG_M5249) := 5307 +cpuclass-$(CONFIG_M527x) := 5307 cpuclass-$(CONFIG_M5272) := 5307 -cpuclass-$(CONFIG_M5282) := 5307 +cpuclass-$(CONFIG_M528x) := 5307 cpuclass-$(CONFIG_M5407) := 5307 cpuclass-$(CONFIG_M68EZ328) := 68328 cpuclass-$(CONFIG_M68VZ328) := 68328 @@ -69,8 +75,9 @@ export PLATFORM BOARD MODEL CPUCLASS cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307 -cflags-$(CONFIG_M5282) := -m5307 -Wa,-S -Wa,-m5307 +cflags-$(CONFIG_M528x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5307) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5407) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M68328) := -m68000 @@ -82,7 +89,7 @@ AFLAGS += $(cflags-y) CFLAGS += $(cflags-y) CFLAGS += -fno-builtin -CFLAGS += -O2 -g +CFLAGS += -O1 -g CFLAGS += -D__linux__ CFLAGS += -DUTS_SYSNAME=\"uClinux\" diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig index b101057f0..e4bd31be9 100644 --- a/arch/m68knommu/defconfig +++ b/arch/m68knommu/defconfig @@ -35,8 +35,9 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_M5206 is not set # CONFIG_M5206e is not set # CONFIG_M5249 is not set +# CONFIG_M527x is not set CONFIG_M5272=y -# CONFIG_M5282 is not set +# CONFIG_M528x is not set # CONFIG_M5307 is not set # CONFIG_M5407 is not set CONFIG_COLDFIRE=y @@ -55,7 +56,10 @@ CONFIG_COLDFIRE=y # CONFIG_CLOCK_60MHz is not set CONFIG_CLOCK_66MHz=y # CONFIG_CLOCK_70MHz is not set +# CONFIG_CLOCK_100MHz is not set # CONFIG_CLOCK_140MHz is not set +# CONFIG_CLOCK_150MHz is not set +# CONFIG_CLOCK_166MHz is not set # # Platform diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile index 1a6a3600e..1c6cd1ab5 100644 --- a/arch/m68knommu/kernel/Makefile +++ b/arch/m68knommu/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for arch/m68knommu/kernel. # -extra-y := vmlinux.lds.s +extra-y := vmlinux.lds obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \ setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c index c803fe64e..02c56f538 100644 --- a/arch/m68knommu/kernel/asm-offsets.c +++ b/arch/m68knommu/kernel/asm-offsets.c @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c index ce5dafa69..8670938f1 100644 --- a/arch/m68knommu/kernel/comempci.c +++ b/arch/m68knommu/kernel/comempci.c @@ -351,8 +351,6 @@ char *pcibios_setup(char *option) } /*****************************************************************************/ -struct pci_fixup pcibios_fixups[] = { { 0 } }; - void pcibios_fixup_bus(struct pci_bus *b) { } diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c index 33e084146..e93a5ad56 100644 --- a/arch/m68knommu/kernel/m68k_ksyms.c +++ b/arch/m68knommu/kernel/m68k_ksyms.c @@ -16,7 +16,6 @@ #include #include #include -#include #include extern void dump_thread(struct pt_regs *, struct user *); @@ -50,16 +49,16 @@ EXPORT_SYMBOL(csum_partial_copy); explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); -EXPORT_SYMBOL_NOVERS(__down_failed_trylock); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_failed_interruptible); +EXPORT_SYMBOL(__down_failed_trylock); +EXPORT_SYMBOL(__up_wakeup); EXPORT_SYMBOL(get_wchan); @@ -79,27 +78,27 @@ extern void __udivsi3(void); extern void __umodsi3(void); /* gcc lib functions */ -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__divsi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(__modsi3); -EXPORT_SYMBOL_NOVERS(__muldi3); -EXPORT_SYMBOL_NOVERS(__mulsi3); -EXPORT_SYMBOL_NOVERS(__udivsi3); -EXPORT_SYMBOL_NOVERS(__umodsi3); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__muldi3); +EXPORT_SYMBOL(__mulsi3); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__umodsi3); -EXPORT_SYMBOL_NOVERS(is_in_rom); +EXPORT_SYMBOL(is_in_rom); #ifdef CONFIG_COLDFIRE extern unsigned int *dma_device_address; extern unsigned long dma_base_addr, _ramend; -EXPORT_SYMBOL_NOVERS(dma_base_addr); -EXPORT_SYMBOL_NOVERS(dma_device_address); -EXPORT_SYMBOL_NOVERS(_ramend); +EXPORT_SYMBOL(dma_base_addr); +EXPORT_SYMBOL(dma_device_address); +EXPORT_SYMBOL(_ramend); extern asmlinkage void trap(void); extern void *_ramvec; -EXPORT_SYMBOL_NOVERS(trap); -EXPORT_SYMBOL_NOVERS(_ramvec); +EXPORT_SYMBOL(trap); +EXPORT_SYMBOL(_ramvec); #endif /* CONFIG_COLDFIRE */ diff --git a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c index 8eb130e8b..3b1a2ff61 100644 --- a/arch/m68knommu/kernel/module.c +++ b/arch/m68knommu/kernel/module.c @@ -82,9 +82,38 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, unsigned int relsec, struct module *me) { - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate_add section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; } int module_finalize(const Elf_Ehdr *hdr, diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 581eef2b7..b0901d817 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -188,7 +188,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) newsp = regs->d2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } int copy_thread(int nr, unsigned long clone_flags, diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 4f3df6d67..15cf79080 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -133,13 +133,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_attach(child); goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } ret = ptrace_check_attach(child, request == PTRACE_KILL); if (ret < 0) goto out_tsk; @@ -271,7 +264,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ @@ -376,10 +369,8 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index edcecd4d0..557238596 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -1,7 +1,7 @@ /* * linux/arch/m68knommu/kernel/setup.c * - * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1999-2004 Greg Ungerer (gerg@snapgear.com) * Copyright (C) 1998,1999 D. Jeff Dionne * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} * Copyright (C) 1998 Kenneth Albanowski @@ -106,11 +106,14 @@ void (*mach_power_off)( void ) = NULL; #if defined(CONFIG_M5249) #define CPU "COLDFIRE(m5249)" #endif +#if defined(CONFIG_M527x) + #define CPU "COLDFIRE(m5270/5271/5274/5275)" +#endif #if defined(CONFIG_M5272) #define CPU "COLDFIRE(m5272)" #endif -#if defined(CONFIG_M5282) - #define CPU "COLDFIRE(m5282)" +#if defined(CONFIG_M528x) + #define CPU "COLDFIRE(m5280/5282)" #endif #if defined(CONFIG_M5307) #define CPU "COLDFIRE(m5307)" diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 3fb0d78f4..c19722c5d 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -616,9 +616,7 @@ adjust_stack: return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } @@ -685,9 +683,7 @@ adjust_stack: return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } @@ -749,147 +745,44 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. - * - * Note that we go through the signals twice: once to check the signals - * that the kernel can handle, and then we build all the user-level signal - * handling stack-frames in one go after that. */ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; - struct k_sigaction *ka; - - current->thread.esp0 = (unsigned long) regs; + int signr; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; if (!oldset) oldset = ¤t->blocked; - for (;;) { - int signr; - - signr = get_signal_to_deliver(&info, regs, NULL); - - if (!signr) - break; - - if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { - current->exit_code = signr; - current->state = TASK_STOPPED; - regs->sr &= ~PS_T; - - /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) { - /* Restart the system call the same way as - if the process were not traced. */ - struct k_sigaction *ka = - ¤t->sighand->action[signr-1]; - int has_handler = - (ka->sa.sa_handler != SIG_IGN && - ka->sa.sa_handler != SIG_DFL); - handle_restart(regs, ka, has_handler); - } - notify_parent(current, SIGCHLD); - schedule(); - - /* We're back. Did the debugger cancel the sig? */ - if (!(signr = current->exit_code)) { - discard_frame: - continue; - } - current->exit_code = 0; - - /* The debugger continued. Ignore SIGSTOP. */ - if (signr == SIGSTOP) - goto discard_frame; - - /* Update the siginfo structure. Is this good? */ - if (signr != info.si_signo) { - info.si_signo = signr; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->parent->pid; - info.si_uid = current->parent->uid; - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(¤t->blocked, signr)) { - send_sig_info(signr, &info, current); - continue; - } - } - - ka = ¤t->sighand->action[signr-1]; - if (ka->sa.sa_handler == SIG_IGN) { - if (signr != SIGCHLD) - continue; - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; - continue; - } - - if (ka->sa.sa_handler == SIG_DFL) { - int exit_code = signr; - - if (current->pid == 1) - continue; - - switch (signr) { - case SIGCONT: case SIGCHLD: - case SIGWINCH: case SIGURG: - continue; - - case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(process_group(current))) - continue; - /* FALLTHRU */ - - case SIGSTOP: - current->state = TASK_STOPPED; - current->exit_code = signr; - if (!(current->parent->sighand->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) - notify_parent(current, SIGCHLD); - schedule(); - continue; - - case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGIOT: case SIGFPE: case SIGSEGV: - case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: - if (do_coredump(signr, exit_code, regs)) - exit_code |= 0x80; - /* FALLTHRU */ - - default: - sigaddset(¤t->pending.signal, signr); - recalc_sigpending(); - current->flags |= PF_SIGNALED; - do_exit(exit_code); - /* NOTREACHED */ - } - } - + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, ka, &info, oldset, regs); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ - if (regs->orig_d0 >= 0) + if (regs->orig_d0 >= 0) { /* Restart the system call - no handlers present */ - handle_restart(regs, NULL, 0); - - /* If we are about to discard some frame stuff we must copy - over the remaining frame. */ - if (regs->stkadj) { - struct pt_regs *tregs = - (struct pt_regs *) ((ulong) regs + regs->stkadj); - - /* This must be copied with decreasing addresses to - handle overlaps. */ - tregs->vector = 0; - tregs->format = 0; - tregs->pc = regs->pc; - tregs->sr = regs->sr; + if (regs->d0 == -ERESTARTNOHAND + || regs->d0 == -ERESTARTSYS + || regs->d0 == -ERESTARTNOINTR) { + regs->d0 = regs->orig_d0; + regs->pc -= 2; + } else if (regs->d0 == -ERESTART_RESTARTBLOCK) { + regs->d0 = __NR_restart_syscall; + regs->pc -= 2; + } } return 0; } diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index 01a8c1d20..897deaa06 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -185,7 +185,7 @@ ENTRY(sys_call_table) .long sys_ni_syscall /* sys_mremap */ .long sys_setresuid16 .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* for vm86 */ + .long sys_getpagesize /* sys_getpagesize */ .long sys_ni_syscall /* old "query_module" */ .long sys_poll .long sys_ni_syscall /* sys_nfsservctl */ @@ -237,42 +237,70 @@ ENTRY(sys_call_table) .long sys_setfsuid /* 215 */ .long sys_setfsgid .long sys_pivot_root - .long sys_ni_syscall /* sys_mincore */ - .long sys_ni_syscall /* sys_madvise */ - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ .long sys_ni_syscall + .long sys_ni_syscall + .long sys_getdents64 /* 220 */ .long sys_gettid - .long sys_ni_syscall /* 225 */ /* sys_readahead */ + .long sys_tkill .long sys_setxattr .long sys_lsetxattr - .long sys_fsetxattr + .long sys_fsetxattr /* 225 */ .long sys_getxattr - .long sys_lgetxattr /* 230 */ + .long sys_lgetxattr .long sys_fgetxattr .long sys_listxattr - .long sys_llistxattr + .long sys_llistxattr /* 230 */ .long sys_flistxattr - .long sys_removexattr /* 235 */ + .long sys_removexattr .long sys_lremovexattr .long sys_fremovexattr - .long sys_tkill + .long sys_futex /* 235 */ .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall /* sys_set_thread_area */ - .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_io_setup /* 245 */ + .long sys_ni_syscall /* sys_mincore */ + .long sys_ni_syscall /* sys_madvise */ + .long sys_fcntl64 + .long sys_readahead /* 240 */ + .long sys_io_setup .long sys_io_destroy .long sys_io_getevents .long sys_io_submit - .long sys_io_cancel - .long sys_ni_syscall /* 250 */ /* sys_alloc_hugepages */ - .long sys_ni_syscall /* sys_freec_hugepages */ + .long sys_io_cancel /* 245 */ + .long sys_fadvise64 .long sys_exit_group .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl /* 250 */ + .long sys_epoll_wait + .long sys_ni_syscall /* sys_remap_file_pages */ + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime /* 255 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 260 */ + .long sys_clock_getres + .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 265 */ + .long sys_utimes + .long sys_fadvise64_64 + .long sys_mbind + .long sys_get_mempolicy + .long sys_set_mempolicy /* 270 */ + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive + .long sys_mq_notify /* 275 */ + .long sys_mq_getsetattr + .long sys_waitid + .long sys_ni_syscall /* sys_setaltroot */ + .long sys_ni_syscall /* sys_add_key */ + .long sys_ni_syscall /* 280 */ /* sys_request_key */ + .long sys_ni_syscall /* sys_keyctl */ .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c index 74308a533..5c3ca6716 100644 --- a/arch/m68knommu/kernel/time.c +++ b/arch/m68knommu/kernel/time.c @@ -41,24 +41,6 @@ static inline int set_rtc_mmss(unsigned long nowtime) return -1; } -static inline void do_profile (unsigned long pc) -{ - if (prof_buffer && current->pid) { - extern int _stext; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - if (pc < prof_len) - ++prof_buffer[pc]; - else - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - ++prof_buffer[prof_len-1]; - } -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -75,9 +57,11 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) write_seqlock(&xtime_lock); do_timer(regs); - - if (!user_mode(regs)) - do_profile(regs->pc); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + if (current->pid) + profile_tick(CPU_PROFILING, regs); /* * If we have an externally synchronized Linux clock, then update diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 4d8f716d7..8ba00a212 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -1,7 +1,7 @@ /* * vmlinux.lds.S -- master linker script for m68knommu arch * - * (C) Copyright 2002-2003, Greg Ungerer + * (C) Copyright 2002-2004, Greg Ungerer * * This ends up looking compilcated, because of the number of * address variations for ram and rom/flash layouts. The real @@ -117,7 +117,8 @@ */ #if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \ defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \ - defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) + defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \ + defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) #define RAM_START 0x20000 #define RAM_LENGTH 0x3e0000 #endif @@ -132,14 +133,14 @@ #define RAM_LENGTH 0xfe0000 #endif -#if defined(CONFIG_M5282C3) +#if defined(CONFIG_M5282EVB) #define RAM_START 0x10000 #define RAM_LENGTH 0x3f0000 #endif /* * The senTec COBRA5282 board has the same - * memory layout as the M5282C3. + * memory layout as the M5282EVB. */ #if defined(CONFIG_COBRA5282) #define RAM_START 0x10000 @@ -153,11 +154,22 @@ */ #if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ - defined(CONFIG_CLEOPATRA) + defined(CONFIG_HW_FEITH) #define RAM_START 0x400 #define RAM_LENGTH 0x3ffc00 #endif +/* + * Sneha Boards mimimun memmory + * The end of RAM will vary depending on how much ram is fitted, + * but this isn't important here, we assume at least 4MiB. + */ +#if defined(CONFIG_CPU16B) +#define RAM_START 0x20000 +#define RAM_LENGTH 0x3e0000 +#endif + + #if defined(CONFIG_RAMKERNEL) #define TEXT ram #define DATA ram @@ -247,6 +259,11 @@ SECTIONS { /* Kernel symbol table: strings */ *(__ksymtab_strings) + /* Built-in module parameters */ + __start___param = .; + *(__param) + __stop___param = .; + . = ALIGN(4) ; _etext = . ; } > TEXT @@ -284,9 +301,6 @@ SECTIONS { __setup_start = .; *(.init.setup) __setup_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) @@ -306,7 +320,7 @@ SECTIONS { __initramfs_start = .; *(.init.ramfs) __initramfs_end = .; - . = ALIGN(4); + . = ALIGN(4096); __init_end = .; } > INIT diff --git a/arch/m68knommu/lib/Makefile b/arch/m68knommu/lib/Makefile index 0c734d9a7..e051a7913 100644 --- a/arch/m68knommu/lib/Makefile +++ b/arch/m68knommu/lib/Makefile @@ -4,4 +4,4 @@ lib-y := ashldi3.o ashrdi3.o lshrdi3.o \ muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ - checksum.o semaphore.o memcpy.o memset.o + checksum.o semaphore.o memcpy.o memset.o delay.o diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c index ce33f2f0b..748990d6b 100644 --- a/arch/m68knommu/mm/init.c +++ b/arch/m68knommu/mm/init.c @@ -38,7 +38,6 @@ #include #include #include -#include #undef DEBUG diff --git a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c index 9ec7dfee5..0eef72915 100644 --- a/arch/m68knommu/mm/memory.c +++ b/arch/m68knommu/mm/memory.c @@ -24,7 +24,6 @@ #include #include #include -#include #include /* diff --git a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S index fdb9392b5..2049f44fd 100644 --- a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S +++ b/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S @@ -21,7 +21,6 @@ */ #define MEM_BASE 0x00000000 /* Memory base at address 0 */ -#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ #define VBR_BASE MEM_BASE /* Vector address */ /*****************************************************************************/ @@ -78,9 +77,36 @@ _start: /* - * Set to 4 meg for the Cadre III board (m5206e). + * SDRAM size for the Cadre III board (m5206e). */ +#if defined(CONFIG_RAMAUTO) + movea.l #0x00000000,%a0 + move.l MCF_MBAR+MCFSIM_DCMR0,%d0 + and.l #0x00fe0000, %d0 + beq noaddr1 + add.l #0x00020000,%d0 + move.l %d0,%a0 +noaddr1: + move.l MCF_MBAR+MCFSIM_DCMR1,%d0 + and.l #0x00fe0000, %d0 + beq noaddr2 + add.l #0x00020000,%d0 + add.l %d0,%a0 +noaddr2: + +#else + +#if defined(CONFIG_RAM32MB) +#define MEM_SIZE 0x02000000 /* Memory size 32Mb */ +#elif defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#elif defined(CONFIG_RAM8MB) +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#else +#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ +#endif move.l #MEM_SIZE, %a0 +#endif move.l %a0, %d0 /* Mem end addr is in a0 */ move.l %d0, %sp /* Set up initial stack ptr */ diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c index cd7c90446..f35b8606c 100644 --- a/arch/m68knommu/platform/5206e/config.c +++ b/arch/m68knommu/platform/5206e/config.c @@ -22,7 +22,6 @@ #include #include #include -#include /***************************************************************************/ diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c index a1bed394d..289c1821b 100644 --- a/arch/m68knommu/platform/5249/config.c +++ b/arch/m68knommu/platform/5249/config.c @@ -21,7 +21,6 @@ #include #include #include -#include /***************************************************************************/ diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c index e325c19fb..a9e0dcee1 100644 --- a/arch/m68knommu/platform/5272/config.c +++ b/arch/m68knommu/platform/5272/config.c @@ -23,7 +23,6 @@ #include #include #include -#include /***************************************************************************/ @@ -110,7 +109,7 @@ void config_BSP(char *commandp, int size) #if defined(CONFIG_BOOTPARAM) strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); commandp[size-1] = 0; -#elif defined(CONFIG_NETtel) +#elif defined(CONFIG_NETtel) || defined(CONFIG_SCALES) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); commandp[size-1] = 0; @@ -118,6 +117,10 @@ void config_BSP(char *commandp, int size) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xffe06000, size); commandp[size-1] = 0; +#elif defined(CONFIG_CANCam) + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xf0010000, size); + commandp[size-1] = 0; #else memset(commandp, 0, size); #endif diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 9959b838e..3f5461088 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile @@ -20,8 +20,10 @@ obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o obj-$(CONFIG_M5206) += timers.o obj-$(CONFIG_M5206e) += timers.o obj-$(CONFIG_M5249) += timers.o +obj-$(CONFIG_M527x) += pit.o obj-$(CONFIG_M5272) += timers.o obj-$(CONFIG_M5307) += config.o timers.o +obj-$(CONFIG_M528x) += pit.o obj-$(CONFIG_M5407) += timers.o ifeq ($(CONFIG_M5307),y) diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c index e816437f2..3f505dabf 100644 --- a/arch/m68knommu/platform/5307/config.c +++ b/arch/m68knommu/platform/5307/config.c @@ -23,7 +23,6 @@ #include #include #include -#include #include /***************************************************************************/ diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c index 99c7d9935..ef49596aa 100644 --- a/arch/m68knommu/platform/5307/timers.c +++ b/arch/m68knommu/platform/5307/timers.c @@ -110,17 +110,8 @@ void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) { /* Reset ColdFire timer2 */ mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long ip = instruction_pointer(regs); - ip -= (unsigned long) &_stext; - ip >>= prof_shift; - if (ip < prof_len) - prof_buffer[ip]++; - } - } + if (current->pid) + profile_tick(CPU_PROFILING, regs); } /***************************************************************************/ diff --git a/arch/m68knommu/platform/5307/vectors.c b/arch/m68knommu/platform/5307/vectors.c index 1f882ca21..ac313a160 100644 --- a/arch/m68knommu/platform/5307/vectors.c +++ b/arch/m68knommu/platform/5307/vectors.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,7 +23,6 @@ #include #include #include -#include #include /***************************************************************************/ diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c index ef76b156d..f7c9018b8 100644 --- a/arch/m68knommu/platform/5407/config.c +++ b/arch/m68knommu/platform/5407/config.c @@ -23,7 +23,6 @@ #include #include #include -#include /***************************************************************************/ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6ab62cb4d..8c253f431 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -11,7 +11,7 @@ config MIPS64 only select this option if you have hardware that actually has a 64-bit processor and if your application will actually benefit from 64-bit processing, otherwise say N. You must say Y for kernels for - SGI IP27 (Origin 200 and 2000). If in doubt say N. + SGI IP27 (Origin 200 and 2000) and SGI IP32 (O2). If in doubt say N. config 64BIT def_bool MIPS64 @@ -66,14 +66,6 @@ config OLIVETTI_M700 the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at . -config BAGET_MIPS - bool "Support for BAGET MIPS series (EXPERIMENTAL)" - depends on MIPS32 && EXPERIMENTAL - help - This enables support for the Baget, a Russian embedded system. For - more details about the Baget see the Linux/MIPS FAQ on - . - config MACH_VR41XX bool "Support for NEC VR41XX-based machines" @@ -146,6 +138,7 @@ config TOSHIBA_JMR3927 depends on MIPS32 select DMA_NONCOHERENT select HW_HAS_PCI + select SWAP_IO_SPACE config MIPS_COBALT bool "Support for Cobalt Server (EXPERIMENTAL)" @@ -198,6 +191,7 @@ config MIPS_EV96100 select IRQ_CPU select MIPS_GT96100 select RM7000_CPU_SCACHE + select SWAP_IO_SPACE help This is an evaluation board based on the Galileo GT-96100 LAN/WAN communications controllers containing a MIPS R5000 compatible core @@ -237,13 +231,6 @@ config LASAT_SYSCTL bool "LASAT sysctl interface" depends on LASAT -config HP_LASERJET - bool "Support for Hewlett Packard LaserJet board" - depends on BROKEN - select DMA_NONCOHERENT - select HW_HAS_PCI - select IRQ_CPU - config MIPS_ITE8172 bool "Support for ITE 8172G board" select DMA_NONCOHERENT @@ -268,6 +255,7 @@ config MIPS_ATLAS bool "Support for MIPS Atlas board" select DMA_NONCOHERENT select HW_HAS_PCI + select SWAP_IO_SPACE help This enables support for the QED R5231-based MIPS Atlas evaluation board. @@ -277,6 +265,7 @@ config MIPS_MALTA select HAVE_STD_PC_SERIAL_PORT select DMA_NONCOHERENT select HW_HAS_PCI + select SWAP_IO_SPACE help This enables support for the VR5000-based MIPS Malta evaluation board. @@ -294,6 +283,7 @@ config MOMENCO_OCELOT select IRQ_CPU select IRQ_CPU_RM7K select RM7000_CPU_SCACHE + select SWAP_IO_SPACE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -306,6 +296,7 @@ config MOMENCO_OCELOT_G select IRQ_CPU_RM7K select PCI_MARVELL select RM7000_CPU_SCACHE + select SWAP_IO_SPACE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -318,10 +309,25 @@ config MOMENCO_OCELOT_C select IRQ_MV64340 select PCI_MARVELL select RM7000_CPU_SCACHE + select SWAP_IO_SPACE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . +config MOMENCO_OCELOT_3 + bool "Support for Momentum Ocelot-3 board" + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU + select IRQ_CPU_RM7K + select IRQ_MV64340 + select PCI_MARVELL + select RM7000_CPU_SCACHE + select SWAP_IO_SPACE + help + The Ocelot-3 is based off Discovery III System Controller and + PMC-Sierra Rm79000 core. + config MOMENCO_JAGUAR_ATX bool "Support for Momentum Jaguar board" select DMA_NONCOHERENT @@ -332,6 +338,7 @@ config MOMENCO_JAGUAR_ATX select LIMITED_DMA select PCI_MARVELL select RM7000_CPU_SCACHE + select SWAP_IO_SPACE help The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -349,6 +356,7 @@ config PMC_YOSEMITE select HW_HAS_PCI select IRQ_CPU select IRQ_CPU_RM7K + select SWAP_IO_SPACE help Yosemite is an evaluation board for the RM9000x2 processor manufactured by PMC-Sierra @@ -381,7 +389,7 @@ config DDB5476 evaluation board. Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port USB, AC97, PCI, PCI VGA card & framebuffer console, + ether port USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller, PS2 keyboard, PS2 mouse, etc. config DDB5477 @@ -400,7 +408,7 @@ config DDB5477_BUS_FREQUENCY int "bus frequency (in kHZ, 0 for auto-detect)" depends on DDB5477 default 0 - + config NEC_OSPREY bool "Support for NEC Osprey board" select DMA_NONCOHERENT @@ -411,6 +419,7 @@ config SGI_IP22 select DMA_NONCOHERENT select IP22_CPU_SCACHE select IRQ_CPU + select SWAP_IO_SPACE help This are the SGI Indy, Challenge S and Indigo2, as well as certain OEM variants like the Tandem CMN B006S. To compile a Linux kernel @@ -421,6 +430,7 @@ config SGI_IP27 depends on MIPS64 select DMA_IP27 select HW_HAS_PCI + select PCI_DOMAINS help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -462,9 +472,9 @@ config MAPPED_KERNEL bool "Mapped kernel support" depends on SGI_IP27 help - Change the way a Linux kernel is loaded unto memory on a MIPS64 + Change the way a Linux kernel is loaded into 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. + NUMA. If you need to understand it, read the source code. config REPLICATE_KTEXT bool "Kernel text replication support" @@ -483,7 +493,7 @@ config REPLICATE_EXHANDLERS config SGI_IP32 bool "Support for SGI IP32 (O2) (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on MIPS64 && EXPERIMENTAL select DMA_NONCOHERENT select HW_HAS_PCI select R5000_CPU_SCACHE @@ -513,15 +523,15 @@ config SOC_AU1550 endchoice -choice +choice prompt "AMD/Alchemy Au1x00 board support" depends on SOC_AU1X00 help These are evaluation boards built by AMD/Alchemy to showcase their Au1X00 Internet Edge Processors. The SOC design - is based on the MIPS32 architecture running at 266/400/500MHz - with many integrated peripherals. Further information can be - found at their website, . Say Y here if you + is based on the MIPS32 architecture running at 266/400/500MHz + with many integrated peripherals. Further information can be + found at their website, . Say Y here if you wish to build a kernel for this platform. config MIPS_PB1000 @@ -529,24 +539,27 @@ config MIPS_PB1000 depends on SOC_AU1000 select DMA_NONCOHERENT select HW_HAS_PCI + select SWAP_IO_SPACE config MIPS_PB1100 bool "PB1100 board" depends on SOC_AU1100 select DMA_NONCOHERENT select HW_HAS_PCI + select SWAP_IO_SPACE config MIPS_PB1500 bool "PB1500 board" depends on SOC_AU1500 - select DMA_NONCOHERENT + select DMA_COHERENT select HW_HAS_PCI config MIPS_PB1550 bool "PB1550 board" depends on SOC_AU1550 - select DMA_NONCOHERENT + select DMA_COHERENT select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE config MIPS_DB1000 bool "DB1000 board" @@ -562,13 +575,16 @@ config MIPS_DB1100 config MIPS_DB1500 bool "DB1500 board" depends on SOC_AU1500 - select DMA_NONCOHERENT + select DMA_COHERENT select HW_HAS_PCI + select MIPS_DISABLE_OBSOLETE_IDE config MIPS_DB1550 bool "DB1550 board" depends on SOC_AU1550 select HW_HAS_PCI + select DMA_COHERENT + select MIPS_DISABLE_OBSOLETE_IDE config MIPS_BOSPORUS bool "Bosporus board" @@ -596,6 +612,7 @@ config SIBYTE_SB1xxx_SOC bool "Support for Broadcom BCM1xxx SOCs (EXPERIMENTAL)" depends on EXPERIMENTAL select DMA_COHERENT + select SWAP_IO_SPACE choice prompt "BCM1xxx SOC-based board" @@ -817,7 +834,16 @@ config TOSHIBA_RBTX4927 depends on MIPS32 select DMA_NONCOHERENT select HW_HAS_PCI + select I8259 select ISA + select SWAP_IO_SPACE + help + This Toshiba board is based on the TX4927 processor. Say Y here to + support this machine type + +config TOSHIBA_FPCIB0 + bool "FPCIB0 Backplane Support" + depends on TOSHIBA_RBTX4927 config RWSEM_GENERIC_SPINLOCK bool @@ -881,10 +907,13 @@ config MIPS_NILE4 depends on LASAT default y +config MIPS_DISABLE_OBSOLETE_IDE + bool + config CPU_LITTLE_ENDIAN bool "Generate little endian code" - default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || NEC_OSPREY || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA - default n if BAGET_MIPS || MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927 + default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || NEC_OSPREY || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA + default n if MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927 help Some MIPS machines can be configured for either little or big endian byte order. These modes require different kernels. Say Y if your @@ -934,8 +963,6 @@ config ITE_BOARD_GEN config SWAP_IO_SPACE bool - depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1xxx_SOC || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MOMENCO_JAGUAR_ATX || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000 - default y # # Unfortunately not all GT64120 systems run the chip at the same clock. @@ -984,7 +1011,7 @@ config IT8712 config BOOT_ELF32 bool - depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI + depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT_3 || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI default y config MIPS_L1_CACHE_SHIFT @@ -1033,11 +1060,6 @@ config FB (e.g. an accelerated X server) and that are not frame buffer device-aware may cause unexpected results. If unsure, say N. -config FB_G364 - bool - depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - config HAVE_STD_PC_SERIAL_PORT bool @@ -1091,7 +1113,6 @@ config TANBAC_TB0219 endmenu - menu "CPU selection" choice @@ -1157,9 +1178,9 @@ config CPU_R6000 processors are extremly rare and the support for them is incomplete. config CPU_NEVADA - bool "R52xx" + bool "RM52xx" help - MIPS Technologies R52x0-series ("Nevada") processors. + QED / PMC-Sierra RM52xx-series ("Nevada") processors. config CPU_R8000 bool "R8000" @@ -1194,7 +1215,7 @@ config PAGE_SIZE_4KB This option select the standard 4kB Linux page size. On some R3000-family processors this is the only available page size. Using 4kB page size will minimize memory consumption and is therefore - recommended for low memory systems. + recommended for low memory systems. config PAGE_SIZE_8KB bool "8kB" @@ -1334,7 +1355,7 @@ config CPU_HAS_SYNC # config HIGHMEM bool "High Memory Support" - depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(BAGET_MIPS || MACH_DECSTATION || MOMENCO_JAGUAR_ATX) + depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX) config SMP bool "Multi-Processing support" @@ -1382,21 +1403,6 @@ config PREEMPT This allows applications to run more reliably even when the system is under load. -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - config RTC_DS1742 bool "DS1742 BRAM/RTC support" depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 @@ -1436,6 +1442,10 @@ config PCI information about which PCI hardware does work under Linux and which doesn't. +config PCI_DOMAINS + bool + depends on PCI + source "drivers/pci/Kconfig" # @@ -1502,9 +1512,24 @@ config TRAD_SIGNALS bool default y if MIPS32 +config BUILD_ELF64 + bool "Use 64-bit ELF format for building" + depends on MIPS64 + help + A 64-bit kernel is usually built using the 64-bit ELF binary object + format as it's one that allows arbitrary 64-bit constructs. For + kernels that are loaded within the KSEG compatibility segments the + 32-bit ELF format can optionally be used resulting in a somewhat + smaller binary, but this option is not explicitly supported by the + toolchain and since binutils 2.14 it does not even work at all. + + Say Y to use the 64-bit format or N to use the 32-bit one. + + If unsure say Y. + config BINFMT_IRIX bool "Include IRIX binary compatibility" - depends on !CPU_LITTLE_ENDIAN && MIPS32 + depends on !CPU_LITTLE_ENDIAN && MIPS32 && BROKEN config MIPS32_COMPAT bool "Kernel support for Linux/MIPS 32-bit binary compatibility" @@ -1550,144 +1575,25 @@ config PM endmenu -menu "MIPS initrd options" - depends on BLK_DEV_INITRD - -config EMBEDDED_RAMDISK - bool "Embed root filesystem ramdisk into the kernel" - -config EMBEDDED_RAMDISK_IMAGE - string "Filename of gziped ramdisk image" - depends on EMBEDDED_RAMDISK - default "ramdisk.gz" - help - This is the filename of the ramdisk image to be built into the - kernel. Relative pathnames are relative to arch/mips/ramdisk/. - The ramdisk image is not part of the kernel distribution; you must - provide one yourself. - -endmenu - source "drivers/Kconfig" source "fs/Kconfig" -menu "Kernel hacking" - -config CROSSCOMPILE - bool "Are you using a crosscompiler" - help - Say Y here if you are compiling the kernel on a different - architecture than the one it is intended to run on. - -config CMDLINE - string "Default kernel command string" - default "" - help - On some platforms, there is currently no way for the boot loader to - pass arguments to the kernel. For these platforms, you can supply - some command-line options at build time by entering them here. In - other cases you can specify kernel args so that you don't have - to set them up in board prom initialization routines. - -config DEBUG_KERNEL - bool "Kernel debugging" - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config KGDB - bool "Remote GDB kernel debugging" - depends on DEBUG_KERNEL - select DEBUG_INFO - help - If you say Y here, it will be possible to remotely debug the MIPS - kernel using gdb. This enlarges your kernel image disk size by - several megabytes and requires a machine with more than 16 MB, - better 32 MB RAM to avoid excessive linking time. This is only - useful for kernel hackers. If unsure, say N. - -config GDB_CONSOLE - bool "Console output to GDB" - depends on KGDB - help - 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'. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config SB1XXX_CORELIS - bool "Corelis Debugger" - depends on SIBYTE_SB1xxx_SOC - select DEBUG_INFO - help - Select compile flags that produce code that can be processed by the - Corelis mksym utility and UDB Emulator. - -config RUNTIME_DEBUG - bool "Enable run-time debugging" - depends on DEBUG_KERNEL - help - If you say Y here, some debugging macros will do run-time checking. - If you say N here, those macros will mostly turn to no-ops. See - include/asm-mips/debug.h for debuging macros. - If unsure, say N. - - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config MIPS_UNCACHED - bool "Run uncached" - depends on DEBUG_KERNEL && !SMP && !SGI_IP27 - help - If you say Y here there kernel will disable all CPU caches. This will - reduce the system's performance dramatically but can help finding - otherwise hard to track bugs. It can also useful if you're doing - hardware debugging with a logic analyzer and need to see all traffic - on the bus. - -config DEBUG_HIGHMEM - bool "Highmem debugging" - depends on DEBUG_KERNEL && HIGHMEM - -endmenu +source "arch/mips/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" + +# +# Use the generic interrupt handling code in kernel/irq/: +# +config GENERIC_HARDIRQS + bool + default y + +config GENERIC_IRQ_PROBE + bool + default y diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 371558708..d90281ace 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -5,13 +5,19 @@ # # Copyright (C) 1994, 95, 96, 2003 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 -# Copyright (C) 2002, 2003 Maciej W. Rozycki +# Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions # for "archclean" cleaning up for this architecture. # +as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \ + -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \ + else echo "$(2)"; fi ;) + +cflags-y := + # # Select the object file format to substitute into the linker script. # @@ -20,22 +26,24 @@ ifdef CONFIG_CPU_LITTLE_ENDIAN 64bit-tool-prefix = mips64el-linux- 32bit-bfd = elf32-tradlittlemips 64bit-bfd = elf64-tradlittlemips +32bit-emul = elf32ltsmip +64bit-emul = elf64ltsmip else 32bit-tool-prefix = mips-linux- 64bit-tool-prefix = mips64-linux- 32bit-bfd = elf32-tradbigmips 64bit-bfd = elf64-tradbigmips +32bit-emul = elf32btsmip +64bit-emul = elf64btsmip endif ifdef CONFIG_MIPS32 gcc-abi = 32 -gas-abi = 32 tool-prefix = $(32bit-tool-prefix) UTS_MACHINE := mips endif ifdef CONFIG_MIPS64 gcc-abi = 64 -gas-abi = 32 tool-prefix = $(64bit-tool-prefix) UTS_MACHINE := mips64 endif @@ -44,6 +52,20 @@ ifdef CONFIG_CROSSCOMPILE CROSS_COMPILE := $(tool-prefix) endif +ifdef CONFIG_BUILD_ELF64 +gas-abi = 64 +ld-emul = $(64bit-emul) +vmlinux-32 = vmlinux.32 +vmlinux-64 = vmlinux +else +gas-abi = 32 +ld-emul = $(32bit-emul) +vmlinux-32 = vmlinux +vmlinux-64 = vmlinux.64 + +cflags-$(CONFIG_MIPS64) += $(call cc-option,-mno-explicit-relocs) +endif + # # GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel # code since it only slows down the whole thing. At some point we might make @@ -54,16 +76,14 @@ endif # machines may also. Since BFD is incredibly buggy with respect to # crossformat linking we rely on the elf2ecoff tool for format conversion. # -cflags-y := -I $(TOPDIR)/include/asm/gcc +cflags-y += -I $(TOPDIR)/include/asm/gcc cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -cflags-y += $(call check_gcc, -finline-limit=100000,) +cflags-y += $(call cc-option, -finline-limit=100000) LDFLAGS_vmlinux += -G 0 -static -n MODFLAGS += -mlong-calls cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer -check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) - # # Use: $(call set_gccflags,,,,,) # @@ -143,6 +163,10 @@ cflags-$(CONFIG_CPU_R4X00) += \ $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ -Wa,--trap +cflags-$(CONFIG_CPU_TX49XX) += \ + $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ + -Wa,--trap + cflags-$(CONFIG_CPU_MIPS32) += \ $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \ -Wa,--trap @@ -162,7 +186,7 @@ cflags-$(CONFIG_CPU_R5432) += \ cflags-$(CONFIG_CPU_NEVADA) += \ $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \ -Wa,--trap -# $(call check_gcc,-mmad,) +# $(call cc-option,-mmad) cflags-$(CONFIG_CPU_RM7000) += \ $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \ @@ -190,14 +214,6 @@ MODFLAGS += -msb1-pass1-workarounds endif endif -# -# ramdisk/initrd support -# You need a compressed ramdisk image, named -# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames -# are relative to arch/mips/ramdisk/. -# -core-$(CONFIG_EMBEDDED_RAMDISK) += arch/mips/ramdisk/ - # # Firmware support # @@ -213,7 +229,7 @@ libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ # core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz -load-$(CONFIG_MACH_JAZZ) += 0x80080000 +load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # # Common Alchemy Au1x00 stuff @@ -226,87 +242,88 @@ cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 # libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/ cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 -load-$(CONFIG_MIPS_PB1000) += 0x80100000 +load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 # # AMD Alchemy Pb1100 eval board # libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/ cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 -load-$(CONFIG_MIPS_PB1100) += 0x80100000 +load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 # # AMD Alchemy Pb1500 eval board # libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 -load-$(CONFIG_MIPS_PB1500) += 0x80100000 +load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 # # AMD Alchemy Pb1550 eval board # libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 -load-$(CONFIG_MIPS_PB1550) += 0x80100000 +load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Db1000 eval board # libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 -load-$(CONFIG_MIPS_DB1000) += 0x80100000 +load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # # AMD Alchemy Db1100 eval board # libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 -load-$(CONFIG_MIPS_DB1100) += 0x80100000 +load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 # # AMD Alchemy Db1500 eval board # libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 -load-$(CONFIG_MIPS_DB1500) += 0x80100000 +load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 + +# +# AMD Alchemy Db1550 eval board +# +libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Bosporus eval board # libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 -load-$(CONFIG_MIPS_BOSPORUS) += 0x80100000 +load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 # # AMD Alchemy Mirage eval board # libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 -load-$(CONFIG_MIPS_MIRAGE) += 0x80100000 +load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 # # 4G-Systems eval board # libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/ -load-$(CONFIG_MIPS_MTX1) += 0x80100000 +load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000 # # MyCable eval board # libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/ -load-$(CONFIG_MIPS_XXS1500) += 0x80100000 - -# -# Baget/MIPS -# -libs-$(CONFIG_BAGET_MIPS) += arch/mips/baget/ arch/mips/baget/prom/ -load-$(CONFIG_BAGET_MIPS) += 0x80001000 +load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000 # # Cobalt Server # core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ -load-$(CONFIG_MIPS_COBALT) += 0x80080000 +load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 # # DECstation family @@ -314,7 +331,7 @@ load-$(CONFIG_MIPS_COBALT) += 0x80080000 core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ -load-$(CONFIG_MACH_DECSTATION) += 0x80040000 +load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000 CLEAN_FILES += drivers/tc/lk201-map.c # @@ -323,33 +340,27 @@ CLEAN_FILES += drivers/tc/lk201-map.c core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/ev64120/ core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/common/ cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120 -load-$(CONFIG_MIPS_EV64120) += 0x80100000 +load-$(CONFIG_MIPS_EV64120) += 0xffffffff80100000 # # Galileo EV96100 Board # core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/ev96100/ cflags-$(CONFIG_MIPS_EV96100) += -Iinclude/asm-mips/mach-ev96100 -load-$(CONFIG_MIPS_EV96100) += 0x80100000 +load-$(CONFIG_MIPS_EV96100) += 0xffffffff80100000 # # Globespan IVR eval board with QED 5231 CPU # core-$(CONFIG_ITE_BOARD_GEN) += arch/mips/ite-boards/generic/ core-$(CONFIG_MIPS_IVR) += arch/mips/ite-boards/ivr/ -load-$(CONFIG_MIPS_IVR) += 0x80100000 - -# -# HP LaserJet -# -core-$(CONFIG_HP_LASERJET) += arch/mips/hp-lj/ -load-$(CONFIG_HP_LASERJET) += 0x80030000 +load-$(CONFIG_MIPS_IVR) += 0xffffffff80100000 # # ITE 8172 eval board with QED 5231 CPU # core-$(CONFIG_MIPS_ITE8172) += arch/mips/ite-boards/qed-4n-s01b/ -load-$(CONFIG_MIPS_ITE8172) += 0x80100000 +load-$(CONFIG_MIPS_ITE8172) += 0xffffffff80100000 # # For all MIPS, Inc. eval boards @@ -362,20 +373,20 @@ core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/ core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips -load-$(CONFIG_MIPS_ATLAS) += 0x80100000 +load-$(CONFIG_MIPS_ATLAS) += 0xffffffff80100000 # # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips -load-$(CONFIG_MIPS_MALTA) += 0x80100000 +load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 # # MIPS SEAD board # core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/ -load-$(CONFIG_MIPS_SEAD) += 0x80100000 +load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 # # Momentum Ocelot board @@ -386,7 +397,7 @@ load-$(CONFIG_MIPS_SEAD) += 0x80100000 core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \ arch/mips/gt64120/momenco_ocelot/ cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot -load-$(CONFIG_MOMENCO_OCELOT) += 0x80100000 +load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000 # # Momentum Ocelot-G board @@ -395,7 +406,7 @@ load-$(CONFIG_MOMENCO_OCELOT) += 0x80100000 # mips_io_port_base. # core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/ -load-$(CONFIG_MOMENCO_OCELOT_G) += 0x80100000 +load-$(CONFIG_MOMENCO_OCELOT_G) += 0xffffffff80100000 # # Momentum Ocelot-C and -CS boards @@ -403,14 +414,21 @@ load-$(CONFIG_MOMENCO_OCELOT_G) += 0x80100000 # The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the # mips_io_port_base. core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/ -load-$(CONFIG_MOMENCO_OCELOT_C) += 0x80100000 +load-$(CONFIG_MOMENCO_OCELOT_C) += 0xffffffff80100000 # # PMC-Sierra Yosemite # core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/ cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite -load-$(CONFIG_PMC_YOSEMITE) += 0x80100000 +load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 + +# +# Momentum Ocelot-3 +# +core-$(CONFIG_MOMENCO_OCELOT_3) += arch/mips/momentum/ocelot_3/ +cflags-$(CONFIG_MOMENCO_OCELOT_3) += -Iinclude/asm-mips/mach-ocelot3 +load-$(CONFIG_MOMENCO_OCELOT_3) += 0xffffffff80100000 # # Momentum Jaguar ATX @@ -418,9 +436,9 @@ load-$(CONFIG_PMC_YOSEMITE) += 0x80100000 core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/ cflags-$(CONFIG_MOMENCO_JAGUAR_ATX) += -Iinclude/asm-mips/mach-ja #ifdef CONFIG_JAGUAR_DMALOW -#load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0x88000000 +#load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff88000000 #else -load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0x80100000 +load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff80100000 #endif # @@ -432,30 +450,30 @@ core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/ # NEC DDB Vrc-5074 # core-$(CONFIG_DDB5074) += arch/mips/ddb5xxx/ddb5074/ -load-$(CONFIG_DDB5074) += 0x80080000 +load-$(CONFIG_DDB5074) += 0xffffffff80080000 # # NEC DDB Vrc-5476 # core-$(CONFIG_DDB5476) += arch/mips/ddb5xxx/ddb5476/ -load-$(CONFIG_DDB5476) += 0x80080000 +load-$(CONFIG_DDB5476) += 0xffffffff80080000 # # NEC DDB Vrc-5477 # core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/ -load-$(CONFIG_DDB5477) += 0x80100000 +load-$(CONFIG_DDB5477) += 0xffffffff80100000 core-$(CONFIG_LASAT) += arch/mips/lasat/ cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat -load-$(CONFIG_LASAT) += 0x80000000 +load-$(CONFIG_LASAT) += 0xffffffff80000000 # # NEC Osprey (vr4181) board # core-$(CONFIG_NEC_OSPREY) += arch/mips/vr4181/common/ \ arch/mips/vr4181/osprey/ -load-$(CONFIG_NEC_OSPREY) += 0x80002000 +load-$(CONFIG_NEC_OSPREY) += 0xffffffff80002000 # # Common VR41xx @@ -467,70 +485,84 @@ cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx # ZAO Networks Capcella (VR4131) # core-$(CONFIG_ZAO_CAPCELLA) += arch/mips/vr41xx/zao-capcella/ -load-$(CONFIG_ZAO_CAPCELLA) += 0x80000000 +load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000 # # Victor MP-C303/304 (VR4122) # core-$(CONFIG_VICTOR_MPC30X) += arch/mips/vr41xx/victor-mpc30x/ -load-$(CONFIG_VICTOR_MPC30X) += 0x80001000 +load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000 # # IBM WorkPad z50 (VR4121) # core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/ -load-$(CONFIG_IBM_WORKPAD) += 0x80004000 +load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000 # # CASIO CASSIPEIA E-55/65 (VR4111) # core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/ -load-$(CONFIG_CASIO_E55) += 0x80004000 +load-$(CONFIG_CASIO_E55) += 0xffffffff80004000 # # TANBAC TB0226 Mbase (VR4131) # core-$(CONFIG_TANBAC_TB0226) += arch/mips/vr41xx/tanbac-tb0226/ -load-$(CONFIG_TANBAC_TB0226) += 0x80000000 +load-$(CONFIG_TANBAC_TB0226) += 0xffffffff80000000 # # TANBAC TB0229 VR4131DIMM (VR4131) # core-$(CONFIG_TANBAC_TB0229) += arch/mips/vr41xx/tanbac-tb0229/ -load-$(CONFIG_TANBAC_TB0229) += 0x80000000 +load-$(CONFIG_TANBAC_TB0229) += 0xffffffff80000000 # # SGI IP22 (Indy/Indigo2) # -# Set the load address to >= 0x88069000 if you want to leave space for symmon, -# 0x80002000 for production kernels. Note that the value must be aligned to -# a multiple of the kernel stack size or the handling of the current variable -# will break so for 64-bit kernels we have to raise the start address by 8kb. +# Set the load address to >= 0xffffffff88069000 if you want to leave space for +# symmon, 0xffffffff80002000 for production kernels. Note that the value must +# be aligned to a multiple of the kernel stack size or the handling of the +# current variable will break so for 64-bit kernels we have to raise the start +# address by 8kb. # core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22 ifdef CONFIG_MIPS32 -load-$(CONFIG_SGI_IP22) += 0x88002000 +load-$(CONFIG_SGI_IP22) += 0xffffffff88002000 endif ifdef CONFIG_MIPS64 -load-$(CONFIG_SGI_IP22) += 0x88004000 +load-$(CONFIG_SGI_IP22) += 0xffffffff88004000 endif # # SGI-IP27 (Origin200/2000) # # Set the load address to >= 0xc000000000300000 if you want to leave space for -# symmon, 0xc00000000001c000 for production kernels. Note that the value -# must be 16kb aligned or the handling of the current variable will break. +# symmon, 0xc00000000001c000 for production kernels. Note that the value must +# be 16kb aligned or the handling of the current variable will break. # ifdef CONFIG_SGI_IP27 core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 -#load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 +ifdef CONFIG_BUILD_ELF64 +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 +OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 +dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 +else +load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 +OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 +endif +else ifdef CONFIG_MAPPED_KERNEL -load-$(CONFIG_SGI_IP27) += 0xc001c000 +load-$(CONFIG_SGI_IP27) += 0xffffffffc001c000 +OBJCOPYFLAGS := --change-addresses=0xc000000080000000 +dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 else -load-$(CONFIG_SGI_IP27) += 0x8001c000 +load-$(CONFIG_SGI_IP27) += 0xffffffff8001c000 +OBJCOPYFLAGS := --change-addresses=0xa800000080000000 +endif endif endif @@ -538,18 +570,13 @@ endif # SGI-IP32 (O2) # # Set the load address to >= 80069000 if you want to leave space for symmon, -# 0x80002000 for production kernels. Note that the value must be aligned to +# 0xffffffff80004000 for production kernels. Note that the value must be aligned to # a multiple of the kernel stack size or the handling of the current variable -# will break so for 64-bit kernels we have to raise the start address by 8kb. +# will break. # core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 -ifdef CONFIG_MIPS32 -load-$(CONFIG_SGI_IP32) += 0x80002000 -endif -ifdef CONFIG_MIPS64 -load-$(CONFIG_SGI_IP32) += 0x80004000 -endif +load-$(CONFIG_SGI_IP32) += 0xffffffff80004000 # # Sibyte SB1250 SOC @@ -559,8 +586,10 @@ endif # removed (as happens, even if they have __initcall/module_init) # core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ +cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ +cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte # # Sibyte BCM91120x (Carmel) board @@ -570,31 +599,31 @@ core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ # Sibyte SWARM board # libs-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CARMEL) := 0x80100000 +load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 libs-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHINE) := 0x80100000 +load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000 libs-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_CRHONE) := 0x80100000 +load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000 libs-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_RHONE) := 0x80100000 +load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SENTOSA) := 0x80100000 +load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 libs-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ -load-$(CONFIG_SIBYTE_SWARM) := 0x80100000 +load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 # # SNI RM200 PCI # core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/ cflags-$(CONFIG_SNI_RM200_PCI) += -Iinclude/asm-mips/mach-rm200 -load-$(CONFIG_SNI_RM200_PCI) += 0x80600000 +load-$(CONFIG_SNI_RM200_PCI) += 0xffffffff80600000 # # Toshiba JMR-TX3927 board # core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/jmr3927/rbhma3100/ \ arch/mips/jmr3927/common/ -load-$(CONFIG_TOSHIBA_JMR3927) += 0x80050000 +load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000 # # Toshiba RBTX4927 board or @@ -602,20 +631,11 @@ load-$(CONFIG_TOSHIBA_JMR3927) += 0x80050000 # core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/ -load-$(CONFIG_TOSHIBA_RBTX4927) += 0x80020000 +load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000 cflags-y += -Iinclude/asm-mips/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ -ifdef CONFIG_MIPS32 -build-bfd = $(32bit-bfd) -cflags-y += $(32bit-isa-y) -endif -ifdef CONFIG_MIPS64 -build-bfd = $(64bit-bfd) -cflags-y += $(64bit-isa-y) -endif - ifdef CONFIG_MIPS32 ifdef CONFIG_CPU_LITTLE_ENDIAN JIFFIES = jiffies_64 @@ -626,16 +646,12 @@ else JIFFIES = jiffies_64 endif -# -# Some machines like the Indy need 32-bit ELF binaries for booting purposes. -# Other need ECOFF, so we build a 32-bit ELF binary for them which we then -# convert to ECOFF using elf2ecoff. -# -# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit -# ELF files from 32-bit files by conversion. -# -#AS += -64 -#LDFLAGS += -m elf64bmip +AFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) + +LDFLAGS += -m $(ld-emul) + +OBJCOPYFLAGS += --remove-section=.reginfo # # Choosing incompatible machines durings configuration will result in @@ -643,15 +659,11 @@ endif # none has been choosen above. # -AFLAGS_vmlinux.lds.o := \ +CPPFLAGS_vmlinux.lds := \ + $(CFLAGS) \ -D"LOADADDR=$(load-y)" \ -D"JIFFIES=$(JIFFIES)" \ - -imacros $(srctree)/include/asm-$(ARCH)/sn/mapped_kernel.h - -AFLAGS += $(cflags-y) -CFLAGS += $(cflags-y) - -LDFLAGS += --oformat $(32bit-bfd) + -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)" head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o @@ -661,44 +673,44 @@ libs-$(CONFIG_MIPS64) += arch/mips/lib-64/ core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/ -ifdef CONFIG_BAGET_MIPS - -BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget - -balo: vmlinux - $(BAGETBOOT) balo - -endif - ifdef CONFIG_LASAT rom.bin rom.sw: vmlinux $(call descend,arch/mips/lasat/image,$@) endif -ifdef CONFIG_MAPPED_KERNEL -vmlinux.64: vmlinux - $(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \ - --change-addresses=0xc000000080000000 $< $@ -else +# +# Some machines like the Indy need 32-bit ELF binaries for booting purposes. +# Other need ECOFF, so we build a 32-bit ELF binary for them which we then +# convert to ECOFF using elf2ecoff. +# +vmlinux.32: vmlinux + $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@ + +# +# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit +# ELF files from 32-bit files by conversion. +# vmlinux.64: vmlinux - $(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \ - --change-addresses=0xa800000080000000 $< $@ -endif + $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@ -makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot $(1) +makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1) -ifdef CONFIG_SGI_IP27 -all: vmlinux.64 +ifdef CONFIG_BOOT_ELF32 +all: $(vmlinux-32) +endif + +ifdef CONFIG_BOOT_ELF64 +all: $(vmlinux-64) endif ifdef CONFIG_SNI_RM200_PCI all: vmlinux.ecoff endif -vmlinux.ecoff vmlinux.rm200: vmlinux +vmlinux.ecoff vmlinux.rm200: $(vmlinux-32) +@$(call makeboot,$@) -vmlinux.srec: vmlinux +vmlinux.srec: $(vmlinux-32) +@$(call makeboot,$@) CLEAN_FILES += vmlinux.ecoff \ @@ -708,7 +720,6 @@ CLEAN_FILES += vmlinux.ecoff \ archclean: @$(MAKE) $(clean)=arch/mips/boot - @$(MAKE) $(clean)=arch/mips/baget @$(MAKE) $(clean)=arch/mips/lasat # Generate #include #include +#include -#include #include #include #include @@ -91,10 +91,10 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { #elif defined(CONFIG_SOC_AU1500) - { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, - { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, @@ -117,16 +117,16 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, - { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, #elif defined(CONFIG_SOC_AU1100) - { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, - { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, - { 2/*AU1000_SD_INT*/, INTC_INT_HIGH_LEVEL, 0}, - { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, @@ -151,9 +151,9 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, /*{ AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0},*/ - /*{ AU1000_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },*/ + { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, #elif defined(CONFIG_SOC_AU1550) @@ -187,6 +187,32 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, +#elif defined(CONFIG_SOC_AU1200) + + { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, + { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, + { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0}, + #else #error "Error: Unknown Alchemy SOC" #endif diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c index 26744b317..84e6cf36f 100644 --- a/arch/mips/au1000/common/cputable.c +++ b/arch/mips/au1000/common/cputable.c @@ -39,6 +39,7 @@ struct cpu_spec cpu_specs[] = { { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, + { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index 9f6c61c25..defdf5b38 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c @@ -37,10 +37,13 @@ #include #include #include +#include #include #include #include +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) + /* * The Descriptor Based DMA supports up to 16 channels. * @@ -63,6 +66,7 @@ static int dbdma_initialized; static void au1xxx_dbdma_init(void); typedef struct dbdma_device_table { + u32 dev_id; u32 dev_flags; u32 dev_tsize; u32 dev_devwidth; @@ -89,64 +93,116 @@ typedef struct dbdma_chan_config { #define DEV_FLAGS_IN (1 << 3) static dbdev_tab_t dbdev_tab[] = { +#ifdef CONFIG_SOC_AU1550 /* UARTS */ - { DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, - { DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, - { DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 }, - { DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 }, + { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, + { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, + { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 }, + { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 }, /* EXT DMA */ - { 0, 0, 0, 0x00000000, 0, 0 }, - { 0, 0, 0, 0x00000000, 0, 0 }, - { 0, 0, 0, 0x00000000, 0, 0 }, - { 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 }, /* USB DEV */ - { DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 }, - { DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 }, - { DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 }, - { DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 }, - { DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 }, - { DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 }, + { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 }, + { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 }, + { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 }, + { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 }, + { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 }, + { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 }, /* PSC 0 */ - { DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, - { DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, /* PSC 1 */ - { DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, - { DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, /* PSC 2 */ - { DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 }, - { DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 }, + { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 }, + { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 }, /* PSC 3 */ - { DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 }, - { DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 }, + { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 }, + { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 }, - { 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */ - { 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */ + { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */ + { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */ /* MAC 0 */ - { DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - { DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, /* MAC 1 */ - { DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - { DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + +#endif /* CONFIG_SOC_AU1550 */ + +#ifdef CONFIG_SOC_AU1200 + { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 }, + { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 }, + { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 }, + { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 }, + + { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, + { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, + { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + + { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, - /* reserved */ - { DEV_FLAGS_INUSE, 0, 0, 0x00000000, 0, 0 }, - { DEV_FLAGS_INUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, - /* Memory */ - { DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* throttle */ - { DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* always */ +#endif // CONFIG_SOC_AU1200 + + { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, }; +#define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) + static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS]; +static dbdev_tab_t * +find_dbdev_id (u32 id) +{ + int i; + dbdev_tab_t *p; + for (i = 0; i < DBDEV_TAB_SIZE; ++i) { + p = &dbdev_tab[i]; + if (p->dev_id == id) + return p; + } + return NULL; +} + /* Allocate a channel and return a non-zero descriptor if successful. */ u32 @@ -172,8 +228,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS)) return 0; - stp = &dbdev_tab[srcid]; - dtp = &dbdev_tab[destid]; + if ((stp = find_dbdev_id(srcid)) == NULL) return 0; + if ((dtp = find_dbdev_id(destid)) == NULL) return 0; + used = 0; rv = 0; @@ -212,7 +269,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, /* If kmalloc fails, it is caught below same * as a channel not available. */ - ctp = (chan_tab_t *)kmalloc(sizeof(chan_tab_t), GFP_KERNEL); + ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL); chan_tab_ptr[i] = ctp; ctp->chan_index = chan = i; break; @@ -313,7 +370,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) * and if we try that first we are likely to not waste larger * slabs of memory. */ - desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL); + desc_base = kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL); if (desc_base == 0) return 0; @@ -324,7 +381,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) kfree((const void *)desc_base); i = entries * sizeof(au1x_ddma_desc_t); i += (sizeof(au1x_ddma_desc_t) - 1); - if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0) + if ((desc_base = kmalloc(i, GFP_KERNEL)) == 0) return 0; desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); @@ -337,8 +394,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) /* Initialize the rings with as much information as we know. */ - srcid = stp - dbdev_tab; /* Index is channel device ID */ - destid = dtp - dbdev_tab; + srcid = stp->dev_id; + destid = dtp->dev_id; cmd0 = cmd1 = src1 = dest1 = 0; src0 = dest0 = 0; @@ -691,7 +748,7 @@ au1xxx_dbdma_chan_free(u32 chanid) kfree(ctp); } -static void +static irqreturn_t dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) { u32 intstat; @@ -718,6 +775,7 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); + return IRQ_HANDLED; } static void @@ -773,3 +831,6 @@ au1xxx_dbdma_dump(u32 chanid) dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } while (dp != ctp->chan_desc_base); } + +#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ + diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c index f364091d0..0035a9bbe 100644 --- a/arch/mips/au1000/common/dma.c +++ b/arch/mips/au1000/common/dma.c @@ -30,6 +30,7 @@ * */ +#include #include #include #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +73,7 @@ struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = { {.dev_id = -1,}, {.dev_id = -1,} }; +EXPORT_SYMBOL(au1000_dma_table); // Device FIFO addresses and default DMA modes static const struct dma_dev { @@ -216,6 +219,7 @@ int request_au1000_dma(int dev_id, const char *dev_str, return i; } +EXPORT_SYMBOL(request_au1000_dma); void free_au1000_dma(unsigned int dmanr) { @@ -233,4 +237,6 @@ void free_au1000_dma(unsigned int dmanr) chan->irq_dev = NULL; chan->dev_id = -1; } +EXPORT_SYMBOL(free_au1000_dma); + #endif // AU1000 AU1500 AU1100 diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 5104328f7..a19bb7e45 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -41,8 +41,8 @@ #include #include #include +#include -#include #include #include #include @@ -66,10 +66,6 @@ #define EXT_INTC1_REQ1 5 /* IP 5 */ #define MIPS_TIMER_IP 7 /* IP 7 */ -#ifdef CONFIG_KGDB -extern void breakpoint(void); -#endif - extern asmlinkage void au1000_IRQ(void); extern void set_debug_traps(void); extern irq_cpustat_t irq_stat [NR_CPUS]; @@ -84,7 +80,6 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr); inline void local_enable_irq(unsigned int irq_nr); inline void local_disable_irq(unsigned int irq_nr); -extern void __init init_generic_irq(void); void (*board_init_irq)(void); #ifdef CONFIG_PM @@ -420,7 +415,7 @@ static void setup_local_irq(unsigned int irq_nr, int type, int int_req) } -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; unsigned long cp0_status; @@ -434,8 +429,6 @@ void __init init_IRQ(void) memset(irq_desc, 0, sizeof(irq_desc)); set_except_vector(0, au1000_IRQ); - init_generic_irq(); - /* Initialize interrupt controllers to a safe state. */ au_writel(0xffffffff, IC0_CFG0CLR); @@ -482,13 +475,6 @@ void __init init_IRQ(void) */ if (board_init_irq) (*board_init_irq)(); - -#ifdef CONFIG_KGDB - /* If local serial I/O used for debug port, enter kgdb at once */ - puts("Waiting for kgdb to connect..."); - set_debug_traps(); - breakpoint(); -#endif } diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c index d5ccbd221..7e187a00f 100644 --- a/arch/mips/au1000/common/pci.c +++ b/arch/mips/au1000/common/pci.c @@ -6,6 +6,8 @@ * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * Support for all devices (greater than 16) added by David Gathright. * * This program is free software; you can redistribute it and/or modify it @@ -35,7 +37,6 @@ #include #include -#include /* TBD */ static struct resource pci_io_resource = { @@ -67,15 +68,12 @@ static unsigned long virt_io_addr; static int __init au1x_pci_setup(void) { #if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) - int i; - struct pci_dev *dev; - virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START, Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1); if (!virt_io_addr) { printk(KERN_ERR "Unable to ioremap pci space\n"); - return; + return 1; } #ifdef CONFIG_DMA_NONCOHERENT diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c index 7d3a509a1..c2ae4624b 100644 --- a/arch/mips/au1000/common/puts.c +++ b/arch/mips/au1000/common/puts.c @@ -92,7 +92,7 @@ puts(unsigned char *cp) } void -fputs(unsigned char *cp) +fputs(const char *cp) { unsigned char ch; int i = 0; diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c index 5bbc6cf05..65b84db80 100644 --- a/arch/mips/au1000/common/reset.c +++ b/arch/mips/au1000/common/reset.c @@ -43,6 +43,7 @@ extern void (*flush_cache_all)(void); void au1000_restart(char *command) { /* Set all integrated peripherals to disabled states */ + extern void board_reset (void); u32 prid = read_c0_prid(); printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n"); @@ -154,18 +155,10 @@ void au1000_restart(char *command) flush_cache_all(); write_c0_wired(0); -#if defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) - /* Do a HW reset if the board can do it */ - - au_writel(0x00000000, 0xAE00001C); -#endif - -#if defined(CONFIG_MIPS_PB1550) - /* reset entire system */ - au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C); - au_sync(); -#endif + /* Give board a chance to do a hardware reset */ + board_reset(); + /* Jump to the beggining in case board_reset() is empty */ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); } diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index d4c92fa67..dbc8b1bda 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -3,6 +3,8 @@ * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * + * Updates to 2.6, Pete Popov, Embedded Alley Solutions, 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 @@ -40,11 +42,6 @@ #include #include -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - extern char * __init prom_getcmdline(void); extern void __init board_setup(void); extern void au1000_restart(char *); @@ -56,12 +53,9 @@ extern void (*board_time_init)(void); extern void au1x_time_init(void); extern void (*board_timer_setup)(struct irqaction *irq); extern void au1x_timer_setup(struct irqaction *irq); -#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)) -extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); -static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size); -#endif extern void au1xxx_time_init(void); extern void au1xxx_timer_setup(struct irqaction *irq); +extern void set_cpuspec(void); static int __init au1x00_setup(void) { @@ -76,7 +70,7 @@ static int __init au1x00_setup(void) prid = read_c0_prid(); cpupll = (au_readl(0xB1900060) & 0x3F) * 12; - printk("(PRId %08X) @ %dMHZ\n", prid, cpupll); + printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll); bclk = sp->cpu_bclk; if (bclk) @@ -146,9 +140,6 @@ static int __init au1x00_setup(void) _machine_power_off = au1000_power_off; board_time_init = au1xxx_time_init; board_timer_setup = au1xxx_timer_setup; -#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)) - fixup_bigphys_addr = au1500_fixup_bigphys_addr; -#endif /* IO/MEM resources. */ set_io_port_base(0); @@ -157,62 +148,48 @@ static int __init au1x00_setup(void) iomem_resource.start = IOMEM_RESOURCE_START; iomem_resource.end = IOMEM_RESOURCE_END; -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif - -#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) -#ifdef CONFIG_USB_OHCI - if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { - char usb_args[80]; - argptr = prom_getcmdline(); - memset(usb_args, 0, sizeof(usb_args)); - sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", - USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); - strcat(argptr, usb_args); - } -#endif - -#ifdef CONFIG_USB_OHCI - /* enable host controller and wait for reset done */ - au_writel(0x08, USB_HOST_CONFIG); - udelay(1000); - au_writel(0x0E, USB_HOST_CONFIG); - udelay(1000); - au_readl(USB_HOST_CONFIG); /* throw away first read */ - while (!(au_readl(USB_HOST_CONFIG) & 0x10)) - au_readl(USB_HOST_CONFIG); -#endif -#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */ - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); au_writel(0, SYS_TOYTRIM); + return 0; } early_initcall(au1x00_setup); -#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)) -/* This routine should be valid for all Au1500 based boards */ -static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size) +#if defined(CONFIG_64BIT_PHYS_ADDR) +/* This routine should be valid for all Au1x based boards */ +phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) { - u32 pci_start = (u32)Au1500_PCI_MEM_START; - u32 pci_end = (u32)Au1500_PCI_MEM_END; + u32 start, end; /* Don't fixup 36 bit addresses */ if ((phys_addr >> 32) != 0) return phys_addr; +#ifdef CONFIG_PCI + start = (u32)Au1500_PCI_MEM_START; + end = (u32)Au1500_PCI_MEM_END; /* check for pci memory window */ - if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { - return (phys_t)((phys_addr - pci_start) + - Au1500_PCI_MEM_START); + if ((phys_addr >= start) && ((phys_addr + size) < end)) { + return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START); } - else - return phys_addr; +#endif + + /* All Au1x SOCs have a pcmcia controller */ + /* We setup our 32 bit pseudo addresses to be equal to the + * 36 bit addr >> 4, to make it easier to check the address + * and fix it. + * The Au1x socket 0 phys attribute address is 0xF 4000 0000. + * The pseudo address we use is 0xF400 0000. Any address over + * 0xF400 0000 is a pcmcia pseudo address. + */ + if ((phys_addr >= 0xF4000000) && (phys_addr < 0xFFFFFFFF)) { + return (phys_t)(phys_addr << 4); + } + + /* default nop */ + return phys_addr; } #endif diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index f58f454cd..0d4dd7cc5 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -38,11 +38,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include @@ -99,6 +100,9 @@ void mips_timer_interrupt(struct pt_regs *regs) kstat_this_cpu.irqs[irq]++; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); @@ -137,6 +141,9 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) while (time_elapsed > 0) { do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif time_elapsed -= MATCH20_INC; last_match20 += MATCH20_INC; jiffie_drift++; @@ -153,6 +160,9 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) if (jiffie_drift >= 999) { jiffie_drift -= 999; do_timer(regs); /* increment jiffies by one */ +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif } } @@ -342,9 +352,9 @@ static unsigned long do_fast_cp0_gettimeoffset(void) __asm__("multu\t%1,%2\n\t" "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); + : "=r" (res) + : "r" (count), "r" (quotient) + : "hi", "lo", GCC_REG_ACCUM); /* * Due to possible jiffies inconsistencies, we need to check diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c index 21e2a91aa..a73a31655 100644 --- a/arch/mips/au1000/common/usbdev.c +++ b/arch/mips/au1000/common/usbdev.c @@ -61,8 +61,6 @@ #define vdbg(fmt, arg...) do {} while (0) #endif -#define MAX(a,b) (((a)>(b))?(a):(b)) - #define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL) #define EP_FIFO_DEPTH 8 @@ -211,9 +209,8 @@ dump_setup(struct usb_ctrlrequest* s) static inline usbdev_pkt_t * alloc_packet(endpoint_t * ep, int data_size, void* data) { - usbdev_pkt_t* pkt = - (usbdev_pkt_t *)kmalloc(sizeof(usbdev_pkt_t) + data_size, - ALLOC_FLAGS); + usbdev_pkt_t* pkt = kmalloc(sizeof(usbdev_pkt_t) + data_size, + ALLOC_FLAGS); if (!pkt) return NULL; pkt->ep_addr = ep->address; diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c index d7fbda492..5cb1166be 100644 --- a/arch/mips/au1000/csb250/irqmap.c +++ b/arch/mips/au1000/csb250/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c index 541837dba..ac05ba0ff 100644 --- a/arch/mips/au1000/db1x00/board_setup.c +++ b/arch/mips/au1000/db1x00/board_setup.c @@ -48,6 +48,12 @@ /* not correct for db1550 */ static BCSR * const bcsr = (BCSR *)0xAE000000; +void board_reset (void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c index cbae591f0..8f6ef0dbe 100644 --- a/arch/mips/au1000/db1x00/irqmap.c +++ b/arch/mips/au1000/db1x00/irqmap.c @@ -40,8 +40,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c index 585861e80..58d41c293 100644 --- a/arch/mips/au1000/db1x00/mirage_ts.c +++ b/arch/mips/au1000/db1x00/mirage_ts.c @@ -68,7 +68,7 @@ int wm97xx_comodule_present = 1; #define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) #define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) #define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -#define DPRINTK(format, arg...) printk(__FUNCTION__ ": " format "\n" , ## arg) +#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg) #define PEN_DOWN_IRQ AU1000_GPIO_7 diff --git a/arch/mips/au1000/hydrogen3/board_setup.c b/arch/mips/au1000/hydrogen3/board_setup.c index 84e1e4119..904417af8 100644 --- a/arch/mips/au1000/hydrogen3/board_setup.c +++ b/arch/mips/au1000/hydrogen3/board_setup.c @@ -47,6 +47,10 @@ extern struct rtc_ops no_rtc_ops; +void board_reset (void) +{ +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c index a335c90bd..6eacaa0da 100644 --- a/arch/mips/au1000/hydrogen3/irqmap.c +++ b/arch/mips/au1000/hydrogen3/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c index 720bc759d..51fcc2cbe 100644 --- a/arch/mips/au1000/mtx-1/irqmap.c +++ b/arch/mips/au1000/mtx-1/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c index ab53e1a6c..042378699 100644 --- a/arch/mips/au1000/pb1000/board_setup.c +++ b/arch/mips/au1000/pb1000/board_setup.c @@ -48,6 +48,10 @@ !!! I shall not define symbols starting with CONFIG_ !!! #endif +void board_reset (void) +{ +} + void __init board_setup(void) { u32 pin_func, static_cfg0; diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c index 215b07a6d..4950c33a4 100644 --- a/arch/mips/au1000/pb1000/irqmap.c +++ b/arch/mips/au1000/pb1000/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c index abe5f47bc..e57c364bd 100644 --- a/arch/mips/au1000/pb1100/board_setup.c +++ b/arch/mips/au1000/pb1100/board_setup.c @@ -37,8 +37,8 @@ #include #include #include -#include -#include +#include +#include #ifdef CONFIG_USB_OHCI // Enable the workaround for the OHCI DoneHead @@ -48,6 +48,12 @@ !!! I shall not define symbols starting with CONFIG_ !!! #endif +void board_reset (void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c index 6333deb60..43be7158b 100644 --- a/arch/mips/au1000/pb1100/irqmap.c +++ b/arch/mips/au1000/pb1100/irqmap.c @@ -39,13 +39,13 @@ #include #include #include +#include -#include #include #include #include #include -#include +#include au1xxx_irq_map_t au1xxx_irq_map[] = { { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted# diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c index 5b7ee00dc..9dd0106dc 100644 --- a/arch/mips/au1000/pb1500/board_setup.c +++ b/arch/mips/au1000/pb1500/board_setup.c @@ -48,6 +48,12 @@ !!! I shall not define symbols starting with CONFIG_ !!! #endif +void board_reset (void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c index 79c4e0fd6..476e25001 100644 --- a/arch/mips/au1000/pb1500/irqmap.c +++ b/arch/mips/au1000/pb1500/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c index 6cd5cc801..654fd311a 100644 --- a/arch/mips/au1000/pb1550/board_setup.c +++ b/arch/mips/au1000/pb1550/board_setup.c @@ -45,6 +45,12 @@ #include #include +void board_reset (void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C); +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c index 4f692163b..889d4949e 100644 --- a/arch/mips/au1000/pb1550/irqmap.c +++ b/arch/mips/au1000/pb1550/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c index 3dcaef1bd..9dadc8253 100644 --- a/arch/mips/au1000/xxs1500/board_setup.c +++ b/arch/mips/au1000/xxs1500/board_setup.c @@ -40,6 +40,12 @@ #include #include +void board_reset (void) +{ + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ + au_writel(0x00000000, 0xAE00001C); +} + void __init board_setup(void) { u32 pin_func; diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c index d751f48a6..954800a0a 100644 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ b/arch/mips/au1000/xxs1500/irqmap.c @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index c010290e5..efbeac326 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -4,6 +4,7 @@ # for more details. # # Copyright (C) 1995, 1998, 2001, 2002 by Ralf Baechle +# Copyright (C) 2004 Maciej W. Rozycki # # @@ -19,29 +20,30 @@ endif # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # -drop-sections = .reginfo .mdebug .comment .note .pdr +drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options strip-flags = $(addprefix --remove-section=,$(drop-sections)) +VMLINUX = vmlinux + all: vmlinux.ecoff vmlinux.srec addinitrd -vmlinux.ecoff: $(obj)/elf2ecoff vmlinux - $(obj)/elf2ecoff vmlinux vmlinux.ecoff $(E2EFLAGS) +vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX) + $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS) $(obj)/elf2ecoff: $(obj)/elf2ecoff.c $(HOSTCC) -o $@ $^ -vmlinux.srec: vmlinux - $(OBJCOPY) -S -O srec $(strip-flags) vmlinux $(obj)/vmlinux.srec +vmlinux.srec: $(VMLINUX) + $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec $(obj)/addinitrd: $(obj)/addinitrd.c $(HOSTCC) -o $@ $^ archhelp: @echo '* vmlinux.ecoff - ECOFF boot image' + @echo '* vmlinux.srec - SREC boot image' clean-files += addinitrd \ elf2ecoff \ vmlinux.ecoff \ - vmlinux.srec \ - zImage.tmp \ - zImage + vmlinux.srec diff --git a/arch/mips/boot/addinitrd.c b/arch/mips/boot/addinitrd.c index 38261f1ae..8b3033304 100644 --- a/arch/mips/boot/addinitrd.c +++ b/arch/mips/boot/addinitrd.c @@ -2,6 +2,8 @@ * addinitrd - program to add a initrd image to an ecoff kernel * * (C) 1999 Thomas Bogendoerfer + * minor modifications, cleanup: Guido Guenther + * further cleanup: Maciej W. Rozycki */ #include @@ -54,7 +56,7 @@ int main (int argc, char *argv[]) exit (1); } - if ((fd_vmlinux = open (argv[1],O_RDWR)) < 0) + if ((fd_vmlinux = open (argv[1],O_RDONLY)) < 0) die ("open vmlinux"); if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile) die ("read file header"); @@ -78,6 +80,11 @@ int main (int argc, char *argv[]) swab = 1; } + /* make sure we have an empty data segment for the initrd */ + if (eaout.dsize || esecs[1].s_size) { + fprintf (stderr, "Data segment not empty. Giving up!\n"); + exit (1); + } if ((fd_initrd = open (argv[2], O_RDONLY)) < 0) die ("open initrd"); if (fstat (fd_initrd, &st) < 0) diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c index ba46e8f1e..6d2a81581 100644 --- a/arch/mips/cobalt/irq.c +++ b/arch/mips/cobalt/irq.c @@ -87,7 +87,7 @@ asmlinkage void cobalt_irq(struct pt_regs *regs) } } -void __init init_IRQ(void) +void __init arch_init_irq(void) { set_except_vector(0, cobalt_handle_int); diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index 1c4610673..6b4737e42 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997 by Ralf Baechle + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) * */ @@ -15,7 +15,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig index 9e0a5bc52..fe58b6023 100644 --- a/arch/mips/configs/atlas_defconfig +++ b/arch/mips/configs/atlas_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:55 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -62,6 +66,7 @@ CONFIG_MIPS_ATLAS=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -69,7 +74,6 @@ CONFIG_MIPS_ATLAS=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -118,7 +122,6 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -135,7 +138,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -144,6 +146,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -175,7 +178,19 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -221,7 +236,8 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -230,12 +246,14 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -295,10 +313,13 @@ CONFIG_IP_PNP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -316,7 +337,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -439,6 +459,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -473,7 +494,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -493,7 +513,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -503,6 +522,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -525,7 +549,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -537,6 +560,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -556,6 +581,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -568,7 +594,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -615,6 +642,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -635,13 +663,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -652,6 +682,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig index b59e45387..24821b6d5 100644 --- a/arch/mips/configs/capcella_defconfig +++ b/arch/mips/configs/capcella_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:55 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y # CONFIG_CASIO_E55 is not set # CONFIG_IBM_WORKPAD is not set @@ -75,6 +80,7 @@ CONFIG_VRC4173=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -82,7 +88,6 @@ CONFIG_VRC4173=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -122,7 +127,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -147,6 +151,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -175,7 +180,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -193,7 +210,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -257,10 +273,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -278,7 +297,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -400,6 +418,7 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -434,7 +453,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -466,7 +484,6 @@ CONFIG_WATCHDOG=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -476,6 +493,11 @@ CONFIG_WATCHDOG=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -498,7 +520,6 @@ CONFIG_WATCHDOG=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -510,6 +531,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -529,6 +552,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -541,7 +565,8 @@ CONFIG_AUTOFS4_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -589,6 +614,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -609,13 +635,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -626,6 +654,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index d47f67bb5..05ad5c80f 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:55 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set CONFIG_MIPS_COBALT=y @@ -62,6 +66,7 @@ CONFIG_MIPS_COBALT=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -69,7 +74,6 @@ CONFIG_MIPS_COBALT=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -113,7 +117,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -138,6 +141,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -167,7 +171,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -185,7 +201,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -245,10 +260,13 @@ CONFIG_INET=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -266,7 +284,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -388,6 +405,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -422,7 +440,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -442,7 +459,6 @@ CONFIG_COBALT_LCD=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -452,6 +468,11 @@ CONFIG_COBALT_LCD=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -474,7 +495,6 @@ CONFIG_COBALT_LCD=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -486,6 +506,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -509,6 +531,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -521,7 +544,8 @@ CONFIG_FS_POSIX_ACL=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -566,6 +590,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -586,13 +611,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -603,6 +630,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 62e748bfd..25ff1aa5d 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:56 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set CONFIG_SOC_AU1X00=y CONFIG_SOC_AU1000=y # CONFIG_SOC_AU1100 is not set @@ -133,7 +138,6 @@ CONFIG_64BIT_PHYS_ADDR=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,10 +147,16 @@ CONFIG_HW_HAS_PCI=y CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m + +# +# PC-card bridges +# # CONFIG_TCIC is not set # CONFIG_PCMCIA_AU1X00 is not set @@ -168,6 +178,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -193,7 +204,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -217,7 +240,6 @@ CONFIG_BLK_DEV_LOOP=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -251,6 +273,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -264,13 +289,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -288,7 +314,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -316,7 +341,7 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=m CONFIG_MIPS_AU1X00_ENET=y # @@ -341,13 +366,13 @@ CONFIG_MIPS_AU1X00_ENET=y # CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m # # Wan interfaces @@ -401,6 +426,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -436,7 +462,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -450,19 +475,17 @@ CONFIG_LEGACY_PTY_COUNT=256 CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -470,6 +493,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -492,7 +520,6 @@ CONFIG_RTC=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -503,6 +530,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -535,6 +564,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -547,7 +577,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -560,6 +591,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -595,6 +627,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -655,13 +688,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -675,14 +710,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -691,8 +730,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index d6b544edb..450a51579 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:56 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set CONFIG_SOC_AU1X00=y # CONFIG_SOC_AU1000 is not set CONFIG_SOC_AU1100=y @@ -133,7 +138,6 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -141,10 +145,16 @@ CONFIG_CPU_HAS_SYNC=y CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m + +# +# PC-card bridges +# # CONFIG_TCIC is not set # CONFIG_PCMCIA_AU1X00 is not set @@ -166,6 +176,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -191,7 +202,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -215,7 +238,6 @@ CONFIG_BLK_DEV_LOOP=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -249,6 +271,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -262,13 +287,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -286,7 +312,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -314,7 +339,7 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=m # CONFIG_MIPS_AU1X00_ENET is not set # @@ -339,13 +364,13 @@ CONFIG_NET_ETHERNET=y # CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m # # Wan interfaces @@ -399,6 +424,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -431,7 +457,6 @@ CONFIG_HW_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -445,19 +470,17 @@ CONFIG_LEGACY_PTY_COUNT=256 CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -465,6 +488,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -487,7 +515,6 @@ CONFIG_RTC=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -498,6 +525,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -530,6 +559,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -542,7 +572,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -555,6 +586,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -590,6 +622,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -650,13 +683,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -670,14 +705,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -686,8 +725,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 97a22cb43..54112075e 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:56 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set CONFIG_SOC_AU1X00=y # CONFIG_SOC_AU1000 is not set # CONFIG_SOC_AU1100 is not set @@ -97,7 +102,8 @@ CONFIG_MIPS_DB1500=y # CONFIG_TOSHIBA_RBTX4927 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_HAVE_DEC_LOCK=y -CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_COHERENT=y +CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -133,26 +139,38 @@ CONFIG_64BIT_PHYS_ADDR=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) # CONFIG_HW_HAS_PCI=y -# CONFIG_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +# CONFIG_YENTA is not set +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set # CONFIG_TCIC is not set -# CONFIG_PCMCIA_AU1X00 is not set +CONFIG_PCMCIA_AU1X00=m # # PCI Hotplug Support # +# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -168,6 +186,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -197,13 +216,24 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access @@ -217,7 +247,9 @@ CONFIG_MTD_DB1X00_USER=y # # Self-contained MTD device drivers # +# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -246,11 +278,29 @@ CONFIG_MTD_DB1X00_USER=y # Block devices # # CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -269,12 +319,12 @@ CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y +# CONFIG_IDE_GENERIC is not set +# CONFIG_BLK_DEV_IDEPCI is not set # CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set @@ -302,6 +352,7 @@ CONFIG_IDE_GENERIC=y # # I2O device support # +# CONFIG_I2O is not set # # Networking support @@ -331,6 +382,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -344,13 +398,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -368,7 +423,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -392,24 +446,51 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # CONFIG_ETHERTAP is not set +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y # CONFIG_MII is not set CONFIG_MIPS_AU1X00_ENET=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) # +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set # # Ethernet (10000 Mbit) # +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -419,20 +500,14 @@ CONFIG_MIPS_AU1X00_ENET=y # # PCMCIA network device support # -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +# CONFIG_NET_PCMCIA is not set # # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set CONFIG_PPP=m CONFIG_PPP_MULTILINK=y # CONFIG_PPP_FILTER is not set @@ -481,6 +556,8 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -514,7 +591,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -533,14 +609,13 @@ CONFIG_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -548,6 +623,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -569,11 +649,139 @@ CONFIG_RTC=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# 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_SONICVIBES is not set +CONFIG_SOUND_AU1000=y +# 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_SOUND_OSS is not set +# CONFIG_SOUND_ALI5455 is not set +# CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_AD1980 is not set # # USB support # +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_MIDI is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_STORAGE is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set + +# +# USB ATM/DSL drivers +# # # USB Gadget Support @@ -606,6 +814,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -618,7 +827,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -631,6 +841,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -668,6 +879,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -728,13 +940,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -748,14 +962,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -764,8 +982,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig index 07803efb6..231976bc8 100644 --- a/arch/mips/configs/ddb5476_defconfig +++ b/arch/mips/configs/ddb5476_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:57 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -62,6 +66,7 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -69,7 +74,6 @@ CONFIG_DDB5476=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -114,7 +118,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -140,6 +143,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -170,7 +174,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -188,7 +204,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -257,10 +272,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -278,7 +296,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -407,6 +424,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -441,7 +459,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -461,7 +478,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -471,6 +487,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -488,6 +509,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Graphics support # +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -499,6 +522,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set @@ -530,6 +554,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -549,6 +575,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -561,7 +588,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -607,6 +635,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -627,13 +656,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="ip=any" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -644,6 +675,8 @@ CONFIG_CMDLINE="ip=any" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig index c09e58c63..1b0c45ace 100644 --- a/arch/mips/configs/ddb5477_defconfig +++ b/arch/mips/configs/ddb5477_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:58 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -62,6 +66,7 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -70,7 +75,6 @@ CONFIG_DDB5477=y CONFIG_DDB5477_BUS_FREQUENCY=0 # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -114,7 +118,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -139,6 +142,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -167,7 +171,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -225,10 +241,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -246,7 +265,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -308,7 +326,6 @@ CONFIG_PCNET32=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # CONFIG_LAN_SAA9730 is not set # @@ -322,6 +339,7 @@ CONFIG_PCNET32=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # @@ -388,6 +406,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -422,7 +441,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -442,7 +460,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -452,6 +469,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -474,7 +496,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -486,6 +507,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -505,6 +528,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -517,7 +541,8 @@ CONFIG_AUTOFS4_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -565,6 +590,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -585,13 +611,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="ip=any" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -602,6 +630,8 @@ CONFIG_CMDLINE="ip=any" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index e7dc8efb0..cb0e8621d 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:58 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_MACH_DECSTATION=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_MACH_DECSTATION=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -116,7 +121,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_WB=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -138,6 +142,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -161,7 +166,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -201,9 +218,8 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_DECNCR=y # CONFIG_SCSI_DECSII is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -218,7 +234,6 @@ CONFIG_SCSI_DECNCR=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -251,10 +266,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -272,7 +290,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -365,6 +382,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -398,7 +416,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -413,12 +430,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -428,6 +443,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -450,7 +470,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -461,6 +480,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -484,6 +505,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -496,7 +518,8 @@ CONFIG_FS_POSIX_ACL=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -569,13 +592,15 @@ CONFIG_ULTRIX_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -586,6 +611,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig index b771f906f..86d99fa96 100644 --- a/arch/mips/configs/e55_defconfig +++ b/arch/mips/configs/e55_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:58 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y CONFIG_CASIO_E55=y # CONFIG_IBM_WORKPAD is not set @@ -74,6 +79,7 @@ CONFIG_CASIO_E55=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -81,7 +87,6 @@ CONFIG_CASIO_E55=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -121,7 +126,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -168,7 +173,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -186,7 +203,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -220,7 +236,6 @@ CONFIG_IDE_GENERIC=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -251,10 +266,13 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -272,7 +290,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -380,6 +397,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -414,7 +432,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -442,12 +459,10 @@ CONFIG_WATCHDOG=y # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -457,6 +472,11 @@ CONFIG_WATCHDOG=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -490,6 +510,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -509,6 +531,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -521,7 +544,8 @@ CONFIG_AUTOFS4_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -568,6 +592,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -588,13 +613,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -605,6 +632,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig index 541629004..b23653bcc 100644 --- a/arch/mips/configs/ev64120_defconfig +++ b/arch/mips/configs/ev64120_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:59 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_KMOD is not set # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -68,6 +73,7 @@ CONFIG_MIPS_EV64120=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -75,7 +81,6 @@ CONFIG_MIPS_EV64120=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -121,7 +126,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -138,7 +142,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -147,6 +150,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -175,7 +179,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -232,10 +248,13 @@ CONFIG_IP_PNP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -253,7 +272,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -382,6 +400,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -416,7 +435,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -436,7 +454,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -446,6 +463,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -468,7 +490,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -480,6 +501,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -499,6 +522,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -511,7 +535,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -557,6 +582,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -577,13 +603,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -594,6 +622,8 @@ CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/d # # Library routines # -CONFIG_CRC16=y +CONFIG_CRC_CCITT=y # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig index eb13fd96d..b3ff846b4 100644 --- a/arch/mips/configs/ev96100_defconfig +++ b/arch/mips/configs/ev96100_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:59 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_KMOD is not set # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_MIPS_EV96100=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_MIPS_EV96100=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -123,7 +128,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -138,7 +142,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -147,6 +150,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -170,7 +174,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -194,7 +210,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -226,10 +241,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -247,7 +265,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -340,6 +357,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -374,7 +392,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -389,12 +406,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -404,6 +419,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -426,7 +446,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -437,6 +456,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -456,6 +477,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -468,7 +490,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -514,6 +537,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -534,13 +558,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -551,6 +577,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 8bc7792d6..5e667febe 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:59 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,6 +27,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y @@ -32,11 +35,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,13 +51,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -68,6 +73,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -75,7 +81,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set CONFIG_SGI_IP22=y -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -126,7 +131,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -140,7 +144,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_TRAD_SIGNALS=y -CONFIG_BINFMT_IRIX=y # # Device Drivers @@ -149,6 +152,7 @@ CONFIG_BINFMT_IRIX=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -172,7 +176,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -212,9 +228,8 @@ CONFIG_SCSI_SPI_ATTRS=m # SCSI low-level drivers # CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -229,7 +244,6 @@ CONFIG_SGIWD93_SCSI=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -263,6 +277,9 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +CONFIG_IP_TCPDIAG_IPV6=y # # IP: Virtual Server Configuration @@ -302,6 +319,7 @@ CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -310,6 +328,9 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CT_PROTO_SCTP is not set CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m @@ -334,8 +355,17 @@ CONFIG_IP_NF_MATCH_HELPER=m CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -354,18 +384,15 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_CONNMARK=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # # IPv6: Netfilter Configuration @@ -414,16 +441,17 @@ CONFIG_SCTP_HMAC_MD5=y CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -431,7 +459,7 @@ CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_DELAY=m +CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y @@ -515,7 +543,7 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV=m CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 @@ -533,6 +561,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -543,7 +572,10 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -569,7 +601,6 @@ CONFIG_SERIAL_CORE=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -588,16 +619,14 @@ CONFIG_WATCHDOG=y # CONFIG_SOFT_WATCHDOG is not set CONFIG_INDYDOG=m # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set CONFIG_SGI_DS1286=m +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=m @@ -608,6 +637,11 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -630,7 +664,6 @@ CONFIG_MAX_RAW_DEVS=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_SGI_NEWPORT_CONSOLE=y CONFIG_DUMMY_CONSOLE=y CONFIG_FONT_8x16=y @@ -652,6 +685,8 @@ CONFIG_LOGO_SGI_CLUT224=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -684,6 +719,7 @@ CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set CONFIG_QFMT_V2=m CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -695,6 +731,7 @@ CONFIG_JOLIET=y CONFIG_ZISOFS=y CONFIG_ZISOFS_FS=m CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -754,10 +791,17 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -827,13 +871,15 @@ CONFIG_NLS_UTF8=m # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -841,30 +887,36 @@ CONFIG_CMDLINE="" # CONFIG_CRYPTO=y CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_TEST=m # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 2962c1db7..6668854ea 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:00 2004 # CONFIG_MIPS=y CONFIG_MIPS64=y @@ -10,11 +12,12 @@ CONFIG_64BIT=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -23,6 +26,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y @@ -30,11 +34,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +50,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -65,6 +72,7 @@ CONFIG_STOP_MACHINE=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -75,7 +83,7 @@ CONFIG_STOP_MACHINE=y CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set CONFIG_DISCONTIGMEM=y -# CONFIG_NUMA is not set +CONFIG_NUMA=y # CONFIG_MAPPED_KERNEL is not set # CONFIG_REPLICATE_KTEXT is not set # CONFIG_REPLICATE_EXHANDLERS is not set @@ -124,7 +132,6 @@ CONFIG_CPU_HAS_SYNC=y CONFIG_SMP=y CONFIG_NR_CPUS=64 # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_MIPS_INSANE_LARGE is not set # @@ -132,6 +139,7 @@ CONFIG_NR_CPUS=64 # CONFIG_HW_HAS_PCI=y CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y CONFIG_MMU=y @@ -141,6 +149,7 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y @@ -154,6 +163,7 @@ CONFIG_BINFMT_ELF32=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -178,10 +188,23 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -226,7 +249,8 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -235,12 +259,14 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set CONFIG_SCSI_QLOGIC_ISP=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -255,7 +281,21 @@ CONFIG_SCSI_QLA2XXX=y # # Multi-device support (RAID and LVM) # -# CONFIG_MD is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=m +CONFIG_MD_RAID5=y +CONFIG_MD_RAID6=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # # Fusion MPT device support @@ -300,10 +340,13 @@ CONFIG_IP_PNP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -321,37 +364,38 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=y -CONFIG_NET_SCH_HTB=y -CONFIG_NET_SCH_HFSC=y -CONFIG_NET_SCH_CSZ=y -CONFIG_NET_SCH_PRIO=y -CONFIG_NET_SCH_RED=y -CONFIG_NET_SCH_SFQ=y -CONFIG_NET_SCH_TEQL=y -CONFIG_NET_SCH_TBF=y -CONFIG_NET_SCH_GRED=y -CONFIG_NET_SCH_DSMARK=y -CONFIG_NET_SCH_DELAY=y -# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=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_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=y -CONFIG_NET_CLS_ROUTE4=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=y -CONFIG_NET_CLS_U32=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m # CONFIG_CLS_U32_PERF is not set # CONFIG_NET_CLS_IND is not set -CONFIG_NET_CLS_RSVP=y -CONFIG_NET_CLS_RSVP6=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m # CONFIG_NET_CLS_ACT is not set CONFIG_NET_CLS_POLICE=y @@ -465,6 +509,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -497,7 +542,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -509,8 +553,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set CONFIG_SGI_IP27_RTC=y +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -527,6 +571,11 @@ CONFIG_SGI_IP27_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -554,6 +603,8 @@ CONFIG_SGI_IP27_RTC=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -577,11 +628,17 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m # CONFIG_AUTOFS4_FS is not set # @@ -593,7 +650,8 @@ CONFIG_AUTOFS_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -634,13 +692,14 @@ CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y +# CONFIG_ROOT_NFS is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -675,13 +734,15 @@ CONFIG_SGI_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -695,24 +756,30 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=y CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_TEST=m # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 7cfe80b94..785a0a217 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:00 2004 # CONFIG_MIPS=y CONFIG_MIPS64=y @@ -10,12 +12,12 @@ CONFIG_64BIT=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -60,6 +65,7 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -114,7 +120,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -130,6 +135,7 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y +# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y @@ -143,6 +149,7 @@ CONFIG_BINFMT_ELF32=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -172,6 +179,18 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -217,13 +236,13 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_AIC7XXX=y CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set CONFIG_AIC7XXX_DEBUG_ENABLE=y CONFIG_AIC7XXX_DEBUG_MASK=0 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -232,12 +251,14 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -296,10 +317,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -317,7 +341,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -442,6 +465,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set # CONFIG_SERIO_MACEPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -476,7 +500,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -496,7 +519,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -506,6 +528,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -528,7 +555,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -540,6 +566,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -559,6 +587,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -571,7 +600,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -584,6 +614,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -618,6 +649,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -648,13 +680,15 @@ CONFIG_SGI_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -665,6 +699,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig index 520acac13..fab0041d9 100644 --- a/arch/mips/configs/it8172_defconfig +++ b/arch/mips/configs/it8172_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:00 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -26,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,13 +51,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -69,6 +74,7 @@ CONFIG_MIPS_ITE8172=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -76,7 +82,6 @@ CONFIG_MIPS_ITE8172=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -120,7 +125,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -170,13 +175,23 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y # CONFIG_MTD_CFI_AMDSTD is not set # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access @@ -185,12 +200,13 @@ CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_START=0x8000000 CONFIG_MTD_PHYSMAP_LEN=0x2000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=4 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -223,7 +239,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -241,7 +269,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -269,7 +296,6 @@ CONFIG_IDE_GENERIC=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -302,10 +328,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -323,7 +352,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -415,6 +443,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -453,7 +482,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -468,12 +496,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -483,6 +509,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -505,7 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -525,8 +555,6 @@ CONFIG_SOUND_PRIME=y # CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_SONICVIBES is not set CONFIG_SOUND_IT8172=y # CONFIG_SOUND_TRIDENT is not set @@ -538,6 +566,8 @@ CONFIG_SOUND_IT8172=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -557,6 +587,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -569,7 +600,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -617,6 +649,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -637,13 +670,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -654,6 +689,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig index 8eace13a3..76a9522b0 100644 --- a/arch/mips/configs/ivr_defconfig +++ b/arch/mips/configs/ivr_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:01 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -26,17 +28,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,13 +51,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -68,6 +73,7 @@ CONFIG_MIPS_IVR=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -75,7 +81,6 @@ CONFIG_MIPS_IVR=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -118,7 +123,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -171,7 +176,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -189,7 +206,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -252,10 +268,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -273,7 +292,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -395,6 +413,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -431,7 +450,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -450,7 +468,6 @@ CONFIG_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -460,6 +477,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -482,7 +504,6 @@ CONFIG_RTC=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -494,6 +515,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -513,6 +536,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -525,7 +549,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -571,6 +596,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -591,13 +617,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -608,6 +636,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig index b6f70da71..d1b4af87c 100644 --- a/arch/mips/configs/jaguar-atx_defconfig +++ b/arch/mips/configs/jaguar-atx_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:01 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # # CONFIG_EXPERIMENTAL is not set CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -24,6 +26,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y @@ -31,11 +34,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -43,6 +48,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # @@ -60,6 +66,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set CONFIG_MOMENCO_JAGUAR_ATX=y CONFIG_JAGUAR_DMALOW=y # CONFIG_PMC_YOSEMITE is not set @@ -119,7 +126,6 @@ CONFIG_CPU_HAS_SYNC=y CONFIG_HIGHMEM=y # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -136,7 +142,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -145,6 +150,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -172,7 +178,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -228,7 +246,12 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -293,7 +316,6 @@ CONFIG_EEPRO100=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -305,11 +327,12 @@ CONFIG_EEPRO100=y # CONFIG_HAMACHI is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set -CONFIG_MV64340_ETH=y -CONFIG_MV64340_ETH_0=y -CONFIG_MV64340_ETH_1=y -CONFIG_MV64340_ETH_2=y +CONFIG_MV643XX_ETH=y +CONFIG_MV643XX_ETH_0=y +CONFIG_MV643XX_ETH_1=y +CONFIG_MV643XX_ETH_2=y # # Ethernet (10000 Mbit) @@ -388,7 +411,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -408,7 +430,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -418,6 +439,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -445,6 +471,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -463,6 +491,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -475,7 +504,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -529,13 +559,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -546,6 +578,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index 4580138f2..5a98bb504 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:01 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set CONFIG_TOSHIBA_JMR3927=y # CONFIG_MIPS_COBALT is not set @@ -62,6 +66,7 @@ CONFIG_TOSHIBA_JMR3927=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -69,7 +74,6 @@ CONFIG_TOSHIBA_JMR3927=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -111,7 +115,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set CONFIG_RTC_DS1742=y # @@ -129,7 +132,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -138,6 +140,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -166,7 +169,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -224,10 +239,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -245,7 +263,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -367,6 +384,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -415,7 +433,6 @@ CONFIG_TXX927_SERIAL_CONSOLE=y # CONFIG_UNIX98_PTYS is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -435,7 +452,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -445,6 +461,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -462,6 +483,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Graphics support # +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -473,6 +496,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set @@ -486,7 +510,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -504,6 +527,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -522,6 +547,7 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -534,7 +560,8 @@ CONFIG_DUMMY_CONSOLE=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -578,6 +605,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -598,13 +626,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -615,6 +645,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig index 3f9fb458b..3f1b36a2f 100644 --- a/arch/mips/configs/lasat200_defconfig +++ b/arch/mips/configs/lasat200_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:02 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -71,6 +76,7 @@ CONFIG_LASAT_SYSCTL=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -78,7 +84,6 @@ CONFIG_LASAT_SYSCTL=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -124,7 +129,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -149,6 +153,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -177,13 +182,24 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_GEN_PROBE=y # CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access @@ -197,6 +213,7 @@ CONFIG_MTD_LASAT=y # # CONFIG_MTD_PMC551 is not set # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set @@ -233,7 +250,19 @@ CONFIG_MTD_LASAT=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -251,7 +280,6 @@ CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -266,7 +294,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -340,10 +367,13 @@ CONFIG_INET=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -361,7 +391,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -482,6 +511,7 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -516,7 +546,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -536,7 +565,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -546,6 +574,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -568,7 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -580,6 +612,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -604,6 +638,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -616,7 +651,8 @@ CONFIG_FS_MBCACHE=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -664,6 +700,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -684,13 +721,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -701,6 +740,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 3259148a2..222a1b5e7 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:02 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_MIPS_MALTA=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_MIPS_MALTA=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -126,7 +131,6 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -151,6 +155,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -181,7 +186,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -238,10 +255,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -259,7 +279,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -321,7 +340,6 @@ CONFIG_PCNET32=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # CONFIG_LAN_SAA9730 is not set # @@ -335,6 +353,7 @@ CONFIG_PCNET32=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # @@ -401,6 +420,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -435,7 +455,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -454,7 +473,6 @@ CONFIG_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -464,6 +482,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -486,7 +509,6 @@ CONFIG_RTC=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -498,6 +520,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -517,6 +541,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set @@ -529,7 +554,8 @@ CONFIG_AUTOFS_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -579,6 +605,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -599,13 +626,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -616,6 +645,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig index 2c3c1f0a1..f28428979 100644 --- a/arch/mips/configs/mpc30x_defconfig +++ b/arch/mips/configs/mpc30x_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:02 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y # CONFIG_CASIO_E55 is not set # CONFIG_IBM_WORKPAD is not set @@ -75,6 +80,7 @@ CONFIG_VRC4173=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -82,7 +88,6 @@ CONFIG_VRC4173=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -122,7 +127,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -147,6 +151,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -175,7 +180,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -234,10 +251,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -255,7 +275,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -377,6 +396,7 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -411,7 +431,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -431,7 +450,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -441,6 +459,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -463,7 +486,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -475,6 +497,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -494,6 +518,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -506,7 +531,8 @@ CONFIG_AUTOFS4_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -552,6 +578,7 @@ CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -572,13 +599,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -592,14 +621,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -608,8 +641,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig index 3eafe9ae7..33d03f454 100644 --- a/arch/mips/configs/ocelot_c_defconfig +++ b/arch/mips/configs/ocelot_c_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:03 2004 # CONFIG_MIPS=y CONFIG_MIPS64=y @@ -10,12 +12,12 @@ CONFIG_64BIT=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +26,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -59,6 +64,7 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set CONFIG_MOMENCO_OCELOT_C=y +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -112,7 +118,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -128,6 +133,7 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y @@ -141,6 +147,7 @@ CONFIG_BINFMT_ELF32=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -169,6 +176,18 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -225,10 +244,13 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -246,7 +268,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -303,7 +324,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set -# CONFIG_MV64340_ETH is not set +# CONFIG_MV643XX_ETH is not set # # Ethernet (10000 Mbit) @@ -369,6 +390,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -403,7 +425,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -423,7 +444,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -433,6 +453,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -455,7 +480,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -467,6 +491,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -486,6 +512,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -498,7 +525,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -546,6 +574,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -566,13 +595,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -583,6 +614,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig index 2f5c2d2f7..62c95e3f3 100644 --- a/arch/mips/configs/ocelot_defconfig +++ b/arch/mips/configs/ocelot_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:04 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,7 +51,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -62,6 +66,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_MOMENCO_OCELOT=y # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -69,7 +74,6 @@ CONFIG_MOMENCO_OCELOT=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -121,7 +125,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -136,7 +139,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -145,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -168,7 +171,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -192,7 +207,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -224,10 +238,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -245,7 +262,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -337,6 +353,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -371,7 +388,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -386,12 +402,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -401,6 +415,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -423,7 +442,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -434,6 +452,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -453,6 +473,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -465,7 +486,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -513,6 +535,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -533,13 +556,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -550,6 +575,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig index a6e93370f..231afaaf2 100644 --- a/arch/mips/configs/ocelot_g_defconfig +++ b/arch/mips/configs/ocelot_g_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:04 2004 # CONFIG_MIPS=y CONFIG_MIPS64=y @@ -10,12 +12,12 @@ CONFIG_64BIT=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +26,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -59,6 +64,7 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_MOMENCO_OCELOT is not set CONFIG_MOMENCO_OCELOT_G=y # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -115,7 +121,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -131,6 +136,7 @@ CONFIG_MMU=y # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_BUILD_ELF64 is not set CONFIG_MIPS32_COMPAT=y CONFIG_COMPAT=y CONFIG_MIPS32_O32=y @@ -144,6 +150,7 @@ CONFIG_BINFMT_ELF32=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -172,6 +179,18 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -228,10 +247,13 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) @@ -249,7 +271,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -372,6 +393,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -406,7 +428,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -426,7 +447,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -436,6 +456,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -458,7 +483,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -470,6 +494,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -489,6 +515,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -501,7 +528,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -549,6 +577,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -569,13 +598,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -586,6 +617,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/osprey_defconfig b/arch/mips/configs/osprey_defconfig index 11564910e..716470eb2 100644 --- a/arch/mips/configs/osprey_defconfig +++ b/arch/mips/configs/osprey_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:04 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set CONFIG_NEC_OSPREY=y # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -115,7 +120,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -136,6 +140,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -159,7 +164,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -183,7 +200,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -216,10 +232,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -237,7 +256,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -329,6 +347,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -363,7 +382,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -378,12 +396,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -393,6 +409,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -415,7 +436,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -426,6 +446,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -445,6 +467,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -457,7 +480,8 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -505,6 +529,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -525,13 +550,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -542,6 +569,8 @@ CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 5bc312a3c..ae56298c6 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:05 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,14 +80,32 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set +CONFIG_SOC_AU1X00=y +# CONFIG_SOC_AU1000 is not set +CONFIG_SOC_AU1100=y +# CONFIG_SOC_AU1500 is not set +# CONFIG_SOC_AU1550 is not set +# CONFIG_MIPS_PB1000 is not set +CONFIG_MIPS_PB1100=y +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set # CONFIG_TOSHIBA_RBTX4927 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SWAP_IO_SPACE=y +# CONFIG_AU1000_USB_DEVICE is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -116,19 +140,27 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) # +CONFIG_HW_HAS_PCI=y +# CONFIG_PCI is not set CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m + +# +# PC-card bridges +# # CONFIG_TCIC is not set +# CONFIG_PCMCIA_AU1X00 is not set # # PCI Hotplug Support @@ -148,13 +180,83 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PB1100=y +CONFIG_MTD_PB1500_BOOT=y +CONFIG_MTD_PB1500_USER=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set # # Parallel port support @@ -173,7 +275,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -197,7 +311,6 @@ CONFIG_BLK_DEV_LOOP=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -231,6 +344,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -244,13 +360,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -268,7 +385,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -297,6 +413,7 @@ CONFIG_NETDEVICES=y # CONFIG_NET_ETHERNET=y # CONFIG_MII is not set +# CONFIG_MIPS_AU1X00_ENET is not set # # Ethernet (1000 Mbit) @@ -318,15 +435,7 @@ CONFIG_NET_ETHERNET=y # # PCMCIA network device support # -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +# CONFIG_NET_PCMCIA is not set # # Wan interfaces @@ -380,6 +489,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -397,6 +507,8 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set # # Serial drivers @@ -406,10 +518,10 @@ CONFIG_HW_CONSOLE=y # # Non-8250 serial port support # +# CONFIG_SERIAL_AU1X00 is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -423,19 +535,17 @@ CONFIG_LEGACY_PTY_COUNT=256 CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -443,6 +553,11 @@ CONFIG_RTC=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -465,7 +580,6 @@ CONFIG_RTC=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -476,6 +590,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -508,6 +624,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -520,7 +637,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -533,6 +651,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -546,6 +665,8 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -568,6 +689,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -628,13 +750,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -648,14 +772,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -664,8 +792,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index aeecf8550..77254620c 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:05 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set CONFIG_SOC_AU1X00=y # CONFIG_SOC_AU1000 is not set # CONFIG_SOC_AU1100 is not set @@ -97,7 +102,7 @@ CONFIG_MIPS_PB1500=y # CONFIG_TOSHIBA_RBTX4927 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_HAVE_DEC_LOCK=y -CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_COHERENT=y CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_AU1000_USB_DEVICE is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 @@ -134,7 +139,6 @@ CONFIG_64BIT_PHYS_ADDR=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -146,10 +150,17 @@ CONFIG_PCI_NAMES=y CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y + +# +# PC-card bridges +# # CONFIG_YENTA is not set CONFIG_PD6729=m # CONFIG_I82092 is not set @@ -175,6 +186,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -205,7 +217,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -219,12 +243,11 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -238,7 +261,6 @@ CONFIG_BLK_DEV_GENERIC=y CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set # CONFIG_IDEDMA_PCI_AUTO is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -317,6 +339,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -330,13 +355,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -354,7 +380,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -387,7 +412,7 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set +CONFIG_MII=m CONFIG_MIPS_AU1X00_ENET=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set @@ -434,13 +459,13 @@ CONFIG_MIPS_AU1X00_ENET=y # CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m # # Wan interfaces @@ -497,6 +522,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -530,7 +556,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -550,14 +575,13 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -565,6 +589,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -592,6 +621,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -624,6 +655,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -636,7 +668,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -649,6 +682,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -684,6 +718,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -744,13 +779,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -764,14 +801,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_CRC32C is not set @@ -780,8 +821,10 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index 519cd8f26..93a221a73 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:05 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +72,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +80,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set CONFIG_SOC_AU1X00=y # CONFIG_SOC_AU1000 is not set # CONFIG_SOC_AU1100 is not set @@ -97,7 +102,8 @@ CONFIG_MIPS_PB1550=y # CONFIG_TOSHIBA_RBTX4927 is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_HAVE_DEC_LOCK=y -CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_COHERENT=y +CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -133,7 +139,6 @@ CONFIG_64BIT_PHYS_ADDR=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -145,15 +150,22 @@ CONFIG_PCI_NAMES=y CONFIG_MMU=y # -# PCMCIA/CardBus support +# PCCARD (PCMCIA/CardBus) support # -CONFIG_PCMCIA=m +CONFIG_PCCARD=m # CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA_OBSOLETE is not set +CONFIG_PCMCIA=m +CONFIG_CARDBUS=y + +# +# PC-card bridges +# # CONFIG_YENTA is not set CONFIG_PD6729=m # CONFIG_I82092 is not set # CONFIG_TCIC is not set -CONFIG_PCMCIA_AU1X00=m +# CONFIG_PCMCIA_AU1X00 is not set # # PCI Hotplug Support @@ -174,6 +186,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -204,7 +217,19 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -218,12 +243,11 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -237,7 +261,6 @@ CONFIG_BLK_DEV_GENERIC=y CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set # CONFIG_IDEDMA_PCI_AUTO is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -316,6 +339,9 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -329,13 +355,14 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # # CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_CONNTRACK_MARK=y # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -353,7 +380,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -431,15 +457,7 @@ CONFIG_MIPS_AU1X00_ENET=y # # PCMCIA network device support # -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set +# CONFIG_NET_PCMCIA is not set # # Wan interfaces @@ -496,6 +514,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -529,7 +548,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -549,14 +567,13 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_SYNCLINK_CS is not set +CONFIG_SYNCLINK_CS=m # CONFIG_RAW_DRIVER is not set # @@ -564,6 +581,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -591,6 +613,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -623,6 +647,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -635,7 +660,8 @@ CONFIG_AUTOFS4_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -648,6 +674,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -683,6 +710,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set @@ -743,13 +771,15 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -763,14 +793,18 @@ CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_BLOWFISH is not set CONFIG_CRYPTO_TWOFISH=y # CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_CRC32C=m @@ -779,8 +813,10 @@ CONFIG_CRYPTO_CRC32C=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 2ec393280..755e49bda 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:06 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -26,6 +28,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y @@ -33,11 +36,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -47,13 +52,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -69,6 +74,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -76,7 +82,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set CONFIG_SNI_RM200_PCI=y @@ -127,7 +132,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -154,6 +158,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -221,10 +226,23 @@ CONFIG_PARIDE_ON26=m CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -275,7 +293,9 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_MEGARAID is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -287,6 +307,7 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m @@ -305,6 +326,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -333,14 +355,16 @@ CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=m # CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m CONFIG_BLK_DEV_DM=m # CONFIG_DM_CRYPT is not set -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # # Fusion MPT device support @@ -385,6 +409,9 @@ CONFIG_IP_PIMSM_V2=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +CONFIG_IP_TCPDIAG_IPV6=y # # IP: Virtual Server Configuration @@ -395,6 +422,7 @@ CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -404,6 +432,9 @@ CONFIG_BRIDGE_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m @@ -429,8 +460,17 @@ CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_PHYSDEV=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -449,18 +489,15 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_CONNMARK=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # # IPv6: Netfilter Configuration @@ -480,6 +517,7 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_AHESP=m CONFIG_IP6_NF_MATCH_LENGTH=m CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_PHYSDEV=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m @@ -524,7 +562,6 @@ CONFIG_XFRM=y CONFIG_BRIDGE=m # CONFIG_VLAN_8021Q is not set CONFIG_DECNET=m -# CONFIG_DECNET_SIOCGIFCONF is not set # CONFIG_DECNET_ROUTER is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set @@ -534,16 +571,17 @@ CONFIG_DECNET=m # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -551,7 +589,7 @@ CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_DELAY=m +CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y @@ -665,7 +703,6 @@ CONFIG_EEPRO100=m # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set # CONFIG_LAN_SAA9730 is not set # CONFIG_NET_POCKET is not set @@ -680,6 +717,7 @@ CONFIG_EEPRO100=m # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m # CONFIG_TIGON3 is not set # @@ -749,6 +787,7 @@ CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set CONFIG_SERIO_PARKBD=m # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -801,7 +840,6 @@ CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=m CONFIG_TIPAR=m -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -821,7 +859,6 @@ CONFIG_RTC=m # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -831,6 +868,16 @@ CONFIG_RTC=m # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_MATROX=m +CONFIG_W1_DS9490=m +CONFIG_W1_DS9490R_BRIDGE=m +CONFIG_W1_THERM=m +CONFIG_W1_SMEM=m + # # Misc devices # @@ -873,6 +920,9 @@ CONFIG_USB=m CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -901,7 +951,7 @@ CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=m CONFIG_USB_HIDINPUT=y @@ -942,7 +992,7 @@ CONFIG_USB_DABUSB=m # # -# USB Network adaptors +# USB Network Adapters # CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m @@ -959,6 +1009,7 @@ CONFIG_USB_BELKIN=y CONFIG_USB_GENESYS=y CONFIG_USB_NET1080=y CONFIG_USB_PL2301=y +CONFIG_USB_KC2190=y # # Intelligent USB Devices/Gadgets @@ -986,6 +1037,7 @@ CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_BELKIN=m CONFIG_USB_SERIAL_WHITEHEAT=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CYPRESS_M8=m CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_VISOR=m @@ -993,6 +1045,7 @@ CONFIG_USB_SERIAL_IPAQ=m CONFIG_USB_SERIAL_IR=m CONFIG_USB_SERIAL_EDGEPORT=m CONFIG_USB_SERIAL_EDGEPORT_TI=m +# CONFIG_USB_SERIAL_IPW is not set CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m CONFIG_USB_SERIAL_KEYSPAN_MPR=y @@ -1030,26 +1083,18 @@ CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_LED=m CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m CONFIG_USB_PHIDGETSERVO=m CONFIG_USB_TEST=m +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # -CONFIG_USB_GADGET=m -CONFIG_USB_GADGET_NET2280=y -CONFIG_USB_NET2280=m -# CONFIG_USB_GADGET_PXA2XX is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_SA1100 is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -CONFIG_USB_GADGET_DUALSPEED=y -CONFIG_USB_ZERO=m -CONFIG_USB_ETH=m -# CONFIG_USB_ETH_RNDIS is not set -CONFIG_USB_GADGETFS=m -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_GADGET is not set # # File systems @@ -1069,10 +1114,7 @@ CONFIG_REISERFS_FS=m CONFIG_REISERFS_FS_XATTR=y CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y -CONFIG_JFS_FS=m -# CONFIG_JFS_POSIX_ACL is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set +# CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m # CONFIG_XFS_RT is not set @@ -1083,6 +1125,7 @@ CONFIG_MINIX_FS=m CONFIG_ROMFS_FS=m # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -1094,6 +1137,7 @@ CONFIG_JOLIET=y CONFIG_ZISOFS=y CONFIG_ZISOFS_FS=m CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -1158,10 +1202,12 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set # CONFIG_CIFS_POSIX is not set CONFIG_NCP_FS=m CONFIG_NCPFS_PACKET_SIGNING=y @@ -1225,7 +1271,7 @@ CONFIG_NLS_CODEPAGE_874=m CONFIG_NLS_ISO8859_8=m CONFIG_NLS_CODEPAGE_1250=m CONFIG_NLS_CODEPAGE_1251=m -# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ASCII=m CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m @@ -1244,13 +1290,15 @@ CONFIG_NLS_UTF8=m # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -1264,6 +1312,7 @@ CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m @@ -1271,7 +1320,10 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_CRC32C is not set @@ -1280,8 +1332,10 @@ CONFIG_CRYPTO_TEST=m # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index 41d73cf45..4254c115c 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:06 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,11 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -24,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +50,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y @@ -51,7 +58,6 @@ CONFIG_STOP_MACHINE=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -67,6 +73,7 @@ CONFIG_STOP_MACHINE=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -74,7 +81,6 @@ CONFIG_STOP_MACHINE=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set CONFIG_SIBYTE_SB1xxx_SOC=y CONFIG_SIBYTE_SWARM=y @@ -149,7 +155,6 @@ CONFIG_CPU_HAS_SYNC=y CONFIG_SMP=y CONFIG_NR_CPUS=2 # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -166,12 +171,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# MIPS initrd options -# -# CONFIG_EMBEDDED_RAMDISK is not set # # Device Drivers @@ -180,6 +179,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -210,7 +210,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=9220 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -228,7 +240,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=y CONFIG_BLK_DEV_IDEFLOPPY=y # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -292,10 +303,13 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -313,7 +327,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -347,7 +360,6 @@ CONFIG_NETDEVICES=y # CONFIG_NET_ETHERNET=y CONFIG_MII=y -CONFIG_NET_SB1250_MAC=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -369,6 +381,7 @@ CONFIG_NET_SB1250_MAC=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +CONFIG_NET_SB1250_MAC=y # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -428,6 +441,7 @@ CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -458,7 +472,6 @@ CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -487,6 +500,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -514,6 +532,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -537,6 +557,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -549,7 +570,8 @@ CONFIG_FS_POSIX_ACL=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -595,6 +617,7 @@ CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -615,14 +638,16 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # CONFIG_SB1XXX_CORELIS is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -636,14 +661,18 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES=m # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_TEA=m # CONFIG_CRYPTO_ARC4 is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_CRC32C is not set @@ -652,8 +681,10 @@ CONFIG_CRYPTO_MICHAEL_MIC=y # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig index b641d81e4..71fd23fbc 100644 --- a/arch/mips/configs/sead_defconfig +++ b/arch/mips/configs/sead_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:06 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set @@ -30,11 +32,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,7 +49,6 @@ CONFIG_IOSCHED_CFQ=y # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -61,6 +64,7 @@ CONFIG_MIPS_SEAD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -68,7 +72,6 @@ CONFIG_MIPS_SEAD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -113,7 +116,6 @@ CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -127,12 +129,6 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# -# MIPS initrd options -# -CONFIG_EMBEDDED_RAMDISK=y -CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz" - # # Device Drivers # @@ -140,6 +136,7 @@ CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz" # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -165,7 +162,19 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=18432 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -189,7 +198,6 @@ CONFIG_BLK_DEV_INITRD=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -237,6 +245,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=y # # Input Device Drivers @@ -271,7 +280,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_UNIX98_PTYS is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -286,12 +294,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -301,6 +307,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -322,7 +333,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -333,6 +343,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -356,6 +368,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -368,7 +381,8 @@ CONFIG_FS_POSIX_ACL=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -413,13 +427,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -430,6 +446,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=y +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig index d942862ad..dc7a5f459 100644 --- a/arch/mips/configs/tb0226_defconfig +++ b/arch/mips/configs/tb0226_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:07 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y # CONFIG_CASIO_E55 is not set # CONFIG_IBM_WORKPAD is not set @@ -73,6 +78,7 @@ CONFIG_TANBAC_TB0226=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -80,7 +86,6 @@ CONFIG_TANBAC_TB0226=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -120,7 +125,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -168,7 +173,19 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -187,7 +204,6 @@ CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_BLK_DEV_IDEFLOPPY is not set CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -230,9 +246,8 @@ CONFIG_SCSI_CONSTANTS=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -247,7 +262,6 @@ CONFIG_SCSI_CONSTANTS=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -270,9 +284,7 @@ CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_NAT=y CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y # CONFIG_IP_PNP_DHCP is not set @@ -286,8 +298,13 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -305,7 +322,6 @@ CONFIG_SYN_COOKIES=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -404,6 +420,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -438,7 +455,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -453,12 +469,10 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -468,6 +482,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -485,13 +504,14 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Graphics support # +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -518,6 +538,8 @@ CONFIG_SOUND=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -537,6 +559,7 @@ CONFIG_EXT2_FS=y # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=m # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y @@ -569,6 +592,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -606,6 +630,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp932" @@ -667,13 +692,15 @@ CONFIG_NLS_ISO8859_1=m # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -684,8 +711,10 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig index cd08e3c03..b45434053 100644 --- a/arch/mips/configs/tb0229_defconfig +++ b/arch/mips/configs/tb0229_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:07 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y # CONFIG_CASIO_E55 is not set # CONFIG_IBM_WORKPAD is not set @@ -75,6 +80,7 @@ CONFIG_VRC4173=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -82,7 +88,6 @@ CONFIG_VRC4173=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -123,7 +128,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -148,6 +152,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -179,7 +184,19 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -227,9 +244,7 @@ CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_NAT=y CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y # CONFIG_IP_PNP_DHCP is not set @@ -244,10 +259,13 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -265,7 +283,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -397,6 +414,7 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -431,7 +449,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -451,7 +468,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -461,6 +477,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -483,7 +504,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -495,6 +515,8 @@ CONFIG_DUMMY_CONSOLE=y # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -527,6 +549,7 @@ CONFIG_XFS_POSIX_ACL=y CONFIG_ROMFS_FS=m # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y @@ -559,6 +582,7 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -596,6 +620,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp932" @@ -657,13 +682,15 @@ CONFIG_NLS_ISO8859_1=m # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -674,8 +701,10 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +CONFIG_CRC_CCITT=m # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig index e0bc0d0b2..d5b7dfe28 100644 --- a/arch/mips/configs/workpad_defconfig +++ b/arch/mips/configs/workpad_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:12:08 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,17 +27,20 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -45,13 +50,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set CONFIG_MACH_VR41XX=y # CONFIG_CASIO_E55 is not set CONFIG_IBM_WORKPAD=y @@ -74,6 +79,7 @@ CONFIG_VRC4171=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -81,7 +87,6 @@ CONFIG_VRC4171=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set # CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -121,7 +126,6 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -143,6 +147,7 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -168,7 +173,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -186,7 +203,6 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -220,7 +236,6 @@ CONFIG_IDE_GENERIC=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -251,10 +266,13 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -272,7 +290,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -380,6 +397,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -414,7 +432,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -442,12 +459,10 @@ CONFIG_WATCHDOG=y # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -457,6 +472,11 @@ CONFIG_WATCHDOG=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -490,6 +510,8 @@ CONFIG_DUMMY_CONSOLE=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -513,6 +535,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y @@ -525,7 +548,8 @@ CONFIG_AUTOFS4_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -572,6 +596,7 @@ CONFIG_LOCKD=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -592,13 +617,15 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -609,6 +636,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig index bf259d809..6e248a3fe 100644 --- a/arch/mips/configs/yosemite_defconfig +++ b/arch/mips/configs/yosemite_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Fri Nov 26 00:00:39 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # # CONFIG_EXPERIMENTAL is not set CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y -CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -24,18 +26,22 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -43,7 +49,9 @@ CONFIG_IOSCHED_CFQ=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y # # Machine selection @@ -60,6 +68,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set CONFIG_PMC_YOSEMITE=y # CONFIG_HYPERTRANSPORT is not set @@ -76,6 +85,7 @@ CONFIG_DMA_COHERENT=y # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_IRQ_CPU=y CONFIG_IRQ_CPU_RM7K=y +CONFIG_SWAP_IO_SPACE=y CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_FB is not set @@ -110,9 +120,9 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_HIGHMEM=y -# CONFIG_SMP is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -129,7 +139,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set # # Device Drivers @@ -138,7 +147,9 @@ CONFIG_TRAD_SIGNALS=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # # Memory Technology Devices (MTD) @@ -165,7 +176,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -222,7 +245,12 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -362,7 +390,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -382,7 +409,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -392,6 +418,11 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -419,6 +450,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # USB support # # CONFIG_USB is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Gadget Support @@ -437,6 +470,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -449,7 +483,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -460,6 +495,7 @@ CONFIG_PROC_KCORE=y CONFIG_SYSFS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -503,13 +539,26 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_KGDB is not set +# CONFIG_RUNTIME_DEBUG is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -520,6 +569,8 @@ CONFIG_CMDLINE="" # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set # CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/ddb5xxx/common/Makefile b/arch/mips/ddb5xxx/common/Makefile index b2d4800a6..bc44e3032 100644 --- a/arch/mips/ddb5xxx/common/Makefile +++ b/arch/mips/ddb5xxx/common/Makefile @@ -2,4 +2,4 @@ # Makefile for the common code of NEC DDB-Vrc5xxx board # -obj-y += irq.o nile4.o prom.o rtc_ds1386.o +obj-y += nile4.o prom.o rtc_ds1386.o diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c index 547386de4..228117e1b 100644 --- a/arch/mips/ddb5xxx/ddb5074/irq.c +++ b/arch/mips/ddb5xxx/ddb5074/irq.c @@ -134,14 +134,8 @@ void ddb_8254timer_irq(void) printk("ddb_8254timer_irq called\n"); } -void __init ddb_irq_setup(void) +void __init arch_init_irq(void) { -#ifdef CONFIG_KGDB - if (remote_debug) - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif - /* setup cascade interrupts */ setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade); setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade); @@ -163,6 +157,4 @@ void __init ddb_irq_setup(void) /* Enable the interrupt cascade */ nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE); - - } diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c index 7c99c8192..68c127cd7 100644 --- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c +++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c @@ -222,7 +222,6 @@ static hw_irq_controller nile4_irq_controller = { void nile4_irq_setup(u32 base) { int i; - extern irq_desc_t irq_desc[]; irq_base=base; @@ -258,7 +257,6 @@ void nile4_irq_setup(u32 base) { irq_desc[i].depth = 1; irq_desc[i].handler = &nile4_irq_controller; } - } #if defined(CONFIG_RUNTIME_DEBUG) diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c index d652aec27..27f6a66ee 100644 --- a/arch/mips/ddb5xxx/ddb5074/setup.c +++ b/arch/mips/ddb5xxx/ddb5074/setup.c @@ -26,11 +26,6 @@ #include #include -#ifdef CONFIG_KGDB -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -#endif - static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; static void ddb_machine_restart(char *command) @@ -63,7 +58,6 @@ static void ddb_machine_power_off(void) } while (1); } -extern void ddb_irq_setup(void); extern void rtc_ds1386_init(unsigned long base); extern void (*board_timer_setup) (struct irqaction * irq); @@ -96,7 +90,6 @@ static void __init ddb5074_setup(void) { extern int panic_timeout; - irq_setup = ddb_irq_setup; set_io_port_base(NILE4_PCI_IO_BASE); isa_slot_offset = NILE4_PCI_MEM_BASE; board_timer_setup = ddb_timer_init; diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c index 6a1202aec..5388b5868 100644 --- a/arch/mips/ddb5xxx/ddb5476/irq.c +++ b/arch/mips/ddb5xxx/ddb5476/irq.c @@ -115,7 +115,7 @@ extern int setup_irq(unsigned int irq, struct irqaction *irqaction); extern void mips_cpu_irq_init(u32 irq_base); extern void vrc5476_irq_init(u32 irq_base); -void __init ddb5476_irq_setup(void) +void __init arch_init_irq(void) { /* hardware initialization */ nile4_irq_setup(); diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c index 2c53c7a47..50b245da0 100644 --- a/arch/mips/ddb5xxx/ddb5476/setup.c +++ b/arch/mips/ddb5xxx/ddb5476/setup.c @@ -36,10 +36,6 @@ #define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT) #endif -#ifdef CONFIG_KGDB -extern void breakpoint(void); -#endif - static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; static void ddb_machine_restart(char *command) @@ -70,7 +66,6 @@ static void ddb_machine_power_off(void) while (1); } -extern void ddb_irq_setup(void); extern void rtc_ds1386_init(unsigned long base); static void __init ddb_time_init(void) @@ -129,14 +124,11 @@ static struct { static void ddb5476_board_init(void); -extern void ddb5476_irq_setup(void); -extern void (*irq_setup)(void); static void __init ddb5476_setup(void) { extern int panic_timeout; - irq_setup = ddb5476_irq_setup; set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE)); board_time_init = ddb_time_init; diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c index c662dd209..a77682be0 100644 --- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c +++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c @@ -66,15 +66,14 @@ static hw_irq_controller vrc5476_irq_controller = { void __init vrc5476_irq_init(u32 base) { - extern irq_desc_t irq_desc[]; u32 i; irq_base = base; for (i= base; i< base + NUM_VRC5476_IRQ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &vrc5476_irq_controller; + irq_desc[i].depth = 1; + irq_desc[i].handler = &vrc5476_irq_controller; } } diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c index dfc2559aa..5f027bfa4 100644 --- a/arch/mips/ddb5xxx/ddb5477/irq.c +++ b/arch/mips/ddb5xxx/ddb5477/irq.c @@ -79,11 +79,8 @@ extern asmlinkage void ddb5477_handle_int(void); extern int setup_irq(unsigned int irq, struct irqaction *irqaction); static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; -void -ddb5477_irq_setup(void) +void __init arch_init_irq(void) { - db_run(printk("ddb5477_irq_setup invoked.\n")); - /* by default, we disable all interrupts and route all vrc5477 * interrupts to pin 0 (irq 2) */ ddb_out32(DDB_INTCTRL0, 0); diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c index ab8b838f9..0d5e70620 100644 --- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c +++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c @@ -100,10 +100,8 @@ hw_irq_controller vrc5477_irq_controller = { NULL /* no affinity stuff for UP */ }; -void -vrc5477_irq_init(u32 irq_base) +void __init vrc5477_irq_init(u32 irq_base) { - extern irq_desc_t irq_desc[]; u32 i; for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) { diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c index dc02a3a80..97b1fcdb5 100644 --- a/arch/mips/ddb5xxx/ddb5477/setup.c +++ b/arch/mips/ddb5xxx/ddb5477/setup.c @@ -3,6 +3,8 @@ * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * arch/mips/ddb5xxx/ddb5477/setup.c * Setup file for DDB5477. * @@ -35,7 +37,6 @@ #include #include #include -#include #include @@ -165,8 +166,6 @@ static void __init ddb_timer_setup(struct irqaction *irq) } static void ddb5477_board_init(void); -extern void ddb5477_irq_setup(void); -extern void (*irq_setup)(void); extern struct pci_controller ddb5477_ext_controller; extern struct pci_controller ddb5477_io_controller; @@ -178,7 +177,6 @@ static int ddb5477_setup(void) /* initialize board - we don't trust the loader */ ddb5477_board_init(); - irq_setup = ddb5477_irq_setup; set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE)); board_time_init = ddb_time_init; diff --git a/arch/mips/dec/boot/decstation.c b/arch/mips/dec/boot/decstation.c index f7e3dc366..23ec745a4 100644 --- a/arch/mips/dec/boot/decstation.c +++ b/arch/mips/dec/boot/decstation.c @@ -26,7 +26,6 @@ #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) extern int _ftext, _end; /* begin and end of kernel image */ -extern void *__rd_start, *__rd_end; /* begin and end of ramdisk image */ extern void kernel_entry(int, char **, unsigned long, int *); void * memcpy(void * dest, const void *src, unsigned int count) @@ -81,11 +80,5 @@ void dec_entry(int argc, char **argv, rex_clear_cache(); } -#ifdef CONFIG_BLK_DEV_INITRD - LOADER_TYPE = 1; - INITRD_START = (long)&__rd_start; - INITRD_SIZE = (long)&__rd_end - (long)&__rd_start; -#endif - kernel_entry(argc, argv, magic, prom_vec); } diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 83b079abd..4b5279e72 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -48,11 +48,6 @@ extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); extern asmlinkage void decstation_handle_int(void); -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - spinlock_t ioasic_ssr_lock; volatile u32 *ioasic_base; @@ -136,11 +131,6 @@ extern void dec_timer_setup(struct irqaction *); static void __init decstation_setup(void) { -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif board_be_init = dec_be_init; board_time_init = dec_time_init; board_timer_setup = dec_timer_setup; @@ -701,7 +691,7 @@ void __init dec_init_kn03(void) } /* dec_init_kn03 */ -void __init init_IRQ(void) +void __init arch_init_irq(void) { switch (mips_machtype) { case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */ diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 8bc7792d6..8e9a6afbe 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Sun Nov 21 14:11:54 2004 # CONFIG_MIPS=y # CONFIG_MIPS64 is not set @@ -11,12 +13,12 @@ CONFIG_MIPS32=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -25,6 +27,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y @@ -32,11 +35,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -46,13 +51,13 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y # # Machine selection # # CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set # CONFIG_MACH_VR41XX is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set @@ -68,6 +73,7 @@ CONFIG_KMOD=y # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_3 is not set # CONFIG_MOMENCO_JAGUAR_ATX is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set @@ -75,7 +81,6 @@ CONFIG_KMOD=y # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set CONFIG_SGI_IP22=y -# CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set @@ -126,7 +131,6 @@ CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y # CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # # Bus options (PCI, PCMCIA, EISA, ISA, TC) @@ -140,7 +144,6 @@ CONFIG_MMU=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_TRAD_SIGNALS=y -CONFIG_BINFMT_IRIX=y # # Device Drivers @@ -149,6 +152,7 @@ CONFIG_BINFMT_IRIX=y # # Generic Driver Options # +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # @@ -172,7 +176,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -212,9 +228,8 @@ CONFIG_SCSI_SPI_ATTRS=m # SCSI low-level drivers # CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set # CONFIG_SCSI_DEBUG is not set # @@ -229,7 +244,6 @@ CONFIG_SGIWD93_SCSI=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -263,6 +277,9 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m +CONFIG_INET_TUNNEL=m +CONFIG_IP_TCPDIAG=m +CONFIG_IP_TCPDIAG_IPV6=y # # IP: Virtual Server Configuration @@ -302,6 +319,7 @@ CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -310,6 +328,9 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CT_PROTO_SCTP is not set CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m @@ -334,8 +355,17 @@ CONFIG_IP_NF_MATCH_HELPER=m CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -354,18 +384,15 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_CONNMARK=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # # IPv6: Netfilter Configuration @@ -414,16 +441,17 @@ CONFIG_SCTP_HMAC_MD5=y CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -431,7 +459,7 @@ CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_DELAY=m +CONFIG_NET_SCH_NETEM=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y @@ -515,7 +543,7 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV=m CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 @@ -533,6 +561,7 @@ CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -543,7 +572,10 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -569,7 +601,6 @@ CONFIG_SERIAL_CORE=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -588,16 +619,14 @@ CONFIG_WATCHDOG=y # CONFIG_SOFT_WATCHDOG is not set CONFIG_INDYDOG=m # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set CONFIG_SGI_DS1286=m +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=m @@ -608,6 +637,11 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -630,7 +664,6 @@ CONFIG_MAX_RAW_DEVS=256 # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_SGI_NEWPORT_CONSOLE=y CONFIG_DUMMY_CONSOLE=y CONFIG_FONT_8x16=y @@ -652,6 +685,8 @@ CONFIG_LOGO_SGI_CLUT224=y # # USB support # +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # # USB Gadget Support @@ -684,6 +719,7 @@ CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set CONFIG_QFMT_V2=m CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -695,6 +731,7 @@ CONFIG_JOLIET=y CONFIG_ZISOFS=y CONFIG_ZISOFS_FS=m CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -754,10 +791,17 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set # CONFIG_AFS_FS is not set # @@ -827,13 +871,15 @@ CONFIG_NLS_UTF8=m # # Kernel hacking # +# CONFIG_DEBUG_KERNEL is not set CONFIG_CROSSCOMPILE=y CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set # # Security options # +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # @@ -841,30 +887,36 @@ CONFIG_CMDLINE="" # CONFIG_CRYPTO=y CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m -# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_TEST=m # # Library routines # -CONFIG_CRC16=m +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c index 0e1ee11d9..97bf094da 100644 --- a/arch/mips/galileo-boards/ev96100/irq.c +++ b/arch/mips/galileo-boards/ev96100/irq.c @@ -59,9 +59,8 @@ asmlinkage void ev96100_cpu_irq(unsigned int pendin) do_IRQ(ffz8(pending >> 8), regs); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { set_except_vector(0, ev96100IRQ); - init_generic_irq(); mips_cpu_irq_init(0); } diff --git a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c index 10189b95d..8cbe84264 100644 --- a/arch/mips/galileo-boards/ev96100/time.c +++ b/arch/mips/galileo-boards/ev96100/time.c @@ -73,6 +73,9 @@ void mips_timer_interrupt(struct pt_regs *regs) do { kstat_this_cpu.irqs[irq]++; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c index 44f33caf2..2287b5953 100644 --- a/arch/mips/gt64120/common/time.c +++ b/arch/mips/gt64120/common/time.c @@ -36,6 +36,9 @@ static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) handled = 1; irq_src &= ~0x00000800; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif } GT_WRITE(GT_INTRCAUSE_OFS, 0); @@ -62,7 +65,6 @@ static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) */ void gt64120_time_init(void) { - extern irq_desc_t irq_desc[NR_IRQS]; static struct irqaction timer; /* Disable timer first */ diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c index 537eab3fd..93101358a 100644 --- a/arch/mips/gt64120/ev64120/irq.c +++ b/arch/mips/gt64120/ev64120/irq.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -128,7 +128,7 @@ void gt64120_irq_setup(void) set_c0_status(IE_IRQ2); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; diff --git a/arch/mips/gt64120/momenco_ocelot/dbg_io.c b/arch/mips/gt64120/momenco_ocelot/dbg_io.c index 3ef3584cf..8720bccfd 100644 --- a/arch/mips/gt64120/momenco_ocelot/dbg_io.c +++ b/arch/mips/gt64120/momenco_ocelot/dbg_io.c @@ -1,6 +1,6 @@ #include -#if defined(CONFIG_KGDB) +#ifdef CONFIG_KGDB #include /* For the serial port location and base baud */ diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c index 681227780..1b56df4f7 100644 --- a/arch/mips/gt64120/momenco_ocelot/irq.c +++ b/arch/mips/gt64120/momenco_ocelot/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -51,7 +51,7 @@ extern asmlinkage void ocelot_handle_int(void); -void __init init_IRQ(void) +void __init arch_init_irq(void) { /* * Clear all of the interrupts while we change the able around a bit. @@ -63,13 +63,6 @@ void __init init_IRQ(void) /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); - init_generic_irq(); mips_cpu_irq_init(0); rm7k_cpu_irq_init(8); - -#ifdef CONFIG_KGDB - printk("start kgdb ...\n"); - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif } diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c index 4be10d820..af8232e08 100644 --- a/arch/mips/ite-boards/generic/irq.c +++ b/arch/mips/ite-boards/generic/irq.c @@ -47,8 +47,8 @@ #include #include #include +#include -#include #include #include #include @@ -65,10 +65,6 @@ #define DPRINTK(fmt, args...) #endif -#ifdef CONFIG_KGDB -extern void breakpoint(void); -#endif - /* revisit */ #define EXT_IRQ0_TO_IP 2 /* IP 2 */ #define EXT_IRQ5_TO_IP 7 /* IP 7 */ @@ -251,7 +247,7 @@ void enable_cpu_timer(void) local_irq_restore(flags); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; unsigned long flags; @@ -259,8 +255,6 @@ void __init init_IRQ(void) memset(irq_desc, 0, sizeof(irq_desc)); set_except_vector(0, it8172_IRQ); - init_generic_irq(); - /* mask all interrupts */ it8172_hw0_icregs->lb_mask = 0xffff; it8172_hw0_icregs->lpc_mask = 0xffff; @@ -297,13 +291,6 @@ void __init init_IRQ(void) } irq_desc[MIPS_CPU_TIMER_IRQ].handler = &cp0_irq_type; set_c0_status(ALLINTS_NOTIMER); - -#ifdef CONFIG_KGDB - /* If local serial I/O used for debug port, enter kgdb at once */ - puts("Waiting for kgdb to connect..."); - set_debug_traps(); - breakpoint(); -#endif } void mips_spurious_interrupt(struct pt_regs *regs) diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index e81e23429..f71495465 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -19,11 +19,9 @@ extern asmlinkage void jazz_handle_int(void); static spinlock_t r4030_lock = SPIN_LOCK_UNLOCKED; -extern asmlinkage void sni_rm200_pci_handle_int(void); - static void enable_r4030_irq(unsigned int irq) { - unsigned int mask = 1 << (irq - JAZZ_IE_PARALLEL); + unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ); unsigned long flags; spin_lock_irqsave(&r4030_lock, flags); @@ -42,7 +40,7 @@ static unsigned int startup_r4030_irq(unsigned int irq) void disable_r4030_irq(unsigned int irq) { - unsigned int mask = ~(1 << (irq - JAZZ_IE_PARALLEL)); + unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); unsigned long flags; spin_lock_irqsave(&r4030_lock, flags); @@ -91,11 +89,10 @@ void __init init_r4030_ints(void) * driver compatibility reasons interrupts 0 - 15 to be the i8259 * interrupts even if the hardware uses a different interrupt numbering. */ -void __init init_IRQ (void) +void __init arch_init_irq(void) { set_except_vector(0, jazz_handle_int); - init_generic_irq(); init_i8259_irqs(); /* Integrated i8259 */ init_r4030_ints(); diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c index ceda294d5..79ac935e5 100644 --- a/arch/mips/jazz/jazzdma.c +++ b/arch/mips/jazz/jazzdma.c @@ -304,6 +304,8 @@ unsigned long vdma_phys2log(unsigned long paddr) return (i << 12) + (paddr & (VDMA_PAGESIZE - 1)); } +EXPORT_SYMBOL(vdma_phys2log); + /* * Translate a logical DMA address to a physical address */ @@ -394,6 +396,8 @@ void vdma_enable(int channel) R4030_CHNL_ENABLE); } +EXPORT_SYMBOL(vdma_enable); + /* * Disable a DMA channel */ @@ -429,6 +433,8 @@ void vdma_disable(int channel) *((volatile unsigned int *) JAZZ_DUMMY_DEVICE); } +EXPORT_SYMBOL(vdma_disable); + /* * Set DMA mode. This function accepts the mode values used * to set a PC-style DMA controller. For the SCSI and FDC @@ -496,6 +502,8 @@ void vdma_set_mode(int channel, int mode) } } +EXPORT_SYMBOL(vdma_set_mode); + /* * Set Transfer Address */ @@ -508,6 +516,8 @@ void vdma_set_addr(int channel, long addr) r4030_write_reg32(JAZZ_R4030_CHNL_ADDR + (channel << 5), addr); } +EXPORT_SYMBOL(vdma_set_addr); + /* * Set Transfer Count */ @@ -520,6 +530,8 @@ void vdma_set_count(int channel, int count) r4030_write_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5), count); } +EXPORT_SYMBOL(vdma_set_count); + /* * Get Residual */ diff --git a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c index f7149c48c..2a9754750 100644 --- a/arch/mips/jazz/reset.c +++ b/arch/mips/jazz/reset.c @@ -11,8 +11,6 @@ #include #include -#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) - #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ static void jazz_write_output(unsigned char val) diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 4ab85b5b2..a0dc56799 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -45,8 +45,8 @@ #include #include #include +#include -#include #include #include #include @@ -343,7 +343,8 @@ static struct irqaction pcierr_action = { int jmr3927_ether1_irq = 0; void jmr3927_irq_init(u32 irq_base); -void jmr3927_irq_setup(void) + +void __init arch_init_irq(void) { /* look for io board's presence */ int have_isac = jmr3927_have_isac(); @@ -421,24 +422,6 @@ void jmr3927_irq_setup(void) set_c0_status(ST0_IM); /* IE bit is still 0. */ } -void (*irq_setup)(void); - -void __init init_IRQ(void) -{ - -#ifdef CONFIG_KGDB - extern void breakpoint(void); - extern void set_debug_traps(void); - - puts("Wait for gdb client connection ...\n"); - set_debug_traps(); - breakpoint(); -#endif - - /* invoke board-specific irq setup */ - irq_setup(); -} - static hw_irq_controller jmr3927_irq_controller = { "jmr3927_irq", jmr3927_irq_startup, @@ -453,7 +436,6 @@ void jmr3927_irq_init(u32 irq_base) { u32 i; - init_generic_irq(); for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 13ddc5ce8..b6431275e 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -184,17 +184,12 @@ unsigned long jmr3927_do_gettimeoffset(void) } -#if defined(CONFIG_BLK_DEV_INITRD) -extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; -#endif - //#undef DO_WRITE_THROUGH #define DO_WRITE_THROUGH #define DO_ENABLE_CACHE extern char * __init prom_getcmdline(void); static void jmr3927_board_init(void); -extern void jmr3927_irq_setup(void); extern struct resource pci_io_resource; extern struct resource pci_mem_resource; @@ -203,7 +198,6 @@ static void __init jmr3927_setup(void) extern int panic_timeout; char *argptr; - irq_setup = jmr3927_irq_setup; set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO); board_time_init = jmr3927_time_init; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 3fd457737..86783790d 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/MIPS kernel. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index 1375d4483..11ebe5d4c 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Maciej W. Rozycki + * Copyright (C) 2003, 2004 Maciej W. Rozycki * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -82,7 +83,7 @@ static inline void mult_sh_align_mod(long *v1, long *v2, long *w, ".set pop" : "=&r" (lv1), "=r" (lw) : "r" (m1), "r" (m2), "r" (s), "I" (0) - : "hi", "lo", "accum"); + : "hi", "lo", GCC_REG_ACCUM); /* We have to use single integers for m1 and m2 and a double * one for p to be sure the mulsidi3 gcc's RTL multiplication * instruction has the workaround applied. Older versions of diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 36777476d..4bb849582 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -100,6 +100,7 @@ static inline void check_wait(void) case CPU_R5000: case CPU_NEVADA: case CPU_RM7000: + case CPU_RM9000: case CPU_TX49XX: case CPU_4KC: case CPU_4KEC: diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index c1f842291..5eb429137 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_PREEMPT .macro preempt_stop reg=t0 @@ -139,7 +140,11 @@ LEAF(spurious_interrupt) 1: ll t0, %lo(irq_err_count)(t1) addiu t0, 1 sc t0, %lo(irq_err_count)(t1) +#if R10000_LLSC_WAR + beqzl t0, 1b +#else beqz t0, 1b +#endif #else lui t1, %hi(irq_err_count) lw t0, %lo(irq_err_count)(t1) diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c index 8b74e9c02..269889302 100644 --- a/arch/mips/kernel/gdb-stub.c +++ b/arch/mips/kernel/gdb-stub.c @@ -171,6 +171,8 @@ static int hexToLong(char **ptr, long *longValue); static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault); void handle_exception(struct gdb_regs *regs); +int kgdb_enabled; + /* * spin locks for smp case */ diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index b8b83bccb..a5b0a389b 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -19,14 +19,25 @@ #include #include +#define PANIC_PIC(msg) \ + .set push; \ + .set reorder; \ + PTR_LA a0,8f; \ + .set noat; \ + PTR_LA AT, panic; \ + jr AT; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) + __INIT NESTED(except_vec0_generic, 0, sp) - PANIC("Exception vector 0 called") + PANIC_PIC("Exception vector 0 called") END(except_vec0_generic) NESTED(except_vec1_generic, 0, sp) - PANIC("Exception vector 1 called") + PANIC_PIC("Exception vector 1 called") END(except_vec1_generic) /* @@ -142,19 +153,17 @@ NESTED(except_vec_ejtag_debug, 0, sp) NESTED(ejtag_debug_handler, PT_SIZE, sp) .set push .set noat - .set noreorder MTC0 k0, CP0_DESAVE mfc0 k0, CP0_DEBUG sll k0, k0, 30 # Check for SDBBP. bgez k0, ejtag_return - nop PTR_LA k0, ejtag_debug_buffer LONG_S k1, 0(k0) SAVE_ALL + move a0, sp jal ejtag_exception_handler - move a0, sp RESTORE_ALL PTR_LA k0, ejtag_debug_buffer LONG_L k1, 0(k0) @@ -163,7 +172,6 @@ ejtag_return: MFC0 k0, CP0_DESAVE .set mips32 deret - nop .set pop END(ejtag_debug_handler) diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 89a8456d9..a64e87d22 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -90,15 +90,35 @@ .endm /* - * For the moment set ST0_KU so the CPU will not spit fire when - * executing 64-bit instructions. The full initialization of the - * CPU's status register is done later in per_cpu_trap_init(). + * For the moment disable interrupts, mark the kernel mode and + * set ST0_KX so that the CPU does not spit fire when using + * 64-bit addresses. A full initialization of the CPU's status + * register is done later in per_cpu_trap_init(). */ - .macro setup_c0_status -#ifdef CONFIG_MIPS64 + .macro setup_c0_status set clr + .set push mfc0 t0, CP0_STATUS - or t0, ST0_KX + or t0, ST0_CU0|\set|0x1f|\clr + xor t0, 0x1f|\clr mtc0 t0, CP0_STATUS + .set noreorder + sll zero,3 # ehb + .set pop + .endm + + .macro setup_c0_status_pri +#ifdef CONFIG_MIPS64 + setup_c0_status ST0_KX 0 +#else + setup_c0_status 0 0 +#endif + .endm + + .macro setup_c0_status_sec +#ifdef CONFIG_MIPS64 + setup_c0_status ST0_KX ST0_BEV +#else + setup_c0_status 0 ST0_BEV #endif .endm @@ -114,7 +134,7 @@ EXPORT(_stext) __INIT NESTED(kernel_entry, 16, sp) # kernel entry point - setup_c0_status + setup_c0_status_pri #ifdef CONFIG_SGI_IP27 GET_NASID_ASM t1 @@ -124,8 +144,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point ARC64_TWIDDLE_PC - CLI # disable interrupts - PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE @@ -144,7 +162,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer - jal start_kernel + j start_kernel END(kernel_entry) #ifdef CONFIG_SMP @@ -153,6 +171,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point * function after setting up the stack and gp registers. */ NESTED(smp_bootstrap, 16, sp) + setup_c0_status_sec + #ifdef CONFIG_SGI_IP27 GET_NASID_ASM t1 dli t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ @@ -166,9 +186,7 @@ NESTED(smp_bootstrap, 16, sp) ARC64_TWIDDLE_PC #endif /* CONFIG_SGI_IP27 */ - CLI - setup_c0_status - jal start_secondary + j start_secondary END(smp_bootstrap) #endif /* CONFIG_SMP */ @@ -201,13 +219,3 @@ NESTED(smp_bootstrap, 16, sp) page invalid_pmd_table, _PMD_ORDER #endif page invalid_pte_table, _PTE_ORDER - -#ifdef CONFIG_MIPS64 - /* - * 64-bit kernel mappings are really screwed up ... - */ - page kptbl, _PGD_ORDER - .globl ekptbl - page kpmdtbl, 0 -ekptbl: -#endif diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 6fb136b7d..7eec7568b 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -209,7 +209,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", irq); + printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } atomic_inc(&irq_err_count); @@ -295,7 +295,7 @@ void __init init_8259A(int auto_eoi) * IRQ2 is cascade interrupt to second interrupt controller */ static struct irqaction irq2 = { - no_action, 0, 0, "cascade", NULL, NULL + no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; static struct resource pic1_io_resource = { diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c index bc07d8112..519cd5d0a 100644 --- a/arch/mips/kernel/ioctl32.c +++ b/arch/mips/kernel/ioctl32.c @@ -47,6 +47,12 @@ COMPATIBLE_IOCTL(SBPROF_ZBSTOP) COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL) #endif /* CONFIG_SIBYTE_TBPROF */ +/*HANDLE_IOCTL(RTC_IRQP_READ, w_long) +COMPATIBLE_IOCTL(RTC_IRQP_SET) +HANDLE_IOCTL(RTC_EPOCH_READ, w_long) +COMPATIBLE_IOCTL(RTC_EPOCH_SET) +*/ + IOCTL_TABLE_END int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index dc9f7924e..1363214e7 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -265,9 +265,8 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, return 0xffffffff; } - elf_phdata = (struct elf_phdr *) - kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, - GFP_KERNEL); + elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, + GFP_KERNEL); if(!elf_phdata) { printk("Cannot kmalloc phdata for IRIX interp.\n"); @@ -436,9 +435,8 @@ static inline int look_for_irix_interpreter(char **name, if (*name != NULL) goto out; - *name = (char *) kmalloc((epp->p_filesz + - strlen(IRIX_INTERP_PREFIX)), - GFP_KERNEL); + *name = kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)), + GFP_KERNEL); if (!*name) return -ENOMEM; @@ -611,7 +609,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) size = elf_ex.e_phentsize * elf_ex.e_phnum; if (size > 65536) goto out; - elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); + elf_phdata = kmalloc(size, GFP_KERNEL); if (elf_phdata == NULL) { retval = -ENOMEM; goto out; @@ -814,8 +812,7 @@ static int load_irix_library(struct file *file) if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) return -ENOEXEC; - elf_phdata = (struct elf_phdr *) - kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); + elf_phdata = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); if (elf_phdata == NULL) return -ENOMEM; @@ -1055,7 +1052,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) struct vm_area_struct *vma; struct elfhdr elf; off_t offset = 0, dataoff; - int limit = current->rlim[RLIMIT_CORE].rlim_cur; + int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; int numnote = 4; struct memelfnote notes[4]; struct elf_prstatus prstatus; /* NT_PRSTATUS */ @@ -1131,14 +1128,28 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); psinfo.pr_sid = prstatus.pr_sid = current->signal->session; - prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); - prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); - prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime); - prstatus.pr_stime.tv_usec = CT_TO_USECS(current->stime); - prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->cutime); - prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime); - prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime); - prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->cstime); + if (current->pid == current->tgid) { + /* + * This is the record for the group leader. Add in the + * cumulative times of previous dead threads. This total + * won't include the time of each live thread whose state + * is included in the core dump. The final total reported + * to our parent process when it calls wait4 will include + * those sums as well as the little bit more time it takes + * this and each other thread to finish dying after the + * core dump synchronization phase. + */ + jiffies_to_timeval(current->utime + current->signal->utime, + &prstatus.pr_utime); + jiffies_to_timeval(current->stime + current->signal->stime, + &prstatus.pr_stime); + } else { + jiffies_to_timeval(current->utime, &prstatus.pr_utime); + jiffies_to_timeval(current->stime, &prstatus.pr_stime); + } + jiffies_to_timeval(current->signal->cutime, &prstatus.pr_cutime); + jiffies_to_timeval(current->signal->cstime, &prstatus.pr_cstime); + if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) { printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) " "(%d)\n", sizeof(elf_gregset_t), sizeof(struct pt_regs)); diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index b15f3b0de..4d94f645b 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -121,9 +121,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, return; segv_and_exit: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static void inline @@ -135,10 +133,8 @@ setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, } static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs * regs) + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - switch(regs->regs[0]) { case ERESTARTNOHAND: regs->regs[2] = EINTR; @@ -160,8 +156,6 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, else setup_irix_frame(ka, regs, sig, oldset); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -173,6 +167,7 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -192,9 +187,9 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } @@ -545,9 +540,9 @@ out: } /* This is here because of irix5_siginfo definition. */ -#define P_PID 0 -#define P_PGID 2 -#define P_ALL 7 +#define IRIX_P_PID 0 +#define IRIX_P_PGID 2 +#define IRIX_P_ALL 7 extern int getrusage(struct task_struct *, int, struct rusage __user *); @@ -584,7 +579,7 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info, retval = -EINVAL; goto out; } - if (type != P_PID && type != P_PGID && type != P_ALL) { + if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL) { retval = -EINVAL; goto out; } @@ -596,9 +591,9 @@ repeat: tsk = current; list_for_each(_p,&tsk->children) { p = list_entry(_p,struct task_struct,sibling); - if ((type == P_PID) && p->pid != pid) + if ((type == IRIX_P_PID) && p->pid != pid) continue; - if ((type == P_PGID) && process_group(p) != pid) + if ((type == IRIX_P_PGID) && process_group(p) != pid) continue; if ((p->exit_signal != SIGCHLD)) continue; @@ -633,8 +628,8 @@ repeat: goto end_waitsys; case TASK_ZOMBIE: - current->cutime += p->utime + p->cutime; - current->cstime += p->stime + p->cstime; + current->signal->cutime += p->utime + p->signal->cutime; + current->signal->cstime += p->stime + p->signal->cstime; if (ru != NULL) getrusage(p, RUSAGE_BOTH, ru); __put_user(SIGCHLD, &info->sig); diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index cb9d2fe59..088bbbc86 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include static unsigned int irq_base; diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 13acf876b..a828ca240 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -28,56 +28,33 @@ #include /* - * Controller mappings for all interrupt sources: + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves. */ -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - } -}; - -static void register_irq_proc (unsigned int irq); +void ack_bad_irq(unsigned int irq) +{ + printk("unexpected IRQ # %d\n", irq); +} -/* - * Special irq handlers. - */ +atomic_t irq_err_count; -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ return IRQ_NONE; } +#undef do_IRQ /* - * Generic no controller code + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). */ - -static void enable_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } -static void disable_none(unsigned int irq) { } -static void ack_none(unsigned int irq) +asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs) { - /* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves, it doesn't deserve - * a generic callback i think. - */ - printk("unexpected interrupt %d\n", irq); -} + irq_enter(); -/* startup is the same as "enable", shutdown is same as "disable" */ -#define shutdown_none disable_none -#define end_none enable_none + __do_IRQ(irq, regs); -struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none -}; + irq_exit(); -atomic_t irq_err_count; + return 1; +} /* * Generic, controller-independent functions: @@ -126,690 +103,20 @@ skip: return 0; } -#ifdef CONFIG_SMP -inline void synchronize_irq(unsigned int irq) -{ - while (irq_desc[irq].status & IRQ_INPROGRESS) - cpu_relax(); -} -#endif - -/* - * This should really return information about whether - * we should do bottom half handling etc. Right now we - * end up _always_ checking the bottom half, which is a - * waste of time and is not what some drivers would - * prefer. - */ -int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) -{ - int status = 1; /* Force the "do bottom halves" bit */ - int retval = 0; - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - - return retval; -} - -static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - struct irqaction *action; - - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { - printk(KERN_ERR "irq event %d: bogus return value %x\n", - irq, action_ret); - } else { - printk(KERN_ERR "irq %d: nobody cared!\n", irq); - } - dump_stack(); - printk(KERN_ERR "handlers:\n"); - action = desc->action; - do { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); - action = action->next; - } while (action); -} - -static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - static int count = 100; - - if (count) { - count--; - __report_bad_irq(irq, desc, action_ret); - } -} - -static int noirqdebug; - -static int __init noirqdebug_setup(char *str) -{ - noirqdebug = 1; - printk("IRQ lockup detection disabled\n"); - return 1; -} - -__setup("noirqdebug", noirqdebug_setup); - -/* - * If 99,900 of the previous 100,000 interrupts have not been handled then - * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to - * turn the IRQ off. - * - * (The other 100-of-100,000 interrupts may have been a correctly-functioning - * device sharing an IRQ with the failing one) - * - * Called under desc->lock - */ -static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - if (action_ret != IRQ_HANDLED) { - desc->irqs_unhandled++; - if (action_ret != IRQ_NONE) - report_bad_irq(irq, desc, action_ret); - } - - desc->irq_count++; - if (desc->irq_count < 100000) - return; - - desc->irq_count = 0; - if (desc->irqs_unhandled > 99900) { - /* - * The interrupt is stuck - */ - __report_bad_irq(irq, desc, action_ret); - /* - * Now kill the IRQ - */ - printk(KERN_EMERG "Disabling IRQ #%d\n", irq); - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - desc->irqs_unhandled = 0; -} - -/* - * 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 of an interrupt - * stack. 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. - */ - -void inline disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables of an interrupt - * stack. That is for two disables you need two enables. 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. - */ +#ifdef CONFIG_KGDB +extern void breakpoint(void); +extern void set_debug_traps(void); -void disable_irq(unsigned int irq) +static int kgdb_flag = 1; +static int __init nokgdb(char *str) { - irq_desc_t *desc = irq_desc + irq; - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line - * providing no disable_irq calls are now in effect. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/* - * do_IRQ handles all normal device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - */ -asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) -{ - /* - * We ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * 0 return value means that this irq is already being - * handled by some other CPU. (or is disabled) - */ - irq_desc_t *desc = irq_desc + irq; - struct irqaction * action; - unsigned int status; - - irq_enter(); - kstat_this_cpu.irqs[irq]++; - spin_lock(&desc->lock); - desc->handler->ack(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - status |= IRQ_PENDING; /* we _want_ to handle it */ - - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { - action = desc->action; - status &= ~IRQ_PENDING; /* we commit to handling */ - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; - - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (unlikely(!action)) - goto out; - - /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. - */ - for (;;) { - irqreturn_t action_ret; - - spin_unlock(&desc->lock); - action_ret = handle_IRQ_event(irq, regs, action); - spin_lock(&desc->lock); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } - desc->status &= ~IRQ_INPROGRESS; - -out: - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - desc->handler->end(irq); - spin_unlock(&desc->lock); - - irq_exit(); - + kgdb_flag = 0; return 1; } - -/** - * 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 - * - */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction * action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); - } +__setup("nokgdb", nokgdb); #endif - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_ATOMIC); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * 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 must not be called from interrupt context. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - desc->handler->shutdown(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; - } -} - -EXPORT_SYMBOL(free_irq); - -/* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that - * comes in on to an unassigned handler will get stuck - * with "IRQ_WAITING" cleared and the interrupt - * disabled. - */ - -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. - * - */ - -unsigned long probe_irq_on(void) -{ - unsigned int i; - irq_desc_t *desc; - unsigned long val; - unsigned long delay; - - down(&probe_sem); - /* - * something may have generated an irq long ago and we want to - * flush such a longstanding irq before considering it as spurious. - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!irq_desc[i].action) - irq_desc[i].handler->startup(i); - spin_unlock_irq(&desc->lock); - } - - /* Wait for longstanding interrupts to trigger. */ - for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ barrier(); - - /* - * enable any unassigned irqs - * (we must startup again here because if a longstanding irq - * happened in the previous stage, it may have masked itself) - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!desc->action) { - desc->status |= IRQ_AUTODETECT | IRQ_WAITING; - if (desc->handler->startup(i)) - desc->status |= IRQ_PENDING; - } - spin_unlock_irq(&desc->lock); - } - - /* - * Wait for spurious interrupts to trigger - */ - for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ barrier(); - - /* - * Now filter out any obviously spurious interrupts - */ - val = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - /* It triggered already - consider it spurious. */ - if (!(status & IRQ_WAITING)) { - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } else - if (i < 32) - val |= 1 << i; - } - spin_unlock_irq(&desc->lock); - } - - return val; -} - -EXPORT_SYMBOL(probe_irq_on); - -/* - * 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. - */ -unsigned int probe_irq_mask(unsigned long val) -{ - int i; - unsigned int mask; - - mask = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (i < 16 && !(status & IRQ_WAITING)) - mask |= 1 << i; - - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - return mask & val; -} - -/* - * 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 - * there 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. - */ - -int probe_irq_off(unsigned long val) -{ - int i, irq_found, nr_irqs; - - nr_irqs = 0; - irq_found = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = i; - nr_irqs++; - } - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - if (nr_irqs > 1) - irq_found = -irq_found; - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - unsigned long flags; - struct irqaction *old, **p; - irq_desc_t *desc = irq_desc + irq; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - desc->handler->startup(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - register_irq_proc(irq); - return 0; -} - -void __init init_generic_irq(void) +void __init init_IRQ(void) { int i; @@ -818,143 +125,16 @@ void __init init_generic_irq(void) irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &no_irq_type; + irq_desc[i].lock = SPIN_LOCK_UNLOCKED; } -} - -EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(probe_irq_mask); - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; - -#ifdef CONFIG_SMP - -static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; - -static cpumask_t 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) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -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; - cpumask_t new_value, tmp; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(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. - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; + arch_init_irq(); - irq_affinity[irq] = new_value; - irq_desc[irq].handler->set_affinity(irq, new_value); - - return full_count; -} - -#endif - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data, new_value; - unsigned long full_count = count, err; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || - irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef 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; - } - - smp_affinity_entry[irq] = entry; +#ifdef CONFIG_KGDB + if (kgdb_flag) { + printk("Wait for gdb client connection ...\n"); + set_debug_traps(); + breakpoint(); } #endif } - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); -} diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 2b2265ada..169393cc9 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -26,36 +26,36 @@ extern long __strnlen_user_asm(const char *s); /* * String functions */ -EXPORT_SYMBOL_NOVERS(memchr); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(strcat); -EXPORT_SYMBOL_NOVERS(strchr); +EXPORT_SYMBOL(memchr); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strchr); #ifdef CONFIG_MIPS64 -EXPORT_SYMBOL_NOVERS(strncmp); +EXPORT_SYMBOL(strncmp); #endif -EXPORT_SYMBOL_NOVERS(strlen); -EXPORT_SYMBOL_NOVERS(strpbrk); -EXPORT_SYMBOL_NOVERS(strncat); -EXPORT_SYMBOL_NOVERS(strnlen); -EXPORT_SYMBOL_NOVERS(strrchr); -EXPORT_SYMBOL_NOVERS(strstr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(kernel_thread); /* * Userspace access stuff. */ -EXPORT_SYMBOL_NOVERS(__copy_user); -EXPORT_SYMBOL_NOVERS(__bzero); -EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm); -EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm); -EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm); -EXPORT_SYMBOL_NOVERS(__strlen_user_asm); -EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm); -EXPORT_SYMBOL_NOVERS(__strnlen_user_asm); +EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(__bzero); +EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); +EXPORT_SYMBOL(__strncpy_from_user_asm); +EXPORT_SYMBOL(__strlen_user_nocheck_asm); +EXPORT_SYMBOL(__strlen_user_asm); +EXPORT_SYMBOL(__strnlen_user_nocheck_asm); +EXPORT_SYMBOL(__strnlen_user_asm); EXPORT_SYMBOL(csum_partial); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 4bb61f32c..fb76e458e 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -5,6 +5,7 @@ * * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2004 Thiemo Seufer */ #include #include @@ -99,10 +100,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childksp = (unsigned long)ti + THREAD_SIZE - 32; + preempt_disable(); + if (is_fpu_owner()) { save_fp(p); } + preempt_enable(); + /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; @@ -140,7 +145,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); clear_tsk_thread_flag(p, TIF_USEDFPU); - p->set_child_tid = p->clear_child_tid = NULL; return 0; } @@ -155,39 +159,30 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) /* * Create a kernel thread */ +ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) +{ + do_exit(fn(arg)); +} + long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { - long retval; - - __asm__ __volatile__( - " move $6, $sp \n" - " move $4, %5 \n" - " li $2, %1 \n" - " syscall \n" - " beq $6, $sp, 1f \n" -#ifdef CONFIG_MIPS32 /* On o32 the caller has to create the stackframe */ - " subu $sp, 32 \n" -#endif - " move $4, %3 \n" - " jalr %4 \n" - " move $4, $2 \n" - " li $2, %2 \n" - " syscall \n" -#ifdef CONFIG_MIPS32 /* On o32 the caller has to deallocate the stackframe */ - " addiu $sp, 32 \n" + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.regs[4] = (unsigned long) arg; + regs.regs[5] = (unsigned long) fn; + regs.cp0_epc = (unsigned long) kernel_thread_helper; + regs.cp0_status = read_c0_status(); +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + regs.cp0_status &= ~(ST0_KUP | ST0_IEC); + regs.cp0_status |= ST0_IEP; +#else + regs.cp0_status |= ST0_EXL; #endif - "1: move %0, $2" - : "=r" (retval) - : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), - "r" (flags | CLONE_VM | CLONE_UNTRACED) - /* - * The called subroutine might have destroyed any of the - * at, result, argument or temporary registers ... - */ - : "$2", "$3", "$4", "$5", "$6", "$7", "$8", - "$9","$10","$11","$12","$13","$14","$15","$24","$25","$31"); - - return retval; + + /* Ok, create the new process.. */ + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } struct mips_frame_info { diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 6e8511390..1ce7bd150 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -277,7 +277,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index df7a51cce..799919d9b 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -262,7 +262,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) */ case PTRACE_KILL: ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 9eb885d23..1fc3b2eb1 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -75,17 +75,8 @@ and t0, t0, t1 LONG_S t0, ST_OFF(t3) -#ifdef CONFIG_MIPS32 - fpu_save_double a0 t0 # clobbers t0 -#endif -#ifdef CONFIG_MIPS64 - sll t2, t0, 5 - bgez t2, 2f - sdc1 $f0, (THREAD_FPU + 0x00)(a0) - fpu_save_16odd a0 -2: - fpu_save_16even a0 t1 # clobbers t1 -#endif + fpu_save_double a0 t1 t0 t2 # c0_status passed in t1 + # clobbers t0 and t2 1: /* @@ -114,18 +105,10 @@ * Save a thread's fp context. */ LEAF(_save_fp) -#ifdef CONFIG_MIPS32 - fpu_save_double a0 t1 # clobbers t1 -#endif #ifdef CONFIG_MIPS64 - mfc0 t0, CP0_STATUS - sll t1, t0, 5 - bgez t1, 1f # 16 register mode? - fpu_save_16odd a0 -1: - fpu_save_16even a0 t1 # clobbers t1 - sdc1 $f0, (THREAD_FPU + 0x00)(a0) + mfc0 t1, CP0_STATUS #endif + fpu_save_double a0 t1 t0 t2 # clobbers t1 jr ra END(_save_fp) @@ -133,19 +116,7 @@ LEAF(_save_fp) * Restore a thread's fp context. */ LEAF(_restore_fp) -#ifdef CONFIG_MIPS32 fpu_restore_double a0, t1 # clobbers t1 -#endif -#ifdef CONFIG_MIPS64 - mfc0 t0, CP0_STATUS - sll t1, t0, 5 - bgez t1, 1f # 16 register mode? - - fpu_restore_16odd a0 -1: fpu_restore_16even a0, t0 # clobbers t0 - ldc1 $f0, (THREAD_FPU + 0x00)(a0) -#endif - jr ra END(_restore_fp) diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 24eab2f9d..0cb95deaa 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -17,6 +17,7 @@ #include #include #include +#include #include /* Highest syscall used of any syscall flavour */ @@ -65,7 +66,7 @@ stack_done: # restarting 1: sw v0, PT_R2(sp) # result -EXPORT(o32_syscall_exit) +o32_syscall_exit: local_irq_disable # make sure need_resched and # signals dont change between # sampling and return @@ -83,17 +84,16 @@ o32_syscall_exit_work: syscall_trace_entry: SAVE_STATIC - sw t2, PT_R1(sp) + move s0, t2 move a0, sp li a1, 0 jal do_syscall_trace - lw t2, PT_R1(sp) lw a0, PT_R4(sp) # Restore argument registers lw a1, PT_R5(sp) lw a2, PT_R6(sp) lw a3, PT_R7(sp) - jalr t2 + jalr s0 li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 @@ -199,7 +199,11 @@ illegal_syscall: 1: ll v0, (a1) move a0, a2 2: sc a0, (a1) +#if R10000_LLSC_WAR + beqzl a0, 1b +#else beqz a0, 1b +#endif .section __ex_table,"a" PTR 1b, bad_stack @@ -618,7 +622,7 @@ out: jr ra sys sys_clock_nanosleep 4 /* 4265 */ sys sys_tgkill 3 sys sys_utimes 2 - sys sys_ni_syscall 0 /* sys_mbind */ + sys sys_mbind 4 sys sys_ni_syscall 0 /* sys_get_mempolicy */ sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */ sys sys_mq_open 4 @@ -628,6 +632,11 @@ out: jr ra sys sys_mq_notify 2 /* 4275 */ sys sys_mq_getsetattr 3 sys sys_ni_syscall 0 /* sys_vserver */ + sys sys_waitid 4 + sys sys_ni_syscall 0 /* available, was setaltroot */ + sys sys_add_key 5 + sys sys_request_key 4 + sys sys_keyctl 5 .endm diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 3125b634f..d0e60b84e 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef CONFIG_BINFMT_ELF32 /* Neither O32 nor N32, so define handle_sys here */ @@ -37,8 +38,7 @@ NESTED(handle_sys64, PT_SIZE, sp) .set at #endif -FEXPORT(__handle_sys64) - subu t0, v0, __NR_64_Linux # check syscall number + dsubu t0, v0, __NR_64_Linux # check syscall number sltiu t0, t0, __NR_64_Linux_syscalls + 1 #if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32) ld t1, PT_EPC(sp) # skip syscall on return @@ -63,12 +63,12 @@ FEXPORT(__handle_sys64) sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # set flag for syscall # restarting 1: sd v0, PT_R2(sp) # result -syscall_exit: +n64_syscall_exit: local_irq_disable # make sure need_resched and # signals dont change between # sampling and return @@ -86,24 +86,25 @@ n64_syscall_exit_work: syscall_trace_entry: SAVE_STATIC - sd t2,PT_R1(sp) + move s0, t2 move a0, sp li a1, 0 jal do_syscall_trace - ld t2,PT_R1(sp) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) ld a3, PT_R7(sp) - jalr t2 + ld a4, PT_R8(sp) + ld a5, PT_R9(sp) + jalr s0 li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result @@ -115,7 +116,7 @@ illegal_syscall: sd v0, PT_R2(sp) li t0, 1 # set error flag sd t0, PT_R7(sp) - j syscall_exit + j n64_syscall_exit END(handle_sys64) LEAF(mips_atomic_set) @@ -133,7 +134,11 @@ illegal_syscall: 1: ll v0, (a1) move a0, a2 2: sc a0, (a1) +#if R10000_LLSC_WAR + beqzl a0, 1b +#else beqz a0, 1b +#endif .section __ex_table,"a" PTR 1b, bad_stack @@ -173,7 +178,7 @@ illegal_syscall: and t0, a2, t0 bnez t0, 1f - b syscall_exit + j n64_syscall_exit 1: SAVE_STATIC move a0, sp @@ -198,17 +203,6 @@ bad_alignment: j _sys_sysmips END(sys_sysmips) - LEAF(sys_syscall) /* Quick'n'dirty ... */ - move v0, a0 - move a0, a1 - move a1, a2 - move a2, a3 - move a3, a4 - move a4, a5 - move a5, a6 - j __handle_sys64 - END(sys_syscall) - .align 3 sys_call_table: PTR sys_read /* 5000 */ @@ -438,7 +432,7 @@ sys_call_table: PTR sys_clock_nanosleep PTR sys_tgkill /* 5225 */ PTR sys_utimes - PTR sys_ni_syscall /* sys_mbind */ + PTR sys_mbind PTR sys_ni_syscall /* sys_get_mempolicy */ PTR sys_ni_syscall /* sys_set_mempolicy */ PTR sys_mq_open /* 5230 */ @@ -448,3 +442,8 @@ sys_call_table: PTR sys_mq_notify PTR sys_mq_getsetattr /* 5235 */ PTR sys_ni_syscall /* sys_vserver */ + PTR sys_waitid + PTR sys_ni_syscall /* available, was setaltroot */ + PTR sys_add_key + PTR sys_request_key /* 5240 */ + PTR sys_keyctl diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index c00459f8f..0d49ab1c2 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -37,7 +37,7 @@ NESTED(handle_sysn32, PT_SIZE, sp) .set at #endif - subu t0, v0, __NR_N32_Linux # check syscall number + dsubu t0, v0, __NR_N32_Linux # check syscall number sltiu t0, t0, __NR_N32_Linux_syscalls + 1 #ifndef CONFIG_MIPS32_O32 @@ -64,11 +64,10 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result -FEXPORT(n32_syscall_exit) local_irq_disable # make sure need_resched and # signals dont change between # sampling and return @@ -86,28 +85,29 @@ n32_syscall_exit_work: n32_syscall_trace_entry: SAVE_STATIC - sd t2,PT_R1(sp) + move s0, t2 move a0, sp li a1, 0 jal do_syscall_trace - ld t2,PT_R1(sp) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) ld a2, PT_R6(sp) ld a3, PT_R7(sp) - jalr t2 + ld a4, PT_R8(sp) + ld a5, PT_R9(sp) + jalr s0 li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result - j n32_syscall_exit + j syscall_exit not_n32_scall: /* This is not an n32 compatibility syscall, pass it on to @@ -334,8 +334,8 @@ EXPORT(sysn32_call_table) PTR sys_restart_syscall PTR sys_semtimedop /* 6215 */ PTR sys_fadvise64_64 - PTR sys_statfs64 - PTR sys_fstatfs64 + PTR compat_sys_statfs64 + PTR compat_sys_fstatfs64 PTR sys_sendfile64 PTR sys_timer_create /* 6220 */ PTR sys_timer_settime @@ -356,5 +356,10 @@ EXPORT(sysn32_call_table) PTR compat_sys_mq_timedsend PTR compat_sys_mq_timedreceive PTR compat_sys_mq_notify - PTR compat_sys_mq_getsetattr /* 6239 */ - PTR sys_ni_syscall /* sys_vserver */ + PTR compat_sys_mq_getsetattr + PTR sys_ni_syscall /* 6240, sys_vserver */ + PTR sys_waitid + PTR sys_ni_syscall /* available, was setaltroot */ + PTR sys_add_key + PTR sys_request_key + PTR sys_keyctl /* 6245 */ diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 3a89bf425..433fc3cdc 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -31,7 +31,7 @@ NESTED(handle_sys, PT_SIZE, sp) .set at ld t1, PT_EPC(sp) # skip syscall on return - subu t0, v0, __NR_O32_Linux # check syscall number + dsubu t0, v0, __NR_O32_Linux # check syscall number sltiu t0, t0, __NR_O32_Linux_syscalls + 1 daddiu t1, 4 # skip to next instruction sd t1, PT_EPC(sp) @@ -48,16 +48,33 @@ NESTED(handle_sys, PT_SIZE, sp) sll a2, a2, 0 sll a3, a3, 0 - /* XXX Put both in one cacheline, should save a bit. */ dsll t0, v0, 3 # offset into table ld t2, (sys_call_table - (__NR_O32_Linux * 8))(t0) - lbu t3, (sys_narg_table - __NR_O32_Linux)(v0) - subu t0, t3, 5 # 5 or more arguments? sd a3, PT_R26(sp) # save a3 for syscall restarting - bgez t0, stackargs -stack_done: + /* + * More than four arguments. Try to deal with it by copying the + * stack arguments from the user stack to the kernel stack. + * This Sucks (TM). + * + * We intentionally keep the kernel stack a little below the top of + * userspace so we don't have to do a slower byte accurate check here. + */ + ld t0, PT_R29(sp) # get old user stack pointer + daddu t1, t0, 32 + bltz t1, bad_stack + +1: lw a4, 16(t0) # argument #5 from usp +2: lw a5, 20(t0) # argument #6 from usp +3: lw a6, 24(t0) # argument #7 from usp + + .section __ex_table,"a" + PTR 1b, bad_stack + PTR 2b, bad_stack + PTR 3b, bad_stack + .previous + li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -70,7 +87,7 @@ stack_done: sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # flag for syscall restarting 1: sd v0, PT_R2(sp) # result @@ -97,11 +114,10 @@ trace_a_syscall: sd a6, PT_R10(sp) sd a7, PT_R11(sp) - sd t2,PT_R1(sp) + move s0, t2 move a0, sp li a1, 0 jal do_syscall_trace - ld t2,PT_R1(sp) ld a0, PT_R4(sp) # Restore argument registers ld a1, PT_R5(sp) @@ -109,15 +125,15 @@ trace_a_syscall: ld a3, PT_R7(sp) ld a4, PT_R8(sp) ld a5, PT_R9(sp) - - jalr t2 + ld a6, PT_R10(sp) # For indirect syscalls + jalr s0 li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 sd t0, PT_R7(sp) # set error flag beqz t0, 1f - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result @@ -125,46 +141,11 @@ trace_a_syscall: /* ------------------------------------------------------------------------ */ - /* - * More than four arguments. Try to deal with it by copying the - * stack arguments from the user stack to the kernel stack. - * This Sucks (TM). - */ -stackargs: - ld t0, PT_R29(sp) # get old user stack pointer - subu t3, 4 - sll t1, t3, 2 # stack valid? - - addu t1, t0 # end address - or t0, t1 - bltz t0, bad_stack # -> sp is bad - - ld t0, PT_R29(sp) # get old user stack pointer - PTR_LA t1, 3f # copy 1 to 2 arguments - sll t3, t3, 2 - subu t1, t3 - jr t1 - - /* Ok, copy the args from the luser stack to the kernel stack */ - .set push - .set noreorder - .set nomacro -1: lw a5, 20(t0) # argument #6 from usp -2: lw a4, 16(t0) # argument #5 from usp -3: .set pop - - j stack_done # go back - - .section __ex_table,"a" - PTR 1b, bad_stack - PTR 2b, bad_stack - .previous - /* * The stackpointer for a call with more than 4 arguments is bad. */ bad_stack: - negu v0 # error + dnegu v0 # error sd v0, PT_R0(sp) sd v0, PT_R2(sp) li t0, 1 # set error flag @@ -200,7 +181,6 @@ LEAF(sys32_syscall) dsll v0, a0, 3 dla v1, sys32_syscall ld t2, (sys_call_table - (__NR_O32_Linux * 8))(v0) - lbu t3, (sys_narg_table - __NR_O32_Linux)(a0) li v0, -EINVAL beq t2, v1, out # do not recurse @@ -220,26 +200,9 @@ LEAF(sys32_syscall) move a0, a1 # shift argument registers move a1, a2 move a2, a3 - -1: lw a3, 16(t0) -2: lw t3, 20(t0) -3: lw t1, 24(t0) - - .section __ex_table,"a" - PTR 1b, efault - PTR 2b, efault - PTR 3b, efault - .previous - - sw t3, 16(sp) # put into new stackframe - sw t1, 20(sp) - - bnez t1, 1f # zero arguments? - daddu a0, sp, 32 # then pass sp in a0 -1: - - sw t3, 16(sp) - sw v1, 20(sp) + move a3, a4 + move a4, a5 + move a5, a6 jr t2 /* Unreached */ @@ -257,299 +220,290 @@ efault: li v0, -EFAULT out: jr ra END(sys32_syscall) - .macro syscalltable - sys sys32_syscall 0 /* 4000 */ - sys sys_exit 1 - sys sys_fork 0 - sys sys_read 3 - sys sys_write 3 - sys sys_open 3 /* 4005 */ - sys sys_close 1 - sys sys_waitpid 3 - sys sys_creat 2 - sys sys_link 2 - sys sys_unlink 1 /* 4010 */ - sys sys32_execve 0 - sys sys_chdir 1 - sys sys_time 1 - sys sys_mknod 3 - sys sys_chmod 2 /* 4015 */ - sys sys_lchown 3 - sys sys_ni_syscall 0 - sys sys_ni_syscall 0 /* was sys_stat */ - sys sys_lseek 3 - sys sys_getpid 0 /* 4020 */ - sys sys_mount 5 - sys sys_oldumount 1 - sys sys_setuid 1 - sys sys_getuid 0 - sys sys_stime 1 /* 4025 */ - sys sys32_ptrace 4 - sys sys_alarm 1 - sys sys_ni_syscall 0 /* was sys_fstat */ - sys sys_pause 0 - sys compat_sys_utime 2 /* 4030 */ - sys sys_ni_syscall 0 - sys sys_ni_syscall 0 - sys sys_access 2 - sys sys_nice 1 - sys sys_ni_syscall 0 /* 4035 */ - sys sys_sync 0 - sys sys_kill 2 - sys sys_rename 2 - sys sys_mkdir 2 - sys sys_rmdir 1 /* 4040 */ - sys sys_dup 1 - sys sys_pipe 0 - sys compat_sys_times 1 - sys sys_ni_syscall 0 - sys sys_brk 1 /* 4045 */ - sys sys_setgid 1 - sys sys_getgid 0 - sys sys_ni_syscall 0 /* was signal 2 */ - sys sys_geteuid 0 - sys sys_getegid 0 /* 4050 */ - sys sys_acct 0 - sys sys_umount 2 - sys sys_ni_syscall 0 - sys compat_sys_ioctl 3 - sys compat_sys_fcntl 3 /* 4055 */ - sys sys_ni_syscall 2 - sys sys_setpgid 2 - sys sys_ni_syscall, 0 - sys sys_olduname 1 - sys sys_umask 1 /* 4060 */ - sys sys_chroot 1 - sys sys32_ustat 2 - sys sys_dup2 2 - sys sys_getppid 0 - sys sys_getpgrp 0 /* 4065 */ - sys sys_setsid 0 - sys sys32_sigaction 3 - sys sys_sgetmask 0 - sys sys_ssetmask 1 - sys sys_setreuid 2 /* 4070 */ - sys sys_setregid 2 - sys sys32_sigsuspend 0 - sys compat_sys_sigpending 1 - sys sys_sethostname 2 - sys compat_sys_setrlimit 2 /* 4075 */ - sys compat_sys_getrlimit 2 - sys compat_sys_getrusage 2 - sys sys32_gettimeofday 2 - sys sys32_settimeofday 2 - sys sys_getgroups 2 /* 4080 */ - sys sys_setgroups 2 - sys sys_ni_syscall 0 /* old_select */ - sys sys_symlink 2 - sys sys_ni_syscall 0 /* was sys_lstat */ - sys sys_readlink 3 /* 4085 */ - sys sys_uselib 1 - sys sys_swapon 2 - sys sys_reboot 3 - sys sys32_readdir 3 - sys old_mmap 6 /* 4090 */ - sys sys_munmap 2 - sys sys_truncate 2 - sys sys_ftruncate 2 - sys sys_fchmod 2 - sys sys_fchown 3 /* 4095 */ - sys sys_getpriority 2 - sys sys_setpriority 3 - sys sys_ni_syscall 0 - sys compat_sys_statfs 2 - sys compat_sys_fstatfs 2 /* 4100 */ - sys sys_ni_syscall 0 /* sys_ioperm */ - sys sys32_socketcall 2 - sys sys_syslog 3 - sys compat_sys_setitimer 3 - sys compat_sys_getitimer 2 /* 4105 */ - sys compat_sys_newstat 2 - sys compat_sys_newlstat 2 - sys compat_sys_newfstat 2 - sys sys_uname 1 - sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */ - sys sys_vhangup 0 - sys sys_ni_syscall 0 /* was sys_idle */ - sys sys_ni_syscall 0 /* sys_vm86 */ - sys sys32_wait4 4 - sys sys_swapoff 1 /* 4115 */ - sys sys32_sysinfo 1 - sys sys32_ipc 6 - sys sys_fsync 1 - sys sys32_sigreturn 0 - sys sys_clone 0 /* 4120 */ - sys sys_setdomainname 2 - sys sys32_newuname 1 - sys sys_ni_syscall 0 /* sys_modify_ldt */ - sys sys32_adjtimex 1 - sys sys_mprotect 3 /* 4125 */ - sys compat_sys_sigprocmask 3 - sys sys_ni_syscall 0 /* was creat_module */ - sys sys_init_module 5 - sys sys_delete_module 1 - sys sys_ni_syscall 0 /* 4130, get_kernel_syms */ - sys sys_quotactl 0 - sys sys_getpgid 1 - sys sys_fchdir 1 - sys sys_bdflush 2 - sys sys_sysfs 3 /* 4135 */ - sys sys32_personality 1 - sys sys_ni_syscall 0 /* for afs_syscall */ - sys sys_setfsuid 1 - sys sys_setfsgid 1 - sys sys32_llseek 5 /* 4140 */ - sys sys32_getdents 3 - sys compat_sys_select 5 - sys sys_flock 2 - sys sys_msync 3 - sys compat_sys_readv 3 /* 4145 */ - sys compat_sys_writev 3 - sys sys_cacheflush 3 - sys sys_cachectl 3 - sys sys_sysmips 4 - sys sys_ni_syscall 0 /* 4150 */ - sys sys_getsid 1 - sys sys_fdatasync 0 - sys sys32_sysctl 1 - sys sys_mlock 2 - sys sys_munlock 2 /* 4155 */ - sys sys_mlockall 1 - sys sys_munlockall 0 - sys sys_sched_setparam 2 - sys sys_sched_getparam 2 - sys sys_sched_setscheduler 3 /* 4160 */ - sys sys_sched_getscheduler 1 - sys sys_sched_yield 0 - sys sys_sched_get_priority_max 1 - sys sys_sched_get_priority_min 1 - sys sys32_sched_rr_get_interval 2 /* 4165 */ - sys compat_sys_nanosleep 2 - sys sys_mremap 4 - sys sys_accept 3 - sys sys_bind 3 - sys sys_connect 3 /* 4170 */ - sys sys_getpeername 3 - sys sys_getsockname 3 - sys sys_getsockopt 5 - sys sys_listen 2 - sys sys_recv 4 /* 4175 */ - sys sys_recvfrom 6 - sys compat_sys_recvmsg 3 - sys sys_send 4 - sys compat_sys_sendmsg 3 - sys sys_sendto 6 /* 4180 */ - sys compat_sys_setsockopt 5 - sys sys_shutdown 2 - sys sys_socket 3 - sys sys_socketpair 4 - sys sys_setresuid 3 /* 4185 */ - sys sys_getresuid 3 - sys sys_ni_syscall 0 /* was query_module */ - sys sys_poll 3 - sys sys_nfsservctl 3 - sys sys_setresgid 3 /* 4190 */ - sys sys_getresgid 3 - sys sys_prctl 5 - sys sys32_rt_sigreturn 0 - sys sys32_rt_sigaction 4 - sys sys32_rt_sigprocmask 4 /* 4195 */ - sys sys32_rt_sigpending 2 - sys sys32_rt_sigtimedwait 4 - sys sys32_rt_sigqueueinfo 3 - sys sys32_rt_sigsuspend 0 - sys sys32_pread 6 /* 4200 */ - sys sys32_pwrite 6 - sys sys_chown 3 - sys sys_getcwd 2 - sys sys_capget 2 - sys sys_capset 2 /* 4205 */ - sys sys32_sigaltstack 0 - sys sys32_sendfile 4 - sys sys_ni_syscall 0 - sys sys_ni_syscall 0 - sys sys32_mmap2 6 /* 4210 */ - sys sys32_truncate64 4 - sys sys32_ftruncate64 4 - sys sys_newstat 2 - sys sys_newlstat 2 - sys sys_newfstat 2 /* 4215 */ - sys sys_pivot_root 2 - sys sys_mincore 3 - sys sys_madvise 3 - sys sys_getdents64 3 - sys compat_sys_fcntl64 3 /* 4220 */ - sys sys_ni_syscall 0 - sys sys_gettid 0 - sys sys32_readahead 5 - sys sys_setxattr 5 - sys sys_lsetxattr 5 /* 4225 */ - sys sys_fsetxattr 5 - sys sys_getxattr 4 - sys sys_lgetxattr 4 - sys sys_fgetxattr 4 - sys sys_listxattr 3 /* 4230 */ - sys sys_llistxattr 3 - sys sys_flistxattr 3 - sys sys_removexattr 2 - sys sys_lremovexattr 2 - sys sys_fremovexattr 2 /* 4235 */ - sys sys_tkill 2 - sys sys_sendfile64 5 - sys compat_sys_futex 5 - sys compat_sys_sched_setaffinity 3 - sys compat_sys_sched_getaffinity 3 /* 4240 */ - sys sys_io_setup 2 - sys sys_io_destroy 1 - sys sys_io_getevents 5 - sys sys_io_submit 3 - sys sys_io_cancel 3 /* 4245 */ - sys sys_exit_group 1 - sys sys_lookup_dcookie 3 - sys sys_epoll_create 1 - sys sys_epoll_ctl 4 - sys sys_epoll_wait 3 /* 4250 */ - sys sys_remap_file_pages 5 - sys sys_set_tid_address 1 - sys sys_restart_syscall 0 - sys sys_fadvise64_64 7 - sys sys_statfs64 3 /* 4255 */ - sys sys_fstatfs64 2 - sys sys_timer_create 3 - sys sys_timer_settime 4 - sys sys_timer_gettime 2 - sys sys_timer_getoverrun 1 /* 4260 */ - sys sys_timer_delete 1 - sys sys_clock_settime 2 - sys sys_clock_gettime 2 - sys sys_clock_getres 2 - sys sys_clock_nanosleep 4 /* 4265 */ - sys sys_tgkill 3 - sys compat_sys_utimes 2 - sys sys_ni_syscall 0 /* sys_mbind */ - sys sys_ni_syscall 0 /* sys_get_mempolicy */ - sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */ - sys compat_sys_mq_open 4 - sys sys_mq_unlink 1 - sys compat_sys_mq_timedsend 5 - sys compat_sys_mq_timedreceive 5 - sys compat_sys_mq_notify 2 /* 4275 */ - sys compat_sys_mq_getsetattr 3 - sys sys_ni_syscall 0 /* sys_vserver */ - - .endm - - .macro sys function, nargs - PTR \function - .endm - .align 3 + .type sys_call_table,@object; sys_call_table: - syscalltable - - .macro sys function, nargs - .byte \nargs - .endm - -sys_narg_table: - syscalltable + PTR sys32_syscall /* 4000 */ + PTR sys_exit + PTR sys_fork + PTR sys_read + PTR sys_write + PTR sys_open /* 4005 */ + PTR sys_close + PTR sys_waitpid + PTR sys_creat + PTR sys_link + PTR sys_unlink /* 4010 */ + PTR sys32_execve + PTR sys_chdir + PTR sys_time + PTR sys_mknod + PTR sys_chmod /* 4015 */ + PTR sys_lchown + PTR sys_ni_syscall + PTR sys_ni_syscall /* was sys_stat */ + PTR sys_lseek + PTR sys_getpid /* 4020 */ + PTR sys_mount + PTR sys_oldumount + PTR sys_setuid + PTR sys_getuid + PTR sys_stime /* 4025 */ + PTR sys32_ptrace + PTR sys_alarm + PTR sys_ni_syscall /* was sys_fstat */ + PTR sys_pause + PTR compat_sys_utime /* 4030 */ + PTR sys_ni_syscall + PTR sys_ni_syscall + PTR sys_access + PTR sys_nice + PTR sys_ni_syscall /* 4035 */ + PTR sys_sync + PTR sys_kill + PTR sys_rename + PTR sys_mkdir + PTR sys_rmdir /* 4040 */ + PTR sys_dup + PTR sys_pipe + PTR compat_sys_times + PTR sys_ni_syscall + PTR sys_brk /* 4045 */ + PTR sys_setgid + PTR sys_getgid + PTR sys_ni_syscall /* was signal 2 */ + PTR sys_geteuid + PTR sys_getegid /* 4050 */ + PTR sys_acct + PTR sys_umount + PTR sys_ni_syscall + PTR compat_sys_ioctl + PTR compat_sys_fcntl /* 4055 */ + PTR sys_ni_syscall + PTR sys_setpgid + PTR sys_ni_syscall + PTR sys_olduname + PTR sys_umask /* 4060 */ + PTR sys_chroot + PTR sys32_ustat + PTR sys_dup2 + PTR sys_getppid + PTR sys_getpgrp /* 4065 */ + PTR sys_setsid + PTR sys32_sigaction + PTR sys_sgetmask + PTR sys_ssetmask + PTR sys_setreuid /* 4070 */ + PTR sys_setregid + PTR sys32_sigsuspend + PTR compat_sys_sigpending + PTR sys_sethostname + PTR compat_sys_setrlimit /* 4075 */ + PTR compat_sys_getrlimit + PTR compat_sys_getrusage + PTR sys32_gettimeofday + PTR sys32_settimeofday + PTR sys_getgroups /* 4080 */ + PTR sys_setgroups + PTR sys_ni_syscall /* old_select */ + PTR sys_symlink + PTR sys_ni_syscall /* was sys_lstat */ + PTR sys_readlink /* 4085 */ + PTR sys_uselib + PTR sys_swapon + PTR sys_reboot + PTR sys32_readdir + PTR old_mmap /* 4090 */ + PTR sys_munmap + PTR sys_truncate + PTR sys_ftruncate + PTR sys_fchmod + PTR sys_fchown /* 4095 */ + PTR sys_getpriority + PTR sys_setpriority + PTR sys_ni_syscall + PTR compat_sys_statfs + PTR compat_sys_fstatfs /* 4100 */ + PTR sys_ni_syscall /* sys_ioperm */ + PTR sys32_socketcall + PTR sys_syslog + PTR compat_sys_setitimer + PTR compat_sys_getitimer /* 4105 */ + PTR compat_sys_newstat + PTR compat_sys_newlstat + PTR compat_sys_newfstat + PTR sys_uname + PTR sys_ni_syscall /* sys_ioperm *//* 4110 */ + PTR sys_vhangup + PTR sys_ni_syscall /* was sys_idle */ + PTR sys_ni_syscall /* sys_vm86 */ + PTR sys32_wait4 + PTR sys_swapoff /* 4115 */ + PTR sys32_sysinfo + PTR sys32_ipc + PTR sys_fsync + PTR sys32_sigreturn + PTR sys_clone /* 4120 */ + PTR sys_setdomainname + PTR sys32_newuname + PTR sys_ni_syscall /* sys_modify_ldt */ + PTR sys32_adjtimex + PTR sys_mprotect /* 4125 */ + PTR compat_sys_sigprocmask + PTR sys_ni_syscall /* was creat_module */ + PTR sys_init_module + PTR sys_delete_module + PTR sys_ni_syscall /* 4130, get_kernel_syms */ + PTR sys_quotactl + PTR sys_getpgid + PTR sys_fchdir + PTR sys_bdflush + PTR sys_sysfs /* 4135 */ + PTR sys32_personality + PTR sys_ni_syscall /* for afs_syscall */ + PTR sys_setfsuid + PTR sys_setfsgid + PTR sys32_llseek /* 4140 */ + PTR sys32_getdents + PTR compat_sys_select + PTR sys_flock + PTR sys_msync + PTR compat_sys_readv /* 4145 */ + PTR compat_sys_writev + PTR sys_cacheflush + PTR sys_cachectl + PTR sys_sysmips + PTR sys_ni_syscall /* 4150 */ + PTR sys_getsid + PTR sys_fdatasync + PTR sys32_sysctl + PTR sys_mlock + PTR sys_munlock /* 4155 */ + PTR sys_mlockall + PTR sys_munlockall + PTR sys_sched_setparam + PTR sys_sched_getparam + PTR sys_sched_setscheduler /* 4160 */ + PTR sys_sched_getscheduler + PTR sys_sched_yield + PTR sys_sched_get_priority_max + PTR sys_sched_get_priority_min + PTR sys32_sched_rr_get_interval /* 4165 */ + PTR compat_sys_nanosleep + PTR sys_mremap + PTR sys_accept + PTR sys_bind + PTR sys_connect /* 4170 */ + PTR sys_getpeername + PTR sys_getsockname + PTR sys_getsockopt + PTR sys_listen + PTR sys_recv /* 4175 */ + PTR sys_recvfrom + PTR compat_sys_recvmsg + PTR sys_send + PTR compat_sys_sendmsg + PTR sys_sendto /* 4180 */ + PTR compat_sys_setsockopt + PTR sys_shutdown + PTR sys_socket + PTR sys_socketpair + PTR sys_setresuid /* 4185 */ + PTR sys_getresuid + PTR sys_ni_syscall /* was query_module */ + PTR sys_poll + PTR sys_nfsservctl + PTR sys_setresgid /* 4190 */ + PTR sys_getresgid + PTR sys_prctl + PTR sys32_rt_sigreturn + PTR sys32_rt_sigaction + PTR sys32_rt_sigprocmask /* 4195 */ + PTR sys32_rt_sigpending + PTR sys32_rt_sigtimedwait + PTR sys32_rt_sigqueueinfo + PTR sys32_rt_sigsuspend + PTR sys32_pread /* 4200 */ + PTR sys32_pwrite + PTR sys_chown + PTR sys_getcwd + PTR sys_capget + PTR sys_capset /* 4205 */ + PTR sys32_sigaltstack + PTR sys32_sendfile + PTR sys_ni_syscall + PTR sys_ni_syscall + PTR sys32_mmap2 /* 4210 */ + PTR sys32_truncate64 + PTR sys32_ftruncate64 + PTR sys_newstat + PTR sys_newlstat + PTR sys_newfstat /* 4215 */ + PTR sys_pivot_root + PTR sys_mincore + PTR sys_madvise + PTR sys_getdents64 + PTR compat_sys_fcntl64 /* 4220 */ + PTR sys_ni_syscall + PTR sys_gettid + PTR sys32_readahead + PTR sys_setxattr + PTR sys_lsetxattr /* 4225 */ + PTR sys_fsetxattr + PTR sys_getxattr + PTR sys_lgetxattr + PTR sys_fgetxattr + PTR sys_listxattr /* 4230 */ + PTR sys_llistxattr + PTR sys_flistxattr + PTR sys_removexattr + PTR sys_lremovexattr + PTR sys_fremovexattr /* 4235 */ + PTR sys_tkill + PTR sys_sendfile64 + PTR compat_sys_futex + PTR compat_sys_sched_setaffinity + PTR compat_sys_sched_getaffinity /* 4240 */ + PTR sys_io_setup + PTR sys_io_destroy + PTR sys_io_getevents + PTR sys_io_submit + PTR sys_io_cancel /* 4245 */ + PTR sys_exit_group + PTR sys_lookup_dcookie + PTR sys_epoll_create + PTR sys_epoll_ctl + PTR sys_epoll_wait /* 4250 */ + PTR sys_remap_file_pages + PTR sys_set_tid_address + PTR sys_restart_syscall + PTR sys_fadvise64_64 + PTR compat_sys_statfs64 /* 4255 */ + PTR compat_sys_fstatfs64 + PTR sys_timer_create + PTR compat_sys_timer_settime + PTR compat_sys_timer_gettime + PTR sys_timer_getoverrun /* 4260 */ + PTR sys_timer_delete + PTR compat_sys_clock_settime + PTR compat_sys_clock_gettime + PTR compat_sys_clock_getres + PTR compat_sys_clock_nanosleep /* 4265 */ + PTR sys_tgkill + PTR compat_sys_utimes + PTR sys_ni_syscall /* sys_mbind */ + PTR sys_ni_syscall /* sys_get_mempolicy */ + PTR sys_ni_syscall /* 4270 sys_set_mempolicy */ + PTR compat_sys_mq_open + PTR sys_mq_unlink + PTR compat_sys_mq_timedsend + PTR compat_sys_mq_timedreceive + PTR compat_sys_mq_notify /* 4275 */ + PTR compat_sys_mq_getsetattr + PTR sys_ni_syscall /* sys_vserver */ + PTR sys_waitid + PTR sys_ni_syscall /* available, was setaltroot */ + PTR sys_add_key /* 4280 */ + PTR sys_request_key + PTR sys_keyctl + .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c index 4197b4109..732c5e680 100644 --- a/arch/mips/kernel/semaphore.c +++ b/arch/mips/kernel/semaphore.c @@ -20,11 +20,10 @@ #include #include #include -#include +#include #include - -#ifdef CONFIG_CPU_HAS_LLSC - +#include +#include /* * Atomically update sem->count. * This does the equivalent of the following: @@ -33,50 +32,51 @@ * tmp = MAX(old_count, 0) + incr; * sem->count = tmp; * return old_count; - */ -static inline int __sem_update_count(struct semaphore *sem, int incr) -{ - int old_count, tmp; - - __asm__ __volatile__( - "1: ll %0, %2 \n" - " sra %1, %0, 31 \n" - " not %1 \n" - " and %1, %0, %1 \n" - " add %1, %1, %3 \n" - " sc %1, %2 \n" - " beqz %1, 1b \n" - : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) - : "r" (incr), "m" (sem->count)); - - return old_count; -} - -#else - -/* + * * On machines without lld/scd we need a spinlock to make the manipulation of * sem->count and sem->waking atomic. Scalability isn't an issue because * this lock is used on UP only so it's just an empty variable. */ -static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; - static inline int __sem_update_count(struct semaphore *sem, int incr) { - unsigned long flags; int old_count, tmp; - spin_lock_irqsave(&semaphore_lock, flags); - old_count = atomic_read(&sem->count); - tmp = max_t(int, old_count, 0) + incr; - atomic_set(&sem->count, tmp); - spin_unlock_irqrestore(&semaphore_lock, flags); + if (cpu_has_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + "1: ll %0, %2 \n" + " sra %1, %0, 31 \n" + " not %1 \n" + " and %1, %0, %1 \n" + " add %1, %1, %3 \n" + " sc %1, %2 \n" + " beqzl %1, 1b \n" + : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) + : "r" (incr), "m" (sem->count)); + } else if (cpu_has_llsc) { + __asm__ __volatile__( + "1: ll %0, %2 \n" + " sra %1, %0, 31 \n" + " not %1 \n" + " and %1, %0, %1 \n" + " add %1, %1, %3 \n" + " sc %1, %2 \n" + " beqz %1, 1b \n" + : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) + : "r" (incr), "m" (sem->count)); + } else { + static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; + unsigned long flags; + + spin_lock_irqsave(&semaphore_lock, flags); + old_count = atomic_read(&sem->count); + tmp = max_t(int, old_count, 0) + incr; + atomic_set(&sem->count, tmp); + spin_unlock_irqrestore(&semaphore_lock, flags); + } return old_count; } -#endif - void __up(struct semaphore *sem) { /* diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 711ad59d6..9411f9059 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -56,8 +56,6 @@ unsigned int PCI_DMA_BUS_IS_PHYS; EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); -extern void * __rd_start, * __rd_end; - /* * Setup information * @@ -194,6 +192,68 @@ static inline void parse_cmdline_early(void) } } +static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end) +{ + /* + * "rd_start=0xNNNNNNNN" defines the memory address of an initrd + * "rd_size=0xNN" it's size + */ + unsigned long start = 0; + unsigned long size = 0; + unsigned long end; + char cmd_line[CL_SIZE]; + char *start_str; + char *size_str; + char *tmp; + + strcpy(cmd_line, command_line); + *command_line = 0; + tmp = cmd_line; + /* Ignore "rd_start=" strings in other parameters. */ + start_str = strstr(cmd_line, "rd_start="); + if (start_str && start_str != cmd_line && *(start_str - 1) != ' ') + start_str = strstr(start_str, " rd_start="); + while (start_str) { + if (start_str != cmd_line) + strncat(command_line, tmp, start_str - tmp); + start = memparse(start_str + 9, &start_str); + tmp = start_str + 1; + start_str = strstr(start_str, " rd_start="); + } + if (*tmp) + strcat(command_line, tmp); + + strcpy(cmd_line, command_line); + *command_line = 0; + tmp = cmd_line; + /* Ignore "rd_size" strings in other parameters. */ + size_str = strstr(cmd_line, "rd_size="); + if (size_str && size_str != cmd_line && *(size_str - 1) != ' ') + size_str = strstr(size_str, " rd_size="); + while (size_str) { + if (size_str != cmd_line) + strncat(command_line, tmp, size_str - tmp); + size = memparse(size_str + 8, &size_str); + tmp = size_str + 1; + size_str = strstr(size_str, " rd_size="); + } + if (*tmp) + strcat(command_line, tmp); + +#ifdef CONFIG_MIPS64 + /* HACK: Guess if the sign extension was forgotten */ + if (start > 0x0000000080000000 && start < 0x00000000ffffffff) + start |= 0xffffffff00000000; +#endif + + end = start + size; + if (start && end) { + *rd_start = start; + *rd_end = end; + return 1; + } + return 0; +} #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) @@ -205,30 +265,42 @@ static inline void parse_cmdline_early(void) static inline void bootmem_init(void) { unsigned long start_pfn; + unsigned long reserved_end = (unsigned long)&_end; #ifndef CONFIG_SGI_IP27 - unsigned long bootmap_size, max_low_pfn, first_usable_pfn; + unsigned long first_usable_pfn; + unsigned long bootmap_size; int i; #endif #ifdef CONFIG_BLK_DEV_INITRD - unsigned long tmp; - unsigned long *initrd_header; - - tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; - if (tmp < (unsigned long)&_end) - tmp += PAGE_SIZE; - initrd_header = (unsigned long *)tmp; - if (initrd_header[0] == 0x494E5244) { - initrd_start = (unsigned long)&initrd_header[2]; - initrd_end = initrd_start + initrd_header[1]; + int initrd_reserve_bootmem = 0; + + /* Board specific code should have set up initrd_start and initrd_end */ + ROOT_DEV = Root_RAM0; + if (parse_rd_cmdline(&initrd_start, &initrd_end)) { + reserved_end = max(reserved_end, initrd_end); + initrd_reserve_bootmem = 1; + } else { + unsigned long tmp; + unsigned long *initrd_header; + + tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - 8; + if (tmp < reserved_end) + tmp += PAGE_SIZE; + initrd_header = (unsigned long *)tmp; + if (initrd_header[0] == 0x494E5244) { + initrd_start = (unsigned long)&initrd_header[2]; + initrd_end = initrd_start + initrd_header[1]; + reserved_end = max(reserved_end, initrd_end); + initrd_reserve_bootmem = 1; + } } - start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE)); -#else +#endif /* CONFIG_BLK_DEV_INITRD */ + /* * Partially used pages are not usable - thus * we are rounding upwards. */ - start_pfn = PFN_UP(CPHYSADDR(&_end)); -#endif /* CONFIG_BLK_DEV_INITRD */ + start_pfn = PFN_UP(CPHYSADDR(reserved_end)); #ifndef CONFIG_SGI_IP27 /* Find the highest page frame number we have available. */ @@ -341,21 +413,14 @@ static inline void bootmem_init(void) /* Reserve the bootmap memory. */ reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size); -#endif +#endif /* CONFIG_SGI_IP27 */ #ifdef CONFIG_BLK_DEV_INITRD - /* Board specific code should have set up initrd_start and initrd_end */ - ROOT_DEV = Root_RAM0; - if (&__rd_start != &__rd_end) { - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; - } initrd_below_start_ok = 1; if (initrd_start) { unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); printk("Initial ramdisk at: 0x%p (%lu bytes)\n", - (void *)initrd_start, - initrd_size); + (void *)initrd_start, initrd_size); if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { printk("initrd extends beyond end of memory " @@ -363,7 +428,11 @@ static inline void bootmem_init(void) sizeof(long) * 2, CPHYSADDR(initrd_end), sizeof(long) * 2, PFN_PHYS(max_low_pfn)); initrd_start = initrd_end = 0; + initrd_reserve_bootmem = 0; } + + if (initrd_reserve_bootmem) + reserve_bootmem(CPHYSADDR(initrd_start), initrd_size); } #endif /* CONFIG_BLK_DEV_INITRD */ } @@ -453,31 +522,10 @@ static void __init do_earlyinitcalls(void) void __init setup_arch(char **cmdline_p) { - unsigned int status; - cpu_probe(); prom_init(); cpu_report(); -#ifdef CONFIG_MIPS32 - /* Disable coprocessors and set FPU for 16/32 FPR register model */ - status = read_c0_status(); - status &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR); - status |= ST0_CU0; - write_c0_status(status); -#endif -#ifdef CONFIG_MIPS64 - /* - * On IP27, I am seeing the TS bit set when the kernel is loaded. - * Maybe because the kernel is in ckseg0 and not xkphys? Clear it - * anyway ... - */ - status = read_c0_status(); - status &= ~(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3); - status |= (ST0_CU0|ST0_KX|ST0_SX|ST0_FR); - write_c0_status(status); -#endif - #if defined(CONFIG_VT) #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index a820be85e..400363cdd 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -20,9 +20,10 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -41,7 +42,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); #ifdef CONFIG_TRAD_SIGNALS save_static_function(sys_sigsuspend); -static_unused int _sys_sigsuspend(struct pt_regs regs) +__attribute_used__ noinline static int +_sys_sigsuspend(nabi_no_regargs struct pt_regs regs) { sigset_t *uset, saveset, newset; @@ -68,7 +70,8 @@ static_unused int _sys_sigsuspend(struct pt_regs regs) #endif save_static_function(sys_rt_sigsuspend); -static_unused int _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { sigset_t *unewset, saveset, newset; size_t sigsetsize; @@ -178,6 +181,8 @@ asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) err |= __get_user(current->used_math, &sc->sc_used_math); + preempt_disable(); + if (current->used_math) { /* restore fpu context if we have used it before */ own_fpu(); @@ -187,22 +192,30 @@ asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) lose_fpu(); } + preempt_enable(); + return err; } +#if PLAT_TRAMPOLINE_STUFF_LINE +#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE))) +#else +#define __tramp +#endif + #ifdef CONFIG_TRAD_SIGNALS struct sigframe { u32 sf_ass[4]; /* argument save space for o32 */ - u32 sf_code[2]; /* signal trampoline */ - struct sigcontext sf_sc; + u32 sf_code[2] __tramp; /* signal trampoline */ + struct sigcontext sf_sc __tramp; sigset_t sf_mask; }; #endif struct rt_sigframe { u32 rs_ass[4]; /* argument save space for o32 */ - u32 rs_code[2]; /* signal trampoline */ - struct siginfo rs_info; + u32 rs_code[2] __tramp; /* signal trampoline */ + struct siginfo rs_info __tramp; struct ucontext rs_uc; }; @@ -320,12 +333,16 @@ inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. */ + preempt_disable(); + if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } err |= save_fp_context(sc); + preempt_enable(); + out: return err; } @@ -336,7 +353,7 @@ out: static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { - unsigned long sp; + unsigned long sp, almask; /* Default to using normal stack */ sp = regs->regs[29]; @@ -352,7 +369,12 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; - return (void *)((sp - frame_size) & ALMASK); + if (PLAT_TRAMPOLINE_STUFF_LINE) + almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1); + else + almask = ALMASK; + + return (void *)((sp - frame_size) & ~(PLAT_TRAMPOLINE_STUFF_LINE - 1)); } #ifdef CONFIG_TRAD_SIGNALS @@ -372,6 +394,9 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, * li v0, __NR_sigreturn * syscall */ + if (PLAT_TRAMPOLINE_STUFF_LINE) + __builtin_memset(frame->sf_code, '0', + PLAT_TRAMPOLINE_STUFF_LINE); err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0); err |= __put_user(0x0000000c , frame->sf_code + 1); flush_cache_sigtramp((unsigned long) frame->sf_code); @@ -406,9 +431,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } #endif @@ -428,6 +451,9 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, * li v0, __NR_rt_sigreturn * syscall */ + if (PLAT_TRAMPOLINE_STUFF_LINE) + __builtin_memset(frame->rs_code, '0', + PLAT_TRAMPOLINE_STUFF_LINE); err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); flush_cache_sigtramp((unsigned long) frame->rs_code); @@ -475,19 +501,15 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } extern void setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info); static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - switch(regs->regs[0]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: @@ -523,8 +545,6 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, setup_frame(ka, regs, sig, oldset); #endif - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -539,6 +559,7 @@ extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -564,9 +585,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 407beff81..12c210424 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -19,9 +19,10 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -29,6 +30,71 @@ #include #include +#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) + +typedef union sigval32 { + int sival_int; + s32 sival_ptr; +} sigval_t32; + +typedef struct siginfo32 { + int si_signo; + int si_code; + int si_errno; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + } _kill; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_clock_t _utime; + int _status; /* exit code */ + compat_clock_t _stime; + } _irix_sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + s32 _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL, SIGXFSZ (To do ...) */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + + /* POSIX.1b timers */ + struct { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + sigval_t32 _sigval; + } _rt; + + } _sifields; +} siginfo_t32; + /* * Including would give use the 64-bit syscall numbers ... */ @@ -127,7 +193,8 @@ static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf) * Atomically swap in the new signal mask, and wait for a signal. */ save_static_function(sys32_sigsuspend); -static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; sigset_t newset, saveset; @@ -154,7 +221,8 @@ static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) } save_static_function(sys32_rt_sigsuspend); -static_unused int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; sigset_t newset, saveset; @@ -295,6 +363,8 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, err |= __get_user(current->used_math, &sc->sc_used_math); + preempt_disable(); + if (current->used_math) { /* restore fpu context if we have used it before */ own_fpu(); @@ -304,6 +374,8 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs, lose_fpu(); } + preempt_enable(); + return err; } @@ -489,12 +561,16 @@ static inline int setup_sigcontext32(struct pt_regs *regs, * Save FPU state to signal context. Signal handler will "inherit" * current FPU state. */ + preempt_disable(); + if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } err |= save_fp_context32(sc); + preempt_enable(); + out: return err; } @@ -574,9 +650,7 @@ static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static inline void setup_rt_frame(struct k_sigaction * ka, @@ -647,16 +721,12 @@ static inline void setup_rt_frame(struct k_sigaction * ka, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs * regs) + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - switch (regs->regs[0]) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: @@ -680,8 +750,6 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, else setup_frame(ka, regs, sig, oldset); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -693,6 +761,7 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info, asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -712,9 +781,9 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index d262fbdc9..4a6174922 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -26,9 +26,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -208,7 +208,5 @@ void setup_rt_frame_n32(struct k_sigaction * ka, return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1f917fe93..3730cc0db 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -45,6 +44,7 @@ cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */ int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ +EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(cpu_online_map); cycles_t cacheflush_time; @@ -236,7 +236,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) init_new_context(current, &init_mm); current_thread_info()->cpu = 0; smp_tune_scheduling(); - prom_build_cpu_map(); prom_prepare_cpus(max_cpus); } @@ -254,16 +253,6 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(0, cpu_callin_map); } -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Startup the CPU with this logical number */ @@ -275,20 +264,10 @@ static int __init do_boot_cpu(int cpu) * The following code is purely to make sure * Linux can schedule processes on this slave. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d\n", cpu); - wake_up_forked_process(idle); - - /* - * We remove it from the pidhash and the runqueue once we've - * got the process: - */ - init_idle(idle, cpu); - - unhash_process(idle); - prom_boot_secondary(cpu, idle); /* XXXKW timeout */ diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 16519f7e8..b5a1d7f0f 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, int do_color_align; unsigned long task_size; -#if CONFIG_MIPS32 +#ifdef CONFIG_MIPS32 task_size = TASK_SIZE; #else task_size = (current->thread.mflags & MF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE; @@ -162,13 +163,15 @@ sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, } save_static_function(sys_fork); -static_unused int _sys_fork(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys_fork(nabi_no_regargs struct pt_regs regs) { return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); } save_static_function(sys_clone); -static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs) +__attribute_used__ noinline static int +_sys_clone(nabi_no_regargs struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; @@ -180,7 +183,7 @@ static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs) newsp = regs.regs[29]; parent_tidptr = (int *) regs.regs[6]; child_tidptr = (int *) regs.regs[7]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 494d1872d..00254cd55 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -128,16 +128,21 @@ asmlinkage int irix_prctl(struct pt_regs *regs) if (value > RLIM_INFINITY) value = RLIM_INFINITY; if (capable(CAP_SYS_ADMIN)) { - current->rlim[RLIMIT_STACK].rlim_max = - current->rlim[RLIMIT_STACK].rlim_cur = value; + task_lock(current->group_leader); + current->signal->rlim[RLIMIT_STACK].rlim_max = + current->signal->rlim[RLIMIT_STACK].rlim_cur = value; + task_unlock(current->group_leader); error = value; break; } - if (value > current->rlim[RLIMIT_STACK].rlim_max) { + task_lock(current->group_leader); + if (value > current->signal->rlim[RLIMIT_STACK].rlim_max) { error = -EINVAL; + task_unlock(current->group_leader); break; } - current->rlim[RLIMIT_STACK].rlim_cur = value; + current->signal->rlim[RLIMIT_STACK].rlim_cur = value; + task_unlock(current->group_leader); error = value; break; } @@ -145,7 +150,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs) case PR_GETSTACKSIZE: printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n", current->comm, current->pid); - error = current->rlim[RLIMIT_STACK].rlim_cur; + error = current->signal->rlim[RLIMIT_STACK].rlim_cur; break; case PR_MAXPPROCS: @@ -282,9 +287,9 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) int pid = (int) regs->regs[base + 5]; char *buf = (char *) regs->regs[base + 6]; struct task_struct *p; - char comm[16]; + char tcomm[sizeof(current->comm)]; - retval = verify_area(VERIFY_WRITE, buf, 16); + retval = verify_area(VERIFY_WRITE, buf, sizeof(tcomm)); if (retval) break; read_lock(&tasklist_lock); @@ -294,11 +299,11 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) retval = -ESRCH; break; } - memcpy(comm, p->comm, 16); + get_task_comm(tcomm, p); read_unlock(&tasklist_lock); /* XXX Need to check sizes. */ - copy_to_user(buf, p->comm, 16); + copy_to_user(buf, tcomm, sizeof(tcomm)); retval = 0; break; } @@ -558,7 +563,7 @@ asmlinkage int irix_brk(unsigned long brk) /* * Check against rlimit and stack.. */ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (brk - mm->end_code > rlim) { @@ -614,8 +619,14 @@ asmlinkage int irix_getgid(struct pt_regs *regs) asmlinkage int irix_stime(int value) { - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; + struct timespec tv; + + tv.tv_sec = value; + tv.tv_nsec = 0; + err = security_settime(&tv, NULL); + if (err) + return err; write_seqlock_irq(&xtime_lock); xtime.tv_sec = value; @@ -810,8 +821,8 @@ asmlinkage int irix_times(struct tms * tbuf) return err; err |= __put_user(current->utime, &tbuf->tms_utime); err |= __put_user(current->stime, &tbuf->tms_stime); - err |= __put_user(current->cutime, &tbuf->tms_cutime); - err |= __put_user(current->cstime, &tbuf->tms_cstime); + err |= __put_user(current->signal->cutime, &tbuf->tms_cutime); + err |= __put_user(current->signal->cstime, &tbuf->tms_cstime); } return err; @@ -913,8 +924,8 @@ asmlinkage int irix_getdomainname(char *name, int len) return error; down_read(&uts_sem); - if(len > (__NEW_UTS_LEN - 1)) - len = __NEW_UTS_LEN - 1; + if (len > __NEW_UTS_LEN) + len = __NEW_UTS_LEN; error = 0; if (copy_to_user(name, system_utsname.domainname, len)) error = -EFAULT; @@ -2132,7 +2143,7 @@ asmlinkage int irix_ulimit(int cmd, int arg) retval = -EINVAL; goto out; #endif - retval = current->rlim[RLIMIT_NOFILE].rlim_cur; + retval = current->signal->rlim[RLIMIT_NOFILE].rlim_cur; goto out; case 5: diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 0199485a4..94d459bea 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -1,7 +1,7 @@ /* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * Copyright (c) 2003 Maciej W. Rozycki + * Copyright (c) 2003, 2004 Maciej W. Rozycki * * Common time service routines for MIPS machines. See * Documentation/mips/time.README. @@ -26,10 +26,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -55,12 +55,6 @@ extern volatile unsigned long wall_jiffies; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; -/* - * whether we emulate local_timer_interrupts for SMP machines. - */ -int emulate_local_timer_interrupt; - - /* * By default we provide the null RTC ops */ @@ -278,7 +272,7 @@ static unsigned long fixed_rate_gettimeoffset(void) __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (sll32_usecs_per_cycle) - : "lo", "accum"); + : "lo", GCC_REG_ACCUM); /* * Due to possible jiffies inconsistencies, we need to check @@ -333,7 +327,7 @@ static unsigned long calibrate_div32_gettimeoffset(void) __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) - : "lo", "accum"); + : "lo", GCC_REG_ACCUM); /* * Due to possible jiffies inconsistencies, we need to check @@ -375,7 +369,7 @@ static unsigned long calibrate_div64_gettimeoffset(void) : "r" (timerhi), "m" (timerlo), "r" (tmp), "r" (USECS_PER_JIFFY), "r" (USECS_PER_JIFFY_FRAC) - : "hi", "lo", "accum"); + : "hi", "lo", GCC_REG_ACCUM); cached_quotient = quotient; } } @@ -389,7 +383,7 @@ static unsigned long calibrate_div64_gettimeoffset(void) __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) - : "lo", "accum"); + : "lo", GCC_REG_ACCUM); /* * Due to possible jiffies inconsistencies, we need to check @@ -417,27 +411,9 @@ static long last_rtc_update; */ void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - unsigned long pc = regs->cp0_epc; - - pc -= (unsigned long) _stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } - } - -#ifdef CONFIG_SMP - /* in UP mode, update_process_times() is invoked by do_timer() */ + if (current->pid) + profile_tick(CPU_PROFILING, regs); update_process_times(user_mode(regs)); -#endif } /* @@ -521,7 +497,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } -#if !defined(CONFIG_SMP) /* * In UP mode, we call local_timer_interrupt() to do profiling * and process accouting. @@ -531,21 +506,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ local_timer_interrupt(irq, dev_id, regs); -#else /* CONFIG_SMP */ - - if (emulate_local_timer_interrupt) { - /* - * this is the place where we send out inter-process - * interrupts and let each CPU do its own profiling - * and process accouting. - * - * Obviously we need to call local_timer_interrupt() for - * the current CPU too. - */ - panic("Not implemented yet!!!"); - } -#endif /* CONFIG_SMP */ - return IRQ_HANDLED; } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index af1b42b58..b7cfe6139 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -390,6 +390,8 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode) goto sig; } + preempt_disable(); + if (ll_task == NULL || ll_task == current) { ll_bit = 1; } else { @@ -397,6 +399,8 @@ static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode) } ll_task = current; + preempt_enable(); + regs->regs[(opcode & RT) >> 16] = value; compute_return_epc(regs); @@ -429,12 +433,18 @@ static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode) signal = SIGBUS; goto sig; } + + preempt_disable(); + if (ll_bit == 0 || ll_task != current) { regs->regs[reg] = 0; + preempt_enable(); compute_return_epc(regs); return; } + preempt_enable(); + if (put_user(regs->regs[reg], vaddr)) { signal = SIGSEGV; goto sig; @@ -494,6 +504,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) if (fcr31 & FPU_CSR_UNI_X) { int sig; + preempt_disable(); + /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... @@ -519,6 +531,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) /* Restore the hardware register state */ restore_fp(current); + preempt_enable(); + /* If something went wrong, signal */ if (sig) force_sig(sig, current); @@ -638,6 +652,8 @@ asmlinkage void do_cpu(struct pt_regs *regs) break; case 1: + preempt_disable(); + own_fpu(); if (current->used_math) { /* Using the FPU again. */ restore_fp(current); @@ -653,6 +669,8 @@ asmlinkage void do_cpu(struct pt_regs *regs) force_sig(sig, current); } + preempt_enable(); + return; case 2: @@ -892,15 +910,21 @@ extern void tlb_init(void); void __init per_cpu_trap_init(void) { unsigned int cpu = smp_processor_id(); + unsigned int status_set = ST0_CU0; - /* Some firmware leaves the BEV flag set, clear it. */ - clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); + /* + * Disable coprocessors and select 32-bit or 64-bit addressing + * and the 16/32 or 32/32 FPR register model. Reset the BEV + * flag that some firmware may have left set and the TS bit (for + * IP27). Set XX for ISA IV code to work. + */ #ifdef CONFIG_MIPS64 - set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX); + status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX; #endif - if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) - set_c0_status(ST0_XX); + status_set |= ST0_XX; + change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, + status_set); /* * Some MIPS CPUs have a dedicated interrupt vector which reduces the @@ -1008,7 +1032,8 @@ void __init trap_init(void) set_except_vector(24, handle_mcheck); if (cpu_has_vce) - memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x80); + /* Special exception: R4[04]00 uses also the divec space. */ + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100); else if (cpu_has_4kex) memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80); else diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 098cfaa23..f073841b6 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -29,6 +29,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } =0 @@ -48,7 +49,7 @@ SECTIONS /* writeable */ .data : { /* Data */ - . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ + . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ *(.data.init_task) *(.data) @@ -84,8 +85,6 @@ SECTIONS /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ __init_begin = .; - /* /DISCARD/ doesn't work for .reginfo */ - .reginfo : { *(.reginfo) } .init.text : { _sinittext = .; *(.init.text) @@ -96,9 +95,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; .early_initcall.init : { __earlyinitcall_start = .; @@ -152,6 +148,14 @@ SECTIONS *(.exit.text) *(.exit.data) *(.exitcall.exit) + + /* ABI crap starts here */ + *(.comment) + *(.MIPS.options) + *(.note) + *(.options) + *(.pdr) + *(.reginfo) } /* This is the MIPS specific mdebug section. */ diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index 08871349a..1148a2d20 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -125,12 +125,10 @@ void lasat_hw0_irqdispatch(struct pt_regs *regs) } } -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; - init_generic_irq(); - switch (mips_machtype) { case MACH_LASAT_100: lasat_int_status = (void *)LASAT_INT_STATUS_REG_100; @@ -147,7 +145,7 @@ void __init init_IRQ(void) *lasat_int_mask &= 0xffff; break; default: - panic("init_IRQ: mips_machtype incorrect"); + panic("arch_init_irq: mips_machtype incorrect"); } /* Now safe to set the exception vector. */ diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index 0c21bb336..e371ed5cb 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -134,7 +134,7 @@ void __init serial_init(void) memset(&s, 0, sizeof(s)); - s.flags = STD_COM_FLAGS|UPF_RESOURCES; + s.flags = STD_COM_FLAGS; s.iotype = SERIAL_IO_MEM; if (mips_machtype == MACH_LASAT_100) { diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c index eb0b6cf80..9f5752cdd 100644 --- a/arch/mips/lib-64/dump_tlb.c +++ b/arch/mips/lib-64/dump_tlb.c @@ -190,7 +190,7 @@ unsigned int vtop(void *address) pgd = pgd_offset(current->mm, addr); pmd = pmd_offset(pgd, addr); pte = pte_offset(pmd, addr); - paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK; + paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK; paddr |= (addr & ~PAGE_MASK); return paddr; diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c index 0d6dce9b7..2a2a0e0c4 100644 --- a/arch/mips/lib/csum_partial_copy.c +++ b/arch/mips/lib/csum_partial_copy.c @@ -6,11 +6,12 @@ * Copyright (C) 1994, 1995 Waldorf Electronics GmbH * Copyright (C) 1998, 1999 Ralf Baechle */ -#include +#include #include #include #include #include +#include /* * copy while checksumming, otherwise like csum_partial @@ -37,6 +38,7 @@ unsigned int csum_partial_copy_from_user (const char *src, char *dst, { int missing; + might_sleep(); missing = copy_from_user(dst, src, len); if (missing) { memset(dst + len - missing, 0, missing); diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c index b8aad5f39..e44e9579b 100644 --- a/arch/mips/lib/dec_and_lock.c +++ b/arch/mips/lib/dec_and_lock.c @@ -28,7 +28,7 @@ */ #ifndef ATOMIC_DEC_AND_LOCK -int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; @@ -51,5 +51,5 @@ int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) return 0; } -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif /* ATOMIC_DEC_AND_LOCK */ diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S index 6e9212035..07660e86c 100644 --- a/arch/mips/lib/strlen_user.S +++ b/arch/mips/lib/strlen_user.S @@ -3,13 +3,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1996, 1998, 1999 by Ralf Baechle + * Copyright (c) 1996, 1998, 1999, 2004 by Ralf Baechle * Copyright (c) 1999 Silicon Graphics, Inc. */ #include #include #include -#include #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index 0f3116255..6e7a8eed4 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S @@ -3,13 +3,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1996, 1998, 1999 by Ralf Baechle + * Copyright (c) 1996, 1998, 1999, 2004 by Ralf Baechle * Copyright (c) 1999 Silicon Graphics, Inc. */ #include #include #include -#include #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index f39b021b0..9b0abe9d7 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -528,9 +528,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) if (MIPSInst_FUNC(ir) != movc_op) return SIGILL; cond = fpucondbit[MIPSInst_RT(ir) >> 2]; - if (((ctx->fcr31 & cond) != 0) != ((MIPSInst_RT(ir) & 1) != 0)) - return 0; - xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)]; + if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0)) + xcp->regs[MIPSInst_RD(ir)] = + xcp->regs[MIPSInst_RS(ir)]; break; #endif diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c index 1e832a624..de77f006b 100644 --- a/arch/mips/mips-boards/atlas/atlas_int.c +++ b/arch/mips/mips-boards/atlas/atlas_int.c @@ -118,12 +118,7 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs) do_IRQ(irq, regs); } -#ifdef CONFIG_KGDB -extern void breakpoint(void); -extern int remote_debug; -#endif - -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; @@ -145,11 +140,4 @@ void __init init_IRQ(void) irq_desc[i].handler = &atlas_irq_type; spin_lock_init(&irq_desc[i].lock); } - -#ifdef CONFIG_KGDB - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif } diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index 3940bb8fc..0a1dd9bbc 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c @@ -84,7 +84,7 @@ static void __init serial_init(void) #endif s.irq = ATLASINT_UART; s.uartclk = ATLAS_BASE_BAUD * 16; - s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; s.iotype = SERIAL_IO_PORT; s.regshift = 3; diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c index 636cdcd25..31caf0603 100644 --- a/arch/mips/mips-boards/generic/init.c +++ b/arch/mips/mips-boards/generic/init.c @@ -42,8 +42,6 @@ extern char rs_getDebugChar(void); extern int saa9730_kgdb_hook(int); extern int saa9730_putDebugChar(char); extern char saa9730_getDebugChar(void); - -int remote_debug = 0; #endif int prom_argc; @@ -219,7 +217,7 @@ void __init kgdb_config (void) generic_putDebugChar (*s++); } - remote_debug = 1; + kgdb_enabled = 1; /* Breakpoint is invoked after interrupts are initialised */ } } diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index 56cf37a26..5ae2b43e4 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -77,7 +77,7 @@ struct prom_pmemblock * __init prom_getmdesc(void) mdesc[1].base = 0x00001000; mdesc[1].size = 0x000ef000; -#if (CONFIG_MIPS_MALTA) +#ifdef CONFIG_MIPS_MALTA /* * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the * south bridge and PCI access always forwarded to the ISA Bus and diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index cccd34cee..92c34bda0 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -2,6 +2,8 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -24,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 9348cd3e6..fe7fc1730 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 33e0f4b20..92c3b667c 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -41,12 +41,6 @@ extern asmlinkage void mipsIRQ(void); -#ifdef CONFIG_KGDB -extern void breakpoint(void); -extern void set_debug_traps(void); -extern int remote_debug; -#endif - static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED; static inline int mips_pcibios_iack(void) @@ -187,18 +181,8 @@ void corehi_irqdispatch(struct pt_regs *regs) die("CoreHi interrupt", regs); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { set_except_vector(0, mipsIRQ); - init_generic_irq(); init_i8259_irqs(); - -#ifdef CONFIG_KGDB - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif } - - diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index 72a16bf1f..3377e66de 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c @@ -22,6 +22,13 @@ #include #include +#ifdef CONFIG_MTD +#include +#include +#include +#include +#endif + #include #include #include @@ -53,6 +60,30 @@ struct resource standard_io_resources[] = { { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, }; +#ifdef CONFIG_MTD +static struct mtd_partition malta_mtd_partitions[] = { + { + .name = "YAMON", + .offset = 0x0, + .size = 0x100000, + .mask_flags = MTD_WRITEABLE + }, + { + .name = "User FS", + .offset = 0x100000, + .size = 0x2e0000 + }, + { + .name = "Board Config", + .offset = 0x3e0000, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE + } +}; + +#define number_partitions (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition)) +#endif + const char *get_system_type(void) { return "MIPS Malta"; @@ -132,13 +163,13 @@ static int __init malta_setup(void) } } else - panic ("Hardware DMA cache coherency not supported\n"); + panic("Hardware DMA cache coherency not supported"); #endif } #ifdef CONFIG_DMA_COHERENT else { - panic ("Hardware DMA cache coherency not supported\n"); + panic("Hardware DMA cache coherency not supported"); } #endif @@ -179,6 +210,15 @@ static int __init malta_setup(void) }; #endif #endif + +#ifdef CONFIG_MTD + /* + * Support for MTD on Malta. Use the generic physmap driver + */ + physmap_configure(0x1e000000, 0x400000, 4, NULL); + physmap_set_partitions(malta_mtd_partitions, number_partitions); +#endif + mips_reboot_setup(); board_time_init = mips_time_init; diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c index 19fb7e27c..e5109657e 100644 --- a/arch/mips/mips-boards/sead/sead_int.c +++ b/arch/mips/mips-boards/sead/sead_int.c @@ -37,7 +37,7 @@ asmlinkage void sead_hw1_irqdispatch(struct pt_regs *regs) do_IRQ(SEADINT_UART1, regs); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { /* * Mask out all interrupt @@ -47,6 +47,5 @@ void __init init_IRQ(void) /* Now safe to set the exception vector. */ set_except_vector(0, mipsIRQ); - init_generic_irq(); mips_cpu_irq_init(0); } diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c index ab6c619f2..29892b88a 100644 --- a/arch/mips/mips-boards/sead/sead_setup.c +++ b/arch/mips/mips-boards/sead/sead_setup.c @@ -73,7 +73,7 @@ static void __init serial_init(void) #endif s.irq = SEADINT_UART0; s.uartclk = SEAD_BASE_BAUD * 16; - s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; s.iotype = 0; s.regshift = 3; diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index 04c393f26..d72f4c839 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -2,7 +2,8 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y += cache.o extable.o fault.o init.o pgtable.o +obj-y += cache.o extable.o fault.o init.o pgtable.o \ + tlbex.o obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o obj-$(CONFIG_MIPS64) += pgtable-64.o @@ -41,22 +42,22 @@ obj-$(CONFIG_CPU_R5432) += tlbex32-r4k.o obj-$(CONFIG_CPU_RM7000) += tlbex32-r4k.o obj-$(CONFIG_CPU_RM9000) += tlbex32-r4k.o obj-$(CONFIG_CPU_R10000) += tlbex32-r4k.o -obj-$(CONFIG_CPU_MIPS32) += tlbex32-r4k.o +obj-$(CONFIG_CPU_MIPS32) += tlbex32-mips32.o obj-$(CONFIG_CPU_MIPS64) += tlbex32-r4k.o obj-$(CONFIG_CPU_SB1) += tlbex32-r4k.o obj-$(CONFIG_CPU_TX39XX) += tlbex32-r3k.o endif ifdef CONFIG_MIPS64 -obj-$(CONFIG_CPU_R4300) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_R4X00) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_R5000) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_NEVADA) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_R5432) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_RM7000) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_RM9000) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_R10000) += tlb64-glue-r4k.o tlbex64-r4k.o -obj-$(CONFIG_CPU_SB1) += tlb64-glue-sb1.o tlbex64-r4k.o -obj-$(CONFIG_CPU_MIPS64) += tlb64-glue-r4k.o tlbex64-r4k.o +obj-$(CONFIG_CPU_R4300) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_R4X00) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_R5000) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_NEVADA) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_R5432) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_RM7000) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_RM9000) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_R10000) += tlb64-glue-r4k.o +obj-$(CONFIG_CPU_SB1) += tlb64-glue-sb1.o +obj-$(CONFIG_CPU_MIPS64) += tlb64-glue-r4k.o endif diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 444df9c5a..887683b3c 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -7,7 +7,7 @@ * Tx39XX R4k style caches added. HK * Copyright (C) 1998, 1999, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * Copyright (C) 2001 Maciej W. Rozycki + * Copyright (C) 2001, 2004 Maciej W. Rozycki */ #include #include @@ -337,6 +337,8 @@ void __init ld_mmu_r23000(void) flush_data_cache_page = r3k_flush_data_cache_page; _dma_cache_wback_inv = r3k_dma_cache_wback_inv; + _dma_cache_wback = r3k_dma_cache_wback_inv; + _dma_cache_inv = r3k_dma_cache_wback_inv; printk("Primary instruction cache %ldkB, linesize %ld bytes.\n", icache_size >> 10, icache_lsize); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index b22df2d80..6249ac94a 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -49,7 +49,7 @@ struct bcache_ops *bcops = &no_sc_ops; #define R4600_HIT_CACHEOP_WAR_IMPL \ do { \ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) \ - *(volatile unsigned long *)KSEG1; \ + *(volatile unsigned long *)CKSEG1; \ if (R4600_V1_HIT_CACHEOP_WAR) \ __asm__ __volatile__("nop;nop;nop;nop"); \ } while (0) @@ -86,7 +86,7 @@ static inline void r4k_blast_dcache_page_indexed_setup(void) static void (* r4k_blast_dcache)(void); -static void r4k_blast_dcache_setup(void) +static inline void r4k_blast_dcache_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -254,16 +254,25 @@ static inline void r4k_blast_scache_setup(void) r4k_blast_scache = blast_scache128; } +/* + * This is former mm's flush_cache_all() which really should be + * flush_cache_vunmap these days ... + */ +static inline void local_r4k_flush_cache_all(void * args) +{ + r4k_blast_dcache(); + r4k_blast_icache(); +} + static void r4k_flush_cache_all(void) { if (!cpu_has_dc_aliases) return; - r4k_blast_dcache(); - r4k_blast_icache(); + on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1); } -static void r4k___flush_cache_all(void) +static inline void local_r4k___flush_cache_all(void * args) { r4k_blast_dcache(); r4k_blast_icache(); @@ -279,9 +288,14 @@ static void r4k___flush_cache_all(void) } } -static void r4k_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) +static void r4k___flush_cache_all(void) { + on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1); +} + +static inline void local_r4k_flush_cache_range(void * args) +{ + struct vm_area_struct *vma = args; int exec; if (!(cpu_context(smp_processor_id(), vma->vm_mm))) @@ -294,8 +308,16 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma, r4k_blast_icache(); } -static void r4k_flush_cache_mm(struct mm_struct *mm) +static void r4k_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) { + on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); +} + +static inline void local_r4k_flush_cache_mm(void * args) +{ + struct mm_struct *mm = args; + if (!cpu_has_dc_aliases) return; @@ -316,9 +338,21 @@ static void r4k_flush_cache_mm(struct mm_struct *mm) r4k_blast_scache(); } -static void r4k_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) +static void r4k_flush_cache_mm(struct mm_struct *mm) +{ + on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1); +} + +struct flush_cache_page_args { + struct vm_area_struct *vma; + unsigned long page; +}; + +static inline void local_r4k_flush_cache_page(void *args) { + struct flush_cache_page_args *fcp_args = args; + struct vm_area_struct *vma = fcp_args->vma; + unsigned long page = fcp_args->page; int exec = vma->vm_flags & VM_EXEC; struct mm_struct *mm = vma->vm_mm; pgd_t *pgdp; @@ -377,14 +411,39 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma, } } +static void r4k_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + struct flush_cache_page_args args; + + args.vma = vma; + args.page = page; + + on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1); +} + +static inline void local_r4k_flush_data_cache_page(void * addr) +{ + r4k_blast_dcache_page((unsigned long) addr); +} + static void r4k_flush_data_cache_page(unsigned long addr) { - r4k_blast_dcache_page(addr); + on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1); } -static void r4k_flush_icache_range(unsigned long start, unsigned long end) +struct flush_icache_range_args { + unsigned long start; + unsigned long end; +}; + +static inline void local_r4k_flush_icache_range(void *args) { + struct flush_icache_range_args *fir_args = args; unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long ic_lsize = current_cpu_data.icache.linesz; + unsigned long start = fir_args->start; + unsigned long end = fir_args->end; unsigned long addr, aend; if (!cpu_has_ic_fills_f_dc) { @@ -407,18 +466,28 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end) if (end - start > icache_size) r4k_blast_icache(); else { - addr = start & ~(dc_lsize - 1); - aend = (end - 1) & ~(dc_lsize - 1); + addr = start & ~(ic_lsize - 1); + aend = (end - 1) & ~(ic_lsize - 1); while (1) { /* Hit_Invalidate_I */ protected_flush_icache_line(addr); if (addr == aend) break; - addr += dc_lsize; + addr += ic_lsize; } } } +static void r4k_flush_icache_range(unsigned long start, unsigned long end) +{ + struct flush_icache_range_args args; + + args.start = start; + args.end = end; + + on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1); +} + /* * Ok, this seriously sucks. We use them to flush a user page but don't * know the virtual address, so we have to blast away the whole icache @@ -426,14 +495,17 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end) * least know the kernel address of the page so we can flush it * selectivly. */ -static void r4k_flush_icache_page(struct vm_area_struct *vma, struct page *page) + +struct flush_icache_page_args { + struct vm_area_struct *vma; + struct page *page; +}; + +static inline void local_r4k_flush_icache_page(void *args) { - /* - * If there's no context yet, or the page isn't executable, no icache - * flush is needed. - */ - if (!(vma->vm_flags & VM_EXEC)) - return; + struct flush_icache_page_args *fip_args = args; + struct vm_area_struct *vma = fip_args->vma; + struct page *page = fip_args->page; /* * Tricky ... Because we don't know the virtual address we've got the @@ -471,6 +543,25 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma, struct page *page) r4k_blast_icache(); } +static void r4k_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + struct flush_icache_page_args args; + + /* + * If there's no context yet, or the page isn't executable, no I-cache + * flush is needed. + */ + if (!(vma->vm_flags & VM_EXEC)) + return; + + args.vma = vma; + args.page = page; + + on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1); +} + + #ifdef CONFIG_DMA_NONCOHERENT static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) @@ -574,10 +665,11 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) * very much about what happens in that case. Usually a segmentation * fault will dump the process later on anyway ... */ -static void r4k_flush_cache_sigtramp(unsigned long addr) +static void local_r4k_flush_cache_sigtramp(void * arg) { unsigned long ic_lsize = current_cpu_data.icache.linesz; unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long addr = (unsigned long) arg; R4600_HIT_CACHEOP_WAR_IMPL; protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); @@ -587,10 +679,10 @@ static void r4k_flush_cache_sigtramp(unsigned long addr) ".set push\n\t" ".set noat\n\t" ".set mips3\n\t" -#if CONFIG_MIPS32 +#ifdef CONFIG_MIPS32 "la $at,1f\n\t" #endif -#if CONFIG_MIPS64 +#ifdef CONFIG_MIPS64 "dla $at,1f\n\t" #endif "cache %0,($at)\n\t" @@ -604,6 +696,11 @@ static void r4k_flush_cache_sigtramp(unsigned long addr) __asm__ __volatile__ ("sync"); } +static void r4k_flush_cache_sigtramp(unsigned long addr) +{ + on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1); +} + static void r4k_flush_icache_all(void) { if (cpu_has_vtag_icache) @@ -893,7 +990,7 @@ static void __init probe_pcache(void) cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", way_string[c->icache.ways], c->icache.linesz); - printk("Primary data cache %ldkB %s, linesize %d bytes.\n", + printk("Primary data cache %ldkB, %s, linesize %d bytes.\n", dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz); } @@ -982,7 +1079,7 @@ static void __init setup_scache(void) case CPU_R4000MC: case CPU_R4400SC: case CPU_R4400MC: - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); + probe_scache_kseg1 = (probe_func_t) (CKSEG1ADDR(&probe_scache)); sc_present = probe_scache_kseg1(config); if (sc_present) c->options |= MIPS_CPU_CACHE_CDEX_S; diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 5bae2b0e9..c90b41209 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -20,10 +20,13 @@ */ #include #include -#include + +#include #include #include #include +#include +#include #include extern void sb1_dma_init(void); @@ -32,17 +35,17 @@ extern void sb1_dma_init(void); static unsigned long icache_size; static unsigned long dcache_size; -static unsigned long icache_line_size; -static unsigned long dcache_line_size; +static unsigned short icache_line_size; +static unsigned short dcache_line_size; static unsigned int icache_index_mask; static unsigned int dcache_index_mask; -static unsigned long icache_assoc; -static unsigned long dcache_assoc; +static unsigned short icache_assoc; +static unsigned short dcache_assoc; -static unsigned int icache_sets; -static unsigned int dcache_sets; +static unsigned short icache_sets; +static unsigned short dcache_sets; static unsigned int icache_range_cutoff; static unsigned int dcache_range_cutoff; @@ -449,6 +452,11 @@ static unsigned int decode_cache_line_size(unsigned int config_field) * 9:7 Dcache Associativity */ +static char *way_string[] = { + "direct mapped", "2-way", "3-way", "4-way", + "5-way", "6-way", "7-way", "8-way", +}; + static __init void probe_cache_sizes(void) { u32 config1; @@ -473,6 +481,13 @@ static __init void probe_cache_sizes(void) */ icache_range_cutoff = icache_sets * icache_line_size; dcache_range_cutoff = (dcache_sets / 2) * icache_line_size; + + printk("Primary instruction cache %ldkB, %s, linesize %d bytes.\n", + icache_size >> 10, way_string[icache_assoc - 1], + icache_line_size); + printk("Primary data cache %ldkB, %s, linesize %d bytes.\n", + dcache_size >> 10, way_string[dcache_assoc - 1], + dcache_line_size); } /* @@ -526,15 +541,14 @@ void ld_mmu_sb1(void) * before subsequent instruction fetch. */ __asm__ __volatile__( + ".set push \n" " .set noat \n" " .set noreorder \n" - " .set mips3\n\t \n" - " la $1, 1f \n" - " mtc0 $1, $14 \n" + " .set mips3 \n" + " " STR(PTR_LA) " $1, 1f \n" + " " STR(MTC0) " $1, $14 \n" " eret \n" - "1: .set mips0\n\t \n" - " .set at \n" - " .set reorder" + "1: .set pop" : : : "memory"); diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 9654d74c5..9b0592dff 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -484,9 +484,9 @@ void __init ld_mmu_tx39(void) current_cpu_data.icache.waybit = 0; current_cpu_data.dcache.waybit = 0; - printk("Primary instruction cache %ldkb, linesize %d bytes\n", + printk("Primary instruction cache %ldkB, linesize %d bytes\n", icache_size >> 10, current_cpu_data.icache.linesz); - printk("Primary data cache %ldkb, linesize %d bytes\n", + printk("Primary data cache %ldkB, linesize %d bytes\n", dcache_size >> 10, current_cpu_data.dcache.linesz); build_clear_page(); diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 820c3af08..ec8077c74 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index b95b91b14..adf352273 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -96,6 +96,15 @@ static int remap_area_pages(unsigned long address, phys_t phys_addr, return error; } +/* + * Allow physical addresses to be fixed up to help 36 bit peripherals. + */ +phys_t __attribute__ ((weak)) +fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + return phys_addr; +} + /* * Generic mapping function (not visible outside): */ @@ -110,7 +119,7 @@ static int remap_area_pages(unsigned long address, phys_t phys_addr, * caller shouldn't need to know that small detail. */ -#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL)) +#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL)) void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) { @@ -119,6 +128,8 @@ void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) phys_t last_addr; void * addr; + phys_addr = fixup_bigphys_addr(phys_addr, size); + /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; if (!size || last_addr < phys_addr) @@ -171,15 +182,14 @@ void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) #define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1) -void __iounmap(void *addr) +void __iounmap(volatile void __iomem *addr) { struct vm_struct *p; if (IS_KSEG1(addr)) return; - vfree((void *) (PAGE_MASK & (unsigned long) addr)); - p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr)); + p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr)); if (!p) { printk(KERN_ERR "iounmap: bad address %p\n", addr); return; diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index 467fdfe21..a26bf8202 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c @@ -224,7 +224,7 @@ static inline void build_cdex_p(void) emit_instruction(mi); } -static void __build_store_reg(int reg) +static void __init __build_store_reg(int reg) { union mips_instruction mi; unsigned int width; @@ -356,7 +356,7 @@ void __init build_clear_page(void) case CPU_R10000: case CPU_R12000: pref_src_mode = Pref_LoadStreamed; - pref_dst_mode = Pref_StoreRetained; + pref_dst_mode = Pref_StoreStreamed; break; default: diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 7eb953305..e4b961cbc 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -52,29 +52,8 @@ void pmd_init(unsigned long addr, unsigned long pagetable) void __init pagetable_init(void) { - pmd_t *pmd; - pte_t *pte; - int i; - /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); - - memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER); - memset((void *)kpmdtbl, 0, PAGE_SIZE); - set_pgd(swapper_pg_dir, __pgd((unsigned long)kpmdtbl)); - - /* - * The 64-bit kernel uses a flat pagetable for it's kernel mappings ... - */ - pmd = kpmdtbl; - pte = kptbl; - i = 0; - while (i < (1 << PGD_ORDER)) { - pmd_val(*pmd) = (unsigned long)pte; - pte += PTRS_PER_PTE; - pmd++; - i++; - } } diff --git a/arch/mips/mm/tlb-andes.c b/arch/mips/mm/tlb-andes.c index e1090c564..94ab754f6 100644 --- a/arch/mips/mm/tlb-andes.c +++ b/arch/mips/mm/tlb-andes.c @@ -17,10 +17,7 @@ #include #include -extern void except_vec0_generic(void); -extern void except_vec0_r4000(void); -extern void except_vec1_generic(void); -extern void except_vec1_r10k(void); +extern void build_tlb_refill_handler(void); #define NTLB_ENTRIES 64 #define NTLB_ENTRIES_HALF 32 @@ -88,7 +85,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - write_c0_entryhi(KSEG0); + write_c0_entryhi(CKSEG0); if(idx < 0) continue; tlb_write_indexed(); @@ -126,7 +123,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT+1))); if (idx < 0) continue; tlb_write_indexed(); @@ -154,7 +151,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - write_c0_entryhi(KSEG0); + write_c0_entryhi(CKSEG0); if (idx < 0) goto finish; tlb_write_indexed(); @@ -184,7 +181,7 @@ void local_flush_tlb_one(unsigned long page) write_c0_entrylo1(0); if (idx >= 0) { /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + write_c0_entryhi(CKSEG0+(idx<<(PAGE_SHIFT+1))); tlb_write_indexed(); } write_c0_entryhi(oldpid); @@ -257,14 +254,5 @@ void __init tlb_init(void) /* Did I tell you that ARC SUCKS? */ -#ifdef CONFIG_MIPS32 - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x100); -#endif -#ifdef CONFIG_MIPS64 - memcpy((void *)(CKSEG0 + 0x000), &except_vec0_generic, 0x80); - memcpy((void *)(CKSEG0 + 0x080), except_vec1_r10k, 0x80); - flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); -#endif + build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index 89a0ee3bd..7948e9a5e 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -26,7 +26,7 @@ #undef DEBUG_TLB -extern char except_vec0_r2300; +extern void build_tlb_refill_handler(void); /* CP0 hazard avoidance. */ #define BARRIER \ @@ -284,6 +284,6 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, void __init tlb_init(void) { local_flush_tlb_all(); - memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x80); + + build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 91fee0688..59d38bc05 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -19,12 +19,7 @@ #include #include -extern void except_vec0_generic(void); -extern void except_vec0_nevada(void); -extern void except_vec0_r4000(void); -extern void except_vec0_r4600(void); -extern void except_vec1_generic(void); -extern void except_vec1_r4k(void); +extern void build_tlb_refill_handler(void); /* CP0 hazard avoidance. */ #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ @@ -255,8 +250,14 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) idx = read_c0_index(); ptep = pte_offset_map(pmdp, address); - write_c0_entrylo0(pte_val(*ptep++) >> 6); - write_c0_entrylo1(pte_val(*ptep) >> 6); + #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) + write_c0_entrylo0(ptep->pte_high); + ptep++; + write_c0_entrylo1(ptep->pte_high); +#else + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); +#endif write_c0_entryhi(address | pid); mtc0_tlbw_hazard(); if (idx < 0) @@ -414,19 +415,5 @@ void __init tlb_init(void) temp_tlb_entry = current_cpu_data.tlbsize - 1; local_flush_tlb_all(); -#ifdef CONFIG_MIPS32 - if (current_cpu_data.cputype == CPU_NEVADA) - memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); - else if (current_cpu_data.cputype == CPU_R4600) - memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); - else - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x100); -#endif -#ifdef CONFIG_MIPS64 - memcpy((void *)(CKSEG0 + 0x00), &except_vec0_generic, 0x80); - memcpy((void *)(CKSEG0 + 0x80), except_vec1_r4k, 0x80); - flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); -#endif + build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index daac80ea3..1bfb09198 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -19,8 +19,7 @@ #include #include -extern void except_vec0_generic(void); -extern void except_vec1_r8k(void); +extern void build_tlb_refill_handler(void); #define TFP_TLB_SIZE 384 #define TFP_TLB_SET_SHIFT 7 @@ -247,7 +246,5 @@ void __init tlb_init(void) local_flush_tlb_all(); - memcpy((void *)(CKSEG0 + 0x00), &except_vec0_generic, 0x80); - memcpy((void *)(CKSEG0 + 0x80), except_vec1_r8k, 0x80); - flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); + build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c index 33c177e65..fb315e284 100644 --- a/arch/mips/mm/tlb-sb1.c +++ b/arch/mips/mm/tlb-sb1.c @@ -23,14 +23,7 @@ #include #include -#ifdef CONFIG_MIPS32 -extern void except_vec0_sb1(void); -extern void except_vec1_generic(void); -#endif -#ifdef CONFIG_MIPS64 -extern void except_vec0_generic(void); -extern void except_vec1_sb1(void); -#endif +extern void build_tlb_refill_handler(void); #define UNIQUE_ENTRYHI(idx) (KSEG0 + ((idx) << (PAGE_SHIFT + 1))) @@ -286,10 +279,17 @@ void local_flush_tlb_one(unsigned long page) these entries, we just bump the asid. */ void local_flush_tlb_mm(struct mm_struct *mm) { - int cpu = smp_processor_id(); + int cpu; + + preempt_disable(); + + cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { drop_mmu_context(mm, cpu); } + + preempt_enable(); } /* Stolen from mips32 routines */ @@ -373,14 +373,5 @@ void tlb_init(void) */ sb1_sanitize_tlb(); -#ifdef CONFIG_MIPS32 - memcpy((void *)KSEG0, &except_vec0_sb1, 0x80); - memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x100); -#endif -#ifdef CONFIG_MIPS64 - memcpy((void *)CKSEG0, &except_vec0_generic, 0x80); - memcpy((void *)(CKSEG0 + 0x80), &except_vec1_sb1, 0x80); - flush_icache_range(CKSEG0, CKSEG0 + 0x100); -#endif + build_tlb_refill_handler(); } diff --git a/arch/mips/mm/tlbex32-r3k.S b/arch/mips/mm/tlbex32-r3k.S index cc4a4642e..04c11f120 100644 --- a/arch/mips/mm/tlbex32-r3k.S +++ b/arch/mips/mm/tlbex32-r3k.S @@ -24,36 +24,6 @@ #define TLB_OPTIMIZE /* If you are paranoid, disable this. */ - .text - .set mips1 - .set noreorder - - __INIT - - /* TLB refill, R[23]00 version */ - LEAF(except_vec0_r2300) - .set noat - .set mips1 - mfc0 k0, CP0_BADVADDR - lw k1, pgd_current # get pgd pointer - srl k0, k0, 22 - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - and k0, k0, 0xffc - addu k1, k1, k0 - lw k0, (k1) - nop - mtc0 k0, CP0_ENTRYLO0 - mfc0 k1, CP0_EPC - tlbwr - jr k1 - rfe - END(except_vec0_r2300) - - __FINIT - /* ABUSE of CPP macros 101. */ /* After this macro runs, the pte faulted on is diff --git a/arch/mips/mm/tlbex32-r4k.S b/arch/mips/mm/tlbex32-r4k.S index 49742718d..ab50b77f9 100644 --- a/arch/mips/mm/tlbex32-r4k.S +++ b/arch/mips/mm/tlbex32-r4k.S @@ -139,271 +139,6 @@ _PAGE_VALID | _PAGE_DIRTY); \ PTE_S pte, (ptr); - __INIT - -#ifdef CONFIG_64BIT_PHYS_ADDR -#define GET_PTE_OFF(reg) -#elif CONFIG_CPU_VR41XX -#define GET_PTE_OFF(reg) srl reg, reg, 3 -#else -#define GET_PTE_OFF(reg) srl reg, reg, 1 -#endif - -/* - * These handlers much be written in a relocatable manner - * because based upon the cpu type an arbitrary one of the - * following pieces of code will be copied to the KSEG0 - * vector location. - */ - /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ - .set noreorder - .set noat - LEAF(except_vec0_r4000) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, _PGDIR_SHIFT # get pgd only bits - - sll k0, k0, 2 - addu k1, k1, k0 # add in pgd offset - mfc0 k0, CP0_CONTEXT # get context reg - lw k1, (k1) - GET_PTE_OFF(k0) # get pte offset - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 # add in offset - PTE_L k0, 0(k1) # get even pte - PTE_L k1, PTE_SIZE(k1) # get odd pte - PTE_SRL k0, k0, 6 # convert to entrylo0 - P_MTC0 k0, CP0_ENTRYLO0 # load it - PTE_SRL k1, k1, 6 # convert to entrylo1 - P_MTC0 k1, CP0_ENTRYLO1 # load it - mtc0_tlbw_hazard - tlbwr # write random tlb entry - tlbw_eret_hazard - eret # return from trap - END(except_vec0_r4000) - - /* TLB refill, EXL == 0, R4600 version */ - LEAF(except_vec0_r4600) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR - srl k0, k0, _PGDIR_SHIFT - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - GET_PTE_OFF(k0) # get pte offset - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 - PTE_L k0, 0(k1) - PTE_L k1, PTE_SIZE(k1) - PTE_SRL k0, k0, 6 - P_MTC0 k0, CP0_ENTRYLO0 - PTE_SRL k1, k1, 6 - P_MTC0 k1, CP0_ENTRYLO1 - nop - tlbwr - nop - eret - END(except_vec0_r4600) - - /* TLB refill, EXL == 0, R52x0 "Nevada" version */ - /* - * This version has a bug workaround for the Nevada. It seems - * as if under certain circumstances the move from cp0_context - * might produce a bogus result when the mfc0 instruction and - * it's consumer are in a different cacheline or a load instruction, - * probably any memory reference, is between them. This is - * potencially slower than the R4000 version, so we use this - * special version. - */ - .set noreorder - .set noat - LEAF(except_vec0_nevada) - .set mips3 - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, _PGDIR_SHIFT # get pgd only bits - lw k1, pgd_current # get pgd pointer - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 # add in pgd offset - lw k1, (k1) - mfc0 k0, CP0_CONTEXT # get context reg - GET_PTE_OFF(k0) # get pte offset - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 # add in offset - PTE_L k0, 0(k1) # get even pte - PTE_L k1, PTE_SIZE(k1) # get odd pte - PTE_SRL k0, k0, 6 # convert to entrylo0 - P_MTC0 k0, CP0_ENTRYLO0 # load it - PTE_SRL k1, k1, 6 # convert to entrylo1 - P_MTC0 k1, CP0_ENTRYLO1 # load it - nop # QED specified nops - nop - tlbwr # write random tlb entry - nop # traditional nop - eret # return from trap - END(except_vec0_nevada) - - /* TLB refill, EXL == 0, SB1 with M3 errata handling version */ - LEAF(except_vec0_sb1) -#if BCM1250_M3_WAR - mfc0 k0, CP0_BADVADDR - mfc0 k1, CP0_ENTRYHI - xor k0, k1 - srl k0, k0, PAGE_SHIFT+1 - bnez k0, 1f -#endif - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, _PGDIR_SHIFT # get pgd only bits - sll k0, k0, 2 - addu k1, k1, k0 # add in pgd offset - mfc0 k0, CP0_CONTEXT # get context reg - lw k1, (k1) - GET_PTE_OFF(k0) # get pte offset - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 # add in offset - PTE_L k0, 0(k1) # get even pte - PTE_L k1, PTE_SIZE(k1) # get odd pte - PTE_SRL k0, k0, 6 # convert to entrylo0 - P_MTC0 k0, CP0_ENTRYLO0 # load it - PTE_SRL k1, k1, 6 # convert to entrylo1 - P_MTC0 k1, CP0_ENTRYLO1 # load it - tlbwr # write random tlb entry -1: eret # return from trap - END(except_vec0_sb1) - - /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ - LEAF(except_vec0_r45k_bvahwbug) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR - srl k0, k0, _PGDIR_SHIFT - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) -#ifndef CONFIG_64BIT_PHYS_ADDR - srl k0, k0, 1 -#endif - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 - PTE_L k0, 0(k1) - PTE_L k1, PTE_SIZE(k1) - nop /* XXX */ - tlbp - PTE_SRL k0, k0, 6 - P_MTC0 k0, CP0_ENTRYLO0 - PTE_SRL k1, k1, 6 - mfc0 k0, CP0_INDEX - P_MTC0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r45k_bvahwbug) - -#ifdef CONFIG_SMP - /* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */ - LEAF(except_vec0_r4k_mphwbug) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR - srl k0, k0, _PGDIR_SHIFT - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) -#ifndef CONFIG_64BIT_PHYS_ADDR - srl k0, k0, 1 -#endif - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 - PTE_L k0, 0(k1) - PTE_L k1, PTE_SIZE(k1) - nop /* XXX */ - tlbp - PTE_SRL k0, k0, 6 - P_MTC0 k0, CP0_ENTRYLO0 - PTE_SRL k1, k1, 6 - mfc0 k0, CP0_INDEX - P_MTC0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_mphwbug) -#endif - - /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */ - LEAF(except_vec0_r4k_250MHZhwbug) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR - srl k0, k0, _PGDIR_SHIFT - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) -#ifndef CONFIG_64BIT_PHYS_ADDR - srl k0, k0, 1 -#endif - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 - PTE_L k0, 0(k1) - PTE_L k1, PTE_SIZE(k1) - PTE_SRL k0, k0, 6 - P_MTC0 zero, CP0_ENTRYLO0 - P_MTC0 k0, CP0_ENTRYLO0 - PTE_SRL k1, k1, 6 - P_MTC0 zero, CP0_ENTRYLO1 - P_MTC0 k1, CP0_ENTRYLO1 - b 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_250MHZhwbug) - -#ifdef CONFIG_SMP - /* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */ - LEAF(except_vec0_r4k_MP250MHZhwbug) - .set mips3 - GET_PGD(k0, k1) # get pgd pointer - mfc0 k0, CP0_BADVADDR - srl k0, k0, _PGDIR_SHIFT - sll k0, k0, 2 # log2(sizeof(pgd_t) - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) -#ifndef CONFIG_64BIT_PHYS_ADDR - srl k0, k0, 1 -#endif - and k0, k0, PTEP_INDX_MSK - addu k1, k1, k0 - PTE_L k0, 0(k1) - PTE_L k1, PTE_SIZE(k1) - nop /* XXX */ - tlbp - PTE_SRL k0, k0, 6 - P_MTC0 zero, CP0_ENTRYLO0 - P_MTC0 k0, CP0_ENTRYLO0 - mfc0 k0, CP0_INDEX - PTE_SRL k1, k1, 6 - P_MTC0 zero, CP0_ENTRYLO1 - P_MTC0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_MP250MHZhwbug) -#endif - - __FINIT .set noreorder @@ -460,6 +195,7 @@ invalid_tlbl: PTE_RELOAD(k1, k0) mtc0_tlbw_hazard tlbwi + nop tlbw_eret_hazard .set mips3 eret @@ -484,6 +220,7 @@ nopage_tlbl: PTE_RELOAD(k1, k0) mtc0_tlbw_hazard tlbwi + nop tlbw_eret_hazard .set mips3 eret @@ -513,6 +250,7 @@ nopage_tlbs: PTE_RELOAD(k1, k0) mtc0_tlbw_hazard tlbwi + nop tlbw_eret_hazard .set mips3 eret diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c index cc25cbcb4..15588f91a 100644 --- a/arch/mips/momentum/jaguar_atx/irq.c +++ b/arch/mips/momentum/jaguar_atx/irq.c @@ -45,7 +45,7 @@ static struct irqaction cascade_mv64340 = { no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL }; -void __init init_IRQ(void) +void __init arch_init_irq(void) { /* * Clear all of the interrupts while we change the able around a bit. @@ -55,7 +55,6 @@ void __init init_IRQ(void) /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, jaguar_handle_int); - init_generic_irq(); mips_cpu_irq_init(0); rm7k_cpu_irq_init(8); diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c index df52d2adf..fa5982ac0 100644 --- a/arch/mips/momentum/jaguar_atx/prom.c +++ b/arch/mips/momentum/jaguar_atx/prom.c @@ -40,7 +40,7 @@ const char *get_system_type(void) return "Momentum Jaguar-ATX"; } -#ifdef CONFIG_MV64340_ETH +#ifdef CONFIG_MV643XX_ETH extern unsigned char prom_mac_addr_base[6]; static void burn_clocks(void) @@ -230,7 +230,7 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_JAGUAR_ATX; -#ifdef CONFIG_MV64340_ETH +#ifdef CONFIG_MV643XX_ETH /* get the base MAC address for on-board ethernet ports */ get_mac(prom_mac_addr_base); #endif diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index a849215b5..30462e715 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -2,7 +2,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Jaguar-ATX board dependent boot routines * - * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 1996, 1997, 2001, 2004 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c index 3ef3584cf..8720bccfd 100644 --- a/arch/mips/momentum/ocelot_c/dbg_io.c +++ b/arch/mips/momentum/ocelot_c/dbg_io.c @@ -1,6 +1,6 @@ #include -#if defined(CONFIG_KGDB) +#ifdef CONFIG_KGDB #include /* For the serial port location and base baud */ diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c index 13dd8bd74..1759d2bd5 100644 --- a/arch/mips/momentum/ocelot_c/irq.c +++ b/arch/mips/momentum/ocelot_c/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -61,7 +61,7 @@ static struct irqaction cascade_mv64340 = { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL }; -void __init init_IRQ(void) +void __init arch_init_irq(void) { /* * Clear all of the interrupts while we change the able around a bit. @@ -71,7 +71,6 @@ void __init init_IRQ(void) /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); - init_generic_irq(); mips_cpu_irq_init(0); /* set up the cascading interrupts */ @@ -82,10 +81,4 @@ void __init init_IRQ(void) mv64340_irq_init(16); uart_irq_init(); cpci_irq_init(); - -#ifdef CONFIG_KGDB - printk("start kgdb ...\n"); - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif } diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c index 762112965..49ac302d8 100644 --- a/arch/mips/momentum/ocelot_c/prom.c +++ b/arch/mips/momentum/ocelot_c/prom.c @@ -32,7 +32,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned long cpu_clock; -#ifdef CONFIG_MV64340_ETH +#ifdef CONFIG_MV643XX_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -45,7 +45,7 @@ const char *get_system_type(void) #endif } -#ifdef CONFIG_MV64340_ETH +#ifdef CONFIG_MV643XX_ETH static void burn_clocks(void) { int i; @@ -227,7 +227,7 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_C; -#ifdef CONFIG_MV64340_ETH +#ifdef CONFIG_MV643XX_ETH /* get the base MAC address for on-board ethernet ports */ get_mac(prom_mac_addr_base); #endif diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c index 3ef3584cf..8720bccfd 100644 --- a/arch/mips/momentum/ocelot_g/dbg_io.c +++ b/arch/mips/momentum/ocelot_g/dbg_io.c @@ -1,6 +1,6 @@ #include -#if defined(CONFIG_KGDB) +#ifdef CONFIG_KGDB #include /* For the serial port location and base baud */ diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c index 93708965b..70ccf395f 100644 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ b/arch/mips/momentum/ocelot_g/gt-irq.c @@ -134,6 +134,9 @@ static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs) /* handle the timer call */ do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif } if (irq_src) { @@ -156,7 +159,6 @@ static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs) */ void gt64240_time_init(void) { - extern irq_desc_t irq_desc[NR_IRQS]; static struct irqaction timer; /* Stop the timer -- we'll use timer #0 */ diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c index 7d838c132..e70ec0e11 100644 --- a/arch/mips/momentum/ocelot_g/irq.c +++ b/arch/mips/momentum/ocelot_g/irq.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ extern asmlinkage void ocelot_handle_int(void); extern void gt64240_irq_init(void); -void __init init_IRQ(void) +void __init arch_init_irq(void) { /* * Clear all of the interrupts while we change the able around a bit. @@ -63,15 +63,8 @@ void __init init_IRQ(void) /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); - init_generic_irq(); mips_cpu_irq_init(0); rm7k_cpu_irq_init(8); gt64240_irq_init(); - -#ifdef CONFIG_KGDB - printk("start kgdb ...\n"); - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif } diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 5ed03fa90..1ef37050c 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -24,8 +24,7 @@ obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o obj-$(CONFIG_DDB5074) += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o obj-$(CONFIG_DDB5476) += ops-ddb5476.o pci-ddb5476.o obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o -obj-$(CONFIG_HP_LASERJET) += pci-hplj.o -obj-$(CONFIG_LASAT) += pci-lasat.o fixup-lasat.o +obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o @@ -37,6 +36,7 @@ obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o +obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c index 4cbef3431..ebd7a4307 100644 --- a/arch/mips/pci/fixup-atlas.c +++ b/arch/mips/pci/fixup-atlas.c @@ -40,11 +40,13 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab[slot][pin]; } -void __init pcibios_fixup_irqs(void) +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) { + return 0; } -#if CONFIG_KGDB +#ifdef CONFIG_KGDB /* * The PCI scan may have moved the saa9730 I/O address, so reread * the address here. @@ -60,13 +62,7 @@ static void atlas_saa9730_base_fixup (struct pci_dev *pdev) printk ("saa9730_base = %x\n", saa9730_base); } -#endif - +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730, + atlas_saa9730_base_fixup); -struct pci_fixup pcibios_fixups[] __initdata = { -#ifdef CONFIG_KGDB - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730, - atlas_saa9730_base_fixup}, #endif - { 0 } -}; diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c index 7bbe12336..a02d2b8a6 100644 --- a/arch/mips/pci/fixup-au1000.c +++ b/arch/mips/pci/fixup-au1000.c @@ -100,9 +100,11 @@ static char irq_tab_alchemy[][5] __initdata = { int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { -return irq_tab_alchemy[slot][pin]; + return irq_tab_alchemy[slot][pin]; } -struct pci_fixup pcibios_fixups[] __initdata = { -{ 0 } -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c index 9a0d68ed6..f2fc82c1c 100644 --- a/arch/mips/pci/fixup-capcella.c +++ b/arch/mips/pci/fixup-capcella.c @@ -43,6 +43,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_capcella[slot][pin]; } -struct pci_fixup pcibios_fixups[] __initdata = { - { .pass = 0, }, -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index f72022a08..57e1ca211 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -41,6 +41,9 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, + qube_raq_via_bmIDE_fixup); + static void qube_raq_galileo_fixup(struct pci_dev *dev) { unsigned short galileo_id; @@ -73,13 +76,8 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev) } } -struct pci_fixup pcibios_fixups[] __initdata = { - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, - qube_raq_via_bmIDE_fixup}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, - qube_raq_galileo_fixup}, - 0 -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, + qube_raq_galileo_fixup); static char irq_tab_cobalt[] __initdata = { [COBALT_PCICONF_CPU] = 0, @@ -106,3 +104,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_cobalt[slot]; } + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c index 025285f9a..b345e528a 100644 --- a/arch/mips/pci/fixup-ddb5074.c +++ b/arch/mips/pci/fixup-ddb5074.c @@ -17,8 +17,5 @@ static void ddb5074_fixup(struct pci_dev *dev) pci_write_config_byte(dev, 0x7e, t8); } -struct pci_fixup pcibios_fixups[] __initdata = { - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, - ddb5074_fixup }, - {0} -}; +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, + ddb5074_fixup); diff --git a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c index 985441343..6abdc88ba 100644 --- a/arch/mips/pci/fixup-ddb5477.c +++ b/arch/mips/pci/fixup-ddb5477.c @@ -41,6 +41,11 @@ static void ddb5477_fixup(struct pci_dev *dev) pci_write_config_byte(dev, 0x41, old | 0xd0); } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, + ddb5477_fixup); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535, + ddb5477_fixup); + /* * Fixup baseboard AMD chip so that tx does not underflow. * bcr_18 |= 0x0800 @@ -69,12 +74,5 @@ static void ddb5477_amd_lance_fixup(struct pci_dev *dev) outw(temp, ioaddr + PCNET32_WIO_BDP); } -struct pci_fixup pcibios_fixups[] __initdata = { - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, - ddb5477_fixup }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535, - ddb5477_fixup }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, - ddb5477_amd_lance_fixup }, - {0} -}; +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, + ddb5477_amd_lance_fixup); diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c index 413bb5b56..e2bc977b6 100644 --- a/arch/mips/pci/fixup-ev96100.c +++ b/arch/mips/pci/fixup-ev96100.c @@ -40,3 +40,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_tab_ev96100[slot][pin]; } + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c index 90c67c35f..3e66b0aa6 100644 --- a/arch/mips/pci/fixup-ip32.c +++ b/arch/mips/pci/fixup-ip32.c @@ -1,7 +1,6 @@ #include #include #include -#include #include /* * O2 has up to 5 PCI devices connected into the MACE bridge. The device @@ -45,6 +44,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_mace[slot][pin]; } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ite8172g.c b/arch/mips/pci/fixup-ite8172g.c index 7b032efba..2290ea422 100644 --- a/arch/mips/pci/fixup-ite8172g.c +++ b/arch/mips/pci/fixup-ite8172g.c @@ -72,3 +72,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_ite8172g[slot][pin]; } + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ivr.c b/arch/mips/pci/fixup-ivr.c index a796ef14f..0c7c16464 100644 --- a/arch/mips/pci/fixup-ivr.c +++ b/arch/mips/pci/fixup-ivr.c @@ -67,3 +67,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_ivr[slot][pin]; } + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c index fa78b9b1f..6c5e1d471 100644 --- a/arch/mips/pci/fixup-jaguar.c +++ b/arch/mips/pci/fixup-jaguar.c @@ -8,14 +8,13 @@ * Marvell wants an NDA for their docs so this was written without * documentation. You've been warned. * - * Copyright (C) 2004 Ralf Baechle + * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org) */ #include #include #include #include -#include /* * WARNING: Example of how _NOT_ to do it. @@ -37,6 +36,8 @@ return 0; panic("Whooops in pcibios_map_irq"); } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c index 682edfaf0..f8696081c 100644 --- a/arch/mips/pci/fixup-jmr3927.c +++ b/arch/mips/pci/fixup-jmr3927.c @@ -88,6 +88,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c index 3345e1952..b9296d994 100644 --- a/arch/mips/pci/fixup-malta.c +++ b/arch/mips/pci/fixup-malta.c @@ -43,11 +43,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return pci_irq[virq]; } -void __init pcibios_fixup_irqs(void) +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) { + return 0; } - static void __init malta_piix_func0_fixup(struct pci_dev *pdev) { unsigned char reg_val; @@ -79,6 +80,8 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev) } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, + malta_piix_func0_fixup); static void __init malta_piix_func1_fixup(struct pci_dev *pdev) { @@ -96,10 +99,5 @@ static void __init malta_piix_func1_fixup(struct pci_dev *pdev) } } -struct pci_fixup pcibios_fixups[] __initdata = { - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, - malta_piix_func0_fixup}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, - malta_piix_func1_fixup}, - { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, + malta_piix_func1_fixup); diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c index 1320c42af..09d6b3647 100644 --- a/arch/mips/pci/fixup-mpc30x.c +++ b/arch/mips/pci/fixup-mpc30x.c @@ -43,6 +43,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_mpc30x[slot]; } -struct pci_fixup pcibios_fixups[] __initdata = { - { .pass = 0, }, -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c index 0cc86eceb..d45494807 100644 --- a/arch/mips/pci/fixup-ocelot-c.c +++ b/arch/mips/pci/fixup-ocelot-c.c @@ -34,6 +34,8 @@ return 0; panic("Whooops in pcibios_map_irq"); } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c index 9a2cc8505..d7a652e32 100644 --- a/arch/mips/pci/fixup-ocelot-g.c +++ b/arch/mips/pci/fixup-ocelot-g.c @@ -30,6 +30,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return -1; } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c index 2182719c0..de4e443da 100644 --- a/arch/mips/pci/fixup-rbtx4927.c +++ b/arch/mips/pci/fixup-rbtx4927.c @@ -9,6 +9,9 @@ * * Copyright (C) 2000-2001 Toshiba Corporation * + * Copyright (C) 2004 MontaVista Software Inc. + * Author: Manish Lachwani (mlachwani@mvista.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 @@ -116,108 +119,22 @@ int pci_get_irq(struct pci_dev *dev, int pin) return irq; } - -#ifdef TX4927_SUPPORT_PCI_66 -extern int tx4927_pci66; -extern void tx4927_pci66_setup(void); -#endif -extern void tx4927_pci_setup(void); - -#ifdef TX4927_SUPPORT_PCI_66 -int tx4927_pci66_check(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev; - unsigned short stat; - int cap66 = 1; - - if (tx4927_pci66 < 0) - return 0; - - /* check 66MHz capability */ - pci_for_each_dev(dev) { - if (cap66) { - pci_read_config_word(dev, PCI_STATUS, &stat); - if (!(stat & PCI_STATUS_66MHZ)) { - printk(KERN_INFO - "PCI: %02x:%02x not 66MHz capable.\n", - dev->bus->number, dev->devfn); - cap66 = 0; - } - } - } - return cap66; -} -#endif - -void __init pcibios_fixup_irqs(void) -{ - unsigned char pin; unsigned char irq; - struct pci_dev *dev; - unsigned int id; - -#ifdef TX4927_SUPPORT_PCI_66 - if (tx4927_pci66_check()) { - tx4927_pci66_setup(); - tx4927_pci_setup(); /* Reinitialize PCIC */ - } -#endif - pci_for_each_dev(dev) { - DBG("FIXUP:\n"); - DBG(" devfn=0x%02x (0x%02x:0x%02x)\n", - dev->devfn, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); + printk("PCI Setup for pin %d \n", pin); - pci_read_config_dword(dev, PCI_VENDOR_ID, &id); - DBG(" id=0x%08x\n", id); + if (dev->device == 0x9130) /* IDE */ + irq = 14; + else + irq = pci_get_irq(dev, pin); - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - DBG(" line=0x%02x/%d\n", irq, irq); - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - DBG(" pin=%d\n", pin); - -#ifdef DEBUG - { - unsigned int tmp; - pci_read_config_dword(dev, 0x10, &tmp); - DBG(" bar0:0x10=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x14, &tmp); - DBG(" bar1:0x14=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x1c, &tmp); - DBG(" bar2:0x1c=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x20, &tmp); - DBG(" bar3:0x20=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x24, &tmp); - DBG(" bar4:0x24=0x%08x\n", tmp); - } -#endif - - irq = 0; - - if (id == 0x91301055) { /* ide */ - irq = 14; - } - - if (pin == 0) { - DBG(" auto irq (now=%d) -- skipping pin=0\n", irq); - } else if (irq) { - DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq); - } else { - DBG(" auto irq (was=%d)\n", irq); - irq = pci_get_irq(dev, pin); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - irq); - dev->irq = irq; - DBG(" auto irq (now=%d)\n", irq); - } - - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - printk(KERN_INFO - "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n", - dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), irq); + return irq; +} - } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; } diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c index 99067c76b..c8ef01a01 100644 --- a/arch/mips/pci/fixup-sni.c +++ b/arch/mips/pci/fixup-sni.c @@ -5,14 +5,13 @@ * * SNI specific PCI support for RM200/RM300. * - * Copyright (C) 1997 - 2000, 2003 Ralf Baechle + * Copyright (C) 1997 - 2000, 2003, 04 Ralf Baechle (ralf@linux-mips.org) */ #include #include #include #include -#include #include /* @@ -83,6 +82,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_tab_rm200[slot][pin]; } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index ca4d99fbe..850a900f0 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -59,6 +59,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } -struct pci_fixup pcibios_fixups[] __initdata = { - { .pass = 0, }, -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c index 50e639e04..61513d5d9 100644 --- a/arch/mips/pci/fixup-tb0226.c +++ b/arch/mips/pci/fixup-tb0226.c @@ -78,6 +78,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } -struct pci_fixup pcibios_fixups[] __initdata = { - { .pass = 0, }, -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c index 92e40b091..81d77a587 100644 --- a/arch/mips/pci/fixup-yosemite.c +++ b/arch/mips/pci/fixup-yosemite.c @@ -34,6 +34,8 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return 3; /* Everything goes to one irq bit */ } -struct pci_fixup pcibios_fixups[] = { - {0} -}; +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c index b921cc6b3..c1c91ca0f 100644 --- a/arch/mips/pci/ops-au1000.c +++ b/arch/mips/pci/ops-au1000.c @@ -288,10 +288,18 @@ static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) { switch (size) { - case 1: - return read_config_byte(bus, devfn, where, (u8 *) val); - case 2: - return read_config_word(bus, devfn, where, (u16 *) val); + case 1: { + u8 _val; + int rc = read_config_byte(bus, devfn, where, &_val); + *val = _val; + return rc; + } + case 2: { + u16 _val; + int rc = read_config_word(bus, devfn, where, &_val); + *val = _val; + return rc; + } default: return read_config_dword(bus, devfn, where, val); } diff --git a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c index 2f40a8c18..b7a8b9a6f 100644 --- a/arch/mips/pci/ops-it8172.c +++ b/arch/mips/pci/ops-it8172.c @@ -7,6 +7,8 @@ * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -32,7 +34,6 @@ #include #include -#include #include #include diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c index 1ac7880dd..819309b8e 100644 --- a/arch/mips/pci/ops-titan.c +++ b/arch/mips/pci/ops-titan.c @@ -58,15 +58,15 @@ static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg, switch (size) { case 1: - TITAN_READ_8(data_reg + (reg & 0x3), val); + *val = TITAN_READ_8(data_reg + (~reg & 0x3)); break; case 2: - TITAN_READ_16(data_reg + (reg & 0x2), val); + *val = TITAN_READ_16(data_reg + (~reg & 0x2)); break; case 4: - TITAN_READ(data_reg, val); + *val = TITAN_READ(data_reg); break; } @@ -98,11 +98,11 @@ static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg, /* write the data */ switch (size) { case 1: - TITAN_WRITE_8(data_reg + (reg & 0x3), val); + TITAN_WRITE_8(data_reg + (~reg & 0x3), val); break; case 2: - TITAN_WRITE_16(data_reg + (reg & 0x2), val); + TITAN_WRITE_16(data_reg + (~reg & 0x2), val); break; case 4: @@ -120,16 +120,3 @@ struct pci_ops titan_pci_ops = { titan_read_config, titan_write_config, }; - -void __init pcibios_init(void) -{ - /* - * XXX These values below need to change - */ - ioport_resource.start = 0xe0000000; - ioport_resource.end = 0xe0000000 + 0x20000000 - 1; - iomem_resource.start = 0xc0000000; - iomem_resource.end = 0xc0000000 + 0x20000000 - 1; - - pci_scan_bus(0, &titan_pci_ops, NULL); -} diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 136c449f8..0e0daadc3 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c @@ -4,6 +4,7 @@ * ahennessy@mvista.com * * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c * @@ -38,7 +39,6 @@ #include #include -#include #include #include diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index 9044ff976..43863ab08 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -4,6 +4,7 @@ * ahennessy@mvista.com * * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c * @@ -12,6 +13,9 @@ * Much of the code is derived from the original DDB5074 port by * Geert Uytterhoeven * + * Copyright 2004 MontaVista Software Inc. + * Author: Manish Lachwani (mlachwani@mvista.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 @@ -38,39 +42,26 @@ #include #include -#include #include #include /* initialize in setup */ struct resource pci_io_resource = { - "pci IO space", - (PCIBIOS_MIN_IO), - ((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1, - IORESOURCE_IO + .name = "TX4927 PCI IO SPACE", + .start = 0x1000, + .end = (0x1000 + (TX4927_PCIIO_SIZE)) - 1, + .flags = IORESOURCE_IO }; /* initialize in setup */ struct resource pci_mem_resource = { - "pci memory space", - TX4927_PCIMEM, - TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, - IORESOURCE_MEM -}; - -extern struct pci_ops tx4927_pci_ops; - -/* - * h/w only supports devices 0x00 to 0x14 - */ -struct pci_controller tx4927_controller = { - .pci_ops = &tx4927_pci_ops, - .io_resource = &pci_io_resource, - .mem_resource = &pci_mem_resource, + .name = "TX4927 PCI MEM SPACE", + .start = TX4927_PCIMEM, + .end = TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, + .flags = IORESOURCE_MEM }; -static int mkaddr(unsigned char bus, unsigned char dev_fn, - unsigned char where, int *flagsp) +static int mkaddr(int bus, int dev_fn, int where, int *flagsp) { if (bus > 0) { /* Type 1 configuration */ @@ -107,107 +98,49 @@ static int check_abort(int flags) return code; } -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int tx4927_pcibios_read_config_byte(struct pci_dev *dev, - int where, unsigned char *val) +static int tx4927_pcibios_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 * val) { - int flags, retval; - unsigned char bus, func_num; + int flags, retval, dev, busno, func; - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); + busno = bus->number; + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; + if (size == 2) { + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *val = - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 3)); -#else - *val = - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)); -#endif - retval = check_abort(flags); - if (retval == PCIBIOS_DEVICE_NOT_FOUND) - *val = 0xff; - return retval; -} - -static int tx4927_pcibios_read_config_word(struct pci_dev *dev, - int where, unsigned short *val) -{ - int flags, retval; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); + if (size == 4) { + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + } /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); + if (bus->parent != NULL) { + busno = bus->number; } else { - bus = 0; + busno = 0; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) + if (mkaddr(busno, devfn, where, &flags)) return -1; -#ifdef __BIG_ENDIAN - *val = - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 2)); -#else - *val = - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)); -#endif - retval = check_abort(flags); - if (retval == PCIBIOS_DEVICE_NOT_FOUND) - *val = 0xffff; - return retval; -} - -static int tx4927_pcibios_read_config_dword(struct pci_dev *dev, - int where, unsigned int *val) -{ - int flags, retval; - unsigned char bus, func_num; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; + switch (size) { + case 1: + *val = *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); + break; + case 2: + *val = *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); + break; + case 4: + *val = tx4927_pcicptr->g2pcfgdata; + break; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *val = tx4927_pcicptr->g2pcfgdata; retval = check_abort(flags); if (retval == PCIBIOS_DEVICE_NOT_FOUND) *val = 0xffffffff; @@ -215,92 +148,62 @@ static int tx4927_pcibios_read_config_dword(struct pci_dev *dev, return retval; } -static int tx4927_pcibios_write_config_byte(struct pci_dev *dev, - int where, unsigned char val) +static int tx4927_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) { - int flags; - unsigned char bus, func_num; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; + int flags, dev, busno, func; + busno = bus->number; + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + if (size == 1) { + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 3)) = val; -#else - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)) = val; -#endif - return check_abort(flags); -} - -static int tx4927_pcibios_write_config_word(struct pci_dev *dev, - int where, unsigned short val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; + if (size == 4) { + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + } /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); + if (bus->parent != NULL) { + busno = bus->number; } else { - bus = 0; + busno = 0; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) + if (mkaddr(busno, devfn, where, &flags)) return -1; -#ifdef __BIG_ENDIAN - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 2)) = val; -#else - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)) = val; -#endif - return check_abort(flags); -} - -static int tx4927_pcibios_write_config_dword(struct pci_dev *dev, - int where, unsigned int val) -{ - int flags; - unsigned char bus, func_num; - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; + switch (size) { + case 1: + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; + break; + + case 2: + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; + break; + case 4: + tx4927_pcicptr->g2pcfgdata = val; + break; } - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - tx4927_pcicptr->g2pcfgdata = val; return check_abort(flags); } struct pci_ops tx4927_pci_ops = { - tx4927_pcibios_read_config_byte, - tx4927_pcibios_read_config_word, - tx4927_pcibios_read_config_dword, - tx4927_pcibios_write_config_byte, - tx4927_pcibios_write_config_word, - tx4927_pcibios_write_config_dword + tx4927_pcibios_read_config, + tx4927_pcibios_write_config +}; + +/* + * h/w only supports devices 0x00 to 0x14 + */ +struct pci_controller tx4927_controller = { + .pci_ops = &tx4927_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, }; diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c index 5bc21b22e..73f9ceeb2 100644 --- a/arch/mips/pci/pci-ddb5074.c +++ b/arch/mips/pci/pci-ddb5074.c @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -54,6 +53,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_map[slot]; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + void __init ddb_pci_reset_bus(void) { u32 temp; diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c index 945e59bce..90dd49509 100644 --- a/arch/mips/pci/pci-ddb5476.c +++ b/arch/mips/pci/pci-ddb5476.c @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -68,6 +67,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq_map[slot]; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + void __init ddb_pci_reset_bus(void) { u32 temp; diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c index fd94115e7..4ddd53eaf 100644 --- a/arch/mips/pci/pci-ddb5477.c +++ b/arch/mips/pci/pci-ddb5477.c @@ -4,6 +4,8 @@ * Copyright (C) 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -15,7 +17,6 @@ #include #include -#include #include #include @@ -175,6 +176,12 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + void ddb_pci_reset_bus(void) { u32 temp; diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c index 8f2becbd8..f9457ea00 100644 --- a/arch/mips/pci/pci-ev96100.c +++ b/arch/mips/pci/pci-ev96100.c @@ -6,6 +6,8 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -31,8 +33,6 @@ #include #include -#include - static struct resource pci_io_resource = { .name = "io pci IO space", .start = 0x10000000, diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 3c4183d45..068e0e508 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include @@ -12,11 +12,12 @@ #include #include #include -#include #include #include #include +extern unsigned int allocate_irqno(void); + /* * Max #PCI busses we can handle; ie, max #PCI bridges. */ @@ -81,7 +82,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, else res = get_dbe(*value, (u32 *) addr); - return PCIBIOS_SUCCESSFUL; + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; oh_my_gawd: @@ -110,6 +111,79 @@ oh_my_gawd: return PCIBIOS_SUCCESSFUL; } +static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int busno = bus->number; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + if (bus->number > 0) + return pci_conf1_read_config(bus, devfn, where, size, value); + + return pci_conf0_read_config(bus, devfn, where, size, value); +} + static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { @@ -176,16 +250,95 @@ oh_my_gawd: return PCIBIOS_SUCCESSFUL; } +static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + int busno = bus->number; + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (bus->number > 0) + return pci_conf1_write_config(bus, devfn, where, size, value); + + return pci_conf0_write_config(bus, devfn, where, size, value); +} + static struct pci_ops bridge_pci_ops = { - .read = pci_conf0_read_config, - .write = pci_conf0_write_config, + .read = pci_read_config, + .write = pci_write_config, }; int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) { + unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; - bridge_t *bridge; static int num_bridges = 0; + bridge_t *bridge; + int slot; printk("a bridge\n"); @@ -193,21 +346,23 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) if (!num_bridges) ioport_resource.end = ~0UL; - bc = &bridges[num_bridges++]; + bc = &bridges[num_bridges]; bc->pc.pci_ops = &bridge_pci_ops; bc->pc.mem_resource = &bc->mem; bc->pc.io_resource = &bc->io; + bc->pc.index = num_bridges; + bc->mem.name = "Bridge PCI MEM"; - bc->pc.mem_offset = 0; + bc->pc.mem_offset = offset; bc->mem.start = 0; bc->mem.end = ~0UL; bc->mem.flags = IORESOURCE_MEM; bc->io.name = "Bridge IO MEM"; + bc->pc.io_offset = offset; bc->io.start = 0UL; - bc->pc.io_offset = 0UL; bc->io.end = ~0UL; bc->io.flags = IORESOURCE_IO; @@ -231,7 +386,7 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) /* * Until otherwise set up, assume all interrupts are from slot 0 */ - bridge->b_int_device = (u32) 0x0; + bridge->b_int_device = 0x0; /* * swap pio's to pci mem and io space (big windows) @@ -248,11 +403,18 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; + for (slot = 0; slot < 8; slot ++) { + bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + bc->pci_int[slot] = -1; + } bridge->b_wid_tflush; /* wait until Bridge PIO complete */ bc->base = bridge; register_pci_controller(&bc->pc); + + num_bridges++; + return 0; } @@ -268,17 +430,13 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - int irq; - - irq = allocate_irqno(); + int irq = bc->pci_int[slot]; - /* - * Argh... This API doesn't handle with errors at all ... - */ if (irq == -1) { - printk(KERN_ERR "Can't allocate interrupt for PCI device %s\n", - pci_name(dev)); - return -1; + irq = bc->pci_int[slot] = request_bridge_irq(bc); + if (irq < 0) + panic("Can't allocate interrupt for PCI device %s\n", + pci_name(dev)); } irq_to_bridge[irq] = bc; @@ -287,6 +445,12 @@ int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + /* * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses * to find the slot number in sense of the bridge device register. @@ -294,7 +458,7 @@ int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) * settings. */ -static void __init pci_disable_swapping(struct pci_dev *dev) +static inline void pci_disable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -305,7 +469,7 @@ static void __init pci_disable_swapping(struct pci_dev *dev) bridge->b_widget.w_tflush; /* Flush */ } -static void __init pci_enable_swapping(struct pci_dev *dev) +static inline void pci_enable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -318,123 +482,8 @@ static void __init pci_enable_swapping(struct pci_dev *dev) static void __init pci_fixup_ioc3(struct pci_dev *d) { - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - unsigned long offset = NODE_OFFSET(bc->nasid); - - printk("PCI: Fixing base addresses for IOC3 device %s\n", pci_name(d)); - - d->resource[0].start |= offset; - d->resource[0].end |= offset; - pci_disable_swapping(d); } -static void __init pci_fixup_isp1020(struct pci_dev *d) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - unsigned short command; - - d->resource[0].start |= (unsigned long) bc->nasid << 32; - printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", pci_name(d)); - - /* - * Configure device to allow bus mastering, i/o and memory mapping. - * Older qlogicisp driver expects to have the IO space enable - * bit set. Things stop working if we program the controllers as not - * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. - */ - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - d->resource[1].flags |= 1; - - pci_enable_swapping(d); -} - -static void __init pci_fixup_isp2x00(struct pci_dev *d) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - bridge_t *bridge = bc->base; - bridgereg_t devreg; - int i; - int slot = PCI_SLOT(d->devfn); - unsigned int start; - unsigned short command; - - printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", pci_name(d)); - - /* set the resource struct for this device */ - start = (u32) (u64) bridge; /* yes, we want to lose the upper 32 bits here */ - start |= BRIDGE_DEVIO(slot); - - d->resource[0].start = start; - d->resource[0].end = d->resource[0].start + 0xff; - d->resource[0].flags = IORESOURCE_IO; - - d->resource[1].start = start; - d->resource[1].end = d->resource[0].start + 0xfff; - d->resource[1].flags = IORESOURCE_MEM; - - /* - * set the bridge device(x) reg for this device - */ - devreg = bridge->b_device[slot].reg; - /* point device(x) to it appropriate small window */ - devreg &= ~BRIDGE_DEV_OFF_MASK; - devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; - bridge->b_device[slot].reg = devreg; - - pci_enable_swapping(d); - - /* set card's base addr reg */ - //pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); - //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); - //pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); - - /* I got these from booting irix on system... */ - pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); - //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); - pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); - - pci_write_config_dword(d, PCI_BASE_ADDRESS_1, start); - //pci_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); - - /* set cache line size */ - pci_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); - - /* set pci bus timeout */ - bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); - bridge->b_wid_tflush; - printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); - - /* set host error field */ - bridge->b_int_host_err = 0x44; - bridge->b_wid_tflush; - - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - for (i = 0; i < 8; i++) - printk("PCI: device(%d)= 0x%x\n", i, - bridge->b_device[i].reg); - - /* configure device to allow bus mastering, i/o and memory mapping */ - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - /*d->resource[1].flags |= 1; */ -} - -struct pci_fixup pcibios_fixups[] = { - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, - pci_fixup_ioc3}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, - pci_fixup_isp1020}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, - pci_fixup_isp2x00}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, - pci_fixup_isp2x00}, - {0} -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + pci_fixup_ioc3); diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c index 3b3e1940e..1faeb034f 100644 --- a/arch/mips/pci/pci-ip32.c +++ b/arch/mips/pci/pci-ip32.c @@ -4,6 +4,7 @@ * for more details. * * Copyright (C) 2000, 2001 Keith M Wesolowski + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) */ #include #include @@ -11,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c index 24943a23c..95a028769 100644 --- a/arch/mips/pci/pci-jmr3927.c +++ b/arch/mips/pci/pci-jmr3927.c @@ -4,6 +4,7 @@ * ahennessy@mvista.com * * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -30,7 +31,6 @@ #include #include -#include #include #include diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index d104360a1..ae3cc4b25 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000, 2001 Keith M Wesolowski + * Copyright (C) 2000, 2001, 04 Keith M Wesolowski */ #include #include @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -66,6 +65,7 @@ early_initcall(lasat_pci_setup); #define LASATINT_PCIB 6 #define LASATINT_PCIC 7 #define LASATINT_PCID 8 + int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { switch (slot) { @@ -87,3 +87,9 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return -1; } + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c index 8b2227277..1d84d36e0 100644 --- a/arch/mips/pci/pci-ocelot-c.c +++ b/arch/mips/pci/pci-ocelot-c.c @@ -3,13 +3,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 by Ralf Baechle + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) */ #include #include #include -#include #include diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c index 239b81fba..1e3430154 100644 --- a/arch/mips/pci/pci-ocelot-g.c +++ b/arch/mips/pci/pci-ocelot-g.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 by Ralf Baechle + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This doesn't really fly - but I don't have a GT64240 system for testing. */ @@ -12,7 +12,6 @@ #include #include #include -#include /* * We assume these address ranges have been programmed into the GT-64240 by diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c index 18e06ecd4..b32343ee0 100644 --- a/arch/mips/pci/pci-sb1250.c +++ b/arch/mips/pci/pci-sb1250.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001,2002,2003 Broadcom Corporation + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,9 +37,9 @@ #include #include #include +#include #include -#include #include #include @@ -89,6 +90,12 @@ int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return dev->irq; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + /* * Some checks before doing config cycles: * In PCI Device Mode, hide everything on bus 0 except the LDT host @@ -181,22 +188,22 @@ struct pci_ops sb1250_pci_ops = { static struct resource sb1250_mem_resource = { .name = "SB1250 PCI MEM", - .start = 0x14000000UL, - .end = 0x17ffffffUL, + .start = 0x40000000UL, + .end = 0x5fffffffUL, .flags = IORESOURCE_MEM, }; static struct resource sb1250_io_resource = { - .name = "SB1250 IO MEM", - .start = 0x14000000UL, - .end = 0x17ffffffUL, + .name = "SB1250 PCI I/O", + .start = 0x00000000UL, + .end = 0x01ffffffUL, .flags = IORESOURCE_IO, }; struct pci_controller sb1250_controller = { .pci_ops = &sb1250_pci_ops, .mem_resource = &sb1250_mem_resource, - .io_resource = &sb1250_io_resource + .io_resource = &sb1250_io_resource, }; static int __init sb1250_pcibios_init(void) @@ -208,8 +215,8 @@ static int __init sb1250_pcibios_init(void) /* CFE will assign PCI resources */ pci_probe_only = 1; - /* set resource limit to avoid errors */ - ioport_resource.end = 0x0000ffff; /* 32MB reserved by sb1250 */ + /* Set I/O resource limits. */ + ioport_resource.end = 0x01ffffff; /* 32MB accessible by sb1250 */ iomem_resource.end = 0xffffffff; /* no HT support yet */ cfg_space = @@ -279,7 +286,3 @@ static int __init sb1250_pcibios_init(void) return 0; } arch_initcall(sb1250_pcibios_init); - -struct pci_fixup pcibios_fixups[] = { - {0} -}; diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index a6db6f028..f21a0d5a0 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -4,6 +4,7 @@ * Copyright (C) 2001-2003 MontaVista Software Inc. * Author: Yoichi Yuasa * Copyright (C) 2004 Yoichi Yuasa + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +31,6 @@ #include #include -#include #include #include "pci-vr41xx.h" diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c index c1151f43c..9ab65c2c8 100644 --- a/arch/mips/pci/pci-yosemite.c +++ b/arch/mips/pci/pci-yosemite.c @@ -3,15 +3,13 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 by Ralf Baechle - * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) */ #include #include #include #include #include -#include extern struct pci_ops titan_pci_ops; @@ -19,19 +17,42 @@ static struct resource py_mem_resource = { "Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM }; +/* + * PMON really reserves 16MB of I/O port space but that's stupid, nothing + * needs that much since allocations are limited to 256 bytes per device + * anyway. So we just claim 64kB here. + */ +#define TITAN_IO_SIZE 0x0000ffffUL + static struct resource py_io_resource = { - "Titan IO MEM", 0x00000000UL, 0x00ffffffUL, IORESOURCE_IO, + "Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO, }; static struct pci_controller py_controller = { .pci_ops = &titan_pci_ops, .mem_resource = &py_mem_resource, - .mem_offset = 0x10000000UL, + .mem_offset = 0x00000000UL, .io_resource = &py_io_resource, .io_offset = 0x00000000UL }; +static char ioremap_failed[] __initdata = "Could not ioremap I/O port range"; + static int __init pmc_yosemite_setup(void) { + unsigned long io_v_base; + + io_v_base = (unsigned long) ioremap(0xe0000000UL,TITAN_IO_SIZE); + if (!io_v_base) + panic(ioremap_failed); + + set_io_port_base(io_v_base); + + ioport_resource.end = TITAN_IO_SIZE - 1; + register_pci_controller(&py_controller); + + return 0; } + +arch_initcall(pmc_yosemite_setup); diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 9bee1e937..54853e763 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -4,7 +4,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * - * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org) */ #include #include @@ -14,8 +14,6 @@ #include #include -#include - /* * Indicate whether we respect the PCI setup left by the firmware. * @@ -223,7 +221,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) if ((err = pcibios_enable_resources(dev, mask)) < 0) return err; - return 0; + return pcibios_plat_dev_init(dev); } static void __init pcibios_fixup_device_resources(struct pci_dev *dev, diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile index bc1758623..ae96a71a3 100644 --- a/arch/mips/pmc-sierra/yosemite/Makefile +++ b/arch/mips/pmc-sierra/yosemite/Makefile @@ -5,3 +5,4 @@ obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o obj-$(CONFIG_KGDB) += dbg_io.o +obj-$(CONFIG_SMP) += smp.o diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c index 1ff8d95d0..abaff965b 100644 --- a/arch/mips/pmc-sierra/yosemite/dbg_io.c +++ b/arch/mips/pmc-sierra/yosemite/dbg_io.c @@ -33,7 +33,7 @@ #include -#if defined(CONFIG_KGDB) +#ifdef CONFIG_KGDB #include /* diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c index b9a12e90a..95bbfd013 100644 --- a/arch/mips/pmc-sierra/yosemite/ht.c +++ b/arch/mips/pmc-sierra/yosemite/ht.c @@ -414,11 +414,6 @@ struct pci_ops titan_pci_ops = { titan_ht_config_write_dword }; - -struct pci_fixup pcibios_fixups[] = { - {0} -}; - void __init pcibios_fixup_bus(struct pci_bus *c) { titan_ht_pcibios_fixup_bus(c); diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S index ebe2e64e2..e577c32f0 100644 --- a/arch/mips/pmc-sierra/yosemite/irq-handler.S +++ b/arch/mips/pmc-sierra/yosemite/irq-handler.S @@ -1,6 +1,7 @@ /* - * Copyright 2003 PMC-Sierra Inc. + * Copyright 2003, 04 PMC-Sierra Inc. * Author: Manish Lachwani (lachwani@pmc-sierra.com + * Copyright 2004 Ralf Baechle (ralf@linux-mips.org) * * First-level interrupt router for the PMC-Sierra Titan board * @@ -27,6 +28,7 @@ CLI .set at .set noreorder + la ra, ret_from_irq mfc0 t0, CP0_CAUSE mfc0 t2, CP0_STATUS @@ -69,42 +71,36 @@ ll_pcia_irq: li a0, 2 move a1, sp #ifdef CONFIG_HYPERTRANSPORT - jal ll_ht_smp_irq_handler + j ll_ht_smp_irq_handler #else - jal do_IRQ + j do_IRQ #endif - j ret_from_irq ll_pcib_irq: li a0, 3 move a1, sp - jal do_IRQ - j ret_from_irq + j do_IRQ ll_duart_irq: li a0, 4 move a1, sp - jal do_IRQ - j ret_from_irq + j do_IRQ ll_smp_irq: li a0, 5 move a1, sp #ifdef CONFIG_SMP - jal jaguar_mailbox_irq + j titan_mailbox_irq #else - jal do_IRQ + j do_IRQ #endif - j ret_from_irq ll_ht_irq: li a0, 6 move a1, sp - jal ll_ht_smp_irq_handler - j ret_from_irq + j ll_ht_smp_irq_handler ll_timer_irq: li a0, 7 move a1, sp - jal do_IRQ - j ret_from_irq + j do_IRQ diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c index e8b7ed63e..8641a9990 100644 --- a/arch/mips/pmc-sierra/yosemite/irq.c +++ b/arch/mips/pmc-sierra/yosemite/irq.c @@ -34,10 +34,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -111,28 +112,22 @@ asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs) #ifdef CONFIG_KGDB extern void init_second_port(void); -extern void breakpoint(void); -extern void set_debug_traps(void); #endif /* * Initialize the next level interrupt handler */ -void __init init_IRQ(void) +void __init arch_init_irq(void) { clear_c0_status(ST0_IM); set_except_vector(0, titan_handle_int); - init_generic_irq(); mips_cpu_irq_init(0); rm7k_cpu_irq_init(8); #ifdef CONFIG_KGDB /* At this point, initialize the second serial port */ init_second_port(); - printk("Start kgdb ... \n"); - set_debug_traps(); - breakpoint(); #endif #ifdef CONFIG_GDB_CONSOLE diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c index 5b4ef33ac..4c2e8c41c 100644 --- a/arch/mips/pmc-sierra/yosemite/prom.c +++ b/arch/mips/pmc-sierra/yosemite/prom.c @@ -4,9 +4,11 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * - * Copyright (C) 2003 PMC-Sierra Inc. + * Copyright (C) 2003, 2004 PMC-Sierra Inc. * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * Copyright (C) 2004 Ralf Baechle */ +#include #include #include #include @@ -21,6 +23,12 @@ #include #include +#ifdef CONFIG_SMP +extern void prom_grab_secondary(void); +#else +#define prom_grab_secondary() do { } while (0) +#endif + #include "setup.h" struct callvectors *debug_vectors; @@ -116,14 +124,10 @@ void __init prom_init(void) } #endif /* CONFIG_MIPS32 */ -#ifdef CONFIG_MIPS64 - - /* Do nothing for the 64-bit for now. Just implement for the 32-bit */ - -#endif /* CONFIG_MIPS64 */ - mips_machgroup = MACH_GROUP_TITAN; mips_machtype = MACH_TITAN_YOSEMITE; + + prom_grab_secondary(); } void __init prom_free_prom_memory(void) diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c index 22c336f9a..abc04358d 100644 --- a/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/arch/mips/pmc-sierra/yosemite/py-console.c @@ -48,8 +48,6 @@ struct yo_uartregs { #define iu_iir u3.iir #define iu_fcr u3.fcr -extern unsigned long uart_base; - #define IO_BASE_64 0x9000000000000000ULL static unsigned char readb_outer_space(unsigned long phys) @@ -110,11 +108,6 @@ static void writeb_outer_space(unsigned long phys, unsigned char c) __asm__("sll $0, $0, 2\n"); } -static inline struct yo_uartregs *console_uart(void) -{ - return (struct yo_uartregs *) (uart_base + 8); -} - void prom_putchar(char c) { unsigned long lsr = 0xfd000008UL + offsetof(struct yo_uartregs, iu_lsr); diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index dfa9cd0ed..c6a9b0392 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -2,6 +2,8 @@ * Copyright (C) 2003 PMC-Sierra Inc. * Author: Manish Lachwani (lachwani@pmc-sierra.com) * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -37,13 +39,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 08064f24b..c1b659c55 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -1,178 +1,152 @@ -/* - * Copyright 2003 PMC-Sierra - * Author: Manish Lachwani (lachwani@pmc-sierra.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. - */ +#include +#include + +#include +#include + +#define LAUNCHSTACK_SIZE 256 + +static spinlock_t launch_lock __initdata; + +static unsigned long secondary_sp __initdata; +static unsigned long secondary_gp __initdata; + +static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata + __attribute__((aligned(2 * sizeof(long)))); -#include -#include -#include -#include +static void __init prom_smp_bootstrap(void) +{ + local_irq_disable(); -#include -#include + while (spin_is_locked(&launch_lock)); -extern void asmlinkage smp_bootstrap(void); + __asm__ __volatile__( + " move $sp, %0 \n" + " move $gp, %1 \n" + " j smp_bootstrap \n" + : + : "r" (secondary_sp), "r" (secondary_gp)); +} /* - * Send inter-processor interrupt + * PMON is a fragile beast. It'll blow up once the mappings it's littering + * right into the middle of KSEG3 are blown away so we have to grab the slave + * core early and keep it in a waiting loop. */ -void core_send_ipi(int cpu, unsigned int action) +void __init prom_grab_secondary(void) { - /* - * Generate and INTMSG so that it can be sent over to the destination CPU - * The INTMSG will put the STATUS bits based on the action desired - */ - switch(action) { - case SMP_RESCHEDULE_YOURSELF: - /* Do nothing */ - break; - case SMP_CALL_FUNCTION: - if (cpu == 1) - *(volatile uint32_t *)(0xbb000a00) = 0x00610002; - else - *(volatile uint32_t *)(0xbb000a00) = 0x00610001; - break; - - default: - panic("core_send_ipi \n"); - } + spin_lock(&launch_lock); + + debug_vectors->cpustart(1, &prom_smp_bootstrap, + launchstack + LAUNCHSTACK_SIZE, 0); } /* - * Mailbox interrupt to handle IPI + * Detect available CPUs, populate phys_cpu_present_map before smp_init + * + * We don't want to start the secondary CPU yet nor do we have a nice probing + * feature in PMON so we just assume presence of the secondary core. */ -void jaguar_mailbox_irq(struct pt_regs *regs) +void prom_prepare_cpus(unsigned int max_cpus) { - int cpu = smp_processor_id(); + cpus_clear(phys_cpu_present_map); + + /* + * The boot CPU + */ + cpu_set(0, phys_cpu_present_map); + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + + /* + * The secondary core + */ + cpu_set(1, phys_cpu_present_map); + __cpu_number_map[1] = 1; + __cpu_logical_map[1] = 1; +} - /* SMP_CALL_FUNCTION */ - smp_call_function_interrupt(); +/* + * Firmware CPU startup hook + * Complicated by PMON's weird interface which tries to minimic the UNIX fork. + * It launches the next * available CPU and copies some information on the + * stack so the first thing we do is throw away that stuff and load useful + * values into the registers ... + */ +void prom_boot_secondary(int cpu, struct task_struct *idle) +{ + unsigned long gp = (unsigned long) idle->thread_info; + unsigned long sp = gp + THREAD_SIZE - 32; + + secondary_sp = sp; + secondary_gp = gp; + + spin_unlock(&launch_lock); +} + +/* Hook for after all CPUs are online */ +void prom_cpus_done(void) +{ } -extern atomic_t cpus_booted; +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ +void prom_init_secondary(void) +{ + set_c0_status(ST0_CO | ST0_IE | ST0_IM); +} -void __init start_secondary(void) +void prom_smp_finish(void) { - unsigned int cpu = smp_processor_id(); - extern atomic_t smp_commenced; - - if (current->processor != 1) { - printk("Impossible CPU %d \n", cpu); - current->processor = 1; - current->cpus_runnable = 1 << 1; - cpu = current->processor; - } - - if (current->mm) - current->mm = NULL; - - prom_init_secondary(); - per_cpu_trap_init(); - - /* - * XXX parity protection should be folded in here when it's converted - * to an option instead of something based on .cputype - */ - pgd_current[cpu] = init_mm.pgd; - cpu_data[cpu].udelay_val = loops_per_jiffy; - prom_smp_finish(); - CPUMASK_SETB(cpu_online_map, cpu); - atomic_inc(&cpus_booted); - __flush_cache_all(); - - printk("Slave cpu booted successfully \n"); - *(volatile uint32_t *)(0xbb000a68) = 0x00000000; - *(volatile uint32_t *)(0xbb000a68) = 0x80000000; - - while (*(volatile uint32_t *)(0xbb000a68) != 0x00000000); - - return cpu_idle(); } -void __init smp_boot_cpus(void) +asmlinkage void titan_mailbox_irq(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + unsigned long status; + + if (cpu == 0) { + status = OCD_READ(RM9000x2_OCD_INTP0STATUS3); + OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status); + } + + if (cpu == 1) { + status = OCD_READ(RM9000x2_OCD_INTP1STATUS3); + OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status); + } + + if (status & 0x2) + smp_call_function_interrupt(); +} + +/* + * Send inter-processor interrupt + */ +void core_send_ipi(int cpu, unsigned int action) { - int i; - int cur_cpu = 0; - - smp_num_cpus = prom_setup_smp(); - printk("Detected %d available CPUs \n", smp_num_cpus); - - init_new_context(current, &init_mm); - current->processor = 0; - cpu_data[0].udelay_val = loops_per_jiffy; - cpu_data[0].asid_cache = ASID_FIRST_VERSION; - CPUMASK_CLRALL(cpu_online_map); - CPUMASK_SETB(cpu_online_map, 0); - atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ - init_idle(); - - __cpu_number_map[0] = 0; - __cpu_logical_map[0] = 0; - - /* - * This loop attempts to compensate for "holes" in the CPU - * numbering. It's overkill, but general. - */ - for (i = 1; i < smp_num_cpus; ) { - struct task_struct *p; - struct pt_regs regs; - int retval; - printk("Starting CPU %d... \n", i); - - /* Spawn a new process normally. Grab a pointer to - its task struct so we can mess with it */ - do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); - - p = init_task.prev_task; - if (!p) - panic("failed fork for CPU %d", i); - - /* This is current for the second processor */ - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ - p->thread.reg31 = (unsigned long) start_secondary; - - del_from_runqueue(p); - unhash_process(p); - init_tasks[i] = p; - - __flush_cache_all(); - - do { - /* Iterate until we find a CPU that comes up */ - cur_cpu++; - retval = prom_boot_secondary(cur_cpu, - (unsigned long)p + KERNEL_STACK_SIZE - 32, - (unsigned long)p); - - } while (!retval && (cur_cpu < NR_CPUS)); - if (retval) { - __cpu_number_map[cur_cpu] = i; - __cpu_logical_map[i] = cur_cpu; - i++; - } else { - panic("CPU discovery disaster"); - } - } - - /* Local semaphore to both the CPUs */ - - *(volatile uint32_t *)(0xbb000a68) = 0x80000000; - while (*(volatile uint32_t *)(0xbb000a68) != 0x00000000); - - smp_threads_ready = 1; + /* + * Generate an INTMSG so that it can be sent over to the + * destination CPU. The INTMSG will put the STATUS bits + * based on the action desired. An alternative strategy + * is to write to the Interrupt Set register, read the + * Interrupt Status register and clear the Interrupt + * Clear register. The latter is preffered. + */ + switch (action) { + case SMP_RESCHEDULE_YOURSELF: + if (cpu == 1) + OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4); + else + OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4); + break; + + case SMP_CALL_FUNCTION: + if (cpu == 1) + OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2); + else + OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2); + break; + } } diff --git a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c index 943c942d7..a28dc7800 100644 --- a/arch/mips/sgi-ip22/ip22-berr.c +++ b/arch/mips/sgi-ip22/ip22-berr.c @@ -65,7 +65,7 @@ static void print_buserr(void) cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", cpu_err_addr); if (gio_err_stat & GIO_ERRMASK) - printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n", + printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n", gio_err_stat, gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index acb44a18d..ea2844d29 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -309,7 +309,7 @@ static struct irqaction map1_cascade = { extern void mips_cpu_irq_init(unsigned int irq_base); -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; @@ -371,7 +371,6 @@ void __init init_IRQ(void) set_except_vector(0, indyIRQ); - init_generic_irq(); /* init CPU irqs */ mips_cpu_irq_init(SGINT_CPU); diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c index fe7f546d3..d77a9d207 100644 --- a/arch/mips/sgi-ip22/ip22-setup.c +++ b/arch/mips/sgi-ip22/ip22-setup.c @@ -29,12 +29,6 @@ #include #include -#ifdef CONFIG_KGDB -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -static int remote_debug = 0; -#endif - unsigned long sgi_gfxaddr; /* @@ -43,7 +37,6 @@ unsigned long sgi_gfxaddr; * * FIXME: provide a mechanism to change the value of stop_a_enabled. */ -int serial_console; int stop_a_enabled; void ip22_do_break(void) @@ -63,9 +56,6 @@ extern void ip22_time_init(void) __init; static int __init ip22_setup(void) { char *ctype; -#ifdef CONFIG_KGDB - char *kgdb_ttyd; -#endif board_be_init = ip22_be_init; ip22_time_init(); @@ -84,9 +74,10 @@ static int __init ip22_setup(void) indy_sc_init(); #endif - /* Set EISA IO port base for Indigo2 */ - set_io_port_base(KSEG1ADDR(0x00080000)); - + /* Set EISA IO port base for Indigo2 + * ioremap cannot fail */ + set_io_port_base((unsigned long)ioremap(0x00080000, + 0x1fffffff - 0x00080000)); /* ARCS console environment variable is set to "g?" for * graphics console, it is set to "d" for the first serial * line and "d2" for the second serial line. @@ -106,7 +97,9 @@ static int __init ip22_setup(void) } #ifdef CONFIG_KGDB - kgdb_ttyd = prom_getcmdline(); + { + char *kgdb_ttyd = prom_getcmdline(); + if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { int line; kgdb_ttyd += strlen("kgdb=ttyd"); @@ -121,9 +114,10 @@ static int __init ip22_setup(void) printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for " "session, please connect your debugger\n", line ? 1:2); - remote_debug = 1; + kgdb_enabled = 1; /* Breakpoints and stuff are in sgi_irq_setup() */ } + } #endif #ifdef CONFIG_VT diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c index 79e0d6c36..524b371f9 100644 --- a/arch/mips/sgi-ip27/ip27-hubio.c +++ b/arch/mips/sgi-ip27/ip27-hubio.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -44,7 +45,7 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, xtalk_addr &= ~(BWIN_SIZE-1); for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) { - if (test_and_set_bit(i, HUB_DATA(cnode)->h_bigwin_used)) + if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used)) continue; /* @@ -177,7 +178,7 @@ void hub_pio_init(cnodeid_t cnode) unsigned i; /* initialize big window piomaps for this hub */ - bitmap_zero(HUB_DATA(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW); + bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW); for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) IIO_ITTE_DISABLE(nasid, i); diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index b8ee02cd0..f624f9da5 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -12,6 +12,7 @@ #include #include /* for numnodes */ #include +#include #include #include #include @@ -40,90 +41,25 @@ #define CPU_NONE (cpuid_t)-1 static DECLARE_BITMAP(hub_init_mask, MAX_COMPACT_NODES); -static hubreg_t region_mask; -static int fine_mode; -static int router_distance; nasid_t master_nasid = INVALID_NASID; cnodeid_t nasid_to_compact_node[MAX_NASIDS]; nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; cnodeid_t cpuid_to_compact_node[MAXCPUS]; -char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; -static hubreg_t get_region(cnodeid_t cnode) -{ - if (fine_mode) - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; - else - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; -} - -static void gen_region_mask(hubreg_t *region_mask, int maxnodes) -{ - cnodeid_t cnode; - - (*region_mask) = 0; - for (cnode = 0; cnode < maxnodes; cnode++) { - (*region_mask) |= 1ULL << get_region(cnode); - } -} - -static int is_fine_dirmode(void) -{ - return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) - >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); -} +EXPORT_SYMBOL(nasid_to_compact_node); extern void pcibr_setup(cnodeid_t); -static __init void per_slice_init(cnodeid_t cnode, int slice) -{ - struct slice_data *si = hub_data[cnode]->slice + slice; - int cpu = smp_processor_id(); - int i; - - for (i = 0; i < LEVELS_PER_SLICE; i++) - si->level_to_irq[i] = -1; - /* - * Some interrupts are reserved by hardware or by software convention. - * Mark these as reserved right away so they won't be used accidently - * later. - */ - for (i = 0; i <= BASE_PCI_IRQ; i++) { - __set_bit(i, si->irq_alloc_mask); - LOCAL_HUB_S(PI_INT_PEND_MOD, i); - } - - __set_bit(IP_PEND0_6_63, si->irq_alloc_mask); - LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); - - for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { - __set_bit(i, si->irq_alloc_mask + 1); - LOCAL_HUB_S(PI_INT_PEND_MOD, i); - } - - LOCAL_HUB_L(PI_INT_PEND0); - - /* - * We use this so we can find the local hub's data as fast as only - * possible. - */ - cpu_data[cpu].data = si; -} - extern void xtalk_probe_node(cnodeid_t nid); -void __init per_hub_init(cnodeid_t cnode) +static void __init per_hub_init(cnodeid_t cnode) { - struct hub_data *hub = HUB_DATA(cnode); + struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - int slice = LOCAL_HUB_L(PI_CPU_NUM); cpu_set(smp_processor_id(), hub->h_cpus); - if (!test_and_set_bit(slice, &hub->slice_map)) - per_slice_init(cnode, slice); - if (test_and_set_bit(cnode, hub_init_mask)) return; @@ -142,13 +78,13 @@ void __init per_hub_init(cnodeid_t cnode) * copy over the caliased exception handlers. */ if (get_compact_nodeid() == cnode) { - extern char except_vec0, except_vec1_r10k; + extern char except_vec0, except_vec1_r4k; extern char except_vec2_generic, except_vec3_generic; memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); memcpy((void *)KSEG0, &except_vec0, 0x80); - memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); + memcpy((void *)KSEG0 + 0x080, &except_vec1_r4k, 0x80); memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x100); __flush_cache_all(); @@ -156,260 +92,76 @@ void __init per_hub_init(cnodeid_t cnode) #endif } -/* - * get_nasid() returns the physical node id number of the caller. - */ -nasid_t -get_nasid(void) -{ - return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) - >> NSRI_NODEID_SHFT); -} - -/* - * Map the physical node id to a virtual node id (virtual node ids are contiguous). - */ -cnodeid_t get_compact_nodeid(void) -{ - return NASID_TO_COMPACT_NODEID(get_nasid()); -} - -#define rou_rflag rou_flags - -static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +void __init per_cpu_init(void) { - klrou_t *router; - lboard_t *brd; - int port; - - if (router_a->rou_rflag == 1) - return; + int cpu = smp_processor_id(); + int slice = LOCAL_HUB_L(PI_CPU_NUM); + cnodeid_t cnode = get_compact_nodeid(); + struct hub_data *hub = hub_data(cnode); + struct slice_data *si = hub->slice + slice; + int i; - if (depth >= router_distance) + if (test_and_set_bit(slice, &hub->slice_map)) return; - router_a->rou_rflag = 1; - - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router_a->rou_port[port].port_nasid == INVALID_NASID) - continue; - - brd = (lboard_t *)NODE_OFFSET_TO_K0( - router_a->rou_port[port].port_nasid, - router_a->rou_port[port].port_offset); - - if (brd->brd_type == KLTYPE_ROUTER) { - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - if (router == router_b) { - if (depth < router_distance) - router_distance = depth; - } - else - router_recurse(router, router_b, depth + 1); - } - } - - router_a->rou_rflag = 0; -} - -int node_distance(nasid_t nasid_a, nasid_t nasid_b) -{ - klrou_t *router, *router_a = NULL, *router_b = NULL; - lboard_t *brd, *dest_brd; - cnodeid_t cnode; - nasid_t nasid; - int port; - - /* Figure out which routers nodes in question are connected to */ - for (cnode = 0; cnode < numnodes; cnode++) { - nasid = COMPACT_TO_NASID_NODEID(cnode); - - if (nasid == -1) continue; - - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); - - if (!brd) - continue; - - do { - if (brd->brd_flags & DUPLICATE_BOARD) - continue; - - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - router->rou_rflag = 0; + clear_c0_status(ST0_IM); - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) - continue; + for (i = 0; i < LEVELS_PER_SLICE; i++) + si->level_to_irq[i] = -1; - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); + /* + * Some interrupts are reserved by hardware or by software convention. + * Mark these as reserved right away so they won't be used accidently + * later. + */ + for (i = 0; i <= BASE_PCI_IRQ; i++) { + __set_bit(i, si->irq_alloc_mask); + LOCAL_HUB_S(PI_INT_PEND_MOD, i); + } - if (dest_brd->brd_type == KLTYPE_IP27) { - if (dest_brd->brd_nasid == nasid_a) - router_a = router; - if (dest_brd->brd_nasid == nasid_b) - router_b = router; - } - } + __set_bit(IP_PEND0_6_63, si->irq_alloc_mask); + LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); - } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER))); + for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { + __set_bit(i, si->irq_alloc_mask + 1); + LOCAL_HUB_S(PI_INT_PEND_MOD, i); } - if (router_a == NULL) { - printk("node_distance: router_a NULL\n"); - return -1; - } - if (router_b == NULL) { - printk("node_distance: router_b NULL\n"); - return -1; - } + LOCAL_HUB_L(PI_INT_PEND0); - if (nasid_a == nasid_b) - return 0; + /* + * We use this so we can find the local hub's data as fast as only + * possible. + */ + cpu_data[cpu].data = si; - if (router_a == router_b) - return 1; + cpu_time_init(); + install_ipi(); - router_distance = 100; - router_recurse(router_a, router_b, 2); + /* Install our NMI handler if symmon hasn't installed one. */ + install_cpu_nmi_handler(cputoslice(cpu)); - return router_distance; -} + set_c0_status(SRB_DEV0 | SRB_DEV1); -static void init_topology_matrix(void) -{ - nasid_t nasid, nasid2; - cnodeid_t row, col; - - for (row = 0; row < MAX_COMPACT_NODES; row++) - for (col = 0; col < MAX_COMPACT_NODES; col++) - node_distances[row][col] = -1; - - for (row = 0; row < numnodes; row++) { - nasid = COMPACT_TO_NASID_NODEID(row); - for (col = 0; col < numnodes; col++) { - nasid2 = COMPACT_TO_NASID_NODEID(col); - node_distances[row][col] = node_distance(nasid, nasid2); - } - } + per_hub_init(cnode); } -static void dump_topology(void) +/* + * get_nasid() returns the physical node id number of the caller. + */ +nasid_t +get_nasid(void) { - nasid_t nasid; - cnodeid_t cnode; - lboard_t *brd, *dest_brd; - int port; - int router_num = 0; - klrou_t *router; - cnodeid_t row, col; - - printk("************** Topology ********************\n"); - - printk(" "); - for (col = 0; col < numnodes; col++) - printk("%02d ", col); - printk("\n"); - for (row = 0; row < numnodes; row++) { - printk("%02d ", row); - for (col = 0; col < numnodes; col++) - printk("%2d ", node_distances[row][col]); - printk("\n"); - } - - for (cnode = 0; cnode < numnodes; cnode++) { - nasid = COMPACT_TO_NASID_NODEID(cnode); - - if (nasid == -1) continue; - - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); - - if (!brd) - continue; - - do { - if (brd->brd_flags & DUPLICATE_BOARD) - continue; - printk("Router %d:", router_num); - router_num++; - - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) - continue; - - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); - - if (dest_brd->brd_type == KLTYPE_IP27) - printk(" %d", dest_brd->brd_nasid); - if (dest_brd->brd_type == KLTYPE_ROUTER) - printk(" r"); - } - printk("\n"); - - } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); - } + return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) + >> NSRI_NODEID_SHFT); } -void mlreset(void) +/* + * Map the physical node id to a virtual node id (virtual node ids are contiguous). + */ +cnodeid_t get_compact_nodeid(void) { - int i; - - master_nasid = get_nasid(); - fine_mode = is_fine_dirmode(); - - /* - * Probe for all CPUs - this creates the cpumask and sets up the - * mapping tables. We need to do this as early as possible. - */ -#ifdef CONFIG_SMP - cpu_node_probe(); -#endif - - init_topology_matrix(); - dump_topology(); - - gen_region_mask(®ion_mask, numnodes); - - setup_replication_mask(numnodes); - - /* - * Set all nodes' calias sizes to 8k - */ - for (i = 0; i < numnodes; i++) { - nasid_t nasid; - - nasid = COMPACT_TO_NASID_NODEID(i); - - /* - * Always have node 0 in the region mask, otherwise - * CALIAS accesses get exceptions since the hub - * thinks it is a node 0 address. - */ - REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); -#ifdef CONFIG_REPLICATE_EXHANDLERS - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); -#else - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); -#endif - -#ifdef LATER - /* - * Set up all hubs to have a big window pointing at - * widget 0. Memory mode, widget 0, offset 0 - */ - REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), - ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | - (0 << IIO_ITTE_WIDGET_SHIFT))); -#endif - } + return NASID_TO_COMPACT_NODEID(get_nasid()); } /* Extracted from the IOC3 meta driver. FIXME. */ @@ -444,20 +196,6 @@ static inline void ioc3_eth_init(void) ioc3->eier = 0; } -void __init per_cpu_init(void) -{ - cnodeid_t cnode = get_compact_nodeid(); - int cpu = smp_processor_id(); - - clear_c0_status(ST0_IM); - per_hub_init(cnode); - cpu_time_init(); - install_ipi(); - /* Install our NMI handler if symmon hasn't installed one. */ - install_cpu_nmi_handler(cputoslice(cpu)); - set_c0_status(SRB_DEV0 | SRB_DEV1); -} - extern void ip27_setup_console(void); extern void ip27_time_init(void); extern void ip27_reboot_setup(void); diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 917c1ee7a..61817a18a 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -14,14 +14,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include -#include #include #include #include @@ -151,9 +152,6 @@ void ip27_do_irq_mask0(struct pt_regs *regs) if (!pend0) return; - /* Prevent any of the picked intrs from recursing */ - LOCAL_HUB_S(pi_int_mask0, mask0 & ~pend0); - swlevel = ms1bit(pend0); #ifdef CONFIG_SMP if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { @@ -176,11 +174,6 @@ void ip27_do_irq_mask0(struct pt_regs *regs) do_IRQ(irq, regs); } - /* clear bit in pend0 */ - pend0 ^= 1UL << swlevel; - - /* Now allow the set of serviced intrs again */ - LOCAL_HUB_S(pi_int_mask0, mask0); LOCAL_HUB_L(PI_INT_PEND0); } @@ -200,19 +193,12 @@ void ip27_do_irq_mask1(struct pt_regs *regs) if (!pend1) return; - /* Prevent any of the picked intrs from recursing */ - LOCAL_HUB_S(pi_int_mask1, mask1 & ~pend1); - swlevel = ms1bit(pend1); /* "map" swlevel to irq */ irq = si->level_to_irq[swlevel]; LOCAL_HUB_CLR_INTR(swlevel); do_IRQ(irq, regs); - /* clear bit in pend1 */ - pend1 ^= 1UL << swlevel; - /* Now allow the set of serviced intrs again */ - LOCAL_HUB_S(pi_int_mask1, mask1); LOCAL_HUB_L(PI_INT_PEND1); } @@ -233,9 +219,6 @@ static int intr_connect_level(int cpu, int bit) __set_bit(bit, si->irq_enable_mask); - /* Make sure it's not already pending when we connect it. */ - REMOTE_HUB_CLR_INTR(nasid, bit); - if (!cputoslice(cpu)) { REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); @@ -272,6 +255,7 @@ static unsigned int startup_bridge_irq(unsigned int irq) bridgereg_t device; bridge_t *bridge; int pin, swlevel; + cpuid_t cpu; pin = SLOT_FROM_PCI_IRQ(irq); bc = IRQ_TO_BRIDGE(irq); @@ -282,13 +266,10 @@ static unsigned int startup_bridge_irq(unsigned int irq) * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = alloc_level(bc->irq_cpu, irq); - intr_connect_level(bc->irq_cpu, swlevel); - + swlevel = find_level(&cpu, irq); bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); bridge->b_int_enable |= (1 << pin); - /* more stuff in int_enable reg */ - bridge->b_int_enable |= 0x7ffffe00; + bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ /* * Enable sending of an interrupt clear packt to the hub on a high to @@ -308,7 +289,7 @@ static unsigned int startup_bridge_irq(unsigned int irq) device |= (pin << (pin*3)); bridge->b_int_device = device; - bridge->b_widget.w_tflush; /* Flush */ + bridge->b_wid_tflush; return 0; /* Never anything pending. */ } @@ -336,26 +317,37 @@ static void shutdown_bridge_irq(unsigned int irq) si->level_to_irq[swlevel] = -1; bridge->b_int_enable &= ~(1 << pin); - bridge->b_widget.w_tflush; /* Flush */ + bridge->b_wid_tflush; } static inline void enable_bridge_irq(unsigned int irq) { - /* All the braindamage happens magically for us in ip27_do_irq */ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, irq); /* Criminal offence */ + intr_connect_level(cpu, swlevel); } -static void disable_bridge_irq(unsigned int irq) +static inline void disable_bridge_irq(unsigned int irq) { - /* All the braindamage happens magically for us in ip27_do_irq */ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, irq); /* Criminal offence */ + intr_disconnect_level(cpu, swlevel); } static void mask_and_ack_bridge_irq(unsigned int irq) { - /* All the braindamage happens magically for us in ip27_do_irq */ + disable_bridge_irq(irq); } static void end_bridge_irq(unsigned int irq) { + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && + irq_desc[irq].action) + enable_bridge_irq(irq); } static struct hw_interrupt_type bridge_irq_type = { @@ -370,15 +362,15 @@ static struct hw_interrupt_type bridge_irq_type = { static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; -unsigned int allocate_irqno(void) +static int allocate_irqno(void) { int irq; again: - irq = find_first_zero_bit(irq_map, LEVELS_PER_SLICE); + irq = find_first_zero_bit(irq_map, NR_IRQS); if (irq >= NR_IRQS) - return -1; + return -ENOSPC; if (test_and_set_bit(irq, irq_map)) goto again; @@ -391,21 +383,49 @@ void free_irqno(unsigned int irq) clear_bit(irq, irq_map); } -void __init init_IRQ(void) +void __devinit register_bridge_irq(unsigned int irq) { - int i; + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 1; + irq_desc[irq].handler = &bridge_irq_type; +} - set_except_vector(0, ip27_irq); +int __devinit request_bridge_irq(struct bridge_controller *bc) +{ + int irq = allocate_irqno(); + int swlevel, cpu; + nasid_t nasid; + + if (irq < 0) + return irq; /* - * Right now the bridge irq is our kitchen sink interrupt type + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken */ - for (i = 0; i <= NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &bridge_irq_type; + cpu = bc->irq_cpu; + swlevel = alloc_level(cpu, irq); + if (unlikely(swlevel < 0)) { + free_irqno(irq); + + return -EAGAIN; } + + /* Make sure it's not already pending when we connect it. */ + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + REMOTE_HUB_CLR_INTR(nasid, swlevel); + + intr_connect_level(cpu, swlevel); + + register_bridge_irq(irq); + + return irq; +} + +void __init arch_init_irq(void) +{ + set_except_vector(0, ip27_irq); } void install_ipi(void) diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index b5e86ad98..fb47c75c4 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c @@ -61,12 +61,12 @@ void __init setup_replication_mask(int maxnodes) static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) { - kern_vars_t *kvp; cnodeid_t client_cnode; + kern_vars_t *kvp; client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); - kvp = &(HUB_DATA(client_nasid)->kern_vars); + kvp = &hub_data(client_nasid)->kern_vars; KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 6c6df7b5b..327eadb4f 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -36,8 +37,226 @@ static short __initdata slot_lastfilled_cache[MAX_COMPACT_NODES]; static unsigned short __initdata slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; static struct bootmem_data __initdata plat_node_bdata[MAX_COMPACT_NODES]; -struct pglist_data *node_data[MAX_COMPACT_NODES]; -struct hub_data *hub_data[MAX_COMPACT_NODES]; +struct node_data *__node_data[MAX_COMPACT_NODES]; + +EXPORT_SYMBOL(__node_data); + +static int fine_mode; + +static int is_fine_dirmode(void) +{ + return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) + >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); +} + +static hubreg_t get_region(cnodeid_t cnode) +{ + if (fine_mode) + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; + else + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; +} + +static hubreg_t region_mask; + +static void gen_region_mask(hubreg_t *region_mask, int maxnodes) +{ + cnodeid_t cnode; + + (*region_mask) = 0; + for (cnode = 0; cnode < maxnodes; cnode++) { + (*region_mask) |= 1ULL << get_region(cnode); + } +} + +#define rou_rflag rou_flags + +static int router_distance; + +static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +{ + klrou_t *router; + lboard_t *brd; + int port; + + if (router_a->rou_rflag == 1) + return; + + if (depth >= router_distance) + return; + + router_a->rou_rflag = 1; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router_a->rou_port[port].port_nasid == INVALID_NASID) + continue; + + brd = (lboard_t *)NODE_OFFSET_TO_K0( + router_a->rou_port[port].port_nasid, + router_a->rou_port[port].port_offset); + + if (brd->brd_type == KLTYPE_ROUTER) { + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + if (router == router_b) { + if (depth < router_distance) + router_distance = depth; + } + else + router_recurse(router, router_b, depth + 1); + } + } + + router_a->rou_rflag = 0; +} + +unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; + +static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b) +{ + klrou_t *router, *router_a = NULL, *router_b = NULL; + lboard_t *brd, *dest_brd; + cnodeid_t cnode; + nasid_t nasid; + int port; + + /* Figure out which routers nodes in question are connected to */ + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + router->rou_rflag = 0; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) { + if (dest_brd->brd_nasid == nasid_a) + router_a = router; + if (dest_brd->brd_nasid == nasid_b) + router_b = router; + } + } + + } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER))); + } + + if (router_a == NULL) { + printk("node_distance: router_a NULL\n"); + return -1; + } + if (router_b == NULL) { + printk("node_distance: router_b NULL\n"); + return -1; + } + + if (nasid_a == nasid_b) + return 0; + + if (router_a == router_b) + return 1; + + router_distance = 100; + router_recurse(router_a, router_b, 2); + + return router_distance; +} + +static void __init init_topology_matrix(void) +{ + nasid_t nasid, nasid2; + cnodeid_t row, col; + + for (row = 0; row < MAX_COMPACT_NODES; row++) + for (col = 0; col < MAX_COMPACT_NODES; col++) + __node_distances[row][col] = -1; + + for (row = 0; row < numnodes; row++) { + nasid = COMPACT_TO_NASID_NODEID(row); + for (col = 0; col < numnodes; col++) { + nasid2 = COMPACT_TO_NASID_NODEID(col); + __node_distances[row][col] = + compute_node_distance(nasid, nasid2); + } + } +} + +static void __init dump_topology(void) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + int router_num = 0; + klrou_t *router; + cnodeid_t row, col; + + printk("************** Topology ********************\n"); + + printk(" "); + for (col = 0; col < numnodes; col++) + printk("%02d ", col); + printk("\n"); + for (row = 0; row < numnodes; row++) { + printk("%02d ", row); + for (col = 0; col < numnodes; col++) + printk("%2d ", node_distance(row, col)); + printk("\n"); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + printk("Router %d:", router_num); + router_num++; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) + printk(" %d", dest_brd->brd_nasid); + if (dest_brd->brd_type == KLTYPE_ROUTER) + printk(" r"); + } + printk("\n"); + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} static pfn_t __init slot_getbasepfn(cnodeid_t cnode, int slot) { @@ -126,6 +345,60 @@ static pfn_t __init slot_psize_compute(cnodeid_t node, int slot) } } +static void __init mlreset(void) +{ + int i; + + master_nasid = get_nasid(); + fine_mode = is_fine_dirmode(); + + /* + * Probe for all CPUs - this creates the cpumask and sets up the + * mapping tables. We need to do this as early as possible. + */ +#ifdef CONFIG_SMP + cpu_node_probe(); +#endif + + init_topology_matrix(); + dump_topology(); + + gen_region_mask(®ion_mask, numnodes); + + setup_replication_mask(numnodes); + + /* + * Set all nodes' calias sizes to 8k + */ + for (i = 0; i < numnodes; i++) { + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(i); + + /* + * Always have node 0 in the region mask, otherwise + * CALIAS accesses get exceptions since the hub + * thinks it is a node 0 address. + */ + REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); +#ifdef CONFIG_REPLICATE_EXHANDLERS + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); +#else + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); +#endif + +#ifdef LATER + /* + * Set up all hubs to have a big window pointing at + * widget 0. Memory mode, widget 0, offset 0 + */ + REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), + ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | + (0 << IIO_ITTE_WIDGET_SHIFT))); +#endif + } +} + static void __init szmem(void) { pfn_t slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ @@ -164,6 +437,45 @@ static void __init szmem(void) } } +static void __init node_mem_init(cnodeid_t node) +{ + pfn_t slot_firstpfn = slot_getbasepfn(node, 0); + pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); + pfn_t slot_freepfn = node_getfirstfree(node); + struct pglist_data *pd; + unsigned long bootmap_size; + + /* + * Allocate the node data structures on the node first. + */ + __node_data[node] = __va(slot_freepfn << PAGE_SHIFT); + + pd = NODE_DATA(node); + pd->bdata = &plat_node_bdata[node]; + + cpus_clear(hub_data(node)->h_cpus); + + slot_freepfn += PFN_UP(sizeof(struct pglist_data) + + sizeof(struct hub_data)); + + bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, + slot_firstpfn, slot_lastpfn); + free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, + (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT); + reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, + ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size); +} + +/* + * A node with nothing. We use it to avoid any special casing in + * node_to_cpumask + */ +static struct node_data null_node = { + .hub = { + .h_cpus = CPU_MASK_NONE + } +}; + /* * Currently, the intranode memory hole support assumes that each slot * contains at least 32 MBytes of memory. We assume all bootmem data @@ -176,31 +488,12 @@ void __init prom_meminit(void) mlreset(); szmem(); - for (node = 0; node < numnodes; node++) { - pfn_t slot_firstpfn = slot_getbasepfn(node, 0); - pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); - pfn_t slot_freepfn = node_getfirstfree(node); - unsigned long bootmap_size; - - /* - * Allocate the node data structures on the node first. - */ - node_data[node] = __va(slot_freepfn << PAGE_SHIFT); - node_data[node]->bdata = &plat_node_bdata[node]; - - hub_data[node] = (struct hub_data *)(node_data[node] + 1); - - cpus_clear(hub_data[node]->h_cpus); - - slot_freepfn += PFN_UP(sizeof(struct pglist_data) + - sizeof(struct hub_data)); - - bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, - slot_firstpfn, slot_lastpfn); - free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT); - reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size); + for (node = 0; node < MAX_COMPACT_NODES; node++) { + if (node < numnodes) { + node_mem_init(node); + continue; + } + __node_data[node] = &null_node; } } @@ -225,7 +518,7 @@ void __init paging_init(void) pfn_t end_pfn = node_getmaxclick(node) + 1; zones_size[ZONE_DMA] = end_pfn - start_pfn; - free_area_init_node(node, NODE_DATA(node), NULL, + free_area_init_node(node, NODE_DATA(node), zones_size, start_pfn, NULL); if (end_pfn > max_low_pfn) diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 1e5ce4ca2..1103e2910 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -122,10 +122,6 @@ void cpu_node_probe(void) printk("Discovered %d cpus on %d nodes\n", highest + 1, numnodes); } -void __init prom_build_cpu_map(void) -{ -} - static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level) { @@ -158,9 +154,6 @@ void __init prom_prepare_cpus(unsigned int max_cpus) for (cnode = 0; cnode < numnodes; cnode++) intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); - /* Master has already done per_cpu_init() */ - install_ipi(); - replicate_kernel_text(numnodes); /* diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index cc0419ad7..9d384d131 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -112,9 +112,7 @@ again: if (cpu == 0) do_timer(regs); -#ifdef CONFIG_SMP update_process_times(user_mode(regs)); -#endif /* CONFIG_SMP */ /* * If we have an externally synchronized Linux clock, then update diff --git a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c index a8c7a776a..7f771bf68 100644 --- a/arch/mips/sgi-ip32/crime.c +++ b/arch/mips/sgi-ip32/crime.c @@ -10,13 +10,14 @@ #include #include #include +#include #include #include #include #include #include -void *sgi_crime; +struct sgi_crime *crime; struct sgi_mace *mace; void __init crime_init(void) @@ -24,13 +25,12 @@ void __init crime_init(void) unsigned int id, rev; const int field = 2 * sizeof(unsigned long); - sgi_crime = ioremap(CRIME_BASE, 1); + crime = ioremap(CRIME_BASE, sizeof(struct sgi_crime)); mace = ioremap(MACE_BASE, sizeof(struct sgi_mace)); - id = crime_read(CRIME_ID); + id = crime->id; rev = id & CRIME_ID_REV; id = (id & CRIME_ID_IDBITS) >> 4; - printk (KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n", id, rev, field, (unsigned long) CRIME_BASE); } @@ -41,19 +41,18 @@ crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) unsigned long stat, addr; int fatal = 0; - stat = crime_read(CRIME_MEM_ERROR_STAT) & CRIME_MEM_ERROR_STAT_MASK; - addr = crime_read(CRIME_MEM_ERROR_ADDR) & CRIME_MEM_ERROR_ADDR_MASK; + stat = crime->mem_error_stat & CRIME_MEM_ERROR_STAT_MASK; + addr = crime->mem_error_addr & CRIME_MEM_ERROR_ADDR_MASK; printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, stat); if (stat & CRIME_MEM_ERROR_INV) printk("INV,"); if (stat & CRIME_MEM_ERROR_ECC) { - unsigned long ecc_syn = crime_read(CRIME_MEM_ERROR_ECC_SYN) & - CRIME_MEM_ERROR_ECC_SYN_MASK; - unsigned long ecc_gen = crime_read(CRIME_MEM_ERROR_ECC_CHK) & - CRIME_MEM_ERROR_ECC_CHK_MASK; - + unsigned long ecc_syn = + crime->mem_ecc_syn & CRIME_MEM_ERROR_ECC_SYN_MASK; + unsigned long ecc_gen = + crime->mem_ecc_chk & CRIME_MEM_ERROR_ECC_CHK_MASK; printk("ECC,SYN=0x%08lx,GEN=0x%08lx,", ecc_syn, ecc_gen); } if (stat & CRIME_MEM_ERROR_MULTIPLE) { @@ -77,7 +76,7 @@ crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) if (stat & CRIME_MEM_ERROR_MACE_ACCESS) printk("MACE,MACEID=0x%02lx,", stat & CRIME_MEM_ERROR_MACE_ID); - crime_write(0, CRIME_MEM_ERROR_STAT); + crime->mem_error_stat = 0; if (fatal) { printk("FATAL>\n"); @@ -91,15 +90,12 @@ crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) irqreturn_t crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) { - unsigned long stat = crime_read(CRIME_CPU_ERROR_STAT) & - CRIME_CPU_ERROR_MASK; - uint64_t addr = crime_read(CRIME_CPU_ERROR_ADDR) & - CRIME_CPU_ERROR_ADDR_MASK; - addr <<= 2; + unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK; + unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK; + addr <<= 2; printk ("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat); - - crime_write(0, CRIME_CPU_ERROR_STAT); + crime->cpu_error_stat = 0; return IRQ_HANDLED; } diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 75846d6e8..9519e5fae 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -30,10 +29,14 @@ #include /* issue a PIO read to make sure no PIO writes are pending */ -#define flush_crime_bus() crime_read(CRIME_CONTROL); +static void inline flush_crime_bus(void) +{ + volatile unsigned long junk = crime->control; +} + static void inline flush_mace_bus(void) { - volatile unsigned long junk = mace_perif_ctrl_read(misc); + volatile unsigned long junk = mace->perif.ctrl.misc; } #undef DEBUG_IRQ @@ -183,7 +186,7 @@ static void enable_crime_irq(unsigned int irq) spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -199,7 +202,7 @@ static void disable_crime_irq(unsigned int irq) spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; flush_crime_bus(); spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -214,9 +217,9 @@ static void mask_and_ack_crime_irq(unsigned int irq) || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { uint64_t crime_int; spin_lock_irqsave(&ip32_irq_lock, flags); - crime_int = crime_read(CRIME_HARD_INT); + crime_int = crime->hard_int; crime_int &= ~(1 << (irq - 1)); - crime_write(crime_int, CRIME_HARD_INT); + crime->hard_int = crime_int; spin_unlock_irqrestore(&ip32_irq_lock, flags); } disable_crime_irq(irq); @@ -257,7 +260,7 @@ static void enable_macepci_irq(unsigned int irq) macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); mace->pci.control = macepci_mask; crime_mask |= 1 << (irq - 1); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -273,7 +276,7 @@ static void disable_macepci_irq(unsigned int irq) spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; flush_crime_bus(); macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); mace->pci.control = macepci_mask; @@ -361,9 +364,9 @@ static void enable_maceisa_irq (unsigned int irq) DBG ("crime_int %08x enabled\n", crime_int); spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= crime_int; - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; maceisa_mask |= 1 << (irq - 33); - mace_perif_ctrl_write(maceisa_mask, imask); + mace->perif.ctrl.imask = maceisa_mask; spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -387,9 +390,9 @@ static void disable_maceisa_irq(unsigned int irq) if(!(maceisa_mask & MACEISA_SUPERIO_INT)) crime_int |= MACE_SUPERIO_INT; crime_mask &= ~crime_int; - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; flush_crime_bus(); - mace_perif_ctrl_write(maceisa_mask, imask); + mace->perif.ctrl.imask = maceisa_mask; flush_mace_bus(); spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -404,9 +407,9 @@ static void mask_and_ack_maceisa_irq(unsigned int irq) case MACEISA_SERIAL2_TDMAPR_IRQ: /* edge triggered */ spin_lock_irqsave(&ip32_irq_lock, flags); - mace_int = mace_perif_ctrl_read(istat); + mace_int = mace->perif.ctrl.istat; mace_int &= ~(1 << (irq - 33)); - mace_perif_ctrl_write(mace_int, istat); + mace->perif.ctrl.istat = mace_int; spin_unlock_irqrestore(&ip32_irq_lock, flags); break; } @@ -442,7 +445,7 @@ static void enable_mace_irq(unsigned int irq) spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -458,7 +461,7 @@ static void disable_mace_irq(unsigned int irq) spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write(crime_mask, CRIME_INT_MASK); + crime->imask = crime_mask; flush_crime_bus(); spin_unlock_irqrestore(&ip32_irq_lock, flags); } @@ -485,19 +488,14 @@ static struct hw_interrupt_type ip32_mace_interrupt = { static void ip32_unknown_interrupt(struct pt_regs *regs) { - uint64_t crime; - printk ("Unknown interrupt occurred!\n"); printk ("cp0_status: %08x\n", read_c0_status()); printk ("cp0_cause: %08x\n", read_c0_cause()); - crime = crime_read(CRIME_INT_MASK); - printk ("CRIME intr mask: %016lx\n", crime); - crime = crime_read(CRIME_INT_STAT); - printk ("CRIME intr status: %016lx\n", crime); - crime = crime_read(CRIME_HARD_INT); - printk ("CRIME hardware intr register: %016lx\n", crime); - printk ("MACE ISA intr mask: %08lx\n", mace_perif_ctrl_read(imask)); - printk ("MACE ISA intr status: %08lx\n", mace_perif_ctrl_read(istat)); + printk ("CRIME intr mask: %016lx\n", crime->imask); + printk ("CRIME intr status: %016lx\n", crime->istat); + printk ("CRIME hardware intr register: %016lx\n", crime->hard_int); + printk ("MACE ISA intr mask: %08lx\n", mace->perif.ctrl.imask); + printk ("MACE ISA intr status: %08lx\n", mace->perif.ctrl.istat); printk ("MACE PCI control register: %08x\n", mace->pci.control); printk("Register dump:\n"); @@ -515,12 +513,12 @@ void ip32_irq0(struct pt_regs *regs) uint64_t crime_int; int irq = 0; - crime_int = crime_read(CRIME_INT_STAT) & crime_mask; + crime_int = crime->istat & crime_mask; irq = ffs(crime_int); crime_int = 1 << (irq - 1); if (crime_int & CRIME_MACEISA_INT_MASK) { - unsigned long mace_int = mace_perif_ctrl_read(istat); + unsigned long mace_int = mace->perif.ctrl.istat; irq = ffs(mace_int & maceisa_mask) + 32; } DBG("*irq %u*\n", irq); @@ -552,18 +550,17 @@ void ip32_irq5(struct pt_regs *regs) ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { unsigned int irq; - init_generic_irq(); /* Install our interrupt handler, then clear and disable all * CRIME and MACE interrupts. */ - crime_write(0, CRIME_INT_MASK); - crime_write(0, CRIME_HARD_INT); - crime_write(0, CRIME_SOFT_INT); - mace_perif_ctrl_write(0, istat); - mace_perif_ctrl_write(0, imask); + crime->imask = 0; + crime->hard_int = 0; + crime->soft_int = 0; + mace->perif.ctrl.istat = 0; + mace->perif.ctrl.imask = 0; set_except_vector(0, ip32_handle_int); for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index ac65798bd..6340468d4 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -41,7 +41,7 @@ static void ip32_machine_power_off(void) __attribute__((noreturn)); static void ip32_machine_restart(char *cmd) { - crime_write(CRIME_CONTROL_HARD_RESET, CRIME_CONTROL); + crime->control = CRIME_CONTROL_HARD_RESET; while (1); } @@ -83,9 +83,9 @@ static void power_timeout(unsigned long data) static void blink_timeout(unsigned long data) { - unsigned long led = mace_perif_ctrl_read(misc) ^ MACEISA_LED_RED; - mace_perif_ctrl_write(led, misc); - mod_timer(&blink_timer, jiffies+data); + unsigned long led = mace->perif.ctrl.misc ^ MACEISA_LED_RED; + mace->perif.ctrl.misc = led; + mod_timer(&blink_timer, jiffies + data); } static void debounce(unsigned long data) @@ -165,8 +165,8 @@ static int panic_event(struct notifier_block *this, unsigned long event, has_paniced = 1; /* turn off the green LED */ - led = mace_perif_ctrl_read(misc) | MACEISA_LED_GREEN; - mace_perif_ctrl_write(led, misc); + led = mace->perif.ctrl.misc | MACEISA_LED_GREEN; + mace->perif.ctrl.misc = led; blink_timer.data = PANIC_FREQ; blink_timeout(PANIC_FREQ); @@ -181,10 +181,10 @@ static struct notifier_block panic_block = { static __init int ip32_reboot_setup(void) { /* turn on the green led only */ - unsigned long led = mace_perif_ctrl_read(misc); + unsigned long led = mace->perif.ctrl.misc; led |= MACEISA_LED_RED; led &= ~MACEISA_LED_GREEN; - mace_perif_ctrl_write(led, misc); + mace->perif.ctrl.misc = led; _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index 51cad2d84..5fccded29 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -80,8 +80,8 @@ void __init ip32_time_init(void) { printk(KERN_INFO "Calibrating system timer... "); write_c0_count(0); - crime_write(0, CRIME_TIMER); - while (crime_read(CRIME_TIMER) < CRIME_MASTER_FREQ * WAIT_MS / 1000) ; + crime->timer = 0; + while (crime->timer < CRIME_MASTER_FREQ * WAIT_MS / 1000) ; mips_hpt_frequency = read_c0_count() * 1000 / WAIT_MS; printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000); } @@ -114,7 +114,7 @@ static int __init ip32_setup(void) o2_serial[0].type = PORT_16550A; o2_serial[0].line = 0; o2_serial[0].irq = MACEISA_SERIAL1_IRQ; - o2_serial[0].flags = STD_COM_FLAGS | UPF_RESOURCES; + o2_serial[0].flags = STD_COM_FLAGS; o2_serial[0].uartclk = BASE_BAUD * 16; o2_serial[0].iotype = UPIO_MEM; o2_serial[0].membase = (char *)&mace->isa.serial1; @@ -125,7 +125,7 @@ static int __init ip32_setup(void) o2_serial[1].type = PORT_16550A; o2_serial[1].line = 1; o2_serial[1].irq = MACEISA_SERIAL2_IRQ; - o2_serial[1].flags = STD_COM_FLAGS | UPF_RESOURCES; + o2_serial[1].flags = STD_COM_FLAGS; o2_serial[1].uartclk = BASE_BAUD * 16; o2_serial[1].iotype = UPIO_MEM; o2_serial[1].membase = (char *)&mace->isa.serial2; diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c index 3dd85d5ba..d6d0364fa 100644 --- a/arch/mips/sibyte/cfe/setup.c +++ b/arch/mips/sibyte/cfe/setup.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -55,36 +56,45 @@ int cfe_cons_handle; #ifdef CONFIG_BLK_DEV_INITRD extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - -#ifdef CONFIG_SMP -static int reboot_smp = 0; #endif #ifdef CONFIG_KGDB extern int kgdb_port; #endif -static void cfe_linux_exit(void) +static void ATTRIB_NORET cfe_linux_exit(void *arg) { -#ifdef CONFIG_SMP + int warm = *(int *)arg; + if (smp_processor_id()) { - if (reboot_smp) { - /* Don't repeat the process from another CPU */ - for (;;); - } else { + static int reboot_smp; + + /* Don't repeat the process from another CPU */ + if (!reboot_smp) { /* Get CPU 0 to do the cfe_exit */ reboot_smp = 1; - smp_call_function((void *)_machine_restart, NULL, 1, 0); - for (;;); + smp_call_function(cfe_linux_exit, arg, 1, 0); } + } else { + printk("Passing control back to CFE...\n"); + cfe_exit(warm, 0); + printk("cfe_exit returned??\n"); } -#endif - printk("passing control back to CFE\n"); - cfe_exit(1, 0); - printk("cfe_exit returned??\n"); - while(1); + while (1); +} + +static void ATTRIB_NORET cfe_linux_restart(char *command) +{ + static const int zero; + + cfe_linux_exit((void *)&zero); +} + +static void ATTRIB_NORET cfe_linux_halt(void) +{ + static const int one = 1; + + cfe_linux_exit((void *)&one); } static __init void prom_meminit(void) @@ -97,17 +107,6 @@ static __init void prom_meminit(void) unsigned long initrd_pstart; unsigned long initrd_pend; -#ifdef CONFIG_EMBEDDED_RAMDISK - /* If we're using an embedded ramdisk, then __rd_start and __rd_end - are defined by the linker to be on either side of the ramdisk - area. Otherwise, initrd_start should be defined by kernel command - line arguments */ - if (initrd_start == 0) { - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; - } -#endif - initrd_pstart = CPHYSADDR(initrd_start); initrd_pend = CPHYSADDR(initrd_end); if (initrd_start && @@ -247,9 +246,9 @@ void __init prom_init(void) char *arg; #endif - _machine_restart = (void (*)(char *))cfe_linux_exit; - _machine_halt = cfe_linux_exit; - _machine_power_off = cfe_linux_exit; + _machine_restart = cfe_linux_restart; + _machine_halt = cfe_linux_halt; + _machine_power_off = cfe_linux_halt; /* * Check if a loader was used; if NOT, the 4 arguments are diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c index fada7042e..73392190d 100644 --- a/arch/mips/sibyte/cfe/smp.c +++ b/arch/mips/sibyte/cfe/smp.c @@ -28,8 +28,10 @@ * Use CFE to find out how many CPUs are available, setting up * phys_cpu_present_map and the logical/physical mappings. * XXXKW will the boot CPU ever not be physical 0? + * + * Common setup before any secondaries are started */ -void __init prom_build_cpu_map(void) +void __init prom_prepare_cpus(unsigned int max_cpus) { int i, num; @@ -48,13 +50,6 @@ void __init prom_build_cpu_map(void) printk("Detected %i available secondary CPU(s)\n", num); } -/* - * Common setup before any secondaries are started - */ -void prom_prepare_cpus(unsigned int max_cpus) -{ -} - /* * Setup the PC, SP, and GP of a secondary processor and start it * running! diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index ddbe64b2d..88d524edc 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -61,19 +61,8 @@ extern unsigned long ldt_eoi_space; #endif #ifdef CONFIG_KGDB -#include -extern void breakpoint(void); static int kgdb_irq; -/* kgdb is on when configured. Pass "nokgdb" kernel arg to turn it off */ -static int kgdb_flag = 1; -static int __init nokgdb(char *str) -{ - kgdb_flag = 0; - return 1; -} -__setup("nokgdb", nokgdb); - /* Default to UART1 */ int kgdb_port = 1; #ifdef CONFIG_SIBYTE_SB1250_DUART @@ -307,10 +296,10 @@ int sb1250_steal_irq(int irq) } /* - * init_IRQ is called early in the boot sequence from init/main.c. It - * is responsible for setting up the interrupt mapper and installing the - * handler that will be responsible for dispatching interrupts to the - * "right" place. + * arch_init_irq is called early in the boot sequence from init/main.c via + * init_IRQ. It is responsible for setting up the interrupt mapper and + * installing the handler that will be responsible for dispatching interrupts + * to the "right" place. */ /* * For now, map all interrupts to IP[2]. We could save @@ -332,7 +321,7 @@ int sb1250_steal_irq(int irq) #define IMR_IP5_VAL K_INT_MAP_I3 #define IMR_IP6_VAL K_INT_MAP_I4 -void __init init_IRQ(void) +void __init arch_init_irq(void) { unsigned int i; @@ -405,10 +394,6 @@ void __init init_IRQ(void) IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (kgdb_irq<<3))); sb1250_unmask_irq(0, kgdb_irq); - - prom_printf("Waiting for GDB on UART port %d\n", kgdb_port); - set_debug_traps(); - breakpoint(); } #endif } diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S index ad6c6b055..75b57a67a 100644 --- a/arch/mips/sibyte/sb1250/irq_handler.S +++ b/arch/mips/sibyte/sb1250/irq_handler.S @@ -18,8 +18,8 @@ /* * sb1250_handle_int() is the routine that is actually called when an interrupt - * occurs. It is installed as the exception vector handler in init_IRQ() in - * arch/mips/sibyte/sb1250/irq.c + * occurs. It is installed as the exception vector handler in arch_init_irq() + * in arch/mips/sibyte/sb1250/irq.c * * In the handle we figure out which interrupts need handling, and use that to * call the dispatcher, which will take care of actually calling registered diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c index 426fb3014..de62ab0f5 100644 --- a/arch/mips/sibyte/sb1250/prom.c +++ b/arch/mips/sibyte/sb1250/prom.c @@ -23,16 +23,11 @@ #include #include #include +#include #include #include -#ifdef CONFIG_EMBEDDED_RAMDISK -/* These are symbols defined by the ramdisk linker script */ -extern unsigned char __rd_start; -extern unsigned char __rd_end; -#endif - #define MAX_RAM_SIZE ((CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - 1) static __init void prom_meminit(void) @@ -41,17 +36,6 @@ static __init void prom_meminit(void) unsigned long initrd_pstart; unsigned long initrd_pend; -#ifdef CONFIG_EMBEDDED_RAMDISK - /* If we're using an embedded ramdisk, then __rd_start and __rd_end - are defined by the linker to be on either side of the ramdisk - area. Otherwise, initrd_start should be defined by kernel command - line arguments */ - if (initrd_start == 0) { - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; - } -#endif - initrd_pstart = __pa(initrd_start); initrd_pend = __pa(initrd_end); if (initrd_start && diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 638da0903..9e7336c7c 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -34,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c index caa44d1d9..afb660218 100644 --- a/arch/mips/sni/irq.c +++ b/arch/mips/sni/irq.c @@ -173,13 +173,12 @@ void __init init_pciasic(void) * driver compatibility reasons interrupts 0 - 15 to be the i8295 * interrupts even if the hardware uses a different interrupt numbering. */ -void __init init_IRQ (void) +void __init arch_init_irq(void) { int i; set_except_vector(0, sni_rm200_pci_handle_int); - init_generic_irq(); init_i8259_irqs(); /* Integrated i8259 */ init_pciasic(); diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index d2fa8b1eb..8f67cee43 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004 by Ralf Baechle + * Copyright (C) 1996, 97, 98, 2000, 03, 04 Ralf Baechle (ralf@linux-mips.org) */ #include #include @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile index 573c75309..8fa126b29 100644 --- a/arch/mips/tx4927/common/Makefile +++ b/arch/mips/tx4927/common/Makefile @@ -8,4 +8,5 @@ obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o +obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o obj-$(CONFIG_KGDB) += tx4927_dbgio.o diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c index bf59409ee..80a0efc9f 100644 --- a/arch/mips/tx4927/common/tx4927_irq.c +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,8 +48,6 @@ /* * DEBUG */ -#define TX4927_IRQ_CHECK_CP0 -#define TX4927_IRQ_CHECK_PIC #undef TX4927_IRQ_DEBUG @@ -239,16 +237,6 @@ static unsigned int tx4927_irq_cp0_startup(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_cp0_enable(irq); return (0); @@ -258,16 +246,6 @@ static void tx4927_irq_cp0_shutdown(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_cp0_disable(irq); return; @@ -279,16 +257,6 @@ static void tx4927_irq_cp0_enable(unsigned int irq) TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - spin_lock_irqsave(&tx4927_cp0_lock, flags); tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq)); @@ -304,16 +272,6 @@ static void tx4927_irq_cp0_disable(unsigned int irq) TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - spin_lock_irqsave(&tx4927_cp0_lock, flags); tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); @@ -327,16 +285,6 @@ static void tx4927_irq_cp0_mask_and_ack(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_cp0_disable(irq); return; @@ -346,16 +294,6 @@ static void tx4927_irq_cp0_end(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq); -#ifdef TX4927_IRQ_CHECK_CP0 - { - if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { tx4927_irq_cp0_enable(irq); } @@ -516,16 +454,6 @@ static unsigned int tx4927_irq_pic_startup(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_pic_enable(irq); return (0); @@ -535,16 +463,6 @@ static void tx4927_irq_pic_shutdown(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_pic_disable(irq); return; @@ -556,16 +474,6 @@ static void tx4927_irq_pic_enable(unsigned int irq) TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - spin_lock_irqsave(&tx4927_pic_lock, flags); tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0, @@ -582,16 +490,6 @@ static void tx4927_irq_pic_disable(unsigned int irq) TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - spin_lock_irqsave(&tx4927_pic_lock, flags); tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), @@ -606,16 +504,6 @@ static void tx4927_irq_pic_mask_and_ack(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - tx4927_irq_pic_disable(irq); return; @@ -625,16 +513,6 @@ static void tx4927_irq_pic_end(unsigned int irq) { TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq); -#ifdef TX4927_IRQ_CHECK_PIC - { - if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { - TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, - "bad irq=%d \n", irq); - panic("\n"); - } - } -#endif - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { tx4927_irq_pic_enable(irq); } diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c index 73d188ff6..16bcbdc6d 100644 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -92,15 +92,6 @@ void __init tx4927_time_init(void) } #endif -#ifdef CONFIG_KGDB - { - printk("Calling breakpoint() -- start remote kgdb\n"); - set_debug_traps(); - breakpoint(); - printk("Calling breakpoint() -- done\n"); - } -#endif - return; } diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index 930304585..ac3dbb597 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -134,10 +134,10 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB #include #include #ifdef CONFIG_RTC_DS1742 -#include +#include #endif #ifdef CONFIG_TOSHIBA_FPCIB0 -#include +#include #endif #include @@ -665,7 +665,7 @@ static void toshiba_rbtx4927_irq_isa_end(unsigned int irq) #endif -void __init init_IRQ(void) +void __init arch_init_irq(void) { extern void tx4927_irq_init(void); @@ -681,13 +681,6 @@ void __init init_IRQ(void) } #endif -#ifdef CONFIG_PCI - { - extern void toshiba_rbtx4927_pci_irq_init(void); - toshiba_rbtx4927_pci_irq_init(); - } -#endif - wbflush(); return; diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c index 3519020b5..e4d095d3e 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c @@ -6,6 +6,9 @@ * * Copyright 2001-2002 MontaVista Software Inc. * + * Copyright (C) 2004 MontaVista Software Inc. + * Author: Manish Lachwani, mlachwani@mvista.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 @@ -86,3 +89,9 @@ const char *get_system_type(void) { return "Toshiba RBTX4927/RBTX4937"; } + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index 77698daa0..b2385c1ee 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c @@ -6,7 +6,7 @@ * * Copyright 2001-2002 MontaVista Software Inc. * - * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2000 RidgeRun, Inc. * Author: RidgeRun, Inc. * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com @@ -17,7 +17,10 @@ * Copyright 2002 MontaVista Software Inc. * Author: Michael Pruznick, michael_pruznick@mvista.com * - * Copyright (C) 2000-2001 Toshiba Corporation + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Copyright (C) 2004 MontaVista Software Inc. + * Author: Manish Lachwani, mlachwani@mvista.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 @@ -61,15 +64,14 @@ #include #include #ifdef CONFIG_RTC_DS1742 -#include +#include #endif #ifdef CONFIG_TOSHIBA_FPCIB0 -#include +#include #endif #include #ifdef CONFIG_PCI #include -#include #endif #ifdef CONFIG_BLK_DEV_IDEPCI #include @@ -146,49 +148,15 @@ static int tx4927_pcic_trdyto = 0; /* default: disabled */ unsigned long tx4927_ce_base[8]; void tx4927_pci_setup(void); void tx4927_reset_pci_pcic(void); -#ifdef TX4927_SUPPORT_PCI_66 -void tx4927_pci66_setup(void); -extern int tx4927_pci66_check(void); -#endif int tx4927_pci66 = 0; /* 0:auto */ #endif char *toshiba_name = ""; #ifdef CONFIG_PCI -void tx4927_dump_pcic_settings(void) -{ - printk("%s pcic settings:",toshiba_name); - { - int i; - unsigned long *preg = (unsigned long *) tx4927_pcicptr; - for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4) { - if (i % 32 == 0) - printk("\n%04x:", i); - if (preg == &tx4927_pcicptr->g2pintack - || preg == &tx4927_pcicptr->g2pspc -#ifdef CONFIG_TX4927BUG_WORKAROUND - || preg == &tx4927_pcicptr->g2pcfgadrs - || preg == &tx4927_pcicptr->g2pcfgdata -#endif - ) { - printk(" XXXXXXXX"); - preg++; - continue; - } - printk(" %08lx", *preg++); - if (preg == &tx4927_pcicptr->g2pcfgadrs) - break; - } - printk("\n"); - } -} - static void tx4927_pcierr_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - extern void tx4927_dump_pcic_settings(void); - #ifdef CONFIG_BLK_DEV_IDEPCI /* ignore MasterAbort for ide probing... */ if (irq == TX4927_IRQ_IRC_PCIERR && @@ -203,6 +171,7 @@ static void tx4927_pcierr_interrupt(int irq, void *dev_id, } #endif printk("PCI error interrupt (irq 0x%x).\n", irq); + printk("pcistat:%04x, g2pstatus:%08lx, pcicstatus:%08lx\n", (unsigned short) (tx4927_pcicptr->pcistatus >> 16), tx4927_pcicptr->g2pstatus, tx4927_pcicptr->pcicstatus); @@ -211,23 +180,10 @@ static void tx4927_pcierr_interrupt(int irq, void *dev_id, (unsigned long) (tx4927_ccfgptr->tear >> 32), (unsigned long) tx4927_ccfgptr->tear); show_regs(regs); - //tx4927_dump_pcic_settings(); - panic("PCI error at PC:%08lx.", regs->cp0_epc); } -static struct irqaction pcic_action = { - tx4927_pcierr_interrupt, 0, 0, "PCI-C", NULL, NULL -}; - -static struct irqaction pcierr_action = { - tx4927_pcierr_interrupt, 0, 0, "PCI-ERR", NULL, NULL -}; - - void __init toshiba_rbtx4927_pci_irq_init(void) { - setup_irq(TX4927_IRQ_IRC_PCIC, &pcic_action); - setup_irq(TX4927_IRQ_IRC_PCIERR, &pcierr_action); return; } @@ -245,91 +201,26 @@ void tx4927_reset_pci_pcic(void) #endif /* CONFIG_PCI */ #ifdef CONFIG_PCI -#ifdef TX4927_SUPPORT_PCI_66 -void tx4927_pci66_setup(void) -{ - int pciclk, pciclkin = 1; - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI66, - "-\n"); - - if (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) - return; - - tx4927_reset_pci_pcic(); - - /* Assert M66EN */ - tx4927_ccfgptr->ccfg |= TX4927_CCFG_PCI66; - /* set PCICLK 66MHz */ - if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) { - unsigned int pcidivmode = 0; - pcidivmode = - (unsigned long) tx4927_ccfgptr-> - ccfg & TX4927_CCFG_PCIDIVMODE_MASK; - if (tx4927_cpu_clock >= 170000000) { - /* CPU 200MHz */ - pcidivmode = TX4927_CCFG_PCIDIVMODE_3; - pciclk = tx4927_cpu_clock / 3; - } else { - /* CPU 166MHz */ - pcidivmode = TX4927_CCFG_PCIDIVMODE_2_5; - pciclk = tx4927_cpu_clock * 2 / 5; - } - tx4927_ccfgptr->ccfg = - (tx4927_ccfgptr->ccfg & ~TX4927_CCFG_PCIDIVMODE_MASK) - | pcidivmode; - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_PCI66, - ":PCICLK: ccfg:0x%08lx\n", - (unsigned long) tx4927_ccfgptr->ccfg); - } else { - int pciclk_setting = *tx4927_pci_clk_ptr; - pciclkin = 0; - pciclk = 66666666; - pciclk_setting &= ~TX4927_PCI_CLK_MASK; - pciclk_setting |= TX4927_PCI_CLK_66; - *tx4927_pci_clk_ptr = pciclk_setting; - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_PCI66, - "PCICLK: pci_clk:%02x\n", *tx4927_pci_clk_ptr); - } - - udelay(10000); - - /* clear PCIC reset */ - tx4927_ccfgptr->clkctr &= ~TX4927_CLKCTR_PCIRST; - /* clear PCI reset */ - *tx4927_pcireset_ptr = 0; - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI66, - "+\n"); - return; -} -#endif /* TX4927_SUPPORT_PCI_66 */ - void print_pci_status(void) { printk("PCI STATUS %lx\n", tx4927_pcicptr->pcistatus); printk("PCIC STATUS %lx\n", tx4927_pcicptr->pcicstatus); } +extern struct pci_controller tx4927_controller; + static struct pci_dev *fake_pci_dev(struct pci_controller *hose, int top_bus, int busnr, int devfn) { static struct pci_dev dev; static struct pci_bus bus; - dev.bus = &bus; - dev.sysdata = hose; + dev.sysdata = (void *)hose; dev.devfn = devfn; bus.number = busnr; bus.ops = hose->pci_ops; - - if (busnr != top_bus) - /* Fake a parent bus structure. */ - bus.parent = &bus; - else - bus.parent = NULL; + bus.parent = NULL; + dev.bus = &bus; return &dev; } @@ -350,15 +241,19 @@ EARLY_PCI_OP(write, byte, u8) EARLY_PCI_OP(write, word, u16) EARLY_PCI_OP(write, dword, u32) -static int __init tx4927_pcibios_init(int busno, struct pci_controller *hose) +static int __init tx4927_pcibios_init(void) { unsigned int id; u32 pci_devfn; + int devfn_start = 0; + int devfn_stop = 0xff; + int busno = 0; /* One bus on the Toshiba */ + struct pci_controller *hose = &tx4927_controller; TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, "-\n"); - for (pci_devfn = 0x0; pci_devfn < 0xff; pci_devfn++) { + for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) { early_read_config_dword(hose, busno, busno, pci_devfn, PCI_VENDOR_ID, &id); @@ -581,12 +476,15 @@ static int __init tx4927_pcibios_init(int busno, struct pci_controller *hose) } + register_pci_controller(&tx4927_controller); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, "+\n"); - return busno; + return 0; } +arch_initcall(tx4927_pcibios_init); + extern struct resource pci_io_resource; extern struct resource pci_mem_resource; @@ -597,11 +495,6 @@ void tx4927_pci_setup(void) TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "-\n"); -#ifndef TX4927_SUPPORT_PCI_66 - if (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) - printk("PCI 66 current unsupported\n"); -#endif - mips_memory_upper = tx4927_get_mem_size() << 20; mips_memory_upper += KSEG0; TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, @@ -736,19 +629,6 @@ void tx4927_pci_setup(void) /* PCI->GB mappings (I/O 256B) */ tx4927_pcicptr->p2giopbase = 0; /* 256B */ - -#ifdef TX4927_SUPPORT_COMMAND_IO - tx4927_pcicptr->p2giogbase = 0 | TX4927_PCIC_P2GIOGBASE_TIOEN | -#ifdef __BIG_ENDIAN - TX4927_PCIC_P2GIOGBASE_TECHG -#else - TX4927_PCIC_P2GIOGBASE_TBSDIS -#endif - ; -#else - tx4927_pcicptr->p2giogbase = 0; -#endif - /* PCI->GB mappings (MEM 512MB) M0 gets all of memory */ tx4927_pcicptr->p2gm0plbase = 0; tx4927_pcicptr->p2gm0pubase = 0; @@ -791,8 +671,6 @@ void tx4927_pci_setup(void) if (tx4927_pcic_trdyto >= 0) { tx4927_pcicptr->g2ptocnt &= ~0xff; tx4927_pcicptr->g2ptocnt |= (tx4927_pcic_trdyto & 0xff); - //printk("%s PCIC -- TRDYTO:%02lx\n",toshiba_name, - // tx4927_pcicptr->g2ptocnt & 0xff); } /* Clear All Local Bus Status */ @@ -825,17 +703,10 @@ void tx4927_pci_setup(void) tx4927_pcicptr->pcistatus = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | -#ifdef TX4927_SUPPORT_COMMAND_IO - PCI_COMMAND_IO | -#endif PCI_COMMAND_PARITY | PCI_COMMAND_SERR; TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, ":pci setup complete:\n"); - //tx4927_dump_pcic_settings(); - - tx4927_pcibios_init(0, &tx4927_controller); - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "+\n"); } @@ -883,6 +754,7 @@ void toshiba_rbtx4927_power_off(void) void __init toshiba_rbtx4927_setup(void) { vu32 cp0_config; + char *argptr; printk("CPU is %s\n", toshiba_name); @@ -923,21 +795,16 @@ void __init toshiba_rbtx4927_setup(void) TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, "+\n"); - - - mips_io_port_base = KSEG1 + TBTX4927_ISA_IO_OFFSET; + set_io_port_base(KSEG1 + TBTX4927_ISA_IO_OFFSET); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, ":mips_io_port_base=0x%08lx\n", mips_io_port_base); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, ":Resource\n"); - ioport_resource.start = 0; ioport_resource.end = 0xffffffff; - iomem_resource.start = 0; iomem_resource.end = 0xffffffff; - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, ":ResetRoutines\n"); _machine_restart = toshiba_rbtx4927_restart; @@ -1000,25 +867,11 @@ void __init toshiba_rbtx4927_setup(void) tx4927_sdramcptr->tr |= 0x02000000; /* RCD:3tck */ #endif -#ifdef TX4927_SUPPORT_PCI_66 - tx4927_pci66_setup(); -#endif - tx4927_pci_setup(); -#endif - - - { - u32 id = 0; - early_read_config_dword(&tx4927_controller, 0, 0, 0x90, - PCI_VENDOR_ID, &id); - if (id == 0x94601055) { - tx4927_using_backplane = 1; - printk("backplane board IS installed\n"); - } else { - printk("backplane board NOT installed\n"); - } - } + if (tx4927_using_backplane == 1) + printk("backplane board IS installed\n"); + else + printk("No Backplane \n"); /* this is on ISA bus behind PCI bus, so need PCI up first */ #ifdef CONFIG_TOSHIBA_FPCIB0 @@ -1065,11 +918,41 @@ void __init toshiba_rbtx4927_setup(void) } #endif +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_SERIAL_TXX9_CONSOLE + argptr = prom_getcmdline(); + if (strstr(argptr, "console=") == NULL) { + strcat(argptr, " console=ttyS0,38400"); + } +#endif + +#ifdef CONFIG_ROOT_NFS + argptr = prom_getcmdline(); + if (strstr(argptr, "root=") == NULL) { + strcat(argptr, " root=/dev/nfs rw"); + } +#endif + + +#ifdef CONFIG_IP_PNP + argptr = prom_getcmdline(); + if (strstr(argptr, "ip=") == NULL) { + strcat(argptr, " ip=any"); + } +#endif + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, - "+\n"); + "+\n"); } +#ifdef CONFIG_RTC_DS1742 +extern unsigned long rtc_ds1742_get_time(void); +extern int rtc_ds1742_set_time(unsigned long); +extern void rtc_ds1742_wait(void); +#endif + void __init toshiba_rbtx4927_time_init(void) { diff --git a/arch/mips/vr4181/common/irq.c b/arch/mips/vr4181/common/irq.c index 4a2458f8b..e4fe177b1 100644 --- a/arch/mips/vr4181/common/irq.c +++ b/arch/mips/vr4181/common/irq.c @@ -184,10 +184,9 @@ static struct irqaction cascade = static struct irqaction reserved = { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL }; -void __init init_IRQ(void) +void __init arch_init_irq(void) { int i; - extern irq_desc_t irq_desc[]; set_except_vector(0, vr4181_handle_irq); @@ -237,13 +236,4 @@ void __init init_IRQ(void) */ setup_irq(VR4181_IRQ_RTCL1, &reserved); setup_irq(VR4181_IRQ_RTCL2, &reserved); - -#ifdef CONFIG_KGDB - printk("Setting debug traps - please connect the remote debugger.\n"); - - set_debug_traps(); - - // you may move this line to whereever you want - breakpoint(); -#endif } diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c index bd2978fd5..fa93b0331 100644 --- a/arch/mips/vr41xx/common/giu.c +++ b/arch/mips/vr41xx/common/giu.c @@ -63,6 +63,12 @@ static uint32_t giu_base; +static struct irqaction giu_cascade = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + #define read_giuint(offset) readw(giu_base + (offset)) #define write_giuint(val, offset) writew((val), giu_base + (offset)) @@ -303,7 +309,6 @@ struct vr41xx_giuint_cascade { }; static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS]; -static struct irqaction giu_cascade = {no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL}; static int no_irq_number(int irq) { diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 4fd195bc9..9d73c6e8b 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -51,6 +51,12 @@ extern void giuint_irq_dispatch(struct pt_regs *regs); static uint32_t icu1_base; static uint32_t icu2_base; +static struct irqaction icu_cascade = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + static unsigned char sysint1_assign[16] = { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char sysint2_assign[16] = { @@ -159,218 +165,268 @@ void vr41xx_enable_piuint(uint16_t mask) { irq_desc_t *desc = irq_desc + PIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MPIUINTREG); - val |= mask; - write_icu1(val, MPIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + set_icu1(MPIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_piuint); + void vr41xx_disable_piuint(uint16_t mask) { irq_desc_t *desc = irq_desc + PIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MPIUINTREG); - val &= ~mask; - write_icu1(val, MPIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + clear_icu1(MPIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_piuint); + void vr41xx_enable_aiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + AIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MAIUINTREG); - val |= mask; - write_icu1(val, MAIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + set_icu1(MAIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_aiuint); + void vr41xx_disable_aiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + AIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MAIUINTREG); - val &= ~mask; - write_icu1(val, MAIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + clear_icu1(MAIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_aiuint); + void vr41xx_enable_kiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + KIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MKIUINTREG); - val |= mask; - write_icu1(val, MKIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + set_icu1(MKIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_kiuint); + void vr41xx_disable_kiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + KIU_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MKIUINTREG); - val &= ~mask; - write_icu1(val, MKIUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + spin_lock_irqsave(&desc->lock, flags); + clear_icu1(MKIUINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_kiuint); + void vr41xx_enable_dsiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + DSIU_IRQ; unsigned long flags; - uint16_t val; spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MDSIUINTREG); - val |= mask; - write_icu1(val, MDSIUINTREG); + set_icu1(MDSIUINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(vr41xx_enable_dsiuint); + void vr41xx_disable_dsiuint(uint16_t mask) { irq_desc_t *desc = irq_desc + DSIU_IRQ; unsigned long flags; - uint16_t val; spin_lock_irqsave(&desc->lock, flags); - val = read_icu1(MDSIUINTREG); - val &= ~mask; - write_icu1(val, MDSIUINTREG); + clear_icu1(MDSIUINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(vr41xx_disable_dsiuint); + void vr41xx_enable_firint(uint16_t mask) { irq_desc_t *desc = irq_desc + FIR_IRQ; unsigned long flags; - uint16_t val; spin_lock_irqsave(&desc->lock, flags); - val = read_icu2(MFIRINTREG); - val |= mask; - write_icu2(val, MFIRINTREG); + set_icu2(MFIRINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(vr41xx_enable_firint); + void vr41xx_disable_firint(uint16_t mask) { irq_desc_t *desc = irq_desc + FIR_IRQ; unsigned long flags; - uint16_t val; spin_lock_irqsave(&desc->lock, flags); - val = read_icu2(MFIRINTREG); - val &= ~mask; - write_icu2(val, MFIRINTREG); + clear_icu2(MFIRINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(vr41xx_disable_firint); + void vr41xx_enable_pciint(void) { irq_desc_t *desc = irq_desc + PCI_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(PCIINT0, MPCIINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(PCIINT0, MPCIINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_pciint); + void vr41xx_disable_pciint(void) { irq_desc_t *desc = irq_desc + PCI_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(0, MPCIINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(0, MPCIINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_pciint); + void vr41xx_enable_scuint(void) { irq_desc_t *desc = irq_desc + SCU_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(SCUINT0, MSCUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(SCUINT0, MSCUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_scuint); + void vr41xx_disable_scuint(void) { irq_desc_t *desc = irq_desc + SCU_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(0, MSCUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(0, MSCUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_scuint); + void vr41xx_enable_csiint(uint16_t mask) { irq_desc_t *desc = irq_desc + CSI_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu2(MCSIINTREG); - val |= mask; - write_icu2(val, MCSIINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + set_icu2(MCSIINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_csiint); + void vr41xx_disable_csiint(uint16_t mask) { irq_desc_t *desc = irq_desc + CSI_IRQ; unsigned long flags; - uint16_t val; - spin_lock_irqsave(&desc->lock, flags); - val = read_icu2(MCSIINTREG); - val &= ~mask; - write_icu2(val, MCSIINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + clear_icu2(MCSIINTREG, mask); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_csiint); + void vr41xx_enable_bcuint(void) { irq_desc_t *desc = irq_desc + BCU_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(BCUINTR, MBCUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(BCUINTR, MBCUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_enable_bcuint); + void vr41xx_disable_bcuint(void) { irq_desc_t *desc = irq_desc + BCU_IRQ; unsigned long flags; - spin_lock_irqsave(&desc->lock, flags); - write_icu2(0, MBCUINTREG); - spin_unlock_irqrestore(&desc->lock, flags); + if (current_cpu_data.cputype == CPU_VR4122 || + current_cpu_data.cputype == CPU_VR4131 || + current_cpu_data.cputype == CPU_VR4133) { + spin_lock_irqsave(&desc->lock, flags); + write_icu2(0, MBCUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); + } } +EXPORT_SYMBOL(vr41xx_disable_bcuint); + /*=======================================================================*/ static unsigned int startup_sysint1_irq(unsigned int irq) @@ -674,8 +730,6 @@ early_initcall(vr41xx_icu_init); /*=======================================================================*/ -static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL}; - static inline void init_vr41xx_icu_irq(void) { int i; @@ -693,11 +747,8 @@ static inline void init_vr41xx_icu_irq(void) setup_irq(INT4_CASCADE_IRQ, &icu_cascade); } -void __init init_IRQ(void) +void __init arch_init_irq(void) { - memset(irq_desc, 0, sizeof(irq_desc)); - - init_generic_irq(); mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); init_vr41xx_icu_irq(); init_vr41xx_giuint_irq(); diff --git a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c index cc445eeff..939ac827e 100644 --- a/arch/mips/vr41xx/common/serial.c +++ b/arch/mips/vr41xx/common/serial.c @@ -115,7 +115,7 @@ void __init vr41xx_siu_init(void) port.line = vr41xx_serial_ports; port.uartclk = SIU_BASE_BAUD * 16; port.irq = SIU_IRQ; - port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: @@ -160,7 +160,7 @@ void __init vr41xx_dsiu_init(void) port.line = vr41xx_serial_ports; port.uartclk = DSIU_BASE_BAUD * 16; port.irq = DSIU_IRQ; - port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; port.mapbase = DSIU_BASE; port.regshift = 0; port.iotype = UPIO_MEM; diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c index 3b006358c..080ad4000 100644 --- a/arch/mips/vr41xx/common/vrc4173.c +++ b/arch/mips/vr41xx/common/vrc4173.c @@ -56,6 +56,9 @@ MODULE_LICENSE("GPL"); #define VRC4173_SYSINT1REG 0x060 #define VRC4173_MSYSINT1REG 0x06c +#define VRC4173_MPIUINTREG 0x06e +#define VRC4173_MAIUINTREG 0x070 +#define VRC4173_MKIUINTREG 0x072 #define VRC4173_SELECTREG 0x09e #define SEL3 0x0008 @@ -316,6 +319,96 @@ static inline void vrc4173_giu_init(void) spin_lock_init(&vrc4173_giu_lock); } +void vrc4173_enable_piuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MPIUINTREG); + val |= mask; + vrc4173_outw(val, VRC4173_MPIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_enable_piuint); + +void vrc4173_disable_piuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MPIUINTREG); + val &= ~mask; + vrc4173_outw(val, VRC4173_MPIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_disable_piuint); + +void vrc4173_enable_aiuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MAIUINTREG); + val |= mask; + vrc4173_outw(val, VRC4173_MAIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_enable_aiuint); + +void vrc4173_disable_aiuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MAIUINTREG); + val &= ~mask; + vrc4173_outw(val, VRC4173_MAIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_disable_aiuint); + +void vrc4173_enable_kiuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MKIUINTREG); + val |= mask; + vrc4173_outw(val, VRC4173_MKIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_enable_kiuint); + +void vrc4173_disable_kiuint(uint16_t mask) +{ + irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ; + unsigned long flags; + uint16_t val; + + spin_lock_irqsave(&desc->lock, flags); + val = vrc4173_inw(VRC4173_MKIUINTREG); + val &= ~mask; + vrc4173_outw(val, VRC4173_MKIUINTREG); + spin_unlock_irqrestore(&desc->lock, flags); +} + +EXPORT_SYMBOL(vrc4173_disable_kiuint); + static void enable_vrc4173_irq(unsigned int irq) { uint16_t val; diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 9e37d3dfe..4bdec1e0f 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -106,7 +106,7 @@ config PARISC64 depends on PA8X00 help Enable this if you want to support 64bit kernel on PA-RISC platform. - + At the moment, only people willing to use more than 2GB of RAM, or having a 64bit-only capable PA-RISC machine should say Y here. @@ -188,76 +188,10 @@ source "fs/Kconfig" source "arch/parisc/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_RWLOCK - bool "Read-write spinlock debugging" - depends on DEBUG_KERNEL && SMP - help - If you say Y here then read-write lock processing will count how many - times it has tried to get the lock and issue an error message after - too many attempts. If you suspect a rwlock problem or a kernel - hacker asks for this option then say Y. Otherwise say N. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -endmenu +source "arch/parisc/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index b59911f2c..17ecb61c4 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -37,8 +37,10 @@ cflags-y := -pipe # are not in gcc 3.2. cflags-y += -mno-space-regs -mfast-indirect-calls -# No fixed-point multiply -cflags-y += -mdisable-fpregs +# Currently we save and restore fpregs on all kernel entry/interruption paths. +# If that gets optimized, we might need to disable the use of fpregs in the +# kernel. +#cflags-y += -mdisable-fpregs # Without this, "ld -r" results in .text sections that are too big # (> 0x40000) for branches to reach stubs. @@ -52,7 +54,6 @@ cflags-$(CONFIG_PA7300LC) += -march=1.1 -mschedule=7300 cflags-$(CONFIG_PA8X00) += -march=2.0 -mschedule=8000 head-y := arch/parisc/kernel/head.o -head-$(CONFIG_PARISC64) := arch/parisc/kernel/head64.o CFLAGS += $(cflags-y) @@ -86,6 +87,12 @@ oldpalo: vmlinux # Shorthands for known targets not supported by parisc, use palo as default Image zImage bzImage: palo +kernel_install: vmlinux + sh $(src)/arch/parisc/install.sh \ + $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" + +install: kernel_install modules_install + prepare: include/asm-parisc/offsets.h arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \ @@ -100,4 +107,8 @@ MRPROPER_FILES += palo.conf define archhelp @echo '* vmlinux - Uncompressed kernel image (./vmlinux)' @echo ' palo - Bootable image (./lifimage)' + @echo ' install - Install kernel using' + @echo ' (your) ~/bin/installkernel or' + @echo ' (distribution) /sbin/installkernel or' + @echo ' copy to $$(INSTALL_PATH)' endef diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index 276fc0d17..e5c57399e 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -11,7 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set -# CONFIG_STANDALONE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y @@ -31,6 +30,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -48,6 +48,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y # # Processor type and features @@ -61,9 +62,12 @@ CONFIG_PA20=y CONFIG_PREFETCH=y CONFIG_PARISC64=y CONFIG_64BIT=y -# CONFIG_SMP is not set +CONFIG_SMP=y +CONFIG_HOTPLUG_CPU=y +# CONFIG_DISCONTIGMEM is not set # CONFIG_PREEMPT is not set CONFIG_COMPAT=y +CONFIG_NR_CPUS=4 # # Bus options (PCI, PCMCIA, EISA, GSC, ISA) @@ -86,6 +90,7 @@ CONFIG_PCMCIA=m CONFIG_PCMCIA_DEBUG=y CONFIG_YENTA=m CONFIG_CARDBUS=y +# CONFIG_PD6729 is not set # CONFIG_I82092 is not set # CONFIG_TCIC is not set @@ -107,6 +112,8 @@ CONFIG_BINFMT_ELF=y # # Generic Driver Options # +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set CONFIG_DEBUG_DRIVER=y @@ -135,7 +142,7 @@ CONFIG_BLK_DEV_UMEM=m CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=6144 CONFIG_BLK_DEV_INITRD=y @@ -165,7 +172,6 @@ CONFIG_CHR_DEV_SG=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -179,6 +185,7 @@ CONFIG_SCSI_FC_ATTRS=m # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set @@ -353,6 +360,8 @@ CONFIG_IP_NF_ARP_MANGLE=m # CONFIG_IP_NF_COMPAT_IPFWADM is not set CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -379,6 +388,7 @@ CONFIG_LLC2=m # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -452,6 +462,7 @@ CONFIG_EPIC100=m # CONFIG_SUNDANCE is not set CONFIG_VIA_RHINE=m CONFIG_VIA_RHINE_MMIO=y +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -501,7 +512,6 @@ CONFIG_PCMCIA_NETWAVE=m # # Wireless 802.11b ISA/PCI cards support # -# CONFIG_AIRO is not set CONFIG_HERMES=m CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m @@ -644,7 +654,6 @@ CONFIG_GEN_RTC_X=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set @@ -660,6 +669,11 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -734,6 +748,7 @@ CONFIG_ISO9660_FS=y CONFIG_JOLIET=y # CONFIG_ZISOFS is not set CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -741,6 +756,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -795,6 +812,9 @@ CONFIG_SMB_FS=m CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -833,6 +853,7 @@ CONFIG_NLS_CODEPAGE_865=m # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m @@ -860,6 +881,8 @@ CONFIG_OPROFILE=m CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_RWLOCK is not set # CONFIG_FRAME_POINTER is not set # CONFIG_DEBUG_INFO is not set @@ -886,7 +909,9 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +# CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set CONFIG_CRYPTO_CRC32C=m @@ -895,6 +920,7 @@ CONFIG_CRYPTO_TEST=m # # Library routines # +CONFIG_CRC_CCITT=m CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index 0800eb3ea..d7c80edf4 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c @@ -43,8 +43,11 @@ int hpux_execve(struct pt_regs *regs) error = do_execve(filename, (char **) regs->gr[25], (char **)regs->gr[24], regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index b032c6b79..04cbd5cb6 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -2,9 +2,7 @@ # Makefile for arch/parisc/kernel # -head-y := head.o -head-$(CONFIG_PARISC64) := head64.o -extra-y := init_task.o $(head-y) vmlinux.lds.s +extra-y := init_task.o head.o vmlinux.lds AFLAGS_entry.o := -traditional AFLAGS_pacache.o := -traditional @@ -14,7 +12,8 @@ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ ptrace.o hardware.o inventory.o drivers.o semaphore.o \ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ - process.o processor.o pdc_cons.o pdc_chassis.o unwind.o + process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ + topology.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_PA11) += pci-dma.o diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index 64d49cb2d..1ad44f92d 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -32,12 +32,13 @@ #include #include #include -#include +#include +#include #include #include -#include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -291,5 +292,8 @@ int main(void) DEFINE(ASM_PT_INITIAL, PT_INITIAL); DEFINE(ASM_PAGE_SIZE, PAGE_SIZE); BLANK(); + DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); + DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); + DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); return 0; } diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index eadc88c5a..359e90bfa 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -33,6 +33,17 @@ int dcache_stride; int icache_stride; EXPORT_SYMBOL(dcache_stride); + +#if defined(CONFIG_SMP) +/* On some machines (e.g. ones with the Merced bus), there can be + * only a single PxTLB broadcast at a time; this must be guaranteed + * by software. We put a spinlock around all TLB flushes to + * ensure this. + */ +spinlock_t pa_tlb_lock = SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL(pa_tlb_lock); +#endif + struct pdc_cache_info cache_info; #ifndef CONFIG_PA20 static struct pdc_btlb_info btlb_info; @@ -245,7 +256,7 @@ void disable_sr_hashing(void) void flush_dcache_page(struct page *page) { struct address_space *mapping = page_mapping(page); - struct vm_area_struct *mpnt = NULL; + struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; unsigned long addr; @@ -272,8 +283,7 @@ void flush_dcache_page(struct page *page) * to flush one address here for them all to become coherent */ flush_dcache_mmap_lock(mapping); - while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, - &iter, pgoff, pgoff)) != NULL) { + vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) { offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; @@ -307,3 +317,13 @@ EXPORT_SYMBOL(flush_kernel_dcache_range_asm); EXPORT_SYMBOL(flush_kernel_dcache_page); EXPORT_SYMBOL(flush_data_cache_local); EXPORT_SYMBOL(flush_kernel_icache_range_asm); + +void clear_user_page_asm(void *page, unsigned long vaddr) +{ + /* This function is implemented in assembly in pacache.S */ + extern void __clear_user_page_asm(void *page, unsigned long vaddr); + + purge_tlb_start(); + __clear_user_page_asm(page, vaddr); + purge_tlb_end(); +} diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index baee63278..b1dd08b03 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -440,8 +440,17 @@ mfctl %cr25,\reg .endm - /* Only allow faults on different spaces from the - * currently active one if we're the kernel */ + /* + space_check(spc,tmp,fault) + + spc - The space we saw the fault with. + tmp - The place to store the current space. + fault - Function to call on failure. + + Only allow faults on different spaces from the + currently active one if we're the kernel + + */ .macro space_check spc,tmp,fault mfsp %sr7,\tmp or,COND(<>) %r0,\spc,%r0 /* user may execute gateway page @@ -774,7 +783,7 @@ __kernel_thread: #ifdef __LP64__ ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl do_fork, %r2 + BL do_fork, %r2 copy %r1, %r24 /* pt_regs */ /* Parent Returns here */ @@ -827,7 +836,7 @@ __execve: #ifdef __LP64__ ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl sys_execve, %r2 + BL sys_execve, %r2 copy %r16, %r26 cmpib,=,n 0,%r28,intr_return /* forward */ @@ -939,6 +948,7 @@ syscall_exit_rfi: STREG %r19,PT_SR7(%r16) intr_return: + /* NOTE: Need to enable interrupts incase we schedule. */ ssm PSW_SM_I, %r0 /* Check for software interrupts */ @@ -982,6 +992,8 @@ intr_restore: ldo PT_FR31(%r29),%r1 rest_fp %r1 rest_general %r29 + + /* Create a "relied upon translation" PA 2.0 Arch. F-5 */ ssm 0,%r0 nop nop @@ -992,8 +1004,15 @@ intr_restore: nop tophys_r1 %r29 rsm (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0 + + /* Restore space id's and special cr's from PT_REGS + * structure pointed to by r29 */ rest_specials %r29 + + /* Important: Note that rest_stack restores r29 + * last (we are using it)! It also restores r1 and r30. */ rest_stack + rfi nop nop @@ -1036,7 +1055,14 @@ intr_do_resched: .import do_signal,code intr_do_signal: - /* Only do signals if we are returning to user space */ + /* + This check is critical to having LWS + working. The IASQ is zero on the gateway + page and we cannot deliver any signals until + we get off the gateway page. + + Only do signals if we are returning to user space + */ LDREG PT_IASQ0(%r16), %r20 CMPIB= 0,%r20,intr_restore /* backward */ nop @@ -1050,7 +1076,7 @@ intr_do_signal: ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl do_signal,%r2 + BL do_signal,%r2 copy %r0, %r26 /* sigset_t *oldset = NULL */ b intr_restore @@ -1443,15 +1469,20 @@ nadtlb_emulate: * of the instruction. Since we don't insert a translation * we can get a lot of faults during a flush loop, so it makes * sense to try to do it here with minimum overhead. We only - * emulate fdc,fic & pdc instructions whose base and index - * registers are not shadowed. We defer everything else to the - * "slow" path. + * emulate fdc,fic,pdc,probew,prober instructions whose base + * and index registers are not shadowed. We defer everything + * else to the "slow" path. */ mfctl %cr19,%r9 /* Get iir */ + + /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits. + Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */ + + /* Checks for fdc,fdce,pdc,"fic,4f" only */ ldi 0x280,%r16 and %r9,%r16,%r17 - cmpb,<>,n %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */ + cmpb,<>,n %r16,%r17,nadtlb_probe_check bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ BL get_register,%r25 extrw,u %r9,15,5,%r8 /* Get index register # */ @@ -1472,6 +1503,32 @@ nadtlb_nullify: rfir nop + /* + When there is no translation for the probe address then we + must nullify the insn and return zero in the target regsiter. + This will indicate to the calling code that it does not have + write/read privileges to this address. + + This should technically work for prober and probew in PA 1.1, + and also probe,r and probe,w in PA 2.0 + + WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN! + THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET. + + */ +nadtlb_probe_check: + ldi 0x80,%r16 + and %r9,%r16,%r17 + cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/ + BL get_register,%r25 /* Find the target register */ + extrw,u %r9,31,5,%r8 /* Get target register */ + CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + BL set_register,%r25 + copy %r0,%r1 /* Write zero to target register */ + b nadtlb_nullify /* Nullify return insn */ + nop + + #ifdef __LP64__ itlb_miss_20w: @@ -1762,7 +1819,7 @@ sys_fork_wrapper: LDREG PT_GR30(%r1),%r25 copy %r1,%r24 - bl sys_clone,%r2 + BL sys_clone,%r2 ldi SIGCHLD,%r26 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 @@ -1782,7 +1839,7 @@ wrapper_exit: /* Set the return value for the child */ child_return: - bl schedule_tail, %r2 + BL schedule_tail, %r2 nop LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 @@ -1807,7 +1864,7 @@ sys_clone_wrapper: STREG %r2,PT_GR19(%r1) /* save for child */ STREG %r30,PT_GR21(%r1) - bl sys_clone,%r2 + BL sys_clone,%r2 copy %r1,%r24 b wrapper_exit @@ -1830,7 +1887,7 @@ sys_vfork_wrapper: STREG %r2,PT_GR19(%r1) /* save for child */ STREG %r30,PT_GR21(%r1) - bl sys_vfork,%r2 + BL sys_vfork,%r2 copy %r1,%r26 b wrapper_exit @@ -1893,10 +1950,10 @@ sys_rt_sigreturn_wrapper: STREG %r2, -RP_OFFSET(%r30) #ifdef __LP64__ ldo FRAME_SIZE(%r30), %r30 - bl sys_rt_sigreturn,%r2 + BL sys_rt_sigreturn,%r2 ldo -16(%r30),%r29 /* Reference param save area */ #else - bl sys_rt_sigreturn,%r2 + BL sys_rt_sigreturn,%r2 ldo FRAME_SIZE(%r30), %r30 #endif @@ -1924,7 +1981,7 @@ sys_sigaltstack_wrapper: STREG %r2, -RP_OFFSET(%r30) #ifdef __LP64__ ldo FRAME_SIZE(%r30), %r30 - bl do_sigaltstack,%r2 + b,l do_sigaltstack,%r2 ldo -16(%r30),%r29 /* Reference param save area */ #else bl do_sigaltstack,%r2 @@ -1944,7 +2001,7 @@ sys32_sigaltstack_wrapper: LDREG TASK_PT_GR30(%r24),%r24 STREG %r2, -RP_OFFSET(%r30) ldo FRAME_SIZE(%r30), %r30 - bl do_sigaltstack32,%r2 + b,l do_sigaltstack32,%r2 ldo -16(%r30),%r29 /* Reference param save area */ ldo -FRAME_SIZE(%r30), %r30 @@ -1962,7 +2019,7 @@ sys_rt_sigsuspend_wrapper: STREG %r2, -RP_OFFSET(%r30) #ifdef __LP64__ ldo FRAME_SIZE(%r30), %r30 - bl sys_rt_sigsuspend,%r2 + b,l sys_rt_sigsuspend,%r2 ldo -16(%r30),%r29 /* Reference param save area */ #else bl sys_rt_sigsuspend,%r2 @@ -1981,9 +2038,11 @@ sys_rt_sigsuspend_wrapper: .export syscall_exit syscall_exit: + /* NOTE: HP-UX syscalls also come through here - after hpux_syscall_exit fixes up return - values. */ + * after hpux_syscall_exit fixes up return + * values. */ + /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit * via syscall_exit_rfi if the signal was received while the process * was running. @@ -2082,11 +2141,15 @@ syscall_restore: LDREG TASK_PT_GR29(%r1),%r29 LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */ + /* NOTE: We use rsm/ssm pair to make this operation atomic */ rsm PSW_SM_I, %r0 LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ mfsp %sr3,%r1 /* Get users space id */ mtsp %r1,%sr7 /* Restore sr7 */ ssm PSW_SM_I, %r0 + + /* Set sr2 to zero for userspace syscalls to work. */ + mtsp %r0,%sr2 mtsp %r1,%sr4 /* Restore sr4 */ mtsp %r1,%sr5 /* Restore sr5 */ mtsp %r1,%sr6 /* Restore sr6 */ @@ -2154,12 +2217,18 @@ syscall_restore_rfi: bb,< %r2,30,pt_regs_ok /* Branch if D set */ ldo TASK_REGS(%r1),%r25 reg_save %r25 /* Save r3 to r18 */ + + /* Save the current sr */ mfsp %sr0,%r2 STREG %r2,TASK_PT_SR0(%r1) + + /* Save the scratch sr */ mfsp %sr1,%r2 STREG %r2,TASK_PT_SR1(%r1) - mfsp %sr2,%r2 - STREG %r2,TASK_PT_SR2(%r1) + + /* sr2 should be set to zero for userspace syscalls */ + STREG %r0,TASK_PT_SR2(%r1) + pt_regs_ok: LDREG TASK_PT_GR31(%r1),%r2 depi 3,31,2,%r2 /* ensure return to user mode. */ @@ -2174,12 +2243,15 @@ pt_regs_ok: syscall_do_softirq: bl do_softirq,%r2 nop + /* NOTE: We enable I-bit incase we schedule later, + * and we might be going back to userspace if we were + * traced. */ b syscall_check_resched ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */ .import schedule,code syscall_do_resched: - bl schedule,%r2 + BL schedule,%r2 #ifdef __LP64__ ldo -16(%r30),%r29 /* Reference param save area */ #else @@ -2203,7 +2275,7 @@ syscall_do_signal: #ifdef __LP64__ ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl do_signal,%r2 + BL do_signal,%r2 copy %r0, %r26 /* sigset_t *oldset = NULL */ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 6ab67aadd..be67248a1 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1276,7 +1276,7 @@ struct wide_stack { long real64_call(unsigned long fn, ...) { va_list args; - extern struct wide_stack real64_stack __attribute__ ((alias ("real_stack"))); + extern struct wide_stack real64_stack; extern unsigned long real64_call_asm(unsigned long *, unsigned long *, unsigned long); diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index 6b65bf468..4abd43910 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -7,7 +7,7 @@ * Reference Specification", March 7, 1999, version 0.96. This * is available at http://parisc-linux.org/documentation/ * - * Copyright 1999 by Alex deVries + * Copyright 1999 by Alex deVries * and copyright 1999 The Puffin Group Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index a3525f1e5..1fb4c05c3 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -1,12 +1,13 @@ -/* - * - * This file is subject to the terms and conditions of the GNU General Public +/* This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1999 by Helge Deller * Copyright 1999 SuSE GmbH (Philipp Rumpf) * Copyright 1999 Philipp Rumpf (prumpf@tux.org) + * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com) + * Copyright (C) 2001 Grant Grundler (Hewlett Packard) + * Copyright (C) 2004 Kyle McMartin * * Initial Version 04-23-1999 by Helge Deller */ @@ -15,12 +16,12 @@ #include #include - +#include + #include #include - - .level 1.1 + .level LEVEL .data @@ -32,12 +33,13 @@ boot_args: .word 0 /* arg3 */ .text - .align 4 + .align 4 .import init_thread_union,data + .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ +#ifndef __LP64__ + .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ .import $global$ /* forward declaration */ - .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ - .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ - +#endif /*!LP64*/ .export stext .export _stext,data /* Kernel want it this way! */ _stext: @@ -56,72 +58,84 @@ stext: .import __bss_start,data .import __bss_stop,data - ldil L%PA(__bss_start),%r3 - ldo R%PA(__bss_start)(%r3),%r3 - ldil L%PA(__bss_stop),%r4 - ldo R%PA(__bss_stop)(%r4),%r4 + load32 PA(__bss_start),%r3 + load32 PA(__bss_stop),%r4 $bss_loop: cmpb,<<,n %r3,%r4,$bss_loop stw,ma %r0,4(%r3) /* Save away the arguments the boot loader passed in (32 bit args) */ - - ldil L%PA(boot_args),%r1 - ldo R%PA(boot_args)(%r1),%r1 + load32 PA(boot_args),%r1 stw,ma %arg0,4(%r1) stw,ma %arg1,4(%r1) stw,ma %arg2,4(%r1) stw,ma %arg3,4(%r1) /* Initialize startup VM. Just map first 8 MB of memory */ - ldil L%PA(pg0),%r1 - ldo R%PA(pg0)(%r1),%r1 - shr %r1,PxD_VALUE_SHIFT,%r3 - ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 + load32 PA(pg0),%r1 - ldil L%PA(swapper_pg_dir),%r4 - ldo R%PA(swapper_pg_dir)(%r4),%r4 +#ifdef __LP64__ + load32 PA(pmd0),%r5 + shrd %r5,PxD_VALUE_SHIFT,%r3 +#else + shr %r1,PxD_VALUE_SHIFT,%r3 +#endif + ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 + + load32 PA(swapper_pg_dir),%r4 mtctl %r4,%cr24 /* Initialize kernel root pointer */ mtctl %r4,%cr25 /* Initialize user root pointer */ + +#ifdef __LP64__ + stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4) + shrd %r1,PxD_VALUE_SHIFT,%r3 + ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 + ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r5 +#else + ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4 +#endif ldi ASM_PT_INITIAL,%r1 - ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4 + 1: +#ifdef __LP64__ + stw %r3,0(%r5) +#else stw %r3,0(%r4) +#endif + ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3 addib,> -1,%r1,1b + +#ifdef __LP64__ + ldo ASM_PMD_ENTRY_SIZE(%r5),%r5 +#else ldo ASM_PGD_ENTRY_SIZE(%r4),%r4 +#endif ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ - ldil L%PA(pg0),%r1 - ldo R%PA(pg0)(%r1),%r1 + load32 PA(pg0),%r1 + $pgt_fill_loop: - stwm %r3,ASM_PTE_ENTRY_SIZE(%r1) + STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) ldo ASM_PAGE_SIZE(%r3),%r3 bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop nop - /* Load the return address...er...crash 'n burn */ copy %r0,%r2 /* And the RFI Target address too */ - ldil L%start_kernel,%r11 - ldo R%start_kernel(%r11),%r11 + load32 start_kernel,%r11 /* And the initial task pointer */ - - ldil L%init_thread_union,%r6 - ldo R%init_thread_union(%r6),%r6 + load32 init_thread_union,%r6 mtctl %r6,%cr30 /* And the stack pointer too */ - ldo THREAD_SZ_ALGN(%r6),%sp /* And the interrupt stack */ - - ldil L%interrupt_stack,%r6 - ldo R%interrupt_stack(%r6),%r6 + load32 interrupt_stack,%r6 mtctl %r6,%cr31 #ifdef CONFIG_SMP @@ -130,8 +144,7 @@ $pgt_fill_loop: ** it's just way easier to deal with here because ** of 64-bit function ptrs and the address is local to this file. */ - ldil L%PA(smp_slave_stext),%r10 - ldo R%PA(smp_slave_stext)(%r10),%r10 + load32 PA(smp_slave_stext),%r10 stw %r10,0x10(%r0) /* MEM_RENDEZ */ stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */ @@ -141,10 +154,16 @@ $pgt_fill_loop: /* ** Code Common to both Monarch and Slave processors. ** Entry: + ** + ** 1.1: ** %r11 must contain RFI target address. ** %r25/%r26 args to pass to target function ** %r2 in case rfi target decides it didn't like something ** + ** 2.0w: + ** %r3 PDCE_PROC address + ** %r11 RFI target address + ** ** Caller must init: SR4-7, %sp, %r10, %cr24/25, */ common_stext: @@ -154,8 +173,50 @@ common_stext: /* Clear PDC entry point - we won't use it */ stw %r0,0x10(%r0) /* MEM_RENDEZ */ stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */ -#endif +#endif /*CONFIG_SMP*/ + +#ifdef __LP64__ + tophys_r1 %sp + /* Save the rfi target address */ + ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 + tophys_r1 %r10 + std %r11, TASK_PT_GR11(%r10) + /* Switch to wide mode Superdome doesn't support narrow PDC + ** calls. + */ +1: mfia %rp /* clear upper part of pcoq */ + ldo 2f-1b(%rp),%rp + depdi 0,31,32,%rp + bv (%rp) + ssm PSW_SM_W,%r0 + + /* Set Wide mode as the "Default" (eg for traps) + ** First trap occurs *right* after (or part of) rfi for slave CPUs. + ** Someday, palo might not do this for the Monarch either. + */ +2: +#define MEM_PDC_LO 0x388 +#define MEM_PDC_HI 0x35C + ldw MEM_PDC_LO(%r0),%r3 + ldw MEM_PDC_HI(%r0),%r6 + depd %r6, 31, 32, %r3 /* move to upper word */ + + ldo PDC_PSW(%r0),%arg0 /* 21 */ + ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ + ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ + load32 PA(stext_pdc_ret), %rp + bv (%r3) + copy %r0,%arg3 + +stext_pdc_ret: + /* restore rfi target address*/ + ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 + tophys_r1 %r10 + ldd TASK_PT_GR11(%r10), %r11 + tovirt_r1 %sp +#endif + /* PARANOID: clear user scratch/user space SR's */ mtsp %r0,%sr0 mtsp %r0,%sr1 @@ -168,17 +229,18 @@ common_stext: mtctl %r0,%cr12 mtctl %r0,%cr13 + /* Prepare to RFI! Man all the cannons! */ + /* Initialize the global data pointer */ - ldil L%$global$,%dp - ldo R%$global$(%dp),%dp + loadgp - /* - * Set up our interrupt table. HPMCs might not work after this! + /* Set up our interrupt table. HPMCs might not work after this! * * We need to install the correct iva for PA1.1 or PA2.0. The * following short sequence of instructions can determine this * (without being illegal on a PA1.1 machine). */ +#ifndef __LP64__ ldi 32,%r10 mtctl %r10,%cr11 .level 2.0 @@ -190,14 +252,39 @@ common_stext: ldo R%PA(fault_vector_11)(%r10),%r10 $is_pa20: - ldil L%PA(fault_vector_20),%r10 - ldo R%PA(fault_vector_20)(%r10),%r10 + .level LEVEL /* restore 1.1 || 2.0w */ +#endif /*!LP64*/ + load32 PA(fault_vector_20),%r10 $install_iva: mtctl %r10,%cr14 - /* Disable Q bit so we can load the iia queue */ - rsm PSW_SM_Q,%r0 +#ifdef __LP64__ + b aligned_rfi + nop + + .align 256 +aligned_rfi: + ssm 0,0 + nop /* 1 */ + nop /* 2 */ + nop /* 3 */ + nop /* 4 */ + nop /* 5 */ + nop /* 6 */ + nop /* 7 */ + nop /* 8 */ +#endif + +#ifdef __LP64__ /* move to psw.h? */ +#define PSW_BITS PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R +#else +#define PSW_BITS PSW_SM_Q +#endif + +$rfi: + /* turn off troublesome PSW bits */ + rsm PSW_BITS,%r0 /* kernel PSW: * - no interruptions except HPMC and TOC (which are handled by PDC) @@ -205,8 +292,7 @@ $install_iva: * - big-endian * - virtually mapped */ - ldil L%KERNEL_PSW,%r10 - ldo R%KERNEL_PSW(%r10),%r10 + load32 KERNEL_PSW,%r10 mtctl %r10,%ipsw /* Set the space pointers for the post-RFI world @@ -232,6 +318,7 @@ $install_iva: .import smp_init_current_idle_task,data .import smp_callin,code +#ifndef __LP64__ smp_callin_rtn: .proc .callinfo @@ -239,9 +326,9 @@ smp_callin_rtn: nop nop .procend +#endif /*!LP64*/ /*************************************************************************** -* * smp_slave_stext is executed by all non-monarch Processors when the Monarch * pokes the slave CPUs in smp.c:smp_boot_cpus(). * @@ -249,8 +336,6 @@ smp_callin_rtn: * mode. Once all available/eligible CPUs are in virtual mode, all are * released and start out by executing their own idle task. *****************************************************************************/ - - smp_slave_stext: .proc .callinfo @@ -264,28 +349,28 @@ smp_slave_stext: mtsp %r0,%sr7 /* Initialize the SP - monarch sets up smp_init_current_idle_task */ - ldil L%PA(smp_init_current_idle_task),%sp - ldo R%PA(smp_init_current_idle_task)(%sp),%sp - ldw 0(%sp),%sp /* load task address */ + load32 PA(smp_init_current_idle_task),%sp + LDREG 0(%sp),%sp /* load task address */ tophys_r1 %sp - ldw TASK_THREAD_INFO(%sp), %sp + LDREG TASK_THREAD_INFO(%sp),%sp mtctl %sp,%cr30 /* store in cr30 */ - addil L%THREAD_SZ_ALGN,%sp /* stack is above task */ - ldo R%THREAD_SZ_ALGN(%r1),%sp + ldo THREAD_SZ_ALGN(%sp),%sp /* point CPU to kernel page tables */ - ldil L%PA(swapper_pg_dir),%r4 - ldo R%PA(swapper_pg_dir)(%r4),%r4 + load32 PA(swapper_pg_dir),%r4 mtctl %r4,%cr24 /* Initialize kernel root pointer */ mtctl %r4,%cr25 /* Initialize user root pointer */ +#ifdef __LP64__ + /* Setup PDCE_PROC entry */ + copy %arg0,%r3 +#else /* Load RFI *return* address in case smp_callin bails */ - ldil L%smp_callin_rtn,%r2 - ldo R%smp_callin_rtn(%r2),%r2 - + load32 smp_callin_rtn,%r2 +#endif + /* Load RFI target address. */ - ldil L%smp_callin,%r11 - ldo R%smp_callin(%r11),%r11 + load32 smp_callin,%r11 /* ok...common code can handle the rest */ b common_stext @@ -293,7 +378,7 @@ smp_slave_stext: .procend #endif /* CONFIG_SMP */ - +#ifndef __LP64__ .data .align 4 @@ -303,3 +388,4 @@ smp_slave_stext: .size $global$,4 $global$: .word 0 +#endif /*!LP64*/ diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index bc96fd28e..c028480b8 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -68,7 +68,7 @@ flush_tlb_all_local: * consolidated. */ - rsm PSW_SM_I,%r19 /* relied upon translation! */ + rsm PSW_SM_I,%r19 /* relied upon translation! PA 2.0 Arch. F-5 */ nop nop nop @@ -475,9 +475,9 @@ copy_user_page_asm: .procend #endif - .export clear_user_page_asm,code + .export __clear_user_page_asm,code -clear_user_page_asm: +__clear_user_page_asm: .proc .callinfo NO_CALLS .entry diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index dadcf1359..1ac65cffb 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -32,7 +32,6 @@ #include EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(memset); @@ -65,13 +64,20 @@ EXPORT_SYMBOL(__cmpxchg_u64); #endif #include -EXPORT_SYMBOL(lcopy_to_user); -EXPORT_SYMBOL(lcopy_from_user); -EXPORT_SYMBOL(lcopy_in_user); EXPORT_SYMBOL(lstrncpy_from_user); EXPORT_SYMBOL(lclear_user); EXPORT_SYMBOL(lstrnlen_user); +/* Global fixups */ +extern void fixup_get_user_skip_1(void); +extern void fixup_get_user_skip_2(void); +extern void fixup_put_user_skip_1(void); +extern void fixup_put_user_skip_2(void); +EXPORT_SYMBOL(fixup_get_user_skip_1); +EXPORT_SYMBOL(fixup_get_user_skip_2); +EXPORT_SYMBOL(fixup_put_user_skip_1); +EXPORT_SYMBOL(fixup_put_user_skip_2); + #ifndef __LP64__ /* Needed so insmod can set dp value */ extern int $global$; diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index ebbcbf295..07850b6e1 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -104,7 +104,9 @@ static inline int map_pte_uncached(pte_t * pte, if (!pte_none(*pte)) printk(KERN_ERR "map_pte_uncached: page already exists\n"); set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); + purge_tlb_start(); pdtlb_kernel(orig_vaddr); + purge_tlb_end(); vaddr += PAGE_SIZE; orig_vaddr += PAGE_SIZE; (*paddr_ptr) += PAGE_SIZE; @@ -179,7 +181,9 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr, do { pte_t page = *pte; pte_clear(pte); + purge_tlb_start(); pdtlb_kernel(orig_vaddr); + purge_tlb_end(); vaddr += PAGE_SIZE; orig_vaddr += PAGE_SIZE; pte++; diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 937ab23ca..3cb08a4a5 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -146,15 +146,6 @@ char *pcibios_setup(char *str) return str; } -/* Used in drivers/pci/quirks.c */ -struct pci_fixup pcibios_fixups[] = { -#ifdef CONFIG_SUPERIO - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci }, -#endif - { 0 } -}; - - /* * Called by pci_set_master() - a driver interface. * diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c index 8072e384e..01f676d16 100644 --- a/arch/parisc/kernel/pdc_cons.c +++ b/arch/parisc/kernel/pdc_cons.c @@ -71,6 +71,19 @@ void pdc_outc(unsigned char c) pdc_iodc_outc(c); } +void pdc_printf(const char *fmt, ...) +{ + va_list args; + char buf[1024]; + int i, len; + + va_start(args, fmt); + len = vscnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for (i = 0; i < len; i++) + pdc_iodc_outc(buf[i]); +} int pdc_console_poll_key(struct console *co) { diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S index 884be8750..87993ae27 100644 --- a/arch/parisc/kernel/perf_asm.S +++ b/arch/parisc/kernel/perf_asm.S @@ -1,18 +1,19 @@ /* low-level asm for "intrigue" (PA8500-8700 CPU perf counters) - * + * * Copyright (C) 2001 Randolph Chung - * + * Copyright (C) 2001 Hewlett-Packard (Grant Grundler) + * * 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 @@ -48,7 +49,7 @@ perf_intrigue_enable_perf_counters: .proc .callinfo frame=0,NO_CALLS .entry - + ldi 0x20,%r25 ; load up perfmon bit mfctl ccr,%r26 ; get coprocessor register or %r25,%r26,%r26 ; set bit @@ -87,35 +88,35 @@ perf_intrigue_disable_perf_counters: .exit .procend -;************************************************************************ -;* * -;* Name: perf_rdr_shift_in_W * -;* * -;* Description: * -;* This routine shifts data in from the RDR in arg0 and returns * -;* the result in ret0. If the RDR is <= 64 bits in length, it * -;* is shifted shifted backup immediately. This is to compensate * -;* for RDR10 which has bits that preclude PDC stack operations * -;* when they are in the wrong state. * -;* * -;* Arguments: * -;* arg0 : rdr to be read * -;* arg1 : bit length of rdr * -;* * -;* Returns: * -;* ret0 = next 64 bits of rdr data from staging register * -;* * -;* Register usage: * -;* arg0 : rdr to be read * -;* arg1 : bit length of rdr * -;* %r24 - original DR2 value * -;* %r1 - scratch * -;* %r29 - scratch * -;* * -;* Returns: * -;* ret0 = RDR data (right justified) * -;* * -;************************************************************************ +;*********************************************************************** +;* +;* Name: perf_rdr_shift_in_W +;* +;* Description: +;* This routine shifts data in from the RDR in arg0 and returns +;* the result in ret0. If the RDR is <= 64 bits in length, it +;* is shifted shifted backup immediately. This is to compensate +;* for RDR10 which has bits that preclude PDC stack operations +;* when they are in the wrong state. +;* +;* Arguments: +;* arg0 : rdr to be read +;* arg1 : bit length of rdr +;* +;* Returns: +;* ret0 = next 64 bits of rdr data from staging register +;* +;* Register usage: +;* arg0 : rdr to be read +;* arg1 : bit length of rdr +;* %r24 - original DR2 value +;* %r1 - scratch +;* %r29 - scratch +;* +;* Returns: +;* ret0 = RDR data (right justified) +;* +;*********************************************************************** .export perf_rdr_shift_in_W,code perf_rdr_shift_in_W: @@ -138,7 +139,7 @@ perf_rdr_shift_in_W: nop nop nop - nop + nop ; ; Cacheline start (32-byte cacheline) @@ -146,11 +147,11 @@ perf_rdr_shift_in_W: nop nop nop - extrd,u arg1,63,6,%r1 ; setup shift amount based on bits to move + extrd,u arg1,63,6,%r1 ; setup shift amount by bits to move mtsar %r1 shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number - blr %r1,%r0 ; branch to 8-instruction sequence + blr %r1,%r0 ; branch to 8-instruction sequence nop ; @@ -160,19 +161,19 @@ perf_rdr_shift_in_W: ; ; RDR 0 sequence ; - SFDIAG (0) + SFDIAG (0) ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 - MTDIAG_1 (1) ; mtdiag %dr1, %r1 + MTDIAG_1 (1) ; mtdiag %dr1, %r1 STDIAG (0) ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 1 sequence ; - sync + sync ssm 0,0 SFDIAG (1) ssm 0,0 @@ -180,11 +181,11 @@ perf_rdr_shift_in_W: ssm 0,0 b,n perf_rdr_shift_in_W_leave nop - + ; ; RDR 2 read sequence ; - SFDIAG (2) + SFDIAG (2) ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 @@ -192,7 +193,7 @@ perf_rdr_shift_in_W: STDIAG (2) ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 3 read sequence ; @@ -208,39 +209,39 @@ perf_rdr_shift_in_W: ; ; RDR 4 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (4) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 5 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (5) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 6 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (6) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 7 read sequence ; @@ -281,26 +282,26 @@ perf_rdr_shift_in_W: ; RDR 10 read sequence ; SFDIAG (10) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (10) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 11 read sequence ; SFDIAG (11) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (11) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 12 read sequence ; @@ -317,77 +318,77 @@ perf_rdr_shift_in_W: ; RDR 13 read sequence ; sync - ssm 0,0 + ssm 0,0 SFDIAG (13) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 14 read sequence ; - SFDIAG (14) - ssm 0,0 + SFDIAG (14) + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (14) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 15 read sequence ; - sync ; RDR 15 read sequence - ssm 0,0 + sync + ssm 0,0 SFDIAG (15) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave nop - + ; ; RDR 16 read sequence ; - sync ; RDR 16 read sequence - ssm 0,0 + sync + ssm 0,0 SFDIAG (16) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 17 read sequence ; - SFDIAG (17) - ssm 0,0 + SFDIAG (17) + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (17) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 18 read sequence ; - SFDIAG (18) - ssm 0,0 + SFDIAG (18) + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (18) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - -; -; RDR 19 read sequence -; + + ; + ; RDR 19 read sequence + ; b,n perf_rdr_shift_in_W_leave nop nop @@ -401,144 +402,144 @@ perf_rdr_shift_in_W: ; RDR 20 read sequence ; sync - ssm 0,0 + ssm 0,0 SFDIAG (20) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 21 read sequence ; sync - ssm 0,0 + ssm 0,0 SFDIAG (21) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 22 read sequence ; sync - ssm 0,0 + ssm 0,0 SFDIAG (22) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 23 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (23) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 24 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (24) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 25 read sequence ; sync - ssm 0,0 + ssm 0,0 SFDIAG (25) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 26 read sequence ; - SFDIAG (26) - ssm 0,0 + SFDIAG (26) + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (26) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 27 read sequence ; SFDIAG (27) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (27) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 28 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (28) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 29 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (29) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_W_leave - ssm 0,0 + ssm 0,0 nop - + ; ; RDR 30 read sequence ; SFDIAG (30) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (30) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_W_leave - + ; ; RDR 31 read sequence ; - sync - ssm 0,0 + sync + ssm 0,0 SFDIAG (31) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) nop - ssm 0,0 + ssm 0,0 nop ; @@ -552,28 +553,28 @@ perf_rdr_shift_in_W_leave: .procend -;************************************************************************ -;* * -;* Name: perf_rdr_shift_out_W * -;* * -;* Description: * -;* This routine moves data to the RDR's. The double-word that * -;* arg1 points to is loaded and moved into the staging register. * -;* Then the STDIAG instruction for the RDR # in arg0 is called * -;* to move the data to the RDR. * -;* * -;* Arguments: * -;* arg0 = rdr number * -;* arg1 = 64-bit value to write * -;* %r24 - DR2 | DR2_SLOW_RET * -;* %r23 - original DR2 value * -;* * -;* Returns: * -;* None * -;* * -;* Register usage: * -;* * -;************************************************************************ +;*********************************************************************** +;* +;* Name: perf_rdr_shift_out_W +;* +;* Description: +;* This routine moves data to the RDR's. The double-word that +;* arg1 points to is loaded and moved into the staging register. +;* Then the STDIAG instruction for the RDR # in arg0 is called +;* to move the data to the RDR. +;* +;* Arguments: +;* arg0 = rdr number +;* arg1 = 64-bit value to write +;* %r24 - DR2 | DR2_SLOW_RET +;* %r23 - original DR2 value +;* +;* Returns: +;* None +;* +;* Register usage: +;* +;*********************************************************************** .export perf_rdr_shift_out_W,code perf_rdr_shift_out_W: @@ -587,24 +588,23 @@ perf_rdr_shift_out_W: depdi,z 1,DR2_SLOW_RET,1,%r24 MFDIAG_2 (23) - or %r24,%r23,%r24 - MTDIAG_2 (24) ; set DR2_SLOW_RET - - MTDIAG_1 (25) ; data to the staging register + or %r24,%r23,%r24 + MTDIAG_2 (24) ; set DR2_SLOW_RET + MTDIAG_1 (25) ; data to the staging register shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number - blr %r1,%r0 ; branch to 8-instruction sequence + blr %r1,%r0 ; branch to 8-instruction sequence nop ; ; RDR 0 write sequence ; sync ; RDR 0 write sequence - ssm 0,0 + ssm 0,0 STDIAG (0) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_W_leave nop - ssm 0,0 + ssm 0,0 nop ; @@ -718,7 +718,7 @@ perf_rdr_shift_out_W: ; ; RDR 10 write sequence ; - sync + sync ssm 0,0 STDIAG (10) STDIAG (26) @@ -862,7 +862,7 @@ perf_rdr_shift_out_W: ; ; RDR 22 write sequence ; - sync + sync ssm 0,0 STDIAG (22) ssm 0,0 @@ -910,7 +910,7 @@ perf_rdr_shift_out_W: ; ; RDR 26 write sequence ; - sync + sync ssm 0,0 STDIAG (10) STDIAG (26) @@ -958,7 +958,7 @@ perf_rdr_shift_out_W: ; ; RDR 30 write sequence ; - sync + sync ssm 0,0 STDIAG (30) ssm 0,0 @@ -970,7 +970,7 @@ perf_rdr_shift_out_W: ; ; RDR 31 write sequence ; - sync + sync ssm 0,0 STDIAG (31) ssm 0,0 @@ -986,34 +986,32 @@ perf_rdr_shift_out_W_leave: .procend -;**************************** CHRIS *********************************** - -;************************************************************************ -;* * -;* Name: rdr_shift_in_U * -;* * -;* Description: * -;* This routine shifts data in from the RDR in arg0 and returns * -;* the result in ret0. If the RDR is <= 64 bits in length, it * -;* is shifted shifted backup immediately. This is to compensate * -;* for RDR10 which has bits that preclude PDC stack operations * -;* when they are in the wrong state. * -;* * -;* Arguments: * -;* arg0 : rdr to be read * -;* arg1 : bit length of rdr * -;* * -;* Returns: * -;* ret0 = next 64 bits of rdr data from staging register * -;* * -;* Register usage: * -;* arg0 : rdr to be read * -;* arg1 : bit length of rdr * -;* %r24 - original DR2 value * -;* %r23 - DR2 | DR2_SLOW_RET * -;* %r1 - scratch * -;* * -;************************************************************************ +;*********************************************************************** +;* +;* Name: rdr_shift_in_U +;* +;* Description: +;* This routine shifts data in from the RDR in arg0 and returns +;* the result in ret0. If the RDR is <= 64 bits in length, it +;* is shifted shifted backup immediately. This is to compensate +;* for RDR10 which has bits that preclude PDC stack operations +;* when they are in the wrong state. +;* +;* Arguments: +;* arg0 : rdr to be read +;* arg1 : bit length of rdr +;* +;* Returns: +;* ret0 = next 64 bits of rdr data from staging register +;* +;* Register usage: +;* arg0 : rdr to be read +;* arg1 : bit length of rdr +;* %r24 - original DR2 value +;* %r23 - DR2 | DR2_SLOW_RET +;* %r1 - scratch +;* +;*********************************************************************** .export perf_rdr_shift_in_U,code perf_rdr_shift_in_U: @@ -1053,75 +1051,75 @@ perf_rdr_shift_in_U: ; Start of next 32-byte cacheline ; SFDIAG (0) ; RDR 0 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (0) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (1) ; RDR 1 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (1) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + sync ; RDR 2 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (4) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 3 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (3) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop sync ; RDR 4 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (4) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 5 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (5) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 6 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (6) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 7 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (7) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop b,n perf_rdr_shift_in_U_leave @@ -1134,95 +1132,95 @@ perf_rdr_shift_in_U: nop SFDIAG (9) ; RDR 9 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (9) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave SFDIAG (10) ; RDR 10 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (10) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (11) ; RDR 11 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (11) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (12) ; RDR 12 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (12) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave SFDIAG (13) ; RDR 13 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (13) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (14) ; RDR 14 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (14) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (15) ; RDR 15 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (15) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + sync ; RDR 16 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (16) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + SFDIAG (17) ; RDR 17 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (17) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (18) ; RDR 18 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (18) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + b,n perf_rdr_shift_in_U_leave nop nop @@ -1233,86 +1231,86 @@ perf_rdr_shift_in_U: nop sync ; RDR 20 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (20) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 21 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (21) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 22 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (22) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 23 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (23) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 24 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (24) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + sync ; RDR 25 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (25) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + SFDIAG (26) ; RDR 26 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (26) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (27) ; RDR 27 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (27) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + sync ; RDR 28 read sequence - ssm 0,0 + ssm 0,0 SFDIAG (28) - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) b,n perf_rdr_shift_in_U_leave - ssm 0,0 + ssm 0,0 nop - + b,n perf_rdr_shift_in_U_leave nop nop @@ -1321,23 +1319,23 @@ perf_rdr_shift_in_U: nop nop nop - + SFDIAG (30) ; RDR 30 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (30) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave - + SFDIAG (31) ; RDR 31 read sequence - ssm 0,0 + ssm 0,0 MFDIAG_1 (28) shrpd ret0,%r0,%sar,%r1 MTDIAG_1 (1) STDIAG (31) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_in_U_leave nop @@ -1347,30 +1345,30 @@ perf_rdr_shift_in_U_leave: MTDIAG_2 (24) ; restore DR2 .procend -;************************************************************************ -;* * -;* Name: rdr_shift_out_U * -;* * -;* Description: * -;* This routine moves data to the RDR's. The double-word that * -;* arg1 points to is loaded and moved into the staging register. * -;* Then the STDIAG instruction for the RDR # in arg0 is called * -;* to move the data to the RDR. * -;* * -;* Arguments: * -;* arg0 = rdr target * -;* arg1 = buffer pointer * -;* * -;* Returns: * -;* None * -;* * -;* Register usage: * -;* arg0 = rdr target * -;* arg1 = buffer pointer * -;* %r24 - DR2 | DR2_SLOW_RET * -;* %r23 - original DR2 value * -;* * -;************************************************************************ +;*********************************************************************** +;* +;* Name: rdr_shift_out_U +;* +;* Description: +;* This routine moves data to the RDR's. The double-word that +;* arg1 points to is loaded and moved into the staging register. +;* Then the STDIAG instruction for the RDR # in arg0 is called +;* to move the data to the RDR. +;* +;* Arguments: +;* arg0 = rdr target +;* arg1 = buffer pointer +;* +;* Returns: +;* None +;* +;* Register usage: +;* arg0 = rdr target +;* arg1 = buffer pointer +;* %r24 - DR2 | DR2_SLOW_RET +;* %r23 - original DR2 value +;* +;*********************************************************************** .export perf_rdr_shift_out_U,code perf_rdr_shift_out_U: @@ -1386,11 +1384,11 @@ perf_rdr_shift_out_U: depdi,z 1,DR2_SLOW_RET,1,%r24 MFDIAG_2 (23) or %r24,%r23,%r24 - MTDIAG_2 (24) ; set DR2_SLOW_RET + MTDIAG_2 (24) ; set DR2_SLOW_RET - MTDIAG_1 (25) ; data to the staging register - shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number - blr %r1,%r0 ; branch to 8-instruction sequence + MTDIAG_1 (25) ; data to the staging register + shladd arg0,2,%r0,%r1 ; %r1 = 4 * RDR number + blr %r1,%r0 ; branch to 8-instruction sequence nop ; @@ -1398,291 +1396,291 @@ perf_rdr_shift_out_U: ; sync ; RDR 0 write sequence - ssm 0,0 + ssm 0,0 STDIAG (0) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 1 write sequence - ssm 0,0 + ssm 0,0 STDIAG (1) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 2 write sequence - ssm 0,0 + ssm 0,0 STDIAG (2) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 3 write sequence - ssm 0,0 + ssm 0,0 STDIAG (3) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 4 write sequence - ssm 0,0 + ssm 0,0 STDIAG (4) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 5 write sequence - ssm 0,0 + ssm 0,0 STDIAG (5) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 6 write sequence - ssm 0,0 + ssm 0,0 STDIAG (6) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 7 write sequence - ssm 0,0 + ssm 0,0 STDIAG (7) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 8 write sequence - ssm 0,0 + ssm 0,0 STDIAG (8) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 9 write sequence - ssm 0,0 + ssm 0,0 STDIAG (9) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 10 write sequence - ssm 0,0 + ssm 0,0 STDIAG (10) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 11 write sequence - ssm 0,0 + ssm 0,0 STDIAG (11) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 12 write sequence - ssm 0,0 + ssm 0,0 STDIAG (12) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 13 write sequence - ssm 0,0 + ssm 0,0 STDIAG (13) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 14 write sequence - ssm 0,0 + ssm 0,0 STDIAG (14) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 15 write sequence - ssm 0,0 + ssm 0,0 STDIAG (15) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 16 write sequence - ssm 0,0 + ssm 0,0 STDIAG (16) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 17 write sequence - ssm 0,0 + ssm 0,0 STDIAG (17) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 18 write sequence - ssm 0,0 + ssm 0,0 STDIAG (18) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 19 write sequence - ssm 0,0 + ssm 0,0 STDIAG (19) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 20 write sequence - ssm 0,0 + ssm 0,0 STDIAG (20) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 21 write sequence - ssm 0,0 + ssm 0,0 STDIAG (21) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 22 write sequence - ssm 0,0 + ssm 0,0 STDIAG (22) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 23 write sequence - ssm 0,0 + ssm 0,0 STDIAG (23) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 24 write sequence - ssm 0,0 + ssm 0,0 STDIAG (24) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 25 write sequence - ssm 0,0 + ssm 0,0 STDIAG (25) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 26 write sequence - ssm 0,0 + ssm 0,0 STDIAG (26) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 27 write sequence - ssm 0,0 + ssm 0,0 STDIAG (27) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 28 write sequence - ssm 0,0 + ssm 0,0 STDIAG (28) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 29 write sequence - ssm 0,0 + ssm 0,0 STDIAG (29) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 30 write sequence - ssm 0,0 + ssm 0,0 STDIAG (30) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop sync ; RDR 31 write sequence - ssm 0,0 + ssm 0,0 STDIAG (31) - ssm 0,0 + ssm 0,0 b,n perf_rdr_shift_out_U_leave nop - ssm 0,0 + ssm 0,0 nop perf_rdr_shift_out_U_leave: diff --git a/arch/parisc/kernel/perf_images.h b/arch/parisc/kernel/perf_images.h index a8ed8d002..d9562fe3f 100644 --- a/arch/parisc/kernel/perf_images.h +++ b/arch/parisc/kernel/perf_images.h @@ -2,6 +2,7 @@ * Imagine for use with the Onyx (PCX-U) CPU interface * * Copyright (C) 2001 Randolph Chung + * Copyright (C) 2001 Hewlett-Packard (Grant Grundler) * * 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 diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index dd938ef77..320fca55f 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -262,7 +262,7 @@ sys_clone(unsigned long clone_flags, unsigned long usp, if(usp == 0) usp = regs->gr[30]; - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL); + return do_fork(clone_flags, usp, regs, 0, user_tid, NULL); } int @@ -363,8 +363,11 @@ asmlinkage int sys_execve(struct pt_regs *regs) goto out; error = do_execve(filename, (char **) regs->gr[25], (char **) regs->gr[24], regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 514e8b5f8..a5cb474ca 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -303,7 +303,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) * that it wants to exit. */ DBG(("sys_ptrace(KILL)\n")); - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ goto out_tsk; child->exit_code = SIGKILL; goto out_wake_notrap; @@ -379,6 +379,10 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) ret = ptrace_detach(child, data); goto out_tsk; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + goto out_tsk; + default: ret = ptrace_request(child, request, addr, data); goto out_tsk; @@ -404,11 +408,8 @@ void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 3637b0a98..8b8ee543a 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -149,7 +149,7 @@ restore_control_regs: rfi_virt2real: /* switch to real mode... */ ssm 0,0 /* See "relied upon translation" */ - nop /* comment in interruption.S */ + nop /* PA 2.0 Arch. F-5 */ nop nop nop @@ -186,7 +186,7 @@ rfi_v2r_1: .align 128 rfi_real2virt: ssm 0,0 /* See "relied upon translation" */ - nop /* comment in interruption.S */ + nop /* PA 2.0 Arch. F-5 */ nop nop nop diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index b220bb22f..4a0a8adbc 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -494,11 +494,9 @@ give_sigsegv: */ static long -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs *regs, int in_syscall) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs *regs, int in_syscall) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", sig, ka, info, oldset, regs); @@ -506,9 +504,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) return 0; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -535,7 +530,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) { siginfo_t info; - struct k_sigaction *ka; + struct k_sigaction ka; int signr; DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", @@ -553,10 +548,15 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) oldset->sig[0], oldset->sig[1]); - signr = get_signal_to_deliver(&info, regs, NULL); - DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); + /* May need to force signal if handle_signal failed to deliver */ + while (1) { + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); - if (signr > 0) { + if (signr <= 0) + break; + /* Restart a system call if necessary. */ if (in_syscall) { /* Check the return code */ @@ -569,8 +569,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) break; case -ERESTARTSYS: - ka = ¤t->sighand->action[signr-1]; - if (!(ka->sa.sa_flags & SA_RESTART)) { + if (!(ka.sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; @@ -578,8 +577,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all - we have to do is fiddle the return - pointer. */ + we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; @@ -589,12 +587,13 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &info, oldset, regs, in_syscall)) { + if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", regs->gr[28]); return 1; } } + /* end of while(1) looping forever if we can't force a signal */ /* Did we come from a system call? */ if (in_syscall) { diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 0f1daa584..5801637b1 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -33,10 +33,10 @@ #include #include #include +#include #include #include -#include #include #include #include /* for flush_tlb_all() proto/macro */ @@ -333,6 +333,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait) struct smp_call_struct data; unsigned long timeout; static spinlock_t lock = SPIN_LOCK_UNLOCKED; + int retries = 0; if (num_online_cpus() < 2) return 0; @@ -365,21 +366,22 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait) /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(IPI_CALL_FUNC); + retry: /* Wait for response */ timeout = jiffies + HZ; while ( (atomic_read (&data.unstarted_count) > 0) && time_before (jiffies, timeout) ) barrier (); + if (atomic_read (&data.unstarted_count) > 0) { + printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d), try %d\n", + smp_processor_id(), ++retries); + goto retry; + } /* We either got one or timed out. Release the lock */ mb(); smp_call_function_data = NULL; - if (atomic_read (&data.unstarted_count) > 0) { - printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n", - smp_processor_id()); - return -ETIMEDOUT; - } while (wait && atomic_read (&data.unfinished_count) > 0) barrier (); @@ -485,24 +487,6 @@ void __init smp_callin(void) panic("smp_callin() AAAAaaaaahhhh....\n"); } -/* - * Create the idle task for a new Slave CPU. DO NOT use kernel_thread() - * because that could end up calling schedule(). If it did, the new idle - * task could get scheduled before we had a chance to remove it from the - * run-queue... - */ -static struct task_struct *fork_by_hand(void) -{ - struct pt_regs regs; - - /* - * don't care about the regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - - /* * Bring one cpu online. */ @@ -521,13 +505,10 @@ int __init smp_boot_one_cpu(int cpuid) * Sheesh . . . */ - idle = fork_by_hand(); + idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - wake_up_forked_process(idle); - init_idle(idle, cpuid); - unhash_process(idle); idle->thread_info->cpu = cpuid; /* Let _start know what logical CPU we're booting diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 625a701f0..96ad250ed 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -234,6 +234,14 @@ asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low, return sys_readahead(fd, (loff_t)high << 32 | low, count); } +asmlinkage long parisc_fadvise64_64(int fd, + unsigned int high_off, unsigned int low_off, + unsigned int high_len, unsigned int low_len, int advice) +{ + return sys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off, + (loff_t)high_len << 32 | low_len, advice); +} + asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) { return -ENOMEM; diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index e78332541..2b42313c1 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -80,8 +80,11 @@ asmlinkage int sys32_execve(struct pt_regs *regs) goto out; error = compat_do_execve(filename, compat_ptr(regs->gr[25]), compat_ptr(regs->gr[24]), regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 1c34cf70d..32ea701f4 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -16,11 +16,32 @@ #include #include + /* We fill the empty parts of the gateway page with + * something that will kill the kernel or a + * userspace application. + */ +#define KILL_INSN break 0,0 + +#include /* for CONFIG_SMP */ + #ifdef __LP64__ .level 2.0w #else .level 1.1 #endif + +#ifndef __LP64__ + .macro fixup_branch,lbl + b \lbl + .endm +#else + .macro fixup_branch,lbl + ldil L%\lbl, %r1 + ldo R%\lbl(%r1), %r1 + bv,n %r0(%r1) + .endm +#endif + .text .import syscall_exit,code @@ -38,21 +59,41 @@ .align 4096 linux_gateway_page: - .rept 56 - break 0,0 + /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */ + .rept 44 + KILL_INSN .endr + /* ADDRESS 0xb0 to 0xb4, lws uses 1 insns for entry */ + /* Light-weight-syscall entry must always be located at 0xb0 */ + /* WARNING: Keep this number updated with table size changes */ +#define __NR_lws_entries (2) + +lws_entry: + /* Unconditional branch to lws_start, located on the + same gateway page */ + b,n lws_start + + /* Fill from 0xb4 to 0xe0 */ + .rept 11 + KILL_INSN + .endr + + /* This function MUST be located at 0xe0 for glibc's threading + mechanism to work. DO NOT MOVE THIS CODE EVER! */ set_thread_pointer: gate .+8, %r0 /* increase privilege */ depi 3, 31, 2, %r31 /* Ensure we return into user mode. */ be 0(%sr7,%r31) /* return to user space */ mtctl %r26, %cr27 /* move arg0 to the control register */ + /* Increase the chance of trapping if random jumps occur to this + address, fill from 0xf0 to 0x100 */ .rept 4 - break 0,0 + KILL_INSN .endr -/* This address must remain fixed, or user binaries go splat. */ +/* This address must remain fixed at 0x100 for glibc's syscalls to work */ .align 256 linux_gateway_entry: gate .+8, %r0 /* become privileged */ @@ -157,6 +198,7 @@ linux_gateway_entry: /* Are we being ptraced? */ mfctl %cr30, %r1 + LDREG TI_TASK(%r1),%r1 LDREG TASK_PTRACE(%r1), %r1 bb,<,n %r1,31,.Ltracesys @@ -177,11 +219,8 @@ linux_gateway_entry: comiclr,>>= __NR_Linux_syscalls, %r20, %r0 b,n .Lsyscall_nosys -#ifdef __LP64__ - ldd,s %r20(%r19), %r19 -#else - ldwx,s %r20(%r19), %r19 -#endif + LDREGX %r20(%r19), %r19 + /* If this is a sys_rt_sigreturn call, and the signal was received * when not in_syscall, then we want to return via syscall_exit_rfi, * not syscall_exit. Signal no. in r20, in_syscall in r25 (see @@ -291,11 +330,8 @@ tracesys_next: comiclr,>>= __NR_Linux_syscalls, %r20, %r0 b,n .Lsyscall_nosys -#ifdef __LP64__ - ldd,s %r20(%r19), %r19 -#else - ldwx,s %r20(%r19), %r19 -#endif + LDREGX %r20(%r19), %r19 + /* If this is a sys_rt_sigreturn call, and the signal was received * when not in_syscall, then we want to return via syscall_exit_rfi, * not syscall_exit. Signal no. in r20, in_syscall in r25 (see @@ -344,12 +380,292 @@ tracesys_sigexit: ldil L%syscall_exit_rfi,%r1 be,n R%syscall_exit_rfi(%sr7,%r1) + + /********************************************************* + Light-weight-syscall code + + r20 - lws number + r26,r25,r24,r23,r22 - Input registers + r28 - Function return register + r21 - Error code. + + Scracth: Any of the above that aren't being + currently used, including r1. + + Return pointer: r31 (Not usable) + + Error codes returned by entry path: + + ENOSYS - r20 was an invalid LWS number. + + *********************************************************/ +lws_start: + /* Gate and ensure we return to userspace */ + gate .+8, %r0 + depi 3, 31, 2, %r31 /* Ensure we return to userspace */ + +#ifdef __LP64__ + /* FIXME: If we are a 64-bit kernel just + * turn this on unconditionally. + */ + ssm PSW_SM_W, %r1 + extrd,u %r1,PSW_W_BIT,1,%r1 + /* sp must be aligned on 4, so deposit the W bit setting into + * the bottom of sp temporarily */ + or,ev %r1,%r30,%r30 + + /* Clip LWS number to a 32-bit value always */ + depdi 0, 31, 32, %r20 +#endif + + /* Is the lws entry number valid? */ + comiclr,>>= __NR_lws_entries, %r20, %r0 + b,n lws_exit_nosys + + /* WARNING: Trashing sr2 and sr3 */ + mfsp %sr7,%r1 /* get userspace into sr3 */ + mtsp %r1,%sr3 + mtsp %r0,%sr2 /* get kernel space into sr2 */ + + /* Load table start */ + ldil L%lws_table, %r1 + ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */ + LDREGX %r20(%sr2,r28), %r21 /* Scratch use of r21 */ + + /* Jump to lws, lws table pointers already relocated */ + be,n 0(%sr2,%r21) + +lws_exit_nosys: + ldo -ENOSYS(%r0),%r21 /* set errno */ + /* Fall through: Return to userspace */ + +lws_exit: +#ifdef __LP64__ + /* decide whether to reset the wide mode bit + * + * For a syscall, the W bit is stored in the lowest bit + * of sp. Extract it and reset W if it is zero */ + extrd,u,*<> %r30,63,1,%r1 + rsm PSW_SM_W, %r0 + /* now reset the lowest bit of sp if it was set */ + xor %r30,%r1,%r30 +#endif + be,n 0(%sr3, %r31) + + + + /*************************************************** + Implementing CAS as an atomic operation: + + %r26 - Address to examine + %r25 - Old value to check (old) + %r24 - New value to set (new) + %r28 - Return prev through this register. + %r21 - Kernel error code + + If debugging is DISabled: + + %r21 has the following meanings: + + EAGAIN - CAS is busy, ldcw failed, try again. + EFAULT - Read or write failed. + + If debugging is enabled: + + EDEADLOCK - CAS called recursively. + EAGAIN && r28 == 1 - CAS is busy. Lock contended. + EAGAIN && r28 == 2 - CAS is busy. ldcw failed. + EFAULT - Read or write failed. + + Scratch: r20, r28, r1 + + ****************************************************/ + + /* Do not enable LWS debugging */ +#define ENABLE_LWS_DEBUG 0 + + /* ELF64 Process entry path */ +lws_compare_and_swap64: +#ifdef __LP64__ + b,n lws_compare_and_swap +#else + /* If we are not a 64-bit kernel, then we don't + * implement having 64-bit input registers + */ + b,n lws_exit_nosys +#endif + + /* ELF32 Process entry path */ +lws_compare_and_swap32: +#ifdef __LP64__ + /* Clip all the input registers */ + depdi 0, 31, 32, %r26 + depdi 0, 31, 32, %r25 + depdi 0, 31, 32, %r24 +#endif + +lws_compare_and_swap: +#ifdef CONFIG_SMP + /* Load start of lock table */ + ldil L%lws_lock_start, %r20 + ldo R%lws_lock_start(%r20), %r28 + + /* Extract four bits from r26 and hash lock (Bits 4-7) */ + extru %r26, 27, 4, %r20 + + /* Find lock to use, the hash is either one of 0 to + 15, multiplied by 16 (keep it 16-byte aligned) + and add to the lock table offset. */ + shlw %r20, 4, %r20 + add %r20, %r28, %r20 + +# ifdef ENABLE_LWS_DEBUG + /* + DEBUG, check for deadlock! + If the thread register values are the same + then we were the one that locked it last and + this is a recurisve call that will deadlock. + We *must* giveup this call and fail. + */ + ldw 4(%sr2,%r20), %r28 /* Load thread register */ + mfctl %cr27, %r21 /* Get current thread register */ + cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */ + b lws_exit /* Return error! */ + ldo -EDEADLOCK(%r0), %r21 +cas_lock: + cmpb,=,n %r0, %r28, cas_nocontend /* Is nobody using it? */ + ldo 1(%r0), %r28 /* 1st case */ + b lws_exit /* Contended... */ + ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ +cas_nocontend: +# endif +/* ENABLE_LWS_DEBUG */ + + ldcw 0(%sr2,%r20), %r28 /* Try to acquire the lock */ + cmpb,<>,n %r0, %r28, cas_action /* Did we get it? */ +cas_wouldblock: + ldo 2(%r0), %r28 /* 2nd case */ + b lws_exit /* Contended... */ + ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ +#endif +/* CONFIG_SMP */ + + /* + prev = *addr; + if ( prev == old ) + *addr = new; + return prev; + */ + + /* NOTES: + This all works becuse intr_do_signal + and schedule both check the return iasq + and see that we are on the kernel page + so this process is never scheduled off + or is ever sent any signal of any sort, + thus it is wholly atomic from usrspaces + perspective + */ +cas_action: +#if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG + /* DEBUG */ + mfctl %cr27, %r1 + stw %r1, 4(%sr2,%r20) +#endif + /* The load and store could fail */ +1: ldw 0(%sr3,%r26), %r28 + sub,<> %r28, %r25, %r0 +2: stw %r24, 0(%sr3,%r26) +#ifdef CONFIG_SMP + /* Free lock */ + stw %r20, 0(%sr2,%r20) +# ifdef ENABLE_LWS_DEBUG + /* Clear thread register indicator */ + stw %r0, 4(%sr2,%r20) +# endif +#endif + /* Return to userspace, set no error */ + b lws_exit + copy %r0, %r21 + +3: + /* Error occured on load or store */ +#ifdef CONFIG_SMP + /* Free lock */ + stw %r20, 0(%sr2,%r20) +# ifdef ENABLE_LWS_DEBUG + stw %r0, 4(%sr2,%r20) +# endif +#endif + b lws_exit + ldo -EFAULT(%r0),%r21 /* set errno */ + nop + nop + nop + nop + + /* Two exception table entries, one for the load, + the other for the store. Either return -EFAULT. + Each of the entries must be relocated. */ + .section __ex_table,"aw" +#ifdef __LP64__ + /* Pad the address calculation */ + .word 0,(2b - linux_gateway_page) + .word 0,(3b - linux_gateway_page) +#else + .word (2b - linux_gateway_page) + .word (3b - linux_gateway_page) +#endif + .previous + + .section __ex_table,"aw" +#ifdef __LP64__ + /* Pad the address calculation */ + .word 0,(1b - linux_gateway_page) + .word 0,(3b - linux_gateway_page) +#else + .word (1b - linux_gateway_page) + .word (3b - linux_gateway_page) +#endif + .previous + +end_compare_and_swap: + + /* Make sure nothing else is placed on this page */ + .align 4096 + .export end_linux_gateway_page +end_linux_gateway_page: + + /* Relocate symbols assuming linux_gateway_page is mapped + to virtual address 0x0 */ +#ifdef __LP64__ + /* FIXME: The code will always be on the gateay page + and thus it will be on the first 4k, the + assembler seems to think that the final + subtraction result is only a word in + length, so we pad the value. + */ +#define LWS_ENTRY(_name_) .word 0,(lws_##_name_ - linux_gateway_page) +#else +#define LWS_ENTRY(_name_) .word (lws_##_name_ - linux_gateway_page) +#endif + + .align 4096 + /* Light-weight-syscall table */ + /* Start of lws table. */ + .export lws_table +.Llws_table: +lws_table: + LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */ + LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */ + /* End of lws table */ + .align 4096 .export sys_call_table .Lsys_call_table: sys_call_table: #include "syscall_table.S" -.end + #ifdef __LP64__ .align 4096 .export sys_call_table64 @@ -359,10 +675,29 @@ sys_call_table64: #include "syscall_table.S" #endif +#ifdef CONFIG_SMP + /* + All light-weight-syscall atomic operations + will use this set of locks + */ + .section .data + .align 4096 + .export lws_lock_start +.Llws_lock_start: +lws_lock_start: + /* lws locks */ + .align 16 + .rept 16 + /* Keep locks aligned at 16-bytes */ + .word 1 + .word 0 + .word 0 + .word 0 + .endr + .previous +#endif +/* CONFIG_SMP for lws_lock_start */ - /* Make sure nothing else is placed on this page */ +.end - .align 4096 - .export end_linux_gateway_page -end_linux_gateway_page: diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 2a3c11955..0328fac99 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -1,6 +1,6 @@ /* System Call Table * - * Copyright (C) 1999-2003 Matthew Wilcox + * Copyright (C) 1999-2004 Matthew Wilcox * Copyright (C) 2000-2001 John Marvin * Copyright (C) 2000 Alan Modra * Copyright (C) 2000-2003 Paul Bame @@ -308,19 +308,18 @@ ENTRY_OURS(ftruncate64) /* 200 */ ENTRY_SAME(getdents64) ENTRY_COMP(fcntl64) - ENTRY_SAME(ni_syscall) - ENTRY_SAME(ni_syscall) - ENTRY_SAME(ni_syscall) /* 205 */ - ENTRY_SAME(gettid) - ENTRY_OURS(readahead) - ENTRY_SAME(ni_syscall) /* tkill */ - + ENTRY_SAME(ni_syscall) /* attrctl -- dead */ + ENTRY_SAME(ni_syscall) /* acl_get -- dead */ + ENTRY_SAME(ni_syscall) /* 205 (acl_set -- dead) */ + ENTRY_SAME(gettid) + ENTRY_OURS(readahead) + ENTRY_SAME(tkill) ENTRY_SAME(sendfile64) ENTRY_COMP(futex) /* 210 */ ENTRY_COMP(sched_setaffinity) ENTRY_COMP(sched_getaffinity) - ENTRY_SAME(ni_syscall) - ENTRY_SAME(ni_syscall) + ENTRY_SAME(ni_syscall) /* set_thread_area */ + ENTRY_SAME(ni_syscall) /* get_thread_area */ ENTRY_SAME(io_setup) /* 215 */ ENTRY_SAME(io_destroy) ENTRY_SAME(io_getevents) @@ -334,12 +333,40 @@ ENTRY_SAME(epoll_ctl) /* 225 */ ENTRY_SAME(epoll_wait) ENTRY_SAME(remap_file_pages) - ENTRY_SAME(semtimedop) - ENTRY_SAME(mq_open) - ENTRY_SAME(mq_unlink) /* 230 */ - ENTRY_SAME(mq_timedsend) - ENTRY_SAME(mq_timedreceive) - ENTRY_SAME(mq_notify) - ENTRY_SAME(mq_getsetattr) - /* Nothing yet */ /* 235 */ + ENTRY_SAME(semtimedop) + ENTRY_SAME(mq_open) + ENTRY_SAME(mq_unlink) /* 230 */ + ENTRY_SAME(mq_timedsend) + ENTRY_SAME(mq_timedreceive) + ENTRY_SAME(mq_notify) + ENTRY_SAME(mq_getsetattr) + ENTRY_COMP(waitid) /* 235 */ + ENTRY_OURS(fadvise64_64) + ENTRY_SAME(set_tid_address) + ENTRY_SAME(setxattr) + ENTRY_SAME(lsetxattr) + ENTRY_SAME(fsetxattr) /* 240 */ + ENTRY_SAME(getxattr) + ENTRY_SAME(lgetxattr) + ENTRY_SAME(fgetxattr) + ENTRY_SAME(listxattr) + ENTRY_SAME(llistxattr) /* 245 */ + ENTRY_SAME(flistxattr) + ENTRY_SAME(removexattr) + ENTRY_SAME(lremovexattr) + ENTRY_SAME(fremovexattr) + ENTRY_COMP(timer_create) /* 250 */ + ENTRY_COMP(timer_settime) + ENTRY_COMP(timer_gettime) + ENTRY_SAME(timer_getoverrun) + ENTRY_SAME(timer_delete) + ENTRY_COMP(clock_settime) /* 255 */ + ENTRY_COMP(clock_gettime) + ENTRY_COMP(clock_getres) + ENTRY_COMP(clock_nanosleep) + ENTRY_SAME(tgkill) + ENTRY_COMP(mbind) /* 260 */ + ENTRY_COMP(get_mempolicy) + ENTRY_COMP(set_mempolicy) + /* Nothing yet */ diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 949998ffb..6cf740734 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -47,44 +47,6 @@ static long halftick; extern void smp_do_timer(struct pt_regs *regs); #endif -static inline void -parisc_do_profile(struct pt_regs *regs) -{ - unsigned long pc = regs->iaoq[0]; -#if 0 - extern unsigned long prof_cpu_mask; -#endif - extern char _stext; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; - -#if 0 - /* FIXME: when we have irq affinity to cpu, we need to - * only look at the cpus specified in this mask - */ - - if (!((1 << smp_processor_id()) & prof_cpu_mask)) - return; -#endif - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - atomic_inc((atomic_t *)&prof_buffer[pc]); -} - irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { long now; @@ -92,7 +54,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) int nticks; int cpu = smp_processor_id(); - parisc_do_profile(regs); + profile_tick(CPU_PROFILING, regs); now = mfctl(16); /* initialize next_tick to time at last clocktick */ @@ -117,6 +79,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) while (nticks--) { #ifdef CONFIG_SMP smp_do_timer(regs); +#else + update_process_times(user_mode(regs)); #endif if (cpu == 0) { write_seqlock(&xtime_lock); diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index ff80b3c1f..7f57fb48e 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -135,32 +135,19 @@ void dump_stack(void) EXPORT_SYMBOL(dump_stack); -void show_stack(struct task_struct *task, unsigned long *s) +static void do_show_stack(struct unwind_frame_info *info) { int i = 1; - struct unwind_frame_info info; - - if (!task) { - unsigned long sp, ip, rp; - -HERE: - asm volatile ("copy %%r30, %0" : "=r"(sp)); - ip = (unsigned long)&&HERE; - rp = (unsigned long)__builtin_return_address(0); - unwind_frame_init(&info, current, sp, ip, rp); - } else { - unwind_frame_init_from_blocked_task(&info, task); - } printk("Backtrace:\n"); while (i <= 16) { - if (unwind_once(&info) < 0 || info.ip == 0) + if (unwind_once(info) < 0 || info->ip == 0) break; - if (__kernel_text_address(info.ip)) { - printk(" [<" RFMT ">] ", info.ip); + if (__kernel_text_address(info->ip)) { + printk(" [<" RFMT ">] ", info->ip); #ifdef CONFIG_KALLSYMS - print_symbol("%s\n", info.ip); + print_symbol("%s\n", info->ip); #else if ((i & 0x03) == 0) printk("\n"); @@ -171,6 +158,25 @@ HERE: printk("\n"); } +void show_stack(struct task_struct *task, unsigned long *s) +{ + struct unwind_frame_info info; + + if (!task) { + unsigned long sp, ip, rp; + +HERE: + asm volatile ("copy %%r30, %0" : "=r"(sp)); + ip = (unsigned long)&&HERE; + rp = (unsigned long)__builtin_return_address(0); + unwind_frame_init(&info, current, sp, ip, rp); + } else { + unwind_frame_init_from_blocked_task(&info, task); + } + + do_show_stack(&info); +} + void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (user_mode(regs)) { @@ -373,9 +379,9 @@ void transfer_pim_to_trap_frame(struct pt_regs *regs) /* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. + * This routine is called as a last resort when everything else + * has gone clearly wrong. We get called for faults in kernel space, + * and HPMC's. */ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) { @@ -407,7 +413,12 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o } - show_stack(NULL, (unsigned long *)regs->gr[30]); + { + /* show_stack(NULL, (unsigned long *)regs->gr[30]); */ + struct unwind_frame_info info; + unwind_frame_init(&info, current, regs->gr[30], regs->iaoq[0], regs->gr[2]); + do_show_stack(&info); + } printk("\n"); printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n", @@ -421,9 +432,16 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o * system will shut down immediately right here. */ pdc_soft_power_button(0); - /* Gutter the processor! */ - for(;;) - ; + /* Call kernel panic() so reboot timeouts work properly + * FIXME: This function should be on the list of + * panic notifiers, and we should call panic + * directly from the location that we wish. + * e.g. We should not call panic from + * parisc_terminate, but rather the oter way around. + * This hack works, prints the panic message twice, + * and it enables reboot timers! + */ + panic(msg); } void handle_interruption(int code, struct pt_regs *regs) @@ -437,6 +455,36 @@ void handle_interruption(int code, struct pt_regs *regs) else local_irq_enable(); + /* Security check: + * If the priority level is still user, and the + * faulting space is not equal to the active space + * then the user is attempting something in a space + * that does not belong to them. Kill the process. + * + * This is normally the situation when the user + * attempts to jump into the kernel space at the + * wrong offset, be it at the gateway page or a + * random location. + * + * We cannot normally signal the process because it + * could *be* on the gateway page, and processes + * executing on the gateway page can't have signals + * delivered. + * + * We merely readjust the address into the users + * space, at a destination address of zero, and + * allow processing to continue. + */ + if (((unsigned long)regs->iaoq[0] & 3) && + ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) { + /* Kill the user process later */ + regs->iaoq[0] = 0 | 3; + regs->iaoq[1] = regs->iaoq[0] + 4; + regs->iasq[0] = regs->iasq[0] = regs->sr[7]; + regs->gr[0] &= ~PSW_B; + return; + } + #if 0 printk(KERN_CRIT "Interruption # %d\n", code); #endif @@ -461,7 +509,7 @@ void handle_interruption(int code, struct pt_regs *regs) case 3: /* Recovery counter trap */ regs->gr[0] &= ~PSW_R; - if (regs->iasq[0]) + if (user_space(regs)) handle_gdb_break(regs, TRAP_TRACE); /* else this must be the start of a syscall - just let it run */ return; @@ -542,12 +590,12 @@ void handle_interruption(int code, struct pt_regs *regs) /* Set to zero, and let the userspace app figure it out from the insn pointed to by si_addr */ si.si_code = 0; - si.si_addr = (void *) regs->iaoq[0]; + si.si_addr = (void __user *) regs->iaoq[0]; force_sig_info(SIGFPE, &si, current); return; - } else - /* The kernel doesn't want to handle condition codes */ - break; + } + /* The kernel doesn't want to handle condition codes */ + break; case 14: /* Assist Exception Trap, i.e. floating point exception. */ @@ -565,9 +613,16 @@ void handle_interruption(int code, struct pt_regs *regs) /* Fall through */ case 17: /* Non-access data TLB miss fault/Non-access data page fault */ - /* TODO: Still need to add slow path emulation code here */ - /* TODO: Understand what is meant by the TODO listed - above this one. (Carlos) */ + /* FIXME: + Still need to add slow path emulation code here! + If the insn used a non-shadow register, then the tlb + handlers could not have their side-effect (e.g. probe + writing to a target register) emulated since rfir would + erase the changes to said register. Instead we have to + setup everything, call this function we are in, and emulate + by hand. Technically we need to emulate: + fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw + */ fault_address = regs->ior; fault_space = regs->isr; break; @@ -598,7 +653,7 @@ void handle_interruption(int code, struct pt_regs *regs) case 25: /* Taken branch trap */ regs->gr[0] &= ~PSW_T; - if (regs->iasq[0]) + if (user_space(regs)) handle_gdb_break(regs, TRAP_BRANCH); /* else this must be the start of a syscall - just let it * run. diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index 530235c0b..3eda1dadc 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -23,6 +23,7 @@ #include #include #include +#include /* #define DEBUG_UNALIGNED 1 */ @@ -38,6 +39,11 @@ #define RFMT "%08lx" #endif +#define FIXUP_BRANCH(lbl) \ + "\tldil L%%" #lbl ", %%r1\n" \ + "\tldo R%%" #lbl "(%%r1), %%r1\n" \ + "\tbv,n %%r0(%%r1)\n" + /* 1111 1100 0000 0000 0001 0011 1100 0000 */ #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) #define OPCODE2(a,b) ((a)<<26|(b)<<1) @@ -134,15 +140,19 @@ static int emulate_ldh(struct pt_regs *regs, int toreg) "1: ldbs 0(%%sr1,%3), %%r20\n" "2: ldbs 1(%%sr1,%3), %0\n" " depw %%r20, 23, 24, %0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (val), "=r" (ret) @@ -175,15 +185,19 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) " subi 32,%%r19,%%r19\n" " mtctl %%r19,11\n" " vshd %0,%%r20,%0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (val), "=r" (ret) @@ -222,15 +236,19 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) " subi 64,%%r19,%%r19\n" " mtsar %%r19\n" " shrpd %0,%%r20,%%sar,%0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (val), "=r" (ret) @@ -250,17 +268,21 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) " mtsar %%r19\n" " vshd %0,%1,%0\n" " vshd %1,%%r20,%1\n" -" cmpclr,= %%r0, %%r0, %2\n" -"4: ldo -2(%%r0), %2\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %2\n" +"4: \n" +" .section .fixup,\"ax\"\n" +"5: ldi -2, %2\n" + FIXUP_BRANCH(4b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(4b-1b)\n" -" .dword 2b,(4b-2b)\n" -" .dword 3b,(4b-3b)\n" +" .dword 1b,5b\n" +" .dword 2b,5b\n" +" .dword 3b,5b\n" #else -" .word 1b,(4b-1b)\n" -" .word 2b,(4b-2b)\n" -" .word 3b,(4b-3b)\n" +" .word 1b,5b\n" +" .word 2b,5b\n" +" .word 3b,5b\n" #endif " .previous\n" : "=r" (valh), "=r" (vall), "=r" (ret) @@ -296,15 +318,19 @@ static int emulate_sth(struct pt_regs *regs, int frreg) " extrw,u %1, 23, 8, %%r19\n" "1: stb %1, 1(%%sr1, %2)\n" "2: stb %%r19, 0(%%sr1, %2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"3: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %0\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (ret) @@ -346,15 +372,19 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop) " or %%r1, %%r21, %%r21\n" " stw %%r20,0(%%sr1,%2)\n" " stw %%r21,4(%%sr1,%2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"3: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %0\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (ret) @@ -399,19 +429,23 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) " or %%r1, %%r21, %%r21\n" "3: std %%r20,0(%%sr1,%2)\n" "4: std %%r21,8(%%sr1,%2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"5: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"5: \n" +" .section .fixup,\"ax\"\n" +"6: ldi -2, %0\n" + FIXUP_BRANCH(5b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(5b-1b)\n" -" .dword 2b,(5b-2b)\n" -" .dword 3b,(5b-3b)\n" -" .dword 4b,(5b-4b)\n" +" .dword 1b,6b\n" +" .dword 2b,6b\n" +" .dword 3b,6b\n" +" .dword 4b,6b\n" #else -" .word 1b,(5b-1b)\n" -" .word 2b,(5b-2b)\n" -" .word 3b,(5b-3b)\n" -" .word 4b,(5b-4b)\n" +" .word 1b,6b\n" +" .word 2b,6b\n" +" .word 3b,6b\n" +" .word 4b,6b\n" #endif " .previous\n" : "=r" (ret) @@ -438,21 +472,25 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) "3: stw %1,0(%%sr1,%1)\n" "4: stw %%r1,4(%%sr1,%3)\n" "5: stw %2,8(%%sr1,%3)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"6: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"6: \n" +" .section .fixup,\"ax\"\n" +"7: ldi -2, %0\n" + FIXUP_BRANCH(6b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(6b-1b)\n" -" .dword 2b,(6b-2b)\n" -" .dword 3b,(6b-3b)\n" -" .dword 4b,(6b-4b)\n" -" .dword 5b,(6b-5b)\n" +" .dword 1b,7b\n" +" .dword 2b,7b\n" +" .dword 3b,7b\n" +" .dword 4b,7b\n" +" .dword 5b,7b\n" #else -" .word 1b,(6b-1b)\n" -" .word 2b,(6b-2b)\n" -" .word 3b,(6b-3b)\n" -" .word 4b,(6b-4b)\n" -" .word 5b,(6b-5b)\n" +" .word 1b,7b\n" +" .word 2b,7b\n" +" .word 3b,7b\n" +" .word 4b,7b\n" +" .word 5b,7b\n" #endif " .previous\n" : "=r" (ret) @@ -492,7 +530,6 @@ void handle_unaligned(struct pt_regs *regs) show_regs(regs); #endif } - if (!unaligned_enabled) goto force_sigbus; } @@ -557,16 +594,6 @@ void handle_unaligned(struct pt_regs *regs) break; } - if (regs->isr != regs->sr[7]) - { - printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n", - regs->isr, regs->sr[7]); - - /* don't kill him though, since he has appropriate access to the page, or we - * would never have gotten here. - */ - } - /* TODO: make this cleaner... */ switch (regs->iir & OPCODE1_MASK) { diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index abd749074..5e1e11520 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -12,8 +12,10 @@ #include #include #include +#include #include +#include #include @@ -40,25 +42,27 @@ static struct unwind_table *unwind_tables, *unwind_tables_end; static inline const struct unwind_table_entry * find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) { - const struct unwind_table_entry *e = 0; + const struct unwind_table_entry *e = NULL; unsigned long lo, hi, mid; - for (lo = 0, hi = table->length; lo < hi; ) - { - mid = (lo + hi) / 2; + lo = 0; + hi = table->length - 1; + + while (lo <= hi) { + mid = (hi - lo) / 2 + lo; e = &table->table[mid]; if (addr < e->region_start) - hi = mid; + hi = mid - 1; else if (addr > e->region_end) lo = mid + 1; else - break; + return e; } - return e; + return NULL; } -static inline const struct unwind_table_entry * +static const struct unwind_table_entry * find_unwind_entry(unsigned long addr) { struct unwind_table *table = unwind_tables; @@ -68,8 +72,7 @@ find_unwind_entry(unsigned long addr) addr <= kernel_unwind_table.end) e = find_unwind_entry_in_table(&kernel_unwind_table, addr); else - for (; table; table = table->next) - { + for (; table; table = table->next) { if (addr >= table->start && addr <= table->end) e = find_unwind_entry_in_table(table, addr); @@ -99,6 +102,11 @@ unwind_table_init(struct unwind_table *table, const char *name, table->next = NULL; for (; start <= end; start++) { + if (start < end && + start->region_end > (start+1)->region_start) { + printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1); + } + start->region_start += base_addr; start->region_end += base_addr; } @@ -114,7 +122,7 @@ unwind_table_add(const char *name, unsigned long base_addr, table = kmalloc(sizeof(struct unwind_table), GFP_USER); if (table == NULL) - return 0; + return NULL; unwind_table_init(table, name, base_addr, gp, start, end); spin_lock_irqsave(&unwind_lock, flags); if (unwind_tables) @@ -170,12 +178,40 @@ static void unwind_frame_regs(struct unwind_frame_info *info) int looking_for_rp, rpoffset = 0; e = find_unwind_entry(info->ip); - if (!e) { + if (e == NULL) { unsigned long sp; extern char _stext[], _etext[]; dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip); +#ifdef CONFIG_KALLSYMS + /* Handle some frequent special cases.... */ + { + char symname[KSYM_NAME_LEN+1]; + char *modname; + unsigned long symsize, offset; + + kallsyms_lookup(info->ip, &symsize, &offset, + &modname, symname); + + dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname); + + if (strcmp(symname, "_switch_to_ret") == 0) { + info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; + info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); + dbg("_switch_to_ret @ %lx - setting " + "prev_sp=%lx prev_ip=%lx\n", + info->ip, info->prev_sp, + info->prev_ip); + return; + } else if (strcmp(symname, "ret_from_kernel_thread") == 0 || + strcmp(symname, "syscall_exit") == 0) { + info->prev_ip = info->prev_sp = 0; + return; + } + } +#endif + /* Since we are doing the unwinding blind, we don't know if we are adjusting the stack correctly or extracting the rp correctly. The rp is checked to see if it belongs to the @@ -185,30 +221,33 @@ static void unwind_frame_regs(struct unwind_frame_info *info) modules. */ sp = info->sp & ~63; do { - info->prev_sp = sp - 64; - - /* FIXME: what happens if we unwind too far so that - sp no longer falls in a mapped kernel page? */ -#ifndef __LP64__ - info->prev_ip = *(unsigned long *)(info->prev_sp - 20); -#else - info->prev_ip = *(unsigned long *)(info->prev_sp - 16); -#endif + unsigned long tmp; + info->prev_sp = sp - 64; + info->prev_ip = 0; + if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) + break; + info->prev_ip = tmp; sp = info->prev_sp; } while (info->prev_ip < (unsigned long)_stext || info->prev_ip > (unsigned long)_etext); - dbg("analyzing func @ %lx with no unwind info, setting prev_sp=%lx prev_ip=%lx\n", info->ip, info->prev_sp, info->prev_ip); - } else { + info->rp = 0; - dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, Save_RP = %d size = %u\n", - e->region_start, e->region_end, e->Save_SP, e->Save_RP, e->Total_frame_size); + dbg("analyzing func @ %lx with no unwind info, setting " + "prev_sp=%lx prev_ip=%lx\n", info->ip, + info->prev_sp, info->prev_ip); + } else { + dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, " + "Save_RP = %d size = %u\n", e->region_start, + e->region_end, e->Save_SP, e->Save_RP, + e->Total_frame_size); looking_for_rp = e->Save_RP; for (npc = e->region_start; - (frame_size < (e->Total_frame_size << 3) || looking_for_rp) && + (frame_size < (e->Total_frame_size << 3) || + looking_for_rp) && npc < info->ip; npc += 4) { @@ -219,22 +258,28 @@ static void unwind_frame_regs(struct unwind_frame_info *info) /* ldo X(sp), sp, or stwm X,D(sp) */ frame_size += (insn & 0x1 ? -1 << 13 : 0) | ((insn & 0x3fff) >> 1); - dbg("analyzing func @ %lx, insn=%08x @ %lx, frame_size = %ld\n", info->ip, insn, npc, frame_size); - } else if ((insn & 0xffe00008) == 0x7ec00008) { + dbg("analyzing func @ %lx, insn=%08x @ " + "%lx, frame_size = %ld\n", info->ip, + insn, npc, frame_size); + } else if ((insn & 0xffe00008) == 0x73c00008) { /* std,ma X,D(sp) */ frame_size += (insn & 0x1 ? -1 << 13 : 0) | (((insn >> 4) & 0x3ff) << 3); - dbg("analyzing func @ %lx, insn=%08x @ %lx, frame_size = %ld\n", info->ip, insn, npc, frame_size); + dbg("analyzing func @ %lx, insn=%08x @ " + "%lx, frame_size = %ld\n", info->ip, + insn, npc, frame_size); } else if (insn == 0x6bc23fd9) { /* stw rp,-20(sp) */ rpoffset = 20; looking_for_rp = 0; - dbg("analyzing func @ %lx, insn=stw rp,-20(sp) @ %lx\n", info->ip, npc); + dbg("analyzing func @ %lx, insn=stw rp," + "-20(sp) @ %lx\n", info->ip, npc); } else if (insn == 0x0fc212c1) { /* std rp,-16(sr0,sp) */ rpoffset = 16; looking_for_rp = 0; - dbg("analyzing func @ %lx, insn=std rp,-16(sp) @ %lx\n", info->ip, npc); + dbg("analyzing func @ %lx, insn=std rp," + "-16(sp) @ %lx\n", info->ip, npc); } } @@ -244,7 +289,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info) info->prev_ip = info->rp; info->rp = 0; - dbg("analyzing func @ %lx, setting prev_sp=%lx prev_ip=%lx\n", info->ip, info->prev_sp, info->prev_ip); + dbg("analyzing func @ %lx, setting prev_sp=%lx " + "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, + info->prev_ip, npc); } } @@ -257,7 +304,8 @@ void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, info->ip = ip; info->rp = rp; - dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", t ? (int)t->pid : 0, info->sp, info->ip); + dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", + t ? (int)t->pid : -1, info->sp, info->ip); } void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t) @@ -285,7 +333,9 @@ int unwind_once(struct unwind_frame_info *next_frame) next_frame->prev_sp = 0; next_frame->prev_ip = 0; - dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", (int)next_frame->t->pid, next_frame->sp, next_frame->ip); + dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", + next_frame->t ? (int)next_frame->t->pid : -1, + next_frame->sp, next_frame->ip); return 0; } diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 7da318ed0..e011bc856 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -52,6 +52,7 @@ SECTIONS .text ALIGN(16) : { *(.text) SCHED_TEXT + LOCK_TEXT *(.text.do_softirq) *(.text.sys_exit) *(.text.do_sigaltstack) @@ -130,9 +131,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 7322c7e63..3ab95fd1a 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile @@ -2,6 +2,6 @@ # Makefile for parisc-specific library files # -lib-y := lusercopy.o bitops.o checksum.o io.o memset.o +lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o lib-$(CONFIG_SMP) += debuglocks.o diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c index 4c077fc4c..2de182f6f 100644 --- a/arch/parisc/lib/bitops.c +++ b/arch/parisc/lib/bitops.c @@ -13,8 +13,8 @@ #include #ifdef CONFIG_SMP -atomic_lock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { - [0 ... (ATOMIC_HASH_SIZE-1)] = (atomic_lock_t) { { 1, 1, 1, 1 } } +spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { + [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED }; #endif @@ -23,10 +23,10 @@ unsigned long __xchg64(unsigned long x, unsigned long *ptr) { unsigned long temp, flags; - atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + _atomic_spin_lock_irqsave(ptr, flags); temp = *ptr; *ptr = x; - atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + _atomic_spin_unlock_irqrestore(ptr, flags); return temp; } #endif @@ -36,10 +36,10 @@ unsigned long __xchg32(int x, int *ptr) unsigned long flags; long temp; - atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + _atomic_spin_lock_irqsave(ptr, flags); temp = (long) *ptr; /* XXX - sign extension wanted? */ *ptr = x; - atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + _atomic_spin_unlock_irqrestore(ptr, flags); return (unsigned long)temp; } @@ -49,10 +49,10 @@ unsigned long __xchg8(char x, char *ptr) unsigned long flags; long temp; - atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + _atomic_spin_lock_irqsave(ptr, flags); temp = (long) *ptr; /* XXX - sign extension wanted? */ *ptr = x; - atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + _atomic_spin_unlock_irqrestore(ptr, flags); return (unsigned long)temp; } @@ -63,10 +63,10 @@ unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsi unsigned long flags; unsigned long prev; - atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + _atomic_spin_lock_irqsave(ptr, flags); if ((prev = *ptr) == old) *ptr = new; - atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + _atomic_spin_unlock_irqrestore(ptr, flags); return prev; } #endif @@ -76,9 +76,9 @@ unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsign unsigned long flags; unsigned int prev; - atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + _atomic_spin_lock_irqsave(ptr, flags); if ((prev = *ptr) == old) *ptr = new; - atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + _atomic_spin_unlock_irqrestore(ptr, flags); return (unsigned long)prev; } diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c index abd29ac69..c402e7533 100644 --- a/arch/parisc/lib/checksum.c +++ b/arch/parisc/lib/checksum.c @@ -24,6 +24,13 @@ #include #include +#define addc(_t,_r) \ + __asm__ __volatile__ ( \ +" add %0, %1, %0\n" \ +" addc %0, %%r0, %0\n" \ + : "=r"(_t) \ + : "r"(_r), "0"(_t)); + static inline unsigned short from32to16(unsigned int x) { /* 32 bits --> 16 bits + carry */ @@ -56,16 +63,25 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) } count >>= 1; /* nr of 32-bit words.. */ if (count) { - unsigned int carry = 0; - do { + while (count >= 4) { + unsigned int r1, r2, r3, r4; + r1 = *(unsigned int *)(buff + 0); + r2 = *(unsigned int *)(buff + 4); + r3 = *(unsigned int *)(buff + 8); + r4 = *(unsigned int *)(buff + 12); + addc(result, r1); + addc(result, r2); + addc(result, r3); + addc(result, r4); + count -= 4; + buff += 16; + } + while (count) { unsigned int w = *(unsigned int *) buff; count--; buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; + addc(result, w); + } result = (result & 0xffff) + (result >> 16); } if (len & 2) { @@ -77,7 +93,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) result += le16_to_cpu(*buff); result = from32to16(result); if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + result = swab16(result); out: return result; } @@ -88,12 +104,8 @@ out: unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) { unsigned int result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - if(sum > result) - result += 1; - return result; + addc(result, sum); + return from32to16(result); } EXPORT_SYMBOL(csum_partial); diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c index 7e79f1bad..5ac3eb047 100644 --- a/arch/parisc/lib/debuglocks.c +++ b/arch/parisc/lib/debuglocks.c @@ -18,6 +18,11 @@ * 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 + * + * We use pdc_printf() throughout the file for all output messages, to avoid + * losing messages because of disabled interrupts. Since we're using these + * messages for debugging purposes, it makes sense not to send them to the + * linux console. */ @@ -25,14 +30,17 @@ #include #include #include +#include /* in_interrupt() */ #include #include /* in_interrupt() */ +#include #undef INIT_STUCK #define INIT_STUCK 1L << 30 #ifdef CONFIG_DEBUG_SPINLOCK + void _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no) { volatile unsigned int *a; @@ -59,12 +67,14 @@ try_again: * __ldcw() returns 1 if we get the lock; otherwise we * spin until the value of the lock changes, or we time out. */ + mb(); a = __ldcw_align(lock); while (stuck && (__ldcw(a) == 0)) while ((*a == 0) && --stuck); + mb(); if (unlikely(stuck <= 0)) { - printk(KERN_WARNING + pdc_printf( "%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)" " owned by %s:%d in %s at %p(%d)\n", base_file, line_no, lock->module, lock, @@ -84,7 +94,7 @@ try_again: lock->bline = line_no; if (unlikely(printed)) { - printk(KERN_WARNING + pdc_printf( "%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n", base_file, line_no, current->comm, inline_pc, cpu, jiffies - started); @@ -94,21 +104,28 @@ try_again: void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no) { CHECK_LOCK(lock); - volatile unsigned int *a = __ldcw_align(lock); + volatile unsigned int *a; + mb(); + a = __ldcw_align(lock); if (unlikely((*a != 0) && lock->babble)) { lock->babble--; - printk(KERN_WARNING + pdc_printf( "%s:%d: spin_unlock(%s:%p) not locked\n", base_file, line_no, lock->module, lock); } *a = 1; + mb(); } int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no) { int ret; - volatile unsigned int *a = __ldcw_align(lock); - if ((ret = (__ldcw(a) != 0))) { + volatile unsigned int *a; + mb(); + a = __ldcw_align(lock); + ret = (__ldcw(a) != 0); + mb(); + if (ret) { lock->oncpu = smp_processor_id(); lock->previous = __builtin_return_address(0); lock->task = current; @@ -150,7 +167,7 @@ void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline) int cpu = smp_processor_id(); if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */ - printk(KERN_WARNING "write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline); + pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline); BUG(); } @@ -167,7 +184,7 @@ retry: stuck--; if ((unlikely(stuck <= 0)) && (rw->counter < 0)) { - printk(KERN_WARNING + pdc_printf( "%s:%d: write_lock stuck on writer" " in %s at %p(%d) %ld ticks\n", bfile, bline, current->comm, inline_pc, @@ -176,7 +193,7 @@ retry: printed = 1; } else if (unlikely(stuck <= 0)) { - printk(KERN_WARNING + pdc_printf( "%s:%d: write_lock stuck on reader" " in %s at %p(%d) %ld ticks\n", bfile, bline, current->comm, inline_pc, @@ -194,13 +211,47 @@ retry: rw->counter = -1; /* remember we are locked */ if (unlikely(printed)) { - printk(KERN_WARNING + pdc_printf( "%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n", bfile, bline, current->comm, inline_pc, cpu, jiffies - started); } } +int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline) +{ +#if 0 + void *inline_pc = __builtin_return_address(0); + int cpu = smp_processor_id(); +#endif + + if(unlikely(in_interrupt())) { /* acquiring write lock in interrupt context, bad idea */ + pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline); + BUG(); + } + + /* Note: if interrupts are disabled (which is most likely), the printk + will never show on the console. We might need a polling method to flush + the dmesg buffer anyhow. */ + + _raw_spin_lock(&rw->lock); + + if(rw->counter != 0) { + /* this basically never happens */ + _raw_spin_unlock(&rw->lock); + + + return 0; + } + + /* got it. now leave without unlocking */ + rw->counter = -1; /* remember we are locked */ +#if 0 + pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n", + bfile, bline, current->comm, inline_pc, cpu); +#endif +} + void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline) { #if 0 @@ -215,7 +266,7 @@ void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline) rw->counter++; #if 0 - printk(KERN_WARNING + pdc_printf( "%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n", bfile, bline, current->comm, inline_pc, cpu, jiffies - started); diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S index 72c9615ed..a0509855c 100644 --- a/arch/parisc/lib/lusercopy.S +++ b/arch/parisc/lib/lusercopy.S @@ -53,124 +53,11 @@ mtsp %r1,%sr1 .endm - /* - * unsigned long - * lcopy_to_user(void *to, const void *from, unsigned long n) - * - * Returns 0 for success. - * otherwise, returns number of bytes not transferred. - */ - - .export lcopy_to_user,code -lcopy_to_user: - .proc - .callinfo NO_CALLS - .entry - comib,=,n 0,%r24,$lctu_done - get_sr -$lctu_loop: - ldbs,ma 1(%r25),%r1 - addib,<> -1,%r24,$lctu_loop -1: stbs,ma %r1,1(%sr1,%r26) -$lctu_done: - bv %r0(%r2) - copy %r24,%r28 - .exit - -2: b $lctu_done - ldo 1(%r24),%r24 - - .section __ex_table,"a" -#ifdef __LP64__ - .dword 1b,(2b-1b) -#else - .word 1b,(2b-1b) -#endif - .previous - - .procend - - /* - * unsigned long - * lcopy_from_user(void *to, const void *from, unsigned long n) - * - * Returns 0 for success. - * otherwise, returns number of bytes not transferred. - * - * NOTE: This routine will also zero any bytes in the - * destination that were not copied due to a fault. - * - */ - - .export lcopy_from_user,code -lcopy_from_user: - .proc - .callinfo NO_CALLS - .entry - comib,=,n 0,%r24,$lcfu_done - get_sr -$lcfu_loop: -1: ldbs,ma 1(%sr1,%r25),%r1 - addib,<> -1,%r24,$lcfu_loop - stbs,ma %r1,1(%r26) -$lcfu_done: - bv %r0(%r2) - copy %r24,%r28 - .exit - -2: copy %r24,%r23 -$lcfu_zero_loop: - addib,<> -1,%r23,$lcfu_zero_loop - stbs,ma %r0,1(%r26) - b $lcfu_done - nop - - .section __ex_table,"a" -#ifdef __LP64__ - .dword 1b,(2b-1b) -#else - .word 1b,(2b-1b) -#endif - .previous - - .procend - - /* - * unsigned long - * lcopy_in_user(void *to, const void *from, unsigned long n) - * - * Returns 0 for success. - * otherwise, returns number of bytes not transferred. - */ - - .export lcopy_in_user,code -lcopy_in_user: - .proc - .callinfo NO_CALLS - .entry - comib,=,n 0,%r24,$lciu_done - get_sr -$lciu_loop: - ldbs,ma 1(%sr1,%r25),%r1 - addib,<> -1,%r24,$lciu_loop -1: stbs,ma %r1,1(%sr1,%r26) -$lciu_done: - bv %r0(%r2) - copy %r24,%r28 - .exit - -2: b $lciu_done - ldo 1(%r24),%r24 - - .section __ex_table,"a" -#ifdef __LP64__ - .dword 1b,(2b-1b) -#else - .word 1b,(2b-1b) -#endif - .previous - - .procend + .macro fixup_branch lbl + ldil L%\lbl, %r1 + ldo R%\lbl(%r1), %r1 + bv %r0(%r1) + .endm /* * long lstrncpy_from_user(char *dst, const char *src, long n) @@ -201,16 +88,18 @@ $lsfu_exit: nop .exit -3: b $lsfu_exit + .section .fixup,"ax" +3: fixup_branch $lsfu_exit ldi -EFAULT,%r28 + .previous - .section __ex_table,"a" + .section __ex_table,"aw" #ifdef __LP64__ - .dword 1b,(3b-1b) - .dword 2b,(3b-2b) + .dword 1b,3b + .dword 2b,3b #else - .word 1b,(3b-1b) - .word 2b,(3b-2b) + .word 1b,3b + .word 2b,3b #endif .previous @@ -239,14 +128,16 @@ $lclu_done: copy %r25,%r28 .exit -2: b $lclu_done + .section .fixup,"ax" +2: fixup_branch $lclu_done ldo 1(%r25),%r25 + .previous - .section __ex_table,"a" + .section __ex_table,"aw" #ifdef __LP64__ - .dword 1b,(2b-1b) + .dword 1b,2b #else - .word 1b,(2b-1b) + .word 1b,2b #endif .previous @@ -282,16 +173,18 @@ $lslen_nzero: b $lslen_done ldo 1(%r26),%r26 /* special case for N == 0 */ -3: b $lslen_done + .section .fixup,"ax" +3: fixup_branch $lslen_done copy %r24,%r26 /* reset r26 so 0 is returned on fault */ + .previous - .section __ex_table,"a" + .section __ex_table,"aw" #ifdef __LP64__ - .dword 1b,(3b-1b) - .dword 2b,(3b-2b) + .dword 1b,3b + .dword 2b,3b #else - .word 1b,(3b-1b) - .word 2b,(3b-2b) + .word 1b,3b + .word 2b,3b #endif .previous diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index d52b3a06a..fd1c77280 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -36,6 +36,9 @@ #define BITSSET 0x1c0 /* for identifying LDCW */ + +DEFINE_PER_CPU(struct exception_data, exception_data); + /* * parisc_acctyp(unsigned int inst) -- * Given a PA-RISC memory access instruction, determine if the @@ -230,17 +233,17 @@ bad_area: no_context: if (!user_mode(regs)) { - fix = search_exception_tables(regs->iaoq[0]); if (fix) { + struct exception_data *d; - if (fix->skip & 1) - regs->gr[8] = -EFAULT; - if (fix->skip & 2) - regs->gr[9] = 0; + d = &__get_cpu_var(exception_data); + d->fault_ip = regs->iaoq[0]; + d->fault_space = regs->isr; + d->fault_addr = regs->ior; - regs->iaoq[0] += ((fix->skip) & ~3); + regs->iaoq[0] = ((fix->fixup) & ~3); /* * NOTE: In some cases the faulting instruction diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 871d7df27..a2dced5be 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -20,6 +20,7 @@ #include #include #include +#include /* for node_online_map */ #include #include @@ -750,7 +751,7 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) #if PTRS_PER_PMD == 1 pmd = (pmd_t *)__pa(pg_dir); #else - pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir)); + pmd = (pmd_t *) pgd_address(*pg_dir); /* * pmd is physical at this point @@ -761,7 +762,7 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) pmd = (pmd_t *) __pa(pmd); } - pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd; + __pgd_val_set(*pg_dir, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pmd); #endif /* now change pmd to kernel virtual addresses */ @@ -771,11 +772,11 @@ map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm) * pg_table is physical at this point */ - pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd)); + pg_table = (pte_t *) pmd_address(*pmd); if (!pg_table) pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL)); - pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) pg_table; + __pmd_val_set(*pmd, PxD_FLAG_PRESENT | PxD_FLAG_VALID | (unsigned long) pg_table); /* now change pg_table to kernel virtual addresses */ @@ -804,19 +805,21 @@ void __init paging_init(void) ZONE_DMA zone. */ zones_size[ZONE_DMA] = pmem_ranges[i].pages; - free_area_init_node(i,NODE_DATA(i),NULL,zones_size, - pmem_ranges[i].start_pfn, 0); - #ifdef CONFIG_DISCONTIGMEM + /* Need to initialize the pfnnid_map before we can initialize + the zone */ { int j; - for (j = (node_start_pfn(i) >> PFNNID_SHIFT); - j <= (node_end_pfn(i) >> PFNNID_SHIFT); + for (j = (pmem_ranges[i].start_pfn >> PFNNID_SHIFT); + j <= ((pmem_ranges[i].start_pfn + pmem_ranges[i].pages) >> PFNNID_SHIFT); j++) { pfnnid_map[j] = i; } } #endif + + free_area_init_node(i, NODE_DATA(i), zones_size, + pmem_ranges[i].start_pfn, NULL); } } diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index f0728f3c0..4a0f3119a 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -51,12 +51,12 @@ #include #include #include +#include #include #include #include #include -#include #include @@ -933,7 +933,7 @@ static void siccuart_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int siccuart_write(struct tty_struct *tty, int from_user, +static int siccuart_write(struct tty_struct *tty, const u_char * buf, int count) { struct SICC_info *info = tty->driver_data; @@ -944,58 +944,23 @@ static int siccuart_write(struct tty_struct *tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = (info->xmit.head + c) & - (SICC_XMIT_SIZE - 1); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (SICC_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SICC_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = (info->xmit.head + c) & + (SICC_XMIT_SIZE - 1); + buf += c; + count -= c; + ret += c; } + restore_flags(flags); if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped) diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c index 3f8aa4197..ac6d55fe2 100644 --- a/arch/ppc/8260_io/enet.c +++ b/arch/ppc/8260_io/enet.c @@ -39,11 +39,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index d56a031e6..a38487b11 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -34,12 +34,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -1986,9 +1986,9 @@ fcc_restart(struct net_device *dev, int duplex) fccp = fcp->fccp; if (duplex) - fccp->fcc_fpsmr |= FCC_PSMR_FDE; + fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB; else - fccp->fcc_fpsmr &= ~FCC_PSMR_FDE; + fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB); /* Enable transmit/receive */ fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT; diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig index bf1361958..ee9b1f0ee 100644 --- a/arch/ppc/8xx_io/Kconfig +++ b/arch/ppc/8xx_io/Kconfig @@ -74,37 +74,6 @@ config ENET_BIG_BUFFERS Allocate large buffers for MPC8xx Etherenet. Increases throughput and decreases the likelihood of dropped packets, but costs memory. -config SMC2_UART - bool "Use SMC2 for UART" - help - If you would like to use SMC2 as a serial port, say Y here. - - If in doubt, say Y here. - -config ALTSMC2 - bool "Use Alternate SMC2 I/O (823/850)" - depends on SMC2_UART - help - 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. - -config CONS_SMC2 - bool "Use SMC2 for Console" - depends on SMC2_UART - help - 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. - -config USE_SCC_IO - bool "Enable SCC2 and SCC3 for UART" - help - 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. - config HTDMSOUND bool "Embedded Planet HIOX Audio" depends on SOUND=y @@ -134,13 +103,36 @@ config 8xx_CPU6 If in doubt, say N here. -config UCODE_PATCH - bool "I2C/SPI Microcode Patch" +choice + prompt "Microcode patch selection" + default NO_UCODE_PATCH + help + Help not implemented yet, coming soon. + +config NO_UCODE_PATCH + bool "None" + +config USB_SOF_UCODE_PATCH + bool "USB SOF patch" + help + Help not implemented yet, coming soon. + +config I2C_SPI_UCODE_PATCH + bool "I2C/SPI relocation patch" help - Motorola releases microcode updates for their 8xx CPM modules. The - microcode update file has updates for IIC, SMC and USB. Currently only - the USB update is available by default, if the MPC8xx USB option is - enabled. If in doubt, say 'N' here. + Help not implemented yet, coming soon. + +config I2C_SPI_SMC1_UCODE_PATCH + bool "I2C/SPI/SMC1 relocation patch" + help + Help not implemented yet, coming soon. + +endchoice + +config UCODE_PATCH + bool + default y + depends on !NO_UCODE_PATCH endmenu diff --git a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile index 7e5121912..d8760181f 100644 --- a/arch/ppc/8xx_io/Makefile +++ b/arch/ppc/8xx_io/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux MPC8xx ppc-specific parts of comm processor # -obj-y := commproc.o uart.o +obj-y := commproc.o obj-$(CONFIG_FEC_ENET) += fec.o obj-$(CONFIG_SCC_ENET) += enet.o diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index 2688504d6..0cc2e7a9c 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c @@ -23,18 +23,20 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include #include #include #include #include +#include #include extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); @@ -51,68 +53,69 @@ struct cpm_action { void *dev_id; }; static struct cpm_action cpm_vecs[CPMVEC_NR]; -static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs); -static void cpm_error_interrupt(void *, struct pt_regs * regs); +static irqreturn_t cpm_interrupt(int irq, void * dev, struct pt_regs * regs); +static irqreturn_t cpm_error_interrupt(int irq, void *dev, struct pt_regs * regs); static void alloc_host_memory(void); +/* Define a table of names to identify CPM interrupt handlers in + * /proc/interrupts. + */ +const char *cpm_int_name[] = + { "error", "PC4", "PC5", "SMC2", + "SMC1", "SPI", "PC6", "Timer 4", + "", "PC7", "PC8", "PC9", + "Timer 3", "", "PC10", "PC11", + "I2C", "RISC Timer", "Timer 2", "", + "IDMA2", "IDMA1", "SDMA error", "PC12", + "PC13", "Timer 1", "PC14", "SCC4", + "SCC3", "SCC2", "SCC1", "PC15" + }; -#if 1 -void -m8xx_cpm_reset(void) +static void +cpm_mask_irq(unsigned int irq) { - volatile immap_t *imp; - volatile cpm8xx_t *commproc; - - imp = (immap_t *)IMAP_ADDR; - commproc = (cpm8xx_t *)&imp->im_cpm; - -#ifdef CONFIG_UCODE_PATCH - /* Perform a reset. - */ - commproc->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG); + int cpm_vec = irq - CPM_IRQ_OFFSET; - /* Wait for it. - */ - while (commproc->cp_cpcr & CPM_CR_FLG); - - cpm_load_patch(imp); -#endif + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_vec); +} - /* Set SDMA Bus Request priority 5. - * On 860T, this also enables FEC priority 6. I am not sure - * this is what we realy want for some applications, but the - * manual recommends it. - * Bit 25, FAM can also be set to use FEC aggressive mode (860T). - */ - imp->im_siu_conf.sc_sdcr = 1; +static void +cpm_unmask_irq(unsigned int irq) +{ + int cpm_vec = irq - CPM_IRQ_OFFSET; - /* Reclaim the DP memory for our use. */ - m8xx_cpm_dpinit(); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_vec); +} - /* Tell everyone where the comm processor resides. - */ - cpmp = (cpm8xx_t *)commproc; +static void +cpm_ack(unsigned int irq) +{ + /* We do not need to do anything here. */ } -/* We used to do this earlier, but have to postpone as long as possible - * to ensure the kernel VM is now running. - */ static void -alloc_host_memory() +cpm_eoi(unsigned int irq) { - uint physaddr; + int cpm_vec = irq - CPM_IRQ_OFFSET; - /* Set the host page for allocation. - */ - host_buffer = (uint)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &physaddr); - host_end = host_buffer + PAGE_SIZE; + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << cpm_vec); } -#else + +struct hw_interrupt_type cpm_pic = { + .typename = " CPM ", + .enable = cpm_unmask_irq, + .disable = cpm_mask_irq, + .ack = cpm_ack, + .end = cpm_eoi, +}; + +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); + void -m8xx_cpm_reset(uint host_page_addr) +m8xx_cpm_reset(uint bootpage) { volatile immap_t *imp; volatile cpm8xx_t *commproc; - pte_t *pte; + pte_t *pte; imp = (immap_t *)IMAP_ADDR; commproc = (cpm8xx_t *)&imp->im_cpm; @@ -134,40 +137,61 @@ m8xx_cpm_reset(uint host_page_addr) * this is what we realy want for some applications, but the * manual recommends it. * Bit 25, FAM can also be set to use FEC aggressive mode (860T). - */ + */ imp->im_siu_conf.sc_sdcr = 1; /* Reclaim the DP memory for our use. */ m8xx_cpm_dpinit(); - /* Set the host page for allocation. - */ - host_buffer = host_page_addr; /* Host virtual page address */ - host_end = host_page_addr + PAGE_SIZE; + /* get the PTE for the bootpage */ + if (!get_pteptr(&init_mm, bootpage, &pte)) + panic("get_pteptr failed\n"); + + /* and make it uncachable */ + pte_val(*pte) |= _PAGE_NO_CACHE; + _tlbie(bootpage); - /* We need to get this page early, so I have to do it the - * hard way. - */ - if (get_pteptr(&init_mm, host_page_addr, &pte)) { - pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(init_mm.mmap, host_buffer); - } - else { - panic("Huh? No CPM host page?"); - } + host_buffer = bootpage; + host_end = host_buffer + PAGE_SIZE; /* Tell everyone where the comm processor resides. */ cpmp = (cpm8xx_t *)commproc; } -#endif + +/* We used to do this earlier, but have to postpone as long as possible + * to ensure the kernel VM is now running. + */ +static void +alloc_host_memory(void) +{ + dma_addr_t physaddr; + + /* Set the host page for allocation. + */ + host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr, + GFP_KERNEL); + host_end = host_buffer + PAGE_SIZE; +} /* This is called during init_IRQ. We used to do it above, but this * was too early since init_IRQ was not yet called. */ +static struct irqaction cpm_error_irqaction = { + .handler = cpm_error_interrupt, + .mask = CPU_MASK_NONE, +}; +static struct irqaction cpm_interrupt_irqaction = { + .handler = cpm_interrupt, + .mask = CPU_MASK_NONE, + .name = "CPM cascade", +}; + void cpm_interrupt_init(void) { + int i; + /* Initialize the CPM interrupt controller. */ ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr = @@ -175,41 +199,52 @@ cpm_interrupt_init(void) ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK; ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0; - /* Set our interrupt handler with the core CPU. - */ - if (request_8xxirq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) + /* install the CPM interrupt controller routines for the CPM + * interrupt vectors + */ + for ( i = CPM_IRQ_OFFSET ; i < CPM_IRQ_OFFSET + NR_CPM_INTS ; i++ ) + irq_desc[i].handler = &cpm_pic; + + /* Set our interrupt handler with the core CPU. */ + if (setup_irq(CPM_INTERRUPT, &cpm_interrupt_irqaction)) panic("Could not allocate CPM IRQ!"); - /* Install our own error handler. - */ - cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); + /* Install our own error handler. */ + cpm_error_irqaction.name = cpm_int_name[CPMVEC_ERROR]; + if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction)) + panic("Could not allocate CPM error IRQ!"); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; } -/* CPM interrupt controller interrupt. -*/ -static void -cpm_interrupt(int irq, void * dev, struct pt_regs * regs) +/* + * Get the CPM interrupt vector. + */ +int +cpm_get_irq(struct pt_regs *regs) { - uint vec; + int cpm_vec; /* Get the vector by setting the ACK bit and then reading * the register. */ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1; - vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr; - vec >>= 11; + cpm_vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr; + cpm_vec >>= 11; - if (cpm_vecs[vec].handler != 0) - (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs); - else - ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); + return cpm_vec; +} - /* After servicing the interrupt, we have to remove the status - * indicator. +/* CPM interrupt controller cascade interrupt. +*/ +static irqreturn_t +cpm_interrupt(int irq, void * dev, struct pt_regs * regs) +{ + /* This interrupt handler never actually gets called. It is + * installed only to unmask the CPM cascade interrupt in the SIU + * and to make the CPM cascade interrupt visible in /proc/interrupts. */ - ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << vec); - + return IRQ_HANDLED; } /* The CPM can generate the error interrupt when there is a race condition @@ -217,41 +252,73 @@ cpm_interrupt(int irq, void * dev, struct pt_regs * regs) * and return. This is a no-op function so we don't need any special * tests in the interrupt handler. */ -static void -cpm_error_interrupt(void *dev, struct pt_regs *regs) +static irqreturn_t +cpm_error_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + return IRQ_HANDLED; +} + +/* A helper function to translate the handler prototype required by + * request_irq() to the handler prototype required by cpm_install_handler(). + */ +static irqreturn_t +cpm_handler_helper(int irq, void *dev_id, struct pt_regs *regs) { + int cpm_vec = irq - CPM_IRQ_OFFSET; + + (*cpm_vecs[cpm_vec].handler)(dev_id, regs); + + return IRQ_HANDLED; } /* Install a CPM interrupt handler. -*/ + * This routine accepts a CPM interrupt vector in the range 0 to 31. + * This routine is retained for backward compatibility. Rather than using + * this routine to install a CPM interrupt handler, you can now use + * request_irq() with an IRQ in the range CPM_IRQ_OFFSET to + * CPM_IRQ_OFFSET + NR_CPM_INTS - 1 (16 to 47). + * + * Notice that the prototype of the interrupt handler function must be + * different depending on whether you install the handler with + * request_irq() or cpm_install_handler(). + */ void -cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs), +cpm_install_handler(int cpm_vec, void (*handler)(void *, struct pt_regs *regs), void *dev_id) { + int err; /* If null handler, assume we are trying to free the IRQ. */ if (!handler) { - cpm_free_handler(vec); + free_irq(CPM_IRQ_OFFSET + cpm_vec, dev_id); return; } - if (cpm_vecs[vec].handler != 0) - printk("CPM interrupt %x replacing %x\n", - (uint)handler, (uint)cpm_vecs[vec].handler); - cpm_vecs[vec].handler = handler; - cpm_vecs[vec].dev_id = dev_id; - ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); + if (cpm_vecs[cpm_vec].handler != 0) + printk(KERN_INFO "CPM interrupt %x replacing %x\n", + (uint)handler, (uint)cpm_vecs[cpm_vec].handler); + cpm_vecs[cpm_vec].handler = handler; + cpm_vecs[cpm_vec].dev_id = dev_id; + + if ((err = request_irq(CPM_IRQ_OFFSET + cpm_vec, cpm_handler_helper, + 0, cpm_int_name[cpm_vec], dev_id))) + printk(KERN_ERR "request_irq() returned %d for CPM vector %d\n", + err, cpm_vec); } /* Free a CPM interrupt handler. -*/ + * This routine accepts a CPM interrupt vector in the range 0 to 31. + * This routine is retained for backward compatibility. + */ void -cpm_free_handler(int vec) +cpm_free_handler(int cpm_vec) { - cpm_vecs[vec].handler = NULL; - cpm_vecs[vec].dev_id = NULL; - ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); + request_irq(CPM_IRQ_OFFSET + cpm_vec, NULL, 0, 0, + cpm_vecs[cpm_vec].dev_id); + + cpm_vecs[cpm_vec].handler = NULL; + cpm_vecs[cpm_vec].dev_id = NULL; } /* We also own one page of host buffer space for the allocation of @@ -262,10 +329,8 @@ m8xx_cpm_hostalloc(uint size) { uint retloc; -#if 1 if (host_buffer == 0) alloc_host_memory(); -#endif if ((host_buffer + size) >= host_end) return(0); diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index 8ddef1c5c..f720d2a4c 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -38,11 +38,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include @@ -581,10 +582,10 @@ static void set_multicast_list(struct net_device *dev) /* Log any net taps. */ printk("%s: Promiscuous mode enabled.\n", dev->name); - cep->sccp->scc_pmsr |= SCC_PMSR_PRO; + cep->sccp->scc_psmr |= SCC_PSMR_PRO; } else { - cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO; + cep->sccp->scc_psmr &= ~SCC_PSMR_PRO; if (dev->flags & IFF_ALLMULTI) { /* Catch all multicast addresses, so set the @@ -835,7 +836,8 @@ static int __init scc_enet_init(void) /* Allocate a page. */ - ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr); + ba = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, + &mem_addr, GFP_KERNEL); /* BUG: no check for failure */ /* Initialize the BD for every fragment in the page. @@ -889,7 +891,7 @@ static int __init scc_enet_init(void) /* Set processing mode. Use Ethernet CRC, catch broadcast, and * start frame search 22 bit times after RENA. */ - sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22); + sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22); /* It is now OK to enable the Ethernet transmitter. * Unfortunately, there are board implementation differences here. diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 5c7c914f8..b2ebae810 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_FEC_PACKETHOOK #include #endif @@ -52,7 +53,6 @@ #include #include #include -#include #include #include @@ -1684,7 +1684,7 @@ static int __init fec_enet_init(void) /* Install our interrupt handler. */ - if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) + if (request_irq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) panic("Could not allocate FEC IRQ!"); #ifdef CONFIG_RPXCLASSIC @@ -1705,7 +1705,7 @@ static int __init fec_enet_init(void) ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |= (0x80000000 >> PHY_INTERRUPT); - if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0) + if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0) panic("Could not allocate MII IRQ!"); #endif diff --git a/arch/ppc/8xx_io/micropatch.c b/arch/ppc/8xx_io/micropatch.c index 68a51ee22..312af0776 100644 --- a/arch/ppc/8xx_io/micropatch.c +++ b/arch/ppc/8xx_io/micropatch.c @@ -19,18 +19,12 @@ #include #include -/* Define this to get SMC patches as well. You need to modify the uart - * driver as well...... -#define USE_SMC_PATCH 1 +/* + * I2C/SPI relocation patch arrays. */ -#ifdef CONFIG_USB_MPC8xx -#define USE_USB_SOF_PATCH -#endif +#ifdef CONFIG_I2C_SPI_UCODE_PATCH -#ifdef USE_IIC_PATCH -#define PATCH_DEFINED - /* IIC/SPI */ uint patch_2000[] = { 0x7FFFEFD9, 0x3FFD0000, @@ -183,11 +177,12 @@ uint patch_2f00[] = { }; #endif -#ifdef USE_SMC_PATCH -#define PATCH_DEFINED -/* SMC2/IIC/SPI Patch */ -/* This is the area from 0x2000 to 0x23ff. -*/ +/* + * I2C/SPI/SMC1 relocation patch arrays. + */ + +#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH + uint patch_2000[] = { 0x3fff0000, 0x3ffd0000, @@ -511,8 +506,6 @@ uint patch_2000[] = { 0x6079e2bb }; - /* This is from 0x2f00 to 0x2fff - */ uint patch_2f00[] = { 0x30303030, 0x3e3e3434, @@ -581,8 +574,6 @@ uint patch_2f00[] = { }; uint patch_2e00[] = { - /* This is from 0x2e00 to 0x2e3c - */ 0x27eeeeee, 0xeeeeeeee, 0xeeeeeeee, @@ -602,8 +593,12 @@ uint patch_2e00[] = { }; #endif -#ifdef USE_USB_SOF_PATCH -#define PATCH_DEFINED +/* + * USB SOF patch arrays. + */ + +#ifdef CONFIG_USB_SOF_UCODE_PATCH + uint patch_2000[] = { 0x7fff0000, 0x7ffd0000, @@ -626,33 +621,21 @@ uint patch_2f00[] = { }; #endif -/* Load the microcode patch. This is called early in the CPM initialization - * with the controller in the reset state. We enable the processor after - * we load the patch. - */ void cpm_load_patch(volatile immap_t *immr) { -#ifdef PATCH_DEFINED - volatile uint *dp; + volatile uint *dp; /* Dual-ported RAM. */ volatile cpm8xx_t *commproc; volatile iic_t *iip; volatile spi_t *spp; + volatile smc_uart_t *smp; int i; commproc = (cpm8xx_t *)&immr->im_cpm; - /* We work closely with commproc.c. We know it only allocates - * from data only space. - * For this particular patch, we only use the bottom 512 bytes - * and the upper 256 byte extension. We will use the space - * starting at 1K for the relocated parameters, as the general - * CPM allocation won't come from that area. - */ +#ifdef CONFIG_USB_SOF_UCODE_PATCH commproc->cp_rccr = 0; - /* Copy the patch into DPRAM. - */ dp = (uint *)(commproc->cp_dpmem); for (i=0; i<(sizeof(patch_2000)/4); i++) *dp++ = patch_2000[i]; @@ -661,29 +644,26 @@ cpm_load_patch(volatile immap_t *immr) for (i=0; i<(sizeof(patch_2f00)/4); i++) *dp++ = patch_2f00[i]; -#ifdef USE_USB_SOF_PATCH -#if 0 /* usb patch should not relocate iic */ - iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; -#define RPBASE 0x0030 - iip->iic_rpbase = RPBASE; + commproc->cp_rccr = 0x0009; - /* Put SPI above the IIC, also 32-byte aligned. - */ - i = (RPBASE + sizeof(iic_t) + 31) & ~31; - spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; - spp->spi_rpbase = i; -#endif + printk("USB SOF microcode patch installed\n"); +#endif /* CONFIG_USB_SOF_UCODE_PATCH */ - /* Enable uCode fetches from DPRAM. */ - commproc->cp_rccr = 0x0009; +#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \ + defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH) + + commproc->cp_rccr = 0; - printk("USB uCode patch installed\n"); -#endif /* USE_USB_SOF_PATCH */ + dp = (uint *)(commproc->cp_dpmem); + for (i=0; i<(sizeof(patch_2000)/4); i++) + *dp++ = patch_2000[i]; -#if defined(USE_SMC_PATCH) || defined(USE_IIC_PATCH) + dp = (uint *)&(commproc->cp_dpmem[0x0f00]); + for (i=0; i<(sizeof(patch_2f00)/4); i++) + *dp++ = patch_2f00[i]; iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; -#define RPBASE 0x0400 +# define RPBASE 0x0500 iip->iic_rpbase = RPBASE; /* Put SPI above the IIC, also 32-byte aligned. @@ -692,58 +672,46 @@ cpm_load_patch(volatile immap_t *immr) spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; spp->spi_rpbase = i; -#ifdef USE_SMC_PATCH +# if defined(CONFIG_I2C_SPI_UCODE_PATCH) + commproc->cp_cpmcr1 = 0x802a; + commproc->cp_cpmcr2 = 0x8028; + commproc->cp_cpmcr3 = 0x802e; + commproc->cp_cpmcr4 = 0x802c; + commproc->cp_rccr = 1; + + printk("I2C/SPI microcode patch installed.\n"); +# endif /* CONFIG_I2C_SPI_UCODE_PATCH */ + +# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH) + dp = (uint *)&(commproc->cp_dpmem[0x0e00]); for (i=0; i<(sizeof(patch_2e00)/4); i++) *dp++ = patch_2e00[i]; - /* Enable the traps to get to it. - */ commproc->cp_cpmcr1 = 0x8080; commproc->cp_cpmcr2 = 0x808a; commproc->cp_cpmcr3 = 0x8028; commproc->cp_cpmcr4 = 0x802a; - - /* Enable uCode fetches from DPRAM. - */ commproc->cp_rccr = 3; -#endif - -#ifdef USE_IIC_PATCH - /* Enable the traps to get to it. - */ - commproc->cp_cpmcr1 = 0x802a; - commproc->cp_cpmcr2 = 0x8028; - commproc->cp_cpmcr3 = 0x802e; - commproc->cp_cpmcr4 = 0x802c; - /* Enable uCode fetches from DPRAM. - */ - commproc->cp_rccr = 1; - - printk("I2C uCode patch installed\n"); -#endif + smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1]; + smp->smc_rpbase = 0x1FC0; - /* Relocate the IIC and SPI parameter areas. These have to - * aligned on 32-byte boundaries. - */ - iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC]; - iip->iic_rpbase = RPBASE; - - /* Put SPI above the IIC, also 32-byte aligned. - */ - i = (RPBASE + sizeof(iic_t) + 31) & ~31; - spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI]; - spp->spi_rpbase = i; + printk("I2C/SPI/SMC1 microcode patch installed.\n"); +# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */ -#endif /* USE_SMC_PATCH || USE_IIC_PATCH */ -#endif /* PATCH_DEFINED */ +#endif /* some variation of the I2C/SPI patch was selected */ } +/* + * Take this entire routine out, since no one calls it and its + * logic is suspect. + */ + +#if 0 void verify_patch(volatile immap_t *immr) { -#ifdef PATCH_DEFINED volatile uint *dp; volatile cpm8xx_t *commproc; int i; @@ -772,6 +740,5 @@ verify_patch(volatile immap_t *immr) } commproc->cp_rccr = 0x0009; -#endif /* PATCH_DEFINED */ } - +#endif diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index cc4e6b9db..de3f1e310 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -11,6 +11,10 @@ config MMU config UID16 bool +config GENERIC_HARDIRQS + bool + default y + config RWSEM_GENERIC_SPINLOCK bool @@ -49,7 +53,7 @@ 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, 52xx, 8260), the IBM embedded - versions (403 and 405) and the high end 64 bit Power processors + versions (403 and 405) and the high end 64 bit Power processors (POWER 3, POWER4, and IBM 970 also known as G5) Unless you are building a kernel for one of the embedded processor systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx. @@ -70,6 +74,7 @@ config POWER4 bool "POWER4 and 970 (G5)" config 8xx + depends on BROKEN bool "8xx" config E500 @@ -184,18 +189,6 @@ config MATH_EMULATION here. Saying Y here will not hurt performance (on any machine) but will increase the size of the kernel. -config CPU_FREQ - bool "CPU Frequency scaling" - help - Clock scaling allows you to change the clock speed of CPUs on the - fly. This is a nice method to save battery power on notebooks, - because the lower the clock speed, the less power the CPU consumes. - - For more information, take a look at or - at - - If in doubt, say N. - source "drivers/cpufreq/Kconfig" config CPU_FREQ_PMAC @@ -626,7 +619,7 @@ config EMBEDDEDBOOT bool depends on 8xx || 8260 default y - + config PPC_MPC52xx bool @@ -685,7 +678,8 @@ config PPC_OF config PPC_GEN550 bool - depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || PRPMC750 || K2 || PRPMC800 + depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \ + PRPMC750 || K2 || PRPMC800 || LOPEC default y config FORCE @@ -751,16 +745,6 @@ config PC_KEYBOARD bool "PC PS/2 style Keyboard" depends on 4xx || CPM2 -config SERIAL_CONSOLE - bool - depends on 8xx - default y - -config SERIAL_CONSOLE_BAUD - int - depends on EV64260 - default "115200" - config PPCBUG_NVRAM bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC default y if PPC_PREP @@ -811,10 +795,6 @@ config PREEMPT config HIGHMEM bool "High memory support" -config KERNEL_ELF - bool - default y - source "fs/Kconfig.binfmt" config PROC_DEVICETREE @@ -832,10 +812,11 @@ config PREP_RESIDUAL Some PReP systems have residual data passed to the kernel by the firmware. This allows detection of memory size, devices present and other useful pieces of information. Sometimes this information is - not present or incorrect. + not present or incorrect, in which case it could lead to the machine + behaving incorrectly. If this happens, either disable PREP_RESIDUAL + or pass the 'noresidual' option to the kernel. - Unless you expect to boot on a PReP system, there is no need to - select Y. + If you are running a PReP system, say Y here, otherwise say N. config PROC_PREPRESIDUAL bool "Support for reading of PReP Residual Data in /proc" @@ -1043,13 +1024,13 @@ config PCI_8260 bool depends on PCI && 8260 && !8272 default y - + config 8260_PCI9 bool " Enable workaround for MPC826x erratum PCI 9" depends on PCI_8260 default y -choice +choice prompt " IDMA channel for PCI 9 workaround" depends on 8260_PCI9 @@ -1228,128 +1209,7 @@ source "lib/Kconfig" source "arch/ppc/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - Say Y here and to CONFIG_SMP to include code to check for missing - spinlock initialization and some other common spinlock errors. - -config DEBUG_HIGHMEM - bool "Highmem debugging" - depends on DEBUG_KERNEL && HIGHMEM - help - This options enables additional error checking for high memory - systems. Disable for production systems. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - depends on DEBUG_KERNEL - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config KGDB - bool "Include kgdb kernel debugger" - depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx) - select DEBUG_INFO - help - Include in-kernel hooks for kgdb, the Linux kernel source level - debugger. See for more information. - Unless you are intending to debug the kernel, say N here. - -choice - prompt "Serial Port" - depends on KGDB - default KGDB_TTYS1 - -config KGDB_TTYS0 - bool "ttyS0" - -config KGDB_TTYS1 - bool "ttyS1" - -config KGDB_TTYS2 - bool "ttyS2" - -config KGDB_TTYS3 - bool "ttyS3" - -endchoice - -config KGDB_CONSOLE - bool "Enable serial console thru kgdb port" - depends on KGDB && 8xx || CPM2 - help - If you enable this, all serial console messages will be sent - over the gdb stub. - If unsure, say N. - -config XMON - bool "Include xmon kernel debugger" - depends on DEBUG_KERNEL - help - Include in-kernel hooks for the xmon kernel monitor/debugger. - Unless you are intending to debug the kernel, say N here. - -config BDI_SWITCH - bool "Include BDI-2000 user context switcher" - depends on DEBUG_KERNEL - help - Include in-kernel support for the Abatron BDI2000 debugger. - Unless you are intending to debug the kernel with one of these - machines, say N here. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use some sort of debugger to - debug the kernel. - If you don't debug the kernel, you can say N. - -config BOOTX_TEXT - bool "Support for early boot text console (BootX or OpenFirmware only)" - depends PPC_OF - help - Say Y here to see progress messages from the boot firmware in text - mode. Requires either BootX or Open Firmware. - -config SERIAL_TEXT_DEBUG - bool "Support for early boot texts over serial port" - depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx - -config PPC_OCP - bool - depends on IBM_OCP || FSL_OCP - default y - -endmenu +source "arch/ppc/Kconfig.debug" source "security/Kconfig" diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug index 0df281455..d2e1eea8e 100644 --- a/arch/ppc/Kconfig.debug +++ b/arch/ppc/Kconfig.debug @@ -53,18 +53,6 @@ config BDI_SWITCH Unless you are intending to debug the kernel with one of these machines, say N here. -config SCHEDSTATS - bool "Collect scheduler statistics" - depends on DEBUG_KERNEL && PROC_FS - help - If you say Y here, additional code will be inserted into the - scheduler and related routines to collect statistics about - scheduler behavior and provide them in /proc/schedstat. These - stats may be useful for both tuning and debugging the scheduler - If you aren't debugging the scheduler or trying to tune a specific - application, you can say N to avoid the very slight overhead - this adds. - config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" depends PPC_OF @@ -78,7 +66,7 @@ config SERIAL_TEXT_DEBUG config PPC_OCP bool - depends on IBM_OCP || FSL_OCP + depends on IBM_OCP || FSL_OCP || XILINX_OCP default y endmenu diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index e15c6919a..53dd5640d 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -13,7 +13,7 @@ # This must match PAGE_OFFSET in include/asm-ppc/page.h. KERNELLOAD := $(CONFIG_KERNEL_START) -HAS_BIARCH := $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;) +HAS_BIARCH := $(call cc-option-yn, -m32) ifeq ($(HAS_BIARCH),y) AS := $(AS) -a32 LD := $(LD) -m elf32ppc @@ -24,10 +24,10 @@ LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic CPPFLAGS += -Iarch/$(ARCH) AFLAGS += -Iarch/$(ARCH) CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ - -ffixed-r2 -Wno-uninitialized -mmultiple + -ffixed-r2 -mmultiple CPP = $(CC) -E $(CFLAGS) -CHECK := $(CHECK) -D__powerpc__=1 +CHECKFLAGS += -D__powerpc__ ifndef CONFIG_E500 CFLAGS += -mstring @@ -70,7 +70,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm all: zImage -AFLAGS_vmlinux.lds.o := -Upowerpc +CPPFLAGS_vmlinux.lds := -Upowerpc # All the instructions talk about "make bzImage". bzImage: zImage @@ -104,16 +104,15 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s $(call filechk,gen-asm-offsets) -ifdef CONFIG_6xx -# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later -NEW_AS := $(shell echo dssall | $(AS) -many -o /dev/null >/dev/null 2>&1 ; echo $$?) -GOODVER := 2.12.1 -else -NEW_AS := 0 -endif +# Use the file '.tmp_gas_check' for binutils tests, as gas won't output +# to stdout and these checks are run even on install targets. +TOUT := .tmp_gas_check +# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec +# instructions. +AS_ALTIVEC := $(shell echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; echo $$?) # gcc-3.4 and binutils-2.14 are a fatal combination. -GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) -BAD_GCC_AS := $(shell echo mftb 5 | $(AS) -mppc -many -o /dev/null >/dev/null 2>&1 && echo 0 || echo 1) +GCC_VERSION := $(call cc-version) +BAD_GCC_AS := $(shell echo mftb 5 | $(AS) -mppc -many -o $(TOUT) >/dev/null 2>&1 && echo 0 || echo 1) checkbin: ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041) @@ -122,13 +121,16 @@ ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041) @echo '*** Please upgrade your binutils or downgrade your gcc' @false endif -ifneq ($(NEW_AS),0) +ifneq ($(AS_ALTIVEC),0) + echo $(AS_ALTIVEC) @echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' @echo 'correctly with old versions of binutils.' - @echo '*** Please upgrade your binutils to ${GOODVER} or newer' + @echo '*** Please upgrade your binutils to 2.12.1 or newer' @false endif @true CLEAN_FILES += include/asm-$(ARCH)/offsets.h \ - arch/$(ARCH)/kernel/asm-offsets.s + arch/$(ARCH)/kernel/asm-offsets.s \ + $(TOUT) + diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index cc93c9eb3..af881d745 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -423,9 +423,6 @@ void __init config_amiga(void) mach_floppy_setup = amiga_floppy_setup; #endif mach_reset = amiga_reset; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_HEARTBEAT mach_heartbeat = amiga_heartbeat; #endif diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index 8c1d7eb8b..995f89bb0 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -23,12 +23,12 @@ subdir-$(CONFIG_PPC_OF) += of1275 # for cleaning subdir- += simple openfirmware -host-progs := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree) +hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree) .PHONY: $(BOOT_TARGETS) $(bootdir-y) $(BOOT_TARGETS): $(bootdir-y) $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ - $(addprefix $(obj)/,$(host-progs)) + $(addprefix $(obj)/,$(hostprogs-y)) $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c index 868fa81b7..7acd03b31 100644 --- a/arch/ppc/boot/common/misc-common.c +++ b/arch/ppc/boot/common/misc-common.c @@ -17,7 +17,7 @@ #include /* for va_ bits */ #include #include -#include "zlib.h" +#include #include "nonstdio.h" /* If we're on a PReP, assume we have a keyboard controller @@ -202,11 +202,10 @@ void error(char *x) while(1); /* Halt */ } -void *zalloc(void *x, unsigned items, unsigned size) +static void *zalloc(unsigned size) { void *p = avail_ram; - size *= items; size = (size + 7) & -8; avail_ram += size; if (avail_ram > end_avail) { @@ -216,18 +215,12 @@ void *zalloc(void *x, unsigned items, unsigned size) return p; } -void zfree(void *x, void *addr, unsigned nb) -{ -} - #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 -#define DEFLATED 8 - void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; @@ -236,7 +229,7 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) /* skip header */ i = 10; flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { puts("bad gzipped data\n"); exit(); } @@ -255,24 +248,24 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) exit(); } - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); + /* Initialize ourself. */ + s.workspace = zalloc(zlib_inflate_workspacesize()); + r = zlib_inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { - puts("inflateInit2 returned "); puthex(r); puts("\n"); + puts("zlib_inflateInit2 returned "); puthex(r); puts("\n"); exit(); } s.next_in = src + i; s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); + r = zlib_inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { puts("inflate returned "); puthex(r); puts("\n"); exit(); } *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); + zlib_inflateEnd(&s); } void @@ -526,6 +519,11 @@ _dump_buf(unsigned char *p, int s) * on others it's an offset from a given location. -- Tom */ +void ISA_init(unsigned long base) +{ + ISA_io = (unsigned char *)base; +} + void outb(int port, unsigned char val) { diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c index 8eb07a63f..9017c547a 100644 --- a/arch/ppc/boot/common/ns16550.c +++ b/arch/ppc/boot/common/ns16550.c @@ -5,14 +5,14 @@ #include #include #include -#include #include #include +#include "nonstdio.h" +#include "serial.h" + #define SERIAL_BAUD 9600 -extern void outb(int port, unsigned char val); -extern unsigned char inb(int port); extern unsigned long ISA_io; static struct serial_state rs_table[RS_TABLE_SIZE] = { diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c index 2dc176ed0..03dfaa01f 100644 --- a/arch/ppc/boot/common/serial_stub.c +++ b/arch/ppc/boot/common/serial_stub.c @@ -11,11 +11,6 @@ * is" without any warranty of any kind, whether express or implied. */ -void __attribute__ ((weak)) -serial_fixups(void) -{ -} - unsigned long __attribute__ ((weak)) serial_init(int chan, void *ignored) { diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S index 93771e298..d0161ac4c 100644 --- a/arch/ppc/boot/common/util.S +++ b/arch/ppc/boot/common/util.S @@ -27,6 +27,7 @@ .text +#ifdef CONFIG_6xx .globl disable_6xx_mmu disable_6xx_mmu: /* Establish default MSR value, exception prefix 0xFFF. @@ -41,7 +42,7 @@ disable_6xx_mmu: /* Test for a 601 */ mfpvr r10 srwi r10,r10,16 - cmpi 0,r10,1 /* 601 ? */ + cmpwi 0,r10,1 /* 601 ? */ beq .clearbats_601 /* Clear BATs */ @@ -94,6 +95,7 @@ disable_6xx_l1cache: sync isync blr +#endif .globl _setup_L2CR _setup_L2CR: @@ -117,9 +119,9 @@ _setup_L2CR: /* Wait for the invalidation to complete */ mfspr r8,PVR srwi r8,r8,16 - cmpli cr0,r8,0x8000 /* 7450 */ - cmpli cr1,r8,0x8001 /* 7455 */ - cmpli cr2,r8,0x8002 /* 7457 */ + cmplwi cr0,r8,0x8000 /* 7450 */ + cmplwi cr1,r8,0x8001 /* 7455 */ + cmplwi cr2,r8,0x8002 /* 7457 */ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ cror 4*cr0+eq,4*cr0+eq,4*cr2+eq bne 2f @@ -190,7 +192,7 @@ timebase_period_ns: udelay: mfspr r4,PVR srwi r4,r4,16 - cmpi 0,r4,1 /* 601 ? */ + cmpwi 0,r4,1 /* 601 ? */ bne .udelay_not_601 00: li r0,86 /* Instructions / microsecond? */ mtctr r0 @@ -213,16 +215,16 @@ udelay: 1: mftbu r5 mftb r6 mftbu r7 - cmp 0,r5,r7 + cmpw 0,r5,r7 bne 1b /* Get [synced] base time */ addc r9,r6,r4 /* Compute end time */ addze r8,r5 2: mftbu r5 - cmp 0,r5,r8 + cmpw 0,r5,r8 blt 2b bgt 3f mftb r6 - cmp 0,r6,r9 + cmpw 0,r6,r9 blt 2b 3: blr diff --git a/arch/ppc/boot/include/nonstdio.h b/arch/ppc/boot/include/nonstdio.h index 7a0f027f9..f2b5526fa 100644 --- a/arch/ppc/boot/include/nonstdio.h +++ b/arch/ppc/boot/include/nonstdio.h @@ -30,3 +30,5 @@ extern void puthex(unsigned long val); extern void puts(const char *); extern void udelay(long delay); extern unsigned char inb(int port); +extern void board_isa_init(void); +extern void ISA_init(unsigned long base); diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile index 97ef7d19e..d4077e690 100644 --- a/arch/ppc/boot/lib/Makefile +++ b/arch/ppc/boot/lib/Makefile @@ -2,7 +2,22 @@ # Makefile for some libs needed by zImage. # -CFLAGS_kbd.o += -Idrivers/char +CFLAGS_kbd.o := -Idrivers/char +CFLAGS_vreset.o := -I$(srctree)/arch/ppc/boot/include -lib-y := zlib.o div64.o +zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c + +lib-y += $(zlib:.c=.o) div64.o lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o + + +# zlib files needs header from their original place +EXTRA_CFLAGS += -Ilib/zlib_inflate + +quiet_cmd_copy_zlib = COPY $@ + cmd_copy_zlib = cat $< > $@ + +$(addprefix $(obj)/,$(zlib)): $(obj)/%: $(srctree)/lib/zlib_inflate/% + $(call cmd,copy_zlib) + +clean-files := $(zlib) diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c index 94c23c0c9..04ba9d57e 100644 --- a/arch/ppc/boot/openfirmware/coffmain.c +++ b/arch/ppc/boot/openfirmware/coffmain.c @@ -12,7 +12,6 @@ #include "nonstdio.h" #include "of1275.h" -#include "zlib.h" /* Passed from the linker */ extern char __image_begin, __image_end; diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c index 71195067c..9e6952781 100644 --- a/arch/ppc/boot/openfirmware/common.c +++ b/arch/ppc/boot/openfirmware/common.c @@ -7,10 +7,10 @@ * 2 of the License, or (at your option) any later version. */ -#include "zlib.h" #include "nonstdio.h" #include "of1275.h" #include +#include #include #include @@ -30,12 +30,11 @@ struct memchunk { static struct memchunk *freechunks; -static void *zalloc(void *x, unsigned items, unsigned size) +static void *zalloc(unsigned size) { void *p; struct memchunk **mpp, *mp; - size *= items; size = (size + 7) & -8; heap_use += size; if (heap_use > heap_max) @@ -57,74 +56,57 @@ static void *zalloc(void *x, unsigned items, unsigned size) return p; } -static void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = (nb + 7) & -8; - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 -#define DEFLATED 8 - void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n\r"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n\r"); - exit(); - } + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n\r"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + printf("gunzip: ran out of data in header\n\r"); + exit(); + } - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n\r", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n\r", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); + /* Initialize ourself. */ + s.workspace = zalloc(zlib_inflate_workspacesize()); + r = zlib_inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf("zlib_inflateInit2 returned %d\n\r", r); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = zlib_inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf("inflate returned %d msg: %s\n\r", r, s.msg); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + zlib_inflateEnd(&s); } /* Make a bi_rec in OF. We need to be passed a name for BI_BOOTLOADER_ID, diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S index 844c0bca2..ab9e897ca 100644 --- a/arch/ppc/boot/openfirmware/misc.S +++ b/arch/ppc/boot/openfirmware/misc.S @@ -16,7 +16,7 @@ setup_bats: mfpvr 5 rlwinm 5,5,16,16,31 /* r3 = 1 for 601, 4 for 604 */ - cmpi 0,5,1 + cmpwi 0,5,1 li 0,0 bne 4f mtibatl 3,0 /* invalidate BAT first */ diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index e31b7e499..57a9c0fbe 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -41,7 +41,7 @@ end-y := elf # if present on 'classic' PPC. cacheflag-y := -DCLEAR_CACHES="" # This file will flush / disable the L2, and L3 if present. -clear_L2_L3 := $(boot)/simple/clear.S +clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S # # See arch/ppc/kconfig and arch/ppc/platforms/Kconfig @@ -64,6 +64,7 @@ zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE end-$(CONFIG_OCOTEA) := ocotea entrypoint-$(CONFIG_OCOTEA) := 0x01000000 + extra.o-$(CONFIG_OCOTEA) := pibs.o extra.o-$(CONFIG_EV64260) := direct.o misc-ev64260.o end-$(CONFIG_EV64260) := ev64260 @@ -73,7 +74,7 @@ zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF end-$(CONFIG_GEMINI) := gemini - extra.o-$(CONFIG_K2) := legacy.o + extra.o-$(CONFIG_K2) := prepmap.o end-$(CONFIG_K2) := k2 cacheflag-$(CONFIG_K2) := -include $(clear_L2_L3) @@ -89,7 +90,7 @@ zimageinitrd-$(motorola) := zImage.initrd-PPLUS end-$(motorola) := pplus # Overrides previous assingment - extra.o-$(CONFIG_PPLUS) := legacy.o + extra.o-$(CONFIG_PPLUS) := prepmap.o extra.o-$(CONFIG_LOPEC) := mpc10x_memory.o zimage-$(pcore) := zImage-STRIPELF @@ -100,7 +101,7 @@ zimageinitrd-$(pcore) := zImage.initrd-STRIPELF zimage-$(CONFIG_PPC_PREP) := zImage-PPLUS zimageinitrd-$(CONFIG_PPC_PREP) := zImage.initrd-PPLUS - extra.o-$(CONFIG_PPC_PREP) := legacy.o + extra.o-$(CONFIG_PPC_PREP) := prepmap.o misc-$(CONFIG_PPC_PREP) += misc-prep.o mpc10x_memory.o end-$(CONFIG_PPC_PREP) := prep diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c index be0b6ca24..a4fbc3900 100644 --- a/arch/ppc/boot/simple/embed_config.c +++ b/arch/ppc/boot/simple/embed_config.c @@ -749,25 +749,25 @@ embed_config(bd_t ** bdp) static const unsigned long line_size = 32; static const unsigned long congruence_classes = 256; unsigned long addr; - u_char *cp; - int i; + unsigned long dccr; bd_t *bd; /* - * At one point, we were getting machine checks. Linux was not - * invalidating the data cache before it was enabled. The - * following code was added to do that. Soon after we had done - * that, we found the real reasons for the machine checks. I've - * run the kernel a few times with the following code - * temporarily removed without any apparent problems. However, - * I objdump'ed the kernel and boot code and found out that - * there were no other dccci's anywhere, so I put the code back - * in and have been reluctant to remove it. It seems safer to - * just leave it here. + * Invalidate the data cache if the data cache is turned off. + * - The 405 core does not invalidate the data cache on power-up + * or reset but does turn off the data cache. We cannot assume + * that the cache contents are valid. + * - If the data cache is turned on this must have been done by + * a bootloader and we assume that the cache contents are + * valid. */ - for (addr = 0; - addr < (congruence_classes * line_size); addr += line_size) { - __asm__("dccci 0,%0": :"b"(addr)); + __asm__("mfdccr %0": "=r" (dccr)); + if (dccr == 0) { + for (addr = 0; + addr < (congruence_classes * line_size); + addr += line_size) { + __asm__("dccci 0,%0": :"b"(addr)); + } } bd = &bdinfo; @@ -775,6 +775,9 @@ embed_config(bd_t ** bdp) bd->bi_memsize = XPAR_DDR_0_SIZE; bd->bi_intfreq = XPAR_CORE_CLOCK_FREQ_HZ; bd->bi_busfreq = XPAR_PLB_CLOCK_FREQ_HZ; + bd->bi_pci_busfreq = XPAR_PCI_0_CLOCK_FREQ_HZ; + timebase_period_ns = 1000000000 / bd->bi_tbfreq; + /* see bi_tbfreq definition in arch/ppc/platforms/4xx/xilinx_ml300.h */ } #endif /* CONFIG_XILINX_ML300 */ diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c index 58e2a92e8..3865f3f8d 100644 --- a/arch/ppc/boot/simple/misc-embedded.c +++ b/arch/ppc/boot/simple/misc-embedded.c @@ -22,7 +22,6 @@ #endif #include "nonstdio.h" -#include "zlib.h" /* The linker tells us where the image is. */ extern char __image_begin, __image_end; @@ -72,6 +71,14 @@ extern void flush_instruction_cache(void); extern void gunzip(void *, int, unsigned char *, int *); extern void embed_config(bd_t **bp); +/* Weak function for boards which don't need to build the + * board info struct because they are using PPCBoot/U-Boot. + */ +void __attribute__ ((weak)) +embed_config(bd_t **bdp) +{ +} + unsigned long load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) { @@ -211,7 +218,7 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *b puts("done.\n"); { struct bi_record *rec; - unsigned long initrd_loc; + unsigned long initrd_loc = 0; unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) + (1 << 20) - 1, (1 << 20)); rec = (struct bi_record *)rec_loc; diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c index da29deca4..75380ac41 100644 --- a/arch/ppc/boot/simple/misc-prep.c +++ b/arch/ppc/boot/simple/misc-prep.c @@ -88,6 +88,7 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, ofinit(OFW_interface); } + board_isa_init(); #if defined(CONFIG_VGA_CONSOLE) vga_init((unsigned char *)0xC0000000); #endif /* CONFIG_VGA_CONSOLE */ diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c index fa181ffb7..d012c3927 100644 --- a/arch/ppc/boot/simple/misc-spruce.c +++ b/arch/ppc/boot/simple/misc-spruce.c @@ -26,7 +26,6 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, /* Define some important locations of the Spruce. */ #define SPRUCE_PCI_CONFIG_ADDR 0xfec00000 #define SPRUCE_PCI_CONFIG_DATA 0xfec00004 -#define SPRUCE_ISA_IO_BASE 0xf8000000 /* PCI configuration space access routines. */ unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR; @@ -86,8 +85,6 @@ void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, out_le32((unsigned *)pci_config_data, val); } -unsigned long isa_io_base = SPRUCE_ISA_IO_BASE; - #define PCNET32_WIO_RDP 0x10 #define PCNET32_WIO_RAP 0x12 #define PCNET32_WIO_RESET 0x14 diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index f09af4f28..1b2ae8d77 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -29,7 +29,6 @@ #include #include "nonstdio.h" -#include "zlib.h" /* Default cmdline */ #ifdef CONFIG_CMDLINE @@ -49,7 +48,9 @@ * Val Henson has requested that Gemini doesn't wait for the * user to edit the cmdline or not. */ -#if (defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_VGA_CONSOLE)) \ +#if (defined(CONFIG_SERIAL_8250_CONSOLE) \ + || defined(CONFIG_VGA_CONSOLE) \ + || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)) \ && !defined(CONFIG_GEMINI) #define INTERACTIVE_CONSOLE 1 #endif @@ -95,9 +96,8 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) #endif char *cp; struct bi_record *rec; - unsigned long initrd_loc, TotalMemory = 0; + unsigned long initrd_loc = 0, TotalMemory = 0; - serial_fixups(); #ifdef CONFIG_SERIAL_8250_CONSOLE com_port = serial_init(0, NULL); #endif @@ -221,7 +221,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) puts("\n"); puts("Uncompressing Linux..."); - gunzip(NULL, 0x400000, zimage_start, &zimage_size); + gunzip(0x0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); /* get the bi_rec address */ @@ -268,10 +268,16 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) return rec; } +void __attribute__ ((weak)) +board_isa_init(void) +{ +} + /* Allow decompress_kernel to be hooked into. This is the default. */ void * __attribute__ ((weak)) load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, void *ign1, void *ign2) { + board_isa_init(); return decompress_kernel(load_addr, num_words, cksum); } diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c index 8a1c663e7..efde532b4 100644 --- a/arch/ppc/boot/simple/mpc52xx_tty.c +++ b/arch/ppc/boot/simple/mpc52xx_tty.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #if MPC52xx_PF_CONSOLE_PORT == 0 diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S index e57d9673e..555a216cc 100644 --- a/arch/ppc/boot/simple/relocate.S +++ b/arch/ppc/boot/simple/relocate.S @@ -50,7 +50,7 @@ relocate: * Check if we need to relocate ourselves to the link addr or were * we loaded there to begin with. */ - cmp cr0,r3,r4 + cmpw cr0,r3,r4 beq start_ldr /* If 0, we don't need to relocate */ /* Move this code somewhere safe. This is max(load + size, end) @@ -122,7 +122,7 @@ do_relocate: GETSYM(r4, start) mr r3,r8 /* Get the load addr */ - cmp cr0,r4,r3 /* If we need to copy from the end, do so */ + cmpw cr0,r4,r3 /* If we need to copy from the end, do so */ bgt do_relocate_from_end do_relocate_from_start: @@ -165,7 +165,7 @@ start_ldr: subi r4,r4,4 li r0,0 50: stwu r0,4(r3) - cmp cr0,r3,r4 + cmpw cr0,r3,r4 bne 50b 90: mr r9,r1 /* Save old stack pointer (in case it matters) */ lis r1,.stack@h diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c index 8158d8c6f..886122283 100644 --- a/arch/ppc/boot/utils/mkbugboot.c +++ b/arch/ppc/boot/utils/mkbugboot.c @@ -1,5 +1,5 @@ /* - * arch/ppc/pp3boot/mkbugboot.c + * arch/ppc/boot/utils/mkbugboot.c * * Makes a Motorola PPCBUG ROM bootable image which can be flashed * into one of the FLASH banks on a Motorola PowerPlus board. @@ -21,6 +21,11 @@ #include #include #include +#ifdef __sun__ +#include +#else +#include +#endif #ifdef __i386__ #define cpu_to_be32(x) le32_to_cpu(x) @@ -49,11 +54,6 @@ unsigned short le16_to_cpu(unsigned short x) /* size of read buffer */ #define SIZE 0x1000 -/* typedef long int32_t; */ -typedef unsigned long uint32_t; -typedef unsigned short uint16_t; -typedef unsigned char uint8_t; - /* PPCBUG ROM boot header */ typedef struct bug_boot_header { uint8_t magic_word[4]; /* "BOOT" */ @@ -96,7 +96,7 @@ void write_bugboot_header(int32_t out_fd, uint32_t boot_size) uint8_t header_block[HEADER_SIZE]; bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0]; - bzero(header_block, HEADER_SIZE); + memset(header_block, 0, HEADER_SIZE); /* Fill in the PPCBUG ROM boot header */ strncpy(bbh->magic_word, "BOOT", 4); /* PPCBUG magic word */ diff --git a/arch/ppc/boot/utils/mktree.c b/arch/ppc/boot/utils/mktree.c index 7ef98c077..2be22e28f 100644 --- a/arch/ppc/boot/utils/mktree.c +++ b/arch/ppc/boot/utils/mktree.c @@ -15,7 +15,11 @@ #include #include #include +#ifdef __sun__ +#include +#else #include +#endif /* This gets tacked on the front of the image. There are also a few * bytes allocated after the _start label used by the boot rom (see diff --git a/arch/ppc/configs/FADS_defconfig b/arch/ppc/configs/FADS_defconfig index aba7bd86e..c1934f828 100644 --- a/arch/ppc/configs/FADS_defconfig +++ b/arch/ppc/configs/FADS_defconfig @@ -295,25 +295,27 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +# CONFIG_SERIAL_CPM_ALT_SMC2 is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -478,10 +480,6 @@ CONFIG_SCC1_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -# CONFIG_ALTSMC2 is not set -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/IVMS8_defconfig b/arch/ppc/configs/IVMS8_defconfig index 3f5eb23c5..66bbefe8e 100644 --- a/arch/ppc/configs/IVMS8_defconfig +++ b/arch/ppc/configs/IVMS8_defconfig @@ -319,25 +319,26 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +# CONFIG_SERIAL_CPM_SMC2 is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -507,8 +508,6 @@ CONFIG_FEC_LXT970=y CONFIG_FEC_LXT971=y CONFIG_FEC_QS6612=y CONFIG_ENET_BIG_BUFFERS=y -# CONFIG_SMC2_UART is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/SM850_defconfig b/arch/ppc/configs/SM850_defconfig index 9553f567c..021884b43 100644 --- a/arch/ppc/configs/SM850_defconfig +++ b/arch/ppc/configs/SM850_defconfig @@ -92,7 +92,8 @@ CONFIG_KERNEL_ELF=y # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_CMDLINE_BOOL is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyCPM1" # # Advanced setup @@ -296,25 +297,27 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +CONFIG_SERIAL_CPM_ALT_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -479,10 +482,6 @@ CONFIG_SCC_ENET=y CONFIG_SCC3_ENET=y # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -CONFIG_ALTSMC2=y -CONFIG_CONS_SMC2=y -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/SPD823TS_defconfig b/arch/ppc/configs/SPD823TS_defconfig index bc3458b7e..ba60fea2b 100644 --- a/arch/ppc/configs/SPD823TS_defconfig +++ b/arch/ppc/configs/SPD823TS_defconfig @@ -295,25 +295,27 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +# CONFIG_SERIAL_CPM_SMC2 is not set +CONFIG_SERIAL_CPM_ALT_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -478,10 +480,6 @@ CONFIG_SCC2_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -CONFIG_ALTSMC2=y -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/TQM823L_defconfig b/arch/ppc/configs/TQM823L_defconfig index 073a99a2c..3b44f3d79 100644 --- a/arch/ppc/configs/TQM823L_defconfig +++ b/arch/ppc/configs/TQM823L_defconfig @@ -296,25 +296,27 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +CONFIG_SERIAL_CPM_ALT_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -479,10 +481,6 @@ CONFIG_SCC2_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -CONFIG_ALTSMC2=y -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/TQM850L_defconfig b/arch/ppc/configs/TQM850L_defconfig index 5aec1d86f..b02d19630 100644 --- a/arch/ppc/configs/TQM850L_defconfig +++ b/arch/ppc/configs/TQM850L_defconfig @@ -296,25 +296,27 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +CONFIG_SERIAL_CPM_ALT_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -479,10 +481,6 @@ CONFIG_SCC2_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -CONFIG_ALTSMC2=y -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/TQM860L_defconfig b/arch/ppc/configs/TQM860L_defconfig index 469fcb48b..857e4ab28 100644 --- a/arch/ppc/configs/TQM860L_defconfig +++ b/arch/ppc/configs/TQM860L_defconfig @@ -320,25 +320,26 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -508,10 +509,6 @@ CONFIG_SCC1_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -# CONFIG_ALTSMC2 is not set -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/bseip_defconfig b/arch/ppc/configs/bseip_defconfig index 227fd153a..ce9f9f77f 100644 --- a/arch/ppc/configs/bseip_defconfig +++ b/arch/ppc/configs/bseip_defconfig @@ -292,25 +292,26 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -476,10 +477,6 @@ CONFIG_SCC2_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set # CONFIG_ENET_BIG_BUFFERS is not set -CONFIG_SMC2_UART=y -# CONFIG_ALTSMC2 is not set -# CONFIG_CONS_SMC2 is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options diff --git a/arch/ppc/configs/mbx_defconfig b/arch/ppc/configs/mbx_defconfig index 213e69d12..52c3799e6 100644 --- a/arch/ppc/configs/mbx_defconfig +++ b/arch/ppc/configs/mbx_defconfig @@ -289,24 +289,26 @@ CONFIG_SOUND_GAMEPORT=y # Macintosh device drivers # -# -# Character devices -# -# CONFIG_SERIAL_NONSTANDARD is not set - # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +CONFIG_SERIAL_CPM_SCC2=y +CONFIG_SERIAL_CPM_SCC3=y +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set # # I2C support @@ -470,10 +472,6 @@ CONFIG_SCC1_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -# CONFIG_ALTSMC2 is not set -# CONFIG_CONS_SMC2 is not set -CONFIG_USE_SCC_IO=y # # Generic MPC8xx Options diff --git a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig index 6e1a38d72..46776b9c1 100644 --- a/arch/ppc/configs/mvme5100_defconfig +++ b/arch/ppc/configs/mvme5100_defconfig @@ -1,26 +1,48 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.9-rc2 +# Wed Sep 22 09:53:26 2004 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -33,24 +55,26 @@ CONFIG_OBSOLETE_MODPARM=y CONFIG_KMOD=y # -# Platform support +# Processor # -CONFIG_PPC=y -CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_40x is not set +# CONFIG_44x is not set # CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8xx is not set +# CONFIG_E500 is not set +CONFIG_ALTIVEC=y +# CONFIG_TAU is not set +# CONFIG_CPU_FREQ is not set +CONFIG_PPC_STD_MMU=y # -# IBM 4xx options +# Platform options # -# CONFIG_8260 is not set -CONFIG_GENERIC_ISA_DMA=y -CONFIG_PPC_STD_MMU=y # CONFIG_PPC_MULTIPLATFORM is not set # CONFIG_APUS is not set -# CONFIG_WILLOW_2 is not set +# CONFIG_WILLOW is not set # CONFIG_PCORE is not set # CONFIG_POWERPMC250 is not set # CONFIG_EV64260 is not set @@ -66,34 +90,30 @@ CONFIG_MVME5100=y # CONFIG_K2 is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_LITE5200 is not set # CONFIG_MVME5100_IPMC761_PRESENT is not set # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -CONFIG_ALTIVEC=y -# CONFIG_TAU is not set -# CONFIG_CPU_FREQ is not set +# CONFIG_HIGHMEM is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" # -# General setup +# Bus options # -# CONFIG_HIGHMEM is not set +CONFIG_GENERIC_ISA_DMA=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_KERNEL_ELF=y -# CONFIG_BINFMT_MISC is not set # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PPC601_SYNC_FIX is not set -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="ip=on" # # Advanced setup @@ -109,15 +129,29 @@ CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 CONFIG_BOOT_LOAD=0x00800000 +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + # # Memory Technology Devices (MTD) # # CONFIG_MTD is not set +# +# Parallel port support +# +# CONFIG_PARPORT is not set + # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -129,46 +163,46 @@ CONFIG_BOOT_LOAD=0x00800000 # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set # CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -184,64 +218,70 @@ CONFIG_BLK_DEV_SR=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set + # # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX 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_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA 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_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -CONFIG_SCSI_SYM53C8XX=y -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=20 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + # # Fusion MPT device support # # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set @@ -250,6 +290,10 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # # CONFIG_I2O is not set +# +# Macintosh device drivers +# + # # Networking support # @@ -261,86 +305,90 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set # # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m +# CONFIG_IP_NF_MATCH_LIMIT is not set +# CONFIG_IP_NF_MATCH_IPRANGE is not set +# CONFIG_IP_NF_MATCH_MAC is not set +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +# CONFIG_IP_NF_MATCH_MARK is not set +# CONFIG_IP_NF_MATCH_MULTIPORT is not set +# CONFIG_IP_NF_MATCH_TOS is not set +# CONFIG_IP_NF_MATCH_RECENT is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_DSCP is not set +# CONFIG_IP_NF_MATCH_AH_ESP 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 CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_MATCH_STATE is not set +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +# CONFIG_IP_NF_MATCH_OWNER is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +# CONFIG_IP_NF_MATCH_SCTP is not set +# CONFIG_IP_NF_FILTER is not set # CONFIG_IP_NF_TARGET_LOG is not set -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m +# CONFIG_IP_NF_TARGET_ULOG is not set +# CONFIG_IP_NF_TARGET_TCPMSS is not set +# CONFIG_IP_NF_NAT is not set +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set # CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=y # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -352,29 +400,33 @@ CONFIG_IPV6_SCTP__=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -382,17 +434,26 @@ CONFIG_MII=y # # Tulip family network device support # -# CONFIG_NET_TULIP is not set +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_NAPI is not set +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set # CONFIG_HP100 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set -CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PIO is not set -# CONFIG_E100 is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -403,6 +464,7 @@ CONFIG_EEPRO100=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -421,52 +483,39 @@ CONFIG_EEPRO100=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set # -# Token Ring devices (depends on LLC=y) +# Wireless LAN (non-hamradio) # -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # -# Graphics support +# Telephony Support # -# CONFIG_FB is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_PHONE is not set # # Input device support @@ -483,18 +532,16 @@ CONFIG_EEPRO100=y # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # # Input Device Drivers # -# -# Macintosh device drivers -# - # # Character devices # +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -502,6 +549,7 @@ CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -510,27 +558,8 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # # IPMI @@ -551,11 +580,23 @@ CONFIG_GEN_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# # # Multimedia devices @@ -567,6 +608,26 @@ CONFIG_GEN_RTC=y # # CONFIG_DVB is not set +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + # # File systems # @@ -592,17 +653,20 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -611,6 +675,7 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -625,19 +690,21 @@ CONFIG_RAMFS=y # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -647,31 +714,26 @@ CONFIG_SUNRPC=y CONFIG_MSDOS_PARTITION=y # -# Sound +# Native Language Support # -# CONFIG_SOUND is not set +# CONFIG_NLS is not set # -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support +# Library routines # -# CONFIG_BT is not set +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set # -# Library routines +# Profiling support # -# CONFIG_CRC32 is not set +# CONFIG_PROFILING is not set # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set -# CONFIG_KALLSYMS is not set # # Security options diff --git a/arch/ppc/configs/rpxcllf_defconfig b/arch/ppc/configs/rpxcllf_defconfig index be4538031..cf932f13f 100644 --- a/arch/ppc/configs/rpxcllf_defconfig +++ b/arch/ppc/configs/rpxcllf_defconfig @@ -1,26 +1,49 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1 +# Mon Nov 1 16:41:04 2004 # CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y # # General setup # -CONFIG_SWAP=y +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y -CONFIG_FUTEX=y +# CONFIG_KALLSYMS is not set +# CONFIG_FUTEX is not set # CONFIG_EPOLL is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_SHMEM is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_TINY_SHMEM=y # # Loadable module support @@ -28,21 +51,23 @@ CONFIG_FUTEX=y # CONFIG_MODULES is not set # -# Platform support +# Processor # -CONFIG_PPC=y -CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_40x is not set +# CONFIG_44x is not set # CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set CONFIG_8xx=y +# CONFIG_E500 is not set +CONFIG_MATH_EMULATION=y +# CONFIG_CPU_FREQ is not set +CONFIG_EMBEDDEDBOOT=y +CONFIG_NOT_COHERENT_CACHE=y # -# IBM 4xx options +# Platform options # -CONFIG_EMBEDDEDBOOT=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_NOT_COHERENT_CACHE=y # CONFIG_RPXLITE is not set CONFIG_RPXCLASSIC=y # CONFIG_BSEIP is not set @@ -66,27 +91,17 @@ CONFIG_RPXCLASSIC=y # CONFIG_WINCEPT is not set # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -CONFIG_MATH_EMULATION=y -# CONFIG_CPU_FREQ is not set - -# -# General setup -# # CONFIG_HIGHMEM is not set -# CONFIG_PCI is not set -# CONFIG_PCI_DOMAINS is not set -# CONFIG_PCI_QSPAN is not set -CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y -CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_HOTPLUG is not set +# CONFIG_CMDLINE_BOOL is not set # -# Parallel port support +# Bus options # -# CONFIG_PARPORT is not set -# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_QSPAN is not set # # Advanced setup @@ -100,51 +115,88 @@ CONFIG_HIGHMEM_START=0xfe000000 CONFIG_LOWMEM_SIZE=0x30000000 CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 CONFIG_BOOT_LOAD=0x00400000 +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + # # Memory Technology Devices (MTD) # # CONFIG_MTD is not set +# +# Parallel port support +# +# CONFIG_PARPORT is not set + # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_LBD is not set +# CONFIG_CDROM_PKTCDVD is not set # -# Multi-device support (RAID and LVM) +# IO Schedulers # -# CONFIG_MD is not set +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set # -# SCSI support +# SCSI device support # # CONFIG_SCSI is not set +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + # # Fusion MPT device support # +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + # # I2O device support # +# +# Macintosh device drivers +# + # # Networking support # @@ -156,66 +208,70 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y +# CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set # CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MII=y +# CONFIG_MII is not set # CONFIG_OAKNET is not set # @@ -225,48 +281,34 @@ CONFIG_MII=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set - -# -# Graphics support -# -# CONFIG_FB is not set +# CONFIG_ISDN is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Telephony Support # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_PHONE is not set # # Input device support @@ -283,54 +325,38 @@ CONFIG_MII=y # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # # Input Device Drivers # -# -# Macintosh device drivers -# - # # Character devices # +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +CONFIG_SERIAL_CPM_SCC2=y +CONFIG_SERIAL_CPM_SCC3=y +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +CONFIG_SERIAL_CPM_SMC2=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_LEGACY_PTYS is not set # # IPMI @@ -346,16 +372,27 @@ CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# # # Multimedia devices @@ -367,6 +404,27 @@ CONFIG_GEN_RTC=y # # CONFIG_DVB is not set +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + # # File systems # @@ -385,6 +443,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -397,17 +456,22 @@ CONFIG_FS_MBCACHE=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -416,6 +480,7 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -432,17 +497,18 @@ CONFIG_RAMFS=y CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -456,16 +522,15 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set # -# Sound +# Native Language Support # -# CONFIG_SOUND is not set +# CONFIG_NLS is not set # # MPC8xx CPM Options @@ -477,42 +542,38 @@ CONFIG_SCC1_ENET=y CONFIG_FEC_ENET=y # CONFIG_USE_MDIO is not set CONFIG_ENET_BIG_BUFFERS=y -CONFIG_SMC2_UART=y -# CONFIG_ALTSMC2 is not set -# CONFIG_CONS_SMC2 is not set -CONFIG_USE_SCC_IO=y # # Generic MPC8xx Options # CONFIG_8xx_COPYBACK=y # CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set +CONFIG_NO_UCODE_PATCH=y +# CONFIG_USB_SOF_UCODE_PATCH is not set +# CONFIG_I2C_SPI_UCODE_PATCH is not set +# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set # -# Bluetooth support +# Library routines # -# CONFIG_BT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set # -# Library routines +# Profiling support # -# CONFIG_CRC32 is not set +# CONFIG_PROFILING is not set # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set -# CONFIG_KALLSYMS is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/ppc/configs/rpxlite_defconfig b/arch/ppc/configs/rpxlite_defconfig index 06e818a1f..828dd6eb5 100644 --- a/arch/ppc/configs/rpxlite_defconfig +++ b/arch/ppc/configs/rpxlite_defconfig @@ -1,26 +1,49 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1 +# Mon Nov 1 16:41:09 2004 # CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y # # General setup # -CONFIG_SWAP=y +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y -CONFIG_FUTEX=y +# CONFIG_KALLSYMS is not set +# CONFIG_FUTEX is not set # CONFIG_EPOLL is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_SHMEM is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_TINY_SHMEM=y # # Loadable module support @@ -28,21 +51,23 @@ CONFIG_FUTEX=y # CONFIG_MODULES is not set # -# Platform support +# Processor # -CONFIG_PPC=y -CONFIG_PPC32=y # CONFIG_6xx is not set # CONFIG_40x is not set +# CONFIG_44x is not set # CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set CONFIG_8xx=y +# CONFIG_E500 is not set +CONFIG_MATH_EMULATION=y +# CONFIG_CPU_FREQ is not set +CONFIG_EMBEDDEDBOOT=y +CONFIG_NOT_COHERENT_CACHE=y # -# IBM 4xx options +# Platform options # -CONFIG_EMBEDDEDBOOT=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_NOT_COHERENT_CACHE=y CONFIG_RPXLITE=y # CONFIG_RPXCLASSIC is not set # CONFIG_BSEIP is not set @@ -66,27 +91,17 @@ CONFIG_RPXLITE=y # CONFIG_WINCEPT is not set # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -CONFIG_MATH_EMULATION=y -# CONFIG_CPU_FREQ is not set - -# -# General setup -# # CONFIG_HIGHMEM is not set -# CONFIG_PCI is not set -# CONFIG_PCI_DOMAINS is not set -# CONFIG_PCI_QSPAN is not set -CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y -CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_HOTPLUG is not set +# CONFIG_CMDLINE_BOOL is not set # -# Parallel port support +# Bus options # -# CONFIG_PARPORT is not set -# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS is not set +# CONFIG_PCI_QSPAN is not set # # Advanced setup @@ -100,51 +115,88 @@ CONFIG_HIGHMEM_START=0xfe000000 CONFIG_LOWMEM_SIZE=0x30000000 CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 CONFIG_BOOT_LOAD=0x00400000 +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + # # Memory Technology Devices (MTD) # # CONFIG_MTD is not set +# +# Parallel port support +# +# CONFIG_PARPORT is not set + # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_LBD is not set +# CONFIG_CDROM_PKTCDVD is not set # -# Multi-device support (RAID and LVM) +# IO Schedulers # -# CONFIG_MD is not set +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set # -# SCSI support +# SCSI device support # # CONFIG_SCSI is not set +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + # # Fusion MPT device support # +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + # # I2O device support # +# +# Macintosh device drivers +# + # # Networking support # @@ -156,60 +208,64 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_DHCP is not set CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y +# CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set # CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) @@ -225,48 +281,34 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -# CONFIG_PPP is not set -# CONFIG_SLIP is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Wireless LAN (non-hamradio) # -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set - -# -# Graphics support -# -# CONFIG_FB is not set +# CONFIG_ISDN is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Telephony Support # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_PHONE is not set # # Input device support @@ -283,54 +325,38 @@ CONFIG_NET_ETHERNET=y # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # # Input Device Drivers # -# -# Macintosh device drivers -# - # # Character devices # +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_CPM=y +CONFIG_SERIAL_CPM_CONSOLE=y +# CONFIG_SERIAL_CPM_SCC1 is not set +# CONFIG_SERIAL_CPM_SCC2 is not set +# CONFIG_SERIAL_CPM_SCC3 is not set +# CONFIG_SERIAL_CPM_SCC4 is not set +CONFIG_SERIAL_CPM_SMC1=y +# CONFIG_SERIAL_CPM_SMC2 is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_LEGACY_PTYS is not set # # IPMI @@ -346,16 +372,27 @@ CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# # # Multimedia devices @@ -367,6 +404,27 @@ CONFIG_GEN_RTC=y # # CONFIG_DVB is not set +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + # # File systems # @@ -385,6 +443,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -397,17 +456,22 @@ CONFIG_FS_MBCACHE=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -416,6 +480,7 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -432,17 +497,18 @@ CONFIG_RAMFS=y CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -456,16 +522,15 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set # -# Sound +# Native Language Support # -# CONFIG_SOUND is not set +# CONFIG_NLS is not set # # MPC8xx CPM Options @@ -476,40 +541,38 @@ CONFIG_SCC2_ENET=y # CONFIG_SCC3_ENET is not set # CONFIG_FEC_ENET is not set # CONFIG_ENET_BIG_BUFFERS is not set -# CONFIG_SMC2_UART is not set -# CONFIG_USE_SCC_IO is not set # # Generic MPC8xx Options # CONFIG_8xx_COPYBACK=y # CONFIG_8xx_CPU6 is not set -# CONFIG_UCODE_PATCH is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set +CONFIG_NO_UCODE_PATCH=y +# CONFIG_USB_SOF_UCODE_PATCH is not set +# CONFIG_I2C_SPI_UCODE_PATCH is not set +# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set # -# Bluetooth support +# Library routines # -# CONFIG_BT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set # -# Library routines +# Profiling support # -# CONFIG_CRC32 is not set +# CONFIG_PROFILING is not set # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set -# CONFIG_KALLSYMS is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 2531070a6..7d0abfff4 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -9,7 +9,7 @@ extra-$(CONFIG_E500) := head_e500.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o extra-$(CONFIG_POWER4) += idle_power4.o -extra-y += vmlinux.lds.s +extra-y += vmlinux.lds obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ @@ -25,7 +25,7 @@ obj-$(CONFIG_SMP) += smp.o smp-tbsync.o obj-$(CONFIG_TAU) += temp.o obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o -ifdef CONFIG_MATH_EMULATION +ifndef CONFIG_MATH_EMULATION obj-$(CONFIG_8xx) += softemu8xx.o endif diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c index 39f51985e..c7d99f033 100644 --- a/arch/ppc/kernel/align.c +++ b/arch/ppc/kernel/align.c @@ -37,6 +37,7 @@ struct aligninfo { #define U 0x10 /* update index register */ #define M 0x20 /* multiple load/store */ #define S 0x40 /* single-precision fp, or byte-swap value */ +#define SX 0x40 /* byte count in XER */ #define HARD 0x80 /* string, stwcx. */ #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ @@ -88,10 +89,10 @@ static struct aligninfo aligninfo[128] = { INVALID, /* 01 0 0101: lwax */ INVALID, /* 01 0 0110 */ INVALID, /* 01 0 0111 */ - { 0, LD+HARD }, /* 01 0 1000: lswx */ - { 0, LD+HARD }, /* 01 0 1001: lswi */ - { 0, ST+HARD }, /* 01 0 1010: stswx */ - { 0, ST+HARD }, /* 01 0 1011: stswi */ + { 4, LD+M+HARD+SX }, /* 01 0 1000: lswx */ + { 4, LD+M+HARD }, /* 01 0 1001: lswi */ + { 4, ST+M+HARD+SX }, /* 01 0 1010: stswx */ + { 4, ST+M+HARD }, /* 01 0 1011: stswi */ INVALID, /* 01 0 1100 */ INVALID, /* 01 0 1101 */ INVALID, /* 01 0 1110 */ @@ -189,7 +190,9 @@ fix_alignment(struct pt_regs *regs) #endif int i, t; int reg, areg; + int offset, nb0; unsigned char __user *addr; + unsigned char *rptr; union { long l; float f; @@ -206,7 +209,8 @@ fix_alignment(struct pt_regs *regs) * an alignment fault. -- paulus */ - instr = *((unsigned int *)regs->nip); + if (__get_user(instr, (unsigned int __user *) regs->nip)) + return 0; opcode = OPCD(instr); reg = RS(instr); areg = RA(instr); @@ -230,7 +234,7 @@ fix_alignment(struct pt_regs *regs) nb = aligninfo[instr].len; if (nb == 0) { - long *p; + long __user *p; int i; if (instr != DCBZ) @@ -242,13 +246,19 @@ fix_alignment(struct pt_regs *regs) * case when we are running with the cache disabled * for debugging. */ - p = (long *) (regs->dar & -L1_CACHE_BYTES); + p = (long __user *) (regs->dar & -L1_CACHE_BYTES); + if (user_mode(regs) + && verify_area(VERIFY_WRITE, p, L1_CACHE_BYTES)) + return -EFAULT; for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i) - p[i] = 0; + if (__put_user(0, p+i)) + return -EFAULT; return 1; } flags = aligninfo[instr].flags; + if ((flags & (LD|ST)) == 0) + return 0; /* For the 4xx-family & Book-E processors, the 'dar' field of the * pt_regs structure is overloaded and is really from the DEAR. @@ -256,6 +266,66 @@ fix_alignment(struct pt_regs *regs) addr = (unsigned char __user *)regs->dar; + if (flags & M) { + /* lmw, stmw, lswi/x, stswi/x */ + nb0 = 0; + if (flags & HARD) { + if (flags & SX) { + nb = regs->xer & 127; + if (nb == 0) + return 1; + } else { + if (__get_user(instr, + (unsigned int __user *)regs->nip)) + return 0; + nb = (instr >> 11) & 0x1f; + if (nb == 0) + nb = 32; + } + if (nb + reg * 4 > 128) { + nb0 = nb + reg * 4 - 128; + nb = 128 - reg * 4; + } + } else { + /* lwm, stmw */ + nb = (32 - reg) * 4; + } + rptr = (unsigned char *) ®s->gpr[reg]; + if (flags & LD) { + for (i = 0; i < nb; ++i) + if (__get_user(rptr[i], addr+i)) + return -EFAULT; + if (nb0 > 0) { + rptr = (unsigned char *) ®s->gpr[0]; + addr += nb; + for (i = 0; i < nb0; ++i) + if (__get_user(rptr[i], addr+i)) + return -EFAULT; + } + for (; (i & 3) != 0; ++i) + rptr[i] = 0; + } else { + for (i = 0; i < nb; ++i) + if (__put_user(rptr[i], addr+i)) + return -EFAULT; + if (nb0 > 0) { + rptr = (unsigned char *) ®s->gpr[0]; + addr += nb; + for (i = 0; i < nb0; ++i) + if (__put_user(rptr[i], addr+i)) + return -EFAULT; + } + } + return 1; + } + + offset = 0; + if (nb < 4) { + /* read/write the least significant bits */ + data.l = 0; + offset = 4 - nb; + } + /* Verify the address of the operand */ if (user_mode(regs)) { if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb)) @@ -268,45 +338,26 @@ fix_alignment(struct pt_regs *regs) giveup_fpu(current); preempt_enable(); } - if (flags & M) - return 0; /* too hard for now */ - /* If we read the operand, copy it in */ + /* If we read the operand, copy it in, else get register values */ if (flags & LD) { - if (nb == 2) { - data.v[0] = data.v[1] = 0; - if (__get_user(data.v[2], addr) - || __get_user(data.v[3], addr+1)) + for (i = 0; i < nb; ++i) + if (__get_user(data.v[offset+i], addr+i)) return -EFAULT; - } else { - for (i = 0; i < nb; ++i) - if (__get_user(data.v[i], addr+i)) - return -EFAULT; - } + } else if (flags & F) { + data.d = current->thread.fpr[reg]; + } else { + data.l = regs->gpr[reg]; } switch (flags & ~U) { - case LD+SE: + case LD+SE: /* sign extend */ if (data.v[2] >= 0x80) data.v[0] = data.v[1] = -1; - /* fall through */ - case LD: - regs->gpr[reg] = data.l; - break; - case LD+S: - if (nb == 2) { - SWAP(data.v[2], data.v[3]); - } else { - SWAP(data.v[0], data.v[3]); - SWAP(data.v[1], data.v[2]); - } - regs->gpr[reg] = data.l; - break; - case ST: - data.l = regs->gpr[reg]; break; + + case LD+S: /* byte-swap */ case ST+S: - data.l = regs->gpr[reg]; if (nb == 2) { SWAP(data.v[2], data.v[3]); } else { @@ -314,50 +365,34 @@ fix_alignment(struct pt_regs *regs) SWAP(data.v[1], data.v[2]); } break; - case LD+F: - current->thread.fpr[reg] = data.d; - break; - case ST+F: - data.d = current->thread.fpr[reg]; - break; - /* these require some floating point conversions... */ - /* we'd like to use the assignment, but we have to compile - * the kernel with -msoft-float so it doesn't use the - * fp regs for copying 8-byte objects. */ + + /* Single-precision FP load and store require conversions... */ case LD+F+S: preempt_disable(); enable_kernel_fp(); - cvt_fd(&data.f, ¤t->thread.fpr[reg], ¤t->thread.fpscr); - /* current->thread.fpr[reg] = data.f; */ + cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); preempt_enable(); break; case ST+F+S: preempt_disable(); enable_kernel_fp(); - cvt_df(¤t->thread.fpr[reg], &data.f, ¤t->thread.fpscr); - /* data.f = current->thread.fpr[reg]; */ + cvt_df(&data.d, &data.f, ¤t->thread.fpscr); preempt_enable(); break; - default: - printk("align: can't handle flags=%x\n", flags); - return 0; } if (flags & ST) { - if (nb == 2) { - if (__put_user(data.v[2], addr) - || __put_user(data.v[3], addr+1)) + for (i = 0; i < nb; ++i) + if (__put_user(data.v[offset+i], addr+i)) return -EFAULT; - } else { - for (i = 0; i < nb; ++i) - if (__put_user(data.v[i], addr+i)) - return -EFAULT; - } + } else if (flags & F) { + current->thread.fpr[reg] = data.d; + } else { + regs->gpr[reg] = data.l; } - if (flags & U) { + if (flags & U) regs->gpr[areg] = regs->dar; - } return 1; } diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index 1999a42d8..946ea9922 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -129,6 +129,13 @@ main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); + DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); return 0; } diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c index c00bad67d..7f53d1939 100644 --- a/arch/ppc/kernel/bitops.c +++ b/arch/ppc/kernel/bitops.c @@ -3,7 +3,7 @@ */ #include -#include +#include /* * If the bitops are not inlined in bitops.h, they are defined here. diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index ee0705c6e..e42049f3e 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S @@ -172,9 +172,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) setup_750cx: mfspr r10, SPRN_HID1 rlwinm r10,r10,4,28,31 - cmpi cr0,r10,7 - cmpi cr1,r10,9 - cmpi cr2,r10,11 + cmpwi cr0,r10,7 + cmpwi cr1,r10,9 + cmpwi cr2,r10,11 cror 4*cr0+eq,4*cr0+eq,4*cr1+eq cror 4*cr0+eq,4*cr0+eq,4*cr2+eq bnelr @@ -218,10 +218,10 @@ setup_745x_specifics: /* All of the bits we have to set..... */ - ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK + ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC BEGIN_FTR_SECTION - ori r11,r11,HID0_BTIC -END_FTR_SECTION_IFCLR(CPU_FTR_NO_BTIC) + xori r11,r11,HID0_BTIC +END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) BEGIN_FTR_SECTION oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) @@ -287,12 +287,12 @@ _GLOBAL(__save_cpu_setup) /* Now deal with CPU type dependent registers */ mfspr r3,PVR srwi r3,r3,16 - cmpli cr0,r3,0x8000 /* 7450 */ - cmpli cr1,r3,0x000c /* 7400 */ - cmpli cr2,r3,0x800c /* 7410 */ - cmpli cr3,r3,0x8001 /* 7455 */ - cmpli cr4,r3,0x8002 /* 7457 */ - cmpli cr5,r3,0x7000 /* 750FX */ + cmplwi cr0,r3,0x8000 /* 7450 */ + cmplwi cr1,r3,0x000c /* 7400 */ + cmplwi cr2,r3,0x800c /* 7410 */ + cmplwi cr3,r3,0x8001 /* 7455 */ + cmplwi cr4,r3,0x8002 /* 7457 */ + cmplwi cr5,r3,0x7000 /* 750FX */ /* cr1 is 7400 || 7410 */ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq /* cr0 is 74xx */ @@ -323,7 +323,7 @@ _GLOBAL(__save_cpu_setup) /* If rev 2.x, backup HID2 */ mfspr r3,PVR andi. r3,r3,0xff00 - cmpi cr0,r3,0x0200 + cmpwi cr0,r3,0x0200 bne 1f mfspr r4,SPRN_HID2 stw r4,CS_HID2(r5) @@ -354,12 +354,12 @@ _GLOBAL(__restore_cpu_setup) /* Now deal with CPU type dependent registers */ mfspr r3,PVR srwi r3,r3,16 - cmpli cr0,r3,0x8000 /* 7450 */ - cmpli cr1,r3,0x000c /* 7400 */ - cmpli cr2,r3,0x800c /* 7410 */ - cmpli cr3,r3,0x8001 /* 7455 */ - cmpli cr4,r3,0x8002 /* 7457 */ - cmpli cr5,r3,0x7000 /* 750FX */ + cmplwi cr0,r3,0x8000 /* 7450 */ + cmplwi cr1,r3,0x000c /* 7400 */ + cmplwi cr2,r3,0x800c /* 7410 */ + cmplwi cr3,r3,0x8001 /* 7455 */ + cmplwi cr4,r3,0x8002 /* 7457 */ + cmplwi cr5,r3,0x7000 /* 750FX */ /* cr1 is 7400 || 7410 */ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq /* cr0 is 74xx */ @@ -412,7 +412,7 @@ _GLOBAL(__restore_cpu_setup) /* If rev 2.x, restore HID2 with low voltage bit cleared */ mfspr r3,PVR andi. r3,r3,0xff00 - cmpi cr0,r3,0x0200 + cmpwi cr0,r3,0x0200 bne 4f lwz r4,CS_HID2(r5) rlwinm r4,r4,0,19,17 @@ -426,7 +426,7 @@ _GLOBAL(__restore_cpu_setup) mftbl r5 3: mftbl r6 sub r6,r6,r5 - cmpli cr0,r6,10000 + cmplwi cr0,r6,10000 ble 3b /* Setup final PLL */ mtspr SPRN_HID1,r4 diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S index 6a6ee985c..f2ea1a990 100644 --- a/arch/ppc/kernel/cpu_setup_power4.S +++ b/arch/ppc/kernel/cpu_setup_power4.S @@ -112,7 +112,9 @@ _GLOBAL(__save_cpu_setup) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR srwi r0,r0,16 - cmpwi r0,0x39 + cmpwi cr0,r0,0x39 + cmpwi cr1,r0,0x3c + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq bne 1f /* Save HID0,1,4 and 5 */ @@ -144,7 +146,9 @@ _GLOBAL(__restore_cpu_setup) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR srwi r0,r0,16 - cmpwi r0,0x39 + cmpwi cr0,r0,0x39 + cmpwi cr1,r0,0x3c + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq bne 1f /* Clear interrupt prefix */ diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index b60fa998b..c86b4b224 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -30,7 +30,6 @@ extern void __setup_cpu_745x(unsigned long offset, int cpu_nr, struct cpu_spec* extern void __setup_cpu_power3(unsigned long offset, int cpu_nr, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, int cpu_nr, struct cpu_spec* spec); extern void __setup_cpu_ppc970(unsigned long offset, int cpu_nr, struct cpu_spec* spec); -extern void __setup_cpu_8xx(unsigned long offset, int cpu_nr, struct cpu_spec* spec); extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spec* spec); #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ @@ -48,14 +47,23 @@ extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spe */ #ifdef CONFIG_ALTIVEC #define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC -#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC +#define PPC_FEATURE_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC #else #define CPU_FTR_ALTIVEC_COMP 0 #define PPC_FEATURE_ALTIVEC_COMP 0 #endif +/* We only set the spe features if the kernel was compiled with + * spe support + */ +#ifdef CONFIG_SPE +#define PPC_FEATURE_SPE_COMP PPC_FEATURE_HAS_SPE +#else +#define PPC_FEATURE_SPE_COMP 0 +#endif + /* We need to mark all pages as being coherent if we're SMP or we - * have a 754x and an MPC107 host bridge. + * have a 74[45]x and an MPC107 host bridge. */ #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) #define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT @@ -63,547 +71,840 @@ extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spe #define CPU_FTR_COMMON 0 #endif +/* The powersave features NAP & DOZE seems to confuse BDI when + debugging. So if a BDI is used, disable theses + */ +#ifndef CONFIG_BDI_SWITCH +#define CPU_FTR_MAYBE_CAN_DOZE CPU_FTR_CAN_DOZE +#define CPU_FTR_MAYBE_CAN_NAP CPU_FTR_CAN_NAP +#else +#define CPU_FTR_MAYBE_CAN_DOZE 0 +#define CPU_FTR_MAYBE_CAN_NAP 0 +#endif + struct cpu_spec cpu_specs[] = { #if CLASSIC_PPC - { /* 601 */ - 0xffff0000, 0x00010000, "601", - CPU_FTR_COMMON | - CPU_FTR_601 | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_601_INSTR | PPC_FEATURE_UNIFIED_CACHE, - 32, 32, - __setup_cpu_601 - }, - { /* 603 */ - 0xffff0000, 0x00030000, "603", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_603 - }, - { /* 603e */ - 0xffff0000, 0x00060000, "603e", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_603 - }, - { /* 603ev */ - 0xffff0000, 0x00070000, "603ev", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_603 - }, - { /* 604 */ - 0xffff0000, 0x00040000, "604", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | - CPU_FTR_HPTE_TABLE, - COMMON_PPC, - 32, 32, - __setup_cpu_604 - }, - { /* 604e */ - 0xfffff000, 0x00090000, "604e", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | - CPU_FTR_HPTE_TABLE, - COMMON_PPC, - 32, 32, - __setup_cpu_604 - }, - { /* 604r */ - 0xffff0000, 0x00090000, "604r", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | - CPU_FTR_HPTE_TABLE, - COMMON_PPC, - 32, 32, - __setup_cpu_604 - }, - { /* 604ev */ - 0xffff0000, 0x000a0000, "604ev", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | - CPU_FTR_HPTE_TABLE, - COMMON_PPC, - 32, 32, - __setup_cpu_604 - }, - { /* 740/750 (0x4202, don't support TAU ?) */ - 0xffffffff, 0x00084202, "740/750", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750 - }, - { /* 745/755 */ - 0xfffff000, 0x00083000, "745/755", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750 - }, - { /* 750CX (80100 and 8010x?) */ - 0xfffffff0, 0x00080100, "750CX", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750cx - }, - { /* 750CX (82201 and 82202) */ - 0xfffffff0, 0x00082200, "750CX", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750cx - }, - { /* 750CXe (82214) */ - 0xfffffff0, 0x00082210, "750CXe", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750cx - }, - { /* 750FX rev 1.x */ - 0xffffff00, 0x70000100, "750FX", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, - COMMON_PPC, - 32, 32, - __setup_cpu_750 - }, - { /* 750FX rev 2.0 must disable HID0[DPM] */ - 0xffffffff, 0x70000200, "750FX", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | - CPU_FTR_NO_DPM, - COMMON_PPC, - 32, 32, - __setup_cpu_750 - }, - { /* 750FX (All revs except 2.0) */ - 0xffff0000, 0x70000000, "750FX", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, - COMMON_PPC, - 32, 32, - __setup_cpu_750fx - }, - { /* 750GX */ - 0xffff0000, 0x70020000, "750GX", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | - CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, - COMMON_PPC, - 32, 32, - __setup_cpu_750fx - }, - { /* 740/750 (L2CR bit need fixup for 740) */ - 0xffff0000, 0x00080000, "740/750", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP, - COMMON_PPC, - 32, 32, - __setup_cpu_750 - }, - { /* 7400 rev 1.1 ? (no TAU) */ - 0xffffffff, 0x000c1101, "7400 (1.1)", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_CAN_NAP, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_7400 - }, - { /* 7400 */ - 0xffff0000, 0x000c0000, "7400", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_CAN_NAP, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_7400 - }, - { /* 7410 */ - 0xffff0000, 0x800c0000, "7410", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | - CPU_FTR_CAN_NAP, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_7410 - }, - { /* 7450 2.0 - no doze/nap */ - 0xffffffff, 0x80000200, "7450", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7450 2.1 */ - 0xffffffff, 0x80000201, "7450", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7450 2.3 and newer */ - 0xffff0000, 0x80000000, "7450", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7455 rev 1.x */ - 0xffffff00, 0x80010100, "7455", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | - CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7455 rev 2.0 */ - 0xffffffff, 0x80010200, "7455", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7455 others */ - 0xffff0000, 0x80010000, "7455", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7447/7457 Rev 1.0 */ - 0xffffffff, 0x80020100, "7447/7457", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7447/7457 Rev 1.1 */ - 0xffffffff, 0x80020101, "7447/7457", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7447/7457 Rev 1.2 and later */ - 0xffff0000, 0x80020000, "7447/7457", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 7447A */ - 0xffff0000, 0x80030000, "7447A", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP | - CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | - CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | - CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, - COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, - 32, 32, - __setup_cpu_745x - }, - { /* 82xx (8240, 8245, 8260 are all 603e cores) */ - 0x7fff0000, 0x00810000, "82xx", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB, - COMMON_PPC, - 32, 32, - __setup_cpu_603 - }, - { /* All G2_LE (603e core, plus some) have the same pvr */ - 0x7fff0000, 0x00820000, "G2_LE", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | - CPU_FTR_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, - COMMON_PPC, - 32, 32, - __setup_cpu_603 - }, - { /* default match, we assume split I/D cache & TB (non-601)... */ - 0x00000000, 0x00000000, "(generic PPC)", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC, - 32, 32, - __setup_cpu_generic - }, + { /* 601 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00010000, + .cpu_name = "601", + .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | + PPC_FEATURE_UNIFIED_CACHE, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_601 + }, + { /* 603 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00030000, + .cpu_name = "603", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603 + }, + { /* 603e */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00060000, + .cpu_name = "603e", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603 + }, + { /* 603ev */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00070000, + .cpu_name = "603ev", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603 + }, + { /* 604 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00040000, + .cpu_name = "604", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 2, + .cpu_setup = __setup_cpu_604 + }, + { /* 604e */ + .pvr_mask = 0xfffff000, + .pvr_value = 0x00090000, + .cpu_name = "604e", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_604 + }, + { /* 604r */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00090000, + .cpu_name = "604r", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_604 + }, + { /* 604ev */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x000a0000, + .cpu_name = "604ev", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_604 + }, + { /* 740/750 (0x4202, don't support TAU ?) */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x00084202, + .cpu_name = "740/750", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, + { /* 745/755 */ + .pvr_mask = 0xfffff000, + .pvr_value = 0x00083000, + .cpu_name = "745/755", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, + { /* 750CX (80100 and 8010x?) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00080100, + .cpu_name = "750CX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750cx + }, + { /* 750CX (82201 and 82202) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00082200, + .cpu_name = "750CX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750cx + }, + { /* 750CXe (82214) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00082210, + .cpu_name = "750CXe", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750cx + }, + { /* 750FX rev 1.x */ + .pvr_mask = 0xffffff00, + .pvr_value = 0x70000100, + .cpu_name = "750FX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, + { /* 750FX rev 2.0 must disable HID0[DPM] */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x70000200, + .cpu_name = "750FX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_NO_DPM, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, + { /* 750FX (All revs except 2.0) */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x70000000, + .cpu_name = "750FX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750fx + }, + { /* 750GX */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x70020000, + .cpu_name = "750GX", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_DUAL_PLL_750FX | + CPU_FTR_HAS_HIGH_BATS, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750fx + }, + { /* 740/750 (L2CR bit need fixup for 740) */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00080000, + .cpu_name = "740/750", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, + { /* 7400 rev 1.1 ? (no TAU) */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x000c1101, + .cpu_name = "7400 (1.1)", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_7400 + }, + { /* 7400 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x000c0000, + .cpu_name = "7400", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_7400 + }, + { /* 7410 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x800c0000, + .cpu_name = "7410", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_7410 + }, + { /* 7450 2.0 - no doze/nap */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80000200, + .cpu_name = "7450", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7450 2.1 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80000201, + .cpu_name = "7450", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7450 2.3 and newer */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80000000, + .cpu_name = "7450", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7455 rev 1.x */ + .pvr_mask = 0xffffff00, + .pvr_value = 0x80010100, + .cpu_name = "7455", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7455 rev 2.0 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80010200, + .cpu_name = "7455", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | + CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7455 others */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80010000, + .cpu_name = "7455", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7447/7457 Rev 1.0 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80020100, + .cpu_name = "7447/7457", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7447/7457 Rev 1.1 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80020101, + .cpu_name = "7447/7457", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7447/7457 Rev 1.2 and later */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80020000, + .cpu_name = "7447/7457", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | + CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | + CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | + CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 7447A */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80030000, + .cpu_name = "7447A", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 82xx (8240, 8245, 8260 are all 603e cores) */ + .pvr_mask = 0x7fff0000, + .pvr_value = 0x00810000, + .cpu_name = "82xx", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603 + }, + { /* All G2_LE (603e core, plus some) have the same pvr */ + .pvr_mask = 0x7fff0000, + .pvr_value = 0x00820000, + .cpu_name = "G2_LE", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603 + }, + { /* default match, we assume split I/D cache & TB (non-601)... */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic PPC)", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_generic + }, #endif /* CLASSIC_PPC */ #ifdef CONFIG_PPC64BRIDGE - { /* Power3 */ - 0xffff0000, 0x00400000, "Power3 (630)", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_64, - 128, 128, - __setup_cpu_power3 - }, - { /* Power3+ */ - 0xffff0000, 0x00410000, "Power3 (630+)", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_64, - 128, 128, - __setup_cpu_power3 - }, + { /* Power3 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00400000, + .cpu_name = "Power3 (630)", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_power3 + }, + { /* Power3+ */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00410000, + .cpu_name = "Power3 (630+)", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_power3 + }, { /* I-star */ - 0xffff0000, 0x00360000, "I-star", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_64, - 128, 128, - __setup_cpu_power3 + .pvr_mask = 0xffff0000, + .pvr_value = 0x00360000, + .cpu_name = "I-star", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_power3 }, { /* S-star */ - 0xffff0000, 0x00370000, "S-star", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_64, - 128, 128, - __setup_cpu_power3 + .pvr_mask = 0xffff0000, + .pvr_value = 0x00370000, + .cpu_name = "S-star", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_power3 }, #endif /* CONFIG_PPC64BRIDGE */ #ifdef CONFIG_POWER4 - { /* Power4 */ - 0xffff0000, 0x00350000, "Power4", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, - COMMON_PPC | PPC_FEATURE_64, - 128, 128, - __setup_cpu_power4 - }, - { /* PPC970 */ - 0xffff0000, 0x00390000, "PPC970", - CPU_FTR_COMMON | - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP, - COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP, - 128, 128, - __setup_cpu_ppc970 - }, + { /* Power4 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00350000, + .cpu_name = "Power4", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_power4 + }, + { /* PPC970 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00390000, + .cpu_name = "PPC970", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | + PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_ppc970 + }, + { /* PPC970FX */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x003c0000, + .cpu_name = "PPC970FX", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_HPTE_TABLE | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_64 | + PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_ppc970 + }, #endif /* CONFIG_POWER4 */ #ifdef CONFIG_8xx - { /* 8xx */ - 0xffff0000, 0x00500000, "8xx", - /* CPU_FTR_CAN_DOZE is possible, if the 8xx code is there.... */ - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 16, 16, - __setup_cpu_8xx /* Empty */ - }, + { /* 8xx */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00500000, + .cpu_name = "8xx", + /* CPU_FTR_MAYBE_CAN_DOZE is possible, + * if the 8xx code is there.... */ + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 16, + .dcache_bsize = 16, + }, #endif /* CONFIG_8xx */ #ifdef CONFIG_40x - { /* 403GC */ - 0xffffff00, 0x00200200, "403GC", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 16, 16, - 0, /*__setup_cpu_403 */ - }, - { /* 403GCX */ - 0xffffff00, 0x00201400, "403GCX", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 16, 16, - 0, /*__setup_cpu_403 */ - }, - { /* 403G ?? */ - 0xffff0000, 0x00200000, "403G ??", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 16, 16, - 0, /*__setup_cpu_403 */ - }, - { /* 405GP */ - 0xffff0000, 0x40110000, "405GP", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* STB 03xxx */ - 0xffff0000, 0x40130000, "STB03xxx", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* STB 04xxx */ - 0xffff0000, 0x41810000, "STB04xxx", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* NP405L */ - 0xffff0000, 0x41610000, "NP405L", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* NP4GS3 */ - 0xffff0000, 0x40B10000, "NP4GS3", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* NP405H */ - 0xffff0000, 0x41410000, "NP405H", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* 405GPr */ - 0xffff0000, 0x50910000, "405GPr", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* STBx25xx */ - 0xffff0000, 0x51510000, "STBx25xx", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* 405LP */ - 0xffff0000, 0x41F10000, "405LP", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_405 */ - }, - { /* Xilinx Virtex-II Pro */ - 0xffff0000, 0x20010000, "Virtex-II Pro", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, - 32, 32, - 0, /*__setup_cpu_405 */ - }, + { /* 403GC */ + .pvr_mask = 0xffffff00, + .pvr_value = 0x00200200, + .cpu_name = "403GC", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 16, + .dcache_bsize = 16, + }, + { /* 403GCX */ + .pvr_mask = 0xffffff00, + .pvr_value = 0x00201400, + .cpu_name = "403GCX", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 16, + .dcache_bsize = 16, + }, + { /* 403G ?? */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00200000, + .cpu_name = "403G ??", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 16, + .dcache_bsize = 16, + }, + { /* 405GP */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x40110000, + .cpu_name = "405GP", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* STB 03xxx */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x40130000, + .cpu_name = "STB03xxx", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* STB 04xxx */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x41810000, + .cpu_name = "STB04xxx", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* NP405L */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x41610000, + .cpu_name = "NP405L", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* NP4GS3 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x40B10000, + .cpu_name = "NP4GS3", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* NP405H */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x41410000, + .cpu_name = "NP405H", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 405GPr */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x50910000, + .cpu_name = "405GPr", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* STBx25xx */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x51510000, + .cpu_name = "STBx25xx", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 405LP */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x41F10000, + .cpu_name = "405LP", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* Xilinx Virtex-II Pro */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x20010000, + .cpu_name = "Virtex-II Pro", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .icache_bsize = 32, + .dcache_bsize = 32, + }, #endif /* CONFIG_40x */ #ifdef CONFIG_44x - { /* 440GP Rev. B */ - 0xf0000fff, 0x40000440, "440GP Rev. B", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_440 */ - }, - { /* 440GP Rev. C */ - 0xf0000fff, 0x40000481, "440GP Rev. C", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_440 */ - }, - { /* 440GX Rev. A */ - 0xf0000fff, 0x50000850, "440GX Rev. A", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_440 */ - }, - { /* 440GX Rev. B */ - 0xf0000fff, 0x50000851, "440GX Rev. B", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_440 */ - }, - { /* 440GX Rev. C */ - 0xf0000fff, 0x50000892, "440GX Rev. C", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_440 */ - }, + { /* 440GP Rev. B */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x40000440, + .cpu_name = "440GP Rev. B", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 440GP Rev. C */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x40000481, + .cpu_name = "440GP Rev. C", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 440GX Rev. A */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x50000850, + .cpu_name = "440GX Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 440GX Rev. B */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x50000851, + .cpu_name = "440GX Rev. B", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 440GX Rev. C */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x50000892, + .cpu_name = "440GX Rev. C", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, #endif /* CONFIG_44x */ #ifdef CONFIG_E500 - { /* e500 */ - 0xffff0000, 0x80200000, "e500", - /* xxx - galak: add CPU_FTR_CAN_DOZE */ - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, - 32, 32, - 0, /*__setup_cpu_e500 */ - }, + { /* e500 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80200000, + .cpu_name = "e500", + /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + }, #endif #if !CLASSIC_PPC - { /* default match */ - 0x00000000, 0x00000000, "(generic PPC)", - CPU_FTR_COMMON, - PPC_FEATURE_32, - 32, 32, - 0, - } + { /* default match */ + .pvr_mask = 0x00000000, + .pvr_value = 0x00000000, + .cpu_name = "(generic PPC)", + .cpu_features = CPU_FTR_COMMON, + .cpu_user_features = PPC_FEATURE_32, + .icache_bsize = 32, + .dcache_bsize = 32, + } #endif /* !CLASSIC_PPC */ }; diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index 54f9a3e75..334b8bfdc 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c @@ -41,11 +41,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -381,6 +381,7 @@ void __dma_sync(void *vaddr, size_t size, int direction) break; } } +EXPORT_SYMBOL(__dma_sync); #ifdef CONFIG_HIGHMEM /* @@ -438,3 +439,4 @@ void __dma_sync_page(struct page *page, unsigned long offset, __dma_sync((void *)start, size, direction); #endif } +EXPORT_SYMBOL(__dma_sync_page); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 4963b79c7..91318c15c 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -206,7 +206,7 @@ _GLOBAL(DoSyscall) andi. r11,r11,_TIF_SYSCALL_TRACE bne- syscall_dotrace syscall_dotrace_cont: - cmpli 0,r0,NR_syscalls + cmplwi 0,r0,NR_syscalls lis r10,sys_call_table@h ori r10,r10,sys_call_table@l slwi r0,r0,2 @@ -222,7 +222,7 @@ ret_from_syscall: #endif mr r6,r3 li r11,-_LAST_ERRNO - cmpl 0,r3,r11 + cmplw 0,r3,r11 rlwinm r12,r1,0,0,18 /* current_thread_info() */ blt+ 30f lwz r11,TI_LOCAL_FLAGS(r12) diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 121978c19..3a3e3c742 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -800,7 +800,7 @@ load_up_fpu: tophys(r6,0) /* get __pa constant */ addis r3,r6,last_task_used_math@ha lwz r4,last_task_used_math@l(r3) - cmpi 0,r4,0 + cmpwi 0,r4,0 beq 1f add r4,r4,r6 addi r4,r4,THREAD /* want last_task_used_math->thread */ @@ -927,7 +927,7 @@ load_up_altivec: tophys(r6,0) addis r3,r6,last_task_used_altivec@ha lwz r4,last_task_used_altivec@l(r3) - cmpi 0,r4,0 + cmpwi 0,r4,0 beq 1f add r4,r4,r6 addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */ @@ -992,11 +992,11 @@ giveup_altivec: SYNC MTMSRD(r5) /* enable use of AltiVec now */ isync - cmpi 0,r3,0 + cmpwi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ lwz r5,PT_REGS(r3) - cmpi 0,r5,0 + cmpwi 0,r5,0 SAVE_32VR(0, r4, r3) mfvscr vr0 li r4,THREAD_VSCR @@ -1030,11 +1030,11 @@ giveup_fpu: MTMSRD(r5) /* enable use of fpu now */ SYNC_601 isync - cmpi 0,r3,0 + cmpwi 0,r3,0 beqlr- /* if no previous owner, done */ addi r3,r3,THREAD /* want THREAD of task */ lwz r5,PT_REGS(r3) - cmpi 0,r5,0 + cmpwi 0,r5,0 SAVE_32FPRS(0, r3) mffs fr0 stfd fr0,THREAD_FPSCR-4(r3) @@ -1539,7 +1539,7 @@ initial_bats: #ifndef CONFIG_PPC64BRIDGE mfspr r9,PVR rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ - cmpi 0,r9,1 + cmpwi 0,r9,1 bne 4f ori r11,r11,4 /* set up BAT registers for 601 */ li r8,0x7f /* valid, block length = 8MB */ @@ -1591,7 +1591,7 @@ setup_disp_bat: lwz r8,4(r8) mfspr r9,PVR rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ - cmpi 0,r9,1 + cmpwi 0,r9,1 beq 1f mtspr DBAT3L,r8 mtspr DBAT3U,r11 diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index f883dc239..cf9347e31 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -41,16 +41,9 @@ #include #include #include +#include "head_booke.h" -/* - * Macros - */ -#define SET_IVOR(vector_number, vector_label) \ - li r26,vector_label@l; \ - mtspr SPRN_IVOR##vector_number,r26; \ - sync - /* As with the other PowerPC ports, it is expected that when code * execution begins here, the following registers contain valid, yet * optional, information: @@ -302,234 +295,6 @@ skpinv: addi r4,r4,1 /* Increment */ * We align on a 32 byte cache line boundary for good measure. */ -#define NORMAL_EXCEPTION_PROLOG \ - mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ - mtspr SPRN_SPRG1,r11; \ - mtspr SPRN_SPRG4W,r1; \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - beq 1f; \ - mfspr r1,SPRG3; /* if from user, start at top of */\ - lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ - addi r1,r1,THREAD_SIZE; \ -1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ - tophys(r11,r1); \ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mfspr r10,SPRG0; \ - stw r10,GPR10(r11); \ - mfspr r12,SPRG1; \ - stw r12,GPR11(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r10,SPRG4R; \ - mfspr r12,SRR0; \ - stw r10,GPR1(r11); \ - mfspr r9,SRR1; \ - stw r10,0(r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception prolog for critical exceptions. This is a little different - * from the normal exception prolog above since a critical exception - * can potentially occur at any point during normal exception processing. - * Thus we cannot use the same SPRG registers as the normal prolog above. - * Instead we use a couple of words of memory at low physical addresses. - * This is OK since we don't support SMP on these processors. For Book E - * processors, we also have a reserved register (SPRG2) that is only used - * in critical exceptions so we can free up a GPR to use as the base for - * indirect access to the critical exception save area. This is necessary - * since the MMU is always on and the save area is offset from KERNELBASE. - */ -#define CRITICAL_EXCEPTION_PROLOG \ - mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \ - lis r8,crit_save@ha; \ - stw r10,crit_r10@l(r8); \ - stw r11,crit_r11@l(r8); \ - mfspr r10,SPRG0; \ - stw r10,crit_sprg0@l(r8); \ - mfspr r10,SPRG1; \ - stw r10,crit_sprg1@l(r8); \ - mfspr r10,SPRG4R; \ - stw r10,crit_sprg4@l(r8); \ - mfspr r10,SPRG5R; \ - stw r10,crit_sprg5@l(r8); \ - mfspr r10,SPRG7R; \ - stw r10,crit_sprg7@l(r8); \ - mfspr r10,SPRN_PID; \ - stw r10,crit_pid@l(r8); \ - mfspr r10,SRR0; \ - stw r10,crit_srr0@l(r8); \ - mfspr r10,SRR1; \ - stw r10,crit_srr1@l(r8); \ - mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - lis r11,critical_stack_top@h; \ - ori r11,r11,critical_stack_top@l; \ - beq 1f; \ - /* COMING FROM USER MODE */ \ - mfspr r11,SPRG3; /* if from user, start at top of */\ - lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ - addi r11,r11,THREAD_SIZE; \ -1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ - stw r12,_DEAR(r11); /* since they may have had stuff */\ - mfspr r9,SPRN_ESR; /* in them at the point where the */\ - stw r9,_ESR(r11); /* exception was taken */\ - mfspr r12,CSRR0; \ - stw r1,GPR1(r11); \ - mfspr r9,CSRR1; \ - stw r1,0(r11); \ - tovirt(r1,r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception prolog for machine check exceptions. This is similar to - * the critical exception prolog, except that machine check exceptions - * have their own save area. For Book E processors, we also have a - * reserved register (SPRG6) that is only used in machine check exceptions - * so we can free up a GPR to use as the base for indirect access to the - * machine check exception save area. This is necessary since the MMU - * is always on and the save area is offset from KERNELBASE. - */ -#define MCHECK_EXCEPTION_PROLOG \ - mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \ - lis r8,mcheck_save@ha; \ - stw r10,mcheck_r10@l(r8); \ - stw r11,mcheck_r11@l(r8); \ - mfspr r10,SPRG0; \ - stw r10,mcheck_sprg0@l(r8); \ - mfspr r10,SPRG1; \ - stw r10,mcheck_sprg1@l(r8); \ - mfspr r10,SPRG4R; \ - stw r10,mcheck_sprg4@l(r8); \ - mfspr r10,SPRG5R; \ - stw r10,mcheck_sprg5@l(r8); \ - mfspr r10,SPRG7R; \ - stw r10,mcheck_sprg7@l(r8); \ - mfspr r10,SPRN_PID; \ - stw r10,mcheck_pid@l(r8); \ - mfspr r10,SRR0; \ - stw r10,mcheck_srr0@l(r8); \ - mfspr r10,SRR1; \ - stw r10,mcheck_srr1@l(r8); \ - mfspr r10,CSRR0; \ - stw r10,mcheck_csrr0@l(r8); \ - mfspr r10,CSRR1; \ - stw r10,mcheck_csrr1@l(r8); \ - mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - lis r11,mcheck_stack_top@h; \ - ori r11,r11,mcheck_stack_top@l; \ - beq 1f; \ - /* COMING FROM USER MODE */ \ - mfspr r11,SPRG3; /* if from user, start at top of */\ - lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ - addi r11,r11,THREAD_SIZE; \ -1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ - stw r12,_DEAR(r11); /* since they may have had stuff */\ - mfspr r9,SPRN_ESR; /* in them at the point where the */\ - stw r9,_ESR(r11); /* exception was taken */\ - mfspr r12,MCSRR0; \ - stw r1,GPR1(r11); \ - mfspr r9,MCSRR1; \ - stw r1,0(r11); \ - tovirt(r1,r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception vectors. - */ -#define START_EXCEPTION(label) \ - .align 5; \ -label: - -#define FINISH_EXCEPTION(func) \ - bl transfer_to_handler_full; \ - .long func; \ - .long ret_from_except_full - -#define EXCEPTION(n, label, hdlr, xfer) \ - START_EXCEPTION(label); \ - NORMAL_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - xfer(n, hdlr) - -#define CRITICAL_EXCEPTION(n, label, hdlr) \ - START_EXCEPTION(label); \ - CRITICAL_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, transfer_to_handler_full, \ - ret_from_except_full) - -#define MCHECK_EXCEPTION(n, label, hdlr) \ - START_EXCEPTION(label); \ - MCHECK_EXCEPTION_PROLOG; \ - lis r4,MCSR_MCS@h; \ - mtspr SPRN_MCSR,r4; \ - mfspr r5,SPRN_ESR; \ - stw r5,_ESR(r11); \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, mcheck_transfer_to_handler, \ - ret_from_mcheck_exc) - -#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ - li r10,trap; \ - stw r10,TRAP(r11); \ - lis r10,msr@h; \ - ori r10,r10,msr@l; \ - copyee(r10, r9); \ - bl tfer; \ - .long hdlr; \ - .long ret - -#define COPY_EE(d, s) rlwimi d,s,0,16,16 -#define NOCOPY(d, s) - -#define EXC_XFER_STD(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ - ret_from_except_full) - -#define EXC_XFER_LITE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ - ret_from_except) - -#define EXC_XFER_EE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ - ret_from_except_full) - -#define EXC_XFER_EE_LITE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ - ret_from_except) - interrupt_base: /* Critical Input Interrupt */ CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException) @@ -834,64 +599,8 @@ interrupt_base: mfspr r10, SPRG0 b InstructionStorage -/* Check for a single step debug exception while in an exception - * handler before state has been saved. This is to catch the case - * where an instruction that we are trying to single step causes - * an exception (eg ITLB/DTLB miss) and thus the first instruction of - * the exception handler generates a single step debug exception. - * - * If we get a debug trap on the first instruction of an exception handler, - * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is - * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). - * The exception handler was handling a non-critical interrupt, so it will - * save (and later restore) the MSR via SPRN_SRR1, which will still have - * the MSR_DE bit set. - */ /* Debug Interrupt */ - START_EXCEPTION(Debug) - CRITICAL_EXCEPTION_PROLOG - - /* - * If this is a single step or branch-taken exception in an - * exception entry sequence, it was probably meant to apply to - * the code where the exception occurred (since exception entry - * doesn't turn off DE automatically). We simulate the effect - * of turning off DE on entry to an exception handler by turning - * off DE in the CSRR1 value and clearing the debug status. - */ - mfspr r10,SPRN_DBSR /* check single-step/branch taken */ - andis. r10,r10,(DBSR_IC|DBSR_BT)@h - beq+ 1f - andi. r0,r9,MSR_PR /* check supervisor */ - beq 2f /* branch if we need to fix it up... */ - - /* continue normal handling for a critical exception... */ -1: mfspr r4,SPRN_DBSR - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(DebugException, 0x2002, \ - (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) - - /* here it looks like we got an inappropriate debug exception. */ -2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */ - mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */ - /* restore state and get out */ - lwz r10,_CCR(r11) - lwz r0,GPR0(r11) - lwz r1,GPR1(r11) - mtcrf 0x80,r10 - mtspr CSRR0,r12 - mtspr CSRR1,r9 - lwz r9,GPR9(r11) - - mtspr SPRG2,r8; /* SPRG2 only used in criticals */ - lis r8,crit_save@ha; - lwz r10,crit_r10@l(r8) - lwz r11,crit_r11@l(r8) - mfspr r8,SPRG2 - - rfci - b . + DEBUG_EXCEPTION /* * Local functions diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S index 5a8933688..f2b0f9f1b 100644 --- a/arch/ppc/kernel/head_4xx.S +++ b/arch/ppc/kernel/head_4xx.S @@ -709,8 +709,20 @@ label: EXCEPTION(0x1E00, Trap_1E, UnknownException, EXC_XFER_EE) EXCEPTION(0x1F00, Trap_1F, UnknownException, EXC_XFER_EE) -/* 0x2000 - Debug Exception -*/ +/* Check for a single step debug exception while in an exception + * handler before state has been saved. This is to catch the case + * where an instruction that we are trying to single step causes + * an exception (eg ITLB/DTLB miss) and thus the first instruction of + * the exception handler generates a single step debug exception. + * + * If we get a debug trap on the first instruction of an exception handler, + * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is + * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). + * The exception handler was handling a non-critical interrupt, so it will + * save (and later restore) the MSR via SPRN_SRR1, which will still have + * the MSR_DE bit set. + */ + /* 0x2000 - Debug Exception */ START_EXCEPTION(0x2000, DebugTrap) CRITICAL_EXCEPTION_PROLOG @@ -723,21 +735,20 @@ label: * off DE in the SRR3 value and clearing the debug status. */ mfspr r10,SPRN_DBSR /* check single-step/branch taken */ - andis. r10,r10,(DBSR_IC|DBSR_BT)@h - beq+ 1f - andi. r0,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */ - beq 2f /* branch if we need to fix it up... */ + andis. r10,r10,DBSR_IC@h + beq+ 2f - /* continue normal handling for a critical exception... */ -1: mfspr r4,SPRN_DBSR - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(DebugException, 0x2002, \ - (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) + andi. r10,r9,MSR_IR|MSR_PR /* check supervisor + MMU off */ + beq 1f /* branch and fix it up */ + + mfspr r10,SPRN_SRR2 /* Faulting instruction address */ + cmplwi r10,0x2100 + bgt+ 2f /* address above exception vectors */ /* here it looks like we got an inappropriate debug exception. */ -2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */ - mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */ +1: rlwinm r9,r9,0,~MSR_DE /* clear DE in the SRR3 value */ + lis r10,DBSR_IC@h /* clear the IC event */ + mtspr SPRN_DBSR,r10 /* restore state and get out */ lwz r10,_CCR(r11) lwz r0,GPR0(r11) @@ -753,6 +764,13 @@ label: rfci b . + /* continue normal handling for a critical exception... */ +2: mfspr r4,SPRN_DBSR + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_TEMPLATE(DebugException, 0x2002, \ + (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ + NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) + /* * The other Data TLB exceptions bail out to this point * if they can't resolve the lightweight TLB fault. diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index cfcd6e122..8b57c3eed 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -32,14 +32,18 @@ #include #include +/* Macro to make the code more readable. */ +#ifdef CONFIG_8xx_CPU6 +#define DO_8xx_CPU6(val, reg) \ + li reg, val; \ + stw reg, 12(r0); \ + lwz reg, 12(r0); +#else +#define DO_8xx_CPU6(val, reg) +#endif .text .globl _stext _stext: - -/* - * _start is defined this way because the XCOFF loader in the OpenFirmware - * on the powermac expects the entry point to be a procedure descriptor. - */ .text .globl _start _start: @@ -77,7 +81,6 @@ _start: * and the CCR at memory location 0.....Someday I'll fix this..... * -- Dan */ - .globl __start __start: mr r31,r3 /* save parameters */ @@ -85,7 +88,6 @@ __start: mr r29,r5 mr r28,r6 mr r27,r7 - li r24,0 /* cpu # */ /* We have to turn on the MMU right away so we get cache modes * set correctly. @@ -113,63 +115,106 @@ turn_on_mmu: * task's thread_struct. */ #define EXCEPTION_PROLOG \ - mtspr SPRG0,r20; \ - mtspr SPRG1,r21; \ - mfcr r20; \ - mfspr r21,SPRG2; /* exception stack to use from */ \ - cmpwi 0,r21,0; /* user mode or RTAS */ \ - bne 1f; \ - tophys(r21,r1); /* use tophys(kernel sp) otherwise */ \ - subi r21,r21,INT_FRAME_SIZE; /* alloc exc. frame */\ -1: stw r20,_CCR(r21); /* save registers */ \ - stw r22,GPR22(r21); \ - stw r23,GPR23(r21); \ - mfspr r20,SPRG0; \ - stw r20,GPR20(r21); \ - mfspr r22,SPRG1; \ - stw r22,GPR21(r21); \ - mflr r20; \ - stw r20,_LINK(r21); \ - mfctr r22; \ - stw r22,_CTR(r21); \ - mfspr r20,XER; \ - stw r20,_XER(r21); \ - mfspr r22,SRR0; \ - mfspr r23,SRR1; \ - stw r0,GPR0(r21); \ - stw r1,GPR1(r21); \ - stw r2,GPR2(r21); \ - stw r1,0(r21); \ - tovirt(r1,r21); /* set new kernel sp */ \ - SAVE_4GPRS(3, r21); \ - SAVE_GPR(7, r21); + mtspr SPRG0,r10; \ + mtspr SPRG1,r11; \ + mfcr r10; \ + EXCEPTION_PROLOG_1; \ + EXCEPTION_PROLOG_2 + +#define EXCEPTION_PROLOG_1 \ + mfspr r11,SRR1; /* check whether user or kernel */ \ + andi. r11,r11,MSR_PR; \ + tophys(r11,r1); /* use tophys(r1) if kernel */ \ + beq 1f; \ + mfspr r11,SPRG3; \ + lwz r11,THREAD_INFO-THREAD(r11); \ + addi r11,r11,THREAD_SIZE; \ + tophys(r11,r11); \ +1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */ + + +#define EXCEPTION_PROLOG_2 \ + CLR_TOP32(r11); \ + stw r10,_CCR(r11); /* save registers */ \ + stw r12,GPR12(r11); \ + stw r9,GPR9(r11); \ + mfspr r10,SPRG0; \ + stw r10,GPR10(r11); \ + mfspr r12,SPRG1; \ + stw r12,GPR11(r11); \ + mflr r10; \ + stw r10,_LINK(r11); \ + mfspr r12,SRR0; \ + mfspr r9,SRR1; \ + stw r1,GPR1(r11); \ + stw r1,0(r11); \ + tovirt(r1,r11); /* set new kernel sp */ \ + li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \ + MTMSRD(r10); /* (except for mach check in rtas) */ \ + stw r0,GPR0(r11); \ + SAVE_4GPRS(3, r11); \ + SAVE_2GPRS(7, r11) + /* * Note: code which follows this uses cr0.eq (set if from kernel), - * r21, r22 (SRR0), and r23 (SRR1). + * r11, r12 (SRR0), and r9 (SRR1). + * + * Note2: once we have set r1 we are in a position to take exceptions + * again, and we could thus set MSR:RI at that point. */ /* * Exception vectors. */ -#define STD_EXCEPTION(n, label, hdlr) \ +#define EXCEPTION(n, label, hdlr, xfer) \ . = n; \ label: \ EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r20,MSR_KERNEL; \ - bl transfer_to_handler; \ - .long hdlr; \ - .long ret_from_except + xfer(n, hdlr) + +#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret) \ + li r10,trap; \ + stw r10,TRAP(r11); \ + li r10,MSR_KERNEL; \ + copyee(r10, r9); \ + bl tfer; \ +i##n: \ + .long hdlr; \ + .long ret + +#define COPY_EE(d, s) rlwimi d,s,0,16,16 +#define NOCOPY(d, s) + +#define EXC_XFER_STD(n, hdlr) \ + EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \ + ret_from_except) + +#define EXC_XFER_EE(n, hdlr) \ + EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \ + ret_from_except_full) + +#define EXC_XFER_EE_LITE(n, hdlr) \ + EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \ + ret_from_except) /* System reset */ -#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */ - STD_EXCEPTION(0x100, Reset, __secondary_start_psurge) -#else - STD_EXCEPTION(0x100, Reset, UnknownException) -#endif + EXCEPTION(0x100, Reset, UnknownException, EXC_XFER_STD) /* Machine check */ - STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) + . = 0x200 +MachineCheck: + EXCEPTION_PROLOG + mfspr r4,DAR + stw r4,_DAR(r11) + mfspr r5,DSISR + stw r5,_DSISR(r11) + addi r3,r1,STACK_FRAME_OVERHEAD + EXC_XFER_STD(0x200, MachineCheckException) /* Data access exception. * This is "never generated" by the MPC8xx. We jump to it for other @@ -178,17 +223,11 @@ label: \ . = 0x300 DataAccess: EXCEPTION_PROLOG - mfspr r20,DSISR - stw r20,_DSISR(r21) - mr r5,r20 + mfspr r10,DSISR + stw r10,_DSISR(r11) + mr r5,r10 mfspr r4,DAR - stw r4,_DAR(r21) - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - bl transfer_to_handler - .long do_page_fault - .long ret_from_except + EXC_XFER_EE_LITE(0x300, handle_page_fault) /* Instruction access exception. * This is "never generated" by the MPC8xx. We jump to it for other @@ -197,94 +236,52 @@ DataAccess: . = 0x400 InstructionAccess: EXCEPTION_PROLOG - addi r3,r1,STACK_FRAME_OVERHEAD - mr r4,r22 - mr r5,r23 - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - bl transfer_to_handler - .long do_page_fault - .long ret_from_except + mr r4,r12 + mr r5,r9 + EXC_XFER_EE_LITE(0x400, handle_page_fault) /* External interrupt */ - . = 0x500; -HardwareInterrupt: - EXCEPTION_PROLOG; - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - li r4,0 - bl transfer_to_handler - .globl do_IRQ_intercept -do_IRQ_intercept: - .long do_IRQ; - .long ret_from_intercept - + EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) /* Alignment exception */ . = 0x600 Alignment: EXCEPTION_PROLOG mfspr r4,DAR - stw r4,_DAR(r21) + stw r4,_DAR(r11) mfspr r5,DSISR - stw r5,_DSISR(r21) + stw r5,_DSISR(r11) addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - bl transfer_to_handler - .long AlignmentException - .long ret_from_except + EXC_XFER_EE(0x600, AlignmentException) /* Program check exception */ - . = 0x700 -ProgramCheck: - EXCEPTION_PROLOG - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - bl transfer_to_handler - .long ProgramCheckException - .long ret_from_except + EXCEPTION(0x700, ProgramCheck, ProgramCheckException, EXC_XFER_STD) /* No FPU on MPC8xx. This exception is not supposed to happen. */ - STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + EXCEPTION(0x800, FPUnavailable, UnknownException, EXC_XFER_STD) - . = 0x900 -Decrementer: - EXCEPTION_PROLOG - addi r3,r1,STACK_FRAME_OVERHEAD - li r20,MSR_KERNEL - bl transfer_to_handler - .globl timer_interrupt_intercept -timer_interrupt_intercept: - .long timer_interrupt - .long ret_from_intercept +/* Decrementer */ + EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE) - STD_EXCEPTION(0xa00, Trap_0a, UnknownException) - STD_EXCEPTION(0xb00, Trap_0b, UnknownException) + EXCEPTION(0xa00, Trap_0a, UnknownException, EXC_XFER_EE) + EXCEPTION(0xb00, Trap_0b, UnknownException, EXC_XFER_EE) /* System call */ . = 0xc00 SystemCall: EXCEPTION_PROLOG - stw r3,ORIG_GPR3(r21) - li r20,MSR_KERNEL - rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ - bl transfer_to_handler - .long DoSyscall - .long ret_from_except + EXC_XFER_EE_LITE(0xc00, DoSyscall) /* Single step - not used on 601 */ - STD_EXCEPTION(0xd00, SingleStep, SingleStepException) - - STD_EXCEPTION(0xe00, Trap_0e, UnknownException) - STD_EXCEPTION(0xf00, Trap_0f, UnknownException) + EXCEPTION(0xd00, SingleStep, SingleStepException, EXC_XFER_STD) + EXCEPTION(0xe00, Trap_0e, UnknownException, EXC_XFER_EE) + EXCEPTION(0xf00, Trap_0f, UnknownException, EXC_XFER_EE) /* On the MPC8xx, this is a software emulation interrupt. It occurs * for all unimplemented and illegal instructions. */ - STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation) + EXCEPTION(0x1000, SoftEmu, SoftwareEmulation, EXC_XFER_STD) . = 0x1100 /* @@ -302,58 +299,43 @@ SystemCall: InstructionTLBMiss: #ifdef CONFIG_8xx_CPU6 stw r3, 8(r0) - li r3, 0x3f80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr M_TW, r20 /* Save a couple of working registers */ - mfcr r20 - stw r20, 0(r0) - stw r21, 4(r0) - mfspr r20, SRR0 /* Get effective address of fault */ -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3780 - stw r3, 12(r0) - lwz r3, 12(r0) #endif - mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */ - mfspr r20, M_TWB /* Get level 1 table entry address */ + DO_8xx_CPU6(0x3f80, r3) + mtspr M_TW, r10 /* Save a couple of working registers */ + mfcr r10 + stw r10, 0(r0) + stw r11, 4(r0) + mfspr r10, SRR0 /* Get effective address of fault */ + DO_8xx_CPU6(0x3780, r3) + mtspr MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */ + mfspr r10, M_TWB /* Get level 1 table entry address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andi. r21, r20, 0x0800 /* Address >= 0x80000000 */ + andi. r11, r10, 0x0800 /* Address >= 0x80000000 */ beq 3f - lis r21, swapper_pg_dir@h - ori r21, r21, swapper_pg_dir@l - rlwimi r20, r21, 0, 2, 19 + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + rlwimi r10, r11, 0, 2, 19 3: - lwz r21, 0(r20) /* Get the level 1 entry */ - rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */ + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ beq 2f /* If zero, don't try to find a pte */ /* We have a pte table, so load the MI_TWC with the attributes * for this "segment." */ - tophys(r21,r21) - ori r21,r21,1 /* Set valid bit */ -#ifdef CONFIG_8xx_CPU6 - li r3, 0x2b80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MI_TWC, r21 /* Set segment attributes */ -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3b80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_TWC, r21 /* Load pte table base address */ - mfspr r21, MD_TWC /* ....and get the pte address */ - lwz r20, 0(r21) /* Get the pte */ + ori r11,r11,1 /* Set valid bit */ + DO_8xx_CPU6(0x2b80, r3) + mtspr MI_TWC, r11 /* Set segment attributes */ + DO_8xx_CPU6(0x3b80, r3) + mtspr MD_TWC, r11 /* Load pte table base address */ + mfspr r11, MD_TWC /* ....and get the pte address */ + lwz r10, 0(r11) /* Get the pte */ - ori r20, r20, _PAGE_ACCESSED - stw r20, 0(r21) + ori r10, r10, _PAGE_ACCESSED + stw r10, 0(r11) /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21, 22 and 28 must be clear. @@ -361,29 +343,24 @@ InstructionTLBMiss: * set. All other Linux PTE bits control the behavior * of the MMU. */ - li r21, 0x00f0 - rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */ - -#ifdef CONFIG_8xx_CPU6 - li r3, 0x2d80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MI_RPN, r20 /* Update TLB entry */ - - mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) + li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + DO_8xx_CPU6(0x2d80, r3) + mtspr MI_RPN, r10 /* Update TLB entry */ + + mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif rfi -2: mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) +2: mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif @@ -393,41 +370,34 @@ InstructionTLBMiss: DataStoreTLBMiss: #ifdef CONFIG_8xx_CPU6 stw r3, 8(r0) - li r3, 0x3f80 - stw r3, 12(r0) - lwz r3, 12(r0) #endif - mtspr M_TW, r20 /* Save a couple of working registers */ - mfcr r20 - stw r20, 0(r0) - stw r21, 4(r0) - mfspr r20, M_TWB /* Get level 1 table entry address */ + DO_8xx_CPU6(0x3f80, r3) + mtspr M_TW, r10 /* Save a couple of working registers */ + mfcr r10 + stw r10, 0(r0) + stw r11, 4(r0) + mfspr r10, M_TWB /* Get level 1 table entry address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andi. r21, r20, 0x0800 + andi. r11, r10, 0x0800 beq 3f - lis r21, swapper_pg_dir@h - ori r21, r21, swapper_pg_dir@l - rlwimi r20, r21, 0, 2, 19 + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + rlwimi r10, r11, 0, 2, 19 3: - lwz r21, 0(r20) /* Get the level 1 entry */ - rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */ + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ beq 2f /* If zero, don't try to find a pte */ /* We have a pte table, so load fetch the pte from the table. */ - tophys(r21, r21) - ori r21, r21, 1 /* Set valid bit in physical L2 page */ -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3b80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_TWC, r21 /* Load pte table base address */ - mfspr r20, MD_TWC /* ....and get the pte address */ - lwz r20, 0(r20) /* Get the pte */ + ori r11, r11, 1 /* Set valid bit in physical L2 page */ + DO_8xx_CPU6(0x3b80, r3) + mtspr MD_TWC, r11 /* Load pte table base address */ + mfspr r10, MD_TWC /* ....and get the pte address */ + lwz r10, 0(r10) /* Get the pte */ /* Insert the Guarded flag into the TWC from the Linux PTE. * It is bit 27 of both the Linux PTE and the TWC (at least @@ -435,17 +405,13 @@ DataStoreTLBMiss: * this into the Linux pgd/pmd and load it in the operation * above. */ - rlwimi r21, r20, 0, 27, 27 -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3b80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_TWC, r21 + rlwimi r11, r10, 0, 27, 27 + DO_8xx_CPU6(0x3b80, r3) + mtspr MD_TWC, r11 - mfspr r21, MD_TWC /* get the pte address again */ - ori r20, r20, _PAGE_ACCESSED - stw r20, 0(r21) + mfspr r11, MD_TWC /* get the pte address again */ + ori r10, r10, _PAGE_ACCESSED + stw r10, 0(r11) /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21, 22 and 28 must be clear. @@ -453,29 +419,24 @@ DataStoreTLBMiss: * set. All other Linux PTE bits control the behavior * of the MMU. */ - li r21, 0x00f0 - rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */ - -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3d80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_RPN, r20 /* Update TLB entry */ - - mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) + li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + DO_8xx_CPU6(0x3d80, r3) + mtspr MD_RPN, r10 /* Update TLB entry */ + + mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif rfi -2: mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) +2: mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif @@ -501,19 +462,17 @@ InstructionTLBError: DataTLBError: #ifdef CONFIG_8xx_CPU6 stw r3, 8(r0) - li r3, 0x3f80 - stw r3, 12(r0) - lwz r3, 12(r0) #endif - mtspr M_TW, r20 /* Save a couple of working registers */ - mfcr r20 - stw r20, 0(r0) - stw r21, 4(r0) + DO_8xx_CPU6(0x3f80, r3) + mtspr M_TW, r10 /* Save a couple of working registers */ + mfcr r10 + stw r10, 0(r0) + stw r11, 4(r0) /* First, make sure this was a store operation. */ - mfspr r20, DSISR - andis. r21, r20, 0x0200 /* If set, indicates store op */ + mfspr r10, DSISR + andis. r11, r10, 0x0200 /* If set, indicates store op */ beq 2f /* The EA of a data TLB miss is automatically stored in the MD_EPN @@ -532,54 +491,45 @@ DataTLBError: * are initialized in mapin_ram(). This will avoid the problem, * assuming we only use the dcbi instruction on kernel addresses. */ - mfspr r20, DAR - rlwinm r21, r20, 0, 0, 19 - ori r21, r21, MD_EVALID - mfspr r20, M_CASID - rlwimi r21, r20, 0, 28, 31 -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3780 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_EPN, r21 + mfspr r10, DAR + rlwinm r11, r10, 0, 0, 19 + ori r11, r11, MD_EVALID + mfspr r10, M_CASID + rlwimi r11, r10, 0, 28, 31 + DO_8xx_CPU6(0x3780, r3) + mtspr MD_EPN, r11 - mfspr r20, M_TWB /* Get level 1 table entry address */ + mfspr r10, M_TWB /* Get level 1 table entry address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ - andi. r21, r20, 0x0800 + andi. r11, r10, 0x0800 beq 3f - lis r21, swapper_pg_dir@h - ori r21, r21, swapper_pg_dir@l - rlwimi r20, r21, 0, 2, 19 + lis r11, swapper_pg_dir@h + ori r11, r11, swapper_pg_dir@l + rlwimi r10, r11, 0, 2, 19 3: - lwz r21, 0(r20) /* Get the level 1 entry */ - rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */ + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ beq 2f /* If zero, bail */ /* We have a pte table, so fetch the pte from the table. */ - tophys(r21, r21) - ori r21, r21, 1 /* Set valid bit in physical L2 page */ -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3b80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_TWC, r21 /* Load pte table base address */ - mfspr r21, MD_TWC /* ....and get the pte address */ - lwz r20, 0(r21) /* Get the pte */ + ori r11, r11, 1 /* Set valid bit in physical L2 page */ + DO_8xx_CPU6(0x3b80, r3) + mtspr MD_TWC, r11 /* Load pte table base address */ + mfspr r11, MD_TWC /* ....and get the pte address */ + lwz r10, 0(r11) /* Get the pte */ - andi. r21, r20, _PAGE_RW /* Is it writeable? */ + andi. r11, r10, _PAGE_RW /* Is it writeable? */ beq 2f /* Bail out if not */ /* Update 'changed', among others. */ - ori r20, r20, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE - mfspr r21, MD_TWC /* Get pte address again */ - stw r20, 0(r21) /* and update pte in table */ + ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE + mfspr r11, MD_TWC /* Get pte address again */ + stw r10, 0(r11) /* and update pte in table */ /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 21, 22 and 28 must be clear. @@ -587,50 +537,45 @@ DataTLBError: * set. All other Linux PTE bits control the behavior * of the MMU. */ - li r21, 0x00f0 - rlwimi r20, r21, 0, 24, 28 /* Set 24-27, clear 28 */ - -#ifdef CONFIG_8xx_CPU6 - li r3, 0x3d80 - stw r3, 12(r0) - lwz r3, 12(r0) -#endif - mtspr MD_RPN, r20 /* Update TLB entry */ - - mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) + li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + DO_8xx_CPU6(0x3d80, r3) + mtspr MD_RPN, r10 /* Update TLB entry */ + + mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif rfi 2: - mfspr r20, M_TW /* Restore registers */ - lwz r21, 0(r0) - mtcr r21 - lwz r21, 4(r0) + mfspr r10, M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif b DataAccess - STD_EXCEPTION(0x1500, Trap_15, UnknownException) - STD_EXCEPTION(0x1600, Trap_16, UnknownException) - STD_EXCEPTION(0x1700, Trap_17, TAUException) - STD_EXCEPTION(0x1800, Trap_18, UnknownException) - STD_EXCEPTION(0x1900, Trap_19, UnknownException) - STD_EXCEPTION(0x1a00, Trap_1a, UnknownException) - STD_EXCEPTION(0x1b00, Trap_1b, UnknownException) + EXCEPTION(0x1500, Trap_15, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1600, Trap_16, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1700, Trap_17, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1800, Trap_18, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1900, Trap_19, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1a00, Trap_1a, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1b00, Trap_1b, UnknownException, EXC_XFER_EE) /* On the MPC8xx, these next four traps are used for development * support of breakpoints and such. Someday I will get around to * using them. */ - STD_EXCEPTION(0x1c00, Trap_1c, UnknownException) - STD_EXCEPTION(0x1d00, Trap_1d, UnknownException) - STD_EXCEPTION(0x1e00, Trap_1e, UnknownException) - STD_EXCEPTION(0x1f00, Trap_1f, UnknownException) + EXCEPTION(0x1c00, Trap_1c, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1d00, Trap_1d, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1e00, Trap_1e, UnknownException, EXC_XFER_EE) + EXCEPTION(0x1f00, Trap_1f, UnknownException, EXC_XFER_EE) . = 0x2000 @@ -638,11 +583,6 @@ DataTLBError: giveup_fpu: blr -/* Maybe someday....... -*/ -_GLOBAL(__setup_cpu_8xx) - blr - /* * This is where the main kernel code starts. */ diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index 6f54039c8..0c655c116 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h @@ -237,4 +237,70 @@ label: ret_from_except) +/* Check for a single step debug exception while in an exception + * handler before state has been saved. This is to catch the case + * where an instruction that we are trying to single step causes + * an exception (eg ITLB/DTLB miss) and thus the first instruction of + * the exception handler generates a single step debug exception. + * + * If we get a debug trap on the first instruction of an exception handler, + * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is + * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). + * The exception handler was handling a non-critical interrupt, so it will + * save (and later restore) the MSR via SPRN_CSRR1, which will still have + * the MSR_DE bit set. + */ +#define DEBUG_EXCEPTION \ + START_EXCEPTION(Debug); \ + CRITICAL_EXCEPTION_PROLOG; \ + \ + /* \ + * If there is a single step or branch-taken exception in an \ + * exception entry sequence, it was probably meant to apply to \ + * the code where the exception occurred (since exception entry \ + * doesn't turn off DE automatically). We simulate the effect \ + * of turning off DE on entry to an exception handler by turning \ + * off DE in the CSRR1 value and clearing the debug status. \ + */ \ + mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ + andis. r10,r10,DBSR_IC@h; \ + beq+ 2f; \ + \ + lis r10,KERNELBASE@h; /* check if exception in vectors */ \ + ori r10,r10,KERNELBASE@l; \ + cmplw r12,r10; \ + blt+ 2f; /* addr below exception vectors */ \ + \ + lis r10,Debug@h; \ + ori r10,r10,Debug@l; \ + cmplw r12,r10; \ + bgt+ 2f; /* addr above exception vectors */ \ + \ + /* here it looks like we got an inappropriate debug exception. */ \ +1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \ + lis r10,DBSR_IC@h; /* clear the IC event */ \ + mtspr SPRN_DBSR,r10; \ + /* restore state and get out */ \ + lwz r10,_CCR(r11); \ + lwz r0,GPR0(r11); \ + lwz r1,GPR1(r11); \ + mtcrf 0x80,r10; \ + mtspr CSRR0,r12; \ + mtspr CSRR1,r9; \ + lwz r9,GPR9(r11); \ + lwz r12,GPR12(r11); \ + mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \ + lis r8,crit_save@ha; \ + lwz r10,crit_r10@l(r8); \ + lwz r11,crit_r11@l(r8); \ + mfspr r8,SPRG2; \ + \ + rfci; \ + b .; \ + \ + /* continue normal handling for a critical exception... */ \ +2: mfspr r4,SPRN_DBSR; \ + addi r3,r1,STACK_FRAME_OVERHEAD; \ + EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) + #endif /* __HEAD_BOOKE_H__ */ diff --git a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S index ceb51d343..c671a9359 100644 --- a/arch/ppc/kernel/head_e500.S +++ b/arch/ppc/kernel/head_e500.S @@ -41,15 +41,7 @@ #include #include #include - -/* - * Macros - */ - -#define SET_IVOR(vector_number, vector_label) \ - li r26,vector_label@l; \ - mtspr SPRN_IVOR##vector_number,r26; \ - sync +#include "head_booke.h" /* As with the other PowerPC ports, it is expected that when code * execution begins here, the following registers contain valid, yet @@ -371,232 +363,6 @@ skpinv: addi r6,r6,1 /* Increment */ * We align on a 32 byte cache line boundary for good measure. */ -#define NORMAL_EXCEPTION_PROLOG \ - mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ - mtspr SPRN_SPRG1,r11; \ - mtspr SPRN_SPRG4W,r1; \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - beq 1f; \ - mfspr r1,SPRG3; /* if from user, start at top of */\ - lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ - addi r1,r1,THREAD_SIZE; \ -1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ - tophys(r11,r1); \ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mfspr r10,SPRG0; \ - stw r10,GPR10(r11); \ - mfspr r12,SPRG1; \ - stw r12,GPR11(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r10,SPRG4R; \ - mfspr r12,SRR0; \ - stw r10,GPR1(r11); \ - mfspr r9,SRR1; \ - stw r10,0(r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception prolog for critical exceptions. This is a little different - * from the normal exception prolog above since a critical exception - * can potentially occur at any point during normal exception processing. - * Thus we cannot use the same SPRG registers as the normal prolog above. - * Instead we use a couple of words of memory at low physical addresses. - * This is OK since we don't support SMP on these processors. For Book E - * processors, we also have a reserved register (SPRG2) that is only used - * in critical exceptions so we can free up a GPR to use as the base for - * indirect access to the critical exception save area. This is necessary - * since the MMU is always on and the save area is offset from KERNELBASE. - */ -#define CRITICAL_EXCEPTION_PROLOG \ - mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \ - lis r8,crit_save@ha; \ - stw r10,crit_r10@l(r8); \ - stw r11,crit_r11@l(r8); \ - mfspr r10,SPRG0; \ - stw r10,crit_sprg0@l(r8); \ - mfspr r10,SPRG1; \ - stw r10,crit_sprg1@l(r8); \ - mfspr r10,SPRG4R; \ - stw r10,crit_sprg4@l(r8); \ - mfspr r10,SPRG5R; \ - stw r10,crit_sprg5@l(r8); \ - mfspr r10,SPRG7R; \ - stw r10,crit_sprg7@l(r8); \ - mfspr r10,SPRN_PID; \ - stw r10,crit_pid@l(r8); \ - mfspr r10,SRR0; \ - stw r10,crit_srr0@l(r8); \ - mfspr r10,SRR1; \ - stw r10,crit_srr1@l(r8); \ - mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - lis r11,critical_stack_top@h; \ - ori r11,r11,critical_stack_top@l; \ - beq 1f; \ - /* COMING FROM USER MODE */ \ - mfspr r11,SPRG3; /* if from user, start at top of */\ - lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ - addi r11,r11,THREAD_SIZE; \ -1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ - stw r12,_DEAR(r11); /* since they may have had stuff */\ - mfspr r9,SPRN_ESR; /* in them at the point where the */\ - stw r9,_ESR(r11); /* exception was taken */\ - mfspr r12,CSRR0; \ - stw r1,GPR1(r11); \ - mfspr r9,CSRR1; \ - stw r1,0(r11); \ - tovirt(r1,r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception prolog for machine check exceptions. This is similar to - * the critical exception prolog, except that machine check exceptions - * have their own save area. For Book E processors, we also have a - * reserved register (SPRG6) that is only used in machine check exceptions - * so we can free up a GPR to use as the base for indirect access to the - * machine check exception save area. This is necessary since the MMU - * is always on and the save area is offset from KERNELBASE. - */ -#define MCHECK_EXCEPTION_PROLOG \ - mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \ - lis r8,mcheck_save@ha; \ - stw r10,mcheck_r10@l(r8); \ - stw r11,mcheck_r11@l(r8); \ - mfspr r10,SPRG0; \ - stw r10,mcheck_sprg0@l(r8); \ - mfspr r10,SPRG1; \ - stw r10,mcheck_sprg1@l(r8); \ - mfspr r10,SPRG4R; \ - stw r10,mcheck_sprg4@l(r8); \ - mfspr r10,SPRG5R; \ - stw r10,mcheck_sprg5@l(r8); \ - mfspr r10,SPRG7R; \ - stw r10,mcheck_sprg7@l(r8); \ - mfspr r10,SPRN_PID; \ - stw r10,mcheck_pid@l(r8); \ - mfspr r10,SRR0; \ - stw r10,mcheck_srr0@l(r8); \ - mfspr r10,SRR1; \ - stw r10,mcheck_srr1@l(r8); \ - mfspr r10,CSRR0; \ - stw r10,mcheck_csrr0@l(r8); \ - mfspr r10,CSRR1; \ - stw r10,mcheck_csrr1@l(r8); \ - mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \ - mfcr r10; /* save CR in r10 for now */\ - mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\ - andi. r11,r11,MSR_PR; \ - lis r11,mcheck_stack_top@h; \ - ori r11,r11,mcheck_stack_top@l; \ - beq 1f; \ - /* COMING FROM USER MODE */ \ - mfspr r11,SPRG3; /* if from user, start at top of */\ - lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ - addi r11,r11,THREAD_SIZE; \ -1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ - stw r10,_CCR(r11); /* save various registers */\ - stw r12,GPR12(r11); \ - stw r9,GPR9(r11); \ - mflr r10; \ - stw r10,_LINK(r11); \ - mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ - stw r12,_DEAR(r11); /* since they may have had stuff */\ - mfspr r9,SPRN_ESR; /* in them at the point where the */\ - stw r9,_ESR(r11); /* exception was taken */\ - mfspr r12,MCSRR0; \ - stw r1,GPR1(r11); \ - mfspr r9,MCSRR1; \ - stw r1,0(r11); \ - tovirt(r1,r11); \ - rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ - stw r0,GPR0(r11); \ - SAVE_4GPRS(3, r11); \ - SAVE_2GPRS(7, r11) - -/* - * Exception vectors. - */ -#define START_EXCEPTION(label) \ - .align 5; \ -label: - -#define FINISH_EXCEPTION(func) \ - bl transfer_to_handler_full; \ - .long func; \ - .long ret_from_except_full - -#define EXCEPTION(n, label, hdlr, xfer) \ - START_EXCEPTION(label); \ - NORMAL_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - xfer(n, hdlr) - -#define CRITICAL_EXCEPTION(n, label, hdlr) \ - START_EXCEPTION(label); \ - CRITICAL_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, transfer_to_handler_full, \ - ret_from_except_full) - -#define MCHECK_EXCEPTION(n, label, hdlr) \ - START_EXCEPTION(label); \ - MCHECK_EXCEPTION_PROLOG; \ - mfspr r5,SPRN_ESR; \ - stw r5,_ESR(r11); \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, mcheck_transfer_to_handler, \ - ret_from_mcheck_exc) - -#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ - li r10,trap; \ - stw r10,TRAP(r11); \ - lis r10,msr@h; \ - ori r10,r10,msr@l; \ - copyee(r10, r9); \ - bl tfer; \ - .long hdlr; \ - .long ret - -#define COPY_EE(d, s) rlwimi d,s,0,16,16 -#define NOCOPY(d, s) - -#define EXC_XFER_STD(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ - ret_from_except_full) - -#define EXC_XFER_LITE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ - ret_from_except) - -#define EXC_XFER_EE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ - ret_from_except_full) - -#define EXC_XFER_EE_LITE(n, hdlr) \ - EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ - ret_from_except) - interrupt_base: /* Critical Input Interrupt */ CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException) @@ -902,64 +668,8 @@ interrupt_base: /* Performance Monitor */ EXCEPTION(0x2060, PerformanceMonitor, UnknownException, EXC_XFER_EE) -/* Check for a single step debug exception while in an exception - * handler before state has been saved. This is to catch the case - * where an instruction that we are trying to single step causes - * an exception (eg ITLB/DTLB miss) and thus the first instruction of - * the exception handler generates a single step debug exception. - * - * If we get a debug trap on the first instruction of an exception handler, - * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is - * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). - * The exception handler was handling a non-critical interrupt, so it will - * save (and later restore) the MSR via SPRN_SRR1, which will still have - * the MSR_DE bit set. - */ /* Debug Interrupt */ - START_EXCEPTION(Debug) - CRITICAL_EXCEPTION_PROLOG - - /* - * If this is a single step or branch-taken exception in an - * exception entry sequence, it was probably meant to apply to - * the code where the exception occurred (since exception entry - * doesn't turn off DE automatically). We simulate the effect - * of turning off DE on entry to an exception handler by turning - * off DE in the CSRR1 value and clearing the debug status. - */ - mfspr r10,SPRN_DBSR /* check single-step/branch taken */ - andis. r10,r10,(DBSR_IC|DBSR_BT)@h - beq+ 1f - andi. r0,r9,MSR_PR /* check supervisor */ - beq 2f /* branch if we need to fix it up... */ - - /* continue normal handling for a critical exception... */ -1: mfspr r4,SPRN_DBSR - addi r3,r1,STACK_FRAME_OVERHEAD - EXC_XFER_TEMPLATE(DebugException, 0x2002, \ - (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ - NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) - - /* here it looks like we got an inappropriate debug exception. */ -2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */ - mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */ - /* restore state and get out */ - lwz r10,_CCR(r11) - lwz r0,GPR0(r11) - lwz r1,GPR1(r11) - mtcrf 0x80,r10 - mtspr CSRR0,r12 - mtspr CSRR1,r9 - lwz r9,GPR9(r11) - - mtspr SPRG2,r8; /* SPRG2 only used in criticals */ - lis r8,crit_save@ha; - lwz r10,crit_r10@l(r8) - lwz r11,crit_r11@l(r8) - mfspr r8,SPRG2 - - rfci - b . + DEBUG_EXCEPTION /* * Local functions diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 5adb6be19..6db80f60c 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -65,3 +66,36 @@ int cpu_idle(void) default_idle(); return 0; } + +#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx) +/* + * Register the sysctl to set/clear powersave_nap. + */ +extern unsigned long powersave_nap; + +static ctl_table powersave_nap_ctl_table[]={ + { + .ctl_name = KERN_PPC_POWERSAVE_NAP, + .procname = "powersave-nap", + .data = &powersave_nap, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { 0, }, +}; +static ctl_table powersave_nap_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, + { 0,}, +}; + +static int __init +register_powersave_nap_sysctl(void) +{ + register_sysctl_table(powersave_nap_sysctl_root, 0); + + return 0; +} + +__initcall(register_powersave_nap_sysctl); +#endif diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S index 608f71ccb..25d009c75 100644 --- a/arch/ppc/kernel/idle_6xx.S +++ b/arch/ppc/kernel/idle_6xx.S @@ -79,12 +79,12 @@ BEGIN_FTR_SECTION /* Now check if user or arch enabled NAP mode */ lis r4,powersave_nap@ha lwz r4,powersave_nap@l(r4) - cmpi 0,r4,0 + cmpwi 0,r4,0 beq 1f lis r3,HID0_NAP@h 1: END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) - cmpi 0,r3,0 + cmpwi 0,r3,0 beqlr /* Clear MSR:EE */ @@ -133,7 +133,7 @@ BEGIN_FTR_SECTION /* Go to low speed mode on some 750FX */ lis r4,powersave_lowspeed@ha lwz r4,powersave_lowspeed@l(r4) - cmpi 0,r4,0 + cmpwi 0,r4,0 beq 1f mfspr r4,SPRN_HID1 oris r4,r4,0x0001 diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S index 538a044f4..73a58ff03 100644 --- a/arch/ppc/kernel/idle_power4.S +++ b/arch/ppc/kernel/idle_power4.S @@ -56,7 +56,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) /* Now check if user or arch enabled NAP mode */ lis r4,powersave_nap@ha lwz r4,powersave_nap@l(r4) - cmpi 0,r4,0 + cmpwi 0,r4,0 beqlr /* Clear MSR:EE */ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 2ac2e4b55..8843f3af2 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -46,9 +46,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -61,296 +62,20 @@ extern atomic_t ipi_recv; extern atomic_t ipi_sent; -void enable_irq(unsigned int irq_nr); -void disable_irq(unsigned int irq_nr); - -static void register_irq_proc (unsigned int irq); #define MAXCOUNT 10000000 -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .lock = SPIN_LOCK_UNLOCKED - } -}; - int ppc_spurious_interrupts = 0; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; atomic_t ppc_n_lost_interrupts; -/* nasty hack for shared irq's since we need to do kmalloc calls but - * can't very early in the boot when we need to do a request irq. - * this needs to be removed. - * -- Cort - */ -#define IRQ_KMALLOC_ENTRIES 8 -static int cache_bitmask = 0; -static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES]; -extern int mem_init_done; - -#if defined(CONFIG_TAU_INT) -extern int tau_interrupts(unsigned long cpu); +#ifdef CONFIG_TAU_INT extern int tau_initialized; +extern int tau_interrupts(int); #endif -void *irq_kmalloc(size_t size, int pri) -{ - unsigned int i; - if ( mem_init_done ) - return kmalloc(size,pri); - for ( i = 0; i < IRQ_KMALLOC_ENTRIES ; i++ ) - if ( ! ( cache_bitmask & (1<flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); - if (desc->handler) { - if (desc->handler->startup) - desc->handler->startup(irq); - else if (desc->handler->enable) - desc->handler->enable(irq); - } - } - spin_unlock_irqrestore(&desc->lock,flags); - - register_irq_proc(irq); - return 0; -} - -void free_irq(unsigned int irq, void* dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - synchronize_irq(irq); - irq_kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - break; - } - return; -} - -EXPORT_SYMBOL(free_irq); - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - struct irqaction *action; - int retval; - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) { - printk(KERN_ERR "request_irq called with NULL handler!\n"); - dump_stack(); - return 0; - } - - action = (struct irqaction *) - irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) { - printk(KERN_ERR "irq_kmalloc() failed for irq %d !\n", irq); - return -ENOMEM; - } - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->dev_id = dev_id; - action->next = NULL; - - retval = setup_irq(irq, action); - if (retval) { - kfree(action); - return retval; - } - - return 0; -} - -EXPORT_SYMBOL(request_irq); - -/* - * 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 of an interrupt - * stack. 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. - */ - -void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - if (!(desc->status & IRQ_PER_CPU)) - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables of an interrupt - * stack. That is for two disables you need two enables. 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. - */ - -void disable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line - * providing no disable_irq calls are now in effect. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - unmask_irq(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk("enable_irq(%u) unbalanced\n", irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -410,113 +135,6 @@ skip: return 0; } -static inline void -handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) -{ - int status = 0; - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); -} - -/* - * Eventually, this should take an array of interrupts and an array size - * so it can dispatch multiple interrupts. - */ -void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) -{ - int status; - struct irqaction *action; - irq_desc_t *desc = irq_desc + irq; - - kstat_this_cpu.irqs[irq]++; - spin_lock(&desc->lock); - ack_irq(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - if (!(status & IRQ_PER_CPU)) - status |= IRQ_PENDING; /* we _want_ to handle it */ - - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { - action = desc->action; - if (!action || !action->handler) { - ppc_spurious_interrupts++; - printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); - /* We can't call disable_irq here, it would deadlock */ - ++desc->depth; - desc->status |= IRQ_DISABLED; - mask_irq(irq); - /* This is a real interrupt, we have to eoi it, - so we jump to out */ - goto out; - } - status &= ~IRQ_PENDING; /* we commit to handling */ - if (!(status & IRQ_PER_CPU)) - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; - - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (unlikely(!action)) - goto out; - - - /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. - */ - for (;;) { - spin_unlock(&desc->lock); - handle_irq_event(irq, regs, action); - spin_lock(&desc->lock); - - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } -out: - desc->status &= ~IRQ_INPROGRESS; - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - if (irq_desc[irq].handler) { - if (irq_desc[irq].handler->end) - irq_desc[irq].handler->end(irq); - else if (irq_desc[irq].handler->enable) - irq_desc[irq].handler->enable(irq); - } - spin_unlock(&desc->lock); -} - void do_IRQ(struct pt_regs *regs) { int irq, first = 1; @@ -531,7 +149,7 @@ void do_IRQ(struct pt_regs *regs) * has already been handled. -- Tom */ while ((irq = ppc_md.get_irq(regs)) >= 0) { - ppc_irq_dispatch_handler(regs, irq); + __do_IRQ(irq, regs); first = 0; } if (irq != -2 && first) @@ -540,178 +158,7 @@ void do_IRQ(struct pt_regs *regs) irq_exit(); } -unsigned long probe_irq_on (void) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_off); - -unsigned int probe_irq_mask(unsigned long irqs) -{ - return 0; -} - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) -{ - while (irq_desc[irq].status & IRQ_INPROGRESS) - barrier(); -} -#endif /* CONFIG_SMP */ - -static struct proc_dir_entry *root_irq_dir; -static struct proc_dir_entry *irq_dir[NR_IRQS]; -static struct proc_dir_entry *smp_affinity_entry[NR_IRQS]; - -#ifdef CONFIG_IRQ_ALL_CPUS -#define DEFAULT_CPU_AFFINITY CPU_MASK_ALL -#else -#define DEFAULT_CPU_AFFINITY cpumask_of_cpu(0) -#endif - -cpumask_t irq_affinity [NR_IRQS]; - -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int irq_affinity_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (int) data, full_count = count, err; - cpumask_t new_value, tmp; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(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. - * - * We assume a 1-1 logical<->physical cpu mapping here. If - * we assume that the cpu indices in /proc/irq/../smp_affinity - * are actually logical cpu #'s then we have no problem. - * -- Cort - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; - - irq_affinity[irq] = new_value; - irq_desc[irq].handler->set_affinity(irq, new_value); - - return full_count; -} - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int err; - int full_count = count; - cpumask_t *mask = (cpumask_t *)data; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - struct proc_dir_entry *entry; - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - - entry->nlink = 1; - entry->data = (void *)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - - smp_affinity_entry[irq] = entry; -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].handler == NULL) - continue; - register_irq_proc(i); - } -} - -irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs) -{ - return IRQ_NONE; -} - void __init init_IRQ(void) { - int i; - - for (i = 0; i < NR_IRQS; ++i) - irq_affinity[i] = DEFAULT_CPU_AFFINITY; - ppc_md.init_IRQ(); } diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 873199e43..2e3a07675 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -214,7 +214,7 @@ _GLOBAL(low_choose_750fx_pll) mtmsr r0 /* If switching to PLL1, disable HID0:BTIC */ - cmpli cr0,r3,0 + cmplwi cr0,r3,0 beq 1f mfspr r5,HID0 rlwinm r5,r5,0,27,25 @@ -239,7 +239,7 @@ _GLOBAL(low_choose_750fx_pll) stw r4,nap_save_hid1@l(r6) /* If switching to PLL0, enable HID0:BTIC */ - cmpli cr0,r3,0 + cmplwi cr0,r3,0 bne 1f mfspr r5,HID0 ori r5,r5,HID0_BTIC @@ -470,7 +470,7 @@ _GLOBAL(_tlbia) ori r9,r9,mmu_hash_lock@l tophys(r9,r9) 10: lwarx r7,0,r9 - cmpi 0,r7,0 + cmpwi 0,r7,0 bne- 10b stwcx. r8,0,r9 bne- 10b @@ -551,7 +551,7 @@ _GLOBAL(_tlbie) ori r9,r9,mmu_hash_lock@l tophys(r9,r9) 10: lwarx r7,0,r9 - cmpi 0,r7,0 + cmpwi 0,r7,0 bne- 10b stwcx. r8,0,r9 bne- 10b @@ -599,7 +599,7 @@ _GLOBAL(flush_instruction_cache) #else mfspr r3,PVR rlwinm r3,r3,16,16,31 - cmpi 0,r3,1 + cmpwi 0,r3,1 beqlr /* for 601, do nothing */ /* 603/604 processor - use invalidate-all bit in HID0 */ mfspr r3,HID0 @@ -617,10 +617,9 @@ _GLOBAL(flush_instruction_cache) * flush_icache_range(unsigned long start, unsigned long stop) */ _GLOBAL(flush_icache_range) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) li r5,L1_CACHE_LINE_SIZE-1 andc r3,r3,r5 subf r4,r3,r4 @@ -735,10 +734,9 @@ _GLOBAL(flush_dcache_all) * void __flush_dcache_icache(void *page) */ _GLOBAL(__flush_dcache_icache) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) rlwinm r3,r3,0,0,19 /* Get page base address */ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ mtctr r4 @@ -764,10 +762,9 @@ _GLOBAL(__flush_dcache_icache) * void __flush_dcache_icache_phys(unsigned long physaddr) */ _GLOBAL(__flush_dcache_icache_phys) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) mfmsr r10 rlwinm r0,r10,0,28,26 /* clear DR */ mtmsr r0 @@ -1144,7 +1141,7 @@ _GLOBAL(kernel_thread) li r4,0 /* new sp (unused) */ li r0,__NR_clone sc - cmpi 0,r3,0 /* parent or child? */ + cmpwi 0,r3,0 /* parent or child? */ bne 1f /* return if parent */ li r0,0 /* make top-level stack frame */ stwu r0,-16(r1) @@ -1450,3 +1447,6 @@ _GLOBAL(sys_call_table) .long sys_mq_notify .long sys_mq_getsetattr .long sys_ni_syscall /* 268 reserved for sys_kexec_load */ + .long sys_add_key + .long sys_request_key /* 270 */ + .long sys_keyctl diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 4145ff7bf..0f1eee33c 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -33,6 +33,7 @@ unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; unsigned long pci_dram_offset = 0; +int pcibios_assign_bus_offset = 1; void pcibios_make_OF_bus_map(void); @@ -45,11 +46,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev); static int reparent_resources(struct resource *parent, struct resource *res); static void fixup_rev1_53c810(struct pci_dev* dev); static void fixup_cpc710_pci64(struct pci_dev* dev); -#ifdef CONFIG_PPC_PMAC -extern void pmac_pci_fixup_cardbus(struct pci_dev* dev); -extern void pmac_pci_fixup_pciata(struct pci_dev* dev); -extern void pmac_pci_fixup_k2_sata(struct pci_dev* dev); -#endif #ifdef CONFIG_PPC_OF static u8* pci_to_OF_bus_map; #endif @@ -64,20 +60,6 @@ struct pci_controller** hose_tail = &hose_head; static int pci_bus_count; -struct pci_fixup pcibios_fixups[] = { - { 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_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64}, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources }, -#ifdef CONFIG_PPC_PMAC - /* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */ - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus }, - { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata }, -#endif /* CONFIG_PPC_PMAC */ - { 0 } -}; - static void fixup_rev1_53c810(struct pci_dev* dev) { @@ -90,6 +72,7 @@ fixup_rev1_53c810(struct pci_dev* dev) dev->class = PCI_CLASS_STORAGE_SCSI; } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); static void fixup_broken_pcnet32(struct pci_dev* dev) @@ -100,6 +83,7 @@ fixup_broken_pcnet32(struct pci_dev* dev) pci_name_device(dev); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); static void fixup_cpc710_pci64(struct pci_dev* dev) @@ -112,6 +96,7 @@ fixup_cpc710_pci64(struct pci_dev* dev) dev->resource[1].start = dev->resource[1].end = 0; dev->resource[1].flags = 0; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); static void pcibios_fixup_resources(struct pci_dev *dev) @@ -158,9 +143,9 @@ pcibios_fixup_resources(struct pci_dev *dev) if (ppc_md.pcibios_fixup_resources) ppc_md.pcibios_fixup_resources(dev); } +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); -void -pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res) { unsigned long offset = 0; @@ -173,6 +158,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->start = res->start - offset; region->end = res->end - offset; } +EXPORT_SYMBOL(pcibios_resource_to_bus); /* * We need to avoid collisions with `mirrored' VGA ports @@ -187,8 +173,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, * but we want to try to avoid allocating at 0x2900-0x2bff * which might have be mirrored at 0x0100-0x03ff.. */ -void -pcibios_align_resource(void *data, struct resource *res, unsigned long size, +void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) { struct pci_dev *dev = data; @@ -208,7 +193,7 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size, } } } - +EXPORT_SYMBOL(pcibios_align_resource); /* * Handle resources of PCI devices. If the world were perfect, we could @@ -246,14 +231,12 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size, static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) { - struct list_head *ln; struct pci_bus *bus; int i; struct resource *res, *pr; /* Depth-First Search on bus tree */ - for (ln = bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); + list_for_each_entry(bus, bus_list, node) { for (i = 0; i < 4; ++i) { if ((res = bus->resource[i]) == NULL || !res->flags || res->start > res->end) @@ -396,7 +379,6 @@ probe_resource(struct pci_bus *parent, struct resource *pr, struct pci_bus *bus; struct pci_dev *dev; struct resource *r; - struct list_head *ln; int i; for (r = pr->child; r != NULL; r = r->sibling) { @@ -405,9 +387,7 @@ probe_resource(struct pci_bus *parent, struct resource *pr, return 1; } } - for (ln = parent->children.next; ln != &parent->children; - ln = ln->next) { - bus = pci_bus_b(ln); + list_for_each_entry(bus, &parent->children, node) { for (i = 0; i < 4; ++i) { if ((r = bus->resource[i]) == NULL) continue; @@ -421,13 +401,12 @@ probe_resource(struct pci_bus *parent, struct resource *pr, } } } - for (ln = parent->devices.next; ln != &parent->devices; ln=ln->next) { - dev = pci_dev_b(ln); + list_for_each_entry(dev, &parent->devices, bus_list) { for (i = 0; i < 6; ++i) { r = &dev->resource[i]; if (!r->flags || (r->flags & IORESOURCE_UNSET)) continue; - if (pci_find_parent_resource(bus->self, r) != pr) + if (pci_find_parent_resource(dev, r) != pr) continue; if (r->end >= res->start && res->end >= r->start) { *conflict = r; @@ -1117,7 +1096,7 @@ do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) static int __init check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) { - struct list_head *ln; + struct pci_dev *dev; int i; int rc = 0; @@ -1125,8 +1104,7 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ } while (0) - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - struct pci_dev *dev = pci_dev_b(ln); + list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; if (class == PCI_CLASS_DISPLAY_VGA || @@ -1167,7 +1145,7 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) static void __init do_fixup_p2p_level(struct pci_bus *bus) { - struct list_head *ln; + struct pci_bus *b; int i, parent_io; int has_vga = 0; @@ -1178,8 +1156,7 @@ do_fixup_p2p_level(struct pci_bus *bus) if (parent_io >= 4) return; - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) { - struct pci_bus *b = pci_bus_b(ln); + list_for_each_entry(b, &bus->children, node) { struct pci_dev *d = b->self; struct pci_controller* hose = (struct pci_controller *)d->sysdata; struct resource *res = b->resource[0]; @@ -1252,12 +1229,10 @@ do_fixup_p2p_level(struct pci_bus *bus) static void pcibios_fixup_p2p_bridges(void) { - struct list_head *ln; + struct pci_bus *b; - for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) { - struct pci_bus *b = pci_bus_b(ln); + list_for_each_entry(b, &pci_root_buses, node) do_fixup_p2p_level(b); - } } #endif /* CONFIG_PPC_PMAC */ @@ -1279,7 +1254,7 @@ pcibios_init(void) bus = pci_scan_bus(hose->first_busno, hose->ops, hose); hose->last_busno = bus->subordinate; if (pci_assign_all_busses || next_busno <= hose->last_busno) - next_busno = hose->last_busno+1; + next_busno = hose->last_busno + pcibios_assign_bus_offset; } pci_bus_count = next_busno; @@ -1616,7 +1591,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); - ret = remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); return ret; @@ -1724,6 +1699,32 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end, res->child = NULL; } +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len) + return NULL; + if (max && len > max) + len = max; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) + return (void __iomem *) start; + /* What? */ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem *addr) +{ + /* Nothing to do */ +} +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); + + /* * Null PCI config access functions, for the case when we can't * find a hose. diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c index a86975032..d61889c24 100644 --- a/arch/ppc/kernel/ppc-stub.c +++ b/arch/ppc/kernel/ppc-stub.c @@ -498,7 +498,7 @@ static struct hard_trap_info unsigned int tt; /* Trap type code for powerpc */ unsigned char signo; /* Signal that we map this trap into */ } hard_trap_info[] = { -#if defined(CONFIG_40x) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) { 0x100, SIGINT }, /* critical input interrupt */ { 0x200, SIGSEGV }, /* machine check */ { 0x300, SIGSEGV }, /* data storage */ @@ -521,7 +521,7 @@ static struct hard_trap_info ** 0x1100 data TLB miss ** 0x1200 instruction TLB miss */ - { 0x2000, SIGTRAP}, /* debug */ + { 0x2002, SIGTRAP}, /* debug */ #else { 0x200, SIGSEGV }, /* machine check */ { 0x300, SIGSEGV }, /* address error (store) */ @@ -602,11 +602,6 @@ handle_exception (struct pt_regs *regs) sigval = computeSignal(regs->trap); ptr = remcomOutBuffer; -#if defined(CONFIG_40x) - *ptr++ = 'S'; - *ptr++ = hexchars[sigval >> 4]; - *ptr++ = hexchars[sigval & 0xf]; -#else *ptr++ = 'T'; *ptr++ = hexchars[sigval >> 4]; *ptr++ = hexchars[sigval & 0xf]; @@ -620,8 +615,6 @@ handle_exception (struct pt_regs *regs) *ptr++ = ':'; ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4); *ptr++ = ';'; -#endif - *ptr++ = 0; putpacket(remcomOutBuffer); @@ -774,10 +767,6 @@ handle_exception (struct pt_regs *regs) * some location may have changed something that is in the instruction cache. */ kgdb_flush_cache_all(); -#if defined(CONFIG_40x) - strcpy(remcomOutBuffer, "OK"); - putpacket(remcomOutBuffer); -#endif mtmsr(msr); kgdb_interruptible(1); @@ -791,10 +780,9 @@ handle_exception (struct pt_regs *regs) case 's': kgdb_flush_cache_all(); -#if defined(CONFIG_40x) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC); regs->msr |= MSR_DE; - regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC); - mtmsr(msr); #else regs->msr |= MSR_SE; #endif diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 91592c03e..b5cd7e411 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -20,9 +20,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -34,9 +35,6 @@ static int ppc_htab_show(struct seq_file *m, void *v); static ssize_t ppc_htab_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos); -int proc_dol2crvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, loff_t *ppos); - extern PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; extern unsigned long _SDR1; @@ -438,3 +436,32 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp, *ppos += *lenp; return 0; } + +#ifdef CONFIG_SYSCTL +/* + * Register our sysctl. + */ +static ctl_table htab_ctl_table[]={ + { + .ctl_name = KERN_PPC_L2CR, + .procname = "l2cr", + .mode = 0644, + .proc_handler = &proc_dol2crvec, + }, + { 0, }, +}; +static ctl_table htab_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, htab_ctl_table, }, + { 0,}, +}; + +static int __init +register_ppc_htab_sysctl(void) +{ + register_sysctl_table(htab_sysctl_root, 0); + + return 0; +} + +__initcall(register_ppc_htab_sysctl); +#endif diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 2d3e630a7..3f5bad466 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -84,10 +84,6 @@ EXPORT_SYMBOL(SingleStepException); EXPORT_SYMBOL(sys_sigreturn); EXPORT_SYMBOL(ppc_n_lost_interrupts); EXPORT_SYMBOL(ppc_lost_interrupts); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); @@ -205,7 +201,6 @@ EXPORT_SYMBOL(giveup_spe); #ifdef CONFIG_SMP EXPORT_SYMBOL(smp_call_function); EXPORT_SYMBOL(smp_hw_index); -EXPORT_SYMBOL(synchronize_irq); #endif EXPORT_SYMBOL(ppc_md); @@ -292,8 +287,6 @@ EXPORT_SYMBOL(local_irq_restore_end); #endif EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); -void ppc_irq_dispatch_handler(struct pt_regs *, int); -EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(tb_ticks_per_jiffy); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); @@ -328,9 +321,6 @@ EXPORT_SYMBOL(cpm_free_handler); #if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) EXPORT_SYMBOL(__res); #endif -#if defined(CONFIG_8xx) -EXPORT_SYMBOL(request_8xxirq); -#endif EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); @@ -352,3 +342,7 @@ EXPORT_SYMBOL(cur_cpu_spec); extern unsigned long agp_special_page; EXPORT_SYMBOL(agp_special_page); #endif +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) +EXPORT_SYMBOL(__mtdcr); +EXPORT_SYMBOL(__mfdcr); +#endif diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 2ea505381..4db17100e 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,6 @@ #include #include #include -#include extern unsigned long _get_SP(void); @@ -321,7 +321,7 @@ void show_regs(struct pt_regs * regs) trap = TRAP(regs); if (trap == 0x300 || trap == 0x600) printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p", + printk("TASK = %p[%d] '%s' THREAD: %p\n", current, current->pid, current->comm, current->thread_info); printk("Last syscall: %ld ", current->thread.last_syscall); @@ -370,6 +370,10 @@ void exit_thread(void) last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif } void flush_thread(void) @@ -378,6 +382,10 @@ void flush_thread(void) last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif } void @@ -422,8 +430,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; unsigned long childframe; - p->set_child_tid = p->clear_child_tid = NULL; - CHECK_FULL_REGS(regs); /* Copy registers */ sp -= sizeof(struct pt_regs); @@ -482,6 +488,10 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) last_task_used_math = NULL; if (last_task_used_altivec == current) last_task_used_altivec = NULL; +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr = 0; #ifdef CONFIG_ALTIVEC @@ -555,8 +565,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, CHECK_FULL_REGS(regs); if (usp == 0) usp = regs->gpr[1]; /* stack pointer for child */ - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tidp, child_tidp); + return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); } int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, @@ -599,8 +608,11 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, preempt_enable(); error = do_execve(filename, (char __user *__user *) a1, (char __user *__user *) a2, regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: return error; @@ -662,7 +674,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) ++count; sp = *(unsigned long *)sp; } -#if !CONFIG_KALLSYMS +#ifndef CONFIG_KALLSYMS if (count > 0) printk("\n"); #endif diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 5cf5624e9..426b6f7d9 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -35,7 +35,7 @@ /* * Set of msr bits that gdb can change on behalf of a process. */ -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) #define MSR_DEBUGCHANGE 0 #else #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) @@ -201,9 +201,9 @@ set_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) { -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; - /* MSR.DE should already be set */ + regs->msr |= MSR_DE; #else regs->msr |= MSR_SE; #endif @@ -216,8 +216,9 @@ clear_single_step(struct task_struct *task) struct pt_regs *regs = task->thread.regs; if (regs != NULL) { -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) task->thread.dbcr0 = 0; + regs->msr &= ~MSR_DE; #else regs->msr &= ~MSR_SE; #endif @@ -377,7 +378,7 @@ int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 376f7369c..aecbef549 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -226,6 +226,10 @@ int show_cpuinfo(struct seq_file *m, void *v) maj = ((pvr >> 8) & 0xFF) - 1; min = pvr & 0xFF; break; + case 0x8020: /* e500 */ + maj = PVR_MAJ(pvr); + min = PVR_MIN(pvr); + break; default: maj = (pvr >> 8) & 0xFF; min = pvr & 0xFF; @@ -418,7 +422,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, * are used for initrd_start and initrd_size, * otherwise they contain 0xdeadbeef. */ - cmd_line[0] = 0; if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) { strlcpy(cmd_line, (char *)r3 + KERNELBASE, sizeof(cmd_line)); @@ -484,6 +487,9 @@ static int __init set_preferred_console(void) char *name; int offset; + if (of_stdout_device == NULL) + return -ENODEV; + /* The user has requested a console so this is already set up. */ if (strstr(saved_command_line, "console=")) return -EBUSY; @@ -744,6 +750,10 @@ void __init setup_arch(char **cmdline_p) if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab); #endif +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index 20b6446c0..b2bc832d7 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -270,7 +270,7 @@ save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, int sigret) static int restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig) { - unsigned long save_r2; + unsigned long save_r2 = 0; #if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) unsigned long msr; #endif @@ -290,7 +290,7 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig) /* force the process to reload the FP registers from current->thread when it next does FP instructions */ - regs->msr &= ~MSR_FP; + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, sizeof(sr->mc_fregs))) return 1; @@ -319,7 +319,7 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig) if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { /* restore spe registers from the stack */ if (__copy_from_user(current->thread.evr, &sr->mc_vregs, - sizeof(sr->mc_vregs))) + ELF_NEVRREG * sizeof(u32))) return 1; } else if (current->thread.used_spe) memset(¤t->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); @@ -329,6 +329,16 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig) return 1; #endif /* CONFIG_SPE */ +#ifndef CONFIG_SMP + preempt_disable(); + if (last_task_used_math == current) + last_task_used_math = NULL; + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; + if (last_task_used_spe == current) + last_task_used_spe = NULL; + preempt_enable(); +#endif return 0; } @@ -404,9 +414,7 @@ badframe: printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) @@ -556,9 +564,7 @@ badframe: printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -604,7 +610,7 @@ badframe: int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; + struct k_sigaction ka; unsigned long frame, newsp; int signr, ret; @@ -613,9 +619,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); - - ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ @@ -626,7 +630,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (signr > 0 && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK || (ret == ERESTARTSYS - && !(ka->sa.sa_flags & SA_RESTART)))) { + && !(ka.sa.sa_flags & SA_RESTART)))) { /* make the system call return an EINTR error */ regs->result = -EINTR; regs->gpr[3] = EINTR; @@ -645,7 +649,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (signr == 0) return 0; /* no signals delivered */ - if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && !on_sig_stack(regs->gpr[1])) newsp = current->sas_ss_sp + current->sas_ss_size; else @@ -653,17 +657,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) newsp &= ~0xfUL; /* Whee! Actually deliver the signal. */ - if (ka->sa.sa_flags & SA_SIGINFO) - handle_rt_signal(signr, ka, &info, oldset, regs, newsp); + if (ka.sa.sa_flags & SA_SIGINFO) + handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); else - handle_signal(signr, ka, &info, oldset, regs, newsp); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + handle_signal(signr, &ka, &info, oldset, regs, newsp); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (!(ka.sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask); sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index c28fbf398..dae491743 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -364,22 +363,15 @@ int __devinit start_secondary(void *unused) int __cpu_up(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; char buf[32]; int c; /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - wake_up_forked_process(p); - - init_idle(p, cpu); - unhash_process(p); - secondary_ti = p->thread_info; p->thread_info->cpu = cpu; diff --git a/arch/ppc/kernel/softemu8xx.c b/arch/ppc/kernel/softemu8xx.c index e44d9a06e..9bbb6bf7b 100644 --- a/arch/ppc/kernel/softemu8xx.c +++ b/arch/ppc/kernel/softemu8xx.c @@ -133,7 +133,7 @@ Soft_emulate_8xx(struct pt_regs *regs) print_8xx_pte(current->mm,regs->nip); pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK; pa |= (regs->nip & ~PAGE_MASK); - pa = __va(pa); + pa = (unsigned long)__va(pa); printk("Kernel VA for NIP %x ", pa); print_8xx_pte(current->mm,pa); } diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index cfeff0479..8839f6f07 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -108,41 +108,18 @@ static inline int tb_delta(unsigned *jiffy_stamp) { return delta; } -extern char _stext; - -static inline void ppc_do_profile (struct pt_regs *regs) +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *regs) { - unsigned long nip; - extern unsigned long prof_cpu_mask; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; + unsigned long pc = instruction_pointer(regs); - nip = instruction_pointer(regs); + if (in_lock_functions(pc)) + return regs->link; - /* - * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. - * (default is all CPUs.) - */ - if (!((1<>= prof_shift; - /* - * Don't ignore out-of-bounds EIP values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (nip > prof_len-1) - nip = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[nip]); + return pc; } +EXPORT_SYMBOL(profile_pc); +#endif /* * timer_interrupt - gets called when the decrementer overflows, @@ -161,10 +138,10 @@ void timer_interrupt(struct pt_regs * regs) irq_enter(); - while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) { + while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) { jiffy_stamp += tb_ticks_per_jiffy; - ppc_do_profile(regs); + profile_tick(CPU_PROFILING, regs); if (smp_processor_id()) continue; @@ -173,6 +150,9 @@ void timer_interrupt(struct pt_regs * regs) write_seqlock(&xtime_lock); tb_last_stamp = jiffy_stamp; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif /* * update the rtc when needed, this should be performed on the diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 544ea9fb5..115c97453 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -357,7 +357,7 @@ void RunModeException(struct pt_regs *regs) /* Illegal instruction emulation support. Originally written to * provide the PVR to user applications using the mfspr rd, PVR. - * Return non-zero if we can't emulate, or EFAULT if the associated + * Return non-zero if we can't emulate, or -EFAULT if the associated * memory access caused an access fault. Return zero on success. * * There are a couple of ways to do this, either "decode" the instruction @@ -368,16 +368,19 @@ void RunModeException(struct pt_regs *regs) #define INST_MFSPR_PVR 0x7c1f42a6 #define INST_MFSPR_PVR_MASK 0xfc1fffff +#define INST_DCBA 0x7c0005ec +#define INST_DCBA_MASK 0x7c0007fe + +#define INST_MCRXR 0x7c000400 +#define INST_MCRXR_MASK 0x7c0007fe + static int emulate_instruction(struct pt_regs *regs) { u32 instword; u32 rd; - int retval; - - retval = -EINVAL; if (!user_mode(regs)) - return retval; + return -EINVAL; CHECK_FULL_REGS(regs); if (get_user(instword, (u32 __user *)(regs->nip))) @@ -388,10 +391,24 @@ static int emulate_instruction(struct pt_regs *regs) if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { rd = (instword >> 21) & 0x1f; regs->gpr[rd] = mfspr(PVR); - retval = 0; - regs->nip += 4; + return 0; + } + + /* Emulating the dcba insn is just a no-op. */ + if ((instword & INST_DCBA_MASK) == INST_DCBA) + return 0; + + /* Emulate the mcrxr insn. */ + if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { + int shift = (instword >> 21) & 0x1c; + unsigned long msk = 0xf0000000UL >> shift; + + regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); + regs->xer &= ~0xf0000000UL; + return 0; } - return retval; + + return -EINVAL; } /* @@ -528,17 +545,23 @@ void ProgramCheckException(struct pt_regs *regs) return; } - if (reason & REASON_PRIVILEGED) { - /* Try to emulate it if we should. */ - if (emulate_instruction(regs) == 0) { + /* Try to emulate it if we should. */ + if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { + switch (emulate_instruction(regs)) { + case 0: + regs->nip += 4; emulate_single_step(regs); return; + case -EFAULT: + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); + return; } - _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); - return; } - _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + if (reason & REASON_PRIVILEGED) + _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); + else + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); } void SingleStepException(struct pt_regs *regs) @@ -624,22 +647,22 @@ void SoftwareEmulation(struct pt_regs *regs) } #endif /* CONFIG_8xx */ -#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) +#if defined(CONFIG_40x) || defined(CONFIG_BOOKE) void DebugException(struct pt_regs *regs, unsigned long debug_status) { -#if 0 - if (debug_status & DBSR_TIE) { /* trap instruction*/ - if (!user_mode(regs) && debugger_bpt(regs)) - return; - _exception(SIGTRAP, regs, 0, 0); - - } -#endif if (debug_status & DBSR_IC) { /* instruction completion */ - if (!user_mode(regs) && debugger_sstep(regs)) - return; - current->thread.dbcr0 &= ~DBCR0_IC; + regs->msr &= ~MSR_DE; + if (user_mode(regs)) { + current->thread.dbcr0 &= ~DBCR0_IC; + } else { + /* Disable instruction completion */ + mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC); + /* Clear the instruction completion event */ + mtspr(SPRN_DBSR, DBSR_IC); + if (debugger_sstep(regs)) + return; + } _exception(SIGTRAP, regs, TRAP_TRACE, 0); } } diff --git a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S index d8fe6b5fb..82a21346b 100644 --- a/arch/ppc/kernel/vector.S +++ b/arch/ppc/kernel/vector.S @@ -106,7 +106,7 @@ vmaddfp: 1: lfsx fr0,r4,r7 lfsx fr1,r5,r7 lfsx fr2,r6,r7 - fmadds fr0,fr0,fr1,fr2 + fmadds fr0,fr0,fr2,fr1 stfsx fr0,r3,r7 addi r7,r7,4 bdnz 1b @@ -133,7 +133,7 @@ vnmsubfp: 1: lfsx fr0,r4,r7 lfsx fr1,r5,r7 lfsx fr2,r6,r7 - fnmsubs fr0,fr0,fr1,fr2 + fnmsubs fr0,fr0,fr2,fr1 stfsx fr0,r3,r7 addi r7,r7,4 bdnz 1b diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S index 342848fe5..5d2cbc780 100644 --- a/arch/ppc/kernel/vmlinux.lds.S +++ b/arch/ppc/kernel/vmlinux.lds.S @@ -32,6 +32,7 @@ SECTIONS { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.got1) __got2_start = .; @@ -102,9 +103,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/ppc/lib/checksum.S b/arch/ppc/lib/checksum.S index 74928a7a2..7874e8a80 100644 --- a/arch/ppc/lib/checksum.S +++ b/arch/ppc/lib/checksum.S @@ -80,13 +80,13 @@ _GLOBAL(csum_partial) adde r0,r0,r5 /* be unnecessary to unroll this loop */ bdnz 2b andi. r4,r4,3 -3: cmpi 0,r4,2 +3: cmpwi 0,r4,2 blt+ 4f lhz r5,4(r3) addi r3,r3,2 subi r4,r4,2 adde r0,r0,r5 -4: cmpi 0,r4,1 +4: cmpwi 0,r4,1 bne+ 5f lbz r5,4(r3) slwi r5,r5,8 /* Upper byte of word */ @@ -143,7 +143,7 @@ _GLOBAL(csum_partial_copy_generic) adde r0,r0,r9 bdnz 82b 13: andi. r5,r5,3 -3: cmpi 0,r5,2 +3: cmpwi 0,r5,2 blt+ 4f 83: lhz r6,4(r3) addi r3,r3,2 @@ -151,7 +151,7 @@ _GLOBAL(csum_partial_copy_generic) 93: sth r6,4(r4) addi r4,r4,2 adde r0,r0,r6 -4: cmpi 0,r5,1 +4: cmpwi 0,r5,1 bne+ 5f 84: lbz r6,4(r3) 94: stb r6,4(r4) @@ -188,7 +188,7 @@ src_error_3: 97: stbu r6,1(r4) bdnz 97b src_error: - cmpi 0,r7,0 + cmpwi 0,r7,0 beq 1f li r6,-EFAULT stw r6,0(r7) @@ -196,7 +196,7 @@ src_error: blr dst_error: - cmpi 0,r8,0 + cmpwi 0,r8,0 beq 1f li r6,-EFAULT stw r6,0(r8) diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c index 252beec63..4ee888070 100644 --- a/arch/ppc/lib/dec_and_lock.c +++ b/arch/ppc/lib/dec_and_lock.c @@ -19,7 +19,7 @@ */ #ifndef ATOMIC_DEC_AND_LOCK -int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; @@ -42,5 +42,5 @@ int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) return 0; } -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif /* ATOMIC_DEC_AND_LOCK */ diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c index 103765660..42c5de2c8 100644 --- a/arch/ppc/lib/rheap.c +++ b/arch/ppc/lib/rheap.c @@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn) /* Grow the after block backwards */ if (before == NULL && after != NULL) { - (int8_t *) after->start -= size; + after->start = (int8_t *)after->start - size; after->size += size; return; } @@ -407,7 +407,7 @@ void *rh_detach_region(rh_info_t * info, void *start, int size) /* blk still in free list, with updated start and/or size */ if (bs == s || be == e) { if (bs == s) - (int8_t *) blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; } else { @@ -471,7 +471,7 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner) newblk->owner = owner; /* blk still in free list, with updated start, size */ - (int8_t *) blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; start = newblk->start; @@ -535,7 +535,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner) /* blk still in free list, with updated start and/or size */ if (bs == s || be == e) { if (bs == s) - (int8_t *) blk->start += size; + blk->start = (int8_t *)blk->start + size; blk->size -= size; } else { @@ -645,6 +645,7 @@ int rh_set_owner(rh_info_t * info, void *start, const char *owner) return -EINVAL; blk->owner = owner; + size = blk->size; return size; } diff --git a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h index aeaa1cde5..afb82b649 100644 --- a/arch/ppc/math-emu/op-common.h +++ b/arch/ppc/math-emu/op-common.h @@ -82,7 +82,6 @@ do { \ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ - __ret |= _FP_ROUND(wc, X); \ _FP_FRAC_SLL_##wc(X, 1); \ if (_FP_FRAC_OVERP_##wc(fs, X)) \ { \ diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c index 1d79838d9..72f7c0d1c 100644 --- a/arch/ppc/mm/44x_mmu.c +++ b/arch/ppc/mm/44x_mmu.c @@ -55,10 +55,8 @@ #include #include "mmu_decl.h" -#include "mem_pieces.h" extern char etext[], _stext[]; -extern struct mem_pieces phys_avail; /* Used by the 44x TLB replacement exception handler. * Just needed it declared someplace. @@ -72,7 +70,7 @@ unsigned int tlb_44x_hwater = 62; static void __init ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys) { - unsigned long attrib; + unsigned long attrib = 0; __asm__ __volatile__("\ clrrwi %2,%2,10\n\ @@ -105,16 +103,6 @@ unsigned long __init mmu_mapin_ram(void) unsigned int pinned_tlbs = 1; int i; - /* - * If lowmem is not on a pin tlb entry size boundary, - * then reserve the last page of system memory. This - * eliminates the possibility of a speculative dcache - * fetch past the end of system memory that would - * result in a machine check exception. - */ - if (total_lowmem | (PPC44x_PIN_SIZE - 1)) - mem_pieces_remove(&phys_avail, total_lowmem - PAGE_SIZE, PAGE_SIZE, 1); - /* Determine number of entries necessary to cover lowmem */ pinned_tlbs = (unsigned int) (_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT); diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c index 6066ff35c..a7f616140 100644 --- a/arch/ppc/mm/4xx_mmu.c +++ b/arch/ppc/mm/4xx_mmu.c @@ -52,6 +52,7 @@ #include #include "mmu_decl.h" +extern int __map_without_ltlbs; /* * MMU_init_hw does the chip-specific initialization of the MMU hardware. */ @@ -102,6 +103,10 @@ unsigned long __init mmu_mapin_ram(void) p = PPC_MEMSTART; s = 0; + if (__map_without_ltlbs) { + return s; + } + while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) { pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 448e80c11..cbed55208 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -104,6 +104,7 @@ extern unsigned long sysmap_size; * -- Cort */ int __map_without_bats; +int __map_without_ltlbs; /* max amount of RAM to use */ unsigned long __max_memory; @@ -204,6 +205,10 @@ void MMU_setup(void) __map_without_bats = 1; } + if (strstr(cmd_line, "noltlbs")) { + __map_without_ltlbs = 1; + } + /* Look for mem= option on command line */ if (strstr(cmd_line, "mem=")) { char *p, *q; diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c index c16d4cce4..4adc48c69 100644 --- a/arch/ppc/mm/pgtable.c +++ b/arch/ppc/mm/pgtable.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -152,19 +153,19 @@ void pte_free(struct page *ptepage) } #ifndef CONFIG_44x -void * +void __iomem * ioremap(phys_addr_t addr, unsigned long size) { return __ioremap(addr, size, _PAGE_NO_CACHE); } #else /* CONFIG_44x */ -void * +void __iomem * ioremap64(unsigned long long addr, unsigned long size) { return __ioremap(addr, size, _PAGE_NO_CACHE); } -void * +void __iomem * ioremap(phys_addr_t addr, unsigned long size) { phys_addr_t addr64 = fixup_bigphys_addr(addr, size); @@ -173,7 +174,7 @@ ioremap(phys_addr_t addr, unsigned long size) } #endif /* CONFIG_44x */ -void * +void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { unsigned long v, i; @@ -256,10 +257,10 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) } out: - return (void *) (v + ((unsigned long)addr & ~PAGE_MASK)); + return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK)); } -void iounmap(void *addr) +void iounmap(volatile void __iomem *addr) { /* * If mapped by BATs then there is nothing to do. @@ -271,6 +272,18 @@ void iounmap(void *addr) vunmap((void *) (PAGE_MASK & (unsigned long)addr)); } +void __iomem *ioport_map(unsigned long port, unsigned int len) +{ + return (void __iomem *) (port + _IO_BASE); +} + +void ioport_unmap(void __iomem *addr) +{ + /* Nothing to do */ +} +EXPORT_SYMBOL(ioport_map); +EXPORT_SYMBOL(ioport_unmap); + int map_page(unsigned long va, phys_addr_t pa, int flags) { diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 578b0ac9c..85e9cdb7b 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -56,6 +56,11 @@ config WALNUT help This option enables support for the IBM PPC405GP evaluation board. +config XILINX_ML300 + bool "Xilinx-ML300" + help + This option enables support for the Xilinx ML300 evaluation board. + endchoice choice @@ -130,6 +135,11 @@ config IBM_OCP depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y +config XILINX_OCP + bool + depends on XILINX_ML300 + default y + config IBM_EMAC4 bool depends on 440GX @@ -160,6 +170,11 @@ config 405GPR depends on SYCAMORE default y +config VIRTEX_II_PRO + bool + depends on XILINX_ML300 + default y + config STB03xxx bool depends on REDWOOD_5 || REDWOOD_6 @@ -167,7 +182,7 @@ config STB03xxx config EMBEDDEDBOOT bool - depends on EP405 + depends on EP405 || XILINX_ML300 default y config IBM_OPENBIOS @@ -184,6 +199,11 @@ config PPC4xx_EDMA depends on !STB03xxx && PPC4xx_DMA default y +config PPC_GEN550 + bool + depends on 4xx + default y + config PM bool "Power Management support (EXPERIMENTAL)" depends on 4xx && EXPERIMENTAL diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index 82064c35d..a1efbf507 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_REDWOOD_5) += redwood5.o obj-$(CONFIG_REDWOOD_6) += redwood6.o obj-$(CONFIG_SYCAMORE) += sycamore.o obj-$(CONFIG_WALNUT) += walnut.o +obj-$(CONFIG_XILINX_ML300) += xilinx_ml300.o obj-$(CONFIG_405GP) += ibm405gp.o obj-$(CONFIG_REDWOOD_5) += ibmstb4.o @@ -21,3 +22,4 @@ obj-$(CONFIG_440GP) += ibm440gp.o obj-$(CONFIG_440GX) += ibm440gx.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o +obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 6c9bde473..cadf0947a 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -1,11 +1,13 @@ /* - * arch/ppc/platforms/ebony.c + * arch/ppc/platforms/4xx/ebony.c * * Ebony board specific routines * - * Matt Porter + * Matt Porter + * Copyright 2002-2004 MontaVista Software Inc. * - * Copyright 2002 MontaVista Software Inc. + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies * * 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 @@ -48,6 +50,10 @@ #include #include +#include + +static struct ibm44x_clocks clocks __initdata; + /* * Ebony IRQ triggering/polarity settings */ @@ -118,8 +124,6 @@ static u_char ebony_IRQ_initsenses[] __initdata = { (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 63: EMAC 1 WOL */ }; -extern void abort(void); - static void __init ebony_calibrate_decr(void) { @@ -143,18 +147,7 @@ ebony_calibrate_decr(void) break; } - tb_ticks_per_jiffy = freq / HZ; - tb_to_us = mulhwu_scale_factor(freq, 1000000); - - /* Set the time base to zero */ - mtspr(SPRN_TBWL, 0); - mtspr(SPRN_TBWU, 0); - - /* Clear any pending timer interrupts */ - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); - - /* Enable decrementer interrupt */ - mtspr(SPRN_TCR, TCR_DIE); + ibm44x_calibrate_decr(freq); } static int @@ -283,7 +276,7 @@ ebony_early_serial_map(void) memset(&port, 0, sizeof(port)); port.membase = ioremap64(PPC440GP_UART0_ADDR, 8); port.irq = 0; - port.uartclk = BASE_BAUD * 16; + port.uartclk = clocks.uart0; port.regshift = 0; port.iotype = SERIAL_IO_MEM; port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; @@ -293,31 +286,33 @@ ebony_early_serial_map(void) printk("Early serial init of port 0 failed\n"); } +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(0, &port); +#endif + port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); port.irq = 1; + port.uartclk = clocks.uart1; port.line = 1; if (early_serial_setup(&port) != 0) { printk("Early serial init of port 1 failed\n"); } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(1, &port); +#endif } static void __init ebony_setup_arch(void) { unsigned char * vpd_base; - struct ibm44x_clocks clocks; struct ocp_def *def; struct ocp_func_emac_data *emacdata; -#if !defined(CONFIG_BDI_SWITCH) - /* - * The Abatron BDI JTAG debugger does not tolerate others - * mucking with the debug registers. - */ - mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); -#endif - /* Set mac_addr for each EMAC */ vpd_base = ioremap64(EBONY_VPD_BASE, EBONY_VPD_SIZE); def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); @@ -361,10 +356,6 @@ ebony_setup_arch(void) ROOT_DEV = Root_HDA1; #endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - ebony_early_serial_map(); ibm4xxPIC_InitSenses = ebony_IRQ_initsenses; @@ -374,152 +365,17 @@ ebony_setup_arch(void) printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n"); } -static void -ebony_restart(char *cmd) -{ - local_irq_disable(); - abort(); -} - -static void -ebony_power_off(void) -{ - local_irq_disable(); - for(;;); -} - -static void -ebony_halt(void) -{ - local_irq_disable(); - for(;;); -} - -/* - * Read the 440GP memory controller to get size of system memory. - */ -static unsigned long __init -ebony_find_end_of_memory(void) -{ - u32 i, bank_config; - u32 mem_size = 0; - - for (i=0; i<4; i++) - { - switch (i) - { - case 0: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR); - break; - case 1: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR); - break; - case 2: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR); - break; - case 3: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR); - break; - } - - bank_config = mfdcr(DCRN_SDRAM0_CFGDATA); - - if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE)) - continue; - switch (SDRAM_CONFIG_BANK_SIZE(bank_config)) - { - case SDRAM_CONFIG_SIZE_8M: - mem_size += PPC44x_MEM_SIZE_8M; - break; - case SDRAM_CONFIG_SIZE_16M: - mem_size += PPC44x_MEM_SIZE_16M; - break; - case SDRAM_CONFIG_SIZE_32M: - mem_size += PPC44x_MEM_SIZE_32M; - break; - case SDRAM_CONFIG_SIZE_64M: - mem_size += PPC44x_MEM_SIZE_64M; - break; - case SDRAM_CONFIG_SIZE_128M: - mem_size += PPC44x_MEM_SIZE_128M; - break; - case SDRAM_CONFIG_SIZE_256M: - mem_size += PPC44x_MEM_SIZE_256M; - break; - case SDRAM_CONFIG_SIZE_512M: - mem_size += PPC44x_MEM_SIZE_512M; - break; - } - } - return mem_size; -} - -static void __init -ebony_init_irq(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) - irq_desc[i].handler = ppc4xx_pic; -} - -#ifdef CONFIG_SERIAL_TEXT_DEBUG -#include -#include -#include - -static struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in */ -}; - -static void -ebony_progress(char *s, unsigned short hex) -{ - volatile char c; - volatile unsigned long com_port; - u16 shift; - - com_port = (unsigned long)rs_table[0].iomem_base; - shift = rs_table[0].iomem_reg_shift; - - while ((c = *s++) != 0) { - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = c; - - } - - /* Send LF/CR to pretty up output */ - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = '\r'; - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = '\n'; -} -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ - void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { parse_bootinfo((struct bi_record *) (r3 + KERNELBASE)); + ibm44x_platform_init(); + ppc_md.setup_arch = ebony_setup_arch; ppc_md.show_cpuinfo = ebony_show_cpuinfo; - ppc_md.init_IRQ = ebony_init_irq; ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ - ppc_md.find_end_of_memory = ebony_find_end_of_memory; - - ppc_md.restart = ebony_restart; - ppc_md.power_off = ebony_power_off; - ppc_md.halt = ebony_halt; - ppc_md.calibrate_decr = ebony_calibrate_decr; ppc_md.time_init = todc_time_init; ppc_md.set_rtc_time = todc_set_rtc_time; @@ -527,10 +383,6 @@ void __init platform_init(unsigned long r3, unsigned long r4, ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; - -#ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = ebony_progress; -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ #ifdef CONFIG_KGDB ppc_md.early_serial_map = ebony_early_serial_map; #endif diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index c4352e6bb..f90ddf309 100755 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -40,21 +40,21 @@ #define EBONY_RTC_SIZE 0x2000 /* Flash */ -#define EBONY_FPGA_ADDR 0x0000000148300000 +#define EBONY_FPGA_ADDR 0x0000000148300000ULL #define EBONY_BOOT_SMALL_FLASH(x) (x & 0x20) #define EBONY_ONBRD_FLASH_EN(x) (x & 0x02) #define EBONY_FLASH_SEL(x) (x & 0x01) -#define EBONY_SMALL_FLASH_LOW1 0x00000001ff800000 -#define EBONY_SMALL_FLASH_LOW2 0x00000001ff880000 -#define EBONY_SMALL_FLASH_HIGH1 0x00000001fff00000 -#define EBONY_SMALL_FLASH_HIGH2 0x00000001fff80000 +#define EBONY_SMALL_FLASH_LOW1 0x00000001ff800000ULL +#define EBONY_SMALL_FLASH_LOW2 0x00000001ff880000ULL +#define EBONY_SMALL_FLASH_HIGH1 0x00000001fff00000ULL +#define EBONY_SMALL_FLASH_HIGH2 0x00000001fff80000ULL #define EBONY_SMALL_FLASH_SIZE 0x80000 -#define EBONY_LARGE_FLASH_LOW 0x00000001ff800000 -#define EBONY_LARGE_FLASH_HIGH 0x00000001ffc00000 +#define EBONY_LARGE_FLASH_LOW 0x00000001ff800000ULL +#define EBONY_LARGE_FLASH_HIGH 0x00000001ffc00000ULL #define EBONY_LARGE_FLASH_SIZE 0x400000 -#define EBONY_SMALL_FLASH_BASE 0x00000001fff80000 -#define EBONY_LARGE_FLASH_BASE 0x00000001ff800000 +#define EBONY_SMALL_FLASH_BASE 0x00000001fff80000ULL +#define EBONY_LARGE_FLASH_BASE 0x00000001ff800000ULL /* * Serial port defines diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 6376890e3..6b3036fb7 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -1,11 +1,11 @@ /* - * arch/ppc/platforms/ocotea.c + * arch/ppc/platforms/4xx/ocotea.c * * Ocotea board specific routines * - * Matt Porter + * Matt Porter * - * Copyright 2003 MontaVista Software Inc. + * Copyright 2003-2004 MontaVista Software 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 @@ -47,7 +47,9 @@ #include #include #include +#include +#include #include /* @@ -57,27 +59,21 @@ */ #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" -extern void abort(void); +bd_t __res; + +static struct ibm44x_clocks clocks __initdata; static void __init ocotea_calibrate_decr(void) { unsigned int freq; - freq = OCOTEA_SYSCLK; - - tb_ticks_per_jiffy = freq / HZ; - tb_to_us = mulhwu_scale_factor(freq, 1000000); - - /* Set the time base to zero */ - mtspr(SPRN_TBWL, 0); - mtspr(SPRN_TBWU, 0); - - /* Clear any pending timer interrupts */ - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + if (mfspr(SPRN_CCR1) & CCR1_TCS) + freq = OCOTEA_TMR_CLK; + else + freq = clocks.cpu; - /* Enable decrementer interrupt */ - mtspr(SPRN_TCR, TCR_DIE); + ibm44x_calibrate_decr(freq); } static int @@ -85,9 +81,10 @@ ocotea_show_cpuinfo(struct seq_file *m) { seq_printf(m, "vendor\t\t: IBM\n"); seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n"); - + ibm440gx_show_cpuinfo(m); return 0; } + static inline int ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { @@ -107,14 +104,54 @@ ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) return PCI_IRQ_TABLE_LOOKUP; } +static void __init ocotea_set_emacdata(void) +{ + struct ocp_def *def; + struct ocp_func_emac_data *emacdata; + int i; + + /* + * Note: Current rev. board only operates in Group 4a + * mode, so we always set EMAC0-1 for SMII and EMAC2-3 + * for RGMII (though these could run in RTBI just the same). + * + * The FPGA reg 3 information isn't even suitable for + * determining the phy_mode, so if the board becomes + * usable in !4a, it will be necessary to parse an environment + * variable from the firmware or similar to properly configure + * the phy_map/phy_mode. + */ + /* Set phy_map, phy_mode, and mac_addr for each EMAC */ + for (i=0; i<4; i++) { + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); + emacdata = def->additions; + if (i < 2) { + emacdata->phy_map = 0x00000001; /* Skip 0x00 */ + emacdata->phy_mode = PHY_MODE_SMII; + } + else { + emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */ + emacdata->phy_mode = PHY_MODE_RGMII; + } + if (i == 0) + memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); + else if (i == 1) + memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); + else if (i == 2) + memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6); + else if (i == 3) + memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6); + } +} + #define PCIX_READW(offset) \ - (readw((u32)pcix_reg_base+offset)) + (readw(pcix_reg_base+offset)) #define PCIX_WRITEW(value, offset) \ - (writew(value, (u32)pcix_reg_base+offset)) + (writew(value, pcix_reg_base+offset)) #define PCIX_WRITEL(value, offset) \ - (writel(value, (u32)pcix_reg_base+offset)) + (writel(value, pcix_reg_base+offset)) /* * FIXME: This is only here to "make it work". This will move @@ -209,7 +246,7 @@ ocotea_setup_hose(void) TODC_ALLOC(); static void __init -ocotea_early_serial_map(const struct ibm44x_clocks *clks) +ocotea_early_serial_map(void) { struct uart_port port; @@ -217,7 +254,7 @@ ocotea_early_serial_map(const struct ibm44x_clocks *clks) memset(&port, 0, sizeof(port)); port.membase = ioremap64(PPC440GX_UART0_ADDR, 8); port.irq = UART0_INT; - port.uartclk = clks->uart0; + port.uartclk = clocks.uart0; port.regshift = 0; port.iotype = SERIAL_IO_MEM; port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; @@ -227,74 +264,33 @@ ocotea_early_serial_map(const struct ibm44x_clocks *clks) printk("Early serial init of port 0 failed\n"); } +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(0, &port); +#endif + port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); port.irq = UART1_INT; - port.uartclk = clks->uart1; + port.uartclk = clocks.uart1; port.line = 1; if (early_serial_setup(&port) != 0) { printk("Early serial init of port 1 failed\n"); } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(1, &port); +#endif } static void __init ocotea_setup_arch(void) { - unsigned char *addr; - unsigned long long mac64; - struct ocp_def *def; - struct ocp_func_emac_data *emacdata; - int i; - struct ibm44x_clocks clocks; - - /* - * Note: Current rev. board only operates in Group 4a - * mode, so we always set EMAC0-1 for SMII and EMAC2-3 - * for RGMII (though these could run in RTBI just the same). - * - * The FPGA reg 3 information isn't even suitable for - * determining the phy_mode, so if the board becomes - * usable in !4a, it will be necessary to parse an environment - * variable from the firmware or similar to properly configure - * the phy_map/phy_mode. - */ - /* Set phy_map, phy_mode, and mac_addr for each EMAC */ - addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE); - for (i=0; i<4; i++) { - mac64 = simple_strtoull(addr+OCOTEA_MAC_OFFSET*i, 0, 16); - def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); - emacdata = def->additions; - if (i < 2) { - emacdata->phy_map = 0x00000001; /* Skip 0x00 */ - emacdata->phy_mode = PHY_MODE_SMII; - } - else { - emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */ - emacdata->phy_mode = PHY_MODE_RGMII; - } - memcpy(emacdata->mac_addr, (char *)&mac64+2, 6); - } - iounmap(addr); + ocotea_set_emacdata(); ibm440gx_tah_enable(); -#if !defined(CONFIG_BDI_SWITCH) - /* - * The Abatron BDI JTAG debugger does not tolerate others - * mucking with the debug registers. - */ - mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); -#endif - - /* - * Determine various clocks. - * To be completely correct we should get SysClk - * from FPGA, because it can be changed by on-board switches - * --ebs - */ - ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); - ocp_sys_info.opb_bus_freq = clocks.opb; - /* Setup TODC access */ TODC_INIT(TODC_TYPE_DS1743, 0, @@ -319,173 +315,50 @@ ocotea_setup_arch(void) ROOT_DEV = Root_HDA1; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - - ocotea_early_serial_map(&clocks); + ocotea_early_serial_map(); /* Identify the system */ printk("IBM Ocotea port (MontaVista Software, Inc. )\n"); } -static void -ocotea_restart(char *cmd) -{ - local_irq_disable(); - abort(); -} - -static void -ocotea_power_off(void) +static void __init ocotea_init(void) { - local_irq_disable(); - for(;;); + ibm440gx_l2c_setup(&clocks); } -static void -ocotea_halt(void) -{ - local_irq_disable(); - for(;;); -} - -/* - * Read the 440GX memory controller to get size of system memory. - */ -static unsigned long __init -ocotea_find_end_of_memory(void) -{ - u32 i, bank_config; - u32 mem_size = 0; - - for (i=0; i<4; i++) - { - switch (i) - { - case 0: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR); - break; - case 1: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR); - break; - case 2: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR); - break; - case 3: - mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR); - break; - } - - bank_config = mfdcr(DCRN_SDRAM0_CFGDATA); - - if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE)) - continue; - switch (SDRAM_CONFIG_BANK_SIZE(bank_config)) - { - case SDRAM_CONFIG_SIZE_8M: - mem_size += PPC44x_MEM_SIZE_8M; - break; - case SDRAM_CONFIG_SIZE_16M: - mem_size += PPC44x_MEM_SIZE_16M; - break; - case SDRAM_CONFIG_SIZE_32M: - mem_size += PPC44x_MEM_SIZE_32M; - break; - case SDRAM_CONFIG_SIZE_64M: - mem_size += PPC44x_MEM_SIZE_64M; - break; - case SDRAM_CONFIG_SIZE_128M: - mem_size += PPC44x_MEM_SIZE_128M; - break; - case SDRAM_CONFIG_SIZE_256M: - mem_size += PPC44x_MEM_SIZE_256M; - break; - case SDRAM_CONFIG_SIZE_512M: - mem_size += PPC44x_MEM_SIZE_512M; - break; - } - } - return mem_size; -} - -static void __init -ocotea_init_irq(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) - irq_desc[i].handler = ppc4xx_pic; -} - -#ifdef CONFIG_SERIAL_TEXT_DEBUG -#include -#include -#include -struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in */ -}; - -static void -ocotea_progress(char *s, unsigned short hex) +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) { - volatile char c; - volatile unsigned long com_port; - u16 shift; - - com_port = (unsigned long)rs_table[0].iomem_base; - shift = rs_table[0].iomem_reg_shift; - - while ((c = *s++) != 0) { - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = c; + parse_bootinfo(find_bootinfo()); - } - - /* Send LF/CR to pretty up output */ - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = '\r'; - while ((*((volatile unsigned char *)com_port + - (UART_LSR << shift)) & UART_LSR_THRE) == 0) - ; - *(volatile unsigned char *)com_port = '\n'; -} -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) + __res = *(bd_t *)(r3 + KERNELBASE); -#if 0 -static void __init -ocotea_map_io(void) -{ - io_block_mapping(0xe0000000, 0x0000000140000000, - 0x00001000, _PAGE_IO); -} -#endif + /* + * Determine various clocks. + * To be completely correct we should get SysClk + * from FPGA, because it can be changed by on-board switches + * --ebs + */ + ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ocp_sys_info.opb_bus_freq = clocks.opb; -void __init platform_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7) -{ - parse_bootinfo((struct bi_record *) (r3 + KERNELBASE)); + /* XXX Fix L2C IRQ triggerring setting (edge-sensitive). + * Firmware (at least PIBS v1.72 OCT/28/2003) sets it incorrectly + * --ebs + */ + mtdcr(DCRN_UIC_TR(UIC2), mfdcr(DCRN_UIC_TR(UIC2)) | 0x00000100); - /* Disable L2-Cache due to hardware issues */ - ibm440gx_l2c_disable(); + ibm44x_platform_init(); ppc_md.setup_arch = ocotea_setup_arch; ppc_md.show_cpuinfo = ocotea_show_cpuinfo; - ppc_md.init_IRQ = ocotea_init_irq; ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ - ppc_md.find_end_of_memory = ocotea_find_end_of_memory; - - ppc_md.restart = ocotea_restart; - ppc_md.power_off = ocotea_power_off; - ppc_md.halt = ocotea_halt; - ppc_md.calibrate_decr = ocotea_calibrate_decr; ppc_md.time_init = todc_time_init; ppc_md.set_rtc_time = todc_set_rtc_time; @@ -493,11 +366,8 @@ void __init platform_init(unsigned long r3, unsigned long r4, ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; - -#ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = ocotea_progress; -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ #ifdef CONFIG_KGDB ppc_md.early_serial_map = ocotea_early_serial_map; #endif + ppc_md.init = ocotea_init; } diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h index 17fe8dada..90cd0afa1 100644 --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -24,13 +24,14 @@ /* F/W TLB mapping used in bootloader glue to reset EMAC */ #define PPC44x_EMAC0_MR0 0xE0000800 -/* Location of MAC addresses in firmware */ -#define OCOTEA_MAC_BASE (OCOTEA_SMALL_FLASH_HIGH+0xb0500) -#define OCOTEA_MAC_SIZE 0x200 -#define OCOTEA_MAC_OFFSET 0x100 - -/* Default clock rate */ -#define OCOTEA_SYSCLK 25000000 +/* Location of MAC addresses in PIBS image */ +#define OCOTEA_PIBS_FLASH 0xfff00000 +#define OCOTEA_PIBS_MAC_BASE (OCOTEA_PIBS_FLASH+0xb0500) +#define OCOTEA_PIBS_MAC_SIZE 0x200 +#define OCOTEA_PIBS_MAC_OFFSET 0x100 + +/* External timer clock frequency */ +#define OCOTEA_TMR_CLK 25000000 /* RTC/NVRAM location */ #define OCOTEA_RTC_ADDR 0x0000000148000000ULL diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index aada7e456..686dd6d9a 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -120,10 +120,6 @@ mpc8540ads_setup_arch(void) mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - #ifdef CONFIG_SERIAL_8250 mpc85xx_early_serial_map(); #endif diff --git a/arch/ppc/platforms/85xx/mpc8555.c b/arch/ppc/platforms/85xx/mpc8555.c index 942758480..b411c1824 100644 --- a/arch/ppc/platforms/85xx/mpc8555.c +++ b/arch/ppc/platforms/85xx/mpc8555.c @@ -77,6 +77,13 @@ struct ocp_def core_ocp[] = { .pm = OCP_CPM_NA, }, { .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_SEC2, + .index = 0, + .paddr = MPC85xx_SEC2_OFFSET, + .irq = MPC85xx_IRQ_SEC2, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PERFMON, .index = 0, .paddr = MPC85xx_PERFMON_OFFSET, diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 0cb2c3458..64c9ce71d 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -145,12 +145,18 @@ mpc8560ads_setup_arch(void) static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) { - while ((irq = cpm2_get_irq(regs)) >= 0) { - ppc_irq_dispatch_handler(regs, irq); - } + while ((irq = cpm2_get_irq(regs)) >= 0) + __do_IRQ(irq, regs); return IRQ_HANDLED; } +static struct irqaction cpm2_irqaction = { + .handler = cpm2_cascade, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "cpm2_cascade", +}; + static void __init mpc8560_ads_init_IRQ(void) { @@ -174,7 +180,7 @@ mpc8560_ads_init_IRQ(void) immap->im_intctl.ic_scprrh = 0x05309770; immap->im_intctl.ic_scprrl = 0x05309770; - request_irq(MPC85xx_IRQ_CPM, cpm2_cascade, SA_INTERRUPT, "cpm2_cascade", NULL); + setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction); return; } diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 7f0fabc5d..45c8671e2 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -142,8 +142,7 @@ mpc85xx_ads_show_cpuinfo(struct seq_file *m) seq_printf(m, "Machine\t\t: unknown\n"); break; } - seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000, - freq % 1000000); + seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); seq_printf(m, "PVR\t\t: 0x%x\n", pvid); seq_printf(m, "SVR\t\t: 0x%x\n", svid); diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index c7e53e39c..1837da991 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -172,8 +172,7 @@ mpc85xx_cds_show_cpuinfo(struct seq_file *m) seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); seq_printf(m, "Machine\t\t: CDS (%x)\n", cadmus[CM_VER]); - seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000, - freq % 1000000); + seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); seq_printf(m, "PVR\t\t: 0x%x\n", pvid); seq_printf(m, "SVR\t\t: 0x%x\n", svid); @@ -191,10 +190,15 @@ mpc85xx_cds_show_cpuinfo(struct seq_file *m) static void cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) { while((irq = cpm2_get_irq(regs)) >= 0) - { - ppc_irq_dispatch_handler(regs,irq); - } + __do_IRQ(irq, regs); } + +static struct irqaction cpm2_irqaction = { + .handler = cpm2_cascade, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "cpm2_cascade", +}; #endif /* CONFIG_CPM2 */ void __init @@ -237,7 +241,7 @@ mpc85xx_cds_init_IRQ(void) immap->im_intctl.ic_scprrh = 0x05309770; immap->im_intctl.ic_scprrl = 0x05309770; - request_irq(MPC85xx_IRQ_CPM, cpm2_cascade, SA_INTERRUPT, "cpm2_cascade", NULL); + setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction); #endif return; @@ -307,7 +311,7 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) { if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; -#if CONFIG_85xx_PCI2 +#ifdef CONFIG_85xx_PCI2 /* With the current code we know PCI2 will be bus 2, however this may * not be guarnteed */ if (bus == 2 && PCI_SLOT(devfn) == 0) @@ -358,10 +362,6 @@ mpc85xx_cds_setup_arch(void) mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - #ifdef CONFIG_SERIAL_8250 mpc85xx_early_serial_map(); #endif diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index a4a91aa6a..50cc50a0c 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -144,9 +144,6 @@ sbc8560_setup_arch(void) /* setup PCI host bridges */ mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_SERIAL_8250 sbc8560_early_serial_map(); #endif diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c index 8cc3323a6..110ae68f6 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.c +++ b/arch/ppc/platforms/85xx/sbc85xx.c @@ -142,8 +142,7 @@ sbc8560_show_cpuinfo(struct seq_file *m) seq_printf(m, "Machine\t\t: unknown\n"); break; } - seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000, - freq % 1000000); + seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); seq_printf(m, "PVR\t\t: 0x%x\n", pvid); seq_printf(m, "SVR\t\t: 0x%x\n", svid); diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile index c59d4871d..c393f58e5 100644 --- a/arch/ppc/platforms/Makefile +++ b/arch/ppc/platforms/Makefile @@ -21,23 +21,21 @@ endif obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o -obj-$(CONFIG_EST8260) += est8260_setup.o -obj-$(CONFIG_PQ2ADS) += pq2ads_setup.o +obj-$(CONFIG_PQ2ADS) += pq2ads.o obj-$(CONFIG_TQM8260) += tqm8260_setup.o obj-$(CONFIG_EV64260) += ev64260_setup.o obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o obj-$(CONFIG_K2) += k2.o -obj-$(CONFIG_LOPEC) += lopec_setup.o lopec_pci.o +obj-$(CONFIG_LOPEC) += lopec.o obj-$(CONFIG_MCPN765) += mcpn765.o obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o -obj-$(CONFIG_MVME5100) += mvme5100_setup.o mvme5100_pci.o +obj-$(CONFIG_MVME5100) += mvme5100.o obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o obj-$(CONFIG_PCORE) += pcore.o obj-$(CONFIG_POWERPMC250) += powerpmc250.o obj-$(CONFIG_PPLUS) += pplus.o obj-$(CONFIG_PRPMC750) += prpmc750.o obj-$(CONFIG_PRPMC800) += prpmc800.o -obj-$(CONFIG_RPX8260) += rpx8260.o obj-$(CONFIG_SANDPOINT) += sandpoint.o obj-$(CONFIG_SBC82xx) += sbc82xx.o obj-$(CONFIG_SPRUCE) += spruce.o diff --git a/arch/ppc/platforms/adir_pic.c b/arch/ppc/platforms/adir_pic.c index ecdf1237b..9947cba52 100644 --- a/arch/ppc/platforms/adir_pic.c +++ b/arch/ppc/platforms/adir_pic.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -20,11 +20,6 @@ static void adir_onboard_pic_enable(unsigned int irq); static void adir_onboard_pic_disable(unsigned int irq); -static void -no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ -} - __init static void adir_onboard_pic_init(void) { @@ -88,6 +83,13 @@ static struct hw_interrupt_type adir_onboard_pic = { NULL }; +static struct irqaction noop_action = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "82c59 primary cascade", +}; + /* * Linux interrupt values are assigned as follows: * @@ -110,11 +112,7 @@ adir_init_IRQ(void) adir_onboard_pic_init(); /* Enable 8259 interrupt cascade */ - request_irq(ADIR_IRQ_VT82C686_INTR, - no_action, - SA_INTERRUPT, - "82c59 primary cascade", - NULL); + setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action); } int diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c index e4ace971a..9575938b9 100644 --- a/arch/ppc/platforms/chrp_pci.c +++ b/arch/ppc/platforms/chrp_pci.c @@ -158,7 +158,7 @@ chrp_pcibios_fixup(void) struct device_node *np; /* PCI interrupts are controlled by the OpenPIC */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { np = pci_device_to_OF_node(dev); if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0)) dev->irq = np->intrs[0].line; diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 56be78eb4..03b3b3b84 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -250,13 +250,6 @@ chrp_setup_arch(void) */ sio_init(); - /* - * Setup the console operations - */ -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ @@ -378,11 +371,19 @@ static void __init chrp_find_openpic(void) } } +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) +static struct irqaction xmon_irqaction = { + .handler = xmon_irq, + .mask = CPU_MASK_NONE, + .name = "XMON break", +}; +#endif + void __init chrp_init_IRQ(void) { struct device_node *np; int i; - unsigned long chrp_int_ack; + unsigned long chrp_int_ack = 0; unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) struct device_node *kbd; @@ -423,7 +424,7 @@ void __init chrp_init_IRQ(void) && strcmp(kbd->parent->type, "adb") == 0) break; if (kbd) - request_irq(HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0); + setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction); #endif } diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c index 71f62a055..863d1e325 100644 --- a/arch/ppc/platforms/chrp_smp.c +++ b/arch/ppc/platforms/chrp_smp.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h index bc51f072a..adba68ecf 100644 --- a/arch/ppc/platforms/est8260.h +++ b/arch/ppc/platforms/est8260.h @@ -10,6 +10,9 @@ #define BOOTROM_RESTART_ADDR ((uint)0xff000104) +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "EST Corporation" +#define CPUINFO_MACHINE "SBC8260 PowerPC" /* A Board Information structure that is given to a program when * prom starts it up. diff --git a/arch/ppc/platforms/gemini_pci.c b/arch/ppc/platforms/gemini_pci.c index 17b251c44..95656091b 100644 --- a/arch/ppc/platforms/gemini_pci.c +++ b/arch/ppc/platforms/gemini_pci.c @@ -15,7 +15,7 @@ void __init gemini_pcibios_fixup(void) int i; struct pci_dev *dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { for(i = 0; i < 6; i++) { if (dev->resource[i].flags & IORESOURCE_IO) { dev->resource[i].start |= (0xfe << 24); diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c index 4e2e18a52..be5c0511f 100644 --- a/arch/ppc/platforms/k2.c +++ b/arch/ppc/platforms/k2.c @@ -116,7 +116,7 @@ void k2_pcibios_fixup(void) /* * Enable DMA support on hdc */ - ide_dev = pci_find_device(PCI_VENDOR_ID_AL, + ide_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, NULL); if (ide_dev) { @@ -126,6 +126,7 @@ void k2_pcibios_fixup(void) ide_dma_base = pci_resource_start(ide_dev, 4); outb(0x00, ide_dma_base + 0x2); outb(0x20, ide_dma_base + 0xa); + pci_dev_put(ide_dev); } #endif } @@ -464,10 +465,6 @@ static void __init k2_setup_arch(void) ROOT_DEV = Root_HDC1; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - /* Identify the system */ printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ " "%d Mhz\n", k2_get_cpu_speed() / 1000000); diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c index 043040dc9..db6ea440c 100644 --- a/arch/ppc/platforms/lite5200.c +++ b/arch/ppc/platforms/lite5200.c @@ -36,6 +36,8 @@ #include +extern int powersave_nap; + /* Board data given by U-Boot */ bd_t __res; EXPORT_SYMBOL(__res); /* For modules */ @@ -64,25 +66,55 @@ struct ocp_def board_ocp[] = { .vendor = OCP_VENDOR_INVALID } }; - + /* ======================================================================== */ /* Platform specific code */ /* ======================================================================== */ static int -icecube_show_cpuinfo(struct seq_file *m) +lite5200_show_cpuinfo(struct seq_file *m) { seq_printf(m, "machine\t\t: Freescale LITE5200\n"); return 0; } static void __init -icecube_setup_arch(void) +lite5200_setup_cpu(void) { + struct mpc52xx_intr *intr; + + u32 intr_ctrl; + + /* Map zones */ + intr = (struct mpc52xx_intr *) + ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr)); + + if (!intr) { + printk("lite5200.c: Error while mapping INTR during lite5200_setup_cpu\n"); + goto unmap_regs; + } + + /* IRQ[0-3] setup : IRQ0 - Level Active Low */ + /* IRQ[1-3] - Level Active High */ + intr_ctrl = in_be32(&intr->ctrl); + intr_ctrl &= ~0x00ff0000; + intr_ctrl |= 0x00c00000; + out_be32(&intr->ctrl, intr_ctrl); + + /* Unmap reg zone */ +unmap_regs: + if (intr) iounmap(intr); +} +static void __init +lite5200_setup_arch(void) +{ /* Add board OCP definitions */ mpc52xx_add_board_devices(board_ocp); + + /* CPU & Port mux setup */ + lite5200_setup_cpu(); } void __init @@ -110,7 +142,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, initrd_end = r5 + KERNELBASE; } #endif - + /* Load the command line */ if (r6) { *(char *)(r7+KERNELBASE) = 0; @@ -120,14 +152,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, /* BAT setup */ mpc52xx_set_bat(); - + /* No ISA bus AFAIK */ isa_io_base = 0; isa_mem_base = 0; + /* Powersave */ + powersave_nap = 1; /* We allow this platform to NAP */ + /* Setup the ppc_md struct */ - ppc_md.setup_arch = icecube_setup_arch; - ppc_md.show_cpuinfo = icecube_show_cpuinfo; + ppc_md.setup_arch = lite5200_setup_arch; + ppc_md.show_cpuinfo = lite5200_show_cpuinfo; ppc_md.show_percpuinfo = NULL; ppc_md.init_IRQ = mpc52xx_init_irq; ppc_md.get_irq = mpc52xx_get_irq; @@ -138,12 +173,12 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.restart = mpc52xx_restart; ppc_md.power_off = mpc52xx_power_off; ppc_md.halt = mpc52xx_halt; - - /* No time keeper on the IceCube */ + + /* No time keeper on the LITE5200 */ ppc_md.time_init = NULL; ppc_md.get_rtc_time = NULL; ppc_md.set_rtc_time = NULL; - + ppc_md.calibrate_decr = mpc52xx_calibrate_decr; #ifdef CONFIG_SERIAL_TEXT_DEBUG ppc_md.progress = mpc52xx_progress; diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c index 0037f5ca4..f0c203085 100644 --- a/arch/ppc/platforms/lopec.c +++ b/arch/ppc/platforms/lopec.c @@ -189,7 +189,7 @@ static unsigned long lopec_idedma_regbase; static void lopec_ide_probe(void) { - struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); lopec_ide_ports_known = 1; @@ -200,6 +200,7 @@ lopec_ide_probe(void) lopec_ide_ctl_regbase[0] = dev->resource[1].start; lopec_ide_ctl_regbase[1] = dev->resource[3].start; lopec_idedma_regbase = dev->resource[4].start; + pci_dev_put(dev); } } diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c index 06ed9384f..83dcc8fae 100644 --- a/arch/ppc/platforms/mcpn765.c +++ b/arch/ppc/platforms/mcpn765.c @@ -58,8 +58,6 @@ #include #include "mcpn765.h" -#include "mcpn765_serial.h" - static u_char mcpn765_openpic_initsenses[] __initdata = { (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */ @@ -187,7 +185,7 @@ mcpn765_setup_via_82c586b(void) struct pci_dev *dev; u_char c; - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, NULL)) == NULL) { printk("No VIA ISA bridge found\n"); @@ -211,8 +209,8 @@ mcpn765_setup_via_82c586b(void) pci_write_config_dword(dev, 0x54, 0); pci_write_config_byte(dev, 0x58, 0); - - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + pci_dev_put(dev); + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, NULL)) == NULL) { printk("No VIA ISA bridge found\n"); @@ -227,6 +225,7 @@ mcpn765_setup_via_82c586b(void) pci_read_config_byte(dev, 0x40, &c); c |= 0x03; pci_write_config_byte(dev, 0x40, c); + pci_dev_put(dev); return; } @@ -324,10 +323,6 @@ mcpn765_setup_arch(void) ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - if ( ppc_md.progress ) ppc_md.progress("mcpn765_setup_arch: find_bridges", 0); diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h index 872338317..4d35ecad0 100644 --- a/arch/ppc/platforms/mcpn765.h +++ b/arch/ppc/platforms/mcpn765.h @@ -6,7 +6,7 @@ * Author: Mark A. Greer * mgreer@mvista.com * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -25,6 +25,7 @@ #ifndef __PPC_PLATFORMS_MCPN765_H #define __PPC_PLATFORMS_MCPN765_H +#include /* PCI Memory space mapping info */ #define MCPN765_PCI_MEM_SIZE 0x40000000U @@ -65,14 +66,57 @@ #define MCPN765_BOARD_EXT_FEATURE_REG 0xfef880f0U #define MCPN765_BOARD_LAST_RESET_REG 0xfef880f8U -/* UART base addresses are defined in */ +/* Defines for UART */ + +/* Define the UART base addresses */ +#define MCPN765_SERIAL_1 0xfef88000 +#define MCPN765_SERIAL_2 0xfef88200 +#define MCPN765_SERIAL_3 0xfef88400 +#define MCPN765_SERIAL_4 0xfef88600 + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 4 +#endif + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD ( 1843200 / 16 ) +#define UART_CLK 1843200 + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +/* All UART IRQ's are wire-OR'd to IRQ 17 */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\ + iomem_base: (u8 *)MCPN765_SERIAL_1, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\ + iomem_base: (u8 *)MCPN765_SERIAL_2, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\ + iomem_base: (u8 *)MCPN765_SERIAL_3, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\ + iomem_base: (u8 *)MCPN765_SERIAL_4, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS /* Define the NVRAM/RTC address strobe & data registers */ #define MCPN765_PHYS_NVRAM_AS0 0xfef880c8U #define MCPN765_PHYS_NVRAM_AS1 0xfef880d0U #define MCPN765_PHYS_NVRAM_DATA 0xfef880d8U - extern void mcpn765_find_bridges(void); #endif /* __PPC_PLATFORMS_MCPN765_H */ diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c index 30b6936c3..dce7225ad 100644 --- a/arch/ppc/platforms/mpc5200.c +++ b/arch/ppc/platforms/mpc5200.c @@ -16,6 +16,12 @@ #include #include + +struct ocp_fs_i2c_data mpc5200_i2c_def = { + .flags = FS_I2C_CLOCK_5200, +}; + + /* Here is the core_ocp struct. * With all the devices common to all board. Even if port multiplexing is * not setup for them (if the user don't want them, just don't select the @@ -23,6 +29,24 @@ * board specific file. */ struct ocp_def core_ocp[] = { + { + .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = MPC52xx_I2C1, + .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */ + .pm = OCP_CPM_NA, + .additions = &mpc5200_i2c_def, + }, + { + .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = MPC52xx_I2C2, + .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */ + .pm = OCP_CPM_NA, + .additions = &mpc5200_i2c_def, + }, { /* Terminating entry */ .vendor = OCP_VENDOR_INVALID } diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c index b08be2458..0ecea917d 100644 --- a/arch/ppc/platforms/mvme5100.c +++ b/arch/ppc/platforms/mvme5100.c @@ -228,7 +228,7 @@ mvme5100_init_IRQ(void) for (i = 0; i < NUM_8259_INTERRUPTS; i++) irq_desc[i].handler = &i8259_pic; - i8259_init(NULL); + i8259_init(0); #else openpic_init(0); #endif diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h index 5cc61d18b..edd479439 100644 --- a/arch/ppc/platforms/mvme5100.h +++ b/arch/ppc/platforms/mvme5100.h @@ -63,10 +63,29 @@ #define MVME5100_SERIAL_IRQ 1 #endif -#define MVME5100_WINBOND_DEVFN 0x58 -#define MVME5100_WINBOND_VIDDID 0x056510ad +#define RS_TABLE_SIZE 4 -extern void mvme5100_setup_bridge(void); +#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 ) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +/* All UART IRQ's are wire-OR'd to one MPIC IRQ */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MVME5100_SERIAL_1, \ + MVME5100_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (unsigned char *)MVME5100_SERIAL_1, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME5100_SERIAL_2, \ + MVME5100_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS1 */ \ + iomem_base: (unsigned char *)MVME5100_SERIAL_2, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS #endif /* __ASM_MVME5100_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c index 9c428720d..af8b51d87 100644 --- a/arch/ppc/platforms/pcore.c +++ b/arch/ppc/platforms/pcore.c @@ -89,7 +89,7 @@ pcore_pcibios_fixup(void) { struct pci_dev *dev; - if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, 0))) { @@ -108,6 +108,7 @@ pcore_pcibios_fixup(void) */ outb(0x00, PCORE_WINBOND_PRI_EDG_LVL); outb(0x1e, PCORE_WINBOND_SEC_EDG_LVL); + pci_dev_put(dev); } } @@ -228,10 +229,6 @@ pcore_setup_arch(void) ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Force PowerCore "); if (board_type == PCORE_TYPE_6750) printk("6750\n"); diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index 5b2221a14..6c0b093c4 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -24,15 +24,17 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include #include +#include +#include /* WARNING !!! This will cause calibrate_delay() to be called, * but this is an __init function ! So you MUST go edit @@ -51,10 +53,6 @@ extern void low_choose_7447a_dfs(int dfs); extern void low_choose_750fx_pll(int pll); extern void low_sleep_handler(void); -extern void openpic_suspend(struct sys_device *sysdev, u32 state); -extern void openpic_resume(struct sys_device *sysdev); -extern void enable_kernel_altivec(void); -extern void enable_kernel_fp(void); /* * Currently, PowerMac cpufreq supports only high & low frequencies @@ -140,11 +138,8 @@ static int __pmac dfs_set_cpu_speed(int low_speed) if (low_speed == 0) { /* ramping up, set voltage first */ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/1000); - } else { - /* ramping down, enable aack delay first */ - pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 1, 0); + /* Make sure we sleep for at least 1ms */ + msleep(1); } /* set frequency */ @@ -153,11 +148,7 @@ static int __pmac dfs_set_cpu_speed(int low_speed) if (low_speed == 1) { /* ramping down, set voltage last */ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/1000); - } else { - /* ramping up, disable aack delay last */ - pmac_call_feature(PMAC_FTR_AACK_DELAY_ENABLE, NULL, 0, 0); + msleep(1); } return 0; @@ -174,8 +165,7 @@ static int __pmac gpios_set_cpu_speed(int low_speed) if (low_speed == 0) { pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); /* Delay is way too big but it's ok, we schedule */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); } /* Set frequency */ @@ -192,8 +182,7 @@ static int __pmac gpios_set_cpu_speed(int low_speed) if (low_speed == 1) { pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); /* Delay is way too big but it's ok, we schedule */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); } #ifdef DEBUG_FREQ @@ -217,7 +206,7 @@ static int __pmac pmu_set_cpu_speed(int low_speed) printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); #endif /* Disable all interrupt sources on openpic */ - openpic_suspend(NULL, 1); + openpic_set_priority(0xf); /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); @@ -284,7 +273,7 @@ static int __pmac pmu_set_cpu_speed(int low_speed) wakeup_decrementer(); /* Restore interrupts */ - openpic_resume(NULL); + openpic_set_priority(0); /* Let interrupts flow again ... */ local_irq_enable(); @@ -301,7 +290,6 @@ static int __pmac pmu_set_cpu_speed(int low_speed) static int __pmac do_set_cpu_speed(int speed_mode) { struct cpufreq_freqs freqs; - int rc; freqs.old = cur_freq; freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; @@ -315,7 +303,7 @@ static int __pmac do_set_cpu_speed(int speed_mode) cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; - return rc; + return 0; } static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy) @@ -498,7 +486,7 @@ static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode) * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) - * - iBook2 500 (PMU based, 400Mhz & 500Mhz) + * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) * - Recent MacRISC3 laptops * - iBook G4s and PowerBook G4s with 7447A CPUs @@ -533,11 +521,8 @@ static int __init pmac_cpufreq_setup(void) machine_is_compatible("PowerBook3,5") || machine_is_compatible("MacRISC3")) { pmac_cpufreq_init_MacRISC3(cpunode); - /* Else check for iBook2 500 */ + /* Else check for iBook2 500/600 */ } else if (machine_is_compatible("PowerBook4,1")) { - /* We only know about 500Mhz model */ - if (cur_freq < 450000 || cur_freq > 550000) - goto out; hi_freq = cur_freq; low_freq = 400000; set_speed_proc = pmu_set_cpu_speed; diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 35714de24..c87d52bf0 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c @@ -117,10 +117,10 @@ static const char* macio_names[] __pmacdata = #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) static struct device_node* uninorth_node __pmacdata; -static u32* uninorth_base __pmacdata; +static u32 __iomem * uninorth_base __pmacdata; static u32 uninorth_rev __pmacdata; static int uninorth_u3 __pmacdata; -static void *u3_ht; +static void __iomem *u3_ht; /* * For each motherboard family, we have a table of functions pointers @@ -517,7 +517,7 @@ dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) /* Save state & config of DBDMA channels */ for (i=0; i<13; i++) { - volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*) + volatile struct dbdma_regs __iomem * chan = (void __iomem *) (macio->base + ((0x8000+i*0x100)>>2)); save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); save[i].cmdptr = in_le32(&chan->cmdptr); @@ -534,7 +534,7 @@ dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) /* Save state & config of DBDMA channels */ for (i=0; i<13; i++) { - volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*) + volatile struct dbdma_regs __iomem * chan = (void __iomem *) (macio->base + ((0x8000+i*0x100)>>2)); out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); while (in_le32(&chan->status) & ACTIVE) @@ -2286,14 +2286,14 @@ found: #ifndef CONFIG_POWER4 /* Fixup Hooper vs. Comet */ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { - u32* mach_id_ptr = (u32*)ioremap(0xf3000034, 4); + u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); if (!mach_id_ptr) return -ENODEV; /* Here, I used to disable the media-bay on comet. It * appears this is wrong, the floppy connector is actually * a kind of media-bay and works with the current driver. */ - if ((*mach_id_ptr) & 0x20000000UL) + if (__raw_readl(mach_id_ptr) & 0x20000000UL) pmac_mb.model_id = PMAC_TYPE_COMET; iounmap(mach_id_ptr); } @@ -2394,7 +2394,7 @@ probe_one_macio(const char* name, const char* compat, int type) { struct device_node* node; int i; - volatile u32* base; + volatile u32 __iomem * base; u32* revp; node = find_devices(name); @@ -2419,7 +2419,7 @@ probe_one_macio(const char* name, const char* compat, int type) printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); return; } - base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size); + base = ioremap(node->addrs[0].address, node->addrs[0].size); if (!base) { printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); return; @@ -2665,7 +2665,7 @@ set_initial_features(void) struct device_node *p = of_get_parent(ui2c); if (p && !strcmp(p->name, "uni-n")) break; - ui2c = of_find_node_by_type(np, "i2c"); + ui2c = of_find_node_by_type(ui2c, "i2c"); } if (ui2c == NULL) break; diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c index 9dcc4e2e5..0b673612b 100644 --- a/arch/ppc/platforms/pmac_pci.c +++ b/arch/ppc/platforms/pmac_pci.c @@ -50,6 +50,7 @@ static struct pci_controller *u3_agp; #endif /* CONFIG_POWER4 */ extern u8 pci_cache_line_size; +extern int pcibios_assign_bus_offset; struct pci_dev *k2_skiplist[2]; @@ -315,6 +316,10 @@ u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, unsigned int addr; int i; + struct device_node *np = pci_busdev_to_OF_node(bus, devfn); + if (np == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + /* * When a device in K2 is powered down, we die on config * cycle accesses. Fix that here. @@ -362,6 +367,9 @@ u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, unsigned int addr; int i; + struct device_node *np = pci_busdev_to_OF_node(bus, devfn); + if (np == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; /* * When a device in K2 is powered down, we die on config * cycle accesses. Fix that here. @@ -565,6 +573,14 @@ pmac_find_bridges(void) init_p2pbridge(); fixup_nec_usb2(); + + /* We are still having some issues with the Xserve G4, enabling + * some offset between bus number and domains for now when we + * assign all busses should help for now + */ + if (pci_assign_all_busses) + pcibios_assign_bus_offset = 0x10; + #ifdef CONFIG_POWER4 /* There is something wrong with DMA on U3/HT. I haven't figured out * the details yet, but if I set the cache line size to 128 bytes like @@ -707,7 +723,7 @@ setup_u3_ht(struct pci_controller* hose, struct reg_property *addr) * properties or figuring out the U3 address space decoding logic and * then read its configuration register (if any). */ - hose->io_base_phys = 0xf4000000 + 0x00400000; + hose->io_base_phys = 0xf4000000; hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); isa_io_base = (unsigned long) hose->io_base_virt; hose->io_resource.name = np->full_name; @@ -873,7 +889,7 @@ pcibios_fixup_OF_interrupts(void) * should find the device node and apply the interrupt * obtained from the OF device-tree */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { struct device_node *node; node = pci_device_to_OF_node(dev); /* this is the node, see if it has interrupts */ @@ -973,7 +989,7 @@ pmac_pcibios_after_init(void) * * -- BenH */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) pci_enable_device(dev); } @@ -1034,6 +1050,8 @@ void pmac_pci_fixup_cardbus(struct pci_dev* dev) } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus); + void pmac_pci_fixup_pciata(struct pci_dev* dev) { u8 progif = 0; @@ -1074,6 +1092,8 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev) printk(KERN_ERR "Rewrite of PROGIF failed !\n"); } } +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); + /* * Disable second function on K2-SATA, it's broken @@ -1104,3 +1124,4 @@ void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata); diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c index bebba8793..8441a4a6a 100644 --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c @@ -214,7 +214,7 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) if (bits == 0) continue; irq += __ilog2(bits); - ppc_irq_dispatch_handler(regs, irq); + __do_IRQ(irq, regs); return IRQ_HANDLED; } printk("gatwick irq not from gatwick pic\n"); @@ -383,11 +383,34 @@ static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs) irq = openpic2_get_irq(regs); if (irq != -1) - ppc_irq_dispatch_handler(regs, irq); + __do_IRQ(irq, regs); return IRQ_HANDLED; } + +static struct irqaction k2u3_cascade_action = { + .handler = k2u3_action, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "U3->K2 Cascade", +}; #endif /* CONFIG_POWER4 */ +#ifdef CONFIG_XMON +static struct irqaction xmon_action = { + .handler = xmon_irq, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "NMI - XMON" +}; +#endif + +static struct irqaction gatwick_cascade_action = { + .handler = gatwick_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + void __init pmac_pic_init(void) { int i; @@ -440,8 +463,9 @@ void __init pmac_pic_init(void) OpenPIC_InitSenses = senses; OpenPIC_NumInitSenses = 128; openpic2_init(PMAC_OPENPIC2_OFFSET); - if (request_irq(irqctrler2->intrs[0].line, k2u3_action, 0, - "U3->K2 Cascade", NULL)) + + if (setup_irq(irqctrler2->intrs[0].line, + &k2u3_cascade_action)) printk("Unable to get OpenPIC IRQ for cascade\n"); } #endif /* CONFIG_POWER4 */ @@ -455,8 +479,7 @@ void __init pmac_pic_init(void) if (pswitch && pswitch->n_intrs) { nmi_irq = pswitch->intrs[0].line; openpic_init_nmi_irq(nmi_irq); - request_irq(nmi_irq, xmon_irq, 0, - "NMI - XMON", NULL); + setup_irq(nmi_irq, &xmon_action); } } #endif /* CONFIG_XMON */ @@ -553,8 +576,7 @@ void __init pmac_pic_init(void) (int)irq_cascade); for ( i = max_real_irqs ; i < max_irqs ; i++ ) irq_desc[i].handler = &gatwick_pic; - request_irq( irq_cascade, gatwick_action, SA_INTERRUPT, - "cascade", NULL ); + setup_irq(irq_cascade, &gatwick_cascade_action); } printk("System has %d possible interrupts\n", max_irqs); if (max_irqs != max_real_irqs) @@ -562,7 +584,7 @@ void __init pmac_pic_init(void) max_real_irqs); #ifdef CONFIG_XMON - request_irq(20, xmon_irq, 0, "NMI - XMON", NULL); + setup_irq(20, &xmon_action); #endif /* CONFIG_XMON */ } diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index b05cee1f7..513952331 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -51,13 +51,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -318,9 +318,6 @@ pmac_setup_arch(void) #ifdef CONFIG_NVRAM pmac_nvram_init(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c index 704742257..d6624b018 100644 --- a/arch/ppc/platforms/pmac_smp.c +++ b/arch/ppc/platforms/pmac_smp.c @@ -32,13 +32,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -405,6 +405,13 @@ static void __init psurge_dual_sync_tb(int cpu_nr) smp_tb_synchronized = 1; } +static struct irqaction psurge_irqaction = { + .handler = psurge_primary_intr, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "primary IPI", +}; + static void __init smp_psurge_setup_cpu(int cpu_nr) { @@ -421,7 +428,7 @@ static void __init smp_psurge_setup_cpu(int cpu_nr) /* reset the entry point so if we get another intr we won't * try to startup again */ out_be32(psurge_start, 0x100); - if (request_irq(30, psurge_primary_intr, SA_INTERRUPT, "primary IPI", NULL)) + if (setup_irq(30, &psurge_irqaction)) printk(KERN_ERR "Couldn't get primary IPI interrupt"); } diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c index cd8e3e7c4..09636546f 100644 --- a/arch/ppc/platforms/pmac_time.c +++ b/arch/ppc/platforms/pmac_time.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h index b834e1786..41a6dc881 100644 --- a/arch/ppc/platforms/powerpmc250.h +++ b/arch/ppc/platforms/powerpmc250.h @@ -7,7 +7,7 @@ * * Borrowed heavily from prpmc750.h by Matt Porter * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -16,8 +16,6 @@ #ifndef __ASMPPC_POWERPMC250_H #define __ASMPPC_POWERPMC250_H -#include - #define POWERPMC250_PCI_CONFIG_ADDR 0x80000cf8 #define POWERPMC250_PCI_CONFIG_DATA 0x80000cfc @@ -37,4 +35,18 @@ #define POWERPMC250_SERIAL 0xff000000 #define POWERPMC250_SERIAL_IRQ 20 +/* UART Defines. */ +#define RS_TABLE_SIZE 1 + +#define BASE_BAUD (POWERPMC250_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +#define SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (u8 *)POWERPMC250_SERIAL, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM } + #endif /* __ASMPPC_POWERPMC250_H */ diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c index 673641ff4..1688f3695 100644 --- a/arch/ppc/platforms/pplus.c +++ b/arch/ppc/platforms/pplus.c @@ -359,7 +359,7 @@ void __init pplus_pib_init(void) * Perform specific configuration for the Via Tech or * or Winbond PCI-ISA-Bridge part. */ - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, dev))) { /* * PPCBUG does not set the enable bits @@ -371,7 +371,7 @@ void __init pplus_pib_init(void) pci_write_config_byte(dev, 0x40, reg); } - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev)) && (dev->devfn = 0x5a)) { /* Force correct USB interrupt */ @@ -379,7 +379,7 @@ void __init pplus_pib_init(void) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } - if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, dev))) { /* Clear PCI Interrupt Routing Control Register. */ short_reg = 0x0000; @@ -389,7 +389,7 @@ void __init pplus_pib_init(void) pci_write_config_byte(dev, 0x43, reg); } - if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))) { /* * Disable LEGIRQ mode so PCI INTS are routed @@ -401,6 +401,7 @@ void __init pplus_pib_init(void) dev->irq = 14; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } + pci_dev_put(dev); } void __init pplus_set_VIA_IDE_legacy(void) @@ -583,8 +584,6 @@ static void __init pplus_setup_arch(void) vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE, 0x08000000); conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; #endif #ifdef CONFIG_PPCBUG_NVRAM /* Read in NVRAM data */ diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h index 1bee6ca56..0c17a0cda 100644 --- a/arch/ppc/platforms/pq2ads.h +++ b/arch/ppc/platforms/pq2ads.h @@ -23,6 +23,10 @@ #define BOOTROM_RESTART_ADDR ((uint)0xff000104) +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Motorola" +#define CPUINFO_MACHINE "PQ2 ADS PowerPC" + /* The ADS8260 has 16, 32-bit wide control/status registers, accessed * only on word boundaries. * Not all are used (yet), or are interesting to us (yet). diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c index 58775fc7f..5dce24212 100644 --- a/arch/ppc/platforms/prep_pci.c +++ b/arch/ppc/platforms/prep_pci.c @@ -49,10 +49,10 @@ static char Utah_pci_IRQ_map[23] __prepdata = 0, /* Slot 1 - unused */ 5, /* Slot 2 - SCSI - NCR825A */ 0, /* Slot 3 - unused */ - 1, /* Slot 4 - Ethernet - DEC2114x */ + 3, /* Slot 4 - Ethernet - DEC2114x */ 0, /* Slot 5 - unused */ - 3, /* Slot 6 - PCI Card slot #1 */ - 4, /* Slot 7 - PCI Card slot #2 */ + 2, /* Slot 6 - PCI Card slot #1 */ + 3, /* Slot 7 - PCI Card slot #2 */ 5, /* Slot 8 - PCI Card slot #3 */ 5, /* Slot 9 - PCI Bridge */ /* added here in case we ever support PCI bridges */ @@ -836,52 +836,59 @@ struct mot_info { void __init ibm_prep_init(void) { -#ifdef CONFIG_PREP_RESIDUAL - u32 addr, real_addr, len; - PPC_DEVICE *mpic; - PnP_TAG_PACKET *pkt; - - /* Use the PReP residual data to determine if an OpenPIC is - * present. If so, get the large vendor packet which will - * tell us the base address and length in memory. - * If we are successful, ioremap the memory area and set - * OpenPIC_Addr (this indicates that the OpenPIC was found). - */ - mpic = residual_find_device(-1, NULL, SystemPeripheral, - ProgrammableInterruptController, MPIC, 0); - if (!mpic) - return; + if (have_residual_data) { + u32 addr, real_addr, len, offset; + PPC_DEVICE *mpic; + PnP_TAG_PACKET *pkt; + + /* Use the PReP residual data to determine if an OpenPIC is + * present. If so, get the large vendor packet which will + * tell us the base address and length in memory. + * If we are successful, ioremap the memory area and set + * OpenPIC_Addr (this indicates that the OpenPIC was found). + */ + mpic = residual_find_device(-1, NULL, SystemPeripheral, + ProgrammableInterruptController, MPIC, 0); + if (!mpic) + return; - pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + - mpic->AllocatedOffset, 9, 0); + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + mpic->AllocatedOffset, 9, 0); - if (!pkt) - return; + if (!pkt) + return; #define p pkt->L4_Pack.L4_Data.L4_PPCPack - if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32))) - return; /* not a 32-bit memory address */ + if (p.PPCData[1] == 32) { + switch (p.PPCData[0]) { + case 1: offset = PREP_ISA_IO_BASE; break; + case 2: offset = PREP_ISA_MEM_BASE; break; + default: return; /* Not I/O or memory?? */ + } + } + else + return; /* Not a 32-bit address */ - real_addr = ld_le32((unsigned int *) (p.PPCData + 4)); - if (real_addr == 0xffffffff) - return; + real_addr = ld_le32((unsigned int *) (p.PPCData + 4)); + if (real_addr == 0xffffffff) + return; - /* Adjust address to be as seen by CPU */ - addr = real_addr + PREP_ISA_MEM_BASE; + /* Adjust address to be as seen by CPU */ + addr = real_addr + offset; - len = ld_le32((unsigned int *) (p.PPCData + 12)); - if (!len) - return; + len = ld_le32((unsigned int *) (p.PPCData + 12)); + if (!len) + return; #undef p - OpenPIC_Addr = ioremap(addr, len); - ppc_md.get_irq = openpic_get_irq; + OpenPIC_Addr = ioremap(addr, len); + ppc_md.get_irq = openpic_get_irq; - OpenPIC_InitSenses = prep_openpic_initsenses; - OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); + OpenPIC_InitSenses = prep_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); - printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x " - "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr); -#endif + printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x " + "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr); + } } static void __init @@ -900,6 +907,17 @@ ibm43p_pci_map_non0(struct pci_dev *dev) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } +void __init +prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) +{ + if (have_residual_data) { + Motherboard_map_name = res->VitalProductData.PrintableModel; + Motherboard_map = NULL; + Motherboard_routes = NULL; + residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi); + } +} + void __init prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) { @@ -1011,21 +1029,31 @@ prep_route_pci_interrupts(void) } } else if ( _prep_type == _PREP_IBM ) { unsigned char irq_edge_mask_lo, irq_edge_mask_hi; + unsigned short irq_edge_mask; + int i; setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi); outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */ outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */ + + irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo; + for (i = 0; i < 16; ++i, irq_edge_mask >>= 1) + if (irq_edge_mask & 1) + irq_desc[i].status |= IRQ_LEVEL; } else { printk("No known machine pci routing!\n"); return; } /* Set up mapping from slots */ - for (i = 1; i <= 4; i++) - ibc_pirq[i-1] = Motherboard_routes[i]; - /* Enable PCI interrupts */ - *ibc_pcicon |= 0x20; + if (Motherboard_routes) { + for (i = 1; i <= 4; i++) + ibc_pirq[i-1] = Motherboard_routes[i]; + + /* Enable PCI interrupts */ + *ibc_pcicon |= 0x20; + } } void __init @@ -1041,7 +1069,7 @@ prep_pib_init(void) * Perform specific configuration for the Via Tech or * or Winbond PCI-ISA-Bridge part. */ - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, dev))) { /* * PPCBUG does not set the enable bits @@ -1052,7 +1080,7 @@ prep_pib_init(void) reg |= 0x03; /* IDE: Chip Enable Bits */ pci_write_config_byte(dev, 0x40, reg); } - if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev)) && (dev->devfn = 0x5a)) { /* Force correct USB interrupt */ @@ -1061,7 +1089,7 @@ prep_pib_init(void) PCI_INTERRUPT_LINE, dev->irq); } - if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, dev))) { /* Clear PCI Interrupt Routing Control Register. */ short_reg = 0x0000; @@ -1072,9 +1100,10 @@ prep_pib_init(void) pci_write_config_byte(dev, 0x43, reg); } } + pci_dev_put(dev); } - if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))){ if (OpenPIC_Addr){ /* @@ -1093,6 +1122,7 @@ prep_pib_init(void) pci_write_config_dword(dev, 0x40, 0x10ff08a1); } } + pci_dev_put(dev); } static void __init @@ -1171,38 +1201,52 @@ void __init prep_pcibios_fixup(void) { struct pci_dev *dev = NULL; + int irq; + int have_openpic = (OpenPIC_Addr != NULL); prep_route_pci_interrupts(); printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); - if (OpenPIC_Addr) { - /* PCI interrupts are controlled by the OpenPIC */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number == 0) { - dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } else { - if (Motherboard_non0 != NULL) - Motherboard_non0(dev); - } + + /* Iterate through all the PCI devices, setting the IRQ */ + for_each_pci_dev(dev) { + /* + * If we have residual data, then this is easy: query the + * residual data for the IRQ line allocated to the device. + * This works the same whether we have an OpenPic or not. + */ + if (have_residual_data) { + irq = residual_pcidev_irq(dev); + dev->irq = have_openpic ? openpic_to_irq(irq) : irq; + } + /* + * If we don't have residual data, then we need to use + * tables to determine the IRQ. The table organisation + * is different depending on whether there is an OpenPIC + * or not. The tables are only used for bus 0, so check + * this first. + */ + else if (dev->bus->number == 0) { + irq = Motherboard_map[PCI_SLOT(dev->devfn)]; + dev->irq = have_openpic ? openpic_to_irq(irq) + : Motherboard_routes[irq]; } + /* + * Finally, if we don't have residual data and the bus is + * non-zero, use the callback (if provided) + */ + else { + if (Motherboard_non0 != NULL) + Motherboard_non0(dev); - /* Setup the Winbond or Via PIB */ - prep_pib_init(); + continue; + } - return; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - /* - * Use our old hard-coded kludge to figure out what - * irq this device uses. This is necessary on things - * without residual data. -- Cort - */ - unsigned char d = PCI_SLOT(dev->devfn); - dev->irq = Motherboard_routes[Motherboard_map[d]]; - } + /* Setup the Winbond or Via PIB */ + prep_pib_init(); } static void __init @@ -1218,12 +1262,13 @@ prep_pcibios_after_init(void) * instead of 0xc0000. vgacon.c (for example) is completely unaware of * this little quirk. */ - dev = pci_find_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL); + dev = pci_get_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL); if (dev) { dev->resource[1].end -= dev->resource[1].start; dev->resource[1].start = 0; /* tell the hardware */ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0); + pci_dev_put(dev); } #endif } @@ -1262,14 +1307,15 @@ prep_find_bridges(void) PREP_ISA_IO_BASE + 0xcfc); printk("PReP architecture\n"); -#ifdef CONFIG_PREP_RESIDUAL - { + + if (have_residual_data) { PPC_DEVICE *hostbridge; hostbridge = residual_find_device(PROCESSORDEVICE, NULL, BridgeController, PCIBridge, -1, 0); if (hostbridge && - hostbridge->DeviceId.Interface == PCIBridgeIndirect) { + ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) || + (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) { PnP_TAG_PACKET * pkt; pkt = PnP_find_large_vendor_packet( res->DevicePnPHeap+hostbridge->AllocatedOffset, @@ -1284,7 +1330,6 @@ prep_find_bridges(void) setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); } } -#endif /* CONFIG_PREP_RESIDUAL */ ppc_md.pcibios_fixup = prep_pcibios_fixup; ppc_md.pcibios_after_init = prep_pcibios_after_init; diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 99acd5170..8051df176 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c @@ -79,6 +79,7 @@ extern void prep_find_bridges(void); int _prep_type; +extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); @@ -193,9 +194,8 @@ prep_ibm_cpuinfo(struct seq_file *m) seq_printf(m, "bad"); seq_printf(m, "\n"); -#ifdef CONFIG_PREP_RESIDUAL /* print info about SIMMs */ - if (res->ResidualLength != 0) { + if (have_residual_data) { int i; seq_printf(m, "simms\t\t: "); for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { @@ -207,7 +207,13 @@ prep_ibm_cpuinfo(struct seq_file *m) } seq_printf(m, "\n"); } -#endif +} + +static int __prep +prep_gen_cpuinfo(struct seq_file *m) +{ + prep_ibm_cpuinfo(m); + return 0; } static int __prep @@ -431,9 +437,8 @@ prep_mot_cpuinfo(struct seq_file *m) } no_l2: -#ifdef CONFIG_PREP_RESIDUAL /* print info about SIMMs */ - if (res->ResidualLength != 0) { + if (have_residual_data) { int i; seq_printf(m, "simms\t\t: "); for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { @@ -445,17 +450,10 @@ no_l2: } seq_printf(m, "\n"); } -#endif return 0; } -static void __prep -prep_tiger1_progress(char *msg, unsigned short code) -{ - outw(code, PREP_IBM_DISP); -} - static void __prep prep_restart(char *cmd) { @@ -561,14 +559,12 @@ prep_show_percpuinfo(struct seq_file *m, int i) { /* PREP's without residual data will give incorrect values here */ seq_printf(m, "clock\t\t: "); -#ifdef CONFIG_PREP_RESIDUAL - if (res->ResidualLength) + if (have_residual_data) seq_printf(m, "%ldMHz\n", (res->VitalProductData.ProcessorHz > 1024) ? res->VitalProductData.ProcessorHz / 1000000 : res->VitalProductData.ProcessorHz); else -#endif /* CONFIG_PREP_RESIDUAL */ seq_printf(m, "???\n"); return 0; @@ -598,9 +594,10 @@ static void __init prep_init_sound(void) * Get the needed resource informations from residual data. * */ -#ifdef CONFIG_PREP_RESIDUAL - audiodevice = residual_find_device(~0, NULL, MultimediaController, - AudioController, -1, 0); + if (have_residual_data) + audiodevice = residual_find_device(~0, NULL, + MultimediaController, AudioController, -1, 0); + if (audiodevice != NULL) { PnP_TAG_PACKET *pkt; @@ -613,7 +610,6 @@ static void __init prep_init_sound(void) if (pkt != NULL) ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask); } -#endif /* * These are the PReP specs' defaults for the cs4231. We use these @@ -649,13 +645,14 @@ static void __init prep_init_sound(void) static void __init prep_init_vesa(void) { -#if defined(CONFIG_PREP_RESIDUAL) && \ - (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \ +#if (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \ defined(CONFIG_FB_VESA)) - PPC_DEVICE *vgadev; + PPC_DEVICE *vgadev = NULL; + + if (have_residual_data) + vgadev = residual_find_device(~0, NULL, DisplayController, + SVGAController, -1, 0); - vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController, - -1, 0); if (vgadev != NULL) { PnP_TAG_PACKET *pkt; @@ -680,7 +677,112 @@ prep_init_vesa(void) } } } -#endif /* CONFIG_PREP_RESIDUAL */ +#endif +} + +/* + * Set DBAT 2 to access 0x80000000 so early progress messages will work + */ +static __inline__ void +prep_set_bat(void) +{ + /* wait for all outstanding memory access to complete */ + mb(); + + /* setup DBATs */ + mtspr(DBAT2U, 0x80001ffe); + mtspr(DBAT2L, 0x8000002a); + + /* wait for updates */ + mb(); +} + +/* + * IBM 3-digit status LED + */ +static unsigned int ibm_statusled_base __prepdata; + +static void __prep +ibm_statusled_progress(char *s, unsigned short hex); + +static int __prep +ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2, + void * dummy3) +{ + ibm_statusled_progress(NULL, 0x505); /* SOS */ + return NOTIFY_DONE; +} + +static struct notifier_block ibm_statusled_block __prepdata = { + ibm_statusled_panic, + NULL, + INT_MAX /* try to do it first */ +}; + +static void __prep +ibm_statusled_progress(char *s, unsigned short hex) +{ + static int notifier_installed; + /* + * Progress uses 4 digits and we have only 3. So, we map 0xffff to + * 0xfff for display switch off. Out of range values are mapped to + * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes. + * Install the panic notifier when the display is first switched off. + */ + if (hex == 0xffff) { + hex = 0xfff; + if (!notifier_installed) { + ++notifier_installed; + notifier_chain_register(&panic_notifier_list, + &ibm_statusled_block); + } + } + else + if (hex > 0xfff) + hex = 0xeff; + + mb(); + outw(hex, ibm_statusled_base); +} + +static void __init +ibm_statusled_init(void) +{ + /* + * The IBM 3-digit LED display is specified in the residual data + * as an operator panel device, type "System Status LED". Find + * that device and determine its address. We validate all the + * other parameters on the off-chance another, similar device + * exists. + */ + if (have_residual_data) { + PPC_DEVICE *led; + PnP_TAG_PACKET *pkt; + + led = residual_find_device(~0, NULL, SystemPeripheral, + OperatorPanel, SystemStatusLED, 0); + if (!led) + return; + + pkt = PnP_find_packet((unsigned char *) + &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0); + if (!pkt) + return; + + if (pkt->S8_Pack.IOInfo != ISAAddr16bit) + return; + if (*(unsigned short *)pkt->S8_Pack.RangeMin != + *(unsigned short *)pkt->S8_Pack.RangeMax) + return; + if (pkt->S8_Pack.IOAlign != 2) + return; + if (pkt->S8_Pack.IONum != 2) + return; + + ibm_statusled_base = ld_le16((unsigned short *) + (pkt->S8_Pack.RangeMin)); + ppc_md.progress = ibm_statusled_progress; + } } static void __init @@ -706,7 +808,7 @@ prep_setup_arch(void) { case _PREP_IBM: reg = inb(PREP_IBM_PLANAR); - printk(KERN_INFO "IBM planar ID: %08x", reg); + printk(KERN_INFO "IBM planar ID: %02x", reg); switch (reg) { case PREP_IBM_SANDALFOOT: prep_gen_enable_l2(); @@ -721,7 +823,16 @@ prep_setup_arch(void) ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo; break; default: - printk(" -- unknown! Assuming Carolina"); + if (have_residual_data) { + prep_gen_enable_l2(); + setup_ibm_pci = prep_residual_setup_pci; + ppc_md.power_off = prep_halt; + ppc_md.show_cpuinfo = prep_gen_cpuinfo; + break; + } + else + printk(" - unknown! Assuming Carolina"); + /* fall through */ case PREP_IBM_CAROLINA_IDE_0: case PREP_IBM_CAROLINA_IDE_1: case PREP_IBM_CAROLINA_IDE_2: @@ -745,7 +856,6 @@ prep_setup_arch(void) setup_ibm_pci = prep_tiger1_setup_pci; ppc_md.power_off = prep_sig750_poweroff; ppc_md.show_cpuinfo = prep_tiger1_cpuinfo; - ppc_md.progress = prep_tiger1_progress; break; } printk("\n"); @@ -808,8 +918,6 @@ prep_setup_arch(void) /* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */ vgacon_remap_base = 0xf0000000; conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; #endif } @@ -821,18 +929,19 @@ prep_setup_arch(void) static void __init prep_calibrate_decr(void) { -#ifdef CONFIG_PREP_RESIDUAL - unsigned long freq, divisor = 4; - - if ( res->VitalProductData.ProcessorBusHz ) { - freq = res->VitalProductData.ProcessorBusHz; - printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", - (freq/divisor)/1000000, - (freq/divisor)%1000000); - tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); - tb_ticks_per_jiffy = freq / HZ / divisor; - } else -#endif + if (have_residual_data) { + unsigned long freq, divisor = 4; + + if ( res->VitalProductData.ProcessorBusHz ) { + freq = res->VitalProductData.ProcessorBusHz; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + (freq/divisor)/1000000, + (freq/divisor)%1000000); + tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); + tb_ticks_per_jiffy = freq / HZ / divisor; + } + } + else todc_calibrate_decr(); } @@ -863,6 +972,12 @@ prep_init_IRQ(void) } for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; + + if (have_residual_data) { + i8259_init(residual_isapic_addr()); + return; + } + /* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory * controller, we poll (as they have a different int-ack address). */ early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid); @@ -1000,18 +1115,27 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5, DMA_MODE_WRITE = 0x48; /* figure out what kind of prep workstation we are */ -#ifdef CONFIG_PREP_RESIDUAL - if ( res->ResidualLength != 0 ) { + if (have_residual_data) { if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) _prep_type = _PREP_IBM; else _prep_type = _PREP_Motorola; - } else /* assume motorola if no residual (netboot?) */ -#endif - { + } + else { + /* assume motorola if no residual (netboot?) */ _prep_type = _PREP_Motorola; } +#ifdef CONFIG_PREP_PRESIDUAL + /* Switch off all residual data processing if the user requests it */ + if (strstr(cmd_line, "noresidual") != NULL) + res = NULL; +#endif + + /* Initialise progress early to get maximum benefit */ + prep_set_bat(); + ibm_statusled_init(); + ppc_md.setup_arch = prep_setup_arch; ppc_md.show_percpuinfo = prep_show_percpuinfo; ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */ diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c index e0ab8e301..b89d144c8 100644 --- a/arch/ppc/platforms/prpmc750.c +++ b/arch/ppc/platforms/prpmc750.c @@ -109,7 +109,7 @@ static void __init prpmc750_pcibios_fixup(void) * resource subsystem doesn't fixup the * PCI mem resources on the CL5446. */ - if ((dev = pci_find_device(PCI_VENDOR_ID_CIRRUS, + if ((dev = pci_get_device(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0))) { dev->resource[0].start += PRPMC750_PCI_PHY_MEM_OFFSET; dev->resource[0].end += PRPMC750_PCI_PHY_MEM_OFFSET; @@ -121,6 +121,7 @@ static void __init prpmc750_pcibios_fixup(void) outb(0x0f, 0x3c4); /* Set proper DRAM config */ outb(0xdf, 0x3c5); + pci_dev_put(dev); } } @@ -193,10 +194,6 @@ static void __init prpmc750_setup_arch(void) ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - OpenPIC_InitSenses = prpmc750_openpic_initsenses; OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses); diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h index 23ed94140..015b4f52c 100644 --- a/arch/ppc/platforms/prpmc750.h +++ b/arch/ppc/platforms/prpmc750.h @@ -5,20 +5,16 @@ * * Author: Matt Porter * - * Copyright 2001 MontaVista Software 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. + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_PRPMC750_H__ #define __ASM_PRPMC750_H__ -#include - /* * Due to limiations imposed by legacy hardware (primaryily IDE controllers), * the PrPMC750 carrier board operates using a PReP address map. @@ -81,5 +77,19 @@ #define PRPMC750_TBEN_REG 0xfef880c0 #define PRPMC750_TBEN_MASK 0x01 +/* UART Defines. */ +#define RS_TABLE_SIZE 4 + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD (PRPMC750_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +#define SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \ + iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM } /* ttyS0 */ + #endif /* __ASM_PRPMC750_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c index 0ffcfdfb1..0e99f8bc3 100644 --- a/arch/ppc/platforms/prpmc800.c +++ b/arch/ppc/platforms/prpmc800.c @@ -309,10 +309,6 @@ static void __init prpmc800_setup_arch(void) ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Port by MontaVista Software, Inc. " "(source@mvista.com)\n"); } diff --git a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h index 4af2f2c9a..e53ec9b42 100644 --- a/arch/ppc/platforms/prpmc800.h +++ b/arch/ppc/platforms/prpmc800.h @@ -5,12 +5,10 @@ * * Author: Dale Farnsworth * - * Copyright 2001 MontaVista Software 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. + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ /* * From Processor to PCI: @@ -63,4 +61,22 @@ #define PRPMC800_INT_IRQ 16 #define PRPMC800_INT_PRI 15 +/* UART Defines. */ +#define RS_TABLE_SIZE 4 + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD (PRPMC800_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +/* UARTS are at IRQ 16 */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\ + iomem_base: (unsigned char *)PRPMC800_SERIAL_1, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS + #endif /* __ASMPPC_PRPMC800_H */ diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c index b094e2715..0f84ca603 100644 --- a/arch/ppc/platforms/residual.c +++ b/arch/ppc/platforms/residual.c @@ -504,7 +504,7 @@ void __init print_residual_device_info(void) #define did dev->DeviceId /* make sure we have residual data first */ - if ( res->ResidualLength == 0 ) + if (!have_residual_data) return; printk("Residual: %ld devices\n", res->ActualNumDevices); @@ -639,7 +639,7 @@ void print_residual_device_info(void) #define did dev->DeviceId /* make sure we have residual data first */ - if ( res->ResidualLength == 0 ) + if (!have_residual_data) return; printk("Residual: %ld devices\n", res->ActualNumDevices); for ( i = 0; @@ -790,7 +790,7 @@ PPC_DEVICE __init *residual_find_device(unsigned long BusMask, int n) { int i; - if ( !res->ResidualLength ) return NULL; + if (!have_residual_data) return NULL; for (i=0; iActualNumDevices; i++) { #define Dev res->Devices[i].DeviceId if ( (Dev.BusId&BusMask) && @@ -813,7 +813,7 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask, int n) { int i; - if ( !res->ResidualLength ) return NULL; + if (!have_residual_data) return NULL; for (i=0; iActualNumDevices; i++) { #define Dev res->Devices[i].DeviceId if ( (Dev.BusId&BusMask) && @@ -827,6 +827,129 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask, return NULL; } +static int __init +residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev) +{ + int irq = -1; + +#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData + if (dev->bus->number == data[16]) { + int i, size; + + size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0)); + for (i = 20; i < size - 4; i += 12) { + unsigned char pin; + int line_irq; + + if (dev->devfn != data[i + 1]) + continue; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + line_irq = ld_le16((unsigned short *) + (&data[i + 4 + 2 * (pin - 1)])); + irq = (line_irq == 0xffff) ? 0 + : line_irq & 0x7fff; + } else + irq = 0; + + break; + } + } +#undef data + + return irq; +} + +int __init +residual_pcidev_irq(struct pci_dev *dev) +{ + int i = 0; + int irq = -1; + PPC_DEVICE *bridge; + + while ((bridge = residual_find_device + (-1, NULL, BridgeController, PCIBridge, -1, i++))) { + + PnP_TAG_PACKET *pkt; + if (bridge->AllocatedOffset) { + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + bridge->AllocatedOffset, 3, 0); + if (!pkt) + continue; + + irq = residual_scan_pcibridge(pkt, dev); + if (irq != -1) + break; + } + } + + return (irq < 0) ? 0 : irq; +} + +void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi) +{ + PPC_DEVICE *dev; + int i = 0; + unsigned short irq_mask = 0x000; /* default to edge */ + + while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) { + PnP_TAG_PACKET *pkt; + unsigned short mask; + int size; + int offset = dev->AllocatedOffset; + + if (!offset) + continue; + + pkt = PnP_find_packet(res->DevicePnPHeap + offset, + IRQFormat, 0); + if (!pkt) + continue; + + size = tag_small_count(pkt->S1_Pack.Tag) + 1; + mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask); + if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c)) + irq_mask |= mask; + } + + *irq_edge_mask_lo = irq_mask & 0xff; + *irq_edge_mask_hi = irq_mask >> 8; +} + +unsigned int __init residual_isapic_addr(void) +{ + PPC_DEVICE *isapic; + PnP_TAG_PACKET *pkt; + unsigned int addr; + + isapic = residual_find_device(~0, NULL, SystemPeripheral, + ProgrammableInterruptController, + ISA_PIC, 0); + if (!isapic) + goto unknown; + + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + isapic->AllocatedOffset, 9, 0); + if (!pkt) + goto unknown; + +#define p pkt->L4_Pack.L4_Data.L4_PPCPack + /* Must be 32-bit system address */ + if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32))) + goto unknown; + + /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */ + if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1) + goto unknown; + + addr = ld_le32((unsigned int *) (p.PPCData + 4)); +#undef p + return addr; +unknown: + return 0; +} + PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag, int n) @@ -901,7 +1024,7 @@ static int proc_prep_residual_read(char * buf, char ** start, off_t off, int __init proc_prep_residual_init(void) { - if (res->ResidualLength) + if (have_residual_data) create_proc_read_entry("residual", S_IRUGO, NULL, proc_prep_residual_read, NULL); return 0; diff --git a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h index 7d5cd8893..843494a50 100644 --- a/arch/ppc/platforms/rpx8260.h +++ b/arch/ppc/platforms/rpx8260.h @@ -70,5 +70,12 @@ extern volatile u_char *rpx6_csr_addr; #define PHY_INTERRUPT SIU_INT_IRQ7 +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Embedded Planet" +#define CPUINFO_MACHINE "EP8260 PowerPC" + +/* Warm reset vector. */ +#define BOOTROM_RESTART_ADDR ((uint)0xfff00104) + #endif /* __ASM_PLATFORMS_RPX8260_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h index d1d81b8b5..6daa10949 100644 --- a/arch/ppc/platforms/rpxclassic.h +++ b/arch/ppc/platforms/rpxclassic.h @@ -82,7 +82,6 @@ extern bd_t m8xx_board_info; /* for pcmcia sandisk */ #ifdef CONFIG_IDE # define MAX_HWIFS 1 -# define request_irq(irq,hand,flg,dev,id) request_8xxirq((irq),(hand),(flg),(dev),(id)) #endif #endif diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h index 69646bf36..deee5bd36 100644 --- a/arch/ppc/platforms/rpxlite.h +++ b/arch/ppc/platforms/rpxlite.h @@ -68,7 +68,6 @@ extern bd_t m8xx_board_info; #ifdef CONFIG_IDE # define MAX_HWIFS 1 -# define request_irq(irq,hand,flg,dev,id) request_8xxirq((irq),(hand),(flg),(dev),(id)) #endif /* CPM Ethernet through SCCx. diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index fdcbcf240..b07f416cc 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c @@ -60,11 +60,6 @@ * of the amount of memory in the system. Once a method of determining * what version of DINK initializes the system for us, if applicable, is * found, we can hopefully stop hardcoding 32MB of RAM. - * - * It is important to note that this code only supports the Sandpoint X3 - * (all flavors) platform, and it does not support the X2 anymore. Code - * that at one time worked on the X2 can be found at: - * ftp://source.mvista.com/pub/linuxppc/obsolete/sandpoint/ */ #include @@ -107,9 +102,13 @@ #include "sandpoint.h" +/* Set non-zero if an X2 Sandpoint detected. */ +static int sandpoint_is_x2; + unsigned char __res[sizeof(bd_t)]; static void sandpoint_halt(void); +static void sandpoint_probe_type(void); /* * Define all of the IRQ senses and polarities. Taken from the @@ -129,7 +128,7 @@ static u_char sandpoint_openpic_initsenses[] __initdata = { * Motorola SPS Sandpoint interrupt routing. */ static inline int -sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { static char pci_irq_table[][4] = /* @@ -149,6 +148,27 @@ sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) return PCI_IRQ_TABLE_LOOKUP; } +static inline int +x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 18, 0, 0, 0 }, /* IDSEL 11 - i8259 on Windbond */ + { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ + { 16, 17, 18, 19 }, /* IDSEL 13 - PCI slot 1 */ + { 17, 18, 19, 16 }, /* IDSEL 14 - PCI slot 2 */ + { 18, 19, 16, 17 }, /* IDSEL 15 - PCI slot 3 */ + { 19, 16, 17, 18 }, /* IDSEL 16 - PCI slot 4 */ + }; + + const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + static void __init sandpoint_setup_winbond_83553(struct pci_controller *hose) { @@ -216,6 +236,18 @@ sandpoint_setup_winbond_83553(struct pci_controller *hose) return; } +/* On the sandpoint X2, we must avoid sending configuration cycles to + * device #12 (IDSEL addr = AD12). + */ +static int +x2_exclude_device(u_char bus, u_char devfn) +{ + if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + static void __init sandpoint_find_bridges(void) { @@ -241,7 +273,11 @@ sandpoint_find_bridges(void) ppc_md.pcibios_fixup = NULL; ppc_md.pcibios_fixup_bus = NULL; ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = sandpoint_map_irq; + if (sandpoint_is_x2) { + ppc_md.pci_map_irq = x2_map_irq; + ppc_md.pci_exclude_device = x2_exclude_device; + } else + ppc_md.pci_map_irq = x3_map_irq; } else { if (ppc_md.progress) @@ -252,41 +288,14 @@ sandpoint_find_bridges(void) return; } -#if defined(CONFIG_SERIAL_8250) && \ - (defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)) -static void __init -sandpoint_early_serial_map(void) -{ - struct uart_port serial_req; - - /* Setup serial port access */ - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.uartclk = UART_CLK; - serial_req.irq = 4; - serial_req.flags = STD_COM_FLAGS; - serial_req.iotype = SERIAL_IO_MEM; - serial_req.membase = (u_char *)SANDPOINT_SERIAL_0; - - gen550_init(0, &serial_req); - - if (early_serial_setup(&serial_req) != 0) - printk(KERN_ERR "Early serial init of port 0 failed\n"); - - /* Assume early_serial_setup() doesn't modify serial_req */ - serial_req.line = 1; - serial_req.irq = 3; /* XXXX */ - serial_req.membase = (u_char *)SANDPOINT_SERIAL_1; - - gen550_init(1, &serial_req); - - if (early_serial_setup(&serial_req) != 0) - printk(KERN_ERR "Early serial init of port 1 failed\n"); -} -#endif - static void __init sandpoint_setup_arch(void) { + /* Probe for Sandpoint model */ + sandpoint_probe_type(); + if (sandpoint_is_x2) + epic_serial_mode = 0; + loops_per_jiffy = 100000000 / HZ; #ifdef CONFIG_BLK_DEV_INITRD @@ -303,10 +312,6 @@ sandpoint_setup_arch(void) /* Lookup PCI host bridges */ sandpoint_find_bridges(); -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); @@ -354,14 +359,49 @@ sandpoint_setup_arch(void) SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \ } +/* + * To probe the Sandpoint type, we need to check for a connection between GPIO + * pins 6 and 7 on the NS87308 SuperIO. + */ +static void __init sandpoint_probe_type(void) +{ + u8 x; + /* First, ensure that the GPIO pins are enabled. */ + SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */ + SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */ + SANDPOINT_87308_CFG_OUTB(0x61, 0x00); + SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */ + + /* Now, set pin 7 to output and pin 6 to input. */ + outb((inb(0x701) | 0x80) & 0xbf, 0x701); + /* Set push-pull output */ + outb(inb(0x702) | 0x80, 0x702); + /* Set pull-up on input */ + outb(inb(0x703) | 0x40, 0x703); + /* Set output high and check */ + x = inb(0x700); + outb(x | 0x80, 0x700); + x = inb(0x700); + sandpoint_is_x2 = ! (x & 0x40); + if (ppc_md.progress && sandpoint_is_x2) + ppc_md.progress("High output says X2", 0); + /* Set output low and check */ + outb(x & 0x7f, 0x700); + sandpoint_is_x2 |= inb(0x700) & 0x40; + if (ppc_md.progress && sandpoint_is_x2) + ppc_md.progress("Low output says X2", 0); + if (ppc_md.progress && ! sandpoint_is_x2) + ppc_md.progress("Sandpoint is X3", 0); +} + /* * Fix IDE interrupts. */ static int __init sandpoint_fix_winbond_83553(void) { - /* Make all 8259 interrupt level sensitive */ - outb(0xf8, 0x4d0); + /* Make some 8259 interrupt level sensitive */ + outb(0xe0, 0x4d0); outb(0xde, 0x4d1); return 0; @@ -434,7 +474,7 @@ sandpoint_init_IRQ(void) OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses); mpc10x_set_openpic(); - openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", + openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade", i8259_irq); /* @@ -535,7 +575,7 @@ static unsigned long sandpoint_idedma_regbase; static void sandpoint_ide_probe(void) { - struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, + struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); if (pdev) { @@ -544,6 +584,7 @@ sandpoint_ide_probe(void) sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start; sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start; sandpoint_idedma_regbase=pdev->resource[4].start; + pci_dev_put(pdev); } sandpoint_ide_ports_known = 1; @@ -693,16 +734,12 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.nvram_read_val = todc_mc146818_read_val; ppc_md.nvram_write_val = todc_mc146818_write_val; -#if defined(CONFIG_SERIAL_8250) && \ - (defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)) - sandpoint_early_serial_map(); #ifdef CONFIG_KGDB ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; #endif #ifdef CONFIG_SERIAL_TEXT_DEBUG ppc_md.progress = gen550_progress; #endif -#endif #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.default_irq = sandpoint_ide_default_irq; diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c index 28a77dba3..102ac19af 100644 --- a/arch/ppc/platforms/sbc82xx.c +++ b/arch/ppc/platforms/sbc82xx.c @@ -16,10 +16,11 @@ */ #include -#include #include #include #include +#include +#include #include #include @@ -28,39 +29,12 @@ #include #include -static void (*callback_setup_arch)(void); static void (*callback_init_IRQ)(void); extern unsigned char __res[sizeof(bd_t)]; -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - extern void (*late_time_init)(void); -static int -sbc82xx_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: Wind River\n" - "machine\t\t: SBC PowerQUICC II\n" - "\n" - "mem size\t\t: 0x%08lx\n" - "console baud\t\t: %ld\n" - "\n", - binfo->bi_memsize, - binfo->bi_baudrate); - return 0; -} - -static void __init -sbc82xx_setup_arch(void) -{ - printk("SBC PowerQUICC II Port\n"); - callback_setup_arch(); -} - #ifdef CONFIG_GEN_RTC TODC_ALLOC(); @@ -168,10 +142,17 @@ static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *re return IRQ_HANDLED; } } - ppc_irq_dispatch_handler(regs, NR_SIU_INTS + irq); + __do_IRQ(NR_SIU_INTS + irq, regs); return IRQ_HANDLED; } +static struct irqaction sbc82xx_i8259_irqaction = { + .handler = sbc82xx_i8259_demux, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "i8259 demux", +}; + void __init sbc82xx_init_IRQ(void) { volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl; @@ -212,8 +193,7 @@ void __init sbc82xx_init_IRQ(void) sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; /* Set interrupt mask */ /* Request cascade IRQ */ - if (request_irq(SIU_INT_IRQ6, sbc82xx_i8259_demux, SA_INTERRUPT, - "i8259 demux", 0)) { + if (setup_irq(SIU_INT_IRQ6, &sbc82xx_i8259_irqaction)) { printk("Installation of i8259 IRQ demultiplexer failed.\n"); } } @@ -236,26 +216,36 @@ static int sbc82xx_pci_map_irq(struct pci_dev *dev, unsigned char idsel, return PCI_IRQ_TABLE_LOOKUP; } +static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev) +{ + uint32_t ctrl; + + if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0)) + return; + + printk(KERN_INFO "Setting up CardBus controller\n"); + + /* Set P2CCLK bit in System Control Register */ + pci_read_config_dword(pdev, 0x80, &ctrl); + ctrl |= (1<<27); + pci_write_config_dword(pdev, 0x80, ctrl); + /* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */ + pci_write_config_dword(pdev, 0x8c, 0x00c01d22); + +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus); void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +m82xx_board_init(void) { - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - /* u-boot may be using one of the FCC Ethernet devices. Use the MAC address to the SCC. */ __res[offsetof(bd_t, bi_enetaddr[5])] &= ~3; /* Anything special for this platform */ - ppc_md.show_cpuinfo = sbc82xx_show_cpuinfo; - - callback_setup_arch = ppc_md.setup_arch; callback_init_IRQ = ppc_md.init_IRQ; - ppc_md.setup_arch = sbc82xx_setup_arch; ppc_md.init_IRQ = sbc82xx_init_IRQ; ppc_md.pci_map_irq = sbc82xx_pci_map_irq; #ifdef CONFIG_GEN_RTC diff --git a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h index adafd49be..e4042d499 100644 --- a/arch/ppc/platforms/sbc82xx.h +++ b/arch/ppc/platforms/sbc82xx.h @@ -18,6 +18,10 @@ #define SBC82xx_MACADDR_NVRAM_FCC2 0x220000d5 /* JP7A */ #define SBC82xx_MACADDR_NVRAM_FCC3 0x220000db /* JP7B */ +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Wind River" +#define CPUINFO_MACHINE "SBC PowerQUICC II" + #define BOOTROM_RESTART_ADDR ((uint)0x40000104) #define SBC82xx_PC_IRQA (NR_SIU_INTS+0) diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c index ad671021e..74be32456 100644 --- a/arch/ppc/platforms/spruce.c +++ b/arch/ppc/platforms/spruce.c @@ -228,11 +228,6 @@ spruce_setup_arch(void) ROOT_DEV = Root_SDA1; #endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - - /* Identify the system */ printk(KERN_INFO "System Identification: IBM Spruce\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); diff --git a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h index 3366cbded..c7a78a646 100644 --- a/arch/ppc/platforms/tqm8260.h +++ b/arch/ppc/platforms/tqm8260.h @@ -14,6 +14,10 @@ #define CPM_MAP_ADDR ((uint)0xFFF00000) #define PHY_INTERRUPT 25 +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "IN2 Systems" +#define CPUINFO_MACHINE "TQM8260 PowerPC" + #define BOOTROM_RESTART_ADDR ((uint)0x40000104) #endif /* __TQM8260_PLATFORM */ diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c index 1241ed5d4..a8880bfc0 100644 --- a/arch/ppc/platforms/tqm8260_setup.c +++ b/arch/ppc/platforms/tqm8260_setup.c @@ -14,33 +14,12 @@ * option) any later version. */ -#include -#include +#include #include #include #include -static void (*callback_setup_arch)(void); - -extern unsigned char __res[sizeof(bd_t)]; - -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - -static int -tqm8260_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: IN2 Systems\n" - "machine\t\t: TQM8260 PowerPC\n" - "mem size\t\t: 0x%08x\n" - "\n", - binfo->bi_memsize); - return 0; -} - static int tqm8260_set_rtc_time(unsigned long time) { @@ -56,24 +35,10 @@ tqm8260_get_rtc_time(void) return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt; } -static void __init -tqm8260_setup_arch(void) -{ - printk("IN2 Systems TQM8260 port\n"); - callback_setup_arch(); -} - void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +m82xx_board_init(void) { - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - /* Anything special for this platform */ - ppc_md.show_cpuinfo = tqm8260_show_cpuinfo; ppc_md.set_rtc_time = tqm8260_set_rtc_time; ppc_md.get_rtc_time = tqm8260_get_rtc_time; - - callback_setup_arch = ppc_md.setup_arch; - ppc_md.setup_arch = tqm8260_setup_arch; +} diff --git a/arch/ppc/platforms/tqm8xx.h b/arch/ppc/platforms/tqm8xx.h index f69b306cb..2150dc87b 100644 --- a/arch/ppc/platforms/tqm8xx.h +++ b/arch/ppc/platforms/tqm8xx.h @@ -72,8 +72,6 @@ static __inline__ void ide_led(int on) #define IDE0_INTERRUPT 13 #ifdef CONFIG_IDE -#define ide_request_irq(irq,hand,flg,dev,id) \ - request_8xxirq((irq),(hand),(flg),(dev),(id)) #endif /*----------------------------------------------------------------------- diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 4de92f498..3a84690df 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -5,6 +5,8 @@ CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC +wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o + obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_IBM_OCP) += ibm_ocp.o @@ -12,17 +14,21 @@ obj-$(CONFIG_44x) += ibm44x_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o obj-$(CONFIG_440GX) += ibm440gx_common.o ifeq ($(CONFIG_4xx),y) -obj-$(CONFIG_4xx) += ppc4xx_pic.o +ifeq ($(CONFIG_VIRTEX_II_PRO),y) +obj-$(CONFIG_40x) += xilinx_pic.o +else +obj-$(CONFIG_40x) += ppc4xx_pic.o +endif +obj-$(CONFIG_44x) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_setup.o obj-$(CONFIG_GEN_RTC) += todc_time.o obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) -obj-$(CONFIG_KGDB) += ppc4xx_kgdb.o obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o endif endif -obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o +obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) ifeq ($(CONFIG_8xx),y) obj-$(CONFIG_PCI) += qspan_pci.o i8259.o endif @@ -45,7 +51,8 @@ obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \ obj-$(CONFIG_MENF1) += todc_time.o i8259.o mpc10x_common.o \ pci_auto.o indirect_pci.o obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \ - i8259.o pci_auto.o hawk_common.o + pci_auto.o hawk_common.o +obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_PAL4) += cpc700_pic.o obj-$(CONFIG_PCORE) += todc_time.o i8259.o pci_auto.o diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c index 43eac4135..bd8335b84 100644 --- a/arch/ppc/syslib/cpm2_pic.c +++ b/arch/ppc/syslib/cpm2_pic.c @@ -1,12 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include "cpm2_pic.h" - /* The CPM2 internal interrupt controller. It is usually * the only interrupt controller. * There are two 32-bit registers (high/low) for up to 64 @@ -18,6 +9,18 @@ * We create two tables, indexed by vector number, to indicate * which register to use and which bit in the register to use. */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "cpm2_pic.h" + static u_char irq_to_siureg[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -123,9 +126,5 @@ cpm2_get_irq(struct pt_regs *regs) if (irq == 0) return(-1); -#if 0 - irq += ppc8260_pic.irq_offset; -#endif return irq; } - diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h index a9da44168..d05003b09 100644 --- a/arch/ppc/syslib/cpm2_pic.h +++ b/arch/ppc/syslib/cpm2_pic.h @@ -1,13 +1,7 @@ #ifndef _PPC_KERNEL_CPM2_H #define _PPC_KERNEL_CPM2_H -#include - extern struct hw_interrupt_type cpm2_pic; - -void cpm2_pic_init(void); -void cpm2_do_IRQ(struct pt_regs *regs, - int cpu); -int cpm2_get_irq(struct pt_regs *regs); +extern int cpm2_get_irq(struct pt_regs *regs); #endif /* _PPC_KERNEL_CPM2_H */ diff --git a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c index 4692ba719..dc2365ce0 100644 --- a/arch/ppc/syslib/gen550_dbg.c +++ b/arch/ppc/syslib/gen550_dbg.c @@ -40,12 +40,12 @@ static int shift; unsigned long direct_inb(unsigned long addr) { - return readb(addr); + return readb((void __iomem *)addr); } void direct_outb(unsigned long addr, unsigned char val) { - writeb(val, addr); + writeb(val, (void __iomem *)addr); } unsigned long io_inb(unsigned long port) diff --git a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c index 232044cdb..7239d5d7d 100644 --- a/arch/ppc/syslib/gen550_kgdb.c +++ b/arch/ppc/syslib/gen550_kgdb.c @@ -9,9 +9,9 @@ * * Adapted from ppc4xx_kgdb.c. * - * Author: Matt Porter + * Author: Matt Porter * - * 2002-2003 (c) MontaVista Software, Inc. This file is licensed under + * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -80,5 +80,7 @@ void gen550_kgdb_map_scc(void) { printk(KERN_DEBUG "kgdb init\n"); + if (ppc_md.early_serial_map) + ppc_md.early_serial_map(); kgdb_debugport = serial_init(KGDB_PORT, NULL); } diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c index 9c2e1506a..a9911dc3a 100644 --- a/arch/ppc/syslib/hawk_common.c +++ b/arch/ppc/syslib/hawk_common.c @@ -285,3 +285,35 @@ hawk_get_mem_size(uint smc_base) return total; } + +int __init +hawk_mpic_init(unsigned int pci_mem_offset) +{ + unsigned short devid; + unsigned int pci_membase; + + /* Check the first PCI device to see if it is a Raven or Hawk. */ + early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid); + + switch (devid) { + case PCI_DEVICE_ID_MOTOROLA_RAVEN: + case PCI_DEVICE_ID_MOTOROLA_HAWK: + break; + default: + OpenPIC_Addr = NULL; + return 1; + } + + /* Read the memory base register. */ + early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase); + + if (pci_membase == 0) { + OpenPIC_Addr = NULL; + return 1; + } + + /* Map the MPIC registers to virtual memory. */ + OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000); + + return 0; +} diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c index c6c361b99..c660f403f 100644 --- a/arch/ppc/syslib/i8259.c +++ b/arch/ppc/syslib/i8259.c @@ -151,6 +151,13 @@ static struct resource pic_edgectrl_iores = { "8259 edge control", 0x4d0, 0x4d1, IORESOURCE_BUSY }; +static struct irqaction i8259_irqaction = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "82c59 secondary cascade", +}; + /* * i8259_init() * intack_addr - PCI interrupt acknowledge (real) address which will return @@ -185,8 +192,7 @@ i8259_init(long intack_addr) spin_unlock_irqrestore(&i8259_lock, flags); /* reserve our resources */ - request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT, - "82c59 secondary cascade", NULL ); + setup_irq( i8259_pic_irq_offset + 2, &i8259_irqaction); request_resource(&ioport_resource, &pic1_iores); request_resource(&ioport_resource, &pic2_iores); request_resource(&ioport_resource, &pic_edgectrl_iores); diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index 5da7bca6b..5e2ce6bf5 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -4,7 +4,7 @@ * PPC440GX system library * * Eugene Surovegin or - * Copyright (c) 2003 Zultys Technologies + * Copyright (c) 2003, 2004 Zultys Technologies * * 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 @@ -14,6 +14,7 @@ */ #include #include +#include #include #include #include @@ -97,10 +98,51 @@ bypass: p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256); } -/* Enable L2 cache (call with IRQs disabled) */ +/* Issue L2C diagnostic command */ +static inline u32 l2c_diag(u32 addr) +{ + mtdcr(DCRN_L2C0_ADDR, addr); + mtdcr(DCRN_L2C0_CMD, L2C_CMD_DIAG); + while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ; + return mfdcr(DCRN_L2C0_DATA); +} + +static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs) +{ + u32 sr = mfdcr(DCRN_L2C0_SR); + if (sr & L2C_SR_CPE){ + /* Read cache trapped address */ + u32 addr = l2c_diag(0x42000000); + printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", addr); + } + if (sr & L2C_SR_TPE){ + /* Read tag trapped address */ + u32 addr = l2c_diag(0x82000000) >> 16; + printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", addr); + } + + /* Clear parity errors */ + if (sr & (L2C_SR_CPE | L2C_SR_TPE)){ + mtdcr(DCRN_L2C0_ADDR, 0); + mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE); + } else + printk(KERN_EMERG "L2C: LRU error\n"); + + return IRQ_HANDLED; +} + +/* Enable L2 cache */ void __init ibm440gx_l2c_enable(void){ u32 r; + unsigned long flags; + + /* Install error handler */ + if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){ + printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n"); + return; + } + local_irq_save(flags); asm volatile ("sync" ::: "memory"); /* Disable SRAM */ @@ -137,20 +179,22 @@ void __init ibm440gx_l2c_enable(void){ /* Enable ICU/DCU ports */ r = mfdcr(DCRN_L2C0_CFG); - r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM - | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI | L2C_CFG_CPEI - | L2C_CFG_NAM | L2C_CFG_NBRM); + r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI + | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM); r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN - | L2C_CFG_SMCM; + | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM; mtdcr(DCRN_L2C0_CFG, r); asm volatile ("sync; isync" ::: "memory"); + local_irq_restore(flags); } -/* Disable L2 cache (call with IRQs disabled) */ +/* Disable L2 cache */ void __init ibm440gx_l2c_disable(void){ u32 r; + unsigned long flags; + local_irq_save(flags); asm volatile ("sync" ::: "memory"); /* Disable L2C mode */ @@ -169,6 +213,20 @@ void __init ibm440gx_l2c_disable(void){ SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW); asm volatile ("sync; isync" ::: "memory"); + local_irq_restore(flags); +} + +void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p) +{ + /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C, + enable it on all other revisions + */ + u32 pvr = mfspr(PVR); + if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB || + (pvr == PVR_440GX_RC && p->cpu > 667000000)) + ibm440gx_l2c_disable(); + else + ibm440gx_l2c_enable(); } int __init ibm440gx_get_eth_grp(void) diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h index 5dbca9896..e73aa0411 100644 --- a/arch/ppc/syslib/ibm440gx_common.h +++ b/arch/ppc/syslib/ibm440gx_common.h @@ -4,7 +4,7 @@ * PPC440GX system library * * Eugene Surovegin or - * Copyright (c) 2003 Zultys Technologies + * Copyright (c) 2003, 2004 Zultys Technologies * * 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 @@ -37,6 +37,9 @@ void ibm440gx_l2c_enable(void) __init; /* Disable L2 cache */ void ibm440gx_l2c_disable(void) __init; +/* Enable/disable L2 cache for a particular chip revision */ +void ibm440gx_l2c_setup(struct ibm44x_clocks*) __init; + /* Get Ethernet Group */ int ibm440gx_get_eth_grp(void) __init; diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index a0cefdc7c..4029c43f5 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -3,8 +3,11 @@ * * PPC44x system library * - * Matt Porter - * Copyright 2002-2003 MontaVista Software Inc. + * Matt Porter + * Copyright 2002-2004 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies * * 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 @@ -13,9 +16,18 @@ * */ #include +#include #include +#include + #include #include +#include +#include +#include +#include + +#include phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) { @@ -35,3 +47,136 @@ phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) return (page_4gb | addr); }; + +void __init ibm44x_calibrate_decr(unsigned int freq) +{ + tb_ticks_per_jiffy = freq / HZ; + tb_to_us = mulhwu_scale_factor(freq, 1000000); + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + + /* Enable decrementer interrupt */ + mtspr(SPRN_TCR, TCR_DIE); +} + +extern void abort(void); + +static void ibm44x_restart(char *cmd) +{ + local_irq_disable(); + abort(); +} + +static void ibm44x_power_off(void) +{ + local_irq_disable(); + for(;;); +} + +static void ibm44x_halt(void) +{ + local_irq_disable(); + for(;;); +} + +/* + * Read the 44x memory controller to get size of system memory. + */ +static unsigned long __init ibm44x_find_end_of_memory(void) +{ + u32 i, bank_config; + u32 mem_size = 0; + + for (i=0; i<4; i++) + { + switch (i) + { + case 0: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR); + break; + case 1: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR); + break; + case 2: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR); + break; + case 3: + mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR); + break; + } + + bank_config = mfdcr(DCRN_SDRAM0_CFGDATA); + + if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE)) + continue; + switch (SDRAM_CONFIG_BANK_SIZE(bank_config)) + { + case SDRAM_CONFIG_SIZE_8M: + mem_size += PPC44x_MEM_SIZE_8M; + break; + case SDRAM_CONFIG_SIZE_16M: + mem_size += PPC44x_MEM_SIZE_16M; + break; + case SDRAM_CONFIG_SIZE_32M: + mem_size += PPC44x_MEM_SIZE_32M; + break; + case SDRAM_CONFIG_SIZE_64M: + mem_size += PPC44x_MEM_SIZE_64M; + break; + case SDRAM_CONFIG_SIZE_128M: + mem_size += PPC44x_MEM_SIZE_128M; + break; + case SDRAM_CONFIG_SIZE_256M: + mem_size += PPC44x_MEM_SIZE_256M; + break; + case SDRAM_CONFIG_SIZE_512M: + mem_size += PPC44x_MEM_SIZE_512M; + break; + } + } + return mem_size; +} + +static void __init ibm44x_init_irq(void) +{ + int i; + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) + irq_desc[i].handler = ppc4xx_pic; +} + +void __init ibm44x_platform_init(void) +{ + ppc_md.init_IRQ = ibm44x_init_irq; + ppc_md.find_end_of_memory = ibm44x_find_end_of_memory; + ppc_md.restart = ibm44x_restart; + ppc_md.power_off = ibm44x_power_off; + ppc_md.halt = ibm44x_halt; + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ +#ifdef CONFIG_KGDB + ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; +#endif + + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ +#if !defined(CONFIG_BDI_SWITCH) + /* Enable internal debug mode */ + mtspr(SPRN_DBCR0, (DBCR0_IDM)); + + /* Clear any residual debug events */ + mtspr(SPRN_DBSR, 0xffffffff); +#endif +} + diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h index ee1053ac2..b14eb603c 100644 --- a/arch/ppc/syslib/ibm44x_common.h +++ b/arch/ppc/syslib/ibm44x_common.h @@ -4,7 +4,7 @@ * PPC44x system library * * Eugene Surovegin or - * Copyright (c) 2003 Zultys Technologies + * Copyright (c) 2003, 2004 Zultys Technologies * * 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 @@ -31,6 +31,12 @@ struct ibm44x_clocks { unsigned int uart1; }; +/* common 44x platform init */ +void ibm44x_platform_init(void) __init; + +/* initialize decrementer and tick-related variables */ +void ibm44x_calibrate_decr(unsigned int freq) __init; + #endif /* __ASSEMBLY__ */ #endif /* __PPC_SYSLIB_IBM44x_COMMON_H */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c index 4bc90eb2c..1cc4f962f 100644 --- a/arch/ppc/syslib/indirect_pci.c +++ b/arch/ppc/syslib/indirect_pci.c @@ -111,6 +111,15 @@ static struct pci_ops indirect_pci_ops = indirect_write_config }; +void __init +setup_indirect_pci_nomap(struct pci_controller* hose, u32 cfg_addr, + u32 cfg_data) +{ + hose->cfg_addr = (unsigned int *)cfg_addr; + hose->cfg_data = (unsigned char *)cfg_data; + hose->ops = &indirect_pci_ops; +} + void __init setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) { @@ -118,9 +127,9 @@ setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) char *mbase; mbase = ioremap(base, PAGE_SIZE); - hose->cfg_addr = (unsigned int *)(mbase + (cfg_addr & ~PAGE_MASK)); + cfg_addr = (u32)(mbase + (cfg_addr & ~PAGE_MASK)); if ((cfg_data & PAGE_MASK) != base) mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); - hose->cfg_data = (unsigned char *)(mbase + (cfg_data & ~PAGE_MASK)); - hose->ops = &indirect_pci_ops; + cfg_data = (u32)(mbase + (cfg_data & ~PAGE_MASK)); + setup_indirect_pci_nomap(hose, cfg_addr, cfg_data); } diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h index 4e2ce7f7c..d1352120a 100644 --- a/arch/ppc/syslib/m8260_pci.h +++ b/arch/ppc/syslib/m8260_pci.h @@ -66,6 +66,7 @@ #endif #ifdef CONFIG_8260_PCI9 +struct pci_controller; extern void setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); #else diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 24e1494c1..2a8c23cbc 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/setup.c + * arch/ppc/syslib/m8260_setup.c * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas @@ -8,36 +8,21 @@ * Further modified for generic 8xx and 8260 by Dan. */ -/* - * bootup setup stuff.. - */ - #include -#include #include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include +#include #include +#include #include -#include #include #include -#include #include #include #include @@ -46,10 +31,6 @@ #include "cpm2_pic.h" -static int m8260_set_rtc_time(unsigned long time); -static unsigned long m8260_get_rtc_time(void); -static void m8260_calibrate_decr(void); - unsigned char __res[sizeof(bd_t)]; extern void cpm2_reset(void); @@ -59,8 +40,10 @@ extern void idma_pci9_init(void); static void __init m8260_setup_arch(void) { - /* Reset the Communication Processor Module. - */ + /* Print out Vendor and Machine info. */ + printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE); + + /* Reset the Communication Processor Module. */ cpm2_reset(); #ifdef CONFIG_8260_PCI9 /* Initialise IDMA for PCI erratum workaround */ @@ -69,6 +52,10 @@ m8260_setup_arch(void) #ifdef CONFIG_PCI_8260 m8260_find_bridges(); #endif +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; +#endif } /* The decrementer counts at the system (internal) clock frequency @@ -77,7 +64,7 @@ m8260_setup_arch(void) static void __init m8260_calibrate_decr(void) { - bd_t *binfo = (bd_t *)__res; + bd_t *binfo = (bd_t *)__res; int freq, divisor; freq = binfo->bi_busfreq; @@ -145,18 +132,22 @@ m8260_power_off(void) } static int -m8260_show_percpuinfo(struct seq_file *m, int i) +m8260_show_cpuinfo(struct seq_file *m) { - bd_t *bp; - - bp = (bd_t *)__res; - - seq_printf(m, "core clock\t: %ld MHz\n" - "CPM clock\t: %ld MHz\n" - "bus clock\t: %ld MHz\n", - bp->bi_intfreq / 1000000, - bp->bi_cpmfreq / 1000000, - bp->bi_busfreq / 1000000); + bd_t *bp = (bd_t *)__res; + + seq_printf(m, "vendor\t\t: %s\n" + "machine\t\t: %s\n" + "\n" + "mem size\t\t: 0x%08x\n" + "console baud\t\t: %d\n" + "\n" + "core clock\t: %u MHz\n" + "CPM clock\t: %u MHz\n" + "bus clock\t: %u MHz\n", + CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize, + bp->bi_baudrate, bp->bi_intfreq / 1000000, + bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000); return 0; } @@ -170,7 +161,6 @@ static void __init m8260_init_IRQ(void) { int i; - void cpm_interrupt_init(void); for ( i = 0 ; i < NR_SIU_INTS ; i++ ) irq_desc[i].handler = &cpm2_pic; @@ -190,10 +180,7 @@ m8260_init_IRQ(void) static unsigned long __init m8260_find_end_of_memory(void) { - bd_t *binfo; - extern unsigned char __res[]; - - binfo = (bd_t *)__res; + bd_t *binfo = (bd_t *)__res; return binfo->bi_memsize; } @@ -216,6 +203,12 @@ m8260_map_io(void) io_block_mapping(IO_VIRT_ADDR, IO_PHYS_ADDR, 0x10000000, _PAGE_IO); } +/* Place-holder for board-specific init */ +void __attribute__ ((weak)) __init +m82xx_board_init(void) +{ +} + /* Inputs: * r3 - Optional pointer to a board information structure. * r4 - Optional pointer to the physical starting address of the init RAM @@ -228,7 +221,7 @@ m8260_map_io(void) * command-line parameters. */ void __init -m8260_init(unsigned long r3, unsigned long r4, unsigned long r5, +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { parse_bootinfo(find_bootinfo()); @@ -250,21 +243,21 @@ m8260_init(unsigned long r3, unsigned long r4, unsigned long r5, } ppc_md.setup_arch = m8260_setup_arch; - ppc_md.show_percpuinfo = m8260_show_percpuinfo; - ppc_md.irq_canonicalize = NULL; + ppc_md.show_cpuinfo = m8260_show_cpuinfo; ppc_md.init_IRQ = m8260_init_IRQ; ppc_md.get_irq = cpm2_get_irq; - ppc_md.init = NULL; ppc_md.restart = m8260_restart; ppc_md.power_off = m8260_power_off; ppc_md.halt = m8260_halt; - ppc_md.time_init = NULL; ppc_md.set_rtc_time = m8260_set_rtc_time; ppc_md.get_rtc_time = m8260_get_rtc_time; ppc_md.calibrate_decr = m8260_calibrate_decr; ppc_md.find_end_of_memory = m8260_find_end_of_memory; ppc_md.setup_io_mappings = m8260_map_io; + + /* Call back for board-specific settings and overrides. */ + m82xx_board_init(); } diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 5ccf07149..41d16c736 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -57,8 +57,15 @@ unsigned char __res[sizeof(bd_t)]; extern void m8xx_ide_init(void); extern unsigned long find_available_memory(void); -extern void m8xx_cpm_reset(uint); +extern void m8xx_cpm_reset(uint cpm_page); +extern void m8xx_wdt_handler_install(bd_t *bp); extern void rpxfb_alloc_pages(void); +extern void cpm_interrupt_init(void); + +void __attribute__ ((weak)) +board_init(void) +{ +} void __init m8xx_setup_arch(void) @@ -102,6 +109,7 @@ m8xx_setup_arch(void) } #endif #endif + board_init(); } void @@ -117,11 +125,19 @@ abort(void) } /* A place holder for time base interrupts, if they are ever enabled. */ -void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) +irqreturn_t timebase_interrupt(int irq, void * dev, struct pt_regs * regs) { printk ("timebase_interrupt()\n"); + + return IRQ_HANDLED; } +static struct irqaction tbint_irqaction = { + .handler = timebase_interrupt, + .mask = CPU_MASK_NONE, + .name = "tbint", +}; + /* The decrementer counts at the system (internal) clock frequency divided by * sixteen, or external oscillator divided by four. We force the processor * to use system clock divided by sixteen. @@ -186,8 +202,15 @@ void __init m8xx_calibrate_decr(void) ((mk_int_int_mask(DEC_INTERRUPT) << 8) | (TBSCR_TBF | TBSCR_TBE)); - if (request_8xxirq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) + if (setup_irq(DEC_INTERRUPT, &tbint_irqaction)) panic("Could not allocate timer IRQ!"); + +#ifdef CONFIG_8xx_WDT + /* Install watchdog timer handler early because it might be + * already enabled by the bootloader + */ + m8xx_wdt_handler_install(binfo); +#endif } /* The RTC on the MPC8xx is an internal register. @@ -255,6 +278,14 @@ m8xx_show_percpuinfo(struct seq_file *m, int i) return 0; } +#ifdef CONFIG_PCI +static struct irqaction mbx_i8259_irqaction = { + .handler = mbx_i8259_action, + .mask = CPU_MASK_NONE, + .name = "i8259 cascade", +}; +#endif + /* Initialize the internal interrupt controller. The number of * interrupts supported can vary with the processor type, and the * 82xx family can have up to 64. @@ -265,25 +296,26 @@ static void __init m8xx_init_IRQ(void) { int i; - void cpm_interrupt_init(void); - for ( i = 0 ; i < NR_SIU_INTS ; i++ ) - irq_desc[i].handler = &ppc8xx_pic; + for (i = SIU_IRQ_OFFSET ; i < SIU_IRQ_OFFSET + NR_SIU_INTS ; i++) + irq_desc[i].handler = &ppc8xx_pic; - /* We could probably incorporate the CPM into the multilevel - * interrupt structure. - */ cpm_interrupt_init(); - unmask_irq(CPM_INTERRUPT); #if defined(CONFIG_PCI) - for ( i = NR_SIU_INTS ; i < (NR_SIU_INTS + NR_8259_INTS) ; i++ ) - irq_desc[i].handler = &i8259_pic; - i8259_pic.irq_offset = NR_SIU_INTS; - i8259_init(); - request_8xxirq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL); - enable_irq(ISA_BRIDGE_INT); -#endif + for (i = I8259_IRQ_OFFSET ; i < I8259_IRQ_OFFSET + NR_8259_INTS ; i++) + irq_desc[i].handler = &i8259_pic; + + i8259_pic_irq_offset = I8259_IRQ_OFFSET; + i8259_init(0); + + /* The i8259 cascade interrupt must be level sensitive. */ + ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel &= + ~(0x80000000 >> ISA_BRIDGE_INT); + + if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction)) + enable_irq(ISA_BRIDGE_INT); +#endif /* CONFIG_PCI */ } /* -------------------------------------------------------------------- */ @@ -334,7 +366,7 @@ m8xx_map_io(void) io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); #endif #endif -#ifdef CONFIG_HTDMSOUND +#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX) io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO); #endif #ifdef CONFIG_FADS @@ -343,6 +375,9 @@ m8xx_map_io(void) #ifdef CONFIG_PCI io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO); #endif +#if defined(CONFIG_NETTA) + io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO); +#endif } void __init diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 153c811b1..ddcb9e06f 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c @@ -43,7 +43,7 @@ #ifdef CONFIG_MPC10X_OPENPIC #ifdef CONFIG_EPIC_SERIAL_MODE -#define EPIC_IRQ_BASE 16 +#define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5) #else #define EPIC_IRQ_BASE 5 #endif @@ -69,20 +69,16 @@ static struct ocp_def mpc10x_i2c_ocp = { .vendor = OCP_VENDOR_MOTOROLA, .function = OCP_FUNC_IIC, .index = 0, - .irq = MPC10X_I2C_IRQ, .additions = &mpc10x_i2c_data }; static struct ocp_def mpc10x_dma_ocp[2] = { { .vendor = OCP_VENDOR_MOTOROLA, .function = OCP_FUNC_DMA, - .index = 0, - .irq = MPC10X_DMA0_IRQ -}, + .index = 0 }, { .vendor = OCP_VENDOR_MOTOROLA, .function = OCP_FUNC_DMA, - .index = 1, - .irq = MPC10X_DMA1_IRQ } + .index = 1 } }; /* Set resources to match bridge memory map */ @@ -292,12 +288,15 @@ mpc10x_bridge_init(struct pci_controller *hose, MPC10X_EUMB_EPIC_SIZE); #endif mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET; + mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ; ocp_add_one_device(&mpc10x_i2c_ocp); mpc10x_dma_ocp[0].paddr = phys_eumb_base + MPC10X_EUMB_DMA_OFFSET + 0x100; + mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ; ocp_add_one_device(&mpc10x_dma_ocp[0]); mpc10x_dma_ocp[1].paddr = phys_eumb_base + MPC10X_EUMB_DMA_OFFSET + 0x200; + mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ; ocp_add_one_device(&mpc10x_dma_ocp[1]); } diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c index 0f88e63b0..4de79d3b9 100644 --- a/arch/ppc/syslib/mpc52xx_pic.c +++ b/arch/ppc/syslib/mpc52xx_pic.c @@ -114,7 +114,7 @@ mpc52xx_ic_ack(unsigned int irq) /* * Only some irqs are reset here, others in interrupting hardware. */ - + switch (irq) { case MPC52xx_IRQ0: val = in_be32(&intr->ctrl); @@ -180,13 +180,14 @@ void __init mpc52xx_init_irq(void) { int i; + u32 intr_ctrl; /* Remap the necessary zones */ intr = (struct mpc52xx_intr *) ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr)); sdma = (struct mpc52xx_sdma *) ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma)); - + if ((intr==NULL) || (sdma==NULL)) panic("Can't ioremap PIC/SDMA register for init_irq !"); @@ -195,12 +196,13 @@ mpc52xx_init_irq(void) out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ - out_be32(&intr->ctrl, - 0x0f000000 | /* clear IRQ 0-3 */ - 0x00c00000 | /* IRQ0: level-sensitive, active low */ + intr_ctrl = in_be32(&intr->ctrl); + intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ + intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ 0x00001000 | /* MEE master external enable */ 0x00000000 | /* 0 means disable IRQ 0-3 */ - 0x00000001); /* CEb route critical normally */ + 0x00000001; /* CEb route critical normally */ + out_be32(&intr->ctrl, intr_ctrl); /* Zero a bunch of the priority settings. */ out_be32(&intr->per_pri1, 0); @@ -214,6 +216,14 @@ mpc52xx_init_irq(void) irq_desc[i].handler = &mpc52xx_ic; irq_desc[i].status = IRQ_LEVEL; } + + #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03) + for (i=0 ; i<4 ; i++) { + int mode; + mode = IRQn_MODE(intr_ctrl,i); + if ((mode == 0x1) || (mode == 0x2)) + irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0; + } } int diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c index 631cea34b..6bd014d7c 100644 --- a/arch/ppc/syslib/mpc52xx_setup.c +++ b/arch/ppc/syslib/mpc52xx_setup.c @@ -1,5 +1,5 @@ /* - * arch/ppc/syslib/mpc52xx_common.c + * arch/ppc/syslib/mpc52xx_setup.c * * Common code for the boards based on Freescale MPC52xx embedded CPU. * @@ -19,10 +19,12 @@ #include +#include #include #include #include #include +#include #include extern bd_t __res; @@ -38,9 +40,9 @@ void mpc52xx_restart(char *cmd) { struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0); - + local_irq_disable(); - + /* Turn on the watchdog and wait for it to expire. It effectively does a reset */ if (gpt0 != NULL) { @@ -99,24 +101,28 @@ mpc52xx_map_io(void) #error "mpc52xx PSC for console not selected" #endif +static void +mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c) +{ + while (!(in_be16(&psc->mpc52xx_psc_status) & + MPC52xx_PSC_SR_TXRDY)); + out_8(&psc->mpc52xx_psc_buffer_8, c); +} + void mpc52xx_progress(char *s, unsigned short hex) { struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE; char c; - /* Don't we need to disable serial interrupts ? */ - while ((c = *s++) != 0) { - if (c == '\n') { - while (!(in_be16(&psc->mpc52xx_psc_status) & - MPC52xx_PSC_SR_TXRDY)) ; - out_8(&psc->mpc52xx_psc_buffer_8, '\r'); - } - while (!(in_be16(&psc->mpc52xx_psc_status) & - MPC52xx_PSC_SR_TXRDY)) ; - out_8(&psc->mpc52xx_psc_buffer_8, c); + if (c == '\n') + mpc52xx_psc_putc(psc, '\r'); + mpc52xx_psc_putc(psc, c); } + + mpc52xx_psc_putc(psc, '\r'); + mpc52xx_psc_putc(psc, '\n'); } #endif /* CONFIG_SERIAL_TEXT_DEBUG */ @@ -137,7 +143,7 @@ mpc52xx_find_end_of_memory(void) /* Temp BAT2 mapping active when this is called ! */ mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL; - + sdram_config_0 = in_be32(&mmap_ctl->sdram0); sdram_config_1 = in_be32(&mmap_ctl->sdram1); @@ -147,10 +153,8 @@ mpc52xx_find_end_of_memory(void) if (((sdram_config_1 & 0x1f) >= 0x13) && ((sdram_config_1 & 0xfff00000) == ramsize)) ramsize += 1 << ((sdram_config_1 & 0xf) + 17); - - iounmap(mmap_ctl); } - + return ramsize; } @@ -167,7 +171,7 @@ mpc52xx_calibrate_decr(void) /* Get RTC & Clock manager modules */ struct mpc52xx_rtc *rtc; struct mpc52xx_cdm *cdm; - + rtc = (struct mpc52xx_rtc*) ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc)); cdm = (struct mpc52xx_cdm*) @@ -206,7 +210,7 @@ mpc52xx_calibrate_decr(void) __res.bi_intfreq = cpufreq; __res.bi_ipbfreq = ipbfreq; __res.bi_pcifreq = pcifreq; - + /* Release mapping */ iounmap((void*)rtc); iounmap((void*)cdm); diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index a19f8c2d9..c900bf9d4 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,6 @@ #include #include #include -#include #include "open_pic_defs.h" @@ -53,7 +53,6 @@ static int (*openpic_cascade_fn)(struct pt_regs *); /* Global Operations */ static void openpic_disable_8259_pass_through(void); -static void openpic_set_priority(u_int pri); static void openpic_set_spurious(u_int vector); #ifdef CONFIG_SMP @@ -261,6 +260,9 @@ static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int #endif /* CONFIG_SMP */ #ifdef CONFIG_EPIC_SERIAL_MODE +/* On platforms that may use EPIC serial mode, the default is enabled. */ +int epic_serial_mode = 1; + static void __init openpic_eicr_set_clk(u_int clkval) { openpic_writefield(&OpenPIC->Global.Global_Configuration1, @@ -412,11 +414,13 @@ void __init openpic_init(int offset) /* Initialize the spurious interrupt */ if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd); - openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset); + openpic_set_spurious(OPENPIC_VEC_SPURIOUS); openpic_disable_8259_pass_through(); #ifdef CONFIG_EPIC_SERIAL_MODE - openpic_eicr_set_clk(7); /* Slowest value until we know better */ - openpic_enable_sie(); + if (epic_serial_mode) { + openpic_eicr_set_clk(7); /* Slowest value until we know better */ + openpic_enable_sie(); + } #endif openpic_set_priority(0); @@ -472,7 +476,7 @@ static u_int openpic_get_priority(void) } #endif /* notused */ -static void __init openpic_set_priority(u_int pri) +void openpic_set_priority(u_int pri) { DECL_THIS_CPU; @@ -681,13 +685,21 @@ openpic_init_nmi_irq(u_int irq) /* * Hookup a cascade to the OpenPIC. */ + +static struct irqaction openpic_cascade_irqaction = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, +}; + void __init openpic_hookup_cascade(u_int irq, char *name, int (*cascade_fn)(struct pt_regs *)) { openpic_cascade_irq = irq; openpic_cascade_fn = cascade_fn; - if (request_irq(irq, no_action, SA_INTERRUPT, name, NULL)) + + if (setup_irq(irq, &openpic_cascade_irqaction)) printk("Unable to get OpenPIC IRQ %d for cascade\n", irq - open_pic_irq_offset); } @@ -865,7 +877,7 @@ openpic_get_irq(struct pt_regs *regs) irq = cirq; openpic_eoi(); } - } else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) + } else if (irq == OPENPIC_VEC_SPURIOUS) irq = -1; return irq; } @@ -942,6 +954,8 @@ int openpic_suspend(struct sys_device *sysdev, u32 state) return 0; } + openpic_set_priority(0xf); + open_pic.enable = openpic_cached_enable_irq; open_pic.disable = openpic_cached_disable_irq; @@ -988,9 +1002,9 @@ int openpic_resume(struct sys_device *sysdev) /* OpenPIC sometimes seem to need some time to be fully back up... */ do { - openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset); + openpic_set_spurious(OPENPIC_VEC_SPURIOUS); } while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK) - != (OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)); + != OPENPIC_VEC_SPURIOUS); openpic_disable_8259_pass_through(); @@ -1015,6 +1029,8 @@ int openpic_resume(struct sys_device *sysdev) open_pic.enable = openpic_enable_irq; open_pic.disable = openpic_disable_irq; + openpic_set_priority(0); + spin_unlock_irqrestore(&openpic_setup_lock, flags); return 0; diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 52cb4a494..191e5af0e 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include "open_pic_defs.h" diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c index 7f94bdf39..81c83bf98 100644 --- a/arch/ppc/syslib/ppc405_pci.c +++ b/arch/ppc/syslib/ppc405_pci.c @@ -82,8 +82,8 @@ ppc4xx_find_bridges(void) unsigned int tmp_addr; unsigned int tmp_size; unsigned int reg_index; - unsigned int new_pmm_max; - unsigned int new_pmm_min; + unsigned int new_pmm_max = 0; + unsigned int new_pmm_min = 0; isa_io_base = 0; isa_mem_base = 0; diff --git a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c index b2f3d8505..89f682524 100644 --- a/arch/ppc/syslib/ppc4xx_dma.c +++ b/arch/ppc/syslib/ppc4xx_dma.c @@ -466,7 +466,7 @@ ppc4xx_init_dma_channel(unsigned int dmanr, ppc_dma_ch_t * p_init) /* clear all polarity signals and then "or" in new signal levels */ polarity &= ~GET_DMA_POLARITY(dmanr); - polarity |= p_dma_ch->polarity; + polarity |= p_init->polarity; #if DCRN_POL > 0 mtdcr(DCRN_POL, polarity); #endif diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c index e6da0a20d..2dc63a58c 100644 --- a/arch/ppc/syslib/ppc4xx_pic.c +++ b/arch/ppc/syslib/ppc4xx_pic.c @@ -256,7 +256,7 @@ static void ppc4xx_uic_end(unsigned int irq) { int bit, word; - unsigned int tr_bits; + unsigned int tr_bits = 0; bit = irq & 0x1f; word = irq >> 5; diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c index f7458822f..5385e76eb 100644 --- a/arch/ppc/syslib/ppc4xx_setup.c +++ b/arch/ppc/syslib/ppc4xx_setup.c @@ -42,6 +42,8 @@ #include #include +#include + /* Function Prototypes */ extern void abort(void); extern void ppc4xx_find_bridges(void); @@ -56,15 +58,19 @@ bd_t __res; void __init ppc4xx_setup_arch(void) { - /* Setup PCI host bridges */ +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + mtspr(SPRN_DBCR0, (DBCR0_IDM)); + mtspr(SPRN_DBSR, 0xffffffff); +#endif + /* Setup PCI host bridges */ #ifdef CONFIG_PCI ppc4xx_find_bridges(); #endif - -#if defined(CONFIG_FB) - conswitchp = &dummy_con; -#endif } /* @@ -193,34 +199,6 @@ ppc4xx_calibrate_decr(void) /* Set the PIT reload value and just let it run. */ mtspr(SPRN_PIT, tb_ticks_per_jiffy); } -#ifdef CONFIG_SERIAL_TEXT_DEBUG - -/* We assume that the UART has already been initialized by the - firmware or the boot loader */ -static void -serial_putc(u8 * com_port, unsigned char c) -{ - while ((readb(com_port + (UART_LSR)) & UART_LSR_THRE) == 0) ; - writeb(c, com_port); -} - -static void -ppc4xx_progress(char *s, unsigned short hex) -{ - char c; -#ifdef SERIAL_DEBUG_IO_BASE - u8 *com_port = (u8 *) SERIAL_DEBUG_IO_BASE; - - while ((c = *s++) != '\0') { - serial_putc(com_port, c); - } - serial_putc(com_port, '\r'); - serial_putc(com_port, '\n'); -#else - printk("%s\r\n"); -#endif -} -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ /* * IDE stuff. @@ -323,13 +301,9 @@ ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.setup_io_mappings = ppc4xx_map_io; #ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = ppc4xx_progress; + ppc_md.progress = gen550_progress; #endif -/* -** m8xx_setup.c, prep_setup.c use -** defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -*/ #if defined(CONFIG_PCI) && defined(CONFIG_IDE) ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports; #endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */ diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index 6ceea97f4..d4e651534 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -277,7 +277,7 @@ mpc85xx_setup_hose(void) hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO; hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO; hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE; -#if CONFIG_85xx_PCI2 +#ifdef CONFIG_85xx_PCI2 isa_io_base = (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE, MPC85XX_PCI1_IO_SIZE + @@ -304,7 +304,7 @@ mpc85xx_setup_hose(void) hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); -#if CONFIG_85xx_PCI2 +#ifdef CONFIG_85xx_PCI2 hose_b = pcibios_alloc_controller(); if (!hose_b) diff --git a/arch/ppc/syslib/ppc8xx_pic.c b/arch/ppc/syslib/ppc8xx_pic.c index 8481a415a..d3b01c6c9 100644 --- a/arch/ppc/syslib/ppc8xx_pic.c +++ b/arch/ppc/syslib/ppc8xx_pic.c @@ -4,11 +4,14 @@ #include #include #include +#include #include #include #include #include "ppc8xx_pic.h" +extern int cpm_get_irq(struct pt_regs *regs); + /* The 8xx internal interrupt controller. It is usually * the only interrupt controller. Some boards, like the MBX and * Sandpoint have the 8259 as a secondary controller. Depending @@ -72,46 +75,13 @@ static void m8xx_mask_and_ack(unsigned int irq_nr) } struct hw_interrupt_type ppc8xx_pic = { - " 8xx SIU ", - NULL, - NULL, - m8xx_unmask_irq, - m8xx_mask_irq, - m8xx_mask_and_ack, - m8xx_end_irq, - 0 + .typename = " 8xx SIU ", + .enable = m8xx_unmask_irq, + .disable = m8xx_mask_irq, + .ack = m8xx_mask_and_ack, + .end = m8xx_end_irq, }; -#if 0 -void -m8xx_do_IRQ(struct pt_regs *regs, - int cpu) -{ - int irq; - unsigned long bits = 0; - - /* For MPC8xx, read the SIVEC register and shift the bits down - * to get the irq number. */ - bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec; - irq = bits >> 26; -#if 0 - irq += ppc8xx_pic.irq_offset; -#endif - bits = 1UL << irq; - - if (irq < 0) { - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", - irq, regs->nip); - ppc_spurious_interrupts++; - } - else { - ppc_irq_dispatch_handler( regs, irq ); - } - -} -#endif - - /* * We either return a valid interrupt or -1 if there is nothing pending */ @@ -129,73 +99,32 @@ m8xx_get_irq(struct pt_regs *regs) * When we read the sivec without an interrupt to process, we will * get back SIU_LEVEL7. In this case, return -1 */ - if (irq == SIU_LEVEL7) - return -1; + if (irq == CPM_INTERRUPT) + irq = CPM_IRQ_OFFSET + cpm_get_irq(regs); +#if defined(CONFIG_PCI) + else if (irq == ISA_BRIDGE_INT) { + int isa_irq; + + if ((isa_irq = i8259_poll(regs)) >= 0) + irq = I8259_IRQ_OFFSET + isa_irq; + } +#endif /* CONFIG_PCI */ + else if (irq == SIU_LEVEL7) + irq = -1; return irq; } -/* The MBX is the only 8xx board that uses the 8259. -*/ #if defined(CONFIG_MBX) && defined(CONFIG_PCI) -void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - int bits, irq; - - /* A bug in the QSpan chip causes it to give us 0xff always - * when doing a character read. So read 32 bits and shift. - * This doesn't seem to return useful values anyway, but - * read it to make sure things are acked. - * -- Cort - */ - irq = (inl(0x508) >> 24)&0xff; - if ( irq != 0xff ) printk("iack %d\n", irq); - - outb(0x0C, 0x20); - irq = inb(0x20) & 7; - if (irq == 2) - { - outb(0x0C, 0xA0); - irq = inb(0xA0); - irq = (irq&7) + 8; - } - bits = 1UL << irq; - irq += i8259_pic.irq_offset; - ppc_irq_dispatch_handler( regs, irq ); -} -#endif - /* Only the MBX uses the external 8259. This allows us to catch standard * drivers that may mess up the internal interrupt controllers, and also * allow them to run without modification on the MBX. */ -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) +void mbx_i8259_action(int irq, void *dev_id, struct pt_regs *regs) { - -#if defined(CONFIG_MBX) && defined(CONFIG_PCI) - irq += i8259_pic.irq_offset; - return (request_8xxirq(irq, handler, irqflags, devname, dev_id)); -#else - /* - * Handle other "well-known" interrupts, but panic on unknown ones. + /* This interrupt handler never actually gets called. It is + * installed only to unmask the 8259 cascade interrupt in the SIU + * and to make the 8259 cascade interrupt visible in /proc/interrupts. */ - switch (irq) { -#ifdef IDE0_INTERRUPT - case IDE0_INTERRUPT: /* IDE0 */ - return (request_8xxirq(irq, handler, irqflags, devname, - dev_id)); -#endif -#ifdef IDE1_INTERRUPT - case IDE1_INTERRUPT: /* IDE1 */ - return (request_8xxirq(irq, handler, irqflags, devname, - dev_id)); -#endif - default: /* unknown IRQ -> panic */ - panic("request_irq"); - } -#endif } - -EXPORT_SYMBOL(request_irq); +#endif /* CONFIG_PCI */ diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 1ddb0c0eb..1b23f1e23 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index c9701d5ba..3d6ea5ee8 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -115,11 +115,11 @@ prom_entry prom __initdata; ihandle prom_chosen __initdata; ihandle prom_stdout __initdata; -char *prom_display_paths[FB_MAX] __initdata; -phandle prom_display_nodes[FB_MAX] __initdata; -unsigned int prom_num_displays __initdata; -char *of_stdout_device __initdata; +static char *prom_display_paths[FB_MAX] __initdata; +static phandle prom_display_nodes[FB_MAX] __initdata; +static unsigned int prom_num_displays __initdata; static ihandle prom_disp_node __initdata; +char *of_stdout_device __initdata; unsigned int rtas_data; /* physical pointer */ unsigned int rtas_entry; /* physical pointer */ @@ -403,6 +403,7 @@ check_display(unsigned long mem) for (j=0; j #include #include +#include #include #include @@ -48,8 +49,6 @@ * --MAG */ -extern spinlock_t rtc_lock; - /* * 'todc_info' should be initialized in your *_setup.c file to * point to a fully initialized 'todc_info_t' structure. @@ -82,13 +81,13 @@ extern spinlock_t rtc_lock; u_char todc_direct_read_val(int addr) { - return readb(todc_info->nvram_data + addr); + return readb((void __iomem *)(todc_info->nvram_data + addr)); } void todc_direct_write_val(int addr, unsigned char val) { - writeb(val, todc_info->nvram_data + addr); + writeb(val, (void __iomem *)(todc_info->nvram_data + addr)); return; } @@ -277,9 +276,9 @@ todc_time_init(void) ulong todc_get_rtc_time(void) { - uint year, mon, day, hour, min, sec; + uint year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0; uint limit, i; - u_char save_control, uip; + u_char save_control, uip = 0; spin_lock(&rtc_lock); save_control = todc_read_val(todc_info->control_a); @@ -361,7 +360,7 @@ int todc_set_rtc_time(unsigned long nowtime) { struct rtc_time tm; - u_char save_control, save_freq_select; + u_char save_control, save_freq_select = 0; spin_lock(&rtc_lock); to_tm(nowtime, &tm); @@ -416,7 +415,7 @@ todc_set_rtc_time(unsigned long nowtime) */ static unsigned char __init todc_read_timereg(int addr) { - unsigned char save_control, val; + unsigned char save_control = 0, val; switch (todc_info->rtc_type) { case TODC_TYPE_DS1557: diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index d88096739..8d3fde10b 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,9 +22,6 @@ #include #include #include -#ifdef CONFIG_SMP -#include -#endif static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; @@ -104,7 +102,7 @@ static struct sysrq_key_op sysrq_xmon_op = { .handler = sysrq_handle_xmon, .help_msg = "Xmon", - .action_msg = "Entering xmon\n", + .action_msg = "Entering xmon", }; #endif diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index e7fe8d4c2..9976e7cb5 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -8,10 +8,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 5705ce63b..6aef1b6ec 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -1,4 +1,4 @@ -# +# # For a description of the syntax of this configuration file, # see Documentation/kbuild/kconfig-language.txt. # @@ -58,16 +58,38 @@ menu "Platform support" choice prompt "Platform Type" - default PPC_PSERIES + default PPC_MULTIPLATFORM config PPC_ISERIES - bool "iSeries" + bool "IBM Legacy iSeries" -config PPC_PSERIES - bool "pSeries / PowerMac G5" +config PPC_MULTIPLATFORM + bool "Generic" endchoice +config PPC_PSERIES + depends on PPC_MULTIPLATFORM + bool " IBM pSeries & new iSeries" + default y + +config PPC_PMAC + depends on PPC_MULTIPLATFORM + bool " Apple G5 based machines" + default y + select ADB_PMU + select U3_DART + +config PPC_MAPLE + depends on PPC_MULTIPLATFORM + bool " Maple 970FX Evaluation Board" + select U3_DART + select MPIC_BROKEN_U3 + default n + help + This option enables support for the Maple 970FX Evaluation Board. + For more informations, refer to http://www.970eval.com + config PPC bool default y @@ -77,7 +99,7 @@ config PPC64 default y config PPC_OF - depends on PPC_PSERIES + depends on PPC_MULTIPLATFORM bool default y @@ -85,14 +107,9 @@ config PPC_OF # exception vectors for it config ALTIVEC bool "Support for VMX (Altivec) vector unit" - depends on PPC_PSERIES + depends on PPC_MULTIPLATFORM default y -config PPC_PMAC - depends on PPC_PSERIES - bool "Apple PowerMac G5 support" - select ADB_PMU - config PPC_SPLPAR depends on PPC_PSERIES bool "Support for shared-processor logical partitions" @@ -103,16 +120,20 @@ config PPC_SPLPAR processors, that is, which share physical processors between two or more partitions. -config PMAC_DART - bool "Enable DART/IOMMU on PowerMac (allow >2G of RAM)" - depends on PPC_PMAC - depends on EXPERIMENTAL +config IBMVIO + depends on PPC_PSERIES || PPC_ISERIES + bool + default y + +config U3_DART + bool + depends on PPC_MULTIPLATFORM default n - help - Enabling DART makes it possible to boot a PowerMac G5 with more - than 2GB of memory. Note that the code is very new and untested - at this time, so it has to be considered experimental. Enabling - this might result in data loss. + +config MPIC_BROKEN_U3 + bool + depends on PPC_MAPLE + default y config PPC_PMAC64 bool @@ -163,7 +184,7 @@ config SMP config IRQ_ALL_CPUS bool "Distribute interrupts on all CPUs by default" - depends on SMP && PPC_PSERIES + depends on SMP && PPC_MULTIPLATFORM help This option gives the kernel permission to distribute IRQs across multiple CPUs. Saying N here will route all IRQs to the first @@ -206,6 +227,13 @@ config PREEMPT Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. +# +# Use the generic interrupt handling code in kernel/irq/: +# +config GENERIC_HARDIRQS + bool + default y + config MSCHUNKS bool depends on PPC_ISERIES @@ -214,7 +242,7 @@ config MSCHUNKS config PPC_RTAS bool "Proc interface to RTAS" - depends on !PPC_ISERIES + depends on PPC_PSERIES config RTAS_FLASH tristate "Firmware flash interface" @@ -226,8 +254,9 @@ config SCANLOG config LPARCFG tristate "LPAR Configuration Data" + depends on PPC_PSERIES || PPC_ISERIES help - Provide system capacity information via human readable + Provide system capacity information via human readable = pairs through a /proc/ppc64/lparcfg interface. endmenu @@ -272,7 +301,7 @@ source "drivers/pci/Kconfig" config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" - depends on SMP && HOTPLUG && EXPERIMENTAL + depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PSERIES ---help--- Say Y here to be able to turn CPUs off and on. @@ -343,102 +372,15 @@ config VIOPATH source "arch/ppc64/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_STACKOVERFLOW - bool "Check for stack overflows" - depends on DEBUG_KERNEL - -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUGGER - bool "Enable debugger hooks" - depends on DEBUG_KERNEL - help - Include in-kernel hooks for kernel debuggers. Unless you are - intending to debug the kernel, say N here. - -config XMON - bool "Include xmon kernel debugger" - depends on DEBUGGER - help - Include in-kernel hooks for the xmon kernel monitor/debugger. - Unless you are intending to debug the kernel, say N here. - -config XMON_DEFAULT - bool "Enable xmon by default" - depends on XMON - -config PPCDBG - bool "Include PPCDBG realtime debugging" - depends on DEBUG_KERNEL - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config IRQSTACKS - bool "Use separate kernel stacks when processing interrupts" - help - If you say Y here the kernel will use separate kernel stacks - for handling hard and soft interrupts. This can help avoid - overflowing the process kernel stacks. - -config SPINLINE - bool "Inline spinlock code at each call site" - depends on SMP && !PPC_SPLPAR && !PPC_ISERIES - help - Say Y if you want to have the code for acquiring spinlocks - and rwlocks inlined at each call site. This makes the kernel - somewhat bigger, but can be useful when profiling the kernel. - - If in doubt, say N. - -endmenu +source "arch/ppc64/Kconfig.debug" source "security/Kconfig" +config KEYS_COMPAT + bool + depends on COMPAT && KEYS + default y + source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug index c3cd4c747..be2d879d8 100644 --- a/arch/ppc64/Kconfig.debug +++ b/arch/ppc64/Kconfig.debug @@ -44,16 +44,4 @@ config IRQSTACKS for handling hard and soft interrupts. This can help avoid overflowing the process kernel stacks. -config SCHEDSTATS - bool "Collect scheduler statistics" - depends on DEBUG_KERNEL && PROC_FS - help - If you say Y here, additional code will be inserted into the - scheduler and related routines to collect statistics about - scheduler behavior and provide them in /proc/schedstat. These - stats may be useful for both tuning and debugging the scheduler - If you aren't debugging the scheduler or trying to tune a specific - application, you can say N to avoid the very slight overhead - this adds. - endmenu diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index 10c1d6299..cbcb8e3a2 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -15,29 +15,35 @@ KERNELLOAD := 0xc000000000000000 -HAS_BIARCH := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;) +HAS_BIARCH := $(call cc-option-yn, -m64) ifeq ($(HAS_BIARCH),y) AS := $(AS) -a64 LD := $(LD) -m elf64ppc CC := $(CC) -m64 endif -CHECK := $(CHECK) -m64 -D__powerpc__=1 +new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi) + +ifeq ($(new_nm),y) +NM := $(NM) --synthetic +endif + +CHECKFLAGS += -m64 -D__powerpc__ LDFLAGS := -m elf64ppc LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) -CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ - -mtraceback=none +CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \ + -mcall-aixdesc ifeq ($(CONFIG_POWER4_ONLY),y) - CFLAGS += $(call check_gcc,-mcpu=power4,) + CFLAGS += $(call cc-option,-mcpu=power4) else - CFLAGS += $(call check_gcc,-mtune=power4,) + CFLAGS += $(call cc-option,-mtune=power4) endif # Enable unit-at-a-time mode when possible. It shrinks the # kernel considerably. -CFLAGS += $(call check_gcc,-funit-at-a-time,) +CFLAGS += $(call cc-option,-funit-at-a-time) head-y := arch/ppc64/kernel/head.o @@ -50,11 +56,13 @@ drivers-$(CONFIG_OPROFILE) += arch/ppc64/oprofile/ boot := arch/ppc64/boot boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd +boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm $(boottarget-y): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ bootimage-$(CONFIG_PPC_PSERIES) := zImage +bootimage-$(CONFIG_PPC_MAPLE) := zImage bootimage-$(CONFIG_PPC_ISERIES) := vmlinux BOOTIMAGE := $(bootimage-y) install: vmlinux diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile index 9d6431dd6..9963fedcc 100644 --- a/arch/ppc64/boot/Makefile +++ b/arch/ppc64/boot/Makefile @@ -25,11 +25,11 @@ CROSS32_COMPILE ?= BOOTCC := $(CROSS32_COMPILE)gcc HOSTCC := gcc -BOOTCFLAGS := $(HOSTCFLAGS) -Iinclude -fno-builtin +BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin BOOTAS := $(CROSS32_COMPILE)as BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional BOOTLD := $(CROSS32_COMPILE)ld -BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(obj)/zImage.lds +BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy OBJCOPYFLAGS := contents,alloc,load,readonly,data @@ -51,36 +51,31 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S #----------------------------------------------------------- # ELF sections within the zImage bootloader/wrapper #----------------------------------------------------------- -required := vmlinux .config System.map +required := vmlinux.strip initrd := initrd obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) -host-progs := piggy addnote addSystemMap addRamDisk +hostprogs-y := piggy addnote addRamDisk targets += zImage zImage.initrd imagesize.c \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.sm vmlinux.initrd vmlinux.sminitrd -extra-y := sysmap.o initrd.o - -quiet_cmd_sysmap = SYSMAP $@ - cmd_sysmap = $(obj)/addSystemMap System.map $< $@ -$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap System.map FORCE - $(call if_changed,sysmap) + vmlinux.initrd +extra-y := initrd.o quiet_cmd_ramdisk = RAMDISK $@ - cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@ -$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE - $(call if_changed,ramdisk) + cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@ -$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE - $(call if_changed,ramdisk) +quiet_cmd_stripvm = STRIP $@ + cmd_stripvm = $(STRIP) -s $< -o $@ -$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE - $(call if_changed,piggy) +vmlinux.strip: vmlinux FORCE + $(call if_changed,stripvm) +$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE + $(call if_changed,ramdisk) addsection = $(BOOTOBJCOPY) $(1) \ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \ @@ -113,9 +108,9 @@ $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd)) $(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE $(call if_changed,addnote) -$(obj)/imagesize.c: vmlinux +$(obj)/imagesize.c: vmlinux.strip @echo Generating $@ - ls -l vmlinux | \ + ls -l vmlinux.strip | \ awk '{printf "/* generated -- do not edit! */\n" \ "unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \ @@ -123,6 +118,6 @@ $(obj)/imagesize.c: vmlinux >> $(obj)/imagesize.c install: $(CONFIGURE) $(obj)/$(BOOTIMAGE) - sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)" + sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)" -clean-files := $(patsubst $(obj)/%,%, $(obj-boot)) +clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip) diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index f5a9718ef..561b2bb78 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -31,13 +31,9 @@ unsigned long strlen(const char *s); void *memmove(void *dest, const void *src, unsigned long n); void *memcpy(void *dest, const void *src, unsigned long n); -static struct bi_record *make_bi_recs(unsigned long); - -#define RAM_START 0x00000000 -#define RAM_END (64<<20) - /* Value picked to match that used by yaboot */ #define PROG_START 0x01400000 +#define RAM_END (256<<20) // Fixme: use OF */ char *avail_ram; char *begin_avail, *end_avail; @@ -48,8 +44,6 @@ unsigned int heap_max; extern char _start[]; extern char _vmlinux_start[]; extern char _vmlinux_end[]; -extern char _sysmap_start[]; -extern char _sysmap_end[]; extern char _initrd_start[]; extern char _initrd_end[]; extern unsigned long vmlinux_filesize; @@ -62,7 +56,6 @@ struct addr_range { }; struct addr_range vmlinux = {0, 0, 0}; struct addr_range vmlinuz = {0, 0, 0}; -struct addr_range sysmap = {0, 0, 0}; struct addr_range initrd = {0, 0, 0}; static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ @@ -70,7 +63,7 @@ static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ typedef void (*kernel_entry_t)( unsigned long, unsigned long, void *, - struct bi_record *); + void *); int (*prom)(void *); @@ -80,12 +73,31 @@ void *stdin; void *stdout; void *stderr; +#define DEBUG + +static unsigned long claim_base = PROG_START; + +static unsigned long try_claim(unsigned long size) +{ + unsigned long addr = 0; + + for(; claim_base < RAM_END; claim_base += 0x100000) { +#ifdef DEBUG + printf(" trying: 0x%08lx\n\r", claim_base); +#endif + addr = (unsigned long)claim(claim_base, size, 0); + if ((void *)addr != (void *)-1) + break; + } + if (addr == 0) + return 0; + claim_base = PAGE_ALIGN(claim_base + size); + return addr; +} -void -start(unsigned long a1, unsigned long a2, void *promptr) +void start(unsigned long a1, unsigned long a2, void *promptr) { - unsigned long i, claim_addr, claim_size; - struct bi_record *bi_recs; + unsigned long i; kernel_entry_t kernel_entry; Elf64_Ehdr *elf64; Elf64_Phdr *elf64ph; @@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr) printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start); -#if 0 - sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start); - sysmap.memsize = sysmap.size; - if ( sysmap.size > 0 ) { - sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF; - claim(sysmap.addr, RAM_END - sysmap.addr, 0); - printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r", - sysmap.addr, (unsigned long)_sysmap_start, sysmap.size); - memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size); + /* + * Now we try to claim some memory for the kernel itself + * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what + * our Makefile stuffs in is an image containing all sort of junk including + * an ELF header. We need to do some calculations here to find the right + * size... In practice we add 1Mb, that is enough, but we should really + * consider fixing the Makefile to put a _raw_ kernel in there ! + */ + vmlinux_memsize += 0x100000; + printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize); + vmlinux.addr = try_claim(vmlinux_memsize); + if (vmlinux.addr == 0) { + printf("Can't allocate memory for kernel image !\n\r"); + exit(); } -#endif + vmlinuz.addr = (unsigned long)_vmlinux_start; + vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); + vmlinux.size = PAGE_ALIGN(vmlinux_filesize); + vmlinux.memsize = vmlinux_memsize; + /* + * Now we try to claim memory for the initrd (and copy it there) + */ initrd.size = (unsigned long)(_initrd_end - _initrd_start); initrd.memsize = initrd.size; if ( initrd.size > 0 ) { - initrd.addr = (RAM_END - initrd.size) & ~0xFFF; - a1 = a2 = 0; - claim(initrd.addr, RAM_END - initrd.addr, 0); + printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size); + initrd.addr = try_claim(initrd.size); + if (initrd.addr == 0) { + printf("Can't allocate memory for initial ramdisk !\n\r"); + exit(); + } + a1 = initrd.addr; + a2 = initrd.size; printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r", initrd.addr, (unsigned long)_initrd_start, initrd.size); - memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size); - } - - vmlinuz.addr = (unsigned long)_vmlinux_start; - vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); - vmlinux.addr = (unsigned long)(void *)-1; - vmlinux.size = PAGE_ALIGN(vmlinux_filesize); - vmlinux.memsize = vmlinux_memsize; - - claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */; - for(claim_addr = PROG_START; - claim_addr <= PROG_START * 8; - claim_addr += 0x100000) { -#ifdef DEBUG - printf(" trying: 0x%08lx\n\r", claim_addr); -#endif - vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0); - if ((void *)vmlinux.addr != (void *)-1) break; - } - if ((void *)vmlinux.addr == (void *)-1) { - printf("claim error, can't allocate kernel memory\n\r"); - exit(); + memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size); + printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr)); } - /* PPPBBB: should kernel always be gziped? */ + /* Eventually gunzip the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { + int len; avail_ram = scratch; begin_avail = avail_high = avail_ram; end_avail = scratch + sizeof(scratch); printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); + len = vmlinuz.size; gunzip((void *)vmlinux.addr, vmlinux.size, - (unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size); - printf("done %lu bytes\n\r", vmlinuz.size); - printf("%u bytes of heap consumed, max in use %u\n\r", + (unsigned char *)vmlinuz.addr, &len); + printf("done 0x%lx bytes\n\r", len); + printf("0x%x bytes of heap consumed, max in use 0x%x\n\r", (unsigned)(avail_high - begin_avail), heap_max); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); @@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr) flush_cache((void *)vmlinux.addr, vmlinux.memsize); - bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize); + if (a1) + printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr)); kernel_entry = (kernel_entry_t)vmlinux.addr; #ifdef DEBUG @@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr) " prom = 0x%lx,\n\r" " bi_recs = 0x%lx,\n\r", (unsigned long)kernel_entry, a1, a2, - (unsigned long)prom, (unsigned long)bi_recs); + (unsigned long)prom, NULL); #endif - kernel_entry( a1, a2, prom, bi_recs ); + kernel_entry( a1, a2, prom, NULL ); printf("Error: Linux kernel returned to zImage bootloader!\n\r"); exit(); } -static struct bi_record * -make_bi_recs(unsigned long addr) -{ - struct bi_record *bi_recs; - struct bi_record *rec; - - bi_recs = rec = bi_rec_init(addr); - - rec = bi_rec_alloc(rec, 2); - rec->tag = BI_FIRST; - /* rec->data[0] = ...; # Written below before return */ - /* rec->data[1] = ...; # Written below before return */ - - rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1); - rec->tag = BI_BOOTLOADER_ID; - sprintf( (char *)rec->data, "chrpboot"); - - rec = bi_rec_alloc(rec, 2); - rec->tag = BI_MACHTYPE; - rec->data[0] = PLATFORM_PSERIES; - rec->data[1] = 1; - - if ( initrd.size > 0 ) { - rec = bi_rec_alloc(rec, 2); - rec->tag = BI_INITRD; - rec->data[0] = initrd.addr; - rec->data[1] = initrd.size; - } - - if ( sysmap.size > 0 ) { - rec = bi_rec_alloc(rec, 2); - rec->tag = BI_SYSMAP; - rec->data[0] = (unsigned long)sysmap.addr; - rec->data[1] = (unsigned long)sysmap.size; - } - - rec = bi_rec_alloc(rec, 1); - rec->tag = BI_LAST; - rec->data[0] = (bi_rec_field)bi_recs; - - /* Save the _end_ address of the bi_rec's in the first bi_rec - * data field for easy access by the kernel. - */ - bi_recs->data[0] = (bi_rec_field)rec; - bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs; - - return bi_recs; -} - struct memchunk { unsigned int size; unsigned int pad; diff --git a/arch/ppc64/boot/zImage.lds b/arch/ppc64/boot/zImage.lds index 7070cd2f7..941ade38f 100644 --- a/arch/ppc64/boot/zImage.lds +++ b/arch/ppc64/boot/zImage.lds @@ -61,19 +61,9 @@ SECTIONS . = ALIGN(4096); _vmlinux_start = .; - .kernel:vmlinux : { *(.kernel:vmlinux) } + .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) } _vmlinux_end = .; - . = ALIGN(4096); - _dotconfig_start = .; - .kernel:.config : { *(.kernel:.config) } - _dotconfig_end = .; - - . = ALIGN(4096); - _sysmap_start = .; - .kernel:System.map : { *(.kernel:System.map) } - _sysmap_end = .; - . = ALIGN(4096); _initrd_start = .; .kernel:initrd : { *(.kernel:initrd) } diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig index 0485eed76..9cc01b5ba 100644 --- a/arch/ppc64/configs/g5_defconfig +++ b/arch/ppc64/configs/g5_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.9-rc3 +# Thu Oct 7 15:18:38 2004 # CONFIG_64BIT=y CONFIG_MMU=y @@ -16,11 +18,11 @@ CONFIG_FORCE_MAX_ZONEORDER=13 # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -32,6 +34,8 @@ CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -39,6 +43,8 @@ CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -50,18 +56,20 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_KMOD is not set CONFIG_STOP_MACHINE=y +CONFIG_SYSVIPC_COMPAT=y # # Platform support # # CONFIG_PPC_ISERIES is not set -CONFIG_PPC_PSERIES=y +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_PSERIES is not set +CONFIG_PPC_PMAC=y CONFIG_PPC=y CONFIG_PPC64=y CONFIG_PPC_OF=y CONFIG_ALTIVEC=y -CONFIG_PPC_PMAC=y -CONFIG_PMAC_DART=y +CONFIG_U3_DART=y CONFIG_PPC_PMAC64=y CONFIG_BOOTX_TEXT=y CONFIG_POWER4_ONLY=y @@ -69,8 +77,8 @@ CONFIG_IOMMU_VMERGE=y CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y CONFIG_NR_CPUS=2 -# CONFIG_HMT is not set -# CONFIG_DISCONTIGMEM is not set +# CONFIG_SCHED_SMT is not set +# CONFIG_PREEMPT is not set # CONFIG_PPC_RTAS is not set # CONFIG_LPARCFG is not set @@ -104,6 +112,8 @@ CONFIG_PROC_DEVICETREE=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set @@ -132,7 +142,8 @@ CONFIG_FW_LOADER=y CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y @@ -146,9 +157,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=y CONFIG_BLK_DEV_IDEFLOPPY=y @@ -170,7 +181,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -196,6 +206,7 @@ CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_IDEDMA_PMAC=y # CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -221,7 +232,6 @@ CONFIG_CHR_DEV_SG=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -235,23 +245,25 @@ CONFIG_SCSI_SPI_ATTRS=y # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set CONFIG_SCSI_SATA=y CONFIG_SCSI_SATA_SVW=y # CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set # CONFIG_SCSI_SATA_SIS is not set # CONFIG_SCSI_SATA_VIA is not set # CONFIG_SCSI_SATA_VITESSE is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set @@ -264,6 +276,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set @@ -277,7 +290,6 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_MESH is not set # CONFIG_SCSI_MAC53C94 is not set # @@ -288,11 +300,15 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=y # CONFIG_MD_RAID6 is not set # CONFIG_MD_MULTIPATH is not set CONFIG_BLK_DEV_DM=y # CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_ZERO is not set # # Fusion MPT device support @@ -332,6 +348,7 @@ CONFIG_IEEE1394_RAWIO=y # # I2O device support # +# CONFIG_I2O is not set # # Macintosh device drivers @@ -340,7 +357,6 @@ CONFIG_ADB=y CONFIG_ADB_PMU=y # CONFIG_PMAC_PBOOK is not set # CONFIG_PMAC_BACKLIGHT is not set -# CONFIG_MAC_SERIAL is not set # CONFIG_INPUT_ADBHID is not set CONFIG_THERM_PM72=y @@ -369,14 +385,13 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m +CONFIG_INET_TUNNEL=y # # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -384,6 +399,8 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=y +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set # CONFIG_IP_NF_FTP is not set # CONFIG_IP_NF_IRC is not set # CONFIG_IP_NF_TFTP is not set @@ -408,8 +425,15 @@ CONFIG_IP_NF_MATCH_HELPER=y CONFIG_IP_NF_MATCH_STATE=y CONFIG_IP_NF_MATCH_CONNTRACK=y CONFIG_IP_NF_MATCH_OWNER=y +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +# CONFIG_IP_NF_MATCH_SCTP is not set +# CONFIG_IP_NF_MATCH_COMMENT is not set CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_LOG=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_IP_NF_TARGET_TCPMSS=y CONFIG_IP_NF_NAT=y CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=y @@ -424,9 +448,7 @@ CONFIG_IP_NF_TARGET_ECN=y CONFIG_IP_NF_TARGET_DSCP=y CONFIG_IP_NF_TARGET_MARK=y CONFIG_IP_NF_TARGET_CLASSIFY=y -CONFIG_IP_NF_TARGET_LOG=y -CONFIG_IP_NF_TARGET_ULOG=y -CONFIG_IP_NF_TARGET_TCPMSS=y +# CONFIG_IP_NF_RAW is not set CONFIG_IP_NF_ARPTABLES=y CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y @@ -438,7 +460,9 @@ CONFIG_XFRM=y # # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set @@ -454,30 +478,33 @@ CONFIG_LLC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m # # ARCnet devices # # CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_MACE is not set -# CONFIG_BMAC is not set -# CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set CONFIG_SUNGEM=y # CONFIG_NET_VENDOR_3COM is not set @@ -509,57 +536,38 @@ CONFIG_TIGON3=m # # CONFIG_IXGB is not set # CONFIG_S2IO is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_IBMVETH is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set # # Token Ring devices # CONFIG_TR=y CONFIG_IBMOL=y -# CONFIG_IBMLS is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set # -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem @@ -598,6 +606,7 @@ CONFIG_SERIO=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -636,8 +645,6 @@ CONFIG_HW_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_HVC_CONSOLE=y -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -673,6 +680,7 @@ CONFIG_I2C_CHARDEV=y # CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -697,23 +705,29 @@ CONFIG_I2C_KEYWEST=y # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # # Hardware Sensors Chip support # # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set @@ -725,11 +739,17 @@ CONFIG_I2C_KEYWEST=y # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -748,6 +768,8 @@ CONFIG_I2C_KEYWEST=y # Graphics support # CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set CONFIG_FB_OF=y @@ -755,10 +777,12 @@ CONFIG_FB_OF=y # CONFIG_FB_PLATINUM is not set # CONFIG_FB_VALKYRIE is not set # CONFIG_FB_CT65550 is not set +# CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set -# CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set CONFIG_FB_RIVA=y +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y @@ -778,10 +802,8 @@ CONFIG_FB_RADEON_I2C=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_PCI_CONSOLE=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y @@ -811,6 +833,7 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set # # USB Host Controller Drivers @@ -829,6 +852,7 @@ CONFIG_USB_ACM=m CONFIG_USB_PRINTER=y CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y CONFIG_USB_STORAGE_ISD200=y @@ -853,6 +877,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -959,6 +984,7 @@ CONFIG_USB_EZUSB=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set # @@ -997,6 +1023,7 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -1004,6 +1031,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -1016,8 +1045,8 @@ CONFIG_SYSFS=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y # @@ -1030,7 +1059,7 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -1054,11 +1083,14 @@ CONFIG_EXPORTFS=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_POSIX is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -1076,7 +1108,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -1110,6 +1141,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -1135,13 +1167,16 @@ CONFIG_OPROFILE=y # Kernel hacking # CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUGGER is not set # CONFIG_PPCDBG is not set -# CONFIG_DEBUG_INFO is not set +CONFIG_IRQSTACKS=y +# CONFIG_SCHEDSTATS is not set # # Security options @@ -1159,6 +1194,7 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m @@ -1166,14 +1202,19 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +# CONFIG_CRYPTO_TEA is not set CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set CONFIG_CRYPTO_TEST=m # # Library routines # +CONFIG_CRC_CCITT=m CONFIG_CRC32=y -CONFIG_ZLIB_INFLATE=m +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig index 63ec73f75..84ae55bcc 100644 --- a/arch/ppc64/configs/iSeries_defconfig +++ b/arch/ppc64/configs/iSeries_defconfig @@ -16,17 +16,17 @@ CONFIG_FORCE_MAX_ZONEORDER=13 # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup # CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y @@ -34,6 +34,7 @@ CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -41,6 +42,8 @@ CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -62,10 +65,11 @@ CONFIG_PPC_ISERIES=y CONFIG_PPC=y CONFIG_PPC64=y # CONFIG_POWER4_ONLY is not set -# CONFIG_IOMMU_VMERGE is not set +CONFIG_IOMMU_VMERGE=y CONFIG_SMP=y CONFIG_NR_CPUS=32 # CONFIG_SCHED_SMT is not set +# CONFIG_PREEMPT is not set CONFIG_MSCHUNKS=y CONFIG_LPARCFG=y @@ -97,6 +101,8 @@ CONFIG_PCI_NAMES=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set @@ -125,7 +131,7 @@ CONFIG_FW_LOADER=m CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -168,22 +174,23 @@ CONFIG_SCSI_FC_ATTRS=y # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA 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_IPS is not set +CONFIG_SCSI_IBMVSCSI=m # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set @@ -209,11 +216,15 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=y -CONFIG_MD_RAID6=y -# CONFIG_MD_MULTIPATH is not set +CONFIG_MD_RAID6=m +CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # # Fusion MPT device support @@ -259,6 +270,7 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m +CONFIG_INET_TUNNEL=y # # IP: Virtual Server Configuration @@ -324,7 +336,13 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPFWADM=m -# CONFIG_IP_NF_RAW is not set +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +# CONFIG_IP_NF_CT_ACCT is not set +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -351,6 +369,7 @@ CONFIG_LLC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -379,7 +398,6 @@ CONFIG_TUN=m # CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -408,18 +426,32 @@ CONFIG_E100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # -# Gigabit Ethernet (1000/10000 Mbit) +# Ethernet (1000 Mbit) # -# CONFIG_NET_GIGE is not set +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # CONFIG_TR=y CONFIG_IBMOL=y -# CONFIG_IBMLS is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set @@ -508,10 +540,11 @@ CONFIG_SERIO_SERPORT=y # # Non-8250 serial port support # +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_ICOM=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -541,6 +574,11 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -592,8 +630,10 @@ CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -CONFIG_JFS_FS=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set @@ -616,6 +656,7 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -623,6 +664,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -663,19 +706,22 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y +CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y +CONFIG_EXPORTFS=m CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y +CONFIG_RPCSEC_GSS_SPKM3=m # CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -691,7 +737,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -714,7 +760,8 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -748,14 +795,16 @@ CONFIG_OPROFILE=y # Kernel hacking # CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUGGER is not set # CONFIG_PPCDBG is not set -# CONFIG_DEBUG_INFO is not set # CONFIG_IRQSTACKS is not set +# CONFIG_SCHEDSTATS is not set # # Security options @@ -773,6 +822,7 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WHIRLPOOL=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m @@ -780,16 +830,19 @@ CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_DEFLATE=m -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_TEST=m # # Library routines # +CONFIG_CRC_CCITT=m CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig index f5503873a..73981148d 100644 --- a/arch/ppc64/configs/pSeries_defconfig +++ b/arch/ppc64/configs/pSeries_defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.9-rc2 +# Thu Sep 23 16:45:05 2004 # CONFIG_64BIT=y CONFIG_MMU=y @@ -16,27 +18,35 @@ CONFIG_FORCE_MAX_ZONEORDER=13 # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -48,25 +58,31 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_KMOD is not set CONFIG_STOP_MACHINE=y +CONFIG_SYSVIPC_COMPAT=y # # Platform support # # CONFIG_PPC_ISERIES is not set +CONFIG_PPC_MULTIPLATFORM=y CONFIG_PPC_PSERIES=y +# CONFIG_PPC_PMAC is not set CONFIG_PPC=y CONFIG_PPC64=y CONFIG_PPC_OF=y CONFIG_ALTIVEC=y -# CONFIG_PPC_PMAC is not set +CONFIG_PPC_SPLPAR=y # CONFIG_BOOTX_TEXT is not set # CONFIG_POWER4_ONLY is not set -# CONFIG_IOMMU_VMERGE is not set +CONFIG_IOMMU_VMERGE=y CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y -CONFIG_NR_CPUS=32 +CONFIG_NR_CPUS=128 # CONFIG_HMT is not set -# CONFIG_DISCONTIGMEM is not set +CONFIG_DISCONTIGMEM=y +CONFIG_NUMA=y +CONFIG_SCHED_SMT=y +# CONFIG_PREEMPT is not set CONFIG_PPC_RTAS=y CONFIG_RTAS_FLASH=m CONFIG_SCANLOG=m @@ -81,6 +97,7 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y +CONFIG_HOTPLUG_CPU=y # # PCMCIA/CardBus support @@ -107,7 +124,9 @@ CONFIG_PROC_DEVICETREE=y # # Generic Driver Options # -CONFIG_FW_LOADER=m +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # @@ -127,7 +146,7 @@ CONFIG_FW_LOADER=m # # Block devices # -CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_FD=m # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -135,7 +154,8 @@ CONFIG_BLK_DEV_FD=y CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -149,9 +169,9 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -173,7 +193,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set CONFIG_BLK_DEV_AMD74XX=y @@ -194,6 +213,7 @@ CONFIG_BLK_DEV_AMD74XX=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set CONFIG_IDEDMA_AUTO=y @@ -219,7 +239,6 @@ CONFIG_CHR_DEV_SG=y # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -233,28 +252,32 @@ CONFIG_SCSI_FC_ATTRS=y # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA 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_IPS is not set +CONFIG_SCSI_IBMVSCSI=m # CONFIG_SCSI_INIA100 is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_IPR=y +# CONFIG_SCSI_IPR_TRACE is not set +# CONFIG_SCSI_IPR_DUMP is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set @@ -277,11 +300,15 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=y -CONFIG_MD_RAID6=y -# CONFIG_MD_MULTIPATH is not set +CONFIG_MD_RAID6=m +CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # # Fusion MPT device support @@ -296,6 +323,7 @@ CONFIG_DM_CRYPT=m # # I2O device support # +# CONFIG_I2O is not set # # Macintosh device drivers @@ -322,19 +350,17 @@ CONFIG_NET_IPIP=y # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -CONFIG_INET_ECN=y CONFIG_SYN_COOKIES=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m +CONFIG_INET_TUNNEL=y # # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -342,6 +368,8 @@ CONFIG_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m @@ -366,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -386,9 +420,8 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m @@ -400,10 +433,11 @@ CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set @@ -419,28 +453,35 @@ CONFIG_LLC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y # # Network testing # # CONFIG_NET_PKTGEN is not set +CONFIG_NETPOLL=y +CONFIG_NETPOLL_RX=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m # # ARCnet devices # # CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set CONFIG_NET_VENDOR_3COM=y @@ -452,6 +493,7 @@ CONFIG_VORTEX=y # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +CONFIG_IBMVETH=m CONFIG_NET_PCI=y CONFIG_PCNET32=y # CONFIG_AMD8111_ETH is not set @@ -471,6 +513,7 @@ CONFIG_E100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -484,7 +527,6 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set CONFIG_TIGON3=y @@ -493,59 +535,40 @@ CONFIG_TIGON3=y # CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_IBMVETH=m -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set +CONFIG_S2IO=m +# CONFIG_S2IO_NAPI is not set # # Token Ring devices # CONFIG_TR=y CONFIG_IBMOL=y -# CONFIG_IBMLS is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -CONFIG_NETCONSOLE=y # -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support +# Wireless LAN (non-hamradio) # -# CONFIG_IRDA is not set +# CONFIG_NET_RADIO is not set # -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set -CONFIG_NETPOLL=y -CONFIG_NETPOLL_RX=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=y # # ISDN subsystem @@ -584,6 +607,7 @@ CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -591,15 +615,17 @@ CONFIG_SERIO_I8042=y CONFIG_INPUT_KEYBOARD=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y -CONFIG_INPUT_PCSPKR=y +# CONFIG_INPUT_PCSPKR is not set # CONFIG_INPUT_UINPUT is not set # @@ -624,16 +650,12 @@ CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_PMACZILOG is not set +CONFIG_SERIAL_ICOM=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 CONFIG_HVC_CONSOLE=y - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +CONFIG_HVCS=m # # IPMI @@ -656,7 +678,7 @@ CONFIG_HVC_CONSOLE=y # CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=y -CONFIG_MAX_RAW_DEVS=256 +CONFIG_MAX_RAW_DEVS=1024 # # I2C support @@ -669,11 +691,13 @@ CONFIG_I2C=y # CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support # # CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set @@ -691,29 +715,51 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set # -# I2C Hardware Sensors Chip support +# Hardware Sensors Chip support # # CONFIG_I2C_SENSOR is not set # CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set + +# +# Other I2C Chip support +# +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set # CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -732,12 +778,14 @@ CONFIG_I2C_ALGOBIT=y # Graphics support # CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set CONFIG_FB_OF=y # CONFIG_FB_CT65550 is not set +# CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set -# CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set # CONFIG_FB_RIVA is not set CONFIG_FB_MATROX=y @@ -765,10 +813,8 @@ CONFIG_FB_RADEON_I2C=y # Console display driver support # # CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_PCI_CONSOLE=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y @@ -798,11 +844,14 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set # # USB Host Controller Drivers # CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_UHCI_HCD is not set @@ -814,6 +863,7 @@ CONFIG_USB_OHCI_HCD=y # CONFIG_USB_PRINTER is not set CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set @@ -834,7 +884,10 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_WACOM is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set # # USB Imaging devices @@ -881,6 +934,8 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set # @@ -905,7 +960,10 @@ CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set -CONFIG_JFS_FS=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set @@ -928,6 +986,7 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -935,6 +994,8 @@ CONFIG_UDF_FS=m CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -942,6 +1003,7 @@ CONFIG_VFAT_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set @@ -974,18 +1036,22 @@ CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y +CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y +CONFIG_EXPORTFS=m CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +CONFIG_RPCSEC_GSS_SPKM3=m # CONFIG_SMB_FS is not set CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1001,7 +1067,7 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -1024,7 +1090,8 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -1049,15 +1116,18 @@ CONFIG_OPROFILE=y # Kernel hacking # CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_PPCDBG is not set -# CONFIG_DEBUG_INFO is not set +CONFIG_IRQSTACKS=y +# CONFIG_SCHEDSTATS is not set # # Security options @@ -1071,24 +1141,31 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_WHIRLPOOL=m +CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_TEST=m # # Library routines # +CONFIG_CRC_CCITT=m CONFIG_CRC32=y +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c index 6f21bde21..c923a8157 100644 --- a/arch/ppc64/kernel/ItLpQueue.c +++ b/arch/ppc64/kernel/ItLpQueue.c @@ -25,7 +25,7 @@ static __inline__ int set_inUse( struct ItLpQueue * lpQueue ) __asm__ __volatile__("\n\ 1: lwarx %0,0,%2 \n\ - cmpi 0,%0,0 \n\ + cmpwi 0,%0,0 \n\ li %0,0 \n\ bne- 2f \n\ addi %0,%0,1 \n\ diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c index 73d919bf8..edd5860fb 100644 --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -6,16 +6,15 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include -#include -#include +#include +#include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index c5dd7e13b..2482c5c2c 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -3,35 +3,35 @@ # EXTRA_CFLAGS += -mno-minimal-toc -extra-y := head.o vmlinux.lds.s +extra-y := head.o vmlinux.lds obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ time.o process.o signal.o syscalls.o misc.o ptrace.o \ - align.o semaphore.o bitops.o stab.o pacaData.o \ + align.o semaphore.o bitops.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o rtc.o init_task.o \ lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ - iommu.o sysfs.o vio.o + iommu.o sysfs.o obj-$(CONFIG_PPC_OF) += of_device.o -pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ - iSeries_IoMmTable.o -pci-obj-$(CONFIG_PPC_PSERIES) += pci_dn.o pci_dma_direct.o +pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o +pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_dma_direct.o -obj-$(CONFIG_PCI) += pci.o pci_iommu.o $(pci-obj-y) +obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ - HvCall.o HvLpConfig.o LparData.o mf_proc.o \ + HvCall.o HvLpConfig.o LparData.o \ iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ iSeries_iommu.o +obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o + obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ - open_pic.o xics.o pSeries_htab.o rtas.o \ - chrp_setup.o i8259.o prom.o pSeries_iommu.o + eeh.o pSeries_nvram.o rtasd.o ras.o \ + xics.o rtas.o pSeries_setup.o pSeries_iommu.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o @@ -44,14 +44,20 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_BOOTX_TEXT) += btext.o obj-$(CONFIG_HVCS) += hvcserver.o +obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ - pmac_time.o pmac_nvram.o pmac_low_i2c.o \ - open_pic_u3.o -obj-$(CONFIG_PMAC_DART) += pmac_iommu.o + pmac_time.o pmac_nvram.o pmac_low_i2c.o + +obj-$(CONFIG_PPC_MAPLE) += maple_setup.o maple_pci.o maple_time.o + +obj-$(CONFIG_U3_DART) += u3_iommu.o ifdef CONFIG_SMP obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o +obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o +obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o +obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o endif obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index f19f76379..8d0aa07dc 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -22,18 +22,17 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -58,6 +57,7 @@ int main(void) DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); + DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); #ifdef CONFIG_ALTIVEC DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); @@ -93,35 +93,25 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); - DEFINE(PACASLBR3, offsetof(struct paca_struct, slb_r3)); #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs)); #endif /* CONFIG_HUGETLB_PAGE */ DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); - DEFINE(PACAPROFENABLED, offsetof(struct paca_struct, prof_enabled)); - DEFINE(PACAPROFLEN, offsetof(struct paca_struct, prof_len)); - DEFINE(PACAPROFSHIFT, offsetof(struct paca_struct, prof_shift)); - DEFINE(PACAPROFBUFFER, offsetof(struct paca_struct, prof_buffer)); - DEFINE(PACAPROFSTEXT, offsetof(struct paca_struct, prof_stext)); DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); + DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(LPPACASRR0, offsetof(struct ItLpPaca, xSavedSrr0)); DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1)); DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt)); DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt)); - DEFINE(LPQCUREVENTPTR, offsetof(struct ItLpQueue, xSlicCurEventPtr)); - DEFINE(LPQOVERFLOW, offsetof(struct ItLpQueue, xPlicOverflowIntPending)); - DEFINE(LPEVENTFLAGS, offsetof(struct HvLpEvent, xFlags)); - DEFINE(PROMENTRY, offsetof(struct prom_t, entry)); /* RTAS */ DEFINE(RTASBASE, offsetof(struct rtas_t, base)); DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); - DEFINE(RTASSIZE, offsetof(struct rtas_t, size)); /* Interrupt register frame */ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); @@ -148,10 +138,6 @@ int main(void) DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); - DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20])); - DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21])); - DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22])); - DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23])); /* * Note: these symbols include _ because they overlap with special * register names diff --git a/arch/ppc64/kernel/bitops.c b/arch/ppc64/kernel/bitops.c index 6b24b0219..ae329e8b4 100644 --- a/arch/ppc64/kernel/bitops.c +++ b/arch/ppc64/kernel/bitops.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c index 33e10865d..c53f079e9 100644 --- a/arch/ppc64/kernel/btext.c +++ b/arch/ppc64/kernel/btext.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -36,6 +36,11 @@ static int g_loc_Y; static int g_max_loc_X; static int g_max_loc_Y; +static int dispDeviceRowBytes; +static int dispDeviceDepth; +static int dispDeviceRect[4]; +static unsigned char *dispDeviceBase, *logicalDisplayBase; + unsigned long disp_BAT[2] __initdata = {0, 0}; #define cmapsz (16*256) @@ -45,30 +50,6 @@ static unsigned char vga_font[cmapsz]; int boot_text_mapped; int force_printk_to_btext = 0; -boot_infos_t disp_bi; - -/* This function will enable the early boot text when doing OF booting. This - * way, xmon output should work too - */ -void __init btext_setup_display(int width, int height, int depth, int pitch, - unsigned long address) -{ - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(&disp_bi); - - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = width / 8; - RELOC(g_max_loc_Y) = height / 16; - bi->logicalDisplayBase = (unsigned char *)address; - bi->dispDeviceBase = (unsigned char *)address; - bi->dispDeviceRowBytes = pitch; - bi->dispDeviceDepth = depth; - bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; - RELOC(boot_text_mapped) = 1; -} /* Here's a small text engine to use during early boot * or for debugging purposes @@ -84,34 +65,84 @@ void __init btext_setup_display(int width, int height, int depth, int pitch, void map_boot_text(void) { unsigned long base, offset, size; - boot_infos_t *bi = &disp_bi; unsigned char *vbase; /* By default, we are no longer mapped */ boot_text_mapped = 0; - if (bi->dispDeviceBase == 0) + if (dispDeviceBase == 0) return; - base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL; - offset = ((unsigned long) bi->dispDeviceBase) - base; - size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset - + bi->dispDeviceRect[0]; + base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) dispDeviceBase) - base; + size = dispDeviceRowBytes * dispDeviceRect[3] + offset + + dispDeviceRect[0]; vbase = __ioremap(base, size, _PAGE_NO_CACHE); if (vbase == 0) return; - bi->logicalDisplayBase = vbase + offset; + logicalDisplayBase = vbase + offset; boot_text_mapped = 1; } +int btext_initialize(struct device_node *np) +{ + unsigned int width, height, depth, pitch; + unsigned long address = 0; + u32 *prop; + + prop = (u32 *)get_property(np, "width", NULL); + if (prop == NULL) + return -EINVAL; + width = *prop; + prop = (u32 *)get_property(np, "height", NULL); + if (prop == NULL) + return -EINVAL; + height = *prop; + prop = (u32 *)get_property(np, "depth", NULL); + if (prop == NULL) + return -EINVAL; + depth = *prop; + pitch = width * ((depth + 7) / 8); + prop = (u32 *)get_property(np, "linebytes", NULL); + if (prop) + pitch = *prop; + if (pitch == 1) + pitch = 0x1000; + prop = (u32 *)get_property(np, "address", NULL); + if (prop) + address = *prop; + + /* FIXME: Add support for PCI reg properties */ + + if (address == 0) + return -EINVAL; + + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; + logicalDisplayBase = (unsigned char *)address; + dispDeviceBase = (unsigned char *)address; + dispDeviceRowBytes = pitch; + dispDeviceDepth = depth; + dispDeviceRect[0] = dispDeviceRect[1] = 0; + dispDeviceRect[2] = width; + dispDeviceRect[3] = height; + + map_boot_text(); + + return 0; +} + + /* Calc the base address of a given point (x,y) */ -static unsigned char * calc_base(boot_infos_t *bi, int x, int y) +static unsigned char * calc_base(int x, int y) { unsigned char *base; - base = bi->logicalDisplayBase; + base = logicalDisplayBase; if (base == 0) - base = bi->dispDeviceBase; - base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); - base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + base = dispDeviceBase; + base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); + base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; return base; } @@ -119,24 +150,22 @@ static unsigned char * calc_base(boot_infos_t *bi, int x, int y) void btext_update_display(unsigned long phys, int width, int height, int depth, int pitch) { - boot_infos_t *bi = &disp_bi; - - if (bi->dispDeviceBase == 0) + if (dispDeviceBase == 0) return; /* check it's the same frame buffer (within 256MB) */ - if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000) + if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000) return; - bi->dispDeviceBase = (__u8 *) phys; - bi->dispDeviceRect[0] = 0; - bi->dispDeviceRect[1] = 0; - bi->dispDeviceRect[2] = width; - bi->dispDeviceRect[3] = height; - bi->dispDeviceDepth = depth; - bi->dispDeviceRowBytes = pitch; + dispDeviceBase = (__u8 *) phys; + dispDeviceRect[0] = 0; + dispDeviceRect[1] = 0; + dispDeviceRect[2] = width; + dispDeviceRect[3] = height; + dispDeviceDepth = depth; + dispDeviceRowBytes = pitch; if (boot_text_mapped) { - iounmap(bi->logicalDisplayBase); + iounmap(logicalDisplayBase); boot_text_mapped = 0; } map_boot_text(); @@ -148,108 +177,101 @@ void btext_update_display(unsigned long phys, int width, int height, void btext_clearscreen(void) { - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(&disp_bi); - unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 3; + unsigned long *base = (unsigned long *)calc_base(0, 0); + unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * + (dispDeviceDepth >> 3)) >> 3; int i,j; - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) { unsigned long *ptr = base; for(j=width; j; --j) *(ptr++) = 0; - base += (bi->dispDeviceRowBytes >> 3); + base += (dispDeviceRowBytes >> 3); } } #ifndef NO_SCROLL static void scrollscreen(void) { - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(&disp_bi); - unsigned long *src = (unsigned long *)calc_base(bi,0,16); - unsigned long *dst = (unsigned long *)calc_base(bi,0,0); - unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * - (bi->dispDeviceDepth >> 3)) >> 3; + unsigned long *src = (unsigned long *)calc_base(0,16); + unsigned long *dst = (unsigned long *)calc_base(0,0); + unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * + (dispDeviceDepth >> 3)) >> 3; int i,j; - for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) { unsigned long *src_ptr = src; unsigned long *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = *(src_ptr++); - src += (bi->dispDeviceRowBytes >> 3); - dst += (bi->dispDeviceRowBytes >> 3); + src += (dispDeviceRowBytes >> 3); + dst += (dispDeviceRowBytes >> 3); } for (i=0; i<16; i++) { unsigned long *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = 0; - dst += (bi->dispDeviceRowBytes >> 3); + dst += (dispDeviceRowBytes >> 3); } } #endif /* ndef NO_SCROLL */ void btext_drawchar(char c) { - unsigned long offset = reloc_offset(); int cline = 0; #ifdef NO_SCROLL int x; #endif - if (!RELOC(boot_text_mapped)) + if (!boot_text_mapped) return; switch (c) { case '\b': - if (RELOC(g_loc_X) > 0) - --RELOC(g_loc_X); + if (g_loc_X > 0) + --g_loc_X; break; case '\t': - RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; + g_loc_X = (g_loc_X & -8) + 8; break; case '\r': - RELOC(g_loc_X) = 0; + g_loc_X = 0; break; case '\n': - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; + g_loc_X = 0; + g_loc_Y++; cline = 1; break; default: - draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); + draw_byte(c, g_loc_X++, g_loc_Y); } - if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y)++; + if (g_loc_X >= g_max_loc_X) { + g_loc_X = 0; + g_loc_Y++; cline = 1; } #ifndef NO_SCROLL - while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { + while (g_loc_Y >= g_max_loc_Y) { scrollscreen(); - RELOC(g_loc_Y)--; + g_loc_Y--; } #else /* wrap around from bottom to top of screen so we don't waste time scrolling each line. -- paulus. */ - if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) - RELOC(g_loc_Y) = 0; + if (g_loc_Y >= g_max_loc_Y) + g_loc_Y = 0; if (cline) { - for (x = 0; x < RELOC(g_max_loc_X); ++x) - draw_byte(' ', x, RELOC(g_loc_Y)); + for (x = 0; x < g_max_loc_X; ++x) + draw_byte(' ', x, g_loc_Y); } #endif } void btext_drawstring(const char *c) { - unsigned long offset = reloc_offset(); - - if (!RELOC(boot_text_mapped)) + if (!boot_text_mapped) return; while (*c) btext_drawchar(*c++); @@ -257,10 +279,9 @@ void btext_drawstring(const char *c) void btext_drawhex(unsigned long v) { - unsigned long offset = reloc_offset(); - char *hex_table = RELOC("0123456789abcdef"); + char *hex_table = "0123456789abcdef"; - if (!RELOC(boot_text_mapped)) + if (!boot_text_mapped) return; btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); @@ -283,14 +304,11 @@ void btext_drawhex(unsigned long v) static void draw_byte(unsigned char c, long locX, long locY) { - unsigned long offset = reloc_offset(); - boot_infos_t* bi = PTRRELOC(&disp_bi); - unsigned char *base = calc_base(bi, locX << 3, locY << 4); - unsigned char *font = PTRRELOC(&vga_font[((unsigned int)c) * 16]); - int rb = bi->dispDeviceRowBytes; - -#if 0 - switch(bi->dispDeviceDepth) { + unsigned char *base = calc_base(locX << 3, locY << 4); + unsigned char *font = &vga_font[((unsigned int)c) * 16]; + int rb = dispDeviceRowBytes; + + switch(dispDeviceDepth) { case 24: case 32: draw_byte_32(font, (unsigned int *)base, rb); @@ -303,17 +321,6 @@ static void draw_byte(unsigned char c, long locX, long locY) draw_byte_8(font, (unsigned int *)base, rb); break; } -#else - if(bi->dispDeviceDepth == 24 || - bi->dispDeviceDepth == 32) { - draw_byte_32(font, (unsigned int *)base, rb); - } else if(bi->dispDeviceDepth == 15 || - bi->dispDeviceDepth == 16) { - draw_byte_16(font, (unsigned int *)base, rb); - } else if(bi->dispDeviceDepth == 8) { - draw_byte_8(font, (unsigned int *)base, rb); - } -#endif } static unsigned int expand_bits_8[16] = { @@ -369,8 +376,7 @@ static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) int l, bits; int fg = 0xFFFFFFFFUL; int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned int *eb = PTRRELOC((int *)expand_bits_16); + unsigned int *eb = (int *)expand_bits_16; for (l = 0; l < 16; ++l) { @@ -388,8 +394,7 @@ static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) int l, bits; int fg = 0x0F0F0F0FUL; int bg = 0x00000000UL; - unsigned long offset = reloc_offset(); - unsigned int *eb = PTRRELOC((int *)expand_bits_8); + unsigned int *eb = (int *)expand_bits_8; for (l = 0; l < 16; ++l) { diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S index 0e009850f..3bd951820 100644 --- a/arch/ppc64/kernel/cpu_setup_power4.S +++ b/arch/ppc64/kernel/cpu_setup_power4.S @@ -156,6 +156,15 @@ _GLOBAL(__restore_cpu_setup) cror 4*cr0+eq,4*cr0+eq,4*cr1+eq bne 1f + /* Before accessing memory, we make sure rm_ci is clear */ + li r0,0 + mfspr r3,SPRN_HID4 + rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */ + sync + mtspr SPRN_HID4,r3 + isync + sync + /* Clear interrupt prefix */ li r0,0 sync diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c index 68d517fa4..c08725182 100644 --- a/arch/ppc64/kernel/dma.c +++ b/arch/ppc64/kernel/dma.c @@ -17,8 +17,10 @@ int dma_supported(struct device *dev, u64 mask) { if (dev->bus == &pci_bus_type) return pci_dma_supported(to_pci_dev(dev), mask); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_dma_supported(to_vio_dev(dev), mask); +#endif /* CONFIG_IBMVIO */ BUG(); return 0; } @@ -28,8 +30,10 @@ int dma_set_mask(struct device *dev, u64 dma_mask) { if (dev->bus == &pci_bus_type) return pci_set_dma_mask(to_pci_dev(dev), dma_mask); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_set_dma_mask(to_vio_dev(dev), dma_mask); +#endif /* CONFIG_IBMVIO */ BUG(); return 0; } @@ -40,8 +44,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size, { if (dev->bus == &pci_bus_type) return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle); +#endif /* CONFIG_IBMVIO */ BUG(); return NULL; } @@ -52,8 +58,10 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, { if (dev->bus == &pci_bus_type) pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); +#ifdef CONFIG_IBMVIO else if (dev->bus == &vio_bus_type) vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle); +#endif /* CONFIG_IBMVIO */ else BUG(); } @@ -64,8 +72,10 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, { if (dev->bus == &pci_bus_type) return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction); +#endif /* CONFIG_IBMVIO */ BUG(); return (dma_addr_t)0; } @@ -76,8 +86,10 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, { if (dev->bus == &pci_bus_type) pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); +#ifdef CONFIG_IBMVIO else if (dev->bus == &vio_bus_type) vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction); +#endif /* CONFIG_IBMVIO */ else BUG(); } @@ -89,8 +101,10 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, { if (dev->bus == &pci_bus_type) return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_map_page(to_vio_dev(dev), page, offset, size, direction); +#endif /* CONFIG_IBMVIO */ BUG(); return (dma_addr_t)0; } @@ -101,8 +115,10 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, { if (dev->bus == &pci_bus_type) pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); +#ifdef CONFIG_IBMVIO else if (dev->bus == &vio_bus_type) vio_unmap_page(to_vio_dev(dev), dma_address, size, direction); +#endif /* CONFIG_IBMVIO */ else BUG(); } @@ -113,8 +129,10 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, { if (dev->bus == &pci_bus_type) return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); +#ifdef CONFIG_IBMVIO if (dev->bus == &vio_bus_type) return vio_map_sg(to_vio_dev(dev), sg, nents, direction); +#endif /* CONFIG_IBMVIO */ BUG(); return 0; } @@ -125,8 +143,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, { if (dev->bus == &pci_bus_type) pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); +#ifdef CONFIG_IBMVIO else if (dev->bus == &vio_bus_type) vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction); +#endif /* CONFIG_IBMVIO */ else BUG(); } diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index 5fdcce2db..63e8185d7 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -17,29 +17,79 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include +#include +#include +#include #include #include -#include -#include #include -#include #include -#include -#include -#include +#include +#include #include #include -#include #include +#include #include "pci.h" #undef DEBUG +/** Overview: + * EEH, or "Extended Error Handling" is a PCI bridge technology for + * dealing with PCI bus errors that can't be dealt with within the + * usual PCI framework, except by check-stopping the CPU. Systems + * that are designed for high-availability/reliability cannot afford + * to crash due to a "mere" PCI error, thus the need for EEH. + * An EEH-capable bridge operates by converting a detected error + * into a "slot freeze", taking the PCI adapter off-line, making + * the slot behave, from the OS'es point of view, as if the slot + * were "empty": all reads return 0xff's and all writes are silently + * ignored. EEH slot isolation events can be triggered by parity + * errors on the address or data busses (e.g. during posted writes), + * which in turn might be caused by dust, vibration, humidity, + * radioactivity or plain-old failed hardware. + * + * Note, however, that one of the leading causes of EEH slot + * freeze events are buggy device drivers, buggy device microcode, + * or buggy device hardware. This is because any attempt by the + * device to bus-master data to a memory address that is not + * assigned to the device will trigger a slot freeze. (The idea + * is to prevent devices-gone-wild from corrupting system memory). + * Buggy hardware/drivers will have a miserable time co-existing + * with EEH. + * + * Ideally, a PCI device driver, when suspecting that an isolation + * event has occured (e.g. by reading 0xff's), will then ask EEH + * whether this is the case, and then take appropriate steps to + * reset the PCI slot, the PCI device, and then resume operations. + * However, until that day, the checking is done here, with the + * eeh_check_failure() routine embedded in the MMIO macros. If + * the slot is found to be isolated, an "EEH Event" is synthesized + * and sent out for processing. + */ + +/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ #define BUID_HI(buid) ((buid) >> 32) #define BUID_LO(buid) ((buid) & 0xffffffff) -#define CONFIG_ADDR(busno, devfn) \ - (((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8) + +/* EEH event workqueue setup. */ +static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED; +LIST_HEAD(eeh_eventlist); +static void eeh_event_handler(void *); +DECLARE_WORK(eeh_event_wq, eeh_event_handler, NULL); + +static struct notifier_block *eeh_notifier_chain; + +/* + * If a device driver keeps reading an MMIO register in an interrupt + * handler after a slot isolation event has occurred, we assume it + * is broken and panic. This sets the threshold for how many read + * attempts we allow before panicking. + */ +#define EEH_MAX_FAILS 1000 +static atomic_t eeh_fail_count; /* RTAS tokens */ static int ibm_set_eeh_option; @@ -48,9 +98,6 @@ static int ibm_read_slot_reset_state; static int ibm_slot_error_detail; static int eeh_subsystem_enabled; -#define EEH_MAX_OPTS 4096 -static char *eeh_opts; -static int eeh_opts_last; /* Buffer for reporting slot-error-detail rtas calls */ static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; @@ -61,17 +108,15 @@ static int eeh_error_buf_size; static DEFINE_PER_CPU(unsigned long, total_mmio_ffs); static DEFINE_PER_CPU(unsigned long, false_positives); static DEFINE_PER_CPU(unsigned long, ignored_failures); - -static int eeh_check_opts_config(struct device_node *dn, int class_code, - int vendor_id, int device_id, - int default_state); +static DEFINE_PER_CPU(unsigned long, slot_resets); /** * The pci address cache subsystem. This subsystem places * PCI device address resources into a red-black tree, sorted * according to the address range, so that given only an i/o * address, the corresponding PCI device can be **quickly** - * found. + * found. It is safe to perform an address lookup in an interrupt + * context; this ability is an important feature. * * Currently, the only customer of this code is the EEH subsystem; * thus, this code has been somewhat tailored to suit EEH better. @@ -209,6 +254,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) { struct device_node *dn; int i; + int inserted = 0; dn = pci_device_to_OF_node(dev); if (!dn) { @@ -242,7 +288,12 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) if (start == 0 || ~start == 0 || end == 0 || ~end == 0) continue; pci_addr_cache_insert(dev, start, end, flags); + inserted = 1; } + + /* If there was nothing to add, the cache has no reference... */ + if (!inserted) + pci_dev_put(dev); } /** @@ -265,6 +316,7 @@ void pci_addr_cache_insert_device(struct pci_dev *dev) static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) { struct rb_node *n; + int removed = 0; restart: n = rb_first(&pci_io_addr_cache_root.rb_root); @@ -274,6 +326,7 @@ restart: if (piar->pcidev == dev) { rb_erase(n, &pci_io_addr_cache_root.rb_root); + removed = 1; kfree(piar); goto restart; } @@ -281,7 +334,8 @@ restart: } /* The cache no longer holds its reference to this device... */ - pci_dev_put(dev); + if (removed) + pci_dev_put(dev); } /** @@ -331,80 +385,168 @@ void __init pci_addr_cache_build(void) #endif } +/* --------------------------------------------------------------- */ +/* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */ + /** - * eeh_token_to_phys - convert EEH address token to phys address - * @token i/o token, should be address in the form 0xA.... + * eeh_register_notifier - Register to find out about EEH events. + * @nb: notifier block to callback on events + */ +int eeh_register_notifier(struct notifier_block *nb) +{ + return notifier_chain_register(&eeh_notifier_chain, nb); +} + +/** + * eeh_unregister_notifier - Unregister to an EEH event notifier. + * @nb: notifier block to callback on events + */ +int eeh_unregister_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&eeh_notifier_chain, nb); +} + +/** + * eeh_panic - call panic() for an eeh event that cannot be handled. + * The philosophy of this routine is that it is better to panic and + * halt the OS than it is to risk possible data corruption by + * oblivious device drivers that don't know better. + * + * @dev pci device that had an eeh event + * @reset_state current reset state of the device slot + */ +static void eeh_panic(struct pci_dev *dev, int reset_state) +{ + /* + * XXX We should create a separate sysctl for this. + * + * Since the panic_on_oops sysctl is used to halt the system + * in light of potential corruption, we can use it here. + */ + if (panic_on_oops) + panic("EEH: MMIO failure (%d) on device:%s %s\n", reset_state, + pci_name(dev), pci_pretty_name(dev)); + else { + __get_cpu_var(ignored_failures)++; + printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s %s\n", + reset_state, pci_name(dev), pci_pretty_name(dev)); + } +} + +/** + * eeh_event_handler - dispatch EEH events. The detection of a frozen + * slot can occur inside an interrupt, where it can be hard to do + * anything about it. The goal of this routine is to pull these + * detection events out of the context of the interrupt handler, and + * re-dispatch them for processing at a later time in a normal context. * - * Converts EEH address tokens into physical addresses. Note that - * ths routine does *not* convert I/O BAR addresses (which start - * with 0xE...) to phys addresses! + * @dummy - unused + */ +static void eeh_event_handler(void *dummy) +{ + unsigned long flags; + struct eeh_event *event; + + while (1) { + spin_lock_irqsave(&eeh_eventlist_lock, flags); + event = NULL; + if (!list_empty(&eeh_eventlist)) { + event = list_entry(eeh_eventlist.next, struct eeh_event, list); + list_del(&event->list); + } + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); + if (event == NULL) + break; + + printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device " + "%s %s\n", event->reset_state, + pci_name(event->dev), pci_pretty_name(event->dev)); + + atomic_set(&eeh_fail_count, 0); + notifier_call_chain (&eeh_notifier_chain, + EEH_NOTIFY_FREEZE, event); + + __get_cpu_var(slot_resets)++; + + pci_dev_put(event->dev); + kfree(event); + } +} + +/** + * eeh_token_to_phys - convert EEH address token to phys address + * @token i/o token, should be address in the form 0xE.... */ -static unsigned long eeh_token_to_phys(unsigned long token) +static inline unsigned long eeh_token_to_phys(unsigned long token) { pte_t *ptep; - unsigned long pa, vaddr; + unsigned long pa; - if (REGION_ID(token) == EEH_REGION_ID) - vaddr = IO_TOKEN_TO_ADDR(token); - else + ptep = find_linux_pte(ioremap_mm.pgd, token); + if (!ptep) return token; - - ptep = find_linux_pte(ioremap_mm.pgd, vaddr); pa = pte_pfn(*ptep) << PAGE_SHIFT; - return pa | (vaddr & (PAGE_SIZE-1)); + return pa | (token & (PAGE_SIZE-1)); } /** - * eeh_check_failure - check if all 1's data is due to EEH slot freeze - * @token i/o token, should be address in the form 0xA.... - * @val value, should be all 1's (XXX why do we need this arg??) + * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze + * @dn device node + * @dev pci device, if known * - * Check for an eeh failure at the given token address. - * The given value has been read and it should be 1's (0xff, 0xffff or - * 0xffffffff). + * Check for an EEH failure for the given device node. Call this + * routine if the result of a read was all 0xff's and you want to + * find out if this is due to an EEH slot freeze. This routine + * will query firmware for the EEH status. * - * Probe to determine if an error actually occurred. If not return val. - * Otherwise panic. + * Returns 0 if there has not been an EEH error; otherwise returns + * a non-zero value and queues up a solt isolation event notification. * - * Note this routine might be called in an interrupt context ... + * It is safe to call this routine in an interrupt context. */ -unsigned long eeh_check_failure(void *token, unsigned long val) +int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) { - unsigned long addr; - struct pci_dev *dev; - struct device_node *dn; int ret; int rets[2]; unsigned long flags; + int rc, reset_state; + struct eeh_event *event; __get_cpu_var(total_mmio_ffs)++; if (!eeh_subsystem_enabled) - return val; + return 0; - /* Finding the phys addr + pci device; this is pretty quick. */ - addr = eeh_token_to_phys((unsigned long)token); - dev = pci_get_device_by_addr(addr); - if (!dev) - return val; - - dn = pci_device_to_OF_node(dev); - if (!dn) { - pci_dev_put(dev); - return val; - } + if (!dn) + return 0; /* Access to IO BARs might get this far and still not want checking. */ if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || dn->eeh_mode & EEH_MODE_NOCHECK) { - pci_dev_put(dev); - return val; + return 0; } if (!dn->eeh_config_addr) { - pci_dev_put(dev); - return val; + return 0; + } + + /* + * If we already have a pending isolation event for this + * slot, we know it's bad already, we don't need to check... + */ + if (dn->eeh_mode & EEH_MODE_ISOLATED) { + atomic_inc(&eeh_fail_count); + if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) { + /* re-read the slot reset state */ + rets[0] = -1; + rtas_call(ibm_read_slot_reset_state, 3, 3, rets, + dn->eeh_config_addr, + BUID_HI(dn->phb->buid), + BUID_LO(dn->phb->buid)); + eeh_panic(dev, rets[0]); + } + return 0; } /* @@ -418,54 +560,96 @@ unsigned long eeh_check_failure(void *token, unsigned long val) dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); - if (ret == 0 && rets[1] == 1 && rets[0] >= 2) { - int log_event; - - spin_lock_irqsave(&slot_errbuf_lock, flags); - memset(slot_errbuf, 0, eeh_error_buf_size); - - log_event = rtas_call(ibm_slot_error_detail, - 8, 1, NULL, dn->eeh_config_addr, - BUID_HI(dn->phb->buid), - BUID_LO(dn->phb->buid), NULL, 0, - virt_to_phys(slot_errbuf), - eeh_error_buf_size, - 2 /* Permanent Error */); - - if (log_event == 0) - log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, - 1 /* Fatal */); - - spin_unlock_irqrestore(&slot_errbuf_lock, flags); - - /* - * XXX We should create a separate sysctl for this. - * - * Since the panic_on_oops sysctl is used to halt - * the system in light of potential corruption, we - * can use it here. - */ - if (panic_on_oops) { - panic("EEH: MMIO failure (%d) on device:%s %s\n", - rets[0], pci_name(dev), pci_pretty_name(dev)); - } else { - __get_cpu_var(ignored_failures)++; - printk(KERN_INFO "EEH: MMIO failure (%d) on device:%s %s\n", - rets[0], pci_name(dev), pci_pretty_name(dev)); - } - } else { + if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) { __get_cpu_var(false_positives)++; + return 0; } + /* prevent repeated reports of this failure */ + dn->eeh_mode |= EEH_MODE_ISOLATED; + + reset_state = rets[0]; + + spin_lock_irqsave(&slot_errbuf_lock, flags); + memset(slot_errbuf, 0, eeh_error_buf_size); + + rc = rtas_call(ibm_slot_error_detail, + 8, 1, NULL, dn->eeh_config_addr, + BUID_HI(dn->phb->buid), + BUID_LO(dn->phb->buid), NULL, 0, + virt_to_phys(slot_errbuf), + eeh_error_buf_size, + 1 /* Temporary Error */); + + if (rc == 0) + log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); + spin_unlock_irqrestore(&slot_errbuf_lock, flags); + + printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n", + rets[0], dn->name, dn->full_name); + event = kmalloc(sizeof(*event), GFP_ATOMIC); + if (event == NULL) { + eeh_panic(dev, reset_state); + return 1; + } + + event->dev = dev; + event->dn = dn; + event->reset_state = reset_state; + + /* We may or may not be called in an interrupt context */ + spin_lock_irqsave(&eeh_eventlist_lock, flags); + list_add(&event->list, &eeh_eventlist); + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); + + /* Most EEH events are due to device driver bugs. Having + * a stack trace will help the device-driver authors figure + * out what happened. So print that out. */ + dump_stack(); + schedule_work(&eeh_event_wq); + + return 0; +} + +EXPORT_SYMBOL(eeh_dn_check_failure); + +/** + * eeh_check_failure - check if all 1's data is due to EEH slot freeze + * @token i/o token, should be address in the form 0xA.... + * @val value, should be all 1's (XXX why do we need this arg??) + * + * Check for an eeh failure at the given token address. + * Check for an EEH failure at the given token address. Call this + * routine if the result of a read was all 0xff's and you want to + * find out if this is due to an EEH slot freeze event. This routine + * will query firmware for the EEH status. + * + * Note this routine is safe to call in an interrupt context. + */ +unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) +{ + unsigned long addr; + struct pci_dev *dev; + struct device_node *dn; + + /* Finding the phys addr + pci device; this is pretty quick. */ + addr = eeh_token_to_phys((unsigned long __force) token); + dev = pci_get_device_by_addr(addr); + if (!dev) + return val; + + dn = pci_device_to_OF_node(dev); + eeh_dn_check_failure (dn, dev); + pci_dev_put(dev); return val; } + EXPORT_SYMBOL(eeh_check_failure); struct eeh_early_enable_info { unsigned int buid_hi; unsigned int buid_lo; - int force_off; }; /* Enable eeh for the given device node. */ @@ -507,18 +691,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data) if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY) enable = 0; - if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id, - enable)) { - if (enable) { - printk(KERN_WARNING "EEH: %s user requested to run " - "without EEH checking.\n", dn->full_name); - enable = 0; - } - } - - if (!enable || info->force_off) { + if (!enable) dn->eeh_mode |= EEH_MODE_NOCHECK; - } /* Ok... see if this device supports EEH. Some do, some don't, * and the only way to find out is to check each and every one. */ @@ -572,15 +746,12 @@ void __init eeh_init(void) { struct device_node *phb, *np; struct eeh_early_enable_info info; - char *eeh_force_off = strstr(saved_command_line, "eeh-force-off"); init_pci_config_tokens(); np = of_find_node_by_path("/rtas"); - if (np == NULL) { - printk(KERN_WARNING "EEH: RTAS not found !\n"); + if (np == NULL) return; - } ibm_set_eeh_option = rtas_token("ibm,set-eeh-option"); ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); @@ -600,13 +771,6 @@ void __init eeh_init(void) eeh_error_buf_size = RTAS_ERROR_LOG_MAX; } - info.force_off = 0; - if (eeh_force_off) { - printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error " - "Handling is user disabled\n"); - info.force_off = 1; - } - /* Enable EEH for all adapters. Note that eeh requires buid's */ for (phb = of_find_node_by_name(NULL, "pci"); phb; phb = of_find_node_by_name(phb, "pci")) { @@ -621,11 +785,10 @@ void __init eeh_init(void) traverse_pci_devices(phb, early_enable_eeh, &info); } - if (eeh_subsystem_enabled) { + if (eeh_subsystem_enabled) printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n"); - } else { - printk(KERN_WARNING "EEH: disabled PCI Enhanced I/O Error Handling\n"); - } + else + printk(KERN_WARNING "EEH: No capable adapters found\n"); } /** @@ -701,48 +864,17 @@ void eeh_remove_device(struct pci_dev *dev) } EXPORT_SYMBOL(eeh_remove_device); -/* - * If EEH is implemented, find the PCI device using given phys addr - * and check to see if eeh failure checking is disabled. - * Remap the addr (trivially) to the EEH region if EEH checking enabled. - * For addresses not known to PCI the vaddr is simply returned unchanged. - */ -void *eeh_ioremap(unsigned long addr, void *vaddr) -{ - struct pci_dev *dev; - struct device_node *dn; - - if (!eeh_subsystem_enabled) - return vaddr; - - dev = pci_get_device_by_addr(addr); - if (!dev) - return vaddr; - - dn = pci_device_to_OF_node(dev); - if (!dn) { - pci_dev_put(dev); - return vaddr; - } - - if (dn->eeh_mode & EEH_MODE_NOCHECK) { - pci_dev_put(dev); - return vaddr; - } - - pci_dev_put(dev); - return (void *)IO_ADDR_TO_TOKEN(vaddr); -} - static int proc_eeh_show(struct seq_file *m, void *v) { unsigned int cpu; unsigned long ffs = 0, positives = 0, failures = 0; + unsigned long resets = 0; for_each_cpu(cpu) { ffs += per_cpu(total_mmio_ffs, cpu); positives += per_cpu(false_positives, cpu); failures += per_cpu(ignored_failures, cpu); + resets += per_cpu(slot_resets, cpu); } if (0 == eeh_subsystem_enabled) { @@ -752,8 +884,11 @@ static int proc_eeh_show(struct seq_file *m, void *v) seq_printf(m, "EEH Subsystem is enabled\n"); seq_printf(m, "eeh_total_mmio_ffs=%ld\n" "eeh_false_positives=%ld\n" - "eeh_ignored_failures=%ld\n", - ffs, positives, failures); + "eeh_ignored_failures=%ld\n" + "eeh_slot_resets=%ld\n" + "eeh_fail_count=%d\n", + ffs, positives, failures, resets, + eeh_fail_count.counter); } return 0; @@ -784,129 +919,3 @@ static int __init eeh_init_proc(void) return 0; } __initcall(eeh_init_proc); - -/* - * Test if "dev" should be configured on or off. - * This processes the options literally from left to right. - * This lets the user specify stupid combinations of options, - * but at least the result should be very predictable. - */ -static int eeh_check_opts_config(struct device_node *dn, - int class_code, int vendor_id, int device_id, - int default_state) -{ - char devname[32], classname[32]; - char *strs[8], *s; - int nstrs, i; - int ret = default_state; - - /* Build list of strings to match */ - nstrs = 0; - s = (char *)get_property(dn, "ibm,loc-code", NULL); - if (s) - strs[nstrs++] = s; - sprintf(devname, "dev%04x:%04x", vendor_id, device_id); - strs[nstrs++] = devname; - sprintf(classname, "class%04x", class_code); - strs[nstrs++] = classname; - strs[nstrs++] = ""; /* yes, this matches the empty string */ - - /* - * Now see if any string matches the eeh_opts list. - * The eeh_opts list entries start with + or -. - */ - for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last)); - s += strlen(s)+1) { - for (i = 0; i < nstrs; i++) { - if (strcasecmp(strs[i], s+1) == 0) { - ret = (strs[i][0] == '+') ? 1 : 0; - } - } - } - return ret; -} - -/* - * Handle kernel eeh-on & eeh-off cmd line options for eeh. - * - * We support: - * eeh-off=loc1,loc2,loc3... - * - * and this option can be repeated so - * eeh-off=loc1,loc2 eeh-off=loc3 - * is the same as eeh-off=loc1,loc2,loc3 - * - * loc is an IBM location code that can be found in a manual or - * via openfirmware (or the Hardware Management Console). - * - * We also support these additional "loc" values: - * - * dev#:# vendor:device id in hex (e.g. dev1022:2000) - * class# class id in hex (e.g. class0200) - * - * If no location code is specified all devices are assumed - * so eeh-off means eeh by default is off. - */ - -/* - * This is implemented as a null separated list of strings. - * Each string looks like this: "+X" or "-X" - * where X is a loc code, vendor:device, class (as shown above) - * or empty which is used to indicate all. - * - * We interpret this option string list so that it will literally - * behave left-to-right even if some combinations don't make sense. - */ -static int __init eeh_parm(char *str, int state) -{ - char *s, *cur, *curend; - - if (!eeh_opts) { - eeh_opts = alloc_bootmem(EEH_MAX_OPTS); - eeh_opts[eeh_opts_last++] = '+'; /* default */ - eeh_opts[eeh_opts_last++] = '\0'; - } - if (*str == '\0') { - eeh_opts[eeh_opts_last++] = state ? '+' : '-'; - eeh_opts[eeh_opts_last++] = '\0'; - return 1; - } - if (*str == '=') - str++; - for (s = str; s && *s != '\0'; s = curend) { - cur = s; - /* ignore empties. Don't treat as "all-on" or "all-off" */ - while (*cur == ',') - cur++; - curend = strchr(cur, ','); - if (!curend) - curend = cur + strlen(cur); - if (*cur) { - int curlen = curend-cur; - if (eeh_opts_last + curlen > EEH_MAX_OPTS-2) { - printk(KERN_WARNING "EEH: sorry...too many " - "eeh cmd line options\n"); - return 1; - } - eeh_opts[eeh_opts_last++] = state ? '+' : '-'; - strncpy(eeh_opts+eeh_opts_last, cur, curlen); - eeh_opts_last += curlen; - eeh_opts[eeh_opts_last++] = '\0'; - } - } - - return 1; -} - -static int __init eehoff_parm(char *str) -{ - return eeh_parm(str, 0); -} - -static int __init eehon_parm(char *str) -{ - return eeh_parm(str, 1); -} - -__setup("eeh-off", eehoff_parm); -__setup("eeh-on", eehon_parm); diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index 2d48d24e7..74e7d48bc 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S @@ -122,7 +122,7 @@ SystemCall_common: andi. r11,r10,_TIF_SYSCALL_T_OR_A bne- syscall_dotrace syscall_dotrace_cont: - cmpli 0,r0,NR_syscalls + cmpldi 0,r0,NR_syscalls bge- syscall_enosys system_call: /* label this so stack traces look sane */ @@ -162,7 +162,7 @@ syscall_error_cont: /* check for syscall tracing or audit */ ld r9,TI_FLAGS(r12) - andi. r0,r9,_TIF_SYSCALL_T_OR_A + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) bne- syscall_exit_trace syscall_exit_trace_cont: @@ -204,7 +204,7 @@ syscall_enosys: syscall_error: lbz r11,TI_SC_NOERR(r12) - cmpi 0,r11,0 + cmpwi 0,r11,0 bne- syscall_error_cont neg r3,r3 oris r5,r5,0x1000 /* Set SO bit in CR */ @@ -265,16 +265,21 @@ _GLOBAL(save_nvgprs) _GLOBAL(ppc32_sigsuspend) bl .save_nvgprs bl .sys32_sigsuspend - b syscall_exit + b 70f _GLOBAL(ppc64_rt_sigsuspend) bl .save_nvgprs bl .sys_rt_sigsuspend - b syscall_exit + b 70f _GLOBAL(ppc32_rt_sigsuspend) bl .save_nvgprs bl .sys32_rt_sigsuspend + /* If sigsuspend() returns zero, we are going into a signal handler */ +70: cmpdi 0,r3,0 + beq .ret_from_except + /* If it returned -EINTR, we need to return via syscall_exit to set + the SO bit in cr0 and potentially stop for ptrace. */ b syscall_exit _GLOBAL(ppc_fork) @@ -317,7 +322,7 @@ _GLOBAL(ppc64_rt_sigreturn) blt syscall_exit clrrdi r4,r1,THREAD_SHIFT ld r4,TI_FLAGS(r4) - andi. r4,r4,_TIF_SYSCALL_T_OR_A + andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) beq+ 81f bl .do_syscall_trace_leave 81: b .ret_from_except @@ -393,9 +398,17 @@ BEGIN_FTR_SECTION cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ cror eq,4*cr1+eq,eq beq 2f /* if yes, don't slbie it */ - oris r6,r6,0x0800 /* set C (class) bit */ - slbie r6 - slbie r6 /* Workaround POWER5 < DD2.1 issue */ + oris r0,r6,0x0800 /* set C (class) bit */ + + /* Bolt in the new stack SLB entry */ + ld r7,KSP_VSID(r4) /* Get new stack's VSID */ + oris r6,r6,(SLB_ESID_V)@h + ori r6,r6,(SLB_NUM_BOLTED-1)@l + slbie r0 + slbie r0 /* Workaround POWER5 < DD2.1 issue */ + slbmte r7,r6 + isync + 2: END_FTR_SECTION_IFSET(CPU_FTR_SLB) clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ @@ -489,10 +502,11 @@ restore: li r3,0 stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ + ori r10,r10,MSR_EE mtmsrd r10 /* hard-enable again */ addi r3,r1,STACK_FRAME_OVERHEAD bl .do_IRQ - b .ret_from_except /* loop back and handle more */ + b .ret_from_except_lite /* loop back and handle more */ 4: stb r5,PACAPROCENABLED(r13) #endif @@ -566,6 +580,7 @@ do_work: li r0,1 stb r0,PACAPROCENABLED(r13) #endif + ori r10,r10,MSR_EE mtmsrd r10,1 /* reenable interrupts */ bl .schedule mfmsr r10 @@ -583,6 +598,7 @@ do_work: user_work: #endif /* Enable interrupts */ + ori r10,r10,MSR_EE mtmsrd r10,1 andi. r0,r4,_TIF_NEED_RESCHED @@ -738,6 +754,10 @@ _STATIC(rtas_restore_regs) mtlr r0 blr /* return to caller */ +#endif /* CONFIG_PPC_PSERIES */ + +#ifdef CONFIG_PPC_MULTIPLATFORM + _GLOBAL(enter_prom) mflr r0 std r0,16(r1) @@ -769,11 +789,8 @@ _GLOBAL(enter_prom) std r11,_MSR(r1) /* Get the PROM entrypoint */ - bl .reloc_offset - LOADADDR(r12,prom) - sub r12,r12,r3 - ld r12,PROMENTRY(r12) - mtlr r12 + ld r0,GPR4(r1) + mtlr r0 /* Switch MSR to 32 bits mode */ @@ -826,4 +843,4 @@ _GLOBAL(enter_prom) mtlr r0 blr -#endif /* defined(CONFIG_PPC_PSERIES) */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index a5d67f599..b56d09ef2 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -26,6 +26,7 @@ #define SECONDARY_PROCESSORS #include +#include #include #include #include @@ -83,13 +84,14 @@ .text .globl _stext _stext: -#ifdef CONFIG_PPC_PSERIES -_STATIC(__start) +#ifdef CONFIG_PPC_MULTIPLATFORM +_GLOBAL(__start) /* NOP this out unconditionally */ BEGIN_FTR_SECTION - b .__start_initialization_pSeries + b .__start_initialization_multiplatform END_FTR_SECTION(0, 1) -#endif +#endif /* CONFIG_PPC_MULTIPLATFORM */ + /* Catch branch to 0 in real mode */ trap #ifdef CONFIG_PPC_ISERIES @@ -117,7 +119,8 @@ embedded_sysmap_start: .globl embedded_sysmap_end embedded_sysmap_end: .llong 0 -#else + +#else /* CONFIG_PPC_ISERIES */ /* Secondary processors spin on this value until it goes to 1. */ .globl __secondary_hold_spinloop @@ -199,6 +202,7 @@ exception_marker: #define EX_R12 24 #define EX_R13 32 #define EX_SRR0 40 +#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ #define EX_DAR 48 #define EX_LR 48 /* SLB miss saves LR, but not DAR */ #define EX_DSISR 56 @@ -322,36 +326,11 @@ label##_Iseries: \ HMT_MEDIUM; \ mtspr SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ - lbz r10,PACAPROFENABLED(r13); \ - cmpwi r10,0; \ - bne- label##_Iseries_profile; \ -label##_Iseries_prof_ret: \ lbz r10,PACAPROCENABLED(r13); \ cmpwi 0,r10,0; \ beq- label##_Iseries_masked; \ EXCEPTION_PROLOG_ISERIES_2; \ b label##_common; \ -label##_Iseries_profile: \ - ld r12,PACALPPACA+LPPACASRR1(r13); \ - andi. r12,r12,MSR_PR; /* Test if in kernel */ \ - bne label##_Iseries_prof_ret; \ - ld r11,PACALPPACA+LPPACASRR0(r13); \ - ld r12,PACAPROFSTEXT(r13); /* _stext */ \ - subf r11,r12,r11; /* offset into kernel */ \ - lwz r12,PACAPROFSHIFT(r13); \ - srd r11,r11,r12; \ - lwz r12,PACAPROFLEN(r13); /* profile table length - 1 */ \ - cmpd r11,r12; /* off end? */ \ - ble 1f; \ - mr r11,r12; /* force into last entry */ \ -1: sldi r11,r11,2; /* convert to offset */ \ - ld r12,PACAPROFBUFFER(r13);/* profile buffer */ \ - add r12,r12,r11; \ -2: lwarx r11,0,r12; /* atomically increment */ \ - addi r11,r11,1; \ - stwcx. r11,0,r12; \ - bne- 2b; \ - b label##_Iseries_prof_ret #ifdef DO_SOFT_DISABLE #define DISABLE_INTS \ @@ -446,21 +425,13 @@ DataAccessSLB_Pseries: std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACASLBR3(r13) + std r3,PACA_EXSLB+EX_R3(r13) mfspr r9,SPRG1 std r9,PACA_EXSLB+EX_R13(r13) mfcr r9 - clrrdi r12,r13,32 /* get high part of &label */ - mfmsr r10 - mfspr r11,SRR0 /* save SRR0 */ - ori r12,r12,(.do_slb_miss)@l - ori r10,r10,MSR_IR|MSR_DR /* DON'T set RI for SLB miss */ - mtspr SRR0,r12 mfspr r12,SRR1 /* and SRR1 */ - mtspr SRR1,r10 mfspr r3,DAR - rfid - b . /* prevent speculative execution */ + b .do_slb_miss /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x400, InstructionAccess) @@ -474,21 +445,13 @@ InstructionAccessSLB_Pseries: std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACASLBR3(r13) + std r3,PACA_EXSLB+EX_R3(r13) mfspr r9,SPRG1 std r9,PACA_EXSLB+EX_R13(r13) mfcr r9 - clrrdi r12,r13,32 /* get high part of &label */ - mfmsr r10 - mfspr r11,SRR0 /* save SRR0 */ - ori r12,r12,(.do_slb_miss)@l - ori r10,r10,MSR_IR|MSR_DR /* DON'T set RI for SLB miss */ - mtspr SRR0,r12 mfspr r12,SRR1 /* and SRR1 */ - mtspr SRR1,r10 - mr r3,r11 /* SRR0 is faulting address */ - rfid - b . /* prevent speculative execution */ + mfspr r3,SRR0 /* SRR0 is faulting address */ + b .do_slb_miss /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt) STD_EXCEPTION_PSERIES(0x600, Alignment) @@ -580,7 +543,7 @@ __end_systemcfg: * VSID generation algorithm. See include/asm/mmu_context.h. */ - .llong 1 /* # ESIDs to be mapped by hypervisor */ + .llong 2 /* # ESIDs to be mapped by hypervisor */ .llong 1 /* # memory ranges to be mapped by hypervisor */ .llong STAB0_PAGE /* Page # of segment table within load area */ .llong 0 /* Reserved */ @@ -588,11 +551,15 @@ __end_systemcfg: .llong 0 /* Reserved */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ - .llong 0x0c00000000 /* ESID to map (Kernel at EA = 0xC000000000000000) */ - .llong 0x06a99b4b14 /* VSID to map (Kernel at VA = 0x6a99b4b140000000) */ + .llong (KERNELBASE>>SID_SHIFT) + .llong 0x408f92c94 /* KERNELBASE VSID */ + /* We have to list the bolted VMALLOC segment here, too, so that it + * will be restored on shared processor switch */ + .llong (VMALLOCBASE>>SID_SHIFT) + .llong 0xf09b89af5 /* VMALLOCBASE VSID */ .llong 8192 /* # pages to map (32 MB) */ .llong 0 /* Offset from start of loadarea to start of map */ - .llong 0x0006a99b4b140000 /* VPN of first page to map */ + .llong 0x408f92c940000 /* VPN of first page to map */ . = 0x6100 @@ -630,8 +597,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) DataAccessSLB_Iseries: mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) - std r3,PACASLBR3(r13) - ld r11,PACALPPACA+LPPACASRR0(r13) + std r3,PACA_EXSLB+EX_R3(r13) ld r12,PACALPPACA+LPPACASRR1(r13) mfspr r3,DAR b .do_slb_miss @@ -642,10 +608,9 @@ DataAccessSLB_Iseries: InstructionAccessSLB_Iseries: mtspr SPRG1,r13 /* save r13 */ EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) - std r3,PACASLBR3(r13) - ld r11,PACALPPACA+LPPACASRR0(r13) + std r3,PACA_EXSLB+EX_R3(r13) ld r12,PACALPPACA+LPPACASRR1(r13) - mr r3,r11 + ld r3,PACALPPACA+LPPACASRR0(r13) b .do_slb_miss MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt) @@ -1033,6 +998,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) * interrupts if necessary. */ beq .ret_from_except_lite + /* For a hash failure, we don't bother re-enabling interrupts */ + ble- 12f + /* * hash_page couldn't handle it, set soft interrupt enable back * to what it was before the trap. Note that .local_irq_restore @@ -1043,6 +1011,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) b 11f #else beq fast_exception_return /* Return from exception on success */ + ble- 12f /* Failure return from hash_page */ + /* fall through */ #endif @@ -1062,6 +1032,15 @@ _GLOBAL(handle_page_fault) bl .bad_page_fault b .ret_from_except +/* We have a page fault that hash_page could handle but HV refused + * the PTE insertion + */ +12: bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD + lwz r4,_DAR(r1) + bl .low_hash_fault + b .ret_from_except + /* here we have a segment miss */ _GLOBAL(do_ste_alloc) bl .ste_allocate /* try to insert stab entry */ @@ -1088,18 +1067,9 @@ _GLOBAL(do_stab_bolted) rldimi r10,r11,7,52 /* r10 = first ste of the group */ /* Calculate VSID */ - /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ - rldic r11,r11,15,36 - ori r11,r11,0xc - - /* VSID_RANDOMIZER */ - li r9,9 - sldi r9,r9,32 - oris r9,r9,58231 - ori r9,r9,39831 - - mulld r9,r11,r9 - rldic r9,r9,12,16 /* r9 = vsid << 12 */ + /* This is a kernel address, so protovsid = ESID */ + ASM_VSID_SCRAMBLE(r11, r9) + rldic r9,r11,12,16 /* r9 = vsid << 12 */ /* Search the primary group for a free entry */ 1: ld r11,0(r10) /* Test valid bit of the current ste */ @@ -1176,7 +1146,6 @@ _GLOBAL(do_slb_miss) mflr r10 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ bl .slb_allocate /* handle it */ @@ -1184,9 +1153,11 @@ _GLOBAL(do_slb_miss) /* All done -- return from exception. */ ld r10,PACA_EXSLB+EX_LR(r13) - ld r3,PACASLBR3(r13) + ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ - ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ +#ifdef CONFIG_PPC_ISERIES + ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ +#endif /* CONFIG_PPC_ISERIES */ mtlr r10 @@ -1199,8 +1170,10 @@ _GLOBAL(do_slb_miss) mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ .machine pop +#ifdef CONFIG_PPC_ISERIES mtspr SRR0,r11 mtspr SRR1,r12 +#endif /* CONFIG_PPC_ISERIES */ ld r9,PACA_EXSLB+EX_R9(r13) ld r10,PACA_EXSLB+EX_R10(r13) ld r11,PACA_EXSLB+EX_R11(r13) @@ -1220,23 +1193,39 @@ unrecov_slb: /* * On pSeries, secondary processors spin in the following code. - * At entry, r3 = this processor's number (in Linux terms, not hardware). + * At entry, r3 = this processor's number (physical cpu id) */ _GLOBAL(pseries_secondary_smp_init) + mr r24,r3 + /* turn on 64-bit mode */ bl .enable_64b_mode isync - /* Set up a paca value for this processor. */ - LOADADDR(r24, paca) /* Get base vaddr of paca array */ - mulli r13,r3,PACA_SIZE /* Calculate vaddr of right paca */ - add r13,r13,r24 /* for this processor. */ - - mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ - mr r24,r3 /* __secondary_start needs cpu# */ + /* Copy some CPU settings from CPU 0 */ + bl .__restore_cpu_setup -1: - HMT_LOW + /* Set up a paca value for this processor. Since we have the + * physical cpu id in r3, we need to search the pacas to find + * which logical id maps to our physical one. + */ + LOADADDR(r13, paca) /* Get base vaddr of paca array */ + li r5,0 /* logical cpu id */ +1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ + cmpw r6,r24 /* Compare to our id */ + beq 2f + addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ + addi r5,r5,1 + cmpwi r5,NR_CPUS + blt 1b + +99: HMT_LOW /* Couldn't find our CPU id */ + b 99b + +2: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ + /* From now on, r24 is expected to be logica cpuid */ + mr r24,r5 +3: HMT_LOW lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ /* start. */ sync @@ -1251,14 +1240,12 @@ _GLOBAL(pseries_secondary_smp_init) bne .__secondary_start #endif #endif - b 1b /* Loop until told to go */ + b 3b /* Loop until told to go */ #ifdef CONFIG_PPC_ISERIES -_GLOBAL(__start_initialization_iSeries) +_STATIC(__start_initialization_iSeries) /* Clear out the BSS */ LOADADDR(r11,__bss_stop) - LOADADDR(r8,__bss_start) - sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ @@ -1295,32 +1282,73 @@ _GLOBAL(__start_initialization_iSeries) ld r6,PACA(r4) /* Get the base paca pointer */ ld r4,PACASTABVIRT(r6) - bl .iSeries_fixup_klimit + bl .iSeries_early_setup /* relocation is on at this point */ b .start_here_common -#endif +#endif /* CONFIG_PPC_ISERIES */ -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM -_STATIC(mmu_off) +_STATIC(__mmu_off) mfmsr r3 andi. r0,r3,MSR_IR|MSR_DR beqlr andc r3,r3,r0 - mtspr SRR0,r4 - mtspr SRR1,r3 + mtspr SPRN_SRR0,r4 + mtspr SPRN_SRR1,r3 sync rfid b . /* prevent speculative execution */ -_GLOBAL(__start_initialization_pSeries) - mr r31,r3 /* save parameters */ + + +/* + * Here is our main kernel entry point. We support currently 2 kind of entries + * depending on the value of r5. + * + * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content + * in r3...r7 + * + * r5 == NULL -> kexec style entry. r3 is a physical pointer to the + * DT block, r4 is a physical pointer to the kernel itself + * + */ +_GLOBAL(__start_initialization_multiplatform) + /* + * Are we booted from a PROM Of-type client-interface ? + */ + cmpldi cr0,r5,0 + bne .__boot_from_prom /* yes -> prom */ + + /* Save parameters */ + mr r31,r3 + mr r30,r4 + + /* Make sure we are running in 64 bits mode */ + bl .enable_64b_mode + + /* Setup some critical 970 SPRs before switching MMU off */ + bl .__970_cpu_preinit + + /* cpu # */ + li r24,0 + + /* Switch off MMU if not already */ + LOADADDR(r4, .__after_prom_start - KERNELBASE) + add r4,r4,r30 + bl .__mmu_off + b .__after_prom_start + +_STATIC(__boot_from_prom) + /* Save parameters */ + mr r31,r3 mr r30,r4 mr r29,r5 mr r28,r6 mr r27,r7 + /* Make sure we are running in 64 bits mode */ bl .enable_64b_mode /* put a relocation offset into r3 */ @@ -1333,7 +1361,7 @@ _GLOBAL(__start_initialization_pSeries) /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 - /* Save parameters */ + /* Restore parameters */ mr r3,r31 mr r4,r30 mr r5,r29 @@ -1342,17 +1370,8 @@ _GLOBAL(__start_initialization_pSeries) /* Do all of the interaction with OF client interface */ bl .prom_init - mr r23,r3 /* Save phys address we are running at */ - - /* Setup some critical 970 SPRs before switching MMU off */ - bl .__970_cpu_preinit - - li r24,0 /* cpu # */ - - /* Switch off MMU if not already */ - LOADADDR(r4, .__after_prom_start - KERNELBASE) - add r4,r4,r23 - bl .mmu_off + /* We never return */ + trap /* * At this point, r3 contains the physical address we are running at, @@ -1378,7 +1397,7 @@ _STATIC(__after_prom_start) li r3,0 /* target addr */ - // XXX FIXME: Use phys returned by OF (r23) + // XXX FIXME: Use phys returned by OF (r30) sub r4,r27,r26 /* source addr */ /* current address of _start */ /* i.e. where we are running */ @@ -1403,8 +1422,9 @@ _STATIC(__after_prom_start) ld r5,0(r5) /* get the value of klimit */ sub r5,r5,r27 bl .copy_and_flush /* copy the rest */ - b .start_here_pSeries -#endif + b .start_here_multiplatform + +#endif /* CONFIG_PPC_MULTIPLATFORM */ /* * Copy routine used to copy the kernel to start at physical address 0 @@ -1609,6 +1629,7 @@ _STATIC(load_up_altivec) li r10,THREAD_VSCR stw r4,THREAD_USED_VR(r5) lvx vr0,r10,r5 + mtvscr vr0 REST_32VRS(0,r4,r5) #ifndef CONFIG_SMP /* Update last_task_used_math to 'current' */ @@ -1823,15 +1844,33 @@ _GLOBAL(enable_64b_mode) isync blr -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM /* * This is where the main kernel code starts. */ -_STATIC(start_here_pSeries) +_STATIC(start_here_multiplatform) /* get a new offset, now that the kernel has moved. */ bl .reloc_offset mr r26,r3 + /* Clear out the BSS. It may have been done in prom_init, + * already but that's irrelevant since prom_init will soon + * be detached from the kernel completely. Besides, we need + * to clear it now for kexec-style entry. + */ + LOADADDR(r11,__bss_stop) + LOADADDR(r8,__bss_start) + sub r11,r11,r8 /* bss size */ + addi r11,r11,7 /* round up to an even double word */ + rldicl. r11,r11,61,3 /* shift right by 3 */ + beq 4f + addi r8,r8,-8 + li r0,0 + mtctr r11 /* zero this many doublewords */ +3: stdu r0,8(r8) + bdnz 3b +4: + mfmsr r6 ori r6,r6,MSR_RI mtmsrd r6 /* RI on */ @@ -1864,19 +1903,6 @@ _STATIC(start_here_pSeries) 91: #endif -#ifdef CONFIG_SMP - /* All secondary cpus are now spinning on a common - * spinloop, release them all now so they can start - * to spin on their individual paca spinloops. - * For non SMP kernels, the secondary cpus never - * get out of the common spinloop. - */ - li r3,1 - LOADADDR(r5,__secondary_hold_spinloop) - tophys(r4,r5) - std r3,0(r4) -#endif - /* The following gets the stack and TOC set up with the regs */ /* pointing to the real addr of the kernel stack. This is */ /* all done to support the C function call below which sets */ @@ -1891,7 +1917,7 @@ _STATIC(start_here_pSeries) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - /* set up the TOC (physical address) */ + /* set up the TOC (physical address) */ LOADADDR(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1904,8 +1930,17 @@ _STATIC(start_here_pSeries) mr r5,r26 bl .identify_cpu - /* Get the pointer to the segment table which is used by */ - /* stab_initialize */ + /* Save some low level config HIDs of CPU0 to be copied to + * other CPUs later on, or used for suspend/resume + */ + bl .__save_cpu_setup + sync + + /* Setup a valid physical PACA pointer in SPRG3 for early_setup + * note that boot_cpuid can always be 0 nowadays since there is + * nowhere it can be initialized differently before we reach this + * code + */ LOADADDR(r27, boot_cpuid) sub r27,r27,r26 lwz r27,0(r27) @@ -1914,12 +1949,18 @@ _STATIC(start_here_pSeries) mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ sub r13,r13,r26 /* convert to physical addr */ - mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ - ld r3,PACASTABREAL(r13) - ori r4,r3,1 /* turn on valid bit */ + /* Do very early kernel initializations, including initial hash table, + * stab and slb setup before we turn on relocation. */ + + /* Restore parameters passed from prom_init/kexec */ + mr r3,r31 + bl .early_setup + /* set the ASR */ + ld r3,PACASTABREAL(r13) + ori r4,r3,1 /* turn on valid bit */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR @@ -1938,13 +1979,7 @@ _STATIC(start_here_pSeries) 98: /* !(rpa hypervisor) || !(star) */ mtasr r4 /* set the stab location */ 99: - mfspr r6,SPRG3 - ld r3,PACASTABREAL(r6) /* restore r3 for stab_initialize */ - - /* Initialize an initial memory mapping and turn on relocation. */ - bl .stab_initialize - bl .htab_initialize - + /* Set SDR1 (hash table pointer) */ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ lwz r3,PLATFORM(r3) /* r3 = platform flags */ /* Test if bit 0 is set (LPAR bit) */ @@ -1961,7 +1996,7 @@ _STATIC(start_here_pSeries) mtspr SRR1,r4 rfid b . /* prevent speculative execution */ -#endif /* CONFIG_PPC_PSERIES */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ /* This is where all platforms converge execution */ _STATIC(start_here_common) @@ -2009,13 +2044,6 @@ _STATIC(start_here_common) ld r2,PACATOC(r13) std r1,PACAKSAVE(r13) - /* Restore the parms passed in from the bootloader. */ - mr r3,r31 - mr r4,r30 - mr r5,r29 - mr r6,r28 - mr r7,r27 - bl .setup_system /* Load up the kernel context */ @@ -2105,6 +2133,22 @@ _GLOBAL(hmt_start_secondary) blr #endif +#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) +_GLOBAL(smp_release_cpus) + /* All secondary cpus are spinning on a common + * spinloop, release them all now so they can start + * to spin on their individual paca spinloops. + * For non SMP kernels, the secondary cpus never + * get out of the common spinloop. + */ + li r3,1 + LOADADDR(r5,__secondary_hold_spinloop) + std r3,0(r5) + sync + blr +#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */ + + /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the data segment, diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c index dedefb305..c72fb8ffe 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/ppc64/kernel/hvconsole.c @@ -1,6 +1,10 @@ /* * hvconsole.c * Copyright (C) 2004 Hollis Blanchard, IBM Corporation + * Copyright (C) 2004 IBM Corporation + * + * Additional Author(s): + * Ryan S. Arnold * * LPAR console support. * @@ -22,14 +26,22 @@ #include #include #include -#include #include +#include -int hvc_get_chars(int index, char *buf, int count) +/** + * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper + * @vtermno: The vtermno or unit_address of the adapter from which to fetch the + * data. + * @buf: The character buffer into which to put the character data fetched from + * firmware. + * @count: not used? + */ +int hvc_get_chars(uint32_t vtermno, char *buf, int count) { unsigned long got; - if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got, + if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got, (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) { /* * Work around a HV bug where it gives us a null @@ -53,40 +65,56 @@ int hvc_get_chars(int index, char *buf, int count) EXPORT_SYMBOL(hvc_get_chars); -int hvc_put_chars(int index, const char *buf, int count) +/** + * hvc_put_chars: send characters to firmware for denoted vterm adapter + * @vtermno: The vtermno or unit_address of the adapter from which the data + * originated. + * @buf: The character buffer that contains the character data to send to + * firmware. + * @count: Send this number of characters. + */ +int hvc_put_chars(uint32_t vtermno, const char *buf, int count) { unsigned long *lbuf = (unsigned long *) buf; long ret; - ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0], + ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], lbuf[1]); if (ret == H_Success) return count; if (ret == H_Busy) return 0; - return -1; + return -EIO; } EXPORT_SYMBOL(hvc_put_chars); -/* return the number of client vterms present */ -/* XXX this requires an interface change to handle multiple discontiguous - * vterms */ -int hvc_count(int *start_termno) +/* + * We hope/assume that the first vty found corresponds to the first console + * device. + */ +int hvc_find_vtys(void) { struct device_node *vty; int num_found = 0; - /* consider only the first vty node. - * we should _always_ be able to find one. */ - vty = of_find_node_by_name(NULL, "vty"); - if (vty && device_is_compatible(vty, "hvterm1")) { - u32 *termno = (u32 *)get_property(vty, "reg", NULL); + for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; + vty = of_find_node_by_name(vty, "vty")) { + uint32_t *vtermno; + + /* We have statically defined space for only a certain number of + * console adapters. */ + if (num_found >= MAX_NR_HVC_CONSOLES) + break; - if (termno && start_termno) - *start_termno = *termno; - num_found = 1; - of_node_put(vty); + vtermno = (uint32_t *)get_property(vty, "reg", NULL); + if (!vtermno) + continue; + + if (device_is_compatible(vty, "hvterm1")) { + hvc_instantiate(*vtermno, num_found); + ++num_found; + } } return num_found; diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c index fbe445ec0..bde8f42da 100644 --- a/arch/ppc64/kernel/hvcserver.c +++ b/arch/ppc64/kernel/hvcserver.c @@ -61,14 +61,21 @@ int hvcs_convert(long to_convert) } } +/** + * hvcs_free_partner_info - free pi allocated by hvcs_get_partner_info + * @head: list_head pointer for an allocated list of partner info structs to + * free. + * + * This function is used to free the partner info list that was returned by + * calling hvcs_get_partner_info(). + */ int hvcs_free_partner_info(struct list_head *head) { struct hvcs_partner_info *pi; struct list_head *element; - if (!head) { + if (!head) return -EINVAL; - } while (!list_empty(head)) { element = head->next; @@ -82,7 +89,7 @@ int hvcs_free_partner_info(struct list_head *head) EXPORT_SYMBOL(hvcs_free_partner_info); /* Helper function for hvcs_get_partner_info */ -int hvcs_next_partner(unsigned int unit_address, +int hvcs_next_partner(uint32_t unit_address, unsigned long last_p_partition_ID, unsigned long last_p_unit_address, unsigned long *pi_buff) @@ -94,25 +101,37 @@ int hvcs_next_partner(unsigned int unit_address, return hvcs_convert(retval); } -/* - * The unit_address parameter is the unit address of the vty-server vdevice - * in whose partner information the caller is interested. This function - * uses a pointer to a list_head instance in which to store the partner info. +/** + * hvcs_get_partner_info - Get all of the partner info for a vty-server adapter + * @unit_address: The unit_address of the vty-server adapter for which this + * function is fetching partner info. + * @head: An initialized list_head pointer to an empty list to use to return the + * list of partner info fetched from the hypervisor to the caller. + * @pi_buff: A page sized buffer pre-allocated prior to calling this function + * that is to be used to be used by firmware as an iterator to keep track + * of the partner info retrieval. + * * This function returns non-zero on success, or if there is no partner info. * + * The pi_buff is pre-allocated prior to calling this function because this + * function may be called with a spin_lock held and kmalloc of a page is not + * recommended as GFP_ATOMIC. + * + * The first long of this buffer is used to store a partner unit address. The + * second long is used to store a partner partition ID and starting at + * pi_buff[2] is the 79 character Converged Location Code (diff size than the + * unsigned longs, hence the casting mumbo jumbo you see later). + * * Invocation of this function should always be followed by an invocation of * hvcs_free_partner_info() using a pointer to the SAME list head instance - * that was used to store the partner_info list. + * that was passed as a parameter to this function. */ -int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head, +int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head, unsigned long *pi_buff) { /* - * This is a page sized buffer to be passed to hvcall per invocation. - * NOTE: the first long returned is unit_address. The second long - * returned is the partition ID and starting with pi_buff[2] are - * HVCS_CLC_LENGTH characters, which are diff size than the unsigned - * long, hence the casting mumbojumbo you see later. + * Dealt with as longs because of the hcall interface even though the + * values are uint32_t. */ unsigned long last_p_partition_ID; unsigned long last_p_unit_address; @@ -122,15 +141,12 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head, memset(pi_buff, 0x00, PAGE_SIZE); /* invalid parameters */ - if (!head) + if (!head || !pi_buff) return -EINVAL; last_p_partition_ID = last_p_unit_address = ~0UL; INIT_LIST_HEAD(head); - if (!pi_buff) - return -ENOMEM; - do { retval = hvcs_next_partner(unit_address, last_p_partition_ID, last_p_unit_address, pi_buff); @@ -183,21 +199,29 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head, } EXPORT_SYMBOL(hvcs_get_partner_info); -/* +/** + * hvcs_register_connection - establish a connection between this vty-server and + * a vty. + * @unit_address: The unit address of the vty-server adapter that is to be + * establish a connection. + * @p_partition_ID: The partition ID of the vty adapter that is to be connected. + * @p_unit_address: The unit address of the vty adapter to which the vty-server + * is to be connected. + * * If this function is called once and -EINVAL is returned it may * indicate that the partner info needs to be refreshed for the * target unit address at which point the caller must invoke * hvcs_get_partner_info() and then call this function again. If, * for a second time, -EINVAL is returned then it indicates that * there is probably already a partner connection registered to a - * different vty-server@ vdevice. It is also possible that a second + * different vty-server adapter. It is also possible that a second * -EINVAL may indicate that one of the parms is not valid, for - * instance if the link was removed between the vty-server@ vdevice - * and the vty@ vdevice that you are trying to open. Don't shoot the + * instance if the link was removed between the vty-server adapter + * and the vty adapter that you are trying to open. Don't shoot the * messenger. Firmware implemented it this way. */ -int hvcs_register_connection( unsigned int unit_address, - unsigned int p_partition_ID, unsigned int p_unit_address) +int hvcs_register_connection( uint32_t unit_address, + uint32_t p_partition_ID, uint32_t p_unit_address) { long retval; retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address, @@ -206,11 +230,17 @@ int hvcs_register_connection( unsigned int unit_address, } EXPORT_SYMBOL(hvcs_register_connection); -/* - * If -EBUSY is returned continue to call this function - * until 0 is returned. +/** + * hvcs_free_connection - free the connection between a vty-server and vty + * @unit_address: The unit address of the vty-server that is to have its + * connection severed. + * + * This function is used to free the partner connection between a vty-server + * adapter and a vty adapter. + * + * If -EBUSY is returned continue to call this function until 0 is returned. */ -int hvcs_free_connection(unsigned int unit_address) +int hvcs_free_connection(uint32_t unit_address) { long retval; retval = plpar_hcall_norets(H_FREE_VTERM, unit_address); diff --git a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c index 2f2b9bf8c..3458cf0c5 100644 --- a/arch/ppc64/kernel/i8259.c +++ b/arch/ppc64/kernel/i8259.c @@ -23,7 +23,8 @@ unsigned char cached_8259[2] = { 0xff, 0xff }; static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; -int i8259_pic_irq_offset; +static int i8259_pic_irq_offset; +static int i8259_present; int i8259_irq(int cpu) { @@ -140,11 +141,13 @@ struct hw_interrupt_type i8259_pic = { NULL }; -void __init i8259_init(void) +void __init i8259_init(int offset) { unsigned long flags; spin_lock_irqsave(&i8259_lock, flags); + i8259_pic_irq_offset = offset; + i8259_present = 1; /* init master interrupt controller */ outb(0x11, 0x20); /* Start init sequence */ outb(0x00, 0x21); /* Vector base */ @@ -160,7 +163,18 @@ void __init i8259_init(void) outb(cached_A1, 0xA1); outb(cached_21, 0x21); spin_unlock_irqrestore(&i8259_lock, flags); + +} + +static int i8259_request_cascade(void) +{ + if (!i8259_present) + return -ENODEV; + request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT, "82c59 secondary cascade", NULL ); - + + return 0; } + +arch_initcall(i8259_request_cascade); diff --git a/arch/ppc64/kernel/i8259.h b/arch/ppc64/kernel/i8259.h index 620a99997..f74764ba0 100644 --- a/arch/ppc64/kernel/i8259.h +++ b/arch/ppc64/kernel/i8259.h @@ -11,7 +11,7 @@ extern struct hw_interrupt_type i8259_pic; -void i8259_init(void); -int i8259_irq(int); +extern void i8259_init(int offset); +extern int i8259_irq(int); #endif /* _PPC_KERNEL_i8259_H */ diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c index 2456227b4..b1177b476 100644 --- a/arch/ppc64/kernel/iSeries_htab.c +++ b/arch/ppc64/kernel/iSeries_htab.c @@ -233,4 +233,6 @@ void hpte_init_iSeries(void) ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; ppc_md.hpte_insert = iSeries_hpte_insert; ppc_md.hpte_remove = iSeries_hpte_remove; + + htab_finish_init(); } diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c index c09ea2aaa..4f0631860 100644 --- a/arch/ppc64/kernel/iSeries_iommu.c +++ b/arch/ppc64/kernel/iSeries_iommu.c @@ -25,30 +25,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include -#include -#include #include -#include -#include - #include - -#include "pci.h" - +#include +#include extern struct list_head iSeries_Global_Device_List; @@ -76,12 +60,11 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, tce.te_bits.tb_pciwr = 1; } - rc = HvCallXm_setTce((u64)tbl->it_index, - (u64)index, - tce.te_word); + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, + tce.te_word); if (rc) - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); - + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", + rc); index++; uaddr += PAGE_SIZE; } @@ -90,20 +73,14 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) { u64 rc; - union tce_entry tce; while (npages--) { - tce.te_word = 0; - rc = HvCallXm_setTce((u64)tbl->it_index, - (u64)index, - tce.te_word); - + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); if (rc) - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); - + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", + rc); index++; } - } @@ -115,17 +92,14 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) { struct iSeries_Device_Node *dp; - for (dp = (struct iSeries_Device_Node *)iSeries_Global_Device_List.next; - dp != (struct iSeries_Device_Node *)&iSeries_Global_Device_List; - dp = (struct iSeries_Device_Node *)dp->Device_List.next) - if (dp->iommu_table != NULL && - dp->iommu_table->it_type == TCE_PCI && - dp->iommu_table->it_offset == tbl->it_offset && - dp->iommu_table->it_index == tbl->it_index && - dp->iommu_table->it_size == tbl->it_size) + list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) { + if ((dp->iommu_table != NULL) && + (dp->iommu_table->it_type == TCE_PCI) && + (dp->iommu_table->it_offset == tbl->it_offset) && + (dp->iommu_table->it_index == tbl->it_index) && + (dp->iommu_table->it_size == tbl->it_size)) return dp->iommu_table; - - + } return NULL; } @@ -143,15 +117,14 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn, { struct iommu_table_cb *parms; - parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL); - + parms = kmalloc(sizeof(*parms), GFP_KERNEL); if (parms == NULL) panic("PCI_DMA: TCE Table Allocation failed."); memset(parms, 0, sizeof(*parms)); - parms->itc_busno = ISERIES_BUS(dn); - parms->itc_slotno = dn->LogicalSlot; + parms->itc_busno = ISERIES_BUS(dn); + parms->itc_slotno = dn->LogicalSlot; parms->itc_virtbus = 0; HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms)); @@ -159,34 +132,32 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn, if (parms->itc_size == 0) panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); - tbl->it_size = parms->itc_size; - tbl->it_busno = parms->itc_busno; - tbl->it_offset = parms->itc_offset; - tbl->it_index = parms->itc_index; - tbl->it_entrysize = sizeof(union tce_entry); - tbl->it_blocksize = 1; - tbl->it_type = TCE_PCI; + tbl->it_size = parms->itc_size; + tbl->it_busno = parms->itc_busno; + tbl->it_offset = parms->itc_offset; + tbl->it_index = parms->itc_index; + tbl->it_entrysize = sizeof(union tce_entry); + tbl->it_blocksize = 1; + tbl->it_type = TCE_PCI; kfree(parms); } -void iommu_devnode_init(struct iSeries_Device_Node *dn) { +void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn) +{ struct iommu_table *tbl; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); iommu_table_getparms(dn, tbl); /* Look for existing tce table */ dn->iommu_table = iommu_table_find(tbl); - if (dn->iommu_table == NULL) dn->iommu_table = iommu_init_table(tbl); else kfree(tbl); - - return; } diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c index fe6d63676..f831d259d 100644 --- a/arch/ppc64/kernel/iSeries_irq.c +++ b/arch/ppc64/kernel/iSeries_irq.c @@ -110,6 +110,7 @@ static unsigned int iSeries_startup_IRQ(unsigned int irq) /* Unmask bridge interrupts in the FISR */ mask = 0x01010000 << function; HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); + iSeries_enable_IRQ(irq); return 0; } diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c index 3472d188e..628a4c02a 100644 --- a/arch/ppc64/kernel/iSeries_pci.c +++ b/arch/ppc64/kernel/iSeries_pci.c @@ -1,4 +1,3 @@ -#define PCIFR(...) /* * iSeries_pci.c * @@ -47,26 +46,19 @@ #include #include -#include "iSeries_IoMmTable.h" #include "pci.h" extern int panic_timeout; -extern unsigned long iSeries_Base_Io_Memory; - -extern struct iommu_table *tceTables[256]; - -extern void iSeries_MmIoTest(void); +extern unsigned long io_page_mask; /* * Forward declares of prototypes. */ static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); -static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb); -static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, - int IdSel); -static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, - struct HvCallPci_BridgeInfo *Info); +static void scan_PHB_slots(struct pci_controller *Phb); +static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); +static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); LIST_HEAD(iSeries_Global_Device_List); @@ -87,7 +79,116 @@ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ static struct pci_ops iSeries_pci_ops; /* - * Log Error infor in Flight Recorder to system Console. + * Table defines + * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. + */ +#define IOMM_TABLE_MAX_ENTRIES 1024 +#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL +#define BASE_IO_MEMORY 0xE000000000000000UL + +static unsigned long max_io_memory = 0xE000000000000000UL; +static long current_iomm_table_entry; + +/* + * Lookup Tables. + */ +static struct iSeries_Device_Node **iomm_table; +static u8 *iobar_table; + +/* + * Static and Global variables + */ +static char *pci_io_text = "iSeries PCI I/O"; +static spinlock_t iomm_table_lock = SPIN_LOCK_UNLOCKED; + +/* + * iomm_table_initialize + * + * Allocates and initalizes the Address Translation Table and Bar + * Tables to get them ready for use. Must be called before any + * I/O space is handed out to the device BARs. + */ +static void iomm_table_initialize(void) +{ + spin_lock(&iomm_table_lock); + iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, + GFP_KERNEL); + iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, + GFP_KERNEL); + spin_unlock(&iomm_table_lock); + if ((iomm_table == NULL) || (iobar_table == NULL)) + panic("PCI: I/O tables allocation failed.\n"); +} + +/* + * iomm_table_allocate_entry + * + * Adds pci_dev entry in address translation table + * + * - Allocates the number of entries required in table base on BAR + * size. + * - Allocates starting at BASE_IO_MEMORY and increases. + * - The size is round up to be a multiple of entry size. + * - CurrentIndex is incremented to keep track of the last entry. + * - Builds the resource entry for allocated BARs. + */ +static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) +{ + struct resource *bar_res = &dev->resource[bar_num]; + long bar_size = pci_resource_len(dev, bar_num); + + /* + * No space to allocate, quick exit, skip Allocation. + */ + if (bar_size == 0) + return; + /* + * Set Resource values. + */ + spin_lock(&iomm_table_lock); + bar_res->name = pci_io_text; + bar_res->start = + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; + bar_res->start += BASE_IO_MEMORY; + bar_res->end = bar_res->start + bar_size - 1; + /* + * Allocate the number of table entries needed for BAR. + */ + while (bar_size > 0 ) { + iomm_table[current_iomm_table_entry] = dev->sysdata; + iobar_table[current_iomm_table_entry] = bar_num; + bar_size -= IOMM_TABLE_ENTRY_SIZE; + ++current_iomm_table_entry; + } + max_io_memory = BASE_IO_MEMORY + + (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); + spin_unlock(&iomm_table_lock); +} + +/* + * allocate_device_bars + * + * - Allocates ALL pci_dev BAR's and updates the resources with the + * BAR value. BARS with zero length will have the resources + * The HvCallPci_getBarParms is used to get the size of the BAR + * space. It calls iomm_table_allocate_entry to allocate + * each entry. + * - Loops through The Bar resources(0 - 5) including the ROM + * is resource(6). + */ +static void allocate_device_bars(struct pci_dev *dev) +{ + struct resource *bar_res; + int bar_num; + + for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { + bar_res = &dev->resource[bar_num]; + iomm_table_allocate_entry(dev, bar_num); + } +} + +/* + * Log error information to system console. * Filter out the device not there errors. * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx @@ -98,7 +199,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, { if (HvRc == 0x0302) return; - printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", Error_Text, Bus, SubBus, AgentId, HvRc); } @@ -132,8 +232,6 @@ static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); node->IoRetry = 0; iSeries_Get_Location_Code(node); - PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node), - ISERIES_DEVFUN(node), node); return node; } @@ -158,11 +256,12 @@ unsigned long __init find_and_init_phbs(void) int ret = HvCallXm_testBus(bus); if (ret == 0) { printk("bus %d appears to exist\n", bus); - phb = pci_alloc_pci_controller(phb_type_hypervisor); - if (phb == NULL) { - PCIFR("Allocate pci_controller failed."); - return -1; - } + + phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); + if (phb == NULL) + return -ENOMEM; + pci_setup_pci_controller(phb); + phb->pci_mem_offset = phb->local_number = bus; phb->first_busno = bus; phb->last_busno = bus; @@ -170,10 +269,9 @@ unsigned long __init find_and_init_phbs(void) PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", phb, bus); - PCIFR("Create iSeries PHB controller: %04X", bus); /* Find and connect the devices. */ - iSeries_Scan_PHBs_Slots(phb); + scan_PHB_slots(phb); } /* * Check for Unexpected Return code, a clue that something @@ -194,9 +292,9 @@ unsigned long __init find_and_init_phbs(void) void iSeries_pcibios_init(void) { PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); - iSeries_IoMmTable_Initialize(); + iomm_table_initialize(); find_and_init_phbs(); - /* pci_assign_all_busses = 0; SFRXXX*/ + io_page_mask = -1; PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); } @@ -213,11 +311,10 @@ void __init iSeries_pci_final_fixup(void) PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); /* Fix up at the device node and pci_dev relationship */ - mf_displaySrc(0xC9000100); + mf_display_src(0xC9000100); printk("pcibios_final_fixup\n"); - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) - != NULL) { + for_each_pci_dev(pdev) { node = find_Device_Node(pdev->bus->number, pdev->devfn); printk("pci dev %p (%x.%x), node %p\n", pdev, pdev->bus->number, pdev->devfn, node); @@ -229,19 +326,18 @@ void __init iSeries_pci_final_fixup(void) PPCDBG(PPCDBG_BUSWALK, "pdev 0x%p <==> DevNode 0x%p\n", pdev, node); - iSeries_allocateDeviceBars(pdev); + allocate_device_bars(pdev); iSeries_Device_Information(pdev, Buffer, sizeof(Buffer)); printk("%d. %s\n", DeviceCount, Buffer); - iommu_devnode_init(node); + iommu_devnode_init_iSeries(node); } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); pdev->irq = node->Irq; } - iSeries_IoMmTable_Status(); iSeries_activate_IRQs(); - mf_displaySrc(0xC9000200); + mf_display_src(0xC9000200); } void pcibios_fixup_bus(struct pci_bus *PciBus) @@ -258,7 +354,7 @@ void pcibios_fixup_resources(struct pci_dev *pdev) /* * Loop through each node function to find usable EADs bridges. */ -static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) +static void scan_PHB_slots(struct pci_controller *Phb) { struct HvCallPci_DeviceInfo *DevInfo; HvBusNumber bus = Phb->local_number; /* System Bus */ @@ -281,7 +377,7 @@ static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) sizeof(struct HvCallPci_DeviceInfo)); if (HvRc == 0) { if (DevInfo->deviceType == HvCallPci_NodeDevice) - iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel); + scan_EADS_bridge(bus, SubBus, IdSel); else printk("PCI: Invalid System Configuration(0x%02X)" " for bus 0x%02x id 0x%02x.\n", @@ -293,7 +389,7 @@ static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) kfree(DevInfo); } -static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus, +static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, int IdSel) { struct HvCallPci_BridgeInfo *BridgeInfo; @@ -338,7 +434,7 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus, if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ - iSeries_Scan_Bridge_Slot(bus, BridgeInfo); + scan_bridge_slot(bus, BridgeInfo); } else printk("PCI: Invalid Bridge Configuration(0x%02X)", BridgeInfo->busUnitInfo.deviceType); @@ -353,7 +449,7 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus, /* * This assumes that the node slot is always on the primary bus! */ -static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, +static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *BridgeInfo) { struct iSeries_Device_Node *node; @@ -419,46 +515,39 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, * I/0 Memory copy MUST use mmio commands on iSeries * To do; For performance, include the hv call directly */ -void *iSeries_memset_io(void *dest, char c, size_t Count) +void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count) { u8 ByteValue = c; long NumberOfBytes = Count; - char *IoBuffer = dest; while (NumberOfBytes > 0) { - iSeries_Write_Byte(ByteValue, (void *)IoBuffer); - ++IoBuffer; + iSeries_Write_Byte(ByteValue, dest++); -- NumberOfBytes; } - return dest; } EXPORT_SYMBOL(iSeries_memset_io); -void *iSeries_memcpy_toio(void *dest, void *source, size_t count) +void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count) { - char *dst = dest; char *src = source; long NumberOfBytes = count; while (NumberOfBytes > 0) { - iSeries_Write_Byte(*src++, (void *)dst++); + iSeries_Write_Byte(*src++, dest++); -- NumberOfBytes; } - return dest; } EXPORT_SYMBOL(iSeries_memcpy_toio); -void *iSeries_memcpy_fromio(void *dest, void *source, size_t count) +void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count) { char *dst = dest; - char *src = source; long NumberOfBytes = count; while (NumberOfBytes > 0) { - *dst++ = iSeries_Read_Byte((void *)src++); + *dst++ = iSeries_Read_Byte(src++); -- NumberOfBytes; } - return dest; } EXPORT_SYMBOL(iSeries_memcpy_fromio); @@ -590,7 +679,7 @@ static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, */ if ((DevNode->IoRetry > Pci_Retry_Max) && (Pci_Error_Flag > 0)) { - mf_displaySrc(0xB6000103); + mf_display_src(0xB6000103); panic_timeout = 0; panic("PCI: Hardware I/O Error, SRC B6000103, " "Automatic Reboot Disabled.\n"); @@ -598,12 +687,8 @@ static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, return -1; /* Retry Try */ } /* If retry was in progress, log success and rest retry count */ - if (DevNode->IoRetry > 0) { - PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).", - TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, - DevNode->IoRetry); + if (DevNode->IoRetry > 0) DevNode->IoRetry = 0; - } return 0; } @@ -612,24 +697,26 @@ static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, * Note: Make sure the passed variable end up on the stack to avoid * the exposure of being device global. */ -static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, - u64 *dsaptr, u64 *BarOffsetPtr) +static inline struct iSeries_Device_Node *xlate_iomm_address( + const volatile void __iomem *IoAddress, + u64 *dsaptr, u64 *BarOffsetPtr) { + unsigned long OrigIoAddr; unsigned long BaseIoAddr; unsigned long TableIndex; struct iSeries_Device_Node *DevNode; - if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) || - ((unsigned long)IoAddress >= iSeries_Max_Io_Memory)) + OrigIoAddr = (unsigned long __force)IoAddress; + if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory)) return NULL; - BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory; - TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; - DevNode = iSeries_IoMmTable[TableIndex]; + BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY; + TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE; + DevNode = iomm_table[TableIndex]; if (DevNode != NULL) { - int barnum = iSeries_IoBarTable[TableIndex]; + int barnum = iobar_table[TableIndex]; *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); - *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; + *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE; } else panic("PCI: Invalid PCI IoAddress detected!\n"); return DevNode; @@ -644,13 +731,13 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, * iSeries_Read_Word = Read Word (16 bit) * iSeries_Read_Long = Read Long (32 bit) */ -u8 iSeries_Read_Byte(void *IoAddress) +u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -673,13 +760,13 @@ u8 iSeries_Read_Byte(void *IoAddress) } EXPORT_SYMBOL(iSeries_Read_Byte); -u16 iSeries_Read_Word(void *IoAddress) +u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -703,13 +790,13 @@ u16 iSeries_Read_Word(void *IoAddress) } EXPORT_SYMBOL(iSeries_Read_Word); -u32 iSeries_Read_Long(void *IoAddress) +u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; struct HvCallPci_LoadReturn ret; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -740,13 +827,13 @@ EXPORT_SYMBOL(iSeries_Read_Long); * iSeries_Write_Word = Write Word(16 bit) * iSeries_Write_Long = Write Long(32 bit) */ -void iSeries_Write_Byte(u8 data, void *IoAddress) +void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -767,13 +854,13 @@ void iSeries_Write_Byte(u8 data, void *IoAddress) } EXPORT_SYMBOL(iSeries_Write_Byte); -void iSeries_Write_Word(u16 data, void *IoAddress) +void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -794,13 +881,13 @@ void iSeries_Write_Word(u16 data, void *IoAddress) } EXPORT_SYMBOL(iSeries_Write_Word); -void iSeries_Write_Long(u32 data, void *IoAddress) +void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) { u64 BarOffset; u64 dsa; u64 rc; struct iSeries_Device_Node *DevNode = - xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + xlate_iomm_address(IoAddress, &dsa, &BarOffset); if (DevNode == NULL) { static unsigned long last_jiffies; @@ -820,7 +907,3 @@ void iSeries_Write_Long(u32 data, void *IoAddress) } while (CheckReturnCode("WWL", DevNode, rc) != 0); } EXPORT_SYMBOL(iSeries_Write_Long); - -void pcibios_name_device(struct pci_dev *dev) -{ -} diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c index e1e48c35e..8848ece79 100644 --- a/arch/ppc64/kernel/iSeries_pci_reset.c +++ b/arch/ppc64/kernel/iSeries_pci_reset.c @@ -65,7 +65,8 @@ int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime, AssertDelay = (5 * HZ) / 10; else AssertDelay = (AssertTime * HZ) / 10; - if (WaitDelay == 0) + + if (DelayTime == 0) WaitDelay = (30 * HZ) / 10; else WaitDelay = (DelayTime * HZ) / 10; diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c index 1babbb6b9..6d7857ced 100644 --- a/arch/ppc64/kernel/iSeries_proc.c +++ b/arch/ppc64/kernel/iSeries_proc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* for HZ */ #include #include #include diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c index e12b50f8c..9ea357fa2 100644 --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c @@ -16,6 +16,8 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include @@ -36,6 +38,7 @@ #include #include #include +#include #include #include "iSeries_setup.h" @@ -52,19 +55,23 @@ #include #include #include +#include + +extern void hvlog(char *fmt, ...); + +#ifdef DEBUG +#define DBG(fmt...) hvlog(fmt) +#else +#define DBG(fmt...) +#endif /* Function Prototypes */ -extern void abort(void); extern void ppcdbg_initialize(void); -extern void iSeries_pcibios_init(void); extern void tce_init_iSeries(void); static void build_iSeries_Memory_Map(void); static void setup_iSeries_cache_sizes(void); static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); -extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, - pte_t *ptep, unsigned hpteflags, unsigned bolted); -static void iSeries_setup_dprofile(void); extern void iSeries_setup_arch(void); extern void iSeries_pci_final_fixup(void); @@ -77,16 +84,8 @@ static unsigned long tbFreqHz; static unsigned long tbFreqMhz; static unsigned long tbFreqMhzHundreths; -unsigned long dprof_shift; -unsigned long dprof_len; -unsigned int *dprof_buffer; - int piranha_simulator; -int boot_cpuid; - -extern char _end[]; - extern int rd_size; /* Defined in drivers/block/rd.c */ extern unsigned long klimit; extern unsigned long embedded_sysmap_start; @@ -285,8 +284,28 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array, return mem_blocks; } -void __init iSeries_init_early(void) +static void __init iSeries_parse_cmdline(void) +{ + char *p, *q; + + /* copy the command line parameter from the primary VSP */ + HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256, + HvLpDma_Direction_RemoteToLocal); + + p = cmd_line; + q = cmd_line + 255; + while(p < q) { + if (!*p || *p == '\n') + break; + ++p; + } + *p = 0; +} + +/*static*/ void __init iSeries_init_early(void) { + DBG(" -> iSeries_init_early()\n"); + ppcdbg_initialize(); #if defined(CONFIG_BLK_DEV_INITRD) @@ -310,25 +329,20 @@ void __init iSeries_init_early(void) iSeries_recal_tb = get_tb(); iSeries_recal_titan = HvCallXm_loadTod(); - ppc_md.setup_arch = iSeries_setup_arch; - ppc_md.get_cpuinfo = iSeries_get_cpuinfo; - ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.get_irq = iSeries_get_irq; - ppc_md.init = NULL; - - ppc_md.pcibios_fixup = iSeries_pci_final_fixup; - - ppc_md.restart = iSeries_restart; - ppc_md.power_off = iSeries_power_off; - ppc_md.halt = iSeries_halt; - - ppc_md.get_boot_time = iSeries_get_boot_time; - ppc_md.set_rtc_time = iSeries_set_rtc_time; - ppc_md.get_rtc_time = iSeries_get_rtc_time; - ppc_md.calibrate_decr = iSeries_calibrate_decr; - ppc_md.progress = iSeries_progress; + /* + * Cache sizes must be initialized before hpte_init_iSeries is called + * as the later need them for flush_icache_range() + */ + setup_iSeries_cache_sizes(); + /* + * Initialize the hash table management pointers + */ hpte_init_iSeries(); + + /* + * Initialize the DMA/TCE management + */ tce_init_iSeries(); /* @@ -336,63 +350,36 @@ void __init iSeries_init_early(void) * AS/400 absolute addresses */ build_iSeries_Memory_Map(); - setup_iSeries_cache_sizes(); + /* Initialize machine-dependency vectors */ #ifdef CONFIG_SMP smp_init_iSeries(); #endif if (itLpNaca.xPirEnvironMode == 0) piranha_simulator = 1; -} - -void __init iSeries_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - char *p, *q; /* Associate Lp Event Queue 0 with processor 0 */ HvCallEvent_setLpEventQueueInterruptProc(0, 0); - /* copy the command line parameter from the primary VSP */ - HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256, - HvLpDma_Direction_RemoteToLocal); - - p = cmd_line; - q = cmd_line + 255; - while( p < q ) { - if (!*p || *p == '\n') - break; - ++p; - } - *p = 0; - - if (strstr(cmd_line, "dprofile=")) { - for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) { - unsigned long size, new_klimit; - - q = p + 9; - if ((p > cmd_line) && (p[-1] != ' ')) - continue; - dprof_shift = simple_strtoul(q, &q, 0); - dprof_len = (unsigned long)_etext - - (unsigned long)_stext; - dprof_len >>= dprof_shift; - size = ((dprof_len * sizeof(unsigned int)) + - (PAGE_SIZE-1)) & PAGE_MASK; - dprof_buffer = (unsigned int *)((klimit + - (PAGE_SIZE-1)) & PAGE_MASK); - new_klimit = ((unsigned long)dprof_buffer) + size; - lmb_reserve(__pa(klimit), (new_klimit-klimit)); - klimit = new_klimit; - memset(dprof_buffer, 0, size); - } - } - - iSeries_setup_dprofile(); - mf_init(); mf_initialized = 1; mb(); + + /* If we were passed an initrd, set the ROOT_DEV properly if the values + * look sensible. If not, clear initrd reference. + */ +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && + initrd_end > initrd_start) + ROOT_DEV = Root_RAM0; + else + initrd_start = initrd_end = 0; +#endif /* CONFIG_BLK_DEV_INITRD */ + + + iSeries_parse_cmdline(); + + DBG(" <- iSeries_init_early()\n"); } /* @@ -746,7 +733,7 @@ void iSeries_restart(char *cmd) */ void iSeries_power_off(void) { - mf_powerOff(); + mf_power_off(); } /* @@ -754,7 +741,7 @@ void iSeries_power_off(void) */ void iSeries_halt(void) { - mf_powerOff(); + mf_power_off(); } /* JDH Hack */ @@ -810,13 +797,13 @@ void __init iSeries_progress(char * st, unsigned short code) printk("Progress: [%04x] - %s\n", (unsigned)code, st); if (!piranha_simulator && mf_initialized) { if (code != 0xffff) - mf_displayProgress(code); + mf_display_progress(code); else - mf_clearSrc(); + mf_clear_src(); } } -void iSeries_fixup_klimit(void) +static void __init iSeries_fixup_klimit(void) { /* * Change klimit to take into account any ram disk @@ -837,22 +824,6 @@ void iSeries_fixup_klimit(void) } } -static void iSeries_setup_dprofile(void) -{ - if (dprof_buffer) { - unsigned i; - - for (i = 0; i < NR_CPUS; ++i) { - paca[i].prof_shift = dprof_shift; - paca[i].prof_len = dprof_len - 1; - paca[i].prof_buffer = dprof_buffer; - paca[i].prof_stext = (unsigned *)_stext; - mb(); - paca[i].prof_enabled = 1; - } - } -} - int __init iSeries_src_init(void) { /* clear the progress line */ @@ -861,3 +832,27 @@ int __init iSeries_src_init(void) } late_initcall(iSeries_src_init); + +void __init iSeries_early_setup(void) +{ + iSeries_fixup_klimit(); + + ppc_md.setup_arch = iSeries_setup_arch; + ppc_md.get_cpuinfo = iSeries_get_cpuinfo; + ppc_md.init_IRQ = iSeries_init_IRQ; + ppc_md.get_irq = iSeries_get_irq; + ppc_md.init_early = iSeries_init_early, + + ppc_md.pcibios_fixup = iSeries_pci_final_fixup; + + ppc_md.restart = iSeries_restart; + ppc_md.power_off = iSeries_power_off; + ppc_md.halt = iSeries_halt; + + ppc_md.get_boot_time = iSeries_get_boot_time; + ppc_md.set_rtc_time = iSeries_set_rtc_time; + ppc_md.get_rtc_time = iSeries_get_rtc_time; + ppc_md.calibrate_decr = iSeries_calibrate_decr; + ppc_md.progress = iSeries_progress; +} + diff --git a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h index 240dad4ef..098041b4c 100644 --- a/arch/ppc64/kernel/iSeries_setup.h +++ b/arch/ppc64/kernel/iSeries_setup.h @@ -19,10 +19,6 @@ #ifndef __ISERIES_SETUP_H__ #define __ISERIES_SETUP_H__ -extern void iSeries_init_early(void); -extern void iSeries_init(unsigned long r3, unsigned long ird_start, - unsigned long ird_end, unsigned long cline_start, - unsigned long cline_end); extern void iSeries_setup_arch(void); extern void iSeries_setup_residual(struct seq_file *m, int cpu_id); extern void iSeries_get_cpuinfo(struct seq_file *m); diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index bc7dbbd2d..ebed2971c 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -16,40 +16,30 @@ */ #include -#include #include #include -#include #include -#include -#include -#include -#include -#include #include +#include +#include +#include -#include -#include #include -#include #include #include -#include #include #include -#include #include #include +#include -extern long cede_processor(void); -extern long poll_pending(void); extern void power4_idle(void); -int (*idle_loop)(void); +static int (*idle_loop)(void); #ifdef CONFIG_PPC_ISERIES -unsigned long maxYieldTime = 0; -unsigned long minYieldTime = 0xffffffffffffffffUL; +static unsigned long maxYieldTime = 0; +static unsigned long minYieldTime = 0xffffffffffffffffUL; static void yield_shared_processor(void) { @@ -80,7 +70,7 @@ static void yield_shared_processor(void) process_iSeries_events(); } -int iSeries_idle(void) +static int iSeries_idle(void) { struct paca_struct *lpaca; long oldval; @@ -91,13 +81,10 @@ int iSeries_idle(void) CTRL = mfspr(CTRLF); CTRL &= ~RUNLATCH; mtspr(CTRLT, CTRL); -#if 0 - init_idle(); -#endif lpaca = get_paca(); - for (;;) { + while (1) { if (lpaca->lppaca.xSharedProc) { if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr)) process_iSeries_events(); @@ -125,13 +112,16 @@ int iSeries_idle(void) schedule(); } + return 0; } -#endif -int default_idle(void) +#else + +static int default_idle(void) { long oldval; + unsigned int cpu = smp_processor_id(); while (1) { oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); @@ -139,9 +129,14 @@ int default_idle(void) if (!oldval) { set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched()) { + while (!need_resched() && !cpu_is_offline(cpu)) { barrier(); + /* + * Go into low thread priority and possibly + * low power mode. + */ HMT_low(); + HMT_very_low(); } HMT_medium(); @@ -151,8 +146,7 @@ int default_idle(void) } schedule(); - if (cpu_is_offline(smp_processor_id()) && - system_state == SYSTEM_RUNNING) + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); } @@ -169,12 +163,15 @@ int dedicated_idle(void) struct paca_struct *lpaca = get_paca(), *ppaca; unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); + unsigned int cpu = smp_processor_id(); - ppaca = &paca[smp_processor_id() ^ 1]; + ppaca = &paca[cpu ^ 1]; while (1) { - /* Indicate to the HV that we are idle. Now would be - * a good time to find other work to dispatch. */ + /* + * Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. + */ lpaca->lppaca.xIdle = 1; oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); @@ -182,42 +179,32 @@ int dedicated_idle(void) set_thread_flag(TIF_POLLING_NRFLAG); start_snooze = __get_tb() + *smt_snooze_delay * tb_ticks_per_usec; - while (!need_resched()) { - /* need_resched could be 1 or 0 at this - * point. If it is 0, set it to 0, so - * an IPI/Prod is sent. If it is 1, keep - * it that way & schedule work. + while (!need_resched() && !cpu_is_offline(cpu)) { + /* + * Go into low thread priority and possibly + * low power mode. */ + HMT_low(); + HMT_very_low(); + if (*smt_snooze_delay == 0 || - __get_tb() < start_snooze) { - HMT_low(); /* Low thread priority */ + __get_tb() < start_snooze) continue; - } - HMT_very_low(); /* Low power mode */ + HMT_medium(); - /* If the SMT mode is system controlled & the - * partner thread is doing work, switch into - * ST mode. - */ - if((naca->smt_state == SMT_DYNAMIC) && - (!(ppaca->lppaca.xIdle))) { - /* Indicate we are no longer polling for - * work, and then clear need_resched. If - * need_resched was 1, set it back to 1 - * and schedule work + if (!(ppaca->lppaca.xIdle)) { + local_irq_disable(); + + /* + * We are about to sleep the thread + * and so wont be polling any + * more. */ clear_thread_flag(TIF_POLLING_NRFLAG); - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - if(oldval == 1) { - set_need_resched(); - break; - } - - /* DRENG: Go HMT_medium here ? */ - local_irq_disable(); - /* SMT dynamic mode. Cede will result + /* + * SMT dynamic mode. Cede will result * in this thread going dormant, if the * partner thread is still doing work. * Thread wakes up if partner goes idle, @@ -225,15 +212,21 @@ int dedicated_idle(void) * occurs. Returning from the cede * enables external interrupts. */ - cede_processor(); + if (!need_resched()) + cede_processor(); + else + local_irq_enable(); } else { - /* Give the HV an opportunity at the + /* + * Give the HV an opportunity at the * processor, since we are not doing * any work. */ poll_pending(); } } + + clear_thread_flag(TIF_POLLING_NRFLAG); } else { set_need_resched(); } @@ -241,57 +234,60 @@ int dedicated_idle(void) HMT_medium(); lpaca->lppaca.xIdle = 0; schedule(); - if (cpu_is_offline(smp_processor_id()) && - system_state == SYSTEM_RUNNING) + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); } return 0; } -int shared_idle(void) +static int shared_idle(void) { struct paca_struct *lpaca = get_paca(); + unsigned int cpu = smp_processor_id(); while (1) { - if (cpu_is_offline(smp_processor_id()) && - system_state == SYSTEM_RUNNING) - cpu_die(); - - /* Indicate to the HV that we are idle. Now would be - * a good time to find other work to dispatch. */ + /* + * Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. + */ lpaca->lppaca.xIdle = 1; - if (!need_resched()) { - local_irq_disable(); - - /* + while (!need_resched() && !cpu_is_offline(cpu)) { + local_irq_disable(); + + /* * Yield the processor to the hypervisor. We return if * an external interrupt occurs (which are driven prior * to returning here) or if a prod occurs from another - * processor. When returning here, external interrupts + * processor. When returning here, external interrupts * are enabled. + * + * Check need_resched() again with interrupts disabled + * to avoid a race. */ - cede_processor(); + if (!need_resched()) + cede_processor(); + else + local_irq_enable(); } HMT_medium(); lpaca->lppaca.xIdle = 0; schedule(); + if (cpu_is_offline(smp_processor_id()) && + system_state == SYSTEM_RUNNING) + cpu_die(); } return 0; } -#endif -int cpu_idle(void) -{ - idle_loop(); - return 0; -} +#endif /* CONFIG_PPC_PSERIES */ -int native_idle(void) +static int native_idle(void) { while(1) { + /* check CPU type here */ if (!need_resched()) power4_idle(); if (need_resched()) @@ -300,33 +296,81 @@ int native_idle(void) return 0; } +#endif /* CONFIG_PPC_ISERIES */ + +int cpu_idle(void) +{ + idle_loop(); + return 0; +} + +int powersave_nap; + +#ifdef CONFIG_SYSCTL +/* + * Register the sysctl to set/clear powersave_nap. + */ +static ctl_table powersave_nap_ctl_table[]={ + { + .ctl_name = KERN_PPC_POWERSAVE_NAP, + .procname = "powersave-nap", + .data = &powersave_nap, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { 0, }, +}; +static ctl_table powersave_nap_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, + { 0,}, +}; + +static int __init +register_powersave_nap_sysctl(void) +{ + register_sysctl_table(powersave_nap_sysctl_root, 0); + + return 0; +} +__initcall(register_powersave_nap_sysctl); +#endif + int idle_setup(void) { + /* + * Move that junk to each platform specific file, eventually define + * a pSeries_idle for shared processor stuff + */ #ifdef CONFIG_PPC_ISERIES idle_loop = iSeries_idle; + return 1; #else + idle_loop = default_idle; +#endif +#ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_PSERIES) { if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { if (get_paca()->lppaca.xSharedProc) { - printk("idle = shared_idle\n"); + printk(KERN_INFO "Using shared processor idle loop\n"); idle_loop = shared_idle; } else { - printk("idle = dedicated_idle\n"); + printk(KERN_INFO "Using dedicated idle loop\n"); idle_loop = dedicated_idle; } } else { - printk("idle = default_idle\n"); + printk(KERN_INFO "Using default idle loop\n"); idle_loop = default_idle; } - } else if (systemcfg->platform == PLATFORM_POWERMAC) { - printk("idle = native_idle\n"); + } +#endif /* CONFIG_PPC_PSERIES */ +#ifndef CONFIG_PPC_ISERIES + if (systemcfg->platform == PLATFORM_POWERMAC || + systemcfg->platform == PLATFORM_MAPLE) { + printk(KERN_INFO "Using native/NAP idle loop\n"); idle_loop = native_idle; - } else { - printk("idle_setup: unknown platform, use default_idle\n"); - idle_loop = default_idle; } -#endif +#endif /* CONFIG_PPC_ISERIES */ return 1; } - diff --git a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S index fb983069d..97e4a2655 100644 --- a/arch/ppc64/kernel/idle_power4.S +++ b/arch/ppc64/kernel/idle_power4.S @@ -46,7 +46,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) /* Now check if user or arch enabled NAP mode */ LOADBASE(r3,powersave_nap) lwz r4,powersave_nap@l(r3) - cmpi 0,r4,0 + cmpwi 0,r4,0 beqlr /* Clear MSR:EE */ diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c index 40ba4c17e..94d1a05b7 100644 --- a/arch/ppc64/kernel/ioctl32.c +++ b/arch/ppc64/kernel/ioctl32.c @@ -22,9 +22,7 @@ #define INCLUDES #include "compat_ioctl.c" -#include #include -#include #define CODE #include "compat_ioctl.c" diff --git a/arch/ppc64/kernel/iomap.c b/arch/ppc64/kernel/iomap.c index b70a9240c..675795295 100644 --- a/arch/ppc64/kernel/iomap.c +++ b/arch/ppc64/kernel/iomap.c @@ -1,3 +1,10 @@ +/* + * arch/ppc64/kernel/iomap.c + * + * ppc64 "iomap" interface implementation. + * + * (C) Copyright 2004 Linus Torvalds + */ #include #include #include diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c index 5cac0d240..7221346dc 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/ppc64/kernel/iommu.c @@ -33,12 +33,12 @@ #include #include #include +#include #include #include #include #include #include -#include #define DBG(...) @@ -59,13 +59,18 @@ static int __init setup_iommu(char *str) __setup("iommu=", setup_iommu); -static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long npages, - unsigned long *handle) +static unsigned long iommu_range_alloc(struct iommu_table *tbl, + unsigned long npages, + unsigned long *handle, + unsigned int align_order) { unsigned long n, end, i, start; unsigned long limit; int largealloc = npages > 15; int pass = 0; + unsigned long align_mask; + + align_mask = 0xffffffffffffffffl >> (64 - align_order); /* This allocator was derived from x86_64's bit string search */ @@ -97,6 +102,10 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np again: n = find_next_zero_bit(tbl->it_map, limit, start); + + /* Align allocation */ + n = (n + align_mask) & ~align_mask; + end = n + npages; if (unlikely(end >= limit)) { @@ -141,14 +150,15 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long np } static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, - unsigned int npages, enum dma_data_direction direction) + unsigned int npages, enum dma_data_direction direction, + unsigned int align_order) { unsigned long entry, flags; dma_addr_t ret = DMA_ERROR_CODE; spin_lock_irqsave(&(tbl->it_lock), flags); - entry = iommu_range_alloc(tbl, npages, NULL); + entry = iommu_range_alloc(tbl, npages, NULL, align_order); if (unlikely(entry == DMA_ERROR_CODE)) { spin_unlock_irqrestore(&(tbl->it_lock), flags); @@ -229,7 +239,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - dma_addr_t dma_next, dma_addr; + dma_addr_t dma_next = 0, dma_addr; unsigned long flags; struct scatterlist *s, *outs, *segstart; int outcount; @@ -264,7 +274,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, vaddr = (unsigned long)page_address(s->page) + s->offset; npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); npages >>= PAGE_SHIFT; - entry = iommu_range_alloc(tbl, npages, &handle); + entry = iommu_range_alloc(tbl, npages, &handle, 0); DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); @@ -425,6 +435,39 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl) return tbl; } +void iommu_free_table(struct device_node *dn) +{ + struct iommu_table *tbl = dn->iommu_table; + unsigned long bitmap_sz, i; + unsigned int order; + + if (!tbl || !tbl->it_map) { + printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__, + dn->full_name); + return; + } + + /* verify that table contains no entries */ + /* it_mapsize is in entries, and we're examining 64 at a time */ + for (i = 0; i < (tbl->it_mapsize/64); i++) { + if (tbl->it_map[i] != 0) { + printk(KERN_WARNING "%s: Unexpected TCEs for %s\n", + __FUNCTION__, dn->full_name); + break; + } + } + + /* calculate bitmap size in bytes */ + bitmap_sz = (tbl->it_mapsize + 7) / 8; + + /* free bitmap */ + order = get_order(bitmap_sz); + free_pages((unsigned long) tbl->it_map, order); + + /* free table */ + kfree(tbl); +} + /* Creates TCEs for a user provided buffer. The user buffer must be * contiguous real kernel storage (not vmalloc). The address of the buffer * passed here is the kernel (virtual) address of the buffer. The buffer @@ -445,7 +488,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, npages >>= PAGE_SHIFT; if (tbl) { - dma_handle = iommu_alloc(tbl, vaddr, npages, direction); + dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0); if (dma_handle == DMA_ERROR_CODE) { if (printk_ratelimit()) { printk(KERN_INFO "iommu_alloc failed, " @@ -504,7 +547,7 @@ void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size, memset(ret, 0, size); /* Set up tces to cover the allocated range */ - mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL); + mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order); if (mapping == DMA_ERROR_CODE) { free_pages((unsigned long)ret, order); ret = NULL; diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 846168746..9410bbf26 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -41,9 +41,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -59,259 +60,12 @@ extern void iSeries_smp_message_recv( struct pt_regs * ); #endif -static void register_irq_proc (unsigned int irq); - -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .lock = SPIN_LOCK_UNLOCKED - } -}; +extern irq_desc_t irq_desc[NR_IRQS]; int __irq_offset_value; int ppc_spurious_interrupts; unsigned long lpevent_count; -int -setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - unsigned long flags; - struct irqaction *old, **p; - irq_desc_t *desc = get_irq_desc(irq); - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); - if (desc->handler && desc->handler->startup) - desc->handler->startup(irq); - unmask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - register_irq_proc(irq); - return 0; -} - -#ifdef CONFIG_SMP - -inline void synchronize_irq(unsigned int irq) -{ - while (get_irq_desc(irq)->status & IRQ_INPROGRESS) - cpu_relax(); -} - -EXPORT_SYMBOL(synchronize_irq); - -#endif /* CONFIG_SMP */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - struct irqaction *action; - int retval; - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) { - printk(KERN_ERR "kmalloc() failed for irq %d !\n", irq); - return -ENOMEM; - } - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->dev_id = dev_id; - action->next = NULL; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - - return 0; -} - -EXPORT_SYMBOL(request_irq); - -void free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc = get_irq_desc(irq); - struct irqaction **p; - unsigned long flags; - - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - break; - } - return; -} - -EXPORT_SYMBOL(free_irq); - -/* - * 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 of an interrupt - * stack. 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. - */ - -inline void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = get_irq_desc(irq); - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - if (!(desc->status & IRQ_PER_CPU)) - desc->status |= IRQ_DISABLED; - mask_irq(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables of an interrupt - * stack. That is for two disables you need two enables. 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. - */ - -void disable_irq(unsigned int irq) -{ - irq_desc_t *desc = get_irq_desc(irq); - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} - -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line - * providing no disable_irq calls are now in effect. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = get_irq_desc(irq); - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - unmask_irq(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(enable_irq); - int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -359,105 +113,7 @@ skip: return 0; } -int handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) -{ - int status = 0; - int retval = 0; - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - return retval; -} - -static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - struct irqaction *action; - - if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { - printk(KERN_ERR "irq event %d: bogus return value %x\n", - irq, action_ret); - } else { - printk(KERN_ERR "irq %d: nobody cared!\n", irq); - } - dump_stack(); - printk(KERN_ERR "handlers:\n"); - action = desc->action; - do { - printk(KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", - (unsigned long)action->handler); - printk("\n"); - action = action->next; - } while (action); -} - -static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - static int count = 100; - - if (count) { - count--; - __report_bad_irq(irq, desc, action_ret); - } -} - -static int noirqdebug; - -static int __init noirqdebug_setup(char *str) -{ - noirqdebug = 1; - printk("IRQ lockup detection disabled\n"); - return 1; -} - -__setup("noirqdebug", noirqdebug_setup); - -/* - * If 99,900 of the previous 100,000 interrupts have not been handled then - * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to - * turn the IRQ off. - * - * (The other 100-of-100,000 interrupts may have been a correctly-functioning - * device sharing an IRQ with the failing one) - * - * Called under desc->lock - */ -static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) -{ - if (action_ret != IRQ_HANDLED) { - desc->irqs_unhandled++; - if (action_ret != IRQ_NONE) - report_bad_irq(irq, desc, action_ret); - } - - desc->irq_count++; - if (desc->irq_count < 100000) - return; - - desc->irq_count = 0; - if (desc->irqs_unhandled > 99900) { - /* - * The interrupt is stuck - */ - __report_bad_irq(irq, desc, action_ret); - /* - * Now kill the IRQ - */ - printk(KERN_EMERG "Disabling IRQ #%d\n", irq); - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - desc->irqs_unhandled = 0; -} +extern int noirqdebug; /* * Eventually, this should take an array of interrupts and an array size @@ -479,7 +135,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) if (desc->status & IRQ_PER_CPU) { /* no locking required for CPU-local interrupts: */ ack_irq(irq); - action_ret = handle_irq_event(irq, regs, desc->action); + action_ret = handle_IRQ_event(irq, regs, desc->action); desc->handler->end(irq); return; } @@ -547,13 +203,13 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) if (curtp != irqtp) { irqtp->task = curtp->task; irqtp->flags = 0; - action_ret = call_handle_irq_event(irq, regs, action, irqtp); + action_ret = call_handle_IRQ_event(irq, regs, action, irqtp); irqtp->task = NULL; if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } else #endif - action_ret = handle_irq_event(irq, regs, action); + action_ret = handle_IRQ_event(irq, regs, action); spin_lock(&desc->lock); if (!noirqdebug) @@ -586,13 +242,13 @@ void do_IRQ(struct pt_regs *regs) irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 4KB free? */ + /* Debugging check for stack overflow: is there less than 2KB free? */ { long sp; sp = __get_SP() & (THREAD_SIZE-1); - if (unlikely(sp < (sizeof(struct thread_info) + 4096))) { + if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { printk("do_IRQ: stack overflow: %ld\n", sp - sizeof(struct thread_info)); dump_stack(); @@ -629,13 +285,13 @@ void do_IRQ(struct pt_regs *regs) irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 4KB free? */ + /* Debugging check for stack overflow: is there less than 2KB free? */ { long sp; sp = __get_SP() & (THREAD_SIZE-1); - if (unlikely(sp < (sizeof(struct thread_info) + 4096))) { + if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { printk("do_IRQ: stack overflow: %ld\n", sp - sizeof(struct thread_info)); dump_stack(); @@ -655,25 +311,6 @@ void do_IRQ(struct pt_regs *regs) } #endif /* CONFIG_PPC_ISERIES */ -unsigned long probe_irq_on (void) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -EXPORT_SYMBOL(probe_irq_off); - -unsigned int probe_irq_mask(unsigned long irqs) -{ - return 0; -} - void __init init_IRQ(void) { static int once = 0; @@ -687,179 +324,6 @@ void __init init_IRQ(void) irq_ctx_init(); } -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; -static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; - -/* Protected by get_irq_desc(irq)->lock. */ -#ifdef CONFIG_IRQ_ALL_CPUS -cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; -#else /* CONFIG_IRQ_ALL_CPUS */ -cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_NONE }; -#endif /* CONFIG_IRQ_ALL_CPUS */ - -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int irq_affinity_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned int irq = (long)data; - irq_desc_t *desc = get_irq_desc(irq); - int ret; - cpumask_t new_value, tmp; - - if (!desc->handler->set_affinity) - return -EIO; - - ret = cpumask_parse(buffer, count, new_value); - if (ret != 0) - return ret; - - /* - * We check for CPU_MASK_ALL in xics to send irqs to all cpus. - * In some cases CPU_MASK_ALL is smaller than the cpumask (eg - * NR_CPUS == 32 and cpumask is a long), so we mask it here to - * be consistent. - */ - cpus_and(new_value, new_value, CPU_MASK_ALL); - - /* - * Grab lock here so cpu_online_map can't change, and also - * protect irq_affinity[]. - */ - spin_lock(&desc->lock); - - /* - * 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. - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) { - ret = -EINVAL; - goto out; - } - - irq_affinity[irq] = new_value; - desc->handler->set_affinity(irq, new_value); - ret = count; - -out: - spin_unlock(&desc->lock); - return ret; -} - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data; - unsigned long full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - -#ifdef CONFIG_PPC_ISERIES - { - unsigned i; - for (i=0; inlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - - smp_affinity_entry[irq] = entry; -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for_each_irq(i) { - if (get_irq_desc(i)->handler == NULL) - continue; - register_irq_proc(i); - } -} - -irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs) -{ - return IRQ_NONE; -} - #ifndef CONFIG_PPC_ISERIES /* * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. @@ -977,7 +441,7 @@ void irq_ctx_init(void) struct thread_info *tp; int i; - for (i = 0; i < NR_CPUS; i++) { + for_each_cpu(i) { memset((void *)softirq_ctx[i], 0, THREAD_SIZE); tp = softirq_ctx[i]; tp->cpu = i; diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c index c2e320635..56d7ba87f 100644 --- a/arch/ppc64/kernel/lmb.c +++ b/arch/ppc64/kernel/lmb.c @@ -13,14 +13,51 @@ #include #include #include +#include #include #include #include #include #include -#include -struct lmb lmb __initdata; +struct lmb lmb; + +#undef DEBUG + +void lmb_dump_all(void) +{ +#ifdef DEBUG + unsigned long i; + struct lmb *_lmb = &lmb; + + udbg_printf("lmb_dump_all:\n"); + udbg_printf(" memory.cnt = 0x%lx\n", + _lmb->memory.cnt); + udbg_printf(" memory.size = 0x%lx\n", + _lmb->memory.size); + for (i=0; i < _lmb->memory.cnt ;i++) { + udbg_printf(" memory.region[0x%x].base = 0x%lx\n", + i, _lmb->memory.region[i].base); + udbg_printf(" .physbase = 0x%lx\n", + _lmb->memory.region[i].physbase); + udbg_printf(" .size = 0x%lx\n", + _lmb->memory.region[i].size); + } + + udbg_printf("\n reserved.cnt = 0x%lx\n", + _lmb->reserved.cnt); + udbg_printf(" reserved.size = 0x%lx\n", + _lmb->reserved.size); + for (i=0; i < _lmb->reserved.cnt ;i++) { + udbg_printf(" reserved.region[0x%x].base = 0x%lx\n", + i, _lmb->reserved.region[i].base); + udbg_printf(" .physbase = 0x%lx\n", + _lmb->reserved.region[i].physbase); + udbg_printf(" .size = 0x%lx\n", + _lmb->reserved.region[i].size); + } +#endif /* DEBUG */ +} static unsigned long __init lmb_addrs_overlap(unsigned long base1, unsigned long size1, @@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2) void __init lmb_init(void) { - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; /* Create a dummy zero size LMB which will get coalesced away later. * This simplifies the lmb_add() code below... @@ -94,8 +130,7 @@ lmb_analyze(void) unsigned long i; unsigned long mem_size = 0; unsigned long size_mask = 0; - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; #ifdef CONFIG_MSCHUNKS unsigned long physbase = 0; #endif @@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size) long __init lmb_add(unsigned long base, unsigned long size) { - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; struct lmb_region *_rgn = &(_lmb->memory); /* On pSeries LPAR systems, the first LMB is our RMO region. */ @@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size) long __init lmb_reserve(unsigned long base, unsigned long size) { - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; struct lmb_region *_rgn = &(_lmb->reserved); return lmb_add_region(_rgn, base, size); @@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) { long i, j; unsigned long base = 0; - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_rsv = &(_lmb->reserved); @@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) unsigned long __init lmb_phys_mem_size(void) { - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; #ifdef CONFIG_MSCHUNKS return _lmb->memory.size; #else @@ -282,8 +313,7 @@ lmb_phys_mem_size(void) unsigned long __init lmb_end_of_DRAM(void) { - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; struct lmb_region *_mem = &(_lmb->memory); int idx = _mem->cnt - 1; @@ -300,8 +330,7 @@ unsigned long __init lmb_abs_to_phys(unsigned long aa) { unsigned long i, pa = aa; - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb *_lmb = &lmb; struct lmb_region *_mem = &(_lmb->memory); for (i=0; i < _mem->cnt; i++) { diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index d729105e5..cb33cc536 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -34,36 +34,64 @@ #include #include -#define MODULE_VERS "1.3" +#define MODULE_VERS "1.5" #define MODULE_NAME "lparcfg" /* #define LPARCFG_DEBUG */ /* find a better place for this function... */ -void log_plpar_hcall_return(unsigned long rc,char * tag) +void log_plpar_hcall_return(unsigned long rc, char *tag) { - if (rc ==0 ) /* success, return */ + if (rc == 0) /* success, return */ return; /* check for null tag ? */ if (rc == H_Hardware) - printk(KERN_INFO "plpar-hcall (%s) failed with hardware fault\n",tag); + printk(KERN_INFO + "plpar-hcall (%s) failed with hardware fault\n", tag); else if (rc == H_Function) - printk(KERN_INFO "plpar-hcall (%s) failed; function not allowed\n",tag); + printk(KERN_INFO + "plpar-hcall (%s) failed; function not allowed\n", tag); else if (rc == H_Authority) - printk(KERN_INFO "plpar-hcall (%s) failed; not authorized to this function\n",tag); + printk(KERN_INFO + "plpar-hcall (%s) failed; not authorized to this function\n", + tag); else if (rc == H_Parameter) - printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",tag); + printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n", + tag); else - printk(KERN_INFO "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",tag,rc); + printk(KERN_INFO + "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n", + tag, rc); } - static struct proc_dir_entry *proc_ppc64_lparcfg; #define LPARCFG_BUFF_SIZE 4096 #ifdef CONFIG_PPC_ISERIES +/* + * For iSeries legacy systems, the PPA purr function is available from the + * xEmulatedTimeBase field in the paca. + */ +static unsigned long get_purr(void) +{ + unsigned long sum_purr = 0; + int cpu; + struct paca_struct *lpaca; + + for_each_cpu(cpu) { + lpaca = paca + cpu; + sum_purr += lpaca->lppaca.xEmulatedTimeBase; + +#ifdef PURR_DEBUG + printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", + cpu, lpaca->lppaca.xEmulatedTimeBase); +#endif + } + return sum_purr; +} + #define lparcfg_write NULL /* @@ -75,62 +103,67 @@ static int lparcfg_data(struct seq_file *m, void *v) int shared, entitled_capacity, max_entitled_capacity; int processors, max_processors; struct paca_struct *lpaca = get_paca(); + unsigned long purr = get_purr(); + + seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); shared = (int)(lpaca->lppaca_ptr->xSharedProc); seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", - e2a(xItExtVpdPanel.mfgID[2]), - e2a(xItExtVpdPanel.mfgID[3]), - e2a(xItExtVpdPanel.systemSerial[1]), - e2a(xItExtVpdPanel.systemSerial[2]), - e2a(xItExtVpdPanel.systemSerial[3]), - e2a(xItExtVpdPanel.systemSerial[4]), - e2a(xItExtVpdPanel.systemSerial[5])); + e2a(xItExtVpdPanel.mfgID[2]), + e2a(xItExtVpdPanel.mfgID[3]), + e2a(xItExtVpdPanel.systemSerial[1]), + e2a(xItExtVpdPanel.systemSerial[2]), + e2a(xItExtVpdPanel.systemSerial[3]), + e2a(xItExtVpdPanel.systemSerial[4]), + e2a(xItExtVpdPanel.systemSerial[5])); seq_printf(m, "system_type=%c%c%c%c\n", - e2a(xItExtVpdPanel.machineType[0]), - e2a(xItExtVpdPanel.machineType[1]), - e2a(xItExtVpdPanel.machineType[2]), - e2a(xItExtVpdPanel.machineType[3])); + e2a(xItExtVpdPanel.machineType[0]), + e2a(xItExtVpdPanel.machineType[1]), + e2a(xItExtVpdPanel.machineType[2]), + e2a(xItExtVpdPanel.machineType[3])); - lp_index = HvLpConfig_getLpIndex(); + lp_index = HvLpConfig_getLpIndex(); seq_printf(m, "partition_id=%d\n", (int)lp_index); seq_printf(m, "system_active_processors=%d\n", - (int)HvLpConfig_getSystemPhysicalProcessors()); + (int)HvLpConfig_getSystemPhysicalProcessors()); seq_printf(m, "system_potential_processors=%d\n", - (int)HvLpConfig_getSystemPhysicalProcessors()); + (int)HvLpConfig_getSystemPhysicalProcessors()); - processors = (int)HvLpConfig_getPhysicalProcessors(); + processors = (int)HvLpConfig_getPhysicalProcessors(); seq_printf(m, "partition_active_processors=%d\n", processors); - max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); + max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); seq_printf(m, "partition_potential_processors=%d\n", max_processors); - if(shared) { - entitled_capacity = HvLpConfig_getSharedProcUnits(); - max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits(); + if (shared) { + entitled_capacity = HvLpConfig_getSharedProcUnits(); + max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits(); } else { - entitled_capacity = processors * 100; - max_entitled_capacity = max_processors * 100; + entitled_capacity = processors * 100; + max_entitled_capacity = max_processors * 100; } seq_printf(m, "partition_entitled_capacity=%d\n", entitled_capacity); seq_printf(m, "partition_max_entitled_capacity=%d\n", - max_entitled_capacity); + max_entitled_capacity); - if(shared) { - pool_id = HvLpConfig_getSharedPoolIndex(); + if (shared) { + pool_id = HvLpConfig_getSharedPoolIndex(); seq_printf(m, "pool=%d\n", (int)pool_id); seq_printf(m, "pool_capacity=%d\n", - (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100)); + (int)(HvLpConfig_getNumProcsInSharedPool(pool_id) * + 100)); + seq_printf(m, "purr=%ld\n", purr); } seq_printf(m, "shared_processor_mode=%d\n", shared); return 0; } -#endif /* CONFIG_PPC_ISERIES */ +#endif /* CONFIG_PPC_ISERIES */ #ifdef CONFIG_PPC_PSERIES /* @@ -158,11 +191,13 @@ static int lparcfg_data(struct seq_file *m, void *v) * XXXX - Processors active on platform. */ static unsigned int h_get_ppp(unsigned long *entitled, - unsigned long *unallocated, unsigned long *aggregation, - unsigned long *resource) + unsigned long *unallocated, + unsigned long *aggregation, + unsigned long *resource) { unsigned long rc; - rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource); + rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated, + aggregation, resource); log_plpar_hcall_return(rc, "H_GET_PPP"); @@ -183,9 +218,9 @@ static unsigned long get_purr(void); * is coming, but at this time is still problematic, so for now this * function will return 0. */ -static unsigned long get_purr() +static unsigned long get_purr(void) { - unsigned long sum_purr=0; + unsigned long sum_purr = 0; return sum_purr; } @@ -202,7 +237,7 @@ static void parse_system_parameter_string(struct seq_file *m) { int call_status; - char * local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); + char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); if (!local_buffer) { printk(KERN_ERR "%s %s kmalloc failure at line %d \n", __FILE__, __FUNCTION__, __LINE__); @@ -219,22 +254,23 @@ static void parse_system_parameter_string(struct seq_file *m) spin_unlock(&rtas_data_buf_lock); if (call_status != 0) { - printk(KERN_INFO "%s %s Error calling get-system-parameter (0x%x)\n", + printk(KERN_INFO + "%s %s Error calling get-system-parameter (0x%x)\n", __FILE__, __FUNCTION__, call_status); } else { int splpar_strlen; int idx, w_idx; - char * workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); + char *workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); if (!workbuffer) { - printk(KERN_ERR "%s %s kmalloc failure at line %d \n",__FILE__,__FUNCTION__,__LINE__); + printk(KERN_ERR "%s %s kmalloc failure at line %d \n", + __FILE__, __FUNCTION__, __LINE__); return; } - #ifdef LPARCFG_DEBUG printk(KERN_INFO "success calling get-system-parameter \n"); #endif splpar_strlen = local_buffer[0] * 16 + local_buffer[1]; - local_buffer += 2; /* step over strlen value */ + local_buffer += 2; /* step over strlen value */ memset(workbuffer, 0, SPLPAR_MAXLENGTH); w_idx = 0; @@ -253,13 +289,15 @@ static void parse_system_parameter_string(struct seq_file *m) w_idx = 0; } else if (local_buffer[idx] == '=') { /* code here to replace workbuffer contents - with different keyword strings */ - if (0 == strcmp(workbuffer,"MaxEntCap")) { - strcpy(workbuffer, "partition_max_entitled_capacity"); + with different keyword strings */ + if (0 == strcmp(workbuffer, "MaxEntCap")) { + strcpy(workbuffer, + "partition_max_entitled_capacity"); w_idx = strlen(workbuffer); } - if (0 == strcmp(workbuffer,"MaxPlatProcs")) { - strcpy(workbuffer, "system_potential_processors"); + if (0 == strcmp(workbuffer, "MaxPlatProcs")) { + strcpy(workbuffer, + "system_potential_processors"); w_idx = strlen(workbuffer); } } @@ -283,7 +321,7 @@ static int lparcfg_count_active_processors(void) while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) { #ifdef LPARCFG_DEBUG - printk(KERN_ERR "cpus_dn %p \n",cpus_dn); + printk(KERN_ERR "cpus_dn %p \n", cpus_dn); #endif count++; } @@ -292,7 +330,8 @@ static int lparcfg_count_active_processors(void) static int lparcfg_data(struct seq_file *m, void *v) { - int system_active_processors; + int partition_potential_processors; + int partition_active_processors; struct device_node *rootdn; const char *model = ""; const char *system_id = ""; @@ -305,12 +344,11 @@ static int lparcfg_data(struct seq_file *m, void *v) model = get_property(rootdn, "model", NULL); system_id = get_property(rootdn, "system-id", NULL); lp_index_ptr = (unsigned int *) - get_property(rootdn, "ibm,partition-no", NULL); + get_property(rootdn, "ibm,partition-no", NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; } - seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); seq_printf(m, "serial_number=%s\n", system_id); @@ -323,11 +361,13 @@ static int lparcfg_data(struct seq_file *m, void *v) lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); if (lrdrp == NULL) { - system_active_processors = systemcfg->processorCount; + partition_potential_processors = systemcfg->processorCount; } else { - system_active_processors = *(lrdrp + 4); + partition_potential_processors = *(lrdrp + 4); } + partition_active_processors = lparcfg_count_active_processors(); + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { unsigned long h_entitled, h_unallocated; unsigned long h_aggregation, h_resource; @@ -342,71 +382,69 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "R6=0x%lx\n", h_aggregation); seq_printf(m, "R7=0x%lx\n", h_resource); - h_pic(&pool_idle_time, &pool_procs); - purr = get_purr(); /* this call handles the ibm,get-system-parameter contents */ parse_system_parameter_string(m); - seq_printf(m, "partition_entitled_capacity=%ld\n", - h_entitled); - - seq_printf(m, "pool=%ld\n", - (h_aggregation >> 0*8) & 0xffff); + seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled); - seq_printf(m, "group=%ld\n", - (h_aggregation >> 2*8) & 0xffff); + seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff); seq_printf(m, "system_active_processors=%ld\n", - (h_resource >> 0*8) & 0xffff); + (h_resource >> 0 * 8) & 0xffff); + + /* pool related entries are apropriate for shared configs */ + if (paca[0].lppaca.xSharedProc) { - seq_printf(m, "pool_capacity=%ld\n", - (h_resource >> 2*8) & 0xffff); + h_pic(&pool_idle_time, &pool_procs); + + seq_printf(m, "pool=%ld\n", + (h_aggregation >> 0 * 8) & 0xffff); + + /* report pool_capacity in percentage */ + seq_printf(m, "pool_capacity=%ld\n", + ((h_resource >> 2 * 8) & 0xffff) * 100); + + seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time); + + seq_printf(m, "pool_num_procs=%ld\n", pool_procs); + } seq_printf(m, "unallocated_capacity_weight=%ld\n", - (h_resource >> 4*8) & 0xFF); + (h_resource >> 4 * 8) & 0xFF); seq_printf(m, "capacity_weight=%ld\n", - (h_resource >> 5*8) & 0xFF); - - seq_printf(m, "capped=%ld\n", - (h_resource >> 6*8) & 0x01); + (h_resource >> 5 * 8) & 0xFF); - seq_printf(m, "unallocated_capacity=%ld\n", - h_unallocated); + seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01); - seq_printf(m, "pool_idle_time=%ld\n", - pool_idle_time); + seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); - seq_printf(m, "pool_num_procs=%ld\n", - pool_procs); + seq_printf(m, "purr=%ld\n", purr); - seq_printf(m, "purr=%ld\n", - purr); + } else { /* non SPLPAR case */ - } else /* non SPLPAR case */ { seq_printf(m, "system_active_processors=%d\n", - system_active_processors); + partition_potential_processors); seq_printf(m, "system_potential_processors=%d\n", - system_active_processors); + partition_potential_processors); seq_printf(m, "partition_max_entitled_capacity=%d\n", - 100*system_active_processors); + partition_potential_processors * 100); seq_printf(m, "partition_entitled_capacity=%d\n", - system_active_processors*100); + partition_active_processors * 100); } seq_printf(m, "partition_active_processors=%d\n", - (int) lparcfg_count_active_processors()); + partition_active_processors); seq_printf(m, "partition_potential_processors=%d\n", - system_active_processors); + partition_potential_processors); - seq_printf(m, "shared_processor_mode=%d\n", - paca[0].lppaca.xSharedProc); + seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.xSharedProc); return 0; } @@ -421,14 +459,15 @@ static int lparcfg_data(struct seq_file *m, void *v) * This function should be invoked only on systems with * FW_FEATURE_SPLPAR. */ -static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t count, loff_t *off) +static ssize_t lparcfg_write(struct file *file, const char __user * buf, + size_t count, loff_t * off) { char *kbuf; char *tmp; u64 new_entitled, *new_entitled_ptr = &new_entitled; u8 new_weight, *new_weight_ptr = &new_weight; - unsigned long current_entitled; /* parameters for h_get_ppp */ + unsigned long current_entitled; /* parameters for h_get_ppp */ unsigned long dummy; unsigned long resource; u8 current_weight; @@ -453,13 +492,13 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c if (!strcmp(kbuf, "partition_entitled_capacity")) { char *endp; - *new_entitled_ptr = (u64)simple_strtoul(tmp, &endp, 10); + *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); if (endp == tmp) goto out; new_weight_ptr = ¤t_weight; } else if (!strcmp(kbuf, "capacity_weight")) { char *endp; - *new_weight_ptr = (u8)simple_strtoul(tmp, &endp, 10); + *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); if (endp == tmp) goto out; new_entitled_ptr = ¤t_entitled; @@ -473,7 +512,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c goto out; } - current_weight = (resource>>5*8)&0xFF; + current_weight = (resource >> 5 * 8) & 0xFF; pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", __FUNCTION__, current_entitled, current_weight); @@ -498,23 +537,23 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c retval = -EIO; } -out: + out: kfree(kbuf); return retval; } -#endif /* CONFIG_PPC_PSERIES */ +#endif /* CONFIG_PPC_PSERIES */ -static int lparcfg_open(struct inode * inode, struct file * file) +static int lparcfg_open(struct inode *inode, struct file *file) { - return single_open(file,lparcfg_data,NULL); + return single_open(file, lparcfg_data, NULL); } struct file_operations lparcfg_fops = { - owner: THIS_MODULE, - read: seq_read, - open: lparcfg_open, - release: single_release, + .owner = THIS_MODULE, + .read = seq_read, + .open = lparcfg_open, + .release = single_release, }; int __init lparcfg_init(void) @@ -533,7 +572,8 @@ int __init lparcfg_init(void) ent->proc_fops = &lparcfg_fops; ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL); if (!ent->data) { - printk(KERN_ERR "Failed to allocate buffer for lparcfg\n"); + printk(KERN_ERR + "Failed to allocate buffer for lparcfg\n"); remove_proc_entry("lparcfg", ent->parent); return -ENOMEM; } @@ -550,7 +590,7 @@ void __exit lparcfg_cleanup(void) { if (proc_ppc64_lparcfg) { if (proc_ppc64_lparcfg->data) { - kfree(proc_ppc64_lparcfg->data); + kfree(proc_ppc64_lparcfg->data); } remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent); } diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c index 02a68b116..1bd52ece4 100644 --- a/arch/ppc64/kernel/mf.c +++ b/arch/ppc64/kernel/mf.c @@ -1,6 +1,7 @@ /* * mf.c * Copyright (C) 2001 Troy D. Armstrong IBM Corporation + * Copyright (C) 2004 Stephen Rothwell IBM Corporation * * This modules exists as an interface between a Linux secondary partition * running on an iSeries and the primary partition's Virtual Service @@ -8,52 +9,44 @@ * all partitions in the iSeries. It also provides miscellaneous low-level * machine facility type operations. * - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include #include -#include -#include #include -#include -#include #include -#include -#include -#include -#include #include #include + +#include +#include #include +#include +#include +#include /* * This is the structure layout for the Machine Facilites LPAR event * flows. */ -union safe_cast { - u64 ptr_as_u64; - void *ptr; -}; - -struct VspCmdData { - union safe_cast token; +struct vsp_cmd_data { + u64 token; u16 cmd; HvLpIndex lp_index; u8 result_code; @@ -81,12 +74,12 @@ struct VspCmdData { } sub_data; }; -struct VspRspData { +struct vsp_rsp_data { struct completion com; - struct VspCmdData *response; + struct vsp_cmd_data *response; }; -struct AllocData { +struct alloc_data { u16 size; u16 type; u32 count; @@ -95,30 +88,30 @@ struct AllocData { HvLpIndex target_lp; }; -struct CeMsgData; +struct ce_msg_data; -typedef void (*CeMsgCompleteHandler)(void *token, struct CeMsgData *vspCmdRsp); +typedef void (*ce_msg_comp_hdlr)(void *token, struct ce_msg_data *vsp_cmd_rsp); -struct CeMsgCompleteData { - CeMsgCompleteHandler handler; +struct ce_msg_comp_data { + ce_msg_comp_hdlr handler; void *token; }; -struct CeMsgData { +struct ce_msg_data { u8 ce_msg[12]; char reserved[4]; - struct CeMsgCompleteData *completion; + struct ce_msg_comp_data *completion; }; -struct IoMFLpEvent { +struct io_mf_lp_event { struct HvLpEvent hp_lp_event; u16 subtype_result_code; u16 reserved1; u32 reserved2; union { - struct AllocData alloc; - struct CeMsgData ce_msg; - struct VspCmdData vsp_cmd; + struct alloc_data alloc; + struct ce_msg_data ce_msg; + struct vsp_cmd_data vsp_cmd; } data; }; @@ -134,7 +127,7 @@ struct IoMFLpEvent { */ struct pending_event { struct pending_event *next; - struct IoMFLpEvent event; + struct io_mf_lp_event event; MFCompleteHandler hdlr; char dma_data[72]; unsigned dma_data_length; @@ -172,7 +165,7 @@ static int signal_event(struct pending_event *ev) unsigned long flags; int go = 1; struct pending_event *ev1; - HvLpEvent_Rc hvRc; + HvLpEvent_Rc hv_rc; /* enqueue the event */ if (ev != NULL) { @@ -199,11 +192,11 @@ static int signal_event(struct pending_event *ev) pending_event_head->dma_data_length, HvLpDma_Direction_LocalToRemote); - hvRc = HvCallEvent_signalLpEvent( + hv_rc = HvCallEvent_signalLpEvent( &pending_event_head->event.hp_lp_event); - if (hvRc != HvLpEvent_Rc_Good) { - printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() failed with %d\n", - (int)hvRc); + if (hv_rc != HvLpEvent_Rc_Good) { + printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() " + "failed with %d\n", (int)hv_rc); spin_lock_irqsave(&pending_event_spinlock, flags); ev1 = pending_event_head; @@ -214,12 +207,8 @@ static int signal_event(struct pending_event *ev) if (ev1 == ev) rc = -EIO; - else if (ev1->hdlr != NULL) { - union safe_cast mySafeCast; - - mySafeCast.ptr_as_u64 = ev1->event.hp_lp_event.xCorrelationToken; - (*ev1->hdlr)(mySafeCast.ptr, -EIO); - } + else if (ev1->hdlr != NULL) + (*ev1->hdlr)((void *)ev1->event.hp_lp_event.xCorrelationToken, -EIO); spin_lock_irqsave(&pending_event_spinlock, flags); free_pending_event(ev1); @@ -236,7 +225,7 @@ static int signal_event(struct pending_event *ev) static struct pending_event *new_pending_event(void) { struct pending_event *ev = NULL; - HvLpIndex primaryLp = HvLpConfig_getPrimaryLpIndex(); + HvLpIndex primary_lp = HvLpConfig_getPrimaryLpIndex(); unsigned long flags; struct HvLpEvent *hev; @@ -246,12 +235,13 @@ static struct pending_event *new_pending_event(void) pending_event_avail = pending_event_avail->next; } spin_unlock_irqrestore(&pending_event_spinlock, flags); - if (ev == NULL) - ev = kmalloc(sizeof(struct pending_event),GFP_ATOMIC); if (ev == NULL) { - printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n", - sizeof(struct pending_event)); - return NULL; + ev = kmalloc(sizeof(struct pending_event), GFP_ATOMIC); + if (ev == NULL) { + printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n", + sizeof(struct pending_event)); + return NULL; + } } memset(ev, 0, sizeof(struct pending_event)); hev = &ev->event.hp_lp_event; @@ -261,38 +251,38 @@ static struct pending_event *new_pending_event(void) hev->xFlags.xFunction = HvLpEvent_Function_Int; hev->xType = HvLpEvent_Type_MachineFac; hev->xSourceLp = HvLpConfig_getLpIndex(); - hev->xTargetLp = primaryLp; - hev->xSizeMinus1 = sizeof(ev->event)-1; + hev->xTargetLp = primary_lp; + hev->xSizeMinus1 = sizeof(ev->event) - 1; hev->xRc = HvLpEvent_Rc_Good; - hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primaryLp, + hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primary_lp, HvLpEvent_Type_MachineFac); - hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primaryLp, + hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primary_lp, HvLpEvent_Type_MachineFac); return ev; } -static int signal_vsp_instruction(struct VspCmdData *vspCmd) +static int signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd) { struct pending_event *ev = new_pending_event(); int rc; - struct VspRspData response; + struct vsp_rsp_data response; if (ev == NULL) return -ENOMEM; init_completion(&response.com); - response.response = vspCmd; + response.response = vsp_cmd; ev->event.hp_lp_event.xSubtype = 6; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'V', 'I'); - ev->event.data.vsp_cmd.token.ptr = &response; - ev->event.data.vsp_cmd.cmd = vspCmd->cmd; + ev->event.data.vsp_cmd.token = (u64)&response; + ev->event.data.vsp_cmd.cmd = vsp_cmd->cmd; ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); ev->event.data.vsp_cmd.result_code = 0xFF; ev->event.data.vsp_cmd.reserved = 0; memcpy(&(ev->event.data.vsp_cmd.sub_data), - &(vspCmd->sub_data), sizeof(vspCmd->sub_data)); + &(vsp_cmd->sub_data), sizeof(vsp_cmd->sub_data)); mb(); rc = signal_event(ev); @@ -305,7 +295,7 @@ static int signal_vsp_instruction(struct VspCmdData *vspCmd) /* * Send a 12-byte CE message to the primary partition VSP object */ -static int signal_ce_msg(char *ce_msg, struct CeMsgCompleteData *completion) +static int signal_ce_msg(char *ce_msg, struct ce_msg_comp_data *completion) { struct pending_event *ev = new_pending_event(); @@ -320,11 +310,23 @@ static int signal_ce_msg(char *ce_msg, struct CeMsgCompleteData *completion) return signal_event(ev); } +/* + * Send a 12-byte CE message (with no data) to the primary partition VSP object + */ +static int signal_ce_msg_simple(u8 ce_op, struct ce_msg_comp_data *completion) +{ + u8 ce_msg[12]; + + memset(ce_msg, 0, sizeof(ce_msg)); + ce_msg[3] = ce_op; + return signal_ce_msg(ce_msg, completion); +} + /* * Send a 12-byte CE message and DMA data to the primary partition VSP object */ static int dma_and_signal_ce_msg(char *ce_msg, - struct CeMsgCompleteData *completion, void *dma_data, + struct ce_msg_comp_data *completion, void *dma_data, unsigned dma_data_length, unsigned remote_address) { struct pending_event *ev = new_pending_event(); @@ -356,7 +358,7 @@ static int shutdown(void) if (rc) { printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), " "hard shutdown commencing\n", rc); - mf_powerOff(); + mf_power_off(); } else printk(KERN_INFO "mf.c: init has been successfully notified " "to proceed with shutdown\n"); @@ -367,10 +369,12 @@ static int shutdown(void) * The primary partition VSP object is sending us a new * event flow. Handle it... */ -static void intReceived(struct IoMFLpEvent *event) +static void handle_int(struct io_mf_lp_event *event) { - int freeIt = 0; - struct pending_event *two = NULL; + struct ce_msg_data *ce_msg_data; + struct ce_msg_data *pce_msg_data; + unsigned long flags; + struct pending_event *pev; /* ack the interrupt */ event->hp_lp_event.xRc = HvLpEvent_Rc_Good; @@ -379,49 +383,42 @@ static void intReceived(struct IoMFLpEvent *event) /* process interrupt */ switch (event->hp_lp_event.xSubtype) { case 0: /* CE message */ - switch (event->data.ce_msg.ce_msg[3]) { + ce_msg_data = &event->data.ce_msg; + switch (ce_msg_data->ce_msg[3]) { case 0x5B: /* power control notification */ - if ((event->data.ce_msg.ce_msg[5] & 0x20) != 0) { + if ((ce_msg_data->ce_msg[5] & 0x20) != 0) { printk(KERN_INFO "mf.c: Commencing partition shutdown\n"); if (shutdown() == 0) - signal_ce_msg("\x00\x00\x00\xDB\x00\x00\x00\x00\x00\x00\x00\x00", NULL); + signal_ce_msg_simple(0xDB, NULL); } break; case 0xC0: /* get time */ - if ((pending_event_head == NULL) || - (pending_event_head->event.data.ce_msg.ce_msg[3] - != 0x40)) + spin_lock_irqsave(&pending_event_spinlock, flags); + pev = pending_event_head; + if (pev != NULL) + pending_event_head = pending_event_head->next; + spin_unlock_irqrestore(&pending_event_spinlock, flags); + if (pev == NULL) break; - freeIt = 1; - if (pending_event_head->event.data.ce_msg.completion != 0) { - CeMsgCompleteHandler handler = pending_event_head->event.data.ce_msg.completion->handler; - void *token = pending_event_head->event.data.ce_msg.completion->token; + pce_msg_data = &pev->event.data.ce_msg; + if (pce_msg_data->ce_msg[3] != 0x40) + break; + if (pce_msg_data->completion != NULL) { + ce_msg_comp_hdlr handler = + pce_msg_data->completion->handler; + void *token = pce_msg_data->completion->token; if (handler != NULL) - (*handler)(token, &(event->data.ce_msg)); + (*handler)(token, ce_msg_data); } - break; - } - - /* remove from queue */ - if (freeIt == 1) { - unsigned long flags; - spin_lock_irqsave(&pending_event_spinlock, flags); - if (pending_event_head != NULL) { - struct pending_event *oldHead = - pending_event_head; - - pending_event_head = pending_event_head->next; - two = pending_event_head; - free_pending_event(oldHead); - } + free_pending_event(pev); spin_unlock_irqrestore(&pending_event_spinlock, flags); + /* send next waiting event */ + if (pending_event_head != NULL) + signal_event(NULL); + break; } - - /* send next waiting event */ - if (two != NULL) - signal_event(NULL); break; case 1: /* IT sys shutdown */ printk(KERN_INFO "mf.c: Commencing system shutdown\n"); @@ -435,68 +432,70 @@ static void intReceived(struct IoMFLpEvent *event) * of a flow we sent to them. If there are other flows queued * up, we must send another one now... */ -static void ackReceived(struct IoMFLpEvent *event) +static void handle_ack(struct io_mf_lp_event *event) { unsigned long flags; - struct pending_event * two = NULL; - unsigned long freeIt = 0; + struct pending_event *two = NULL; + unsigned long free_it = 0; + struct ce_msg_data *ce_msg_data; + struct ce_msg_data *pce_msg_data; + struct vsp_rsp_data *rsp; /* handle current event */ - if (pending_event_head != NULL) { - switch (event->hp_lp_event.xSubtype) { - case 0: /* CE msg */ - if (event->data.ce_msg.ce_msg[3] == 0x40) { - if (event->data.ce_msg.ce_msg[2] != 0) { - freeIt = 1; - if (pending_event_head->event.data.ce_msg.completion - != 0) { - CeMsgCompleteHandler handler = pending_event_head->event.data.ce_msg.completion->handler; - void *token = pending_event_head->event.data.ce_msg.completion->token; - - if (handler != NULL) - (*handler)(token, &(event->data.ce_msg)); - } - } - } else - freeIt = 1; - break; - case 4: /* allocate */ - case 5: /* deallocate */ - if (pending_event_head->hdlr != NULL) { - union safe_cast mySafeCast; + if (pending_event_head == NULL) { + printk(KERN_ERR "mf.c: stack empty for receiving ack\n"); + return; + } - mySafeCast.ptr_as_u64 = event->hp_lp_event.xCorrelationToken; - (*pending_event_head->hdlr)(mySafeCast.ptr, event->data.alloc.count); - } - freeIt = 1; + switch (event->hp_lp_event.xSubtype) { + case 0: /* CE msg */ + ce_msg_data = &event->data.ce_msg; + if (ce_msg_data->ce_msg[3] != 0x40) { + free_it = 1; break; - case 6: - { - struct VspRspData *rsp = (struct VspRspData *)event->data.vsp_cmd.token.ptr; - - if (rsp != NULL) { - if (rsp->response != NULL) - memcpy(rsp->response, &(event->data.vsp_cmd), sizeof(event->data.vsp_cmd)); - complete(&rsp->com); - } else - printk(KERN_ERR "mf.c: no rsp\n"); - freeIt = 1; - } + } + if (ce_msg_data->ce_msg[2] == 0) + break; + free_it = 1; + pce_msg_data = &pending_event_head->event.data.ce_msg; + if (pce_msg_data->completion != NULL) { + ce_msg_comp_hdlr handler = + pce_msg_data->completion->handler; + void *token = pce_msg_data->completion->token; + + if (handler != NULL) + (*handler)(token, ce_msg_data); + } + break; + case 4: /* allocate */ + case 5: /* deallocate */ + if (pending_event_head->hdlr != NULL) + (*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count); + free_it = 1; + break; + case 6: + free_it = 1; + rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token; + if (rsp == NULL) { + printk(KERN_ERR "mf.c: no rsp\n"); break; } + if (rsp->response != NULL) + memcpy(rsp->response, &event->data.vsp_cmd, + sizeof(event->data.vsp_cmd)); + complete(&rsp->com); + break; } - else - printk(KERN_ERR "mf.c: stack empty for receiving ack\n"); /* remove from queue */ spin_lock_irqsave(&pending_event_spinlock, flags); - if ((pending_event_head != NULL) && (freeIt == 1)) { + if ((pending_event_head != NULL) && (free_it == 1)) { struct pending_event *oldHead = pending_event_head; pending_event_head = pending_event_head->next; two = pending_event_head; free_pending_event(oldHead); - } + } spin_unlock_irqrestore(&pending_event_spinlock, flags); /* send next waiting event */ @@ -510,15 +509,15 @@ static void ackReceived(struct IoMFLpEvent *event) * parse it enough to know if it is an interrupt or an * acknowledge. */ -static void hvHandler(struct HvLpEvent *event, struct pt_regs *regs) +static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs) { if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) { switch(event->xFlags.xFunction) { case HvLpEvent_Function_Ack: - ackReceived((struct IoMFLpEvent *)event); + handle_ack((struct io_mf_lp_event *)event); break; case HvLpEvent_Function_Int: - intReceived((struct IoMFLpEvent *)event); + handle_int((struct io_mf_lp_event *)event); break; default: printk(KERN_ERR "mf.c: non ack/int event received\n"); @@ -532,9 +531,9 @@ static void hvHandler(struct HvLpEvent *event, struct pt_regs *regs) * Global kernel interface to allocate and seed events into the * Hypervisor. */ -void mf_allocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, +void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type, unsigned size, unsigned count, MFCompleteHandler hdlr, - void *userToken) + void *user_token) { struct pending_event *ev = new_pending_event(); int rc; @@ -542,14 +541,11 @@ void mf_allocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, if (ev == NULL) { rc = -ENOMEM; } else { - union safe_cast mine; - - mine.ptr = userToken; ev->event.hp_lp_event.xSubtype = 4; - ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; + ev->event.hp_lp_event.xCorrelationToken = (u64)user_token; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'M', 'A'); - ev->event.data.alloc.target_lp = targetLp; + ev->event.data.alloc.target_lp = target_lp; ev->event.data.alloc.type = type; ev->event.data.alloc.size = size; ev->event.data.alloc.count = count; @@ -557,16 +553,16 @@ void mf_allocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, rc = signal_event(ev); } if ((rc != 0) && (hdlr != NULL)) - (*hdlr)(userToken, rc); + (*hdlr)(user_token, rc); } -EXPORT_SYMBOL(mf_allocateLpEvents); +EXPORT_SYMBOL(mf_allocate_lp_events); /* * Global kernel interface to unseed and deallocate events already in * Hypervisor. */ -void mf_deallocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, - unsigned count, MFCompleteHandler hdlr, void *userToken) +void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type, + unsigned count, MFCompleteHandler hdlr, void *user_token) { struct pending_event *ev = new_pending_event(); int rc; @@ -574,33 +570,31 @@ void mf_deallocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, if (ev == NULL) rc = -ENOMEM; else { - union safe_cast mine; - - mine.ptr = userToken; ev->event.hp_lp_event.xSubtype = 5; - ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; + ev->event.hp_lp_event.xCorrelationToken = (u64)user_token; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'M', 'D'); - ev->event.data.alloc.target_lp = targetLp; + ev->event.data.alloc.target_lp = target_lp; ev->event.data.alloc.type = type; ev->event.data.alloc.count = count; ev->hdlr = hdlr; rc = signal_event(ev); } if ((rc != 0) && (hdlr != NULL)) - (*hdlr)(userToken, rc); + (*hdlr)(user_token, rc); } -EXPORT_SYMBOL(mf_deallocateLpEvents); +EXPORT_SYMBOL(mf_deallocate_lp_events); /* * Global kernel interface to tell the VSP object in the primary * partition to power this partition off. */ -void mf_powerOff(void) +void mf_power_off(void) { printk(KERN_INFO "mf.c: Down it goes...\n"); - signal_ce_msg("\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", NULL); - for (;;); + signal_ce_msg_simple(0x4d, NULL); + for (;;) + ; } /* @@ -610,18 +604,21 @@ void mf_powerOff(void) void mf_reboot(void) { printk(KERN_INFO "mf.c: Preparing to bounce...\n"); - signal_ce_msg("\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL); - for (;;); + signal_ce_msg_simple(0x4e, NULL); + for (;;) + ; } /* * Display a single word SRC onto the VSP control panel. */ -void mf_displaySrc(u32 word) +void mf_display_src(u32 word) { u8 ce[12]; - memcpy(ce, "\x00\x00\x00\x4A\x00\x00\x00\x01\x00\x00\x00\x00", 12); + memset(ce, 0, sizeof(ce)); + ce[3] = 0x4a; + ce[7] = 0x01; ce[8] = word >> 24; ce[9] = word >> 16; ce[10] = word >> 8; @@ -632,7 +629,7 @@ void mf_displaySrc(u32 word) /* * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. */ -void mf_displayProgress(u16 value) +void mf_display_progress(u16 value) { u8 ce[12]; u8 src[72]; @@ -656,9 +653,9 @@ void mf_displayProgress(u16 value) * Clear the VSP control panel. Used to "erase" an SRC that was * previously displayed. */ -void mf_clearSrc(void) +void mf_clear_src(void) { - signal_ce_msg("\x00\x00\x00\x4B\x00\x00\x00\x00\x00\x00\x00\x00", NULL); + signal_ce_msg_simple(0x4b, NULL); } /* @@ -674,71 +671,331 @@ void mf_init(void) i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc); ++i) free_pending_event(&pending_event_prealloc[i]); - HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hvHandler); + HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler); /* virtual continue ack */ - signal_ce_msg("\x00\x00\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00", NULL); + signal_ce_msg_simple(0x57, NULL); /* initialization complete */ - printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities initialized\n"); + printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities " + "initialized\n"); } -void mf_setSide(char side) +struct rtc_time_data { + struct completion com; + struct ce_msg_data ce_msg; + int rc; +}; + +static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) { - u64 newSide; - struct VspCmdData myVspCmd; + struct rtc_time_data *rtc = token; - memset(&myVspCmd, 0, sizeof(myVspCmd)); - switch (side) { - case 'A': newSide = 0; - break; - case 'B': newSide = 1; - break; - case 'C': newSide = 2; - break; - default: newSide = 3; + memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg)); + rtc->rc = 0; + complete(&rtc->com); +} + +int mf_get_rtc(struct rtc_time *tm) +{ + struct ce_msg_comp_data ce_complete; + struct rtc_time_data rtc_data; + int rc; + + memset(&ce_complete, 0, sizeof(ce_complete)); + memset(&rtc_data, 0, sizeof(rtc_data)); + init_completion(&rtc_data.com); + ce_complete.handler = &get_rtc_time_complete; + ce_complete.token = &rtc_data; + rc = signal_ce_msg_simple(0x40, &ce_complete); + if (rc) + return rc; + wait_for_completion(&rtc_data.com); + tm->tm_wday = 0; + tm->tm_yday = 0; + tm->tm_isdst = 0; + if (rtc_data.rc) { + tm->tm_sec = 0; + tm->tm_min = 0; + tm->tm_hour = 0; + tm->tm_mday = 15; + tm->tm_mon = 5; + tm->tm_year = 52; + return rtc_data.rc; + } + + if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) || + (rtc_data.ce_msg.ce_msg[2] == 0xaf)) { + /* TOD clock is not set */ + tm->tm_sec = 1; + tm->tm_min = 1; + tm->tm_hour = 1; + tm->tm_mday = 10; + tm->tm_mon = 8; + tm->tm_year = 71; + mf_set_rtc(tm); + } + { + u8 *ce_msg = rtc_data.ce_msg.ce_msg; + u8 year = ce_msg[5]; + u8 sec = ce_msg[6]; + u8 min = ce_msg[7]; + u8 hour = ce_msg[8]; + u8 day = ce_msg[10]; + u8 mon = ce_msg[11]; + + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + + if (year <= 69) + year += 100; + + tm->tm_sec = sec; + tm->tm_min = min; + tm->tm_hour = hour; + tm->tm_mday = day; + tm->tm_mon = mon; + tm->tm_year = year; + } + + return 0; +} + +int mf_set_rtc(struct rtc_time *tm) +{ + char ce_time[12]; + u8 day, mon, hour, min, sec, y1, y2; + unsigned year; + + year = 1900 + tm->tm_year; + y1 = year / 100; + y2 = year % 100; + + sec = tm->tm_sec; + min = tm->tm_min; + hour = tm->tm_hour; + day = tm->tm_mday; + mon = tm->tm_mon + 1; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hour); + BIN_TO_BCD(mon); + BIN_TO_BCD(day); + BIN_TO_BCD(y1); + BIN_TO_BCD(y2); + + memset(ce_time, 0, sizeof(ce_time)); + ce_time[3] = 0x41; + ce_time[4] = y1; + ce_time[5] = y2; + ce_time[6] = sec; + ce_time[7] = min; + ce_time[8] = hour; + ce_time[10] = day; + ce_time[11] = mon; + + return signal_ce_msg(ce_time, NULL); +} + +#ifdef CONFIG_PROC_FS + +static int proc_mf_dump_cmdline(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + char *p; + struct vsp_cmd_data vsp_cmd; + int rc; + dma_addr_t dma_addr; + + /* The HV appears to return no more than 256 bytes of command line */ + if (off >= 256) + return 0; + if ((off + count) > 256) + count = 256 - off; + + dma_addr = dma_map_single(iSeries_vio_dev, page, off + count, + DMA_FROM_DEVICE); + if (dma_mapping_error(dma_addr)) + return -ENOMEM; + memset(page, 0, off + count); + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.cmd = 33; + vsp_cmd.sub_data.kern.token = dma_addr; + vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + vsp_cmd.sub_data.kern.side = (u64)data; + vsp_cmd.sub_data.kern.length = off + count; + mb(); + rc = signal_vsp_instruction(&vsp_cmd); + dma_unmap_single(iSeries_vio_dev, dma_addr, off + count, + DMA_FROM_DEVICE); + if (rc) + return rc; + if (vsp_cmd.result_code != 0) + return -ENOMEM; + p = page; + len = 0; + while (len < (off + count)) { + if ((*p == '\0') || (*p == '\n')) { + if (*p == '\0') + *p = '\n'; + p++; + len++; + *eof = 1; break; + } + p++; + len++; } - myVspCmd.sub_data.ipl_type = newSide; - myVspCmd.cmd = 10; - (void)signal_vsp_instruction(&myVspCmd); + if (len < off) { + *eof = 1; + len = 0; + } + return len; } -char mf_getSide(void) +#if 0 +static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) { - char returnValue = ' '; - int rc = 0; - struct VspCmdData myVspCmd; + struct vsp_cmd_data vsp_cmd; + int rc; + int len = *size; + dma_addr_t dma_addr; + + dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, + DMA_FROM_DEVICE); + memset(buffer, 0, len); + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.cmd = 32; + vsp_cmd.sub_data.kern.token = dma_addr; + vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + vsp_cmd.sub_data.kern.side = side; + vsp_cmd.sub_data.kern.offset = offset; + vsp_cmd.sub_data.kern.length = len; + mb(); + rc = signal_vsp_instruction(&vsp_cmd); + if (rc == 0) { + if (vsp_cmd.result_code == 0) + *size = vsp_cmd.sub_data.length_out; + else + rc = -ENOMEM; + } + + dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); + + return rc; +} + +static int proc_mf_dump_vmlinux(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int sizeToGet = count; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) { + if (sizeToGet != 0) { + *start = page + off; + return sizeToGet; + } + *eof = 1; + return 0; + } + *eof = 1; + return 0; +} +#endif + +static int proc_mf_dump_side(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + char mf_current_side = ' '; + struct vsp_cmd_data vsp_cmd; - memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.cmd = 2; - myVspCmd.sub_data.ipl_type = 0; + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.cmd = 2; + vsp_cmd.sub_data.ipl_type = 0; mb(); - rc = signal_vsp_instruction(&myVspCmd); - if (rc != 0) - return returnValue; + if (signal_vsp_instruction(&vsp_cmd) == 0) { + if (vsp_cmd.result_code == 0) { + switch (vsp_cmd.sub_data.ipl_type) { + case 0: mf_current_side = 'A'; + break; + case 1: mf_current_side = 'B'; + break; + case 2: mf_current_side = 'C'; + break; + default: mf_current_side = 'D'; + break; + } + } + } + + len = sprintf(page, "%c\n", mf_current_side); + + if (len <= (off + count)) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int proc_mf_change_side(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char side; + u64 newSide; + struct vsp_cmd_data vsp_cmd; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; - if (myVspCmd.result_code == 0) { - switch (myVspCmd.sub_data.ipl_type) { - case 0: returnValue = 'A'; + if (count == 0) + return 0; + + if (get_user(side, buffer)) + return -EFAULT; + + switch (side) { + case 'A': newSide = 0; break; - case 1: returnValue = 'B'; + case 'B': newSide = 1; break; - case 2: returnValue = 'C'; + case 'C': newSide = 2; break; - default: returnValue = 'D'; + case 'D': newSide = 3; break; - } + default: + printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n"); + return -EINVAL; } - return returnValue; + + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.sub_data.ipl_type = newSide; + vsp_cmd.cmd = 10; + + (void)signal_vsp_instruction(&vsp_cmd); + + return count; } -void mf_getSrcHistory(char *buffer, int size) -{ #if 0 - struct IplTypeReturnStuff returnStuff; +static void mf_getSrcHistory(char *buffer, int size) +{ + struct IplTypeReturnStuff return_stuff; struct pending_event *ev = new_pending_event(); int rc = 0; char *pages[4]; @@ -751,13 +1008,13 @@ void mf_getSrcHistory(char *buffer, int size) || (pages[2] == NULL) || (pages[3] == NULL)) return -ENOMEM; - returnStuff.xType = 0; - returnStuff.xRc = 0; - returnStuff.xDone = 0; + return_stuff.xType = 0; + return_stuff.xRc = 0; + return_stuff.xDone = 0; ev->event.hp_lp_event.xSubtype = 6; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'V', 'I'); - ev->event.data.vsp_cmd.xEvent = &returnStuff; + ev->event.data.vsp_cmd.xEvent = &return_stuff; ev->event.data.vsp_cmd.cmd = 4; ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); ev->event.data.vsp_cmd.result_code = 0xFF; @@ -770,312 +1027,213 @@ void mf_getSrcHistory(char *buffer, int size) if (signal_event(ev) != 0) return; - while (returnStuff.xDone != 1) + while (return_stuff.xDone != 1) udelay(10); - if (returnStuff.xRc == 0) + if (return_stuff.xRc == 0) memcpy(buffer, pages[0], size); kfree(pages[0]); kfree(pages[1]); kfree(pages[2]); kfree(pages[3]); -#endif -} - -void mf_setCmdLine(const char *cmdline, int size, u64 side) -{ - struct VspCmdData myVspCmd; - dma_addr_t dma_addr = 0; - char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, - GFP_ATOMIC); - - if (page == NULL) { - printk(KERN_ERR "mf.c: couldn't allocate memory to set command line\n"); - return; - } - - copy_from_user(page, cmdline, size); - - memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.cmd = 31; - myVspCmd.sub_data.kern.token = dma_addr; - myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; - myVspCmd.sub_data.kern.side = side; - myVspCmd.sub_data.kern.length = size; - mb(); - (void)signal_vsp_instruction(&myVspCmd); - - dma_free_coherent(iSeries_vio_dev, size, page, dma_addr); } +#endif -int mf_getCmdLine(char *cmdline, int *size, u64 side) +static int proc_mf_dump_src(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct VspCmdData myVspCmd; - int rc; - int len = *size; - dma_addr_t dma_addr; - - dma_addr = dma_map_single(iSeries_vio_dev, cmdline, len, - DMA_FROM_DEVICE); - memset(cmdline, 0, len); - memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.cmd = 33; - myVspCmd.sub_data.kern.token = dma_addr; - myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; - myVspCmd.sub_data.kern.side = side; - myVspCmd.sub_data.kern.length = len; - mb(); - rc = signal_vsp_instruction(&myVspCmd); - - if (rc == 0) { - if (myVspCmd.result_code == 0) - len = myVspCmd.sub_data.length_out; #if 0 - else - memcpy(cmdline, "Bad cmdline", 11); -#endif - } - - dma_unmap_single(iSeries_vio_dev, dma_addr, *size, DMA_FROM_DEVICE); - + int len; + + mf_getSrcHistory(page, count); + len = count; + len -= off; + if (len < count) { + *eof = 1; + if (len <= 0) + return 0; + } else + len = count; + *start = page + off; return len; +#else + return 0; +#endif } - -int mf_setVmlinuxChunk(const char *buffer, int size, int offset, u64 side) +static int proc_mf_change_src(struct file *file, const char __user *buffer, + unsigned long count, void *data) { - struct VspCmdData myVspCmd; - int rc; - dma_addr_t dma_addr = 0; - char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, - GFP_ATOMIC); + char stkbuf[10]; - if (page == NULL) { - printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); - return -ENOMEM; - } + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; - copy_from_user(page, buffer, size); - memset(&myVspCmd, 0, sizeof(myVspCmd)); - - myVspCmd.cmd = 30; - myVspCmd.sub_data.kern.token = dma_addr; - myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; - myVspCmd.sub_data.kern.side = side; - myVspCmd.sub_data.kern.offset = offset; - myVspCmd.sub_data.kern.length = size; - mb(); - rc = signal_vsp_instruction(&myVspCmd); - if (rc == 0) { - if (myVspCmd.result_code == 0) - rc = 0; - else - rc = -ENOMEM; + if ((count < 4) && (count != 1)) { + printk(KERN_ERR "mf_proc: invalid src\n"); + return -EINVAL; } - dma_free_coherent(iSeries_vio_dev, size, page, dma_addr); + if (count > (sizeof(stkbuf) - 1)) + count = sizeof(stkbuf) - 1; + if (copy_from_user(stkbuf, buffer, count)) + return -EFAULT; - return rc; + if ((count == 1) && (*stkbuf == '\0')) + mf_clear_src(); + else + mf_display_src(*(u32 *)stkbuf); + + return count; } -int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) +static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, + unsigned long count, void *data) { - struct VspCmdData myVspCmd; - int rc; - int len = *size; + struct vsp_cmd_data vsp_cmd; dma_addr_t dma_addr; + char *page; + int ret = -EACCES; - dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, - DMA_FROM_DEVICE); - memset(buffer, 0, len); - memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.cmd = 32; - myVspCmd.sub_data.kern.token = dma_addr; - myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; - myVspCmd.sub_data.kern.side = side; - myVspCmd.sub_data.kern.offset = offset; - myVspCmd.sub_data.kern.length = len; - mb(); - rc = signal_vsp_instruction(&myVspCmd); - if (rc == 0) { - if (myVspCmd.result_code == 0) - *size = myVspCmd.sub_data.length_out; - else - rc = -ENOMEM; - } + if (!capable(CAP_SYS_ADMIN)) + goto out; - dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); + dma_addr = 0; + page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, + GFP_ATOMIC); + ret = -ENOMEM; + if (page == NULL) + goto out; + + ret = -EFAULT; + if (copy_from_user(page, buffer, count)) + goto out_free; + + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.cmd = 31; + vsp_cmd.sub_data.kern.token = dma_addr; + vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + vsp_cmd.sub_data.kern.side = (u64)data; + vsp_cmd.sub_data.kern.length = count; + mb(); + (void)signal_vsp_instruction(&vsp_cmd); + ret = count; - return rc; +out_free: + dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); +out: + return ret; } -int mf_setRtcTime(unsigned long time) +static ssize_t proc_mf_change_vmlinux(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) { - struct rtc_time tm; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + ssize_t rc; + dma_addr_t dma_addr; + char *page; + struct vsp_cmd_data vsp_cmd; - to_tm(time, &tm); + rc = -EACCES; + if (!capable(CAP_SYS_ADMIN)) + goto out; - return mf_setRtc(&tm); + dma_addr = 0; + page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, + GFP_ATOMIC); + rc = -ENOMEM; + if (page == NULL) { + printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); + goto out; + } + rc = -EFAULT; + if (copy_from_user(page, buf, count)) + goto out_free; + + memset(&vsp_cmd, 0, sizeof(vsp_cmd)); + vsp_cmd.cmd = 30; + vsp_cmd.sub_data.kern.token = dma_addr; + vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + vsp_cmd.sub_data.kern.side = (u64)dp->data; + vsp_cmd.sub_data.kern.offset = *ppos; + vsp_cmd.sub_data.kern.length = count; + mb(); + rc = signal_vsp_instruction(&vsp_cmd); + if (rc) + goto out_free; + rc = -ENOMEM; + if (vsp_cmd.result_code != 0) + goto out_free; + + *ppos += count; + rc = count; +out_free: + dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); +out: + return rc; } -struct RtcTimeData { - struct completion com; - struct CeMsgData xCeMsg; - int xRc; +static struct file_operations proc_vmlinux_operations = { + .write = proc_mf_change_vmlinux, }; -void getRtcTimeComplete(void * token, struct CeMsgData *ceMsg) +static int __init mf_proc_init(void) { - struct RtcTimeData *rtc = (struct RtcTimeData *)token; - - memcpy(&(rtc->xCeMsg), ceMsg, sizeof(rtc->xCeMsg)); - rtc->xRc = 0; - complete(&rtc->com); -} - -static unsigned long lastsec = 1; + struct proc_dir_entry *mf_proc_root; + struct proc_dir_entry *ent; + struct proc_dir_entry *mf; + char name[2]; + int i; -int mf_getRtcTime(unsigned long *time) -{ - u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart)); - u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1); - int year = 1970; - int year1 = (dataWord1 >> 24) & 0x000000FF; - int year2 = (dataWord1 >> 16) & 0x000000FF; - int sec = (dataWord1 >> 8) & 0x000000FF; - int min = dataWord1 & 0x000000FF; - int hour = (dataWord2 >> 24) & 0x000000FF; - int day = (dataWord2 >> 8) & 0x000000FF; - int mon = dataWord2 & 0x000000FF; - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year1); - BCD_TO_BIN(year2); - year = year1 * 100 + year2; - - *time = mktime(year, mon, day, hour, min, sec); - *time += (jiffies / HZ); - - /* - * Now THIS is a nasty hack! - * It ensures that the first two calls to mf_getRtcTime get different - * answers. That way the loop in init_time (time.c) will not think - * the clock is stuck. - */ - if (lastsec) { - *time -= lastsec; - --lastsec; + mf_proc_root = proc_mkdir("iSeries/mf", NULL); + if (!mf_proc_root) + return 1; + + name[1] = '\0'; + for (i = 0; i < 4; i++) { + name[0] = 'A' + i; + mf = proc_mkdir(name, mf_proc_root); + if (!mf) + return 1; + + ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf); + if (!ent) + return 1; + ent->nlink = 1; + ent->data = (void *)(long)i; + ent->read_proc = proc_mf_dump_cmdline; + ent->write_proc = proc_mf_change_cmdline; + + if (i == 3) /* no vmlinux entry for 'D' */ + continue; + + ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf); + if (!ent) + return 1; + ent->nlink = 1; + ent->data = (void *)(long)i; + ent->proc_fops = &proc_vmlinux_operations; } - return 0; -} - -int mf_getRtc(struct rtc_time *tm) -{ - struct CeMsgCompleteData ceComplete; - struct RtcTimeData rtcData; - int rc; - - memset(&ceComplete, 0, sizeof(ceComplete)); - memset(&rtcData, 0, sizeof(rtcData)); - init_completion(&rtcData.com); - ceComplete.handler = &getRtcTimeComplete; - ceComplete.token = (void *)&rtcData; - rc = signal_ce_msg("\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", - &ceComplete); - if (rc == 0) { - wait_for_completion(&rtcData.com); - - if (rtcData.xRc == 0) { - if ((rtcData.xCeMsg.ce_msg[2] == 0xa9) || - (rtcData.xCeMsg.ce_msg[2] == 0xaf)) { - /* TOD clock is not set */ - tm->tm_sec = 1; - tm->tm_min = 1; - tm->tm_hour = 1; - tm->tm_mday = 10; - tm->tm_mon = 8; - tm->tm_year = 71; - mf_setRtc(tm); - } - { - u32 dataWord1 = *((u32 *)(rtcData.xCeMsg.ce_msg+4)); - u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.ce_msg+8)); - u8 year = (dataWord1 >> 16) & 0x000000FF; - u8 sec = (dataWord1 >> 8) & 0x000000FF; - u8 min = dataWord1 & 0x000000FF; - u8 hour = (dataWord2 >> 24) & 0x000000FF; - u8 day = (dataWord2 >> 8) & 0x000000FF; - u8 mon = dataWord2 & 0x000000FF; - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - - if (year <= 69) - year += 100; - - tm->tm_sec = sec; - tm->tm_min = min; - tm->tm_hour = hour; - tm->tm_mday = day; - tm->tm_mon = mon; - tm->tm_year = year; - } - } else { - rc = rtcData.xRc; - tm->tm_sec = 0; - tm->tm_min = 0; - tm->tm_hour = 0; - tm->tm_mday = 15; - tm->tm_mon = 5; - tm->tm_year = 52; - } - tm->tm_wday = 0; - tm->tm_yday = 0; - tm->tm_isdst = 0; - } + ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + if (!ent) + return 1; + ent->nlink = 1; + ent->data = (void *)0; + ent->read_proc = proc_mf_dump_side; + ent->write_proc = proc_mf_change_side; + + ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + if (!ent) + return 1; + ent->nlink = 1; + ent->data = (void *)0; + ent->read_proc = proc_mf_dump_src; + ent->write_proc = proc_mf_change_src; - return rc; + return 0; } -int mf_setRtc(struct rtc_time * tm) -{ - char ceTime[12] = "\x00\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00"; - u8 day, mon, hour, min, sec, y1, y2; - unsigned year; - - year = 1900 + tm->tm_year; - y1 = year / 100; - y2 = year % 100; - - sec = tm->tm_sec; - min = tm->tm_min; - hour = tm->tm_hour; - day = tm->tm_mday; - mon = tm->tm_mon + 1; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hour); - BIN_TO_BCD(mon); - BIN_TO_BCD(day); - BIN_TO_BCD(y1); - BIN_TO_BCD(y2); +__initcall(mf_proc_init); - ceTime[4] = y1; - ceTime[5] = y2; - ceTime[6] = sec; - ceTime[7] = min; - ceTime[8] = hour; - ceTime[10] = day; - ceTime[11] = mon; - - return signal_ce_msg(ceTime, NULL); -} +#endif /* CONFIG_PROC_FS */ diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index d0d509e4a..6460c443e 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -115,18 +115,59 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_handle_irq_event) +_GLOBAL(call_handle_IRQ_event) mflr r0 std r0,16(r1) stdu r1,THREAD_SIZE-112(r6) mr r1,r6 - bl .handle_irq_event + bl .handle_IRQ_event ld r1,0(r1) ld r0,16(r1) mtlr r0 blr #endif /* CONFIG_IRQSTACKS */ + /* + * To be called by C code which needs to do some operations with MMU + * disabled. Note that interrupts have to be disabled by the caller + * prior to calling us. The code called _MUST_ be in the RMO of course + * and part of the linear mapping as we don't attempt to translate the + * stack pointer at all. The function is called with the stack switched + * to this CPU emergency stack + * + * prototype is void *call_with_mmu_off(void *func, void *data); + * + * the called function is expected to be of the form + * + * void *called(void *data); + */ +_GLOBAL(call_with_mmu_off) + mflr r0 /* get link, save it on stackframe */ + std r0,16(r1) + mr r1,r5 /* save old stack ptr */ + ld r1,PACAEMERGSP(r13) /* get emerg. stack */ + subi r1,r1,STACK_FRAME_OVERHEAD + std r0,16(r1) /* save link on emerg. stack */ + std r5,0(r1) /* save old stack ptr in backchain */ + ld r3,0(r3) /* get to real function ptr (assume same TOC) */ + bl 2f /* we need LR to return, continue at label 2 */ + + ld r0,16(r1) /* we return here from the call, get LR and */ + ld r1,0(r1) /* .. old stack ptr */ + mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ + mfmsr r4 + ori r4,r4,MSR_IR|MSR_DR + mtspr SPRN_SRR1,r4 + rfid + +2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ + mr r3,r4 /* get parameter */ + mfmsr r0 + ori r0,r0,MSR_IR|MSR_DR + xori r0,r0,MSR_IR|MSR_DR + mtspr SPRN_SRR1,r0 + rfid + /* * Flush instruction cache. */ @@ -454,23 +495,6 @@ _GLOBAL(_outsl_ns) sync blr -_GLOBAL(abs) - cmpi 0,r3,0 - bge 10f - neg r3,r3 -10: blr - -_GLOBAL(_get_PVR) - mfspr r3,PVR - blr - -_GLOBAL(_get_PIR) - mfspr r3,PIR - blr - -_GLOBAL(_get_HID0) - mfspr r3,HID0 - blr _GLOBAL(cvt_fd) lfd 0,0(r5) /* load up fpscr value */ @@ -567,6 +591,69 @@ _GLOBAL(do_cpu_ftr_fixups) isync b 1b +#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) +/* + * Do an IO access in real mode + */ +_GLOBAL(real_readb) + mfmsr r7 + ori r0,r7,MSR_DR + xori r0,r0,MSR_DR + sync + mtmsrd r0 + sync + isync + mfspr r6,SPRN_HID4 + rldicl r5,r6,32,0 + ori r5,r5,0x100 + rldicl r5,r5,32,0 + sync + mtspr SPRN_HID4,r5 + isync + slbia + isync + lbz r3,0(r3) + sync + mtspr SPRN_HID4,r6 + isync + slbia + isync + mtmsrd r7 + sync + isync + blr + + /* + * Do an IO access in real mode + */ +_GLOBAL(real_writeb) + mfmsr r7 + ori r0,r7,MSR_DR + xori r0,r0,MSR_DR + sync + mtmsrd r0 + sync + isync + mfspr r6,SPRN_HID4 + rldicl r5,r6,32,0 + ori r5,r5,0x100 + rldicl r5,r5,32,0 + sync + mtspr SPRN_HID4,r5 + isync + slbia + isync + stb r3,0(r4) + sync + mtspr SPRN_HID4,r6 + isync + slbia + isync + mtmsrd r7 + sync + isync + blr +#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ /* * Create a kernel thread @@ -583,7 +670,7 @@ _GLOBAL(kernel_thread) li r4,0 /* new sp (unused) */ li r0,__NR_clone sc - cmpi 0,r3,0 /* parent or child? */ + cmpdi 0,r3,0 /* parent or child? */ bne 1f /* return if parent */ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) @@ -600,7 +687,7 @@ _GLOBAL(kernel_thread) ld r30,-16(r1) blr -#ifdef CONFIG_PPC_ISERIES /* hack hack hack */ +#ifndef CONFIG_PPC_PSERIES /* hack hack hack */ #define ppc_rtas sys_ni_syscall #endif @@ -848,27 +935,27 @@ _GLOBAL(sys_call_table32) .llong .sys_epoll_wait .llong .sys_remap_file_pages .llong .ppc32_timer_create /* 240 */ - .llong .compat_timer_settime - .llong .compat_timer_gettime + .llong .compat_sys_timer_settime + .llong .compat_sys_timer_gettime .llong .sys_timer_getoverrun .llong .sys_timer_delete - .llong .compat_clock_settime /* 245 */ - .llong .compat_clock_gettime - .llong .compat_clock_getres - .llong .compat_clock_nanosleep + .llong .compat_sys_clock_settime /* 245 */ + .llong .compat_sys_clock_gettime + .llong .compat_sys_clock_getres + .llong .compat_sys_clock_nanosleep .llong .ppc32_swapcontext .llong .sys32_tgkill /* 250 */ .llong .sys32_utimes - .llong .compat_statfs64 - .llong .compat_fstatfs64 + .llong .compat_sys_statfs64 + .llong .compat_sys_fstatfs64 .llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */ .llong .ppc_rtas /* 255 */ .llong .sys_ni_syscall /* 256 reserved for sys_debug_setcontext */ .llong .sys_ni_syscall /* 257 reserved for vserver */ .llong .sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */ - .llong .sys_ni_syscall /* 259 reserved for new sys_mbind */ - .llong .sys_ni_syscall /* 260 reserved for new sys_get_mempolicy */ - .llong .sys_ni_syscall /* 261 reserved for new sys_set_mempolicy */ + .llong .compat_sys_mbind + .llong .compat_sys_get_mempolicy /* 260 */ + .llong .compat_sys_set_mempolicy .llong .compat_sys_mq_open .llong .sys_mq_unlink .llong .compat_sys_mq_timedsend @@ -876,6 +963,9 @@ _GLOBAL(sys_call_table32) .llong .compat_sys_mq_notify .llong .compat_sys_mq_getsetattr .llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */ + .llong .sys32_add_key + .llong .sys32_request_key + .llong .compat_sys_keyctl .balign 8 _GLOBAL(sys_call_table) @@ -1138,9 +1228,9 @@ _GLOBAL(sys_call_table) .llong .sys_ni_syscall /* 256 reserved for sys_debug_setcontext */ .llong .sys_ni_syscall /* 257 reserved for vserver */ .llong .sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */ - .llong .sys_ni_syscall /* 259 reserved for new sys_mbind */ - .llong .sys_ni_syscall /* 260 reserved for new sys_get_mempolicy */ - .llong .sys_ni_syscall /* 261 reserved for new sys_set_mempolicy */ + .llong .sys_mbind + .llong .sys_get_mempolicy /* 260 */ + .llong .sys_set_mempolicy .llong .sys_mq_open .llong .sys_mq_unlink .llong .sys_mq_timedsend @@ -1148,3 +1238,6 @@ _GLOBAL(sys_call_table) .llong .sys_mq_notify .llong .sys_mq_getsetattr .llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */ + .llong .sys_add_key + .llong .sys_request_key /* 270 */ + .llong .sys_keyctl diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c index 89d6a0ad7..f3644ad5d 100644 --- a/arch/ppc64/kernel/nvram.c +++ b/arch/ppc64/kernel/nvram.c @@ -43,9 +43,9 @@ static struct nvram_partition * nvram_part; static long nvram_error_log_index = -1; static long nvram_error_log_size = 0; -volatile int no_more_logging = 1; /* Until we initialize everything, - * make sure we don't try logging - * anything */ +int no_logging = 1; /* Until we initialize everything, + * make sure we don't try logging + * anything */ extern volatile int error_log_cnt; @@ -77,7 +77,7 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) } -static ssize_t dev_nvram_read(struct file *file, char *buf, +static ssize_t dev_nvram_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { ssize_t len; @@ -117,7 +117,7 @@ static ssize_t dev_nvram_read(struct file *file, char *buf, } -static ssize_t dev_nvram_write(struct file *file, const char *buf, +static ssize_t dev_nvram_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t len; @@ -340,7 +340,7 @@ static int nvram_create_os_partition(void) struct list_head * p; struct nvram_partition * part; struct nvram_partition * new_part = NULL; - struct nvram_partition * free_part; + struct nvram_partition * free_part = NULL; int seq_init[2] = { 0, 0 }; loff_t tmp_index; long size = 0; @@ -603,6 +603,7 @@ void __exit nvram_cleanup(void) } +#ifdef CONFIG_PPC_PSERIES /* nvram_write_error_log * @@ -639,7 +640,7 @@ int nvram_write_error_log(char * buff, int length, unsigned int err_type) loff_t tmp_index; struct err_log_info info; - if (no_more_logging) { + if (no_logging) { return -EPERM; } @@ -710,7 +711,7 @@ int nvram_read_error_log(char * buff, int length, unsigned int * err_type) /* This doesn't actually zero anything, but it sets the event_logged * word to tell that this event is safely in syslog. */ -int nvram_clear_error_log() +int nvram_clear_error_log(void) { loff_t tmp_index; int clear_word = ERR_FLAG_ALREADY_LOGGED; @@ -727,6 +728,7 @@ int nvram_clear_error_log() return 0; } +#endif /* CONFIG_PPC_PSERIES */ module_init(nvram_init); module_exit(nvram_cleanup); diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index 91749173f..2946121eb 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "pci.h" @@ -88,9 +89,153 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) } +static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, + long npages, unsigned long uaddr, + enum dma_data_direction direction) +{ + u64 rc; + union tce_entry tce; + + tce.te_word = 0; + tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; + tce.te_rdwr = 1; + if (direction != DMA_TO_DEVICE) + tce.te_pciwr = 1; + + while (npages--) { + rc = plpar_tce_put((u64)tbl->it_index, + (u64)tcenum << 12, + tce.te_word ); + + if (rc && printk_ratelimit()) { + printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\ttcenum = 0x%lx\n", (u64)tcenum); + printk("\ttce val = 0x%lx\n", tce.te_word ); + show_stack(current, (unsigned long *)__get_SP()); + } + + tcenum++; + tce.te_rpn++; + } +} + +DEFINE_PER_CPU(void *, tce_page) = NULL; + +static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, + long npages, unsigned long uaddr, + enum dma_data_direction direction) +{ + u64 rc; + union tce_entry tce, *tcep; + long l, limit; + + if (npages == 1) + return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, + direction); + + tcep = __get_cpu_var(tce_page); + + /* This is safe to do since interrupts are off when we're called + * from iommu_alloc{,_sg}() + */ + if (!tcep) { + tcep = (void *)__get_free_page(GFP_ATOMIC); + /* If allocation fails, fall back to the loop implementation */ + if (!tcep) + return tce_build_pSeriesLP(tbl, tcenum, npages, + uaddr, direction); + __get_cpu_var(tce_page) = tcep; + } + + tce.te_word = 0; + tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; + tce.te_rdwr = 1; + if (direction != DMA_TO_DEVICE) + tce.te_pciwr = 1; + + /* We can map max one pageful of TCEs at a time */ + do { + /* + * Set up the page with TCE data, looping through and setting + * the values. + */ + limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry)); + + for (l = 0; l < limit; l++) { + tcep[l] = tce; + tce.te_rpn++; + } + + rc = plpar_tce_put_indirect((u64)tbl->it_index, + (u64)tcenum << 12, + (u64)virt_to_abs(tcep), + limit); + + npages -= limit; + tcenum += limit; + } while (npages > 0 && !rc); + + if (rc && printk_ratelimit()) { + printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\tnpages = 0x%lx\n", (u64)npages); + printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word); + show_stack(current, (unsigned long *)__get_SP()); + } +} + +static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) +{ + u64 rc; + union tce_entry tce; + + tce.te_word = 0; + + while (npages--) { + rc = plpar_tce_put((u64)tbl->it_index, + (u64)tcenum << 12, + tce.te_word); + + if (rc && printk_ratelimit()) { + printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\ttcenum = 0x%lx\n", (u64)tcenum); + printk("\ttce val = 0x%lx\n", tce.te_word ); + show_stack(current, (unsigned long *)__get_SP()); + } + + tcenum++; + } +} + + +static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) +{ + u64 rc; + union tce_entry tce; + + tce.te_word = 0; + + rc = plpar_tce_stuff((u64)tbl->it_index, + (u64)tcenum << 12, + tce.te_word, + npages); + + if (rc && printk_ratelimit()) { + printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); + printk("\trc = %ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\tnpages = 0x%lx\n", (u64)npages); + printk("\ttce val = 0x%lx\n", tce.te_word ); + show_stack(current, (unsigned long *)__get_SP()); + } +} + + static void iommu_buses_init(void) { - struct pci_controller* phb; + struct pci_controller *phb, *tmp; struct device_node *dn, *first_dn; int num_slots, num_slots_ilog2; int first_phb = 1; @@ -106,10 +251,10 @@ static void iommu_buses_init(void) else tcetable_ilog2 = 22; - /* XXX Should we be using pci_root_buses instead? -ojn + /* XXX Should we be using pci_root_buses instead? -ojn */ - for (phb=hose_head; phb; phb=phb->next) { + list_for_each_entry_safe(phb, tmp, &hose_list, list_node) { first_dn = ((struct device_node *)phb->arch_data)->child; /* Carve 2GB into the largest dma_window_size possible */ @@ -131,7 +276,7 @@ static void iommu_buses_init(void) first_phb = 0; for (dn = first_dn; dn != NULL; dn = dn->sibling) - iommu_devnode_init(dn); + iommu_devnode_init_pSeries(dn); } } @@ -145,7 +290,11 @@ static void iommu_buses_init_lpar(struct list_head *bus_list) for (ln=bus_list->next; ln != bus_list; ln=ln->next) { bus = pci_bus_b(ln); - busdn = PCI_GET_DN(bus); + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ dma_window = (unsigned int *)get_property(busdn, "ibm,dma-window", NULL); if (dma_window) { @@ -153,7 +302,7 @@ static void iommu_buses_init_lpar(struct list_head *bus_list) * Do it now because iommu_table_setparms_lpar needs it. */ busdn->bussubno = bus->number; - iommu_devnode_init(busdn); + iommu_devnode_init_pSeries(busdn); } /* look for a window on a bridge even if the PHB had one */ @@ -166,24 +315,22 @@ static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) { - phandle node; - unsigned long i; - struct of_tce_table *oft; - - node = ((struct device_node *)(phb->arch_data))->node; - - oft = NULL; - - for (i=0; of_tce_table[i].node; i++) - if(of_tce_table[i].node == node) { - oft = &of_tce_table[i]; - break; - } - - if (!oft) - panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name); + struct device_node *node; + unsigned long *basep; + unsigned int *sizep; + + node = (struct device_node *)phb->arch_data; + + basep = (unsigned long *)get_property(node, "linux,tce-base", NULL); + sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL); + if (basep == NULL || sizep == NULL) { + printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has " + "missing tce entries !\n", dn->full_name); + return; + } - memset((void *)oft->base, 0, oft->size); + tbl->it_base = (unsigned long)__va(*basep); + memset((void *)tbl->it_base, 0, *sizep); tbl->it_busno = phb->bus->number; @@ -207,10 +354,10 @@ static void iommu_table_setparms(struct pci_controller *phb, if (phb->dma_window_base_cur > (1 << 19)) panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); - tbl->it_base = oft->base; tbl->it_index = 0; tbl->it_entrysize = sizeof(union tce_entry); tbl->it_blocksize = 16; + tbl->it_type = TCE_PCI; } /* @@ -246,10 +393,11 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, tbl->it_index = dma_window[0]; tbl->it_entrysize = sizeof(union tce_entry); tbl->it_blocksize = 16; + tbl->it_type = TCE_PCI; } -void iommu_devnode_init(struct device_node *dn) +void iommu_devnode_init_pSeries(struct device_node *dn) { struct iommu_table *tbl; @@ -264,7 +412,6 @@ void iommu_devnode_init(struct device_node *dn) dn->iommu_table = iommu_init_table(tbl); } - void iommu_setup_pSeries(void) { struct pci_dev *dev = NULL; @@ -279,8 +426,8 @@ void iommu_setup_pSeries(void) * pci device_node. This means get_iommu_table() won't need to search * up the device tree to find it. */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - mydn = dn = PCI_GET_DN(dev); + for_each_pci_dev(dev) { + mydn = dn = pci_device_to_OF_node(dev); while (dn && dn->iommu_table == NULL) dn = dn->parent; @@ -289,12 +436,19 @@ void iommu_setup_pSeries(void) } } - /* These are called very early. */ void tce_init_pSeries(void) { - ppc_md.tce_build = tce_build_pSeries; - ppc_md.tce_free = tce_free_pSeries; + if (!(systemcfg->platform & PLATFORM_LPAR)) { + ppc_md.tce_build = tce_build_pSeries; + ppc_md.tce_free = tce_free_pSeries; + } else if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) { + ppc_md.tce_build = tce_buildmulti_pSeriesLP; + ppc_md.tce_free = tce_freemulti_pSeriesLP; + } else { + ppc_md.tce_build = tce_build_pSeriesLP; + ppc_md.tce_free = tce_free_pSeriesLP; + } pci_iommu_init(); } diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c index a44c33268..21e8a27ce 100644 --- a/arch/ppc64/kernel/pSeries_lpar.c +++ b/arch/ppc64/kernel/pSeries_lpar.c @@ -19,6 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define DEBUG + #include #include #include @@ -34,10 +36,16 @@ #include #include #include -#include #include #include #include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif /* in pSeries_hvCall.S */ EXPORT_SYMBOL(plpar_hcall); @@ -45,149 +53,80 @@ EXPORT_SYMBOL(plpar_hcall_4out); EXPORT_SYMBOL(plpar_hcall_norets); EXPORT_SYMBOL(plpar_hcall_8arg_2ret); -long poll_pending(void) -{ - unsigned long dummy; - return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, - &dummy, &dummy, &dummy); -} - -long prod_processor(void) -{ - plpar_hcall_norets(H_PROD); - return(0); -} - -long cede_processor(void) -{ - plpar_hcall_norets(H_CEDE); - return(0); -} +extern void fw_feature_init(void); +extern void pSeries_find_serial_port(void); -long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa) -{ - plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); - return(0); -} -long plpar_pte_remove(unsigned long flags, - unsigned long ptex, - unsigned long avpn, - unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) -{ - unsigned long dummy; - return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, - old_pteh_ret, old_ptel_ret, &dummy); -} +int vtermno; /* virtual terminal# for udbg */ -long plpar_pte_read(unsigned long flags, - unsigned long ptex, - unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) +#define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) +static void udbg_hvsi_putc(unsigned char c) { - unsigned long dummy; - return plpar_hcall(H_READ, flags, ptex, 0, 0, - old_pteh_ret, old_ptel_ret, &dummy); -} + /* packet's seqno isn't used anyways */ + uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c }; + int rc; -long plpar_pte_protect(unsigned long flags, - unsigned long ptex, - unsigned long avpn) -{ - return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn); -} + if (c == '\n') + udbg_hvsi_putc('\r'); -long plpar_tce_get(unsigned long liobn, - unsigned long ioba, - unsigned long *tce_ret) -{ - unsigned long dummy; - return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, - tce_ret, &dummy, &dummy); + do { + rc = plpar_put_term_char(vtermno, sizeof(packet), packet); + } while (rc == H_Busy); } -long plpar_tce_put(unsigned long liobn, - unsigned long ioba, - unsigned long tceval) -{ - return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval); -} +static long hvsi_udbg_buf_len; +static uint8_t hvsi_udbg_buf[256]; -long plpar_get_term_char(unsigned long termno, - unsigned long *len_ret, - char *buf_ret) +static int udbg_hvsi_getc_poll(void) { - unsigned long *lbuf = (unsigned long *)buf_ret; /* ToDo: alignment? */ - return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, - len_ret, lbuf+0, lbuf+1); -} + unsigned char ch; + int rc, i; + + if (hvsi_udbg_buf_len == 0) { + rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf); + if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) { + /* bad read or non-data packet */ + hvsi_udbg_buf_len = 0; + } else { + /* remove the packet header */ + for (i = 4; i < hvsi_udbg_buf_len; i++) + hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i]; + hvsi_udbg_buf_len -= 4; + } + } -long plpar_put_term_char(unsigned long termno, - unsigned long len, - const char *buffer) -{ - unsigned long *lbuf = (unsigned long *)buffer; /* ToDo: alignment? */ - return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0], - lbuf[1]); -} + if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) { + /* no data ready */ + hvsi_udbg_buf_len = 0; + return -1; + } -static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, - long npages, unsigned long uaddr, - enum dma_data_direction direction) -{ - u64 rc; - union tce_entry tce; - - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; - tce.te_rdwr = 1; - if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; - - while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word ); - - if (rc && printk_ratelimit()) { - printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); - printk("\tindex = 0x%lx\n", (u64)tbl->it_index); - printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); - show_stack(current, (unsigned long *)__get_SP()); - } - - tcenum++; - tce.te_rpn++; + ch = hvsi_udbg_buf[0]; + /* shift remaining data down */ + for (i = 1; i < hvsi_udbg_buf_len; i++) { + hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i]; } + hvsi_udbg_buf_len--; + + return ch; } -static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) +static unsigned char udbg_hvsi_getc(void) { - u64 rc; - union tce_entry tce; - - tce.te_word = 0; - - while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word ); - - if (rc && printk_ratelimit()) { - printk("tce_free_pSeriesLP: plpar_tce_put failed\n"); - printk("\trc = %ld\n", rc); - printk("\tindex = 0x%lx\n", (u64)tbl->it_index); - printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); - show_stack(current, (unsigned long *)__get_SP()); + int ch; + for (;;) { + ch = udbg_hvsi_getc_poll(); + if (ch == -1) { + /* This shouldn't be needed...but... */ + volatile unsigned long delay; + for (delay=0; delay < 2000000; delay++) + ; + } else { + return ch; } - - tcenum++; } } -int vtermno; /* virtual terminal# for udbg */ - static void udbg_putcLP(unsigned char c) { char buf[16]; @@ -249,8 +188,19 @@ static unsigned char udbg_getcLP(void) } } +/* call this from early_init() for a working debug console on + * vterm capable LPAR machines + */ +void udbg_init_debug_lpar(void) +{ + vtermno = 0; + ppc_md.udbg_putc = udbg_putcLP; + ppc_md.udbg_getc = udbg_getcLP; + ppc_md.udbg_getc_poll = udbg_getc_pollLP; +} + /* returns 0 if couldn't find or use /chosen/stdout as console */ -static int find_udbg_vterm(void) +int find_udbg_vterm(void) { struct device_node *stdout_node; u32 *termno; @@ -258,15 +208,14 @@ static int find_udbg_vterm(void) int found = 0; /* find the boot console from /chosen/stdout */ - if (!of_stdout_device) { - printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n"); - return found; - } - stdout_node = of_find_node_by_path(of_stdout_device); - if (!stdout_node) { - printk(KERN_WARNING "couldn't find node from /chosen/stdout\n"); - return found; - } + if (!of_chosen) + return 0; + name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); + if (name == NULL) + return 0; + stdout_node = of_find_node_by_path(name); + if (!stdout_node) + return 0; /* now we have the stdout node; figure out what type of device it is. */ name = (char *)get_property(stdout_node, "name", NULL); @@ -285,18 +234,24 @@ static int find_udbg_vterm(void) ppc_md.udbg_getc_poll = udbg_getc_pollLP; found = 1; } - } else { - /* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */ - printk(KERN_WARNING "%s doesn't speak hvterm1; " - "can't print udbg messages\n", of_stdout_device); + } else if (device_is_compatible(stdout_node, "hvterm-protocol")) { + termno = (u32 *)get_property(stdout_node, "reg", NULL); + if (termno) { + vtermno = termno[0]; + ppc_md.udbg_putc = udbg_hvsi_putc; + ppc_md.udbg_getc = udbg_hvsi_getc; + ppc_md.udbg_getc_poll = udbg_hvsi_getc_poll; + found = 1; + } } } else if (strncmp(name, "serial", 6)) { /* XXX fix ISA serial console */ printk(KERN_WARNING "serial stdout on LPAR ('%s')! " - "can't print udbg messages\n", of_stdout_device); + "can't print udbg messages\n", + stdout_node->full_name); } else { printk(KERN_WARNING "don't know how to print to stdout '%s'\n", - of_stdout_device); + stdout_node->full_name); } out: @@ -304,34 +259,21 @@ out: return found; } -void pSeries_lpar_mm_init(void); - -/* This is called early in setup.c. - * Use it to setup page table ppc_md stuff as well as udbg. - */ -void pSeriesLP_init_early(void) +void vpa_init(int cpu) { - pSeries_lpar_mm_init(); - - tce_init_pSeries(); - - ppc_md.tce_build = tce_build_pSeriesLP; - ppc_md.tce_free = tce_free_pSeriesLP; - - pci_iommu_init(); - -#ifdef CONFIG_SMP - smp_init_pSeries(); -#endif + int hwcpu = get_hard_smp_processor_id(cpu); + unsigned long vpa = (unsigned long)&(paca[cpu].lppaca); + long ret; + unsigned long flags; - /* The keyboard is not useful in the LPAR environment. - * Leave all the ppc_md keyboard interfaces NULL. - */ + /* Register the Virtual Processor Area (VPA) */ + flags = 1UL << (63 - 18); + ret = register_vpa(flags, hwcpu, __pa(vpa)); - if (0 == find_udbg_vterm()) { - printk(KERN_WARNING - "can't use stdout; can't print early debug messages.\n"); - } + if (ret) + printk(KERN_ERR "WARNING: vpa_init: VPA registration for " + "cpu %d (hw %d) of area %lx returns %ld\n", + cpu, hwcpu, __pa(vpa), ret); } long pSeries_lpar_hpte_insert(unsigned long hpte_group, @@ -377,7 +319,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0, lhpte.dw1.dword1, &slot, &dummy0, &dummy1); - if (lpar_rc == H_PTEG_Full) + if (unlikely(lpar_rc == H_PTEG_Full)) return -1; /* @@ -385,7 +327,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, * will fail. However we must catch the failure in hash_page * or we will loop forever, so return -2 in this case. */ - if (lpar_rc != H_Success) + if (unlikely(lpar_rc != H_Success)) return -2; /* Because of iSeries, we have to pass down the secondary @@ -415,9 +357,7 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group) if (lpar_rc == H_Success) return i; - if (lpar_rc != H_Not_Found) - panic("Bad return code from pte remove rc = %lx\n", - lpar_rc); + BUG_ON(lpar_rc != H_Not_Found); slot_offset++; slot_offset &= 0x7; @@ -426,6 +366,18 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group) return -1; } +static void pSeries_lpar_hptab_clear(void) +{ + unsigned long size_bytes = 1UL << naca->pftSize; + unsigned long hpte_count = size_bytes >> 4; + unsigned long dummy1, dummy2; + int i; + + /* TODO: Use bulk call */ + for (i = 0; i < hpte_count; i++) + plpar_pte_remove(0, i, 0, &dummy1, &dummy2); +} + /* * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and * the low 3 bits of flags happen to line up. So no transform is needed. @@ -447,8 +399,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp, if (lpar_rc == H_Not_Found) return -1; - if (lpar_rc != H_Success) - panic("bad return code from pte protect rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); return 0; } @@ -464,11 +415,10 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot) /* Do not need RPN to logical page translation */ /* No cross CEC PFT access */ flags = 0; - + lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1); - if (lpar_rc != H_Success) - panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); return dword0; } @@ -519,15 +469,12 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, vpn = va >> PAGE_SHIFT; slot = pSeries_lpar_hpte_find(vpn); - if (slot == -1) - panic("updateboltedpp: Could not find page to bolt\n"); + BUG_ON(slot == -1); flags = newpp & 3; lpar_rc = plpar_pte_protect(flags, slot, 0); - if (lpar_rc != H_Success) - panic("Bad return code from pte bolted protect rc = %lx\n", - lpar_rc); + BUG_ON(lpar_rc != H_Success); } static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, @@ -546,8 +493,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, if (lpar_rc == H_Not_Found) return; - if (lpar_rc != H_Success) - panic("Bad return code from invalidate rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); } /* @@ -560,18 +506,19 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number, int i; unsigned long flags; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE); - if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE)) + if (lock_tlbie) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); for (i = 0; i < number; i++) flush_hash_page(context, batch->addr[i], batch->pte[i], local); - if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE)) + if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); } -void pSeries_lpar_mm_init(void) +void hpte_init_lpar(void) { ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp; @@ -579,4 +526,7 @@ void pSeries_lpar_mm_init(void) ppc_md.hpte_insert = pSeries_lpar_hpte_insert; ppc_md.hpte_remove = pSeries_lpar_hpte_remove; ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; + ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear; + + htab_finish_init(); } diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index 92bc868f3..9c5a313d9 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -37,20 +36,13 @@ #include #include #include -#include #include #include #include -#include "open_pic.h" +#include "mpic.h" #include "pci.h" -/* legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch - devices we don't have access to. */ -unsigned long io_page_mask; - -EXPORT_SYMBOL(io_page_mask); - /* RTAS tokens */ static int read_pci_config; static int write_pci_config; @@ -59,7 +51,7 @@ static int ibm_write_pci_config; static int s7a_workaround; -extern unsigned long pci_probe_only; +extern struct mpic *pSeries_mpic; static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) { @@ -68,7 +60,9 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va int ret; if (!dn) - return -2; + return PCIBIOS_DEVICE_NOT_FOUND; + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; addr = (dn->busno << 16) | (dn->devfn << 8) | where; buid = dn->phb->buid; @@ -79,7 +73,15 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); } *val = returnval; - return ret; + + if (ret) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (returnval == EEH_IO_ERROR_VALUE(size) + && eeh_dn_check_failure (dn, NULL)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; } static int rtas_pci_read_config(struct pci_bus *bus, @@ -106,7 +108,9 @@ static int rtas_write_config(struct device_node *dn, int where, int size, u32 va int ret; if (!dn) - return -2; + return PCIBIOS_DEVICE_NOT_FOUND; + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; addr = (dn->busno << 16) | (dn->devfn << 8) | where; buid = dn->phb->buid; @@ -115,7 +119,11 @@ static int rtas_write_config(struct device_node *dn, int where, int size, u32 va } else { ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val); } - return ret; + + if (ret) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; } static int rtas_pci_write_config(struct pci_bus *bus, @@ -141,196 +149,49 @@ struct pci_ops rtas_pci_ops = { rtas_pci_write_config }; -/****************************************************************** - * pci_read_irq_line - * - * Reads the Interrupt Pin to determine if interrupt is use by card. - * If the interrupt is used, then gets the interrupt line from the - * openfirmware and sets it in the pci_dev and pci_config line. - * - ******************************************************************/ -int pci_read_irq_line(struct pci_dev *pci_dev) +static int is_python(struct device_node *dev) { - u8 intpin; - struct device_node *node; - - pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); + char *model = (char *)get_property(dev, "model", NULL); - if (intpin == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_name(pci_dev)); - return 0; - } - - node = pci_device_to_OF_node(pci_dev); - if (node == NULL) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n", - pci_name(pci_dev)); - return -1; - } - if (node->n_intrs == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_name(pci_dev)); - return -1; - } - pci_dev->irq = node->intrs[0].line; - - if (s7a_workaround) { - if (pci_dev->irq > 16) - pci_dev->irq -= 3; - } + if (model && strstr(model, "Python")) + return 1; - pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); - - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n", - pci_name(pci_dev), pci_dev->irq); return 0; } -EXPORT_SYMBOL(pci_read_irq_line); -#define ISA_SPACE_MASK 0x1 -#define ISA_SPACE_IO 0x1 - -static void pci_process_ISA_OF_ranges(struct device_node *isa_node, - unsigned long phb_io_base_phys, - void * phb_io_base_virt) +static int get_phb_reg_prop(struct device_node *dev, + unsigned int addr_size_words, + struct reg_property64 *reg) { - struct isa_range *range; - unsigned long pci_addr; - unsigned int isa_addr; - unsigned int size; - int rlen = 0; - - range = (struct isa_range *) get_property(isa_node, "ranges", &rlen); - if (rlen < sizeof(struct isa_range)) { - printk(KERN_ERR "unexpected isa range size: %s\n", - __FUNCTION__); - return; - } - - /* From "ISA Binding to 1275" - * The ranges property is laid out as an array of elements, - * each of which comprises: - * cells 0 - 1: an ISA address - * cells 2 - 4: a PCI address - * (size depending on dev->n_addr_cells) - * cell 5: the size of the range - */ - if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { - isa_addr = range->isa_addr.a_lo; - pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | - range->pci_addr.a_lo; - - /* Assume these are both zero */ - if ((pci_addr != 0) || (isa_addr != 0)) { - printk(KERN_ERR "unexpected isa to pci mapping: %s\n", - __FUNCTION__); - return; - } - - size = PAGE_ALIGN(range->size); - - __ioremap_explicit(phb_io_base_phys, - (unsigned long) phb_io_base_virt, - size, _PAGE_NO_CACHE); - } -} + unsigned int *ui_ptr = NULL, len; -static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose, - struct device_node *dev, - int primary) -{ - unsigned int *ranges; - unsigned long size; - int rlen = 0; - int memno = 0; - struct resource *res; - int np, na = prom_n_addr_cells(dev); - unsigned long pci_addr, cpu_phys_addr; - struct device_node *isa_dn; - - np = na + 5; - - /* From "PCI Binding to 1275" - * The ranges property is laid out as an array of elements, - * each of which comprises: - * cells 0 - 2: a PCI address - * cells 3 or 3+4: a CPU physical address - * (size depending on dev->n_addr_cells) - * cells 4+5 or 5+6: the size of the range - */ - rlen = 0; - hose->io_base_phys = 0; - ranges = (unsigned int *) get_property(dev, "ranges", &rlen); - while ((rlen -= np * sizeof(unsigned int)) >= 0) { - res = NULL; - pci_addr = (unsigned long)ranges[1] << 32 | ranges[2]; - - cpu_phys_addr = ranges[3]; - if (na == 2) - cpu_phys_addr = cpu_phys_addr << 32 | ranges[4]; - - size = (unsigned long)ranges[na+3] << 32 | ranges[na+4]; - - switch (ranges[0] >> 24) { - case 1: /* I/O space */ - hose->io_base_phys = cpu_phys_addr; - hose->io_base_virt = reserve_phb_iospace(size); - PPCDBG(PPCDBG_PHBINIT, - "phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", - hose->global_number, hose->io_base_phys, - (unsigned long) hose->io_base_virt); - - if (primary) { - pci_io_base = (unsigned long)hose->io_base_virt; - isa_dn = of_find_node_by_type(NULL, "isa"); - if (isa_dn) { - isa_io_base = pci_io_base; - pci_process_ISA_OF_ranges(isa_dn, - hose->io_base_phys, - hose->io_base_virt); - of_node_put(isa_dn); - /* Allow all IO */ - io_page_mask = -1; - } - } + /* Found a PHB, now figure out where his registers are mapped. */ + ui_ptr = (unsigned int *)get_property(dev, "reg", &len); + if (ui_ptr == NULL) + return 1; - res = &hose->io_resource; - res->flags = IORESOURCE_IO; - res->start = pci_addr; - res->start += (unsigned long)hose->io_base_virt - - pci_io_base; - break; - case 2: /* memory space */ - memno = 0; - while (memno < 3 && hose->mem_resources[memno].flags) - ++memno; - - if (memno == 0) - hose->pci_mem_offset = cpu_phys_addr - pci_addr; - if (memno < 3) { - res = &hose->mem_resources[memno]; - res->flags = IORESOURCE_MEM; - res->start = cpu_phys_addr; - } - break; - } - if (res != NULL) { - res->name = dev->full_name; - res->end = res->start + size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } - ranges += np; + if (addr_size_words == 1) { + reg->address = ((struct reg_property32 *)ui_ptr)->address; + reg->size = ((struct reg_property32 *)ui_ptr)->size; + } else { + *reg = *((struct reg_property64 *)ui_ptr); } + + return 0; } -static void python_countermeasures(unsigned long addr) +static void python_countermeasures(struct device_node *dev, + unsigned int addr_size_words) { - void *chip_regs; - volatile u32 *tmp, i; + struct reg_property64 reg_struct; + void __iomem *chip_regs; + volatile u32 val; + + if (get_phb_reg_prop(dev, addr_size_words, ®_struct)) + return; /* Python's register file is 1 MB in size. */ - chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000); + chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000); /* * Firmware doesn't always clear this bit which is critical @@ -339,17 +200,17 @@ static void python_countermeasures(unsigned long addr) #define PRG_CL_RESET_VALID 0x00010000 - tmp = (u32 *)((unsigned long)chip_regs + 0xf6030); - - if (*tmp & PRG_CL_RESET_VALID) { + val = in_be32(chip_regs + 0xf6030); + if (val & PRG_CL_RESET_VALID) { printk(KERN_INFO "Python workaround: "); - *tmp &= ~PRG_CL_RESET_VALID; + val &= ~PRG_CL_RESET_VALID; + out_be32(chip_regs + 0xf6030, val); /* * We must read it back for changes to * take effect */ - i = *tmp; - printk("reg0: %x\n", i); + val = in_be32(chip_regs + 0xf6030); + printk("reg0: %x\n", val); } iounmap(chip_regs); @@ -363,7 +224,7 @@ void __init init_pci_config_tokens (void) ibm_write_pci_config = rtas_token("ibm,write-pci-config"); } -unsigned long __init get_phb_buid (struct device_node *phb) +unsigned long __devinit get_phb_buid (struct device_node *phb) { int addr_cells; unsigned int *buid_vals; @@ -393,95 +254,103 @@ unsigned long __init get_phb_buid (struct device_node *phb) return buid; } -static struct pci_controller * __init alloc_phb(struct device_node *dev, - unsigned int addr_size_words) +static int phb_set_bus_ranges(struct device_node *dev, + struct pci_controller *phb) { - struct pci_controller *phb; - unsigned int *ui_ptr = NULL, len; - struct reg_property64 reg_struct; int *bus_range; - char *model; - enum phb_types phb_type; - struct property *of_prop; - - model = (char *)get_property(dev, "model", NULL); - - if (!model) { - printk(KERN_ERR "alloc_phb: phb has no model property\n"); - model = ""; - } - - /* Found a PHB, now figure out where his registers are mapped. */ - ui_ptr = (unsigned int *) get_property(dev, "reg", &len); - if (ui_ptr == NULL) { - PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); - return NULL; - } + unsigned int len; - if (addr_size_words == 1) { - reg_struct.address = ((struct reg_property32 *)ui_ptr)->address; - reg_struct.size = ((struct reg_property32 *)ui_ptr)->size; - } else { - reg_struct = *((struct reg_property64 *)ui_ptr); - } + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + return 1; + } + + phb->first_busno = bus_range[0]; + phb->last_busno = bus_range[1]; - if (strstr(model, "Python")) { - phb_type = phb_type_python; - } else if (strstr(model, "Speedwagon")) { - phb_type = phb_type_speedwagon; - } else if (strstr(model, "Winnipeg")) { - phb_type = phb_type_winnipeg; - } else { - printk(KERN_ERR "alloc_phb: unknown PHB %s\n", model); - phb_type = phb_type_unknown; - } + return 0; +} - phb = pci_alloc_pci_controller(phb_type); - if (phb == NULL) - return NULL; +static int __devinit setup_phb(struct device_node *dev, + struct pci_controller *phb, + unsigned int addr_size_words) +{ + pci_setup_pci_controller(phb); - if (phb_type == phb_type_python) - python_countermeasures(reg_struct.address); + if (is_python(dev)) + python_countermeasures(dev, addr_size_words); - bus_range = (int *) get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - kfree(phb); - return NULL; - } + if (phb_set_bus_ranges(dev, phb)) + return 1; - of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + - sizeof(phb->global_number)); + phb->arch_data = dev; + phb->ops = &rtas_pci_ops; + phb->buid = get_phb_buid(dev); - if (!of_prop) { - kfree(phb); - return NULL; - } + return 0; +} +static void __devinit add_linux_pci_domain(struct device_node *dev, + struct pci_controller *phb, + struct property *of_prop) +{ memset(of_prop, 0, sizeof(struct property)); of_prop->name = "linux,pci-domain"; of_prop->length = sizeof(phb->global_number); of_prop->value = (unsigned char *)&of_prop[1]; memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number)); prom_add_property(dev, of_prop); +} - phb->first_busno = bus_range[0]; - phb->last_busno = bus_range[1]; +static struct pci_controller * __init alloc_phb(struct device_node *dev, + unsigned int addr_size_words) +{ + struct pci_controller *phb; + struct property *of_prop; - phb->arch_data = dev; - phb->ops = &rtas_pci_ops; + phb = alloc_bootmem(sizeof(struct pci_controller)); + if (phb == NULL) + return NULL; - phb->buid = get_phb_buid(dev); + of_prop = alloc_bootmem(sizeof(struct property) + + sizeof(phb->global_number)); + if (!of_prop) + return NULL; + + if (setup_phb(dev, phb, addr_size_words)) + return NULL; + + add_linux_pci_domain(dev, phb, of_prop); return phb; } +static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words) +{ + struct pci_controller *phb; + + phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), + GFP_KERNEL); + if (phb == NULL) + return NULL; + + if (setup_phb(dev, phb, addr_size_words)) + return NULL; + + phb->is_dynamic = 1; + + /* TODO: linux,pci-domain? */ + + return phb; +} + unsigned long __init find_and_init_phbs(void) { struct device_node *node; struct pci_controller *phb; unsigned int root_size_cells = 0; unsigned int index; - unsigned int *opprop; + unsigned int *opprop = NULL; struct device_node *root = of_find_node_by_path("/"); if (naca->interrupt_controller == IC_OPEN_PIC) { @@ -503,11 +372,12 @@ unsigned long __init find_and_init_phbs(void) if (!phb) continue; - pci_process_bridge_OF_ranges(phb, node, index == 0); + pci_process_bridge_OF_ranges(phb, node); + pci_setup_phb_io(phb, index == 0); - if (naca->interrupt_controller == IC_OPEN_PIC) { + if (naca->interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { int addr = root_size_cells * (index + 2) - 1; - openpic_setup_ISU(index, opprop[addr]); + mpic_assign_isu(pSeries_mpic, index, opprop[addr]); } index++; @@ -516,12 +386,58 @@ unsigned long __init find_and_init_phbs(void) of_node_put(root); pci_devs_phb_init(); + /* + * pci_probe_only and pci_assign_all_buses can be set via properties + * in chosen. + */ + if (of_chosen) { + int *prop; + + prop = (int *)get_property(of_chosen, "linux,pci-probe-only", + NULL); + if (prop) + pci_probe_only = *prop; + + prop = (int *)get_property(of_chosen, + "linux,pci-assign-all-buses", NULL); + if (prop) + pci_assign_all_buses = *prop; + } + return 0; } -void pcibios_name_device(struct pci_dev *dev) +struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) { + struct device_node *root = of_find_node_by_path("/"); + unsigned int root_size_cells = 0; + struct pci_controller *phb; + struct pci_bus *bus; + + root_size_cells = prom_n_size_cells(root); + + phb = alloc_phb_dynamic(dn, root_size_cells); + if (!phb) + return NULL; + + pci_process_bridge_OF_ranges(phb, dn); + + pci_setup_phb_io_dynamic(phb); + of_node_put(root); + + pci_devs_phb_init_dynamic(phb); + phb->last_busno = 0xff; + bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data); + phb->bus = bus; + phb->last_busno = bus->subordinate; + + return phb; +} +EXPORT_SYMBOL(init_phb_dynamic); + #if 0 +void pcibios_name_device(struct pci_dev *dev) +{ struct device_node *dn; /* @@ -541,98 +457,9 @@ void pcibios_name_device(struct pci_dev *dev) } } } -#endif } - -void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, - struct pci_bus *bus) -{ - /* Update device resources. */ - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (dev->resource[i].flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; - unsigned long start, end, mask; - - start = dev->resource[i].start += offset; - end = dev->resource[i].end += offset; - - /* Need to allow IO access to pages that are in the - ISA range */ - if (start < MAX_ISA_PORT) { - if (end > MAX_ISA_PORT) - end = MAX_ISA_PORT; - - start >>= PAGE_SHIFT; - end >>= PAGE_SHIFT; - - /* get the range of pages for the map */ - mask = ((1 << (end+1))-1) ^ ((1 << start)-1); - io_page_mask |= mask; - } - } - else if (dev->resource[i].flags & IORESOURCE_MEM) { - dev->resource[i].start += hose->pci_mem_offset; - dev->resource[i].end += hose->pci_mem_offset; - } - } -} -EXPORT_SYMBOL(pcibios_fixup_device_resources); - -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); - struct list_head *ln; - - /* XXX or bus->parent? */ - struct pci_dev *dev = bus->self; - struct resource *res; - int i; - - if (!dev) { - /* Root bus. */ - - hose->bus = bus; - bus->resource[0] = res = &hose->io_resource; - if (!res->flags) - BUG(); /* No I/O resource for this PHB? */ - - if (request_resource(&ioport_resource, res)) - printk(KERN_ERR "Failed to request IO on " - "PCI domain %d\n", pci_domain_nr(bus)); - - - for (i = 0; i < 3; ++i) { - res = &hose->mem_resources[i]; - if (!res->flags && i == 0) - BUG(); /* No memory resource for this PHB? */ - bus->resource[i+1] = res; - if (res->flags && request_resource(&iomem_resource, res)) - printk(KERN_ERR "Failed to request MEM on " - "PCI domain %d\n", - pci_domain_nr(bus)); - } - } else if (pci_probe_only && - (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - /* This is a subordinate bridge */ - - pci_read_bridge_bases(bus); - pcibios_fixup_device_resources(dev, bus); - } - - /* XXX Need to check why Alpha doesnt do this - Anton */ - if (!pci_probe_only) - return; - - for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { - struct pci_dev *dev = pci_dev_b(ln); - if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) - pcibios_fixup_device_resources(dev, bus); - } -} -EXPORT_SYMBOL(pcibios_fixup_bus); +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); +#endif static void check_s7a(void) { @@ -648,152 +475,116 @@ static void check_s7a(void) } } -static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, - unsigned long *start_virt, unsigned long *size) +/* RPA-specific bits for removing PHBs */ +int pcibios_remove_root_bus(struct pci_controller *phb) { - struct pci_controller *hose = PCI_GET_PHB_PTR(bus); - struct pci_bus_region region; + struct pci_bus *b = phb->bus; struct resource *res; + int rc, i; - if (bus->self) { - res = bus->resource[0]; - pcibios_resource_to_bus(bus->self, ®ion, res); - *start_phys = hose->io_base_phys + region.start; - *start_virt = (unsigned long) hose->io_base_virt + - region.start; - if (region.end > region.start) - *size = region.end - region.start + 1; - else { - printk("%s(): unexpected region 0x%lx->0x%lx\n", - __FUNCTION__, region.start, region.end); - return 1; - } - - } else { - /* Root Bus */ - res = &hose->io_resource; - *start_phys = hose->io_base_phys; - *start_virt = (unsigned long) hose->io_base_virt; - if (res->end > res->start) - *size = res->end - res->start + 1; - else { - printk("%s(): unexpected region 0x%lx->0x%lx\n", - __FUNCTION__, res->start, res->end); - return 1; - } + res = b->resource[0]; + if (!res->flags) { + printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__, + b->name); + return 1; } - return 0; -} - -int unmap_bus_range(struct pci_bus *bus) -{ - unsigned long start_phys; - unsigned long start_virt; - unsigned long size; - - if (!bus) { - printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + rc = unmap_bus_range(b); + if (rc) { + printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", + __FUNCTION__, b->name); return 1; } - - if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) - return 1; - if (iounmap_explicit((void *) start_virt, size)) - return 1; - return 0; -} -EXPORT_SYMBOL(unmap_bus_range); - -int remap_bus_range(struct pci_bus *bus) -{ - unsigned long start_phys; - unsigned long start_virt; - unsigned long size; - - if (!bus) { - printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + if (release_resource(res)) { + printk(KERN_ERR "%s: failed to release IO on bus %s\n", + __FUNCTION__, b->name); return 1; } - - if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) - return 1; - if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE)) - return 1; + + for (i = 1; i < 3; ++i) { + res = b->resource[i]; + if (!res->flags && i == 0) { + printk(KERN_ERR "%s: no MEM resource for PHB %s\n", + __FUNCTION__, b->name); + return 1; + } + if (res->flags && release_resource(res)) { + printk(KERN_ERR + "%s: failed to release IO %d on bus %s\n", + __FUNCTION__, i, b->name); + return 1; + } + } + + list_del(&phb->list_node); + if (phb->is_dynamic) + kfree(phb); return 0; } -EXPORT_SYMBOL(remap_bus_range); +EXPORT_SYMBOL(pcibios_remove_root_bus); -static void phbs_fixup_io(void) +static void __init pSeries_request_regions(void) { - struct pci_controller *hose; - - for (hose=hose_head;hose;hose=hose->next) - remap_bus_range(hose->bus); + request_region(0x20,0x20,"pic1"); + request_region(0xa0,0x20,"pic2"); + request_region(0x00,0x20,"dma1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); } -extern void chrp_request_regions(void); - void __init pSeries_final_fixup(void) { struct pci_dev *dev = NULL; check_s7a(); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + for_each_pci_dev(dev) { pci_read_irq_line(dev); + if (s7a_workaround) { + if (dev->irq > 16) { + dev->irq -= 3; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } + } + } - phbs_fixup_io(); - chrp_request_regions(); + phbs_remap_io(); + pSeries_request_regions(); pci_fix_bus_sysdata(); - if (!ppc64_iommu_off) + + if (!of_chosen || !get_property(of_chosen, "linux,iommu-off", NULL)) iommu_setup_pSeries(); -} -/*********************************************************************** - * pci_find_hose_for_OF_device - * - * This function finds the PHB that matching device_node in the - * OpenFirmware by scanning all the pci_controllers. - * - ***********************************************************************/ -struct pci_controller* -pci_find_hose_for_OF_device(struct device_node *node) -{ - while (node) { - struct pci_controller *hose; - for (hose=hose_head;hose;hose=hose->next) - if (hose->arch_data == node) - return hose; - node=node->parent; - } - return NULL; + pci_addr_cache_build(); } /* - * ppc64 can have multifunction devices that do not respond to function 0. - * In this case we must scan all functions. + * Assume the winbond 82c105 is the IDE controller on a + * p610. We should probably be more careful in case + * someone tries to plug in a similar adapter. */ -int -pcibios_scan_all_fns(struct pci_bus *bus, int devfn) +static void fixup_winbond_82c105(struct pci_dev* dev) { - struct device_node *busdn, *dn; - - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - - /* - * Check to see if there is any of the 8 functions are in the - * device tree. If they are then we need to scan all the - * functions of this slot. - */ - for (dn = busdn->child; dn; dn = dn->sibling) - if ((dn->devfn >> 3) == (devfn >> 3)) - return 1; - - return 0; + int i; + unsigned int reg; + + if (!(systemcfg->platform & PLATFORM_PSERIES)) + return; + + printk("Using INTC for W82c105 IDE controller.\n"); + pci_read_config_dword(dev, 0x40, ®); + /* Enable LEGIRQ to use INTC instead of ISA interrupts */ + pci_write_config_dword(dev, 0x40, reg | (1<<11)); + + for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) { + /* zap the 2nd function of the winbond chip */ + if (dev->resource[i].flags & IORESOURCE_IO + && dev->bus->number == 0 && dev->devfn == 0x81) + dev->resource[i].flags &= ~IORESOURCE_IO; + } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, + fixup_winbond_82c105); diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c index 80e028904..3787957ab 100644 --- a/arch/ppc64/kernel/pSeries_setup.c +++ b/arch/ppc64/kernel/pSeries_setup.c @@ -61,19 +61,18 @@ #include #include "i8259.h" -#include "open_pic.h" #include #include #include +#include "mpic.h" + #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) #else #define DBG(fmt...) #endif -extern void pSeries_init_openpic(void); - extern void find_and_init_phbs(void); extern void pSeries_final_fixup(void); @@ -82,6 +81,8 @@ extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); extern int pSeries_set_rtc_time(struct rtc_time *rtc_time); extern void find_udbg_vterm(void); extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void); /* from head.S */ +extern void generic_find_legacy_serial_ports(unsigned int *default_speed); + int fwnmi_active; /* TRUE if an FWNMI handler is present */ unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address. @@ -91,6 +92,9 @@ extern unsigned long loops_per_jiffy; extern unsigned long ppc_proc_freq; extern unsigned long ppc_tb_freq; +static volatile void __iomem * chrp_int_ack_special; +struct mpic *pSeries_mpic; + void pSeries_get_cpuinfo(struct seq_file *m) { struct device_node *root; @@ -120,15 +124,84 @@ static void __init fwnmi_init(void) fwnmi_active = 1; } -static void __init pSeries_setup_arch(void) +static int pSeries_irq_cascade(struct pt_regs *regs, void *data) +{ + if (chrp_int_ack_special) + return readb(chrp_int_ack_special); + else + return i8259_irq(smp_processor_id()); +} + +static void __init pSeries_init_mpic(void) +{ + unsigned int *addrp; + struct device_node *np; + int i; + + /* All ISUs are setup, complete initialization */ + mpic_init(pSeries_mpic); + + /* Check what kind of cascade ACK we have */ + if (!(np = of_find_node_by_name(NULL, "pci")) + || !(addrp = (unsigned int *) + get_property(np, "8259-interrupt-acknowledge", NULL))) + printk(KERN_ERR "Cannot find pci to get ack address\n"); + else + chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1); + of_node_put(np); + + /* Setup the legacy interrupts & controller */ + for (i = 0; i < NUM_ISA_INTERRUPTS; i++) + irq_desc[i].handler = &i8259_pic; + i8259_init(0); + + /* Hook cascade to mpic */ + mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL); +} + +static void __init pSeries_setup_mpic(void) { - struct device_node *root; unsigned int *opprop; + unsigned long openpic_addr = 0; + unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS]; + struct device_node *root; + int irq_count; + /* Find the Open PIC if present */ + root = of_find_node_by_path("/"); + opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); + if (opprop != 0) { + int n = prom_n_addr_cells(root); + + for (openpic_addr = 0; n > 0; --n) + openpic_addr = (openpic_addr << 32) + *opprop++; + printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); + } + of_node_put(root); + + BUG_ON(openpic_addr == 0); + + /* Get the sense values from OF */ + prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS); + + /* Setup the openpic driver */ + irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ + pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY, + 16, 16, irq_count, /* isu size, irq offset, irq count */ + NR_IRQS - 4, /* ipi offset */ + senses, irq_count, /* sense & sense size */ + " MPIC "); +} + +static void __init pSeries_setup_arch(void) +{ /* Fixup ppc_md depending on the type of interrupt controller */ if (naca->interrupt_controller == IC_OPEN_PIC) { - ppc_md.init_IRQ = pSeries_init_openpic; - ppc_md.get_irq = openpic_get_irq; + ppc_md.init_IRQ = pSeries_init_mpic; + ppc_md.get_irq = mpic_get_irq; + /* Allocate the mpic now, so that find_and_init_phbs() can + * fill the ISUs */ + pSeries_setup_mpic(); } else { ppc_md.init_IRQ = xics_init_IRQ; ppc_md.get_irq = xics_get_irq; @@ -156,26 +229,14 @@ static void __init pSeries_setup_arch(void) eeh_init(); find_and_init_phbs(); - /* Find the Open PIC if present */ - root = of_find_node_by_path("/"); - opprop = (unsigned int *) get_property(root, - "platform-open-pic", NULL); - if (opprop != 0) { - int n = prom_n_addr_cells(root); - unsigned long openpic; - - for (openpic = 0; n > 0; --n) - openpic = (openpic << 32) + *opprop++; - printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic); - OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE); - } - of_node_put(root); - #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif pSeries_nvram_init(); + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) + vpa_init(boot_cpuid); } static int __init pSeries_init_panel(void) @@ -189,75 +250,6 @@ static int __init pSeries_init_panel(void) arch_initcall(pSeries_init_panel); - -void __init pSeries_find_serial_port(void) -{ - struct device_node *np; - unsigned long encode_phys_size = 32; - u32 *sizeprop; - - struct isa_reg_property { - u32 space; - u32 address; - u32 size; - }; - struct pci_reg_property { - struct pci_address addr; - u32 size_hi; - u32 size_lo; - }; - - DBG(" -> pSeries_find_serial_port()\n"); - - naca->serialPortAddr = 0; - - np = of_find_node_by_path("/"); - if (!np) - return; - sizeprop = (u32 *)get_property(np, "#size-cells", NULL); - if (sizeprop != NULL) - encode_phys_size = (*sizeprop) << 5; - - for (np = NULL; (np = of_find_node_by_type(np, "serial"));) { - struct device_node *isa, *pci; - struct isa_reg_property *reg; - union pci_range *rangesp; - char *typep; - - typep = (char *)get_property(np, "ibm,aix-loc", NULL); - if ((typep == NULL) || (typep && strcmp(typep, "S1"))) - continue; - - reg = (struct isa_reg_property *)get_property(np, "reg", NULL); - - isa = of_get_parent(np); - if (!isa) { - DBG("no isa parent found\n"); - break; - } - pci = of_get_parent(isa); - if (!pci) { - DBG("no pci parent found\n"); - break; - } - - rangesp = (union pci_range *)get_property(pci, "ranges", NULL); - - if ( encode_phys_size == 32 ) - naca->serialPortAddr = rangesp->pci32.phys+reg->address; - else { - naca->serialPortAddr = - ((((unsigned long)rangesp->pci64.phys_hi) << 32) - | - (rangesp->pci64.phys_lo)) + reg->address; - } - break; - } - - DBG(" <- pSeries_find_serial_port()\n"); -} - - /* Build up the firmware_features bitmask field * using contents of device-tree/ibm,hypertas-functions. * Ultimately this functionality may be moved into prom.c prom_init(). @@ -330,6 +322,20 @@ static void __init pSeries_discover_pic(void) } } +static void pSeries_cpu_die(void) +{ + local_irq_disable(); + /* Some hardware requires clearing the CPPR, while other hardware does not + * it is safe either way + */ + pSeriesLP_cppr_info(0, 0); + rtas_stop_self(); + /* Should never get here... */ + BUG(); + for(;;); +} + + /* * Early initialization. Relocation is on but do not reference unbolted pages */ @@ -337,6 +343,7 @@ static void __init pSeries_init_early(void) { void *comport; int iommu_off = 0; + unsigned int default_speed; DBG(" -> pSeries_init_early()\n"); @@ -350,14 +357,14 @@ static void __init pSeries_init_early(void) get_property(of_chosen, "linux,iommu-off", NULL)); } - pSeries_find_serial_port(); + generic_find_legacy_serial_ports(&default_speed); if (systemcfg->platform & PLATFORM_LPAR) find_udbg_vterm(); else if (naca->serialPortAddr) { /* Map the uart for udbg. */ comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE); - udbg_init_uart(comport); + udbg_init_uart(comport, default_speed); ppc_md.udbg_putc = udbg_putc; ppc_md.udbg_getc = udbg_getc; @@ -542,6 +549,31 @@ static void __init pSeries_calibrate_decr(void) setup_default_decr(); } +static int pSeries_check_legacy_ioport(unsigned int baseport) +{ + struct device_node *np; + +#define I8042_DATA_REG 0x60 +#define FDC_BASE 0x3f0 + + + switch(baseport) { + case I8042_DATA_REG: + np = of_find_node_by_type(NULL, "8042"); + if (np == NULL) + return -ENODEV; + of_node_put(np); + break; + case FDC_BASE: + np = of_find_node_by_type(NULL, "fdc"); + if (np == NULL) + return -ENODEV; + of_node_put(np); + break; + } + return 0; +} + /* * Called very early, MMU is off, device-tree isn't unflattened */ @@ -571,9 +603,11 @@ struct machdep_calls __initdata pSeries_md = { .power_off = rtas_power_off, .halt = rtas_halt, .panic = rtas_os_term, + .cpu_die = pSeries_cpu_die, .get_boot_time = pSeries_get_boot_time, .get_rtc_time = pSeries_get_rtc_time, .set_rtc_time = pSeries_set_rtc_time, .calibrate_decr = pSeries_calibrate_decr, .progress = pSeries_progress, + .check_legacy_ioport = pSeries_check_legacy_ioport, }; diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 0e4228316..72dcf20ca 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -7,13 +7,12 @@ * 2 of the License, or (at your option) any later version. */ -#include -#include -#include #include +#include #include #include #include +#include #include #include @@ -27,13 +26,6 @@ struct systemcfg *systemcfg; * field correctly */ extern unsigned long __toc_start; -/* Stack space used when we detect a bad kernel stack pointer, and - * early in SMP boots before relocation is enabled. - * - * ABI requires stack to be 128-byte aligned - */ -char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128))); - /* The Paca is an array with one entry per processor. Each contains an * ItLpPaca, which contains the information shared between the * hypervisor and Linux. Each also contains an ItLpRegSave area which @@ -44,19 +36,29 @@ char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128))); * processors. The processor VPD array needs one entry per physical * processor (not thread). */ -#define PACAINITDATA(number,start,lpq,asrr,asrv) \ -{ \ +#ifdef CONFIG_PPC_ISERIES +#define EXTRA_INITS(number, lpq) \ .lppaca_ptr = &paca[number].lppaca, \ + .lpqueue_ptr = (lpq), /* &xItLpQueue, */ \ .reg_save_ptr = &paca[number].reg_save, \ + .reg_save = { \ + .xDesc = 0xd397d9e2, /* "LpRS" */ \ + .xSize = sizeof(struct ItLpRegSave) \ + }, +#else +#define EXTRA_INITS(number, lpq) +#endif + +#define PACAINITDATA(number,start,lpq,asrr,asrv) \ +{ \ .lock_token = 0x8000, \ .paca_index = (number), /* Paca Index */ \ - .lpqueue_ptr = (lpq), /* &xItLpQueue, */ \ .default_decr = 0x00ff0000, /* Initial Decr */ \ .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ .stab_real = (asrr), /* Real pointer to segment table */ \ .stab_addr = (asrv), /* Virt pointer to segment table */ \ - .emergency_sp = &emergency_stack[((number)+1) * PAGE_SIZE], \ .cpu_start = (start), /* Processor start */ \ + .hw_cpu_id = 0xffff, \ .lppaca = { \ .xDesc = 0xd397d781, /* "LpPa" */ \ .xSize = sizeof(struct ItLpPaca), \ @@ -66,13 +68,10 @@ char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128))); .xEndOfQuantum = 0xfffffffffffffffful, \ .xSLBCount = 64, \ }, \ - .reg_save = { \ - .xDesc = 0xd397d9e2, /* "LpRS" */ \ - .xSize = sizeof(struct ItLpRegSave) \ - }, \ + EXTRA_INITS((number), (lpq)) \ } -struct paca_struct paca[] __page_aligned = { +struct paca_struct paca[] = { #ifdef CONFIG_PPC_ISERIES PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR), #else diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 30e50023c..9891dbead 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -11,18 +11,16 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include -#include #include #include -#include -#include -#include #include -#include #include +#include #include #include @@ -30,17 +28,29 @@ #include #include #include -#include -#include -#include -#include #include +#include #include "pci.h" +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + unsigned long pci_probe_only = 1; unsigned long pci_assign_all_buses = 0; +/* + * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch + * devices we don't have access to. + */ +unsigned long io_page_mask; + +EXPORT_SYMBOL(io_page_mask); + + unsigned int pcibios_assign_all_busses(void) { return pci_assign_all_buses; @@ -55,16 +65,9 @@ unsigned int pcibios_assign_all_busses(void) unsigned long isa_io_base; /* NULL if no ISA bus */ unsigned long pci_io_base; -void pcibios_name_device(struct pci_dev* dev); -void pcibios_final_fixup(void); -static void fixup_broken_pcnet32(struct pci_dev* dev); -static void fixup_windbond_82c105(struct pci_dev* dev); -extern void fixup_k2_sata(struct pci_dev* dev); - void iSeries_pcibios_init(void); -struct pci_controller *hose_head; -struct pci_controller **hose_tail = &hose_head; +LIST_HEAD(hose_list); struct pci_dma_ops pci_dma_ops; EXPORT_SYMBOL(pci_dma_ops); @@ -74,20 +77,6 @@ int global_phb_number; /* Global phb counter */ /* Cached ISA bridge dev. */ struct pci_dev *ppc64_isabridge_dev = NULL; -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, - fixup_broken_pcnet32 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, - fixup_windbond_82c105 }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, - pcibios_name_device }, -#ifdef CONFIG_PPC_PMAC - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, 0x0240, - fixup_k2_sata }, -#endif - { 0 } -}; - static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { @@ -96,32 +85,10 @@ static void fixup_broken_pcnet32(struct pci_dev* dev) pci_name_device(dev); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); -static void fixup_windbond_82c105(struct pci_dev* dev) -{ - /* Assume the windbond 82c105 is the IDE controller on a - * p610. We should probably be more careful in case - * someone tries to plug in a similar adapter. - */ - int i; - unsigned int reg; - - printk("Using INTC for W82c105 IDE controller.\n"); - pci_read_config_dword(dev, 0x40, ®); - /* Enable LEGIRQ to use INTC instead of ISA interrupts */ - pci_write_config_dword(dev, 0x40, reg | (1<<11)); - - for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) { - /* zap the 2nd function of the winbond chip */ - if (dev->resource[i].flags & IORESOURCE_IO - && dev->bus->number == 0 && dev->devfn == 0x81) - dev->resource[i].flags &= ~IORESOURCE_IO; - } -} - -void -pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, - struct resource *res) +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) { unsigned long offset = 0; struct pci_controller *hose = PCI_GET_PHB_PTR(dev); @@ -190,68 +157,27 @@ void pcibios_align_resource(void *data, struct resource *res, res->start = start; } -/* - * Allocate pci_controller(phb) initialized common variables. +static spinlock_t hose_spinlock = SPIN_LOCK_UNLOCKED; + +/* + * pci_controller(phb) initialized common variables. */ -struct pci_controller * __init -pci_alloc_pci_controller(enum phb_types controller_type) +void __devinit pci_setup_pci_controller(struct pci_controller *hose) { - struct pci_controller *hose; - char *model; - -#ifdef CONFIG_PPC_ISERIES - hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); -#else - hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); -#endif - if(hose == NULL) { - printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); - return NULL; - } - memset(hose, 0, sizeof(struct pci_controller)); - - switch(controller_type) { -#ifdef CONFIG_PPC_ISERIES - case phb_type_hypervisor: - model = "PHB HV"; - break; -#endif - case phb_type_python: - model = "PHB PY"; - break; - case phb_type_speedwagon: - model = "PHB SW"; - break; - case phb_type_winnipeg: - model = "PHB WP"; - break; - case phb_type_apple: - model = "PHB APPLE"; - break; - default: - model = "PHB UK"; - break; - } + memset(hose, 0, sizeof(struct pci_controller)); - if(strlen(model) < 8) - strcpy(hose->what,model); - else - memcpy(hose->what,model,7); - hose->type = controller_type; - hose->global_number = global_phb_number++; - - *hose_tail = hose; - hose_tail = &hose->next; - return hose; + spin_lock(&hose_spinlock); + hose->global_number = global_phb_number++; + list_add_tail(&hose->list_node, &hose_list); + spin_unlock(&hose_spinlock); } static void __init pcibios_claim_one_bus(struct pci_bus *b) { - struct list_head *ld; + struct pci_dev *dev; struct pci_bus *child_bus; - for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { - struct pci_dev *dev = pci_dev_b(ld); + list_for_each_entry(dev, &b->devices, bus_list) { int i; for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -270,29 +196,26 @@ static void __init pcibios_claim_one_bus(struct pci_bus *b) #ifndef CONFIG_PPC_ISERIES static void __init pcibios_claim_of_setup(void) { - struct list_head *lb; + struct pci_bus *b; - for (lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) { - struct pci_bus *b = pci_bus_b(lb); + list_for_each_entry(b, &pci_root_buses, node) pcibios_claim_one_bus(b); - } } #endif static int __init pcibios_init(void) { - struct pci_controller *hose; + struct pci_controller *hose, *tmp; struct pci_bus *bus; #ifdef CONFIG_PPC_ISERIES iSeries_pcibios_init(); #endif - //ppc64_boot_msg(0x40, "PCI Probe"); printk("PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ - for (hose = hose_head; hose; hose = hose->next) { + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { hose->last_busno = 0xff; bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data); @@ -308,23 +231,18 @@ static int __init pcibios_init(void) pci_assign_unassigned_resources() is able to work correctly with [partially] allocated PCI tree. */ pci_assign_unassigned_resources(); -#endif +#endif /* !CONFIG_PPC_ISERIES */ /* Call machine dependent final fixup */ if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); /* Cache the location of the ISA bridge (if we have one) */ - ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); if (ppc64_isabridge_dev != NULL) printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); printk("PCI: Probing PCI hardware done\n"); - //ppc64_boot_msg(0x41, "PCI Done"); - -#ifdef CONFIG_PPC_PSERIES - pci_addr_cache_build(); -#endif return 0; } @@ -414,9 +332,9 @@ int pci_name_bus(char *name, struct pci_bus *bus) * * Returns negative error code on failure, zero on success. */ -static __inline__ int -__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) +static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, + struct vm_area_struct *vma, + enum pci_mmap_state mmap_state) { struct pci_controller *hose = PCI_GET_PHB_PTR(dev); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; @@ -471,9 +389,9 @@ __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, * Set vm_flags of VMA, as appropriate for this architecture, for a pci device * mapping. */ -static __inline__ void -__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) +static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, + struct vm_area_struct *vma, + enum pci_mmap_state mmap_state) { vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; } @@ -482,9 +400,10 @@ __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci * device mapping. */ -static __inline__ void -__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) +static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, + struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, + int write_combine) { long prot = pgprot_val(vma->vm_page_prot); @@ -518,13 +437,13 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); - ret = remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot); return ret; } -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM static ssize_t pci_show_devspec(struct device *dev, char *buf) { struct pci_dev *pdev; @@ -537,11 +456,432 @@ static ssize_t pci_show_devspec(struct device *dev, char *buf) return sprintf(buf, "%s", np->full_name); } static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); -#endif /* CONFIG_PPC_PSERIES */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ void pcibios_add_platform_entries(struct pci_dev *pdev) { -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM device_create_file(&pdev->dev, &dev_attr_devspec); -#endif /* CONFIG_PPC_PSERIES */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ +} + +#ifdef CONFIG_PPC_MULTIPLATFORM + +#define ISA_SPACE_MASK 0x1 +#define ISA_SPACE_IO 0x1 + +static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, + unsigned long phb_io_base_phys, + void __iomem * phb_io_base_virt) +{ + struct isa_range *range; + unsigned long pci_addr; + unsigned int isa_addr; + unsigned int size; + int rlen = 0; + + range = (struct isa_range *) get_property(isa_node, "ranges", &rlen); + if (range == NULL || (rlen < sizeof(struct isa_range))) { + printk(KERN_ERR "no ISA ranges or unexpected isa range size," + "mapping 64k\n"); + __ioremap_explicit(phb_io_base_phys, (unsigned long)phb_io_base_virt, + 0x10000, _PAGE_NO_CACHE); + return; + } + + /* From "ISA Binding to 1275" + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 1: an ISA address + * cells 2 - 4: a PCI address + * (size depending on dev->n_addr_cells) + * cell 5: the size of the range + */ + if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { + isa_addr = range->isa_addr.a_lo; + pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | + range->pci_addr.a_lo; + + /* Assume these are both zero */ + if ((pci_addr != 0) || (isa_addr != 0)) { + printk(KERN_ERR "unexpected isa to pci mapping: %s\n", + __FUNCTION__); + return; + } + + size = PAGE_ALIGN(range->size); + + __ioremap_explicit(phb_io_base_phys, + (unsigned long) phb_io_base_virt, + size, _PAGE_NO_CACHE); + } +} + +void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev) +{ + unsigned int *ranges; + unsigned long size; + int rlen = 0; + int memno = 0; + struct resource *res; + int np, na = prom_n_addr_cells(dev); + unsigned long pci_addr, cpu_phys_addr; + + np = na + 5; + + /* From "PCI Binding to 1275" + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + rlen = 0; + hose->io_base_phys = 0; + ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + pci_addr = (unsigned long)ranges[1] << 32 | ranges[2]; + + cpu_phys_addr = ranges[3]; + if (na == 2) + cpu_phys_addr = cpu_phys_addr << 32 | ranges[4]; + + size = (unsigned long)ranges[na+3] << 32 | ranges[na+4]; + if (size == 0) + continue; + switch ((ranges[0] >> 24) & 0x3) { + case 1: /* I/O space */ + hose->io_base_phys = cpu_phys_addr; + hose->pci_io_size = size; + + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = pci_addr; + DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number, + res->start, res->start + size - 1); + break; + case 2: /* memory space */ + memno = 0; + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + + if (memno == 0) + hose->pci_mem_offset = cpu_phys_addr - pci_addr; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + res->start = cpu_phys_addr; + DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number, + res->start, res->start + size - 1); + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; + } +} + +void __init pci_setup_phb_io(struct pci_controller *hose, int primary) +{ + unsigned long size = hose->pci_io_size; + unsigned long io_virt_offset; + struct resource *res; + struct device_node *isa_dn; + + hose->io_base_virt = reserve_phb_iospace(size); + DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", + hose->global_number, hose->io_base_phys, + (unsigned long) hose->io_base_virt); + + if (primary) { + pci_io_base = (unsigned long)hose->io_base_virt; + isa_dn = of_find_node_by_type(NULL, "isa"); + if (isa_dn) { + isa_io_base = pci_io_base; + pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, + hose->io_base_virt); + of_node_put(isa_dn); + /* Allow all IO */ + io_page_mask = -1; + } + } + + io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; + res = &hose->io_resource; + res->start += io_virt_offset; + res->end += io_virt_offset; +} + +void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose) +{ + unsigned long size = hose->pci_io_size; + unsigned long io_virt_offset; + struct resource *res; + + hose->io_base_virt = __ioremap(hose->io_base_phys, size, + _PAGE_NO_CACHE); + DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", + hose->global_number, hose->io_base_phys, + (unsigned long) hose->io_base_virt); + + io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; + res = &hose->io_resource; + res->start += io_virt_offset; + res->end += io_virt_offset; +} + + +static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, + unsigned long *start_virt, unsigned long *size) +{ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_bus_region region; + struct resource *res; + + if (bus->self) { + res = bus->resource[0]; + pcibios_resource_to_bus(bus->self, ®ion, res); + *start_phys = hose->io_base_phys + region.start; + *start_virt = (unsigned long) hose->io_base_virt + + region.start; + if (region.end > region.start) + *size = region.end - region.start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, region.start, region.end); + return 1; + } + + } else { + /* Root Bus */ + res = &hose->io_resource; + *start_phys = hose->io_base_phys; + *start_virt = (unsigned long) hose->io_base_virt; + if (res->end > res->start) + *size = res->end - res->start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, res->start, res->end); + return 1; + } + } + + return 0; } + +int unmap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; + + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + if (iounmap_explicit((void __iomem *) start_virt, size)) + return 1; + + return 0; +} +EXPORT_SYMBOL(unmap_bus_range); + +int remap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; + + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); + if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE)) + return 1; + + return 0; +} +EXPORT_SYMBOL(remap_bus_range); + +void phbs_remap_io(void) +{ + struct pci_controller *hose, *tmp; + + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + remap_bus_range(hose->bus); +} + + +/* + * This function finds the PHB that matching device_node in the + * OpenFirmware by scanning all the pci_controllers. + */ +struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node) +{ + while (node) { + struct pci_controller *hose, *tmp; + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + if (hose->arch_data == node) + return hose; + node=node->parent; + } + return NULL; +} + +/* + * ppc64 can have multifunction devices that do not respond to function 0. + * In this case we must scan all functions. + */ +int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) +{ + struct device_node *busdn, *dn; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + + if (busdn == NULL) + return 0; + + /* + * Check to see if there is any of the 8 functions are in the + * device tree. If they are then we need to scan all the + * functions of this slot. + */ + for (dn = busdn->child; dn; dn = dn->sibling) + if ((dn->devfn >> 3) == (devfn >> 3)) + return 1; + + return 0; +} + + +void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, + struct pci_bus *bus) +{ + /* Update device resources. */ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (dev->resource[i].flags & IORESOURCE_IO) { + unsigned long offset = (unsigned long)hose->io_base_virt + - pci_io_base; + unsigned long start, end, mask; + + start = dev->resource[i].start += offset; + end = dev->resource[i].end += offset; + + /* Need to allow IO access to pages that are in the + ISA range */ + if (start < MAX_ISA_PORT) { + if (end > MAX_ISA_PORT) + end = MAX_ISA_PORT; + + start >>= PAGE_SHIFT; + end >>= PAGE_SHIFT; + + /* get the range of pages for the map */ + mask = ((1 << (end+1))-1) ^ ((1 << start)-1); + io_page_mask |= mask; + } + } + else if (dev->resource[i].flags & IORESOURCE_MEM) { + dev->resource[i].start += hose->pci_mem_offset; + dev->resource[i].end += hose->pci_mem_offset; + } + } +} +EXPORT_SYMBOL(pcibios_fixup_device_resources); + +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_dev *dev = bus->self; + struct resource *res; + int i; + + if (!dev) { + /* Root bus. */ + + hose->bus = bus; + bus->resource[0] = res = &hose->io_resource; + + if (res->flags && request_resource(&ioport_resource, res)) + printk(KERN_ERR "Failed to request IO on " + "PCI domain %d\n", pci_domain_nr(bus)); + + for (i = 0; i < 3; ++i) { + res = &hose->mem_resources[i]; + bus->resource[i+1] = res; + if (res->flags && request_resource(&iomem_resource, res)) + printk(KERN_ERR "Failed to request MEM on " + "PCI domain %d\n", + pci_domain_nr(bus)); + } + } else if (pci_probe_only && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + /* This is a subordinate bridge */ + + pci_read_bridge_bases(bus); + pcibios_fixup_device_resources(dev, bus); + } + + if (!pci_probe_only) + return; + + list_for_each_entry(dev, &bus->devices, bus_list) { + if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + pcibios_fixup_device_resources(dev, bus); + } +} +EXPORT_SYMBOL(pcibios_fixup_bus); + +/* + * Reads the interrupt pin to determine if interrupt is use by card. + * If the interrupt is used, then gets the interrupt line from the + * openfirmware and sets it in the pci_dev and pci_config line. + */ +int pci_read_irq_line(struct pci_dev *pci_dev) +{ + u8 intpin; + struct device_node *node; + + pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); + if (intpin == 0) + return 0; + + node = pci_device_to_OF_node(pci_dev); + if (node == NULL) + return -1; + + if (node->n_intrs == 0) + return -1; + + pci_dev->irq = node->intrs[0].line; + + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); + + return 0; +} +EXPORT_SYMBOL(pci_read_irq_line); + +#endif /* CONFIG_PPC_MULTIPLATFORM */ diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h index 2ca27ccc7..2ed6b674b 100644 --- a/arch/ppc64/kernel/pci.h +++ b/arch/ppc64/kernel/pci.h @@ -14,30 +14,28 @@ extern unsigned long isa_io_base; -extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type); +extern void pci_setup_pci_controller(struct pci_controller *hose); +extern void pci_setup_phb_io(struct pci_controller *hose, int primary); + extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); +extern void pci_setup_phb_io_dynamic(struct pci_controller *hose); -extern struct pci_controller* hose_head; -extern struct pci_controller** hose_tail; +extern struct list_head hose_list; extern int global_phb_number; -/******************************************************************* - * Platform functions that are brand specific implementation. - *******************************************************************/ extern unsigned long find_and_init_phbs(void); extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ -/******************************************************************* - * PCI device_node operations - *******************************************************************/ +/* PCI device_node operations */ struct device_node; typedef void *(*traverse_func)(struct device_node *me, void *data); void *traverse_pci_devices(struct device_node *start, traverse_func pre, void *data); void pci_devs_phb_init(void); +void pci_devs_phb_init_dynamic(struct pci_controller *phb); void pci_fix_bus_sysdata(void); struct device_node *fetch_dev_dn(struct pci_dev *dev); @@ -51,5 +49,8 @@ void pci_addr_cache_remove_device(struct pci_dev *dev); void init_pci_config_tokens (void); unsigned long get_phb_buid (struct device_node *); +extern unsigned long pci_probe_only; +extern unsigned long pci_assign_all_buses; +extern int pci_read_irq_line(struct pci_dev *pci_dev); #endif /* __PPC_KERNEL_PCI_H__ */ diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index c771bdc64..ab328ffb6 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c @@ -42,33 +42,17 @@ * Traverse_func that inits the PCI fields of the device node. * NOTE: this *must* be done before read/write config to the device. */ -static void * __init update_dn_pci_info(struct device_node *dn, void *data) +static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) { struct pci_controller *phb = data; u32 *regs; - char *device_type = get_property(dn, "device_type", NULL); - char *model; dn->phb = phb; - if (device_type && (strcmp(device_type, "pci") == 0) && - (get_property(dn, "class-code", NULL) == 0)) { - /* special case for PHB's. Sigh. */ - regs = (u32 *)get_property(dn, "bus-range", NULL); - dn->busno = regs[0]; - - model = (char *)get_property(dn, "model", NULL); - - if (strstr(model, "U3")) - dn->devfn = -1; - else - dn->devfn = 0; /* assumption */ - } else { - regs = (u32 *)get_property(dn, "reg", NULL); - if (regs) { - /* First register entry is addr (00BBSS00) */ - dn->busno = (regs[0] >> 16) & 0xff; - dn->devfn = (regs[0] >> 8) & 0xff; - } + regs = (u32 *)get_property(dn, "reg", NULL); + if (regs) { + /* First register entry is addr (00BBSS00) */ + dn->busno = (regs[0] >> 16) & 0xff; + dn->devfn = (regs[0] >> 8) & 0xff; } return NULL; } @@ -97,20 +81,25 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, struct device_node *dn, *nextdn; void *ret; - if (pre && ((ret = pre(start, data)) != NULL)) - return ret; + /* We started with a phb, iterate all childs */ for (dn = start->child; dn; dn = nextdn) { + u32 *classp, class; + nextdn = NULL; - if (get_property(dn, "class-code", NULL)) { - if (pre && ((ret = pre(dn, data)) != NULL)) - return ret; - if (dn->child) - /* Depth first...do children */ - nextdn = dn->child; - else if (dn->sibling) - /* ok, try next sibling instead. */ - nextdn = dn->sibling; - } + classp = (u32 *)get_property(dn, "class-code", NULL); + class = classp ? *classp : 0; + + if (pre && ((ret = pre(dn, data)) != NULL)) + return ret; + + /* If we are a PCI bridge, go down */ + if (dn->child && ((class >> 8) == PCI_CLASS_BRIDGE_PCI || + (class >> 8) == PCI_CLASS_BRIDGE_CARDBUS)) + /* Depth first...do children */ + nextdn = dn->child; + else if (dn->sibling) + /* ok, try next sibling instead. */ + nextdn = dn->sibling; if (!nextdn) { /* Walk up to next valid sibling. */ do { @@ -124,21 +113,17 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, return NULL; } -/* - * Same as traverse_pci_devices except this does it for all phbs. - */ -static void *traverse_all_pci_devices(traverse_func pre) +void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb) { - struct pci_controller *phb; - void *ret; + struct device_node * dn = (struct device_node *) phb->arch_data; - for (phb = hose_head; phb; phb = phb->next) - if ((ret = traverse_pci_devices(phb->arch_data, pre, phb)) - != NULL) - return ret; - return NULL; -} + /* PHB nodes themselves must not match */ + dn->devfn = dn->busno = -1; + dn->phb = phb; + /* Update dn->phb ptrs for new phb and children devices */ + traverse_pci_devices(dn, update_dn_pci_info, phb); +} /* * Traversal func that looks for a value. @@ -148,6 +133,7 @@ static void *is_devfn_node(struct device_node *dn, void *data) { int busno = ((unsigned long)data >> 8) & 0xff; int devfn = ((unsigned long)data) & 0xff; + return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL; } @@ -174,10 +160,8 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev) phb_dn = phb->arch_data; dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval); - if (dn) { + if (dn) dev->sysdata = dn; - /* ToDo: call some device init hook here */ - } return dn; } EXPORT_SYMBOL(fetch_dev_dn); @@ -189,18 +173,19 @@ EXPORT_SYMBOL(fetch_dev_dn); */ void __init pci_devs_phb_init(void) { + struct pci_controller *phb, *tmp; + /* This must be done first so the device nodes have valid pci info! */ - traverse_all_pci_devices(update_dn_pci_info); + list_for_each_entry_safe(phb, tmp, &hose_list, list_node) + pci_devs_phb_init_dynamic(phb); } static void __init pci_fixup_bus_sysdata_list(struct list_head *bus_list) { - struct list_head *ln; struct pci_bus *bus; - for (ln = bus_list->next; ln != bus_list; ln = ln->next) { - bus = pci_bus_b(ln); + list_for_each_entry(bus, bus_list, node) { if (bus->self) bus->sysdata = bus->self->sysdata; pci_fixup_bus_sysdata_list(&bus->children); diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c index 4d99851fe..dd5ad02d7 100644 --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/ppc64/kernel/pci_iommu.c @@ -43,6 +43,13 @@ #include #endif /* CONFIG_PPC_ISERIES */ +/* + * We can use ->sysdata directly and avoid the extra work in + * pci_device_to_OF_node since ->sysdata will have been initialised + * in the iommu init code for all devices. + */ +#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) + static inline struct iommu_table *devnode_table(struct pci_dev *dev) { if (!dev) @@ -54,9 +61,9 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev) return ISERIES_DEVNODE(dev)->iommu_table; #endif /* CONFIG_PPC_ISERIES */ -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM return PCI_GET_DN(dev)->iommu_table; -#endif /* CONFIG_PPC_PSERIES */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ } diff --git a/arch/ppc64/kernel/pmac.h b/arch/ppc64/kernel/pmac.h index 4d69b3abc..40e1c5030 100644 --- a/arch/ppc64/kernel/pmac.h +++ b/arch/ppc64/kernel/pmac.h @@ -18,7 +18,6 @@ extern void pmac_calibrate_decr(void); extern void pmac_pcibios_fixup(void); extern void pmac_pci_init(void); extern void pmac_setup_pci_dma(void); -extern void fixup_k2_sata(struct pci_dev* dev); extern void pmac_check_ht_link(void); extern void pmac_setup_smp(void); diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c index c059a7608..c45ecbdb2 100644 --- a/arch/ppc64/kernel/pmac_feature.c +++ b/arch/ppc64/kernel/pmac_feature.c @@ -44,9 +44,9 @@ #undef DEBUG_FEATURE #ifdef DEBUG_FEATURE -#define DBG(fmt,...) printk(KERN_DEBUG fmt) +#define DBG(fmt...) printk(KERN_DEBUG fmt) #else -#define DBG(fmt,...) +#define DBG(fmt...) #endif /* @@ -343,6 +343,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { PMAC_TYPE_POWERMAC_G5, g5_features, 0, }, + { "PowerMac7,3", "PowerMac G5", + PMAC_TYPE_POWERMAC_G5, g5_features, + 0, + }, { "RackMac3,1", "XServe G5", PMAC_TYPE_POWERMAC_G5, g5_features, 0, @@ -611,7 +615,7 @@ int __init pmac_feature_late_init(void) device_initcall(pmac_feature_late_init); - +#if 0 static void dump_HT_speeds(char *name, u32 cfg, u32 frq) { int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; @@ -625,6 +629,7 @@ static void dump_HT_speeds(char *name, u32 cfg, u32 frq) name, freqs[freq], bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); } +#endif void __init pmac_check_ht_link(void) { diff --git a/arch/ppc64/kernel/pmac_low_i2c.c b/arch/ppc64/kernel/pmac_low_i2c.c index d07579f2b..f3f39e8e3 100644 --- a/arch/ppc64/kernel/pmac_low_i2c.c +++ b/arch/ppc64/kernel/pmac_low_i2c.c @@ -16,9 +16,10 @@ * properties parser */ +#undef DEBUG + #include #include -#include #include #include #include @@ -33,12 +34,12 @@ #define MAX_LOW_I2C_HOST 4 -#if 1 +#ifdef DEBUG #define DBG(x...) do {\ printk(KERN_DEBUG "KW:" x); \ } while(0) #else -#define DBGG(x...) +#define DBG(x...) #endif struct low_i2c_host; @@ -50,11 +51,11 @@ struct low_i2c_host struct device_node *np; /* OF device node */ struct semaphore mutex; /* Access mutex for use by i2c-keywest */ low_i2c_func_t func; /* Access function */ - int is_open : 1; /* Poor man's access control */ + unsigned int is_open : 1; /* Poor man's access control */ int mode; /* Current mode */ int channel; /* Current channel */ int num_channels; /* Number of channels */ - unsigned long base; /* For keywest-i2c, base address */ + void __iomem *base; /* For keywest-i2c, base address */ int bsteps; /* And register stepping */ int speed; /* And speed */ }; @@ -154,14 +155,12 @@ static const char *__kw_state_names[] = { static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) { - return in_8(((volatile u8 *)host->base) - + (((unsigned)reg) << host->bsteps)); + return readb(host->base + (((unsigned int)reg) << host->bsteps)); } static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) { - out_8(((volatile u8 *)host->base) - + (((unsigned)reg) << host->bsteps), val); + writeb(val, host->base + (((unsigned)reg) << host->bsteps)); (void)__kw_read_reg(host, reg_subaddr); } @@ -174,14 +173,19 @@ static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) */ static u8 kw_wait_interrupt(struct low_i2c_host* host) { - int i; + int i, j; u8 isr; - for (i = 0; i < 200000; i++) { + for (i = 0; i < 100000; i++) { isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; if (isr != 0) return isr; - udelay(1); + + /* This code is used with the timebase frozen, we cannot rely + * on udelay ! For now, just use a bogus loop + */ + for (j = 1; j < 10000; j++) + mb(); } return isr; } @@ -190,6 +194,8 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int { u8 ack; + DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr); + if (isr == 0) { if (state != state_stop) { DBG("KW: Timeout !\n"); @@ -301,11 +307,9 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, break; case pmac_low_i2c_mode_stdsub: mode_reg |= KW_I2C_MODE_STANDARDSUB; - kw_write_reg(reg_subaddr, subaddr); break; case pmac_low_i2c_mode_combined: mode_reg |= KW_I2C_MODE_COMBINED; - kw_write_reg(reg_subaddr, subaddr); break; } @@ -317,6 +321,11 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, /* Set up address and r/w bit */ kw_write_reg(reg_addr, addr); + /* Set up the sub address */ + if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB + || (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) + kw_write_reg(reg_subaddr, subaddr); + /* Start sending address & disable interrupt*/ kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); kw_write_reg(reg_control, KW_I2C_CTL_XADDR); @@ -333,7 +342,7 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, static void keywest_low_i2c_add(struct device_node *np) { struct low_i2c_host *host = find_low_i2c_host(NULL); - unsigned long *psteps, *prate, steps, aoffset = 0; + u32 *psteps, *prate, steps, aoffset = 0; struct device_node *parent; if (host == NULL) { @@ -345,7 +354,7 @@ static void keywest_low_i2c_add(struct device_node *np) init_MUTEX(&host->mutex); host->np = of_node_get(np); - psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); + psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); steps = psteps ? (*psteps) : 0x10; for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) steps >>= 1; @@ -357,7 +366,7 @@ static void keywest_low_i2c_add(struct device_node *np) } /* Select interface rate */ host->speed = KW_I2C_MODE_100KHZ; - prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); + prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); if (prate) switch(*prate) { case 100: host->speed = KW_I2C_MODE_100KHZ; @@ -369,8 +378,9 @@ static void keywest_low_i2c_add(struct device_node *np) host->speed = KW_I2C_MODE_25KHZ; break; } + host->mode = pmac_low_i2c_mode_std; - host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset, + host->base = ioremap(np->addrs[0].address + aoffset, np->addrs[0].size); host->func = keywest_low_i2c_func; } diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c index 169195713..00d1db487 100644 --- a/arch/ppc64/kernel/pmac_pci.c +++ b/arch/ppc64/kernel/pmac_pci.c @@ -39,14 +39,10 @@ #define DBG(x...) #endif -extern int pci_probe_only; -extern int pci_read_irq_line(struct pci_dev *pci_dev); - /* XXX Could be per-controller, but I don't think we risk anything by * assuming we won't have both UniNorth and Bandit */ static int has_uninorth; static struct pci_controller *u3_agp; -u8 pci_cache_line_size; struct pci_dev *k2_skiplist[2]; static int __init fixup_one_level_bus_range(struct device_node *node, int higher) @@ -150,16 +146,9 @@ static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -188,16 +177,9 @@ static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; @@ -236,14 +218,44 @@ static struct pci_ops macrisc_pci_ops = * implement self-view of the HT host yet */ -static int skip_k2_device(struct pci_bus *bus, unsigned int devfn) +/* + * This function deals with some "special cases" devices. + * + * 0 -> No special case + * 1 -> Skip the device but act as if the access was successfull + * (return 0xff's on reads, eventually, cache config space + * accesses in a later version) + * -1 -> Hide the device (unsuccessful acess) + */ +static int u3_ht_skip_device(struct pci_controller *hose, + struct pci_bus *bus, unsigned int devfn) { + struct device_node *busdn, *dn; int i; + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ for (i=0; i<2; i++) if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && k2_skiplist[i]->devfn == devfn) return 1; + + /* We only allow config cycles to devices that are in OF device-tree + * as we are apparently having some weird things going on with some + * revs of K2 on recent G5s + */ + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = hose->arch_data; + for (dn = busdn->child; dn; dn = dn->sibling) + if (dn->devfn == devfn) + break; + if (dn == NULL) + return -1; + return 0; } @@ -259,8 +271,7 @@ static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose, { if (bus == hose->first_busno) { /* For now, we don't self probe U3 HT bridge */ - if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || - PCI_SLOT(devfn) < 1) + if (PCI_SLOT(devfn) == 0) return 0; return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset); } else @@ -271,29 +282,21 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. We may ultimately want - * to cache the config space for those instead of returning - * 0xffffffff's to make life easier to HW detection tools - */ - if (skip_k2_device(bus, devfn)) { + + switch (u3_ht_skip_device(hose, bus, devfn)) { + case 0: + break; + case 1: switch (len) { case 1: *val = 0xff; break; @@ -303,6 +306,8 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, *val = 0xfffffffful; break; } return PCIBIOS_SUCCESSFUL; + default: + return PCIBIOS_DEVICE_NOT_FOUND; } /* @@ -327,28 +332,24 @@ static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { struct pci_controller *hose; - struct device_node *busdn; unsigned long addr; - if (bus->self) - busdn = pci_device_to_OF_node(bus->self); - else - busdn = bus->sysdata; /* must be a phb */ - if (busdn == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - hose = busdn->phb; + hose = pci_bus_to_host(bus); if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - if (skip_k2_device(bus, devfn)) + + switch (u3_ht_skip_device(hose, bus, devfn)) { + case 0: + break; + case 1: return PCIBIOS_SUCCESSFUL; + default: + return PCIBIOS_DEVICE_NOT_FOUND; + } /* * Note: the caller has already checked that offset is @@ -419,7 +420,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) * properties or figuring out the U3 address space decoding logic and * then read it's configuration register (if any). */ - hose->io_base_phys = 0xf4000000 + 0x00400000; + hose->io_base_phys = 0xf4000000; hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt; hose->io_resource.name = np->full_name; @@ -503,7 +504,7 @@ static void __init pmac_process_bridge_OF_ranges(struct pci_controller *hose, dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); if (!dt_ranges) return; - /* lc_ranges = (unsigned int *) alloc_bootmem(rlen);*/ + /* lc_ranges = alloc_bootmem(rlen);*/ lc_ranges = static_lc_ranges; if (!lc_ranges) return; /* what can we do here ? */ @@ -613,15 +614,17 @@ static int __init add_bridge(struct device_node *dev) dev->full_name); } - hose = pci_alloc_pci_controller(phb_type_apple); - if (!hose) - return -ENOMEM; + hose = alloc_bootmem(sizeof(struct pci_controller)); + if (hose == NULL) + return -ENOMEM; + pci_setup_pci_controller(hose); + hose->arch_data = dev; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + - sizeof(hose->global_number)); + of_prop = alloc_bootmem(sizeof(struct property) + + sizeof(hose->global_number)); if (of_prop) { memset(of_prop, 0, sizeof(struct property)); of_prop->name = "linux,pci-domain"; @@ -659,22 +662,19 @@ void __init pmac_pcibios_fixup(void) { struct pci_dev *dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + for_each_pci_dev(dev) pci_read_irq_line(dev); pci_fix_bus_sysdata(); -#ifdef CONFIG_PMAC_DART - iommu_setup_pmac(); -#endif /* CONFIG_PMAC_DART */ - + iommu_setup_u3(); } static void __init pmac_fixup_phb_resources(void) { - struct pci_controller *hose; + struct pci_controller *hose, *tmp; - for (hose = hose_head; hose; hose = hose->next) { + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; hose->io_resource.start += offset; hose->io_resource.end += offset; @@ -739,20 +739,18 @@ void __init pmac_pci_init(void) pmac_check_ht_link(); - /* Tell pci.c to use the common resource allocation mecanism */ - pci_probe_only = 0; + /* Tell pci.c to not use the common resource allocation mecanism */ + pci_probe_only = 1; - /* HT don't do more than 64 bytes transfers. FIXME: Deal with - * the exception of U3/AGP (hook into pci_set_mwi) - */ - pci_cache_line_size = 16; /* 64 bytes */ + /* Allow all IO */ + io_page_mask = -1; } /* * Disable second function on K2-SATA, it's broken * and disable IO BARs on first one */ -void fixup_k2_sata(struct pci_dev* dev) +static void fixup_k2_sata(struct pci_dev* dev) { int i; u16 cmd; @@ -777,3 +775,4 @@ void fixup_k2_sata(struct pci_dev* dev) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata); diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index 58e8b392e..92b0e3c93 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -23,6 +23,8 @@ * bootup setup stuff.. */ +#undef DEBUG + #include #include #include @@ -51,19 +53,17 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include #include #include #include -#include #include #include #include @@ -72,6 +72,14 @@ #include #include "pmac.h" +#include "mpic.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + static int current_root_goodness = -1; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ @@ -81,10 +89,6 @@ int sccdbg; extern void udbg_init_scc(struct device_node *np); -#ifdef CONFIG_BOOTX_TEXT -void pmac_progress(char *s, unsigned short hex); -#endif - void __pmac pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; @@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m) void __init pmac_setup_arch(void) { - struct device_node *cpu; - int *fp; - unsigned long pvr; - - pvr = PVR_VER(mfspr(PVR)); - - /* Set loops_per_jiffy to a half-way reasonable value, - for use until calibrate_delay gets called. */ - cpu = find_type_devices("cpu"); - if (cpu != 0) { - fp = (int *) get_property(cpu, "clock-frequency", NULL); - if (fp != 0) { - if (pvr == 4 || pvr >= 8) - /* 604, G3, G4 etc. */ - loops_per_jiffy = *fp / HZ; - else - /* 601, 603, etc. */ - loops_per_jiffy = *fp / (2*HZ); - } else - loops_per_jiffy = 50000000 / HZ; + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000; + + /* Probe motherboard chipset */ + pmac_feature_init(); +#if 0 + /* Lock-enable the SCC channel used for debug */ + if (sccdbg) { + np = of_find_node_by_name(NULL, "escc"); + if (np) + pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, + PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); } - +#endif /* We can NAP */ powersave_nap = 1; @@ -183,67 +179,13 @@ void __init pmac_setup_arch(void) #endif } -extern char *bootpath; -extern char *bootdevice; -void *boot_host; -int boot_target; -int boot_part; -extern dev_t boot_dev; - #ifdef CONFIG_SCSI -void __init note_scsi_host(struct device_node *node, void *host) +void note_scsi_host(struct device_node *node, void *host) { - int l; - char *p; - - l = strlen(node->full_name); - if (bootpath != NULL && bootdevice != NULL - && strncmp(node->full_name, bootdevice, l) == 0 - && (bootdevice[l] == '/' || bootdevice[l] == 0)) { - boot_host = host; - /* - * There's a bug in OF 1.0.5. (Why am I not surprised.) - * If you pass a path like scsi/sd@1:0 to canon, it returns - * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 - * That is, the scsi target number doesn't get preserved. - * So we pick the target number out of bootpath and use that. - */ - p = strstr(bootpath, "/sd@"); - if (p != NULL) { - p += 4; - boot_target = simple_strtoul(p, NULL, 10); - p = strchr(p, ':'); - if (p != NULL) - boot_part = simple_strtoul(p + 1, NULL, 10); - } - } + /* Obsolete */ } #endif -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -static dev_t __init find_ide_boot(void) -{ - char *p; - int n; - dev_t __init pmac_find_ide_boot(char *bootdevice, int n); - - if (bootdevice == NULL) - return 0; - p = strrchr(bootdevice, '/'); - if (p == NULL) - return 0; - n = p - bootdevice; - - return pmac_find_ide_boot(bootdevice, n); -} -#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ - -void __init find_boot_device(void) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - boot_dev = find_ide_boot(); -#endif -} static int initializing = 1; @@ -258,7 +200,7 @@ late_initcall(pmac_late_init); /* can't be __init - can be called whenever a disk is first accessed */ void __pmac note_bootable_part(dev_t dev, int part, int goodness) { - static int found_boot = 0; + extern dev_t boot_dev; char *p; if (!initializing) @@ -270,10 +212,6 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness) if (p != NULL && (p == saved_command_line || p[-1] == ' ')) return; - if (!found_boot) { - find_boot_device(); - found_boot = 1; - } if (!boot_dev || dev == boot_dev) { ROOT_DEV = dev + part; boot_dev = 0; @@ -313,46 +251,78 @@ static void btext_putc(unsigned char c) } #endif /* CONFIG_BOOTX_TEXT */ +static void __init init_boot_display(void) +{ + char *name; + struct device_node *np = NULL; + int rc = -ENODEV; + + printk("trying to initialize btext ...\n"); + + name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); + if (name != NULL) { + np = of_find_node_by_path(name); + if (np != NULL) { + if (strcmp(np->type, "display") != 0) { + printk("boot stdout isn't a display !\n"); + of_node_put(np); + np = NULL; + } + } + } + if (np) + rc = btext_initialize(np); + if (rc == 0) + return; + + for (np = NULL; (np = of_find_node_by_type(np, "display"));) { + if (get_property(np, "linux,opened", NULL)) { + printk("trying %s ...\n", np->full_name); + rc = btext_initialize(np); + printk("result: %d\n", rc); + } + if (rc == 0) + return; + } +} + /* * Early initialization. - * Relocation is on but do not reference unbolted pages - * Also, device-tree hasn't been "finished", so don't muck with - * it too much */ void __init pmac_init_early(void) { - hpte_init_pSeries(); + DBG(" -> pmac_init_early\n"); + + /* Initialize hash table, from now on, we can take hash faults + * and call ioremap + */ + hpte_init_native(); + + /* Init SCC */ + if (strstr(cmd_line, "sccdbg")) { + sccdbg = 1; + udbg_init_scc(NULL); + } + else { #ifdef CONFIG_BOOTX_TEXT - ppc_md.udbg_putc = btext_putc; - ppc_md.udbg_getc = dummy_getc; - ppc_md.udbg_getc_poll = dummy_getc_poll; + init_boot_display(); + + ppc_md.udbg_putc = btext_putc; + ppc_md.udbg_getc = dummy_getc; + ppc_md.udbg_getc_poll = dummy_getc_poll; #endif /* CONFIG_BOOTX_TEXT */ -} + } -extern void* OpenPIC_Addr; -extern void* OpenPIC2_Addr; -extern u_int OpenPIC_NumInitSenses; -extern u_char *OpenPIC_InitSenses; -extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack, - int programmer_switch_irq); -extern void openpic2_init(int offset); -extern int openpic_get_irq(struct pt_regs *regs); -extern int openpic2_get_irq(struct pt_regs *regs); + /* Setup interrupt mapping options */ + naca->interrupt_controller = IC_OPEN_PIC; -static int pmac_cascade_irq = -1; + DBG(" <- pmac_init_early\n"); +} -static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs) +static int pmac_u3_cascade(struct pt_regs *regs, void *data) { - int irq; - - for (;;) { - irq = openpic2_get_irq(regs); - if (irq == -1) - break; - ppc_irq_dispatch_handler(regs, irq); - } - return IRQ_HANDLED; + return mpic_get_one_irq((struct mpic *)data, regs); } static __init void pmac_init_IRQ(void) @@ -360,6 +330,7 @@ static __init void pmac_init_IRQ(void) struct device_node *irqctrler = NULL; struct device_node *irqctrler2 = NULL; struct device_node *np = NULL; + struct mpic *mpic1, *mpic2; /* We first try to detect Apple's new Core99 chipset, since mac-io * is quite different on those machines and contains an IBM MPIC2. @@ -379,98 +350,59 @@ static __init void pmac_init_IRQ(void) (unsigned int)irqctrler->addrs[0].address); prom_get_irq_senses(senses, 0, 128); - OpenPIC_InitSenses = senses; - OpenPIC_NumInitSenses = 128; - OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, - irqctrler->addrs[0].size); - openpic_init(1, 0, NULL, -1); + mpic1 = mpic_alloc(irqctrler->addrs[0].address, + MPIC_PRIMARY | MPIC_WANTS_RESET, + 0, 0, 128, 256, senses, 128, " K2-MPIC "); + BUG_ON(mpic1 == NULL); + mpic_init(mpic1); if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && irqctrler2->n_addrs > 0) { printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", (u32)irqctrler2->addrs[0].address, irqctrler2->intrs[0].line); + pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); - OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, - irqctrler2->addrs[0].size); prom_get_irq_senses(senses, 128, 128 + 128); - OpenPIC_InitSenses = senses; - OpenPIC_NumInitSenses = 128; - openpic2_init(128); - pmac_cascade_irq = irqctrler2->intrs[0].line; + + /* We don't need to set MPIC_BROKEN_U3 here since we don't have + * hypertransport interrupts routed to it + */ + mpic2 = mpic_alloc(irqctrler2->addrs[0].address, + MPIC_BIG_ENDIAN | MPIC_WANTS_RESET, + 0, 128, 128, 0, senses, 128, " U3-MPIC "); + BUG_ON(mpic2 == NULL); + mpic_init(mpic2); + mpic_setup_cascade(irqctrler2->intrs[0].line, + pmac_u3_cascade, mpic2); } } of_node_put(irqctrler); of_node_put(irqctrler2); } -/* We cannot do request_irq too early ... Right now, we get the - * cascade as a core_initcall, which should be fine for our needs - */ -static int __init pmac_irq_cascade_init(void) -{ - if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0, - "U3->K2 Cascade", NULL)) - printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n"); - return 0; -} - -core_initcall(pmac_irq_cascade_init); - -void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* Probe motherboard chipset */ - pmac_feature_init(); - - /* Init SCC */ - if (strstr(cmd_line, "sccdbg")) { - sccdbg = 1; - udbg_init_scc(NULL); - } - - /* Fill up the machine description */ - ppc_md.setup_arch = pmac_setup_arch; - ppc_md.get_cpuinfo = pmac_show_cpuinfo; - - ppc_md.init_IRQ = pmac_init_IRQ; - ppc_md.get_irq = openpic_get_irq; - - ppc_md.pcibios_fixup = pmac_pcibios_fixup; - - ppc_md.restart = pmac_restart; - ppc_md.power_off = pmac_power_off; - ppc_md.halt = pmac_halt; - - ppc_md.get_boot_time = pmac_get_boot_time; - ppc_md.set_rtc_time = pmac_set_rtc_time; - ppc_md.get_rtc_time = pmac_get_rtc_time; - ppc_md.calibrate_decr = pmac_calibrate_decr; - - ppc_md.feature_call = pmac_do_feature_call; - - -#ifdef CONFIG_BOOTX_TEXT - ppc_md.progress = pmac_progress; -#endif /* CONFIG_BOOTX_TEXT */ - - if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); - -} - -#ifdef CONFIG_BOOTX_TEXT -void __init pmac_progress(char *s, unsigned short hex) +static void __init pmac_progress(char *s, unsigned short hex) { if (sccdbg) { udbg_puts(s); - udbg_putc('\n'); + udbg_puts("\n"); } +#ifdef CONFIG_BOOTX_TEXT else if (boot_text_mapped) { btext_drawstring(s); - btext_drawchar('\n'); + btext_drawstring("\n"); } -} #endif /* CONFIG_BOOTX_TEXT */ +} + +/* + * pmac has no legacy IO, anything calling this function has to + * fail or bad things will happen + */ +static int pmac_check_legacy_ioport(unsigned int baseport) +{ + return -ENODEV; +} static int __init pmac_declare_of_platform_devices(void) { @@ -489,3 +421,42 @@ static int __init pmac_declare_of_platform_devices(void) } device_initcall(pmac_declare_of_platform_devices); + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init pmac_probe(int platform) +{ + if (platform != PLATFORM_POWERMAC) + return 0; + + /* + * On U3, the DART (iommu) must be allocated now since it + * has an impact on htab_initialize (due to the large page it + * occupies having to be broken up so the DART itself is not + * part of the cacheable linar mapping + */ + alloc_u3_dart_table(); + + return 1; +} + +struct machdep_calls __initdata pmac_md = { + .probe = pmac_probe, + .setup_arch = pmac_setup_arch, + .init_early = pmac_init_early, + .get_cpuinfo = pmac_show_cpuinfo, + .init_IRQ = pmac_init_IRQ, + .get_irq = mpic_get_irq, + .pcibios_fixup = pmac_pcibios_fixup, + .restart = pmac_restart, + .power_off = pmac_power_off, + .halt = pmac_halt, + .get_boot_time = pmac_get_boot_time, + .set_rtc_time = pmac_set_rtc_time, + .get_rtc_time = pmac_get_rtc_time, + .calibrate_decr = pmac_calibrate_decr, + .feature_call = pmac_do_feature_call, + .progress = pmac_progress, + .check_legacy_ioport = pmac_check_legacy_ioport +}; diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c index a67e2a595..4008b4410 100644 --- a/arch/ppc64/kernel/pmac_smp.c +++ b/arch/ppc64/kernel/pmac_smp.c @@ -21,6 +21,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#undef DEBUG + #include #include #include @@ -28,17 +31,16 @@ #include #include #include -#include #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -48,42 +50,180 @@ #include #include #include +#include + +#include "mpic.h" -#include "open_pic.h" +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif extern void pmac_secondary_start_1(void); extern void pmac_secondary_start_2(void); extern void pmac_secondary_start_3(void); -extern void smp_openpic_message_pass(int target, int msg); - extern struct smp_ops_t *smp_ops; +static void (*pmac_tb_freeze)(int freeze); +static struct device_node *pmac_tb_clock_chip_host; +static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; +static unsigned long timebase; + +static void smp_core99_cypress_tb_freeze(int freeze) +{ + u8 data; + int rc; + + /* Strangely, the device-tree says address is 0xd2, but darwin + * accesses 0xd0 ... + */ + pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); + rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, + 0xd0 | pmac_low_i2c_read, + 0x81, &data, 1); + if (rc != 0) + goto bail; + + data = (data & 0xf3) | (freeze ? 0x00 : 0x0c); + + pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); + rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, + 0xd0 | pmac_low_i2c_write, + 0x81, &data, 1); + + bail: + if (rc != 0) { + printk("Cypress Timebase %s rc: %d\n", + freeze ? "freeze" : "unfreeze", rc); + panic("Timebase freeze failed !\n"); + } +} + +static void smp_core99_pulsar_tb_freeze(int freeze) +{ + u8 data; + int rc; + + /* Strangely, the device-tree says address is 0xd2, but darwin + * accesses 0xd0 ... + */ + pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); + rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, + 0xd4 | pmac_low_i2c_read, + 0x2e, &data, 1); + if (rc != 0) + goto bail; + + data = (data & 0x88) | (freeze ? 0x11 : 0x22); + + pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); + rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, + 0xd4 | pmac_low_i2c_write, + 0x2e, &data, 1); + bail: + if (rc != 0) { + printk(KERN_ERR "Pulsar Timebase %s rc: %d\n", + freeze ? "freeze" : "unfreeze", rc); + panic("Timebase freeze failed !\n"); + } +} + + +static void smp_core99_give_timebase(void) +{ + /* Open i2c bus for synchronous access */ + if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0)) + panic("Can't open i2c for TB sync !\n"); + + spin_lock(&timebase_lock); + (*pmac_tb_freeze)(1); + mb(); + timebase = get_tb(); + spin_unlock(&timebase_lock); + + while (timebase) + barrier(); + + spin_lock(&timebase_lock); + (*pmac_tb_freeze)(0); + spin_unlock(&timebase_lock); + + /* Close i2c bus */ + pmac_low_i2c_close(pmac_tb_clock_chip_host); +} + + +static void __devinit smp_core99_take_timebase(void) +{ + while (!timebase) + barrier(); + spin_lock(&timebase_lock); + set_tb(timebase >> 32, timebase & 0xffffffff); + timebase = 0; + spin_unlock(&timebase_lock); +} + + static int __init smp_core99_probe(void) { - struct device_node *cpus; - int ncpus = 1; + struct device_node *cpus; + struct device_node *cc; + int ncpus = 0; /* Maybe use systemconfiguration here ? */ if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); - cpus = find_type_devices("cpu"); - if (cpus == NULL) - return 0; - while ((cpus = cpus->next) != NULL) + /* Count CPUs in the device-tree */ + for (cpus = NULL; (cpus = of_find_node_by_type(cpus, "cpu")) != NULL;) ++ncpus; printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus); - if (ncpus > 1) - openpic_request_IPIs(); + /* Nothing more to do if less than 2 of them */ + if (ncpus <= 1) + return 1; + + /* Look for the clock chip */ + for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) { + struct device_node *p = of_get_parent(cc); + u32 *reg; + int ok; + ok = p && device_is_compatible(p, "uni-n-i2c"); + if (!ok) + goto next; + reg = (u32 *)get_property(cc, "reg", NULL); + if (reg == NULL) + goto next; + switch (*reg) { + case 0xd2: + pmac_tb_freeze = smp_core99_cypress_tb_freeze; + printk(KERN_INFO "Timebase clock is Cypress chip\n"); + break; + case 0xd4: + pmac_tb_freeze = smp_core99_pulsar_tb_freeze; + printk(KERN_INFO "Timebase clock is Pulsar chip\n"); + break; + } + if (pmac_tb_freeze != NULL) { + pmac_tb_clock_chip_host = p; + smp_ops->give_timebase = smp_core99_give_timebase; + smp_ops->take_timebase = smp_core99_take_timebase; + break; + } + next: + of_node_put(p); + } + + mpic_request_ipis(); return ncpus; } static void __init smp_core99_kick_cpu(int nr) { - int save_vector; + int save_vector, j; unsigned long new_vector; unsigned long flags; volatile unsigned int *vector @@ -103,15 +243,16 @@ static void __init smp_core99_kick_cpu(int nr) * b .pmac_secondary_start - KERNELBASE */ switch(nr) { - case 1: - new_vector = (unsigned long)pmac_secondary_start_1; - break; - case 2: - new_vector = (unsigned long)pmac_secondary_start_2; - break; - case 3: - new_vector = (unsigned long)pmac_secondary_start_3; - break; + case 1: + new_vector = (unsigned long)pmac_secondary_start_1; + break; + case 2: + new_vector = (unsigned long)pmac_secondary_start_2; + break; + case 3: + default: + new_vector = (unsigned long)pmac_secondary_start_3; + break; } *vector = 0x48000002 + (new_vector - KERNELBASE); @@ -127,7 +268,8 @@ static void __init smp_core99_kick_cpu(int nr) * ideally, all that crap will be done in prom.c and the CPU left * in a RAM-based wait loop like CHRP. */ - mdelay(1); + for (j = 1; j < 1000000; j++) + mb(); /* Restore our exception vector */ *vector = save_vector; @@ -139,8 +281,8 @@ static void __init smp_core99_kick_cpu(int nr) static void __init smp_core99_setup_cpu(int cpu_nr) { - /* Setup openpic */ - do_openpic_setup_cpu(); + /* Setup MPIC */ + mpic_setup_this_cpu(); if (cpu_nr == 0) { extern void g5_phy_disable_cpu1(void); @@ -150,15 +292,12 @@ static void __init smp_core99_setup_cpu(int cpu_nr) */ if (num_online_cpus() < 2) g5_phy_disable_cpu1(); - if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); + if (ppc_md.progress) ppc_md.progress("smp_core99_setup_cpu 0 done", 0x349); } } -extern void smp_generic_give_timebase(void); -extern void smp_generic_take_timebase(void); - struct smp_ops_t core99_smp_ops __pmacdata = { - .message_pass = smp_openpic_message_pass, + .message_pass = smp_mpic_message_pass, .probe = smp_core99_probe, .kick_cpu = smp_core99_kick_cpu, .setup_cpu = smp_core99_setup_cpu, diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c index aea28b989..06f379855 100644 --- a/arch/ppc64/kernel/pmac_time.c +++ b/arch/ppc64/kernel/pmac_time.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c index 836cf2a43..cf543e042 100644 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ b/arch/ppc64/kernel/ppc_ksyms.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -119,7 +119,6 @@ EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(flush_instruction_cache); -EXPORT_SYMBOL(_get_PVR); EXPORT_SYMBOL(giveup_fpu); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(giveup_altivec); @@ -137,7 +136,7 @@ EXPORT_SYMBOL(local_irq_restore); EXPORT_SYMBOL(ppc_md); -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); EXPORT_SYMBOL(find_compatible_devices); @@ -148,12 +147,12 @@ EXPORT_SYMBOL(find_all_nodes); EXPORT_SYMBOL(get_property); #endif -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memchr); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c index ed172cd78..07bf32122 100644 --- a/arch/ppc64/kernel/proc_ppc64.c +++ b/arch/ppc64/kernel/proc_ppc64.c @@ -33,7 +33,8 @@ #include static loff_t page_map_seek( struct file *file, loff_t off, int whence); -static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos); +static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, + loff_t *ppos); static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); static struct file_operations page_map_fops = { @@ -161,7 +162,8 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence) return (file->f_pos = new); } -static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) +static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, + loff_t *ppos) { struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size); @@ -176,7 +178,8 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) if ((vma->vm_end - vma->vm_start) > dp->size) return -EINVAL; - remap_page_range( vma, vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot ); + remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT, + dp->size, vma->vm_page_prot); return 0; } @@ -207,7 +210,8 @@ static void proc_ppc64_create_ofdt(void) * whole nodes along with their properties. Operations on individual * properties are not implemented (yet). */ -static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, loff_t *off) +static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, + loff_t *off) { int rv = 0; char *kbuf; @@ -301,7 +305,8 @@ out: return rv; } -static struct property *new_property(const char *name, const int length, const unsigned char *value, struct property *last) +static struct property *new_property(const char *name, const int length, + const unsigned char *value, struct property *last) { struct property *new = kmalloc(sizeof(*new), GFP_KERNEL); @@ -342,7 +347,8 @@ cleanup: * this function does no allocation or copying of the data. Return value * is set to the next name in buf, or NULL on error. */ -static char * parse_next_property(char *buf, char *end, char **name, int *length, unsigned char **value) +static char * parse_next_property(char *buf, char *end, char **name, int *length, + unsigned char **value) { char *tmp; @@ -350,13 +356,15 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length tmp = strchr(buf, ' '); if (!tmp) { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } *tmp = '\0'; if (++tmp >= end) { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } @@ -364,11 +372,13 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length *length = -1; *length = simple_strtoul(tmp, &tmp, 10); if (*length == -1) { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } if (*tmp != ' ' || ++tmp >= end) { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } @@ -376,11 +386,13 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length *value = tmp; tmp += *length; if (tmp > end) { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } else if (tmp < end && *tmp != ' ' && *tmp != '\0') { - printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "property parse failed in %s at line %d\n", + __FUNCTION__, __LINE__); return NULL; } tmp++; diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 5acc56729..e647e7bc9 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -147,7 +147,6 @@ EXPORT_SYMBOL(enable_kernel_altivec); */ void flush_altivec_to_thread(struct task_struct *tsk) { -#ifdef CONFIG_ALTIVEC if (tsk->thread.regs) { preempt_disable(); if (tsk->thread.regs->msr & MSR_VEC) { @@ -158,7 +157,6 @@ void flush_altivec_to_thread(struct task_struct *tsk) } preempt_enable(); } -#endif } int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) @@ -317,8 +315,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, extern void ret_from_fork(void); unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; - p->set_child_tid = p->clear_child_tid = NULL; - /* Copy registers */ sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; @@ -356,6 +352,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, kregs = (struct pt_regs *) sp; sp -= STACK_FRAME_OVERHEAD; p->thread.ksp = sp; + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { + unsigned long sp_vsid = get_kernel_vsid(sp); + + sp_vsid <<= SLB_VSID_SHIFT; + sp_vsid |= SLB_VSID_KERNEL; + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + sp_vsid |= SLB_VSID_L; + + p->thread.ksp_vsid = sp_vsid; + } /* * The PPC64 ABI makes use of a TOC to contain function @@ -387,11 +393,22 @@ void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp) /* Check whether the e_entry function descriptor entries * need to be relocated before we can use them. */ - if ( load_addr != 0 ) { + if (load_addr != 0) { entry += load_addr; toc += load_addr; } + /* + * If we exec out of a kernel thread then thread.regs will not be + * set. Do it now. + */ + if (!current->thread.regs) { + unsigned long childregs = (unsigned long)current->thread_info + + THREAD_SIZE; + childregs -= sizeof(struct pt_regs); + current->thread.regs = (struct pt_regs *)childregs; + } + regs->nip = entry; regs->gpr[1] = sp; regs->gpr[2] = toc; @@ -458,7 +475,7 @@ int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3, } } - return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, + return do_fork(clone_flags, p2, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -493,8 +510,11 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, error = do_execve(filename, (char __user * __user *) a1, (char __user * __user *) a2, regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index bdf5e3a47..eebec2619 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -15,7 +15,7 @@ * 2 of the License, or (at your option) any later version. */ -#undef DEBUG_PROM +#undef DEBUG #include #include @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -52,1808 +52,59 @@ #include #include #include -#include "open_pic.h" -#ifdef CONFIG_LOGO_LINUX_CLUT224 -#include -extern const struct linux_logo logo_linux_clut224; -#endif - -/* - * Properties whose value is longer than this get excluded from our - * copy of the device tree. This value does need to be big enough to - * ensure that we don't lose things like the interrupt-map property - * on a PCI-PCI bridge. - */ -#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024) - -/* - * prom_init() is called very early on, before the kernel text - * and data have been mapped to KERNELBASE. At this point the code - * is running at whatever address it has been loaded at, so - * references to extern and static variables must be relocated - * explicitly. The procedure reloc_offset() returns the address - * we're currently running at minus the address we were linked at. - * (Note that strings count as static variables.) - * - * Because OF may have mapped I/O devices into the area starting at - * KERNELBASE, particularly on CHRP machines, we can't safely call - * OF once the kernel has been mapped to KERNELBASE. Therefore all - * OF calls should be done within prom_init(), and prom_init() - * and all routines called within it must be careful to relocate - * references as necessary. - * - * Note that the bss is cleared *after* prom_init runs, so we have - * to make sure that any static or extern variables it accesses - * are put in the data segment. - */ - - -#define PROM_BUG() do { \ - prom_printf("kernel BUG at %s line 0x%x!\n", \ - RELOC(__FILE__), __LINE__); \ - __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ -} while (0) - -#ifdef DEBUG_PROM -#define prom_debug(x...) prom_printf(x) -#else -#define prom_debug(x...) -#endif - - -struct pci_reg_property { - struct pci_address addr; - u32 size_hi; - u32 size_lo; -}; - - -struct isa_reg_property { - u32 space; - u32 address; - u32 size; -}; - -struct pci_intr_map { - struct pci_address addr; - u32 dunno; - phandle int_ctrler; - u32 intr; -}; - - -typedef unsigned long interpret_func(struct device_node *, unsigned long, - int, int, int); - -#ifndef FB_MAX /* avoid pulling in all of the fb stuff */ -#define FB_MAX 8 -#endif - -/* prom structure */ -struct prom_t prom; - -char *prom_display_paths[FB_MAX] __initdata = { NULL, }; -phandle prom_display_nodes[FB_MAX] __initdata; -unsigned int prom_num_displays = 0; -char *of_stdout_device = NULL; - -static int iommu_force_on; -int ppc64_iommu_off; - -extern struct rtas_t rtas; -extern unsigned long klimit; -extern struct lmb lmb; - -#define MAX_PHB (32 * 6) /* 32 drawers * 6 PHBs/drawer */ -struct of_tce_table of_tce_table[MAX_PHB + 1]; - -char *bootpath = NULL; -char *bootdevice = NULL; - -int boot_cpuid = 0; -#define MAX_CPU_THREADS 2 - -struct device_node *allnodes = NULL; -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static rwlock_t devtree_lock = RW_LOCK_UNLOCKED; - -extern unsigned long reloc_offset(void); - -extern void enter_prom(struct prom_args *args); -extern void copy_and_flush(unsigned long dest, unsigned long src, - unsigned long size, unsigned long offset); - -unsigned long dev_tree_size; -unsigned long _get_PIR(void); - -#ifdef CONFIG_HMT -struct { - unsigned int pir; - unsigned int threadid; -} hmt_thread_data[NR_CPUS]; -#endif /* CONFIG_HMT */ - -char testString[] = "LINUX\n"; - -/* - * This are used in calls to call_prom. The 4th and following - * arguments to call_prom should be 32-bit values. 64 bit values - * are truncated to 32 bits (and fortunately don't get interpreted - * as two arguments). - */ -#define ADDR(x) (u32) ((unsigned long)(x) - offset) - -/* This is the one and *ONLY* place where we actually call open - * firmware from, since we need to make sure we're running in 32b - * mode when we do. We switch back to 64b mode upon return. - */ - -#define PROM_ERROR (-1) - -static int __init call_prom(const char *service, int nargs, int nret, ...) -{ - int i; - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - va_list list; - - _prom->args.service = ADDR(service); - _prom->args.nargs = nargs; - _prom->args.nret = nret; - _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]); - - va_start(list, nret); - for (i=0; i < nargs; i++) - _prom->args.args[i] = va_arg(list, prom_arg_t); - va_end(list); - - for (i=0; i < nret ;i++) - _prom->args.rets[i] = 0; - - enter_prom(&_prom->args); - - return (nret > 0)? _prom->args.rets[0]: 0; -} - - -static void __init prom_print(const char *msg) -{ - const char *p, *q; - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - - if (_prom->stdout == 0) - return; - - for (p = msg; *p != 0; p = q) { - for (q = p; *q != 0 && *q != '\n'; ++q) - ; - if (q > p) - call_prom("write", 3, 1, _prom->stdout, p, q - p); - if (*q == 0) - break; - ++q; - call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2); - } -} - - -static void __init prom_print_hex(unsigned long val) -{ - unsigned long offset = reloc_offset(); - int i, nibbles = sizeof(val)*2; - char buf[sizeof(val)*2+1]; - struct prom_t *_prom = PTRRELOC(&prom); - - for (i = nibbles-1; i >= 0; i--) { - buf[i] = (val & 0xf) + '0'; - if (buf[i] > '9') - buf[i] += ('a'-'0'-10); - val >>= 4; - } - buf[nibbles] = '\0'; - call_prom("write", 3, 1, _prom->stdout, buf, nibbles); -} - - -static void __init prom_printf(const char *format, ...) -{ - unsigned long offset = reloc_offset(); - const char *p, *q, *s; - va_list args; - unsigned long v; - struct prom_t *_prom = PTRRELOC(&prom); - - va_start(args, format); - for (p = PTRRELOC(format); *p != 0; p = q) { - for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) - ; - if (q > p) - call_prom("write", 3, 1, _prom->stdout, p, q - p); - if (*q == 0) - break; - if (*q == '\n') { - ++q; - call_prom("write", 3, 1, _prom->stdout, - ADDR("\r\n"), 2); - continue; - } - ++q; - if (*q == 0) - break; - switch (*q) { - case 's': - ++q; - s = va_arg(args, const char *); - prom_print(s); - break; - case 'x': - ++q; - v = va_arg(args, unsigned long); - prom_print_hex(v); - break; - } - } -} - - -static void __init __attribute__((noreturn)) prom_panic(const char *reason) -{ - unsigned long offset = reloc_offset(); - - prom_print(PTRRELOC(reason)); - /* ToDo: should put up an SRC here */ - call_prom("exit", 0, 0); - - for (;;) /* should never get here */ - ; -} - - -static int __init prom_next_node(phandle *nodep) -{ - phandle node; - - if ((node = *nodep) != 0 - && (*nodep = call_prom("child", 1, 1, node)) != 0) - return 1; - if ((*nodep = call_prom("peer", 1, 1, node)) != 0) - return 1; - for (;;) { - if ((node = call_prom("parent", 1, 1, node)) == 0) - return 0; - if ((*nodep = call_prom("peer", 1, 1, node)) != 0) - return 1; - } -} - -static int __init prom_getprop(phandle node, const char *pname, - void *value, size_t valuelen) -{ - unsigned long offset = reloc_offset(); - - return call_prom("getprop", 4, 1, node, ADDR(pname), - (u32)(unsigned long) value, (u32) valuelen); -} - -static void __init prom_initialize_naca(void) -{ - phandle node; - char type[64]; - unsigned long num_cpus = 0; - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - struct naca_struct *_naca = RELOC(naca); - struct systemcfg *_systemcfg = RELOC(systemcfg); - - /* NOTE: _naca->debug_switch is already initialized. */ - prom_debug("prom_initialize_naca: start...\n"); - - _naca->pftSize = 0; /* ilog2 of htab size. computed below. */ - - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "device_type", type, sizeof(type)); - - if (!strcmp(type, RELOC("cpu"))) { - num_cpus += 1; - - /* We're assuming *all* of the CPUs have the same - * d-cache and i-cache sizes... -Peter - */ - if ( num_cpus == 1 ) { - u32 size, lsize; - const char *dc, *ic; - - if (_systemcfg->platform == PLATFORM_POWERMAC){ - dc = "d-cache-block-size"; - ic = "i-cache-block-size"; - } else { - dc = "d-cache-line-size"; - ic = "i-cache-line-size"; - } - - prom_getprop(node, "d-cache-size", - &size, sizeof(size)); - - prom_getprop(node, dc, &lsize, sizeof(lsize)); - - _systemcfg->dCacheL1Size = size; - _systemcfg->dCacheL1LineSize = lsize; - _naca->dCacheL1LogLineSize = __ilog2(lsize); - _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize; - - prom_getprop(node, "i-cache-size", - &size, sizeof(size)); - - prom_getprop(node, ic, &lsize, sizeof(lsize)); - - _systemcfg->iCacheL1Size = size; - _systemcfg->iCacheL1LineSize = lsize; - _naca->iCacheL1LogLineSize = __ilog2(lsize); - _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize; - - if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) { - u32 pft_size[2]; - prom_getprop(node, "ibm,pft-size", - &pft_size, sizeof(pft_size)); - /* pft_size[0] is the NUMA CEC cookie */ - _naca->pftSize = pft_size[1]; - } - } - } else if (!strcmp(type, RELOC("serial"))) { - phandle isa, pci; - struct isa_reg_property reg; - union pci_range ranges; - - if (_systemcfg->platform == PLATFORM_POWERMAC) - continue; - type[0] = 0; - prom_getprop(node, "ibm,aix-loc", type, sizeof(type)); - - if (strcmp(type, RELOC("S1"))) - continue; - - prom_getprop(node, "reg", ®, sizeof(reg)); - - isa = call_prom("parent", 1, 1, node); - if (!isa) - PROM_BUG(); - pci = call_prom("parent", 1, 1, isa); - if (!pci) - PROM_BUG(); - - prom_getprop(pci, "ranges", &ranges, sizeof(ranges)); - - if ( _prom->encode_phys_size == 32 ) - _naca->serialPortAddr = ranges.pci32.phys+reg.address; - else { - _naca->serialPortAddr = - ((((unsigned long)ranges.pci64.phys_hi) << 32) | - (ranges.pci64.phys_lo)) + reg.address; - } - } - } - - if (_systemcfg->platform == PLATFORM_POWERMAC) - _naca->interrupt_controller = IC_OPEN_PIC; - else { - _naca->interrupt_controller = IC_INVALID; - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "name", type, sizeof(type)); - if (strcmp(type, RELOC("interrupt-controller"))) - continue; - prom_getprop(node, "compatible", type, sizeof(type)); - if (strstr(type, RELOC("open-pic"))) - _naca->interrupt_controller = IC_OPEN_PIC; - else if (strstr(type, RELOC("ppc-xicp"))) - _naca->interrupt_controller = IC_PPC_XIC; - else - prom_printf("prom: failed to recognize" - " interrupt-controller\n"); - break; - } - } - - if (_naca->interrupt_controller == IC_INVALID) { - prom_printf("prom: failed to find interrupt-controller\n"); - PROM_BUG(); - } - - /* We gotta have at least 1 cpu... */ - if ( (_systemcfg->processorCount = num_cpus) < 1 ) - PROM_BUG(); - - _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - - if (_systemcfg->platform == PLATFORM_PSERIES || - _systemcfg->platform == PLATFORM_POWERMAC) { - unsigned long rnd_mem_size, pteg_count; - - /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize); - if (rnd_mem_size < _systemcfg->physicalMemorySize) - rnd_mem_size <<= 1; - - /* # pages / 2 */ - pteg_count = (rnd_mem_size >> (12 + 1)); - - _naca->pftSize = __ilog2(pteg_count << 7); - } - - if (_naca->pftSize == 0) { - prom_printf("prom: failed to compute pftSize!\n"); - PROM_BUG(); - } - - /* Add an eye catcher and the systemcfg layout version number */ - strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64")); - _systemcfg->version.major = SYSTEMCFG_MAJOR; - _systemcfg->version.minor = SYSTEMCFG_MINOR; - _systemcfg->processor = _get_PVR(); - - prom_debug("systemcfg->processorCount = 0x%x\n", - _systemcfg->processorCount); - prom_debug("systemcfg->physicalMemorySize = 0x%x\n", - _systemcfg->physicalMemorySize); - prom_debug("naca->pftSize = 0x%x\n", - _naca->pftSize); - prom_debug("systemcfg->dCacheL1LineSize = 0x%x\n", - _systemcfg->dCacheL1LineSize); - prom_debug("systemcfg->iCacheL1LineSize = 0x%x\n", - _systemcfg->iCacheL1LineSize); - prom_debug("naca->serialPortAddr = 0x%x\n", - _naca->serialPortAddr); - prom_debug("naca->interrupt_controller = 0x%x\n", - _naca->interrupt_controller); - prom_debug("systemcfg->platform = 0x%x\n", - _systemcfg->platform); - prom_debug("prom_initialize_naca: end...\n"); -} - - -static void __init early_cmdline_parse(void) -{ - unsigned long offset = reloc_offset(); - char *opt; -#ifndef CONFIG_PMAC_DART - struct systemcfg *_systemcfg = RELOC(systemcfg); -#endif - - opt = strstr(RELOC(cmd_line), RELOC("iommu=")); - if (opt) { - prom_printf("opt is:%s\n", opt); - opt += 6; - while (*opt && *opt == ' ') - opt++; - if (!strncmp(opt, RELOC("off"), 3)) - RELOC(ppc64_iommu_off) = 1; - else if (!strncmp(opt, RELOC("force"), 5)) - RELOC(iommu_force_on) = 1; - } - -#ifndef CONFIG_PMAC_DART - if (_systemcfg->platform == PLATFORM_POWERMAC) { - RELOC(ppc64_iommu_off) = 1; - prom_printf("DART disabled on PowerMac !\n"); - } -#endif -} - -#ifdef DEBUG_PROM -void prom_dump_lmb(void) -{ - unsigned long i; - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); - - prom_printf("\nprom_dump_lmb:\n"); - prom_printf(" memory.cnt = 0x%x\n", - _lmb->memory.cnt); - prom_printf(" memory.size = 0x%x\n", - _lmb->memory.size); - for (i=0; i < _lmb->memory.cnt ;i++) { - prom_printf(" memory.region[0x%x].base = 0x%x\n", - i, _lmb->memory.region[i].base); - prom_printf(" .physbase = 0x%x\n", - _lmb->memory.region[i].physbase); - prom_printf(" .size = 0x%x\n", - _lmb->memory.region[i].size); - } - - prom_printf("\n reserved.cnt = 0x%x\n", - _lmb->reserved.cnt); - prom_printf(" reserved.size = 0x%x\n", - _lmb->reserved.size); - for (i=0; i < _lmb->reserved.cnt ;i++) { - prom_printf(" reserved.region[0x%x\n].base = 0x%x\n", - i, _lmb->reserved.region[i].base); - prom_printf(" .physbase = 0x%x\n", - _lmb->reserved.region[i].physbase); - prom_printf(" .size = 0x%x\n", - _lmb->reserved.region[i].size); - } -} -#endif /* DEBUG_PROM */ - -static void __init prom_initialize_lmb(void) -{ - phandle node; - char type[64]; - unsigned long i, offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - struct systemcfg *_systemcfg = RELOC(systemcfg); - union lmb_reg_property reg; - unsigned long lmb_base, lmb_size; - unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; - - lmb_init(); - - /* XXX Quick HACK. Proper fix is to drop those structures and properly use - * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2 - */ - if (_systemcfg->platform == PLATFORM_POWERMAC) - bytes_per_reg = 12; - - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "device_type", type, sizeof(type)); - - if (strcmp(type, RELOC("memory"))) - continue; - - num_regs = prom_getprop(node, "reg", ®, sizeof(reg)) - / bytes_per_reg; - - for (i=0; i < num_regs ;i++) { - if (_systemcfg->platform == PLATFORM_POWERMAC) { - lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32; - lmb_base |= (unsigned long)reg.addrPM[i].address_lo; - lmb_size = reg.addrPM[i].size; - } else if (_prom->encode_phys_size == 32) { - lmb_base = reg.addr32[i].address; - lmb_size = reg.addr32[i].size; - } else { - lmb_base = reg.addr64[i].address; - lmb_size = reg.addr64[i].size; - } - - /* We limit memory to 2GB if the IOMMU is off */ - if (RELOC(ppc64_iommu_off)) { - if (lmb_base >= 0x80000000UL) - continue; - - if ((lmb_base + lmb_size) > 0x80000000UL) - lmb_size = 0x80000000UL - lmb_base; - } - - if (lmb_add(lmb_base, lmb_size) < 0) - prom_printf("Too many LMB's, discarding this one...\n"); - } - - } - - lmb_analyze(); -#ifdef DEBUG_PROM - prom_dump_lmb(); -#endif /* DEBUG_PROM */ -} - -static void __init -prom_instantiate_rtas(void) -{ - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - struct rtas_t *_rtas = PTRRELOC(&rtas); - struct systemcfg *_systemcfg = RELOC(systemcfg); - ihandle prom_rtas; - u32 getprop_rval; - char hypertas_funcs[4]; - - prom_debug("prom_instantiate_rtas: start...\n"); - - prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); - if (prom_rtas != (ihandle) -1) { - unsigned long x; - x = prom_getprop(prom_rtas, "ibm,hypertas-functions", - hypertas_funcs, sizeof(hypertas_funcs)); - - if (x != PROM_ERROR) { - prom_printf("Hypertas detected, assuming LPAR !\n"); - _systemcfg->platform = PLATFORM_PSERIES_LPAR; - } - - prom_getprop(prom_rtas, "rtas-size", - &getprop_rval, sizeof(getprop_rval)); - _rtas->size = getprop_rval; - prom_printf("instantiating rtas"); - if (_rtas->size != 0) { - unsigned long rtas_region = RTAS_INSTANTIATE_MAX; - - /* Grab some space within the first RTAS_INSTANTIATE_MAX bytes - * of physical memory (or within the RMO region) because RTAS - * runs in 32-bit mode and relocate off. - */ - if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) { - struct lmb *_lmb = PTRRELOC(&lmb); - rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX); - } - - _rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region); - - prom_printf(" at 0x%x", _rtas->base); - - prom_rtas = call_prom("open", 1, 1, ADDR("/rtas")); - prom_printf("..."); - - if (call_prom("call-method", 3, 2, - ADDR("instantiate-rtas"), - prom_rtas, - _rtas->base) != PROM_ERROR) { - _rtas->entry = (long)_prom->args.rets[1]; - } - RELOC(rtas_rmo_buf) - = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, - rtas_region); - } - - if (_rtas->entry <= 0) { - prom_printf(" failed\n"); - } else { - prom_printf(" done\n"); - } - - prom_debug("rtas->base = 0x%x\n", _rtas->base); - prom_debug("rtas->entry = 0x%x\n", _rtas->entry); - prom_debug("rtas->size = 0x%x\n", _rtas->size); - } - prom_debug("prom_instantiate_rtas: end...\n"); -} - - -#ifdef CONFIG_PMAC_DART -static void __init prom_initialize_dart_table(void) -{ - unsigned long offset = reloc_offset(); - extern unsigned long dart_tablebase; - extern unsigned long dart_tablesize; - - /* Only reserve DART space if machine has more than 2GB of RAM - * or if requested with iommu=on on cmdline. - */ - if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on)) - return; - - /* 512 pages (2MB) is max DART tablesize. */ - RELOC(dart_tablesize) = 1UL << 21; - /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we - * will blow up an entire large page anyway in the kernel mapping - */ - RELOC(dart_tablebase) = (unsigned long) - abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L)); - - prom_printf("Dart at: %x\n", RELOC(dart_tablebase)); -} -#endif /* CONFIG_PMAC_DART */ - -static void __init prom_initialize_tce_table(void) -{ - phandle node; - ihandle phb_node; - unsigned long offset = reloc_offset(); - char compatible[64], path[64], type[64], model[64]; - unsigned long i, table = 0; - unsigned long base, vbase, align; - unsigned int minalign, minsize; - struct of_tce_table *prom_tce_table = RELOC(of_tce_table); - unsigned long tce_entry, *tce_entryp; - - if (RELOC(ppc64_iommu_off)) - return; - - prom_debug("starting prom_initialize_tce_table\n"); - - /* Search all nodes looking for PHBs. */ - for (node = 0; prom_next_node(&node); ) { - if (table == MAX_PHB) { - prom_printf("WARNING: PCI host bridge ignored, " - "need to increase MAX_PHB\n"); - continue; - } - - compatible[0] = 0; - type[0] = 0; - model[0] = 0; - prom_getprop(node, "compatible", - compatible, sizeof(compatible)); - prom_getprop(node, "device_type", type, sizeof(type)); - prom_getprop(node, "model", model, sizeof(model)); - - /* Keep the old logic in tack to avoid regression. */ - if (compatible[0] != 0) { - if ((strstr(compatible, RELOC("python")) == NULL) && - (strstr(compatible, RELOC("Speedwagon")) == NULL) && - (strstr(compatible, RELOC("Winnipeg")) == NULL)) - continue; - } else if (model[0] != 0) { - if ((strstr(model, RELOC("ython")) == NULL) && - (strstr(model, RELOC("peedwagon")) == NULL) && - (strstr(model, RELOC("innipeg")) == NULL)) - continue; - } - - if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) { - continue; - } - - if (prom_getprop(node, "tce-table-minalign", &minalign, - sizeof(minalign)) == PROM_ERROR) { - minalign = 0; - } - - if (prom_getprop(node, "tce-table-minsize", &minsize, - sizeof(minsize)) == PROM_ERROR) { - minsize = 4UL << 20; - } - - /* - * Even though we read what OF wants, we just set the table - * size to 4 MB. This is enough to map 2GB of PCI DMA space. - * By doing this, we avoid the pitfalls of trying to DMA to - * MMIO space and the DMA alias hole. - * - * On POWER4, firmware sets the TCE region by assuming - * each TCE table is 8MB. Using this memory for anything - * else will impact performance, so we always allocate 8MB. - * Anton - */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) - minsize = 8UL << 20; - else - minsize = 4UL << 20; - - /* Align to the greater of the align or size */ - align = max(minalign, minsize); - - /* Carve out storage for the TCE table. */ - base = lmb_alloc(minsize, align); - - if ( !base ) { - prom_panic("ERROR, cannot find space for TCE table.\n"); - } - - vbase = (unsigned long)abs_to_virt(base); - - /* Save away the TCE table attributes for later use. */ - prom_tce_table[table].node = node; - prom_tce_table[table].base = vbase; - prom_tce_table[table].size = minsize; - - prom_debug("TCE table: 0x%x\n", table); - prom_debug("\tnode = 0x%x\n", node); - prom_debug("\tbase = 0x%x\n", vbase); - prom_debug("\tsize = 0x%x\n", minsize); - - /* Initialize the table to have a one-to-one mapping - * over the allocated size. - */ - tce_entryp = (unsigned long *)base; - for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { - tce_entry = (i << PAGE_SHIFT); - tce_entry |= 0x3; - *tce_entryp = tce_entry; - } - - /* It seems OF doesn't null-terminate the path :-( */ - memset(path, 0, sizeof(path)); - /* Call OF to setup the TCE hardware */ - if (call_prom("package-to-path", 3, 1, node, - path, sizeof(path)-1) == PROM_ERROR) { - prom_printf("package-to-path failed\n"); - } else { - prom_printf("opening PHB %s", path); - } - - phb_node = call_prom("open", 1, 1, path); - if ( (long)phb_node <= 0) { - prom_printf("... failed\n"); - } else { - prom_printf("... done\n"); - } - call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"), - phb_node, -1, minsize, - (u32) base, (u32) (base >> 32)); - call_prom("close", 1, 0, phb_node); - - table++; - } - - /* Flag the first invalid entry */ - prom_tce_table[table].node = 0; - prom_debug("ending prom_initialize_tce_table\n"); -} - -/* - * With CHRP SMP we need to use the OF to start the other - * processors so we can't wait until smp_boot_cpus (the OF is - * trashed by then) so we have to put the processors into - * a holding pattern controlled by the kernel (not OF) before - * we destroy the OF. - * - * This uses a chunk of low memory, puts some holding pattern - * code there and sends the other processors off to there until - * smp_boot_cpus tells them to do something. The holding pattern - * checks that address until its cpu # is there, when it is that - * cpu jumps to __secondary_start(). smp_boot_cpus() takes care - * of setting those values. - * - * We also use physical address 0x4 here to tell when a cpu - * is in its holding pattern code. - * - * Fixup comment... DRENG / PPPBBB - Peter - * - * -- Cort - */ -static void __init prom_hold_cpus(unsigned long mem) -{ - unsigned long i; - unsigned int reg; - phandle node; - unsigned long offset = reloc_offset(); - char type[64], *path; - int cpuid = 0; - unsigned int interrupt_server[MAX_CPU_THREADS]; - unsigned int cpu_threads, hw_cpu_num; - int propsize; - extern void __secondary_hold(void); - extern unsigned long __secondary_hold_spinloop; - extern unsigned long __secondary_hold_acknowledge; - unsigned long *spinloop - = (void *)virt_to_abs(&__secondary_hold_spinloop); - unsigned long *acknowledge - = (void *)virt_to_abs(&__secondary_hold_acknowledge); - unsigned long secondary_hold - = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold)); - struct systemcfg *_systemcfg = RELOC(systemcfg); - struct paca_struct *lpaca = PTRRELOC(&paca[0]); - struct prom_t *_prom = PTRRELOC(&prom); -#ifdef CONFIG_SMP - struct naca_struct *_naca = RELOC(naca); -#endif - - /* On pmac, we just fill out the various global bitmasks and - * arrays indicating our CPUs are here, they are actually started - * later on from pmac_smp - */ - if (_systemcfg->platform == PLATFORM_POWERMAC) { - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "device_type", type, sizeof(type)); - if (strcmp(type, RELOC("cpu")) != 0) - continue; - reg = -1; - prom_getprop(node, "reg", ®, sizeof(reg)); - lpaca[cpuid].hw_cpu_id = reg; - -#ifdef CONFIG_SMP - cpu_set(cpuid, RELOC(cpu_available_map)); - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_present_at_boot)); - if (reg == 0) - cpu_set(cpuid, RELOC(cpu_online_map)); -#endif /* CONFIG_SMP */ - cpuid++; - } - return; - } - - /* Initially, we must have one active CPU. */ - _systemcfg->processorCount = 1; - - prom_debug("prom_hold_cpus: start...\n"); - prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); - prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); - prom_debug(" 1) acknowledge = 0x%x\n", - (unsigned long)acknowledge); - prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge); - prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold); - - /* Set the common spinloop variable, so all of the secondary cpus - * will block when they are awakened from their OF spinloop. - * This must occur for both SMP and non SMP kernels, since OF will - * be trashed when we move the kernel. - */ - *spinloop = 0; - -#ifdef CONFIG_HMT - for (i=0; i < NR_CPUS; i++) { - RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; - } -#endif - /* look for cpus */ - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "device_type", type, sizeof(type)); - if (strcmp(type, RELOC("cpu")) != 0) - continue; - - /* Skip non-configured cpus. */ - prom_getprop(node, "status", type, sizeof(type)); - if (strcmp(type, RELOC("okay")) != 0) - continue; - - reg = -1; - prom_getprop(node, "reg", ®, sizeof(reg)); - - path = (char *) mem; - memset(path, 0, 256); - if (call_prom("package-to-path", 3, 1, - node, path, 255) == PROM_ERROR) - continue; - - prom_debug("\ncpuid = 0x%x\n", cpuid); - prom_debug("cpu hw idx = 0x%x\n", reg); - lpaca[cpuid].hw_cpu_id = reg; - - /* Init the acknowledge var which will be reset by - * the secondary cpu when it awakens from its OF - * spinloop. - */ - *acknowledge = (unsigned long)-1; - - propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s", - &interrupt_server, - sizeof(interrupt_server)); - if (propsize < 0) { - /* no property. old hardware has no SMT */ - cpu_threads = 1; - interrupt_server[0] = reg; /* fake it with phys id */ - } else { - /* We have a threaded processor */ - cpu_threads = propsize / sizeof(u32); - if (cpu_threads > MAX_CPU_THREADS) { - prom_printf("SMT: too many threads!\n" - "SMT: found %x, max is %x\n", - cpu_threads, MAX_CPU_THREADS); - cpu_threads = 1; /* ToDo: panic? */ - } - } - - hw_cpu_num = interrupt_server[0]; - if (hw_cpu_num != _prom->cpu) { - /* Primary Thread of non-boot cpu */ - prom_printf("%x : starting cpu %s... ", cpuid, path); - call_prom("start-cpu", 3, 0, node, - secondary_hold, cpuid); - - for ( i = 0 ; (i < 100000000) && - (*acknowledge == ((unsigned long)-1)); i++ ) ; - - if (*acknowledge == cpuid) { - prom_printf("... done\n"); - /* We have to get every CPU out of OF, - * even if we never start it. */ - if (cpuid >= NR_CPUS) - goto next; -#ifdef CONFIG_SMP - /* Set the number of active processors. */ - _systemcfg->processorCount++; - cpu_set(cpuid, RELOC(cpu_available_map)); - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_present_at_boot)); -#endif - } else { - prom_printf("... failed: %x\n", *acknowledge); - } - } -#ifdef CONFIG_SMP - else { - prom_printf("%x : booting cpu %s\n", cpuid, path); - cpu_set(cpuid, RELOC(cpu_available_map)); - cpu_set(cpuid, RELOC(cpu_possible_map)); - cpu_set(cpuid, RELOC(cpu_online_map)); - cpu_set(cpuid, RELOC(cpu_present_at_boot)); - } -#endif -next: -#ifdef CONFIG_SMP - /* Init paca for secondary threads. They start later. */ - for (i=1; i < cpu_threads; i++) { - cpuid++; - if (cpuid >= NR_CPUS) - continue; - lpaca[cpuid].hw_cpu_id = interrupt_server[i]; - prom_printf("%x : preparing thread ... ", - interrupt_server[i]); - if (_naca->smt_state) { - cpu_set(cpuid, RELOC(cpu_available_map)); - cpu_set(cpuid, RELOC(cpu_present_at_boot)); - prom_printf("available\n"); - } else { - prom_printf("not available\n"); - } - } -#endif - cpuid++; - } -#ifdef CONFIG_HMT - /* Only enable HMT on processors that provide support. */ - if (__is_processor(PV_PULSAR) || - __is_processor(PV_ICESTAR) || - __is_processor(PV_SSTAR)) { - prom_printf(" starting secondary threads\n"); - - for (i = 0; i < NR_CPUS; i += 2) { - if (!cpu_online(i)) - continue; - - if (i == 0) { - unsigned long pir = _get_PIR(); - if (__is_processor(PV_PULSAR)) { - RELOC(hmt_thread_data)[i].pir = - pir & 0x1f; - } else { - RELOC(hmt_thread_data)[i].pir = - pir & 0x3ff; - } - } -/* cpu_set(i+1, cpu_online_map); */ - cpu_set(i+1, RELOC(cpu_possible_map)); - } - _systemcfg->processorCount *= 2; - } else { - prom_printf("Processor is not HMT capable\n"); - } -#endif - - if (cpuid > NR_CPUS) - prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) - ") exceeded: ignoring extras\n"); - - prom_debug("prom_hold_cpus: end...\n"); -} - -static void __init smt_setup(void) -{ - char *p, *q; - char my_smt_enabled = SMT_DYNAMIC; - ihandle prom_options = 0; - char option[9]; - unsigned long offset = reloc_offset(); - struct naca_struct *_naca = RELOC(naca); - char found = 0; - - if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) { - for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) { - q = p + 12; - if (p > RELOC(cmd_line) && p[-1] != ' ') - continue; - found = 1; - if (q[0] == 'o' && q[1] == 'f' && - q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) { - my_smt_enabled = SMT_OFF; - } else if (q[0]=='o' && q[1] == 'n' && - (q[2] == ' ' || q[2] == '\0')) { - my_smt_enabled = SMT_ON; - } else { - my_smt_enabled = SMT_DYNAMIC; - } - } - } - if (!found) { - prom_options = call_prom("finddevice", 1, 1, ADDR("/options")); - if (prom_options != (ihandle) -1) { - prom_getprop(prom_options, "ibm,smt-enabled", - option, sizeof(option)); - if (option[0] != 0) { - found = 1; - if (!strcmp(option, RELOC("off"))) - my_smt_enabled = SMT_OFF; - else if (!strcmp(option, RELOC("on"))) - my_smt_enabled = SMT_ON; - else - my_smt_enabled = SMT_DYNAMIC; - } - } - } - - if (!found ) - my_smt_enabled = SMT_DYNAMIC; /* default to on */ - - _naca->smt_state = my_smt_enabled; -} - - -#ifdef CONFIG_BOOTX_TEXT - -/* This function will enable the early boot text when doing OF booting. This - * way, xmon output should work too - */ -static void __init setup_disp_fake_bi(ihandle dp) -{ - int width = 640, height = 480, depth = 8, pitch; - unsigned address; - struct pci_reg_property addrs[8]; - int i, naddrs; - char name[64]; - unsigned long offset = reloc_offset(); - - memset(name, 0, sizeof(name)); - prom_getprop(dp, "name", name, sizeof(name)); - name[sizeof(name)-1] = 0; - prom_printf("Initializing fake screen: %s\n", name); - - prom_getprop(dp, "width", &width, sizeof(width)); - prom_getprop(dp, "height", &height, sizeof(height)); - prom_getprop(dp, "depth", &depth, sizeof(depth)); - pitch = width * ((depth + 7) / 8); - prom_getprop(dp, "linebytes", &pitch, sizeof(pitch)); - if (pitch == 1) - pitch = 0x1000; /* for strange IBM display */ - address = 0; - - prom_printf("width %x height %x depth %x linebytes %x\n", - width, height, depth, depth); - - prom_getprop(dp, "address", &address, sizeof(address)); - if (address == 0) { - /* look for an assigned address with a size of >= 1MB */ - naddrs = prom_getprop(dp, "assigned-addresses", - addrs, sizeof(addrs)); - naddrs /= sizeof(struct pci_reg_property); - for (i = 0; i < naddrs; ++i) { - if (addrs[i].size_lo >= (1 << 20)) { - address = addrs[i].addr.a_lo; - /* use the BE aperture if possible */ - if (addrs[i].size_lo >= (16 << 20)) - address += (8 << 20); - break; - } - } - if (address == 0) { - prom_printf("Failed to get address of frame buffer\n"); - return; - } - } - btext_setup_display(width, height, depth, pitch, address); - prom_printf("Addr of fb: %x\n", address); - RELOC(boot_text_mapped) = 0; -} -#endif /* CONFIG_BOOTX_TEXT */ - -static void __init prom_init_client_services(unsigned long pp) -{ - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - - /* Get a handle to the prom entry point before anything else */ - _prom->entry = pp; - - /* Init default value for phys size */ - _prom->encode_phys_size = 32; - - /* get a handle for the stdout device */ - _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); - if ((long)_prom->chosen <= 0) - prom_panic("cannot find chosen"); /* msg won't be printed :( */ - - /* get device tree root */ - _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); - if ((long)_prom->root <= 0) - prom_panic("cannot find device tree root"); /* msg won't be printed :( */ -} - -static void __init prom_init_stdout(void) -{ - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - u32 val; - - if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0) - prom_panic("cannot find stdout"); - - _prom->stdout = val; -} - -static int __init prom_find_machine_type(void) -{ - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - char compat[256]; - int len, i = 0; - - len = prom_getprop(_prom->root, "compatible", - compat, sizeof(compat)-1); - if (len > 0) { - compat[len] = 0; - while (i < len) { - char *p = &compat[i]; - int sl = strlen(p); - if (sl == 0) - break; - if (strstr(p, RELOC("Power Macintosh")) || - strstr(p, RELOC("MacRISC4"))) - return PLATFORM_POWERMAC; - i += sl + 1; - } - } - /* Default to pSeries */ - return PLATFORM_PSERIES; -} - -static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) -{ - unsigned long offset = reloc_offset(); - - return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r); -} - -/* - * If we have a display that we don't know how to drive, - * we will want to try to execute OF's open method for it - * later. However, OF will probably fall over if we do that - * we've taken over the MMU. - * So we check whether we will need to open the display, - * and if so, open it now. - */ -static unsigned long __init check_display(unsigned long mem) -{ - phandle node; - ihandle ih; - int i, j; - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - char type[16], *path; - static unsigned char default_colors[] = { - 0x00, 0x00, 0x00, - 0x00, 0x00, 0xaa, - 0x00, 0xaa, 0x00, - 0x00, 0xaa, 0xaa, - 0xaa, 0x00, 0x00, - 0xaa, 0x00, 0xaa, - 0xaa, 0xaa, 0x00, - 0xaa, 0xaa, 0xaa, - 0x55, 0x55, 0x55, - 0x55, 0x55, 0xff, - 0x55, 0xff, 0x55, - 0x55, 0xff, 0xff, - 0xff, 0x55, 0x55, - 0xff, 0x55, 0xff, - 0xff, 0xff, 0x55, - 0xff, 0xff, 0xff - }; - const unsigned char *clut; - - _prom->disp_node = 0; - - prom_printf("Looking for displays\n"); - if (RELOC(of_stdout_device) != 0) - prom_printf("OF stdout is : %s\n", - PTRRELOC(RELOC(of_stdout_device))); - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - prom_getprop(node, "device_type", type, sizeof(type)); - if (strcmp(type, RELOC("display")) != 0) - continue; - /* It seems OF doesn't null-terminate the path :-( */ - path = (char *) mem; - memset(path, 0, 256); - - /* - * leave some room at the end of the path for appending extra - * arguments - */ - if (call_prom("package-to-path", 3, 1, node, path, 250) < 0) - continue; - prom_printf("found display : %s\n", path); - - /* - * If this display is the device that OF is using for stdout, - * move it to the front of the list. - */ - mem += strlen(path) + 1; - i = RELOC(prom_num_displays); - RELOC(prom_num_displays) = i + 1; - if (RELOC(of_stdout_device) != 0 && i > 0 - && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { - for (; i > 0; --i) { - RELOC(prom_display_paths[i]) - = RELOC(prom_display_paths[i-1]); - RELOC(prom_display_nodes[i]) - = RELOC(prom_display_nodes[i-1]); - } - _prom->disp_node = node; - } - RELOC(prom_display_paths[i]) = PTRUNRELOC(path); - RELOC(prom_display_nodes[i]) = node; - if (_prom->disp_node == 0) - _prom->disp_node = node; - if (RELOC(prom_num_displays) >= FB_MAX) - break; - } - prom_printf("Opening displays...\n"); - for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) { - path = PTRRELOC(RELOC(prom_display_paths[j])); - prom_printf("opening display : %s", path); - ih = call_prom("open", 1, 1, path); - if (ih == (ihandle)0 || ih == (ihandle)-1) { - prom_printf("... failed\n"); - continue; - } - - prom_printf("... done\n"); - - /* Setup a useable color table when the appropriate - * method is available. Should update this to set-colors */ - clut = RELOC(default_colors); - for (i = 0; i < 32; i++, clut += 3) - if (prom_set_color(ih, i, clut[0], clut[1], - clut[2]) != 0) - break; - -#ifdef CONFIG_LOGO_LINUX_CLUT224 - clut = PTRRELOC(RELOC(logo_linux_clut224.clut)); - for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3) - if (prom_set_color(ih, i + 32, clut[0], clut[1], - clut[2]) != 0) - break; -#endif /* CONFIG_LOGO_LINUX_CLUT224 */ - } - - return DOUBLEWORD_ALIGN(mem); -} - -/* Return (relocated) pointer to this much memory: moves initrd if reqd. */ -static void __init *__make_room(unsigned long *mem_start, unsigned long *mem_end, - unsigned long needed, unsigned long align) -{ - void *ret; - - *mem_start = ALIGN(*mem_start, align); - if (*mem_start + needed > *mem_end) { -#ifdef CONFIG_BLK_DEV_INITRD - unsigned long offset = reloc_offset(); - /* FIXME: Apple OF doesn't map unclaimed mem. If this - * ever happened on G5, we'd need to fix. */ - unsigned long initrd_len; - - if (*mem_end != RELOC(initrd_start)) - prom_panic("No memory for copy_device_tree"); - - prom_printf("Huge device_tree: moving initrd\n"); - /* Move by 4M. */ - initrd_len = RELOC(initrd_end) - RELOC(initrd_start); - *mem_end = RELOC(initrd_start) + 4 * 1024 * 1024; - memmove((void *)*mem_end, (void *)RELOC(initrd_start), - initrd_len); - RELOC(initrd_start) = *mem_end; - RELOC(initrd_end) = RELOC(initrd_start) + initrd_len; -#else - prom_panic("No memory for copy_device_tree"); -#endif - } - - ret = (void *)*mem_start; - *mem_start += needed; - - return ret; -} - -#define make_room(startp, endp, type) \ - __make_room(startp, endp, sizeof(type), __alignof__(type)) - -static void __init -inspect_node(phandle node, struct device_node *dad, - unsigned long *mem_start, unsigned long *mem_end, - struct device_node ***allnextpp) -{ - int l; - phandle child; - struct device_node *np; - struct property *pp, **prev_propp; - char *prev_name, *namep; - unsigned char *valp; - unsigned long offset = reloc_offset(); - phandle ibm_phandle; - - np = make_room(mem_start, mem_end, struct device_node); - memset(np, 0, sizeof(*np)); - - np->node = node; - **allnextpp = PTRUNRELOC(np); - *allnextpp = &np->allnext; - if (dad != 0) { - np->parent = PTRUNRELOC(dad); - /* we temporarily use the `next' field as `last_child'. */ - if (dad->next == 0) - dad->child = PTRUNRELOC(np); - else - dad->next->sibling = PTRUNRELOC(np); - dad->next = np; - } - - /* get and store all properties */ - prev_propp = &np->properties; - prev_name = RELOC(""); - for (;;) { - /* 32 is max len of name including nul. */ - namep = make_room(mem_start, mem_end, char[32]); - if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { - /* No more nodes: unwind alloc */ - *mem_start = (unsigned long)namep; - break; - } - /* Trim off some if we can */ - *mem_start = DOUBLEWORD_ALIGN((unsigned long)namep - + strlen(namep) + 1); - pp = make_room(mem_start, mem_end, struct property); - pp->name = PTRUNRELOC(namep); - prev_name = namep; - - pp->length = call_prom("getproplen", 2, 1, node, namep); - if (pp->length < 0) - continue; - if (pp->length > MAX_PROPERTY_LENGTH) { - char path[128]; - - prom_printf("WARNING: ignoring large property "); - /* It seems OF doesn't null-terminate the path :-( */ - memset(path, 0, sizeof(path)); - if (call_prom("package-to-path", 3, 1, node, - path, sizeof(path)-1) > 0) - prom_printf("[%s] ", path); - prom_printf("%s length 0x%x\n", namep, pp->length); - continue; - } - valp = __make_room(mem_start, mem_end, pp->length, 1); - pp->value = PTRUNRELOC(valp); - call_prom("getprop", 4, 1, node, namep, valp, pp->length); - *prev_propp = PTRUNRELOC(pp); - prev_propp = &pp->next; - } - - /* Add a "linux,phandle" property. */ - namep = make_room(mem_start, mem_end, char[16]); - strcpy(namep, RELOC("linux,phandle")); - pp = make_room(mem_start, mem_end, struct property); - pp->name = PTRUNRELOC(namep); - pp->length = sizeof(phandle); - valp = make_room(mem_start, mem_end, phandle); - pp->value = PTRUNRELOC(valp); - *(phandle *)valp = node; - *prev_propp = PTRUNRELOC(pp); - pp->next = NULL; - - /* Set np->linux_phandle to the value of the ibm,phandle property - if it exists, otherwise to the phandle for this node. */ - np->linux_phandle = node; - if (prom_getprop(node, "ibm,phandle", - &ibm_phandle, sizeof(ibm_phandle)) > 0) - np->linux_phandle = ibm_phandle; - - /* get the node's full name */ - namep = (char *)*mem_start; - l = call_prom("package-to-path", 3, 1, node, - namep, *mem_end - *mem_start); - if (l >= 0) { - /* Didn't fit? Get more room. */ - if (l+1 > *mem_end - *mem_start) { - namep = __make_room(mem_start, mem_end, l+1, 1); - call_prom("package-to-path", 3, 1, node, namep, l); - } - np->full_name = PTRUNRELOC(namep); - namep[l] = '\0'; - *mem_start = DOUBLEWORD_ALIGN(*mem_start + l + 1); - } - - /* do all our children */ - child = call_prom("child", 1, 1, node); - while (child != (phandle)0) { - inspect_node(child, np, mem_start, mem_end, - allnextpp); - child = call_prom("peer", 1, 1, child); - } -} - -/* - * Make a copy of the device tree from the PROM. - */ -static unsigned long __init -copy_device_tree(unsigned long mem_start) -{ - phandle root; - struct device_node **allnextp; - unsigned long offset = reloc_offset(); - unsigned long mem_end; - - /* We pass mem_end-mem_start to OF: keep it well under 32-bit */ - mem_end = mem_start + 1024*1024*1024; -#ifdef CONFIG_BLK_DEV_INITRD - if (RELOC(initrd_start) && RELOC(initrd_start) > mem_start) - mem_end = RELOC(initrd_start); -#endif /* CONFIG_BLK_DEV_INITRD */ - - root = call_prom("peer", 1, 1, (phandle)0); - if (root == (phandle)0) { - prom_panic("couldn't get device tree root\n"); - } - allnextp = &RELOC(allnodes); - inspect_node(root, NULL, &mem_start, &mem_end, &allnextp); - *allnextp = NULL; - return mem_start; -} - -/* Verify bi_recs are good */ -static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs) -{ - struct bi_record *first, *last; - - prom_debug("birec_verify: r6=0x%x\n", (unsigned long)bi_recs); - if (bi_recs != NULL) - prom_debug(" tag=0x%x\n", bi_recs->tag); - - if ( bi_recs == NULL || bi_recs->tag != BI_FIRST ) - return NULL; - - last = (struct bi_record *)(long)bi_recs->data[0]; - - prom_debug(" last=0x%x\n", (unsigned long)last); - if (last != NULL) - prom_debug(" last_tag=0x%x\n", last->tag); - - if ( last == NULL || last->tag != BI_LAST ) - return NULL; - - first = (struct bi_record *)(long)last->data[0]; - prom_debug(" first=0x%x\n", (unsigned long)first); - - if ( first == NULL || first != bi_recs ) - return NULL; - - return bi_recs; -} - -static void __init prom_bi_rec_reserve(void) -{ - unsigned long offset = reloc_offset(); - struct prom_t *_prom = PTRRELOC(&prom); - struct bi_record *rec; - - if ( _prom->bi_recs != NULL) { - - for ( rec=_prom->bi_recs; - rec->tag != BI_LAST; - rec=bi_rec_next(rec) ) { - prom_debug("bi: 0x%x\n", rec->tag); - switch (rec->tag) { -#ifdef CONFIG_BLK_DEV_INITRD - case BI_INITRD: - RELOC(initrd_start) = (unsigned long)(rec->data[0]); - RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1]; - break; -#endif /* CONFIG_BLK_DEV_INITRD */ - } - } - /* The next use of this field will be after relocation - * is enabled, so convert this physical address into a - * virtual address. - */ - _prom->bi_recs = PTRUNRELOC(_prom->bi_recs); - } -} - -/* - * We enter here early on, when the Open Firmware prom is still - * handling exceptions and the MMU hash table for us. - */ - -unsigned long __init -prom_init(unsigned long r3, unsigned long r4, unsigned long pp, - unsigned long r6, unsigned long r7) -{ - unsigned long mem; - ihandle prom_cpu; - phandle cpu_pkg; - unsigned long offset = reloc_offset(); - long l; - char *p, *d; - unsigned long phys; - u32 getprop_rval; - struct systemcfg *_systemcfg; - struct paca_struct *lpaca = PTRRELOC(&paca[0]); - struct prom_t *_prom = PTRRELOC(&prom); - - /* First zero the BSS -- use memset, some arches don't have - * caches on yet */ - memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start); - - /* Setup systemcfg and NACA pointers now */ - RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset); - RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset); - - /* Init interface to Open Firmware and pickup bi-recs */ - prom_init_client_services(pp); - - /* Init prom stdout device */ - prom_init_stdout(); - - prom_debug("klimit=0x%x\n", RELOC(klimit)); - prom_debug("offset=0x%x\n", offset); - prom_debug("->mem=0x%x\n", RELOC(klimit) - offset); - - /* check out if we have bi_recs */ - _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6); - if ( _prom->bi_recs != NULL ) { - RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + - _prom->bi_recs->data[1]); - prom_debug("bi_recs=0x%x\n", (unsigned long)_prom->bi_recs); - prom_debug("new mem=0x%x\n", RELOC(klimit) - offset); - } - - /* If we don't have birec's or didn't find them, check for an initrd - * using the "yaboot" way - */ -#ifdef CONFIG_BLK_DEV_INITRD - if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) { - RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3; - RELOC(initrd_end) = RELOC(initrd_start) + r4; - RELOC(initrd_below_start_ok) = 1; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Default machine type. */ - _systemcfg->platform = prom_find_machine_type(); - - /* On pSeries, copy the CPU hold code */ - if (_systemcfg->platform == PLATFORM_PSERIES) - copy_and_flush(0, KERNELBASE - offset, 0x100, 0); - - /* Start storing things at klimit */ - mem = RELOC(klimit) - offset; - - /* Get the full OF pathname of the stdout device */ - p = (char *) mem; - memset(p, 0, 256); - call_prom("instance-to-path", 3, 1, _prom->stdout, p, 255); - RELOC(of_stdout_device) = PTRUNRELOC(p); - mem += strlen(p) + 1; - - getprop_rval = 1; - prom_getprop(_prom->root, "#size-cells", - &getprop_rval, sizeof(getprop_rval)); - _prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64; - - /* Determine which cpu is actually running right _now_ */ - if (prom_getprop(_prom->chosen, "cpu", - &prom_cpu, sizeof(prom_cpu)) <= 0) - prom_panic("cannot find boot cpu"); - - cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); - prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); - _prom->cpu = getprop_rval; - lpaca[0].hw_cpu_id = _prom->cpu; - - RELOC(boot_cpuid) = 0; - - prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu); - - /* Get the boot device and translate it to a full OF pathname. */ - p = (char *) mem; - l = prom_getprop(_prom->chosen, "bootpath", p, 1<<20); - if (l > 0) { - p[l] = 0; /* should already be null-terminated */ - RELOC(bootpath) = PTRUNRELOC(p); - mem += l + 1; - d = (char *) mem; - *d = 0; - call_prom("canon", 3, 1, p, d, 1<<20); - RELOC(bootdevice) = PTRUNRELOC(d); - mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1); - } - - RELOC(cmd_line[0]) = 0; - if ((long)_prom->chosen > 0) { - prom_getprop(_prom->chosen, "bootargs", p, sizeof(cmd_line)); - if (p != NULL && p[0] != 0) - strlcpy(RELOC(cmd_line), p, sizeof(cmd_line)); - } - - early_cmdline_parse(); - - prom_initialize_lmb(); - - prom_bi_rec_reserve(); - - mem = check_display(mem); - - if (_systemcfg->platform != PLATFORM_POWERMAC) - prom_instantiate_rtas(); - - /* Initialize some system info into the Naca early... */ - prom_initialize_naca(); - - smt_setup(); - - /* If we are on an SMP machine, then we *MUST* do the - * following, regardless of whether we have an SMP - * kernel or not. - */ - prom_hold_cpus(mem); - - prom_debug("after basic inits, mem=0x%x\n", mem); -#ifdef CONFIG_BLK_DEV_INITRD - prom_debug("initrd_start=0x%x\n", RELOC(initrd_start)); - prom_debug("initrd_end=0x%x\n", RELOC(initrd_end)); -#endif /* CONFIG_BLK_DEV_INITRD */ - prom_debug("copying OF device tree...\n"); - - mem = copy_device_tree(mem); - - RELOC(klimit) = mem + offset; +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif - prom_debug("new klimit is\n"); - prom_debug("klimit=0x%x\n", RELOC(klimit)); - prom_debug(" ->mem=0x%x\n", mem); +struct pci_reg_property { + struct pci_address addr; + u32 size_hi; + u32 size_lo; +}; - lmb_reserve(0, __pa(RELOC(klimit))); +struct isa_reg_property { + u32 space; + u32 address; + u32 size; +}; -#ifdef CONFIG_BLK_DEV_INITRD - if (RELOC(initrd_start)) { - unsigned long initrd_len; - initrd_len = RELOC(initrd_end) - RELOC(initrd_start); - /* Move initrd if it's where we're going to copy kernel. */ - if (RELOC(initrd_start) < __pa(RELOC(klimit))) { - memmove((void *)mem, (void *)RELOC(initrd_start), - initrd_len); - RELOC(initrd_start) = mem; - RELOC(initrd_end) = mem + initrd_len; - } +typedef unsigned long interpret_func(struct device_node *, unsigned long, + int, int, int); - lmb_reserve(RELOC(initrd_start), initrd_len); - } -#endif /* CONFIG_BLK_DEV_INITRD */ +extern struct rtas_t rtas; +extern struct lmb lmb; +extern unsigned long klimit; - if (_systemcfg->platform == PLATFORM_PSERIES) - prom_initialize_tce_table(); +static int __initdata dt_root_addr_cells; +static int __initdata dt_root_size_cells; +static int __initdata iommu_is_off; +int __initdata iommu_force_on; +typedef u32 cell_t; -#ifdef CONFIG_PMAC_DART - if (_systemcfg->platform == PLATFORM_POWERMAC) - prom_initialize_dart_table(); +#if 0 +static struct boot_param_header *initial_boot_params __initdata; +#else +struct boot_param_header *initial_boot_params; #endif -#ifdef CONFIG_BOOTX_TEXT - if (_prom->disp_node) { - prom_printf("Setting up bi display...\n"); - setup_disp_fake_bi(_prom->disp_node); - } -#endif /* CONFIG_BOOTX_TEXT */ - - prom_printf("Calling quiesce ...\n"); - call_prom("quiesce", 0, 0); - phys = KERNELBASE - offset; +static struct device_node *allnodes = NULL; -#ifdef CONFIG_BLK_DEV_INITRD - /* If we had an initrd, we convert its address to virtual */ - if (RELOC(initrd_start)) { - RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start)); - RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end)); - } -#endif /* CONFIG_BLK_DEV_INITRD */ +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static rwlock_t devtree_lock = RW_LOCK_UNLOCKED; - prom_printf("returning from prom_init\n"); - return phys; -} +/* export that to outside world */ +struct device_node *of_chosen; /* * Find the device_node with a given phandle. */ -static struct device_node * __devinit -find_phandle(phandle ph) +static struct device_node * find_phandle(phandle ph) { struct device_node *np; @@ -1866,8 +117,7 @@ find_phandle(phandle ph) /* * Find the interrupt parent of a node. */ -static struct device_node * __devinit -intr_parent(struct device_node *p) +static struct device_node * __devinit intr_parent(struct device_node *p) { phandle *parp; @@ -1908,14 +158,14 @@ int __devinit prom_n_intr_cells(struct device_node *np) * Map an interrupt from a device up to the platform interrupt * descriptor. */ -static int __devinit -map_interrupt(unsigned int **irq, struct device_node **ictrler, - struct device_node *np, unsigned int *ints, int nintrc) +static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, + struct device_node *np, unsigned int *ints, + int nintrc) { struct device_node *p, *ipar; unsigned int *imap, *imask, *ip; int i, imaplen, match; - int newintrc, newaddrc; + int newintrc = 0, newaddrc = 0; unsigned int *reg; int naddrc; @@ -2004,9 +254,9 @@ map_interrupt(unsigned int **irq, struct device_node **ictrler, return nintrc; } -static unsigned long __init -finish_node_interrupts(struct device_node *np, unsigned long mem_start, - int measure_only) +static unsigned long __init finish_node_interrupts(struct device_node *np, + unsigned long mem_start, + int measure_only) { unsigned int *ints; int intlen, intrcells, intrcount; @@ -2067,9 +317,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -interpret_pci_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec, int measure_only) +static unsigned long __init interpret_pci_props(struct device_node *np, + unsigned long mem_start, + int naddrc, int nsizec, + int measure_only) { struct address_range *adr; struct pci_reg_property *pci_addrs; @@ -2095,9 +346,10 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -interpret_dbdma_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec, int measure_only) +static unsigned long __init interpret_dbdma_props(struct device_node *np, + unsigned long mem_start, + int naddrc, int nsizec, + int measure_only) { struct reg_property32 *rp; struct address_range *adr; @@ -2135,9 +387,10 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -interpret_macio_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec, int measure_only) +static unsigned long __init interpret_macio_props(struct device_node *np, + unsigned long mem_start, + int naddrc, int nsizec, + int measure_only) { struct reg_property32 *rp; struct address_range *adr; @@ -2175,9 +428,10 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -interpret_isa_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec, int measure_only) +static unsigned long __init interpret_isa_props(struct device_node *np, + unsigned long mem_start, + int naddrc, int nsizec, + int measure_only) { struct isa_reg_property *rp; struct address_range *adr; @@ -2187,7 +441,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start, if (rp != 0 && l >= sizeof(struct isa_reg_property)) { i = 0; adr = (struct address_range *) mem_start; - while ((l -= sizeof(struct reg_property)) >= 0) { + while ((l -= sizeof(struct isa_reg_property)) >= 0) { if (!measure_only) { adr[i].space = rp[i].space; adr[i].address = rp[i].address; @@ -2203,9 +457,10 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -interpret_root_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec, int measure_only) +static unsigned long __init interpret_root_props(struct device_node *np, + unsigned long mem_start, + int naddrc, int nsizec, + int measure_only) { struct address_range *adr; int i, l; @@ -2233,21 +488,15 @@ interpret_root_props(struct device_node *np, unsigned long mem_start, return mem_start; } -static unsigned long __init -finish_node(struct device_node *np, unsigned long mem_start, - interpret_func *ifunc, int naddrc, int nsizec, int measure_only) +static unsigned long __init finish_node(struct device_node *np, + unsigned long mem_start, + interpret_func *ifunc, + int naddrc, int nsizec, + int measure_only) { struct device_node *child; int *ip; - np->name = get_property(np, "name", NULL); - np->type = get_property(np, "device_type", NULL); - - if (!np->name) - np->name = ""; - if (!np->type) - np->type = ""; - /* get the device addresses and interrupts */ if (ifunc != NULL) mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only); @@ -2298,24 +547,526 @@ finish_node(struct device_node *np, unsigned long mem_start, /** * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). - * It traverses the device tree and fills in the name, type, - * {n_}addrs and {n_}intrs fields of each node. + * It traverses the device tree and fills in some of the additional, + * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt + * mapping is also initialized at this point. */ -void __init -finish_device_tree(void) +void __init finish_device_tree(void) { - unsigned long mem = klimit; + unsigned long mem, size; + DBG(" -> finish_device_tree\n"); + + if (naca->interrupt_controller == IC_INVALID) { + DBG("failed to configure interrupt controller type\n"); + panic("failed to configure interrupt controller type\n"); + } + + /* Initialize virtual IRQ map */ virt_irq_init(); - dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1); - mem = (long)abs_to_virt(lmb_alloc(dev_tree_size, - __alignof__(struct device_node))); - if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size) + /* Finish device-tree (pre-parsing some properties etc...) */ + size = finish_node(allnodes, 0, NULL, 0, 0, 1); + mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128)); + if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size) BUG(); - rtas.dev = of_find_node_by_name(NULL, "rtas"); + + DBG(" <- finish_device_tree\n"); +} + +#ifdef DEBUG +#define printk udbg_printf +#endif + +static inline char *find_flat_dt_string(u32 offset) +{ + return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings + + offset; +} + +/** + * This function is used to scan the flattened device-tree, it is + * used to extract the memory informations at boot before we can + * unflatten the tree + */ +static int __init scan_flat_dt(int (*it)(unsigned long node, + const char *full_path, void *data), + void *data) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + int rc = 0; + + do { + u32 tag = *((u32 *)p); + char *pathp; + + p += 4; + if (tag == OF_DT_END_NODE) + continue; + if (tag == OF_DT_END) + break; + if (tag == OF_DT_PROP) { + u32 sz = *((u32 *)p); + p += 8; + p = _ALIGN(p, sz >= 8 ? 8 : 4); + p += sz; + p = _ALIGN(p, 4); + continue; + } + if (tag != OF_DT_BEGIN_NODE) { + printk(KERN_WARNING "Invalid tag %x scanning flattened" + " device tree !\n", tag); + return -EINVAL; + } + pathp = (char *)p; + p = _ALIGN(p + strlen(pathp) + 1, 4); + rc = it(p, pathp, data); + if (rc != 0) + break; + } while(1); + + return rc; +} + +/** + * This function can be used within scan_flattened_dt callback to get + * access to properties + */ +static void* __init get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) +{ + unsigned long p = node; + + do { + u32 tag = *((u32 *)p); + u32 sz, noff; + const char *nstr; + + p += 4; + if (tag != OF_DT_PROP) + return NULL; + + sz = *((u32 *)p); + noff = *((u32 *)(p + 4)); + p += 8; + p = _ALIGN(p, sz >= 8 ? 8 : 4); + + nstr = find_flat_dt_string(noff); + if (nstr == NULL) { + printk(KERN_WARNING "Can't find property index name !\n"); + return NULL; + } + if (strcmp(name, nstr) == 0) { + if (size) + *size = sz; + return (void *)p; + } + p += sz; + p = _ALIGN(p, 4); + } while(1); +} + +static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, + unsigned long align) +{ + void *res; + + *mem = _ALIGN(*mem, align); + res = (void *)*mem; + *mem += size; + + return res; +} + +static unsigned long __init unflatten_dt_node(unsigned long mem, + unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp) +{ + struct device_node *np; + struct property *pp, **prev_pp = NULL; + char *pathp; + u32 tag; + unsigned int l; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_BEGIN_NODE) { + printk("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + pathp = (char *)*p; + l = strlen(pathp) + 1; + *p = _ALIGN(*p + l, 4); + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l, + __alignof__(struct device_node)); + if (allnextpp) { + memset(np, 0, sizeof(*np)); + np->full_name = ((char*)np) + sizeof(struct device_node); + memcpy(np->full_name, pathp, l); + prev_pp = &np->properties; + **allnextpp = np; + *allnextpp = &np->allnext; + if (dad != NULL) { + np->parent = dad; + /* we temporarily use the `next' field as `last_child'. */ + if (dad->next == 0) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + } + while(1) { + u32 sz, noff; + char *pname; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_PROP) + break; + *p += 4; + sz = *((u32 *)(*p)); + noff = *((u32 *)((*p) + 4)); + *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4); + + pname = find_flat_dt_string(noff); + if (pname == NULL) { + printk("Can't find property name in list !\n"); + break; + } + l = strlen(pname) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property), + __alignof__(struct property)); + if (allnextpp) { + if (strcmp(pname, "linux,phandle") == 0) { + np->node = *((u32 *)*p); + if (np->linux_phandle == 0) + np->linux_phandle = np->node; + } + if (strcmp(pname, "ibm,phandle") == 0) + np->linux_phandle = *((u32 *)*p); + pp->name = pname; + pp->length = sz; + pp->value = (void *)*p; + *prev_pp = pp; + prev_pp = &pp->next; + } + *p = _ALIGN((*p) + sz, 4); + } + if (allnextpp) { + *prev_pp = NULL; + np->name = get_property(np, "name", NULL); + np->type = get_property(np, "device_type", NULL); + + if (!np->name) + np->name = ""; + if (!np->type) + np->type = ""; + } + while (tag == OF_DT_BEGIN_NODE) { + mem = unflatten_dt_node(mem, p, np, allnextpp); + tag = *((u32 *)(*p)); + } + if (tag != OF_DT_END_NODE) { + printk("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + return mem; +} + + +/** + * unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used (this used to be done by finish_device_tree) + */ +void __init unflatten_device_tree(void) +{ + unsigned long start, mem, size; + struct device_node **allnextp = &allnodes; + char *p; + int l = 0; + + DBG(" -> unflatten_device_tree()\n"); + + /* First pass, scan for size */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + size = unflatten_dt_node(0, &start, NULL, NULL); + + DBG(" size is %lx, allocating...\n", size); + + /* Allocate memory for the expanded device tree */ + mem = (unsigned long)abs_to_virt(lmb_alloc(size, + __alignof__(struct device_node))); + DBG(" unflattening...\n", mem); + + /* Second pass, do actual unflattening */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + unflatten_dt_node(mem, &start, NULL, &allnextp); + if (*((u32 *)start) != OF_DT_END) + printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start)); + *allnextp = NULL; + + /* Get pointer to OF "/chosen" node for use everywhere */ + of_chosen = of_find_node_by_path("/chosen"); + + /* Retreive command line */ + if (of_chosen != NULL) { + p = (char *)get_property(of_chosen, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE)); + } +#ifdef CONFIG_CMDLINE + if (l == 0 || (l == 1 && (*p) == 0)) + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif /* CONFIG_CMDLINE */ + + DBG("Command line is: %s\n", cmd_line); + + DBG(" <- unflatten_device_tree()\n"); +} + + +static int __init early_init_dt_scan_cpus(unsigned long node, + const char *full_path, void *data) +{ + char *type = get_flat_dt_prop(node, "device_type", NULL); + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + /* On LPAR, look for the first ibm,pft-size property for the hash table size + */ + if (systemcfg->platform == PLATFORM_PSERIES_LPAR && naca->pftSize == 0) { + u32 *pft_size; + pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL); + if (pft_size != NULL) { + /* pft_size[0] is the NUMA CEC cookie */ + naca->pftSize = pft_size[1]; + } + } + + if (initial_boot_params && initial_boot_params->version >= 2) { + /* version 2 of the kexec param format adds the phys cpuid + * of booted proc. + */ + boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; + boot_cpuid = 0; + } else { + /* Check if it's the boot-cpu, set it's hw index in paca now */ + if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { + u32 *prop = get_flat_dt_prop(node, "reg", NULL); + set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); + boot_cpuid_phys = get_hard_smp_processor_id(0); + } + } + + return 0; +} + +static int __init early_init_dt_scan_chosen(unsigned long node, + const char *full_path, void *data) +{ + u32 *prop; + + if (strcmp(full_path, "/chosen") != 0) + return 0; + + /* get platform type */ + prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); + if (prop == NULL) + return 0; + systemcfg->platform = *prop; + + /* check if iommu is forced on or off */ + if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) + iommu_is_off = 1; + if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) + iommu_force_on = 1; + +#ifdef CONFIG_PPC_PSERIES + /* To help early debugging via the front panel, we retreive a minimal + * set of RTAS infos now if available + */ + { + u64 *basep, *entryp; + + basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL); + entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL); + prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL); + if (basep && entryp && prop) { + rtas.base = *basep; + rtas.entry = *entryp; + rtas.size = *prop; + } + } +#endif /* CONFIG_PPC_PSERIES */ + + /* break now */ + return 1; +} + +static int __init early_init_dt_scan_root(unsigned long node, + const char *full_path, void *data) +{ + u32 *prop; + + if (strcmp(full_path, "/") != 0) + return 0; + + prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); + dt_root_size_cells = (prop == NULL) ? 1 : *prop; + + prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); + dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + + /* break now */ + return 1; +} + +static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) +{ + cell_t *p = *cellp; + unsigned long r = 0; + + /* Ignore more than 2 cells */ + while (s > 2) { + p++; + s--; + } + while (s) { + r <<= 32; + r |= *(p++); + s--; + } + + *cellp = p; + return r; +} + + +static int __init early_init_dt_scan_memory(unsigned long node, + const char *full_path, void *data) +{ + char *type = get_flat_dt_prop(node, "device_type", NULL); + cell_t *reg, *endp; + unsigned long l; + + /* We are scanning "memory" nodes only */ + if (type == NULL || strcmp(type, "memory") != 0) + return 0; + + reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); + if (reg == NULL) + return 0; + + endp = reg + (l / sizeof(cell_t)); + + DBG("memory scan node %s ...\n", full_path); + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + unsigned long base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + + if (size == 0) + continue; + DBG(" - %lx , %lx\n", base, size); + if (iommu_is_off) { + if (base >= 0x80000000ul) + continue; + if ((base + size) > 0x80000000ul) + size = 0x80000000ul - base; + } + lmb_add(base, size); + } + return 0; +} + +static void __init early_reserve_mem(void) +{ + u64 base, size; + u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) + + initial_boot_params->off_mem_rsvmap); + while (1) { + base = *(reserve_map++); + size = *(reserve_map++); + if (size == 0) + break; + DBG("reserving: %lx -> %lx\n", base, size); + lmb_reserve(base, size); + } + +#if 0 + DBG("memory reserved, lmbs :\n"); + lmb_dump_all(); +#endif +} + +void __init early_init_devtree(void *params) +{ + DBG(" -> early_init_devtree()\n"); + + /* Setup flat device-tree pointer */ + initial_boot_params = params; + + /* By default, hash size is not set */ + naca->pftSize = 0; + + /* Retreive various informations from the /chosen node of the + * device-tree, including the platform type, initrd location and + * size, TCE reserve, and more ... + */ + scan_flat_dt(early_init_dt_scan_chosen, NULL); + + /* Scan memory nodes and rebuild LMBs */ + lmb_init(); + scan_flat_dt(early_init_dt_scan_root, NULL); + scan_flat_dt(early_init_dt_scan_memory, NULL); + lmb_analyze(); + systemcfg->physicalMemorySize = lmb_phys_mem_size(); + lmb_reserve(0, __pa(klimit)); + + DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize); + + /* Reserve LMB regions used by kernel, initrd, dt, etc... */ + early_reserve_mem(); + + DBG("Scanning CPUs ...\n"); + + /* Retreive hash table size from flattened tree */ + scan_flat_dt(early_init_dt_scan_cpus, NULL); + + /* If hash size wasn't obtained above, we calculate it now based on + * the total RAM size + */ + if (naca->pftSize == 0) { + unsigned long rnd_mem_size, pteg_count; + + /* round mem_size up to next power of 2 */ + rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); + if (rnd_mem_size < systemcfg->physicalMemorySize) + rnd_mem_size <<= 1; + + /* # pages / 2 */ + pteg_count = (rnd_mem_size >> (12 + 1)); + + naca->pftSize = __ilog2(pteg_count << 7); + } + + DBG("Hash pftSize: %x\n", (int)naca->pftSize); + DBG(" <- early_init_devtree()\n"); } +#undef printk + int prom_n_addr_cells(struct device_node* np) { @@ -2350,8 +1101,7 @@ prom_n_size_cells(struct device_node* np) * Work out the sense (active-low level / active-high edge) * of each interrupt from the device tree. */ -void __init -prom_get_irq_senses(unsigned char *senses, int off, int max) +void __init prom_get_irq_senses(unsigned char *senses, int off, int max) { struct device_node *np; int i, j; @@ -2363,7 +1113,9 @@ prom_get_irq_senses(unsigned char *senses, int off, int max) for (j = 0; j < np->n_intrs; j++) { i = np->intrs[j].line; if (i >= off && i < max) - senses[i-off] = np->intrs[j].sense; + senses[i-off] = np->intrs[j].sense ? + IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE : + IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE; } } } @@ -2627,6 +1379,28 @@ struct device_node *of_find_node_by_path(const char *path) } EXPORT_SYMBOL(of_find_node_by_path); +/** + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + read_lock(&devtree_lock); + for (np = allnodes; np != 0; np = np->allnext) + if (np->linux_phandle == handle) + break; + if (np) + of_node_get(np); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + /** * of_find_all_nodes - Get next node in global list * @prev: Previous node or NULL to start iteration @@ -2886,6 +1660,7 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node) return 0; } + /* * Fix up the uninitialized fields in a new device node: * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields @@ -2971,12 +1746,14 @@ static int of_finish_dynamic_node(struct device_node *node) /* fixing up iommu_table */ +#ifdef CONFIG_PPC_PSERIES if (strcmp(node->name, "pci") == 0 && get_property(node, "ibm,dma-window", NULL)) { node->bussubno = node->busno; - iommu_devnode_init(node); + iommu_devnode_init_pSeries(node); } else node->iommu_table = parent->iommu_table; +#endif /* CONFIG_PPC_PSERIES */ out: of_node_put(parent); @@ -3034,6 +1811,15 @@ int of_add_node(const char *path, struct property *proplist) return 0; } +/* + * Prepare an OF node for removal from system + */ +static void of_cleanup_node(struct device_node *np) +{ + if (np->iommu_table && get_property(np, "ibm,dma-window", NULL)) + iommu_free_table(np); +} + /* * Remove an OF device node from the system. * Caller should have already "gotten" np. @@ -3051,6 +1837,8 @@ int of_remove_node(struct device_node *np) return -EBUSY; } + of_cleanup_node(np); + write_lock(&devtree_lock); OF_MARK_STALE(np); remove_node_proc_entries(np); @@ -3163,3 +1951,13 @@ print_properties(struct device_node *np) } } #endif + + + + + + + + + + diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index f62bda79e..e570799a8 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +51,6 @@ #include #include #include -#include "open_pic.h" #ifdef CONFIG_LOGO_LINUX_CLUT224 #include @@ -160,8 +159,6 @@ extern void copy_and_flush(unsigned long dest, unsigned long src, extern unsigned long klimit; -//int global_width = 640, global_height = 480, global_depth = 8, global_pitch; -//unsigned global_address; /* prom structure */ static struct prom_t __initdata prom; @@ -675,7 +672,7 @@ static void __init prom_init_mem(void) if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) RELOC(alloc_top) = RELOC(rmo_top); else - RELOC(alloc_top) = min(0x40000000ul, RELOC(ram_top)); + RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top)); RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000); RELOC(alloc_top_high) = RELOC(ram_top); @@ -704,48 +701,51 @@ static void __init prom_instantiate_rtas(void) { unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); - phandle prom_rtas; - u64 base, entry = 0; - u32 size; + phandle prom_rtas, rtas_node; + u32 base, entry = 0; + u32 size = 0; prom_debug("prom_instantiate_rtas: start...\n"); prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); - if (prom_rtas != (phandle) -1) { - prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); - if (size != 0) { - base = alloc_down(size, PAGE_SIZE, 0); - if (base == 0) { - prom_printf("RTAS allocation failed !\n"); - return; - } - prom_printf("instantiating rtas at 0x%x", base); - - prom_rtas = call_prom("open", 1, 1, ADDR("/rtas")); - prom_printf("..."); + prom_debug("prom_rtas: %x\n", prom_rtas); + if (prom_rtas == (phandle) -1) + return; - if (call_prom("call-method", 3, 2, - ADDR("instantiate-rtas"), - prom_rtas, base) != PROM_ERROR) { - entry = (long)_prom->args.rets[1]; - } - if (entry == 0) { - prom_printf(" failed\n"); - return; - } - prom_printf(" done\n"); + prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); + if (size == 0) + return; - reserve_mem(base, size); - } + base = alloc_down(size, PAGE_SIZE, 0); + if (base == 0) { + prom_printf("RTAS allocation failed !\n"); + return; + } + prom_printf("instantiating rtas at 0x%x", base); - prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base)); - prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry)); - prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size)); + rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); + prom_printf("..."); - prom_debug("rtas base = 0x%x\n", base); - prom_debug("rtas entry = 0x%x\n", entry); - prom_debug("rtas size = 0x%x\n", (long)size); + if (call_prom("call-method", 3, 2, + ADDR("instantiate-rtas"), + rtas_node, base) != PROM_ERROR) { + entry = (long)_prom->args.rets[1]; + } + if (entry == 0) { + prom_printf(" failed\n"); + return; } + prom_printf(" done\n"); + + reserve_mem(base, size); + + prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); + prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); + + prom_debug("rtas base = 0x%x\n", base); + prom_debug("rtas entry = 0x%x\n", entry); + prom_debug("rtas size = 0x%x\n", (long)size); + prom_debug("prom_instantiate_rtas: end...\n"); } @@ -760,7 +760,7 @@ static void __init prom_initialize_tce_table(void) unsigned long offset = reloc_offset(); char compatible[64], type[64], model[64]; char *path = RELOC(prom_scratch); - u64 base, vbase, align; + u64 base, align; u32 minalign, minsize; u64 tce_entry, *tce_entryp; u64 local_alloc_top, local_alloc_bottom; @@ -832,12 +832,9 @@ static void __init prom_initialize_tce_table(void) if (base < local_alloc_bottom) local_alloc_bottom = base; - vbase = (unsigned long)abs_to_virt(base); - /* Save away the TCE table attributes for later use. */ - prom_setprop(node, "linux,tce-base", &vbase, sizeof(vbase)); + prom_setprop(node, "linux,tce-base", &base, sizeof(base)); prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); - prom_setprop(node, "linux,has-tce-table", NULL, 0); /* It seems OF doesn't null-terminate the path :-( */ memset(path, 0, sizeof(path)); @@ -952,9 +949,9 @@ static void __init prom_hold_cpus(void) continue; /* Skip non-configured cpus. */ - prom_getprop(node, "status", type, sizeof(type)); - if (strcmp(type, RELOC("okay")) != 0) - continue; + if (prom_getprop(node, "status", type, sizeof(type)) > 0) + if (strcmp(type, RELOC("okay")) != 0) + continue; reg = -1; prom_getprop(node, "reg", ®, sizeof(reg)); @@ -991,12 +988,13 @@ static void __init prom_hold_cpus(void) /* Primary Thread of non-boot cpu */ prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg); call_prom("start-cpu", 3, 0, node, - secondary_hold, cpuid); + secondary_hold, reg); for ( i = 0 ; (i < 100000000) && - (*acknowledge == ((unsigned long)-1)); i++ ) ; + (*acknowledge == ((unsigned long)-1)); i++ ) + mb(); - if (*acknowledge == cpuid) { + if (*acknowledge == reg) { prom_printf("done\n"); /* We have to get every CPU out of OF, * even if we never start it. */ @@ -1110,6 +1108,16 @@ static void __init prom_init_stdout(void) } } +static void __init prom_close_stdin(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + ihandle val; + + if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0) + call_prom("close", 1, 0, val); +} + static int __init prom_find_machine_type(void) { unsigned long offset = reloc_offset(); @@ -1130,6 +1138,8 @@ static int __init prom_find_machine_type(void) if (strstr(p, RELOC("Power Macintosh")) || strstr(p, RELOC("MacRISC4"))) return PLATFORM_POWERMAC; + if (strstr(p, RELOC("Momentum,Maple"))) + return PLATFORM_MAPLE; i += sl + 1; } } @@ -1161,7 +1171,7 @@ static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) * So we check whether we will need to open the display, * and if so, open it now. */ -static unsigned long __init prom_check_displays(void) +static void __init prom_check_displays(void) { unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); @@ -1602,11 +1612,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long prom_debug("klimit=0x%x\n", RELOC(klimit)); prom_debug("offset=0x%x\n", offset); - /* - * Reserve kernel in reserve map - */ - reserve_mem(0, __pa(RELOC(klimit))); - /* * Check for an initrd */ @@ -1691,6 +1696,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long prom_printf("copying OF device tree ...\n"); flatten_device_tree(); + /* in case stdin is USB and still active on IBM machines... */ + prom_close_stdin(); + /* * Call OF "quiesce" method to shut down pending DMA's from * devices etc... diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index aeead8375..b3f560bd8 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -182,7 +182,7 @@ int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ @@ -318,7 +318,8 @@ void do_syscall_trace_leave(void) if (unlikely(current->audit_context)) audit_syscall_exit(current, 0); /* FIXME: pass pt_regs */ - if (test_thread_flag(TIF_SYSCALL_TRACE) + if ((test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SINGLESTEP)) && (current->ptrace & PT_PTRACED)) do_syscall_trace(); } diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index e0ab44dc1..ee81b1b77 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -314,7 +314,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c index 595ae6ec2..06f69b37f 100644 --- a/arch/ppc64/kernel/ras.c +++ b/arch/ppc64/kernel/ras.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -161,7 +161,8 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) RAS_VECTOR_OFFSET, virt_irq_to_real(irq_offset_down(irq)), RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, - critical, __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX); + critical, __pa(&ras_log_buf), + rtas_get_error_log_max()); udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n", *((unsigned long *)&ras_log_buf), status, state); @@ -196,11 +197,12 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) RAS_VECTOR_OFFSET, virt_irq_to_real(irq_offset_down(irq)), RTAS_INTERNAL_ERROR, 1 /*Time Critical */, - __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX); + __pa(&ras_log_buf), + rtas_get_error_log_max()); rtas_elog = (struct rtas_error_log *)ras_log_buf; - if ((status == 0) && (rtas_elog->severity >= SEVERITY_ERROR_SYNC)) + if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC)) fatal = 1; else fatal = 0; diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c index a055759b6..c857aa14d 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/ppc64/kernel/rtas-proc.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -580,7 +580,7 @@ static void ppc_rtas_process_sensor(struct seq_file *m, } break; case THERMAL_SENSOR: - seq_printf(m, "Temp. (°C/°F):\t"); + seq_printf(m, "Temp. (C/F):\t"); temperature = 1; break; case LID_STATUS: diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c index 438d258dc..0eb8956a7 100644 --- a/arch/ppc64/kernel/rtas.c +++ b/arch/ppc64/kernel/rtas.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -37,17 +36,22 @@ struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED }; +EXPORT_SYMBOL(rtas); + char rtas_err_buf[RTAS_ERROR_LOG_MAX]; spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED; char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned; +unsigned long rtas_rmo_buf; void -call_rtas_display_status(char c) +call_rtas_display_status(unsigned char c) { struct rtas_args *args = &rtas.args; unsigned long s; + if (!rtas.base) + return; spin_lock_irqsave(&rtas.lock, s); args->token = 10; @@ -61,6 +65,31 @@ call_rtas_display_status(char c) spin_unlock_irqrestore(&rtas.lock, s); } +void +call_rtas_display_status_delay(unsigned char c) +{ + static int pending_newline = 0; /* did last write end with unprinted newline? */ + static int width = 16; + + if (c == '\n') { + while (width-- > 0) + call_rtas_display_status(' '); + width = 16; + udelay(500000); + pending_newline = 1; + } else { + if (pending_newline) { + call_rtas_display_status('\r'); + call_rtas_display_status('\n'); + } + pending_newline = 0; + if (width--) { + call_rtas_display_status(c); + udelay(10000); + } + } +} + int rtas_token(const char *service) { @@ -73,6 +102,26 @@ rtas_token(const char *service) return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } +/* + * Return the firmware-specified size of the error log buffer + * for all rtas calls that require an error buffer argument. + * This includes 'check-exception' and 'rtas-last-error'. + */ +int rtas_get_error_log_max(void) +{ + static int rtas_error_log_max; + if (rtas_error_log_max) + return rtas_error_log_max; + + rtas_error_log_max = rtas_token ("rtas-error-log-max"); + if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) || + (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) { + printk (KERN_WARNING "RTAS: bad log buffer size %d\n", rtas_error_log_max); + rtas_error_log_max = RTAS_ERROR_LOG_MAX; + } + return rtas_error_log_max; +} + /** Return a copy of the detailed error text associated with the * most recent failed call to rtas. Because the error text @@ -84,28 +133,27 @@ static int __fetch_rtas_last_error(void) { struct rtas_args err_args, save_args; + u32 bufsz; + + bufsz = rtas_get_error_log_max(); err_args.token = rtas_token("rtas-last-error"); err_args.nargs = 2; err_args.nret = 1; - err_args.rets = (rtas_arg_t *)&(err_args.args[2]); err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf); - err_args.args[1] = RTAS_ERROR_LOG_MAX; + err_args.args[1] = bufsz; err_args.args[2] = 0; save_args = rtas.args; rtas.args = err_args; - PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", - __pa(&err_args)); enter_rtas(__pa(&rtas.args)); - PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); err_args = rtas.args; rtas.args = save_args; - return err_args.rets[0]; + return err_args.args[2]; } int rtas_call(int token, int nargs, int nret, int *outputs, ...) @@ -165,9 +213,12 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) /* Log the error in the unlikely case that there was one. */ if (unlikely(logit)) { - buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC); - if (buff_copy) { - memcpy(buff_copy, rtas_err_buf, RTAS_ERROR_LOG_MAX); + buff_copy = rtas_err_buf; + if (mem_init_done) { + buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC); + if (buff_copy) + memcpy(buff_copy, rtas_err_buf, + RTAS_ERROR_LOG_MAX); } } @@ -176,7 +227,8 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) if (buff_copy) { log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); - kfree(buff_copy); + if (mem_init_done) + kfree(buff_copy); } return ret; } @@ -403,6 +455,9 @@ void rtas_os_term(char *str) { int status; + if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term")) + return; + snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str); do { @@ -417,7 +472,6 @@ void rtas_os_term(char *str) } while (status == RTAS_BUSY); } -unsigned long rtas_rmo_buf = 0; asmlinkage int ppc_rtas(struct rtas_args __user *uargs) { @@ -481,7 +535,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) return 0; } -#ifdef CONFIG_HOTPLUG_CPU /* This version can't take the spinlock, because it never returns */ struct rtas_args rtas_stop_self_args = { @@ -506,7 +559,53 @@ void rtas_stop_self(void) panic("Alas, I survived.\n"); } + +/* + * Call early during boot, before mem init or bootmem, to retreive the RTAS + * informations from the device-tree and allocate the RMO buffer for userland + * accesses. + */ +void __init rtas_initialize(void) +{ + /* Get RTAS dev node and fill up our "rtas" structure with infos + * about it. + */ + rtas.dev = of_find_node_by_name(NULL, "rtas"); + if (rtas.dev) { + u32 *basep, *entryp; + u32 *sizep; + + basep = (u32 *)get_property(rtas.dev, "linux,rtas-base", NULL); + sizep = (u32 *)get_property(rtas.dev, "rtas-size", NULL); + if (basep != NULL && sizep != NULL) { + rtas.base = *basep; + rtas.size = *sizep; + entryp = (u32 *)get_property(rtas.dev, "linux,rtas-entry", NULL); + if (entryp == NULL) /* Ugh */ + rtas.entry = rtas.base; + else + rtas.entry = *entryp; + } else + rtas.dev = NULL; + } + /* If RTAS was found, allocate the RMO buffer for it and look for + * the stop-self token if any + */ + if (rtas.dev) { + unsigned long rtas_region = RTAS_INSTANTIATE_MAX; + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); + + rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, + rtas_region); + +#ifdef CONFIG_HOTPLUG_CPU + rtas_stop_self_args.token = rtas_token("stop-self"); #endif /* CONFIG_HOTPLUG_CPU */ + } + +} + EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); @@ -518,3 +617,4 @@ EXPORT_SYMBOL(rtas_get_sensor); EXPORT_SYMBOL(rtas_get_power_level); EXPORT_SYMBOL(rtas_set_power_level); EXPORT_SYMBOL(rtas_set_indicator); +EXPORT_SYMBOL(rtas_get_error_log_max); diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c index aac9e9609..b43b8e4c0 100644 --- a/arch/ppc64/kernel/rtas_flash.c +++ b/arch/ppc64/kernel/rtas_flash.c @@ -562,6 +562,7 @@ static int validate_flash_release(struct inode *inode, struct file *file) validate_flash(args_buf); } + /* The matching atomic_inc was in rtas_excl_open() */ atomic_dec(&dp->count); return 0; @@ -572,7 +573,8 @@ static void remove_flash_pde(struct proc_dir_entry *dp) if (dp) { if (dp->data != NULL) kfree(dp->data); - remove_proc_entry(dp->name, NULL); + dp->owner = NULL; + remove_proc_entry(dp->name, dp->parent); } } diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c index 7538cea27..536f04970 100644 --- a/arch/ppc64/kernel/rtasd.c +++ b/arch/ppc64/kernel/rtasd.c @@ -46,7 +46,9 @@ static unsigned int rtas_event_scan_rate; static unsigned int rtas_error_log_max; static unsigned int rtas_error_log_buffer_max; -extern volatile int no_more_logging; +static int full_rtas_msgs = 0; + +extern int no_logging; volatile int error_log_cnt = 0; @@ -57,6 +59,37 @@ volatile int error_log_cnt = 0; */ static unsigned char logdata[RTAS_ERROR_LOG_MAX]; +static int get_eventscan_parms(void); + +static char *rtas_type[] = { + "Unknown", "Retry", "TCE Error", "Internal Device Failure", + "Timeout", "Data Parity", "Address Parity", "Cache Parity", + "Address Invalid", "ECC Uncorrected", "ECC Corrupted", +}; + +static char *rtas_event_type(int type) +{ + if ((type > 0) && (type < 11)) + return rtas_type[type]; + + switch (type) { + case RTAS_TYPE_EPOW: + return "EPOW"; + case RTAS_TYPE_PLATFORM: + return "Platform Error"; + case RTAS_TYPE_IO: + return "I/O Event"; + case RTAS_TYPE_INFO: + return "Platform Information Event"; + case RTAS_TYPE_DEALLOC: + return "Resource Deallocation Event"; + case RTAS_TYPE_DUMP: + return "Dump Notification Event"; + } + + return rtas_type[0]; +} + /* To see this info, grep RTAS /var/log/messages and each entry * will be collected together with obvious begin/end. * There will be a unique identifier on the begin and end lines. @@ -73,38 +106,48 @@ static unsigned char logdata[RTAS_ERROR_LOG_MAX]; static void printk_log_rtas(char *buf, int len) { - int i,j,n; + int i,j,n = 0; int perline = 16; char buffer[64]; char * str = "RTAS event"; - printk(RTAS_DEBUG "%d -------- %s begin --------\n", error_log_cnt, str); - - /* - * Print perline bytes on each line, each line will start - * with RTAS and a changing number, so syslogd will - * print lines that are otherwise the same. Separate every - * 4 bytes with a space. - */ - for (i=0; i < len; i++) { - j = i % perline; - if (j == 0) { - memset(buffer, 0, sizeof(buffer)); - n = sprintf(buffer, "RTAS %d:", i/perline); + if (full_rtas_msgs) { + printk(RTAS_DEBUG "%d -------- %s begin --------\n", + error_log_cnt, str); + + /* + * Print perline bytes on each line, each line will start + * with RTAS and a changing number, so syslogd will + * print lines that are otherwise the same. Separate every + * 4 bytes with a space. + */ + for (i = 0; i < len; i++) { + j = i % perline; + if (j == 0) { + memset(buffer, 0, sizeof(buffer)); + n = sprintf(buffer, "RTAS %d:", i/perline); + } + + if ((i % 4) == 0) + n += sprintf(buffer+n, " "); + + n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); + + if (j == (perline-1)) + printk(KERN_DEBUG "%s\n", buffer); } + if ((i % perline) != 0) + printk(KERN_DEBUG "%s\n", buffer); - if ((i % 4) == 0) - n += sprintf(buffer+n, " "); - - n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); + printk(RTAS_DEBUG "%d -------- %s end ----------\n", + error_log_cnt, str); + } else { + struct rtas_error_log *errlog = (struct rtas_error_log *)buf; - if (j == (perline-1)) - printk(KERN_DEBUG "%s\n", buffer); + printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", + error_log_cnt, rtas_event_type(errlog->type), + errlog->severity); } - if ((i % perline) != 0) - printk(KERN_DEBUG "%s\n", buffer); - - printk(RTAS_DEBUG "%d -------- %s end ----------\n", error_log_cnt, str); } static int log_rtas_len(char * buf) @@ -121,6 +164,9 @@ static int log_rtas_len(char * buf) len += err->extended_log_length; } + if (rtas_error_log_max == 0) { + get_eventscan_parms(); + } if (len > rtas_error_log_max) len = rtas_error_log_max; @@ -148,7 +194,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) int len = 0; DEBUG("logging event\n"); - if (buf == NULL) return; @@ -168,12 +213,20 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) } /* Write error to NVRAM */ - if (!no_more_logging && !(err_type & ERR_FLAG_BOOT)) + if (!no_logging && !(err_type & ERR_FLAG_BOOT)) nvram_write_error_log(buf, len, err_type); + /* + * rtas errors can occur during boot, and we do want to capture + * those somewhere, even if nvram isn't ready (why not?), and even + * if rtasd isn't ready. Put them into the boot log, at least. + */ + if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG) + printk_log_rtas(buf, len); + /* Check to see if we need to or have stopped logging */ - if (fatal || no_more_logging) { - no_more_logging = 1; + if (fatal || no_logging) { + no_logging = 1; spin_unlock_irqrestore(&rtasd_log_lock, s); return; } @@ -181,9 +234,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) /* call type specific method for error */ switch (err_type & ERR_TYPE_MASK) { case ERR_TYPE_RTAS_LOG: - /* put into syslog and error_log file */ - printk_log_rtas(buf, len); - offset = rtas_error_log_buffer_max * ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); @@ -225,7 +275,7 @@ static int rtas_log_release(struct inode * inode, struct file * file) * know that we can safely clear the events in NVRAM. * Next we'll sit and wait for something else to log. */ -static ssize_t rtas_log_read(struct file * file, char * buf, +static ssize_t rtas_log_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { int error; @@ -249,7 +299,7 @@ static ssize_t rtas_log_read(struct file * file, char * buf, spin_lock_irqsave(&rtasd_log_lock, s); /* if it's 0, then we know we got the last one (the one in NVRAM) */ - if (rtas_log_size == 0 && !no_more_logging) + if (rtas_log_size == 0 && !no_logging) nvram_clear_error_log(); spin_unlock_irqrestore(&rtasd_log_lock, s); @@ -291,15 +341,18 @@ static int enable_surveillance(int timeout) { int error; - error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, - SURVEILLANCE_TOKEN, 0, timeout); + error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout); - if (error) { - printk(KERN_ERR "rtasd: could not enable surveillance\n"); - return -1; + if (error == 0) + return 0; + + if (error == RTAS_NO_SUCH_INDICATOR) { + printk(KERN_INFO "rtasd: surveillance not supported\n"); + return 0; } - return 0; + printk(KERN_ERR "rtasd: could not update surveillance\n"); + return -1; } static int get_eventscan_parms(void) @@ -318,21 +371,8 @@ static int get_eventscan_parms(void) rtas_event_scan_rate = *ip; DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate); - ip = (int *)get_property(node, "rtas-error-log-max", NULL); - if (ip == NULL) { - printk(KERN_ERR "rtasd: no rtas-error-log-max\n"); - of_node_put(node); - return -1; - } - rtas_error_log_max = *ip; - DEBUG("rtas-error-log-max %d\n", rtas_error_log_max); - - if (rtas_error_log_max > RTAS_ERROR_LOG_MAX) { - printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX); - rtas_error_log_max = RTAS_ERROR_LOG_MAX; - } - /* Make room for the sequence number */ + rtas_error_log_max = rtas_get_error_log_max(); rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); of_node_put(node); @@ -377,9 +417,6 @@ static int rtasd(void *unused) goto error; } - /* We can use rtas_log_buf now */ - no_more_logging = 0; - printk(KERN_ERR "RTAS daemon started\n"); DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); @@ -388,6 +425,10 @@ static int rtasd(void *unused) memset(logdata, 0, rtas_error_log_max); rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type); + + /* We can use rtas_log_buf now */ + no_logging = 0; + if (!rc) { if (err_type != ERR_FLAG_ALREADY_LOGGED) { pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); @@ -473,5 +514,15 @@ static int __init surveillance_setup(char *str) return 1; } +static int __init rtasmsgs_setup(char *str) +{ + if (strcmp(str, "on") == 0) + full_rtas_msgs = 1; + else if (strcmp(str, "off") == 0) + full_rtas_msgs = 0; + + return 1; +} __initcall(rtas_init); __setup("surveillance=", surveillance_setup); +__setup("rtasmsgs=", rtasmsgs_setup); diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 7bf41f3ca..f941278bd 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c @@ -34,8 +34,8 @@ #include #include #include +#include -#include #include #include #include @@ -185,11 +185,10 @@ static struct file_operations rtc_fops = { .release = rtc_release, }; -static struct miscdevice rtc_dev= -{ - RTC_MINOR, - "rtc", - &rtc_fops +static struct miscdevice rtc_dev = { + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops }; static int __init rtc_init(void) @@ -201,9 +200,11 @@ static int __init rtc_init(void) return retval; #ifdef CONFIG_PROC_FS - if (create_proc_read_entry ("driver/rtc", 0, NULL, rtc_read_proc, NULL) == NULL) + if (create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL) + == NULL) { misc_deregister(&rtc_dev); return -ENOMEM; + } #endif printk(KERN_INFO "i/pSeries Real Time Clock Driver v" RTC_VERSION "\n"); @@ -275,7 +276,7 @@ void iSeries_get_rtc_time(struct rtc_time *rtc_tm) if (piranha_simulator) return; - mf_getRtc(rtc_tm); + mf_get_rtc(rtc_tm); rtc_tm->tm_mon--; } @@ -285,7 +286,7 @@ void iSeries_get_rtc_time(struct rtc_time *rtc_tm) */ int iSeries_set_rtc_time(struct rtc_time *tm) { - mf_setRtc(tm); + mf_set_rtc(tm); return 0; } @@ -356,7 +357,7 @@ void pSeries_get_boot_time(struct rtc_time *rtc_tm) } } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); - if (error != 0) { + if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", error); return; @@ -384,7 +385,7 @@ void pSeries_get_rtc_time(struct rtc_time *rtc_tm) do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { - if (in_interrupt()) { + if (in_interrupt() && printk_ratelimit()) { printk(KERN_WARNING "error: reading clock would delay interrupt\n"); return; /* delay not allowed */ } @@ -395,7 +396,7 @@ void pSeries_get_rtc_time(struct rtc_time *rtc_tm) } } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); - if (error != 0) { + if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", error); return; @@ -430,7 +431,7 @@ int pSeries_set_rtc_time(struct rtc_time *tm) } } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); - if (error != 0) + if (error != 0 && printk_ratelimit()) printk(KERN_WARNING "error: setting the clock failed (%d)\n", error); diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index dc090d425..abb144118 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c @@ -10,6 +10,8 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include @@ -27,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -47,60 +52,86 @@ #include #include #include +#include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +/* + * Here are some early debugging facilities. You can enable one + * but your kernel will not boot on anything else if you do so + */ + +/* This one is for use on LPAR machines that support an HVC console + * on vterm 0 + */ +extern void udbg_init_debug_lpar(void); +/* This one is for use on Apple G5 machines + */ +extern void udbg_init_pmac_realmode(void); +/* That's RTAS panel debug */ +extern void call_rtas_display_status_delay(unsigned char c); +/* Here's maple real mode debug */ +extern void udbg_init_maple_realmode(void); + +#define EARLY_DEBUG_INIT() do {} while(0) + +#if 0 +#define EARLY_DEBUG_INIT() udbg_init_debug_lpar() +#define EARLY_DEBUG_INIT() udbg_init_maple_realmode() +#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode() +#define EARLY_DEBUG_INIT() \ + do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0) +#endif -extern unsigned long klimit; /* extern void *stab; */ extern HTAB htab_data; -extern unsigned long loops_per_jiffy; - -int have_of = 1; +extern unsigned long klimit; -extern void chrp_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void pmac_init(unsigned long r3, - unsigned long r4, - unsigned long r5, - unsigned long r6, - unsigned long r7); - -extern void iSeries_init( void ); -extern void iSeries_init_early( void ); -extern void pSeries_init_early( void ); -extern void pSeriesLP_init_early(void); -extern void pmac_init_early(void); -extern void mm_init_ppc64( void ); -extern void pseries_secondary_smp_init(unsigned long); +extern void mm_init_ppc64(void); extern int idle_setup(void); -extern void vpa_init(int cpu); +extern void stab_initialize(unsigned long stab); +extern void htab_initialize(void); +extern void early_init_devtree(void *flat_dt); +extern void unflatten_device_tree(void); + +extern void smp_release_cpus(void); unsigned long decr_overclock = 1; unsigned long decr_overclock_proc0 = 1; unsigned long decr_overclock_set = 0; unsigned long decr_overclock_proc0_set = 0; -int powersave_nap; +int have_of = 1; +int boot_cpuid = 0; +int boot_cpuid_phys = 0; +dev_t boot_dev; -unsigned char aux_device_present; +/* + * These are used in binfmt_elf.c to put aux entries on the stack + * for each elf executable being started. + */ +int dcache_bsize; +int icache_bsize; +int ucache_bsize; -void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7); -int parse_bootinfo(void); +/* The main machine-dep calls structure + */ +struct machdep_calls ppc_md; #ifdef CONFIG_MAGIC_SYSRQ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ -struct machdep_calls ppc_md; static int ppc64_panic_event(struct notifier_block *, unsigned long, void *); - static struct notifier_block ppc64_panic_block = { - notifier_call: ppc64_panic_event, - priority: INT_MIN /* may not return; must be done last */ + .notifier_call = ppc64_panic_event, + .priority = INT_MIN /* may not return; must be done last */ }; /* @@ -112,42 +143,32 @@ static struct notifier_block ppc64_panic_block = { * these processors use on existing boards. -- Dan */ struct screen_info screen_info = { - 0, 25, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 80, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 25, /* orig-video-lines */ - 1, /* orig-video-isVGA */ - 16 /* orig-video-points */ + .orig_x = 0, + .orig_y = 25, + .orig_video_cols = 80, + .orig_video_lines = 25, + .orig_video_isVGA = 1, + .orig_video_points = 16 }; -/* - * These are used in binfmt_elf.c to put aux entries on the stack - * for each elf executable being started. - */ -int dcache_bsize; -int icache_bsize; -int ucache_bsize; - /* * Initialize the PPCDBG state. Called before relocation has been enabled. */ -void ppcdbg_initialize(void) { - unsigned long offset = reloc_offset(); - struct naca_struct *_naca = RELOC(naca); - - _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; +void __init ppcdbg_initialize(void) +{ + naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */ + /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; } +/* + * Early boot console based on udbg + */ static struct console udbg_console = { .name = "udbg", .write = udbg_console_write, .flags = CON_PRINTBUFFER, .index = -1, }; - static int early_console_initialized; void __init disable_early_printk(void) @@ -158,111 +179,479 @@ void __init disable_early_printk(void) early_console_initialized = 0; } -/* - * Do some initial setup of the system. The parameters are those which - * were passed in from the bootloader. +#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) + +static int smt_enabled_cmdline; + +/* Look for ibm,smt-enabled OF option */ +static void check_smt_enabled(void) +{ + struct device_node *dn; + char *smt_option; + + /* Allow the command line to overrule the OF option */ + if (smt_enabled_cmdline) + return; + + dn = of_find_node_by_path("/options"); + + if (dn) { + smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL); + + if (smt_option) { + if (!strcmp(smt_option, "on")) + smt_enabled_at_boot = 1; + else if (!strcmp(smt_option, "off")) + smt_enabled_at_boot = 0; + } + } +} + +/* Look for smt-enabled= cmdline option */ +static int __init early_smt_enabled(char *p) +{ + smt_enabled_cmdline = 1; + + if (!p) + return 0; + + if (!strcmp(p, "on") || !strcmp(p, "1")) + smt_enabled_at_boot = 1; + else if (!strcmp(p, "off") || !strcmp(p, "0")) + smt_enabled_at_boot = 0; + + return 0; +} +early_param("smt-enabled", early_smt_enabled); + +/** + * setup_cpu_maps - initialize the following cpu maps: + * cpu_possible_map + * cpu_present_map + * cpu_sibling_map + * + * Having the possible map set up early allows us to restrict allocations + * of things like irqstacks to num_possible_cpus() rather than NR_CPUS. + * + * We do not initialize the online map here; cpus set their own bits in + * cpu_online_map as they come up. + * + * This function is valid only for Open Firmware systems. finish_device_tree + * must be called before using this. + * + * While we're here, we may as well set the "physical" cpu ids in the paca. */ -void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +static void __init setup_cpu_maps(void) { -#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES) - int ret, i; -#endif + struct device_node *dn = NULL; + int cpu = 0; + int swap_cpuid = 0; + + check_smt_enabled(); + + while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { + u32 *intserv; + int j, len = sizeof(u32), nthreads; + + intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s", + &len); + if (!intserv) + intserv = (u32 *)get_property(dn, "reg", NULL); + + nthreads = len / sizeof(u32); + + for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { + /* + * Only spin up secondary threads if SMT is enabled. + * We must leave space in the logical map for the + * threads. + */ + if (j == 0 || smt_enabled_at_boot) { + cpu_set(cpu, cpu_present_map); + set_hard_smp_processor_id(cpu, intserv[j]); + } + if (intserv[j] == boot_cpuid_phys) + swap_cpuid = cpu; + cpu_set(cpu, cpu_possible_map); + cpu++; + } + } -#ifdef CONFIG_XMON_DEFAULT - xmon_init(); -#endif + /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that + * boot cpu is logical 0. + */ + if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { + u32 tmp; + tmp = get_hard_smp_processor_id(0); + set_hard_smp_processor_id(0, boot_cpuid_phys); + set_hard_smp_processor_id(swap_cpuid, tmp); + } -#ifdef CONFIG_PPC_ISERIES - /* pSeries systems are identified in prom.c via OF. */ - if ( itLpNaca.xLparInstalled == 1 ) - systemcfg->platform = PLATFORM_ISERIES_LPAR; -#endif - - switch (systemcfg->platform) { -#ifdef CONFIG_PPC_ISERIES - case PLATFORM_ISERIES_LPAR: - iSeries_init_early(); - break; -#endif + /* + * On pSeries LPAR, we need to know how many cpus + * could possibly be added to this partition. + */ + if (systemcfg->platform == PLATFORM_PSERIES_LPAR && + (dn = of_find_node_by_path("/rtas"))) { + int num_addr_cell, num_size_cell, maxcpus; + unsigned int *ireg; + + num_addr_cell = prom_n_addr_cells(dn); + num_size_cell = prom_n_size_cells(dn); + + ireg = (unsigned int *) + get_property(dn, "ibm,lrdr-capacity", NULL); + + if (!ireg) + goto out; + + maxcpus = ireg[num_addr_cell + num_size_cell]; + + /* Double maxcpus for processors which have SMT capability */ + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + maxcpus *= 2; + + if (maxcpus > NR_CPUS) { + printk(KERN_WARNING + "Partition configured for %d cpus, " + "operating system maximum is %d.\n", + maxcpus, NR_CPUS); + maxcpus = NR_CPUS; + } else + printk(KERN_INFO "Partition configured for %d cpus.\n", + maxcpus); + + for (cpu = 0; cpu < maxcpus; cpu++) + cpu_set(cpu, cpu_possible_map); + out: + of_node_put(dn); + } + + /* + * Do the sibling map; assume only two threads per processor. + */ + for_each_cpu(cpu) { + cpu_set(cpu, cpu_sibling_map[cpu]); + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); + } + + systemcfg->processorCount = num_present_cpus(); +} +#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */ + + +#ifdef CONFIG_PPC_MULTIPLATFORM +extern struct machdep_calls pSeries_md; +extern struct machdep_calls pmac_md; +extern struct machdep_calls maple_md; + +/* Ultimately, stuff them in an elf section like initcalls... */ +static struct machdep_calls __initdata *machines[] = { #ifdef CONFIG_PPC_PSERIES - case PLATFORM_PSERIES: - pSeries_init_early(); - parse_bootinfo(); - break; - - case PLATFORM_PSERIES_LPAR: - pSeriesLP_init_early(); - parse_bootinfo(); - break; + &pSeries_md, #endif /* CONFIG_PPC_PSERIES */ #ifdef CONFIG_PPC_PMAC - case PLATFORM_POWERMAC: - pmac_init_early(); - parse_bootinfo(); + &pmac_md, #endif /* CONFIG_PPC_PMAC */ +#ifdef CONFIG_PPC_MAPLE + &maple_md, +#endif /* CONFIG_PPC_MAPLE */ + NULL +}; + +/* + * Early initialization entry point. This is called by head.S + * with MMU translation disabled. We rely on the "feature" of + * the CPU that ignores the top 2 bits of the address in real + * mode so we can access kernel globals normally provided we + * only toy with things in the RMO region. From here, we do + * some early parsing of the device-tree to setup out LMB + * data structures, and allocate & initialize the hash table + * and segment tables so we can start running with translation + * enabled. + * + * It is this function which will call the probe() callback of + * the various platform types and copy the matching one to the + * global ppc_md structure. Your platform can eventually do + * some very early initializations from the probe() routine, but + * this is not recommended, be very careful as, for example, the + * device-tree is not accessible via normal means at this point. + */ + +void __init early_setup(unsigned long dt_ptr) +{ + struct paca_struct *lpaca = get_paca(); + static struct machdep_calls **mach; + + /* + * Enable early debugging if any specified (see top of + * this file) + */ + EARLY_DEBUG_INIT(); + + DBG(" -> early_setup()\n"); + + /* + * Fill the default DBG level in naca (do we want to keep + * that old mecanism around forever ?) + */ + ppcdbg_initialize(); + + /* + * Do early initializations using the flattened device + * tree, like retreiving the physical memory map or + * calculating/retreiving the hash table size + */ + early_init_devtree(__va(dt_ptr)); + + /* + * Iterate all ppc_md structures until we find the proper + * one for the current machine type + */ + DBG("Probing machine type for platform %x...\n", + systemcfg->platform); + + for (mach = machines; *mach; mach++) { + if ((*mach)->probe(systemcfg->platform)) + break; + } + /* What can we do if we didn't find ? */ + if (*mach == NULL) { + DBG("No suitable machine found !\n"); + for (;;); + } + ppc_md = **mach; + + /* our udbg callbacks got overriden by the above, let's put them + * back in. Ultimately, I want those things to be split from the + * main ppc_md + */ + EARLY_DEBUG_INIT(); + + DBG("Found, Initializing memory management...\n"); + + /* + * Initialize stab / SLB management + */ + stab_initialize(lpaca->stab_real); + + /* + * Initialize the MMU Hash table and create the linear mapping + * of memory + */ + htab_initialize(); + + DBG(" <- early_setup()\n"); +} + + +/* + * Initialize some remaining members of the naca and systemcfg structures + * (at least until we get rid of them completely). This is mostly some + * cache informations about the CPU that will be used by cache flush + * routines and/or provided to userland + */ +static void __init initialize_naca(void) +{ + struct device_node *np; + unsigned long num_cpus = 0; + + DBG(" -> initialize_naca()\n"); + + for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) { + num_cpus += 1; + + /* We're assuming *all* of the CPUs have the same + * d-cache and i-cache sizes... -Peter + */ + + if ( num_cpus == 1 ) { + u32 *sizep, *lsizep; + u32 size, lsize; + const char *dc, *ic; + + /* Then read cache informations */ + if (systemcfg->platform == PLATFORM_POWERMAC) { + dc = "d-cache-block-size"; + ic = "i-cache-block-size"; + } else { + dc = "d-cache-line-size"; + ic = "i-cache-line-size"; + } + + size = 0; + lsize = cur_cpu_spec->dcache_bsize; + sizep = (u32 *)get_property(np, "d-cache-size", NULL); + if (sizep != NULL) + size = *sizep; + lsizep = (u32 *) get_property(np, dc, NULL); + if (lsizep != NULL) + lsize = *lsizep; + + if (sizep == 0 || lsizep == 0) + DBG("Argh, can't find dcache properties ! " + "sizep: %p, lsizep: %p\n", sizep, lsizep); + + systemcfg->dCacheL1Size = size; + systemcfg->dCacheL1LineSize = lsize; + naca->dCacheL1LogLineSize = __ilog2(lsize); + naca->dCacheL1LinesPerPage = PAGE_SIZE/(lsize); + + size = 0; + lsize = cur_cpu_spec->icache_bsize; + sizep = (u32 *)get_property(np, "i-cache-size", NULL); + if (sizep != NULL) + size = *sizep; + lsizep = (u32 *)get_property(np, ic, NULL); + if (lsizep != NULL) + lsize = *lsizep; + if (sizep == 0 || lsizep == 0) + DBG("Argh, can't find icache properties ! " + "sizep: %p, lsizep: %p\n", sizep, lsizep); + + systemcfg->iCacheL1Size = size; + systemcfg->iCacheL1LineSize = lsize; + naca->iCacheL1LogLineSize = __ilog2(lsize); + naca->iCacheL1LinesPerPage = PAGE_SIZE/(lsize); + + } + } + + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); + systemcfg->version.major = SYSTEMCFG_MAJOR; + systemcfg->version.minor = SYSTEMCFG_MINOR; + systemcfg->processor = mfspr(SPRN_PVR); + + DBG(" <- initialize_naca()\n"); +} + +static void __init check_for_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + u64 *prop; + + DBG(" -> check_for_initrd()\n"); + + prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL); + if (prop != NULL) { + initrd_start = (unsigned long)__va(*prop); + prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL); + if (prop != NULL) { + initrd_end = (unsigned long)__va(*prop); + initrd_below_start_ok = 1; + } else + initrd_start = 0; } /* If we were passed an initrd, set the ROOT_DEV properly if the values * look sensible. If not, clear initrd reference. */ -#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && initrd_end > initrd_start) ROOT_DEV = Root_RAM0; else initrd_start = initrd_end = 0; + + if (initrd_start) + printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end); + + DBG(" <- check_for_initrd()\n"); #endif /* CONFIG_BLK_DEV_INITRD */ +} -#ifdef CONFIG_BOOTX_TEXT - map_boot_text(); - if (systemcfg->platform == PLATFORM_POWERMAC) { - early_console_initialized = 1; - register_console(&udbg_console); - } -#endif /* CONFIG_BOOTX_TEXT */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ -#ifdef CONFIG_PPC_PSERIES - if (systemcfg->platform & PLATFORM_PSERIES) { - early_console_initialized = 1; - register_console(&udbg_console); - __irq_offset_value = NUM_ISA_INTERRUPTS; - finish_device_tree(); - chrp_init(r3, r4, r5, r6, r7); +/* + * Do some initial setup of the system. The parameters are those which + * were passed in from the bootloader. + */ +void __init setup_system(void) +{ + DBG(" -> setup_system()\n"); -#ifdef CONFIG_SMP - /* Start secondary threads on SMT systems */ - for (i = 0; i < NR_CPUS; i++) { - if (cpu_available(i) && !cpu_possible(i)) { - printk("%16.16x : starting thread\n", i); - rtas_call(rtas_token("start-cpu"), 3, 1, &ret, - get_hard_smp_processor_id(i), - (u32)*((unsigned long *)pseries_secondary_smp_init), - i); - cpu_set(i, cpu_possible_map); - systemcfg->processorCount++; - } - } -#endif /* CONFIG_SMP */ - } +#ifdef CONFIG_PPC_ISERIES + /* pSeries systems are identified in prom.c via OF. */ + if (itLpNaca.xLparInstalled == 1) + systemcfg->platform = PLATFORM_ISERIES_LPAR; + + ppc_md.init_early(); +#else /* CONFIG_PPC_ISERIES */ + + /* + * Unflatten the device-tree passed by prom_init or kexec + */ + unflatten_device_tree(); + + /* + * Fill the naca & systemcfg structures with informations + * retreived from the device-tree. Need to be called before + * finish_device_tree() since the later requires some of the + * informations filled up here to properly parse the interrupt + * tree. + * It also sets up the cache line sizes which allows to call + * routines like flush_icache_range (used by the hash init + * later on). + */ + initialize_naca(); + +#ifdef CONFIG_PPC_PSERIES + /* + * Initialize RTAS if available + */ + rtas_initialize(); #endif /* CONFIG_PPC_PSERIES */ -#ifdef CONFIG_PPC_PMAC - if (systemcfg->platform == PLATFORM_POWERMAC) { - finish_device_tree(); - pmac_init(r3, r4, r5, r6, r7); - } -#endif /* CONFIG_PPC_PMAC */ + /* + * Check if we have an initrd provided via the device-tree + */ + check_for_initrd(); -#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_PPC_PMAC) - rtas_stop_self_args.token = rtas_token("stop-self"); -#endif /* CONFIG_HOTPLUG_CPU && !CONFIG_PPC_PMAC */ + /* + * Do some platform specific early initializations, that includes + * setting up the hash table pointers. It also sets up some interrupt-mapping + * related options that will be used by finish_device_tree() + */ + ppc_md.init_early(); - /* Finish initializing the hash table (do the dynamic - * patching for the fast-path hashtable.S code) + /* + * "Finish" the device-tree, that is do the actual parsing of + * some of the properties like the interrupt map */ - htab_finish_init(); + finish_device_tree(); + + /* + * Initialize xmon + */ +#ifdef CONFIG_XMON_DEFAULT + xmon_init(); +#endif + /* + * Register early console + */ + early_console_initialized = 1; + register_console(&udbg_console); + +#endif /* !CONFIG_PPC_ISERIES */ + + /* Save unparsed command line copy for /proc/cmdline */ + strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); + + parse_early_param(); + +#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) + /* + * iSeries has already initialized the cpu maps at this point. + */ + setup_cpu_maps(); + + /* Release secondary cpus out of their spinloops at 0x60 now that + * we can map physical -> logical CPU ids + */ + smp_release_cpus(); +#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */ printk("Starting Linux PPC64 %s\n", UTS_RELEASE); @@ -272,6 +661,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller); printk("systemcfg = 0x%p\n", systemcfg); + printk("systemcfg->platform = 0x%x\n", systemcfg->platform); printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); @@ -282,28 +672,10 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, mm_init_ppc64(); -#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES) - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - vpa_init(boot_cpuid); - } -#endif - - /* Select the correct idle loop for the platform. */ - idle_setup(); - - switch (systemcfg->platform) { -#ifdef CONFIG_PPC_ISERIES - case PLATFORM_ISERIES_LPAR: - iSeries_init(); - break; -#endif - default: - /* The following relies on the device tree being */ - /* fully configured. */ - parse_cmd_line(r3, r4, r5, r6, r7); - } + DBG(" <- setup_system()\n"); } + void machine_restart(char *cmd) { if (ppc_md.nvram_sync) @@ -373,7 +745,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_SMP pvr = per_cpu(pvr, cpu_id); #else - pvr = _get_PVR(); + pvr = mfspr(SPRN_PVR); #endif maj = (pvr >> 8) & 0xFF; min = pvr & 0xFF; @@ -425,76 +797,66 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -/* - * Fetch the cmd_line from open firmware. - */ -void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +#if 0 /* XXX not currently used */ +unsigned long memory_limit; + +static int __init early_parsemem(char *p) { - cmd_line[0] = 0; + if (!p) + return 0; -#ifdef CONFIG_CMDLINE - strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); -#endif /* CONFIG_CMDLINE */ + memory_limit = memparse(p, &p); -#ifdef CONFIG_PPC_PSERIES - { - struct device_node *chosen; - - chosen = of_find_node_by_name(NULL, "chosen"); - if (chosen != NULL) { - char *p; - p = get_property(chosen, "bootargs", NULL); - if (p != NULL && p[0] != 0) - strlcpy(cmd_line, p, sizeof(cmd_line)); - of_node_put(chosen); - } - } -#endif - - /* Look for mem= option on command line */ - if (strstr(cmd_line, "mem=")) { - char *p, *q; - unsigned long maxmem = 0; - extern unsigned long __max_memory; - - for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { - q = p + 4; - if (p > cmd_line && p[-1] != ' ') - continue; - maxmem = simple_strtoul(q, &q, 0); - if (*q == 'k' || *q == 'K') { - maxmem <<= 10; - ++q; - } else if (*q == 'm' || *q == 'M') { - maxmem <<= 20; - ++q; - } - } - __max_memory = maxmem; - } + return 0; } +early_param("mem", early_parsemem); +#endif -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM static int __init set_preferred_console(void) { - struct device_node *prom_stdout; + struct device_node *prom_stdout = NULL; char *name; - int offset; + u32 *spd; + int offset = 0; + + DBG(" -> set_preferred_console()\n"); /* The user has requested a console so this is already set up. */ - if (strstr(saved_command_line, "console=")) + if (strstr(saved_command_line, "console=")) { + DBG(" console was specified !\n"); return -EBUSY; + } - prom_stdout = find_path_device(of_stdout_device); - if (!prom_stdout) + if (!of_chosen) { + DBG(" of_chosen is NULL !\n"); + return -ENODEV; + } + /* We are getting a weird phandle from OF ... */ + /* ... So use the full path instead */ + name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); + if (name == NULL) { + DBG(" no linux,stdout-path !\n"); + return -ENODEV; + } + prom_stdout = of_find_node_by_path(name); + if (!prom_stdout) { + DBG(" can't find stdout package %s !\n", name); return -ENODEV; + } + DBG("stdout is %s\n", prom_stdout->full_name); name = (char *)get_property(prom_stdout, "name", NULL); - if (!name) - return -ENODEV; + if (!name) { + DBG(" stdout package has no name !\n"); + goto not_found; + } + spd = (u32 *)get_property(prom_stdout, "current-speed", NULL); - if (strcmp(name, "serial") == 0) { + if (0) + ; +#ifdef CONFIG_SERIAL_8250_CONSOLE + else if (strcmp(name, "serial") == 0) { int i; u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i); if (i > 8) { @@ -513,76 +875,77 @@ static int __init set_preferred_console(void) break; default: /* We dont recognise the serial port */ - return -ENODEV; + goto not_found; } } - } else if (strcmp(name, "vty") == 0) - /* pSeries LPAR virtual console */ - return add_preferred_console("hvc", 0, NULL); + } +#endif /* CONFIG_SERIAL_8250_CONSOLE */ +#ifdef CONFIG_PPC_PSERIES + else if (strcmp(name, "vty") == 0) { + u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL); + char *compat = (char *)get_property(prom_stdout, "compatible", NULL); + + if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) { + /* Host Virtual Serial Interface */ + int offset; + switch (reg[0]) { + case 0x30000000: + offset = 0; + break; + case 0x30000001: + offset = 1; + break; + default: + goto not_found; + } + of_node_put(prom_stdout); + DBG("Found hvsi console at offset %d\n", offset); + return add_preferred_console("hvsi", offset, NULL); + } else { + /* pSeries LPAR virtual console */ + of_node_put(prom_stdout); + DBG("Found hvc console\n"); + return add_preferred_console("hvc", 0, NULL); + } + } +#endif /* CONFIG_PPC_PSERIES */ +#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE else if (strcmp(name, "ch-a") == 0) offset = 0; else if (strcmp(name, "ch-b") == 0) offset = 1; +#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */ else - return -ENODEV; - - return add_preferred_console("ttyS", offset, NULL); - + goto not_found; + of_node_put(prom_stdout); + + DBG("Found serial console at ttyS%d\n", offset); + + if (spd) { + static char __initdata opt[16]; + sprintf(opt, "%d", *spd); + return add_preferred_console("ttyS", offset, opt); + } else + return add_preferred_console("ttyS", offset, NULL); + + not_found: + DBG("No preferred console found !\n"); + of_node_put(prom_stdout); + return -ENODEV; } console_initcall(set_preferred_console); - -int parse_bootinfo(void) -{ - struct bi_record *rec; - - rec = prom.bi_recs; - - if ( rec == NULL || rec->tag != BI_FIRST ) - return -1; - - for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) { - switch (rec->tag) { - case BI_CMD_LINE: - strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line)); - break; - } - } - - return 0; -} -#endif - -int __init ppc_init(void) -{ - /* clear the progress line */ - ppc_md.progress(" ", 0xffff); - - if (ppc_md.init != NULL) { - ppc_md.init(); - } - return 0; -} - -arch_initcall(ppc_init); - -void __init ppc64_calibrate_delay(void) -{ - loops_per_jiffy = tb_ticks_per_jiffy; - - printk("Calibrating delay loop... %lu.%02lu BogoMips\n", - loops_per_jiffy/(500000/HZ), - loops_per_jiffy/(5000/HZ) % 100); -} - -extern void (*calibrate_delay)(void); +#endif /* CONFIG_PPC_MULTIPLATFORM */ #ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { - int i; + unsigned int i; - /* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */ - for (i = 0; i < NR_CPUS; i++) { + /* + * interrupt stacks must be under 256MB, we cannot afford to take + * SLB misses on them. + */ + for_each_cpu(i) { softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, THREAD_SIZE, 0x10000000)); hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, @@ -593,6 +956,31 @@ static void __init irqstack_early_init(void) #define irqstack_early_init() #endif +/* + * Stack space used when we detect a bad kernel stack pointer, and + * early in SMP boots before relocation is enabled. + */ +static void __init emergency_stack_init(void) +{ + unsigned long limit; + unsigned int i; + + /* + * Emergency stacks must be under 256MB, we cannot afford to take + * SLB misses on them. The ABI also requires them to be 128-byte + * aligned. + * + * Since we use these as temporary stacks during secondary CPU + * bringup, we need to get at them in real mode. This means they + * must also be within the RMO region. + */ + limit = min(0x10000000UL, lmb.rmo_size); + + for_each_cpu(i) + paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128, + limit)) + PAGE_SIZE; +} + /* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until @@ -603,17 +991,9 @@ void __init setup_arch(char **cmdline_p) extern int panic_timeout; extern void do_init_bootmem(void); - calibrate_delay = ppc64_calibrate_delay; - ppc64_boot_msg(0x12, "Setup Arch"); -#ifdef CONFIG_XMON - if (strstr(cmd_line, "xmon")) { - /* ensure xmon is enabled */ - xmon_init(); - debugger(0); - } -#endif /* CONFIG_XMON */ + *cmdline_p = cmd_line; /* * Set cache line size based on type of cpu as a default. @@ -634,21 +1014,22 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long) _edata; init_mm.brk = klimit; - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - *cmdline_p = cmd_line; - irqstack_early_init(); + emergency_stack_init(); /* set up the bootmem stuff with available memory */ do_init_bootmem(); ppc_md.setup_arch(); + /* Select the correct idle loop for the platform. */ + idle_setup(); + paging_init(); ppc64_boot_msg(0x15, "Setup Done"); } + /* ToDo: do something useful if ppc_md is not yet setup. */ #define PPC64_LINUX_FUNCTION 0x0f000000 #define PPC64_IPL_MESSAGE 0xc0000000 @@ -753,3 +1134,211 @@ int set_decr_overclock( char * str ) __setup("spread_lpevents=", set_spread_lpevents ); __setup("decr_overclock_proc0=", set_decr_overclock_proc0 ); __setup("decr_overclock=", set_decr_overclock ); + +#ifndef CONFIG_PPC_ISERIES +/* + * This function can be used by platforms to "find" legacy serial ports. + * It works for "serial" nodes under an "isa" node, and will try to + * respect the "ibm,aix-loc" property if any. It works with up to 8 + * ports. + */ + +#define MAX_LEGACY_SERIAL_PORTS 8 +static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1]; +static unsigned int old_serial_count; + +void __init generic_find_legacy_serial_ports(unsigned int *default_speed) +{ + struct device_node *np; + u32 *sizeprop; + + struct isa_reg_property { + u32 space; + u32 address; + u32 size; + }; + struct pci_reg_property { + struct pci_address addr; + u32 size_hi; + u32 size_lo; + }; + + DBG(" -> generic_find_legacy_serial_port()\n"); + + naca->serialPortAddr = 0; + if (default_speed) + *default_speed = 0; + + np = of_find_node_by_path("/"); + if (!np) + return; + + /* First fill our array */ + for (np = NULL; (np = of_find_node_by_type(np, "serial"));) { + struct device_node *isa, *pci; + struct isa_reg_property *reg; + unsigned long phys_size, addr_size, io_base; + u32 *rangesp; + u32 *interrupts, *clk, *spd; + char *typep; + int index, rlen, rentsize; + + /* Ok, first check if it's under an "isa" parent */ + isa = of_get_parent(np); + if (!isa || strcmp(isa->name, "isa")) { + DBG("%s: no isa parent found\n", np->full_name); + continue; + } + + /* Now look for an "ibm,aix-loc" property that gives us ordering + * if any... + */ + typep = (char *)get_property(np, "ibm,aix-loc", NULL); + + /* Get the ISA port number */ + reg = (struct isa_reg_property *)get_property(np, "reg", NULL); + if (reg == NULL) + goto next_port; + /* We assume the interrupt number isn't translated ... */ + interrupts = (u32 *)get_property(np, "interrupts", NULL); + /* get clock freq. if present */ + clk = (u32 *)get_property(np, "clock-frequency", NULL); + /* get default speed if present */ + spd = (u32 *)get_property(np, "current-speed", NULL); + /* Default to locate at end of array */ + index = old_serial_count; /* end of the array by default */ + + /* If we have a location index, then use it */ + if (typep && *typep == 'S') { + index = simple_strtol(typep+1, NULL, 0) - 1; + /* if index is out of range, use end of array instead */ + if (index >= MAX_LEGACY_SERIAL_PORTS) + index = old_serial_count; + /* if our index is still out of range, that mean that + * array is full, we could scan for a free slot but that + * make little sense to bother, just skip the port + */ + if (index >= MAX_LEGACY_SERIAL_PORTS) + goto next_port; + if (index >= old_serial_count) + old_serial_count = index + 1; + /* Check if there is a port who already claimed our slot */ + if (serial_ports[index].iobase != 0) { + /* if we still have some room, move it, else override */ + if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) { + DBG("Moved legacy port %d -> %d\n", index, + old_serial_count); + serial_ports[old_serial_count++] = + serial_ports[index]; + } else { + DBG("Replacing legacy port %d\n", index); + } + } + } + if (index >= MAX_LEGACY_SERIAL_PORTS) + goto next_port; + if (index >= old_serial_count) + old_serial_count = index + 1; + + /* Now fill the entry */ + memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port)); + serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16; + serial_ports[index].iobase = reg->address; + serial_ports[index].irq = interrupts ? interrupts[0] : 0; + serial_ports[index].flags = ASYNC_BOOT_AUTOCONF; + + DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n", + index, + serial_ports[index].iobase, + serial_ports[index].irq, + serial_ports[index].uartclk); + + /* Get phys address of IO reg for port 1 */ + if (index != 0) + goto next_port; + + pci = of_get_parent(isa); + if (!pci) { + DBG("%s: no pci parent found\n", np->full_name); + goto next_port; + } + + rangesp = (u32 *)get_property(pci, "ranges", &rlen); + if (rangesp == NULL) { + of_node_put(pci); + goto next_port; + } + rlen /= 4; + + /* we need the #size-cells of the PCI bridge node itself */ + phys_size = 1; + sizeprop = (u32 *)get_property(pci, "#size-cells", NULL); + if (sizeprop != NULL) + phys_size = *sizeprop; + /* we need the parent #addr-cells */ + addr_size = prom_n_addr_cells(pci); + rentsize = 3 + addr_size + phys_size; + io_base = 0; + for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) { + if (((rangesp[0] >> 24) & 0x3) != 1) + continue; /* not IO space */ + io_base = rangesp[3]; + if (addr_size == 2) + io_base = (io_base << 32) | rangesp[4]; + } + if (io_base != 0) { + naca->serialPortAddr = io_base + reg->address; + if (default_speed && spd) + *default_speed = *spd; + } + of_node_put(pci); + next_port: + of_node_put(isa); + } + + DBG(" <- generic_find_legacy_serial_port()\n"); +} + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_ports, + }, +}; + +static int __init serial_dev_init(void) +{ + return platform_device_register(&serial_device); +} +arch_initcall(serial_dev_init); + +#endif /* CONFIG_PPC_ISERIES */ + +int check_legacy_ioport(unsigned long base_port) +{ + if (ppc_md.check_legacy_ioport == NULL) + return 0; + return ppc_md.check_legacy_ioport(base_port); +} +EXPORT_SYMBOL(check_legacy_ioport); + +#ifdef CONFIG_XMON +static int __init early_xmon(char *p) +{ + /* ensure xmon is enabled */ + xmon_init(); + debugger(NULL); + + return 0; +} +early_param("xmon", early_xmon); +#endif + +void cpu_die(void) +{ + if (ppc_md.cpu_die) + ppc_md.cpu_die(); + local_irq_disable(); + for (;;); +} diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c index 8323d7355..1e228bdc0 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/ppc64/kernel/signal.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -99,7 +99,7 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal(&saveset, regs)) - return regs->gpr[3]; + return 0; } } @@ -127,7 +127,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, * v_regs pointer or not */ #ifdef CONFIG_ALTIVEC - elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve) & ~0xful); + elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful); #endif long err = 0; @@ -178,8 +178,11 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, elf_vrreg_t __user *v_regs; #endif unsigned long err = 0; - unsigned long save_r13; + unsigned long save_r13 = 0; elf_greg_t *gregs = (elf_greg_t *)regs; +#ifdef CONFIG_ALTIVEC + unsigned long msr; +#endif int i; /* If this is not a signal return, we preserve the TLS in r13 */ @@ -205,13 +208,15 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); + err |= __get_user(msr, &sc->gp_regs[PT_MSR]); if (err) return err; /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ - if (v_regs != 0 && (regs->msr & MSR_VEC) != 0) - err |= __copy_from_user(current->thread.vr, v_regs, 33 * sizeof(vector128)); + if (v_regs != 0 && (msr & MSR_VEC) != 0) + err |= __copy_from_user(current->thread.vr, v_regs, + 33 * sizeof(vector128)); else if (current->thread.used_vr) - memset(¤t->thread.vr, 0, 33); + memset(current->thread.vr, 0, 33 * sizeof(vector128)); /* Always get VRSAVE back */ if (v_regs != 0) err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); @@ -219,6 +224,14 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, current->thread.vrsave = 0; #endif /* CONFIG_ALTIVEC */ +#ifndef CONFIG_SMP + preempt_disable(); + if (last_task_used_math == current) + last_task_used_math = NULL; + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; + preempt_enable(); +#endif /* Force reload of FP/VEC */ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); @@ -371,10 +384,11 @@ badframe: printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", regs, uc, &uc->uc_mcontext); #endif - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); + return 0; } -static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for @@ -420,7 +434,7 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, /* Allocate a dummy caller frame for the signal handler. */ newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; - err |= put_user(0, (unsigned long __user *)newsp); + err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); @@ -439,37 +453,41 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, if (err) goto badframe; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - do_exit(SIGSEGV); + force_sigsegv(signr, current); + return 0; } /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +static int handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - /* Set up Signal Frame */ - setup_rt_frame(sig, ka, info, oldset, regs); + int ret; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + /* Set up Signal Frame */ + ret = setup_rt_frame(sig, ka, info, oldset, regs); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (ret && !(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } - return; + + return ret; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) @@ -512,6 +530,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; int signr; + struct k_sigaction ka; /* * If the current thread is 32 bit - invoke the @@ -523,15 +542,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - struct k_sigaction *ka = ¤t->sighand->action[signr-1]; - /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) - syscall_restart(regs, ka); - handle_signal(signr, ka, &info, oldset, regs); - return 1; + syscall_restart(regs, &ka); + return handle_signal(signr, &ka, &info, oldset, regs); } if (TRAP(regs) == 0x0C00) { /* System Call! */ diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index 106f008af..bdc0d624b 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -189,7 +190,7 @@ static long restore_user_regs(struct pt_regs *regs, elf_greg_t64 *gregs = (elf_greg_t64 *)regs; int i; long err = 0; - unsigned int save_r2; + unsigned int save_r2 = 0; #ifdef CONFIG_ALTIVEC unsigned long msr; #endif @@ -227,13 +228,21 @@ static long restore_user_regs(struct pt_regs *regs, sizeof(sr->mc_vregs))) return 1; } else if (current->thread.used_vr) - memset(¤t->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128)); + memset(current->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128)); /* Always get VRSAVE back */ if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32])) return 1; #endif /* CONFIG_ALTIVEC */ +#ifndef CONFIG_SMP + preempt_disable(); + if (last_task_used_math == current) + last_task_used_math = NULL; + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; + preempt_enable(); +#endif return 0; } @@ -276,14 +285,12 @@ long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, schedule(); if (do_signal32(&saveset, regs)) /* - * If a signal handler needs to be called, - * do_signal32() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal32() doesn't touch - * R3, so it's still set to -EINTR (see above). + * Returning 0 means we return to userspace via + * ret_from_except and thus restore all user + * registers from *regs. This is what we need + * to do when a signal has been delivered. */ - return regs->gpr[3]; + return 0; } } @@ -472,10 +479,14 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s) &d->si_addr); break; case __SI_POLL >> 16: - case __SI_TIMER >> 16: err |= __put_user(s->si_band, &d->si_band); err |= __put_user(s->si_fd, &d->si_fd); break; + case __SI_TIMER >> 16: + err |= __put_user(s->si_tid, &d->si_tid); + err |= __put_user(s->si_overrun, &d->si_overrun); + err |= __put_user(s->si_int, &d->si_int); + break; case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ case __SI_MESGQ >> 16: err |= __put_user(s->si_int, &d->si_int); @@ -575,14 +586,12 @@ int sys32_rt_sigsuspend(compat_sigset_t __user * unewset, size_t sigsetsize, int schedule(); if (do_signal32(&saveset, regs)) /* - * If a signal handler needs to be called, - * do_signal32() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal32() doesn't touch - * R3, so it's still set to -EINTR (see above). + * Returning 0 means we return to userspace via + * ret_from_except and thus restore all user + * registers from *regs. This is what we need + * to do when a signal has been delivered. */ - return regs->gpr[3]; + return 0; } } @@ -641,9 +650,9 @@ int sys32_sigaltstack(u32 __new, u32 __old, int r5, * Set up a signal frame for a "real-time" signal handler * (one which gets siginfo). */ -static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long newsp) +static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, unsigned long newsp) { struct rt_sigframe32 __user *rt_sf; struct mcontext32 __user *frame; @@ -692,16 +701,18 @@ static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, regs->trap = 0; regs->result = 0; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); + return 0; } static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig) @@ -812,7 +823,7 @@ long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, /* * OK, we're invoking a handler */ -static void handle_signal32(unsigned long sig, struct k_sigaction *ka, +static int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, unsigned long newsp) { @@ -857,16 +868,18 @@ static void handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->trap = 0; regs->result = 0; - return; + if (test_thread_flag(TIF_SINGLESTEP)) + ptrace_notify(SIGTRAP); + + return 1; badframe: #if DEBUG_SIG printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n", regs, frame, *newspp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); + return 0; } /* @@ -928,18 +941,16 @@ badframe: int do_signal32(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; unsigned int frame, newsp; int signr, ret; + struct k_sigaction ka; if (!oldset) oldset = ¤t->blocked; newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); - - ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ @@ -950,7 +961,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) if (signr > 0 && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK || (ret == ERESTARTSYS - && !(ka->sa.sa_flags & SA_RESTART)))) { + && !(ka.sa.sa_flags & SA_RESTART)))) { /* make the system call return an EINTR error */ regs->result = -EINTR; regs->gpr[3] = EINTR; @@ -969,7 +980,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) if (signr == 0) return 0; /* no signals delivered */ - if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && (!on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); else @@ -977,21 +988,19 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) newsp &= ~0xfUL; /* Whee! Actually deliver the signal. */ - if (ka->sa.sa_flags & SA_SIGINFO) - handle_rt_signal32(signr, ka, &info, oldset, regs, newsp); + if (ka.sa.sa_flags & SA_SIGINFO) + ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); else - handle_signal32(signr, ka, &info, oldset, regs, newsp); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + ret = handle_signal32(signr, &ka, &info, oldset, regs, newsp); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (ret && !(ka.sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, + &ka.sa.sa_mask); sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } - return 1; + return ret; } diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 1f3003408..a46c63b50 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -15,6 +15,8 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include @@ -36,31 +38,32 @@ #include #include #include -#include #include #include #include #include #include -#include -#include -#include #include #include -#include "open_pic.h" #include -#include #include #include -#include +#include + +#include "mpic.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif int smp_threads_ready; unsigned long cache_decay_ticks; cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; -cpumask_t cpu_available_map = CPU_MASK_NONE; -cpumask_t cpu_present_at_boot = CPU_MASK_NONE; +cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); @@ -73,118 +76,15 @@ extern unsigned char stab_array[]; extern int cpu_idle(void *unused); void smp_call_function_interrupt(void); -extern long register_vpa(unsigned long flags, unsigned long proc, - unsigned long vpa); + +int smt_enabled_at_boot = 1; /* Low level assembly function used to backup CPU 0 state */ extern void __save_cpu_setup(void); -#ifdef CONFIG_PPC_ISERIES -static unsigned long iSeries_smp_message[NR_CPUS]; - -void iSeries_smp_message_recv( struct pt_regs * regs ) -{ - int cpu = smp_processor_id(); - int msg; - - if ( num_online_cpus() < 2 ) - return; - - for ( msg = 0; msg < 4; ++msg ) - if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) ) - smp_message_recv( msg, regs ); -} - -static inline void smp_iSeries_do_message(int cpu, int msg) -{ - set_bit(msg, &iSeries_smp_message[cpu]); - HvCall_sendIPI(&(paca[cpu])); -} - -static void smp_iSeries_message_pass(int target, int msg) -{ - int i; - - if (target < NR_CPUS) - smp_iSeries_do_message(target, msg); - else { - for_each_online_cpu(i) { - if (target == MSG_ALL_BUT_SELF - && i == smp_processor_id()) - continue; - smp_iSeries_do_message(i, msg); - } - } -} - -static int smp_iSeries_numProcs(void) -{ - unsigned np, i; - - np = 0; - for (i=0; i < NR_CPUS; ++i) { - if (paca[i].lppaca.xDynProcStatus < 2) { - cpu_set(i, cpu_available_map); - cpu_set(i, cpu_possible_map); - cpu_set(i, cpu_present_at_boot); - ++np; - } - } - return np; -} - -static int smp_iSeries_probe(void) -{ - unsigned i; - unsigned np = 0; - - for (i=0; i < NR_CPUS; ++i) { - if (paca[i].lppaca.xDynProcStatus < 2) { - /*paca[i].active = 1;*/ - ++np; - } - } - - return np; -} - -static void smp_iSeries_kick_cpu(int nr) -{ - BUG_ON(nr < 0 || nr >= NR_CPUS); - - /* Verify that our partition has a processor nr */ - if (paca[nr].lppaca.xDynProcStatus >= 2) - return; - - /* The processor is currently spinning, waiting - * for the cpu_start field to become non-zero - * After we set cpu_start, the processor will - * continue on to secondary_start in iSeries_head.S - */ - paca[nr].cpu_start = 1; -} - -static void __devinit smp_iSeries_setup_cpu(int nr) -{ -} - -static struct smp_ops_t iSeries_smp_ops = { - .message_pass = smp_iSeries_message_pass, - .probe = smp_iSeries_probe, - .kick_cpu = smp_iSeries_kick_cpu, - .setup_cpu = smp_iSeries_setup_cpu, -}; -/* This is called very early. */ -void __init smp_init_iSeries(void) -{ - smp_ops = &iSeries_smp_ops; - systemcfg->processorCount = smp_iSeries_numProcs(); -} -#endif - -#ifdef CONFIG_PPC_PSERIES -void smp_openpic_message_pass(int target, int msg) +#ifdef CONFIG_PPC_MULTIPLATFORM +void smp_mpic_message_pass(int target, int msg) { /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ){ @@ -195,279 +95,52 @@ void smp_openpic_message_pass(int target, int msg) switch ( target ) { case MSG_ALL: - openpic_cause_IPI(msg, 0xffffffff); + mpic_send_ipi(msg, 0xffffffff); break; case MSG_ALL_BUT_SELF: - openpic_cause_IPI(msg, - 0xffffffff & ~(1 << smp_processor_id())); + mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id())); break; default: - openpic_cause_IPI(msg, 1< 1) - openpic_request_IPIs(); + mpic_request_ipis(); return nr_cpus; } -static void __devinit smp_openpic_setup_cpu(int cpu) -{ - do_openpic_setup_cpu(); -} - -#ifdef CONFIG_HOTPLUG_CPU -/* Get state of physical CPU. - * Return codes: - * 0 - The processor is in the RTAS stopped state - * 1 - stop-self is in progress - * 2 - The processor is not in the RTAS stopped state - * -1 - Hardware Error - * -2 - Hardware Busy, Try again later. - */ -static int query_cpu_stopped(unsigned int pcpu) -{ - int cpu_status; - int status, qcss_tok; - - qcss_tok = rtas_token("query-cpu-stopped-state"); - BUG_ON(qcss_tok == RTAS_UNKNOWN_SERVICE); - status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); - if (status != 0) { - printk(KERN_ERR - "RTAS query-cpu-stopped-state failed: %i\n", status); - return status; - } - - return cpu_status; -} - -int __cpu_disable(void) -{ - /* FIXME: go put this in a header somewhere */ - extern void xics_migrate_irqs_away(void); - - systemcfg->processorCount--; - - /*fix boot_cpuid here*/ - if (smp_processor_id() == boot_cpuid) - boot_cpuid = any_online_cpu(cpu_online_map); - - /* FIXME: abstract this to not be platform specific later on */ - xics_migrate_irqs_away(); - return 0; -} - -void __cpu_die(unsigned int cpu) -{ - int tries; - int cpu_status; - unsigned int pcpu = get_hard_smp_processor_id(cpu); - - for (tries = 0; tries < 5; tries++) { - cpu_status = query_cpu_stopped(pcpu); - - if (cpu_status == 0) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - } - if (cpu_status != 0) { - printk("Querying DEAD? cpu %i (%i) shows %i\n", - cpu, pcpu, cpu_status); - } - - /* Isolation and deallocation are definatly done by - * drslot_chrp_cpu. If they were not they would be - * done here. Change isolate state to Isolate and - * change allocation-state to Unusable. - */ - paca[cpu].cpu_start = 0; - - /* So we can recognize if it fails to come up next time. */ - cpu_callin_map[cpu] = 0; -} - -/* Kill this cpu */ -void cpu_die(void) -{ - local_irq_disable(); - /* Some hardware requires clearing the CPPR, while other hardware does not - * it is safe either way - */ - pSeriesLP_cppr_info(0, 0); - rtas_stop_self(); - /* Should never get here... */ - BUG(); - for(;;); -} - -/* Search all cpu device nodes for an offline logical cpu. If a - * device node has a "ibm,my-drc-index" property (meaning this is an - * LPAR), paranoid-check whether we own the cpu. For each "thread" - * of a cpu, if it is offline and has the same hw index as before, - * grab that in preference. - */ -static unsigned int find_physical_cpu_to_start(unsigned int old_hwindex) -{ - struct device_node *np = NULL; - unsigned int best = -1U; - - while ((np = of_find_node_by_type(np, "cpu"))) { - int nr_threads, len; - u32 *index = (u32 *)get_property(np, "ibm,my-drc-index", NULL); - u32 *tid = (u32 *) - get_property(np, "ibm,ppc-interrupt-server#s", &len); - - if (!tid) - tid = (u32 *)get_property(np, "reg", &len); - - if (!tid) - continue; - - /* If there is a drc-index, make sure that we own - * the cpu. - */ - if (index) { - int state; - int rc = rtas_get_sensor(9003, *index, &state); - if (rc != 0 || state != 1) - continue; - } - - nr_threads = len / sizeof(u32); - - while (nr_threads--) { - if (0 == query_cpu_stopped(tid[nr_threads])) { - best = tid[nr_threads]; - if (best == old_hwindex) - goto out; - } - } - } -out: - of_node_put(np); - return best; -} - -/** - * smp_startup_cpu() - start the given cpu - * - * At boot time, there is nothing to do. At run-time, call RTAS with - * the appropriate start location, if the cpu is in the RTAS stopped - * state. - * - * Returns: - * 0 - failure - * 1 - success - */ -static inline int __devinit smp_startup_cpu(unsigned int lcpu) -{ - int status; - extern void (*pseries_secondary_smp_init)(unsigned int cpu); - unsigned long start_here = __pa(pseries_secondary_smp_init); - unsigned int pcpu; - - /* At boot time the cpus are already spinning in hold - * loops, so nothing to do. */ - if (system_state == SYSTEM_BOOTING) - return 1; - - pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu)); - if (pcpu == -1U) { - printk(KERN_INFO "No more cpus available, failing\n"); - return 0; - } - - /* Fixup atomic count: it exited inside IRQ handler. */ - paca[lcpu].__current->thread_info->preempt_count = 0; - - /* At boot this is done in prom.c. */ - paca[lcpu].hw_cpu_id = pcpu; - - status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL, - pcpu, start_here, lcpu); - if (status != 0) { - printk(KERN_ERR "start-cpu failed: %i\n", status); - return 0; - } - return 1; -} - -static inline void look_for_more_cpus(void) -{ - int num_addr_cell, num_size_cell, len, i, maxcpus; - struct device_node *np; - unsigned int *ireg; - - /* Find the property which will tell us about how many CPUs - * we're allowed to have. */ - if ((np = find_path_device("/rtas")) == NULL) { - printk(KERN_ERR "Could not find /rtas in device tree!"); - return; - } - num_addr_cell = prom_n_addr_cells(np); - num_size_cell = prom_n_size_cells(np); - - ireg = (unsigned int *)get_property(np, "ibm,lrdr-capacity", &len); - if (ireg == NULL) { - /* FIXME: make sure not marked as lrdr_capable() */ - return; - } - - maxcpus = ireg[num_addr_cell + num_size_cell]; - - /* Double maxcpus for processors which have SMT capability */ - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - maxcpus *= 2; - - - if (maxcpus > NR_CPUS) { - printk(KERN_WARNING - "Partition configured for %d cpus, " - "operating system maximum is %d.\n", maxcpus, NR_CPUS); - maxcpus = NR_CPUS; - } else - printk(KERN_INFO "Partition configured for %d cpus.\n", - maxcpus); - - /* Make those cpus (which might appear later) possible too. */ - for (i = 0; i < maxcpus; i++) - cpu_set(i, cpu_possible_map); -} -#else /* ... CONFIG_HOTPLUG_CPU */ -static inline int __devinit smp_startup_cpu(unsigned int lcpu) +void __devinit smp_mpic_setup_cpu(int cpu) { - return 1; + mpic_setup_this_cpu(); } -static inline void look_for_more_cpus(void) -{ -} -#endif /* CONFIG_HOTPLUG_CPU */ -static void smp_pSeries_kick_cpu(int nr) +void __devinit smp_generic_kick_cpu(int nr) { BUG_ON(nr < 0 || nr >= NR_CPUS); - if (!smp_startup_cpu(nr)) - return; - /* * The processor is currently spinning, waiting for the * cpu_start field to become non-zero After we set cpu_start, * the processor will continue on to secondary_start */ paca[nr].cpu_start = 1; + mb(); } -#endif /* CONFIG_PPC_PSERIES */ + +#endif /* CONFIG_PPC_MULTIPLATFORM */ static void __init smp_space_timers(unsigned int max_cpus) { @@ -484,118 +157,9 @@ static void __init smp_space_timers(unsigned int max_cpus) } } -#ifdef CONFIG_PPC_PSERIES -void vpa_init(int cpu) -{ - unsigned long flags; - - /* Register the Virtual Processor Area (VPA) */ - flags = 1UL << (63 - 18); - register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].lppaca))); -} - -static inline void smp_xics_do_message(int cpu, int msg) -{ - set_bit(msg, &xics_ipi_message[cpu].value); - mb(); - xics_cause_IPI(cpu); -} - -static void smp_xics_message_pass(int target, int msg) -{ - unsigned int i; - - if (target < NR_CPUS) { - smp_xics_do_message(target, msg); - } else { - for_each_online_cpu(i) { - if (target == MSG_ALL_BUT_SELF - && i == smp_processor_id()) - continue; - smp_xics_do_message(i, msg); - } - } -} - -extern void xics_request_IPIs(void); - -static int __init smp_xics_probe(void) -{ -#ifdef CONFIG_SMP - xics_request_IPIs(); -#endif - - return cpus_weight(cpu_possible_map); -} - -static void __devinit smp_xics_setup_cpu(int cpu) -{ - if (cpu != boot_cpuid) - xics_setup_cpu(); -} - -static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; -static unsigned long timebase = 0; - -static void __devinit pSeries_give_timebase(void) -{ - spin_lock(&timebase_lock); - rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); - timebase = get_tb(); - spin_unlock(&timebase_lock); - - while (timebase) - barrier(); - rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); -} - -static void __devinit pSeries_take_timebase(void) -{ - while (!timebase) - barrier(); - spin_lock(&timebase_lock); - set_tb(timebase >> 32, timebase & 0xffffffff); - timebase = 0; - spin_unlock(&timebase_lock); -} - -static struct smp_ops_t pSeries_openpic_smp_ops = { - .message_pass = smp_openpic_message_pass, - .probe = smp_openpic_probe, - .kick_cpu = smp_pSeries_kick_cpu, - .setup_cpu = smp_openpic_setup_cpu, -}; - -static struct smp_ops_t pSeries_xics_smp_ops = { - .message_pass = smp_xics_message_pass, - .probe = smp_xics_probe, - .kick_cpu = smp_pSeries_kick_cpu, - .setup_cpu = smp_xics_setup_cpu, -}; - -/* This is called very early */ -void __init smp_init_pSeries(void) -{ - - if (naca->interrupt_controller == IC_OPEN_PIC) - smp_ops = &pSeries_openpic_smp_ops; - else - smp_ops = &pSeries_xics_smp_ops; - - /* Non-lpar has additional take/give timebase */ - if (systemcfg->platform == PLATFORM_PSERIES) { - smp_ops->give_timebase = pSeries_give_timebase; - smp_ops->take_timebase = pSeries_take_timebase; - } -} -#endif - void smp_local_timer_interrupt(struct pt_regs * regs) { - if (!--(get_paca()->prof_counter)) { - update_process_times(user_mode(regs)); - (get_paca()->prof_counter)=get_paca()->prof_multiplier; - } + update_process_times(user_mode(regs)); } void smp_message_recv(int msg, struct pt_regs *regs) @@ -751,6 +315,8 @@ out: return ret; } +EXPORT_SYMBOL(smp_call_function); + void smp_call_function_interrupt(void) { void (*func) (void *info); @@ -794,26 +360,17 @@ DECLARE_PER_CPU(unsigned int, pvr); static void __devinit smp_store_cpu_info(int id) { - per_cpu(pvr, id) = _get_PVR(); + per_cpu(pvr, id) = mfspr(SPRN_PVR); } static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* create a process for the processor */ - /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, - 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - wake_up_forked_process(p); - init_idle(p, cpu); - unhash_process(p); - paca[cpu].__current = p; current_set[cpu] = p->thread_info; } @@ -822,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int cpu; + DBG("smp_prepare_cpus\n"); + /* * setup_cpu may need to be called on the boot cpu. We havent * spun any cpus up but lets be paranoid. @@ -831,8 +390,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) /* Fixup boot cpu */ smp_store_cpu_info(boot_cpuid); cpu_callin_map[boot_cpuid] = 1; - paca[boot_cpuid].prof_counter = 1; - paca[boot_cpuid].prof_multiplier = 1; #ifndef CONFIG_PPC_ISERIES paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb(); @@ -843,15 +400,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus) * number of msecs off until someone does a settimeofday() */ do_gtod.tb_orig_stamp = tb_last_stamp; - - look_for_more_cpus(); + systemcfg->tb_orig_stamp = tb_last_stamp; #endif max_cpus = smp_ops->probe(); - /* Backup CPU 0 state if necessary */ - __save_cpu_setup(); - smp_space_timers(max_cpus); for_each_cpu(cpu) @@ -863,7 +416,6 @@ void __devinit smp_prepare_boot_cpu(void) { BUG_ON(smp_processor_id() != boot_cpuid); - /* cpu_possible is set up in prom.c */ cpu_set(boot_cpuid, cpu_online_map); paca[boot_cpuid].__current = current; @@ -875,11 +427,9 @@ int __devinit __cpu_up(unsigned int cpu) int c; /* At boot, don't bother with non-present cpus -JSCHOPP */ - if (system_state == SYSTEM_BOOTING && !cpu_present_at_boot(cpu)) + if (system_state < SYSTEM_RUNNING && !cpu_present(cpu)) return -ENOENT; - paca[cpu].prof_counter = 1; - paca[cpu].prof_multiplier = 1; paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock; if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { @@ -895,6 +445,11 @@ int __devinit __cpu_up(unsigned int cpu) paca[cpu].stab_real = virt_to_abs(tmp); } + /* Make sure callin-map entry is 0 (can be leftover a CPU + * hotplug + */ + cpu_callin_map[cpu] = 0; + /* The information for processor bringup must * be written out to main store before we release * the processor. @@ -902,6 +457,7 @@ int __devinit __cpu_up(unsigned int cpu) mb(); /* wake up cpus */ + DBG("smp: kicking cpu %d\n", cpu); smp_ops->kick_cpu(cpu); /* @@ -909,7 +465,7 @@ int __devinit __cpu_up(unsigned int cpu) * use this value that I found through experimentation. * -- Cort */ - if (system_state == SYSTEM_BOOTING) + if (system_state < SYSTEM_RUNNING) for (c = 5000; c && !cpu_callin_map[cpu]; c--) udelay(100); #ifdef CONFIG_HOTPLUG_CPU @@ -941,7 +497,7 @@ int __devinit __cpu_up(unsigned int cpu) return 0; } -extern unsigned int default_distrib_server; + /* Activate a secondary processor. */ int __devinit start_secondary(void *unused) { @@ -958,20 +514,8 @@ int __devinit start_secondary(void *unused) if (smp_ops->take_timebase) smp_ops->take_timebase(); -#ifdef CONFIG_PPC_PSERIES - if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - vpa_init(cpu); - } - -#ifdef CONFIG_IRQ_ALL_CPUS - /* Put the calling processor into the GIQ. This is really only - * necessary from a secondary thread as the OF start-cpu interface - * performs this function for us on primary threads. - */ - /* TODO: 9005 is #defined in rtas-proc.c -- move to a header */ - rtas_set_indicator(9005, default_distrib_server, 1); -#endif -#endif + if (smp_ops->late_setup_cpu) + smp_ops->late_setup_cpu(cpu); spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); @@ -1004,219 +548,12 @@ void __init smp_cpus_done(unsigned int max_cpus) smp_threads_ready = 1; set_cpus_allowed(current, old_mask); -} - -#ifdef CONFIG_SCHED_SMT -#ifdef CONFIG_NUMA -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static struct sched_group sched_group_nodes[MAX_NUMNODES]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -static DEFINE_PER_CPU(struct sched_domain, node_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - struct sched_domain *node_domain = &per_cpu(node_domains, i); - int node = cpu_to_node(i); - cpumask_t nodemask = node_to_cpumask(node); - cpumask_t my_cpumask = cpumask_of_cpu(i); - cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); - - *cpu_domain = SD_SIBLING_INIT; - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); - else - cpu_domain->span = my_cpumask; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = nodemask; - phys_domain->parent = node_domain; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - - *node_domain = SD_NODE_INIT; - node_domain->span = cpu_possible_map; - node_domain->groups = &sched_group_nodes[node]; - } - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - for (i = 0; i < MAX_NUMNODES; i++) { - int j; - cpumask_t nodemask; - struct sched_group *node = &sched_group_nodes[i]; - cpumask_t node_cpumask = node_to_cpumask(i); - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu_mask(j, nodemask) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); - struct sched_group *cpu = &sched_group_phys[j]; - - if (j != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* - * Make each extra sibling increase power by 10% of - * the basic CPU. This is very arbitrary. - */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - node->cpu_power += cpu->cpu_power; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - /* Set up nodes */ - first = last = NULL; - for (i = 0; i < MAX_NUMNODES; i++) { - struct sched_group *cpu = &sched_group_nodes[i]; - cpumask_t nodemask; - cpumask_t node_cpumask = node_to_cpumask(i); - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - cpu->cpumask = nodemask; - /* ->cpu_power already setup */ - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#else /* !CONFIG_NUMA */ -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - cpumask_t my_cpumask = cpumask_of_cpu(i); - cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); - - *cpu_domain = SD_SIBLING_INIT; - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); - else - cpu_domain->span = my_cpumask; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = cpu_possible_map; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_group *cpu = &sched_group_phys[i]; - - if (i != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* See SMT+NUMA setup for comment */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } + /* + * We know at boot the maximum number of cpus we can add to + * a partition and set cpu_possible_map accordingly. cpu_present_map + * needs to match for the hotplug code to allow us to hot add + * any offline cpus. + */ + cpu_present_map = cpu_possible_map; } -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_SCHED_SMT */ diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c index 26e5e8dd9..2ff7af2c9 100644 --- a/arch/ppc64/kernel/sys_ppc32.c +++ b/arch/ppc64/kernel/sys_ppc32.c @@ -72,7 +72,6 @@ #include #include #include -#include #include #include "pci.h" @@ -622,8 +621,11 @@ long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2, error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: @@ -634,8 +636,24 @@ out: void start_thread32(struct pt_regs* regs, unsigned long nip, unsigned long sp) { set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); - memset(®s->ctr, 0, 4 * sizeof(regs->ctr)); + + /* + * If we exec out of a kernel thread then thread.regs will not be + * set. Do it now. + */ + if (!current->thread.regs) { + unsigned long childregs = (unsigned long)current->thread_info + + THREAD_SIZE; + childregs -= sizeof(struct pt_regs); + current->thread.regs = (struct pt_regs *)childregs; + } + + /* + * ELF_PLAT_INIT already clears all registers but it also sets r2. + * So just clear r2 here. + */ + regs->gpr[2] = 0; + regs->nip = nip; regs->gpr[1] = sp; regs->msr = MSR_USER32; @@ -700,7 +718,7 @@ asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf (unsigned long) dfn, (unsigned long) off, (unsigned long) len, - (unsigned char __user *)AA(ubuf)); + compat_ptr(ubuf)); } asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) @@ -709,7 +727,7 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu (unsigned long) dfn, (unsigned long) off, (unsigned long) len, - (unsigned char __user *)AA(ubuf)); + compat_ptr(ubuf)); } #define IOBASE_BRIDGE_NUMBER 0 @@ -1095,7 +1113,7 @@ struct __sysctl_args32 { u32 __unused[4]; }; -extern asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) +asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) { struct __sysctl_args32 tmp; int error; @@ -1114,19 +1132,20 @@ extern asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) glibc's __sysctl uses rw memory for the structure anyway. */ oldlenp = (size_t __user *)addr; - if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) || + if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) || put_user(oldlen, oldlenp)) return -EFAULT; } lock_kernel(); - error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval), - oldlenp, (void __user *)A(tmp.newval), tmp.newlen); + error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, + compat_ptr(tmp.oldval), oldlenp, + compat_ptr(tmp.newval), tmp.newlen); unlock_kernel(); if (oldlenp) { if (!error) { if (get_user(oldlen, oldlenp) || - put_user(oldlen, (u32 __user *)A(tmp.oldlenp))) + put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp))) error = -EFAULT; } copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); @@ -1309,3 +1328,21 @@ long ppc32_timer_create(clockid_t clock, return err; } + +asmlinkage long sys32_add_key(const char __user *_type, + const char __user *_description, + const void __user *_payload, + u32 plen, + u32 ringid) +{ + return sys_add_key(_type, _description, _payload, plen, ringid); +} + +asmlinkage long sys32_request_key(const char __user *_type, + const char __user *_description, + const char __user *_callout_info, + u32 destringid) +{ + return sys_request_key(_type, _description, _callout_info, destringid); +} + diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 41b34932f..95c083163 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -5,6 +5,9 @@ #include #include #include +#include +#include + #include #include #include @@ -14,8 +17,7 @@ /* SMT stuff */ -#ifndef CONFIG_PPC_ISERIES - +#ifdef CONFIG_PPC_MULTIPLATFORM /* default to snooze disabled */ DEFINE_PER_CPU(unsigned long, smt_snooze_delay); @@ -91,11 +93,6 @@ static int __init setup_smt_snooze_delay(char *str) } __setup("smt-snooze-delay=", setup_smt_snooze_delay); -#endif - - -/* PMC stuff */ - /* * Enabling PMCs will slow partition context switch times so we only do * it the first time we write to the PMCs. @@ -103,18 +100,14 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay); static DEFINE_PER_CPU(char, pmcs_enabled); -#ifdef CONFIG_PPC_ISERIES -void ppc64_enable_pmcs(void) -{ - /* XXX Implement for iseries */ -} -#else void ppc64_enable_pmcs(void) { unsigned long hid0; +#ifdef CONFIG_PPC_PSERIES unsigned long set, reset; int ret; unsigned int ctrl; +#endif /* CONFIG_PPC_PSERIES */ /* Only need to enable them once */ if (__get_cpu_var(pmcs_enabled)) @@ -123,37 +116,42 @@ void ppc64_enable_pmcs(void) __get_cpu_var(pmcs_enabled) = 1; switch (systemcfg->platform) { - case PLATFORM_PSERIES: - hid0 = mfspr(HID0); - hid0 |= 1UL << (63 - 20); - - /* POWER4 requires the following sequence */ - asm volatile( - "sync\n" - "mtspr %1, %0\n" - "mfspr %0, %1\n" - "mfspr %0, %1\n" - "mfspr %0, %1\n" - "mfspr %0, %1\n" - "mfspr %0, %1\n" - "mfspr %0, %1\n" - "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0): - "memory"); - break; - - case PLATFORM_PSERIES_LPAR: - set = 1UL << 63; - reset = 0; - ret = plpar_hcall_norets(H_PERFMON, set, reset); - if (ret) - printk(KERN_ERR "H_PERFMON call returned %d", - ret); - break; - - default: - break; + case PLATFORM_PSERIES: + case PLATFORM_POWERMAC: + hid0 = mfspr(HID0); + hid0 |= 1UL << (63 - 20); + + /* POWER4 requires the following sequence */ + asm volatile( + "sync\n" + "mtspr %1, %0\n" + "mfspr %0, %1\n" + "mfspr %0, %1\n" + "mfspr %0, %1\n" + "mfspr %0, %1\n" + "mfspr %0, %1\n" + "mfspr %0, %1\n" + "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0): + "memory"); + break; + +#ifdef CONFIG_PPC_PSERIES + case PLATFORM_PSERIES_LPAR: + set = 1UL << 63; + reset = 0; + ret = plpar_hcall_norets(H_PERFMON, set, reset); + if (ret) + printk(KERN_ERR "H_PERFMON call on cpu %u " + "returned %d\n", + smp_processor_id(), ret); + break; +#endif /* CONFIG_PPC_PSERIES */ + + default: + break; } +#ifdef CONFIG_PPC_PSERIES /* instruct hypervisor to maintain PMCs */ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { char *ptr = (char *)&paca[smp_processor_id()].lppaca; @@ -169,8 +167,19 @@ void ppc64_enable_pmcs(void) ctrl |= RUNLATCH; mtspr(CTRLT, ctrl); } +#endif /* CONFIG_PPC_PSERIES */ } -#endif + +#else + +/* PMC stuff */ +void ppc64_enable_pmcs(void) +{ + /* XXX Implement for iseries */ +} +#endif /* CONFIG_PPC_MULTIPLATFORM */ + +EXPORT_SYMBOL(ppc64_enable_pmcs); /* XXX convert to rusty's on_one_cpu */ static unsigned long run_on_cpu(unsigned long cpu, diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 64844df4a..aea2c5cfa 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -83,7 +85,7 @@ static unsigned long first_settimeofday = 1; #define XSEC_PER_SEC (1024*1024) unsigned long tb_ticks_per_jiffy; -unsigned long tb_ticks_per_usec; +unsigned long tb_ticks_per_usec = 100; /* sane default */ unsigned long tb_ticks_per_sec; unsigned long next_xtime_sync_tb; unsigned long xtime_sync_interval; @@ -101,50 +103,12 @@ extern unsigned long wall_jiffies; extern unsigned long lpevent_count; extern int smp_tb_synchronized; +extern struct timezone sys_tz; + void ppc_adjtimex(void); static unsigned adjusting_time = 0; -/* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ -static inline void ppc64_do_profile(struct pt_regs *regs) -{ - unsigned long nip; - extern unsigned long prof_cpu_mask; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; - - nip = instruction_pointer(regs); - - /* - * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. - * (default is all CPUs.) - */ - if (!((1<>= prof_shift; - /* - * Don't ignore out-of-bounds EIP values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (nip > prof_len-1) - nip = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[nip]); -} - static __inline__ void timer_check_rtc(void) { /* @@ -195,6 +159,19 @@ static __inline__ void timer_sync_xtime( unsigned long cur_tb ) } } +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + + if (in_lock_functions(pc)) + return regs->link; + + return pc; +} +EXPORT_SYMBOL(profile_pc); +#endif + #ifdef CONFIG_PPC_ISERIES /* @@ -233,6 +210,8 @@ static void iSeries_tb_recal(void) do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; tb_to_xs = divres.result_low; do_gtod.varp->tb_to_xs = tb_to_xs; + systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; + systemcfg->tb_to_xs = tb_to_xs; } else { printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" @@ -273,7 +252,7 @@ int timer_interrupt(struct pt_regs * regs) irq_enter(); #ifndef CONFIG_PPC_ISERIES - ppc64_do_profile(regs); + profile_tick(CPU_PROFILING, regs); #endif lpaca->lppaca.xIntDword.xFields.xDecrInt = 0; @@ -281,12 +260,27 @@ int timer_interrupt(struct pt_regs * regs) while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) { #ifdef CONFIG_SMP - smp_local_timer_interrupt(regs); + /* + * We cannot disable the decrementer, so in the period + * between this cpu's being marked offline in cpu_online_map + * and calling stop-self, it is taking timer interrupts. + * Avoid calling into the scheduler rebalancing code if this + * is the case. + */ + if (!cpu_is_offline(cpu)) + smp_local_timer_interrupt(regs); #endif + /* + * No need to check whether cpu is offline here; boot_cpuid + * should have been fixed up by now. + */ if (cpu == boot_cpuid) { write_seqlock(&xtime_lock); tb_last_stamp = lpaca->next_jiffy_update_tb; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif timer_sync_xtime( cur_tb ); timer_check_rtc(); write_sequnlock(&xtime_lock); @@ -408,6 +402,7 @@ int do_settimeofday(struct timespec *tv) new_xsec += new_sec * XSEC_PER_SEC; if ( new_xsec > delta_xsec ) { do_gtod.varp->stamp_xsec = new_xsec - delta_xsec; + systemcfg->stamp_xsec = new_xsec - delta_xsec; } else { /* This is only for the case where the user is setting the time @@ -416,8 +411,13 @@ int do_settimeofday(struct timespec *tv) * the time to Jan 5, 1970 */ do_gtod.varp->stamp_xsec = new_xsec; do_gtod.tb_orig_stamp = tb_last_stamp; + systemcfg->stamp_xsec = new_xsec; + systemcfg->tb_orig_stamp = tb_last_stamp; } + systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; + systemcfg->tz_dsttime = sys_tz.tz_dsttime; + write_sequnlock_irqrestore(&xtime_lock, flags); clock_was_set(); return 0; @@ -435,9 +435,7 @@ long ppc64_sys32_stime(int __user * tptr) { int value; struct timespec myTimeval; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; if (get_user(value, tptr)) return -EFAULT; @@ -445,6 +443,10 @@ long ppc64_sys32_stime(int __user * tptr) myTimeval.tv_sec = value; myTimeval.tv_nsec = 0; + err = security_settime(&myTimeval, NULL); + if (err) + return err; + do_settimeofday(&myTimeval); return 0; @@ -460,9 +462,7 @@ long ppc64_sys_stime(long __user * tptr) { long value; struct timespec myTimeval; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; if (get_user(value, tptr)) return -EFAULT; @@ -470,6 +470,10 @@ long ppc64_sys_stime(long __user * tptr) myTimeval.tv_sec = value; myTimeval.tv_nsec = 0; + err = security_settime(&myTimeval, NULL); + if (err) + return err; + do_settimeofday(&myTimeval); return 0; @@ -520,6 +524,11 @@ void __init time_init(void) do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; do_gtod.varp->tb_to_xs = tb_to_xs; do_gtod.tb_to_us = tb_to_us; + systemcfg->tb_orig_stamp = tb_last_stamp; + systemcfg->tb_update_count = 0; + systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; + systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; + systemcfg->tb_to_xs = tb_to_xs; xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8); next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval; @@ -655,6 +664,22 @@ void ppc_adjtimex(void) do_gtod.varp = temp_varp; do_gtod.var_idx = temp_idx; + /* + * tb_update_count is used to allow the problem state gettimeofday code + * to assure itself that it sees a consistent view of the tb_to_xs and + * stamp_xsec variables. It reads the tb_update_count, then reads + * tb_to_xs and stamp_xsec and then reads tb_update_count again. If + * the two values of tb_update_count match and are even then the + * tb_to_xs and stamp_xsec values are consistent. If not, then it + * loops back and reads them again until this criteria is met. + */ + ++(systemcfg->tb_update_count); + wmb(); + systemcfg->tb_to_xs = new_tb_to_xs; + systemcfg->stamp_xsec = new_stamp_xsec; + wmb(); + ++(systemcfg->tb_update_count); + write_sequnlock_irqrestore( &xtime_lock, flags ); } diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index 5f70f7bc1..90700b414 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -134,14 +134,20 @@ int die(const char *str, struct pt_regs *regs, long err) } static void -_exception(int signr, siginfo_t *info, struct pt_regs *regs) +_exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { + siginfo_t info; + if (!user_mode(regs)) { if (die("Exception in kernel mode", regs, signr)) return; } - force_sig_info(signr, info, current); + memset(&info, 0, sizeof(info)); + info.si_signo = signr; + info.si_code = code; + info.si_addr = (void __user *) addr; + force_sig_info(signr, &info, current); } #ifdef CONFIG_PPC_PSERIES @@ -213,27 +219,21 @@ SystemResetException(struct pt_regs *regs) */ static int recover_mce(struct pt_regs *regs, struct rtas_error_log err) { - siginfo_t info; - - if (err.disposition == DISP_FULLY_RECOVERED) { + if (err.disposition == RTAS_DISP_FULLY_RECOVERED) { /* Platform corrected itself */ return 1; } else if ((regs->msr & MSR_RI) && user_mode(regs) && - err.severity == SEVERITY_ERROR_SYNC && - err.disposition == DISP_NOT_RECOVERED && - err.target == TARGET_MEMORY && - err.type == TYPE_ECC_UNCORR && + err.severity == RTAS_SEVERITY_ERROR_SYNC && + err.disposition == RTAS_DISP_NOT_RECOVERED && + err.target == RTAS_TARGET_MEMORY && + err.type == RTAS_TYPE_ECC_UNCORR && !(current->pid == 0 || current->pid == 1)) { /* Kill off a user process with an ECC error */ - info.si_signo = SIGBUS; - info.si_errno = 0; - /* XXX something better for ECC error? */ - info.si_code = BUS_ADRERR; - info.si_addr = (void __user *)regs->nip; printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n", current->pid); - _exception(SIGBUS, &info, regs); + /* XXX something better for ECC error? */ + _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); return 1; } return 0; @@ -278,35 +278,46 @@ MachineCheckException(struct pt_regs *regs) void UnknownException(struct pt_regs *regs) { - siginfo_t info; - printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = 0; - info.si_addr = NULL; - _exception(SIGTRAP, &info, regs); + _exception(SIGTRAP, regs, 0, 0); } void InstructionBreakpointException(struct pt_regs *regs) { - siginfo_t info; - if (debugger_iabr_match(regs)) return; - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void __user *)regs->nip; - _exception(SIGTRAP, &info, regs); + _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); +} + +void +SingleStepException(struct pt_regs *regs) +{ + regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ + + if (debugger_sstep(regs)) + return; + + _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); +} + +/* + * After we have successfully emulated an instruction, we have to + * check if the instruction was being single-stepped, and if so, + * pretend we got a single-step exception. This was pointed out + * by Kumar Gala. -- paulus + */ +static inline void emulate_single_step(struct pt_regs *regs) +{ + if (regs->msr & MSR_SE) + SingleStepException(regs); } static void parse_fpe(struct pt_regs *regs) { - siginfo_t info; + int code = 0; unsigned long fpscr; flush_fp_to_thread(current); @@ -315,31 +326,84 @@ static void parse_fpe(struct pt_regs *regs) /* Invalid operation */ if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) - info.si_code = FPE_FLTINV; + code = FPE_FLTINV; /* Overflow */ else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX)) - info.si_code = FPE_FLTOVF; + code = FPE_FLTOVF; /* Underflow */ else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX)) - info.si_code = FPE_FLTUND; + code = FPE_FLTUND; /* Divide by zero */ else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX)) - info.si_code = FPE_FLTDIV; + code = FPE_FLTDIV; /* Inexact result */ else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX)) - info.si_code = FPE_FLTRES; + code = FPE_FLTRES; + + _exception(SIGFPE, regs, code, regs->nip); +} + +/* + * Illegal instruction emulation support. Return non-zero if we can't + * emulate, or -EFAULT if the associated memory access caused an access + * fault. Return zero on success. + */ + +#define INST_DCBA 0x7c0005ec +#define INST_DCBA_MASK 0x7c0007fe + +#define INST_MCRXR 0x7c000400 +#define INST_MCRXR_MASK 0x7c0007fe + +static int emulate_instruction(struct pt_regs *regs) +{ + unsigned int instword; - else - info.si_code = 0; + if (!user_mode(regs)) + return -EINVAL; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_addr = (void __user *)regs->nip; - _exception(SIGFPE, &info, regs); + CHECK_FULL_REGS(regs); + + if (get_user(instword, (unsigned int __user *)(regs->nip))) + return -EFAULT; + + /* Emulating the dcba insn is just a no-op. */ + if ((instword & INST_DCBA_MASK) == INST_DCBA) { + static int warned; + + if (!warned) { + printk(KERN_WARNING + "process %d (%s) uses obsolete 'dcba' insn\n", + current->pid, current->comm); + warned = 1; + } + return 0; + } + + /* Emulate the mcrxr insn. */ + if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { + static int warned; + unsigned int shift; + + if (!warned) { + printk(KERN_WARNING + "process %d (%s) uses obsolete 'mcrxr' insn\n", + current->pid, current->comm); + warned = 1; + } + + shift = (instword >> 21) & 0x1c; + regs->ccr &= ~(0xf0000000 >> shift); + regs->ccr |= (regs->xer & 0xf0000000) >> shift; + regs->xer &= ~0xf0000000; + return 0; + } + + return -EINVAL; } /* @@ -395,20 +459,14 @@ check_bug_trap(struct pt_regs *regs) void ProgramCheckException(struct pt_regs *regs) { - siginfo_t info; - if (regs->msr & 0x100000) { /* IEEE FP exception */ - parse_fpe(regs); + } else if (regs->msr & 0x40000) { /* Privileged instruction */ + _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_PRVOPC; - info.si_addr = (void __user *)regs->nip; - _exception(SIGILL, &info, regs); } else if (regs->msr & 0x20000) { /* trap exception */ @@ -419,19 +477,24 @@ ProgramCheckException(struct pt_regs *regs) regs->nip += 4; return; } - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void __user *)regs->nip; - _exception(SIGTRAP, &info, regs); + _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); + } else { - /* Illegal instruction */ + /* Illegal instruction; try to emulate it. */ + switch (emulate_instruction(regs)) { + case 0: + regs->nip += 4; + emulate_single_step(regs); + break; - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)regs->nip; - _exception(SIGILL, &info, regs); + case -EFAULT: + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); + break; + + default: + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + break; + } } } @@ -448,13 +511,7 @@ void AltivecUnavailableException(struct pt_regs *regs) if (user_mode(regs)) { /* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ - siginfo_t info; - - memset(&info, 0, sizeof(info)); - info.si_signo = SIGILL; - info.si_code = ILL_ILLOPC; - info.si_addr = (void *) regs->nip; - _exception(SIGILL, &info, regs); + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); return; } #endif @@ -463,41 +520,22 @@ void AltivecUnavailableException(struct pt_regs *regs) die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); } -void -SingleStepException(struct pt_regs *regs) -{ - siginfo_t info; - - regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ - - if (debugger_sstep(regs)) - return; - - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_TRACE; - info.si_addr = (void __user *)regs->nip; - _exception(SIGTRAP, &info, regs); -} - -/* - * After we have successfully emulated an instruction, we have to - * check if the instruction was being single-stepped, and if so, - * pretend we got a single-step exception. This was pointed out - * by Kumar Gala. -- paulus - */ -static inline void emulate_single_step(struct pt_regs *regs) -{ - if (regs->msr & MSR_SE) - SingleStepException(regs); -} +/* Ensure exceptions are disabled */ +#define MMCR0_PMXE (1UL << (31 - 5)) +#define MMCR0_PMAO (1UL << (31 - 24)) static void dummy_perf(struct pt_regs *regs) { + unsigned int mmcr0 = mfspr(SPRN_MMCR0); + + mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO); + mtspr(SPRN_MMCR0, mmcr0); } void (*perf_irq)(struct pt_regs *) = dummy_perf; +EXPORT_SYMBOL(perf_irq); + void PerformanceMonitorException(struct pt_regs *regs) { @@ -508,7 +546,6 @@ void AlignmentException(struct pt_regs *regs) { int fixed; - siginfo_t info; fixed = fix_alignment(regs); @@ -521,11 +558,7 @@ AlignmentException(struct pt_regs *regs) /* Operand address was bad */ if (fixed == -EFAULT) { if (user_mode(regs)) { - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = (void __user *)regs->dar; - force_sig_info(SIGSEGV, &info, current); + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->dar); } else { /* Search exception table */ bad_page_fault(regs, regs->dar, SIGSEGV); @@ -534,11 +567,7 @@ AlignmentException(struct pt_regs *regs) return; } - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)regs->nip; - _exception(SIGBUS, &info, regs); + _exception(SIGBUS, regs, BUS_ADRALN, regs->nip); } #ifdef CONFIG_ALTIVEC diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c index 2bb0b39f6..051cac60b 100644 --- a/arch/ppc64/kernel/u3_iommu.c +++ b/arch/ppc64/kernel/u3_iommu.c @@ -267,6 +267,7 @@ static int dart_init(struct device_node *dart_node) void iommu_setup_u3(void) { + struct pci_controller *phb, *tmp; struct pci_dev *dev = NULL; struct device_node *dn; @@ -290,7 +291,7 @@ void iommu_setup_u3(void) /* We only have one iommu table on the mac for now, which makes * things simple. Setup all PCI devices to point to this table */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { /* We must use pci_device_to_OF_node() to make sure that * we get the real "final" pointer to the device in the * pci_dev sysdata and not the temporary PHB one @@ -299,6 +300,11 @@ void iommu_setup_u3(void) if (dn) dn->iommu_table = &iommu_table_u3; } + /* We also make sure we set all PHBs ... */ + list_for_each_entry_safe(phb, tmp, &hose_list, list_node) { + dn = (struct device_node *)phb->arch_data; + dn->iommu_table = &iommu_table_u3; + } } void __init alloc_u3_dart_table(void) diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c index da2179154..7d5f51844 100644 --- a/arch/ppc64/kernel/udbg.c +++ b/arch/ppc64/kernel/udbg.c @@ -11,6 +11,8 @@ #include #define WANT_PPCDBG_TAB /* Only defined here */ +#include +#include #include #include #include @@ -20,6 +22,9 @@ #include #include +extern u8 real_readb(volatile u8 __iomem *addr); +extern void real_writeb(u8 data, volatile u8 __iomem *addr); + struct NS16550 { /* this struct must be packed */ unsigned char rbr; /* 0 */ @@ -47,21 +52,25 @@ struct NS16550 { #define LSR_TEMT 0x40 /* Xmitter empty */ #define LSR_ERR 0x80 /* Error */ -static volatile struct NS16550 *udbg_comport; +static volatile struct NS16550 __iomem *udbg_comport; -void udbg_init_uart(void *comport) +void udbg_init_uart(void __iomem *comport, unsigned int speed) { + u16 dll = speed ? (115200 / speed) : 12; + if (comport) { - udbg_comport = (struct NS16550 *)comport; - udbg_comport->lcr = 0x00; eieio(); - udbg_comport->ier = 0xFF; eieio(); - udbg_comport->ier = 0x00; eieio(); - udbg_comport->lcr = 0x80; eieio(); /* Access baud rate */ - udbg_comport->dll = 12; eieio(); /* 1 = 115200, 2 = 57600, 3 = 38400, 12 = 9600 baud */ - udbg_comport->dlm = 0; eieio(); /* dll >> 8 which should be zero for fast rates; */ - udbg_comport->lcr = 0x03; eieio(); /* 8 data, 1 stop, no parity */ - udbg_comport->mcr = 0x03; eieio(); /* RTS/DTR */ - udbg_comport->fcr = 0x07; eieio(); /* Clear & enable FIFOs */ + udbg_comport = (struct NS16550 __iomem *)comport; + out_8(&udbg_comport->lcr, 0x00); + out_8(&udbg_comport->ier, 0xff); + out_8(&udbg_comport->ier, 0x00); + out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */ + out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600, + 3 = 38400, 12 = 9600 baud */ + out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero + for fast rates; */ + out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */ + out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */ + out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */ } } @@ -70,7 +79,8 @@ void udbg_init_uart(void *comport) #define SCC_TXRDY 4 #define SCC_RXRDY 1 -static volatile u8 *sccc, *sccd; +static volatile u8 __iomem *sccc; +static volatile u8 __iomem *sccd; static unsigned char scc_inittab[] = { 13, 0, /* set baud rate divisor */ @@ -84,31 +94,44 @@ static unsigned char scc_inittab[] = { void udbg_init_scc(struct device_node *np) { + u32 *reg; unsigned long addr; int i, x; if (np == NULL) np = of_find_node_by_name(NULL, "escc"); - if (np == NULL) + if (np == NULL || np->parent == NULL) return; - - /* Lock-enable the SCC channel */ - pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); + + udbg_printf("found SCC...\n"); + /* Get address within mac-io ASIC */ + reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) + return; + addr = reg[0]; + udbg_printf("local addr: %lx\n", addr); + /* Get address of mac-io PCI itself */ + reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL); + if (reg == NULL) + return; + addr += reg[2]; + udbg_printf("final addr: %lx\n", addr); /* Setup for 57600 8N1 */ - addr = np->addrs[0].address + 0x20; - sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; + addr += 0x20; + sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; sccc += addr & ~PAGE_MASK; sccd = sccc + 0x10; + udbg_printf("ioremap result sccc: %p\n", sccc); + mb(); + for (i = 20000; i != 0; --i) - x = *sccc; eieio(); - *sccc = 9; eieio(); /* reset A or B side */ - *sccc = 0xc0; eieio(); - for (i = 0; i < sizeof(scc_inittab); ++i) { - *sccc = scc_inittab[i]; - eieio(); - } + x = in_8(sccc); + out_8(sccc, 0x09); /* reset A or B side */ + out_8(sccc, 0xc0); + for (i = 0; i < sizeof(scc_inittab); ++i) + out_8(sccc, scc_inittab[i]); ppc_md.udbg_putc = udbg_putc; ppc_md.udbg_getc = udbg_getc; @@ -119,25 +142,71 @@ void udbg_init_scc(struct device_node *np) #endif /* CONFIG_PPC_PMAC */ -void udbg_putc(unsigned char c) +#if CONFIG_PPC_PMAC +static void udbg_real_putc(unsigned char c) +{ + while ((real_readb(sccc) & SCC_TXRDY) == 0) + ; + real_writeb(c, sccd); + if (c == '\n') + udbg_real_putc('\r'); +} + +void udbg_init_pmac_realmode(void) +{ + sccc = (volatile u8 __iomem *)0x80013020ul; + sccd = (volatile u8 __iomem *)0x80013030ul; + + ppc_md.udbg_putc = udbg_real_putc; + ppc_md.udbg_getc = NULL; + ppc_md.udbg_getc_poll = NULL; +} +#endif /* CONFIG_PPC_PMAC */ + +#ifdef CONFIG_PPC_MAPLE +void udbg_maple_real_putc(unsigned char c) { if (udbg_comport) { - while ((udbg_comport->lsr & LSR_THRE) == 0) + while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) /* wait for idle */; - udbg_comport->thr = c; eieio(); + real_writeb(c, &udbg_comport->thr); eieio(); if (c == '\n') { /* Also put a CR. This is for convenience. */ - while ((udbg_comport->lsr & LSR_THRE) == 0) + while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) /* wait for idle */; - udbg_comport->thr = '\r'; eieio(); + real_writeb('\r', &udbg_comport->thr); eieio(); + } + } +} + +void udbg_init_maple_realmode(void) +{ + udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8; + + ppc_md.udbg_putc = udbg_maple_real_putc; + ppc_md.udbg_getc = NULL; + ppc_md.udbg_getc_poll = NULL; +} +#endif /* CONFIG_PPC_MAPLE */ + +void udbg_putc(unsigned char c) +{ + if (udbg_comport) { + while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) + /* wait for idle */; + out_8(&udbg_comport->thr, c); + if (c == '\n') { + /* Also put a CR. This is for convenience. */ + while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) + /* wait for idle */; + out_8(&udbg_comport->thr, '\r'); } } #ifdef CONFIG_PPC_PMAC else if (sccc) { - while ((*sccc & SCC_TXRDY) == 0) - eieio(); - *sccd = c; - eieio(); + while ((in_8(sccc) & SCC_TXRDY) == 0) + ; + out_8(sccd, c); if (c == '\n') udbg_putc('\r'); } @@ -147,16 +216,15 @@ void udbg_putc(unsigned char c) int udbg_getc_poll(void) { if (udbg_comport) { - if ((udbg_comport->lsr & LSR_DR) != 0) - return udbg_comport->rbr; + if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0) + return in_8(&udbg_comport->rbr); else return -1; } #ifdef CONFIG_PPC_PMAC else if (sccc) { - eieio(); - if ((*sccc & SCC_RXRDY) != 0) - return *sccd; + if ((in_8(sccc) & SCC_RXRDY) != 0) + return in_8(sccd); else return -1; } @@ -167,16 +235,15 @@ int udbg_getc_poll(void) unsigned char udbg_getc(void) { if (udbg_comport) { - while ((udbg_comport->lsr & LSR_DR) == 0) + while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) /* wait for char */; - return udbg_comport->rbr; + return in_8(&udbg_comport->rbr); } #ifdef CONFIG_PPC_PMAC else if (sccc) { - eieio(); - while ((*sccc & SCC_RXRDY) == 0) - eieio(); - return *sccd; + while ((in_8(sccc) & SCC_RXRDY) == 0) + ; + return in_8(sccd); } #endif /* CONFIG_PPC_PMAC */ return 0; @@ -191,9 +258,12 @@ void udbg_puts(const char *s) while ((c = *s++) != '\0') ppc_md.udbg_putc(c); } - } else { + } +#if 0 + else { printk("%s", s); } +#endif } int udbg_write(const char *s, int n) @@ -218,7 +288,7 @@ int udbg_read(char *buf, int buflen) char c, *p = buf; int i; - if (!ppc_md.udbg_putc) + if (!ppc_md.udbg_getc) return 0; for (i = 0; i < buflen; ++i) { diff --git a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c index 1430ef592..cb207629f 100644 --- a/arch/ppc64/kernel/vecemu.c +++ b/arch/ppc64/kernel/vecemu.c @@ -263,7 +263,7 @@ emulate_altivec(struct pt_regs *regs) unsigned int va, vb, vc, vd; vector128 *vrs; - if (get_user(instr, (unsigned int *) regs->nip)) + if (get_user(instr, (unsigned int __user *) regs->nip)) return -EFAULT; if ((instr >> 26) != 4) return -EINVAL; /* not an altivec instruction */ diff --git a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S index 940cd7287..b79d33e40 100644 --- a/arch/ppc64/kernel/vector.S +++ b/arch/ppc64/kernel/vector.S @@ -89,7 +89,7 @@ _GLOBAL(vmaddfp) 1: lfsx fr0,r4,r7 lfsx fr1,r5,r7 lfsx fr2,r6,r7 - fmadds fr0,fr0,fr1,fr2 + fmadds fr0,fr0,fr2,fr1 stfsx fr0,r3,r7 addi r7,r7,4 bdnz 1b @@ -109,7 +109,7 @@ _GLOBAL(vnmsubfp) 1: lfsx fr0,r4,r7 lfsx fr1,r5,r7 lfsx fr2,r6,r7 - fnmsubs fr0,fr0,fr1,fr2 + fnmsubs fr0,fr0,fr2,fr1 stfsx fr0,r3,r7 addi r7,r7,4 bdnz 1b diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c index a5fd6e772..ed2045177 100644 --- a/arch/ppc64/kernel/vio.c +++ b/arch/ppc64/kernel/vio.c @@ -225,6 +225,10 @@ static void probe_bus_iseries(void) struct vio_dev *viodev; int i; + /* there is only one of each of these */ + vio_register_device_iseries("viocons", 0); + vio_register_device_iseries("vscsi", 0); + vlan_map = HvLpConfig_getVirtualLanIndexMap(); for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { if ((vlan_map & (0x8000 >> i)) == 0) @@ -517,24 +521,7 @@ static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev) newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - /* RPA docs say that #address-cells is always 1 for virtual - devices, but some older boxes' OF returns 2. This should - be removed by GA, unless there is legacy OFs that still - have 2 for #address-cells */ - size = ((dma_window[1+vio_num_address_cells] >> PAGE_SHIFT) << 3) - >> PAGE_SHIFT; - - /* This is just an ugly kludge. Remove as soon as the OF for all - machines actually follow the spec and encodes the offset field - as phys-encode (that is, #address-cells wide)*/ - if (dma_window_property_size == 12) { - size = ((dma_window[1] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; - } else if (dma_window_property_size == 20) { - size = ((dma_window[4] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; - } else { - printk(KERN_WARNING "vio_build_iommu_table: Invalid size of ibm,my-dma-window=%i, using 0x80 for size\n", dma_window_property_size); - size = 0x80; - } + size = ((dma_window[4] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; /* There should be some code to extract the phys-encoded offset using prom_n_addr_cells(). However, according to a comment diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c index 7b6c257f4..a6e90222c 100644 --- a/arch/ppc64/kernel/viopath.c +++ b/arch/ppc64/kernel/viopath.c @@ -38,8 +38,8 @@ #include #include #include +#include -#include #include #include #include @@ -473,7 +473,7 @@ static int allocateEvents(HvLpIndex remoteLp, int numEvents) parms.used_wait_atomic = 0; parms.sem = &Semaphore; } - mf_allocateLpEvents(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */ + mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */ numEvents, &viopath_donealloc, &parms); if (in_atomic()) { while (atomic_read(&wait_atomic)) @@ -582,7 +582,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) doneAllocParms.used_wait_atomic = 0; doneAllocParms.sem = &Semaphore; - mf_deallocateLpEvents(remoteLp, HvLpEvent_Type_VirtualIo, + mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, numReq, &viopath_donealloc, &doneAllocParms); down(&Semaphore); diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S index 1d9b61143..4103cc13f 100644 --- a/arch/ppc64/kernel/vmlinux.lds.S +++ b/arch/ppc64/kernel/vmlinux.lds.S @@ -14,6 +14,7 @@ SECTIONS .text : { *(.text .text.*) SCHED_TEXT + LOCK_TEXT *(.fixup) . = ALIGN(4096); _etext = .; @@ -61,12 +62,6 @@ SECTIONS __setup_end = .; } - __param : { - __start___param = .; - *(__param) - __stop___param = .; - } - .initcall.init : { __initcall_start = .; *(.initcall1.init) @@ -122,10 +117,13 @@ SECTIONS .data : { *(.data .data.rel* .toc1) - *(.opd) *(.branch_lt) } + .opd : { + *(.opd) + } + .got : { __toc_start = .; *(.got) diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index c9f950c2c..674166e14 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -85,7 +85,7 @@ struct xics_ipl { } qirr; }; -static struct xics_ipl *xics_per_cpu[NR_CPUS]; +static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS]; static int xics_irq_8259_cascade = 0; static int xics_irq_8259_cascade_real = 0; @@ -116,22 +116,22 @@ typedef struct { static int pSeries_xirr_info_get(int n_cpu) { - return xics_per_cpu[n_cpu]->xirr.word; + return in_be32(&xics_per_cpu[n_cpu]->xirr.word); } static void pSeries_xirr_info_set(int n_cpu, int value) { - xics_per_cpu[n_cpu]->xirr.word = value; + out_be32(&xics_per_cpu[n_cpu]->xirr.word, value); } static void pSeries_cppr_info(int n_cpu, u8 value) { - xics_per_cpu[n_cpu]->xirr.bytes[0] = value; + out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value); } static void pSeries_qirr_info(int n_cpu, u8 value) { - xics_per_cpu[n_cpu]->qirr.bytes[0] = value; + out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value); } static xics_ops pSeries_ops = { @@ -216,12 +216,15 @@ xics_ops pSeriesLP_ops = { static unsigned int xics_startup(unsigned int virq) { - virq = irq_offset_down(virq); - if (radix_tree_insert(&irq_map, virt_irq_to_real(virq), - &virt_irq_to_real_map[virq]) == -ENOMEM) + unsigned int irq; + + irq = irq_offset_down(virq); + if (radix_tree_insert(&irq_map, virt_irq_to_real(irq), + &virt_irq_to_real_map[irq]) == -ENOMEM) printk(KERN_CRIT "Out of memory creating real -> virtual" " IRQ mapping for irq %u (real 0x%x)\n", - virq, virt_irq_to_real(virq)); + virq, virt_irq_to_real(irq)); + xics_enable_irq(virq); return 0; /* return value is ignored */ } @@ -454,7 +457,7 @@ void xics_init_IRQ(void) struct xics_interrupt_node { unsigned long addr; unsigned long size; - } inodes[NR_CPUS]; + } intnodes[NR_CPUS]; ppc64_boot_msg(0x20, "XICS Init"); @@ -481,13 +484,13 @@ nextnode: panic("xics_init_IRQ: can't find interrupt reg property"); while (ilen) { - inodes[indx].addr = (unsigned long long)*ireg++ << 32; + intnodes[indx].addr = (unsigned long)*ireg++ << 32; ilen -= sizeof(uint); - inodes[indx].addr |= *ireg++; + intnodes[indx].addr |= *ireg++; ilen -= sizeof(uint); - inodes[indx].size = (unsigned long long)*ireg++ << 32; + intnodes[indx].size = (unsigned long)*ireg++ << 32; ilen -= sizeof(uint); - inodes[indx].size |= *ireg++; + intnodes[indx].size |= *ireg++; ilen -= sizeof(uint); indx++; if (indx >= NR_CPUS) break; @@ -501,8 +504,9 @@ nextnode: np; np = of_find_node_by_type(np, "cpu")) { ireg = (uint *)get_property(np, "reg", &ilen); - if (ireg && ireg[0] == hard_smp_processor_id()) { - ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); + if (ireg && ireg[0] == boot_cpuid_phys) { + ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", + &ilen); i = ilen / sizeof(int); if (ireg && i > 0) { default_server = ireg[0]; @@ -513,8 +517,8 @@ nextnode: } of_node_put(np); - intr_base = inodes[0].addr; - intr_size = (ulong)inodes[0].size; + intr_base = intnodes[0].addr; + intr_size = intnodes[0].size; np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { @@ -535,16 +539,18 @@ nextnode: if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP for_each_cpu(i) { + int hard_id; + /* FIXME: Do this dynamically! --RR */ - if (!cpu_present_at_boot(i)) + if (!cpu_present(i)) continue; - xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, - (ulong)inodes[get_hard_smp_processor_id(i)].size, - _PAGE_NO_CACHE); + + hard_id = get_hard_smp_processor_id(i); + xics_per_cpu[i] = ioremap(intnodes[hard_id].addr, + intnodes[hard_id].size); } #else - xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, - _PAGE_NO_CACHE); + xics_per_cpu[0] = ioremap(intr_base, intr_size); #endif /* CONFIG_SMP */ } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; @@ -575,7 +581,7 @@ static int __init xics_setup_i8259(void) no_action, 0, "8259 cascade", NULL)) printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " "cascade\n"); - i8259_init(); + i8259_init(0); } return 0; } diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile index 01924ec67..48ae16077 100644 --- a/arch/ppc64/lib/Makefile +++ b/arch/ppc64/lib/Makefile @@ -15,3 +15,4 @@ ifdef CONFIG_PPC_ISERIES obj-$(CONFIG_PCI) += e2a.o endif +lib-$(CONFIG_XMON) += sstep.o diff --git a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S index 4ac6a63ca..ef96c6c58 100644 --- a/arch/ppc64/lib/checksum.S +++ b/arch/ppc64/lib/checksum.S @@ -92,19 +92,19 @@ _GLOBAL(csum_partial) adde r5,r5,r6 bdnz 2b andi. r4,r4,7 /* compute bytes left to sum after doublewords */ -3: cmpi 0,r4,4 /* is at least a full word left? */ +3: cmpwi 0,r4,4 /* is at least a full word left? */ blt 4f lwz r6,8(r3) /* sum this word */ addi r3,r3,4 subi r4,r4,4 adde r5,r5,r6 -4: cmpi 0,r4,2 /* is at least a halfword left? */ +4: cmpwi 0,r4,2 /* is at least a halfword left? */ blt+ 5f lhz r6,8(r3) /* sum this halfword */ addi r3,r3,2 subi r4,r4,2 adde r5,r5,r6 -5: cmpi 0,r4,1 /* is at least a byte left? */ +5: cmpwi 0,r4,1 /* is at least a byte left? */ bne+ 6f lbz r6,8(r3) /* sum this byte */ slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */ @@ -150,7 +150,7 @@ _GLOBAL(csum_partial_copy_generic) adde r0,r0,r6 bdnz 82b andi. r5,r5,3 -3: cmpi 0,r5,2 +3: cmpwi 0,r5,2 blt+ 4f 83: lhz r6,4(r3) addi r3,r3,2 @@ -158,7 +158,7 @@ _GLOBAL(csum_partial_copy_generic) 93: sth r6,4(r4) addi r4,r4,2 adde r0,r0,r6 -4: cmpi 0,r5,1 +4: cmpwi 0,r5,1 bne+ 5f 84: lbz r6,4(r3) 94: stb r6,4(r4) @@ -198,7 +198,7 @@ src_error_3: bdnz 97b .globl src_error src_error: - cmpi 0,r7,0 + cmpdi 0,r7,0 beq 1f li r6,-EFAULT stw r6,0(r7) @@ -207,7 +207,7 @@ src_error: .globl dst_error dst_error: - cmpi 0,r8,0 + cmpdi 0,r8,0 beq 1f li r6,-EFAULT stw r6,0(r8) diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c index 84ffb543b..6e8d85917 100644 --- a/arch/ppc64/lib/dec_and_lock.c +++ b/arch/ppc64/lib/dec_and_lock.c @@ -28,7 +28,7 @@ */ #ifndef ATOMIC_DEC_AND_LOCK -int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; @@ -51,5 +51,5 @@ int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) return 0; } -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif /* ATOMIC_DEC_AND_LOCK */ diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c index 58e973cc8..72d642d7e 100644 --- a/arch/ppc64/lib/locks.c +++ b/arch/ppc64/lib/locks.c @@ -20,28 +20,9 @@ #include #include -#ifndef CONFIG_SPINLINE - -/* - * On a system with shared processors (that is, where a physical - * processor is multiplexed between several virtual processors), - * there is no point spinning on a lock if the holder of the lock - * isn't currently scheduled on a physical processor. Instead - * we detect this situation and ask the hypervisor to give the - * rest of our timeslice to the lock holder. - * - * So that we can tell which virtual processor is holding a lock, - * we put 0x80000000 | smp_processor_id() in the lock when it is - * held. Conveniently, we have a word in the paca that holds this - * value. - */ - /* waiting for a spinlock... */ #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) -/* We only yield to the hypervisor if we are in shared processor mode */ -#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc) - void __spin_yield(spinlock_t *lock) { unsigned int lock_value, holder_cpu, yield_count; @@ -63,100 +44,16 @@ void __spin_yield(spinlock_t *lock) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); #else - plpar_hcall_norets(H_CONFER, holder_cpu, yield_count); + plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), + yield_count); #endif } -#else /* SPLPAR || ISERIES */ -#define __spin_yield(x) barrier() -#define SHARED_PROCESSOR 0 -#endif - -/* - * This returns the old value in the lock, so we succeeded - * in getting the lock if the return value is 0. - */ -static __inline__ unsigned long __spin_trylock(spinlock_t *lock) -{ - unsigned long tmp, tmp2; - - __asm__ __volatile__( -" lwz %1,%3(13) # __spin_trylock\n\ -1: lwarx %0,0,%2\n\ - cmpwi 0,%0,0\n\ - bne- 2f\n\ - stwcx. %1,0,%2\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r" (tmp), "=&r" (tmp2) - : "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token)) - : "cr0", "memory"); - - return tmp; -} - -int _raw_spin_trylock(spinlock_t *lock) -{ - return __spin_trylock(lock) == 0; -} - -EXPORT_SYMBOL(_raw_spin_trylock); - -void _raw_spin_lock(spinlock_t *lock) -{ - while (1) { - if (likely(__spin_trylock(lock) == 0)) - break; - do { - HMT_low(); - if (SHARED_PROCESSOR) - __spin_yield(lock); - } while (likely(lock->lock != 0)); - HMT_medium(); - } -} - -EXPORT_SYMBOL(_raw_spin_lock); - -void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags) -{ - unsigned long flags_dis; - - while (1) { - if (likely(__spin_trylock(lock) == 0)) - break; - local_save_flags(flags_dis); - local_irq_restore(flags); - do { - HMT_low(); - if (SHARED_PROCESSOR) - __spin_yield(lock); - } while (likely(lock->lock != 0)); - HMT_medium(); - local_irq_restore(flags_dis); - } -} - -EXPORT_SYMBOL(_raw_spin_lock_flags); - -void spin_unlock_wait(spinlock_t *lock) -{ - while (lock->lock) { - HMT_low(); - if (SHARED_PROCESSOR) - __spin_yield(lock); - } - HMT_medium(); -} - -EXPORT_SYMBOL(spin_unlock_wait); - /* * Waiting for a read lock or a write lock on a rwlock... * This turns out to be the same for read and write locks, since * we only know the holder if it is write-locked. */ -#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) void __rw_yield(rwlock_t *rw) { int lock_value; @@ -179,121 +76,20 @@ void __rw_yield(rwlock_t *rw) HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, ((u64)holder_cpu << 32) | yield_count); #else - plpar_hcall_norets(H_CONFER, holder_cpu, yield_count); + plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu), + yield_count); #endif } - -#else /* SPLPAR || ISERIES */ -#define __rw_yield(x) barrier() #endif -/* - * This returns the old value in the lock + 1, - * so we got a read lock if the return value is > 0. - */ -static __inline__ long __read_trylock(rwlock_t *rw) -{ - long tmp; - - __asm__ __volatile__( -"1: lwarx %0,0,%1 # read_trylock\n\ - extsw %0,%0\n\ - addic. %0,%0,1\n\ - ble- 2f\n\ - stwcx. %0,0,%1\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r" (tmp) - : "r" (&rw->lock) - : "cr0", "xer", "memory"); - - return tmp; -} - -int _raw_read_trylock(rwlock_t *rw) -{ - return __read_trylock(rw) > 0; -} - -EXPORT_SYMBOL(_raw_read_trylock); - -void _raw_read_lock(rwlock_t *rw) -{ - while (1) { - if (likely(__read_trylock(rw) > 0)) - break; - do { - HMT_low(); - if (SHARED_PROCESSOR) - __rw_yield(rw); - } while (likely(rw->lock < 0)); - HMT_medium(); - } -} - -EXPORT_SYMBOL(_raw_read_lock); - -void _raw_read_unlock(rwlock_t *rw) -{ - long tmp; - - __asm__ __volatile__( - "eieio # read_unlock\n\ -1: lwarx %0,0,%1\n\ - addic %0,%0,-1\n\ - stwcx. %0,0,%1\n\ - bne- 1b" - : "=&r"(tmp) - : "r"(&rw->lock) - : "cr0", "memory"); -} - -EXPORT_SYMBOL(_raw_read_unlock); - -/* - * This returns the old value in the lock, - * so we got the write lock if the return value is 0. - */ -static __inline__ long __write_trylock(rwlock_t *rw) -{ - long tmp, tmp2; - - __asm__ __volatile__( -" lwz %1,%3(13) # write_trylock\n\ -1: lwarx %0,0,%2\n\ - cmpwi 0,%0,0\n\ - bne- 2f\n\ - stwcx. %1,0,%2\n\ - bne- 1b\n\ - isync\n\ -2:" : "=&r" (tmp), "=&r" (tmp2) - : "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token)) - : "cr0", "memory"); - - return tmp; -} - -int _raw_write_trylock(rwlock_t *rw) -{ - return __write_trylock(rw) == 0; -} - -EXPORT_SYMBOL(_raw_write_trylock); - -void _raw_write_lock(rwlock_t *rw) +void spin_unlock_wait(spinlock_t *lock) { - while (1) { - if (likely(__write_trylock(rw) == 0)) - break; - do { - HMT_low(); - if (SHARED_PROCESSOR) - __rw_yield(rw); - } while (likely(rw->lock != 0)); - HMT_medium(); + while (lock->lock) { + HMT_low(); + if (SHARED_PROCESSOR) + __spin_yield(lock); } + HMT_medium(); } -EXPORT_SYMBOL(_raw_write_lock); - -#endif /* CONFIG_SPINLINE */ +EXPORT_SYMBOL(spin_unlock_wait); diff --git a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile index 0306babff..ac522d57b 100644 --- a/arch/ppc64/mm/Makefile +++ b/arch/ppc64/mm/Makefile @@ -4,6 +4,8 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o slb_low.o slb.o +obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \ + slb_low.o slb.o stab.o mmap.o obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S index 0d6b5c29b..68dd4b9ad 100644 --- a/arch/ppc64/mm/hash_low.S +++ b/arch/ppc64/mm/hash_low.S @@ -172,9 +172,9 @@ htab_insert_pte: li r9,0 _GLOBAL(htab_call_hpte_insert1) bl . /* Will be patched by htab_finish_init() */ - cmpi 0,r3,0 + cmpdi 0,r3,0 bge htab_pte_insert_ok /* Insertion successful */ - cmpi 0,r3,-2 /* Critical failure */ + cmpdi 0,r3,-2 /* Critical failure */ beq- htab_pte_insert_failure /* Now try secondary slot */ @@ -194,9 +194,9 @@ _GLOBAL(htab_call_hpte_insert1) li r9,0 _GLOBAL(htab_call_hpte_insert2) bl . /* Will be patched by htab_finish_init() */ - cmpi 0,r3,0 + cmpdi 0,r3,0 bge+ htab_pte_insert_ok /* Insertion successful */ - cmpi 0,r3,-2 /* Critical failure */ + cmpdi 0,r3,-2 /* Critical failure */ beq- htab_pte_insert_failure /* Both are full, we need to evict something */ @@ -263,7 +263,7 @@ _GLOBAL(htab_call_hpte_updatepp) /* if we failed because typically the HPTE wasn't really here * we try an insertion. */ - cmpi 0,r3,-1 + cmpdi 0,r3,-1 beq- htab_insert_pte /* Clear the BUSY bit and Write out the PTE */ @@ -278,6 +278,10 @@ htab_wrong_access: b bail htab_pte_insert_failure: - b .htab_insert_failure + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b bail diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c index 0d8c8ab19..77297fc9b 100644 --- a/arch/ppc64/mm/hash_native.c +++ b/arch/ppc64/mm/hash_native.c @@ -387,33 +387,37 @@ static void native_flush_hash_range(unsigned long context, local_irq_restore(flags); } -void hpte_init_native(void) -{ #ifdef CONFIG_PPC_PSERIES - struct device_node *root; - const char *model; -#endif /* CONFIG_PPC_PSERIES */ +/* Disable TLB batching on nighthawk */ +static inline int tlb_batching_enabled(void) +{ + struct device_node *root = of_find_node_by_path("/"); + int enabled = 1; + + if (root) { + const char *model = get_property(root, "model", NULL); + if (model && !strcmp(model, "IBM,9076-N81")) + enabled = 0; + of_node_put(root); + } + + return enabled; +} +#else +static inline int tlb_batching_enabled(void) +{ + return 1; +} +#endif +void hpte_init_native(void) +{ ppc_md.hpte_invalidate = native_hpte_invalidate; ppc_md.hpte_updatepp = native_hpte_updatepp; ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp; ppc_md.hpte_insert = native_hpte_insert; ppc_md.hpte_remove = native_hpte_remove; - -#ifdef CONFIG_PPC_PSERIES - /* Disable TLB batching on nighthawk */ - root = of_find_node_by_path("/"); - if (root) { - model = get_property(root, "model", NULL); - if (!strcmp(model, "CHRP IBM,9076-N81")) { - of_node_put(root); - goto bail; - } - of_node_put(root); - } -#endif /* CONFIG_PPC_PSERIES */ - - ppc_md.flush_hash_range = native_flush_hash_range; - bail: + if (tlb_batching_enabled()) + ppc_md.flush_hash_range = native_flush_hash_range; htab_finish_init(); } diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c index f40565840..c2aceedf9 100644 --- a/arch/ppc64/mm/hash_utils.c +++ b/arch/ppc64/mm/hash_utils.c @@ -18,6 +18,8 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include #include #include @@ -50,6 +53,12 @@ #include #include +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + /* * Note: pte --> Linux PTE * HPTE --> PowerPC Hashed Page Table Entry @@ -62,9 +71,9 @@ * */ -#ifdef CONFIG_PMAC_DART +#ifdef CONFIG_U3_DART extern unsigned long dart_tablebase; -#endif /* CONFIG_PMAC_DART */ +#endif /* CONFIG_U3_DART */ HTAB htab_data = {NULL, 0, 0, 0, 0}; @@ -80,7 +89,7 @@ static inline void loop_forever(void) ; } -#ifdef CONFIG_PPC_PSERIES +#ifdef CONFIG_PPC_MULTIPLATFORM static inline void create_pte_mapping(unsigned long start, unsigned long end, unsigned long mode, int large) { @@ -99,7 +108,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end, int ret; if (large) - vpn = va >> LARGE_PAGE_SHIFT; + vpn = va >> HPAGE_SHIFT; else vpn = va >> PAGE_SHIFT; @@ -107,12 +116,14 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end, hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - if (systemcfg->platform == PLATFORM_PSERIES_LPAR) +#ifdef CONFIG_PPC_PSERIES + if (systemcfg->platform & PLATFORM_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, virt_to_abs(addr) >> PAGE_SHIFT, 0, mode, 1, large); else - ret = pSeries_hpte_insert(hpteg, va, +#endif /* CONFIG_PPC_PSERIES */ + ret = native_hpte_insert(hpteg, va, virt_to_abs(addr) >> PAGE_SHIFT, 0, mode, 1, large); @@ -130,6 +141,8 @@ void __init htab_initialize(void) unsigned long mode_rw; int i, use_largepages = 0; + DBG(" -> htab_initialize()\n"); + /* * Calculate the required size of the htab. We want the number of * PTEGs to equal one half the number of real pages. @@ -146,12 +159,19 @@ void __init htab_initialize(void) htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (systemcfg->platform == PLATFORM_PSERIES || - systemcfg->platform == PLATFORM_POWERMAC) { + if (systemcfg->platform & PLATFORM_LPAR) { + /* Using a hypervisor which owns the htab */ + htab_data.htab = NULL; + _SDR1 = 0; + } else { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ table = lmb_alloc(htab_size_bytes, htab_size_bytes); + + DBG("Hash table allocated at %lx, size: %lx\n", table, + htab_size_bytes); + if ( !table ) { ppc64_terminate_msg(0x20, "hpt space"); loop_forever(); @@ -163,10 +183,6 @@ void __init htab_initialize(void) /* Initialize the HPT with no entries */ memset((void *)table, 0, htab_size_bytes); - } else { - /* Using a hypervisor which owns the htab */ - htab_data.htab = NULL; - _SDR1 = 0; } mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; @@ -178,14 +194,16 @@ void __init htab_initialize(void) if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) use_largepages = 1; - /* add all physical memory to the bootmem map */ + /* create bolted the linear mapping in the hash table */ for (i=0; i < lmb.memory.cnt; i++) { unsigned long base, size; base = lmb.memory.region[i].physbase + KERNELBASE; size = lmb.memory.region[i].size; -#ifdef CONFIG_PMAC_DART + DBG("creating mapping for region: %lx : %lx\n", base, size); + +#ifdef CONFIG_U3_DART /* Do not map the DART space. Fortunately, it will be aligned * in such a way that it will not cross two lmb regions and will * fit within a single 16Mb page. @@ -193,6 +211,8 @@ void __init htab_initialize(void) * only use 2Mb of that space. We will use more of it later for * AGP GART. We have to use a full 16Mb large page. */ + DBG("DART base: %lx\n", dart_tablebase); + if (dart_tablebase != 0 && dart_tablebase >= base && dart_tablebase < (base + size)) { if (base != dart_tablebase) @@ -203,13 +223,14 @@ void __init htab_initialize(void) mode_rw, use_largepages); continue; } -#endif /* CONFIG_PMAC_DART */ +#endif /* CONFIG_U3_DART */ create_pte_mapping(base, base + size, mode_rw, use_largepages); } + DBG(" <- htab_initialize()\n"); } #undef KB #undef MB -#endif +#endif /* CONFIG_PPC_MULTIPLATFORM */ /* * Called by asm hashtable.S for doing lazy icache flush @@ -236,14 +257,11 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) return pp; } -/* - * Called by asm hashtable.S in case of critical insert failure +/* Result code is: + * 0 - handled + * 1 - normal page fault + * -1 - critical hash insertion error */ -void htab_insert_failure(void) -{ - panic("hash_page: pte_insert failed\n"); -} - int hash_page(unsigned long ea, unsigned long access, unsigned long trap) { void *pgdir; @@ -255,24 +273,24 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) int local = 0; cpumask_t tmp; - /* Check for invalid addresses. */ - if (!IS_VALID_EA(ea)) - return 1; - switch (REGION_ID(ea)) { case USER_REGION_ID: user_region = 1; mm = current->mm; - if (mm == NULL) + if ((ea > USER_END) || (! mm)) return 1; vsid = get_vsid(mm->context.id, ea); break; case IO_REGION_ID: + if (ea > IMALLOC_END) + return 1; mm = &ioremap_mm; vsid = get_kernel_vsid(ea); break; case VMALLOC_REGION_ID: + if (ea > VMALLOC_END) + return 1; mm = &init_mm; vsid = get_kernel_vsid(ea); break; @@ -323,9 +341,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, int local) { unsigned long vsid, vpn, va, hash, secondary, slot; - - /* XXX fix for large ptes */ - unsigned long large = 0; + unsigned long huge = pte_huge(pte); if ((ea >= USER_START) && (ea <= USER_END)) vsid = get_vsid(context, ea); @@ -333,18 +349,18 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - if (large) - vpn = va >> LARGE_PAGE_SHIFT; + if (huge) + vpn = va >> HPAGE_SHIFT; else vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, large); + hash = hpt_hash(vpn, huge); secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; if (secondary) hash = ~hash; slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; - ppc_md.hpte_invalidate(slot, va, large, local); + ppc_md.hpte_invalidate(slot, va, huge, local); } void flush_hash_range(unsigned long context, unsigned long number, int local) @@ -371,6 +387,25 @@ static inline void make_bl(unsigned int *insn_addr, void *func) (unsigned long)insn_addr); } +/* + * low_hash_fault is called when we the low level hash code failed + * to instert a PTE due to an hypervisor error + */ +void low_hash_fault(struct pt_regs *regs, unsigned long address) +{ + if (user_mode(regs)) { + siginfo_t info; + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void __user *)address; + force_sig_info(SIGBUS, &info, current); + return; + } + bad_page_fault(regs, address, SIGBUS); +} + void __init htab_finish_init(void) { extern unsigned int *htab_call_hpte_insert1; diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c index b704e00d2..7fbc4d063 100644 --- a/arch/ppc64/mm/hugetlbpage.c +++ b/arch/ppc64/mm/hugetlbpage.c @@ -27,116 +27,143 @@ #include -/* HugePTE layout: - * - * 31 30 ... 15 14 13 12 10 9 8 7 6 5 4 3 2 1 0 - * PFN>>12..... - - - - - - HASH_IX.... 2ND HASH RW - HG=1 - */ +#define HUGEPGDIR_SHIFT (HPAGE_SHIFT + PAGE_SHIFT - 3) +#define HUGEPGDIR_SIZE (1UL << HUGEPGDIR_SHIFT) +#define HUGEPGDIR_MASK (~(HUGEPGDIR_SIZE-1)) + +#define HUGEPTE_INDEX_SIZE 9 +#define HUGEPGD_INDEX_SIZE 10 + +#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE) +#define PTRS_PER_HUGEPGD (1 << HUGEPGD_INDEX_SIZE) -#define HUGEPTE_SHIFT 15 -#define _HUGEPAGE_PFN 0xffff8000 -#define _HUGEPAGE_BAD 0x00007f00 -#define _HUGEPAGE_HASHPTE 0x00000008 -#define _HUGEPAGE_SECONDARY 0x00000010 -#define _HUGEPAGE_GROUP_IX 0x000000e0 -#define _HUGEPAGE_HPTEFLAGS (_HUGEPAGE_HASHPTE | _HUGEPAGE_SECONDARY | \ - _HUGEPAGE_GROUP_IX) -#define _HUGEPAGE_RW 0x00000004 - -typedef struct {unsigned int val;} hugepte_t; -#define hugepte_val(hugepte) ((hugepte).val) -#define __hugepte(x) ((hugepte_t) { (x) } ) -#define hugepte_pfn(x) \ - ((unsigned long)(hugepte_val(x)>>HUGEPTE_SHIFT) << HUGETLB_PAGE_ORDER) -#define mk_hugepte(page,wr) __hugepte( \ - ((page_to_pfn(page)>>HUGETLB_PAGE_ORDER) << HUGEPTE_SHIFT ) \ - | (!!(wr) * _HUGEPAGE_RW) | _PMD_HUGEPAGE ) - -#define hugepte_bad(x) ( !(hugepte_val(x) & _PMD_HUGEPAGE) || \ - (hugepte_val(x) & _HUGEPAGE_BAD) ) -#define hugepte_page(x) pfn_to_page(hugepte_pfn(x)) -#define hugepte_none(x) (!(hugepte_val(x) & _HUGEPAGE_PFN)) - - -static void flush_hash_hugepage(mm_context_t context, unsigned long ea, - hugepte_t pte, int local); - -static inline unsigned int hugepte_update(hugepte_t *p, unsigned int clr, - unsigned int set) +static inline int hugepgd_index(unsigned long addr) { - unsigned int old, tmp; - - __asm__ __volatile__( - "1: lwarx %0,0,%3 # pte_update\n\ - andc %1,%0,%4 \n\ - or %1,%1,%5 \n\ - stwcx. %1,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=&r" (tmp), "=m" (*p) - : "r" (p), "r" (clr), "r" (set), "m" (*p) - : "cc" ); - return old; + return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT; } -static inline void set_hugepte(hugepte_t *ptep, hugepte_t pte) +static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr) { - hugepte_update(ptep, ~_HUGEPAGE_HPTEFLAGS, - hugepte_val(pte) & ~_HUGEPAGE_HPTEFLAGS); + int index; + + if (! mm->context.huge_pgdir) + return NULL; + + + index = hugepgd_index(addr); + BUG_ON(index >= PTRS_PER_HUGEPGD); + return mm->context.huge_pgdir + index; } -static hugepte_t *hugepte_alloc(struct mm_struct *mm, unsigned long addr) +static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr) { - pgd_t *pgd; - pmd_t *pmd = NULL; + int index; - BUG_ON(!in_hugepage_area(mm->context, addr)); + if (pgd_none(*dir)) + return NULL; - pgd = pgd_offset(mm, addr); - pmd = pmd_alloc(mm, pgd, addr); + index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE; + return (pte_t *)pgd_page(*dir) + index; +} - /* We shouldn't find a (normal) PTE page pointer here */ - BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd)); - - return (hugepte_t *)pmd; +static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr) +{ + BUG_ON(! in_hugepage_area(mm->context, addr)); + + if (! mm->context.huge_pgdir) { + pgd_t *new; + spin_unlock(&mm->page_table_lock); + /* Don't use pgd_alloc(), because we want __GFP_REPEAT */ + new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT); + BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE)); + spin_lock(&mm->page_table_lock); + + /* + * Because we dropped the lock, we should re-check the + * entry, as somebody else could have populated it.. + */ + if (mm->context.huge_pgdir) + pgd_free(new); + else + mm->context.huge_pgdir = new; + } + return hugepgd_offset(mm, addr); } -static hugepte_t *hugepte_offset(struct mm_struct *mm, unsigned long addr) +static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir, + unsigned long addr) { - pgd_t *pgd; - pmd_t *pmd = NULL; + if (! pgd_present(*dir)) { + pte_t *new; + + spin_unlock(&mm->page_table_lock); + new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT); + BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE)); + spin_lock(&mm->page_table_lock); + /* + * Because we dropped the lock, we should re-check the + * entry, as somebody else could have populated it.. + */ + if (pgd_present(*dir)) { + if (new) + kmem_cache_free(zero_cache, new); + } else { + struct page *ptepage; + + if (! new) + return NULL; + ptepage = virt_to_page(new); + ptepage->mapping = (void *) mm; + ptepage->index = addr & HUGEPGDIR_MASK; + pgd_populate(mm, dir, new); + } + } - BUG_ON(!in_hugepage_area(mm->context, addr)); + return hugepte_offset(dir, addr); +} - pgd = pgd_offset(mm, addr); - if (pgd_none(*pgd)) - return NULL; +static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) +{ + pgd_t *pgd; - pmd = pmd_offset(pgd, addr); + BUG_ON(! in_hugepage_area(mm->context, addr)); - /* We shouldn't find a (normal) PTE page pointer here */ - BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd)); + pgd = hugepgd_offset(mm, addr); + if (! pgd) + return NULL; - return (hugepte_t *)pmd; + return hugepte_offset(pgd, addr); } -static void setup_huge_pte(struct mm_struct *mm, struct page *page, - hugepte_t *ptep, int write_access) +static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) { - hugepte_t entry; - int i; + pgd_t *pgd; - mm->rss += (HPAGE_SIZE / PAGE_SIZE); - entry = mk_hugepte(page, write_access); - for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) - set_hugepte(ptep+i, entry); + BUG_ON(! in_hugepage_area(mm->context, addr)); + + pgd = hugepgd_alloc(mm, addr); + if (! pgd) + return NULL; + + return hugepte_alloc(mm, pgd, addr); } -static void teardown_huge_pte(hugepte_t *ptep) +static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, + struct page *page, pte_t *ptep, int write_access) { - int i; + pte_t entry; + + mm->rss += (HPAGE_SIZE / PAGE_SIZE); + if (write_access) { + entry = + pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); + } else { + entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot)); + } + entry = pte_mkyoung(entry); + entry = pte_mkhuge(entry); - for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) - pmd_clear((pmd_t *)(ptep+i)); + set_pte(ptep, entry); } /* @@ -213,6 +240,7 @@ static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg) } page = pmd_page(*pmd); pmd_clear(pmd); + mm->nr_ptes--; dec_page_state(nr_page_table_pages); pte_free_tlb(tlb, page); } @@ -248,7 +276,7 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len) { if (within_hugepage_high_range(addr, len)) return 0; - else if ((addr < 0x100000000) && ((addr+len) < 0x100000000)) { + else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) { int err; /* Yes, we need both tests, in case addr+len overflows * 64-bit arithmetic */ @@ -267,34 +295,31 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len) int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { - hugepte_t *src_pte, *dst_pte, entry; + pte_t *src_pte, *dst_pte, entry; struct page *ptepage; unsigned long addr = vma->vm_start; unsigned long end = vma->vm_end; + int err = -ENOMEM; while (addr < end) { - BUG_ON(! in_hugepage_area(src->context, addr)); - BUG_ON(! in_hugepage_area(dst->context, addr)); - - dst_pte = hugepte_alloc(dst, addr); + dst_pte = huge_pte_alloc(dst, addr); if (!dst_pte) - return -ENOMEM; + goto out; - src_pte = hugepte_offset(src, addr); + src_pte = huge_pte_offset(src, addr); entry = *src_pte; - if ((addr % HPAGE_SIZE) == 0) { - /* This is the first hugepte in a batch */ - ptepage = hugepte_page(entry); - get_page(ptepage); - dst->rss += (HPAGE_SIZE / PAGE_SIZE); - } - set_hugepte(dst_pte, entry); + ptepage = pte_page(entry); + get_page(ptepage); + dst->rss += (HPAGE_SIZE / PAGE_SIZE); + set_pte(dst_pte, entry); - - addr += PMD_SIZE; + addr += HPAGE_SIZE; } - return 0; + + err = 0; + out: + return err; } int @@ -309,18 +334,16 @@ follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, vpfn = vaddr/PAGE_SIZE; while (vaddr < vma->vm_end && remainder) { - BUG_ON(!in_hugepage_area(mm->context, vaddr)); - if (pages) { - hugepte_t *pte; + pte_t *pte; struct page *page; - pte = hugepte_offset(mm, vaddr); + pte = huge_pte_offset(mm, vaddr); /* hugetlb should be locked, and hence, prefaulted */ - WARN_ON(!pte || hugepte_none(*pte)); + WARN_ON(!pte || pte_none(*pte)); - page = &hugepte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; + page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; WARN_ON(!PageCompound(page)); @@ -346,26 +369,31 @@ follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { - return ERR_PTR(-EINVAL); + pte_t *ptep; + struct page *page; + + if (! in_hugepage_area(mm->context, address)) + return ERR_PTR(-EINVAL); + + ptep = huge_pte_offset(mm, address); + page = pte_page(*ptep); + if (page) + page += (address % HPAGE_SIZE) / PAGE_SIZE; + + return page; } int pmd_huge(pmd_t pmd) { - return pmd_hugepage(pmd); + return 0; } struct page * follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write) { - struct page *page; - - BUG_ON(! pmd_hugepage(*pmd)); - - page = hugepte_page(*(hugepte_t *)pmd); - if (page) - page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT); - return page; + BUG(); + return NULL; } void unmap_hugepage_range(struct vm_area_struct *vma, @@ -373,44 +401,38 @@ void unmap_hugepage_range(struct vm_area_struct *vma, { struct mm_struct *mm = vma->vm_mm; unsigned long addr; - hugepte_t *ptep; + pte_t *ptep; struct page *page; - int cpu; - int local = 0; - cpumask_t tmp; WARN_ON(!is_vm_hugetlb_page(vma)); BUG_ON((start % HPAGE_SIZE) != 0); BUG_ON((end % HPAGE_SIZE) != 0); - /* XXX are there races with checking cpu_vm_mask? - Anton */ - cpu = get_cpu(); - tmp = cpumask_of_cpu(cpu); - if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) - local = 1; - for (addr = start; addr < end; addr += HPAGE_SIZE) { - hugepte_t pte; - - BUG_ON(!in_hugepage_area(mm->context, addr)); + pte_t pte; - ptep = hugepte_offset(mm, addr); - if (!ptep || hugepte_none(*ptep)) + ptep = huge_pte_offset(mm, addr); + if (!ptep || pte_none(*ptep)) continue; pte = *ptep; - page = hugepte_page(pte); - teardown_huge_pte(ptep); - - if (hugepte_val(pte) & _HUGEPAGE_HASHPTE) - flush_hash_hugepage(mm->context, addr, - pte, local); + page = pte_page(pte); + pte_clear(ptep); put_page(page); } - put_cpu(); - mm->rss -= (end - start) >> PAGE_SHIFT; + flush_tlb_pending(); +} + +void hugetlb_free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev, + unsigned long start, unsigned long end) +{ + /* Because the huge pgtables are only 2 level, they can take + * at most around 4M, much less than one hugepage which the + * process is presumably entitled to use. So we don't bother + * freeing up the pagetables on unmap, and wait until + * destroy_context() to clean up the lot. */ } int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) @@ -426,16 +448,14 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) spin_lock(&mm->page_table_lock); for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { unsigned long idx; - hugepte_t *pte = hugepte_alloc(mm, addr); + pte_t *pte = huge_pte_alloc(mm, addr); struct page *page; - BUG_ON(!in_hugepage_area(mm->context, addr)); - if (!pte) { ret = -ENOMEM; goto out; } - if (!hugepte_none(*pte)) + if (! pte_none(*pte)) continue; idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) @@ -462,7 +482,7 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) goto out; } } - setup_huge_pte(mm, page, pte, vma->vm_flags & VM_WRITE); + set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); } out: spin_unlock(&mm->page_table_lock); @@ -527,6 +547,108 @@ full_search: return -ENOMEM; } +/* + * This mmap-allocator allocates new areas top-down from below the + * stack's low limit (the base): + * + * Because we have an exclusive hugepage region which lies within the + * normal user address space, we have to take special measures to make + * non-huge mmap()s evade the hugepage reserved regions. + */ +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) +{ + struct vm_area_struct *vma, *prev_vma; + struct mm_struct *mm = current->mm; + unsigned long base = mm->mmap_base, addr = addr0; + int first_time = 1; + + /* requested length too big for entire address space */ + if (len > TASK_SIZE) + return -ENOMEM; + + /* dont allow allocations above current base */ + if (mm->free_area_cache > base) + mm->free_area_cache = base; + + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start) + && !is_hugepage_only_range(addr,len)) + return addr; + } + +try_again: + /* make sure it can fit in the remaining address space */ + if (mm->free_area_cache < len) + goto fail; + + /* either no address requested or cant fit in requested address hole */ + addr = (mm->free_area_cache - len) & PAGE_MASK; + do { +hugepage_recheck: + if (touches_hugepage_low_range(addr, len)) { + addr = (addr & ((~0) << SID_SHIFT)) - len; + goto hugepage_recheck; + } else if (touches_hugepage_high_range(addr, len)) { + addr = TASK_HPAGE_BASE - len; + } + + /* + * Lookup failure means no vma is above this address, + * i.e. return with success: + */ + if (!(vma = find_vma_prev(mm, addr, &prev_vma))) + return addr; + + /* + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ + if (addr+len <= vma->vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + else + /* pull free_area_cache down to the first hole */ + if (mm->free_area_cache == vma->vm_end) + mm->free_area_cache = vma->vm_start; + + /* try just below the current vma->vm_start */ + addr = vma->vm_start-len; + } while (len <= vma->vm_start); + +fail: + /* + * if hint left us with no space for the requested + * mapping then try again: + */ + if (first_time) { + mm->free_area_cache = base; + first_time = 0; + goto try_again; + } + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + mm->free_area_cache = TASK_UNMAPPED_BASE; + addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); + /* + * Restore the topdown base: + */ + mm->free_area_cache = base; + + return addr; +} + static unsigned long htlb_get_low_area(unsigned long len, u16 segmask) { unsigned long addr = 0; @@ -614,20 +736,55 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, } } +void hugetlb_mm_free_pgd(struct mm_struct *mm) +{ + int i; + pgd_t *pgdir; + + spin_lock(&mm->page_table_lock); + + pgdir = mm->context.huge_pgdir; + if (! pgdir) + return; + + mm->context.huge_pgdir = NULL; + + /* cleanup any hugepte pages leftover */ + for (i = 0; i < PTRS_PER_HUGEPGD; i++) { + pgd_t *pgd = pgdir + i; + + if (! pgd_none(*pgd)) { + pte_t *pte = (pte_t *)pgd_page(*pgd); + struct page *ptepage = virt_to_page(pte); + + ptepage->mapping = NULL; + + BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE)); + kmem_cache_free(zero_cache, pte); + } + pgd_clear(pgd); + } + + BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE)); + kmem_cache_free(zero_cache, pgdir); + + spin_unlock(&mm->page_table_lock); +} + int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long ea, unsigned long vsid, int local) { - hugepte_t *ptep; + pte_t *ptep; unsigned long va, vpn; int is_write; - hugepte_t old_pte, new_pte; - unsigned long hpteflags, prpn, flags; + pte_t old_pte, new_pte; + unsigned long hpteflags, prpn; long slot; + int err = 1; - /* We have to find the first hugepte in the batch, since - * that's the one that will store the HPTE flags */ - ea &= HPAGE_MASK; - ptep = hugepte_offset(mm, ea); + spin_lock(&mm->page_table_lock); + + ptep = huge_pte_offset(mm, ea); /* Search the Linux page table for a match with va */ va = (vsid << 28) | (ea & 0x0fffffff); @@ -637,19 +794,18 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, * If no pte found or not present, send the problem up to * do_page_fault */ - if (unlikely(!ptep || hugepte_none(*ptep))) - return 1; + if (unlikely(!ptep || pte_none(*ptep))) + goto out; - BUG_ON(hugepte_bad(*ptep)); +/* BUG_ON(pte_bad(*ptep)); */ /* * Check the user's access rights to the page. If access should be * prevented then send the problem up to do_page_fault. */ is_write = access & _PAGE_RW; - if (unlikely(is_write && !(hugepte_val(*ptep) & _HUGEPAGE_RW))) - return 1; - + if (unlikely(is_write && !(pte_val(*ptep) & _PAGE_RW))) + goto out; /* * At this point, we have a pte (old_pte) which can be used to build * or update an HPTE. There are 2 cases: @@ -662,41 +818,40 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, * page is currently not DIRTY. */ - spin_lock_irqsave(&mm->page_table_lock, flags); old_pte = *ptep; new_pte = old_pte; - hpteflags = 0x2 | (! (hugepte_val(new_pte) & _HUGEPAGE_RW)); + hpteflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW)); /* Check if pte already has an hpte (case 2) */ - if (unlikely(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE)) { + if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) { /* There MIGHT be an HPTE for this pte */ unsigned long hash, slot; hash = hpt_hash(vpn, 1); - if (hugepte_val(old_pte) & _HUGEPAGE_SECONDARY) + if (pte_val(old_pte) & _PAGE_SECONDARY) hash = ~hash; slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; - slot += (hugepte_val(old_pte) & _HUGEPAGE_GROUP_IX) >> 5; + slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12; if (ppc_md.hpte_updatepp(slot, hpteflags, va, 1, local) == -1) - hugepte_val(old_pte) &= ~_HUGEPAGE_HPTEFLAGS; + pte_val(old_pte) &= ~_PAGE_HPTEFLAGS; } - if (likely(!(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE))) { + if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) { unsigned long hash = hpt_hash(vpn, 1); unsigned long hpte_group; - prpn = hugepte_pfn(old_pte); + prpn = pte_pfn(old_pte); repeat: hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; /* Update the linux pte with the HPTE slot */ - hugepte_val(new_pte) &= ~_HUGEPAGE_HPTEFLAGS; - hugepte_val(new_pte) |= _HUGEPAGE_HASHPTE; + pte_val(new_pte) &= ~_PAGE_HPTEFLAGS; + pte_val(new_pte) |= _PAGE_HASHPTE; /* Add in WIMG bits */ /* XXX We should store these in the pte */ @@ -707,7 +862,7 @@ repeat: /* Primary is full, try the secondary */ if (unlikely(slot == -1)) { - hugepte_val(new_pte) |= _HUGEPAGE_SECONDARY; + pte_val(new_pte) |= _PAGE_SECONDARY; hpte_group = ((~hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; slot = ppc_md.hpte_insert(hpte_group, va, prpn, @@ -724,39 +879,20 @@ repeat: if (unlikely(slot == -2)) panic("hash_huge_page: pte_insert failed\n"); - hugepte_val(new_pte) |= (slot<<5) & _HUGEPAGE_GROUP_IX; + pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX; /* * No need to use ldarx/stdcx here because all who * might be updating the pte will hold the - * page_table_lock or the hash_table_lock - * (we hold both) + * page_table_lock */ *ptep = new_pte; } - spin_unlock_irqrestore(&mm->page_table_lock, flags); + err = 0; - return 0; -} - -static void flush_hash_hugepage(mm_context_t context, unsigned long ea, - hugepte_t pte, int local) -{ - unsigned long vsid, vpn, va, hash, slot; - - BUG_ON(hugepte_bad(pte)); - BUG_ON(!in_hugepage_area(context, ea)); - - vsid = get_vsid(context.id, ea); + out: + spin_unlock(&mm->page_table_lock); - va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> LARGE_PAGE_SHIFT; - hash = hpt_hash(vpn, 1); - if (hugepte_val(pte) & _HUGEPAGE_SECONDARY) - hash = ~hash; - slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; - slot += (hugepte_val(pte) & _HUGEPAGE_GROUP_IX) >> 5; - - ppc_md.hpte_invalidate(slot, va, 1, local); + return err; } diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c index 2399f3fcb..9d92b0d9c 100644 --- a/arch/ppc64/mm/imalloc.c +++ b/arch/ppc64/mm/imalloc.c @@ -37,33 +37,51 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr) return 0; } +/* Return whether the region described by v_addr and size is a subset + * of the region described by parent + */ +static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, + struct vm_struct *parent) +{ + return (int) (v_addr >= (unsigned long) parent->addr && + v_addr < (unsigned long) parent->addr + parent->size && + size < parent->size); +} + +/* Return whether the region described by v_addr and size is a superset + * of the region described by child + */ +static int im_region_is_superset(unsigned long v_addr, unsigned long size, + struct vm_struct *child) +{ + struct vm_struct parent; + + parent.addr = (void *) v_addr; + parent.size = size; + + return im_region_is_subset((unsigned long) child->addr, child->size, + &parent); +} + /* Return whether the region described by v_addr and size overlaps - * the region described by vm. Overlapping regions meet the + * the region described by vm. Overlapping regions meet the * following conditions: * 1) The regions share some part of the address space * 2) The regions aren't identical - * 3) The first region is not a subset of the second + * 3) Neither region is a subset of the other */ -static inline int im_region_overlaps(unsigned long v_addr, unsigned long size, +static int im_region_overlaps(unsigned long v_addr, unsigned long size, struct vm_struct *vm) { + if (im_region_is_superset(v_addr, size, vm)) + return 0; + return (v_addr + size > (unsigned long) vm->addr + vm->size && v_addr < (unsigned long) vm->addr + vm->size) || (v_addr < (unsigned long) vm->addr && v_addr + size > (unsigned long) vm->addr); } -/* Return whether the region described by v_addr and size is a subset - * of the region described by vm - */ -static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, - struct vm_struct *vm) -{ - return (int) (v_addr >= (unsigned long) vm->addr && - v_addr < (unsigned long) vm->addr + vm->size && - size < vm->size); -} - /* Determine imalloc status of region described by v_addr and size. * Can return one of the following: * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. @@ -73,28 +91,37 @@ static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, * IM_REGION_EXISTS - Exact region already allocated in imalloc space. * vm will be assigned to a ptr to the existing imlist * member. - * IM_REGION_OVERLAPS - A portion of the region is already allocated in - * imalloc space. + * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space. + * IM_REGION_SUPERSET - Region is a superset of a region that is already + * allocated in imalloc space. */ -static int im_region_status(unsigned long v_addr, unsigned long size, +static int im_region_status(unsigned long v_addr, unsigned long size, struct vm_struct **vm) { struct vm_struct *tmp; - for (tmp = imlist; tmp; tmp = tmp->next) - if (v_addr < (unsigned long) tmp->addr + tmp->size) + for (tmp = imlist; tmp; tmp = tmp->next) + if (v_addr < (unsigned long) tmp->addr + tmp->size) break; - + if (tmp) { if (im_region_overlaps(v_addr, size, tmp)) return IM_REGION_OVERLAP; *vm = tmp; - if (im_region_is_subset(v_addr, size, tmp)) + if (im_region_is_subset(v_addr, size, tmp)) { + /* Return with tmp pointing to superset */ return IM_REGION_SUBSET; - else if (v_addr == (unsigned long) tmp->addr && - size == tmp->size) + } + if (im_region_is_superset(v_addr, size, tmp)) { + /* Return with tmp pointing to first subset */ + return IM_REGION_SUPERSET; + } + else if (v_addr == (unsigned long) tmp->addr && + size == tmp->size) { + /* Return with tmp pointing to exact region */ return IM_REGION_EXISTS; + } } *vm = NULL; @@ -208,6 +235,10 @@ static struct vm_struct * __im_get_area(unsigned long req_addr, tmp = split_im_region(req_addr, size, tmp); break; case IM_REGION_EXISTS: + /* Return requested region */ + break; + case IM_REGION_SUPERSET: + /* Return first existing subset of requested region */ break; default: printk(KERN_ERR "%s() unexpected imalloc region status\n", diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index 99d923868..d5f98fc77 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,6 @@ #include #include - -struct mmu_context_queue_t mmu_context_queue; int mem_init_done; unsigned long ioremap_bot = IMALLOC_BASE; static unsigned long phbs_io_bot = PHBS_IO_BASE; @@ -85,7 +84,6 @@ unsigned long __max_memory; /* info on what we think the IO hole is */ unsigned long io_hole_start; unsigned long io_hole_size; -unsigned long top_of_ram; void show_mem(void) { @@ -118,18 +116,18 @@ void show_mem(void) #ifdef CONFIG_PPC_ISERIES -void *ioremap(unsigned long addr, unsigned long size) +void __iomem *ioremap(unsigned long addr, unsigned long size) { - return (void *)addr; + return (void __iomem *)addr; } -extern void *__ioremap(unsigned long addr, unsigned long size, +extern void __iomem *__ioremap(unsigned long addr, unsigned long size, unsigned long flags) { - return (void *)addr; + return (void __iomem *)addr; } -void iounmap(void *addr) +void iounmap(volatile void __iomem *addr) { return; } @@ -183,7 +181,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags) } -static void * __ioremap_com(unsigned long addr, unsigned long pa, +static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, unsigned long ea, unsigned long size, unsigned long flags) { @@ -198,20 +196,17 @@ static void * __ioremap_com(unsigned long addr, unsigned long pa, map_io_page(ea+i, pa+i, flags); } - return (void *) (ea + (addr & ~PAGE_MASK)); + return (void __iomem *) (ea + (addr & ~PAGE_MASK)); } -void * +void __iomem * ioremap(unsigned long addr, unsigned long size) { - void *ret = __ioremap(addr, size, _PAGE_NO_CACHE); - if(mem_init_done) - return eeh_ioremap(addr, ret); /* may remap the addr */ - return ret; + return __ioremap(addr, size, _PAGE_NO_CACHE); } -void * +void __iomem * __ioremap(unsigned long addr, unsigned long size, unsigned long flags) { unsigned long pa, ea; @@ -268,9 +263,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, */ ; } else { - area = im_get_area(ea, size, IM_REGION_UNUSED|IM_REGION_SUBSET); + area = im_get_area(ea, size, + IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); if (area == NULL) { - printk(KERN_ERR "could not obtain imalloc area for ea 0x%lx\n", ea); + /* Expected when PHB-dlpar is in play */ return 1; } if (ea != (unsigned long) area->addr) { @@ -354,19 +350,18 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, * * XXX what about calls before mem_init_done (ie python_countermeasures()) */ -void iounmap(void *addr) +void iounmap(volatile void __iomem *token) { unsigned long address, start, end, size; struct mm_struct *mm; pgd_t *dir; + void *addr; if (!mem_init_done) { return; } - /* addr could be in EEH or IO region, map it to IO region regardless. - */ - addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK); + addr = (void *) ((unsigned long __force) token & PAGE_MASK); if ((size = im_free(addr)) == 0) { return; @@ -392,27 +387,55 @@ void iounmap(void *addr) return; } -int iounmap_explicit(void *addr, unsigned long size) +static int iounmap_subset_regions(unsigned long addr, unsigned long size) +{ + struct vm_struct *area; + + /* Check whether subsets of this region exist */ + area = im_get_area(addr, size, IM_REGION_SUPERSET); + if (area == NULL) + return 1; + + while (area) { + iounmap((void __iomem *) area->addr); + area = im_get_area(addr, size, + IM_REGION_SUPERSET); + } + + return 0; +} + +int iounmap_explicit(volatile void __iomem *start, unsigned long size) { struct vm_struct *area; + unsigned long addr; + int rc; - /* addr could be in EEH or IO region, map it to IO region regardless. - */ - addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK); + addr = (unsigned long __force) start & PAGE_MASK; /* Verify that the region either exists or is a subset of an existing * region. In the latter case, split the parent region to create * the exact region */ - area = im_get_area((unsigned long) addr, size, + area = im_get_area(addr, size, IM_REGION_EXISTS | IM_REGION_SUBSET); if (area == NULL) { - printk(KERN_ERR "%s() cannot unmap nonexistent range 0x%lx\n", - __FUNCTION__, (unsigned long) addr); - return 1; + /* Determine whether subset regions exist. If so, unmap */ + rc = iounmap_subset_regions(addr, size); + if (rc) { + printk(KERN_ERR + "%s() cannot unmap nonexistent range 0x%lx\n", + __FUNCTION__, addr); + return 1; + } + } else { + iounmap((void __iomem *) area->addr); } - + /* + * FIXME! This can't be right: iounmap(area->addr); + * Maybe it should be "iounmap(area);" + */ return 0; } @@ -447,41 +470,76 @@ void free_initrd_mem(unsigned long start, unsigned long end) } #endif +static spinlock_t mmu_context_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_IDR(mmu_context_idr); + +int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + int index; + int err; + +#ifdef CONFIG_HUGETLB_PAGE + /* We leave htlb_segs as it was, but for a fork, we need to + * clear the huge_pgdir. */ + mm->context.huge_pgdir = NULL; +#endif + +again: + if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL)) + return -ENOMEM; + + spin_lock(&mmu_context_lock); + err = idr_get_new_above(&mmu_context_idr, NULL, 1, &index); + spin_unlock(&mmu_context_lock); + + if (err == -EAGAIN) + goto again; + else if (err) + return err; + + if (index > MAX_CONTEXT) { + idr_remove(&mmu_context_idr, index); + return -ENOMEM; + } + + mm->context.id = index; + + return 0; +} + +void destroy_context(struct mm_struct *mm) +{ + spin_lock(&mmu_context_lock); + idr_remove(&mmu_context_idr, mm->context.id); + spin_unlock(&mmu_context_lock); + + mm->context.id = NO_CONTEXT; + + hugetlb_mm_free_pgd(mm); +} + /* * Do very early mm setup. */ void __init mm_init_ppc64(void) { +#ifndef CONFIG_PPC_ISERIES unsigned long i; +#endif ppc64_boot_msg(0x100, "MM Init"); - /* Reserve all contexts < FIRST_USER_CONTEXT for kernel use. - * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT) - * are stored on a stack/queue for easy allocation and deallocation. - */ - mmu_context_queue.lock = SPIN_LOCK_UNLOCKED; - mmu_context_queue.head = 0; - mmu_context_queue.tail = NUM_USER_CONTEXT-1; - mmu_context_queue.size = NUM_USER_CONTEXT; - for (i = 0; i < NUM_USER_CONTEXT; i++) - mmu_context_queue.elements[i] = i + FIRST_USER_CONTEXT; - /* This is the story of the IO hole... please, keep seated, * unfortunately, we are out of oxygen masks at the moment. * So we need some rough way to tell where your big IO hole * is. On pmac, it's between 2G and 4G, on POWER3, it's around * that area as well, on POWER4 we don't have one, etc... - * We need that to implement something approx. decent for - * page_is_ram() so that /dev/mem doesn't map cacheable IO space - * when XFree resquest some IO regions witout using O_SYNC, we - * also need that as a "hint" when sizing the TCE table on POWER3 + * We need that as a "hint" when sizing the TCE table on POWER3 * So far, the simplest way that seem work well enough for us it * to just assume that the first discontinuity in our physical * RAM layout is the IO hole. That may not be correct in the future * (and isn't on iSeries but then we don't care ;) */ - top_of_ram = lmb_end_of_DRAM(); #ifndef CONFIG_PPC_ISERIES for (i = 1; i < lmb.memory.cnt; i++) { @@ -504,22 +562,32 @@ void __init mm_init_ppc64(void) ppc64_boot_msg(0x100, "MM Init Done"); } - /* * This is called by /dev/mem to know if a given address has to * be mapped non-cacheable or not */ -int page_is_ram(unsigned long physaddr) +int page_is_ram(unsigned long pfn) { -#ifdef CONFIG_PPC_ISERIES - return 1; + int i; + unsigned long paddr = (pfn << PAGE_SHIFT); + + for (i=0; i < lmb.memory.cnt; i++) { + unsigned long base; + +#ifdef CONFIG_MSCHUNKS + base = lmb.memory.region[i].physbase; +#else + base = lmb.memory.region[i].base; #endif - if (physaddr >= top_of_ram) - return 0; - return io_hole_start == 0 || physaddr < io_hole_start || - physaddr >= (io_hole_start + io_hole_size); -} + if ((paddr >= base) && + (paddr < (base + lmb.memory.region[i].size))) { + return 1; + } + } + return 0; +} +EXPORT_SYMBOL(page_is_ram); /* * Initialize the bootmem system and give it all the memory we @@ -573,6 +641,7 @@ void __init paging_init(void) unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; unsigned long total_ram = lmb_phys_mem_size(); + unsigned long top_of_ram = lmb_end_of_DRAM(); printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); @@ -587,7 +656,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT; - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); mem_map = contig_page_data.node_mem_map; } @@ -622,59 +691,53 @@ module_init(setup_kcore); void __init mem_init(void) { -#ifndef CONFIG_DISCONTIGMEM - unsigned long addr; +#ifdef CONFIG_DISCONTIGMEM + int nid; #endif - int codepages = 0; - int datapages = 0; - int initpages = 0; + pg_data_t *pgdat; + unsigned long i; + struct page *page; + unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; num_physpages = max_low_pfn; /* RAM is assumed contiguous */ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); #ifdef CONFIG_DISCONTIGMEM -{ - int nid; - for (nid = 0; nid < numnodes; nid++) { - if (node_data[nid].node_spanned_pages != 0) { + if (NODE_DATA(nid)->node_spanned_pages != 0) { printk("freeing bootmem node %x\n", nid); totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); } } - - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", - (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10), - codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), - initpages<< (PAGE_SHIFT-10), - PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM())); -} #else max_mapnr = num_physpages; - totalram_pages += free_all_bootmem(); +#endif - for (addr = KERNELBASE; addr < (unsigned long)__va(lmb_end_of_DRAM()); - addr += PAGE_SIZE) { - if (!PageReserved(virt_to_page(addr))) - continue; - if (addr < (unsigned long)_etext) - codepages++; - - else if (addr >= (unsigned long)__init_begin - && addr < (unsigned long)__init_end) - initpages++; - else if (addr < klimit) - datapages++; + for_each_pgdat(pgdat) { + for (i = 0; i < pgdat->node_spanned_pages; i++) { + page = pgdat->node_mem_map + i; + if (PageReserved(page)) + reservedpages++; + } } - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", - (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10), - codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), - initpages<< (PAGE_SHIFT-10), - PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM())); -#endif + codesize = (unsigned long)&_etext - (unsigned long)&_stext; + initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; + datasize = (unsigned long)&_edata - (unsigned long)&__init_end; + bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start; + + printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, " + "%luk reserved, %luk data, %luk bss, %luk init)\n", + (unsigned long)nr_free_pages() << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10), + codesize >> 10, + reservedpages << (PAGE_SHIFT-10), + datasize >> 10, + bsssize >> 10, + initsize >> 10); + mem_init_done = 1; #ifdef CONFIG_PPC_ISERIES @@ -806,14 +869,14 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, local_irq_restore(flags); } -void * reserve_phb_iospace(unsigned long size) +void __iomem * reserve_phb_iospace(unsigned long size) { - void *virt_addr; + void __iomem *virt_addr; if (phbs_io_bot >= IMALLOC_BASE) panic("reserve_phb_iospace(): phb io space overflow\n"); - virt_addr = (void *) phbs_io_bot; + virt_addr = (void __iomem *) phbs_io_bot; phbs_io_bot += size; return virt_addr; diff --git a/arch/ppc64/mm/mmap.c b/arch/ppc64/mm/mmap.c index 5ebf68668..fe65f522a 100644 --- a/arch/ppc64/mm/mmap.c +++ b/arch/ppc64/mm/mmap.c @@ -37,7 +37,7 @@ static inline unsigned long mmap_base(void) { - unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; if (gap < MIN_GAP) gap = MIN_GAP; @@ -54,13 +54,13 @@ static inline int mmap_is_legacy(void) */ if (!test_thread_flag(TIF_32BIT)) return 1; - - if (current->personality & ADDR_COMPAT_LAYOUT) + + if (current->personality & ADDR_COMPAT_LAYOUT) return 1; - - if (current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) + + if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) return 1; - + return sysctl_legacy_va_layout; } @@ -81,7 +81,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c index eb3313694..5d902b744 100644 --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -14,15 +14,17 @@ #include #include #include +#include +#include +#include #include #include #include -#if 1 -#define dbg(args...) printk(KERN_INFO args) -#else -#define dbg(args...) -#endif +static int numa_enabled = 1; + +static int numa_debug; +#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); } #ifdef DEBUG_NUMA #define ARRAY_INITIALISER -1 @@ -36,9 +38,19 @@ char *numa_memory_lookup_table; cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0}; -struct pglist_data node_data[MAX_NUMNODES]; -bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +struct pglist_data *node_data[MAX_NUMNODES]; +bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; static unsigned long node0_io_hole_size; +static int min_common_depth; + +/* + * We need somewhere to store start/span for each node until we have + * allocated the real node_data structures. + */ +static struct { + unsigned long node_start_pfn; + unsigned long node_spanned_pages; +} init_node_data[MAX_NUMNODES] __initdata; EXPORT_SYMBOL(node_data); EXPORT_SYMBOL(numa_cpu_lookup_table); @@ -48,7 +60,6 @@ EXPORT_SYMBOL(nr_cpus_in_node); static inline void map_cpu_to_node(int cpu, int node) { - dbg("cpu %d maps to domain %d\n", cpu, node); numa_cpu_lookup_table[cpu] = node; if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) { cpu_set(cpu, numa_cpumask_lookup_table[node]); @@ -56,7 +67,24 @@ static inline void map_cpu_to_node(int cpu, int node) } } -static struct device_node * __init find_cpu_node(unsigned int cpu) +#ifdef CONFIG_HOTPLUG_CPU +static void unmap_cpu_from_node(unsigned long cpu) +{ + int node = numa_cpu_lookup_table[cpu]; + + dbg("removing cpu %lu from node %d\n", cpu, node); + + if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) { + cpu_clear(cpu, numa_cpumask_lookup_table[node]); + nr_cpus_in_node[node]--; + } else { + printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n", + cpu, node); + } +} +#endif /* CONFIG_HOTPLUG_CPU */ + +static struct device_node * __devinit find_cpu_node(unsigned int cpu) { unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); struct device_node *cpu_node = NULL; @@ -68,9 +96,11 @@ static struct device_node * __init find_cpu_node(unsigned int cpu) interrupt_server = (unsigned int *)get_property(cpu_node, "ibm,ppc-interrupt-server#s", &len); + len = len / sizeof(u32); + if (interrupt_server && (len > 0)) { while (len--) { - if (interrupt_server[len-1] == hw_cpuid) + if (interrupt_server[len] == hw_cpuid) return cpu_node; } } else { @@ -86,29 +116,24 @@ static struct device_node * __init find_cpu_node(unsigned int cpu) /* must hold reference to node during call */ static int *of_get_associativity(struct device_node *dev) - { - unsigned int *result; - int len; - - result = (unsigned int *)get_property(dev, "ibm,associativity", &len); - - if (len <= 0) - return NULL; - - return result; +{ + return (unsigned int *)get_property(dev, "ibm,associativity", NULL); } -static int of_node_numa_domain(struct device_node *device, int depth) +static int of_node_numa_domain(struct device_node *device) { int numa_domain; unsigned int *tmp; + if (min_common_depth == -1) + return 0; + tmp = of_get_associativity(device); - if (tmp && (tmp[0] >= depth)) { - numa_domain = tmp[depth]; + if (tmp && (tmp[0] >= min_common_depth)) { + numa_domain = tmp[min_common_depth]; } else { - printk(KERN_ERR "WARNING: no NUMA information for " - "%s\n", device->full_name); + dbg("WARNING: no NUMA information for %s\n", + device->full_name); numa_domain = 0; } return numa_domain; @@ -128,7 +153,7 @@ static int of_node_numa_domain(struct device_node *device, int depth) * * - Dave Hansen */ -static int find_min_common_depth(void) +static int __init find_min_common_depth(void) { int depth; unsigned int *ref_points; @@ -137,11 +162,8 @@ static int find_min_common_depth(void) rtas_root = of_find_node_by_path("/rtas"); - if (!rtas_root) { - printk(KERN_ERR "WARNING: %s() could not find rtas root\n", - __FUNCTION__); + if (!rtas_root) return -1; - } /* * this property is 2 32-bit integers, each representing a level of @@ -155,8 +177,8 @@ static int find_min_common_depth(void) if ((len >= 1) && ref_points) { depth = ref_points[1]; } else { - printk(KERN_ERR "WARNING: could not find NUMA " - "associativity reference point\n"); + dbg("WARNING: could not find NUMA " + "associativity reference point\n"); depth = -1; } of_node_put(rtas_root); @@ -178,64 +200,117 @@ static unsigned long read_cell_ul(struct device_node *device, unsigned int **buf return result; } +/* + * Figure out to which domain a cpu belongs and stick it there. + * Return the id of the domain used. + */ +static int numa_setup_cpu(unsigned long lcpu) +{ + int numa_domain = 0; + struct device_node *cpu = find_cpu_node(lcpu); + + if (!cpu) { + WARN_ON(1); + goto out; + } + + numa_domain = of_node_numa_domain(cpu); + + if (numa_domain >= numnodes) { + /* + * POWER4 LPAR uses 0xffff as invalid node, + * dont warn in this case. + */ + if (numa_domain != 0xffff) + printk(KERN_ERR "WARNING: cpu %ld " + "maps to invalid NUMA node %d\n", + lcpu, numa_domain); + numa_domain = 0; + } +out: + node_set_online(numa_domain); + + map_cpu_to_node(lcpu, numa_domain); + + of_node_put(cpu); + + return numa_domain; +} + +static int cpu_numa_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + unsigned long lcpu = (unsigned long)hcpu; + int ret = NOTIFY_DONE; + + switch (action) { + case CPU_UP_PREPARE: + if (min_common_depth == -1 || !numa_enabled) + map_cpu_to_node(lcpu, 0); + else + numa_setup_cpu(lcpu); + ret = NOTIFY_OK; + break; +#ifdef CONFIG_HOTPLUG_CPU + case CPU_DEAD: + case CPU_UP_CANCELED: + unmap_cpu_from_node(lcpu); + break; + ret = NOTIFY_OK; +#endif + } + return ret; +} + static int __init parse_numa_properties(void) { struct device_node *cpu = NULL; struct device_node *memory = NULL; - int depth; int max_domain = 0; long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; unsigned long i; - if (strstr(saved_command_line, "numa=off")) { + if (numa_enabled == 0) { printk(KERN_WARNING "NUMA disabled by user\n"); return -1; } numa_memory_lookup_table = (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); + memset(numa_memory_lookup_table, 0, entries * sizeof(char)); for (i = 0; i < entries ; i++) numa_memory_lookup_table[i] = ARRAY_INITIALISER; - depth = find_min_common_depth(); + min_common_depth = find_min_common_depth(); - printk(KERN_INFO "NUMA associativity depth for CPU/Memory: %d\n", depth); - if (depth < 0) - return depth; + dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); + if (min_common_depth < 0) + return min_common_depth; + max_domain = numa_setup_cpu(boot_cpuid); + + /* + * Even though we connect cpus to numa domains later in SMP init, + * we need to know the maximum node id now. This is because each + * node id must have NODE_DATA etc backing it. + * As a result of hotplug we could still have cpus appear later on + * with larger node ids. In that case we force the cpu into node 0. + */ for_each_cpu(i) { int numa_domain; cpu = find_cpu_node(i); if (cpu) { - numa_domain = of_node_numa_domain(cpu, depth); + numa_domain = of_node_numa_domain(cpu); of_node_put(cpu); - if (numa_domain >= MAX_NUMNODES) { - /* - * POWER4 LPAR uses 0xffff as invalid node, - * dont warn in this case. - */ - if (numa_domain != 0xffff) - printk(KERN_ERR "WARNING: cpu %ld " - "maps to invalid NUMA node %d\n", - i, numa_domain); - numa_domain = 0; - } - } else { - printk(KERN_ERR "WARNING: no NUMA information for " - "cpu %ld\n", i); - numa_domain = 0; + if (numa_domain < MAX_NUMNODES && + max_domain < numa_domain) + max_domain = numa_domain; } - - node_set_online(numa_domain); - - if (max_domain < numa_domain) - max_domain = numa_domain; - - map_cpu_to_node(i, numa_domain); } memory = NULL; @@ -260,7 +335,7 @@ new_range: start = _ALIGN_DOWN(start, MEMORY_INCREMENT); size = _ALIGN_UP(size, MEMORY_INCREMENT); - numa_domain = of_node_numa_domain(memory, depth); + numa_domain = of_node_numa_domain(memory); if (numa_domain >= MAX_NUMNODES) { if (numa_domain != 0xffff) @@ -281,22 +356,22 @@ new_range: * this simple case and complain if there is a gap in * memory */ - if (node_data[numa_domain].node_spanned_pages) { + if (init_node_data[numa_domain].node_spanned_pages) { unsigned long shouldstart = - node_data[numa_domain].node_start_pfn + - node_data[numa_domain].node_spanned_pages; + init_node_data[numa_domain].node_start_pfn + + init_node_data[numa_domain].node_spanned_pages; if (shouldstart != (start / PAGE_SIZE)) { - printk(KERN_ERR "Hole in node, disabling " - "region start %lx length %lx\n", - start, size); + printk(KERN_ERR "WARNING: Hole in node, " + "disabling region start %lx " + "length %lx\n", start, size); continue; } - node_data[numa_domain].node_spanned_pages += + init_node_data[numa_domain].node_spanned_pages += size / PAGE_SIZE; } else { - node_data[numa_domain].node_start_pfn = + init_node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; - node_data[numa_domain].node_spanned_pages = + init_node_data[numa_domain].node_spanned_pages = size / PAGE_SIZE; } @@ -304,9 +379,6 @@ new_range: numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = numa_domain; - dbg("memory region %lx to %lx maps to domain %d\n", - start, start+size, numa_domain); - ranges--; if (ranges) goto new_range; @@ -332,17 +404,17 @@ static void __init setup_nonnuma(void) long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT; numa_memory_lookup_table = (char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1)); + memset(numa_memory_lookup_table, 0, entries * sizeof(char)); for (i = 0; i < entries ; i++) numa_memory_lookup_table[i] = ARRAY_INITIALISER; } - for (i = 0; i < NR_CPUS; i++) - map_cpu_to_node(i, 0); + map_cpu_to_node(boot_cpuid, 0); node_set_online(0); - node_data[0].node_start_pfn = 0; - node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE; + init_node_data[0].node_start_pfn = 0; + init_node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE; for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0; @@ -350,9 +422,91 @@ static void __init setup_nonnuma(void) node0_io_hole_size = top_of_ram - total_ram; } +static void __init dump_numa_topology(void) +{ + unsigned int node; + unsigned int count; + + if (min_common_depth == -1 || !numa_enabled) + return; + + for (node = 0; node < MAX_NUMNODES; node++) { + unsigned long i; + + if (!node_online(node)) + continue; + + printk(KERN_INFO "Node %d Memory:", node); + + count = 0; + + for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) { + if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) { + if (count == 0) + printk(" 0x%lx", i); + ++count; + } else { + if (count > 0) + printk("-0x%lx", i); + count = 0; + } + } + + if (count > 0) + printk("-0x%lx", i); + printk("\n"); + } + return; +} + +/* + * Allocate some memory, satisfying the lmb or bootmem allocator where + * required. nid is the preferred node and end is the physical address of + * the highest address in the node. + * + * Returns the physical address of the memory. + */ +static unsigned long careful_allocation(int nid, unsigned long size, + unsigned long align, unsigned long end) +{ + unsigned long ret = lmb_alloc_base(size, align, end); + + /* retry over all memory */ + if (!ret) + ret = lmb_alloc_base(size, align, lmb_end_of_DRAM()); + + if (!ret) + panic("numa.c: cannot allocate %lu bytes on node %d", + size, nid); + + /* + * If the memory came from a previously allocated node, we must + * retry with the bootmem allocator. + */ + if (pa_to_nid(ret) < nid) { + nid = pa_to_nid(ret); + ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid), + size, align, 0); + + if (!ret) + panic("numa.c: cannot allocate %lu bytes on node %d", + size, nid); + + ret = virt_to_abs(ret); + + dbg("alloc_bootmem %lx %lx\n", ret, size); + } + + return ret; +} + void __init do_init_bootmem(void) { int nid; + static struct notifier_block ppc64_numa_nb = { + .notifier_call = cpu_numa_callback, + .priority = 1 /* Must run before sched domains notifier. */ + }; min_low_pfn = 0; max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; @@ -360,6 +514,10 @@ void __init do_init_bootmem(void) if (parse_numa_properties()) setup_nonnuma(); + else + dump_numa_topology(); + + register_cpu_notifier(&ppc64_numa_nb); for (nid = 0; nid < numnodes; nid++) { unsigned long start_paddr, end_paddr; @@ -367,24 +525,38 @@ void __init do_init_bootmem(void) unsigned long bootmem_paddr; unsigned long bootmap_pages; - if (node_data[nid].node_spanned_pages == 0) - continue; + start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE; + end_paddr = start_paddr + (init_node_data[nid].node_spanned_pages * PAGE_SIZE); - start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE; - end_paddr = start_paddr + - (node_data[nid].node_spanned_pages * PAGE_SIZE); + /* Allocate the node structure node local if possible */ + NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid, + sizeof(struct pglist_data), + SMP_CACHE_BYTES, end_paddr); + NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid)); + memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); - dbg("node %d\n", nid); - dbg("start_paddr = %lx\n", start_paddr); - dbg("end_paddr = %lx\n", end_paddr); + dbg("node %d\n", nid); + dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; + NODE_DATA(nid)->node_start_pfn = + init_node_data[nid].node_start_pfn; + NODE_DATA(nid)->node_spanned_pages = + init_node_data[nid].node_spanned_pages; + + if (init_node_data[nid].node_spanned_pages == 0) + continue; + + dbg("start_paddr = %lx\n", start_paddr); + dbg("end_paddr = %lx\n", end_paddr); bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT); - dbg("bootmap_pages = %lx\n", bootmap_pages); - bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT, + bootmem_paddr = careful_allocation(nid, + bootmap_pages << PAGE_SHIFT, PAGE_SIZE, end_paddr); + memset(abs_to_virt(bootmem_paddr), 0, + bootmap_pages << PAGE_SHIFT); dbg("bootmap_paddr = %lx\n", bootmem_paddr); init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, @@ -442,7 +614,6 @@ void __init paging_init(void) { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; - struct page *node_mem_map; int nid; memset(zones_size, 0, sizeof(zones_size)); @@ -463,17 +634,22 @@ void __init paging_init(void) dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid, zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]); - /* - * Give this empty node a dummy struct page to avoid - * us from trying to allocate a node local mem_map - * in free_area_init_node (which will fail). - */ - if (!node_data[nid].node_spanned_pages) - node_mem_map = alloc_bootmem(sizeof(struct page)); - else - node_mem_map = NULL; - - free_area_init_node(nid, NODE_DATA(nid), node_mem_map, - zones_size, start_pfn, zholes_size); + free_area_init_node(nid, NODE_DATA(nid), zones_size, + start_pfn, zholes_size); } } + +static int __init early_numa(char *p) +{ + if (!p) + return 0; + + if (strstr(p, "off")) + numa_enabled = 0; + + if (strstr(p, "debug")) + numa_debug = 1; + + return 0; +} +early_param("numa", early_numa); diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c index bc6125804..7424d8d24 100644 --- a/arch/ppc64/mm/slb.c +++ b/arch/ppc64/mm/slb.c @@ -24,32 +24,55 @@ extern void slb_allocate(unsigned long ea); +static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot) +{ + return (ea & ESID_MASK) | SLB_ESID_V | slot; +} + +static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags) +{ + return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags; +} + static inline void create_slbe(unsigned long ea, unsigned long vsid, unsigned long flags, unsigned long entry) { - ea = (ea & ESID_MASK) | SLB_ESID_V | entry; - vsid = (vsid << SLB_VSID_SHIFT) | flags; asm volatile("slbmte %0,%1" : - : "r" (vsid), "r" (ea) + : "r" (mk_vsid_data(ea, flags)), + "r" (mk_esid_data(ea, entry)) : "memory" ); } -static void slb_add_bolted(void) +static void slb_flush_and_rebolt(void) { -#ifndef CONFIG_PPC_ISERIES - WARN_ON(!irqs_disabled()); - /* If you change this make sure you change SLB_NUM_BOLTED - * appropriately too */ + * appropriately too. */ + unsigned long ksp_flags = SLB_VSID_KERNEL; + unsigned long ksp_esid_data; - /* Slot 1 - first VMALLOC segment - * Since modules end up there it gets hit very heavily. - */ - create_slbe(VMALLOCBASE, get_kernel_vsid(VMALLOCBASE), - SLB_VSID_KERNEL, 1); + WARN_ON(!irqs_disabled()); - asm volatile("isync":::"memory"); -#endif + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + ksp_flags |= SLB_VSID_L; + + ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); + if ((ksp_esid_data & ESID_MASK) == KERNELBASE) + ksp_esid_data &= ~SLB_ESID_V; + + /* We need to do this all in asm, so we're sure we don't touch + * the stack between the slbia and rebolting it. */ + asm volatile("isync\n" + "slbia\n" + /* Slot 1 - first VMALLOC segment */ + "slbmte %0,%1\n" + /* Slot 2 - kernel stack */ + "slbmte %2,%3\n" + "isync" + :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)), + "r"(mk_esid_data(VMALLOCBASE, 1)), + "r"(mk_vsid_data(ksp_esid_data, ksp_flags)), + "r"(ksp_esid_data) + : "memory"); } /* Flush all user entries from the segment table of the current processor. */ @@ -71,8 +94,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) } asm volatile("isync" : : : "memory"); } else { - asm volatile("isync; slbia; isync" : : : "memory"); - slb_add_bolted(); + slb_flush_and_rebolt(); } /* Workaround POWER5 < DD2.1 issue */ @@ -115,22 +137,27 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) void slb_initialize(void) { -#ifdef CONFIG_PPC_ISERIES - asm volatile("isync; slbia; isync":::"memory"); -#else + /* On iSeries the bolted entries have already been set up by + * the hypervisor from the lparMap data in head.S */ +#ifndef CONFIG_PPC_ISERIES unsigned long flags = SLB_VSID_KERNEL; - /* Invalidate the entire SLB (even slot 0) & all the ERATS */ - if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) - flags |= SLB_VSID_L; + /* Invalidate the entire SLB (even slot 0) & all the ERATS */ + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + flags |= SLB_VSID_L; - asm volatile("isync":::"memory"); - asm volatile("slbmte %0,%0"::"r" (0) : "memory"); + asm volatile("isync":::"memory"); + asm volatile("slbmte %0,%0"::"r" (0) : "memory"); asm volatile("isync; slbia; isync":::"memory"); - create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), - flags, 0); - + create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0); + create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE), + SLB_VSID_KERNEL, 1); + /* We don't bolt the stack for the time being - we're in boot, + * so the stack is in the bolted segment. By the time it goes + * elsewhere, we'll call _switch() which will bolt in the new + * one. */ + asm volatile("isync":::"memory"); #endif - slb_add_bolted(); + get_paca()->stab_rr = SLB_NUM_BOLTED; } diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S index 4b3dfe091..8379d678f 100644 --- a/arch/ppc64/mm/slb_low.S +++ b/arch/ppc64/mm/slb_low.S @@ -37,8 +37,21 @@ _GLOBAL(slb_allocate) * a free slot first but that took too long. Unfortunately we * dont have any LRU information to help us choose a slot. */ +#ifdef CONFIG_PPC_ISERIES + /* + * On iSeries, the "bolted" stack segment can be cast out on + * shared processor switch so we need to check for a miss on + * it and restore it to the right slot. + */ + ld r9,PACAKSAVE(r13) + clrrdi r9,r9,28 + clrrdi r11,r3,28 + li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */ + cmpld r9,r11 + beq 3f +#endif /* CONFIG_PPC_ISERIES */ + ld r10,PACASTABRR(r13) -3: addi r10,r10,1 /* use a cpu feature mask if we ever change our slb size */ cmpldi r10,SLB_NUM_ENTRIES @@ -46,55 +59,28 @@ _GLOBAL(slb_allocate) blt+ 4f li r10,SLB_NUM_BOLTED - /* - * Never cast out the segment for our kernel stack. Since we - * dont invalidate the ERAT we could have a valid translation - * for the kernel stack during the first part of exception exit - * which gets invalidated due to a tlbie from another cpu at a - * non recoverable point (after setting srr0/1) - Anton - */ -4: slbmfee r11,r10 - srdi r11,r11,27 - /* - * Use paca->ksave as the value of the kernel stack pointer, - * because this is valid at all times. - * The >> 27 (rather than >> 28) is so that the LSB is the - * valid bit - this way we check valid and ESID in one compare. - * In order to completely close the tiny race in the context - * switch (between updating r1 and updating paca->ksave), - * we check against both r1 and paca->ksave. - */ - srdi r9,r1,27 - ori r9,r9,1 /* mangle SP for later compare */ - cmpd r11,r9 - beq- 3b - ld r9,PACAKSAVE(r13) - srdi r9,r9,27 - ori r9,r9,1 - cmpd r11,r9 - beq- 3b - +4: std r10,PACASTABRR(r13) - +3: /* r3 = faulting address, r10 = entry */ srdi r9,r3,60 /* get region */ srdi r3,r3,28 /* get esid */ cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */ - /* r9 = region, r3 = esid, cr7 = <>KERNELBASE */ - - rldicr. r11,r3,32,16 - bne- 8f /* invalid ea bits set */ - addi r11,r9,-1 - cmpldi r11,0xb - blt- 8f /* invalid region */ + rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */ + oris r10,r10,SLB_ESID_V@h /* r10 |= SLB_ESID_V */ - /* r9 = region, r3 = esid, r10 = entry, cr7 = <>KERNELBASE */ + /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */ blt cr7,0f /* user or kernel? */ - /* kernel address */ + /* kernel address: proto-VSID = ESID */ + /* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but + * this code will generate the protoVSID 0xfffffffff for the + * top segment. That's ok, the scramble below will translate + * it to VSID 0, which is reserved as a bad VSID - one which + * will never have any pages in it. */ li r11,SLB_VSID_KERNEL BEGIN_FTR_SECTION bne cr7,9f @@ -102,8 +88,12 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) b 9f -0: /* user address */ +0: /* user address: proto-VSID = context<<15 | ESID */ li r11,SLB_VSID_USER + + srdi. r9,r3,13 + bne- 8f /* invalid ea bits set */ + #ifdef CONFIG_HUGETLB_PAGE BEGIN_FTR_SECTION /* check against the hugepage ranges */ @@ -125,33 +115,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) #endif /* CONFIG_HUGETLB_PAGE */ 6: ld r9,PACACONTEXTID(r13) + rldimi r3,r9,USER_ESID_BITS,0 -9: /* r9 = "context", r3 = esid, r11 = flags, r10 = entry */ - - rldimi r9,r3,15,0 /* r9= VSID ordinal */ - -7: rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */ - oris r10,r10,SLB_ESID_V@h /* r10 |= SLB_ESID_V */ - - /* r9 = ordinal, r3 = esid, r11 = flags, r10 = esid_data */ - - li r3,VSID_RANDOMIZER@higher - sldi r3,r3,32 - oris r3,r3,VSID_RANDOMIZER@h - ori r3,r3,VSID_RANDOMIZER@l - - mulld r9,r3,r9 /* r9 = ordinal * VSID_RANDOMIZER */ - clrldi r9,r9,28 /* r9 &= VSID_MASK */ - sldi r9,r9,SLB_VSID_SHIFT /* r9 <<= SLB_VSID_SHIFT */ - or r9,r9,r11 /* r9 |= flags */ +9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ + ASM_VSID_SCRAMBLE(r3,r9) - /* r9 = vsid_data, r10 = esid_data, cr7 = <>KERNELBASE */ + rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */ /* * No need for an isync before or after this slbmte. The exception * we enter with and the rfid we exit with are context synchronizing. */ - slbmte r9,r10 + slbmte r11,r10 bgelr cr7 /* we're done for kernel addresses */ @@ -174,6 +149,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) blr 8: /* invalid EA */ - li r9,0 /* 0 VSID ordinal -> BAD_VSID */ + li r3,0 /* BAD_VSID */ li r11,SLB_VSID_USER /* flags don't much matter */ - b 7b + b 9b diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c index 8825e14cb..aa2d76ca4 100644 --- a/arch/ppc64/mm/tlb.c +++ b/arch/ppc64/mm/tlb.c @@ -26,10 +26,10 @@ #include #include #include +#include #include #include #include -#include #include DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c index 391e9afba..476c85700 100644 --- a/arch/ppc64/oprofile/common.c +++ b/arch/ppc64/oprofile/common.c @@ -52,17 +52,10 @@ static int op_ppc64_setup(void) static void op_ppc64_shutdown(void) { - /* - * We need to be sure we have cleared all pending exceptions before - * removing the interrupt handler. For the moment we play it safe and - * leave it in - */ -#if 0 mb(); /* Remove our interrupt handler. We may be removing this module. */ perf_irq = save_perf_irq; -#endif } static void op_ppc64_cpu_start(void *dummy) @@ -90,6 +83,14 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root) { int i; + /* + * There is one mmcr0, mmcr1 and mmcra for setting the events for + * all of the counters. + */ + oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0); + oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1); + oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra); + for (i = 0; i < model->num_counters; ++i) { struct dentry *dir; char buf[3]; @@ -111,6 +112,15 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root) oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); + oprofilefs_create_ulong(sb, root, "backtrace_spinlocks", + &sys.backtrace_spinlocks); + + /* Default to tracing both kernel and user */ + sys.enable_kernel = 1; + sys.enable_user = 1; + + /* Turn on backtracing through spinlocks by default */ + sys.backtrace_spinlocks = 1; return 0; } @@ -128,7 +138,7 @@ int __init oprofile_arch_init(struct oprofile_operations **ops) { unsigned int pvr; - pvr = _get_PVR(); + pvr = mfspr(SPRN_PVR); switch (PVR_VER(pvr)) { case PV_630: diff --git a/arch/ppc64/oprofile/op_impl.h b/arch/ppc64/oprofile/op_impl.h index aa9c8af60..30c71a03b 100644 --- a/arch/ppc64/oprofile/op_impl.h +++ b/arch/ppc64/oprofile/op_impl.h @@ -19,6 +19,12 @@ /* freeze counters. set to 1 on a perfmon exception */ #define MMCR0_FC (1UL << (31 - 0)) +/* freeze in supervisor state */ +#define MMCR0_KERNEL_DISABLE (1UL << (31 - 1)) + +/* freeze in problem state */ +#define MMCR0_PROBLEM_DISABLE (1UL << (31 - 2)) + /* freeze counters while MSR mark = 1 */ #define MMCR0_FCM1 (1UL << (31 - 3)) @@ -28,15 +34,15 @@ /* freeze counters on enabled condition or event */ #define MMCR0_FCECE (1UL << (31 - 6)) -/* performance monitor alert has occurred, set to 0 after handling exception */ -#define MMCR0_PMAO (1UL << (31 - 24)) - /* PMC1 count enable*/ #define MMCR0_PMC1INTCONTROL (1UL << (31 - 16)) /* PMCn count enable*/ #define MMCR0_PMCNINTCONTROL (1UL << (31 - 17)) +/* performance monitor alert has occurred, set to 0 after handling exception */ +#define MMCR0_PMAO (1UL << (31 - 24)) + /* state of MSR HV when SIAR set */ #define MMCRA_SIHV (1UL << (63 - 35)) @@ -60,8 +66,12 @@ struct op_counter_config { /* System-wide configuration as set via oprofilefs. */ struct op_system_config { + unsigned long mmcr0; + unsigned long mmcr1; + unsigned long mmcra; unsigned long enable_kernel; unsigned long enable_user; + unsigned long backtrace_spinlocks; }; /* Per-arch configuration */ diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c index 8a0e7a867..4f8bf02fb 100644 --- a/arch/ppc64/oprofile/op_model_power4.c +++ b/arch/ppc64/oprofile/op_model_power4.c @@ -17,7 +17,7 @@ #include #include -#define dbg(args...) printk(args) +#define dbg(args...) #include "op_impl.h" @@ -27,6 +27,18 @@ static int num_counters; static int oprofile_running; static int mmcra_has_sihv; +/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ +static u32 mmcr0_val; +static u64 mmcr1_val; +static u32 mmcra_val; + +/* + * Since we do not have an NMI, backtracing through spinlocks is + * only a best guess. In light of this, allow it to be disabled at + * runtime. + */ +static int backtrace_spinlocks; + static void power4_reg_setup(struct op_counter_config *ctr, struct op_system_config *sys, int num_ctrs) @@ -45,18 +57,38 @@ static void power4_reg_setup(struct op_counter_config *ctr, if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV) mmcra_has_sihv = 1; + /* + * The performance counter event settings are given in the mmcr0, + * mmcr1 and mmcra values passed from the user in the + * op_system_config structure (sys variable). + */ + mmcr0_val = sys->mmcr0; + mmcr1_val = sys->mmcr1; + mmcra_val = sys->mmcra; + + backtrace_spinlocks = sys->backtrace_spinlocks; + for (i = 0; i < num_counters; ++i) reset_value[i] = 0x80000000UL - ctr[i].count; - /* XXX setup user and kernel profiling */ + /* setup user and kernel profiling */ + if (sys->enable_kernel) + mmcr0_val &= ~MMCR0_KERNEL_DISABLE; + else + mmcr0_val |= MMCR0_KERNEL_DISABLE; + + if (sys->enable_user) + mmcr0_val &= ~MMCR0_PROBLEM_DISABLE; + else + mmcr0_val |= MMCR0_PROBLEM_DISABLE; } extern void ppc64_enable_pmcs(void); static void power4_cpu_setup(void *unused) { - unsigned int mmcr0 = mfspr(SPRN_MMCR0); - unsigned long mmcra = mfspr(SPRN_MMCRA); + unsigned int mmcr0 = mmcr0_val; + unsigned long mmcra = mmcra_val; ppc64_enable_pmcs(); @@ -68,6 +100,8 @@ static void power4_cpu_setup(void *unused) mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL; mtspr(SPRN_MMCR0, mmcr0); + mtspr(SPRN_MMCR1, mmcr1_val); + mmcra |= MMCRA_SAMPLE_ENABLE; mtspr(SPRN_MMCRA, mmcra); @@ -145,19 +179,38 @@ static void __attribute_used__ kernel_unknown_bucket(void) { } +static unsigned long check_spinlock_pc(struct pt_regs *regs, + unsigned long profile_pc) +{ + unsigned long pc = instruction_pointer(regs); + + /* + * If both the SIAR (sampled instruction) and the perfmon exception + * occurred in a spinlock region then we account the sample to the + * calling function. This isnt 100% correct, we really need soft + * IRQ disable so we always get the perfmon exception at the + * point at which the SIAR is set. + */ + if (backtrace_spinlocks && in_lock_functions(pc) && + in_lock_functions(profile_pc)) + return regs->link; + else + return profile_pc; +} + /* * On GQ and newer the MMCRA stores the HV and PR bits at the time * the SIAR was sampled. We use that to work out if the SIAR was sampled in * the hypervisor, our exception vectors or RTAS. */ -static unsigned long get_pc(void) +static unsigned long get_pc(struct pt_regs *regs) { unsigned long pc = mfspr(SPRN_SIAR); unsigned long mmcra; /* Cant do much about it */ if (!mmcra_has_sihv) - return pc; + return check_spinlock_pc(regs, pc); mmcra = mfspr(SPRN_MMCRA); @@ -171,10 +224,6 @@ static unsigned long get_pc(void) if (mmcra & MMCRA_SIPR) return pc; - /* Were we in our exception vectors? */ - if (pc < 0x4000UL) - return (unsigned long)__va(pc); - #ifdef CONFIG_PPC_PSERIES /* Were we in RTAS? */ if (pc >= rtas.base && pc < (rtas.base + rtas.size)) @@ -182,12 +231,16 @@ static unsigned long get_pc(void) return *((unsigned long *)rtas_bucket); #endif + /* Were we in our exception vectors or SLB real mode miss handler? */ + if (pc < 0x1000000UL) + return (unsigned long)__va(pc); + /* Not sure where we were */ if (pc < KERNELBASE) /* function descriptor madness */ return *((unsigned long *)kernel_unknown_bucket); - return pc; + return check_spinlock_pc(regs, pc); } static int get_kernel(unsigned long pc) @@ -214,7 +267,7 @@ static void power4_handle_interrupt(struct pt_regs *regs, unsigned int cpu = smp_processor_id(); unsigned int mmcr0; - pc = get_pc(); + pc = get_pc(regs); is_kernel = get_kernel(pc); /* set the PMM bit (see comment below) */ diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c index 21ceb0b7c..251fdef43 100644 --- a/arch/ppc64/oprofile/op_model_rs64.c +++ b/arch/ppc64/oprofile/op_model_rs64.c @@ -15,14 +15,14 @@ #include #include -#define dbg(args...) printk(args) +#define dbg(args...) #include "op_impl.h" static void ctrl_write(unsigned int i, unsigned int val) { - unsigned int tmp; - unsigned long shift, mask; + unsigned int tmp = 0; + unsigned long shift = 0, mask = 0; dbg("ctrl_write %d %x\n", i, val); diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c index c61770ca0..e1fc2ca64 100644 --- a/arch/ppc64/xmon/start.c +++ b/arch/ppc64/xmon/start.c @@ -35,7 +35,7 @@ static struct sysrq_key_op sysrq_xmon_op = { .handler = sysrq_handle_xmon, .help_msg = "Xmon", - .action_msg = "Entering xmon\n", + .action_msg = "Entering xmon", }; static int __init setup_xmon_sysrq(void) @@ -173,7 +173,7 @@ xmon_fgets(char *str, int nb, void *f) c = xmon_getchar(); if (c == -1) { if (p == str) - return 0; + return NULL; break; } *p++ = c; diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index d84ac32fa..8ff281b99 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "nonstdio.h" #include "privinst.h" @@ -39,7 +40,7 @@ #define skipbl xmon_skipbl #ifdef CONFIG_SMP -volatile cpumask_t cpus_in_xmon = CPU_MASK_NONE; +cpumask_t cpus_in_xmon = CPU_MASK_NONE; static unsigned long xmon_taken = 1; static int xmon_owner; static int xmon_gate; @@ -85,9 +86,6 @@ static unsigned bpinstr = 0x7fe00008; /* trap */ #define BP_NUM(bp) ((bp) - bpts + 1) -/* Bits in SRR1 that are copied from MSR */ -#define MSR_MASK 0xffffffff87c0ffff - /* Prototypes */ static int cmds(struct pt_regs *); static int mread(unsigned long, void *, int); @@ -132,7 +130,6 @@ static void csum(void); static void bootcmds(void); void dump_segments(void); static void symbol_lookup(void); -static int emulate_step(struct pt_regs *regs, unsigned int instr); static void xmon_print_symbol(unsigned long address, const char *mid, const char *after); static const char *getvecname(unsigned long vec); @@ -148,7 +145,6 @@ extern int xmon_read_poll(void); extern int setjmp(long *); extern void longjmp(long *, int); extern unsigned long _ASR; -extern char SystemCall_common[]; pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */ @@ -252,30 +248,28 @@ extern inline void sync(void) static inline void disable_surveillance(void) { -#ifndef CONFIG_PPC_ISERIES +#ifdef CONFIG_PPC_PSERIES /* Since this can't be a module, args should end up below 4GB. */ static struct rtas_args args; - if (systemcfg->platform & PLATFORM_PSERIES) { - /* - * At this point we have got all the cpus we can into - * xmon, so there is hopefully no other cpu calling RTAS - * at the moment, even though we don't take rtas.lock. - * If we did try to take rtas.lock there would be a - * real possibility of deadlock. - */ - args.token = rtas_token("set-indicator"); - if (args.token == RTAS_UNKNOWN_SERVICE) - return; - args.nargs = 3; - args.nret = 1; - args.rets = &args.args[3]; - args.args[0] = SURVEILLANCE_TOKEN; - args.args[1] = 0; - args.args[2] = 0; - enter_rtas(__pa(&args)); - } -#endif + /* + * At this point we have got all the cpus we can into + * xmon, so there is hopefully no other cpu calling RTAS + * at the moment, even though we don't take rtas.lock. + * If we did try to take rtas.lock there would be a + * real possibility of deadlock. + */ + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; + args.nargs = 3; + args.nret = 1; + args.rets = &args.args[3]; + args.args[0] = SURVEILLANCE_TOKEN; + args.args[1] = 0; + args.args[2] = 0; + enter_rtas(__pa(&args)); +#endif /* CONFIG_PPC_PSERIES */ } #ifdef CONFIG_SMP @@ -403,9 +397,11 @@ int xmon_core(struct pt_regs *regs, int fromipi) if (ncpus > 1) { smp_send_debugger_break(MSG_ALL_BUT_SELF); /* wait for other cpus to come in */ - for (timeout = 100000000; timeout != 0; --timeout) + for (timeout = 100000000; timeout != 0; --timeout) { if (cpus_weight(cpus_in_xmon) >= ncpus) break; + barrier(); + } } remove_bpts(); disable_surveillance(); @@ -490,6 +486,9 @@ int xmon_core(struct pt_regs *regs, int fromipi) if (stepped == 0) { regs->nip = (unsigned long) &bp->instr[0]; atomic_inc(&bp->ref_count); + } else if (stepped < 0) { + printf("Couldn't single-step %s instruction\n", + (IS_RFID(bp->instr[0])? "rfid": "mtmsrd")); } } } @@ -647,7 +646,7 @@ static struct bpt *at_breakpoint(unsigned long pc) for (i = 0; i < NBPTS; ++i, ++bp) if (bp->enabled && pc == bp->address) return bp; - return 0; + return NULL; } static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp) @@ -757,108 +756,6 @@ static void remove_cpu_bpts(void) set_iabr(0); } -static int branch_taken(unsigned int instr, struct pt_regs *regs) -{ - unsigned int bo = (instr >> 21) & 0x1f; - unsigned int bi; - - if ((bo & 4) == 0) { - /* decrement counter */ - --regs->ctr; - if (((bo >> 1) & 1) ^ (regs->ctr == 0)) - return 0; - } - if ((bo & 0x10) == 0) { - /* check bit from CR */ - bi = (instr >> 16) & 0x1f; - if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1)) - return 0; - } - return 1; -} - -/* - * Emulate instructions that cause a transfer of control. - * Returns 1 if the step was emulated, 0 if not, - * or -1 if the instruction is one that should not be stepped, - * such as an rfid, or a mtmsrd that would clear MSR_RI. - */ -static int emulate_step(struct pt_regs *regs, unsigned int instr) -{ - unsigned int opcode, rd; - unsigned long int imm; - - opcode = instr >> 26; - switch (opcode) { - case 16: /* bc */ - imm = (signed short)(instr & 0xfffc); - if ((instr & 2) == 0) - imm += regs->nip; - regs->nip += 4; /* XXX check 32-bit mode */ - if (instr & 1) - regs->link = regs->nip; - if (branch_taken(instr, regs)) - regs->nip = imm; - return 1; - case 17: /* sc */ - regs->gpr[9] = regs->gpr[13]; - regs->gpr[11] = regs->nip + 4; - regs->gpr[12] = regs->msr & MSR_MASK; - regs->gpr[13] = (unsigned long) get_paca(); - regs->nip = (unsigned long) &SystemCall_common; - regs->msr = MSR_KERNEL; - return 1; - case 18: /* b */ - imm = instr & 0x03fffffc; - if (imm & 0x02000000) - imm -= 0x04000000; - if ((instr & 2) == 0) - imm += regs->nip; - if (instr & 1) - regs->link = regs->nip + 4; - regs->nip = imm; - return 1; - case 19: - switch (instr & 0x7fe) { - case 0x20: /* bclr */ - case 0x420: /* bcctr */ - imm = (instr & 0x400)? regs->ctr: regs->link; - regs->nip += 4; /* XXX check 32-bit mode */ - if (instr & 1) - regs->link = regs->nip; - if (branch_taken(instr, regs)) - regs->nip = imm; - return 1; - case 0x24: /* rfid, scary */ - printf("Can't single-step an rfid instruction\n"); - return -1; - } - case 31: - rd = (instr >> 21) & 0x1f; - switch (instr & 0x7fe) { - case 0xa6: /* mfmsr */ - regs->gpr[rd] = regs->msr & MSR_MASK; - regs->nip += 4; - return 1; - case 0x164: /* mtmsrd */ - /* only MSR_EE and MSR_RI get changed if bit 15 set */ - /* mtmsrd doesn't change MSR_HV and MSR_ME */ - imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL; - imm = (regs->msr & MSR_MASK & ~imm) - | (regs->gpr[rd] & imm); - if ((imm & MSR_RI) == 0) { - printf("Can't step an instruction that would " - "clear MSR.RI\n"); - return -1; - } - regs->msr = imm; - regs->nip += 4; - return 1; - } - } - return 0; -} - /* Command interpreting routine */ static char *last_cmd; @@ -990,8 +887,11 @@ static int do_step(struct pt_regs *regs) if ((regs->msr & (MSR_SF|MSR_PR|MSR_IR)) == (MSR_SF|MSR_IR)) { if (mread(regs->nip, &instr, 4) == 4) { stepped = emulate_step(regs, instr); - if (stepped < 0) + if (stepped < 0) { + printf("Couldn't single-step %s instruction\n", + (IS_RFID(instr)? "rfid": "mtmsrd")); return 0; + } if (stepped > 0) { regs->trap = 0xd00 | (regs->trap & 1); printf("stepped to "); @@ -1584,7 +1484,7 @@ extern char exc_prolog; extern char dec_exc; void -super_regs() +super_regs(void) { int cmd; unsigned long val; @@ -1818,7 +1718,7 @@ static char *memex_subcmd_help_string = ""; void -memex() +memex(void) { int cmd, inc, i, nslash; unsigned long n; @@ -1969,7 +1869,7 @@ memex() } int -bsesc() +bsesc(void) { int c; @@ -1987,7 +1887,7 @@ bsesc() || ('a' <= (c) && (c) <= 'f') \ || ('A' <= (c) && (c) <= 'F')) void -dump() +dump(void) { int c; @@ -2059,7 +1959,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr) { int nr, dotted; unsigned long first_adr; - unsigned long inst, last_inst; + unsigned long inst, last_inst = 0; unsigned char val[4]; dotted = 0; @@ -2152,7 +2052,7 @@ static unsigned mend; static unsigned mask; void -memlocate() +memlocate(void) { unsigned a, n; unsigned char val[4]; @@ -2185,7 +2085,7 @@ static unsigned long mskip = 0x1000; static unsigned long mlim = 0xffffffff; void -memzcan() +memzcan(void) { unsigned char v; unsigned a; @@ -2214,7 +2114,7 @@ memzcan() /* Input scanning routines */ int -skipbl() +skipbl(void) { int c; @@ -2239,8 +2139,7 @@ static char *regnames[N_PTREGS] = { }; int -scanhex(vp) -unsigned long *vp; +scanhex(unsigned long *vp) { int c, d; unsigned long v; @@ -2324,7 +2223,7 @@ unsigned long *vp; } void -scannl() +scannl(void) { int c; @@ -2367,13 +2266,13 @@ static char line[256]; static char *lineptr; void -flush_input() +flush_input(void) { lineptr = NULL; } int -inchar() +inchar(void) { if (lineptr == NULL || *lineptr == 0) { if (fgets(line, sizeof(line), stdin) == NULL) { @@ -2386,8 +2285,7 @@ inchar() } void -take_input(str) -char *str; +take_input(char *str) { lineptr = str; } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ce8cb18b9..ab50e5c44 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -48,34 +48,6 @@ config ARCH_S390_31 depends on ARCH_S390X = 'n' default y -choice - prompt "Processor type" - default MARCH_G5 - -config MARCH_G5 - bool "S/390 model G5 and G6" - depends on ARCH_S390_31 - help - Select this to build a 31 bit kernel that works - on all S/390 and zSeries machines. - -config MARCH_Z900 - bool "IBM eServer zSeries model z800 and z900" - help - Select this to optimize for zSeries machines. This - will enable some optimizations that are not available - on older 31 bit only CPUs. - -config MARCH_Z990 - bool "IBM eServer zSeries model z890 and z990" - help - Select this enable optimizations for model z890/z990. - This will be slightly faster but does not work on - older machines such as the z900. - -endchoice - - config SMP bool "Symmetric multi-processing support" ---help--- @@ -121,7 +93,7 @@ config MATHEMU depends on MARCH_G5 help This option is required for IEEE compliant floating point arithmetic - on older S/390 machines. Say Y unless you know your machine doesn't + on older S/390 machines. Say Y unless you know your machine doesn't need this. config S390_SUPPORT @@ -150,13 +122,112 @@ config BINFMT_ELF32 This allows you to run 32-bit Linux/ELF binaries on your zSeries in 64 bit mode. Everybody wants this; say Y. +comment "Code generation options" + +choice + prompt "Processor type" + default MARCH_G5 + +config MARCH_G5 + bool "S/390 model G5 and G6" + depends on ARCH_S390_31 + help + Select this to build a 31 bit kernel that works + on all S/390 and zSeries machines. + +config MARCH_Z900 + bool "IBM eServer zSeries model z800 and z900" + help + Select this to optimize for zSeries machines. This + will enable some optimizations that are not available + on older 31 bit only CPUs. + +config MARCH_Z990 + bool "IBM eServer zSeries model z890 and z990" + help + Select this enable optimizations for model z890/z990. + This will be slightly faster but does not work on + older machines such as the z900. + +endchoice + +config PACK_STACK + bool "Pack kernel stack" + help + This option enables the compiler option -mkernel-backchain if it + is available. If the option is available the compiler supports + the new stack layout which dramatically reduces the minimum stack + frame size. With an old compiler a non-leaf function needs a + minimum of 96 bytes on 31 bit and 160 bytes on 64 bit. With + -mkernel-backchain the minimum size drops to 16 byte on 31 bit + and 24 byte on 64 bit. + + Say Y if you are unsure. + +config SMALL_STACK + bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb" + depends on PACK_STACK + help + If you say Y here and the compiler supports the -mkernel-backchain + option the kernel will use a smaller kernel stack size. For 31 bit + the reduced size is 4kb instead of 8kb and for 64 bit it is 8kb + instead of 16kb. This allows to run more thread on a system and + reduces the pressure on the memory management for higher order + page allocations. + + Say N if you are unsure. + + +config CHECK_STACK + bool "Detect kernel stack overflow" + help + This option enables the compiler option -mstack-guard and + -mstack-size if they are available. If the compiler supports them + it will emit additional code to each function prolog to trigger + an illegal operation if the kernel stack is about to overflow. + + Say N if you are unsure. + +config STACK_GUARD + int "Size of the guard area (128-1024)" + range 128 1024 + depends on CHECK_STACK + default "256" + help + This allows you to specify the size of the guard area at the lower + end of the kernel stack. If the kernel stack points into the guard + area on function entry an illegal operation is triggered. The size + needs to be a power of 2. Please keep in mind that the size of an + interrupt frame is 184 bytes for 31 bit and 328 bytes on 64 bit. + The minimum size for the stack guard should be 256 for 31 bit and + 512 for 64 bit. + +config WARN_STACK + bool "Emit compiler warnings for function with broken stack usage" + help + This option enables the compiler options -mwarn-framesize and + -mwarn-dynamicstack. If the compiler supports these options it + will generate warnings for function which either use alloca or + create a stack frame bigger then CONFIG_WARN_STACK_SIZE. + + Say N if you are unsure. + +config WARN_STACK_SIZE + int "Maximum frame size considered safe (128-2048)" + range 128 2048 + depends on WARN_STACK + default "256" + help + This allows you to specify the maximum frame size a function may + have without the compiler complaining about it. + comment "I/O subsystem configuration" config MACHCHK_WARNING bool "Process warning machine checks" help Select this option if you want the machine check handler on IBM S/390 or - zSeries to process warning machine checks (e.g. on power failures). + zSeries to process warning machine checks (e.g. on power failures). If unsure, say "Y". config QDIO @@ -388,64 +459,10 @@ source "fs/Kconfig" source "arch/s390/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config KALLSYMS - bool "Load all symbols for debugging/kksymoops" - depends on DEBUG_KERNEL - help - Say Y here to let the kernel print out symbolic crash information and - symbolic stack backtraces. This increases the size of the kernel - somewhat, as all symbols have to be loaded into the kernel image. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -endmenu +source "arch/s390/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 68c1a72b0..344d30205 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -18,6 +18,7 @@ LDFLAGS := -m elf_s390 CFLAGS += -m31 AFLAGS += -m31 UTS_MACHINE := s390 +STACK_SIZE := 8192 endif ifdef CONFIG_ARCH_S390X @@ -26,16 +27,49 @@ MODFLAGS += -fpic -D__PIC__ CFLAGS += -m64 AFLAGS += -m64 UTS_MACHINE := s390x +STACK_SIZE := 16384 endif -cflags-$(CONFIG_MARCH_G5) += $(call check_gcc,-march=g5,) -cflags-$(CONFIG_MARCH_Z900) += $(call check_gcc,-march=z900,) -cflags-$(CONFIG_MARCH_Z990) += $(call check_gcc,-march=z990,) +cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5) +cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) +cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) + +# old style option for packed stacks +ifeq ($(call cc-option-yn,-mkernel-backchain),y) +cflags-$(CONFIG_PACK_STACK) += -mkernel-backchain -D__PACK_STACK +aflags-$(CONFIG_PACK_STACK) += -D__PACK_STACK +cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK +aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK +ifdef CONFIG_SMALL_STACK +STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) ) +endif +endif + +# new style option for packed stacks +ifeq ($(call cc-option-yn,-mpacked-stack),y) +cflags-$(CONFIG_PACK_STACK) += -mpacked-stack -D__PACK_STACK +aflags-$(CONFIG_PACK_STACK) += -D__PACK_STACK +cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK +aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK +ifdef CONFIG_SMALL_STACK +STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) ) +endif +endif + +ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y) +cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE) +cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) +endif + +ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y) +cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack +cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE) +endif -CFLAGS += $(cflags-y) -CFLAGS += $(call check_gcc,-finline-limit=10000,) +CFLAGS += -mbackchain $(cflags-y) +CFLAGS += $(call cc-option,-finline-limit=10000) CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare -CFLAGS += -mbackchain +AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index a21e30846..462ee9a84 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c @@ -102,8 +102,12 @@ static inline void appldata_debug_print(struct appldata_mem_data *mem_data) */ static void appldata_get_mem_data(void *data) { - struct sysinfo val; - struct page_state ps; + /* + * don't put large structures on the stack, we are + * serialized through the appldata_ops_lock and can use static + */ + static struct sysinfo val; + static struct page_state ps; struct appldata_mem_data *mem_data; mem_data = data; diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index a67fd8afc..4d97eef36 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -14,5 +14,5 @@ $(obj)/image: vmlinux FORCE $(call if_changed,objcopy) install: $(CONFIGURE) $(obj)/image - sh -x $(obj)/install.sh $(KERNELRELEASE) $(obj)/image \ + sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/image \ System.map Kerntypes "$(INSTALL_PATH)" diff --git a/arch/s390/defconfig b/arch/s390/defconfig index d4cd42c3e..ef3aea10f 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc2 +# Tue Nov 30 14:00:30 2004 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -11,10 +13,12 @@ CONFIG_UID16=y # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -23,6 +27,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=17 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set @@ -31,11 +36,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -44,6 +51,7 @@ CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # @@ -56,14 +64,22 @@ CONFIG_KMOD=y # CONFIG_ARCH_S390X is not set # CONFIG_64BIT is not set CONFIG_ARCH_S390_31=y -CONFIG_MARCH_G5=y -# CONFIG_MARCH_Z900 is not set -# CONFIG_MARCH_Z990 is not set CONFIG_SMP=y CONFIG_NR_CPUS=32 # CONFIG_HOTPLUG_CPU is not set CONFIG_MATHEMU=y +# +# Code generation options +# +CONFIG_MARCH_G5=y +# CONFIG_MARCH_Z900 is not set +# CONFIG_MARCH_Z990 is not set +CONFIG_PACK_STACK=y +# CONFIG_SMALL_STACK is not set +# CONFIG_CHECK_STACK is not set +# CONFIG_WARN_STACK is not set + # # I/O subsystem configuration # @@ -130,9 +146,7 @@ CONFIG_SCSI_FC_ATTRS=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y CONFIG_CCW=y @@ -146,7 +160,9 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set +# CONFIG_CDROM_PKTCDVD is not set # # S/390 block device drivers @@ -154,12 +170,20 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_XPRAM=m # CONFIG_DCSSBLK is not set CONFIG_DASD=y -# CONFIG_DASD_PROFILE is not set +CONFIG_DASD_PROFILE=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y CONFIG_DASD_DIAG=y # CONFIG_DASD_CMB is not set +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y + # # Multi-device support (RAID and LVM) # @@ -168,9 +192,11 @@ CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m +# CONFIG_MD_RAID10 is not set CONFIG_MD_RAID5=m # CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m +# CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set # @@ -179,6 +205,11 @@ CONFIG_MD_MULTIPATH=m CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=2048 +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set + # # S/390 character device drivers # @@ -205,6 +236,9 @@ CONFIG_S390_TAPE_BLOCK=y # S/390 tape hardware support # CONFIG_S390_TAPE_34XX=m +# CONFIG_VMLOGRDR is not set +# CONFIG_MONREADER is not set +# CONFIG_DCSS_SHM is not set # # Cryptographic devices @@ -236,11 +270,15 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +CONFIG_IP_TCPDIAG_IPV6=y CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set # CONFIG_NETFILTER is not set CONFIG_XFRM=y @@ -262,7 +300,6 @@ CONFIG_XFRM=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -381,6 +418,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -406,6 +444,7 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -419,7 +458,6 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -443,6 +481,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -485,13 +524,16 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -506,16 +548,19 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_SHA1_Z990 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_DES_Z990 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES_GENERIC is not set +# CONFIG_CRYPTO_AES is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 892b7e1b0..a19cb59ed 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,11 +6,11 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o profile.o + semaphore.o s390_ext.o debug.o profile.o irq.o extra-$(CONFIG_ARCH_S390_31) += head.o extra-$(CONFIG_ARCH_S390X) += head64.o -extra-y += init_task.o vmlinux.lds.s +extra-y += init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index ce2b03578..3f7018e9d 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -22,6 +22,8 @@ int main(void) DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment),); BLANK(); + DEFINE(__TASK_pid, offsetof(struct task_struct, pid),); + BLANK(); DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),); DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),); DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),); @@ -39,5 +41,9 @@ int main(void) DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),); DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),); DEFINE(__PT_SIZE, sizeof(struct pt_regs),); + BLANK(); + DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),); + DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),); + DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),); return 0; } diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 01c188c70..302bbb610 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c @@ -56,6 +56,9 @@ #define ELF_CORE_COPY_REGS(pr_reg, regs) dump_regs32(regs, &pr_reg); +#define ELF_CORE_COPY_TASK_REGS(tsk, regs) dump_task_regs32(tsk, regs) + +#define ELF_CORE_COPY_FPREGS(tsk, fpregs) dump_task_fpu(tsk, fpregs) /* This yields a mask that user programs can use to figure out what instruction set this CPU supports. */ @@ -99,13 +102,37 @@ static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs) int i; memcpy(®s->psw.mask, &ptregs->psw.mask, 4); - memcpy(®s->psw.addr, &ptregs->psw.addr, 4); + memcpy(®s->psw.addr, (char *)&ptregs->psw.addr + 4, 4); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = ptregs->gprs[i]; + save_access_regs(regs->acrs); regs->orig_gpr2 = ptregs->orig_gpr2; return 1; } +static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs) +{ + struct pt_regs *ptregs = __KSTK_PTREGS(tsk); + int i; + + memcpy(®s->psw.mask, &ptregs->psw.mask, 4); + memcpy(®s->psw.addr, (char *)&ptregs->psw.addr + 4, 4); + for (i = 0; i < NUM_GPRS; i++) + regs->gprs[i] = ptregs->gprs[i]; + memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs)); + regs->orig_gpr2 = ptregs->orig_gpr2; + return 1; +} + +static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) +{ + if (tsk == current) + save_fp_regs((s390_fp_regs *) fpregs); + else + memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t)); + return 1; +} + #include #include #include diff --git a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c index 595c43a89..51b294d33 100644 --- a/arch/s390/kernel/compat_exec.c +++ b/arch/s390/kernel/compat_exec.c @@ -39,7 +39,7 @@ int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -68,8 +68,12 @@ int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack) /* executable stack setting would be applied here */ mpnt->vm_page_prot = PAGE_COPY; mpnt->vm_flags = VM_STACK_FLAGS; - insert_vm_struct(mm, mpnt); - mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + if ((ret = insert_vm_struct(mm, mpnt))) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } + mm->stack_vm = mm->total_vm = vma_pages(mpnt); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 5685c5feb..01f57183d 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -725,8 +725,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo) int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info, uinfo, 3*sizeof(int)) || - copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) + if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); @@ -752,7 +751,9 @@ sys32_execve(struct pt_regs regs) compat_ptr(regs.gprs[4]), ®s); if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); current->thread.fp_regs.fpc=0; __asm__ __volatile__ ("sr 0,0\n\t" @@ -1219,7 +1220,7 @@ asmlinkage long sys32_clone(struct pt_regs regs) child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL); if (!newsp) newsp = regs.gprs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index e8c8b2fe7..f29bcb856 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -118,10 +118,10 @@ int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from) err |= __get_user(to->si_errno, &from->si_errno); err |= __get_user(to->si_code, &from->si_code); - if (from->si_code < 0) + if (to->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { + switch (to->si_code >> 16) { case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ case __SI_MESGQ >> 16: err |= __get_user(to->si_int, &from->si_int); @@ -218,14 +218,17 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) { struct k_sigaction new_ka, old_ka; + unsigned long sa_handler, sa_restorer; int ret; if (act) { compat_old_sigset_t mask; if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) || - __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(sa_handler, &act->sa_handler) || + __get_user(sa_restorer, &act->sa_restorer)) return -EFAULT; + new_ka.sa.sa_handler = (__sighandler_t) sa_handler; + new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer; __get_user(new_ka.sa.sa_flags, &act->sa_flags); __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); @@ -234,9 +237,11 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { + sa_handler = (unsigned long) old_ka.sa.sa_handler; + sa_restorer = (unsigned long) old_ka.sa.sa_restorer; if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(sa_handler, &oact->sa_handler) || + __put_user(sa_restorer, &oact->sa_restorer)) return -EFAULT; __put_user(old_ka.sa.sa_flags, &oact->sa_flags); __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); @@ -253,6 +258,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact, size_t sigsetsize) { struct k_sigaction new_ka, old_ka; + unsigned long sa_handler; int ret; compat_sigset_t set32; @@ -261,7 +267,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, return -EINVAL; if (act) { - ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler); + ret = get_user(sa_handler, &act->sa_handler); ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); switch (_NSIG_WORDS) { @@ -278,6 +284,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, if (ret) return -EFAULT; + new_ka.sa.sa_handler = (__sighandler_t) sa_handler; } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); @@ -311,17 +318,19 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, struct pt_regs *regs) { stack_t kss, koss; + unsigned long ss_sp; int ret, err = 0; mm_segment_t old_fs = get_fs(); if (uss) { if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) return -EFAULT; - err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp); + err |= __get_user(ss_sp, &uss->ss_sp); err |= __get_user(kss.ss_size, &uss->ss_size); err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) return -EFAULT; + kss.ss_sp = (void *) ss_sp; } set_fs (KERNEL_DS); @@ -333,7 +342,8 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; - err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp); + ss_sp = (unsigned long) koss.ss_sp; + err |= __put_user(ss_sp, &uoss->ss_sp); err |= __put_user(koss.ss_size, &uoss->ss_size); err |= __put_user(koss.ss_flags, &uoss->ss_flags); if (err) @@ -552,9 +562,7 @@ static void setup_frame32(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -604,9 +612,7 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -614,20 +620,15 @@ give_sigsegv: */ void -handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(sig, ka, info, oldset, regs); else setup_frame32(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 41adc6120..cf8815006 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1262,19 +1262,19 @@ sys32_fadvise64_64_wrapper: sys32_clock_settime_wrapper: lgfr %r2,%r2 # clockid_t (int) llgtr %r3,%r3 # struct compat_timespec * - jg compat_clock_settime + jg compat_sys_clock_settime .globl sys32_clock_gettime_wrapper sys32_clock_gettime_wrapper: lgfr %r2,%r2 # clockid_t (int) llgtr %r3,%r3 # struct compat_timespec * - jg compat_clock_gettime + jg compat_sys_clock_gettime .globl sys32_clock_getres_wrapper sys32_clock_getres_wrapper: lgfr %r2,%r2 # clockid_t (int) llgtr %r3,%r3 # struct compat_timespec * - jg compat_clock_getres + jg compat_sys_clock_getres .globl sys32_clock_nanosleep_wrapper sys32_clock_nanosleep_wrapper: @@ -1282,7 +1282,7 @@ sys32_clock_nanosleep_wrapper: lgfr %r3,%r3 # int llgtr %r4,%r4 # struct compat_timespec * llgtr %r5,%r5 # struct compat_timespec * - jg compat_clock_nanosleep + jg compat_sys_clock_nanosleep .globl sys32_timer_create_wrapper sys32_timer_create_wrapper: @@ -1297,13 +1297,13 @@ sys32_timer_settime_wrapper: lgfr %r3,%r3 # int llgtr %r4,%r4 # struct compat_itimerspec * llgtr %r5,%r5 # struct compat_itimerspec * - jg compat_timer_settime + jg compat_sys_timer_settime .globl sys32_timer_gettime_wrapper sys32_timer_gettime_wrapper: lgfr %r2,%r2 # timer_t (int) llgtr %r3,%r3 # struct compat_itimerspec * - jg compat_timer_gettime + jg compat_sys_timer_gettime .globl sys32_timer_getoverrun_wrapper sys32_timer_getoverrun_wrapper: @@ -1354,14 +1354,14 @@ compat_sys_statfs64_wrapper: llgtr %r2,%r2 # const char * llgfr %r3,%r3 # compat_size_t llgtr %r4,%r4 # struct compat_statfs64 * - jg compat_statfs64 + jg compat_sys_statfs64 .globl compat_sys_fstatfs64_wrapper compat_sys_fstatfs64_wrapper: llgfr %r2,%r2 # unsigned int fd llgfr %r3,%r3 # compat_size_t llgtr %r4,%r4 # struct compat_statfs64 * - jg compat_fstatfs64 + jg compat_sys_fstatfs64 .globl compat_sys_mq_open_wrapper compat_sys_mq_open_wrapper: diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index d48351583..9957926bc 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -15,7 +15,7 @@ #include static spinlock_t cpcmd_lock = SPIN_LOCK_UNLOCKED; -static char cpcmd_buf[128]; +static char cpcmd_buf[240]; void cpcmd(char *cmd, char *response, int rlen) { @@ -24,22 +24,23 @@ void cpcmd(char *cmd, char *response, int rlen) int cmdlen; spin_lock_irqsave(&cpcmd_lock, flags); - cmdlen = strlen(cmd); - strcpy(cpcmd_buf, cmd); - ASCEBC(cpcmd_buf, cmdlen); + cmdlen = strlen(cmd); + BUG_ON(cmdlen>240); + strcpy(cpcmd_buf, cmd); + ASCEBC(cpcmd_buf, cmdlen); - if (response != NULL && rlen > 0) { + if (response != NULL && rlen > 0) { #ifndef CONFIG_ARCH_S390X asm volatile ("LRA 2,0(%0)\n\t" "LR 4,%1\n\t" "O 4,%4\n\t" "LRA 3,0(%2)\n\t" "LR 5,%3\n\t" - ".long 0x83240008 # Diagnose 83\n\t" + ".long 0x83240008 # Diagnose X'08'\n\t" : /* no output */ : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) - : "2", "3", "4", "5" ); + : "cc", "2", "3", "4", "5" ); #else /* CONFIG_ARCH_S390X */ asm volatile (" lrag 2,0(%0)\n" " lgr 4,%1\n" @@ -47,19 +48,19 @@ void cpcmd(char *cmd, char *response, int rlen) " lrag 3,0(%2)\n" " lgr 5,%3\n" " sam31\n" - " .long 0x83240008 # Diagnose 83\n" + " .long 0x83240008 # Diagnose X'08'\n" " sam64" : /* no output */ : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) - : "2", "3", "4", "5" ); + : "cc", "2", "3", "4", "5" ); #endif /* CONFIG_ARCH_S390X */ EBCASC(response, rlen); } else { #ifndef CONFIG_ARCH_S390X asm volatile ("LRA 2,0(%0)\n\t" "LR 3,%1\n\t" - ".long 0x83230008 # Diagnose 83\n\t" + ".long 0x83230008 # Diagnose X'08'\n\t" : /* no output */ : "a" (cpcmd_buf), "d" (cmdlen) : "2", "3" ); @@ -67,7 +68,7 @@ void cpcmd(char *cmd, char *response, int rlen) asm volatile (" lrag 2,0(%0)\n" " lgr 3,%1\n" " sam31\n" - " .long 0x83230008 # Diagnose 83\n" + " .long 0x83230008 # Diagnose X'08'\n" " sam64" : /* no output */ : "a" (cpcmd_buf), "d" (cmdlen) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index f1e538c9d..37ebc9487 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,7 +25,6 @@ #include -#define MIN(a,b) (((a)<(b))?(a):(b)) #define DEBUG_PROLOG_ENTRY -1 /* typedefs */ @@ -435,7 +435,7 @@ static ssize_t debug_output(struct file *file, /* file descriptor */ while(count < len){ size = debug_format_entry(p_info); - size = MIN((len - count), (size - entry_offset)); + size = min((len - count), (size - entry_offset)); if(size){ if (copy_to_user(user_buf + count, @@ -709,6 +709,70 @@ extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active, proceed_active_area(id); } +static int debug_stoppable=1; +static int debug_active=1; + +#define CTL_S390DBF 5677 +#define CTL_S390DBF_STOPPABLE 5678 +#define CTL_S390DBF_ACTIVE 5679 + +/* + * proc handler for the running debug_active sysctl + * always allow read, allow write only if debug_stoppable is set or + * if debug_active is already off + */ +static int s390dbf_procactive(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + if (!write || debug_stoppable || !debug_active) + return proc_dointvec(table, write, filp, buffer, lenp, ppos); + else + return 0; +} + + +static struct ctl_table s390dbf_table[] = { + { + .ctl_name = CTL_S390DBF_STOPPABLE, + .procname = "debug_stoppable", + .data = &debug_stoppable, + .maxlen = sizeof(int), + .mode = S_IRUGO | S_IWUSR, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + }, + { + .ctl_name = CTL_S390DBF_ACTIVE, + .procname = "debug_active", + .data = &debug_active, + .maxlen = sizeof(int), + .mode = S_IRUGO | S_IWUSR, + .proc_handler = &s390dbf_procactive, + .strategy = &sysctl_intvec, + }, + { .ctl_name = 0 } +}; + +static struct ctl_table s390dbf_dir_table[] = { + { + .ctl_name = CTL_S390DBF, + .procname = "s390dbf", + .maxlen = 0, + .mode = S_IRUGO | S_IXUGO, + .child = s390dbf_table, + }, + { .ctl_name = 0 } +}; + +struct ctl_table_header *s390dbf_sysctl_header; + +void debug_stop_all(void) +{ + if (debug_stoppable) + debug_active = 0; +} + + /* * debug_event_common: * - write debug entry with given size @@ -720,10 +784,12 @@ debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf, unsigned long flags; debug_entry_t *active; + if (!debug_active) + return NULL; spin_lock_irqsave(&id->lock, flags); active = get_active_entry(id); memset(DEBUG_DATA(active), 0, id->buf_size); - memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size)); + memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size)); debug_finish_entry(id, active, level, 0); spin_unlock_irqrestore(&id->lock, flags); @@ -741,10 +807,12 @@ debug_entry_t *debug_exception_common(debug_info_t * id, int level, unsigned long flags; debug_entry_t *active; + if (!debug_active) + return NULL; spin_lock_irqsave(&id->lock, flags); active = get_active_entry(id); memset(DEBUG_DATA(active), 0, id->buf_size); - memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size)); + memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size)); debug_finish_entry(id, active, level, 1); spin_unlock_irqrestore(&id->lock, flags); @@ -781,7 +849,8 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id, if((!id) || (level > id->level)) return NULL; - + if (!debug_active) + return NULL; numargs=debug_count_numargs(string); spin_lock_irqsave(&id->lock, flags); @@ -789,7 +858,7 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id, curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active); va_start(ap,string); curr_event->string=string; - for(idx=0;idxbuf_size / sizeof(long))-1));idx++) + for(idx=0;idxbuf_size / sizeof(long))-1);idx++) curr_event->args[idx]=va_arg(ap,long); va_end(ap); debug_finish_entry(id, active, level, 0); @@ -813,6 +882,8 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id, if((!id) || (level > id->level)) return NULL; + if (!debug_active) + return NULL; numargs=debug_count_numargs(string); @@ -821,7 +892,7 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id, curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active); va_start(ap,string); curr_event->string=string; - for(idx=0;idxbuf_size / sizeof(long))-1));idx++) + for(idx=0;idxbuf_size / sizeof(long))-1);idx++) curr_event->args[idx]=va_arg(ap,long); va_end(ap); debug_finish_entry(id, active, level, 1); @@ -839,6 +910,7 @@ static int __init debug_init(void) { int rc = 0; + s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1); down(&debug_lock); #ifdef CONFIG_PROC_FS debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL); @@ -1157,7 +1229,7 @@ int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view, } /* number of arguments used for sprintf (without the format string) */ - num_used_args = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1)); + num_used_args = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1)); memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int)); @@ -1187,6 +1259,7 @@ void __exit debug_exit(void) #ifdef CONFIG_PROC_FS remove_proc_entry(debug_proc_root_entry->name, NULL); #endif /* CONFIG_PROC_FS */ + unregister_sysctl_table(s390dbf_sysctl_header); return; } @@ -1200,6 +1273,7 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(debug_register); EXPORT_SYMBOL(debug_unregister); EXPORT_SYMBOL(debug_set_level); +EXPORT_SYMBOL(debug_stop_all); EXPORT_SYMBOL(debug_register_view); EXPORT_SYMBOL(debug_unregister_view); EXPORT_SYMBOL(debug_event_common); diff --git a/arch/s390/kernel/ebcdic.c b/arch/s390/kernel/ebcdic.c index 52d5a78b5..bb0f97313 100644 --- a/arch/s390/kernel/ebcdic.c +++ b/arch/s390/kernel/ebcdic.c @@ -391,10 +391,10 @@ __u8 _ebc_toupper[256] = 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; -EXPORT_SYMBOL_NOVERS(_ascebc_500); -EXPORT_SYMBOL_NOVERS(_ebcasc_500); -EXPORT_SYMBOL_NOVERS(_ascebc); -EXPORT_SYMBOL_NOVERS(_ebcasc); -EXPORT_SYMBOL_NOVERS(_ebc_tolower); -EXPORT_SYMBOL_NOVERS(_ebc_toupper); +EXPORT_SYMBOL(_ascebc_500); +EXPORT_SYMBOL(_ebcasc_500); +EXPORT_SYMBOL(_ascebc); +EXPORT_SYMBOL(_ebcasc); +EXPORT_SYMBOL(_ebc_tolower); +EXPORT_SYMBOL(_ebc_toupper); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1f87bf29c..f72f9ec9b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -19,6 +19,7 @@ #include #include #include +#include /* * Stack layout for the system_call stack entry. @@ -52,6 +53,9 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) +STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER +STACK_SIZE = 1 << STACK_SHIFT + #define BASED(name) name-system_call(%r13) /* @@ -86,10 +90,16 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) bnz BASED(1f) 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? slr %r14,%r15 - sra %r14,13 + sra %r14,STACK_SHIFT be BASED(2f) 1: l %r15,__LC_ASYNC_STACK .endif +#ifdef CONFIG_CHECK_STACK + b BASED(3f) +2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + bz BASED(stack_overflow) +3: +#endif 2: s %r15,BASED(.Lc_spsize) # make room for registers & psw mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack la %r12,\psworg @@ -99,7 +109,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) st %r12,SP_ILC(%r15) mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack la %r12,0 - st %r12,0(%r15) # clear back chain + st %r12,__SF_BACKCHAIN(%r15) # clear back chain .endm .macro RESTORE_ALL sync @@ -124,46 +134,23 @@ __switch_to: __switch_to_base: tm __THREAD_per(%r3),0xe8 # new process is using per ? bz __switch_to_noper-__switch_to_base(%r1) # if not we're fine - stctl %c9,%c11,24(%r15) # We are using per stuff - clc __THREAD_per(12,%r3),24(%r15) + stctl %c9,%c11,__SF_EMPTY(%r15) # We are using per stuff + clc __THREAD_per(12,%r3),__SF_EMPTY(%r15) be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't __switch_to_noper: - stm %r6,%r15,24(%r15) # store __switch_to registers of prev task + stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp - lm %r6,%r15,24(%r15) # load __switch_to registers of next task + lm %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task st %r3,__LC_CURRENT # __LC_CURRENT = current task struct + lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 l %r3,__THREAD_info(%r3) # load thread_info from task struct st %r3,__LC_THREAD_INFO - ahi %r3,8192 + ahi %r3,STACK_SIZE st %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack br %r14 -/* - * do_softirq calling function. We want to run the softirq functions on the - * asynchronous interrupt stack. - */ - .global do_call_softirq -do_call_softirq: - stnsm 24(%r15),0xfc - stm %r12,%r15,28(%r15) - lr %r12,%r15 - basr %r13,0 -do_call_base: - l %r0,__LC_ASYNC_STACK - slr %r0,%r15 - sra %r0,13 - be 0f-do_call_base(%r13) - l %r15,__LC_ASYNC_STACK -0: sl %r15,.Lc_overhead-do_call_base(%r13) - st %r12,0(%r15) # store backchain - l %r1,.Ldo_softirq-do_call_base(%r13) - basr %r14,%r1 - lm %r12,%r15,28(%r12) - ssm 24(%r15) - br %r14 - __critical_start: /* * SVC interrupt handler routine. System calls are synchronous events and @@ -242,6 +229,8 @@ sysc_sigpending: basr %r14,%r1 # call do_signal tm __TI_flags+3(%r9),_TIF_RESTART_SVC bo BASED(sysc_restart) + tm __TI_flags+3(%r9),_TIF_SINGLE_STEP + bo BASED(sysc_singlestep) b BASED(sysc_leave) # out of here, do NOT recheck # @@ -304,9 +293,12 @@ sysc_tracenogo: ret_from_fork: l %r13,__LC_SVC_NEW_PSW+4 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct - l %r1,BASED(.Lschedtail) + tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? + bo BASED(0f) + st %r15,SP_R15(%r15) # store stack pointer for new kthread +0: l %r1,BASED(.Lschedtail) basr %r14,%r1 - stosm 24(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_return) # @@ -457,7 +449,7 @@ pgm_svcper: mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP - stosm 24(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc) /* @@ -493,16 +485,16 @@ io_preempt: l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) - xc 0(4,%r1),0(%r1) # clear back chain + xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1 io_resume_loop: tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bno BASED(io_leave) mvc __TI_precount(4,%r9),BASED(.Lc_pactive) - stosm 24(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts l %r1,BASED(.Lschedule) basr %r14,%r1 # call schedule - stnsm 24(%r15),0xfc # disable I/O and ext. interrupts + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts xc __TI_precount(4,%r9),__TI_precount(%r9) b BASED(io_resume_loop) #endif @@ -514,7 +506,7 @@ io_work: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) - xc 0(4,%r1),0(%r1) # clear back chain + xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1 # # One of the work bits is on. Find out which one. @@ -532,9 +524,9 @@ io_work_loop: # io_reschedule: l %r1,BASED(.Lschedule) - stosm 24(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts basr %r14,%r1 # call scheduler - stnsm 24(%r15),0xfc # disable I/O and ext. interrupts + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts tm __TI_flags+3(%r9),_TIF_WORK_INT bz BASED(io_leave) # there is no work to do b BASED(io_work_loop) @@ -543,12 +535,12 @@ io_reschedule: # _TIF_SIGPENDING is set, call do_signal # io_sigpending: - stosm 24(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs sr %r3,%r3 # clear *oldset l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal - stnsm 24(%r15),0xfc # disable I/O and ext. interrupts + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts b BASED(io_leave) # out of here, do NOT recheck /* @@ -589,8 +581,8 @@ restart_int_handler: l %r15,__LC_SAVE_AREA+60 # load ksp lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs lam %a0,%a15,__LC_AREGS_SAVE_AREA - stosm 0(%r15),0x04 # now we can turn dat on - lm %r6,%r15,24(%r15) # load registers from clone + lm %r6,%r15,__SF_GPRS(%r15) # load registers from clone + stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on basr %r14,0 l %r14,restart_addr-.(%r14) br %r14 # branch to start_secondary @@ -611,6 +603,31 @@ restart_crash: restart_go: #endif +#ifdef CONFIG_CHECK_STACK +/* + * The synchronous or the asynchronous stack overflowed. We are dead. + * No need to properly save the registers, we are going to panic anyway. + * Setup a pt_regs so that show_trace can provide a good call trace. + */ +stack_overflow: + l %r15,__LC_PANIC_STACK # change to panic stack + sl %r15,BASED(.Lc_spsize) + mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack + stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack + la %r1,__LC_SAVE_AREA + ch %r12,BASED(.L0x020) # old psw addr == __LC_SVC_OLD_PSW ? + be BASED(0f) + ch %r12,BASED(.L0x028) # old psw addr == __LC_PGM_OLD_PSW ? + be BASED(0f) + la %r1,__LC_SAVE_AREA+16 +0: mvc SP_R12(16,%r15),0(%r1) # move %r12-%r15 to stack + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain + l %r1,BASED(1f) # branch to kernel_stack_overflow + la %r2,SP_PTREGS(%r15) # load pt_regs + br %r1 +1: .long kernel_stack_overflow +#endif + cleanup_table_system_call: .long system_call + 0x80000000, sysc_do_svc + 0x80000000 cleanup_table_sysc_return: @@ -695,7 +712,6 @@ cleanup_sysc_leave_lpsw: .Ldo_IRQ: .long do_IRQ .Ldo_extint: .long do_extint .Ldo_signal: .long do_signal -.Ldo_softirq: .long do_softirq .Lhandle_per: .long do_single_step .Ljump_table: .long pgm_check_table .Lschedule: .long schedule diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 54190092b..adbe2a5f5 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -19,6 +19,7 @@ #include #include #include +#include /* * Stack layout for the system_call stack entry. @@ -48,6 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE +STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER +STACK_SIZE = 1 << STACK_SHIFT + _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) @@ -85,10 +89,16 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) jnz 1f 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? slgr %r14,%r15 - srag %r14,%r14,14 + srag %r14,%r14,STACK_SHIFT jz 2f 1: lg %r15,__LC_ASYNC_STACK # load async stack .endif +#ifdef CONFIG_CHECK_STACK + j 3f +2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + jz stack_overflow +3: +#endif 2: aghi %r15,-SP_SIZE # make room for registers & psw mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack la %r12,\psworg @@ -98,7 +108,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) st %r12,SP_ILC(%r15) mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack la %r12,0 - stg %r12,0(%r15) + stg %r12,__SF_BACKCHAIN(%r15) .endm .macro RESTORE_ALL sync @@ -121,43 +131,23 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) __switch_to: tm __THREAD_per+4(%r3),0xe8 # is the new process using per ? jz __switch_to_noper # if not we're fine - stctg %c9,%c11,48(%r15) # We are using per stuff - clc __THREAD_per(24,%r3),48(%r15) + stctg %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff + clc __THREAD_per(24,%r3),__SF_EMPTY(%r15) je __switch_to_noper # we got away without bashing TLB's lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't __switch_to_noper: - stmg %r6,%r15,48(%r15) # store __switch_to registers of prev task + stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp - lmg %r6,%r15,48(%r15) # load __switch_to registers of next task + lmg %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task stg %r3,__LC_CURRENT # __LC_CURRENT = current task struct + lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 lg %r3,__THREAD_info(%r3) # load thread_info from task struct stg %r3,__LC_THREAD_INFO - aghi %r3,16384 + aghi %r3,STACK_SIZE stg %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack br %r14 -/* - * do_softirq calling function. We want to run the softirq functions on the - * asynchronous interrupt stack. - */ - .global do_call_softirq -do_call_softirq: - stnsm 48(%r15),0xfc - stmg %r12,%r15,56(%r15) - lgr %r12,%r15 - lg %r0,__LC_ASYNC_STACK - slgr %r0,%r15 - srag %r0,%r0,14 - je 0f - lg %r15,__LC_ASYNC_STACK -0: aghi %r15,-STACK_FRAME_OVERHEAD - stg %r12,0(%r15) # store back chain - brasl %r14,do_softirq - lmg %r12,%r15,56(%r12) - ssm 48(%r15) - br %r14 - __critical_start: /* * SVC interrupt handler routine. System calls are synchronous events and @@ -241,6 +231,8 @@ sysc_sigpending: brasl %r14,do_signal # call do_signal tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart + tm __TI_flags+7(%r9),_TIF_SINGLE_STEP + jo sysc_singlestep j sysc_leave # out of here, do NOT recheck # @@ -304,7 +296,10 @@ sysc_tracenogo: ret_from_fork: lg %r13,__LC_SVC_NEW_PSW+8 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct - brasl %r14,schedule_tail + tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? + jo 0f + stg %r15,SP_R15(%r15) # store stack pointer for new kthread +0: brasl %r14,schedule_tail stosm 24(%r15),0x03 # reenable interrupts j sysc_return @@ -504,7 +499,7 @@ pgm_svcper: mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP - stosm 48(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc /* @@ -539,16 +534,16 @@ io_preempt: lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) - xc 0(8,%r1),0(%r1) # clear back chain + xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 io_resume_loop: tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jno io_leave larl %r1,.Lc_pactive mvc __TI_precount(4,%r9),0(%r1) - stosm 48(%r15),0x03 # reenable interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,schedule # call schedule - stnsm 48(%r15),0xfc # disable I/O and ext. interrupts + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts xc __TI_precount(4,%r9),__TI_precount(%r9) j io_resume_loop #endif @@ -560,7 +555,7 @@ io_work: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) - xc 0(8,%r1),0(%r1) # clear back chain + xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 # # One of the work bits is on. Find out which one. @@ -577,23 +572,23 @@ io_work_loop: # _TIF_NEED_RESCHED is set, call schedule # io_reschedule: - stosm 48(%r15),0x03 # reenable interrupts - brasl %r14,schedule # call scheduler - stnsm 48(%r15),0xfc # disable I/O and ext. interrupts + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + brasl %r14,schedule # call scheduler + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts tm __TI_flags+7(%r9),_TIF_WORK_INT - jz io_leave # there is no work to do + jz io_leave # there is no work to do j io_work_loop # # _TIF_SIGPENDING is set, call do_signal # io_sigpending: - stosm 48(%r15),0x03 # reenable interrupts - la %r2,SP_PTREGS(%r15) # load pt_regs - slgr %r3,%r3 # clear *oldset - brasl %r14,do_signal # call do_signal - stnsm 48(%r15),0xfc # disable I/O and ext. interrupts - j sysc_leave # out of here, do NOT recheck + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + la %r2,SP_PTREGS(%r15) # load pt_regs + slgr %r3,%r3 # clear *oldset + brasl %r14,do_signal # call do_signal + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + j sysc_leave # out of here, do NOT recheck /* * External interrupt handler routine @@ -631,8 +626,8 @@ restart_int_handler: lctlg %c0,%c15,0(%r10) # get new ctl regs lghi %r10,__LC_AREGS_SAVE_AREA lam %a0,%a15,0(%r10) - stosm 0(%r15),0x04 # now we can turn dat on - lmg %r6,%r15,48(%r15) # load registers from clone + lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone + stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on jg start_secondary #else /* @@ -649,6 +644,29 @@ restart_crash: restart_go: #endif +#ifdef CONFIG_CHECK_STACK +/* + * The synchronous or the asynchronous stack overflowed. We are dead. + * No need to properly save the registers, we are going to panic anyway. + * Setup a pt_regs so that show_trace can provide a good call trace. + */ +stack_overflow: + lg %r15,__LC_PANIC_STACK # change to panic stack + aghi %r1,-SP_SIZE + mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack + stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack + la %r1,__LC_SAVE_AREA + chi %r12,__LC_SVC_OLD_PSW + je 0f + chi %r12,__LC_PGM_OLD_PSW + je 0f + la %r1,__LC_SAVE_AREA+16 +0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain + la %r2,SP_PTREGS(%r15) # load pt_regs + jg kernel_stack_overflow +#endif + cleanup_table_system_call: .quad system_call, sysc_do_svc cleanup_table_sysc_return: diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index fb295b79f..b804c55bd 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifndef CONFIG_IPL .org 0 @@ -741,10 +743,10 @@ _stext: basr %r13,0 # get base # l %r15,.Linittu-.LPG2(%r13) mvc __LC_CURRENT(4),__TI_task(%r15) - ahi %r15,8192 # init_task_union + 8192 + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE st %r15,__LC_KERNEL_STACK # set end of kernel stack ahi %r15,-96 - xc 0(4,%r15),0(%r15) # set backchain to zero + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain # check control registers stctl %c0,%c15,0(%r15) diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index e32a8e90f..8366793bc 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifndef CONFIG_IPL .org 0 @@ -741,10 +743,10 @@ _stext: basr %r13,0 # get base larl %r15,init_thread_union lg %r14,__TI_task(%r15) # cache current in lowcore stg %r14,__LC_CURRENT - aghi %r15,16384 # init_task_union + 16384 + aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE stg %r15,__LC_KERNEL_STACK # set end of kernel stack aghi %r15,-160 - xc 0(8,%r15),0(%r15) # set backchain to zero + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain # check control registers stctg %c0,%c15,0(%r15) diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 79a422247..75275fe90 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -86,7 +86,7 @@ asmlinkage void do_softirq(void) " la 15,0(%1)\n" : : "a" (new), "a" (old), "a" (__do_softirq) - : "0", "1", "2", "3", "4", "5", + : "0", "1", "2", "3", "4", "5", "14", "cc", "memory" ); } else /* We are already on the async stack. */ diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 73cb6baeb..1a97c5204 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -58,14 +58,11 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - unsigned long bc; + struct stack_frame *sf; - bc = *((unsigned long *) tsk->thread.ksp); -#ifndef CONFIG_ARCH_S390X - return *((unsigned long *) (bc+56)); -#else - return *((unsigned long *) (bc+112)); -#endif + sf = (struct stack_frame *) tsk->thread.ksp; + sf = (struct stack_frame *) sf->back_chain; + return sf->gprs[8]; } /* @@ -186,41 +183,20 @@ void show_regs(struct pt_regs *regs) extern void kernel_thread_starter(void); -#ifndef CONFIG_ARCH_S390X - __asm__(".align 4\n" "kernel_thread_starter:\n" - " l 15,0(8)\n" - " sr 15,7\n" - " stosm 24(15),3\n" - " lr 2,10\n" + " la 2,0(10)\n" " basr 14,9\n" - " sr 2,2\n" + " la 2,0\n" " br 11\n"); -#else /* CONFIG_ARCH_S390X */ - -__asm__(".align 4\n" - "kernel_thread_starter:\n" - " lg 15,0(8)\n" - " sgr 15,7\n" - " stosm 48(15),3\n" - " lgr 2,10\n" - " basr 14,9\n" - " sgr 2,2\n" - " br 11\n"); - -#endif /* CONFIG_ARCH_S390X */ - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); - regs.psw.mask = PSW_KERNEL_BITS; + regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT; regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE; - regs.gprs[7] = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); - regs.gprs[8] = __LC_KERNEL_STACK; regs.gprs[9] = (unsigned long) fn; regs.gprs[10] = (unsigned long) arg; regs.gprs[11] = (unsigned long) do_exit; @@ -253,34 +229,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { - struct stack_frame + struct fake_frame { - unsigned long back_chain; - unsigned long eos; - unsigned long glue1; - unsigned long glue2; - unsigned long scratch[2]; - unsigned long gprs[10]; /* gprs 6 -15 */ - unsigned int fprs[4]; /* fpr 4 and 6 */ - unsigned int empty[4]; + struct stack_frame sf; struct pt_regs childregs; } *frame; - frame = ((struct stack_frame *) + frame = ((struct fake_frame *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; p->thread.ksp = (unsigned long) frame; - p->set_child_tid = p->clear_child_tid = NULL; /* Store access registers to kernel stack of new process. */ frame->childregs = *regs; frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ frame->childregs.gprs[15] = new_stackp; - frame->back_chain = frame->eos = 0; + frame->sf.back_chain = 0; /* new return point is ret_from_fork */ - frame->gprs[8] = (unsigned long) ret_from_fork; + frame->sf.gprs[8] = (unsigned long) ret_from_fork; /* fake return stack for resume(), don't go back to schedule */ - frame->gprs[9] = (unsigned long) frame; + frame->sf.gprs[9] = (unsigned long) frame; /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); @@ -336,7 +304,7 @@ asmlinkage long sys_clone(struct pt_regs regs) child_tidptr = (int __user *) regs.gprs[5]; if (!newsp) newsp = regs.gprs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } @@ -371,7 +339,9 @@ asmlinkage long sys_execve(struct pt_regs regs) error = do_execve(filename, (char __user * __user *) regs.gprs[3], (char __user * __user *) regs.gprs[4], ®s); if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); current->thread.fp_regs.fpc = 0; if (MACHINE_HAS_IEEE) asm volatile("sfpc %0,%0" : : "d" (0)); @@ -423,30 +393,26 @@ void dump_thread(struct pt_regs * regs, struct user * dump) unsigned long get_wchan(struct task_struct *p) { - unsigned long r14, r15, bc; - unsigned long stack_page; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) + struct stack_frame *sf, *low, *high; + unsigned long return_address; + int count; + + if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info) return 0; - stack_page = (unsigned long) p->thread_info; - r15 = p->thread.ksp; - if (!stack_page || r15 < stack_page || - r15 >= THREAD_SIZE - sizeof(unsigned long) + stack_page) + low = (struct stack_frame *) p->thread_info; + high = (struct stack_frame *) + ((unsigned long) p->thread_info + THREAD_SIZE) - 1; + sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN); + if (sf <= low || sf > high) return 0; - bc = (*(unsigned long *) r15) & PSW_ADDR_INSN; - do { - if (bc < stack_page || - bc >= THREAD_SIZE - sizeof(unsigned long) + stack_page) + for (count = 0; count < 16; count++) { + sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN); + if (sf <= low || sf > high) return 0; -#ifndef CONFIG_ARCH_S390X - r14 = (*(unsigned long *) (bc+56)) & PSW_ADDR_INSN; -#else - r14 = *(unsigned long *) (bc+112); -#endif - if (!in_sched_functions(r14)) - return r14; - bc = (*(unsigned long *) bc) & PSW_ADDR_INSN; - } while (count++ < 16); + return_address = sf->gprs[8] & PSW_ADDR_INSN; + if (!in_sched_functions(return_address)) + return return_address; + } return 0; } diff --git a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c index f219748d7..7ba777eec 100644 --- a/arch/s390/kernel/profile.c +++ b/arch/s390/kernel/profile.c @@ -6,52 +6,15 @@ * */ #include +#include static struct proc_dir_entry * root_irq_dir; -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, - const char __user *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data; - unsigned long full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -cpumask_t prof_cpu_mask = CPU_MASK_ALL; - void init_irq_proc(void) { - struct proc_dir_entry *entry; - /* create /proc/irq */ root_irq_dir = proc_mkdir("irq", 0); /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; + create_prof_cpu_mask(root_irq_dir); } diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 26b89e55d..2df9d1af0 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -626,7 +626,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) * perhaps it should be put in the status that it wants to * exit. */ - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ return 0; child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ @@ -640,7 +640,10 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) return -EIO; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; - set_single_step(child); + if (data) + set_tsk_thread_flag(child, TIF_SINGLE_STEP); + else + set_single_step(child); /* give it a chance to run. */ wake_up_process(child); return 0; diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index c00e5e328..b61490bd1 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 43afd32f8..1a5ba047e 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -23,16 +23,18 @@ /* * memory management */ -EXPORT_SYMBOL_NOVERS(_oi_bitmap); -EXPORT_SYMBOL_NOVERS(_ni_bitmap); -EXPORT_SYMBOL_NOVERS(_zb_findmap); -EXPORT_SYMBOL_NOVERS(_sb_findmap); -EXPORT_SYMBOL_NOVERS(__copy_from_user_asm); -EXPORT_SYMBOL_NOVERS(__copy_to_user_asm); -EXPORT_SYMBOL_NOVERS(__clear_user_asm); -EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm); -EXPORT_SYMBOL_NOVERS(__strnlen_user_asm); +EXPORT_SYMBOL(_oi_bitmap); +EXPORT_SYMBOL(_ni_bitmap); +EXPORT_SYMBOL(_zb_findmap); +EXPORT_SYMBOL(_sb_findmap); +EXPORT_SYMBOL(__copy_from_user_asm); +EXPORT_SYMBOL(__copy_to_user_asm); +EXPORT_SYMBOL(__copy_in_user_asm); +EXPORT_SYMBOL(__clear_user_asm); +EXPORT_SYMBOL(__strncpy_from_user_asm); +EXPORT_SYMBOL(__strnlen_user_asm); EXPORT_SYMBOL(diag10); +EXPORT_SYMBOL(default_storage_key); /* * semaphore ops @@ -60,6 +62,5 @@ EXPORT_SYMBOL(csum_fold); EXPORT_SYMBOL(console_mode); EXPORT_SYMBOL(console_devno); EXPORT_SYMBOL(console_irq); -EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index a50891ce0..1324fc6ce 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -53,6 +53,7 @@ unsigned int console_devno = -1; unsigned int console_irq = -1; unsigned long memory_size = 0; unsigned long machine_flags = 0; +unsigned int default_storage_key = 0; struct { unsigned long addr, size, type; } memory_chunk[MEMORY_CHUNKS] = { { 0 } }; @@ -503,6 +504,10 @@ void __init setup_arch(char **cmdline_p) lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->async_stack = (unsigned long) __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; +#ifdef CONFIG_CHECK_STACK + lc->panic_stack = (unsigned long) + __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; +#endif lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union; #ifdef CONFIG_ARCH_S390X @@ -604,49 +609,3 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -/* - * show_interrupts is needed by /proc/interrupts. - */ - -static const char *intrclass_names[] = { - "EXT", - "I/O", -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - - if (i == 0) { - seq_puts(p, " "); - for (j=0; jsa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -414,9 +412,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -424,20 +420,15 @@ give_sigsegv: */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(sig, ka, info, oldset, regs); else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -461,6 +452,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) unsigned long retval = 0, continue_addr = 0, restart_addr = 0; siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -494,7 +486,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Get signal to deliver. When running under ptrace, at this point the debugger may change all our registers ... */ - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* Depending on the signal settings we may need to revert the decision to restart the system call. */ @@ -513,14 +505,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) #ifdef CONFIG_S390_SUPPORT if (test_thread_flag(TIF_31BIT)) { extern void handle_signal32(unsigned long sig, + struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); - handle_signal32(signr, &info, oldset, regs); + handle_signal32(signr, &ka, &info, oldset, regs); return 1; } #endif - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index eb8a5161a..b5c09d144 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -562,21 +562,15 @@ int __devinit start_secondary(void *cpuvoid) static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* * don't care about the psw and regs settings since we'll never * reschedule the forked task. */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - wake_up_forked_process(p); - init_idle(p, cpu); - unhash_process(p); current_set[cpu] = p; } @@ -643,6 +637,7 @@ __cpu_up(unsigned int cpu) { struct task_struct *idle; struct _lowcore *cpu_lowcore; + struct stack_frame *sf; sigp_ccode ccode; int curr_cpu; @@ -666,9 +661,14 @@ __cpu_up(unsigned int cpu) idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; - cpu_lowcore->save_area[15] = idle->thread.ksp; cpu_lowcore->kernel_stack = (unsigned long) idle->thread_info + (THREAD_SIZE); + sf = (struct stack_frame *) (cpu_lowcore->kernel_stack + - sizeof(struct pt_regs) + - sizeof(struct stack_frame)); + memset(sf, 0, sizeof(struct stack_frame)); + sf->gprs[9] = (unsigned long) sf; + cpu_lowcore->save_area[15] = (unsigned long) sf; __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15); __asm__ __volatile__("stam 0,15,0(%0)" : : "a" (&cpu_lowcore->access_regs_save_area) @@ -747,7 +747,7 @@ cpu_die(void) void __init smp_prepare_cpus(unsigned int max_cpus) { - unsigned long async_stack; + unsigned long stack; unsigned int cpu; int i; @@ -767,12 +767,18 @@ void __init smp_prepare_cpus(unsigned int max_cpus) lowcore_ptr[i] = (struct _lowcore *) __get_free_pages(GFP_KERNEL|GFP_DMA, sizeof(void*) == 8 ? 1 : 0); - async_stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER); - if (lowcore_ptr[i] == NULL || async_stack == 0ULL) + stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER); + if (lowcore_ptr[i] == NULL || stack == 0ULL) panic("smp_boot_cpus failed to allocate memory\n"); *(lowcore_ptr[i]) = S390_lowcore; - lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE); + lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE); +#ifdef CONFIG_CHECK_STACK + stack = __get_free_pages(GFP_KERNEL,0); + if (stack == 0ULL) + panic("smp_boot_cpus failed to allocate memory\n"); + lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); +#endif } set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 9186fe765..f5207d916 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -283,5 +283,6 @@ SYSCALL(sys_mq_open,sys_mq_open,compat_sys_mq_open_wrapper) SYSCALL(sys_mq_unlink,sys_mq_unlink,sys32_mq_unlink_wrapper) SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend_wrapper) SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper) -SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) +SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */ SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper) +NI_SYSCALL /* reserved for kexec */ diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 12f46a65a..2fea300f4 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -174,47 +174,7 @@ __calculate_ticks(__u64 elapsed) #ifdef CONFIG_PROFILING -extern char _stext, _etext; - -/* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ -static inline void s390_do_profile(struct pt_regs * regs) -{ - unsigned long eip; - extern cpumask_t prof_cpu_mask; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; - - eip = instruction_pointer(regs); - - /* - * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. - * (default is all CPUs.) - */ - if (!cpu_isset(smp_processor_id(), prof_cpu_mask)) - return; - - eip -= (unsigned long) &_stext; - eip >>= prof_shift; - /* - * Don't ignore out-of-bounds EIP values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (eip > prof_len-1) - eip = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[eip]); -} +#define s390_do_profile(regs) profile_tick(CPU_PROFILING, regs) #else #define s390_do_profile(regs) do { ; } while(0) #endif /* CONFIG_PROFILING */ @@ -273,8 +233,10 @@ void account_ticks(struct pt_regs *regs) while (ticks--) update_process_times(user_mode(regs)); #else - while (ticks--) + while (ticks--) { do_timer(regs); + update_process_times(user_mode(regs)); + } #endif s390_do_profile(regs); } @@ -298,18 +260,21 @@ static inline void stop_hz_timer(void) if (sysctl_hz_timer != 0) return; + cpu_set(smp_processor_id(), nohz_cpu_mask); + /* * Leave the clock comparator set up for the next timer * tick if either rcu or a softirq is pending. */ - if (rcu_pending(smp_processor_id()) || local_softirq_pending()) + if (rcu_pending(smp_processor_id()) || local_softirq_pending()) { + cpu_clear(smp_processor_id(), nohz_cpu_mask); return; + } /* * This cpu is going really idle. Set up the clock comparator * for the next event. */ - cpu_set(smp_processor_id(), nohz_cpu_mask); timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; asm volatile ("SCKC %0" : : "m" (timer)); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6614d4be1..6451cec05 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -38,6 +38,7 @@ #include #include #include +#include /* Called from entry.S only */ extern void handle_per_exception(struct pt_regs *regs); @@ -67,54 +68,93 @@ extern pgm_check_handler_t do_monitor_call; #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) #ifndef CONFIG_ARCH_S390X -#define RET_ADDR 56 #define FOURLONG "%08lx %08lx %08lx %08lx\n" static int kstack_depth_to_print = 12; - #else /* CONFIG_ARCH_S390X */ -#define RET_ADDR 112 #define FOURLONG "%016lx %016lx %016lx %016lx\n" static int kstack_depth_to_print = 20; - #endif /* CONFIG_ARCH_S390X */ -void show_trace(struct task_struct *task, unsigned long * stack) +/* + * For show_trace we have tree different stack to consider: + * - the panic stack which is used if the kernel stack has overflown + * - the asynchronous interrupt stack (cpu related) + * - the synchronous kernel stack (process related) + * The stack trace can start at any of the three stack and can potentially + * touch all of them. The order is: panic stack, async stack, sync stack. + */ +static unsigned long +__show_trace(unsigned long sp, unsigned long low, unsigned long high) { - unsigned long backchain, low_addr, high_addr, ret_addr; + struct stack_frame *sf; + struct pt_regs *regs; - if (!stack) - stack = (task == NULL) ? *stack_pointer : &(task->thread.ksp); + while (1) { + sp = sp & PSW_ADDR_INSN; + if (sp < low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *) sp; + printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN); + print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN); + /* Follow the backchain. */ + while (1) { + low = sp; + sp = sf->back_chain & PSW_ADDR_INSN; + if (!sp) + break; + if (sp <= low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *) sp; + printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN); + print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN); + } + /* Zero backchain detected, check for interrupt frame. */ + sp = (unsigned long) (sf + 1); + if (sp <= low || sp > high - sizeof(*regs)) + return sp; + regs = (struct pt_regs *) sp; + printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN); + print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN); + low = sp; + sp = regs->gprs[15]; + } +} + +void show_trace(struct task_struct *task, unsigned long * stack) +{ + register unsigned long __r15 asm ("15"); + unsigned long sp; + sp = (unsigned long) stack; + if (!sp) + sp = task ? task->thread.ksp : __r15; printk("Call Trace:\n"); - low_addr = ((unsigned long) stack) & PSW_ADDR_INSN; - high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE; - /* Skip the first frame (biased stack) */ - backchain = *((unsigned long *) low_addr) & PSW_ADDR_INSN; - /* Print up to 8 lines */ - while (backchain > low_addr && backchain <= high_addr) { - ret_addr = *((unsigned long *) (backchain+RET_ADDR)) & PSW_ADDR_INSN; - printk(" [<%016lx>] ", ret_addr); - print_symbol("%s\n", ret_addr); - low_addr = backchain; - backchain = *((unsigned long *) backchain) & PSW_ADDR_INSN; - } +#ifdef CONFIG_CHECK_STACK + sp = __show_trace(sp, S390_lowcore.panic_stack - 4096, + S390_lowcore.panic_stack); +#endif + sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE, + S390_lowcore.async_stack); + if (task) + __show_trace(sp, (unsigned long) task->thread_info, + (unsigned long) task->thread_info + THREAD_SIZE); + else + __show_trace(sp, S390_lowcore.thread_info, + S390_lowcore.thread_info + THREAD_SIZE); printk("\n"); } void show_stack(struct task_struct *task, unsigned long *sp) { + register unsigned long * __r15 asm ("15"); unsigned long *stack; int i; // debugging aid: "show_stack(NULL);" prints the // back trace for this cpu. - if (!sp) { - if (task) - sp = (unsigned long *) task->thread.ksp; - else - sp = *stack_pointer; - } + if (!sp) + sp = task ? (unsigned long *) task->thread.ksp : __r15; stack = sp; for (i = 0; i < kstack_depth_to_print; i++) { @@ -238,8 +278,10 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char * str, struct pt_regs * regs, long err) { static int die_counter; - console_verbose(); - spin_lock_irq(&die_lock); + + debug_stop_all(); + console_verbose(); + spin_lock_irq(&die_lock); bust_spinlocks(1); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); show_regs(regs); @@ -252,6 +294,20 @@ void die(const char * str, struct pt_regs * regs, long err) do_exit(SIGSEGV); } +static void inline +report_user_fault(long interruption_code, struct pt_regs *regs) +{ +#if defined(CONFIG_SYSCTL) + if (!sysctl_userprocess_debug) + return; +#endif +#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) + printk("User process fault: interruption code 0x%lX\n", + interruption_code); + show_regs(regs); +#endif +} + static void inline do_trap(long interruption_code, int signr, char *str, struct pt_regs *regs, siginfo_t *info) { @@ -266,23 +322,8 @@ static void inline do_trap(long interruption_code, int signr, char *str, struct task_struct *tsk = current; tsk->thread.trap_no = interruption_code & 0xffff; - if (info) - force_sig_info(signr, info, tsk); - else - force_sig(signr, tsk); -#ifndef CONFIG_SYSCTL -#ifdef CONFIG_PROCESS_DEBUG - printk("User process fault: interruption code 0x%lX\n", - interruption_code); - show_regs(regs); -#endif -#else - if (sysctl_userprocess_debug) { - printk("User process fault: interruption code 0x%lX\n", - interruption_code); - show_regs(regs); - } -#endif + force_sig_info(signr, info, tsk); + report_user_fault(interruption_code, regs); } else { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); @@ -304,10 +345,15 @@ void do_single_step(struct pt_regs *regs) force_sig(SIGTRAP, current); } -#define DO_ERROR(signr, str, name) \ -asmlinkage void name(struct pt_regs * regs, long interruption_code) \ -{ \ - do_trap(interruption_code, signr, str, regs, NULL); \ +asmlinkage void +default_trap_handler(struct pt_regs * regs, long interruption_code) +{ + if (regs->psw.mask & PSW_MASK_PSTATE) { + local_irq_enable(); + do_exit(SIGSEGV); + report_user_fault(interruption_code, regs); + } else + die("Unknown program exception", regs, interruption_code); } #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \ @@ -321,8 +367,6 @@ asmlinkage void name(struct pt_regs * regs, long interruption_code) \ do_trap(interruption_code, signr, str, regs, &info); \ } -DO_ERROR(SIGSEGV, "Unknown program exception", default_trap_handler) - DO_ERROR_INFO(SIGILL, "addressing exception", addressing_exception, ILL_ILLADR, get_check_address(regs)) DO_ERROR_INFO(SIGILL, "execute exception", execute_exception, @@ -381,6 +425,7 @@ do_fp_trap(struct pt_regs *regs, void *location, asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) { + siginfo_t info; __u8 opcode[6]; __u16 *location; int signal = 0; @@ -424,12 +469,27 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) } else signal = SIGILL; +#ifdef CONFIG_MATHEMU if (signal == SIGFPE) do_fp_trap(regs, location, current->thread.fp_regs.fpc, interruption_code); - else if (signal) + else if (signal == SIGSEGV) { + info.si_signo = signal; + info.si_errno = 0; + info.si_code = SEGV_MAPERR; + info.si_addr = (void *) location; do_trap(interruption_code, signal, - "illegal operation", regs, NULL); + "user address fault", regs, &info); + } else +#endif + if (signal) { + info.si_signo = signal; + info.si_errno = 0; + info.si_code = ILL_ILLOPC; + info.si_addr = (void *) location; + do_trap(interruption_code, signal, + "illegal operation", regs, &info); + } } @@ -591,6 +651,26 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code) } } +asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code) +{ + siginfo_t info; + + /* Set user psw back to home space mode. */ + if (regs->psw.mask & PSW_MASK_PSTATE) + regs->psw.mask |= PSW_ASC_HOME; + /* Send SIGILL. */ + info.si_signo = SIGILL; + info.si_errno = 0; + info.si_code = ILL_PRVOPC; + info.si_addr = get_check_address(regs); + do_trap(int_code, SIGILL, "space switch event", regs, &info); +} + +asmlinkage void kernel_stack_overflow(struct pt_regs * regs) +{ + die("Kernel stack overflow", regs, 0); + panic("Corrupt kernel stack, can't continue."); +} /* init is done in lowcore.S and head.S */ @@ -629,7 +709,7 @@ void __init trap_init(void) pgm_check_table[0x3B] = &do_dat_exception; #endif /* CONFIG_ARCH_S390X */ pgm_check_table[0x15] = &operand_exception; - pgm_check_table[0x1C] = &privileged_op; + pgm_check_table[0x1C] = &space_switch_exception; pgm_check_table[0x1D] = &hfp_sqrt_exception; pgm_check_table[0x40] = &do_monitor_call; diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index b4534b286..89fdb3808 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -24,6 +24,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } = 0x0700 @@ -78,9 +79,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index d9ccdbdc2..02d2179e4 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -21,7 +21,7 @@ #include #include -#define VTIMER_MAGIC (0x4b87ad6e + 1) +#define VTIMER_MAGIC (TIMER_MAGIC + 1) static ext_int_info_t ext_int_info_timer; DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index 966af7c52..9cf22aa48 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -46,7 +46,7 @@ size_t strlen(const char *s) { return __strend(s) - s; } -EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL(strlen); /** * strnlen - Find the length of a length-limited string @@ -59,7 +59,7 @@ size_t strnlen(const char * s, size_t n) { return __strnend(s, n) - s; } -EXPORT_SYMBOL_NOVERS(strnlen); +EXPORT_SYMBOL(strnlen); /** * strcpy - Copy a %NUL terminated string @@ -79,7 +79,7 @@ char *strcpy(char *dest, const char *src) : "cc", "memory" ); return ret; } -EXPORT_SYMBOL_NOVERS(strcpy); +EXPORT_SYMBOL(strcpy); /** * strlcpy - Copy a %NUL terminated string into a sized buffer @@ -103,7 +103,7 @@ size_t strlcpy(char *dest, const char *src, size_t size) } return ret; } -EXPORT_SYMBOL_NOVERS(strlcpy); +EXPORT_SYMBOL(strlcpy); /** * strncpy - Copy a length-limited, %NUL-terminated string @@ -121,7 +121,7 @@ char *strncpy(char *dest, const char *src, size_t n) __builtin_memcpy(dest, src, len); return dest; } -EXPORT_SYMBOL_NOVERS(strncpy); +EXPORT_SYMBOL(strncpy); /** * strcat - Append one %NUL-terminated string to another @@ -144,7 +144,7 @@ char *strcat(char *dest, const char *src) : "d" (r0), "0" (0UL) : "cc", "memory" ); return ret; } -EXPORT_SYMBOL_NOVERS(strcat); +EXPORT_SYMBOL(strcat); /** * strlcat - Append a length-limited, %NUL-terminated string to another @@ -168,7 +168,7 @@ size_t strlcat(char *dest, const char *src, size_t n) } return res; } -EXPORT_SYMBOL_NOVERS(strlcat); +EXPORT_SYMBOL(strlcat); /** * strncat - Append a length-limited, %NUL-terminated string to another @@ -190,7 +190,7 @@ char *strncat(char *dest, const char *src, size_t n) __builtin_memcpy(p, src, len); return dest; } -EXPORT_SYMBOL_NOVERS(strncat); +EXPORT_SYMBOL(strncat); /** * strcmp - Compare two strings @@ -217,7 +217,7 @@ int strcmp(const char *cs, const char *ct) : : "cc" ); return ret; } -EXPORT_SYMBOL_NOVERS(strcmp); +EXPORT_SYMBOL(strcmp); /** * strrchr - Find the last occurrence of a character in a string @@ -235,7 +235,7 @@ char * strrchr(const char * s, int c) } while (--len > 0); return 0; } -EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL(strrchr); /** * strstr - Find the first substring in a %NUL terminated string @@ -269,7 +269,7 @@ char * strstr(const char * s1,const char * s2) } return 0; } -EXPORT_SYMBOL_NOVERS(strstr); +EXPORT_SYMBOL(strstr); /** * memchr - Find a character in an area of memory. @@ -293,7 +293,7 @@ void *memchr(const void *s, int c, size_t n) : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" ); return (void *) ret; } -EXPORT_SYMBOL_NOVERS(memchr); +EXPORT_SYMBOL(memchr); /** * memcmp - Compare two areas of memory @@ -319,7 +319,7 @@ int memcmp(const void *cs, const void *ct, size_t n) ret = *(char *) r2 - *(char *) r4; return ret; } -EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL(memcmp); /** * memscan - Find a character in an area of memory. @@ -340,7 +340,7 @@ void *memscan(void *s, int c, size_t n) : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" ); return (void *) ret; } -EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL(memscan); /** * memcpy - Copy one area of memory to another @@ -354,7 +354,7 @@ void *memcpy(void *dest, const void *src, size_t n) { return __builtin_memcpy(dest, src, n); } -EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL(memcpy); /** * bcopy - Copy one area of memory to another @@ -369,7 +369,7 @@ void bcopy(const void *srcp, void *destp, size_t n) { __builtin_memcpy(destp, srcp, n); } -EXPORT_SYMBOL_NOVERS(bcopy); +EXPORT_SYMBOL(bcopy); /** * memset - Fill a region of memory with the given value @@ -393,4 +393,4 @@ void *memset(void *s, int c, size_t n) } while (--n > 0); return s; } -EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL(memset); diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index f8583caa6..aa9a42b6e 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile @@ -2,6 +2,6 @@ # Makefile for the linux s390-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extmem.o +obj-y := init.o fault.o ioremap.o extmem.o mmap.o obj-$(CONFIG_CMM) += cmm.o diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index b0b2714ea..73feefb52 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -1,11 +1,10 @@ /* - * File...........: arch/s390/mm/dcss.c - * Author(s)......: Steven Shultz - * Carsten Otte + * File...........: arch/s390/mm/extmem.c + * Author(s)......: Carsten Otte + * Rob M van der Heij + * Steven Shultz * Bugreports.to..: - * thanks to Rob M van der Heij - * - he wrote the diag64 function - * (C) IBM Corporation 2002 + * (C) IBM Corporation 2002-2004 */ #include @@ -41,20 +40,48 @@ #define DCSS_FINDSEG 0x0c #define DCSS_LOADNOLY 0x10 #define DCSS_SEGEXT 0x18 -#define DCSS_QACTV 0x0c +#define DCSS_FINDSEGA 0x0c + +struct qrange { + unsigned int start; // 3byte start address, 1 byte type + unsigned int end; // 3byte end address, 1 byte reserved +}; + +struct qout64 { + int segstart; + int segend; + int segcnt; + int segrcnt; + struct qrange range[6]; +}; + +struct qin64 { + char qopcode; + char rsrv1[3]; + char qrcode; + char rsrv2[3]; + char qname[8]; + unsigned int qoutptr; + short int qoutlen; +}; struct dcss_segment { - struct list_head list; - char dcss_name[8]; - unsigned long start_addr; - unsigned long end; - atomic_t ref_count; - int dcss_attr; - int shared_attr; + struct list_head list; + char dcss_name[8]; + unsigned long start_addr; + unsigned long end; + atomic_t ref_count; + int do_nonshared; + unsigned int vm_segtype; + struct qrange range[6]; + int segcnt; }; static spinlock_t dcss_lock = SPIN_LOCK_UNLOCKED; static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list); +static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", + "EW/EN-MIXED" }; + extern struct { unsigned long addr, size, type; } memory_chunk[MEMORY_CHUNKS]; @@ -63,20 +90,46 @@ extern struct { * Create the 8 bytes, ebcdic VM segment name from * an ascii name. */ -static void inline dcss_mkname(char *name, char *dcss_name) +static void inline +dcss_mkname(char *name, char *dcss_name) +{ + int i; + + for (i = 0; i < 8; i++) { + if (name[i] == '\0') + break; + dcss_name[i] = toupper(name[i]); + }; + for (; i < 8; i++) + dcss_name[i] = ' '; + ASCEBC(dcss_name, 8); +} + + +/* + * search all segments in dcss_list, and return the one + * namend *name. If not found, return NULL. + */ +static struct dcss_segment * +segment_by_name (char *name) { - int i; - - for (i = 0; i <= 8; i++) { - if (name[i] == '\0') - break; - dcss_name[i] = toupper(name[i]); - }; - for (; i <= 8; i++) - dcss_name[i] = ' '; - ASCEBC(dcss_name, 8); + char dcss_name[9]; + struct list_head *l; + struct dcss_segment *tmp, *retval = NULL; + + BUG_ON (!spin_is_locked(&dcss_lock)); + dcss_mkname (name, dcss_name); + list_for_each (l, &dcss_list) { + tmp = list_entry (l, struct dcss_segment, list); + if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) { + retval = tmp; + break; + } + } + return retval; } + /* * Perform a function on a dcss segment. */ @@ -84,337 +137,378 @@ static inline int dcss_diag (__u8 func, void *parameter, unsigned long *ret1, unsigned long *ret2) { - unsigned long rx, ry; - int rc; + unsigned long rx, ry; + int rc; - rx = (unsigned long) parameter; - ry = (unsigned long) func; - __asm__ __volatile__( + rx = (unsigned long) parameter; + ry = (unsigned long) func; + __asm__ __volatile__( #ifdef CONFIG_ARCH_S390X - " sam31\n" // switch to 31 bit - " diag %0,%1,0x64\n" - " sam64\n" // switch back to 64 bit + " sam31\n" // switch to 31 bit + " diag %0,%1,0x64\n" + " sam64\n" // switch back to 64 bit #else - " diag %0,%1,0x64\n" + " diag %0,%1,0x64\n" #endif - " ipm %2\n" - " srl %2,28\n" - : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" ); - *ret1 = rx; - *ret2 = ry; - return rc; + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" ); + *ret1 = rx; + *ret2 = ry; + return rc; +} + +static inline int +dcss_diag_translate_rc (int vm_rc) { + if (vm_rc == 44) + return -ENOENT; + return -EIO; +} + + +/* do a diag to get info about a segment. + * fills start_address, end and vm_segtype fields + */ +static int +query_segment_type (struct dcss_segment *seg) +{ + struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA); + struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA); + + int diag_cc, rc, i; + unsigned long dummy, vmrc; + + if ((qin == NULL) || (qout == NULL)) { + rc = -ENOMEM; + goto out_free; + } + + /* initialize diag input parameters */ + qin->qopcode = DCSS_FINDSEGA; + qin->qoutptr = (unsigned long) qout; + qin->qoutlen = sizeof(struct qout64); + memcpy (qin->qname, seg->dcss_name, 8); + + diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc); + + if (diag_cc > 1) { + rc = dcss_diag_translate_rc (vmrc); + goto out_free; + } + + if (qout->segcnt > 6) { + rc = -ENOTSUPP; + goto out_free; + } + + if (qout->segcnt == 1) { + seg->vm_segtype = qout->range[0].start & 0xff; + } else { + /* multi-part segment. only one type supported here: + - all parts are contiguous + - all parts are either EW or EN type + - maximum 6 parts allowed */ + unsigned long start = qout->segstart >> PAGE_SHIFT; + for (i=0; isegcnt; i++) { + if (((qout->range[i].start & 0xff) != SEG_TYPE_EW) && + ((qout->range[i].start & 0xff) != SEG_TYPE_EN)) { + rc = -ENOTSUPP; + goto out_free; + } + if (start != qout->range[i].start >> PAGE_SHIFT) { + rc = -ENOTSUPP; + goto out_free; + } + start = (qout->range[i].end >> PAGE_SHIFT) + 1; + } + seg->vm_segtype = SEG_TYPE_EWEN; + } + + /* analyze diag output and update seg */ + seg->start_addr = qout->segstart; + seg->end = qout->segend; + + memcpy (seg->range, qout->range, 6*sizeof(struct qrange)); + seg->segcnt = qout->segcnt; + + rc = 0; + + out_free: + if (qin) kfree(qin); + if (qout) kfree(qout); + return rc; +} + +/* + * check if the given segment collides with guest storage. + * returns 1 if this is the case, 0 if no collision was found + */ +static int +segment_overlaps_storage(struct dcss_segment *seg) +{ + int i; + + for (i=0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { + if (memory_chunk[i].type != 0) + continue; + if ((memory_chunk[i].addr >> 20) > (seg->end >> 20)) + continue; + if (((memory_chunk[i].addr + memory_chunk[i].size - 1) >> 20) + < (seg->start_addr >> 20)) + continue; + return 1; + } + return 0; } +/* + * check if segment collides with other segments that are currently loaded + * returns 1 if this is the case, 0 if no collision was found + */ +static int +segment_overlaps_others (struct dcss_segment *seg) +{ + struct list_head *l; + struct dcss_segment *tmp; + + BUG_ON (!spin_is_locked(&dcss_lock)); + list_for_each(l, &dcss_list) { + tmp = list_entry(l, struct dcss_segment, list); + if ((tmp->start_addr >> 20) > (seg->end >> 20)) + continue; + if ((tmp->end >> 20) < (seg->start_addr >> 20)) + continue; + if (seg == tmp) + continue; + return 1; + } + return 0; +} -/* use to issue "extended" dcss query */ +/* + * check if segment exceeds the kernel mapping range (detected or set via mem=) + * returns 1 if this is the case, 0 if segment fits into the range + */ static inline int -dcss_diag_query(char *name, int *rwattr, int *shattr, unsigned long *segstart, unsigned long *segend) +segment_exceeds_range (struct dcss_segment *seg) { - int i,j,rc; - unsigned long rx, ry; - - typedef struct segentry { - char thisseg[8]; - } segentry; - - struct qout64 { - int segstart; - int segend; - int segcnt; - int segrcnt; - segentry segout[6]; - }; - - struct qin64 { - char qopcode; - char rsrv1[3]; - char qrcode; - char rsrv2[3]; - char qname[8]; - unsigned int qoutptr; - short int qoutlen; - }; - - - struct qin64 *qinarea; - struct qout64 *qoutarea; - - qinarea = (struct qin64*) get_zeroed_page (GFP_DMA); - if (!qinarea) { - rc =-ENOMEM; - goto out; - } - qoutarea = (struct qout64*) get_zeroed_page (GFP_DMA); - if (!qoutarea) { - rc = -ENOMEM; - free_page ((unsigned long) qinarea); - goto out; - } - memset (qinarea,0,PAGE_SIZE); - memset (qoutarea,0,PAGE_SIZE); - - qinarea->qopcode = DCSS_QACTV; /* do a query for active - segments */ - qinarea->qoutptr = (unsigned long) qoutarea; - qinarea->qoutlen = sizeof(struct qout64); - - /* Move segment name into double word aligned - field and pad with blanks to 8 long. - */ - - for (i = j = 0 ; i < 8; i++) { - qinarea->qname[i] = (name[j] == '\0') ? ' ' : name[j++]; - } - - /* name already in EBCDIC */ - /* ASCEBC ((void *)&qinarea.qname, 8); */ - - /* set the assembler variables */ - rx = (unsigned long) qinarea; - ry = DCSS_SEGEXT; /* this is extended function */ - - /* issue diagnose x'64' */ - __asm__ __volatile__( -#ifdef CONFIG_ARCH_S390X - " sam31\n" // switch to 31 bit - " diag %0,%1,0x64\n" - " sam64\n" // switch back to 64 bit -#else - " diag %0,%1,0x64\n" -#endif - " ipm %2\n" - " srl %2,28\n" - : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" ); - - /* parse the query output area */ - *segstart=qoutarea->segstart; - *segend=qoutarea->segend; - - if (rc > 1) - { - *rwattr = 2; - *shattr = 2; - rc = 0; - goto free; - } - - if (qoutarea->segcnt > 6) - { - *rwattr = 3; - *shattr = 3; - rc = 0; - goto free; - } - - *rwattr = 1; - *shattr = 1; - - for (i=0; i < qoutarea->segrcnt; i++) { - if (qoutarea->segout[i].thisseg[3] == 2 || - qoutarea->segout[i].thisseg[3] == 3 || - qoutarea->segout[i].thisseg[3] == 6 ) - *rwattr = 0; - if (qoutarea->segout[i].thisseg[3] == 1 || - qoutarea->segout[i].thisseg[3] == 3 || - qoutarea->segout[i].thisseg[3] == 5 ) - *shattr = 0; - } /* end of for statement */ - rc = 0; - free: - free_page ((unsigned long) qoutarea); - free_page ((unsigned long) qinarea); + int seg_last_pfn = (seg->end) >> PAGE_SHIFT; + if (seg_last_pfn > max_pfn) + return 1; + return 0; +} + +/* + * get info about a segment + * possible return values: + * -ENOSYS : we are not running on VM + * -EIO : could not perform query diagnose + * -ENOENT : no such segment + * -ENOTSUPP: multi-part segment cannot be used with linux + * -ENOSPC : segment cannot be used (overlaps with storage) + * -ENOMEM : out of memory + * 0 .. 6 : type of segment as defined in include/asm-s390/extmem.h + */ +int +segment_type (char* name) +{ + int rc; + struct dcss_segment seg; + + if (!MACHINE_IS_VM) + return -ENOSYS; + + dcss_mkname(name, seg.dcss_name); + rc = query_segment_type (&seg); + if (rc < 0) + return rc; + return seg.vm_segtype; +} + +/* + * real segment loading function, called from segment_load + */ +static int +__segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end) +{ + struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), + GFP_DMA); + int dcss_command, rc, diag_cc; + + if (seg == NULL) { + rc = -ENOMEM; + goto out; + } + dcss_mkname (name, seg->dcss_name); + rc = query_segment_type (seg); + if (rc < 0) + goto out_free; + if (segment_exceeds_range(seg)) { + PRINT_WARN ("segment_load: not loading segment %s - exceeds" + " kernel mapping range\n",name); + rc = -ERANGE; + goto out_free; + } + if (segment_overlaps_storage(seg)) { + PRINT_WARN ("segment_load: not loading segment %s - overlaps" + " storage\n",name); + rc = -ENOSPC; + goto out_free; + } + if (segment_overlaps_others(seg)) { + PRINT_WARN ("segment_load: not loading segment %s - overlaps" + " other segments\n",name); + rc = -EBUSY; + goto out_free; + } + if (do_nonshared) + dcss_command = DCSS_LOADNSR; + else + dcss_command = DCSS_LOADNOLY; + + diag_cc = dcss_diag(dcss_command, seg->dcss_name, + &seg->start_addr, &seg->end); + if (diag_cc > 1) { + PRINT_WARN ("segment_load: could not load segment %s - " + "diag returned error (%ld)\n",name,seg->end); + rc = dcss_diag_translate_rc (seg->end); + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &seg->start_addr, &seg->end); + goto out_free; + } + seg->do_nonshared = do_nonshared; + atomic_set(&seg->ref_count, 1); + list_add(&seg->list, &dcss_list); + rc = seg->vm_segtype; + *addr = seg->start_addr; + *end = seg->end; + if (do_nonshared) + PRINT_INFO ("segment_load: loaded segment %s range %p .. %p " + "type %s in non-shared mode\n", name, + (void*)seg->start_addr, (void*)seg->end, + segtype_string[seg->vm_segtype]); + else + PRINT_INFO ("segment_load: loaded segment %s range %p .. %p " + "type %s in shared mode\n", name, + (void*)seg->start_addr, (void*)seg->end, + segtype_string[seg->vm_segtype]); + goto out; + out_free: + kfree (seg); out: - return rc; + return rc; } /* - * Load a DCSS segment via the diag 0x64. + * this function loads a DCSS segment + * name : name of the DCSS + * do_nonshared : 0 indicates that the dcss should be shared with other linux images + * 1 indicates that the dcss should be exclusive for this linux image + * addr : will be filled with start address of the segment + * end : will be filled with end address of the segment + * return values: + * -ENOSYS : we are not running on VM + * -EIO : could not perform query or load diagnose + * -ENOENT : no such segment + * -ENOTSUPP: multi-part segment cannot be used with linux + * -ENOSPC : segment cannot be used (overlaps with storage) + * -EBUSY : segment can temporarily not be used (overlaps with dcss) + * -ERANGE : segment cannot be used (exceeds kernel mapping range) + * -EPERM : segment is currently loaded with incompatible permissions + * -ENOMEM : out of memory + * 0 .. 6 : type of segment as defined in include/asm-s390/extmem.h */ -int segment_load(char *name, int segtype, unsigned long *addr, - unsigned long *end) +int +segment_load (char *name, int do_nonshared, unsigned long *addr, + unsigned long *end) { - char dcss_name[8]; - struct list_head *l; - struct dcss_segment *seg, *tmp; - unsigned long dummy; - unsigned long segstart, segend; - int rc = 0,i; - int rwattr, shattr; - - if (!MACHINE_IS_VM) - return -ENOSYS; - dcss_mkname(name, dcss_name); - /* search for the dcss in list of currently loaded segments */ - spin_lock(&dcss_lock); - seg = NULL; - list_for_each(l, &dcss_list) { - tmp = list_entry(l, struct dcss_segment, list); - if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) { - seg = tmp; - break; - } - } - - if (seg == NULL) { - /* find out the attributes of this - shared segment */ - dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend); - /* does segment collide with main memory? */ - for (i=0; i < MEMORY_CHUNKS; i++) { - if (memory_chunk[i].type != 0) - continue; - if (memory_chunk[i].addr > segend) - continue; - if (memory_chunk[i].addr + memory_chunk[i].size <= segstart) - continue; - spin_unlock(&dcss_lock); - return -ENOENT; - } - /* or does it collide with other (loaded) segments? */ - list_for_each(l, &dcss_list) { - tmp = list_entry(l, struct dcss_segment, list); - if ((segstart <= tmp->end && segstart >= tmp->start_addr) || - (segend <= tmp->end && segend >= tmp->start_addr) || - (segstart <= tmp->start_addr && segend >= tmp->end)) { - PRINT_ERR("Segment Overlap!\n"); - spin_unlock(&dcss_lock); - return -ENOENT; - } - } - - /* do case statement on segtype */ - /* if asking for shared ro, - shared rw works */ - /* if asking for exclusive ro, - exclusive rw works */ - - switch(segtype) { - case SEGMENT_SHARED_RO: - if (shattr > 1 || rwattr > 1) { - spin_unlock(&dcss_lock); - return -ENOENT; - } else { - if (shattr == 0 && rwattr == 0) - rc = SEGMENT_EXCLUSIVE_RO; - if (shattr == 0 && rwattr == 1) - rc = SEGMENT_EXCLUSIVE_RW; - if (shattr == 1 && rwattr == 0) - rc = SEGMENT_SHARED_RO; - if (shattr == 1 && rwattr == 1) - rc = SEGMENT_SHARED_RW; - } - break; - case SEGMENT_SHARED_RW: - if (shattr > 1 || rwattr != 1) { - spin_unlock(&dcss_lock); - return -ENOENT; - } else { - if (shattr == 0) - rc = SEGMENT_EXCLUSIVE_RW; - if (shattr == 1) - rc = SEGMENT_SHARED_RW; - } - break; - - case SEGMENT_EXCLUSIVE_RO: - if (shattr > 0 || rwattr > 1) { - spin_unlock(&dcss_lock); - return -ENOENT; - } else { - if (rwattr == 0) - rc = SEGMENT_EXCLUSIVE_RO; - if (rwattr == 1) - rc = SEGMENT_EXCLUSIVE_RW; - } - break; - - case SEGMENT_EXCLUSIVE_RW: -/* if (shattr != 0 || rwattr != 1) { - spin_unlock(&dcss_lock); - return -ENOENT; - } else { -*/ - rc = SEGMENT_EXCLUSIVE_RW; -// } - break; - - default: - spin_unlock(&dcss_lock); - return -ENOENT; - } /* end switch */ - - seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA); - if (seg != NULL) { - memcpy(seg->dcss_name, dcss_name, 8); - if (rc == SEGMENT_EXCLUSIVE_RW) { - if (dcss_diag(DCSS_LOADNSR, seg->dcss_name, - &seg->start_addr, &seg->end) == 0) { - if (seg->end < max_low_pfn*PAGE_SIZE ) { - atomic_set(&seg->ref_count, 1); - list_add(&seg->list, &dcss_list); - *addr = seg->start_addr; - *end = seg->end; - seg->dcss_attr = rc; - if (shattr == 1 && rwattr == 1) - seg->shared_attr = SEGMENT_SHARED_RW; - else if (shattr == 1 && rwattr == 0) - seg->shared_attr = SEGMENT_SHARED_RO; - else - seg->shared_attr = SEGMENT_EXCLUSIVE_RW; - } else { - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - kfree (seg); - rc = -ENOENT; - } - } else { - kfree(seg); - rc = -ENOENT; - } - goto out; - } - if (dcss_diag(DCSS_LOADNOLY, seg->dcss_name, - &seg->start_addr, &seg->end) == 0) { - if (seg->end < max_low_pfn*PAGE_SIZE ) { - atomic_set(&seg->ref_count, 1); - list_add(&seg->list, &dcss_list); - *addr = seg->start_addr; - *end = seg->end; - seg->dcss_attr = rc; - seg->shared_attr = rc; - } else { - dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - kfree (seg); - rc = -ENOENT; - } - } else { - kfree(seg); - rc = -ENOENT; - } - } else rc = -ENOMEM; - } else { - /* found */ - if ((segtype == SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr != SEGMENT_EXCLUSIVE_RW)) { - PRINT_ERR("Segment already loaded in other mode than EXCLUSIVE_RW!\n"); - rc = -EPERM; - goto out; - /* reload segment in exclusive mode */ -/* dcss_diag(DCSS_LOADNSR, seg->dcss_name, - &seg->start_addr, &seg->end); - seg->dcss_attr = SEGMENT_EXCLUSIVE_RW;*/ + struct dcss_segment *seg; + int rc; + + if (!MACHINE_IS_VM) + return -ENOSYS; + + spin_lock (&dcss_lock); + seg = segment_by_name (name); + if (seg == NULL) + rc = __segment_load (name, do_nonshared, addr, end); + else { + if (do_nonshared == seg->do_nonshared) { + atomic_inc(&seg->ref_count); + *addr = seg->start_addr; + *end = seg->end; + rc = seg->vm_segtype; + } else { + *addr = *end = 0; + rc = -EPERM; } - if ((segtype != SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr == SEGMENT_EXCLUSIVE_RW)) { - PRINT_ERR("Segment already loaded in EXCLUSIVE_RW mode!\n"); - rc = -EPERM; - goto out; - } - atomic_inc(&seg->ref_count); - *addr = seg->start_addr; - *end = seg->end; - rc = seg->dcss_attr; - } -out: - spin_unlock(&dcss_lock); - return rc; + } + spin_unlock (&dcss_lock); + return rc; +} + +/* + * this function modifies the shared state of a DCSS segment. note that + * name : name of the DCSS + * do_nonshared : 0 indicates that the dcss should be shared with other linux images + * 1 indicates that the dcss should be exclusive for this linux image + * return values: + * -EIO : could not perform load diagnose (segment gone!) + * -ENOENT : no such segment (segment gone!) + * -EAGAIN : segment is in use by other exploiters, try later + * -EINVAL : no segment with the given name is currently loaded - name invalid + * 0 : operation succeeded + */ +int +segment_modify_shared (char *name, int do_nonshared) +{ + struct dcss_segment *seg; + unsigned long dummy; + int dcss_command, rc, diag_cc; + + spin_lock (&dcss_lock); + seg = segment_by_name (name); + if (seg == NULL) { + rc = -EINVAL; + goto out_unlock; + } + if (do_nonshared == seg->do_nonshared) { + PRINT_INFO ("segment_modify_shared: not reloading segment %s" + " - already in requested mode\n",name); + rc = 0; + goto out_unlock; + } + if (atomic_read (&seg->ref_count) != 1) { + PRINT_WARN ("segment_modify_shared: not reloading segment %s - " + "segment is in use by other driver(s)\n",name); + rc = -EAGAIN; + goto out_unlock; + } + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); + if (do_nonshared) + dcss_command = DCSS_LOADNSR; + else + dcss_command = DCSS_LOADNOLY; + diag_cc = dcss_diag(dcss_command, seg->dcss_name, + &seg->start_addr, &seg->end); + if (diag_cc > 1) { + PRINT_WARN ("segment_modify_shared: could not reload segment %s" + " - diag returned error (%ld)\n",name,seg->end); + rc = dcss_diag_translate_rc (seg->end); + goto out_del; + } + seg->do_nonshared = do_nonshared; + rc = 0; + goto out_unlock; + out_del: + list_del(&seg->list); + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); + kfree (seg); + out_unlock: + spin_unlock(&dcss_lock); + return rc; } /* @@ -422,84 +516,72 @@ out: * it from the address space if nobody is using it * any longer. */ -void segment_unload(char *name) +void +segment_unload(char *name) { - char dcss_name[8]; - unsigned long dummy; - struct list_head *l,*l_tmp; - struct dcss_segment *seg; - - if (!MACHINE_IS_VM) - return; - dcss_mkname(name, dcss_name); - spin_lock(&dcss_lock); - list_for_each_safe(l, l_tmp, &dcss_list) { - seg = list_entry(l, struct dcss_segment, list); - if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { - if (atomic_dec_return(&seg->ref_count) == 0) { - /* Last user of the segment is - gone. */ - list_del(&seg->list); - dcss_diag(DCSS_PURGESEG, seg->dcss_name, - &dummy, &dummy); - kfree(seg); - } - break; - } - } - spin_unlock(&dcss_lock); + unsigned long dummy; + struct dcss_segment *seg; + + if (!MACHINE_IS_VM) + return; + + spin_lock(&dcss_lock); + seg = segment_by_name (name); + if (seg == NULL) { + PRINT_ERR ("could not find segment %s in segment_unload, " + "please report to linux390@de.ibm.com\n",name); + goto out_unlock; + } + if (atomic_dec_return(&seg->ref_count) == 0) { + list_del(&seg->list); + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); + kfree(seg); + } +out_unlock: + spin_unlock(&dcss_lock); } /* - * Replace an existing DCSS segment, so that machines - * that load it anew will see the new version. + * save segment content permanently */ -void segment_replace(char *name) +void segment_save(char *name) { - char dcss_name[8]; - struct list_head *l; - struct dcss_segment *seg; - int mybeg = 0; - int myend = 0; - char mybuff1[80]; - char mybuff2[80]; - - if (!MACHINE_IS_VM) - return; - dcss_mkname(name, dcss_name); - - memset (mybuff1, 0, sizeof(mybuff1)); - memset (mybuff2, 0, sizeof(mybuff2)); - - spin_lock(&dcss_lock); - list_for_each(l, &dcss_list) { - seg = list_entry(l, struct dcss_segment, list); - if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { - mybeg = seg->start_addr >> 12; - myend = (seg->end) >> 12; - if (seg->shared_attr == SEGMENT_EXCLUSIVE_RW) - sprintf(mybuff1, "DEFSEG %s %X-%X EW", - name, mybeg, myend); - if (seg->shared_attr == SEGMENT_EXCLUSIVE_RO) - sprintf(mybuff1, "DEFSEG %s %X-%X RO", - name, mybeg, myend); - if (seg->shared_attr == SEGMENT_SHARED_RW) - sprintf(mybuff1, "DEFSEG %s %X-%X SW", - name, mybeg, myend); - if (seg->shared_attr == SEGMENT_SHARED_RO) - sprintf(mybuff1, "DEFSEG %s %X-%X SR", - name, mybeg, myend); - spin_unlock(&dcss_lock); - sprintf(mybuff2, "SAVESEG %s", name); - cpcmd(mybuff1, NULL, 80); - cpcmd(mybuff2, NULL, 80); - break; - } - - } - if (myend == 0) spin_unlock(&dcss_lock); + struct dcss_segment *seg; + int startpfn = 0; + int endpfn = 0; + char cmd1[160]; + char cmd2[80]; + int i; + + if (!MACHINE_IS_VM) + return; + + spin_lock(&dcss_lock); + seg = segment_by_name (name); + + if (seg == NULL) { + PRINT_ERR ("could not find segment %s in segment_save, please report to linux390@de.ibm.com\n",name); + return; + } + + startpfn = seg->start_addr >> PAGE_SHIFT; + endpfn = (seg->end) >> PAGE_SHIFT; + sprintf(cmd1, "DEFSEG %s", name); + for (i=0; isegcnt; i++) { + sprintf(cmd1+strlen(cmd1), " %X-%X %s", + seg->range[i].start >> PAGE_SHIFT, + seg->range[i].end >> PAGE_SHIFT, + segtype_string[seg->range[i].start & 0xff]); + } + sprintf(cmd2, "SAVESEG %s", name); + cpcmd(cmd1, NULL, 80); + cpcmd(cmd2, NULL, 80); + spin_unlock(&dcss_lock); } EXPORT_SYMBOL(segment_load); EXPORT_SYMBOL(segment_unload); -EXPORT_SYMBOL(segment_replace); +EXPORT_SYMBOL(segment_save); +EXPORT_SYMBOL(segment_type); +EXPORT_SYMBOL(segment_modify_shared); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 8b2dda883..d6bd3d429 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -25,11 +25,11 @@ #include #include #include +#include #include #include #include -#include #ifndef CONFIG_ARCH_S390X #define __FAIL_ADDR_MASK 0x7ffff000 @@ -126,8 +126,8 @@ static inline int check_user_space(struct pt_regs *regs, int error_code) * Send SIGSEGV to task. This is an external routine * to keep the stack usage of do_page_fault small. */ -static void force_sigsegv(struct pt_regs *regs, unsigned long error_code, - int si_code, unsigned long address) +static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, + int si_code, unsigned long address) { struct siginfo si; @@ -282,7 +282,7 @@ bad_area: if (regs->psw.mask & PSW_MASK_PSTATE) { tsk->thread.prot_addr = address; tsk->thread.trap_no = error_code; - force_sigsegv(regs, error_code, si_code, address); + do_sigsegv(regs, error_code, si_code, address); return; } diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 1039196ef..ebe73afa7 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -37,7 +37,7 @@ static inline unsigned long mmap_base(void) { - unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; if (gap < MIN_GAP) gap = MIN_GAP; @@ -58,7 +58,7 @@ static inline int mmap_is_legacy(void) #endif return sysctl_legacy_va_layout || (current->personality & ADDR_COMPAT_LAYOUT) || - current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY; + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY; } /* diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ce61d06ca..d734b2ad2 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -51,6 +51,12 @@ config SH_7300_SOLUTION_ENGINE Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V) evalutation board. +config SH_73180_SOLUTION_ENGINE + bool "SolutionEngine73180" + help + Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3) + evalutation board. + config SH_7751_SYSTEMH bool "SystemH7751R" help @@ -137,6 +143,16 @@ config SH_ADX config SH_MPC1211 bool "MPC1211" +config SH_SH03 + bool "SH03" + help + CTP/PCI-SH03 is a CPU module computer that produced + by Interface Corporation. + It is compact and excellent in durability. + It will play an active part in your factory or laboratory + as a FA computer. + More information at + config SH_SECUREEDGE5410 bool "SecureEdge5410" help @@ -156,6 +172,15 @@ config SH_RTS7751R2D Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. +config SH_EDOSK7705 + bool "EDOSK7705" + +config SH_SH4202_MICRODEV + bool "SH4-202 MicroDev" + help + Select SH4-202 MicroDev if configuring for a SuperH MicroDev board + with an SH4-202 CPU. + config SH_UNKNOWN bool "BareCPU" help @@ -194,7 +219,7 @@ endchoice choice prompt "Processor subtype" - + config CPU_SUBTYPE_SH7604 bool "SH7604" depends on CPU_SH2 @@ -245,6 +270,10 @@ config CPU_SUBTYPE_SH7760 bool "SH7760" depends on CPU_SH4 +config CPU_SUBTYPE_SH73180 + bool "SH73180" + depends on CPU_SH4 + config CPU_SUBTYPE_ST40STB1 bool "ST40STB1 / ST40RA" depends on CPU_SH4 @@ -258,8 +287,17 @@ config CPU_SUBTYPE_ST40GX1 help Select ST40GX1 if you have a ST40GX1 CPU. +config CPU_SUBTYPE_SH4_202 + bool "SH4-202" + depends on CPU_SH4 + endchoice +config SH7705_CACHE_32KB + bool "Enable 32KB cache size for SH7705" + depends on CPU_SUBTYPE_SH7705 + default y + config MMU bool "Support for memory management hardware" depends on !CPU_SH2 @@ -296,12 +334,12 @@ config CMDLINE # Platform-specific memory start and size definitions config MEMORY_START hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SECUREEDGE5410 - default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D) + default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV + default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705) ---help--- Computers built with Hitachi SuperH processors always map the ROM starting at address zero. But the processor - does not specify the range that RAM takes. + does not specify the range that RAM takes. The physical memory (RAM) start address will be automatically set to 08000000, unless you selected one of the following @@ -315,10 +353,10 @@ config MEMORY_START config MEMORY_SIZE hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) - default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 - default "0x04000000" if !MEMORY_OVERRIDE && (SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D) - default "0x02000000" if !MEMORY_OVERRIDE && SH_SOLUTION_ENGINE - default "0x08000000" if SH_MPC1211 + default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705 + default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) + default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV) + default "0x08000000" if SH_MPC1211 || SH_SH03 help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command @@ -328,7 +366,7 @@ config MEMORY_SIZE config MEMORY_SET bool - depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D) + depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705) default y help This is an option about which you will never be asked a question. @@ -339,11 +377,11 @@ config MEMORY_SET # If none of the above have set memory start/size, ask the user. config MEMORY_OVERRIDE bool "Override default load address and memory size" - + # XXX: break these out into the board-specific configs below config CF_ENABLER bool "Compact Flash Enabler support" - depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 + depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03 ---help--- Compact Flash is a small, removable mass storage device introduced in 1994 originally as a PCMCIA device. If you say `Y' here, you @@ -387,7 +425,7 @@ config CF_BASE_ADDR # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool - depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE + depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE default y help Selecting this option will allow the Linux kernel to emulate @@ -395,6 +433,16 @@ config SH_RTC If unsure, say N. +config SH_FPU + bool "FPU support" + depends on !CPU_SH3 + default y + help + Selecting this option will enable support for SH processors that + have FPU units (ie, SH77xx). + + This option must be set in order to enable the FPU. + config SH_DSP bool "DSP support" depends on !CPU_SH4 @@ -438,8 +486,8 @@ config DISCONTIGMEM config ZERO_PAGE_OFFSET hex "Zero page offset" - default "0x00001000" if !SH_MPC1211 - default "0x00004000" if SH_MPC1211 + default "0x00001000" if !(SH_MPC1211 || SH_SH03) + default "0x00004000" if SH_MPC1211 || SH_SH03 help This sets the default offset of zero page. @@ -522,7 +570,7 @@ config SH_STORE_QUEUES help Selecting this option will enable an in-kernel API for manipulating the store queues integrated in the SH-4 processors. - + config SMP bool "Symmetric multi-processing support" ---help--- @@ -572,7 +620,7 @@ config RTS7751R2D_REV11 config SH_PCLK_CALC bool - default n if CPU_SUBTYPE_SH7300 + default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180 default y help This option will cause the PCLK value to be probed at run-time. It @@ -581,9 +629,11 @@ config SH_PCLK_CALC config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" - default "49876504" if CPU_SUBTYPE_SH7750 - default "60013568" if CPU_SUBTYPE_SH7751 + default "50000000" if CPU_SUBTYPE_SH7750 + default "60000000" if CPU_SUBTYPE_SH7751 default "33333333" if CPU_SUBTYPE_SH7300 + default "27000000" if CPU_SUBTYPE_SH73180 + default "66000000" if CPU_SUBTYPE_SH4_202 default "1193182" help This option is used to specify the peripheral clock frequency. This @@ -595,16 +645,6 @@ config SH_PCLK_FREQ menu "CPU Frequency scaling" -config CPU_FREQ - bool "CPU Frequency scaling" - help - CPU clock scaling allows you to change the clock speed of the - running CPU on the fly. - - For details, take a look at . - - If unsure, say N. - source "drivers/cpufreq/Kconfig" config CPU_FREQ_TABLE @@ -636,7 +676,7 @@ source "arch/sh/cchips/Kconfig" config HEARTBEAT bool "Heartbeat LED" - depends on SH_MPC1211 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D + depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV help Use the power-on LED on your machine as a load meter. The exact behavior is platform-dependent, but normally the flash frequency is @@ -662,7 +702,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" # PCMCIA outright. -- PFM. config ISA bool - default y if PCMCIA + default y if PCMCIA || SMC91X help 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 @@ -730,7 +770,7 @@ config EMBEDDED_RAMDISK_IMAGE default "ramdisk.gz" help This is the filename of the ramdisk image to be built into the - kernel. Relative pathnames are relative to arch/mips/ramdisk/. + kernel. Relative pathnames are relative to arch/sh/ramdisk/. The ramdisk image is not part of the kernel distribution; you must provide one yourself. @@ -742,161 +782,10 @@ source "fs/Kconfig" source "arch/sh/oprofile/Kconfig" -menu "Kernel hacking" - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - help - 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. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config SH_STANDARD_BIOS - bool "Use LinuxSH standard BIOS" - help - 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. - -config EARLY_SCIF_CONSOLE - bool "Use early SCIF console" - depends on CPU_SH4 - -config EARLY_PRINTK - bool "Early printk support" - depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE - help - Say Y here to redirect kernel printk 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. If unsure, say N. - -config KGDB - bool "Include KGDB kernel debugger" - help - Include in-kernel hooks for kgdb, the Linux kernel source level - debugger. See for more information. - Unless you are intending to debug the kernel, say N here. - -menu "KGDB configuration options" - depends on KGDB - -config MORE_COMPILE_OPTIONS - bool "Add any additional compile options" - help - If you want to add additional CFLAGS to the kernel build, enable this - option and then enter what you would like to add in the next question. - Note however that -g is already appended with the selection of KGDB. - -config COMPILE_OPTIONS - string "Additional compile arguments" - depends on MORE_COMPILE_OPTIONS - -config KGDB_NMI - bool "Enter KGDB on NMI" - default n - -config KGDB_THREAD - bool "Include KGDB thread support" - default y - -config SH_KGDB_CONSOLE - bool "Console messages through GDB" - default n - -config KGDB_SYSRQ - bool "Allow SysRq 'G' to enter KGDB" - default y - -config KGDB_KERNEL_ASSERTS - bool "Include KGDB kernel assertions" - default n - -comment "Serial port setup" - -config KGDB_DEFPORT - int "Port number (ttySCn)" - default "1" - -config KGDB_DEFBAUD - int "Baud rate" - default "115200" - -choice - prompt "Parity" - depends on KGDB - default KGDB_DEFPARITY_N - -config KGDB_DEFPARITY_N - bool "None" - -config KGDB_DEFPARITY_E - bool "Even" - -config KGDB_DEFPARITY_O - bool "Odd" - -endchoice - -choice - prompt "Data bits" - depends on KGDB - default KGDB_DEFBITS_8 - -config KGDB_DEFBITS_8 - bool "8" - -config KGDB_DEFBITS_7 - bool "7" - -endchoice - -endmenu - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - default y if KGDB - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -endmenu +source "arch/sh/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 7e0087146..0c520643a 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -14,24 +14,13 @@ # this architecture # -# -# We don't necessarily agree with the top-level Makefile with regards to what -# does and does not qualify as a noconfig_targets rule. In this case, we're -# still dependant on .config settings in order for core-y (machdir-y in -# particular) to resolve the proper directory. So we just manually include it -# if it hasn't been already.. -# -ifndef include_config --include .config -endif - cflags-y := -mb cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml cflags-$(CONFIG_CPU_SH2) += -m2 cflags-$(CONFIG_CPU_SH3) += -m3 cflags-$(CONFIG_CPU_SH4) += -m4 \ - $(call check_gcc,-mno-implicit-fp,-m4-nofpu) + $(call cc-option,-mno-implicit-fp,-m4-nofpu) cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -76,6 +65,7 @@ core-$(CONFIG_EMBEDDED_RAMDISK) += arch/sh/ramdisk/ machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751 machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300 +machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180 machdir-$(CONFIG_SH_STB1_HARP) := harp machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 @@ -91,10 +81,13 @@ machdir-$(CONFIG_SH_BIGSUR) := bigsur machdir-$(CONFIG_SH_SH2000) := sh2000 machdir-$(CONFIG_SH_ADX) := adx machdir-$(CONFIG_SH_MPC1211) := mpc1211 +machdir-$(CONFIG_SH_SH03) := sh03 machdir-$(CONFIG_SH_SECUREEDGE5410) := snapgear machdir-$(CONFIG_SH_HS7751RVOIP) := renesas/hs7751rvoip machdir-$(CONFIG_SH_RTS7751R2D) := renesas/rts7751r2d machdir-$(CONFIG_SH_7751_SYSTEMH) := renesas/systemh +machdir-$(CONFIG_SH_EDOSK7705) := renesas/edosk7705 +machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev machdir-$(CONFIG_SH_UNKNOWN) := unknown incdir-y := $(notdir $(machdir-y)) @@ -102,9 +95,12 @@ incdir-y := $(notdir $(machdir-y)) incdir-$(CONFIG_SH_SOLUTION_ENGINE) := se incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se7751 incdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se7300 +incdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se73180 incdir-$(CONFIG_SH_HP600) := hp6xx +ifneq ($(machdir-y),) core-y += arch/sh/boards/$(machdir-y)/ +endif # Companion chips core-$(CONFIG_HD64461) += arch/sh/cchips/hd6446x/hd64461/ @@ -122,25 +118,41 @@ drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ boot := arch/sh/boot -AFLAGS_vmlinux.lds.o := -traditional +CPPFLAGS_vmlinux.lds := -traditional -prepare: target_links +# Update machine arch and proc symlinks if something which affects +# them changed. We use .arch and .mach to indicate when they were +# updated last, otherwise make uses the target directory mtime. -.PHONY: target_links FORCE +include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER + @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)' +ifneq ($(KBUILD_SRC),) + $(Q)mkdir -p include/asm-sh + $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu +else + $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu +endif + @touch $@ -all: zImage +include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER + @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)' +ifneq ($(KBUILD_SRC),) + $(Q)mkdir -p include/asm-sh + $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach +else + $(Q)ln -fsn $(incdir-y) include/asm-sh/mach +endif + @touch $@ -target_links: - @echo ' Making asm-sh/cpu -> asm-sh/$(cpuincdir-y) link' - @rm -f include/asm-sh/cpu - @ln -sf $(cpuincdir-y) include/asm-sh/cpu - @echo ' Making asm-sh/mach -> asm-sh/$(incdir-y) link' - @rm -f include/asm-sh/mach - @ln -sf $(incdir-y) include/asm-sh/mach +prepare: maketools include/asm-sh/.cpu include/asm-sh/.mach +.PHONY: maketools FORCE +maketools: include/asm-sh/asm-offsets.h include/linux/version.h FORCE $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h +all: zImage + zImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ @@ -149,6 +161,15 @@ compressed: zImage archclean: $(Q)$(MAKE) $(clean)=$(boot) +CLEAN_FILES += include/asm-sh/machtypes.h include/asm-sh/asm-offsets.h + +arch/sh/kernel/asm-offsets.s: include/asm include/linux/version.h \ + include/asm-sh/.cpu include/asm-sh/.mach + +include/asm-sh/asm-offsets.h: arch/sh/kernel/asm-offsets.s + $(call filechk,gen-asm-offsets) + + define archhelp @echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)' endef diff --git a/arch/sh/boards/bigsur/irq.c b/arch/sh/boards/bigsur/irq.c index 082472448..c188fc32d 100644 --- a/arch/sh/boards/bigsur/irq.c +++ b/arch/sh/boards/bigsur/irq.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/arch/sh/boards/bigsur/setup.c b/arch/sh/boards/bigsur/setup.c index 9cb329269..e69be0519 100644 --- a/arch/sh/boards/bigsur/setup.c +++ b/arch/sh/boards/bigsur/setup.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/sh/boards/dreamcast/setup.c b/arch/sh/boards/dreamcast/setup.c index c59d1599b..55dece35c 100644 --- a/arch/sh/boards/dreamcast/setup.c +++ b/arch/sh/boards/dreamcast/setup.c @@ -1,15 +1,15 @@ -/* +/* * arch/sh/boards/dreamcast/setup.c * * Hardware support for the Sega Dreamcast. * * Copyright (c) 2001, 2002 M. R. Brown - * Copyright (c) 2002, 2003 Paul Mundt + * Copyright (c) 2002, 2003, 2004 Paul Mundt * * This file is part of the LinuxDC project (www.linuxdc.org) * * Released under the terms of the GNU GPL v2.0. - * + * * This file originally bore the message (with enclosed-$): * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp * SEGA Dreamcast support @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,10 @@ extern void (*board_time_init)(void); extern void aica_time_init(void); extern int gapspci_init(void); extern int systemasic_irq_demux(int); + +void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int); +int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t); + const char *get_system_type(void) { return "Sega Dreamcast"; @@ -43,6 +48,11 @@ struct sh_machine_vector mv_dreamcast __initmv = { .mv_nr_irqs = NR_IRQS, .mv_irq_demux = systemasic_irq_demux, + +#ifdef CONFIG_PCI + .mv_consistent_alloc = dreamcast_consistent_alloc, + .mv_consistent_free = dreamcast_consistent_free, +#endif }; ALIAS_MV(dreamcast) diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c index 0d64b28b0..05b01b8f4 100644 --- a/arch/sh/boards/harp/setup.c +++ b/arch/sh/boards/harp/setup.c @@ -54,3 +54,38 @@ int __init platform_setup(void) return 0; } + +/* + * pcibios_map_platform_irq + * + * This is board specific and returns the IRQ for a given PCI device. + * It is used by the PCI code (arch/sh/kernel/st40_pci*) + * + */ + +#define HARP_PCI_IRQ 1 +#define HARP_BRIDGE_IRQ 2 +#define OVERDRIVE_SLOT0_IRQ 0 + + +int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + switch (slot) { +#ifdef CONFIG_SH_STB1_HARP + case 2: /*This is the PCI slot on the */ + return HARP_PCI_IRQ; + case 1: /* this is the bridge */ + return HARP_BRIDGE_IRQ; +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + case 1: + case 2: + case 3: + return slot - 1; +#else +#error Unknown board +#endif + default: + return -1; + } +} + diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c index c9bbd72b4..ba3a65439 100644 --- a/arch/sh/boards/mpc1211/pci.c +++ b/arch/sh/boards/mpc1211/pci.c @@ -176,14 +176,7 @@ static void __devinit quirk_ali_ide_ports(struct pci_dev *dev) dev->resource[4].end = 0xf00f; dev->resource[4].flags = IORESOURCE_IO; } - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, - PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports }, - { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports); char * __devinit pcibios_setup(char *str) { diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c index 54020ebbb..276fa11ee 100644 --- a/arch/sh/boards/overdrive/galileo.c +++ b/arch/sh/boards/overdrive/galileo.c @@ -455,13 +455,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } } - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); void __init pcibios_init(void) { diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c index 275ea1a7e..1c9bfeda0 100644 --- a/arch/sh/boards/overdrive/pcidma.c +++ b/arch/sh/boards/overdrive/pcidma.c @@ -25,7 +25,7 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, printk("BUG: pci_alloc_consistent() called - not yet supported\n"); /* We ALWAYS need DMA memory on the overdrive hardware, - * due to it's extreme wierdness + * due to it's extreme weirdness * Need to flush the cache here as well, since the memory * can still be seen through the cache! */ diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c index c1ff45407..1efc18e78 100644 --- a/arch/sh/boards/renesas/rts7751r2d/mach.c +++ b/arch/sh/boards/renesas/rts7751r2d/mach.c @@ -24,7 +24,7 @@ extern void *rts7751r2d_ioremap(unsigned long, unsigned long); extern int rts7751r2d_irq_demux(int irq); extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int); -extern void voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t); +extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t); /* * The Machine Vector @@ -62,7 +62,9 @@ struct sh_machine_vector mv_rts7751r2d __initmv = { #endif .mv_irq_demux = rts7751r2d_irq_demux, +#ifdef CONFIG_USB_OHCI_HCD .mv_consistent_alloc = voyagergx_consistent_alloc, .mv_consistent_free = voyagergx_consistent_free, +#endif }; ALIAS_MV(rts7751r2d) diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c index dff4fbd86..210897b31 100644 --- a/arch/sh/boards/se/770x/irq.c +++ b/arch/sh/boards/se/770x/irq.c @@ -1,5 +1,4 @@ -/* $Id: irq.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $ - * +/* * linux/arch/sh/boards/se/770x/irq.c * * Copyright (C) 2000 Kazumoto Kojima @@ -12,6 +11,7 @@ #include #include #include +#include #include /* @@ -30,6 +30,32 @@ void __init init_se_IRQ(void) * 12: mouse * 14: ide0 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7705) + /* Disable all interrupts */ + ctrl_outw(0, BCR_ILCRA); + ctrl_outw(0, BCR_ILCRB); + ctrl_outw(0, BCR_ILCRC); + ctrl_outw(0, BCR_ILCRD); + ctrl_outw(0, BCR_ILCRE); + ctrl_outw(0, BCR_ILCRF); + ctrl_outw(0, BCR_ILCRG); + /* This is default value */ + make_ipr_irq(0xf-0x2, BCR_ILCRA, 2, 0x2); + make_ipr_irq(0xf-0xa, BCR_ILCRA, 1, 0xa); + make_ipr_irq(0xf-0x5, BCR_ILCRB, 0, 0x5); + make_ipr_irq(0xf-0x8, BCR_ILCRC, 1, 0x8); + make_ipr_irq(0xf-0xc, BCR_ILCRC, 0, 0xc); + make_ipr_irq(0xf-0xe, BCR_ILCRD, 3, 0xe); + make_ipr_irq(0xf-0x3, BCR_ILCRD, 1, 0x3); /* LAN */ + make_ipr_irq(0xf-0xd, BCR_ILCRE, 2, 0xd); + make_ipr_irq(0xf-0x9, BCR_ILCRE, 1, 0x9); + make_ipr_irq(0xf-0x1, BCR_ILCRE, 0, 0x1); + make_ipr_irq(0xf-0xf, BCR_ILCRF, 3, 0xf); + make_ipr_irq(0xf-0xb, BCR_ILCRF, 1, 0xb); + make_ipr_irq(0xf-0x7, BCR_ILCRG, 3, 0x7); + make_ipr_irq(0xf-0x6, BCR_ILCRG, 2, 0x6); + make_ipr_irq(0xf-0x4, BCR_ILCRG, 1, 0x4); +#else make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); @@ -50,4 +76,5 @@ void __init init_se_IRQ(void) /* NOTE: #2 and #13 are not used on PC */ make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ +#endif } diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c index aa5dde2f5..f9b4c56cc 100644 --- a/arch/sh/boards/se/770x/mach.c +++ b/arch/sh/boards/se/770x/mach.c @@ -33,6 +33,8 @@ struct sh_machine_vector mv_se __initmv = { .mv_nr_irqs = 32, #elif defined(CONFIG_CPU_SUBTYPE_SH7709) .mv_nr_irqs = 61, +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) + .mv_nr_irqs = 86, #endif .mv_inb = se_inb, diff --git a/arch/sh/boards/se/7751/io.c b/arch/sh/boards/se/7751/io.c index 224a5e37d..99041b269 100644 --- a/arch/sh/boards/se/7751/io.c +++ b/arch/sh/boards/se/7751/io.c @@ -18,7 +18,7 @@ #include #include -#include +#include "../../../drivers/pci/pci-sh7751.h" #if 0 /****************************************************************** diff --git a/arch/sh/boards/se/7751/pci.c b/arch/sh/boards/se/7751/pci.c index 2f8682ebc..1f273efd2 100644 --- a/arch/sh/boards/se/7751/pci.c +++ b/arch/sh/boards/se/7751/pci.c @@ -19,7 +19,7 @@ #include #include -#include +#include "../../../drivers/pci/pci-sh7751.h" #define PCIMCR_MRSET_OFF 0xBFFFFFFF #define PCIMCR_RFSH_OFF 0xFFFFFFFB diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 05ca14dfa..75a6876bf 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -22,7 +22,7 @@ CONFIG_MEMORY_START ?= 0x0c000000 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000 IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)]) -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds.s +LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE $(call if_changed,ld) diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c index 95a309d14..921d12b42 100644 --- a/arch/sh/cchips/voyagergx/consistent.c +++ b/arch/sh/cchips/voyagergx/consistent.c @@ -49,13 +49,13 @@ void *voyagergx_consistent_alloc(struct device *dev, size_t size, if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || (dev->bus == &sh_bus_types[SH_BUS_VIRT] && shdev->dev_id != SH_DEV_ID_USB_OHCI)) - return consistent_alloc(flag, size, handle); + return NULL; start = OHCI_SRAM_START + OHCI_HCCA_SIZE; entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC); if (!entry) - return NULL; + return ERR_PTR(-ENOMEM); entry->len = (size + 15) & ~15; @@ -91,11 +91,11 @@ out: kfree(entry); spin_unlock_irqrestore(&voya_list_lock, flags); - return NULL; + return ERR_PTR(-EINVAL); } -void voyagergx_consistent_free(struct device *dev, size_t size, - void *vaddr, dma_addr_t handle) +int voyagergx_consistent_free(struct device *dev, size_t size, + void *vaddr, dma_addr_t handle) { struct voya_alloc_entry *entry; struct sh_dev *shdev = to_sh_dev(dev); @@ -103,10 +103,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size, if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] || (dev->bus == &sh_bus_types[SH_BUS_VIRT] && - shdev->dev_id != SH_DEV_ID_USB_OHCI)) { - consistent_free(vaddr, size); - return; - } + shdev->dev_id != SH_DEV_ID_USB_OHCI)) + return -EINVAL; spin_lock_irqsave(&voya_list_lock, flags); list_for_each_entry(entry, &voya_alloc_list, list) { @@ -119,6 +117,8 @@ void voyagergx_consistent_free(struct device *dev, size_t size, break; } spin_unlock_irqrestore(&voya_list_lock, flags); + + return 0; } EXPORT_SYMBOL(voyagergx_consistent_alloc); diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig index b724a5192..34fd8d1d4 100644 --- a/arch/sh/configs/rts7751r2d_defconfig +++ b/arch/sh/configs/rts7751r2d_defconfig @@ -18,9 +18,12 @@ CONFIG_BROKEN_ON_SMP=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y @@ -29,6 +32,8 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -44,6 +49,7 @@ CONFIG_OBSOLETE_MODPARM=y # # CONFIG_SH_SOLUTION_ENGINE is not set # CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7300_SOLUTION_ENGINE is not set # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_STB1_HARP is not set # CONFIG_SH_STB1_OVERDRIVE is not set @@ -61,6 +67,7 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_SH_ADX is not set # CONFIG_SH_MPC1211 is not set # CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_HS7751RVOIP is not set CONFIG_SH_RTS7751R2D=y # CONFIG_SH_UNKNOWN is not set # CONFIG_CPU_SH2 is not set @@ -68,6 +75,7 @@ CONFIG_SH_RTS7751R2D=y CONFIG_CPU_SH4=y # CONFIG_CPU_SUBTYPE_SH7604 is not set # CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set # CONFIG_CPU_SUBTYPE_SH7709 is not set @@ -75,6 +83,7 @@ CONFIG_CPU_SH4=y CONFIG_CPU_SUBTYPE_SH7751=y # CONFIG_CPU_SUBTYPE_SH7760 is not set # CONFIG_CPU_SUBTYPE_ST40STB1 is not set +# CONFIG_CPU_SUBTYPE_ST40GX1 is not set CONFIG_MMU=y CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1" @@ -92,14 +101,29 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_SH_OCRAM is not set # CONFIG_SH_STORE_QUEUES is not set # CONFIG_SMP is not set -CONFIG_VOYAGERGX=y CONFIG_RTS7751R2D_REV11=y +CONFIG_SH_PCLK_CALC=y CONFIG_SH_PCLK_FREQ=60000000 + +# +# CPU Frequency scaling +# # CONFIG_CPU_FREQ is not set + +# +# DMA support +# CONFIG_SH_DMA=y CONFIG_NR_ONCHIP_DMA_CHANNELS=8 # CONFIG_NR_DMA_CHANNELS_BOOL is not set -# CONFIG_DMA_PAGE_OPS is not set + +# +# Companion Chips +# +CONFIG_VOYAGERGX=y +# CONFIG_HD6446X_SERIES is not set +CONFIG_HEARTBEAT=y +CONFIG_RTC_9701JE=y # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -109,15 +133,14 @@ CONFIG_PCI=y CONFIG_SH_PCIDMA_NONCOHERENT=y CONFIG_PCI_AUTO=y CONFIG_PCI_AUTO_UPDATE_RESOURCES=y -CONFIG_PCI_DMA=y # CONFIG_PCI_LEGACY_PROC is not set CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y # # PCMCIA/CardBus support # CONFIG_PCMCIA=m +# CONFIG_PCMCIA_DEBUG is not set CONFIG_YENTA=m CONFIG_CARDBUS=y # CONFIG_I82092 is not set @@ -131,6 +154,8 @@ CONFIG_PCMCIA_PROBE=y CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set # CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set # # Executable file formats @@ -139,6 +164,10 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_FLAT is not set # CONFIG_BINFMT_MISC is not set +# +# Device Drivers +# + # # Generic Driver Options # @@ -154,6 +183,11 @@ CONFIG_BINFMT_ELF=y # # CONFIG_PARPORT is not set +# +# Plug and Play support +# +# CONFIG_PNP is not set + # # Block devices # @@ -165,6 +199,7 @@ CONFIG_BINFMT_ELF=y # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_CARMEL is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set @@ -174,6 +209,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y # @@ -181,7 +217,6 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECS=m # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set @@ -192,11 +227,13 @@ CONFIG_BLK_DEV_IDECS=m # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_IDEPCI is not set +CONFIG_IDE_SH=y +# CONFIG_IDE_ARM is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set -# CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_HD is not set # @@ -215,10 +252,19 @@ CONFIG_BLK_DEV_IDECS=m # CONFIG_MD is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set +# +# I2O device support +# +# CONFIG_I2O is not set + # # Networking support # @@ -239,23 +285,21 @@ CONFIG_INET=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -264,6 +308,7 @@ CONFIG_IPV6_SCTP__=y # 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 # @@ -275,16 +320,21 @@ CONFIG_IPV6_SCTP__=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set # # Ethernet (10 or 100Mbit) @@ -325,6 +375,7 @@ CONFIG_NET_PCI=y # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_CS89x0 is not set # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set @@ -355,7 +406,6 @@ CONFIG_8139TOO=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -363,10 +413,12 @@ CONFIG_8139TOO=y # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -395,27 +447,20 @@ CONFIG_HERMES=m # CONFIG_PLX_HERMES is not set # CONFIG_TMD_HERMES is not set # CONFIG_PCI_HERMES is not set +# CONFIG_ATMEL is not set # # Wireless 802.11b Pcmcia/Cardbus cards support # CONFIG_PCMCIA_HERMES=m # CONFIG_AIRO_CS is not set -# CONFIG_PCMCIA_ATMEL is not set # CONFIG_PCMCIA_WL3501 is not set -CONFIG_NET_WIRELESS=y # -# Token Ring devices +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support # -# CONFIG_TR is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set +# CONFIG_PRISM54 is not set +CONFIG_NET_WIRELESS=y # # PCMCIA network device support @@ -423,24 +468,20 @@ CONFIG_NET_WIRELESS=y # CONFIG_NET_PCMCIA is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Bluetooth support +# Wan interfaces # -# CONFIG_BT is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -472,28 +513,7 @@ CONFIG_SOUND_GAMEPORT=y # Character devices # # CONFIG_VT is not set -# CONFIG_SERIAL is not set -CONFIG_SH_SCI=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_RTC_9701JE=y - -# -# Unix 98 PTY support -# -# CONFIG_UNIX98_PTYS is not set -CONFIG_HEARTBEAT=y -# CONFIG_PSMOUSE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set +# CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers @@ -504,142 +524,47 @@ CONFIG_HEARTBEAT=y # Non-8250 serial port support # # CONFIG_SERIAL_SH_SCI is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_QIC02_TAPE is not set # -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Algorithms -# - -# -# I2C Hardware Bus support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -CONFIG_MINIX_FS=y -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems +# IPMI # -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -# CONFIG_NTFS_FS is not set +# CONFIG_IPMI_HANDLER is not set # -# Pseudo filesystems +# Watchdog Cards # -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -# CONFIG_DEVFS_FS is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # -# Miscellaneous filesystems +# Ftape, the floppy tape device driver # -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # -# Network File Systems +# PCMCIA character devices # -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_EXPORTFS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set # -# Partition Types +# I2C support # -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y +# CONFIG_I2C is not set # -# Native Language Support +# Misc devices # -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=y -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 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 # # Multimedia devices @@ -665,14 +590,21 @@ CONFIG_SOUND=y # Advanced Linux Sound Architecture # CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m # CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_OSSEMUL is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set # # Generic devices # +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m # CONFIG_SND_DUMMY is not set # CONFIG_SND_MTPAV is not set # CONFIG_SND_SERIAL_U16550 is not set @@ -707,12 +639,19 @@ CONFIG_SND=m # # PCI devices # +CONFIG_SND_AC97_CODEC=m # CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set # CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set @@ -731,6 +670,7 @@ CONFIG_SND_YMFPCI=m # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set # CONFIG_SND_SONICVIBES is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VX222 is not set @@ -740,6 +680,7 @@ CONFIG_SND_YMFPCI=m # # CONFIG_SND_VXPOCKET is not set # CONFIG_SND_VXP440 is not set +# CONFIG_SND_PDAUDIOCF is not set # # Open Sound System @@ -747,10 +688,6 @@ CONFIG_SND_YMFPCI=m CONFIG_SOUND_PRIME=m # CONFIG_SOUND_BT878 is not set CONFIG_SOUND_CMPCI=m -# CONFIG_SOUND_CMPCI_FM is not set -# CONFIG_SOUND_CMPCI_MIDI is not set -# CONFIG_SOUND_CMPCI_JOYSTICK is not set -# CONFIG_SOUND_CMPCI_CM8738 is not set # CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_CS4281 is not set @@ -776,19 +713,146 @@ CONFIG_SOUND_VOYAGERGX=m # USB support # # CONFIG_USB is not set + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_EXPORTFS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +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=y +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 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 + # # Profiling support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y # # Kernel hacking # # CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set # CONFIG_KGDB is not set # CONFIG_FRAME_POINTER is not set @@ -806,3 +870,4 @@ CONFIG_SOUND_VOYAGERGX=m # Library routines # CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig index 4162d3d6d..6501d94ff 100644 --- a/arch/sh/configs/se7751_defconfig +++ b/arch/sh/configs/se7751_defconfig @@ -284,6 +284,7 @@ CONFIG_IPV6_SCTP__=y # 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 # diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 3fc34e1cf..7c3330f11 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -211,8 +211,9 @@ int __init register_dmac(struct dma_info *info) INIT_LIST_HEAD(&info->list); - printk(KERN_INFO "DMA: Registering %s handler (%d channels).\n", - info->name, info->nr_channels); + printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n", + info->name, info->nr_channels, + info->nr_channels > 1 ? "s" : ""); BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); @@ -282,7 +283,6 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(request_dma); EXPORT_SYMBOL(free_dma); EXPORT_SYMBOL(register_dmac); -EXPORT_SYMBOL(unregister_dmac); EXPORT_SYMBOL(get_dma_residue); EXPORT_SYMBOL(get_dma_info); EXPORT_SYMBOL(get_dma_channel); diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index f369e6c25..231e3f6fb 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -3,7 +3,7 @@ * * G2 bus DMA support * - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003, 2004 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -59,104 +59,102 @@ static struct irqaction g2_dma_irq = { .flags = SA_INTERRUPT, }; -static int g2_enable_dma(struct dma_info *info) +static int g2_enable_dma(struct dma_channel *chan) { - unsigned int chan = info->chan; + unsigned int chan_nr = chan->chan; - g2_dma->channel[chan].chan_enable = 1; - g2_dma->channel[chan].xfer_enable = 1; + g2_dma->channel[chan_nr].chan_enable = 1; + g2_dma->channel[chan_nr].xfer_enable = 1; return 0; } -static int g2_disable_dma(struct dma_info *info) +static int g2_disable_dma(struct dma_channel *chan) { - unsigned int chan = info->chan; + unsigned int chan_nr = chan->chan; - g2_dma->channel[chan].chan_enable = 0; - g2_dma->channel[chan].xfer_enable = 0; + g2_dma->channel[chan_nr].chan_enable = 0; + g2_dma->channel[chan_nr].xfer_enable = 0; return 0; } -static int g2_xfer_dma(struct dma_info *info) +static int g2_xfer_dma(struct dma_channel *chan) { - unsigned int chan = info->chan; + unsigned int chan_nr = chan->chan; - if (info->sar & 31) { - printk("g2dma: unaligned source 0x%lx\n", info->sar); + if (chan->sar & 31) { + printk("g2dma: unaligned source 0x%lx\n", chan->sar); return -EINVAL; } - if (info->dar & 31) { - printk("g2dma: unaligned dest 0x%lx\n", info->dar); + if (chan->dar & 31) { + printk("g2dma: unaligned dest 0x%lx\n", chan->dar); return -EINVAL; } /* Align the count */ - if (info->count & 31) - info->count = (info->count + (32 - 1)) & ~(32 - 1); + if (chan->count & 31) + chan->count = (chan->count + (32 - 1)) & ~(32 - 1); /* Fixup destination */ - info->dar += 0xa0800000; + chan->dar += 0xa0800000; /* Fixup direction */ - info->mode = !info->mode; + chan->mode = !chan->mode; - flush_icache_range((unsigned long)info->sar, info->count); + flush_icache_range((unsigned long)chan->sar, chan->count); - g2_disable_dma(info); + g2_disable_dma(chan); - g2_dma->channel[chan].g2_addr = info->dar & 0x1fffffe0; - g2_dma->channel[chan].root_addr = info->sar & 0x1fffffe0; - g2_dma->channel[chan].size = (info->count & ~31) | 0x80000000; - g2_dma->channel[chan].direction = info->mode; + g2_dma->channel[chan_nr].g2_addr = chan->dar & 0x1fffffe0; + g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0; + g2_dma->channel[chan_nr].size = (chan->count & ~31) | 0x80000000; + g2_dma->channel[chan_nr].direction = chan->mode; /* * bit 0 - ??? * bit 1 - if set, generate a hardware event on transfer completion * bit 2 - ??? something to do with suspend? */ - g2_dma->channel[chan].ctrl = 5; /* ?? */ + g2_dma->channel[chan_nr].ctrl = 5; /* ?? */ + + g2_enable_dma(chan); - g2_enable_dma(info); - /* debug cruft */ pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, " "0x%08lx, %ld, %ld, %ld, %ld\n", - g2_dma->channel[chan].size, - g2_dma->channel[chan].root_addr, - g2_dma->channel[chan].g2_addr, - g2_dma->channel[chan].direction, - g2_dma->channel[chan].ctrl, - g2_dma->channel[chan].chan_enable, - g2_dma->channel[chan].xfer_enable); + g2_dma->channel[chan_nr].size, + g2_dma->channel[chan_nr].root_addr, + g2_dma->channel[chan_nr].g2_addr, + g2_dma->channel[chan_nr].direction, + g2_dma->channel[chan_nr].ctrl, + g2_dma->channel[chan_nr].chan_enable, + g2_dma->channel[chan_nr].xfer_enable); return 0; } static struct dma_ops g2_dma_ops = { - .name = "G2 DMA", .xfer = g2_xfer_dma, }; +static struct dma_info g2_dma_info = { + .name = "G2 DMA", + .nr_channels = 4, + .ops = &g2_dma_ops, + .flags = DMAC_CHANNELS_TEI_CAPABLE, +}; + static int __init g2_dma_init(void) { - int i, base; - setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq); /* Magic */ g2_dma->wait_state = 27; g2_dma->magic = 0x4659404f; - /* G2 channels come after on-chip and pvr2 */ - base = ONCHIP_NR_DMA_CHANNELS + PVR2_NR_DMA_CHANNELS; - - for (i = 0; i < G2_NR_DMA_CHANNELS; i++) - dma_info[base + i].ops = &g2_dma_ops; - - return register_dmac(&g2_dma_ops); + return register_dmac(&g2_dma_info); } static void __exit g2_dma_exit(void) diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index ee54adae2..2e1d58f2d 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -3,7 +3,7 @@ * * NEC PowerVR 2 (Dreamcast) DMA support * - * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003, 2004 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -38,7 +38,7 @@ static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *reg return IRQ_HANDLED; } -static int pvr2_request_dma(struct dma_info *info) +static int pvr2_request_dma(struct dma_channel *chan) { if (ctrl_inl(PVR2_DMA_MODE) != 0) return -EBUSY; @@ -48,21 +48,21 @@ static int pvr2_request_dma(struct dma_info *info) return 0; } -static int pvr2_get_dma_residue(struct dma_info *info) +static int pvr2_get_dma_residue(struct dma_channel *chan) { return xfer_complete == 0; } -static int pvr2_xfer_dma(struct dma_info *info) +static int pvr2_xfer_dma(struct dma_channel *chan) { - if (info->sar || !info->dar) + if (chan->sar || !chan->dar) return -EINVAL; xfer_complete = 0; - ctrl_outl(info->dar, PVR2_DMA_ADDR); - ctrl_outl(info->count, PVR2_DMA_COUNT); - ctrl_outl(info->mode & DMA_MODE_MASK, PVR2_DMA_MODE); + ctrl_outl(chan->dar, PVR2_DMA_ADDR); + ctrl_outl(chan->count, PVR2_DMA_COUNT); + ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE); return 0; } @@ -74,26 +74,24 @@ static struct irqaction pvr2_dma_irq = { }; static struct dma_ops pvr2_dma_ops = { - .name = "PowerVR 2 DMA", .request = pvr2_request_dma, .get_residue = pvr2_get_dma_residue, .xfer = pvr2_xfer_dma, }; +static struct dma_info pvr2_dma_info = { + .name = "PowerVR 2 DMA", + .nr_channels = 1, + .ops = &pvr2_dma_ops, + .flags = DMAC_CHANNELS_TEI_CAPABLE, +}; + static int __init pvr2_dma_init(void) { - int i, base; - setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); - /* PVR2 cascade comes after on-chip DMAC */ - base = ONCHIP_NR_DMA_CHANNELS; - - for (i = 0; i < PVR2_NR_DMA_CHANNELS; i++) - dma_info[base + i].ops = &pvr2_dma_ops; - - return register_dmac(&pvr2_dma_ops); + return register_dmac(&pvr2_dma_info); } static void __exit pvr2_dma_exit(void) diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile index 4923bbf5e..365bc16a4 100644 --- a/arch/sh/drivers/pci/Makefile +++ b/arch/sh/drivers/pci/Makefile @@ -13,4 +13,4 @@ obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o - +obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o diff --git a/arch/sh/drivers/pci/dma-dreamcast.c b/arch/sh/drivers/pci/dma-dreamcast.c index ff6169720..83de7ef4e 100644 --- a/arch/sh/drivers/pci/dma-dreamcast.c +++ b/arch/sh/drivers/pci/dma-dreamcast.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -30,18 +32,21 @@ static int gapspci_dma_used = 0; -void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) +void *dreamcast_consistent_alloc(struct device *dev, size_t size, + dma_addr_t *dma_handle, int flag) { unsigned long buf; - if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) + if (dev && dev->bus != &pci_bus_type) return NULL; - buf = GAPSPCI_DMA_BASE+gapspci_dma_used; + if (gapspci_dma_used + size > GAPSPCI_DMA_SIZE) + return ERR_PTR(-EINVAL); + + buf = GAPSPCI_DMA_BASE + gapspci_dma_used; gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); - + *dma_handle = (dma_addr_t)buf; buf = P2SEGADDR(buf); @@ -52,10 +57,15 @@ void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size, return (void *)buf; } -void __pci_free_consistent(struct pci_dev *hwdev, size_t size, +int dreamcast_consistent_free(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { + if (dev && dev->bus != &pci_bus_type) + return -EINVAL; + /* XXX */ gapspci_dma_used = 0; + + return 0; } diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index aa5e24a65..cf30e2fa5 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -47,11 +47,7 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev) } } -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, - PCI_ANY_ID, gapspci_fixup_resources }, - { 0, } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources); void __init pcibios_fixup_bus(struct pci_bus *bus) { @@ -66,7 +62,7 @@ void __init pcibios_fixup_irqs(void) { struct pci_dev *dev = 0; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { /* * The interrupt routing semantics here are quite trivial. * diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c index 7b5dbe157..0c590fc7a 100644 --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c @@ -18,15 +18,26 @@ int pci_fixup_pcic(void) { - unsigned long mcr; + unsigned long bcr1, mcr; - outl(0xfb900047, SH7751_PCICONF1); - outl(0xab000001, SH7751_PCICONF4); + bcr1 = inl(SH7751_BCR1); + bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + outl(bcr1, PCI_REG(SH7751_PCIBCR1)); + + /* Enable all interrupts, so we known what to fix */ + outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM)); + outl(0x0000380f, PCI_REG(SH7751_PCIAINTM)); + + outl(0xfb900047, PCI_REG(SH7751_PCICONF1)); + outl(0xab000001, PCI_REG(SH7751_PCICONF4)); mcr = inl(SH7751_MCR); mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; - outl(mcr, SH7751_PCIMCR); + outl(mcr, PCI_REG(SH7751_PCIMCR)); + outl(0x0c000000, PCI_REG(SH7751_PCICONF5)); + outl(0xd0000000, PCI_REG(SH7751_PCICONF6)); + outl(0x0c000000, PCI_REG(SH7751_PCILAR0)); + outl(0x00000000, PCI_REG(SH7751_PCILAR1)); return 0; } - diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c index 2bceb43c9..beafa11f4 100644 --- a/arch/sh/drivers/pci/ops-rts7751r2d.c +++ b/arch/sh/drivers/pci/ops-rts7751r2d.c @@ -61,7 +61,12 @@ EXPORT_SYMBOL(board_pci_channels); static struct sh7751_pci_address_map sh7751_pci_map = { .window0 = { .base = SH7751_CS3_BASE_ADDR, - .size = 0x03f00000, + .size = 0x04000000, + }, + + .window1 = { + .base = 0x00000000, /* Unused */ + .size = 0x00000000, /* Unused */ }, .flags = SH7751_PCIC_NO_RESET, diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c index 2ad70d499..4cef4d1d8 100644 --- a/arch/sh/drivers/pci/pci-auto.c +++ b/arch/sh/drivers/pci/pci-auto.c @@ -524,8 +524,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) PCI_COMMAND, cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); +#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) early_write_config_byte(hose, top_bus, current_bus, pci_devfn, PCI_LATENCY_TIMER, 0x80); +#endif /* Allocate PCI I/O and/or memory space */ pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5); diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index b2bb72972..6d4c9f2b3 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c @@ -33,6 +33,8 @@ static unsigned int pci_probe = PCI_PROBE_CONF1; extern int pci_fixup_pcic(void); +void pcibios_fixup_irqs(void) __attribute__ ((weak)); + /* * Direct access to PCI hardware... */ @@ -158,7 +160,6 @@ static int __init pci_check_direct(void) * Handle bus scanning and fixups .... */ -#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) static void __init pci_fixup_ide_bases(struct pci_dev *d) { int i; @@ -177,16 +178,9 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } } +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); #endif -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { -#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D) - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, -#endif - { 0 } -}; - /* * Called after each bus is probed, but before its children * are examined. @@ -263,7 +257,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) outl(0, PCI_REG(SH7751_PCICLKR)); /* Clear Powerdown IRQ's (not done in reset) */ word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; - outl(word, PCI_REG(SH7751_PCICLKR)); + outl(word, PCI_REG(SH7751_PCIPINT)); /* * This code is unused for some boards as it is done in the @@ -368,7 +362,7 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) * TODO: add support for the internal error interrupts and * DMA interrupts... */ - + #ifdef CONFIG_SH_RTS7751R2D pci_fixup_pcic(); #endif diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c index 29e7bf619..2688f4159 100644 --- a/arch/sh/drivers/pci/pci-st40.c +++ b/arch/sh/drivers/pci/pci-st40.c @@ -18,6 +18,7 @@ #include #include #include +#include /* irqreturn_t */ #include "pci-st40.h" @@ -28,24 +29,22 @@ #define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) +#define ST40PCI_REG_INDEXED(reg, index) \ + (ST40PCI_REG(reg##0) + \ + ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index)) #define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) #define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) #define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) +#define ST40PCI_WRITE_INDEXED(reg, index, val) \ + writel((val), ST40PCI_REG_INDEXED(reg, index)); #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) -#define ST40PCI_SERR_IRQ 64 -#define ST40PCI_SERR_INT_GROUP 0 -#define ST40PCI_SERR_INT_POS 0 -#define ST40PCI_SERR_INT_PRI 15 - -#define ST40PCI_ERR_IRQ 65 -#define ST40PCI_ERR_INT_GROUP 1 -#define ST40PCI_ERR_INT_POS 1 -#define ST40PCI_ERR_INT_PRI 14 +#define ST40PCI_SERR_IRQ 64 +#define ST40PCI_ERR_IRQ 65 /* Macros to extract PLL params */ @@ -69,47 +68,143 @@ #define PLL_25MHZ 0x793c8512 #define PLL_33MHZ PLL_SET(18,88,3,295) +static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, + unsigned long pciOffset, unsigned long regionSize); + +/* + * The pcibios_map_platform_irq function is defined in the appropriate + * board specific code and referenced here + */ +extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin); static __init void SetPCIPLL(void) { - /* Stop the PLL */ - writel(0, PLLPCICR); + { + /* Lets play with the PLL values */ + unsigned long pll1cr1; + unsigned long mdiv, ndiv, pdiv; + unsigned long muxcr; + unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 }; + unsigned int freq; + +#define CLKGENA 0xbb040000 +#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48 + pll1cr1 = ctrl_inl(PLLPCICR); + printk("PLL1CR1 %08lx\n", pll1cr1); + mdiv = PLL_MDIV(pll1cr1); + ndiv = PLL_NDIV(pll1cr1); + pdiv = PLL_PDIV(pll1cr1); + printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv); + freq = ((2*27*ndiv)/mdiv) / (1 << pdiv); + printk("PLL freq %dMHz\n", freq); + muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR); + printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]); + } +} - /* Always run at 33Mhz. The PCI clock is totally async - * to the rest of the system - */ - writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR); - printk("ST40PCI: Waiting for PCI PLL to lock\n"); - while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0); - writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR); +struct pci_err { + unsigned mask; + const char *error_string; +}; + +static struct pci_err int_error[]={ + { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"}, + { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"}, + { INT_TMTO, "TMTO: Target memory read/write timeout"}, + { INT_MDEI, "MDEI: Master function disable error"}, + { INT_APEDI, "APEDI: Address parity error"}, + { INT_SDI, "SDI: SERR detected"}, + { INT_DPEITW, "DPEITW: Data parity error target write"}, + { INT_PEDITR, "PEDITR: PERR detected"}, + { INT_TADIM, "TADIM: Target abort detected"}, + { INT_MADIM, "MADIM: Master abort detected"}, + { INT_MWPDI, "MWPDI: PERR from target at data write"}, + { INT_MRDPEI, "MRDPEI: Master read data parity error"} +}; +#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err)) + +static struct pci_err aint_error[]={ + { AINT_MBI, "MBI: Master broken"}, + { AINT_TBTOI, "TBTOI: Target bus timeout"}, + { AINT_MBTOI, "MBTOI: Master bus timeout"}, + { AINT_TAI, "TAI: Target abort"}, + { AINT_MAI, "MAI: Master abort"}, + { AINT_RDPEI, "RDPEI: Read data parity"}, + { AINT_WDPE, "WDPE: Write data parity"} +}; + +#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err)) + +static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors) +{ + int i; + + for(i=0;i1) return IRQ_HANDLED; - if (pci_int) { - printk("PCI INTERRUPT!\n"); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(INT, ~0); + printk("** PCI ERROR **\n"); + + if(pci_int) { + printk("** INT register status\n"); + print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS); } - pci_aint = ST40PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(AINT, ~0); + if(pci_aint) { + printk("** AINT register status\n"); + print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS); + } + + printk("** Address and command info\n"); + + printk("** Command %s : Address 0x%x\n", + pci_commands[pci_cir&0xf],pci_air); + + if(pci_cir&CIR_PIOTEM) { + printk("CIR_PIOTEM:PIO transfer error for master\n"); + } + if(pci_cir&CIR_RWTET) { + printk("CIR_RWTET:Read/Write transfer error for target\n"); } return IRQ_HANDLED; @@ -119,7 +214,7 @@ static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *reg /* Rounds a number UP to the nearest power of two. Used for * sizing the PCI window. */ -static u32 __init r2p2(u32 num) +static u32 r2p2(u32 num) { int i = 31; u32 tmp = num; @@ -160,13 +255,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } } - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); int __init st40pci_init(unsigned memStart, unsigned memSize) { @@ -185,12 +274,16 @@ int __init st40pci_init(unsigned memStart, unsigned memSize) /* Loop while core resets */ while (ST40PCI_READ(CR) & CR_SOFT_RESET); + /* Switch off interrupts */ + ST40PCI_WRITE(INTM, 0); + ST40PCI_WRITE(AINT, 0); + /* Now, lets reset all the cards on the bus with extreme prejudice */ ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); udelay(250); /* Set bus active, take it out of reset */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE); + ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE); /* The PCI spec says that no access must be made to the bus until 1 second * after reset. This seem ludicrously long, but some delay is needed here @@ -225,37 +318,20 @@ int __init st40pci_init(unsigned memStart, unsigned memSize) /* Set up the 64K window */ ST40PCI_WRITE(IOBMR, 0x0); - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ - - if (memSize < (64 * 1024)) { - printk("Ridiculous memory size of 0x%x?\n",memSize); - return 0; - } - - lsr0 = - (memSize > - (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) - - 0x10000) | 0x1); + /* Now we set up the mbars so the PCI bus can see the local memory */ + /* Expose a 256M window starting at PCI address 0... */ + ST40PCI_WRITE(CSR_MBAR0, 0); + ST40PCI_WRITE(LSR0, 0x0fff0001); - ST40PCI_WRITE(LSR0, lsr0); - - ST40PCI_WRITE(CSR_MBAR0, memStart); - ST40PCI_WRITE(LAR0, memStart); + /* ... and set up the initial incomming window to expose all of RAM */ + pci_set_rbar_region(7, memStart, memStart, memSize); /* Maximise timeout values */ ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); - - /* Install the pci interrupt handlers */ - make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0, - ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS, - ST40PCI_SERR_INT_PRI); - - make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP, - ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI); - + ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING); return 1; } @@ -338,7 +414,7 @@ static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int return PCIBIOS_SUCCESSFUL; } -static struct pci_ops pci_config_ops = { +struct pci_ops st40pci_config_ops = { .read = st40pci_read, .write = st40pci_write, }; @@ -354,36 +430,12 @@ static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) } -/* This needs to be shunted out of here into the board specific bit */ -#define HARP_PCI_IRQ 1 -#define HARP_BRIDGE_IRQ 2 -#define OVERDRIVE_SLOT0_IRQ 0 - -static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - switch (slot) { -#ifdef CONFIG_SH_STB1_HARP - case 2: /*This is the PCI slot on the */ - return HARP_PCI_IRQ; - case 1: /* this is the bridge */ - return HARP_BRIDGE_IRQ; -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - case 1: - case 2: - case 3: - return slot - 1; -#else -#error Unknown board -#endif - default: - return -1; - } -} - -void __init pcibios_init(void) +static int __init pcibios_init(void) { extern unsigned long memory_start, memory_end; + printk(KERN_ALERT "pci-st40.c: pcibios_init\n"); + if (sh_mv.mv_init_pci != NULL) { sh_mv.mv_init_pci(); } @@ -398,7 +450,7 @@ void __init pcibios_init(void) if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, SA_INTERRUPT, "st40pci", NULL)) { printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); - return; + return -EIO; } /* Enable the PCI interrupts on the device */ @@ -412,12 +464,46 @@ void __init pcibios_init(void) #endif /* ok, do the scan man */ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); + pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL); pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_harp_irq); + pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq); + return 0; } +subsys_initcall(pcibios_init); + void __init pcibios_fixup_bus(struct pci_bus *bus) { } + +/* + * Publish a region of local address space over the PCI bus + * to other devices. + */ +static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, + unsigned long pciOffset, unsigned long regionSize) +{ + unsigned long mask; + + if (region > 7) + return; + + if (regionSize > (512 * 1024 * 1024)) + return; + + mask = r2p2(regionSize) - 0x10000; + + /* Diable the region (in case currently in use, should never happen) */ + ST40PCI_WRITE_INDEXED(RSR, region, 0); + + /* Start of local address space to publish */ + ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) ); + + /* Start of region in PCI address space as an offset from MBAR0 */ + ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset); + + /* Size of region */ + ST40PCI_WRITE_INDEXED(RSR, region, mask | 1); +} + diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h index 2e3451a97..d729e0c2d 100644 --- a/arch/sh/drivers/pci/pci-st40.h +++ b/arch/sh/drivers/pci/pci-st40.h @@ -33,13 +33,36 @@ #define ST40PCI_LAR0 0x1c #define ST40PCI_INT 0x24 +#define INT_MNLTDIM (1<<15) +#define INT_TTADI (1<<14) +#define INT_TMTO (1<<9) +#define INT_MDEI (1<<8) +#define INT_APEDI (1<<7) +#define INT_SDI (1<<6) +#define INT_DPEITW (1<<5) +#define INT_PEDITR (1<<4) +#define INT_TADIM (1<<3) #define INT_MADIM (1<<2) +#define INT_MWPDI (1<<1) +#define INT_MRDPEI (1<<0) #define ST40PCI_INTM 0x28 #define ST40PCI_AIR 0x2c + #define ST40PCI_CIR 0x30 +#define CIR_PIOTEM (1<<31) +#define CIR_RWTET (1<<26) + #define ST40PCI_AINT 0x40 +#define AINT_MBI (1<<13) +#define AINT_TBTOI (1<<12) +#define AINT_MBTOI (1<<11) +#define AINT_TAI (1<<3) +#define AINT_MAI (1<<2) +#define AINT_RDPEI (1<<1) +#define AINT_WDPE (1<<0) + #define ST40PCI_AINTM 0x44 #define ST40PCI_BMIR 0x48 #define ST40PCI_PAR 0x4c @@ -51,6 +74,53 @@ #define ST40PCI_IOBMR 0x74 #define ST40PCI_PDR 0x78 +/* H8 specific registers start here */ +#define ST40PCI_WCBAR 0x7c +#define ST40PCI_LOCCFG_UNLOCK 0x34 + +#define ST40PCI_RBAR0 0x100 +#define ST40PCI_RSR0 0x104 +#define ST40PCI_RLAR0 0x108 + +#define ST40PCI_RBAR1 0x110 +#define ST40PCI_RSR1 0x114 +#define ST40PCI_RLAR1 0x118 + + +#define ST40PCI_RBAR2 0x120 +#define ST40PCI_RSR2 0x124 +#define ST40PCI_RLAR2 0x128 + +#define ST40PCI_RBAR3 0x130 +#define ST40PCI_RSR3 0x134 +#define ST40PCI_RLAR3 0x138 + +#define ST40PCI_RBAR4 0x140 +#define ST40PCI_RSR4 0x144 +#define ST40PCI_RLAR4 0x148 + +#define ST40PCI_RBAR5 0x150 +#define ST40PCI_RSR5 0x154 +#define ST40PCI_RLAR5 0x158 + +#define ST40PCI_RBAR6 0x160 +#define ST40PCI_RSR6 0x164 +#define ST40PCI_RLAR6 0x168 + +#define ST40PCI_RBAR7 0x170 +#define ST40PCI_RSR7 0x174 +#define ST40PCI_RLAR7 0x178 + + +#define ST40PCI_RBAR(n) (0x100+(0x10*(n))) +#define ST40PCI_RSR(n) (0x104+(0x10*(n))) +#define ST40PCI_RLAR(n) (0x108+(0x10*(n))) + +#define ST40PCI_PERF 0x80 +#define PERF_MASTER_WRITE_POSTING (1<<4) +/* H8 specific registers end here */ + + /* These are configs space registers */ #define ST40PCI_CSR_VID 0x10000 #define ST40PCI_CSR_DID 0x10002 diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 4bf35336d..363bc839b 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -106,6 +106,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for(idx=0; idx<6; idx++) { + if (!(mask & (1 << idx))) + continue; r = &dev->resource[idx]; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because " diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index d36bd9410..8b819698d 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH kernel. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 975103f34..352f71a10 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -24,8 +24,8 @@ extern void detect_cpu_and_cache_system(void); * Generic wrapper for command line arguments to disable on-chip * peripherals (nofpu, nodsp, and so forth). */ -#define onchip_setup(x) \ -static int x##_disabled __initdata = 0; \ +#define onchip_setup(x) \ +static int x##_disabled __initdata = 0; \ \ static int __init x##_setup(char *opts) \ { \ @@ -88,7 +88,7 @@ static void __init cache_init(void) } while (--ways); } - /* + /* * Default CCR values .. enable the caches * and invalidate them immediately.. */ @@ -160,7 +160,7 @@ static void __init dsp_init(void) } #endif /* CONFIG_SH_DSP */ -/* +/** * sh_cpu_init * * This is our initial entry point for each CPU, and is invoked on the boot @@ -200,7 +200,7 @@ asmlinkage void __init sh_cpu_init(void) #ifdef CONFIG_SH_DSP /* Probe for DSP */ dsp_init(); - + /* Disable the DSP */ if (dsp_disabled) { printk("DSP Disabled\n"); diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq_imask.c index be2c82385..f76901e73 100644 --- a/arch/sh/kernel/cpu/irq_imask.c +++ b/arch/sh/kernel/cpu/irq_imask.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq_ipr.c index daae02e6b..7ea3d2d03 100644 --- a/arch/sh/kernel/cpu/irq_ipr.c +++ b/arch/sh/kernel/cpu/irq_ipr.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ static void mask_and_ack_ipr(unsigned int); static void end_ipr_irq(unsigned int irq); static unsigned int startup_ipr_irq(unsigned int irq) -{ +{ enable_ipr_irq(irq); return 0; /* never anything pending */ } @@ -281,6 +282,10 @@ void __init init_IRQ(void) #endif /* !CONFIG_CPU_SUBTYPE_SH7300 */ #endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/ +#ifdef CONFIG_CPU_SUBTYPE_ST40 + init_IRQ_intc2(); +#endif + /* Perform the machine specific initialisation */ if (sh_mv.mv_init_irq != NULL) { sh_mv.mv_init_irq(); @@ -329,3 +334,6 @@ int ipr_irq_demux(int irq) return irq; } #endif + +EXPORT_SYMBOL(make_ipr_irq); + diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile index eb38f91d1..389353fba 100644 --- a/arch/sh/kernel/cpu/sh2/Makefile +++ b/arch/sh/kernel/cpu/sh2/Makefile @@ -2,3 +2,5 @@ # Makefile for the Linux/SuperH SH-2 backends. # +obj-y := probe.o + diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 196c5f07e..a64532e4d 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -2,5 +2,5 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o +obj-y := ex.o probe.o diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index fd5976143..ead1071ea 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -2,8 +2,9 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := fpu.o ex.o +obj-y := ex.o probe.o +obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S index 2cc32adfe..8221e9d15 100644 --- a/arch/sh/kernel/cpu/sh4/ex.S +++ b/arch/sh/kernel/cpu/sh4/ex.S @@ -37,8 +37,11 @@ ENTRY(exception_handling_table) .long exception_error ! address error load .long exception_error ! address error store /* 100 */ #endif - +#if defined(CONFIG_SH_FPU) .long do_fpu_error /* 120 */ +#else + .long exception_error /* 120 */ +#endif .long exception_error /* 140 */ .long system_call ! Unconditional Trap /* 160 */ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ @@ -126,8 +129,13 @@ ENTRY(interrupt_table) .long exception_error ! 46 .long exception_error ! 47 #endif +#if defined(CONFIG_SH_FPU) .long do_fpu_state_restore ! 48 /* 800 */ .long do_fpu_state_restore ! 49 /* 820 */ +#else + .long exception_error + .long exception_error +#endif #if defined(CONFIG_CPU_SUBTYPE_SH7751) .long exception_error /* 840 */ .long exception_error @@ -217,6 +225,66 @@ ENTRY(interrupt_table) .long exception_error .long do_IRQ ! ADC adi .long do_IRQ ! CMT cmti /* FA0 */ +#elif defined(CONFIG_CPU_SUBTYPE_SH73180) + .long do_IRQ ! 50 0x840 + .long do_IRQ ! 51 0x860 + .long do_IRQ ! 52 0x880 + .long do_IRQ ! 53 0x8a0 + .long do_IRQ ! 54 0x8c0 + .long do_IRQ ! 55 0x8e0 + .long do_IRQ ! 56 0x900 + .long do_IRQ ! 57 0x920 + .long do_IRQ ! 58 0x940 + .long do_IRQ ! 59 0x960 + .long do_IRQ ! 60 0x980 + .long do_IRQ ! 61 0x9a0 + .long do_IRQ ! 62 0x9c0 + .long do_IRQ ! 63 0x9e0 + .long do_IRQ ! 64 0xa00 + .long do_IRQ ! 65 0xa20 + .long do_IRQ ! 66 0xa40 + .long do_IRQ ! 67 0xa60 + .long do_IRQ ! 68 0xa80 + .long do_IRQ ! 69 0xaa0 + .long do_IRQ ! 70 0xac0 + .long do_IRQ ! 71 0xae0 + .long do_IRQ ! 72 0xb00 + .long do_IRQ ! 73 0xb20 + .long do_IRQ ! 74 0xb40 + .long do_IRQ ! 75 0xb60 + .long do_IRQ ! 76 0xb80 + .long do_IRQ ! 77 0xba0 + .long do_IRQ ! 78 0xbc0 + .long do_IRQ ! 79 0xbe0 + .long do_IRQ ! 80 0xc00 + .long do_IRQ ! 81 0xc20 + .long do_IRQ ! 82 0xc40 + .long do_IRQ ! 83 0xc60 + .long do_IRQ ! 84 0xc80 + .long do_IRQ ! 85 0xca0 + .long do_IRQ ! 86 0xcc0 + .long do_IRQ ! 87 0xce0 + .long do_IRQ ! 88 0xd00 + .long do_IRQ ! 89 0xd20 + .long do_IRQ ! 90 0xd40 + .long do_IRQ ! 91 0xd60 + .long do_IRQ ! 92 0xd80 + .long do_IRQ ! 93 0xda0 + .long do_IRQ ! 94 0xdc0 + .long do_IRQ ! 95 0xde0 + .long do_IRQ ! 96 0xe00 + .long do_IRQ ! 97 0xe20 + .long do_IRQ ! 98 0xe40 + .long do_IRQ ! 99 0xe60 + .long do_IRQ ! 100 0xe80 + .long do_IRQ ! 101 0xea0 + .long do_IRQ ! 102 0xec0 + .long do_IRQ ! 103 0xee0 + .long do_IRQ ! 104 0xf00 + .long do_IRQ ! 105 0xf20 + .long do_IRQ ! 106 0xf40 + .long do_IRQ ! 107 0xf60 + .long do_IRQ ! 108 0xf80 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) .long exception_error ! 50 0x840 .long exception_error ! 51 0x860 diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c index ec99f4cc4..099ebbf89 100644 --- a/arch/sh/kernel/cpu/sh4/irq_intc2.c +++ b/arch/sh/kernel/cpu/sh4/irq_intc2.c @@ -22,8 +22,11 @@ struct intc2_data { - unsigned int addr; /* Address of Interrupt Priority Register */ - int mask; /*Mask to apply */ + unsigned char msk_offset; + unsigned char msk_shift; +#ifdef CONFIG_CPU_SUBTYPE_ST40 + int (*clear_irq) (int); +#endif }; @@ -56,33 +59,34 @@ static struct hw_interrupt_type intc2_irq_type = { static void disable_intc2_irq(unsigned int irq) { - unsigned addr; - int offset=irq-INTC2_FIRST_IRQ; - unsigned val,flags; + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; // Sanity check - if(offset<0 || offset>=NR_INTC2_IRQS) return; - - addr=intc2_data[offset].addr+INTC2_INTMSK_OFFSET; + if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) + return; - local_irq_save(flags); - val=ctrl_inl(addr); - val|=intc2_data[offset].mask; - ctrl_outl(val,addr); + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; - local_irq_restore(flags); + ctrl_outl(1<=NR_INTC2_IRQS) return; + /* Sanity check */ + if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) + return; - ctrl_outl(intc2_data[offset].mask, - intc2_data[offset].addr+INTC2_INTMSKCLR_OFFSET); + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + ctrl_outl(1<=NR_INTC2_IRQS) { + if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) return; - } disable_irq_nosync(irq); + /* Fill the data we need */ - intc2_data[offset].addr=addr; - intc2_data[offset].mask=1<irq, p->ipr_offset, p->ipr_shift, + p-> msk_offset, p->msk_shift, 13); + } +} + +/* Adds a termination callback to the interrupt */ +void intc2_add_clear_irq(int irq, int (*fn)(int)) +{ + if (irq < INTC2_FIRST_IRQ) + return; + + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; +} +#endif /* CONFIG_CPU_SUBTYPE_ST40 */ diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 3dfe1741d..31579c2ff 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -36,7 +36,6 @@ static spinlock_t sq_mapping_lock = SPIN_LOCK_UNLOCKED; /** * sq_flush - Flush (prefetch) the store queue cache - * * @addr: the store queue address to flush * * Executes a prefetch instruction on the specified store queue cache, @@ -49,7 +48,6 @@ inline void sq_flush(void *addr) /** * sq_flush_range - Flush (prefetch) a specific SQ range - * * @start: the store queue address to start flushing from * @len: the length to flush * @@ -99,7 +97,7 @@ static unsigned long __sq_get_next_addr(void) { if (!list_empty(&sq_mapping_list)) { struct list_head *pos, *tmp; - + /* * Read one off the list head, as it will have the highest * mapped allocation. Set the next one up right above it. @@ -126,11 +124,10 @@ static unsigned long __sq_get_next_addr(void) /** * __sq_remap - Perform a translation from the SQ to a phys addr + * @map: sq mapping containing phys and store queue addresses. * - * @phys: Physical address to map store queues too. - * @virt: Associated store queue address. - * - * Maps the store queue address @virt to the physical address @phys. + * Maps the store queue address specified in the mapping to the physical + * address specified in the mapping. */ static struct sq_mapping *__sq_remap(struct sq_mapping *map) { @@ -210,7 +207,6 @@ static struct sq_mapping *__sq_remap(struct sq_mapping *map) /** * sq_remap - Map a physical address through the Store Queues - * * @phys: Physical address of mapping. * @size: Length of mapping. * @name: User invoking mapping. @@ -254,7 +250,6 @@ struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *n /** * sq_unmap - Unmap a Store Queue allocation - * * @map: Pre-allocated Store Queue mapping. * * Unmaps the store queue allocation @map that was previously created by @@ -272,7 +267,6 @@ void sq_unmap(struct sq_mapping *map) /** * sq_clear - Clear a store queue range - * * @addr: Address to start clearing from. * @len: Length to clear. * @@ -282,7 +276,7 @@ void sq_unmap(struct sq_mapping *map) void sq_clear(unsigned long addr, unsigned int len) { int i; - + /* Clear out both queues linearly */ for (i = 0; i < 8; i++) { ctrl_outl(0, addr + i + 0); @@ -294,7 +288,6 @@ void sq_clear(unsigned long addr, unsigned int len) /** * sq_vma_unmap - Unmap a VMA range - * * @area: VMA containing range. * @addr: Start of range. * @len: Length of range. @@ -314,25 +307,24 @@ static void sq_vma_unmap(struct vm_area_struct *area, entry = list_entry(pos, typeof(*entry), list); if (entry->sq_addr == addr) { - /* + /* * We could probably get away without doing the tlb flush * here, as generic code should take care of most of this * when unmapping the rest of the VMA range for us. Leave * it in for added sanity for the time being.. */ __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK); - + list_del(&entry->list); kfree(entry); return; - } + } } } /** * sq_vma_sync - Sync a VMA range - * * @area: VMA containing range. * @start: Start of range. * @len: Length of range. @@ -359,7 +351,6 @@ static struct vm_operations_struct sq_vma_ops = { /** * sq_mmap - mmap() for /dev/cpu/sq - * * @file: unused. * @vma: VMA to remap. * @@ -373,7 +364,7 @@ static int sq_mmap(struct file *file, struct vm_area_struct *vma) unsigned long size = vma->vm_end - vma->vm_start; struct sq_mapping *map; - /* + /* * We're not interested in any arbitrary virtual address that has * been stuck in the VMA, as we already know what addresses we * want. Save off the size, and reposition the VMA to begin at @@ -391,7 +382,7 @@ static int sq_mmap(struct file *file, struct vm_area_struct *vma) if (io_remap_page_range(vma, map->sq_addr, map->addr, size, vma->vm_page_prot)) return -EAGAIN; - + vma->vm_ops = &sq_vma_ops; return 0; @@ -406,7 +397,7 @@ static int sq_mapping_read_proc(char *buf, char **start, off_t off, list_for_each_prev(pos, &sq_mapping_list) { struct sq_mapping *entry; - + entry = list_entry(pos, typeof(*entry), list); p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr, diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 8c2769c0d..1378db375 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -3,6 +3,7 @@ * * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2002 M. R. Brown + * Copyright (C) 2004 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -109,7 +110,8 @@ void scif_sercon_init(int baud) ctrl_outw(0, SCIF_REG); /* Set baud rate */ - ctrl_outb((50000000 / (32 * baud)) - 1, SCIF_REG + 4); + ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / + (32 * baud) - 1, SCIF_REG + 4); ctrl_outw(12, SCIF_REG + 24); ctrl_outw(8, SCIF_REG + 24); diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index 05dcc2e01..6615e4838 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -1139,5 +1140,10 @@ ENTRY(sys_call_table) .long sys_mq_timedreceive /* 280 */ .long sys_mq_notify .long sys_mq_getsetattr + .long sys_ni_syscall /* Reserved for kexec */ + .long sys_waitid + .long sys_add_key /* 285 */ + .long sys_request_key + .long sys_keyctl /* End of entry.S */ diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index d78503dd2..9a7d93626 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -31,10 +31,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -137,14 +137,16 @@ unlock: int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { int status = 1; /* Force the "do bottom halves" bit */ - int retval = 0; + int ret, retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { - status |= action->flags; - retval |= action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; + retval |= ret; action = action->next; } while (action); diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 8ba6dd300..64f547aa1 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -199,7 +199,7 @@ void exit_thread(void) void flush_thread(void) { -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; struct pt_regs *regs = (struct pt_regs *) ((unsigned long)tsk->thread_info @@ -222,7 +222,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) { int fpvalid = 0; -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; fpvalid = tsk->used_math; @@ -259,7 +259,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) { int fpvalid = 0; -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_SH_FPU) fpvalid = tsk->used_math; if (fpvalid) { struct pt_regs *regs = (struct pt_regs *) @@ -281,7 +281,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_SH_FPU) struct task_struct *tsk = current; unlazy_fpu(tsk, regs); @@ -306,7 +306,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->gbr = childregs->regs[0]; } childregs->regs[0] = 0; /* Set return value for child */ - p->set_child_tid = p->clear_child_tid = NULL; p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; @@ -363,7 +362,7 @@ ubc_set_tracing(int asid, unsigned long pc) */ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next) { -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_SH_FPU) struct pt_regs *regs = (struct pt_regs *) ((unsigned long)prev->thread_info + THREAD_SIZE - sizeof(struct pt_regs) @@ -440,7 +439,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, { if (!newsp) newsp = regs.regs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -481,8 +480,11 @@ asmlinkage int sys_execve(char *ufilename, char **uargv, (char __user * __user *)uargv, (char __user * __user *)uenvp, ®s); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: return error; diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 017826912..d14810a45 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -217,7 +217,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index ca2105907..16694472e 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -443,6 +443,7 @@ static const char *cpu_name[] = { [CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R", [CPU_SH7760] = "SH7760", + [CPU_SH73180] = "SH73180", [CPU_ST40RA] = "ST40RA", [CPU_ST40GX1] = "ST40GX1", [CPU_SH4_202] = "SH4-202", @@ -457,7 +458,7 @@ const char *get_cpu_subtype(void) #ifdef CONFIG_PROC_FS static const char *cpu_flags[] = { - "none", "fpu", "p2flush", "mmuassoc", "dsp", + "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", }; static void show_cpuflags(struct seq_file *m) diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index 9d176936c..5b53e10bb 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c @@ -1,5 +1,4 @@ -/* $Id: sh_bios.c,v 1.2 2003/05/04 19:29:53 lethal Exp $ - * +/* * linux/arch/sh/kernel/sh_bios.c * C interface for trapping into the standard LinuxSH BIOS. * diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 42868fca4..469698610 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -16,10 +16,10 @@ #include #include #include -#include #include #include #include +#include extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); @@ -87,6 +87,8 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(__div64_32); + #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name) /* These symbols are generated by the compiler itself */ @@ -98,8 +100,9 @@ DECLARE_EXPORT(__ashldi3); DECLARE_EXPORT(__lshrdi3); DECLARE_EXPORT(__movstr); +EXPORT_SYMBOL_NOVERS(strcpy); + #ifdef CONFIG_CPU_SH4 - DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); @@ -110,6 +113,14 @@ EXPORT_SYMBOL(flush_cache_range); EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(__flush_purge_region); #endif + +#if defined(CONFIG_SH7705_CACHE_32KB) +EXPORT_SYMBOL(flush_cache_all); +EXPORT_SYMBOL(flush_cache_range); +EXPORT_SYMBOL(flush_dcache_page); +EXPORT_SYMBOL(__flush_purge_region); +#endif + EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(__down_trylock); @@ -118,4 +129,6 @@ EXPORT_SYMBOL(synchronize_irq); #endif EXPORT_SYMBOL(csum_partial); +EXPORT_SYMBOL(csum_ipv6_magic); EXPORT_SYMBOL(consistent_sync); +EXPORT_SYMBOL(clear_page); diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index ccee2eca5..a758053c6 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $ +/* $Id: signal.c,v 1.21 2004/06/28 13:18:44 doyu Exp $ * * linux/arch/sh/kernel/signal.c * @@ -155,7 +155,7 @@ struct rt_sigframe u16 retcode[8]; }; -#ifdef CONFIG_CPU_SH4 +#ifdef CONFIG_SH_FPU static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) { struct task_struct *tsk = current; @@ -192,7 +192,7 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, sizeof(long)*(16*2+2)); } -#endif /* CONFIG_CPU_SH4 */ +#endif /* CONFIG_SH_FPU */ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p) @@ -213,7 +213,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p COPY(sr); COPY(pc); #undef COPY -#ifdef CONFIG_CPU_SH4 +#ifdef CONFIG_SH_FPU if (cpu_data->flags & CPU_HAS_FPU) { int owned_fp; struct task_struct *tsk = current; @@ -326,7 +326,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, COPY(sr); COPY(pc); #undef COPY -#ifdef CONFIG_CPU_SH4 +#ifdef CONFIG_SH_FPU err |= save_sigcontext_fpu(sc, regs); #endif @@ -413,9 +413,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -490,21 +488,17 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* * OK, we're invoking a handler - */ + */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Are we from a system call? */ if (regs->tra >= 0) { /* If so, check system call restarting.. */ @@ -574,6 +568,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -592,10 +587,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index adb8eae9f..6ff83edf8 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -98,19 +97,12 @@ void __devinit smp_prepare_boot_cpu(void) int __cpu_up(unsigned int cpu) { struct task_struct *tsk; - struct pt_regs regs; - memset(®s, 0, sizeof(struct pt_regs)); - tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, 0, 0); + tsk = fork_idle(cpu); if (IS_ERR(tsk)) panic("Failed forking idle task for cpu %d\n", cpu); - wake_up_forked_process(tsk); - - init_idle(tsk, cpu); - unhash_process(tsk); - tsk->thread_info->cpu = cpu; cpu_set(cpu, cpu_online_map); diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 3bcdf4ca4..149803d26 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -1,6 +1,5 @@ -/* $Id: time.c,v 1.21 2004/04/21 00:09:15 lethal Exp $ - * - * linux/arch/sh/kernel/time.c +/* + * arch/sh/kernel/time.c * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf @@ -24,6 +23,7 @@ #include #include #include +#include #include #include @@ -95,8 +95,8 @@ EXPORT_SYMBOL(jiffies_64); void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday; int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday; #else -void (*rtc_get_time)(struct timespec *) = 0; -int (*rtc_set_time)(const time_t) = 0; +void (*rtc_get_time)(struct timespec *); +int (*rtc_set_time)(const time_t); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) @@ -112,12 +112,21 @@ static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 }; static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; #elif defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SUBTYPE_SH73180) +static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; +static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +#define bfc_divisors ifc_divisors /* Same */ +#define bfc_values ifc_values +#define pfc_divisors ifc_divisors /* Same */ +#define pfc_values ifc_values +#else static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 }; #define bfc_divisors ifc_divisors /* Same */ #define bfc_values ifc_values static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 }; +#endif #else #error "Unknown ifc/bfc/pfc/stc values for this processor" #endif @@ -139,7 +148,7 @@ static unsigned long do_gettimeoffset(void) static unsigned long jiffies_p = 0; /* - * cache volatile jiffies temporarily; we have IRQs turned off. + * cache volatile jiffies temporarily; we have IRQs turned off. */ unsigned long jiffies_t; @@ -147,7 +156,7 @@ static unsigned long do_gettimeoffset(void) /* timer count may underflow right here */ count = ctrl_inl(TMU0_TCNT); /* read the latched count */ - jiffies_t = jiffies; + jiffies_t = jiffies; /* * avoiding timer inconsistencies (they are rare, but they happen)... @@ -161,7 +170,7 @@ static unsigned long do_gettimeoffset(void) if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ /* - * We cannot detect lost timer interrupts ... + * We cannot detect lost timer interrupts ... * well, that's why we call them lost, don't we? :) * [hmm, on the Pentium and Alpha we can ... sort of] */ @@ -191,7 +200,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin(&xtime_lock); usec = do_gettimeoffset(); - + lost = jiffies - wall_jiffies; if (lost) usec += lost * (1000000 / HZ); @@ -250,36 +259,6 @@ EXPORT_SYMBOL(do_settimeofday); /* last time the RTC clock got updated */ static long last_rtc_update; -/* Profiling definitions */ -extern unsigned long prof_cpu_mask; -extern unsigned int * prof_buffer; -extern unsigned long prof_len; -extern unsigned long prof_shift; -extern char _stext; - -static inline void sh_do_profile(unsigned long pc) -{ - /* Don't profile cpu_idle.. */ - if (!prof_buffer || !current->pid) - return; - - if (pc >= 0xa0000000UL && pc < 0xc0000000UL) - pc -= 0x20000000; - - pc -= (unsigned long)&_stext; - pc >>= prof_shift; - - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - - atomic_inc((atomic_t *)&prof_buffer[pc]); -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -287,9 +266,10 @@ static inline void sh_do_profile(unsigned long pc) static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_timer(regs); - - if (!user_mode(regs)) - sh_do_profile(regs->pc); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + profile_tick(CPU_PROFILING, regs); #ifdef CONFIG_HEARTBEAT if (sh_mv.mv_heartbeat != NULL) @@ -394,8 +374,8 @@ static unsigned int __init get_timer_frequency(void) return freq * factor; } -void (*board_time_init)(void) = 0; -void (*board_timer_setup)(struct irqaction *irq) = 0; +void (*board_time_init)(void); +void (*board_timer_setup)(struct irqaction *irq); static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ; @@ -439,10 +419,16 @@ void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsign *pfc = pfc_divisors[tmp]; #endif #elif defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SUBTYPE_SH73180) + *ifc = ifc_divisors[(frqcr>> 20) & 0x0007]; + *bfc = bfc_divisors[(frqcr>> 12) & 0x0007]; + *pfc = pfc_divisors[frqcr & 0x0007]; +#else *ifc = ifc_divisors[(frqcr >> 6) & 0x0007]; *bfc = bfc_divisors[(frqcr >> 3) & 0x0007]; *pfc = pfc_divisors[frqcr & 0x0007]; #endif +#endif } /* @@ -450,7 +436,7 @@ void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsign * the divisors and the physical values. */ #define _FREQ_TABLE(x) \ - unsigned int get_##x##_divisor(unsigned int value) \ + unsigned int get_##x##_divisor(unsigned int value) \ { return x##_divisors[value]; } \ \ unsigned int get_##x##_value(unsigned int divisor) \ @@ -462,109 +448,120 @@ _FREQ_TABLE(pfc); #ifdef CONFIG_CPU_SUBTYPE_ST40STB1 -/* The ST40 divisors are totally different so we set the cpu data -** clocks using a different algorithm -** -** I've just plugged this from the 2.4 code - Alex Bennee -*/ +/* + * The ST40 divisors are totally different so we set the cpu data + * clocks using a different algorithm + * + * I've just plugged this from the 2.4 code + * - Alex Bennee + */ #define CCN_PVR_CHIP_SHIFT 24 #define CCN_PVR_CHIP_MASK 0xff #define CCN_PVR_CHIP_ST40STB1 0x4 struct frqcr_data { - unsigned short frqcr; - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; + unsigned short frqcr; + + struct { + unsigned char multiplier; + unsigned char divisor; + } factor[3]; }; static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, + { 0x000, {{1,1}, {1,1}, {1,2}}}, + { 0x002, {{1,1}, {1,1}, {1,4}}}, + { 0x004, {{1,1}, {1,1}, {1,8}}}, + { 0x008, {{1,1}, {1,2}, {1,2}}}, + { 0x00A, {{1,1}, {1,2}, {1,4}}}, + { 0x00C, {{1,1}, {1,2}, {1,8}}}, + { 0x011, {{1,1}, {2,3}, {1,6}}}, + { 0x013, {{1,1}, {2,3}, {1,3}}}, + { 0x01A, {{1,1}, {1,2}, {1,4}}}, + { 0x01C, {{1,1}, {1,2}, {1,8}}}, + { 0x023, {{1,1}, {2,3}, {1,3}}}, + { 0x02C, {{1,1}, {1,2}, {1,8}}}, + { 0x048, {{1,2}, {1,2}, {1,4}}}, + { 0x04A, {{1,2}, {1,2}, {1,6}}}, + { 0x04C, {{1,2}, {1,2}, {1,8}}}, + { 0x05A, {{1,2}, {1,3}, {1,6}}}, + { 0x05C, {{1,2}, {1,3}, {1,6}}}, + { 0x063, {{1,2}, {1,4}, {1,4}}}, + { 0x06C, {{1,2}, {1,4}, {1,8}}}, + { 0x091, {{1,3}, {1,3}, {1,6}}}, + { 0x093, {{1,3}, {1,3}, {1,6}}}, + { 0x0A3, {{1,3}, {1,6}, {1,6}}}, + { 0x0DA, {{1,4}, {1,4}, {1,8}}}, + { 0x0DC, {{1,4}, {1,4}, {1,8}}}, + { 0x0EC, {{1,4}, {1,8}, {1,8}}}, + { 0x123, {{1,4}, {1,4}, {1,8}}}, + { 0x16C, {{1,4}, {1,8}, {1,8}}}, }; struct memclk_data { - unsigned char multiplier; - unsigned char divisor; + unsigned char multiplier; + unsigned char divisor; }; + static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 + {1,1}, // 000 + {1,2}, // 001 + {1,3}, // 010 + {2,3}, // 011 + {1,4}, // 100 + {1,6}, // 101 + {1,8}, // 110 + {1,8} // 111 }; static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr) { - unsigned int cpu_clock, master_clock, bus_clock, memory_clock; - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; - - for (a=0; afrqcr == (frqcr & 0x1ff)) - break; - } - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; - printk("ERROR: Unrecognised FRQCR value (0x%x), using default multipliers\n",frqcr); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - master_clock = module_clock * d->factor[2].divisor / d->factor[2].multiplier; - bus_clock = master_clock * d->factor[1].multiplier / d->factor[1].divisor; - memory_clock = master_clock * e->multiplier / e->divisor; - cpu_clock = master_clock * d->factor[0].multiplier / d->factor[0].divisor; - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.memory_clock = memory_clock; - current_cpu_data.module_clock = module_clock; + unsigned int cpu_clock, master_clock, bus_clock, memory_clock; + struct frqcr_data *d; + int a; + unsigned long memclkcr; + struct memclk_data *e; -} + for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) { + d = &st40_frqcr_table[a]; + + if (d->frqcr == (frqcr & 0x1ff)) + break; + } + if (a == ARRAY_SIZE(st40_frqcr_table)) { + d = st40_frqcr_table; + + printk("ERROR: Unrecognised FRQCR value (0x%x), " + "using default multipliers\n", frqcr); + } + + memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); + e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; + + printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d " + "Mem: %d/%d Periph: %d/%d\n", + d->factor[0].multiplier, d->factor[0].divisor, + d->factor[1].multiplier, d->factor[1].divisor, + e->multiplier, e->divisor, + d->factor[2].multiplier, d->factor[2].divisor); + + master_clock = module_clock * d->factor[2].divisor + / d->factor[2].multiplier; + bus_clock = master_clock * d->factor[1].multiplier + / d->factor[1].divisor; + memory_clock = master_clock * e->multiplier + / e->divisor; + cpu_clock = master_clock * d->factor[0].multiplier + / d->factor[0].divisor; + + current_cpu_data.cpu_clock = cpu_clock; + current_cpu_data.master_clock = master_clock; + current_cpu_data.bus_clock = bus_clock; + current_cpu_data.memory_clock = memory_clock; + current_cpu_data.module_clock = module_clock; +} #endif void __init time_init(void) @@ -580,7 +577,6 @@ void __init time_init(void) if (board_time_init) board_time_init(); - /* * If we don't have an RTC (such as with the SH7300), don't attempt to * probe the timer frequency. Rely on an either hardcoded peripheral @@ -595,15 +591,10 @@ void __init time_init(void) { unsigned int freq; - /* + /* * If we've specified a peripheral clock frequency, and we have * an RTC, compare it against the autodetected value. Complain * if there's a mismatch. - * - * Note: We should allow for some high and low watermarks for - * the frequency here (compensating for potential drift), as - * otherwise we'll likely end up triggering this essentially - * on every boot. */ timer_freq = get_timer_frequency(); freq = timer_freq * 4; @@ -618,20 +609,22 @@ void __init time_init(void) #endif #ifdef CONFIG_CPU_SUBTYPE_ST40STB1 + /* XXX: Update ST40 code to use board_time_init() */ pvr = ctrl_inl(CCN_PVR); frqcr = ctrl_inw(FRQCR); printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr); - if (((pvr >>CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) - st40_specific_time_init(current_cpu_data.module_clock, frqcr); + + if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) + st40_specific_time_init(current_cpu_data.module_clock, frqcr); else #endif - get_current_frequency_divisors(&ifc, &bfc, &pfc); + get_current_frequency_divisors(&ifc, &bfc, &pfc); - if (rtc_get_time) + if (rtc_get_time) { rtc_get_time(&xtime); - else { - xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0); - xtime.tv_nsec = 0; + } else { + xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0); + xtime.tv_nsec = 0; } set_normalized_timespec(&wall_to_monotonic, @@ -644,9 +637,9 @@ void __init time_init(void) } /* - ** for ST40 chips the current_cpu_data should already be set - ** so not having valid pfc/bfc/ifc shouldn't be a problem - */ + * for ST40 chips the current_cpu_data should already be set + * so not having valid pfc/bfc/ifc shouldn't be a problem + */ if (!current_cpu_data.master_clock) current_cpu_data.master_clock = current_cpu_data.module_clock * pfc; if (!current_cpu_data.bus_clock) @@ -668,11 +661,8 @@ void __init time_init(void) printk("Module clock: %d.%02dMHz\n", (current_cpu_data.module_clock / 1000000), (current_cpu_data.module_clock % 1000000)/10000); -#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D) - interval = ((current_cpu_data.module_clock/4 + HZ/2) / HZ) - 1; -#else + interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ; -#endif printk("Interval = %ld\n", interval); diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index da5721f4a..7eb06719d 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -438,7 +438,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x0F00: /* bf/s lab */ ret = handle_unaligned_delayslot(regs); if (ret==0) { -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) != 0) regs->pc += 4; /* next after slot */ else @@ -451,7 +451,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x0D00: /* bt/s lab */ ret = handle_unaligned_delayslot(regs); if (ret==0) { -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) == 0) regs->pc += 4; /* next after slot */ else diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 923980741..51bdc1cf7 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -23,6 +23,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } = 0x0009 @@ -75,9 +76,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index 3ed8e7cda..b5681e3f9 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -2,6 +2,12 @@ # Makefile for SuperH-specific library files.. # -lib-y = delay.o memcpy.o memset.o memmove.o memchr.o \ +lib-y = delay.o memset.o memmove.o memchr.o \ checksum.o strcasecmp.o strlen.o div64.o udivdi3.o \ div64-generic.o + +memcpy-y := memcpy.o +memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o + +lib-y += $(memcpy-y) + diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 38e004cff..9489a1424 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -19,5 +19,7 @@ obj-y += $(mmu-y) ifdef CONFIG_MMU obj-$(CONFIG_CPU_SH3) += tlb-sh3.o obj-$(CONFIG_CPU_SH4) += tlb-sh4.o ioremap.o +obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o endif +obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o diff --git a/arch/sh/mm/cache-sh2.c b/arch/sh/mm/cache-sh2.c index ee5b452b1..2689cb24e 100644 --- a/arch/sh/mm/cache-sh2.c +++ b/arch/sh/mm/cache-sh2.c @@ -24,7 +24,7 @@ unsigned long __get_oc_addr(unsigned long set, unsigned long way) { unsigned long ccr; - + /* * On SH-2 the way bit isn't tracked in the address field * if we're doing address array access .. instead, we need @@ -48,25 +48,3 @@ unsigned long __get_oc_addr(unsigned long set, unsigned long way) return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); } -int __init detect_cpu_and_cache_system(void) -{ - /* - * For now, assume SH7604 .. fix this later. - */ - cpu_data->type = CPU_SH7604; - cpu_data->dcache.ways = 4; - cpu_data->dcache.way_shift = 6; - cpu_data->dcache.sets = 64; - cpu_data->dcache.entry_shift = 4; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - cpu_data->dcache.flags = 0; - - /* - * SH-2 doesn't have separate caches - */ - cpu_data->dcache.flags |= SH_CACHE_COMBINED; - cpu_data->icache = cpu_data->dcache; - - return 0; -} - diff --git a/arch/sh/mm/cache-sh3.c b/arch/sh/mm/cache-sh3.c index b03d5e441..838731fc6 100644 --- a/arch/sh/mm/cache-sh3.c +++ b/arch/sh/mm/cache-sh3.c @@ -1,9 +1,10 @@ -/* $Id: cache-sh3.c,v 1.9 2004/05/02 01:46:30 sugioka Exp $ - * - * linux/arch/sh/mm/cache-sh3.c +/* + * arch/sh/mm/cache-sh3.c * * Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. */ #include @@ -21,72 +22,6 @@ #include #include -int __init detect_cpu_and_cache_system(void) -{ - unsigned long addr0, addr1, data0, data1, data2, data3; - - jump_to_P2(); - /* - * Check if the entry shadows or not. - * When shadowed, it's 128-entry system. - * Otherwise, it's 256-entry system. - */ - addr0 = CACHE_OC_ADDRESS_ARRAY + (3 << 12); - addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12); - - /* First, write back & invalidate */ - data0 = ctrl_inl(addr0); - ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0); - data1 = ctrl_inl(addr1); - ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1); - - /* Next, check if there's shadow or not */ - data0 = ctrl_inl(addr0); - data0 ^= SH_CACHE_VALID; - ctrl_outl(data0, addr0); - data1 = ctrl_inl(addr1); - data2 = data1 ^ SH_CACHE_VALID; - ctrl_outl(data2, addr1); - data3 = ctrl_inl(addr0); - - /* Lastly, invaliate them. */ - ctrl_outl(data0&~SH_CACHE_VALID, addr0); - ctrl_outl(data2&~SH_CACHE_VALID, addr1); - - back_to_P1(); - - cpu_data->dcache.ways = 4; - cpu_data->dcache.entry_shift = 4; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - cpu_data->dcache.flags = 0; - - /* - * 7709A/7729 has 16K cache (256-entry), while 7702 has only - * 2K(direct) 7702 is not supported (yet) - */ - if (data0 == data1 && data2 == data3) { /* Shadow */ - cpu_data->dcache.way_incr = (1 << 11); - cpu_data->dcache.entry_mask = 0x7f0; - cpu_data->dcache.sets = 128; - cpu_data->type = CPU_SH7708; - - cpu_data->flags |= CPU_HAS_MMU_PAGE_ASSOC; - } else { /* 7709A or 7729 */ - cpu_data->dcache.way_incr = (1 << 12); - cpu_data->dcache.entry_mask = 0xff0; - cpu_data->dcache.sets = 256; - cpu_data->type = CPU_SH7729; - } - - /* - * SH-3 doesn't have separate caches - */ - cpu_data->dcache.flags |= SH_CACHE_COMBINED; - cpu_data->icache = cpu_data->dcache; - - return 0; -} - /* * Write back the dirty D-caches, but not invalidate them. * @@ -116,7 +51,7 @@ void __flush_wback_region(void *start, int size) addr = addrstart | (v & cpu_data->dcache.entry_mask); local_irq_save(flags); data = ctrl_inl(addr); - + if ((data & CACHE_PHYSADDR_MASK) == (p & CACHE_PHYSADDR_MASK)) { data &= ~SH_CACHE_UPDATED; diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index adb99d833..a877087d0 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -1,10 +1,13 @@ -/* $Id: cache-sh4.c,v 1.26 2004/02/19 12:47:24 lethal Exp $ - * - * linux/arch/sh/mm/cache-sh4.c +/* + * arch/sh/mm/cache-sh4.c * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt * Copyright (C) 2003 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ #include @@ -28,126 +31,6 @@ static void __flush_cache_4096_all_ex(unsigned long start); extern void __flush_dcache_all(void); static void __flush_dcache_all_ex(void); -int __init detect_cpu_and_cache_system(void) -{ - unsigned long pvr, prr, cvr; - unsigned long size; - - static unsigned long sizes[16] = { - [1] = (1 << 12), - [2] = (1 << 13), - [4] = (1 << 14), - [8] = (1 << 15), - [9] = (1 << 16) - }; - - pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; - prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; - cvr = (ctrl_inl(CCN_CVR)); - - /* - * Setup some sane SH-4 defaults for the icache - */ - cpu_data->icache.way_incr = (1 << 13); - cpu_data->icache.entry_shift = 5; - cpu_data->icache.entry_mask = 0x1fe0; - cpu_data->icache.sets = 256; - cpu_data->icache.ways = 1; - cpu_data->icache.linesz = L1_CACHE_BYTES; - - /* - * And again for the dcache .. - */ - cpu_data->dcache.way_incr = (1 << 14); - cpu_data->dcache.entry_shift = 5; - cpu_data->dcache.entry_mask = 0x3fe0; - cpu_data->dcache.sets = 512; - cpu_data->dcache.ways = 1; - cpu_data->dcache.linesz = L1_CACHE_BYTES; - - /* Set the FPU flag, virtually all SH-4's have one */ - cpu_data->flags |= CPU_HAS_FPU; - - /* - * Probe the underlying processor version/revision and - * adjust cpu_data setup accordingly. - */ - switch (pvr) { - case 0x205: - cpu_data->type = CPU_SH7750; - cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG; - break; - case 0x206: - cpu_data->type = CPU_SH7750S; - - /* - * FIXME: This is needed for 7750, but do we need it for the - * 7750S too? For now, assume we do.. -- PFM - */ - cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG; - - break; - case 0x1100: - cpu_data->type = CPU_SH7751; - break; - case 0x8000: - cpu_data->type = CPU_ST40RA; - break; - case 0x8100: - cpu_data->type = CPU_ST40GX1; - break; - case 0x700: - cpu_data->type = CPU_SH4_501; - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - - /* No FPU on the SH4-500 series.. */ - cpu_data->flags &= ~CPU_HAS_FPU; - break; - case 0x600: - cpu_data->type = CPU_SH4_202; - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - break; - case 0x500 ... 0x501: - switch (prr) { - case 0x10: cpu_data->type = CPU_SH7750R; break; - case 0x11: cpu_data->type = CPU_SH7751R; break; - case 0x50: cpu_data->type = CPU_SH7760; break; - } - - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; - - break; - default: - cpu_data->type = CPU_SH_NONE; - break; - } - - /* - * On anything that's not a direct-mapped cache, look to the CVR - * for I/D-cache specifics. - */ - if (cpu_data->icache.ways > 1) { - size = sizes[(cvr >> 20) & 0xf]; - cpu_data->icache.way_incr = size / cpu_data->icache.ways; - cpu_data->icache.sets = (size >> 6); - cpu_data->icache.entry_mask = - ((size / cpu_data->icache.ways) - (1 << 5)); - } - - if (cpu_data->dcache.ways > 1) { - size = sizes[(cvr >> 16) & 0xf]; - cpu_data->dcache.way_incr = size / cpu_data->dcache.ways; - cpu_data->dcache.sets = (size >> 6); - cpu_data->dcache.entry_mask = - ((size / cpu_data->dcache.ways) - (1 << 5)); - } - - return 0; -} - /* * SH-4 has virtually indexed and physically tagged cache. */ diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index 789bacf1a..1f7af0c73 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -78,4 +78,8 @@ void consistent_sync(void *vaddr, size_t size, int direction) BUG(); } } + +EXPORT_SYMBOL(consistent_alloc); +EXPORT_SYMBOL(consistent_free); EXPORT_SYMBOL(consistent_sync); + diff --git a/arch/sh/mm/extable.c b/arch/sh/mm/extable.c index 994d9280d..505ede7c2 100644 --- a/arch/sh/mm/extable.c +++ b/arch/sh/mm/extable.c @@ -1,5 +1,4 @@ -/* $Id: extable.c,v 1.3 2003/05/06 23:28:50 lethal Exp $ - * +/* * linux/arch/sh/mm/extable.c * Taken from: * linux/arch/i386/mm/extable.c diff --git a/arch/sh/mm/fault-nommu.c b/arch/sh/mm/fault-nommu.c index e757b2c18..34d4e0c68 100644 --- a/arch/sh/mm/fault-nommu.c +++ b/arch/sh/mm/fault-nommu.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 43a9e2689..7abba2161 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 7b49b6976..030008e1f 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -214,8 +214,8 @@ void __init paging_init(void) */ disable_mmu(); #endif - - free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/ mem_map = NODE_DATA(0)->node_mem_map; @@ -225,7 +225,7 @@ void __init paging_init(void) */ zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); + free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); #endif } diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index aaa8e871c..9f490c274 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -1,5 +1,4 @@ -/* $Id: ioremap.c,v 1.9 2004/02/25 04:59:10 lethal Exp $ - * +/* * arch/sh/mm/ioremap.c * * Re-map IO memory to kernel address space so that we can access it. diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index 318d1a529..7a0d5c10b 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -40,6 +39,16 @@ void update_mmu_cache(struct vm_area_struct * vma, if (vma && current->active_mm != vma->vm_mm) return; +#if defined(CONFIG_SH7705_CACHE_32KB) + struct page *page; + page = pte_page(pte); + if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); + } +#endif + local_irq_save(flags); /* Set PTEH register */ diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index 4b7a0bcdc..115b1b6be 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile index 2b68bb584..686738d4a 100644 --- a/arch/sh/oprofile/Makefile +++ b/arch/sh/oprofile/Makefile @@ -7,7 +7,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ timer_int.o ) profdrvr-y := op_model_null.o -profdrvr-$(CONFIG_SH_DREAMCAST) := op_model_dreamcast.o +profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750) := op_model_sh7750.o oprofile-y := $(DRIVER_OBJS) $(profdrvr-y) diff --git a/arch/sh/ramdisk/Makefile b/arch/sh/ramdisk/Makefile index a22d86bf0..99e1c6867 100644 --- a/arch/sh/ramdisk/Makefile +++ b/arch/sh/ramdisk/Makefile @@ -12,8 +12,9 @@ img := $(subst $(src)//,/,$(src)/$(img)) quiet_cmd_ramdisk = LD $@ define cmd_ramdisk - $(LD) -T $(src)/ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img) + $(LD) -T $(srctree)/$(src)/ld.script -b binary --oformat $(O_FORMAT) \ + -o $@ $(img) endef -$(obj)/ramdisk.o: $(img) $(src)/ld.script +$(obj)/ramdisk.o: $(img) $(srctree)/$(src)/ld.script $(call cmd,ramdisk) diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile index 268bf3efc..3c370a113 100644 --- a/arch/sh/tools/Makefile +++ b/arch/sh/tools/Makefile @@ -10,7 +10,6 @@ # Shamelessly cloned from ARM. # -include/asm-sh/machtypes.h: $(obj)/machgen.sh $(obj)/mach-types +include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types @echo ' Generating $@' - @$(CONFIG_SHELL) $(obj)/machgen.sh $(obj)/mach-types > $@ - + $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; } diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index faf6d9e38..0693fbd1f 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -8,6 +8,7 @@ SE SH_SOLUTION_ENGINE 7751SE SH_7751_SOLUTION_ENGINE 7300SE SH_7300_SOLUTION_ENGINE +73180SE SH_73180_SOLUTION_ENGINE 7751SYSTEMH SH_7751_SYSTEMH HP600 SH_HP600 HP620 SH_HP620 @@ -24,4 +25,7 @@ MPC1211 SH_MPC1211 SNAPGEAR SH_SECUREEDGE5410 HS7751RVOIP SH_HS7751RVOIP RTS7751R2D SH_RTS7751R2D +EDOSK7705 SH_EDOSK7705 +SH4202_MICRODEV SH_SH4202_MICRODEV +SH03 SH_SH03 diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig index 0ac5d418e..551ba9a20 100644 --- a/arch/sh64/Kconfig +++ b/arch/sh64/Kconfig @@ -263,58 +263,10 @@ source "fs/Kconfig" source "arch/sh64/oprofile/Kconfig" -menu "Kernel hacking" - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - 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. - -config EARLY_PRINTK - bool "Early SCIF console support" - -config DEBUG_KERNEL_WITH_GDB_STUB - bool "GDB Stub kernel debug" - -config SH64_PROC_TLB - bool "Debug: report TLB fill/purge activity through /proc/tlb" - depends on PROC_FS - -config SH64_PROC_ASIDS - bool "Debug: report ASIDs through /proc/asids" - depends on PROC_FS - -config SH64_SR_WATCH - bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" - -config SH_ALPHANUMERIC - bool "Enable debug outputs to on-board alphanumeric display" - -config SH_NO_BSS_INIT - bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)" - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - default y if KGDB - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it will give very useful debugging information. - If you don't debug the kernel, you can say N, but we may not be able - to solve problems without frame pointers. - -endmenu +source "arch/sh64/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/sh64/boot/compressed/Makefile b/arch/sh64/boot/compressed/Makefile index 3f6cbf017..9cd216718 100644 --- a/arch/sh64/boot/compressed/Makefile +++ b/arch/sh64/boot/compressed/Makefile @@ -12,7 +12,7 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz \ - head.o misc.o cache.o piggy.o vmlinux.lds.o + head.o misc.o cache.o piggy.o vmlinux.lds EXTRA_AFLAGS := -traditional @@ -25,7 +25,7 @@ OBJECTS := $(obj)/head.o $(obj)/misc.o $(obj)/cache.o ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000]) LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \ - -T $(obj)/../../kernel/vmlinux.lds.s \ + -T $(obj)/../../kernel/vmlinux.lds \ --no-warn-mismatch $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE @@ -41,6 +41,6 @@ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T OBJCOPYFLAGS += -R .empty_zero_page -$(obj)/piggy.o: $(obj)/vmlinux.lds.s $(obj)/vmlinux.bin.gz FORCE +$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE $(call if_changed,ld) diff --git a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c index bcf6385db..b0f138f54 100644 --- a/arch/sh64/kernel/irq.c +++ b/arch/sh64/kernel/irq.c @@ -30,9 +30,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -148,6 +148,7 @@ asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs) int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { int status; + int ret; status = 1; /* Force the "do bottom halves" bit */ @@ -155,8 +156,9 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * local_irq_enable(); do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) diff --git a/arch/sh64/kernel/irq_intc.c b/arch/sh64/kernel/irq_intc.c index 4062ae55e..43f88f3a7 100644 --- a/arch/sh64/kernel/irq_intc.c +++ b/arch/sh64/kernel/irq_intc.c @@ -20,12 +20,12 @@ #include #include #include +#include /* this includes also #include -#include /* this includes also #include #include diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c index c2b4f00e2..368cab7a9 100644 --- a/arch/sh64/kernel/pci_sh5.c +++ b/arch/sh64/kernel/pci_sh5.c @@ -48,12 +48,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } } - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); char * __init pcibios_setup(char *str) { @@ -522,7 +517,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) bus->resource[0]->flags |= IORESOURCE_IO; bus->resource[1]->flags |= IORESOURCE_MEM; - /* For now, propogate host limits to the bus; + /* For now, propagate host limits to the bus; * we'll adjust them later. */ #if 1 diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index f9e82274e..9f46fbcec 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -765,9 +765,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->regs[9] = 0; /* Set return value for child */ childregs->sr |= SR_FD; /* Invalidate FPU flag */ - /* From sh */ - p->set_child_tid = p->clear_child_tid = NULL; - p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; @@ -820,7 +817,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, { if (!newsp) newsp = pregs->regs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0); + return do_fork(clone_flags, newsp, pregs, 0, 0, 0); } /* @@ -862,8 +859,11 @@ asmlinkage int sys_execve(char *ufilename, char **uargv, (char __user * __user *)uargv, (char __user * __user *)uenvp, pregs); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); out: unlock_kernel(); @@ -901,7 +901,7 @@ unsigned long get_wchan(struct task_struct *p) */ pc = thread_saved_pc(p); -#if CONFIG_FRAME_POINTER +#ifdef CONFIG_FRAME_POINTER if (in_sh64_switch_to(pc)) { sh64_switch_to_fp = (long) p->thread.sp; /* r14 is saved at offset 4 in the sh64_switch_to frame */ diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 887e89a45..f27c696b3 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -257,7 +257,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); @@ -311,11 +311,8 @@ asmlinkage void syscall_trace(void) if (!(tsk->ptrace & PT_PTRACED)) return; - tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - tsk->state = TASK_STOPPED; - notify_parent(tsk, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c index 80712f1ef..36cd5de95 100644 --- a/arch/sh64/kernel/sh_ksyms.c +++ b/arch/sh64/kernel/sh_ksyms.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -59,17 +58,17 @@ EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(screen_info); #endif -EXPORT_SYMBOL_NOVERS(__down); -EXPORT_SYMBOL_NOVERS(__down_trylock); -EXPORT_SYMBOL_NOVERS(__up); -EXPORT_SYMBOL_NOVERS(__put_user_asm_l); -EXPORT_SYMBOL_NOVERS(__get_user_asm_l); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(strchr); -EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__put_user_asm_l); +EXPORT_SYMBOL(__get_user_asm_l); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(flush_dcache_page); @@ -78,7 +77,7 @@ EXPORT_SYMBOL(flush_dcache_page); extern void __sdivsi3(void); extern void __muldi3(void); extern void __udivsi3(void); -EXPORT_SYMBOL_NOVERS(__sdivsi3); -EXPORT_SYMBOL_NOVERS(__muldi3); -EXPORT_SYMBOL_NOVERS(__udivsi3); +EXPORT_SYMBOL(__sdivsi3); +EXPORT_SYMBOL(__muldi3); +EXPORT_SYMBOL(__udivsi3); diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c index 376b8998b..a848fbdb1 100644 --- a/arch/sh64/kernel/signal.c +++ b/arch/sh64/kernel/signal.c @@ -520,9 +520,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -628,9 +626,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c index 128bd22af..9d73104f6 100644 --- a/arch/sh64/kernel/time.c +++ b/arch/sh64/kernel/time.c @@ -298,37 +298,6 @@ static int set_rtc_time(unsigned long nowtime) /* last time the RTC clock got updated */ static long last_rtc_update = 0; -static inline void sh64_do_profile(struct pt_regs *regs) -{ - extern int _stext; - unsigned long pc; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - /* Don't profile cpu_idle.. */ - if (!prof_buffer || !current->pid) - return; - - pc = instruction_pointer(regs); - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - - /* - * Don't ignore out-of-bounds PC values silently, put them into the - * last histogram slot, so if present, they will show up as a sharp - * peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - - /* We could just be sloppy and not lock against a re-entry on this - increment, but the profiling code won't always be linked in anyway. */ - atomic_inc((atomic_t *)&prof_buffer[pc]); -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -340,8 +309,10 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg ctc_last_interrupt = (unsigned long) current_ctc; do_timer(regs); - - sh64_do_profile(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + profile_tick(CPU_PROFILING, regs); #ifdef CONFIG_HEARTBEAT { diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S index a3fba816b..7d9f7a633 100644 --- a/arch/sh64/kernel/vmlinux.lds.S +++ b/arch/sh64/kernel/vmlinux.lds.S @@ -59,6 +59,7 @@ SECTIONS *(.text64) *(.text..SHmedia32) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) #ifdef CONFIG_LITTLE_ENDIAN @@ -106,9 +107,6 @@ SECTIONS __setup_start = .; .init.setup : C_PHYS(.init.setup) { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : C_PHYS(__param) { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : C_PHYS(.initcall.init) { *(.initcall1.init) diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index b5ab4a88c..d1190b415 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include /* required by inline asm statements */ diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c index 17cdeb425..09cd9c879 100644 --- a/arch/sh64/mm/init.c +++ b/arch/sh64/mm/init.c @@ -122,8 +122,8 @@ void __init paging_init(void) * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA. */ zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN; - - free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/ mem_map = NODE_DATA(0)->node_mem_map; diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c index a69f7751c..69f686c88 100644 --- a/arch/sh64/mm/tlbmiss.c +++ b/arch/sh64/mm/tlbmiss.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include /* required by inline asm statements */ diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 7d0688aa6..020de327e 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -23,11 +23,11 @@ config GENERIC_ISA_DMA source "init/Kconfig" - -menu "General setup" +menu "General machine setup" config VT bool + select INPUT default y ---help--- If you say Y here, you will get support for terminal devices with @@ -86,8 +86,8 @@ config SMP depends on BROKEN ---help--- This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. If you say N here, the kernel will run on single and multiprocessor machines, but will use only one CPU of a multiprocessor machine. If @@ -95,17 +95,11 @@ config SMP singleprocessor machines. On a singleprocessor machine, the kernel will run faster if you say N here. - Note that if you say Y here and choose architecture "586" or - "Pentium" under "Processor family", the kernel will not work on 486 - architectures. Similarly, multiprocessor kernels for the "PPro" - architecture may not work on all Pentium based boards. - People using multiprocessor machines who say Y here should also say Y to "Enhanced Real Time Clock Support", below. The "Advanced Power Management" code will be disabled if you say Y here. See also the , - , and the SMP-HOWTO available at . @@ -189,10 +183,10 @@ config SERIAL_CONSOLE (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) + your boot loader (silo) about how to pass options to the kernel at + boot time.) - If you don't have a VGA card installed and you say Y here, the + If you don't have a graphics card installed and you say Y here, the kernel will automatically use the first serial line, /dev/ttyS0, as system console. @@ -217,12 +211,13 @@ config SUN_PM bool default y help - Enable power management and CPU standby features on supported - SPARC platforms. + Enable power management and CPU standby features on supported + SPARC platforms. config SUN4 bool "Support for SUN4 machines (disables SUN4[CDM] support)" depends on !SMP + default n help Say Y here if, and only if, your machine is a sun4. Note that a kernel compiled with this option will run only on sun4. @@ -249,7 +244,10 @@ config SUN_OPENPROMFS -t openpromfs none /proc/openprom". To compile the /proc/openprom support as a module, choose M here: the - module will be called openpromfs. If unsure, choose M. + module will be called openpromfs. + + Only choose N if you know in advance that you will not need to modify + OpenPROM settings on the running system. source "fs/Kconfig.binfmt" @@ -282,9 +280,9 @@ config PRINTER If you have several parallel ports, you can specify which ports to use with the "lp" kernel command line option. (Try "man bootparam" - or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time.) The syntax of the - "lp" command line option can be found in . + or see the documentation of your boot loader (silo) about how to pass + options to the kernel at boot time.) The syntax of the "lp" command + line option can be found in . If you have more than 8 printers, you need to increase the LP_NO macro in lp.c and the PARPORT_MAX macro in parport.h. @@ -380,81 +378,10 @@ source "drivers/usb/Kconfig" source "drivers/char/watchdog/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_HIGHMEM - bool "Highmem debugging" - depends on DEBUG_KERNEL && HIGHMEM - help - This options enables additional error checking for high memory - systems. Disable for production systems. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - depends on DEBUG_KERNEL - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting (adds 70K)" - depends on DEBUG_KERNEL - help - 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. - -endmenu +source "arch/sparc/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 15fcf89e1..7b3bbaf08 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -13,7 +13,7 @@ AS := $(AS) -32 LDFLAGS := -m elf32_sparc -CHECK := $(CHECK) -D__sparc__=1 +CHECKFLAGS += -D__sparc__ #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index b19cc8689..b36508431 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -7,28 +7,52 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -host-progs := piggyback btfixupprep -targets := tftpboot.img btfix.o btfix.s image +hostprogs-y := piggyback btfixupprep +targets := tftpboot.img btfix.o btfix.S image quiet_cmd_elftoaout = ELFTOAOUT $@ cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ -quiet_cmd_piggy = PIGGY $@ +quiet_cmd_piggy = PIGGY $@ cmd_piggy = $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG) -quiet_cmd_btfix = BTFIX $@ +quiet_cmd_btfix = BTFIX $@ cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ +quiet_cmd_sysmap = SYSMAP $(obj)/System.map + cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap +quiet_cmd_image = LD $@ + cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@ + +define rule_image + $(if $($(quiet)cmd_image), \ + echo ' $($(quiet)cmd_image)' &&) \ + $(cmd_image); \ + $(if $($(quiet)cmd_sysmap), \ + echo ' $($(quiet)cmd_sysmap)' &&) \ + $(cmd_sysmap) $@ $(obj)/System.map; \ + if [ $$? -ne 0 ]; then \ + rm -f $@; \ + /bin/false; \ + fi; \ + echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd +endef BTOBJS := $(HEAD_Y) $(INIT_Y) BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y) -LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group $(kallsyms.o) +LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \ + --start-group $(BTLIBS) --end-group \ + $(kallsyms.o) $(obj)/btfix.o -# Actual linking +# Link the final image including btfixup'ed symbols. +# This is a replacement for the link done in the top-level Makefile. +# Note: No dependency on the prerequisite files since that would require +# make to try check if they are updated - and due to changes +# in gcc options (path for example) this would result in +# these files being recompiled for each build. $(obj)/image: $(obj)/btfix.o FORCE - $(call if_changed,ld) - $(NM) $@ | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(obj)/System.map + $(call if_changed_rule,image) $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) -$(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE +$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE $(call if_changed,btfix) diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index fcf149e00..3d22ba2af 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds EXTRA_AFLAGS := -ansi diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index d01b6cc66..406dd94af 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -28,7 +28,7 @@ #define APC_OBPNAME "power-management" #define APC_DEVNAME "apc" -volatile static u8 *regs; +volatile static u8 __iomem *regs; static int apc_regsize; static int apc_no_idle __initdata = 0; @@ -70,7 +70,7 @@ void apc_swift_idle(void) static inline void apc_free(void) { - sbus_iounmap((unsigned long)regs, apc_regsize); + sbus_iounmap(regs, apc_regsize); } static int apc_open(struct inode *inode, struct file *f) @@ -155,9 +155,9 @@ sbus_done: } apc_regsize = sdev->reg_addrs[0].reg_size; - regs = (u8*) sbus_ioremap(&sdev->resource[0], 0, + regs = sbus_ioremap(&sdev->resource[0], 0, apc_regsize, APC_OBPNAME); - if(NULL == regs) { + if(!regs) { printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME); return -ENODEV; } diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index 44b6dd75e..4bb41a1a3 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c @@ -17,7 +17,7 @@ /* auxio_register is not static because it is referenced * in entry.S::floppy_tdone */ -unsigned long auxio_register = 0UL; +void __iomem *auxio_register = NULL; static spinlock_t auxio_lock = SPIN_LOCK_UNLOCKED; void __init auxio_probe(void) @@ -63,7 +63,7 @@ void __init auxio_probe(void) /* Fix the address on sun4m and sun4c. */ if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || sparc_cpu_model == sun4c) - auxio_register |= 3; + auxio_register += (3 - ((unsigned long)auxio_register & 3)); set_auxio(AUXIO_LED, 0); } diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 8ae7e5d3c..1754192c6 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -275,7 +275,7 @@ void __init ebus_init(void) } } - pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0); + pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0); if (!pdev) { return; } @@ -342,7 +342,7 @@ void __init ebus_init(void) } next_ebus: - pdev = pci_find_device(PCI_VENDOR_ID_SUN, + pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, pdev); if (!pdev) break; @@ -356,4 +356,6 @@ void __init ebus_init(void) ebus->next = 0; ++num_ebus; } + if (pdev) + pci_dev_put(pdev); } diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 14a4b9593..b448166f5 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -38,7 +38,7 @@ #define curptr g6 -#define NR_SYSCALLS 283 /* Each OS is different... */ +#define NR_SYSCALLS 284 /* Each OS is different... */ /* These are just handy. */ #define _SV save %sp, -STACKFRAME_SZ, %sp @@ -858,7 +858,7 @@ vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG .globl invalid_segment_patch1, invalid_segment_patch2 - .globl num_context_patch1, num_context_patch2 + .globl num_context_patch1 .globl vac_linesize_patch, vac_hwflush_patch1 .globl vac_hwflush_patch2 @@ -1508,7 +1508,7 @@ syscall_is_too_hard: .globl ret_sys_call ret_sys_call: ld [%curptr + TI_FLAGS], %l6 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 set PSR_C, %g2 bgeu 1f @@ -1587,7 +1587,7 @@ solaris_syscall: st %o0, [%sp + STACKFRAME_SZ + PT_I0] set PSR_C, %g2 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu 1f ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 @@ -1678,7 +1678,7 @@ bsd_is_too_hard: st %o0, [%sp + STACKFRAME_SZ + PT_I0] set PSR_C, %g2 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu 1f ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index af81a999f..fc31de66b 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c @@ -23,6 +23,6 @@ EXPORT_SYMBOL(init_task); * in etrap.S which assumes it. */ union thread_union init_thread_union - __attribute__((section (".text,#alloc"))) + __attribute__((section (".text\"\n\t#"))) __attribute__((aligned (THREAD_SIZE))) = { INIT_THREAD_INFO(init_task) }; diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 5b4a0e194..21e4e6f84 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -47,8 +47,8 @@ struct resource *_sparc_find_resource(struct resource *r, unsigned long); -static void *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz); -static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, +static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz); +static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, unsigned long size, char *name); static void _sparc_free_io(struct resource *res); @@ -103,7 +103,7 @@ static void xres_free(struct xresource *xrp) { * * Bus type is always zero on IIep. */ -void *ioremap(unsigned long offset, unsigned long size) +void __iomem *ioremap(unsigned long offset, unsigned long size) { char name[14]; @@ -114,7 +114,7 @@ void *ioremap(unsigned long offset, unsigned long size) /* * Comlimentary to ioremap(). */ -void iounmap(void *virtual) +void iounmap(volatile void __iomem *virtual) { unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; struct resource *res; @@ -134,24 +134,24 @@ void iounmap(void *virtual) /* */ -unsigned long sbus_ioremap(struct resource *phyres, unsigned long offset, +void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset, unsigned long size, char *name) { - return (unsigned long) _sparc_alloc_io(phyres->flags & 0xF, + return _sparc_alloc_io(phyres->flags & 0xF, phyres->start + offset, size, name); } /* */ -void sbus_iounmap(unsigned long addr, unsigned long size) +void sbus_iounmap(volatile void __iomem *addr, unsigned long size) { - iounmap((void *)addr); + iounmap(addr); } /* * Meat of mapping */ -static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, +static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, unsigned long size, char *name) { static int printed_full; @@ -159,7 +159,7 @@ static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, struct resource *res; char *tack; int tlen; - void *va; /* P3 diag */ + void __iomem *va; /* P3 diag */ if (name == NULL) name = "???"; @@ -189,7 +189,7 @@ static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, /* */ -static void * +static void __iomem * _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz) { unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK); @@ -206,7 +206,7 @@ _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz) pa &= PAGE_MASK; sparc_mapiorange(bus, pa, res->start, res->end - res->start + 1); - return (void *) (res->start + offset); + return (void __iomem *) (res->start + offset); } /* diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index cfabf35ee..4e0ed320d 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index bc52cd482..f8ccbfc10 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -36,10 +36,6 @@ #include -struct pci_fixup pcibios_fixups[] = { - { 0 } -}; - unsigned int pcic_pin_to_irq(unsigned int pin, char *name); /* @@ -607,7 +603,7 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) */ void __init pcibios_fixup_bus(struct pci_bus *bus) { - struct list_head *walk; + struct pci_dev *dev; int i, has_io, has_mem; unsigned int cmd; struct linux_pcic *pcic; @@ -629,9 +625,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) return; } - walk = &bus->devices; - for (walk = walk->next; walk != &bus->devices; walk = walk->next) { - struct pci_dev *dev = pci_dev_b(walk); + list_for_each_entry(dev, &bus->devices, bus_list) { /* * Comment from i386 branch: @@ -720,6 +714,9 @@ static irqreturn_t pcic_timer_handler (int irq, void *h, struct pt_regs *regs) write_seqlock(&xtime_lock); /* Dummy, to show that we remember */ pcic_clear_clock_irq(); do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif write_sequnlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 869c2f13b..7eca8871f 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -30,7 +30,7 @@ #define PMC_IDLE_REG 0x00 #define PMC_IDLE_ON 0x01 -volatile static u8 *regs; +volatile static u8 __iomem *regs; static int pmc_regsize; #define pmc_readb(offs) (sbus_readb(regs+offs)) @@ -55,7 +55,7 @@ void pmc_swift_idle(void) static inline void pmc_free(void) { - sbus_iounmap((unsigned long)regs, pmc_regsize); + sbus_iounmap(regs, pmc_regsize); } static int __init pmc_probe(void) @@ -76,9 +76,9 @@ sbus_done: } pmc_regsize = sdev->reg_addrs[0].reg_size; - regs = (u8*) sbus_ioremap(&sdev->resource[0], 0, + regs = sbus_ioremap(&sdev->resource[0], 0, pmc_regsize, PMC_OBPNAME); - if(NULL == regs) { + if (!regs) { printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME); return -ENODEV; } diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 4ff019336..f07d01464 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -45,7 +45,7 @@ /* * Power management idle function - * Set in pm platform drivers + * Set in pm platform drivers (apc.c and pmc.c) */ void (*pm_idle)(void); @@ -122,7 +122,7 @@ int cpu_idle(void) } while((!need_resched()) && pm_idle) { - (*pm_idle)(); /* XXX Huh? On sparc?! */ + (*pm_idle)(); } schedule(); @@ -435,8 +435,6 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, { unsigned long parent_tid_ptr, child_tid_ptr; - clone_flags &= ~CLONE_IDLETASK; - parent_tid_ptr = regs->u_regs[UREG_I2]; child_tid_ptr = regs->u_regs[UREG_I4]; @@ -482,8 +480,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, #endif } - p->set_child_tid = p->clear_child_tid = NULL; - /* * p->thread_info new_stack childregs * ! ! ! {if(PSR_PS) } @@ -672,8 +668,11 @@ asmlinkage int sparc_execve(struct pt_regs *regs) (char __user * __user *)regs->u_regs[base + UREG_I2], regs); putname(filename); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } out: return error; } diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index d838bd8f6..62b8fd1db 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -567,7 +567,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) * exit. */ case PTRACE_KILL: { - if (child->state == TASK_ZOMBIE) { /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ pt_succ_return(regs, 0); goto out_tsk; } @@ -614,12 +614,9 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; current->thread.flags ^= MAGIC_CONSTANT; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 7bc43b4c0..55352ed85 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 28edf9319..7f677a39c 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -20,9 +20,9 @@ #include #include #include /* do_coredum */ +#include #include -#include #include #include #include @@ -274,7 +274,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs) return; segv_and_exit: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } asmlinkage void do_sigreturn(struct pt_regs *regs) @@ -341,7 +341,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) return; segv_and_exit: - send_sig(SIGSEGV, current, 1); + force_sig(SIGSEGV, current); } asmlinkage void do_rt_sigreturn(struct pt_regs *regs) @@ -401,7 +401,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) spin_unlock_irq(¤t->sighand->siglock); return; segv: - send_sig(SIGSEGV, current, 1); + force_sig(SIGSEGV, current); } /* Checks if the fp is valid */ @@ -549,7 +549,7 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old sigill_and_return: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signr, current); } @@ -635,6 +635,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; + regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 4. signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; @@ -662,7 +663,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, sigill_and_return: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signo, current); } static inline void @@ -719,6 +720,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; + regs->u_regs[UREG_I2] = (unsigned long) &sf->regs; regs->pc = (unsigned long) ka->sa.sa_handler; regs->npc = (regs->pc + 4); @@ -744,7 +746,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, sigill: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signo, current); } /* Setup a Solaris stack frame */ @@ -874,7 +876,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, sigill_and_return: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signr, current); } asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) @@ -887,7 +889,7 @@ asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) synchronize_user_stack(); if (current_thread_info()->w_saved) - goto sigsegv_and_return; + return -EFAULT; err = clear_user(uc, sizeof(*uc)); if (err) @@ -928,9 +930,6 @@ asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) * we have already stuffed all of it with sync_user_stack */ return (err ? -EFAULT : 0); - -sigsegv_and_return: - do_exit(SIGSEGV); } /* Set the context for a svr4 application, this is Solaris way to sigreturn */ @@ -1016,7 +1015,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) return (err ? -EFAULT : 0); sigsegv_and_return: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } static inline void @@ -1034,8 +1033,6 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, else setup_frame(&ka->sa, regs, signr, oldset, info); } - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -1075,6 +1072,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, { siginfo_t info; struct sparc_deliver_cookie cookie; + struct k_sigaction ka; int signr; /* @@ -1094,15 +1092,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart(cookie.orig_i0, regs, &ka->sa); - handle_signal(signr, ka, &info, oldset, regs, svr4_signal); + syscall_restart(cookie.orig_i0, regs, &ka.sa); + handle_signal(signr, &ka, &info, oldset, + regs, svr4_signal); return 1; } if (cookie.restart_syscall && diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 46591a15e..f11dd14db 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index fdaacfa47..7282bc3ee 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -214,6 +213,10 @@ EXPORT_SYMBOL(pci_dma_sync_single_for_cpu); EXPORT_SYMBOL(pci_dma_sync_single_for_device); EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu); EXPORT_SYMBOL(pci_dma_sync_sg_for_device); +EXPORT_SYMBOL(pci_map_sg); +EXPORT_SYMBOL(pci_unmap_sg); +EXPORT_SYMBOL(pci_map_page); +EXPORT_SYMBOL(pci_unmap_page); /* Actually, ioremap/iounmap are not PCI specific. But it is ok for drivers. */ EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(iounmap); @@ -298,6 +301,9 @@ EXPORT_SYMBOL(csum_partial); /* Cache flushing. */ EXPORT_SYMBOL(sparc_flush_page_to_ram); +/* For when serial stuff is built as modules. */ +EXPORT_SYMBOL(sun_do_break); + EXPORT_SYMBOL(__ret_efault); EXPORT_SYMBOL(memcmp); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 9f659c2f4..1de4c8a39 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -201,18 +201,9 @@ void __init smp4d_boot_cpus(void) int no; /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - + p = fork_idle(i); cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - current_set[i] = p->thread_info; - - unhash_process(p); - for (no = 0; !cpu_find_by_instance(no, NULL, &mid) && mid != i; no++) ; @@ -418,8 +409,6 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait) panic("Bogon SMP message pass."); } -extern void sparc_do_profile(unsigned long pc, unsigned long o7); - void smp4d_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = hard_smp4d_processor_id(); @@ -437,8 +426,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) show_leds(cpu); } - if(!user_mode(regs)) - sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); + profile_tick(CPU_PROFILING, regs); if(!--prof_counter(cpu)) { int user = user_mode(regs); diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index f2fc64edc..100433e05 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #define IRQ_RESCHEDULE 13 @@ -173,18 +173,9 @@ void __init smp4m_boot_cpus(void) int timeout; /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - + p = fork_idle(i); cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - current_set[i] = p->thread_info; - - unhash_process(p); - /* See trampoline.S for details... */ entry += ((i-1) * 3); @@ -400,16 +391,13 @@ void smp4m_cross_call_irq(void) ccall_info.processors_out[i] = 1; } -extern void sparc_do_profile(unsigned long pc, unsigned long o7); - void smp4m_percpu_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); clear_profile_irq(cpu); - if(!user_mode(regs)) - sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); + profile_tick(CPU_PROFILING, regs); if(!--prof_counter(cpu)) { int user = user_mode(regs); diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index b248f0576..ad049c1f3 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -178,7 +178,7 @@ asmlinkage int sunos_brk(unsigned long brk) * Check against rlimit and stack.. */ retval = -ENOMEM; - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (brk - current->mm->end_code > rlim) diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index fd452a6d3..928ffeb0f 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -74,8 +74,8 @@ sys_call_table: /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink -/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall -/*280*/ .long sys_ni_syscall, sys_ni_syscall, sys_ni_syscall +/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid +/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -181,5 +181,6 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys /*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys #endif diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index bdec61be6..f0457026a 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL(jiffies_64); spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; enum sparc_clock_type sp_clock_typ; spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED; -unsigned long mstk48t02_regs = 0UL; +void __iomem *mstk48t02_regs = NULL; static struct mostek48t08 *mstk48t08_regs = NULL; static int set_rtc_mmss(unsigned long); static int sbus_do_settimeofday(struct timespec *tv); @@ -79,38 +79,26 @@ struct intersil *intersil_clock; #endif -static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; - -/* 32-bit Sparc specific profiling function. */ -void sparc_do_profile(unsigned long pc, unsigned long o7) +unsigned long profile_pc(struct pt_regs *regs) { - if(prof_buffer && current->pid) { - extern int _stext; - extern int __copy_user_begin, __copy_user_end; - extern int __atomic_begin, __atomic_end; - extern int __bzero_begin, __bzero_end; - extern int __bitops_begin, __bitops_end; - - if ((pc >= (unsigned long) &__copy_user_begin && - pc < (unsigned long) &__copy_user_end) || - (pc >= (unsigned long) &__atomic_begin && - pc < (unsigned long) &__atomic_end) || - (pc >= (unsigned long) &__bzero_begin && - pc < (unsigned long) &__bzero_end) || - (pc >= (unsigned long) &__bitops_begin && - pc < (unsigned long) &__bitops_end)) - pc = o7; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - - spin_lock(&ticker_lock); - if(pc < prof_len) - prof_buffer[pc]++; - else - prof_buffer[prof_len - 1]++; - spin_unlock(&ticker_lock); - } + extern char __copy_user_begin[], __copy_user_end[]; + extern char __atomic_begin[], __atomic_end[]; + extern char __bzero_begin[], __bzero_end[]; + extern char __bitops_begin[], __bitops_end[]; + + unsigned long pc = regs->pc; + + if (in_lock_functions(pc) || + (pc >= (unsigned long) __copy_user_begin && + pc < (unsigned long) __copy_user_end) || + (pc >= (unsigned long) __atomic_begin && + pc < (unsigned long) __atomic_end) || + (pc >= (unsigned long) __bzero_begin && + pc < (unsigned long) __bzero_end) || + (pc >= (unsigned long) __bitops_begin && + pc < (unsigned long) __bitops_end)) + pc = regs->u_regs[UREG_RETPC]; + return pc; } __volatile__ unsigned int *master_l10_counter; @@ -129,8 +117,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) static long last_rtc_update; #ifndef CONFIG_SMP - if(!user_mode(regs)) - sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]); + profile_tick(CPU_PROFILING, regs); #endif /* Protect counter clear so that do_gettimeoffset works */ @@ -147,6 +134,10 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) clear_clock_irq(); do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + /* Determine when to update the Mostek clock. */ if ((time_status & STA_UNSYNC) == 0 && @@ -359,7 +350,7 @@ static __inline__ void clock_probe(void) mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0, sizeof(struct mostek48t08), "mk48t08"); - mstk48t02_regs = (unsigned long)&mstk48t08_regs->regs; + mstk48t02_regs = &mstk48t08_regs->regs; } else { prom_printf("CLOCK: Unknown model name '%s'\n",model); prom_halt(); diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 8d4bbfaf3..38938d2e6 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -13,6 +13,7 @@ SECTIONS { *(.text) SCHED_TEXT + LOCK_TEXT *(.gnu.warning) } =0 _etext = .; @@ -46,9 +47,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index f375c8e36..1e711bb66 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c @@ -10,9 +10,9 @@ */ #include +#include #include -#include /** * bit_map_string_get - find and set a bit string in bit map. diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c index 6d2febb04..f4c6851b5 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic.c @@ -41,7 +41,7 @@ static inline void forget_pte(pte_t page) #endif } -/* Remap IO memory, the same way as remap_page_range(), but use +/* Remap IO memory, the same way as remap_pfn_range(), but use * the obio memory space. * * They use a pgprot that sets PAGE_IO and does not check the diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 7eddc56b7..40b36f0b3 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -11,6 +11,7 @@ #include #include #include /* pte_offset_map => kmap_atomic */ +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index b661ca03a..cbc9dd799 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -173,6 +173,7 @@ static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus) } iommu_viking_flush_iotlb(iopte0, npages); + flush_cache_all(); // hack to fix dma errors with hypersparc return busa0; } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c18475eaa..b873e8421 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1341,7 +1341,7 @@ void __init srmmu_paging_init(void) zones_size[ZONE_HIGHMEM] = npages; zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, pfn_base, zholes_size); mem_map = contig_page_data.node_mem_map; } @@ -1463,6 +1463,7 @@ static void __init poke_hypersparc(void) static void __init init_hypersparc(void) { srmmu_name = "ROSS HyperSparc"; + srmmu_modtype = HyperSparc; init_vac_layout(); diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index b56b67b45..fd85c7b01 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -379,7 +379,7 @@ extern unsigned long invalid_segment_patch1, invalid_segment_patch1_ff; extern unsigned long invalid_segment_patch2, invalid_segment_patch2_ff; extern unsigned long invalid_segment_patch1_1ff, invalid_segment_patch2_1ff; extern unsigned long num_context_patch1, num_context_patch1_16; -extern unsigned long num_context_patch2, num_context_patch2_16; +extern unsigned long num_context_patch2_16; extern unsigned long vac_linesize_patch, vac_linesize_patch_32; extern unsigned long vac_hwflush_patch1, vac_hwflush_patch1_on; extern unsigned long vac_hwflush_patch2, vac_hwflush_patch2_on; @@ -2114,7 +2114,7 @@ void __init sun4c_paging_init(void) zones_size[ZONE_HIGHMEM] = npages; zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, pfn_base, zholes_size); mem_map = contig_page_data.node_mem_map; } diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 604428879..79f88cd36 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -12,10 +12,13 @@ config MMU bool default y -source "init/Kconfig" +config TIME_INTERPOLATION + bool + default y +source "init/Kconfig" -menu "General setup" +menu "General machine setup" config BBC_I2C tristate "UltraSPARC-III bootbus i2c controller driver" @@ -132,16 +135,7 @@ config NR_CPUS depends on SMP default "32" -config CPU_FREQ - bool "CPU Frequency scaling" - help - Clock scaling allows you to change the clock speed of CPUs on the - fly. Currently there are only sparc64 drivers for UltraSPARC-III - and UltraSPARC-IIe processors. - - For details, take a look at . - - If in doubt, say N. +source "drivers/cpufreq/Kconfig" config CPU_FREQ_TABLE tristate "CPU frequency table helpers" @@ -173,8 +167,6 @@ config US2E_FREQ If in doubt, say N. -source "drivers/cpufreq/Kconfig" - # Identify this as a Sparc64 build config SPARC64 bool @@ -549,7 +541,6 @@ config UNIX98_PTY_COUNT endmenu - menu "XFree86 DRI support" config DRM @@ -604,113 +595,10 @@ source "drivers/char/watchdog/Kconfig" source "arch/sparc64/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - depends DEBUG_KERNEL - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting (adds 70K)" - depends on DEBUG_KERNEL - help - 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. - -config DEBUG_DCFLUSH - bool "D-cache flush debugging" - depends on DEBUG_KERNEL - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config STACK_DEBUG - depends on DEBUG_KERNEL - bool "Stack Overflow Detection Support" - -config DEBUG_BOOTMEM - depends on DEBUG_KERNEL - bool "Debug BOOTMEM initialization" - -# We have a custom atomic_dec_and_lock() implementation but it's not -# compatible with spinlock debugging so we need to fall back on -# the generic version in that case. -config HAVE_DEC_LOCK - bool - depends on SMP && !DEBUG_SPINLOCK - default y - -config MCOUNT - bool - depends on STACK_DEBUG - default y - -config FRAME_POINTER - bool - depends on MCOUNT - default y - -endmenu +source "arch/sparc64/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index fc57c40c2..61724880f 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -8,16 +8,16 @@ # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) # -CHECK := $(CHECK) -D__sparc__=1 -D__sparc_v9__=1 +CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 -AFLAGS_vmlinux.lds.o += -Usparc +CPPFLAGS_vmlinux.lds += -Usparc CC := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi ) -NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) +NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow) NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; ) -INLINE_LIMIT := $(shell if $(CC) -m64 -finline-limit=100000 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) +INLINE_LIMIT := $(call cc-option-yn, -m64 -finline-limit=100000) export NEW_GCC diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile index 5eb14ff1c..6968a6da5 100644 --- a/arch/sparc64/boot/Makefile +++ b/arch/sparc64/boot/Makefile @@ -7,7 +7,7 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -host-progs := piggyback +hostprogs-y := piggyback targets := image tftpboot.img vmlinux.aout quiet_cmd_elftoaout = ELF2AOUT $@ diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 7fa2d47a6..a989a80f5 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,18 +1,23 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc3 +# Wed Dec 8 21:14:26 2004 # CONFIG_64BIT=y CONFIG_MMU=y +CONFIG_TIME_INTERPOLATION=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -21,6 +26,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=15 CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -28,11 +34,13 @@ CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -42,11 +50,12 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y # -# General setup +# General machine setup # CONFIG_BBC_I2C=m CONFIG_VT=y @@ -56,9 +65,7 @@ CONFIG_SMP=y # CONFIG_PREEMPT is not set CONFIG_NR_CPUS=4 CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=y -CONFIG_US3_FREQ=m -CONFIG_US2E_FREQ=m +# CONFIG_CPU_FREQ_DEBUG is not set CONFIG_CPU_FREQ_PROC_INTF=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set @@ -66,6 +73,10 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=m # CONFIG_CPU_FREQ_24_API is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_TABLE=y +CONFIG_US3_FREQ=m +CONFIG_US2E_FREQ=m CONFIG_SPARC64=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HUGETLB_PAGE_SIZE_4MB=y @@ -118,6 +129,8 @@ CONFIG_FW_LOADER=m # Graphics support # CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y # CONFIG_FB_CIRRUS is not set CONFIG_FB_PM2=y # CONFIG_FB_PM2_FIFO_DISCONNECT is not set @@ -133,8 +146,10 @@ CONFIG_FB_CG6=y # CONFIG_FB_ATY128 is not set CONFIG_FB_ATY=y CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_GX=y +# CONFIG_FB_ATY_GENERIC_LCD is not set # CONFIG_FB_ATY_XL_INIT is not set +CONFIG_FB_ATY_GX=y +# CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set @@ -153,7 +168,6 @@ CONFIG_FB_FFB=y # # Console display driver support # -# CONFIG_MDA_CONSOLE is not set # CONFIG_PROM_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y @@ -217,7 +231,21 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m # CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +CONFIG_CDROM_PKTCDVD_WCACHE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -236,7 +264,6 @@ CONFIG_BLK_DEV_IDETAPE=m # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y # # IDE chipset support/bugfixes @@ -251,7 +278,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_IDEDMA_ONLYDISK=y -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set @@ -328,8 +354,10 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000 # CONFIG_AIC79XX_DEBUG_ENABLE is not set CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -# CONFIG_SCSI_MEGARAID is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set CONFIG_SCSI_SATA=y +CONFIG_SCSI_SATA_AHCI=m CONFIG_SCSI_SATA_SVW=m CONFIG_SCSI_ATA_PIIX=m CONFIG_SCSI_SATA_NV=m @@ -337,12 +365,14 @@ CONFIG_SCSI_SATA_PROMISE=m CONFIG_SCSI_SATA_SX4=m CONFIG_SCSI_SATA_SIL=m CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m CONFIG_SCSI_SATA_VIA=m CONFIG_SCSI_SATA_VITESSE=m CONFIG_SCSI_DMX3191D=m CONFIG_SCSI_EATA_PIO=m # CONFIG_SCSI_FUTURE_DOMAIN is not set CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m CONFIG_SCSI_INIA100=m CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m @@ -353,9 +383,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -CONFIG_SCSI_IPR=m -# CONFIG_SCSI_IPR_TRACE is not set -# CONFIG_SCSI_IPR_DUMP is not set +# CONFIG_SCSI_IPR is not set CONFIG_SCSI_QLOGIC_ISP=m CONFIG_SCSI_QLOGIC_FC=y CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y @@ -398,9 +426,11 @@ CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=m CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m +# CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m @@ -412,7 +442,6 @@ CONFIG_DM_ZERO=m # CONFIG_FUSION=m CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m CONFIG_FUSION_CTL=m CONFIG_FUSION_LAN=m @@ -475,6 +504,9 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # # IP: Virtual Server Configuration @@ -514,6 +546,7 @@ CONFIG_IPV6_PRIVACY=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -523,6 +556,9 @@ CONFIG_BRIDGE_NETFILTER=y # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m CONFIG_IP_NF_TFTP=m @@ -548,8 +584,17 @@ CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_PHYSDEV=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -568,18 +613,15 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_CONNMARK=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m # # IPv6: Netfilter Configuration @@ -599,6 +641,7 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_AHESP=m CONFIG_IP6_NF_MATCH_LENGTH=m CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_PHYSDEV=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_MANGLE=m @@ -654,7 +697,6 @@ CONFIG_ATM_BR2684_IPFILTER=y CONFIG_BRIDGE=m CONFIG_VLAN_8021Q=m CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y CONFIG_DECNET_ROUTER=y CONFIG_DECNET_ROUTE_FWMARK=y CONFIG_LLC=m @@ -668,7 +710,6 @@ CONFIG_LAPB=m CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing @@ -704,6 +745,11 @@ CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_ACT=y CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m # # Network testing @@ -865,7 +911,6 @@ CONFIG_SUNDANCE=m CONFIG_SUNDANCE_MMIO=y CONFIG_VIA_RHINE=m # CONFIG_VIA_RHINE_MMIO is not set -CONFIG_VIA_VELOCITY=m # # Ethernet (1000 Mbit) @@ -880,7 +925,9 @@ CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m +CONFIG_R8169_NAPI=y CONFIG_SK98LIN=m +CONFIG_VIA_VELOCITY=m CONFIG_TIGON3=m # @@ -998,6 +1045,11 @@ CONFIG_ISDN_CAPI_CAPI20=m # Active AVM cards # CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m # # Active Eicon DIVA Server cards @@ -1064,6 +1116,7 @@ CONFIG_SERIO_I8042=y # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_RAW=m # # Input Device Drivers @@ -1095,6 +1148,7 @@ CONFIG_I2C_CHARDEV=m # CONFIG_I2C_ALGOBIT=y CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m # # I2C Hardware Bus support @@ -1103,6 +1157,7 @@ CONFIG_I2C_ALI1535=m CONFIG_I2C_ALI1563=m CONFIG_I2C_ALI15X3=m CONFIG_I2C_AMD756=m +# CONFIG_I2C_AMD756_S4882 is not set CONFIG_I2C_AMD8111=m CONFIG_I2C_I801=m CONFIG_I2C_I810=m @@ -1116,9 +1171,11 @@ CONFIG_SCx200_ACB=m CONFIG_I2C_SIS5595=m CONFIG_I2C_SIS630=m CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m CONFIG_I2C_VIA=m CONFIG_I2C_VIAPRO=m CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m # # Hardware Sensors Chip support @@ -1126,20 +1183,25 @@ CONFIG_I2C_VOODOO3=m CONFIG_I2C_SENSOR=m CONFIG_SENSORS_ADM1021=m CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m CONFIG_SENSORS_ADM1031=m CONFIG_SENSORS_ASB100=m CONFIG_SENSORS_DS1621=m CONFIG_SENSORS_FSCHER=m CONFIG_SENSORS_GL518SM=m CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m CONFIG_SENSORS_LM75=m CONFIG_SENSORS_LM77=m CONFIG_SENSORS_LM78=m CONFIG_SENSORS_LM80=m CONFIG_SENSORS_LM83=m CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m CONFIG_SENSORS_LM90=m CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SMSC47M1=m CONFIG_SENSORS_VIA686A=m CONFIG_SENSORS_W83781D=m CONFIG_SENSORS_W83L785TS=m @@ -1186,6 +1248,7 @@ CONFIG_MINIX_FS=m CONFIG_ROMFS_FS=m # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m @@ -1220,6 +1283,8 @@ CONFIG_DEVFS_MOUNT=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -1262,6 +1327,7 @@ CONFIG_EXPORTFS=m CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set CONFIG_CIFS=m @@ -1357,7 +1423,7 @@ CONFIG_VIDEO_SAA5249=m CONFIG_TUNER_3036=m # CONFIG_VIDEO_STRADIS is not set # CONFIG_VIDEO_ZORAN is not set -CONFIG_VIDEO_SAA7134=m +# CONFIG_VIDEO_SAA7134 is not set CONFIG_VIDEO_MXB=m CONFIG_VIDEO_DPC=m CONFIG_VIDEO_HEXIUM_ORION=m @@ -1378,26 +1444,6 @@ CONFIG_RADIO_MAESTRO=m CONFIG_DVB=y CONFIG_DVB_CORE=m -# -# Supported Frontend Modules -# -CONFIG_DVB_TWINHAN_DST=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_SP887X_FIRMWARE_FILE="/etc/dvb/sc_main.mc" -CONFIG_DVB_ALPS_TDLB7=m -CONFIG_DVB_ALPS_TDMB7=m -CONFIG_DVB_ATMEL_AT76C651=m -CONFIG_DVB_CX24110=m -CONFIG_DVB_GRUNDIG_29504_491=m -CONFIG_DVB_GRUNDIG_29504_401=m -CONFIG_DVB_MT312=m -CONFIG_DVB_VES1820=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_TDA1004X_FIRMWARE_FILE="/usr/lib/hotplug/firmware/tda1004x.bin" -CONFIG_DVB_NXT6000=m - # # Supported SAA7146 based PCI Adapters # @@ -1413,6 +1459,11 @@ CONFIG_DVB_BUDGET_PATCH=m # # CONFIG_DVB_TTUSB_BUDGET is not set CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_DIBUSB=m +CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235=y +CONFIG_DVB_DIBCOM_DEBUG=y +CONFIG_DVB_CINERGYT2=m +# CONFIG_DVB_CINERGYT2_TUNING is not set # # Supported FlexCopII (B2C2) Adapters @@ -1423,6 +1474,45 @@ CONFIG_DVB_B2C2_SKYSTAR=m # Supported BT878 Adapters # CONFIG_DVB_BT8XX=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA80XX=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_DIB3000MB=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_ATMEL_AT76C651=m +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_VIDEO_VIDEOBUF=m @@ -1473,11 +1563,13 @@ CONFIG_SND_VIRMIDI=m CONFIG_SND_AC97_CODEC=m CONFIG_SND_ALI5451=m CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m CONFIG_SND_AU8810=m CONFIG_SND_AU8820=m CONFIG_SND_AU8830=m CONFIG_SND_AZT3328=m CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set CONFIG_SND_CS46XX=m # CONFIG_SND_CS46XX_NEW_DSP is not set CONFIG_SND_CS4281=m @@ -1509,9 +1601,10 @@ CONFIG_SND_SONICVIBES=m CONFIG_SND_VX222=m # -# ALSA USB devices +# USB devices # # CONFIG_SND_USB_AUDIO is not set +CONFIG_SND_USB_USX2Y=m # # ALSA Sparc devices @@ -1531,6 +1624,9 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -1552,6 +1648,10 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_MIDI is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_RW_DETECT=y @@ -1565,7 +1665,7 @@ CONFIG_USB_STORAGE_SDDR55=y # CONFIG_USB_STORAGE_JUMPSHOT is not set # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y @@ -1596,14 +1696,13 @@ CONFIG_USB_HPUSBSCSI=m # CONFIG_USB_IBMCAM is not set # CONFIG_USB_KONICAWC is not set # CONFIG_USB_OV511 is not set -CONFIG_USB_PWC=m # CONFIG_USB_SE401 is not set CONFIG_USB_SN9C102=m # CONFIG_USB_STV680 is not set CONFIG_USB_W9968CF=m # -# USB Network adaptors +# USB Network Adapters # CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m @@ -1620,6 +1719,7 @@ CONFIG_USB_BELKIN=y CONFIG_USB_GENESYS=y CONFIG_USB_NET1080=y CONFIG_USB_PL2301=y +CONFIG_USB_KC2190=y # # Intelligent USB Devices/Gadgets @@ -1646,6 +1746,7 @@ CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_BELKIN=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CYPRESS_M8=m CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_FTDI_SIO=m # CONFIG_USB_SERIAL_VISOR is not set @@ -1653,6 +1754,7 @@ CONFIG_USB_SERIAL_IPAQ=m # CONFIG_USB_SERIAL_IR is not set CONFIG_USB_SERIAL_EDGEPORT=m # CONFIG_USB_SERIAL_EDGEPORT_TI is not set +CONFIG_USB_SERIAL_IPW=m CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m # CONFIG_USB_SERIAL_KEYSPAN_MPR is not set @@ -1689,10 +1791,16 @@ CONFIG_USB_LEGOTOWER=m CONFIG_USB_LCD=m CONFIG_USB_LED=m CONFIG_USB_CYTHERM=m -CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_PHIDGETKIT=m CONFIG_USB_PHIDGETSERVO=m CONFIG_USB_TEST=m +# +# USB ATM/DSL drivers +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m + # # USB Gadget Support # @@ -1733,14 +1841,17 @@ CONFIG_OPROFILE=m # Kernel hacking # CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_DCFLUSH is not set # CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_KPROBES=y +# CONFIG_DEBUG_DCFLUSH is not set # CONFIG_STACK_DEBUG is not set # CONFIG_DEBUG_BOOTMEM is not set CONFIG_HAVE_DEC_LOCK=y @@ -1748,6 +1859,8 @@ CONFIG_HAVE_DEC_LOCK=y # # Security options # +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY is not set # @@ -1761,6 +1874,7 @@ CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m @@ -1771,6 +1885,7 @@ CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 2caca47d8..093281bdf 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -5,7 +5,7 @@ EXTRA_AFLAGS := -ansi EXTRA_CFLAGS := -Werror -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y := process.o setup.o cpu.o idprom.o \ traps.o devices.o auxio.o \ @@ -22,6 +22,7 @@ obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o +obj-$(CONFIG_KPROBES) += kprobes.o ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos32.o sunos_ioctl32.o diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 24ecb1075..11672d2d3 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -17,7 +17,7 @@ #include /* This cannot be static, as it is referenced in entry.S */ -unsigned long auxio_register = 0UL; +void __iomem *auxio_register = 0UL; enum auxio_type { AUXIO_TYPE_NODEV, @@ -30,7 +30,7 @@ static spinlock_t auxio_lock = SPIN_LOCK_UNLOCKED; static void __auxio_sbus_set(u8 bits_on, u8 bits_off) { - if(auxio_register) { + if (auxio_register) { unsigned char regval; unsigned long flags; unsigned char newval; @@ -49,7 +49,7 @@ static void __auxio_sbus_set(u8 bits_on, u8 bits_off) static void __auxio_ebus_set(u8 bits_on, u8 bits_off) { - if(auxio_register) { + if (auxio_register) { unsigned char regval; unsigned long flags; unsigned char newval; @@ -126,7 +126,8 @@ found_sdev: if (sdev) { auxio_devtype = AUXIO_TYPE_SBUS; auxio_register = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, "auxiliaryIO"); + sdev->reg_addrs[0].reg_size, + "auxiliaryIO"); } #ifdef CONFIG_PCI else { @@ -142,7 +143,7 @@ found_sdev: ebus_done: if (edev) { auxio_devtype = AUXIO_TYPE_EBUS; - auxio_register = (unsigned long) + auxio_register = ioremap(edev->resource[0].start, sizeof(u32)); } } diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index 3dbf2660c..0cad0a432 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -102,12 +102,12 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file) /* If the size of the dump file exceeds the rlimit, then see what would happen if we wrote the stack, but not the data area. */ if ((dump.u_dsize+dump.u_ssize) > - current->rlim[RLIMIT_CORE].rlim_cur) + current->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; /* Make sure we have enough room to write the stack and data areas. */ if ((dump.u_ssize) > - current->rlim[RLIMIT_CORE].rlim_cur) + current->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; /* make sure we actually have a data and stack area to dump */ @@ -218,7 +218,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) * size limits imposed on them by creating programs with large * arrays in the data or bss. */ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ex.a_data + ex.a_bss > rlim) diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index a28046203..c13eaf030 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -27,12 +27,12 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ do { unsigned int *dest = &(__elf_regs[0]); \ struct pt_regs *src = (__pt_regs); \ - unsigned int *sp; \ + unsigned int __user *sp; \ int i; \ for(i = 0; i < 16; i++) \ dest[i] = (unsigned int) src->u_regs[i];\ /* Don't try this at home kids... */ \ - sp = (unsigned int *) (src->u_regs[14] & \ + sp = (unsigned int __user *) (src->u_regs[14] & \ 0x00000000fffffffc); \ for(i = 0; i < 16; i++) \ __get_user(dest[i+16], &sp[i]); \ @@ -79,7 +79,7 @@ typedef struct { #define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS)) -#define ELF_ET_DYN_BASE 0x08000000 +#define ELF_ET_DYN_BASE 0x70000000 #include diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 2296525af..97cf912f0 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -72,7 +72,7 @@ struct mctrl_info { struct obp_mem_layout layout_prop; int layout_size; - void *regs; + void __iomem *regs; u64 timing_control1; u64 timing_control2; diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 1462b2460..c4b705d0e 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -26,7 +26,7 @@ #define curptr g6 -#define NR_SYSCALLS 283 /* Each OS is different... */ +#define NR_SYSCALLS 284 /* Each OS is different... */ .text .align 32 @@ -1778,7 +1778,7 @@ ret_sys_call: stx %l0, [%curptr + TI_FLAGS] 1: - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f andcc %l0, _TIF_SYSCALL_TRACE, %l6 80: diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 9468eacdc..d50b755c7 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -17,7 +17,8 @@ #define TASK_REGOFF (THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ) #define ETRAP_PSTATE1 (PSTATE_RMO | PSTATE_PRIV) -#define ETRAP_PSTATE2 (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) +#define ETRAP_PSTATE2 \ + (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) /* * On entry, %g7 is return address - 0x4. @@ -27,91 +28,91 @@ .text .align 64 .globl etrap, etrap_irq, etraptl1 -etrap: rdpr %pil, %g2 ! Single Group +etrap: rdpr %pil, %g2 etrap_irq: - rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,pn %xcc, 1f ! CTI - sub %sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2 ! IEU1 - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - - sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group - sethi %hi(TSTATE_PEF), %g3 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - and %g1, %g3, %g3 ! IEU1 - brnz,pn %g3, 1f ! CTI+IEU1 Group - add %g6, %g2, %g2 ! IEU0 - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] ! Store Group - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] ! Store Group - rd %y, %g3 ! Single Group+4bubbles - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] ! Store Group - st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y] ! Store Group - save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group - mov %g6, %l6 ! IEU0 Group - - bne,pn %xcc, 3f ! CTI - mov PRIMARY_CONTEXT, %l4 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - mov 1, %l5 ! IEU1 - stb %l5, [%l6 + TI_FPDEPTH] ! Store - - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store Group - flush %l6 ! Single Group+9bubbles - wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles -2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles - mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - - mov %g7, %l2 ! IEU1 - wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles - stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] ! Store Group - stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] ! Store Group - stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] ! Store Group - stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] ! Store Group - stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] ! Store Group - stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] ! Store Group - - stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] ! Store Group - stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] ! Store Group - stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] ! Store Group - stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] ! Store Group - stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] ! Store Group - stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] ! Store Group - stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] ! Store Group - - stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] ! Store Group - stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] ! Store Group - wrpr %g0, ETRAP_PSTATE2, %pstate ! Single Group+4bubbles - mov %l6, %g6 ! IEU0 - jmpl %l2 + 0x4, %g0 ! CTI Group - ldx [%g6 + TI_TASK], %g4 ! Load + rdpr %tstate, %g1 + sllx %g2, 20, %g3 + andcc %g1, TSTATE_PRIV, %g0 + or %g1, %g3, %g1 + bne,pn %xcc, 1f + sub %sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2 + wrpr %g0, 7, %cleanwin + + sethi %hi(TASK_REGOFF), %g2 + sethi %hi(TSTATE_PEF), %g3 + or %g2, %lo(TASK_REGOFF), %g2 + and %g1, %g3, %g3 + brnz,pn %g3, 1f + add %g6, %g2, %g2 + wr %g0, 0, %fprs +1: rdpr %tpc, %g3 + + stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] + rdpr %tnpc, %g1 + stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] + rd %y, %g3 + stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] + st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y] + save %g2, -STACK_BIAS, %sp ! Ordering here is critical + mov %g6, %l6 + + bne,pn %xcc, 3f + mov PRIMARY_CONTEXT, %l4 + rdpr %canrestore, %g3 + rdpr %wstate, %g2 + wrpr %g0, 0, %canrestore + sll %g2, 3, %g2 + mov 1, %l5 + stb %l5, [%l6 + TI_FPDEPTH] + + wrpr %g3, 0, %otherwin + wrpr %g2, 0, %wstate + stxa %g0, [%l4] ASI_DMMU + flush %l6 + wr %g0, ASI_AIUS, %asi +2: wrpr %g0, 0x0, %tl + mov %g4, %l4 + mov %g5, %l5 + + mov %g7, %l2 + wrpr %g0, ETRAP_PSTATE1, %pstate + stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] + stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] + stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] + stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] + stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] + stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] + + stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] + stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] + stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] + stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] + stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] + stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] + stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] + + stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] + stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] + wrpr %g0, ETRAP_PSTATE2, %pstate + mov %l6, %g6 + jmpl %l2 + 0x4, %g0 + ldx [%g6 + TI_TASK], %g4 nop nop nop -3: ldub [%l6 + TI_FPDEPTH], %l5 ! Load Group - add %l6, TI_FPSAVED + 1, %l4 ! IEU0 - srl %l5, 1, %l3 ! IEU0 Group - add %l5, 2, %l5 ! IEU1 - stb %l5, [%l6 + TI_FPDEPTH] ! Store - ba,pt %xcc, 2b ! CTI - stb %g0, [%l4 + %l3] ! Store Group +3: ldub [%l6 + TI_FPDEPTH], %l5 + add %l6, TI_FPSAVED + 1, %l4 + srl %l5, 1, %l3 + add %l5, 2, %l5 + stb %l5, [%l6 + TI_FPDEPTH] + ba,pt %xcc, 2b + stb %g0, [%l4 + %l3] nop etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself. - * We place this right after pt_regs on the trap stack. The layout - * is: + * We place this right after pt_regs on the trap stack. + * The layout is: * 0x00 TL1's TSTATE * 0x08 TL1's TPC * 0x10 TL1's TNPC @@ -166,81 +167,81 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself. wrpr %g1, %tl stx %g1, [%g2 + STACK_BIAS + 0x80] - rdpr %tstate, %g1 ! Single Group+4bubbles - sub %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - ba,pt %xcc, 1b ! CTI Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU0 + rdpr %tstate, %g1 + sub %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2 + ba,pt %xcc, 1b + andcc %g1, TSTATE_PRIV, %g0 .align 64 .globl scetrap -scetrap: rdpr %pil, %g2 ! Single Group - rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,pn %xcc, 1f ! CTI - sub %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2 ! IEU1 - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - - sllx %g1, 51, %g3 ! IEU0 Group - sethi %hi(TASK_REGOFF), %g2 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - brlz,pn %g3, 1f ! CTI+IEU1 - add %g6, %g2, %g2 ! IEU0 Group - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] ! Store Group - - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] ! Store Group - stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] ! Store Group - save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group - mov %g6, %l6 ! IEU0 Group - bne,pn %xcc, 2f ! CTI - mov ASI_P, %l7 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - mov PRIMARY_CONTEXT, %l4 ! IEU1 - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store - flush %l6 ! Single Group+9bubbles - - mov ASI_AIUS, %l7 ! IEU0 Group -2: mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - add %g7, 0x4, %l2 ! IEU1 - wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles - stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] ! Store Group - stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] ! Store Group - sllx %l7, 24, %l7 ! IEU0 - - stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] ! Store Group - rdpr %cwp, %l0 ! Single Group - stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] ! Store Group - stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] ! Store Group - stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] ! Store Group - stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] ! Store Group - or %l7, %l0, %l7 ! IEU0 - sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 ! IEU1 - - or %l7, %l0, %l7 ! IEU0 Group - wrpr %l2, %tnpc ! Single Group+4bubbles - wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate ! Single Group+4bubbles - stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] ! Store Group - stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] ! Store Group - stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] ! Store Group - stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] ! Store Group - stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] ! Store Group - - stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] ! Store Group - stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] ! Store Group - mov %l6, %g6 ! IEU1 - stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] ! Store Group - ldx [%g6 + TI_TASK], %g4 ! Load Group +scetrap: rdpr %pil, %g2 + rdpr %tstate, %g1 + sllx %g2, 20, %g3 + andcc %g1, TSTATE_PRIV, %g0 + or %g1, %g3, %g1 + bne,pn %xcc, 1f + sub %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2 + wrpr %g0, 7, %cleanwin + + sllx %g1, 51, %g3 + sethi %hi(TASK_REGOFF), %g2 + or %g2, %lo(TASK_REGOFF), %g2 + brlz,pn %g3, 1f + add %g6, %g2, %g2 + wr %g0, 0, %fprs +1: rdpr %tpc, %g3 + stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE] + + rdpr %tnpc, %g1 + stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] + stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] + save %g2, -STACK_BIAS, %sp ! Ordering here is critical + mov %g6, %l6 + bne,pn %xcc, 2f + mov ASI_P, %l7 + rdpr %canrestore, %g3 + + rdpr %wstate, %g2 + wrpr %g0, 0, %canrestore + sll %g2, 3, %g2 + mov PRIMARY_CONTEXT, %l4 + wrpr %g3, 0, %otherwin + wrpr %g2, 0, %wstate + stxa %g0, [%l4] ASI_DMMU + flush %l6 + + mov ASI_AIUS, %l7 +2: mov %g4, %l4 + mov %g5, %l5 + add %g7, 0x4, %l2 + wrpr %g0, ETRAP_PSTATE1, %pstate + stx %g1, [%sp + PTREGS_OFF + PT_V9_G1] + stx %g2, [%sp + PTREGS_OFF + PT_V9_G2] + sllx %l7, 24, %l7 + + stx %g3, [%sp + PTREGS_OFF + PT_V9_G3] + rdpr %cwp, %l0 + stx %g4, [%sp + PTREGS_OFF + PT_V9_G4] + stx %g5, [%sp + PTREGS_OFF + PT_V9_G5] + stx %g6, [%sp + PTREGS_OFF + PT_V9_G6] + stx %g7, [%sp + PTREGS_OFF + PT_V9_G7] + or %l7, %l0, %l7 + sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 + + or %l7, %l0, %l7 + wrpr %l2, %tnpc + wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate + stx %i0, [%sp + PTREGS_OFF + PT_V9_I0] + stx %i1, [%sp + PTREGS_OFF + PT_V9_I1] + stx %i2, [%sp + PTREGS_OFF + PT_V9_I2] + stx %i3, [%sp + PTREGS_OFF + PT_V9_I3] + stx %i4, [%sp + PTREGS_OFF + PT_V9_I4] + + stx %i5, [%sp + PTREGS_OFF + PT_V9_I5] + stx %i6, [%sp + PTREGS_OFF + PT_V9_I6] + mov %l6, %g6 + stx %i7, [%sp + PTREGS_OFF + PT_V9_I7] + ldx [%g6 + TI_TASK], %g4 done nop nop diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 01c8869a7..4a286a800 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -50,6 +50,7 @@ bootup_user_stack: */ .global root_flags, ram_flags, root_dev .global sparc_ramdisk_image, sparc_ramdisk_size + .global sparc_ramdisk_image64 .ascii "HdrS" .word LINUX_VERSION_CODE @@ -60,7 +61,7 @@ bootup_user_stack: * 0x0202 : Supports kernel params string * 0x0201 : Supports reboot_command */ - .half 0x0300 /* HdrS version */ + .half 0x0301 /* HdrS version */ root_flags: .half 1 @@ -74,6 +75,8 @@ sparc_ramdisk_size: .word 0 .xword reboot_command .xword bootstr_info +sparc_ramdisk_image64: + .xword 0 .word _end /* We must be careful, 32-bit OpenBOOT will get confused if it diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index d52b84291..3162b2ed1 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -791,16 +790,24 @@ void handler_irq(int irq, struct pt_regs *regs) #endif if ((flags & IBF_MULTI) == 0) { struct irqaction *ap = bp->irq_info; - ap->handler(__irq(bp), ap->dev_id, regs); - random |= ap->flags & SA_SAMPLE_RANDOM; + int ret; + + ret = ap->handler(__irq(bp), ap->dev_id, regs); + if (ret == IRQ_HANDLED) + random |= ap->flags; } else { void **vector = (void **)bp->irq_info; int ent; for (ent = 0; ent < 4; ent++) { struct irqaction *ap = vector[ent]; if (ap != NULL) { - ap->handler(__irq(bp), ap->dev_id, regs); - random |= ap->flags & SA_SAMPLE_RANDOM; + int ret; + + ret = ap->handler(__irq(bp), + ap->dev_id, + regs); + if (ret == IRQ_HANDLED) + random |= ap->flags; } } } @@ -813,8 +820,9 @@ void handler_irq(int irq, struct pt_regs *regs) } #endif upa_writel(ICLR_IDLE, bp->iclr); + /* Test and add entropy */ - if (random) + if (random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); } } else diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 8ad507779..30862abee 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -262,7 +262,7 @@ void __init isa_init(void) device = PCI_DEVICE_ID_AL_M1533; pdev = NULL; - while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { + while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index bc5cc1d17..801ab91a7 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -15,7 +15,7 @@ * traps. The top-level scheme is similar to that used * in the x86 kprobes implementation. * - * In the kprobe->insn[] array we store the original + * In the kprobe->ainsn.insn[] array we store the original * instruction at index zero and a break instruction at * index one. * @@ -24,12 +24,12 @@ * - Remember "regs->tnpc" and interrupt level stored in * "regs->tstate" so we can restore them later * - Disable PIL interrupts - * - Set regs->tpc to point to kprobe->insn[0] - * - Set regs->tnpc to point to kprobe->insn[1] + * - Set regs->tpc to point to kprobe->ainsn.insn[0] + * - Set regs->tnpc to point to kprobe->ainsn.insn[1] * - Mark that we are actively in a kprobe * * At this point we wait for the second breakpoint at - * kprobe->insn[1] to hit. When it does we: + * kprobe->ainsn.insn[1] to hit. When it does we: * - Run the post-handler * - Set regs->tpc to "remembered" regs->tnpc stored above, * restore the PIL interrupt level in "regs->tstate" as well @@ -38,10 +38,15 @@ * - Mark that we are no longer actively in a kprobe. */ -void arch_prepare_kprobe(struct kprobe *p) +int arch_prepare_kprobe(struct kprobe *p) +{ + p->ainsn.insn[0] = *p->addr; + p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; + return 0; +} + +void arch_remove_kprobe(struct kprobe *p) { - p->insn[0] = *p->addr; - p->insn[1] = BREAKPOINT_INSTRUCTION_2; } /* kprobe_status settings */ @@ -59,8 +64,8 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); regs->tstate |= TSTATE_PIL; - regs->tpc = (unsigned long) &p->insn[0]; - regs->tnpc = (unsigned long) &p->insn[1]; + regs->tpc = (unsigned long) &p->ainsn.insn[0]; + regs->tnpc = (unsigned long) &p->ainsn.insn[1]; } static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) @@ -199,19 +204,19 @@ static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc) * instruction. To avoid the SMP problems that can occur when we * temporarily put back the original opcode to single-step, we * single-stepped a copy of the instruction. The address of this - * copy is p->insn. + * copy is p->ainsn.insn. * * This function prepares to return from the post-single-step * breakpoint trap. */ static void resume_execution(struct kprobe *p, struct pt_regs *regs) { - u32 insn = p->insn[0]; + u32 insn = p->ainsn.insn[0]; regs->tpc = current_kprobe_orig_tnpc; regs->tnpc = relbranch_fixup(insn, (unsigned long) p->addr, - (unsigned long) &p->insn[0], + (unsigned long) &p->ainsn.insn[0], regs->tnpc); retpc_fixup(regs, insn, (unsigned long) p->addr); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 31cc686de..c4d053387 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -41,7 +41,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, #else /* List of all PCI controllers found in the system. */ -spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED; struct pci_controller_info *pci_controller_root = NULL; /* Each PCI controller found gets a unique index. */ @@ -298,12 +297,9 @@ static void __init pci_controller_probe(void) static void __init pci_scan_each_controller_bus(void) { struct pci_controller_info *p; - unsigned long flags; - spin_lock_irqsave(&pci_controller_lock, flags); for (p = pci_controller_root; p; p = p->next) p->scan_bus(p); - spin_unlock_irqrestore(&pci_controller_lock, flags); } /* Reorder the pci_dev chain, so that onboard devices come first @@ -351,10 +347,6 @@ static int __init pcibios_init(void) subsys_initcall(pcibios_init); -struct pci_fixup pcibios_fixups[] = { - { 0 } -}; - void pcibios_fixup_bus(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; @@ -733,7 +725,7 @@ static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vm static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - vma->vm_flags |= (VM_SHM | VM_LOCKED); + vma->vm_flags |= (VM_IO | VM_RESERVED); } /* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index fda652414..58310aace 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -15,18 +15,13 @@ */ void __init pci_fixup_host_bridge_self(struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; - - walk = walk->next; - while (walk != &pbus->devices) { - struct pci_dev *pdev = pci_dev_b(walk); + struct pci_dev *pdev; + list_for_each_entry(pdev, &pbus->devices, bus_list) { if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) { pbus->self = pdev; return; } - - walk = walk->next; } prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n"); @@ -217,31 +212,18 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, struct pci_pbm_info *pbm, int prom_node) { - struct list_head *walk = &pbus->devices; - - /* This loop is coded like this because the cookie - * fillin routine can delete devices from the tree. - */ - walk = walk->next; - while (walk != &pbus->devices) { - struct pci_dev *pdev = pci_dev_b(walk); - struct list_head *walk_next = walk->next; + struct pci_dev *pdev, *pdev_next; + struct pci_bus *this_pbus, *pbus_next; + /* This must be _safe because the cookie fillin + routine can delete devices from the tree. */ + list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) pdev_cookie_fillin(pbm, pdev, prom_node); - walk = walk_next; - } - - walk = &pbus->children; - walk = walk->next; - while (walk != &pbus->children) { - struct pci_bus *this_pbus = pci_bus_b(walk); + list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { struct pcidev_cookie *pcp = this_pbus->self->sysdata; - struct list_head *walk_next = walk->next; pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node); - - walk = walk_next; } } @@ -431,14 +413,14 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm, void __init pci_record_assignments(struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *dev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) - pdev_record_assignments(pbm, pci_dev_b(walk)); + list_for_each_entry(dev, &pbus->devices, bus_list) + pdev_record_assignments(pbm, dev); - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_record_assignments(pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_record_assignments(pbm, bus); } /* Return non-zero if PDEV has implicit I/O resources even @@ -549,14 +531,14 @@ static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm, void __init pci_assign_unassigned(struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *dev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) - pdev_assign_unassigned(pbm, pci_dev_b(walk)); + list_for_each_entry(dev, &pbus->devices, bus_list) + pdev_assign_unassigned(pbm, dev); - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_assign_unassigned(pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_assign_unassigned(pbm, bus); } static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt) @@ -797,14 +779,14 @@ have_irq: void __init pci_fixup_irq(struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *dev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) - pdev_fixup_irq(pci_dev_b(walk)); + list_for_each_entry(dev, &pbus->devices, bus_list) + pdev_fixup_irq(dev); - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_fixup_irq(pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_fixup_irq(pbm, bus); } static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) @@ -897,7 +879,7 @@ static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk; + struct pci_dev *pdev; int all_are_66mhz; u16 status; @@ -906,11 +888,8 @@ void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, goto out; } - walk = &pbus->devices; all_are_66mhz = 1; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { - struct pci_dev *pdev = pci_dev_b(walk); - + list_for_each_entry(pdev, &pbus->devices, bus_list) { pci_read_config_word(pdev, PCI_STATUS, &status); if (!(status & PCI_STATUS_66MHZ)) { all_are_66mhz = 0; @@ -929,17 +908,17 @@ out: void pci_setup_busmastering(struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *dev; + struct pci_bus *bus; int is_66mhz; is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) - pdev_setup_busmastering(pci_dev_b(walk), is_66mhz); + list_for_each_entry(dev, &pbus->devices, bus_list) + pdev_setup_busmastering(dev, is_66mhz); - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_setup_busmastering(pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_setup_busmastering(pbm, bus); } void pci_register_legacy_regions(struct resource *io_res, @@ -987,10 +966,10 @@ void pci_scan_for_target_abort(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *pdev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { - struct pci_dev *pdev = pci_dev_b(walk); + list_for_each_entry(pdev, &pbus->devices, bus_list) { u16 status, error_bits; pci_read_config_word(pdev, PCI_STATUS, &status); @@ -1005,19 +984,18 @@ void pci_scan_for_target_abort(struct pci_controller_info *p, } } - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_scan_for_target_abort(p, pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_scan_for_target_abort(p, pbm, bus); } void pci_scan_for_master_abort(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *pdev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { - struct pci_dev *pdev = pci_dev_b(walk); + list_for_each_entry(pdev, &pbus->devices, bus_list) { u16 status, error_bits; pci_read_config_word(pdev, PCI_STATUS, &status); @@ -1031,19 +1009,18 @@ void pci_scan_for_master_abort(struct pci_controller_info *p, } } - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_scan_for_master_abort(p, pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_scan_for_master_abort(p, pbm, bus); } void pci_scan_for_parity_error(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct pci_bus *pbus) { - struct list_head *walk = &pbus->devices; + struct pci_dev *pdev; + struct pci_bus *bus; - for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { - struct pci_dev *pdev = pci_dev_b(walk); + list_for_each_entry(pdev, &pbus->devices, bus_list) { u16 status, error_bits; pci_read_config_word(pdev, PCI_STATUS, &status); @@ -1058,7 +1035,6 @@ void pci_scan_for_parity_error(struct pci_controller_info *p, } } - walk = &pbus->children; - for (walk = walk->next; walk != &pbus->children; walk = walk->next) - pci_scan_for_parity_error(p, pbm, pci_bus_b(walk)); + list_for_each_entry(bus, &pbus->children, node) + pci_scan_for_parity_error(p, pbm, bus); } diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 302a0a2ce..6c3205962 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -11,7 +11,6 @@ #include #include -extern spinlock_t pci_controller_lock; extern struct pci_controller_info *pci_controller_root; extern int pci_num_controllers; diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index cca82a12e..292983413 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -56,6 +56,39 @@ static void __iommu_flushall(struct pci_iommu *iommu) } } +#define IOPTE_CONSISTENT(CTX) \ + (IOPTE_VALID | IOPTE_CACHE | \ + (((CTX) << 47) & IOPTE_CONTEXT)) + +#define IOPTE_STREAMING(CTX) \ + (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF) + +/* Existing mappings are never marked invalid, instead they + * are pointed to a dummy page. + */ +#define IOPTE_IS_DUMMY(iommu, iopte) \ + ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) + +static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) +{ + unsigned long val = iopte_val(*iopte); + + val &= ~IOPTE_PAGE; + val |= iommu->dummy_page_pa; + + iopte_val(*iopte) = val; +} + +void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize) +{ + int i; + + tsbsize /= sizeof(iopte_t); + + for (i = 0; i < tsbsize; i++) + iopte_make_dummy(iommu, &iommu->page_table[i]); +} + static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) { iopte_t *iopte, *limit, *first; @@ -79,7 +112,7 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n first = iopte; for (;;) { - if (iopte_val(*iopte) == 0UL) { + if (IOPTE_IS_DUMMY(iommu, iopte)) { if ((iopte + (1 << cnum)) >= limit) ent = 0; else @@ -142,12 +175,12 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); while (iopte > iommu->page_table) { iopte--; - if (!(iopte_val(*iopte) & IOPTE_VALID)) { + if (IOPTE_IS_DUMMY(iommu, iopte)) { unsigned long tmp = npages; while (--tmp) { iopte--; - if (iopte_val(*iopte) & IOPTE_VALID) + if (!IOPTE_IS_DUMMY(iommu, iopte)) break; } if (tmp == 0) { @@ -162,15 +195,6 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long return NULL; } -#define IOPTE_CONSISTENT(CTX) \ - (IOPTE_VALID | IOPTE_CACHE | \ - (((CTX) << 47) & IOPTE_CONTEXT)) - -#define IOPTE_STREAMING(CTX) \ - (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF) - -#define IOPTE_INVALID 0UL - /* Allocate and map kernel buffer of size SIZE using consistent mode * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. @@ -261,7 +285,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ limit = (iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); while (walk < limit) { - if (iopte_val(*walk) != IOPTE_INVALID) + if (!IOPTE_IS_DUMMY(iommu, walk)) break; walk++; } @@ -280,7 +304,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; for (i = 0; i < npages; i++, iopte++) - iopte_val(*iopte) = IOPTE_INVALID; + iopte_make_dummy(iommu, iopte); if (iommu->iommu_ctxflush) { pci_iommu_write(iommu->iommu_ctxflush, ctx); @@ -376,7 +400,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU - if (iopte_val(*base) == IOPTE_INVALID) + if (IOPTE_IS_DUMMY(iommu, base)) printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0)); #endif @@ -415,7 +439,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int } /* Step 2: Clear out first TSB entry. */ - iopte_val(*base) = IOPTE_INVALID; + iopte_make_dummy(iommu, base); free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); @@ -611,7 +635,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); #ifdef DEBUG_PCI_IOMMU - if (iopte_val(*base) == IOPTE_INVALID) + if (IOPTE_IS_DUMMY(iommu, base)) printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0)); #endif @@ -648,7 +672,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, } /* Step 2: Clear out first TSB entry. */ - iopte_val(*base) = IOPTE_INVALID; + iopte_make_dummy(iommu, base); free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages, ctx); @@ -790,7 +814,7 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) /* ALI sound chips generate 31-bits of DMA, a special register * determines what bit 31 is emitted as. */ - ali_isa_bridge = pci_find_device(PCI_VENDOR_ID_AL, + ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); @@ -800,6 +824,7 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) else val &= ~0x01; pci_write_config_byte(ali_isa_bridge, 0x7e, val); + pci_dev_put(ali_isa_bridge); } int pci_dma_supported(struct pci_dev *pdev, u64 device_mask) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index dc4d63084..2dacbd780 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1076,17 +1076,17 @@ static void __init psycho_register_error_handlers(struct pci_controller_info *p) * bits for each PBM. */ tmp = psycho_read(base + PSYCHO_PCIA_CTRL); - tmp |= (PSYCHO_PCICTRL_SBH_ERR | - PSYCHO_PCICTRL_SERR | - PSYCHO_PCICTRL_SBH_INT | + tmp |= (PSYCHO_PCICTRL_SERR | + PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); + tmp &= ~(PSYCHO_PCICTRL_SBH_INT); psycho_write(base + PSYCHO_PCIA_CTRL, tmp); tmp = psycho_read(base + PSYCHO_PCIB_CTRL); - tmp |= (PSYCHO_PCICTRL_SBH_ERR | - PSYCHO_PCICTRL_SERR | - PSYCHO_PCICTRL_SBH_INT | + tmp |= (PSYCHO_PCICTRL_SERR | + PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); + tmp &= ~(PSYCHO_PCICTRL_SBH_INT); psycho_write(base + PSYCHO_PCIB_CTRL, tmp); } @@ -1241,6 +1241,14 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + /* Using assumed page size 8K with 128K entries we need 1MB iommu page * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. @@ -1254,7 +1262,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) iommu->page_table_sz_bits = 17; iommu->page_table_map_base = 0xc0000000; iommu->dma_addr_mask = 0xffffffff; - memset((char *)tsbbase, 0, IO_TSB_SIZE); + pci_iommu_table_init(iommu, IO_TSB_SIZE); /* We start with no consistent mappings. */ iommu->lowest_consistent_map = @@ -1479,22 +1487,18 @@ void __init psycho_init(int node, char *model_name) struct linux_prom64_registers pr_regs[3]; struct pci_controller_info *p; struct pci_iommu *iommu; - unsigned long flags; u32 upa_portid; int is_pbm_a, err; upa_portid = prom_getintdefault(node, "upa-portid", 0xff); - spin_lock_irqsave(&pci_controller_lock, flags); for(p = pci_controller_root; p; p = p->next) { if (p->pbm_A.portid == upa_portid) { - spin_unlock_irqrestore(&pci_controller_lock, flags); is_pbm_a = (p->pbm_A.prom_node == 0); psycho_pbm_init(p, node, is_pbm_a); return; } } - spin_unlock_irqrestore(&pci_controller_lock, flags); p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { @@ -1510,10 +1514,8 @@ void __init psycho_init(int node, char *model_name) memset(iommu, 0, sizeof(*iommu)); p->pbm_A.iommu = p->pbm_B.iommu = iommu; - spin_lock_irqsave(&pci_controller_lock, flags); p->next = pci_controller_root; pci_controller_root = p; - spin_unlock_irqrestore(&pci_controller_lock, flags); p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 6a266a7bf..2bf247792 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1113,10 +1113,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) { - struct list_head *walk = &sabre_bus->devices; + struct pci_dev *pdev; - for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) { - struct pci_dev *pdev = pci_dev_b(walk); + list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { @@ -1178,10 +1177,9 @@ static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm) static void __init sabre_scan_bus(struct pci_controller_info *p) { static int once; - struct pci_bus *sabre_bus; + struct pci_bus *sabre_bus, *pbus; struct pci_pbm_info *pbm; struct pcidev_cookie *cookie; - struct list_head *walk; int sabres_scanned; /* The APB bridge speaks to the Sabre host PCI bridge @@ -1217,9 +1215,7 @@ static void __init sabre_scan_bus(struct pci_controller_info *p) sabres_scanned = 0; - walk = &sabre_bus->children; - for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) { - struct pci_bus *pbus = pci_bus_b(walk); + list_for_each_entry(pbus, &sabre_bus->children, node) { if (pbus->number == p->pbm_A.pci_first_busno) { pbm = &p->pbm_A; @@ -1293,6 +1289,14 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8)); if (!tsbbase) { prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n"); @@ -1301,7 +1305,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, iommu->page_table = (iopte_t *)tsbbase; iommu->page_table_map_base = dvma_offset; iommu->dma_addr_mask = dma_mask; - memset((char *)tsbbase, 0, PAGE_SIZE << order); + pci_iommu_table_init(iommu, PAGE_SIZE << order); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); @@ -1546,7 +1550,6 @@ void __init sabre_init(int pnode, char *model_name) struct linux_prom64_registers pr_regs[2]; struct pci_controller_info *p; struct pci_iommu *iommu; - unsigned long flags; int tsbsize, err; u32 busrange[2]; u32 vdma[2]; @@ -1594,10 +1597,8 @@ void __init sabre_init(int pnode, char *model_name) upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); - spin_lock_irqsave(&pci_controller_lock, flags); p->next = pci_controller_root; pci_controller_root = p; - spin_unlock_irqrestore(&pci_controller_lock, flags); p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index be6fa906a..f72da320b 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1171,7 +1171,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info prom_halt(); } bucket = __bucket(irq); - tmp = readl(bucket->imap); + tmp = upa_readl(bucket->imap); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); @@ -1309,7 +1309,7 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) prom_halt(); } bucket = __bucket(irq); - tmp = readl(bucket->imap); + tmp = upa_readl(bucket->imap); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_CE_INO); @@ -1372,10 +1372,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p) SCHIZO_PCICTRL_RTRY_ERR | SCHIZO_PCICTRL_SBH_ERR | SCHIZO_PCICTRL_SERR | - SCHIZO_PCICTRL_SBH_INT | SCHIZO_PCICTRL_EEN); - err_no_mask = SCHIZO_PCICTRL_DTO_ERR; + err_no_mask = (SCHIZO_PCICTRL_DTO_ERR | + SCHIZO_PCICTRL_SBH_INT); /* Enable PCI Error interrupts and clear error * bits for each PBM. @@ -1766,6 +1766,14 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) * in pci_iommu.c */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + /* Using assumed page size 8K with 128K entries we need 1MB iommu page * table (128K ioptes * 8 bytes per iopte). This is * page order 7 on UltraSparc. @@ -1780,7 +1788,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) iommu->page_table = (iopte_t *)tsbbase; iommu->page_table_map_base = vdma[0]; iommu->dma_addr_mask = dma_mask; - memset((char *)tsbbase, 0, PAGE_SIZE << order); + pci_iommu_table_init(iommu, PAGE_SIZE << order); switch (tsbsize) { case 64: @@ -2073,13 +2081,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type) { struct pci_controller_info *p; struct pci_iommu *iommu; - unsigned long flags; int is_pbm_a; u32 portid; portid = prom_getintdefault(node, "portid", 0xff); - spin_lock_irqsave(&pci_controller_lock, flags); for(p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; @@ -2091,13 +2097,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type) &p->pbm_B); if (portid_compare(pbm->portid, portid, chip_type)) { - spin_unlock_irqrestore(&pci_controller_lock, flags); is_pbm_a = (p->pbm_A.prom_node == 0); schizo_pbm_init(p, node, portid, chip_type); return; } } - spin_unlock_irqrestore(&pci_controller_lock, flags); p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { @@ -2122,10 +2126,8 @@ static void __init __schizo_init(int node, char *model_name, int chip_type) memset(iommu, 0, sizeof(*iommu)); p->pbm_B.iommu = iommu; - spin_lock_irqsave(&pci_controller_lock, flags); p->next = pci_controller_root; pci_controller_root = p; - spin_unlock_irqrestore(&pci_controller_lock, flags); p->index = pci_num_controllers++; p->pbms_same_domain = 0; diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 006a562dc..52f14e399 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -27,7 +27,7 @@ int scons_pwroff = 1; #ifdef CONFIG_PCI -static unsigned long power_reg = 0UL; +static void __iomem *power_reg; static DECLARE_WAIT_QUEUE_HEAD(powerd_wait); static int button_pressed; @@ -52,7 +52,7 @@ void machine_power_off(void) { if (!serial_console || scons_pwroff) { #ifdef CONFIG_PCI - if (power_reg != 0UL) { + if (power_reg) { /* Both register bits seem to have the * same effect, so until I figure out * what the difference is... @@ -130,8 +130,8 @@ void __init power_init(void) return; found: - power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4); - printk("power: Control reg at %016lx ... ", power_reg); + power_reg = ioremap(edev->resource[0].start, 0x4); + printk("power: Control reg at %p ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ if (has_button_interrupt(edev)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { @@ -141,8 +141,7 @@ found: printk("powerd running.\n"); if (request_irq(edev->irqs[0], - power_handler, SA_SHIRQ, "power", - (void *) power_reg) < 0) + power_handler, SA_SHIRQ, "power", NULL) < 0) printk("power: Error, cannot register IRQ handler.\n"); } else { printk("not using powerd.\n"); diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 145ce7c73..7d86895f3 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -588,8 +588,6 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, { int __user *parent_tid_ptr, *child_tid_ptr; - clone_flags &= ~CLONE_IDLETASK; - #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]); @@ -623,8 +621,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, p->thread.smp_lock_pc = 0; #endif - p->set_child_tid = p->clear_child_tid = NULL; - /* Calculate offset to stack_frame & pt_regs */ child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); @@ -831,7 +827,9 @@ asmlinkage int sparc_execve(struct pt_regs *regs) current_thread_info()->xfsr[0] = 0; current_thread_info()->fpsaved[0] = 0; regs->tstate &= ~TSTATE_PEF; + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); } out: return error; diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 3e9aa09a9..721ab5ba8 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -559,7 +559,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) * exit. */ case PTRACE_KILL: { - if (child->state == TASK_ZOMBIE) { /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) { /* already dead */ pt_succ_return(regs, 0); goto out_tsk; } @@ -627,11 +627,8 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 438e373ce..51e762bcd 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index ba3fcb4b2..aa298d31d 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -23,9 +23,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -84,8 +84,8 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) regs->tnpc = npc; err |= __get_user(regs->y, &((*grp)[MC_Y])); err |= __get_user(tstate, &((*grp)[MC_TSTATE])); - regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); + regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); + regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); @@ -135,7 +135,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) return; do_sigsegv: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } asmlinkage void sparc64_get_context(struct pt_regs *regs) @@ -226,7 +226,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs) return; do_sigsegv: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } struct rt_signal_frame { @@ -408,9 +408,9 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= __get_user(tstate, &sf->regs.tstate); err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs)); - /* User can only change condition codes in %tstate. */ - regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); - regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); + /* User can only change condition codes and %asi in %tstate. */ + regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC); + regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC)); err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) @@ -439,7 +439,7 @@ void do_rt_sigreturn(struct pt_regs *regs) spin_unlock_irq(¤t->sighand->siglock); return; segv: - send_sig(SIGSEGV, current, 1); + force_sig(SIGSEGV, current); } /* Checks if the fp is valid */ @@ -545,6 +545,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; + /* The sigcontext is passed in this way because of how it + * is defined in GLIBC's /usr/include/bits/sigcontext.h + * for sparc64. It includes the 128 bytes of siginfo_t. + */ + regs->u_regs[UREG_I2] = (unsigned long) &sf->info; + /* 5. signal handler */ regs->tpc = (unsigned long) ka->sa.sa_handler; regs->tnpc = (regs->tpc + 4); @@ -559,7 +565,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, sigill: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signo, current); } static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, @@ -568,8 +574,6 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, { setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -609,6 +613,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, { siginfo_t info; struct signal_deliver_cookie cookie; + struct k_sigaction ka; int signr; cookie.restart_syscall = restart_syscall; @@ -626,15 +631,11 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, } #endif - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart(orig_i0, regs, &ka->sa); - handle_signal(signr, ka, &info, oldset, regs); + syscall_restart(orig_i0, regs, &ka.sa); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } if (cookie.restart_syscall && diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index a9a5b31a3..ab2660494 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -20,9 +20,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -59,6 +59,16 @@ struct signal_sframe32 { unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; }; +/* This magic should be in g_upper[0] for all upper parts + * to be valid. + */ +#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269 +typedef struct { + unsigned int g_upper[8]; + unsigned int o_upper[8]; + unsigned int asi; +} siginfo_extra_v8plus_t; + /* * And the new one, intended to be used for Linux applications only * (we have enough in there to work with clone). @@ -76,9 +86,61 @@ struct new_signal_frame32 { __siginfo_fpu_t fpu_state; }; +struct siginfo32 { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + sigval_t32 _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + unsigned int _uid; /* sender's uid */ + sigval_t32 _sigval; + } _rt; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + unsigned int _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ + struct { + u32 _addr; /* faulting insn/memory ref. */ + int _trapno; + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +}; + struct rt_signal_frame32 { struct sparc_stackf32 ss; - siginfo_t32 info; + struct siginfo32 info; struct pt_regs32 regs; compat_sigset_t mask; /* __siginfo_fpu32_t * */ u32 fpu_save; @@ -95,11 +157,11 @@ struct rt_signal_frame32 { #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) -int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) +int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from) { int err; - if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32))) + if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32))) return -EFAULT; /* If you change siginfo_t structure, please be sure @@ -119,7 +181,7 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) case __SI_TIMER >> 16: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr); + err |= __put_user(from->si_int, &to->si_int); break; case __SI_CHLD >> 16: err |= __put_user(from->si_utime, &to->si_utime); @@ -145,6 +207,22 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) return err; } +/* CAUTION: This is just a very minimalist implementation for the + * sake of compat_sys_rt_sigqueueinfo() + */ +int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from) +{ + if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32))) + return -EFAULT; + + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, from->_sifields._pad, + SI_PAD_SIZE)) + return -EFAULT; + + return 0; +} + /* * atomically swap in the new signal mask, and wait for a signal. * This is really tricky on the Sparc, watch out... @@ -299,8 +377,13 @@ void do_new_sigreturn32(struct pt_regs *regs) if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { err |= __get_user(i, &sf->v8plus.g_upper[0]); if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { + unsigned long asi; + for (i = UREG_G1; i <= UREG_I7; i++) err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __get_user(asi, &sf->v8plus.asi); + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= ((asi & 0xffUL) << 24UL); } } @@ -330,7 +413,7 @@ void do_new_sigreturn32(struct pt_regs *regs) return; segv: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } asmlinkage void do_sigreturn32(struct pt_regs *regs) @@ -400,7 +483,7 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs) return; segv: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) @@ -447,8 +530,13 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) { err |= __get_user(i, &sf->v8plus.g_upper[0]); if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) { + unsigned long asi; + for (i = UREG_G1; i <= UREG_I7; i++) err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __get_user(asi, &sf->v8plus.asi); + regs->tstate &= ~TSTATE_ASI; + regs->tstate |= ((asi & 0xffUL) << 24UL); } } @@ -487,7 +575,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) spin_unlock_irq(¤t->sighand->siglock); return; segv: - do_exit(SIGSEGV); + force_sig(SIGSEGV, current); } /* Checks if the fp is valid */ @@ -648,7 +736,7 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o return; sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signr, current); } @@ -715,7 +803,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size); err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]); for (i = 1; i < 16; i++) - err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __put_user(((u32 *)regs->u_regs)[2*i], + &sf->v8plus.g_upper[i]); + err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, + &sf->v8plus.asi); if (psr & PSR_EF) { err |= save_fpu_state32(regs, &sf->fpu_state); @@ -749,6 +840,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; + regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 4. signal handler */ regs->tpc = (unsigned long) ka->sa.sa_handler; @@ -795,7 +887,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, sigill: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signo, current); } /* Setup a Solaris stack frame */ @@ -919,7 +1011,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, return; sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signr, current); } asmlinkage int @@ -1070,7 +1162,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) return -EINTR; sigsegv: - do_exit(SIGSEGV); + return -EFAULT; } static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, @@ -1119,6 +1211,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, for (i = 1; i < 16; i++) err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]); + err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL, + &sf->v8plus.asi); if (psr & PSR_EF) { err |= save_fpu_state32(regs, &sf->fpu_state); @@ -1157,6 +1251,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signr; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; + regs->u_regs[UREG_I2] = (unsigned long) &sf->regs; /* 4. signal handler */ regs->tpc = (unsigned long) ka->sa.sa_handler; @@ -1206,7 +1301,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, sigill: do_exit(SIGILL); sigsegv: - do_exit(SIGSEGV); + force_sigsegv(signr, current); } static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, @@ -1225,8 +1320,6 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, else setup_frame32(&ka->sa, regs, signr, oldset, info); } - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -1266,21 +1359,19 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, { siginfo_t info; struct signal_deliver_cookie cookie; + struct k_sigaction ka; int signr; int svr4_signal = current->personality == PER_SVR4; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart32(orig_i0, regs, &ka->sa); - handle_signal32(signr, ka, &info, oldset, regs, svr4_signal); + syscall_restart32(orig_i0, regs, &ka.sa); + handle_signal32(signr, &ka, &info, oldset, + regs, svr4_signal); return 1; } if (cookie.restart_syscall && diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index abc65dc6d..f2d24dc1d 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -103,15 +103,6 @@ extern void inherit_locked_prom_mappings(int save_p); void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); - extern int bigkernel; - extern unsigned long kern_locked_tte_data; - - if (bigkernel) { - prom_dtlb_load(sparc64_highest_locked_tlbent()-1, - kern_locked_tte_data + 0x400000, KERNBASE + 0x400000); - prom_itlb_load(sparc64_highest_locked_tlbent()-1, - kern_locked_tte_data + 0x400000, KERNBASE + 0x400000); - } inherit_locked_prom_mappings(0); @@ -303,14 +294,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu) struct task_struct *p; int timeout, ret, cpu_node; - kernel_thread(NULL, NULL, CLONE_IDLETASK); - - p = prev_task(&init_task); - - init_idle(p, cpu); - - unhash_process(p); - + p = fork_idle(cpu); callin_flag = 0; cpu_new_thread = p->thread_info; cpu_set(cpu, cpu_callout_map); @@ -981,8 +965,6 @@ void smp_promstop_others(void) smp_cross_call(&xcall_promstop, 0, 0, 0); } -extern void sparc64_do_profile(struct pt_regs *regs); - #define prof_multiplier(__cpu) cpu_data(__cpu).multiplier #define prof_counter(__cpu) cpu_data(__cpu).counter @@ -1008,7 +990,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) } do { - sparc64_do_profile(regs); + profile_tick(CPU_PROFILING, regs); if (!--prof_counter(cpu)) { irq_enter(); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 5eafadd28..6b7ef23b9 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -74,8 +73,6 @@ extern void *__bzero(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); -extern int __strncmp(const char *, const char *, __kernel_size_t); -extern __kernel_size_t __strlen(const char *); extern __kernel_size_t strlen(const char *); extern void linux_sparc_syscall(void); extern void rtrap(void); @@ -144,7 +141,7 @@ EXPORT_SYMBOL(synchronize_irq); #if defined(CONFIG_MCOUNT) extern void _mcount(void); -EXPORT_SYMBOL_NOVERS(_mcount); +EXPORT_SYMBOL(_mcount); #endif /* CPU online map and active count. */ @@ -180,15 +177,13 @@ EXPORT_SYMBOL(__atomic_sub); EXPORT_SYMBOL(__atomic64_add); EXPORT_SYMBOL(__atomic64_sub); #ifdef CONFIG_SMP -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif /* Atomic bit operations. */ EXPORT_SYMBOL(___test_and_set_bit); EXPORT_SYMBOL(___test_and_clear_bit); EXPORT_SYMBOL(___test_and_change_bit); -EXPORT_SYMBOL(___test_and_set_le_bit); -EXPORT_SYMBOL(___test_and_clear_le_bit); /* Bit searching */ EXPORT_SYMBOL(find_next_bit); @@ -295,7 +290,6 @@ EXPORT_SYMBOL(__prom_getchild); EXPORT_SYMBOL(__prom_getsibling); /* sparc library symbols */ -EXPORT_SYMBOL(__strlen); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(__strlen_user); @@ -334,7 +328,6 @@ EXPORT_SYMBOL(sys_close); #endif /* Special internal versions of library functions. */ -EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(_clear_page); EXPORT_SYMBOL(clear_user_page); EXPORT_SYMBOL(copy_user_page); @@ -342,8 +335,7 @@ EXPORT_SYMBOL(__bzero); EXPORT_SYMBOL(__memscan_zero); EXPORT_SYMBOL(__memscan_generic); EXPORT_SYMBOL(__memcmp); -EXPORT_SYMBOL(__strncmp); -EXPORT_SYMBOL(__memmove); +EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(csum_partial); @@ -351,9 +343,12 @@ EXPORT_SYMBOL(csum_partial_copy_sparc64); EXPORT_SYMBOL(ip_fast_csum); /* Moving data to/from/in userspace. */ -EXPORT_SYMBOL(__copy_to_user); -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(__copy_in_user); +EXPORT_SYMBOL(___copy_to_user); +EXPORT_SYMBOL(___copy_from_user); +EXPORT_SYMBOL(___copy_in_user); +EXPORT_SYMBOL(copy_to_user_fixup); +EXPORT_SYMBOL(copy_from_user_fixup); +EXPORT_SYMBOL(copy_in_user_fixup); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__bzero_noasi); @@ -367,17 +362,24 @@ EXPORT_SYMBOL(pfn_to_page); /* No version information on this, heavily used in inline asm, * and will always be 'void __ret_efault(void)'. */ -EXPORT_SYMBOL_NOVERS(__ret_efault); +EXPORT_SYMBOL(__ret_efault); /* No version information on these, as gcc produces such symbols. */ -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strncmp); + +/* Delay routines. */ +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__ndelay); +EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(__delay); void VISenter(void); /* RAID code needs this */ -EXPORT_SYMBOL_NOVERS(VISenter); +EXPORT_SYMBOL(VISenter); /* for input/keybdev */ EXPORT_SYMBOL(sun_do_break); diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 7a5d4f4e5..5a95e98c5 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -84,9 +84,9 @@ SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) SIGN1(sys32_mlockall, sys_mlockall, %o0) SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0) -SIGN1(sys32_clock_settime, compat_clock_settime, %o1) -SIGN1(sys32_clock_nanosleep, compat_clock_nanosleep, %o1) -SIGN1(sys32_timer_settime, compat_timer_settime, %o1) +SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1) +SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) +SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) SIGN1(sys32_mq_open, compat_sys_mq_open, %o1) SIGN1(sys32_select, compat_sys_select, %o0) @@ -120,7 +120,7 @@ SIGN1(sys32_setgroups, sys_setgroups, %o0) SIGN2(sys32_setpgid, sys_setpgid, %o0, %o1) SIGN3(sys32_setpriority, sys_setpriority, %o0, %o1, %o2) SIGN1(sys32_ssetmask, sys_ssetmask, %o0) -SIGN2(sys32_syslog, sys_syslog, %o0, %o1) +SIGN2(sys32_syslog, sys_syslog, %o0, %o2) SIGN1(sys32_umask, sys_umask, %o0) SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2) SIGN1(sys32_sendto, sys_sendto, %o0) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 56e277383..28014dc74 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1045,7 +1045,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, } asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, - siginfo_t32 __user *uinfo, + struct siginfo32 __user *uinfo, struct compat_timespec __user *uts, compat_size_t sigsetsize) { @@ -1130,15 +1130,15 @@ asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, } asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig, - siginfo_t32 __user *uinfo) + struct siginfo32 __user *uinfo) { siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info, uinfo, 3*sizeof(int)) || - copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) + if (copy_siginfo_to_kernel32(&info, uinfo)) return -EFAULT; + set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs (old_fs); @@ -1274,7 +1274,9 @@ asmlinkage long sparc32_execve(struct pt_regs *regs) current_thread_info()->xfsr[0] = 0; current_thread_info()->fpsaved[0] = 0; regs->tstate &= ~TSTATE_PEF; + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); } out: return error; @@ -1736,3 +1738,33 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, return err; } +asmlinkage long compat_sys_waitid(u32 which, u32 pid, + struct siginfo32 __user *uinfo, u32 options, + struct compat_rusage __user *uru) +{ + siginfo_t info; + struct rusage ru; + long ret; + mm_segment_t old_fs = get_fs(); + + memset(&info, 0, sizeof(info)); + + set_fs (KERNEL_DS); + ret = sys_waitid(which, pid, (siginfo_t __user *) &info, + options, + uru ? (struct rusage __user *) &ru : NULL); + set_fs (old_fs); + + if (ret < 0 || info.si_signo == 0) + return ret; + + if (uru) { + ret = put_compat_rusage(&ru, uru); + if (ret) + return ret; + } + + BUG_ON(info.si_code & __SI_MASK); + info.si_code |= __SI_CHLD; + return copy_siginfo_to_user32(uinfo, &info); +} diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index ace96ee27..1bf38a5ea 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -142,7 +142,7 @@ asmlinkage int sunos_brk(u32 baddr) } /* Check against rlimit and stack.. */ retval = -ENOMEM; - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (brk - current->mm->end_code > rlim) diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index a937ab707..5776d3900 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -60,23 +60,23 @@ sys_call_table32: .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sparc64_newuname /*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl .word sys32_epoll_wait, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask -/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_old_readdir +/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 /*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex /*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 -/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_statfs64 - .word compat_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall +/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_sys_statfs64 + .word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep /*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl - .word sys_ni_syscall, sys32_clock_settime, compat_clock_gettime, compat_clock_getres, sys32_clock_nanosleep -/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun + .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep +/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink - .word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, sys_ni_syscall -/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall + .word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid +/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl #endif /* CONFIG_COMPAT */ @@ -141,8 +141,8 @@ sys_call_table: /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink - .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall -/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall + .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid +/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -247,5 +247,5 @@ sunos_sys_table: .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys - + .word sunos_nosys #endif diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index f961a0d3b..0a93354f1 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -63,10 +64,31 @@ static unsigned long mstk48t59_regs = 0UL; static int set_rtc_mmss(unsigned long); -struct sparc64_tick_ops *tick_ops; +static __init unsigned long dummy_get_tick(void) +{ + return 0; +} + +static __initdata struct sparc64_tick_ops dummy_tick_ops = { + .get_tick = dummy_get_tick, +}; + +struct sparc64_tick_ops *tick_ops = &dummy_tick_ops; #define TICK_PRIV_BIT (1UL << 63) +#ifdef CONFIG_SMP +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + + if (in_lock_functions(pc)) + return regs->u_regs[UREG_RETPC]; + return pc; +} +EXPORT_SYMBOL(profile_pc); +#endif + static void tick_disable_protection(void) { /* Set things up so user can access tick register for profiling @@ -418,7 +440,6 @@ static struct sparc64_tick_ops hbtick_operations = { unsigned long timer_tick_offset; unsigned long timer_tick_compare; -static unsigned long timer_ticks_per_usec_quotient; static unsigned long timer_ticks_per_nsec_quotient; #define TICK_SIZE (tick_nsec / 1000) @@ -441,28 +462,6 @@ static inline void timer_check_rtc(void) } } -void sparc64_do_profile(struct pt_regs *regs) -{ - unsigned long pc; - - profile_hook(regs); - - if (user_mode(regs)) - return; - - if (!prof_buffer) - return; - - pc = regs->tpc; - - pc -= (unsigned long) _stext; - pc >>= prof_shift; - - if(pc >= prof_len) - pc = prof_len - 1; - atomic_inc((atomic_t *)&prof_buffer[pc]); -} - static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { unsigned long ticks, pstate; @@ -471,7 +470,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) do { #ifndef CONFIG_SMP - sparc64_do_profile(regs); + profile_tick(CPU_PROFILING, regs); + update_process_times(user_mode(regs)); #endif do_timer(regs); @@ -920,10 +920,10 @@ try_isa_clock: } /* This is gets the master TICK_INT timer going. */ -static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *)) +static unsigned long sparc64_init_timers(void) { - unsigned long pstate, clock; - int node, err; + unsigned long clock; + int node; #ifdef CONFIG_SMP extern void smp_tick_init(void); #endif @@ -956,6 +956,14 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc smp_tick_init(); #endif + return clock; +} + +static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *)) +{ + unsigned long pstate; + int err; + /* Register IRQ handler. */ err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC, "timer", NULL); @@ -981,8 +989,6 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc : "r" (pstate)); local_irq_enable(); - - return clock; } struct freq_table { @@ -1034,18 +1040,28 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val static struct notifier_block sparc64_cpufreq_notifier_block = { .notifier_call = sparc64_cpufreq_notifier }; -#endif + +#endif /* CONFIG_CPU_FREQ */ + +static struct time_interpolator sparc64_cpu_interpolator = { + .source = TIME_SOURCE_CPU, + .shift = 16, + .mask = 0xffffffffffffffffLL +}; /* The quotient formula is taken from the IA64 port. */ -#define SPARC64_USEC_PER_CYC_SHIFT 30UL #define SPARC64_NSEC_PER_CYC_SHIFT 30UL void __init time_init(void) { - unsigned long clock = sparc64_init_timers(timer_interrupt); + unsigned long clock = sparc64_init_timers(); - timer_ticks_per_usec_quotient = - (((1000000UL << SPARC64_USEC_PER_CYC_SHIFT) + - (clock / 2)) / clock); + sparc64_cpu_interpolator.frequency = clock; + register_time_interpolator(&sparc64_cpu_interpolator); + + /* Now that the interpolator is registered, it is + * safe to start the timer ticking. + */ + sparc64_start_timers(timer_interrupt); timer_ticks_per_nsec_quotient = (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + @@ -1057,17 +1073,6 @@ void __init time_init(void) #endif } -static __inline__ unsigned long do_gettimeoffset(void) -{ - unsigned long ticks = tick_ops->get_tick(); - - ticks += timer_tick_offset; - ticks -= timer_tick_compare; - - return (ticks * timer_ticks_per_usec_quotient) - >> SPARC64_USEC_PER_CYC_SHIFT; -} - unsigned long long sched_clock(void) { unsigned long ticks = tick_ops->get_tick(); @@ -1076,100 +1081,6 @@ unsigned long long sched_clock(void) >> SPARC64_NSEC_PER_CYC_SHIFT; } -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - if (this_is_starfire) - return 0; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - nsec -= do_gettimeoffset() * 1000; - nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ); - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - -/* Ok, my cute asm atomicity trick doesn't work anymore. - * There are just too many variables that need to be protected - * now (both members of xtime, wall_jiffies, et al.) - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - unsigned long max_ntp_tick = tick_usec - tickadj; - - do { - unsigned long lost; - - seq = read_seqbegin(&xtime_lock); - usec = do_gettimeoffset(); - lost = jiffies - wall_jiffies; - - /* - * If time_adjust is negative then NTP is slowing the clock - * so make sure not to go into next possible interval. - * Better to lose some accuracy than have time go backwards.. - */ - if (unlikely(time_adjust < 0)) { - usec = min(usec, max_ntp_tick); - - if (lost) - usec += lost * max_ntp_tick; - } - else if (unlikely(lost)) - usec += lost * tick_usec; - - sec = xtime.tv_sec; - - /* Believe it or not, this divide shows up on - * kernel profiles. The problem is that it is - * both 64-bit and signed. Happily, 32-bits - * of precision is all we really need and in - * doing so gcc ends up emitting a cheap multiply. - * - * XXX Why is tv_nsec 'long' and 'signed' in - * XXX the first place, can it even be negative? - */ - usec += ((unsigned int) xtime.tv_nsec / 1000U); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 28fe12b23..f1d764b2d 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -90,7 +90,9 @@ startup_continue: sllx %g2, 32, %g2 wr %g2, 0, %tick_cmpr - /* Call OBP by hand to lock KERNBASE into i/d tlbs. */ + /* Call OBP by hand to lock KERNBASE into i/d tlbs. + * We lock 2 consequetive entries if we are 'bigkernel'. + */ mov %o0, %l0 sethi %hi(prom_entry_lock), %g2 @@ -136,6 +138,46 @@ startup_continue: call %o1 add %sp, (2047 + 128), %o0 + sethi %hi(bigkernel), %g2 + lduw [%g2 + %lo(bigkernel)], %g2 + cmp %g2, 0 + be,pt %icc, do_dtlb + nop + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(itlb_load), %g2 + or %g2, %lo(itlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE + 0x400000), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + sethi %hi(0x400000), %g1 + add %g2, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + + mov 14, %g2 + BRANCH_IF_ANY_CHEETAH(g1,g5,1f) + + mov 62, %g2 +1: + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + +do_dtlb: sethi %hi(call_method), %g2 or %g2, %lo(call_method), %g2 stx %g2, [%sp + 2047 + 128 + 0x00] @@ -168,6 +210,47 @@ startup_continue: call %o1 add %sp, (2047 + 128), %o0 + sethi %hi(bigkernel), %g2 + lduw [%g2 + %lo(bigkernel)], %g2 + cmp %g2, 0 + be,pt %icc, do_unlock + nop + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(dtlb_load), %g2 + or %g2, %lo(dtlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE + 0x400000), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + sethi %hi(0x400000), %g1 + add %g2, %g1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + + mov 14, %g2 + BRANCH_IF_ANY_CHEETAH(g1,g5,1f) + + mov 62, %g2 +1: + + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + +do_unlock: sethi %hi(prom_entry_lock), %g2 stb %g0, [%g2 + %lo(prom_entry_lock)] membar #StoreStore | #StoreLoad diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 473901974..7519f39c5 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -36,10 +36,24 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include #endif +struct notifier_block *sparc64die_chain; +static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED; + +int register_die_notifier(struct notifier_block *nb) +{ + int err = 0; + unsigned long flags; + spin_lock_irqsave(&die_notifier_lock, flags); + err = notifier_chain_register(&sparc64die_chain, nb); + spin_unlock_irqrestore(&die_notifier_lock, flags); + return err; +} + /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap * stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout @@ -71,11 +85,20 @@ static void dump_tl1_traplog(struct tl1_traplog *p) } } -void bad_trap (struct pt_regs *regs, long lvl) +void do_call_debug(struct pt_regs *regs) +{ + notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); +} + +void bad_trap(struct pt_regs *regs, long lvl) { char buffer[32]; siginfo_t info; + if (notify_die(DIE_TRAP, "bad trap", regs, + 0, lvl, SIGTRAP) == NOTIFY_STOP) + return; + if (lvl < 0x100) { sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl); die_if_kernel(buffer, regs); @@ -84,7 +107,7 @@ void bad_trap (struct pt_regs *regs, long lvl) lvl -= 0x100; if (regs->tstate & TSTATE_PRIV) { sprintf(buffer, "Kernel bad sw trap %lx", lvl); - die_if_kernel (buffer, regs); + die_if_kernel(buffer, regs); } if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; @@ -98,10 +121,14 @@ void bad_trap (struct pt_regs *regs, long lvl) force_sig_info(SIGILL, &info, current); } -void bad_trap_tl1 (struct pt_regs *regs, long lvl) +void bad_trap_tl1(struct pt_regs *regs, long lvl) { char buffer[32]; + if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs, + 0, lvl, SIGTRAP) == NOTIFY_STOP) + return; + dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); sprintf (buffer, "Bad trap %lx at tl>0", lvl); @@ -121,6 +148,10 @@ void instruction_access_exception(struct pt_regs *regs, { siginfo_t info; + if (notify_die(DIE_TRAP, "instruction access exception", regs, + 0, 0x8, SIGTRAP) == NOTIFY_STOP) + return; + if (regs->tstate & TSTATE_PRIV) { printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n", sfsr, sfar); @@ -141,15 +172,23 @@ void instruction_access_exception(struct pt_regs *regs, void instruction_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { + if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, + 0, 0x8, SIGTRAP) == NOTIFY_STOP) + return; + dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); instruction_access_exception(regs, sfsr, sfar); } -void data_access_exception (struct pt_regs *regs, - unsigned long sfsr, unsigned long sfar) +void data_access_exception(struct pt_regs *regs, + unsigned long sfsr, unsigned long sfar) { siginfo_t info; + if (notify_die(DIE_TRAP, "data access exception", regs, + 0, 0x30, SIGTRAP) == NOTIFY_STOP) + return; + if (regs->tstate & TSTATE_PRIV) { /* Test if this comes from uaccess places. */ unsigned long fixup; @@ -220,6 +259,10 @@ void do_iae(struct pt_regs *regs) spitfire_clean_and_reenable_l1_caches(); + if (notify_die(DIE_TRAP, "instruction access exception", regs, + 0, 0x8, SIGTRAP) == NOTIFY_STOP) + return; + info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_OBJERR; @@ -230,6 +273,8 @@ void do_iae(struct pt_regs *regs) void do_dae(struct pt_regs *regs) { + siginfo_t info; + #ifdef CONFIG_PCI if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) { spitfire_clean_and_reenable_l1_caches(); @@ -244,7 +289,18 @@ void do_dae(struct pt_regs *regs) return; } #endif - do_iae(regs); + spitfire_clean_and_reenable_l1_caches(); + + if (notify_die(DIE_TRAP, "data access exception", regs, + 0, 0x30, SIGTRAP) == NOTIFY_STOP) + return; + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_OBJERR; + info.si_addr = (void *)0; + info.si_trapno = 0; + force_sig_info(SIGBUS, &info, current); } static char ecc_syndrome_table[] = { @@ -1638,6 +1694,10 @@ void do_fpe_common(struct pt_regs *regs) void do_fpieee(struct pt_regs *regs) { + if (notify_die(DIE_TRAP, "fpu exception ieee", regs, + 0, 0x24, SIGFPE) == NOTIFY_STOP) + return; + do_fpe_common(regs); } @@ -1648,6 +1708,10 @@ void do_fpother(struct pt_regs *regs) struct fpustate *f = FPUSTATE; int ret = 0; + if (notify_die(DIE_TRAP, "fpu exception other", regs, + 0, 0x25, SIGFPE) == NOTIFY_STOP) + return; + switch ((current_thread_info()->xfsr[0] & 0x1c000)) { case (2 << 14): /* unfinished_FPop */ case (3 << 14): /* unimplemented_FPop */ @@ -1663,6 +1727,10 @@ void do_tof(struct pt_regs *regs) { siginfo_t info; + if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs, + 0, 0x26, SIGEMT) == NOTIFY_STOP) + return; + if (regs->tstate & TSTATE_PRIV) die_if_kernel("Penguin overflow trap from kernel mode", regs); if (test_thread_flag(TIF_32BIT)) { @@ -1681,6 +1749,10 @@ void do_div0(struct pt_regs *regs) { siginfo_t info; + if (notify_die(DIE_TRAP, "integer division by zero", regs, + 0, 0x28, SIGFPE) == NOTIFY_STOP) + return; + if (regs->tstate & TSTATE_PRIV) die_if_kernel("TL0: Kernel divide by zero.", regs); if (test_thread_flag(TIF_32BIT)) { @@ -1771,6 +1843,37 @@ void dump_stack(void) EXPORT_SYMBOL(dump_stack); +static inline int is_kernel_stack(struct task_struct *task, + struct reg_window *rw) +{ + unsigned long rw_addr = (unsigned long) rw; + unsigned long thread_base, thread_end; + + if (rw_addr < PAGE_OFFSET) { + if (task != &init_task) + return 0; + } + + thread_base = (unsigned long) task->thread_info; + thread_end = thread_base + sizeof(union thread_union); + if (rw_addr >= thread_base && + rw_addr < thread_end && + !(rw_addr & 0x7UL)) + return 1; + + return 0; +} + +static inline struct reg_window *kernel_stack_up(struct reg_window *rw) +{ + unsigned long fp = rw->ins[6]; + + if (!fp) + return NULL; + + return (struct reg_window *) (fp + STACK_BIAS); +} + void die_if_kernel(char *str, struct pt_regs *regs) { static int die_counter; @@ -1786,6 +1889,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) " \\__U_/\n"); printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); + notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); __asm__ __volatile__("flushw"); __show_regs(regs); if (regs->tstate & TSTATE_PRIV) { @@ -1795,17 +1899,14 @@ void die_if_kernel(char *str, struct pt_regs *regs) /* Stop the back trace when we hit userland or we * find some badly aligned kernel stack. */ - while (rw && - count++ < 30 && - (((unsigned long) rw) >= PAGE_OFFSET) && - (char *) rw < ((char *) current) - + sizeof (union thread_union) && - !(((unsigned long) rw) & 0x7)) { + while (rw && + count++ < 30&& + is_kernel_stack(current, rw)) { printk("Caller[%016lx]", rw->ins[7]); print_symbol(": %s", rw->ins[7]); printk("\n"); - rw = (struct reg_window *) - (rw->ins[6] + STACK_BIAS); + + rw = kernel_stack_up(rw); } instruction_dump ((unsigned int *) regs->tpc); } else { @@ -1834,6 +1935,10 @@ void do_illegal_instruction(struct pt_regs *regs) u32 insn; siginfo_t info; + if (notify_die(DIE_TRAP, "illegal instruction", regs, + 0, 0x10, SIGILL) == NOTIFY_STOP) + return; + if (tstate & TSTATE_PRIV) die_if_kernel("Kernel illegal instruction", regs); if (test_thread_flag(TIF_32BIT)) @@ -1859,6 +1964,10 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo { siginfo_t info; + if (notify_die(DIE_TRAP, "memory address unaligned", regs, + 0, 0x34, SIGSEGV) == NOTIFY_STOP) + return; + if (regs->tstate & TSTATE_PRIV) { extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, @@ -1881,6 +1990,10 @@ void do_privop(struct pt_regs *regs) { siginfo_t info; + if (notify_die(DIE_TRAP, "privileged operation", regs, + 0, 0x11, SIGILL) == NOTIFY_STOP) + return; + if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 40f7919aa..491bb3681 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -158,7 +158,7 @@ tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168) tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c) tl0_linux64: LINUX_64BIT_SYSCALL_TRAP tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context) -tl0_resv170: BTRAP(0x170) BTRAP(0x171) BTRAP(0x172) +tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172) tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177) tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c) tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f) diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 646a788fa..8a9d3b6bf 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -19,8 +19,8 @@ #include #include #include +#include #include -#include /* #define DEBUG_MNA */ diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index 8faeee09f..a710d38d1 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S @@ -16,6 +16,7 @@ SECTIONS { *(.text) SCHED_TEXT + LOCK_TEXT *(.gnu.warning) } =0 _etext = .; @@ -52,9 +53,6 @@ SECTIONS __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index 2da5af9a1..3cf408cb1 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile @@ -7,11 +7,14 @@ EXTRA_CFLAGS := -Werror lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ - VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ - VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ - U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ - U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o splock.o \ - find_bit.o + VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ + VIScsumcopyusr.o VISsave.o atomic.o bitops.o \ + U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ + U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ + copy_in_user.o user_fixup.o memmove.o \ + mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o + +obj-y += iomap.o diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c index b64aee993..3008d536e 100644 --- a/arch/sparc64/lib/PeeCeeI.c +++ b/arch/sparc64/lib/PeeCeeI.c @@ -7,7 +7,7 @@ #include #include -void outsb(unsigned long addr, const void *src, unsigned long count) +void outsb(void __iomem *addr, const void *src, unsigned long count) { const u8 *p = src; @@ -15,7 +15,7 @@ void outsb(unsigned long addr, const void *src, unsigned long count) outb(*p++, addr); } -void outsw(unsigned long addr, const void *src, unsigned long count) +void outsw(void __iomem *addr, const void *src, unsigned long count) { if(count) { u16 *ps = (u16 *)src; @@ -44,7 +44,7 @@ void outsw(unsigned long addr, const void *src, unsigned long count) } } -void outsl(unsigned long addr, const void *src, unsigned long count) +void outsl(void __iomem *addr, const void *src, unsigned long count) { if(count) { if((((u64)src) & 0x3) == 0) { @@ -119,7 +119,7 @@ void outsl(unsigned long addr, const void *src, unsigned long count) } } -void insb(unsigned long addr, void *dst, unsigned long count) +void insb(void __iomem *addr, void *dst, unsigned long count) { if(count) { u32 *pi; @@ -144,7 +144,7 @@ void insb(unsigned long addr, void *dst, unsigned long count) } } -void insw(unsigned long addr, void *dst, unsigned long count) +void insw(void __iomem *addr, void *dst, unsigned long count) { if(count) { u16 *ps = dst; @@ -169,7 +169,7 @@ void insw(unsigned long addr, void *dst, unsigned long count) } } -void insl(unsigned long addr, void *dst, unsigned long count) +void insl(void __iomem *addr, void *dst, unsigned long count) { if(count) { if((((unsigned long)dst) & 0x3) == 0) { diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S index 46b446b14..df600b667 100644 --- a/arch/sparc64/lib/U3copy_from_user.S +++ b/arch/sparc64/lib/U3copy_from_user.S @@ -3,410 +3,20 @@ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ -#include -#include -#include -#include - -#define XCC xcc - -#define EXNV_RAW(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: ba U3cfu_fixup; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: add %o1, %o3, %o0; \ - ba U3cfu_fixup; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV4(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: add %o1, %o3, %o0; \ - a, b, %o1; \ - ba U3cfu_fixup; \ - add %o1, 4, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV8(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: add %o1, %o3, %o0; \ - a, b, %o1; \ - ba U3cfu_fixup; \ - add %o1, 8, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - ba U3cfu_fixup; \ - a, b, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX2(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - add %o1, %o4, %o1; \ - ba U3cfu_fixup; \ - add %o1, 0x1c0, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX3(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - sll %g3, 6, %g3; \ - add %o1, 0x80, %o1; \ - ba U3cfu_fixup; \ - add %o1, %g3, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX4(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o1; \ - add %o1, 0x40, %o1; \ - ba U3cfu_fixup; \ - add %o1, %g3, %o1; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - - .register %g2,#scratch - .register %g3,#scratch - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - */ - - .text - .align 32 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ - - .globl U3copy_from_user -U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */ - cmp %o2, 0 - be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 - bleu,a,pn %XCC, 80f - or %o3, %o2, %o3 - - cmp %o2, 256 - blu,pt %XCC, 70f - andcc %o3, 0x7, %g0 - - ba,pt %xcc, 1f - andcc %o0, 0x3f, %g2 - - /* Here len >= 256 and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. - */ - .align 64 -1: - /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %XCC, 2f - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x40, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: EXNV_RAW(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2) - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - - bg,pt %XCC, 1b - stb %o3, [%o0 + -1] - -2: VISEntryHalf - and %o1, 0x7, %g1 - ba,pt %xcc, 1f - alignaddr %o1, %g0, %o1 - - .align 64 -1: - membar #StoreLoad | #StoreStore | #LoadStore - prefetcha [%o1 + 0x000] %asi, #one_read - prefetcha [%o1 + 0x040] %asi, #one_read - andn %o2, (0x40 - 1), %o4 - prefetcha [%o1 + 0x080] %asi, #one_read - prefetcha [%o1 + 0x0c0] %asi, #one_read - EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) - prefetcha [%o1 + 0x100] %asi, #one_read - EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) - prefetcha [%o1 + 0x140] %asi, #one_read - EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) - prefetcha [%o1 + 0x180] %asi, #one_read - faligndata %f0, %f2, %f16 - EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) - faligndata %f2, %f4, %f18 - EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) - faligndata %f4, %f6, %f20 - EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) - faligndata %f6, %f8, %f22 - - EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) - faligndata %f8, %f10, %f24 - EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) - faligndata %f10, %f12, %f26 - EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) - - sub %o4, 0x80, %o4 - add %o1, 0x40, %o1 - ba,pt %xcc, 1f - srl %o4, 6, %o3 - - .align 64 -1: - EX3(ldda [%o1 + 0x008] %asi, %f2) - faligndata %f12, %f14, %f28 - EX3(ldda [%o1 + 0x010] %asi, %f4) - faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P - EX3(ldda [%o1 + 0x018] %asi, %f6) - faligndata %f0, %f2, %f16 - - EX3(ldda [%o1 + 0x020] %asi, %f8) - faligndata %f2, %f4, %f18 - EX3(ldda [%o1 + 0x028] %asi, %f10) - faligndata %f4, %f6, %f20 - EX3(ldda [%o1 + 0x030] %asi, %f12) - faligndata %f6, %f8, %f22 - EX3(ldda [%o1 + 0x038] %asi, %f14) - faligndata %f8, %f10, %f24 - - EX3(ldda [%o1 + 0x040] %asi, %f0) - prefetcha [%o1 + 0x180] %asi, #one_read - faligndata %f10, %f12, %f26 - subcc %o3, 0x01, %o3 - add %o1, 0x40, %o1 - bg,pt %XCC, 1b - add %o0, 0x40, %o0 - - /* Finally we copy the last full 64-byte block. */ - EX3(ldda [%o1 + 0x008] %asi, %f2) - faligndata %f12, %f14, %f28 - EX3(ldda [%o1 + 0x010] %asi, %f4) - faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P - EX3(ldda [%o1 + 0x018] %asi, %f6) - faligndata %f0, %f2, %f16 - EX3(ldda [%o1 + 0x020] %asi, %f8) - faligndata %f2, %f4, %f18 - EX3(ldda [%o1 + 0x028] %asi, %f10) - faligndata %f4, %f6, %f20 - EX3(ldda [%o1 + 0x030] %asi, %f12) - faligndata %f6, %f8, %f22 - EX3(ldda [%o1 + 0x038] %asi, %f14) - faligndata %f8, %f10, %f24 - cmp %g1, 0 - be,pt %XCC, 1f - add %o0, 0x40, %o0 - EX4(ldda [%o1 + 0x040] %asi, %f0) -1: faligndata %f10, %f12, %f26 - faligndata %f12, %f14, %f28 - faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P - add %o0, 0x40, %o0 - add %o1, 0x40, %o1 - - membar #Sync - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer. - */ - and %o2, 0x3f, %o2 - andcc %o2, 0x38, %g2 - be,pn %XCC, 10f - subcc %g2, 0x8, %g2 - be,pn %XCC, 10f - cmp %g1, 0 - - be,a,pt %XCC, 1f - EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) - -1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) - add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 - subcc %g2, 0x8, %g2 - faligndata %f0, %f2, %f8 - std %f8, [%o0 + 0x00] - be,pn %XCC, 10f - add %o0, 0x8, %o0 - EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) - add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 - subcc %g2, 0x8, %g2 - faligndata %f2, %f0, %f8 - std %f8, [%o0 + 0x00] - bne,pn %XCC, 1b - add %o0, 0x8, %o0 - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -10: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %XCC, 85f - sub %o0, %o1, %o3 - - andcc %g1, 0x7, %g0 - bne,pn %icc, 90f - andcc %o2, 0x8, %g0 - be,pt %icc, 1f - nop - EXNV(ldxa [%o1] %asi, %o5, add %o2, %g0) - stx %o5, [%o1 + %o3] - add %o1, 0x8, %o1 - -1: andcc %o2, 0x4, %g0 - be,pt %icc, 1f - nop - EXNV(lduwa [%o1] %asi, %o5, and %o2, 0x7) - stw %o5, [%o1 + %o3] - add %o1, 0x4, %o1 - -1: andcc %o2, 0x2, %g0 - be,pt %icc, 1f - nop - EXNV(lduha [%o1] %asi, %o5, and %o2, 0x3) - sth %o5, [%o1 + %o3] - add %o1, 0x2, %o1 - -1: andcc %o2, 0x1, %g0 - be,pt %icc, 85f - nop - EXNV(lduba [%o1] %asi, %o5, and %o2, 0x1) - ba,pt %xcc, 85f - stb %o5, [%o1 + %o3] - -70: /* 16 < len <= 64 */ - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - - andn %o2, 0x7, %o4 - and %o2, 0x7, %o2 -1: subcc %o4, 0x8, %o4 - EXNV8(ldxa [%o1] %asi, %o5, add %o2, %o4) - stx %o5, [%o1 + %o3] - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 - EXNV4(lduwa [%o1] %asi, %o5, add %o2, %g0) - stw %o5, [%o1 + %o3] - add %o1, 0x4, %o1 -1: cmp %o2, 0 - be,pt %XCC, 85f - nop - ba,pt %xcc, 90f - nop - -80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - -1: - subcc %o2, 4, %o2 - EXNV(lduwa [%o1] %asi, %g1, add %o2, %g0) - stw %g1, [%o1 + %o3] - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -85: retl - clr %o0 - - .align 32 -90: - subcc %o2, 1, %o2 - EXNV(lduba [%o1] %asi, %g1, add %o2, %g0) - stb %g1, [%o1 + %o3] - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - clr %o0 - -U3cfu_fixup: - /* Since this is copy_from_user(), zero out the rest of the - * kernel buffer. - */ - cmp %o1, 0 - ble,pn %icc, 2f - mov %o1, %g2 - -1: subcc %g2, 1, %g2 - stb %g0, [%o0] - bne,pt %icc, 1b - add %o0, 1, %o0 - -2: retl - mov %o1, %o0 +#define EX_LD(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; + +#define FUNC_NAME U3copy_from_user +#define LOAD(type,addr,dest) type##a [addr] %asi, dest +#define EX_RETVAL(x) 0 + +#include "U3memcpy.S" diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S index 715227156..f337f22ed 100644 --- a/arch/sparc64/lib/U3copy_to_user.S +++ b/arch/sparc64/lib/U3copy_to_user.S @@ -1,415 +1,33 @@ -/* U3copy_to_user.S: UltraSparc-III optimized memcpy. +/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace. * * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) */ -#include -#include -#include -#include - -#define XCC xcc - -#define EXNV(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV2(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 1, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV3(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 4, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXNV4(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: a, b, %o0; \ - retl; \ - add %o0, 8, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EX(x,y,a,b) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - retl; \ - a, b, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ +#define EX_ST(x) \ +98: x; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + mov 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ .align 4; -#define EXBLK1(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - add %o4, 0x1c0, %o1; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK2(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - sll %o3, 6, %o3; \ - and %o2, (0x40 - 1), %o2; \ - add %o3, 0x80, %o1; \ - retl; \ - add %o1, %o2, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK3(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x80, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; -#define EXBLK4(x,y) \ -98: x,y; \ - .section .fixup; \ - .align 4; \ -99: VISExitHalf; \ - and %o2, (0x40 - 1), %o2; \ - retl; \ - add %o2, 0x40, %o0; \ - .section __ex_table; \ - .align 4; \ - .word 98b, 99b; \ - .text; \ - .align 4; - - .register %g2,#scratch - .register %g3,#scratch - - /* Special/non-trivial issues of this code: - * - * 1) %o5 is preserved from VISEntryHalf to VISExitHalf - * 2) Only low 32 FPU registers are used so that only the - * lower half of the FPU register set is dirtied by this - * code. This is especially important in the kernel. - * 3) This code never prefetches cachelines past the end - * of the source buffer. - */ - - .text - .align 32 - /* The cheetah's flexible spine, oversized liver, enlarged heart, - * slender muscular body, and claws make it the swiftest hunter - * in Africa and the fastest animal on land. Can reach speeds - * of up to 2.4GB per second. - */ +#define FUNC_NAME U3copy_to_user +#define STORE(type,src,addr) type##a src, [addr] ASI_AIUS +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_AIUS +#define EX_RETVAL(x) 0 - .globl U3copy_to_user -U3copy_to_user: /* %o0=dst, %o1=src, %o2=len */ /* Writing to %asi is _expensive_ so we hardcode it. * Reading %asi to check for KERNEL_DS is comparatively * cheap. */ - rd %asi, %g1 - cmp %g1, ASI_AIUS - bne,pn %icc, U3memcpy_user_stub - nop - - cmp %o2, 0 - be,pn %XCC, 85f - or %o0, %o1, %o3 - cmp %o2, 16 - bleu,a,pn %XCC, 80f - or %o3, %o2, %o3 - - cmp %o2, 256 - blu,pt %XCC, 70f - andcc %o3, 0x7, %g0 - - ba,pt %xcc, 1f - andcc %o0, 0x3f, %g2 - - /* Here len >= 256 and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. - */ - .align 64 -1: - /* Is 'dst' already aligned on an 64-byte boundary? */ - be,pt %XCC, 2f - - /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number - * of bytes to copy to make 'dst' 64-byte aligned. We pre- - * subtract this from 'len'. - */ - sub %g2, 0x40, %g2 - sub %g0, %g2, %g2 - sub %o2, %g2, %o2 - - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 - - bg,pt %XCC, 1b - EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) - -2: VISEntryHalf - and %o1, 0x7, %g1 - ba,pt %xcc, 1f - alignaddr %o1, %g0, %o1 - - .align 64 -1: - membar #StoreLoad | #StoreStore | #LoadStore - prefetch [%o1 + 0x000], #one_read - prefetch [%o1 + 0x040], #one_read - andn %o2, (0x40 - 1), %o4 - prefetch [%o1 + 0x080], #one_read - prefetch [%o1 + 0x0c0], #one_read - ldd [%o1 + 0x000], %f0 - prefetch [%o1 + 0x100], #one_read - ldd [%o1 + 0x008], %f2 - prefetch [%o1 + 0x140], #one_read - ldd [%o1 + 0x010], %f4 - prefetch [%o1 + 0x180], #one_read - faligndata %f0, %f2, %f16 - ldd [%o1 + 0x018], %f6 - faligndata %f2, %f4, %f18 - ldd [%o1 + 0x020], %f8 - faligndata %f4, %f6, %f20 - ldd [%o1 + 0x028], %f10 - faligndata %f6, %f8, %f22 - - ldd [%o1 + 0x030], %f12 - faligndata %f8, %f10, %f24 - ldd [%o1 + 0x038], %f14 - faligndata %f10, %f12, %f26 - ldd [%o1 + 0x040], %f0 - - sub %o4, 0x80, %o4 - add %o1, 0x40, %o1 - ba,pt %xcc, 1f - srl %o4, 6, %o3 - - .align 64 -1: - ldd [%o1 + 0x008], %f2 - faligndata %f12, %f14, %f28 - ldd [%o1 + 0x010], %f4 - faligndata %f14, %f0, %f30 - EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS) - ldd [%o1 + 0x018], %f6 - faligndata %f0, %f2, %f16 - - ldd [%o1 + 0x020], %f8 - faligndata %f2, %f4, %f18 - ldd [%o1 + 0x028], %f10 - faligndata %f4, %f6, %f20 - ldd [%o1 + 0x030], %f12 - faligndata %f6, %f8, %f22 - ldd [%o1 + 0x038], %f14 - faligndata %f8, %f10, %f24 - - ldd [%o1 + 0x040], %f0 - prefetch [%o1 + 0x180], #one_read - faligndata %f10, %f12, %f26 - subcc %o3, 0x01, %o3 - add %o1, 0x40, %o1 - bg,pt %XCC, 1b - add %o0, 0x40, %o0 - - /* Finally we copy the last full 64-byte block. */ - ldd [%o1 + 0x008], %f2 - faligndata %f12, %f14, %f28 - ldd [%o1 + 0x010], %f4 - faligndata %f14, %f0, %f30 - EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS) - ldd [%o1 + 0x018], %f6 - faligndata %f0, %f2, %f16 - ldd [%o1 + 0x020], %f8 - faligndata %f2, %f4, %f18 - ldd [%o1 + 0x028], %f10 - faligndata %f4, %f6, %f20 - ldd [%o1 + 0x030], %f12 - faligndata %f6, %f8, %f22 - ldd [%o1 + 0x038], %f14 - faligndata %f8, %f10, %f24 - cmp %g1, 0 - be,pt %XCC, 1f - add %o0, 0x40, %o0 - ldd [%o1 + 0x040], %f0 -1: faligndata %f10, %f12, %f26 - faligndata %f12, %f14, %f28 - faligndata %f14, %f0, %f30 - EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS) - add %o0, 0x40, %o0 - add %o1, 0x40, %o1 - - membar #Sync - - /* Now we copy the (len modulo 64) bytes at the end. - * Note how we borrow the %f0 loaded above. - * - * Also notice how this code is careful not to perform a - * load past the end of the src buffer. - */ - and %o2, 0x3f, %o2 - andcc %o2, 0x38, %g2 - be,pn %XCC, 2f - subcc %g2, 0x8, %g2 - be,pn %XCC, 2f - cmp %g1, 0 - - be,a,pt %XCC, 1f - ldd [%o1 + 0x00], %f0 - -1: ldd [%o1 + 0x08], %f2 - add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 - subcc %g2, 0x8, %g2 - faligndata %f0, %f2, %f8 - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) - be,pn %XCC, 2f - add %o0, 0x8, %o0 - ldd [%o1 + 0x08], %f0 - add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 - subcc %g2, 0x8, %g2 - faligndata %f2, %f0, %f8 - EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) - bne,pn %XCC, 1b - add %o0, 0x8, %o0 - - /* If anything is left, we copy it one byte at a time. - * Note that %g1 is (src & 0x3) saved above before the - * alignaddr was performed. - */ -2: - cmp %o2, 0 - add %o1, %g1, %o1 - VISExitHalf - be,pn %XCC, 85f - sub %o0, %o1, %o3 - - andcc %g1, 0x7, %g0 - bne,pn %icc, 90f - andcc %o2, 0x8, %g0 - be,pt %icc, 1f - nop - ldx [%o1], %o5 - EXNV(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0) - add %o1, 0x8, %o1 - -1: andcc %o2, 0x4, %g0 - be,pt %icc, 1f - nop - lduw [%o1], %o5 - EXNV(stwa %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x7) - add %o1, 0x4, %o1 - -1: andcc %o2, 0x2, %g0 - be,pt %icc, 1f - nop - lduh [%o1], %o5 - EXNV(stha %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x3) - add %o1, 0x2, %o1 - -1: andcc %o2, 0x1, %g0 - be,pt %icc, 85f - nop - ldub [%o1], %o5 - ba,pt %xcc, 85f - EXNV(stba %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x1) - -70: /* 16 < len <= 64 */ - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - - andn %o2, 0x7, %o4 - and %o2, 0x7, %o2 -1: subcc %o4, 0x8, %o4 - ldx [%o1], %o5 - EXNV4(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %o4) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 - lduw [%o1], %o5 - EXNV3(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0) - add %o1, 0x4, %o1 -1: cmp %o2, 0 - be,pt %XCC, 85f - nop - ba,pt %xcc, 90f - nop - -80: /* 0 < len <= 16 */ - andcc %o3, 0x3, %g0 - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - -1: - subcc %o2, 4, %o2 - lduw [%o1], %g1 - EXNV3(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -85: retl - clr %o0 +#define PREAMBLE \ + rd %asi, %g1; \ + cmp %g1, ASI_AIUS; \ + bne,pn %icc, memcpy_user_stub; \ + nop; \ - .align 32 -90: - subcc %o2, 1, %o2 - ldub [%o1], %g1 - EXNV2(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl - clr %o0 +#include "U3memcpy.S" diff --git a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S index e9982deef..5cde95446 100644 --- a/arch/sparc64/lib/U3memcpy.S +++ b/arch/sparc64/lib/U3memcpy.S @@ -6,14 +6,50 @@ #ifdef __KERNEL__ #include #include -#include -#include #else #define ASI_BLK_P 0xf0 #define FPRS_FEF 0x04 +#ifdef MEMCPY_DEBUG +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \ + clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0; +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#else #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs #endif +#endif + +#ifndef EX_LD +#define EX_LD(x) x +#endif + +#ifndef EX_ST +#define EX_ST(x) x +#endif + +#ifndef EX_RETVAL +#define EX_RETVAL(x) x +#endif + +#ifndef LOAD +#define LOAD(type,addr,dest) type [addr], dest +#endif + +#ifndef STORE +#define STORE(type,src,addr) type src, [addr] +#endif + +#ifndef STORE_BLK +#define STORE_BLK(src,addr) stda src, [addr] ASI_BLK_P +#endif + +#ifndef FUNC_NAME +#define FUNC_NAME U3memcpy +#endif + +#ifndef PREAMBLE +#define PREAMBLE +#endif #ifndef XCC #define XCC xcc @@ -33,7 +69,7 @@ */ .text - .align 32 + .align 64 /* The cheetah's flexible spine, oversized liver, enlarged heart, * slender muscular body, and claws make it the swiftest hunter @@ -41,137 +77,158 @@ * of up to 2.4GB per second. */ - .globl U3memcpy -U3memcpy: /* %o0=dst, %o1=src, %o2=len */ + .globl FUNC_NAME + .type FUNC_NAME,#function +FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + PREAMBLE mov %o0, %g5 cmp %o2, 0 be,pn %XCC, 85f or %o0, %o1, %o3 cmp %o2, 16 - bleu,a,pn %XCC, 70f + blu,a,pn %XCC, 80f or %o3, %o2, %o3 - cmp %o2, 256 - blu,pt %XCC, 80f + cmp %o2, (3 * 64) + blu,pt %XCC, 70f andcc %o3, 0x7, %g0 - ba,pt %xcc, 1f - andcc %o0, 0x3f, %g2 - - /* Here len >= 256 and condition codes reflect execution - * of "andcc %o0, 0x7, %g2", done by caller. + /* Clobbers o5/g1/g2/g3/g7/icc/xcc. We must preserve + * o5 from here until we hit VISExitHalf. */ - .align 64 -1: + VISEntryHalf + /* Is 'dst' already aligned on an 64-byte boundary? */ + andcc %o0, 0x3f, %g2 be,pt %XCC, 2f /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number * of bytes to copy to make 'dst' 64-byte aligned. We pre- * subtract this from 'len'. */ - sub %g2, 0x40, %g2 + sub %o0, %o1, %o4 + sub %g2, 0x40, %g2 sub %g0, %g2, %g2 sub %o2, %g2, %o2 + andcc %g2, 0x7, %g1 + be,pt %icc, 2f + and %g2, 0x38, %g2 - /* Copy %g2 bytes from src to dst, one byte at a time. */ -1: ldub [%o1 + 0x00], %o3 - add %o1, 0x1, %o1 - add %o0, 0x1, %o0 - subcc %g2, 0x1, %g2 +1: subcc %g1, 0x1, %g1 + EX_LD(LOAD(ldub, %o1 + 0x00, %o3)) + EX_ST(STORE(stb, %o3, %o1 + %o4)) + bgu,pt %XCC, 1b + add %o1, 0x1, %o1 - bg,pt %XCC, 1b - stb %o3, [%o0 + -1] + add %o1, %o4, %o0 -2: VISEntryHalf +2: cmp %g2, 0x0 and %o1, 0x7, %g1 - ba,pt %xcc, 1f + be,pt %icc, 3f alignaddr %o1, %g0, %o1 - .align 64 -1: - membar #StoreLoad | #StoreStore | #LoadStore - prefetch [%o1 + 0x000], #one_read - prefetch [%o1 + 0x040], #one_read + EX_LD(LOAD(ldd, %o1, %f4)) +1: EX_LD(LOAD(ldd, %o1 + 0x8, %f6)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f4, %f6, %f0 + EX_ST(STORE(std, %f0, %o0)) + be,pn %icc, 3f + add %o0, 0x8, %o0 + + EX_LD(LOAD(ldd, %o1 + 0x8, %f4)) + add %o1, 0x8, %o1 + subcc %g2, 0x8, %g2 + faligndata %f6, %f4, %f2 + EX_ST(STORE(std, %f2, %o0)) + bne,pt %icc, 1b + add %o0, 0x8, %o0 + +3: LOAD(prefetch, %o1 + 0x000, #one_read) + LOAD(prefetch, %o1 + 0x040, #one_read) andn %o2, (0x40 - 1), %o4 - prefetch [%o1 + 0x080], #one_read - prefetch [%o1 + 0x0c0], #one_read - ldd [%o1 + 0x000], %f0 - prefetch [%o1 + 0x100], #one_read - ldd [%o1 + 0x008], %f2 - prefetch [%o1 + 0x140], #one_read - ldd [%o1 + 0x010], %f4 - prefetch [%o1 + 0x180], #one_read + LOAD(prefetch, %o1 + 0x080, #one_read) + LOAD(prefetch, %o1 + 0x0c0, #one_read) + LOAD(prefetch, %o1 + 0x100, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x000, %f0)) + LOAD(prefetch, %o1 + 0x140, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) + LOAD(prefetch, %o1 + 0x180, #one_read) + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) + LOAD(prefetch, %o1 + 0x1c0, #one_read) faligndata %f0, %f2, %f16 - ldd [%o1 + 0x018], %f6 + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) faligndata %f2, %f4, %f18 - ldd [%o1 + 0x020], %f8 + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) faligndata %f4, %f6, %f20 - ldd [%o1 + 0x028], %f10 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) faligndata %f6, %f8, %f22 - ldd [%o1 + 0x030], %f12 + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) faligndata %f8, %f10, %f24 - ldd [%o1 + 0x038], %f14 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) faligndata %f10, %f12, %f26 - ldd [%o1 + 0x040], %f0 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) - sub %o4, 0x80, %o4 + subcc %o4, 0x80, %o4 add %o1, 0x40, %o1 - ba,pt %xcc, 1f + bgu,pt %XCC, 1f srl %o4, 6, %o3 + ba,pt %xcc, 2f + nop .align 64 1: - ldd [%o1 + 0x008], %f2 + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) faligndata %f12, %f14, %f28 - ldd [%o1 + 0x010], %f4 + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P - ldd [%o1 + 0x018], %f6 + EX_ST(STORE_BLK(%f16, %o0)) + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) faligndata %f0, %f2, %f16 + add %o0, 0x40, %o0 - ldd [%o1 + 0x020], %f8 + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) faligndata %f2, %f4, %f18 - ldd [%o1 + 0x028], %f10 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) faligndata %f4, %f6, %f20 - ldd [%o1 + 0x030], %f12 + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) + subcc %o3, 0x01, %o3 faligndata %f6, %f8, %f22 - ldd [%o1 + 0x038], %f14 - faligndata %f8, %f10, %f24 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) - ldd [%o1 + 0x040], %f0 - prefetch [%o1 + 0x180], #one_read + faligndata %f8, %f10, %f24 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) + LOAD(prefetch, %o1 + 0x1c0, #one_read) faligndata %f10, %f12, %f26 - subcc %o3, 0x01, %o3 - add %o1, 0x40, %o1 bg,pt %XCC, 1b - add %o0, 0x40, %o0 + add %o1, 0x40, %o1 /* Finally we copy the last full 64-byte block. */ - ldd [%o1 + 0x008], %f2 +2: + EX_LD(LOAD(ldd, %o1 + 0x008, %f2)) faligndata %f12, %f14, %f28 - ldd [%o1 + 0x010], %f4 + EX_LD(LOAD(ldd, %o1 + 0x010, %f4)) faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P - ldd [%o1 + 0x018], %f6 + EX_ST(STORE_BLK(%f16, %o0)) + EX_LD(LOAD(ldd, %o1 + 0x018, %f6)) faligndata %f0, %f2, %f16 - ldd [%o1 + 0x020], %f8 + EX_LD(LOAD(ldd, %o1 + 0x020, %f8)) faligndata %f2, %f4, %f18 - ldd [%o1 + 0x028], %f10 + EX_LD(LOAD(ldd, %o1 + 0x028, %f10)) faligndata %f4, %f6, %f20 - ldd [%o1 + 0x030], %f12 + EX_LD(LOAD(ldd, %o1 + 0x030, %f12)) faligndata %f6, %f8, %f22 - ldd [%o1 + 0x038], %f14 + EX_LD(LOAD(ldd, %o1 + 0x038, %f14)) faligndata %f8, %f10, %f24 cmp %g1, 0 be,pt %XCC, 1f add %o0, 0x40, %o0 - ldd [%o1 + 0x040], %f0 + EX_LD(LOAD(ldd, %o1 + 0x040, %f0)) 1: faligndata %f10, %f12, %f26 faligndata %f12, %f14, %f28 faligndata %f14, %f0, %f30 - stda %f16, [%o0] ASI_BLK_P + EX_ST(STORE_BLK(%f16, %o0)) add %o0, 0x40, %o0 add %o1, 0x40, %o1 membar #Sync @@ -189,23 +246,22 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */ be,pn %XCC, 2f cmp %g1, 0 + sub %o2, %g2, %o2 be,a,pt %XCC, 1f - ldd [%o1 + 0x00], %f0 + EX_LD(LOAD(ldd, %o1 + 0x00, %f0)) -1: ldd [%o1 + 0x08], %f2 +1: EX_LD(LOAD(ldd, %o1 + 0x08, %f2)) add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 subcc %g2, 0x8, %g2 faligndata %f0, %f2, %f8 - std %f8, [%o0 + 0x00] + EX_ST(STORE(std, %f8, %o0)) be,pn %XCC, 2f add %o0, 0x8, %o0 - ldd [%o1 + 0x08], %f0 + EX_LD(LOAD(ldd, %o1 + 0x08, %f0)) add %o1, 0x8, %o1 - sub %o2, 0x8, %o2 subcc %g2, 0x8, %g2 faligndata %f2, %f0, %f8 - std %f8, [%o0 + 0x00] + EX_ST(STORE(std, %f8, %o0)) bne,pn %XCC, 1b add %o0, 0x8, %o0 @@ -225,48 +281,60 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */ andcc %o2, 0x8, %g0 be,pt %icc, 1f nop - ldx [%o1], %o5 - stx %o5, [%o1 + %o3] + EX_LD(LOAD(ldx, %o1, %o5)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) add %o1, 0x8, %o1 1: andcc %o2, 0x4, %g0 be,pt %icc, 1f nop - lduw [%o1], %o5 - stw %o5, [%o1 + %o3] + EX_LD(LOAD(lduw, %o1, %o5)) + EX_ST(STORE(stw, %o5, %o1 + %o3)) add %o1, 0x4, %o1 1: andcc %o2, 0x2, %g0 be,pt %icc, 1f nop - lduh [%o1], %o5 - sth %o5, [%o1 + %o3] + EX_LD(LOAD(lduh, %o1, %o5)) + EX_ST(STORE(sth, %o5, %o1 + %o3)) add %o1, 0x2, %o1 1: andcc %o2, 0x1, %g0 be,pt %icc, 85f nop - ldub [%o1], %o5 + EX_LD(LOAD(ldub, %o1, %o5)) ba,pt %xcc, 85f - stb %o5, [%o1 + %o3] + EX_ST(STORE(stb, %o5, %o1 + %o3)) + .align 64 70: /* 16 < len <= 64 */ - bne,pn %XCC, 90f + bne,pn %XCC, 75f sub %o0, %o1, %o3 - andn %o2, 0x7, %o4 - and %o2, 0x7, %o2 -1: subcc %o4, 0x8, %o4 - ldx [%o1], %o5 - stx %o5, [%o1 + %o3] +72: + andn %o2, 0xf, %o4 + and %o2, 0xf, %o2 +1: subcc %o4, 0x10, %o4 + EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) + EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 + EX_ST(STORE(stx, %g1, %o1 + %o3)) bgu,pt %XCC, 1b add %o1, 0x8, %o1 - andcc %o2, 0x4, %g0 +73: andcc %o2, 0x8, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x8, %o2 + EX_LD(LOAD(ldx, %o1, %o5)) + EX_ST(STORE(stx, %o5, %o1 + %o3)) + add %o1, 0x8, %o1 +1: andcc %o2, 0x4, %g0 be,pt %XCC, 1f nop sub %o2, 0x4, %o2 - lduw [%o1], %o5 - stw %o5, [%o1 + %o3] + EX_LD(LOAD(lduw, %o1, %o5)) + EX_ST(STORE(stw, %o5, %o1 + %o3)) add %o1, 0x4, %o1 1: cmp %o2, 0 be,pt %XCC, 85f @@ -274,6 +342,53 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 90f nop +75: + andcc %o0, 0x7, %g1 + sub %g1, 0x8, %g1 + be,pn %icc, 2f + sub %g0, %g1, %g1 + sub %o2, %g1, %o2 + +1: subcc %g1, 1, %g1 + EX_LD(LOAD(ldub, %o1, %o5)) + EX_ST(STORE(stb, %o5, %o1 + %o3)) + bgu,pt %icc, 1b + add %o1, 1, %o1 + +2: add %o1, %o3, %o0 + andcc %o1, 0x7, %g1 + bne,pt %icc, 8f + sll %g1, 3, %g1 + + cmp %o2, 16 + bgeu,pt %icc, 72b + nop + ba,a,pt %xcc, 73b + +8: mov 64, %o3 + andn %o1, 0x7, %o1 + EX_LD(LOAD(ldx, %o1, %g2)) + sub %o3, %g1, %o3 + andn %o2, 0x7, %o4 + sllx %g2, %g1, %g2 +1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) + subcc %o4, 0x8, %o4 + add %o1, 0x8, %o1 + srlx %g3, %o3, %o5 + or %o5, %g2, %o5 + EX_ST(STORE(stx, %o5, %o0)) + add %o0, 0x8, %o0 + bgu,pt %icc, 1b + sllx %g3, %g1, %g2 + + srl %g1, 3, %g1 + andcc %o2, 0x7, %o2 + be,pn %icc, 85f + add %o1, %g1, %o1 + ba,pt %xcc, 90f + sub %o0, %o1, %o3 + + .align 64 80: /* 0 < len <= 16 */ andcc %o3, 0x3, %g0 bne,pn %XCC, 90f @@ -281,34 +396,22 @@ U3memcpy: /* %o0=dst, %o1=src, %o2=len */ 1: subcc %o2, 4, %o2 - lduw [%o1], %g1 - stw %g1, [%o1 + %o3] + EX_LD(LOAD(lduw, %o1, %g1)) + EX_ST(STORE(stw, %g1, %o1 + %o3)) bgu,pt %XCC, 1b add %o1, 4, %o1 85: retl - mov %g5, %o0 + mov EX_RETVAL(%g5), %o0 - .align 32 + .align 32 90: subcc %o2, 1, %o2 - ldub [%o1], %g1 - stb %g1, [%o1 + %o3] + EX_LD(LOAD(ldub, %o1, %g1)) + EX_ST(STORE(stb, %g1, %o1 + %o3)) bgu,pt %XCC, 90b add %o1, 1, %o1 retl - mov %g5, %o0 + mov EX_RETVAL(%g5), %o0 - /* Act like copy_{to,in}_user(), ie. return zero instead - * of original destination pointer. This is invoked when - * copy_{to,in}_user() finds that %asi is kernel space. - */ - .globl U3memcpy_user_stub -U3memcpy_user_stub: - save %sp, -192, %sp - mov %i0, %o0 - mov %i1, %o1 - call U3memcpy - mov %i2, %o2 - ret - restore %g0, %g0, %o0 + .size FUNC_NAME, .-FUNC_NAME diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S index a0d6d8ac3..26463d8a4 100644 --- a/arch/sparc64/lib/atomic.S +++ b/arch/sparc64/lib/atomic.S @@ -10,6 +10,7 @@ .align 64 .globl __atomic_add + .type __atomic_add,#function __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ lduw [%o1], %g5 add %g5, %o0, %g7 @@ -19,8 +20,10 @@ __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ membar #StoreLoad | #StoreStore retl add %g7, %o0, %o0 + .size __atomic_add, .-__atomic_add .globl __atomic_sub + .type __atomic_sub,#function __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */ lduw [%o1], %g5 sub %g5, %o0, %g7 @@ -30,8 +33,10 @@ __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */ membar #StoreLoad | #StoreStore retl sub %g7, %o0, %o0 + .size __atomic_sub, .-__atomic_sub .globl __atomic64_add + .type __atomic64_add,#function __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ ldx [%o1], %g5 add %g5, %o0, %g7 @@ -41,8 +46,10 @@ __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ membar #StoreLoad | #StoreStore retl add %g7, %o0, %o0 + .size __atomic64_add, .-__atomic64_add .globl __atomic64_sub + .type __atomic64_sub,#function __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */ ldx [%o1], %g5 sub %g5, %o0, %g7 @@ -52,4 +59,4 @@ __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */ membar #StoreLoad | #StoreStore retl sub %g7, %o0, %o0 - + .size __atomic64_sub, .-__atomic64_sub diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S index 0c2aacc83..c1e370068 100644 --- a/arch/sparc64/lib/bitops.S +++ b/arch/sparc64/lib/bitops.S @@ -9,6 +9,7 @@ .text .align 64 .globl ___test_and_set_bit + .type ___test_and_set_bit,#function ___test_and_set_bit: /* %o0=nr, %o1=addr */ srlx %o0, 6, %g1 mov 1, %g5 @@ -26,8 +27,10 @@ ___test_and_set_bit: /* %o0=nr, %o1=addr */ ldx [%o1], %g7 2: retl membar #StoreLoad | #StoreStore + .size ___test_and_set_bit, .-___test_and_set_bit .globl ___test_and_clear_bit + .type ___test_and_clear_bit,#function ___test_and_clear_bit: /* %o0=nr, %o1=addr */ srlx %o0, 6, %g1 mov 1, %g5 @@ -45,8 +48,10 @@ ___test_and_clear_bit: /* %o0=nr, %o1=addr */ ldx [%o1], %g7 2: retl membar #StoreLoad | #StoreStore + .size ___test_and_clear_bit, .-___test_and_clear_bit .globl ___test_and_change_bit + .type ___test_and_change_bit,#function ___test_and_change_bit: /* %o0=nr, %o1=addr */ srlx %o0, 6, %g1 mov 1, %g5 @@ -64,41 +69,4 @@ ___test_and_change_bit: /* %o0=nr, %o1=addr */ 2: retl membar #StoreLoad | #StoreStore nop - - .globl ___test_and_set_le_bit -___test_and_set_le_bit: /* %o0=nr, %o1=addr */ - srlx %o0, 5, %g1 - mov 1, %g5 - sllx %g1, 2, %g3 - and %o0, 31, %g2 - sllx %g5, %g2, %g5 - add %o1, %g3, %o1 - lduwa [%o1] ASI_PL, %g7 -1: andcc %g7, %g5, %o0 - bne,pn %icc, 2f - xor %g7, %g5, %g1 - casa [%o1] ASI_PL, %g7, %g1 - cmp %g7, %g1 - bne,a,pn %icc, 1b - lduwa [%o1] ASI_PL, %g7 -2: retl - membar #StoreLoad | #StoreStore - - .globl ___test_and_clear_le_bit -___test_and_clear_le_bit: /* %o0=nr, %o1=addr */ - srlx %o0, 5, %g1 - mov 1, %g5 - sllx %g1, 2, %g3 - and %o0, 31, %g2 - sllx %g5, %g2, %g5 - add %o1, %g3, %o1 - lduwa [%o1] ASI_PL, %g7 -1: andcc %g7, %g5, %o0 - be,pn %icc, 2f - xor %g7, %g5, %g1 - casa [%o1] ASI_PL, %g7, %g1 - cmp %g7, %g1 - bne,a,pn %icc, 1b - lduwa [%o1] ASI_PL, %g7 -2: retl - membar #StoreLoad | #StoreStore + .size ___test_and_change_bit, .-___test_and_change_bit diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S index 862eefb17..23ebf2c97 100644 --- a/arch/sparc64/lib/copy_page.S +++ b/arch/sparc64/lib/copy_page.S @@ -45,6 +45,7 @@ .align 32 .globl copy_user_page + .type copy_user_page,#function copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ lduw [%g6 + TI_PRE_COUNT], %o4 sethi %uhi(PAGE_OFFSET), %g2 @@ -237,3 +238,5 @@ copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */ retl stw %o4, [%g6 + TI_PRE_COUNT] + + .size copy_user_page, .-copy_user_page diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c index 9e083e27d..9fb4dedc8 100644 --- a/arch/sparc64/lib/debuglocks.c +++ b/arch/sparc64/lib/debuglocks.c @@ -84,7 +84,7 @@ again: put_cpu(); } -int _spin_trylock(spinlock_t *lock) +int _do_spin_trylock(spinlock_t *lock) { unsigned long val, caller; int cpu = get_cpu(); diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S index 399c13509..e86906744 100644 --- a/arch/sparc64/lib/dec_and_lock.S +++ b/arch/sparc64/lib/dec_and_lock.S @@ -25,8 +25,8 @@ * } */ - .globl atomic_dec_and_lock -atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */ + .globl _atomic_dec_and_lock +_atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */ loop1: lduw [%o0], %g5 subcc %g5, 1, %g7 be,pn %icc, start_to_zero diff --git a/arch/sparc64/lib/find_bit.c b/arch/sparc64/lib/find_bit.c index 585261449..27545fbf5 100644 --- a/arch/sparc64/lib/find_bit.c +++ b/arch/sparc64/lib/find_bit.c @@ -1,4 +1,4 @@ -#include +#include /** * find_next_bit - find the next set bit in a memory region diff --git a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S index e7d349fac..58ca5b9a8 100644 --- a/arch/sparc64/lib/ipcsum.S +++ b/arch/sparc64/lib/ipcsum.S @@ -1,6 +1,7 @@ .text - .align 32 - .globl ip_fast_csum + .align 32 + .globl ip_fast_csum + .type ip_fast_csum,#function ip_fast_csum: /* %o0 = iph, %o1 = ihl */ sub %o1, 4, %g7 lduw [%o0 + 0x00], %o2 @@ -30,3 +31,4 @@ ip_fast_csum: /* %o0 = iph, %o1 = ihl */ set 0xffff, %o1 retl and %o2, %o1, %o0 + .size ip_fast_csum, .-ip_fast_csum diff --git a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S index 55527f639..066ec1ed7 100644 --- a/arch/sparc64/lib/strlen.S +++ b/arch/sparc64/lib/strlen.S @@ -9,9 +9,9 @@ #define HI_MAGIC 0x80808080 .align 32 - .global strlen, __strlen + .globl strlen + .type strlen,#function strlen: -__strlen: mov %o0, %o1 andcc %o0, 3, %g0 be,pt %icc, 9f @@ -76,3 +76,5 @@ __strlen: 13: retl mov 2, %o0 + + .size strlen, .-strlen diff --git a/arch/sparc64/lib/strncmp.S b/arch/sparc64/lib/strncmp.S index 474ba7296..6f14f53db 100644 --- a/arch/sparc64/lib/strncmp.S +++ b/arch/sparc64/lib/strncmp.S @@ -7,9 +7,9 @@ #include .text - .align 4 - .global __strncmp, strncmp -__strncmp: + .align 32 + .globl strncmp + .type strncmp,#function strncmp: brlez,pn %o2, 3f lduba [%o0] (ASI_PNF), %o3 @@ -29,3 +29,4 @@ strncmp: 3: retl clr %o0 + .size strncmp, .-strncmp diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S index 9abb371e4..93d600a31 100644 --- a/arch/sparc64/lib/strncpy_from_user.S +++ b/arch/sparc64/lib/strncpy_from_user.S @@ -12,7 +12,7 @@ 0: .xword 0x0101010101010101 .text - .align 4 + .align 32 /* Must return: * @@ -31,6 +31,7 @@ */ .globl __strncpy_from_user + .type __strncpy_from_user,#function __strncpy_from_user: /* %o0=dest, %o1=src, %o2=count */ sethi %hi(0b), %o5 ! IEU0 Group @@ -122,6 +123,7 @@ __strncpy_from_user: mov %o2, %o0 2: retl add %o2, %o3, %o0 + .size __strncpy_from_user, .-__strncpy_from_user .section .fixup,#alloc,#execinstr .align 4 diff --git a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S index 8eeba353d..f748fd6bb 100644 --- a/arch/sparc64/lib/xor.S +++ b/arch/sparc64/lib/xor.S @@ -18,8 +18,9 @@ * !(len & 127) && len >= 256 */ .text - .globl xor_vis_2 - .type xor_vis_2,@function + .align 32 + .globl xor_vis_2 + .type xor_vis_2,#function xor_vis_2: rd %fprs, %o5 andcc %o5, FPRS_FEF|FPRS_DU, %g0 @@ -87,11 +88,10 @@ xor_vis_2: wr %g1, %g0, %asi retl wr %g0, 0, %fprs - .size xor_vis_2, .-xor_vis_2 + .size xor_vis_2, .-xor_vis_2 - - .globl xor_vis_3 - .type xor_vis_3,@function + .globl xor_vis_3 + .type xor_vis_3,#function xor_vis_3: rd %fprs, %o5 andcc %o5, FPRS_FEF|FPRS_DU, %g0 @@ -156,11 +156,10 @@ xor_vis_3: wr %g1, %g0, %asi retl wr %g0, 0, %fprs - .size xor_vis_3, .-xor_vis_3 - + .size xor_vis_3, .-xor_vis_3 - .globl xor_vis_4 - .type xor_vis_4,@function + .globl xor_vis_4 + .type xor_vis_4,#function xor_vis_4: rd %fprs, %o5 andcc %o5, FPRS_FEF|FPRS_DU, %g0 @@ -244,11 +243,10 @@ xor_vis_4: wr %g1, %g0, %asi retl wr %g0, 0, %fprs - .size xor_vis_4, .-xor_vis_4 - + .size xor_vis_4, .-xor_vis_4 - .globl xor_vis_5 - .type xor_vis_5,@function + .globl xor_vis_5 + .type xor_vis_5,#function xor_vis_5: mov %o5, %g5 rd %fprs, %o5 @@ -353,4 +351,4 @@ xor_vis_5: wr %g1, %g0, %asi retl wr %g0, 0, %fprs - .size xor_vis_5, .-xor_vis_5 + .size xor_vis_5, .-xor_vis_5 diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 49c3dd29a..8c07be369 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -27,6 +27,7 @@ #include #include #include +#include #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) @@ -147,6 +148,9 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk, printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", (tsk->mm ? (unsigned long) tsk->mm->pgd : (unsigned long) tsk->active_mm->pgd)); + if (notify_die(DIE_GPF, "general protection fault", regs, + 0, 0, SIGSEGV) == NOTIFY_STOP) + return; die_if_kernel("Oops", regs); } @@ -318,8 +322,13 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) int si_code, fault_code; unsigned long address; - si_code = SEGV_MAPERR; fault_code = get_thread_fault_code(); + + if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, + fault_code, 0, SIGSEGV) == NOTIFY_STOP) + return; + + si_code = SEGV_MAPERR; address = current_thread_info()->fault_address; if ((fault_code & FAULT_CODE_ITLB) && @@ -343,7 +352,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto intr_or_no_mm; if (test_thread_flag(TIF_32BIT)) { @@ -352,7 +361,15 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) address &= 0xffffffff; } - down_read(&mm->mmap_sem); + if (!down_read_trylock(&mm->mmap_sem)) { + if ((regs->tstate & TSTATE_PRIV) && + !search_exception_tables(regs->tpc)) { + insn = get_fault_insn(regs, insn); + goto handle_kernel_fault; + } + down_read(&mm->mmap_sem); + } + vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -437,16 +454,18 @@ good_area: } switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index 149dc1b4c..6be13eb89 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -15,15 +15,7 @@ #include #include -static inline void forget_pte(pte_t page) -{ - if (!pte_none(page)) { - printk("forget_pte: old mapping existed!\n"); - BUG(); - } -} - -/* Remap IO memory, the same way as remap_page_range(), but use +/* Remap IO memory, the same way as remap_pfn_range(), but use * the obio memory space. * * They use a pgprot that sets PAGE_IO and does not check the @@ -43,7 +35,6 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign if (end > PMD_SIZE) end = PMD_SIZE; do { - pte_t oldpage; pte_t entry; unsigned long curend = address + PAGE_SIZE; @@ -75,10 +66,8 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign if (offset & 0x1UL) pte_val(entry) &= ~(_PAGE_E); do { - oldpage = *pte; - pte_clear(pte); + BUG_ON(!pte_none(*pte)); set_pte(pte, entry); - forget_pte(oldpage); address += PAGE_SIZE; pte++; } while (address < curend); @@ -132,8 +121,8 @@ int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned from = (from + PGDIR_SIZE) & PGDIR_MASK; dir++; } + flush_tlb_range(vma, beg, end); spin_unlock(&mm->page_table_lock); - flush_tlb_range(vma, beg, end); return error; } diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 60308cead..e85060445 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -68,6 +68,7 @@ unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; extern char _start[], _end[]; /* Initial ramdisk setup */ +extern unsigned long sparc_ramdisk_image64; extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; @@ -1279,10 +1280,12 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) #ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ - if (sparc_ramdisk_image) { - if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE) - sparc_ramdisk_image -= KERNBASE; - initrd_start = sparc_ramdisk_image + phys_base; + if (sparc_ramdisk_image || sparc_ramdisk_image64) { + unsigned long ramdisk_image = sparc_ramdisk_image ? + sparc_ramdisk_image : sparc_ramdisk_image64; + if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE) + ramdisk_image -= KERNBASE; + initrd_start = ramdisk_image + phys_base; initrd_end = initrd_start + sparc_ramdisk_size; if (initrd_end > end_of_phys_memory) { printk(KERN_CRIT "initrd extends beyond end of memory " @@ -1325,6 +1328,10 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) size = initrd_end - initrd_start; /* Resert the initrd image area. */ +#ifdef CONFIG_DEBUG_BOOTMEM + prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n", + initrd_start, initrd_end); +#endif reserve_bootmem(initrd_start, size); *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -1377,7 +1384,7 @@ void __init paging_init(void) if ((real_end > ((unsigned long)KERNBASE + 0x400000))) bigkernel = 1; #ifdef CONFIG_BLK_DEV_INITRD - if (sparc_ramdisk_image) + if (sparc_ramdisk_image || sparc_ramdisk_image64) real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size)); #endif @@ -1502,7 +1509,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = npages; zholes_size[ZONE_DMA] = npages - pages_avail; - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, phys_base >> PAGE_SHIFT, zholes_size); mem_map = contig_page_data.node_mem_map; } @@ -1738,6 +1745,7 @@ void free_initmem (void) page = (addr + ((unsigned long) __va(kern_base)) - ((unsigned long) KERNBASE)); + memset((void *)addr, 0xcc, PAGE_SIZE); p = virt_to_page(page); ClearPageReserved(p); diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index ba0453023..0cc9dad75 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S @@ -109,7 +109,7 @@ ret_from_solaris: sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - cmp %o0, -ENOIOCTLCMD + cmp %o0, -ERESTART_RESTARTBLOCK sllx %g2, 32, %g2 bgeu,pn %xcc, 1f andcc %l6, _TIF_SYSCALL_TRACE, %l6 diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index a237c68ac..d7c99fa89 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -600,23 +600,23 @@ asmlinkage int solaris_ulimit(int cmd, int val) { switch (cmd) { case 1: /* UL_GETFSIZE - in 512B chunks */ - return current->rlim[RLIMIT_FSIZE].rlim_cur >> 9; + return current->signal->rlim[RLIMIT_FSIZE].rlim_cur >> 9; case 2: /* UL_SETFSIZE */ if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE; val <<= 9; - lock_kernel(); - if (val > current->rlim[RLIMIT_FSIZE].rlim_max) { + task_lock(current->group_leader); + if (val > current->signal->rlim[RLIMIT_FSIZE].rlim_max) { if (!capable(CAP_SYS_RESOURCE)) { - unlock_kernel(); + task_unlock(current->group_leader); return -EPERM; } - current->rlim[RLIMIT_FSIZE].rlim_max = val; + current->signal->rlim[RLIMIT_FSIZE].rlim_max = val; } - current->rlim[RLIMIT_FSIZE].rlim_cur = val; - unlock_kernel(); + current->signal->rlim[RLIMIT_FSIZE].rlim_cur = val; + task_unlock(current->group_leader); return 0; case 3: /* UL_GMEMLIM */ - return current->rlim[RLIMIT_DATA].rlim_cur; + return current->signal->rlim[RLIMIT_DATA].rlim_cur; case 4: /* UL_GDESLIM */ return NR_OPEN; } diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 4a3db02e1..15b4cfe07 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk) return sunos_brk(brk); } -#define set_utsfield(to, from, dotchop, countfrom) { \ - char *p; \ - int i, len = (countfrom) ? \ - ((sizeof(to) > sizeof(from) ? \ - sizeof(from) : sizeof(to))) : sizeof(to); \ - if (copy_to_user(to, from, len)) \ - return -EFAULT; \ - if (dotchop) \ - for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \ - else \ - i = len - 1; \ - if (__put_user('\0', (char __user *)((to)+i))) \ - return -EFAULT; \ +static int __set_utsfield(char __user *to, int to_size, + const char *from, int from_size, + int dotchop, int countfrom) +{ + int len = countfrom ? (to_size > from_size ? + from_size : to_size) : to_size; + int off; + + if (copy_to_user(to, from, len)) + return -EFAULT; + + off = len < to_size? len: len - 1; + if (dotchop) { + const char *p = strnchr(from, len, '.'); + if (p) off = p - from; + } + + if (__put_user('\0', to + off)) + return -EFAULT; + + return 0; } +#define set_utsfield(to, from, dotchop, countfrom) \ + __set_utsfield((to), sizeof(to), \ + (from), sizeof(from), \ + (dotchop), (countfrom)) + struct sol_uname { char sysname[9]; char nodename[9]; @@ -219,17 +232,20 @@ static char *serial(char *buffer) asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) { struct sol_uname __user *v = A(buf); + int err; + switch (which) { case 0: /* old uname */ /* Let's cheat */ - set_utsfield(v->sysname, "SunOS", 1, 0); + err = set_utsfield(v->sysname, "SunOS", 1, 0); down_read(&uts_sem); - set_utsfield(v->nodename, system_utsname.nodename, 1, 1); + err |= set_utsfield(v->nodename, system_utsname.nodename, + 1, 1); up_read(&uts_sem); - set_utsfield(v->release, "2.6", 0, 0); - set_utsfield(v->version, "Generic", 0, 0); - set_utsfield(v->machine, machine(), 0, 0); - return 0; + err |= set_utsfield(v->release, "2.6", 0, 0); + err |= set_utsfield(v->version, "Generic", 0, 0); + err |= set_utsfield(v->machine, machine(), 0, 0); + return (err ? -EFAULT : 0); case 2: /* ustat */ return -ENOSYS; case 3: /* fusers */ @@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) asmlinkage int solaris_utsname(u32 buf) { struct sol_utsname __user *v = A(buf); + int err; + /* Why should we not lie a bit? */ down_read(&uts_sem); - set_utsfield(v->sysname, "SunOS", 0, 0); - set_utsfield(v->nodename, system_utsname.nodename, 1, 1); - set_utsfield(v->release, "5.6", 0, 0); - set_utsfield(v->version, "Generic", 0, 0); - set_utsfield(v->machine, machine(), 0, 0); + err = set_utsfield(v->sysname, "SunOS", 0, 0); + err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1); + err |= set_utsfield(v->release, "5.6", 0, 0); + err |= set_utsfield(v->version, "Generic", 0, 0); + err |= set_utsfield(v->machine, machine(), 0, 0); up_read(&uts_sem); - return 0; + + return (err ? -EFAULT : 0); } #define SI_SYSNAME 1 /* return name of operating system */ diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S index 853afe9d1..d25667eea 100644 --- a/arch/sparc64/solaris/systbl.S +++ b/arch/sparc64/solaris/systbl.S @@ -295,4 +295,20 @@ solaris_sys_table: .word solaris_unimplemented /* 265 */ .word solaris_unimplemented /* 266 */ .word solaris_unimplemented /* 267 */ + .word solaris_unimplemented /* 268 */ + .word solaris_unimplemented /* 269 */ + .word solaris_unimplemented /* 270 */ + .word solaris_unimplemented /* 271 */ + .word solaris_unimplemented /* 272 */ + .word solaris_unimplemented /* 273 */ + .word solaris_unimplemented /* 274 */ + .word solaris_unimplemented /* 275 */ + .word solaris_unimplemented /* 276 */ + .word solaris_unimplemented /* 277 */ + .word solaris_unimplemented /* 278 */ + .word solaris_unimplemented /* 279 */ + .word solaris_unimplemented /* 280 */ + .word solaris_unimplemented /* 281 */ + .word solaris_unimplemented /* 282 */ + .word solaris_unimplemented /* 283 */ diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 47fbaf3f4..663f89d69 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -1,3 +1,8 @@ +# UML uses the generic IRQ sugsystem +config GENERIC_HARDIRQS + bool + default y + config USERMODE bool default y @@ -34,7 +39,7 @@ config MODE_TT help This option controls whether tracing thread support is compiled into UML. Normally, this should be set to Y. If you intend to - use only skas mode (and the host has the skas patch applied to it), + use only skas mode (and the host has the skas patch applied to it), then it is OK to say N here. config STATIC_LINK @@ -45,7 +50,7 @@ config STATIC_LINK If CONFIG_MODE_TT is disabled, then this option gives you the ability to force a static link of UML. Normally, if only skas mode is built in to UML, it will be linked as a shared binary. This is inconvenient - for use in a chroot jail. So, if you intend to run UML inside a + for use in a chroot jail. So, if you intend to run UML inside a chroot, and you disable CONFIG_MODE_TT, you probably want to say Y here. @@ -61,6 +66,20 @@ config MODE_SKAS config NET bool "Networking support" + help + Unless you really know what you are doing, you should say Y here. + The reason is that some programs need kernel networking support even + when running on a stand-alone machine that isn't connected to any + other computer. If you are upgrading from an older kernel, you + should consider updating your networking tools too because changes + in the kernel and the tools often go hand in hand. The tools are + contained in the package net-tools, the location and version number + of which are given in Documentation/Changes. + + For a general introduction to Linux networking, it is highly + recommended to read the NET-HOWTO, available from + . + source "fs/Kconfig.binfmt" @@ -82,12 +101,30 @@ config HOSTFS For more information, see . - If you'd like to be able to work with files stored on the host, + If you'd like to be able to work with files stored on the host, say Y or M here; otherwise say N. +config HPPFS + tristate "HoneyPot ProcFS (EXPERIMENTAL)" + depends on BROKEN + help + hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc + entries to be overridden, removed, or fabricated from the host. + Its purpose is to allow a UML to appear to be a physical machine + by removing or changing anything in /proc which gives away the + identity of a UML. + + See http://user-mode-linux.sf.net/hppfs.html for more information. + + You only need this if you are setting up a UML honeypot. Otherwise, + it is safe to say 'N' here. + + If you are actively using it, please ask for it to be fixed. In this + moment, it does not work on 2.6 (it works somehow on 2.4). config MCONSOLE bool "Management console" + default y help The user mode linux management console is a low-level interface to the kernel, somewhat like the i386 SysRq interface. Since there is @@ -102,29 +139,42 @@ config MCONSOLE It is safe to say 'Y' here. -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on MCONSOLE - config HOST_2G_2G bool "2G/2G host address space split" - -config UML_SMP - bool "Symmetric multi-processing support" + default n help - This option enables UML SMP support. UML implements virtual SMP by - allowing as many processes to run simultaneously on the host as - there are virtual processors configured. Obviously, if the host is - a uniprocessor, those processes will timeshare, but, inside UML, - will appear to be running simultaneously. If the host is a - multiprocessor, then UML processes may run simultaneously, depending - on the host scheduler. - CONFIG_SMP will be set to whatever this option is set to. - It is safe to leave this unchanged. + This is needed when the host on which you run has a 2G/2G memory + split, instead of the customary 3G/1G. + + Note that to enable such a host + configuration, which makes sense only in some cases, you need special + host patches. + + So, if you do not know what to do here, say 'N'. config SMP - bool - default UML_SMP + bool "Symmetric multi-processing support (EXPERIMENTAL)" + default n + depends on MODE_TT && EXPERIMENTAL + help + This option enables UML SMP support. + It is NOT related to having a real SMP box. Not directly, at least. + + UML implements virtual SMP by allowing as many processes to run + simultaneously on the host as there are virtual processors configured. + + Obviously, if the host is a uniprocessor, those processes will + timeshare, but, inside UML, will appear to be running simultaneously. + If the host is a multiprocessor, then UML processes may run + simultaneously, depending on the host scheduler. + + This, however, is supported only in TT mode. So, if you use the SKAS + patch on your host, switching to TT mode and enabling SMP usually gives + you worse performances. + Also, since the support for SMP has been under-developed, there could + be some bugs being exposed by enabling SMP. + + If you don't know what to do, say N. config NR_CPUS int "Maximum number of CPUs (2-32)" @@ -140,11 +190,11 @@ config NEST_LEVEL in. Normally, this is zero, meaning that it will run directly on the host. Setting it to one will build a UML that can run inside a UML that is running on the host. Generally, if you intend this UML to run - inside another UML, set CONFIG_NEST_LEVEL to one more than the host + inside another UML, set CONFIG_NEST_LEVEL to one more than the host UML. - Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to - greater than one, then the guest UML should have its CONFIG_NEST_LEVEL + Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to + greater than one, then the guest UML should have its CONFIG_NEST_LEVEL set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. Only change this if you are running nested UMLs. @@ -159,6 +209,7 @@ config KERNEL_HALF_GIGS config HIGHMEM bool "Highmem support" + depends on BROKEN config KERNEL_STACK_ORDER int "Kernel stack size order" @@ -168,6 +219,17 @@ config KERNEL_STACK_ORDER be 1 << order pages. The default is OK unless you're running Valgrind on UML, in which case, set this to 3. +config UML_REAL_TIME_CLOCK + bool "Real-time Clock" + default y + help + This option makes UML time deltas match wall clock deltas. This should + normally be enabled. The exception would be if you are debugging with + UML and spend long times with UML stopped at a breakpoint. In this + case, when UML is restarted, it will call the timer enough times to make + up for the time spent at the breakpoint. This could result in a + noticable lag. If this is a problem, then disable this option. + endmenu source "init/Kconfig" @@ -195,6 +257,7 @@ source "crypto/Kconfig" source "lib/Kconfig" menu "SCSI support" +depends on BROKEN config SCSI tristate "SCSI support" @@ -211,61 +274,12 @@ endmenu source "drivers/md/Kconfig" -source "drivers/mtd/Kconfig" - - -menu "Kernel hacking" - -config DEBUG_SLAB - bool "Debug memory allocations" +if BROKEN + source "drivers/mtd/Kconfig" +endif -config DEBUG_SPINLOCK - bool "Debug spinlocks usage" - -config DEBUG_INFO - bool "Enable kernel debugging symbols" - help - When this is enabled, the User-Mode Linux binary will include - debugging symbols. This enlarges the binary by a few megabytes, - but aids in tracking down kernel problems in UML. It is required - if you intend to do any kernel development. - - If you're truly short on disk space or don't expect to report any - bugs back to the UML developers, say N, otherwise say Y. - -config FRAME_POINTER +config INPUT bool - default y if DEBUG_INFO - -config PT_PROXY - bool "Enable ptrace proxy" - depends on XTERM_CHAN && DEBUG_INFO - -config GPROF - bool "Enable gprof support" - depends on DEBUG_INFO - help - This allows profiling of a User-Mode Linux kernel with the gprof - utility. - - See for more - details. - - If you're involved in UML kernel development and want to use gprof, - say Y. If you're unsure, say N. - -config GCOV - bool "Enable gcov support" - depends on DEBUG_INFO - help - This option allows developers to retrieve coverage data from a UML - session. - - See for more - details. - - If you're involved in UML kernel development and want to use gcov, - say Y. If you're unsure, say N. - -endmenu + default n +source "arch/um/Kconfig.debug" diff --git a/arch/um/Kconfig_block b/arch/um/Kconfig_block index fba53d9bb..1f0f9ccb4 100644 --- a/arch/um/Kconfig_block +++ b/arch/um/Kconfig_block @@ -29,6 +29,10 @@ config BLK_DEV_UBD_SYNC wise choice too. In all other cases (for example, if you're just playing around with User-Mode Linux) you can choose N. +config BLK_DEV_COW_COMMON + bool + default BLK_DEV_UBD + config BLK_DEV_LOOP tristate "Loopback device support" @@ -39,6 +43,10 @@ config BLK_DEV_NBD config BLK_DEV_RAM tristate "RAM disk support" +config BLK_DEV_RAM_COUNT + int "Default number of RAM disks" if BLK_DEV_RAM + default "16" + config BLK_DEV_RAM_SIZE int "Default RAM disk size" depends on BLK_DEV_RAM @@ -48,8 +56,36 @@ config BLK_DEV_INITRD bool "Initial RAM disk (initrd) support" depends on BLK_DEV_RAM=y +#Copied directly from drivers/block/Kconfig +config INITRAMFS_SOURCE + string "Source directory of cpio_list" + default "" + help + This can be set to either a directory containing files, etc to be + included in the initramfs archive, or a file containing newline + separated entries. + + If it is a file, it should be in the following format: + # a comment + file + dir + nod + + Where: + name of the file/dir/nod in the archive + location of the file in the current filesystem + mode/permissions of the file + user id (0=root) + group id (0=root) + device type (b=block, c=character) + major number of nod + minor number of nod + + If you are not sure, leave it blank. + config MMAPPER tristate "Example IO memory driver" + depends on BROKEN help The User-Mode Linux port can provide support for IO Memory emulation with this option. This allows a host file to be @@ -64,5 +100,6 @@ config MMAPPER If you'd like to be able to provide a simulated IO port space for User-Mode Linux processes, say Y. If unsure, say N. -endmenu +source "drivers/block/Kconfig.iosched" +endmenu diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char index a21cbbc7e..09f47388c 100644 --- a/arch/um/Kconfig_char +++ b/arch/um/Kconfig_char @@ -72,6 +72,10 @@ config XTERM_CHAN well, since UML's gdb currently requires an xterm. It is safe to say 'Y' here. +config NOCONFIG_CHAN + bool + default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && FD_CHAN && NULL_CHAN) + config CON_ZERO_CHAN string "Default main console channel initialization" default "fd:0,fd:1" @@ -108,11 +112,55 @@ config SSL_CHAN config UNIX98_PTYS bool "Unix98 PTY support" - -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx for + masters and /dev/ttyxx for slaves of pseudo terminals. This scheme + has a number of problems. The GNU C library glibc 2.1 and later, + however, supports the Unix98 naming standard: in order to acquire a + pseudo terminal, a process opens /dev/ptmx; the number of the pseudo + terminal is then made available to the process and the pseudo + terminal slave can be accessed as /dev/pts/. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. + + All modern Linux systems use the Unix98 ptys. Say Y unless + you're on an embedded system and want to conserve memory. + +config LEGACY_PTYS + bool "Legacy (BSD) PTY support" + default y + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx + for masters and /dev/ttyxx for slaves of pseudo + terminals. This scheme has a number of problems, including + security. This option enables these legacy devices; on most + systems, it is safe to say N. + + +config LEGACY_PTY_COUNT + int "Maximum number of legacy PTY in use" + depends on LEGACY_PTYS default "256" + ---help--- + The maximum number of legacy PTYs that can be used at any one time. + The default is 256, and should be more than enough. Embedded + systems may want to reduce this to save memory. + + When not in use, each legacy PTY occupies 12 bytes on 32-bit + architectures and 24 bytes on 64-bit architectures. config WATCHDOG bool "Watchdog Timer Support" diff --git a/arch/um/Kconfig_net b/arch/um/Kconfig_net index 443a74bd6..1c2f9a70d 100644 --- a/arch/um/Kconfig_net +++ b/arch/um/Kconfig_net @@ -1,5 +1,5 @@ -menu "Network Devices" +menu "UML Network Devices" depends on NET # UML virtual driver @@ -135,7 +135,7 @@ config UML_NET_MCAST config UML_NET_PCAP bool "pcap transport" - depends on UML_NET + depends on UML_NET && BROKEN help The pcap transport makes a pcap packet stream on the host look like an ethernet device inside UML. This is useful for making @@ -176,73 +176,5 @@ config UML_NET_SLIRP Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp" - -# Below are hardware-independent drivers mirrored from -# drivers/net/Config.in. It would be nice if Linux -# had HW independent drivers separated from the other -# but it does not. Until then each non-ISA/PCI arch -# needs to provide it's own menu of network drivers -config DUMMY - tristate "Dummy net driver support" - -config BONDING - tristate "Bonding driver support" - -config EQUALIZER - tristate "EQL (serial line load balancing) support" - -config TUN - tristate "Universal TUN/TAP device driver support" - -config ETHERTAP - tristate "Ethertap network tap (OBSOLETE)" - depends on EXPERIMENTAL && NETLINK - -config PPP - tristate "PPP (point-to-point protocol) support" - -config PPP_MULTILINK - bool "PPP multilink support (EXPERIMENTAL)" - depends on PPP && EXPERIMENTAL - -config PPP_FILTER - bool "PPP filtering" - depends on PPP && FILTER - -config PPP_ASYNC - tristate "PPP support for async serial ports" - depends on PPP - -config PPP_SYNC_TTY - tristate "PPP support for sync tty ports" - depends on PPP - -config PPP_DEFLATE - tristate "PPP Deflate compression" - depends on PPP - -config PPP_BSDCOMP - tristate "PPP BSD-Compress compression" - depends on PPP - -config PPPOE - tristate "PPP over Ethernet (EXPERIMENTAL)" - depends on PPP && EXPERIMENTAL - -config SLIP - tristate "SLIP (serial line) support" - -config SLIP_COMPRESSED - bool "CSLIP compressed headers" - depends on SLIP=y - -config SLIP_SMART - bool "Keepalive and linefill" - depends on SLIP=y - -config SLIP_MODE_SLIP6 - bool "Six bit SLIP encapsulation" - depends on SLIP=y - endmenu diff --git a/arch/um/Makefile b/arch/um/Makefile index bb7d3f6ba..b8371a958 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -5,45 +5,38 @@ ARCH_DIR = arch/um OS := $(shell uname -s) +# We require bash because the vmlinux link and loader script cpp use bash +# features. +SHELL := /bin/bash -# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE) -# The way the toplevel Makefile is written EXTRAVERSION is not supposed -# to be changed outside the toplevel Makefile, but recalculating MODLIB is -# a sufficient workaround until we no longer need architecture dependent -# EXTRAVERSION... -MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +filechk_gen_header = $< -ifeq ($(CONFIG_DEBUG_INFO),y) -CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -endif - -core-y += $(ARCH_DIR)/kernel/ \ - $(ARCH_DIR)/drivers/ \ +core-y += $(ARCH_DIR)/kernel/ \ + $(ARCH_DIR)/drivers/ \ $(ARCH_DIR)/sys-$(SUBARCH)/ # Have to precede the include because the included Makefiles reference them. -SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \ - include/asm-um/sigcontext.h include/asm-um/processor.h \ - include/asm-um/ptrace.h include/asm-um/arch-signal.h +SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ + arch-signal.h module.h +SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h -include $(ARCH_DIR)/Makefile-$(SUBARCH) -include $(ARCH_DIR)/Makefile-os-$(OS) - MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas ifneq ($(MAKEFILE-y),) - include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y)) + include $(addprefix $(srctree)/$(ARCH_DIR)/,$(MAKEFILE-y)) endif -EXTRAVERSION := $(EXTRAVERSION)-1um +ARCH_INCLUDE := -I$(ARCH_DIR)/include +SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) -ARCH_INCLUDE = -I$(ARCH_DIR)/include +include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) +include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common @@ -52,32 +45,46 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \ - $(MODE_INCLUDE) + -Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE) + +CFLAGS += $(call cc-option,-fno-unit-at-a-time,) LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc +# These are needed for clean and mrproper, since in that case .config is not +# included; the values here are meaningless + +CONFIG_NEST_LEVEL ?= 0 +CONFIG_KERNEL_HALF_GIGS ?= 0 + SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) ifeq ($(CONFIG_MODE_SKAS), y) -$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h +$(SYS_HEADERS) : $(ARCH_DIR)/include/skas_ptregs.h endif -include/linux/version.h: arch/$(ARCH)/Makefile +.PHONY: linux -$(ARCH_DIR)/vmlinux.lds.S : - touch $@ +all: linux -prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) +linux: vmlinux + ln -f $< $@ -LDFLAGS_vmlinux = -r +define archhelp + echo '* linux - Binary kernel image (./linux) - for backward' + echo ' compatibility only, this creates a hard link to the' + echo ' real kernel binary, the the "vmlinux" binary you' + echo ' find in the kernel root.' +endef -vmlinux: $(ARCH_DIR)/main.o +prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \ + $(ARCH_DIR)/kernel/vmlinux.lds.S # These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT + # CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case. LINK_TT = -static -LD_SCRIPT_TT := uml.lds.s +LD_SCRIPT_TT := uml.lds.S ifeq ($(CONFIG_STATIC_LINK),y) LINK-y += $(LINK_TT) @@ -98,82 +105,101 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT) CONFIG_KERNEL_STACK_ORDER ?= 2 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) -AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \ - -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \ - -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \ - -DKERNEL_STACK_SIZE=$(STACK_SIZE) - -AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum - -LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y) - -$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE - $(call if_changed_dep,as_s_S) +ifndef START + START = $$(($(TOP_ADDR) - $(SIZE))) +endif -linux: vmlinux $(LD_SCRIPT-y) - $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \ - -o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil +CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \ + -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ + -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \ + -DKERNEL_STACK_SIZE=$(STACK_SIZE)) + +CFLAGS_vmlinux = $(LINK-y) $(LINK_WRAPS) +define cmd_vmlinux__ + $(CC) $(CFLAGS_vmlinux) -o $@ \ + -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ + -Wl,--start-group $(vmlinux-main) -Wl,--end-group \ + -L/usr/lib -lutil \ + $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \ + FORCE ,$^) ; rm -f linux +endef USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS)) +USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS)) USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ $(MODE_INCLUDE) +USER_CFLAGS += $(ARCH_USER_CFLAGS) # To get a definition of F_SETSIG USER_CFLAGS += -D_GNU_SOURCE -CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \ - $(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS) +#When cleaning we don't include .config, so we don't include +#TT or skas makefiles and don't clean skas_ptregs.h. +CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ + $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h -$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c - $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< +MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \ + $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os archmrproper: - for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \ - do \ - $(MAKE) -C $$d archmrproper; \ - done - rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \ - $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) - -archclean: sysclean - for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \ - do \ - $(MAKE) -C $$d clean; \ - done - find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ + @: + +archclean: + $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util + @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -o -name '*.gcov' \) -type f -print | xargs rm -f - rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS) -archdep: - for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done +#We need to re-preprocess this when the symlink dest changes. +#So we touch it. +$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE + @echo ' SYMLINK $@' + $(Q)ln -sf $(LD_SCRIPT-y) $@ + $(Q)touch $@ $(SYMLINK_HEADERS): - cd $(TOPDIR)/$(dir $@) ; \ + @echo ' SYMLINK $@' + $(Q)cd $(TOPDIR)/$(dir $@) ; \ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) include/asm-um/arch: - cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch + @echo ' SYMLINK $@' + $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch $(ARCH_DIR)/include/sysdep: - cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep + @echo ' SYMLINK $@' + $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep $(ARCH_DIR)/os: - cd $(ARCH_DIR) && ln -sf os-$(OS) os + @echo ' SYMLINK $@' + $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os + +# Generated files +define filechk_umlconfig + sed 's/ CONFIG/ UML_CONFIG/' +endef + +$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h + $(call filechk,umlconfig) + +$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task + $(call filechk,gen_header) + +$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants + $(call filechk,gen_header) -$(ARCH_DIR)/include/uml-config.h : - sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@ +$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs + $(call filechk,gen_header) -$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task - $< > $@ +$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/util \ + FORCE ; -$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants - $< > $@ +$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ; -$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \ - $(ARCH_DIR)/util FORCE ; +$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE + $(Q)$(MAKE) $(build)=$@ -$(ARCH_DIR)/util: FORCE - @$(call descend,$@,) +$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE + $(Q)$(MAKE) $(build)=$@ export SUBARCH USER_CFLAGS OS diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 3bd90fbdb..7c7d00847 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -1,37 +1,46 @@ ifeq ($(CONFIG_HOST_2G_2G), y) -TOP_ADDR = 0x80000000 +TOP_ADDR := 0x80000000 else -TOP_ADDR = 0xc0000000 +TOP_ADDR := 0xc0000000 +endif + +ifeq ($(CONFIG_MODE_SKAS),y) + ifneq ($(CONFIG_MODE_TT),y) + START := 0x8048000 + endif endif CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) -ELF_ARCH = $(SUBARCH) -ELF_FORMAT = elf32-$(SUBARCH) +ARCH_USER_CFLAGS := + +ifneq ($(CONFIG_GPROF),y) +ARCH_CFLAGS += -DUM_FASTCALL +endif + +ELF_ARCH := $(SUBARCH) +ELF_FORMAT := elf32-$(SUBARCH) OBJCOPYFLAGS := -O binary -R .note -R .comment -S -LDFLAGS_BLOB := --format binary --oformat elf32-i386 -SYS_DIR := $(ARCH_DIR)/include/sysdep-i386 SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util -SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h +SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h prepare: $(SYS_HEADERS) $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc - $< > $@ + $(call filechk,gen_header) $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread - $< > $@ + $(call filechk,gen_header) -$(SYS_UTIL_DIR)/mk_sc: FORCE ; - @$(call descend,$(SYS_UTIL_DIR),$@) +$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ -$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; - @$(call descend,$(SYS_UTIL_DIR),$@) +$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ -$(SYS_UTIL_DIR): include/asm FORCE - @$(call descend,$@,) +$(SYS_UTIL_DIR): scripts_basic include/asm FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) -sysclean : - rm -f $(SYS_HEADERS) +CLEAN_FILES += $(SYS_HEADERS) diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas index b9dfec5f7..fb3050ff9 100644 --- a/arch/um/Makefile-skas +++ b/arch/um/Makefile-skas @@ -9,12 +9,9 @@ CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage CFLAGS-$(CONFIG_GPROF) += $(PROFILE) LINK-$(CONFIG_GPROF) += $(PROFILE) -MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include +MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/skas/include LINK_SKAS = -Wl,-rpath,/lib -LD_SCRIPT_SKAS = dyn.lds.s +LD_SCRIPT_SKAS = dyn.lds.S -GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h - -$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h : - $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h +GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt index 8d58a3083..eed367d9c 100644 --- a/arch/um/Makefile-tt +++ b/arch/um/Makefile-tt @@ -3,5 +3,4 @@ # Licensed under the GPL # -MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include - +MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/tt/include diff --git a/arch/um/config.release b/arch/um/config.release index 6d32bc20c..fc68bcb92 100644 --- a/arch/um/config.release +++ b/arch/um/config.release @@ -227,7 +227,6 @@ CONFIG_ROMFS_FS=m CONFIG_EXT2_FS=y CONFIG_SYSV_FS=m CONFIG_UDF_FS=m -# CONFIG_UDF_RW is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set diff --git a/arch/um/defconfig b/arch/um/defconfig index 412d006b9..0524a22fa 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -1,47 +1,86 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-mm5 +# Sun Nov 14 15:27:58 2004 # +CONFIG_GENERIC_HARDIRQS=y CONFIG_USERMODE=y CONFIG_MMU=y -CONFIG_SWAP=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GENERIC_CALIBRATE_DELAY=y # -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General Setup +# UML-specific options # CONFIG_MODE_TT=y CONFIG_MODE_SKAS=y CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y +CONFIG_BINFMT_MISC=m CONFIG_HOSTFS=y CONFIG_MCONSOLE=y -CONFIG_MAGIC_SYSRQ=y # CONFIG_HOST_2G_2G is not set -# CONFIG_UML_SMP is not set # CONFIG_SMP is not set CONFIG_NEST_LEVEL=0 CONFIG_KERNEL_HALF_GIGS=1 -# CONFIG_HIGHMEM is not set -CONFIG_PROC_MM=y CONFIG_KERNEL_STACK_ORDER=2 +CONFIG_UML_REAL_TIME_CLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set # # Loadable module support # CONFIG_MODULES=y -# CONFIG_KMOD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # # Character Devices @@ -54,31 +93,42 @@ CONFIG_PORT_CHAN=y CONFIG_PTY_CHAN=y CONFIG_TTY_CHAN=y CONFIG_XTERM_CHAN=y +# CONFIG_NOCONFIG_CHAN is not set CONFIG_CON_ZERO_CHAN="fd:0,fd:1" CONFIG_CON_CHAN="xterm" CONFIG_SSL_CHAN="pty" CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set -CONFIG_UML_SOUND=y -CONFIG_SOUND=y -CONFIG_HOSTAUDIO=y +CONFIG_UML_SOUND=m +CONFIG_SOUND=m +CONFIG_HOSTAUDIO=m # # Block Devices # CONFIG_BLK_DEV_UBD=y -# CONFIG_BLK_DEV_UBD_SYNC is not set -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_UBD_SYNC=y +CONFIG_BLK_DEV_COW_COMMON=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -# CONFIG_MMAPPER is not set +CONFIG_INITRAMFS_SOURCE="" + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y CONFIG_NETDEVICES=y # -# Network Devices +# UML Network Devices # CONFIG_UML_NET=y CONFIG_UML_NET_ETHERTAP=y @@ -86,24 +136,7 @@ CONFIG_UML_NET_TUNTAP=y CONFIG_UML_NET_SLIP=y CONFIG_UML_NET_DAEMON=y CONFIG_UML_NET_MCAST=y -# CONFIG_UML_NET_PCAP is not set CONFIG_UML_NET_SLIRP=y -CONFIG_DUMMY=y -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=y -# CONFIG_ETHERTAP is not set -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=y -# CONFIG_SLIP_COMPRESSED is not set -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set # # Networking support @@ -115,8 +148,6 @@ CONFIG_SLIP=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -126,39 +157,55 @@ CONFIG_INET=y # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set -# CONFIG_XFRM_USER is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_KGDBOE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m # # Ethernet (10 or 100Mbit) @@ -170,83 +217,123 @@ CONFIG_IPV6_SCTP__=y # # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # -# CONFIG_SHAPER is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +CONFIG_SLIP=m +# CONFIG_SLIP_COMPRESSED is not set +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISER4_FS is not set +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -CONFIG_MINIX_FS=m # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_XFS_FS is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_EXPORTFS is not set -# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # @@ -254,11 +341,11 @@ CONFIG_EXT2_FS=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set @@ -283,6 +370,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -301,6 +389,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -311,93 +400,26 @@ CONFIG_NLS_DEFAULT="iso8859-1" # # Library routines # +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set - -# -# SCSI support -# -CONFIG_SCSI=y -CONFIG_GENERIC_ISA_DMA=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_DEBUG_QUEUES=y -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_DEBUG=y +# CONFIG_LIBCRC32C is not set # # Multi-device support (RAID and LVM) # # CONFIG_MD is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set -# CONFIG_MTD_CONCAT is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -# CONFIG_MTD_CFI is not set -# CONFIG_MTD_JEDECPROBE is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set +# CONFIG_INPUT is not set # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_INFO=y CONFIG_FRAME_POINTER=y CONFIG_PT_PROXY=y diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 8ea9ada4a..127bb4d07 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -15,7 +15,7 @@ mcast-objs := mcast_kern.o mcast_user.o #pcap-objs := pcap_kern.o pcap_user.o $(PCAP) net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o -hostaudio-objs := hostaudio_kern.o hostaudio_user.o +hostaudio-objs := hostaudio_kern.o ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o harddog-objs := harddog_kern.o harddog_user.o @@ -39,6 +39,7 @@ obj-$(CONFIG_PTY_CHAN) += pty.o obj-$(CONFIG_TTY_CHAN) += tty.o obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o +obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-y += stdio_console.o $(CHAN_OBJS) @@ -46,18 +47,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \ null.o pty.o tty.o xterm.o -USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file)) +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean: - -modules: - -fastdep: - -dep: - -archmrproper: clean - diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 9e45a082e..7a8d75086 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "chan_kern.h" @@ -16,7 +17,9 @@ #include "irq_user.h" #include "sigio.h" #include "line.h" +#include "os.h" +#ifdef CONFIG_NOCONFIG_CHAN static void *not_configged_init(char *str, int device, struct chan_opts *opts) { printk(KERN_ERR "Using a channel type which is configured out of " @@ -85,6 +88,55 @@ static struct chan_ops not_configged_ops = { .free = not_configged_free, .winch = 0, }; +#endif /* CONFIG_NOCONFIG_CHAN */ + +void generic_close(int fd, void *unused) +{ + os_close_file(fd); +} + +int generic_read(int fd, char *c_out, void *unused) +{ + int n; + + n = os_read_file(fd, c_out, sizeof(*c_out)); + + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-EIO); + return(n); +} + +/* XXX Trivial wrapper around os_write_file */ + +int generic_write(int fd, const char *buf, int n, void *unused) +{ + return(os_write_file(fd, buf, n)); +} + +int generic_window_size(int fd, void *unused, unsigned short *rows_out, + unsigned short *cols_out) +{ + int rows, cols; + int ret; + + ret = os_window_size(fd, &rows, &cols); + if(ret < 0) + return(ret); + + ret = ((*rows_out != rows) || (*cols_out != cols)); + + *rows_out = rows; + *cols_out = cols; + + return(ret); +} + +void generic_free(void *data) +{ + kfree(data); +} static void tty_receive_char(struct tty_struct *tty, char ch) { @@ -265,6 +317,11 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, { int n = 0; + if(chan == NULL){ + CONFIG_CHUNK(str, size, n, "none", 1); + return(n); + } + CONFIG_CHUNK(str, size, n, chan->ops->type, 0); if(chan->dev == NULL){ @@ -420,7 +477,8 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, INIT_LIST_HEAD(chans); } - if((out = strchr(str, ',')) != NULL){ + out = strchr(str, ','); + if(out != NULL){ in = str; *out = '\0'; out++; @@ -475,12 +533,15 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, goto out; } err = chan->ops->read(chan->fd, &c, chan->data); - if(err > 0) tty_receive_char(tty, c); + if(err > 0) + tty_receive_char(tty, c); } while(err > 0); + if(err == 0) reactivate_fd(chan->fd, irq); if(err == -EIO){ if(chan->primary){ - if(tty != NULL) tty_hangup(tty); + if(tty != NULL) + tty_hangup(tty); line_disable(dev, irq); close_chan(chans); free_chan(chans); diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 714bace49..b62f8e283 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -22,67 +21,32 @@ #include "choose-mode.h" #include "mode.h" -void generic_close(int fd, void *unused) -{ - close(fd); -} - -int generic_read(int fd, char *c_out, void *unused) -{ - int n; - - n = read(fd, c_out, sizeof(*c_out)); - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-EIO); - return(1); -} - -int generic_write(int fd, const char *buf, int n, void *unused) -{ - int count; - - count = write(fd, buf, n); - if(count < 0) return(-errno); - return(count); -} - int generic_console_write(int fd, const char *buf, int n, void *unused) { struct termios save, new; int err; if(isatty(fd)){ - tcgetattr(fd, &save); + CATCH_EINTR(err = tcgetattr(fd, &save)); + if (err) + goto error; new = save; + /* The terminal becomes a bit less raw, to handle \n also as + * "Carriage Return", not only as "New Line". Otherwise, the new + * line won't start at the first column.*/ new.c_oflag |= OPOST; - tcsetattr(fd, TCSAFLUSH, &new); + CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new)); + if (err) + goto error; } err = generic_write(fd, buf, n, NULL); - if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save); + /* Restore raw mode, in any case; we *must* ignore any error apart + * EINTR, except for debug.*/ + if(isatty(fd)) + CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); return(err); -} - -int generic_window_size(int fd, void *unused, unsigned short *rows_out, - unsigned short *cols_out) -{ - struct winsize size; - int ret = 0; - - if(ioctl(fd, TIOCGWINSZ, &size) == 0){ - ret = ((*rows_out != size.ws_row) || - (*cols_out != size.ws_col)); - *rows_out = size.ws_row; - *cols_out = size.ws_col; - } - return(ret); -} - -void generic_free(void *data) -{ - kfree(data); +error: + return(-errno); } static void winch_handler(int sig) @@ -100,14 +64,16 @@ static int winch_thread(void *arg) struct winch_data *data = arg; sigset_t sigs; int pty_fd, pipe_fd; + int count, err; char c = 1; - close(data->close_me); + os_close_file(data->close_me); pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; - if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)) + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("winch_thread : failed to write synchronization " - "byte, errno = %d\n", errno); + "byte, err = %d\n", -count); signal(SIGWINCH, winch_handler); sigfillset(&sigs); @@ -123,26 +89,24 @@ static int winch_thread(void *arg) exit(1); } - if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){ - printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno); - exit(1); - } - if(tcsetpgrp(pty_fd, os_getpid()) < 0){ - printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno); + err = os_new_tty_pgrp(pty_fd, os_getpid()); + if(err < 0){ + printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err); exit(1); } - if(read(pipe_fd, &c, sizeof(c)) != sizeof(c)) + count = os_read_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("winch_thread : failed to read synchronization byte, " - "errno = %d\n", errno); + "err = %d\n", -count); while(1){ pause(); - if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){ - printk("winch_thread : write failed, errno = %d\n", - errno); - } + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("winch_thread : write failed, err = %d\n", + -count); } } @@ -154,8 +118,8 @@ static int winch_tramp(int fd, void *device_data, int *fd_out) char c; err = os_pipe(fds, 1, 1); - if(err){ - printk("winch_tramp : os_pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("winch_tramp : os_pipe failed, err = %d\n", -err); return(err); } @@ -168,12 +132,12 @@ static int winch_tramp(int fd, void *device_data, int *fd_out) return(pid); } - close(fds[1]); + os_close_file(fds[1]); *fd_out = fds[0]; - n = read(fds[0], &c, sizeof(c)); + n = os_read_file(fds[0], &c, sizeof(c)); if(n != sizeof(c)){ printk("winch_tramp : failed to read synchronization byte\n"); - printk("read returned %d, errno = %d\n", n, errno); + printk("read failed, err = %d\n", -n); printk("fd %d will not support SIGWINCH\n", fd); *fd_out = -1; } @@ -183,20 +147,24 @@ static int winch_tramp(int fd, void *device_data, int *fd_out) void register_winch(int fd, void *device_data) { int pid, thread, thread_fd; + int count; char c = 1; - if(!isatty(fd)) return; + if(!isatty(fd)) + return; pid = tcgetpgrp(fd); - if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && - (pid == -1)){ + if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, + device_data) && (pid == -1)){ thread = winch_tramp(fd, device_data, &thread_fd); if(fd != -1){ register_winch_irq(thread_fd, fd, thread, device_data); - if(write(thread_fd, &c, sizeof(c)) != sizeof(c)) + count = os_write_file(thread_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("register_winch : failed to write " - "synchronization byte\n"); + "synchronization byte, err = %d\n", + -count); } } } diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index d875d0435..19517312a 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -13,22 +13,22 @@ #error "__BYTE_ORDER not defined" #endif -extern int init_cow_file(int fd, char *cow_file, char *backing_file, - int sectorsize, int alignment, int *bitmap_offset_out, +extern int init_cow_file(int fd, char *cow_file, char *backing_file, + int sectorsize, int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out); extern int file_reader(__u64 offset, char *buf, int len, void *arg); -extern int read_cow_header(int (*reader)(__u64, char *, int, void *), - void *arg, __u32 *version_out, - char **backing_file_out, time_t *mtime_out, - __u64 *size_out, int *sectorsize_out, +extern int read_cow_header(int (*reader)(__u64, char *, int, void *), + void *arg, __u32 *version_out, + char **backing_file_out, time_t *mtime_out, + __u64 *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out); -extern int write_cow_header(char *cow_file, int fd, char *backing_file, +extern int write_cow_header(char *cow_file, int fd, char *backing_file, int sectorsize, int alignment, long long *size); extern void cow_sizes(int version, __u64 size, int sectorsize, int align, - int bitmap_offset, unsigned long *bitmap_len_out, + int bitmap_offset, unsigned long *bitmap_len_out, int *data_offset_out); #endif diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 014c2c853..122664b6b 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -27,20 +27,20 @@ struct cow_header_v1 { #define PATH_LEN_V2 MAXPATHLEN struct cow_header_v2 { - unsigned long magic; - unsigned long version; + __u32 magic; + __u32 version; char backing_file[PATH_LEN_V2]; time_t mtime; __u64 size; int sectorsize; }; -/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in +/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in * case other systems have different values for MAXPATHLEN */ #define PATH_LEN_V3 4096 -/* Changes from V2 - +/* Changes from V2 - * PATH_LEN_V3 as described above * Explicitly specify field bit lengths for systems with different * lengths for the usual C types. Not sure whether char or @@ -67,7 +67,7 @@ struct cow_header_v2 { struct cow_header_v3 { __u32 magic; __u32 version; - time_t mtime; + __u32 mtime; __u64 size; __u32 sectorsize; __u32 alignment; @@ -90,15 +90,15 @@ union cow_header { #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) -void cow_sizes(int version, __u64 size, int sectorsize, int align, - int bitmap_offset, unsigned long *bitmap_len_out, +void cow_sizes(int version, __u64 size, int sectorsize, int align, + int bitmap_offset, unsigned long *bitmap_len_out, int *data_offset_out) { if(version < 3){ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); *data_offset_out = bitmap_offset + *bitmap_len_out; - *data_offset_out = (*data_offset_out + sectorsize - 1) / + *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize; *data_offset_out *= sectorsize; } @@ -117,7 +117,7 @@ static int absolutize(char *to, int size, char *from) int remaining; if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { - cow_printf("absolutize : unable to get cwd - errno = %d\n", + cow_printf("absolutize : unable to get cwd - errno = %d\n", errno); return(-1); } @@ -126,7 +126,7 @@ static int absolutize(char *to, int size, char *from) *slash = '\0'; if(chdir(from)){ *slash = '/'; - cow_printf("absolutize : Can't cd to '%s' - " + cow_printf("absolutize : Can't cd to '%s' - " "errno = %d\n", from, errno); return(-1); } @@ -158,7 +158,7 @@ static int absolutize(char *to, int size, char *from) return(0); } -int write_cow_header(char *cow_file, int fd, char *backing_file, +int write_cow_header(char *cow_file, int fd, char *backing_file, int sectorsize, int alignment, long long *size) { struct cow_header_v3 *header; @@ -183,12 +183,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, err = -EINVAL; if(strlen(backing_file) > sizeof(header->backing_file) - 1){ cow_printf("Backing file name \"%s\" is too long - names are " - "limited to %d characters\n", backing_file, + "limited to %d characters\n", backing_file, sizeof(header->backing_file) - 1); goto out_free; } - if(absolutize(header->backing_file, sizeof(header->backing_file), + if(absolutize(header->backing_file, sizeof(header->backing_file), backing_file)) goto out_free; @@ -234,10 +234,10 @@ int file_reader(__u64 offset, char *buf, int len, void *arg) /* XXX Need to sanity-check the values read from the header */ -int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, - __u32 *version_out, char **backing_file_out, - time_t *mtime_out, __u64 *size_out, - int *sectorsize_out, __u32 *align_out, +int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, + __u32 *version_out, char **backing_file_out, + time_t *mtime_out, __u64 *size_out, + int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out) { union cow_header *header; @@ -310,7 +310,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, } else { cow_printf("read_cow_header - invalid COW version\n"); - goto out; + goto out; } err = -ENOMEM; *backing_file_out = cow_strdup(file); @@ -326,18 +326,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, } int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, - int alignment, int *bitmap_offset_out, + int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out) { __u64 size, offset; char zero = 0; int err; - err = write_cow_header(cow_file, fd, backing_file, sectorsize, + err = write_cow_header(cow_file, fd, backing_file, sectorsize, alignment, &size); - if(err) + if(err) goto out; - + *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, bitmap_len_out, data_offset_out); @@ -349,9 +349,9 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, goto out; } - /* does not really matter how much we write it is just to set EOF + /* does not really matter how much we write it is just to set EOF * this also sets the entire COW bitmap - * to zero without having to allocate it + * to zero without having to allocate it */ err = cow_write_file(fd, &zero, sizeof(zero)); if(err != sizeof(zero)){ diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index de71aec2d..cf15b4a8b 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -53,7 +53,8 @@ static int connect_to_switch(struct daemon_data *pri) struct request_v3 req; int fd, n, err; - if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ + pri->control = socket(AF_UNIX, SOCK_STREAM, 0); + if(pri->control < 0){ printk("daemon_open : control socket failed, errno = %d\n", errno); return(-errno); @@ -67,7 +68,8 @@ static int connect_to_switch(struct daemon_data *pri) goto out; } - if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){ + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if(fd < 0){ printk("daemon_open : data socket failed, errno = %d\n", errno); err = -errno; @@ -91,18 +93,18 @@ static int connect_to_switch(struct daemon_data *pri) req.version = SWITCH_VERSION; req.type = REQ_NEW_CONTROL; req.sock = *local_addr; - n = write(pri->control, &req, sizeof(req)); + n = os_write_file(pri->control, &req, sizeof(req)); if(n != sizeof(req)){ - printk("daemon_open : control setup request returned %d, " - "errno = %d\n", n, errno); + printk("daemon_open : control setup request failed, err = %d\n", + -n); err = -ENOTCONN; goto out; } - n = read(pri->control, sun, sizeof(*sun)); + n = os_read_file(pri->control, sun, sizeof(*sun)); if(n != sizeof(*sun)){ - printk("daemon_open : read of data socket returned %d, " - "errno = %d\n", n, errno); + printk("daemon_open : read of data socket failed, err = %d\n", + -n); err = -ENOTCONN; goto out_close; } @@ -111,9 +113,9 @@ static int connect_to_switch(struct daemon_data *pri) return(fd); out_close: - close(fd); + os_close_file(fd); out: - close(pri->control); + os_close_file(pri->control); return(err); } @@ -153,8 +155,8 @@ static void daemon_remove(void *data) { struct daemon_data *pri = data; - close(pri->fd); - close(pri->control); + os_close_file(pri->fd); + os_close_file(pri->control); if(pri->data_addr != NULL) kfree(pri->data_addr); if(pri->ctl_addr != NULL) kfree(pri->ctl_addr); if(pri->local_addr != NULL) kfree(pri->local_addr); diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 4ac314c1a..1c6daad92 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "user.h" #include "user_util.h" #include "chan_user.h" @@ -35,7 +36,8 @@ void *fd_init(char *str, int device, struct chan_opts *opts) printk("fd_init : couldn't parse file descriptor '%s'\n", str); return(NULL); } - if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct fd_chan) { .fd = n, .raw = opts->raw }); return(data); @@ -44,10 +46,16 @@ void *fd_init(char *str, int device, struct chan_opts *opts) int fd_open(int input, int output, int primary, void *d, char **dev_out) { struct fd_chan *data = d; + int err; if(data->raw && isatty(data->fd)){ - tcgetattr(data->fd, &data->tt); - raw(data->fd, 0); + CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); + if(err) + return(err); + + err = raw(data->fd); + if(err) + return(err); } sprintf(data->str, "%d", data->fd); *dev_out = data->str; @@ -57,9 +65,13 @@ int fd_open(int input, int output, int primary, void *d, char **dev_out) void fd_close(int fd, void *d) { struct fd_chan *data = d; + int err; if(data->raw && isatty(fd)){ - tcsetattr(fd, TCSAFLUSH, &data->tt); + CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); + if(err) + printk("Failed to restore terminal state - " + "errno = %d\n", -err); data->raw = 0; } } diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index cbbf41b5f..d934181b8 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -27,10 +27,10 @@ static void pre_exec(void *d) dup2(data->stdin, 0); dup2(data->stdout, 1); dup2(data->stdout, 2); - close(data->stdin); - close(data->stdout); - close(data->close_me[0]); - close(data->close_me[1]); + os_close_file(data->stdin); + os_close_file(data->stdout); + os_close_file(data->close_me[0]); + os_close_file(data->close_me[1]); } int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) @@ -44,15 +44,15 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) char **args = NULL; err = os_pipe(in_fds, 1, 0); - if(err){ - printk("harddog_open - os_pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("harddog_open - os_pipe failed, err = %d\n", -err); + goto out; } err = os_pipe(out_fds, 1, 0); - if(err){ - printk("harddog_open - os_pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("harddog_open - os_pipe failed, err = %d\n", -err); + goto out_close_in; } data.stdin = out_fds[0]; @@ -72,42 +72,47 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) pid = run_helper(pre_exec, &data, args, NULL); - close(out_fds[0]); - close(in_fds[1]); + os_close_file(out_fds[0]); + os_close_file(in_fds[1]); if(pid < 0){ err = -pid; - printk("harddog_open - run_helper failed, errno = %d\n", err); - goto out; + printk("harddog_open - run_helper failed, errno = %d\n", -err); + goto out_close_out; } - n = read(in_fds[0], &c, sizeof(c)); + n = os_read_file(in_fds[0], &c, sizeof(c)); if(n == 0){ printk("harddog_open - EOF on watchdog pipe\n"); helper_wait(pid); err = -EIO; - goto out; + goto out_close_out; } else if(n < 0){ printk("harddog_open - read of watchdog pipe failed, " - "errno = %d\n", errno); + "err = %d\n", -n); helper_wait(pid); - err = -errno; - goto out; + err = n; + goto out_close_out; } *in_fd_ret = in_fds[0]; *out_fd_ret = out_fds[1]; return(0); + + out_close_in: + os_close_file(in_fds[0]); + os_close_file(in_fds[1]); + out_close_out: + os_close_file(out_fds[0]); + os_close_file(out_fds[1]); out: - close(out_fds[1]); - close(in_fds[0]); return(err); } void stop_watchdog(int in_fd, int out_fd) { - close(in_fd); - close(out_fd); + os_close_file(in_fd); + os_close_file(out_fd); } int ping_watchdog(int fd) @@ -115,11 +120,12 @@ int ping_watchdog(int fd) int n; char c = '\n'; - n = write(fd, &c, sizeof(c)); - if(n < sizeof(c)){ - printk("ping_watchdog - write failed, errno = %d\n", - errno); - return(-errno); + n = os_write_file(fd, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("ping_watchdog - write failed, err = %d\n", -n); + if(n < 0) + return(n); + return(-EIO); } return 1; diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index b512783a4..d5742783e 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -5,44 +5,64 @@ #include "linux/config.h" #include "linux/module.h" -#include "linux/version.h" #include "linux/init.h" #include "linux/slab.h" #include "linux/fs.h" #include "linux/sound.h" #include "linux/soundcard.h" +#include "asm/uaccess.h" #include "kern_util.h" #include "init.h" -#include "hostaudio.h" +#include "os.h" + +struct hostaudio_state { + int fd; +}; + +struct hostmixer_state { + int fd; +}; + +#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" +#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" /* Only changed from linux_main at boot time */ char *dsp = HOSTAUDIO_DEV_DSP; char *mixer = HOSTAUDIO_DEV_MIXER; +#define DSP_HELP \ +" This is used to specify the host dsp device to the hostaudio driver.\n" \ +" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" + +#define MIXER_HELP \ +" This is used to specify the host mixer device to the hostaudio driver.\n"\ +" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" + #ifndef MODULE static int set_dsp(char *name, int *add) { - dsp = uml_strdup(name); + dsp = name; return(0); } -__uml_setup("dsp=", set_dsp, -"dsp=\n" -" This is used to specify the host dsp device to the hostaudio driver.\n" -" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" -); +__uml_setup("dsp=", set_dsp, "dsp=\n" DSP_HELP); static int set_mixer(char *name, int *add) { - mixer = uml_strdup(name); + mixer = name; return(0); } -__uml_setup("mixer=", set_mixer, -"mixer=\n" -" This is used to specify the host mixer device to the hostaudio driver.\n" -" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -); +__uml_setup("mixer=", set_mixer, "mixer=\n" MIXER_HELP); + +#else /*MODULE*/ + +MODULE_PARM(dsp, "s"); +MODULE_PARM_DESC(dsp, DSP_HELP); + +MODULE_PARM(mixer, "s"); +MODULE_PARM_DESC(mixer, MIXER_HELP); + #endif /* /dev/dsp file operations */ @@ -51,23 +71,56 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct hostaudio_state *state = file->private_data; + void *kbuf; + int err; #ifdef DEBUG printk("hostaudio: read called, count = %d\n", count); #endif - return(hostaudio_read_user(state, buffer, count, ppos)); + kbuf = kmalloc(count, GFP_KERNEL); + if(kbuf == NULL) + return(-ENOMEM); + + err = os_read_file(state->fd, kbuf, count); + if(err < 0) + goto out; + + if(copy_to_user(buffer, kbuf, err)) + err = -EFAULT; + + out: + kfree(kbuf); + return(err); } static ssize_t hostaudio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct hostaudio_state *state = file->private_data; + void *kbuf; + int err; #ifdef DEBUG printk("hostaudio: write called, count = %d\n", count); #endif - return(hostaudio_write_user(state, buffer, count, ppos)); + + kbuf = kmalloc(count, GFP_KERNEL); + if(kbuf == NULL) + return(-ENOMEM); + + err = -EFAULT; + if(copy_from_user(kbuf, buffer, count)) + goto out; + + err = os_write_file(state->fd, kbuf, count); + if(err < 0) + goto out; + *ppos += err; + + out: + kfree(kbuf); + return(err); } static unsigned int hostaudio_poll(struct file *file, @@ -86,12 +139,43 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct hostaudio_state *state = file->private_data; + unsigned long data = 0; + int err; #ifdef DEBUG printk("hostaudio: ioctl called, cmd = %u\n", cmd); #endif - - return(hostaudio_ioctl_user(state, cmd, arg)); + switch(cmd){ + case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + if(get_user(data, (int *) arg)) + return(-EFAULT); + break; + default: + break; + } + + err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data); + + switch(cmd){ + case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + if(put_user(data, (int *) arg)) + return(-EFAULT); + break; + default: + break; + } + + return(err); } static int hostaudio_open(struct inode *inode, struct file *file) @@ -105,17 +189,19 @@ static int hostaudio_open(struct inode *inode, struct file *file) #endif state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); - if(state == NULL) return(-ENOMEM); + if(state == NULL) + return(-ENOMEM); if(file->f_mode & FMODE_READ) r = 1; if(file->f_mode & FMODE_WRITE) w = 1; - ret = hostaudio_open_user(state, r, w, dsp); + ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); if(ret < 0){ kfree(state); return(ret); } + state->fd = ret; file->private_data = state; return(0); } @@ -123,16 +209,15 @@ static int hostaudio_open(struct inode *inode, struct file *file) static int hostaudio_release(struct inode *inode, struct file *file) { struct hostaudio_state *state = file->private_data; - int ret; #ifdef DEBUG printk("hostaudio: release called\n"); #endif - ret = hostaudio_release_user(state); + os_close_file(state->fd); kfree(state); - return(ret); + return(0); } /* /dev/mixer file operations */ @@ -146,7 +231,7 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, printk("hostmixer: ioctl called\n"); #endif - return(hostmixer_ioctl_mixdev_user(state, cmd, arg)); + return(os_ioctl_generic(state->fd, cmd, arg)); } static int hostmixer_open_mixdev(struct inode *inode, struct file *file) @@ -165,9 +250,11 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) if(file->f_mode & FMODE_READ) r = 1; if(file->f_mode & FMODE_WRITE) w = 1; - ret = hostmixer_open_mixdev_user(state, r, w, mixer); + ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); if(ret < 0){ + printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", + dsp, -ret); kfree(state); return(ret); } @@ -179,16 +266,15 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) static int hostmixer_release(struct inode *inode, struct file *file) { struct hostmixer_state *state = file->private_data; - int ret; #ifdef DEBUG printk("hostmixer: release called\n"); #endif - ret = hostmixer_release_mixdev_user(state); + os_close_file(state->fd); kfree(state); - return(ret); + return(0); } @@ -225,7 +311,8 @@ MODULE_LICENSE("GPL"); static int __init hostaudio_init_module(void) { - printk(KERN_INFO "UML Audio Relay\n"); + printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", + dsp, mixer); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); if(module_data.dev_audio < 0){ diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 92efc73ca..43611d11d 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -6,8 +6,8 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/list.h" +#include "linux/interrupt.h" #include "linux/devfs_fs_kernel.h" -#include "asm/irq.h" #include "asm/uaccess.h" #include "chan_kern.h" #include "irq_user.h" @@ -16,38 +16,55 @@ #include "user_util.h" #include "kern_util.h" #include "os.h" +#include "irq_kern.h" #define LINE_BUFSIZE 4096 -void line_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) { struct line *dev = data; if(dev->count > 0) chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, dev); + return IRQ_HANDLED; } -void line_timer_cb(void *arg) +static void line_timer_cb(void *arg) { struct line *dev = arg; line_interrupt(dev->driver->read_irq, dev, NULL); } -static void buffer_data(struct line *line, const char *buf, int len) +static int write_room(struct line *dev) { - int end; + int n; + + if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); + + n = dev->head - dev->tail; + if(n <= 0) n = LINE_BUFSIZE + n; + return(n - 1); +} + +static int buffer_data(struct line *line, const char *buf, int len) +{ + int end, room; if(line->buffer == NULL){ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); if(line->buffer == NULL){ printk("buffer_data - atomic allocation failed\n"); - return; + return(0); } line->head = line->buffer; line->tail = line->buffer; } + + room = write_room(line); + len = (len > room) ? room : len; + end = line->buffer + LINE_BUFSIZE - line->tail; if(len < end){ memcpy(line->tail, buf, len); @@ -56,10 +73,11 @@ static void buffer_data(struct line *line, const char *buf, int len) else { memcpy(line->tail, buf, end); buf += end; - len -= end; - memcpy(line->buffer, buf, len); - line->tail = line->buffer + len; + memcpy(line->buffer, buf, len - end); + line->tail = line->buffer + len - end; } + + return(len); } static int flush_buffer(struct line *line) @@ -89,67 +107,61 @@ static int flush_buffer(struct line *line) return(line->head == line->tail); } -int line_write(struct line *lines, struct tty_struct *tty, int from_user, - const char *buf, int len) +int line_write(struct line *lines, struct tty_struct *tty, const char *buf, int len) { struct line *line; - char *new; unsigned long flags; - int n, err, i; + int n, err, i, ret = 0; if(tty->stopped) return 0; - if(from_user){ - new = kmalloc(len, GFP_KERNEL); - if(new == NULL) - return(0); - n = copy_from_user(new, buf, len); - if(n == len) - return(-EFAULT); - buf = new; - } - i = tty->index; line = &lines[i]; down(&line->sem); if(line->head != line->tail){ local_irq_save(flags); - buffer_data(line, buf, len); + ret += buffer_data(line, buf, len); err = flush_buffer(line); local_irq_restore(flags); if(err <= 0) - goto out; + goto out_up; } else { n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if(n < 0){ - len = n; - goto out; + ret = n; + goto out_up; } - if(n < len) - buffer_data(line, buf + n, len - n); + + len -= n; + ret += n; + if(len > 0) + ret += buffer_data(line, buf + n, len); } - out: + out_up: up(&line->sem); - return(len); + return(ret); } -void line_write_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t line_write_interrupt(int irq, void *data, + struct pt_regs *unused) { struct line *dev = data; struct tty_struct *tty = dev->tty; int err; err = flush_buffer(dev); - if(err == 0) return; + if(err == 0) + return(IRQ_NONE); else if(err < 0){ dev->head = dev->buffer; dev->tail = dev->buffer; } - if(tty == NULL) return; + if(tty == NULL) + return(IRQ_NONE); if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) @@ -161,21 +173,9 @@ void line_write_interrupt(int irq, void *data, struct pt_regs *unused) * writes. */ - if (waitqueue_active(&tty->write_wait)) + if(waitqueue_active(&tty->write_wait)) wake_up_interruptible(&tty->write_wait); - -} - -int line_write_room(struct tty_struct *tty) -{ - struct line *dev = tty->driver_data; - int n; - - if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); - - n = dev->head - dev->tail; - if(n <= 0) n = LINE_BUFSIZE + n; - return(n - 1); + return(IRQ_HANDLED); } int line_setup_irq(int fd, int input, int output, void *data) @@ -201,13 +201,17 @@ void line_disable(struct line *line, int current_irq) if(line->driver->read_irq == current_irq) free_irq_later(line->driver->read_irq, line); - else + else { + free_irq_by_irq_and_dev(line->driver->read_irq, line); free_irq(line->driver->read_irq, line); + } if(line->driver->write_irq == current_irq) free_irq_later(line->driver->write_irq, line); - else + else { + free_irq_by_irq_and_dev(line->driver->write_irq, line); free_irq(line->driver->write_irq, line); + } line->have_irq = 0; } @@ -305,20 +309,20 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed) if(*end != '='){ printk(KERN_ERR "line_setup failed to parse \"%s\"\n", init); - return(1); + return(0); } init = end; } init++; if((n >= 0) && (n >= num)){ printk("line_setup - %d out of range ((0 ... %d) allowed)\n", - n, num); - return(1); + n, num - 1); + return(0); } else if(n >= 0){ if(lines[n].count > 0){ printk("line_setup - device %d is open\n", n); - return(1); + return(0); } if(lines[n].init_pri <= INIT_ONE){ lines[n].init_pri = INIT_ONE; @@ -332,7 +336,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed) else if(!all_allowed){ printk("line_setup - can't configure all devices from " "mconsole\n"); - return(1); + return(0); } else { for(i = 0; i < num; i++){ @@ -346,7 +350,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed) } } } - return(0); + return(1); } int line_config(struct line *lines, int num, char *str) @@ -357,7 +361,7 @@ int line_config(struct line *lines, int num, char *str) printk("line_config - uml_strdup failed\n"); return(-ENOMEM); } - return(line_setup(lines, num, new, 0)); + return(!line_setup(lines, num, new, 0)); } int line_get_config(char *name, struct line *lines, int num, char *str, @@ -369,7 +373,7 @@ int line_get_config(char *name, struct line *lines, int num, char *str, dev = simple_strtoul(name, &end, 0); if((*end != '\0') || (end == name)){ - *error_out = "line_setup failed to parse device number"; + *error_out = "line_get_config failed to parse device number"; return(0); } @@ -379,15 +383,15 @@ int line_get_config(char *name, struct line *lines, int num, char *str, } line = &lines[dev]; + down(&line->sem); - if(!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); else if(line->count == 0) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); - up(&line->sem); + return(n); } @@ -396,7 +400,14 @@ int line_remove(struct line *lines, int num, char *str) char config[sizeof("conxxxx=none\0")]; sprintf(config, "%s=none", str); - return(line_setup(lines, num, config, 0)); + return(!line_setup(lines, num, config, 0)); +} + +int line_write_room(struct tty_struct *tty) +{ + struct line *dev = tty->driver_data; + + return(write_room(dev)); } struct tty_driver *line_register_devfs(struct lines *set, @@ -412,7 +423,8 @@ struct tty_driver *line_register_devfs(struct lines *set, return NULL; driver->driver_name = line_driver->name; - driver->name = line_driver->devfs_name; + driver->name = line_driver->device_name; + driver->devfs_name = line_driver->devfs_name; driver->major = line_driver->major; driver->minor_start = line_driver->minor_start; driver->type = line_driver->type; @@ -432,7 +444,7 @@ struct tty_driver *line_register_devfs(struct lines *set, for(i = 0; i < nlines; i++){ if(!lines[i].valid) - tty_unregister_devfs(driver, i); + tty_unregister_device(driver, i); } mconsole_register_dev(&line_driver->mc); @@ -465,24 +477,25 @@ struct winch { struct line *line; }; -void winch_interrupt(int irq, void *data, struct pt_regs *unused) +irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) { struct winch *winch = data; struct tty_struct *tty; int err; char c; - err = generic_read(winch->fd, &c, NULL); - if(err < 0){ - if(err != -EAGAIN){ - printk("winch_interrupt : read failed, errno = %d\n", - -err); - printk("fd %d is losing SIGWINCH support\n", - winch->tty_fd); - free_irq(irq, data); - return; + if(winch->fd != -1){ + err = generic_read(winch->fd, &c, NULL); + if(err < 0){ + if(err != -EAGAIN){ + printk("winch_interrupt : read failed, " + "errno = %d\n", -err); + printk("fd %d is losing SIGWINCH support\n", + winch->tty_fd); + return(IRQ_HANDLED); + } + goto out; } - goto out; } tty = winch->line->tty; if(tty != NULL){ @@ -492,7 +505,9 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused) kill_pg(tty->pgrp, SIGWINCH, 1); } out: - reactivate_fd(winch->fd, WINCH_IRQ); + if(winch->fd != -1) + reactivate_fd(winch->fd, WINCH_IRQ); + return(IRQ_HANDLED); } DECLARE_MUTEX(winch_handler_sem); @@ -529,7 +544,10 @@ static void winch_cleanup(void) list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); - close(winch->fd); + if(winch->fd != -1){ + deactivate_fd(winch->fd, WINCH_IRQ); + os_close_file(winch->fd); + } if(winch->pid != -1) os_kill_process(winch->pid, 1); } diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 58e5db630..0fe1d9fa9 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -23,6 +23,7 @@ #include "kern_util.h" #include "user_util.h" #include "user.h" +#include "os.h" #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) @@ -62,7 +63,8 @@ static int mcast_open(void *data) goto out; } - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); fd = -ENOMEM; @@ -72,7 +74,7 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -82,7 +84,7 @@ static int mcast_open(void *data) sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -91,7 +93,7 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -99,7 +101,7 @@ static int mcast_open(void *data) /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -115,7 +117,7 @@ static int mcast_open(void *data) "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); - close(fd); + os_close_file(fd); fd = -EINVAL; } @@ -137,7 +139,7 @@ static void mcast_close(int fd, void *data) errno); } - close(fd); + os_close_file(fd); } int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b12cb189d..0c87589c0 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -15,7 +15,11 @@ #include "linux/sysrq.h" #include "linux/workqueue.h" #include "linux/module.h" +#include "linux/file.h" +#include "linux/fs.h" +#include "linux/namei.h" #include "linux/proc_fs.h" +#include "linux/syscalls.h" #include "asm/irq.h" #include "asm/uaccess.h" #include "user_util.h" @@ -27,6 +31,7 @@ #include "init.h" #include "os.h" #include "umid.h" +#include "irq_kern.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) @@ -47,27 +52,26 @@ static struct notifier_block reboot_notifier = { LIST_HEAD(mc_requests); -void mc_work_proc(void *unused) +static void mc_work_proc(void *unused) { struct mconsole_entry *req; unsigned long flags; - int done; - do { + while(!list_empty(&mc_requests)){ local_save_flags(flags); req = list_entry(mc_requests.next, struct mconsole_entry, list); list_del(&req->list); - done = list_empty(&mc_requests); local_irq_restore(flags); req->request.cmd->handler(&req->request); kfree(req); - } while(!done); + } } DECLARE_WORK(mconsole_work, mc_work_proc, NULL); -void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mconsole_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { int fd; struct mconsole_entry *new; @@ -75,9 +79,10 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) fd = (int) dev_id; while (mconsole_get_request(fd, &req)){ - if(req.cmd->as_interrupt) (*req.cmd->handler)(&req); + if(req.cmd->context == MCONSOLE_INTR) + (*req.cmd->handler)(&req); else { - new = kmalloc(sizeof(req), GFP_ATOMIC); + new = kmalloc(sizeof(*new), GFP_ATOMIC); if(new == NULL) mconsole_reply(&req, "Out of memory", 1, 0); else { @@ -86,8 +91,10 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } } - if(!list_empty(&mc_requests)) schedule_work(&mconsole_work); + if(!list_empty(&mc_requests)) + schedule_work(&mconsole_work); reactivate_fd(fd, MCONSOLE_IRQ); + return(IRQ_HANDLED); } void mconsole_version(struct mc_request *req) @@ -100,20 +107,174 @@ void mconsole_version(struct mc_request *req) mconsole_reply(req, version, 0, 0); } +void mconsole_log(struct mc_request *req) +{ + int len; + char *ptr = req->request.data; + + ptr += strlen("log "); + + len = req->len - (ptr - req->request.data); + printk("%.*s", len, ptr); + mconsole_reply(req, "", 0, 0); +} + +/* This is a more convoluted version of mconsole_proc, which has some stability + * problems; however, we need it fixed, because it is expected that UML users + * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still + * show the real procfs content, not the ones from hppfs.*/ +#if 0 +void mconsole_proc(struct mc_request *req) +{ + struct nameidata nd; + struct file_system_type *proc; + struct super_block *super; + struct file *file; + int n, err; + char *ptr = req->request.data, *buf; + + ptr += strlen("proc"); + while(isspace(*ptr)) ptr++; + + proc = get_fs_type("proc"); + if(proc == NULL){ + mconsole_reply(req, "procfs not registered", 1, 0); + goto out; + } + + super = (*proc->get_sb)(proc, 0, NULL, NULL); + put_filesystem(proc); + if(super == NULL){ + mconsole_reply(req, "Failed to get procfs superblock", 1, 0); + goto out; + } + up_write(&super->s_umount); + + nd.dentry = super->s_root; + nd.mnt = NULL; + nd.flags = O_RDONLY + 1; + nd.last_type = LAST_ROOT; + + /* START: it was experienced that the stability problems are closed + * if commenting out these two calls + the below read cycle. To + * make UML crash again, it was enough to readd either one.*/ + err = link_path_walk(ptr, &nd); + if(err){ + mconsole_reply(req, "Failed to look up file", 1, 0); + goto out_kill; + } + + file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); + if(IS_ERR(file)){ + mconsole_reply(req, "Failed to open file", 1, 0); + goto out_kill; + } + /*END*/ + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if(buf == NULL){ + mconsole_reply(req, "Failed to allocate buffer", 1, 0); + goto out_fput; + } + + if((file->f_op != NULL) && (file->f_op->read != NULL)){ + do { + n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, + &file->f_pos); + if(n >= 0){ + buf[n] = '\0'; + mconsole_reply(req, buf, 0, (n > 0)); + } + else { + mconsole_reply(req, "Read of file failed", + 1, 0); + goto out_free; + } + } while(n > 0); + } + else mconsole_reply(req, "", 0, 0); + + out_free: + kfree(buf); + out_fput: + fput(file); + out_kill: + deactivate_super(super); + out: ; +} +#endif + +void mconsole_proc(struct mc_request *req) +{ + char path[64]; + char *buf; + int len; + int fd; + int first_chunk = 1; + char *ptr = req->request.data; + + ptr += strlen("proc"); + while(isspace(*ptr)) ptr++; + snprintf(path, sizeof(path), "/proc/%s", ptr); + + fd = sys_open(path, 0, 0); + if (fd < 0) { + mconsole_reply(req, "Failed to open file", 1, 0); + printk("open %s: %d\n",path,fd); + goto out; + } + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if(buf == NULL){ + mconsole_reply(req, "Failed to allocate buffer", 1, 0); + goto out_close; + } + + for (;;) { + len = sys_read(fd, buf, PAGE_SIZE-1); + if (len < 0) { + mconsole_reply(req, "Read of file failed", 1, 0); + goto out_free; + } + /*Begin the file content on his own line.*/ + if (first_chunk) { + mconsole_reply(req, "\n", 0, 1); + first_chunk = 0; + } + if (len == PAGE_SIZE-1) { + buf[len] = '\0'; + mconsole_reply(req, buf, 0, 1); + } else { + buf[len] = '\0'; + mconsole_reply(req, buf, 0, 0); + break; + } + } + + out_free: + kfree(buf); + out_close: + sys_close(fd); + out: + /* nothing */; +} + #define UML_MCONSOLE_HELPTEXT \ -"Commands: - version - Get kernel version - help - Print this message - halt - Halt UML - reboot - Reboot UML - config = - Add a new device to UML; - same syntax as command line - config - Query the configuration of a device - remove - Remove a device from UML - sysrq - Performs the SysRq action controlled by the letter - cad - invoke the Ctl-Alt-Del handler - stop - pause the UML; it will do nothing until it receives a 'go' - go - continue the UML after a 'stop' +"Commands: \n\ + version - Get kernel version \n\ + help - Print this message \n\ + halt - Halt UML \n\ + reboot - Reboot UML \n\ + config = - Add a new device to UML; \n\ + same syntax as command line \n\ + config - Query the configuration of a device \n\ + remove - Remove a device from UML \n\ + sysrq - Performs the SysRq action controlled by the letter \n\ + cad - invoke the Ctl-Alt-Del handler \n\ + stop - pause the UML; it will do nothing until it receives a 'go' \n\ + go - continue the UML after a 'stop' \n\ + log - make UML enter into the kernel log\n\ + proc - returns the contents of the UML's /proc/\n\ " void mconsole_help(struct mc_request *req) @@ -279,8 +440,8 @@ void mconsole_sysrq(struct mc_request *req) ptr += strlen("sysrq"); while(isspace(*ptr)) ptr++; - handle_sysrq(*ptr, ¤t->thread.regs, NULL); mconsole_reply(req, "", 0, 0); + handle_sysrq(*ptr, ¤t->thread.regs, NULL); } #else void mconsole_sysrq(struct mc_request *req) @@ -302,7 +463,7 @@ int mconsole_init(void) if(umid_file_name("mconsole", file, sizeof(file))) return(-1); snprintf(mconsole_socket_name, sizeof(file), "%s", file); - sock = create_unix_socket(file, sizeof(file)); + sock = os_create_unix_socket(file, sizeof(file), 1); if (sock < 0){ printk("Failed to initialize management console\n"); return(1); @@ -344,11 +505,16 @@ static int write_proc_mconsole(struct file *file, const char *buffer, if(buf == NULL) return(-ENOMEM); - if(copy_from_user(buf, buffer, count)) - return(-EFAULT); + if(copy_from_user(buf, buffer, count)){ + count = -EFAULT; + goto out; + } + buf[count] = '\0'; mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); + out: + kfree(buf); return(count); } diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 11b09a96f..fe5afb132 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -18,16 +18,18 @@ #include "umid.h" static struct mconsole_command commands[] = { - { "version", mconsole_version, 1 }, - { "halt", mconsole_halt, 0 }, - { "reboot", mconsole_reboot, 0 }, - { "config", mconsole_config, 0 }, - { "remove", mconsole_remove, 0 }, - { "sysrq", mconsole_sysrq, 1 }, - { "help", mconsole_help, 1 }, - { "cad", mconsole_cad, 1 }, - { "stop", mconsole_stop, 0 }, - { "go", mconsole_go, 1 }, + { "version", mconsole_version, MCONSOLE_INTR }, + { "halt", mconsole_halt, MCONSOLE_PROC }, + { "reboot", mconsole_reboot, MCONSOLE_PROC }, + { "config", mconsole_config, MCONSOLE_PROC }, + { "remove", mconsole_remove, MCONSOLE_PROC }, + { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, + { "help", mconsole_help, MCONSOLE_INTR }, + { "cad", mconsole_cad, MCONSOLE_INTR }, + { "stop", mconsole_stop, MCONSOLE_PROC }, + { "go", mconsole_go, MCONSOLE_INTR }, + { "log", mconsole_log, MCONSOLE_INTR }, + { "proc", mconsole_proc, MCONSOLE_PROC }, }; /* Initialized in mconsole_init, which is an initcall */ @@ -139,6 +141,7 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more) memcpy(reply.data, str, len); reply.data[len] = '\0'; total -= len; + str += len; reply.len = len + 1; len = sizeof(reply) + reply.len - sizeof(reply.data); diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 628d8f804..313846434 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -81,10 +81,10 @@ mmapper_mmap(struct file *file, struct vm_area_struct * vma) size = vma->vm_end - vma->vm_start; if(size > mmapper_size) return(-EFAULT); - /* XXX A comment above remap_page_range says it should only be + /* XXX A comment above remap_pfn_range says it should only be * called when the mm semaphore is held */ - if (remap_page_range(vma, vma->vm_start, p_buf, size, + if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size, vma->vm_page_prot)) goto out; ret = 0; @@ -120,7 +120,10 @@ static int __init mmapper_init(void) printk(KERN_INFO "Mapper v0.1\n"); v_buf = (char *) find_iomem("mmapper", &mmapper_size); - if(mmapper_size == 0) return(0); + if(mmapper_size == 0){ + printk(KERN_ERR "mmapper_init - find_iomem failed\n"); + return(0); + } p_buf = __pa(v_buf); diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index a52b79dfd..66347c26f 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -19,6 +19,8 @@ #include "linux/inetdevice.h" #include "linux/ctype.h" #include "linux/bootmem.h" +#include "linux/ethtool.h" +#include "asm/uaccess.h" #include "user_util.h" #include "kern_util.h" #include "net_kern.h" @@ -26,6 +28,7 @@ #include "mconsole_kern.h" #include "init.h" #include "irq_user.h" +#include "irq_kern.h" static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; LIST_HEAD(opened); @@ -37,7 +40,8 @@ static int uml_net_rx(struct net_device *dev) struct sk_buff *skb; /* If we can't allocate memory, try again next round. */ - if ((skb = dev_alloc_skb(dev->mtu)) == NULL) { + skb = dev_alloc_skb(dev->mtu); + if (skb == NULL) { lp->stats.rx_dropped++; return 0; } @@ -61,14 +65,14 @@ static int uml_net_rx(struct net_device *dev) return pkt_len; } -void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct uml_net_private *lp = dev->priv; int err; if(!netif_running(dev)) - return; + return(IRQ_NONE); spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; @@ -83,6 +87,7 @@ void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) out: spin_unlock(&lp->lock); + return(IRQ_HANDLED); } static int uml_net_open(struct net_device *dev) @@ -124,6 +129,13 @@ static int uml_net_open(struct net_device *dev) spin_lock(&opened_lock); list_add(&lp->list, &opened); spin_unlock(&opened_lock); + + /* clear buffer - it can happen that the host side of the interface + * is full when we get here. In this case, new data is never queued, + * SIGIOs never arrive, and the net never works. + */ + while((err = uml_net_rx(dev)) > 0) ; + out: spin_unlock(&lp->lock); return(err); @@ -136,6 +148,7 @@ static int uml_net_close(struct net_device *dev) netif_stop_queue(dev); spin_lock(&lp->lock); + free_irq_by_irq_and_dev(dev->irq, dev); free_irq(dev->irq, dev); if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; @@ -237,7 +250,30 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - return(-EINVAL); + static const struct ethtool_drvinfo info = { + .cmd = ETHTOOL_GDRVINFO, + .driver = "uml virtual ethernet", + .version = "42", + }; + void *useraddr; + u32 ethcmd; + + switch (cmd) { + case SIOCETHTOOL: + useraddr = ifr->ifr_data; + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + switch (ethcmd) { + case ETHTOOL_GDRVINFO: + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + default: + return -EOPNOTSUPP; + } + default: + return -EINVAL; + } } void uml_net_user_timer_expire(unsigned long _conn) @@ -250,37 +286,6 @@ void uml_net_user_timer_expire(unsigned long _conn) #endif } -/* - * default do nothing hard header packet routines for struct net_device init. - * real ethernet transports will overwrite with real routines. - */ -static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) -{ - return(0); /* no change */ -} - -static int uml_net_rebuild_header(struct sk_buff *skb) -{ - return(0); /* ignore */ -} - -static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh) -{ - return(-1); /* fail */ -} - -static void uml_net_header_cache_update(struct hh_cache *hh, - struct net_device *dev, unsigned char * haddr) -{ - /* ignore */ -} - -static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr) -{ - return(0); /* nothing */ -} - static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED; static struct list_head devices = LIST_HEAD_INIT(devices); @@ -290,7 +295,7 @@ static int eth_configure(int n, void *init, char *mac, struct uml_net *device; struct net_device *dev; struct uml_net_private *lp; - int err, size; + int save, err, size; size = transport->private_size + sizeof(struct uml_net_private) + sizeof(((struct uml_net_private *) 0)->user); @@ -332,12 +337,6 @@ static int eth_configure(int n, void *init, char *mac, snprintf(dev->name, sizeof(dev->name), "eth%d", n); device->dev = dev; - dev->hard_header = uml_net_hard_header; - dev->rebuild_header = uml_net_rebuild_header; - dev->hard_header_cache = uml_net_header_cache; - dev->header_cache_update= uml_net_header_cache_update; - dev->hard_header_parse = uml_net_header_parse; - (*transport->kern->init)(dev, init); dev->mtu = transport->user->max_packet; @@ -364,21 +363,29 @@ static int eth_configure(int n, void *init, char *mac, } lp = dev->priv; - INIT_LIST_HEAD(&lp->list); - spin_lock_init(&lp->lock); - lp->dev = dev; - lp->fd = -1; - lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 }; - lp->have_mac = device->have_mac; - lp->protocol = transport->kern->protocol; - lp->open = transport->user->open; - lp->close = transport->user->close; - lp->remove = transport->user->remove; - lp->read = transport->kern->read; - lp->write = transport->kern->write; - lp->add_address = transport->user->add_address; - lp->delete_address = transport->user->delete_address; - lp->set_mtu = transport->user->set_mtu; + /* lp.user is the first four bytes of the transport data, which + * has already been initialized. This structure assignment will + * overwrite that, so we make sure that .user gets overwritten with + * what it already has. + */ + save = lp->user[0]; + *lp = ((struct uml_net_private) + { .list = LIST_HEAD_INIT(lp->list), + .lock = SPIN_LOCK_UNLOCKED, + .dev = dev, + .fd = -1, + .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, + .have_mac = device->have_mac, + .protocol = transport->kern->protocol, + .open = transport->user->open, + .close = transport->user->close, + .remove = transport->user->remove, + .read = transport->kern->read, + .write = transport->kern->write, + .add_address = transport->user->add_address, + .delete_address = transport->user->delete_address, + .set_mtu = transport->user->set_mtu, + .user = { save } }); init_timer(&lp->tl); lp->tl.function = uml_net_user_timer_expire; @@ -611,7 +618,8 @@ static int net_remove(char *str) unregister_netdev(dev); list_del(&device->list); - free_netdev(device); + kfree(device); + free_netdev(dev); return(0); } diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 75a83e9e1..2e4e1d49f 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -26,8 +26,7 @@ int tap_open_common(void *dev, char *gate_addr) if(gate_addr == NULL) return(0); if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ - printk("Invalid tap IP address - '%s'\n", - gate_addr); + printk("Invalid tap IP address - '%s'\n", gate_addr); return(-EINVAL); } return(0); @@ -60,18 +59,18 @@ void read_output(int fd, char *output, int len) } *output = '\0'; - if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){ - printk("read_output - read of length failed, errno = %d\n", - errno); + n = os_read_file(fd, &remain, sizeof(remain)); + if(n != sizeof(remain)){ + printk("read_output - read of length failed, err = %d\n", -n); return; } while(remain != 0){ n = (remain < len) ? remain : len; - actual = read(fd, output, n); + actual = os_read_file(fd, output, n); if(actual != n){ printk("read_output - read of data failed, " - "errno = %d\n", errno); + "err = %d\n", -actual); return; } remain -= actual; @@ -83,13 +82,12 @@ int net_read(int fd, void *buf, int len) { int n; - while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ; + n = os_read_file(fd, buf, len); - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-ENOTCONN); + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-ENOTCONN); return(n); } @@ -112,13 +110,13 @@ int net_write(int fd, void *buf, int len) { int n; - while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ; - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-ENOTCONN); - return(n); + n = os_write_file(fd, buf, len); + + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-ENOTCONN); + return(n); } int net_send(int fd, void *buf, int len) @@ -157,7 +155,7 @@ static void change_pre_exec(void *arg) { struct change_pre_exec_data *data = arg; - close(data->close_me); + os_close_file(data->close_me); dup2(data->stdout, 1); } @@ -167,17 +165,18 @@ static int change_tramp(char **argv, char *output, int output_len) struct change_pre_exec_data pe_data; err = os_pipe(fds, 1, 0); - if(err){ - printk("change_tramp - pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("change_tramp - pipe failed, err = %d\n", -err); return(err); } pe_data.close_me = fds[0]; pe_data.stdout = fds[1]; pid = run_helper(change_pre_exec, &pe_data, argv, NULL); - close(fds[1]); + os_close_file(fds[1]); read_output(fds[0], output, output_len); - waitpid(pid, NULL, 0); + + CATCH_EINTR(err = waitpid(pid, NULL, 0)); return(pid); } diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index d361554eb..66b2fbe3d 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c @@ -5,7 +5,6 @@ #include #include -#include #include "chan_user.h" #include "os.h" diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 3c4463019..14f66da4d 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -6,6 +6,7 @@ #include "linux/list.h" #include "linux/sched.h" #include "linux/slab.h" +#include "linux/interrupt.h" #include "linux/irq.h" #include "linux/spinlock.h" #include "linux/errno.h" @@ -14,6 +15,7 @@ #include "kern_util.h" #include "kern.h" #include "irq_user.h" +#include "irq_kern.h" #include "port.h" #include "init.h" #include "os.h" @@ -38,21 +40,21 @@ struct port_dev { struct connection { struct list_head list; int fd; - int helper_pid; + int helper_pid; int socket[2]; int telnetd_pid; struct port_list *port; }; -static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) { struct connection *conn = data; int fd; - fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); + fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); if(fd < 0){ if(fd == -EAGAIN) - return; + return(IRQ_NONE); printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -fd); @@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) list_add(&conn->list, &conn->port->connections); up(&conn->port->sem); + return(IRQ_HANDLED); } static int port_accept(struct port_list *port) @@ -102,8 +105,7 @@ static int port_accept(struct port_list *port) } list_add(&conn->list, &port->pending); - ret = 1; - goto out; + return(1); out_free: kfree(conn); @@ -138,12 +140,13 @@ void port_work_proc(void *unused) DECLARE_WORK(port_work, port_work_proc, NULL); -static void port_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs) { struct port_list *port = data; port->has_connection = 1; schedule_work(&port_work); + return(IRQ_HANDLED); } void *port_data(int port_num) @@ -239,6 +242,7 @@ int port_wait(void *data) * connection. Then we loop here throwing out failed * connections until a good one is found. */ + free_irq_by_irq_and_dev(TELNETD_IRQ, conn); free_irq(TELNETD_IRQ, conn); if(conn->fd >= 0) break; diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index 7a37cf6a2..996e817f3 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -47,10 +47,12 @@ void *port_init(char *str, int device, struct chan_opts *opts) return(NULL); } - if((kern_data = port_data(port)) == NULL) + kern_data = port_data(port); + if(kern_data == NULL) return(NULL); - if((data = um_kmalloc(sizeof(*data))) == NULL) + data = um_kmalloc(sizeof(*data)); + if(data == NULL) goto err; *data = ((struct port_chan) { .raw = opts->raw, @@ -74,12 +76,17 @@ void port_free(void *d) int port_open(int input, int output, int primary, void *d, char **dev_out) { struct port_chan *data = d; - int fd; + int fd, err; fd = port_wait(data->kernel_data); if((fd >= 0) && data->raw){ - tcgetattr(fd, &data->tt); - raw(fd, 0); + CATCH_EINTR(err = tcgetattr(fd, &data->tt)); + if(err) + return(err); + + err = raw(fd); + if(err) + return(err); } *dev_out = data->dev; return(fd); @@ -90,7 +97,7 @@ void port_close(int fd, void *d) struct port_chan *data = d; port_remove_dev(data->kernel_data); - close(fd); + os_close_file(fd); } int port_console_write(int fd, const char *buf, int n, void *d) @@ -116,12 +123,18 @@ struct chan_ops port_ops = { int port_listen_fd(int port) { struct sockaddr_in addr; - int fd, err; + int fd, err, arg; fd = socket(PF_INET, SOCK_STREAM, 0); if(fd == -1) return(-errno); + arg = 1; + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ + err = -errno; + goto out; + } + addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); @@ -130,11 +143,15 @@ int port_listen_fd(int port) goto out; } - if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){ + if(listen(fd, 1) < 0){ err = -errno; goto out; } + err = os_set_fd_block(fd, 0); + if(err < 0) + goto out; + return(fd); out: os_close_file(fd); @@ -153,10 +170,10 @@ void port_pre_exec(void *arg) dup2(data->sock_fd, 0); dup2(data->sock_fd, 1); dup2(data->sock_fd, 2); - close(data->sock_fd); + os_close_file(data->sock_fd); dup2(data->pipe_fd, 3); os_shutdown_socket(3, 1, 0); - close(data->pipe_fd); + os_close_file(data->pipe_fd); } int port_connection(int fd, int *socket, int *pid_out) @@ -166,11 +183,12 @@ int port_connection(int fd, int *socket, int *pid_out) "/usr/lib/uml/port-helper", NULL }; struct port_pre_exec_data data; - if((new = os_accept_connection(fd)) < 0) - return(-errno); + new = os_accept_connection(fd); + if(new < 0) + return(new); err = os_pipe(socket, 0, 0); - if(err) + if(err < 0) goto out_close; data = ((struct port_pre_exec_data) @@ -186,11 +204,11 @@ int port_connection(int fd, int *socket, int *pid_out) out_shutdown: os_shutdown_socket(socket[0], 1, 1); - close(socket[0]); + os_close_file(socket[0]); os_shutdown_socket(socket[1], 1, 1); - close(socket[1]); + os_close_file(socket[1]); out_close: - close(new); + os_close_file(new); return(err); } diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 027405386..c4634b500 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -7,12 +7,12 @@ #include #include #include -#include #include #include "chan_user.h" #include "user.h" #include "user_util.h" #include "kern_util.h" +#include "os.h" struct pty_chan { void (*announce)(char *dev_name, int dev); @@ -26,7 +26,8 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts) { struct pty_chan *data; - if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct pty_chan) { .announce = opts->announce, .dev = device, .raw = opts->raw }); @@ -37,15 +38,21 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out) { struct pty_chan *data = d; char *dev; - int fd; + int fd, err; - if((fd = get_pty()) < 0){ + fd = get_pty(); + if(fd < 0){ printk("open_pts : Failed to open pts\n"); return(-errno); } if(data->raw){ - tcgetattr(fd, &data->tt); - raw(fd, 0); + CATCH_EINTR(err = tcgetattr(fd, &data->tt)); + if(err) + return(err); + + err = raw(fd); + if(err) + return(err); } dev = ptsname(fd); @@ -57,29 +64,27 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out) int getmaster(char *line) { - struct stat stb; char *pty, *bank, *cp; - int master; + int master, err; pty = &line[strlen("/dev/ptyp")]; for (bank = "pqrs"; *bank; bank++) { line[strlen("/dev/pty")] = *bank; *pty = '0'; - if (stat(line, &stb) < 0) + if (os_stat_file(line, NULL) < 0) break; for (cp = "0123456789abcdef"; *cp; cp++) { *pty = *cp; - master = open(line, O_RDWR); + master = os_open_file(line, of_rdwr(OPENFLAGS()), 0); if (master >= 0) { char *tp = &line[strlen("/dev/")]; - int ok; /* verify slave side is usable */ *tp = 't'; - ok = access(line, R_OK|W_OK) == 0; + err = os_access(line, OS_ACC_RW_OK); *tp = 'p'; - if (ok) return(master); - (void) close(master); + if(err == 0) return(master); + (void) os_close_file(master); } } } @@ -89,13 +94,19 @@ int getmaster(char *line) int pty_open(int input, int output, int primary, void *d, char **dev_out) { struct pty_chan *data = d; - int fd; + int fd, err; char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx"; fd = getmaster(dev); - if(fd < 0) return(-errno); + if(fd < 0) + return(-errno); + + if(data->raw){ + err = raw(fd); + if(err) + return(err); + } - if(data->raw) raw(fd, 0); if(data->announce) (*data->announce)(dev, data->dev); sprintf(data->dev_name, "%s", dev); diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 782cf522b..3d8d4ca36 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -4,11 +4,9 @@ #include #include #include -#include -#include +#include #include #include -#include #include #include "user_util.h" #include "kern_util.h" @@ -65,9 +63,9 @@ static void slip_pre_exec(void *arg) { struct slip_pre_exec_data *data = arg; - if(data->stdin != -1) dup2(data->stdin, 0); + if(data->stdin >= 0) dup2(data->stdin, 0); dup2(data->stdout, 1); - if(data->close_me != -1) close(data->close_me); + if(data->close_me >= 0) os_close_file(data->close_me); } static int slip_tramp(char **argv, int fd) @@ -77,8 +75,8 @@ static int slip_tramp(char **argv, int fd) int status, pid, fds[2], err, output_len; err = os_pipe(fds, 1, 0); - if(err){ - printk("slip_tramp : pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("slip_tramp : pipe failed, err = %d\n", -err); return(err); } @@ -96,16 +94,18 @@ static int slip_tramp(char **argv, int fd) printk("slip_tramp : failed to allocate output " "buffer\n"); - close(fds[1]); + os_close_file(fds[1]); read_output(fds[0], output, output_len); if(output != NULL){ printk("%s", output); kfree(output); } - if(waitpid(pid, &status, 0) < 0) err = errno; + CATCH_EINTR(err = waitpid(pid, &status, 0)); + if(err < 0) + err = errno; else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ printk("'%s' didn't exit with status 0\n", argv[0]); - err = EINVAL; + err = -EINVAL; } } return(err); @@ -118,15 +118,17 @@ static int slip_open(void *data) char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, NULL }; - int sfd, mfd, disc, sencap, err; + int sfd, mfd, err; - if((mfd = get_pty()) < 0){ - printk("umn : Failed to open pty\n"); - return(-1); + mfd = get_pty(); + if(mfd < 0){ + printk("umn : Failed to open pty, err = %d\n", -mfd); + return(mfd); } - if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){ - printk("Couldn't open tty for slip line\n"); - return(-1); + sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); + if(sfd < 0){ + printk("Couldn't open tty for slip line, err = %d\n", -sfd); + return(sfd); } if(set_up_tty(sfd)) return(-1); pri->slave = sfd; @@ -138,28 +140,23 @@ static int slip_open(void *data) err = slip_tramp(argv, sfd); - if(err != 0){ - printk("slip_tramp failed - errno = %d\n", err); - return(-err); + if(err < 0){ + printk("slip_tramp failed - err = %d\n", -err); + return(err); } - if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){ - printk("SIOCGIFNAME failed, errno = %d\n", errno); - return(-errno); + err = os_get_ifname(pri->slave, pri->name); + if(err < 0){ + printk("get_ifname failed, err = %d\n", -err); + return(err); } iter_addresses(pri->dev, open_addr, pri->name); } else { - disc = N_SLIP; - if(ioctl(sfd, TIOCSETD, &disc) < 0){ - printk("Failed to set slip line discipline - " - "errno = %d\n", errno); - return(-errno); - } - sencap = 0; - if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){ - printk("Failed to set slip encapsulation - " - "errno = %d\n", errno); - return(-errno); + err = os_set_slip(sfd); + if(err < 0){ + printk("Failed to set slip discipline encapsulation - " + "err = %d\n", -err); + return(err); } } return(mfd); @@ -181,9 +178,9 @@ static void slip_close(int fd, void *data) err = slip_tramp(argv, -1); if(err != 0) - printk("slip_tramp failed - errno = %d\n", err); - close(fd); - close(pri->slave); + printk("slip_tramp failed - errno = %d\n", -err); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; } @@ -243,7 +240,7 @@ static void slip_add_addr(unsigned char *addr, unsigned char *netmask, { struct slip_data *pri = data; - if(pri->slave == -1) return; + if(pri->slave < 0) return; open_addr(addr, netmask, pri->name); } @@ -252,7 +249,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask, { struct slip_data *pri = data; - if(pri->slave == -1) return; + if(pri->slave < 0) return; close_addr(addr, netmask, pri->name); } diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index cbdbb65c3..c322515c7 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -4,8 +4,7 @@ #include #include #include -#include -#include +#include #include #include #include "user_util.h" @@ -48,15 +47,15 @@ static int slirp_tramp(char **argv, int fd) return(pid); } - + +/* XXX This is just a trivial wrapper around os_pipe */ static int slirp_datachan(int *mfd, int *sfd) { int fds[2], err; err = os_pipe(fds, 1, 1); - if(err){ - printk("slirp_datachan: Failed to open pipe, errno = %d\n", - -err); + if(err < 0){ + printk("slirp_datachan: Failed to open pipe, err = %d\n", -err); return(err); } @@ -77,7 +76,7 @@ static int slirp_open(void *data) pid = slirp_tramp(pri->argw.argv, sfd); if(pid < 0){ - printk("slirp_tramp failed - errno = %d\n", pid); + printk("slirp_tramp failed - errno = %d\n", -pid); os_close_file(sfd); os_close_file(mfd); return(pid); @@ -97,8 +96,8 @@ static void slirp_close(int fd, void *data) struct slirp_data *pri = data; int status,err; - close(fd); - close(pri->slave); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; @@ -114,13 +113,13 @@ static void slirp_close(int fd, void *data) } #endif - err = waitpid(pri->pid, &status, WNOHANG); - if(err<0) { + CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); + if(err < 0) { printk("slirp_close: waitpid returned %d\n", errno); return; } - if(err==0) { + if(err == 0) { printk("slirp_close: process %d has not exited\n"); return; } diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index 826a77c8c..af687e29a 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -10,6 +10,7 @@ #include "linux/major.h" #include "linux/mm.h" #include "linux/init.h" +#include "linux/console.h" #include "asm/termbits.h" #include "asm/irq.h" #include "line.h" @@ -53,8 +54,9 @@ static int ssl_remove(char *str); static struct line_driver driver = { .name = "UML serial line", - .devfs_name = "tts/%d", - .major = TTYAUX_MAJOR, + .device_name = "ttS", + .devfs_name = "tts/", + .major = TTY_MAJOR, .minor_start = 64, .type = TTY_DRIVER_TYPE_SERIAL, .subtype = 0, @@ -109,15 +111,15 @@ static void ssl_close(struct tty_struct *tty, struct file * filp) line_close(serial_lines, tty); } -static int ssl_write(struct tty_struct * tty, int from_user, +static int ssl_write(struct tty_struct * tty, const unsigned char *buf, int count) { - return(line_write(serial_lines, tty, from_user, buf, count)); + return(line_write(serial_lines, tty, buf, count)); } static void ssl_put_char(struct tty_struct *tty, unsigned char ch) { - line_write(serial_lines, tty, 0, &ch, sizeof(ch)); + line_write(serial_lines, tty, &ch, sizeof(ch)); } static void ssl_flush_chars(struct tty_struct *tty) @@ -149,6 +151,9 @@ static int ssl_ioctl(struct tty_struct *tty, struct file * file, case TCSETSW: case TCGETA: case TIOCMGET: + case TCSBRK: + case TCSBRKP: + case TIOCMSET: ret = -ENOIOCTLCMD; break; default: @@ -212,6 +217,37 @@ static struct tty_operations ssl_ops = { */ static int ssl_init_done = 0; +static void ssl_console_write(struct console *c, const char *string, + unsigned len) +{ + struct line *line = &serial_lines[c->index]; + if(ssl_init_done) + down(&line->sem); + console_write_chan(&line->chan_list, string, len); + if(ssl_init_done) + up(&line->sem); +} + +static struct tty_driver *ssl_console_device(struct console *c, int *index) +{ + *index = c->index; + return ssl_driver; +} + +static int ssl_console_setup(struct console *co, char *options) +{ + return(0); +} + +static struct console ssl_cons = { + name: "ttyS", + write: ssl_console_write, + device: ssl_console_device, + setup: ssl_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + int ssl_init(void) { char *new_title; @@ -227,17 +263,18 @@ int ssl_init(void) new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) opts.xterm_title = new_title; + register_console(&ssl_cons); ssl_init_done = 1; return(0); } -__initcall(ssl_init); +late_initcall(ssl_init); static int ssl_chan_setup(char *str) { - line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]), - str, 1); - return(1); + return(line_setup(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), + str, 1)); } __setup("ssl", ssl_chan_setup); diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 3ae795edf..e721e15d8 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -17,8 +17,8 @@ #include "linux/init.h" #include "linux/interrupt.h" #include "linux/slab.h" +#include "linux/hardirq.h" #include "asm/current.h" -#include "asm/hardirq.h" #include "asm/irq.h" #include "stdio_console.h" #include "line.h" @@ -83,7 +83,8 @@ static int con_remove(char *str); static struct line_driver driver = { .name = "UML console", - .devfs_name = "vc/%d", + .device_name = "tty", + .devfs_name = "vc/", .major = TTY_MAJOR, .minor_start = 0, .type = TTY_DRIVER_TYPE_CONSOLE, @@ -142,10 +143,10 @@ static void con_close(struct tty_struct *tty, struct file *filp) line_close(vts, tty); } -static int con_write(struct tty_struct *tty, int from_user, +static int con_write(struct tty_struct *tty, const unsigned char *buf, int count) { - return(line_write(vts, tty, from_user, buf, count)); + return(line_write(vts, tty, buf, count)); } static void set_termios(struct tty_struct *tty, struct termios * old) @@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_struct *tty) static int con_init_done = 0; +static struct tty_operations console_ops = { + .open = con_open, + .close = con_close, + .write = con_write, + .chars_in_buffer = chars_in_buffer, + .set_termios = set_termios, + .write_room = line_write_room, +}; + int stdio_init(void) { char *new_title; @@ -166,7 +176,8 @@ int stdio_init(void) printk(KERN_INFO "Initializing stdio console driver\n"); console_driver = line_register_devfs(&console_lines, &driver, - &console_ops, vts, sizeof(vts)/sizeof(vts[0])); + &console_ops, vts, + sizeof(vts)/sizeof(vts[0])); lines_init(vts, sizeof(vts)/sizeof(vts[0])); @@ -178,52 +189,53 @@ int stdio_init(void) return(0); } -__initcall(stdio_init); +late_initcall(stdio_init); -static void console_write(struct console *console, const char *string, +static void uml_console_write(struct console *console, const char *string, unsigned len) { - if(con_init_done) down(&vts[console->index].sem); - console_write_chan(&vts[console->index].chan_list, string, len); - if(con_init_done) up(&vts[console->index].sem); -} + struct line *line = &vts[console->index]; -static struct tty_operations console_ops = { - .open = con_open, - .close = con_close, - .write = con_write, - .chars_in_buffer = chars_in_buffer, - .set_termios = set_termios, - .write_room = line_write_room, -}; + if(con_init_done) + down(&line->sem); + console_write_chan(&line->chan_list, string, len); + if(con_init_done) + up(&line->sem); +} -static struct tty_driver *console_device(struct console *c, int *index) +static struct tty_driver *uml_console_device(struct console *c, int *index) { *index = c->index; return console_driver; } -static int console_setup(struct console *co, char *options) +static int uml_console_setup(struct console *co, char *options) { return(0); } -static struct console stdiocons = INIT_CONSOLE("tty", console_write, - console_device, console_setup, - CON_PRINTBUFFER); +static struct console stdiocons = { + name: "tty", + write: uml_console_write, + device: uml_console_device, + setup: uml_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; -static void __init stdio_console_init(void) +static int __init stdio_console_init(void) { INIT_LIST_HEAD(&vts[0].chan_list); list_add(&init_console_chan.list, &vts[0].chan_list); register_console(&stdiocons); + return(0); } + console_initcall(stdio_console_init); static int console_chan_setup(char *str) { - line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1); - return(1); + return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); } __setup("con", console_chan_setup); diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index e9eb9e362..dd008aa8f 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include "chan_user.h" @@ -30,7 +29,8 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts) } str++; - if((data = um_kmalloc(sizeof(*data))) == NULL) + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct tty_chan) { .dev = str, .raw = opts->raw }); @@ -41,13 +41,18 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts) int tty_open(int input, int output, int primary, void *d, char **dev_out) { struct tty_chan *data = d; - int fd; + int fd, err; fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); if(fd < 0) return(fd); if(data->raw){ - tcgetattr(fd, &data->tt); - raw(fd, 0); + CATCH_EINTR(err = tcgetattr(fd, &data->tt)); + if(err) + return(err); + + err = raw(fd); + if(err) + return(err); } *dev_out = data->dev; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0c3890b3e..53fba09ad 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -8,6 +8,13 @@ * old style ubd by setting UBD_SHIFT to 0 * 2002-09-27...2002-10-18 massive tinkering for 2.5 * partitions have changed in 2.5 + * 2003-01-29 more tinkering for 2.5.59-1 + * This should now address the sysfs problems and has + * the symlink for devfs to allow for booting with + * the common /dev/ubd/discX/... names rather than + * only /dev/ubdN/discN this version also has lots of + * clean ups preparing for ubd-many. + * James McMechan */ #define MAJOR_NR UBD_MAJOR @@ -40,9 +47,12 @@ #include "mconsole_kern.h" #include "init.h" #include "irq_user.h" +#include "irq_kern.h" #include "ubd_user.h" #include "2_5compat.h" #include "os.h" +#include "mem.h" +#include "mem_kern.h" static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED; static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; @@ -56,6 +66,10 @@ static int ubd_ioctl(struct inode * inode, struct file * file, #define MAX_DEV (8) +/* Changed in early boot */ +static int ubd_do_mmap = 0; +#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE + static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, .open = ubd_open, @@ -67,7 +81,7 @@ static struct block_device_operations ubd_blops = { static request_queue_t *ubd_queue; /* Protected by ubd_lock */ -static int fake_major = 0; +static int fake_major = MAJOR_NR; static struct gendisk *ubd_gendisk[MAX_DEV]; static struct gendisk *fake_gendisk[MAX_DEV]; @@ -96,13 +110,19 @@ struct cow { struct ubd { char *file; - int is_dir; int count; int fd; __u64 size; struct openflags boot_openflags; struct openflags openflags; + int no_cow; struct cow cow; + + int map_writes; + int map_reads; + int nomap_writes; + int nomap_reads; + int write_maps; }; #define DEFAULT_COW { \ @@ -115,21 +135,28 @@ struct ubd { #define DEFAULT_UBD { \ .file = NULL, \ - .is_dir = 0, \ .count = 0, \ .fd = -1, \ .size = -1, \ .boot_openflags = OPEN_FLAGS, \ .openflags = OPEN_FLAGS, \ + .no_cow = 0, \ .cow = DEFAULT_COW, \ + .map_writes = 0, \ + .map_reads = 0, \ + .nomap_writes = 0, \ + .nomap_reads = 0, \ + .write_maps = 0, \ } struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; static int ubd0_init(void) { - if(ubd_dev[0].file == NULL) - ubd_dev[0].file = "root_fs"; + struct ubd *dev = &ubd_dev[0]; + + if(dev->file == NULL) + dev->file = "root_fs"; return(0); } @@ -196,19 +223,46 @@ __uml_help(fake_ide_setup, " Create ide0 entries that map onto ubd devices.\n\n" ); +static int parse_unit(char **ptr) +{ + char *str = *ptr, *end; + int n = -1; + + if(isdigit(*str)) { + n = simple_strtoul(str, &end, 0); + if(end == str) + return(-1); + *ptr = end; + } + else if (('a' <= *str) && (*str <= 'h')) { + n = *str - 'a'; + str++; + *ptr = str; + } + return(n); +} + static int ubd_setup_common(char *str, int *index_out) { + struct ubd *dev; struct openflags flags = global_openflags; char *backing_file; int n, err; if(index_out) *index_out = -1; - n = *str++; + n = *str; if(n == '='){ - static int fake_major_allowed = 1; char *end; int major; + str++; + if(!strcmp(str, "mmap")){ + CHOOSE_MODE(printk("mmap not supported by the ubd " + "driver in tt mode\n"), + ubd_do_mmap = 1); + return(0); + } + if(!strcmp(str, "sync")){ global_openflags.s = 1; return(0); @@ -220,20 +274,14 @@ static int ubd_setup_common(char *str, int *index_out) return(1); } - if(!fake_major_allowed){ - printk(KERN_ERR "Can't assign a fake major twice\n"); - return(1); - } - err = 1; spin_lock(&ubd_lock); - if(!fake_major_allowed){ + if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; } fake_major = major; - fake_major_allowed = 0; printk(KERN_INFO "Setting extra ubd major number to %d\n", major); @@ -243,25 +291,23 @@ static int ubd_setup_common(char *str, int *index_out) return(err); } - if(n < '0'){ - printk(KERN_ERR "ubd_setup : index out of range\n"); } - - if((n >= '0') && (n <= '9')) n -= '0'; - else if((n >= 'a') && (n <= 'z')) n -= 'a'; - else { - printk(KERN_ERR "ubd_setup : device syntax invalid\n"); + n = parse_unit(&str); + if(n < 0){ + printk(KERN_ERR "ubd_setup : couldn't parse unit number " + "'%s'\n", str); return(1); } if(n >= MAX_DEV){ - printk(KERN_ERR "ubd_setup : index out of range " - "(%d devices)\n", MAX_DEV); + printk(KERN_ERR "ubd_setup : index %d out of range " + "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1); return(1); } err = 1; spin_lock(&ubd_lock); - if(ubd_dev[n].file != NULL){ + dev = &ubd_dev[n]; + if(dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out2; } @@ -276,6 +322,11 @@ static int ubd_setup_common(char *str, int *index_out) flags.s = 1; str++; } + if (*str == 'd'){ + dev->no_cow = 1; + str++; + } + if(*str++ != '='){ printk(KERN_ERR "ubd_setup : Expected '='\n"); goto out2; @@ -284,14 +335,17 @@ static int ubd_setup_common(char *str, int *index_out) err = 0; backing_file = strchr(str, ','); if(backing_file){ - *backing_file = '\0'; - backing_file++; - } - ubd_dev[n].file = str; - if(ubd_is_dir(ubd_dev[n].file)) - ubd_dev[n].is_dir = 1; - ubd_dev[n].cow.file = backing_file; - ubd_dev[n].boot_openflags = flags; + if(dev->no_cow) + printk(KERN_ERR "Can't specify both 'd' and a " + "cow file\n"); + else { + *backing_file = '\0'; + backing_file++; + } + } + dev->file = str; + dev->cow.file = backing_file; + dev->boot_openflags = flags; out2: spin_unlock(&ubd_lock); return(err); @@ -321,8 +375,7 @@ __uml_help(ubd_setup, static int fakehd_set = 0; static int fakehd(char *str) { - printk(KERN_INFO - "fakehd : Changing ubd name to \"hd\".\n"); + printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n"); fakehd_set = 1; return 1; } @@ -343,14 +396,13 @@ int thread_fd = -1; */ int intr_count = 0; -static void ubd_finish(struct request *req, int error) +/* call ubd_finish if you need to serialize */ +static void __ubd_finish(struct request *req, int error) { int nsect; if(error){ - spin_lock(&ubd_io_lock); end_request(req, 0); - spin_unlock(&ubd_io_lock); return; } nsect = req->current_nr_sectors; @@ -359,41 +411,57 @@ static void ubd_finish(struct request *req, int error) req->errors = 0; req->nr_sectors -= nsect; req->current_nr_sectors = 0; - spin_lock(&ubd_io_lock); end_request(req, 1); +} + +static inline void ubd_finish(struct request *req, int error) +{ + spin_lock(&ubd_io_lock); + __ubd_finish(req, error); spin_unlock(&ubd_io_lock); } +/* Called without ubd_io_lock held */ static void ubd_handler(void) { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); - int n; + int n, err; do_ubd = NULL; intr_count++; n = read_ubd_fs(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " - "errno = %d\n", os_getpid(), -n); + "err = %d\n", os_getpid(), -n); spin_lock(&ubd_io_lock); end_request(rq, 0); spin_unlock(&ubd_io_lock); return; } - if((req.offset != ((__u64) (rq->sector)) << 9) || - (req.length != (rq->current_nr_sectors) << 9)) + if((req.op != UBD_MMAP) && + ((req.offset != ((__u64) (rq->sector)) << 9) || + (req.length != (rq->current_nr_sectors) << 9))) panic("I/O op mismatch"); + if(req.map_fd != -1){ + err = physmem_subst_mapping(req.buffer, req.map_fd, + req.map_offset, 1); + if(err) + printk("ubd_handler - physmem_subst_mapping failed, " + "err = %d\n", -err); + } + ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); do_ubd_request(ubd_queue); } -static void ubd_intr(int irq, void *dev, struct pt_regs *unused) +static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) { ubd_handler(); + return(IRQ_HANDLED); } /* Only changed by ubd_init, which is an initcall. */ @@ -417,10 +485,14 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out) static void ubd_close(struct ubd *dev) { + if(ubd_do_mmap) + physmem_forget_descriptor(dev->fd); os_close_file(dev->fd); if(dev->cow.file == NULL) return; + if(ubd_do_mmap) + physmem_forget_descriptor(dev->cow.fd); os_close_file(dev->cow.fd); vfree(dev->cow.bitmap); dev->cow.bitmap = NULL; @@ -429,18 +501,20 @@ static void ubd_close(struct ubd *dev) static int ubd_open_dev(struct ubd *dev) { struct openflags flags; - int err, n, create_cow, *create_ptr; + char **back_ptr; + int err, create_cow, *create_ptr; + dev->openflags = dev->boot_openflags; create_cow = 0; create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; - dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file, + back_ptr = dev->no_cow ? NULL : &dev->cow.file; + dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr, &dev->cow.bitmap_offset, &dev->cow.bitmap_len, &dev->cow.data_offset, create_ptr); if((dev->fd == -ENOENT) && create_cow){ - n = dev - ubd_dev; dev->fd = create_cow_file(dev->file, dev->cow.file, - dev->openflags, 1 << 9, + dev->openflags, 1 << 9, PAGE_SIZE, &dev->cow.bitmap_offset, &dev->cow.bitmap_len, &dev->cow.data_offset); @@ -455,13 +529,17 @@ static int ubd_open_dev(struct ubd *dev) if(dev->cow.file != NULL){ err = -ENOMEM; dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); - if(dev->cow.bitmap == NULL) goto error; + if(dev->cow.bitmap == NULL){ + printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); + goto error; + } flush_tlb_kernel_vm(); err = read_cow_bitmap(dev->fd, dev->cow.bitmap, dev->cow.bitmap_offset, dev->cow.bitmap_len); - if(err) goto error; + if(err < 0) + goto error; flags = dev->openflags; flags.w = 0; @@ -481,17 +559,31 @@ static int ubd_new_disk(int major, u64 size, int unit, { struct gendisk *disk; + char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")]; + int err; disk = alloc_disk(1 << UBD_SHIFT); - if (!disk) - return -ENOMEM; + if(disk == NULL) + return(-ENOMEM); disk->major = major; disk->first_minor = unit << UBD_SHIFT; disk->fops = &ubd_blops; set_capacity(disk, size / 512); - sprintf(disk->disk_name, "ubd"); - sprintf(disk->devfs_name, "ubd/disc%d", unit); + if(major == MAJOR_NR){ + sprintf(disk->disk_name, "ubd%c", 'a' + unit); + sprintf(disk->devfs_name, "ubd/disc%d", unit); + sprintf(from, "ubd/%d", unit); + sprintf(to, "disc%d/disc", unit); + err = devfs_mk_symlink(from, to); + if(err) + printk("ubd_new_disk failed to make link from %s to " + "%s, error = %d\n", from, to, err); + } + else { + sprintf(disk->disk_name, "ubd_fake%d", unit); + sprintf(disk->devfs_name, "ubd_fake/disc%d", unit); + } disk->private_data = &ubd_dev[unit]; disk->queue = ubd_queue; @@ -506,24 +598,21 @@ static int ubd_add(int n) struct ubd *dev = &ubd_dev[n]; int err; - if(dev->is_dir) - return(-EISDIR); - - if (!dev->file) + if(dev->file == NULL) return(-ENODEV); if (ubd_open_dev(dev)) return(-ENODEV); err = ubd_file_size(dev, &dev->size); - if(err) + if(err < 0) return(err); err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); if(err) return(err); - if(fake_major) + if(fake_major != MAJOR_NR) ubd_new_disk(fake_major, dev->size, n, &fake_gendisk[n]); @@ -561,42 +650,42 @@ static int ubd_config(char *str) return(err); } -static int ubd_get_config(char *dev, char *str, int size, char **error_out) +static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *ubd; + struct ubd *dev; char *end; - int major, n = 0; + int n, len = 0; - major = simple_strtoul(dev, &end, 0); - if((*end != '\0') || (end == dev)){ - *error_out = "ubd_get_config : didn't parse major number"; + n = simple_strtoul(name, &end, 0); + if((*end != '\0') || (end == name)){ + *error_out = "ubd_get_config : didn't parse device number"; return(-1); } - if((major >= MAX_DEV) || (major < 0)){ - *error_out = "ubd_get_config : major number out of range"; + if((n >= MAX_DEV) || (n < 0)){ + *error_out = "ubd_get_config : device number out of range"; return(-1); } - ubd = &ubd_dev[major]; + dev = &ubd_dev[n]; spin_lock(&ubd_lock); - if(ubd->file == NULL){ - CONFIG_CHUNK(str, size, n, "", 1); + if(dev->file == NULL){ + CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, n, ubd->file, 0); + CONFIG_CHUNK(str, size, len, dev->file, 0); - if(ubd->cow.file != NULL){ - CONFIG_CHUNK(str, size, n, ",", 0); - CONFIG_CHUNK(str, size, n, ubd->cow.file, 1); + if(dev->cow.file != NULL){ + CONFIG_CHUNK(str, size, len, ",", 0); + CONFIG_CHUNK(str, size, len, dev->cow.file, 1); } - else CONFIG_CHUNK(str, size, n, "", 1); + else CONFIG_CHUNK(str, size, len, "", 1); out: spin_unlock(&ubd_lock); - return(n); + return(len); } static int ubd_remove(char *str) @@ -604,11 +693,9 @@ static int ubd_remove(char *str) struct ubd *dev; int n, err = -ENODEV; - if(!isdigit(*str)) - return(err); /* it should be a number 0-7/a-h */ + n = parse_unit(&str); - n = *str - '0'; - if(n >= MAX_DEV) + if((n < 0) || (n >= MAX_DEV)) return(err); dev = &ubd_dev[n]; @@ -667,9 +754,7 @@ int ubd_init(void) return -1; } - elevator_init(ubd_queue, &elevator_noop); - - if (fake_major != 0) { + if (fake_major != MAJOR_NR) { char name[sizeof("ubd_nnn\0")]; snprintf(name, sizeof(name), "ubd_%d", fake_major); @@ -688,9 +773,11 @@ int ubd_driver_init(void){ unsigned long stack; int err; + /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/ if(global_openflags.s){ - printk(KERN_INFO "ubd : Synchronous mode\n"); - return(0); + printk(KERN_INFO "ubd: Synchronous mode\n"); + /* Letting ubd=sync be like using ubd#s= instead of ubd#= is + * enough. So use anyway the io thread. */ } stack = alloc_stack(0, 0); io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), @@ -699,12 +786,13 @@ int ubd_driver_init(void){ printk(KERN_ERR "ubd : Failed to start I/O thread (errno = %d) - " "falling back to synchronous I/O\n", -io_pid); + io_pid = -1; return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, SA_INTERRUPT, "ubd", ubd_dev); - if(err != 0) printk(KERN_ERR - "um_request_irq failed - errno = %d\n", -err); + if(err != 0) + printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return(err); } @@ -714,15 +802,9 @@ static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ubd *dev = disk->private_data; - int err = -EISDIR; - - if(dev->is_dir == 1) - goto out; + int err = 0; - err = 0; if(dev->count == 0){ - dev->openflags = dev->boot_openflags; - err = ubd_open_dev(dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", @@ -749,91 +831,211 @@ static int ubd_release(struct inode * inode, struct file * file) return(0); } -void cowify_req(struct io_thread_req *req, struct ubd *dev) +static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, + __u64 *cow_offset, unsigned long *bitmap, + __u64 bitmap_offset, unsigned long *bitmap_words, + __u64 bitmap_len) +{ + __u64 sector = io_offset >> 9; + int i, update_bitmap = 0; + + for(i = 0; i < length >> 9; i++){ + if(cow_mask != NULL) + ubd_set_bit(i, (unsigned char *) cow_mask); + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) + continue; + + update_bitmap = 1; + ubd_set_bit(sector + i, (unsigned char *) bitmap); + } + + if(!update_bitmap) + return; + + *cow_offset = sector / (sizeof(unsigned long) * 8); + + /* This takes care of the case where we're exactly at the end of the + * device, and *cow_offset + 1 is off the end. So, just back it up + * by one word. Thanks to Lynn Kerby for the fix and James McMechan + * for the original diagnosis. + */ + if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / + sizeof(unsigned long) - 1)) + (*cow_offset)--; + + bitmap_words[0] = bitmap[*cow_offset]; + bitmap_words[1] = bitmap[*cow_offset + 1]; + + *cow_offset *= sizeof(unsigned long); + *cow_offset += bitmap_offset; +} + +static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, + __u64 bitmap_offset, __u64 bitmap_len) { - int i, update_bitmap, sector = req->offset >> 9; + __u64 sector = req->offset >> 9; + int i; if(req->length > (sizeof(req->sector_mask) * 8) << 9) panic("Operation too long"); + if(req->op == UBD_READ) { for(i = 0; i < req->length >> 9; i++){ - if(ubd_test_bit(sector + i, (unsigned char *) - dev->cow.bitmap)){ + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) ubd_set_bit(i, (unsigned char *) &req->sector_mask); - } } - } - else { - update_bitmap = 0; - for(i = 0; i < req->length >> 9; i++){ - ubd_set_bit(i, (unsigned char *) - &req->sector_mask); - if(!ubd_test_bit(sector + i, (unsigned char *) - dev->cow.bitmap)) - update_bitmap = 1; - ubd_set_bit(sector + i, (unsigned char *) - dev->cow.bitmap); - } - if(update_bitmap){ - req->cow_offset = sector / (sizeof(unsigned long) * 8); - req->bitmap_words[0] = - dev->cow.bitmap[req->cow_offset]; - req->bitmap_words[1] = - dev->cow.bitmap[req->cow_offset + 1]; - req->cow_offset *= sizeof(unsigned long); - req->cow_offset += dev->cow.bitmap_offset; + } + else cowify_bitmap(req->offset, req->length, &req->sector_mask, + &req->cow_offset, bitmap, bitmap_offset, + req->bitmap_words, bitmap_len); +} + +static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) +{ + __u64 sector; + unsigned char *bitmap; + int bit, i; + + /* mmap must have been requested on the command line */ + if(!ubd_do_mmap) + return(-1); + + /* The buffer must be page aligned */ + if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0) + return(-1); + + /* The request must be a page long */ + if((req->current_nr_sectors << 9) != PAGE_SIZE) + return(-1); + + if(dev->cow.file == NULL) + return(dev->fd); + + sector = offset >> 9; + bitmap = (unsigned char *) dev->cow.bitmap; + bit = ubd_test_bit(sector, bitmap); + + for(i = 1; i < req->current_nr_sectors; i++){ + if(ubd_test_bit(sector + i, bitmap) != bit) + return(-1); + } + + if(bit || (rq_data_dir(req) == WRITE)) + offset += dev->cow.data_offset; + + /* The data on disk must be page aligned */ + if((offset % UBD_MMAP_BLOCK_SIZE) != 0) + return(-1); + + return(bit ? dev->fd : dev->cow.fd); +} + +static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, + struct request *req, + struct io_thread_req *io_req) +{ + int err; + + if(rq_data_dir(req) == WRITE){ + /* Writes are almost no-ops since the new data is already in the + * host page cache + */ + dev->map_writes++; + if(dev->cow.file != NULL) + cowify_bitmap(io_req->offset, io_req->length, + &io_req->sector_mask, &io_req->cow_offset, + dev->cow.bitmap, dev->cow.bitmap_offset, + io_req->bitmap_words, + dev->cow.bitmap_len); + } + else { + int w; + + if((dev->cow.file != NULL) && (fd == dev->cow.fd)) + w = 0; + else w = dev->openflags.w; + + if((dev->cow.file != NULL) && (fd == dev->fd)) + offset += dev->cow.data_offset; + + err = physmem_subst_mapping(req->buffer, fd, offset, w); + if(err){ + printk("physmem_subst_mapping failed, err = %d\n", + -err); + return(1); } + dev->map_reads++; } + io_req->op = UBD_MMAP; + io_req->buffer = req->buffer; + return(0); } +/* Called with ubd_io_lock held */ static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; struct ubd *dev = disk->private_data; - __u64 block; - int nsect; + __u64 offset; + int len, fd; if(req->rq_status == RQ_INACTIVE) return(1); - if(dev->is_dir){ - strcpy(req->buffer, "HOSTFS:"); - strcat(req->buffer, dev->file); - spin_lock(&ubd_io_lock); - end_request(req, 1); - spin_unlock(&ubd_io_lock); - return(1); - } - if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); - spin_lock(&ubd_io_lock); end_request(req, 0); - spin_unlock(&ubd_io_lock); return(1); } - block = req->sector; - nsect = req->current_nr_sectors; + offset = ((__u64) req->sector) << 9; + len = req->current_nr_sectors << 9; - io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE; io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; io_req->fds[1] = dev->fd; + io_req->map_fd = -1; + io_req->cow_offset = -1; + io_req->offset = offset; + io_req->length = len; + io_req->error = 0; + io_req->sector_mask = 0; + + fd = mmap_fd(req, dev, io_req->offset); + if(fd > 0){ + /* If mmapping is otherwise OK, but the first access to the + * page is a write, then it's not mapped in yet. So we have + * to write the data to disk first, then we can map the disk + * page in and continue normally from there. + */ + if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){ + io_req->map_fd = dev->fd; + io_req->map_offset = io_req->offset + + dev->cow.data_offset; + dev->write_maps++; + } + else return(prepare_mmap_request(dev, fd, io_req->offset, req, + io_req)); + } + + if(rq_data_dir(req) == READ) + dev->nomap_reads++; + else dev->nomap_writes++; + + io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; io_req->offsets[1] = dev->cow.data_offset; - io_req->offset = ((__u64) block) << 9; - io_req->length = nsect << 9; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - io_req->sector_mask = 0; - io_req->cow_offset = -1; - io_req->error = 0; - if(dev->cow.file != NULL) cowify_req(io_req, dev); + if(dev->cow.file != NULL) + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); + return(0); } +/* Called with ubd_io_lock held */ static void do_ubd_request(request_queue_t *q) { struct io_thread_req io_req; @@ -841,18 +1043,17 @@ static void do_ubd_request(request_queue_t *q) int err, n; if(thread_fd == -1){ - while(!list_empty(&q->queue_head)){ - req = elv_next_request(q); + while((req = elv_next_request(q)) != NULL){ err = prepare_request(req, &io_req); if(!err){ do_io(&io_req); - ubd_finish(req, io_req.error); + __ubd_finish(req, io_req.error); } } } else { - if(do_ubd || list_empty(&q->queue_head)) return; - req = elv_next_request(q); + if(do_ubd || (req = elv_next_request(q)) == NULL) + return; err = prepare_request(req, &io_req); if(!err){ do_ubd = ubd_handler; @@ -870,7 +1071,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file, { struct hd_geometry *loc = (struct hd_geometry *) arg; struct ubd *dev = inode->i_bdev->bd_disk->private_data; - int err; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -885,35 +1085,9 @@ static int ubd_ioctl(struct inode * inode, struct file * file, g.heads = 128; g.sectors = 32; g.cylinders = dev->size / (128 * 32 * 512); - g.start = 2; + g.start = get_start_sect(inode->i_bdev); return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); - case HDIO_SET_UNMASKINTR: - if(!capable(CAP_SYS_ADMIN)) return(-EACCES); - if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev)) - return(-EINVAL); - return(0); - - case HDIO_GET_UNMASKINTR: - if(!arg) return(-EINVAL); - err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if(err) - return(err); - return(0); - - case HDIO_GET_MULTCOUNT: - if(!arg) return(-EINVAL); - err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if(err) - return(err); - return(0); - - case HDIO_SET_MULTCOUNT: - if(!capable(CAP_SYS_ADMIN)) return(-EACCES); - if(inode->i_bdev->bd_contains != inode->i_bdev) - return(-EINVAL); - return(0); - case HDIO_GET_IDENTITY: ubd_id.cyls = dev->size / (128 * 32 * 512); if(copy_to_user((char *) arg, (char *) &ubd_id, @@ -935,6 +1109,142 @@ static int ubd_ioctl(struct inode * inode, struct file * file, return(-EINVAL); } +static int ubd_check_remapped(int fd, unsigned long address, int is_write, + __u64 offset) +{ + __u64 bitmap_offset; + unsigned long new_bitmap[2]; + int i, err, n; + + /* If it's not a write access, we can't do anything about it */ + if(!is_write) + return(0); + + /* We have a write */ + for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){ + struct ubd *dev = &ubd_dev[i]; + + if((dev->fd != fd) && (dev->cow.fd != fd)) + continue; + + /* It's a write to a ubd device */ + + if(!dev->openflags.w){ + /* It's a write access on a read-only device - probably + * shouldn't happen. If the kernel is trying to change + * something with no intention of writing it back out, + * then this message will clue us in that this needs + * fixing + */ + printk("Write access to mapped page from readonly ubd " + "device %d\n", i); + return(0); + } + + /* It's a write to a writeable ubd device - it must be COWed + * because, otherwise, the page would have been mapped in + * writeable + */ + + if(!dev->cow.file) + panic("Write fault on writeable non-COW ubd device %d", + i); + + /* It should also be an access to the backing file since the + * COW pages should be mapped in read-write + */ + + if(fd == dev->fd) + panic("Write fault on a backing page of ubd " + "device %d\n", i); + + /* So, we do the write, copying the backing data to the COW + * file... + */ + + err = os_seek_file(dev->fd, offset + dev->cow.data_offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of ubd " + "device %d, err = %d", + offset + dev->cow.data_offset, i, -err); + + n = os_write_file(dev->fd, (void *) address, PAGE_SIZE); + if(n != PAGE_SIZE) + panic("Couldn't copy data to COW file of ubd " + "device %d, err = %d", i, -n); + + /* ... updating the COW bitmap... */ + + cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, + dev->cow.bitmap, dev->cow.bitmap_offset, + new_bitmap, dev->cow.bitmap_len); + + err = os_seek_file(dev->fd, bitmap_offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of ubd " + "device %d, err = %d", bitmap_offset, i, -err); + + n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap)); + if(n != sizeof(new_bitmap)) + panic("Couldn't update bitmap of ubd device %d, " + "err = %d", i, -n); + + /* Maybe we can map the COW page in, and maybe we can't. If + * it is a pre-V3 COW file, we can't, since the alignment will + * be wrong. If it is a V3 or later COW file which has been + * moved to a system with a larger page size, then maybe we + * can't, depending on the exact location of the page. + */ + + offset += dev->cow.data_offset; + + /* Remove the remapping, putting the original anonymous page + * back. If the COW file can be mapped in, that is done. + * Otherwise, the COW page is read in. + */ + + if(!physmem_remove_mapping((void *) address)) + panic("Address 0x%lx not remapped by ubd device %d", + address, i); + if((offset % UBD_MMAP_BLOCK_SIZE) == 0) + physmem_subst_mapping((void *) address, dev->fd, + offset, 1); + else { + err = os_seek_file(dev->fd, offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of " + "ubd device %d, err = %d", offset, i, + -err); + + n = os_read_file(dev->fd, (void *) address, PAGE_SIZE); + if(n != PAGE_SIZE) + panic("Failed to read page from offset %llx of " + "COW file of ubd device %d, err = %d", + offset, i, -n); + } + + return(1); + } + + /* It's not a write on a ubd device */ + return(0); +} + +static struct remapper ubd_remapper = { + .list = LIST_HEAD_INIT(ubd_remapper.list), + .proc = ubd_check_remapped, +}; + +static int ubd_remapper_setup(void) +{ + if(ubd_do_mmap) + register_remapper(&ubd_remapper); + + return(0); +} + +__initcall(ubd_remapper_setup); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index 93b6f3e90..882d2f7c1 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -11,11 +11,8 @@ #include #include #include -#include #include -#include #include -#include #include #include #include "asm/types.h" @@ -24,146 +21,30 @@ #include "user.h" #include "ubd_user.h" #include "os.h" +#include "cow.h" #include #include -#if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(x) (x) -# define htonll(x) (x) -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define ntohll(x) bswap_64(x) -# define htonll(x) bswap_64(x) -#else -#error "__BYTE_ORDER not defined" -#endif - -#define PATH_LEN_V1 256 - -struct cow_header_v1 { - int magic; - int version; - char backing_file[PATH_LEN_V1]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -#define PATH_LEN_V2 MAXPATHLEN - -struct cow_header_v2 { - unsigned long magic; - unsigned long version; - char backing_file[PATH_LEN_V2]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -union cow_header { - struct cow_header_v1 v1; - struct cow_header_v2 v2; -}; - -#define COW_MAGIC 0x4f4f4f4d /* MOOO */ -#define COW_VERSION 2 - -static void sizes(__u64 size, int sectorsize, int bitmap_offset, - unsigned long *bitmap_len_out, int *data_offset_out) -{ - *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); - - *data_offset_out = bitmap_offset + *bitmap_len_out; - *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize; - *data_offset_out *= sectorsize; -} - -static int read_cow_header(int fd, int *magic_out, char **backing_file_out, - time_t *mtime_out, __u64 *size_out, - int *sectorsize_out, int *bitmap_offset_out) -{ - union cow_header *header; - char *file; - int err, n; - unsigned long version, magic; - - header = um_kmalloc(sizeof(*header)); - if(header == NULL){ - printk("read_cow_header - Failed to allocate header\n"); - return(-ENOMEM); - } - err = -EINVAL; - n = read(fd, header, sizeof(*header)); - if(n < offsetof(typeof(header->v1), backing_file)){ - printk("read_cow_header - short header\n"); - goto out; - } - - magic = header->v1.magic; - if(magic == COW_MAGIC) { - version = header->v1.version; - } - else if(magic == ntohl(COW_MAGIC)){ - version = ntohl(header->v1.version); - } - else goto out; - - *magic_out = COW_MAGIC; - - if(version == 1){ - if(n < sizeof(header->v1)){ - printk("read_cow_header - failed to read V1 header\n"); - goto out; - } - *mtime_out = header->v1.mtime; - *size_out = header->v1.size; - *sectorsize_out = header->v1.sectorsize; - *bitmap_offset_out = sizeof(header->v1); - file = header->v1.backing_file; - } - else if(version == 2){ - if(n < sizeof(header->v2)){ - printk("read_cow_header - failed to read V2 header\n"); - goto out; - } - *mtime_out = ntohl(header->v2.mtime); - *size_out = ntohll(header->v2.size); - *sectorsize_out = ntohl(header->v2.sectorsize); - *bitmap_offset_out = sizeof(header->v2); - file = header->v2.backing_file; - } - else { - printk("read_cow_header - invalid COW version\n"); - goto out; - } - err = -ENOMEM; - *backing_file_out = uml_strdup(file); - if(*backing_file_out == NULL){ - printk("read_cow_header - failed to allocate backing file\n"); - goto out; - } - err = 0; - out: - kfree(header); - return(err); -} static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) { - struct stat buf1, buf2; + struct uml_stat buf1, buf2; + int err; if(from_cmdline == NULL) return(1); if(!strcmp(from_cmdline, from_cow)) return(1); - if(stat(from_cmdline, &buf1) < 0){ - printk("Couldn't stat '%s', errno = %d\n", from_cmdline, - errno); + err = os_stat_file(from_cmdline, &buf1); + if(err < 0){ + printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); return(1); } - if(stat(from_cow, &buf2) < 0){ - printk("Couldn't stat '%s', errno = %d\n", from_cow, errno); + err = os_stat_file(from_cow, &buf2); + if(err < 0){ + printk("Couldn't stat '%s', err = %d\n", from_cow, -err); return(1); } - if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino)) + if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) return(1); printk("Backing file mismatch - \"%s\" requested,\n" @@ -174,20 +55,21 @@ static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) static int backing_file_mismatch(char *file, __u64 size, time_t mtime) { - struct stat64 buf; + unsigned long modtime; long long actual; int err; - if(stat64(file, &buf) < 0){ - printk("Failed to stat backing file \"%s\", errno = %d\n", - file, errno); - return(-errno); + err = os_file_modtime(file, &modtime); + if(err < 0){ + printk("Failed to get modification time of backing file " + "\"%s\", err = %d\n", file, -err); + return(err); } err = os_file_size(file, &actual); - if(err){ + if(err < 0){ printk("Failed to get size of backing file \"%s\", " - "errno = %d\n", file, -err); + "err = %d\n", file, -err); return(err); } @@ -196,9 +78,9 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime) "file\n", size, actual); return(-EINVAL); } - if(buf.st_mtime != mtime){ + if(modtime != mtime){ printk("mtime mismatch (%ld vs %ld) of COW header vs backing " - "file\n", mtime, buf.st_mtime); + "file\n", mtime, modtime); return(-EINVAL); } return(0); @@ -209,124 +91,16 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len) int err; err = os_seek_file(fd, offset); - if(err != 0) return(-errno); - err = read(fd, buf, len); - if(err < 0) return(-errno); - return(0); -} + if(err < 0) + return(err); -static int absolutize(char *to, int size, char *from) -{ - char save_cwd[256], *slash; - int remaining; + err = os_read_file(fd, buf, len); + if(err < 0) + return(err); - if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { - printk("absolutize : unable to get cwd - errno = %d\n", errno); - return(-1); - } - slash = strrchr(from, '/'); - if(slash != NULL){ - *slash = '\0'; - if(chdir(from)){ - *slash = '/'; - printk("absolutize : Can't cd to '%s' - errno = %d\n", - from, errno); - return(-1); - } - *slash = '/'; - if(getcwd(to, size) == NULL){ - printk("absolutize : unable to get cwd of '%s' - " - "errno = %d\n", from, errno); - return(-1); - } - remaining = size - strlen(to); - if(strlen(slash) + 1 > remaining){ - printk("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcat(to, slash); - } - else { - if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ - printk("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcpy(to, save_cwd); - strcat(to, "/"); - strcat(to, from); - } - chdir(save_cwd); return(0); } -static int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, long long *size) -{ - struct cow_header_v2 *header; - struct stat64 buf; - int err; - - err = os_seek_file(fd, 0); - if(err != 0){ - printk("write_cow_header - lseek failed, errno = %d\n", errno); - return(-errno); - } - - err = -ENOMEM; - header = um_kmalloc(sizeof(*header)); - if(header == NULL){ - printk("Failed to allocate COW V2 header\n"); - goto out; - } - header->magic = htonl(COW_MAGIC); - header->version = htonl(COW_VERSION); - - err = -EINVAL; - if(strlen(backing_file) > sizeof(header->backing_file) - 1){ - printk("Backing file name \"%s\" is too long - names are " - "limited to %d characters\n", backing_file, - sizeof(header->backing_file) - 1); - goto out_free; - } - - if(absolutize(header->backing_file, sizeof(header->backing_file), - backing_file)) - goto out_free; - - err = stat64(header->backing_file, &buf); - if(err < 0){ - printk("Stat of backing file '%s' failed, errno = %d\n", - header->backing_file, errno); - err = -errno; - goto out_free; - } - - err = os_file_size(header->backing_file, size); - if(err){ - printk("Couldn't get size of backing file '%s', errno = %d\n", - header->backing_file, -*size); - goto out_free; - } - - header->mtime = htonl(buf.st_mtime); - header->size = htonll(*size); - header->sectorsize = htonl(sectorsize); - - err = write(fd, header, sizeof(*header)); - if(err != sizeof(*header)){ - printk("Write of header to new COW file '%s' failed, " - "errno = %d\n", cow_file, errno); - goto out_free; - } - err = 0; - out_free: - kfree(header); - out: - return(err); -} - int open_ubd_file(char *file, struct openflags *openflags, char **backing_file_out, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out, @@ -334,26 +108,36 @@ int open_ubd_file(char *file, struct openflags *openflags, { time_t mtime; __u64 size; + __u32 version, align; char *backing_file; - int fd, err, sectorsize, magic, same, mode = 0644; + int fd, err, sectorsize, same, mode = 0644; - if((fd = os_open_file(file, *openflags, mode)) < 0){ + fd = os_open_file(file, *openflags, mode); + if(fd < 0){ if((fd == -ENOENT) && (create_cow_out != NULL)) *create_cow_out = 1; if(!openflags->w || ((errno != EROFS) && (errno != EACCES))) return(-errno); openflags->w = 0; - if((fd = os_open_file(file, *openflags, mode)) < 0) + fd = os_open_file(file, *openflags, mode); + if(fd < 0) return(fd); } + + err = os_lock_file(fd, openflags->w); + if(err < 0){ + printk("Failed to lock '%s', err = %d\n", file, -err); + goto out_close; + } + if(backing_file_out == NULL) return(fd); - err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, - §orsize, bitmap_offset_out); + err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, + &size, §orsize, &align, bitmap_offset_out); if(err && (*backing_file_out != NULL)){ printk("Failed to read COW header from COW file \"%s\", " - "errno = %d\n", file, err); - goto error; + "errno = %d\n", file, -err); + goto out_close; } if(err) return(fd); @@ -363,36 +147,33 @@ int open_ubd_file(char *file, struct openflags *openflags, if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ printk("Switching backing file to '%s'\n", *backing_file_out); - err = write_cow_header(file, fd, *backing_file_out, - sectorsize, &size); + err = write_cow_header(file, fd, *backing_file_out, + sectorsize, align, &size); if(err){ - printk("Switch failed, errno = %d\n", err); + printk("Switch failed, errno = %d\n", -err); return(err); } } else { *backing_file_out = backing_file; err = backing_file_mismatch(*backing_file_out, size, mtime); - if(err) goto error; + if(err) goto out_close; } - sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, - data_offset_out); + cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, + bitmap_len_out, data_offset_out); return(fd); - error: - close(fd); + out_close: + os_close_file(fd); return(err); } int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, - int sectorsize, int *bitmap_offset_out, + int sectorsize, int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out) { - __u64 blocks; - long zero; - int err, fd, i; - long long size; + int err, fd; flags.c = 1; fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); @@ -403,57 +184,49 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, goto out; } - err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size); - if(err) goto out_close; - - blocks = (size + sectorsize - 1) / sectorsize; - blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8); - zero = 0; - for(i = 0; i < blocks; i++){ - err = write(fd, &zero, sizeof(zero)); - if(err != sizeof(zero)){ - printk("Write of bitmap to new COW file '%s' failed, " - "errno = %d\n", cow_file, errno); - goto out_close; - } - } - - sizes(size, sectorsize, sizeof(struct cow_header_v2), - bitmap_len_out, data_offset_out); - *bitmap_offset_out = sizeof(struct cow_header_v2); - - return(fd); - - out_close: - close(fd); + err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment, + bitmap_offset_out, bitmap_len_out, + data_offset_out); + if(!err) + return(fd); + os_close_file(fd); out: return(err); } +/* XXX Just trivial wrappers around os_read_file and os_write_file */ int read_ubd_fs(int fd, void *buffer, int len) { - int n; - - n = read(fd, buffer, len); - if(n < 0) return(-errno); - else return(n); + return(os_read_file(fd, buffer, len)); } int write_ubd_fs(int fd, char *buffer, int len) { - int n; - - n = write(fd, buffer, len); - if(n < 0) return(-errno); - else return(n); + return(os_write_file(fd, buffer, len)); } -int ubd_is_dir(char *file) +static int update_bitmap(struct io_thread_req *req) { - struct stat64 buf; + int n; + + if(req->cow_offset == -1) + return(0); + + n = os_seek_file(req->fds[1], req->cow_offset); + if(n < 0){ + printk("do_io - bitmap lseek failed : err = %d\n", -n); + return(1); + } - if(stat64(file, &buf) < 0) return(0); - return(S_ISDIR(buf.st_mode)); + n = os_write_file(req->fds[1], &req->bitmap_words, + sizeof(req->bitmap_words)); + if(n != sizeof(req->bitmap_words)){ + printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, + req->fds[1]); + return(1); + } + + return(0); } void do_io(struct io_thread_req *req) @@ -461,8 +234,18 @@ void do_io(struct io_thread_req *req) char *buf; unsigned long len; int n, nsectors, start, end, bit; + int err; __u64 off; + if(req->op == UBD_MMAP){ + /* Touch the page to force the host to do any necessary IO to + * get it into memory + */ + n = *((volatile int *) req->buffer); + req->error = update_bitmap(req); + return; + } + nsectors = req->length / req->sectorsize; start = 0; do { @@ -473,15 +256,14 @@ void do_io(struct io_thread_req *req) &req->sector_mask) == bit)) end++; - if(end != nsectors) - printk("end != nsectors\n"); off = req->offset + req->offsets[bit] + start * req->sectorsize; len = (end - start) * req->sectorsize; buf = &req->buffer[start * req->sectorsize]; - if(os_seek_file(req->fds[bit], off) != 0){ - printk("do_io - lseek failed : errno = %d\n", errno); + err = os_seek_file(req->fds[bit], off); + if(err < 0){ + printk("do_io - lseek failed : err = %d\n", -err); req->error = 1; return; } @@ -490,11 +272,10 @@ void do_io(struct io_thread_req *req) do { buf = &buf[n]; len -= n; - n = read(req->fds[bit], buf, len); + n = os_read_file(req->fds[bit], buf, len); if (n < 0) { - printk("do_io - read returned %d : " - "errno = %d fd = %d\n", n, - errno, req->fds[bit]); + printk("do_io - read failed, err = %d " + "fd = %d\n", -n, req->fds[bit]); req->error = 1; return; } @@ -502,11 +283,10 @@ void do_io(struct io_thread_req *req) if (n < len) memset(&buf[n], 0, len - n); } else { - n = write(req->fds[bit], buf, len); + n = os_write_file(req->fds[bit], buf, len); if(n != len){ - printk("do_io - write returned %d : " - "errno = %d fd = %d\n", n, - errno, req->fds[bit]); + printk("do_io - write failed err = %d " + "fd = %d\n", -n, req->fds[bit]); req->error = 1; return; } @@ -515,24 +295,7 @@ void do_io(struct io_thread_req *req) start = end; } while(start < nsectors); - if(req->cow_offset != -1){ - if(os_seek_file(req->fds[1], req->cow_offset) != 0){ - printk("do_io - bitmap lseek failed : errno = %d\n", - errno); - req->error = 1; - return; - } - n = write(req->fds[1], &req->bitmap_words, - sizeof(req->bitmap_words)); - if(n != sizeof(req->bitmap_words)){ - printk("do_io - bitmap update returned %d : " - "errno = %d fd = %d\n", n, errno, req->fds[1]); - req->error = 1; - return; - } - } - req->error = 0; - return; + req->error = update_bitmap(req); } /* Changed in start_io_thread, which is serialized by being called only @@ -550,19 +313,23 @@ int io_thread(void *arg) signal(SIGWINCH, SIG_IGN); while(1){ - n = read(kernel_fd, &req, sizeof(req)); - if(n < 0) printk("io_thread - read returned %d, errno = %d\n", - n, errno); - else if(n < sizeof(req)){ - printk("io_thread - short read : length = %d\n", n); + n = os_read_file(kernel_fd, &req, sizeof(req)); + if(n != sizeof(req)){ + if(n < 0) + printk("io_thread - read failed, fd = %d, " + "err = %d\n", kernel_fd, -n); + else { + printk("io_thread - short read, fd = %d, " + "length = %d\n", kernel_fd, n); + } continue; } io_count++; do_io(&req); - n = write(kernel_fd, &req, sizeof(req)); + n = os_write_file(kernel_fd, &req, sizeof(req)); if(n != sizeof(req)) - printk("io_thread - write failed, errno = %d\n", - errno); + printk("io_thread - write failed, fd = %d, err = %d\n", + kernel_fd, -n); } } @@ -571,10 +338,11 @@ int start_io_thread(unsigned long sp, int *fd_out) int pid, fds[2], err; err = os_pipe(fds, 1, 1); - if(err){ - printk("start_io_thread - os_pipe failed, errno = %d\n", -err); - return(-1); + if(err < 0){ + printk("start_io_thread - os_pipe failed, err = %d\n", -err); + goto out; } + kernel_fd = fds[0]; *fd_out = fds[1]; @@ -582,32 +350,20 @@ int start_io_thread(unsigned long sp, int *fd_out) NULL); if(pid < 0){ printk("start_io_thread - clone failed : errno = %d\n", errno); - return(-errno); - } - return(pid); -} - -#ifdef notdef -int start_io_thread(unsigned long sp, int *fd_out) -{ - int pid; - - if((kernel_fd = get_pty()) < 0) return(-1); - raw(kernel_fd, 0); - if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){ - printk("Couldn't open tty for IO\n"); - return(-1); + err = -errno; + goto out_close; } - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, - NULL); - if(pid < 0){ - printk("start_io_thread - clone failed : errno = %d\n", errno); - return(-errno); - } return(pid); + + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + kernel_fd = -1; + *fd_out = -1; + out: + return(err); } -#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 59c4ba89f..f417b3b66 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,8 @@ void *xterm_init(char *str, int device, struct chan_opts *opts) { struct xterm_chan *data; - if((data = malloc(sizeof(*data))) == NULL) return(NULL); + data = malloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct xterm_chan) { .pid = -1, .helper_pid = -1, .device = device, @@ -83,6 +83,7 @@ __uml_setup("xterm=", xterm_setup, " are 'xterm=gnome-terminal,-t,-x'.\n\n" ); +/* XXX This badly needs some cleaning up in the error paths */ int xterm_open(int input, int output, int primary, void *d, char **dev_out) { struct xterm_chan *data = d; @@ -93,7 +94,7 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out) "/usr/lib/uml/port-helper", "-uml-socket", file, NULL }; - if(access(argv[4], X_OK)) + if(os_access(argv[4], OS_ACC_X_OK) < 0) argv[4] = "port-helper"; fd = mkstemp(file); @@ -106,13 +107,13 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out) printk("xterm_open : unlink failed, errno = %d\n", errno); return(-errno); } - close(fd); + os_close_file(fd); - fd = create_unix_socket(file, sizeof(file)); + fd = os_create_unix_socket(file, sizeof(file), 1); if(fd < 0){ printk("xterm_open : create_unix_socket failed, errno = %d\n", -fd); - return(-fd); + return(fd); } sprintf(title, data->title, data->device); @@ -128,20 +129,32 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out) if(data->direct_rcv) new = os_rcv_fd(fd, &data->helper_pid); else { - if((err = os_set_fd_block(fd, 0)) != 0){ + err = os_set_fd_block(fd, 0); + if(err < 0){ printk("xterm_open : failed to set descriptor " - "non-blocking, errno = %d\n", err); + "non-blocking, err = %d\n", -err); return(err); } new = xterm_fd(fd, &data->helper_pid); } if(new < 0){ - printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new); + printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); goto out; } - tcgetattr(new, &data->tt); - if(data->raw) raw(new, 0); + CATCH_EINTR(err = tcgetattr(new, &data->tt)); + if(err){ + new = err; + goto out; + } + + if(data->raw){ + err = raw(new); + if(err){ + new = err; + goto out; + } + } data->pid = pid; *dev_out = NULL; @@ -160,7 +173,7 @@ void xterm_close(int fd, void *d) if(data->helper_pid != -1) os_kill_process(data->helper_pid, 0); data->helper_pid = -1; - close(fd); + os_close_file(fd); } void xterm_free(void *d) diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index 1b4683fe3..f3d33d044 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c @@ -5,9 +5,12 @@ #include "linux/errno.h" #include "linux/slab.h" +#include "linux/signal.h" +#include "linux/interrupt.h" #include "asm/semaphore.h" #include "asm/irq.h" #include "irq_user.h" +#include "irq_kern.h" #include "kern_util.h" #include "os.h" #include "xterm.h" @@ -19,17 +22,18 @@ struct xterm_wait { int new_fd; }; -static void xterm_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs) { struct xterm_wait *xterm = data; int fd; fd = os_rcv_fd(xterm->fd, &xterm->pid); if(fd == -EAGAIN) - return; + return(IRQ_NONE); xterm->new_fd = fd; up(&xterm->sem); + return(IRQ_HANDLED); } int xterm_fd(int socket, int *pid_out) @@ -54,14 +58,17 @@ int xterm_fd(int socket, int *pid_out) if(err){ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " "err = %d\n", err); - return(err); + ret = err; + goto out; } down(&data->sem); + free_irq_by_irq_and_dev(XTERM_IRQ, data); free_irq(XTERM_IRQ, data); ret = data->new_fd; *pid_out = data->pid; + out: kfree(data); return(ret); diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h index 6d36d9c30..abdb015a4 100644 --- a/arch/um/include/2_5compat.h +++ b/arch/um/include/2_5compat.h @@ -6,20 +6,6 @@ #ifndef __2_5_COMPAT_H__ #define __2_5_COMPAT_H__ -#include "linux/version.h" - -#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \ - name : dev_name, \ - write : write_proc, \ - read : NULL, \ - device : device_proc, \ - setup : setup_proc, \ - flags : f, \ - index : -1, \ - cflag : 0, \ - next : NULL \ -} - #define INIT_HARDSECT(arr, maj, sizes) #define SET_PRI(task) do ; while(0) diff --git a/arch/um/include/frame_kern.h b/arch/um/include/frame_kern.h index 21becc6fc..b67ea3e94 100644 --- a/arch/um/include/frame_kern.h +++ b/arch/um/include/frame_kern.h @@ -10,13 +10,11 @@ #include "sysdep/frame_kern.h" extern int setup_signal_stack_sc(unsigned long stack_top, int sig, - unsigned long handler, - void (*restorer)(void), + struct k_sigaction *ka, struct pt_regs *regs, sigset_t *mask); extern int setup_signal_stack_si(unsigned long stack_top, int sig, - unsigned long handler, - void (*restorer)(void), + struct k_sigaction *ka, struct pt_regs *regs, siginfo_t *info, sigset_t *mask); diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h index 4bcb829d7..3af52a634 100644 --- a/arch/um/include/irq_kern.h +++ b/arch/um/include/irq_kern.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -9,7 +9,7 @@ #include "linux/interrupt.h" extern int um_request_irq(unsigned int irq, int fd, int type, - irqreturn_t (*handler)(int, void *, + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id); diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index 087bd39d0..f724b7172 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h @@ -10,10 +10,11 @@ enum { IRQ_READ, IRQ_WRITE }; extern void sigio_handler(int sig, union uml_pt_regs *regs); extern int activate_fd(int irq, int fd, int type, void *dev_id); -extern void free_irq_by_irq_and_dev(int irq, void *dev_id); +extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); extern void free_irq_by_fd(int fd); extern void reactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum); +extern int deactivate_all_fds(void); extern void forward_interrupts(int pid); extern void init_irq_signals(int on_sigstack); extern void forward_ipi(int fd, int pid); diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 09e76a308..15389c886 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -29,7 +29,7 @@ extern int kernel_thread_proc(void *data); extern void syscall_segv(int sig); extern int current_pid(void); extern unsigned long alloc_stack(int order, int atomic); -extern int do_signal(int error); +extern int do_signal(void); extern int is_stack_fault(unsigned long sp); extern unsigned long segv(unsigned long address, unsigned long ip, int is_write, int is_user, void *sc); @@ -41,7 +41,7 @@ extern int is_tracing(void *task); extern int segv_syscall(void); extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); extern int page_size(void); -extern int page_mask(void); +extern unsigned long page_mask(void); extern int need_finish_fork(void); extern void free_stack(unsigned long stack, int order); extern void add_input_request(int op, void (*proc)(int), void *arg); @@ -60,12 +60,11 @@ extern void finish_fork(void); extern void paging_init(void); extern void init_flush_vm(void); extern void *syscall_sp(void *t); -extern void syscall_trace(void); +extern void syscall_trace(union uml_pt_regs *regs, int entryexit); extern int hz(void); -extern void idle_timer(void); +extern void uml_idle_timer(void); extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); extern int external_pid(void *t); -extern int pid_to_processor_id(int pid); extern void boot_timer_handler(int sig); extern void interrupt_end(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); @@ -89,9 +88,7 @@ extern int remove_gdb(void); extern char *uml_strdup(char *string); extern void unprotect_kernel_mem(void); extern void protect_kernel_mem(void); -extern void set_kmem_end(unsigned long); extern void uml_cleanup(void); -extern int pid_to_processor_id(int pid); extern void set_current(void *t); extern void lock_signalled_task(void *t); extern void IPI_handler(int cpu); @@ -100,7 +97,9 @@ extern void *get_init_task(void); extern int clear_user_proc(void *buf, int size); extern int copy_to_user_proc(void *to, void *from, int size); extern int copy_from_user_proc(void *to, void *from, int size); +extern int strlen_user_proc(char *str); extern void bus_handler(int sig, union uml_pt_regs *regs); +extern void winch(int sig, union uml_pt_regs *regs); extern long execute_syscall(void *r); extern int smp_sigio_handler(void); extern void *get_current(void); @@ -111,6 +110,7 @@ extern void arch_switch(void); extern void free_irq(unsigned int, void *); extern int um_in_interrupt(void); extern int cpu(void); + #endif /* diff --git a/arch/um/include/line.h b/arch/um/include/line.h index e9783dc16..4f2853fbd 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -9,12 +9,14 @@ #include "linux/list.h" #include "linux/workqueue.h" #include "linux/tty.h" +#include "linux/interrupt.h" #include "asm/semaphore.h" #include "chan_user.h" #include "mconsole_kern.h" struct line_driver { char *name; + char *device_name; char *devfs_name; short major; short minor_start; @@ -67,15 +69,12 @@ struct lines { #define LINES_INIT(n) { num : n } -extern void line_interrupt(int irq, void *data, struct pt_regs *unused); -extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused); extern void line_close(struct line *lines, struct tty_struct *tty); extern int line_open(struct line *lines, struct tty_struct *tty, struct chan_opts *opts); extern int line_setup(struct line *lines, int num, char *init, int all_allowed); -extern int line_write(struct line *line, struct tty_struct *tty, int from_user, - const char *buf, int len); +extern int line_write(struct line *line, struct tty_struct *tty, const char *buf, int len); extern int line_write_room(struct tty_struct *tty); extern char *add_xterm_umid(char *base); extern int line_setup_irq(int fd, int input, int output, void *data); diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index 7eea2fac0..9fbe3083f 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -41,11 +41,13 @@ struct mconsole_notify { struct mc_request; +enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; + struct mconsole_command { char *command; void (*handler)(struct mc_request *req); - int as_interrupt; + enum mc_context context; }; struct mc_request @@ -77,6 +79,8 @@ extern void mconsole_sysrq(struct mc_request *req); extern void mconsole_cad(struct mc_request *req); extern void mconsole_stop(struct mc_request *req); extern void mconsole_go(struct mc_request *req); +extern void mconsole_log(struct mc_request *req); +extern void mconsole_proc(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h index bad6b30b8..10c46c389 100644 --- a/arch/um/include/mem.h +++ b/arch/um/include/mem.h @@ -1,19 +1,18 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #ifndef __MEM_H__ #define __MEM_H__ -struct vm_reserved { - struct list_head list; - unsigned long start; - unsigned long end; -}; +#include "linux/types.h" -extern void set_usable_vm(unsigned long start, unsigned long end); -extern void set_kmem_end(unsigned long new); +extern int phys_mapping(unsigned long phys, __u64 *offset_out); +extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); +extern int is_remapped(void *virt); +extern int physmem_remove_mapping(void *virt); +extern void physmem_forget_descriptor(int fd); #endif diff --git a/arch/um/include/mem_kern.h b/arch/um/include/mem_kern.h index b39f03d94..cb7e196d3 100644 --- a/arch/um/include/mem_kern.h +++ b/arch/um/include/mem_kern.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index d80ac354b..d6404bb64 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h @@ -32,46 +32,42 @@ #ifndef _MEM_USER_H #define _MEM_USER_H -struct mem_region { +struct iomem_region { + struct iomem_region *next; char *driver; - unsigned long start_pfn; - unsigned long start; - unsigned long len; - void *mem_map; int fd; + int size; + unsigned long phys; + unsigned long virt; }; -extern struct mem_region *regions[]; -extern struct mem_region physmem_region; +extern struct iomem_region *iomem_regions; +extern int iomem_size; #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) extern unsigned long host_task_size; extern unsigned long task_size; +extern void check_devanon(void); extern int init_mem_user(void); extern int create_mem_file(unsigned long len); -extern void setup_range(int fd, char *driver, unsigned long start, - unsigned long pfn, unsigned long total, int need_vm, - struct mem_region *region, void *reserved); extern void setup_memory(void *entry); extern unsigned long find_iomem(char *driver, unsigned long *len_out); -extern int init_maps(struct mem_region *region); -extern int nregions(void); -extern int reserve_vm(unsigned long start, unsigned long end, void *e); +extern int init_maps(unsigned long physmem, unsigned long iomem, + unsigned long highmem); extern unsigned long get_vm(unsigned long len); extern void setup_physmem(unsigned long start, unsigned long usable, - unsigned long len); -extern int setup_region(struct mem_region *region, void *entry); + unsigned long len, unsigned long highmem); extern void add_iomem(char *name, int fd, unsigned long size); -extern struct mem_region *phys_region(unsigned long phys); extern unsigned long phys_offset(unsigned long phys); extern void unmap_physmem(void); -extern int map_memory(unsigned long virt, unsigned long phys, - unsigned long len, int r, int w, int x); +extern void map_memory(unsigned long virt, unsigned long phys, + unsigned long len, int r, int w, int x); extern int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern unsigned long get_kmem_end(void); +extern void check_tmpexec(void); #endif diff --git a/arch/um/include/mode.h b/arch/um/include/mode.h index 23b95f999..786cf563e 100644 --- a/arch/um/include/mode.h +++ b/arch/um/include/mode.h @@ -9,11 +9,11 @@ #include "uml-config.h" #ifdef UML_CONFIG_MODE_TT -#include "../kernel/tt/include/mode.h" +#include "mode-tt.h" #endif #ifdef UML_CONFIG_MODE_SKAS -#include "../kernel/skas/include/mode.h" +#include "mode-skas.h" #endif #endif diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h index 562174bf4..2d88afd0c 100644 --- a/arch/um/include/mode_kern.h +++ b/arch/um/include/mode_kern.h @@ -9,11 +9,11 @@ #include "linux/config.h" #ifdef CONFIG_MODE_TT -#include "../kernel/tt/include/mode_kern.h" +#include "mode_kern-tt.h" #endif #ifdef CONFIG_MODE_SKAS -#include "../kernel/skas/include/mode_kern.h" +#include "mode_kern-skas.h" #endif #endif diff --git a/arch/um/include/os.h b/arch/um/include/os.h index b9b1f0c1d..07340c8cf 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -17,6 +17,32 @@ #define OS_TYPE_FIFO 6 #define OS_TYPE_SOCK 7 +/* os_access() flags */ +#define OS_ACC_F_OK 0 /* Test for existence. */ +#define OS_ACC_X_OK 1 /* Test for execute permission. */ +#define OS_ACC_W_OK 2 /* Test for write permission. */ +#define OS_ACC_R_OK 4 /* Test for read permission. */ +#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ + +/* + * types taken from stat_file() in hostfs_user.c + * (if they are wrong here, they are wrong there...). + */ +struct uml_stat { + int ust_dev; /* device */ + unsigned long long ust_ino; /* inode */ + int ust_mode; /* protection */ + int ust_nlink; /* number of hard links */ + int ust_uid; /* user ID of owner */ + int ust_gid; /* group ID of owner */ + unsigned long long ust_size; /* total size, in bytes */ + int ust_blksize; /* blocksize for filesystem I/O */ + unsigned long long ust_blocks; /* number of blocks allocated */ + unsigned long ust_atime; /* time of last access */ + unsigned long ust_mtime; /* time of last modification */ + unsigned long ust_ctime; /* time of last change */ +}; + struct openflags { unsigned int r : 1; unsigned int w : 1; @@ -84,42 +110,64 @@ static inline struct openflags of_excl(struct openflags flags) flags.e = 1; return(flags); } - + static inline struct openflags of_cloexec(struct openflags flags) { flags.cl = 1; return(flags); } +extern int os_stat_file(const char *file_name, struct uml_stat *buf); +extern int os_stat_fd(const int fd, struct uml_stat *buf); +extern int os_access(const char *file, int mode); +extern void os_print_error(int error, const char* str); +extern int os_get_exec_close(int fd, int *close_on_exec); +extern int os_set_exec_close(int fd, int close_on_exec); +extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); +extern int os_window_size(int fd, int *rows, int *cols); +extern int os_new_tty_pgrp(int fd, int pid); +extern int os_get_ifname(int fd, char *namebuf); +extern int os_set_slip(int fd); +extern int os_set_owner(int fd, int pid); +extern int os_sigio_async(int master, int slave); +extern int os_mode_fd(int fd, int mode); + extern int os_seek_file(int fd, __u64 offset); extern int os_open_file(char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); -extern int os_write_file(int fd, void *buf, int count); +extern int os_write_file(int fd, const void *buf, int count); extern int os_file_size(char *file, long long *size_out); +extern int os_file_modtime(char *file, unsigned long *modtime); extern int os_pipe(int *fd, int stream, int close_on_exec); extern int os_set_fd_async(int fd, int owner); +extern int os_clear_fd_async(int fd); extern int os_set_fd_block(int fd, int blocking); extern int os_accept_connection(int fd); +extern int os_create_unix_socket(char *file, int len, int close_on_exec); extern int os_shutdown_socket(int fd, int r, int w); extern void os_close_file(int fd); extern int os_rcv_fd(int fd, int *helper_pid_out); -extern int create_unix_socket(char *file, int len); +extern int create_unix_socket(char *file, int len, int close_on_exec); extern int os_connect_socket(char *name); extern int os_file_type(char *file); extern int os_file_mode(char *file, struct openflags *mode_out); +extern int os_lock_file(int fd, int excl); extern unsigned long os_process_pc(int pid); extern int os_process_parent(int pid); extern void os_stop_process(int pid); extern void os_kill_process(int pid, int reap_child); +extern void os_kill_ptraced_process(int pid, int reap_child); extern void os_usr1_process(int pid); extern int os_getpid(void); -extern int os_map_memory(void *virt, int fd, unsigned long off, +extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); extern int os_protect_memory(void *addr, unsigned long len, int r, int w, int x); extern int os_unmap_memory(void *addr, int len); +extern void os_flush_stdout(void); +extern unsigned long long os_usecs(void); #endif diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h index ad35d0c2b..227cef5fa 100644 --- a/arch/um/include/ptrace_user.h +++ b/arch/um/include/ptrace_user.h @@ -15,4 +15,15 @@ extern void arch_enter_kernel(void *task, int pid); extern void arch_leave_kernel(void *task, int pid); extern void ptrace_pokeuser(unsigned long addr, unsigned long data); + +/* syscall emulation path in ptrace */ + +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif + +void set_using_sysemu(int value); +int get_using_sysemu(void); +extern int sysemu_supported; + #endif diff --git a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h index adaea4d5a..b075e543d 100644 --- a/arch/um/include/signal_user.h +++ b/arch/um/include/signal_user.h @@ -11,6 +11,8 @@ extern int signal_stack_size; extern int change_sig(int signal, int on); extern void set_sigstack(void *stack, int size); extern void set_handler(int sig, void (*handler)(int), int flags, ...); +extern int set_signals(int enable); +extern int get_signals(void); #endif diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h index 7cd983d88..cfb5fb4f5 100644 --- a/arch/um/include/skas_ptrace.h +++ b/arch/um/include/skas_ptrace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ diff --git a/arch/um/include/syscall_user.h b/arch/um/include/syscall_user.h index bc7be6293..811d0ec24 100644 --- a/arch/um/include/syscall_user.h +++ b/arch/um/include/syscall_user.h @@ -7,7 +7,7 @@ #define __SYSCALL_USER_H extern int record_syscall_start(int syscall); -extern void record_syscall_end(int index, int result); +extern void record_syscall_end(int index, long result); #endif diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h index d1ca652a7..bb6b343f1 100644 --- a/arch/um/include/sysdep-i386/checksum.h +++ b/arch/um/include/sysdep-i386/checksum.h @@ -5,6 +5,7 @@ #ifndef __UM_SYSDEP_CHECKSUM_H #define __UM_SYSDEP_CHECKSUM_H +#include "linux/in6.h" #include "linux/string.h" /* @@ -102,7 +103,8 @@ static inline unsigned short ip_fast_csum(unsigned char * iph, are modified, we must also specify them as outputs, or gcc will assume they contain their original values. */ : "=r" (sum), "=r" (iph), "=r" (ihl) - : "1" (iph), "2" (ihl)); + : "1" (iph), "2" (ihl) + : "memory"); return(sum); } diff --git a/arch/um/include/sysdep-i386/frame_user.h b/arch/um/include/sysdep-i386/frame_user.h index b4065b235..13faf079a 100644 --- a/arch/um/include/sysdep-i386/frame_user.h +++ b/arch/um/include/sysdep-i386/frame_user.h @@ -56,26 +56,26 @@ static inline void setup_arch_frame(struct arch_frame_data_raw *in, * it would have to be __builtin_frame_address(1). */ -static inline unsigned long frame_restorer(void) -{ - unsigned long *fp; - - fp = __builtin_frame_address(0); - return((unsigned long) (fp + 1)); -} +#define frame_restorer() \ +({ \ + unsigned long *fp; \ +\ + fp = __builtin_frame_address(0); \ + ((unsigned long) (fp + 1)); \ +}) /* Similarly, this returns the value of sp when the handler was first * entered. This is used to calculate the proper sp when delivering * signals. */ -static inline unsigned long frame_sp(void) -{ - unsigned long *fp; - - fp = __builtin_frame_address(0); - return((unsigned long) (fp + 1)); -} +#define frame_sp() \ +({ \ + unsigned long *fp; \ +\ + fp = __builtin_frame_address(0); \ + ((unsigned long) (fp + 1)); \ +}) #endif diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 26c70cf8b..887fdb61e 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h @@ -28,8 +28,8 @@ */ #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) -/* These are General Protection and Page Fault */ -#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14)) +/* This is Page Fault */ +#define SEGV_IS_FIXABLE(trap) (trap == 14) #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc))) diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h index 08d7c1323..47687dcf2 100644 --- a/arch/um/include/sysdep-i386/syscalls.h +++ b/arch/um/include/sysdep-i386/syscalls.h @@ -11,39 +11,34 @@ typedef long syscall_handler_t(struct pt_regs); #define EXECUTE_SYSCALL(syscall, regs) \ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) -extern syscall_handler_t sys_modify_ldt; -extern syscall_handler_t old_mmap_i386; -extern syscall_handler_t old_select; -extern syscall_handler_t sys_ni_syscall; - #define ARCH_SYSCALLS \ - [ __NR_mmap ] = old_mmap_i386, \ - [ __NR_select ] = old_select, \ - [ __NR_vm86old ] = sys_ni_syscall, \ - [ __NR_modify_ldt ] = sys_modify_ldt, \ - [ __NR_lchown32 ] = sys_lchown, \ - [ __NR_getuid32 ] = sys_getuid, \ - [ __NR_getgid32 ] = sys_getgid, \ - [ __NR_geteuid32 ] = sys_geteuid, \ - [ __NR_getegid32 ] = sys_getegid, \ - [ __NR_setreuid32 ] = sys_setreuid, \ - [ __NR_setregid32 ] = sys_setregid, \ - [ __NR_getgroups32 ] = sys_getgroups, \ - [ __NR_setgroups32 ] = sys_setgroups, \ - [ __NR_fchown32 ] = sys_fchown, \ - [ __NR_setresuid32 ] = sys_setresuid, \ - [ __NR_getresuid32 ] = sys_getresuid, \ - [ __NR_setresgid32 ] = sys_setresgid, \ - [ __NR_getresgid32 ] = sys_getresgid, \ - [ __NR_chown32 ] = sys_chown, \ - [ __NR_setuid32 ] = sys_setuid, \ - [ __NR_setgid32 ] = sys_setgid, \ - [ __NR_setfsuid32 ] = sys_setfsuid, \ - [ __NR_setfsgid32 ] = sys_setfsgid, \ - [ __NR_pivot_root ] = sys_pivot_root, \ - [ __NR_mincore ] = sys_mincore, \ - [ __NR_madvise ] = sys_madvise, \ - [ 222 ] = sys_ni_syscall, + [ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \ + [ __NR_select ] = (syscall_handler_t *) old_select, \ + [ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \ + [ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \ + [ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \ + [ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \ + [ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \ + [ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \ + [ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \ + [ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \ + [ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \ + [ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \ + [ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \ + [ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \ + [ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \ + [ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \ + [ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \ + [ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \ + [ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \ + [ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \ + [ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \ + [ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \ + [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \ + [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \ + [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \ + [ 222 ] = (syscall_handler_t *) sys_ni_syscall, /* 222 doesn't yet have a name in include/asm-i386/unistd.h */ diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h index 9ddb749f7..6793a2fcd 100644 --- a/arch/um/include/time_user.h +++ b/arch/um/include/time_user.h @@ -11,6 +11,7 @@ extern void switch_timers(int to_real); extern void set_interval(int timer_type); extern void idle_sleep(int secs); extern void enable_timer(void); +extern void disable_timer(void); extern unsigned long time_lock(void); extern void time_unlock(unsigned long); diff --git a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h index b28beaf58..9bac59c4c 100644 --- a/arch/um/include/ubd_user.h +++ b/arch/um/include/ubd_user.h @@ -9,7 +9,7 @@ #include "os.h" -enum ubd_req { UBD_READ, UBD_WRITE }; +enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; struct io_thread_req { enum ubd_req op; @@ -20,8 +20,10 @@ struct io_thread_req { char *buffer; int sectorsize; unsigned long sector_mask; - unsigned long cow_offset; + unsigned long long cow_offset; unsigned long bitmap_words[2]; + int map_fd; + unsigned long long map_offset; int error; }; @@ -31,7 +33,7 @@ extern int open_ubd_file(char *file, struct openflags *openflags, int *create_cow_out); extern int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, int sectorsize, - int *bitmap_offset_out, + int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out); extern int read_cow_bitmap(int fd, void *buf, int offset, int len); @@ -39,7 +41,6 @@ extern int read_ubd_fs(int fd, void *buffer, int len); extern int write_ubd_fs(int fd, char *buffer, int len); extern int start_io_thread(unsigned long sp, int *fds_out); extern void do_io(struct io_thread_req *req); -extern int ubd_is_dir(char *file); static inline int ubd_test_bit(__u64 bit, unsigned char *data) { diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h index 3c5660ff9..5243f455f 100644 --- a/arch/um/include/um_mmu.h +++ b/arch/um/include/um_mmu.h @@ -10,11 +10,11 @@ #include "choose-mode.h" #ifdef CONFIG_MODE_TT -#include "../kernel/tt/include/mmu.h" +#include "mmu-tt.h" #endif #ifdef CONFIG_MODE_SKAS -#include "../kernel/skas/include/mmu.h" +#include "mmu-skas.h" #endif typedef union { diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 41afa3a8f..0924fcc95 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -10,11 +10,11 @@ #include "choose-mode.h" #ifdef CONFIG_MODE_TT -#include "../kernel/tt/include/uaccess.h" +#include "uaccess-tt.h" #endif #ifdef CONFIG_MODE_SKAS -#include "../kernel/skas/include/uaccess.h" +#include "uaccess-skas.h" #endif #define access_ok(type, addr, size) \ @@ -38,22 +38,73 @@ static inline int copy_to_user(void *to, const void *from, int n) from, n)); } +/* + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ + static inline int strncpy_from_user(char *dst, const char *src, int count) { return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, dst, src, count)); } +/* + * __clear_user: - Zero a block of memory in user space, with less checking. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ static inline int __clear_user(void *mem, int len) { return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); } +/* + * clear_user: - Zero a block of memory in user space. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ static inline int clear_user(void *mem, int len) { return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); } +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * @n: The maximum valid length + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ static inline int strnlen_user(const void *str, int len) { return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); diff --git a/arch/um/include/user.h b/arch/um/include/user.h index 6f009be0f..57ee9e261 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -14,6 +14,9 @@ extern void *um_kmalloc_atomic(int size); extern void kfree(void *ptr); extern int in_aton(char *str); extern int open_gdb_chan(void); +extern int strlcpy(char *, const char *, int); +extern void *um_vmalloc(int size); +extern void vfree(void *ptr); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index e87b8fcb0..4fc088eb7 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -8,14 +8,14 @@ #include "sysdep/ptrace.h" +#define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) + extern int mode_tt; extern int grantpt(int __fd); extern int unlockpt(int __fd); extern char *ptsname(int __fd); -enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; - struct cpu_task { int pid; void *task; @@ -59,13 +59,11 @@ extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern void *add_signal_handler(int sig, void (*handler)(int)); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); -extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags); extern int linux_main(int argc, char **argv); extern void set_cmdline(char *cmd); extern void input_cb(void (*proc)(void *), void *arg, int arg_len); extern int get_pty(void); extern void *um_kmalloc(int size); -extern int raw(int fd, int complain); extern int switcheroo(int fd, int prot, void *from, void *to, int size); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(void); @@ -76,7 +74,6 @@ extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); extern char *get_umid(int only_if_set); extern void do_longjmp(void *p, int val); -extern void suspend_new_thread(int fd); extern int detach(int pid, int sig); extern int attach(int pid); extern void kill_child_dead(int pid); @@ -86,11 +83,15 @@ extern void check_sigio(void); extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); extern void write_sigio_workaround(void); extern void arch_check_bugs(void); +extern int cpu_feature(char *what, char *buf, int len); extern int arch_handle_signal(int sig, union uml_pt_regs *regs); extern int arch_fixup(unsigned long address, void *sc_ptr); extern void forward_pending_sigio(int target); extern int can_do_skas(void); - +extern void arch_init_thread(void); +extern int setjmp_wrapper(void (*proc)(void *, void *), ...); +extern int raw(int fd); + #endif /* diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 0f13dd4c7..9fa9711ec 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -3,15 +3,16 @@ # Licensed under the GPL # -extra-y := vmlinux.lds.s +extra-y := vmlinux.lds +clean-files := vmlinux.lds.S obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \ - process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ - sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \ - syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ - umid.o user_syms.o user_util.o + helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ + physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \ + sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ + syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \ + time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \ + um_arch.o umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,43 +25,19 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \ - process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o + main.o process.o tempfile.o time.o tty_log.o umid.o user_util.o frame.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__ -DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__ - - -CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \ - -I/usr/include -I../include - -CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS)) +CFLAGS_frame.o := -fno-omit-frame-pointer $(USER_OBJS) : %.o: %.c - $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -# This has to be separate because it needs be compiled with frame pointers -# regardless of how the rest of the kernel is built. - -$(obj)/frame.o: $(src)/frame.c - $(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $< - -QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while() { $$_ =~ s/CONFIG/$$config/; print $$_ }' - -$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config - $(PERL) -e $(QUOTE) < $(src)/config.c.in > $@ - -$(obj)/config.o : $(obj)/config.c - -clean: - rm -f config.c - for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done - -modules: - -fastdep: + $(CC) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) -c -o $@ $< -dep: +QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while() { $$_ =~ s/CONFIG/$$config/; print $$_ }' -archmrproper: clean +quiet_cmd_quote = QUOTE $@ +cmd_quote = $(PERL) -e $(QUOTE) < $< > $@ +targets += config.c +$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE + $(call if_changed,quote) diff --git a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in index f6c96b955..c062cbfe3 100644 --- a/arch/um/kernel/config.c.in +++ b/arch/um/kernel/config.c.in @@ -7,9 +7,7 @@ #include #include "init.h" -static __initdata char *config = " -CONFIG -"; +static __initdata char *config = "CONFIG"; static int __init print_config(char *line, int *add) { diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index ee1642119..39ddb0968 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -59,6 +59,8 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT + *(.fixup) *(.stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index a6be6b542..4336240c1 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -32,31 +32,38 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); } -static int execve1(char *file, char **argv, char **env) +extern void log_exec(char **argv, void *tty); + +static long execve1(char *file, char **argv, char **env) { - int error; + long error; +#ifdef CONFIG_TTY_LOG + log_exec(argv, current->tty); +#endif error = do_execve(file, argv, env, ¤t->thread.regs); if (error == 0){ + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); set_cmdline(current_cmd()); } return(error); } -int um_execve(char *file, char **argv, char **env) +long um_execve(char *file, char **argv, char **env) { - int err; + long err; err = execve1(file, argv, env); - if(!err) + if(!err) do_longjmp(current->thread.exec_buf, 1); return(err); } -int sys_execve(char *file, char **argv, char **env) +long sys_execve(char *file, char **argv, char **env) { - int error; + long error; char *filename; lock_kernel(); diff --git a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c index d8993f293..804bfeb97 100644 --- a/arch/um/kernel/frame.c +++ b/arch/um/kernel/frame.c @@ -21,6 +21,7 @@ #include "sysdep/sigcontext.h" #include "frame_user.h" #include "kern_util.h" +#include "user_util.h" #include "ptrace_user.h" #include "os.h" @@ -40,7 +41,7 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp, /* Wait for it to stop itself and continue it with a SIGUSR1 to force * it into the signal handler. */ - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); @@ -60,7 +61,7 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp, * At this point, the handler has stuffed the addresses of * sig, sc, and SA_RESTORER in raw. */ - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); @@ -82,7 +83,8 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp, errno); exit(1); } - if(waitpid(pid, &status, 0) < 0){ + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); } @@ -138,7 +140,7 @@ static void child_common(struct common_raw *common, sighandler_t handler, } if(sigaltstack(&ss, NULL) < 0){ printf("sigaltstack failed - errno = %d\n", errno); - kill(getpid(), SIGKILL); + kill(os_getpid(), SIGKILL); } if(restorer){ @@ -160,7 +162,7 @@ static void child_common(struct common_raw *common, sighandler_t handler, if(err < 0){ printf("sigaction failed - errno = %d\n", errno); - kill(getpid(), SIGKILL); + kill(os_getpid(), SIGKILL); } os_stop_process(os_getpid()); @@ -189,7 +191,7 @@ static void sc_handler(int sig, struct sigcontext sc) setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr); os_stop_process(os_getpid()); - kill(getpid(), SIGKILL); + kill(os_getpid(), SIGKILL); } static int sc_child(void *arg) @@ -227,7 +229,7 @@ static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext) ucontext->uc_mcontext.fpregs, raw_si->common.sr); os_stop_process(os_getpid()); - kill(getpid(), SIGKILL); + kill(os_getpid(), SIGKILL); } static int si_child(void *arg) @@ -279,7 +281,7 @@ void capture_signal_stack(void) struct sc_frame_raw raw_sc; struct si_frame_raw raw_si; void *stack, *sigstack; - unsigned long top, sig_top, base; + unsigned long top, base; stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -292,7 +294,6 @@ void capture_signal_stack(void) } top = (unsigned long) stack + PAGE_SIZE - sizeof(void *); - sig_top = (unsigned long) sigstack + PAGE_SIZE; /* Get the sigcontext, no sigrestorer layout */ raw_sc.restorer = 0; diff --git a/arch/um/kernel/frame_kern.c b/arch/um/kernel/frame_kern.c index 9ff437466..fe215c958 100644 --- a/arch/um/kernel/frame_kern.c +++ b/arch/um/kernel/frame_kern.c @@ -6,7 +6,6 @@ #include "asm/ptrace.h" #include "asm/uaccess.h" #include "asm/signal.h" -#include "asm/uaccess.h" #include "asm/ucontext.h" #include "frame_kern.h" #include "sigcontext.h" @@ -29,12 +28,15 @@ static int copy_restorer(void (*restorer)(void), unsigned long start, sizeof(restorer))); } +extern int userspace_pid[]; + static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, struct arch_frame_data *arch) { return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), arch), - copy_sc_to_user_skas(to, fp, &from->regs, + copy_sc_to_user_skas(userspace_pid[0], to, fp, + &from->regs, current->thread.cr2, current->thread.err))); } @@ -54,11 +56,11 @@ static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, } int setup_signal_stack_si(unsigned long stack_top, int sig, - unsigned long handler, void (*restorer)(void), - struct pt_regs *regs, siginfo_t *info, - sigset_t *mask) + struct k_sigaction *ka, struct pt_regs *regs, + siginfo_t *info, sigset_t *mask) { unsigned long start; + void *restorer; void *sip, *ucp, *fp; start = stack_top - signal_frame_si.common.len; @@ -66,6 +68,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ucp = (void *) (start + signal_frame_si.uc_index); fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext)); + restorer = NULL; + if(ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + if(restorer == NULL) panic("setup_signal_stack_si - no restorer"); @@ -83,21 +89,26 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, signal_frame_si.common.sr_relative)) return(1); - PT_REGS_IP(regs) = handler; + PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index; return(0); } int setup_signal_stack_sc(unsigned long stack_top, int sig, - unsigned long handler, void (*restorer)(void), - struct pt_regs *regs, sigset_t *mask) + struct k_sigaction *ka, struct pt_regs *regs, + sigset_t *mask) { struct frame_common *frame = &signal_frame_sc_sr.common; + void *restorer; void *user_sc; int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); unsigned long sigs, sr; unsigned long start = stack_top - frame->len - sig_size; + restorer = NULL; + if(ka->sa.sa_flags & SA_RESTORER) + restorer = ka->sa.sa_restorer; + user_sc = (void *) (start + signal_frame_sc_sr.sc_index); if(restorer == NULL){ frame = &signal_frame_sc.common; @@ -119,7 +130,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) return(1); - PT_REGS_IP(regs) = handler; + PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_SP(regs) = start + frame->sp_index; return(0); diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index 5c4b27942..0e3d409d9 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c @@ -7,12 +7,12 @@ #include #include #include -#include #include #include #include #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "os.h" struct helper_data { @@ -33,6 +33,7 @@ static int helper_child(void *arg) { struct helper_data *data = arg; char **argv = data->argv; + int errval; if(helper_pause){ signal(SIGHUP, helper_hup); @@ -41,8 +42,9 @@ static int helper_child(void *arg) if(data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); execvp(argv[0], argv); + errval = errno; printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); - write(data->fd, &errno, sizeof(errno)); + os_write_file(data->fd, &errval, sizeof(errval)); os_kill_process(os_getpid(), 0); return(0); } @@ -59,17 +61,20 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, if((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; else stack = alloc_stack(0, um_in_interrupt()); - if(stack == 0) return(-ENOMEM); + if(stack == 0) + return(-ENOMEM); err = os_pipe(fds, 1, 0); - if(err){ - printk("run_helper : pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("run_helper : pipe failed, err = %d\n", -err); + goto out_free; } - if(fcntl(fds[1], F_SETFD, 1) != 0){ - printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n", - errno); - return(-errno); + + err = os_set_exec_close(fds[1], 1); + if(err < 0){ + printk("run_helper : setting FD_CLOEXEC failed, err = %d\n", + -err); + goto out_close; } sp = stack + page_size() - sizeof(void *); @@ -80,23 +85,34 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ printk("run_helper : clone failed, errno = %d\n", errno); - return(-errno); + err = -errno; + goto out_close; } - close(fds[1]); - n = read(fds[0], &err, sizeof(err)); + + os_close_file(fds[1]); + n = os_read_file(fds[0], &err, sizeof(err)); if(n < 0){ - printk("run_helper : read on pipe failed, errno = %d\n", - errno); - return(-errno); + printk("run_helper : read on pipe failed, err = %d\n", -n); + err = n; + goto out_kill; } else if(n != 0){ - waitpid(pid, NULL, 0); - pid = -err; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + pid = -errno; } if(stack_out == NULL) free_stack(stack, 0); else *stack_out = stack; return(pid); + + out_kill: + os_kill_process(pid, 1); + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + out_free: + free_stack(stack, 0); + return(err); } int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, @@ -116,10 +132,12 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, return(-errno); } if(stack_out == NULL){ - pid = waitpid(pid, &status, 0); - if(pid < 0) + CATCH_EINTR(pid = waitpid(pid, &status, 0)); + if(pid < 0){ printk("run_helper_thread - wait failed, errno = %d\n", - pid); + errno); + pid = -errno; + } if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " "0x%x\n", status); @@ -133,7 +151,7 @@ int helper_wait(int pid, int block) { int ret; - ret = waitpid(pid, NULL, WNOHANG); + CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); if(ret < 0){ printk("helper_wait : waitpid failed, errno = %d\n", errno); return(-errno); diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index be82cafe9..cd7c85be0 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -8,7 +8,6 @@ #include "linux/module.h" #include "linux/sched.h" #include "linux/init_task.h" -#include "linux/version.h" #include "linux/mqueue.h" #include "asm/uaccess.h" #include "asm/pgtable.h" @@ -19,7 +18,7 @@ static struct fs_struct init_fs = INIT_FS; struct mm_struct init_mm = INIT_MM(init_mm); static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); - +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); EXPORT_SYMBOL(init_mm); /* @@ -44,26 +43,12 @@ union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; -struct task_struct *alloc_task_struct(void) -{ - return((struct task_struct *) - __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER)); -} - void unprotect_stack(unsigned long stack) { protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 1, 1, 0, 1); } -void free_task_struct(struct task_struct *task) -{ - /* free_pages decrements the page counter and only actually frees - * the pages if they are now not accessed by anything. - */ - free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER); -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c index 944c734ca..57d5b41db 100644 --- a/arch/um/kernel/initrd_user.c +++ b/arch/um/kernel/initrd_user.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "user_util.h" @@ -19,13 +18,15 @@ int load_initrd(char *filename, void *buf, int size) { int fd, n; - if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){ - printk("Opening '%s' failed - errno = %d\n", filename, errno); + fd = os_open_file(filename, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Opening '%s' failed - err = %d\n", filename, -fd); return(-1); } - if((n = read(fd, buf, size)) != size){ - printk("Read of %d bytes from '%s' returned %d, errno = %d\n", - size, filename, n, errno); + n = os_read_file(fd, buf, size); + if(n != size){ + printk("Read of %d bytes from '%s' failed, err = %d\n", size, + filename, -n); return(-1); } return(0); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 0e968bb11..9d572b6ff 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -18,9 +18,10 @@ #include "linux/proc_fs.h" #include "linux/init.h" #include "linux/seq_file.h" +#include "linux/profile.h" +#include "linux/hardirq.h" #include "asm/irq.h" #include "asm/hw_irq.h" -#include "asm/hardirq.h" #include "asm/atomic.h" #include "asm/signal.h" #include "asm/system.h" @@ -29,246 +30,54 @@ #include "user_util.h" #include "kern_util.h" #include "irq_user.h" +#include "irq_kern.h" -static void register_irq_proc (unsigned int irq); - -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - } -}; - -/* - * Generic no controller code - */ - -static void enable_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } -static void disable_none(unsigned int irq) { } -static void ack_none(unsigned int irq) -{ -/* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves, it doesn't deserve - * a generic callback i think. - */ -#ifdef CONFIG_X86 - printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); -#ifdef CONFIG_X86_LOCAL_APIC - /* - * Currently unexpected vectors happen only on SMP and APIC. - * We _must_ ack these because every local APIC has only N - * irq slots per priority level, and a 'hanging, unacked' IRQ - * holds up an irq slot - in excessive cases (when multiple - * unexpected vectors occur) that might lock up the APIC - * completely. - */ - ack_APIC_irq(); -#endif -#endif -} - -/* startup is the same as "enable", shutdown is same as "disable" */ -#define shutdown_none disable_none -#define end_none enable_none - -struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none -}; - -/* Not changed */ -volatile unsigned long irq_err_count; /* * Generic, controller-independent functions: */ -int get_irq_list(char *buf) +int show_interrupts(struct seq_file *p, void *v) { - int i, j; - unsigned long flags; + int i = *(loff_t *) v, j; struct irqaction * action; - char *p = buf; + unsigned long flags; - p += sprintf(p, " "); - for (j=0; jtypename); - p += sprintf(p, " %s", action->name); + seq_printf(p, " %14s", irq_desc[i].handler->typename); + seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) - p += sprintf(p, ", %s", action->name); - *p++ = '\n'; - end: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - p += sprintf(p, "\n"); -#ifdef notdef -#ifdef CONFIG_SMP - p += sprintf(p, "LOC: "); - for (j = 0; j < num_online_cpus(); j++) - p += sprintf(p, "%10u ", - apic_timer_irqs[cpu_logical_map(j)]); - p += sprintf(p, "\n"); -#endif -#endif - p += sprintf(p, "ERR: %10lu\n", irq_err_count); - return p - buf; -} - - -int show_interrupts(struct seq_file *p, void *v) -{ - return(0); -} - -/* - * This should really return information about whether - * we should do bottom half handling etc. Right now we - * end up _always_ checking the bottom half, which is a - * waste of time and is not what some drivers would - * prefer. - */ -int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, - struct irqaction * action) -{ - int status = 1; /* Force the "do bottom halves" bit */ - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); + seq_printf(p, ", %s", action->name); - do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - - local_irq_disable(); - - return status; -} - -/* - * 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 of an interrupt - * stack. 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. - */ - -inline void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_putc(p, '\n'); } - spin_unlock_irqrestore(&desc->lock, flags); -} -#ifdef CONFIG_SMP -inline void synchronize_irq(unsigned int irq) -{ - /* is there anything to synchronize with? */ - if (!irq_desc[irq].action) - return; - - while (irq_desc[irq].status & IRQ_INPROGRESS) - cpu_relax(); -} -#endif - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables of an interrupt - * stack. That is for two disables you need two enables. 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. - */ - -void disable_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - synchronize_irq(irq); -} - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line - * providing no disable_irq calls are now in effect. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk(KERN_ERR "enable_irq() unbalanced from %p\n", - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); + return 0; } /* @@ -277,416 +86,30 @@ void enable_irq(unsigned int irq) * handlers). */ unsigned int do_IRQ(int irq, union uml_pt_regs *regs) -{ - /* - * 0 return value means that this irq is already being - * handled by some other CPU. (or is disabled) - */ - int cpu = smp_processor_id(); - irq_desc_t *desc = irq_desc + irq; - struct irqaction * action; - unsigned int status; - - irq_enter(); - kstat_cpu(cpu).irqs[irq]++; - spin_lock(&desc->lock); - desc->handler->ack(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - status |= IRQ_PENDING; /* we _want_ to handle it */ - - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - action = desc->action; - status &= ~IRQ_PENDING; /* we commit to handling */ - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; - - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (!action) - goto out; - - /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. - */ - for (;;) { - spin_unlock(&desc->lock); - handle_IRQ_event(irq, (struct pt_regs *) regs, action); - spin_lock(&desc->lock); - - if (!(desc->status & IRQ_PENDING)) - break; - desc->status &= ~IRQ_PENDING; - } - desc->status &= ~IRQ_INPROGRESS; -out: - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - desc->handler->end(irq); - spin_unlock(&desc->lock); - - irq_exit(); - - return 1; -} - -/** - * 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 - * - */ - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) { - int retval; - struct irqaction * action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk(KERN_ERR "Bad boy: %s (at 0x%x) called us " - "without a dev_id!\n", devname, (&irq)[-1]); - } -#endif - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; + irq_enter(); + __do_IRQ(irq, (struct pt_regs *) regs); + irq_exit(); + return 1; } -EXPORT_SYMBOL(request_irq); - int um_request_irq(unsigned int irq, int fd, int type, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { - int retval; + int err; - retval = request_irq(irq, handler, irqflags, devname, dev_id); - if(retval) return(retval); - return(activate_fd(irq, fd, type, dev_id)); -} - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - unsigned long flags; - struct irqaction *old, **p; - irq_desc_t *desc = irq_desc + irq; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~IRQ_DISABLED; - desc->handler->startup(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); + err = request_irq(irq, handler, irqflags, devname, dev_id); + if(err) + return(err); - register_irq_proc(irq); - return 0; -} - -/** - * 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. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - desc->handler->shutdown(irq); - } - free_irq_by_irq_and_dev(irq, dev_id); - spin_unlock_irqrestore(&desc->lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - synchronize_irq(irq); - kfree(action); - return; - } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; - } -} - -EXPORT_SYMBOL(free_irq); - -/* These are initialized by sysctl_init, which is called from init/main.c */ -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; -static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; - -/* These are read and written as longs, so a read won't see a partial write - * even during a race. - */ -static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; - -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -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; - cpumask_t new_value, tmp; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(buffer, count, new_value); - -#ifdef CONFIG_SMP - /* - * 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. - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; -#endif - - irq_affinity[irq] = new_value; - irq_desc[irq].handler->set_affinity(irq, new_value); - - return full_count; -} - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, - unsigned long count, void *data) -{ - cpumask_t *mask = (cpumask_t *)data, new_value; - unsigned long full_count = count, err; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - struct proc_dir_entry *entry; - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || - irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - - /* 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; - - smp_affinity_entry[irq] = entry; -} - -/* Read and written as a long */ -cpumask_t prof_cpu_mask = CPU_MASK_ALL; - -void __init init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); + if(fd != -1) + err = activate_fd(irq, fd, type, dev_id); + return(err); } +EXPORT_SYMBOL(um_request_irq); +EXPORT_SYMBOL(reactivate_fd); static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED; @@ -703,90 +126,27 @@ void irq_unlock(unsigned long flags) spin_unlock_irqrestore(&irq_spinlock, flags); } -unsigned long probe_irq_on(void) -{ - return(0); -} - -EXPORT_SYMBOL(probe_irq_on); - -int probe_irq_off(unsigned long val) -{ - return(0); -} - -EXPORT_SYMBOL(probe_irq_off); - -static unsigned int startup_SIGIO_irq(unsigned int irq) -{ - return(0); -} - -static void shutdown_SIGIO_irq(unsigned int irq) -{ -} - -static void enable_SIGIO_irq(unsigned int irq) -{ -} - -static void disable_SIGIO_irq(unsigned int irq) -{ -} - -static void mask_and_ack_SIGIO(unsigned int irq) -{ -} - -static void end_SIGIO_irq(unsigned int irq) -{ -} - -static unsigned int startup_SIGVTALRM_irq(unsigned int irq) -{ - return(0); -} - -static void shutdown_SIGVTALRM_irq(unsigned int irq) -{ -} - -static void enable_SIGVTALRM_irq(unsigned int irq) -{ -} - -static void disable_SIGVTALRM_irq(unsigned int irq) -{ -} - -static void mask_and_ack_SIGVTALRM(unsigned int irq) -{ -} - -static void end_SIGVTALRM_irq(unsigned int irq) +/* presently hw_interrupt_type must define (startup || enable) && + * disable && end */ +static void dummy(unsigned int irq) { } static struct hw_interrupt_type SIGIO_irq_type = { - "SIGIO", - startup_SIGIO_irq, - shutdown_SIGIO_irq, - enable_SIGIO_irq, - disable_SIGIO_irq, - mask_and_ack_SIGIO, - end_SIGIO_irq, - NULL + .typename = "SIGIO", + .disable = dummy, + .enable = dummy, + .ack = dummy, + .end = dummy }; static struct hw_interrupt_type SIGVTALRM_irq_type = { - "SIGVTALRM", - startup_SIGVTALRM_irq, - shutdown_SIGVTALRM_irq, - enable_SIGVTALRM_irq, - disable_SIGVTALRM_irq, - mask_and_ack_SIGVTALRM, - end_SIGVTALRM_irq, - NULL + .typename = "SIGVTALRM", + .shutdown = dummy, /* never called */ + .disable = dummy, + .enable = dummy, + .ack = dummy, + .end = dummy }; void __init init_IRQ(void) diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c index 57fe9bb72..ba4900413 100644 --- a/arch/um/kernel/irq_user.c +++ b/arch/um/kernel/irq_user.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -49,7 +48,8 @@ void sigio_handler(int sig, union uml_pt_regs *regs) if(smp_sigio_handler()) return; while(1){ - if((n = poll(pollfds, pollfds_num, 0)) < 0){ + n = poll(pollfds, pollfds_num, 0); + if(n < 0){ if(errno == EINTR) continue; printk("sigio_handler : poll returned %d, " "errno = %d\n", n, errno); @@ -263,7 +263,7 @@ static int same_irq_and_dev(struct irq_fd *irq, void *d) return((irq->irq == data->irq) && (irq->id == data->dev)); } -void free_irq_by_irq_and_dev(int irq, void *dev) +void free_irq_by_irq_and_dev(unsigned int irq, void *dev) { struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, .dev = dev }); @@ -364,36 +364,47 @@ void deactivate_fd(int fd, int irqnum) irq_unlock(flags); } -void forward_ipi(int fd, int pid) +int deactivate_all_fds(void) { - if(fcntl(fd, F_SETOWN, pid) < 0){ - int save_errno = errno; - if(fcntl(fd, F_GETOWN, 0) != pid){ - printk("forward_ipi: F_SETOWN failed, fd = %d, " - "me = %d, target = %d, errno = %d\n", fd, - os_getpid(), pid, save_errno); - } + struct irq_fd *irq; + int err; + + for(irq=active_fds;irq != NULL;irq = irq->next){ + err = os_clear_fd_async(irq->fd); + if(err) + return(err); } + + return(0); +} + +void forward_ipi(int fd, int pid) +{ + int err; + + err = os_set_owner(fd, pid); + if(err < 0) + printk("forward_ipi: set_owner failed, fd = %d, me = %d, " + "target = %d, err = %d\n", fd, os_getpid(), pid, -err); } void forward_interrupts(int pid) { struct irq_fd *irq; unsigned long flags; + int err; flags = irq_lock(); for(irq=active_fds;irq != NULL;irq = irq->next){ - if(fcntl(irq->fd, F_SETOWN, pid) < 0){ - int save_errno = errno; - if(fcntl(irq->fd, F_GETOWN, 0) != pid){ - /* XXX Just remove the irq rather than - * print out an infinite stream of these - */ - printk("Failed to forward %d to pid %d, " - "errno = %d\n", irq->fd, pid, - save_errno); - } + err = os_set_owner(irq->fd, pid); + if(err < 0){ + /* XXX Just remove the irq rather than + * print out an infinite stream of these + */ + printk("Failed to forward %d to pid %d, err = %d\n", + irq->fd, pid, -err); } + irq->pid = pid; } irq_unlock(flags); diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 1f82ad73a..a867e18c6 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -8,7 +8,7 @@ #include "linux/string.h" #include "linux/smp_lock.h" #include "linux/spinlock.h" -#include +#include "linux/highmem.h" #include "asm/current.h" #include "asm/delay.h" #include "asm/processor.h" @@ -19,6 +19,7 @@ #include "asm/tlbflush.h" #include "kern_util.h" #include "user_util.h" +#include "mem_user.h" #include "os.h" #include "helper.h" @@ -34,34 +35,67 @@ EXPORT_SYMBOL(task_size); EXPORT_SYMBOL(flush_tlb_range); EXPORT_SYMBOL(host_task_size); EXPORT_SYMBOL(arch_validate); +EXPORT_SYMBOL(get_kmem_end); -EXPORT_SYMBOL(region_pa); -EXPORT_SYMBOL(region_va); -EXPORT_SYMBOL(phys_mem_map); -EXPORT_SYMBOL(page_mem_map); EXPORT_SYMBOL(page_to_phys); EXPORT_SYMBOL(phys_to_page); EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(um_virt_to_phys); +EXPORT_SYMBOL(__virt_to_page); +EXPORT_SYMBOL(to_phys); +EXPORT_SYMBOL(to_virt); EXPORT_SYMBOL(mode_tt); EXPORT_SYMBOL(handle_page_fault); +EXPORT_SYMBOL(find_iomem); +#ifdef CONFIG_MODE_TT +EXPORT_SYMBOL(strncpy_from_user_tt); +EXPORT_SYMBOL(copy_from_user_tt); +EXPORT_SYMBOL(copy_to_user_tt); +#endif + +#ifdef CONFIG_MODE_SKAS +EXPORT_SYMBOL(strncpy_from_user_skas); +EXPORT_SYMBOL(copy_to_user_skas); +EXPORT_SYMBOL(copy_from_user_skas); +#endif +EXPORT_SYMBOL(uml_strdup); + +EXPORT_SYMBOL(os_stat_fd); +EXPORT_SYMBOL(os_stat_file); +EXPORT_SYMBOL(os_access); +EXPORT_SYMBOL(os_print_error); +EXPORT_SYMBOL(os_get_exec_close); +EXPORT_SYMBOL(os_set_exec_close); EXPORT_SYMBOL(os_getpid); EXPORT_SYMBOL(os_open_file); EXPORT_SYMBOL(os_read_file); EXPORT_SYMBOL(os_write_file); EXPORT_SYMBOL(os_seek_file); +EXPORT_SYMBOL(os_lock_file); +EXPORT_SYMBOL(os_ioctl_generic); EXPORT_SYMBOL(os_pipe); EXPORT_SYMBOL(os_file_type); +EXPORT_SYMBOL(os_file_mode); +EXPORT_SYMBOL(os_file_size); +EXPORT_SYMBOL(os_flush_stdout); EXPORT_SYMBOL(os_close_file); +EXPORT_SYMBOL(os_set_fd_async); +EXPORT_SYMBOL(os_set_fd_block); EXPORT_SYMBOL(helper_wait); EXPORT_SYMBOL(os_shutdown_socket); +EXPORT_SYMBOL(os_create_unix_socket); EXPORT_SYMBOL(os_connect_socket); +EXPORT_SYMBOL(os_accept_connection); +EXPORT_SYMBOL(os_rcv_fd); EXPORT_SYMBOL(run_helper); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(do_gettimeofday); +EXPORT_SYMBOL(do_settimeofday); + /* This is here because UML expands open to sys_open, not to a system * call instruction. */ @@ -75,10 +109,10 @@ EXPORT_SYMBOL(sys_wait4); /* required for SMP */ extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); -EXPORT_SYMBOL_NOVERS(__write_lock_failed); +EXPORT_SYMBOL(__write_lock_failed); extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); -EXPORT_SYMBOL_NOVERS(__read_lock_failed); +EXPORT_SYMBOL(__read_lock_failed); #endif @@ -90,3 +124,13 @@ EXPORT_SYMBOL(kunmap_atomic); EXPORT_SYMBOL(kmap_atomic_to_page); #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c index e1fd2c583..301180483 100644 --- a/arch/um/kernel/main.c +++ b/arch/um/kernel/main.c @@ -17,11 +17,16 @@ #include "kern_util.h" #include "mem_user.h" #include "signal_user.h" +#include "time_user.h" +#include "irq_user.h" #include "user.h" #include "init.h" #include "mode.h" #include "choose-mode.h" #include "uml-config.h" +#include "irq_user.h" +#include "time_user.h" +#include "os.h" /* Set in set_stklim, which is called from main and __wrap_malloc. * __wrap_malloc only calls it if main hasn't started. @@ -171,7 +176,7 @@ int main(int argc, char **argv, char **envp) } #define CAN_KMALLOC() \ - (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1)) + (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1)) extern void *__real_malloc(int); diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 84a895c2a..09add571c 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -1,74 +1,66 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include "linux/config.h" -#include "linux/module.h" -#include "linux/types.h" +#include "linux/stddef.h" +#include "linux/kernel.h" #include "linux/mm.h" -#include "linux/fs.h" -#include "linux/init.h" #include "linux/bootmem.h" #include "linux/swap.h" -#include "linux/slab.h" -#include "linux/vmalloc.h" #include "linux/highmem.h" +#include "linux/gfp.h" #include "asm/page.h" -#include "asm/pgtable.h" +#include "asm/fixmap.h" #include "asm/pgalloc.h" -#include "asm/bitops.h" -#include "asm/uaccess.h" -#include "asm/tlb.h" #include "user_util.h" #include "kern_util.h" -#include "mem_user.h" -#include "mem.h" #include "kern.h" -#include "init.h" -#include "os.h" -#include "mode_kern.h" +#include "mem_user.h" #include "uml_uaccess.h" +#include "os.h" + +extern char __binary_start; /* Changed during early boot */ -pgd_t swapper_pg_dir[1024]; -unsigned long high_physmem; -unsigned long vm_start; -unsigned long vm_end; -unsigned long highmem; unsigned long *empty_zero_page = NULL; unsigned long *empty_bad_page = NULL; - -/* Not modified */ -const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; - -extern char __init_begin, __init_end; -extern long physmem_size; - -/* Not changed by UML */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -/* Changed during early boot */ +pgd_t swapper_pg_dir[1024]; +unsigned long highmem; int kmalloc_ok = 0; -#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1) -struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL }; -#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1) - -/* Changed during early boot */ static unsigned long brk_end; +void unmap_physmem(void) +{ + os_unmap_memory((void *) brk_end, uml_reserved - brk_end); +} + static void map_cb(void *unused) { map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); } -void unmap_physmem(void) +#ifdef CONFIG_HIGHMEM +static void setup_highmem(unsigned long highmem_start, + unsigned long highmem_len) { - os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -} + struct page *page; + unsigned long highmem_pfn; + int i; -extern char __binary_start; + highmem_start_page = virt_to_page(highmem_start); + + highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; + for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ + page = &mem_map[highmem_pfn + i]; + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + set_page_count(page, 1); + __free_page(page); + } +} +#endif void mem_init(void) { @@ -103,50 +95,15 @@ void mem_init(void) totalhigh_pages = highmem >> PAGE_SHIFT; totalram_pages += totalhigh_pages; num_physpages = totalram_pages; - max_mapnr = totalram_pages; max_pfn = totalram_pages; printk(KERN_INFO "Memory: %luk available\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); kmalloc_ok = 1; -} - -/* Changed during early boot */ -static unsigned long kmem_top = 0; - -unsigned long get_kmem_end(void) -{ - if(kmem_top == 0) - kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); - return(kmem_top); -} - -void set_kmem_end(unsigned long new) -{ - kmem_top = new; -} #ifdef CONFIG_HIGHMEM -/* Changed during early boot */ -pte_t *kmap_pte; -pgprot_t kmap_prot; - -EXPORT_SYMBOL(kmap_prot); -EXPORT_SYMBOL(kmap_pte); - -#define kmap_get_fixmap_pte(vaddr) \ - pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) - -void __init kmap_init(void) -{ - unsigned long kmap_vstart; - - /* cache the first kmap pte */ - kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); - kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - - kmap_prot = PAGE_KERNEL; + setup_highmem(end_iomem, highmem); +#endif } -#endif /* CONFIG_HIGHMEM */ static void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) @@ -178,76 +135,24 @@ static void __init fixrange_init(unsigned long start, unsigned long end, } } -int init_maps(struct mem_region *region) -{ - struct page *p, *map; - int i, n, len; - - if(region == &physmem_region){ - region->mem_map = mem_map; - return(0); - } - else if(region->mem_map != NULL) return(0); - - n = region->len >> PAGE_SHIFT; - len = n * sizeof(struct page); - if(kmalloc_ok){ - map = kmalloc(len, GFP_KERNEL); - if(map == NULL) map = vmalloc(len); - } - else map = alloc_bootmem_low_pages(len); - - if(map == NULL) - return(-ENOMEM); - for(i = 0; i < n; i++){ - p = &map[i]; - set_page_count(p, 0); - SetPageReserved(p); - INIT_LIST_HEAD(&p->list); - } - region->mem_map = map; - return(0); -} +#if CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; -DECLARE_MUTEX(regions_sem); +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) -static int setup_one_range(int fd, char *driver, unsigned long start, - unsigned long pfn, int len, - struct mem_region *region) +void __init kmap_init(void) { - int i; - - down(®ions_sem); - for(i = 0; i < NREGIONS; i++){ - if(regions[i] == NULL) break; - } - if(i == NREGIONS){ - printk("setup_range : no free regions\n"); - i = -1; - goto out; - } - - if(fd == -1) - fd = create_mem_file(len); + unsigned long kmap_vstart; - if(region == NULL){ - region = alloc_bootmem_low_pages(sizeof(*region)); - if(region == NULL) - panic("Failed to allocating mem_region"); - } + /* cache the first kmap pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - *region = ((struct mem_region) { .driver = driver, - .start_pfn = pfn, - .start = start, - .len = len, - .fd = fd } ); - regions[i] = region; - out: - up(®ions_sem); - return(i); + kmap_prot = PAGE_KERNEL; } -#ifdef CONFIG_HIGHMEM static void init_highmem(void) { pgd_t *pgd; @@ -268,63 +173,20 @@ static void init_highmem(void) kmap_init(); } - -void setup_highmem(unsigned long len) -{ - struct mem_region *region; - struct page *page, *map; - unsigned long phys; - int i, cur, index; - - phys = physmem_size; - do { - cur = min(len, (unsigned long) REGION_SIZE); - i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur, - NULL); - if(i == -1){ - printk("setup_highmem - setup_one_range failed\n"); - return; - } - region = regions[i]; - index = phys / PAGE_SIZE; - region->mem_map = &mem_map[index]; - - map = region->mem_map; - for(i = 0; i < (cur >> PAGE_SHIFT); i++){ - page = &map[i]; - ClearPageReserved(page); - set_bit(PG_highmem, &page->flags); - set_page_count(page, 1); - __free_page(page); - } - phys += cur; - len -= cur; - } while(len > 0); -} -#endif +#endif /* CONFIG_HIGHMEM */ void paging_init(void) { - struct mem_region *region; - unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr; - int i, index; + unsigned long zones_size[MAX_NR_ZONES], vaddr; + int i; empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); for(i=0;i> PAGE_SHIFT) - - (uml_physmem >> PAGE_SHIFT); + zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); zones_size[2] = highmem >> PAGE_SHIFT; free_area_init(zones_size); - start = phys_region_index(__pa(uml_physmem)); - end = phys_region_index(__pa(high_physmem - 1)); - for(i = start; i <= end; i++){ - region = regions[i]; - index = (region->start - uml_physmem) / PAGE_SIZE; - region->mem_map = &mem_map[index]; - if(i > start) free_bootmem(__pa(region->start), region->len); - } /* * Fixed mappings, only the page table structure has to be @@ -335,15 +197,33 @@ void paging_init(void) #ifdef CONFIG_HIGHMEM init_highmem(); - setup_highmem(highmem); #endif } -pte_t __bad_page(void) +struct page *arch_validate(struct page *page, int mask, int order) { - clear_page(empty_bad_page); - return pte_mkdirty(mk_pte((struct page *) empty_bad_page, - PAGE_SHARED)); + unsigned long addr, zero = 0; + int i; + + again: + if(page == NULL) return(page); + if(PageHighMem(page)) return(page); + + addr = (unsigned long) page_address(page); + for(i = 0; i < (1 << order); i++){ + current->thread.fault_addr = (void *) addr; + if(__do_copy_to_user((void *) addr, &zero, + sizeof(zero), + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)){ + if(!(mask & __GFP_WAIT)) return(NULL); + else break; + } + addr += PAGE_SIZE; + } + if(i == (1 << order)) return(page); + page = alloc_pages(mask, order); + goto again; } /* This can't do anything because nothing in the kernel image can be freed @@ -401,395 +281,6 @@ void show_mem(void) printk("%d pages swap cached\n", cached); } -static int __init uml_mem_setup(char *line, int *add) -{ - char *retptr; - physmem_size = memparse(line,&retptr); - return 0; -} -__uml_setup("mem=", uml_mem_setup, -"mem=\n" -" This controls how much \"physical\" memory the kernel allocates\n" -" for the system. The size is specified as a number followed by\n" -" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -" This is not related to the amount of memory in the physical\n" -" machine. It can be more, and the excess, if it's ever used, will\n" -" just be swapped out.\n Example: mem=64M\n\n" -); - -struct page *arch_validate(struct page *page, int mask, int order) -{ - unsigned long addr, zero = 0; - int i; - - again: - if(page == NULL) return(page); - if(PageHighMem(page)) return(page); - - addr = (unsigned long) page_address(page); - for(i = 0; i < (1 << order); i++){ - current->thread.fault_addr = (void *) addr; - if(__do_copy_to_user((void *) addr, &zero, - sizeof(zero), - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)){ - if(!(mask & __GFP_WAIT)) return(NULL); - else break; - } - addr += PAGE_SIZE; - } - if(i == (1 << order)) return(page); - page = alloc_pages(mask, order); - goto again; -} - -DECLARE_MUTEX(vm_reserved_sem); -static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved); - -/* Static structures, linked in to the list in early boot */ -static struct vm_reserved head = { - .list = LIST_HEAD_INIT(head.list), - .start = 0, - .end = 0xffffffff -}; - -static struct vm_reserved tail = { - .list = LIST_HEAD_INIT(tail.list), - .start = 0, - .end = 0xffffffff -}; - -void set_usable_vm(unsigned long start, unsigned long end) -{ - list_add(&head.list, &vm_reserved); - list_add(&tail.list, &head.list); - head.end = start; - tail.start = end; -} - -int reserve_vm(unsigned long start, unsigned long end, void *e) - -{ - struct vm_reserved *entry = e, *reserved, *prev; - struct list_head *ele; - int err; - - down(&vm_reserved_sem); - list_for_each(ele, &vm_reserved){ - reserved = list_entry(ele, struct vm_reserved, list); - if(reserved->start >= end) goto found; - } - panic("Reserved vm out of range"); - found: - prev = list_entry(ele->prev, struct vm_reserved, list); - if(prev->end > start) - panic("Can't reserve vm"); - if(entry == NULL) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if(entry == NULL){ - printk("reserve_vm : Failed to allocate entry\n"); - err = -ENOMEM; - goto out; - } - *entry = ((struct vm_reserved) - { .list = LIST_HEAD_INIT(entry->list), - .start = start, - .end = end }); - list_add(&entry->list, &prev->list); - err = 0; - out: - up(&vm_reserved_sem); - return(0); -} - -unsigned long get_vm(unsigned long len) -{ - struct vm_reserved *this, *next; - struct list_head *ele; - unsigned long start; - int err; - - down(&vm_reserved_sem); - list_for_each(ele, &vm_reserved){ - this = list_entry(ele, struct vm_reserved, list); - next = list_entry(ele->next, struct vm_reserved, list); - if((this->start < next->start) && - (this->end + len + PAGE_SIZE <= next->start)) - goto found; - } - up(&vm_reserved_sem); - return(0); - found: - up(&vm_reserved_sem); - start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE; - err = reserve_vm(start, start + len, NULL); - if(err) return(0); - return(start); -} - -int nregions(void) -{ - return(NREGIONS); -} - -void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn, - unsigned long len, int need_vm, struct mem_region *region, - void *reserved) -{ - int i, cur; - - do { - cur = min(len, (unsigned long) REGION_SIZE); - i = setup_one_range(fd, driver, start, pfn, cur, region); - region = regions[i]; - if(need_vm && setup_region(region, reserved)){ - kfree(region); - regions[i] = NULL; - return; - } - start += cur; - if(pfn != -1) pfn += cur; - len -= cur; - } while(len > 0); -} - -struct iomem { - char *name; - int fd; - unsigned long size; -}; - -/* iomem regions can only be added on the command line at the moment. - * Locking will be needed when they can be added via mconsole. - */ - -struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = - { .name = NULL, - .fd = -1, - .size = 0 } }; - -int num_iomem_regions = 0; - -void add_iomem(char *name, int fd, unsigned long size) -{ - if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0])) - return; - size = (size + PAGE_SIZE - 1) & PAGE_MASK; - iomem_regions[num_iomem_regions++] = - ((struct iomem) { .name = name, - .fd = fd, - .size = size } ); -} - -int setup_iomem(void) -{ - struct iomem *iomem; - int i; - - for(i = 0; i < num_iomem_regions; i++){ - iomem = &iomem_regions[i]; - setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1, - NULL, NULL); - } - return(0); -} - -__initcall(setup_iomem); - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - -/* Changed during early boot */ -static struct mem_region physmem_region; -static struct vm_reserved physmem_reserved; - -void setup_physmem(unsigned long start, unsigned long reserve_end, - unsigned long len) -{ - struct mem_region *region = &physmem_region; - struct vm_reserved *reserved = &physmem_reserved; - unsigned long cur, pfn = 0; - int do_free = 1, bootmap_size; - - do { - cur = min(len, (unsigned long) REGION_SIZE); - if(region == NULL) - region = alloc_bootmem_low_pages(sizeof(*region)); - if(reserved == NULL) - reserved = alloc_bootmem_low_pages(sizeof(*reserved)); - if((region == NULL) || (reserved == NULL)) - panic("Couldn't allocate physmem region or vm " - "reservation\n"); - setup_range(-1, NULL, start, pfn, cur, 1, region, reserved); - - if(do_free){ - unsigned long reserve = reserve_end - start; - int pfn = PFN_UP(__pa(reserve_end)); - int delta = (len - reserve) >> PAGE_SHIFT; - - bootmap_size = init_bootmem(pfn, pfn + delta); - free_bootmem(__pa(reserve_end) + bootmap_size, - cur - bootmap_size - reserve); - do_free = 0; - } - start += cur; - pfn += cur >> PAGE_SHIFT; - len -= cur; - region = NULL; - reserved = NULL; - } while(len > 0); -} - -struct mem_region *phys_region(unsigned long phys) -{ - unsigned int n = phys_region_index(phys); - - if(regions[n] == NULL) - panic("Physical address in uninitialized region"); - return(regions[n]); -} - -unsigned long phys_offset(unsigned long phys) -{ - return(phys_addr(phys)); -} - -struct page *phys_mem_map(unsigned long phys) -{ - return((struct page *) phys_region(phys)->mem_map); -} - -struct page *pte_mem_map(pte_t pte) -{ - return(phys_mem_map(pte_val(pte))); -} - -struct mem_region *page_region(struct page *page, int *index_out) -{ - int i; - struct mem_region *region; - struct page *map; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) continue; - map = region->mem_map; - if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){ - if(index_out != NULL) *index_out = i; - return(region); - } - } - panic("No region found for page"); - return(NULL); -} - -unsigned long page_to_pfn(struct page *page) -{ - struct mem_region *region = page_region(page, NULL); - - return(region->start_pfn + (page - (struct page *) region->mem_map)); -} - -struct mem_region *pfn_to_region(unsigned long pfn, int *index_out) -{ - struct mem_region *region; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) - continue; - - if((region->start_pfn <= pfn) && - (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){ - if(index_out != NULL) - *index_out = i; - return(region); - } - } - return(NULL); -} - -struct page *pfn_to_page(unsigned long pfn) -{ - struct mem_region *region = pfn_to_region(pfn, NULL); - struct page *mem_map = (struct page *) region->mem_map; - - return(&mem_map[pfn - region->start_pfn]); -} - -unsigned long phys_to_pfn(unsigned long p) -{ - struct mem_region *region = regions[phys_region_index(p)]; - - return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT)); -} - -unsigned long pfn_to_phys(unsigned long pfn) -{ - int n; - struct mem_region *region = pfn_to_region(pfn, &n); - - return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n)); -} - -struct page *page_mem_map(struct page *page) -{ - return((struct page *) page_region(page, NULL)->mem_map); -} - -extern unsigned long region_pa(void *virt) -{ - struct mem_region *region; - unsigned long addr = (unsigned long) virt; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) continue; - if((region->start <= addr) && - (addr <= region->start + region->len)) - return(mk_phys(addr - region->start, i)); - } - panic("region_pa : no region for virtual address"); - return(0); -} - -extern void *region_va(unsigned long phys) -{ - return((void *) (phys_region(phys)->start + phys_addr(phys))); -} - -unsigned long page_to_phys(struct page *page) -{ - int n; - struct mem_region *region = page_region(page, &n); - struct page *map = region->mem_map; - return(mk_phys((page - map) << PAGE_SHIFT, n)); -} - -struct page *phys_to_page(unsigned long phys) -{ - struct page *mem_map; - - mem_map = phys_mem_map(phys); - return(mem_map + (phys_offset(phys) >> PAGE_SHIFT)); -} - -static int setup_mem_maps(void) -{ - struct mem_region *region; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if((region != NULL) && (region->fd > 0)) init_maps(region); - } - return(0); -} - -__initcall(setup_mem_maps); - /* * Allocate and free page tables. */ diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c index d90345b5f..67357fa51 100644 --- a/arch/um/kernel/mem_user.c +++ b/arch/um/kernel/mem_user.c @@ -34,10 +34,9 @@ #include #include #include -#include #include #include -#include +#include #include #include #include "kern_util.h" @@ -47,105 +46,167 @@ #include "init.h" #include "os.h" #include "tempfile.h" +#include "kern_constants.h" extern struct mem_region physmem_region; #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" -int create_mem_file(unsigned long len) +static int create_tmp_file(unsigned long len) { - int fd; + int fd, err; char zero; fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); - if (fchmod(fd, 0777) < 0){ - perror("fchmod"); + if(fd < 0) { + os_print_error(fd, "make_tempfile"); exit(1); } - if(os_seek_file(fd, len) < 0){ - perror("lseek"); + + err = os_mode_fd(fd, 0777); + if(err < 0){ + os_print_error(err, "os_mode_fd"); + exit(1); + } + err = os_seek_file(fd, len); + if(err < 0){ + os_print_error(err, "os_seek_file"); exit(1); } zero = 0; - if(write(fd, &zero, 1) != 1){ - perror("write"); + err = os_write_file(fd, &zero, 1); + if(err != 1){ + os_print_error(err, "os_write_file"); exit(1); } - if(fcntl(fd, F_SETFD, 1) != 0) - perror("Setting FD_CLOEXEC failed"); + return(fd); } -int setup_region(struct mem_region *region, void *entry) +void check_tmpexec(void) { - void *loc, *start; - char *driver; - int err, offset; - - if(region->start != -1){ - err = reserve_vm(region->start, - region->start + region->len, entry); - if(err){ - printk("setup_region : failed to reserve " - "0x%x - 0x%x for driver '%s'\n", - region->start, - region->start + region->len, - region->driver); - return(-1); - } - } - else region->start = get_vm(region->len); - if(region->start == 0){ - if(region->driver == NULL) driver = "physmem"; - else driver = region->driver; - printk("setup_region : failed to find vm for " - "driver '%s' (length %d)\n", driver, region->len); - return(-1); + void *addr; + int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); + + addr = mmap(NULL, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); + printf("Checking PROT_EXEC mmap in /tmp..."); + fflush(stdout); + if(addr == MAP_FAILED){ + err = errno; + perror("failed"); + if(err == EPERM) + printf("/tmp must be not mounted noexec\n"); + exit(1); } - if(region->start == uml_physmem){ - start = (void *) uml_reserved; - offset = uml_reserved - uml_physmem; + printf("OK\n"); + munmap(addr, UM_KERN_PAGE_SIZE); +} + +static int have_devanon = 0; + +void check_devanon(void) +{ + int fd; + + printk("Checking for /dev/anon on the host..."); + fd = open("/dev/anon", O_RDWR); + if(fd < 0){ + printk("Not available (open failed with errno %d)\n", errno); + return; } - else { - start = (void *) region->start; - offset = 0; + + printk("OK\n"); + have_devanon = 1; +} + +static int create_anon_file(unsigned long len) +{ + void *addr; + int fd; + + fd = open("/dev/anon", O_RDWR); + if(fd < 0) { + os_print_error(fd, "opening /dev/anon"); + exit(1); } - loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_FIXED, region->fd, offset); - if(loc != start){ - perror("Mapping memory"); + addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if(addr == MAP_FAILED){ + os_print_error((int) addr, "mapping physmem file"); exit(1); } - return(0); + munmap(addr, len); + + return(fd); +} + +int create_mem_file(unsigned long len) +{ + int err, fd; + + if(have_devanon) + fd = create_anon_file(len); + else fd = create_tmp_file(len); + + err = os_set_exec_close(fd, 1); + if(err < 0) + os_print_error(err, "exec_close"); + return(fd); } +struct iomem_region *iomem_regions = NULL; +int iomem_size = 0; + static int __init parse_iomem(char *str, int *add) { - struct stat buf; + struct iomem_region *new; + struct uml_stat buf; char *file, *driver; - int fd; + int fd, err, size; driver = str; file = strchr(str,','); if(file == NULL){ - printk("parse_iomem : failed to parse iomem\n"); - return(1); + printf("parse_iomem : failed to parse iomem\n"); + goto out; } *file = '\0'; file++; fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); if(fd < 0){ - printk("parse_iomem - Couldn't open io file, errno = %d\n", - errno); - return(1); + os_print_error(fd, "parse_iomem - Couldn't open io file"); + goto out; } - if(fstat(fd, &buf) < 0) { - printk("parse_iomem - cannot fstat file, errno = %d\n", errno); - return(1); + + err = os_stat_fd(fd, &buf); + if(err < 0){ + os_print_error(err, "parse_iomem - cannot stat_fd file"); + goto out_close; } - add_iomem(driver, fd, buf.st_size); + + new = malloc(sizeof(*new)); + if(new == NULL){ + perror("Couldn't allocate iomem_region struct"); + goto out_close; + } + + size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); + + *new = ((struct iomem_region) { .next = iomem_regions, + .driver = driver, + .fd = fd, + .size = size, + .phys = 0, + .virt = 0 }); + iomem_regions = new; + iomem_size += new->size + UM_KERN_PAGE_SIZE; + return(0); + out_close: + os_close_file(fd); + out: + return(1); } __uml_setup("iomem=", parse_iomem, @@ -153,72 +214,52 @@ __uml_setup("iomem=", parse_iomem, " Configure as an IO memory region named .\n\n" ); -#ifdef notdef -int logging = 0; -int logging_fd = -1; - -int logging_line = 0; -char logging_buf[256]; - -void log(char *fmt, ...) -{ - va_list ap; - struct timeval tv; - struct openflags flags; - - if(logging == 0) return; - if(logging_fd < 0){ - flags = of_create(of_trunc(of_rdrw(OPENFLAGS()))); - logging_fd = os_open_file("log", flags, 0644); - } - gettimeofday(&tv, NULL); - sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, - tv.tv_usec); - va_start(ap, fmt); - vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); - va_end(ap); - write(logging_fd, logging_buf, strlen(logging_buf)); -} -#endif - -int map_memory(unsigned long virt, unsigned long phys, unsigned long len, - int r, int w, int x) -{ - struct mem_region *region = phys_region(phys); - - return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len, - r, w, x)); -} - int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed) { - if(os_protect_memory((void *) addr, len, r, w, x) < 0){ + int err; + + err = os_protect_memory((void *) addr, len, r, w, x); + if(err < 0){ if(must_succeed) - panic("protect failed, errno = %d", errno); - else return(-errno); + panic("protect failed, err = %d", -err); + else return(err); } return(0); } -unsigned long find_iomem(char *driver, unsigned long *len_out) +#if 0 +/* Debugging facility for dumping stuff out to the host, avoiding the timing + * problems that come with printf and breakpoints. + * Enable in case of emergency. + */ + +int logging = 1; +int logging_fd = -1; + +int logging_line = 0; +char logging_buf[512]; + +void log(char *fmt, ...) { - struct mem_region *region; - int i, n; - - n = nregions(); - for(i = 0; i < n; i++){ - region = regions[i]; - if(region == NULL) continue; - if((region->driver != NULL) && - !strcmp(region->driver, driver)){ - *len_out = region->len; - return(region->start); - } - } - *len_out = 0; - return 0; + va_list ap; + struct timeval tv; + struct openflags flags; + + if(logging == 0) return; + if(logging_fd < 0){ + flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); + logging_fd = os_open_file("log", flags, 0644); + } + gettimeofday(&tv, NULL); + sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, + tv.tv_usec); + va_start(ap, fmt); + vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); + va_end(ap); + write(logging_fd, logging_buf, strlen(logging_buf)); } +#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index d0e0f50dc..3253bc0e3 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -1,13 +1,14 @@ -/* +/* * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/mm.h" -#include "linux/ghash.h" +#include "linux/rbtree.h" #include "linux/slab.h" #include "linux/vmalloc.h" #include "linux/bootmem.h" +#include "linux/module.h" #include "asm/types.h" #include "asm/pgtable.h" #include "kern_util.h" @@ -19,36 +20,8 @@ #include "kern.h" #include "init.h" -#if 0 -static pgd_t physmem_pgd[PTRS_PER_PGD]; - -static struct phys_desc *lookup_mapping(void *addr) -{ - pgd = &physmem_pgd[pgd_index(addr)]; - if(pgd_none(pgd)) - return(NULL); - - pmd = pmd_offset(pgd, addr); - if(pmd_none(pmd)) - return(NULL); - - pte = pte_offset_kernel(pmd, addr); - return((struct phys_desc *) pte_val(pte)); -} - -static struct add_mapping(void *addr, struct phys_desc *new) -{ -} -#endif - -#define PHYS_HASHSIZE (8192) - -struct phys_desc; - -DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc); - struct phys_desc { - struct virtmem_ptrs virt_ptrs; + struct rb_node rb; int fd; __u64 offset; void *virt; @@ -56,21 +29,48 @@ struct phys_desc { struct list_head list; }; -struct virtmem_table virtmem_hash; +static struct rb_root phys_mappings = RB_ROOT; -static int virt_cmp(void *virt1, void *virt2) +static struct rb_node **find_rb(void *virt) { - return(virt1 != virt2); + struct rb_node **n = &phys_mappings.rb_node; + struct phys_desc *d; + + while(*n != NULL){ + d = rb_entry(*n, struct phys_desc, rb); + if(d->virt == virt) + return(n); + + if(d->virt > virt) + n = &(*n)->rb_left; + else + n = &(*n)->rb_right; + } + + return(n); } -static int virt_hash(void *virt) +static struct phys_desc *find_phys_mapping(void *virt) { - unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT; - return(addr % PHYS_HASHSIZE); + struct rb_node **n = find_rb(virt); + + if(*n == NULL) + return(NULL); + + return(rb_entry(*n, struct phys_desc, rb)); } -DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, - virt_hash); +static void insert_phys_mapping(struct phys_desc *desc) +{ + struct rb_node **n = find_rb(desc->virt); + + if(*n != NULL) + panic("Physical remapping for %p already present", + desc->virt); + + rb_link_node(&desc->rb, (*n)->rb_parent, n); + rb_insert_color(&desc->rb, &phys_mappings); +} LIST_HEAD(descriptor_mappings); @@ -106,7 +106,7 @@ static struct desc_mapping *descriptor_mapping(int fd) if(desc == NULL) return(NULL); - *desc = ((struct desc_mapping) + *desc = ((struct desc_mapping) { .fd = fd, .list = LIST_HEAD_INIT(desc->list), .pages = LIST_HEAD_INIT(desc->pages) }); @@ -127,7 +127,8 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) return(-ENOMEM); phys = __pa(virt); - if(find_virtmem_hash(&virtmem_hash, virt) != NULL) + desc = find_phys_mapping(virt); + if(desc != NULL) panic("Address 0x%p is already substituted\n", virt); err = -ENOMEM; @@ -135,14 +136,13 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) if(desc == NULL) goto out; - *desc = ((struct phys_desc) - { .virt_ptrs = { NULL, NULL }, - .fd = fd, + *desc = ((struct phys_desc) + { .fd = fd, .offset = offset, .virt = virt, .phys = __pa(virt), .list = LIST_HEAD_INIT(desc->list) }); - insert_virtmem_hash(&virtmem_hash, desc); + insert_phys_mapping(desc); list_add(&desc->list, &fd_maps->pages); @@ -151,7 +151,7 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) if(!err) goto out; - remove_virtmem_hash(&virtmem_hash, desc); + rb_erase(&desc->rb, &phys_mappings); kfree(desc); out: return(err); @@ -164,7 +164,7 @@ static void remove_mapping(struct phys_desc *desc) void *virt = desc->virt; int err; - remove_virtmem_hash(&virtmem_hash, desc); + rb_erase(&desc->rb, &phys_mappings); list_del(&desc->list); kfree(desc); @@ -179,7 +179,7 @@ int physmem_remove_mapping(void *virt) struct phys_desc *desc; virt = (void *) ((unsigned long) virt & PAGE_MASK); - desc = find_virtmem_hash(&virtmem_hash, virt); + desc = find_phys_mapping(virt); if(desc == NULL) return(0); @@ -221,6 +221,10 @@ void physmem_forget_descriptor(int fd) kfree(desc); } +EXPORT_SYMBOL(physmem_forget_descriptor); +EXPORT_SYMBOL(physmem_remove_mapping); +EXPORT_SYMBOL(physmem_subst_mapping); + void arch_free_page(struct page *page, int order) { void *virt; @@ -234,7 +238,9 @@ void arch_free_page(struct page *page, int order) int is_remapped(void *virt) { - return(find_virtmem_hash(&virtmem_hash, virt) != NULL); + struct phys_desc *desc = find_phys_mapping(virt); + + return(desc != NULL); } /* Changed during early boot */ @@ -273,7 +279,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) if(kmalloc_ok){ map = kmalloc(total_len, GFP_KERNEL); - if(map == NULL) + if(map == NULL) map = vmalloc(total_len); } else map = alloc_bootmem_low_pages(total_len); @@ -322,12 +328,12 @@ static unsigned long kmem_top = 0; unsigned long get_kmem_end(void) { - if(kmem_top == 0) + if(kmem_top == 0) kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); return(kmem_top); } -void map_memory(unsigned long virt, unsigned long phys, unsigned long len, +void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x) { __u64 offset; @@ -335,9 +341,14 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, fd = phys_mapping(phys, &offset); err = os_map_memory((void *) virt, fd, offset, len, r, w, x); - if(err) + if(err) { + if(err == -ENOMEM) + printk("try increasing the host's " + "/proc/sys/vm/max_map_count to /4096\n"); panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " "err = %d\n", virt, fd, offset, len, r, w, x, err); + } } #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) @@ -353,7 +364,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, physmem_fd = create_mem_file(len + highmem); offset = uml_reserved - uml_physmem; - err = os_map_memory((void *) uml_reserved, physmem_fd, offset, + err = os_map_memory((void *) uml_reserved, physmem_fd, offset, len - offset, 1, 1, 0); if(err < 0){ os_print_error(err, "Mapping memory"); @@ -367,8 +378,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end, int phys_mapping(unsigned long phys, __u64 *offset_out) { - struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, - __va(phys & PAGE_MASK)); + struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK)); int fd = -1; if(desc != NULL){ @@ -381,9 +391,9 @@ int phys_mapping(unsigned long phys, __u64 *offset_out) } else if(phys < __pa(end_iomem)){ struct iomem_region *region = iomem_regions; - + while(region != NULL){ - if((phys >= region->phys) && + if((phys >= region->phys) && (phys < region->phys + region->size)){ fd = region->fd; *offset_out = phys - region->phys; @@ -419,7 +429,7 @@ __uml_setup("mem=", uml_mem_setup, unsigned long find_iomem(char *driver, unsigned long *len_out) { struct iomem_region *region = iomem_regions; - + while(region != NULL){ if(!strcmp(region->driver, driver)){ *len_out = region->size; @@ -437,7 +447,7 @@ int setup_iomem(void) int err; while(region != NULL){ - err = os_map_memory((void *) iomem_start, region->fd, 0, + err = os_map_memory((void *) iomem_start, region->fd, 0, region->size, 1, 1, 0); if(err) printk("Mapping iomem region for driver '%s' failed, " diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 4c3aa4535..d2f0e82ca 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -9,18 +9,17 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include #include #include #include +#include #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -47,7 +46,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) int flags = 0, pages; if(sig_stack != NULL){ - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; + pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); set_sigstack(sig_stack, pages * page_size()); flags = SA_ONSTACK; } @@ -71,8 +70,7 @@ void init_new_thread_signals(int altstack) set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGUSR2, (__sighandler_t) sig_handler, - SA_NOMASK | flags, -1); - (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0); + flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); signal(SIGHUP, SIG_IGN); init_irq_signals(altstack); @@ -122,36 +120,48 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack, /* Start the process and wait for it to kill itself */ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); - if(new_pid < 0) return(-errno); - while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ; - if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", - errno); - if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) - panic("outer trampoline didn't exit with SIGKILL"); + if(new_pid < 0) + return(new_pid); - return(arg.pid); -} + CATCH_EINTR(err = waitpid(new_pid, &status, 0)); + if(err < 0) + panic("Waiting for outer trampoline failed - errno = %d", + errno); -void suspend_new_thread(int fd) -{ - char c; - - os_stop_process(os_getpid()); + if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) + panic("outer trampoline didn't exit with SIGKILL, " + "status = %d", status); - if(read(fd, &c, sizeof(c)) != sizeof(c)) - panic("read failed in suspend_new_thread"); + return(arg.pid); } static int ptrace_child(void *arg) { - int pid = os_getpid(); + int ret; + int pid = os_getpid(), ppid = getppid(); + int sc_result; if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ perror("ptrace"); os_kill_process(pid, 0); } os_stop_process(pid); - _exit(os_getpid() == pid); + + /*This syscall will be intercepted by the parent. Don't call more than + * once, please.*/ + sc_result = os_getpid(); + + if (sc_result == pid) + ret = 1; /*Nothing modified by the parent, we are running + normally.*/ + else if (sc_result == ppid) + ret = 0; /*Expected in check_ptrace and check_sysemu when they + succeed in modifying the stack frame*/ + else + ret = 2; /*Serious trouble! This could be caused by a bug in + host 2.6 SKAS3/2.6 patch before release -V6, together + with a bug in the UML code itself.*/ + _exit(ret); } static int start_ptraced_child(void **stack_out) @@ -168,7 +178,7 @@ static int start_ptraced_child(void **stack_out) pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); if(pid < 0) panic("check_ptrace : clone failed, errno = %d", errno); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) @@ -179,18 +189,92 @@ static int start_ptraced_child(void **stack_out) return(pid); } -static void stop_ptraced_child(int pid, void *stack, int exitcode) +/* When testing for SYSEMU support, if it is one of the broken versions, we must + * just avoid using sysemu, not panic, but only if SYSEMU features are broken. + * So only for SYSEMU features we test mustpanic, while normal host features + * must work anyway!*/ +static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic) { - int status, n; + int status, n, ret = 0; if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) panic("check_ptrace : ptrace failed, errno = %d", errno); - n = waitpid(pid, &status, 0); - if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) - panic("check_ptrace : child exited with status 0x%x", status); + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { + int exit_with = WEXITSTATUS(status); + if (exit_with == 2) + printk("check_ptrace : child exited with status 2. " + "Serious trouble happening! Try updating your " + "host skas patch!\nDisabling SYSEMU support."); + printk("check_ptrace : child exited with exitcode %d, while " + "expecting %d; status 0x%x", exit_with, + exitcode, status); + if (mustpanic) + panic("\n"); + else + printk("\n"); + ret = -1; + } if(munmap(stack, PAGE_SIZE) < 0) panic("check_ptrace : munmap failed, errno = %d", errno); + return ret; +} + +static int force_sysemu_disabled = 0; + +static int __init nosysemu_cmd_param(char *str, int* add) +{ + force_sysemu_disabled = 1; + return 0; +} + +__uml_setup("nosysemu", nosysemu_cmd_param, + "nosysemu\n" + " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n" + " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n" + " behaviour of ptrace() and helps reducing host context switch rate.\n" + " To make it working, you need a kernel patch for your host, too.\n" + " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n\n"); + +static void __init check_sysemu(void) +{ + void *stack; + int pid, n, status; + + printk("Checking syscall emulation patch for ptrace..."); + sysemu_supported = 0; + pid = start_ptraced_child(&stack); + + if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) + goto fail; + + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + if (n < 0) + panic("check_sysemu : wait failed, errno = %d", errno); + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("check_sysemu : expected SIGTRAP, " + "got status = %d", status); + + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, + os_getpid()); + if(n < 0) + panic("check_sysemu : failed to modify system " + "call return, errno = %d", errno); + + if (stop_ptraced_child(pid, stack, 0, 0) < 0) + goto fail_stopped; + + sysemu_supported = 1; + printk("OK\n"); + set_using_sysemu(!force_sysemu_disabled); + return; + +fail: + stop_ptraced_child(pid, stack, 1, 0); +fail_stopped: + sysemu_supported = 0; + printk("missing\n"); } void __init check_ptrace(void) @@ -205,7 +289,7 @@ void __init check_ptrace(void) if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) panic("check_ptrace : ptrace failed, errno = %d", errno); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) @@ -223,17 +307,18 @@ void __init check_ptrace(void) break; } } - stop_ptraced_child(pid, stack, 0); + stop_ptraced_child(pid, stack, 0, 1); printk("OK\n"); + check_sysemu(); } int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) { - jmp_buf buf; + sigjmp_buf buf; int n; *jmp_ptr = &buf; - n = setjmp(buf); + n = sigsetjmp(buf, 1); if(n != 0) return(n); (*fn)(arg); @@ -270,10 +355,10 @@ int can_do_skas(void) else printf("found\n"); init_registers(pid); - stop_ptraced_child(pid, stack, 1); + stop_ptraced_child(pid, stack, 1, 1); printf("Checking for /proc/mm..."); - if(access("/proc/mm", W_OK)){ + if(os_access("/proc/mm", OS_ACC_W_OK) < 0){ printf("not found\n"); ret = 0; } diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index e17600a9b..18255bd75 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright 2003 PathScale, Inc. * Licensed under the GPL */ @@ -16,6 +17,10 @@ #include "linux/module.h" #include "linux/init.h" #include "linux/capability.h" +#include "linux/vmalloc.h" +#include "linux/spinlock.h" +#include "linux/proc_fs.h" +#include "linux/ptrace.h" #include "asm/unistd.h" #include "asm/mman.h" #include "asm/segment.h" @@ -23,7 +28,6 @@ #include "asm/pgtable.h" #include "asm/processor.h" #include "asm/tlbflush.h" -#include "asm/spinlock.h" #include "asm/uaccess.h" #include "asm/user.h" #include "user_util.h" @@ -52,17 +56,12 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; struct task_struct *get_task(int pid, int require) { - struct task_struct *task, *ret; + struct task_struct *ret; - ret = NULL; read_lock(&tasklist_lock); - for_each_process(task){ - if(task->pid == pid){ - ret = task; - break; - } - } + ret = find_task_by_pid(pid); read_unlock(&tasklist_lock); + if(require && (ret == NULL)) panic("get_task couldn't find a task\n"); return(ret); } @@ -95,7 +94,8 @@ unsigned long alloc_stack(int order, int atomic) int flags = GFP_KERNEL; if(atomic) flags |= GFP_ATOMIC; - if((page = __get_free_pages(flags, order)) == 0) + page = __get_free_pages(flags, order); + if(page == 0) return(0); stack_protections(page); return(page); @@ -103,22 +103,25 @@ unsigned long alloc_stack(int order, int atomic) int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - struct task_struct *p; + int pid; current->thread.request.u.thread.proc = fn; current->thread.request.u.thread.arg = arg; - p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL); - if(IS_ERR(p)) panic("do_fork failed in kernel_thread"); - return(p->pid); + pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL, + NULL); + if(pid < 0) + panic("do_fork failed in kernel_thread, errno = %d", pid); + return(pid); } void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { - unsigned cpu = smp_processor_id(); + int cpu = smp_processor_id(); + if (prev != next) - clear_bit(cpu, &prev->cpu_vm_mask); - set_bit(cpu, &next->cpu_vm_mask); + cpu_clear(cpu, prev->cpu_vm_mask); + cpu_set(cpu, next->cpu_vm_mask); } void set_current(void *t) @@ -129,7 +132,7 @@ void set_current(void *t) { external_pid(task), task }); } -void *switch_to(void *prev, void *next, void *last) +void *_switch_to(void *prev, void *next, void *last) { return(CHOOSE_MODE(switch_to_tt(prev, next), switch_to_skas(prev, next))); @@ -138,7 +141,7 @@ void *switch_to(void *prev, void *next, void *last) void interrupt_end(void) { if(need_resched()) schedule(); - if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(0); + if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal(); } void release_thread(struct task_struct *task) @@ -149,7 +152,7 @@ void release_thread(struct task_struct *task) void exit_thread(void) { CHOOSE_MODE(exit_thread_tt(), exit_thread_skas()); - unprotect_stack((unsigned long) current->thread_info); + unprotect_stack((unsigned long) current_thread); } void *get_current(void) @@ -157,13 +160,15 @@ void *get_current(void) return(current); } +void prepare_to_copy(struct task_struct *tsk) +{ +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { p->thread = (struct thread_struct) INIT_THREAD; - p->thread.kernel_stack = - (unsigned long) p->thread_info + 2 * PAGE_SIZE; return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, clone_flags, sp, stack_top, p, regs)); } @@ -190,7 +195,7 @@ int current_pid(void) void default_idle(void) { - idle_timer(); + uml_idle_timer(); atomic_inc(&init_mm.mm_count); current->mm = &init_mm; @@ -204,7 +209,6 @@ void default_idle(void) * although we are an idle CPU, we do not want to * get into the scheduler unnecessarily. */ - irq_stat[smp_processor_id()].idle_timestamp = jiffies; if(need_resched()) schedule(); @@ -222,7 +226,7 @@ int page_size(void) return(PAGE_SIZE); } -int page_mask(void) +unsigned long page_mask(void) { return(PAGE_MASK); } @@ -299,6 +303,11 @@ void *um_kmalloc_atomic(int size) return(kmalloc(size, GFP_ATOMIC)); } +void *um_vmalloc(int size) +{ + return(vmalloc(size)); +} + unsigned long get_fault_addr(void) { return((unsigned long) current->thread.fault_addr); @@ -318,8 +327,7 @@ int user_context(unsigned long sp) unsigned long stack; stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); - stack += 2 * PAGE_SIZE; - return(stack != current->thread.kernel_stack); + return(stack != (unsigned long) current_thread); } extern void remove_umid_dir(void); @@ -367,10 +375,15 @@ int clear_user_proc(void *buf, int size) return(clear_user(buf, size)); } +int strlen_user_proc(char *str) +{ + return(strlen_user(str)); +} + int smp_sigio_handler(void) { #ifdef CONFIG_SMP - int cpu = current->thread_info->cpu; + int cpu = current_thread->cpu; IPI_handler(cpu); if(cpu != 0) return(1); @@ -385,7 +398,75 @@ int um_in_interrupt(void) int cpu(void) { - return(current->thread_info->cpu); + return(current_thread->cpu); +} + +static atomic_t using_sysemu = ATOMIC_INIT(0); +int sysemu_supported; + +void set_using_sysemu(int value) +{ + atomic_set(&using_sysemu, sysemu_supported && value); +} + +int get_using_sysemu(void) +{ + return atomic_read(&using_sysemu); +} + +static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) +{ + if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ + *eof = 1; + + return strlen(buf); +} + +static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data) +{ + char tmp[2]; + + if (copy_from_user(tmp, buf, 1)) + return -EFAULT; + + if (tmp[0] == '0' || tmp[0] == '1') + set_using_sysemu(tmp[0] - '0'); + return count; /*We use the first char, but pretend to write everything*/ +} + +int __init make_proc_sysemu(void) +{ + struct proc_dir_entry *ent; + if (!sysemu_supported) + return 0; + + ent = create_proc_entry("sysemu", 0600, &proc_root); + + if (ent == NULL) + { + printk("Failed to register /proc/sysemu\n"); + return(0); + } + + ent->read_proc = proc_read_sysemu; + ent->write_proc = proc_write_sysemu; + + return 0; +} + +late_initcall(make_proc_sysemu); + +int singlestepping(void * t) +{ + struct task_struct *task = t ? t : current; + + if ( ! (task->ptrace & PT_DTRACE) ) + return(0); + + if (task->thread.singlestep_syscall) + return(0); + + return 1; } /* diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index c68c937f6..e8caff95d 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -22,14 +22,11 @@ */ void ptrace_disable(struct task_struct *child) { + child->ptrace &= ~PT_DTRACE; + child->thread.singlestep_syscall = 0; } -extern long do_mmap2(struct task_struct *task, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, - unsigned long pgoff); - -int sys_ptrace(long request, long pid, long addr, long data) +long sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int i, ret; @@ -144,6 +141,9 @@ int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; if ((unsigned long) data > _NSIG) break; + + child->ptrace &= ~PT_DTRACE; + child->thread.singlestep_syscall = 0; if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } @@ -163,8 +163,11 @@ int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: { ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; + + child->ptrace &= ~PT_DTRACE; + child->thread.singlestep_syscall = 0; child->exit_code = SIGKILL; wake_up_process(child); break; @@ -176,6 +179,7 @@ int sys_ptrace(long request, long pid, long addr, long data) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->ptrace |= PT_DTRACE; + child->thread.singlestep_syscall = 0; child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -292,7 +296,7 @@ int sys_ptrace(long request, long pid, long addr, long data) } #endif default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: @@ -302,23 +306,34 @@ int sys_ptrace(long request, long pid, long addr, long data) return ret; } -void syscall_trace(void) +void syscall_trace(union uml_pt_regs *regs, int entryexit) { - if (!test_thread_flag(TIF_SYSCALL_TRACE)) + int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; + int tracesysgood; + + if (unlikely(current->audit_context)) { + if (!entryexit) + audit_syscall_entry(current, regs->orig_eax, + regs->ebx, regs->ecx, + regs->edx, regs->esi); + else + audit_syscall_exit(current, regs->eax); + } + + if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_singlestep) return; if (!(current->ptrace & PT_PTRACED)) return; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); - - /* - * this isn't the same as continuing with a signal, but it will do + tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep; + ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); + + /* force do_signal() --> is_syscall() */ + set_thread_flag(TIF_SIGPENDING); + + /* this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the * stopping signal is not SIGTRAP. -brl */ diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 3e4ab2963..207f89d74 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -15,6 +15,7 @@ #ifdef CONFIG_SMP static void kill_idlers(int me) { +#ifdef CONFIG_MODE_TT struct task_struct *p; int i; @@ -23,6 +24,7 @@ static void kill_idlers(int me) if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) os_kill_process(p->thread.mode.tt.extern_pid, 0); } +#endif } #endif diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c index 02272e623..11297378f 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio_kern.c @@ -1,31 +1,38 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/kernel.h" #include "linux/list.h" #include "linux/slab.h" -#include "asm/irq.h" +#include "linux/signal.h" +#include "linux/interrupt.h" #include "init.h" #include "sigio.h" #include "irq_user.h" +#include "irq_kern.h" /* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; -void sigio_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) { read_sigio_fd(sigio_irq_fd); reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); + return(IRQ_HANDLED); } int write_sigio_irq(int fd) { - if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", - NULL)){ - printk("write_sigio_irq : um_request_irq failed\n"); + int err; + + err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, + SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", + NULL); + if(err){ + printk("write_sigio_irq : um_request_irq failed, err = %d\n", + err); return(-1); } sigio_irq_fd = fd; diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index b5ce13d55..82d19b451 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include "init.h" #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "sigio.h" #include "helper.h" #include "os.h" @@ -26,7 +26,7 @@ int pty_output_sigio = 0; int pty_close_sigio = 0; /* Used as a flag during SIGIO testing early in boot */ -static int got_sigio = 0; +static volatile int got_sigio = 0; void __init handler(int sig) { @@ -45,19 +45,18 @@ static void openpty_cb(void *arg) info->err = 0; if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) - info->err = errno; + info->err = -errno; } void __init check_one_sigio(void (*proc)(int, int)) { struct sigaction old, new; - struct termios tt; struct openpty_arg pty = { .master = -1, .slave = -1 }; - int master, slave, flags; + int master, slave, err; initial_thread_cb(openpty_cb, &pty); if(pty.err){ - printk("openpty failed, errno = %d\n", pty.err); + printk("openpty failed, errno = %d\n", -pty.err); return; } @@ -69,23 +68,14 @@ void __init check_one_sigio(void (*proc)(int, int)) return; } - if(tcgetattr(master, &tt) < 0) - panic("check_sigio : tcgetattr failed, errno = %d\n", errno); - cfmakeraw(&tt); - if(tcsetattr(master, TCSADRAIN, &tt) < 0) - panic("check_sigio : tcsetattr failed, errno = %d\n", errno); + /* Not now, but complain so we now where we failed. */ + err = raw(master); + if (err < 0) + panic("check_sigio : __raw failed, errno = %d\n", -err); - if((flags = fcntl(master, F_GETFL)) < 0) - panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno); - - if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)) - panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, " - "errno = %d\n", errno); - - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) - panic("check_sigio : fcntl F_SETFL failed, errno = %d\n", - errno); + err = os_sigio_async(master, slave); + if(err < 0) + panic("tty_fds : sigio_async failed, err = %d\n", -err); if(sigaction(SIGIO, NULL, &old) < 0) panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); @@ -97,8 +87,8 @@ void __init check_one_sigio(void (*proc)(int, int)) got_sigio = 0; (*proc)(master, slave); - close(master); - close(slave); + os_close_file(master); + os_close_file(slave); if(sigaction(SIGIO, &old, NULL) < 0) panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); @@ -112,25 +102,25 @@ static void tty_output(int master, int slave) printk("Checking that host ptys support output SIGIO..."); memset(buf, 0, sizeof(buf)); - while(write(master, buf, sizeof(buf)) > 0) ; + + while(os_write_file(master, buf, sizeof(buf)) > 0) ; if(errno != EAGAIN) panic("check_sigio : write failed, errno = %d\n", errno); - - while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; + while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; if(got_sigio){ printk("Yes\n"); pty_output_sigio = 1; } - else if(errno == EAGAIN) printk("No, enabling workaround\n"); - else panic("check_sigio : read failed, errno = %d\n", errno); + else if(n == -EAGAIN) printk("No, enabling workaround\n"); + else panic("check_sigio : read failed, err = %d\n", n); } static void tty_close(int master, int slave) { printk("Checking that host ptys support SIGIO on close..."); - close(slave); + os_close_file(slave); if(got_sigio){ printk("Yes\n"); pty_close_sigio = 1; @@ -140,7 +130,8 @@ static void tty_close(int master, int slave) void __init check_sigio(void) { - if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){ + if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && + (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ printk("No pseudo-terminals available - skipping pty SIGIO " "check\n"); return; @@ -201,11 +192,10 @@ static int write_sigio_thread(void *unused) p = &fds->poll[i]; if(p->revents == 0) continue; if(p->fd == sigio_private[1]){ - n = read(sigio_private[1], &c, sizeof(c)); + n = os_read_file(sigio_private[1], &c, sizeof(c)); if(n != sizeof(c)) printk("write_sigio_thread : " - "read failed, errno = %d\n", - errno); + "read failed, err = %d\n", -n); tmp = current_poll; current_poll = next_poll; next_poll = tmp; @@ -218,10 +208,10 @@ static int write_sigio_thread(void *unused) (fds->used - i) * sizeof(*fds->poll)); } - n = write(respond_fd, &c, sizeof(c)); + n = os_write_file(respond_fd, &c, sizeof(c)); if(n != sizeof(c)) printk("write_sigio_thread : write failed, " - "errno = %d\n", errno); + "err = %d\n", -n); } } } @@ -252,15 +242,15 @@ static void update_thread(void) char c; flags = set_signals(0); - n = write(sigio_private[0], &c, sizeof(c)); + n = os_write_file(sigio_private[0], &c, sizeof(c)); if(n != sizeof(c)){ - printk("update_thread : write failed, errno = %d\n", errno); + printk("update_thread : write failed, err = %d\n", -n); goto fail; } - n = read(sigio_private[0], &c, sizeof(c)); + n = os_read_file(sigio_private[0], &c, sizeof(c)); if(n != sizeof(c)){ - printk("update_thread : read failed, errno = %d\n", errno); + printk("update_thread : read failed, err = %d\n", -n); goto fail; } @@ -271,10 +261,10 @@ static void update_thread(void) if(write_sigio_pid != -1) os_kill_process(write_sigio_pid, 1); write_sigio_pid = -1; - close(sigio_private[0]); - close(sigio_private[1]); - close(write_sigio_fds[0]); - close(write_sigio_fds[1]); + os_close_file(sigio_private[0]); + os_close_file(sigio_private[1]); + os_close_file(write_sigio_fds[0]); + os_close_file(write_sigio_fds[1]); sigio_unlock(); set_signals(flags); } @@ -369,15 +359,15 @@ void write_sigio_workaround(void) goto out; err = os_pipe(write_sigio_fds, 1, 1); - if(err){ + if(err < 0){ printk("write_sigio_workaround - os_pipe 1 failed, " - "errno = %d\n", -err); + "err = %d\n", -err); goto out; } err = os_pipe(sigio_private, 1, 1); - if(err){ + if(err < 0){ printk("write_sigio_workaround - os_pipe 2 failed, " - "errno = %d\n", -err); + "err = %d\n", -err); goto out_close1; } if(setup_initial_poll(sigio_private[1])) @@ -399,11 +389,11 @@ void write_sigio_workaround(void) os_kill_process(write_sigio_pid, 1); write_sigio_pid = -1; out_close2: - close(sigio_private[0]); - close(sigio_private[1]); + os_close_file(sigio_private[0]); + os_close_file(sigio_private[1]); out_close1: - close(write_sigio_fds[0]); - close(write_sigio_fds[1]); + os_close_file(write_sigio_fds[0]); + os_close_file(write_sigio_fds[1]); sigio_unlock(); } @@ -412,10 +402,16 @@ int read_sigio_fd(int fd) int n; char c; - n = read(fd, &c, sizeof(c)); + n = os_read_file(fd, &c, sizeof(c)); if(n != sizeof(c)){ - printk("read_sigio_fd - read failed, errno = %d\n", errno); - return(-errno); + if(n < 0) { + printk("read_sigio_fd - read failed, err = %d\n", -n); + return(n); + } + else { + printk("read_sigio_fd - short read, bytes = %d\n", n); + return(-EIO); + } } return(n); } diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 6e13847ed..fdebc09d3 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -31,17 +31,6 @@ EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); -static void force_segv(int sig) -{ - if(sig == SIGSEGV){ - struct k_sigaction *ka; - - ka = ¤t->sig->action[SIGSEGV - 1]; - ka->sa.sa_handler = SIG_DFL; - } - force_sig(SIGSEGV, current); -} - #define _S(nr) (1<<((nr)-1)) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) @@ -49,53 +38,55 @@ static void force_segv(int sig) /* * OK, we're invoking a handler */ -static int handle_signal(struct pt_regs *regs, unsigned long signr, - struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, int error) +static int handle_signal(struct pt_regs *regs, unsigned long signr, + struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset) { - __sighandler_t handler; - void (*restorer)(void); unsigned long sp; - sigset_t save; - int err, ret; - - ret = 0; - switch(error){ - case -ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = - do_no_restart_syscall; - case -ERESTARTNOHAND: - ret = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - ret = -EINTR; + int err; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + /* Did we come from a system call? */ + if(PT_REGS_SYSCALL_NR(regs) >= 0){ + /* If so, check system call restarting.. */ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + PT_REGS_SYSCALL_RET(regs) = -EINTR; break; - } + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + PT_REGS_SYSCALL_RET(regs) = -EINTR; + break; + } /* fallthrough */ - case -ERESTARTNOINTR: - PT_REGS_RESTART_SYSCALL(regs); - PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); - - /* This is because of the UM_SET_SYSCALL_RETURN and the fact - * that on i386 the system call number and return value are - * in the same register. When the system call restarts, %eax - * had better have the system call number in it. Since the - * return value doesn't matter (except that it shouldn't be - * -ERESTART*), we'll stick the system call number there. - */ - ret = PT_REGS_SYSCALL_NR(regs); - break; + case -ERESTARTNOINTR: + PT_REGS_RESTART_SYSCALL(regs); + PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); + break; + } } - handler = ka->sa.sa_handler; - save = *oldset; + sp = PT_REGS_SP(regs); + if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) + sp = current->sas_ss_sp + current->sas_ss_size; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + if(ka->sa.sa_flags & SA_SIGINFO) + err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); + else + err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if(err){ + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *oldset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + force_sigsegv(signr, current); + } + else if(!(ka->sa.sa_flags & SA_NODEFER)){ spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -104,50 +95,24 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, spin_unlock_irq(¤t->sighand->siglock); } - sp = PT_REGS_SP(regs); - - if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) - sp = current->sas_ss_sp + current->sas_ss_size; - - if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret); - - if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; - else restorer = NULL; - - if(ka->sa.sa_flags & SA_SIGINFO) - err = setup_signal_stack_si(sp, signr, (unsigned long) handler, - restorer, regs, info, &save); - else - err = setup_signal_stack_sc(sp, signr, (unsigned long) handler, - restorer, regs, &save); - if(err) goto segv; - - return(0); - segv: - force_segv(signr); - return(1); + return err; } -static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) +static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) { + struct k_sigaction ka_copy; siginfo_t info; - struct k_sigaction *ka; - int err, sig; - - if (!oldset) - oldset = ¤t->blocked; + int sig, handled_sig = 0; - sig = get_signal_to_deliver(&info, regs, NULL); - if(sig == 0) - return(0); - - /* Whee! Actually deliver the signal. */ - ka = ¤t->sig->action[sig -1 ]; - err = handle_signal(regs, sig, ka, &info, oldset, error); - if(!err) return(1); + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ + handled_sig = 1; + /* Whee! Actually deliver the signal. */ + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) + break; + } /* Did we come from a system call? */ - if(PT_REGS_SYSCALL_NR(regs) >= 0){ + if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ /* Restart the system call - no handlers present */ if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || @@ -168,21 +133,21 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) * on the host. The tracing thread will check this flag and * PTRACE_SYSCALL if necessary. */ - if((current->ptrace & PT_DTRACE) && - is_syscall(PT_REGS_IP(¤t->thread.regs))) - (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0); - return(0); + if(current->ptrace & PT_DTRACE) + current->thread.singlestep_syscall = + is_syscall(PT_REGS_IP(¤t->thread.regs)); + return(handled_sig); } -int do_signal(int error) +int do_signal(void) { - return(kern_do_signal(¤t->thread.regs, NULL, error)); + return(kern_do_signal(¤t->thread.regs, ¤t->blocked)); } /* * Atomically swap in the new signal mask, and wait for a signal. */ -int sys_sigsuspend(int history0, int history1, old_sigset_t mask) +long sys_sigsuspend(int history0, int history1, old_sigset_t mask) { sigset_t saveset; @@ -193,15 +158,16 @@ int sys_sigsuspend(int history0, int history1, old_sigset_t mask) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if(kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) + if(kern_do_signal(¤t->thread.regs, &saveset)) return(-EINTR); } } -int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) +long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) { sigset_t saveset, newset; @@ -219,28 +185,68 @@ int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) + if (kern_do_signal(¤t->thread.regs, &saveset)) return(-EINTR); } } +int sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +long sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); +} + +extern int userspace_pid[]; + static int copy_sc_from_user(struct pt_regs *to, void *from, struct arch_frame_data *arch) { int ret; ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch), - copy_sc_from_user_skas(&to->regs, from)); + copy_sc_from_user_skas(userspace_pid[0], + &to->regs, from)); return(ret); } -int sys_sigreturn(struct pt_regs regs) +long sys_sigreturn(struct pt_regs regs) { - void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); - void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); + void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); + void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); spin_lock_irq(¤t->sighand->siglock); @@ -255,10 +261,10 @@ int sys_sigreturn(struct pt_regs regs) return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); } -int sys_rt_sigreturn(struct pt_regs regs) +long sys_rt_sigreturn(struct pt_regs regs) { - struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs)); - void *fp; + unsigned long sp = PT_REGS_SP(¤t->thread.regs); + struct ucontext __user *uc = sp_to_uc(sp); int sig_size = _NSIG_WORDS * sizeof(unsigned long); spin_lock_irq(¤t->sighand->siglock); @@ -266,7 +272,6 @@ int sys_rt_sigreturn(struct pt_regs regs) sigdelsetmask(¤t->blocked, ~_BLOCKABLE); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext)); copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, &signal_frame_si.common.arch); return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c index 52cfd60a1..2468cd6a6 100644 --- a/arch/um/kernel/signal_user.c +++ b/arch/um/kernel/signal_user.c @@ -57,6 +57,10 @@ int change_sig(int signal, int on) return(!sigismember(&old, signal)); } +/* Both here and in set/get_signal we don't touch SIGPROF, because we must not + * disable profiling; it's safe because the profiling code does not interact + * with the kernel code at all.*/ + static void change_signals(int type) { sigset_t mask; @@ -65,7 +69,6 @@ static void change_signals(int type) sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIO); - sigaddset(&mask, SIGPROF); if(sigprocmask(type, &mask, NULL) < 0) panic("Failed to change signal mask - errno = %d", errno); } @@ -80,6 +83,12 @@ void unblock_signals(void) change_signals(SIG_UNBLOCK); } +/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled + * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to + * be able to profile all of UML, not just the non-critical sections. If + * profiling is not thread-safe, then that is not my problem. We can disable + * profiling when SMP is enabled in that case. + */ #define SIGIO_BIT 0 #define SIGVTALRM_BIT 1 @@ -114,6 +123,11 @@ int set_signals(int enable) sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } + + /* This is safe - sigprocmask is guaranteed to copy locally the + * value of new_set, do his work and then, at the end, write to + * old_set. + */ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) panic("Failed to enable signals"); ret = enable_mask(&mask); diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 72c79956f..43320030f 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -1,24 +1,16 @@ # -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # -obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \ - process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \ +obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ + syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \ sys-$(SUBARCH)/ +subdir-y := util + USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -include/skas_ptregs.h : util/mk_ptregs - util/mk_ptregs > $@ - -util/mk_ptregs : - $(MAKE) -C util - $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : - $(MAKE) -C util clean - $(RM) -f include/skas_ptregs.h diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c index 49356d26a..c6b4d5dba 100644 --- a/arch/um/kernel/skas/exec_kern.c +++ b/arch/um/kernel/skas/exec_kern.c @@ -12,7 +12,7 @@ #include "asm/mmu_context.h" #include "tlb.h" #include "skas.h" -#include "mmu.h" +#include "um_mmu.h" #include "os.h" void flush_thread_skas(void) diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index d9614f6cd..2f6eaa374 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -8,7 +8,7 @@ #include "sysdep/ptrace.h" -extern int userspace_pid; +extern int userspace_pid[]; extern void switch_threads(void *me, void *next); extern void thread_wait(void *sw, void *fb); @@ -28,11 +28,10 @@ extern int unmap(int fd, void *addr, int len); extern int protect(int fd, unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern void user_signal(int sig, union uml_pt_regs *regs); -extern int singlestepping_skas(void); extern int new_mm(int from); extern void save_registers(union uml_pt_regs *regs); extern void restore_registers(union uml_pt_regs *regs); -extern void start_userspace(void); +extern void start_userspace(int cpu); extern void init_registers(int pid); #endif diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c index d163090c0..cfcfa0d60 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/kernel/skas/mem_user.c @@ -7,6 +7,7 @@ #include #include #include "mem_user.h" +#include "mem.h" #include "user.h" #include "os.h" #include "proc_mm.h" @@ -15,12 +16,12 @@ void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x) { struct proc_mm_op map; - struct mem_region *region; - int prot, n; + __u64 offset; + int prot, n, phys_fd; prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - region = phys_region(phys); + phys_fd = phys_mapping(phys, &offset); map = ((struct proc_mm_op) { .op = MM_MMAP, .u = @@ -30,12 +31,12 @@ void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, .prot = prot, .flags = MAP_SHARED | MAP_FIXED, - .fd = region->fd, - .offset = phys_offset(phys) + .fd = phys_fd, + .offset = offset } } } ); n = os_write_file(fd, &map, sizeof(map)); if(n != sizeof(map)) - printk("map : /proc/mm map failed, errno = %d\n", errno); + printk("map : /proc/mm map failed, err = %d\n", -n); } int unmap(int fd, void *addr, int len) @@ -49,8 +50,13 @@ int unmap(int fd, void *addr, int len) { .addr = (unsigned long) addr, .len = len } } } ); n = os_write_file(fd, &unmap, sizeof(unmap)); - if((n != 0) && (n != sizeof(unmap))) - return(-errno); + if(n != sizeof(unmap)) { + if(n < 0) + return(n); + else if(n > 0) + return(-EIO); + } + return(0); } @@ -71,11 +77,15 @@ int protect(int fd, unsigned long addr, unsigned long len, int r, int w, .prot = prot } } } ); n = os_write_file(fd, &protect, sizeof(protect)); - if((n != 0) && (n != sizeof(protect))){ + if(n != sizeof(protect)) { + if(n == 0) return(0); + if(must_succeed) - panic("protect failed, errno = %d", errno); - return(-errno); + panic("protect failed, err = %d", -n); + + return(-EIO); } + return(0); } diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 5911cdd0c..6cb9a6d02 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -22,9 +22,11 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) else from = -1; mm->context.skas.mm_fd = new_mm(from); - if(mm->context.skas.mm_fd < 0) - panic("init_new_context_skas - new_mm failed, errno = %d\n", - mm->context.skas.mm_fd); + if(mm->context.skas.mm_fd < 0){ + printk("init_new_context_skas - new_mm failed, errno = %d\n", + mm->context.skas.mm_fd); + return(mm->context.skas.mm_fd); + } return(0); } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index cb91f8cd1..33e46206d 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -24,6 +25,19 @@ #include "os.h" #include "proc_mm.h" #include "skas_ptrace.h" +#include "chan_user.h" +#include "signal_user.h" + +int is_skas_winch(int pid, int fd, void *data) +{ + if(pid != os_getpid()) + return(0); + + register_winch_irq(-1, fd, -1, data); + return(1); +} + +/* These are set once at boot time and not changed thereafter */ unsigned long exec_regs[FRAME_SIZE]; unsigned long exec_fp_regs[HOST_FP_SIZE]; @@ -43,37 +57,39 @@ static void handle_segv(int pid) segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); } -static void handle_trap(int pid, union uml_pt_regs *regs) +/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ +static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) { int err, syscall_nr, status; syscall_nr = PT_SYSCALL_NR(regs->skas.regs); - if(syscall_nr < 1){ + UPT_SYSCALL_NR(regs) = syscall_nr; + if(syscall_nr < 0){ relay_signal(SIGTRAP, regs); return; } - UPT_SYSCALL_NR(regs) = syscall_nr; - err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); - if(err < 0) - panic("handle_trap - nullifying syscall failed errno = %d\n", - errno); + if (!local_using_sysemu) + { + err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); + if(err < 0) + panic("handle_trap - nullifying syscall failed errno = %d\n", + errno); - err = ptrace(PTRACE_SYSCALL, pid, 0, 0); - if(err < 0) - panic("handle_trap - continuing to end of syscall failed, " - "errno = %d\n", errno); + err = ptrace(PTRACE_SYSCALL, pid, 0, 0); + if(err < 0) + panic("handle_trap - continuing to end of syscall failed, " + "errno = %d\n", errno); - err = waitpid(pid, &status, WUNTRACED); - if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - panic("handle_trap - failed to wait at end of syscall, " - "errno = %d, status = %d\n", errno, status); + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); + if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("handle_trap - failed to wait at end of syscall, " + "errno = %d, status = %d\n", errno, status); + } handle_syscall(regs); } -int userspace_pid; - static int userspace_tramp(void *arg) { init_new_thread_signals(0); @@ -83,7 +99,11 @@ static int userspace_tramp(void *arg) return(0); } -void start_userspace(void) +/* Each element set once, and only accessed by a single processor anyway */ +#define NR_CPUS 1 +int userspace_pid[NR_CPUS]; + +void start_userspace(int cpu) { void *stack; unsigned long sp; @@ -101,7 +121,7 @@ void start_userspace(void) panic("start_userspace : clone failed, errno = %d", errno); do { - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("start_userspace : wait failed, errno = %d", errno); @@ -114,21 +134,26 @@ void start_userspace(void) if(munmap(stack, PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - userspace_pid = pid; + userspace_pid[cpu] = pid; } void userspace(union uml_pt_regs *regs) { - int err, status, op; + int err, status, op, pt_syscall_parm, pid = userspace_pid[0]; + int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ restore_registers(regs); - err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0); + local_using_sysemu = get_using_sysemu(); + + pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; + err = ptrace(pt_syscall_parm, pid, 0, 0); + if(err) - panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", - errno); + panic("userspace - PTRACE_%s failed, errno = %d\n", + local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); while(1){ - err = waitpid(userspace_pid, &status, WUNTRACED); + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); @@ -139,16 +164,17 @@ void userspace(union uml_pt_regs *regs) if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: - handle_segv(userspace_pid); + handle_segv(pid); break; case SIGTRAP: - handle_trap(userspace_pid, regs); + handle_trap(pid, regs, local_using_sysemu); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: + case SIGWINCH: user_signal(WSTOPSIG(status), regs); break; default: @@ -160,45 +186,63 @@ void userspace(union uml_pt_regs *regs) restore_registers(regs); - op = singlestepping_skas() ? PTRACE_SINGLESTEP : - PTRACE_SYSCALL; - err = ptrace(op, userspace_pid, 0, 0); + /*Now we ended the syscall, so re-read local_using_sysemu.*/ + local_using_sysemu = get_using_sysemu(); + pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; + + op = singlestepping(NULL) ? PTRACE_SINGLESTEP : + pt_syscall_parm; + + err = ptrace(op, pid, 0, 0); if(err) - panic("userspace - PTRACE_SYSCALL failed, " - "errno = %d\n", errno); + panic("userspace - PTRACE_%s failed, " + "errno = %d\n", + local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); } } void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, void (*handler)(int)) { - jmp_buf switch_buf, fork_buf; + unsigned long flags; + sigjmp_buf switch_buf, fork_buf; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; - if(setjmp(fork_buf) == 0) + /* Somewhat subtle - siglongjmp restores the signal mask before doing + * the longjmp. This means that when jumping from one stack to another + * when the target stack has interrupts enabled, an interrupt may occur + * on the source stack. This is bad when starting up a process because + * it's not supposed to get timer ticks until it has been scheduled. + * So, we disable interrupts around the sigsetjmp to ensure that + * they can't happen until we get back here where they are safe. + */ + flags = get_signals(); + block_signals(); + if(sigsetjmp(fork_buf, 1) == 0) new_thread_proc(stack, handler); + set_signals(flags); remove_sigstack(); } void thread_wait(void *sw, void *fb) { - jmp_buf buf, **switch_buf = sw, *fork_buf; + sigjmp_buf buf, **switch_buf = sw, *fork_buf; *switch_buf = &buf; fork_buf = fb; - if(setjmp(buf) == 0) - longjmp(*fork_buf, 1); + if(sigsetjmp(buf, 1) == 0) + siglongjmp(*fork_buf, 1); } -static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs, - unsigned long *fp_regs) +static int move_registers(int pid, int int_op, int fp_op, + union uml_pt_regs *regs, unsigned long *fp_regs) { - if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0) + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) return(-errno); - if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0) + if(ptrace(fp_op, pid, 0, fp_regs) < 0) return(-errno); return(0); } @@ -217,10 +261,11 @@ void save_registers(union uml_pt_regs *regs) fp_regs = regs->skas.fp; } - err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs); + err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs, + fp_regs); if(err) panic("save_registers - saving registers failed, errno = %d\n", - err); + -err); } void restore_registers(union uml_pt_regs *regs) @@ -237,42 +282,43 @@ void restore_registers(union uml_pt_regs *regs) fp_regs = regs->skas.fp; } - err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs); + err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs, + fp_regs); if(err) panic("restore_registers - saving registers failed, " - "errno = %d\n", err); + "errno = %d\n", -err); } void switch_threads(void *me, void *next) { - jmp_buf my_buf, **me_ptr = me, *next_buf = next; + sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; *me_ptr = &my_buf; - if(setjmp(my_buf) == 0) - longjmp(*next_buf, 1); + if(sigsetjmp(my_buf, 1) == 0) + siglongjmp(*next_buf, 1); } -static jmp_buf initial_jmpbuf; +static sigjmp_buf initial_jmpbuf; /* XXX Make these percpu */ static void (*cb_proc)(void *arg); static void *cb_arg; -static jmp_buf *cb_back; +static sigjmp_buf *cb_back; int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) { - jmp_buf **switch_buf = switch_buf_ptr; + sigjmp_buf **switch_buf = switch_buf_ptr; int n; *fork_buf_ptr = &initial_jmpbuf; - n = setjmp(initial_jmpbuf); + n = sigsetjmp(initial_jmpbuf, 1); if(n == 0) new_thread_proc((void *) stack, new_thread_handler); else if(n == 1) remove_sigstack(); else if(n == 2){ (*cb_proc)(cb_arg); - longjmp(*cb_back, 1); + siglongjmp(*cb_back, 1); } else if(n == 3){ kmalloc_ok = 0; @@ -282,7 +328,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) kmalloc_ok = 0; return(1); } - longjmp(**switch_buf, 1); + siglongjmp(**switch_buf, 1); } void remove_sigstack(void) @@ -297,15 +343,15 @@ void remove_sigstack(void) void initial_thread_cb_skas(void (*proc)(void *), void *arg) { - jmp_buf here; + sigjmp_buf here; cb_proc = proc; cb_arg = arg; cb_back = &here; block_signals(); - if(setjmp(here) == 0) - longjmp(initial_jmpbuf, 2); + if(sigsetjmp(here, 1) == 0) + siglongjmp(initial_jmpbuf, 2); unblock_signals(); cb_proc = NULL; @@ -316,40 +362,21 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) void halt_skas(void) { block_signals(); - longjmp(initial_jmpbuf, 3); + siglongjmp(initial_jmpbuf, 3); } void reboot_skas(void) { block_signals(); - longjmp(initial_jmpbuf, 4); -} - -int new_mm(int from) -{ - struct proc_mm_op copy; - int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0); - - if(fd < 0) - return(-errno); - - if(from != -1){ - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, - .u = - { .copy_segments = from } } ); - n = os_write_file(fd, ©, sizeof(copy)); - if(n != sizeof(copy)) - printk("new_mm : /proc/mm copy_segments failed, " - "errno = %d\n", errno); - } - return(fd); + siglongjmp(initial_jmpbuf, 4); } void switch_mm_skas(int mm_fd) { int err; - err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd); +#warning need cpu pid in switch_mm_skas + err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); if(err) panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", errno); @@ -357,7 +384,8 @@ void switch_mm_skas(int mm_fd) void kill_off_processes_skas(void) { - os_kill_process(userspace_pid, 1); +#warning need to loop over userspace_pids in kill_off_processes_skas + os_kill_ptraced_process(userspace_pid[0], 1); } void init_registers(int pid) diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 128146c80..b0c53a48e 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -6,6 +6,12 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/ptrace.h" +#include "linux/proc_fs.h" +#include "linux/file.h" +#include "linux/errno.h" +#include "linux/init.h" +#include "asm/uaccess.h" +#include "asm/atomic.h" #include "kern_util.h" #include "time_user.h" #include "signal_user.h" @@ -16,14 +22,7 @@ #include "frame.h" #include "kern.h" #include "mode.h" - -int singlestepping_skas(void) -{ - int ret = current->ptrace & PT_DTRACE; - - current->ptrace &= ~PT_DTRACE; - return(ret); -} +#include "proc_mm.h" void *switch_to_skas(void *prev, void *next) { @@ -61,11 +60,13 @@ void new_thread_handler(int sig) thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); -#ifdef CONFIG_SMP - schedule_tail(NULL); -#endif + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; + /* The return value is 1 if the kernel thread execs a process, + * 0 if it just exits + */ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); if(n == 1) userspace(¤t->thread.regs.regs); @@ -93,11 +94,11 @@ void fork_handler(int sig) current->thread.mode.skas.fork_buf); force_flush_all(); -#ifdef CONFIG_SMP + if(current->thread.prev_sched == NULL) + panic("blech"); + schedule_tail(current->thread.prev_sched); -#endif current->thread.prev_sched = NULL; - unblock_signals(); userspace(¤t->thread.regs.regs); } @@ -128,15 +129,36 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, handler = new_thread_handler; } - new_thread((void *) p->thread.kernel_stack, - &p->thread.mode.skas.switch_buf, + new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, &p->thread.mode.skas.fork_buf, handler); return(0); } +int new_mm(int from) +{ + struct proc_mm_op copy; + int n, fd; + + fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); + if(fd < 0) + return(fd); + + if(from != -1){ + copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, + .u = + { .copy_segments = from } } ); + n = os_write_file(fd, ©, sizeof(copy)); + if(n != sizeof(copy)) + printk("new_mm : /proc/mm copy_segments failed, " + "err = %d\n", -n); + } + + return(fd); +} + void init_idle_skas(void) { - cpu_tasks[current->thread_info->cpu].pid = os_getpid(); + cpu_tasks[current_thread->cpu].pid = os_getpid(); default_idle(); } @@ -160,27 +182,29 @@ static int start_kernel_proc(void *unused) int start_uml_skas(void) { - start_userspace(); + start_userspace(0); capture_signal_stack(); init_new_thread_signals(1); - idle_timer(); + uml_idle_timer(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread((void *) init_task.thread.kernel_stack, + return(start_idle_thread(init_task.thread_info, &init_task.thread.mode.skas.switch_buf, &init_task.thread.mode.skas.fork_buf)); } int external_pid_skas(struct task_struct *task) { - return(userspace_pid); +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); } int thread_pid_skas(struct task_struct *task) { - return(userspace_pid); +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); } /* diff --git a/arch/um/kernel/skas/sys-i386/Makefile b/arch/um/kernel/skas/sys-i386/Makefile index 2ad8271c6..3eeea057c 100644 --- a/arch/um/kernel/skas/sys-i386/Makefile +++ b/arch/um/kernel/skas/sys-i386/Makefile @@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : diff --git a/arch/um/kernel/skas/sys-i386/sigcontext.c b/arch/um/kernel/skas/sys-i386/sigcontext.c index 5f340e102..b015d1960 100644 --- a/arch/um/kernel/skas/sys-i386/sigcontext.c +++ b/arch/um/kernel/skas/sys-i386/sigcontext.c @@ -12,10 +12,9 @@ #include "kern_util.h" #include "user.h" #include "sigcontext.h" +#include "mode.h" -extern int userspace_pid; - -int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr) +int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr) { struct sigcontext sc, *from = from_ptr; unsigned long fpregs[FP_FRAME_SIZE]; @@ -41,13 +40,12 @@ int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr) regs->skas.regs[EIP] = sc.eip; regs->skas.regs[CS] = sc.cs; regs->skas.regs[EFL] = sc.eflags; - regs->skas.regs[UESP] = sc.esp_at_signal; regs->skas.regs[SS] = sc.ss; regs->skas.fault_addr = sc.cr2; regs->skas.fault_type = FAULT_WRITE(sc.err); regs->skas.trap_type = sc.trapno; - err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs); + err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs); if(err < 0){ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, " "errno = %d\n", errno); @@ -57,8 +55,9 @@ int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr) return(0); } -int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, - unsigned long fault_addr, int fault_type) +int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, + union uml_pt_regs *regs, unsigned long fault_addr, + int fault_type) { struct sigcontext sc, *to = to_ptr; struct _fpstate *to_fp; @@ -86,7 +85,7 @@ int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, sc.err = TO_SC_ERR(fault_type); sc.trapno = regs->skas.trap_type; - err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs); + err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs); if(err < 0){ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " "errno = %d\n", errno); diff --git a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c index bc837a77e..bdf040ce5 100644 --- a/arch/um/kernel/skas/syscall_kern.c +++ b/arch/um/kernel/skas/syscall_kern.c @@ -1,9 +1,10 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/sys.h" +#include "linux/ptrace.h" #include "asm/errno.h" #include "asm/unistd.h" #include "asm/ptrace.h" diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c index caccb772b..b7fd594eb 100644 --- a/arch/um/kernel/skas/syscall_user.c +++ b/arch/um/kernel/skas/syscall_user.c @@ -10,10 +10,6 @@ #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" -/* XXX Bogus */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 void handle_syscall(union uml_pt_regs *regs) { @@ -22,15 +18,12 @@ void handle_syscall(union uml_pt_regs *regs) index = record_syscall_start(UPT_SYSCALL_NR(regs)); - syscall_trace(); + syscall_trace(regs, 0); result = execute_syscall(regs); REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); - if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || - (result == -ERESTARTNOINTR)) - do_signal(result); - syscall_trace(); + syscall_trace(regs, 1); record_syscall_end(index, result); } diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c index ed3d6bcd5..02e3e06bb 100644 --- a/arch/um/kernel/skas/tlb.c +++ b/arch/um/kernel/skas/tlb.c @@ -77,7 +77,7 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) int updated = 0, err; mm = &init_mm; - for(addr = start_vm; addr < end_vm;){ + for(addr = start; addr < end;){ pgd = pgd_offset(mm, addr); pmd = pmd_offset(pgd, addr); if(pmd_present(*pmd)){ diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c index 0906f65b8..96593709a 100644 --- a/arch/um/kernel/skas/trap_user.c +++ b/arch/um/kernel/skas/trap_user.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -19,8 +19,10 @@ void sig_handler_common_skas(int sig, void *sc_ptr) struct skas_regs *r; struct signal_info *info; int save_errno = errno; + int save_user; r = &TASK_REGS(get_current())->skas; + save_user = r->is_user; r->is_user = 0; r->fault_addr = SC_FAULT_ADDR(sc); r->fault_type = SC_FAULT_TYPE(sc); @@ -33,16 +35,13 @@ void sig_handler_common_skas(int sig, void *sc_ptr) (*info->handler)(sig, (union uml_pt_regs *) r); errno = save_errno; + r->is_user = save_user; } -extern int missed_ticks[]; - void user_signal(int sig, union uml_pt_regs *regs) { struct signal_info *info; - if(sig == SIGVTALRM) - missed_ticks[cpu()]++; regs->skas.is_user = 1; regs->skas.fault_addr = 0; regs->skas.fault_type = 0; diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index ea82f19b2..77048cd67 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -12,8 +12,9 @@ #include "asm/pgtable.h" #include "asm/uaccess.h" #include "kern_util.h" +#include "user_util.h" -extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, +extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out); static unsigned long maybe_map(unsigned long virt, int is_write) @@ -25,7 +26,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write) int dummy_code; if(IS_ERR(phys) || (is_write && !pte_write(pte))){ - err = handle_page_fault(virt, 0, is_write, 0, &dummy_code); + err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); if(err) return(0); phys = um_virt_to_phys(current, virt, NULL); @@ -33,7 +34,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write) return((unsigned long) phys); } -static int do_op(unsigned long addr, int len, int is_write, +static int do_op(unsigned long addr, int len, int is_write, int (*op)(unsigned long addr, int len, void *arg), void *arg) { struct page *page; @@ -51,37 +52,67 @@ static int do_op(unsigned long addr, int len, int is_write, return(n); } -static int buffer_op(unsigned long addr, int len, int is_write, - int (*op)(unsigned long addr, int len, void *arg), - void *arg) +static void do_buffer_op(void *jmpbuf, void *arg_ptr) { + va_list args = *((va_list *) arg_ptr); + unsigned long addr = va_arg(args, unsigned long); + int len = va_arg(args, int); + int is_write = va_arg(args, int); + int (*op)(unsigned long, int, void *) = va_arg(args, void *); + void *arg = va_arg(args, void *); + int *res = va_arg(args, int *); int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); int remain = len, n; + current->thread.fault_catcher = jmpbuf; n = do_op(addr, size, is_write, op, arg); - if(n != 0) - return(n < 0 ? remain : 0); + if(n != 0){ + *res = (n < 0 ? remain : 0); + goto out; + } addr += size; remain -= size; - if(remain == 0) - return(0); + if(remain == 0){ + *res = 0; + goto out; + } while(addr < ((addr + remain) & PAGE_MASK)){ n = do_op(addr, PAGE_SIZE, is_write, op, arg); - if(n != 0) - return(n < 0 ? remain : 0); + if(n != 0){ + *res = (n < 0 ? remain : 0); + goto out; + } addr += PAGE_SIZE; remain -= PAGE_SIZE; } - if(remain == 0) - return(0); + if(remain == 0){ + *res = 0; + goto out; + } n = do_op(addr, remain, is_write, op, arg); if(n != 0) - return(n < 0 ? remain : 0); - return(0); + *res = (n < 0 ? remain : 0); + else *res = 0; + out: + current->thread.fault_catcher = NULL; +} + +static int buffer_op(unsigned long addr, int len, int is_write, + int (*op)(unsigned long addr, int len, void *arg), + void *arg) +{ + int faulted, res; + + faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, + &res); + if(!faulted) + return(res); + + return(addr + len - (unsigned long) current->thread.fault_addr); } static int copy_chunk_from_user(unsigned long from, int len, void *arg) @@ -135,7 +166,7 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) n = strnlen(to, len); *to_ptr += n; - if(n < len) + if(n < len) return(1); return(0); } @@ -153,7 +184,7 @@ int strncpy_from_user_skas(char *dst, const char *src, int count) if(!access_ok_skas(VERIFY_READ, src, 1)) return(-EFAULT); - n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, + n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, &ptr); if(n != 0) return(-EFAULT); @@ -178,7 +209,7 @@ int clear_user_skas(void *mem, int len) return(0); } - return(access_ok_skas(VERIFY_WRITE, mem, len) ? + return(access_ok_skas(VERIFY_WRITE, mem, len) ? buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); } diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile index e62dc253e..a26e0c34a 100644 --- a/arch/um/kernel/skas/util/Makefile +++ b/arch/um/kernel/skas/util/Makefile @@ -1,10 +1,2 @@ -all: mk_ptregs - -mk_ptregs : mk_ptregs.o - $(CC) -o mk_ptregs mk_ptregs.o - -mk_ptregs.o : mk_ptregs.c - $(CC) -c $< - -clean : - $(RM) -f mk_ptregs *.o *~ +hostprogs-y := mk_ptregs +always := $(hostprogs-y) diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c index 658791017..116f74d2c 100644 --- a/arch/um/kernel/skas/util/mk_ptregs.c +++ b/arch/um/kernel/skas/util/mk_ptregs.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index b8158556c..b5e66b291 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -1,9 +1,15 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/config.h" +#include "linux/percpu.h" +#include "asm/pgalloc.h" +#include "asm/tlb.h" + +/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */ +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); #ifdef CONFIG_SMP @@ -12,10 +18,10 @@ #include "linux/threads.h" #include "linux/interrupt.h" #include "linux/err.h" +#include "linux/hardirq.h" #include "asm/smp.h" #include "asm/processor.h" #include "asm/spinlock.h" -#include "asm/hardirq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" @@ -23,9 +29,11 @@ #include "os.h" /* CPU online map, set by smp_boot_cpus */ -unsigned long cpu_online_map = cpumask_of_cpu(0); +cpumask_t cpu_online_map = CPU_MASK_NONE; +cpumask_t cpu_possible_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_online_map); +EXPORT_SYMBOL(cpu_possible_map); /* Per CPU bogomips and other parameters * The only piece used here is the ipi pipe, which is set before SMP is @@ -33,14 +41,6 @@ EXPORT_SYMBOL(cpu_online_map); */ struct cpuinfo_um cpu_data[NR_CPUS]; -spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED; - -atomic_t global_bh_count; - -/* Not used by UML */ -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile long global_irq_lock; - /* Set when the idlers are all forked */ int smp_threads_ready = 0; @@ -55,80 +55,44 @@ struct task_struct *idle_threads[NR_CPUS]; void smp_send_reschedule(int cpu) { - write(cpu_data[cpu].ipi_pipe[1], "R", 1); + os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1); num_reschedules_sent++; } -static void show(char * str) -{ - int cpu = smp_processor_id(); - - printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu); -} - -#define MAXCOUNT 100000000 - -static inline void wait_on_bh(void) -{ - int count = MAXCOUNT; - do { - if (!--count) { - show("wait_on_bh"); - count = ~0; - } - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} - -/* - * This is called when we want to synchronize with - * bottom half handlers. We need to wait until - * no other CPU is executing any bottom half handler. - * - * Don't wait if we're already running in an interrupt - * context or are inside a bh handler. - */ -void synchronize_bh(void) -{ - if (atomic_read(&global_bh_count) && !in_interrupt()) - wait_on_bh(); -} - void smp_send_stop(void) { int i; printk(KERN_INFO "Stopping all CPUs..."); for(i = 0; i < num_online_cpus(); i++){ - if(i == current->thread_info->cpu) + if(i == current_thread->cpu) continue; - write(cpu_data[i].ipi_pipe[1], "S", 1); + os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); } printk("done\n"); } -static cpumask_t smp_commenced_mask; -static cpumask_t smp_callin_map = CPU_MASK_NONE; +static cpumask_t smp_commenced_mask = CPU_MASK_NONE; +static cpumask_t cpu_callin_map = CPU_MASK_NONE; static int idle_proc(void *cpup) { int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); - if(err) - panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, - -err); + if(err < 0) + panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.mode.tt.extern_pid); wmb(); - if (cpu_test_and_set(cpu, &smp_callin_map)) { + if (cpu_test_and_set(cpu, cpu_callin_map)) { printk("huh, CPU#%d already present??\n", cpu); BUG(); } - while (!cpu_isset(cpu, &smp_commenced_mask)) + while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); cpu_set(cpu, cpu_online_map); @@ -143,14 +107,16 @@ static struct task_struct *idle_thread(int cpu) current->thread.request.u.thread.proc = idle_proc; current->thread.request.u.thread.arg = (void *) cpu; - new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL); - if(IS_ERR(new_task)) panic("do_fork failed in idle_thread"); + new_task = fork_idle(cpu); + if(IS_ERR(new_task)) + panic("copy_process failed in idle_thread, error = %ld", + PTR_ERR(new_task)); cpu_tasks[cpu] = ((struct cpu_task) { .pid = new_task->thread.mode.tt.extern_pid, .task = new_task } ); idle_threads[cpu] = new_task; - CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, + CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, sizeof(c)), ({ panic("skas mode doesn't support SMP"); })); return(new_task); @@ -160,15 +126,21 @@ void smp_prepare_cpus(unsigned int maxcpus) { struct task_struct *idle; unsigned long waittime; - int err, cpu; + int err, cpu, me = smp_processor_id(); + int i; + + for (i = 0; i < ncpus; ++i) + cpu_set(i, cpu_possible_map); - cpu_set(0, cpu_online_map); - cpu_set(0, smp_callin_map); + cpu_clear(me, cpu_online_map); + cpu_set(me, cpu_online_map); + cpu_set(me, cpu_callin_map); - err = os_pipe(cpu_data[0].ipi_pipe, 1, 1); - if(err) panic("CPU#0 failed to create IPI pipe, errno = %d", -err); + err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); + if(err < 0) + panic("CPU#0 failed to create IPI pipe, errno = %d", -err); - activate_ipi(cpu_data[0].ipi_pipe[0], + activate_ipi(cpu_data[me].ipi_pipe[0], current->thread.mode.tt.extern_pid); for(cpu = 1; cpu < ncpus; cpu++){ @@ -180,10 +152,10 @@ void smp_prepare_cpus(unsigned int maxcpus) unhash_process(idle); waittime = 200000000; - while (waittime-- && !cpu_isset(cpu, smp_callin_map)) + while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) cpu_relax(); - if (cpu_isset(cpu, smp_callin_map)) + if (cpu_isset(cpu, cpu_callin_map)) printk("done\n"); else printk("failed\n"); } @@ -216,7 +188,7 @@ void IPI_handler(int cpu) int fd; fd = cpu_data[cpu].ipi_pipe[0]; - while (read(fd, &c, 1) == 1) { + while (os_read_file(fd, &c, 1) == 1) { switch (c) { case 'C': smp_call_function_slave(cpu); @@ -276,9 +248,9 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, info = _info; for (i=0;ithread_info->cpu) && + if((i != current_thread->cpu) && cpu_isset(i, cpu_online_map)) - write(cpu_data[i].ipi_pipe[1], "C", 1); + os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); while (atomic_read(&scf_started) != cpus) barrier(); diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c index 77a7d922e..314925365 100644 --- a/arch/um/kernel/sys_call_table.c +++ b/arch/um/kernel/sys_call_table.c @@ -5,7 +5,6 @@ #include "linux/config.h" #include "linux/unistd.h" -#include "linux/version.h" #include "linux/sys.h" #include "linux/swap.h" #include "linux/syscalls.h" @@ -14,251 +13,49 @@ #include "sysdep/syscalls.h" #include "kern_util.h" -extern syscall_handler_t sys_restart_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_exit; +#ifdef CONFIG_NFSD +#define NFSSERVCTL sys_nfsservctl +#else +#define NFSSERVCTL sys_ni_syscall +#endif + +#define LAST_GENERIC_SYSCALL __NR_vserver + +#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL +#define LAST_SYSCALL LAST_GENERIC_SYSCALL +#else +#define LAST_SYSCALL LAST_ARCH_SYSCALL +#endif + extern syscall_handler_t sys_fork; -extern syscall_handler_t sys_creat; -extern syscall_handler_t sys_link; -extern syscall_handler_t sys_unlink; -extern syscall_handler_t sys_chdir; -extern syscall_handler_t sys_mknod; -extern syscall_handler_t sys_chmod; -extern syscall_handler_t sys_lchown16; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_stat; -extern syscall_handler_t sys_getpid; -extern syscall_handler_t sys_oldumount; -extern syscall_handler_t sys_setuid16; -extern syscall_handler_t sys_getuid16; +extern syscall_handler_t sys_execve; +extern syscall_handler_t um_time; +extern syscall_handler_t um_mount; +extern syscall_handler_t um_stime; extern syscall_handler_t sys_ptrace; -extern syscall_handler_t sys_alarm; -extern syscall_handler_t sys_fstat; -extern syscall_handler_t sys_pause; -extern syscall_handler_t sys_utime; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_access; -extern syscall_handler_t sys_nice; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_sync; -extern syscall_handler_t sys_kill; -extern syscall_handler_t sys_rename; -extern syscall_handler_t sys_mkdir; -extern syscall_handler_t sys_rmdir; extern syscall_handler_t sys_pipe; -extern syscall_handler_t sys_times; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_brk; -extern syscall_handler_t sys_setgid16; -extern syscall_handler_t sys_getgid16; -extern syscall_handler_t sys_signal; -extern syscall_handler_t sys_geteuid16; -extern syscall_handler_t sys_getegid16; -extern syscall_handler_t sys_acct; -extern syscall_handler_t sys_umount; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ioctl; -extern syscall_handler_t sys_fcntl; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_setpgid; -extern syscall_handler_t sys_ni_syscall; extern syscall_handler_t sys_olduname; -extern syscall_handler_t sys_umask; -extern syscall_handler_t sys_chroot; -extern syscall_handler_t sys_ustat; -extern syscall_handler_t sys_dup2; -extern syscall_handler_t sys_getppid; -extern syscall_handler_t sys_getpgrp; extern syscall_handler_t sys_sigaction; -extern syscall_handler_t sys_sgetmask; -extern syscall_handler_t sys_ssetmask; -extern syscall_handler_t sys_setreuid16; -extern syscall_handler_t sys_setregid16; extern syscall_handler_t sys_sigsuspend; -extern syscall_handler_t sys_sigpending; -extern syscall_handler_t sys_sethostname; -extern syscall_handler_t sys_setrlimit; -extern syscall_handler_t sys_old_getrlimit; -extern syscall_handler_t sys_getrusage; -extern syscall_handler_t sys_gettimeofday; -extern syscall_handler_t sys_settimeofday; -extern syscall_handler_t sys_getgroups16; -extern syscall_handler_t sys_setgroups16; -extern syscall_handler_t sys_symlink; -extern syscall_handler_t sys_lstat; -extern syscall_handler_t sys_readlink; -extern syscall_handler_t sys_swapon; -extern syscall_handler_t sys_uselib; -extern syscall_handler_t sys_reboot; extern syscall_handler_t old_readdir; -extern syscall_handler_t sys_munmap; -extern syscall_handler_t sys_truncate; -extern syscall_handler_t sys_ftruncate; -extern syscall_handler_t sys_fchmod; -extern syscall_handler_t sys_fchown16; -extern syscall_handler_t sys_getpriority; -extern syscall_handler_t sys_setpriority; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_statfs; -extern syscall_handler_t sys_fstatfs; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_socketcall; -extern syscall_handler_t sys_syslog; -extern syscall_handler_t sys_setitimer; -extern syscall_handler_t sys_getitimer; -extern syscall_handler_t sys_newstat; -extern syscall_handler_t sys_newlstat; -extern syscall_handler_t sys_newfstat; extern syscall_handler_t sys_uname; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_vhangup; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_swapoff; -extern syscall_handler_t sys_sysinfo; extern syscall_handler_t sys_ipc; -extern syscall_handler_t sys_fsync; extern syscall_handler_t sys_sigreturn; -extern syscall_handler_t sys_rt_sigreturn; extern syscall_handler_t sys_clone; -extern syscall_handler_t sys_setdomainname; -extern syscall_handler_t sys_newuname; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_adjtimex; -extern syscall_handler_t sys_mprotect; -extern syscall_handler_t sys_sigprocmask; -extern syscall_handler_t sys_init_module; -extern syscall_handler_t sys_delete_module; -extern syscall_handler_t sys_quotactl; -extern syscall_handler_t sys_getpgid; -extern syscall_handler_t sys_fchdir; -extern syscall_handler_t sys_bdflush; -extern syscall_handler_t sys_sysfs; -extern syscall_handler_t sys_personality; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_setfsuid16; -extern syscall_handler_t sys_setfsgid16; -extern syscall_handler_t sys_llseek; -extern syscall_handler_t sys_getdents; -extern syscall_handler_t sys_flock; -extern syscall_handler_t sys_msync; -extern syscall_handler_t sys_readv; -extern syscall_handler_t sys_writev; -extern syscall_handler_t sys_getsid; -extern syscall_handler_t sys_fdatasync; -extern syscall_handler_t sys_mlock; -extern syscall_handler_t sys_munlock; -extern syscall_handler_t sys_mlockall; -extern syscall_handler_t sys_munlockall; -extern syscall_handler_t sys_sched_setparam; -extern syscall_handler_t sys_sched_getparam; -extern syscall_handler_t sys_sched_setscheduler; -extern syscall_handler_t sys_sched_getscheduler; -extern syscall_handler_t sys_sched_get_priority_max; -extern syscall_handler_t sys_sched_get_priority_min; -extern syscall_handler_t sys_sched_rr_get_interval; -extern syscall_handler_t sys_nanosleep; -extern syscall_handler_t sys_mremap; -extern syscall_handler_t sys_setresuid16; -extern syscall_handler_t sys_getresuid16; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_poll; -extern syscall_handler_t sys_nfsservctl; -extern syscall_handler_t sys_setresgid16; -extern syscall_handler_t sys_getresgid16; -extern syscall_handler_t sys_prctl; -extern syscall_handler_t sys_ni_syscall; +extern syscall_handler_t sys_rt_sigreturn; extern syscall_handler_t sys_rt_sigaction; -extern syscall_handler_t sys_rt_sigprocmask; -extern syscall_handler_t sys_rt_sigpending; -extern syscall_handler_t sys_rt_sigtimedwait; -extern syscall_handler_t sys_rt_sigqueueinfo; -extern syscall_handler_t sys_rt_sigsuspend; -extern syscall_handler_t sys_pread64; -extern syscall_handler_t sys_pwrite64; -extern syscall_handler_t sys_chown16; -extern syscall_handler_t sys_getcwd; -extern syscall_handler_t sys_capget; -extern syscall_handler_t sys_capset; extern syscall_handler_t sys_sigaltstack; -extern syscall_handler_t sys_sendfile; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; extern syscall_handler_t sys_vfork; -extern syscall_handler_t sys_getrlimit; extern syscall_handler_t sys_mmap2; -extern syscall_handler_t sys_truncate64; -extern syscall_handler_t sys_ftruncate64; -extern syscall_handler_t sys_stat64; -extern syscall_handler_t sys_lstat64; -extern syscall_handler_t sys_fstat64; -extern syscall_handler_t sys_lchown; -extern syscall_handler_t sys_getuid; -extern syscall_handler_t sys_getgid; -extern syscall_handler_t sys_geteuid; -extern syscall_handler_t sys_getegid; -extern syscall_handler_t sys_setreuid; -extern syscall_handler_t sys_setregid; -extern syscall_handler_t sys_getgroups; -extern syscall_handler_t sys_setgroups; -extern syscall_handler_t sys_fchown; -extern syscall_handler_t sys_setresuid; -extern syscall_handler_t sys_getresuid; -extern syscall_handler_t sys_setresgid; -extern syscall_handler_t sys_getresgid; -extern syscall_handler_t sys_chown; -extern syscall_handler_t sys_setuid; -extern syscall_handler_t sys_setgid; -extern syscall_handler_t sys_setfsuid; -extern syscall_handler_t sys_setfsgid; -extern syscall_handler_t sys_pivot_root; -extern syscall_handler_t sys_mincore; -extern syscall_handler_t sys_madvise; -extern syscall_handler_t sys_fcntl64; -extern syscall_handler_t sys_getdents64; -extern syscall_handler_t sys_gettid; -extern syscall_handler_t sys_readahead; -extern syscall_handler_t sys_tkill; -extern syscall_handler_t sys_sendfile64; -extern syscall_handler_t sys_futex; -extern syscall_handler_t sys_sched_setaffinity; -extern syscall_handler_t sys_sched_getaffinity; -extern syscall_handler_t sys_io_setup; -extern syscall_handler_t sys_io_destroy; -extern syscall_handler_t sys_io_getevents; -extern syscall_handler_t sys_io_submit; -extern syscall_handler_t sys_io_cancel; -extern syscall_handler_t sys_exit_group; -extern syscall_handler_t sys_lookup_dcookie; -extern syscall_handler_t sys_epoll_create; -extern syscall_handler_t sys_epoll_ctl; -extern syscall_handler_t sys_epoll_wait; -extern syscall_handler_t sys_remap_file_pages; -extern syscall_handler_t sys_set_tid_address; - -#ifdef CONFIG_NFSD -#define NFSSERVCTL sys_nfsservctl -#else -#define NFSSERVCTL sys_ni_syscall -#endif - -extern syscall_handler_t um_mount; -extern syscall_handler_t um_time; -extern syscall_handler_t um_stime; - -#define LAST_GENERIC_SYSCALL __NR_set_tid_address - -#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL -#define LAST_SYSCALL LAST_GENERIC_SYSCALL -#else -#define LAST_SYSCALL LAST_ARCH_SYSCALL -#endif +extern syscall_handler_t old_mmap_i386; +extern syscall_handler_t old_select; +extern syscall_handler_t sys_modify_ldt; +extern syscall_handler_t sys_rt_sigsuspend; syscall_handler_t *sys_call_table[] = { - [ __NR_restart_syscall ] = sys_restart_syscall, - [ __NR_exit ] = sys_exit, - [ __NR_fork ] = sys_fork, + [ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall, + [ __NR_exit ] (syscall_handler_t *) sys_exit, + [ __NR_fork ] (syscall_handler_t *) sys_fork, [ __NR_read ] = (syscall_handler_t *) sys_read, [ __NR_write ] = (syscall_handler_t *) sys_write, @@ -266,229 +63,249 @@ syscall_handler_t *sys_call_table[] = { [ __NR_open ] = (syscall_handler_t *) sys_open, [ __NR_close ] = (syscall_handler_t *) sys_close, [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, - [ __NR_creat ] = sys_creat, - [ __NR_link ] = sys_link, - [ __NR_unlink ] = sys_unlink, + [ __NR_creat ] (syscall_handler_t *) sys_creat, + [ __NR_link ] (syscall_handler_t *) sys_link, + [ __NR_unlink ] (syscall_handler_t *) sys_unlink, [ __NR_execve ] = (syscall_handler_t *) sys_execve, /* declared differently in kern_util.h */ - [ __NR_chdir ] = sys_chdir, + [ __NR_chdir ] (syscall_handler_t *) sys_chdir, [ __NR_time ] = um_time, - [ __NR_mknod ] = sys_mknod, - [ __NR_chmod ] = sys_chmod, - [ __NR_lchown ] = sys_lchown16, - [ __NR_break ] = sys_ni_syscall, - [ __NR_oldstat ] = sys_stat, + [ __NR_mknod ] (syscall_handler_t *) sys_mknod, + [ __NR_chmod ] (syscall_handler_t *) sys_chmod, + [ __NR_lchown ] (syscall_handler_t *) sys_lchown16, + [ __NR_break ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_oldstat ] (syscall_handler_t *) sys_stat, [ __NR_lseek ] = (syscall_handler_t *) sys_lseek, - [ __NR_getpid ] = sys_getpid, + [ __NR_getpid ] (syscall_handler_t *) sys_getpid, [ __NR_mount ] = um_mount, - [ __NR_umount ] = sys_oldumount, - [ __NR_setuid ] = sys_setuid16, - [ __NR_getuid ] = sys_getuid16, + [ __NR_umount ] (syscall_handler_t *) sys_oldumount, + [ __NR_setuid ] (syscall_handler_t *) sys_setuid16, + [ __NR_getuid ] (syscall_handler_t *) sys_getuid16, [ __NR_stime ] = um_stime, - [ __NR_ptrace ] = sys_ptrace, - [ __NR_alarm ] = sys_alarm, - [ __NR_oldfstat ] = sys_fstat, - [ __NR_pause ] = sys_pause, - [ __NR_utime ] = sys_utime, - [ __NR_stty ] = sys_ni_syscall, - [ __NR_gtty ] = sys_ni_syscall, - [ __NR_access ] = sys_access, - [ __NR_nice ] = sys_nice, - [ __NR_ftime ] = sys_ni_syscall, - [ __NR_sync ] = sys_sync, - [ __NR_kill ] = sys_kill, - [ __NR_rename ] = sys_rename, - [ __NR_mkdir ] = sys_mkdir, - [ __NR_rmdir ] = sys_rmdir, + [ __NR_ptrace ] (syscall_handler_t *) sys_ptrace, + [ __NR_alarm ] (syscall_handler_t *) sys_alarm, + [ __NR_oldfstat ] (syscall_handler_t *) sys_fstat, + [ __NR_pause ] (syscall_handler_t *) sys_pause, + [ __NR_utime ] (syscall_handler_t *) sys_utime, + [ __NR_stty ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_access ] (syscall_handler_t *) sys_access, + [ __NR_nice ] (syscall_handler_t *) sys_nice, + [ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_sync ] (syscall_handler_t *) sys_sync, + [ __NR_kill ] (syscall_handler_t *) sys_kill, + [ __NR_rename ] (syscall_handler_t *) sys_rename, + [ __NR_mkdir ] (syscall_handler_t *) sys_mkdir, + [ __NR_rmdir ] (syscall_handler_t *) sys_rmdir, /* Declared differently in asm/unistd.h */ [ __NR_dup ] = (syscall_handler_t *) sys_dup, - [ __NR_pipe ] = sys_pipe, - [ __NR_times ] = sys_times, - [ __NR_prof ] = sys_ni_syscall, - [ __NR_brk ] = sys_brk, - [ __NR_setgid ] = sys_setgid16, - [ __NR_getgid ] = sys_getgid16, - [ __NR_signal ] = sys_signal, - [ __NR_geteuid ] = sys_geteuid16, - [ __NR_getegid ] = sys_getegid16, - [ __NR_acct ] = sys_acct, - [ __NR_umount2 ] = sys_umount, - [ __NR_lock ] = sys_ni_syscall, - [ __NR_ioctl ] = sys_ioctl, - [ __NR_fcntl ] = sys_fcntl, - [ __NR_mpx ] = sys_ni_syscall, - [ __NR_setpgid ] = sys_setpgid, - [ __NR_ulimit ] = sys_ni_syscall, - [ __NR_oldolduname ] = sys_olduname, - [ __NR_umask ] = sys_umask, - [ __NR_chroot ] = sys_chroot, - [ __NR_ustat ] = sys_ustat, - [ __NR_dup2 ] = sys_dup2, - [ __NR_getppid ] = sys_getppid, - [ __NR_getpgrp ] = sys_getpgrp, + [ __NR_pipe ] (syscall_handler_t *) sys_pipe, + [ __NR_times ] (syscall_handler_t *) sys_times, + [ __NR_prof ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_brk ] (syscall_handler_t *) sys_brk, + [ __NR_setgid ] (syscall_handler_t *) sys_setgid16, + [ __NR_getgid ] (syscall_handler_t *) sys_getgid16, + [ __NR_signal ] (syscall_handler_t *) sys_signal, + [ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16, + [ __NR_getegid ] (syscall_handler_t *) sys_getegid16, + [ __NR_acct ] (syscall_handler_t *) sys_acct, + [ __NR_umount2 ] (syscall_handler_t *) sys_umount, + [ __NR_lock ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_ioctl ] (syscall_handler_t *) sys_ioctl, + [ __NR_fcntl ] (syscall_handler_t *) sys_fcntl, + [ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_setpgid ] (syscall_handler_t *) sys_setpgid, + [ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_oldolduname ] (syscall_handler_t *) sys_olduname, + [ __NR_umask ] (syscall_handler_t *) sys_umask, + [ __NR_chroot ] (syscall_handler_t *) sys_chroot, + [ __NR_ustat ] (syscall_handler_t *) sys_ustat, + [ __NR_dup2 ] (syscall_handler_t *) sys_dup2, + [ __NR_getppid ] (syscall_handler_t *) sys_getppid, + [ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp, [ __NR_setsid ] = (syscall_handler_t *) sys_setsid, - [ __NR_sigaction ] = sys_sigaction, - [ __NR_sgetmask ] = sys_sgetmask, - [ __NR_ssetmask ] = sys_ssetmask, - [ __NR_setreuid ] = sys_setreuid16, - [ __NR_setregid ] = sys_setregid16, - [ __NR_sigsuspend ] = sys_sigsuspend, - [ __NR_sigpending ] = sys_sigpending, - [ __NR_sethostname ] = sys_sethostname, - [ __NR_setrlimit ] = sys_setrlimit, - [ __NR_getrlimit ] = sys_old_getrlimit, - [ __NR_getrusage ] = sys_getrusage, - [ __NR_gettimeofday ] = sys_gettimeofday, - [ __NR_settimeofday ] = sys_settimeofday, - [ __NR_getgroups ] = sys_getgroups16, - [ __NR_setgroups ] = sys_setgroups16, - [ __NR_symlink ] = sys_symlink, - [ __NR_oldlstat ] = sys_lstat, - [ __NR_readlink ] = sys_readlink, - [ __NR_uselib ] = sys_uselib, + [ __NR_sigaction ] (syscall_handler_t *) sys_sigaction, + [ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask, + [ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask, + [ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16, + [ __NR_setregid ] (syscall_handler_t *) sys_setregid16, + [ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend, + [ __NR_sigpending ] (syscall_handler_t *) sys_sigpending, + [ __NR_sethostname ] (syscall_handler_t *) sys_sethostname, + [ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit, + [ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit, + [ __NR_getrusage ] (syscall_handler_t *) sys_getrusage, + [ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday, + [ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday, + [ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16, + [ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16, + [ __NR_symlink ] (syscall_handler_t *) sys_symlink, + [ __NR_oldlstat ] (syscall_handler_t *) sys_lstat, + [ __NR_readlink ] (syscall_handler_t *) sys_readlink, + [ __NR_uselib ] (syscall_handler_t *) sys_uselib, [ __NR_swapon ] = (syscall_handler_t *) sys_swapon, - [ __NR_reboot ] = sys_reboot, + [ __NR_reboot ] (syscall_handler_t *) sys_reboot, [ __NR_readdir ] = old_readdir, - [ __NR_munmap ] = sys_munmap, - [ __NR_truncate ] = sys_truncate, - [ __NR_ftruncate ] = sys_ftruncate, - [ __NR_fchmod ] = sys_fchmod, - [ __NR_fchown ] = sys_fchown16, - [ __NR_getpriority ] = sys_getpriority, - [ __NR_setpriority ] = sys_setpriority, - [ __NR_profil ] = sys_ni_syscall, - [ __NR_statfs ] = sys_statfs, - [ __NR_fstatfs ] = sys_fstatfs, - [ __NR_ioperm ] = sys_ni_syscall, - [ __NR_socketcall ] = sys_socketcall, - [ __NR_syslog ] = sys_syslog, - [ __NR_setitimer ] = sys_setitimer, - [ __NR_getitimer ] = sys_getitimer, - [ __NR_stat ] = sys_newstat, - [ __NR_lstat ] = sys_newlstat, - [ __NR_fstat ] = sys_newfstat, - [ __NR_olduname ] = sys_uname, - [ __NR_iopl ] = sys_ni_syscall, - [ __NR_vhangup ] = sys_vhangup, - [ __NR_idle ] = sys_ni_syscall, + [ __NR_munmap ] (syscall_handler_t *) sys_munmap, + [ __NR_truncate ] (syscall_handler_t *) sys_truncate, + [ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate, + [ __NR_fchmod ] (syscall_handler_t *) sys_fchmod, + [ __NR_fchown ] (syscall_handler_t *) sys_fchown16, + [ __NR_getpriority ] (syscall_handler_t *) sys_getpriority, + [ __NR_setpriority ] (syscall_handler_t *) sys_setpriority, + [ __NR_profil ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_statfs ] (syscall_handler_t *) sys_statfs, + [ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs, + [ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_socketcall ] (syscall_handler_t *) sys_socketcall, + [ __NR_syslog ] (syscall_handler_t *) sys_syslog, + [ __NR_setitimer ] (syscall_handler_t *) sys_setitimer, + [ __NR_getitimer ] (syscall_handler_t *) sys_getitimer, + [ __NR_stat ] (syscall_handler_t *) sys_newstat, + [ __NR_lstat ] (syscall_handler_t *) sys_newlstat, + [ __NR_fstat ] (syscall_handler_t *) sys_newfstat, + [ __NR_olduname ] (syscall_handler_t *) sys_uname, + [ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_vhangup ] (syscall_handler_t *) sys_vhangup, + [ __NR_idle ] (syscall_handler_t *) sys_ni_syscall, [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4, [ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff, - [ __NR_sysinfo ] = sys_sysinfo, - [ __NR_ipc ] = sys_ipc, - [ __NR_fsync ] = sys_fsync, - [ __NR_sigreturn ] = sys_sigreturn, - [ __NR_clone ] = sys_clone, - [ __NR_setdomainname ] = sys_setdomainname, - [ __NR_uname ] = sys_newuname, - [ __NR_adjtimex ] = sys_adjtimex, - [ __NR_mprotect ] = sys_mprotect, - [ __NR_sigprocmask ] = sys_sigprocmask, - [ __NR_create_module ] = sys_ni_syscall, - [ __NR_init_module ] = sys_init_module, - [ __NR_delete_module ] = sys_delete_module, - [ __NR_get_kernel_syms ] = sys_ni_syscall, - [ __NR_quotactl ] = sys_quotactl, - [ __NR_getpgid ] = sys_getpgid, - [ __NR_fchdir ] = sys_fchdir, - [ __NR_bdflush ] = sys_bdflush, - [ __NR_sysfs ] = sys_sysfs, - [ __NR_personality ] = sys_personality, - [ __NR_afs_syscall ] = sys_ni_syscall, - [ __NR_setfsuid ] = sys_setfsuid16, - [ __NR_setfsgid ] = sys_setfsgid16, - [ __NR__llseek ] = sys_llseek, - [ __NR_getdents ] = sys_getdents, + [ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo, + [ __NR_ipc ] (syscall_handler_t *) sys_ipc, + [ __NR_fsync ] (syscall_handler_t *) sys_fsync, + [ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn, + [ __NR_clone ] (syscall_handler_t *) sys_clone, + [ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname, + [ __NR_uname ] (syscall_handler_t *) sys_newuname, + [ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex, + [ __NR_mprotect ] (syscall_handler_t *) sys_mprotect, + [ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask, + [ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_init_module ] (syscall_handler_t *) sys_init_module, + [ __NR_delete_module ] (syscall_handler_t *) sys_delete_module, + [ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_quotactl ] (syscall_handler_t *) sys_quotactl, + [ __NR_getpgid ] (syscall_handler_t *) sys_getpgid, + [ __NR_fchdir ] (syscall_handler_t *) sys_fchdir, + [ __NR_bdflush ] (syscall_handler_t *) sys_bdflush, + [ __NR_sysfs ] (syscall_handler_t *) sys_sysfs, + [ __NR_personality ] (syscall_handler_t *) sys_personality, + [ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16, + [ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16, + [ __NR__llseek ] (syscall_handler_t *) sys_llseek, + [ __NR_getdents ] (syscall_handler_t *) sys_getdents, [ __NR__newselect ] = (syscall_handler_t *) sys_select, - [ __NR_flock ] = sys_flock, - [ __NR_msync ] = sys_msync, - [ __NR_readv ] = sys_readv, - [ __NR_writev ] = sys_writev, - [ __NR_getsid ] = sys_getsid, - [ __NR_fdatasync ] = sys_fdatasync, + [ __NR_flock ] (syscall_handler_t *) sys_flock, + [ __NR_msync ] (syscall_handler_t *) sys_msync, + [ __NR_readv ] (syscall_handler_t *) sys_readv, + [ __NR_writev ] (syscall_handler_t *) sys_writev, + [ __NR_getsid ] (syscall_handler_t *) sys_getsid, + [ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync, [ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl, - [ __NR_mlock ] = sys_mlock, - [ __NR_munlock ] = sys_munlock, - [ __NR_mlockall ] = sys_mlockall, - [ __NR_munlockall ] = sys_munlockall, - [ __NR_sched_setparam ] = sys_sched_setparam, - [ __NR_sched_getparam ] = sys_sched_getparam, - [ __NR_sched_setscheduler ] = sys_sched_setscheduler, - [ __NR_sched_getscheduler ] = sys_sched_getscheduler, + [ __NR_mlock ] (syscall_handler_t *) sys_mlock, + [ __NR_munlock ] (syscall_handler_t *) sys_munlock, + [ __NR_mlockall ] (syscall_handler_t *) sys_mlockall, + [ __NR_munlockall ] (syscall_handler_t *) sys_munlockall, + [ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam, + [ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam, + [ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler, + [ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler, [ __NR_sched_yield ] = (syscall_handler_t *) yield, - [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max, - [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min, - [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval, - [ __NR_nanosleep ] = sys_nanosleep, - [ __NR_mremap ] = sys_mremap, - [ __NR_setresuid ] = sys_setresuid16, - [ __NR_getresuid ] = sys_getresuid16, - [ __NR_vm86 ] = sys_ni_syscall, - [ __NR_query_module ] = sys_ni_syscall, - [ __NR_poll ] = sys_poll, - [ __NR_nfsservctl ] = NFSSERVCTL, - [ __NR_setresgid ] = sys_setresgid16, - [ __NR_getresgid ] = sys_getresgid16, - [ __NR_prctl ] = sys_prctl, - [ __NR_rt_sigreturn ] = sys_rt_sigreturn, - [ __NR_rt_sigaction ] = sys_rt_sigaction, - [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask, - [ __NR_rt_sigpending ] = sys_rt_sigpending, - [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait, - [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo, - [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend, - [ __NR_pread64 ] = sys_pread64, - [ __NR_pwrite64 ] = sys_pwrite64, - [ __NR_chown ] = sys_chown16, - [ __NR_getcwd ] = sys_getcwd, - [ __NR_capget ] = sys_capget, - [ __NR_capset ] = sys_capset, - [ __NR_sigaltstack ] = sys_sigaltstack, - [ __NR_sendfile ] = sys_sendfile, - [ __NR_getpmsg ] = sys_ni_syscall, - [ __NR_putpmsg ] = sys_ni_syscall, - [ __NR_vfork ] = sys_vfork, - [ __NR_ugetrlimit ] = sys_getrlimit, - [ __NR_mmap2 ] = sys_mmap2, - [ __NR_truncate64 ] = sys_truncate64, - [ __NR_ftruncate64 ] = sys_ftruncate64, - [ __NR_stat64 ] = sys_stat64, - [ __NR_lstat64 ] = sys_lstat64, - [ __NR_fstat64 ] = sys_fstat64, - [ __NR_fcntl64 ] = sys_fcntl64, - [ __NR_getdents64 ] = sys_getdents64, - [ __NR_gettid ] = sys_gettid, - [ __NR_readahead ] = sys_readahead, - [ __NR_setxattr ] = sys_ni_syscall, - [ __NR_lsetxattr ] = sys_ni_syscall, - [ __NR_fsetxattr ] = sys_ni_syscall, - [ __NR_getxattr ] = sys_ni_syscall, - [ __NR_lgetxattr ] = sys_ni_syscall, - [ __NR_fgetxattr ] = sys_ni_syscall, - [ __NR_listxattr ] = sys_ni_syscall, - [ __NR_llistxattr ] = sys_ni_syscall, - [ __NR_flistxattr ] = sys_ni_syscall, - [ __NR_removexattr ] = sys_ni_syscall, - [ __NR_lremovexattr ] = sys_ni_syscall, - [ __NR_fremovexattr ] = sys_ni_syscall, - [ __NR_tkill ] = sys_tkill, - [ __NR_sendfile64 ] = sys_sendfile64, - [ __NR_futex ] = sys_futex, - [ __NR_sched_setaffinity ] = sys_sched_setaffinity, - [ __NR_sched_getaffinity ] = sys_sched_getaffinity, - [ __NR_io_setup ] = sys_io_setup, - [ __NR_io_destroy ] = sys_io_destroy, - [ __NR_io_getevents ] = sys_io_getevents, - [ __NR_io_submit ] = sys_io_submit, - [ __NR_io_cancel ] = sys_io_cancel, - [ __NR_exit_group ] = sys_exit_group, - [ __NR_lookup_dcookie ] = sys_lookup_dcookie, - [ __NR_epoll_create ] = sys_epoll_create, - [ __NR_epoll_ctl ] = sys_epoll_ctl, - [ __NR_epoll_wait ] = sys_epoll_wait, - [ __NR_remap_file_pages ] = sys_remap_file_pages, - [ __NR_set_tid_address ] = sys_set_tid_address, + [ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max, + [ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min, + [ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval, + [ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep, + [ __NR_mremap ] (syscall_handler_t *) sys_mremap, + [ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16, + [ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16, + [ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_poll ] (syscall_handler_t *) sys_poll, + [ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL, + [ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16, + [ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16, + [ __NR_prctl ] (syscall_handler_t *) sys_prctl, + [ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn, + [ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction, + [ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask, + [ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending, + [ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait, + [ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo, + [ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend, + [ __NR_pread64 ] (syscall_handler_t *) sys_pread64, + [ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64, + [ __NR_chown ] (syscall_handler_t *) sys_chown16, + [ __NR_getcwd ] (syscall_handler_t *) sys_getcwd, + [ __NR_capget ] (syscall_handler_t *) sys_capget, + [ __NR_capset ] (syscall_handler_t *) sys_capset, + [ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack, + [ __NR_sendfile ] (syscall_handler_t *) sys_sendfile, + [ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_vfork ] (syscall_handler_t *) sys_vfork, + [ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit, + [ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2, + [ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64, + [ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64, + [ __NR_stat64 ] (syscall_handler_t *) sys_stat64, + [ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64, + [ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64, + [ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64, + [ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64, + [ 223 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_gettid ] (syscall_handler_t *) sys_gettid, + [ __NR_readahead ] (syscall_handler_t *) sys_readahead, + [ __NR_setxattr ] (syscall_handler_t *) sys_setxattr, + [ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr, + [ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr, + [ __NR_getxattr ] (syscall_handler_t *) sys_getxattr, + [ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr, + [ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr, + [ __NR_listxattr ] (syscall_handler_t *) sys_listxattr, + [ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr, + [ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr, + [ __NR_removexattr ] (syscall_handler_t *) sys_removexattr, + [ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr, + [ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr, + [ __NR_tkill ] (syscall_handler_t *) sys_tkill, + [ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64, + [ __NR_futex ] (syscall_handler_t *) sys_futex, + [ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity, + [ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity, + [ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_io_setup ] (syscall_handler_t *) sys_io_setup, + [ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy, + [ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents, + [ __NR_io_submit ] (syscall_handler_t *) sys_io_submit, + [ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel, + [ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64, + [ 251 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_exit_group ] (syscall_handler_t *) sys_exit_group, + [ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie, + [ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create, + [ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl, + [ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait, + [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages, + [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address, + [ __NR_timer_create ] (syscall_handler_t *) sys_timer_create, + [ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime, + [ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime, + [ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun, + [ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete, + [ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime, + [ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime, + [ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres, + [ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep, + [ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64, + [ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64, + [ __NR_tgkill ] (syscall_handler_t *) sys_tgkill, + [ __NR_utimes ] (syscall_handler_t *) sys_utimes, + [ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64, + [ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall, ARCH_SYSCALLS [ LAST_SYSCALL + 1 ... NR_syscalls ] = diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c index 2af5fc2e5..a549b3b14 100644 --- a/arch/um/kernel/syscall_kern.c +++ b/arch/um/kernel/syscall_kern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -36,32 +36,23 @@ long um_mount(char * dev_name, char * dir_name, char * type, long sys_fork(void) { - struct task_struct *p; + long ret; current->thread.forking = 1; - p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL); + ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL); current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); -} - -long sys_clone(unsigned long clone_flags, unsigned long newsp) -{ - struct task_struct *p; - - current->thread.forking = 1; - p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL); - current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); + return(ret); } long sys_vfork(void) { - struct task_struct *p; + long ret; current->thread.forking = 1; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL); + ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, + NULL); current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); + return(ret); } /* common code for old and new mmaps */ @@ -113,11 +104,11 @@ struct mmap_arg_struct { unsigned long offset; }; -int old_mmap(unsigned long addr, unsigned long len, +long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) { - int err = -EINVAL; + long err = -EINVAL; if (offset & ~PAGE_MASK) goto out; @@ -129,50 +120,19 @@ int old_mmap(unsigned long addr, unsigned long len, * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -int sys_pipe(unsigned long * fildes) +long sys_pipe(unsigned long * fildes) { int fd[2]; - int error; + long error; error = do_pipe(fd); if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) + if (copy_to_user(fildes, fd, sizeof(fd))) error = -EFAULT; } return error; } -int sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * @@ -254,13 +214,13 @@ int sys_ipc (uint call, int first, int second, return sys_shmctl (first, second, (struct shmid_ds *) ptr); default: - return -EINVAL; + return -ENOSYS; } } -int sys_uname(struct old_utsname * name) +long sys_uname(struct old_utsname * name) { - int err; + long err; if (!name) return -EFAULT; down_read(&uts_sem); @@ -269,9 +229,9 @@ int sys_uname(struct old_utsname * name) return err?-EFAULT:0; } -int sys_olduname(struct oldold_utsname * name) +long sys_olduname(struct oldold_utsname * name) { - int error; + long error; if (!name) return -EFAULT; @@ -303,11 +263,6 @@ int sys_olduname(struct oldold_utsname * name) return error; } -int sys_sigaltstack(const stack_t *uss, stack_t *uoss) -{ - return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); -} - long execute_syscall(void *r) { return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r)); diff --git a/arch/um/kernel/syscall_user.c b/arch/um/kernel/syscall_user.c index 3712286fe..01b711e00 100644 --- a/arch/um/kernel/syscall_user.c +++ b/arch/um/kernel/syscall_user.c @@ -11,7 +11,7 @@ struct { int syscall; int pid; - int result; + long result; struct timeval start; struct timeval end; } syscall_record[1024]; @@ -30,7 +30,7 @@ int record_syscall_start(int syscall) return(index); } -void record_syscall_end(int index, int result) +void record_syscall_end(int index, long result) { syscall_record[index].result = result; gettimeofday(&syscall_record[index].end, NULL); diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index b43c21466..ea24ebf53 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -6,6 +6,7 @@ #include "linux/sched.h" #include "linux/kernel.h" #include "linux/module.h" +#include "linux/kallsyms.h" #include "asm/page.h" #include "asm/processor.h" #include "sysrq.h" @@ -13,21 +14,20 @@ void show_trace(unsigned long * stack) { - int i; + /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from + * arch/i386/kernel/traps.c. */ unsigned long addr; if (!stack) stack = (unsigned long*) &stack; - printk("Call Trace: "); - i = 1; + printk("Call Trace: \n"); while (((long) stack & (THREAD_SIZE-1)) != 0) { addr = *stack++; if (__kernel_text_address(addr)) { - if (i && ((i % 6) == 0)) - printk("\n "); - printk("[<%08lx>] ", addr); - i++; + printk(" [<%08lx>]", addr); + print_symbol(" %s", addr); + printk("\n"); } } printk("\n"); @@ -44,13 +44,7 @@ void dump_stack(void) } EXPORT_SYMBOL(dump_stack); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +void show_stack(struct task_struct *task, unsigned long *sp) +{ + show_trace(sp); +} diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c index 3fd42081d..b1674bc13 100644 --- a/arch/um/kernel/tempfile.c +++ b/arch/um/kernel/tempfile.c @@ -28,6 +28,7 @@ static void __init find_tempdir(void) } if((dir == NULL) || (*dir == '\0')) dir = "/tmp"; + tempdir = malloc(strlen(dir) + 2); if(tempdir == NULL){ fprintf(stderr, "Failed to malloc tempdir, " @@ -49,7 +50,8 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink) else *tempname = 0; strcat(tempname, template); - if((fd = mkstemp(tempname)) < 0){ + fd = mkstemp(tempname); + if(fd < 0){ fprintf(stderr, "open - cannot create %s: %s\n", tempname, strerror(errno)); return -1; @@ -59,7 +61,8 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink) return -1; } if(out_tempname){ - if((*out_tempname = strdup(tempname)) == NULL){ + *out_tempname = strdup(tempname); + if(*out_tempname == NULL){ perror("strdup"); return -1; } diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 6f0d7573e..96691a0df 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -4,24 +4,33 @@ */ #include +#include #include #include #include #include #include -#include "linux/module.h" #include "user_util.h" #include "kern_util.h" #include "user.h" #include "process.h" #include "signal_user.h" #include "time_user.h" +#include "kern_constants.h" + +/* XXX This really needs to be declared and initialized in a kernel file since + * it's in + */ +extern struct timespec wall_to_monotonic; extern struct timeval xtime; +struct timeval local_offset = { 0, 0 }; + void timer(void) { gettimeofday(&xtime, NULL); + timeradd(&xtime, &local_offset, &xtime); } void set_interval(int timer_type) @@ -44,6 +53,15 @@ void enable_timer(void) errno); } +void disable_timer(void) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); +} + void switch_timers(int to_real) { struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); @@ -66,7 +84,7 @@ void switch_timers(int to_real) errno); } -void idle_timer(void) +void uml_idle_timer(void) { if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) panic("Couldn't unset SIGVTALRM handler"); @@ -76,14 +94,23 @@ void idle_timer(void) set_interval(ITIMER_REAL); } +extern int do_posix_clock_monotonic_gettime(struct timespec *tp); + void time_init(void) { + struct timespec now; + if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) panic("Couldn't set SIGVTALRM handler"); set_interval(ITIMER_VIRTUAL); + + do_posix_clock_monotonic_gettime(&now); + wall_to_monotonic.tv_sec = -now.tv_sec; + wall_to_monotonic.tv_nsec = -now.tv_nsec; } -struct timeval local_offset = { 0, 0 }; +/* Declared in linux/time.h, which can't be included here */ +extern void clock_was_set(void); void do_gettimeofday(struct timeval *tv) { @@ -96,15 +123,13 @@ void do_gettimeofday(struct timeval *tv) clock_was_set(); } -EXPORT_SYMBOL(do_gettimeofday); - int do_settimeofday(struct timespec *tv) { struct timeval now; unsigned long flags; struct timeval tv_in; - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC) return -EINVAL; tv_in.tv_sec = tv->tv_sec; @@ -114,9 +139,9 @@ int do_settimeofday(struct timespec *tv) gettimeofday(&now, NULL); timersub(&tv_in, &now, &local_offset); time_unlock(flags); -} -EXPORT_SYMBOL(do_settimeofday); + return(0); +} void idle_sleep(int secs) { diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 752fd03f2..aee0f7f1a 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -20,6 +20,7 @@ #include "user_util.h" #include "time_user.h" #include "mode.h" +#include "os.h" u64 jiffies_64; @@ -30,22 +31,63 @@ int hz(void) return(HZ); } +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies_64 * (1000000000 / HZ); +} + /* Changed at early boot */ int timer_irq_inited = 0; -/* missed_ticks will be modified after kernel memory has been - * write-protected, so this puts it in a section which will be left - * write-enabled. - */ -int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS]; +static int first_tick; +static unsigned long long prev_usecs; +#ifdef CONFIG_UML_REAL_TIME_CLOCK +static long long delta; /* Deviation per interval */ +#endif + +#define MILLION 1000000 void timer_irq(union uml_pt_regs *regs) { - int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu]; + unsigned long long ticks = 0; + + if(!timer_irq_inited){ + /* This is to ensure that ticks don't pile up when + * the timer handler is suspended */ + first_tick = 0; + return; + } + + if(first_tick){ +#ifdef CONFIG_UML_REAL_TIME_CLOCK + /* We've had 1 tick */ + unsigned long long usecs = os_usecs(); + + delta += usecs - prev_usecs; + prev_usecs = usecs; - if(!timer_irq_inited) return; - missed_ticks[cpu] = 0; - while(ticks--) do_IRQ(TIMER_IRQ, regs); + /* Protect against the host clock being set backwards */ + if(delta < 0) + delta = 0; + + ticks += (delta * HZ) / MILLION; + delta -= (ticks * MILLION) / HZ; +#else + ticks = 1; +#endif + } + else { + prev_usecs = os_usecs(); + first_tick = 1; + } + + while(ticks > 0){ + do_IRQ(TIMER_IRQ, regs); + ticks--; + } } void boot_timer_handler(int sig) @@ -58,12 +100,15 @@ void boot_timer_handler(int sig) do_timer(®s); } -void um_timer(int irq, void *dev, struct pt_regs *regs) +irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) { + unsigned long flags; + do_timer(regs); - write_seqlock(&xtime_lock); + write_seqlock_irqsave(&xtime_lock, flags); timer(); - write_sequnlock(&xtime_lock); + write_sequnlock_irqrestore(&xtime_lock, flags); + return(IRQ_HANDLED); } long um_time(int * tloc) @@ -81,12 +126,12 @@ long um_time(int * tloc) long um_stime(int * tptr) { int value; - struct timeval new; + struct timespec new; if (get_user(value, tptr)) return -EFAULT; new.tv_sec = value; - new.tv_usec = 0; + new.tv_nsec = 0; do_settimeofday(&new); return 0; } @@ -110,7 +155,7 @@ void __udelay(um_udelay_t usecs) { int i, n; - n = (loops_per_jiffy * HZ * usecs) / 1000000; + n = (loops_per_jiffy * HZ * usecs) / MILLION; for(i=0;ithread_info->cpu == 0) + local_irq_enable(); + if(current_thread->cpu == 0) timer_irq(regs); } @@ -136,6 +181,7 @@ static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED; unsigned long time_lock(void) { unsigned long flags; + spin_lock_irqsave(&timer_spinlock, flags); return(flags); } @@ -150,8 +196,8 @@ int __init timer_init(void) int err; CHOOSE_MODE(user_time_init_tt(), user_time_init_skas()); - if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", - NULL)) != 0) + err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); + if(err != 0) printk(KERN_ERR "timer_init : request_irq failed - " "errno = %d\n", -err); timer_irq_inited = 1; @@ -160,7 +206,6 @@ int __init timer_init(void) __initcall(timer_init); - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 7925dc459..cba33ef6d 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -16,12 +16,15 @@ #include "asm/tlbflush.h" #include "asm/a.out.h" #include "asm/current.h" +#include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" #include "chan_kern.h" #include "mconsole_kern.h" #include "2_5compat.h" +#include "mem.h" +#include "mem_kern.h" int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out) @@ -51,12 +54,10 @@ int handle_page_fault(unsigned long address, unsigned long ip, if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; page = address & PAGE_MASK; - if(page == (unsigned long) current->thread_info + PAGE_SIZE) - panic("Kernel stack overflow"); pgd = pgd_offset(mm, page); pmd = pmd_offset(pgd, page); - survive: do { + survive: switch (handle_mm_fault(mm, vma, address, is_write)){ case VM_FAULT_MINOR: current->min_flt++; @@ -75,10 +76,10 @@ int handle_page_fault(unsigned long address, unsigned long ip, } pte = pte_offset_kernel(pmd, page); } while(!pte_present(*pte)); + err = 0; *pte = pte_mkyoung(*pte); if(pte_write(*pte)) *pte = pte_mkdirty(*pte); flush_tlb_page(vma, page); - err = 0; out: up_read(&mm->mmap_sem); return(err); @@ -94,10 +95,36 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - err = -ENOMEM; goto out; } +LIST_HEAD(physmem_remappers); + +void register_remapper(struct remapper *info) +{ + list_add(&info->list, &physmem_remappers); +} + +static int check_remapped_addr(unsigned long address, int is_write) +{ + struct remapper *remapper; + struct list_head *ele; + __u64 offset; + int fd; + + fd = phys_mapping(__pa(address), &offset); + if(fd == -1) + return(0); + + list_for_each(ele, &physmem_remappers){ + remapper = list_entry(ele, struct remapper, list); + if((*remapper->proc)(fd, address, is_write, offset)) + return(1); + } + + return(0); +} + unsigned long segv(unsigned long address, unsigned long ip, int is_write, int is_user, void *sc) { @@ -109,7 +136,9 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write, flush_tlb_kernel_vm(); return(0); } - if(current->mm == NULL) + else if(check_remapped_addr(address & PAGE_MASK, is_write)) + return(0); + else if(current->mm == NULL) panic("Segfault with no mm"); err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); @@ -120,9 +149,8 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write, current->thread.fault_addr = (void *) address; do_longjmp(catcher, 1); } - else if(current->thread.fault_addr != NULL){ + else if(current->thread.fault_addr != NULL) panic("fault_addr set but no fault catcher"); - } else if(arch_fixup(ip, sc)) return(0); @@ -155,8 +183,6 @@ void bad_segv(unsigned long address, unsigned long ip, int is_write) { struct siginfo si; - printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx " - "(ip 0x%lx)\n", current->comm, current->pid, address, ip); si.si_signo = SIGSEGV; si.si_code = SEGV_ACCERR; si.si_addr = (void *) address; @@ -180,6 +206,11 @@ void bus_handler(int sig, union uml_pt_regs *regs) else relay_signal(sig, regs); } +void winch(int sig, union uml_pt_regs *regs) +{ + do_IRQ(WINCH_IRQ, regs); +} + void trap_init(void) { } diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c index 63812e597..d12eac64a 100644 --- a/arch/um/kernel/trap_user.c +++ b/arch/um/kernel/trap_user.c @@ -5,11 +5,9 @@ #include #include -#include #include #include #include -#include #include #include #include @@ -34,7 +32,14 @@ void kill_child_dead(int pid) { kill(pid, SIGKILL); kill(pid, SIGCONT); - while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); + do { + int n; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + if (n > 0) + kill(pid, SIGCONT); + else + break; + } while(1); } /* Unlocked - don't care if this is a bit off */ @@ -82,6 +87,8 @@ struct signal_info sig_info[] = { .is_irq = 0 }, [ SIGILL ] { .handler = relay_signal, .is_irq = 0 }, + [ SIGWINCH ] { .handler = winch, + .is_irq = 1 }, [ SIGBUS ] { .handler = bus_handler, .is_irq = 0 }, [ SIGSEGV] { .handler = segv_handler, @@ -102,12 +109,11 @@ void sig_handler(int sig, struct sigcontext sc) sig, &sc); } -extern int timer_irq_inited, missed_ticks[]; +extern int timer_irq_inited; void alarm_handler(int sig, struct sigcontext sc) { if(!timer_irq_inited) return; - missed_ticks[cpu()]++; if(sig == SIGALRM) switch_timers(0); @@ -121,9 +127,9 @@ void alarm_handler(int sig, struct sigcontext sc) void do_longjmp(void *b, int val) { - jmp_buf *buf = b; + sigjmp_buf *buf = b; - longjmp(*buf, val); + siglongjmp(*buf, val); } /* diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile index 439688b0d..1fa49c49b 100644 --- a/arch/um/kernel/tt/Makefile +++ b/arch/um/kernel/tt/Makefile @@ -1,13 +1,14 @@ # -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # extra-y := unmap_fin.o +clean-files := unmap_tmp.o obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ - uaccess_user.o sys-$(SUBARCH)/ + uaccess.o uaccess_user.o sys-$(SUBARCH)/ obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ @@ -20,12 +21,9 @@ UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< -$(O_TARGET) : $(obj)/unmap_fin.o - $(obj)/unmap.o: $(src)/unmap.c $(CC) $(UNMAP_CFLAGS) -c -o $@ $< -$(obj)/unmap_fin.o : $(src)/unmap.o - ld -r -o $@ $< -lc -L/usr/lib - -clean : +$(obj)/unmap_fin.o : $(obj)/unmap.o + ld -r -o $(obj)/unmap_tmp.o $< -lc -L/usr/lib + objcopy $(obj)/unmap_tmp.o $@ -G switcheroo diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index afd94713d..065b504a6 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -14,9 +14,11 @@ #include "kern_util.h" #include "irq_user.h" #include "time_user.h" +#include "signal_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" +#include "mode.h" static int exec_tramp(void *sig_stack) { @@ -38,8 +40,7 @@ void flush_thread_tt(void) do_exit(SIGKILL); } - new_pid = start_fork_tramp((void *) current->thread.kernel_stack, - stack, 0, exec_tramp); + new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); if(new_pid < 0){ printk(KERN_ERR "flush_thread : new thread failed, errno = %d\n", @@ -47,17 +48,19 @@ void flush_thread_tt(void) do_exit(SIGKILL); } - if(current->thread_info->cpu == 0) + if(current_thread->cpu == 0) forward_interrupts(new_pid); current->thread.request.op = OP_EXEC; current->thread.request.u.exec.pid = new_pid; - unprotect_stack((unsigned long) current->thread_info); + unprotect_stack((unsigned long) current_thread); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + change_sig(SIGUSR1, 0); enable_timer(); free_page(stack); protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current->thread_info); + task_protections((unsigned long) current_thread); force_flush_all(); unblock_signals(); } diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c index 35d108266..6d5fa825a 100644 --- a/arch/um/kernel/tt/exec_user.c +++ b/arch/um/kernel/tt/exec_user.c @@ -19,13 +19,18 @@ void do_exec(int old_pid, int new_pid) { unsigned long regs[FRAME_SIZE]; + int err; if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || - (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) || - (waitpid(new_pid, 0, WUNTRACED) < 0)) + (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) tracer_panic("do_exec failed to attach proc - errno = %d", errno); + CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); + if (err < 0) + tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", + errno); + if(ptrace_getregs(old_pid, regs) < 0) tracer_panic("do_exec failed to get registers - errno = %d", errno); diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h index b7c474518..e6d64eb86 100644 --- a/arch/um/kernel/tt/include/tt.h +++ b/arch/um/kernel/tt/include/tt.h @@ -24,11 +24,9 @@ extern void set_init_pid(int pid); extern int set_user_mode(void *task); extern void set_tracing(void *t, int tracing); extern int is_tracing(void *task); -extern int singlestepping_tt(void *t); -extern void clear_singlestep(void *t); extern void syscall_handler(int sig, union uml_pt_regs *regs); extern void exit_kernel(int pid, void *task); -extern int do_syscall(void *task, int pid); +extern int do_syscall(void *task, int pid, int local_using_sysemu); extern int is_valid_pid(int pid); extern void remap_data(void *segment_start, void *segment_end, int w); diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c index 0c39b2663..34090b8d2 100644 --- a/arch/um/kernel/tt/mem.c +++ b/arch/um/kernel/tt/mem.c @@ -18,7 +18,7 @@ void before_mem_tt(unsigned long brk_start) if(!jail || debug) remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); - remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1); + remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); } #ifdef CONFIG_HOST_2G_2G diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index e10db3f1f..308526745 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c @@ -25,14 +25,13 @@ void remap_data(void *segment_start, void *segment_end, int w) size = (unsigned long) segment_end - (unsigned long) segment_start; data = create_mem_file(size); - if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, - MAP_SHARED, data, 0)) == MAP_FAILED){ + addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); + if(addr == MAP_FAILED){ perror("mapping new data segment"); exit(1); } memcpy(addr, segment_start, size); - if(switcheroo(data, prot, addr, segment_start, - size) < 0){ + if(switcheroo(data, prot, addr, segment_start, size) < 0){ printf("switcheroo failed\n"); exit(1); } diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 7a2f330a3..b6a6153fd 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -28,7 +28,7 @@ void *switch_to_tt(void *prev, void *next, void *last) { - struct task_struct *from, *to; + struct task_struct *from, *to, *prev_sched; unsigned long flags; int err, vtalrm, alrm, prof, cpu; char c; @@ -62,16 +62,28 @@ void *switch_to_tt(void *prev, void *next, void *last) reading = 0; err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) - panic("write of switch_pipe failed, errno = %d", -err); + panic("write of switch_pipe failed, err = %d", -err); reading = 1; - if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD)) + if((from->exit_state == EXIT_ZOMBIE) || (from->exit_state == EXIT_DEAD)) os_kill_process(os_getpid(), 0); err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); + /* If the process that we have just scheduled away from has exited, + * then it needs to be killed here. The reason is that, even though + * it will kill itself when it next runs, that may be too late. Its + * stack will be freed, possibly before then, and if that happens, + * we have a use-after-free situation. So, it gets killed here + * in case it has not already killed itself. + */ + prev_sched = current->thread.prev_sched; + if((prev_sched->exit_state == EXIT_ZOMBIE) || + (prev_sched->exit_state == EXIT_DEAD)) + os_kill_ptraced_process(prev_sched->thread.mode.tt.extern_pid, 1); + /* This works around a nasty race with 'jail'. If we are switching * between two threads of a threaded app and the incoming process * runs before the outgoing process reaches the read, and it makes @@ -104,50 +116,92 @@ void *switch_to_tt(void *prev, void *next, void *last) void release_thread_tt(struct task_struct *task) { - os_kill_process(task->thread.mode.tt.extern_pid, 0); + int pid = task->thread.mode.tt.extern_pid; + + if(os_getpid() != pid) + os_kill_process(pid, 0); } void exit_thread_tt(void) { - close(current->thread.mode.tt.switch_pipe[0]); - close(current->thread.mode.tt.switch_pipe[1]); + os_close_file(current->thread.mode.tt.switch_pipe[0]); + os_close_file(current->thread.mode.tt.switch_pipe[1]); +} + +void suspend_new_thread(int fd) +{ + int err; + char c; + + os_stop_process(os_getpid()); + err = os_read_file(fd, &c, sizeof(c)); + if(err != sizeof(c)) + panic("read failed in suspend_new_thread, err = %d", -err); } void schedule_tail(task_t *prev); static void new_thread_handler(int sig) { + unsigned long disable; int (*fn)(void *); void *arg; fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; + UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); + disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | + (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); + SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; + suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); - block_signals(); + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + init_new_thread_signals(1); -#ifdef CONFIG_SMP - schedule_tail(current->thread.prev_sched); -#endif enable_timer(); free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); - force_flush_all(); - current->thread.prev_sched = NULL; change_sig(SIGUSR1, 1); change_sig(SIGVTALRM, 1); change_sig(SIGPROF, 1); - unblock_signals(); + local_irq_enable(); if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) do_exit(0); + + /* XXX No set_user_mode here because a newly execed process will + * immediately segfault on its non-existent IP, coming straight back + * to the signal handler, which will call set_user_mode on its way + * out. This should probably change since it's confusing. + */ } static int new_thread_proc(void *stack) { + /* local_irq_disable is needed to block out signals until this thread is + * properly scheduled. Otherwise, the tracing thread will get mighty + * upset about any signals that arrive before that. + * This has the complication that it sets the saved signal mask in + * the sigcontext to block signals. This gets restored when this + * thread (or a descendant, since they get a copy of this sigcontext) + * returns to userspace. + * So, this is compensated for elsewhere. + * XXX There is still a small window until local_irq_disable() actually + * finishes where signals are possible - shouldn't be a problem in + * practice since SIGIO hasn't been forwarded here yet, and the + * local_irq_disable should finish before a SIGVTALRM has time to be + * delivered. + */ + + local_irq_disable(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -156,7 +210,7 @@ static int new_thread_proc(void *stack) * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, * so it is blocked before it's called. They are re-enabled on sigreturn * despite the fact that they were blocked when the SIGUSR1 was issued because - * copy_thread copies the parent's signcontext, including the signal mask + * copy_thread copies the parent's sigcontext, including the signal mask * onto the signal frame. */ @@ -165,35 +219,33 @@ void finish_fork_handler(int sig) UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); -#ifdef CONFIG_SMP - schedule_tail(NULL); -#endif + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + enable_timer(); change_sig(SIGVTALRM, 1); local_irq_enable(); - force_flush_all(); if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current->thread_info); - - current->thread.prev_sched = NULL; + task_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); + local_irq_disable(); change_sig(SIGUSR1, 0); set_user_mode(current); } -static int sigusr1 = SIGUSR1; - int fork_tramp(void *stack) { - int sig = sigusr1; - local_irq_disable(); + arch_init_thread(); init_new_thread_stack(stack, finish_fork_handler); - kill(os_getpid(), sig); + os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); return(0); } @@ -213,8 +265,8 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, } err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); - if(err){ - printk("copy_thread : pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("copy_thread : pipe failed, err = %d\n", -err); return(err); } @@ -227,8 +279,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, clone_flags &= CLONE_VM; p->thread.temp_stack = stack; - new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack, - clone_flags, tramp); + new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); if(new_pid < 0){ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -new_pid); @@ -246,19 +297,29 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, current->thread.request.op = OP_FORK; current->thread.request.u.fork.pid = new_pid; os_usr1_process(os_getpid()); - return(0); + + /* Enable the signal and then disable it to ensure that it is handled + * here, and nowhere else. + */ + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); + err = 0; + return(err); } void reboot_tt(void) { current->thread.request.op = OP_REBOOT; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); } void halt_tt(void) { current->thread.request.op = OP_HALT; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); } void kill_off_processes_tt(void) @@ -285,6 +346,9 @@ void initial_thread_cb_tt(void (*proc)(void *), void *arg) current->thread.request.u.cb.proc = proc; current->thread.request.u.cb.arg = arg; os_usr1_process(os_getpid()); + change_sig(SIGUSR1, 1); + + change_sig(SIGUSR1, 0); } } @@ -377,8 +441,8 @@ static void mprotect_kernel_mem(int w) pages = (1 << CONFIG_KERNEL_STACK_ORDER); - start = (unsigned long) current->thread_info + PAGE_SIZE; - end = (unsigned long) current + PAGE_SIZE * pages; + start = (unsigned long) current_thread + PAGE_SIZE; + end = (unsigned long) current_thread + PAGE_SIZE * pages; protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1); protect_memory(end, high_physmem - end, 1, w, 1, 1); @@ -454,24 +518,9 @@ void set_init_pid(int pid) init_task.thread.mode.tt.extern_pid = pid; err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); - if(err) panic("Can't create switch pipe for init_task, errno = %d", - err); -} - -int singlestepping_tt(void *t) -{ - struct task_struct *task = t; - - if(task->thread.mode.tt.singlestep_syscall) - return(0); - return(task->ptrace & PT_DTRACE); -} - -void clear_singlestep(void *t) -{ - struct task_struct *task = t; - - task->ptrace &= ~PT_DTRACE; + if(err) + panic("Can't create switch pipe for init_task, errno = %d", + -err); } int start_uml_tt(void) @@ -479,9 +528,9 @@ int start_uml_tt(void) void *sp; int pages; - pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2; - sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE - - sizeof(unsigned long); + pages = (1 << CONFIG_KERNEL_STACK_ORDER); + sp = (void *) ((unsigned long) init_task.thread_info) + + pages * PAGE_SIZE - sizeof(unsigned long); return(tracer(start_kernel_proc, sp)); } diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile index 97d4f0bc1..9f9daf5c1 100644 --- a/arch/um/kernel/tt/ptproxy/Makefile +++ b/arch/um/kernel/tt/ptproxy/Makefile @@ -9,5 +9,3 @@ USER_OBJS := $(foreach file,$(obj-y),$(src)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean: diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c index 65504f8c6..458ecf9a4 100644 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ b/arch/um/kernel/tt/ptproxy/proxy.c @@ -15,7 +15,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml #include #include #include -#include #include #include #include @@ -273,7 +272,7 @@ void fake_child_exit(void) child_proxy(1, W_EXITCODE(0, 0)); while(debugger.waiting == 1){ - pid = waitpid(debugger.pid, &status, WUNTRACED); + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); if(pid != debugger.pid){ printk("fake_child_exit - waitpid failed, " "errno = %d\n", errno); @@ -281,7 +280,7 @@ void fake_child_exit(void) } debugger_proxy(status, debugger.pid); } - pid = waitpid(debugger.pid, &status, WUNTRACED); + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); if(pid != debugger.pid){ printk("fake_child_exit - waitpid failed, " "errno = %d\n", errno); @@ -293,10 +292,10 @@ void fake_child_exit(void) } char gdb_init_string[] = -"att 1 -b panic -b stop -handle SIGWINCH nostop noprint pass +"att 1 \n\ +b panic \n\ +b stop \n\ +handle SIGWINCH nostop noprint pass \n\ "; int start_debugger(char *prog, int startup, int stop, int *fd_out) @@ -304,7 +303,8 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out) int slave, child; slave = open_gdb_chan(); - if((child = fork()) == 0){ + child = fork(); + if(child == 0){ char *tempname = NULL; int fd; @@ -327,18 +327,19 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out) exit(1); #endif } - if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){ - printk("start_debugger : make_tempfile failed, errno = %d\n", - errno); + fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); + if(fd < 0){ + printk("start_debugger : make_tempfile failed," + "err = %d\n", -fd); exit(1); } - write(fd, gdb_init_string, sizeof(gdb_init_string) - 1); + os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); if(startup){ if(stop){ - write(fd, "b start_kernel\n", + os_write_file(fd, "b start_kernel\n", strlen("b start_kernel\n")); } - write(fd, "c\n", strlen("c\n")); + os_write_file(fd, "c\n", strlen("c\n")); } if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ printk("start_debugger : PTRACE_TRACEME failed, " diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index 50a120d5e..c42855aed 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -9,6 +9,7 @@ terms and conditions. #include #include #include +#include #include #include #include diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c index aad7e4b62..86ef67653 100644 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ b/arch/um/kernel/tt/ptproxy/wait.c @@ -56,21 +56,23 @@ int parent_wait_return(struct debugger *debugger, pid_t unused) int real_wait_return(struct debugger *debugger) { unsigned long ip; - int err, pid; + int pid; pid = debugger->pid; + ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); - ip = IP_RESTART_SYSCALL(ip); - err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip); + IP_RESTART_SYSCALL(ip); + if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0) tracer_panic("real_wait_return : Failed to restart system " - "call, errno = %d\n"); + "call, errno = %d\n", errno); + if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || debugger_normal_return(debugger, -1)) tracer_panic("real_wait_return : gdb failed to wait, " - "errno = %d\n"); + "errno = %d\n", errno); return(0); } diff --git a/arch/um/kernel/tt/sys-i386/Makefile b/arch/um/kernel/tt/sys-i386/Makefile index 2ad8271c6..3eeea057c 100644 --- a/arch/um/kernel/tt/sys-i386/Makefile +++ b/arch/um/kernel/tt/sys-i386/Makefile @@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c index 1b71f9ce5..891045bb9 100644 --- a/arch/um/kernel/tt/syscall_kern.c +++ b/arch/um/kernel/tt/syscall_kern.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -123,12 +123,6 @@ long execute_syscall_tt(void *r) set_fs(USER_DS); - if(current->thread.mode.tt.singlestep_syscall){ - current->thread.mode.tt.singlestep_syscall = 0; - current->ptrace &= ~PT_DTRACE; - force_sig(SIGTRAP, current); - } - return(res); } diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c index f7c845d99..b06217d02 100644 --- a/arch/um/kernel/tt/syscall_user.c +++ b/arch/um/kernel/tt/syscall_user.c @@ -17,10 +17,6 @@ #include "syscall_user.h" #include "tt.h" -/* XXX Bogus */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 void syscall_handler_tt(int sig, union uml_pt_regs *regs) { @@ -33,7 +29,7 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs) SC_START_SYSCALL(sc); index = record_syscall_start(syscall); - syscall_trace(); + syscall_trace(regs, 0); result = execute_syscall(regs); /* regs->sc may have changed while the system call ran (there may @@ -42,15 +38,12 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs) UPT_SC(regs) = sc; SC_SET_SYSCALL_RETURN(sc, result); - if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || - (result == -ERESTARTNOINTR)) - do_signal(result); - syscall_trace(); + syscall_trace(regs, 1); record_syscall_end(index, result); } -int do_syscall(void *task, int pid) +int do_syscall(void *task, int pid, int local_using_sysemu) { unsigned long proc_regs[FRAME_SIZE]; union uml_pt_regs *regs; @@ -63,13 +56,17 @@ int do_syscall(void *task, int pid) regs = TASK_REGS(task); UPT_SYSCALL_NR(regs) = syscall; - if(syscall < 1) return(0); + if(syscall < 0) + return(0); if((syscall != __NR_sigreturn) && ((unsigned long *) PT_IP(proc_regs) >= &_stext) && ((unsigned long *) PT_IP(proc_regs) <= &_etext)) tracer_panic("I'm tracing myself and I can't get out"); + if(local_using_sysemu) + return(1); + if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid) < 0) tracer_panic("do_syscall : Nullifying syscall failed, " diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index 32ac316de..d8ad334cf 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -10,6 +10,7 @@ #include "asm/page.h" #include "asm/pgtable.h" #include "asm/uaccess.h" +#include "asm/tlbflush.h" #include "user_util.h" #include "mem_user.h" #include "os.h" diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index 6a6322a3e..33b9209a1 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -39,16 +39,17 @@ int is_tracer_winch(int pid, int fd, void *data) return(0); register_winch_irq(tracer_winch[0], fd, -1, data); - return(0); + return(1); } static void tracer_winch_handler(int sig) { + int n; char c = 1; - if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c)) - printk("tracer_winch_handler - write failed, errno = %d\n", - errno); + n = os_write_file(tracer_winch[1], &c, sizeof(c)); + if(n != sizeof(c)) + printk("tracer_winch_handler - write failed, err = %d\n", -n); } /* Called only by the tracing thread during initialization */ @@ -58,9 +59,8 @@ static void setup_tracer_winch(void) int err; err = os_pipe(tracer_winch, 1, 1); - if(err){ - printk("setup_tracer_winch : os_pipe failed, errno = %d\n", - -err); + if(err < 0){ + printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); return; } signal(SIGWINCH, tracer_winch_handler); @@ -130,8 +130,8 @@ static void sleeping_process_signal(int pid, int sig) case SIGTSTP: if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) tracer_panic("sleeping_process_signal : Failed to " - "continue pid %d, errno = %d\n", pid, - sig); + "continue pid %d, signal = %d, " + "errno = %d\n", pid, sig, errno); break; /* This happens when the debugger (e.g. strace) is doing system call @@ -145,7 +145,7 @@ static void sleeping_process_signal(int pid, int sig) if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) tracer_panic("sleeping_process_signal : Failed to " "PTRACE_SYSCALL pid %d, errno = %d\n", - pid, sig); + pid, errno); break; case SIGSTOP: break; @@ -184,6 +184,7 @@ int tracer(int (*init_proc)(void *), void *sp) unsigned long eip = 0; int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; + int pt_syscall_parm, local_using_sysemu; capture_signal_stack(); signal(SIGPIPE, SIG_IGN); @@ -192,7 +193,7 @@ int tracer(int (*init_proc)(void *), void *sp) printf("tracing thread pid = %d\n", tracing_pid); pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("waitpid on idle thread failed, errno = %d\n", errno); exit(1); @@ -218,7 +219,7 @@ int tracer(int (*init_proc)(void *), void *sp) err = attach(debugger_parent); if(err){ printf("Failed to attach debugger parent %d, " - "errno = %d\n", debugger_parent, err); + "errno = %d\n", debugger_parent, -err); debugger_parent = -1; } else { @@ -233,7 +234,8 @@ int tracer(int (*init_proc)(void *), void *sp) } set_cmdline("(tracing thread)"); while(1){ - if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){ + CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); + if(pid <= 0){ if(errno != ECHILD){ printf("wait failed - errno = %d\n", errno); } @@ -296,6 +298,9 @@ int tracer(int (*init_proc)(void *), void *sp) tracing = is_tracing(task); old_tracing = tracing; + local_using_sysemu = get_using_sysemu(); + pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; + switch(sig){ case SIGUSR1: sig = 0; @@ -329,8 +334,8 @@ int tracer(int (*init_proc)(void *), void *sp) continue; } tracing = 0; - if(do_syscall(task, pid)) sig = SIGUSR2; - else clear_singlestep(task); + if(do_syscall(task, pid, local_using_sysemu)) + sig = SIGUSR2; break; case SIGPROF: if(tracing) sig = 0; @@ -347,6 +352,7 @@ int tracer(int (*init_proc)(void *), void *sp) case SIGBUS: case SIGILL: case SIGWINCH: + default: tracing = 0; break; @@ -366,9 +372,9 @@ int tracer(int (*init_proc)(void *), void *sp) } if(tracing){ - if(singlestepping_tt(task)) + if(singlestepping(task)) cont_type = PTRACE_SINGLESTEP; - else cont_type = PTRACE_SYSCALL; + else cont_type = pt_syscall_parm; } else cont_type = PTRACE_CONT; @@ -401,7 +407,7 @@ static int __init uml_debug_setup(char *line, int *add) if(!strcmp(line, "go")) debug_stop = 0; else if(!strcmp(line, "parent")) debug_parent = 1; - else printk("Unknown debug option : '%s'\n", line); + else printf("Unknown debug option : '%s'\n", line); line = next; } diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index 7a6dbf5f9..81b911fcd 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -23,6 +23,20 @@ void sig_handler_common_tt(int sig, void *sc_ptr) unprotect_kernel_mem(); + /* This is done because to allow SIGSEGV to be delivered inside a SEGV + * handler. This can happen in copy_user, and if SEGV is disabled, + * the process will die. + */ + if(sig == SIGSEGV) + change_sig(SIGSEGV, 1); + + /* This is done because to allow SIGSEGV to be delivered inside a SEGV + * handler. This can happen in copy_user, and if SEGV is disabled, + * the process will die. + */ + if(sig == SIGSEGV) + change_sig(SIGSEGV, 1); + r = &TASK_REGS(get_current())->tt; save_regs = *r; is_user = user_context(SC_SP(sc)); @@ -30,7 +44,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr) if(sig != SIGUSR2) r->syscall = -1; - change_sig(SIGUSR1, 1); info = &sig_info[sig]; if(!info->is_irq) unblock_signals(); @@ -39,7 +52,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr) if(is_user){ interrupt_end(); block_signals(); - change_sig(SIGUSR1, 0); set_user_mode(NULL); } *r = save_regs; diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index 9c8401120..040971893 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -8,7 +8,7 @@ int copy_from_user_tt(void *to, const void *from, int n) { - if(!access_ok_tt(VERIFY_READ, from, n)) + if(!access_ok_tt(VERIFY_READ, from, n)) return(n); return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, @@ -19,7 +19,7 @@ int copy_to_user_tt(void *to, const void *from, int n) { if(!access_ok_tt(VERIFY_WRITE, to, n)) return(n); - + return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, ¤t->thread.fault_catcher)); } @@ -28,10 +28,10 @@ int strncpy_from_user_tt(char *dst, const char *src, int count) { int n; - if(!access_ok_tt(VERIFY_READ, src, 1)) + if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT); - n = __do_strncpy_from_user(dst, src, count, + n = __do_strncpy_from_user(dst, src, count, ¤t->thread.fault_addr, ¤t->thread.fault_catcher); if(n < 0) return(-EFAULT); diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index 537ee9fba..f01475512 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c @@ -8,15 +8,20 @@ #include #include "user_util.h" #include "uml_uaccess.h" +#include "task.h" +#include "kern_util.h" int __do_copy_from_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, __do_copy, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(0); else return(n - (fault - (unsigned long) from)); } @@ -29,11 +34,14 @@ static void __do_strncpy(void *dst, const void *src, int count) int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, __do_strncpy, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(strlen(dst)); else return(-1); } @@ -46,11 +54,14 @@ static void __do_clear(void *to, const void *from, int n) int __do_clear_user(void *mem, unsigned long len, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, __do_clear, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(0); else return(len - (fault - (unsigned long) mem)); } @@ -58,19 +69,20 @@ int __do_clear_user(void *mem, unsigned long len, int __do_strnlen_user(const char *str, unsigned long n, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; int ret; unsigned long *faddrp = (unsigned long *)fault_addr; - jmp_buf jbuf; + sigjmp_buf jbuf; *fault_catcher = &jbuf; - if(setjmp(jbuf) == 0){ + if(sigsetjmp(jbuf, 1) == 0) ret = strlen(str) + 1; - } - else { - ret = *faddrp - (unsigned long) str; - } + else ret = *faddrp - (unsigned long) str; + *fault_addr = NULL; *fault_catcher = NULL; + + TASK_REGS(get_current())->tt = save; return ret; } diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c index 36d3e6992..3f7aecdbe 100644 --- a/arch/um/kernel/tt/unmap.c +++ b/arch/um/kernel/tt/unmap.c @@ -3,10 +3,7 @@ * Licensed under the GPL */ -#include -#include #include -#include "user.h" int switcheroo(int fd, int prot, void *from, void *to, int size) { diff --git a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c index 61c4cc3af..9ada656f6 100644 --- a/arch/um/kernel/tty_log.c +++ b/arch/um/kernel/tty_log.c @@ -9,10 +9,10 @@ #include #include #include -#include #include #include "init.h" #include "user.h" +#include "kern_util.h" #include "os.h" #define TTY_LOG_DIR "./" @@ -24,29 +24,40 @@ static int tty_log_fd = -1; #define TTY_LOG_OPEN 1 #define TTY_LOG_CLOSE 2 #define TTY_LOG_WRITE 3 +#define TTY_LOG_EXEC 4 + +#define TTY_READ 1 +#define TTY_WRITE 2 struct tty_log_buf { int what; unsigned long tty; int len; + int direction; + unsigned long sec; + unsigned long usec; }; -int open_tty_log(void *tty) +int open_tty_log(void *tty, void *current_tty) { struct timeval tv; struct tty_log_buf data; char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")]; int fd; + gettimeofday(&tv, NULL); if(tty_log_fd != -1){ - data = ((struct tty_log_buf) { what : TTY_LOG_OPEN, - tty : (unsigned long) tty, - len : 0 }); - write(tty_log_fd, &data, sizeof(data)); + data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN, + .tty = (unsigned long) tty, + .len = sizeof(current_tty), + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + os_write_file(tty_log_fd, ¤t_tty, data.len); return(tty_log_fd); } - gettimeofday(&tv, NULL); sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec); @@ -62,30 +73,117 @@ int open_tty_log(void *tty) void close_tty_log(int fd, void *tty) { struct tty_log_buf data; + struct timeval tv; if(tty_log_fd != -1){ - data = ((struct tty_log_buf) { what : TTY_LOG_CLOSE, - tty : (unsigned long) tty, - len : 0 }); - write(tty_log_fd, &data, sizeof(data)); + gettimeofday(&tv, NULL); + data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE, + .tty = (unsigned long) tty, + .len = 0, + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); return; } - close(fd); + os_close_file(fd); } -int write_tty_log(int fd, char *buf, int len, void *tty) +static int log_chunk(int fd, const char *buf, int len) { + int total = 0, try, missed, n; + char chunk[64]; + + while(len > 0){ + try = (len > sizeof(chunk)) ? sizeof(chunk) : len; + missed = copy_from_user_proc(chunk, (char *) buf, try); + try -= missed; + n = os_write_file(fd, chunk, try); + if(n != try) { + if(n < 0) + return(n); + return(-EIO); + } + if(missed != 0) + return(-EFAULT); + + len -= try; + total += try; + buf += try; + } + + return(total); +} + +int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) +{ + struct timeval tv; struct tty_log_buf data; + int direction; if(fd == tty_log_fd){ - data = ((struct tty_log_buf) { what : TTY_LOG_WRITE, - tty : (unsigned long) tty, - len : len }); - write(tty_log_fd, &data, sizeof(data)); + gettimeofday(&tv, NULL); + direction = is_read ? TTY_READ : TTY_WRITE; + data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE, + .tty = (unsigned long) tty, + .len = len, + .direction = direction, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + } + + return(log_chunk(fd, buf, len)); +} + +void log_exec(char **argv, void *tty) +{ + struct timeval tv; + struct tty_log_buf data; + char **ptr,*arg; + int len; + + if(tty_log_fd == -1) return; + + gettimeofday(&tv, NULL); + + len = 0; + for(ptr = argv; ; ptr++){ + if(copy_from_user_proc(&arg, ptr, sizeof(arg))) + return; + if(arg == NULL) break; + len += strlen_user_proc(arg); + } + + data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC, + .tty = (unsigned long) tty, + .len = len, + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + + for(ptr = argv; ; ptr++){ + if(copy_from_user_proc(&arg, ptr, sizeof(arg))) + return; + if(arg == NULL) break; + log_chunk(tty_log_fd, arg, strlen_user_proc(arg)); } - return(write(fd, buf, len)); } +extern void register_tty_logger(int (*opener)(void *, void *), + int (*writer)(int, const char *, int, + void *, int), + void (*closer)(int, void *)); + +static int register_logger(void) +{ + register_tty_logger(open_tty_log, write_tty_log, close_tty_log); + return(0); +} + +__uml_initcall(register_logger); + static int __init set_tty_log_dir(char *name, int *add) { tty_log_dir = name; @@ -104,9 +202,11 @@ static int __init set_tty_log_fd(char *name, int *add) tty_log_fd = strtoul(name, &end, 0); if((*end != '\0') || (end == name)){ - printk("set_tty_log_fd - strtoul failed on '%s'\n", name); + printf("set_tty_log_fd - strtoul failed on '%s'\n", name); tty_log_fd = -1; } + + *add = 0; return 0; } diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c index eb9be24ce..d035257ed 100644 --- a/arch/um/kernel/uaccess_user.c +++ b/arch/um/kernel/uaccess_user.c @@ -18,9 +18,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n, { unsigned long *faddrp = (unsigned long *) fault_addr, ret; - jmp_buf jbuf; + sigjmp_buf jbuf; *fault_catcher = &jbuf; - if(setjmp(jbuf) == 0){ + if(sigsetjmp(jbuf, 1) == 0){ (*op)(to, from, n); ret = 0; *faulted_out = 0; diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index e8f0cacc1..8a33c9d4a 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -27,7 +27,6 @@ #include "user_util.h" #include "kern_util.h" #include "kern.h" -#include "mprot.h" #include "mem_user.h" #include "mem.h" #include "umid.h" @@ -38,13 +37,18 @@ #include "mode_kern.h" #include "mode.h" -#define DEFAULT_COMMAND_LINE "root=6200" +#define DEFAULT_COMMAND_LINE "root=98:0" struct cpuinfo_um boot_cpu_data = { .loops_per_jiffy = 0, .ipi_pipe = { -1, -1 } }; +/* Placeholder to make UML link until the vsyscall stuff is actually + * implemented + */ +void *__kernel_vsyscall; + unsigned long thread_saved_pc(struct task_struct *task) { return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, @@ -53,18 +57,22 @@ unsigned long thread_saved_pc(struct task_struct *task) static int show_cpuinfo(struct seq_file *m, void *v) { - int index; + int index = 0; - index = (struct cpuinfo_um *)v - cpu_data; #ifdef CONFIG_SMP + index = (struct cpuinfo_um *) v - cpu_data; if (!cpu_online(index)) return 0; #endif - seq_printf(m, "bogomips\t: %lu.%02lu\n", + seq_printf(m, "processor\t: %d\n", index); + seq_printf(m, "vendor_id\t: User Mode Linux\n"); + seq_printf(m, "model name\t: UML\n"); + seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); + seq_printf(m, "host\t\t: %s\n", host_info); + seq_printf(m, "bogomips\t: %lu.%02lu\n\n", loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100); - seq_printf(m, "host\t\t: %s\n", host_info); return(0); } @@ -134,12 +142,12 @@ void set_cmdline(char *cmd) if(umid != NULL){ snprintf(argv1_begin, (argv1_end - argv1_begin) * sizeof(*ptr), - "(%s)", umid); + "(%s) ", umid); ptr = &argv1_begin[strlen(argv1_begin)]; } else ptr = argv1_begin; - snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd); + snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); memset(argv1_begin + strlen(argv1_begin), '\0', argv1_end - argv1_begin - strlen(argv1_begin)); #endif @@ -179,7 +187,7 @@ __uml_setup("root=", uml_root_setup, static int __init uml_ncpus_setup(char *line, int *add) { if (!sscanf(line, "%d", &ncpus)) { - printk("Couldn't parse [%s]\n", line); + printf("Couldn't parse [%s]\n", line); return -1; } @@ -210,7 +218,7 @@ static int __init mode_tt_setup(char *line, int *add) static int __init mode_tt_setup(char *line, int *add) { - printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); + printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); return(0); } @@ -221,7 +229,7 @@ static int __init mode_tt_setup(char *line, int *add) static int __init mode_tt_setup(char *line, int *add) { - printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); + printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); return(0); } @@ -291,15 +299,15 @@ static void __init uml_postsetup(void) /* Set during early boot */ unsigned long brk_start; -static struct vm_reserved kernel_vm_reserved; +unsigned long end_iomem; #define MIN_VMALLOC (32 * 1024 * 1024) int linux_main(int argc, char **argv) { - unsigned long avail; + unsigned long avail, diff; unsigned long virtmem_size, max_physmem; - unsigned int i, add, err; + unsigned int i, add; for (i = 1; i < argc; i++){ if((i == 1) && (argv[i][0] == ' ')) continue; @@ -313,8 +321,23 @@ int linux_main(int argc, char **argv) uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, &host_task_size, &task_size); + /* Need to check this early because mmapping happens before the + * kernel is running. + */ + check_tmpexec(); + brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); + /* Increase physical memory size for exec-shield users + so they actually get what they asked for. This should + add zero for non-exec shield users */ + + diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); + if(diff > 1024 * 1024){ + printf("Adding %ld bytes to physical memory to account for " + "exec-shield gap\n", diff); + physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); + } uml_physmem = uml_start; @@ -328,12 +351,16 @@ int linux_main(int argc, char **argv) argv1_end = &argv[1][strlen(argv[1])]; #endif - set_usable_vm(uml_physmem, get_kmem_end()); - highmem = 0; - max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC; - if(physmem_size > max_physmem){ - highmem = physmem_size - max_physmem; + iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; + max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; + + /* Zones have to begin on a 1 << MAX_ORDER page boundary, + * so this makes sure that's true for highmem + */ + max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); + if(physmem_size + iomem_size > max_physmem){ + highmem = physmem_size + iomem_size - max_physmem; physmem_size -= highmem; #ifndef CONFIG_HIGHMEM highmem = 0; @@ -343,11 +370,19 @@ int linux_main(int argc, char **argv) } high_physmem = uml_physmem + physmem_size; - high_memory = (void *) high_physmem; + end_iomem = high_physmem + iomem_size; + high_memory = (void *) end_iomem; start_vm = VMALLOC_START; - setup_physmem(uml_physmem, uml_reserved, physmem_size); + setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); + if(init_maps(physmem_size, iomem_size, highmem)){ + printf("Failed to allocate mem_map for %ld bytes of physical " + "memory and %ld bytes of highmem\n", physmem_size, + highmem); + exit(1); + } + virtmem_size = physmem_size; avail = get_kmem_end() - start_vm; if(physmem_size > avail) virtmem_size = avail; @@ -357,28 +392,23 @@ int linux_main(int argc, char **argv) printf("Kernel virtual memory size shrunk to %ld bytes\n", virtmem_size); - err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved); - if(err){ - printf("Failed to reserve VM area for kernel VM\n"); - exit(1); - } - uml_postsetup(); - init_task.thread.kernel_stack = (unsigned long) &init_thread_info + - 2 * PAGE_SIZE; - task_protections((unsigned long) &init_thread_info); + os_flush_stdout(); return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); } +extern int uml_exitcode; + static int panic_exit(struct notifier_block *self, unsigned long unused1, void *unused2) { -#ifdef CONFIG_MAGIC_SYSRQ - handle_sysrq('p', ¤t->thread.regs, NULL, NULL); -#endif + bust_spinlocks(1); + show_regs(&(current->thread.regs)); + bust_spinlocks(0); + uml_exitcode = 1; machine_halt(); return(0); } @@ -403,6 +433,11 @@ void __init check_bugs(void) arch_check_bugs(); check_ptrace(); check_sigio(); + check_devanon(); +} + +void apply_alternatives(void *start, void *end) +{ } /* diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 1da1a0d66..aab119319 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -33,18 +32,19 @@ static char *uml_dir = UML_DIR; static int umid_is_random = 1; static int umid_inited = 0; -static int make_umid(void); +static int make_umid(int (*printer)(const char *fmt, ...)); -static int __init set_umid(char *name, int is_random) +static int __init set_umid(char *name, int is_random, + int (*printer)(const char *fmt, ...)) { if(umid_inited){ - printk("Unique machine name can't be set twice\n"); + (*printer)("Unique machine name can't be set twice\n"); return(-1); } if(strlen(name) > UMID_LEN - 1) - printk("Unique machine name is being truncated to %s " - "characters\n", UMID_LEN); + (*printer)("Unique machine name is being truncated to %d " + "characters\n", UMID_LEN); strlcpy(umid, name, sizeof(umid)); umid_is_random = is_random; @@ -54,7 +54,8 @@ static int __init set_umid(char *name, int is_random) static int __init set_umid_arg(char *name, int *add) { - return(set_umid(name, 0)); + *add = 0; + return(set_umid(name, 0, printf)); } __uml_setup("umid=", set_umid_arg, @@ -67,7 +68,7 @@ int __init umid_file_name(char *name, char *buf, int len) { int n; - if(!umid_inited && make_umid()) return(-1); + if(!umid_inited && make_umid(printk)) return(-1); n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; if(n > len){ @@ -85,22 +86,23 @@ static int __init create_pid_file(void) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")]; - int fd; + int fd, n; if(umid_file_name("pid", file, sizeof(file))) return 0; fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 0644); if(fd < 0){ - printk("Open of machine pid file \"%s\" failed - " - "errno = %d\n", file, -fd); + printf("Open of machine pid file \"%s\" failed - " + "err = %d\n", file, -fd); return 0; } sprintf(pid, "%d\n", os_getpid()); - if(write(fd, pid, strlen(pid)) != strlen(pid)) - printk("Write of pid file failed - errno = %d\n", errno); - close(fd); + n = os_write_file(fd, pid, strlen(pid)); + if(n != strlen(pid)) + printf("Write of pid file failed - err = %d\n", -n); + os_close_file(fd); return 0; } @@ -111,7 +113,8 @@ static int actually_do_remove(char *dir) int len; char file[256]; - if((directory = opendir(dir)) == NULL){ + directory = opendir(dir); + if(directory == NULL){ printk("actually_do_remove : couldn't open directory '%s', " "errno = %d\n", dir, errno); return(1); @@ -160,22 +163,24 @@ int not_dead_yet(char *dir) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p; + int dead, fd, p, n; sprintf(file, "%s/pid", dir); dead = 0; - if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){ + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ if(fd != -ENOENT){ printk("not_dead_yet : couldn't open pid file '%s', " - "errno = %d\n", file, -fd); + "err = %d\n", file, -fd); return(1); } dead = 1; } if(fd > 0){ - if(read(fd, pid, sizeof(pid)) < 0){ + n = os_read_file(fd, pid, sizeof(pid)); + if(n < 0){ printk("not_dead_yet : couldn't read pid file '%s', " - "errno = %d\n", file, errno); + "err = %d\n", file, -n); return(1); } p = strtoul(pid, &end, 0); @@ -195,17 +200,20 @@ int not_dead_yet(char *dir) static int __init set_uml_dir(char *name, int *add) { if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ - uml_dir = malloc(strlen(name) + 1); + uml_dir = malloc(strlen(name) + 2); if(uml_dir == NULL){ - printk("Failed to malloc uml_dir - error = %d\n", + printf("Failed to malloc uml_dir - error = %d\n", errno); uml_dir = name; + /* Return 0 here because do_initcalls doesn't look at + * the return value. + */ return(0); } sprintf(uml_dir, "%s/", name); } else uml_dir = name; - return 0; + return(0); } static int __init make_uml_dir(void) @@ -217,7 +225,7 @@ static int __init make_uml_dir(void) char *home = getenv("HOME"); if(home == NULL){ - printk("make_uml_dir : no value in environment for " + printf("make_uml_dir : no value in environment for " "$HOME\n"); exit(1); } @@ -232,57 +240,59 @@ static int __init make_uml_dir(void) dir[len + 1] = '\0'; } - if((uml_dir = malloc(strlen(dir) + 1)) == NULL){ + uml_dir = malloc(strlen(dir) + 1); + if(uml_dir == NULL){ printf("make_uml_dir : malloc failed, errno = %d\n", errno); exit(1); } strcpy(uml_dir, dir); if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ - printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno); + printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno); return(-1); } return 0; } -static int __init make_umid(void) +static int __init make_umid(int (*printer)(const char *fmt, ...)) { int fd, err; char tmp[strlen(uml_dir) + UMID_LEN + 1]; strlcpy(tmp, uml_dir, sizeof(tmp)); - if(*umid == 0){ + if(!umid_inited){ strcat(tmp, "XXXXXX"); fd = mkstemp(tmp); if(fd < 0){ - printk("make_umid - mkstemp failed, errno = %d\n", - errno); + (*printer)("make_umid - mkstemp failed, errno = %d\n", + errno); return(1); } - close(fd); + os_close_file(fd); /* There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ unlink(tmp); - set_umid(&tmp[strlen(uml_dir)], 1); + set_umid(&tmp[strlen(uml_dir)], 1, printer); } sprintf(tmp, "%s%s", uml_dir, umid); - if((err = mkdir(tmp, 0777)) < 0){ + err = mkdir(tmp, 0777); + if(err < 0){ if(errno == EEXIST){ if(not_dead_yet(tmp)){ - printk("umid '%s' is in use\n", umid); + (*printer)("umid '%s' is in use\n", umid); return(-1); } err = mkdir(tmp, 0777); } } if(err < 0){ - printk("Failed to create %s - errno = %d\n", umid, errno); + (*printer)("Failed to create %s - errno = %d\n", umid, errno); return(-1); } @@ -295,7 +305,13 @@ __uml_setup("uml_dir=", set_uml_dir, ); __uml_postsetup(make_uml_dir); -__uml_postsetup(make_umid); + +static int __init make_umid_setup(void) +{ + return(make_umid(printf)); +} + +__uml_postsetup(make_umid_setup); __uml_postsetup(create_pid_file); /* diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 89ed32983..72b608cc9 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -35,6 +35,8 @@ SECTIONS { *(.text) SCHED_TEXT + LOCK_TEXT + *(.fixup) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) *(.gnu.linkonce.t*) diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 9e4fbae93..b2c7c5d2e 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -5,10 +5,10 @@ #include #include -#include #include #include -#include +#include +#include #include #include #include @@ -81,19 +81,19 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay) int status, ret; while(1){ - if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) || + CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); + if((ret < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ if(ret < 0){ - if(errno == EINTR) continue; printk("wait failed, errno = %d\n", errno); } else if(WIFEXITED(status)) - printk("process exited with status %d\n", - WEXITSTATUS(status)); + printk("process %d exited with status %d\n", + pid, WEXITSTATUS(status)); else if(WIFSIGNALED(status)) - printk("process exited with signal %d\n", - WTERMSIG(status)); + printk("process %d exited with signal %d\n", + pid, WTERMSIG(status)); else if((WSTOPSIG(status) == SIGVTALRM) || (WSTOPSIG(status) == SIGALRM) || (WSTOPSIG(status) == SIGIO) || @@ -109,8 +109,8 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay) ptrace(cont_type, pid, 0, WSTOPSIG(status)); continue; } - else printk("process stopped with signal %d\n", - WSTOPSIG(status)); + else printk("process %d stopped with signal %d\n", + pid, WSTOPSIG(status)); panic("wait_for_stop failed to wait for %d to stop " "with %d\n", pid, sig); } @@ -118,29 +118,27 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay) } } -int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags) -{ - int pid; - - pid = clone(fn, sp, flags, arg); - if(pid < 0) return(-1); - wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); - ptrace(PTRACE_CONT, pid, 0, 0); - return(pid); -} - -int raw(int fd, int complain) +int raw(int fd) { struct termios tt; int err; - tcgetattr(fd, &tt); + CATCH_EINTR(err = tcgetattr(fd, &tt)); + if (err < 0) { + printk("tcgetattr failed, errno = %d\n", errno); + return(-errno); + } + cfmakeraw(&tt); - err = tcsetattr(fd, TCSANOW, &tt); - if((err < 0) && complain){ - printk("tcsetattr failed, errno = %d\n", errno); + + CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); + if (err < 0) { + printk("tcsetattr failed, errno = %d\n", errno); return(-errno); } + + /* XXX tcsetattr could have applied only some changes + * (and cfmakeraw() is a set of changes) */ return(0); } @@ -163,6 +161,21 @@ void setup_hostinfo(void) host.release, host.version, host.machine); } +int setjmp_wrapper(void (*proc)(void *, void *), ...) +{ + va_list args; + sigjmp_buf buf; + int n; + + n = sigsetjmp(buf, 1); + if(n == 0){ + va_start(args, proc); + (*proc)(&buf, &args); + } + va_end(args); + return(n); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 37eea4a32..ff94c8f61 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,13 +3,9 @@ # Licensed under the GPL # -obj-y = file.o process.o tty.o drivers/ +obj-y = file.o process.o time.o tty.o user_syms.o drivers/ -USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file)) +USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : - -archmrproper: diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 17f156104..6ae4b19d9 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -8,7 +8,6 @@ #include "linux/init.h" #include "linux/netdevice.h" #include "linux/etherdevice.h" -#include "linux/init.h" #include "net_kern.h" #include "net_user.h" #include "etap.h" diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index e27592985..cd4d6544d 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "net_user.h" #include "etap.h" #include "helper.h" @@ -42,13 +42,14 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, { struct addr_change change; void *output; + int n; change.what = op; memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); - if(write(fd, &change, sizeof(change)) != sizeof(change)) - printk("etap_change - request failed, errno = %d\n", - errno); + n = os_write_file(fd, &change, sizeof(change)); + if(n != sizeof(change)) + printk("etap_change - request failed, err = %d\n", -n); output = um_kmalloc(page_size()); if(output == NULL) printk("etap_change : Failed to allocate output buffer\n"); @@ -82,15 +83,15 @@ static void etap_pre_exec(void *arg) struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - close(data->data_me); - close(data->control_me); + os_close_file(data->data_me); + os_close_file(data->control_me); } static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; - int pid, status, err; + int pid, status, err, n; char version_buf[sizeof("nnnnn\0")]; char data_fd_buf[sizeof("nnnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; @@ -114,21 +115,22 @@ static int etap_tramp(char *dev, char *gate, int control_me, pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args, NULL); - if(pid < 0) err = errno; - close(data_remote); - close(control_remote); - if(read(control_me, &c, sizeof(c)) != sizeof(c)){ - printk("etap_tramp : read of status failed, errno = %d\n", - errno); - return(EINVAL); + if(pid < 0) err = pid; + os_close_file(data_remote); + os_close_file(control_remote); + n = os_read_file(control_me, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("etap_tramp : read of status failed, err = %d\n", -n); + return(-EINVAL); } if(c != 1){ printk("etap_tramp : uml_net failed\n"); - err = EINVAL; - if(waitpid(pid, &status, 0) < 0) err = errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){ + err = -EINVAL; + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(n < 0) + err = -errno; + else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) printk("uml_net didn't exit with status 1\n"); - } } return(err); } @@ -143,14 +145,14 @@ static int etap_open(void *data) if(err) return(err); err = os_pipe(data_fds, 0, 0); - if(err){ - printk("data os_pipe failed - errno = %d\n", -err); + if(err < 0){ + printk("data os_pipe failed - err = %d\n", -err); return(err); } err = os_pipe(control_fds, 1, 0); - if(err){ - printk("control os_pipe failed - errno = %d\n", -err); + if(err < 0){ + printk("control os_pipe failed - err = %d\n", -err); return(err); } @@ -167,9 +169,9 @@ static int etap_open(void *data) kfree(output); } - if(err != 0){ - printk("etap_tramp failed - errno = %d\n", err); - return(-err); + if(err < 0){ + printk("etap_tramp failed - err = %d\n", -err); + return(err); } pri->data_fd = data_fds[0]; @@ -183,11 +185,11 @@ static void etap_close(int fd, void *data) struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - close(fd); + os_close_file(fd); os_shutdown_socket(pri->data_fd, 1, 1); - close(pri->data_fd); + os_close_file(pri->data_fd); pri->data_fd = -1; - close(pri->control_fd); + os_close_file(pri->control_fd); pri->control_fd = -1; } diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index c858f1160..4b83c6c3f 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include "net_user.h" #include "tuntap.h" #include "kern_util.h" +#include "user_util.h" #include "user.h" #include "helper.h" #include "os.h" @@ -61,7 +61,7 @@ static void tuntap_pre_exec(void *arg) struct tuntap_pre_exec_data *data = arg; dup2(data->stdout, 1); - close(data->close_me); + os_close_file(data->close_me); } static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, @@ -86,7 +86,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, if(pid < 0) return(-pid); - close(remote); + os_close_file(remote); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -107,19 +107,19 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, if(n < 0){ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", errno); - return(errno); + return(-errno); } - waitpid(pid, NULL, 0); + CATCH_EINTR(waitpid(pid, NULL, 0)); cmsg = CMSG_FIRSTHDR(&msg); if(cmsg == NULL){ printk("tuntap_open_tramp : didn't receive a message\n"); - return(EINVAL); + return(-EINVAL); } if((cmsg->cmsg_level != SOL_SOCKET) || (cmsg->cmsg_type != SCM_RIGHTS)){ printk("tuntap_open_tramp : didn't receive a descriptor\n"); - return(EINVAL); + return(-EINVAL); } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; return(0); @@ -133,27 +133,29 @@ static int tuntap_open(void *data) int err, fds[2], len, used; err = tap_open_common(pri->dev, pri->gate_addr); - if(err) return(err); + if(err < 0) + return(err); if(pri->fixed_config){ - if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){ - printk("Failed to open /dev/net/tun, errno = %d\n", - errno); - return(-errno); + pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); + if(pri->fd < 0){ + printk("Failed to open /dev/net/tun, err = %d\n", + -pri->fd); + return(pri->fd); } memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP; + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ - printk("TUNSETIFF failed, errno = %d", errno); - close(pri->fd); + printk("TUNSETIFF failed, errno = %d\n", errno); + os_close_file(pri->fd); return(-errno); } } else { err = os_pipe(fds, 0, 0); - if(err){ - printk("tuntap_open : os_pipe failed - errno = %d\n", + if(err < 0){ + printk("tuntap_open : os_pipe failed - err = %d\n", -err); return(err); } @@ -166,19 +168,19 @@ static int tuntap_open(void *data) fds[1], buffer, len, &used); output = buffer; - if(err == 0){ - pri->dev_name = uml_strdup(buffer); - output += IFNAMSIZ; - printk(output); - free_output_buffer(buffer); - } - else { - printk(output); + if(err < 0) { + printk("%s", output); free_output_buffer(buffer); - printk("tuntap_open_tramp failed - errno = %d\n", err); - return(-err); + printk("tuntap_open_tramp failed - err = %d\n", -err); + return(err); } - close(fds[0]); + + pri->dev_name = uml_strdup(buffer); + output += IFNAMSIZ; + printk("%s", output); + free_output_buffer(buffer); + + os_close_file(fds[0]); iter_addresses(pri->dev, open_addr, pri->dev_name); } @@ -191,7 +193,7 @@ static void tuntap_close(int fd, void *data) if(!pri->fixed_config) iter_addresses(pri->dev, close_addr, pri->dev_name); - close(fd); + os_close_file(fd); pri->fd = -1; } diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index e622db007..77d4066d1 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -17,33 +19,236 @@ #include "user.h" #include "kern_util.h" -int os_file_type(char *file) +static void copy_stat(struct uml_stat *dst, struct stat64 *src) +{ + *dst = ((struct uml_stat) { + .ust_dev = src->st_dev, /* device */ + .ust_ino = src->st_ino, /* inode */ + .ust_mode = src->st_mode, /* protection */ + .ust_nlink = src->st_nlink, /* number of hard links */ + .ust_uid = src->st_uid, /* user ID of owner */ + .ust_gid = src->st_gid, /* group ID of owner */ + .ust_size = src->st_size, /* total size, in bytes */ + .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ + .ust_blocks = src->st_blocks, /* number of blocks allocated */ + .ust_atime = src->st_atime, /* time of last access */ + .ust_mtime = src->st_mtime, /* time of last modification */ + .ust_ctime = src->st_ctime, /* time of last change */ + }); +} + +int os_stat_fd(const int fd, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = fstat64(fd, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_stat_file(const char *file_name, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = stat64(file_name, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_access(const char* file, int mode) +{ + int amode, err; + + amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | + (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; + + err = access(file, amode); + if(err < 0) + return(-errno); + + return(0); +} + +void os_print_error(int error, const char* str) +{ + errno = error < 0 ? -error : error; + + perror(str); +} + +/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ +int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) +{ + int err; + + err = ioctl(fd, cmd, arg); + if(err < 0) + return(-errno); + + return(err); +} + +int os_window_size(int fd, int *rows, int *cols) +{ + struct winsize size; + + if(ioctl(fd, TIOCGWINSZ, &size) < 0) + return(-errno); + + *rows = size.ws_row; + *cols = size.ws_col; + + return(0); +} + +int os_new_tty_pgrp(int fd, int pid) +{ + if(ioctl(fd, TIOCSCTTY, 0) < 0){ + printk("TIOCSCTTY failed, errno = %d\n", errno); + return(-errno); + } + + if(tcsetpgrp(fd, pid) < 0){ + printk("tcsetpgrp failed, errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +/* FIXME: ensure namebuf in os_get_if_name is big enough */ +int os_get_ifname(int fd, char* namebuf) +{ + if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) + return(-errno); + + return(0); +} + +int os_set_slip(int fd) +{ + int disc, sencap; + + disc = N_SLIP; + if(ioctl(fd, TIOCSETD, &disc) < 0){ + printk("Failed to set slip line discipline - " + "errno = %d\n", errno); + return(-errno); + } + + sencap = 0; + if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ + printk("Failed to set slip encapsulation - " + "errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +int os_set_owner(int fd, int pid) +{ + if(fcntl(fd, F_SETOWN, pid) < 0){ + int save_errno = errno; + + if(fcntl(fd, F_GETOWN, 0) != pid) + return(-save_errno); + } + + return(0); +} + +/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ +int os_sigio_async(int master, int slave) +{ + int flags; + + flags = fcntl(master, F_GETFL); + if(flags < 0) { + printk("fcntl F_GETFL failed, errno = %d\n", errno); + return(-errno); + } + + if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || + (fcntl(master, F_SETOWN, os_getpid()) < 0)){ + printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", + errno); + return(-errno); + } + + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ + printk("fcntl F_SETFL failed, errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +int os_mode_fd(int fd, int mode) { - struct stat64 buf; + int err; + + do { + err = fchmod(fd, mode); + } while((err < 0) && (errno==EINTR)) ; - if(stat64(file, &buf) == -1) + if(err < 0) return(-errno); - if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); - else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); - else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); - else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); - else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO); - else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK); + return(0); +} + +int os_file_type(char *file) +{ + struct uml_stat buf; + int err; + + err = os_stat_file(file, &buf); + if(err < 0) + return(err); + + if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR); + else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK); + else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV); + else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV); + else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO); + else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK); else return(OS_TYPE_FILE); } int os_file_mode(char *file, struct openflags *mode_out) { + int err; + *mode_out = OPENFLAGS(); - if(!access(file, W_OK)) *mode_out = of_write(*mode_out); - else if(errno != EACCES) - return(-errno); + err = os_access(file, OS_ACC_W_OK); + if((err < 0) && (err != -EACCES)) + return(err); - if(!access(file, R_OK)) *mode_out = of_read(*mode_out); - else if(errno != EACCES) - return(-errno); + *mode_out = of_write(*mode_out); + + err = os_access(file, OS_ACC_R_OK); + if((err < 0) && (err != -EACCES)) + return(err); + + *mode_out = of_read(*mode_out); return(0); } @@ -63,16 +268,14 @@ int os_open_file(char *file, struct openflags flags, int mode) if(flags.e) f |= O_EXCL; fd = open64(file, f, mode); - if(fd < 0) return(-errno); - - if(flags.cl){ - if(fcntl(fd, F_SETFD, 1)){ - close(fd); - return(-errno); - } + if(fd < 0) + return(-errno); + + if(flags.cl && fcntl(fd, F_SETFD, 1)){ + os_close_file(fd); + return(-errno); } - return(fd); return(fd); } @@ -90,7 +293,7 @@ int os_connect_socket(char *name) err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); if(err) - return(err); + return(-errno); return(fd); } @@ -105,92 +308,167 @@ int os_seek_file(int fd, __u64 offset) __u64 actual; actual = lseek64(fd, offset, SEEK_SET); - if(actual != offset) return(-errno); + if(actual != offset) + return(-errno); return(0); } -int os_read_file(int fd, void *buf, int len) +static int fault_buffer(void *start, int len, + int (*copy_proc)(void *addr, void *buf, int len)) { - int n; + int page = getpagesize(), i; + char c; - /* Force buf into memory if it's not already. */ + for(i = 0; i < len; i += page){ + if((*copy_proc)(start + i, &c, sizeof(c))) + return(-EFAULT); + } + if((len % page) != 0){ + if((*copy_proc)(start + len - 1, &c, sizeof(c))) + return(-EFAULT); + } + return(0); +} - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, &c, sizeof(c))) - return(-EFAULT); -#endif +static int file_io(int fd, void *buf, int len, + int (*io_proc)(int fd, void *buf, int len), + int (*copy_user_proc)(void *addr, void *buf, int len)) +{ + int n, err; + + do { + n = (*io_proc)(fd, buf, len); + if((n < 0) && (errno == EFAULT)){ + err = fault_buffer(buf, len, copy_user_proc); + if(err) + return(err); + n = (*io_proc)(fd, buf, len); + } + } while((n < 0) && (errno == EINTR)); - n = read(fd, buf, len); if(n < 0) return(-errno); return(n); } -int os_write_file(int fd, void *buf, int count) +int os_read_file(int fd, void *buf, int len) { - int n; - - /* Force buf into memory if it's not already. */ - - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, buf, buf[0])) - return(-EFAULT); -#endif + return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, + copy_from_user_proc)); +} - n = write(fd, buf, count); - if(n < 0) - return(-errno); - return(n); +int os_write_file(int fd, const void *buf, int len) +{ + return(file_io(fd, (void *) buf, len, + (int (*)(int, void *, int)) write, copy_to_user_proc)); } int os_file_size(char *file, long long *size_out) { - struct stat64 buf; + struct uml_stat buf; + int err; - if(stat64(file, &buf) == -1){ - printk("Couldn't stat \"%s\" : errno = %d\n", file, errno); - return(-errno); + err = os_stat_file(file, &buf); + if(err < 0){ + printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + return(err); } - if(S_ISBLK(buf.st_mode)){ + + if(S_ISBLK(buf.ust_mode)){ int fd, blocks; - if((fd = open64(file, O_RDONLY)) < 0){ - printk("Couldn't open \"%s\", errno = %d\n", file, - errno); - return(-errno); + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open \"%s\", errno = %d\n", file, -fd); + return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - close(fd); - return(-errno); + err = -errno; + os_close_file(fd); + return(err); } *size_out = ((long long) blocks) * 512; - close(fd); + os_close_file(fd); return(0); } - *size_out = buf.st_size; + *size_out = buf.ust_size; + return(0); +} + +int os_file_modtime(char *file, unsigned long *modtime) +{ + struct uml_stat buf; + int err; + + err = os_stat_file(file, &buf); + if(err < 0){ + printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + return(err); + } + + *modtime = buf.ust_mtime; return(0); } +int os_get_exec_close(int fd, int* close_on_exec) +{ + int ret; + + do { + ret = fcntl(fd, F_GETFD); + } while((ret < 0) && (errno == EINTR)) ; + + if(ret < 0) + return(-errno); + + *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; + return(ret); +} + +int os_set_exec_close(int fd, int close_on_exec) +{ + int flag, err; + + if(close_on_exec) flag = FD_CLOEXEC; + else flag = 0; + + do { + err = fcntl(fd, F_SETFD, flag); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + return(err); +} + int os_pipe(int *fds, int stream, int close_on_exec) { int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; err = socketpair(AF_UNIX, type, 0, fds); - if(err) + if(err < 0) return(-errno); if(!close_on_exec) return(0); - if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0)) - printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", - errno); + err = os_set_exec_close(fds[0], 1); + if(err < 0) + goto error; + + err = os_set_exec_close(fds[1], 1); + if(err < 0) + goto error; return(0); + + error: + printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); + os_close_file(fds[1]); + os_close_file(fds[0]); + return(err); } int os_set_fd_async(int fd, int owner) @@ -219,6 +497,16 @@ int os_set_fd_async(int fd, int owner) return(0); } +int os_clear_fd_async(int fd) +{ + int flags = fcntl(fd, F_GETFL); + + flags &= ~(O_ASYNC | O_NONBLOCK); + if(fcntl(fd, F_SETFL, flags) < 0) + return(-errno); + return(0); +} + int os_set_fd_block(int fd, int blocking) { int flags; @@ -270,7 +558,7 @@ int os_shutdown_socket(int fd, int r, int w) return(-EINVAL); } err = shutdown(fd, what); - if(err) + if(err < 0) return(-errno); return(0); } @@ -315,7 +603,7 @@ int os_rcv_fd(int fd, int *helper_pid_out) return(new); } -int create_unix_socket(char *file, int len) +int os_create_unix_socket(char *file, int len, int close_on_exec) { struct sockaddr_un addr; int sock, err; @@ -327,6 +615,13 @@ int create_unix_socket(char *file, int len) return(-errno); } + if(close_on_exec) { + err = os_set_exec_close(sock, 1); + if(err < 0) + printk("create_unix_socket : close_on_exec failed, " + "err = %d", -err); + } + addr.sun_family = AF_UNIX; /* XXX Be more careful about overflow */ @@ -334,14 +629,45 @@ int create_unix_socket(char *file, int len) err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0){ - printk("create_listening_socket - bind failed, errno = %d\n", - errno); + printk("create_listening_socket at '%s' - bind failed, " + "errno = %d\n", file, errno); return(-errno); } return(sock); } +void os_flush_stdout(void) +{ + fflush(stdout); +} + +int os_lock_file(int fd, int excl) +{ + int type = excl ? F_WRLCK : F_RDLCK; + struct flock lock = ((struct flock) { .l_type = type, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 } ); + int err, save; + + err = fcntl(fd, F_SETLK, &lock); + if(!err) + goto out; + + save = -errno; + err = fcntl(fd, F_GETLK, &lock); + if(err){ + err = -errno; + goto out; + } + + printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); + err = save; + out: + return(err); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index a97778f31..cce8631fd 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,35 +7,45 @@ #include #include #include +#include +#include #include #include #include "os.h" #include "user.h" +#include "user_util.h" + +#define ARBITRARY_ADDR -1 +#define FAILURE_PID -1 + +#define STAT_PATH_LEN sizeof("/proc/#######/stat\0") +#define COMM_SCANF "%*[^)])" unsigned long os_process_pc(int pid) { - char proc_stat[sizeof("/proc/#####/stat\0")], buf[256]; + char proc_stat[STAT_PATH_LEN], buf[256]; unsigned long pc; - int fd; + int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); if(fd < 0){ - printk("os_process_pc - couldn't open '%s', errno = %d\n", - proc_stat, errno); - return(-1); + printk("os_process_pc - couldn't open '%s', err = %d\n", + proc_stat, -fd); + return(ARBITRARY_ADDR); } - if(read(fd, buf, sizeof(buf)) < 0){ - printk("os_process_pc - couldn't read '%s', errno = %d\n", - proc_stat, errno); - close(fd); - return(-1); + err = os_read_file(fd, buf, sizeof(buf)); + if(err < 0){ + printk("os_process_pc - couldn't read '%s', err = %d\n", + proc_stat, -err); + os_close_file(fd); + return(ARBITRARY_ADDR); } - close(fd); - pc = -1; - if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d " + os_close_file(fd); + pc = ARBITRARY_ADDR; + if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %ld", &pc) != 1){ + "%*d %*d %*d %*d %*d %lu", &pc) != 1){ printk("os_process_pc - couldn't find pc in '%s'\n", buf); } return(pc); @@ -43,7 +53,7 @@ unsigned long os_process_pc(int pid) int os_process_parent(int pid) { - char stat[sizeof("/proc/nnnnn/stat\0")]; + char stat[STAT_PATH_LEN]; char data[256]; int parent, n, fd; @@ -52,22 +62,22 @@ int os_process_parent(int pid) snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); fd = os_open_file(stat, of_read(OPENFLAGS()), 0); if(fd < 0){ - printk("Couldn't open '%s', errno = %d\n", stat, -fd); - return(-1); + printk("Couldn't open '%s', err = %d\n", stat, -fd); + return(FAILURE_PID); } - n = read(fd, data, sizeof(data)); - close(fd); + n = os_read_file(fd, data, sizeof(data)); + os_close_file(fd); if(n < 0){ - printk("Couldn't read '%s', errno = %d\n", stat); - return(-1); + printk("Couldn't read '%s', err = %d\n", stat, -n); + return(FAILURE_PID); } - parent = -1; - /* XXX This will break if there is a space in the command */ - n = sscanf(data, "%*d %*s %*c %d", &parent); - if(n != 1) printk("Failed to scan '%s'\n", data); + parent = FAILURE_PID; + n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); + if(n != 1) + printk("Failed to scan '%s'\n", data); return(parent); } @@ -81,21 +91,32 @@ void os_kill_process(int pid, int reap_child) { kill(pid, SIGKILL); if(reap_child) - waitpid(pid, NULL, 0); + CATCH_EINTR(waitpid(pid, NULL, 0)); } +void os_kill_ptraced_process(int pid, int reap_child) +{ + ptrace(PTRACE_KILL, pid); + if(reap_child) + CATCH_EINTR(waitpid(pid, NULL, 0)); +} + void os_usr1_process(int pid) { kill(pid, SIGUSR1); } +/*Don't use the glibc version, which caches the result in TLS. It misses some + * syscalls, and also breaks with clone(), which does not unshare the TLS.*/ +inline _syscall0(pid_t, getpid) + int os_getpid(void) { return(getpid()); } -int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, +int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x) { void *loc; @@ -104,8 +125,8 @@ int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, - fd, off); + loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, + fd, off); if(loc == MAP_FAILED) return(-errno); return(0); @@ -126,7 +147,8 @@ int os_unmap_memory(void *addr, int len) int err; err = munmap(addr, len); - if(err < 0) return(-errno); + if(err < 0) + return(-errno); return(0); } diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c index 2866ddbc9..4cfdd18ea 100644 --- a/arch/um/os-Linux/tty.c +++ b/arch/um/os-Linux/tty.c @@ -28,10 +28,10 @@ int get_pty(void) struct grantpt_info info; int fd; - if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){ - printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n", - errno); - return(-1); + fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); + if(fd < 0){ + printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); + return(fd); } info.fd = fd; @@ -39,7 +39,7 @@ int get_pty(void) if(info.res < 0){ printk("get_pty : Couldn't grant pty - errno = %d\n", - info.err); + -info.err); return(-1); } if(unlockpt(fd) < 0){ diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index ef0fb71e4..2433c9e68 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -14,18 +14,20 @@ extern size_t strlen(const char *); extern void *memcpy(void *, const void *, size_t); +extern void *memmove(void *, const void *, size_t); extern void *memset(void *, int, size_t); extern int printf(const char *, ...); EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(printf); EXPORT_SYMBOL(strstr); /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. - * However, the modules will use the CRC defined *here*, no matter if it is + * However, the modules will use the CRC defined *here*, no matter if it is * good; so the versions of these symbols will always match */ #define EXPORT_SYMBOL_PROTO(sym) \ diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 7525859c5..0f65a9259 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,14 +1,21 @@ -obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \ - ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o +obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \ + ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_MODULES) += module.o USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -SYMLINKS = semaphore.c highmem.c module.c +SYMLINKS = bitops.c semaphore.c highmem.c module.c + +# this needs to be before the foreach, because clean-files does not accept +# complete paths like $(src)/$f. +clean-files := $(SYMLINKS) + SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f) +bitops.c-dir = lib semaphore.c-dir = kernel highmem.c-dir = mm module.c-dir = kernel @@ -24,19 +31,4 @@ $(USER_OBJS) : %.o: %.c $(SYMLINKS): $(call make_link,$@) -clean: - $(MAKE) -C util clean - -fastdep: - -dep: - -archmrproper: - rm -f $(SYMLINKS) - -archclean: - -archdep: - -modules: - +subdir- := util diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 3905bab88..41b0ab2fe 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c @@ -4,20 +4,21 @@ */ #include -#include #include #include #include +#include #include "kern_util.h" #include "user.h" #include "sysdep/ptrace.h" #include "task.h" +#include "os.h" #define MAXTOKEN 64 /* Set during early boot */ -int cpu_has_cmov = 1; -int cpu_has_xmm = 0; +int host_has_cmov = 1; +int host_has_xmm = 0; static char token(int fd, char *buf, int len, char stop) { @@ -27,13 +28,15 @@ static char token(int fd, char *buf, int len, char stop) ptr = buf; end = &buf[len]; do { - n = read(fd, ptr, sizeof(*ptr)); + n = os_read_file(fd, ptr, sizeof(*ptr)); c = *ptr++; - if(n == 0) return(0); - else if(n != sizeof(*ptr)){ - printk("Reading /proc/cpuinfo failed, " - "errno = %d\n", errno); - return(-errno); + if(n != sizeof(*ptr)){ + if(n == 0) return(0); + printk("Reading /proc/cpuinfo failed, err = %d\n", -n); + if(n < 0) + return(n); + else + return(-EIO); } } while((c != '\n') && (c != stop) && (ptr < end)); @@ -45,45 +48,79 @@ static char token(int fd, char *buf, int len, char stop) return(c); } -static int check_cpu_feature(char *feature, int *have_it) +static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) { - char buf[MAXTOKEN], c; - int fd, len = sizeof(buf)/sizeof(buf[0]), n; - - printk("Checking for host processor %s support...", feature); - fd = open("/proc/cpuinfo", O_RDONLY); - if(fd < 0){ - printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno); - return(0); - } + int n; + char c; - *have_it = 0; - buf[len - 1] = '\0'; + scratch[len - 1] = '\0'; while(1){ - c = token(fd, buf, len - 1, ':'); - if(c <= 0) goto out; + c = token(fd, scratch, len - 1, ':'); + if(c <= 0) + return(0); else if(c != ':'){ printk("Failed to find ':' in /proc/cpuinfo\n"); - goto out; + return(0); } - if(!strncmp(buf, "flags", strlen("flags"))) break; + if(!strncmp(scratch, key, strlen(key))) + return(1); do { - n = read(fd, &c, sizeof(c)); + n = os_read_file(fd, &c, sizeof(c)); if(n != sizeof(c)){ printk("Failed to find newline in " - "/proc/cpuinfo, n = %d, errno = %d\n", - n, errno); - goto out; + "/proc/cpuinfo, err = %d\n", -n); + return(0); } } while(c != '\n'); } + return(0); +} + +int cpu_feature(char *what, char *buf, int len) +{ + int fd, ret = 0; + + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + if(!find_cpuinfo_line(fd, what, buf, len)){ + printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); + goto out_close; + } + + token(fd, buf, len, '\n'); + ret = 1; + + out_close: + os_close_file(fd); + return(ret); +} + +static int check_cpu_flag(char *feature, int *have_it) +{ + char buf[MAXTOKEN], c; + int fd, len = sizeof(buf)/sizeof(buf[0]); + + printk("Checking for host processor %s support...", feature); + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + *have_it = 0; + if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) + goto out; c = token(fd, buf, len - 1, ' '); if(c < 0) goto out; else if(c != ' '){ - printk("Failed to find ':' in /proc/cpuinfo\n"); + printk("Failed to find ' ' in /proc/cpuinfo\n"); goto out; } @@ -100,48 +137,76 @@ static int check_cpu_feature(char *feature, int *have_it) out: if(*have_it == 0) printk("No\n"); else if(*have_it == 1) printk("Yes\n"); - close(fd); + os_close_file(fd); return(1); } +#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems + * for some people. + */ +static void disable_lcall(void) +{ + struct modify_ldt_ldt_s ldt; + int err; + + bzero(&ldt, sizeof(ldt)); + ldt.entry_number = 7; + ldt.base_addr = 0; + ldt.limit = 0; + err = modify_ldt(1, &ldt, sizeof(ldt)); + if(err) + printk("Failed to disable lcall7 - errno = %d\n", errno); +} +#endif + +void arch_init_thread(void) +{ +#if 0 + disable_lcall(); +#endif +} + void arch_check_bugs(void) { int have_it; - if(access("/proc/cpuinfo", R_OK)){ + if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ printk("/proc/cpuinfo not available - skipping CPU capability " "checks\n"); return; } - if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it; - if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it; + if(check_cpu_flag("cmov", &have_it)) + host_has_cmov = have_it; + if(check_cpu_flag("xmm", &have_it)) + host_has_xmm = have_it; } int arch_handle_signal(int sig, union uml_pt_regs *regs) { - unsigned long ip; + unsigned char tmp[2]; /* This is testing for a cmov (0x0f 0x4x) instruction causing a * SIGILL in init. */ if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); - ip = UPT_IP(regs); - if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40)) + if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) + panic("SIGILL in init, could not read instructions!\n"); + if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) return(0); - if(cpu_has_cmov == 0) + if(host_has_cmov == 0) panic("SIGILL caused by cmov, which this processor doesn't " "implement, boot a filesystem compiled for older " "processors"); - else if(cpu_has_cmov == 1) + else if(host_has_cmov == 1) panic("SIGILL caused by cmov, which this processor claims to " "implement"); - else if(cpu_has_cmov == -1) + else if(host_has_cmov == -1) panic("SIGILL caused by cmov, couldn't tell if this processor " "implements it, boot a filesystem compiled for older " "processors"); - else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov); + else panic("Bad value for host_has_cmov (%d)", host_has_cmov); return(0); } diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c index 6a0ec334c..d0bbcdfdb 100644 --- a/arch/um/sys-i386/fault.c +++ b/arch/um/sys-i386/fault.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,16 +7,24 @@ #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" -extern unsigned long search_exception_table(unsigned long addr); +/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ +struct exception_table_entry +{ + unsigned long insn; + unsigned long fixup; +}; +const struct exception_table_entry *search_exception_tables(unsigned long add); + +/* Compare this to arch/i386/mm/extable.c:fixup_exception() */ int arch_fixup(unsigned long address, void *sc_ptr) { struct sigcontext *sc = sc_ptr; - unsigned long fixup; + const struct exception_table_entry *fixup; fixup = search_exception_tables(address); if(fixup != 0){ - sc->eip = fixup; + sc->eip = fixup->fixup; return(1); } return(0); diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 33e302160..ba77ccaa8 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -13,6 +13,8 @@ #ifdef CONFIG_MODE_TT extern int modify_ldt(int func, void *ptr, unsigned long bytecount); +/* XXX this needs copy_to_user and copy_from_user */ + int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) { if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 817ef7479..42322d888 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -7,6 +7,7 @@ #include "asm/elf.h" #include "asm/ptrace.h" #include "asm/uaccess.h" +#include "asm/unistd.h" #include "ptrace_user.h" #include "sysdep/sigcontext.h" #include "sysdep/sc.h" @@ -23,11 +24,12 @@ int is_syscall(unsigned long addr) n = copy_from_user(&instr, (void *) addr, sizeof(instr)); if(n){ - printk("is_syscall : failed to read instruction from 0x%lu\n", + printk("is_syscall : failed to read instruction from 0x%lx\n", addr); return(0); } - return(instr == 0x80cd); + /* int 0x80 or sysenter */ + return((instr == 0x80cd) || (instr == 0x340f)); } /* determines which flags the user has access to. */ diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 70da62313..b1021e82b 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c @@ -39,10 +39,11 @@ static void write_debugregs(int pid, unsigned long *regs) nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); for(i = 0; i < nregs; i++){ if((i == 4) || (i == 5)) continue; - if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], + if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i], regs[i]) < 0) - printk("write_debugregs - ptrace failed, " - "errno = %d\n", errno); + printk("write_debugregs - ptrace failed on " + "register %d, value = 0x%x, errno = %d\n", i, + regs[i], errno); } } @@ -54,7 +55,7 @@ static void read_debugregs(int pid, unsigned long *regs) dummy = NULL; nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); for(i = 0; i < nregs; i++){ - regs[i] = ptrace(PTRACE_PEEKUSR, pid, + regs[i] = ptrace(PTRACE_PEEKUSER, pid, &dummy->u_debugreg[i], 0); } } diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c index 751549bd7..6ad31749b 100644 --- a/arch/um/sys-i386/syscalls.c +++ b/arch/um/sys-i386/syscalls.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include "linux/sched.h" #include "asm/mman.h" #include "asm/uaccess.h" #include "asm/unistd.h" @@ -56,6 +57,27 @@ int old_select(struct sel_arg_struct *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } +/* The i386 version skips reading from %esi, the fourth argument. So we must do + * this, too. + */ +int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid, + int unused, int *child_tid) +{ + long ret; + + /* XXX: normal arch do here this pass, and also pass the regs to + * do_fork, instead of NULL. Currently the arch-independent code + * ignores these values, while the UML code (actually it's + * copy_thread) does the right thing. But this should change, + probably. */ + /*if (!newsp) + newsp = UPT_SP(current->thread.regs);*/ + current->thread.forking = 1; + ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); + current->thread.forking = 0; + return(ret); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c index 51333335b..281fc7b8c 100644 --- a/arch/um/sys-i386/sysrq.c +++ b/arch/um/sys-i386/sysrq.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + #include "linux/kernel.h" #include "linux/smp.h" #include "linux/sched.h" diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile index a3eca5f22..34860f9ca 100644 --- a/arch/um/sys-i386/util/Makefile +++ b/arch/um/sys-i386/util/Makefile @@ -1,17 +1,8 @@ -host-progs := mk_sc -always := $(host-progs) mk_thread -targets := mk_thread_kern.o mk_thread_user.o +hostprogs-y := mk_sc mk_thread +always := $(hostprogs-y) -mk_sc-objs := mk_sc.o +mk_thread-objs := mk_thread_kern.o mk_thread_user.o -$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o - $(CC) $(CFLAGS) -o $@ $^ - -$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c - $(CC) $(USER_CFLAGS) -c -o $@ $< - -clean : - $(RM) -f $(build-targets) - -archmrproper : clean +HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS) diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c index 224b6ad75..85cbd3039 100644 --- a/arch/um/sys-i386/util/mk_sc.c +++ b/arch/um/sys-i386/util/mk_sc.c @@ -38,6 +38,7 @@ int main(int argc, char **argv) SC_OFFSET("SC_ERR", err); SC_OFFSET("SC_CR2", cr2); SC_OFFSET("SC_FPSTATE", fpstate); + SC_OFFSET("SC_SIGMASK", oldmask); SC_FP_OFFSET("SC_FP_CW", cw); SC_FP_OFFSET("SC_FP_SW", sw); SC_FP_OFFSET("SC_FP_TAG", tag); diff --git a/arch/um/sys-ia64/Makefile b/arch/um/sys-ia64/Makefile index 4dd735320..d02f4c265 100644 --- a/arch/um/sys-ia64/Makefile +++ b/arch/um/sys-ia64/Makefile @@ -7,18 +7,5 @@ all: $(OBJ) $(OBJ): $(OBJS) rm -f $@ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -clean: - rm -f $(OBJS) -fastdep: - -archmrproper: - -archclean: - rm -f link.ld - @$(MAKEBOOT) clean - -archdep: - @$(MAKEBOOT) dep - -modules: +clean-files := $(OBJS) link.ld diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile index 3767c2583..af200268f 100644 --- a/arch/um/sys-ppc/Makefile +++ b/arch/um/sys-ppc/Makefile @@ -66,13 +66,4 @@ misc.o: misc.S ppc_defs.h $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm -clean: - rm -f $(OBJS) - rm -f ppc_defs.h - rm -f checksum.S semaphore.c mk_defs.c - -fastdep: - -dep: - -modules: +clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile index defd03861..e2ab71209 100644 --- a/arch/um/util/Makefile +++ b/arch/um/util/Makefile @@ -1,23 +1,8 @@ -always := mk_task mk_constants -targets := mk_task_user.o mk_task_kern.o \ - mk_constants_user.o mk_constants_kern.o +hostprogs-y := mk_task mk_constants +always := $(hostprogs-y) -$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o - $(CC) -o $@ $^ +mk_task-objs := mk_task_user.o mk_task_kern.o +mk_constants-objs := mk_constants_user.o mk_constants_kern.o -$(obj)/mk_task_user.o: $(src)/mk_task_user.c - $(CC) -o $@ -c $< - -$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o - $(CC) -o $@ $^ - -$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c - $(CC) -c $< -o $@ - -$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - $(RM) $(build-targets) - -archmrproper: +HOSTCFLAGS_mk_task_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_constants_kern.o := $(CFLAGS) $(CPPFLAGS) diff --git a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c index 7e7493431..cdcb1232a 100644 --- a/arch/um/util/mk_constants_kern.c +++ b/arch/um/util/mk_constants_kern.c @@ -1,5 +1,6 @@ #include "linux/kernel.h" #include "linux/stringify.h" +#include "linux/time.h" #include "asm/page.h" extern void print_head(void); @@ -11,6 +12,7 @@ int main(int argc, char **argv) { print_head(); print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE); + print_constant_str("UM_KERN_EMERG", KERN_EMERG); print_constant_str("UM_KERN_ALERT", KERN_ALERT); print_constant_str("UM_KERN_CRIT", KERN_CRIT); @@ -19,6 +21,8 @@ int main(int argc, char **argv) print_constant_str("UM_KERN_NOTICE", KERN_NOTICE); print_constant_str("UM_KERN_INFO", KERN_INFO); print_constant_str("UM_KERN_DEBUG", KERN_DEBUG); + + print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC); print_tail(); return(0); } diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index 8665652e2..4bb7e5150 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig @@ -68,7 +68,6 @@ menu "Processor type and features" bool "Anna" endchoice - #### V850E processor-specific config # All CPUs currently supported use the v850e architecture @@ -153,7 +152,6 @@ menu "Processor type and features" bool default RTE_MB_A_PCI - #### Some feature-specific configs # Everything except for the GDB simulator uses the same interrupt controller @@ -181,7 +179,6 @@ menu "Processor type and features" bool default !V850E_CACHE && !V850E2_CACHE - #### Misc config config ROM_KERNEL @@ -305,34 +302,7 @@ source "sound/Kconfig" source "drivers/usb/Kconfig" - -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - If you don't debug the kernel, you can say N. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL - help - Enables console device to interprent special characters as - commands to dump state information. - -config NO_KERNEL_MSG - bool "Suppress Kernel BUG Messages" - help - Do not output any debug BUG messages within the kernel. - -endmenu +source "arch/v850/Kconfig.debug" source "security/Kconfig" diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile index 117bcaaa0..3930482bd 100644 --- a/arch/v850/kernel/Makefile +++ b/arch/v850/kernel/Makefile @@ -9,7 +9,7 @@ # for more details. # -extra-y := head.o init_task.o vmlinux.lds.s +extra-y := head.o init_task.o vmlinux.lds obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \ signal.o irq.o mach.o ptrace.o bug.o diff --git a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c index 666930d9c..24f291369 100644 --- a/arch/v850/kernel/asm-consts.c +++ b/arch/v850/kernel/asm-consts.c @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #define DEFINE(sym, val) \ diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c index 17e3dbafc..af2e804b7 100644 --- a/arch/v850/kernel/fpga85e2c.c +++ b/arch/v850/kernel/fpga85e2c.c @@ -20,11 +20,11 @@ #include #include #include +#include #include #include #include -#include #include "mach.h" diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c index 89809fb98..336cbf21d 100644 --- a/arch/v850/kernel/irq.c +++ b/arch/v850/kernel/irq.c @@ -141,13 +141,15 @@ skip: int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { int status = 1; /* Force the "do bottom halves" bit */ + int ret; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) diff --git a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c index 9bd818b0f..673b50994 100644 --- a/arch/v850/kernel/memcons.c +++ b/arch/v850/kernel/memcons.c @@ -88,8 +88,7 @@ int memcons_tty_open (struct tty_struct *tty, struct file *filp) return 0; } -int memcons_tty_write (struct tty_struct *tty, int from_user, - const unsigned char *buf, int len) +int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len) { return write (buf, len); } diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index fc06058f2..8fa780757 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -1,8 +1,8 @@ /* * arch/v850/kernel/ptrace.c -- `ptrace' system call * - * Copyright (C) 2002,03 NEC Electronics Corporation - * Copyright (C) 2002,03 Miles Bader + * Copyright (C) 2002,03,04 NEC Electronics Corporation + * Copyright (C) 2002,03,04 Miles Bader * * Derived from arch/mips/kernel/ptrace.c: * @@ -147,14 +147,8 @@ int sys_ptrace(long request, long pid, long addr, long data) rval = ptrace_attach(child); goto out_tsk; } - rval = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } - if (child->parent != current) + rval = ptrace_check_attach(child, request == PTRACE_KILL); + if (rval < 0) goto out_tsk; switch (request) { @@ -238,7 +232,7 @@ int sys_ptrace(long request, long pid, long addr, long data) */ case PTRACE_KILL: rval = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; wake_up_process(child); @@ -269,11 +263,8 @@ asmlinkage void syscall_trace(void) return; /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c index da39beb8e..78a9cad86 100644 --- a/arch/v850/kernel/rte_mb_a_pci.c +++ b/arch/v850/kernel/rte_mb_a_pci.c @@ -254,7 +254,7 @@ static void __devinit pcibios_assign_resources (void) struct pci_dev *dev = NULL; struct resource *r; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { unsigned di_num; unsigned class = dev->class >> 8; @@ -322,8 +322,6 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, /* Stubs for things we don't use. */ -struct pci_fixup pcibios_fixups[] = { { 0 } }; - /* Called after each bus is probed, but before its children are examined. */ void pcibios_fixup_bus(struct pci_bus *b) { diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c index 8e8bf5ddc..dacc9b331 100644 --- a/arch/v850/kernel/setup.c +++ b/arch/v850/kernel/setup.c @@ -280,8 +280,8 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len) #if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1)) #error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it) #endif - - free_area_init_node (0, NODE_DATA(0), 0, zones_size, + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node (0, NODE_DATA(0), zones_size, ADDR_TO_PAGE (PAGE_OFFSET), 0); mem_map = NODE_DATA(0)->node_mem_map; } diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c index caa9e3a04..9432ff84a 100644 --- a/arch/v850/kernel/signal.c +++ b/arch/v850/kernel/signal.c @@ -344,9 +344,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -421,9 +419,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -431,11 +427,9 @@ give_sigsegv: */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Are we from a system call? */ if (PT_REGS_SYSCALL (regs)) { /* If so, check system call restarting.. */ @@ -468,9 +462,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -493,6 +484,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -506,10 +498,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c index 9aed8871b..7f0efaa02 100644 --- a/arch/v850/kernel/simcons.c +++ b/arch/v850/kernel/simcons.c @@ -59,7 +59,7 @@ int simcons_tty_open (struct tty_struct *tty, struct file *filp) return 0; } -int simcons_tty_write (struct tty_struct *tty, int from_user, +int simcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int count) { return V850_SIM_SYSCALL (write, 1, buf, count); diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c index 74067adea..f722a2682 100644 --- a/arch/v850/kernel/time.c +++ b/arch/v850/kernel/time.c @@ -40,24 +40,6 @@ unsigned long long sched_clock(void) return (unsigned long long)jiffies * (1000000000 / HZ); } -static inline void do_profile (unsigned long pc) -{ - if (prof_buffer && current->pid) { - extern int _stext; - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - if (pc < prof_len) - ++prof_buffer[pc]; - else - /* - * Don't ignore out-of-bounds PC values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - ++prof_buffer[prof_len-1]; - } -} - /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -74,10 +56,10 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs) mach_tick (); do_timer (regs); - - if (! user_mode (regs)) - do_profile (regs->pc); - +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif + profile_tick(CPU_PROFILING, regs); #if 0 /* * If we have an externally synchronized Linux clock, then update diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c index 2336da438..0ca64900d 100644 --- a/arch/v850/kernel/v850_ksyms.c +++ b/arch/v850/kernel/v850_ksyms.c @@ -14,7 +14,6 @@ #include #include #include -#include #include @@ -37,29 +36,29 @@ EXPORT_SYMBOL (ip_compute_csum); EXPORT_SYMBOL (ip_fast_csum); /* string / mem functions */ -EXPORT_SYMBOL_NOVERS (strcpy); -EXPORT_SYMBOL_NOVERS (strncpy); -EXPORT_SYMBOL_NOVERS (strcat); -EXPORT_SYMBOL_NOVERS (strncat); -EXPORT_SYMBOL_NOVERS (strcmp); -EXPORT_SYMBOL_NOVERS (strncmp); -EXPORT_SYMBOL_NOVERS (strchr); -EXPORT_SYMBOL_NOVERS (strlen); -EXPORT_SYMBOL_NOVERS (strnlen); -EXPORT_SYMBOL_NOVERS (strpbrk); -EXPORT_SYMBOL_NOVERS (strrchr); -EXPORT_SYMBOL_NOVERS (strstr); -EXPORT_SYMBOL_NOVERS (memset); -EXPORT_SYMBOL_NOVERS (memcpy); -EXPORT_SYMBOL_NOVERS (memmove); -EXPORT_SYMBOL_NOVERS (memcmp); -EXPORT_SYMBOL_NOVERS (memscan); +EXPORT_SYMBOL (strcpy); +EXPORT_SYMBOL (strncpy); +EXPORT_SYMBOL (strcat); +EXPORT_SYMBOL (strncat); +EXPORT_SYMBOL (strcmp); +EXPORT_SYMBOL (strncmp); +EXPORT_SYMBOL (strchr); +EXPORT_SYMBOL (strlen); +EXPORT_SYMBOL (strnlen); +EXPORT_SYMBOL (strpbrk); +EXPORT_SYMBOL (strrchr); +EXPORT_SYMBOL (strstr); +EXPORT_SYMBOL (memset); +EXPORT_SYMBOL (memcpy); +EXPORT_SYMBOL (memmove); +EXPORT_SYMBOL (memcmp); +EXPORT_SYMBOL (memscan); /* semaphores */ -EXPORT_SYMBOL_NOVERS (__down); -EXPORT_SYMBOL_NOVERS (__down_interruptible); -EXPORT_SYMBOL_NOVERS (__down_trylock); -EXPORT_SYMBOL_NOVERS (__up); +EXPORT_SYMBOL (__down); +EXPORT_SYMBOL (__down_interruptible); +EXPORT_SYMBOL (__down_trylock); +EXPORT_SYMBOL (__up); /* * libgcc functions - functions that are used internally by the @@ -72,8 +71,8 @@ extern void __lshrdi3 (void); extern void __muldi3 (void); extern void __negdi2 (void); -EXPORT_SYMBOL_NOVERS (__ashldi3); -EXPORT_SYMBOL_NOVERS (__ashrdi3); -EXPORT_SYMBOL_NOVERS (__lshrdi3); -EXPORT_SYMBOL_NOVERS (__muldi3); -EXPORT_SYMBOL_NOVERS (__negdi2); +EXPORT_SYMBOL (__ashldi3); +EXPORT_SYMBOL (__ashrdi3); +EXPORT_SYMBOL (__lshrdi3); +EXPORT_SYMBOL (__muldi3); +EXPORT_SYMBOL (__negdi2); diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S index 71669f7a9..bbd3429bc 100644 --- a/arch/v850/kernel/vmlinux.lds.S +++ b/arch/v850/kernel/vmlinux.lds.S @@ -60,6 +60,11 @@ ___start___kcrctab_gpl = .; \ *(__kcrctab_gpl) \ ___stop___kcrctab_gpl = .; \ + /* Built-in module parameters */ \ + ___start___param = .; \ + *(__param) \ + ___stop___param = .; + /* Kernel text segment, and some constant data areas. */ #define TEXT_CONTENTS \ @@ -111,9 +116,6 @@ *(.init.setup) /* 2.5 convention */ \ *(.setup.init) /* 2.4 convention */ \ ___setup_end = . ; \ - ___start___param = . ; \ - *(__param) \ - ___stop___param = . ; \ ___initcall_start = . ; \ *(.initcall.init) \ *(.initcall1.init) \ diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 2122afc52..4ffa04271 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -4,7 +4,7 @@ # # Note: ISA is disabled and will hopefully never be enabled. # If you managed to buy an ISA x86-64 box you'll have to fix all the -# ISA drivers you need yourself. +# ISA drivers you need yourself. # mainmenu "Linux Kernel Configuration" @@ -57,7 +57,7 @@ config EARLY_PRINTK it is not recommended because it looks ugly and doesn't cooperate with klogd/syslogd or the X server. You should normally N here, unless you want to debug such a crash. - + config HPET_TIMER bool default y @@ -72,12 +72,17 @@ config HPET_TIMER If unsure, say Y. config HPET_EMULATE_RTC - def_bool HPET_TIMER && RTC=y + bool "Provide RTC interrupt" + depends on HPET_TIMER && RTC=y config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" @@ -90,14 +95,14 @@ choice config MK8 bool "AMD-Opteron/Athlon64" help - Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. + Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. config MPSC - bool "Intel x86-64" + bool "Intel x86-64" help Optimize for Intel IA32 with 64bit extension CPUs (Prescott/Nocona/Potomac) - + config GENERIC_CPU bool "Generic-x86-64" help @@ -130,8 +135,8 @@ config MICROCODE tristate "/dev/cpu/microcode - Intel CPU microcode support" ---help--- If you say Y here the 'File systems' section, you will be - able to update the microcode on Intel processors. You will - obviously need the actual microcode binary data itself which is + able to update the microcode on Intel processors. You will + obviously need the actual microcode binary data itself which is not shipped with the Linux kernel. For latest news and information on obtaining all the required @@ -165,7 +170,7 @@ config X86_HT bool depends on SMP && !MK8 default y - + config MATH_EMULATION bool @@ -231,13 +236,13 @@ config PREEMPT be preempted even if it is in kernel mode executing a system call. This allows applications to run more reliably even when the system is under load. On contrary it may also break your drivers and add - priority inheritance problems to your system. Don't select it if + priority inheritance problems to your system. Don't select it if you rely on a stable system or have slightly obscure hardware. It's also not very well tested on x86-64 currently. You have been warned. - Say Y here if you are feeling brave and building a kernel for a - desktop, embedded or real-time system. Say N if you are unsure. + Say Y here if you are feeling brave and building a kernel for a + desktop, embedded or real-time system. Say N if you are unsure. config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" @@ -251,6 +256,7 @@ config SCHED_SMT config K8_NUMA bool "K8 NUMA support" + select NUMA depends on SMP help Enable NUMA (Non Unified Memory Architecture) support for @@ -260,15 +266,23 @@ config K8_NUMA This code is recommended on all multiprocessor Opteron systems and normally doesn't hurt on others. +config NUMA_EMU + bool "NUMA emulation support" + select NUMA + depends on SMP + help + Enable NUMA emulation. A flat machine will be split + into virtual nodes when booted with "numa=fake=N", where N is the + number of nodes. This is only useful for debugging. + config DISCONTIGMEM bool - depends on K8_NUMA + depends on NUMA default y config NUMA bool - depends on K8_NUMA - default y + default n config HAVE_DEC_LOCK bool @@ -292,12 +306,13 @@ config NR_CPUS config GART_IOMMU bool "IOMMU support" + depends on PCI help Support the K8 IOMMU. Needed to run systems with more than 4GB of memory properly with 32-bit PCI devices that do not support DAC (Double Address Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter. Normally the kernel will take the right choice by itself. - If unsure say Y + If unsure, say Y. # need this always enabled with GART_IOMMU for the VIA workaround config SWIOTLB @@ -310,16 +325,31 @@ config DUMMY_IOMMU depends on !GART_IOMMU && !SWIOTLB default y help - Don't use IOMMU code. This will cause problems when you have more than 4GB + Don't use IOMMU code. This will cause problems when you have more than 4GB of memory and any 32-bit devices. Don't turn on unless you know what you are doing. config X86_MCE - bool + bool "Machine check support" if EMBEDDED default y + help + Include a machine check error handler to report hardware errors. + This version will require the mcelog utility to decode some + machine check error logs. See + ftp://ftp.x86-64.org/pub/linux/tools/mcelog endmenu +# +# Use the generic interrupt handling code in kernel/irq/: +# +config GENERIC_HARDIRQS + bool + default y + +config GENERIC_IRQ_PROBE + bool + default y menu "Power management options" @@ -336,17 +366,27 @@ menu "Bus options (PCI etc.)" config PCI bool "PCI support" -# x86-64 doesn't support PCI BIOS access from long mode so always go direct. +# x86-64 doesn't support PCI BIOS access from long mode so always go direct. config PCI_DIRECT bool depends on PCI default y -config PCI_MMCONFIG - bool "Support mmconfig PCI config space access" +config PCI_MMCONFIG + bool "Support mmconfig PCI config space access" depends on PCI select ACPI_BOOT +config UNORDERED_IO + bool "Unordered IO mapping access" + depends on EXPERIMENTAL + help + Use unordered stores to access IO memory mappings in device drivers. + Still very experimental. When a driver works on IA64/ppc64/pa-risc it should + work with this option, but it makes the drivers behave differently + from i386. Requires that the driver writer used memory barriers + properly. + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" @@ -398,110 +438,10 @@ source fs/Kconfig source "arch/x86_64/oprofile/Kconfig" -menu "Kernel hacking" - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL - help - 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. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - 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. - -# !SMP for now because the context switch early causes GPF in segment reloading -# and the GS base checking does the wrong thing then, causing a hang. -config CHECKING - bool "Additional run-time checks" - depends on DEBUG_KERNEL && !SMP - help - Enables some internal consistency checks for kernel debugging. - You should normally say N. - -config INIT_DEBUG - bool "Debug __init statements" - depends on DEBUG_KERNEL - help - Fill __init and __initdata at the end of boot. This helps debugging - illegal uses of __init and __initdata after initialization. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to use gdb to debug the kernel. - Please note that this option requires new binutils. - If you don't debug the kernel, you can say N. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - help - Compile the kernel with frame pointers. This may help for some - debugging with external debuggers. Note the standard oops backtracer - doesn't make use of this and the x86-64 kernel doesn't ensure an consistent - frame pointer through inline assembly (semaphores etc.) - Normally you should say N. - -config IOMMU_DEBUG - depends on GART_IOMMU && DEBUG_KERNEL - bool "Enable IOMMU debugging" - help - Force the IOMMU to on even when you have less than 4GB of - memory and add debugging code. On overflow always panic. And - allow to enable IOMMU leak tracing. Can be disabled at boot - time with iommu=noforce. This will also enable scatter gather - list merging. Currently not recommended for production - code. When you use it make sure you have a big enough - IOMMU/AGP aperture. Most of the options enabled by this can - be set more finegrained using the iommu= command line - options. See Documentation/x86_64/boot-options.txt for more - details. - -config IOMMU_LEAK - bool "IOMMU leak tracing" - depends on DEBUG_KERNEL - depends on IOMMU_DEBUG - help - Add a simple leak tracer to the IOMMU code. This is useful when you - are debugging a buggy device driver that leaks IOMMU mappings. - -#config X86_REMOTE_DEBUG -# bool "kgdb debugging stub" - -endmenu +source "arch/x86_64/Kconfig.debug" source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index 2ba7f5a05..9cf1410d2 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -18,18 +18,6 @@ config INIT_DEBUG Fill __init and __initdata at the end of boot. This helps debugging illegal uses of __init and __initdata after initialization. -config SCHEDSTATS - bool "Collect scheduler statistics" - depends on DEBUG_KERNEL && PROC_FS - help - If you say Y here, additional code will be inserted into the - scheduler and related routines to collect statistics about - scheduler behavior and provide them in /proc/schedstat. These - stats may be useful for both tuning and debugging the scheduler - If you aren't debugging the scheduler or trying to tune a specific - application, you can say N to avoid the very slight overhead - this adds. - config IOMMU_DEBUG depends on GART_IOMMU && DEBUG_KERNEL bool "Enable IOMMU debugging" @@ -45,6 +33,16 @@ config IOMMU_DEBUG options. See Documentation/x86_64/boot-options.txt for more details. +config KPROBES + bool "Kprobes" + depends on DEBUG_KERNEL + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". + config IOMMU_LEAK bool "IOMMU leak tracing" depends on DEBUG_KERNEL diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index 9b9a504ef..a69f7bcdf 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -37,10 +37,10 @@ LDFLAGS := -m elf_x86_64 OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -e stext -CHECK := $(CHECK) -D__x86_64__=1 +CHECKFLAGS += -D__x86_64__ -m64 -cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,) -cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,) +cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) +cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) CFLAGS += $(cflags-y) CFLAGS += -mno-red-zone @@ -54,11 +54,11 @@ ifneq ($(CONFIG_DEBUG_INFO),y) CFLAGS += -fno-asynchronous-unwind-tables # -fweb shrinks the kernel a bit, but the difference is very small # it also messes up debugging, so don't use it for now. -#CFLAGS += $(call check_gcc,-fweb,) +#CFLAGS += $(call cc-option,-fweb) endif # -funit-at-a-time shrinks the kernel .text considerably # unfortunately it makes reading oopses harder. -CFLAGS += $(call check_gcc,-funit-at-a-time,) +CFLAGS += $(call cc-option,-funit-at-a-time) head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o @@ -77,6 +77,7 @@ boot := arch/x86_64/boot all: bzImage BOOTIMAGE := arch/x86_64/boot/bzImage +KBUILD_IMAGE := $(BOOTIMAGE) bzImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile index 1c2d3cbca..f4399c701 100644 --- a/arch/x86_64/boot/Makefile +++ b/arch/x86_64/boot/Makefile @@ -30,7 +30,8 @@ targets := vmlinux.bin bootsect bootsect.o \ EXTRA_CFLAGS := -m32 -host-progs := tools/build +hostprogs-y := tools/build +HOST_EXTRACFLAGS += $(LINUXINCLUDE) subdir- := compressed/ #Let make clean descend in compressed/ # --------------------------------------------------------------------------- diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile index 759956d1b..f89d96f11 100644 --- a/arch/x86_64/boot/compressed/Makefile +++ b/arch/x86_64/boot/compressed/Makefile @@ -11,7 +11,7 @@ EXTRA_AFLAGS := -traditional -m32 # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with # -m32 -CFLAGS := -m32 -D__KERNEL__ -Iinclude -O2 +CFLAGS := -m32 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing LDFLAGS := -m elf_i386 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386 diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S index 5d4cdc1ab..0587477c9 100644 --- a/arch/x86_64/boot/video.S +++ b/arch/x86_64/boot/video.S @@ -66,6 +66,7 @@ #define VIDEO_80x30 0x0f05 #define VIDEO_80x34 0x0f06 #define VIDEO_80x60 0x0f07 +#define VIDEO_GFX_HACK 0x0f08 #define VIDEO_LAST_SPECIAL 0x0f09 /* Video modes given by resolution */ @@ -97,7 +98,6 @@ #define PARAM_LFB_PAGES 0x32 #define PARAM_VESA_ATTRIB 0x34 - /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN #define DO_STORE call store_screen @@ -133,6 +133,7 @@ vid1: #ifdef CONFIG_VIDEO_RETAIN call restore_screen # Restore screen contents #endif /* CONFIG_VIDEO_RETAIN */ + call store_edid #endif /* CONFIG_VIDEO_SELECT */ call mode_params # Store mode parameters popw %ds # Restore original DS @@ -231,6 +232,41 @@ mopar_gr: xorl %eax, %eax movw 18(%di), %ax movl %eax, %fs:(PARAM_LFB_SIZE) + +# switching the DAC to 8-bit is for <= 8 bpp only + movw %fs:(PARAM_LFB_DEPTH), %ax + cmpw $8, %ax + jg dac_done + +# get DAC switching capability + xorl %eax, %eax + movb 10(%di), %al + testb $1, %al + jz dac_set + +# attempt to switch DAC to 8-bit + movw $0x4f08, %ax + movw $0x0800, %bx + int $0x10 + cmpw $0x004f, %ax + jne dac_set + movb %bh, dac_size # store actual DAC size + +dac_set: +# set color size to DAC size + movb dac_size, %al + movb %al, %fs:(PARAM_LFB_COLORS+0) + movb %al, %fs:(PARAM_LFB_COLORS+2) + movb %al, %fs:(PARAM_LFB_COLORS+4) + movb %al, %fs:(PARAM_LFB_COLORS+6) + +# set color offsets to 0 + movb $0, %fs:(PARAM_LFB_COLORS+1) + movb $0, %fs:(PARAM_LFB_COLORS+3) + movb $0, %fs:(PARAM_LFB_COLORS+5) + movb $0, %fs:(PARAM_LFB_COLORS+7) + +dac_done: # get protected mode interface informations movw $0x4f0a, %ax xorw %bx, %bx @@ -440,7 +476,7 @@ setalias: # Setting of user mode (AX=mode ID) => CF=success mode_set: - movw %ax, %fs:(0x01fa) + movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S movw %ax, %bx cmpb $0xff, %ah jz setalias @@ -744,7 +780,15 @@ set_80x60: movw $0x503c, force_size jmp setvde +# Special hack for ThinkPad graphics set_gfx: +#ifdef CONFIG_VIDEO_GFX_HACK + movw $VIDEO_GFX_BIOS_AX, %ax + movw $VIDEO_GFX_BIOS_BX, %bx + int $0x10 + movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size + stc +#endif ret #ifdef CONFIG_VIDEO_RETAIN @@ -969,6 +1013,10 @@ vga_modes: .word 0x5022 # 80x34 .word VIDEO_80x60 .word 0x503c # 80x60 +#ifdef CONFIG_VIDEO_GFX_HACK + .word VIDEO_GFX_HACK + .word VIDEO_GFX_DUMMY_RESOLUTION +#endif vga_modes_end: # Detect VESA modes. @@ -1875,6 +1923,39 @@ skip10: movb %ah, %al popw %ax ret +store_edid: + pushw %es # just save all registers + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %di + + pushw %fs + popw %es + + movl $0x13131313, %eax # memset block with 0x13 + movw $32, %cx + movw $0x140, %di + cld + rep + stosl + + movw $0x4f15, %ax # do VBE/DDC + movw $0x01, %bx + movw $0x00, %cx + movw $0x01, %dx + movw $0x140, %di + int $0x10 + + popw %di # restore all registers + popw %dx + popw %cx + popw %bx + popw %ax + popw %es + ret + # VIDEO_SELECT-only variables mt_end: .word 0 # End of video mode table if built edit_buf: .space 6 # Line editor buffer @@ -1883,6 +1964,7 @@ scanning: .byte 0 # Performing mode scan do_restore: .byte 0 # Screen contents altered during mode change svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +dac_size: .byte 6 # DAC bit depth # Status messages keymsg: .ascii "Press to see video modes available, " diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index bf6969fa0..06d778083 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,5 +1,7 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.10-rc1-bk6 +# Thu Oct 28 00:07:32 2004 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -11,17 +13,19 @@ CONFIG_EARLY_PRINTK=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y +CONFIG_LOCK_KERNEL=y # # General setup # +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -30,18 +34,18 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=18 # CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +# CONFIG_TINY_SHMEM is not set # # Loadable module support @@ -51,6 +55,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set CONFIG_STOP_MACHINE=y @@ -75,6 +80,7 @@ CONFIG_SMP=y # CONFIG_PREEMPT is not set CONFIG_SCHED_SMT=y CONFIG_K8_NUMA=y +# CONFIG_NUMA_EMU is not set CONFIG_DISCONTIGMEM=y CONFIG_NUMA=y CONFIG_HAVE_DEC_LOCK=y @@ -82,12 +88,16 @@ CONFIG_NR_CPUS=8 CONFIG_GART_IOMMU=y CONFIG_SWIOTLB=y CONFIG_X86_MCE=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y # # Power management options # CONFIG_PM=y +# CONFIG_PM_DEBUG is not set CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" # # ACPI (Advanced Configuration and Power Interface) Support @@ -105,6 +115,7 @@ CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_ASUS is not set CONFIG_ACPI_TOSHIBA=y +CONFIG_ACPI_BLACKLIST_YEAR=2001 CONFIG_ACPI_DEBUG=y CONFIG_ACPI_BUS=y CONFIG_ACPI_EC=y @@ -123,6 +134,8 @@ CONFIG_ACPI_SYSTEM=y CONFIG_PCI=y CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y +CONFIG_UNORDERED_IO=y +CONFIG_PCI_MSI=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set @@ -144,6 +157,8 @@ CONFIG_UID16=y # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # @@ -171,11 +186,22 @@ CONFIG_BLK_DEV_FD=y CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" CONFIG_LBD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support @@ -186,16 +212,15 @@ CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -212,7 +237,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set CONFIG_BLK_DEV_AMD74XX=y @@ -273,36 +297,47 @@ CONFIG_BLK_DEV_SD=y # SCSI low-level drivers # CONFIG_BLK_DEV_3W_XXXX_RAID=y +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set +CONFIG_SCSI_AIC79XX=y +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=4000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set # CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y +# CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set # CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set CONFIG_SCSI_SATA_VIA=y # CONFIG_SCSI_SATA_VITESSE is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLOGIC_1280_1040 is not set CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set @@ -324,7 +359,6 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_FUSION=y CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set # CONFIG_FUSION_CTL is not set # @@ -362,11 +396,13 @@ CONFIG_IP_MULTICAST=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set # CONFIG_NETFILTER is not set @@ -386,12 +422,12 @@ CONFIG_IPV6=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -465,6 +501,7 @@ CONFIG_E1000=y # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # @@ -532,6 +569,7 @@ CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set # # Input Device Drivers @@ -575,7 +613,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set # # IPMI @@ -602,6 +639,9 @@ CONFIG_AGP_AMD64=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +CONFIG_HPET_MMAP=y CONFIG_MAX_RAW_DEVS=256 CONFIG_HANGCHECK_TIMER=y @@ -610,6 +650,11 @@ CONFIG_HANGCHECK_TIMER=y # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + # # Misc devices # @@ -635,7 +680,6 @@ CONFIG_HANGCHECK_TIMER=y # Console display driver support # CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y # @@ -686,6 +730,10 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y # # USB Host Controller Drivers @@ -694,7 +742,7 @@ CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers @@ -706,6 +754,7 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_PRINTER=y CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_RW_DETECT is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set @@ -716,7 +765,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_JUMPSHOT is not set # -# USB Human Interface Devices (HID) +# USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y @@ -777,9 +826,14 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_TEST is not set +# +# USB ATM/DSL drivers +# + # # USB Gadget Support # @@ -830,7 +884,8 @@ CONFIG_ISO9660_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -842,6 +897,7 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y @@ -879,6 +935,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set @@ -906,17 +963,20 @@ CONFIG_OPROFILE=y # Kernel hacking # CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_INIT_DEBUG is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_FRAME_POINTER is not set +CONFIG_INIT_DEBUG=y # CONFIG_IOMMU_DEBUG is not set # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -927,5 +987,6 @@ CONFIG_MAGIC_SYSRQ=y # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 040e56f75..9d5991982 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c @@ -31,6 +31,7 @@ #include #include #include +#include #undef WARN_OLD #undef CORE_DUMP /* probably broken */ @@ -168,12 +169,12 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file) /* If the size of the dump file exceeds the rlimit, then see what would happen if we wrote the stack, but not the data area. */ if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > - current->rlim[RLIMIT_CORE].rlim_cur) + current->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; /* Make sure we have enough room to write the stack and data areas. */ if ((dump.u_ssize+1) * PAGE_SIZE > - current->rlim[RLIMIT_CORE].rlim_cur) + current->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; /* make sure we actually have a data and stack area to dump */ @@ -281,7 +282,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) * size limits imposed on them by creating programs with large * arrays in the data or bss. */ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; + rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ex.a_data + ex.a_bss > rlim) diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 8e6b845f7..1abc95c54 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -182,6 +182,7 @@ struct elf_prpsinfo #define user user32 #define __ASM_X86_64_ELF_H 1 +#define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) //#include #include @@ -301,6 +302,9 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen"); #define elf_addr_t __u32 +#undef TASK_SIZE +#define TASK_SIZE 0xffffffff + static void elf32_init(struct pt_regs *); #include "../../../fs/binfmt_elf.c" @@ -330,7 +334,7 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) unsigned long stack_base; struct vm_area_struct *mpnt; struct mm_struct *mm = current->mm; - int i; + int i, ret; stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE; mm->arg_start = bprm->p + stack_base; @@ -357,15 +361,19 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack) mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = IA32_STACK_TOP; if (executable_stack == EXSTACK_ENABLE_X) - mpnt->vm_flags = vm_stack_flags32 | VM_EXEC; + mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC; else if (executable_stack == EXSTACK_DISABLE_X) - mpnt->vm_flags = vm_stack_flags32 & ~VM_EXEC; + mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; else - mpnt->vm_flags = vm_stack_flags32; + mpnt->vm_flags = VM_STACK_FLAGS; mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? PAGE_COPY_EXEC : PAGE_COPY; - insert_vm_struct(mm, mpnt); - mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + if ((ret = insert_vm_struct(mm, mpnt))) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, mpnt); + return ret; + } + mm->stack_vm = mm->total_vm = vma_pages(mpnt); } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { @@ -387,9 +395,6 @@ elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int p unsigned long map_addr; struct task_struct *me = current; - if (prot & PROT_READ) - prot |= vm_force_exec32; - down_write(&me->mm->mmap_sem); map_addr = do_mmap(filep, ELF_PAGESTART(addr), eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 8c6964245..d259f8a6f 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -171,23 +171,8 @@ struct ioctl_trans ioctl_start[] = { COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 5716c8bec..5fb7d173b 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -115,7 +115,8 @@ int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from) } asmlinkage long -sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs) +sys32_sigsuspend(int history0, int history1, old_sigset_t mask, + struct pt_regs *regs) { sigset_t saveset; @@ -126,11 +127,11 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs r recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.rax = -EINTR; + regs->rax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(®s, &saveset)) + if (do_signal(regs, &saveset)) return -EINTR; } } @@ -138,7 +139,7 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs r asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, stack_ia32_t __user *uoss_ptr, - struct pt_regs regs) + struct pt_regs *regs) { stack_t uss,uoss; int ret; @@ -155,7 +156,7 @@ sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || @@ -274,9 +275,9 @@ badframe: return 1; } -asmlinkage long sys32_sigreturn(struct pt_regs regs) +asmlinkage long sys32_sigreturn(struct pt_regs *regs) { - struct sigframe __user *frame = (struct sigframe __user *)(regs.rsp-8); + struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8); sigset_t set; unsigned int eax; @@ -294,20 +295,23 @@ asmlinkage long sys32_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (ia32_restore_sigcontext(®s, &frame->sc, &eax)) + if (ia32_restore_sigcontext(regs, &frame->sc, &eax)) goto badframe; return eax; badframe: - signal_fault(®s, frame, "32bit sigreturn"); + signal_fault(regs, frame, "32bit sigreturn"); return 0; } -asmlinkage long sys32_rt_sigreturn(struct pt_regs regs) +asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) { - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs.rsp - 4); + struct rt_sigframe __user *frame; sigset_t set; unsigned int eax; + struct pt_regs tregs; + + frame = (struct rt_sigframe __user *)(regs->rsp - 4); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -320,16 +324,17 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (ia32_restore_sigcontext(®s, &frame->uc.uc_mcontext, &eax)) + if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) goto badframe; - if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, regs) == -EFAULT) + tregs = *regs; + if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT) goto badframe; return eax; badframe: - signal_fault(®s,frame,"32bit rt sigreturn"); + signal_fault(regs,frame,"32bit rt sigreturn"); return 0; } @@ -342,6 +347,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ struct pt_regs *regs, unsigned int mask) { int tmp, err = 0; + u32 eflags; tmp = 0; __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); @@ -366,7 +372,11 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ err |= __put_user(current->thread.trap_no, &sc->trapno); err |= __put_user(current->thread.error_code, &sc->err); err |= __put_user((u32)regs->rip, &sc->eip); - err |= __put_user((u32)regs->eflags, &sc->eflags); + eflags = regs->eflags; + if (current->ptrace & PT_PTRACED) { + eflags &= ~TF_MASK; + } + err |= __put_user((u32)eflags, &sc->eflags); err |= __put_user((u32)regs->rsp, &sc->esp_at_signal); tmp = save_i387_ia32(current, fpstate, regs, 0); @@ -484,7 +494,13 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, regs->ss = __USER32_DS; set_fs(USER_DS); - regs->eflags &= ~TF_MASK; + if (regs->eflags & TF_MASK) { + if (current->ptrace & PT_PTRACED) { + ptrace_notify(SIGTRAP); + } else { + regs->eflags &= ~TF_MASK; + } + } #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -494,9 +510,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs,frame,"32bit signal deliver"); + force_sigsegv(sig, current); } void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -580,7 +594,13 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->ss = __USER32_DS; set_fs(USER_DS); - regs->eflags &= ~TF_MASK; + if (regs->eflags & TF_MASK) { + if (current->ptrace & PT_PTRACED) { + ptrace_notify(SIGTRAP); + } else { + regs->eflags &= ~TF_MASK; + } + } #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -590,8 +610,6 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs, frame, "32bit rt signal setup"); + force_sigsegv(sig, current); } diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 0a2fb66b6..d469f9293 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -270,35 +270,32 @@ quiet_ni_syscall: ret CFI_ENDPROC - .macro PTREGSCALL label, func + .macro PTREGSCALL label, func, arg .globl \label \label: leaq \func(%rip),%rax + leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ jmp ia32_ptregs_common .endm - PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn - PTREGSCALL stub32_sigreturn, sys32_sigreturn - PTREGSCALL stub32_sigaltstack, sys32_sigaltstack - PTREGSCALL stub32_sigsuspend, sys32_sigsuspend - PTREGSCALL stub32_execve, sys32_execve - PTREGSCALL stub32_fork, sys_fork - PTREGSCALL stub32_clone, sys32_clone - PTREGSCALL stub32_vfork, sys_vfork - PTREGSCALL stub32_iopl, sys_iopl - PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend + PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi + PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi + PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx + PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx + PTREGSCALL stub32_execve, sys32_execve, %rcx + PTREGSCALL stub32_fork, sys_fork, %rdi + PTREGSCALL stub32_clone, sys32_clone, %rdx + PTREGSCALL stub32_vfork, sys_vfork, %rdi + PTREGSCALL stub32_iopl, sys_iopl, %rsi + PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx ENTRY(ia32_ptregs_common) CFI_STARTPROC popq %r11 SAVE_REST - movq %r11, %r15 call *%rax - movq %r15, %r11 RESTORE_REST - leaq ia32_sysret(%rip),%r11 - pushq %r11 - ret + jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC .data @@ -332,7 +329,7 @@ ia32_sys_call_table: .quad sys_getuid16 .quad sys_stime /* stime */ /* 25 */ .quad sys32_ptrace /* ptrace */ - .quad sys_alarm /* XXX sign extension??? */ + .quad sys_alarm .quad sys_fstat /* (old)fstat */ .quad sys_pause .quad compat_sys_utime /* 30 */ @@ -394,7 +391,7 @@ ia32_sys_call_table: .quad sys_uselib .quad sys_swapon .quad sys_reboot - .quad sys32_oldreaddir + .quad compat_sys_old_readdir .quad sys32_mmap /* 90 */ .quad sys_munmap .quad sys_truncate @@ -436,7 +433,7 @@ ia32_sys_call_table: .quad sys_init_module .quad sys_delete_module .quad quiet_ni_syscall /* 130 get_kernel_syms */ - .quad sys32_quotactl /* quotactl */ + .quad sys_quotactl .quad sys_getpgid .quad sys_fchdir .quad quiet_ni_syscall /* bdflush */ @@ -446,7 +443,7 @@ ia32_sys_call_table: .quad sys_setfsuid16 .quad sys_setfsgid16 .quad sys_llseek /* 140 */ - .quad sys32_getdents + .quad compat_sys_getdents .quad compat_sys_select .quad sys_flock .quad sys_msync @@ -525,7 +522,7 @@ ia32_sys_call_table: .quad sys_pivot_root .quad sys_mincore .quad sys_madvise - .quad sys_getdents64 /* 220 getdents64 */ + .quad compat_sys_getdents64 /* 220 getdents64 */ .quad compat_sys_fcntl64 .quad quiet_ni_syscall /* tux */ .quad quiet_ni_syscall /* security */ @@ -550,37 +547,37 @@ ia32_sys_call_table: .quad compat_sys_sched_getaffinity .quad sys32_set_thread_area .quad sys32_get_thread_area - .quad sys32_io_setup /* 245 */ + .quad compat_sys_io_setup /* 245 */ .quad sys_io_destroy - .quad sys32_io_getevents - .quad sys32_io_submit + .quad compat_sys_io_getevents + .quad compat_sys_io_submit .quad sys_io_cancel .quad sys_fadvise64 /* 250 */ .quad quiet_ni_syscall /* free_huge_pages */ .quad sys_exit_group - .quad sys_lookup_dcookie + .quad sys32_lookup_dcookie .quad sys_epoll_create .quad sys_epoll_ctl /* 255 */ .quad sys_epoll_wait .quad sys_remap_file_pages .quad sys_set_tid_address .quad sys32_timer_create - .quad compat_timer_settime /* 260 */ - .quad compat_timer_gettime + .quad compat_sys_timer_settime /* 260 */ + .quad compat_sys_timer_gettime .quad sys_timer_getoverrun .quad sys_timer_delete - .quad compat_clock_settime - .quad compat_clock_gettime /* 265 */ - .quad compat_clock_getres - .quad compat_clock_nanosleep - .quad compat_statfs64 - .quad compat_fstatfs64 + .quad compat_sys_clock_settime + .quad compat_sys_clock_gettime /* 265 */ + .quad compat_sys_clock_getres + .quad compat_sys_clock_nanosleep + .quad compat_sys_statfs64 + .quad compat_sys_fstatfs64 .quad sys_tgkill /* 270 */ .quad compat_sys_utimes .quad sys32_fadvise64_64 .quad quiet_ni_syscall /* sys_vserver */ .quad sys_mbind - .quad compat_get_mempolicy /* 275 */ + .quad compat_sys_get_mempolicy /* 275 */ .quad sys_set_mempolicy .quad compat_sys_mq_open .quad sys_mq_unlink @@ -589,6 +586,7 @@ ia32_sys_call_table: .quad compat_sys_mq_notify .quad compat_sys_mq_getsetattr .quad quiet_ni_syscall /* reserved for kexec */ + .quad sys32_waitid /* don't forget to change IA32_NR_syscalls */ ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 01202b792..81d4a9883 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -109,7 +109,8 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) case offsetof(struct user32, u_debugreg[7]): val &= ~DR_CONTROL_RESERVED; - /* You are not expected to understand this ... I don't neither. */ + /* See arch/i386/kernel/ptrace.c for an explanation of + * this awkward check.*/ for(i=0; i<4; i++) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) return -EIO; @@ -249,8 +250,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_GETFPREGS: case PTRACE_SETFPXREGS: case PTRACE_GETFPXREGS: + case PTRACE_GETEVENTMSG: break; - } child = find_target(request, pid, &ret); @@ -363,6 +364,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; } + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message,(unsigned int __user *)(u64)data); + break; + default: ret = -EINVAL; break; diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index ab8003492..ddd20d476 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -218,9 +218,6 @@ sys32_mmap(struct mmap_arg_struct __user *arg) return -EBADF; } - if (a.prot & PROT_READ) - a.prot |= vm_force_exec32; - mm = current->mm; down_write(&mm->mmap_sem); retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT); @@ -235,8 +232,6 @@ sys32_mmap(struct mmap_arg_struct __user *arg) asmlinkage long sys32_mprotect(unsigned long start, size_t len, unsigned long prot) { - if (prot & PROT_READ) - prot |= vm_force_exec32; return sys_mprotect(start,len,prot); } @@ -478,134 +473,6 @@ sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -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]; -}; - -struct getdents32_callback { - struct linux32_dirent __user * current_dir; - struct linux32_dirent __user * previous; - int count; - int error; -}; - -struct readdir32_callback { - struct old_linux32_dirent __user * dirent; - int count; -}; - -static int -filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, - unsigned int d_type) -{ - struct linux32_dirent __user * dirent; - struct getdents32_callback * buf = (struct getdents32_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2, 4); - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - dirent = buf->previous; - if (dirent) - put_user(offset, &dirent->d_off); - dirent = buf->current_dir; - buf->previous = dirent; - put_user(ino, &dirent->d_ino); - put_user(reclen, &dirent->d_reclen); - copy_to_user(dirent->d_name, name, namlen); - put_user(0, dirent->d_name + namlen); - put_user(d_type, (char __user *)dirent + reclen - 1); - dirent = ((void __user *)dirent) + reclen; - buf->current_dir = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage long -sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count) -{ - struct file * file; - struct linux32_dirent __user * lastdirent; - struct getdents32_callback buf; - int error; - - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - - buf.current_dir = (struct linux32_dirent __user *) dirent; - buf.previous = NULL; - buf.count = count; - buf.error = 0; - - error = vfs_readdir(file, filldir32, &buf); - if (error < 0) - goto out_putf; - error = buf.error; - lastdirent = buf.previous; - if (lastdirent) { - put_user(file->f_pos, &lastdirent->d_off); - error = count - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -static int -fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned d_type) -{ - struct readdir32_callback * buf = (struct readdir32_callback *) __buf; - struct old_linux32_dirent __user * dirent; - - if (buf->count) - return -EINVAL; - buf->count++; - dirent = buf->dirent; - put_user(ino, &dirent->d_ino); - put_user(offset, &dirent->d_offset); - put_user(namlen, &dirent->d_namlen); - copy_to_user(dirent->d_name, name, namlen); - put_user(0, dirent->d_name + namlen); - return 0; -} - -asmlinkage long -sys32_oldreaddir (unsigned int fd, void __user * dirent, unsigned int count) -{ - int error; - struct file * file; - struct readdir32_callback buf; - - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - - buf.count = 0; - buf.dirent = dirent; - - error = vfs_readdir(file, fillonedir32, &buf); - if (error >= 0) - error = buf.count; - fput(file); -out: - return error; -} - struct sel_arg_struct { unsigned int n; unsigned int inp; @@ -658,11 +525,12 @@ sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) int sys32_ni_syscall(int call) { struct task_struct *me = current; - static char lastcomm[8]; - if (strcmp(lastcomm, me->comm)) { - printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", call, - current->comm); - strcpy(lastcomm, me->comm); + static char lastcomm[sizeof(me->comm)]; + + if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { + printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", + call, me->comm); + strncpy(lastcomm, me->comm, sizeof(lastcomm)); } return -ENOSYS; } @@ -1044,9 +912,6 @@ asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len, return -EBADF; } - if (prot & PROT_READ) - prot |= vm_force_exec32; - down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(&mm->mmap_sem); @@ -1125,7 +990,7 @@ long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) } asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs regs) + compat_uptr_t __user *envp, struct pt_regs *regs) { long error; char * filename; @@ -1134,21 +999,50 @@ asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, error = PTR_ERR(filename); if (IS_ERR(filename)) return error; - error = compat_do_execve(filename, argv, envp, ®s); - if (error == 0) + error = compat_do_execve(filename, argv, envp, regs); + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); return error; } -asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs) +asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, + struct pt_regs *regs) { - void __user *parent_tid = (void __user *)regs.rdx; - void __user *child_tid = (void __user *)regs.rdi; + void __user *parent_tid = (void __user *)regs->rdx; + void __user *child_tid = (void __user *)regs->rdi; if (!newsp) - newsp = regs.rsp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - parent_tid, child_tid); + newsp = regs->rsp; + return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); +} + +asmlinkage long sys32_waitid(int which, compat_pid_t pid, + siginfo_t32 __user *uinfo, int options, + struct compat_rusage __user *uru) +{ + siginfo_t info; + struct rusage ru; + long ret; + mm_segment_t old_fs = get_fs(); + + info.si_signo = 0; + set_fs (KERNEL_DS); + ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options, + uru ? &ru : NULL); + set_fs (old_fs); + + if (ret < 0 || info.si_signo == 0) + return ret; + + if (uru && (ret = put_compat_rusage(&ru, uru))) + return ret; + + BUG_ON(info.si_code & __SI_MASK); + info.si_code |= __SI_CHLD; + return ia32_copy_siginfo_to_user(uinfo, &info); } /* @@ -1165,90 +1059,6 @@ long sys32_kill(int pid, int sig) return sys_kill(pid, sig); } - -long sys32_io_setup(unsigned nr_reqs, u32 __user *ctx32p) -{ - long ret; - aio_context_t ctx64; - mm_segment_t oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_io_setup(nr_reqs, &ctx64); - set_fs(oldfs); - /* truncating is ok because it's a user address */ - if (!ret) - ret = put_user((u32)ctx64, ctx32p); - return ret; -} - -asmlinkage long sys32_io_submit(aio_context_t ctx_id, int nr, - compat_uptr_t __user *iocbpp) -{ - struct kioctx *ctx; - long ret = 0; - int i; - - if (unlikely(nr < 0)) - return -EINVAL; - - if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp))))) - return -EFAULT; - - ctx = lookup_ioctx(ctx_id); - if (unlikely(!ctx)) { - pr_debug("EINVAL: io_submit: invalid context id\n"); - return -EINVAL; - } - - for (i=0; i= 0xffffffff || - !access_ok(VERIFY_WRITE, events, nr * sizeof(struct io_event))) - return -EFAULT; - if (timeout && get_compat_timespec(&t, timeout)) - return -EFAULT; - oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_io_getevents(ctx_id,min_nr,nr,events,timeout ? &t : NULL); - set_fs(oldfs); - if (!ret && timeout && put_compat_timespec(&t, timeout)) - return -EFAULT; - return ret; -} - asmlinkage long sys32_open(const char __user * filename, int flags, int mode) { char * tmp; @@ -1262,7 +1072,7 @@ asmlinkage long sys32_open(const char __user * filename, int flags, int mode) if (fd >= 0) { struct file *f = filp_open(tmp, flags, mode); error = PTR_ERR(f); - if (unlikely(IS_ERR(f))) { + if (IS_ERR(f)) { put_unused_fd(fd); fd = error; } else @@ -1316,26 +1126,20 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, long sys32_vm86_warning(void) { struct task_struct *me = current; - static char lastcomm[8]; - if (strcmp(lastcomm, me->comm)) { + static char lastcomm[sizeof(me->comm)]; + if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", me->comm); - strcpy(lastcomm, me->comm); + strncpy(lastcomm, me->comm, sizeof(lastcomm)); } return -ENOSYS; } -long sys32_quotactl(void) -{ - struct task_struct *me = current; - static char lastcomm[8]; - if (strcmp(lastcomm, me->comm)) { - printk(KERN_INFO "%s: 32bit quotactl not supported on 64 bit kernel\n", - me->comm); - strcpy(lastcomm, me->comm); - } - return -ENOSYS; -} +long sys32_lookup_dcookie(u32 addr_low, u32 addr_high, + char __user * buf, size_t len) +{ + return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); +} cond_syscall(sys32_ipc) diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c index 1806bff66..8d5762b59 100644 --- a/arch/x86_64/ia32/syscall32.c +++ b/arch/x86_64/ia32/syscall32.c @@ -28,18 +28,22 @@ extern unsigned char syscall32_sysenter[], syscall32_sysenter_end[]; extern int sysctl_vsyscall32; char *syscall32_page; -static int use_sysenter __initdata = -1; +static int use_sysenter = -1; -/* RED-PEN: This knows too much about high level VM */ -/* Alternative would be to generate a vma with appropriate backing options - and let it be handled by generic VM */ -int map_syscall32(struct mm_struct *mm, unsigned long address) +/* + * Map the 32bit vsyscall page on demand. + * + * RED-PEN: This knows too much about high level VM. + * + * Alternative would be to generate a vma with appropriate backing options + * and let it be handled by generic VM. + */ +int __map_syscall32(struct mm_struct *mm, unsigned long address) { pte_t *pte; pmd_t *pmd; int err = 0; - down_read(&mm->mmap_sem); spin_lock(&mm->page_table_lock); pmd = pmd_alloc(mm, pgd_offset(mm, address), address); if (pmd && (pte = pte_alloc_map(mm, pmd, address)) != NULL) { @@ -54,6 +58,14 @@ int map_syscall32(struct mm_struct *mm, unsigned long address) } else err = -ENOMEM; spin_unlock(&mm->page_table_lock); + return err; +} + +int map_syscall32(struct mm_struct *mm, unsigned long address) +{ + int err; + down_read(&mm->mmap_sem); + err = __map_syscall32(mm, address); up_read(&mm->mmap_sem); return err; } @@ -76,7 +88,8 @@ static int __init init_syscall32(void) __initcall(init_syscall32); -void __init syscall32_cpu_init(void) +/* May not be __init: called during resume */ +void syscall32_cpu_init(void) { if (use_sysenter < 0) use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL); diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index dc6f2695e..2c0f3af82 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -2,14 +2,14 @@ # Makefile for the linux kernel. # -extra-y := head.o head64.o init_task.o vmlinux.lds.s +extra-y := head.o head64.o init_task.o vmlinux.lds EXTRA_AFLAGS := -traditional obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ - ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ + ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bootflag.o e820.o reboot.o warmreboot.o -obj-y += mce.o + setup64.o bootflag.o e820.o reboot.o warmreboot.o quirks.o +obj-$(CONFIG_X86_MCE) += mce.o obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ obj-$(CONFIG_ACPI_BOOT) += acpi/ obj-$(CONFIG_X86_MSR) += msr.o @@ -17,7 +17,8 @@ obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ + genapic.o genapic_cluster.o genapic_flat.o obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ @@ -25,14 +26,17 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o obj-$(CONFIG_SWIOTLB) += swiotlb.o -obj-$(CONFIG_SCHED_SMT) += domain.o +obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_MODULES) += module.o obj-y += topology.o +obj-y += intel_cacheinfo.o bootflag-y += ../../i386/kernel/bootflag.o cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/mach-default/topology.o swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o +intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o +quirks-y += ../../i386/kernel/quirks.o diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 164b6d078..1d8b3912c 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -31,6 +31,8 @@ int iommu_aperture_allowed __initdata = 0; int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; +int fix_aperture __initdata = 1; + /* This code runs before the PCI subsystem is initialized, so just access the northbridge directly. */ @@ -202,7 +204,7 @@ void __init iommu_hole_init(void) u64 aper_base; int valid_agp = 0; - if (iommu_aperture_disabled) + if (iommu_aperture_disabled || !fix_aperture) return; printk("Checking aperture...\n"); @@ -241,20 +243,15 @@ void __init iommu_hole_init(void) /* Got the aperture from the AGP bridge */ } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) || force_iommu || - valid_agp || + valid_agp || fallback_aper_force) { - /* When there is a AGP bridge in the system assume the - user wants to use the AGP driver too and needs an - aperture. However this case (AGP but no good - aperture) should only happen with a more broken than - usual BIOS, because it would even break Windows. */ - - printk("Your BIOS doesn't leave a aperture memory hole\n"); - printk("Please enable the IOMMU option in the BIOS setup\n"); - printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); - + printk("Your BIOS doesn't leave a aperture memory hole\n"); + printk("Please enable the IOMMU option in the BIOS setup\n"); + printk("This costs you %d MB of RAM\n", + 32 << fallback_aper_order); + aper_order = fallback_aper_order; - aper_alloc = allocate_aperture(); + aper_alloc = allocate_aperture(); if (!aper_alloc) { /* Could disable AGP and IOMMU here, but it's probably not worth it. But the later users cannot deal with diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 6fb84e2c7..cd37a0aa6 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -32,6 +32,9 @@ #include #include #include +#include + +int apic_verbosity; int disable_apic_timer __initdata; @@ -123,7 +126,7 @@ void __init connect_bsp_APIC(void) * PIC mode, enable APIC mode in the IMCR, i.e. * connect BSP's local APIC to INT and NMI lines. */ - printk(KERN_INFO "leaving PIC mode, enabling APIC mode.\n"); + apic_printk(APIC_VERBOSE, "leaving PIC mode, enabling APIC mode.\n"); outb(0x70, 0x22); outb(0x01, 0x23); } @@ -138,7 +141,7 @@ void disconnect_bsp_APIC(void) * interrupts, including IPIs, won't work beyond * this point! The only exception are INIT IPIs. */ - printk(KERN_INFO "disabling APIC mode, entering PIC mode.\n"); + apic_printk(APIC_QUIET, "disabling APIC mode, entering PIC mode.\n"); outb(0x70, 0x22); outb(0x00, 0x23); } @@ -172,10 +175,10 @@ int __init verify_local_APIC(void) * The version register is read-only in a real APIC. */ reg0 = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg0); + apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0); apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); reg1 = apic_read(APIC_LVR); - Dprintk("Getting VERSION: %x\n", reg1); + apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1); /* * The two version reads above should print the same @@ -199,10 +202,10 @@ int __init verify_local_APIC(void) * The ID register is read/write in a real APIC. */ reg0 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg0); + apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0); apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); reg1 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg1); + apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1); apic_write(APIC_ID, reg0); if (reg1 != (reg0 ^ APIC_ID_MASK)) return 0; @@ -213,9 +216,9 @@ int __init verify_local_APIC(void) * compatibility mode, but most boxes are anymore. */ reg0 = apic_read(APIC_LVT0); - Dprintk("Getting LVT0: %x\n", reg0); + apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0); reg1 = apic_read(APIC_LVT1); - Dprintk("Getting LVT1: %x\n", reg1); + apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1); return 1; } @@ -227,7 +230,7 @@ void __init sync_Arb_IDs(void) */ apic_wait_icr_idle(); - Dprintk("Synchronizing Arb IDs.\n"); + apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n"); apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT); } @@ -298,8 +301,7 @@ void __init setup_local_APIC (void) * Double-check whether this APIC is really registered. * This is meaningless in clustered apic mode, so we skip it. */ - if (!clustered_apic_mode && - !physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map)) + if (!apic_id_registered()) BUG(); /* @@ -307,23 +309,7 @@ void __init setup_local_APIC (void) * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ - - if (!clustered_apic_mode) { - /* - * In clustered apic mode, the firmware does this for us - * Put the APIC into flat delivery mode. - * Must be "all ones" explicitly for 82489DX. - */ - apic_write_around(APIC_DFR, 0xffffffff); - - /* - * Set up the logical destination ID. - */ - value = apic_read(APIC_LDR); - value &= ~APIC_LDR_MASK; - value |= (1<<(smp_processor_id()+24)); - apic_write_around(APIC_LDR, value); - } + init_apic_ldr(); /* * Set Task Priority to 'accept all'. We never change this @@ -388,10 +374,10 @@ void __init setup_local_APIC (void) value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; if (!smp_processor_id() && (pic_mode || !value)) { value = APIC_DM_EXTINT; - Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id()); + apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id()); } else { value = APIC_DM_EXTINT | APIC_LVT_MASKED; - Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id()); + apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id()); } apic_write_around(APIC_LVT0, value); @@ -407,12 +393,11 @@ void __init setup_local_APIC (void) apic_write_around(APIC_LVT1, value); if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */ + unsigned oldvalue; maxlvt = get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - Dprintk("ESR value before enabling vector: %08x\n", value); - + oldvalue = apic_read(APIC_ESR); value = ERROR_APIC_VECTOR; // enables sending errors apic_write_around(APIC_LVTERR, value); /* @@ -421,7 +406,10 @@ void __init setup_local_APIC (void) if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - Dprintk("ESR value after enabling vector: %08x\n", value); + if (value != oldvalue) + apic_printk(APIC_VERBOSE, + "ESR value after enabling vector: %08x, after %08x\n", + oldvalue, value); } else { if (esr_disable) /* @@ -430,9 +418,9 @@ void __init setup_local_APIC (void) * ESR disabled - we can't do anything useful with the * errors anyway - mbligh */ - printk("Leaving ESR disabled.\n"); + apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n"); else - printk("No ESR for 82489DX.\n"); + apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n"); } nmi_watchdog_default(); @@ -564,6 +552,21 @@ static void apic_pm_activate(void) { } #endif /* CONFIG_PM */ +static int __init apic_set_verbosity(char *str) +{ + if (strcmp("debug", str) == 0) + apic_verbosity = APIC_DEBUG; + else if (strcmp("verbose", str) == 0) + apic_verbosity = APIC_VERBOSE; + else + printk(KERN_WARNING "APIC Verbosity level %s not recognised" + " use apic=verbose or apic=debug", str); + + return 0; +} + +__setup("apic=", apic_set_verbosity); + /* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. @@ -599,7 +602,7 @@ void __init init_apic_mappings(void) apic_phys = mp_lapic_addr; set_fixmap_nocache(FIX_APIC_BASE, apic_phys); - Dprintk("mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); + apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); /* * Fetch the APIC ID of the BSP in case we have a @@ -621,7 +624,7 @@ void __init init_apic_mappings(void) ioapic_phys = __pa(ioapic_phys); } set_fixmap_nocache(idx, ioapic_phys); - Dprintk("mapped IOAPIC to %016lx (%016lx)\n", + apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n", __fix_to_virt(idx), ioapic_phys); idx++; } @@ -836,8 +839,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); - x86_do_profile(regs); - + profile_tick(CPU_PROFILING, regs); if (--per_cpu(prof_counter, cpu) <= 0) { /* * The multiplier may have changed since the last time we got @@ -903,6 +905,54 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) irq_exit(); } +/* + * oem_force_hpet_timer -- force HPET mode for some boxes. + * + * Thus far, the major user of this is IBM's Summit2 series: + * + * Clustered boxes may have unsynced TSC problems if they are + * multi-chassis. Use available data to take a good guess. + * If in doubt, go HPET. + */ +__init int oem_force_hpet_timer(void) +{ + int i, clusters, zeros; + unsigned id; + DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); + + bitmap_empty(clustermap, NUM_APIC_CLUSTERS); + + for (i = 0; i < NR_CPUS; i++) { + id = bios_cpu_apicid[i]; + if (id != BAD_APICID) + __set_bit(APIC_CLUSTERID(id), clustermap); + } + + /* Problem: Partially populated chassis may not have CPUs in some of + * the APIC clusters they have been allocated. Only present CPUs have + * bios_cpu_apicid entries, thus causing zeroes in the bitmap. Since + * clusters are allocated sequentially, count zeros only if they are + * bounded by ones. + */ + clusters = 0; + zeros = 0; + for (i = 0; i < NUM_APIC_CLUSTERS; i++) { + if (test_bit(i, clustermap)) { + clusters += 1 + zeros; + zeros = 0; + } else + ++zeros; + } + + /* + * If clusters > 2, then should be multi-chassis. Return 1 for HPET. + * Else return 0 to use TSC. + * May have to revisit this when multi-core + hyperthreaded CPUs come + * out, but AFAIK this will work even for them. + */ + return (clusters > 2); +} + /* * This interrupt should _never_ happen with our APIC/SMP architecture */ @@ -962,7 +1012,7 @@ asmlinkage void smp_error_interrupt(void) 6: Received illegal vector 7: Illegal register address */ - printk (KERN_INFO "APIC error on CPU%d: %02x(%02x)\n", + printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n", smp_processor_id(), v , v1); irq_exit(); } diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index 757f55078..37d12fa5e 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -7,8 +7,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig index 1b3aefc8d..acaf62aa5 100644 --- a/arch/x86_64/kernel/cpufreq/Kconfig +++ b/arch/x86_64/kernel/cpufreq/Kconfig @@ -4,18 +4,6 @@ menu "CPU Frequency scaling" -config CPU_FREQ - bool "CPU Frequency scaling" - help - Clock scaling allows you to change the clock speed of CPUs on the - fly. This is a nice method to save battery power on notebooks, - because the lower the clock speed, the less power the CPU consumes. - - For more information, take a look at - or at - - If in doubt, say N. - source "drivers/cpufreq/Kconfig" config CPU_FREQ_TABLE @@ -41,4 +29,76 @@ config X86_POWERNOW_K8 If in doubt, say N. +config X86_POWERNOW_K8_ACPI + bool + depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y")) + default y + +config X86_SPEEDSTEP_CENTRINO + tristate "Intel Enhanced SpeedStep" + depends on CPU_FREQ_TABLE && ACPI_PROCESSOR + help + This adds the CPUFreq driver for Enhanced SpeedStep enabled + mobile CPUs. This means Intel Pentium M (Centrino) CPUs + or 64bit enabled Intel Xeons. + + For details, take a look at . + + If in doubt, say N. + +config X86_SPEEDSTEP_CENTRINO_ACPI + bool + depends on X86_SPEEDSTEP_CENTRINO + default y + +config X86_ACPI_CPUFREQ + tristate "ACPI Processor P-States driver" + depends on CPU_FREQ_TABLE && ACPI_PROCESSOR + help + This driver adds a CPUFreq driver which utilizes the ACPI + Processor Performance States. + + For details, take a look at . + + If in doubt, say N. + +comment "shared options" + depends on CPU_FREQ + +config X86_ACPI_CPUFREQ_PROC_INTF + bool "/proc/acpi/processor/../performance interface (deprecated)" + depends on PROC_FS + depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI + help + This enables the deprecated /proc/acpi/processor/../performance + interface. While it is helpful for debugging, the generic, + cross-architecture cpufreq interfaces should be used. + + If in doubt, say N. + +config X86_P4_CLOCKMOD + tristate "Intel Pentium 4 clock modulation" + depends on CPU_FREQ_TABLE && EMBEDDED + help + This adds the clock modulation driver for Intel Pentium 4 / XEON + processors. When enabled it will lower CPU temperature by skipping + clocks. + + This driver should be only used in exceptional + circumstances when very low power is needed because it causes severe + slowdowns and noticeable latencies. Normally Speedstep should be used + instead. + + For details, take a look at . + + Unless you are absolutely sure say N. + + +config X86_SPEEDSTEP_LIB + tristate + depends on (X86_P4_CLOCKMOD) + default (X86_P4_CLOCKMOD) + + endmenu + diff --git a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile index f02ed52be..d8b593879 100644 --- a/arch/x86_64/kernel/cpufreq/Makefile +++ b/arch/x86_64/kernel/cpufreq/Makefile @@ -2,6 +2,16 @@ # Reuse the i386 cpufreq drivers # +SRCDIR := ../../../i386/kernel/cpu/cpufreq + obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o +obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o +obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o -powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o +powernow-k8-objs := ${SRCDIR}/powernow-k8.o +speedstep-centrino-objs := ${SRCDIR}/speedstep-centrino.o +acpi-cpufreq-objs := ${SRCDIR}/acpi-cpufreq.o +p4-clockmod-objs := ${SRCDIR}/p4-clockmod.o +speedstep-lib-objs := ${SRCDIR}/speedstep-lib.o diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index 98041f50e..5ed9bd2cd 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c @@ -8,9 +8,9 @@ /* Simple VGA output */ #ifdef __i386__ -#define VGABASE __pa(__PAGE_OFFSET + 0xb8000UL) +#define VGABASE (__ISA_IO_base + 0xb8000) #else -#define VGABASE 0xffffffff800b8000UL +#define VGABASE ((void *)0xffffffff800b8000UL) #endif #define MAX_YPOS 25 @@ -99,18 +99,17 @@ static void early_serial_write(struct console *con, const char *s, unsigned n) #define DEFAULT_BAUD 9600 -static __init void early_serial_init(char *opt) +static __init void early_serial_init(char *s) { unsigned char c; unsigned divisor; unsigned baud = DEFAULT_BAUD; - char *s, *e; + char *e; - if (*opt == ',') - ++opt; + if (*s == ',') + ++s; - s = strsep(&opt, ","); - if (s != NULL) { + if (*s) { unsigned port; if (!strncmp(s,"0x",2)) { early_serial_base = simple_strtoul(s, &e, 16); @@ -124,6 +123,9 @@ static __init void early_serial_init(char *opt) port = 0; early_serial_base = bases[port]; } + s += strcspn(s, ","); + if (*s == ',') + s++; } outb(0x3, early_serial_base + LCR); /* 8n1 */ @@ -131,8 +133,7 @@ static __init void early_serial_init(char *opt) outb(0, early_serial_base + FCR); /* no fifo */ outb(0x3, early_serial_base + MCR); /* DTR + RTS */ - s = strsep(&opt, ","); - if (s != NULL) { + if (*s) { baud = simple_strtoul(s, &e, 0); if (baud == 0 || s == e) baud = DEFAULT_BAUD; diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 89f74f738..d8d906a7d 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -297,7 +297,7 @@ int_very_careful: sti SAVE_REST /* Check for syscall exit trace */ - testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),%edx + testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx jz int_signal pushq %rdi leaq 8(%rsp),%rdi # &ptregs -> arg1 @@ -305,6 +305,7 @@ int_very_careful: popq %rdi btr $TIF_SYSCALL_TRACE,%edi btr $TIF_SYSCALL_AUDIT,%edi + btr $TIF_SINGLESTEP,%edi jmp int_restore_rest int_signal: @@ -323,19 +324,20 @@ int_restore_rest: * Certain special system calls that need to save a complete full stack frame. */ - .macro PTREGSCALL label,func + .macro PTREGSCALL label,func,arg .globl \label \label: leaq \func(%rip),%rax + leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ jmp ptregscall_common .endm - PTREGSCALL stub_clone, sys_clone - PTREGSCALL stub_fork, sys_fork - PTREGSCALL stub_vfork, sys_vfork - PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend - PTREGSCALL stub_sigaltstack, sys_sigaltstack - PTREGSCALL stub_iopl, sys_iopl + PTREGSCALL stub_clone, sys_clone, %r8 + PTREGSCALL stub_fork, sys_fork, %rdi + PTREGSCALL stub_vfork, sys_vfork, %rdi + PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx + PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx + PTREGSCALL stub_iopl, sys_iopl, %rsi ENTRY(ptregscall_common) CFI_STARTPROC @@ -385,6 +387,7 @@ ENTRY(stub_rt_sigreturn) CFI_STARTPROC addq $8, %rsp SAVE_REST + movq %rsp,%rdi FIXUP_TOP_OF_STACK %r11 call sys_rt_sigreturn movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer @@ -904,6 +907,7 @@ ENTRY(divide_error) ENTRY(spurious_interrupt_bug) zeroentry do_spurious_interrupt_bug +#ifdef CONFIG_X86_MCE /* runs on exception stack */ ENTRY(machine_check) CFI_STARTPROC @@ -912,6 +916,7 @@ ENTRY(machine_check) paranoidentry do_machine_check jmp paranoid_exit CFI_ENDPROC +#endif ENTRY(call_debug) zeroentry do_call_debug diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 23a2b5e02..a66143f77 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -176,6 +176,18 @@ initial_code: init_rsp: .quad init_thread_union+THREAD_SIZE-8 +ENTRY(early_idt_handler) + xorl %eax,%eax + movq 8(%rsp),%rsi # get rip + movq (%rsp),%rdx + movq %cr2,%rcx + leaq early_idt_msg(%rip),%rdi + call early_printk +1: hlt + jmp 1b + +early_idt_msg: + .asciz "PANIC: early exception rip %lx error %lx cr2 %lx\n" .code32 ENTRY(no_long_mode) diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index 127a67880..5254e90a8 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -11,12 +11,14 @@ #include #include #include +#include #include #include #include #include #include +#include /* Don't add a printk in there. printk relies on the PDA which is not initialized yet. */ @@ -79,7 +81,11 @@ extern char _end[]; void __init x86_64_start_kernel(char * real_mode_data) { char *s; + int i; + for (i = 0; i < 256; i++) + set_intr_gate(i, early_idt_handler); + asm volatile("lidt %0" :: "m" (idt_descr)); clear_bss(); pda_init(0); copy_bootdata(real_mode_data); diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index c52b859c9..7929a2e53 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -329,7 +329,7 @@ spurious_8259A_irq: * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", irq); + printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } atomic_inc(&irq_err_count); @@ -342,7 +342,7 @@ spurious_8259A_irq: } } -void __init init_8259A(int auto_eoi) +void init_8259A(int auto_eoi) { unsigned long flags; @@ -385,6 +385,57 @@ void __init init_8259A(int auto_eoi) spin_unlock_irqrestore(&i8259A_lock, flags); } +static char irq_trigger[2]; +/** + * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ + */ +static void restore_ELCR(char *trigger) +{ + outb(trigger[0], 0x4d0); + outb(trigger[1], 0x4d1); +} + +static void save_ELCR(char *trigger) +{ + /* IRQ 0,1,2,8,13 are marked as reserved */ + trigger[0] = inb(0x4d0) & 0xF8; + trigger[1] = inb(0x4d1) & 0xDE; +} + +static int i8259A_resume(struct sys_device *dev) +{ + init_8259A(0); + restore_ELCR(irq_trigger); + return 0; +} + +static int i8259A_suspend(struct sys_device *dev, u32 state) +{ + save_ELCR(irq_trigger); + return 0; +} + +static struct sysdev_class i8259_sysdev_class = { + set_kset_name("i8259"), + .suspend = i8259A_suspend, + .resume = i8259A_resume, +}; + +static struct sys_device device_i8259A = { + .id = 0, + .cls = &i8259_sysdev_class, +}; + +static int __init i8259A_init_sysfs(void) +{ + int error = sysdev_class_register(&i8259_sysdev_class); + if (!error) + error = sysdev_register(&device_i8259A); + return error; +} + +device_initcall(i8259A_init_sysfs); + /* * IRQ2 is cascade interrupt to second interrupt controller */ diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c index 33185ca33..8bc4becb8 100644 --- a/arch/x86_64/kernel/init_task.c +++ b/arch/x86_64/kernel/init_task.c @@ -44,8 +44,7 @@ EXPORT_SYMBOL(init_task); * section. Since TSS's are completely CPU-local, we want them * on exact cacheline boundaries, to eliminate cacheline ping-pong. */ -struct tss_struct init_tss[NR_CPUS] __cacheline_aligned; - +DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp; #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 6cb45b7eb..c22a8f045 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -30,17 +30,17 @@ #include #include #include +#include #include #include #include #include +#include -int sis_apic_bug; /* not actually supported, dummy for compile */ - -#undef APIC_LOCKUP_DEBUG +#define __apicdebuginit __init -#define APIC_LOCKUP_DEBUG +int sis_apic_bug; /* not actually supported, dummy for compile */ static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; @@ -80,7 +80,7 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static void __init add_pin_to_irq(unsigned int irq, int apic, int pin) +static void add_pin_to_irq(unsigned int irq, int apic, int pin) { static int first_free_entry = NR_IRQS; struct irq_pin_list *entry = irq_2_pin + irq; @@ -128,10 +128,6 @@ DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) /* mask = 1 */ DO_ACTION( __unmask, 0, &= 0xfffeffff, ) /* mask = 0 */ -DO_ACTION( __mask_and_edge, 0, = (reg & 0xffff7fff) | 0x00010000, ) - /* mask = 1, trigger = 0 */ -DO_ACTION( __unmask_and_level, 0, = (reg & 0xfffeffff) | 0x00008000, ) - /* mask = 0, trigger = 1 */ static void mask_IO_APIC_irq (unsigned int irq) { @@ -262,12 +258,14 @@ void __init check_ioapic(void) #endif return; case PCI_VENDOR_ID_NVIDIA: -#ifndef CONFIG_SMP +#ifdef CONFIG_ACPI + /* All timer overrides on Nvidia + seem to be wrong. Skip them. */ + acpi_skip_timer_override = 1; printk(KERN_INFO - "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", - num,slot,vendor); - skip_ioapic_setup = 1; + "Nvidia board detected. Ignoring ACPI timer override.\n"); #endif + /* RED-PEN skip them on mptables too? */ return; } @@ -292,13 +290,13 @@ static int __init ioapic_pirq_setup(char *str) pirq_entries[i] = -1; pirqs_enabled = 1; - printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n"); + apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n"); max = MAX_PIRQS; if (ints[0] < MAX_PIRQS) max = ints[0]; for (i = 0; i < max; i++) { - printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); + apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); /* * PIRQs are mapped upside down, usually. */ @@ -312,7 +310,7 @@ __setup("pirq=", ioapic_pirq_setup); /* * Find the IRQ entry number of a certain pin. */ -static int __init find_irq_entry(int apic, int pin, int type) +static int find_irq_entry(int apic, int pin, int type) { int i; @@ -357,10 +355,10 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) { int apic, i, best_guess = -1; - Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", + apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", bus, slot, pin); if (mp_bus_id_to_pci_bus[bus] == -1) { - printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); + apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus); return -1; } for (i = 0; i < mp_irq_entries; i++) { @@ -396,13 +394,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) /* * EISA Edge/Level control register, ELCR */ -static int __init EISA_ELCR(unsigned int irq) +static int EISA_ELCR(unsigned int irq) { if (irq < 16) { unsigned int port = 0x4d0 + (irq >> 3); return (inb(port) >> (irq & 7)) & 1; } - printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq); + apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq); return 0; } @@ -501,7 +499,7 @@ static int __init MPBIOS_polarity(int idx) return polarity; } -static int __init MPBIOS_trigger(int idx) +static int MPBIOS_trigger(int idx) { int bus = mp_irqs[idx].mpc_srcbus; int trigger; @@ -625,10 +623,10 @@ static int pin_2_irq(int idx, int apic, int pin) if ((pin >= 16) && (pin <= 23)) { if (pirq_entries[pin-16] != -1) { if (!pirq_entries[pin-16]) { - printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16); + apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16); } else { irq = pirq_entries[pin-16]; - printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n", + apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n", pin-16, irq); } } @@ -656,11 +654,7 @@ static inline int IO_APIC_irq_trigger(int irq) /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; -#ifdef CONFIG_PCI_MSI int assign_irq_vector(int irq) -#else -int __init assign_irq_vector(int irq) -#endif { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; @@ -719,7 +713,7 @@ void __init setup_IO_APIC_irqs(void) int apic, pin, idx, irq, first_notcon = 1, vector; unsigned long flags; - printk(KERN_DEBUG "init IO_APIC IRQs\n"); + apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); for (apic = 0; apic < nr_ioapics; apic++) { for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { @@ -729,18 +723,18 @@ void __init setup_IO_APIC_irqs(void) */ memset(&entry,0,sizeof(entry)); - entry.delivery_mode = dest_LowestPrio; - entry.dest_mode = INT_DELIVERY_MODE; + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; entry.mask = 0; /* enable IRQ */ - entry.dest.logical.logical_dest = TARGET_CPUS; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { if (first_notcon) { - printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); + apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); first_notcon = 0; } else - printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin); + apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin); continue; } @@ -750,7 +744,7 @@ void __init setup_IO_APIC_irqs(void) if (irq_trigger(idx)) { entry.trigger = 1; entry.mask = 1; - entry.dest.logical.logical_dest = TARGET_CPUS; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); } irq = pin_2_irq(idx, apic, pin); @@ -775,7 +769,7 @@ void __init setup_IO_APIC_irqs(void) } if (!first_notcon) - printk(" not connected.\n"); + apic_printk(APIC_VERBOSE," not connected.\n"); } /* @@ -798,10 +792,10 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) * We use logical delivery to get the timer IRQ * to the first CPU. */ - entry.dest_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; entry.mask = 0; /* unmask IRQ now */ - entry.dest.logical.logical_dest = TARGET_CPUS; - entry.delivery_mode = dest_LowestPrio; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); + entry.delivery_mode = INT_DELIVERY_MODE; entry.polarity = 0; entry.trigger = 0; entry.vector = vector; @@ -825,13 +819,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) void __init UNEXPECTED_IO_APIC(void) { -#if 0 - printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n"); - printk(KERN_WARNING " to linux-smp@vger.kernel.org\n"); -#endif } -void __init print_IO_APIC(void) +void __apicdebuginit print_IO_APIC(void) { int apic, i; union IO_APIC_reg_00 reg_00; @@ -839,7 +829,10 @@ void __init print_IO_APIC(void) union IO_APIC_reg_02 reg_02; unsigned long flags; - printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); + if (apic_verbosity == APIC_QUIET) + return; + + printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); for (i = 0; i < nr_ioapics; i++) printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]); @@ -955,11 +948,14 @@ void __init print_IO_APIC(void) return; } -static void print_APIC_bitfield (int base) +static __apicdebuginit void print_APIC_bitfield (int base) { unsigned int v; int i, j; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); for (i = 0; i < 8; i++) { v = apic_read(base + i*0x10); @@ -973,10 +969,13 @@ static void print_APIC_bitfield (int base) } } -void /*__init*/ print_local_APIC(void * dummy) +void __apicdebuginit print_local_APIC(void * dummy) { unsigned int v, ver, maxlvt; + if (apic_verbosity == APIC_QUIET) + return; + printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", smp_processor_id(), hard_smp_processor_id()); v = apic_read(APIC_ID); @@ -1058,12 +1057,15 @@ void print_all_local_APICs (void) on_each_cpu(print_local_APIC, NULL, 1, 1); } -void /*__init*/ print_PIC(void) +void __apicdebuginit print_PIC(void) { extern spinlock_t i8259A_lock; unsigned int v; unsigned long flags; + if (apic_verbosity == APIC_QUIET) + return; + printk(KERN_DEBUG "\nprinting PIC contents\n"); spin_lock_irqsave(&i8259A_lock, flags); @@ -1141,7 +1143,6 @@ void disable_IO_APIC(void) static void __init setup_ioapic_ids_from_mpc (void) { union IO_APIC_reg_00 reg_00; - physid_mask_t phys_id_present_map = phys_cpu_present_map; int apic; int i; unsigned char old_id; @@ -1160,35 +1161,14 @@ static void __init setup_ioapic_ids_from_mpc (void) old_id = mp_ioapics[apic].mpc_apicid; if (mp_ioapics[apic].mpc_apicid >= 0xf) { - printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", + apic_printk(APIC_QUIET,KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); - printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", + apic_printk(APIC_QUIET,KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", reg_00.bits.ID); mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; } - /* - * Sanity check, is the ID really free? Every APIC in a - * system must have a unique ID or we get lots of nice - * 'stuck on smp_invalidate_needed IPI wait' messages. - */ - if (physid_isset(mp_ioapics[apic].mpc_apicid, phys_id_present_map)) { - printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", - apic, mp_ioapics[apic].mpc_apicid); - for (i = 0; i < 0xf; i++) - if (!physid_isset(i, phys_id_present_map)) - break; - if (i >= 0xf) - panic("Max APIC ID exceeded!\n"); - printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - i); - physid_set(i, phys_id_present_map); - mp_ioapics[apic].mpc_apicid = i; - } else { - printk(KERN_INFO - "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid); - physid_set(mp_ioapics[apic].mpc_apicid, phys_id_present_map); - } + printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid); /* @@ -1205,7 +1185,7 @@ static void __init setup_ioapic_ids_from_mpc (void) * Read the right value from the MPC table and * write it into the ID register. */ - printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", + apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", mp_ioapics[apic].mpc_apicid); reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; @@ -1220,9 +1200,9 @@ static void __init setup_ioapic_ids_from_mpc (void) reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); + printk("could not set ID!\n"); else - printk(" ok.\n"); + apic_printk(APIC_VERBOSE," ok.\n"); } } @@ -1332,61 +1312,7 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq) static void end_level_ioapic_irq (unsigned int irq) { - unsigned long v; - int i; - -/* - * It appears there is an erratum which affects at least version 0x11 - * of I/O APIC (that's the 82093AA and cores integrated into various - * chipsets). Under certain conditions a level-triggered interrupt is - * erroneously delivered as edge-triggered one but the respective IRR - * bit gets set nevertheless. As a result the I/O unit expects an EOI - * message but it will never arrive and further interrupts are blocked - * from the source. The exact reason is so far unknown, but the - * phenomenon was observed when two consecutive interrupt requests - * from a given source get delivered to the same CPU and the source is - * temporarily disabled in between. - * - * A workaround is to simulate an EOI message manually. We achieve it - * by setting the trigger mode to edge and then to level when the edge - * trigger mode gets detected in the TMR of a local APIC for a - * level-triggered interrupt. We mask the source for the time of the - * operation to prevent an edge-triggered interrupt escaping meanwhile. - * The idea is from Manfred Spraul. --macro - */ - i = IO_APIC_VECTOR(irq); - v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); - ack_APIC_irq(); - - if (!(v & (1 << (i & 0x1f)))) { -#ifdef APIC_LOCKUP_DEBUG - struct irq_pin_list *entry; -#endif - -#ifdef APIC_MISMATCH_DEBUG - atomic_inc(&irq_mis_count); -#endif - spin_lock(&ioapic_lock); - __mask_and_edge_IO_APIC_irq(irq); -#ifdef APIC_LOCKUP_DEBUG - for (entry = irq_2_pin + irq;;) { - unsigned int reg; - - if (entry->pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2); - if (reg & 0x00004000) - printk(KERN_CRIT "Aieee!!! Remote IRR" - " still set after unlock!\n"); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } -#endif - __unmask_and_level_IO_APIC_irq(irq); - spin_unlock(&ioapic_lock); - } } static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) @@ -1397,9 +1323,9 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) dest = cpu_mask_to_apicid(mask); /* - * Only the first 8 bits are valid. + * Only the high 8 bits are valid. */ - dest = dest << 24; + dest = SET_APIC_LOGICAL_ID(dest); spin_lock_irqsave(&ioapic_lock, flags); __DO_ACTION(1, = dest, ) @@ -1671,7 +1597,7 @@ static inline void check_timer(void) pin1 = find_isa_irq_pin(0, mp_INT); pin2 = find_isa_irq_pin(0, mp_ExtINT); - printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); + apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2); if (pin1 != -1) { /* @@ -1689,12 +1615,12 @@ static inline void check_timer(void) return; } clear_IO_APIC_pin(0, pin1); - printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); + apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); } - printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); + apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); if (pin2 != -1) { - printk("\n..... (found pin %d) ...", pin2); + apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2); /* * legacy devices should be connected to IO APIC #0 */ @@ -1720,7 +1646,7 @@ static inline void check_timer(void) nmi_watchdog = 0; } - printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); + apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); disable_8259A_irq(0); irq_desc[0].handler = &lapic_irq_type; @@ -1728,13 +1654,13 @@ static inline void check_timer(void) enable_8259A_irq(0); if (timer_irq_works()) { - printk(" works.\n"); + apic_printk(APIC_QUIET, " works.\n"); return; } apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); - printk(" failed.\n"); + apic_printk(APIC_VERBOSE," failed.\n"); - printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); + apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ..."); init_8259A(0); make_8259A_irq(0); @@ -1743,10 +1669,10 @@ static inline void check_timer(void) unlock_ExtINT_logic(); if (timer_irq_works()) { - printk(" works.\n"); + apic_printk(APIC_VERBOSE," works.\n"); return; } - printk(" failed :(.\n"); + apic_printk(APIC_VERBOSE," failed :(.\n"); panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); } @@ -1768,7 +1694,7 @@ void __init setup_IO_APIC(void) else io_apic_irqs = ~PIC_IRQS; - printk("ENABLING IO-APIC IRQs\n"); + apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); /* * Set up the IO-APIC IRQ routing table. @@ -1783,13 +1709,105 @@ void __init setup_IO_APIC(void) print_IO_APIC(); } +struct sysfs_ioapic_data { + struct sys_device dev; + struct IO_APIC_route_entry entry[0]; +}; +static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS]; + +static int ioapic_suspend(struct sys_device *dev, u32 state) +{ + struct IO_APIC_route_entry *entry; + struct sysfs_ioapic_data *data; + unsigned long flags; + int i; + + data = container_of(dev, struct sysfs_ioapic_data, dev); + entry = data->entry; + spin_lock_irqsave(&ioapic_lock, flags); + for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { + *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i); + *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i); + } + spin_unlock_irqrestore(&ioapic_lock, flags); + + return 0; +} + +static int ioapic_resume(struct sys_device *dev) +{ + struct IO_APIC_route_entry *entry; + struct sysfs_ioapic_data *data; + unsigned long flags; + union IO_APIC_reg_00 reg_00; + int i; + + data = container_of(dev, struct sysfs_ioapic_data, dev); + entry = data->entry; + + spin_lock_irqsave(&ioapic_lock, flags); + reg_00.raw = io_apic_read(dev->id, 0); + if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) { + reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; + io_apic_write(dev->id, 0, reg_00.raw); + } + for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { + io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1)); + io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0)); + } + spin_unlock_irqrestore(&ioapic_lock, flags); + + return 0; +} + +static struct sysdev_class ioapic_sysdev_class = { + set_kset_name("ioapic"), + .suspend = ioapic_suspend, + .resume = ioapic_resume, +}; + +static int __init ioapic_init_sysfs(void) +{ + struct sys_device * dev; + int i, size, error = 0; + + error = sysdev_class_register(&ioapic_sysdev_class); + if (error) + return error; + + for (i = 0; i < nr_ioapics; i++ ) { + size = sizeof(struct sys_device) + nr_ioapic_registers[i] + * sizeof(struct IO_APIC_route_entry); + mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL); + if (!mp_ioapic_data[i]) { + printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); + continue; + } + memset(mp_ioapic_data[i], 0, size); + dev = &mp_ioapic_data[i]->dev; + dev->id = i; + dev->cls = &ioapic_sysdev_class; + error = sysdev_register(dev); + if (error) { + kfree(mp_ioapic_data[i]); + mp_ioapic_data[i] = NULL; + printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); + continue; + } + } + + return 0; +} + +device_initcall(ioapic_init_sysfs); + /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration -------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_BOOT -#define IO_APIC_MAX_ID 15 +#define IO_APIC_MAX_ID 0xFE int __init io_apic_get_unique_id (int ioapic, int apic_id) { @@ -1815,7 +1833,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) spin_unlock_irqrestore(&ioapic_lock, flags); if (apic_id >= IO_APIC_MAX_ID) { - printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " + apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " "%d\n", ioapic, apic_id, reg_00.bits.ID); apic_id = reg_00.bits.ID; } @@ -1834,7 +1852,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) if (i == IO_APIC_MAX_ID) panic("Max apic_id exceeded!\n"); - printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " + apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " "trying %d\n", ioapic, apic_id, i); apic_id = i; @@ -1855,7 +1873,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); } - printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); + apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); return apic_id; } @@ -1893,7 +1911,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a unsigned long flags; if (!IO_APIC_IRQ(irq)) { - printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", + apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", ioapic); return -EINVAL; } @@ -1906,9 +1924,9 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a memset(&entry,0,sizeof(entry)); - entry.delivery_mode = dest_LowestPrio; - entry.dest_mode = INT_DELIVERY_MODE; - entry.dest.logical.logical_dest = TARGET_CPUS; + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); entry.trigger = edge_level; entry.polarity = active_high_low; entry.mask = 1; /* Disabled (masked) */ @@ -1921,20 +1939,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a entry.vector = assign_irq_vector(irq); - printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " + apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> " "IRQ %d Mode:%i Active:%i)\n", ioapic, mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); - if (use_pci_vector() && !platform_legacy_irq(irq)) - irq = IO_APIC_VECTOR(irq); - if (edge_level) { - irq_desc[irq].handler = &ioapic_level_type; - } else { - irq_desc[irq].handler = &ioapic_edge_type; - } - - set_intr_gate(entry.vector, interrupt[irq]); + ioapic_register_intr(irq, entry.vector, edge_level); if (!ioapic && (irq < 16)) disable_8259A_irq(irq); @@ -1949,20 +1959,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a #endif /*CONFIG_ACPI_BOOT*/ -#ifndef CONFIG_SMP -void send_IPI_self(int vector) + +/* + * This function currently is only a helper for the i386 smp boot process where + * we need to reprogram the ioredtbls to cater for the cpus which have come online + * so mask in all cases should simply be TARGET_CPUS + */ +void __init setup_ioapic_dest(void) { - unsigned int cfg; + int pin, ioapic, irq, irq_entry; - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + if (skip_ioapic_setup == 1) + return; - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); + for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { + for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { + irq_entry = find_irq_entry(ioapic, pin, mp_INT); + if (irq_entry == -1) + continue; + irq = pin_2_irq(irq_entry, ioapic, pin); + set_ioapic_affinity_irq(irq, TARGET_CPUS); + } + + } } -#endif diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c index 0a90fd08f..cde0e868e 100644 --- a/arch/x86_64/kernel/ioport.c +++ b/arch/x86_64/kernel/ioport.c @@ -28,12 +28,12 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex clear_bit(i, bitmap); } - /* * this changes the io permissions bitmap in the current task. */ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) { + unsigned int i, max_long, bytes, bytes_updated; struct thread_struct * t = ¤t->thread; struct tss_struct * tss; unsigned long *bitmap; @@ -59,16 +59,34 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) /* * do it in the per-thread copy and in the TSS ... + * + * Disable preemption via get_cpu() - we must not switch away + * because the ->io_bitmap_max value must match the bitmap + * contents: */ + tss = &per_cpu(init_tss, get_cpu()); + set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); - tss = init_tss + get_cpu(); - if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */ - set_bitmap(tss->io_bitmap, from, num, !turn_on); - } else { - memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES); - tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */ - } + + /* + * Search for a (possibly new) maximum. This is simple and stupid, + * to keep it obviously correct: + */ + max_long = 0; + for (i = 0; i < IO_BITMAP_LONGS; i++) + if (t->io_bitmap_ptr[i] != ~0UL) + max_long = i; + + bytes = (max_long + 1) * sizeof(long); + bytes_updated = max(bytes, t->io_bitmap_max); + + t->io_bitmap_max = bytes; + + /* Update the TSS: */ + memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); + put_cpu(); + return 0; } @@ -83,9 +101,9 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) * code. */ -asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs) +asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) { - unsigned int old = (regs.eflags >> 12) & 3; + unsigned int old = (regs->eflags >> 12) & 3; if (level > 3) return -EINVAL; @@ -94,6 +112,6 @@ asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs) if (!capable(CAP_SYS_RAWIO)) return -EPERM; } - regs.eflags = (regs.eflags &~ 0x3000UL) | (level << 12); + regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12); return 0; } diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index 189418294..62b112e4d 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -3,127 +3,19 @@ * * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. + * This file contains the lowest level x86_64-specific interrupt + * entry and irq statistics code. All the remaining irq logic is + * done by the generic kernel/irq/ code and in the + * x86_64-specific irq controller code. (e.g. i8259.c and + * io_apic.c.) */ -/* - * (mostly architecture independent, will move to kernel/irq.c in 2.5.) - * - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include #include - -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include - - - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -/* - * Controller mappings for all interrupt sources: - */ -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { - [0 ... NR_IRQS-1] = { - .handler = &no_irq_type, - .lock = SPIN_LOCK_UNLOCKED - } -}; - -static void register_irq_proc (unsigned int irq); - -/* - * Special irq handlers. - */ - -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_NONE; } - -/* - * Generic no controller code - */ - -static void enable_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } -static void disable_none(unsigned int irq) { } -static void ack_none(unsigned int irq) -{ -/* - * 'what should we do if we get a hw irq event on an illegal vector'. - * each architecture has to answer this themselves, it doesn't deserve - * a generic callback i think. - */ -#ifdef CONFIG_X86 - printk("unexpected IRQ trap at vector %02x\n", irq); -#ifdef CONFIG_X86_LOCAL_APIC - /* - * Currently unexpected vectors happen only on SMP and APIC. - * We _must_ ack these because every local APIC has only N - * irq slots per priority level, and a 'hanging, unacked' IRQ - * holds up an irq slot - in excessive cases (when multiple - * unexpected vectors occur) that might lock up the APIC - * completely. - */ - ack_APIC_irq(); -#endif -#endif -} - -/* startup is the same as "enable", shutdown is same as "disable" */ -#define shutdown_none disable_none -#define end_none enable_none - -struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none -}; +#include atomic_t irq_err_count; #ifdef CONFIG_X86_IO_APIC @@ -195,129 +87,6 @@ skip: return 0; } -#ifdef CONFIG_SMP -inline void synchronize_irq(unsigned int irq) -{ - while (irq_desc[irq].status & IRQ_INPROGRESS) - cpu_relax(); -} -#endif - -/* - * This should really return information about whether - * we should do bottom half handling etc. Right now we - * end up _always_ checking the bottom half, which is a - * waste of time and is not what some drivers would - * prefer. - */ -int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) -{ - int status = 1; /* Force the "do bottom halves" bit */ - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - do { - status |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - - return status; -} - -/* - * 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 must not be called from IRQ context. - */ - -inline void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -/** - * 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. - */ - -void disable_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - synchronize_irq(irq); -} - -/** - * 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. - */ - -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - break; - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific @@ -325,628 +94,15 @@ void enable_irq(unsigned int irq) */ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) { - /* - * We ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * 0 return value means that this irq is already being - * handled by some other CPU. (or is disabled) - */ - unsigned irq = regs->orig_rax & 0xff; /* high bits used in ret_from_ code */ - int cpu = smp_processor_id(); - irq_desc_t *desc = irq_desc + irq; - struct irqaction * action; - unsigned int status; - - if (irq > 256) BUG(); - - irq_enter(); - kstat_cpu(cpu).irqs[irq]++; - spin_lock(&desc->lock); - desc->handler->ack(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - status |= IRQ_PENDING; /* we _want_ to handle it */ + /* high bits used in ret_from_ code */ + unsigned irq = regs->orig_rax & 0xff; - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { - action = desc->action; - status &= ~IRQ_PENDING; /* we commit to handling */ - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; - - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (unlikely(!action)) - goto out; - - /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. - */ - for (;;) { - spin_unlock(&desc->lock); - handle_IRQ_event(irq, regs, action); - spin_lock(&desc->lock); - - if (unlikely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } - desc->status &= ~IRQ_INPROGRESS; -out: - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - if (irq > 256) BUG(); - desc->handler->end(irq); - spin_unlock(&desc->lock); + irq_enter(); + BUG_ON(irq > 256); + __do_IRQ(irq, regs); irq_exit(); - return 1; -} - -int can_request_irq(unsigned int irq, unsigned long irqflags) -{ - struct irqaction *action; - - if (irq >= NR_IRQS) - return 0; - action = irq_desc[irq].action; - if (action) { - if (irqflags & action->flags & SA_SHIRQ) - action = NULL; - } - return !action; -} - -/** - * 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 - * - */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction * action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); - } -#endif - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_ATOMIC); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * 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. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - irq_desc_t *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - if (action) { - struct irqaction **pp = p; - p = &action->next; - if (action->dev_id != dev_id) - continue; - /* Found it - now remove it from the list of entries */ - *pp = action->next; - if (!desc->action) { - desc->status |= IRQ_DISABLED; - desc->handler->shutdown(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - synchronize_irq(irq); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; - } -} - -EXPORT_SYMBOL(free_irq); - -/* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that - * comes in on to an unassigned handler will get stuck - * with "IRQ_WAITING" cleared and the interrupt - * disabled. - */ - -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. - * - */ - -unsigned long probe_irq_on(void) -{ - unsigned int i; - irq_desc_t *desc; - unsigned long val; - unsigned long delay; - - down(&probe_sem); - /* - * something may have generated an irq long ago and we want to - * flush such a longstanding irq before considering it as spurious. - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!irq_desc[i].action) - irq_desc[i].handler->startup(i); - spin_unlock_irq(&desc->lock); - } - - /* Wait for longstanding interrupts to trigger. */ - for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ barrier(); - - /* - * enable any unassigned irqs - * (we must startup again here because if a longstanding irq - * happened in the previous stage, it may have masked itself) - */ - for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc + i; - - spin_lock_irq(&desc->lock); - if (!desc->action) { - desc->status |= IRQ_AUTODETECT | IRQ_WAITING; - if (desc->handler->startup(i)) - desc->status |= IRQ_PENDING; - } - spin_unlock_irq(&desc->lock); - } - - /* - * Wait for spurious interrupts to trigger - */ - for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ barrier(); - - /* - * Now filter out any obviously spurious interrupts - */ - val = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - /* It triggered already - consider it spurious. */ - if (!(status & IRQ_WAITING)) { - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } else - if (i < 32) - val |= 1 << i; - } - spin_unlock_irq(&desc->lock); - } - - return val; -} - -EXPORT_SYMBOL(probe_irq_on); - -/* - * 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. - */ -unsigned int probe_irq_mask(unsigned long val) -{ - int i; - unsigned int mask; - - mask = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (i < 16 && !(status & IRQ_WAITING)) - mask |= 1 << i; - - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - return mask & val; -} - -/* - * 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 shouldn't happen) - * nothing prevents two IRQ probe callers from overlapping. The - * results of this are non-optimal. - */ - -int probe_irq_off(unsigned long val) -{ - int i, irq_found, nr_irqs; - - nr_irqs = 0; - irq_found = 0; - for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc + i; - unsigned int status; - - spin_lock_irq(&desc->lock); - status = desc->status; - - if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) { - if (!nr_irqs) - irq_found = i; - nr_irqs++; - } - desc->status = status & ~IRQ_AUTODETECT; - desc->handler->shutdown(i); - } - spin_unlock_irq(&desc->lock); - } - up(&probe_sem); - - if (nr_irqs > 1) - irq_found = -irq_found; - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - unsigned long flags; - struct irqaction *old, **p; - irq_desc_t *desc = irq_desc + irq; - - if (desc->handler == &no_irq_type) - return -ENOSYS; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * 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); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); - desc->handler->startup(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - register_irq_proc(irq); - return 0; -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; - -#ifdef CONFIG_SMP - -static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; - -static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int irq_affinity_write_proc (struct file *file, - const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (long) data, full_count = count, err; - cpumask_t tmp, new_value; - - if (!irq_desc[irq].handler->set_affinity) - return -EIO; - - err = cpumask_parse(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. - */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; - - irq_affinity[irq] = new_value; - irq_desc[irq].handler->set_affinity(irq, new_value); - - return full_count; -} - -#endif - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static int prof_cpu_mask_write_proc (struct file *file, - const char __user *buffer, - unsigned long count, void *data) -{ - unsigned long full_count = count, err; - cpumask_t new_value, *mask = (cpumask_t *)data; - - err = cpumask_parse(buffer, count, new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || - irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef 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; - } - - smp_affinity_entry[irq] = entry; - } -#endif -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) -{ - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); - - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - - if (!entry) - return; - - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; - - /* - * Create entries for all existing IRQs. - */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); + return 1; } diff --git a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c index c7d7dac04..d7e5d0cf4 100644 --- a/arch/x86_64/kernel/ldt.c +++ b/arch/x86_64/kernel/ldt.c @@ -135,6 +135,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) return 0; if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; + down(&mm->context.sem); size = mm->context.size*LDT_ENTRY_SIZE; if (size > bytecount) @@ -145,12 +146,17 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) err = -EFAULT; up(&mm->context.sem); if (err < 0) - return err; + goto error_return; if (size != bytecount) { /* zero-fill the rest */ - clear_user(ptr+size, bytecount-size); + if (clear_user(ptr+size, bytecount-size) != 0) { + err = -EFAULT; + goto error_return; + } } return bytecount; +error_return: + return err; } static int read_default_ldt(void __user * ptr, unsigned long bytecount) diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 3bb678f1e..5da150baf 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -24,7 +24,8 @@ #define MISC_MCELOG_MINOR 227 #define NR_BANKS 5 -static int mce_disabled __initdata; +static int mce_dont_init; + /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic, 3: never panic or exit (for testing only) */ static int tolerant = 1; @@ -48,8 +49,7 @@ static void mce_log(struct mce *mce) mce->finished = 0; smp_wmb(); for (;;) { - entry = mcelog.next; - read_barrier_depends(); + entry = rcu_dereference(mcelog.next); /* When the buffer fills up discard new entries. Assume that the earlier errors are the more interesting. */ if (entry >= MCE_LOG_LEN) { @@ -72,7 +72,8 @@ static void mce_log(struct mce *mce) static void print_mce(struct mce *m) { - printk(KERN_EMERG + printk(KERN_EMERG "\n" + KERN_EMERG "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", m->cpu, m->mcgstatus, m->bank, m->status); if (m->rip) { @@ -101,7 +102,7 @@ static void mce_panic(char *msg, struct mce *backup, unsigned long start) if (time_before(tsc, start)) continue; print_mce(&mcelog.entry[i]); - if (mcelog.entry[i].tsc == backup->tsc) + if (backup && mcelog.entry[i].tsc == backup->tsc) backup = NULL; } if (backup) @@ -114,9 +115,8 @@ static void mce_panic(char *msg, struct mce *backup, unsigned long start) static int mce_available(struct cpuinfo_x86 *c) { - return !mce_disabled && - test_bit(X86_FEATURE_MCE, &c->x86_capability) && - test_bit(X86_FEATURE_MCA, &c->x86_capability); + return test_bit(X86_FEATURE_MCE, &c->x86_capability) && + test_bit(X86_FEATURE_MCA, &c->x86_capability); } /* @@ -128,8 +128,9 @@ void do_machine_check(struct pt_regs * regs, long error_code) struct mce m, panicm; int nowayout = (tolerant < 1); int kill_it = 0; - u64 mcestart; + u64 mcestart = 0; int i; + int panicm_found = 0; if (regs) notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL); @@ -139,17 +140,11 @@ void do_machine_check(struct pt_regs * regs, long error_code) memset(&m, 0, sizeof(struct mce)); m.cpu = hard_smp_processor_id(); rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); - if (!regs && (m.mcgstatus & MCG_STATUS_MCIP)) - return; if (!(m.mcgstatus & MCG_STATUS_RIPV)) kill_it = 1; - if (regs) { - m.rip = regs->rip; - m.cs = regs->cs; - } rdtscll(mcestart); - mb(); + barrier(); for (i = 0; i < banks; i++) { if (!bank[i]) @@ -157,52 +152,64 @@ void do_machine_check(struct pt_regs * regs, long error_code) m.misc = 0; m.addr = 0; + m.bank = i; + m.tsc = 0; rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); if ((m.status & MCI_STATUS_VAL) == 0) continue; - /* Should be implied by the banks check above, but - check it anyways */ - if ((m.status & MCI_STATUS_EN) == 0) - continue; - /* Did this bank cause the exception? */ - /* Assume that the bank with uncorrectable errors did it, - and that there is only a single one. */ - if (m.status & MCI_STATUS_UC) { - panicm = m; - } else { - m.rip = 0; - m.cs = 0; + if (m.status & MCI_STATUS_EN) { + /* In theory _OVER could be a nowayout too, but + assume any overflowed errors were no fatal. */ + nowayout |= !!(m.status & MCI_STATUS_PCC); + kill_it |= !!(m.status & MCI_STATUS_UC); } - /* In theory _OVER could be a nowayout too, but - assume any overflowed errors were no fatal. */ - nowayout |= !!(m.status & MCI_STATUS_PCC); - kill_it |= !!(m.status & MCI_STATUS_UC); - m.bank = i; - if (m.status & MCI_STATUS_MISCV) rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); if (m.status & MCI_STATUS_ADDRV) rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); - rdtscll(m.tsc); + if (regs && (m.mcgstatus & MCG_STATUS_RIPV)) { + m.rip = regs->rip; + m.cs = regs->cs; + } else { + m.rip = 0; + m.cs = 0; + } + + if (error_code != -1) + rdtscll(m.tsc); wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); mce_log(&m); + + /* Did this bank cause the exception? */ + /* Assume that the bank with uncorrectable errors did it, + and that there is only a single one. */ + if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) { + panicm = m; + panicm_found = 1; + } + + tainted |= TAINT_MACHINE_CHECK; } - wrmsrl(MSR_IA32_MCG_STATUS, 0); /* Never do anything final in the polling timer */ if (!regs) - return; + goto out; + + /* If we didn't find an uncorrectable error, pick + the last one (shouldn't happen, just being safe). */ + if (!panicm_found) + panicm = m; if (nowayout) - mce_panic("Machine check", &m, mcestart); + mce_panic("Machine check", &panicm, mcestart); if (kill_it) { int user_space = 0; if (m.mcgstatus & MCG_STATUS_RIPV) - user_space = m.rip && (m.cs & 3); + user_space = panicm.rip && (panicm.cs & 3); /* When the machine was in user space and the CPU didn't get confused it's normally not necessary to panic, unless you @@ -215,18 +222,15 @@ void do_machine_check(struct pt_regs * regs, long error_code) (unsigned)current->pid <= 1) mce_panic("Uncorrected machine check", &panicm, mcestart); - /* do_exit takes an awful lot of locks and has as slight risk - of deadlocking. If you don't want that don't set tolerant >= 2 */ + /* do_exit takes an awful lot of locks and has as + slight risk of deadlocking. If you don't want that + don't set tolerant >= 2 */ if (tolerant < 3) do_exit(SIGBUS); } -} -static void mce_clear_all(void) -{ - int i; - for (i = 0; i < banks; i++) - wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); + out: + /* Last thing done in the machine check exception to clear state. */ wrmsrl(MSR_IA32_MCG_STATUS, 0); } @@ -269,22 +273,25 @@ static void mce_init(void *dummy) int i; rdmsrl(MSR_IA32_MCG_CAP, cap); - if (cap & MCG_CTL_P) - wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); - banks = cap & 0xff; if (banks > NR_BANKS) { printk(KERN_INFO "MCE: warning: using only %d banks\n", banks); banks = NR_BANKS; } - mce_clear_all(); + /* Log the machine checks left over from the previous reset. + This also clears all registers */ + do_machine_check(NULL, -1); + + set_in_cr4(X86_CR4_MCE); + + if (cap & MCG_CTL_P) + wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); + for (i = 0; i < banks; i++) { wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); } - - set_in_cr4(X86_CR4_MCE); } /* Add per CPU specific workarounds here */ @@ -308,7 +315,9 @@ void __init mcheck_init(struct cpuinfo_x86 *c) mce_cpu_quirks(c); - if (test_and_set_bit(smp_processor_id(), &mce_cpus) || !mce_available(c)) + if (mce_dont_init || + test_and_set_bit(smp_processor_id(), &mce_cpus) || + !mce_available(c)) return; mce_init(NULL); @@ -333,9 +342,8 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff int i, err; down(&mce_read_sem); - next = mcelog.next; - read_barrier_depends(); - + next = rcu_dereference(mcelog.next); + /* Only supports full reads right now */ if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { up(&mce_read_sem); @@ -353,8 +361,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff memset(mcelog.entry, 0, next * sizeof(struct mce)); mcelog.next = 0; - smp_wmb(); - + synchronize_kernel(); /* Collect entries that were still getting written before the synchronize. */ @@ -412,15 +419,16 @@ static struct miscdevice mce_log_device = { static int __init mcheck_disable(char *str) { - mce_disabled = 1; + mce_dont_init = 1; return 0; } -/* mce=off disable machine check */ +/* mce=off disables machine check. Note you can reenable it later + using sysfs */ static int __init mcheck_enable(char *str) { if (!strcmp(str, "off")) - mce_disabled = 1; + mce_dont_init = 1; else printk("mce= argument %s ignored. Please use /sys", str); return 0; @@ -436,7 +444,6 @@ __setup("mce", mcheck_enable); /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */ static int mce_resume(struct sys_device *dev) { - mce_clear_all(); on_each_cpu(mce_init, NULL, 1, 1); return 0; } @@ -465,7 +472,7 @@ static struct sys_device device_mce = { /* Why are there no generic functions for this? */ #define ACCESSOR(name, var, start) \ static ssize_t show_ ## name(struct sys_device *s, char *buf) { \ - return sprintf(buf, "%lu\n", (unsigned long)var); \ + return sprintf(buf, "%lx\n", (unsigned long)var); \ } \ static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \ char *end; \ @@ -494,7 +501,7 @@ static __init int mce_init_device(void) if (!err) err = sysdev_register(&device_mce); if (!err) { - /* could create per CPU objects, but is not worth it. */ + /* could create per CPU objects, but it is not worth it. */ sysdev_create_file(&device_mce, &attr_bank0ctl); sysdev_create_file(&device_mce, &attr_bank1ctl); sysdev_create_file(&device_mce, &attr_bank2ctl); diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 646b3c0a9..1f415db88 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -330,6 +330,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) } } } + clustered_apic_check(); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors; @@ -895,25 +896,25 @@ void __init mp_config_acpi_legacy_irqs (void) return; } -void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) +int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) { int ioapic = -1; int ioapic_pin = 0; int idx, bit = 0; if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) - return; + return gsi; #ifdef CONFIG_ACPI_BUS /* Don't set up the ACPI SCI because it's already set up */ if (acpi_fadt.sci_int == gsi) - return; + return gsi; #endif ioapic = mp_find_ioapic(gsi); if (ioapic < 0) { printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); - return; + return gsi; } ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start; @@ -929,12 +930,12 @@ void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ioapic_pin); - return; + return gsi; } if ((1<cpu == smp_processor_id() ) - cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); + struct msr_command *cmd = (struct msr_command *)cmd_block; + + if (cmd->cpu == smp_processor_id()) + cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); } static void msr_smp_rdmsr(void *cmd_block) { - struct msr_command *cmd = (struct msr_command *) cmd_block; - - if ( cmd->cpu == smp_processor_id() ) - cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); + struct msr_command *cmd = (struct msr_command *)cmd_block; + + if (cmd->cpu == smp_processor_id()) + cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); } static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) { - struct msr_command cmd; - int ret; - - preempt_disable(); - if ( cpu == smp_processor_id() ) { - ret = wrmsr_eio(reg, eax, edx); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - cmd.data[0] = eax; - cmd.data[1] = edx; - - smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); - ret = cmd.err; - } - preempt_enable(); - return ret; + struct msr_command cmd; + int ret; + + preempt_disable(); + if (cpu == smp_processor_id()) { + ret = wrmsr_eio(reg, eax, edx); + } else { + cmd.cpu = cpu; + cmd.reg = reg; + cmd.data[0] = eax; + cmd.data[1] = edx; + + smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); + ret = cmd.err; + } + preempt_enable(); + return ret; } -static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) +static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx) { - struct msr_command cmd; - int ret; - - preempt_disable(); - if ( cpu == smp_processor_id() ) { - ret = rdmsr_eio(reg, eax, edx); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - - smp_call_function(msr_smp_rdmsr, &cmd, 1, 1); - - *eax = cmd.data[0]; - *edx = cmd.data[1]; - - ret = cmd.err; - } - preempt_enable(); - return ret; + struct msr_command cmd; + int ret; + + preempt_disable(); + if (cpu == smp_processor_id()) { + ret = rdmsr_eio(reg, eax, edx); + } else { + cmd.cpu = cpu; + cmd.reg = reg; + + smp_call_function(msr_smp_rdmsr, &cmd, 1, 1); + + *eax = cmd.data[0]; + *edx = cmd.data[1]; + + ret = cmd.err; + } + preempt_enable(); + return ret; } -#else /* ! CONFIG_SMP */ +#else /* ! CONFIG_SMP */ static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) { - return wrmsr_eio(reg, eax, edx); + return wrmsr_eio(reg, eax, edx); } static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) { - return rdmsr_eio(reg, eax, edx); + return rdmsr_eio(reg, eax, edx); } -#endif /* ! CONFIG_SMP */ +#endif /* ! CONFIG_SMP */ static loff_t msr_seek(struct file *file, loff_t offset, int orig) { - loff_t ret = -EINVAL; - lock_kernel(); - switch (orig) { - case 0: - file->f_pos = offset; - ret = file->f_pos; - break; - case 1: - file->f_pos += offset; - ret = file->f_pos; - } - unlock_kernel(); - return ret; + loff_t ret = -EINVAL; + + lock_kernel(); + switch (orig) { + case 0: + file->f_pos = offset; + ret = file->f_pos; + break; + case 1: + file->f_pos += offset; + ret = file->f_pos; + } + unlock_kernel(); + return ret; } -static ssize_t msr_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t msr_read(struct file *file, char __user * buf, + size_t count, loff_t * ppos) { - char __user *tmp = buf; - u32 data[2]; - size_t rv; - u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); - int err; - - if ( count % 8 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 8 ) { - err = do_rdmsr(cpu, reg, &data[0], &data[1]); - if ( err ) - return err; - if ( copy_to_user(tmp,&data,8) ) - return -EFAULT; - tmp += 8; - } - - return tmp - buf; + u32 __user *tmp = (u32 __user *) buf; + u32 data[2]; + size_t rv; + u32 reg = *ppos; + int cpu = iminor(file->f_dentry->d_inode); + int err; + + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + + for (rv = 0; count; count -= 8) { + err = do_rdmsr(cpu, reg, &data[0], &data[1]); + if (err) + return err; + if (copy_to_user(tmp, &data, 8)) + return -EFAULT; + tmp += 2; + } + + return ((char __user *)tmp) - buf; } -static ssize_t msr_write(struct file * file, const char __user * buf, +static ssize_t msr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - const char __user *tmp = buf; - u32 data[2]; - size_t rv; - u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); - int err; - - if ( count % 8 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 8 ) { - if ( copy_from_user(&data,tmp,8) ) - return -EFAULT; - err = do_wrmsr(cpu, reg, data[0], data[1]); - if ( err ) - return err; - tmp += 8; - } - - return tmp - buf; + const u32 __user *tmp = (const u32 __user *)buf; + u32 data[2]; + size_t rv; + u32 reg = *ppos; + int cpu = iminor(file->f_dentry->d_inode); + int err; + + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + + for (rv = 0; count; count -= 8) { + if (copy_from_user(&data, tmp, 8)) + return -EFAULT; + err = do_wrmsr(cpu, reg, data[0], data[1]); + if (err) + return err; + tmp += 2; + } + + return ((char __user *)tmp) - buf; } static int msr_open(struct inode *inode, struct file *file) { - int cpu = iminor(file->f_dentry->d_inode); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; - - if (cpu >= NR_CPUS || !cpu_online(cpu)) - return -ENXIO; /* No such CPU */ - if ( !cpu_has(c, X86_FEATURE_MSR) ) - return -EIO; /* MSR not supported */ - - return 0; + unsigned int cpu = iminor(file->f_dentry->d_inode); + struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + + if (cpu >= NR_CPUS || !cpu_online(cpu)) + return -ENXIO; /* No such CPU */ + if (!cpu_has(c, X86_FEATURE_MSR)) + return -EIO; /* MSR not supported */ + + return 0; } /* * File operations we support */ static struct file_operations msr_fops = { - .owner = THIS_MODULE, - .llseek = msr_seek, - .read = msr_read, - .write = msr_write, - .open = msr_open, + .owner = THIS_MODULE, + .llseek = msr_seek, + .read = msr_read, + .write = msr_write, + .open = msr_open, }; int __init msr_init(void) { - if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { - printk(KERN_ERR "msr: unable to get major %d for msr\n", - MSR_MAJOR); - return -EBUSY; - } - - return 0; + if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { + printk(KERN_ERR "msr: unable to get major %d for msr\n", + MSR_MAJOR); + return -EBUSY; + } + + return 0; } void __exit msr_exit(void) { - unregister_chrdev(MSR_MAJOR, "cpu/msr"); + unregister_chrdev(MSR_MAJOR, "cpu/msr"); } module_init(msr_init); diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 35dd5dfc0..143fe2fc4 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ static unsigned int lapic_nmi_owner; * -1: the lapic NMI watchdog is disabled, but can be enabled */ int nmi_active; /* oprofile uses this */ -static int panic_on_timeout; +int panic_on_timeout; unsigned int nmi_watchdog = NMI_DEFAULT; static unsigned int nmi_hz = HZ; @@ -344,8 +345,6 @@ void setup_apic_nmi_watchdog(void) nmi_active = 1; } -static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; - /* * the best way to detect whether a CPU has a 'hard lockup' problem * is to check it's local APIC timer IRQ counts. If they are not @@ -390,25 +389,12 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) */ alert_counter[cpu]++; if (alert_counter[cpu] == 5*nmi_hz) { - if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { + if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) + == NOTIFY_STOP) { alert_counter[cpu] = 0; return; } - spin_lock(&nmi_print_lock); - /* - * We are in trouble anyway, lets at least try - * to get a message out. - */ - bust_spinlocks(1); - printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); - show_registers(regs); - if (panic_on_timeout || panic_on_oops) - panic("nmi watchdog"); - printk("console shuts up ...\n"); - console_silent(); - spin_unlock(&nmi_print_lock); - bust_spinlocks(0); - do_exit(SIGSEGV); + die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs); } } else { last_irq_sums[cpu] = sum; @@ -446,6 +432,49 @@ void unset_nmi_callback(void) nmi_callback = dummy_nmi_callback; } +#ifdef CONFIG_SYSCTL + +static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) +{ + unsigned char reason = get_nmi_reason(); + char buf[64]; + + if (!(reason & 0xc0)) { + sprintf(buf, "NMI received for unknown reason %02x\n", reason); + die_nmi(buf,regs); + } + return 0; +} + +/* + * proc handler for /proc/sys/kernel/unknown_nmi_panic + */ +int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file, + void __user *buffer, size_t *length, loff_t *ppos) +{ + int old_state; + + old_state = unknown_nmi_panic; + proc_dointvec(table, write, file, buffer, length, ppos); + if (!!old_state == !!unknown_nmi_panic) + return 0; + + if (unknown_nmi_panic) { + if (reserve_lapic_nmi() < 0) { + unknown_nmi_panic = 0; + return -EBUSY; + } else { + set_nmi_callback(unknown_nmi_panic_callback); + } + } else { + release_lapic_nmi(); + unset_nmi_callback(); + } + return 0; +} + +#endif + EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(reserve_lapic_nmi); diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index 7eb3fc72a..cab471cf3 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c @@ -1,5 +1,5 @@ /* - * Dynamic DMA mapping support. Common code + * Dynamic DMA mapping support. */ #include @@ -24,38 +24,37 @@ * Device ownership issues as mentioned above for pci_map_single are * the same here. */ -int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction) +int dma_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction) { int i; - BUG_ON(direction == PCI_DMA_NONE); + BUG_ON(direction == DMA_NONE); for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; BUG_ON(!s->page); - s->dma_address = pci_map_page(hwdev, s->page, s->offset, - s->length, direction); + s->dma_address = virt_to_bus(page_address(s->page) +s->offset); s->dma_length = s->length; } return nents; } -EXPORT_SYMBOL(pci_map_sg); +EXPORT_SYMBOL(dma_map_sg); /* Unmap a set of streaming mode DMA translations. * Again, cpu read rules concerning calls here are the same as for * pci_unmap_single() above. */ -void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, - int nents, int dir) +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, int dir) { int i; for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; BUG_ON(s->page == NULL); BUG_ON(s->dma_address == 0); - pci_unmap_single(dev, s->dma_address, s->dma_length, dir); + dma_unmap_single(dev, s->dma_address, s->dma_length, dir); } } -EXPORT_SYMBOL(pci_unmap_sg); +EXPORT_SYMBOL(dma_unmap_sg); diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 09fde74cb..8092737f7 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -22,21 +22,15 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include -#ifdef CONFIG_PREEMPT -#define preempt_atomic() in_atomic() -#else -#define preempt_atomic() 1 -#endif - dma_addr_t bad_dma_address; unsigned long iommu_bus_base; /* GART remapping area (physical) */ @@ -54,7 +48,7 @@ int force_iommu = 1; int panic_on_overflow = 0; int force_iommu = 0; #endif -int iommu_merge = 0; +int iommu_merge = 1; int iommu_sac_force = 0; /* If this is disabled the IOMMU will use an optimized flushing strategy @@ -64,6 +58,10 @@ int iommu_sac_force = 0; also seen with Qlogic at least). */ int iommu_fullflush = 1; +/* This tells the BIO block layer to assume merging. Default to off + because we cannot guarantee merging later. */ +int iommu_bio_merge = 0; + #define MAX_NB 8 /* Allocation bitmap for the remapping area */ @@ -83,7 +81,7 @@ static u32 gart_unmapped_entry; #define for_all_nb(dev) \ dev = NULL; \ - while ((dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)\ + while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)\ if (dev->bus->number == 0 && \ (PCI_SLOT(dev->devfn) >= 24) && (PCI_SLOT(dev->devfn) <= 31)) @@ -104,8 +102,16 @@ AGPEXTERN __u32 *agp_gatt_table; static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, - size_t size, int dir); +static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, + size_t size, int dir, int do_panic); + +/* Dummy device used for NULL arguments (normally ISA). Better would + be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */ +static struct device fallback_dev = { + .bus_id = "fallback device", + .coherent_dma_mask = 0xffffffff, + .dma_mask = &fallback_dev.coherent_dma_mask, +}; static unsigned long alloc_iommu(int size) { @@ -146,25 +152,31 @@ static void free_iommu(unsigned long offset, int size) /* * Use global flush state to avoid races with multiple flushers. */ -static void flush_gart(struct pci_dev *dev) +static void flush_gart(struct device *dev) { unsigned long flags; int flushed = 0; - int i; + int i, max; spin_lock_irqsave(&iommu_bitmap_lock, flags); if (need_flush) { + max = 0; for (i = 0; i < MAX_NB; i++) { - u32 w; if (!northbridges[i]) continue; pci_write_config_dword(northbridges[i], 0x9c, northbridge_flush_word[i] | 1); + flushed++; + max = i; + } + for (i = 0; i <= max; i++) { + u32 w; + if (!northbridges[i]) + continue; /* Make sure the hardware actually executed the flush. */ do { pci_read_config_dword(northbridges[i], 0x9c, &w); } while (w & 1); - flushed++; } if (!flushed) printk("nothing to flush?\n"); @@ -173,31 +185,47 @@ static void flush_gart(struct pci_dev *dev) spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } +/* Allocate DMA memory on node near device */ +noinline +static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order) +{ + struct page *page; + int node; + if (dev->bus == &pci_bus_type) { + cpumask_t mask; + mask = pcibus_to_cpumask(to_pci_dev(dev)->bus->number); + node = cpu_to_node(first_cpu(mask)); + } else + node = numa_node_id(); + page = alloc_pages_node(node, gfp, order); + return page ? page_address(page) : NULL; +} + /* - * Allocate memory for a consistent mapping. + * Allocate memory for a coherent mapping. */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) +void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + unsigned gfp) { void *memory; - int gfp = preempt_atomic() ? GFP_ATOMIC : GFP_KERNEL; unsigned long dma_mask = 0; u64 bus; - if (hwdev) - dma_mask = hwdev->dev.coherent_dma_mask; + if (!dev) + dev = &fallback_dev; + dma_mask = dev->coherent_dma_mask; if (dma_mask == 0) dma_mask = 0xffffffff; /* Kludge to make it bug-to-bug compatible with i386. i386 - uses the normal dma_mask for alloc_consistent. */ - if (hwdev) - dma_mask &= hwdev->dma_mask; + uses the normal dma_mask for alloc_coherent. */ + dma_mask &= *dev->dma_mask; again: - memory = (void *)__get_free_pages(gfp, get_order(size)); + memory = dma_alloc_pages(dev, gfp, get_order(size)); if (memory == NULL) - return NULL; + return NULL; { int high, mmu; @@ -208,11 +236,21 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, mmu = 1; if (no_iommu || dma_mask < 0xffffffffUL) { if (high) { + free_pages((unsigned long)memory, + get_order(size)); + + if (swiotlb) { + return + swiotlb_alloc_coherent(dev, size, + dma_handle, + gfp); + } + if (!(gfp & GFP_DMA)) { gfp |= GFP_DMA; goto again; } - goto free; + return NULL; } mmu = 0; } @@ -223,28 +261,32 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, } } - *dma_handle = pci_map_area(hwdev, bus, size, PCI_DMA_BIDIRECTIONAL); + *dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0); if (*dma_handle == bad_dma_address) goto error; - flush_gart(hwdev); + flush_gart(dev); return memory; error: if (panic_on_overflow) - panic("pci_alloc_consistent: overflow %lu bytes\n", size); -free: + panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size); free_pages((unsigned long)memory, get_order(size)); return NULL; } /* - * Unmap consistent memory. + * Unmap coherent memory. * The caller must ensure that the device has finished accessing the mapping. */ -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t bus) { - pci_unmap_single(hwdev, bus, size, 0); + if (swiotlb) { + swiotlb_free_coherent(dev, size, vaddr, bus); + return; + } + + dma_unmap_single(dev, bus, size, 0); free_pages((unsigned long)vaddr, get_order(size)); } @@ -280,7 +322,7 @@ void dump_leak(void) #define CLEAR_LEAK(x) #endif -static void iommu_full(struct pci_dev *dev, size_t size, int dir) +static void iommu_full(struct device *dev, size_t size, int dir, int do_panic) { /* * Ran out of IOMMU space for this operation. This is very bad. @@ -293,14 +335,14 @@ static void iommu_full(struct pci_dev *dev, size_t size, int dir) */ printk(KERN_ERR - "PCI-DMA: Out of IOMMU space for %lu bytes at device %s[%s]\n", - size, dev ? pci_pretty_name(dev) : "", dev ? dev->slot_name : "?"); + "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", + size, dev->bus_id); - if (size > PAGE_SIZE*EMERGENCY_PAGES) { + if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic("PCI-DMA: Memory will be corrupted\n"); + panic("PCI-DMA: Memory would be corrupted\n"); if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic("PCI-DMA: Random memory will be DMAed\n"); + panic("PCI-DMA: Random memory would be DMAed\n"); } #ifdef CONFIG_IOMMU_LEAK @@ -308,9 +350,9 @@ static void iommu_full(struct pci_dev *dev, size_t size, int dir) #endif } -static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t size) +static inline int need_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = dev ? dev->dma_mask : 0xffffffff; + u64 mask = *dev->dma_mask; int high = addr + size >= mask; int mmu = high; if (force_iommu) @@ -323,9 +365,9 @@ static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t siz return mmu; } -static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_t size) +static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = dev ? dev->dma_mask : 0xffffffff; + u64 mask = *dev->dma_mask; int high = addr + size >= mask; int mmu = high; if (no_iommu) { @@ -339,8 +381,8 @@ static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_ /* Map a single continuous physical area into the IOMMU. * Caller needs to check if the iommu is needed and flush. */ -static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, - size_t size, int dir) +static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, + size_t size, int dir, int do_panic) { unsigned long npages = to_pages(phys_mem, size); unsigned long iommu_page = alloc_iommu(npages); @@ -349,8 +391,8 @@ static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, if (!nonforced_iommu(dev, phys_mem, size)) return phys_mem; if (panic_on_overflow) - panic("pci_map_area overflow %lu bytes\n", size); - iommu_full(dev, size, dir); + panic("dma_map_area overflow %lu bytes\n", size); + iommu_full(dev, size, dir, do_panic); return bad_dma_address; } @@ -363,44 +405,44 @@ static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, } /* Map a single area into the IOMMU */ -dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) -{ +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir) +{ unsigned long phys_mem, bus; - BUG_ON(dir == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); -#ifdef CONFIG_SWIOTLB if (swiotlb) - return swiotlb_map_single(&dev->dev,addr,size,dir); -#endif + return swiotlb_map_single(dev,addr,size,dir); + if (!dev) + dev = &fallback_dev; phys_mem = virt_to_phys(addr); if (!need_iommu(dev, phys_mem, size)) return phys_mem; - bus = pci_map_area(dev, phys_mem, size, dir); + bus = dma_map_area(dev, phys_mem, size, dir, 1); flush_gart(dev); return bus; } -/* Fallback for pci_map_sg in case of overflow */ -static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg, +/* Fallback for dma_map_sg in case of overflow */ +static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; #ifdef CONFIG_IOMMU_DEBUG - printk(KERN_DEBUG "pci_map_sg overflow\n"); + printk(KERN_DEBUG "dma_map_sg overflow\n"); #endif for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; unsigned long addr = page_to_phys(s->page) + s->offset; if (nonforced_iommu(dev, addr, s->length)) { - addr = pci_map_area(dev, addr, s->length, dir); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) - pci_unmap_sg(dev, sg, i, dir); + dma_unmap_sg(dev, sg, i, dir); nents = 0; sg[0].dma_length = 0; break; @@ -414,7 +456,7 @@ static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg, } /* Map multiple scatterlist entries continuous into the first. */ -static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, +static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages) { unsigned long iommu_start = alloc_iommu(pages); @@ -452,7 +494,7 @@ static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, return 0; } -static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, +static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages, int need) { @@ -462,14 +504,14 @@ static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, sout->dma_length = sg[start].length; return 0; } - return __pci_map_cont(sg, start, stopat, sout, pages); + return __dma_map_cont(sg, start, stopat, sout, pages); } /* * DMA map all entries in a scatterlist. * Merge chunks that have page aligned sizes into a continuous mapping. - */ -int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) + */ +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; int out; @@ -477,19 +519,14 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) unsigned long pages = 0; int need = 0, nextneed; -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_map_sg(&dev->dev,sg,nents,dir); -#endif - - BUG_ON(dir == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); if (nents == 0) return 0; -#ifdef CONFIG_SWIOTLB if (swiotlb) - return swiotlb_map_sg(&dev->dev,sg,nents,dir); -#endif + return swiotlb_map_sg(dev,sg,nents,dir); + if (!dev) + dev = &fallback_dev; out = 0; start = 0; @@ -508,19 +545,19 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) boundary and the new one doesn't have an offset. */ if (!iommu_merge || !nextneed || !need || s->offset || (ps->offset + ps->length) % PAGE_SIZE) { - if (pci_map_cont(sg, start, i, sg+out, pages, + if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; pages = 0; start = i; } - } + } need = nextneed; pages += to_pages(s->offset, s->length); } - if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0) + if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; flush_gart(dev); @@ -530,34 +567,32 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) error: flush_gart(NULL); - pci_unmap_sg(dev, sg, nents, dir); + dma_unmap_sg(dev, sg, nents, dir); /* When it was forced try again unforced */ if (force_iommu) - return pci_map_sg_nonforce(dev, sg, nents, dir); + return dma_map_sg_nonforce(dev, sg, nents, dir); if (panic_on_overflow) - panic("pci_map_sg: overflow on %lu pages\n", pages); - iommu_full(dev, pages << PAGE_SHIFT, dir); + panic("dma_map_sg: overflow on %lu pages\n", pages); + iommu_full(dev, pages << PAGE_SHIFT, dir, 0); for (i = 0; i < nents; i++) sg[i].dma_address = bad_dma_address; return 0; } /* - * Free a PCI mapping. + * Free a DMA mapping. */ -void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, int direction) { unsigned long iommu_page; int npages; int i; -#ifdef CONFIG_SWIOTLB if (swiotlb) { - swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction); + swiotlb_unmap_single(dev,dma_addr,size,direction); return; } -#endif if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) @@ -574,22 +609,25 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, /* * Wrapper for pci_unmap_single working with scatterlists. */ -void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, - int dir) +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; + if (swiotlb) { + swiotlb_unmap_sg(dev,sg,nents,dir); + return; + } for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; if (!s->dma_length || !s->length) break; - pci_unmap_single(dev, s->dma_address, s->dma_length, dir); + dma_unmap_single(dev, s->dma_address, s->dma_length, dir); } } -int pci_dma_supported(struct pci_dev *dev, u64 mask) +int dma_supported(struct device *dev, u64 mask) { /* Copied from i386. Doesn't make much sense, because it will - only work for pci_alloc_consistent. + only work for pci_alloc_coherent. The caller just has to use GFP_DMA in this case. */ if (mask < 0x00ffffff) return 0; @@ -605,22 +643,31 @@ int pci_dma_supported(struct pci_dev *dev, u64 mask) Assume all masks <= 40 bits are of this type. Normally this doesn't make any difference, but gives more gentle handling of IOMMU overflow. */ if (iommu_sac_force && (mask >= 0xffffffffffULL)) { - printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask); + printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask); return 0; } return 1; } -EXPORT_SYMBOL(pci_unmap_sg); -EXPORT_SYMBOL(pci_map_sg); -EXPORT_SYMBOL(pci_map_single); -EXPORT_SYMBOL(pci_unmap_single); -EXPORT_SYMBOL(pci_dma_supported); +int dma_get_cache_alignment(void) +{ + return boot_cpu_data.x86_clflush_size; +} + +EXPORT_SYMBOL(dma_unmap_sg); +EXPORT_SYMBOL(dma_map_sg); +EXPORT_SYMBOL(dma_map_single); +EXPORT_SYMBOL(dma_unmap_single); +EXPORT_SYMBOL(dma_supported); EXPORT_SYMBOL(no_iommu); EXPORT_SYMBOL(force_iommu); EXPORT_SYMBOL(bad_dma_address); -EXPORT_SYMBOL(iommu_merge); +EXPORT_SYMBOL(iommu_bio_merge); +EXPORT_SYMBOL(iommu_sac_force); +EXPORT_SYMBOL(dma_get_cache_alignment); +EXPORT_SYMBOL(dma_alloc_coherent); +EXPORT_SYMBOL(dma_free_coherent); static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) { @@ -747,7 +794,7 @@ static int __init pci_iommu_init(void) if (swiotlb) { no_iommu = 1; - printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); + printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); return -1; } @@ -851,7 +898,7 @@ static int __init pci_iommu_init(void) fs_initcall(pci_iommu_init); /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] - [,forcesac][,fullflush][,nomerge] + [,forcesac][,fullflush][,nomerge][,biomerge] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. off don't use the IOMMU @@ -859,60 +906,73 @@ fs_initcall(pci_iommu_init); memaper[=order] allocate an own aperture over RAM with size 32MB^order. noforce don't force IOMMU usage. Default. force Force IOMMU. - merge Do SG merging. Implies force (experimental) + merge Do lazy merging. This may improve performance on some block devices. + Implies force (experimental) + biomerge Do merging at the BIO layer. This is more efficient than merge, + but should be only done with very big IOMMUs. Implies merge,force. nomerge Don't do SG merging. forcesac For SAC mode for masks <40bits (experimental) fullflush Flush IOMMU on each allocation (default) nofullflush Don't use IOMMU fullflush allowed overwrite iommu off workarounds for specific chipsets. soft Use software bounce buffering (default for Intel machines) + noaperture Don't touch the aperture for AGP. */ -__init int iommu_setup(char *opt) +__init int iommu_setup(char *p) { int arg; - char *p = opt; - - for (;;) { - if (!memcmp(p,"noagp", 5)) + + while (*p) { + if (!strncmp(p,"noagp",5)) no_agp = 1; - if (!memcmp(p,"off", 3)) + if (!strncmp(p,"off",3)) no_iommu = 1; - if (!memcmp(p,"force", 5)) { + if (!strncmp(p,"force",5)) { force_iommu = 1; iommu_aperture_allowed = 1; } - if (!memcmp(p,"allowed",7)) + if (!strncmp(p,"allowed",7)) iommu_aperture_allowed = 1; - if (!memcmp(p,"noforce", 7)) { + if (!strncmp(p,"noforce",7)) { iommu_merge = 0; force_iommu = 0; } - if (!memcmp(p, "memaper", 7)) { + if (!strncmp(p, "memaper", 7)) { fallback_aper_force = 1; p += 7; - if (*p == '=' && get_option(&p, &arg)) - fallback_aper_order = arg; + if (*p == '=') { + ++p; + if (get_option(&p, &arg)) + fallback_aper_order = arg; + } } - if (!memcmp(p, "panic", 5)) + if (!strncmp(p, "biomerge",8)) { + iommu_bio_merge = 4096; + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "panic",5)) panic_on_overflow = 1; - if (!memcmp(p, "nopanic", 7)) + if (!strncmp(p, "nopanic",7)) panic_on_overflow = 0; - if (!memcmp(p, "merge", 5)) { + if (!strncmp(p, "merge",5)) { iommu_merge = 1; force_iommu = 1; } - if (!memcmp(p, "nomerge", 7)) + if (!strncmp(p, "nomerge",7)) iommu_merge = 0; - if (!memcmp(p, "forcesac", 8)) + if (!strncmp(p, "forcesac",8)) iommu_sac_force = 1; - if (!memcmp(p, "fullflush", 9)) + if (!strncmp(p, "fullflush",8)) iommu_fullflush = 1; - if (!memcmp(p, "nofullflush", 11)) + if (!strncmp(p, "nofullflush",11)) iommu_fullflush = 0; - if (!memcmp(p, "soft", 4)) + if (!strncmp(p, "soft",4)) swiotlb = 1; + if (!strncmp(p, "noaperture",10)) + fix_aperture = 0; #ifdef CONFIG_IOMMU_LEAK - if (!memcmp(p,"leak", 4)) { + if (!strncmp(p,"leak",4)) { leak_trace = 1; p += 4; if (*p == '=') ++p; @@ -922,10 +982,9 @@ __init int iommu_setup(char *opt) #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - do { - if (*p == ' ' || *p == 0) - return 0; - } while (*p++ != ','); + p += strcspn(p, ","); + if (*p == ',') + ++p; } return 1; } diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index 00fb2645c..67d90b89a 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -1,8 +1,11 @@ +/* Fallback functions when the main IOMMU code is not compiled in. This + code is roughly equivalent to i386. */ #include #include #include #include #include +#include int iommu_merge = 0; EXPORT_SYMBOL(iommu_merge); @@ -10,57 +13,80 @@ EXPORT_SYMBOL(iommu_merge); dma_addr_t bad_dma_address; EXPORT_SYMBOL(bad_dma_address); +int iommu_bio_merge = 0; +EXPORT_SYMBOL(iommu_bio_merge); + +int iommu_sac_force = 0; +EXPORT_SYMBOL(iommu_sac_force); + /* * Dummy IO MMU functions */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) +void *dma_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, unsigned gfp) { void *ret; - int gfp = GFP_ATOMIC; - - if (hwdev == NULL || - end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) || /* XXX */ - (u32)hwdev->dma_mask < 0xffffffff) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); + u64 mask; + int order = get_order(size); - if (ret != NULL) { - memset(ret, 0, size); + if (hwdev) + mask = hwdev->coherent_dma_mask & *hwdev->dma_mask; + else + mask = 0xffffffff; + for (;;) { + ret = (void *)__get_free_pages(gfp, order); + if (ret == NULL) + return NULL; *dma_handle = virt_to_bus(ret); + if ((*dma_handle & ~mask) == 0) + break; + free_pages((unsigned long)ret, order); + if (gfp & GFP_DMA) + return NULL; + gfp |= GFP_DMA; } + + memset(ret, 0, size); return ret; } +EXPORT_SYMBOL(dma_alloc_coherent); -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long)vaddr, get_order(size)); } +EXPORT_SYMBOL(dma_free_coherent); -int pci_dma_supported(struct pci_dev *hwdev, u64 mask) +int dma_supported(struct device *hwdev, u64 mask) { /* * we fall back to GFP_DMA when the mask isn't all 1s, * so we can't guarantee allocations that must be * within a tighter range than GFP_DMA.. - * RED-PEN this won't work for pci_map_single. Caller has to - * use GFP_DMA in the first place. + * RED-PEN this won't work for pci_map_single. Caller has to + * use GFP_DMA in the first place. */ if (mask < 0x00ffffff) return 0; return 1; } +EXPORT_SYMBOL(dma_supported); -EXPORT_SYMBOL(pci_dma_supported); +int dma_get_cache_alignment(void) +{ + return boot_cpu_data.x86_clflush_size; +} +EXPORT_SYMBOL(dma_get_cache_alignment); static int __init check_ram(void) { if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { - printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n" - KERN_ERR "WARNING 32bit PCI may malfunction.\n"); + printk( + KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n" + KERN_ERR "WARNING 32bit PCI may malfunction.\n"); } return 0; } diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index f7d3cf3ca..1ce2e1f9a 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -54,6 +54,9 @@ unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; atomic_t hlt_counter = ATOMIC_INIT(0); +unsigned long boot_option_idle_override = 0; +EXPORT_SYMBOL(boot_option_idle_override); + /* * Powermanagement idle function, if any.. */ @@ -130,11 +133,20 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - while (!need_resched()) + while (!need_resched()) { + void (*idle)(void); + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); + idle = pm_idle; + if (!idle) + idle = default_idle; idle(); + rcu_read_unlock(); + } schedule(); } } @@ -168,9 +180,7 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_MWAIT)) { /* * Skip, if setup has overridden idle. - * Also, take care of system with asymmetric CPUs. - * Use, mwait_idle only if all cpus support it. - * If not, we fallback to default_idle() + * One CPU supports mwait => All CPUs supports mwait */ if (!pm_idle) { if (!printed) { @@ -179,10 +189,7 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c) } pm_idle = mwait_idle; } - return; } - pm_idle = default_idle; - return; } static int __init idle_setup (char *str) @@ -192,6 +199,7 @@ static int __init idle_setup (char *str) pm_idle = poll_idle; } + boot_option_idle_override = 1; return 1; } @@ -255,11 +263,17 @@ void show_regs(struct pt_regs *regs) void exit_thread(void) { struct task_struct *me = current; + struct thread_struct *t = &me->thread; if (me->thread.io_bitmap_ptr) { - struct tss_struct *tss = init_tss + get_cpu(); - kfree(me->thread.io_bitmap_ptr); - me->thread.io_bitmap_ptr = NULL; - tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; + struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); + + kfree(t->io_bitmap_ptr); + t->io_bitmap_ptr = NULL; + /* + * Careful, clear this in the TSS too: + */ + memset(tss->io_bitmap, 0xff, t->io_bitmap_max); + t->io_bitmap_max = 0; put_cpu(); } } @@ -349,7 +363,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, if (rsp == ~0UL) { childregs->rsp = (unsigned long)childregs; } - p->set_child_tid = p->clear_child_tid = NULL; p->thread.rsp = (unsigned long) childregs; p->thread.rsp0 = (unsigned long) (childregs+1); @@ -367,8 +380,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); - if (!p->thread.io_bitmap_ptr) + if (!p->thread.io_bitmap_ptr) { + p->thread.io_bitmap_max = 0; return -ENOMEM; + } memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES); } @@ -387,8 +402,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, } err = 0; out: - if (err && p->thread.io_bitmap_ptr) + if (err && p->thread.io_bitmap_ptr) { kfree(p->thread.io_bitmap_ptr); + p->thread.io_bitmap_max = 0; + } return err; } @@ -409,7 +426,7 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); - struct tss_struct *tss = init_tss + cpu; + struct tss_struct *tss = &per_cpu(init_tss, cpu); unlazy_fpu(prev_p); @@ -495,22 +512,18 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct * * Handle the IO bitmap */ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { - if (next->io_bitmap_ptr) { + if (next->io_bitmap_ptr) /* - * 2 cachelines copy ... not good, but not that - * bad either. Anyone got something better? - * This only affects processes which use ioperm(). - */ - memcpy(tss->io_bitmap, next->io_bitmap_ptr, IO_BITMAP_BYTES); - tss->io_bitmap_base = IO_BITMAP_OFFSET; - } else { + * Copy the relevant range of the IO bitmap. + * Normally this is 128 bytes or less: + */ + memcpy(tss->io_bitmap, next->io_bitmap_ptr, + max(prev->io_bitmap_max, next->io_bitmap_max)); + else { /* - * a bitmap offset pointing outside of the TSS limit - * causes a nicely controllable SIGSEGV if a process - * tries to use a port IO instruction. The first - * sys_ioperm() call sets up the bitmap properly. + * Clear any possible leftover bits: */ - tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; + memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); } } @@ -532,8 +545,11 @@ long sys_execve(char __user *name, char __user * __user *argv, if (IS_ERR(filename)) return error; error = do_execve(filename, argv, envp, ®s); - if (error == 0) + if (error == 0) { + task_lock(current); current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } putname(filename); return error; } @@ -546,17 +562,16 @@ void set_personality_64bit(void) clear_thread_flag(TIF_IA32); } -asmlinkage long sys_fork(struct pt_regs regs) +asmlinkage long sys_fork(struct pt_regs *regs) { - return do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); + return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); } -asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs regs) +asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) { if (!newsp) - newsp = regs.rsp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - parent_tid, child_tid); + newsp = regs->rsp; + return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } /* @@ -569,9 +584,9 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void _ * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage long sys_vfork(struct pt_regs regs) +asmlinkage long sys_vfork(struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0, NULL, NULL); } diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 5dd7752ae..17a4bd966 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -88,6 +88,7 @@ void ptrace_disable(struct task_struct *child) { long tmp; + clear_tsk_thread_flag(child, TIF_SINGLESTEP); tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); } @@ -322,6 +323,8 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ret = 0; break; case offsetof(struct user, u_debugreg[7]): + /* See arch/i386/kernel/ptrace.c for an explanation of + * this awkward check.*/ data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5454 >> ((data >> (16 + 4*i)) & 0xf)) & 1) @@ -344,6 +347,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data set_tsk_thread_flag(child,TIF_SYSCALL_TRACE); else clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE); + clear_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = data; /* make sure the single step bit is not set. */ tmp = get_stack_long(child, EFL_OFFSET); @@ -393,8 +397,9 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data long tmp; ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ break; + clear_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; @@ -416,6 +421,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data } tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); + set_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -429,30 +435,32 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data break; case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, FRAME_SIZE)) { + if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, + sizeof(struct user_regs_struct))) { ret = -EIO; break; } + ret = 0; for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { - __put_user(getreg(child, ui),(unsigned long __user *) data); + ret |= __put_user(getreg(child, ui),(unsigned long __user *) data); data += sizeof(long); } - ret = 0; break; } case PTRACE_SETREGS: { /* Set all gp regs in the child. */ unsigned long tmp; - if (!access_ok(VERIFY_READ, (unsigned __user *)data, FRAME_SIZE)) { + if (!access_ok(VERIFY_READ, (unsigned __user *)data, + sizeof(struct user_regs_struct))) { ret = -EIO; break; } + ret = 0; for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { - __get_user(tmp, (unsigned long __user *) data); + ret |= __get_user(tmp, (unsigned long __user *) data); putreg(child, ui, tmp); data += sizeof(long); } - ret = 0; break; } @@ -528,7 +536,8 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) if (unlikely(current->audit_context)) audit_syscall_exit(current, regs->rax); - if (test_thread_flag(TIF_SYSCALL_TRACE) + if ((test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SINGLESTEP)) && (current->ptrace & PT_PTRACED)) syscall_trace(regs); } diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index c0d3c8dfa..22f485c77 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -56,6 +56,7 @@ #include #include #include +#include /* * Machine setup.. @@ -71,7 +72,7 @@ EXPORT_SYMBOL(acpi_disabled); #ifdef CONFIG_ACPI_BOOT extern int __initdata acpi_ht; extern acpi_interrupt_flags acpi_sci_flags; -/* int __initdata acpi_force = 0; */ +int __initdata acpi_force = 0; #endif /* For PCI or other memory-mapped resources */ @@ -79,8 +80,10 @@ unsigned long pci_mem_start = 0x10000000; unsigned long saved_video_mode; +#ifdef CONFIG_SWIOTLB int swiotlb; EXPORT_SYMBOL(swiotlb); +#endif /* * Setup options @@ -105,7 +108,8 @@ char command_line[COMMAND_LINE_SIZE]; struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO }, { "pic1", 0x20, 0x21, IORESOURCE_BUSY | IORESOURCE_IO }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY | IORESOURCE_IO }, + { "timer0", 0x40, 0x43, IORESOURCE_BUSY | IORESOURCE_IO }, + { "timer1", 0x50, 0x53, IORESOURCE_BUSY | IORESOURCE_IO }, { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY | IORESOURCE_IO }, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY | IORESOURCE_IO }, { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY | IORESOURCE_IO }, @@ -248,14 +252,14 @@ static __init void parse_cmdline_early (char ** cmdline_p) if (!memcmp(from, "acpi=force", 10)) { /* add later when we do DMI horrors: */ - /* acpi_force = 1; */ + acpi_force = 1; acpi_disabled = 0; } /* acpi=ht just means: do ACPI MADT parsing at bootup, but don't enable the full ACPI interpreter */ if (!memcmp(from, "acpi=ht", 7)) { - /* if (!acpi_force) */ + if (!acpi_force) disable_acpi(); acpi_ht = 1; } @@ -423,6 +427,20 @@ static inline void copy_edd(void) } #endif +#define EBDA_ADDR_POINTER 0x40E +static void __init reserve_ebda_region(void) +{ + unsigned int addr; + /** + * there is a real-mode segmented pointer pointing to the + * 4K EBDA area at 0x40E + */ + addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER); + addr <<= 4; + if (addr) + reserve_bootmem_generic(addr, PAGE_SIZE); +} + void __init setup_arch(char **cmdline_p) { unsigned long low_mem_size; @@ -487,6 +505,9 @@ void __init setup_arch(char **cmdline_p) */ reserve_bootmem_generic(0, PAGE_SIZE); + /* reserve ebda region */ + reserve_ebda_region(); + #ifdef CONFIG_SMP /* * But first pinch a few for the stack/trampoline stuff @@ -662,6 +683,26 @@ static int __init init_amd(struct cpuinfo_x86 *c) } } display_cacheinfo(c); + + if (c->cpuid_level >= 0x80000008) { + c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; + if (c->x86_num_cores & (c->x86_num_cores - 1)) + c->x86_num_cores = 1; + +#ifdef CONFIG_NUMA + /* On a dual core setup the lower bits of apic id + distingush the cores. Fix up the CPU<->node mappings + here based on that. + Assumes number of cores is a power of two. */ + if (c->x86_num_cores > 1) { + int cpu = c->x86_apicid; + cpu_to_node[cpu] = cpu >> hweight32(c->x86_num_cores - 1); + printk(KERN_INFO "CPU %d -> Node %d\n", + cpu, cpu_to_node[cpu]); + } +#endif + } + return r; } @@ -670,7 +711,6 @@ static void __init detect_ht(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP u32 eax, ebx, ecx, edx; int index_lsb, index_msb, tmp; - int initial_apic_id; int cpu = smp_processor_id(); if (!cpu_has(c, X86_FEATURE_HT)) @@ -705,8 +745,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c) } if (index_lsb != index_msb ) index_msb++; - initial_apic_id = ebx >> 24 & 0xff; - phys_proc_id[cpu] = initial_apic_id >> index_msb; + phys_proc_id[cpu] = phys_pkg_id(index_msb); printk(KERN_INFO "CPU: Physical Processor ID: %d\n", phys_proc_id[cpu]); @@ -714,133 +753,12 @@ static void __init detect_ht(struct cpuinfo_x86 *c) #endif } -#define LVL_1_INST 1 -#define LVL_1_DATA 2 -#define LVL_2 3 -#define LVL_3 4 -#define LVL_TRACE 5 - -struct _cache_table -{ - unsigned char descriptor; - char cache_type; - short size; -}; - -/* all the cache descriptor types we care about (no TLB or trace cache entries) */ -static struct _cache_table cache_table[] __initdata = -{ - { 0x06, LVL_1_INST, 8 }, - { 0x08, LVL_1_INST, 16 }, - { 0x0a, LVL_1_DATA, 8 }, - { 0x0c, LVL_1_DATA, 16 }, - { 0x22, LVL_3, 512 }, - { 0x23, LVL_3, 1024 }, - { 0x25, LVL_3, 2048 }, - { 0x29, LVL_3, 4096 }, - { 0x2c, LVL_1_DATA, 32 }, - { 0x30, LVL_1_INST, 32 }, - { 0x39, LVL_2, 128 }, - { 0x3b, LVL_2, 128 }, - { 0x3c, LVL_2, 256 }, - { 0x41, LVL_2, 128 }, - { 0x42, LVL_2, 256 }, - { 0x43, LVL_2, 512 }, - { 0x44, LVL_2, 1024 }, - { 0x45, LVL_2, 2048 }, - { 0x66, LVL_1_DATA, 8 }, - { 0x67, LVL_1_DATA, 16 }, - { 0x68, LVL_1_DATA, 32 }, - { 0x70, LVL_TRACE, 12 }, - { 0x71, LVL_TRACE, 16 }, - { 0x72, LVL_TRACE, 32 }, - { 0x79, LVL_2, 128 }, - { 0x7a, LVL_2, 256 }, - { 0x7b, LVL_2, 512 }, - { 0x7c, LVL_2, 1024 }, - { 0x82, LVL_2, 256 }, - { 0x83, LVL_2, 512 }, - { 0x84, LVL_2, 1024 }, - { 0x85, LVL_2, 2048 }, - { 0x86, LVL_2, 512 }, - { 0x87, LVL_2, 1024 }, - { 0x00, 0, 0} -}; - static void __init init_intel(struct cpuinfo_x86 *c) { /* Cache sizes */ - unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; unsigned n; - if (c->cpuid_level > 1) { - /* supports eax=2 call */ - int i, j, n; - int regs[4]; - unsigned char *dp = (unsigned char *)regs; - - /* Number of times to iterate */ - n = cpuid_eax(2) & 0xFF; - - for ( i = 0 ; i < n ; i++ ) { - cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); - - /* If bit 31 is set, this is an unknown format */ - for ( j = 0 ; j < 3 ; j++ ) { - if ( regs[j] < 0 ) regs[j] = 0; - } - - /* Byte 0 is level count, not a descriptor */ - for ( j = 1 ; j < 16 ; j++ ) { - unsigned char des = dp[j]; - unsigned char k = 0; - - /* look up this descriptor in the table */ - while (cache_table[k].descriptor != 0) - { - if (cache_table[k].descriptor == des) { - switch (cache_table[k].cache_type) { - case LVL_1_INST: - l1i += cache_table[k].size; - break; - case LVL_1_DATA: - l1d += cache_table[k].size; - break; - case LVL_2: - l2 += cache_table[k].size; - break; - case LVL_3: - l3 += cache_table[k].size; - break; - case LVL_TRACE: - trace += cache_table[k].size; - break; - } - - break; - } - - k++; - } - } - } - - if (trace) - printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); - else if (l1i) - printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); - if (l1d) - printk(", L1 D cache: %dK\n", l1d); - else - printk("\n"); - if (l2) - printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); - if (l3) - printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); - - c->x86_cache_size = l2 ? l2 : (l1i+l1d); - } - + init_intel_cacheinfo(c); n = cpuid_eax(0x80000000); if (n >= 0x80000008) { unsigned eax = cpuid_eax(0x80000008); @@ -885,6 +803,8 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) c->x86_model_id[0] = '\0'; /* Unset */ c->x86_clflush_size = 64; c->x86_cache_alignment = c->x86_clflush_size; + c->x86_num_cores = 1; + c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data; memset(&c->x86_capability, 0, sizeof c->x86_capability); /* Get vendor name */ @@ -912,6 +832,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c) } if (c->x86_capability[0] & (1<<19)) c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; + c->x86_apicid = misc >> 24; } else { /* Have CPUID level 0 only - unheard of */ c->x86 = 4; @@ -931,8 +852,10 @@ void __init identify_cpu(struct cpuinfo_x86 *c) /* AMD-defined flags: level 0x80000001 */ xlvl = cpuid_eax(0x80000000); if ( (xlvl & 0xffff0000) == 0x80000000 ) { - if ( xlvl >= 0x80000001 ) + if ( xlvl >= 0x80000001 ) { c->x86_capability[1] = cpuid_edx(0x80000001); + c->x86_capability[5] = cpuid_ecx(0x80000001); + } if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } @@ -985,7 +908,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c) boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } +#ifdef CONFIG_X86_MCE mcheck_init(c); +#endif } @@ -1024,10 +949,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, /* AMD-defined */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL, - NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -1042,10 +967,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", - "est", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL, + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* AMD-defined (#2) */ + "lahf_lm", "htvalid", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static char *x86_power_flags[] = { "ts", /* temperature sensor */ @@ -1086,7 +1017,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_X86_HT - if (cpu_has_ht) { + if (smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", phys_proc_id[c - cpu_data]); seq_printf(m, "siblings\t: %d\n", smp_num_siblings); } @@ -1132,6 +1063,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) } } + if (c->x86_num_cores > 1) + seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); + seq_printf(m, "\n\n"); return 0; diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 9d3137a55..370093376 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -11,11 +11,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -43,78 +43,27 @@ char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); unsigned long __supported_pte_mask = ~0UL; static int do_not_nx __initdata = 0; -unsigned long vm_stack_flags = __VM_STACK_FLAGS; -unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; -unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; -unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; -unsigned long vm_force_exec32 = PROT_EXEC; /* noexec=on|off Control non executable mappings for 64bit processes. -on Enable +on Enable(default) off Disable -noforce (default) Don't enable by default for heap/stack/data, - but allow PROT_EXEC to be effective - */ static int __init nonx_setup(char *str) { - if (!strncmp(str, "on",3)) { + if (!strcmp(str, "on")) { __supported_pte_mask |= _PAGE_NX; do_not_nx = 0; - vm_data_default_flags &= ~VM_EXEC; - vm_stack_flags &= ~VM_EXEC; - } else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { - do_not_nx = (str[0] == 'o'); - if (do_not_nx) - __supported_pte_mask &= ~_PAGE_NX; - vm_data_default_flags |= VM_EXEC; - vm_stack_flags |= VM_EXEC; + } else if (!strcmp(str, "off")) { + do_not_nx = 1; + __supported_pte_mask &= ~_PAGE_NX; } return 1; } __setup("noexec=", nonx_setup); -/* noexec32=opt{,opt} - -Control the no exec default for 32bit processes. Can be also overwritten -per executable using ELF header flags (e.g. needed for the X server) -Requires noexec=on or noexec=noforce to be effective. - -Valid options: - all,on Heap,stack,data is non executable. - off (default) Heap,stack,data is executable - stack Stack is non executable, heap/data is. - force Don't imply PROT_EXEC for PROT_READ - compat (default) Imply PROT_EXEC for PROT_READ - -*/ - static int __init nonx32_setup(char *str) - { - char *s; - while ((s = strsep(&str, ",")) != NULL) { - if (!strcmp(s, "all") || !strcmp(s,"on")) { - vm_data_default_flags32 &= ~VM_EXEC; - vm_stack_flags32 &= ~VM_EXEC; - } else if (!strcmp(s, "off")) { - vm_data_default_flags32 |= VM_EXEC; - vm_stack_flags32 |= VM_EXEC; - } else if (!strcmp(s, "stack")) { - vm_data_default_flags32 |= VM_EXEC; - vm_stack_flags32 &= ~VM_EXEC; - } else if (!strcmp(s, "force")) { - vm_force_exec32 = 0; - } else if (!strcmp(s, "compat")) { - vm_force_exec32 = PROT_EXEC; - } - } - return 1; -} - -__setup("noexec32=", nonx32_setup); - /* * Great future plan: * Declare PDA itself and support (irqstack,tss,pml4) as per cpu data. @@ -193,7 +142,8 @@ void pda_init(int cpu) char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ] __attribute__((section(".bss.page_aligned"))); -void __init syscall_init(void) +/* May not be marked __init: used by software suspend */ +void syscall_init(void) { /* * LSTAR and STAR live in a bit strange symbiosis. @@ -235,10 +185,11 @@ void __init cpu_init (void) #else int cpu = smp_processor_id(); #endif - struct tss_struct * t = &init_tss[cpu]; + struct tss_struct *t = &per_cpu(init_tss, cpu); unsigned long v; char *estacks = NULL; struct task_struct *me; + int i; /* CPU 0 is initialised in head64.c */ if (cpu != 0) { @@ -265,8 +216,8 @@ void __init cpu_init (void) cpu_gdt_descr[cpu].size = GDT_SIZE; cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu]; - __asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu])); - __asm__ __volatile__("lidt %0": "=m" (idt_descr)); + asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu])); + asm volatile("lidt %0" :: "m" (idt_descr)); memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8); @@ -302,12 +253,13 @@ void __init cpu_init (void) t->ist[v] = (unsigned long)estacks; } - t->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; + t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap); /* - * This is required because the CPU will access up to + * <= is required because the CPU will access up to * 8 bits beyond the end of the IO permission bitmap. */ - t->io_bitmap[IO_BITMAP_LONGS] = ~0UL; + for (i = 0; i <= IO_BITMAP_LONGS; i++) + t->io_bitmap[i] = ~0UL; atomic_inc(&init_mm.mm_count); me->active_mm = &init_mm; diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index f6eb0e337..e9aa2ca0b 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -40,7 +40,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs); asmlinkage long -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs regs) +sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) { sigset_t saveset, newset; @@ -59,21 +59,22 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs re spin_unlock_irq(¤t->sighand->siglock); #ifdef DEBUG_SIG printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n", - saveset, newset, ®s, regs.rip); + saveset, newset, regs, regs->rip); #endif - regs.rax = -EINTR; + regs->rax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(®s, &saveset)) + if (do_signal(regs, &saveset)) return -EINTR; } } asmlinkage long -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs regs) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + struct pt_regs *regs) { - return do_sigaltstack(uss, uoss, regs.rsp); + return do_sigaltstack(uss, uoss, regs->rsp); } @@ -134,13 +135,13 @@ badframe: return 1; } -asmlinkage long sys_rt_sigreturn(struct pt_regs regs) +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; long eax; - frame = (struct rt_sigframe __user *)(regs.rsp - 8); + frame = (struct rt_sigframe __user *)(regs->rsp - 8); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { goto badframe; } @@ -154,7 +155,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs regs) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &eax)) { + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) { goto badframe; } @@ -162,13 +163,13 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs regs) printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax); #endif - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs.rsp) == -EFAULT) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->rsp) == -EFAULT) goto badframe; return eax; badframe: - signal_fault(®s,frame,"sigreturn"); + signal_fault(regs,frame,"sigreturn"); return 0; } @@ -180,6 +181,7 @@ static inline int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) { int err = 0; + unsigned long eflags; err |= __put_user(0, &sc->gs); err |= __put_user(0, &sc->fs); @@ -203,7 +205,11 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo err |= __put_user(me->thread.trap_no, &sc->trapno); err |= __put_user(me->thread.error_code, &sc->err); err |= __put_user(regs->rip, &sc->rip); - err |= __put_user(regs->eflags, &sc->eflags); + eflags = regs->eflags; + if (current->ptrace & PT_PTRACED) { + eflags &= ~TF_MASK; + } + err |= __put_user(eflags, &sc->eflags); err |= __put_user(mask, &sc->oldmask); err |= __put_user(me->thread.cr2, &sc->cr2); @@ -287,7 +293,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (ka->sa.sa_flags & SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { - printk("%s forgot to set SA_RESTORER for signal %d.\n", me->comm, sig); + /* could use a vstub here */ goto give_sigsegv; } @@ -318,7 +324,13 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->rsp = (unsigned long)frame; set_fs(USER_DS); - regs->eflags &= ~TF_MASK; + if (regs->eflags & TF_MASK) { + if ((current->ptrace & (PT_PTRACED | PT_DTRACE)) == (PT_PTRACED | PT_DTRACE)) { + ptrace_notify(SIGTRAP); + } else { + regs->eflags &= ~TF_MASK; + } + } #ifdef DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", @@ -328,9 +340,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs,frame,"signal deliver"); + force_sigsegv(sig, current); } /* @@ -338,18 +348,16 @@ give_sigsegv: */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - #ifdef DEBUG_SIG printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, regs->rip, regs->rsp, regs); #endif /* Are we from a system call? */ - if (regs->orig_rax >= 0) { + if ((long)regs->orig_rax >= 0) { /* If so, check system call restarting.. */ switch (regs->rax) { case -ERESTART_RESTARTBLOCK: @@ -379,9 +387,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, #endif setup_rt_frame(sig, ka, info, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -398,6 +403,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, */ int do_signal(struct pt_regs *regs, sigset_t *oldset) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -419,7 +425,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will @@ -430,13 +436,13 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7)); /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } no_signal: /* Did we come from a system call? */ - if (regs->orig_rax >= 0) { + if ((long)regs->orig_rax >= 0) { /* Restart the system call - no handlers present */ long res = regs->rax; if (res == -ERESTARTNOHAND || diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 409460ebc..4b70f27b8 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -24,105 +24,7 @@ #include #include #include - -/* - * the following functions deal with sending IPIs between CPUs. - * - * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. - */ - -static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector) -{ - unsigned int icr = APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; - if (vector == KDB_VECTOR) - icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI; - return icr; -} - -static inline int __prepare_ICR2 (unsigned int mask) -{ - return SET_APIC_DEST_FIELD(mask); -} - -static inline void __send_IPI_shortcut(unsigned int shortcut, int vector) -{ - /* - * Subtle. In the case of the 'never do double writes' workaround - * we have to lock out interrupts to be safe. As we don't care - * of the value read we use an atomic rmw access to avoid costly - * cli/sti. Otherwise we use an even cheaper single atomic write - * to the APIC. - */ - unsigned int cfg; - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - /* - * No need to touch the target chip field - */ - cfg = __prepare_ICR(shortcut, vector); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); -} - -static inline void send_IPI_allbutself(int vector) -{ - /* - * if there are no other CPUs in the system then - * we get an APIC send error if we try to broadcast. - * thus we have to avoid sending IPIs in this case. - */ - if (num_online_cpus() > 1) - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector); -} - -static inline void send_IPI_all(int vector) -{ - __send_IPI_shortcut(APIC_DEST_ALLINC, vector); -} - -void send_IPI_self(int vector) -{ - __send_IPI_shortcut(APIC_DEST_SELF, vector); -} - -static inline void send_IPI_mask(cpumask_t cpumask, int vector) -{ - unsigned long mask = cpus_addr(cpumask)[0]; - unsigned long cfg; - unsigned long flags; - - local_save_flags(flags); - local_irq_disable(); - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - /* - * prepare target chip field - */ - cfg = __prepare_ICR2(mask); - apic_write_around(APIC_ICR2, cfg); - - /* - * program the ICR - */ - cfg = __prepare_ICR(0, vector); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); - local_irq_restore(flags); -} +#include /* * Smarter SMP flushing macros. @@ -382,30 +284,14 @@ static struct call_data_struct * call_data; * this function sends a 'generic call function' IPI to all other CPUs * in the system. */ - -int smp_call_function (void (*func) (void *info), void *info, int nonatomic, - int wait) -/* - * [SUMMARY] Run a function on all other CPUs. - * The function to run. This must be fast and non-blocking. - * An arbitrary pointer to pass to the function. - * currently unused. - * If true, wait (atomically) until function has completed on other CPUs. - * [RETURNS] 0 on success, else a negative status code. Does not return until - * remote CPUs are nearly ready to execute <> or are or have executed. - * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ +static void __smp_call_function (void (*func) (void *info), void *info, + int nonatomic, int wait) { struct call_data_struct data; int cpus = num_online_cpus()-1; if (!cpus) - return 0; - - /* Can deadlock when called with interrupts disabled */ - WARN_ON(irqs_disabled()); + return; data.func = func; data.info = info; @@ -414,7 +300,6 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, if (wait) atomic_set(&data.finished, 0); - spin_lock(&call_lock); call_data = &data; wmb(); /* Send a message to all other CPUs and wait for them to respond */ @@ -422,13 +307,36 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, /* Wait for response */ while (atomic_read(&data.started) != cpus) - barrier(); + cpu_relax(); - if (wait) - while (atomic_read(&data.finished) != cpus) - barrier(); - spin_unlock(&call_lock); + if (!wait) + return; + while (atomic_read(&data.finished) != cpus) + cpu_relax(); +} + +/* + * smp_call_function - run a function on all other CPUs. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: currently unused. + * @wait: If true, wait (atomically) until function has completed on other + * CPUs. + * + * Returns 0 on success, else a negative status code. Does not return until + * remote CPUs are nearly ready to execute func or are or have executed. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + * Actually there are a few legal cases, like panic. + */ +int smp_call_function (void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + spin_lock(&call_lock); + __smp_call_function(func,info,nonatomic,wait); + spin_unlock(&call_lock); return 0; } @@ -452,7 +360,15 @@ static void smp_really_stop_cpu(void *dummy) void smp_send_stop(void) { - smp_call_function(smp_really_stop_cpu, NULL, 1, 0); + int nolock = 0; + /* Don't deadlock on the call lock in panic */ + if (!spin_trylock(&call_lock)) { + /* ignore locking because we have paniced anyways */ + nolock = 1; + } + __smp_call_function(smp_really_stop_cpu, NULL, 0, 0); + if (!nolock) + spin_unlock(&call_lock); smp_stop_cpu(); } diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 29f2578bf..1d8dc1840 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -55,14 +56,12 @@ /* Number of siblings per CPU package */ int smp_num_siblings = 1; -char phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ +/* Package ID of each logical CPU */ +u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map; -/* which logical CPU number maps to which CPU (physical APIC ID) */ -volatile char x86_cpu_to_apicid[NR_CPUS]; - static cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; static cpumask_t smp_commenced_mask; @@ -390,16 +389,6 @@ void __init start_secondary(void) extern volatile unsigned long init_rsp; extern void (*initial_code)(void); -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #if APIC_DEBUG static inline void inquire_remote_apic(int apicid) { @@ -573,26 +562,17 @@ static void __init do_boot_cpu (int apicid) * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(idle); x86_cpu_to_apicid[cpu] = apicid; - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle,cpu); - - unhash_process(idle); - cpu_pda[cpu].pcurrent = idle; start_rip = setup_trampoline(); init_rsp = idle->thread.rsp; - init_tss[cpu].rsp0 = init_rsp; + per_cpu(init_tss,cpu).rsp0 = init_rsp; initial_code = start_secondary; clear_ti_thread_flag(idle->thread_info, TIF_FORK); @@ -675,6 +655,8 @@ static void __init do_boot_cpu (int apicid) cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */ clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */ cpucount--; + x86_cpu_to_apicid[cpu] = BAD_APICID; + x86_cpu_to_log_apicid[cpu] = BAD_APICID; } } @@ -967,6 +949,9 @@ int __devinit __cpu_up(unsigned int cpu) void __init smp_cpus_done(unsigned int max_cpus) { +#ifdef CONFIG_X86_IO_APIC + setup_ioapic_dest(); +#endif zap_low_mappings(); } diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index 751982df5..ebaa1e37d 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c @@ -129,7 +129,7 @@ void restore_processor_state(void) void fix_processor_context(void) { int cpu = smp_processor_id(); - struct tss_struct * t = init_tss + cpu; + struct tss_struct *t = &per_cpu(init_tss, cpu); set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S index 99a1adf86..8a3999810 100644 --- a/arch/x86_64/kernel/suspend_asm.S +++ b/arch/x86_64/kernel/suspend_asm.S @@ -1,22 +1,18 @@ -/* originally gcc generated, but now changed. don't overwrite. */ +/* Originally gcc generated, modified by hand + * + * This may not use any stack, nor any variable that is not "NoSave": + * + * Its rewriting one kernel image with another. What is stack in "old" + * image could very well be data page in "new" image, and overwriting + * your own stack under you is bad idea. + */ .text #include #include #include -/* Input: - * rdi resume flag - */ - -ENTRY(do_magic) -.LFB5: - subq $8, %rsp -.LCFI2: - testl %edi, %edi - jne .L90 - call do_magic_suspend_1 - call save_processor_state +ENTRY(swsusp_arch_suspend) movq %rsp, saved_context_esp(%rip) movq %rax, saved_context_eax(%rip) @@ -36,36 +32,35 @@ ENTRY(do_magic) movq %r15, saved_context_r15(%rip) pushfq ; popq saved_context_eflags(%rip) - addq $8, %rsp - jmp do_magic_suspend_2 -.L90: + call swsusp_save + ret + +ENTRY(swsusp_arch_resume) /* set up cr3 */ leaq init_level4_pgt(%rip),%rax subq $__START_KERNEL_map,%rax - movq %rax,%cr3 + movq %rax,%cr3 movq mmu_cr4_features(%rip), %rax movq %rax, %rdx - andq $~(1<<7), %rdx # PGE - movq %rdx, %cr4; # turn off PGE - movq %cr3, %rcx; # flush TLB - movq %rcx, %cr3; - movq %rax, %cr4; # turn PGE back on + movq %rdx, %cr4; # turn off PGE + movq %cr3, %rcx; # flush TLB + movq %rcx, %cr3; + movq %rax, %cr4; # turn PGE back on - call do_magic_resume_1 movl nr_copy_pages(%rip), %eax xorl %ecx, %ecx - movq $0, loop(%rip) + movq $0, %r10 testl %eax, %eax - je .L108 + jz done .L105: xorl %esi, %esi - movq $0, loop2(%rip) + movq $0, %r11 jmp .L104 .p2align 4,,7 -.L111: - movq loop(%rip), %rcx +copy_one_page: + movq %r10, %rcx .L104: movq pagedir_nosave(%rip), %rdx movq %rcx, %rax @@ -75,27 +70,26 @@ ENTRY(do_magic) movzbl (%rsi,%rax), %eax movb %al, (%rsi,%rcx) - movq %cr3, %rax; # flush TLB - movq %rax, %cr3; + movq %cr3, %rax; # flush TLB + movq %rax, %cr3; - movq loop2(%rip), %rax + movq %r11, %rax incq %rax cmpq $4095, %rax movq %rax, %rsi - movq %rax, loop2(%rip) - jbe .L111 - movq loop(%rip), %rax + movq %rax, %r11 + jbe copy_one_page + movq %r10, %rax incq %rax movq %rax, %rcx - movq %rax, loop(%rip) + movq %rax, %r10 mov nr_copy_pages(%rip), %eax cmpq %rax, %rcx jb .L105 -.L108: - .align 4 +done: movl $24, %eax + movl %eax, %ds - movl %eax, %ds movq saved_context_esp(%rip), %rsp movq saved_context_ebp(%rip), %rbp movq saved_context_eax(%rip), %rax @@ -113,13 +107,5 @@ ENTRY(do_magic) movq saved_context_r14(%rip), %r14 movq saved_context_r15(%rip), %r15 pushq saved_context_eflags(%rip) ; popfq - call restore_processor_state - addq $8, %rsp - jmp do_magic_resume_2 - - .section .data.nosave -loop: - .quad 0 -loop2: - .quad 0 - .previous + call swsusp_restore + ret diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 10c511f50..12b5549c0 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -11,7 +11,6 @@ * Copyright (c) 2002 Vojtech Pavlik * Copyright (c) 2003 Andi Kleen * RTC support code taken from arch/i386/kernel/timers/time_hpet.c - * */ #include @@ -33,7 +32,9 @@ #include #include #include +#include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #endif @@ -42,16 +43,20 @@ u64 jiffies_64 = INITIAL_JIFFIES; EXPORT_SYMBOL(jiffies_64); +#ifdef CONFIG_CPU_FREQ +static void cpufreq_delayed_get(void); +#endif + extern int using_apic_timer; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; static int nohpet __initdata = 0; +static int notsc __initdata = 0; #undef HPET_HACK_ENABLE_DANGEROUS - unsigned int cpu_khz; /* TSC clocks / usec, not used here */ unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* HPET clocks / interrupt */ @@ -82,7 +87,7 @@ static inline void rdtscll_sync(unsigned long *tsc) * timer interrupt has happened already, but vxtime.trigger wasn't updated yet. * This is not a problem, because jiffies hasn't updated either. They are bound * together by xtime_lock. - */ + */ static inline unsigned int do_gettimeoffset_tsc(void) { @@ -119,7 +124,7 @@ void do_gettimeofday(struct timeval *tv) usec = xtime.tv_nsec / 1000; /* i386 does some correction here to keep the clock - monotonus even when ntpd is fixing drift. + monotonous even when ntpd is fixing drift. But they didn't work for me, there is a non monotonic clock anyways with ntp. I dropped all corrections now until a real solution can @@ -176,6 +181,28 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); +unsigned long profile_pc(struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + + /* Assume the lock function has either no stack frame or only a single word. + This checks if the address on the stack looks like a kernel text address. + There is a small window for false hits, but in that case the tick + is just accounted to the spinlock function. + Better would be to write these functions in assembler again + and check exactly. */ + if (in_lock_functions(pc)) { + char *v = *(char **)regs->rsp; + if ((v >= _stext && v <= _etext) || + (v >= _sinittext && v <= _einittext) || + (v >= (char *)MODULES_VADDR && v <= (char *)MODULES_END)) + return (unsigned long)v; + return ((unsigned long *)regs->rsp)[1]; + } + return pc; +} +EXPORT_SYMBOL(profile_pc); + /* * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500 * ms after the second nowtime has started, because when nowtime is written @@ -214,7 +241,7 @@ static void set_rtc_mmss(unsigned long nowtime) * overflow. This avoids messing with unknown time zones but requires your RTC * not to be off by more than 15 minutes. Since we're calling it only when * our clock is externally synchronized using NTP, this shouldn't be a problem. - */ + */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; @@ -293,19 +320,56 @@ unsigned long long monotonic_clock(void) } EXPORT_SYMBOL(monotonic_clock); +static noinline void handle_lost_ticks(int lost, struct pt_regs *regs) +{ + static long lost_count; + static int warned; + + if (report_lost_ticks) { + printk(KERN_WARNING "time.c: Lost %d timer " + "tick(s)! ", lost); + print_symbol("rip %s)\n", regs->rip); + } + + if (lost_count == 1000 && !warned) { + printk(KERN_WARNING + "warning: many lost ticks.\n" + KERN_WARNING "Your time source seems to be instable or " + "some driver is hogging interupts\n"); + print_symbol("rip %s\n", regs->rip); + if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) { + printk(KERN_WARNING "Falling back to HPET\n"); + vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; + vxtime.mode = VXTIME_HPET; + do_gettimeoffset = do_gettimeoffset_hpet; + } + /* else should fall back to PIT, but code missing. */ + warned = 1; + } else + lost_count++; + +#ifdef CONFIG_CPU_FREQ + /* In some cases the CPU can change frequency without us noticing + (like going into thermal throttle) + Give cpufreq a change to catch up. */ + if ((lost_count+1) % 25 == 0) { + cpufreq_delayed_get(); + } +#endif +} static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { static unsigned long rtc_update = 0; - unsigned long tsc, lost = 0; - int delay, offset = 0; + unsigned long tsc; + int delay, offset = 0, lost = 0; /* * Here we are in the timer irq handler. We have irqs locally disabled (so we * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running * on the other CPU, so we need a lock. We also need to lock the vsyscall * variables, because both do_timer() and us change them -arca+vojtech - */ + */ write_seqlock(&xtime_lock); @@ -354,12 +418,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) (((long) offset << 32) / vxtime.tsc_quot) - 1; } - if (lost) { - if (report_lost_ticks) { - printk(KERN_WARNING "time.c: Lost %ld timer " - "tick(s)! ", lost); - print_symbol("rip %s)\n", regs->rip); - } + if (lost > 0) { + handle_lost_ticks(lost, regs); jiffies += lost; } @@ -368,6 +428,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif /* * In the SMP case we use the local APIC timer interrupt to do the profiling, @@ -376,7 +439,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ #ifndef CONFIG_X86_LOCAL_APIC - x86_do_profile(regs); + profile_tick(CPU_PROFILING, regs); #else if (!using_apic_timer) smp_local_timer_interrupt(regs); @@ -509,6 +572,38 @@ unsigned long get_cmos_time(void) Should fix up last_tsc too. Currently gettimeofday in the first tick after the change will be slightly wrong. */ +#include + +static unsigned int cpufreq_delayed_issched = 0; +static unsigned int cpufreq_init = 0; +static struct work_struct cpufreq_delayed_get_work; + +static void handle_cpufreq_delayed_get(void *v) +{ + unsigned int cpu; + for_each_online_cpu(cpu) { + cpufreq_get(cpu); + } + cpufreq_delayed_issched = 0; +} + +/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries + * to verify the CPU frequency the timing core thinks the CPU is running + * at is still correct. + */ +static void cpufreq_delayed_get(void) +{ + static int warned; + if (cpufreq_init && !cpufreq_delayed_issched) { + cpufreq_delayed_issched = 1; + if (!warned) { + warned = 1; + printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n"); + } + schedule_work(&cpufreq_delayed_get_work); + } +} + static unsigned int ref_freq = 0; static unsigned long loops_per_jiffy_ref = 0; @@ -518,14 +613,18 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_freqs *freq = data; - unsigned long *lpj; + unsigned long *lpj, dummy; + lpj = &dummy; + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) #ifdef CONFIG_SMP lpj = &cpu_data[freq->cpu].loops_per_jiffy; #else lpj = &boot_cpu_data.loops_per_jiffy; #endif + + if (!ref_freq) { ref_freq = freq->old; loops_per_jiffy_ref = *lpj; @@ -538,7 +637,8 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); - vxtime.tsc_quot = (1000L << 32) / cpu_khz; + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) + vxtime.tsc_quot = (1000L << 32) / cpu_khz; } set_cyc2ns_scale(cpu_khz_ref / 1000); @@ -549,6 +649,18 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, static struct notifier_block time_cpufreq_notifier_block = { .notifier_call = time_cpufreq_notifier }; + +static int __init cpufreq_tsc(void) +{ + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER)) + cpufreq_init = 1; + return 0; +} + +core_initcall(cpufreq_tsc); + #endif /* @@ -615,31 +727,59 @@ static unsigned int __init pit_calibrate_tsc(void) return (end - start) / 50; } -static int hpet_init(void) +#ifdef CONFIG_HPET +static __init int late_hpet_init(void) { - unsigned int cfg, id; + struct hpet_data hd; + unsigned int ntimer; if (!vxtime.hpet_address) - return -1; - set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address); - __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); + return -1; -/* - * Read the period, compute tick and quotient. - */ + memset(&hd, 0, sizeof (hd)); - id = hpet_readl(HPET_ID); + ntimer = hpet_readl(HPET_ID); + ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; + ntimer++; - if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) || - !(id & HPET_ID_LEGSUP)) - return -1; + /* + * Register with driver. + * Timer0 and Timer1 is used by platform. + */ + hd.hd_phys_address = vxtime.hpet_address; + hd.hd_address = (void *)fix_to_virt(FIX_HPET_BASE); + hd.hd_nirqs = ntimer; + hd.hd_flags = HPET_DATA_PLATFORM; + hpet_reserve_timer(&hd, 0); +#ifdef CONFIG_HPET_EMULATE_RTC + hpet_reserve_timer(&hd, 1); +#endif + hd.hd_irq[0] = HPET_LEGACY_8254; + hd.hd_irq[1] = HPET_LEGACY_RTC; + if (ntimer > 2) { + struct hpet *hpet; + struct hpet_timer *timer; + int i; - hpet_period = hpet_readl(HPET_PERIOD); - if (hpet_period < 100000 || hpet_period > 100000000) - return -1; + hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE); - hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) / - hpet_period; + for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer; + timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & + Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; + + } + + hpet_alloc(&hd); + return 0; +} +fs_initcall(late_hpet_init); +#endif + +static int hpet_timer_stop_set_go(unsigned long tick) +{ + unsigned int cfg; /* * Stop the timers and reset the main counter. @@ -671,6 +811,40 @@ static int hpet_init(void) return 0; } +static int hpet_init(void) +{ + unsigned int id; + + if (!vxtime.hpet_address) + return -1; + set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address); + __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); + +/* + * Read the period, compute tick and quotient. + */ + + id = hpet_readl(HPET_ID); + + if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) || + !(id & HPET_ID_LEGSUP)) + return -1; + + hpet_period = hpet_readl(HPET_PERIOD); + if (hpet_period < 100000 || hpet_period > 100000000) + return -1; + + hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) / + hpet_period; + + return hpet_timer_stop_set_go(hpet_tick); +} + +static int hpet_reenable(void) +{ + return hpet_timer_stop_set_go(hpet_tick); +} + void __init pit_init(void) { unsigned long flags; @@ -705,9 +879,9 @@ void __init time_init(void) outl(0x800038a0, 0xcf8); outl(0xff000001, 0xcfc); outl(0x800038a0, 0xcf8); - hpet_address = inl(0xcfc) & 0xfffffffe; + vxtime.hpet_address = inl(0xcfc) & 0xfffffffe; printk(KERN_WARNING "time.c: WARNING: Enabled HPET " - "at %#lx.\n", hpet_address); + "at %#lx.\n", vxtime.hpet_address); } #endif if (nohpet) @@ -725,8 +899,8 @@ void __init time_init(void) cpu_khz = hpet_calibrate_tsc(); timename = "HPET"; } else { - pit_init(); - cpu_khz = pit_calibrate_tsc(); + pit_init(); + cpu_khz = pit_calibrate_tsc(); timename = "PIT"; } @@ -742,26 +916,40 @@ void __init time_init(void) setup_irq(0, &irq0); set_cyc2ns_scale(cpu_khz / 1000); - -#ifdef CONFIG_CPU_FREQ - cpufreq_register_notifier(&time_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); -#endif } void __init time_init_smp(void) { char *timetype; - if (vxtime.hpet_address) { + /* + * AMD systems with more than one CPU don't have fully synchronized + * TSCs. Always use HPET gettimeofday for these, although it is slower. + * Intel SMP systems usually have synchronized TSCs, so use always + * the TSC. + * + * Exceptions: + * IBM Summit2 checked by oem_force_hpet_timer(). + * AMD dual core may also not need HPET. Check me. + * + * Can be turned off with "notsc". + */ + if (num_online_cpus() > 1 && + boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + notsc = 1; + /* Some systems will want to disable TSC and use HPET. */ + if (oem_force_hpet_timer()) + notsc = 1; + if (vxtime.hpet_address && notsc) { timetype = "HPET"; vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick; vxtime.mode = VXTIME_HPET; do_gettimeoffset = do_gettimeoffset_hpet; } else { - timetype = "PIT/TSC"; + timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC"; vxtime.mode = VXTIME_TSC; } + printk(KERN_INFO "time.c: Using %s based timekeeping.\n", timetype); } @@ -769,7 +957,7 @@ __setup("report_lost_ticks", time_setup); static long clock_cmos_diff; -static int time_suspend(struct sys_device *dev, u32 state) +static int timer_suspend(struct sys_device *dev, u32 state) { /* * Estimate time zone so that set_time can update the clock @@ -779,34 +967,40 @@ static int time_suspend(struct sys_device *dev, u32 state) return 0; } -static int time_resume(struct sys_device *dev) +static int timer_resume(struct sys_device *dev) { - unsigned long sec = get_cmos_time() + clock_cmos_diff; - write_seqlock_irq(&xtime_lock); + unsigned long flags; + unsigned long sec; + + if (vxtime.hpet_address) + hpet_reenable(); + + sec = get_cmos_time() + clock_cmos_diff; + write_seqlock_irqsave(&xtime_lock,flags); xtime.tv_sec = sec; xtime.tv_nsec = 0; - write_sequnlock_irq(&xtime_lock); + write_sequnlock_irqrestore(&xtime_lock,flags); return 0; } -static struct sysdev_class pit_sysclass = { - .resume = time_resume, - .suspend = time_suspend, - set_kset_name("pit"), +static struct sysdev_class timer_sysclass = { + .resume = timer_resume, + .suspend = timer_suspend, + set_kset_name("timer"), }; /* XXX this driverfs stuff should probably go elsewhere later -john */ -static struct sys_device device_i8253 = { +static struct sys_device device_timer = { .id = 0, - .cls = &pit_sysclass, + .cls = &timer_sysclass, }; static int time_init_device(void) { - int error = sysdev_class_register(&pit_sysclass); + int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sysdev_register(&device_i8253); + error = sysdev_register(&device_timer); return error; } @@ -1038,6 +1232,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) } #endif + + static int __init nohpet_setup(char *s) { nohpet = 1; @@ -1045,3 +1241,14 @@ static int __init nohpet_setup(char *s) } __setup("nohpet", nohpet_setup); + + +static int __init notsc_setup(char *s) +{ + notsc = 1; + return 0; +} + +__setup("notsc", notsc_setup); + + diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 99d0ec2ab..50e9621b0 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -43,9 +43,11 @@ #include #include #include +#include #include + extern struct gate_struct idt_table[256]; asmlinkage void divide_error(void); @@ -72,6 +74,17 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void call_debug(void); struct notifier_block *die_chain; +static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED; + +int register_die_notifier(struct notifier_block *nb) +{ + int err = 0; + unsigned long flags; + spin_lock_irqsave(&die_notifier_lock, flags); + err = notifier_chain_register(&die_chain, nb); + spin_unlock_irqrestore(&die_notifier_lock, flags); + return err; +} static inline void conditional_sti(struct pt_regs *regs) { @@ -110,9 +123,10 @@ unsigned long *in_exception_stack(int cpu, unsigned long stack) { int k; for (k = 0; k < N_EXCEPTION_STACKS; k++) { - unsigned long end = init_tss[cpu].ist[k] + EXCEPTION_STKSZ; + struct tss_struct *tss = &per_cpu(init_tss, cpu); + unsigned long end = tss->ist[k] + EXCEPTION_STKSZ; - if (stack >= init_tss[cpu].ist[k] && stack <= end) + if (stack >= tss->ist[k] && stack <= end) return (unsigned long *)end; } return NULL; @@ -352,7 +366,7 @@ void __die(const char * str, struct pt_regs * regs, long err) #ifdef CONFIG_DEBUG_PAGEALLOC printk("DEBUG_PAGEALLOC"); #endif - printk("\n"); + printk("\n"); notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); show_registers(regs); /* Executive summary in case the oops scrolled away */ @@ -375,6 +389,22 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e die(str, regs, err); } +void die_nmi(char *str, struct pt_regs *regs) +{ + oops_begin(); + /* + * We are in trouble anyway, lets at least try + * to get a message out. + */ + printk(str, safe_smp_processor_id()); + show_registers(regs); + if (panic_on_timeout || panic_on_oops) + panic("nmi watchdog"); + printk("console shuts up ...\n"); + oops_end(); + do_exit(SIGSEGV); +} + static inline unsigned long get_cr2(void) { unsigned long address; @@ -436,7 +466,8 @@ static void do_trap(int trapnr, int signr, char *str, #define DO_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ - if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ return; \ do_trap(trapnr, signr, str, regs, error_code, NULL); \ } @@ -449,13 +480,13 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ info.si_errno = 0; \ info.si_code = sicode; \ info.si_addr = (void __user *)siaddr; \ - if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ return; \ do_trap(trapnr, signr, str, regs, error_code, &info); \ } DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip) -DO_ERROR( 3, SIGTRAP, "int3", int3); DO_ERROR( 4, SIGSEGV, "overflow", overflow) DO_ERROR( 5, SIGSEGV, "bounds", bounds) DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip) @@ -463,14 +494,15 @@ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available) DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) -DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) +DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR(18, SIGSEGV, "reserved", reserved) #define DO_ERROR_STACK(trapnr, signr, str, name) \ asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \ { \ struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \ - if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ + == NOTIFY_STOP) \ return regs; \ if (regs->cs & 3) { \ memcpy(pr, regs, sizeof(struct pt_regs)); \ @@ -513,7 +545,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) tsk->thread.error_code = error_code; tsk->thread.trap_no = 13; force_sig(SIGSEGV, tsk); - return; + return; } /* kernel gp */ @@ -559,12 +591,17 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) printk("Do you have a strange power saving mode enabled?\n"); } -asmlinkage void default_do_nmi(struct pt_regs * regs) +asmlinkage void default_do_nmi(struct pt_regs *regs) { - unsigned char reason = inb(0x61); + unsigned char reason = 0; + + /* Only the BSP gets external NMIs from the system. */ + if (!smp_processor_id()) + reason = get_nmi_reason(); if (!(reason & 0xc0)) { - if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) == NOTIFY_BAD) + if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) + == NOTIFY_STOP) return; #ifdef CONFIG_X86_LOCAL_APIC /* @@ -579,8 +616,11 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) unknown_nmi_error(reason, regs); return; } - if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD) + if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP) return; + + /* AK: following checks seem to be broken on modern chipsets. FIXME */ + if (reason & 0x80) mem_parity_error(reason, regs); if (reason & 0x40) @@ -596,6 +636,15 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) inb(0x71); /* dummy */ } +asmlinkage void do_int3(struct pt_regs * regs, long error_code) +{ + if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { + return; + } + do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); + return; +} + /* runs on IST stack. */ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) { @@ -625,6 +674,10 @@ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) asm("movq %%db6,%0" : "=r" (condition)); + if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, + SIGTRAP) == NOTIFY_STOP) { + return regs; + } conditional_sti(regs); /* Mask out spurious debug traps due to lazy DR7 setting */ @@ -670,27 +723,53 @@ clear_dr7: return regs; clear_TF_reenable: - printk("clear_tf_reenable\n"); set_tsk_thread_flag(tsk, TIF_SINGLESTEP); clear_TF: /* RED-PEN could cause spurious errors */ if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) - != NOTIFY_BAD) + != NOTIFY_STOP) regs->eflags &= ~TF_MASK; return regs; } +static int kernel_math_error(struct pt_regs *regs, char *str) +{ + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->rip); + if (fixup) { + regs->rip = fixup->fixup; + return 1; + } + notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE); +#if 0 + /* This should be a die, but warn only for now */ + die(str, regs, 0); +#else + printk(KERN_DEBUG "%s: %s at ", current->comm, str); + printk_address(regs->rip); + printk("\n"); +#endif + return 0; +} + /* * Note that we play around with the 'TS' bit in an attempt to get * the correct behaviour even in the presence of the asynchronous * IRQ13 behaviour */ -void math_error(void __user *rip) +asmlinkage void do_coprocessor_error(struct pt_regs *regs) { + void __user *rip = (void __user *)(regs->rip); struct task_struct * task; siginfo_t info; unsigned short cwd, swd; + + conditional_sti(regs); + if ((regs->cs & 3) == 0 && + kernel_math_error(regs, "kernel x87 math error")) + return; + /* * Save the info for the exception handler and clear the error. */ @@ -740,23 +819,23 @@ void math_error(void __user *rip) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_coprocessor_error(struct pt_regs * regs) -{ - conditional_sti(regs); - math_error((void __user *)regs->rip); -} - asmlinkage void bad_intr(void) { printk("bad interrupt"); } -static inline void simd_math_error(void __user *rip) +asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) { + void __user *rip = (void __user *)(regs->rip); struct task_struct * task; siginfo_t info; unsigned short mxcsr; + conditional_sti(regs); + if ((regs->cs & 3) == 0 && + kernel_math_error(regs, "simd math error")) + return; + /* * Save the info for the exception handler and clear the error. */ @@ -799,12 +878,6 @@ static inline void simd_math_error(void __user *rip) force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs) -{ - conditional_sti(regs); - simd_math_error((void __user *)regs->rip); -} - asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) { } @@ -837,8 +910,8 @@ void __init trap_init(void) set_intr_gate(0,÷_error); set_intr_gate_ist(1,&debug,DEBUG_STACK); set_intr_gate_ist(2,&nmi,NMI_STACK); - set_system_gate(3,&int3); /* int3-5 can be called from all */ - set_system_gate(4,&overflow); + set_intr_gate(3,&int3); + set_system_gate(4,&overflow); /* int4-5 can be called from all */ set_system_gate(5,&bounds); set_intr_gate(6,&invalid_op); set_intr_gate(7,&device_not_available); @@ -852,7 +925,9 @@ void __init trap_init(void) set_intr_gate(15,&spurious_interrupt_bug); set_intr_gate(16,&coprocessor_error); set_intr_gate(17,&alignment_check); +#ifdef CONFIG_X86_MCE set_intr_gate_ist(18,&machine_check, MCE_STACK); +#endif set_intr_gate(19,&simd_coprocessor_error); #ifdef CONFIG_IA32_EMULATION @@ -875,3 +950,11 @@ static int __init oops_dummy(char *s) return -1; } __setup("oops=", oops_dummy); + +static int __init kstack_setup(char *s) +{ + kstack_depth_to_print = simple_strtoul(s,NULL,0); + return 0; +} +__setup("kstack=", kstack_setup); + diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index 21383547b..65108e17e 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -16,6 +16,7 @@ SECTIONS .text : { *(.text) SCHED_TEXT + LOCK_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 @@ -44,32 +45,31 @@ SECTIONS } __bss_end = .; - . = ALIGN(64); + . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); .data.cacheline_aligned : { *(.data.cacheline_aligned) } +#define AFTER(x) BINALIGN(LOADADDR(x) + SIZEOF(x), 16) +#define BINALIGN(x,y) (((x) + (y) - 1) & ~((y) - 1)) +#define CACHE_ALIGN(x) BINALIGN(x, CONFIG_X86_L1_CACHE_BYTES) + .vsyscall_0 -10*1024*1024: AT ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) { *(.vsyscall_0) } __vsyscall_0 = LOADADDR(.vsyscall_0); - . = ALIGN(64); - .xtime_lock : AT ((LOADADDR(.vsyscall_0) + SIZEOF(.vsyscall_0) + 63) & ~(63)) { *(.xtime_lock) } + . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); + .xtime_lock : AT CACHE_ALIGN(AFTER(.vsyscall_0)) { *(.xtime_lock) } xtime_lock = LOADADDR(.xtime_lock); - . = ALIGN(16); - .vxtime : AT ((LOADADDR(.xtime_lock) + SIZEOF(.xtime_lock) + 15) & ~(15)) { *(.vxtime) } + .vxtime : AT AFTER(.xtime_lock) { *(.vxtime) } vxtime = LOADADDR(.vxtime); - . = ALIGN(16); - .wall_jiffies : AT ((LOADADDR(.vxtime) + SIZEOF(.vxtime) + 15) & ~(15)) { *(.wall_jiffies) } + .wall_jiffies : AT AFTER(.vxtime) { *(.wall_jiffies) } wall_jiffies = LOADADDR(.wall_jiffies); - . = ALIGN(16); - .sys_tz : AT ((LOADADDR(.wall_jiffies) + SIZEOF(.wall_jiffies) + 15) & ~(15)) { *(.sys_tz) } + .sys_tz : AT AFTER(.wall_jiffies) { *(.sys_tz) } sys_tz = LOADADDR(.sys_tz); - . = ALIGN(16); - .sysctl_vsyscall : AT ((LOADADDR(.sys_tz) + SIZEOF(.sys_tz) + 15) & ~(15)) { *(.sysctl_vsyscall) } - sysctl_vsyscall = LOADADDR(.sysctl_vsyscall); - . = ALIGN(16); - .jiffies : AT ((LOADADDR(.sysctl_vsyscall) + SIZEOF(.sysctl_vsyscall) + 15) & ~(15)) { *(.jiffies) } - jiffies = LOADADDR(.jiffies); - . = ALIGN(16); - .xtime : AT ((LOADADDR(.jiffies) + SIZEOF(.jiffies) + 15) & ~(15)) { *(.xtime) } + .sysctl_vsyscall : AT AFTER(.sys_tz) { *(.sysctl_vsyscall) } + sysctl_vsyscall = LOADADDR(.sysctl_vsyscall); + .xtime : AT AFTER(.sysctl_vsyscall) { *(.xtime) } xtime = LOADADDR(.xtime); + . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); + .jiffies : AT CACHE_ALIGN(AFTER(.xtime)) { *(.jiffies) } + jiffies = LOADADDR(.jiffies); .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) } . = LOADADDR(.vsyscall_0) + 4096; @@ -86,14 +86,13 @@ SECTIONS *(.init.text) _einittext = .; } + __initdata_begin = .; .init.data : { *(.init.data) } + __initdata_end = .; . = ALIGN(16); __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index 13ec453e2..f28a07c77 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -88,7 +89,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv) __vxtime.tsc_quot) >> 32; /* See comment in x86_64 do_gettimeofday. */ } else { - usec += ((readl(fix_to_virt(VSYSCALL_HPET) + 0xf0) - + usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) - __vxtime.last) * __vxtime.quot) >> 32; } } while (read_seqretry(&__xtime_lock, sequence)); @@ -165,14 +166,12 @@ static void __init map_vsyscall(void) static int __init vsyscall_init(void) { - if ((unsigned long) &vgettimeofday != VSYSCALL_ADDR(__NR_vgettimeofday)) - panic("vgettimeofday link addr broken"); - if ((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime)) - panic("vtime link addr broken"); - if (VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)) - panic("fixmap first vsyscall %lx should be %lx", __fix_to_virt(VSYSCALL_FIRST_PAGE), - VSYSCALL_ADDR(0)); + BUG_ON(((unsigned long) &vgettimeofday != + VSYSCALL_ADDR(__NR_vgettimeofday))); + BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime)); + BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE))); map_vsyscall(); + sysctl_vsyscall = 1; return 0; } diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 1fb138482..032c0e238 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include extern spinlock_t rtc_lock; @@ -63,10 +63,10 @@ EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(get_cmos_time); -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); -EXPORT_SYMBOL_NOVERS(__down_failed_trylock); -EXPORT_SYMBOL_NOVERS(__up_wakeup); +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_failed_interruptible); +EXPORT_SYMBOL(__down_failed_trylock); +EXPORT_SYMBOL(__up_wakeup); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_nocheck); EXPORT_SYMBOL(ip_compute_csum); @@ -76,14 +76,14 @@ EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(__const_udelay); -EXPORT_SYMBOL_NOVERS(__get_user_1); -EXPORT_SYMBOL_NOVERS(__get_user_2); -EXPORT_SYMBOL_NOVERS(__get_user_4); -EXPORT_SYMBOL_NOVERS(__get_user_8); -EXPORT_SYMBOL_NOVERS(__put_user_1); -EXPORT_SYMBOL_NOVERS(__put_user_2); -EXPORT_SYMBOL_NOVERS(__put_user_4); -EXPORT_SYMBOL_NOVERS(__put_user_8); +EXPORT_SYMBOL(__get_user_1); +EXPORT_SYMBOL(__get_user_2); +EXPORT_SYMBOL(__get_user_4); +EXPORT_SYMBOL(__get_user_8); +EXPORT_SYMBOL(__put_user_1); +EXPORT_SYMBOL(__put_user_2); +EXPORT_SYMBOL(__put_user_4); +EXPORT_SYMBOL(__put_user_8); EXPORT_SYMBOL(strpbrk); EXPORT_SYMBOL(strstr); @@ -108,18 +108,15 @@ EXPORT_SYMBOL(pcibios_penalize_isa_irq); EXPORT_SYMBOL(pci_mem_start); #endif -#ifdef CONFIG_X86_USE_3DNOW -EXPORT_SYMBOL(_mmx_memcpy); -EXPORT_SYMBOL(mmx_clear_page); -EXPORT_SYMBOL(mmx_copy_page); -#endif +EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(cpu_pda); #ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL_NOVERS(__write_lock_failed); -EXPORT_SYMBOL_NOVERS(__read_lock_failed); +EXPORT_SYMBOL(__write_lock_failed); +EXPORT_SYMBOL(__read_lock_failed); EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(smp_call_function); @@ -164,36 +161,44 @@ extern void * __memcpy(void *,const void *,__kernel_size_t); extern char * strcat(char *, const char *); extern int memcmp(const void * cs,const void * ct,size_t count); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(strlen); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(strcpy); -EXPORT_SYMBOL_NOVERS(strncmp); -EXPORT_SYMBOL_NOVERS(strncpy); -EXPORT_SYMBOL_NOVERS(strchr); -EXPORT_SYMBOL_NOVERS(strcmp); -EXPORT_SYMBOL_NOVERS(strcat); -EXPORT_SYMBOL_NOVERS(strncat); -EXPORT_SYMBOL_NOVERS(memchr); -EXPORT_SYMBOL_NOVERS(strrchr); -EXPORT_SYMBOL_NOVERS(strnlen); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(__memcpy); -EXPORT_SYMBOL_NOVERS(memcmp); - -/* syscall export needed for misdesigned sound drivers. */ -EXPORT_SYMBOL(sys_read); -EXPORT_SYMBOL(sys_lseek); -EXPORT_SYMBOL(sys_open); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(memchr); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(__memcpy); +EXPORT_SYMBOL(memcmp); + +#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM +/* prototypes are wrong, these are assembly with custom calling functions */ +extern void rwsem_down_read_failed_thunk(void); +extern void rwsem_wake_thunk(void); +extern void rwsem_downgrade_thunk(void); +extern void rwsem_down_write_failed_thunk(void); +EXPORT_SYMBOL(rwsem_down_read_failed_thunk); +EXPORT_SYMBOL(rwsem_wake_thunk); +EXPORT_SYMBOL(rwsem_downgrade_thunk); +EXPORT_SYMBOL(rwsem_down_write_failed_thunk); +#endif EXPORT_SYMBOL(empty_zero_page); #ifdef CONFIG_HAVE_DEC_LOCK -EXPORT_SYMBOL(atomic_dec_and_lock); +EXPORT_SYMBOL(_atomic_dec_and_lock); #endif EXPORT_SYMBOL(die_chain); +EXPORT_SYMBOL(register_die_notifier); #ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_sibling_map); @@ -201,7 +206,7 @@ EXPORT_SYMBOL(smp_num_siblings); #endif extern void do_softirq_thunk(void); -EXPORT_SYMBOL_NOVERS(do_softirq_thunk); +EXPORT_SYMBOL(do_softirq_thunk); void out_of_line_bug(void); EXPORT_SYMBOL(out_of_line_bug); @@ -211,10 +216,9 @@ EXPORT_SYMBOL(init_level4_pgt); extern unsigned long __supported_pte_mask; EXPORT_SYMBOL(__supported_pte_mask); -EXPORT_SYMBOL(clear_page); - #ifdef CONFIG_SMP EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL_GPL(flush_tlb_all); #endif +EXPORT_SYMBOL(cpu_khz); diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile index 32b206440..6b26a1c1e 100644 --- a/arch/x86_64/lib/Makefile +++ b/arch/x86_64/lib/Makefile @@ -8,7 +8,7 @@ obj-y := io.o lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \ usercopy.o getuser.o putuser.o \ - thunk.o clear_page.o copy_page.o bitstr.o + thunk.o clear_page.o copy_page.o bitstr.o bitops.o lib-y += memcpy.o memmove.o memset.o copy_user.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff --git a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c index 6060dd908..994d76650 100644 --- a/arch/x86_64/lib/bitops.c +++ b/arch/x86_64/lib/bitops.c @@ -1,5 +1,5 @@ #include -#include +#include #undef find_first_zero_bit #undef find_next_zero_bit diff --git a/arch/x86_64/lib/bitstr.c b/arch/x86_64/lib/bitstr.c index 598d79de8..24676609a 100644 --- a/arch/x86_64/lib/bitstr.c +++ b/arch/x86_64/lib/bitstr.c @@ -1,4 +1,5 @@ -#include +#include +#include /* Find string of zero bits in a bitmap */ unsigned long @@ -23,3 +24,5 @@ find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len) } return n; } + +EXPORT_SYMBOL(find_next_zero_string); diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S index 6859a7809..bd556c804 100644 --- a/arch/x86_64/lib/copy_user.S +++ b/arch/x86_64/lib/copy_user.S @@ -73,7 +73,7 @@ bad_to_user: * rdx count * * Output: - * eax uncopied bytes or 0 if successfull. + * eax uncopied bytes or 0 if successful. */ .globl copy_user_generic .p2align 4 @@ -179,9 +179,9 @@ copy_user_generic: movl $8,%r9d subl %ecx,%r9d movl %r9d,%ecx - subq %r9,%rdx - jz .Lsmall_align - js .Lsmall_align + cmpq %r9,%rdx + jz .Lhandle_7 + js .Lhandle_7 .Lalign_1: .Ls11: movb (%rsi),%bl .Ld11: movb %bl,(%rdi) @@ -189,10 +189,8 @@ copy_user_generic: incq %rdi decl %ecx jnz .Lalign_1 + subq %r9,%rdx jmp .Lafter_bad_alignment -.Lsmall_align: - addq %r9,%rdx - jmp .Lhandle_7 #endif /* table sorted by exception address */ @@ -219,8 +217,8 @@ copy_user_generic: .quad .Ls10,.Le_byte .quad .Ld10,.Le_byte #ifdef FIX_ALIGNMENT - .quad .Ls11,.Le_byte - .quad .Ld11,.Le_byte + .quad .Ls11,.Lzero_rest + .quad .Ld11,.Lzero_rest #endif .quad .Le5,.Le_zero .previous diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c index c5b166224..18abae985 100644 --- a/arch/x86_64/lib/csum-wrappers.c +++ b/arch/x86_64/lib/csum-wrappers.c @@ -22,6 +22,7 @@ unsigned int csum_partial_copy_from_user(const char __user *src, char *dst, int len, unsigned int isum, int *errp) { + might_sleep(); *errp = 0; if (likely(access_ok(VERIFY_READ,src, len))) { /* Why 6, not 7? To handle odd addresses aligned we @@ -69,6 +70,7 @@ unsigned int csum_partial_copy_to_user(const char *src, char __user *dst, int len, unsigned int isum, int *errp) { + might_sleep(); if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) { *errp = -EFAULT; return 0; diff --git a/arch/x86_64/lib/dec_and_lock.c b/arch/x86_64/lib/dec_and_lock.c index ffd486900..ab43394dc 100644 --- a/arch/x86_64/lib/dec_and_lock.c +++ b/arch/x86_64/lib/dec_and_lock.c @@ -10,7 +10,7 @@ #include #include -int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; diff --git a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c index 12cac5ba7..e93d5255f 100644 --- a/arch/x86_64/lib/memmove.c +++ b/arch/x86_64/lib/memmove.c @@ -10,18 +10,10 @@ void *memmove(void * dest,const void *src,size_t count) if (dest < src) { __inline_memcpy(dest,src,count); } else { - /* Could be more clever and move longs */ - unsigned long d0, d1, d2; - __asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (count), - "1" (count-1+(const char *)src), - "2" (count-1+(char *)dest) - :"memory"); + char *p = (char *) dest + count; + char *s = (char *) src + count; + while (count--) + *--p = *--s; } return dest; } diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c index a17c85c5b..db8abba1a 100644 --- a/arch/x86_64/lib/usercopy.c +++ b/arch/x86_64/lib/usercopy.c @@ -14,6 +14,7 @@ #define __do_strncpy_from_user(dst,src,count,res) \ do { \ long __d0, __d1, __d2; \ + might_sleep(); \ __asm__ __volatile__( \ " testq %1,%1\n" \ " jz 2f\n" \ @@ -63,6 +64,7 @@ strncpy_from_user(char *dst, const char __user *src, long count) unsigned long __clear_user(void __user *addr, unsigned long size) { long __d0; + might_sleep(); /* no memory constraint because it doesn't change any memory gcc knows about */ asm volatile( diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 32a1d0ce9..98d54f2ec 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -23,16 +23,17 @@ #include /* For unblank_screen() */ #include #include +#include #include #include #include -#include #include #include #include #include #include +#include void bust_spinlocks(int yes) { @@ -58,16 +59,17 @@ void bust_spinlocks(int yes) /* Sometimes the CPU reports invalid exceptions on prefetch. Check that here and ignore. Opcode checker based on code by Richard Brunner */ -static int is_prefetch(struct pt_regs *regs, unsigned long addr) +static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, + unsigned long error_code) { unsigned char *instr = (unsigned char *)(regs->rip); int scan_more = 1; int prefetch = 0; unsigned char *max_instr = instr + 15; - /* Avoid recursive faults for this common case */ - if (regs->rip == addr) - return 0; + /* If it was a exec fault ignore */ + if (error_code & (1<<4)) + return 0; /* Code segments in LDT could have a non zero base. Don't check when that's possible */ @@ -218,6 +220,18 @@ int unhandled_signal(struct task_struct *tsk, int sig) (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); } +static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, + unsigned long error_code) +{ + oops_begin(); + printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", + current->comm, address); + dump_pagetable(address); + __die("Bad pagetable", regs, error_code); + oops_end(); + do_exit(SIGKILL); +} + int page_fault_trace; int exception_trace = 1; @@ -256,6 +270,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) /* get the address */ __asm__("movq %%cr2,%0":"=r" (address)); + if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + SIGSEGV) == NOTIFY_STOP) + return; if (likely(regs->eflags & X86_EFLAGS_IF)) local_irq_enable(); @@ -268,11 +285,32 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) mm = tsk->mm; info.si_code = SEGV_MAPERR; - /* 5 => page not present and from supervisor mode */ - if (unlikely(!(error_code & 5) && - ((address >= VMALLOC_START && address <= VMALLOC_END) || - (address >= MODULES_VADDR && address <= MODULES_END)))) - goto vmalloc_fault; + + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + * + * This verifies that the fault happens in kernel space + * (error_code & 4) == 0, and that the fault was not a + * protection error (error_code & 1) == 0. + */ + if (unlikely(address >= TASK_SIZE)) { + if (!(error_code & 5)) + goto vmalloc_fault; + /* + * Don't take the mm semaphore here. If we fixup a prefetch + * fault we could otherwise deadlock. + */ + goto bad_area_nosemaphore; + } + + if (unlikely(error_code & (1 << 3))) + goto page_table_corruption; /* * If we're in an interrupt or have no user @@ -282,7 +320,27 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) goto bad_area_nosemaphore; again: - down_read(&mm->mmap_sem); + /* When running in the kernel we expect faults to occur only to + * addresses in user space. All other faults represent errors in the + * kernel and should generate an OOPS. Unfortunatly, in the case of an + * erroneous fault occuring in a code path which already holds mmap_sem + * we will deadlock attempting to validate the fault against the + * address space. Luckily the kernel only validly references user + * space from well defined areas of code, which are listed in the + * exceptions table. + * + * As the vast majority of faults will be valid we will only perform + * the source reference check when there is a possibilty of a deadlock. + * Attempt to lock the address space, if we cannot we then validate the + * source. If this is invalid we can skip the address space check, + * thus avoiding the deadlock. + */ + if (!down_read_trylock(&mm->mmap_sem)) { + if ((error_code & 4) == 0 && + !search_exception_tables(regs->rip)) + goto bad_area_nosemaphore; + down_read(&mm->mmap_sem); + } vma = find_vma(mm, address); if (!vma) @@ -351,18 +409,18 @@ bad_area: bad_area_nosemaphore: #ifdef CONFIG_IA32_EMULATION - /* 32bit vsyscall. map on demand. */ - if (test_thread_flag(TIF_IA32) && + /* 32bit vsyscall. map on demand. */ + if (test_thread_flag(TIF_IA32) && address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { - if (map_syscall32(mm, address) < 0) - goto out_of_memory2; - return; - } + if (map_syscall32(mm, address) < 0) + goto out_of_memory2; + return; + } #endif /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { - if (is_prefetch(regs, address)) + if (is_prefetch(regs, address, error_code)) return; /* Work around K8 erratum #100 K8 in compat mode @@ -376,7 +434,7 @@ bad_area_nosemaphore: return; if (exception_trace && unhandled_signal(tsk, SIGSEGV)) { - printk(KERN_INFO + printk(KERN_INFO "%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", tsk->comm, tsk->pid, address, regs->rip, regs->rsp, error_code); @@ -407,7 +465,7 @@ no_context: * Hall of shame of CPU/BIOS bugs. */ - if (is_prefetch(regs, address)) + if (is_prefetch(regs, address, error_code)) return; if (is_errata93(regs, address)) @@ -481,10 +539,8 @@ vmalloc_fault: * is really there and when yes flush the local TLB. */ pgd = pgd_offset_k(address); - if (pgd != current_pgd_offset_k(address)) - BUG(); if (!pgd_present(*pgd)) - goto bad_area_nosemaphore; + goto bad_area_nosemaphore; pmd = pmd_offset(pgd, address); if (!pmd_present(*pmd)) goto bad_area_nosemaphore; @@ -495,4 +551,7 @@ vmalloc_fault: __flush_tlb_all(); return; } + +page_table_corruption: + pgtable_bad(address, regs, error_code); } diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index f393e3355..e0bf7b9f7 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -41,6 +41,10 @@ #define Dprintk(x...) #endif +#ifdef CONFIG_GART_IOMMU +extern int swiotlb; +#endif + extern char _stext[]; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -396,6 +400,8 @@ static inline int page_is_ram (unsigned long pagenr) return 0; } +extern int swiotlb_force; + static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; @@ -405,7 +411,10 @@ void __init mem_init(void) int tmp; #ifdef CONFIG_SWIOTLB - if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) + if (swiotlb_force) + swiotlb = 1; + if (!iommu_aperture && + (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu)) swiotlb = 1; if (swiotlb) swiotlb_init(); @@ -475,6 +484,8 @@ void __init mem_init(void) #endif } +extern char __initdata_begin[], __initdata_end[]; + void free_initmem(void) { unsigned long addr; @@ -483,12 +494,11 @@ void free_initmem(void) for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); set_page_count(virt_to_page(addr), 1); -#ifdef CONFIG_INIT_DEBUG memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); -#endif free_page(addr); totalram_pages++; } + memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); printk ("Freeing unused kernel memory: %luk freed\n", (&__init_end - &__init_begin) >> 10); } @@ -596,7 +606,16 @@ static struct vm_area_struct gate32_vma = { struct vm_area_struct *get_gate_vma(struct task_struct *tsk) { - return test_tsk_thread_flag(tsk, TIF_IA32) ? &gate32_vma : &gate_vma; +#ifdef CONFIG_IA32_EMULATION + if (test_tsk_thread_flag(tsk, TIF_IA32)) { + /* lookup code assumes the pages are present. set them up + now */ + if (__map_syscall32(tsk->mm, 0xfffe000) < 0) + return NULL; + return &gate32_vma; + } +#endif + return &gate_vma; } int in_gate_area(struct task_struct *task, unsigned long addr) diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index 0cc4a612f..d9ddeeecf 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -111,7 +111,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) { void * addr; struct vm_struct * area; @@ -126,7 +126,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag * Don't remap the low PCI/ISA area, it's always mapped.. */ if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); + return (__force void __iomem *)phys_to_virt(phys_addr); /* * Don't allow anybody to remap normal RAM that we're using.. @@ -164,7 +164,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag vunmap(addr); return NULL; } - return (void *) (offset + (char *)addr); + return (__force void __iomem *) (offset + (char *)addr); } /** @@ -189,9 +189,9 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag * Must be freed with iounmap. */ -void *ioremap_nocache (unsigned long phys_addr, unsigned long size) +void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) { - void *p = __ioremap(phys_addr, size, _PAGE_PCD); + void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD); if (!p) return p; @@ -212,7 +212,7 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size) return p; } -void iounmap(void *addr) +void iounmap(volatile void __iomem *addr) { struct vm_struct *p; if (addr <= high_memory) diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 0ec22c11c..96cf21236 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -100,8 +101,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) limit <<= 24; limit |= (1<<24)-1; - if (limit > end_pfn_map << PAGE_SHIFT) - limit = end_pfn_map << PAGE_SHIFT; + if (limit > end_pfn << PAGE_SHIFT) + limit = end_pfn << PAGE_SHIFT; if (limit <= base) continue; diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 598a35c19..12eef59ca 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -10,6 +10,8 @@ #include #include #include +#include + #include #include #include @@ -135,7 +137,7 @@ void __init setup_node_zones(int nodeid) zones[ZONE_NORMAL] = end_pfn - start_pfn; } - free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, + free_area_init_node(nodeid, NODE_DATA(nodeid), zones, start_pfn, NULL); } @@ -151,9 +153,9 @@ void __init numa_init_array(void) for (i = 0; i < MAXNODE; i++) { if (node_online(i)) continue; - rr = find_next_bit(node_online_map, MAX_NUMNODES, rr); + rr = next_node(rr, node_online_map); if (rr == MAX_NUMNODES) - rr = find_first_bit(node_online_map, MAX_NUMNODES); + rr = first_node(node_online_map); node_data[i] = node_data[rr]; cpu_to_node[i] = rr; rr++; @@ -162,10 +164,62 @@ void __init numa_init_array(void) set_bit(0, &node_to_cpumask[cpu_to_node(0)]); } +#ifdef CONFIG_NUMA_EMU +int numa_fake __initdata = 0; + +/* Numa emulation */ +static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) +{ + int i; + struct node nodes[MAXNODE]; + unsigned long sz = ((end_pfn - start_pfn)< 1) { + unsigned long x = 1; + while ((x << 1) < sz) + x <<= 1; + if (x < sz/2) + printk("Numa emulation unbalanced. Complain to maintainer\n"); + sz = x; + } + + memset(&nodes,0,sizeof(nodes)); + for (i = 0; i < numa_fake; i++) { + nodes[i].start = (start_pfn<> 20); + } + numnodes = numa_fake; + memnode_shift = compute_hash_shift(nodes); + if (memnode_shift < 0) { + memnode_shift = 0; + printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); + return -1; + } + for (i = 0; i < numa_fake; i++) + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + numa_init_array(); + return 0; +} +#endif + void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) { int i; +#ifdef CONFIG_NUMA_EMU + if (numa_fake && !numa_emulation(start_pfn, end_pfn)) + return; +#endif + #ifdef CONFIG_K8_NUMA if (!numa_off && !k8_scan_nodes(start_pfn<E #define D_KEY ctx->D -static u8 pow_tab[256]; -static u8 log_tab[256]; -static u8 sbx_tab[256]; -static u8 isb_tab[256]; +static u8 pow_tab[256] __initdata; +static u8 log_tab[256] __initdata; +static u8 sbx_tab[256] __initdata; +static u8 isb_tab[256] __initdata; static u32 rco_tab[10]; static u32 ft_tab[4][256]; static u32 it_tab[4][256]; @@ -113,7 +113,7 @@ static u32 it_tab[4][256]; static u32 fl_tab[4][256]; static u32 il_tab[4][256]; -static inline u8 +static inline u8 __init f_mult (u8 a, u8 b) { u8 aa = log_tab[a], cc = aa + log_tab[b]; @@ -153,14 +153,14 @@ f_mult (u8 a, u8 b) il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) -static void +static void __init gen_tabs (void) { u32 i, t; u8 p, q; /* log and power tables for GF(2**8) finite field with - 0x011b as modular polynomial - the simplest prmitive + 0x011b as modular polynomial - the simplest primitive root is 0x03, used here to generate the tables */ for (i = 0, p = 1; i < 256; ++i) { diff --git a/crypto/api.c b/crypto/api.c index 6f0e62571..394169a85 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -155,8 +155,12 @@ out: void crypto_free_tfm(struct crypto_tfm *tfm) { + struct crypto_alg *alg = tfm->__crt_alg; + int size = sizeof(*tfm) + alg->cra_ctxsize; + crypto_exit_ops(tfm); - crypto_alg_put(tfm->__crt_alg); + crypto_alg_put(alg); + memset(tfm, 0, size); kfree(tfm); } diff --git a/crypto/arc4.c b/crypto/arc4.c index b66eb1f0d..9efbcaae8 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -3,7 +3,7 @@ * * ARC4 Cipher Algorithm * - * Jon Oberheide + * Jon Oberheide * * 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 @@ -100,4 +100,4 @@ module_exit(arc4_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); -MODULE_AUTHOR("Jon Oberheide "); +MODULE_AUTHOR("Jon Oberheide "); diff --git a/crypto/blowfish.c b/crypto/blowfish.c index 8fd18dcdb..83d575557 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -3,9 +3,9 @@ * * Blowfish Cipher Algorithm, by Bruce Schneier. * http://www.counterpane.com/blowfish.html - * - * Adapated from Kerneli implementation. - * + * + * Adapted from Kerneli implementation. + * * Copyright (c) Herbert Valerio Riedel * Copyright (c) Kyle McMartin * Copyright (c) 2002 James Morris @@ -316,7 +316,7 @@ static const u32 bf_sbox[256 * 4] = { * The blowfish encipher, processes 64-bit blocks. * NOTE: This function MUSTN'T respect endianess */ -static inline void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src) +static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src) { const u32 *P = bctx->p; const u32 *S = bctx->s; diff --git a/crypto/internal.h b/crypto/internal.h index b51fad1f9..e68e43886 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -17,7 +17,6 @@ #include #include #include -#include #include extern enum km_type crypto_km_types[]; diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 540dd9ac1..f6a5c9e5b 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out, { /* walk->data may be pointing the first byte of the next page; however, we know we transfered at least one byte. So, - walk->data - 1 will be a virutual address in the mapped page. */ + walk->data - 1 will be a virtual address in the mapped page. */ if (out) flush_dcache_page(walk->page); diff --git a/crypto/serpent.c b/crypto/serpent.c index 9802b1c54..4c95ba9c5 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c @@ -4,6 +4,10 @@ * Serpent Cipher Algorithm. * * Copyright (C) 2002 Dag Arne Osvik + * 2003 Herbert Valerio Riedel + * + * Added tnepres support: Ruben Jesus Garcia Hernandez , 18.10.2004 + * Based on code by hvr * * 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 @@ -212,7 +216,8 @@ struct serpent_ctx { u32 expkey[SERPENT_EXPKEY_WORDS]; }; -static int setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) + +static int serpent_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { u32 *k = ((struct serpent_ctx *)ctx)->expkey; u8 *k8 = (u8 *)k; @@ -362,7 +367,7 @@ static int setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) return 0; } -static void encrypt(void *ctx, u8 *dst, const u8 *src) +static void serpent_encrypt(void *ctx, u8 *dst, const u8 *src) { const u32 *k = ((struct serpent_ctx *)ctx)->expkey, @@ -420,7 +425,7 @@ static void encrypt(void *ctx, u8 *dst, const u8 *src) d[3] = cpu_to_le32(r3); } -static void decrypt(void *ctx, u8 *dst, const u8 *src) +static void serpent_decrypt(void *ctx, u8 *dst, const u8 *src) { const u32 *k = ((struct serpent_ctx *)ctx)->expkey, @@ -483,18 +488,101 @@ static struct crypto_alg serpent_alg = { .cra_u = { .cipher = { .cia_min_keysize = SERPENT_MIN_KEY_SIZE, .cia_max_keysize = SERPENT_MAX_KEY_SIZE, - .cia_setkey = setkey, - .cia_encrypt = encrypt, - .cia_decrypt = decrypt } } + .cia_setkey = serpent_setkey, + .cia_encrypt = serpent_encrypt, + .cia_decrypt = serpent_decrypt } } +}; + +static int tnepres_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +{ + u8 rev_key[SERPENT_MAX_KEY_SIZE]; + int i; + + if ((keylen < SERPENT_MIN_KEY_SIZE) + || (keylen > SERPENT_MAX_KEY_SIZE)) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + for (i = 0; i < keylen; ++i) + rev_key[keylen - i - 1] = key[i]; + + return serpent_setkey(ctx, rev_key, keylen, flags); +} + +static void tnepres_encrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 * const s = (const u32 * const)src; + u32 * const d = (u32 * const)dst; + + u32 rs[4], rd[4]; + + rs[0] = swab32(s[3]); + rs[1] = swab32(s[2]); + rs[2] = swab32(s[1]); + rs[3] = swab32(s[0]); + + serpent_encrypt(ctx, (u8 *)rd, (u8 *)rs); + + d[0] = swab32(rd[3]); + d[1] = swab32(rd[2]); + d[2] = swab32(rd[1]); + d[3] = swab32(rd[0]); +} + +static void tnepres_decrypt(void *ctx, u8 *dst, const u8 *src) +{ + const u32 * const s = (const u32 * const)src; + u32 * const d = (u32 * const)dst; + + u32 rs[4], rd[4]; + + rs[0] = swab32(s[3]); + rs[1] = swab32(s[2]); + rs[2] = swab32(s[1]); + rs[3] = swab32(s[0]); + + serpent_decrypt(ctx, (u8 *)rd, (u8 *)rs); + + d[0] = swab32(rd[3]); + d[1] = swab32(rd[2]); + d[2] = swab32(rd[1]); + d[3] = swab32(rd[0]); +} + +static struct crypto_alg tnepres_alg = { + .cra_name = "tnepres", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = SERPENT_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(serpent_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = SERPENT_MIN_KEY_SIZE, + .cia_max_keysize = SERPENT_MAX_KEY_SIZE, + .cia_setkey = tnepres_setkey, + .cia_encrypt = tnepres_encrypt, + .cia_decrypt = tnepres_decrypt } } }; static int __init init(void) { - return crypto_register_alg(&serpent_alg); + int ret = crypto_register_alg(&serpent_alg); + + if (ret) + return ret; + + ret = crypto_register_alg(&tnepres_alg); + + if (ret) + crypto_unregister_alg(&serpent_alg); + + return ret; } static void __exit fini(void) { + crypto_unregister_alg(&tnepres_alg); crypto_unregister_alg(&serpent_alg); } @@ -502,5 +590,6 @@ module_init(init); module_exit(fini); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Serpent Cipher Algorithm"); +MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm"); MODULE_AUTHOR("Dag Arne Osvik "); +MODULE_ALIAS("tnepres"); diff --git a/crypto/sha256.c b/crypto/sha256.c index e8adf150d..39f5a6547 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -63,15 +63,7 @@ static inline u32 RORu32(u32 x, u32 y) static inline void LOAD_OP(int I, u32 *W, const u8 *input) { - u32 t1 = input[(4 * I)] & 0xff; - - t1 <<= 8; - t1 |= input[(4 * I) + 1] & 0xff; - t1 <<= 8; - t1 |= input[(4 * I) + 2] & 0xff; - t1 <<= 8; - t1 |= input[(4 * I) + 3] & 0xff; - W[I] = t1; + W[I] = __be32_to_cpu( ((u32*)(input))[I] ); } static inline void BLEND_OP(int I, u32 *W) diff --git a/crypto/sha512.c b/crypto/sha512.c index f1a8dc0ae..6acaea9b7 100644 --- a/crypto/sha512.c +++ b/crypto/sha512.c @@ -30,6 +30,7 @@ struct sha512_ctx { u64 state[8]; u32 count[4]; u8 buf[128]; + u64 W[80]; }; static inline u64 Ch(u64 x, u64 y, u64 z) @@ -104,34 +105,18 @@ const u64 sha512_K[80] = { static inline void LOAD_OP(int I, u64 *W, const u8 *input) { - u64 t1 = input[(8*I) ] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+1] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+2] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+3] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+4] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+5] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+6] & 0xff; - t1 <<= 8; - t1 |= input[(8*I)+7] & 0xff; - W[I] = t1; + W[I] = __be64_to_cpu( ((u64*)(input))[I] ); } static inline void BLEND_OP(int I, u64 *W) { - W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; + W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; } static void -sha512_transform(u64 *state, const u8 *input) +sha512_transform(u64 *state, u64 *W, const u8 *input) { u64 a, b, c, d, e, f, g, h, t1, t2; - u64 W[80]; int i; @@ -172,7 +157,6 @@ sha512_transform(u64 *state, const u8 *input) /* erase our data */ a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, 80 * sizeof(u64)); } static void @@ -230,10 +214,10 @@ sha512_update(void *ctx, const u8 *data, unsigned int len) /* Transform as many times as possible. */ if (len >= part_len) { memcpy(&sctx->buf[index], data, part_len); - sha512_transform(sctx->state, sctx->buf); + sha512_transform(sctx->state, sctx->W, sctx->buf); for (i = part_len; i + 127 < len; i+=128) - sha512_transform(sctx->state, &data[i]); + sha512_transform(sctx->state, sctx->W, &data[i]); index = 0; } else { @@ -242,6 +226,9 @@ sha512_update(void *ctx, const u8 *data, unsigned int len) /* Buffer remaining input */ memcpy(&sctx->buf[index], &data[i], len - i); + + /* erase our data */ + memset(sctx->W, 0, sizeof(sctx->W)); } static void diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index f1e631b9c..6740b8515 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "tcrypt.h" /* @@ -61,7 +62,8 @@ static char *tvmem; static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", - "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL + "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", + "khazad", "wp512", "wp384", "wp256", "tnepres", NULL }; static void @@ -649,6 +651,10 @@ do_test(void) test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS); test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS); + //TNEPRES + test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS); + //AES test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); @@ -678,8 +684,17 @@ do_test(void) test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); + //ANUBIS + test_cipher ("anubis", MODE_ECB, ENCRYPT, anubis_enc_tv_template, ANUBIS_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, DECRYPT, anubis_dec_tv_template, ANUBIS_DEC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); + test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS); + test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS); test_deflate(); test_crc32c(); #ifdef CONFIG_CRYPTO_HMAC @@ -734,6 +749,8 @@ do_test(void) break; case 9: + test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS); break; case 10: @@ -791,6 +808,30 @@ do_test(void) test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); break; + case 22: + test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS); + break; + + case 23: + test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS); + break; + + case 24: + test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS); + break; + + case 25: + test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS); + break; + + case 26: + test_cipher ("anubis", MODE_ECB, ENCRYPT, anubis_enc_tv_template, ANUBIS_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, DECRYPT, anubis_dec_tv_template, ANUBIS_DEC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + break; + #ifdef CONFIG_CRYPTO_HMAC case 100: test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); @@ -846,7 +887,7 @@ static void __exit fini(void) { } module_init(init); module_exit(fini); -MODULE_PARM(mode, "i"); +module_param(mode, int, 0); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Quick & dirty crypto testing module"); diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 56a825d65..0b48ed632 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -301,6 +301,259 @@ struct hash_testvec sha512_tv_template[] = { }, }; + +/* + * WHIRLPOOL test vectors from Whirlpool package + * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE + * submission + */ +#define WP512_TEST_VECTORS 8 + +struct hash_testvec wp512_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, + 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, + 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, + 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, + 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }, + + + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F, + 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7, + 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69, + 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42, + 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6, + 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59, + 0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5, + 0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB, + 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B, + 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72, + 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C, + 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27, + 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6, + 0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82, + 0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, + 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, + 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, + 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, + 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, + 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, + 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, + 0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9, + 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A, + 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5, + 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B, + 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A, + 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6, + 0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D, + 0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B, + 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90, + 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC, + 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E, + 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F, + 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6, + 0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21, + 0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 }, + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D, + 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0, + 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6, + 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29, + 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5, + 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A, + 0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B, + 0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, + 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48, + 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62, + 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69, + 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B, + 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56, + 0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6, + 0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD }, + }, +}; + +#define WP384_TEST_VECTORS 8 + +struct hash_testvec wp384_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, + 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, + 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, + 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57 }, + + + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F, + 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7, + 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69, + 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42, + 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6, + 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59 }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB, + 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B, + 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72, + 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C, + 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27, + 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6 }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, + 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, + 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, + 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, + 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, + 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9, + 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A, + 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5, + 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B, + 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A, + 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6 }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B, + 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90, + 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC, + 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E, + 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F, + 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6 }, + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D, + 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0, + 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6, + 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29, + 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5, + 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, + 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48, + 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62, + 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69, + 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B, + 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56 }, + }, +}; + +#define WP256_TEST_VECTORS 8 + +struct hash_testvec wp256_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, + 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, + 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7 }, + + + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F, + 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7, + 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69, + 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42 }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB, + 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B, + 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72, + 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, + 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, + 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, + 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9, + 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A, + 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5, + 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B, + 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90, + 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC, + 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E }, + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D, + 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0, + 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6, + 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29 }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, + 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48, + 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62, + 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 }, + }, +}; + + #ifdef CONFIG_CRYPTO_HMAC /* * HMAC-MD5 test vectors from RFC2202 @@ -1186,11 +1439,14 @@ struct cipher_testvec tf_cbc_dec_tv_template[] = { /* * Serpent test vectors. These are backwards because Serpent writes - * octect sequences in right-to-left mode. + * octet sequences in right-to-left mode. */ #define SERPENT_ENC_TEST_VECTORS 4 #define SERPENT_DEC_TEST_VECTORS 4 +#define TNEPRES_ENC_TEST_VECTORS 4 +#define TNEPRES_DEC_TEST_VECTORS 4 + struct cipher_testvec serpent_enc_tv_template[] = { { @@ -1233,6 +1489,57 @@ struct cipher_testvec serpent_enc_tv_template[] = }, }; +struct cipher_testvec tnepres_enc_tv_template[] = +{ + { /* KeySize=128, PT=0, I=1 */ + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .ilen = 16, + .result = { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05, + 0x2c, 0xd8, 0xff, 0xa5, 0x98, 0x6b, 0xd2, 0xdd }, + .rlen = 16, + }, { /* KeySize=192, PT=0, I=1 */ + .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 24, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 16, + .result = { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68, + 0xac, 0x36, 0x78, 0xf7, 0xa3, 0xf6, 0x0c, 0x66 }, + .rlen = 16, + }, { /* KeySize=256, PT=0, I=1 */ + .key = { 0x80, 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 }, + .klen = 32, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 16, + .result = { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb, + 0xc0, 0xeb, 0xd2, 0x1a, 0x82, 0xef, 0x08, 0x19 }, + .rlen = 16, + }, { /* KeySize=256, I=257 */ + .key = { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }, + .klen = 32, + .input = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }, + .ilen = 16, + .result = { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b, + 0xb8, 0x32, 0xe4, 0x33, 0xf8, 0x9f, 0x26, 0xde }, + .rlen = 16, + }, +}; + + struct cipher_testvec serpent_dec_tv_template[] = { { @@ -1275,6 +1582,49 @@ struct cipher_testvec serpent_dec_tv_template[] = }, }; +struct cipher_testvec tnepres_dec_tv_template[] = +{ + { + .input = { 0x41, 0xcc, 0x6b, 0x31, 0x59, 0x31, 0x45, 0x97, + 0x6d, 0x6f, 0xbb, 0x38, 0x4b, 0x37, 0x21, 0x28 }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .klen = 16, + .input = { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47, + 0x81, 0x45, 0x0b, 0xfa, 0x0c, 0xd6, 0xad, 0x6e }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .klen = 32, + .input = { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49, + 0xa8, 0x4e, 0x76, 0xd6, 0xf5, 0x0d, 0x78, 0xee }, + .ilen = 16, + .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .rlen = 16, + }, { /* KeySize=128, I=121 */ + .key = { [15] = 0x80 }, + .klen = 16, + .input = { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06, + 0x46, 0x2a, 0xf4, 0xef, 0x81, 0x54, 0x4e, 0x26 }, + .ilen = 16, + .result = { [0 ... 15] = 0x00 }, + .rlen = 16, + }, +}; + + /* Cast6 test vectors from RFC 2612 */ #define CAST6_ENC_TEST_VECTORS 3 #define CAST6_DEC_TEST_VECTORS 3 @@ -1916,6 +2266,211 @@ struct cipher_testvec khazad_dec_tv_template[] = { }, }; +/* + * Anubis test vectors. + */ + +#define ANUBIS_ENC_TEST_VECTORS 5 +#define ANUBIS_DEC_TEST_VECTORS 5 +#define ANUBIS_CBC_ENC_TEST_VECTORS 2 +#define ANUBIS_CBC_DEC_TEST_VECTORS 2 + +struct cipher_testvec anubis_enc_tv_template[] = { + { + .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .klen = 16, + .input = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .ilen = 16, + .result = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f, + 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 }, + .rlen = 16, + }, { + + .key = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03 }, + .klen = 20, + .input = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, + .ilen = 16, + .result = { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49, + 0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae }, + .rlen = 16, + }, { + .key = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24 }, + .klen = 28, + .input = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 }, + .ilen = 16, + .result = { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d, + 0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde }, + .rlen = 16, + }, { + .key = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 }, + .klen = 32, + .input = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 }, + .ilen = 16, + .result = { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4, + 0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe }, + .rlen = 16, + }, { + .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .klen = 40, + .input = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .ilen = 16, + .result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97, + 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee }, + .rlen = 16, + }, +}; + +struct cipher_testvec anubis_dec_tv_template[] = { + { + .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .klen = 16, + .input = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f, + 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 }, + .ilen = 16, + .result = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .rlen = 16, + }, { + + .key = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03 }, + .klen = 20, + .input = { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49, + 0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae }, + .ilen = 16, + .result = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, + .rlen = 16, + }, { + .key = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24 }, + .klen = 28, + .input = { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d, + 0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde }, + .ilen = 16, + .result = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 }, + .rlen = 16, + }, { + .key = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 }, + .klen = 32, + .input = { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4, + 0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe }, + .ilen = 16, + .result = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, + 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 }, + .rlen = 16, + }, { + .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .input = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97, + 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee }, + .klen = 40, + .ilen = 16, + .result = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .rlen = 16, + }, +}; + +struct cipher_testvec anubis_cbc_enc_tv_template[] = { + { + .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .klen = 16, + .input = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .ilen = 32, + .result = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f, + 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90, + 0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66, + 0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe }, + .rlen = 32, + }, { + .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .klen = 40, + .input = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .ilen = 32, + .result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97, + 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee, + 0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75, + 0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 }, + .rlen = 32, + }, +}; + +struct cipher_testvec anubis_cbc_dec_tv_template[] = { + { + .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .klen = 16, + .input = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f, + 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90, + 0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66, + 0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe }, + .ilen = 32, + .result = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, + .rlen = 32, + }, { + .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .klen = 40, + .input = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97, + 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee, + 0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75, + 0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 }, + .ilen = 32, + .result = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 }, + .rlen = 32, + }, +}; + /* * Compression stuff. */ diff --git a/crypto/tea.c b/crypto/tea.c index bf943294d..588a143c1 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -154,7 +154,7 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) while (sum != limit) { y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; - sum += TEA_DELTA; + sum += XTEA_DELTA; z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; } diff --git a/crypto/twofish.c b/crypto/twofish.c index 5d6d02c1a..4efff8cf9 100644 --- a/crypto/twofish.c +++ b/crypto/twofish.c @@ -1,7 +1,7 @@ /* * Twofish for CryptoAPI * - * Originaly Twofish for GPG + * Originally Twofish for GPG * By Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 @@ -514,7 +514,7 @@ static const u8 calc_sb_tbl[512] = { * preprocessed through q0 and q1 respectively; for longer keys they are the * output of previous stages. j is the index of the first key byte to use. * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 - * twice, doing the Psuedo-Hadamard Transform, and doing the necessary + * twice, doing the Pseudo-Hadamard Transform, and doing the necessary * rotations. Its parameters are: a, the array to write the results into, * j, the index of the first output entry, k and l, the preprocessed indices * for index 2i, and m and n, the preprocessed indices for index 2i+1. diff --git a/drivers/Kconfig b/drivers/Kconfig index 3270c2a3a..42e7ef5b2 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -54,4 +54,6 @@ source "sound/Kconfig" source "drivers/usb/Kconfig" +source "drivers/mmc/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 847d2c1ed..46b313027 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ +obj-y += video/ obj-$(CONFIG_ACPI_BOOT) += acpi/ # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so @@ -15,6 +16,14 @@ obj-$(CONFIG_PNP) += pnp/ # char/ comes before serial/ etc so that the VT console is the boot-time # default. obj-y += char/ + +# i810fb and intelfb depend on char/agp/ +obj-$(CONFIG_FB_I810) += video/i810/ +obj-$(CONFIG_FB_INTEL) += video/intelfb/ + +# we also need input/serio early so serio bus is initialized by the time +# serial drivers start registering their serio ports +obj-$(CONFIG_SERIO) += input/serio/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ net/ media/ @@ -26,9 +35,9 @@ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ -obj-y += cdrom/ video/ +obj-y += cdrom/ obj-$(CONFIG_MTD) += mtd/ -obj-$(CONFIG_PCMCIA) += pcmcia/ +obj-$(CONFIG_PCCARD) += pcmcia/ obj-$(CONFIG_DIO) += dio/ obj-$(CONFIG_SBUS) += sbus/ obj-$(CONFIG_ZORRO) += zorro/ @@ -39,7 +48,6 @@ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_GAMEPORT) += input/gameport/ -obj-$(CONFIG_SERIO) += input/serio/ obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_W1) += w1/ @@ -50,4 +58,5 @@ obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ +obj-$(CONFIG_MMC) += mmc/ obj-y += firmware/ diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c index 0e7a399d2..9cc2e8436 100644 --- a/drivers/acorn/block/fd1772.c +++ b/drivers/acorn/block/fd1772.c @@ -138,9 +138,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index a742764db..0e37df0b8 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -110,6 +110,21 @@ config ACPI_BUTTON down the system. Until then, you can cat it, and see output when a button is pressed. +config ACPI_VIDEO + tristate "Video" + depends on ACPI_INTERPRETER + depends on EXPERIMENTAL + depends on !IA64_SGI_SN + default m + help + This driver implement the ACPI Extensions For Display Adapters + for integrated graphics devices on motherboard, as specified in + ACPI 2.0 Specification, Appendix B, allowing to perform some basic + control like defining the video POST device, retrieving EDID information + or to setup a video output, etc. + Note that this is an ref. implementation only. It may or may not work + for your integrated video device. + config ACPI_FAN tristate "Fan" depends on ACPI_INTERPRETER @@ -176,6 +191,20 @@ config ACPI_ASUS something works not quite as expected, please use the mailing list available on the above page (acpi4asus-user@lists.sourceforge.net) +config ACPI_IBM + tristate "IBM ThinkPad Laptop Extras" + depends on X86 + depends on ACPI_INTERPRETER + default m + ---help--- + This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds + support for Fn-Fx key combinations, Bluetooth control, video + output switching, ThinkLight control, UltraBay eject and more. + For more information about this driver see Documentation/ibm-acpi.txt + and http://ibm-acpi.sf.net/ . + + If you have an IBM ThinkPad laptop, say Y or M here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on X86 @@ -204,6 +233,32 @@ config ACPI_TOSHIBA If you have a legacy free Toshiba laptop (such as the Libretto L1 series), say Y. +config ACPI_CUSTOM_DSDT + bool "Include Custom DSDT" + depends on ACPI_INTERPRETER && !STANDALONE + default n + help + Thist option is to load a custom ACPI DSDT + If you don't know what that is, say N. + +config ACPI_CUSTOM_DSDT_FILE + string "Custom DSDT Table file to include" + depends on ACPI_CUSTOM_DSDT + default "" + help + Enter the full path name to the file wich includes the AmlCode declaration. + +config ACPI_BLACKLIST_YEAR + int "Disable ACPI for systems before Jan 1st this year" + default 0 + help + enter a 4-digit year, eg. 2001 to disable ACPI by default + on platforms with DMI BIOS date before January 1st that year. + "acpi=force" can be used to override this mechanism. + + Enter 0 to disable this mechanism and allow ACPI to + run by default no matter what the year. (default) + config ACPI_DEBUG bool "Debug Statements" depends on ACPI_INTERPRETER diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index beb93c60d..e5d1afe25 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -12,8 +12,6 @@ endif EXTRA_CFLAGS += $(ACPI_CFLAGS) -obj-$(CONFIG_ACPI) := acpi_ksyms.o - # # ACPI Boot-Time Table Parsing # @@ -38,6 +36,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o +obj-$(CONFIG_ACPI_VIDEO) += video.o obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o @@ -46,5 +45,6 @@ obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o +obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o -obj-$(CONFIG_ACPI_BUS) += scan.o +obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 7333d5ffc..e0f498c7b 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -117,11 +117,11 @@ int acpi_ac_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE("acpi_ac_seq_show"); if (!ac) - return 0; + return_VALUE(0); if (acpi_ac_get_state(ac)) { seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); - return 0; + return_VALUE(0); } seq_puts(seq, "state: "); @@ -137,7 +137,7 @@ int acpi_ac_seq_show(struct seq_file *seq, void *offset) break; } - return 0; + return_VALUE(0); } static int acpi_ac_open_fs(struct inode *inode, struct file *file) @@ -212,7 +212,7 @@ acpi_ac_notify ( ACPI_FUNCTION_TRACE("acpi_ac_notify"); if (!ac) - return; + return_VOID; if (acpi_bus_get_device(ac->handle, &device)) return_VOID; diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index c884d4aaa..f2ca51bef 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -42,7 +42,7 @@ #include #include -#define ASUS_ACPI_VERSION "0.28" +#define ASUS_ACPI_VERSION "0.29" #define PROC_ASUS "asus" //the directory #define PROC_MLED "mled" @@ -123,14 +123,18 @@ struct asus_hotk { L3C, //L3800C L3D, //L3400D L3H, //L3H, but also L2000E + L4R, //L4500R L5x, //L5800C L8L, //L8400L M1A, //M1300A M2E, //M2400E, L4400L + M6N, //M6800N + M6R, //M6700R P30, //Samsung P30 S1x, //S1300A, but also L1400B and M2400A (L84F) S2x, //S200 (J1 reported), Victor MP-XP7210 - xxN, //M2400N, M3700N, M6800N, S1300N, S5200N (Centrino) + xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON + //(Centrino) END_MODEL } model; //Models currently supported u16 event_count[128]; //count for each event TODO make this better @@ -246,6 +250,19 @@ static struct model_data model_conf[END_MODEL] = { .display_get = "\\INFB" }, + { + .name = "L4R", + .mt_mled = "MLED", + .mt_wled = "WLED", + .wled_status = "\\_SB.PCI0.SBRG.SG13", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\_SB.PCI0.SBSM.SEO4", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD" + }, + { .name = "L5x", .mt_mled = "MLED", @@ -288,6 +305,31 @@ static struct model_data model_conf[END_MODEL] = { .display_get = "\\INFB" }, + { + .name = "M6N", + .mt_mled = "MLED", + .mt_wled = "WLED", + .wled_status = "\\_SB.PCI0.SBRG.SG13", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\_SB.BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\SSTE" + }, + { + .name = "M6R", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\_SB.PCI0.SBSM.SEO4", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\SSTE" + }, + + { .name = "P30", .mt_wled = "WLED", @@ -344,6 +386,9 @@ static struct proc_dir_entry *asus_proc_dir; */ static struct acpi_table_header *asus_info; +/* The actual device the driver binds to */ +static struct asus_hotk *hotk; + /* * The hotkey driver declaration */ @@ -408,7 +453,6 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, { int len = 0; int temp; - struct asus_hotk *hotk = (struct asus_hotk *) data; char buf[16]; //enough for all info /* * We use the easy way, we don't care of off and count, so we don't set eof @@ -428,7 +472,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, len += sprintf(page + len, "SFUN value : 0x%04x\n", temp); /* * Another value for userspace: the ASYM method returns 0x02 for - * battery low and 0x04 for battery critical, it's readings tend to be + * battery low and 0x04 for battery critical, its readings tend to be * more accurate than those provided by _BST. * Note: since not all the laptops provide this method, errors are * silently ignored. @@ -467,7 +511,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, /* Generic LED functions */ static int -read_led(struct asus_hotk *hotk, const char *ledname, int ledmask) +read_led(const char *ledname, int ledmask) { if (ledname) { int led_status; @@ -498,7 +542,7 @@ static int parse_arg(const char __user *buf, unsigned long count, int *val) /* FIXME: kill extraneous args so it can be called independently */ static int -write_led(const char __user *buffer, unsigned long count, struct asus_hotk *hotk, +write_led(const char __user *buffer, unsigned long count, char *ledname, int ledmask, int invert) { int value; @@ -528,8 +572,7 @@ static int proc_read_mled(char *page, char **start, off_t off, int count, int *eof, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return sprintf(page, "%d\n", read_led(hotk, hotk->methods->mled_status, MLED_ON)); + return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON)); } @@ -537,8 +580,7 @@ static int proc_write_mled(struct file *file, const char __user *buffer, unsigned long count, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return write_led(buffer, count, hotk, hotk->methods->mt_mled, MLED_ON, 1); + return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); } /* @@ -548,16 +590,14 @@ static int proc_read_wled(char *page, char **start, off_t off, int count, int *eof, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return sprintf(page, "%d\n", read_led(hotk, hotk->methods->wled_status, WLED_ON)); + return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON)); } static int proc_write_wled(struct file *file, const char __user *buffer, unsigned long count, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return write_led(buffer, count, hotk, hotk->methods->mt_wled, WLED_ON, 0); + return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); } /* @@ -567,21 +607,18 @@ static int proc_read_tled(char *page, char **start, off_t off, int count, int *eof, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return sprintf(page, "%d\n", read_led(hotk, hotk->methods->tled_status, TLED_ON)); + return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON)); } static int proc_write_tled(struct file *file, const char __user *buffer, unsigned long count, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return write_led(buffer, count, hotk, hotk->methods->mt_tled, TLED_ON, 0); + return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); } - -static int get_lcd_state(struct asus_hotk *hotk) +static int get_lcd_state(void) { int lcd = 0; @@ -622,13 +659,13 @@ static int get_lcd_state(struct asus_hotk *hotk) return (lcd & 1); } -static int set_lcd_state(struct asus_hotk *hotk, int value) +static int set_lcd_state(int value) { int lcd = 0; acpi_status status = 0; lcd = value ? 1 : 0; - if (lcd != get_lcd_state(hotk)) { + if (lcd != get_lcd_state()) { /* switch */ if (hotk->model != L3H) { status = @@ -651,7 +688,7 @@ static int proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, void *data) { - return sprintf(page, "%d\n", get_lcd_state((struct asus_hotk *) data)); + return sprintf(page, "%d\n", get_lcd_state()); } @@ -660,16 +697,15 @@ proc_write_lcd(struct file *file, const char __user *buffer, unsigned long count, void *data) { int value; - struct asus_hotk *hotk = (struct asus_hotk *) data; count = parse_arg(buffer, count, &value); if (count > 0) - set_lcd_state(hotk, value); + set_lcd_state(value); return count; } -static int read_brightness(struct asus_hotk *hotk) +static int read_brightness(void) { int value; @@ -689,7 +725,7 @@ static int read_brightness(struct asus_hotk *hotk) /* * Change the brightness level */ -static void set_brightness(int value, struct asus_hotk *hotk) +static void set_brightness(int value) { acpi_status status = 0; @@ -702,7 +738,7 @@ static void set_brightness(int value, struct asus_hotk *hotk) } /* No SPLV method if we are here, act as appropriate */ - value -= read_brightness(hotk); + value -= read_brightness(); while (value != 0) { status = acpi_evaluate_object(NULL, (value > 0) ? hotk->methods->brightness_up : @@ -719,8 +755,7 @@ static int proc_read_brn(char *page, char **start, off_t off, int count, int *eof, void *data) { - struct asus_hotk *hotk = (struct asus_hotk *) data; - return sprintf(page, "%d\n", read_brightness(hotk)); + return sprintf(page, "%d\n", read_brightness()); } static int @@ -728,13 +763,12 @@ proc_write_brn(struct file *file, const char __user *buffer, unsigned long count, void *data) { int value; - struct asus_hotk *hotk = (struct asus_hotk *) data; count = parse_arg(buffer, count, &value); if (count > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ - set_brightness(value, hotk); + set_brightness(value); } else if (count < 0) { printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } @@ -742,7 +776,7 @@ proc_write_brn(struct file *file, const char __user *buffer, return count; } -static void set_display(int value, struct asus_hotk *hotk) +static void set_display(int value) { /* no sanity check needed for now */ if (!write_acpi_int(hotk->handle, hotk->methods->display_set, @@ -760,10 +794,10 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, void *data) { int value = 0; - struct asus_hotk *hotk = (struct asus_hotk *) data; if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); + value &= 0x07; /* needed for some models, shouldn't hurt others */ return sprintf(page, "%d\n", value); } @@ -778,11 +812,10 @@ proc_write_disp(struct file *file, const char __user *buffer, unsigned long count, void *data) { int value; - struct asus_hotk *hotk = (struct asus_hotk *) data; count = parse_arg(buffer, count, &value); if (count > 0) - set_display(value, hotk); + set_display(value); else if (count < 0) printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); @@ -817,7 +850,6 @@ __init asus_proc_add(char *name, proc_writefunc *writefunc, static int __init asus_hotk_add_fs(struct acpi_device *device) { struct proc_dir_entry *proc; - struct asus_hotk *hotk = acpi_driver_data(device); mode_t mode; /* @@ -869,13 +901,12 @@ static int __init asus_hotk_add_fs(struct acpi_device *device) } if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || - (hotk->methods->brightness_get && hotk->methods->brightness_get)) { + (hotk->methods->brightness_get && hotk->methods->brightness_set)) { asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device); } if (hotk->methods->display_set) { asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device); - } return 0; @@ -883,10 +914,7 @@ static int __init asus_hotk_add_fs(struct acpi_device *device) static int asus_hotk_remove_fs(struct acpi_device* device) { - struct asus_hotk* hotk = acpi_driver_data(device); - - - if(acpi_device_dir(device)){ + if(acpi_device_dir(device)) { remove_proc_entry(PROC_INFO,acpi_device_dir(device)); if (hotk->methods->mt_wled) remove_proc_entry(PROC_WLED,acpi_device_dir(device)); @@ -894,11 +922,12 @@ static int asus_hotk_remove_fs(struct acpi_device* device) remove_proc_entry(PROC_MLED,acpi_device_dir(device)); if (hotk->methods->mt_tled) remove_proc_entry(PROC_TLED,acpi_device_dir(device)); - if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) + if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) remove_proc_entry(PROC_LCD, acpi_device_dir(device)); - if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get)) + if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || + (hotk->methods->brightness_get && hotk->methods->brightness_set)) remove_proc_entry(PROC_BRN, acpi_device_dir(device)); - if (hotk->methods->display_set) + if (hotk->methods->display_set) remove_proc_entry(PROC_DISP, acpi_device_dir(device)); } return 0; @@ -907,11 +936,7 @@ static int asus_hotk_remove_fs(struct acpi_device* device) static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { - /* TODO Find a better way to handle events count. Here, in data, we receive - * the hotk, so we can do anything! - */ - struct asus_hotk *hotk = (struct asus_hotk *) data; - + /* TODO Find a better way to handle events count.*/ if (!hotk) return; @@ -931,7 +956,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) * This function is used to initialize the hotk with right values. In this * method, we can make all the detection we want, and modify the hotk struct */ -static int __init asus_hotk_get_info(struct asus_hotk *hotk) +static int __init asus_hotk_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -998,11 +1023,19 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk) hotk->model = L3C; else if (strncmp(model->string.pointer, "L8L", 3) == 0) hotk->model = L8L; + else if (strncmp(model->string.pointer, "L4R", 3) == 0) + hotk->model = L4R; + else if (strncmp(model->string.pointer, "M6N", 3) == 0) + hotk->model = M6N; + else if (strncmp(model->string.pointer, "M6R", 3) == 0) + hotk->model = M6R; else if (strncmp(model->string.pointer, "M2N", 3) == 0 || strncmp(model->string.pointer, "M3N", 3) == 0 || + strncmp(model->string.pointer, "M5N", 3) == 0 || strncmp(model->string.pointer, "M6N", 3) == 0 || strncmp(model->string.pointer, "S1N", 3) == 0 || - strncmp(model->string.pointer, "S5N", 3) == 0) + strncmp(model->string.pointer, "S5N", 3) == 0 || + strncmp(model->string.pointer, "W1N", 3) == 0) hotk->model = xxN; else if (strncmp(model->string.pointer, "M1", 2) == 0) hotk->model = M1A; @@ -1025,7 +1058,6 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk) hotk->model = L5x; if (hotk->model == END_MODEL) { - /* By default use the same values, as I don't know others */ printk("unsupported, trying default values, supply the " "developers with your DSDT\n"); hotk->model = M2E; @@ -1040,16 +1072,14 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk) hotk->methods->lcd_status = NULL; /* L2B is similar enough to L3C to use its settings, with this only exception */ - else if (strncmp(model->string.pointer, "S5N", 3) == 0) + else if (strncmp(model->string.pointer, "S5N", 3) == 0 || + strncmp(model->string.pointer, "M5N", 3) == 0) hotk->methods->mt_mled = NULL; - /* S5N has no MLED */ - else if (strncmp(model->string.pointer, "M6N", 3) == 0) { - hotk->methods->display_get = NULL; //TODO - hotk->methods->lcd_status = "\\_SB.BKLT"; - hotk->methods->mt_wled = "WLED"; - hotk->methods->wled_status = "\\_SB.PCI0.SBRG.SG13"; - /* M6N differs slightly and has a usable WLED */ - } + /* S5N and M5N have no MLED */ + else if (strncmp(model->string.pointer, "M2N", 3) == 0 || + strncmp(model->string.pointer, "W1N", 3) == 0) + hotk->methods->mt_wled = "WLED"; + /* M2N and W1N have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) hotk->methods->mled_status = NULL; @@ -1062,20 +1092,16 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk) } - -static int __init asus_hotk_check(struct asus_hotk *hotk) +static int __init asus_hotk_check(void) { int result = 0; - if (!hotk) - return(-EINVAL); - result = acpi_bus_get_status(hotk->device); if (result) return(result); if (hotk->device->status.present) { - result = asus_hotk_get_info(hotk); + result = asus_hotk_get_info(); } else { printk(KERN_ERR " Hotkey device not present, aborting\n"); return(-EINVAL); @@ -1085,10 +1111,8 @@ static int __init asus_hotk_check(struct asus_hotk *hotk) } - static int __init asus_hotk_add(struct acpi_device *device) { - struct asus_hotk *hotk = NULL; acpi_status status = AE_OK; int result; @@ -1111,7 +1135,7 @@ static int __init asus_hotk_add(struct acpi_device *device) hotk->device = device; - result = asus_hotk_check(hotk); + result = asus_hotk_check(); if (result) goto end; @@ -1152,16 +1176,14 @@ static int __init asus_hotk_add(struct acpi_device *device) return(result); } + static int asus_hotk_remove(struct acpi_device *device, int type) { acpi_status status = 0; - struct asus_hotk *hotk = NULL; if (!device || !acpi_driver_data(device)) return(-EINVAL); - hotk = (struct asus_hotk *) acpi_driver_data(device); - status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify); if (ACPI_FAILURE(status)) @@ -1179,20 +1201,24 @@ static int __init asus_acpi_init(void) { int result; + if (acpi_disabled) + return -ENODEV; + asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); if (!asus_proc_dir) { printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); - return(-ENODEV); + return -ENODEV; } asus_proc_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 0) { + if (result < 1) { + acpi_bus_unregister_driver(&asus_hotk_driver); remove_proc_entry(PROC_ASUS, acpi_root_dir); - return(-ENODEV); + return -ENODEV; } - return(0); + return 0; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index f6218dd8f..a10de067d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -341,32 +342,22 @@ acpi_battery_check ( -------------------------------------------------------------------------- */ struct proc_dir_entry *acpi_battery_dir; - -static int -acpi_battery_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +static int acpi_battery_read_info(struct seq_file *seq, void *offset) { int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery *battery = (struct acpi_battery *) seq->private; struct acpi_battery_info *bif = NULL; char *units = "?"; - char *p = page; - int len = 0; ACPI_FUNCTION_TRACE("acpi_battery_read_info"); - if (!battery || (off != 0)) + if (!battery) goto end; if (battery->flags.present) - p += sprintf(p, "present: yes\n"); + seq_printf(seq, "present: yes\n"); else { - p += sprintf(p, "present: no\n"); + seq_printf(seq, "present: no\n"); goto end; } @@ -374,98 +365,88 @@ acpi_battery_read_info ( result = acpi_battery_get_info(battery, &bif); if (result || !bif) { - p += sprintf(p, "ERROR: Unable to read battery information\n"); + seq_printf(seq, "ERROR: Unable to read battery information\n"); goto end; } units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "design capacity: unknown\n"); + seq_printf(seq, "design capacity: unknown\n"); else - p += sprintf(p, "design capacity: %d %sh\n", + seq_printf(seq, "design capacity: %d %sh\n", (u32) bif->design_capacity, units); if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "last full capacity: unknown\n"); + seq_printf(seq, "last full capacity: unknown\n"); else - p += sprintf(p, "last full capacity: %d %sh\n", + seq_printf(seq, "last full capacity: %d %sh\n", (u32) bif->last_full_capacity, units); switch ((u32) bif->battery_technology) { case 0: - p += sprintf(p, "battery technology: non-rechargeable\n"); + seq_printf(seq, "battery technology: non-rechargeable\n"); break; case 1: - p += sprintf(p, "battery technology: rechargeable\n"); + seq_printf(seq, "battery technology: rechargeable\n"); break; default: - p += sprintf(p, "battery technology: unknown\n"); + seq_printf(seq, "battery technology: unknown\n"); break; } if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "design voltage: unknown\n"); + seq_printf(seq, "design voltage: unknown\n"); else - p += sprintf(p, "design voltage: %d mV\n", + seq_printf(seq, "design voltage: %d mV\n", (u32) bif->design_voltage); - p += sprintf(p, "design capacity warning: %d %sh\n", + seq_printf(seq, "design capacity warning: %d %sh\n", (u32) bif->design_capacity_warning, units); - p += sprintf(p, "design capacity low: %d %sh\n", + seq_printf(seq, "design capacity low: %d %sh\n", (u32) bif->design_capacity_low, units); - p += sprintf(p, "capacity granularity 1: %d %sh\n", + seq_printf(seq, "capacity granularity 1: %d %sh\n", (u32) bif->battery_capacity_granularity_1, units); - p += sprintf(p, "capacity granularity 2: %d %sh\n", + seq_printf(seq, "capacity granularity 2: %d %sh\n", (u32) bif->battery_capacity_granularity_2, units); - p += sprintf(p, "model number: %s\n", + seq_printf(seq, "model number: %s\n", bif->model_number); - p += sprintf(p, "serial number: %s\n", + seq_printf(seq, "serial number: %s\n", bif->serial_number); - p += sprintf(p, "battery type: %s\n", + seq_printf(seq, "battery type: %s\n", bif->battery_type); - p += sprintf(p, "OEM info: %s\n", + seq_printf(seq, "OEM info: %s\n", bif->oem_info); end: kfree(bif); - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return_VALUE(0); +} - return_VALUE(len); +static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_info, PDE(inode)->data); } static int -acpi_battery_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +acpi_battery_read_state (struct seq_file *seq, void *offset) { int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery *battery = (struct acpi_battery *) seq->private; struct acpi_battery_status *bst = NULL; char *units = "?"; - char *p = page; - int len = 0; ACPI_FUNCTION_TRACE("acpi_battery_read_state"); - if (!battery || (off != 0)) + if (!battery) goto end; if (battery->flags.present) - p += sprintf(p, "present: yes\n"); + seq_printf(seq, "present: yes\n"); else { - p += sprintf(p, "present: no\n"); + seq_printf(seq, "present: no\n"); goto end; } @@ -477,81 +458,71 @@ acpi_battery_read_state ( result = acpi_battery_get_status(battery, &bst); if (result || !bst) { - p += sprintf(p, "ERROR: Unable to read battery status\n"); + seq_printf(seq, "ERROR: Unable to read battery status\n"); goto end; } if (!(bst->state & 0x04)) - p += sprintf(p, "capacity state: ok\n"); + seq_printf(seq, "capacity state: ok\n"); else - p += sprintf(p, "capacity state: critical\n"); + seq_printf(seq, "capacity state: critical\n"); if ((bst->state & 0x01) && (bst->state & 0x02)){ - p += sprintf(p, "charging state: charging/discharging\n"); + seq_printf(seq, "charging state: charging/discharging\n"); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Battery Charging and Discharging?\n")); } else if (bst->state & 0x01) - p += sprintf(p, "charging state: discharging\n"); + seq_printf(seq, "charging state: discharging\n"); else if (bst->state & 0x02) - p += sprintf(p, "charging state: charging\n"); + seq_printf(seq, "charging state: charging\n"); else { - p += sprintf(p, "charging state: charged\n"); + seq_printf(seq, "charging state: charged\n"); } if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "present rate: unknown\n"); + seq_printf(seq, "present rate: unknown\n"); else - p += sprintf(p, "present rate: %d %s\n", + seq_printf(seq, "present rate: %d %s\n", (u32) bst->present_rate, units); if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "remaining capacity: unknown\n"); + seq_printf(seq, "remaining capacity: unknown\n"); else - p += sprintf(p, "remaining capacity: %d %sh\n", + seq_printf(seq, "remaining capacity: %d %sh\n", (u32) bst->remaining_capacity, units); if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) - p += sprintf(p, "present voltage: unknown\n"); + seq_printf(seq, "present voltage: unknown\n"); else - p += sprintf(p, "present voltage: %d mV\n", + seq_printf(seq, "present voltage: %d mV\n", (u32) bst->present_voltage); end: kfree(bst); - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; + return_VALUE(0); +} - return_VALUE(len); +static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_state, PDE(inode)->data); } static int -acpi_battery_read_alarm ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +acpi_battery_read_alarm (struct seq_file *seq, void *offset) { - struct acpi_battery *battery = (struct acpi_battery *) data; + struct acpi_battery *battery = (struct acpi_battery *) seq->private; char *units = "?"; - char *p = page; - int len = 0; ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); - if (!battery || (off != 0)) + if (!battery) goto end; if (!battery->flags.present) { - p += sprintf(p, "present: no\n"); + seq_printf(seq, "present: no\n"); goto end; } @@ -561,34 +532,28 @@ acpi_battery_read_alarm ( /* Battery Alarm */ - p += sprintf(p, "alarm: "); + seq_printf(seq, "alarm: "); if (!battery->alarm) - p += sprintf(p, "unsupported\n"); + seq_printf(seq, "unsupported\n"); else - p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units); + seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return_VALUE(0); } -static int +static ssize_t acpi_battery_write_alarm ( - struct file *file, - const char __user *buffer, - unsigned long count, - void *data) + struct file *file, + const char __user *buffer, + size_t count, + loff_t *ppos) { int result = 0; - struct acpi_battery *battery = (struct acpi_battery *) data; char alarm_string[12] = {'\0'}; + struct seq_file *m = (struct seq_file *)file->private_data; + struct acpi_battery *battery = (struct acpi_battery *)m->private; ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); @@ -611,6 +576,35 @@ acpi_battery_write_alarm ( return_VALUE(count); } +static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); +} + +static struct file_operations acpi_battery_info_ops = { + .open = acpi_battery_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static struct file_operations acpi_battery_state_ops = { + .open = acpi_battery_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static struct file_operations acpi_battery_alarm_ops = { + .open = acpi_battery_alarm_open_fs, + .read = seq_read, + .write = acpi_battery_write_alarm, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; static int acpi_battery_add_fs ( @@ -636,7 +630,7 @@ acpi_battery_add_fs ( "Unable to create '%s' fs entry\n", ACPI_BATTERY_FILE_INFO)); else { - entry->read_proc = acpi_battery_read_info; + entry->proc_fops = &acpi_battery_info_ops; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -649,7 +643,7 @@ acpi_battery_add_fs ( "Unable to create '%s' fs entry\n", ACPI_BATTERY_FILE_STATUS)); else { - entry->read_proc = acpi_battery_read_state; + entry->proc_fops = &acpi_battery_state_ops; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } @@ -662,8 +656,7 @@ acpi_battery_add_fs ( "Unable to create '%s' fs entry\n", ACPI_BATTERY_FILE_ALARM)); else { - entry->read_proc = acpi_battery_read_alarm; - entry->write_proc = acpi_battery_write_alarm; + entry->proc_fops = &acpi_battery_alarm_ops; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9cf61ba9d..4c010e7f1 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -2,7 +2,9 @@ * blacklist.c * * Check to see if the given machine has a known bad ACPI BIOS + * or if the BIOS is too old. * + * Copyright (C) 2004 Len Brown * Copyright (C) 2002 Andy Grover * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -30,6 +32,7 @@ #include #include #include +#include enum acpi_blacklist_predicates { @@ -56,20 +59,6 @@ struct acpi_blacklist_item */ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { - /* Portege 7020, BIOS 8.10 */ - {"TOSHIB", "7020CT ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0}, - /* Portege 4030 */ - {"TOSHIB", "4030 ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0}, - /* Portege 310/320, BIOS 7.1 */ - {"TOSHIB", "310 ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0}, - /* Seattle 2, old bios rev. */ - {"INTEL ", "440BX ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* ASUS K7M */ - {"ASUS ", "K7M ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* Intel 810 Motherboard? */ - {"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0}, - /* Compaq Presario 711FR */ - {"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0}, /* Compaq Presario 1700 */ {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1}, /* Sony FX120, FX140, FX150? */ @@ -84,6 +73,45 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = }; +#if CONFIG_ACPI_BLACKLIST_YEAR + +static int __init +blacklist_by_year(void) +{ + int year; + char *s = dmi_get_system_info(DMI_BIOS_DATE); + + if (!s) + return 0; + if (!*s) + return 0; + + s = strrchr(s, '/'); + if (!s) + return 0; + + s += 1; + + year = simple_strtoul(s,NULL,0); + + if (year < 100) { /* 2-digit year */ + year += 1900; + if (year < 1996) /* no dates < spec 1.0 */ + year += 100; + } + + if (year < CONFIG_ACPI_BLACKLIST_YEAR) { + printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " + "acpi=force is required to enable ACPI\n", + year, CONFIG_ACPI_BLACKLIST_YEAR); + return 1; + } + return 0; +} +#else +static inline int blacklist_by_year(void) { return 0; } +#endif + int __init acpi_blacklisted(void) { @@ -134,6 +162,8 @@ acpi_blacklisted(void) } } + blacklisted += blacklist_by_year(); + return blacklisted; } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 51362331a..f625a0a20 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -22,6 +22,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include #include #include #include @@ -44,8 +45,11 @@ extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); #endif FADT_DESCRIPTOR acpi_fadt; +EXPORT_SYMBOL(acpi_fadt); + struct acpi_device *acpi_root; struct proc_dir_entry *acpi_root_dir; +EXPORT_SYMBOL(acpi_root_dir); #define STRUCT_TO_INT(s) (*((int*)&s)) @@ -80,6 +84,7 @@ acpi_bus_get_device ( return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_get_device); int acpi_bus_get_status ( @@ -125,6 +130,7 @@ acpi_bus_get_status ( return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_get_status); /* -------------------------------------------------------------------------- @@ -182,6 +188,7 @@ acpi_bus_get_power ( return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_get_power); int @@ -270,6 +277,7 @@ end: return_VALUE(result); } +EXPORT_SYMBOL(acpi_bus_set_power); @@ -319,6 +327,7 @@ acpi_bus_generate_event ( return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_generate_event); int acpi_bus_receive_event ( @@ -332,7 +341,7 @@ acpi_bus_receive_event ( ACPI_FUNCTION_TRACE("acpi_bus_receive_event"); if (!event) - return -EINVAL; + return_VALUE(-EINVAL); if (list_empty(&acpi_bus_event_list)) { @@ -364,6 +373,7 @@ acpi_bus_receive_event ( return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_receive_event); /* -------------------------------------------------------------------------- @@ -590,14 +600,20 @@ acpi_bus_init_irq (void) } -static int __init -acpi_bus_init (void) +void __init +acpi_early_init (void) { - int result = 0; acpi_status status = AE_OK; struct acpi_buffer buffer = {sizeof(acpi_fadt), &acpi_fadt}; - ACPI_FUNCTION_TRACE("acpi_bus_init"); + ACPI_FUNCTION_TRACE("acpi_early_init"); + + if (acpi_disabled) + return_VOID; + + /* enable workarounds, unless strict ACPI spec. compliance */ + if (!acpi_strict) + acpi_gbl_enable_interpreter_slack = TRUE; status = acpi_initialize_subsystem(); if (ACPI_FAILURE(status)) { @@ -617,7 +633,7 @@ acpi_bus_init (void) status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to get the FADT\n"); - goto error1; + goto error0; } #ifdef CONFIG_X86 @@ -640,12 +656,40 @@ acpi_bus_init (void) } #endif - status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); + status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE)); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); + goto error0; + } + + return_VOID; + +error0: + disable_acpi(); + return_VOID; +} + +static int __init +acpi_bus_init (void) +{ + int result = 0; + acpi_status status = AE_OK; + extern acpi_status acpi_os_initialize1(void); + + ACPI_FUNCTION_TRACE("acpi_bus_init"); + + status = acpi_os_initialize1(); + + status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n"); goto error1; } + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n"); + goto error1; + } #ifdef CONFIG_ACPI_EC /* * ACPI 2.0 requires the EC driver to be loaded and work before @@ -693,7 +737,6 @@ acpi_bus_init (void) /* Mimic structured exception handling */ error1: acpi_terminate(); -error0: return_VALUE(-ENODEV); } @@ -708,12 +751,9 @@ static int __init acpi_init (void) printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION); - /* Initial core debug level excludes drivers, so include them now */ - acpi_set_debug(ACPI_DEBUG_LOW); - if (acpi_disabled) { printk(KERN_INFO PREFIX "Interpreter disabled.\n"); - return -ENODEV; + return_VALUE(-ENODEV); } firmware_register(&acpi_subsys); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index a5b45095d..31aded126 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -116,12 +116,12 @@ static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); if (!button || !button->device) - return 0; + return_VALUE(0); seq_printf(seq, "type: %s\n", acpi_device_name(button->device)); - return 0; + return_VALUE(0); } static int acpi_button_info_open_fs(struct inode *inode, struct file *file) @@ -138,7 +138,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); if (!button || !button->device) - return 0; + return_VALUE(0); status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); if (ACPI_FAILURE(status)) { @@ -148,7 +148,7 @@ static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); } - return 0; + return_VALUE(0); } static int acpi_button_state_open_fs(struct inode *inode, struct file *file) @@ -456,6 +456,15 @@ acpi_button_add ( goto end; } + if (device->wakeup.flags.valid) { + /* Button's GPE is run-wake GPE */ + acpi_set_gpe_type(device->wakeup.gpe_device, + device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); + acpi_enable_gpe(device->wakeup.gpe_device, + device->wakeup.gpe_number, ACPI_NOT_ISR); + device->wakeup.state.enabled = 1; + } + printk(KERN_INFO PREFIX "%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 585f59db4..9fb8caedb 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -13,6 +14,81 @@ ACPI_MODULE_NAME ("debug") #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" +#ifdef MODULE_PARAM_PREFIX +#undef MODULE_PARAM_PREFIX +#endif + +#define MODULE_PARAM_PREFIX +module_param(acpi_dbg_layer, uint, 0400); +module_param(acpi_dbg_level, uint, 0400); + +struct acpi_dlayer { + const char *name; + unsigned long value; +}; +struct acpi_dlevel { + const char *name; + unsigned long value; +}; +#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } + +const struct acpi_dlayer acpi_debug_layers[] = +{ + ACPI_DEBUG_INIT(ACPI_UTILITIES), + ACPI_DEBUG_INIT(ACPI_HARDWARE), + ACPI_DEBUG_INIT(ACPI_EVENTS), + ACPI_DEBUG_INIT(ACPI_TABLES), + ACPI_DEBUG_INIT(ACPI_NAMESPACE), + ACPI_DEBUG_INIT(ACPI_PARSER), + ACPI_DEBUG_INIT(ACPI_DISPATCHER), + ACPI_DEBUG_INIT(ACPI_EXECUTER), + ACPI_DEBUG_INIT(ACPI_RESOURCES), + ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), + ACPI_DEBUG_INIT(ACPI_OS_SERVICES), + ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), + ACPI_DEBUG_INIT(ACPI_COMPILER), + ACPI_DEBUG_INIT(ACPI_TOOLS), +}; + +const struct acpi_dlevel acpi_debug_levels[] = +{ + ACPI_DEBUG_INIT(ACPI_LV_ERROR), + ACPI_DEBUG_INIT(ACPI_LV_WARN), + ACPI_DEBUG_INIT(ACPI_LV_INIT), + ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), + ACPI_DEBUG_INIT(ACPI_LV_INFO), + + ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), + ACPI_DEBUG_INIT(ACPI_LV_PARSE), + ACPI_DEBUG_INIT(ACPI_LV_LOAD), + ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), + ACPI_DEBUG_INIT(ACPI_LV_EXEC), + ACPI_DEBUG_INIT(ACPI_LV_NAMES), + ACPI_DEBUG_INIT(ACPI_LV_OPREGION), + ACPI_DEBUG_INIT(ACPI_LV_BFIELD), + ACPI_DEBUG_INIT(ACPI_LV_TABLES), + ACPI_DEBUG_INIT(ACPI_LV_VALUES), + ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), + ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), + ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), + ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), + + ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), + ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), + ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), + + ACPI_DEBUG_INIT(ACPI_LV_MUTEX), + ACPI_DEBUG_INIT(ACPI_LV_THREADS), + ACPI_DEBUG_INIT(ACPI_LV_IO), + ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), + + ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), + ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), + ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), + ACPI_DEBUG_INIT(ACPI_LV_EVENTS), +}; +#define NUM_OF(v) ( sizeof(v)/sizeof(v[0]) ) + static int acpi_system_read_debug ( char *page, @@ -24,16 +100,41 @@ acpi_system_read_debug ( { char *p = page; int size = 0; + int i; if (off != 0) goto end; + p += sprintf(p, "%-25s\tHex SET\n", "Description"); + switch ((unsigned long) data) { case 0: - p += sprintf(p, "0x%08x\n", acpi_dbg_layer); + for (i = 0; i < NUM_OF(acpi_debug_layers); i++) { + p += sprintf(p, "%-25s\t0x%08lX [%c]\n", + acpi_debug_layers[i].name, + acpi_debug_layers[i].value, + (acpi_dbg_layer & acpi_debug_layers[i].value) ? + '*' : ' '); + } + p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", + ACPI_ALL_DRIVERS, + (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS? + '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ? + ' ' : '-'); + p += sprintf(p, + "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", + acpi_dbg_layer); break; case 1: - p += sprintf(p, "0x%08x\n", acpi_dbg_level); + for (i = 0; i < NUM_OF(acpi_debug_levels); i++) { + p += sprintf(p, "%-25s\t0x%08lX [%c]\n", + acpi_debug_levels[i].name, + acpi_debug_levels[i].value, + (acpi_dbg_level & acpi_debug_levels[i].value) ? + '*' : ' '); + } + p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n", + acpi_dbg_level); break; default: p += sprintf(p, "Invalid debug option\n"); diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 360fbe5e8..4fd369018 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -58,15 +58,12 @@ * * FUNCTION: acpi_ds_parse_method * - * PARAMETERS: obj_handle - Node of the method - * Level - Current nesting level - * Context - Points to a method counter - * return_value - Not used + * PARAMETERS: obj_handle - Method node * * RETURN: Status * - * DESCRIPTION: Call the parser and parse the AML that is - * associated with the method. + * DESCRIPTION: Call the parser and parse the AML that is associated with the + * method. * * MUTEX: Assumes parser is locked * @@ -145,8 +142,9 @@ acpi_ds_parse_method ( return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start, - obj_desc->method.aml_length, NULL, NULL, 1); + status = acpi_ds_init_aml_walk (walk_state, op, node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); @@ -190,8 +188,6 @@ acpi_ds_parse_method ( * increments the thread count, and waits at the method semaphore * for clearance to execute. * - * MUTEX: Locks/unlocks parser. - * ******************************************************************************/ acpi_status @@ -250,7 +246,8 @@ acpi_ds_begin_method_execution ( * * FUNCTION: acpi_ds_call_control_method * - * PARAMETERS: walk_state - Current state of the walk + * PARAMETERS: Thread - Info for this thread + * this_walk_state - Current walk state * Op - Current Op to be walked * * RETURN: Status @@ -267,8 +264,9 @@ acpi_ds_call_control_method ( { acpi_status status; struct acpi_namespace_node *method_node; - union acpi_operand_object *obj_desc; struct acpi_walk_state *next_walk_state; + union acpi_operand_object *obj_desc; + struct acpi_parameter_info info; u32 i; @@ -309,7 +307,6 @@ acpi_ds_call_control_method ( return_ACPI_STATUS (AE_NO_MEMORY); } - /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); @@ -320,7 +317,7 @@ acpi_ds_call_control_method ( status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, - NULL, NULL, 1); + NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (next_walk_state); goto cleanup; @@ -348,9 +345,12 @@ acpi_ds_call_control_method ( */ this_walk_state->operands [this_walk_state->num_operands] = NULL; + info.parameters = &this_walk_state->operands[0]; + info.parameter_type = ACPI_PARAM_ARGS; + status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, - &this_walk_state->operands[0], NULL, 3); + &info, 3); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -382,7 +382,7 @@ acpi_ds_call_control_method ( /* On error, we must delete the new walk state */ cleanup: - if (next_walk_state->method_desc) { + if (next_walk_state && (next_walk_state->method_desc)) { /* Decrement the thread count on the method parse tree */ next_walk_state->method_desc->method.thread_count--; @@ -397,12 +397,13 @@ cleanup: * * FUNCTION: acpi_ds_restart_control_method * - * PARAMETERS: walk_state - State of the method when it was preempted - * Op - Pointer to new current op + * PARAMETERS: walk_state - State for preempted method (caller) + * return_desc - Return value from the called method * * RETURN: Status * - * DESCRIPTION: Restart a method that was preempted + * DESCRIPTION: Restart a method that was preempted by another (nested) method + * invocation. Handle the return value (if any) from the callee. * ******************************************************************************/ @@ -417,17 +418,35 @@ acpi_ds_restart_control_method ( ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "****Restart [%4.4s] Op %p return_value_from_callee %p\n", + (char *) &walk_state->method_node->name, walk_state->method_call_op, + return_desc)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + " return_from_this_method_used?=%X res_stack %p Walk %p\n", + walk_state->return_used, + walk_state->results, walk_state)); + + /* Did the called method return a value? */ + if (return_desc) { + /* Are we actually going to use the return value? */ + if (walk_state->return_used) { - /* - * Get the return value (if any) from the previous method. - * NULL if no return value - */ + /* Save the return value from the previous method */ + status = acpi_ds_result_push (return_desc, walk_state); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (return_desc); return_ACPI_STATUS (status); } + + /* + * Save as THIS method's return value in case it is returned + * immediately to yet another method + */ + walk_state->return_desc = return_desc; } else { /* @@ -438,11 +457,6 @@ acpi_ds_restart_control_method ( } } - ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, - "Method=%p Return=%p return_used?=%X res_stack=%p State=%p\n", - walk_state->method_call_op, return_desc, walk_state->return_used, - walk_state->results, walk_state)); - return_ACPI_STATUS (AE_OK); } diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index e1926534b..7515477d0 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -312,7 +312,7 @@ acpi_ds_method_data_set_value ( ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "obj %p op %X, ref count = %d [%s]\n", object, + "new_obj %p Opcode %X, Refs=%d [%s]\n", object, opcode, object->common.reference_count, acpi_ut_get_type_name (object->common.type))); @@ -350,7 +350,7 @@ acpi_ds_method_data_set_value ( * RETURN: Data type of current value of the selected Arg or Local * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_object_type acpi_ds_method_data_get_type ( u16 opcode, @@ -385,6 +385,7 @@ acpi_ds_method_data_get_type ( return_VALUE (ACPI_GET_OBJECT_TYPE (object)); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -448,7 +449,22 @@ acpi_ds_method_data_get_value ( * was referenced by the method (via the ASL) * before it was initialized. Either case is an error. */ - switch (opcode) { + + /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ + + if (acpi_gbl_enable_interpreter_slack) { + object = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!object) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + object->integer.value = 0; + node->object = object; + } + + /* Otherwise, return the error */ + + else switch (opcode) { case AML_ARG_OP: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at node %p\n", @@ -572,7 +588,7 @@ acpi_ds_store_object_to_local ( ACPI_FUNCTION_TRACE ("ds_store_object_to_local"); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%d Idx=%d Obj=%p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", opcode, index, obj_desc)); /* Parameter validation */ @@ -656,11 +672,13 @@ acpi_ds_store_object_to_local ( new_obj_desc, current_obj_desc)); /* - * Store this object to the Node - * (perform the indirect store) + * Store this object to the Node (perform the indirect store) + * NOTE: No implicit conversion is performed, as per the ACPI + * specification rules on storing to Locals/Args. */ status = acpi_ex_store_object_to_node (new_obj_desc, - current_obj_desc->reference.object, walk_state); + current_obj_desc->reference.object, walk_state, + ACPI_NO_IMPLICIT_CONVERSION); /* Remove local reference if we copied the object above */ diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index e0a313f57..68084760e 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -79,7 +79,6 @@ acpi_ds_execute_arguments ( acpi_status status; union acpi_parse_object *op; struct acpi_walk_state *walk_state; - union acpi_parse_object *arg; ACPI_FUNCTION_TRACE ("ds_execute_arguments"); @@ -105,7 +104,7 @@ acpi_ds_execute_arguments ( } status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, - aml_length, NULL, NULL, 1); + aml_length, NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); @@ -126,9 +125,7 @@ acpi_ds_execute_arguments ( /* Get and init the Op created above */ - arg = op->common.value.arg; op->common.node = node; - arg->common.node = node; acpi_ps_delete_parse_tree (op); /* Evaluate the deferred arguments */ @@ -150,7 +147,7 @@ acpi_ds_execute_arguments ( /* Execute the opcode and arguments */ status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start, - aml_length, NULL, NULL, 3); + aml_length, NULL, 3); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 5c6a37e05..b18c0df3a 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -60,11 +60,10 @@ * * FUNCTION: acpi_ds_is_result_used * - * PARAMETERS: Op - * result_obj - * walk_state + * PARAMETERS: Op - Current Op + * walk_state - Current State * - * RETURN: Status + * RETURN: TRUE if result is used, FALSE otherwise * * DESCRIPTION: Check if a result object will be used by the parent * @@ -89,18 +88,39 @@ acpi_ds_is_result_used ( } /* - * If there is no parent, the result can't possibly be used! - * (An executing method typically has no parent, since each - * method is parsed separately) However, a method that is - * invoked from another method has a parent. + * If there is no parent, we are executing at the method level. + * An executing method typically has no parent, since each method + * is parsed separately. */ if (!op->common.parent) { + /* + * If this is the last statement in the method, we know it is not a + * Return() operator (would not come here.) The following code is the + * optional support for a so-called "implicit return". Some AML code + * assumes that the last value of the method is "implicitly" returned + * to the caller. Just save the last result as the return value. + * NOTE: this is optional because the ASL language does not actually + * support this behavior. + */ + if ((acpi_gbl_enable_interpreter_slack) && + (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Result of [%s] will be implicitly returned\n", + acpi_ps_get_opcode_name (op->common.aml_opcode))); + + /* Use the top of the result stack as the implicit return value */ + + walk_state->return_desc = walk_state->results->results.obj_desc[0]; + return_VALUE (TRUE); + } + + /* No parent, the return value cannot possibly be used */ + return_VALUE (FALSE); } - /* - * Get info on the parent. The root Op is AML_SCOPE - */ + /* Get info on the parent. The root_op is AML_SCOPE */ + parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op)); @@ -204,9 +224,9 @@ result_not_used: * * FUNCTION: acpi_ds_delete_result_if_not_used * - * PARAMETERS: Op - * result_obj - * walk_state + * PARAMETERS: Op - Current parse Op + * result_obj - Result of the operation + * walk_state - Current state * * RETURN: Status * @@ -313,7 +333,7 @@ acpi_ds_clear_operands ( u32 i; - ACPI_FUNCTION_TRACE_PTR ("acpi_ds_clear_operands", walk_state); + ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state); /* @@ -338,8 +358,9 @@ acpi_ds_clear_operands ( * * FUNCTION: acpi_ds_create_operand * - * PARAMETERS: walk_state - * Arg + * PARAMETERS: walk_state - Current walk state + * Arg - Parse object for the argument + * arg_index - Which argument (zero based) * * RETURN: Status * diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 02872ca22..56196605d 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -60,17 +60,18 @@ * Dispatch table for opcode classes */ static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = { - acpi_ex_opcode_1A_0T_0R, - acpi_ex_opcode_1A_0T_1R, - acpi_ex_opcode_1A_1T_0R, - acpi_ex_opcode_1A_1T_1R, - acpi_ex_opcode_2A_0T_0R, - acpi_ex_opcode_2A_0T_1R, - acpi_ex_opcode_2A_1T_1R, - acpi_ex_opcode_2A_2T_1R, - acpi_ex_opcode_3A_0T_0R, - acpi_ex_opcode_3A_1T_1R, - acpi_ex_opcode_6A_0T_1R}; + acpi_ex_opcode_0A_0T_1R, + acpi_ex_opcode_1A_0T_0R, + acpi_ex_opcode_1A_0T_1R, + acpi_ex_opcode_1A_1T_0R, + acpi_ex_opcode_1A_1T_1R, + acpi_ex_opcode_2A_0T_0R, + acpi_ex_opcode_2A_0T_1R, + acpi_ex_opcode_2A_1T_1R, + acpi_ex_opcode_2A_2T_1R, + acpi_ex_opcode_3A_0T_0R, + acpi_ex_opcode_3A_1T_1R, + acpi_ex_opcode_6A_0T_1R}; /***************************************************************************** * @@ -413,7 +414,7 @@ acpi_ds_exec_end_op ( * routine. There is one routine per opcode "type" based upon the * number of opcode arguments and return type. */ - status = acpi_gbl_op_type_dispatch [op_type] (walk_state); + status = acpi_gbl_op_type_dispatch[op_type] (walk_state); } else { /* @@ -425,7 +426,9 @@ acpi_ds_exec_end_op ( (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) && (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) && (walk_state->operands[0]->reference.opcode == - walk_state->operands[1]->reference.opcode)) { + walk_state->operands[1]->reference.opcode) && + (walk_state->operands[0]->reference.offset == + walk_state->operands[1]->reference.offset)) { status = AE_OK; } else { @@ -639,7 +642,8 @@ acpi_ds_exec_end_op ( * conditional predicate */ - if ((walk_state->control_state) && + if ((ACPI_SUCCESS (status)) && + (walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) && (walk_state->control_state->control.predicate_op == op)) { @@ -649,6 +653,19 @@ acpi_ds_exec_end_op ( cleanup: + + /* Invoke exception handler on error */ + + if (ACPI_FAILURE (status) && + acpi_gbl_exception_handler && + !(status & AE_CODE_CONTROL)) { + acpi_ex_exit_interpreter (); + status = acpi_gbl_exception_handler (status, + walk_state->method_node->name.integer, walk_state->opcode, + walk_state->aml_offset, NULL); + acpi_ex_enter_interpreter (); + } + if (walk_state->result_obj) { /* Break to debugger to display result */ diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 409aa6e95..f01f9c4fc 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -50,6 +50,9 @@ #include #include +#ifdef _ACPI_ASL_COMPILER +#include +#endif #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME ("dswload") @@ -179,6 +182,18 @@ acpi_ds_load1_begin_op ( */ status = acpi_ns_lookup (walk_state->scope_info, path, object_type, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); +#ifdef _ACPI_ASL_COMPILER + if (status == AE_NOT_FOUND) { + /* + * Table disassembly: + * Target of Scope() not found. Generate an External for it, and + * insert the name into the namespace. + */ + acpi_dm_add_to_external_list (path); + status = acpi_ns_lookup (walk_state->scope_info, path, object_type, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); + } +#endif if (ACPI_FAILURE (status)) { ACPI_REPORT_NSERROR (path, status); return (status); @@ -529,7 +544,16 @@ acpi_ds_load2_begin_op ( status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); if (ACPI_FAILURE (status)) { +#ifdef _ACPI_ASL_COMPILER + if (status == AE_NOT_FOUND) { + status = AE_OK; + } + else { + ACPI_REPORT_NSERROR (buffer_ptr, status); + } +#else ACPI_REPORT_NSERROR (buffer_ptr, status); +#endif return_ACPI_STATUS (status); } /* diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 2b3956226..5474776b6 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -51,6 +51,8 @@ ACPI_MODULE_NAME ("dswstate") +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_ds_result_insert @@ -174,6 +176,8 @@ acpi_ds_result_remove ( return (AE_OK); } +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * @@ -445,7 +449,7 @@ acpi_ds_result_stack_pop ( * Should be used with great care, if at all! * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_ds_obj_stack_delete_all ( struct acpi_walk_state *walk_state) @@ -467,6 +471,7 @@ acpi_ds_obj_stack_delete_all ( return_ACPI_STATUS (AE_OK); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -687,7 +692,7 @@ acpi_ds_obj_stack_pop_and_delete ( * be within the range of the current stack pointer. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE void * acpi_ds_obj_stack_get_value ( u32 index, @@ -712,6 +717,7 @@ acpi_ds_obj_stack_get_value ( return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) - index]); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -867,6 +873,7 @@ acpi_ds_create_walk_state ( status = acpi_ds_result_stack_push (walk_state); if (ACPI_FAILURE (status)) { + acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state); return_PTR (NULL); } @@ -906,8 +913,7 @@ acpi_ds_init_aml_walk ( struct acpi_namespace_node *method_node, u8 *aml_start, u32 aml_length, - union acpi_operand_object **params, - union acpi_operand_object **return_obj_desc, + struct acpi_parameter_info *info, u32 pass_number) { acpi_status status; @@ -926,8 +932,17 @@ acpi_ds_init_aml_walk ( /* The next_op of the next_walk will be the beginning of the method */ walk_state->next_op = NULL; - walk_state->params = params; - walk_state->caller_return_desc = return_obj_desc; + + if (info) { + if (info->parameter_type == ACPI_PARAM_GPE) { + walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info, + info->parameters); + } + else { + walk_state->params = info->parameters; + walk_state->caller_return_desc = &info->return_object; + } + } status = acpi_ps_init_scope (&walk_state->parser_state, op); if (ACPI_FAILURE (status)) { @@ -949,7 +964,7 @@ acpi_ds_init_aml_walk ( /* Init the method arguments */ - status = acpi_ds_method_data_init_args (params, ACPI_METHOD_NUM_ARGS, walk_state); + status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 56bb801e2..d80c42427 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1,6 +1,7 @@ /* * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $) * + * Copyright (C) 2004 Luming Yu * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh * @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -262,6 +264,7 @@ ec_read(u8 addr, u8 *val) else return err; } +EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) @@ -278,6 +281,7 @@ ec_write(u8 addr, u8 val) return err; } +EXPORT_SYMBOL(ec_write); static int @@ -381,7 +385,7 @@ end: acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); } -static void +static u32 acpi_ec_gpe_handler ( void *data) { @@ -389,12 +393,17 @@ acpi_ec_gpe_handler ( struct acpi_ec *ec = (struct acpi_ec *) data; if (!ec) - return; + return ACPI_INTERRUPT_NOT_HANDLED; acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_ec_gpe_query, ec); + + if (status == AE_OK) + return ACPI_INTERRUPT_HANDLED; + else + return ACPI_INTERRUPT_NOT_HANDLED; } /* -------------------------------------------------------------------------- @@ -436,9 +445,15 @@ acpi_ec_space_handler ( ACPI_FUNCTION_TRACE("acpi_ec_space_handler"); - if ((address > 0xFF) || (bit_width != 8) || !value || !handler_context) + if ((address > 0xFF) || !value || !handler_context) return_VALUE(AE_BAD_PARAMETER); + if(bit_width != 8) { + printk(KERN_WARNING PREFIX "acpi_ec_space_handler: bit_width should be 8\n"); + if (acpi_strict) + return_VALUE(AE_BAD_PARAMETER); + } + ec = (struct acpi_ec *) handler_context; switch (function) { @@ -479,41 +494,38 @@ struct proc_dir_entry *acpi_ec_dir; static int -acpi_ec_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +acpi_ec_read_info (struct seq_file *seq, void *offset) { - struct acpi_ec *ec = (struct acpi_ec *) data; - char *p = page; - int len = 0; + struct acpi_ec *ec = (struct acpi_ec *) seq->private; ACPI_FUNCTION_TRACE("acpi_ec_read_info"); - if (!ec || (off != 0)) + if (!ec) goto end; - p += sprintf(p, "gpe bit: 0x%02x\n", + seq_printf(seq, "gpe bit: 0x%02x\n", (u32) ec->gpe_bit); - p += sprintf(p, "ports: 0x%02x, 0x%02x\n", + seq_printf(seq, "ports: 0x%02x, 0x%02x\n", (u32) ec->status_addr.address, (u32) ec->data_addr.address); - p += sprintf(p, "use global lock: %s\n", + seq_printf(seq, "use global lock: %s\n", ec->global_lock?"yes":"no"); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return_VALUE(0); } +static int acpi_ec_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_ec_read_info, PDE(inode)->data); +} + +static struct file_operations acpi_ec_info_ops = { + .open = acpi_ec_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; static int acpi_ec_add_fs ( @@ -530,13 +542,17 @@ acpi_ec_add_fs ( return_VALUE(-ENODEV); } - entry = create_proc_read_entry(ACPI_EC_FILE_INFO, S_IRUGO, - acpi_device_dir(device), acpi_ec_read_info, - acpi_driver_data(device)); + entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO, + acpi_device_dir(device)); if (!entry) ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to create '%s' fs entry\n", ACPI_EC_FILE_INFO)); + else { + entry->proc_fops = &acpi_ec_info_ops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } return_VALUE(0); } @@ -729,6 +745,8 @@ acpi_ec_start ( if (ACPI_FAILURE(status)) { return_VALUE(-ENODEV); } + acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler (ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, @@ -814,6 +832,8 @@ acpi_ec_ecdt_probe (void) if (ACPI_FAILURE(status)) { goto error; } + acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index abdb3a5a2..558ec7b33 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -50,7 +50,7 @@ /******************************************************************************* * - * FUNCTION: acpi_ev_initialize + * FUNCTION: acpi_ev_initialize_events * * PARAMETERS: None * @@ -61,13 +61,13 @@ ******************************************************************************/ acpi_status -acpi_ev_initialize ( +acpi_ev_initialize_events ( void) { acpi_status status; - ACPI_FUNCTION_TRACE ("ev_initialize"); + ACPI_FUNCTION_TRACE ("ev_initialize_events"); /* Make sure we have ACPI tables */ @@ -104,7 +104,7 @@ acpi_ev_initialize ( /******************************************************************************* * - * FUNCTION: acpi_ev_handler_initialize + * FUNCTION: acpi_ev_install_xrupt_handlers * * PARAMETERS: None * @@ -115,13 +115,13 @@ acpi_ev_initialize ( ******************************************************************************/ acpi_status -acpi_ev_handler_initialize ( +acpi_ev_install_xrupt_handlers ( void) { acpi_status status; - ACPI_FUNCTION_TRACE ("ev_handler_initialize"); + ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers"); /* Install the SCI handler */ diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 221dca54d..0c54d314a 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -49,6 +49,253 @@ ACPI_MODULE_NAME ("evgpe") +/******************************************************************************* + * + * FUNCTION: acpi_ev_set_gpe_type + * + * PARAMETERS: gpe_event_info - GPE to set + * Type - New type + * + * RETURN: Status + * + * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) + * + ******************************************************************************/ + +acpi_status +acpi_ev_set_gpe_type ( + struct acpi_gpe_event_info *gpe_event_info, + u8 type) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ev_set_gpe_type"); + + + /* Validate type and update register enable masks */ + + switch (type) { + case ACPI_GPE_TYPE_WAKE: + case ACPI_GPE_TYPE_RUNTIME: + case ACPI_GPE_TYPE_WAKE_RUN: + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Disable the GPE if currently enabled */ + + status = acpi_ev_disable_gpe (gpe_event_info); + + /* Type was validated above */ + + gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ + gpe_event_info->flags |= type; /* Insert type */ + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_update_gpe_enable_masks + * + * PARAMETERS: gpe_event_info - GPE to update + * Type - What to do: ACPI_GPE_DISABLE or + * ACPI_GPE_ENABLE + * + * RETURN: Status + * + * DESCRIPTION: Updates GPE register enable masks based on the GPE type + * + ******************************************************************************/ + +acpi_status +acpi_ev_update_gpe_enable_masks ( + struct acpi_gpe_event_info *gpe_event_info, + u8 type) +{ + struct acpi_gpe_register_info *gpe_register_info; + u8 register_bit; + + + ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks"); + + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return_ACPI_STATUS (AE_NOT_EXIST); + } + register_bit = gpe_event_info->register_bit; + + /* 1) Disable case. Simply clear all enable bits */ + + if (type == ACPI_GPE_DISABLE) { + ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit); + ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit); + return_ACPI_STATUS (AE_OK); + } + + /* 2) Enable case. Set/Clear the appropriate enable bits */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit); + ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit); + break; + + case ACPI_GPE_TYPE_RUNTIME: + ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit); + ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + ACPI_SET_BIT (gpe_register_info->enable_for_wake, register_bit); + ACPI_SET_BIT (gpe_register_info->enable_for_run, register_bit); + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_enable_gpe + * + * PARAMETERS: gpe_event_info - GPE to enable + * write_to_hardware - Enable now, or just mark data structs + * (WAKE GPEs should be deferred) + * + * RETURN: Status + * + * DESCRIPTION: Enable a GPE based on the GPE type + * + ******************************************************************************/ + +acpi_status +acpi_ev_enable_gpe ( + struct acpi_gpe_event_info *gpe_event_info, + u8 write_to_hardware) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ev_enable_gpe"); + + + /* Make sure HW enable masks are updated */ + + status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Mark wake-enabled or HW enable, or both */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + + ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + + ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + + /*lint -fallthrough */ + + case ACPI_GPE_TYPE_RUNTIME: + + ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); + + if (write_to_hardware) { + /* Clear the GPE (of stale events), then enable it */ + + status = acpi_hw_clear_gpe (gpe_event_info); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Enable the requested runtime GPE */ + + status = acpi_hw_write_gpe_enable_reg (gpe_event_info); + } + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_disable_gpe + * + * PARAMETERS: gpe_event_info - GPE to disable + * + * RETURN: Status + * + * DESCRIPTION: Disable a GPE based on the GPE type + * + ******************************************************************************/ + +acpi_status +acpi_ev_disable_gpe ( + struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ev_disable_gpe"); + + + if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { + return_ACPI_STATUS (AE_OK); + } + + /* Make sure HW enable masks are updated */ + + status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Mark wake-disabled or HW disable, or both */ + + switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { + case ACPI_GPE_TYPE_WAKE: + ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + break; + + case ACPI_GPE_TYPE_WAKE_RUN: + ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); + + /*lint -fallthrough */ + + case ACPI_GPE_TYPE_RUNTIME: + + /* Disable the requested runtime GPE */ + + ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); + status = acpi_hw_write_gpe_enable_reg (gpe_event_info); + break; + + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + return_ACPI_STATUS (AE_OK); +} + + /******************************************************************************* * * FUNCTION: acpi_ev_get_gpe_event_info @@ -139,11 +386,12 @@ acpi_ev_gpe_detect ( u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u8 enabled_status_byte; struct acpi_gpe_register_info *gpe_register_info; - u32 in_value; + u32 status_reg; + u32 enable_reg; acpi_status status; struct acpi_gpe_block_info *gpe_block; - u32 i; - u32 j; + acpi_native_uint i; + acpi_native_uint j; ACPI_FUNCTION_NAME ("ev_gpe_detect"); @@ -171,33 +419,27 @@ acpi_ev_gpe_detect ( /* Read the Status Register */ - status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, + status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg, &gpe_register_info->status_address); - gpe_register_info->status = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; } /* Read the Enable Register */ - status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, + status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg, &gpe_register_info->enable_address); - gpe_register_info->enable = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, - "GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n", - ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address), - gpe_register_info->status, - ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address), - gpe_register_info->enable)); + "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", + gpe_register_info->base_gpe_number, status_reg, enable_reg)); /* First check if there is anything active at all in this register */ - enabled_status_byte = (u8) (gpe_register_info->status & - gpe_register_info->enable); + enabled_status_byte = (u8) (status_reg & enable_reg); if (!enabled_status_byte) { /* No active GPEs in this register, move on */ @@ -216,7 +458,7 @@ acpi_ev_gpe_detect ( */ int_status |= acpi_ev_gpe_dispatch ( &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j], - j + gpe_register_info->base_gpe_number); + (u32) j + gpe_register_info->base_gpe_number); } } } @@ -255,6 +497,7 @@ acpi_ev_asynch_execute_gpe_method ( u32 gpe_number = 0; acpi_status status; struct acpi_gpe_event_info local_gpe_event_info; + struct acpi_parameter_info info; ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method"); @@ -272,6 +515,10 @@ acpi_ev_asynch_execute_gpe_method ( return_VOID; } + /* Set the GPE flags for return to enabled state */ + + (void) acpi_ev_enable_gpe (gpe_event_info, FALSE); + /* * Take a snapshot of the GPE info for this level - we copy the * info to prevent a race condition with remove_handler/remove_block. @@ -283,23 +530,33 @@ acpi_ev_asynch_execute_gpe_method ( return_VOID; } - if (local_gpe_event_info.method_node) { + /* + * Must check for control method type dispatch one more + * time to avoid race with ev_gpe_install_handler + */ + if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { /* - * Invoke the GPE Method (_Lxx, _Exx): - * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx + * control method that corresponds to this GPE */ - status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL); + info.node = local_gpe_event_info.dispatch.method_node; + info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info); + info.parameter_type = ACPI_PARAM_GPE; + + status = acpi_ns_evaluate_by_handle (&info); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n", + ACPI_REPORT_ERROR (( + "%s while evaluating method [%4.4s] for GPE[%2X]\n", acpi_format_exception (status), - acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number)); + acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node), + gpe_number)); } } if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) { /* - * GPE is level-triggered, we clear the GPE status bit after handling - * the event. + * GPE is level-triggered, we clear the GPE status bit after + * handling the event. */ status = acpi_hw_clear_gpe (&local_gpe_event_info); if (ACPI_FAILURE (status)) { @@ -309,7 +566,7 @@ acpi_ev_asynch_execute_gpe_method ( /* Enable this GPE */ - (void) acpi_hw_enable_gpe (&local_gpe_event_info); + (void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info); return_VOID; } @@ -354,6 +611,15 @@ acpi_ev_gpe_dispatch ( } } + /* Save current system state */ + + if (acpi_gbl_system_awake_and_running) { + ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING); + } + else { + ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING); + } + /* * Dispatch the GPE to either an installed handler, or the control * method associated with this GPE (_Lxx or _Exx). @@ -361,10 +627,15 @@ acpi_ev_gpe_dispatch ( * If there is neither a handler nor a method, we disable the level to * prevent further events from coming in here. */ - if (gpe_event_info->handler) { - /* Invoke the installed handler (at interrupt level) */ + switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { + case ACPI_GPE_DISPATCH_HANDLER: - gpe_event_info->handler (gpe_event_info->context); + /* + * Invoke the installed handler (at interrupt level) + * Ignore return status for now. TBD: leave GPE disabled on error? + */ + (void) gpe_event_info->dispatch.handler->address ( + gpe_event_info->dispatch.handler->context); /* It is now safe to clear level-triggered events. */ @@ -377,13 +648,15 @@ acpi_ev_gpe_dispatch ( return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } } - } - else if (gpe_event_info->method_node) { + break; + + case ACPI_GPE_DISPATCH_METHOD: + /* * Disable GPE, so it doesn't keep firing before the method has a * chance to run. */ - status = acpi_hw_disable_gpe (gpe_event_info); + status = acpi_ev_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (( "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", @@ -402,8 +675,10 @@ acpi_ev_gpe_dispatch ( "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n", gpe_number)); } - } - else { + break; + + default: + /* No handler or method to run! */ ACPI_REPORT_ERROR (( @@ -414,15 +689,68 @@ acpi_ev_gpe_dispatch ( * Disable the GPE. The GPE will remain disabled until the ACPI * Core Subsystem is restarted, or a handler is installed. */ - status = acpi_hw_disable_gpe (gpe_event_info); + status = acpi_ev_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (( "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n", gpe_number)); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); } + break; } return_VALUE (ACPI_INTERRUPT_HANDLED); } + +#ifdef ACPI_GPE_NOTIFY_CHECK + +/******************************************************************************* + * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED + * + * FUNCTION: acpi_ev_check_for_wake_only_gpe + * + * PARAMETERS: gpe_event_info - info for this GPE + * + * RETURN: Status + * + * DESCRIPTION: Determine if a a GPE is "wake-only". + * + * Called from Notify() code in interpreter when a "device_wake" + * Notify comes in. + * + ******************************************************************************/ + +acpi_status +acpi_ev_check_for_wake_only_gpe ( + struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe"); + + + if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */ + ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ { + /* This must be a wake-only GPE, disable it */ + + status = acpi_ev_disable_gpe (gpe_event_info); + + /* Set GPE to wake-only. Do not change wake disabled/enabled status */ + + acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE); + + ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n", + gpe_event_info)); + + /* This was a wake-only GPE */ + + return_ACPI_STATUS (AE_WAKE_ONLY_GPE); + } + + return_ACPI_STATUS (AE_OK); +} +#endif + + diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index b1fbf7dec..dae8f8c31 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -53,7 +53,7 @@ * * FUNCTION: acpi_ev_valid_gpe_event * - * PARAMETERS: gpe_event_info - Info for this GPE + * PARAMETERS: gpe_event_info - Info for this GPE * * RETURN: TRUE if the gpe_event is valid * @@ -105,17 +105,18 @@ acpi_ev_valid_gpe_event ( * FUNCTION: acpi_ev_walk_gpe_list * * PARAMETERS: gpe_walk_callback - Routine called for each GPE block + * Flags - ACPI_NOT_ISR or ACPI_ISR * * RETURN: Status * * DESCRIPTION: Walk the GPE lists. - * FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ acpi_status acpi_ev_walk_gpe_list ( - ACPI_GPE_CALLBACK gpe_walk_callback) + ACPI_GPE_CALLBACK gpe_walk_callback, + u32 flags) { struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; @@ -125,7 +126,7 @@ acpi_ev_walk_gpe_list ( ACPI_FUNCTION_TRACE ("ev_walk_gpe_list"); - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR); + acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags); /* Walk the interrupt level descriptor list */ @@ -149,11 +150,58 @@ acpi_ev_walk_gpe_list ( } unlock_and_exit: - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR); + acpi_os_release_lock (acpi_gbl_gpe_lock, flags); return_ACPI_STATUS (status); } +/****************************************************************************** + * + * FUNCTION: acpi_ev_delete_gpe_handlers + * + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Delete all Handler objects found in the GPE data structs. + * Used only prior to termination. + * + ******************************************************************************/ + +acpi_status +acpi_ev_delete_gpe_handlers ( + struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block) +{ + struct acpi_gpe_event_info *gpe_event_info; + acpi_native_uint i; + acpi_native_uint j; + + + ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers"); + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j]; + + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { + ACPI_MEM_FREE (gpe_event_info->dispatch.handler); + gpe_event_info->dispatch.handler = NULL; + gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; + } + } + } + + return_ACPI_STATUS (AE_OK); +} + + /******************************************************************************* * * FUNCTION: acpi_ev_save_method_info @@ -188,6 +236,7 @@ acpi_ev_save_method_info ( u32 gpe_number; char name[ACPI_NAME_SIZE + 1]; u8 type; + acpi_status status; ACPI_FUNCTION_TRACE ("ev_save_method_info"); @@ -206,16 +255,16 @@ acpi_ev_save_method_info ( * 2) Edge/Level determination is based on the 2nd character * of the method name * - * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE if a - * _PRW object is found that points to this GPE. + * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE + * if a _PRW object is found that points to this GPE. */ switch (name[1]) { case 'L': - type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME; + type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': - type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME; + type = ACPI_GPE_EDGE_TRIGGERED; break; default: @@ -253,27 +302,35 @@ acpi_ev_save_method_info ( /* * Now we can add this information to the gpe_event_info block - * for use during dispatch of this GPE. + * for use during dispatch of this GPE. Default type is RUNTIME, although + * this may change when the _PRW methods are executed later. */ gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; - gpe_event_info->flags = type; - gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle; + gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD | + ACPI_GPE_TYPE_RUNTIME); + + gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle; + + /* Update enable mask, but don't enable the HW GPE as of yet */ + + status = acpi_ev_enable_gpe (gpe_event_info, FALSE); ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", name, gpe_number)); - return_ACPI_STATUS (AE_OK); + return_ACPI_STATUS (status); } /******************************************************************************* * - * FUNCTION: acpi_ev_get_gpe_type + * FUNCTION: acpi_ev_match_prw_and_gpe * * PARAMETERS: Callback from walk_namespace * - * RETURN: Status + * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is + * not aborted on a single _PRW failure. * * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a * Device. Run the _PRW method. If present, extract the GPE @@ -282,7 +339,7 @@ acpi_ev_save_method_info ( ******************************************************************************/ static acpi_status -acpi_ev_get_gpe_type ( +acpi_ev_match_prw_and_gpe ( acpi_handle obj_handle, u32 level, void *info, @@ -299,19 +356,18 @@ acpi_ev_get_gpe_type ( acpi_status status; - ACPI_FUNCTION_TRACE ("ev_get_gpe_type"); + ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe"); /* Check for a _PRW method under this device */ status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW, ACPI_BTYPE_PACKAGE, &pkg_desc); - if (status == AE_NOT_FOUND) { + if (ACPI_FAILURE (status)) { + /* Ignore all errors from _PRW, we don't want to abort the subsystem */ + return_ACPI_STATUS (AE_OK); } - else if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } /* The returned _PRW package must have at least two elements */ @@ -370,16 +426,21 @@ acpi_ev_get_gpe_type ( if ((gpe_device == target_gpe_device) && (gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { - /* Mark GPE for WAKE but DISABLED (even for wake) */ - gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; - gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE; + + /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ + + gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); + status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE); } cleanup: acpi_ut_remove_reference (pkg_desc); - - return_ACPI_STATUS (status); + return_ACPI_STATUS (AE_OK); } @@ -742,7 +803,7 @@ acpi_ev_create_gpe_info_blocks ( /* Init the event_info for each GPE within this register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - this_event->bit_mask = acpi_gbl_decode_to8bit[j]; + this_event->register_bit = acpi_gbl_decode_to8bit[j]; this_event->register_info = this_register; this_event++; } @@ -817,6 +878,7 @@ acpi_ev_create_gpe_block ( acpi_status status; struct acpi_gpe_walk_info gpe_info; + ACPI_FUNCTION_TRACE ("ev_create_gpe_block"); @@ -835,6 +897,7 @@ acpi_ev_create_gpe_block ( gpe_block->register_count = register_count; gpe_block->block_base_number = gpe_block_base_number; + gpe_block->node = gpe_device; ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address)); @@ -854,18 +917,6 @@ acpi_ev_create_gpe_block ( return_ACPI_STATUS (status); } - /* Dump info about this GPE block */ - - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, - "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n", - gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), - gpe_device->name.ascii, - gpe_block->register_count, - ACPI_FORMAT_UINT64 (gpe_block->block_address.address), - interrupt_level)); - /* Find all GPE methods (_Lxx, _Exx) for this block */ status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device, @@ -873,27 +924,28 @@ acpi_ev_create_gpe_block ( gpe_block, NULL); /* - * Runtime option: Should Wake GPEs be enabled at runtime? The default is - * No,they should only be enabled just as the machine goes to sleep. + * Runtime option: Should Wake GPEs be enabled at runtime? The default + * is No,they should only be enabled just as the machine goes to sleep. */ if (acpi_gbl_leave_wake_gpes_disabled) { /* - * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each - * GPE that has one or more _PRWs that reference it is by definition a - * WAKE GPE and will not be enabled while the machine is running.) + * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. + * (Each GPE that has one or more _PRWs that reference it is by + * definition a WAKE GPE and will not be enabled while the machine + * is running.) */ gpe_info.gpe_block = gpe_block; gpe_info.gpe_device = gpe_device; status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe, &gpe_info, NULL); } /* - * Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have - * a corresponding _Lxx or _Exx method. All other GPEs must be enabled via - * the acpi_enable_gpe() external interface. + * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs, + * and 2) have a corresponding _Lxx or _Exx method. All other GPEs must + * be enabled via the acpi_enable_gpe() external interface. */ wake_gpe_count = 0; gpe_enabled_count = 0; @@ -903,23 +955,33 @@ acpi_ev_create_gpe_block ( /* Get the info block for this particular GPE */ gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j]; - if ((gpe_event_info->method_node) && - ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) { - /* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */ - - status = acpi_hw_enable_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + + if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) && + (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } - if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) { + if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) { wake_gpe_count++; } } } + /* Dump info about this GPE block */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", + (u32) gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), + gpe_device->name.ascii, + gpe_block->register_count, + interrupt_level)); + + /* Enable all valid GPEs found above */ + + status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block); + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Found %u Wake, Enabled %u Runtime GPEs in this block\n", wake_gpe_count, gpe_enabled_count)); @@ -1056,7 +1118,8 @@ acpi_ev_gpe_initialize ( if ((register_count0 + register_count1) == 0) { /* GPEs are not required by ACPI, this is OK */ - ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "There are no GPE blocks defined in the FADT\n")); status = AE_OK; goto cleanup; } diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 1bfb10df3..35e61d522 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -88,9 +88,10 @@ acpi_ev_is_notify_object ( * * FUNCTION: acpi_ev_queue_notify_request * - * PARAMETERS: + * PARAMETERS: Node - NS node for the notified object + * notify_value - Value from the Notify() request * - * RETURN: None. + * RETURN: Status * * DESCRIPTION: Dispatch a device notification event to a previously * installed handler. @@ -139,14 +140,12 @@ acpi_ev_queue_notify_request ( acpi_notify_value_names[notify_value])); } else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "notify value: 0x%2.2x **Device Specific**\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n", notify_value)); } - /* - * Get the notify object attached to the NS Node - */ + /* Get the notify object attached to the NS Node */ + obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* We have the notify object, Get the right handler */ @@ -194,11 +193,13 @@ acpi_ev_queue_notify_request ( } if (!handler_obj) { - /* There is no per-device notify handler for this device */ - + /* + * There is no per-device notify handler for this device. + * This may or may not be a problem. + */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "No notify handler for [%4.4s] node %p\n", - acpi_ut_get_node_name (node), node)); + "No notify handler for Notify(%4.4s, %X) node %p\n", + acpi_ut_get_node_name (node), notify_value, node)); } return (status); @@ -209,7 +210,7 @@ acpi_ev_queue_notify_request ( * * FUNCTION: acpi_ev_notify_dispatch * - * PARAMETERS: + * PARAMETERS: Context - To be passsed to the notify handler * * RETURN: None. * @@ -276,6 +277,8 @@ acpi_ev_notify_dispatch ( * * FUNCTION: acpi_ev_global_lock_thread * + * PARAMETERS: Context - From thread interface, not used + * * RETURN: None * * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the @@ -309,7 +312,9 @@ acpi_ev_global_lock_thread ( * * FUNCTION: acpi_ev_global_lock_handler * - * RETURN: Status + * PARAMETERS: Context - From thread interface, not used + * + * RETURN: ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED * * DESCRIPTION: Invoked directly from the SCI handler when a global lock * release interrupt occurs. Grab the global lock and queue @@ -356,6 +361,8 @@ acpi_ev_global_lock_handler ( * * FUNCTION: acpi_ev_init_global_lock_handler * + * PARAMETERS: None + * * RETURN: Status * * DESCRIPTION: Install a handler for the global lock release event @@ -395,6 +402,8 @@ acpi_ev_init_global_lock_handler (void) * * FUNCTION: acpi_ev_acquire_global_lock * + * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. + * * RETURN: Status * * DESCRIPTION: Attempt to gain ownership of the Global Lock. @@ -462,6 +471,10 @@ acpi_ev_acquire_global_lock ( * * FUNCTION: acpi_ev_release_global_lock * + * PARAMETERS: None + * + * RETURN: Status + * * DESCRIPTION: Releases ownership of the Global Lock. * ******************************************************************************/ @@ -548,7 +561,7 @@ acpi_ev_terminate (void) /* Disable all GPEs in all GPE blocks */ - status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block); + status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR); /* Remove SCI handler */ @@ -558,6 +571,10 @@ acpi_ev_terminate (void) } } + /* Deallocate all handler objects installed within GPE info structs */ + + status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR); + /* Return to original mode if necessary */ if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index ec81e587f..b7ff3b162 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -61,7 +61,7 @@ static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA /******************************************************************************* * - * FUNCTION: acpi_ev_init_address_spaces + * FUNCTION: acpi_ev_install_region_handlers * * PARAMETERS: None * @@ -72,15 +72,20 @@ static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA ******************************************************************************/ acpi_status -acpi_ev_init_address_spaces ( +acpi_ev_install_region_handlers ( void) { acpi_status status; acpi_native_uint i; - ACPI_FUNCTION_TRACE ("ev_init_address_spaces"); + ACPI_FUNCTION_TRACE ("ev_install_region_handlers"); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + /* * All address spaces (PCI Config, EC, SMBus) are scope dependent * and registration must occur for a specific device. @@ -99,9 +104,8 @@ acpi_ev_init_address_spaces ( * has already been installed (via acpi_install_address_space_handler). * Similar for AE_SAME_HANDLER. */ - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, + status = acpi_ev_install_space_handler (acpi_gbl_root_node, acpi_gbl_default_address_spaces[i], ACPI_DEFAULT_HANDLER, NULL, NULL); switch (status) { @@ -111,15 +115,63 @@ acpi_ev_init_address_spaces ( /* These exceptions are all OK */ + status = AE_OK; break; default: - return_ACPI_STATUS (status); + goto unlock_and_exit; } } - return_ACPI_STATUS (AE_OK); +unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_initialize_op_regions + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG methods for all Operation Regions that have + * an installed default region handler. + * + ******************************************************************************/ + +acpi_status +acpi_ev_initialize_op_regions ( + void) +{ + acpi_status status; + acpi_native_uint i; + + + ACPI_FUNCTION_TRACE ("ev_initialize_op_regions"); + + + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* + * Run the _REG methods for op_regions in each default address space + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + /* TBD: Make sure handler is the DEFAULT handler, otherwise + * _REG will have already been run. + */ + status = acpi_ev_execute_reg_methods (acpi_gbl_root_node, + acpi_gbl_default_address_spaces[i]); + } + + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (status); } @@ -128,7 +180,7 @@ acpi_ev_init_address_spaces ( * FUNCTION: acpi_ev_execute_reg_method * * PARAMETERS: region_obj - Object structure - * Function - On (1) or Off (0) + * Function - Passed to _REG: On (1) or Off (0) * * RETURN: Status * @@ -138,11 +190,12 @@ acpi_ev_init_address_spaces ( acpi_status acpi_ev_execute_reg_method ( - union acpi_operand_object *region_obj, + union acpi_operand_object *region_obj, u32 function) { - union acpi_operand_object *params[3]; - union acpi_operand_object *region_obj2; + struct acpi_parameter_info info; + union acpi_operand_object *params[3]; + union acpi_operand_object *region_obj2; acpi_status status; @@ -159,10 +212,11 @@ acpi_ev_execute_reg_method ( } /* - * _REG method has two arguments - * Arg0: Integer: Operation region space ID + * The _REG method has two arguments: + * + * Arg0, Integer: Operation region space ID * Same value as region_obj->Region.space_id - * Arg1: Integer: connection status + * Arg1, Integer: connection status * 1 for connecting the handler, * 0 for disconnecting the handler * Passed as a parameter @@ -178,16 +232,21 @@ acpi_ev_execute_reg_method ( goto cleanup; } - /* Set up the parameter objects */ + /* Setup the parameter objects */ params[0]->integer.value = region_obj->region.space_id; params[1]->integer.value = function; params[2] = NULL; + info.node = region_obj2->extra.method_REG; + info.parameters = params; + info.parameter_type = ACPI_PARAM_ARGS; + /* Execute the method, no return value */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL)); - status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL); + ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname ( + ACPI_TYPE_METHOD, info.node, NULL)); + status = acpi_ns_evaluate_by_handle (&info); acpi_ut_remove_reference (params[1]); @@ -203,7 +262,6 @@ cleanup: * FUNCTION: acpi_ev_address_space_dispatch * * PARAMETERS: region_obj - Internal region object - * space_id - ID of the address space (0-255) * Function - Read or Write operation * Address - Where in the space to read or write * bit_width - Field width in bits (8, 16, 32, or 64) @@ -326,7 +384,7 @@ acpi_ev_address_space_dispatch ( ACPI_FORMAT_UINT64 (address), acpi_ut_get_region_name (region_obj->region.space_id))); - if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't @@ -347,7 +405,7 @@ acpi_ev_address_space_dispatch ( acpi_format_exception (status))); } - if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter @@ -366,8 +424,8 @@ acpi_ev_address_space_dispatch ( * * FUNCTION: acpi_ev_detach_region * - * PARAMETERS: region_obj - Region Object - * acpi_ns_is_locked - Namespace Region Already Locked? + * PARAMETERS: region_obj - Region Object + * acpi_ns_is_locked - Namespace Region Already Locked? * * RETURN: None * @@ -501,9 +559,9 @@ acpi_ev_detach_region( * * FUNCTION: acpi_ev_attach_region * - * PARAMETERS: handler_obj - Handler Object - * region_obj - Region Object - * acpi_ns_is_locked - Namespace Region Already Locked? + * PARAMETERS: handler_obj - Handler Object + * region_obj - Region Object + * acpi_ns_is_locked - Namespace Region Already Locked? * * RETURN: None * @@ -676,6 +734,273 @@ acpi_ev_install_handler ( return (status); } + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_space_handler + * + * PARAMETERS: Node - Namespace node for the device + * space_id - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * Assumes namespace is locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_install_space_handler ( + struct acpi_namespace_node *node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, + void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_status status; + acpi_object_type type; + u16 flags = 0; + + + ACPI_FUNCTION_TRACE ("ev_install_space_handler"); + + + /* + * This registration is valid for only the types below + * and the root. This is where the default handlers + * get placed. + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && + (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + handler = acpi_ex_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + handler = acpi_ex_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + handler = acpi_ex_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + case ACPI_ADR_SPACE_CMOS: + handler = acpi_ex_cmos_space_handler; + setup = acpi_ev_cmos_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + handler = acpi_ex_pci_bar_space_handler; + setup = acpi_ev_pci_bar_region_setup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + + default: + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object (node); + if (obj_desc) { + /* + * The attached device object already exists. + * Make sure the handler is not already installed. + */ + handler_obj = obj_desc->device.handler; + + /* Walk the handler list for this device */ + + while (handler_obj) { + /* Same space_id indicates a handler already installed */ + + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } + else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + handler_obj = handler_obj->address_space.next; + } + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", node)); + + /* obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } + else { + type = node->type; + } + + obj_desc = acpi_ut_create_internal_object (type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8) type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object (node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + acpi_ut_get_region_name (space_id), space_id, + acpi_ut_get_node_name (node), node, obj_desc)); + + /* + * Install the handler + * + * At this point there is no existing handler. + * Just allocate the object for the handler and link it + * into the list. + */ + handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8) space_id; + handler_obj->address_space.hflags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.handler; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.handler = handler_obj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, + handler_obj, NULL); + +unlock_and_exit: + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_ev_execute_reg_methods + * + * PARAMETERS: Node - Namespace node for the device + * space_id - The address space ID + * + * RETURN: Status + * + * DESCRIPTION: Run all _REG methods for the input Space ID; + * Note: assumes namespace is locked, or system init time. + * + ******************************************************************************/ + +acpi_status +acpi_ev_execute_reg_methods ( + struct acpi_namespace_node *node, + acpi_adr_space_type space_id) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("ev_execute_reg_methods"); + + + /* + * Run all _REG methods for all Operation Regions for this + * space ID. This is a separate walk in order to handle any + * interdependencies between regions and _REG methods. (i.e. handlers + * must be installed for all regions of this Space ID before we + * can run any _REG methods) + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, + &space_id, NULL); + + return_ACPI_STATUS (status); +} + + /******************************************************************************* * * FUNCTION: acpi_ev_reg_run @@ -693,19 +1018,13 @@ acpi_ev_reg_run ( void *context, void **return_value) { - union acpi_operand_object *handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; + acpi_adr_space_type space_id; acpi_status status; - handler_obj = (union acpi_operand_object *) context; - - /* Parameter validation */ - - if (!handler_obj) { - return (AE_OK); - } + space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context); /* Convert and validate the device handle */ @@ -732,10 +1051,9 @@ acpi_ev_reg_run ( return (AE_OK); } - /* Object is a Region */ - if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + if (obj_desc->region.space_id != space_id) { /* * This region is for a different address space * -- just ignore it diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 2e480d301..e19d82297 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -54,7 +54,7 @@ * * FUNCTION: acpi_ev_system_memory_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context @@ -108,7 +108,7 @@ acpi_ev_system_memory_region_setup ( * * FUNCTION: acpi_ev_io_space_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context @@ -144,7 +144,7 @@ acpi_ev_io_space_region_setup ( * * FUNCTION: acpi_ev_pci_config_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context @@ -317,7 +317,7 @@ acpi_ev_pci_config_region_setup ( * * FUNCTION: acpi_ev_pci_bar_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context @@ -348,7 +348,7 @@ acpi_ev_pci_bar_region_setup ( * * FUNCTION: acpi_ev_cmos_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context @@ -379,7 +379,7 @@ acpi_ev_cmos_region_setup ( * * FUNCTION: acpi_ev_default_region_setup * - * PARAMETERS: region_obj - Region we are interested in + * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index d33b99057..e38de807d 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -51,6 +52,52 @@ ACPI_MODULE_NAME ("evxface") +/******************************************************************************* + * + * FUNCTION: acpi_install_exception_handler + * + * PARAMETERS: Handler - Pointer to the handler function for the + * event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_install_exception_handler ( + acpi_exception_handler handler) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("acpi_install_exception_handler"); + + + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Don't allow two handlers. */ + + if (acpi_gbl_exception_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_exception_handler = handler; + +cleanup: + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (status); +} +#endif /* ACPI_FUTURE_USAGE */ + + /******************************************************************************* * * FUNCTION: acpi_install_fixed_event_handler @@ -121,6 +168,7 @@ cleanup: (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_install_fixed_event_handler); /******************************************************************************* @@ -178,6 +226,7 @@ acpi_remove_fixed_event_handler ( (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_remove_fixed_event_handler); /******************************************************************************* @@ -188,6 +237,7 @@ acpi_remove_fixed_event_handler ( * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device * Handler - Address of the handler * Context - Value passed to the handler on each GPE * @@ -243,20 +293,21 @@ acpi_install_notify_handler ( if (device == ACPI_ROOT_OBJECT) { /* Make sure the handler is not already installed */ - if (((handler_type == ACPI_SYSTEM_NOTIFY) && - acpi_gbl_system_notify.handler) || - ((handler_type == ACPI_DEVICE_NOTIFY) && + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { acpi_gbl_system_notify.node = node; acpi_gbl_system_notify.handler = handler; acpi_gbl_system_notify.context = context; } - else /* ACPI_DEVICE_NOTIFY */ { + + if (handler_type & ACPI_DEVICE_NOTIFY) { acpi_gbl_device_notify.node = node; acpi_gbl_device_notify.handler = handler; acpi_gbl_device_notify.context = context; @@ -284,9 +335,9 @@ acpi_install_notify_handler ( if (obj_desc) { /* Object exists - make sure there's no handler */ - if (((handler_type == ACPI_SYSTEM_NOTIFY) && + if (((handler_type & ACPI_SYSTEM_NOTIFY) && obj_desc->common_notify.system_notify) || - ((handler_type == ACPI_DEVICE_NOTIFY) && + ((handler_type & ACPI_DEVICE_NOTIFY) && obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; @@ -308,7 +359,6 @@ acpi_install_notify_handler ( /* Remove local reference to the object */ acpi_ut_remove_reference (obj_desc); - if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -326,12 +376,19 @@ acpi_install_notify_handler ( notify_obj->notify.handler = handler; notify_obj->notify.context = context; - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { obj_desc->common_notify.system_notify = notify_obj; } - else /* ACPI_DEVICE_NOTIFY */ { + + if (handler_type & ACPI_DEVICE_NOTIFY) { obj_desc->common_notify.device_notify = notify_obj; } + + if (handler_type == ACPI_ALL_NOTIFY) { + /* Extra ref if installed in both */ + + acpi_ut_add_reference (notify_obj); + } } @@ -339,6 +396,7 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_install_notify_handler); /******************************************************************************* @@ -349,7 +407,9 @@ unlock_and_exit: * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) + * ACPI_ALL_NOTIFY: both system and device * Handler - Address of the handler + * * RETURN: Status * * DESCRIPTION: Remove a handler for notifies on an ACPI device @@ -392,15 +452,14 @@ acpi_remove_notify_handler ( goto unlock_and_exit; } - /* - * Root Object - */ + /* Root Object */ + if (device == ACPI_ROOT_OBJECT) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n")); - if (((handler_type == ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_system_notify.handler) || - ((handler_type == ACPI_DEVICE_NOTIFY) && + if (((handler_type & ACPI_SYSTEM_NOTIFY) && + !acpi_gbl_system_notify.handler) || + ((handler_type & ACPI_DEVICE_NOTIFY) && !acpi_gbl_device_notify.handler)) { status = AE_NOT_EXIST; goto unlock_and_exit; @@ -415,21 +474,21 @@ acpi_remove_notify_handler ( return_ACPI_STATUS (status); } - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { acpi_gbl_system_notify.node = NULL; acpi_gbl_system_notify.handler = NULL; acpi_gbl_system_notify.context = NULL; } - else { + + if (handler_type & ACPI_DEVICE_NOTIFY) { acpi_gbl_device_notify.node = NULL; acpi_gbl_device_notify.handler = NULL; acpi_gbl_device_notify.context = NULL; } } - /* - * All Other Objects - */ + /* All Other Objects */ + else { /* Notifies allowed on this object? */ @@ -448,38 +507,47 @@ acpi_remove_notify_handler ( /* Object exists - make sure there's an existing handler */ - if (handler_type == ACPI_SYSTEM_NOTIFY) { + if (handler_type & ACPI_SYSTEM_NOTIFY) { notify_obj = obj_desc->common_notify.system_notify; - } - else { - notify_obj = obj_desc->common_notify.device_notify; - } + if ((!notify_obj) || + (notify_obj->notify.handler != handler)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ - if ((!notify_obj) || - (notify_obj->notify.handler != handler)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - /* Make sure all deferred tasks are completed */ + /* Remove the handler */ + obj_desc->common_notify.system_notify = NULL; + acpi_ut_remove_reference (notify_obj); + } - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - acpi_os_wait_events_complete(NULL); - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + if (handler_type & ACPI_DEVICE_NOTIFY) { + notify_obj = obj_desc->common_notify.device_notify; + if ((!notify_obj) || + (notify_obj->notify.handler != handler)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ - /* Remove the handler */ + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + acpi_os_wait_events_complete(NULL); + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.system_notify = NULL; - } - else { + /* Remove the handler */ obj_desc->common_notify.device_notify = NULL; + acpi_ut_remove_reference (notify_obj); } - - acpi_ut_remove_reference (notify_obj); } @@ -487,6 +555,7 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_remove_notify_handler); /******************************************************************************* @@ -497,7 +566,7 @@ unlock_and_exit: * gpe_block - GPE block (NULL == FADT GPEs) * Type - Whether this GPE should be treated as an * edge- or level-triggered interrupt. - * Handler - Address of the handler + * Address - Address of the handler * Context - Value passed to the handler on each GPE * * RETURN: Status @@ -511,11 +580,12 @@ acpi_install_gpe_handler ( acpi_handle gpe_device, u32 gpe_number, u32 type, - acpi_gpe_handler handler, + acpi_event_handler address, void *context) { - acpi_status status; struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler"); @@ -523,7 +593,7 @@ acpi_install_gpe_handler ( /* Parameter validation */ - if (!handler) { + if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -542,33 +612,48 @@ acpi_install_gpe_handler ( /* Make sure that there isn't a handler there already */ - if (gpe_event_info->handler) { + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } - /* Install the handler */ + /* Allocate and init handler object */ - acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); - gpe_event_info->handler = handler; - gpe_event_info->context = context; - gpe_event_info->flags = (u8) type; - acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info)); + if (!handler) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } - /* Clear the GPE (of stale events), the enable it */ + handler->address = address; + handler->context = context; + handler->method_node = gpe_event_info->dispatch.method_node; - status = acpi_hw_clear_gpe (gpe_event_info); + /* Disable the GPE before installing the handler */ + + status = acpi_ev_disable_gpe (gpe_event_info); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_enable_gpe (gpe_event_info); + /* Install the handler */ + + acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + gpe_event_info->dispatch.handler = handler; + + /* Setup up dispatch flags to indicate handler (vs. method) */ + + gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ + gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); + + acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_install_gpe_handler); /******************************************************************************* @@ -577,7 +662,7 @@ unlock_and_exit: * * PARAMETERS: gpe_number - The event to remove a handler * gpe_block - GPE block (NULL == FADT GPEs) - * Handler - Address of the handler + * Address - Address of the handler * * RETURN: Status * @@ -589,10 +674,11 @@ acpi_status acpi_remove_gpe_handler ( acpi_handle gpe_device, u32 gpe_number, - acpi_gpe_handler handler) + acpi_event_handler address) { - acpi_status status; struct acpi_gpe_event_info *gpe_event_info; + struct acpi_handler_info *handler; + acpi_status status; ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler"); @@ -600,7 +686,7 @@ acpi_remove_gpe_handler ( /* Parameter validation */ - if (!handler) { + if (!address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -617,21 +703,27 @@ acpi_remove_gpe_handler ( goto unlock_and_exit; } - /* Disable the GPE before removing the handler */ + /* Make sure that a handler is indeed installed */ - status = acpi_hw_disable_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) { + status = AE_NOT_EXIST; goto unlock_and_exit; } /* Make sure that the installed handler is the same */ - if (gpe_event_info->handler != handler) { - (void) acpi_hw_enable_gpe (gpe_event_info); + if (gpe_event_info->dispatch.handler->address != address) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } + /* Disable the GPE before removing the handler */ + + status = acpi_ev_disable_gpe (gpe_event_info); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + /* Make sure all deferred tasks are completed */ (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); @@ -644,15 +736,27 @@ acpi_remove_gpe_handler ( /* Remove the handler */ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); - gpe_event_info->handler = NULL; - gpe_event_info->context = NULL; + handler = gpe_event_info->dispatch.handler; + + /* Restore Method node (if any), set dispatch flags */ + + gpe_event_info->dispatch.method_node = handler->method_node; + gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ + if (handler->method_node) { + gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; + } acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); + /* Now we can free the handler object */ + + ACPI_MEM_FREE (handler); + unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_remove_gpe_handler); /******************************************************************************* @@ -695,6 +799,7 @@ acpi_acquire_global_lock ( return (status); } +EXPORT_SYMBOL(acpi_acquire_global_lock); /******************************************************************************* @@ -723,5 +828,5 @@ acpi_release_global_lock ( status = acpi_ev_release_global_lock (); return (status); } - +EXPORT_SYMBOL(acpi_release_global_lock); diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 640f51fb0..ddd100d81 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -200,16 +201,16 @@ acpi_enable_event ( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_enable_event); /******************************************************************************* * - * FUNCTION: acpi_enable_gpe + * FUNCTION: acpi_set_gpe_type * * PARAMETERS: gpe_device - Parent GPE Device * gpe_number - GPE level within the GPE block - * Flags - Just enable, or also wake enable? - * Called from ISR or not + * Type - New GPE type * * RETURN: Status * @@ -218,26 +219,17 @@ acpi_enable_event ( ******************************************************************************/ acpi_status -acpi_enable_gpe ( +acpi_set_gpe_type ( acpi_handle gpe_device, u32 gpe_number, - u32 flags) + u8 type) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE ("acpi_enable_gpe"); - + ACPI_FUNCTION_TRACE ("acpi_set_gpe_type"); - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - } /* Ensure that we have a valid GPE number */ @@ -247,93 +239,76 @@ acpi_enable_gpe ( goto unlock_and_exit; } - /* Check for Wake vs Runtime GPE */ - - if (flags & ACPI_EVENT_WAKE_ENABLE) { - /* Ensure the requested wake GPE is disabled */ - - status = acpi_hw_disable_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } - - /* Defer Enable of Wake GPE until sleep time */ - - acpi_hw_enable_gpe_for_wakeup (gpe_event_info); + if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { + return_ACPI_STATUS (AE_OK); } - else { - /* Enable the requested runtime GPE */ - status = acpi_hw_enable_gpe (gpe_event_info); - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } - } + /* Set the new type (will disable GPE if currently enabled) */ + status = acpi_ev_set_gpe_type (gpe_event_info, type); unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); - } return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_set_gpe_type); /******************************************************************************* * - * FUNCTION: acpi_disable_event + * FUNCTION: acpi_enable_gpe * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved + * PARAMETERS: gpe_device - Parent GPE Device + * gpe_number - GPE level within the GPE block + * Flags - Just enable, or also wake enable? + * Called from ISR or not * * RETURN: Status * - * DESCRIPTION: Disable an ACPI event (fixed) + * DESCRIPTION: Enable an ACPI event (general purpose) * ******************************************************************************/ acpi_status -acpi_disable_event ( - u32 event, +acpi_enable_gpe ( + acpi_handle gpe_device, + u32 gpe_number, u32 flags) { acpi_status status = AE_OK; - u32 value; + struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE ("acpi_disable_event"); + ACPI_FUNCTION_TRACE ("acpi_enable_gpe"); - /* Decode the Fixed Event */ + /* Use semaphore lock if not executing at interrupt level */ - if (event > ACPI_EVENT_MAX) { - return_ACPI_STATUS (AE_BAD_PARAMETER); + if (flags & ACPI_NOT_ISR) { + status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } - /* - * Disable the requested fixed event (by writing a zero to the - * enable register bit) - */ - status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, - 0, ACPI_MTX_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + /* Ensure that we have a valid GPE number */ - status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, - &value, ACPI_MTX_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; } - if (value != 0) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Could not disable %s events\n", acpi_ut_get_event_name (event))); - return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); - } + /* Perform the enable */ + + status = acpi_ev_enable_gpe (gpe_event_info, TRUE); +unlock_and_exit: + if (flags & ACPI_NOT_ISR) { + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); + } return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_enable_gpe); /******************************************************************************* @@ -342,7 +317,7 @@ acpi_disable_event ( * * PARAMETERS: gpe_device - Parent GPE Device * gpe_number - GPE level within the GPE block - * Flags - Just enable, or also wake enable? + * Flags - Just disable, or also wake disable? * Called from ISR or not * * RETURN: Status @@ -381,23 +356,72 @@ acpi_disable_gpe ( goto unlock_and_exit; } + status = acpi_ev_disable_gpe (gpe_event_info); + +unlock_and_exit: + if (flags & ACPI_NOT_ISR) { + (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); + } + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: acpi_disable_event + * + * PARAMETERS: Event - The fixed eventto be enabled + * Flags - Reserved + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (fixed) + * + ******************************************************************************/ + +acpi_status +acpi_disable_event ( + u32 event, + u32 flags) +{ + acpi_status status = AE_OK; + u32 value; + + + ACPI_FUNCTION_TRACE ("acpi_disable_event"); + + + /* Decode the Fixed Event */ + + if (event > ACPI_EVENT_MAX) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + /* - * Only disable the requested GPE number for wake if specified. - * Otherwise, turn it totally off + * Disable the requested fixed event (by writing a zero to the + * enable register bit) */ - if (flags & ACPI_EVENT_WAKE_DISABLE) { - acpi_hw_disable_gpe_for_wakeup (gpe_event_info); + status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, + 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - else { - status = acpi_hw_disable_gpe (gpe_event_info); + + status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, + &value, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } -unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); + if (value != 0) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Could not disable %s events\n", acpi_ut_get_event_name (event))); + return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } + return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_disable_event); /******************************************************************************* @@ -411,7 +435,7 @@ unlock_and_exit: * DESCRIPTION: Clear an ACPI event (fixed) * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_clear_event ( u32 event) @@ -437,6 +461,8 @@ acpi_clear_event ( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_clear_event); +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -493,6 +519,8 @@ unlock_and_exit: } +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_get_event_status @@ -594,6 +622,7 @@ unlock_and_exit: } return_ACPI_STATUS (status); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -686,6 +715,7 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_install_gpe_block); /******************************************************************************* @@ -746,4 +776,4 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } - +EXPORT_SYMBOL(acpi_remove_gpe_block); diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index b31d4fdfe..58332cd4e 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -42,11 +42,11 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include #include -#include #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evxfregn") @@ -76,12 +76,8 @@ acpi_install_address_space_handler ( acpi_adr_space_setup setup, void *context) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; struct acpi_namespace_node *node; acpi_status status; - acpi_object_type type; - u16 flags = 0; ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler"); @@ -106,207 +102,22 @@ acpi_install_address_space_handler ( goto unlock_and_exit; } - /* - * This registration is valid for only the types below - * and the root. This is where the default handlers - * get placed. - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && - (node != acpi_gbl_root_node)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - if (handler == ACPI_DEFAULT_HANDLER) { - flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - handler = acpi_ex_system_memory_space_handler; - setup = acpi_ev_system_memory_region_setup; - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - handler = acpi_ex_system_io_space_handler; - setup = acpi_ev_io_space_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_CONFIG: - handler = acpi_ex_pci_config_space_handler; - setup = acpi_ev_pci_config_region_setup; - break; - - case ACPI_ADR_SPACE_CMOS: - handler = acpi_ex_cmos_space_handler; - setup = acpi_ev_cmos_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - handler = acpi_ex_pci_bar_space_handler; - setup = acpi_ev_pci_bar_region_setup; - break; - - case ACPI_ADR_SPACE_DATA_TABLE: - handler = acpi_ex_data_table_space_handler; - setup = NULL; - break; - - default: - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } - - /* If the caller hasn't specified a setup routine, use the default */ - - if (!setup) { - setup = acpi_ev_default_region_setup; - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object (node); - if (obj_desc) { - /* - * The attached device object already exists. - * Make sure the handler is not already installed. - */ - handler_obj = obj_desc->device.handler; - - /* Walk the handler list for this device */ - - while (handler_obj) { - /* Same space_id indicates a handler already installed */ - - if(handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler == handler) { - /* - * It is (relatively) OK to attempt to install the SAME - * handler twice. This can easily happen with PCI_Config space. - */ - status = AE_SAME_HANDLER; - goto unlock_and_exit; - } - else { - /* A handler is already installed */ - - status = AE_ALREADY_EXISTS; - } - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - handler_obj = handler_obj->address_space.next; - } - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, - "Creating object on Device %p while installing handler\n", node)); - - /* obj_desc does not exist, create one */ + /* Install the handler for all Regions for this Space ID */ - if (node->type == ACPI_TYPE_ANY) { - type = ACPI_TYPE_DEVICE; - } - else { - type = node->type; - } - - obj_desc = acpi_ut_create_internal_object (type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init new descriptor */ - - obj_desc->common.type = (u8) type; - - /* Attach the new object to the Node */ - - status = acpi_ns_attach_object (node, obj_desc, type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference (obj_desc); - - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } - } - - ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, - "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name (space_id), space_id, - acpi_ut_get_node_name (node), node, obj_desc)); - - /* - * Install the handler - * - * At this point there is no existing handler. - * Just allocate the object for the handler and link it - * into the list. - */ - handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); - if (!handler_obj) { - status = AE_NO_MEMORY; + status = acpi_ev_install_space_handler (node, space_id, handler, setup, context); + if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - /* Init handler obj */ - - handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.hflags = flags; - handler_obj->address_space.region_list = NULL; - handler_obj->address_space.node = node; - handler_obj->address_space.handler = handler; - handler_obj->address_space.context = context; - handler_obj->address_space.setup = setup; - - /* Install at head of Device.address_space list */ - - handler_obj->address_space.next = obj_desc->device.handler; - - /* - * The Device object is the first reference on the handler_obj. - * Each region that uses the handler adds a reference. - */ - obj_desc->device.handler = handler_obj; - - /* - * Walk the namespace finding all of the regions this - * handler will manage. - * - * Start at the device and search the branch toward - * the leaf nodes until either the leaf is encountered or - * a device is detected that has an address handler of the - * same type. - * - * In either case, back up and search down the remainder - * of the branch - */ - status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, - handler_obj, NULL); - - /* - * Now we can run the _REG methods for all Regions for this - * space ID. This is a separate walk in order to handle any - * interdependencies between regions and _REG methods. (i.e. handlers - * must be installed for all regions of this Space ID before we - * can run any _REG methods. - */ - status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, - handler_obj, NULL); + /* Run all _REG methods for this address space */ + + status = acpi_ev_execute_reg_methods (node, space_id); unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_install_address_space_handler); /******************************************************************************* @@ -432,5 +243,5 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } - +EXPORT_SYMBOL(acpi_remove_address_space_handler); diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index dfe7e0463..1e6a89805 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -48,6 +48,7 @@ #include #include #include +#include #define _COMPONENT ACPI_EXECUTER @@ -285,7 +286,7 @@ acpi_ex_load_op ( union acpi_operand_object *ddb_handle; union acpi_operand_object *buffer_desc = NULL; struct acpi_table_header *table_ptr = NULL; - u8 *table_data_ptr; + acpi_physical_address address; struct acpi_table_header table_header; u32 i; @@ -300,18 +301,39 @@ acpi_ex_load_op ( ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n", obj_desc, acpi_ut_get_object_type_name (obj_desc))); - /* Get the table header */ + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them now and save the results. + */ + if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_region_arguments (obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* Get the base physical address of the region */ + + address = obj_desc->region.address; + + /* Get the table length from the table header */ table_header.length = 0; - for (i = 0; i < sizeof (struct acpi_table_header); i++) { + for (i = 0; i < 8; i++) { status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, - (acpi_physical_address) i, 8, + (acpi_physical_address) (i + address), 8, ((u8 *) &table_header) + i); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } + /* Sanity check the table length */ + + if (table_header.length < sizeof (struct acpi_table_header)) { + return_ACPI_STATUS (AE_BAD_HEADER); + } + /* Allocate a buffer for the entire table */ table_ptr = ACPI_MEM_ALLOCATE (table_header.length); @@ -319,17 +341,12 @@ acpi_ex_load_op ( return_ACPI_STATUS (AE_NO_MEMORY); } - /* Copy the header to the buffer */ - - ACPI_MEMCPY (table_ptr, &table_header, sizeof (struct acpi_table_header)); - table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (struct acpi_table_header)); - - /* Get the table from the op region */ + /* Get the entire table from the op region */ for (i = 0; i < table_header.length; i++) { status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ, - (acpi_physical_address) i, 8, - ((u8 *) table_data_ptr + i)); + (acpi_physical_address) (i + address), 8, + ((u8 *) table_ptr + i)); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -355,6 +372,12 @@ acpi_ex_load_op ( } table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer); + + /* Sanity check the table length */ + + if (table_ptr->length < sizeof (struct acpi_table_header)) { + return_ACPI_STATUS (AE_BAD_HEADER); + } break; diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 04c04e4ae..a29b8653c 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -58,7 +58,7 @@ * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new Integer object is returned - * walk_state - Current method state + * Flags - Used for string conversion * * RETURN: Status * @@ -70,13 +70,13 @@ acpi_status acpi_ex_convert_to_integer ( union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc, - struct acpi_walk_state *walk_state) + u32 flags) { - u32 i; - union acpi_operand_object *ret_desc; - u32 count; + union acpi_operand_object *return_desc; u8 *pointer; acpi_integer result; + u32 i; + u32 count; acpi_status status; @@ -85,15 +85,17 @@ acpi_ex_convert_to_integer ( switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_INTEGER: + + /* No conversion necessary */ + *result_desc = obj_desc; return_ACPI_STATUS (AE_OK); + case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: - pointer = (u8 *) obj_desc->string.pointer; - count = obj_desc->string.length; - break; - case ACPI_TYPE_BUFFER: + /* Note: Takes advantage of common buffer/string fields */ + pointer = obj_desc->buffer.pointer; count = obj_desc->buffer.length; break; @@ -126,10 +128,12 @@ acpi_ex_convert_to_integer ( case ACPI_TYPE_STRING: /* - * Convert string to an integer - * String must be hexadecimal as per the ACPI specification + * Convert string to an integer - for most cases, the string must be + * hexadecimal as per the ACPI specification. The only exception (as + * of ACPI 3.0) is that the to_integer() operator allows both decimal + * and hexadecimal strings (hex prefixed with "0x"). */ - status = acpi_ut_strtoul64 ((char *) pointer, 16, &result); + status = acpi_ut_strtoul64 ((char *) pointer, flags, &result); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -139,8 +143,8 @@ acpi_ex_convert_to_integer ( case ACPI_TYPE_BUFFER: /* - * Buffer conversion - we simply grab enough raw data from the - * buffer to fill an integer + * Convert buffer to an integer - we simply grab enough raw data + * from the buffer to fill an integer */ for (i = 0; i < count; i++) { /* @@ -161,27 +165,15 @@ acpi_ex_convert_to_integer ( /* * Create a new integer */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); - if (!ret_desc) { + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!return_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the Result */ - ret_desc->integer.value = result; - - /* - * If we are about to overwrite the original object on the operand stack, - * we must remove a reference on the original object because we are - * essentially removing it from the stack. - */ - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - - *result_desc = ret_desc; + return_desc->integer.value = result; + *result_desc = return_desc; return_ACPI_STATUS (AE_OK); } @@ -193,7 +185,6 @@ acpi_ex_convert_to_integer ( * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String * result_desc - Where the new buffer object is returned - * walk_state - Current method state * * RETURN: Status * @@ -204,11 +195,9 @@ acpi_ex_convert_to_integer ( acpi_status acpi_ex_convert_to_buffer ( union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc, - struct acpi_walk_state *walk_state) + union acpi_operand_object **result_desc) { - union acpi_operand_object *ret_desc; - u32 i; + union acpi_operand_object *return_desc; u8 *new_buf; @@ -230,17 +219,17 @@ acpi_ex_convert_to_buffer ( * Create a new Buffer object. * Need enough space for one integer */ - ret_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width); - if (!ret_desc) { + return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width); + if (!return_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Copy the integer to the buffer */ + /* Copy the integer to the buffer, LSB first */ - new_buf = ret_desc->buffer.pointer; - for (i = 0; i < acpi_gbl_integer_byte_width; i++) { - new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8)); - } + new_buf = return_desc->buffer.pointer; + ACPI_MEMCPY (new_buf, + &obj_desc->integer.value, + acpi_gbl_integer_byte_width); break; @@ -250,14 +239,14 @@ acpi_ex_convert_to_buffer ( * Create a new Buffer object * Size will be the string length */ - ret_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length); - if (!ret_desc) { + return_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length); + if (!return_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the string to the buffer */ - new_buf = ret_desc->buffer.pointer; + new_buf = return_desc->buffer.pointer; ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer, obj_desc->string.length); break; @@ -269,32 +258,20 @@ acpi_ex_convert_to_buffer ( /* Mark buffer initialized */ - ret_desc->common.flags |= AOPOBJ_DATA_VALID; - - /* - * If we are about to overwrite the original object on the operand stack, - * we must remove a reference on the original object because we are - * essentially removing it from the stack. - */ - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - - *result_desc = ret_desc; + return_desc->common.flags |= AOPOBJ_DATA_VALID; + *result_desc = return_desc; return_ACPI_STATUS (AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_ex_convert_ascii + * FUNCTION: acpi_ex_convert_to_ascii * * PARAMETERS: Integer - Value to be converted - * Base - 10 or 16 + * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX * String - Where the string is returned - * data_width - Size of data item to be converted + * data_width - Size of data item to be converted, in bytes * * RETURN: Actual string length * @@ -305,79 +282,81 @@ acpi_ex_convert_to_buffer ( u32 acpi_ex_convert_to_ascii ( acpi_integer integer, - u32 base, + u16 base, u8 *string, u8 data_width) { - u32 i; - u32 j; - u32 k = 0; - char hex_digit; acpi_integer digit; + acpi_native_uint i; + acpi_native_uint j; + acpi_native_uint k = 0; + acpi_native_uint hex_length; + acpi_native_uint decimal_length; u32 remainder; - u32 length; - u8 leading_zero; + u8 supress_zeros; ACPI_FUNCTION_ENTRY (); - if (data_width < sizeof (acpi_integer)) { - leading_zero = FALSE; - length = data_width; - } - else { - leading_zero = TRUE; - length = sizeof (acpi_integer); - } - switch (base) { case 10: + /* Setup max length for the decimal number */ + + switch (data_width) { + case 1: + decimal_length = ACPI_MAX8_DECIMAL_DIGITS; + break; + + case 4: + decimal_length = ACPI_MAX32_DECIMAL_DIGITS; + break; + + case 8: + default: + decimal_length = ACPI_MAX64_DECIMAL_DIGITS; + break; + } + + supress_zeros = TRUE; /* No leading zeros */ remainder = 0; - for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) { + + for (i = decimal_length; i > 0; i--) { /* Divide by nth factor of 10 */ digit = integer; for (j = 0; j < i; j++) { - (void) acpi_ut_short_divide (&digit, 10, &digit, &remainder); + (void) acpi_ut_short_divide (digit, 10, &digit, &remainder); } - /* Create the decimal digit */ + /* Handle leading zeros */ if (remainder != 0) { - leading_zero = FALSE; + supress_zeros = FALSE; } - if (!leading_zero) { + if (!supress_zeros) { string[k] = (u8) (ACPI_ASCII_ZERO + remainder); k++; } } break; - case 16: - /* Copy the integer to the buffer */ + hex_length = ACPI_MUL_2 (data_width); /* 2 ascii hex chars per data byte */ - for (i = 0, j = ((length * 2) -1); i < (length * 2); i++, j--) { + for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) { + /* Get one hex digit, most significant digits first */ - hex_digit = acpi_ut_hex_to_ascii_char (integer, (j * 4)); - if (hex_digit != ACPI_ASCII_ZERO) { - leading_zero = FALSE; - } - - if (!leading_zero) { - string[k] = (u8) hex_digit; - k++; - } + string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j)); + k++; } break; - default: - break; + return (0); } /* @@ -392,7 +371,7 @@ acpi_ex_convert_to_ascii ( } string [k] = 0; - return (k); + return ((u32) k); } @@ -401,11 +380,9 @@ acpi_ex_convert_to_ascii ( * FUNCTION: acpi_ex_convert_to_string * * PARAMETERS: obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String + * Integer, Buffer, or String * result_desc - Where the string object is returned - * Base - 10 or 16 - * max_length - Max length of the returned string - * walk_state - Current method state + * Type - String flags (base and conversion type) * * RETURN: Status * @@ -417,15 +394,14 @@ acpi_status acpi_ex_convert_to_string ( union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc, - u32 base, - u32 max_length, - struct acpi_walk_state *walk_state) + u32 type) { - union acpi_operand_object *ret_desc; + union acpi_operand_object *return_desc; u8 *new_buf; - u8 *pointer; - u32 string_length; + u32 string_length = 0; + u16 base = 16; u32 i; + u8 separator = ','; ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc); @@ -434,130 +410,129 @@ acpi_ex_convert_to_string ( switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_STRING: - if (max_length >= obj_desc->string.length) { - *result_desc = obj_desc; - return_ACPI_STATUS (AE_OK); - } - else { - /* Must copy the string first and then truncate it */ + /* No conversion necessary */ - return_ACPI_STATUS (AE_NOT_IMPLEMENTED); - } + *result_desc = obj_desc; + return_ACPI_STATUS (AE_OK); case ACPI_TYPE_INTEGER: - string_length = acpi_gbl_integer_byte_width * 2; - if (base == 10) { + switch (type) { + case ACPI_EXPLICIT_CONVERT_DECIMAL: + + /* Make room for maximum decimal number */ + string_length = ACPI_MAX_DECIMAL_DIGITS; + base = 10; + break; + + default: + + /* Two hex string characters for each integer byte */ + + string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width); + break; } /* * Create a new String + * Need enough space for one ASCII integer (plus null terminator) */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); - if (!ret_desc) { + return_desc = acpi_ut_create_string_object ((acpi_size) string_length); + if (!return_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } - /* Need enough space for one ASCII integer plus null terminator */ + new_buf = return_desc->buffer.pointer; - new_buf = ACPI_MEM_CALLOCATE ((acpi_size) string_length + 1); - if (!new_buf) { - ACPI_REPORT_ERROR - (("ex_convert_to_string: Buffer allocation failure\n")); - acpi_ut_remove_reference (ret_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } + /* Convert integer to string */ - /* Convert */ - - i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf, sizeof (acpi_integer)); + string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, + new_buf, acpi_gbl_integer_byte_width); /* Null terminate at the correct place */ - if (max_length < i) { - new_buf[max_length] = 0; - ret_desc->string.length = max_length; - } - else { - new_buf [i] = 0; - ret_desc->string.length = i; - } - - ret_desc->buffer.pointer = new_buf; + return_desc->string.length = string_length; + new_buf [string_length] = 0; break; case ACPI_TYPE_BUFFER: - /* Find the string length */ + switch (type) { + case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string operator */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * decimal values separated by commas." + */ + base = 10; + string_length = obj_desc->buffer.length; /* 4 chars for each decimal */ - pointer = obj_desc->buffer.pointer; - for (string_length = 0; string_length < obj_desc->buffer.length; string_length++) { - /* Exit on null terminator */ + /*lint -fallthrough */ - if (!pointer[string_length]) { - break; + case ACPI_IMPLICIT_CONVERT_HEX: + /* + * From the ACPI spec: + *"The entire contents of the buffer are converted to a string of + * two-character hexadecimal numbers, each separated by a space." + */ + if (type == ACPI_IMPLICIT_CONVERT_HEX) { + separator = ' '; } - } - if (max_length > ACPI_MAX_STRING_CONVERSION) { - if (string_length > ACPI_MAX_STRING_CONVERSION) { + /*lint -fallthrough */ + + case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string operator */ + /* + * From ACPI: "If Data is a buffer, it is converted to a string of + * hexadecimal values separated by commas." + */ + string_length += (obj_desc->buffer.length * 3); + if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ { return_ACPI_STATUS (AE_AML_STRING_LIMIT); } - } - /* - * Create a new string object - */ - ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); - if (!ret_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } + /* Create a new string object and string buffer */ - /* String length is the lesser of the Max or the actual length */ + return_desc = acpi_ut_create_string_object ((acpi_size) string_length -1); + if (!return_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } - if (max_length < string_length) { - string_length = max_length; - } + new_buf = return_desc->buffer.pointer; - new_buf = ACPI_MEM_CALLOCATE ((acpi_size) string_length + 1); - if (!new_buf) { - ACPI_REPORT_ERROR - (("ex_convert_to_string: Buffer allocation failure\n")); - acpi_ut_remove_reference (ret_desc); - return_ACPI_STATUS (AE_NO_MEMORY); - } + /* + * Convert buffer bytes to hex or decimal values + * (separated by commas) + */ + for (i = 0; i < obj_desc->buffer.length; i++) { + new_buf += acpi_ex_convert_to_ascii ( + (acpi_integer) obj_desc->buffer.pointer[i], base, + new_buf, 1); + *new_buf++ = separator; /* each separated by a comma or space */ + } - /* Copy the appropriate number of buffer characters */ + /* Null terminate the string (overwrites final comma from above) */ - ACPI_MEMCPY (new_buf, pointer, string_length); + new_buf--; + *new_buf = 0; - /* Null terminate */ + /* Recalculate length */ - new_buf [string_length] = 0; - ret_desc->buffer.pointer = new_buf; - ret_desc->string.length = string_length; - break; + return_desc->string.length = ACPI_STRLEN (return_desc->string.pointer); + break; + default: + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + break; default: return_ACPI_STATUS (AE_TYPE); } - /* - * If we are about to overwrite the original object on the operand stack, - * we must remove a reference on the original object because we are - * essentially removing it from the stack. - */ - if (*result_desc == obj_desc) { - if (walk_state->opcode != AML_STORE_OP) { - acpi_ut_remove_reference (obj_desc); - } - } - - *result_desc = ret_desc; + *result_desc = return_desc; return_ACPI_STATUS (AE_OK); } @@ -635,7 +610,8 @@ acpi_ex_convert_to_target_type ( * These types require an Integer operand. We can convert * a Buffer or a String to an Integer if necessary. */ - status = acpi_ex_convert_to_integer (source_desc, result_desc, walk_state); + status = acpi_ex_convert_to_integer (source_desc, result_desc, + 16); break; @@ -645,7 +621,8 @@ acpi_ex_convert_to_target_type ( * The operand must be a String. We can convert an * Integer or Buffer if necessary */ - status = acpi_ex_convert_to_string (source_desc, result_desc, 16, ACPI_UINT32_MAX, walk_state); + status = acpi_ex_convert_to_string (source_desc, result_desc, + ACPI_IMPLICIT_CONVERT_HEX); break; @@ -655,7 +632,7 @@ acpi_ex_convert_to_target_type ( * The operand must be a Buffer. We can convert an * Integer or String if necessary */ - status = acpi_ex_convert_to_buffer (source_desc, result_desc, walk_state); + status = acpi_ex_convert_to_buffer (source_desc, result_desc); break; diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 5c2c912ed..042f0c9ab 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -55,7 +55,6 @@ /* * The following routines are used for debug output only */ - #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /***************************************************************************** @@ -64,7 +63,7 @@ * * PARAMETERS: *obj_desc - Pointer to entry to be dumped * - * RETURN: Status + * RETURN: None * * DESCRIPTION: Dump an operand object * @@ -72,12 +71,11 @@ void acpi_ex_dump_operand ( - union acpi_operand_object *obj_desc) + union acpi_operand_object *obj_desc, + u32 depth) { - u8 *buf = NULL; u32 length; - union acpi_operand_object **element; - u16 element_index; + u32 index; ACPI_FUNCTION_NAME ("ex_dump_operand") @@ -89,9 +87,9 @@ acpi_ex_dump_operand ( if (!obj_desc) { /* - * This usually indicates that something serious is wrong + * This could be a null element of a package */ - acpi_os_printf ("Null Object Descriptor\n"); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); return; } @@ -103,15 +101,19 @@ acpi_ex_dump_operand ( if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "%p is not a node or operand object: [%s]\n", - obj_desc, acpi_ut_get_descriptor_name (obj_desc))); + "%p is not a node or operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc))); ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object)); return; } /* obj_desc is a valid object */ - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc)); + if (depth > 0) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "%*s[%u] ", depth, " ", depth)); + } + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "%p ", obj_desc)); + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: @@ -125,8 +127,8 @@ acpi_ex_dump_operand ( case AML_NAME_OP: - ACPI_DUMP_PATHNAME (obj_desc->reference.object, "Reference: Name: ", - ACPI_LV_INFO, _COMPONENT); + ACPI_DUMP_PATHNAME (obj_desc->reference.object, + "Reference: Name: ", ACPI_LV_INFO, _COMPONENT); ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO); break; @@ -134,27 +136,27 @@ acpi_ex_dump_operand ( case AML_INDEX_OP: acpi_os_printf ("Reference: Index %p\n", - obj_desc->reference.object); + obj_desc->reference.object); break; case AML_REF_OF_OP: acpi_os_printf ("Reference: (ref_of) %p\n", - obj_desc->reference.object); + obj_desc->reference.object); break; case AML_ARG_OP: acpi_os_printf ("Reference: Arg%d", - obj_desc->reference.offset); + obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Value is an Integer */ acpi_os_printf (" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64 (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); } acpi_os_printf ("\n"); @@ -164,14 +166,14 @@ acpi_ex_dump_operand ( case AML_LOCAL_OP: acpi_os_printf ("Reference: Local%d", - obj_desc->reference.offset); + obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Value is an Integer */ acpi_os_printf (" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64 (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); } acpi_os_printf ("\n"); @@ -181,7 +183,7 @@ acpi_ex_dump_operand ( case AML_INT_NAMEPATH_OP: acpi_os_printf ("Reference.Node->Name %X\n", - obj_desc->reference.node->name.integer); + obj_desc->reference.node->name.integer); break; @@ -194,18 +196,15 @@ acpi_ex_dump_operand ( break; } - break; case ACPI_TYPE_BUFFER: acpi_os_printf ("Buffer len %X @ %p \n", - obj_desc->buffer.length, - obj_desc->buffer.pointer); + obj_desc->buffer.length, obj_desc->buffer.pointer); length = obj_desc->buffer.length; - if (length > 64) { length = 64; } @@ -215,41 +214,37 @@ acpi_ex_dump_operand ( if (obj_desc->buffer.pointer) { acpi_os_printf ("Buffer Contents: "); - for (buf = obj_desc->buffer.pointer; length--; ++buf) { - acpi_os_printf (" %02x", *buf); + for (index = 0; index < length; index++) { + acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]); } acpi_os_printf ("\n"); } - break; case ACPI_TYPE_INTEGER: acpi_os_printf ("Integer %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; case ACPI_TYPE_PACKAGE: - acpi_os_printf ("Package count %X @ %p\n", - obj_desc->package.count, obj_desc->package.elements); + acpi_os_printf ("Package [Len %X] element_array %p\n", + obj_desc->package.count, obj_desc->package.elements); /* - * If elements exist, package vector pointer is valid, + * If elements exist, package element pointer is valid, * and debug_level exceeds 1, dump package's elements. */ if (obj_desc->package.count && obj_desc->package.elements && acpi_dbg_level > 1) { - for (element_index = 0, element = obj_desc->package.elements; - element_index < obj_desc->package.count; - ++element_index, ++element) { - acpi_ex_dump_operand (*element); + for (index = 0; index < obj_desc->package.count; index++) { + acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1); } } - acpi_os_printf ("\n"); break; @@ -277,7 +272,7 @@ acpi_ex_dump_operand ( case ACPI_TYPE_STRING: acpi_os_printf ("String length %X @ %p ", - obj_desc->string.length, obj_desc->string.pointer); + obj_desc->string.length, obj_desc->string.pointer); acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf ("\n"); break; @@ -297,7 +292,7 @@ acpi_ex_dump_operand ( obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset); - ACPI_DUMP_STACK_ENTRY (obj_desc->field.region_obj); + acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1); break; @@ -321,9 +316,8 @@ acpi_ex_dump_operand ( acpi_os_printf ("*not a Buffer* \n"); } else { - ACPI_DUMP_STACK_ENTRY (obj_desc->buffer_field.buffer_obj); + acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1); } - break; @@ -387,10 +381,13 @@ acpi_ex_dump_operand ( * * FUNCTION: acpi_ex_dump_operands * - * PARAMETERS: interpreter_mode - Load or Exec - * *Ident - Identification + * PARAMETERS: Operands - Operand list + * interpreter_mode - Load or Exec + * Ident - Identification * num_levels - # of stack entries to dump above line - * *Note - Output notation + * Note - Output notation + * module_name - Caller's module name + * line_number - Caller's invocation line number * * DESCRIPTION: Dump the object stack * @@ -407,7 +404,6 @@ acpi_ex_dump_operands ( u32 line_number) { acpi_native_uint i; - union acpi_operand_object **obj_desc; ACPI_FUNCTION_NAME ("ex_dump_operands"); @@ -432,8 +428,7 @@ acpi_ex_dump_operands ( /* Dump the operand stack starting at the top */ for (i = 0; num_levels > 0; i--, num_levels--) { - obj_desc = &operands[i]; - acpi_ex_dump_operand (*obj_desc); + acpi_ex_dump_operand (operands[i], 0); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, @@ -443,6 +438,8 @@ acpi_ex_dump_operands ( } +#ifdef ACPI_FUTURE_USAGE + /***************************************************************************** * * FUNCTION: acpi_ex_out* @@ -489,8 +486,7 @@ acpi_ex_out_address ( #if ACPI_MACHINE_WIDTH == 16 acpi_os_printf ("%20s : %p\n", title, value); #else - acpi_os_printf ("%20s : %8.8X%8.8X\n", title, - ACPI_FORMAT_UINT64 (value)); + acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value)); #endif } @@ -499,7 +495,7 @@ acpi_ex_out_address ( * * FUNCTION: acpi_ex_dump_node * - * PARAMETERS: *Node - Descriptor to dump + * PARAMETERS: *Node - Descriptor to dump * Flags - Force display * * DESCRIPTION: Dumps the members of the given.Node @@ -563,22 +559,25 @@ acpi_ex_dump_object_descriptor ( if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags); - acpi_os_printf ("\nAttached Object (%p):\n", ((struct acpi_namespace_node *) obj_desc)->object); - acpi_ex_dump_object_descriptor (((struct acpi_namespace_node *) obj_desc)->object, flags); - return; + acpi_os_printf ("\nAttached Object (%p):\n", + ((struct acpi_namespace_node *) obj_desc)->object); + acpi_ex_dump_object_descriptor ( + ((struct acpi_namespace_node *) obj_desc)->object, flags); + return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", - obj_desc, acpi_ut_get_descriptor_name (obj_desc)); + acpi_os_printf ( + "ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", + obj_desc, acpi_ut_get_descriptor_name (obj_desc)); return_VOID; } /* Common Fields */ - acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc)); + acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc)); acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count); - acpi_ex_out_integer ("Flags", obj_desc->common.flags); + acpi_ex_out_integer ("Flags", obj_desc->common.flags); /* Object-specific Fields */ @@ -592,7 +591,7 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_STRING: - acpi_ex_out_integer ("Length", obj_desc->string.length); + acpi_ex_out_integer ("Length", obj_desc->string.length); acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer); acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX); @@ -602,17 +601,17 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_BUFFER: - acpi_ex_out_integer ("Length", obj_desc->buffer.length); - acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); + acpi_ex_out_integer ("Length", obj_desc->buffer.length); + acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length); break; case ACPI_TYPE_PACKAGE: - acpi_ex_out_integer ("Flags", obj_desc->package.flags); - acpi_ex_out_integer ("Count", obj_desc->package.count); - acpi_ex_out_pointer ("Elements", obj_desc->package.elements); + acpi_ex_out_integer ("Flags", obj_desc->package.flags); + acpi_ex_out_integer ("Count", obj_desc->package.count); + acpi_ex_out_pointer ("Elements", obj_desc->package.elements); /* Dump the package contents */ @@ -621,7 +620,8 @@ acpi_ex_dump_object_descriptor ( for (i = 0; i < obj_desc->package.count; i++) { acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); if (obj_desc->package.elements[i]) { - acpi_os_printf (" %s", acpi_ut_get_object_type_name (obj_desc->package.elements[i])); + acpi_os_printf (" %s", + acpi_ut_get_object_type_name (obj_desc->package.elements[i])); } acpi_os_printf ("\n"); } @@ -639,38 +639,38 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_EVENT: - acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore); + acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore); break; case ACPI_TYPE_METHOD: - acpi_ex_out_integer ("param_count", obj_desc->method.param_count); - acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); - acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); - acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id); - acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length); - acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start); + acpi_ex_out_integer ("param_count", obj_desc->method.param_count); + acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); + acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); + acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id); + acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length); + acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start); break; case ACPI_TYPE_MUTEX: - acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level); + acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level); acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread); - acpi_ex_out_integer ("acquisition_depth",obj_desc->mutex.acquisition_depth); - acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore); + acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth); + acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore); break; case ACPI_TYPE_REGION: - acpi_ex_out_integer ("space_id", obj_desc->region.space_id); - acpi_ex_out_integer ("Flags", obj_desc->region.flags); - acpi_ex_out_address ("Address", obj_desc->region.address); - acpi_ex_out_integer ("Length", obj_desc->region.length); - acpi_ex_out_pointer ("Handler", obj_desc->region.handler); - acpi_ex_out_pointer ("Next", obj_desc->region.next); + acpi_ex_out_integer ("space_id", obj_desc->region.space_id); + acpi_ex_out_integer ("Flags", obj_desc->region.flags); + acpi_ex_out_address ("Address", obj_desc->region.address); + acpi_ex_out_integer ("Length", obj_desc->region.length); + acpi_ex_out_pointer ("Handler", obj_desc->region.handler); + acpi_ex_out_pointer ("Next", obj_desc->region.next); break; @@ -686,11 +686,11 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_PROCESSOR: acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); - acpi_ex_out_integer ("Length", obj_desc->processor.length); - acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); + acpi_ex_out_integer ("Length", obj_desc->processor.length); + acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); - acpi_ex_out_pointer ("Handler", obj_desc->processor.handler); + acpi_ex_out_pointer ("Handler", obj_desc->processor.handler); break; @@ -698,7 +698,7 @@ acpi_ex_dump_object_descriptor ( acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); - acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler); + acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler); break; @@ -707,35 +707,35 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags); - acpi_ex_out_integer ("access_byte_width", obj_desc->common_field.access_byte_width); - acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length); + acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags); + acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width); + acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length); acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset); acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset); acpi_ex_out_integer ("datum_valid_bits", obj_desc->common_field.datum_valid_bits); - acpi_ex_out_integer ("end_fld_valid_bits", obj_desc->common_field.end_field_valid_bits); - acpi_ex_out_integer ("end_buf_valid_bits", obj_desc->common_field.end_buffer_valid_bits); - acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node); + acpi_ex_out_integer ("end_fld_valid_bits",obj_desc->common_field.end_field_valid_bits); + acpi_ex_out_integer ("end_buf_valid_bits",obj_desc->common_field.end_buffer_valid_bits); + acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node); switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_BUFFER_FIELD: - acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj); + acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj); break; case ACPI_TYPE_LOCAL_REGION_FIELD: - acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj); + acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj); break; case ACPI_TYPE_LOCAL_BANK_FIELD: - acpi_ex_out_integer ("Value", obj_desc->bank_field.value); - acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj); - acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj); + acpi_ex_out_integer ("Value", obj_desc->bank_field.value); + acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj); + acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_ex_out_integer ("Value", obj_desc->index_field.value); - acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); - acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); + acpi_ex_out_integer ("Value", obj_desc->index_field.value); + acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); + acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); break; default: @@ -747,29 +747,29 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_LOCAL_REFERENCE: - acpi_ex_out_integer ("target_type", obj_desc->reference.target_type); - acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name); - acpi_ex_out_integer ("Offset", obj_desc->reference.offset); - acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object); - acpi_ex_out_pointer ("Node", obj_desc->reference.node); - acpi_ex_out_pointer ("Where", obj_desc->reference.where); + acpi_ex_out_integer ("target_type", obj_desc->reference.target_type); + acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name); + acpi_ex_out_integer ("Offset", obj_desc->reference.offset); + acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object); + acpi_ex_out_pointer ("Node", obj_desc->reference.node); + acpi_ex_out_pointer ("Where", obj_desc->reference.where); break; case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); - acpi_ex_out_pointer ("Next", obj_desc->address_space.next); - acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); - acpi_ex_out_pointer ("Node", obj_desc->address_space.node); - acpi_ex_out_pointer ("Context", obj_desc->address_space.context); + acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); + acpi_ex_out_pointer ("Next", obj_desc->address_space.next); + acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); + acpi_ex_out_pointer ("Node", obj_desc->address_space.node); + acpi_ex_out_pointer ("Context", obj_desc->address_space.context); break; case ACPI_TYPE_LOCAL_NOTIFY: - acpi_ex_out_pointer ("Node", obj_desc->notify.node); - acpi_ex_out_pointer ("Context", obj_desc->notify.context); + acpi_ex_out_pointer ("Node", obj_desc->notify.node); + acpi_ex_out_pointer ("Context", obj_desc->notify.context); break; @@ -779,7 +779,8 @@ acpi_ex_dump_object_descriptor ( case ACPI_TYPE_LOCAL_DATA: default: - acpi_os_printf ("ex_dump_object_descriptor: Display not implemented for object type %s\n", + acpi_os_printf ( + "ex_dump_object_descriptor: Display not implemented for object type %s\n", acpi_ut_get_object_type_name (obj_desc)); break; } @@ -787,5 +788,7 @@ acpi_ex_dump_object_descriptor ( return_VOID; } +#endif /* ACPI_FUTURE_USAGE */ + #endif diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 4ce49b9bf..5f8fbdb16 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -130,6 +130,21 @@ acpi_ex_setup_region ( if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + obj_desc->common_field.access_byte_width)) { + if (acpi_gbl_enable_interpreter_slack) { + /* + * Slack mode only: We will go ahead and allow access to this + * field if it is within the region length rounded up to the next + * access width boundary. + */ + if (ACPI_ROUND_UP (rgn_desc->region.length, + obj_desc->common_field.access_byte_width) >= + (obj_desc->common_field.base_byte_offset + + (acpi_native_uint) obj_desc->common_field.access_byte_width + + field_datum_byte_offset)) { + return_ACPI_STATUS (AE_OK); + } + } + if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { /* * This is the case where the access_type (acc_word, etc.) is wider @@ -154,40 +169,7 @@ acpi_ex_setup_region ( field_datum_byte_offset, obj_desc->common_field.access_byte_width, acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); - if (!acpi_strict) { - /* - * Allow access to the field if it is within the region size - * rounded up to a multiple of the access byte width. This - * overcomes "off-by-one" programming errors in the AML often - * found in Toshiba laptops. These errors were allowed by - * the Microsoft ASL compiler. - */ - u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length, - obj_desc->common_field.access_byte_width); - - if (rounded_length < (obj_desc->common_field.base_byte_offset - + field_datum_byte_offset - + obj_desc->common_field.access_byte_width)) { - return_ACPI_STATUS (AE_AML_REGION_LIMIT); - } else { - static int warn_once = 1; - if (warn_once) { - // Could also associate a flag with each field, and - // warn once for each field. - ACPI_REPORT_WARNING(( - "The ACPI AML in your computer contains errors, " - "please nag the manufacturer to correct it.\n")); - ACPI_REPORT_WARNING(( - "Allowing relaxed access to fields; " - "turn on CONFIG_ACPI_DEBUG for details.\n")); - warn_once = 0; - } - return_ACPI_STATUS (AE_OK); - } - } - else { - return_ACPI_STATUS (AE_AML_REGION_LIMIT); - } + return_ACPI_STATUS (AE_AML_REGION_LIMIT); } return_ACPI_STATUS (AE_OK); @@ -277,7 +259,7 @@ acpi_ex_access_region ( rgn_desc->region.space_id)); } else if (status == AE_NOT_EXIST) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + ACPI_REPORT_ERROR (( "Region %s(%X) has no handler\n", acpi_ut_get_region_name (rgn_desc->region.space_id), rgn_desc->region.space_id)); @@ -764,16 +746,85 @@ acpi_ex_set_buffer_datum ( } +/******************************************************************************* + * + * FUNCTION: acpi_ex_common_buffer_setup + * + * PARAMETERS: obj_desc - Field object + * buffer_length - Length of caller's buffer + * datum_count - Where the datum_count is returned + * + * RETURN: Status, datum_count + * + * DESCRIPTION: Common code to validate the incoming buffer size and compute + * the number of field "datums" that must be read or written. + * A "datum" is the smallest unit that can be read or written + * to the field, it is either 1,2,4, or 8 bytes. + * + ******************************************************************************/ + +acpi_status +acpi_ex_common_buffer_setup ( + union acpi_operand_object *obj_desc, + u32 buffer_length, + u32 *datum_count) +{ + u32 byte_field_length; + u32 actual_byte_field_length; + + + ACPI_FUNCTION_TRACE ("ex_common_buffer_setup"); + + + /* + * Incoming buffer must be at least as long as the field, we do not + * allow "partial" field reads/writes. We do not care if the buffer is + * larger than the field, this typically happens when an integer is + * read/written to a field that is actually smaller than an integer. + */ + byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( + obj_desc->common_field.bit_length); + if (byte_field_length > buffer_length) { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field size %X (bytes) is too large for buffer (%X)\n", + byte_field_length, buffer_length)); + + return_ACPI_STATUS (AE_BUFFER_OVERFLOW); + } + + /* + * Create "actual" field byte count (minimum number of bytes that + * must be read), then convert to datum count (minimum number + * of datum-sized units that must be read) + */ + actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( + obj_desc->common_field.start_field_bit_offset + + obj_desc->common_field.bit_length); + + + *datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length, + obj_desc->common_field.access_byte_width); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n", + byte_field_length, actual_byte_field_length, + *datum_count, obj_desc->common_field.access_byte_width)); + + return_ACPI_STATUS (AE_OK); +} + + /******************************************************************************* * * FUNCTION: acpi_ex_extract_from_field * - * PARAMETERS: *obj_desc - Field to be read - * *Value - Where to store value + * PARAMETERS: obj_desc - Field to be read + * Buffer - Where to store the field data + * buffer_length - Length of Buffer * * RETURN: Status * - * DESCRIPTION: Retrieve the value of the given field + * DESCRIPTION: Retrieve the current value of the given field * ******************************************************************************/ @@ -789,7 +840,6 @@ acpi_ex_extract_from_field ( acpi_integer previous_raw_datum = 0; acpi_integer this_raw_datum = 0; acpi_integer merged_datum = 0; - u32 byte_field_length; u32 datum_count; u32 i; @@ -797,39 +847,13 @@ acpi_ex_extract_from_field ( ACPI_FUNCTION_TRACE ("ex_extract_from_field"); - /* - * The field must fit within the caller's buffer - */ - byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length); - if (byte_field_length > buffer_length) { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Field size %X (bytes) too large for buffer (%X)\n", - byte_field_length, buffer_length)); - - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); - } - - /* Convert field byte count to datum count, round up if necessary */ - - datum_count = ACPI_ROUND_UP_TO (byte_field_length, - obj_desc->common_field.access_byte_width); + /* Validate buffer, compute number of datums */ - /* - * If the field is not aligned on a datum boundary and does not - * fit within a single datum, we must read an extra datum. - * - * We could just split the aligned and non-aligned cases since the - * aligned case is so very simple, but this would require more code. - */ - if ((obj_desc->common_field.end_field_valid_bits != 0) && - (!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) { - datum_count++; + status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "byte_len %X, datum_len %X, byte_gran %X\n", - byte_field_length, datum_count,obj_desc->common_field.access_byte_width)); - /* * Clear the caller's buffer (the whole buffer length as given) * This is very important, especially in the cases where the buffer @@ -942,12 +966,13 @@ acpi_ex_extract_from_field ( * * FUNCTION: acpi_ex_insert_into_field * - * PARAMETERS: *obj_desc - Field to be set - * Buffer - Value to store + * PARAMETERS: obj_desc - Field to be written + * Buffer - Data to be written + * buffer_length - Length of Buffer * * RETURN: Status * - * DESCRIPTION: Store the value into the given field + * DESCRIPTION: Store the Buffer contents into the given field * ******************************************************************************/ @@ -964,42 +989,19 @@ acpi_ex_insert_into_field ( acpi_integer merged_datum; acpi_integer previous_raw_datum; acpi_integer this_raw_datum; - u32 byte_field_length; u32 datum_count; ACPI_FUNCTION_TRACE ("ex_insert_into_field"); - /* - * Incoming buffer must be at least as long as the field, we do not - * allow "partial" field writes. We do not care if the buffer is - * larger than the field, this typically happens when an integer is - * written to a field that is actually smaller than an integer. - */ - byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( - obj_desc->common_field.bit_length); - if (buffer_length < byte_field_length) { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Buffer length %X too small for field %X\n", - buffer_length, byte_field_length)); + /* Validate buffer, compute number of datums */ - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); + status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); } - byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES ( - obj_desc->common_field.start_field_bit_offset + - obj_desc->common_field.bit_length); - - /* Convert byte count to datum count, round up if necessary */ - - datum_count = ACPI_ROUND_UP_TO (byte_field_length, - obj_desc->common_field.access_byte_width); - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Bytes %X, Datums %X, byte_gran %X\n", - byte_field_length, datum_count, obj_desc->common_field.access_byte_width)); - /* * Break the request into up to three parts (similar to an I/O request): * 1) non-aligned part at start diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 74fd68491..6bd793424 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -149,8 +149,9 @@ acpi_ex_get_object_reference ( * * FUNCTION: acpi_ex_concat_template * - * PARAMETERS: *obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object + * actual_return_desc - Where to place the return object * walk_state - Current walk state * * RETURN: Status @@ -161,8 +162,8 @@ acpi_ex_get_object_reference ( acpi_status acpi_ex_concat_template ( - union acpi_operand_object *obj_desc1, - union acpi_operand_object *obj_desc2, + union acpi_operand_object *operand0, + union acpi_operand_object *operand1, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { @@ -179,16 +180,16 @@ acpi_ex_concat_template ( /* Find the end_tags in each resource template */ - end_tag1 = acpi_ut_get_resource_end_tag (obj_desc1); - end_tag2 = acpi_ut_get_resource_end_tag (obj_desc2); + end_tag1 = acpi_ut_get_resource_end_tag (operand0); + end_tag2 = acpi_ut_get_resource_end_tag (operand1); if (!end_tag1 || !end_tag2) { return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Compute the length of each part */ - length1 = ACPI_PTR_DIFF (end_tag1, obj_desc1->buffer.pointer); - length2 = ACPI_PTR_DIFF (end_tag2, obj_desc2->buffer.pointer) + + length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer); + length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) + 2; /* Size of END_TAG */ /* Create a new buffer object for the result */ @@ -201,8 +202,8 @@ acpi_ex_concat_template ( /* Copy the templates to the new descriptor */ new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, length1); - ACPI_MEMCPY (new_buf + length1, obj_desc2->buffer.pointer, length2); + ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1); + ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2); /* Compute the new checksum */ @@ -221,8 +222,8 @@ acpi_ex_concat_template ( * * FUNCTION: acpi_ex_do_concatenate * - * PARAMETERS: obj_desc1 - First source object - * obj_desc2 - Second source object + * PARAMETERS: Operand0 - First source object + * Operand1 - Second source object * actual_return_desc - Where to place the return object * walk_state - Current walk state * @@ -234,20 +235,57 @@ acpi_ex_concat_template ( acpi_status acpi_ex_do_concatenate ( - union acpi_operand_object *obj_desc1, - union acpi_operand_object *obj_desc2, + union acpi_operand_object *operand0, + union acpi_operand_object *operand1, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { - acpi_status status; - u32 i; - acpi_integer this_integer; + union acpi_operand_object *local_operand1 = operand1; union acpi_operand_object *return_desc; char *new_buf; + acpi_status status; + acpi_size new_length; - ACPI_FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE ("ex_do_concatenate"); + + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE (operand0)) { + case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); + break; + + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string (operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; + + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer (operand1, &local_operand1); + break; + + default: + ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", + ACPI_GET_OBJECT_TYPE (operand0))); + status = AE_AML_INTERNAL; + } + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ /* * There are three cases to handle: @@ -256,113 +294,102 @@ acpi_ex_do_concatenate ( * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc1)) { + switch (ACPI_GET_OBJECT_TYPE (operand0)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ - return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width * 2); + return_desc = acpi_ut_create_buffer_object ( + ACPI_MUL_2 (acpi_gbl_integer_byte_width)); if (!return_desc) { - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } new_buf = (char *) return_desc->buffer.pointer; - /* Convert the first integer */ + /* Copy the first integer, LSB first */ - this_integer = obj_desc1->integer.value; - for (i = 0; i < acpi_gbl_integer_byte_width; i++) { - new_buf[i] = (char) this_integer; - this_integer >>= 8; - } + ACPI_MEMCPY (new_buf, + &operand0->integer.value, + acpi_gbl_integer_byte_width); - /* Convert the second integer */ - - this_integer = obj_desc2->integer.value; - for (; i < (ACPI_MUL_2 (acpi_gbl_integer_byte_width)); i++) { - new_buf[i] = (char) this_integer; - this_integer >>= 8; - } + /* Copy the second integer (LSB first) after the first */ + ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width, + &local_operand1->integer.value, + acpi_gbl_integer_byte_width); break; - case ACPI_TYPE_STRING: /* Result of two Strings is a String */ - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); - if (!return_desc) { - return (AE_NO_MEMORY); + new_length = (acpi_size) operand0->string.length + + (acpi_size) local_operand1->string.length; + if (new_length > ACPI_MAX_STRING_CONVERSION) { + status = AE_AML_STRING_LIMIT; + goto cleanup; } - /* Operand0 is string */ - - new_buf = ACPI_MEM_CALLOCATE ((acpi_size) obj_desc1->string.length + - (acpi_size) obj_desc2->string.length + 1); - if (!new_buf) { - ACPI_REPORT_ERROR - (("ex_do_concatenate: String allocation failure\n")); + return_desc = acpi_ut_create_string_object (new_length); + if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } - /* Concatenate the strings */ - - ACPI_STRCPY (new_buf, obj_desc1->string.pointer); - ACPI_STRCPY (new_buf + obj_desc1->string.length, - obj_desc2->string.pointer); + new_buf = return_desc->string.pointer; - /* Complete the String object initialization */ + /* Concatenate the strings */ - return_desc->string.pointer = new_buf; - return_desc->string.length = obj_desc1->string.length + - obj_desc2->string.length; + ACPI_STRCPY (new_buf, + operand0->string.pointer); + ACPI_STRCPY (new_buf + operand0->string.length, + local_operand1->string.pointer); break; - case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_buffer_object ( - (acpi_size) obj_desc1->buffer.length + - (acpi_size) obj_desc2->buffer.length); + (acpi_size) operand0->buffer.length + + (acpi_size) local_operand1->buffer.length); if (!return_desc) { - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } new_buf = (char *) return_desc->buffer.pointer; /* Concatenate the buffers */ - ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, - obj_desc1->buffer.length); - ACPI_MEMCPY (new_buf + obj_desc1->buffer.length, obj_desc2->buffer.pointer, - obj_desc2->buffer.length); - + ACPI_MEMCPY (new_buf, + operand0->buffer.pointer, + operand0->buffer.length); + ACPI_MEMCPY (new_buf + operand0->buffer.length, + local_operand1->buffer.pointer, + local_operand1->buffer.length); break; - default: /* Invalid object type, should not happen here */ - ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", - ACPI_GET_OBJECT_TYPE (obj_desc1))); - status = AE_AML_INTERNAL; - return_desc = NULL; + ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n", + ACPI_GET_OBJECT_TYPE (operand0))); + status =AE_AML_INTERNAL; + goto cleanup; } *actual_return_desc = return_desc; - return (AE_OK); - cleanup: - - acpi_ut_remove_reference (return_desc); - return (status); + if (local_operand1 != operand1) { + acpi_ut_remove_reference (local_operand1); + } + return_ACPI_STATUS (AE_OK); } @@ -371,8 +398,8 @@ cleanup: * FUNCTION: acpi_ex_do_math_op * * PARAMETERS: Opcode - AML opcode - * Operand0 - Integer operand #0 - * Operand1 - Integer operand #1 + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 * * RETURN: Integer result of the operation * @@ -385,60 +412,62 @@ cleanup: acpi_integer acpi_ex_do_math_op ( u16 opcode, - acpi_integer operand0, - acpi_integer operand1) + acpi_integer integer0, + acpi_integer integer1) { + ACPI_FUNCTION_ENTRY (); + switch (opcode) { - case AML_ADD_OP: /* Add (Operand0, Operand1, Result) */ + case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ - return (operand0 + operand1); + return (integer0 + integer1); - case AML_BIT_AND_OP: /* And (Operand0, Operand1, Result) */ + case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ - return (operand0 & operand1); + return (integer0 & integer1); - case AML_BIT_NAND_OP: /* NAnd (Operand0, Operand1, Result) */ + case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ - return (~(operand0 & operand1)); + return (~(integer0 & integer1)); - case AML_BIT_OR_OP: /* Or (Operand0, Operand1, Result) */ + case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ - return (operand0 | operand1); + return (integer0 | integer1); - case AML_BIT_NOR_OP: /* NOr (Operand0, Operand1, Result) */ + case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ - return (~(operand0 | operand1)); + return (~(integer0 | integer1)); - case AML_BIT_XOR_OP: /* XOr (Operand0, Operand1, Result) */ + case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ - return (operand0 ^ operand1); + return (integer0 ^ integer1); - case AML_MULTIPLY_OP: /* Multiply (Operand0, Operand1, Result) */ + case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ - return (operand0 * operand1); + return (integer0 * integer1); case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ - return (operand0 << operand1); + return (integer0 << integer1); case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ - return (operand0 >> operand1); + return (integer0 >> integer1); - case AML_SUBTRACT_OP: /* Subtract (Operand0, Operand1, Result) */ + case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ - return (operand0 - operand1); + return (integer0 - integer1); default: @@ -447,20 +476,86 @@ acpi_ex_do_math_op ( } +/******************************************************************************* + * + * FUNCTION: acpi_ex_do_logical_numeric_op + * + * PARAMETERS: Opcode - AML opcode + * Integer0 - Integer operand #0 + * Integer1 - Integer operand #1 + * logical_result - TRUE/FALSE result of the operation + * + * RETURN: Status + * + * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric + * operators (LAnd and LOr), both operands must be integers. + * + * Note: cleanest machine code seems to be produced by the code + * below, rather than using statements of the form: + * Result = (Integer0 && Integer1); + * + ******************************************************************************/ + +acpi_status +acpi_ex_do_logical_numeric_op ( + u16 opcode, + acpi_integer integer0, + acpi_integer integer1, + u8 *logical_result) +{ + acpi_status status = AE_OK; + u8 local_result = FALSE; + + + ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op"); + + + switch (opcode) { + case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ + + if (integer0 && integer1) { + local_result = TRUE; + } + break; + + case AML_LOR_OP: /* LOr (Integer0, Integer1) */ + + if (integer0 || integer1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; + } + + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS (status); +} + + /******************************************************************************* * * FUNCTION: acpi_ex_do_logical_op * * PARAMETERS: Opcode - AML opcode - * Operand0 - Integer operand #0 - * Operand1 - Integer operand #1 + * Operand0 - operand #0 + * Operand1 - operand #1 + * logical_result - TRUE/FALSE result of the operation * - * RETURN: TRUE/FALSE result of the operation + * RETURN: Status * * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the * functions here is to prevent a lot of pointer dereferencing * to obtain the operands and to simplify the generation of the - * logical value. + * logical value. For the Numeric operators (LAnd and LOr), both + * operands must be integers. For the other logical operators, + * operands can be any combination of Integer/String/Buffer. The + * first operand determines the type to which the second operand + * will be converted. * * Note: cleanest machine code seems to be produced by the code * below, rather than using statements of the form: @@ -468,60 +563,175 @@ acpi_ex_do_math_op ( * ******************************************************************************/ -u8 +acpi_status acpi_ex_do_logical_op ( u16 opcode, - acpi_integer operand0, - acpi_integer operand1) + union acpi_operand_object *operand0, + union acpi_operand_object *operand1, + u8 *logical_result) { + union acpi_operand_object *local_operand1 = operand1; + acpi_integer integer0; + acpi_integer integer1; + u32 length0; + u32 length1; + acpi_status status = AE_OK; + u8 local_result = FALSE; + int compare; - switch (opcode) { + ACPI_FUNCTION_TRACE ("ex_do_logical_op"); - case AML_LAND_OP: /* LAnd (Operand0, Operand1) */ - if (operand0 && operand1) { - return (TRUE); - } + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI 3.0+ specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism. + */ + switch (ACPI_GET_OBJECT_TYPE (operand0)) { + case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); break; + case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string (operand1, &local_operand1, + ACPI_IMPLICIT_CONVERT_HEX); + break; - case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer (operand1, &local_operand1); + break; - if (operand0 == operand1) { - return (TRUE); - } + default: + status = AE_AML_INTERNAL; break; + } + if (ACPI_FAILURE (status)) { + goto cleanup; + } - case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + /* + * Two cases: 1) Both Integers, 2) Both Strings or Buffers + */ + if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) { + /* + * 1) Both operands are of type integer + * Note: local_operand1 may have changed above + */ + integer0 = operand0->integer.value; + integer1 = local_operand1->integer.value; - if (operand0 > operand1) { - return (TRUE); - } - break; + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + if (integer0 == integer1) { + local_result = TRUE; + } + break; + + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (integer0 > integer1) { + local_result = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ - case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + if (integer0 < integer1) { + local_result = TRUE; + } + break; - if (operand0 < operand1) { - return (TRUE); + default: + status = AE_AML_INTERNAL; + break; } - break; + } + else { + /* + * 2) Both operands are Strings or both are Buffers + * Note: Code below takes advantage of common Buffer/String + * object fields. local_operand1 may have changed above. Use + * memcmp to handle nulls in buffers. + */ + length0 = operand0->buffer.length; + length1 = local_operand1->buffer.length; + + /* Lexicographic compare: compare the data bytes */ + + compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer, + (const char * ) local_operand1->buffer.pointer, + (length0 > length1) ? length1 : length0); + + switch (opcode) { + case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ + + /* Length and all bytes must be equal */ + + if ((length0 == length1) && + (compare == 0)) { + /* Length and all bytes match ==> TRUE */ + + local_result = TRUE; + } + break; + case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ - case AML_LOR_OP: /* LOr (Operand0, Operand1) */ + if (compare > 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + if (compare < 0) { + goto cleanup; /* FALSE */ + } - if (operand0 || operand1) { - return (TRUE); + /* Bytes match (to shortest length), compare lengths */ + + if (length0 > length1) { + local_result = TRUE; + } + break; + + case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ + + if (compare > 0) { + goto cleanup; /* FALSE */ + } + if (compare < 0) { + local_result = TRUE; + goto cleanup; /* TRUE */ + } + + /* Bytes match (to shortest length), compare lengths */ + + if (length0 < length1) { + local_result = TRUE; + } + break; + + default: + status = AE_AML_INTERNAL; + break; } - break; + } - default: - break; +cleanup: + + /* New object was created if implicit conversion performed - delete */ + + if (local_operand1 != operand1) { + acpi_ut_remove_reference (local_operand1); } - return (FALSE); + /* Return the logical result and status */ + + *logical_result = local_result; + return_ACPI_STATUS (status); } diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index cee2c126e..c709ed2f5 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -54,7 +54,7 @@ * * FUNCTION: acpi_ex_unlink_mutex * - * PARAMETERS: *obj_desc - The mutex to be unlinked + * PARAMETERS: obj_desc - The mutex to be unlinked * * RETURN: Status * @@ -73,6 +73,8 @@ acpi_ex_unlink_mutex ( return; } + /* Doubly linked list */ + if (obj_desc->mutex.next) { (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; } @@ -90,8 +92,8 @@ acpi_ex_unlink_mutex ( * * FUNCTION: acpi_ex_link_mutex * - * PARAMETERS: *obj_desc - The mutex to be linked - * *list_head - head of the "acquired_mutex" list + * PARAMETERS: obj_desc - The mutex to be linked + * list_head - head of the "acquired_mutex" list * * RETURN: Status * @@ -130,8 +132,8 @@ acpi_ex_link_mutex ( * * FUNCTION: acpi_ex_acquire_mutex * - * PARAMETERS: *time_desc - The 'time to delay' object descriptor - * *obj_desc - The object descriptor for this op + * PARAMETERS: time_desc - The 'time to delay' object descriptor + * obj_desc - The object descriptor for this op * * RETURN: Status * @@ -173,9 +175,8 @@ acpi_ex_acquire_mutex ( return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } - /* - * Support for multiple acquires by the owning thread - */ + /* Support for multiple acquires by the owning thread */ + if (obj_desc->mutex.owner_thread) { /* Special case for Global Lock, allow all threads */ @@ -199,10 +200,11 @@ acpi_ex_acquire_mutex ( return_ACPI_STATUS (status); } - /* Have the mutex, update mutex and walk info */ + /* Have the mutex: update mutex and walk info and save the sync_level */ - obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.owner_thread = walk_state->thread; obj_desc->mutex.acquisition_depth = 1; + obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; @@ -218,7 +220,7 @@ acpi_ex_acquire_mutex ( * * FUNCTION: acpi_ex_release_mutex * - * PARAMETERS: *obj_desc - The object descriptor for this op + * PARAMETERS: obj_desc - The object descriptor for this op * * RETURN: Status * @@ -281,9 +283,8 @@ acpi_ex_release_mutex ( return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } - /* - * Match multiple Acquires with multiple Releases - */ + /* Match multiple Acquires with multiple Releases */ + obj_desc->mutex.acquisition_depth--; if (obj_desc->mutex.acquisition_depth != 0) { /* Just decrement the depth and return */ @@ -299,10 +300,10 @@ acpi_ex_release_mutex ( status = acpi_ex_system_release_mutex (obj_desc); - /* Update the mutex and walk state */ + /* Update the mutex and walk state, restore sync_level before acquire */ obj_desc->mutex.owner_thread = NULL; - walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; + walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; return_ACPI_STATUS (status); } @@ -312,7 +313,7 @@ acpi_ex_release_mutex ( * * FUNCTION: acpi_ex_release_all_mutexes * - * PARAMETERS: *mutex_list - Head of the mutex list + * PARAMETERS: mutex_list - Head of the mutex list * * RETURN: Status * @@ -332,9 +333,8 @@ acpi_ex_release_all_mutexes ( ACPI_FUNCTION_ENTRY (); - /* - * Traverse the list of owned mutexes, releasing each one. - */ + /* Traverse the list of owned mutexes, releasing each one */ + while (next) { this = next; next = this->mutex.next; @@ -352,7 +352,11 @@ acpi_ex_release_all_mutexes ( /* Mark mutex unowned */ - this->mutex.owner_thread = NULL; + this->mutex.owner_thread = NULL; + + /* Update Thread sync_level (Last mutex is the important one) */ + + thread->current_sync_level = this->mutex.original_sync_level; } } diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 8ba1e6469..6e3193964 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -67,7 +67,7 @@ * Where: * * xA - ARGUMENTS: The number of arguments (input operands) that are - * required for this opcode type (1 through 6 args). + * required for this opcode type (0 through 6 args). * yT - TARGETS: The number of targets (output operands) that are required * for this opcode type (0, 1, or 2 targets). * zR - RETURN VALUE: Indicates whether this opcode type returns a value @@ -77,6 +77,69 @@ * fully resolved operands. !*/ +/******************************************************************************* + * + * FUNCTION: acpi_ex_opcode_0A_0T_1R + * + * PARAMETERS: walk_state - Current state (contains AML opcode) + * + * RETURN: Status + * + * DESCRIPTION: Execute operator with no operands, one return value + * + ******************************************************************************/ + +acpi_status +acpi_ex_opcode_0A_0T_1R ( + struct acpi_walk_state *walk_state) +{ + acpi_status status = AE_OK; + union acpi_operand_object *return_desc = NULL; + + + ACPI_FUNCTION_TRACE_STR ("ex_opcode_0A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + + + /* Examine the AML opcode */ + + switch (walk_state->opcode) { + case AML_TIMER_OP: /* Timer () */ + + /* Create a return object of type Integer */ + + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + return_desc->integer.value = acpi_os_get_timer (); + break; + + default: /* Unknown opcode */ + + ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", + walk_state->opcode)); + status = AE_AML_BAD_OPCODE; + break; + } + +cleanup: + + if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (return_desc); + } + + return_ACPI_STATUS (status); +} + + /******************************************************************************* * * FUNCTION: acpi_ex_opcode_1A_0T_0R @@ -124,7 +187,7 @@ acpi_ex_opcode_1A_0T_0R ( case AML_SLEEP_OP: /* Sleep (msec_time) */ - status = acpi_ex_system_do_suspend ((u32) operand[0]->integer.value); + status = acpi_ex_system_do_suspend (operand[0]->integer.value); break; @@ -222,7 +285,7 @@ acpi_ex_opcode_1A_1T_1R ( union acpi_operand_object *return_desc2 = NULL; u32 temp32; u32 i; - u32 power_of_ten; + acpi_integer power_of_ten; acpi_integer digit; @@ -262,7 +325,8 @@ acpi_ex_opcode_1A_1T_1R ( * Acpi specification describes Integer type as a little * endian unsigned value, so this boundary condition is valid. */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + for (temp32 = 0; return_desc->integer.value && + temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { return_desc->integer.value >>= 1; } @@ -278,13 +342,15 @@ acpi_ex_opcode_1A_1T_1R ( * The Acpi specification describes Integer type as a little * endian unsigned value, so this boundary condition is valid. */ - for (temp32 = 0; return_desc->integer.value && temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { + for (temp32 = 0; return_desc->integer.value && + temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { return_desc->integer.value <<= 1; } /* Since the bit position is one-based, subtract from 33 (65) */ - return_desc->integer.value = temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + return_desc->integer.value = temp32 == 0 ? 0 : + (ACPI_INTEGER_BIT_SIZE + 1) - temp32; break; @@ -319,7 +385,8 @@ acpi_ex_opcode_1A_1T_1R ( /* Sum the digit into the result with the current power of 10 */ - return_desc->integer.value += (((acpi_integer) temp32) * power_of_ten); + return_desc->integer.value += (((acpi_integer) temp32) * + power_of_ten); /* Shift to next BCD digit */ @@ -340,18 +407,20 @@ acpi_ex_opcode_1A_1T_1R ( /* Each BCD digit is one nybble wide */ for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { - (void) acpi_ut_short_divide (&digit, 10, &digit, &temp32); + (void) acpi_ut_short_divide (digit, 10, &digit, &temp32); /* Insert the BCD digit that resides in the remainder from above */ - return_desc->integer.value |= (((acpi_integer) temp32) << (i * 4)); + return_desc->integer.value |= (((acpi_integer) temp32) << + ACPI_MUL_4 (i)); } /* Overflow if there is any data left in Digit */ if (digit > 0) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Integer too large to convert to BCD: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (operand[0]->integer.value))); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Integer too large to convert to BCD: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (operand[0]->integer.value))); status = AE_AML_NUMERIC_OVERFLOW; goto cleanup; } @@ -429,42 +498,47 @@ acpi_ex_opcode_1A_1T_1R ( */ case AML_COPY_OP: /* Copy (Source, Target) */ - status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc, walk_state); + status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc, + walk_state); break; case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */ - status = acpi_ex_convert_to_string (operand[0], &return_desc, 10, ACPI_UINT32_MAX, walk_state); + status = acpi_ex_convert_to_string (operand[0], &return_desc, + ACPI_EXPLICIT_CONVERT_DECIMAL); break; case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */ - status = acpi_ex_convert_to_string (operand[0], &return_desc, 16, ACPI_UINT32_MAX, walk_state); + status = acpi_ex_convert_to_string (operand[0], &return_desc, + ACPI_EXPLICIT_CONVERT_HEX); break; case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */ - status = acpi_ex_convert_to_buffer (operand[0], &return_desc, walk_state); + status = acpi_ex_convert_to_buffer (operand[0], &return_desc); break; case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */ - status = acpi_ex_convert_to_integer (operand[0], &return_desc, walk_state); + status = acpi_ex_convert_to_integer (operand[0], &return_desc, + ACPI_ANY_BASE); break; - case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ - case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ + case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ + case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ /* * These are two obsolete opcodes */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s is obsolete and not implemented\n", - acpi_ps_get_opcode_name (walk_state->opcode))); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "%s is obsolete and not implemented\n", + acpi_ps_get_opcode_name (walk_state->opcode))); status = AE_SUPPORT; goto cleanup; @@ -537,7 +611,13 @@ acpi_ex_opcode_1A_0T_1R ( goto cleanup; } - return_desc->integer.value = !operand[0]->integer.value; + /* + * Set result to ONES (TRUE) if Value == 0. Note: + * return_desc->Integer.Value is initially == 0 (FALSE) from above. + */ + if (!operand[0]->integer.value) { + return_desc->integer.value = ACPI_INTEGER_MAX; + } break; @@ -545,54 +625,80 @@ acpi_ex_opcode_1A_0T_1R ( case AML_INCREMENT_OP: /* Increment (Operand) */ /* - * Since we are expecting a Reference operand, it - * can be either a NS Node or an internal object. + * Create a new integer. Can't just get the base integer and + * increment it because it may be an Arg or Field. + */ + return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); + if (!return_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Since we are expecting a Reference operand, it can be either a + * NS Node or an internal object. */ - return_desc = operand[0]; - if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_OPERAND) { + temp_desc = operand[0]; + if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) { /* Internal reference object - prevent deletion */ - acpi_ut_add_reference (return_desc); + acpi_ut_add_reference (temp_desc); } /* - * Convert the return_desc Reference to a Number - * (This removes a reference on the return_desc object) + * Convert the Reference operand to an Integer (This removes a + * reference on the Operand[0] object) + * + * NOTE: We use LNOT_OP here in order to force resolution of the + * reference operand to an actual integer. */ - status = acpi_ex_resolve_operands (AML_LNOT_OP, &return_desc, walk_state); + status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n", - acpi_ps_get_opcode_name (walk_state->opcode), acpi_format_exception(status))); + acpi_ps_get_opcode_name (walk_state->opcode), + acpi_format_exception(status))); goto cleanup; } /* - * return_desc is now guaranteed to be an Integer object - * Do the actual increment or decrement + * temp_desc is now guaranteed to be an Integer object -- + * Perform the actual increment or decrement */ - if (AML_INCREMENT_OP == walk_state->opcode) { - return_desc->integer.value++; + if (walk_state->opcode == AML_INCREMENT_OP) { + return_desc->integer.value = temp_desc->integer.value +1; } else { - return_desc->integer.value--; + return_desc->integer.value = temp_desc->integer.value -1; } - /* Store the result back in the original descriptor */ + /* Finished with this Integer object */ + + acpi_ut_remove_reference (temp_desc); + /* + * Store the result back (indirectly) through the original + * Reference object + */ status = acpi_ex_store (return_desc, operand[0], walk_state); break; case AML_TYPE_OP: /* object_type (source_object) */ + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. For example, we don't want + * to resolve a field_unit to its value, we want the actual field_unit + * object. + */ + /* Get the type of the base object */ status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL); if (ACPI_FAILURE (status)) { goto cleanup; } - /* Allocate a descriptor to hold the type. */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); @@ -607,6 +713,11 @@ acpi_ex_opcode_1A_0T_1R ( case AML_SIZE_OF_OP: /* size_of (source_object) */ + /* + * Note: The operand is not resolved at this point because we want to + * get the associated object, not its value. + */ + /* Get the base object */ status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, &temp_desc); @@ -615,11 +726,19 @@ acpi_ex_opcode_1A_0T_1R ( } /* - * Type is guaranteed to be a buffer, string, or package at this - * point (even if the original operand was an object reference, it - * will be resolved and typechecked during operand resolution.) + * The type of the base object must be integer, buffer, string, or + * package. All others are not supported. + * + * NOTE: Integer is not specifically supported by the ACPI spec, + * but is supported implicitly via implicit operand conversion. + * rather than bother with conversion, we just use the byte width + * global (4 or 8 bytes). */ switch (type) { + case ACPI_TYPE_INTEGER: + value = acpi_gbl_integer_byte_width; + break; + case ACPI_TYPE_BUFFER: value = temp_desc->buffer.length; break; @@ -633,7 +752,8 @@ acpi_ex_opcode_1A_0T_1R ( break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "size_of, Not Buf/Str/Pkg - found type %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n", acpi_ut_get_type_name (type))); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -803,7 +923,8 @@ acpi_ex_opcode_1A_0T_1R ( * an uninitialized package element and is thus a * severe error. */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "NULL package element obj %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "NULL package element obj %p\n", operand[0])); status = AE_AML_UNINITIALIZED_ELEMENT; goto cleanup; @@ -815,7 +936,8 @@ acpi_ex_opcode_1A_0T_1R ( default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Index target_type %X in obj %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unknown Index target_type %X in obj %p\n", operand[0]->reference.target_type, operand[0])); status = AE_AML_OPERAND_TYPE; goto cleanup; @@ -839,7 +961,8 @@ acpi_ex_opcode_1A_0T_1R ( default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode in ref(%p) - %X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unknown opcode in ref(%p) - %X\n", operand[0], operand[0]->reference.opcode)); status = AE_TYPE; diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 70602ad44..877831825 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -97,6 +97,7 @@ acpi_ex_opcode_2A_0T_0R ( { union acpi_operand_object **operand = &walk_state->operands[0]; struct acpi_namespace_node *node; + u32 value; acpi_status status = AE_OK; @@ -113,16 +114,46 @@ acpi_ex_opcode_2A_0T_0R ( node = (struct acpi_namespace_node *) operand[0]; + /* Second value is the notify value */ + + value = (u32) operand[1]->integer.value; + /* Notifies allowed on this object? */ if (!acpi_ev_is_notify_object (node)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unexpected notify object type [%s]\n", acpi_ut_get_type_name (node->type))); status = AE_AML_OPERAND_TYPE; break; } +#ifdef ACPI_GPE_NOTIFY_CHECK + /* + * GPE method wake/notify check. Here, we want to ensure that we + * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx + * GPE method during system runtime. If we do, the GPE is marked + * as "wake-only" and disabled. + * + * 1) Is the Notify() value == device_wake? + * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) + * 3) Did the original GPE happen at system runtime? + * (versus during wake) + * + * If all three cases are true, this is a wake-only GPE that should + * be disabled at runtime. + */ + if (value == 2) /* device_wake */ { + status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info); + if (ACPI_FAILURE (status)) { + /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ + + return_ACPI_STATUS (AE_OK) + } + } +#endif + /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method @@ -130,8 +161,7 @@ acpi_ex_opcode_2A_0T_0R ( * from this thread -- because handlers may in turn run other * control methods. */ - status = acpi_ev_queue_notify_request (node, - (u32) operand[1]->integer.value); + status = acpi_ev_queue_notify_request (node, value); break; @@ -169,7 +199,8 @@ acpi_ex_opcode_2A_2T_1R ( acpi_status status; - ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R", + acpi_ps_get_opcode_name (walk_state->opcode)); /* @@ -192,8 +223,10 @@ acpi_ex_opcode_2A_2T_1R ( /* Quotient to return_desc1, remainder to return_desc2 */ - status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value, - &return_desc1->integer.value, &return_desc2->integer.value); + status = acpi_ut_divide (operand[0]->integer.value, + operand[1]->integer.value, + &return_desc1->integer.value, + &return_desc2->integer.value); if (ACPI_FAILURE (status)) { goto cleanup; } @@ -262,13 +295,13 @@ acpi_ex_opcode_2A_1T_1R ( { union acpi_operand_object **operand = &walk_state->operands[0]; union acpi_operand_object *return_desc = NULL; - union acpi_operand_object *temp_desc = NULL; u32 index; acpi_status status = AE_OK; acpi_size length; - ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R", + acpi_ps_get_opcode_name (walk_state->opcode)); /* @@ -301,52 +334,17 @@ acpi_ex_opcode_2A_1T_1R ( /* return_desc will contain the remainder */ - status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value, - NULL, &return_desc->integer.value); + status = acpi_ut_divide (operand[0]->integer.value, + operand[1]->integer.value, + NULL, + &return_desc->integer.value); break; case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ - /* - * Convert the second operand if necessary. The first operand - * determines the type of the second operand, (See the Data Types - * section of the ACPI specification.) Both object types are - * guaranteed to be either Integer/String/Buffer by the operand - * resolution mechanism above. - */ - switch (ACPI_GET_OBJECT_TYPE (operand[0])) { - case ACPI_TYPE_INTEGER: - status = acpi_ex_convert_to_integer (operand[1], &temp_desc, walk_state); - break; - - case ACPI_TYPE_STRING: - status = acpi_ex_convert_to_string (operand[1], &temp_desc, 16, ACPI_UINT32_MAX, walk_state); - break; - - case ACPI_TYPE_BUFFER: - status = acpi_ex_convert_to_buffer (operand[1], &temp_desc, walk_state); - break; - - default: - ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", - ACPI_GET_OBJECT_TYPE (operand[0]))); - status = AE_AML_INTERNAL; - } - - if (ACPI_FAILURE (status)) { - goto cleanup; - } - - /* - * Both operands are now known to be the same object type - * (Both are Integer, String, or Buffer), and we can now perform the - * concatenation. - */ - status = acpi_ex_do_concatenate (operand[0], temp_desc, &return_desc, walk_state); - if (temp_desc != operand[1]) { - acpi_ut_remove_reference (temp_desc); - } + status = acpi_ex_do_concatenate (operand[0], operand[1], + &return_desc, walk_state); break; @@ -357,55 +355,45 @@ acpi_ex_opcode_2A_1T_1R ( * been converted.) Copy the raw buffer data to a new object of type String. */ - /* Get the length of the new string */ - + /* + * Get the length of the new string. It is the smallest of: + * 1) Length of the input buffer + * 2) Max length as specified in the to_string operator + * 3) Length of input buffer up to a zero byte (null terminator) + * + * NOTE: A length of zero is ok, and will create a zero-length, null + * terminated string. + */ length = 0; - if (operand[1]->integer.value == 0) { - /* Handle optional length value */ - - operand[1]->integer.value = ACPI_INTEGER_MAX; - } - while ((length < operand[0]->buffer.length) && (length < operand[1]->integer.value) && (operand[0]->buffer.pointer[length])) { length++; + if (length > ACPI_MAX_STRING_CONVERSION) { + status = AE_AML_STRING_LIMIT; + goto cleanup; + } } - if (length > ACPI_MAX_STRING_CONVERSION) { - status = AE_AML_STRING_LIMIT; - goto cleanup; - } - - /* Create the internal return object */ + /* Allocate a new string object */ - return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + return_desc = acpi_ut_create_string_object (length); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } - /* Allocate a new string buffer (Length + 1 for null terminator) */ - - return_desc->string.pointer = ACPI_MEM_CALLOCATE (length + 1); - if (!return_desc->string.pointer) { - status = AE_NO_MEMORY; - goto cleanup; - } + /* Copy the raw buffer data with no transform. NULL terminated already. */ - /* Copy the raw buffer data with no transform */ - - ACPI_MEMCPY (return_desc->string.pointer, operand[0]->buffer.pointer, length); - - /* Set the string length */ - - return_desc->string.length = (u32) length; + ACPI_MEMCPY (return_desc->string.pointer, + operand[0]->buffer.pointer, length); break; case AML_CONCAT_RES_OP: /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ - status = acpi_ex_concat_template (operand[0], operand[1], &return_desc, walk_state); + status = acpi_ex_concat_template (operand[0], operand[1], + &return_desc, walk_state); break; @@ -428,7 +416,8 @@ acpi_ex_opcode_2A_1T_1R ( /* Object to be indexed is a Package */ if (index >= operand[0]->package.count) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value (%X) beyond package end (%X)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Index value (%X) beyond package end (%X)\n", index, operand[0]->package.count)); status = AE_AML_PACKAGE_LIMIT; goto cleanup; @@ -442,7 +431,8 @@ acpi_ex_opcode_2A_1T_1R ( /* Object to be indexed is a Buffer */ if (index >= operand[0]->buffer.length) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value (%X) beyond end of buffer (%X)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Index value (%X) beyond end of buffer (%X)\n", index, operand[0]->buffer.length)); status = AE_AML_BUFFER_LIMIT; goto cleanup; @@ -528,7 +518,8 @@ acpi_ex_opcode_2A_0T_1R ( u8 logical_result = FALSE; - ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode)); + ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R", + acpi_ps_get_opcode_name (walk_state->opcode)); /* Create the internal return object */ @@ -542,10 +533,15 @@ acpi_ex_opcode_2A_0T_1R ( /* * Execute the Opcode */ - if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ { - logical_result = acpi_ex_do_logical_op (walk_state->opcode, - operand[0]->integer.value, - operand[1]->integer.value); + if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ { + status = acpi_ex_do_logical_numeric_op (walk_state->opcode, + operand[0]->integer.value, operand[1]->integer.value, + &logical_result); + goto store_logical_result; + } + else if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ { + status = acpi_ex_do_logical_op (walk_state->opcode, operand[0], + operand[1], &logical_result); goto store_logical_result; } diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index c5c6dd8e0..0834af85f 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -508,6 +508,7 @@ acpi_ex_prep_field_value ( if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { ACPI_REPORT_ERROR (("Null Index Object during field prep\n")); + acpi_ut_delete_object_desc (obj_desc); return_ACPI_STATUS (AE_AML_INTERNAL); } diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 3262f1a1d..4fef755ce 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -121,7 +121,7 @@ acpi_ex_system_memory_space_handler ( * Hardware does not support non-aligned data transfers, we must verify * the request. */ - (void) acpi_ut_short_divide ((acpi_integer *) &address, length, NULL, &remainder); + (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder); if (remainder != 0) { return_ACPI_STATUS (AE_AML_ALIGNMENT); } diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index e998da7cd..c339d7471 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -187,15 +187,15 @@ acpi_ex_resolve_object_to_value ( return_ACPI_STATUS (status); } + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n", + stack_desc->reference.offset, obj_desc)); + /* * Now we can delete the original Reference Object and - * replace it with the resolve value + * replace it with the resolved value */ acpi_ut_remove_reference (stack_desc); *stack_ptr = obj_desc; - - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] value_obj is %p\n", - stack_desc->reference.offset, obj_desc)); break; @@ -327,11 +327,44 @@ acpi_ex_resolve_multiple ( union acpi_operand_object *obj_desc = (void *) operand; struct acpi_namespace_node *node; acpi_object_type type; + acpi_status status; ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple"); + /* + * Operand can be either a namespace node or an operand descriptor + */ + switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { + case ACPI_DESC_TYPE_OPERAND: + type = obj_desc->common.type; + break; + + case ACPI_DESC_TYPE_NAMED: + type = ((struct acpi_namespace_node *) obj_desc)->type; + obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc); + + /* If we had an Alias node, use the attached object for type info */ + + if (type == ACPI_TYPE_LOCAL_ALIAS) { + type = ((struct acpi_namespace_node *) obj_desc)->type; + obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc); + } + break; + + default: + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + + /* + * If type is anything other than a reference, we are done + */ + if (type != ACPI_TYPE_LOCAL_REFERENCE) { + goto exit; + } + /* * For reference objects created via the ref_of or Index operators, * we need to get to the base object (as per the ACPI specification @@ -424,6 +457,33 @@ acpi_ex_resolve_multiple ( break; + case AML_LOCAL_OP: + case AML_ARG_OP: + + if (return_desc) { + status = acpi_ds_method_data_get_value (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state, &obj_desc); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + acpi_ut_remove_reference (obj_desc); + } + else { + status = acpi_ds_method_data_get_node (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state, &node); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { + type = ACPI_TYPE_ANY; + goto exit; + } + } + break; + + case AML_DEBUG_OP: /* The Debug Object is of type "debug_object" */ diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index d410bd7f1..51df1a705 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -160,7 +160,7 @@ acpi_ex_resolve_operands ( return_ACPI_STATUS (AE_AML_INTERNAL); } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] operand_types=%X \n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] required_operand_types=%8.8X \n", opcode, op_info->name, arg_types)); /* @@ -227,12 +227,13 @@ acpi_ex_resolve_operands ( case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */ ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Reference Opcode: %s\n", op_info->name))); + "Operand is a Reference, ref_opcode [%s]\n", + (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name))); break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown Reference Opcode %X [%s]\n", + "Operand is a Reference, Unknown Reference Opcode %X [%s]\n", obj_desc->reference.opcode, (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)); @@ -398,7 +399,7 @@ acpi_ex_resolve_operands ( * But we can implicitly convert from a STRING or BUFFER * Aka - "Implicit Source Operand Conversion" */ - status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, walk_state); + status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -420,7 +421,7 @@ acpi_ex_resolve_operands ( * But we can implicitly convert from a STRING or INTEGER * Aka - "Implicit Source Operand Conversion" */ - status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr, walk_state); + status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -442,7 +443,8 @@ acpi_ex_resolve_operands ( * But we can implicitly convert from a BUFFER or INTEGER * Aka - "Implicit Source Operand Conversion" */ - status = acpi_ex_convert_to_string (obj_desc, stack_ptr, 16, ACPI_UINT32_MAX, walk_state); + status = acpi_ex_convert_to_string (obj_desc, stack_ptr, + ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE (status)) { if (status == AE_TYPE) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, @@ -494,7 +496,7 @@ acpi_ex_resolve_operands ( /* Highest priority conversion is to type Buffer */ - status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr, walk_state); + status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 8c884652c..33fbfed24 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -102,7 +102,8 @@ acpi_ex_store ( * Storing an object into a Named node. */ status = acpi_ex_store_object_to_node (source_desc, - (struct acpi_namespace_node *) dest_desc, walk_state); + (struct acpi_namespace_node *) dest_desc, walk_state, + ACPI_IMPLICIT_CONVERSION); return_ACPI_STATUS (status); } @@ -128,7 +129,8 @@ acpi_ex_store ( /* Destination is not a Reference object */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Destination is not a Reference or Constant object [%p]\n", dest_desc)); + "Target is not a Reference or Constant object - %s [%p]\n", + acpi_ut_get_object_type_name (dest_desc), dest_desc)); ACPI_DUMP_STACK_ENTRY (source_desc); ACPI_DUMP_STACK_ENTRY (dest_desc); @@ -153,7 +155,7 @@ acpi_ex_store ( /* Storing an object into a Name "container" */ status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object, - walk_state); + walk_state, ACPI_IMPLICIT_CONVERSION); break; @@ -181,23 +183,37 @@ acpi_ex_store ( * Storing to the Debug object causes the value stored to be * displayed and otherwise has no effect -- see ACPI Specification */ - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Write to Debug Object: ****:\n\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "**** Write to Debug Object: Object %p %s ****:\n\n", + source_desc, acpi_ut_get_object_type_name (source_desc))); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ", - acpi_ut_get_object_type_name (source_desc))); + acpi_ut_get_object_type_name (source_desc))); + + if (!acpi_ut_valid_internal_object (source_desc)) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, + "%p, Invalid Internal Object!\n", source_desc)); + break; + } switch (ACPI_GET_OBJECT_TYPE (source_desc)) { case ACPI_TYPE_INTEGER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", + if (acpi_gbl_integer_byte_width == 4) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", + (u32) source_desc->integer.value)); + } + else { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (source_desc->integer.value))); + } break; case ACPI_TYPE_BUFFER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X", - (u32) source_desc->buffer.length)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]", + (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER (source_desc->buffer.pointer, (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32); break; @@ -205,22 +221,22 @@ acpi_ex_store ( case ACPI_TYPE_STRING: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n", - source_desc->string.length, source_desc->string.pointer)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", + source_desc->string.length, source_desc->string.pointer)); break; case ACPI_TYPE_PACKAGE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n", - source_desc->package.count, source_desc->package.elements)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] Elements Ptr - %p\n", + source_desc->package.count, source_desc->package.elements)); break; default: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n", - source_desc)); + source_desc)); break; } @@ -399,6 +415,7 @@ acpi_ex_store_object_to_index ( * PARAMETERS: source_desc - Value to be stored * Node - Named object to receive the value * walk_state - Current walk state + * implicit_conversion - Perform implicit conversion (yes/no) * * RETURN: Status * @@ -421,7 +438,8 @@ acpi_status acpi_ex_store_object_to_node ( union acpi_operand_object *source_desc, struct acpi_namespace_node *node, - struct acpi_walk_state *walk_state) + struct acpi_walk_state *walk_state, + u8 implicit_conversion) { acpi_status status = AE_OK; union acpi_operand_object *target_desc; @@ -451,6 +469,14 @@ acpi_ex_store_object_to_node ( return_ACPI_STATUS (status); } + /* If no implicit conversion, drop into the default case below */ + + if (!implicit_conversion) { + /* Force execution of default (no implicit conversion) */ + + target_type = ACPI_TYPE_ANY; + } + /* * Do the actual store operation */ diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 42a1332b5..46e5fa6d0 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -167,7 +167,7 @@ acpi_ex_system_do_stall ( acpi_status acpi_ex_system_do_suspend ( - u32 how_long) + acpi_integer how_long) { acpi_status status; @@ -179,8 +179,7 @@ acpi_ex_system_do_suspend ( acpi_ex_exit_interpreter (); - acpi_os_sleep ((u16) (how_long / (u32) 1000), - (u16) (how_long % (u32) 1000)); + acpi_os_sleep (how_long); /* And now we must get the interpreter again */ diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index bc425b2b4..85253b389 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -280,25 +280,25 @@ acpi_ex_digits_needed ( { u32 num_digits; acpi_integer current_value; - acpi_integer quotient; ACPI_FUNCTION_TRACE ("ex_digits_needed"); - /* - * acpi_integer is unsigned, so we don't worry about a '-' - */ - if ((current_value = value) == 0) { + /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ + + if (value == 0) { return_VALUE (1); } + current_value = value; num_digits = 0; + /* Count the digits in the requested base */ + while (current_value) { - (void) acpi_ut_short_divide (¤t_value, base, "ient, NULL); + (void) acpi_ut_short_divide (current_value, base, ¤t_value, NULL); num_digits++; - current_value = quotient; } return_VALUE (num_digits); @@ -361,7 +361,6 @@ acpi_ex_unsigned_integer_to_string ( u32 count; u32 digits_needed; u32 remainder; - acpi_integer quotient; ACPI_FUNCTION_ENTRY (); @@ -371,9 +370,8 @@ acpi_ex_unsigned_integer_to_string ( out_string[digits_needed] = 0; for (count = digits_needed; count > 0; count--) { - (void) acpi_ut_short_divide (&value, 10, "ient, &remainder); + (void) acpi_ut_short_divide (value, 10, &value, &remainder); out_string[count-1] = (char) ('0' + remainder);\ - value = quotient; } } diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index fa2a1b414..2c5422dfe 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -75,51 +76,41 @@ struct proc_dir_entry *acpi_fan_dir; static int -acpi_fan_read_state ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +acpi_fan_read_state (struct seq_file *seq, void *offset) { - struct acpi_fan *fan = (struct acpi_fan *) data; - char *p = page; - int len = 0; + struct acpi_fan *fan = (struct acpi_fan *) seq->private; int state = 0; ACPI_FUNCTION_TRACE("acpi_fan_read_state"); - if (!fan || (off != 0)) + if (!fan) goto end; if (acpi_bus_get_power(fan->handle, &state)) goto end; - p += sprintf(p, "status: %s\n", + seq_printf(seq, "status: %s\n", !state?"on":"off"); end: - len = (p - page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - - return_VALUE(len); + return_VALUE(0); } +static int acpi_fan_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_fan_read_state, PDE(inode)->data); +} -static int +static ssize_t acpi_fan_write_state ( struct file *file, const char __user *buffer, - unsigned long count, - void *data) + size_t count, + loff_t *ppos) { int result = 0; - struct acpi_fan *fan = (struct acpi_fan *) data; + struct seq_file *m = (struct seq_file *)file->private_data; + struct acpi_fan *fan = (struct acpi_fan *) m->private; char state_string[12] = {'\0'}; ACPI_FUNCTION_TRACE("acpi_fan_write_state"); @@ -140,6 +131,14 @@ acpi_fan_write_state ( return_VALUE(count); } +static struct file_operations acpi_fan_state_ops = { + .open = acpi_fan_state_open_fs, + .read = seq_read, + .write = acpi_fan_write_state, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; static int acpi_fan_add_fs ( @@ -168,8 +167,7 @@ acpi_fan_add_fs ( "Unable to create '%s' fs entry\n", ACPI_FAN_FILE_STATE)); else { - entry->read_proc = acpi_fan_read_state; - entry->write_proc = acpi_fan_write_state; + entry->proc_fops = &acpi_fan_state_ops; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } diff --git a/drivers/acpi/hardware/Makefile b/drivers/acpi/hardware/Makefile index 97989bc85..438ad373b 100644 --- a/drivers/acpi/hardware/Makefile +++ b/drivers/acpi/hardware/Makefile @@ -2,6 +2,8 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o hwtimer.o +obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o + +obj-$(ACPI_FUTURE_USAGE) += hwtimer.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index f3fddc274..e4f17ac9f 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -51,104 +51,24 @@ /****************************************************************************** * - * FUNCTION: acpi_hw_enable_gpe + * FUNCTION: acpi_hw_write_gpe_enable_reg * * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled * * RETURN: Status * - * DESCRIPTION: Enable a single GPE. + * DESCRIPTION: Write a GPE enable register. Note: The bit for this GPE must + * already be cleared or set in the parent register + * enable_for_run mask. * ******************************************************************************/ acpi_status -acpi_hw_enable_gpe ( - struct acpi_gpe_event_info *gpe_event_info) -{ - u32 in_byte; - acpi_status status; - - - ACPI_FUNCTION_ENTRY (); - - - /* - * Read the current value of the register, set the appropriate bit - * to enable the GPE, and write out the new register. - */ - status = acpi_hw_low_level_read (8, &in_byte, - &gpe_event_info->register_info->enable_address); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Write with the new GPE bit enabled */ - - status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask), - &gpe_event_info->register_info->enable_address); - - return (status); -} - - -/****************************************************************************** - * - * FUNCTION: acpi_hw_enable_gpe_for_wakeup - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be enabled - * - * RETURN: None - * - * DESCRIPTION: Keep track of which GPEs the OS has requested not be - * disabled when going to sleep. - * - ******************************************************************************/ - -void -acpi_hw_enable_gpe_for_wakeup ( +acpi_hw_write_gpe_enable_reg ( struct acpi_gpe_event_info *gpe_event_info) { struct acpi_gpe_register_info *gpe_register_info; - - - ACPI_FUNCTION_ENTRY (); - - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return; - } - - /* - * Set the bit so we will not enable this GPE when sleeping (and disable - * it upon wake) - */ - gpe_register_info->wake_enable |= gpe_event_info->bit_mask; - gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED); -} - - -/****************************************************************************** - * - * FUNCTION: acpi_hw_disable_gpe - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled - * - * RETURN: Status - * - * DESCRIPTION: Disable a single GPE. - * - ******************************************************************************/ - -acpi_status -acpi_hw_disable_gpe ( - struct acpi_gpe_event_info *gpe_event_info) -{ - u32 in_byte; acpi_status status; - struct acpi_gpe_register_info *gpe_register_info; ACPI_FUNCTION_ENTRY (); @@ -158,67 +78,15 @@ acpi_hw_disable_gpe ( gpe_register_info = gpe_event_info->register_info; if (!gpe_register_info) { - return (AE_BAD_PARAMETER); - } - - /* - * Read the current value of the register, clear the appropriate bit, - * and write out the new register value to disable the GPE. - */ - status = acpi_hw_low_level_read (8, &in_byte, - &gpe_register_info->enable_address); - if (ACPI_FAILURE (status)) { - return (status); + return (AE_NOT_EXIST); } - /* Write the byte with this GPE bit cleared */ + /* Write the entire GPE (runtime) enable register */ - status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)), + status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run, &gpe_register_info->enable_address); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Make sure this GPE is disabled for wake, also */ - - acpi_hw_disable_gpe_for_wakeup (gpe_event_info); - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: acpi_hw_disable_gpe_for_wakeup - * - * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled - * - * RETURN: None - * - * DESCRIPTION: Keep track of which GPEs the OS has requested not be - * disabled when going to sleep. - * - ******************************************************************************/ -void -acpi_hw_disable_gpe_for_wakeup ( - struct acpi_gpe_event_info *gpe_event_info) -{ - struct acpi_gpe_register_info *gpe_register_info; - - - ACPI_FUNCTION_ENTRY (); - - - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return; - } - - /* Clear the bit so we will disable this when sleeping */ - - gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask); + return (status); } @@ -228,7 +96,7 @@ acpi_hw_disable_gpe_for_wakeup ( * * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared * - * RETURN: status_status + * RETURN: Status * * DESCRIPTION: Clear the status bit for a single GPE. * @@ -248,7 +116,7 @@ acpi_hw_clear_gpe ( * Write a one to the appropriate bit in the status register to * clear this GPE. */ - status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask, + status = acpi_hw_low_level_write (8, gpe_event_info->register_bit, &gpe_event_info->register_info->status_address); return (status); @@ -267,14 +135,14 @@ acpi_hw_clear_gpe ( * DESCRIPTION: Return the status of a single GPE. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_hw_get_gpe_status ( struct acpi_gpe_event_info *gpe_event_info, acpi_event_status *event_status) { u32 in_byte; - u8 bit_mask; + u8 register_bit; struct acpi_gpe_register_info *gpe_register_info; acpi_status status; acpi_event_status local_event_status = 0; @@ -293,33 +161,28 @@ acpi_hw_get_gpe_status ( /* Get the register bitmask for this GPE */ - bit_mask = gpe_event_info->bit_mask; + register_bit = gpe_event_info->register_bit; - /* GPE Enabled? */ + /* GPE currently enabled? (enabled for runtime?) */ - status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address); - if (ACPI_FAILURE (status)) { - goto unlock_and_exit; - } - - if (bit_mask & in_byte) { + if (register_bit & gpe_register_info->enable_for_run) { local_event_status |= ACPI_EVENT_FLAG_ENABLED; } - /* GPE Enabled for wake? */ + /* GPE enabled for wake? */ - if (bit_mask & gpe_register_info->wake_enable) { + if (register_bit & gpe_register_info->enable_for_wake) { local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; } - /* GPE active (set)? */ + /* GPE currently active (status bit == 1)? */ status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - if (bit_mask & in_byte) { + if (register_bit & in_byte) { local_event_status |= ACPI_EVENT_FLAG_SET; } @@ -331,6 +194,7 @@ acpi_hw_get_gpe_status ( unlock_and_exit: return (status); } +#endif /* ACPI_FUTURE_USAGE */ /****************************************************************************** @@ -411,64 +275,43 @@ acpi_hw_clear_gpe_block ( /****************************************************************************** * - * FUNCTION: acpi_hw_prepare_gpe_block_for_sleep + * FUNCTION: acpi_hw_enable_runtime_gpe_block * * PARAMETERS: gpe_xrupt_info - GPE Interrupt info * gpe_block - Gpe Block info * * RETURN: Status * - * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within - * a single GPE block + * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes + * combination wake/run GPEs.) * ******************************************************************************/ -static acpi_status -acpi_hw_prepare_gpe_block_for_sleep ( +acpi_status +acpi_hw_enable_runtime_gpe_block ( struct acpi_gpe_xrupt_info *gpe_xrupt_info, struct acpi_gpe_block_info *gpe_block) { u32 i; - struct acpi_gpe_register_info *gpe_register_info; - u32 in_value; acpi_status status; - /* Get the register info for the entire GPE block */ - - gpe_register_info = gpe_block->register_info; + /* NOTE: assumes that all GPEs are currently disabled */ /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { - /* - * Read the enabled/disabled status of all GPEs. We - * will be using it to restore all the GPEs later. - * - * NOTE: Wake GPEs are are ALL disabled at this time, so when we wake - * and restore this register, they will be automatically disabled. - */ - status = acpi_hw_low_level_read (8, &in_value, - &gpe_register_info->enable_address); - if (ACPI_FAILURE (status)) { - return (status); + if (!gpe_block->register_info[i].enable_for_run) { + continue; } - gpe_register_info->enable = (u8) in_value; + /* Enable all "runtime" GPEs in this register */ - /* - * 1) Disable all runtime GPEs - * 2) Enable all wakeup GPEs - */ - status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, - &gpe_register_info->enable_address); + status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run, + &gpe_block->register_info[i].enable_address); if (ACPI_FAILURE (status)) { return (status); } - - /* Point to next GPE register */ - - gpe_register_info++; } return (AE_OK); @@ -477,122 +320,125 @@ acpi_hw_prepare_gpe_block_for_sleep ( /****************************************************************************** * - * FUNCTION: acpi_hw_prepare_gpes_for_sleep + * FUNCTION: acpi_hw_enable_wakeup_gpe_block * - * PARAMETERS: None + * PARAMETERS: gpe_xrupt_info - GPE Interrupt info + * gpe_block - Gpe Block info * * RETURN: Status * - * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs. - * Called with interrupts disabled. The interrupt handler also - * modifies gpe_register_info->Enable, so it should not be - * given the chance to run until after the runtime GPEs are - * re-enabled. + * DESCRIPTION: Enable all "wake" GPEs within a GPE block. (Includes + * combination wake/run GPEs.) * ******************************************************************************/ acpi_status -acpi_hw_prepare_gpes_for_sleep ( - void) +acpi_hw_enable_wakeup_gpe_block ( + struct acpi_gpe_xrupt_info *gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block) { + u32 i; acpi_status status; - ACPI_FUNCTION_ENTRY (); + /* Examine each GPE Register within the block */ + for (i = 0; i < gpe_block->register_count; i++) { + if (!gpe_block->register_info[i].enable_for_wake) { + continue; + } - status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep); - return (status); + /* Enable all "wake" GPEs in this register */ + + status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake, + &gpe_block->register_info[i].enable_address); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + return (AE_OK); } /****************************************************************************** * - * FUNCTION: acpi_hw_restore_gpe_block_on_wake + * FUNCTION: acpi_hw_disable_all_gpes * - * PARAMETERS: gpe_xrupt_info - GPE Interrupt info - * gpe_block - Gpe Block info + * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR * * RETURN: Status * - * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one - * GPE block + * DESCRIPTION: Disable and clear all GPEs * ******************************************************************************/ -static acpi_status -acpi_hw_restore_gpe_block_on_wake ( - struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block) +acpi_status +acpi_hw_disable_all_gpes ( + u32 flags) { - u32 i; - struct acpi_gpe_register_info *gpe_register_info; acpi_status status; - /* This callback processes one entire GPE block */ + ACPI_FUNCTION_TRACE ("hw_disable_all_gpes"); - /* Get the register info for the entire GPE block */ - gpe_register_info = gpe_block->register_info; + status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags); + status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags); + return_ACPI_STATUS (status); +} - /* Examine each GPE register within the block */ - for (i = 0; i < gpe_block->register_count; i++) { - /* Clear the entire status register */ +/****************************************************************************** + * + * FUNCTION: acpi_hw_enable_all_runtime_gpes + * + * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR + * + * RETURN: Status + * + * DESCRIPTION: Enable all GPEs of the given type + * + ******************************************************************************/ - status = acpi_hw_low_level_write (8, 0xFF, - &gpe_block->register_info[i].status_address); - if (ACPI_FAILURE (status)) { - return (status); - } +acpi_status +acpi_hw_enable_all_runtime_gpes ( + u32 flags) +{ + acpi_status status; - /* - * Restore the GPE Enable register, which will do the following: - * - * 1) Disable all wakeup GPEs - * 2) Enable all runtime GPEs - * - * (On sleep, we saved the enabled status of all GPEs) - */ - status = acpi_hw_low_level_write (8, gpe_register_info->enable, - &gpe_register_info->enable_address); - if (ACPI_FAILURE (status)) { - return (status); - } - /* Point to next GPE register */ + ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes"); - gpe_register_info++; - } - return (AE_OK); + status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags); + return_ACPI_STATUS (status); } /****************************************************************************** * - * FUNCTION: acpi_hw_restore_gpes_on_wake + * FUNCTION: acpi_hw_enable_all_wakeup_gpes * - * PARAMETERS: None + * PARAMETERS: Flags - ACPI_NOT_ISR or ACPI_ISR * * RETURN: Status * - * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all - * GPE blocks + * DESCRIPTION: Enable all GPEs of the given type * ******************************************************************************/ acpi_status -acpi_hw_restore_gpes_on_wake ( - void) +acpi_hw_enable_all_wakeup_gpes ( + u32 flags) { acpi_status status; - ACPI_FUNCTION_ENTRY (); + ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes"); - status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake); - return (status); + status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags); + return_ACPI_STATUS (status); } + diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index a7c651316..11daf53c5 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -43,6 +43,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -61,6 +62,7 @@ * RETURN: none * * DESCRIPTION: Clears all fixed and general purpose status bits + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ @@ -103,7 +105,7 @@ acpi_hw_clear_acpi_status ( /* Clear the GPE Bits in all GPE registers in all GPE blocks */ - status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block); + status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR); unlock_and_exit: if (flags & ACPI_MTX_LOCK) { @@ -135,7 +137,7 @@ acpi_get_sleep_type_data ( u8 *sleep_type_b) { acpi_status status = AE_OK; - union acpi_operand_object *obj_desc; + struct acpi_parameter_info info; ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data"); @@ -152,8 +154,9 @@ acpi_get_sleep_type_data ( /* * Evaluate the namespace object containing the values for this state */ + info.parameters = NULL; status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state], - NULL, &obj_desc); + &info); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n", acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state])); @@ -163,50 +166,53 @@ acpi_get_sleep_type_data ( /* Must have a return object */ - if (!obj_desc) { + if (!info.return_object) { ACPI_REPORT_ERROR (("Missing Sleep State object\n")); status = AE_NOT_EXIST; } /* It must be of type Package */ - else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) { + else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) { ACPI_REPORT_ERROR (("Sleep State object not a Package\n")); status = AE_AML_OPERAND_TYPE; } /* The package must have at least two elements */ - else if (obj_desc->package.count < 2) { + else if (info.return_object->package.count < 2) { ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n")); status = AE_AML_NO_OPERAND; } /* The first two elements must both be of type Integer */ - else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) { + else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) || + (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) { ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n", - acpi_ut_get_object_type_name (obj_desc->package.elements[0]), - acpi_ut_get_object_type_name (obj_desc->package.elements[1]))); + acpi_ut_get_object_type_name (info.return_object->package.elements[0]), + acpi_ut_get_object_type_name (info.return_object->package.elements[1]))); status = AE_AML_OPERAND_TYPE; } else { /* * Valid _Sx_ package size, type, and value */ - *sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value; - *sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value; + *sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value; + *sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value; } if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n", - acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc))); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "While evaluating sleep_state [%s], bad Sleep object %p type %s\n", + acpi_gbl_sleep_state_names[sleep_state], info.return_object, + acpi_ut_get_object_type_name (info.return_object))); } - acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (info.return_object); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_sleep_type_data); /******************************************************************************* @@ -245,8 +251,8 @@ acpi_hw_get_bit_register_info ( * return_value - Value that was read from the register * Flags - Lock the hardware or not * - * RETURN: Value is read from specified Register. Value returned is - * normalized to bit0 (is shifted all the way right) + * RETURN: Status and the value read from specified Register. Value + * returned is normalized to bit0 (is shifted all the way right) * * DESCRIPTION: ACPI bit_register read function. * @@ -280,6 +286,8 @@ acpi_get_register ( } } + /* Read from the register */ + status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, bit_reg_info->parent_register, ®ister_value); @@ -301,6 +309,7 @@ acpi_get_register ( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_register); /******************************************************************************* @@ -309,10 +318,10 @@ acpi_get_register ( * * PARAMETERS: register_id - ID of ACPI bit_register to access * Value - (only used on write) value to write to the - * Register, NOT pre-normalized to the bit pos. + * Register, NOT pre-normalized to the bit pos * Flags - Lock the hardware or not * - * RETURN: None + * RETURN: Status * * DESCRIPTION: ACPI Bit Register write function. * @@ -451,16 +460,18 @@ unlock_and_exit: value, register_value, bit_reg_info->parent_register)); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_set_register); /****************************************************************************** * * FUNCTION: acpi_hw_register_read * - * PARAMETERS: use_lock - Mutex hw access. - * register_id - register_iD + Offset. + * PARAMETERS: use_lock - Mutex hw access + * register_id - register_iD + Offset + * return_value - Value that was read from the register * - * RETURN: Value read or written. + * RETURN: Status and the value read. * * DESCRIPTION: Acpi register read function. Registers are read at the * given offset. @@ -568,10 +579,11 @@ unlock_and_exit: * * FUNCTION: acpi_hw_register_write * - * PARAMETERS: use_lock - Mutex hw access. - * register_id - register_iD + Offset. + * PARAMETERS: use_lock - Mutex hw access + * register_id - register_iD + Offset + * Value - The value to write * - * RETURN: Value read or written. + * RETURN: Status * * DESCRIPTION: Acpi register Write function. Registers are written at the * given offset. @@ -687,11 +699,11 @@ unlock_and_exit: * * PARAMETERS: Width - 8, 16, or 32 * Value - Where the value is returned - * Register - GAS register structure + * Reg - GAS register structure * * RETURN: Status * - * DESCRIPTION: Read from either memory, IO, or PCI config space. + * DESCRIPTION: Read from either memory or IO space. * ******************************************************************************/ @@ -701,8 +713,7 @@ acpi_hw_low_level_read ( u32 *value, struct acpi_generic_address *reg) { - struct acpi_pci_id pci_id; - u16 pci_register; + u64 address; acpi_status status; @@ -714,41 +725,34 @@ acpi_hw_low_level_read ( * a non-zero address within. However, don't return an error * because the PM1A/B code must not fail if B isn't present. */ - if ((!reg) || - (!reg->address)) { + if (!reg) { + return (AE_OK); + } + + /* Get a local copy of the address. Handles possible alignment issues */ + + ACPI_MOVE_64_TO_64 (&address, ®->address); + if (!address) { return (AE_OK); } *value = 0; /* - * Three address spaces supported: - * Memory, IO, or PCI_Config. + * Two address spaces supported: Memory or IO. + * PCI_Config is not supported here because the GAS struct is insufficient */ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: status = acpi_os_read_memory ( - (acpi_physical_address) reg->address, + (acpi_physical_address) address, value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_os_read_port ((acpi_io_address) reg->address, - value, width); - break; - - - case ACPI_ADR_SPACE_PCI_CONFIG: - - pci_id.segment = 0; - pci_id.bus = 0; - pci_id.device = ACPI_PCI_DEVICE (reg->address); - pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - - status = acpi_os_read_pci_configuration (&pci_id, pci_register, + status = acpi_os_read_port ((acpi_io_address) address, value, width); break; @@ -761,7 +765,7 @@ acpi_hw_low_level_read ( ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", *value, width, - ACPI_FORMAT_UINT64 (reg->address), + ACPI_FORMAT_UINT64 (address), acpi_ut_get_region_name (reg->address_space_id))); return (status); @@ -774,11 +778,11 @@ acpi_hw_low_level_read ( * * PARAMETERS: Width - 8, 16, or 32 * Value - To be written - * Register - GAS register structure + * Reg - GAS register structure * * RETURN: Status * - * DESCRIPTION: Write to either memory, IO, or PCI config space. + * DESCRIPTION: Write to either memory or IO space. * ******************************************************************************/ @@ -788,8 +792,7 @@ acpi_hw_low_level_write ( u32 value, struct acpi_generic_address *reg) { - struct acpi_pci_id pci_id; - u16 pci_register; + u64 address; acpi_status status; @@ -801,44 +804,37 @@ acpi_hw_low_level_write ( * a non-zero address within. However, don't return an error * because the PM1A/B code must not fail if B isn't present. */ - if ((!reg) || - (!reg->address)) { + if (!reg) { + return (AE_OK); + } + + /* Get a local copy of the address. Handles possible alignment issues */ + + ACPI_MOVE_64_TO_64 (&address, ®->address); + if (!address) { return (AE_OK); } /* - * Three address spaces supported: - * Memory, IO, or PCI_Config. + * Two address spaces supported: Memory or IO. + * PCI_Config is not supported here because the GAS struct is insufficient */ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: status = acpi_os_write_memory ( - (acpi_physical_address) reg->address, + (acpi_physical_address) address, value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_os_write_port ((acpi_io_address) reg->address, + status = acpi_os_write_port ((acpi_io_address) address, value, width); break; - case ACPI_ADR_SPACE_PCI_CONFIG: - - pci_id.segment = 0; - pci_id.bus = 0; - pci_id.device = ACPI_PCI_DEVICE (reg->address); - pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - - status = acpi_os_write_pci_configuration (&pci_id, pci_register, - (acpi_integer) value, width); - break; - - default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); @@ -847,7 +843,7 @@ acpi_hw_low_level_write ( ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", value, width, - ACPI_FORMAT_UINT64 (reg->address), + ACPI_FORMAT_UINT64 (address), acpi_ut_get_region_name (reg->address_space_id))); return (status); diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index f0c04149f..3467380d2 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -42,6 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include + #include #define _COMPONENT ACPI_HARDWARE @@ -110,7 +112,7 @@ acpi_set_firmware_waking_vector ( * DESCRIPTION: Access function for firmware_waking_vector field in FACS * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_firmware_waking_vector ( acpi_physical_address *physical_address) @@ -136,6 +138,7 @@ acpi_get_firmware_waking_vector ( return_ACPI_STATUS (AE_OK); } +#endif /****************************************************************************** @@ -265,19 +268,21 @@ acpi_enter_sleep_state ( sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A); sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE); - if (sleep_state != ACPI_STATE_S5) { - /* Clear wake status */ + /* Clear wake status */ - status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } - status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } + /* Clear all fixed and general purpose status bits */ + status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + if (sleep_state != ACPI_STATE_S5) { /* Disable BM arbitration */ status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); @@ -287,10 +292,16 @@ acpi_enter_sleep_state ( } /* - * 1) Disable all runtime GPEs + * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ - status = acpi_hw_prepare_gpes_for_sleep (); + status = acpi_hw_disable_all_gpes (ACPI_ISR); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -383,6 +394,7 @@ acpi_enter_sleep_state ( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_enter_sleep_state); /****************************************************************************** @@ -420,10 +432,16 @@ acpi_enter_sleep_state_s4bios ( } /* - * 1) Disable all runtime GPEs + * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ - status = acpi_hw_prepare_gpes_for_sleep (); + status = acpi_hw_disable_all_gpes (ACPI_ISR); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -442,6 +460,7 @@ acpi_enter_sleep_state_s4bios ( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios); /****************************************************************************** @@ -453,6 +472,7 @@ acpi_enter_sleep_state_s4bios ( * RETURN: Status * * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. * ******************************************************************************/ @@ -540,19 +560,25 @@ acpi_leave_sleep_state ( /* * Restore the GPEs: - * 1) Disable all wakeup GPEs + * 1) Disable/Clear all GPEs * 2) Enable all runtime GPEs */ - status = acpi_hw_restore_gpes_on_wake (); + status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + acpi_gbl_system_awake_and_running = TRUE; + + status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Enable power button */ - acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id, + (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id, 1, ACPI_MTX_DO_NOT_LOCK); - acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id, + (void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id, 1, ACPI_MTX_DO_NOT_LOCK); /* Enable BM arbitration */ diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index 8878aff9d..458120e4a 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -42,6 +42,8 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include + #include #define _COMPONENT ACPI_HARDWARE @@ -52,11 +54,11 @@ * * FUNCTION: acpi_get_timer_resolution * - * PARAMETERS: none + * PARAMETERS: Resolution - Where the resolution is returned * - * RETURN: Number of bits of resolution in the PM Timer (24 or 32). + * RETURN: Status and timer resolution * - * DESCRIPTION: Obtains resolution of the ACPI PM Timer. + * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits). * ******************************************************************************/ @@ -86,11 +88,11 @@ acpi_get_timer_resolution ( * * FUNCTION: acpi_get_timer * - * PARAMETERS: none + * PARAMETERS: Ticks - Where the timer value is returned * - * RETURN: Current value of the ACPI PM Timer (in ticks). + * RETURN: Status and current ticks * - * DESCRIPTION: Obtains current value of ACPI PM Timer. + * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). * ******************************************************************************/ @@ -112,17 +114,18 @@ acpi_get_timer ( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_timer); /****************************************************************************** * * FUNCTION: acpi_get_timer_duration * - * PARAMETERS: start_ticks - * end_ticks - * time_elapsed + * PARAMETERS: start_ticks - Starting timestamp + * end_ticks - End timestamp + * time_elapsed - Where the elapsed time is returned * - * RETURN: time_elapsed + * RETURN: Status and time_elapsed * * DESCRIPTION: Computes the time elapsed (in microseconds) between two * PM Timer time stamps, taking into account the possibility of @@ -136,7 +139,7 @@ acpi_get_timer ( * Note that this function accommodates only a single timer * rollover. Thus for 24-bit timers, this function should only * be used for calculating durations less than ~4.6 seconds - * (~20 minutes for 32-bit timers) -- calculations below + * (~20 minutes for 32-bit timers) -- calculations below: * * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes @@ -149,10 +152,9 @@ acpi_get_timer_duration ( u32 end_ticks, u32 *time_elapsed) { - u32 delta_ticks = 0; - union uint64_overlay normalized_ticks; acpi_status status; - acpi_integer out_quotient; + u32 delta_ticks; + acpi_integer quotient; ACPI_FUNCTION_TRACE ("acpi_get_timer_duration"); @@ -164,8 +166,7 @@ acpi_get_timer_duration ( /* * Compute Tick Delta: - * ------------------- - * Handle (max one) timer rollovers on 24- versus 32-bit timers. + * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. */ if (start_ticks < end_ticks) { delta_ticks = end_ticks - start_ticks; @@ -182,26 +183,21 @@ acpi_get_timer_duration ( delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; } } - else { + else /* start_ticks == end_ticks */ { *time_elapsed = 0; return_ACPI_STATUS (AE_OK); } /* - * Compute Duration: - * ----------------- - * - * Requires a 64-bit divide: + * Compute Duration (Requires a 64-bit multiply and divide): * * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; */ - normalized_ticks.full = ((u64) delta_ticks) * 1000000; + status = acpi_ut_short_divide (((u64) delta_ticks) * 1000000, + PM_TIMER_FREQUENCY, "ient, NULL); - status = acpi_ut_short_divide (&normalized_ticks.full, PM_TIMER_FREQUENCY, - &out_quotient, NULL); - - *time_elapsed = (u32) out_quotient; + *time_elapsed = (u32) quotient; return_ACPI_STATUS (status); } - +EXPORT_SYMBOL(acpi_get_timer_duration); diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index ee9c5d13e..61ea70742 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -62,7 +62,7 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data) struct acpi_resource_io *io_res = &res->data.io; if (io_res->min_base_address != io_res->max_base_address) - return AE_OK; + return_VALUE(AE_OK); if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n", io_res->min_base_address, @@ -86,7 +86,7 @@ acpi_reserve_io_ranges (struct acpi_resource *res, void *data) if (requested_res) requested_res->flags &= ~IORESOURCE_BUSY; - return AE_OK; + return_VALUE(AE_OK); } static int acpi_motherboard_add (struct acpi_device *device) diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile index 9462af174..3f63d3640 100644 --- a/drivers/acpi/namespace/Makefile +++ b/drivers/acpi/namespace/Makefile @@ -2,9 +2,11 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := nsaccess.o nsdumpdv.o nsload.o nssearch.o nsxfeval.o \ +obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \ nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ nsparse.o +obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o + EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 23baf93bf..6cbe22f72 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -161,8 +161,10 @@ acpi_ns_root_initialize (void) #if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App) - /* i_aSL Compiler cheats by putting parameter count in the owner_iD */ - + /* + * i_aSL Compiler cheats by putting parameter count + * in the owner_iD + */ new_node->owner_id = obj_desc->method.param_count; #else /* Mark this as a very SPECIAL method */ @@ -193,7 +195,7 @@ acpi_ns_root_initialize (void) case ACPI_TYPE_MUTEX: obj_desc->mutex.node = new_node; - obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL + obj_desc->mutex.sync_level = (u8) ACPI_STRTOUL (val, NULL, 10); if (ACPI_STRCMP (init_val->name, "_GL_") == 0) { @@ -204,6 +206,7 @@ acpi_ns_root_initialize (void) status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, &obj_desc->mutex.semaphore); if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } @@ -219,6 +222,7 @@ acpi_ns_root_initialize (void) status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); if (ACPI_FAILURE (status)) { + acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } @@ -236,7 +240,8 @@ acpi_ns_root_initialize (void) /* Store pointer to value descriptor in the Node */ - status = acpi_ns_attach_object (new_node, obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc)); + status = acpi_ns_attach_object (new_node, obj_desc, + ACPI_GET_OBJECT_TYPE (obj_desc)); /* Remove local reference to the object */ @@ -462,7 +467,8 @@ acpi_ns_lookup ( type = this_node->type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Prefix-only Pathname (Zero name segments), Flags=%X\n", flags)); + "Prefix-only Pathname (Zero name segments), Flags=%X\n", + flags)); break; case AML_DUAL_NAME_PREFIX: @@ -554,7 +560,7 @@ acpi_ns_lookup ( /* Try to find the single (4 character) ACPI name */ status = acpi_ns_search_and_enter (simple_name, walk_state, current_node, - interpreter_mode, this_search_type, local_flags, &this_node); + interpreter_mode, this_search_type, local_flags, &this_node); if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { /* Name not found in ACPI namespace */ diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index c9dd49ff7..73640fe7b 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -267,7 +267,7 @@ acpi_ns_install_node ( else { #ifdef ACPI_ALPHABETIC_NAMESPACE /* - * Walk the list whilst searching for the the correct + * Walk the list whilst searching for the correct * alphabetic placement. */ previous_child_node = NULL; @@ -502,8 +502,8 @@ acpi_ns_delete_namespace_subtree ( * visit the node */ level++; - parent_node = child_node; - child_node = NULL; + parent_node = child_node; + child_node = NULL; } } else { @@ -650,8 +650,8 @@ acpi_ns_delete_namespace_by_owner ( * visit the node */ level++; - parent_node = child_node; - child_node = NULL; + parent_node = child_node; + child_node = NULL; } else if (child_node->owner_id == owner_id) { deletion_node = child_node; diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 8afa1dcf7..57279b297 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -198,7 +198,8 @@ acpi_ns_dump_one_object ( } if (!acpi_ut_valid_acpi_name (this_node->name.integer)) { - ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", this_node->name.integer)); + ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", + this_node->name.integer)); } /* @@ -226,9 +227,8 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_PROCESSOR: acpi_os_printf ("ID %X Len %.4X Addr %p\n", - obj_desc->processor.proc_id, - obj_desc->processor.length, - (char *) obj_desc->processor.address); + obj_desc->processor.proc_id, obj_desc->processor.length, + (char *) obj_desc->processor.address); break; @@ -241,16 +241,15 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_METHOD: acpi_os_printf ("Args %X Len %.4X Aml %p\n", - (u32) obj_desc->method.param_count, - obj_desc->method.aml_length, - obj_desc->method.aml_start); + (u32) obj_desc->method.param_count, + obj_desc->method.aml_length, obj_desc->method.aml_start); break; case ACPI_TYPE_INTEGER: acpi_os_printf ("= %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (obj_desc->integer.value)); + ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; @@ -258,7 +257,7 @@ acpi_ns_dump_one_object ( if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { acpi_os_printf ("Elements %.2X\n", - obj_desc->package.count); + obj_desc->package.count); } else { acpi_os_printf ("[Length not yet evaluated]\n"); @@ -298,11 +297,12 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_REGION: - acpi_os_printf ("[%s]", acpi_ut_get_region_name (obj_desc->region.space_id)); + acpi_os_printf ("[%s]", + acpi_ut_get_region_name (obj_desc->region.space_id)); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n", - ACPI_FORMAT_UINT64 (obj_desc->region.address), - obj_desc->region.length); + ACPI_FORMAT_UINT64 (obj_desc->region.address), + obj_desc->region.length); } else { acpi_os_printf (" [Address/Length not yet evaluated]\n"); @@ -313,7 +313,7 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf ("[%s]\n", - acpi_ps_get_opcode_name (obj_desc->reference.opcode)); + acpi_ps_get_opcode_name (obj_desc->reference.opcode)); break; @@ -322,7 +322,7 @@ acpi_ns_dump_one_object ( if (obj_desc->buffer_field.buffer_obj && obj_desc->buffer_field.buffer_obj->buffer.node) { acpi_os_printf ("Buf [%4.4s]", - acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node)); + acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node)); } break; @@ -330,30 +330,31 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf ("Rgn [%4.4s]", - acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node)); + acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]", - acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node), - acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node)); + acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node), + acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node)); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]", - acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node), - acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node)); + acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node), + acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node)); break; case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: - acpi_os_printf ("Target %4.4s (%p)\n", acpi_ut_get_node_name (obj_desc), obj_desc); + acpi_os_printf ("Target %4.4s (%p)\n", + acpi_ut_get_node_name (obj_desc), obj_desc); break; default: @@ -371,10 +372,10 @@ acpi_ns_dump_one_object ( case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n", - (obj_desc->common_field.base_byte_offset * 8) - + obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.bit_length, - obj_desc->common_field.access_byte_width); + (obj_desc->common_field.base_byte_offset * 8) + + obj_desc->common_field.start_field_bit_offset, + obj_desc->common_field.bit_length, + obj_desc->common_field.access_byte_width); break; default: @@ -471,12 +472,13 @@ acpi_ns_dump_one_object ( obj_type = ACPI_GET_OBJECT_TYPE (obj_desc); if (obj_type > ACPI_TYPE_LOCAL_MAX) { - acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n", obj_type); + acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n", + obj_type); bytes_to_dump = 32; } else { acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n", - acpi_ut_get_type_name (obj_type), obj_type); + acpi_ut_get_type_name (obj_type), obj_type); bytes_to_dump = sizeof (union acpi_operand_object); } break; @@ -484,8 +486,9 @@ acpi_ns_dump_one_object ( default: - acpi_os_printf ("(String or Buffer ptr - not an object descriptor) [%s]\n", - acpi_ut_get_descriptor_name (obj_desc)); + acpi_os_printf ( + "(String or Buffer ptr - not an object descriptor) [%s]\n", + acpi_ut_get_descriptor_name (obj_desc)); bytes_to_dump = 16; break; } @@ -547,12 +550,14 @@ cleanup: } +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_ns_dump_objects * * PARAMETERS: Type - Object type to be dumped - * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX + * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX * for an effectively unlimited depth. * owner_id - Dump only objects owned by this ID. Use * ACPI_UINT32_MAX to match all owners. @@ -632,6 +637,8 @@ acpi_ns_dump_tables ( return_VOID; } +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index 7196a0112..ec90210a5 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -91,10 +91,10 @@ acpi_ns_dump_one_device ( ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); } - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.value, - ACPI_FORMAT_UINT64 (info->address), - info->current_status)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, + " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", + info->hardware_id.value, ACPI_FORMAT_UINT64 (info->address), + info->current_status)); ACPI_MEM_FREE (info); } @@ -133,7 +133,8 @@ acpi_ns_dump_root_devices (void) return; } - ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, + "Display of all devices in the namespace:\n")); status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index b054b365c..d2e1a2846 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -57,14 +57,9 @@ * * FUNCTION: acpi_ns_evaluate_relative * - * PARAMETERS: Handle - The relative containing object - * Pathname - Name of method to execute, If NULL, the + * PARAMETERS: Pathname - Name of method to execute, If NULL, the * handle is the object to execute - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. + * Info - Method info block * * RETURN: Status * @@ -77,13 +72,10 @@ acpi_status acpi_ns_evaluate_relative ( - struct acpi_namespace_node *handle, char *pathname, - union acpi_operand_object **params, - union acpi_operand_object **return_object) + struct acpi_parameter_info *info) { acpi_status status; - struct acpi_namespace_node *prefix_node; struct acpi_namespace_node *node = NULL; union acpi_generic_state *scope_info; char *internal_path = NULL; @@ -95,7 +87,7 @@ acpi_ns_evaluate_relative ( /* * Must have a valid object handle */ - if (!handle) { + if (!info || !info->node) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -118,8 +110,8 @@ acpi_ns_evaluate_relative ( goto cleanup; } - prefix_node = acpi_ns_map_handle_to_node (handle); - if (!prefix_node) { + info->node = acpi_ns_map_handle_to_node (info->node); + if (!info->node) { (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); status = AE_BAD_PARAMETER; goto cleanup; @@ -127,7 +119,7 @@ acpi_ns_evaluate_relative ( /* Lookup the name in the namespace */ - scope_info->scope.node = prefix_node; + scope_info->scope.node = info->node; status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, &node); @@ -141,13 +133,13 @@ acpi_ns_evaluate_relative ( } /* - * Now that we have a handle to the object, we can attempt - * to evaluate it. + * Now that we have a handle to the object, we can attempt to evaluate it. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", pathname, node, acpi_ns_get_attached_object (node))); - status = acpi_ns_evaluate_by_handle (node, params, return_object); + info->node = node; + status = acpi_ns_evaluate_by_handle (info); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n", pathname)); @@ -166,9 +158,10 @@ cleanup1: * FUNCTION: acpi_ns_evaluate_by_name * * PARAMETERS: Pathname - Fully qualified pathname to the object - * return_object - Where to put method's return value (if + * Info - Contains: + * return_object - Where to put method's return value (if * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, + * Params - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. * @@ -184,11 +177,9 @@ cleanup1: acpi_status acpi_ns_evaluate_by_name ( char *pathname, - union acpi_operand_object **params, - union acpi_operand_object **return_object) + struct acpi_parameter_info *info) { acpi_status status; - struct acpi_namespace_node *node = NULL; char *internal_path = NULL; @@ -211,24 +202,24 @@ acpi_ns_evaluate_by_name ( status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &node); + &info->node); (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object at [%s] was not found, status=%.4X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Object at [%s] was not found, status=%.4X\n", pathname, status)); goto cleanup; } /* - * Now that we have a handle to the object, we can attempt - * to evaluate it. + * Now that we have a handle to the object, we can attempt to evaluate it. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, node, acpi_ns_get_attached_object (node))); + pathname, info->node, acpi_ns_get_attached_object (info->node))); - status = acpi_ns_evaluate_by_handle (node, params, return_object); + status = acpi_ns_evaluate_by_handle (info); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n", pathname)); @@ -254,6 +245,7 @@ cleanup: * Params - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. + * param_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. * @@ -267,13 +259,9 @@ cleanup: acpi_status acpi_ns_evaluate_by_handle ( - struct acpi_namespace_node *handle, - union acpi_operand_object **params, - union acpi_operand_object **return_object) + struct acpi_parameter_info *info) { - struct acpi_namespace_node *node; acpi_status status; - union acpi_operand_object *local_return_object; ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle"); @@ -287,15 +275,13 @@ acpi_ns_evaluate_by_handle ( /* Parameter Validation */ - if (!handle) { + if (!info) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - if (return_object) { - /* Initialize the return value to an invalid object */ + /* Initialize the return value to an invalid object */ - *return_object = NULL; - } + info->return_object = NULL; /* Get the prefix handle and Node */ @@ -304,72 +290,52 @@ acpi_ns_evaluate_by_handle ( return_ACPI_STATUS (status); } - node = acpi_ns_map_handle_to_node (handle); - if (!node) { + info->node = acpi_ns_map_handle_to_node (info->node); + if (!info->node) { (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* - * For a method alias, we must grab the actual method node - * so that proper scoping context will be established - * before execution. + * For a method alias, we must grab the actual method node so that proper + * scoping context will be established before execution. */ - if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object); + if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object); } /* * Two major cases here: * 1) The object is an actual control method -- execute it. - * 2) The object is not a method -- just return it's current - * value + * 2) The object is not a method -- just return it's current value * - * In both cases, the namespace is unlocked by the - * acpi_ns* procedure + * In both cases, the namespace is unlocked by the acpi_ns* procedure */ - if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) { + if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) { /* * Case 1) We have an actual control method to execute */ - status = acpi_ns_execute_control_method (node, params, - &local_return_object); + status = acpi_ns_execute_control_method (info); } else { /* - * Case 2) Object is NOT a method, just return its - * current value + * Case 2) Object is NOT a method, just return its current value */ - status = acpi_ns_get_object_value (node, &local_return_object); + status = acpi_ns_get_object_value (info); } /* - * Check if there is a return value on the stack that must - * be dealt with + * Check if there is a return value on the stack that must be dealt with */ if (status == AE_CTRL_RETURN_VALUE) { - /* - * If the Method returned a value and the caller - * provided a place to store a returned value, Copy - * the returned value to the object descriptor provided - * by the caller. - */ - if (return_object) { - /* - * Valid return object, copy the pointer to - * the returned object - */ - *return_object = local_return_object; - } - /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ status = AE_OK; } /* - * Namespace was unlocked by the handling acpi_ns* function, - * so we just return + * Namespace was unlocked by the handling acpi_ns* function, so we + * just return */ return_ACPI_STATUS (status); } @@ -379,12 +345,7 @@ acpi_ns_evaluate_by_handle ( * * FUNCTION: acpi_ns_execute_control_method * - * PARAMETERS: method_node - The method to execute - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_obj_desc - List of result objects to be returned - * from the method. + * PARAMETERS: Info - Method info block (w/params) * * RETURN: Status * @@ -396,9 +357,7 @@ acpi_ns_evaluate_by_handle ( acpi_status acpi_ns_execute_control_method ( - struct acpi_namespace_node *method_node, - union acpi_operand_object **params, - union acpi_operand_object **return_obj_desc) + struct acpi_parameter_info *info) { acpi_status status; union acpi_operand_object *obj_desc; @@ -409,7 +368,7 @@ acpi_ns_execute_control_method ( /* Verify that there is a method associated with this object */ - obj_desc = acpi_ns_get_attached_object (method_node); + obj_desc = acpi_ns_get_attached_object (info->node); if (!obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); @@ -417,7 +376,7 @@ acpi_ns_execute_control_method ( return_ACPI_STATUS (AE_NULL_OBJECT); } - ACPI_DUMP_PATHNAME (method_node, "Execute Method:", + ACPI_DUMP_PATHNAME (info->node, "Execute Method:", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", @@ -444,7 +403,7 @@ acpi_ns_execute_control_method ( return_ACPI_STATUS (status); } - status = acpi_psx_execute (method_node, params, return_obj_desc); + status = acpi_psx_execute (info); acpi_ex_exit_interpreter (); return_ACPI_STATUS (status); @@ -455,8 +414,7 @@ acpi_ns_execute_control_method ( * * FUNCTION: acpi_ns_get_object_value * - * PARAMETERS: Node - The object - * return_obj_desc - Where the objects value is returned + * PARAMETERS: Info - Method info block (w/params) * * RETURN: Status * @@ -468,39 +426,35 @@ acpi_ns_execute_control_method ( acpi_status acpi_ns_get_object_value ( - struct acpi_namespace_node *node, - union acpi_operand_object **return_obj_desc) + struct acpi_parameter_info *info) { acpi_status status = AE_OK; - struct acpi_namespace_node *resolved_node = node; + struct acpi_namespace_node *resolved_node = info->node; ACPI_FUNCTION_TRACE ("ns_get_object_value"); /* - * Objects require additional resolution steps (e.g., the - * Node may be a field that must be read, etc.) -- we can't just grab - * the object out of the node. + * Objects require additional resolution steps (e.g., the Node may be a + * field that must be read, etc.) -- we can't just grab the object out of + * the node. */ /* - * Use resolve_node_to_value() to get the associated value. This call - * always deletes obj_desc (allocated above). + * Use resolve_node_to_value() to get the associated value. This call always + * deletes obj_desc (allocated above). * - * NOTE: we can get away with passing in NULL for a walk state - * because obj_desc is guaranteed to not be a reference to either - * a method local or a method argument (because this interface can only be - * called from the acpi_evaluate external interface, never called from - * a running control method.) + * NOTE: we can get away with passing in NULL for a walk state because + * obj_desc is guaranteed to not be a reference to either a method local or + * a method argument (because this interface can only be called from the + * acpi_evaluate external interface, never called from a running method.) * - * Even though we do not directly invoke the interpreter - * for this, we must enter it because we could access an opregion. - * The opregion access code assumes that the interpreter - * is locked. + * Even though we do not directly invoke the interpreter for this, we must + * enter it because we could access an opregion. The opregion access code + * assumes that the interpreter is locked. * - * We must release the namespace lock before entering the - * intepreter. + * We must release the namespace lock before entering the intepreter. */ status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { @@ -511,16 +465,18 @@ acpi_ns_get_object_value ( if (ACPI_SUCCESS (status)) { status = acpi_ex_resolve_node_to_value (&resolved_node, NULL); /* - * If acpi_ex_resolve_node_to_value() succeeded, the return value was - * placed in resolved_node. + * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed + * in resolved_node. */ acpi_ex_exit_interpreter (); if (ACPI_SUCCESS (status)) { status = AE_CTRL_RETURN_VALUE; - *return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node); + info->return_object = ACPI_CAST_PTR + (union acpi_operand_object, resolved_node); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n", - *return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc))); + info->return_object, + acpi_ut_get_object_type_name (info->return_object))); } } diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index c8e9317ab..c6518f894 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -77,7 +77,8 @@ acpi_ns_initialize_objects ( ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Completing Region/Field/Buffer/Package initialization:")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Completing Region/Field/Buffer/Package initialization:")); /* Set all init info to zero */ @@ -142,14 +143,15 @@ acpi_ns_initialize_devices ( info.num_STA = 0; info.num_INI = 0; - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Executing all Device _STA and_INI methods:")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Executing all Device _STA and_INI methods:")); status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* Walk namespace for all objects of type Device or Processor */ + /* Walk namespace for all objects */ status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL); @@ -257,8 +259,8 @@ acpi_ns_init_one_object ( } /* - * Each of these types can contain executable AML code within - * the declaration. + * Each of these types can contain executable AML code within the + * declaration. */ switch (type) { case ACPI_TYPE_REGION: @@ -267,21 +269,18 @@ acpi_ns_init_one_object ( status = acpi_ds_get_region_arguments (obj_desc); break; - case ACPI_TYPE_BUFFER_FIELD: info->field_init++; status = acpi_ds_get_buffer_field_arguments (obj_desc); break; - case ACPI_TYPE_BUFFER: info->buffer_init++; status = acpi_ds_get_buffer_arguments (obj_desc); break; - case ACPI_TYPE_PACKAGE: info->package_init++; @@ -301,15 +300,17 @@ acpi_ns_init_one_object ( acpi_format_exception (status))); } - /* Print a dot for each object unless we are going to print the entire pathname */ - + /* + * Print a dot for each object unless we are going to print the entire + * pathname + */ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); } /* - * We ignore errors from above, and always return OK, since - * we don't want to abort the walk on any single error. + * We ignore errors from above, and always return OK, since we don't want + * to abort the walk on any single error. */ acpi_ex_exit_interpreter (); return (AE_OK); @@ -337,29 +338,34 @@ acpi_ns_init_one_device ( void *context, void **return_value) { - acpi_status status; - struct acpi_namespace_node *node; - u32 flags; struct acpi_device_walk_info *info = (struct acpi_device_walk_info *) context; + struct acpi_parameter_info pinfo; + u32 flags; + acpi_status status; ACPI_FUNCTION_TRACE ("ns_init_one_device"); - node = acpi_ns_map_handle_to_node (obj_handle); - if (!node) { + pinfo.parameters = NULL; + pinfo.parameter_type = ACPI_PARAM_ARGS; + + pinfo.node = acpi_ns_map_handle_to_node (obj_handle); + if (!pinfo.node) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* - * We will run _STA/_INI on Devices and Processors only + * We will run _STA/_INI on Devices, Processors and thermal_zones only */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR)) { + if ((pinfo.node->type != ACPI_TYPE_DEVICE) && + (pinfo.node->type != ACPI_TYPE_PROCESSOR) && + (pinfo.node->type != ACPI_TYPE_THERMAL)) { return_ACPI_STATUS (AE_OK); } - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && (!(acpi_dbg_level & ACPI_LV_INFO))) { + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && + (!(acpi_dbg_level & ACPI_LV_INFO))) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); } @@ -368,17 +374,17 @@ acpi_ns_init_one_device ( /* * Run _STA to determine if we can run _INI on the device. */ - ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA")); - status = acpi_ut_execute_STA (node, &flags); + ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA")); + status = acpi_ut_execute_STA (pinfo.node, &flags); if (ACPI_FAILURE (status)) { - if (node->type == ACPI_TYPE_DEVICE) { + if (pinfo.node->type == ACPI_TYPE_DEVICE) { /* Ignore error and move on to next device */ return_ACPI_STATUS (AE_OK); } - /* _STA is not required for Processor objects */ + /* _STA is not required for Processor or thermal_zone objects */ } else { info->num_STA++; @@ -393,22 +399,22 @@ acpi_ns_init_one_device ( /* * The device is present. Run _INI. */ - ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, obj_handle, "_INI")); - status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL); + ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI")); + status = acpi_ns_evaluate_relative ("_INI", &pinfo); if (ACPI_FAILURE (status)) { /* No _INI (AE_NOT_FOUND) means device requires no initialization */ if (status != AE_NOT_FOUND) { /* Ignore error and move on to next device */ - #ifdef ACPI_DEBUG_OUTPUT - char *scope_name = acpi_ns_get_external_pathname (obj_handle); +#ifdef ACPI_DEBUG_OUTPUT + char *scope_name = acpi_ns_get_external_pathname (pinfo.node); ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n", scope_name, acpi_format_exception (status))); ACPI_MEM_FREE (scope_name); - #endif +#endif } status = AE_OK; @@ -422,9 +428,8 @@ acpi_ns_init_one_device ( if (acpi_gbl_init_handler) { /* External initialization handler is present, call it */ - status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI); + status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI); } - return_ACPI_STATUS (status); } diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 314ec6659..fe3319c16 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -92,12 +92,14 @@ acpi_ns_load_table ( return_ACPI_STATUS (AE_BAD_PARAMETER); } - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n", table_desc->aml_start)); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n", + table_desc->aml_start)); /* Ignore table if there is no AML contained within */ if (!table_desc->aml_length) { - ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n", table_desc->pointer->signature)); + ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n", + table_desc->pointer->signature)); return_ACPI_STATUS (AE_OK); } @@ -110,7 +112,8 @@ acpi_ns_load_table ( * to another control method, we can't continue parsing * because we don't know how many arguments to parse next! */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Loading table into namespace ****\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "**** Loading table into namespace ****\n")); status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { @@ -196,7 +199,6 @@ acpi_ns_load_table_by_type ( if (ACPI_SUCCESS (status)) { table_desc->loaded_into_namespace = TRUE; } - break; @@ -252,7 +254,6 @@ acpi_ns_load_table_by_type ( table_desc = table_desc->next; } - break; @@ -320,6 +321,8 @@ acpi_ns_load_namespace ( } +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_ns_delete_subtree @@ -451,5 +454,7 @@ acpi_ns_unload_namespace ( return_ACPI_STATUS (status); } +#endif /* ACPI_FUTURE_USAGE */ + #endif diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index e0b9663ae..4316ea668 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -202,7 +202,11 @@ acpi_ns_get_pathname_length ( next_node = acpi_ns_get_parent_node (next_node); } - return (size + 1); + if (!size) { + size = 1; /* Root node case */ + } + + return (size + 1); /* +1 for null string terminator */ } @@ -253,7 +257,8 @@ acpi_ns_handle_to_pathname ( acpi_ns_build_external_path (node, required_size, buffer->pointer); - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n", (char *) buffer->pointer, (u32) required_size)); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n", + (char *) buffer->pointer, (u32) required_size)); return_ACPI_STATUS (AE_OK); } diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index f550ce5c1..530982a38 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -94,8 +94,9 @@ acpi_ns_one_complete_parse ( return_ACPI_STATUS (AE_NO_MEMORY); } - status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start, - table_desc->aml_length, NULL, NULL, pass_number); + status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, + table_desc->aml_start, table_desc->aml_length, + NULL, pass_number); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (walk_state); return_ACPI_STATUS (status); diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index 7870a43eb..0edc5e204 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -96,8 +96,10 @@ acpi_ns_search_node ( scope_name = acpi_ns_get_external_pathname (node); if (scope_name) { - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, node, (char *) &target_name, acpi_ut_get_type_name (type))); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Searching %s (%p) For [%4.4s] (%s)\n", + scope_name, node, (char *) &target_name, + acpi_ut_get_type_name (type))); ACPI_MEM_FREE (scope_name); } @@ -164,7 +166,7 @@ acpi_ns_search_node ( * PARAMETERS: *target_name - Ascii ACPI name to search for * *Node - Starting node where search will begin * Type - Object type to match - * **return_node - Where the matched Named Obj is returned + * **return_node - Where the matched Node is returned * * RETURN: Status * @@ -199,13 +201,13 @@ acpi_ns_search_parent_tree ( parent_node = acpi_ns_get_parent_node (node); /* - * If there is no parent (i.e., we are at the root) or - * type is "local", we won't be searching the parent tree. + * If there is no parent (i.e., we are at the root) or type is "local", + * we won't be searching the parent tree. */ if (!parent_node) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n", (char *) &target_name)); - return_ACPI_STATUS (AE_NOT_FOUND); + return_ACPI_STATUS (AE_NOT_FOUND); } if (acpi_ns_local (type)) { @@ -217,11 +219,12 @@ acpi_ns_search_parent_tree ( /* Search the parent tree */ - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching parent for %4.4s\n", (char *) &target_name)); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Searching parent [%4.4s] for [%4.4s]\n", + acpi_ut_get_node_name (parent_node), (char *) &target_name)); /* - * Search parents until found the target or we have backed up to - * the root + * Search parents until target is found or we have backed up to the root */ while (parent_node) { /* @@ -230,7 +233,7 @@ acpi_ns_search_parent_tree ( * the actual name we are searching for. Typechecking comes later. */ status = acpi_ns_search_node (target_name, parent_node, - ACPI_TYPE_ANY, return_node); + ACPI_TYPE_ANY, return_node); if (ACPI_SUCCESS (status)) { return_ACPI_STATUS (status); } @@ -293,7 +296,8 @@ acpi_ns_search_and_enter ( /* Parameter validation */ if (!node || !target_name || !return_node) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null param: Node %p Name %X return_node %p\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Null param: Node %p Name %X return_node %p\n", node, target_name, return_node)); ACPI_REPORT_ERROR (("ns_search_and_enter: Null parameter\n")); @@ -330,22 +334,20 @@ acpi_ns_search_and_enter ( } /* - * The name was not found. If we are NOT performing the - * first pass (name entry) of loading the namespace, search - * the parent tree (all the way to the root if necessary.) - * We don't want to perform the parent search when the - * namespace is actually being loaded. We want to perform - * the search when namespace references are being resolved - * (load pass 2) and during the execution phase. + * The name was not found. If we are NOT performing the first pass + * (name entry) of loading the namespace, search the parent tree (all the + * way to the root if necessary.) We don't want to perform the parent + * search when the namespace is actually being loaded. We want to perform + * the search when namespace references are being resolved (load pass 2) + * and during the execution phase. */ if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) && (flags & ACPI_NS_SEARCH_PARENT)) { /* - * Not found at this level - search parent tree according - * to ACPI specification + * Not found at this level - search parent tree according to the + * ACPI specification */ - status = acpi_ns_search_parent_tree (target_name, node, - type, return_node); + status = acpi_ns_search_parent_tree (target_name, node, type, return_node); if (ACPI_SUCCESS (status)) { return_ACPI_STATUS (status); } @@ -355,7 +357,8 @@ acpi_ns_search_and_enter ( * In execute mode, just search, never add names. Exit now. */ if (interpreter_mode == ACPI_IMODE_EXECUTE) { - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s Not found in %p [Not adding]\n", + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%4.4s Not found in %p [Not adding]\n", (char *) &target_name, node)); return_ACPI_STATUS (AE_NOT_FOUND); diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index bf49ce296..47509cc87 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -85,12 +85,14 @@ acpi_ns_report_error ( if (lookup_status == AE_BAD_CHARACTER) { /* There is a non-ascii character in the name */ - acpi_os_printf ("[0x%4.4X] (NON-ASCII)\n", *(ACPI_CAST_PTR (u32, internal_name))); + acpi_os_printf ("[0x%4.4X] (NON-ASCII)\n", + *(ACPI_CAST_PTR (u32, internal_name))); } else { /* Convert path to external format */ - status = acpi_ns_externalize_name (ACPI_UINT32_MAX, internal_name, NULL, &name); + status = acpi_ns_externalize_name (ACPI_UINT32_MAX, + internal_name, NULL, &name); /* Print target name */ @@ -141,7 +143,8 @@ acpi_ns_report_method_error ( if (path) { - status = acpi_ns_get_node_by_path (path, prefix_node, ACPI_NS_NO_UPSEARCH, &node); + status = acpi_ns_get_node_by_path (path, prefix_node, + ACPI_NS_NO_UPSEARCH, &node); if (ACPI_FAILURE (status)) { acpi_os_printf ("report_method_error: Could not get node\n"); return; @@ -180,7 +183,7 @@ acpi_ns_print_node_pathname ( return; } - /* Convert handle to a full pathname and print it (with supplied message) */ + /* Convert handle to full pathname and print it (with supplied message) */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; @@ -324,13 +327,11 @@ acpi_ns_get_internal_name_length ( info->fully_qualified = FALSE; /* - * For the internal name, the required length is 4 bytes - * per segment, plus 1 each for root_prefix, multi_name_prefix_op, - * segment count, trailing null (which is not really needed, - * but no there's harm in putting it there) + * For the internal name, the required length is 4 bytes per segment, plus + * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null + * (which is not really needed, but no there's harm in putting it there) * - * strlen() + 1 covers the first name_seg, which has no - * path separator + * strlen() + 1 covers the first name_seg, which has no path separator */ if (acpi_ns_valid_root_prefix (next_external_char[0])) { info->fully_qualified = TRUE; @@ -347,10 +348,9 @@ acpi_ns_get_internal_name_length ( } /* - * Determine the number of ACPI name "segments" by counting - * the number of path separators within the string. Start - * with one segment since the segment count is (# separators) - * + 1, and zero separators is ok. + * Determine the number of ACPI name "segments" by counting the number of + * path separators within the string. Start with one segment since the + * segment count is [(# separators) + 1], and zero separators is ok. */ if (*next_external_char) { info->num_segments = 1; @@ -625,7 +625,8 @@ acpi_ns_externalize_name ( /* 4-byte names */ names_index = prefix_length + 2; - num_segments = (acpi_native_uint) (u8) internal_name[(acpi_native_uint) (prefix_length + 1)]; + num_segments = (acpi_native_uint) (u8) + internal_name[(acpi_native_uint) (prefix_length + 1)]; break; case AML_DUAL_NAME_PREFIX: @@ -672,7 +673,7 @@ acpi_ns_externalize_name ( } /* - * Build converted_name... + * Build converted_name */ *converted_name = ACPI_MEM_CALLOCATE (required_length); if (!(*converted_name)) { @@ -756,7 +757,7 @@ acpi_ns_map_handle_to_node ( * * PARAMETERS: Node - Node to be converted to a Handle * - * RETURN: An USER acpi_handle + * RETURN: A user handle * * DESCRIPTION: Convert a real Node to a namespace handle * @@ -960,7 +961,7 @@ cleanup: * (which "should not happen"). * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_name acpi_ns_find_parent_name ( struct acpi_namespace_node *child_node) @@ -976,7 +977,8 @@ acpi_ns_find_parent_name ( parent_node = acpi_ns_get_parent_node (child_node); if (parent_node) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Parent of %p [%4.4s] is %p [%4.4s]\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Parent of %p [%4.4s] is %p [%4.4s]\n", child_node, acpi_ut_get_node_name (child_node), parent_node, acpi_ut_get_node_name (parent_node))); @@ -985,12 +987,14 @@ acpi_ns_find_parent_name ( } } - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "unable to find parent of %p (%4.4s)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Unable to find parent of %p (%4.4s)\n", child_node, acpi_ut_get_node_name (child_node))); } return_VALUE (ACPI_UNKNOWN_NAME); } +#endif /******************************************************************************* @@ -1018,11 +1022,9 @@ acpi_ns_get_parent_node ( } /* - * Walk to the end of this peer list. - * The last entry is marked with a flag and the peer - * pointer is really a pointer back to the parent. - * This saves putting a parent back pointer in each and - * every named object! + * Walk to the end of this peer list. The last entry is marked with a flag + * and the peer pointer is really a pointer back to the parent. This saves + * putting a parent back pointer in each and every named object! */ while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { node = node->peer; @@ -1039,8 +1041,8 @@ acpi_ns_get_parent_node ( * * PARAMETERS: Node - Current table entry * - * RETURN: Next valid Node in the linked node list. NULL if no more valid - * nodess + * RETURN: Next valid Node in the linked node list. NULL if no more valid + * nodes. * * DESCRIPTION: Find the next valid node within a name table. * Useful for implementing NULL-end-of-list loops. diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 5482e74de..3831228a2 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -264,8 +264,8 @@ acpi_ns_walk_namespace ( * node, visit the onde */ level++; - parent_node = child_node; - child_node = NULL; + parent_node = child_node; + child_node = NULL; } } } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 312835443..ce55bdfcb 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -42,6 +42,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -72,7 +73,7 @@ * be valid (non-null) * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_evaluate_object_typed ( acpi_handle handle, @@ -143,6 +144,7 @@ acpi_evaluate_object_typed ( return_buffer->length = 0; return_ACPI_STATUS (AE_TYPE); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -174,8 +176,7 @@ acpi_evaluate_object ( { acpi_status status; acpi_status status2; - union acpi_operand_object **internal_params = NULL; - union acpi_operand_object *internal_return_obj = NULL; + struct acpi_parameter_info info; acpi_size buffer_space_needed; u32 i; @@ -183,6 +184,11 @@ acpi_evaluate_object ( ACPI_FUNCTION_TRACE ("acpi_evaluate_object"); + info.node = handle; + info.parameters = NULL; + info.return_object = NULL; + info.parameter_type = ACPI_PARAM_ARGS; + /* * If there are parameters to be passed to the object * (which must be a control method), the external objects @@ -193,9 +199,10 @@ acpi_evaluate_object ( * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - internal_params = ACPI_MEM_CALLOCATE (((acpi_size) external_params->count + 1) * - sizeof (void *)); - if (!internal_params) { + info.parameters = ACPI_MEM_CALLOCATE ( + ((acpi_size) external_params->count + 1) * + sizeof (void *)); + if (!info.parameters) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -205,15 +212,16 @@ acpi_evaluate_object ( */ for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i], - &internal_params[i]); + &info.parameters[i]); if (ACPI_FAILURE (status)) { - acpi_ut_delete_internal_object_list (internal_params); + acpi_ut_delete_internal_object_list (info.parameters); return_ACPI_STATUS (status); } } - internal_params[external_params->count] = NULL; + info.parameters[external_params->count] = NULL; } + /* * Three major cases: * 1) Fully qualified pathname @@ -225,8 +233,7 @@ acpi_evaluate_object ( /* * The path is fully qualified, just evaluate by name */ - status = acpi_ns_evaluate_by_name (pathname, internal_params, - &internal_return_obj); + status = acpi_ns_evaluate_by_name (pathname, &info); } else if (!handle) { /* @@ -256,15 +263,13 @@ acpi_evaluate_object ( * The null pathname case means the handle is for * the actual object to be evaluated */ - status = acpi_ns_evaluate_by_handle (handle, internal_params, - &internal_return_obj); + status = acpi_ns_evaluate_by_handle (&info); } else { /* * Both a Handle and a relative Pathname */ - status = acpi_ns_evaluate_relative (handle, pathname, internal_params, - &internal_return_obj); + status = acpi_ns_evaluate_relative (pathname, &info); } } @@ -274,11 +279,11 @@ acpi_evaluate_object ( * copy the return value to an external object. */ if (return_buffer) { - if (!internal_return_obj) { + if (!info.return_object) { return_buffer->length = 0; } else { - if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that * the object we are evaluating has nothing interesting to @@ -288,7 +293,7 @@ acpi_evaluate_object ( * support for various types at a later date if necessary. */ status = AE_TYPE; - internal_return_obj = NULL; /* No need to delete a NS Node */ + info.return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } @@ -297,7 +302,7 @@ acpi_evaluate_object ( * Find out how large a buffer is needed * to contain the returned object */ - status = acpi_ut_get_object_size (internal_return_obj, + status = acpi_ut_get_object_size (info.return_object, &buffer_space_needed); if (ACPI_SUCCESS (status)) { /* Validate/Allocate/Clear caller buffer */ @@ -309,13 +314,14 @@ acpi_evaluate_object ( */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Needed buffer size %X, %s\n", - (u32) buffer_space_needed, acpi_format_exception (status))); + (u32) buffer_space_needed, + acpi_format_exception (status))); } else { /* * We have enough space for the object, build it */ - status = acpi_ut_copy_iobject_to_eobject (internal_return_obj, + status = acpi_ut_copy_iobject_to_eobject (info.return_object, return_buffer); } } @@ -323,7 +329,7 @@ acpi_evaluate_object ( } } - if (internal_return_obj) { + if (info.return_object) { /* * Delete the internal return object. NOTE: Interpreter * must be locked to avoid race condition. @@ -334,7 +340,7 @@ acpi_evaluate_object ( * Delete the internal return object. (Or at least * decrement the reference count by one) */ - acpi_ut_remove_reference (internal_return_obj); + acpi_ut_remove_reference (info.return_object); acpi_ex_exit_interpreter (); } } @@ -342,14 +348,15 @@ acpi_evaluate_object ( /* * Free the input parameter list (if we created one), */ - if (internal_params) { + if (info.parameters) { /* Free the allocated parameter block */ - acpi_ut_delete_internal_object_list (internal_params); + acpi_ut_delete_internal_object_list (info.parameters); } return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_evaluate_object); /******************************************************************************* @@ -422,6 +429,7 @@ acpi_walk_namespace ( (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_walk_namespace); /******************************************************************************* @@ -595,6 +603,7 @@ acpi_get_devices ( (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_devices); /******************************************************************************* diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index a1acb9f12..1e4d9ebd7 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -42,6 +42,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -129,6 +130,7 @@ acpi_get_handle ( return (status); } +EXPORT_SYMBOL(acpi_get_handle); /****************************************************************************** @@ -210,6 +212,7 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } +EXPORT_SYMBOL(acpi_get_name); /****************************************************************************** @@ -281,7 +284,7 @@ acpi_get_object_info ( if (info.type == ACPI_TYPE_DEVICE) { /* * Get extra info for ACPI Devices objects only: - * Run the Device _HID, _UID, _CID, _STA, and _ADR methods. + * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info.Valid bitfield is used @@ -330,7 +333,7 @@ acpi_get_object_info ( status = acpi_ut_execute_sxds (node, info.highest_dstates); if (ACPI_SUCCESS (status)) { - info.valid |= ACPI_VALID_STA; + info.valid |= ACPI_VALID_SXDS; } status = AE_OK; @@ -359,4 +362,5 @@ cleanup: } return (status); } +EXPORT_SYMBOL(acpi_get_object_info); diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index 537032073..3ed437071 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -42,6 +42,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -106,6 +107,7 @@ acpi_get_type ( status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } +EXPORT_SYMBOL(acpi_get_type); /******************************************************************************* @@ -171,6 +173,7 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } +EXPORT_SYMBOL(acpi_get_parent); /******************************************************************************* @@ -255,5 +258,5 @@ unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } - +EXPORT_SYMBOL(acpi_get_next_object); diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 0646b2955..1f63b4d71 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -51,6 +51,7 @@ acpi_table_print_srat_entry ( switch (header->type) { case ACPI_SRAT_PROCESSOR_AFFINITY: +#ifdef ACPI_DEBUG_OUTPUT { struct acpi_table_processor_affinity *p = (struct acpi_table_processor_affinity*) header; @@ -58,9 +59,11 @@ acpi_table_print_srat_entry ( p->apic_id, p->lsapic_eid, p->proximity_domain, p->flags.enabled?"enabled":"disabled")); } +#endif /* ACPI_DEBUG_OUTPUT */ break; case ACPI_SRAT_MEMORY_AFFINITY: +#ifdef ACPI_DEBUG_OUTPUT { struct acpi_table_memory_affinity *p = (struct acpi_table_memory_affinity*) header; @@ -70,6 +73,7 @@ acpi_table_print_srat_entry ( p->flags.enabled ? "enabled" : "disabled", p->flags.hot_pluggable ? " hot-pluggable" : "")); } +#endif /* ACPI_DEBUG_OUTPUT */ break; default: @@ -94,8 +98,6 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size) /* downcast just for %llu vs %lu for i386/ia64 */ localities = (u32) slit->localities; - printk(KERN_INFO PREFIX "SLIT localities %ux%u\n", localities, localities); - acpi_numa_slit_init(slit); return 0; @@ -103,7 +105,9 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size) static int __init -acpi_parse_processor_affinity (acpi_table_entry_header *header) +acpi_parse_processor_affinity ( + acpi_table_entry_header *header, + const unsigned long end) { struct acpi_table_processor_affinity *processor_affinity; @@ -121,7 +125,9 @@ acpi_parse_processor_affinity (acpi_table_entry_header *header) static int __init -acpi_parse_memory_affinity (acpi_table_entry_header *header) +acpi_parse_memory_affinity ( + acpi_table_entry_header *header, + const unsigned long end) { struct acpi_table_memory_affinity *memory_affinity; @@ -148,8 +154,6 @@ acpi_parse_srat (unsigned long phys_addr, unsigned long size) srat = (struct acpi_table_srat *) __va(phys_addr); - printk(KERN_INFO PREFIX "SRAT revision %d\n", srat->table_revision); - return 0; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 433fdd701..5d8afd7ab 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -26,6 +26,7 @@ */ #include +#include #include #include #include @@ -51,25 +52,37 @@ ACPI_MODULE_NAME ("osl") struct acpi_os_dpc { - OSD_EXECUTION_CALLBACK function; + acpi_osd_exec_callback function; void *context; }; +#ifdef CONFIG_ACPI_CUSTOM_DSDT +#include CONFIG_ACPI_CUSTOM_DSDT_FILE +#endif #ifdef ENABLE_DEBUGGER #include + /* stuff for debugger support */ int acpi_in_debugger; +EXPORT_SYMBOL(acpi_in_debugger); + extern char line_buf[80]; #endif /*ENABLE_DEBUGGER*/ static unsigned int acpi_irq_irq; -static OSD_HANDLER acpi_irq_handler; +static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; acpi_status acpi_os_initialize(void) +{ + return AE_OK; +} + +acpi_status +acpi_os_initialize1(void) { /* * Initialize PCI configuration space access, as we'll need to access @@ -108,6 +121,7 @@ acpi_os_printf(const char *fmt,...) acpi_os_vprintf(fmt, args); va_end(args); } +EXPORT_SYMBOL(acpi_os_printf); void acpi_os_vprintf(const char *fmt, va_list args) @@ -138,6 +152,7 @@ acpi_os_free(void *ptr) { kfree(ptr); } +EXPORT_SYMBOL(acpi_os_free); acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) @@ -165,11 +180,11 @@ acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr) } acpi_status -acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt) +acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt) { if (efi_enabled) { if (EFI_MEMORY_WB & efi_mem_attributes(phys)) { - *virt = phys_to_virt(phys); + *virt = (void __iomem *) phys_to_virt(phys); } else { *virt = ioremap(phys, size); } @@ -191,11 +206,12 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt) } void -acpi_os_unmap_memory(void *virt, acpi_size size) +acpi_os_unmap_memory(void __iomem *virt, acpi_size size) { iounmap(virt); } +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) { @@ -206,6 +222,7 @@ acpi_os_get_physical_address(void *virt, acpi_physical_address *phys) return AE_OK; } +#endif #define ACPI_MAX_OVERRIDE_LEN 100 @@ -220,7 +237,7 @@ acpi_os_predefined_override (const struct acpi_predefined_names *init_val, *new_val = NULL; if (!memcmp (init_val->name, "_OS_", 4) && strlen(acpi_os_name)) { - printk(KERN_INFO PREFIX "Overriding _OS definition %s\n", + printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n", acpi_os_name); *new_val = acpi_os_name; } @@ -235,7 +252,14 @@ acpi_os_table_override (struct acpi_table_header *existing_table, if (!existing_table || !new_table) return AE_BAD_PARAMETER; +#ifdef CONFIG_ACPI_CUSTOM_DSDT + if (strncmp(existing_table->signature, "DSDT", 4) == 0) + *new_table = (struct acpi_table_header*)AmlCode; + else + *new_table = NULL; +#else *new_table = NULL; +#endif return AE_OK; } @@ -246,7 +270,7 @@ acpi_irq(int irq, void *dev_id, struct pt_regs *regs) } acpi_status -acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context) +acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context) { unsigned int irq; @@ -274,7 +298,7 @@ acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context) } acpi_status -acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) { if (irq) { free_irq(irq, acpi_irq); @@ -290,11 +314,12 @@ acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) */ void -acpi_os_sleep(u32 sec, u32 ms) +acpi_os_sleep(acpi_integer ms) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ * sec + (ms * HZ) / 1000); + schedule_timeout(((signed long) ms * HZ) / 1000); } +EXPORT_SYMBOL(acpi_os_sleep); void acpi_os_stall(u32 us) @@ -309,6 +334,30 @@ acpi_os_stall(u32 us) us -= delay; } } +EXPORT_SYMBOL(acpi_os_stall); + +/* + * Support ACPI 3.0 AML Timer operand + * Returns 64-bit free-running, monotonically increasing timer + * with 100ns granularity + */ +u64 +acpi_os_get_timer (void) +{ + static u64 t; + +#ifdef CONFIG_HPET + /* TBD: use HPET if available */ +#endif + +#ifdef CONFIG_X86_PM_TIMER + /* TBD: default to PM timer if HPET was not available */ +#endif + if (!t) + printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); + + return(++t); +} acpi_status acpi_os_read_port( @@ -338,6 +387,7 @@ acpi_os_read_port( return AE_OK; } +EXPORT_SYMBOL(acpi_os_read_port); acpi_status acpi_os_write_port( @@ -362,6 +412,7 @@ acpi_os_write_port( return AE_OK; } +EXPORT_SYMBOL(acpi_os_write_port); acpi_status acpi_os_read_memory( @@ -370,30 +421,31 @@ acpi_os_read_memory( u32 width) { u32 dummy; - void *virt_addr; + void __iomem *virt_addr; int iomem = 0; if (efi_enabled) { if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - virt_addr = phys_to_virt(phys_addr); + /* HACK ALERT! We can use readb/w/l on real memory too.. */ + virt_addr = (void __iomem *) phys_to_virt(phys_addr); } else { iomem = 1; virt_addr = ioremap(phys_addr, width); } } else - virt_addr = phys_to_virt(phys_addr); + virt_addr = (void __iomem *) phys_to_virt(phys_addr); if (!value) value = &dummy; switch (width) { case 8: - *(u8*) value = *(u8*) virt_addr; + *(u8*) value = readb(virt_addr); break; case 16: - *(u16*) value = *(u16*) virt_addr; + *(u16*) value = readw(virt_addr); break; case 32: - *(u32*) value = *(u32*) virt_addr; + *(u32*) value = readl(virt_addr); break; default: BUG(); @@ -413,28 +465,29 @@ acpi_os_write_memory( u32 value, u32 width) { - void *virt_addr; + void __iomem *virt_addr; int iomem = 0; if (efi_enabled) { if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) { - virt_addr = phys_to_virt(phys_addr); + /* HACK ALERT! We can use writeb/w/l on real memory too */ + virt_addr = (void __iomem *) phys_to_virt(phys_addr); } else { iomem = 1; virt_addr = ioremap(phys_addr, width); } } else - virt_addr = phys_to_virt(phys_addr); + virt_addr = (void __iomem *) phys_to_virt(phys_addr); switch (width) { case 8: - *(u8*) virt_addr = value; + writeb(value, virt_addr); break; case 16: - *(u16*) virt_addr = value; + writew(value, virt_addr); break; case 32: - *(u32*) virt_addr = value; + writel(value, virt_addr); break; default: BUG(); @@ -470,12 +523,15 @@ acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value return AE_ERROR; } + BUG_ON(!raw_pci_ops); + result = raw_pci_ops->read(pci_id->segment, pci_id->bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, value); return (result ? AE_ERROR : AE_OK); } +EXPORT_SYMBOL(acpi_os_read_pci_configuration); acpi_status acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integer value, u32 width) @@ -496,6 +552,8 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ return AE_ERROR; } + BUG_ON(!raw_pci_ops); + result = raw_pci_ops->write(pci_id->segment, pci_id->bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, value); @@ -624,7 +682,7 @@ acpi_os_execute_deferred ( acpi_status acpi_os_queue_for_execution( u32 priority, - OSD_EXECUTION_CALLBACK function, + acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; @@ -667,6 +725,7 @@ acpi_os_queue_for_execution( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_os_queue_for_execution); void acpi_os_wait_events_complete( @@ -674,6 +733,7 @@ acpi_os_wait_events_complete( { flush_workqueue(kacpid_wq); } +EXPORT_SYMBOL(acpi_os_wait_events_complete); /* * Allocate the memory for a spinlock and initialize it. @@ -785,6 +845,7 @@ acpi_os_create_semaphore( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_os_create_semaphore); /* @@ -811,6 +872,7 @@ acpi_os_delete_semaphore( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_os_delete_semaphore); /* @@ -900,6 +962,7 @@ acpi_os_wait_semaphore( return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_os_wait_semaphore); /* @@ -926,7 +989,9 @@ acpi_os_signal_semaphore( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_os_signal_semaphore); +#ifdef ACPI_FUTURE_USAGE u32 acpi_os_get_line(char *buffer) { @@ -945,6 +1010,7 @@ acpi_os_get_line(char *buffer) return 0; } +#endif /* ACPI_FUTURE_USAGE */ /* Assumes no unreadable holes inbetween */ u8 @@ -952,11 +1018,12 @@ acpi_os_readable(void *ptr, acpi_size len) { #if defined(__i386__) || defined(__x86_64__) char tmp; - return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1); + return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1); #endif return 1; } +#ifdef ACPI_FUTURE_USAGE u8 acpi_os_writable(void *ptr, acpi_size len) { @@ -964,6 +1031,7 @@ acpi_os_writable(void *ptr, acpi_size len) The later may be difficult at early boot when kmap doesn't work yet. */ return 1; } +#endif u32 acpi_os_get_thread_id (void) @@ -985,17 +1053,22 @@ acpi_os_signal ( printk(KERN_ERR PREFIX "Fatal opcode executed\n"); break; case ACPI_SIGNAL_BREAKPOINT: - { - char *bp_info = (char*) info; - - printk(KERN_ERR "ACPI breakpoint: %s\n", bp_info); - } + /* + * AML Breakpoint + * ACPI spec. says to treat it as a NOP unless + * you are debugging. So if/when we integrate + * AML debugger into the kernel debugger its + * hook will go here. But until then it is + * not useful to print anything on breakpoints. + */ + break; default: break; } return AE_OK; } +EXPORT_SYMBOL(acpi_os_signal); int __init acpi_os_name_setup(char *str) @@ -1066,15 +1139,23 @@ __setup("acpi_serialize", acpi_serialize_setup); * Run-time events on the same GPE this flag is available * to tell Linux to keep the wake-time GPEs enabled at run-time. */ -static int __init -acpi_leave_gpes_disabled_setup(char *str) +int __init +acpi_wake_gpes_always_on_setup(char *str) { - printk(KERN_INFO PREFIX "leave wake GPEs disabled\n"); + printk(KERN_INFO PREFIX "wake GPEs not disabled\n"); - acpi_gbl_leave_wake_gpes_disabled = TRUE; + acpi_gbl_leave_wake_gpes_disabled = FALSE; return 1; } -__setup("acpi_leave_gpes_disabled", acpi_leave_gpes_disabled_setup); +__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); + +/* + * max_cstate is defined in the base kernel so modules can + * change it w/o depending on the state of the processor module. + */ +unsigned int max_cstate = ACPI_C_STATES_MAX; + +EXPORT_SYMBOL(max_cstate); diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 198e2206b..6025b75d7 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -194,6 +194,7 @@ #define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST) #define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_TIMER_OP ARG_NONE #define ARGP_TO_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) #define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) #define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) @@ -251,7 +252,7 @@ #define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_CREATE_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_CREATE_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) -#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) +#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) #define ARGI_DEBUG_OP ARG_NONE #define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) #define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REF_OR_STRING) @@ -270,10 +271,10 @@ #define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE #define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) -#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) -#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) +#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) #define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE -#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA) #define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE #define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE @@ -317,7 +318,7 @@ #define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT) -#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT) +#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */ #define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE @@ -325,13 +326,14 @@ #define ARGI_STRING_OP ARGI_INVALID_OPCODE #define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE +#define ARGI_TIMER_OP ARG_NONE #define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) #define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) #define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) #define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) #define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) #define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET) -#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) +#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */ #define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE) #define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER) @@ -527,8 +529,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = /* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE), /* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), -/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), -/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), +/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), +/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), /* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 3B */ ACPI_OP ("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3C */ ACPI_OP ("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), @@ -588,7 +590,6 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = /* 6C */ ACPI_OP ("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), /* 6D */ ACPI_OP ("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), - /* ACPI 2.0 opcodes */ /* 6E */ ACPI_OP ("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT), @@ -606,7 +607,11 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = /* 7A */ ACPI_OP ("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 7B */ ACPI_OP ("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP ("DataTableRegion", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), -/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE) +/* 7D */ ACPI_OP ("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + +/* ACPI 3.0 opcodes */ + +/* 7E */ ACPI_OP ("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_FLAGS_EXEC_0A_0T_1R) /*! [End] no source code translation !*/ }; @@ -615,7 +620,6 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = * This table is directly indexed by the opcodes, and returns an * index into the table above */ - static const u8 acpi_gbl_short_op_index[256] = { /* 0 1 2 3 4 5 6 7 */ @@ -654,7 +658,10 @@ static const u8 acpi_gbl_short_op_index[256] = /* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, }; - +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) + */ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { /* 0 1 2 3 4 5 6 7 */ @@ -665,7 +672,7 @@ static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = /* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, /* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, /* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, /* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, /* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, /* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, @@ -724,7 +731,7 @@ acpi_ps_get_opcode_info ( default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown extended opcode [%X]\n", opcode)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown AML opcode [%4.4X]\n", opcode)); break; } diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 00a3540f0..8c588dcd7 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -164,123 +164,125 @@ acpi_ps_complete_this_op ( /* Delete this op and the subtree below it if asked to */ - if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) && - (walk_state->op_info->class != AML_CLASS_ARGUMENT)) { - /* Make sure that we only delete this subtree */ + if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || + (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { + return_VOID; + } + + /* Make sure that we only delete this subtree */ + + if (op->common.parent) { + /* + * Check if we need to replace the operator and its subtree + * with a return value op (placeholder op) + */ + parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); + + switch (parent_info->class) { + case AML_CLASS_CONTROL: + break; + + case AML_CLASS_CREATE: - if (op->common.parent) { /* - * Check if we need to replace the operator and its subtree - * with a return value op (placeholder op) + * These opcodes contain term_arg operands. The current + * op must be replaced by a placeholder return op */ - parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); - - switch (parent_info->class) { - case AML_CLASS_CONTROL: - break; + replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); + if (!replacement_op) { + goto cleanup; + } + break; - case AML_CLASS_CREATE: + case AML_CLASS_NAMED_OBJECT: - /* - * These opcodes contain term_arg operands. The current - * op must be replaced by a placeholder return op - */ + /* + * These opcodes contain term_arg operands. The current + * op must be replaced by a placeholder return op + */ + if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || + (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || + (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); if (!replacement_op) { - return_VOID; + goto cleanup; } - break; - - case AML_CLASS_NAMED_OBJECT: + } - /* - * These opcodes contain term_arg operands. The current - * op must be replaced by a placeholder return op - */ - if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || - (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || - (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || - (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || - (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { - replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); + if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && + (walk_state->descending_callback != acpi_ds_exec_begin_op)) { + if ((op->common.aml_opcode == AML_BUFFER_OP) || + (op->common.aml_opcode == AML_PACKAGE_OP) || + (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { + replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); if (!replacement_op) { - return_VOID; + goto cleanup; } + + replacement_op->named.data = op->named.data; + replacement_op->named.length = op->named.length; } + } + break; - if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && - (walk_state->descending_callback != acpi_ds_exec_begin_op)) { - if ((op->common.aml_opcode == AML_BUFFER_OP) || - (op->common.aml_opcode == AML_PACKAGE_OP) || - (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { - replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); - if (!replacement_op) { - return_VOID; - } + default: + replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); + if (!replacement_op) { + goto cleanup; + } + } - replacement_op->named.data = op->named.data; - replacement_op->named.length = op->named.length; - } - } - break; + /* We must unlink this op from the parent tree */ - default: - replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); - if (!replacement_op) { - return_VOID; - } + prev = op->common.parent->common.value.arg; + if (prev == op) { + /* This op is the first in the list */ + + if (replacement_op) { + replacement_op->common.parent = op->common.parent; + replacement_op->common.value.arg = NULL; + replacement_op->common.node = op->common.node; + op->common.parent->common.value.arg = replacement_op; + replacement_op->common.next = op->common.next; + } + else { + op->common.parent->common.value.arg = op->common.next; } + } - /* We must unlink this op from the parent tree */ + /* Search the parent list */ - prev = op->common.parent->common.value.arg; - if (prev == op) { - /* This op is the first in the list */ + else while (prev) { + /* Traverse all siblings in the parent's argument list */ + next = prev->common.next; + if (next == op) { if (replacement_op) { - replacement_op->common.parent = op->common.parent; - replacement_op->common.value.arg = NULL; - replacement_op->common.node = op->common.node; - op->common.parent->common.value.arg = replacement_op; - replacement_op->common.next = op->common.next; + replacement_op->common.parent = op->common.parent; + replacement_op->common.value.arg = NULL; + replacement_op->common.node = op->common.node; + prev->common.next = replacement_op; + replacement_op->common.next = op->common.next; + next = NULL; } else { - op->common.parent->common.value.arg = op->common.next; + prev->common.next = op->common.next; + next = NULL; } } - /* Search the parent list */ - - else while (prev) { - /* Traverse all siblings in the parent's argument list */ - - next = prev->common.next; - if (next == op) { - if (replacement_op) { - replacement_op->common.parent = op->common.parent; - replacement_op->common.value.arg = NULL; - replacement_op->common.node = op->common.node; - prev->common.next = replacement_op; - replacement_op->common.next = op->common.next; - next = NULL; - } - else { - prev->common.next = op->common.next; - next = NULL; - } - } - - prev = next; - } + prev = next; } + } - /* Now we can actually delete the subtree rooted at op */ - acpi_ps_delete_parse_tree (op); +cleanup: - return_VOID; - } + /* Now we can actually delete the subtree rooted at op */ + acpi_ps_delete_parse_tree (op); return_VOID; } @@ -552,7 +554,8 @@ acpi_ps_parse_loop ( if (!pre_op) { pre_op = acpi_ps_alloc_op (walk_state->opcode); if (!pre_op) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto close_this_op; } } @@ -578,7 +581,8 @@ acpi_ps_parse_loop ( /* Make sure that we found a NAME and didn't run out of arguments */ if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { - return_ACPI_STATUS (AE_AML_NO_OPERAND); + status = AE_AML_NO_OPERAND; + goto close_this_op; } /* We know that this arg is a name, move to next arg */ @@ -638,7 +642,8 @@ acpi_ps_parse_loop ( walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); op = acpi_ps_alloc_op (walk_state->opcode); if (!op) { - return_ACPI_STATUS (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto close_this_op; } if (walk_state->op_info->flags & AML_CREATE) { @@ -801,7 +806,7 @@ acpi_ps_parse_loop ( status = acpi_ps_push_scope (parser_state, op, walk_state->arg_types, walk_state->arg_count); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto close_this_op; } op = NULL; continue; @@ -1128,7 +1133,7 @@ acpi_ps_parse_aml ( else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } - else if (status != AE_OK) { + else if ((status != AE_OK) && (walk_state->method_desc)) { ACPI_REPORT_METHOD_ERROR ("Method execution failed", walk_state->method_node, NULL, status); diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index a25f31c8a..15e7ec1d8 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -181,6 +181,8 @@ acpi_ps_append_arg ( } +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_ps_get_child @@ -192,7 +194,6 @@ acpi_ps_append_arg ( * DESCRIPTION: Get op's children or NULL if none * ******************************************************************************/ - union acpi_parse_object * acpi_ps_get_child ( union acpi_parse_object *op) @@ -322,4 +323,5 @@ acpi_ps_get_depth_next ( return (next); } +#endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index e4b8a280e..148b8f441 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -129,10 +129,9 @@ union acpi_parse_object* acpi_ps_alloc_op ( u16 opcode) { - union acpi_parse_object *op = NULL; - u32 size; - u8 flags; + union acpi_parse_object *op; const struct acpi_opcode_info *op_info; + u8 flags = ACPI_PARSEOP_GENERIC; ACPI_FUNCTION_ENTRY (); @@ -140,32 +139,28 @@ acpi_ps_alloc_op ( op_info = acpi_ps_get_opcode_info (opcode); - /* Allocate the minimum required size object */ + /* Determine type of parse_op required */ if (op_info->flags & AML_DEFER) { - size = sizeof (struct acpi_parse_obj_named); flags = ACPI_PARSEOP_DEFERRED; } else if (op_info->flags & AML_NAMED) { - size = sizeof (struct acpi_parse_obj_named); flags = ACPI_PARSEOP_NAMED; } else if (opcode == AML_INT_BYTELIST_OP) { - size = sizeof (struct acpi_parse_obj_named); flags = ACPI_PARSEOP_BYTELIST; } - else { - size = sizeof (struct acpi_parse_obj_common); - flags = ACPI_PARSEOP_GENERIC; - } - if (size == sizeof (struct acpi_parse_obj_common)) { - /* - * The generic op is by far the most common (16 to 1) - */ + /* Allocate the minimum required size object */ + + if (flags == ACPI_PARSEOP_GENERIC) { + /* The generic op (default) is by far the most common (16 to 1) */ + op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE); } else { + /* Extended parseop */ + op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT); } @@ -272,6 +267,7 @@ acpi_ps_is_prefix_char ( /* * Get op's name (4-byte name segment) or 0 if unnamed */ +#ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name ( union acpi_parse_object *op) @@ -288,6 +284,7 @@ acpi_ps_get_name ( return (op->named.name); } +#endif /* ACPI_FUTURE_USAGE */ /* diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index b7917cfdc..9281f6aec 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -57,7 +57,7 @@ * * FUNCTION: acpi_psx_execute * - * PARAMETERS: method_node - A method object containing both the AML + * PARAMETERS: Info->Node - A method object containing both the AML * address and length. * **Params - List of parameters to pass to method, * terminated by NULL. Params itself may be @@ -73,9 +73,7 @@ acpi_status acpi_psx_execute ( - struct acpi_namespace_node *method_node, - union acpi_operand_object **params, - union acpi_operand_object **return_obj_desc) + struct acpi_parameter_info *info) { acpi_status status; union acpi_operand_object *obj_desc; @@ -89,29 +87,30 @@ acpi_psx_execute ( /* Validate the Node and get the attached object */ - if (!method_node) { + if (!info || !info->node) { return_ACPI_STATUS (AE_NULL_ENTRY); } - obj_desc = acpi_ns_get_attached_object (method_node); + obj_desc = acpi_ns_get_attached_object (info->node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ - status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL); + status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - if (params) { + if ((info->parameter_type == ACPI_PARAM_ARGS) && + (info->parameters)) { /* * The caller "owns" the parameters, so give each one an extra * reference */ - for (i = 0; params[i]; i++) { - acpi_ut_add_reference (params[i]); + for (i = 0; info->parameters[i]; i++) { + acpi_ut_add_reference (info->parameters[i]); } } @@ -121,7 +120,7 @@ acpi_psx_execute ( */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", - method_node, obj_desc)); + info->node, obj_desc)); /* Create and init a Root Node */ @@ -147,8 +146,9 @@ acpi_psx_execute ( goto cleanup2; } - status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, - obj_desc->method.aml_length, NULL, NULL, 1); + status = acpi_ds_init_aml_walk (walk_state, op, info->node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE (status)) { goto cleanup3; } @@ -159,7 +159,6 @@ acpi_psx_execute ( acpi_ps_delete_parse_tree (op); if (ACPI_FAILURE (status)) { goto cleanup1; /* Walk state is already deleted */ - } /* @@ -167,7 +166,7 @@ acpi_psx_execute ( */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", - method_node, obj_desc)); + info->node, obj_desc)); /* Create and init a Root Node */ @@ -179,8 +178,8 @@ acpi_psx_execute ( /* Init new op with the method name and pointer back to the NS node */ - acpi_ps_set_name (op, method_node->name.integer); - op->common.node = method_node; + acpi_ps_set_name (op, info->node->name.integer); + op->common.node = info->node; /* Create and initialize a new walk state */ @@ -190,8 +189,9 @@ acpi_psx_execute ( goto cleanup2; } - status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, - obj_desc->method.aml_length, params, return_obj_desc, 3); + status = acpi_ds_init_aml_walk (walk_state, op, info->node, + obj_desc->method.aml_start, + obj_desc->method.aml_length, info, 3); if (ACPI_FAILURE (status)) { goto cleanup3; } @@ -210,13 +210,14 @@ cleanup2: acpi_ps_delete_parse_tree (op); cleanup1: - if (params) { + if ((info->parameter_type == ACPI_PARAM_ARGS) && + (info->parameters)) { /* Take away the extra reference that we gave the parameters above */ - for (i = 0; params[i]; i++) { + for (i = 0; info->parameters[i]; i++) { /* Ignore errors, just do them all */ - (void) acpi_ut_update_object_reference (params[i], REF_DECREMENT); + (void) acpi_ut_update_object_reference (info->parameters[i], REF_DECREMENT); } } @@ -228,10 +229,10 @@ cleanup1: * If the method has returned an object, signal this to the caller with * a control exception code */ - if (*return_obj_desc) { + if (info->return_object) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n", - *return_obj_desc)); - ACPI_DUMP_STACK_ENTRY (*return_obj_desc); + info->return_object)); + ACPI_DUMP_STACK_ENTRY (info->return_object); status = AE_CTRL_RETURN_VALUE; } diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index ec264c806..ce3f41b24 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -67,6 +67,7 @@ acpi_pci_data_handler ( * to resolve PCI information for ACPI-PCI devices defined in the namespace. * This typically occurs when resolving PCI operation region information. */ +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_os_get_pci_id ( acpi_handle handle, @@ -114,6 +115,7 @@ acpi_os_get_pci_id ( return_ACPI_STATUS(AE_OK); } +#endif /* ACPI_FUTURE_USAGE */ int diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 23e994522..41e85c214 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -227,6 +227,11 @@ acpi_pci_irq_add_prt ( PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +/* + * acpi_pci_irq_lookup + * success: return IRQ >= 0 + * failure: return -1 + */ static int acpi_pci_irq_lookup ( struct pci_bus *bus, @@ -249,14 +254,14 @@ acpi_pci_irq_lookup ( entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); if (!entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); - return_VALUE(0); + return_VALUE(-1); } if (entry->link.handle) { irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); - if (!irq) { + if (irq < 0) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); - return_VALUE(0); + return_VALUE(-1); } } else { irq = entry->link.index; @@ -269,6 +274,11 @@ acpi_pci_irq_lookup ( return_VALUE(irq); } +/* + * acpi_pci_irq_derive + * success: return IRQ >= 0 + * failure: return < 0 + */ static int acpi_pci_irq_derive ( struct pci_dev *dev, @@ -277,7 +287,7 @@ acpi_pci_irq_derive ( int *active_high_low) { struct pci_dev *bridge = dev; - int irq = 0; + int irq = -1; u8 bridge_pin = 0; ACPI_FUNCTION_TRACE("acpi_pci_irq_derive"); @@ -289,7 +299,7 @@ acpi_pci_irq_derive ( * Attempt to derive an IRQ for this device from a parent bridge's * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). */ - while (!irq && bridge->bus->self) { + while (irq < 0 && bridge->bus->self) { pin = (pin + PCI_SLOT(bridge->devfn)) % 4; bridge = bridge->bus->self; @@ -299,7 +309,7 @@ acpi_pci_irq_derive ( if (!bridge_pin) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(bridge))); - return_VALUE(0); + return_VALUE(-1); } /* Pin is from 0 to 3 */ bridge_pin --; @@ -310,9 +320,9 @@ acpi_pci_irq_derive ( pin, edge_level, active_high_low); } - if (!irq) { + if (irq < 0) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev))); - return_VALUE(0); + return_VALUE(-1); } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n", @@ -321,6 +331,11 @@ acpi_pci_irq_derive ( return_VALUE(irq); } +/* + * acpi_pci_irq_enable + * success: return 0 + * failure: return < 0 + */ int acpi_pci_irq_enable ( @@ -358,20 +373,20 @@ acpi_pci_irq_enable ( * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ - if (!irq) + if (irq < 0) irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ - if (!irq) { + if (irq < 0) { printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ - if (dev->irq && (dev->irq <= 0xF)) { + if (dev->irq >= 0 && (dev->irq <= 0xF)) { printk(" - using IRQ %d\n", dev->irq); - return_VALUE(dev->irq); + return_VALUE(0); } else { printk("\n"); @@ -388,5 +403,7 @@ acpi_pci_irq_enable ( (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); - return_VALUE(dev->irq); + return_VALUE(0); } +EXPORT_SYMBOL(acpi_pci_irq_enable); + diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 13e922551..bc724160b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -29,6 +29,7 @@ * for IRQ management (e.g. start()->_SRS). */ +#include #include #include #include @@ -71,7 +72,7 @@ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 edge_level; /* All IRQs */ u8 active_high_low; /* All IRQs */ - u8 setonboot; + u8 initialized; u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; @@ -109,13 +110,13 @@ acpi_pci_link_check_possible ( switch (resource->id) { case ACPI_RSTYPE_START_DPF: - return AE_OK; + return_ACPI_STATUS(AE_OK); case ACPI_RSTYPE_IRQ: { struct acpi_resource_irq *p = &resource->data.irq; if (!p || !p->number_of_interrupts) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } for (i = 0; (inumber_of_interrupts && iinterrupts[i]) { @@ -136,7 +137,7 @@ acpi_pci_link_check_possible ( if (!p || !p->number_of_interrupts) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank EXT IRQ resource\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } for (i = 0; (inumber_of_interrupts && iinterrupts[i]) { @@ -154,10 +155,10 @@ acpi_pci_link_check_possible ( default: ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource is not an IRQ entry\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } - return AE_CTRL_TERMINATE; + return_ACPI_STATUS(AE_CTRL_TERMINATE); } @@ -206,7 +207,7 @@ acpi_pci_link_check_current ( */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Blank IRQ resource\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } *irq = p->interrupts[0]; break; @@ -221,7 +222,7 @@ acpi_pci_link_check_current ( */ ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank EXT IRQ resource\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } *irq = p->interrupts[0]; break; @@ -229,9 +230,9 @@ acpi_pci_link_check_current ( default: ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Resource isn't an IRQ\n")); - return AE_OK; + return_ACPI_STATUS(AE_OK); } - return AE_CTRL_TERMINATE; + return_ACPI_STATUS(AE_CTRL_TERMINATE); } /* @@ -447,7 +448,7 @@ acpi_pci_link_set ( #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) -static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = { +static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ @@ -467,7 +468,7 @@ static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = { /* >IRQ15 */ }; -int +int __init acpi_irq_penalty_init(void) { struct list_head *node = NULL; @@ -517,7 +518,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) { ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); - if (link->irq.setonboot) + if (link->irq.initialized) return_VALUE(0); /* @@ -571,11 +572,16 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) { acpi_device_bid(link->device), link->irq.active); } - link->irq.setonboot = 1; + link->irq.initialized = 1; return_VALUE(0); } +/* + * acpi_pci_link_get_irq + * success: return IRQ >= 0 + * failure: return -1 + */ int acpi_pci_link_get_irq ( @@ -593,27 +599,27 @@ acpi_pci_link_get_irq ( result = acpi_bus_get_device(handle, &device); if (result) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); - return_VALUE(0); + return_VALUE(-1); } link = (struct acpi_pci_link *) acpi_driver_data(device); if (!link) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); - return_VALUE(0); + return_VALUE(-1); } /* TBD: Support multiple index (IRQ) entries per Link Device */ if (index) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index)); - return_VALUE(0); + return_VALUE(-1); } if (acpi_pci_link_allocate(link)) - return_VALUE(0); + return_VALUE(-1); if (!link->irq.active) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); - return_VALUE(0); + return_VALUE(-1); } if (edge_level) *edge_level = link->irq.edge_level; @@ -694,6 +700,42 @@ end: } +static int +acpi_pci_link_resume ( + struct acpi_pci_link *link) +{ + ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); + + if (link->irq.active && link->irq.initialized) + return_VALUE(acpi_pci_link_set(link, link->irq.active)); + else + return_VALUE(0); +} + + +static int +irqrouter_resume( + struct sys_device *dev) +{ + struct list_head *node = NULL; + struct acpi_pci_link *link = NULL; + + ACPI_FUNCTION_TRACE("irqrouter_resume"); + + list_for_each(node, &acpi_link.entries) { + + link = list_entry(node, struct acpi_pci_link, node); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + continue; + } + + acpi_pci_link_resume(link); + } + return_VALUE(0); +} + + static int acpi_pci_link_remove ( struct acpi_device *device, @@ -749,6 +791,18 @@ static int __init acpi_irq_penalty_update(char *str, int used) return 1; } +/* + * We'd like PNP to call this routine for the + * single ISA_USED value for each legacy device. + * But instead it calls us with each POSSIBLE setting. + * There is no ISA_POSSIBLE weight, so we simply use + * the (small) PCI_USING penalty. + */ +void acpi_penalize_isa_irq(int irq) +{ + acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; +} + /* * Over-ride default table to reserve additional IRQs for use by ISA * e.g. acpi_irq_isa=5 @@ -774,23 +828,54 @@ __setup("acpi_irq_pci=", acpi_irq_pci); static int __init acpi_irq_nobalance_set(char *str) { acpi_irq_balance = 0; - return(1); + return 1; } __setup("acpi_irq_nobalance", acpi_irq_nobalance_set); int __init acpi_irq_balance_set(char *str) { acpi_irq_balance = 1; - return(1); + return 1; } __setup("acpi_irq_balance", acpi_irq_balance_set); +static struct sysdev_class irqrouter_sysdev_class = { + set_kset_name("irqrouter"), + .resume = irqrouter_resume, +}; + + +static struct sys_device device_irqrouter = { + .id = 0, + .cls = &irqrouter_sysdev_class, +}; + + +static int __init irqrouter_init_sysfs(void) +{ + int error; + + ACPI_FUNCTION_TRACE("irqrouter_init_sysfs"); + + if (acpi_disabled || acpi_noirq) + return_VALUE(0); + + error = sysdev_class_register(&irqrouter_sysdev_class); + if (!error) + error = sysdev_register(&device_irqrouter); + + return_VALUE(error); +} + +device_initcall(irqrouter_init_sysfs); + + static int __init acpi_pci_link_init (void) { ACPI_FUNCTION_TRACE("acpi_pci_link_init"); - if (acpi_pci_disabled) + if (acpi_noirq) return_VALUE(0); acpi_link.count = 0; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index dd08b633a..2adaba68b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -90,6 +90,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) return n; } +EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { @@ -112,6 +113,7 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) driver->remove(root->handle); } } +EXPORT_SYMBOL(acpi_pci_unregister_driver); static acpi_status get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 657ddef48..419b371d9 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -288,6 +288,86 @@ acpi_power_off_device ( return_VALUE(0); } +/* + * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229): + * 1. Power on the power resources required for the wakeup device + * 2. Enable _PSW (power state wake) for the device if present + */ +int acpi_enable_wakeup_device_power (struct acpi_device *dev) +{ + union acpi_object arg = {ACPI_TYPE_INTEGER}; + struct acpi_object_list arg_list = {1, &arg}; + acpi_status status = AE_OK; + int i; + int ret = 0; + + ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power"); + if (!dev || !dev->wakeup.flags.valid) + return_VALUE(-1); + + arg.integer.value = 1; + /* Open power resource */ + for (i = 0; i < dev->wakeup.resources.count; i++) { + ret = acpi_power_on(dev->wakeup.resources.handles[i]); + if (ret) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error transition power state\n")); + dev->wakeup.flags.valid = 0; + return_VALUE(-1); + } + } + + /* Execute PSW */ + status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); + if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n")); + dev->wakeup.flags.valid = 0; + ret = -1; + } + + return_VALUE(ret); +} + +/* + * Shutdown a wakeup device, counterpart of above method + * 1. Disable _PSW (power state wake) + * 2. Shutdown down the power resources + */ +int acpi_disable_wakeup_device_power (struct acpi_device *dev) +{ + union acpi_object arg = {ACPI_TYPE_INTEGER}; + struct acpi_object_list arg_list = {1, &arg}; + acpi_status status = AE_OK; + int i; + int ret = 0; + + ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power"); + + if (!dev || !dev->wakeup.flags.valid) + return_VALUE(-1); + + arg.integer.value = 0; + /* Execute PSW */ + status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); + if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n")); + dev->wakeup.flags.valid = 0; + return_VALUE(-1); + } + + /* Close power resource */ + for (i = 0; i < dev->wakeup.resources.count; i++) { + ret = acpi_power_off_device(dev->wakeup.resources.handles[i]); + if (ret) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error transition power state\n")); + dev->wakeup.flags.valid = 0; + return_VALUE(-1); + } + } + + return_VALUE(ret); +} /* -------------------------------------------------------------------------- Device Power Management @@ -433,7 +513,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset) resource->references); end: - return 0; + return_VALUE(0); } static int acpi_power_open_fs(struct inode *inode, struct file *file) diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 8d7b78df6..64ce1e92e 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -39,11 +39,16 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include #include #include @@ -210,11 +215,13 @@ acpi_processor_errata_piix4 ( * each IDE controller's DMA status to make sure we catch all * DMA activity. */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) + if (dev) { errata.piix4.bmisx = pci_resource_start(dev, 4); + pci_dev_put(dev); + } /* * Type-F DMA @@ -225,7 +232,7 @@ acpi_processor_errata_piix4 ( * disable C3 support if this is enabled, as some legacy * devices won't operate well if fast DMA is disabled. */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, PCI_ANY_ID, PCI_ANY_ID, NULL); if (dev) { @@ -233,6 +240,7 @@ acpi_processor_errata_piix4 ( pci_read_config_byte(dev, 0x77, &value2); if ((value1 & 0x80) || (value2 & 0x80)) errata.piix4.fdma = 1; + pci_dev_put(dev); } break; @@ -264,10 +272,12 @@ acpi_processor_errata ( /* * PIIX4 */ - dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) + if (dev) { result = acpi_processor_errata_piix4(dev); + pci_dev_put(dev); + } return_VALUE(result); } @@ -329,8 +339,8 @@ acpi_processor_idle (void) { struct acpi_processor *pr = NULL; struct acpi_processor_cx *cx = NULL; - int next_state = 0; - int sleep_ticks = 0; + unsigned int next_state = 0; + unsigned int sleep_ticks = 0; u32 t1, t2 = 0; pr = processors[smp_processor_id()]; @@ -343,6 +353,15 @@ acpi_processor_idle (void) */ local_irq_disable(); + /* + * Check whether we truly need to go idle, or should + * reschedule: + */ + if (unlikely(need_resched())) { + local_irq_enable(); + return; + } + cx = &(pr->power.states[pr->power.state]); /* @@ -402,8 +421,15 @@ acpi_processor_idle (void) switch (pr->power.state) { case ACPI_STATE_C1: - /* Invoke C1. */ - safe_halt(); + /* + * Invoke C1. + * Use the appropriate idle routine, the one that would + * be used without acpi C-states. + */ + if (pm_idle_save) + pm_idle_save(); + else + safe_halt(); /* * TBD: Can't get time duration while in C1, as resumes * go to an ISR rather than here. Need to instrument @@ -459,8 +485,9 @@ acpi_processor_idle (void) * Track the number of longs (time asleep is greater than threshold) * and promote when the count threshold is reached. Note that bus * mastering activity may prevent promotions. + * Do not promote above max_cstate. */ - if (cx->promotion.state) { + if (cx->promotion.state && (cx->promotion.state <= max_cstate)) { if (sleep_ticks > cx->promotion.threshold.ticks) { cx->promotion.count++; cx->demotion.count = 0; @@ -497,6 +524,13 @@ acpi_processor_idle (void) } end: + /* + * Demote if current state exceeds max_cstate + */ + if (pr->power.state > max_cstate) { + next_state = max_cstate; + } + /* * New Cx State? * ------------- @@ -759,7 +793,10 @@ static DECLARE_MUTEX(performance_sem); * policy is adjusted accordingly. */ -static int acpi_processor_ppc_is_init = 0; +#define PPC_REGISTERED 1 +#define PPC_IN_USE 2 + +static int acpi_processor_ppc_status = 0; static int acpi_processor_ppc_notifier(struct notifier_block *nb, unsigned long event, @@ -817,6 +854,10 @@ acpi_processor_get_platform_limit ( * (e.g. 0 = states 0..n; 1 = states 1..n; etc. */ status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); + + if (status != AE_NOT_FOUND) + acpi_processor_ppc_status |= PPC_IN_USE; + if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n")); return_VALUE(-ENODEV); @@ -841,17 +882,17 @@ static int acpi_processor_ppc_has_changed( static void acpi_processor_ppc_init(void) { if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) - acpi_processor_ppc_is_init = 1; + acpi_processor_ppc_status |= PPC_REGISTERED; else printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n"); } static void acpi_processor_ppc_exit(void) { - if (acpi_processor_ppc_is_init) + if (acpi_processor_ppc_status & PPC_REGISTERED) cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER); - acpi_processor_ppc_is_init = 0; + acpi_processor_ppc_status &= ~PPC_REGISTERED; } /* @@ -859,7 +900,6 @@ static void acpi_processor_ppc_exit(void) { * _PCT and _PSS structures are read out and written into struct * acpi_processor_performance. */ - static int acpi_processor_set_pdc (struct acpi_processor *pr) { acpi_status status = AE_OK; @@ -964,7 +1004,7 @@ acpi_processor_get_performance_states ( struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"}; struct acpi_buffer state = {0, NULL}; union acpi_object *pss = NULL; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states"); @@ -1047,6 +1087,8 @@ acpi_processor_get_performance_info ( if (!pr || !pr->performance || !pr->handle) return_VALUE(-EINVAL); + acpi_processor_set_pdc(pr); + status = acpi_get_handle(pr->handle, "_PCT", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -1054,8 +1096,6 @@ acpi_processor_get_performance_info ( return_VALUE(-ENODEV); } - acpi_processor_set_pdc(pr); - result = acpi_processor_get_performance_control(pr); if (result) return_VALUE(result); @@ -1072,6 +1112,73 @@ acpi_processor_get_performance_info ( } +int acpi_processor_notify_smm(struct module *calling_module) { + acpi_status status; + static int is_done = 0; + + ACPI_FUNCTION_TRACE("acpi_processor_notify_smm"); + + if (!(acpi_processor_ppc_status & PPC_REGISTERED)) + return_VALUE(-EBUSY); + + if (!try_module_get(calling_module)) + return_VALUE(-EINVAL); + + /* is_done is set to negative if an error occured, + * and to postitive if _no_ error occured, but SMM + * was already notified. This avoids double notification + * which might lead to unexpected results... + */ + if (is_done > 0) { + module_put(calling_module); + return_VALUE(0); + } + else if (is_done < 0) { + module_put(calling_module); + return_VALUE(is_done); + } + + is_done = -EIO; + + /* Can't write pstate_cnt to smi_cmd if either value is zero */ + if ((!acpi_fadt.smi_cmd) || + (!acpi_fadt.pstate_cnt)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No SMI port or pstate_cnt\n")); + module_put(calling_module); + return_VALUE(0); + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); + + /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use + * it anyway, so we need to support it... */ + if (acpi_fadt_is_v1) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n")); + } + + status = acpi_os_write_port (acpi_fadt.smi_cmd, + (u32) acpi_fadt.pstate_cnt, 8); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Failed to write pstate_cnt [0x%x] to " + "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); + module_put(calling_module); + return_VALUE(status); + } + + /* Success. If there's no _PPC, we need to fear nothing, so + * we can allow the cpufreq driver to be rmmod'ed. */ + is_done = 1; + + if (!(acpi_processor_ppc_status & PPC_IN_USE)) + module_put(calling_module); + + return_VALUE(0); +} +EXPORT_SYMBOL(acpi_processor_notify_smm); + + #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF /* /proc/acpi/processor/../performance interface (DEPRECATED) */ @@ -1086,7 +1193,7 @@ static struct file_operations acpi_processor_perf_fops = { static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = (struct acpi_processor *)seq->private; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show"); @@ -1112,7 +1219,7 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) (u32) pr->performance->states[i].transition_latency); end: - return 0; + return_VALUE(0); } static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) @@ -1121,7 +1228,7 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) PDE(inode)->data); } -static int +static ssize_t acpi_processor_write_performance ( struct file *file, const char __user *buffer, @@ -1228,7 +1335,7 @@ acpi_processor_register_performance ( ACPI_FUNCTION_TRACE("acpi_processor_register_performance"); - if (!acpi_processor_ppc_is_init) + if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return_VALUE(-EINVAL); down(&performance_sem); @@ -1269,9 +1376,6 @@ acpi_processor_unregister_performance ( ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); - if (!acpi_processor_ppc_is_init) - return_VOID; - down(&performance_sem); pr = processors[cpu]; @@ -1837,7 +1941,7 @@ static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) pr->flags.limit ? "yes" : "no"); end: - return 0; + return_VALUE(0); } static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) @@ -1849,7 +1953,7 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file) static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = (struct acpi_processor *)seq->private; - int i = 0; + unsigned int i; ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show"); @@ -1858,9 +1962,11 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) seq_printf(seq, "active state: C%d\n" "default state: C%d\n" + "max_cstate: C%d\n" "bus master activity: %08x\n", pr->power.state, pr->power.default_state, + max_cstate, pr->power.bm_activity); seq_puts(seq, "states:\n"); @@ -1892,7 +1998,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) } end: - return 0; + return_VALUE(0); } static int acpi_processor_power_open_fs(struct inode *inode, struct file *file) @@ -1936,7 +2042,7 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset (pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0)); end: - return 0; + return_VALUE(0); } static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file) @@ -1997,7 +2103,7 @@ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) pr->limit.thermal.px, pr->limit.thermal.tx); end: - return 0; + return_VALUE(0); } static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file) @@ -2146,6 +2252,37 @@ acpi_processor_remove_fs ( return_VALUE(0); } +/* Use the acpiid in MADT to map cpus in case of SMP */ +#ifndef CONFIG_SMP +#define convert_acpiid_to_cpu(acpi_id) (0xff) +#else + +#ifdef CONFIG_IA64 +#define arch_acpiid_to_apicid ia64_acpiid_to_sapicid +#define arch_cpu_to_apicid ia64_cpu_to_sapicid +#define ARCH_BAD_APICID (0xffff) +#else +#define arch_acpiid_to_apicid x86_acpiid_to_apicid +#define arch_cpu_to_apicid x86_cpu_to_apicid +#define ARCH_BAD_APICID (0xff) +#endif + +static u8 convert_acpiid_to_cpu(u8 acpi_id) +{ + u16 apic_id; + int i; + + apic_id = arch_acpiid_to_apicid[acpi_id]; + if (apic_id == ARCH_BAD_APICID) + return -1; + + for (i = 0; i < NR_CPUS; i++) { + if (arch_cpu_to_apicid[i] == apic_id) + return i; + } + return -1; +} +#endif /* -------------------------------------------------------------------------- Driver Interface @@ -2158,7 +2295,8 @@ acpi_processor_get_info ( acpi_status status = 0; union acpi_object object = {0}; struct acpi_buffer buffer = {sizeof(union acpi_object), &object}; - static int cpu_index = 0; + u8 cpu_index; + static int cpu0_initialized; ACPI_FUNCTION_TRACE("acpi_processor_get_info"); @@ -2168,13 +2306,6 @@ acpi_processor_get_info ( if (num_online_cpus() > 1) errata.smp = TRUE; - /* - * Extra Processor objects may be enumerated on MP systems with - * less than the max # of CPUs. They should be ignored. - */ - if ((cpu_index + 1) > num_online_cpus()) - return_VALUE(-ENODEV); - acpi_processor_errata(pr); /* @@ -2206,9 +2337,27 @@ acpi_processor_get_info ( * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c */ - pr->id = cpu_index++; pr->acpi_id = object.processor.proc_id; + cpu_index = convert_acpiid_to_cpu(pr->acpi_id); + + if ( !cpu0_initialized && (cpu_index == 0xff)) { + /* Handle UP system running SMP kernel, with no LAPIC in MADT */ + cpu_index = 0; + } else if (cpu_index > num_online_cpus()) { + /* + * Extra Processor objects may be enumerated on MP systems with + * less than the max # of CPUs. They should be ignored. + */ + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error getting cpuindex for acpiid 0x%x\n", + pr->acpi_id)); + return_VALUE(-ENODEV); + } + cpu0_initialized = 1; + + pr->id = cpu_index; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, pr->acpi_id)); @@ -2234,7 +2383,6 @@ acpi_processor_get_info ( * (In particular, allocating the IO range for Cardbus) */ request_region(pr->throttling.address, 6, "ACPI CPU throttle"); - request_region(acpi_fadt.xpm_tmr_blk.address, 4, "ACPI timer"); } acpi_processor_get_power_info(pr); @@ -2330,22 +2478,28 @@ acpi_processor_add ( /* * Install the idle handler if processor power management is supported. - * Note that the default idle handler (default_idle) will be used on + * Note that we use previously set idle handler will be used on * platforms that only support C1. */ - if ((pr->id == 0) && (pr->flags.power)) { - pm_idle_save = pm_idle; - pm_idle = acpi_processor_idle; + if ((pr->flags.power) && (!boot_option_idle_override)) { + printk(KERN_INFO PREFIX "%s [%s] (supports", + acpi_device_name(device), acpi_device_bid(device)); + for (i = 1; i < ACPI_C_STATE_COUNT; i++) + if (pr->power.states[i].valid) + printk(" C%d", i); + printk(")\n"); + if (pr->id == 0) { + pm_idle_save = pm_idle; + pm_idle = acpi_processor_idle; + } } - printk(KERN_INFO PREFIX "%s [%s] (supports", - acpi_device_name(device), acpi_device_bid(device)); - for (i=1; ipower.states[i].valid) - printk(" C%d", i); - if (pr->flags.throttling) - printk(", %d throttling states", pr->throttling.state_count); - printk(")\n"); + if (pr->flags.throttling) { + printk(KERN_INFO PREFIX "%s [%s] (supports", + acpi_device_name(device), acpi_device_bid(device)); + printk(" %d throttling states", pr->throttling.state_count); + printk(")\n"); + } end: if (result) { @@ -2373,8 +2527,15 @@ acpi_processor_remove ( pr = (struct acpi_processor *) acpi_driver_data(device); /* Unregister the idle handler when processor #0 is removed. */ - if (pr->id == 0) + if (pr->id == 0) { pm_idle = pm_idle_save; + /* + * We are about to unload the current idle thread pm callback + * (pm_idle), Wait for all processors to update cached/local + * copies of pm_idle before proceeding. + */ + synchronize_kernel(); + } status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify); @@ -2392,6 +2553,38 @@ acpi_processor_remove ( return_VALUE(0); } +/* + * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. + * For now disable this. Probably a bug somewhere else. + * + * To skip this limit, boot/load with a large max_cstate limit. + */ +static int no_c2c3(struct dmi_system_id *id) +{ + if (max_cstate > ACPI_C_STATES_MAX) + return 0; + + printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." + " Override with \"processor.max_cstate=9\"\n", id->ident); + + max_cstate = 1; + + return 0; +} + +static struct dmi_system_id __initdata processor_dmi_table[] = { + { no_c2c3, "IBM ThinkPad R40e", { + DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), + DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, + { no_c2c3, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), + DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }}, + {}, +}; + +/* We keep the driver loaded even when ACPI is not running. + This is needed for the powernow-k8 driver, that works even without + ACPI, but needs symbols from this driver */ static int __init acpi_processor_init (void) @@ -2405,19 +2598,24 @@ acpi_processor_init (void) acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); if (!acpi_processor_dir) - return_VALUE(-ENODEV); + return_VALUE(0); acpi_processor_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&acpi_processor_driver); if (result < 0) { remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); - return_VALUE(-ENODEV); + return_VALUE(0); } acpi_thermal_cpufreq_init(); acpi_processor_ppc_init(); + dmi_check_system(processor_dmi_table); + + if (max_cstate < ACPI_C_STATES_MAX) + printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate); + return_VALUE(0); } @@ -2441,5 +2639,6 @@ acpi_processor_exit (void) module_init(acpi_processor_init); module_exit(acpi_processor_exit); +module_param_named(max_cstate, max_cstate, uint, 0); EXPORT_SYMBOL(acpi_processor_set_thermal_limit); diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile index 9916b6572..2130b7417 100644 --- a/drivers/acpi/resources/Makefile +++ b/drivers/acpi/resources/Makefile @@ -3,6 +3,8 @@ # obj-y := rsaddr.o rscreate.o rsio.o rslist.o rsmisc.o rsxface.o \ - rscalc.o rsdump.o rsirq.o rsmemory.o rsutils.o + rscalc.o rsirq.o rsmemory.o rsutils.o + +obj-$(ACPI_FUTURE_USAGE) += rsdump.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 299fc9376..3622852af 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -74,7 +74,6 @@ acpi_rs_get_byte_stream_length ( { acpi_size byte_stream_size_needed = 0; acpi_size segment_size; - struct acpi_resource_ext_irq *ex_irq = NULL; u8 done = FALSE; @@ -91,8 +90,8 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_IRQ: /* * IRQ Resource - * For an IRQ Resource, Byte 3, although optional, will - * always be created - it holds IRQ information. + * For an IRQ Resource, Byte 3, although optional, will always be + * created - it holds IRQ information. */ segment_size = 4; break; @@ -108,8 +107,8 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_START_DPF: /* * Start Dependent Functions Resource - * For a start_dependent_functions Resource, Byte 1, - * although optional, will always be created. + * For a start_dependent_functions Resource, Byte 1, although + * optional, will always be created. */ segment_size = 2; break; @@ -141,10 +140,9 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_VENDOR: /* * Vendor Defined Resource - * For a Vendor Specific resource, if the Length is - * between 1 and 7 it will be created as a Small - * Resource data type, otherwise it is a Large - * Resource data type. + * For a Vendor Specific resource, if the Length is between 1 and 7 + * it will be created as a Small Resource data type, otherwise it + * is a Large Resource data type. */ if (linked_list->data.vendor_specific.length > 7) { segment_size = 3; @@ -191,10 +189,9 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_ADDRESS16: /* * 16-Bit Address Resource - * The base size of this byte stream is 16. If a - * Resource Source string is not NULL, add 1 for - * the Index + the length of the null terminated - * string Resource Source + 1 for the null. + * The base size of this byte stream is 16. If a Resource Source + * string is not NULL, add 1 for the Index + the length of the null + * terminated string Resource Source + 1 for the null. */ segment_size = 16; @@ -223,10 +220,9 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_ADDRESS64: /* * 64-Bit Address Resource - * The base size of this byte stream is 46. If a Resource - * Source string is not NULL, add 1 for the Index + the - * length of the null terminated string Resource Source + - * 1 for the null. + * The base size of this byte stream is 46. If a resource_source + * string is not NULL, add 1 for the Index + the length of the null + * terminated string Resource Source + 1 for the null. */ segment_size = 46; @@ -239,9 +235,8 @@ acpi_rs_get_byte_stream_length ( case ACPI_RSTYPE_EXT_IRQ: /* * Extended IRQ Resource - * The base size of this byte stream is 9. This is for an - * Interrupt table length of 1. For each additional - * interrupt, add 4. + * The base size of this byte stream is 9. This is for an Interrupt + * table length of 1. For each additional interrupt, add 4. * If a Resource Source string is not NULL, add 1 for the * Index + the length of the null terminated string * Resource Source + 1 for the null. @@ -249,7 +244,7 @@ acpi_rs_get_byte_stream_length ( segment_size = 9 + (((acpi_size) linked_list->data.extended_irq.number_of_interrupts - 1) * 4); - if (ex_irq && ex_irq->resource_source.string_ptr) { + if (linked_list->data.extended_irq.resource_source.string_ptr) { segment_size += linked_list->data.extended_irq.resource_source.string_length; segment_size++; } @@ -257,8 +252,7 @@ acpi_rs_get_byte_stream_length ( default: /* - * If we get here, everything is out of sync, - * so exit with an error + * If we get here, everything is out of sync, exit with error */ return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); @@ -366,7 +360,6 @@ acpi_rs_get_list_length ( /* * 32-Bit Memory Range Resource */ - bytes_consumed = 20; structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32); @@ -395,14 +388,12 @@ acpi_rs_get_list_length ( bytes_consumed = temp16 + 3; /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 43, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 43, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. */ if (43 < temp16) { temp8 = (u8) (temp16 - 44); @@ -433,14 +424,12 @@ acpi_rs_get_list_length ( bytes_consumed = temp16 + 3; /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 23, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 23, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. */ if (23 < temp16) { temp8 = (u8) (temp16 - 24); @@ -471,14 +460,12 @@ acpi_rs_get_list_length ( bytes_consumed = temp16 + 3; /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 13, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 13, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. */ if (13 < temp16) { temp8 = (u8) (temp16 - 14); @@ -509,9 +496,8 @@ acpi_rs_get_list_length ( bytes_consumed = temp16 + 3; /* - * Point past the length field and the - * Interrupt vector flags to save off the - * Interrupt table length to the Temp8 variable. + * Point past the length field and the Interrupt vector flags to + * save off the Interrupt table length to the Temp8 variable. */ buffer += 3; temp8 = *buffer; @@ -523,14 +509,12 @@ acpi_rs_get_list_length ( additional_bytes = (u8) ((temp8 - 1) * 4); /* - * Resource Source Index and Resource Source are - * optional elements. Check the length of the - * Bytestream. If it is greater than 9, that - * means that an Index exists and is followed by - * a null termininated string. Therefore, set - * the temp variable to the length minus the minimum - * byte stream length plus the byte for the Index to - * determine the size of the NULL terminiated string. + * Resource Source Index and Resource Source are optional elements. + * Check the length of the Bytestream. If it is greater than 9, + * that means that an Index exists and is followed by a null + * terminated string. Therefore, set the temp variable to the + * length minus the minimum byte stream length plus the byte for + * the Index to determine the size of the NULL terminated string. */ if (9 + additional_bytes < temp16) { temp8 = (u8) (temp16 - (9 + additional_bytes)); @@ -565,9 +549,8 @@ acpi_rs_get_list_length ( bytes_consumed = 3; } - /* - * Point past the descriptor - */ + /* Point past the descriptor */ + ++buffer; /* @@ -595,9 +578,8 @@ acpi_rs_get_list_length ( buffer = byte_stream_buffer; bytes_consumed = 3; - /* - * Point past the descriptor - */ + /* Point past the descriptor */ + ++buffer; /* diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index eaf77c635..7588ce13a 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -175,7 +175,7 @@ acpi_rs_get_crs_method_data ( * and the contents of the callers buffer is undefined. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_rs_get_prs_method_data ( acpi_handle handle, @@ -210,6 +210,7 @@ acpi_rs_get_prs_method_data ( acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -289,6 +290,7 @@ acpi_rs_set_srs_method_data ( acpi_handle handle, struct acpi_buffer *in_buffer) { + struct acpi_parameter_info info; union acpi_operand_object *params[2]; acpi_status status; struct acpi_buffer buffer; @@ -329,10 +331,14 @@ acpi_rs_set_srs_method_data ( params[0]->common.flags = AOPOBJ_DATA_VALID; params[1] = NULL; + info.node = handle; + info.parameters = params; + info.parameter_type = ACPI_PARAM_ARGS; + /* * Execute the method, no return value */ - status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL); + status = acpi_ns_evaluate_relative ("_SRS", &info); /* * Clean up and return the status from acpi_ns_evaluate_relative diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 362f6252b..7e736ca81 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -156,6 +157,7 @@ acpi_get_current_resources ( status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_current_resources); /******************************************************************************* @@ -178,7 +180,7 @@ acpi_get_current_resources ( * and the value of ret_buffer is undefined. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_possible_resources ( acpi_handle device_handle, @@ -208,6 +210,8 @@ acpi_get_possible_resources ( status = acpi_rs_get_prs_method_data (device_handle, ret_buffer); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_possible_resources); +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -259,7 +263,8 @@ acpi_walk_resources ( /* Setup pointers */ resource = (struct acpi_resource *) buffer.pointer; - buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length); + buffer_end = ACPI_CAST_PTR (struct acpi_resource, + ((u8 *) buffer.pointer + buffer.length)); /* Walk the resource list */ @@ -309,6 +314,7 @@ cleanup: acpi_os_free (buffer.pointer); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_walk_resources); /******************************************************************************* @@ -353,6 +359,7 @@ acpi_set_current_resources ( status = acpi_rs_set_srs_method_data (device_handle, in_buffer); return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_set_current_resources); #define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field) @@ -426,3 +433,5 @@ acpi_resource_to_address64 ( return (AE_OK); } +EXPORT_SYMBOL(acpi_resource_to_address64); + diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index be148f489..da2e35c1d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -4,6 +4,7 @@ #include #include +#include #include #include /* for acpi_ex_eisa_id_to_string() */ @@ -23,7 +24,8 @@ extern struct acpi_device *acpi_root; #define ACPI_BUS_DEVICE_NAME "System Bus" static LIST_HEAD(acpi_device_list); -static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED; +spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED; +LIST_HEAD(acpi_wakeup_device_list); static void acpi_device_release(struct kobject * kobj) { @@ -115,9 +117,6 @@ acpi_bus_get_power_flags ( status = acpi_get_handle(device->handle, "_IRC", &handle); if (ACPI_SUCCESS(status)) device->power.flags.inrush_current = 1; - status = acpi_get_handle(device->handle, "_PRW", &handle); - if (ACPI_SUCCESS(status)) - device->power.flags.wake_capable = 1; /* * Enumerate supported power management states @@ -160,9 +159,130 @@ acpi_bus_get_power_flags ( device->power.state = ACPI_STATE_UNKNOWN; - return 0; + return_VALUE(0); +} + +int +acpi_match_ids ( + struct acpi_device *device, + char *ids) +{ + int error = 0; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + if (device->flags.hardware_id) + if (strstr(ids, device->pnp.hardware_id)) + goto Done; + + if (device->flags.compatible_ids) { + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + int i; + + /* compare multiple _CID entries against driver ids */ + for (i = 0; i < cid_list->count; i++) + { + if (strstr(ids, cid_list->id[i].value)) + goto Done; + } + } + error = -ENOENT; + + Done: + if (buffer.pointer) + acpi_os_free(buffer.pointer); + return error; +} + +static acpi_status +acpi_bus_extract_wakeup_device_power_package ( + struct acpi_device *device, + union acpi_object *package) +{ + int i = 0; + union acpi_object *element = NULL; + + if (!device || !package || (package->package.count < 2)) + return AE_BAD_PARAMETER; + + element = &(package->package.elements[0]); + if (!element) + return AE_BAD_PARAMETER; + if (element->type == ACPI_TYPE_PACKAGE) { + if ((element->package.count < 2) || + (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) || + (element->package.elements[1].type != ACPI_TYPE_INTEGER)) + return AE_BAD_DATA; + device->wakeup.gpe_device = element->package.elements[0].reference.handle; + device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value; + }else if (element->type == ACPI_TYPE_INTEGER) { + device->wakeup.gpe_number = element->integer.value; + }else + return AE_BAD_DATA; + + element = &(package->package.elements[1]); + if (element->type != ACPI_TYPE_INTEGER) { + return AE_BAD_DATA; + } + device->wakeup.sleep_state = element->integer.value; + + if ((package->package.count - 2) > ACPI_MAX_HANDLES) { + return AE_NO_MEMORY; + } + device->wakeup.resources.count = package->package.count - 2; + for (i=0; i < device->wakeup.resources.count; i++) { + element = &(package->package.elements[i + 2]); + if (element->type != ACPI_TYPE_ANY ) { + return AE_BAD_DATA; + } + + device->wakeup.resources.handles[i] = element->reference.handle; + } + + return AE_OK; } +static int +acpi_bus_get_wakeup_device_flags ( + struct acpi_device *device) +{ + acpi_status status = 0; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *package = NULL; + + ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags"); + + /* _PRW */ + status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRW\n")); + goto end; + } + + package = (union acpi_object *) buffer.pointer; + status = acpi_bus_extract_wakeup_device_power_package(device, package); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n")); + goto end; + } + + acpi_os_free(buffer.pointer); + + device->wakeup.flags.valid = 1; + /* Power button, Lid switch always enable wakeup*/ + if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E")) + device->wakeup.flags.run_wake = 1; + + /* TBD: lock */ + INIT_LIST_HEAD(&device->wakeup_list); + spin_lock(&acpi_device_lock); + list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); + spin_unlock(&acpi_device_lock); + +end: + if (ACPI_FAILURE(status)) + device->flags.wake_capable = 0; + return_VALUE(0); +} /* -------------------------------------------------------------------------- Performance Management @@ -195,30 +315,9 @@ acpi_bus_match ( struct acpi_device *device, struct acpi_driver *driver) { - int error = 0; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - - if (device->flags.hardware_id) - if (strstr(driver->ids, device->pnp.hardware_id)) - goto Done; - - if (device->flags.compatible_ids) { - struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; - int i; - - /* compare multiple _CID entries against driver ids */ - for (i = 0; i < cid_list->count; i++) - { - if (strstr(driver->ids, cid_list->id[i].value)) - goto Done; - } - } - error = -ENOENT; - - Done: - if (buffer.pointer) - acpi_os_free(buffer.pointer); - return error; + if (driver && driver->ops.match) + return driver->ops.match(device, driver); + return acpi_match_ids(device, driver->ids); } @@ -276,6 +375,7 @@ acpi_bus_driver_init ( static int acpi_driver_attach(struct acpi_driver * drv) { struct list_head * node, * next; + int count = 0; ACPI_FUNCTION_TRACE("acpi_driver_attach"); @@ -290,6 +390,7 @@ static int acpi_driver_attach(struct acpi_driver * drv) if (!acpi_bus_match(dev, drv)) { if (!acpi_bus_driver_init(dev, drv)) { atomic_inc(&drv->references); + count++; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", drv->name, dev->pnp.bus_id)); } @@ -297,7 +398,7 @@ static int acpi_driver_attach(struct acpi_driver * drv) spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); - return_VALUE(0); + return_VALUE(count); } static int acpi_driver_detach(struct acpi_driver * drv) @@ -328,29 +429,32 @@ static int acpi_driver_detach(struct acpi_driver * drv) * acpi_bus_register_driver * ------------------------ * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. + * devices that match the driver's criteria and binds. Returns the + * number of devices that were claimed by the driver, or a negative + * error status for failure. */ int acpi_bus_register_driver ( struct acpi_driver *driver) { - int error = 0; + int count; ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); if (acpi_disabled) return_VALUE(-ENODEV); - if (driver) { - spin_lock(&acpi_device_lock); - list_add_tail(&driver->node, &acpi_bus_drivers); - spin_unlock(&acpi_device_lock); - acpi_driver_attach(driver); - } else - error = -EINVAL; + if (!driver) + return_VALUE(-EINVAL); - return_VALUE(error); + spin_lock(&acpi_device_lock); + list_add_tail(&driver->node, &acpi_bus_drivers); + spin_unlock(&acpi_device_lock); + count = acpi_driver_attach(driver); + + return_VALUE(count); } +EXPORT_SYMBOL(acpi_bus_register_driver); /** @@ -379,6 +483,7 @@ acpi_bus_unregister_driver ( error = -EINVAL; return_VALUE(error); } +EXPORT_SYMBOL(acpi_bus_unregister_driver); /** * acpi_bus_find_driver @@ -395,9 +500,6 @@ acpi_bus_find_driver ( ACPI_FUNCTION_TRACE("acpi_bus_find_driver"); - if (!device->flags.hardware_id && !device->flags.compatible_ids) - goto Done; - spin_lock(&acpi_device_lock); list_for_each_safe(node,next,&acpi_bus_drivers) { struct acpi_driver * driver = container_of(node,struct acpi_driver,node); @@ -469,6 +571,11 @@ acpi_bus_get_flags ( if (ACPI_SUCCESS(status)) device->flags.power_manageable = 1; + /* Presence of _PRW indicates wake capable */ + status = acpi_get_handle(device->handle, "_PRW", &temp); + if (ACPI_SUCCESS(status)) + device->flags.wake_capable = 1; + /* TBD: Peformance management */ return_VALUE(0); @@ -657,7 +764,7 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, #endif /*CONFIG_ACPI_DEBUG_OUTPUT*/ } -static int +int acpi_bus_add ( struct acpi_device **child, struct acpi_device *parent, @@ -740,6 +847,16 @@ acpi_bus_add ( goto end; } + /* + * Wakeup device management + *----------------------- + */ + if (device->flags.wake_capable) { + result = acpi_bus_get_wakeup_device_flags(device); + if (result) + goto end; + } + /* * Performance Management * ---------------------- @@ -791,7 +908,7 @@ end: return_VALUE(result); } - +EXPORT_SYMBOL(acpi_bus_add); static int acpi_bus_scan (struct acpi_device *start) @@ -895,6 +1012,7 @@ static int acpi_bus_scan (struct acpi_device *start) return_VALUE(0); } +EXPORT_SYMBOL(acpi_bus_scan); static int diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile index 975d03d59..d6c017709 100644 --- a/drivers/acpi/sleep/Makefile +++ b/drivers/acpi/sleep/Makefile @@ -1,4 +1,4 @@ -obj-y := poweroff.o +obj-y := poweroff.o wakeup.o obj-$(CONFIG_ACPI_SLEEP) += main.o obj-$(CONFIG_ACPI_SLEEP_PROC_FS) += proc.o diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c7b17e7fa..4cd42eadb 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -1,6 +1,7 @@ /* * sleep.c - ACPI sleep support. * + * Copyright (c) 2004 David Shaohua Li * Copyright (c) 2000-2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Lab * @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include "sleep.h" @@ -35,16 +37,16 @@ static int init_8259A_after_S1; /** * acpi_pm_prepare - Do preliminary suspend work. - * @state: suspend state we're entering. + * @pm_state: suspend state we're entering. * * Make sure we support the state. If we do, and we need it, set the * firmware waking vector and do arch-specific nastiness to get the * wakeup code to the waking vector. */ -static int acpi_pm_prepare(u32 state) +static int acpi_pm_prepare(suspend_state_t pm_state) { - u32 acpi_state = acpi_suspend_states[state]; + u32 acpi_state = acpi_suspend_states[pm_state]; if (!sleep_states[acpi_state]) return -EPERM; @@ -52,13 +54,15 @@ static int acpi_pm_prepare(u32 state) /* do we have a wakeup address for S2 and S3? */ /* Here, we support only S4BIOS, those we set the wakeup address */ /* S4OS is only supported for now via swsusp.. */ - if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_DISK) { + if (pm_state == PM_SUSPEND_MEM || pm_state == PM_SUSPEND_DISK) { if (!acpi_wakeup_address) return -EFAULT; acpi_set_firmware_waking_vector( - (acpi_physical_address) acpi_wakeup_address); + (acpi_physical_address) virt_to_phys( + (void *)acpi_wakeup_address)); } ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); acpi_enter_sleep_state_prep(acpi_state); return 0; } @@ -66,23 +70,23 @@ static int acpi_pm_prepare(u32 state) /** * acpi_pm_enter - Actually enter a sleep state. - * @state: State we're entering. + * @pm_state: State we're entering. * * Flush caches and go to sleep. For STR or STD, we have to call * arch-specific assembly, which in turn call acpi_enter_sleep_state(). * It's unfortunate, but it works. Please fix if you're feeling frisky. */ -static int acpi_pm_enter(u32 state) +static int acpi_pm_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; unsigned long flags = 0; - u32 acpi_state = acpi_suspend_states[state]; + u32 acpi_state = acpi_suspend_states[pm_state]; ACPI_FLUSH_CPU_CACHE(); /* Do arch specific saving of state. */ - if (state > PM_SUSPEND_STANDBY) { + if (pm_state > PM_SUSPEND_STANDBY) { int error = acpi_save_state_mem(); if (error) return error; @@ -90,7 +94,8 @@ static int acpi_pm_enter(u32 state) local_irq_save(flags); - switch (state) + acpi_enable_wakeup_device(acpi_state); + switch (pm_state) { case PM_SUSPEND_STANDBY: barrier(); @@ -118,7 +123,7 @@ static int acpi_pm_enter(u32 state) * And, in the case of the latter, the memory image should have already * been loaded from disk. */ - if (state > PM_SUSPEND_STANDBY) + if (pm_state > PM_SUSPEND_STANDBY) acpi_restore_state_mem(); @@ -128,15 +133,18 @@ static int acpi_pm_enter(u32 state) /** * acpi_pm_finish - Finish up suspend sequence. - * @state: State we're coming out of. + * @pm_state: State we're coming out of. * * This is called after we wake back up (or if entering the sleep state * failed). */ -static int acpi_pm_finish(u32 state) +static int acpi_pm_finish(suspend_state_t pm_state) { - acpi_leave_sleep_state(state); + u32 acpi_state = acpi_suspend_states[pm_state]; + + acpi_leave_sleep_state(acpi_state); + acpi_disable_wakeup_device(acpi_state); /* reset firmware waking vector */ acpi_set_firmware_waking_vector((acpi_physical_address) 0); @@ -199,7 +207,7 @@ static int __init acpi_sleep_init(void) return 0; printk(KERN_INFO PREFIX "(supports"); - for (i=0; i #include #include +#include "sleep.h" static void acpi_power_off (void) @@ -16,6 +17,7 @@ acpi_power_off (void) printk("%s called\n",__FUNCTION__); /* Some SMP machines only can poweroff in boot CPU */ set_cpus_allowed(current, cpumask_of_cpu(0)); + acpi_wakeup_gpe_poweroff_prepare(); acpi_enter_sleep_state_prep(ACPI_STATE_S5); ACPI_DISABLE_IRQS(); acpi_enter_sleep_state(ACPI_STATE_S5); diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 7eb206096..a94d946e1 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -15,6 +15,7 @@ #define ACPI_SYSTEM_FILE_SLEEP "sleep" #define ACPI_SYSTEM_FILE_ALARM "alarm" +#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE "wakeup" #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME ("sleep") @@ -69,7 +70,7 @@ acpi_system_write_sleep ( state = simple_strtoul(str, NULL, 0); #ifdef CONFIG_SOFTWARE_SUSPEND if (state == 4) { - software_suspend(); + error = software_suspend(); goto Done; } #endif @@ -352,6 +353,84 @@ end: return_VALUE(result ? result : count); } +extern struct list_head acpi_wakeup_device_list; +extern spinlock_t acpi_device_lock; + +static int +acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) +{ + struct list_head * node, * next; + + seq_printf(seq, "Device Sleep state Status\n"); + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list); + + if (!dev->wakeup.flags.valid) + continue; + spin_unlock(&acpi_device_lock); + if (dev->wakeup.flags.run_wake) + seq_printf(seq, "%4s %4d %8s\n", + dev->pnp.bus_id, (u32) dev->wakeup.sleep_state, + dev->wakeup.state.enabled ? "*enabled" : "*disabled"); + else + seq_printf(seq, "%4s %4d %8s\n", + dev->pnp.bus_id, (u32) dev->wakeup.sleep_state, + dev->wakeup.state.enabled ? "enabled" : "disabled"); + spin_lock(&acpi_device_lock); + } + spin_unlock(&acpi_device_lock); + return 0; +} + +static ssize_t +acpi_system_write_wakeup_device ( + struct file *file, + const char __user *buffer, + size_t count, + loff_t *ppos) +{ + struct list_head * node, * next; + char strbuf[5]; + char str[5] = ""; + int len = count; + + if (len > 4) len = 4; + + if (copy_from_user(strbuf, buffer, len)) + return -EFAULT; + strbuf[len] = '\0'; + sscanf(strbuf, "%s", str); + + spin_lock(&acpi_device_lock); + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list); + if (!dev->wakeup.flags.valid) + continue; + + if (!strncmp(dev->pnp.bus_id, str, 4)) { + dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1; + break; + } + } + spin_unlock(&acpi_device_lock); + return count; +} + +static int +acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data); +} + +static struct file_operations acpi_system_wakeup_device_fops = { + .open = acpi_system_wakeup_device_open_fs, + .read = seq_read, + .write = acpi_system_write_wakeup_device, + .llseek = seq_lseek, + .release = single_release, +}; static struct file_operations acpi_system_sleep_fops = { .open = acpi_system_sleep_open_fs, @@ -388,6 +467,13 @@ static int acpi_sleep_proc_init(void) S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); if (entry) entry->proc_fops = &acpi_system_alarm_fops; + + /* 'wakeup device' [R/W]*/ + entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE, + S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir); + if (entry) + entry->proc_fops = &acpi_system_wakeup_device_fops; + return 0; } diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index ad38f4153..efd0001c6 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h @@ -2,3 +2,7 @@ extern u8 sleep_states[]; extern int acpi_suspend (u32 state); +extern void acpi_enable_wakeup_device_prep(u8 sleep_state); +extern void acpi_enable_wakeup_device(u8 sleep_state); +extern void acpi_disable_wakeup_device(u8 sleep_state); +extern void acpi_wakeup_gpe_poweroff_prepare(void); diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 9c004b948..d9b199969 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -1,5 +1,6 @@ /* * wakeup.c - support wakeup devices + * Copyright (C) 2004 Li Shaohua */ #include @@ -13,14 +14,16 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME ("wakeup_devices") +extern struct list_head acpi_wakeup_device_list; +extern spinlock_t acpi_device_lock; + +#ifdef CONFIG_ACPI_SLEEP /** * acpi_enable_wakeup_device_prep - prepare wakeup devices * @sleep_state: ACPI state * Enable all wakup devices power if the devices' wakeup level * is higher than requested sleep level */ -extern struct list_head acpi_wakeup_device_list; -extern spinlock_t acpi_device_lock; void acpi_enable_wakeup_device_prep( @@ -179,3 +182,28 @@ static int __init acpi_wakeup_device_init(void) } late_initcall(acpi_wakeup_device_init); +#endif + +/* + * Disable all wakeup GPEs before power off. + * + * Since acpi_enter_sleep_state() will disable all + * RUNTIME GPEs, we simply mark all GPES that + * are not enabled for wakeup from S5 as RUNTIME. + */ +void acpi_wakeup_gpe_poweroff_prepare(void) +{ + struct list_head * node, * next; + + list_for_each_safe(node, next, &acpi_wakeup_device_list) { + struct acpi_device * dev = container_of(node, + struct acpi_device, wakeup_list); + + /* The GPE can wakeup system from S5, don't touch it */ + if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5) + continue; + /* acpi_set_gpe_type will automatically disable GPE */ + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME); + } +} diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 9919e76d7..8925a6ca5 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -24,6 +24,7 @@ */ #include +#include #include #include @@ -48,35 +49,26 @@ extern FADT_DESCRIPTOR acpi_fadt; -------------------------------------------------------------------------- */ static int -acpi_system_read_info ( - char *page, - char **start, - off_t off, - int count, - int *eof, - void *data) +acpi_system_read_info (struct seq_file *seq, void *offset) { - char *p = page; - int size = 0; - ACPI_FUNCTION_TRACE("acpi_system_read_info"); - if (off != 0) - goto end; - - p += sprintf(p, "version: %x\n", ACPI_CA_VERSION); - -end: - size = (p - page); - if (size <= off+count) *eof = 1; - *start = page + off; - size -= off; - if (size>count) size = count; - if (size<0) size = 0; + seq_printf(seq, "version: %x\n", ACPI_CA_VERSION); + return_VALUE(0); +} - return_VALUE(size); +static int acpi_system_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_system_read_info, PDE(inode)->data); } +static struct file_operations acpi_system_info_ops = { + .open = acpi_system_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static ssize_t acpi_system_read_dsdt (struct file*, char __user *, size_t, loff_t*); static struct file_operations acpi_system_dsdt_ops = { @@ -152,10 +144,13 @@ static int __init acpi_system_init (void) /* 'info' [R] */ name = ACPI_SYSTEM_FILE_INFO; - entry = create_proc_read_entry(name, - S_IRUGO, acpi_root_dir, acpi_system_read_info,NULL); + entry = create_proc_entry(name, + S_IRUGO, acpi_root_dir); if (!entry) goto Error; + else { + entry->proc_fops = &acpi_system_info_ops; + } /* 'dsdt' [R] */ name = ACPI_SYSTEM_FILE_DSDT; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index e7480822b..fb64bd5d2 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -101,7 +101,7 @@ acpi_table_print ( else name = header->signature; - printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", + printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name, header->revision, header->oem_id, header->oem_table_id, header->oem_revision, header->asl_compiler_id, header->asl_compiler_revision, @@ -587,7 +587,7 @@ acpi_table_init (void) return -ENODEV; } - printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", + printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n", rsdp->revision, rsdp->oem_id, (void *) rsdp_phys); if (rsdp->revision < 2) diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index ee6818832..65a90b3c8 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -50,6 +51,9 @@ ACPI_MODULE_NAME ("tbconvrt") +u8 acpi_fadt_is_v1; +EXPORT_SYMBOL(acpi_fadt_is_v1); + /******************************************************************************* * * FUNCTION: acpi_tb_get_table_count @@ -212,6 +216,7 @@ acpi_tb_convert_fadt1 ( /* ACPI 1.0 FACS */ /* The BIOS stored FADT should agree with Revision 1.0 */ + acpi_fadt_is_v1 = 1; /* * Copy the table header and the common part of the tables. @@ -240,9 +245,12 @@ acpi_tb_convert_fadt1 ( /* * Processor Performance State Control. This is the value OSPM writes to * the SMI_CMD register to assume processor performance state control - * responsibility. There isn't any equivalence in 1.0, leave it zeroed. + * responsibility. There isn't any equivalence in 1.0, but as many 1.x + * ACPI tables contain _PCT and _PSS we also keep this value, unless + * acpi_strict is set. */ - local_fadt->pstate_cnt = 0; + if (acpi_strict) + local_fadt->pstate_cnt = 0; /* * Support for the _CST object and C States change notification. @@ -251,10 +259,26 @@ acpi_tb_convert_fadt1 ( local_fadt->cst_cnt = 0; /* - * Since there isn't any equivalence in 1.0 and since it highly likely - * that a 1.0 system has legacy support. + * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. + * It primarily adds the FADT reset mechanism. */ - local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; + if ((original_fadt->revision == 2) && + (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) { + /* + * Grab the entire generic address struct, plus the 1-byte reset value + * that immediately follows. + */ + ACPI_MEMCPY (&local_fadt->reset_register, + &((struct fadt_descriptor_rev2_minus *) original_fadt)->reset_register, + sizeof (struct acpi_generic_address) + 1); + } + else { + /* + * Since there isn't any equivalence in 1.0 and since it is highly + * likely that a 1.0 system has legacy support. + */ + local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; + } /* * Convert the V1.0 block addresses to V2.0 GAS structures @@ -418,23 +442,21 @@ acpi_tb_convert_table_fadt (void) /* - * acpi_gbl_FADT is valid - * Allocate and zero the 2.0 FADT buffer - */ - local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2)); - if (local_fadt == NULL) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* - * FADT length and version validation. The table must be at least as - * long as the version 1.0 FADT + * acpi_gbl_FADT is valid. Validate the FADT length. The table must be + * at least as long as the version 1.0 FADT */ if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) { - ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT->length)); + ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n", acpi_gbl_FADT->length)); return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } + /* Allocate buffer for the ACPI 2.0(+) FADT */ + + local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2)); + if (!local_fadt) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) { /* Length is too short to be a V2.0 table */ diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 1456c7b32..537942444 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -167,6 +167,9 @@ acpi_tb_get_table_header ( return_ACPI_STATUS (AE_BAD_PARAMETER); } + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n", + return_header->signature)); + return_ACPI_STATUS (AE_OK); } diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 79efa36b7..83d07834a 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -266,9 +266,10 @@ acpi_tb_init_table_descriptor ( if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed - * at this location, so return an error. + * at this location, so return an error. */ if (list_head->next) { + ACPI_MEM_FREE (table_desc); return_ACPI_STATUS (AE_ALREADY_EXISTS); } diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index fef603f40..ac9451d9c 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -62,7 +62,7 @@ * return a pointer to that table descriptor. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE acpi_status acpi_tb_handle_to_object ( u16 table_id, @@ -90,6 +90,7 @@ acpi_tb_handle_to_object ( ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id)); return (AE_BAD_PARAMETER); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index c92e71508..1cce360b6 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -42,6 +42,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -137,6 +138,8 @@ error_exit: } +#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_load_table @@ -343,6 +346,8 @@ acpi_get_table_header ( } +#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_get_table @@ -439,5 +444,5 @@ acpi_get_table ( ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length); return_ACPI_STATUS (AE_OK); } - +EXPORT_SYMBOL(acpi_get_table); diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index b7328345d..b92693c48 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -87,12 +88,28 @@ acpi_tb_find_table ( return_ACPI_STATUS (AE_AML_STRING_LIMIT); } - /* Find the table */ + if (!ACPI_STRNCMP (signature, DSDT_SIG, ACPI_NAME_SIZE)) { + /* + * The DSDT pointer is contained in the FADT, not the RSDT. + * This code should suffice, because the only code that would perform + * a "find" on the DSDT is the data_table_region() AML opcode -- in + * which case, the DSDT is guaranteed to be already loaded. + * If this becomes insufficient, the FADT will have to be found first. + */ + if (!acpi_gbl_DSDT) { + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } - status = acpi_get_firmware_table (signature, 1, - ACPI_LOGICAL_ADDRESSING, &table); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + table = acpi_gbl_DSDT; + } + else { + /* Find the table */ + + status = acpi_get_firmware_table (signature, 1, + ACPI_LOGICAL_ADDRESSING, &table); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } } /* Check oem_id and oem_table_id */ @@ -102,6 +119,7 @@ acpi_tb_find_table ( return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND); } + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n", table->signature)); *table_ptr = table; return_ACPI_STATUS (AE_OK); } @@ -115,17 +133,14 @@ acpi_tb_find_table ( * Instance - the non zero instance of the table, allows * support for multiple tables of the same type * Flags - Physical/Virtual support - * ret_buffer - pointer to a structure containing a buffer to - * receive the table + * table_pointer - Where a buffer containing the table is + * returned * * RETURN: Status * - * DESCRIPTION: This function is called to get an ACPI table. The caller - * supplies an out_buffer large enough to contain the entire ACPI - * table. Upon completion - * the out_buffer->Length field will indicate the number of bytes - * copied into the out_buffer->buf_ptr buffer. This table will be - * a complete table including the header. + * DESCRIPTION: This function is called to get an ACPI table. A buffer is + * allocated for the table and returned in table_pointer. + * This table will be a complete table including the header. * ******************************************************************************/ @@ -136,12 +151,11 @@ acpi_get_firmware_table ( u32 flags, struct acpi_table_header **table_pointer) { - struct acpi_pointer rsdp_address; - struct acpi_pointer address; acpi_status status; - struct acpi_table_header header; - struct acpi_table_desc table_info; - struct acpi_table_desc rsdt_info; + struct acpi_pointer address; + struct acpi_table_header *header = NULL; + struct acpi_table_desc *table_info = NULL; + struct acpi_table_desc *rsdt_info; u32 table_count; u32 i; u32 j; @@ -152,45 +166,41 @@ acpi_get_firmware_table ( /* * Ensure that at least the table manager is initialized. We don't - * require that the entire ACPI subsystem is up for this interface + * require that the entire ACPI subsystem is up for this interface. + * If we have a buffer, we must have a length too */ - - /* - * If we have a buffer, we must have a length too - */ - if ((instance == 0) || - (!signature) || + if ((instance == 0) || + (!signature) || (!table_pointer)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - rsdt_info.pointer = NULL; + /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { /* Get the RSDP */ - status = acpi_os_get_root_pointer (flags, &rsdp_address); + status = acpi_os_get_root_pointer (flags, &address); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { - status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor), + status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor), (void *) &acpi_gbl_RSDP); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } else { - acpi_gbl_RSDP = rsdp_address.pointer.logical; + acpi_gbl_RSDP = address.pointer.logical; } - /* - * The signature and checksum must both be correct - */ + /* The signature and checksum must both be correct */ + if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { /* Nope, BAD Signature */ @@ -204,10 +214,9 @@ acpi_get_firmware_table ( } } - /* Get the RSDT and validate it */ + /* Get the RSDT address via the RSDP */ acpi_tb_get_rsdt_address (&address); - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, @@ -217,20 +226,40 @@ acpi_get_firmware_table ( address.pointer_type |= flags; - status = acpi_tb_get_table (&address, &rsdt_info); + /* Get and validate the RSDT */ + + rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); + if (!rsdt_info) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + status = acpi_tb_get_table (&address, rsdt_info); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup; } - status = acpi_tb_validate_rsdt (rsdt_info.pointer); + status = acpi_tb_validate_rsdt (rsdt_info->pointer); if (ACPI_FAILURE (status)) { goto cleanup; } - /* Get the number of table pointers within the RSDT */ + /* Allocate a scratch table header and table descriptor */ + + header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header)); + if (!header) { + status = AE_NO_MEMORY; + goto cleanup; + } - table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer); + table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc)); + if (!table_info) { + status = AE_NO_MEMORY; + goto cleanup; + } + /* Get the number of table pointers within the RSDT */ + + table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* @@ -241,35 +270,36 @@ acpi_get_firmware_table ( /* Get the next table pointer, handle RSDT vs. XSDT */ if (acpi_gbl_RSDP->revision < 2) { - address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i]; + address.pointer.value = (ACPI_CAST_PTR ( + RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } else { - address.pointer.value = - (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i]; + address.pointer.value = (ACPI_CAST_PTR ( + XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } /* Get the table header */ - status = acpi_tb_get_table_header (&address, &header); + status = acpi_tb_get_table_header (&address, header); if (ACPI_FAILURE (status)) { goto cleanup; } /* Compare table signatures and table instance */ - if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { + if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ - status = acpi_tb_get_table_body (&address, &header, &table_info); + status = acpi_tb_get_table_body (&address, header, table_info); if (ACPI_FAILURE (status)) { goto cleanup; } - *table_pointer = table_info.pointer; + *table_pointer = table_info->pointer; goto cleanup; } } @@ -281,9 +311,18 @@ acpi_get_firmware_table ( cleanup: - acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length); + acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); + ACPI_MEM_FREE (rsdt_info); + + if (header) { + ACPI_MEM_FREE (header); + } + if (table_info) { + ACPI_MEM_FREE (table_info); + } return_ACPI_STATUS (status); } +EXPORT_SYMBOL(acpi_get_firmware_table); /* TBD: Move to a new file */ @@ -389,14 +428,17 @@ acpi_tb_scan_memory_for_rsdp ( * Flags - Current memory mode (logical vs. * physical addressing) * - * RETURN: Status + * RETURN: Status, RSDP physical address * * 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). + * NOTE1: The RSDp must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) + * Only a 32-bit physical address is necessary. + * + * NOTE2: This function is always available, regardless of the + * initialization state of the rest of ACPI. * ******************************************************************************/ @@ -407,8 +449,8 @@ acpi_tb_find_rsdp ( { u8 *table_ptr; u8 *mem_rover; - u64 phys_addr; - acpi_status status = AE_OK; + u32 physical_address; + acpi_status status; ACPI_FUNCTION_TRACE ("tb_find_rsdp"); @@ -419,36 +461,57 @@ acpi_tb_find_rsdp ( */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { /* - * 1) Search EBDA (low memory) paragraphs + * 1a) Get the location of the EBDA */ - status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE, + status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION, + ACPI_EBDA_PTR_LENGTH, (void *) &table_ptr); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", - ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n", + ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); return_ACPI_STATUS (status); } - mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE); - acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE); + ACPI_MOVE_16_TO_32 (&physical_address, table_ptr); + physical_address <<= 4; /* Convert segment to physical address */ + acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH); - if (mem_rover) { - /* Found it, return the physical address */ + /* EBDA present? */ - phys_addr = ACPI_LO_RSDP_WINDOW_BASE; - phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr); + if (physical_address > 0x400) { + /* + * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length) + */ + status = acpi_os_map_memory ((acpi_physical_address) physical_address, + ACPI_EBDA_WINDOW_SIZE, + (void *) &table_ptr); + if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n", + physical_address, ACPI_EBDA_WINDOW_SIZE)); + return_ACPI_STATUS (status); + } - table_info->physical_address = phys_addr; - return_ACPI_STATUS (AE_OK); + mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE); + acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE); + + if (mem_rover) { + /* Found it, return the physical address */ + + physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr); + + table_info->physical_address = (acpi_physical_address) physical_address; + return_ACPI_STATUS (AE_OK); + } } /* - * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ - status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE, + status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE, + ACPI_HI_RSDP_WINDOW_SIZE, (void *) &table_ptr); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (status); } @@ -459,10 +522,9 @@ acpi_tb_find_rsdp ( if (mem_rover) { /* Found it, return the physical address */ - phys_addr = ACPI_HI_RSDP_WINDOW_BASE; - phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr); + physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr); - table_info->physical_address = phys_addr; + table_info->physical_address = (acpi_physical_address) physical_address; return_ACPI_STATUS (AE_OK); } } @@ -472,19 +534,29 @@ acpi_tb_find_rsdp ( */ else { /* - * 1) Search EBDA (low memory) paragraphs + * 1a) Get the location of the EBDA */ - mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE), - ACPI_LO_RSDP_WINDOW_SIZE); - if (mem_rover) { - /* Found it, return the physical address */ - - table_info->physical_address = ACPI_TO_INTEGER (mem_rover); - return_ACPI_STATUS (AE_OK); + ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION); + physical_address <<= 4; /* Convert segment to physical address */ + + /* EBDA present? */ + + if (physical_address > 0x400) { + /* + * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length) + */ + mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address), + ACPI_EBDA_WINDOW_SIZE); + if (mem_rover) { + /* Found it, return the physical address */ + + table_info->physical_address = ACPI_TO_INTEGER (mem_rover); + return_ACPI_STATUS (AE_OK); + } } /* - * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE), ACPI_HI_RSDP_WINDOW_SIZE); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 7b94ac081..e6d077ab4 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -60,6 +60,7 @@ #define ACPI_THERMAL_NOTIFY_HOT 0xF1 #define ACPI_THERMAL_MODE_ACTIVE 0x00 #define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_MODE_CRITICAL 0xff #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" #define ACPI_THERMAL_MAX_ACTIVE 10 @@ -75,7 +76,7 @@ MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); MODULE_LICENSE("GPL"); static int tzp; -MODULE_PARM(tzp, "i"); +module_param(tzp, int, 0); MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); @@ -160,6 +161,7 @@ struct acpi_thermal { unsigned long last_temperature; unsigned long polling_frequency; u8 cooling_mode; + volatile u8 zombie; struct acpi_thermal_flags flags; struct acpi_thermal_state state; struct acpi_thermal_trips trips; @@ -224,7 +226,7 @@ acpi_thermal_get_temperature ( status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature); if (ACPI_FAILURE(status)) - return -ENODEV; + return_VALUE(-ENODEV); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature)); @@ -289,13 +291,6 @@ acpi_thermal_set_cooling_mode ( status = acpi_get_handle(tz->handle, "_SCP", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); - status = acpi_get_handle(tz->handle, "_PSV", &handle); - if(!ACPI_FAILURE(status)) { - tz->cooling_mode = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", - mode?"passive":"active")); - return_VALUE(0); - } return_VALUE(-ENODEV); } @@ -333,7 +328,7 @@ acpi_thermal_get_trip_points ( if (ACPI_FAILURE(status)) { tz->trips.critical.flags.valid = 0; ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n")); - return -ENODEV; + return_VALUE(-ENODEV); } else { tz->trips.critical.flags.valid = 1; @@ -653,7 +648,10 @@ static void acpi_thermal_run ( unsigned long data) { - acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_thermal_check, (void *) data); + struct acpi_thermal *tz = (struct acpi_thermal *)data; + if (!tz->zombie) + acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_thermal_check, (void *) data); } @@ -665,7 +663,7 @@ acpi_thermal_check ( struct acpi_thermal *tz = (struct acpi_thermal *) data; unsigned long sleep_time = 0; int i = 0; - struct acpi_thermal_state state = tz->state; + struct acpi_thermal_state state; ACPI_FUNCTION_TRACE("acpi_thermal_check"); @@ -674,6 +672,8 @@ acpi_thermal_check ( return_VOID; } + state = tz->state; + result = acpi_thermal_get_temperature(tz); if (result) return_VOID; @@ -801,7 +801,7 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) } end: - return 0; + return_VALUE(0); } static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) @@ -828,7 +828,7 @@ static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) KELVIN_TO_CELSIUS(tz->temperature)); end: - return 0; + return_VALUE(0); } static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) @@ -881,7 +881,7 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) } end: - return 0; + return_VALUE(0); } static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) @@ -899,8 +899,10 @@ acpi_thermal_write_trip_points ( struct seq_file *m = (struct seq_file *)file->private_data; struct acpi_thermal *tz = (struct acpi_thermal *)m->private; - char limit_string[25] = {'\0'}; - int critical, hot, passive, active0, active1; + char limit_string[65] = {'\0'}; + int num, critical, hot, passive; + int active[ACPI_THERMAL_MAX_ACTIVE]; + int i = 0; ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points"); @@ -916,7 +918,11 @@ acpi_thermal_write_trip_points ( limit_string[count] = '\0'; - if (sscanf(limit_string, "%d:%d:%d:%d:%d", &critical, &hot, &passive, &active0, &active1) != 5) { + num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &critical, &hot, &passive, + &active[0], &active[1], &active[2], &active[3], &active[4], + &active[5], &active[6], &active[7], &active[8], &active[9]); + if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); return_VALUE(-EINVAL); } @@ -924,8 +930,11 @@ acpi_thermal_write_trip_points ( tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical); tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot); tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive); - tz->trips.active[0].temperature = CELSIUS_TO_KELVIN(active0); - tz->trips.active[1].temperature = CELSIUS_TO_KELVIN(active1); + for (i = 0; i < num - 3; i++) { + if (!(tz->trips.active[i].flags.valid)) + break; + tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]); + } return_VALUE(count); } @@ -941,15 +950,17 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) goto end; if (!tz->flags.cooling_mode) { - seq_puts(seq, "\n"); - goto end; + seq_puts(seq, "\n"); } - seq_printf(seq, "cooling mode: %s\n", - tz->cooling_mode?"passive":"active"); + if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL ) + seq_printf(seq, "cooling mode: critical\n"); + else + seq_printf(seq, "cooling mode: %s\n", + tz->cooling_mode?"passive":"active"); end: - return 0; + return_VALUE(0); } static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) @@ -988,6 +999,8 @@ acpi_thermal_write_cooling_mode ( if (result) return_VALUE(result); + acpi_thermal_check(tz); + return_VALUE(count); } @@ -1010,7 +1023,7 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) (tz->polling_frequency / 10)); end: - return 0; + return_VALUE(0); } static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) @@ -1225,16 +1238,34 @@ acpi_thermal_get_info ( if (result) return_VALUE(result); - /* Set the cooling mode [_SCP] to active cooling (default) */ - result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); - if (!result) - tz->flags.cooling_mode = 1; - /* Get trip points [_CRT, _PSV, etc.] (required) */ result = acpi_thermal_get_trip_points(tz); if (result) return_VALUE(result); + /* Set the cooling mode [_SCP] to active cooling (default) */ + result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); + if (!result) + tz->flags.cooling_mode = 1; + else { + /* Oh,we have not _SCP method. + Generally show cooling_mode by _ACx, _PSV,spec 12.2*/ + tz->flags.cooling_mode = 0; + if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) { + if ( tz->trips.passive.temperature > tz->trips.active[0].temperature ) + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + else + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) { + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) { + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + } else { + /* _ACx and _PSV are optional, but _CRT is required */ + tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL; + } + } + /* Get default polling frequency [_TZP] (optional) */ if (tzp) tz->polling_frequency = tzp; @@ -1324,8 +1355,14 @@ acpi_thermal_remove ( tz = (struct acpi_thermal *) acpi_driver_data(device); - if (timer_pending(&(tz->timer))) - del_timer(&(tz->timer)); + /* avoid timer adding new defer task */ + tz->zombie = 1; + /* wait for running timer (on other CPUs) finish */ + del_timer_sync(&(tz->timer)); + /* synchronize deferred task */ + acpi_os_wait_events_complete(NULL); + /* deferred task may reinsert timer */ + del_timer_sync(&(tz->timer)); status = acpi_remove_notify_handler(tz->handle, ACPI_DEVICE_NOTIFY, acpi_thermal_notify); @@ -1347,6 +1384,7 @@ acpi_thermal_remove ( acpi_thermal_remove_fs(device); + kfree(tz); return_VALUE(0); } diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 2050d238d..1fe884739 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -259,13 +259,13 @@ acpi_ut_validate_buffer ( * * FUNCTION: acpi_ut_initialize_buffer * - * PARAMETERS: required_length - Length needed - * Buffer - Buffer to be validated + * PARAMETERS: Buffer - Buffer to be validated + * required_length - Length needed * * RETURN: Status * * DESCRIPTION: Validate that the buffer is of the required length or - * allocate a new buffer. + * allocate a new buffer. Returned buffer is always zeroed. * ******************************************************************************/ @@ -305,24 +305,25 @@ acpi_ut_initialize_buffer ( /* Allocate a new buffer with local interface to allow tracking */ - buffer->pointer = ACPI_MEM_ALLOCATE (required_length); + buffer->pointer = ACPI_MEM_CALLOCATE (required_length); if (!buffer->pointer) { return (AE_NO_MEMORY); } - - /* Clear the buffer */ - - ACPI_MEMSET (buffer->pointer, 0, required_length); break; default: - /* Validate the size of the buffer */ + /* Existing buffer: Validate the size of the buffer */ if (buffer->length < required_length) { status = AE_BUFFER_OVERFLOW; + break; } + + /* Clear the buffer */ + + ACPI_MEMSET (buffer->pointer, 0, required_length); break; } @@ -472,7 +473,7 @@ acpi_ut_allocate_and_track ( acpi_status status; - allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_block), component, + allocation = acpi_ut_allocate (size + sizeof (struct acpi_debug_mem_header), component, module, line); if (!allocation) { return (NULL); @@ -518,7 +519,7 @@ acpi_ut_callocate_and_track ( acpi_status status; - allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_block), component, + allocation = acpi_ut_callocate (size + sizeof (struct acpi_debug_mem_header), component, module, line); if (!allocation) { /* Report allocation error */ @@ -603,7 +604,8 @@ acpi_ut_free_and_track ( * * FUNCTION: acpi_ut_find_allocation * - * PARAMETERS: Allocation - Address of allocated memory + * PARAMETERS: list_id - Memory list to search + * Allocation - Address of allocated memory * * RETURN: A list element if found; NULL otherwise. * @@ -646,7 +648,8 @@ acpi_ut_find_allocation ( * * FUNCTION: acpi_ut_track_allocation * - * PARAMETERS: Allocation - Address of allocated memory + * PARAMETERS: list_id - Memory list to search + * Allocation - Address of allocated memory * Size - Size of the allocation * alloc_type - MEM_MALLOC or MEM_CALLOC * Component - Component type of caller @@ -710,6 +713,7 @@ acpi_ut_track_allocation ( allocation->line = line; ACPI_STRNCPY (allocation->module, module, ACPI_MAX_MODULE_NAME); + allocation->module[ACPI_MAX_MODULE_NAME-1] = 0; /* Insert at list head */ @@ -733,7 +737,8 @@ unlock_and_exit: * * FUNCTION: acpi_ut_remove_allocation * - * PARAMETERS: Allocation - Address of allocated memory + * PARAMETERS: list_id - Memory list to search + * Allocation - Address of allocated memory * Component - Component type of caller * Module - Source file name of caller * Line - Line number of caller @@ -813,7 +818,7 @@ acpi_ut_remove_allocation ( * DESCRIPTION: Print some info about the outstanding allocations. * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE void acpi_ut_dump_allocation_info ( void) @@ -859,6 +864,7 @@ acpi_ut_dump_allocation_info ( */ return_VOID; } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index f04e81aac..9290313e2 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -424,23 +424,21 @@ acpi_ut_copy_esimple_to_isimple ( break; default: - /* - * Whatever other type -- it is not supported - */ + /* All other types are not supported */ + return_ACPI_STATUS (AE_SUPPORT); } - switch (external_object->type) { - /* Must COPY string and buffer contents */ + switch (external_object->type) { case ACPI_TYPE_STRING: internal_object->string.pointer = ACPI_MEM_CALLOCATE ((acpi_size) external_object->string.length + 1); if (!internal_object->string.pointer) { - return_ACPI_STATUS (AE_NO_MEMORY); + goto error_exit; } ACPI_MEMCPY (internal_object->string.pointer, @@ -456,7 +454,7 @@ acpi_ut_copy_esimple_to_isimple ( internal_object->buffer.pointer = ACPI_MEM_CALLOCATE (external_object->buffer.length); if (!internal_object->buffer.pointer) { - return_ACPI_STATUS (AE_NO_MEMORY); + goto error_exit; } ACPI_MEMCPY (internal_object->buffer.pointer, @@ -479,6 +477,11 @@ acpi_ut_copy_esimple_to_isimple ( *ret_internal_object = internal_object; return_ACPI_STATUS (AE_OK); + + +error_exit: + acpi_ut_remove_reference (internal_object); + return_ACPI_STATUS (AE_NO_MEMORY); } @@ -747,7 +750,7 @@ acpi_ut_copy_ielement_to_ielement ( status = acpi_ut_copy_simple_object (source_object, target_object); if (ACPI_FAILURE (status)) { - return (status); + goto error_exit; } *this_target_ptr = target_object; @@ -781,8 +784,8 @@ acpi_ut_copy_ielement_to_ielement ( ACPI_MEM_CALLOCATE (((acpi_size) source_object->package.count + 1) * sizeof (void *)); if (!target_object->package.elements) { - ACPI_MEM_FREE (target_object); - return (AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto error_exit; } /* @@ -802,6 +805,10 @@ acpi_ut_copy_ielement_to_ielement ( } return (status); + +error_exit: + acpi_ut_remove_reference (target_object); + return (status); } diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 4fc32d596..bf7c41a56 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include @@ -178,6 +179,7 @@ acpi_ut_debug_print ( va_start (args, format); acpi_os_vprintf (format, args); } +EXPORT_SYMBOL(acpi_ut_debug_print); /***************************************************************************** @@ -219,6 +221,7 @@ acpi_ut_debug_print_raw ( va_start (args, format); acpi_os_vprintf (format, args); } +EXPORT_SYMBOL(acpi_ut_debug_print_raw); /***************************************************************************** @@ -250,6 +253,7 @@ acpi_ut_trace ( acpi_ut_debug_print (ACPI_LV_FUNCTIONS, line_number, dbg_info, "%s\n", acpi_gbl_fn_entry_str); } +EXPORT_SYMBOL(acpi_ut_trace); /***************************************************************************** @@ -378,6 +382,7 @@ acpi_ut_exit ( acpi_gbl_nesting_level--; } +EXPORT_SYMBOL(acpi_ut_exit); /***************************************************************************** @@ -418,6 +423,7 @@ acpi_ut_status_exit ( acpi_gbl_nesting_level--; } +EXPORT_SYMBOL(acpi_ut_status_exit); /***************************************************************************** @@ -451,6 +457,7 @@ acpi_ut_value_exit ( acpi_gbl_nesting_level--; } +EXPORT_SYMBOL(acpi_ut_value_exit); /***************************************************************************** diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index dd57a1674..bb5a0f800 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -621,6 +621,10 @@ acpi_ut_add_reference ( return_VOID; } + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Incremented]\n", + object, object->common.reference_count)); + /* Increment the reference count */ (void) acpi_ut_update_object_reference (object, REF_INCREMENT); @@ -664,8 +668,9 @@ acpi_ut_remove_reference ( return_VOID; } - ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X\n", - object, object->common.reference_count)); + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Decremented]\n", + object, object->common.reference_count)); /* * Decrement the reference count, and only actually delete the object diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index c3f5900b6..0aa1fde7e 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -133,7 +133,7 @@ acpi_ut_evaluate_object ( u32 expected_return_btypes, union acpi_operand_object **return_desc) { - union acpi_operand_object *obj_desc; + struct acpi_parameter_info info; acpi_status status; u32 return_btype; @@ -141,9 +141,13 @@ acpi_ut_evaluate_object ( ACPI_FUNCTION_TRACE ("ut_evaluate_object"); + info.node = prefix_node; + info.parameters = NULL; + info.parameter_type = ACPI_PARAM_ARGS; + /* Evaluate the object/method */ - status = acpi_ns_evaluate_relative (prefix_node, path, NULL, &obj_desc); + status = acpi_ns_evaluate_relative (path, &info); if (ACPI_FAILURE (status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", @@ -159,7 +163,7 @@ acpi_ut_evaluate_object ( /* Did we get a return object? */ - if (!obj_desc) { + if (!info.return_object) { if (expected_return_btypes) { ACPI_REPORT_METHOD_ERROR ("No object was returned from", prefix_node, path, AE_NOT_EXIST); @@ -172,7 +176,7 @@ acpi_ut_evaluate_object ( /* Map the return object type to the bitmapped type */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + switch (ACPI_GET_OBJECT_TYPE (info.return_object)) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; @@ -202,17 +206,17 @@ acpi_ut_evaluate_object ( ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Type returned from %s was incorrect: %X\n", - path, ACPI_GET_OBJECT_TYPE (obj_desc))); + path, ACPI_GET_OBJECT_TYPE (info.return_object))); /* On error exit, we must delete the return object */ - acpi_ut_remove_reference (obj_desc); + acpi_ut_remove_reference (info.return_object); return_ACPI_STATUS (AE_TYPE); } /* Object type is OK, return it */ - *return_desc = obj_desc; + *return_desc = info.return_object; return_ACPI_STATUS (AE_OK); } diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index e1d19936e..9945a73d4 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -43,6 +43,8 @@ #define DEFINE_ACPI_GLOBALS +#include + #include #include @@ -142,16 +144,13 @@ unknown: */ /* Debug switch - level and trace mask */ - -#ifdef ACPI_DEBUG_OUTPUT u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; -#else -u32 acpi_dbg_level = ACPI_NORMAL_DEFAULT; -#endif +EXPORT_SYMBOL(acpi_dbg_level); /* Debug switch - layer (component) mask */ -u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT; +u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; +EXPORT_SYMBOL(acpi_dbg_layer); u32 acpi_gbl_nesting_level = 0; @@ -171,27 +170,40 @@ u8 acpi_gbl_shutdown = TRUE; const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128}; -const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { - "\\_S0_", - "\\_S1_", - "\\_S2_", - "\\_S3_", - "\\_S4_", - "\\_S5_"}; - -const char *acpi_gbl_highest_dstate_names[4] = { - "_S1D", - "_S2D", - "_S3D", - "_S4D"}; +const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = +{ + "\\_S0_", + "\\_S1_", + "\\_S2_", + "\\_S3_", + "\\_S4_", + "\\_S5_" +}; -/* Strings supported by the _OSI predefined (internal) method */ +const char *acpi_gbl_highest_dstate_names[4] = +{ + "_S1D", + "_S2D", + "_S3D", + "_S4D" +}; -const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { - "Linux", - "Windows 2000", - "Windows 2001", - "Windows 2001.1"}; +/* + * Strings supported by the _OSI predefined (internal) method. + * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS. + */ +const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = +{ + "Linux", + "Windows 2000", + "Windows 2001", + "Windows 2001.1", + "Windows 2001 SP0", + "Windows 2001 SP1", + "Windows 2001 SP2", + "Windows 2001 SP3", + "Windows 2001 SP4" +}; /****************************************************************************** @@ -213,7 +225,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, {"_SB_", ACPI_TYPE_DEVICE, NULL}, {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, - {"_TZ_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_TZ_", ACPI_TYPE_THERMAL, NULL}, {"_REV", ACPI_TYPE_INTEGER, "2"}, {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, {"_GL_", ACPI_TYPE_MUTEX, "0"}, @@ -561,26 +573,37 @@ acpi_ut_get_node_name ( struct acpi_namespace_node *node = (struct acpi_namespace_node *) object; + /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + if (!object) { - return ("NULL NODE"); + return ("NULL"); } - if (object == ACPI_ROOT_OBJECT) + /* Check for Root node */ + + if ((object == ACPI_ROOT_OBJECT) || + (object == acpi_gbl_root_node)) { - node = acpi_gbl_root_node; + return ("\"\\\" "); } + /* Descriptor must be a namespace node */ + if (node->descriptor != ACPI_DESC_TYPE_NAMED) { - return ("****"); + return ("####"); } + /* Name must be a valid ACPI name */ + if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii)) { - return ("----"); + return ("????"); } + /* Return the name */ + return (node->name.ascii); } @@ -783,10 +806,6 @@ acpi_ut_init_globals ( ACPI_FUNCTION_TRACE ("ut_init_globals"); - /* Runtime configuration */ - - acpi_gbl_create_osi_method = TRUE; - acpi_gbl_all_methods_serialized = FALSE; /* Memory allocation and cache lists */ @@ -846,6 +865,7 @@ acpi_ut_init_globals ( acpi_gbl_system_notify.handler = NULL; acpi_gbl_device_notify.handler = NULL; + acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; /* Global "typed" ACPI table pointers */ @@ -880,6 +900,7 @@ acpi_ut_init_globals ( /* Hardware oriented */ acpi_gbl_events_initialized = FALSE; + acpi_gbl_system_awake_and_running = TRUE; /* Namespace */ diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 573176cac..8a2df7046 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -59,7 +59,7 @@ * * FUNCTION: acpi_ut_short_divide * - * PARAMETERS: in_dividend - Pointer to the dividend + * PARAMETERS: Dividend - 64-bit dividend * Divisor - 32-bit divisor * out_quotient - Pointer to where the quotient is returned * out_remainder - Pointer to where the remainder is returned @@ -74,19 +74,18 @@ acpi_status acpi_ut_short_divide ( - acpi_integer *in_dividend, + acpi_integer dividend, u32 divisor, acpi_integer *out_quotient, u32 *out_remainder) { - union uint64_overlay dividend; + union uint64_overlay dividend_ovl; union uint64_overlay quotient; u32 remainder32; ACPI_FUNCTION_TRACE ("ut_short_divide"); - dividend.full = *in_dividend; /* Always check for a zero divisor */ @@ -95,13 +94,15 @@ acpi_ut_short_divide ( return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); } + dividend_ovl.full = dividend; + /* * The quotient is 64 bits, the remainder is always 32 bits, * and is generated by the second divide. */ - ACPI_DIV_64_BY_32 (0, dividend.part.hi, divisor, + ACPI_DIV_64_BY_32 (0, dividend_ovl.part.hi, divisor, quotient.part.hi, remainder32); - ACPI_DIV_64_BY_32 (remainder32, dividend.part.lo, divisor, + ACPI_DIV_64_BY_32 (remainder32, dividend_ovl.part.lo, divisor, quotient.part.lo, remainder32); /* Return only what was requested */ @@ -121,8 +122,8 @@ acpi_ut_short_divide ( * * FUNCTION: acpi_ut_divide * - * PARAMETERS: in_dividend - Pointer to the dividend - * in_divisor - Pointer to the divisor + * PARAMETERS: in_dividend - Dividend + * in_divisor - Divisor * out_quotient - Pointer to where the quotient is returned * out_remainder - Pointer to where the remainder is returned * @@ -134,8 +135,8 @@ acpi_ut_short_divide ( acpi_status acpi_ut_divide ( - acpi_integer *in_dividend, - acpi_integer *in_divisor, + acpi_integer in_dividend, + acpi_integer in_divisor, acpi_integer *out_quotient, acpi_integer *out_remainder) { @@ -155,13 +156,13 @@ acpi_ut_divide ( /* Always check for a zero divisor */ - if (*in_divisor == 0) { + if (in_divisor == 0) { ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n")); return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); } - divisor.full = *in_divisor; - dividend.full = *in_dividend; + divisor.full = in_divisor; + dividend.full = in_dividend; if (divisor.part.hi == 0) { /* * 1) Simplest case is where the divisor is 32 bits, we can @@ -269,7 +270,7 @@ acpi_ut_divide ( acpi_status acpi_ut_short_divide ( - acpi_integer *in_dividend, + acpi_integer in_dividend, u32 divisor, acpi_integer *out_quotient, u32 *out_remainder) @@ -288,10 +289,10 @@ acpi_ut_short_divide ( /* Return only what was requested */ if (out_quotient) { - *out_quotient = *in_dividend / divisor; + *out_quotient = in_dividend / divisor; } if (out_remainder) { - *out_remainder = (u32) *in_dividend % divisor; + *out_remainder = (u32) in_dividend % divisor; } return_ACPI_STATUS (AE_OK); @@ -299,8 +300,8 @@ acpi_ut_short_divide ( acpi_status acpi_ut_divide ( - acpi_integer *in_dividend, - acpi_integer *in_divisor, + acpi_integer in_dividend, + acpi_integer in_divisor, acpi_integer *out_quotient, acpi_integer *out_remainder) { @@ -309,7 +310,7 @@ acpi_ut_divide ( /* Always check for a zero divisor */ - if (*in_divisor == 0) { + if (in_divisor == 0) { ACPI_REPORT_ERROR (("acpi_ut_divide: Divide by zero\n")); return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); } @@ -318,10 +319,10 @@ acpi_ut_divide ( /* Return only what was requested */ if (out_quotient) { - *out_quotient = *in_dividend / *in_divisor; + *out_quotient = in_dividend / in_divisor; } if (out_remainder) { - *out_remainder = *in_dividend % *in_divisor; + *out_remainder = in_dividend % in_divisor; } return_ACPI_STATUS (AE_OK); diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 9efcb99a3..9cfe115ce 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -356,16 +356,15 @@ acpi_ut_valid_acpi_character ( * FUNCTION: acpi_ut_strtoul64 * * PARAMETERS: String - Null terminated string - * Terminater - Where a pointer to the terminating byte is returned - * Base - Radix of the string + * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE + * ret_integer - Where the converted integer is returned * - * RETURN: Converted value + * RETURN: Status and Converted value * * DESCRIPTION: Convert a string into an unsigned value. + * NOTE: Does not support Octal strings, not needed. * ******************************************************************************/ -#define NEGATIVE 1 -#define POSITIVE 0 acpi_status acpi_ut_strtoul64 ( @@ -373,50 +372,40 @@ acpi_ut_strtoul64 ( u32 base, acpi_integer *ret_integer) { - u32 index; + u32 this_digit; acpi_integer return_value = 0; - acpi_status status = AE_OK; - acpi_integer dividend; acpi_integer quotient; - *ret_integer = 0; + ACPI_FUNCTION_TRACE ("ut_stroul64"); + switch (base) { - case 0: - case 8: + case ACPI_ANY_BASE: case 10: case 16: break; default: - /* - * The specified Base parameter is not in the domain of - * this function: - */ - return (AE_BAD_PARAMETER); + /* Invalid Base */ + return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* - * skip over any white space in the buffer: - */ + /* Skip over any white space in the buffer */ + while (ACPI_IS_SPACE (*string) || *string == '\t') { ++string; } /* * If the input parameter Base is zero, then we need to - * determine if it is octal, decimal, or hexadecimal: + * determine if it is decimal or hexadecimal: */ if (base == 0) { - if (*string == '0') { - if (ACPI_TOLOWER (*(++string)) == 'x') { - base = 16; - ++string; - } - else { - base = 8; - } + if ((*string == '0') && + (ACPI_TOLOWER (*(++string)) == 'x')) { + base = 16; + ++string; } else { base = 10; @@ -424,76 +413,67 @@ acpi_ut_strtoul64 ( } /* - * For octal and hexadecimal bases, skip over the leading + * For hexadecimal base, skip over the leading * 0 or 0x, if they are present. */ - if (base == 8 && *string == '0') { - string++; - } - if (base == 16 && *string == '0' && ACPI_TOLOWER (*(++string)) == 'x') { string++; } - /* Main loop: convert the string to an unsigned long */ + /* Main loop: convert the string to a 64-bit integer */ while (*string) { if (ACPI_IS_DIGIT (*string)) { - index = ((u8) *string) - '0'; + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8) *string) - '0'; } else { - index = (u8) ACPI_TOUPPER (*string); - if (ACPI_IS_UPPER ((char) index)) { - index = index - 'A' + 10; + this_digit = (u8) ACPI_TOUPPER (*string); + if (ACPI_IS_UPPER ((char) this_digit)) { + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; } else { goto error_exit; } } - if (index >= base) { + /* Check to see if digit is out of range */ + + if (this_digit >= base) { goto error_exit; } - /* Check to see if value is out of range: */ + /* Divide the digit into the correct position */ - dividend = ACPI_INTEGER_MAX - (acpi_integer) index; - (void) acpi_ut_short_divide (÷nd, base, "ient, NULL); + (void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit), + base, "ient, NULL); if (return_value > quotient) { goto error_exit; } return_value *= base; - return_value += index; + return_value += this_digit; ++string; } *ret_integer = return_value; - return (status); + return_ACPI_STATUS (AE_OK); error_exit: - switch (base) { - case 8: - status = AE_BAD_OCTAL_CONSTANT; - break; + /* Base was set/validated above */ - case 10: - status = AE_BAD_DECIMAL_CONSTANT; - break; - - case 16: - status = AE_BAD_HEX_CONSTANT; - break; - - default: - /* Base validated above */ - break; + if (base == 10) { + return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); + } + else { + return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); } - - return (status); } @@ -508,7 +488,7 @@ error_exit: * DESCRIPTION: Convert string to uppercase * ******************************************************************************/ - +#ifdef ACPI_FUTURE_USAGE char * acpi_ut_strupr ( char *src_string) @@ -528,6 +508,7 @@ acpi_ut_strupr ( return (src_string); } +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index b3b8757c1..73467983c 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -155,9 +155,8 @@ acpi_ut_create_buffer_object ( ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size); - /* - * Create a new Buffer object - */ + /* Create a new Buffer object */ + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!buffer_desc) { return_PTR (NULL); @@ -189,6 +188,61 @@ acpi_ut_create_buffer_object ( } +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_string_object + * + * PARAMETERS: string_size - Size of string to be created. Does not + * include NULL terminator, this is added + * automatically. + * + * RETURN: Pointer to a new String object + * + * DESCRIPTION: Create a fully initialized string object + * + ******************************************************************************/ + +union acpi_operand_object * +acpi_ut_create_string_object ( + acpi_size string_size) +{ + union acpi_operand_object *string_desc; + char *string; + + + ACPI_FUNCTION_TRACE_U32 ("ut_create_string_object", string_size); + + + /* Create a new String object */ + + string_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); + if (!string_desc) { + return_PTR (NULL); + } + + /* + * Allocate the actual string buffer -- (Size + 1) for NULL terminator. + * NOTE: Zero-length strings are NULL terminated + */ + string = ACPI_MEM_CALLOCATE (string_size + 1); + if (!string) { + ACPI_REPORT_ERROR (("create_string: could not allocate size %X\n", + (u32) string_size)); + acpi_ut_remove_reference (string_desc); + return_PTR (NULL); + } + + /* Complete string object initialization */ + + string_desc->string.pointer = string; + string_desc->string.length = (u32) string_size; + + /* Return the new string descriptor */ + + return_PTR (string_desc); +} + + /******************************************************************************* * * FUNCTION: acpi_ut_valid_internal_object diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 5cbd93eef..fabe751e1 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -41,6 +41,7 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include #include #include @@ -157,9 +158,8 @@ acpi_enable_subsystem ( } } - /* - * Enable ACPI mode - */ + /* Enable ACPI mode */ + if (!(flags & ACPI_NO_ACPI_ENABLE)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n")); @@ -173,7 +173,21 @@ acpi_enable_subsystem ( } /* - * Initialize ACPI Event handling + * Install the default op_region handlers. These are installed unless + * other handlers have already been installed via the + * install_address_space_handler interface. + */ + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); + + status = acpi_ev_install_region_handlers (); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* + * Initialize ACPI Event handling (Fixed and General Purpose) * * NOTE: We must have the hardware AND events initialized before we can execute * ANY control methods SAFELY. Any control method can require ACPI hardware @@ -182,18 +196,18 @@ acpi_enable_subsystem ( if (!(flags & ACPI_NO_EVENT_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n")); - status = acpi_ev_initialize (); + status = acpi_ev_initialize_events (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } - /* Install the SCI handler, Global Lock handler, and GPE handlers */ + /* Install the SCI handler and Global Lock handler */ if (!(flags & ACPI_NO_HANDLER_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n")); - status = acpi_ev_handler_initialize (); + status = acpi_ev_install_xrupt_handlers (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -226,18 +240,16 @@ acpi_initialize_objects ( /* - * Install the default op_region handlers. These are installed unless - * other handlers have already been installed via the - * install_address_space_handler interface. + * Run all _REG methods * - * NOTE: This will cause _REG methods to be run. Any objects accessed + * NOTE: Any objects accessed * by the _REG methods will be automatically initialized, even if they * contain executable AML (see call to acpi_ns_initialize_objects below). */ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n")); - status = acpi_ev_init_address_spaces (); + status = acpi_ev_initialize_op_regions (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -249,7 +261,7 @@ acpi_initialize_objects ( * objects: operation_regions, buffer_fields, Buffers, and Packages. */ if (!(flags & ACPI_NO_OBJECT_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n")); status = acpi_ns_initialize_objects (); if (ACPI_FAILURE (status)) { @@ -331,6 +343,8 @@ acpi_terminate (void) } +#ifdef ACPI_FUTURE_USAGE + /***************************************************************************** * * FUNCTION: acpi_subsystem_status @@ -444,6 +458,7 @@ acpi_get_system_info ( return_ACPI_STATUS (AE_OK); } +EXPORT_SYMBOL(acpi_get_system_info); /***************************************************************************** @@ -478,6 +493,8 @@ acpi_install_initialization_handler ( return AE_OK; } +#endif /* ACPI_FUTURE_USAGE */ + /***************************************************************************** * diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index ed66215b3..6b356175f 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -233,6 +233,7 @@ acpi_extract_package ( return_ACPI_STATUS(AE_OK); } +EXPORT_SYMBOL(acpi_extract_package); acpi_status @@ -268,6 +269,7 @@ acpi_evaluate_integer ( return_ACPI_STATUS(AE_OK); } +EXPORT_SYMBOL(acpi_evaluate_integer); #if 0 @@ -373,7 +375,7 @@ acpi_evaluate_reference ( } if (package->package.count > ACPI_MAX_HANDLES) { - return AE_NO_MEMORY; + return_ACPI_STATUS(AE_NO_MEMORY); } list->count = package->package.count; @@ -409,5 +411,5 @@ end: return_ACPI_STATUS(status); } - +EXPORT_SYMBOL(acpi_evaluate_reference); diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile index bcd60fb8d..d1dcd8eae 100644 --- a/drivers/atm/Makefile +++ b/drivers/atm/Makefile @@ -3,7 +3,7 @@ # fore_200e-objs := fore200e.o -host-progs := fore200e_mkfirm +hostprogs-y := fore200e_mkfirm # Files generated that shall be removed upon make clean clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \ @@ -68,4 +68,4 @@ $(obj)/fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \ # deal with the various suffixes of the binary firmware images $(obj)/%.bin $(obj)/%.bin1 $(obj)/%.bin2: $(src)/%.data objcopy -Iihex $< -Obinary $@.gz - gzip -df $@.gz + gzip -n -df $@.gz diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index fe809480e..8a8521cda 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -313,9 +313,6 @@ static u32 __initdata ucode_data[] = { static void do_housekeeping (unsigned long arg); /********** globals **********/ -static amb_dev * amb_devs = NULL; -static struct timer_list housekeeping = TIMER_INITIALIZER(do_housekeeping, 0, 1); - static unsigned short debug = 0; static unsigned int cmds = 8; static unsigned int txs = 32; @@ -870,7 +867,7 @@ static inline void interrupts_off (amb_dev * dev) { static irqreturn_t interrupt_handler(int irq, void *dev_id, struct pt_regs *pt_regs) { - amb_dev * dev = amb_devs; + amb_dev * dev = (amb_dev *) dev_id; (void) pt_regs; PRINTD (DBG_IRQ|DBG_FLOW, "interrupt_handler: %p", dev_id); @@ -879,24 +876,6 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq); return IRQ_NONE; } - // Did one of our cards generate the interrupt? - while (dev) { - if (dev == dev_id) - break; - dev = dev->prev; - } - // impossible - unless we add the device to our list after both - // registering the IRQ handler for it and enabling interrupts, AND - // the card generates an IRQ at startup - should not happen again - if (!dev) { - PRINTD (DBG_IRQ, "irq for unknown device: %d", irq); - return IRQ_NONE; - } - // impossible - unless we have memory corruption of dev or kernel - if (irq != dev->irq) { - PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq); - return IRQ_NONE; - } { u32 interrupt = rd_plain (dev, offsetof(amb_mem, interrupt)); @@ -1554,22 +1533,13 @@ static const struct atmdev_ops amb_ops = { /********** housekeeping **********/ static void do_housekeeping (unsigned long arg) { - amb_dev * dev = amb_devs; - // data is set to zero at module unload - (void) arg; + amb_dev * dev = (amb_dev *) arg; - if (housekeeping.data) { - while (dev) { + // could collect device-specific (not driver/atm-linux) stats here - // could collect device-specific (not driver/atm-linux) stats here - - // last resort refill once every ten seconds - fill_rx_pools (dev); - - dev = dev->prev; - } - mod_timer(&housekeeping, jiffies + 10*HZ); - } + // last resort refill once every ten seconds + fill_rx_pools (dev); + mod_timer(&dev->housekeeping, jiffies + 10*HZ); return; } @@ -2225,6 +2195,7 @@ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) // set up known dev items straight away dev->pci_dev = pci_dev; + pci_set_drvdata(pci_dev, dev); dev->iobase = pci_resource_start (pci_dev, 1); dev->irq = pci_dev->irq; @@ -2284,18 +2255,23 @@ out: return ret; } -static int __init do_pci_device(struct pci_dev *pci_dev) +static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { amb_dev * dev; int err; // read resources from PCI configuration space - u8 irq = pci_dev->irq; - u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 0)); - u32 iobase = pci_resource_start (pci_dev, 1); + unsigned int irq = pci_dev->irq; + + if (pci_dev->device == PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD) { + PRINTK (KERN_ERR, "skipped broken (PLX rev 2) card"); + err = -EINVAL; + goto out; + } PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at" - " IO %x, IRQ %u, MEM %p", iobase, irq, membase); + " IO %lx, IRQ %u, MEM %p", pci_resource_start(pci_dev, 1), + irq, bus_to_virt(pci_resource_start(pci_dev, 0))); // check IO region err = pci_request_region(pci_dev, 1, DEV_LABEL); @@ -2348,9 +2324,10 @@ static int __init do_pci_device(struct pci_dev *pci_dev) dev->atm_dev->ci_range.vpi_bits = NUM_VPI_BITS; dev->atm_dev->ci_range.vci_bits = NUM_VCI_BITS; - // update linked list - dev->prev = amb_devs; - amb_devs = dev; + init_timer(&dev->housekeeping); + dev->housekeeping.function = do_housekeeping; + dev->housekeeping.data = (unsigned long) dev; + mod_timer(&dev->housekeeping, jiffies); // enable host interrupts interrupts_on (dev); @@ -2371,29 +2348,25 @@ out_release: goto out; } -static int __init amb_probe (void) { - struct pci_dev * pci_dev; - int devs; - - PRINTD (DBG_FLOW, "amb_probe"); - - devs = 0; - pci_dev = NULL; - while ((pci_dev = pci_find_device - (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR, pci_dev) - )) { - if (do_pci_device(pci_dev) == 0) - devs++; - } - - pci_dev = NULL; - while ((pci_dev = pci_find_device - (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD, pci_dev) - )) - PRINTK (KERN_ERR, "skipped broken (PLX rev 2) card"); - - return devs; +static void __devexit amb_remove_one(struct pci_dev *pci_dev) +{ + struct amb_dev *dev; + + dev = pci_get_drvdata(pci_dev); + + PRINTD(DBG_INFO|DBG_INIT, "closing %p (atm_dev = %p)", dev, dev->atm_dev); + del_timer_sync(&dev->housekeeping); + // the drain should not be necessary + drain_rx_pools(dev); + interrupts_off(dev); + amb_reset(dev, 0); + free_irq(dev->irq, dev); + pci_disable_device(pci_dev); + destroy_queues(dev); + atm_dev_deregister(dev->atm_dev); + kfree(dev); + pci_release_region(pci_dev, 1); } static void __init amb_check_args (void) { @@ -2441,13 +2414,13 @@ static void __init amb_check_args (void) { MODULE_AUTHOR(maintainer_string); MODULE_DESCRIPTION(description_string); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "h"); -MODULE_PARM(cmds, "i"); -MODULE_PARM(txs, "i"); -MODULE_PARM(rxs, __MODULE_STRING(NUM_RX_POOLS) "i"); -MODULE_PARM(rxs_bs, __MODULE_STRING(NUM_RX_POOLS) "i"); -MODULE_PARM(rx_lats, "i"); -MODULE_PARM(pci_lat, "b"); +module_param(debug, ushort, 0644); +module_param(cmds, uint, 0); +module_param(txs, uint, 0); +module_param_array(rxs, uint, NULL, 0); +module_param_array(rxs_bs, uint, NULL, 0); +module_param(rx_lats, uint, 0); +module_param(pci_lat, byte, 0); MODULE_PARM_DESC(debug, "debug bitmap, see .h file"); MODULE_PARM_DESC(cmds, "number of command queue entries"); MODULE_PARM_DESC(txs, "number of TX queue entries"); @@ -2458,9 +2431,25 @@ MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); /********** module entry **********/ -static int __init amb_module_init (void) { - int devs; - +static struct pci_device_id amb_pci_tbl[] = { + { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 }, + { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, amb_pci_tbl); + +static struct pci_driver amb_driver = { + .name = "amb", + .probe = amb_probe, + .remove = __devexit_p(amb_remove_one), + .id_table = amb_pci_tbl, +}; + +static int __init amb_module_init (void) +{ PRINTD (DBG_FLOW|DBG_INIT, "init_module"); // sanity check - cast needed as printk does not support %Zu @@ -2475,49 +2464,16 @@ static int __init amb_module_init (void) { amb_check_args(); // get the juice - devs = amb_probe(); - - if (devs) { - mod_timer (&housekeeping, jiffies); - } else { - PRINTK (KERN_INFO, "no (usable) adapters found"); - } - - return devs ? 0 : -ENODEV; + return pci_module_init(&amb_driver); } /********** module exit **********/ -static void __exit amb_module_exit (void) { - amb_dev * dev; - +static void __exit amb_module_exit (void) +{ PRINTD (DBG_FLOW|DBG_INIT, "cleanup_module"); - // paranoia - housekeeping.data = 0; - del_timer_sync(&housekeeping); - - while (amb_devs) { - struct pci_dev *pdev; - - dev = amb_devs; - pdev = dev->pci_dev; - amb_devs = dev->prev; - - PRINTD (DBG_INFO|DBG_INIT, "closing %p (atm_dev = %p)", dev, dev->atm_dev); - // the drain should not be necessary - drain_rx_pools (dev); - interrupts_off (dev); - amb_reset (dev, 0); - free_irq (dev->irq, dev); - pci_disable_device (pdev); - destroy_queues (dev); - atm_dev_deregister (dev->atm_dev); - kfree (dev); - pci_release_region (pdev, 1); - } - - return; + return pci_unregister_driver(&amb_driver); } module_init(amb_module_init); diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h index 75681ade5..3892dcf9d 100644 --- a/drivers/atm/ambassador.h +++ b/drivers/atm/ambassador.h @@ -649,7 +649,7 @@ struct amb_dev { struct atm_dev * atm_dev; struct pci_dev * pci_dev; - struct amb_dev * prev; + struct timer_list housekeeping; }; typedef struct amb_dev amb_dev; diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 0572f724b..381e9c18a 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -271,6 +271,28 @@ static void atmtcp_c_close(struct atm_vcc *vcc) } } read_unlock(&vcc_sklist_lock); + module_put(THIS_MODULE); +} + + +static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci) +{ + struct hlist_head *head; + struct atm_vcc *vcc; + struct hlist_node *node; + struct sock *s; + + head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)]; + + sk_for_each(s, node, head) { + vcc = atm_sk(s); + if (vcc->dev == dev && + vcc->vci == vci && vcc->vpi == vpi && + vcc->qos.rxtp.traffic_class != ATM_NONE) { + return vcc; + } + } + return NULL; } @@ -278,11 +300,9 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) { struct atm_dev *dev; struct atmtcp_hdr *hdr; - struct sock *s; - struct hlist_node *node; - struct atm_vcc *out_vcc = NULL; + struct atm_vcc *out_vcc; struct sk_buff *new_skb; - int i, result = 0; + int result = 0; if (!skb->len) return 0; dev = vcc->dev_data; @@ -293,19 +313,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) goto done; } read_lock(&vcc_sklist_lock); - for(i = 0; i < VCC_HTABLE_SIZE; ++i) { - struct hlist_head *head = &vcc_hash[i]; - - sk_for_each(s, node, head) { - out_vcc = atm_sk(s); - if (out_vcc->dev != dev) - continue; - if (out_vcc->vpi == ntohs(hdr->vpi) && - out_vcc->vci == ntohs(hdr->vci) && - out_vcc->qos.rxtp.traffic_class != ATM_NONE) - break; - } - } + out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci)); read_unlock(&vcc_sklist_lock); if (!out_vcc) { atomic_inc(&vcc->stats->tx_err); diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 8b137034d..78e34ee79 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -173,7 +173,7 @@ static void dump_mem(struct eni_dev *eni_dev) int i; for (i = 0; i < eni_dev->free_len; i++) - printk(KERN_DEBUG " %d: 0x%lx %d\n",i, + printk(KERN_DEBUG " %d: %p %d\n",i, eni_dev->free_list[i].start, 1 << eni_dev->free_list[i].order); } @@ -191,19 +191,19 @@ static void dump(struct atm_dev *dev) printk(KERN_NOTICE "TX buffers\n"); for (i = 0; i < NR_CHAN; i++) if (eni_dev->tx[i].send) - printk(KERN_NOTICE " TX %d @ 0x%lx: %ld\n",i, + printk(KERN_NOTICE " TX %d @ %p: %ld\n",i, eni_dev->tx[i].send,eni_dev->tx[i].words*4); printk(KERN_NOTICE "RX buffers\n"); for (i = 0; i < 1024; i++) if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx) - printk(KERN_NOTICE " RX %d @ 0x%lx: %ld\n",i, + printk(KERN_NOTICE " RX %d @ %p: %ld\n",i, ENI_VCC(eni_dev->rx_map[i])->recv, ENI_VCC(eni_dev->rx_map[i])->words*4); printk(KERN_NOTICE "----\n"); } -static void eni_put_free(struct eni_dev *eni_dev,unsigned long start, +static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start, unsigned long size) { struct eni_free *list; @@ -215,17 +215,17 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start, len = eni_dev->free_len; while (size) { if (len >= eni_dev->free_list_size) { - printk(KERN_CRIT "eni_put_free overflow (0x%lx,%ld)\n", + printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n", start,size); break; } - for (order = 0; !((start | size) & (1 << order)); order++); + for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++); if (MID_MIN_BUF_SIZE > (1 << order)) { printk(KERN_CRIT "eni_put_free: order %d too small\n", order); break; } - list[len].start = start; + list[len].start = (void __iomem *) start; list[len].order = order; len++; start += 1 << order; @@ -236,16 +236,16 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start, } -static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size) +static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size) { struct eni_free *list; - unsigned long start; + void __iomem *start; int len,i,order,best_order,index; list = eni_dev->free_list; len = eni_dev->free_len; if (*size < MID_MIN_BUF_SIZE) *size = MID_MIN_BUF_SIZE; - if (*size > MID_MAX_BUF_SIZE) return 0; + if (*size > MID_MAX_BUF_SIZE) return NULL; for (order = 0; (1 << order) < *size; order++); DPRINTK("trying: %ld->%d\n",*size,order); best_order = 65; /* we don't have more than 2^64 of anything ... */ @@ -260,7 +260,7 @@ static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size) best_order = list[i].order; index = i; } - if (best_order == 65) return 0; + if (best_order == 65) return NULL; start = list[index].start-eni_dev->base_diff; list[index] = list[--len]; eni_dev->free_len = len; @@ -273,7 +273,7 @@ static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size) } -static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start, +static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start, unsigned long size) { struct eni_free *list; @@ -283,20 +283,20 @@ static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start, list = eni_dev->free_list; len = eni_dev->free_len; for (order = -1; size; order++) size >>= 1; - DPRINTK("eni_free_mem: 0x%lx+0x%lx (order %d)\n",start,size,order); + DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order); for (i = 0; i < len; i++) - if (list[i].start == (start^(1 << order)) && + if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) && list[i].order == order) { DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i, list[i].start,start,1 << order,list[i].order,order); list[i] = list[--len]; - start &= ~(unsigned long) (1 << order); + start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order)); order++; i = -1; continue; } if (len >= eni_dev->free_list_size) { - printk(KERN_ALERT "eni_free_mem overflow (0x%lx,%d)\n",start, + printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start, order); return; } @@ -333,7 +333,7 @@ static void rx_ident_err(struct atm_vcc *vcc) printk(KERN_ALERT " host descr 0x%lx, rx pos 0x%lx, descr value " "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos, (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4)); - printk(KERN_ALERT " last 0x%p, servicing %d\n",eni_vcc->last, + printk(KERN_ALERT " last %p, servicing %d\n",eni_vcc->last, eni_vcc->servicing); EVENT("---dump ends here---\n",0,0); printk(KERN_NOTICE "---recent events---\n"); @@ -617,7 +617,8 @@ static int rx_aal5(struct atm_vcc *vcc) static inline int rx_vcc(struct atm_vcc *vcc) { - unsigned long vci_dsc,tmp; + void __iomem *vci_dsc; + unsigned long tmp; struct eni_vcc *eni_vcc; eni_vcc = ENI_VCC(vcc); @@ -728,7 +729,7 @@ static void dequeue_rx(struct atm_dev *dev) struct eni_vcc *eni_vcc; struct atm_vcc *vcc; struct sk_buff *skb; - unsigned long vci_dsc; + void __iomem *vci_dsc; int first; eni_dev = ENI_DEV(dev); @@ -808,7 +809,7 @@ static int open_rx_first(struct atm_vcc *vcc) static int open_rx_second(struct atm_vcc *vcc) { - unsigned long here; + void __iomem *here; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; unsigned long size; @@ -840,7 +841,7 @@ static int open_rx_second(struct atm_vcc *vcc) static void close_rx(struct atm_vcc *vcc) { DECLARE_WAITQUEUE(wait,current); - unsigned long here; + void __iomem *here; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; @@ -1289,7 +1290,8 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp, struct eni_dev *eni_dev = ENI_DEV(vcc->dev); struct eni_vcc *eni_vcc = ENI_VCC(vcc); struct eni_tx *tx; - unsigned long size,mem; + unsigned long size; + void __iomem *mem; int rate,ubr,unlimited,new_tx; int pre,res,order; int error; @@ -1313,7 +1315,7 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp, size = UBR_BUFFER; } new_tx = !eni_vcc->tx; - mem = 0; /* for gcc */ + mem = NULL; /* for gcc */ if (!new_tx) tx = eni_vcc->tx; else { mem = eni_alloc_mem(eni_dev,&size); @@ -1347,7 +1349,7 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp, error = -EINVAL; if (error) { if (new_tx) { - tx->send = 0; + tx->send = NULL; eni_free_mem(eni_dev,mem,size); } return error; @@ -1421,7 +1423,7 @@ static void close_tx(struct atm_vcc *vcc) eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index))) schedule(); eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2); - eni_vcc->tx->send = 0; + eni_vcc->tx->send = NULL; eni_dev->tx_bw += eni_vcc->tx->reserved; } eni_vcc->tx = NULL; @@ -1442,7 +1444,7 @@ static int start_tx(struct atm_dev *dev) skb_queue_head_init(&eni_dev->tx_queue); eni_out(0,MID_DMA_WR_TX); for (i = 0; i < NR_CHAN; i++) { - eni_dev->tx[i].send = 0; + eni_dev->tx[i].send = NULL; eni_dev->tx[i].index = i; } return 0; @@ -1687,9 +1689,9 @@ static int __devinit get_esi_asic(struct atm_dev *dev) #undef GET_SEPROM -static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base) +static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base) { - unsigned long mac_base; + void __iomem *mac_base; int i; mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom); @@ -1700,10 +1702,11 @@ static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base) static int __devinit eni_do_init(struct atm_dev *dev) { - struct midway_eprom *eprom; + struct midway_eprom __iomem *eprom; struct eni_dev *eni_dev; struct pci_dev *pci_dev; - unsigned long real_base,base; + unsigned long real_base; + void __iomem *base; unsigned char revision; int error,i,last; @@ -1730,17 +1733,16 @@ static int __devinit eni_do_init(struct atm_dev *dev) } printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,", dev->number,revision,real_base,eni_dev->irq); - if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) { + if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) { printk("\n"); printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page " "mapping\n",dev->number); return error; } - eni_dev->base_diff = real_base-base; + eni_dev->base_diff = real_base - (unsigned long) base; /* id may not be present in ASIC Tonga boards - check this @@@ */ if (!eni_dev->asic) { - eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct - midway_eprom)); + eprom = (base+EPROM_SIZE-sizeof(struct midway_eprom)); if (readl(&eprom->magic) != ENI155_MAGIC) { printk("\n"); printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad " @@ -1790,7 +1792,9 @@ static int __devinit eni_do_init(struct atm_dev *dev) static int __devinit eni_start(struct atm_dev *dev) { struct eni_dev *eni_dev; - unsigned long buf,buffer_mem; + + void __iomem *buf; + unsigned long buffer_mem; int error; DPRINTK(">eni_start\n"); @@ -1828,7 +1832,7 @@ static int __devinit eni_start(struct atm_dev *dev) tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev); eni_dev->events = 0; /* initialize memory management */ - buffer_mem = eni_dev->mem-(buf-eni_dev->ram); + buffer_mem = eni_dev->mem - (buf - eni_dev->ram); eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2; eni_dev->free_list = (struct eni_free *) kmalloc( sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL); @@ -1955,7 +1959,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs) */ tasklet_disable(&eni_dev->task); skb_queue_walk(&eni_dev->tx_queue, skb) { - unsigned long dsc; + void __iomem *dsc; if (ATM_SKB(skb)->vcc != vcc) continue; dsc = tx->send+ENI_PRV_POS(skb)*4; @@ -2136,9 +2140,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) if (!tx->send) continue; if (!--left) { - return sprintf(page,"tx[%d]: 0x%06lx-0x%06lx " + return sprintf(page,"tx[%d]: 0x%ld-0x%ld " "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i, - tx->send-eni_dev->ram, + (unsigned long) (tx->send - eni_dev->ram), tx->send-eni_dev->ram+tx->words*4-1,tx->words*4, tx->reserved,tx->shaping, tx == eni_dev->ubr ? " (UBR)" : ""); @@ -2162,9 +2166,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) if (--left) continue; length = sprintf(page,"vcc %4d: ",vcc->vci); if (eni_vcc->rx) { - length += sprintf(page+length,"0x%06lx-0x%06lx " + length += sprintf(page+length,"0x%ld-0x%ld " "(%6ld bytes)", - eni_vcc->recv-eni_dev->ram, + (unsigned long) (eni_vcc->recv - eni_dev->ram), eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1, eni_vcc->words*4); if (eni_vcc->tx) length += sprintf(page+length,", "); @@ -2183,8 +2187,8 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) unsigned long offset; if (--left) continue; - offset = eni_dev->ram+eni_dev->base_diff; - return sprintf(page,"free 0x%06lx-0x%06lx (%6d bytes)\n", + offset = (unsigned long) eni_dev->ram+eni_dev->base_diff; + return sprintf(page,"free %p-%p (%6d bytes)\n", fe->start-offset,fe->start-offset+(1 << fe->order)-1, 1 << fe->order); } @@ -2285,9 +2289,7 @@ static int __init eni_init(void) sizeof(skb->cb),sizeof(struct eni_skb_prv)); return -EIO; } - if (pci_register_driver(&eni_driver) > 0) return 0; - pci_unregister_driver (&eni_driver); - return -ENODEV; + return pci_register_driver(&eni_driver); } diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index e7af66bd8..385090c2a 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -33,12 +33,12 @@ struct eni_free { - unsigned long start; /* counting in bytes */ + void __iomem *start; /* counting in bytes */ int order; }; struct eni_tx { - unsigned long send; /* base, 0 if unused */ + void __iomem *send; /* base, 0 if unused */ int prescaler; /* shaping prescaler */ int resolution; /* shaping divider */ unsigned long tx_pos; /* current TX write position */ @@ -51,7 +51,7 @@ struct eni_tx { struct eni_vcc { int (*rx)(struct atm_vcc *vcc); /* RX function, NULL if none */ - unsigned long recv; /* receive buffer */ + void __iomem *recv; /* receive buffer */ unsigned long words; /* its size in words */ unsigned long descr; /* next descriptor (RX) */ unsigned long rx_pos; /* current RX descriptor pos */ @@ -72,13 +72,13 @@ struct eni_dev { u32 events; /* pending events */ /*-------------------------------- base pointers into Midway address space */ - unsigned long phy; /* PHY interface chip registers */ - unsigned long reg; /* register base */ - unsigned long ram; /* RAM base */ - unsigned long vci; /* VCI table */ - unsigned long rx_dma; /* RX DMA queue */ - unsigned long tx_dma; /* TX DMA queue */ - unsigned long service; /* service list */ + void __iomem *phy; /* PHY interface chip registers */ + void __iomem *reg; /* register base */ + void __iomem *ram; /* RAM base */ + void __iomem *vci; /* VCI table */ + void __iomem *rx_dma; /* RX DMA queue */ + void __iomem *tx_dma; /* TX DMA queue */ + void __iomem *service; /* service list */ /*-------------------------------- TX part */ struct eni_tx tx[NR_CHAN]; /* TX channels */ struct eni_tx *ubr; /* UBR channel */ diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 91b85a95d..d6f161d16 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -306,11 +306,11 @@ static int fs_debug = 0; #ifdef MODULE #ifdef DEBUG -MODULE_PARM(fs_debug, "i"); +module_param(fs_debug, int, 0644); #endif -MODULE_PARM(loopback, "i"); -MODULE_PARM(num, "i"); -MODULE_PARM(fs_keystream, "i"); +module_param(loopback, int, 0); +module_param(num, int, 0); +module_param(fs_keystream, int, 0); /* XXX Add rx_buf_sizes, and rx_pool_sizes As per request Amar. -- REW */ #endif @@ -1667,7 +1667,7 @@ static int __devinit fs_init (struct fs_dev *dev) dev->hw_base = pci_resource_start(pci_dev, 0); - dev->base = (ulong) ioremap(dev->hw_base, 0x1000); + dev->base = ioremap(dev->hw_base, 0x1000); reset_chip (dev); @@ -1704,8 +1704,7 @@ static int __devinit fs_init (struct fs_dev *dev) } /* Try again after 10ms. */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout ((HZ+99)/100); + msleep(10); } if (!to) { @@ -2013,66 +2012,6 @@ void __devexit firestream_remove_one (struct pci_dev *pdev) func_exit (); } - -#if 0 -int __init fs_detect(void) -{ - struct pci_dev *pci_dev; - int devs = 0; - - func_enter (); - pci_dev = NULL; - while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FUJITSU_ME, - PCI_DEVICE_ID_FUJITSU_FS50, - pci_dev))) { - if (fs_register_and_init (pci_dev, &fs_pci_tbl[0])) - break; - devs++; - } - - while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FUJITSU_ME, - PCI_DEVICE_ID_FUJITSU_FS155, - pci_dev))) { - if (fs_register_and_init (pci_dev, FS_IS155)) - break; - devs++; - } - func_exit (); - return devs; -} -#else - -#if 0 -int __init init_PCI (void) -{ /* Begin init_PCI */ - - int pci_count; - printk ("init_PCI\n"); - /* - memset (&firestream_driver, 0, sizeof (firestream_driver)); - firestream_driver.name = "firestream"; - firestream_driver.id_table = firestream_pci_tbl; - firestream_driver.probe = fs_register_and_init; - */ - pci_count = pci_register_driver (&firestream_driver); - - if (pci_count <= 0) { - pci_unregister_driver (&firestream_driver); - pci_count = 0; - } - - return(pci_count); - -} /* End init_PCI */ -#endif -#endif - -/* -#ifdef MODULE -#define firestream_init init_module -#endif -*/ - static struct pci_device_id firestream_pci_tbl[] = { { PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50}, @@ -2111,3 +2050,4 @@ module_exit(firestream_cleanup_module); MODULE_LICENSE("GPL"); + diff --git a/drivers/atm/firestream.h b/drivers/atm/firestream.h index 8ef266cc8..49e783e35 100644 --- a/drivers/atm/firestream.h +++ b/drivers/atm/firestream.h @@ -477,7 +477,7 @@ struct fs_dev { struct timer_list timer; unsigned long hw_base; /* mem base address */ - unsigned long base; /* Mapping of base address */ + void __iomem *base; /* Mapping of base address */ int channo; unsigned long channel_mask; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b2f13752c..3b1eedb72 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -275,7 +275,7 @@ fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs) static int -fore200e_io_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs) +fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs) { unsigned long timeout = jiffies + MSECS(msecs); int ok; @@ -347,7 +347,7 @@ fore200e_reset(struct fore200e* fore200e, int diag) { int ok; - fore200e->cp_monitor = (struct cp_monitor*)(fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET); + fore200e->cp_monitor = fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET; fore200e->bus->write(BSTAT_COLD_START, &fore200e->cp_monitor->bstat); @@ -440,7 +440,7 @@ fore200e_shutdown(struct fore200e* fore200e) #ifdef CONFIG_ATM_FORE200E_PCA -static u32 fore200e_pca_read(volatile u32* addr) +static u32 fore200e_pca_read(volatile u32 __iomem *addr) { /* on big-endian hosts, the board is configured to convert the endianess of slave RAM accesses */ @@ -448,7 +448,7 @@ static u32 fore200e_pca_read(volatile u32* addr) } -static void fore200e_pca_write(u32 val, volatile u32* addr) +static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr) { /* on big-endian hosts, the board is configured to convert the endianess of slave RAM accesses */ @@ -576,9 +576,9 @@ fore200e_pca_map(struct fore200e* fore200e) DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); /* gain access to the PCA specific registers */ - fore200e->regs.pca.hcr = (u32*)(fore200e->virt_base + PCA200E_HCR_OFFSET); - fore200e->regs.pca.imr = (u32*)(fore200e->virt_base + PCA200E_IMR_OFFSET); - fore200e->regs.pca.psr = (u32*)(fore200e->virt_base + PCA200E_PSR_OFFSET); + fore200e->regs.pca.hcr = fore200e->virt_base + PCA200E_HCR_OFFSET; + fore200e->regs.pca.imr = fore200e->virt_base + PCA200E_IMR_OFFSET; + fore200e->regs.pca.psr = fore200e->virt_base + PCA200E_PSR_OFFSET; fore200e->state = FORE200E_STATE_MAP; return 0; @@ -689,7 +689,7 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom) *entry->status = STATUS_PENDING; - fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.prom_block.opcode); + fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.prom_block.opcode); ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); @@ -730,14 +730,14 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page) #ifdef CONFIG_ATM_FORE200E_SBA static u32 -fore200e_sba_read(volatile u32* addr) +fore200e_sba_read(volatile u32 __iomem *addr) { return sbus_readl(addr); } static void -fore200e_sba_write(u32 val, volatile u32* addr) +fore200e_sba_write(u32 val, volatile u32 __iomem *addr) { sbus_writel(val, addr); } @@ -856,10 +856,10 @@ fore200e_sba_map(struct fore200e* fore200e) unsigned int bursts; /* gain access to the SBA specific registers */ - fore200e->regs.sba.hcr = (u32*)sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); - fore200e->regs.sba.bsr = (u32*)sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); - fore200e->regs.sba.isr = (u32*)sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); - fore200e->virt_base = (u32*)sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); + fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); + fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); + fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); + fore200e->virt_base = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); if (fore200e->virt_base == NULL) { printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); @@ -884,10 +884,10 @@ fore200e_sba_map(struct fore200e* fore200e) static void fore200e_sba_unmap(struct fore200e* fore200e) { - sbus_iounmap((ulong)fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); - sbus_iounmap((ulong)fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); - sbus_iounmap((ulong)fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); - sbus_iounmap((ulong)fore200e->virt_base, SBA200E_RAM_LENGTH); + sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); + sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); + sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); + sbus_iounmap(fore200e->virt_base, SBA200E_RAM_LENGTH); } @@ -1477,12 +1477,12 @@ fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* #endif /* the MTU is not used by the cp, except in the case of AAL0 */ fore200e->bus->write(mtu, &entry->cp_entry->cmd.activate_block.mtu); - fore200e->bus->write(*(u32*)&vpvc, (u32*)&entry->cp_entry->cmd.activate_block.vpvc); - fore200e->bus->write(*(u32*)&activ_opcode, (u32*)&entry->cp_entry->cmd.activate_block.opcode); + fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.vpvc); + fore200e->bus->write(*(u32*)&activ_opcode, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.opcode); } else { - fore200e->bus->write(*(u32*)&vpvc, (u32*)&entry->cp_entry->cmd.deactivate_block.vpvc); - fore200e->bus->write(*(u32*)&deactiv_opcode, (u32*)&entry->cp_entry->cmd.deactivate_block.opcode); + fore200e->bus->write(*(u32*)&vpvc, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.vpvc); + fore200e->bus->write(*(u32*)&deactiv_opcode, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.opcode); } ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); @@ -1858,7 +1858,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) tpd_haddr.haddr = entry->tpd_dma >> TPD_HADDR_SHIFT; /* shift the address, as we are in a bitfield */ *entry->status = STATUS_PENDING; - fore200e->bus->write(*(u32*)&tpd_haddr, (u32*)&entry->cp_entry->tpd_haddr); + fore200e->bus->write(*(u32*)&tpd_haddr, (u32 __iomem *)&entry->cp_entry->tpd_haddr); spin_unlock_irqrestore(&fore200e->q_lock, flags); @@ -1893,7 +1893,7 @@ fore200e_getstats(struct fore200e* fore200e) *entry->status = STATUS_PENDING; - fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.stats_block.opcode); + fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.stats_block.opcode); ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); @@ -1996,7 +1996,7 @@ fore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask) *entry->status = STATUS_PENDING; - fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode); + fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.oc3_block.opcode); ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400); @@ -2291,7 +2291,7 @@ fore200e_init_bs_queue(struct fore200e* fore200e) int scheme, magn, i; struct host_bsq* bsq; - struct cp_bsq_entry* cp_entry; + struct cp_bsq_entry __iomem * cp_entry; for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) { for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) { @@ -2321,8 +2321,8 @@ fore200e_init_bs_queue(struct fore200e* fore200e) } /* get the base address of the cp resident buffer supply queue entries */ - cp_entry = (struct cp_bsq_entry*)(fore200e->virt_base + - fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ])); + cp_entry = fore200e->virt_base + + fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ]); /* fill the host resident and cp resident buffer supply queue entries */ for (i = 0; i < QUEUE_SIZE_BS; i++) { @@ -2352,7 +2352,7 @@ static int __init fore200e_init_rx_queue(struct fore200e* fore200e) { struct host_rxq* rxq = &fore200e->host_rxq; - struct cp_rxq_entry* cp_entry; + struct cp_rxq_entry __iomem * cp_entry; int i; DPRINTK(2, "receive queue is being initialized\n"); @@ -2378,8 +2378,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e) } /* get the base address of the cp resident rx queue entries */ - cp_entry = (struct cp_rxq_entry*)(fore200e->virt_base + - fore200e->bus->read(&fore200e->cp_queues->cp_rxq)); + cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_rxq); /* fill the host resident and cp resident rx entries */ for (i=0; i < QUEUE_SIZE_RX; i++) { @@ -2413,7 +2412,7 @@ static int __init fore200e_init_tx_queue(struct fore200e* fore200e) { struct host_txq* txq = &fore200e->host_txq; - struct cp_txq_entry* cp_entry; + struct cp_txq_entry __iomem * cp_entry; int i; DPRINTK(2, "transmit queue is being initialized\n"); @@ -2439,8 +2438,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e) } /* get the base address of the cp resident tx queue entries */ - cp_entry = (struct cp_txq_entry*)(fore200e->virt_base + - fore200e->bus->read(&fore200e->cp_queues->cp_txq)); + cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_txq); /* fill the host resident and cp resident tx entries */ for (i=0; i < QUEUE_SIZE_TX; i++) { @@ -2477,7 +2475,7 @@ static int __init fore200e_init_cmd_queue(struct fore200e* fore200e) { struct host_cmdq* cmdq = &fore200e->host_cmdq; - struct cp_cmdq_entry* cp_entry; + struct cp_cmdq_entry __iomem * cp_entry; int i; DPRINTK(2, "command queue is being initialized\n"); @@ -2492,8 +2490,7 @@ fore200e_init_cmd_queue(struct fore200e* fore200e) } /* get the base address of the cp resident cmd queue entries */ - cp_entry = (struct cp_cmdq_entry*)(fore200e->virt_base + - fore200e->bus->read(&fore200e->cp_queues->cp_cmdq)); + cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_cmdq); /* fill the host resident and cp resident cmd entries */ for (i=0; i < QUEUE_SIZE_CMD; i++) { @@ -2521,7 +2518,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e, enum buffer_scheme scheme, enum buffer_magn magn, int queue_length, int pool_size, int supply_blksize) { - struct bs_spec* bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ]; + struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ]; fore200e->bus->write(queue_length, &bs_spec->queue_length); fore200e->bus->write(fore200e_rx_buf_size[ scheme ][ magn ], &bs_spec->buffer_size); @@ -2533,7 +2530,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e, static int __init fore200e_initialize(struct fore200e* fore200e) { - struct cp_queues* cpq; + struct cp_queues __iomem * cpq; int ok, scheme, magn; DPRINTK(2, "device %s being initialized\n", fore200e->name); @@ -2541,7 +2538,7 @@ fore200e_initialize(struct fore200e* fore200e) init_MUTEX(&fore200e->rate_sf); spin_lock_init(&fore200e->q_lock); - cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET); + cpq = fore200e->cp_queues = fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET; /* enable cp to host interrupts */ fore200e->bus->write(1, &cpq->imask); @@ -2585,7 +2582,7 @@ fore200e_initialize(struct fore200e* fore200e) static void __init fore200e_monitor_putc(struct fore200e* fore200e, char c) { - struct cp_monitor* monitor = fore200e->cp_monitor; + struct cp_monitor __iomem * monitor = fore200e->cp_monitor; #if 0 printk("%c", c); @@ -2597,7 +2594,7 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c) static int __init fore200e_monitor_getc(struct fore200e* fore200e) { - struct cp_monitor* monitor = fore200e->cp_monitor; + struct cp_monitor __iomem * monitor = fore200e->cp_monitor; unsigned long timeout = jiffies + MSECS(50); int c; @@ -2673,7 +2670,7 @@ fore200e_load_fw(struct fore200e* fore200e) struct fw_header* fw_header = (struct fw_header*) fw_data; - u32* load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset); + u32 __iomem *load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset); DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", fore200e->name, load_addr, fw_size); @@ -2854,7 +2851,7 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) " board serial number:\t\t%d\n\n", fore200e_irq_itoa(fore200e->irq), (void*)fore200e->phys_base, - (void*)fore200e->virt_base, + fore200e->virt_base, fore200e->esi[0], fore200e->esi[1], fore200e->esi[2], fore200e->esi[3], fore200e->esi[4], fore200e->esi[5], fore200e->esi[4] * 256 + fore200e->esi[5]); @@ -2938,7 +2935,7 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) } if (!left--) { - struct cp_monitor* cp_monitor = fore200e->cp_monitor; + struct cp_monitor __iomem * cp_monitor = fore200e->cp_monitor; return sprintf(page, "\n\n" diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index aca550b66..492f7f549 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h @@ -520,7 +520,7 @@ typedef struct cp_cmdq_entry { /* host resident transmit queue entry */ typedef struct host_txq_entry { - struct cp_txq_entry* cp_entry; /* addr of cp resident tx queue entry */ + struct cp_txq_entry __iomem *cp_entry; /* addr of cp resident tx queue entry */ enum status* status; /* addr of host resident status */ struct tpd* tpd; /* addr of transmit PDU descriptor */ u32 tpd_dma; /* DMA address of tpd */ @@ -535,7 +535,7 @@ typedef struct host_txq_entry { /* host resident receive queue entry */ typedef struct host_rxq_entry { - struct cp_rxq_entry* cp_entry; /* addr of cp resident rx queue entry */ + struct cp_rxq_entry __iomem *cp_entry; /* addr of cp resident rx queue entry */ enum status* status; /* addr of host resident status */ struct rpd* rpd; /* addr of receive PDU descriptor */ u32 rpd_dma; /* DMA address of rpd */ @@ -545,7 +545,7 @@ typedef struct host_rxq_entry { /* host resident buffer supply queue entry */ typedef struct host_bsq_entry { - struct cp_bsq_entry* cp_entry; /* addr of cp resident buffer supply queue entry */ + struct cp_bsq_entry __iomem *cp_entry; /* addr of cp resident buffer supply queue entry */ enum status* status; /* addr of host resident status */ struct rbd_block* rbd_block; /* addr of receive buffer descriptor block */ u32 rbd_block_dma; /* DMA address od rdb */ @@ -555,7 +555,7 @@ typedef struct host_bsq_entry { /* host resident command queue entry */ typedef struct host_cmdq_entry { - struct cp_cmdq_entry* cp_entry; /* addr of cp resident cmd queue entry */ + struct cp_cmdq_entry __iomem *cp_entry; /* addr of cp resident cmd queue entry */ enum status *status; /* addr of host resident status */ } host_cmdq_entry_t; @@ -565,7 +565,7 @@ typedef struct host_cmdq_entry { typedef struct chunk { void* alloc_addr; /* base address of allocated chunk */ void* align_addr; /* base address of aligned chunk */ - u32 dma_addr; /* DMA address of aligned chunk */ + dma_addr_t dma_addr; /* DMA address of aligned chunk */ int direction; /* direction of DMA mapping */ u32 alloc_size; /* length of allocated chunk */ u32 align_size; /* length of aligned chunk */ @@ -645,7 +645,7 @@ typedef struct host_bsq { typedef struct fw_header { u32 magic; /* magic number */ - u32 version; /* firware version id */ + u32 version; /* firmware version id */ u32 load_offset; /* fw load offset in board memory */ u32 start_offset; /* fw execution start address in board memory */ } fw_header_t; @@ -772,18 +772,18 @@ typedef enum fore200e_state { /* PCA-200E registers */ typedef struct fore200e_pca_regs { - volatile u32* hcr; /* address of host control register */ - volatile u32* imr; /* address of host interrupt mask register */ - volatile u32* psr; /* address of PCI specific register */ + volatile u32 __iomem * hcr; /* address of host control register */ + volatile u32 __iomem * imr; /* address of host interrupt mask register */ + volatile u32 __iomem * psr; /* address of PCI specific register */ } fore200e_pca_regs_t; /* SBA-200E registers */ typedef struct fore200e_sba_regs { - volatile u32* hcr; /* address of host control register */ - volatile u32* bsr; /* address of burst transfer size register */ - volatile u32* isr; /* address of interrupt level selection register */ + volatile u32 __iomem *hcr; /* address of host control register */ + volatile u32 __iomem *bsr; /* address of burst transfer size register */ + volatile u32 __iomem *isr; /* address of interrupt level selection register */ } fore200e_sba_regs_t; @@ -807,8 +807,8 @@ typedef struct fore200e_bus { int status_alignment; /* status words DMA alignment requirement */ const unsigned char* fw_data; /* address of firmware data start */ const unsigned int* fw_size; /* address of firmware data size */ - u32 (*read)(volatile u32*); - void (*write)(u32, volatile u32*); + u32 (*read)(volatile u32 __iomem *); + void (*write)(u32, volatile u32 __iomem *); u32 (*dma_map)(struct fore200e*, void*, int, int); void (*dma_unmap)(struct fore200e*, u32, int, int); void (*dma_sync_for_cpu)(struct fore200e*, u32, int, int); @@ -852,12 +852,12 @@ typedef struct fore200e { void* bus_dev; /* bus-specific kernel data */ int irq; /* irq number */ unsigned long phys_base; /* physical base address */ - void* virt_base; /* virtual base address */ + void __iomem * virt_base; /* virtual base address */ unsigned char esi[ ESI_LEN ]; /* end system identifier */ - struct cp_monitor* cp_monitor; /* i960 monitor address */ - struct cp_queues* cp_queues; /* cp resident queues */ + struct cp_monitor __iomem * cp_monitor; /* i960 monitor address */ + struct cp_queues __iomem * cp_queues; /* cp resident queues */ struct host_cmdq host_cmdq; /* host resident cmd queue */ struct host_txq host_txq; /* host resident tx queue */ struct host_rxq host_rxq; /* host resident rx queue */ diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 71e5b5146..ccd54a85c 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -148,12 +148,12 @@ static u8 read_prom_byte(struct he_dev *he_dev, int addr); /* globals */ struct he_dev *he_devs = NULL; -static short disable64 = -1; +static int disable64 = 0; static short nvpibits = -1; static short nvcibits = -1; static short rx_skb_reserve = 16; -static short irq_coalesce = 1; -static short sdh = 0; +static int irq_coalesce = 1; +static int sdh = 0; static struct atmdev_ops he_ops = { @@ -1007,6 +1007,7 @@ he_start(struct atm_dev *dev) { struct he_dev *he_dev; struct pci_dev *pci_dev; + unsigned long membase; u16 command; u32 gen_cntl_0, host_cntl, lb_swap; @@ -1019,8 +1020,8 @@ he_start(struct atm_dev *dev) he_dev = HE_DEV(dev); pci_dev = he_dev->pci_dev; - he_dev->membase = pci_dev->resource[0].start; - HPRINTK("membase = 0x%lx irq = %d.\n", he_dev->membase, pci_dev->irq); + membase = pci_resource_start(pci_dev, 0); + HPRINTK("membase = 0x%lx irq = %d.\n", membase, pci_dev->irq); /* * pci bus controller initialization @@ -1080,7 +1081,7 @@ he_start(struct atm_dev *dev) hprintk("can't set latency timer to %d\n", timer); } - if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) { + if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) { hprintk("can't set up page mapping\n"); return -EINVAL; } @@ -1700,7 +1701,7 @@ he_stop(struct he_dev *he_dev) } if (he_dev->membase) - iounmap((void *) he_dev->membase); + iounmap(he_dev->membase); } static struct he_tpd * @@ -1962,7 +1963,7 @@ he_service_tbrq(struct he_dev *he_dev, int group) struct he_tpd *tpd; int slot, updated = 0; #ifdef USE_TPD_POOL - struct list_head *p; + struct he_tpd *__tpd; #endif /* 2.1.6 transmit buffer return queue */ @@ -1977,8 +1978,7 @@ he_service_tbrq(struct he_dev *he_dev, int group) TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : ""); #ifdef USE_TPD_POOL tpd = NULL; - list_for_each(p, &he_dev->outstanding_tpds) { - struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry); + list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) { if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) { tpd = __tpd; list_del(&__tpd->entry); @@ -2595,9 +2595,8 @@ he_close(struct atm_vcc *vcc) while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) && (retry < MAX_RETRY)) { - set_current_state(TASK_UNINTERRUPTIBLE); - (void) schedule_timeout(sleep); - if (sleep < HZ) + msleep(sleep); + if (sleep < 250) sleep = sleep * 2; ++retry; @@ -3033,17 +3032,17 @@ read_prom_byte(struct he_dev *he_dev, int addr) MODULE_LICENSE("GPL"); MODULE_AUTHOR("chas williams "); MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver"); -MODULE_PARM(disable64, "h"); +module_param(disable64, bool, 0); MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers"); -MODULE_PARM(nvpibits, "i"); +module_param(nvpibits, short, 0); MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)"); -MODULE_PARM(nvcibits, "i"); +module_param(nvcibits, short, 0); MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)"); -MODULE_PARM(rx_skb_reserve, "i"); +module_param(rx_skb_reserve, short, 0); MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)"); -MODULE_PARM(irq_coalesce, "i"); +module_param(irq_coalesce, bool, 0); MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)"); -MODULE_PARM(sdh, "i"); +module_param(sdh, bool, 0); MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); static struct pci_device_id he_pci_tbl[] = { @@ -3052,6 +3051,8 @@ static struct pci_device_id he_pci_tbl[] = { { 0, } }; +MODULE_DEVICE_TABLE(pci, he_pci_tbl); + static struct pci_driver he_driver = { .name = "he", .probe = he_init_one, diff --git a/drivers/atm/he.h b/drivers/atm/he.h index 0a4adaf4b..7075ef4aa 100644 --- a/drivers/atm/he.h +++ b/drivers/atm/he.h @@ -265,7 +265,7 @@ struct he_cs_stper struct he_dev { unsigned int number; unsigned int irq; - unsigned long membase; + void __iomem *membase; char prod_id[30]; char mac_addr[6]; diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 9ae4121ae..088440b80 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -354,8 +354,7 @@ static inline void __init show_version (void) { /********** globals **********/ -static hrz_dev * hrz_devs = NULL; -static struct timer_list housekeeping; +static void do_housekeeping (unsigned long arg); static unsigned short debug = 0; static unsigned short vpi_bits = 0; @@ -1386,7 +1385,7 @@ static inline void rx_data_av_handler (hrz_dev * dev) { static irqreturn_t interrupt_handler(int irq, void *dev_id, struct pt_regs *pt_regs) { - hrz_dev * dev = hrz_devs; + hrz_dev * dev = (hrz_dev *) dev_id; u32 int_source; unsigned int irq_ok; (void) pt_regs; @@ -1397,16 +1396,6 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq); return IRQ_NONE; } - // Did one of our cards generate the interrupt? - while (dev) { - if (dev == dev_id) - break; - dev = dev->prev; - } - if (!dev) { - PRINTD (DBG_IRQ, "irq not for me: %d", irq); - return IRQ_NONE; - } if (irq != dev->irq) { PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq); return IRQ_NONE; @@ -1462,28 +1451,18 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, /********** housekeeping **********/ -static void set_timer (struct timer_list * timer, unsigned int delay) { - timer->expires = jiffies + delay; - add_timer (timer); - return; -} - static void do_housekeeping (unsigned long arg) { // just stats at the moment - hrz_dev * dev = hrz_devs; - (void) arg; - // data is set to zero at module unload - if (housekeeping.data) { - while (dev) { - // collect device-specific (not driver/atm-linux) stats here - dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF); - dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF); - dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF); - dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF); - dev = dev->prev; - } - set_timer (&housekeeping, HZ/10); - } + hrz_dev * dev = (hrz_dev *) arg; + + // collect device-specific (not driver/atm-linux) stats here + dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF); + dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF); + dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF); + dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF); + + mod_timer (&dev->housekeeping, jiffies + HZ/10); + return; } @@ -2719,157 +2698,176 @@ static const struct atmdev_ops hrz_ops = { .owner = THIS_MODULE, }; -static int __init hrz_probe (void) { - struct pci_dev * pci_dev; - int devs; - - PRINTD (DBG_FLOW, "hrz_probe"); - - devs = 0; - pci_dev = NULL; - while ((pci_dev = pci_find_device - (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev) - )) { - hrz_dev * dev; - - // adapter slot free, read resources from PCI configuration space - u32 iobase = pci_resource_start (pci_dev, 0); - u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1)); - u8 irq = pci_dev->irq; - - /* XXX DEV_LABEL is a guess */ - if (!request_region (iobase, HRZ_IO_EXTENT, DEV_LABEL)) - continue; +static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +{ + hrz_dev * dev; + int err = 0; - if (pci_enable_device (pci_dev)) - continue; - - dev = kmalloc (sizeof(hrz_dev), GFP_KERNEL); - if (!dev) { - // perhaps we should be nice: deregister all adapters and abort? - PRINTD (DBG_ERR, "out of memory"); - continue; - } - - memset (dev, 0, sizeof(hrz_dev)); - - // grab IRQ and install handler - move this someplace more sensible - if (request_irq (irq, - interrupt_handler, - SA_SHIRQ, /* irqflags guess */ - DEV_LABEL, /* name guess */ - dev)) { - PRINTD (DBG_WARN, "request IRQ failed!"); - // free_irq is at "endif" - } else { - - PRINTD (DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", - iobase, irq, membase); - - dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, NULL); - if (!(dev->atm_dev)) { - PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); - } else { + // adapter slot free, read resources from PCI configuration space + u32 iobase = pci_resource_start (pci_dev, 0); + u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1)); + u8 irq = pci_dev->irq; unsigned char lat; - - PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", - dev->atm_dev->number, dev, dev->atm_dev); + + PRINTD (DBG_FLOW, "hrz_probe"); + + /* XXX DEV_LABEL is a guess */ + if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL)) + return -EINVAL; + + if (pci_enable_device(pci_dev)) { + err = -EINVAL; + goto out_release; + } + + dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL); + if (!dev) { + // perhaps we should be nice: deregister all adapters and abort? + PRINTD(DBG_ERR, "out of memory"); + err = -ENOMEM; + goto out_disable; + } + + memset(dev, 0, sizeof(hrz_dev)); + + pci_set_drvdata(pci_dev, dev); + + // grab IRQ and install handler - move this someplace more sensible + if (request_irq(irq, + interrupt_handler, + SA_SHIRQ, /* irqflags guess */ + DEV_LABEL, /* name guess */ + dev)) { + PRINTD(DBG_WARN, "request IRQ failed!"); + err = -EINVAL; + goto out_free; + } + + PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", + iobase, irq, membase); + + dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL); + if (!(dev->atm_dev)) { + PRINTD(DBG_ERR, "failed to register Madge ATM adapter"); + err = -EINVAL; + goto out_free_irq; + } + + PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", + dev->atm_dev->number, dev, dev->atm_dev); dev->atm_dev->dev_data = (void *) dev; dev->pci_dev = pci_dev; - + // enable bus master accesses - pci_set_master (pci_dev); - + pci_set_master(pci_dev); + // frobnicate latency (upwards, usually) - pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat); + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat); if (pci_lat) { - PRINTD (DBG_INFO, "%s PCI latency timer from %hu to %hu", - "changing", lat, pci_lat); - pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, pci_lat); + PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu", + "changing", lat, pci_lat); + pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat); } else if (lat < MIN_PCI_LATENCY) { - PRINTK (KERN_INFO, "%s PCI latency timer from %hu to %hu", - "increasing", lat, MIN_PCI_LATENCY); - pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY); + PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu", + "increasing", lat, MIN_PCI_LATENCY); + pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY); } - + dev->iobase = iobase; dev->irq = irq; dev->membase = membase; - + dev->rx_q_entry = dev->rx_q_reset = &memmap->rx_q_entries[0]; dev->rx_q_wrap = &memmap->rx_q_entries[RX_CHANS-1]; - + // these next three are performance hacks dev->last_vc = -1; dev->tx_last = -1; dev->tx_idle = 0; - + dev->tx_regions = 0; dev->tx_bytes = 0; dev->tx_skb = NULL; dev->tx_iovec = NULL; - + dev->tx_cell_count = 0; dev->rx_cell_count = 0; dev->hec_error_count = 0; dev->unassigned_cell_count = 0; - + dev->noof_spare_buffers = 0; - + { - unsigned int i; - for (i = 0; i < TX_CHANS; ++i) - dev->tx_channel_record[i] = -1; + unsigned int i; + for (i = 0; i < TX_CHANS; ++i) + dev->tx_channel_record[i] = -1; } - + dev->flags = 0; - + // Allocate cell rates and remember ASIC version // Fibre: ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53 // Copper: (WRONG) we want 6 into the above, close to 25Mb/s // Copper: (plagarise!) 25600000/8/270*260/53 - n/53 - - if (hrz_init (dev)) { - // to be really pedantic, this should be ATM_OC3c_PCR - dev->tx_avail = ATM_OC3_PCR; - dev->rx_avail = ATM_OC3_PCR; - set_bit (ultra, &dev->flags); // NOT "|= ultra" ! + + if (hrz_init(dev)) { + // to be really pedantic, this should be ATM_OC3c_PCR + dev->tx_avail = ATM_OC3_PCR; + dev->rx_avail = ATM_OC3_PCR; + set_bit(ultra, &dev->flags); // NOT "|= ultra" ! } else { - dev->tx_avail = ((25600000/8)*26)/(27*53); - dev->rx_avail = ((25600000/8)*26)/(27*53); - PRINTD (DBG_WARN, "Buggy ASIC: no TX bus-mastering."); + dev->tx_avail = ((25600000/8)*26)/(27*53); + dev->rx_avail = ((25600000/8)*26)/(27*53); + PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering."); } - + // rate changes spinlock - spin_lock_init (&dev->rate_lock); - + spin_lock_init(&dev->rate_lock); + // on-board memory access spinlock; we want atomic reads and // writes to adapter memory (handles IRQ and SMP) - spin_lock_init (&dev->mem_lock); - - init_waitqueue_head (&dev->tx_queue); - + spin_lock_init(&dev->mem_lock); + + init_waitqueue_head(&dev->tx_queue); + // vpi in 0..4, vci in 6..10 dev->atm_dev->ci_range.vpi_bits = vpi_bits; dev->atm_dev->ci_range.vci_bits = 10-vpi_bits; - - // update count and linked list - ++devs; - dev->prev = hrz_devs; - hrz_devs = dev; - // success - continue; - - /* not currently reached */ - atm_dev_deregister (dev->atm_dev); - } /* atm_dev_register */ - free_irq (irq, dev); - - } /* request_irq */ - kfree (dev); - release_region(iobase, HRZ_IO_EXTENT); - } /* kmalloc and while */ - return devs; + + init_timer(&dev->housekeeping); + dev->housekeeping.function = do_housekeeping; + dev->housekeeping.data = (unsigned long) dev; + mod_timer(&dev->housekeeping, jiffies); + +out: + return err; + +out_free_irq: + free_irq(dev->irq, dev); +out_free: + kfree(dev); +out_disable: + pci_disable_device(pci_dev); +out_release: + release_region(iobase, HRZ_IO_EXTENT); + goto out; +} + +static void __devexit hrz_remove_one(struct pci_dev *pci_dev) +{ + hrz_dev *dev; + + dev = pci_get_drvdata(pci_dev); + + PRINTD(DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev); + del_timer_sync(&dev->housekeeping); + hrz_reset(dev); + atm_dev_deregister(dev->atm_dev); + free_irq(dev->irq, dev); + release_region(dev->iobase, HRZ_IO_EXTENT); + kfree(dev); + + pci_disable_device(pci_dev); } static void __init hrz_check_args (void) { @@ -2898,22 +2896,35 @@ static void __init hrz_check_args (void) { MODULE_AUTHOR(maintainer_string); MODULE_DESCRIPTION(description_string); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "h"); -MODULE_PARM(vpi_bits, "h"); -MODULE_PARM(max_tx_size, "i"); -MODULE_PARM(max_rx_size, "i"); -MODULE_PARM(pci_lat, "b"); +module_param(debug, ushort, 0644); +module_param(vpi_bits, ushort, 0); +module_param(max_tx_size, int, 0); +module_param(max_rx_size, int, 0); +module_param(pci_lat, byte, 0); MODULE_PARM_DESC(debug, "debug bitmap, see .h file"); MODULE_PARM_DESC(vpi_bits, "number of bits (0..4) to allocate to VPIs"); MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames"); MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames"); MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); +static struct pci_device_id hrz_pci_tbl[] = { + { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, hrz_pci_tbl); + +static struct pci_driver hrz_driver = { + .name = "horizon", + .probe = hrz_probe, + .remove = __devexit_p(hrz_remove_one), + .id_table = hrz_pci_tbl, +}; + /********** module entry **********/ static int __init hrz_module_init (void) { - int devs; - // sanity check - cast is needed since printk does not support %Zu if (sizeof(struct MEMMAP) != 128*1024/4) { PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).", @@ -2927,44 +2938,15 @@ static int __init hrz_module_init (void) { hrz_check_args(); // get the juice - devs = hrz_probe(); - - if (devs) { - init_timer (&housekeeping); - housekeeping.function = do_housekeeping; - // paranoia - housekeeping.data = 1; - set_timer (&housekeeping, 0); - } else { - PRINTK (KERN_ERR, "no (usable) adapters found"); - } - - return devs ? 0 : -ENODEV; + return pci_module_init(&hrz_driver); } /********** module exit **********/ static void __exit hrz_module_exit (void) { - hrz_dev * dev; PRINTD (DBG_FLOW, "cleanup_module"); - // paranoia - housekeeping.data = 0; - del_timer (&housekeeping); - - while (hrz_devs) { - dev = hrz_devs; - hrz_devs = dev->prev; - - PRINTD (DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev); - hrz_reset (dev); - atm_dev_deregister (dev->atm_dev); - free_irq (dev->irq, dev); - release_region (dev->iobase, HRZ_IO_EXTENT); - kfree (dev); - } - - return; + return pci_unregister_driver(&hrz_driver); } module_init(hrz_module_init); diff --git a/drivers/atm/horizon.h b/drivers/atm/horizon.h index ec5ba498d..e2cc7020f 100644 --- a/drivers/atm/horizon.h +++ b/drivers/atm/horizon.h @@ -457,7 +457,7 @@ struct hrz_dev { unsigned long unassigned_cell_count; struct pci_dev * pci_dev; - struct hrz_dev * prev; + struct timer_list housekeeping; }; typedef struct hrz_dev hrz_dev; diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index b2bede540..80e304cf3 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -1266,8 +1266,9 @@ idt77252_rx_raw(struct idt77252_dev *card) 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); + pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(queue), + queue->end - queue->head - 16, + PCI_DMA_FROMDEVICE); while (head != tail) { unsigned int vpi, vci, pti; @@ -1360,10 +1361,10 @@ drop: 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); + pci_dma_sync_single_for_cpu(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", @@ -2516,7 +2517,7 @@ idt77252_close(struct atm_vcc *vcc) struct vc_map *vc = vcc->dev_data; unsigned long flags; unsigned long addr; - int timeout; + unsigned long timeout; down(&card->mutex); @@ -2566,9 +2567,9 @@ done: } spin_unlock_irqrestore(&vc->lock, flags); - timeout = 5 * HZ; + timeout = 5 * 1000; while (atomic_read(&vc->scq->used) > 0) { - timeout = schedule_timeout(timeout); + timeout = msleep_interruptible(timeout); if (!timeout) break; } @@ -3164,11 +3165,11 @@ deinit_card(struct idt77252_dev *card) for (i = 0; i < 4; i++) { if (card->fbq[i]) - iounmap((void *) card->fbq[i]); + iounmap(card->fbq[i]); } if (card->membase) - iounmap((void *) card->membase); + iounmap(card->membase); clear_bit(IDT77252_BIT_INIT, &card->flags); DIPRINTK("%s: Card deinitialized.\n", card->name); @@ -3681,18 +3682,25 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) struct idt77252_dev *card; struct atm_dev *dev; ushort revision = 0; - int i; + int i, err; + if ((err = pci_enable_device(pcidev))) { + printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev)); + return err; + } + if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) { printk("idt77252-%d: can't read PCI_REVISION_ID\n", index); - return -ENODEV; + err = -ENODEV; + goto err_out_disable_pdev; } card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL); if (!card) { printk("idt77252-%d: can't allocate private data\n", index); - return -ENOMEM; + err = -ENOMEM; + goto err_out_disable_pdev; } memset(card, 0, sizeof(struct idt77252_dev)); @@ -3715,26 +3723,24 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) card->tst_timer.function = tst_timer; /* Do the I/O remapping... */ - card->membase = (unsigned long) ioremap(membase, 1024); + card->membase = ioremap(membase, 1024); if (!card->membase) { printk("%s: can't ioremap() membase\n", card->name); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_card; } if (idt77252_preset(card)) { printk("%s: preset failed\n", card->name); - iounmap((void *) card->membase); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL); if (!dev) { printk("%s: can't register atm device\n", card->name); - iounmap((void *) card->membase); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } dev->dev_data = card; card->atmdev = dev; @@ -3743,22 +3749,19 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) suni_init(dev); if (!dev->phy) { printk("%s: can't init SUNI\n", card->name); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_deinit_card; } #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); + card->fbq[i] = 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; + err = -EIO; + goto err_out_deinit_card; } } @@ -3769,9 +3772,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) if (init_card(dev)) { printk("%s: init_card failed\n", card->name); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_deinit_card; } dev->ci_range.vpi_bits = card->vpibits; @@ -3783,12 +3785,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) 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; + err = -EIO; + goto err_out_stop; } *last = card; @@ -3796,6 +3794,23 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) index++; return 0; + +err_out_stop: + if (dev->phy->stop) + dev->phy->stop(dev); + +err_out_deinit_card: + deinit_card(card); + +err_out_iounmap: + iounmap(card->membase); + +err_out_free_card: + kfree(card); + +err_out_disable_pdev: + pci_disable_device(pcidev); + return err; } static struct pci_device_id idt77252_pci_tbl[] = @@ -3805,6 +3820,8 @@ static struct pci_device_id idt77252_pci_tbl[] = { 0, } }; +MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl); + static struct pci_driver idt77252_driver = { .name = "idt77252", .id_table = idt77252_pci_tbl, @@ -3826,11 +3843,7 @@ static int __init idt77252_init(void) return -EIO; } - if (pci_register_driver(&idt77252_driver) > 0) - return 0; - - pci_unregister_driver(&idt77252_driver); - return -ENODEV; + return pci_register_driver(&idt77252_driver); } static void __exit idt77252_exit(void) @@ -3848,6 +3861,7 @@ static void __exit idt77252_exit(void) if (dev->phy->stop) dev->phy->stop(dev); deinit_card(card); + pci_disable_device(card->pcidev); kfree(card); } @@ -3859,10 +3873,10 @@ module_exit(idt77252_exit); MODULE_LICENSE("GPL"); -MODULE_PARM(vpibits, "i"); +module_param(vpibits, uint, 0); MODULE_PARM_DESC(vpibits, "number of VPI bits supported (0, 1, or 2)"); #ifdef CONFIG_ATM_IDT77252_DEBUG -MODULE_PARM(debug, "i"); +module_param(debug, ulong, 0644); MODULE_PARM_DESC(debug, "debug bitmap, see drivers/atm/idt77252.h"); #endif diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h index 5a087c4e9..cfdd15e7d 100644 --- a/drivers/atm/idt77252.h +++ b/drivers/atm/idt77252.h @@ -355,9 +355,9 @@ struct idt77252_dev struct pci_dev *pcidev; /* PCI handle (desriptor) */ struct atm_dev *atmdev; /* ATM device desriptor */ - unsigned long membase; /* SAR's memory base address */ + void __iomem *membase; /* SAR's memory base address */ unsigned long srambase; /* SAR's sram base address */ - unsigned long fbq[4]; /* FBQ fill addresses */ + void __iomem *fbq[4]; /* FBQ fill addresses */ struct semaphore mutex; spinlock_t cmd_lock; /* for r/w utility/sram */ diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 0c8395cfb..73dd5cc38 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -81,14 +81,14 @@ static struct timer_list ia_timer = TIMER_INITIALIZER(ia_led_timer, 0, 0); struct atm_vcc *vcc_close_que[100]; static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ; static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ; -static u32 IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER +static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0; -MODULE_PARM(IA_TX_BUF, "i"); -MODULE_PARM(IA_TX_BUF_SZ, "i"); -MODULE_PARM(IA_RX_BUF, "i"); -MODULE_PARM(IA_RX_BUF_SZ, "i"); -MODULE_PARM(IADebugFlag, "i"); +module_param(IA_TX_BUF, int, 0); +module_param(IA_TX_BUF_SZ, int, 0); +module_param(IA_RX_BUF, int, 0); +module_param(IA_RX_BUF_SZ, int, 0); +module_param(IADebugFlag, uint, 0644); MODULE_LICENSE("GPL"); @@ -615,12 +615,13 @@ static int ia_avail_descs(IADEV *iadev) { return tmp; } +static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); + static int ia_que_tx (IADEV *iadev) { struct sk_buff *skb; int num_desc; struct atm_vcc *vcc; struct ia_vcc *iavcc; - static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb); num_desc = ia_avail_descs(iadev); while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) { @@ -1010,7 +1011,8 @@ static struct atm_dev *ia_boards = NULL; void desc_dbg(IADEV *iadev) { u_short tcq_wr_ptr, tcq_st_ptr, tcq_ed_ptr; - u32 tmp, i; + u32 i; + void __iomem *tmp; // regval = readl((u32)ia_cmds->maddr); tcq_wr_ptr = readw(iadev->seg_reg+TCQ_WR_PTR); printk("B_tcq_wr = 0x%x desc = %d last desc = %d\n", @@ -1024,7 +1026,7 @@ void desc_dbg(IADEV *iadev) { i = 0; while (tcq_st_ptr != tcq_ed_ptr) { tmp = iadev->seg_ram+tcq_st_ptr; - printk("TCQ slot %d desc = %d Addr = 0x%x\n", i++, readw(tmp), tmp); + printk("TCQ slot %d desc = %d Addr = %p\n", i++, readw(tmp), tmp); tcq_st_ptr += 2; } for(i=0; i num_tx_desc; i++) @@ -1080,7 +1082,7 @@ static int rx_pkt(struct atm_dev *dev) IADEV *iadev; struct atm_vcc *vcc; unsigned short status; - struct rx_buf_desc *buf_desc_ptr; + struct rx_buf_desc __iomem *buf_desc_ptr; int desc; struct dle* wr_ptr; int len; @@ -1095,7 +1097,7 @@ static int rx_pkt(struct atm_dev *dev) } /* mask 1st 3 bits to get the actual descno. */ desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff; - IF_RX(printk("reass_ram = 0x%x iadev->rfL.pcq_rd = 0x%x desc = %d\n", + IF_RX(printk("reass_ram = %p iadev->rfL.pcq_rd = 0x%x desc = %d\n", iadev->reass_ram, iadev->rfL.pcq_rd, desc); printk(" pcq_wr_ptr = 0x%x\n", readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);) @@ -1109,7 +1111,7 @@ static int rx_pkt(struct atm_dev *dev) /* get the buffer desc entry. update stuff. - doesn't seem to be any update necessary */ - buf_desc_ptr = (struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR; + buf_desc_ptr = iadev->RX_DESC_BASE_ADDR; /* make the ptr point to the corresponding buffer desc entry */ buf_desc_ptr += desc; if (!desc || (desc > iadev->num_rx_desc) || @@ -1358,8 +1360,8 @@ INCR_DLE: static int open_rx(struct atm_vcc *vcc) { IADEV *iadev; - u_short *vc_table; - u_short *reass_ptr; + u_short __iomem *vc_table; + u_short __iomem *reass_ptr; IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);) if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; @@ -1372,8 +1374,8 @@ static int open_rx(struct atm_vcc *vcc) } /* Make only this VCI in the vc table valid and let all others be invalid entries */ - vc_table = (u_short *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize); - vc_table += vcc->vci; + vc_table = iadev->reass_ram+RX_VC_TABLE*iadev->memSize; + vc_table += vcc->vci; /* mask the last 6 bits and OR it with 3 for 1K VCs */ *vc_table = vcc->vci << 6; @@ -1387,9 +1389,8 @@ static int open_rx(struct atm_vcc *vcc) ia_open_abr_vc(iadev, &srv_p, vcc, 0); } else { /* for UBR later may need to add CBR logic */ - reass_ptr = (u_short *) - (iadev->reass_ram+REASS_TABLE*iadev->memSize); - reass_ptr += vcc->vci; + reass_ptr = iadev->reass_ram+REASS_TABLE*iadev->memSize; + reass_ptr += vcc->vci; *reass_ptr = NO_AAL5_PKT; } @@ -1403,7 +1404,7 @@ static int open_rx(struct atm_vcc *vcc) static int rx_init(struct atm_dev *dev) { IADEV *iadev; - struct rx_buf_desc *buf_desc_ptr; + struct rx_buf_desc __iomem *buf_desc_ptr; unsigned long rx_pkt_start = 0; void *dle_addr; struct abr_vc_table *abr_vc_table; @@ -1465,13 +1466,13 @@ static int rx_init(struct atm_dev *dev) /* Initialize each entry in the Buffer Descriptor Table */ iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize; - buf_desc_ptr =(struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR; - memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); + buf_desc_ptr = iadev->RX_DESC_BASE_ADDR; + memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr++; rx_pkt_start = iadev->rx_pkt_ram; for(i=1; i<=iadev->num_rx_desc; i++) { - memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); + memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr)); buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16; buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff; buf_desc_ptr++; @@ -2053,10 +2054,9 @@ static int tx_init(struct atm_dev *dev) IF_INIT(printk("CBR_TAB_BEG = 0x%x, CBR_TAB_END = 0x%x, CBR_PTR = 0x%x\n", readw(iadev->seg_reg+CBR_TAB_BEG), readw(iadev->seg_reg+CBR_TAB_END), readw(iadev->seg_reg+CBR_TAB_END+1));) - tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize); /* Initialize the CBR Schedualing Table */ - memset((caddr_t)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize), + memset_io(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize, 0, iadev->num_vc*6); iadev->CbrRemEntries = iadev->CbrTotEntries = iadev->num_vc*3; iadev->CbrEntryPt = 0; @@ -2287,7 +2287,8 @@ static int reset_sar(struct atm_dev *dev) static int __init ia_init(struct atm_dev *dev) { IADEV *iadev; - unsigned long real_base, base; + unsigned long real_base; + void __iomem *base; unsigned short command; unsigned char revision; int error, i; @@ -2343,7 +2344,7 @@ static int __init ia_init(struct atm_dev *dev) udelay(10); /* mapping the physical address to a virtual address in address space */ - base=(unsigned long)ioremap((unsigned long)real_base,iadev->pci_map_size); /* ioremap is not resolved ??? */ + base = ioremap(real_base,iadev->pci_map_size); /* ioremap is not resolved ??? */ if (!base) { @@ -2351,39 +2352,38 @@ static int __init ia_init(struct atm_dev *dev) dev->number); return error; } - IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%lx,irq=%d\n", + IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n", dev->number, revision, base, iadev->irq);) /* filling the iphase dev structure */ iadev->mem = iadev->pci_map_size /2; - iadev->base_diff = real_base - base; iadev->real_base = real_base; iadev->base = base; /* Bus Interface Control Registers */ - iadev->reg = (u32 *) (base + REG_BASE); + iadev->reg = base + REG_BASE; /* Segmentation Control Registers */ - iadev->seg_reg = (u32 *) (base + SEG_BASE); + iadev->seg_reg = base + SEG_BASE; /* Reassembly Control Registers */ - iadev->reass_reg = (u32 *) (base + REASS_BASE); + iadev->reass_reg = base + REASS_BASE; /* Front end/ DMA control registers */ - iadev->phy = (u32 *) (base + PHY_BASE); - iadev->dma = (u32 *) (base + PHY_BASE); + iadev->phy = base + PHY_BASE; + iadev->dma = base + PHY_BASE; /* RAM - Segmentation RAm and Reassembly RAM */ - iadev->ram = (u32 *) (base + ACTUAL_RAM_BASE); - iadev->seg_ram = (base + ACTUAL_SEG_RAM_BASE); - iadev->reass_ram = (base + ACTUAL_REASS_RAM_BASE); + iadev->ram = base + ACTUAL_RAM_BASE; + iadev->seg_ram = base + ACTUAL_SEG_RAM_BASE; + iadev->reass_ram = base + ACTUAL_REASS_RAM_BASE; /* lets print out the above */ - IF_INIT(printk("Base addrs: %08x %08x %08x \n %08x %08x %08x %08x\n", - (u32)iadev->reg,(u32)iadev->seg_reg,(u32)iadev->reass_reg, - (u32)iadev->phy, (u32)iadev->ram, (u32)iadev->seg_ram, - (u32)iadev->reass_ram);) + IF_INIT(printk("Base addrs: %p %p %p \n %p %p %p %p\n", + iadev->reg,iadev->seg_reg,iadev->reass_reg, + iadev->phy, iadev->ram, iadev->seg_ram, + iadev->reass_ram);) /* lets try reading the MAC address */ error = get_esi(dev); if (error) { - iounmap((void *) iadev->base); + iounmap(iadev->base); return error; } printk("IA: "); @@ -2393,7 +2393,7 @@ static int __init ia_init(struct atm_dev *dev) /* reset SAR */ if (reset_sar(dev)) { - iounmap((void *) iadev->base); + iounmap(iadev->base); printk("IA: reset SAR fail, please try again\n"); return 1; } @@ -2659,7 +2659,7 @@ static void ia_close(struct atm_vcc *vcc) vc_table += vcc->vci; *vc_table = (vcc->vci << 6) | 15; if (vcc->qos.rxtp.traffic_class == ATM_ABR) { - struct abr_vc_table *abr_vc_table = (struct abr_vc_table *) + struct abr_vc_table __iomem *abr_vc_table = (iadev->reass_ram+ABR_VC_TABLE*iadev->memSize); abr_vc_table += vcc->vci; abr_vc_table->rdf = 0x0003; @@ -2890,7 +2890,7 @@ static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname, static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { IADEV *iadev; struct dle *wr_ptr; - struct tx_buf_desc *buf_desc_ptr; + struct tx_buf_desc __iomem *buf_desc_ptr; int desc; int comp_code; int total_len; @@ -2994,7 +2994,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { printk("\n");) /* Build the buffer descriptor */ - buf_desc_ptr = (struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE); + buf_desc_ptr = iadev->seg_ram+TX_DESC_BASE; buf_desc_ptr += desc; /* points to the corresponding entry */ buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT; /* Huh ? p.115 of users guide describes this as a read-only register */ @@ -3252,7 +3252,7 @@ static void __devexit ia_remove_one(struct pci_dev *pdev) atm_dev_deregister(dev); IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);) - iounmap((void *) iadev->base); + iounmap(iadev->base); pci_disable_device(pdev); ia_free_rx(iadev); diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index 9da028683..dc6ff8691 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -996,18 +996,18 @@ typedef struct _SUNI_STATS_ typedef struct iadev_t { /*-----base pointers into (i)chipSAR+ address space */ - u32 *phy; /* base pointer into phy(SUNI) */ - u32 *dma; /* base pointer into DMA control + u32 __iomem *phy; /* base pointer into phy(SUNI) */ + u32 __iomem *dma; /* base pointer into DMA control registers */ - u32 *reg; /* base pointer to SAR registers + u32 __iomem *reg; /* base pointer to SAR registers - Bus Interface Control Regs */ - u32 *seg_reg; /* base pointer to segmentation engine + u32 __iomem *seg_reg; /* base pointer to segmentation engine internal registers */ - u32 *reass_reg; /* base pointer to reassemble engine + u32 __iomem *reass_reg; /* base pointer to reassemble engine internal registers */ - u32 *ram; /* base pointer to SAR RAM */ - unsigned int seg_ram; - unsigned int reass_ram; + u32 __iomem *ram; /* base pointer to SAR RAM */ + void __iomem *seg_ram; + void __iomem *reass_ram; struct dle_q tx_dle_q; struct free_desc_q *tx_free_desc_qhead; struct sk_buff_head tx_dma_q, tx_backlog; @@ -1019,7 +1019,7 @@ typedef struct iadev_t { struct cpcs_trailer_desc *tx_buf; u16 num_tx_desc, tx_buf_sz, rate_limit; u32 tx_cell_cnt, tx_pkt_cnt; - u32 MAIN_VC_TABLE_ADDR, EXT_VC_TABLE_ADDR, ABR_SCHED_TABLE_ADDR; + void __iomem *MAIN_VC_TABLE_ADDR, *EXT_VC_TABLE_ADDR, *ABR_SCHED_TABLE_ADDR; struct dle_q rx_dle_q; struct free_desc_q *rx_free_desc_qhead; struct sk_buff_head rx_dma_q; @@ -1027,13 +1027,13 @@ typedef struct iadev_t { struct atm_vcc **rx_open; /* list of all open VCs */ u16 num_rx_desc, rx_buf_sz, rxing; u32 rx_pkt_ram, rx_tmp_cnt, rx_tmp_jif; - u32 RX_DESC_BASE_ADDR; + void __iomem *RX_DESC_BASE_ADDR; u32 drop_rxpkt, drop_rxcell, rx_cell_cnt, rx_pkt_cnt; struct atm_dev *next_board; /* other iphase devices */ struct pci_dev *pci; int mem; - unsigned long base_diff; /* virtual - real base address */ - unsigned int real_base, base; /* real and virtual base address */ + unsigned int real_base; /* real and virtual base address */ + void __iomem *base; unsigned int pci_map_size; /*pci map size of board */ unsigned char irq; unsigned char bus; diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 53f6d29c5..c5c4a89bc 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -191,7 +191,7 @@ #define LANAI_EEPROM_SIZE (128) typedef int vci_t; -typedef unsigned long bus_addr_t; +typedef void __iomem *bus_addr_t; /* DMA buffer in host memory for TX, RX, or service list. */ struct lanai_buffer { @@ -471,7 +471,7 @@ enum lanai_register { static inline bus_addr_t reg_addr(const struct lanai_dev *lanai, enum lanai_register reg) { - return lanai->base + (bus_addr_t) reg; + return lanai->base + reg; } static inline u32 reg_read(const struct lanai_dev *lanai, @@ -651,7 +651,7 @@ static inline u32 cardvcc_read(const struct lanai_vcc *lvcc, { u32 val; APRINTK(lvcc->vbase != 0, "cardvcc_read: unbound vcc!\n"); - val= readl(lvcc->vbase + (bus_addr_t) offset); + val= readl(lvcc->vbase + offset); RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n", lvcc->vci, (int) offset, val); return val; @@ -666,7 +666,7 @@ static inline void cardvcc_write(const struct lanai_vcc *lvcc, (unsigned int) val, lvcc->vci, (unsigned int) offset); RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n", lvcc->vci, (unsigned int) offset, (unsigned int) val); - writel(val, lvcc->vbase + (bus_addr_t) offset); + writel(val, lvcc->vbase + offset); } /* -------------------- COMPUTE SIZE OF AN AAL5 PDU: */ @@ -813,7 +813,7 @@ static void lanai_shutdown_tx_vci(struct lanai_dev *lanai, DPRINTK("read, write = %d, %d\n", read, write); break; } - schedule_timeout(HZ / 25); + msleep(40); } /* 15.2.2 - clear out all tx registers */ cardvcc_write(lvcc, 0, vcc_txreadptr); @@ -1481,7 +1481,7 @@ static inline struct lanai_vcc *new_lanai_vcc(void) struct lanai_vcc *lvcc; lvcc = (struct lanai_vcc *) kmalloc(sizeof(*lvcc), GFP_KERNEL); if (likely(lvcc != NULL)) { - lvcc->vbase = 0; + lvcc->vbase = NULL; lvcc->rx.atmvcc = lvcc->tx.atmvcc = NULL; lvcc->nref = 0; memset(&lvcc->stats, 0, sizeof lvcc->stats); @@ -1565,7 +1565,7 @@ static inline void host_vcc_unbind(struct lanai_dev *lanai, if (lvcc->vbase == 0) return; /* This vcc was never bound */ DPRINTK("Unbinding vci %d\n", lvcc->vci); - lvcc->vbase = 0; + lvcc->vbase = NULL; lanai->vccs[lvcc->vci] = NULL; #ifdef USE_POWERDOWN if (--lanai->nbound == 0) { @@ -2177,7 +2177,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev) /* 3.2: PCI initialization */ if ((result = lanai_pci_start(lanai)) != 0) goto error; - raw_base = (bus_addr_t) lanai->pci->resource[0].start; + raw_base = lanai->pci->resource[0].start; lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE); if (lanai->base == 0) { printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n"); @@ -2279,7 +2279,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev) lanai->conf1 = reg_read(lanai, Config1_Reg) | CONFIG1_POWERDOWN; conf1_write(lanai); #endif - iounmap((void *) lanai->base); + iounmap(lanai->base); error_pci: pci_disable_device(lanai->pci); error: @@ -2309,7 +2309,7 @@ static void lanai_dev_close(struct atm_dev *atmdev) pci_disable_device(lanai->pci); vcc_table_deallocate(lanai); service_buffer_deallocate(lanai); - iounmap((void *) lanai->base); + iounmap(lanai->base); kfree(lanai); } diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index b63669c1f..e6fb0b362 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -267,7 +267,7 @@ static struct atmdev_ops atm_ops = }; static struct timer_list ns_timer; static char *mac[NS_MAX_CARDS]; -MODULE_PARM(mac, "1-" __MODULE_STRING(NS_MAX_CARDS) "s"); +module_param_array(mac, charp, NULL, 0); MODULE_LICENSE("GPL"); @@ -467,6 +467,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) u32 u32d[4]; u32 ns_cfg_rctsize; int bcount; + unsigned long membase; error = 0; @@ -494,8 +495,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) card->index = i; card->atmdev = NULL; card->pcidev = pcidev; - card->membase = pci_resource_start(pcidev, 1); - card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE); + membase = pci_resource_start(pcidev, 1); + card->membase = ioremap(membase, NS_IOREMAP_SIZE); if (card->membase == 0) { printk("nicstar%d: can't ioremap() membase.\n",i); diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h index f762abcf2..a7eaee736 100644 --- a/drivers/atm/nicstar.h +++ b/drivers/atm/nicstar.h @@ -763,7 +763,7 @@ typedef struct ns_dev { int index; /* Card ID to the device driver */ int sram_size; /* In k x 32bit words. 32 or 128 */ - unsigned long membase; /* Card's memory base address */ + void __iomem *membase; /* Card's memory base address */ unsigned long max_pcr; int rct_size; /* Number of entries */ int vpibits; diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c index ef6b0c9f8..7a842ef71 100644 --- a/drivers/atm/nicstarmac.c +++ b/drivers/atm/nicstarmac.c @@ -162,7 +162,7 @@ nicstar_read_eprom_status( virt_addr_t base ) */ static u_int8_t -read_eprom_byte(u_int32_t base, u_int8_t offset) +read_eprom_byte(virt_addr_t base, u_int8_t offset) { u_int32_t val = 0; int i,j=0; diff --git a/drivers/atm/nicstarmac.h b/drivers/atm/nicstarmac.h index 0592daee4..80beec52f 100644 --- a/drivers/atm/nicstarmac.h +++ b/drivers/atm/nicstarmac.h @@ -7,7 +7,7 @@ ******************************************************************************/ -typedef unsigned int virt_addr_t; +typedef void __iomem *virt_addr_t; u_int32_t nicstar_read_eprom_status( virt_addr_t base ); void nicstar_init_eprom( virt_addr_t base ); diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 88d548a18..6ed9ddbbf 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -46,6 +46,8 @@ * - OAM */ +#define ZATM_COPPER 1 + #if 0 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) #else @@ -1577,51 +1579,77 @@ static const struct atmdev_ops ops = { .change_qos = zatm_change_qos, }; -static int __init zatm_module_init(void) +static int __devinit zatm_init_one(struct pci_dev *pci_dev, + const struct pci_device_id *ent) { struct atm_dev *dev; struct zatm_dev *zatm_dev; - int devs,type; - - zatm_dev = (struct zatm_dev *) kmalloc(sizeof(struct zatm_dev), - GFP_KERNEL); - if (!zatm_dev) return -ENOMEM; - devs = 0; - for (type = 0; type < 2; type++) { - struct pci_dev *pci_dev; - - pci_dev = NULL; - while ((pci_dev = pci_find_device(PCI_VENDOR_ID_ZEITNET,type ? - PCI_DEVICE_ID_ZEITNET_1225 : PCI_DEVICE_ID_ZEITNET_1221, - pci_dev))) { - if (pci_enable_device(pci_dev)) break; - dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); - if (!dev) break; - zatm_dev->pci_dev = pci_dev; - dev->dev_data = zatm_dev; - zatm_dev->copper = type; - if (zatm_init(dev) || zatm_start(dev)) { - atm_dev_deregister(dev); - break; - } - zatm_dev->more = zatm_boards; - zatm_boards = dev; - devs++; - zatm_dev = (struct zatm_dev *) kmalloc(sizeof(struct - zatm_dev),GFP_KERNEL); - if (!zatm_dev) { - printk(KERN_EMERG "zatm.c: memory shortage\n"); - goto out; - } - } + int ret = -ENOMEM; + + zatm_dev = (struct zatm_dev *) kmalloc(sizeof(*zatm_dev), GFP_KERNEL); + if (!zatm_dev) { + printk(KERN_EMERG "%s: memory shortage\n", DEV_LABEL); + goto out; } + + dev = atm_dev_register(DEV_LABEL, &ops, -1, NULL); + if (!dev) + goto out_free; + + ret = pci_enable_device(pci_dev); + if (ret < 0) + goto out_deregister; + + ret = pci_request_regions(pci_dev, DEV_LABEL); + if (ret < 0) + goto out_disable; + + zatm_dev->pci_dev = pci_dev; + dev = (struct atm_dev *)zatm_dev; + zatm_dev->copper = (int)ent->driver_data; + if ((ret = zatm_init(dev)) || (ret = zatm_start(dev))) + goto out_release; + + pci_set_drvdata(pci_dev, dev); + zatm_dev->more = zatm_boards; + zatm_boards = dev; + ret = 0; out: + return ret; + +out_release: + pci_release_regions(pci_dev); +out_disable: + pci_disable_device(pci_dev); +out_deregister: + atm_dev_deregister(dev); +out_free: kfree(zatm_dev); - - return 0; + goto out; } + MODULE_LICENSE("GPL"); -module_init(zatm_module_init); +static struct pci_device_id zatm_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1221, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, ZATM_COPPER }, + { PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1225, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, zatm_pci_tbl); + +static struct pci_driver zatm_driver = { + .name = DEV_LABEL, + .id_table = zatm_pci_tbl, + .probe = zatm_init_one, +}; + +static int __init zatm_init_module(void) +{ + return pci_module_init(&zatm_driver); +} + +module_init(zatm_init_module); /* module_exit not defined so not unloadable */ diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 0a160b2a5..20f597eff 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -14,7 +14,7 @@ config PREVENT_FIRMWARE_BUILD default y help Say yes to avoid building firmware. Firmware is usually shipped - with the driver, and only when updating the firware a rebuild + with the driver, and only when updating the firmware a rebuild should be made. If unsure say Y here. diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12701407b..be36edd42 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -135,6 +135,52 @@ static struct kobj_type ktype_bus = { decl_subsys(bus, &ktype_bus, NULL); +static int __bus_for_each_dev(struct bus_type *bus, struct device *start, + void *data, int (*fn)(struct device *, void *)) +{ + struct list_head *head; + struct device *dev; + int error = 0; + + if (!(bus = get_bus(bus))) + return -EINVAL; + + head = &bus->devices.list; + dev = list_prepare_entry(start, head, bus_list); + list_for_each_entry_continue(dev, head, bus_list) { + get_device(dev); + error = fn(dev, data); + put_device(dev); + if (error) + break; + } + put_bus(bus); + return error; +} + +static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void * data, int (*fn)(struct device_driver *, void *)) +{ + struct list_head *head; + struct device_driver *drv; + int error = 0; + + if (!(bus = get_bus(bus))) + return -EINVAL; + + head = &bus->drivers.list; + drv = list_prepare_entry(start, head, kobj.entry); + list_for_each_entry_continue(drv, head, kobj.entry) { + get_driver(drv); + error = fn(drv, data); + put_driver(drv); + if (error) + break; + } + put_bus(bus); + return error; +} + /** * bus_for_each_dev - device iterator. * @bus: bus type. @@ -154,30 +200,16 @@ decl_subsys(bus, &ktype_bus, NULL); * to retain this data, it should do, and increment the reference * count in the supplied callback. */ + int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *)) { - struct device *dev; - struct list_head * head; - int error = 0; - - if (!(bus = get_bus(bus))) - return -EINVAL; - - head = &bus->devices.list; - dev = list_prepare_entry(start, head, bus_list); + int ret; down_read(&bus->subsys.rwsem); - list_for_each_entry_continue(dev, head, bus_list) { - get_device(dev); - error = fn(dev, data); - put_device(dev); - if (error) - break; - } + ret = __bus_for_each_dev(bus, start, data, fn); up_read(&bus->subsys.rwsem); - put_bus(bus); - return error; + return ret; } /** @@ -203,34 +235,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *)) { - struct list_head * head; - struct device_driver *drv; - int error = 0; - - if(!(bus = get_bus(bus))) - return -EINVAL; - - head = &bus->drivers.list; - drv = list_prepare_entry(start, head, kobj.entry); + int ret; down_read(&bus->subsys.rwsem); - list_for_each_entry_continue(drv, head, kobj.entry) { - get_driver(drv); - error = fn(drv, data); - put_driver(drv); - if(error) - break; - } + ret = __bus_for_each_drv(bus, start, data, fn); up_read(&bus->subsys.rwsem); - put_bus(bus); - return error; + return ret; } /** * device_bind_driver - bind a driver to one device. * @dev: device. * - * Allow manual attachment of a driver to a deivce. + * Allow manual attachment of a driver to a device. * Caller must have already set @dev->driver. * * Note that this does not modify the bus reference count @@ -246,38 +263,40 @@ void device_bind_driver(struct device * dev) list_add_tail(&dev->driver_list, &dev->driver->devices); sysfs_create_link(&dev->driver->kobj, &dev->kobj, kobject_name(&dev->kobj)); + sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); } /** - * bus_match - check compatibility between device & driver. - * @dev: device. + * driver_probe_device - attempt to bind device & driver. * @drv: driver. + * @dev: device. * - * First, we call the bus's match function, which should compare - * the device IDs the driver supports with the device IDs of the - * device. Note we don't do this ourselves because we don't know - * the format of the ID structures, nor what is to be considered - * a match and what is not. + * First, we call the bus's match function, if one present, which + * should compare the device IDs the driver supports with the + * device IDs of the device. Note we don't do this ourselves + * because we don't know the format of the ID structures, nor what + * is to be considered a match and what is not. * * If we find a match, we call @drv->probe(@dev) if it exists, and - * call attach() above. + * call device_bind_driver() above. */ -static int bus_match(struct device * dev, struct device_driver * drv) -{ - int error = -ENODEV; - if (dev->bus->match(dev, drv)) { - dev->driver = drv; - if (drv->probe) { - if ((error = drv->probe(dev))) { - dev->driver = NULL; - return error; - } +int driver_probe_device(struct device_driver * drv, struct device * dev) +{ + if (drv->bus->match && !drv->bus->match(dev, drv)) + return -ENODEV; + + dev->driver = drv; + if (drv->probe) { + int error = drv->probe(dev); + if (error) { + dev->driver = NULL; + return error; } - device_bind_driver(dev); - error = 0; } - return error; + + device_bind_driver(dev); + return 0; } @@ -285,10 +304,11 @@ static int bus_match(struct device * dev, struct device_driver * drv) * device_attach - try to attach device to a driver. * @dev: device. * - * Walk the list of drivers that the bus has and call bus_match() - * for each pair. If a compatible pair is found, break out and return. + * Walk the list of drivers that the bus has and call + * driver_probe_device() for each pair. If a compatible + * pair is found, break out and return. */ -static int device_attach(struct device * dev) +int device_attach(struct device * dev) { struct bus_type * bus = dev->bus; struct list_head * entry; @@ -302,7 +322,7 @@ static int device_attach(struct device * dev) if (bus->match) { list_for_each(entry, &bus->drivers.list) { struct device_driver * drv = to_drv(entry); - error = bus_match(dev, drv); + error = driver_probe_device(drv, dev); if (!error) /* success, driver matched */ return 1; @@ -322,13 +342,13 @@ static int device_attach(struct device * dev) * driver_attach - try to bind driver to devices. * @drv: driver. * - * Walk the list of devices that the bus has on it and try to match - * the driver with each one. - * If bus_match() returns 0 and the @dev->driver is set, we've found - * a compatible pair. + * Walk the list of devices that the bus has on it and try to + * match the driver with each one. If driver_probe_device() + * returns 0 and the @dev->driver is set, we've found a + * compatible pair. * - * Note that we ignore the -ENODEV error from bus_match(), since it's - * perfectly valid for a driver not to bind to any devices. + * Note that we ignore the -ENODEV error from driver_probe_device(), + * since it's perfectly valid for a driver not to bind to any devices. */ void driver_attach(struct device_driver * drv) { @@ -342,7 +362,7 @@ void driver_attach(struct device_driver * drv) list_for_each(entry, &bus->devices.list) { struct device * dev = container_of(entry, struct device, bus_list); if (!dev->driver) { - error = bus_match(dev, drv); + error = driver_probe_device(drv, dev); if (error && (error != -ENODEV)) /* driver matched but the probe failed */ printk(KERN_WARNING @@ -368,6 +388,7 @@ void device_release_driver(struct device * dev) struct device_driver * drv = dev->driver; if (drv) { sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); + sysfs_remove_link(&dev->kobj, "driver"); list_del_init(&dev->driver_list); device_detach_shutdown(dev); if (drv->remove) @@ -515,7 +536,7 @@ int bus_add_driver(struct device_driver * drv) if (bus) { pr_debug("bus %s: add driver %s\n", bus->name, drv->name); - error = kobject_set_name(&drv->kobj, drv->name); + error = kobject_set_name(&drv->kobj, "%s", drv->name); if (error) { put_bus(bus); return error; @@ -529,6 +550,7 @@ int bus_add_driver(struct device_driver * drv) down_write(&bus->subsys.rwsem); driver_attach(drv); up_write(&bus->subsys.rwsem); + module_add_driver(drv->owner, drv); driver_add_attrs(bus, drv); } @@ -553,6 +575,7 @@ void bus_remove_driver(struct device_driver * drv) pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); driver_detach(drv); up_write(&drv->bus->subsys.rwsem); + module_remove_driver(drv); kobject_unregister(&drv->kobj); put_bus(drv->bus); } @@ -584,7 +607,9 @@ int bus_rescan_devices(struct bus_type * bus) { int count = 0; - bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); + down_write(&bus->subsys.rwsem); + __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); + up_write(&bus->subsys.rwsem); return count; } @@ -664,7 +689,7 @@ int bus_register(struct bus_type * bus) { int retval; - retval = kobject_set_name(&bus->subsys.kset.kobj, bus->name); + retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); if (retval) goto out; @@ -721,20 +746,23 @@ int __init buses_init(void) } -EXPORT_SYMBOL(bus_for_each_dev); -EXPORT_SYMBOL(bus_for_each_drv); +EXPORT_SYMBOL_GPL(bus_for_each_dev); +EXPORT_SYMBOL_GPL(bus_for_each_drv); -EXPORT_SYMBOL(device_bind_driver); -EXPORT_SYMBOL(device_release_driver); +EXPORT_SYMBOL_GPL(driver_probe_device); +EXPORT_SYMBOL_GPL(device_bind_driver); +EXPORT_SYMBOL_GPL(device_release_driver); +EXPORT_SYMBOL_GPL(device_attach); +EXPORT_SYMBOL_GPL(driver_attach); -EXPORT_SYMBOL(bus_add_device); -EXPORT_SYMBOL(bus_remove_device); -EXPORT_SYMBOL(bus_register); -EXPORT_SYMBOL(bus_unregister); -EXPORT_SYMBOL(bus_rescan_devices); -EXPORT_SYMBOL(get_bus); -EXPORT_SYMBOL(put_bus); -EXPORT_SYMBOL(find_bus); +EXPORT_SYMBOL_GPL(bus_add_device); +EXPORT_SYMBOL_GPL(bus_remove_device); +EXPORT_SYMBOL_GPL(bus_register); +EXPORT_SYMBOL_GPL(bus_unregister); +EXPORT_SYMBOL_GPL(bus_rescan_devices); +EXPORT_SYMBOL_GPL(get_bus); +EXPORT_SYMBOL_GPL(put_bus); +EXPORT_SYMBOL_GPL(find_bus); -EXPORT_SYMBOL(bus_create_file); -EXPORT_SYMBOL(bus_remove_file); +EXPORT_SYMBOL_GPL(bus_create_file); +EXPORT_SYMBOL_GPL(bus_remove_file); diff --git a/drivers/base/class.c b/drivers/base/class.c index 2693bb545..54b20126c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -139,7 +139,7 @@ int class_register(struct class * cls) INIT_LIST_HEAD(&cls->children); INIT_LIST_HEAD(&cls->interfaces); - error = kobject_set_name(&cls->subsys.kset.kobj, cls->name); + error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); if (error) return error; @@ -283,8 +283,40 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp, { struct class_device *class_dev = to_class_dev(kobj); int retval = 0; + int i = 0; + int length = 0; pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); + + if (class_dev->dev) { + /* add physical device, backing this device */ + struct device *dev = class_dev->dev; + char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); + + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, + &length, "PHYSDEVPATH=%s", path); + kfree(path); + + /* add bus name of physical device */ + if (dev->bus) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVBUS=%s", dev->bus->name); + + /* add driver name of physical device */ + if (dev->driver) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVDRIVER=%s", dev->driver->name); + + /* terminate, set to next free slot, shrink available space */ + envp[i] = NULL; + envp = &envp[i]; + num_envp -= i; + buffer = &buffer[length]; + buffer_size -= length; + } + if (class_dev->class->hotplug) { /* have the bus specific function add its stuff */ retval = class_dev->class->hotplug (class_dev, envp, num_envp, @@ -349,21 +381,26 @@ void class_device_initialize(struct class_device *class_dev) int class_device_add(struct class_device *class_dev) { - struct class * parent; + struct class * parent = NULL; struct class_interface * class_intf; int error; class_dev = class_device_get(class_dev); - if (!class_dev || !strlen(class_dev->class_id)) + if (!class_dev) return -EINVAL; + if (!strlen(class_dev->class_id)) { + error = -EINVAL; + goto register_done; + } + parent = class_get(class_dev->class); pr_debug("CLASS: registering class device: ID = '%s'\n", class_dev->class_id); /* first, register with generic layer. */ - kobject_set_name(&class_dev->kobj, class_dev->class_id); + kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); if (parent) class_dev->kobj.parent = &parent->subsys.kset.kobj; @@ -523,22 +560,22 @@ int __init classes_init(void) return 0; } -EXPORT_SYMBOL(class_create_file); -EXPORT_SYMBOL(class_remove_file); -EXPORT_SYMBOL(class_register); -EXPORT_SYMBOL(class_unregister); -EXPORT_SYMBOL(class_get); -EXPORT_SYMBOL(class_put); - -EXPORT_SYMBOL(class_device_register); -EXPORT_SYMBOL(class_device_unregister); -EXPORT_SYMBOL(class_device_initialize); -EXPORT_SYMBOL(class_device_add); -EXPORT_SYMBOL(class_device_del); -EXPORT_SYMBOL(class_device_get); -EXPORT_SYMBOL(class_device_put); -EXPORT_SYMBOL(class_device_create_file); -EXPORT_SYMBOL(class_device_remove_file); - -EXPORT_SYMBOL(class_interface_register); -EXPORT_SYMBOL(class_interface_unregister); +EXPORT_SYMBOL_GPL(class_create_file); +EXPORT_SYMBOL_GPL(class_remove_file); +EXPORT_SYMBOL_GPL(class_register); +EXPORT_SYMBOL_GPL(class_unregister); +EXPORT_SYMBOL_GPL(class_get); +EXPORT_SYMBOL_GPL(class_put); + +EXPORT_SYMBOL_GPL(class_device_register); +EXPORT_SYMBOL_GPL(class_device_unregister); +EXPORT_SYMBOL_GPL(class_device_initialize); +EXPORT_SYMBOL_GPL(class_device_add); +EXPORT_SYMBOL_GPL(class_device_del); +EXPORT_SYMBOL_GPL(class_device_get); +EXPORT_SYMBOL_GPL(class_device_put); +EXPORT_SYMBOL_GPL(class_device_create_file); +EXPORT_SYMBOL_GPL(class_device_remove_file); + +EXPORT_SYMBOL_GPL(class_interface_register); +EXPORT_SYMBOL_GPL(class_interface_unregister); diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c index 3410636de..8a3b8fa7e 100644 --- a/drivers/base/class_simple.c +++ b/drivers/base/class_simple.c @@ -122,7 +122,7 @@ EXPORT_SYMBOL(class_simple_destroy); * be created, showing the dev_t for the device. The pointer to the struct * class_device will be returned from the call. Any further sysfs files that * might be required can be created using this pointer. - * Note: the struct class_device passed to this function must have previously been + * Note: the struct class_simple passed to this function must have previously been * created with a call to class_simple_create(). */ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...) diff --git a/drivers/base/core.c b/drivers/base/core.c index 153cdc48b..4e6cce8e6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -116,8 +116,29 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp, int num_envp, char *buffer, int buffer_size) { struct device *dev = to_dev(kobj); + int i = 0; + int length = 0; int retval = 0; + /* add bus name of physical device */ + if (dev->bus) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVBUS=%s", dev->bus->name); + + /* add driver name of physical device */ + if (dev->driver) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVDRIVER=%s", dev->driver->name); + + /* terminate, set to next free slot, shrink available space */ + envp[i] = NULL; + envp = &envp[i]; + num_envp -= i; + buffer = &buffer[length]; + buffer_size -= length; + if (dev->bus->hotplug) { /* have the bus specific function add its stuff */ retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size); @@ -209,19 +230,19 @@ void device_initialize(struct device *dev) */ int device_add(struct device *dev) { - struct device * parent; - int error; + struct device *parent = NULL; + int error = -EINVAL; dev = get_device(dev); if (!dev || !strlen(dev->bus_id)) - return -EINVAL; + goto Error; parent = get_device(dev->parent); pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); /* first, register with generic layer. */ - kobject_set_name(&dev->kobj, dev->bus_id); + kobject_set_name(&dev->kobj, "%s", dev->bus_id); if (parent) dev->kobj.parent = &parent->kobj; @@ -293,7 +314,8 @@ struct device * get_device(struct device * dev) */ void put_device(struct device * dev) { - kobject_put(&dev->kobj); + if (dev) + kobject_put(&dev->kobj); } @@ -401,17 +423,17 @@ int __init devices_init(void) return subsystem_register(&devices_subsys); } -EXPORT_SYMBOL(device_for_each_child); +EXPORT_SYMBOL_GPL(device_for_each_child); -EXPORT_SYMBOL(device_initialize); -EXPORT_SYMBOL(device_add); -EXPORT_SYMBOL(device_register); +EXPORT_SYMBOL_GPL(device_initialize); +EXPORT_SYMBOL_GPL(device_add); +EXPORT_SYMBOL_GPL(device_register); -EXPORT_SYMBOL(device_del); -EXPORT_SYMBOL(device_unregister); -EXPORT_SYMBOL(get_device); -EXPORT_SYMBOL(put_device); -EXPORT_SYMBOL(device_find); +EXPORT_SYMBOL_GPL(device_del); +EXPORT_SYMBOL_GPL(device_unregister); +EXPORT_SYMBOL_GPL(get_device); +EXPORT_SYMBOL_GPL(put_device); +EXPORT_SYMBOL_GPL(device_find); -EXPORT_SYMBOL(device_create_file); -EXPORT_SYMBOL(device_remove_file); +EXPORT_SYMBOL_GPL(device_create_file); +EXPORT_SYMBOL_GPL(device_remove_file); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index aa66d7198..42f4337f9 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -32,6 +32,8 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, switch (buf[0]) { case '0': ret = cpu_down(cpu->sysdev.id); + if (!ret) + kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); break; case '1': ret = cpu_up(cpu->sysdev.id); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 735bd1702..9556f912f 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -129,11 +129,11 @@ struct device_driver *driver_find(const char *name, struct bus_type *bus) return NULL; } -EXPORT_SYMBOL(driver_register); -EXPORT_SYMBOL(driver_unregister); -EXPORT_SYMBOL(get_driver); -EXPORT_SYMBOL(put_driver); -EXPORT_SYMBOL(driver_find); - -EXPORT_SYMBOL(driver_create_file); -EXPORT_SYMBOL(driver_remove_file); +EXPORT_SYMBOL_GPL(driver_register); +EXPORT_SYMBOL_GPL(driver_unregister); +EXPORT_SYMBOL_GPL(get_driver); +EXPORT_SYMBOL_GPL(put_driver); +EXPORT_SYMBOL_GPL(driver_find); + +EXPORT_SYMBOL_GPL(driver_create_file); +EXPORT_SYMBOL_GPL(driver_remove_file); diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c index 0cff0498e..88ab04493 100644 --- a/drivers/base/firmware.c +++ b/drivers/base/firmware.c @@ -30,5 +30,5 @@ int __init firmware_init(void) return subsystem_register(&firmware_subsys); } -EXPORT_SYMBOL(firmware_register); -EXPORT_SYMBOL(firmware_unregister); +EXPORT_SYMBOL_GPL(firmware_register); +EXPORT_SYMBOL_GPL(firmware_unregister); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index a57ba84eb..26c9464af 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -94,19 +94,17 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); - int i = 0; - char *scratch = buffer; + int i = 0, len = 0; if (!test_bit(FW_STATUS_READY, &fw_priv->status)) return -ENODEV; - if (buffer_size < (FIRMWARE_NAME_MAX + 10)) - return -ENOMEM; - if (num_envp < 1) + if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, + "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; - envp[i++] = scratch; - scratch += sprintf(scratch, "FIRMWARE=%s", fw_priv->fw_id) + 1; + envp[i] = NULL; + return 0; } @@ -235,6 +233,8 @@ firmware_data_write(struct kobject *kobj, struct firmware *fw; ssize_t retval; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; down(&fw_lock); fw = fw_priv->fw; if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { @@ -420,7 +420,7 @@ request_firmware(const struct firmware **firmware_p, const char *name, add_timer(&fw_priv->timeout); } - kobject_hotplug("add", &class_dev->kobj); + kobject_hotplug(&class_dev->kobj, KOBJ_ADD); wait_for_completion(&fw_priv->completion); set_bit(FW_STATUS_DONE, &fw_priv->status); @@ -439,6 +439,7 @@ request_firmware(const struct firmware **firmware_p, const char *name, error_kfree_fw: kfree(firmware); + *firmware_p = NULL; out: return retval; } @@ -580,4 +581,3 @@ EXPORT_SYMBOL(release_firmware); EXPORT_SYMBOL(request_firmware); EXPORT_SYMBOL(request_firmware_nowait); EXPORT_SYMBOL(register_firmware); -EXPORT_SYMBOL(firmware_class); diff --git a/drivers/base/node.c b/drivers/base/node.c index c1187363f..df74785ef 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -19,7 +19,7 @@ static struct sysdev_class node_class = { static ssize_t node_read_cpumap(struct sys_device * dev, char * buf) { struct node *node_dev = to_node(dev); - cpumask_t mask = node_dev->cpumap; + cpumask_t mask = node_to_cpumask(node_dev->sysdev.id); int len; /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */ @@ -38,11 +38,19 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) int n; int nid = dev->id; struct sysinfo i; + unsigned long inactive; + unsigned long active; + unsigned long free; + si_meminfo_node(&i, nid); + __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); + n = sprintf(buf, "\n" "Node %d MemTotal: %8lu kB\n" "Node %d MemFree: %8lu kB\n" "Node %d MemUsed: %8lu kB\n" + "Node %d Active: %8lu kB\n" + "Node %d Inactive: %8lu kB\n" "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" "Node %d LowTotal: %8lu kB\n" @@ -50,6 +58,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), + nid, K(active), + nid, K(inactive), nid, K(i.totalhigh), nid, K(i.freehigh), nid, K(i.totalram - i.totalhigh), @@ -111,7 +121,6 @@ int __init register_node(struct node *node, int num, struct node *parent) { int error; - node->cpumap = node_to_cpumask(num); node->sysdev.id = num; node->sysdev.cls = &node_class; error = sysdev_register(&node->sysdev); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9f285ed4e..04451da00 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -298,13 +298,13 @@ u64 dma_get_required_mask(struct device *dev) } return mask & *dev->dma_mask; } -EXPORT_SYMBOL(dma_get_required_mask); +EXPORT_SYMBOL_GPL(dma_get_required_mask); #endif -EXPORT_SYMBOL(platform_bus); -EXPORT_SYMBOL(platform_bus_type); -EXPORT_SYMBOL(platform_device_register); -EXPORT_SYMBOL(platform_device_register_simple); -EXPORT_SYMBOL(platform_device_unregister); -EXPORT_SYMBOL(platform_get_irq); -EXPORT_SYMBOL(platform_get_resource); +EXPORT_SYMBOL_GPL(platform_bus); +EXPORT_SYMBOL_GPL(platform_bus_type); +EXPORT_SYMBOL_GPL(platform_device_register); +EXPORT_SYMBOL_GPL(platform_device_register_simple); +EXPORT_SYMBOL_GPL(platform_device_unregister); +EXPORT_SYMBOL_GPL(platform_get_irq); +EXPORT_SYMBOL_GPL(platform_get_resource); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 635ea2001..15e6a8f95 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -28,6 +28,7 @@ LIST_HEAD(dpm_off); LIST_HEAD(dpm_off_irq); DECLARE_MUTEX(dpm_sem); +DECLARE_MUTEX(dpm_list_sem); /* * PM Reference Counting. @@ -66,7 +67,7 @@ void device_pm_set_parent(struct device * dev, struct device * parent) dev->power.pm_parent = parent; device_pm_hold(parent); } -EXPORT_SYMBOL(device_pm_set_parent); +EXPORT_SYMBOL_GPL(device_pm_set_parent); int device_pm_add(struct device * dev) { @@ -75,12 +76,12 @@ int device_pm_add(struct device * dev) pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); atomic_set(&dev->power.pm_users, 0); - down(&dpm_sem); + down(&dpm_list_sem); list_add_tail(&dev->power.entry, &dpm_active); device_pm_set_parent(dev, dev->parent); if ((error = dpm_sysfs_add(dev))) list_del(&dev->power.entry); - up(&dpm_sem); + up(&dpm_list_sem); return error; } @@ -88,11 +89,11 @@ void device_pm_remove(struct device * dev) { pr_debug("PM: Removing info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", dev->kobj.name); - down(&dpm_sem); + down(&dpm_list_sem); dpm_sysfs_remove(dev); device_pm_release(dev->power.pm_parent); - list_del(&dev->power.entry); - up(&dpm_sem); + list_del_init(&dev->power.entry); + up(&dpm_list_sem); } diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 6971cc667..66cb431b1 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -27,6 +27,11 @@ extern void device_shutdown(void); */ extern struct semaphore dpm_sem; +/* + * Used to serialize changes to the dpm_* lists. + */ +extern struct semaphore dpm_list_sem; + /* * The PM lists. */ diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 1d830be4c..f8f505575 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -31,16 +31,22 @@ int resume_device(struct device * dev) void dpm_resume(void) { + down(&dpm_list_sem); while(!list_empty(&dpm_off)) { struct list_head * entry = dpm_off.next; struct device * dev = to_device(entry); + + get_device(dev); list_del_init(entry); + list_add_tail(entry, &dpm_active); + up(&dpm_list_sem); if (!dev->power.prev_state) resume_device(dev); - - list_add_tail(entry, &dpm_active); + down(&dpm_list_sem); + put_device(dev); } + up(&dpm_list_sem); } @@ -58,7 +64,7 @@ void device_resume(void) up(&dpm_sem); } -EXPORT_SYMBOL(device_resume); +EXPORT_SYMBOL_GPL(device_resume); /** @@ -76,9 +82,13 @@ void dpm_power_up(void) { while(!list_empty(&dpm_off_irq)) { struct list_head * entry = dpm_off_irq.next; + struct device * dev = to_device(entry); + + get_device(dev); list_del_init(entry); - resume_device(to_device(entry)); list_add_tail(entry, &dpm_active); + resume_device(dev); + put_device(dev); } } @@ -97,6 +107,6 @@ void device_power_up(void) dpm_power_up(); } -EXPORT_SYMBOL(device_power_up); +EXPORT_SYMBOL_GPL(device_power_up); diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 86f9e6ec0..94c1311ee 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -63,11 +63,6 @@ int suspend_device(struct device * dev, u32 state) * If we hit a failure with any of the devices, call device_resume() * above to bring the suspended devices back to life. * - * Note this function leaves dpm_sem held to - * a) block other devices from registering. - * b) prevent other PM operations from happening after we've begun. - * c) make sure we're exclusive when we disable interrupts. - * */ int device_suspend(u32 state) @@ -75,32 +70,43 @@ int device_suspend(u32 state) int error = 0; down(&dpm_sem); - while(!list_empty(&dpm_active)) { + down(&dpm_list_sem); + while (!list_empty(&dpm_active) && error == 0) { struct list_head * entry = dpm_active.prev; struct device * dev = to_device(entry); + + get_device(dev); + up(&dpm_list_sem); + error = suspend_device(dev, state); - if (!error) { - list_del(&dev->power.entry); - list_add(&dev->power.entry, &dpm_off); - } else if (error == -EAGAIN) { - list_del(&dev->power.entry); - list_add(&dev->power.entry, &dpm_off_irq); - } else { + down(&dpm_list_sem); + + /* Check if the device got removed */ + if (!list_empty(&dev->power.entry)) { + /* Move it to the dpm_off or dpm_off_irq list */ + if (!error) { + list_del(&dev->power.entry); + list_add(&dev->power.entry, &dpm_off); + } else if (error == -EAGAIN) { + list_del(&dev->power.entry); + list_add(&dev->power.entry, &dpm_off_irq); + error = 0; + } + } + if (error) printk(KERN_ERR "Could not suspend device %s: " "error %d\n", kobject_name(&dev->kobj), error); - goto Error; - } + put_device(dev); } - Done: + up(&dpm_list_sem); + if (error) + dpm_resume(); up(&dpm_sem); return error; - Error: - dpm_resume(); - goto Done; } -EXPORT_SYMBOL(device_suspend); +EXPORT_SYMBOL_GPL(device_suspend); /** @@ -132,5 +138,5 @@ int device_power_down(u32 state) goto Done; } -EXPORT_SYMBOL(device_power_down); +EXPORT_SYMBOL_GPL(device_power_down); diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 9d10500cd..c3a99df3c 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -73,8 +73,8 @@ void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) sysfs_remove_file(&s->kobj, &a->attr); } -EXPORT_SYMBOL(sysdev_create_file); -EXPORT_SYMBOL(sysdev_remove_file); +EXPORT_SYMBOL_GPL(sysdev_create_file); +EXPORT_SYMBOL_GPL(sysdev_remove_file); /* * declare system_subsys @@ -98,8 +98,8 @@ void sysdev_class_unregister(struct sysdev_class * cls) kset_unregister(&cls->kset); } -EXPORT_SYMBOL(sysdev_class_register); -EXPORT_SYMBOL(sysdev_class_unregister); +EXPORT_SYMBOL_GPL(sysdev_class_register); +EXPORT_SYMBOL_GPL(sysdev_class_unregister); static LIST_HEAD(global_drivers); @@ -157,8 +157,8 @@ void sysdev_driver_unregister(struct sysdev_class * cls, up_write(&system_subsys.rwsem); } -EXPORT_SYMBOL(sysdev_driver_register); -EXPORT_SYMBOL(sysdev_driver_unregister); +EXPORT_SYMBOL_GPL(sysdev_driver_register); +EXPORT_SYMBOL_GPL(sysdev_driver_unregister); @@ -392,5 +392,5 @@ int __init system_bus_init(void) return subsystem_register(&system_subsys); } -EXPORT_SYMBOL(sysdev_register); -EXPORT_SYMBOL(sysdev_unregister); +EXPORT_SYMBOL_GPL(sysdev_register); +EXPORT_SYMBOL_GPL(sysdev_unregister); diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 56b9ce97c..9d28e25fc 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -288,12 +288,17 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) Controller->PCIDevice, DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T), sizeof(DAC960_V2_ScatterGatherSegment_T), 0); + if (ScatterGatherPool == NULL) + return DAC960_Failure(Controller, + "AUXILIARY STRUCTURE CREATION (SG)"); RequestSensePool = pci_pool_create("DAC960_V2_RequestSense", Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T), sizeof(int), 0); - if (ScatterGatherPool == NULL || RequestSensePool == NULL) + if (RequestSensePool == NULL) { + pci_pool_destroy(ScatterGatherPool); return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION (SG)"); + } Controller->ScatterGatherPool = ScatterGatherPool; Controller->V2.RequestSensePool = RequestSensePool; } @@ -535,7 +540,7 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) static void DAC960_BA_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandMailbox_T *NextCommandMailbox = Controller->V2.NextCommandMailbox; @@ -560,7 +565,7 @@ static void DAC960_BA_QueueCommand(DAC960_Command_T *Command) static void DAC960_LP_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandMailbox_T *NextCommandMailbox = Controller->V2.NextCommandMailbox; @@ -586,7 +591,7 @@ static void DAC960_LP_QueueCommand(DAC960_Command_T *Command) static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox = Controller->V1.NextCommandMailbox; @@ -612,7 +617,7 @@ static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command) static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox = Controller->V1.NextCommandMailbox; @@ -638,7 +643,7 @@ static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command) static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox = Controller->V1.NextCommandMailbox; @@ -664,7 +669,7 @@ static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command) static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; DAC960_V1_CommandMailbox_T *NextCommandMailbox = Controller->V1.NextCommandMailbox; @@ -689,7 +694,7 @@ static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command) static void DAC960_PD_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; while (DAC960_PD_MailboxFullP(ControllerBaseAddress)) @@ -706,7 +711,7 @@ static void DAC960_PD_QueueCommand(DAC960_Command_T *Command) static void DAC960_P_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; switch (CommandMailbox->Common.CommandOpcode) @@ -1127,7 +1132,7 @@ static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller, static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_HardwareType_T hw_type = Controller->HardwareType; struct pci_dev *PCI_Device = Controller->PCIDevice; struct dma_loaf *DmaPages = &Controller->DmaPages; @@ -1333,7 +1338,7 @@ skip_mailboxes: static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T *Controller) { - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; struct pci_dev *PCI_Device = Controller->PCIDevice; struct dma_loaf *DmaPages = &Controller->DmaPages; size_t DmaPagesSize; @@ -2673,8 +2678,8 @@ DAC960_DetectController(struct pci_dev *PCI_Device, DAC960_Controller_T *Controller = NULL; unsigned char DeviceFunction = PCI_Device->devfn; unsigned char ErrorStatus, Parameter0, Parameter1; - unsigned int IRQ_Channel = PCI_Device->irq; - void *BaseAddress; + unsigned int IRQ_Channel; + void __iomem *BaseAddress; int i; Controller = (DAC960_Controller_T *) @@ -2953,6 +2958,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device, /* Acquire shared access to the IRQ Channel. */ + IRQ_Channel = PCI_Device->irq; if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, Controller->FullModelName, Controller) < 0) { @@ -5196,7 +5202,7 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_StatusMailbox_T *NextStatusMailbox; unsigned long flags; @@ -5239,7 +5245,7 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_StatusMailbox_T *NextStatusMailbox; unsigned long flags; @@ -5282,7 +5288,7 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_StatusMailbox_T *NextStatusMailbox; unsigned long flags; @@ -5321,7 +5327,7 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_StatusMailbox_T *NextStatusMailbox; unsigned long flags; @@ -5360,7 +5366,7 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; unsigned long flags; spin_lock_irqsave(&Controller->queue_lock, flags); @@ -5399,7 +5405,7 @@ static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel, struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; - void *ControllerBaseAddress = Controller->BaseAddress; + void __iomem *ControllerBaseAddress = Controller->BaseAddress; unsigned long flags; spin_lock_irqsave(&Controller->queue_lock, flags); diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index be8f8992a..d5e8e7190 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -2282,8 +2282,8 @@ DAC960_Command_T; typedef struct DAC960_Controller { - void *BaseAddress; - void *MemoryMappedAddress; + void __iomem *BaseAddress; + void __iomem *MemoryMappedAddress; DAC960_FirmwareType_T FirmwareType; DAC960_HardwareType_T HardwareType; DAC960_IO_Address_T IO_Address; @@ -2527,7 +2527,7 @@ DAC960_Controller_T; * dma_addr_t. */ static inline -void dma_addr_writeql(dma_addr_t addr, void *write_address) +void dma_addr_writeql(dma_addr_t addr, void __iomem *write_address) { union { u64 wq; @@ -2643,7 +2643,7 @@ DAC960_BA_ErrorStatusRegister_T; */ static inline -void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_BA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2653,7 +2653,7 @@ void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress) } static inline -void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_BA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2663,7 +2663,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) } static inline -void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_BA_GenerateInterrupt(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2673,7 +2673,7 @@ void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_BA_ControllerReset(void *ControllerBaseAddress) +void DAC960_BA_ControllerReset(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2683,7 +2683,7 @@ void DAC960_BA_ControllerReset(void *ControllerBaseAddress) } static inline -void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_BA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2693,7 +2693,7 @@ void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress) } static inline -boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -2702,7 +2702,7 @@ boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress) } static inline -boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress) { DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -2711,7 +2711,7 @@ boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress) } static inline -void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -2721,7 +2721,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -2731,7 +2731,7 @@ void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_BA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress) { DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -2742,7 +2742,7 @@ void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress) } static inline -boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -2751,7 +2751,7 @@ boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -2760,7 +2760,7 @@ boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_BA_EnableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -2771,7 +2771,7 @@ void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress) } static inline -void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_BA_DisableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -2782,7 +2782,7 @@ void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress) } static inline -boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress) { DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = @@ -2805,7 +2805,7 @@ void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T static inline -void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, +void DAC960_BA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress, dma_addr_t CommandMailboxDMA) { dma_addr_writeql(CommandMailboxDMA, @@ -2814,19 +2814,19 @@ void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, } static inline DAC960_V2_CommandIdentifier_T -DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress) +DAC960_BA_ReadCommandIdentifier(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset); } static inline DAC960_V2_CommandStatus_T -DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress) +DAC960_BA_ReadCommandStatus(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2); } static inline boolean -DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_BA_ReadErrorStatus(void __iomem *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) @@ -2948,7 +2948,7 @@ DAC960_LP_ErrorStatusRegister_T; */ static inline -void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LP_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2958,7 +2958,7 @@ void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress) } static inline -void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_LP_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2968,7 +2968,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) } static inline -void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_LP_GenerateInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2978,7 +2978,7 @@ void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LP_ControllerReset(void *ControllerBaseAddress) +void DAC960_LP_ControllerReset(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2988,7 +2988,7 @@ void DAC960_LP_ControllerReset(void *ControllerBaseAddress) } static inline -void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LP_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -2998,7 +2998,7 @@ void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress) } static inline -boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3007,7 +3007,7 @@ boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress) } static inline -boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress) { DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3016,7 +3016,7 @@ boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress) } static inline -void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3026,7 +3026,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3036,7 +3036,7 @@ void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_LP_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3047,7 +3047,7 @@ void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress) } static inline -boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3056,7 +3056,7 @@ boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3065,7 +3065,7 @@ boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_LP_EnableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -3075,7 +3075,7 @@ void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress) } static inline -void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_LP_DisableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -3085,7 +3085,7 @@ void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress) } static inline -boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress) { DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = @@ -3107,7 +3107,7 @@ void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T } static inline -void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, +void DAC960_LP_WriteHardwareMailbox(void __iomem *ControllerBaseAddress, dma_addr_t CommandMailboxDMA) { dma_addr_writeql(CommandMailboxDMA, @@ -3116,19 +3116,19 @@ void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, } static inline DAC960_V2_CommandIdentifier_T -DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress) +DAC960_LP_ReadCommandIdentifier(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset); } static inline DAC960_V2_CommandStatus_T -DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress) +DAC960_LP_ReadCommandStatus(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2); } static inline boolean -DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_LP_ReadErrorStatus(void __iomem *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) @@ -3262,7 +3262,7 @@ DAC960_LA_ErrorStatusRegister_T; */ static inline -void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3272,7 +3272,7 @@ void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress) } static inline -void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3282,7 +3282,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) } static inline -void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_LA_GenerateInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3292,7 +3292,7 @@ void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LA_ControllerReset(void *ControllerBaseAddress) +void DAC960_LA_ControllerReset(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3302,7 +3302,7 @@ void DAC960_LA_ControllerReset(void *ControllerBaseAddress) } static inline -void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3312,7 +3312,7 @@ void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress) } static inline -boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3321,7 +3321,7 @@ boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress) } static inline -boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress) { DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3330,7 +3330,7 @@ boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress) } static inline -void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3340,7 +3340,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3350,7 +3350,7 @@ void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress) { DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3361,7 +3361,7 @@ void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress) } static inline -boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3370,7 +3370,7 @@ boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3379,7 +3379,7 @@ boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_EnableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -3389,7 +3389,7 @@ void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress) } static inline -void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_DisableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; @@ -3399,7 +3399,7 @@ void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress) } static inline -boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress) { DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = @@ -3422,7 +3422,7 @@ void DAC960_LA_WriteCommandMailbox(DAC960_V1_CommandMailbox_T } static inline -void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress, +void DAC960_LA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress, DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], @@ -3436,20 +3436,20 @@ void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress, } static inline DAC960_V1_CommandIdentifier_T -DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +DAC960_LA_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress) { return readb(ControllerBaseAddress + DAC960_LA_StatusCommandIdentifierRegOffset); } static inline DAC960_V1_CommandStatus_T -DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress) +DAC960_LA_ReadStatusRegister(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset); } static inline boolean -DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_LA_ReadErrorStatus(void __iomem *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) @@ -3583,7 +3583,7 @@ DAC960_PG_ErrorStatusRegister_T; */ static inline -void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3593,7 +3593,7 @@ void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress) } static inline -void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3603,7 +3603,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) } static inline -void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PG_GenerateInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3613,7 +3613,7 @@ void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_PG_ControllerReset(void *ControllerBaseAddress) +void DAC960_PG_ControllerReset(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3623,7 +3623,7 @@ void DAC960_PG_ControllerReset(void *ControllerBaseAddress) } static inline -void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3633,7 +3633,7 @@ void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress) } static inline -boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3642,7 +3642,7 @@ boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress) } static inline -boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress) { DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3651,7 +3651,7 @@ boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress) } static inline -void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3661,7 +3661,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3671,7 +3671,7 @@ void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3682,7 +3682,7 @@ void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress) } static inline -boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3691,7 +3691,7 @@ boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3700,7 +3700,7 @@ boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) } static inline -void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_EnableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; @@ -3712,7 +3712,7 @@ void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress) } static inline -void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_DisableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; @@ -3724,7 +3724,7 @@ void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress) } static inline -boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress) { DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = @@ -3747,7 +3747,7 @@ void DAC960_PG_WriteCommandMailbox(DAC960_V1_CommandMailbox_T } static inline -void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress, +void DAC960_PG_WriteHardwareMailbox(void __iomem *ControllerBaseAddress, DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], @@ -3761,20 +3761,20 @@ void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress, } static inline DAC960_V1_CommandIdentifier_T -DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +DAC960_PG_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress) { return readb(ControllerBaseAddress + DAC960_PG_StatusCommandIdentifierRegOffset); } static inline DAC960_V1_CommandStatus_T -DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress) +DAC960_PG_ReadStatusRegister(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset); } static inline boolean -DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PG_ReadErrorStatus(void __iomem *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) @@ -3903,7 +3903,7 @@ DAC960_PD_ErrorStatusRegister_T; */ static inline -void DAC960_PD_NewCommand(void *ControllerBaseAddress) +void DAC960_PD_NewCommand(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3913,7 +3913,7 @@ void DAC960_PD_NewCommand(void *ControllerBaseAddress) } static inline -void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeStatus(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3923,7 +3923,7 @@ void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress) } static inline -void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PD_GenerateInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3933,7 +3933,7 @@ void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress) } static inline -void DAC960_PD_ControllerReset(void *ControllerBaseAddress) +void DAC960_PD_ControllerReset(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; @@ -3943,7 +3943,7 @@ void DAC960_PD_ControllerReset(void *ControllerBaseAddress) } static inline -boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3952,7 +3952,7 @@ boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress) } static inline -boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress) { DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = @@ -3961,7 +3961,7 @@ boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress) } static inline -void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress) { DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; @@ -3971,7 +3971,7 @@ void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress) } static inline -boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress) { DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = @@ -3980,7 +3980,7 @@ boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress) } static inline -void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_EnableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; @@ -3990,7 +3990,7 @@ void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress) } static inline -void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_DisableInterrupts(void __iomem *ControllerBaseAddress) { DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; @@ -4000,7 +4000,7 @@ void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress) } static inline -boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress) { DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = @@ -4009,7 +4009,7 @@ boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress) } static inline -void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress, +void DAC960_PD_WriteCommandMailbox(void __iomem *ControllerBaseAddress, DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], @@ -4023,20 +4023,20 @@ void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress, } static inline DAC960_V1_CommandIdentifier_T -DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +DAC960_PD_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress) { return readb(ControllerBaseAddress + DAC960_PD_StatusCommandIdentifierRegOffset); } static inline DAC960_V1_CommandStatus_T -DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress) +DAC960_PD_ReadStatusRegister(void __iomem *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset); } static inline boolean -DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PD_ReadErrorStatus(void __iomem *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index c44f27f24..f4ed730a7 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -166,7 +166,7 @@ config BLK_CPQ_CISS_DA config CISS_SCSI_TAPE bool "SCSI tape drive support for Smart Array 5xxx" - depends on BLK_CPQ_CISS_DA && SCSI + depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS help When enabled (Y), this option allows SCSI tape drives and SCSI medium changers (tape robots) to be accessed via a Compaq 5xxx array @@ -301,6 +301,17 @@ config BLK_DEV_SX8 Use devices /dev/sx8/$N and /dev/sx8/$Np$M. +config BLK_DEV_UB + tristate "Low Performance USB Block driver" + depends on USB + help + This driver supports certain USB attached storage devices + such as flash keys. + + Warning: Enabling this cripples the usb-storage driver. + + If unsure, say N. + config BLK_DEV_RAM tristate "RAM disk support" ---help--- @@ -320,6 +331,14 @@ config BLK_DEV_RAM Most normal users won't need the RAM disk functionality, and can thus say N here. +config BLK_DEV_RAM_COUNT + int "Default number of RAM disks" if BLK_DEV_RAM + default "16" + help + The default value is 16 RAM disks. Change this if you know what + are doing. If you boot from a filesystem that needs to be extracted + in memory, you will need at least one RAM disk (e.g. root on cramfs). + config BLK_DEV_RAM_SIZE int "Default RAM disk size (kbytes)" depends on BLK_DEV_RAM @@ -339,6 +358,32 @@ config BLK_DEV_INITRD "real" root file system, etc. See for details. +config INITRAMFS_SOURCE + string "Source directory of cpio_list" + default "" + help + This can be set to either a directory containing files, etc to be + included in the initramfs archive, or a file containing newline + separated entries. + + If it is a file, it should be in the following format: + # a comment + file + dir + nod + + Where: + name of the file/dir/nod in the archive + location of the file in the current filesystem + mode/permissions of the file + user id (0=root) + group id (0=root) + device type (b=block, c=character) + major number of nod + minor number of nod + + If you are not sure, leave it blank. + config LBD bool "Support for Large Block Devices" depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH @@ -347,6 +392,41 @@ config LBD your machine, or if you want to have a raid or loopback device bigger than 2TB. Otherwise say N. +config CDROM_PKTCDVD + tristate "Packet writing on CD/DVD media" + help + If you have a CDROM drive that supports packet writing, say Y to + include preliminary support. It should work with any MMC/Mt Fuji + compliant ATAPI or SCSI drive, which is just about any newer CD + writer. + + Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible. + DVD-RW disks must be in restricted overwrite mode. + + To compile this driver as a module, choose M here: the + module will be called pktcdvd. + +config CDROM_PKTCDVD_BUFFERS + int "Free buffers for data gathering" + depends on CDROM_PKTCDVD + default "8" + help + This controls the maximum number of active concurrent packets. More + concurrent packets can increase write performance, but also require + more memory. Each concurrent packet will require approximately 64Kb + of non-swappable kernel memory, memory which will be allocated at + pktsetup time. + +config CDROM_PKTCDVD_WCACHE + bool "Enable write caching" + depends on CDROM_PKTCDVD + help + If enabled, write caching will be set for the CD-R/W device. For now + this option is dangerous unless the CD-RW media is known good, as we + don't do deferred write error handling yet. + source "drivers/s390/block/Kconfig" +source "drivers/block/Kconfig.iosched" + endmenu diff --git a/drivers/block/Kconfig.iosched b/drivers/block/Kconfig.iosched index d938c5fd1..6070a4806 100644 --- a/drivers/block/Kconfig.iosched +++ b/drivers/block/Kconfig.iosched @@ -1,5 +1,8 @@ + +menu "IO Schedulers" + config IOSCHED_NOOP - bool "No-op I/O scheduler" if EMBEDDED + bool default y ---help--- The no-op I/O scheduler is a minimal scheduler that does basic merging @@ -9,7 +12,7 @@ config IOSCHED_NOOP the kernel. config IOSCHED_AS - bool "Anticipatory I/O scheduler" if EMBEDDED + tristate "Anticipatory I/O scheduler" default y ---help--- The anticipatory I/O scheduler is the default disk scheduler. It is @@ -18,7 +21,7 @@ config IOSCHED_AS slower in some cases especially some database loads. config IOSCHED_DEADLINE - bool "Deadline I/O scheduler" if EMBEDDED + tristate "Deadline I/O scheduler" default y ---help--- The deadline I/O scheduler is simple and compact, and is often as @@ -28,9 +31,11 @@ config IOSCHED_DEADLINE anticipatory I/O scheduler and so is a good choice. config IOSCHED_CFQ - bool "CFQ I/O scheduler" if EMBEDDED + tristate "CFQ I/O scheduler" default y ---help--- The CFQ I/O scheduler tries to distribute bandwidth equally among all processes in the system. It should provide a fair working environment, suitable for desktop systems. + +endmenu diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 2654b5b76..1cf09a1c0 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o +obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o @@ -42,4 +43,5 @@ obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o obj-$(CONFIG_VIODASD) += viodasd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o +obj-$(CONFIG_BLK_DEV_UB) += ub.o diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 42c1e5663..19ca2e57e 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -105,9 +105,9 @@ #define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */ #define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */ -static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ +static unsigned long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ -MODULE_PARM(fd_def_df0,"l"); +module_param(fd_def_df0, ulong, 0); MODULE_LICENSE("GPL"); static struct request_queue *floppy_queue; @@ -386,16 +386,6 @@ static void fd_motor_off(unsigned long drive) fd_select(drive); udelay (1); fd_deselect(drive); - -#ifdef MODULE -/* - this is the last interrupt for any drive access, happens after - release (from floppy_off). So we have to wait until now to decrease - the use count. -*/ - if (decusecount) - MOD_DEC_USE_COUNT; -#endif } static void floppy_off (unsigned int nr) @@ -1590,10 +1580,6 @@ static int floppy_open(struct inode *inode, struct file *filp) local_irq_save(flags); fd_ref[drive]++; fd_device[drive] = system; -#ifdef MODULE - if (unit[drive].motor == 0) - MOD_INC_USE_COUNT; -#endif local_irq_restore(flags); unit[drive].dtype=&data_types[system]; @@ -1839,6 +1825,7 @@ int init_module(void) return amiga_floppy_init(); } +#if 0 /* not safe to unload */ void cleanup_module(void) { int i; @@ -1860,3 +1847,4 @@ void cleanup_module(void) unregister_blkdev(FLOPPY_MAJOR, "fd"); } #endif +#endif diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 0ef6a665d..fb625b49b 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -614,7 +614,7 @@ static void as_antic_stop(struct as_data *ad) static void as_antic_timeout(unsigned long data) { struct request_queue *q = (struct request_queue *)data; - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -945,7 +945,7 @@ static void update_write_batch(struct as_data *ad) */ static void as_completed_request(request_queue_t *q, struct request *rq) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(rq); WARN_ON(!list_empty(&rq->queuelist)); @@ -1030,7 +1030,7 @@ static void as_remove_queued_request(request_queue_t *q, struct request *rq) { struct as_rq *arq = RQ_DATA(rq); const int data_dir = arq->is_sync; - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; WARN_ON(arq->state != AS_RQ_QUEUED); @@ -1361,7 +1361,7 @@ fifo_expired: static struct request *as_next_request(request_queue_t *q) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct request *rq = NULL; /* @@ -1469,7 +1469,7 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq) */ static void as_requeue_request(request_queue_t *q, struct request *rq) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(rq); if (arq) { @@ -1509,7 +1509,7 @@ static void as_account_queued_request(struct as_data *ad, struct request *rq) static void as_insert_request(request_queue_t *q, struct request *rq, int where) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(rq); if (arq) { @@ -1562,7 +1562,7 @@ as_insert_request(request_queue_t *q, struct request *rq, int where) */ static int as_queue_empty(request_queue_t *q) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; if (!list_empty(&ad->fifo_list[REQ_ASYNC]) || !list_empty(&ad->fifo_list[REQ_SYNC]) @@ -1601,7 +1601,7 @@ as_latter_request(request_queue_t *q, struct request *rq) static int as_merge(request_queue_t *q, struct request **req, struct bio *bio) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; sector_t rb_key = bio->bi_sector + bio_sectors(bio); struct request *__rq; int ret; @@ -1656,7 +1656,7 @@ out_insert: static void as_merged_request(request_queue_t *q, struct request *req) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(req); /* @@ -1701,7 +1701,7 @@ static void as_merged_requests(request_queue_t *q, struct request *req, struct request *next) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(req); struct as_rq *anext = RQ_DATA(next); @@ -1788,7 +1788,7 @@ static void as_work_handler(void *data) static void as_put_request(request_queue_t *q, struct request *rq) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(rq); if (!arq) { @@ -1807,7 +1807,7 @@ static void as_put_request(request_queue_t *q, struct request *rq) static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { - struct as_data *ad = q->elevator.elevator_data; + struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); if (arq) { @@ -1828,21 +1828,21 @@ static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask) static int as_may_queue(request_queue_t *q, int rw) { - int ret = 0; - struct as_data *ad = q->elevator.elevator_data; + int ret = ELV_MQUEUE_MAY; + struct as_data *ad = q->elevator->elevator_data; struct io_context *ioc; if (ad->antic_status == ANTIC_WAIT_REQ || ad->antic_status == ANTIC_WAIT_NEXT) { ioc = as_get_io_context(); if (ad->io_context == ioc) - ret = 1; + ret = ELV_MQUEUE_MUST; put_io_context(ioc); } return ret; } -static void as_exit(request_queue_t *q, elevator_t *e) +static void as_exit_queue(elevator_t *e) { struct as_data *ad = e->elevator_data; @@ -1862,7 +1862,7 @@ static void as_exit(request_queue_t *q, elevator_t *e) * initialize elevator private data (as_data), and alloc a arq for * each request on the free lists */ -static int as_init(request_queue_t *q, elevator_t *e) +static int as_init_queue(request_queue_t *q, elevator_t *e) { struct as_data *ad; int i; @@ -1962,10 +1962,10 @@ static ssize_t as_est_show(struct as_data *ad, char *page) return pos; } -#define SHOW_FUNCTION(__FUNC, __VAR) \ +#define SHOW_FUNCTION(__FUNC, __VAR) \ static ssize_t __FUNC(struct as_data *ad, char *page) \ -{ \ - return as_var_show(__VAR, (page)); \ +{ \ + return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ } SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]); @@ -1982,6 +1982,7 @@ static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \ *(__PTR) = (MIN); \ else if (*(__PTR) > (MAX)) \ *(__PTR) = (MAX); \ + *(__PTR) = msecs_to_jiffies(*(__PTR)); \ return ret; \ } STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX); @@ -2070,39 +2071,64 @@ static struct kobj_type as_ktype = { .default_attrs = default_attrs, }; -static int __init as_slab_setup(void) +static struct elevator_type iosched_as = { + .ops = { + .elevator_merge_fn = as_merge, + .elevator_merged_fn = as_merged_request, + .elevator_merge_req_fn = as_merged_requests, + .elevator_next_req_fn = as_next_request, + .elevator_add_req_fn = as_insert_request, + .elevator_remove_req_fn = as_remove_request, + .elevator_requeue_req_fn = as_requeue_request, + .elevator_queue_empty_fn = as_queue_empty, + .elevator_completed_req_fn = as_completed_request, + .elevator_former_req_fn = as_former_request, + .elevator_latter_req_fn = as_latter_request, + .elevator_set_req_fn = as_set_request, + .elevator_put_req_fn = as_put_request, + .elevator_may_queue_fn = as_may_queue, + .elevator_init_fn = as_init_queue, + .elevator_exit_fn = as_exit_queue, + }, + + .elevator_ktype = &as_ktype, + .elevator_name = "anticipatory", + .elevator_owner = THIS_MODULE, +}; + +static int __init as_init(void) { + int ret; + arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq), 0, 0, NULL, NULL); - if (!arq_pool) - panic("as: can't init slab pool\n"); + return -ENOMEM; - return 0; + ret = elv_register(&iosched_as); + if (!ret) { + /* + * don't allow AS to get unregistered, since we would have + * to browse all tasks in the system and release their + * as_io_context first + */ + __module_get(THIS_MODULE); + return 0; + } + + kmem_cache_destroy(arq_pool); + return ret; } -subsys_initcall(as_slab_setup); - -elevator_t iosched_as = { - .elevator_merge_fn = as_merge, - .elevator_merged_fn = as_merged_request, - .elevator_merge_req_fn = as_merged_requests, - .elevator_next_req_fn = as_next_request, - .elevator_add_req_fn = as_insert_request, - .elevator_remove_req_fn = as_remove_request, - .elevator_requeue_req_fn = as_requeue_request, - .elevator_queue_empty_fn = as_queue_empty, - .elevator_completed_req_fn = as_completed_request, - .elevator_former_req_fn = as_former_request, - .elevator_latter_req_fn = as_latter_request, - .elevator_set_req_fn = as_set_request, - .elevator_put_req_fn = as_put_request, - .elevator_may_queue_fn = as_may_queue, - .elevator_init_fn = as_init, - .elevator_exit_fn = as_exit, - - .elevator_ktype = &as_ktype, - .elevator_name = "anticipatory", -}; +static void __exit as_exit(void) +{ + kmem_cache_destroy(arq_pool); + elv_unregister(&iosched_as); +} + +module_init(as_init); +module_exit(as_exit); -EXPORT_SYMBOL(iosched_as); +MODULE_AUTHOR("Nick Piggin"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("anticipatory IO scheduler"); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 5509e5620..97bf2d4b9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -46,14 +46,14 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "Compaq CISS Driver (v 2.6.2)" +#define DRIVER_NAME "HP CISS Driver (v 2.6.2)" #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i"); + " SA6i V100"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -82,7 +82,7 @@ const struct pci_device_id cciss_pci_device_id[] = { 0x0E11, 0x4091, 0, 0, 0}, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409E, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS, 0x103C, 0x3211, 0, 0, 0}, {0,} }; @@ -115,7 +115,7 @@ static struct board_type products[] = { /*define how many times we will try a command because of bus resets */ #define MAX_CMD_RETRIES 3 -#define READ_AHEAD 256 +#define READ_AHEAD 1024 #define NR_CMDS 384 /* #commands that can be outstanding */ #define MAX_CTLR 8 @@ -185,17 +185,18 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr, } return c; } -#ifdef CONFIG_PROC_FS #include "cciss_scsi.c" /* For SCSI tape support */ +#ifdef CONFIG_PROC_FS + /* * Report information about this controller. */ -#define ENG_GIG 1048576000 +#define ENG_GIG 1000000000 #define ENG_GIG_FACTOR (ENG_GIG/512) #define RAID_UNKNOWN 6 -static const char *raid_label[] = {"0","4","1(0+1)","5","5+1","ADG", +static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG", "UNKNOWN"}; static struct proc_dir_entry *proc_cciss; @@ -209,7 +210,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, ctlr_info_t *h = (ctlr_info_t*)data; drive_info_struct *drv; unsigned long flags; - unsigned int vol_sz, vol_sz_frac; + sector_t vol_sz, vol_sz_frac; ctlr = h->ctlr; @@ -246,32 +247,21 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, pos += size; len += size; cciss_proc_tape_report(ctlr, buffer, &pos, &len); for(i=0; i<=h->highest_lun; i++) { - sector_t tmp; drv = &h->drv[i]; if (drv->block_size == 0) continue; - vol_sz = drv->nr_blocks; - sector_div(vol_sz, ENG_GIG_FACTOR); - - /* - * Awkwardly do this: - * vol_sz_frac = - * (drv->nr_blocks%ENG_GIG_FACTOR)*100/ENG_GIG_FACTOR; - */ - tmp = drv->nr_blocks; - vol_sz_frac = sector_div(tmp, ENG_GIG_FACTOR); - - /* Now, vol_sz_frac = (drv->nr_blocks%ENG_GIG_FACTOR) */ + vol_sz = drv->nr_blocks; + vol_sz_frac = sector_div(vol_sz, ENG_GIG_FACTOR); vol_sz_frac *= 100; sector_div(vol_sz_frac, ENG_GIG_FACTOR); if (drv->raid_level > 5) drv->raid_level = RAID_UNKNOWN; size = sprintf(buffer+len, "cciss/c%dd%d:" - "\t%4d.%02dGB\tRAID %s\n", - ctlr, i, vol_sz,vol_sz_frac, + "\t%4u.%02uGB\tRAID %s\n", + ctlr, i, (int)vol_sz, (int)vol_sz_frac, raid_label[drv->raid_level]); pos += size; len += size; } @@ -449,13 +439,22 @@ static int cciss_open(struct inode *inode, struct file *filep) /* * Root is allowed to open raw volume zero even if it's not configured - * so array config can still work. I don't think I really like this, + * so array config can still work. Root is also allowed to open any + * volume that has a LUN ID, so it can issue IOCTL to reread the + * disk information. I don't think I really like this * but I'm already using way to many device nodes to claim another one * for "raw controller". */ if (drv->nr_blocks == 0) { - if (iminor(inode) != 0) + if (iminor(inode) != 0) { /* not node 0? */ + /* if not node 0 make sure it is a partition = 0 */ + if (iminor(inode) & 0x0f) { return -ENXIO; + /* if it is, make sure we have a LUN ID */ + } else if (drv->LunID == 0) { + return -ENXIO; + } + } if (!capable(CAP_SYS_ADMIN)) return -EPERM; } @@ -578,7 +577,7 @@ int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) p); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info)); + err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info)); if (err) return -EFAULT; return err; @@ -610,7 +609,7 @@ int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg, err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) p); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info)); + err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info)); if (err) return -EFAULT; return err; @@ -810,7 +809,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, luninfo.num_opens = drv->usage_count; luninfo.num_parts = 0; /* count partitions 1 to 15 with sizes > 0 */ - for(i=1; i part[i]) continue; if (disk->part[i]->nr_sects != 0) @@ -866,6 +865,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, kfree(buff); return -EFAULT; } + } else { + memset(buff, 0, iocommand.buf_size); } if ((c = cmd_alloc(host , 0)) == NULL) { @@ -1012,6 +1013,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, copy_from_user(buff[sg_used], data_ptr, sz)) { status = -ENOMEM; goto cleanup1; + } else { + memset(buff[sg_used], 0, sz); } left -= sz; data_ptr += sz; @@ -1097,18 +1100,11 @@ cleanup1: return(status); } default: - return -EBADRQC; + return -ENOTTY; } } -static int cciss_revalidate(struct gendisk *disk) -{ - drive_info_struct *drv = disk->private_data; - set_capacity(disk, drv->nr_blocks); - return 0; -} - /* * revalidate_allvol is for online array config utilities. After a * utility reconfigures the drives in the array, it can use this function @@ -1160,7 +1156,9 @@ static int revalidate_allvol(ctlr_info_t *host) for (i = 0; i < NWD; i++) { struct gendisk *disk = host->gendisk[i]; drive_info_struct *drv = &(host->drv[i]); - if (!drv->nr_blocks) + /* we must register the controller even if no disks exist */ + /* this is for the online array utilities */ + if (!drv->heads && i) continue; blk_queue_hardsect_size(host->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); @@ -1477,21 +1475,22 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, drv->sectors = 32; // Sectors per track drv->cylinders = total_size / 255 / 32; } else { + unsigned int t; + drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = inq_buff->data_byte[6]; drv->sectors = inq_buff->data_byte[7]; drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8; drv->cylinders += inq_buff->data_byte[5]; + drv->raid_level = inq_buff->data_byte[8]; + t = drv->heads * drv->sectors; + if (t > 1) { + drv->cylinders = total_size/t; + } } } else { /* Get geometry failed */ - printk(KERN_WARNING "cciss: reading geometry failed, " - "continuing with default geometry\n"); - drv->block_size = block_size; - drv->nr_blocks = total_size; - drv->heads = 255; - drv->sectors = 32; // Sectors per track - drv->cylinders = total_size / 255 / 32; + printk(KERN_WARNING "cciss: reading geometry failed\n"); } printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", drv->heads, drv->sectors, drv->cylinders); @@ -1509,8 +1508,8 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, return_code = sendcmd(CCISS_READ_CAPACITY, ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1; - *block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0])); + *total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1; + *block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0])); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; @@ -1520,6 +1519,7 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, *total_size, *block_size); return; } + static int register_new_disk(ctlr_info_t *h) { struct gendisk *disk; @@ -1663,7 +1663,9 @@ static int register_new_disk(ctlr_info_t *h) /* setup partitions per disk */ disk = h->gendisk[logvol]; set_capacity(disk, h->drv[logvol].nr_blocks); - add_disk(disk); + /* if it's the controller it's already added */ + if(logvol) + add_disk(disk); freeret: kfree(ld_buff); kfree(size_buff); @@ -1675,6 +1677,53 @@ free_err: logvol = -1; goto freeret; } + +static int cciss_revalidate(struct gendisk *disk) +{ + ctlr_info_t *h = get_host(disk); + drive_info_struct *drv = get_drv(disk); + int logvol; + int FOUND=0; + unsigned int block_size; + unsigned int total_size; + ReadCapdata_struct *size_buff = NULL; + InquiryData_struct *inq_buff = NULL; + + for(logvol=0; logvol < CISS_MAX_LUN; logvol++) + { + if(h->drv[logvol].LunID == drv->LunID) { + FOUND=1; + break; + } + } + + if (!FOUND) return 1; + + size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); + if (size_buff == NULL) + { + printk(KERN_WARNING "cciss: out of memory\n"); + return 1; + } + inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) + { + printk(KERN_WARNING "cciss: out of memory\n"); + kfree(size_buff); + return 1; + } + + cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size); + cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv); + + blk_queue_hardsect_size(h->queue, drv->block_size); + set_capacity(disk, drv->nr_blocks); + + kfree(size_buff); + kfree(inq_buff); + return 0; +} + /* * Wait polling for a command to complete. * The memory mapped FIFO is polled for the completion. @@ -1844,13 +1893,13 @@ cleanup1: /* * Map (physical) PCI mem into (virtual) kernel space */ -static ulong remap_pci_mem(ulong base, ulong size) +static void __iomem *remap_pci_mem(ulong base, ulong size) { ulong page_base = ((ulong) base) & PAGE_MASK; ulong page_offs = ((ulong) base) - page_base; - ulong page_remapped = (ulong) ioremap(page_base, page_offs+size); + void __iomem *page_remapped = ioremap(page_base, page_offs+size); - return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL); + return page_remapped ? (page_remapped + page_offs) : NULL; } /* @@ -2300,7 +2349,6 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) { ushort subsystem_vendor_id, subsystem_device_id, command; - unchar irq = pdev->irq; __u32 board_id, scratchpad = 0; __u64 cfg_offset; __u32 cfg_base_addr; @@ -2359,11 +2407,11 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) #ifdef CCISS_DEBUG printk("command = %x\n", command); - printk("irq = %x\n", irq); + printk("irq = %x\n", pdev->irq); printk("board_id = %x\n", board_id); #endif /* CCISS_DEBUG */ - c->intr = irq; + c->intr = pdev->irq; /* * Memory base addr is first addr , the second points to the config @@ -2411,9 +2459,9 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) #ifdef CCISS_DEBUG printk("cfg offset = %x\n", cfg_offset); #endif /* CCISS_DEBUG */ - c->cfgtable = (CfgTable_struct *) - remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index) - + cfg_offset, sizeof(CfgTable_struct)); + c->cfgtable = remap_pci_mem(pci_resource_start(pdev, + cfg_base_addr_index) + cfg_offset, + sizeof(CfgTable_struct)); c->board_id = board_id; #ifdef CCISS_DEBUG @@ -2763,7 +2811,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, disk->fops = &cciss_fops; disk->queue = hba[i]->queue; disk->private_data = drv; - if( !(drv->nr_blocks)) + /* we must register the controller even if no disks exist */ + /* this is for the online array utilities */ + if(!drv->heads && j) continue; blk_queue_hardsect_size(hba[i]->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); @@ -2825,7 +2875,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) } free_irq(hba[i]->intr, hba[i]); pci_set_drvdata(pdev, NULL); - iounmap((void*)hba[i]->vaddr); + iounmap(hba[i]->vaddr); cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname); remove_proc_entry(hba[i]->devname, proc_cciss); diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 825855cd4..8ab689c21 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -43,12 +43,12 @@ struct ctlr_info char firm_ver[4]; // Firmware version struct pci_dev *pdev; __u32 board_id; - unsigned long vaddr; + void __iomem *vaddr; unsigned long paddr; unsigned long io_mem_addr; unsigned long io_mem_length; - CfgTable_struct *cfgtable; - int intr; + CfgTable_struct __iomem *cfgtable; + unsigned int intr; int interrupts_enabled; int max_commands; int commands_outstanding; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 9df82b8e9..452a4aff9 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -28,7 +28,9 @@ through the array controller. Note in particular, neither physical nor logical disks are presented through the scsi layer. */ -#include "../scsi/scsi.h" +#include +#include +#include #include #include #include @@ -61,15 +63,8 @@ int cciss_scsi_proc_info( int length, /* length of data in buffer */ int func); /* 0 == read, 1 == write */ -int cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)); -#if 0 -int cciss_scsi_abort(Scsi_Cmnd *cmd); -#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS -int cciss_scsi_reset(Scsi_Cmnd *cmd, unsigned int reset_flags); -#else -int cciss_scsi_reset(Scsi_Cmnd *cmd); -#endif -#endif +int cciss_scsi_queue_command (struct scsi_cmnd *cmd, + void (* done)(struct scsi_cmnd *)); static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { { .name = "cciss0", .ndevices = 0 }, @@ -82,7 +77,7 @@ static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { { .name = "cciss7", .ndevices = 0 }, }; -static Scsi_Host_Template cciss_driver_template = { +static struct scsi_host_template cciss_driver_template = { .module = THIS_MODULE, .name = "cciss", .proc_name = "cciss", @@ -552,7 +547,7 @@ cciss_scsi_setup(int cntl_num) static void complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) { - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; ctlr_info_t *ctlr; u64bit addr64; ErrorInfo_struct *ei; @@ -565,7 +560,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) return; } - cmd = (Scsi_Cmnd *) cp->scsi_cmd; + cmd = (struct scsi_cmnd *) cp->scsi_cmd; ctlr = hba[cp->ctlr]; /* undo the DMA mappings */ @@ -573,14 +568,14 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag) if (cmd->use_sg) { pci_unmap_sg(ctlr->pdev, cmd->buffer, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); } else if (cmd->request_bufflen) { addr64.val32.lower = cp->SG[0].Addr.lower; addr64.val32.upper = cp->SG[0].Addr.upper; pci_unmap_single(ctlr->pdev, (dma_addr_t) addr64.val, cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); } cmd->result = (DID_OK << 16); /* host byte */ @@ -783,9 +778,8 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c, cp->Request.Type.Direction = direction; /* Fill in the SG list and do dma mapping */ - cciss_map_one(c->pdev, cp, - (unsigned char *) buf, bufsize, - scsi_to_pci_dma_dir(SCSI_DATA_READ)); + cciss_map_one(c->pdev, cp, (unsigned char *) buf, + bufsize, DMA_FROM_DEVICE); cp->waiting = &wait; @@ -799,9 +793,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c, wait_for_completion(&wait); /* undo the dma mapping */ - cciss_unmap_one(c->pdev, cp, bufsize, - scsi_to_pci_dma_dir(SCSI_DATA_READ)); - + cciss_unmap_one(c->pdev, cp, bufsize, DMA_FROM_DEVICE); return(0); } @@ -1180,14 +1172,14 @@ cciss_scsi_info(struct Scsi_Host *sa) } -/* cciss_scatter_gather takes a Scsi_Cmnd, (cmd), and does the pci +/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci dma mapping and fills in the scatter gather entries of the cciss command, cp. */ static void cciss_scatter_gather(struct pci_dev *pdev, CommandList_struct *cp, - Scsi_Cmnd *cmd) + struct scsi_cmnd *cmd) { unsigned int use_sg, nsegs=0, len; struct scatterlist *scatter = (struct scatterlist *) cmd->buffer; @@ -1200,7 +1192,7 @@ cciss_scatter_gather(struct pci_dev *pdev, addr64 = (__u64) pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); cp->SG[0].Addr.lower = (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF); @@ -1213,7 +1205,7 @@ cciss_scatter_gather(struct pci_dev *pdev, else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, - scsi_to_pci_dma_dir(cmd->sc_data_direction)); + cmd->sc_data_direction); for (nsegs=0; nsegs < use_sg; nsegs++) { addr64 = (__u64) sg_dma_address(&scatter[nsegs]); @@ -1234,7 +1226,7 @@ cciss_scatter_gather(struct pci_dev *pdev, int -cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { ctlr_info_t **c; int ctlr, rc; @@ -1302,11 +1294,10 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) cp->Request.Type.Attribute = ATTR_SIMPLE; switch(cmd->sc_data_direction) { - case SCSI_DATA_WRITE: cp->Request.Type.Direction = XFER_WRITE; break; - case SCSI_DATA_READ: cp->Request.Type.Direction = XFER_READ; break; - case SCSI_DATA_NONE: cp->Request.Type.Direction = XFER_NONE; break; - - case SCSI_DATA_UNKNOWN: + case DMA_TO_DEVICE: cp->Request.Type.Direction = XFER_WRITE; break; + case DMA_FROM_DEVICE: cp->Request.Type.Direction = XFER_READ; break; + case DMA_NONE: cp->Request.Type.Direction = XFER_NONE; break; + case DMA_BIDIRECTIONAL: // This can happen if a buggy application does a scsi passthru // and sets both inlen and outlen to non-zero. ( see // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() ) diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index 068f4eae0..6c24f236f 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -22,96 +22,211 @@ #include #include +static unsigned long max_elapsed_crq; +static unsigned long max_elapsed_dispatch; + /* * tunables */ -static int cfq_quantum = 4; -static int cfq_queued = 8; +static int cfq_quantum = 4; /* max queue in one round of service */ +static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ +static int cfq_service = HZ; /* period over which service is avg */ +static int cfq_fifo_expire_r = HZ / 2; /* fifo timeout for sync requests */ +static int cfq_fifo_expire_w = 5 * HZ; /* fifo timeout for async requests */ +static int cfq_fifo_rate = HZ / 8; /* fifo expiry rate */ +static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ +static int cfq_back_penalty = 2; /* penalty of a backwards seek */ +/* + * for the hash of cfqq inside the cfqd + */ #define CFQ_QHASH_SHIFT 6 #define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) -#define list_entry_qhash(entry) list_entry((entry), struct cfq_queue, cfq_hash) +#define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) -#define CFQ_MHASH_SHIFT 8 +/* + * for the hash of crq inside the cfqq + */ +#define CFQ_MHASH_SHIFT 6 #define CFQ_MHASH_BLOCK(sec) ((sec) >> 3) #define CFQ_MHASH_ENTRIES (1 << CFQ_MHASH_SHIFT) -#define CFQ_MHASH_FN(sec) (hash_long(CFQ_MHASH_BLOCK((sec)),CFQ_MHASH_SHIFT)) -#define ON_MHASH(crq) !list_empty(&(crq)->hash) +#define CFQ_MHASH_FN(sec) hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct cfq_rq, hash) +#define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) #define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) -#define RQ_DATA(rq) ((struct cfq_rq *) (rq)->elevator_private) +#define RQ_DATA(rq) (rq)->elevator_private + +/* + * rb-tree defines + */ +#define RB_NONE (2) +#define RB_EMPTY(node) ((node)->rb_node == NULL) +#define RB_CLEAR_COLOR(node) (node)->rb_color = RB_NONE +#define RB_CLEAR(node) do { \ + (node)->rb_parent = NULL; \ + RB_CLEAR_COLOR((node)); \ + (node)->rb_right = NULL; \ + (node)->rb_left = NULL; \ +} while (0) +#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) +#define ON_RB(node) ((node)->rb_color != RB_NONE) +#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) +#define rq_rb_key(rq) (rq)->sector + +/* + * threshold for switching off non-tag accounting + */ +#define CFQ_MAX_TAG (4) + +/* + * sort key types and names + */ +enum { + CFQ_KEY_PGID, + CFQ_KEY_TGID, + CFQ_KEY_UID, + CFQ_KEY_GID, + CFQ_KEY_LAST, +}; + +static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL }; static kmem_cache_t *crq_pool; static kmem_cache_t *cfq_pool; -static mempool_t *cfq_mpool; +static kmem_cache_t *cfq_ioc_pool; struct cfq_data { struct list_head rr_list; - struct list_head *dispatch; - struct list_head *cfq_hash; + struct list_head empty_list; - struct list_head *crq_hash; + struct hlist_head *cfq_hash; + struct hlist_head *crq_hash; + /* queues on rr_list (ie they have pending requests */ unsigned int busy_queues; + unsigned int max_queued; + atomic_t ref; + + int key_type; + mempool_t *crq_pool; request_queue_t *queue; + sector_t last_sector; + + int rq_in_driver; + /* - * tunables + * tunables, see top of file */ unsigned int cfq_quantum; unsigned int cfq_queued; + unsigned int cfq_fifo_expire_r; + unsigned int cfq_fifo_expire_w; + unsigned int cfq_fifo_batch_expire; + unsigned int cfq_back_penalty; + unsigned int cfq_back_max; + unsigned int find_best_crq; + + unsigned int cfq_tagged; }; struct cfq_queue { - struct list_head cfq_hash; + /* reference count */ + atomic_t ref; + /* parent cfq_data */ + struct cfq_data *cfqd; + /* hash of mergeable requests */ + struct hlist_node cfq_hash; + /* hash key */ + unsigned long key; + /* whether queue is on rr (or empty) list */ + int on_rr; + /* on either rr or empty list of cfqd */ struct list_head cfq_list; + /* sorted list of pending requests */ struct rb_root sort_list; - int pid; + /* if fifo isn't expired, next request to serve */ + struct cfq_rq *next_crq; + /* requests queued in sort_list */ int queued[2]; -#if 0 - /* - * with a simple addition like this, we can do io priorities. almost. - * does need a split request free list, too. - */ - int io_prio -#endif + /* currently allocated requests */ + int allocated[2]; + /* fifo list of requests in sort_list */ + struct list_head fifo[2]; + /* last time fifo expired */ + unsigned long last_fifo_expire; + + int key_type; + + unsigned long service_start; + unsigned long service_used; + + unsigned int max_rate; + + /* number of requests that have been handed to the driver */ + int in_flight; + /* number of currently allocated requests */ + int alloc_limit[2]; }; struct cfq_rq { struct rb_node rb_node; sector_t rb_key; - struct request *request; + struct hlist_node hash; struct cfq_queue *cfq_queue; + struct cfq_io_context *io_context; + + unsigned long service_start; + unsigned long queue_start; - struct list_head hash; + unsigned int in_flight : 1; + unsigned int accounted : 1; + unsigned int is_sync : 1; + unsigned int is_write : 1; }; -static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq); -static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid); -static void cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_rq *crq); +static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned long); +static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); +static void cfq_update_next_crq(struct cfq_rq *); +static void cfq_put_cfqd(struct cfq_data *cfqd); /* - * lots of deadline iosched dupes, can be abstracted later... + * what the fairness is based on (ie how processes are grouped and + * differentiated) */ -static inline void __cfq_del_crq_hash(struct cfq_rq *crq) +static inline unsigned long +cfq_hash_key(struct cfq_data *cfqd, struct task_struct *tsk) { - list_del_init(&crq->hash); + /* + * optimize this so that ->key_type is the offset into the struct + */ + switch (cfqd->key_type) { + case CFQ_KEY_PGID: + return process_group(tsk); + default: + case CFQ_KEY_TGID: + return tsk->tgid; + case CFQ_KEY_UID: + return tsk->uid; + case CFQ_KEY_GID: + return tsk->gid; + } } +/* + * lots of deadline iosched dupes, can be abstracted later... + */ static inline void cfq_del_crq_hash(struct cfq_rq *crq) { - if (ON_MHASH(crq)) - __cfq_del_crq_hash(crq); + hlist_del_init(&crq->hash); } static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq) @@ -120,32 +235,32 @@ static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq) if (q->last_merge == crq->request) q->last_merge = NULL; + + cfq_update_next_crq(crq); } static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) { - struct request *rq = crq->request; + const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); - BUG_ON(ON_MHASH(crq)); + BUG_ON(!hlist_unhashed(&crq->hash)); - list_add(&crq->hash, &cfqd->crq_hash[CFQ_MHASH_FN(rq_hash_key(rq))]); + hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); } static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) { - struct list_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; + struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)]; + struct hlist_node *entry, *next; - while ((entry = next) != hash_list) { + hlist_for_each_safe(entry, next, hash_list) { struct cfq_rq *crq = list_entry_hash(entry); struct request *__rq = crq->request; - next = entry->next; - - BUG_ON(!ON_MHASH(crq)); + BUG_ON(hlist_unhashed(&crq->hash)); if (!rq_mergeable(__rq)) { - __cfq_del_crq_hash(crq); + cfq_del_crq_hash(crq); continue; } @@ -157,29 +272,257 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) } /* - * rb tree support functions + * Lifted from AS - choose which of crq1 and crq2 that is best served now. + * We choose the request that is closest to the head right now. Distance + * behind the head are penalized and only allowed to a certain extent. */ -#define RB_NONE (2) -#define RB_EMPTY(node) ((node)->rb_node == NULL) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) -#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) -#define rq_rb_key(rq) (rq)->sector +static struct cfq_rq * +cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) +{ + sector_t last, s1, s2, d1 = 0, d2 = 0; + int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */ + unsigned long back_max; + + if (crq1 == NULL || crq1 == crq2) + return crq2; + if (crq2 == NULL) + return crq1; + + s1 = crq1->request->sector; + s2 = crq2->request->sector; + + last = cfqd->last_sector; + +#if 0 + if (!list_empty(&cfqd->queue->queue_head)) { + struct list_head *entry = &cfqd->queue->queue_head; + unsigned long distance = ~0UL; + struct request *rq; + + while ((entry = entry->prev) != &cfqd->queue->queue_head) { + rq = list_entry_rq(entry); + + if (blk_barrier_rq(rq)) + break; + + if (distance < abs(s1 - rq->sector + rq->nr_sectors)) { + distance = abs(s1 - rq->sector +rq->nr_sectors); + last = rq->sector + rq->nr_sectors; + } + if (distance < abs(s2 - rq->sector + rq->nr_sectors)) { + distance = abs(s2 - rq->sector +rq->nr_sectors); + last = rq->sector + rq->nr_sectors; + } + } + } +#endif + + /* + * by definition, 1KiB is 2 sectors + */ + back_max = cfqd->cfq_back_max * 2; + + /* + * Strict one way elevator _except_ in the case where we allow + * short backward seeks which are biased as twice the cost of a + * similar forward seek. + */ + if (s1 >= last) + d1 = s1 - last; + else if (s1 + back_max >= last) + d1 = (last - s1) * cfqd->cfq_back_penalty; + else + r1_wrap = 1; + + if (s2 >= last) + d2 = s2 - last; + else if (s2 + back_max >= last) + d2 = (last - s2) * cfqd->cfq_back_penalty; + else + r2_wrap = 1; + + /* Found required data */ + if (!r1_wrap && r2_wrap) + return crq1; + else if (!r2_wrap && r1_wrap) + return crq2; + else if (r1_wrap && r2_wrap) { + /* both behind the head */ + if (s1 <= s2) + return crq1; + else + return crq2; + } + + /* Both requests in front of the head */ + if (d1 < d2) + return crq1; + else if (d2 < d1) + return crq2; + else { + if (s1 >= s2) + return crq1; + else + return crq2; + } +} -static inline void cfq_del_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) +/* + * would be nice to take fifo expire time into account as well + */ +static struct cfq_rq * +cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_rq *last) +{ + struct cfq_rq *crq_next = NULL, *crq_prev = NULL; + struct rb_node *rbnext, *rbprev; + + if (!ON_RB(&last->rb_node)) + return NULL; + + if ((rbnext = rb_next(&last->rb_node)) == NULL) + rbnext = rb_first(&cfqq->sort_list); + + rbprev = rb_prev(&last->rb_node); + + if (rbprev) + crq_prev = rb_entry_crq(rbprev); + if (rbnext) + crq_next = rb_entry_crq(rbnext); + + return cfq_choose_req(cfqd, crq_next, crq_prev); +} + +static void cfq_update_next_crq(struct cfq_rq *crq) { + struct cfq_queue *cfqq = crq->cfq_queue; + + if (cfqq->next_crq == crq) + cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); +} + +static int cfq_check_sort_rr_list(struct cfq_queue *cfqq) +{ + struct list_head *head = &cfqq->cfqd->rr_list; + struct list_head *next, *prev; + + /* + * list might still be ordered + */ + next = cfqq->cfq_list.next; + if (next != head) { + struct cfq_queue *cnext = list_entry_cfqq(next); + + if (cfqq->service_used > cnext->service_used) + return 1; + } + + prev = cfqq->cfq_list.prev; + if (prev != head) { + struct cfq_queue *cprev = list_entry_cfqq(prev); + + if (cfqq->service_used < cprev->service_used) + return 1; + } + + return 0; +} + +static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue) +{ + struct list_head *entry = &cfqq->cfqd->rr_list; + + if (!cfqq->on_rr) + return; + if (!new_queue && !cfq_check_sort_rr_list(cfqq)) + return; + + list_del(&cfqq->cfq_list); + + /* + * sort by our mean service_used, sub-sort by in-flight requests + */ + while ((entry = entry->prev) != &cfqq->cfqd->rr_list) { + struct cfq_queue *__cfqq = list_entry_cfqq(entry); + + if (cfqq->service_used > __cfqq->service_used) + break; + else if (cfqq->service_used == __cfqq->service_used) { + struct list_head *prv; + + while ((prv = entry->prev) != &cfqq->cfqd->rr_list) { + __cfqq = list_entry_cfqq(prv); + + WARN_ON(__cfqq->service_used > cfqq->service_used); + if (cfqq->service_used != __cfqq->service_used) + break; + if (cfqq->in_flight > __cfqq->in_flight) + break; + + entry = prv; + } + } + } + + list_add(&cfqq->cfq_list, entry); +} + +/* + * add to busy list of queues for service, trying to be fair in ordering + * the pending list according to requests serviced + */ +static inline void +cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + /* + * it's currently on the empty list + */ + cfqq->on_rr = 1; + cfqd->busy_queues++; + + if (time_after(jiffies, cfqq->service_start + cfq_service)) + cfqq->service_used >>= 3; + + cfq_sort_rr_list(cfqq, 1); +} + +static inline void +cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + list_move(&cfqq->cfq_list, &cfqd->empty_list); + cfqq->on_rr = 0; + + BUG_ON(!cfqd->busy_queues); + cfqd->busy_queues--; +} + +/* + * rb tree support functions + */ +static inline void cfq_del_crq_rb(struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = crq->cfq_queue; + if (ON_RB(&crq->rb_node)) { - cfqq->queued[rq_data_dir(crq->request)]--; + struct cfq_data *cfqd = cfqq->cfqd; + + BUG_ON(!cfqq->queued[crq->is_sync]); + + cfq_update_next_crq(crq); + + cfqq->queued[crq->is_sync]--; rb_erase(&crq->rb_node, &cfqq->sort_list); - crq->cfq_queue = NULL; + RB_CLEAR_COLOR(&crq->rb_node); + + if (RB_EMPTY(&cfqq->sort_list) && cfqq->on_rr) + cfq_del_cfqq_rr(cfqd, cfqq); } } static struct cfq_rq * -__cfq_add_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) +__cfq_add_crq_rb(struct cfq_rq *crq) { - struct rb_node **p = &cfqq->sort_list.rb_node; + struct rb_node **p = &crq->cfq_queue->sort_list.rb_node; struct rb_node *parent = NULL; struct cfq_rq *__crq; @@ -199,30 +542,50 @@ __cfq_add_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) return NULL; } -static void -cfq_add_crq_rb(struct cfq_data *cfqd, struct cfq_queue *cfqq,struct cfq_rq *crq) +static void cfq_add_crq_rb(struct cfq_rq *crq) { + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; struct request *rq = crq->request; struct cfq_rq *__alias; crq->rb_key = rq_rb_key(rq); - cfqq->queued[rq_data_dir(rq)]++; -retry: - __alias = __cfq_add_crq_rb(cfqq, crq); - if (!__alias) { - rb_insert_color(&crq->rb_node, &cfqq->sort_list); - crq->cfq_queue = cfqq; - return; + cfqq->queued[crq->is_sync]++; + + /* + * looks a little odd, but the first insert might return an alias. + * if that happens, put the alias on the dispatch list + */ + while ((__alias = __cfq_add_crq_rb(crq)) != NULL) + cfq_dispatch_sort(cfqd->queue, __alias); + + rb_insert_color(&crq->rb_node, &cfqq->sort_list); + + if (!cfqq->on_rr) + cfq_add_cfqq_rr(cfqd, cfqq); + + /* + * check if this request is a better next-serve candidate + */ + cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); +} + +static inline void +cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) +{ + if (ON_RB(&crq->rb_node)) { + rb_erase(&crq->rb_node, &cfqq->sort_list); + cfqq->queued[crq->is_sync]--; } - cfq_dispatch_sort(cfqd, cfqq, __alias); - goto retry; + cfq_add_crq_rb(crq); } static struct request * cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) { - struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->tgid); + const unsigned long key = cfq_hash_key(cfqd, current); + struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, key); struct rb_node *n; if (!cfqq) @@ -244,30 +607,44 @@ out: return NULL; } -static void cfq_remove_request(request_queue_t *q, struct request *rq) +/* + * make sure the service time gets corrected on reissue of this request + */ +static void cfq_requeue_request(request_queue_t *q, struct request *rq) { - struct cfq_data *cfqd = q->elevator.elevator_data; struct cfq_rq *crq = RQ_DATA(rq); if (crq) { struct cfq_queue *cfqq = crq->cfq_queue; + if (cfqq->cfqd->cfq_tagged) { + cfqq->service_used--; + cfq_sort_rr_list(cfqq, 0); + } + + crq->accounted = 0; + cfqq->cfqd->rq_in_driver--; + } + list_add(&rq->queuelist, &q->queue_head); +} + +static void cfq_remove_request(request_queue_t *q, struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + + if (crq) { cfq_remove_merge_hints(q, crq); list_del_init(&rq->queuelist); - if (cfqq) { - cfq_del_crq_rb(cfqq, crq); - - if (RB_EMPTY(&cfqq->sort_list)) - cfq_put_queue(cfqd, cfqq); - } + if (crq->cfq_queue) + cfq_del_crq_rb(crq); } } static int cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct request *__rq; int ret; @@ -305,7 +682,7 @@ out_insert: static void cfq_merged_request(request_queue_t *q, struct request *req) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_rq *crq = RQ_DATA(req); cfq_del_crq_hash(crq); @@ -314,234 +691,570 @@ static void cfq_merged_request(request_queue_t *q, struct request *req) if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) { struct cfq_queue *cfqq = crq->cfq_queue; - cfq_del_crq_rb(cfqq, crq); - cfq_add_crq_rb(cfqd, cfqq, crq); + cfq_update_next_crq(crq); + cfq_reposition_crq_rb(cfqq, crq); } q->last_merge = req; } static void -cfq_merged_requests(request_queue_t *q, struct request *req, +cfq_merged_requests(request_queue_t *q, struct request *rq, struct request *next) { - cfq_merged_request(q, req); + struct cfq_rq *crq = RQ_DATA(rq); + struct cfq_rq *cnext = RQ_DATA(next); + + cfq_merged_request(q, rq); + + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(cnext->queue_start, crq->queue_start)) { + list_move(&rq->queuelist, &next->queuelist); + crq->queue_start = cnext->queue_start; + } + } + + cfq_update_next_crq(cnext); cfq_remove_request(q, next); } -static void -cfq_dispatch_sort(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_rq *crq) +/* + * we dispatch cfqd->cfq_quantum requests in total from the rr_list queues, + * this function sector sorts the selected request to minimize seeks. we start + * at cfqd->last_sector, not 0. + */ +static void cfq_dispatch_sort(request_queue_t *q, struct cfq_rq *crq) { - struct list_head *head = cfqd->dispatch, *entry = head; + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq = crq->cfq_queue; + struct list_head *head = &q->queue_head, *entry = head; struct request *__rq; + sector_t last; - cfq_del_crq_rb(cfqq, crq); - cfq_remove_merge_hints(cfqd->queue, crq); + cfq_del_crq_rb(crq); + cfq_remove_merge_hints(q, crq); + list_del(&crq->request->queuelist); - if (!list_empty(head)) { - __rq = list_entry_rq(head->next); + last = cfqd->last_sector; + while ((entry = entry->prev) != head) { + __rq = list_entry_rq(entry); + + if (blk_barrier_rq(crq->request)) + break; + if (!blk_fs_request(crq->request)) + break; - if (crq->request->sector < __rq->sector) { - entry = head->prev; - goto link; + if (crq->request->sector > __rq->sector) + break; + if (__rq->sector > last && crq->request->sector < last) { + last = crq->request->sector; + break; } } - while ((entry = entry->prev) != head) { - __rq = list_entry_rq(entry); + cfqd->last_sector = last; + crq->in_flight = 1; + cfqq->in_flight++; + list_add(&crq->request->queuelist, entry); +} - if (crq->request->sector <= __rq->sector) - break; +/* + * return expired entry, or NULL to just start from scratch in rbtree + */ +static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) +{ + struct cfq_data *cfqd = cfqq->cfqd; + const int reads = !list_empty(&cfqq->fifo[0]); + const int writes = !list_empty(&cfqq->fifo[1]); + unsigned long now = jiffies; + struct cfq_rq *crq; + + if (time_before(now, cfqq->last_fifo_expire + cfqd->cfq_fifo_batch_expire)) + return NULL; + + crq = RQ_DATA(list_entry(cfqq->fifo[0].next, struct request, queuelist)); + if (reads && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_r)) { + cfqq->last_fifo_expire = now; + return crq; + } + + crq = RQ_DATA(list_entry(cfqq->fifo[1].next, struct request, queuelist)); + if (writes && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_w)) { + cfqq->last_fifo_expire = now; + return crq; } -link: - list_add_tail(&crq->request->queuelist, entry); + return NULL; } +/* + * dispatch a single request from given queue + */ static inline void -__cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd, - struct cfq_queue *cfqq) +cfq_dispatch_request(request_queue_t *q, struct cfq_data *cfqd, + struct cfq_queue *cfqq) { - struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list)); + struct cfq_rq *crq; + + /* + * follow expired path, else get first next available + */ + if ((crq = cfq_check_fifo(cfqq)) == NULL) { + if (cfqd->find_best_crq) + crq = cfqq->next_crq; + else + crq = rb_entry_crq(rb_first(&cfqq->sort_list)); + } - cfq_dispatch_sort(cfqd, cfqq, crq); + cfqd->last_sector = crq->request->sector + crq->request->nr_sectors; + + /* + * finally, insert request into driver list + */ + cfq_dispatch_sort(q, crq); } -static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd) +static int cfq_dispatch_requests(request_queue_t *q, int max_dispatch) { + struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_queue *cfqq; struct list_head *entry, *tmp; - int ret, queued, good_queues; + int queued, busy_queues, first_round; if (list_empty(&cfqd->rr_list)) return 0; - queued = ret = 0; + queued = 0; + first_round = 1; restart: - good_queues = 0; + busy_queues = 0; list_for_each_safe(entry, tmp, &cfqd->rr_list) { - cfqq = list_entry_cfqq(cfqd->rr_list.next); + cfqq = list_entry_cfqq(entry); BUG_ON(RB_EMPTY(&cfqq->sort_list)); - __cfq_dispatch_requests(q, cfqd, cfqq); + /* + * first round of queueing, only select from queues that + * don't already have io in-flight + */ + if (first_round && cfqq->in_flight) + continue; + + cfq_dispatch_request(q, cfqd, cfqq); - if (RB_EMPTY(&cfqq->sort_list)) - cfq_put_queue(cfqd, cfqq); - else - good_queues++; + if (!RB_EMPTY(&cfqq->sort_list)) + busy_queues++; queued++; - ret = 1; } - if ((queued < cfqd->cfq_quantum) && good_queues) + if ((queued < max_dispatch) && (busy_queues || first_round)) { + first_round = 0; goto restart; + } - return ret; + return queued; +} + +static inline void cfq_account_dispatch(struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; + unsigned long now, elapsed; + + if (!blk_fs_request(crq->request)) + return; + + /* + * accounted bit is necessary since some drivers will call + * elv_next_request() many times for the same request (eg ide) + */ + if (crq->accounted) + return; + + now = jiffies; + if (cfqq->service_start == ~0UL) + cfqq->service_start = now; + + /* + * on drives with tagged command queueing, command turn-around time + * doesn't necessarily reflect the time spent processing this very + * command inside the drive. so do the accounting differently there, + * by just sorting on the number of requests + */ + if (cfqd->cfq_tagged) { + if (time_after(now, cfqq->service_start + cfq_service)) { + cfqq->service_start = now; + cfqq->service_used /= 10; + } + + cfqq->service_used++; + cfq_sort_rr_list(cfqq, 0); + } + + elapsed = now - crq->queue_start; + if (elapsed > max_elapsed_dispatch) + max_elapsed_dispatch = elapsed; + + crq->accounted = 1; + crq->service_start = now; + + if (++cfqd->rq_in_driver >= CFQ_MAX_TAG && !cfqd->cfq_tagged) { + cfqq->cfqd->cfq_tagged = 1; + printk("cfq: depth %d reached, tagging now on\n", CFQ_MAX_TAG); + } +} + +static inline void +cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq) +{ + struct cfq_data *cfqd = cfqq->cfqd; + + if (!crq->accounted) + return; + + WARN_ON(!cfqd->rq_in_driver); + cfqd->rq_in_driver--; + + if (!cfqd->cfq_tagged) { + unsigned long now = jiffies; + unsigned long duration = now - crq->service_start; + + if (time_after(now, cfqq->service_start + cfq_service)) { + cfqq->service_start = now; + cfqq->service_used >>= 3; + } + + cfqq->service_used += duration; + cfq_sort_rr_list(cfqq, 0); + + if (duration > max_elapsed_crq) + max_elapsed_crq = duration; + } } static struct request *cfq_next_request(request_queue_t *q) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct request *rq; - if (!list_empty(cfqd->dispatch)) { + if (!list_empty(&q->queue_head)) { struct cfq_rq *crq; dispatch: - rq = list_entry_rq(cfqd->dispatch->next); + rq = list_entry_rq(q->queue_head.next); - crq = RQ_DATA(rq); - if (crq) + if ((crq = RQ_DATA(rq)) != NULL) { cfq_remove_merge_hints(q, crq); + cfq_account_dispatch(crq); + } return rq; } - if (cfq_dispatch_requests(q, cfqd)) + if (cfq_dispatch_requests(q, cfqd->cfq_quantum)) goto dispatch; return NULL; } +/* + * task holds one reference to the queue, dropped when task exits. each crq + * in-flight on this queue also holds a reference, dropped when crq is freed. + * + * queue lock must be held here. + */ +static void cfq_put_queue(struct cfq_queue *cfqq) +{ + BUG_ON(!atomic_read(&cfqq->ref)); + + if (!atomic_dec_and_test(&cfqq->ref)) + return; + + BUG_ON(rb_first(&cfqq->sort_list)); + BUG_ON(cfqq->on_rr); + + cfq_put_cfqd(cfqq->cfqd); + + /* + * it's on the empty list and still hashed + */ + list_del(&cfqq->cfq_list); + hlist_del(&cfqq->cfq_hash); + kmem_cache_free(cfq_pool, cfqq); +} + static inline struct cfq_queue * -__cfq_find_cfq_hash(struct cfq_data *cfqd, int pid, const int hashval) +__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval) { - struct list_head *hash_list = &cfqd->cfq_hash[hashval]; - struct list_head *entry; + struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; + struct hlist_node *entry, *next; - list_for_each(entry, hash_list) { + hlist_for_each_safe(entry, next, hash_list) { struct cfq_queue *__cfqq = list_entry_qhash(entry); - if (__cfqq->pid == pid) + if (__cfqq->key == key) return __cfqq; } return NULL; } -static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid) +static struct cfq_queue * +cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key) +{ + return __cfq_find_cfq_hash(cfqd, key, hash_long(key, CFQ_QHASH_SHIFT)); +} + +static inline void +cfq_rehash_cfqq(struct cfq_data *cfqd, struct cfq_queue **cfqq, + struct cfq_io_context *cic) { - const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT); + unsigned long hashkey = cfq_hash_key(cfqd, current); + unsigned long hashval = hash_long(hashkey, CFQ_QHASH_SHIFT); + struct cfq_queue *__cfqq; + unsigned long flags; - return __cfq_find_cfq_hash(cfqd, pid, hashval); + spin_lock_irqsave(cfqd->queue->queue_lock, flags); + + hlist_del(&(*cfqq)->cfq_hash); + + __cfqq = __cfq_find_cfq_hash(cfqd, hashkey, hashval); + if (!__cfqq || __cfqq == *cfqq) { + __cfqq = *cfqq; + hlist_add_head(&__cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + __cfqq->key_type = cfqd->key_type; + } else { + atomic_inc(&__cfqq->ref); + cic->cfqq = __cfqq; + cfq_put_queue(*cfqq); + *cfqq = __cfqq; + } + + cic->cfqq = __cfqq; + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); } -static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) +static void cfq_free_io_context(struct cfq_io_context *cic) { - cfqd->busy_queues--; - list_del(&cfqq->cfq_list); - list_del(&cfqq->cfq_hash); - mempool_free(cfqq, cfq_mpool); + kmem_cache_free(cfq_ioc_pool, cic); } -static struct cfq_queue *__cfq_get_queue(struct cfq_data *cfqd, int pid, - int gfp_mask) +/* + * locking hierarchy is: io_context lock -> queue locks + */ +static void cfq_exit_io_context(struct cfq_io_context *cic) { - const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT); + struct cfq_queue *cfqq = cic->cfqq; + struct list_head *entry = &cic->list; + request_queue_t *q; + unsigned long flags; + + /* + * put the reference this task is holding to the various queues + */ + spin_lock_irqsave(&cic->ioc->lock, flags); + while ((entry = cic->list.next) != &cic->list) { + struct cfq_io_context *__cic; + + __cic = list_entry(entry, struct cfq_io_context, list); + list_del(entry); + + q = __cic->cfqq->cfqd->queue; + spin_lock(q->queue_lock); + cfq_put_queue(__cic->cfqq); + spin_unlock(q->queue_lock); + } + + q = cfqq->cfqd->queue; + spin_lock(q->queue_lock); + cfq_put_queue(cfqq); + spin_unlock(q->queue_lock); + + cic->cfqq = NULL; + spin_unlock_irqrestore(&cic->ioc->lock, flags); +} + +static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags) +{ + struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_flags); + + if (cic) { + cic->dtor = cfq_free_io_context; + cic->exit = cfq_exit_io_context; + INIT_LIST_HEAD(&cic->list); + cic->cfqq = NULL; + } + + return cic; +} + +/* + * Setup general io context and cfq io context. There can be several cfq + * io contexts per general io context, if this process is doing io to more + * than one device managed by cfq. Note that caller is holding a reference to + * cfqq, so we don't need to worry about it disappearing + */ +static struct cfq_io_context * +cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags) +{ + struct cfq_data *cfqd = (*cfqq)->cfqd; + struct cfq_queue *__cfqq = *cfqq; + struct cfq_io_context *cic; + struct io_context *ioc; + + might_sleep_if(gfp_flags & __GFP_WAIT); + + ioc = get_io_context(gfp_flags); + if (!ioc) + return NULL; + + if ((cic = ioc->cic) == NULL) { + cic = cfq_alloc_io_context(gfp_flags); + + if (cic == NULL) + goto err; + + ioc->cic = cic; + cic->ioc = ioc; + cic->cfqq = __cfqq; + atomic_inc(&__cfqq->ref); + } else { + struct cfq_io_context *__cic; + unsigned long flags; + + /* + * since the first cic on the list is actually the head + * itself, need to check this here or we'll duplicate an + * cic per ioc for no reason + */ + if (cic->cfqq == __cfqq) + goto out; + + /* + * cic exists, check if we already are there. linear search + * should be ok here, the list will usually not be more than + * 1 or a few entries long + */ + spin_lock_irqsave(&ioc->lock, flags); + list_for_each_entry(__cic, &cic->list, list) { + /* + * this process is already holding a reference to + * this queue, so no need to get one more + */ + if (__cic->cfqq == __cfqq) { + cic = __cic; + spin_unlock_irqrestore(&ioc->lock, flags); + goto out; + } + } + spin_unlock_irqrestore(&ioc->lock, flags); + + /* + * nope, process doesn't have a cic assoicated with this + * cfqq yet. get a new one and add to list + */ + __cic = cfq_alloc_io_context(gfp_flags); + if (__cic == NULL) + goto err; + + __cic->ioc = ioc; + __cic->cfqq = __cfqq; + atomic_inc(&__cfqq->ref); + spin_lock_irqsave(&ioc->lock, flags); + list_add(&__cic->list, &cic->list); + spin_unlock_irqrestore(&ioc->lock, flags); + + cic = __cic; + *cfqq = __cfqq; + } + +out: + /* + * if key_type has been changed on the fly, we lazily rehash + * each queue at lookup time + */ + if ((*cfqq)->key_type != cfqd->key_type) + cfq_rehash_cfqq(cfqd, cfqq, cic); + + return cic; +err: + put_io_context(ioc); + return NULL; +} + +static struct cfq_queue * +__cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask) +{ + const int hashval = hash_long(key, CFQ_QHASH_SHIFT); struct cfq_queue *cfqq, *new_cfqq = NULL; - request_queue_t *q = cfqd->queue; retry: - cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval); + cfqq = __cfq_find_cfq_hash(cfqd, key, hashval); if (!cfqq) { if (new_cfqq) { cfqq = new_cfqq; new_cfqq = NULL; } else if (gfp_mask & __GFP_WAIT) { - spin_unlock_irq(q->queue_lock); - new_cfqq = mempool_alloc(cfq_mpool, gfp_mask); - spin_lock_irq(q->queue_lock); + spin_unlock_irq(cfqd->queue->queue_lock); + new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); + spin_lock_irq(cfqd->queue->queue_lock); goto retry; } else - return NULL; + goto out; - INIT_LIST_HEAD(&cfqq->cfq_hash); + memset(cfqq, 0, sizeof(*cfqq)); + + INIT_HLIST_NODE(&cfqq->cfq_hash); INIT_LIST_HEAD(&cfqq->cfq_list); RB_CLEAR_ROOT(&cfqq->sort_list); - - cfqq->pid = pid; - cfqq->queued[0] = cfqq->queued[1] = 0; - list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + INIT_LIST_HEAD(&cfqq->fifo[0]); + INIT_LIST_HEAD(&cfqq->fifo[1]); + + cfqq->key = key; + hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + atomic_set(&cfqq->ref, 0); + cfqq->cfqd = cfqd; + atomic_inc(&cfqd->ref); + cfqq->key_type = cfqd->key_type; + cfqq->service_start = ~0UL; } if (new_cfqq) - mempool_free(new_cfqq, cfq_mpool); - - return cfqq; -} - -static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, int pid, - int gfp_mask) -{ - request_queue_t *q = cfqd->queue; - struct cfq_queue *cfqq; - - spin_lock_irq(q->queue_lock); - cfqq = __cfq_get_queue(cfqd, pid, gfp_mask); - spin_unlock_irq(q->queue_lock); + kmem_cache_free(cfq_pool, new_cfqq); + atomic_inc(&cfqq->ref); +out: + WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); return cfqq; } static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq) { - struct cfq_queue *cfqq; + crq->is_sync = 0; + if (rq_data_dir(crq->request) == READ || current->flags & PF_SYNCWRITE) + crq->is_sync = 1; - cfqq = __cfq_get_queue(cfqd, current->tgid, GFP_ATOMIC); - if (cfqq) { - cfq_add_crq_rb(cfqd, cfqq, crq); + cfq_add_crq_rb(crq); + crq->queue_start = jiffies; - if (list_empty(&cfqq->cfq_list)) { - list_add(&cfqq->cfq_list, &cfqd->rr_list); - cfqd->busy_queues++; - } - } else { - /* - * should can only happen if the request wasn't allocated - * through blk_alloc_request(), eg stack requests from ide-cd - * (those should be removed) _and_ we are in OOM. - */ - list_add_tail(&crq->request->queuelist, cfqd->dispatch); - } + list_add_tail(&crq->request->queuelist, &crq->cfq_queue->fifo[crq->is_sync]); } static void cfq_insert_request(request_queue_t *q, struct request *rq, int where) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_rq *crq = RQ_DATA(rq); switch (where) { case ELEVATOR_INSERT_BACK: - while (cfq_dispatch_requests(q, cfqd)) + while (cfq_dispatch_requests(q, cfqd->cfq_quantum)) ; - list_add_tail(&rq->queuelist, cfqd->dispatch); + list_add_tail(&rq->queuelist, &q->queue_head); break; case ELEVATOR_INSERT_FRONT: - list_add(&rq->queuelist, cfqd->dispatch); + list_add(&rq->queuelist, &q->queue_head); break; case ELEVATOR_INSERT_SORT: BUG_ON(!blk_fs_request(rq)); @@ -562,12 +1275,27 @@ cfq_insert_request(request_queue_t *q, struct request *rq, int where) static int cfq_queue_empty(request_queue_t *q) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; - if (list_empty(cfqd->dispatch) && list_empty(&cfqd->rr_list)) - return 1; + return list_empty(&q->queue_head) && list_empty(&cfqd->rr_list); +} + +static void cfq_completed_request(request_queue_t *q, struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + + if (unlikely(!blk_fs_request(rq))) + return; + + if (crq->in_flight) { + struct cfq_queue *cfqq = crq->cfq_queue; + + WARN_ON(!cfqq->in_flight); + cfqq->in_flight--; + + cfq_account_completion(cfqq, crq); + } - return 0; } static struct request * @@ -596,101 +1324,171 @@ cfq_latter_request(request_queue_t *q, struct request *rq) static int cfq_may_queue(request_queue_t *q, int rw) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_queue *cfqq; - int ret = 1; + int ret = ELV_MQUEUE_MAY; - if (!cfqd->busy_queues) - goto out; + if (current->flags & PF_MEMALLOC) + return ELV_MQUEUE_MAY; - cfqq = cfq_find_cfq_hash(cfqd, current->tgid); + cfqq = cfq_find_cfq_hash(cfqd, cfq_hash_key(cfqd, current)); if (cfqq) { - int limit = (q->nr_requests - cfqd->cfq_queued) / cfqd->busy_queues; + int limit = cfqd->max_queued; + + if (cfqq->allocated[rw] < cfqd->cfq_queued) + return ELV_MQUEUE_MUST; + + if (cfqd->busy_queues) + limit = q->nr_requests / cfqd->busy_queues; - if (limit < 3) - limit = 3; + if (limit < cfqd->cfq_queued) + limit = cfqd->cfq_queued; else if (limit > cfqd->max_queued) limit = cfqd->max_queued; - if (cfqq->queued[rw] > limit) - ret = 0; + if (cfqq->allocated[rw] >= limit) { + if (limit > cfqq->alloc_limit[rw]) + cfqq->alloc_limit[rw] = limit; + + ret = ELV_MQUEUE_NO; + } } -out: + return ret; } +static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) +{ + struct request_list *rl = &q->rq; + const int write = waitqueue_active(&rl->wait[WRITE]); + const int read = waitqueue_active(&rl->wait[READ]); + + if (read && cfqq->allocated[READ] < cfqq->alloc_limit[READ]) + wake_up(&rl->wait[READ]); + if (write && cfqq->allocated[WRITE] < cfqq->alloc_limit[WRITE]) + wake_up(&rl->wait[WRITE]); +} + +/* + * queue lock held here + */ static void cfq_put_request(request_queue_t *q, struct request *rq) { - struct cfq_data *cfqd = q->elevator.elevator_data; + struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_rq *crq = RQ_DATA(rq); - struct request_list *rl; - int other_rw; if (crq) { + struct cfq_queue *cfqq = crq->cfq_queue; + BUG_ON(q->last_merge == rq); - BUG_ON(ON_MHASH(crq)); + BUG_ON(!hlist_unhashed(&crq->hash)); + + if (crq->io_context) + put_io_context(crq->io_context->ioc); + + BUG_ON(!cfqq->allocated[crq->is_write]); + cfqq->allocated[crq->is_write]--; mempool_free(crq, cfqd->crq_pool); rq->elevator_private = NULL; - } - /* - * work-around for may_queue "bug": if a read gets issued and refused - * to queue because writes ate all the allowed slots and no other - * reads are pending for this queue, it could get stuck infinitely - * since freed_request() only checks the waitqueue for writes when - * freeing them. or vice versa for a single write vs many reads. - * so check here whether "the other" data direction might be able - * to queue and wake them - */ - rl = &q->rq; - other_rw = rq_data_dir(rq) ^ 1; - if (rl->count[other_rw] <= q->nr_requests) { smp_mb(); - if (waitqueue_active(&rl->wait[other_rw])) - wake_up(&rl->wait[other_rw]); + cfq_check_waiters(q, cfqq); + cfq_put_queue(cfqq); } } +/* + * Allocate cfq data structures associated with this request. A queue and + */ static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { - struct cfq_data *cfqd = q->elevator.elevator_data; - struct cfq_queue *cfqq; + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_io_context *cic; + const int rw = rq_data_dir(rq); + struct cfq_queue *cfqq, *saved_cfqq; struct cfq_rq *crq; + unsigned long flags; + + might_sleep_if(gfp_mask & __GFP_WAIT); + + spin_lock_irqsave(q->queue_lock, flags); + + cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask); + if (!cfqq) + goto out_lock; + +repeat: + if (cfqq->allocated[rw] >= cfqd->max_queued) + goto out_lock; + + cfqq->allocated[rw]++; + spin_unlock_irqrestore(q->queue_lock, flags); /* - * prepare a queue up front, so cfq_enqueue() doesn't have to + * if hashing type has changed, the cfq_queue might change here. */ - cfqq = cfq_get_queue(cfqd, current->tgid, gfp_mask); - if (!cfqq) - return 1; + saved_cfqq = cfqq; + cic = cfq_get_io_context(&cfqq, gfp_mask); + if (!cic) + goto err; + + /* + * repeat allocation checks on queue change + */ + if (unlikely(saved_cfqq != cfqq)) { + spin_lock_irqsave(q->queue_lock, flags); + saved_cfqq->allocated[rw]--; + goto repeat; + } crq = mempool_alloc(cfqd->crq_pool, gfp_mask); if (crq) { - memset(crq, 0, sizeof(*crq)); RB_CLEAR(&crq->rb_node); + crq->rb_key = 0; crq->request = rq; - crq->cfq_queue = NULL; - INIT_LIST_HEAD(&crq->hash); + INIT_HLIST_NODE(&crq->hash); + crq->cfq_queue = cfqq; + crq->io_context = cic; + crq->service_start = crq->queue_start = 0; + crq->in_flight = crq->accounted = crq->is_sync = 0; + crq->is_write = rw; rq->elevator_private = crq; + cfqq->alloc_limit[rw] = 0; return 0; } + put_io_context(cic->ioc); +err: + spin_lock_irqsave(q->queue_lock, flags); + cfqq->allocated[rw]--; + cfq_put_queue(cfqq); +out_lock: + spin_unlock_irqrestore(q->queue_lock, flags); return 1; } -static void cfq_exit(request_queue_t *q, elevator_t *e) +static void cfq_put_cfqd(struct cfq_data *cfqd) { - struct cfq_data *cfqd = e->elevator_data; + request_queue_t *q = cfqd->queue; + + if (!atomic_dec_and_test(&cfqd->ref)) + return; + + blk_put_queue(q); - e->elevator_data = NULL; mempool_destroy(cfqd->crq_pool); kfree(cfqd->crq_hash); kfree(cfqd->cfq_hash); kfree(cfqd); } -static int cfq_init(request_queue_t *q, elevator_t *e) +static void cfq_exit_queue(elevator_t *e) +{ + cfq_put_cfqd(e->elevator_data); +} + +static int cfq_init_queue(request_queue_t *q, elevator_t *e) { struct cfq_data *cfqd; int i; @@ -701,12 +1499,13 @@ static int cfq_init(request_queue_t *q, elevator_t *e) memset(cfqd, 0, sizeof(*cfqd)); INIT_LIST_HEAD(&cfqd->rr_list); + INIT_LIST_HEAD(&cfqd->empty_list); - cfqd->crq_hash = kmalloc(sizeof(struct list_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); + cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); if (!cfqd->crq_hash) goto out_crqhash; - cfqd->cfq_hash = kmalloc(sizeof(struct list_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL); + cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL); if (!cfqd->cfq_hash) goto out_cfqhash; @@ -715,23 +1514,33 @@ static int cfq_init(request_queue_t *q, elevator_t *e) goto out_crqpool; for (i = 0; i < CFQ_MHASH_ENTRIES; i++) - INIT_LIST_HEAD(&cfqd->crq_hash[i]); + INIT_HLIST_HEAD(&cfqd->crq_hash[i]); for (i = 0; i < CFQ_QHASH_ENTRIES; i++) - INIT_LIST_HEAD(&cfqd->cfq_hash[i]); + INIT_HLIST_HEAD(&cfqd->cfq_hash[i]); - cfqd->dispatch = &q->queue_head; e->elevator_data = cfqd; + cfqd->queue = q; + atomic_inc(&q->refcnt); /* * just set it to some high value, we want anyone to be able to queue * some requests. fairness is handled differently */ - cfqd->max_queued = q->nr_requests; - q->nr_requests = 8192; + q->nr_requests = 1024; + cfqd->max_queued = q->nr_requests / 16; + q->nr_batching = cfq_queued; + cfqd->key_type = CFQ_KEY_TGID; + cfqd->find_best_crq = 1; + atomic_set(&cfqd->ref, 1); cfqd->cfq_queued = cfq_queued; cfqd->cfq_quantum = cfq_quantum; + cfqd->cfq_fifo_expire_r = cfq_fifo_expire_r; + cfqd->cfq_fifo_expire_w = cfq_fifo_expire_w; + cfqd->cfq_fifo_batch_expire = cfq_fifo_rate; + cfqd->cfq_back_max = cfq_back_max; + cfqd->cfq_back_penalty = cfq_back_penalty; return 0; out_crqpool: @@ -743,29 +1552,39 @@ out_crqhash: return -ENOMEM; } +static void cfq_slab_kill(void) +{ + if (crq_pool) + kmem_cache_destroy(crq_pool); + if (cfq_pool) + kmem_cache_destroy(cfq_pool); + if (cfq_ioc_pool) + kmem_cache_destroy(cfq_ioc_pool); +} + static int __init cfq_slab_setup(void) { crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0, NULL, NULL); - if (!crq_pool) - panic("cfq_iosched: can't init crq pool\n"); + goto fail; cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0, NULL, NULL); - if (!cfq_pool) - panic("cfq_iosched: can't init cfq pool\n"); - - cfq_mpool = mempool_create(64, mempool_alloc_slab, mempool_free_slab, cfq_pool); + goto fail; - if (!cfq_mpool) - panic("cfq_iosched: can't init cfq mpool\n"); + cfq_ioc_pool = kmem_cache_create("cfq_ioc_pool", + sizeof(struct cfq_io_context), 0, 0, NULL, NULL); + if (!cfq_ioc_pool) + goto fail; return 0; +fail: + cfq_slab_kill(); + return -ENOMEM; } -subsys_initcall(cfq_slab_setup); /* * sysfs parts below --> @@ -791,27 +1610,86 @@ cfq_var_store(unsigned int *var, const char *page, size_t count) return count; } -#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t +cfq_clear_elapsed(struct cfq_data *cfqd, const char *page, size_t count) +{ + max_elapsed_dispatch = max_elapsed_crq = 0; + return count; +} + +static ssize_t +cfq_set_key_type(struct cfq_data *cfqd, const char *page, size_t count) +{ + spin_lock_irq(cfqd->queue->queue_lock); + if (!strncmp(page, "pgid", 4)) + cfqd->key_type = CFQ_KEY_PGID; + else if (!strncmp(page, "tgid", 4)) + cfqd->key_type = CFQ_KEY_TGID; + else if (!strncmp(page, "uid", 3)) + cfqd->key_type = CFQ_KEY_UID; + else if (!strncmp(page, "gid", 3)) + cfqd->key_type = CFQ_KEY_GID; + spin_unlock_irq(cfqd->queue->queue_lock); + return count; +} + +static ssize_t +cfq_read_key_type(struct cfq_data *cfqd, char *page) +{ + ssize_t len = 0; + int i; + + for (i = CFQ_KEY_PGID; i < CFQ_KEY_LAST; i++) { + if (cfqd->key_type == i) + len += sprintf(page+len, "[%s] ", cfq_key_types[i]); + else + len += sprintf(page+len, "%s ", cfq_key_types[i]); + } + len += sprintf(page+len, "\n"); + return len; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ { \ - return cfq_var_show(__VAR, (page)); \ + unsigned int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return cfq_var_show(__data, (page)); \ } -SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum); -SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued); +SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); +SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); +SHOW_FUNCTION(cfq_fifo_expire_r_show, cfqd->cfq_fifo_expire_r, 1); +SHOW_FUNCTION(cfq_fifo_expire_w_show, cfqd->cfq_fifo_expire_w, 1); +SHOW_FUNCTION(cfq_fifo_batch_expire_show, cfqd->cfq_fifo_batch_expire, 1); +SHOW_FUNCTION(cfq_find_best_show, cfqd->find_best_crq, 0); +SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); +SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); #undef SHOW_FUNCTION -#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ { \ - int ret = cfq_var_store(__PTR, (page), count); \ - if (*(__PTR) < (MIN)) \ - *(__PTR) = (MIN); \ - else if (*(__PTR) > (MAX)) \ - *(__PTR) = (MAX); \ + unsigned int __data; \ + int ret = cfq_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ return ret; \ } -STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, INT_MAX); -STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, INT_MAX); +STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_fifo_expire_r_store, &cfqd->cfq_fifo_expire_r, 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_expire_w_store, &cfqd->cfq_fifo_expire_w, 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_batch_expire_store, &cfqd->cfq_fifo_batch_expire, 0, UINT_MAX, 1); +STORE_FUNCTION(cfq_find_best_store, &cfqd->find_best_crq, 0, 1, 0); +STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); +STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); #undef STORE_FUNCTION static struct cfq_fs_entry cfq_quantum_entry = { @@ -824,10 +1702,57 @@ static struct cfq_fs_entry cfq_queued_entry = { .show = cfq_queued_show, .store = cfq_queued_store, }; +static struct cfq_fs_entry cfq_fifo_expire_r_entry = { + .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_expire_r_show, + .store = cfq_fifo_expire_r_store, +}; +static struct cfq_fs_entry cfq_fifo_expire_w_entry = { + .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_expire_w_show, + .store = cfq_fifo_expire_w_store, +}; +static struct cfq_fs_entry cfq_fifo_batch_expire_entry = { + .attr = {.name = "fifo_batch_expire", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_batch_expire_show, + .store = cfq_fifo_batch_expire_store, +}; +static struct cfq_fs_entry cfq_find_best_entry = { + .attr = {.name = "find_best_crq", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_find_best_show, + .store = cfq_find_best_store, +}; +static struct cfq_fs_entry cfq_back_max_entry = { + .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_back_max_show, + .store = cfq_back_max_store, +}; +static struct cfq_fs_entry cfq_back_penalty_entry = { + .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_back_penalty_show, + .store = cfq_back_penalty_store, +}; +static struct cfq_fs_entry cfq_clear_elapsed_entry = { + .attr = {.name = "clear_elapsed", .mode = S_IWUSR }, + .store = cfq_clear_elapsed, +}; +static struct cfq_fs_entry cfq_key_type_entry = { + .attr = {.name = "key_type", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_read_key_type, + .store = cfq_set_key_type, +}; static struct attribute *default_attrs[] = { &cfq_quantum_entry.attr, &cfq_queued_entry.attr, + &cfq_fifo_expire_r_entry.attr, + &cfq_fifo_expire_w_entry.attr, + &cfq_fifo_batch_expire_entry.attr, + &cfq_key_type_entry.attr, + &cfq_find_best_entry.attr, + &cfq_back_max_entry.attr, + &cfq_back_penalty_entry.attr, + &cfq_clear_elapsed_entry.attr, NULL, }; @@ -868,23 +1793,56 @@ struct kobj_type cfq_ktype = { .default_attrs = default_attrs, }; -elevator_t iosched_cfq = { - .elevator_name = "cfq", - .elevator_ktype = &cfq_ktype, - .elevator_merge_fn = cfq_merge, - .elevator_merged_fn = cfq_merged_request, - .elevator_merge_req_fn = cfq_merged_requests, - .elevator_next_req_fn = cfq_next_request, - .elevator_add_req_fn = cfq_insert_request, - .elevator_remove_req_fn = cfq_remove_request, - .elevator_queue_empty_fn = cfq_queue_empty, - .elevator_former_req_fn = cfq_former_request, - .elevator_latter_req_fn = cfq_latter_request, - .elevator_set_req_fn = cfq_set_request, - .elevator_put_req_fn = cfq_put_request, - .elevator_may_queue_fn = cfq_may_queue, - .elevator_init_fn = cfq_init, - .elevator_exit_fn = cfq_exit, +static struct elevator_type iosched_cfq = { + .ops = { + .elevator_merge_fn = cfq_merge, + .elevator_merged_fn = cfq_merged_request, + .elevator_merge_req_fn = cfq_merged_requests, + .elevator_next_req_fn = cfq_next_request, + .elevator_add_req_fn = cfq_insert_request, + .elevator_remove_req_fn = cfq_remove_request, + .elevator_requeue_req_fn = cfq_requeue_request, + .elevator_queue_empty_fn = cfq_queue_empty, + .elevator_completed_req_fn = cfq_completed_request, + .elevator_former_req_fn = cfq_former_request, + .elevator_latter_req_fn = cfq_latter_request, + .elevator_set_req_fn = cfq_set_request, + .elevator_put_req_fn = cfq_put_request, + .elevator_may_queue_fn = cfq_may_queue, + .elevator_init_fn = cfq_init_queue, + .elevator_exit_fn = cfq_exit_queue, + }, + .elevator_ktype = &cfq_ktype, + .elevator_name = "cfq", + .elevator_owner = THIS_MODULE, }; -EXPORT_SYMBOL(iosched_cfq); +int cfq_init(void) +{ + int ret; + + if (cfq_slab_setup()) + return -ENOMEM; + + ret = elv_register(&iosched_cfq); + if (!ret) { + __module_get(THIS_MODULE); + return 0; + } + + cfq_slab_kill(); + return ret; +} + +static void __exit cfq_exit(void) +{ + cfq_slab_kill(); + elv_unregister(&iosched_cfq); +} + +module_init(cfq_init); +module_exit(cfq_exit); + +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler"); diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index b42a8d33f..137451931 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -21,7 +21,6 @@ */ #include /* CONFIG_PROC_FS */ #include -#include #include #include #include @@ -138,7 +137,7 @@ static struct gendisk *ida_gendisk[MAX_CTLR][NWD]; int cpqarray_init_step2(void); static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev); -static void *remap_pci_mem(ulong base, ulong size); +static void __iomem *remap_pci_mem(ulong base, ulong size); static int cpqarray_eisa_detect(void); static int pollcomplete(int ctlr); static void getgeometry(int ctlr); @@ -551,10 +550,10 @@ static int __init cpqarray_init_one( struct pci_dev *pdev, } static struct pci_driver cpqarray_pci_driver = { - name: "cpqarray", - probe: cpqarray_init_one, - remove: __devexit_p(cpqarray_remove_one_pci), - id_table: cpqarray_pci_device_id, + .name = "cpqarray", + .probe = cpqarray_init_one, + .remove = __devexit_p(cpqarray_remove_one_pci), + .id_table = cpqarray_pci_device_id, }; /* @@ -569,9 +568,9 @@ int __init cpqarray_init_step2(void) /* detect controllers */ printk(DRIVER_NAME "\n"); -/* TODO: If it's an eisa only system, will rc return negative? */ + rc = pci_register_driver(&cpqarray_pci_driver); - if (rc < 0) + if (rc) return rc; cpqarray_eisa_detect(); @@ -722,17 +721,16 @@ DBGINFO( /* * Map (physical) PCI mem into (virtual) kernel space */ -static void *remap_pci_mem(ulong base, ulong size) +static void __iomem *remap_pci_mem(ulong base, ulong size) { ulong page_base = ((ulong) base) & PAGE_MASK; ulong page_offs = ((ulong) base) - page_base; - void *page_remapped = ioremap(page_base, page_offs+size); + void __iomem *page_remapped = ioremap(page_base, page_offs+size); return (page_remapped ? (page_remapped + page_offs) : NULL); } #ifndef MODULE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13) /* * Config string is a comma separated set of i/o addresses of EISA cards. */ @@ -749,18 +747,6 @@ static int cpqarray_setup(char *str) __setup("smart2=", cpqarray_setup); -#else - -/* - * Copy the contents of the ints[] array passed to us by init. - */ -void cpqarray_setup(char *str, int *ints) -{ - int i; - for(i=0; ielevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq = RQ_DATA(rq); const int data_dir = rq_data_dir(drq->request); @@ -317,7 +317,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq) struct deadline_rq *drq = RQ_DATA(rq); if (drq) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; list_del_init(&drq->fifo); deadline_remove_merge_hints(q, drq); @@ -328,7 +328,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq) static int deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct request *__rq; int ret; @@ -383,7 +383,7 @@ out_insert: static void deadline_merged_request(request_queue_t *q, struct request *req) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq = RQ_DATA(req); /* @@ -407,7 +407,7 @@ static void deadline_merged_requests(request_queue_t *q, struct request *req, struct request *next) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq = RQ_DATA(req); struct deadline_rq *dnext = RQ_DATA(next); @@ -604,7 +604,7 @@ dispatch_request: static struct request *deadline_next_request(request_queue_t *q) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct request *rq; /* @@ -625,7 +625,7 @@ dispatch: static void deadline_insert_request(request_queue_t *q, struct request *rq, int where) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; /* barriers must flush the reorder queue */ if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) @@ -653,7 +653,7 @@ deadline_insert_request(request_queue_t *q, struct request *rq, int where) static int deadline_queue_empty(request_queue_t *q) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; if (!list_empty(&dd->fifo_list[WRITE]) || !list_empty(&dd->fifo_list[READ]) @@ -687,7 +687,7 @@ deadline_latter_request(request_queue_t *q, struct request *rq) return NULL; } -static void deadline_exit(request_queue_t *q, elevator_t *e) +static void deadline_exit_queue(elevator_t *e) { struct deadline_data *dd = e->elevator_data; @@ -703,7 +703,7 @@ static void deadline_exit(request_queue_t *q, elevator_t *e) * initialize elevator private data (deadline_data), and alloc a drq for * each request on the free lists */ -static int deadline_init(request_queue_t *q, elevator_t *e) +static int deadline_init_queue(request_queue_t *q, elevator_t *e) { struct deadline_data *dd; int i; @@ -748,7 +748,7 @@ static int deadline_init(request_queue_t *q, elevator_t *e) static void deadline_put_request(request_queue_t *q, struct request *rq) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq = RQ_DATA(rq); if (drq) { @@ -760,7 +760,7 @@ static void deadline_put_request(request_queue_t *q, struct request *rq) static int deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { - struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_data *dd = q->elevator->elevator_data; struct deadline_rq *drq; drq = mempool_alloc(dd->drq_pool, gfp_mask); @@ -805,33 +805,41 @@ deadline_var_store(unsigned int *var, const char *page, size_t count) return count; } -#define SHOW_FUNCTION(__FUNC, __VAR) \ +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ static ssize_t __FUNC(struct deadline_data *dd, char *page) \ { \ - return deadline_var_show(__VAR, (page)); \ -} -SHOW_FUNCTION(deadline_readexpire_show, dd->fifo_expire[READ]); -SHOW_FUNCTION(deadline_writeexpire_show, dd->fifo_expire[WRITE]); -SHOW_FUNCTION(deadline_writesstarved_show, dd->writes_starved); -SHOW_FUNCTION(deadline_frontmerges_show, dd->front_merges); -SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch); + unsigned int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return deadline_var_show(__data, (page)); \ +} +SHOW_FUNCTION(deadline_readexpire_show, dd->fifo_expire[READ], 1); +SHOW_FUNCTION(deadline_writeexpire_show, dd->fifo_expire[WRITE], 1); +SHOW_FUNCTION(deadline_writesstarved_show, dd->writes_starved, 0); +SHOW_FUNCTION(deadline_frontmerges_show, dd->front_merges, 0); +SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0); #undef SHOW_FUNCTION -#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \ { \ - int ret = deadline_var_store(__PTR, (page), count); \ - if (*(__PTR) < (MIN)) \ - *(__PTR) = (MIN); \ - else if (*(__PTR) > (MAX)) \ - *(__PTR) = (MAX); \ + unsigned int __data; \ + int ret = deadline_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ return ret; \ } -STORE_FUNCTION(deadline_readexpire_store, &dd->fifo_expire[READ], 0, INT_MAX); -STORE_FUNCTION(deadline_writeexpire_store, &dd->fifo_expire[WRITE], 0, INT_MAX); -STORE_FUNCTION(deadline_writesstarved_store, &dd->writes_starved, INT_MIN, INT_MAX); -STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1); -STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX); +STORE_FUNCTION(deadline_readexpire_store, &dd->fifo_expire[READ], 0, INT_MAX, 1); +STORE_FUNCTION(deadline_writeexpire_store, &dd->fifo_expire[WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(deadline_writesstarved_store, &dd->writes_starved, INT_MIN, INT_MAX, 0); +STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1, 0); +STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); #undef STORE_FUNCTION static struct deadline_fs_entry deadline_readexpire_entry = { @@ -906,36 +914,54 @@ struct kobj_type deadline_ktype = { .default_attrs = default_attrs, }; -static int __init deadline_slab_setup(void) +static struct elevator_type iosched_deadline = { + .ops = { + .elevator_merge_fn = deadline_merge, + .elevator_merged_fn = deadline_merged_request, + .elevator_merge_req_fn = deadline_merged_requests, + .elevator_next_req_fn = deadline_next_request, + .elevator_add_req_fn = deadline_insert_request, + .elevator_remove_req_fn = deadline_remove_request, + .elevator_queue_empty_fn = deadline_queue_empty, + .elevator_former_req_fn = deadline_former_request, + .elevator_latter_req_fn = deadline_latter_request, + .elevator_set_req_fn = deadline_set_request, + .elevator_put_req_fn = deadline_put_request, + .elevator_init_fn = deadline_init_queue, + .elevator_exit_fn = deadline_exit_queue, + }, + + .elevator_ktype = &deadline_ktype, + .elevator_name = "deadline", + .elevator_owner = THIS_MODULE, +}; + +static int __init deadline_init(void) { + int ret; + drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq), 0, 0, NULL, NULL); if (!drq_pool) - panic("deadline: can't init slab pool\n"); + return -ENOMEM; - return 0; + ret = elv_register(&iosched_deadline); + if (ret) + kmem_cache_destroy(drq_pool); + + return ret; } -subsys_initcall(deadline_slab_setup); - -elevator_t iosched_deadline = { - .elevator_merge_fn = deadline_merge, - .elevator_merged_fn = deadline_merged_request, - .elevator_merge_req_fn = deadline_merged_requests, - .elevator_next_req_fn = deadline_next_request, - .elevator_add_req_fn = deadline_insert_request, - .elevator_remove_req_fn = deadline_remove_request, - .elevator_queue_empty_fn = deadline_queue_empty, - .elevator_former_req_fn = deadline_former_request, - .elevator_latter_req_fn = deadline_latter_request, - .elevator_set_req_fn = deadline_set_request, - .elevator_put_req_fn = deadline_put_request, - .elevator_init_fn = deadline_init, - .elevator_exit_fn = deadline_exit, - - .elevator_ktype = &deadline_ktype, - .elevator_name = "deadline", -}; +static void __exit deadline_exit(void) +{ + kmem_cache_destroy(drq_pool); + elv_unregister(&iosched_deadline); +} + +module_init(deadline_init); +module_exit(deadline_exit); -EXPORT_SYMBOL(iosched_deadline); +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("deadline IO scheduler"); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 35c9385ac..52e29886f 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -37,6 +37,9 @@ #include +static spinlock_t elv_list_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(elv_list); + /* * can we safely merge with this request? */ @@ -60,6 +63,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) return 0; } +EXPORT_SYMBOL(elv_rq_merge_ok); inline int elv_try_merge(struct request *__rq, struct bio *bio) { @@ -77,6 +81,7 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio) return ret; } +EXPORT_SYMBOL(elv_try_merge); inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) { @@ -85,31 +90,136 @@ inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) return ELEVATOR_NO_MERGE; } +EXPORT_SYMBOL(elv_try_last_merge); -/* - * general block -> elevator interface starts here - */ -int elevator_init(request_queue_t *q, elevator_t *type) +struct elevator_type *elevator_find(const char *name) { - elevator_t *e = &q->elevator; + struct elevator_type *e = NULL; + struct list_head *entry; + + spin_lock_irq(&elv_list_lock); + list_for_each(entry, &elv_list) { + struct elevator_type *__e; - memcpy(e, type, sizeof(*e)); + __e = list_entry(entry, struct elevator_type, list); + + if (!strcmp(__e->elevator_name, name)) { + e = __e; + break; + } + } + spin_unlock_irq(&elv_list_lock); + + return e; +} + +static void elevator_put(struct elevator_type *e) +{ + module_put(e->elevator_owner); +} + +static struct elevator_type *elevator_get(const char *name) +{ + struct elevator_type *e = elevator_find(name); + + if (!e) + return NULL; + if (!try_module_get(e->elevator_owner)) + return NULL; + + return e; +} + +static int elevator_attach(request_queue_t *q, struct elevator_type *e, + struct elevator_queue *eq) +{ + int ret = 0; + + memset(eq, 0, sizeof(*eq)); + eq->ops = &e->ops; + eq->elevator_type = e; INIT_LIST_HEAD(&q->queue_head); q->last_merge = NULL; + q->elevator = eq; + + if (eq->ops->elevator_init_fn) + ret = eq->ops->elevator_init_fn(q, eq); + + return ret; +} - if (e->elevator_init_fn) - return e->elevator_init_fn(q, e); +static char chosen_elevator[16]; +static void elevator_setup_default(void) +{ + /* + * check if default is set and exists + */ + if (chosen_elevator[0] && elevator_find(chosen_elevator)) + return; + +#if defined(CONFIG_IOSCHED_AS) + strcpy(chosen_elevator, "anticipatory"); +#elif defined(CONFIG_IOSCHED_DEADLINE) + strcpy(chosen_elevator, "deadline"); +#elif defined(CONFIG_IOSCHED_CFQ) + strcpy(chosen_elevator, "cfq"); +#elif defined(CONFIG_IOSCHED_NOOP) + strcpy(chosen_elevator, "noop"); +#else +#error "You must build at least 1 IO scheduler into the kernel" +#endif + printk(KERN_INFO "elevator: using %s as default io scheduler\n", + chosen_elevator); +} + +static int __init elevator_setup(char *str) +{ + strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); return 0; } -void elevator_exit(request_queue_t *q) +__setup("elevator=", elevator_setup); + +int elevator_init(request_queue_t *q, char *name) +{ + struct elevator_type *e = NULL; + struct elevator_queue *eq; + int ret = 0; + + elevator_setup_default(); + + if (!name) + name = chosen_elevator; + + e = elevator_get(name); + if (!e) + return -EINVAL; + + eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); + if (!eq) { + elevator_put(e->elevator_type); + return -ENOMEM; + } + + ret = elevator_attach(q, e, eq); + if (ret) { + kfree(eq); + elevator_put(e->elevator_type); + } + + return ret; +} + +void elevator_exit(elevator_t *e) { - elevator_t *e = &q->elevator; + if (e->ops->elevator_exit_fn) + e->ops->elevator_exit_fn(e); - if (e->elevator_exit_fn) - e->elevator_exit_fn(q, e); + elevator_put(e->elevator_type); + e->elevator_type = NULL; + kfree(e); } int elevator_global_init(void) @@ -119,32 +229,32 @@ int elevator_global_init(void) int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_merge_fn) - return e->elevator_merge_fn(q, req, bio); + if (e->ops->elevator_merge_fn) + return e->ops->elevator_merge_fn(q, req, bio); return ELEVATOR_NO_MERGE; } void elv_merged_request(request_queue_t *q, struct request *rq) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_merged_fn) - e->elevator_merged_fn(q, rq); + if (e->ops->elevator_merged_fn) + e->ops->elevator_merged_fn(q, rq); } void elv_merge_requests(request_queue_t *q, struct request *rq, struct request *next) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; if (q->last_merge == next) q->last_merge = NULL; - if (e->elevator_merge_req_fn) - e->elevator_merge_req_fn(q, rq, next); + if (e->ops->elevator_merge_req_fn) + e->ops->elevator_merge_req_fn(q, rq, next); } void elv_requeue_request(request_queue_t *q, struct request *rq) @@ -160,8 +270,8 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) * if iosched has an explicit requeue hook, then use that. otherwise * just put the request at the front of the queue */ - if (q->elevator.elevator_requeue_req_fn) - q->elevator.elevator_requeue_req_fn(q, rq); + if (q->elevator->ops->elevator_requeue_req_fn) + q->elevator->ops->elevator_requeue_req_fn(q, rq); else __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } @@ -180,15 +290,24 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, blk_plug_device(q); rq->q = q; - q->elevator.elevator_add_req_fn(q, rq, where); - if (blk_queue_plugged(q)) { - int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight; + if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) { + q->elevator->ops->elevator_add_req_fn(q, rq, where); - if (nrq == q->unplug_thresh) - __generic_unplug_device(q); - } + if (blk_queue_plugged(q)) { + int nrq = q->rq.count[READ] + q->rq.count[WRITE] + - q->in_flight; + if (nrq == q->unplug_thresh) + __generic_unplug_device(q); + } + } else + /* + * if drain is set, store the request "locally". when the drain + * is finished, the requests will be handed ordered to the io + * scheduler + */ + list_add_tail(&rq->queuelist, &q->drain_list); } void elv_add_request(request_queue_t *q, struct request *rq, int where, @@ -203,7 +322,7 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where, static inline struct request *__elv_next_request(request_queue_t *q) { - return q->elevator.elevator_next_req_fn(q); + return q->elevator->ops->elevator_next_req_fn(q); } struct request *elv_next_request(request_queue_t *q) @@ -242,7 +361,8 @@ struct request *elv_next_request(request_queue_t *q) end_that_request_chunk(rq, 0, nr_bytes); end_that_request_last(rq); } else { - printk("%s: bad return=%d\n", __FUNCTION__, ret); + printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__, + ret); break; } } @@ -252,7 +372,7 @@ struct request *elv_next_request(request_queue_t *q) void elv_remove_request(request_queue_t *q, struct request *rq) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; /* * the time frame between a request being removed from the lists @@ -274,16 +394,16 @@ void elv_remove_request(request_queue_t *q, struct request *rq) if (rq == q->last_merge) q->last_merge = NULL; - if (e->elevator_remove_req_fn) - e->elevator_remove_req_fn(q, rq); + if (e->ops->elevator_remove_req_fn) + e->ops->elevator_remove_req_fn(q, rq); } int elv_queue_empty(request_queue_t *q) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_queue_empty_fn) - return e->elevator_queue_empty_fn(q); + if (e->ops->elevator_queue_empty_fn) + return e->ops->elevator_queue_empty_fn(q); return list_empty(&q->queue_head); } @@ -292,10 +412,10 @@ struct request *elv_latter_request(request_queue_t *q, struct request *rq) { struct list_head *next; - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_latter_req_fn) - return e->elevator_latter_req_fn(q, rq); + if (e->ops->elevator_latter_req_fn) + return e->ops->elevator_latter_req_fn(q, rq); next = rq->queuelist.next; if (next != &q->queue_head && next != &rq->queuelist) @@ -308,10 +428,10 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) { struct list_head *prev; - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_former_req_fn) - return e->elevator_former_req_fn(q, rq); + if (e->ops->elevator_former_req_fn) + return e->ops->elevator_former_req_fn(q, rq); prev = rq->queuelist.prev; if (prev != &q->queue_head && prev != &rq->queuelist) @@ -322,10 +442,10 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_set_req_fn) - return e->elevator_set_req_fn(q, rq, gfp_mask); + if (e->ops->elevator_set_req_fn) + return e->ops->elevator_set_req_fn(q, rq, gfp_mask); rq->elevator_private = NULL; return 0; @@ -333,25 +453,25 @@ int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask) void elv_put_request(request_queue_t *q, struct request *rq) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_put_req_fn) - e->elevator_put_req_fn(q, rq); + if (e->ops->elevator_put_req_fn) + e->ops->elevator_put_req_fn(q, rq); } int elv_may_queue(request_queue_t *q, int rw) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; - if (e->elevator_may_queue_fn) - return e->elevator_may_queue_fn(q, rw); + if (e->ops->elevator_may_queue_fn) + return e->ops->elevator_may_queue_fn(q, rw); - return 0; + return ELV_MQUEUE_MAY; } void elv_completed_request(request_queue_t *q, struct request *rq) { - elevator_t *e = &q->elevator; + elevator_t *e = q->elevator; /* * request is released from the driver, io must be done @@ -359,22 +479,20 @@ void elv_completed_request(request_queue_t *q, struct request *rq) if (blk_account_rq(rq)) q->in_flight--; - if (e->elevator_completed_req_fn) - e->elevator_completed_req_fn(q, rq); + if (e->ops->elevator_completed_req_fn) + e->ops->elevator_completed_req_fn(q, rq); } int elv_register_queue(struct request_queue *q) { - elevator_t *e; - - e = &q->elevator; + elevator_t *e = q->elevator; e->kobj.parent = kobject_get(&q->kobj); if (!e->kobj.parent) return -EBUSY; snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); - e->kobj.ktype = e->elevator_ktype; + e->kobj.ktype = e->elevator_type->elevator_ktype; return kobject_register(&e->kobj); } @@ -382,12 +500,157 @@ int elv_register_queue(struct request_queue *q) void elv_unregister_queue(struct request_queue *q) { if (q) { - elevator_t * e = &q->elevator; + elevator_t *e = q->elevator; kobject_unregister(&e->kobj); kobject_put(&q->kobj); } } +int elv_register(struct elevator_type *e) +{ + if (elevator_find(e->elevator_name)) + BUG(); + + spin_lock_irq(&elv_list_lock); + list_add_tail(&e->list, &elv_list); + spin_unlock_irq(&elv_list_lock); + + printk(KERN_INFO "io scheduler %s registered\n", e->elevator_name); + return 0; +} +EXPORT_SYMBOL_GPL(elv_register); + +void elv_unregister(struct elevator_type *e) +{ + spin_lock_irq(&elv_list_lock); + list_del_init(&e->list); + spin_unlock_irq(&elv_list_lock); +} +EXPORT_SYMBOL_GPL(elv_unregister); + +/* + * switch to new_e io scheduler. be careful not to introduce deadlocks - + * we don't free the old io scheduler, before we have allocated what we + * need for the new one. this way we have a chance of going back to the old + * one, if the new one fails init for some reason. we also do an intermediate + * switch to noop to ensure safety with stack-allocated requests, since they + * don't originate from the block layer allocator. noop is safe here, because + * it never needs to touch the elevator itself for completion events. DRAIN + * flags will make sure we don't touch it for additions either. + */ +static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) +{ + elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL); + struct elevator_type *noop_elevator = NULL; + elevator_t *old_elevator; + + if (!e) + goto error; + + /* + * first step, drain requests from the block freelist + */ + blk_wait_queue_drained(q, 0); + + /* + * unregister old elevator data + */ + elv_unregister_queue(q); + old_elevator = q->elevator; + + /* + * next step, switch to noop since it uses no private rq structures + * and doesn't allocate any memory for anything. then wait for any + * non-fs requests in-flight + */ + noop_elevator = elevator_get("noop"); + spin_lock_irq(q->queue_lock); + elevator_attach(q, noop_elevator, e); + spin_unlock_irq(q->queue_lock); + + blk_wait_queue_drained(q, 1); + + /* + * attach and start new elevator + */ + if (elevator_attach(q, new_e, e)) + goto fail; + + if (elv_register_queue(q)) + goto fail_register; + + /* + * finally exit old elevator and start queue again + */ + elevator_exit(old_elevator); + blk_finish_queue_drain(q); + elevator_put(noop_elevator); + return; + +fail_register: + /* + * switch failed, exit the new io scheduler and reattach the old + * one again (along with re-adding the sysfs dir) + */ + elevator_exit(e); +fail: + q->elevator = old_elevator; + elv_register_queue(q); + blk_finish_queue_drain(q); +error: + if (noop_elevator) + elevator_put(noop_elevator); + elevator_put(new_e); + printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); +} + +ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) +{ + char elevator_name[ELV_NAME_MAX]; + struct elevator_type *e; + + memset(elevator_name, 0, sizeof(elevator_name)); + strncpy(elevator_name, name, sizeof(elevator_name)); + + if (elevator_name[strlen(elevator_name) - 1] == '\n') + elevator_name[strlen(elevator_name) - 1] = '\0'; + + e = elevator_get(elevator_name); + if (!e) { + printk(KERN_ERR "elevator: type %s not found\n", elevator_name); + return -EINVAL; + } + + if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) + return count; + + elevator_switch(q, e); + return count; +} + +ssize_t elv_iosched_show(request_queue_t *q, char *name) +{ + elevator_t *e = q->elevator; + struct elevator_type *elv = e->elevator_type; + struct list_head *entry; + int len = 0; + + spin_lock_irq(q->queue_lock); + list_for_each(entry, &elv_list) { + struct elevator_type *__e; + + __e = list_entry(entry, struct elevator_type, list); + if (!strcmp(elv->elevator_name, __e->elevator_name)) + len += sprintf(name+len, "[%s] ", elv->elevator_name); + else + len += sprintf(name+len, "%s ", __e->elevator_name); + } + spin_unlock_irq(q->queue_lock); + + len += sprintf(len+name, "\n"); + return len; +} + module_init(elevator_global_init); EXPORT_SYMBOL(elv_add_request); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5bf390d1b..4f824c17b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1787,10 +1787,11 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs) } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei); } - if (handler) - schedule_bh(handler); - else + if (!handler) { FDCS->reset = 1; + return IRQ_NONE; + } + schedule_bh(handler); is_alive("normal interrupt end"); /* FIXME! Was it really for us? */ @@ -4124,7 +4125,7 @@ static struct param_table { int *var; int def_param; int param2; -} config_params[] = { +} config_params[] __initdata = { {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */ {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0}, @@ -4286,6 +4287,13 @@ int __init floppy_init(void) } use_virtual_dma = can_use_virtual_dma & 1; +#if defined(CONFIG_PPC64) + if (check_legacy_ioport(FDC1)) { + del_timer(&fd_timeout); + err = -ENODEV; + goto out_unreg_region; + } +#endif fdc_state[0].address = FDC1; if (fdc_state[0].address == -1) { del_timer(&fd_timeout); @@ -4315,6 +4323,12 @@ int __init floppy_init(void) floppy_track_buffer = NULL; max_buffer_sectors = 0; } + /* + * Small 10 msec delay to let through any interrupt that + * initialization might have triggered, to not + * confuse detection: + */ + msleep(10); for (i = 0; i < N_FDC; i++) { fdc = i; @@ -4623,9 +4637,9 @@ void cleanup_module(void) wait_for_completion(&device_release); } -MODULE_PARM(floppy, "s"); -MODULE_PARM(FLOPPY_IRQ, "i"); -MODULE_PARM(FLOPPY_DMA, "i"); +module_param(floppy, charp, 0); +module_param(FLOPPY_IRQ, int, 0); +module_param(FLOPPY_DMA, int, 0); MODULE_AUTHOR("Alain L. Knaff"); MODULE_SUPPORTED_DEVICE("fd"); MODULE_LICENSE("GPL"); diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index e82caa224..bfbdcf0a3 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -365,7 +365,9 @@ static ssize_t disk_size_read(struct gendisk * disk, char *page) static ssize_t disk_stats_read(struct gendisk * disk, char *page) { + preempt_disable(); disk_round_stats(disk); + preempt_enable(); return sprintf(page, "%8u %8u %8llu %8u " "%8u %8u %8llu %8u " @@ -436,8 +438,52 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj) return ((ktype == &ktype_block) || (ktype == &ktype_part)); } +static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + struct device *dev = NULL; + struct kobj_type *ktype = get_ktype(kobj); + int length = 0; + int i = 0; + + /* get physical device backing disk or partition */ + if (ktype == &ktype_block) { + struct gendisk *disk = container_of(kobj, struct gendisk, kobj); + dev = disk->driverfs_dev; + } else if (ktype == &ktype_part) { + struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj); + dev = disk->driverfs_dev; + } + + if (dev) { + /* add physical device, backing this device */ + char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); + + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, + &length, "PHYSDEVPATH=%s", path); + kfree(path); + + /* add bus name of physical device */ + if (dev->bus) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVBUS=%s", dev->bus->name); + + /* add driver name of physical device */ + if (dev->driver) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVDRIVER=%s", dev->driver->name); + + envp[i] = NULL; + } + + return 0; +} + static struct kset_hotplug_ops block_hotplug_ops = { - .filter = block_hotplug_filter, + .filter = block_hotplug_filter, + .hotplug = block_hotplug, }; /* declare block_subsys. */ @@ -494,7 +540,9 @@ static int diskstats_show(struct seq_file *s, void *v) "\n\n"); */ + preempt_disable(); disk_round_stats(gp); + preempt_enable(); seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n", gp->major, n + gp->first_minor, disk_name(gp, n, buf), disk_stat_read(gp, reads), disk_stat_read(gp, read_merges), diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c index 283a9f2fa..43ff0c6ed 100644 --- a/drivers/block/ioctl.c +++ b/drivers/block/ioctl.c @@ -194,7 +194,8 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, return -EACCES; if (disk->fops->ioctl) { ret = disk->fops->ioctl(inode, file, cmd, arg); - if (ret != -EINVAL) + /* -EINVAL to handle old uncorrected drivers */ + if (ret != -EINVAL && ret != -ENOTTY) return ret; } fsync_bdev(bdev); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 17c403ebd..98db1776b 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -100,7 +100,7 @@ static void blk_queue_congestion_threshold(struct request_queue *q) nr = q->nr_requests; q->nr_congestion_on = nr; - nr = q->nr_requests - (q->nr_requests / 8) - 1; + nr = q->nr_requests - (q->nr_requests / 8) - (q->nr_requests / 16) - 1; if (nr < 1) nr = 1; q->nr_congestion_off = nr; @@ -154,6 +154,8 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev) return ret; } +EXPORT_SYMBOL(blk_get_backing_dev_info); + void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) { q->activity_fn = fn; @@ -241,6 +243,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) blk_queue_hardsect_size(q, 512); blk_queue_dma_alignment(q, 511); blk_queue_congestion_threshold(q); + q->nr_batching = BLK_BATCH_REQ; q->unplug_thresh = 4; /* hmm */ q->unplug_delay = (3 * HZ) / 1000; /* 3 milliseconds */ @@ -258,10 +261,51 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); blk_queue_activity_fn(q, NULL, NULL); + + INIT_LIST_HEAD(&q->drain_list); } EXPORT_SYMBOL(blk_queue_make_request); +/** + * blk_queue_ordered - does this queue support ordered writes + * @q: the request queue + * @flag: see below + * + * Description: + * For journalled file systems, doing ordered writes on a commit + * block instead of explicitly doing wait_on_buffer (which is bad + * for performance) can be a big win. Block drivers supporting this + * feature should call this function and indicate so. + * + **/ +void blk_queue_ordered(request_queue_t *q, int flag) +{ + if (flag) + set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags); + else + clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags); +} + +EXPORT_SYMBOL(blk_queue_ordered); + +/** + * blk_queue_issue_flush_fn - set function for issuing a flush + * @q: the request queue + * @iff: the function to be called issuing the flush + * + * Description: + * If a driver supports issuing a flush command, the support is notified + * to the block layer by defining it through this call. + * + **/ +void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff) +{ + q->issue_flush_fn = iff; +} + +EXPORT_SYMBOL(blk_queue_issue_flush_fn); + /** * blk_queue_bounce_limit - set bounce buffer limit for queue * @q: the request queue for the device @@ -311,7 +355,7 @@ void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors) printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors); } - q->max_sectors = max_sectors; + q->max_sectors = q->max_hw_sectors = max_sectors; } EXPORT_SYMBOL(blk_queue_max_sectors); @@ -413,7 +457,8 @@ EXPORT_SYMBOL(blk_queue_hardsect_size); void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b) { /* zero is "infinity" */ - t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors); + t->max_sectors = t->max_hw_sectors = + min_not_zero(t->max_sectors,b->max_sectors); t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments); t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); @@ -482,15 +527,14 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) EXPORT_SYMBOL(blk_queue_find_tag); /** - * blk_queue_free_tags - release tag maintenance info + * __blk_queue_free_tags - release tag maintenance info * @q: the request queue for the device * * Notes: * blk_cleanup_queue() will take care of calling this function, if tagging - * has been used. So there's usually no need to call this directly, unless - * tagging is just being disabled but the queue remains in function. + * has been used. So there's no need to call this directly. **/ -void blk_queue_free_tags(request_queue_t *q) +static void __blk_queue_free_tags(request_queue_t *q) { struct blk_queue_tag *bqt = q->queue_tags; @@ -514,12 +558,27 @@ void blk_queue_free_tags(request_queue_t *q) q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED); } +/** + * blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + * + * Notes: + * This is used to disabled tagged queuing to a device, yet leave + * queue in function. + **/ +void blk_queue_free_tags(request_queue_t *q) +{ + clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); +} + EXPORT_SYMBOL(blk_queue_free_tags); static int init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) { int bits, i; + struct request **tag_index; + unsigned long *tag_map; if (depth > q->nr_requests * 2) { depth = q->nr_requests * 2; @@ -527,32 +586,31 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) __FUNCTION__, depth); } - tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); - if (!tags->tag_index) + tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); + if (!tag_index) goto fail; bits = (depth / BLK_TAGS_PER_LONG) + 1; - tags->tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC); - if (!tags->tag_map) + tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC); + if (!tag_map) goto fail; - memset(tags->tag_index, 0, depth * sizeof(struct request *)); - memset(tags->tag_map, 0, bits * sizeof(unsigned long)); + memset(tag_index, 0, depth * sizeof(struct request *)); + memset(tag_map, 0, bits * sizeof(unsigned long)); tags->max_depth = depth; tags->real_max_depth = bits * BITS_PER_LONG; + tags->tag_index = tag_index; + tags->tag_map = tag_map; /* * set the upper bits if the depth isn't a multiple of the word size */ for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++) - __set_bit(i, tags->tag_map); + __set_bit(i, tag_map); - INIT_LIST_HEAD(&tags->busy_list); - tags->busy = 0; - atomic_set(&tags->refcnt, 1); return 0; fail: - kfree(tags->tag_index); + kfree(tag_index); return -ENOMEM; } @@ -564,13 +622,26 @@ fail: int blk_queue_init_tags(request_queue_t *q, int depth, struct blk_queue_tag *tags) { - if (!tags) { + int rc; + + BUG_ON(tags && q->queue_tags && tags != q->queue_tags); + + if (!tags && !q->queue_tags) { tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC); if (!tags) goto fail; if (init_tag_map(q, tags, depth)) goto fail; + + INIT_LIST_HEAD(&tags->busy_list); + tags->busy = 0; + atomic_set(&tags->refcnt, 1); + } else if (q->queue_tags) { + if ((rc = blk_queue_resize_tags(q, depth))) + return rc; + set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); + return 0; } else atomic_inc(&tags->refcnt); @@ -1286,9 +1357,29 @@ void blk_stop_queue(request_queue_t *q) blk_remove_plug(q); set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); } - EXPORT_SYMBOL(blk_stop_queue); +/** + * blk_sync_queue - cancel any pending callbacks on a queue + * @q: the queue + * + * Description: + * The block layer may perform asynchronous callback activity + * on a queue, such as calling the unplug function after a timeout. + * A block device may call blk_sync_queue to ensure that any + * such activity is cancelled, thus allowing it to release resources + * the the callbacks might use. The caller must already have made sure + * that its ->make_request_fn will not re-add plugging prior to calling + * this function. + * + */ +void blk_sync_queue(struct request_queue *q) +{ + del_timer_sync(&q->unplug_timer); + kblockd_flush(); +} +EXPORT_SYMBOL(blk_sync_queue); + /** * blk_run_queue - run a single device queue * @q: The queue to run @@ -1302,7 +1393,6 @@ void blk_run_queue(struct request_queue *q) q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); } - EXPORT_SYMBOL(blk_run_queue); /** @@ -1327,16 +1417,16 @@ void blk_cleanup_queue(request_queue_t * q) if (!atomic_dec_and_test(&q->refcnt)) return; - elevator_exit(q); + if (q->elevator) + elevator_exit(q->elevator); - del_timer_sync(&q->unplug_timer); - kblockd_flush(); + blk_sync_queue(q); if (rl->rq_pool) mempool_destroy(rl->rq_pool); - if (blk_queue_tagged(q)) - blk_queue_free_tags(q); + if (q->queue_tags) + __blk_queue_free_tags(q); kmem_cache_free(requestq_cachep, q); } @@ -1350,6 +1440,7 @@ static int blk_init_free_list(request_queue_t *q) rl->count[READ] = rl->count[WRITE] = 0; init_waitqueue_head(&rl->wait[READ]); init_waitqueue_head(&rl->wait[WRITE]); + init_waitqueue_head(&rl->drain); rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep); @@ -1361,45 +1452,6 @@ static int blk_init_free_list(request_queue_t *q) static int __make_request(request_queue_t *, struct bio *); -static elevator_t *chosen_elevator = -#if defined(CONFIG_IOSCHED_AS) - &iosched_as; -#elif defined(CONFIG_IOSCHED_DEADLINE) - &iosched_deadline; -#elif defined(CONFIG_IOSCHED_CFQ) - &iosched_cfq; -#elif defined(CONFIG_IOSCHED_NOOP) - &elevator_noop; -#else - NULL; -#error "You must have at least 1 I/O scheduler selected" -#endif - -#if defined(CONFIG_IOSCHED_AS) || defined(CONFIG_IOSCHED_DEADLINE) || defined (CONFIG_IOSCHED_NOOP) -static int __init elevator_setup(char *str) -{ -#ifdef CONFIG_IOSCHED_DEADLINE - if (!strcmp(str, "deadline")) - chosen_elevator = &iosched_deadline; -#endif -#ifdef CONFIG_IOSCHED_AS - if (!strcmp(str, "as")) - chosen_elevator = &iosched_as; -#endif -#ifdef CONFIG_IOSCHED_CFQ - if (!strcmp(str, "cfq")) - chosen_elevator = &iosched_cfq; -#endif -#ifdef CONFIG_IOSCHED_NOOP - if (!strcmp(str, "noop")) - chosen_elevator = &elevator_noop; -#endif - return 1; -} - -__setup("elevator=", elevator_setup); -#endif /* CONFIG_IOSCHED_AS || CONFIG_IOSCHED_DEADLINE || CONFIG_IOSCHED_NOOP */ - request_queue_t *blk_alloc_queue(int gfp_mask) { request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask); @@ -1452,21 +1504,14 @@ EXPORT_SYMBOL(blk_alloc_queue); **/ request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) { - request_queue_t *q; - static int printed; + request_queue_t *q = blk_alloc_queue(GFP_KERNEL); - q = blk_alloc_queue(GFP_KERNEL); if (!q) return NULL; if (blk_init_free_list(q)) goto out_init; - if (!printed) { - printed = 1; - printk("Using %s io scheduler\n", chosen_elevator->elevator_name); - } - q->request_fn = rfn; q->back_merge_fn = ll_back_merge_fn; q->front_merge_fn = ll_front_merge_fn; @@ -1487,8 +1532,10 @@ request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) /* * all done */ - if (!elevator_init(q, chosen_elevator)) + if (!elevator_init(q, NULL)) { + blk_queue_congestion_threshold(q); return q; + } blk_cleanup_queue(q); out_init: @@ -1516,13 +1563,20 @@ static inline void blk_free_request(request_queue_t *q, struct request *rq) mempool_free(rq, q->rq.rq_pool); } -static inline struct request *blk_alloc_request(request_queue_t *q,int gfp_mask) +static inline struct request *blk_alloc_request(request_queue_t *q, int rw, + int gfp_mask) { struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); if (!rq) return NULL; + /* + * first three bits are identical in rq->flags and bio->bi_rw, + * see bio.h and blkdev.h + */ + rq->flags = rw; + if (!elv_set_request(q, rq, gfp_mask)) return rq; @@ -1534,7 +1588,7 @@ static inline struct request *blk_alloc_request(request_queue_t *q,int gfp_mask) * ioc_batching returns true if the ioc is a valid batching request and * should be given priority access to a request. */ -static inline int ioc_batching(struct io_context *ioc) +static inline int ioc_batching(request_queue_t *q, struct io_context *ioc) { if (!ioc) return 0; @@ -1544,7 +1598,7 @@ static inline int ioc_batching(struct io_context *ioc) * even if the batch times out, otherwise we could theoretically * lose wakeups. */ - return ioc->nr_batch_requests == BLK_BATCH_REQ || + return ioc->nr_batch_requests == q->nr_batching || (ioc->nr_batch_requests > 0 && time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME)); } @@ -1555,12 +1609,12 @@ static inline int ioc_batching(struct io_context *ioc) * is the behaviour we want though - once it gets a wakeup it should be given * a nice run. */ -void ioc_set_batching(struct io_context *ioc) +void ioc_set_batching(request_queue_t *q, struct io_context *ioc) { - if (!ioc || ioc_batching(ioc)) + if (!ioc || ioc_batching(q, ioc)) return; - ioc->nr_batch_requests = BLK_BATCH_REQ; + ioc->nr_batch_requests = q->nr_batching; ioc->last_waited = jiffies; } @@ -1576,11 +1630,14 @@ static void freed_request(request_queue_t *q, int rw) if (rl->count[rw] < queue_congestion_off_threshold(q)) clear_queue_congested(q, rw); if (rl->count[rw]+1 <= q->nr_requests) { + smp_mb(); if (waitqueue_active(&rl->wait[rw])) wake_up(&rl->wait[rw]); - if (!waitqueue_active(&rl->wait[rw])) - blk_clear_queue_full(q, rw); + blk_clear_queue_full(q, rw); } + if (unlikely(waitqueue_active(&rl->drain)) && + !rl->count[READ] && !rl->count[WRITE]) + wake_up(&rl->drain); } #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) @@ -1593,6 +1650,9 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) struct request_list *rl = &q->rq; struct io_context *ioc = get_io_context(gfp_mask); + if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) + goto out; + spin_lock_irq(q->queue_lock); if (rl->count[rw]+1 >= q->nr_requests) { /* @@ -1602,13 +1662,22 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) * will be blocked. */ if (!blk_queue_full(q, rw)) { - ioc_set_batching(ioc); + ioc_set_batching(q, ioc); blk_set_queue_full(q, rw); } } - if (blk_queue_full(q, rw) - && !ioc_batching(ioc) && !elv_may_queue(q, rw)) { + switch (elv_may_queue(q, rw)) { + case ELV_MQUEUE_NO: + spin_unlock_irq(q->queue_lock); + goto out; + case ELV_MQUEUE_MAY: + break; + case ELV_MQUEUE_MUST: + goto get_rq; + } + + if (blk_queue_full(q, rw) && !ioc_batching(q, ioc)) { /* * The queue is full and the allocating process is not a * "batcher", and not exempted by the IO scheduler @@ -1617,12 +1686,13 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) goto out; } +get_rq: rl->count[rw]++; if (rl->count[rw] >= queue_congestion_on_threshold(q)) set_queue_congested(q, rw); spin_unlock_irq(q->queue_lock); - rq = blk_alloc_request(q, gfp_mask); + rq = blk_alloc_request(q, rw, gfp_mask); if (!rq) { /* * Allocation failed presumably due to memory. Undo anything @@ -1637,17 +1707,11 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) goto out; } - if (ioc_batching(ioc)) + if (ioc_batching(q, ioc)) ioc->nr_batch_requests--; INIT_LIST_HEAD(&rq->queuelist); - /* - * first three bits are identical in rq->flags and bio->bi_rw, - * see bio.h and blkdev.h - */ - rq->flags = rw; - rq->errors = 0; rq->rq_status = RQ_ACTIVE; rq->bio = rq->biotail = NULL; @@ -1696,7 +1760,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw) * See ioc_batching, ioc_set_batching */ ioc = get_io_context(GFP_NOIO); - ioc_set_batching(ioc); + ioc_set_batching(q, ioc); put_io_context(ioc); } finish_wait(&rl->wait[rw], &wait); @@ -1925,10 +1989,11 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, } rq->flags |= REQ_NOMERGE; - rq->waiting = &wait; + if (!rq->waiting) + rq->waiting = &wait; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); - wait_for_completion(&wait); + wait_for_completion(rq->waiting); rq->waiting = NULL; if (rq->errors) @@ -1939,6 +2004,72 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, EXPORT_SYMBOL(blk_execute_rq); +/** + * blkdev_issue_flush - queue a flush + * @bdev: blockdev to issue flush for + * @error_sector: error sector + * + * Description: + * Issue a flush for the block device in question. Caller can supply + * room for storing the error offset in case of a flush error, if they + * wish to. Caller must run wait_for_completion() on its own. + */ +int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) +{ + request_queue_t *q; + + if (bdev->bd_disk == NULL) + return -ENXIO; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + if (!q->issue_flush_fn) + return -EOPNOTSUPP; + + return q->issue_flush_fn(q, bdev->bd_disk, error_sector); +} + +EXPORT_SYMBOL(blkdev_issue_flush); + +/** + * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices + * @q: device queue + * @disk: gendisk + * @error_sector: error offset + * + * Description: + * Devices understanding the SCSI command set, can use this function as + * a helper for issuing a cache flush. Note: driver is required to store + * the error offset (in case of error flushing) in ->sector of struct + * request. + */ +int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT); + int ret; + + rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; + rq->sector = 0; + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->cmd[0] = 0x35; + rq->cmd_len = 12; + rq->data = NULL; + rq->data_len = 0; + rq->timeout = 60 * HZ; + + ret = blk_execute_rq(q, disk, rq); + + if (ret && error_sector) + *error_sector = rq->sector; + + blk_put_request(rq); + return ret; +} + +EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn); + void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) { int rw = rq_data_dir(rq); @@ -1947,13 +2078,13 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) return; if (rw == READ) { - disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); + __disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); if (!new_io) - disk_stat_inc(rq->rq_disk, read_merges); + __disk_stat_inc(rq->rq_disk, read_merges); } else if (rw == WRITE) { - disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); + __disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); if (!new_io) - disk_stat_inc(rq->rq_disk, write_merges); + __disk_stat_inc(rq->rq_disk, write_merges); } if (new_io) { disk_round_stats(rq->rq_disk); @@ -1999,12 +2130,12 @@ void disk_round_stats(struct gendisk *disk) { unsigned long now = jiffies; - disk_stat_add(disk, time_in_queue, + __disk_stat_add(disk, time_in_queue, disk->in_flight * (now - disk->stamp)); disk->stamp = now; if (disk->in_flight) - disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); + __disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); disk->stamp_idle = now; } @@ -2192,7 +2323,7 @@ EXPORT_SYMBOL(__blk_attempt_remerge); static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; - int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; + int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err; sector_t sector; sector = bio->bi_sector; @@ -2210,9 +2341,11 @@ static int __make_request(request_queue_t *q, struct bio *bio) spin_lock_prefetch(q->queue_lock); - barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw); - - ra = bio->bi_rw & (1 << BIO_RW_AHEAD); + barrier = bio_barrier(bio); + if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) { + err = -EOPNOTSUPP; + goto end_io; + } again: spin_lock_irq(q->queue_lock); @@ -2247,9 +2380,7 @@ again: break; bio->bi_next = req->bio; - req->cbio = req->bio = bio; - req->nr_cbio_segments = bio_segments(bio); - req->nr_cbio_sectors = bio_sectors(bio); + req->bio = bio; /* * may not be valid. if the low level driver said @@ -2292,7 +2423,8 @@ get_rq: /* * READA bit set */ - if (ra) + err = -EWOULDBLOCK; + if (bio_rw_ahead(bio)) goto end_io; freereq = get_request_wait(q, rw); @@ -2303,10 +2435,9 @@ get_rq: req->flags |= REQ_CMD; /* - * inherit FAILFAST from bio and don't stack up - * retries for read ahead + * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) */ - if (ra || test_bit(BIO_RW_FAILFAST, &bio->bi_rw)) + if (bio_rw_ahead(bio) || bio_failfast(bio)) req->flags |= REQ_FAILFAST; /* @@ -2321,11 +2452,9 @@ get_rq: req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; req->nr_phys_segments = bio_phys_segments(q, bio); req->nr_hw_segments = bio_hw_segments(q, bio); - req->nr_cbio_segments = bio_segments(bio); - req->nr_cbio_sectors = bio_sectors(bio); req->buffer = bio_data(bio); /* see ->buffer comment above */ req->waiting = NULL; - req->cbio = req->bio = req->biotail = bio; + req->bio = req->biotail = bio; req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; @@ -2340,7 +2469,7 @@ out: return 0; end_io: - bio_endio(bio, nr_sectors << 9, -EWOULDBLOCK); + bio_endio(bio, nr_sectors << 9, err); return 0; } @@ -2369,6 +2498,106 @@ static inline void blk_partition_remap(struct bio *bio) } } +void blk_finish_queue_drain(request_queue_t *q) +{ + struct request_list *rl = &q->rq; + struct request *rq; + + spin_lock_irq(q->queue_lock); + clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags); + + while (!list_empty(&q->drain_list)) { + rq = list_entry_rq(q->drain_list.next); + + list_del_init(&rq->queuelist); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); + } + + spin_unlock_irq(q->queue_lock); + + wake_up(&rl->wait[0]); + wake_up(&rl->wait[1]); + wake_up(&rl->drain); +} + +static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch) +{ + int wait = rl->count[READ] + rl->count[WRITE]; + + if (dispatch) + wait += !list_empty(&q->queue_head); + + return wait; +} + +/* + * We rely on the fact that only requests allocated through blk_alloc_request() + * have io scheduler private data structures associated with them. Any other + * type of request (allocated on stack or through kmalloc()) should not go + * to the io scheduler core, but be attached to the queue head instead. + */ +void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch) +{ + struct request_list *rl = &q->rq; + DEFINE_WAIT(wait); + + spin_lock_irq(q->queue_lock); + set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags); + + while (wait_drain(q, rl, wait_dispatch)) { + prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE); + + if (wait_drain(q, rl, wait_dispatch)) { + __generic_unplug_device(q); + spin_unlock_irq(q->queue_lock); + io_schedule(); + spin_lock_irq(q->queue_lock); + } + + finish_wait(&rl->drain, &wait); + } + + spin_unlock_irq(q->queue_lock); +} + +/* + * block waiting for the io scheduler being started again. + */ +static inline void block_wait_queue_running(request_queue_t *q) +{ + DEFINE_WAIT(wait); + + while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) { + struct request_list *rl = &q->rq; + + prepare_to_wait_exclusive(&rl->drain, &wait, + TASK_UNINTERRUPTIBLE); + + /* + * re-check the condition. avoids using prepare_to_wait() + * in the fast path (queue is running) + */ + if (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) + io_schedule(); + + finish_wait(&rl->drain, &wait); + } +} + +static void handle_bad_sector(struct bio *bio) +{ + char b[BDEVNAME_SIZE]; + + printk(KERN_INFO "attempt to access beyond end of device\n"); + printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n", + bdevname(bio->bi_bdev, b), + bio->bi_rw, + (unsigned long long)bio->bi_sector + bio_sectors(bio), + (long long)(bio->bi_bdev->bd_inode->i_size >> 9)); + + set_bit(BIO_EOF, &bio->bi_flags); +} + /** * generic_make_request: hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. @@ -2399,26 +2628,19 @@ void generic_make_request(struct bio *bio) sector_t maxsector; int ret, nr_sectors = bio_sectors(bio); + might_sleep(); /* Test device or partition size, when known. */ maxsector = bio->bi_bdev->bd_inode->i_size >> 9; if (maxsector) { sector_t sector = bio->bi_sector; - if (maxsector < nr_sectors || - maxsector - nr_sectors < sector) { - char b[BDEVNAME_SIZE]; - /* This may well happen - the kernel calls - * bread() without checking the size of the - * device, e.g., when mounting a device. */ - printk(KERN_INFO - "attempt to access beyond end of device\n"); - printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n", - bdevname(bio->bi_bdev, b), - bio->bi_rw, - (unsigned long long) sector + nr_sectors, - (long long) maxsector); - - set_bit(BIO_EOF, &bio->bi_flags); + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - the kernel calls bread() + * without checking the size of the device, e.g., when + * mounting a device. + */ + handle_bad_sector(bio); goto end_io; } } @@ -2446,17 +2668,19 @@ end_io: break; } - if (unlikely(bio_sectors(bio) > q->max_sectors)) { + if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) { printk("bio too big device %s (%u > %u)\n", bdevname(bio->bi_bdev, b), bio_sectors(bio), - q->max_sectors); + q->max_hw_sectors); goto end_io; } if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) goto end_io; + block_wait_queue_running(q); + /* * If this device has partitions, remap block n * of partition p to block n+start(p) of the disk. @@ -2505,103 +2729,40 @@ void submit_bio(int rw, struct bio *bio) EXPORT_SYMBOL(submit_bio); -/** - * blk_rq_next_segment - * @rq: the request being processed - * - * Description: - * Points to the next segment in the request if the current segment - * is complete. Leaves things unchanged if this segment is not over - * or if no more segments are left in this request. - * - * Meant to be used for bio traversal during I/O submission - * Does not affect any I/O completions or update completion state - * in the request, and does not modify any bio fields. - * - * Decrementing rq->nr_sectors, rq->current_nr_sectors and - * rq->nr_cbio_sectors as data is transferred is the caller's - * responsibility and should be done before calling this routine. - **/ -void blk_rq_next_segment(struct request *rq) -{ - if (rq->current_nr_sectors > 0) - return; - - if (rq->nr_cbio_sectors > 0) { - --rq->nr_cbio_segments; - rq->current_nr_sectors = blk_rq_vec(rq)->bv_len >> 9; - } else { - if ((rq->cbio = rq->cbio->bi_next)) { - rq->nr_cbio_segments = bio_segments(rq->cbio); - rq->nr_cbio_sectors = bio_sectors(rq->cbio); - rq->current_nr_sectors = bio_cur_sectors(rq->cbio); - } - } - - /* remember the size of this segment before we start I/O */ - rq->hard_cur_sectors = rq->current_nr_sectors; -} - -/** - * process_that_request_first - process partial request submission - * @req: the request being processed - * @nr_sectors: number of sectors I/O has been submitted on - * - * Description: - * May be used for processing bio's while submitting I/O without - * signalling completion. Fails if more data is requested than is - * available in the request in which case it doesn't advance any - * pointers. - * - * Assumes a request is correctly set up. No sanity checks. - * - * Return: - * 0 - no more data left to submit (not processed) - * 1 - data available to submit for this request (processed) - **/ -int process_that_request_first(struct request *req, unsigned int nr_sectors) -{ - unsigned int nsect; - - if (req->nr_sectors < nr_sectors) - return 0; - - req->nr_sectors -= nr_sectors; - req->sector += nr_sectors; - while (nr_sectors) { - nsect = min_t(unsigned, req->current_nr_sectors, nr_sectors); - req->current_nr_sectors -= nsect; - nr_sectors -= nsect; - if (req->cbio) { - req->nr_cbio_sectors -= nsect; - blk_rq_next_segment(req); - } - } - return 1; -} - -EXPORT_SYMBOL(process_that_request_first); - void blk_recalc_rq_segments(struct request *rq) { struct bio *bio, *prevbio = NULL; int nr_phys_segs, nr_hw_segs; + unsigned int phys_size, hw_size; + request_queue_t *q = rq->q; if (!rq->bio) return; - nr_phys_segs = nr_hw_segs = 0; + phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; rq_for_each_bio(bio, rq) { /* Force bio hw/phys segs to be recalculated. */ bio->bi_flags &= ~(1 << BIO_SEG_VALID); - nr_phys_segs += bio_phys_segments(rq->q, bio); - nr_hw_segs += bio_hw_segments(rq->q, bio); + nr_phys_segs += bio_phys_segments(q, bio); + nr_hw_segs += bio_hw_segments(q, bio); if (prevbio) { - if (blk_phys_contig_segment(rq->q, prevbio, bio)) + int pseg = phys_size + prevbio->bi_size + bio->bi_size; + int hseg = hw_size + prevbio->bi_size + bio->bi_size; + + if (blk_phys_contig_segment(q, prevbio, bio) && + pseg <= q->max_segment_size) { nr_phys_segs--; - if (blk_hw_contig_segment(rq->q, prevbio, bio)) + phys_size += prevbio->bi_size + bio->bi_size; + } else + phys_size = 0; + + if (blk_hw_contig_segment(q, prevbio, bio) && + hseg <= q->max_segment_size) { nr_hw_segs--; + hw_size += prevbio->bi_size + bio->bi_size; + } else + hw_size = 0; } prevbio = bio; } @@ -2617,8 +2778,7 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) rq->hard_nr_sectors -= nsect; /* - * Move the I/O submission pointers ahead if required, - * i.e. for drivers not aware of rq->cbio. + * Move the I/O submission pointers ahead if required. */ if ((rq->nr_sectors >= rq->hard_nr_sectors) && (rq->sector <= rq->hard_sector)) { @@ -2626,11 +2786,7 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) rq->nr_sectors = rq->hard_nr_sectors; rq->hard_cur_sectors = bio_cur_sectors(rq->bio); rq->current_nr_sectors = rq->hard_cur_sectors; - rq->nr_cbio_segments = bio_segments(rq->bio); - rq->nr_cbio_sectors = bio_sectors(rq->bio); rq->buffer = bio_data(rq->bio); - - rq->cbio = rq->bio; } /* @@ -2647,9 +2803,16 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) static int __end_that_request_first(struct request *req, int uptodate, int nr_bytes) { - int total_bytes, bio_nbytes, error = 0, next_idx = 0; + int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; + /* + * extend uptodate bool to allow < 0 value to be direct io error + */ + error = 0; + if (end_io_error(uptodate)) + error = !uptodate ? -EIO : uptodate; + /* * for a REQ_BLOCK_PC request, we want to carry any eventual * sense key with us all the way through @@ -2658,7 +2821,6 @@ static int __end_that_request_first(struct request *req, int uptodate, req->errors = 0; if (!uptodate) { - error = -EIO; if (blk_fs_request(req) && !(req->flags & REQ_QUIET)) printk("end_request: I/O error, dev %s, sector %llu\n", req->rq_disk ? req->rq_disk->disk_name : "?", @@ -2741,7 +2903,7 @@ static int __end_that_request_first(struct request *req, int uptodate, /** * end_that_request_first - end I/O on a request * @req: the request being processed - * @uptodate: 0 for I/O error + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error * @nr_sectors: number of sectors to end I/O on * * Description: @@ -2762,7 +2924,7 @@ EXPORT_SYMBOL(end_that_request_first); /** * end_that_request_chunk - end I/O on a request * @req: the request being processed - * @uptodate: 0 for I/O error + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error * @nr_bytes: number of bytes to complete * * Description: @@ -2796,12 +2958,12 @@ void end_that_request_last(struct request *req) unsigned long duration = jiffies - req->start_time; switch (rq_data_dir(req)) { case WRITE: - disk_stat_inc(disk, writes); - disk_stat_add(disk, write_ticks, duration); + __disk_stat_inc(disk, writes); + __disk_stat_add(disk, write_ticks, duration); break; case READ: - disk_stat_inc(disk, reads); - disk_stat_add(disk, read_ticks, duration); + __disk_stat_inc(disk, reads); + __disk_stat_add(disk, read_ticks, duration); break; } disk_round_stats(disk); @@ -2836,33 +2998,13 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); - rq->nr_cbio_segments = bio_segments(bio); - rq->nr_cbio_sectors = bio_sectors(bio); rq->buffer = bio_data(bio); - rq->cbio = rq->bio = rq->biotail = bio; + rq->bio = rq->biotail = bio; } EXPORT_SYMBOL(blk_rq_bio_prep); -void blk_rq_prep_restart(struct request *rq) -{ - struct bio *bio; - - bio = rq->cbio = rq->bio; - if (bio) { - rq->nr_cbio_segments = bio_segments(bio); - rq->nr_cbio_sectors = bio_sectors(bio); - rq->hard_cur_sectors = bio_cur_sectors(bio); - rq->buffer = bio_data(bio); - } - rq->sector = rq->hard_sector; - rq->nr_sectors = rq->hard_nr_sectors; - rq->current_nr_sectors = rq->hard_cur_sectors; -} - -EXPORT_SYMBOL(blk_rq_prep_restart); - int kblockd_schedule_work(struct work_struct *work) { return queue_work(kblockd_workqueue, work); @@ -2874,6 +3016,7 @@ void kblockd_flush(void) { flush_workqueue(kblockd_workqueue); } +EXPORT_SYMBOL(kblockd_flush); int __init blk_dev_init(void) { @@ -2892,6 +3035,7 @@ int __init blk_dev_init(void) blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; + return 0; } @@ -2908,9 +3052,13 @@ void put_io_context(struct io_context *ioc) if (atomic_dec_and_test(&ioc->refcount)) { if (ioc->aic && ioc->aic->dtor) ioc->aic->dtor(ioc->aic); + if (ioc->cic && ioc->cic->dtor) + ioc->cic->dtor(ioc->cic); + kmem_cache_free(iocontext_cachep, ioc); } } +EXPORT_SYMBOL(put_io_context); /* Called by the exitting task */ void exit_io_context(void) @@ -2920,14 +3068,15 @@ void exit_io_context(void) local_irq_save(flags); ioc = current->io_context; - if (ioc) { - if (ioc->aic && ioc->aic->exit) - ioc->aic->exit(ioc->aic); - put_io_context(ioc); - current->io_context = NULL; - } else - WARN_ON(1); + current->io_context = NULL; local_irq_restore(flags); + + if (ioc->aic && ioc->aic->exit) + ioc->aic->exit(ioc->aic); + if (ioc->cic && ioc->cic->exit) + ioc->cic->exit(ioc->cic); + + put_io_context(ioc); } /* @@ -2946,22 +3095,42 @@ struct io_context *get_io_context(int gfp_flags) local_irq_save(flags); ret = tsk->io_context; - if (ret == NULL) { - ret = kmem_cache_alloc(iocontext_cachep, GFP_ATOMIC); - if (ret) { - atomic_set(&ret->refcount, 1); - ret->pid = tsk->pid; - ret->last_waited = jiffies; /* doesn't matter... */ - ret->nr_batch_requests = 0; /* because this is 0 */ - ret->aic = NULL; + if (ret) + goto out; + + local_irq_restore(flags); + + ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); + if (ret) { + atomic_set(&ret->refcount, 1); + ret->pid = tsk->pid; + ret->last_waited = jiffies; /* doesn't matter... */ + ret->nr_batch_requests = 0; /* because this is 0 */ + ret->aic = NULL; + ret->cic = NULL; + spin_lock_init(&ret->lock); + + local_irq_save(flags); + + /* + * very unlikely, someone raced with us in setting up the task + * io context. free new context and just grab a reference. + */ + if (!tsk->io_context) tsk->io_context = ret; + else { + kmem_cache_free(iocontext_cachep, ret); + ret = tsk->io_context; } - } - if (ret) + +out: atomic_inc(&ret->refcount); - local_irq_restore(flags); + local_irq_restore(flags); + } + return ret; } +EXPORT_SYMBOL(get_io_context); void copy_io_context(struct io_context **pdst, struct io_context **psrc) { @@ -2975,6 +3144,7 @@ void copy_io_context(struct io_context **pdst, struct io_context **psrc) *pdst = src; } } +EXPORT_SYMBOL(copy_io_context); void swap_io_context(struct io_context **ioc1, struct io_context **ioc2) { @@ -2983,7 +3153,7 @@ void swap_io_context(struct io_context **ioc1, struct io_context **ioc2) *ioc1 = *ioc2; *ioc2 = temp; } - +EXPORT_SYMBOL(swap_io_context); /* * sysfs parts below @@ -3063,13 +3233,61 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count) unsigned long ra_kb; ssize_t ret = queue_var_store(&ra_kb, page, count); + spin_lock_irq(q->queue_lock); if (ra_kb > (q->max_sectors >> 1)) ra_kb = (q->max_sectors >> 1); q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); + spin_unlock_irq(q->queue_lock); + + return ret; +} + +static ssize_t queue_max_sectors_show(struct request_queue *q, char *page) +{ + int max_sectors_kb = q->max_sectors >> 1; + + return queue_var_show(max_sectors_kb, (page)); +} + +static ssize_t +queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) +{ + unsigned long max_sectors_kb, + max_hw_sectors_kb = q->max_hw_sectors >> 1, + page_kb = 1 << (PAGE_CACHE_SHIFT - 10); + ssize_t ret = queue_var_store(&max_sectors_kb, page, count); + int ra_kb; + + if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb) + return -EINVAL; + /* + * Take the queue lock to update the readahead and max_sectors + * values synchronously: + */ + spin_lock_irq(q->queue_lock); + /* + * Trim readahead window as well, if necessary: + */ + ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); + if (ra_kb > max_sectors_kb) + q->backing_dev_info.ra_pages = + max_sectors_kb >> (PAGE_CACHE_SHIFT - 10); + + q->max_sectors = max_sectors_kb << 1; + spin_unlock_irq(q->queue_lock); + return ret; } +static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) +{ + int max_hw_sectors_kb = q->max_hw_sectors >> 1; + + return queue_var_show(max_hw_sectors_kb, (page)); +} + + static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, .show = queue_requests_show, @@ -3082,9 +3300,29 @@ static struct queue_sysfs_entry queue_ra_entry = { .store = queue_ra_store, }; +static struct queue_sysfs_entry queue_max_sectors_entry = { + .attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR }, + .show = queue_max_sectors_show, + .store = queue_max_sectors_store, +}; + +static struct queue_sysfs_entry queue_max_hw_sectors_entry = { + .attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO }, + .show = queue_max_hw_sectors_show, +}; + +static struct queue_sysfs_entry queue_iosched_entry = { + .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, + .show = elv_iosched_show, + .store = elv_iosched_store, +}; + static struct attribute *default_attrs[] = { &queue_requests_entry.attr, &queue_ra_entry.attr, + &queue_max_hw_sectors_entry.attr, + &queue_max_sectors_entry.attr, + &queue_iosched_entry.attr, NULL, }; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 946742912..9e1b08b73 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -47,7 +47,7 @@ #include #include - +#include #include #include #include @@ -1073,7 +1073,7 @@ static struct block_device_operations lo_fops = { /* * And now the modules code and kernel interface. */ -MODULE_PARM(max_loop, "i"); +module_param(max_loop, int, 0); MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index b98b70b8f..75ad39dc6 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -128,23 +128,11 @@ static void nbd_end_request(struct request *req) { int uptodate = (req->errors == 0) ? 1 : 0; request_queue_t *q = req->q; - struct nbd_device *lo = req->rq_disk->private_data; unsigned long flags; dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name, req, uptodate? "done": "failed"); - spin_lock(&lo->queue_lock); - while (req->ref_count > 1) { /* still in send */ - spin_unlock(&lo->queue_lock); - printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n", - lo->disk->disk_name, req, req->ref_count); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); /* wait a second */ - spin_lock(&lo->queue_lock); - } - spin_unlock(&lo->queue_lock); - spin_lock_irqsave(q->queue_lock, flags); if (!end_that_request_first(req, uptodate, req->nr_sectors)) { end_that_request_last(req); @@ -228,7 +216,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, return result; } -void nbd_send_req(struct nbd_device *lo, struct request *req) +static int nbd_send_req(struct nbd_device *lo, struct request *req) { int result, i, flags; struct nbd_request request; @@ -288,11 +276,11 @@ void nbd_send_req(struct nbd_device *lo, struct request *req) } } up(&lo->tx_lock); - return; + return 0; error_out: up(&lo->tx_lock); - req->errors++; + return 1; } static struct request *nbd_find_request(struct nbd_device *lo, char *handle) @@ -477,26 +465,19 @@ static void do_nbd_request(request_queue_t * q) } list_add(&req->queuelist, &lo->queue_head); - req->ref_count++; /* make sure req does not get freed */ spin_unlock(&lo->queue_lock); - nbd_send_req(lo, req); - - if (req->errors) { + if (nbd_send_req(lo, req) != 0) { printk(KERN_ERR "%s: Request send failed\n", lo->disk->disk_name); - spin_lock(&lo->queue_lock); - list_del_init(&req->queuelist); - req->ref_count--; - spin_unlock(&lo->queue_lock); - nbd_end_request(req); - spin_lock_irq(q->queue_lock); - continue; + if (nbd_find_request(lo, (char *)&req) != NULL) { + /* we still own req */ + req->errors++; + nbd_end_request(req); + } else /* we're racing with nbd_clear_que */ + printk(KERN_DEBUG "nbd: can't find req\n"); } - spin_lock(&lo->queue_lock); - req->ref_count--; - spin_unlock(&lo->queue_lock); spin_lock_irq(q->queue_lock); continue; diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c index ffef40be1..707dddd7d 100644 --- a/drivers/block/noop-iosched.c +++ b/drivers/block/noop-iosched.c @@ -83,12 +83,31 @@ struct request *elevator_noop_next_request(request_queue_t *q) return NULL; } -elevator_t elevator_noop = { - .elevator_merge_fn = elevator_noop_merge, - .elevator_merge_req_fn = elevator_noop_merge_requests, - .elevator_next_req_fn = elevator_noop_next_request, - .elevator_add_req_fn = elevator_noop_add_request, - .elevator_name = "noop", +static struct elevator_type elevator_noop = { + .ops = { + .elevator_merge_fn = elevator_noop_merge, + .elevator_merge_req_fn = elevator_noop_merge_requests, + .elevator_next_req_fn = elevator_noop_next_request, + .elevator_add_req_fn = elevator_noop_add_request, + }, + .elevator_name = "noop", + .elevator_owner = THIS_MODULE, }; -EXPORT_SYMBOL(elevator_noop); +int noop_init(void) +{ + return elv_register(&elevator_noop); +} + +void noop_exit(void) +{ + elv_unregister(&elevator_noop); +} + +module_init(noop_init); +module_exit(noop_exit); + + +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("No-op IO scheduler"); diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c index 9f9401c1a..8d29459a1 100644 --- a/drivers/block/paride/paride.c +++ b/drivers/block/paride/paride.c @@ -140,7 +140,7 @@ static void pi_claim(PIA * pi) #endif } -void pi_unclaim(PIA * pi) +static void pi_unclaim(PIA * pi) { pi->claimed = 0; #ifdef CONFIG_PARPORT @@ -149,8 +149,6 @@ void pi_unclaim(PIA * pi) #endif } -EXPORT_SYMBOL(pi_unclaim); - void pi_connect(PIA * pi) { pi_claim(pi); diff --git a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h index e8e2a934b..c6d98ef09 100644 --- a/drivers/block/paride/paride.h +++ b/drivers/block/paride/paride.h @@ -88,8 +88,6 @@ extern void pi_write_block(PIA *pi, char * buf, int count); extern void pi_read_block(PIA *pi, char * buf, int count); -extern void pi_unclaim(PIA *pi); - extern void pi_connect(PIA *pi); extern void pi_disconnect(PIA *pi); diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index d73e3ec9f..8f28ff71a 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -262,7 +262,7 @@ static void pg_init_units(void) int *parm = *drives[unit]; struct pg *dev = &devices[unit]; dev->pi = &dev->pia; - set_bit(0, &dev->access); + clear_bit(0, &dev->access); dev->busy = 0; dev->present = 0; dev->bufptr = NULL; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index fe8332e34..80848c2a7 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -60,15 +61,12 @@ #include -/* The RAM disk size is now a parameter */ -#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ - /* Various static variables go here. Most are used only in the RAM disk code. */ -static struct gendisk *rd_disks[NUM_RAMDISKS]; -static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ -static struct request_queue *rd_queue[NUM_RAMDISKS]; +static struct gendisk *rd_disks[CONFIG_BLK_DEV_RAM_COUNT]; +static struct block_device *rd_bdev[CONFIG_BLK_DEV_RAM_COUNT];/* Protected device data */ +static struct request_queue *rd_queue[CONFIG_BLK_DEV_RAM_COUNT]; /* * Parameters for the boot-loading of the RAM disk. These are set by @@ -349,13 +347,17 @@ static int rd_open(struct inode *inode, struct file *filp) if (rd_bdev[unit] == NULL) { struct block_device *bdev = inode->i_bdev; struct address_space *mapping; + unsigned bsize; int gfp_mask; inode = igrab(bdev->bd_inode); rd_bdev[unit] = bdev; bdev->bd_openers++; - bdev->bd_block_size = rd_blocksize; - inode->i_size = get_capacity(rd_disks[unit])<<9; + bsize = bdev_hardsect_size(bdev); + bdev->bd_block_size = bsize; + inode->i_blkbits = blksize_bits(bsize); + inode->i_size = get_capacity(bdev->bd_disk)<<9; + mapping = inode->i_mapping; mapping->a_ops = &ramdisk_aops; mapping->backing_dev_info = &rd_backing_dev_info; @@ -398,7 +400,7 @@ static void __exit rd_cleanup(void) { int i; - for (i = 0; i < NUM_RAMDISKS; i++) { + for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) { struct block_device *bdev = rd_bdev[i]; rd_bdev[i] = NULL; if (bdev) { @@ -428,7 +430,7 @@ static int __init rd_init(void) rd_blocksize = BLOCK_SIZE; } - for (i = 0; i < NUM_RAMDISKS; i++) { + for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) { rd_disks[i] = alloc_disk(1); if (!rd_disks[i]) goto out; @@ -441,7 +443,7 @@ static int __init rd_init(void) devfs_mk_dir("rd"); - for (i = 0; i < NUM_RAMDISKS; i++) { + for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) { struct gendisk *disk = rd_disks[i]; rd_queue[i] = blk_alloc_queue(GFP_KERNEL); @@ -449,6 +451,7 @@ static int __init rd_init(void) goto out_queue; blk_queue_make_request(rd_queue[i], &rd_make_request); + blk_queue_hardsect_size(rd_queue[i], rd_blocksize); /* rd_size is given in kB */ disk->major = RAMDISK_MAJOR; @@ -465,7 +468,7 @@ static int __init rd_init(void) /* rd_size is given in kB */ printk("RAMDISK driver initialized: " "%d RAM disks of %dK size %d blocksize\n", - NUM_RAMDISKS, rd_size, rd_blocksize); + CONFIG_BLK_DEV_RAM_COUNT, rd_size, rd_blocksize); return 0; out_queue: @@ -503,9 +506,10 @@ __setup("ramdisk_blocksize=", ramdisk_blocksize); #endif /* options - modular */ -MODULE_PARM (rd_size, "1i"); +module_param(rd_size, int, 0); MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes."); -MODULE_PARM (rd_blocksize, "i"); +module_param(rd_blocksize, int, 0); MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes."); +MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR); MODULE_LICENSE("GPL"); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 41d023931..73d323b73 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -107,12 +107,13 @@ static int sg_emulated_host(request_queue_t *q, int __user *p) #define CMD_READ_SAFE 0x01 #define CMD_WRITE_SAFE 0x02 +#define CMD_WARNED 0x04 #define safe_for_read(cmd) [cmd] = CMD_READ_SAFE #define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE static int verify_command(struct file *file, unsigned char *cmd) { - static const unsigned char cmd_type[256] = { + static unsigned char cmd_type[256] = { /* Basic read-only commands */ safe_for_read(TEST_UNIT_READY), @@ -126,15 +127,20 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_read(INQUIRY), safe_for_read(MODE_SENSE), safe_for_read(MODE_SENSE_10), + safe_for_read(LOG_SENSE), safe_for_read(START_STOP), + safe_for_read(GPCMD_VERIFY_10), + safe_for_read(VERIFY_16), /* Audio CD commands */ safe_for_read(GPCMD_PLAY_CD), safe_for_read(GPCMD_PLAY_AUDIO_10), safe_for_read(GPCMD_PLAY_AUDIO_MSF), safe_for_read(GPCMD_PLAY_AUDIO_TI), + safe_for_read(GPCMD_PAUSE_RESUME), /* CD/DVD data reading */ + safe_for_read(GPCMD_READ_BUFFER_CAPACITY), safe_for_read(GPCMD_READ_CD), safe_for_read(GPCMD_READ_CD_MSF), safe_for_read(GPCMD_READ_DISC_INFO), @@ -146,6 +152,12 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_read(GPCMD_READ_TOC_PMA_ATIP), safe_for_read(GPCMD_REPORT_KEY), safe_for_read(GPCMD_SCAN), + safe_for_read(GPCMD_GET_CONFIGURATION), + safe_for_read(GPCMD_READ_FORMAT_CAPACITIES), + safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION), + safe_for_read(GPCMD_GET_PERFORMANCE), + safe_for_read(GPCMD_SEEK), + safe_for_read(GPCMD_STOP_PLAY_SCAN), /* Basic writing commands */ safe_for_write(WRITE_6), @@ -154,8 +166,26 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_write(WRITE_12), safe_for_write(WRITE_VERIFY_12), safe_for_write(WRITE_16), - safe_for_write(WRITE_BUFFER), safe_for_write(WRITE_LONG), + safe_for_write(ERASE), + safe_for_write(GPCMD_MODE_SELECT_10), + safe_for_write(MODE_SELECT), + safe_for_write(LOG_SELECT), + safe_for_write(GPCMD_BLANK), + safe_for_write(GPCMD_CLOSE_TRACK), + safe_for_write(GPCMD_FLUSH_CACHE), + safe_for_write(GPCMD_FORMAT_UNIT), + safe_for_write(GPCMD_REPAIR_RZONE_TRACK), + safe_for_write(GPCMD_RESERVE_RZONE_TRACK), + safe_for_write(GPCMD_SEND_DVD_STRUCTURE), + safe_for_write(GPCMD_SEND_EVENT), + safe_for_write(GPCMD_SEND_KEY), + safe_for_write(GPCMD_SEND_OPC), + safe_for_write(GPCMD_SEND_CUE_SHEET), + safe_for_write(GPCMD_SET_SPEED), + safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL), + safe_for_write(GPCMD_LOAD_UNLOAD), + safe_for_write(GPCMD_SET_STREAMING), }; unsigned char type = cmd_type[cmd[0]]; @@ -169,6 +199,11 @@ static int verify_command(struct file *file, unsigned char *cmd) return 0; } + if (!(type & CMD_WARNED)) { + cmd_type[cmd[0]] = CMD_WARNED; + printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]); + } + /* And root can do any command.. */ if (capable(CAP_SYS_RAWIO)) return 0; @@ -266,11 +301,11 @@ static int sg_io(struct file *file, request_queue_t *q, blk_execute_rq(q, bd_disk, rq); /* write to all output members */ - hdr->status = rq->errors; - hdr->masked_status = (hdr->status >> 1) & 0x1f; - hdr->msg_status = 0; - hdr->host_status = 0; - hdr->driver_status = 0; + hdr->status = 0xff & rq->errors; + hdr->masked_status = status_byte(rq->errors); + hdr->msg_status = msg_byte(rq->errors); + hdr->host_status = host_byte(rq->errors); + hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; @@ -511,6 +546,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, * old junk scsi send command ioctl */ case SCSI_IOCTL_SEND_COMMAND: + printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); err = -EINVAL; if (!arg) break; diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index ca17d8373..375bf7243 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -176,8 +176,8 @@ struct swim3 { struct floppy_state { enum swim_state state; - volatile struct swim3 *swim3; /* hardware registers */ - struct dbdma_regs *dma; /* DMA controller registers */ + struct swim3 __iomem *swim3; /* hardware registers */ + struct dbdma_regs __iomem *dma; /* DMA controller registers */ int swim3_intr; /* interrupt number for SWIM3 */ int dma_intr; /* interrupt number for DMA channel */ int cur_cyl; /* cylinder head is on, or -1 */ @@ -259,7 +259,7 @@ int swim3_init(void); static void swim3_select(struct floppy_state *fs, int sel) { - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; out_8(&sw->select, RELAX); if (sel & 8) @@ -271,7 +271,7 @@ static void swim3_select(struct floppy_state *fs, int sel) static void swim3_action(struct floppy_state *fs, int action) { - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; swim3_select(fs, action); udelay(1); @@ -283,7 +283,7 @@ static void swim3_action(struct floppy_state *fs, int action) static int swim3_readbit(struct floppy_state *fs, int bit) { - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; int stat; swim3_select(fs, bit); @@ -381,7 +381,7 @@ static void set_timeout(struct floppy_state *fs, int nticks, static inline void scan_track(struct floppy_state *fs) { - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; swim3_select(fs, READ_DATA_0); in_8(&sw->intr); /* clear SEEN_SECTOR bit */ @@ -394,7 +394,7 @@ static inline void scan_track(struct floppy_state *fs) static inline void seek_track(struct floppy_state *fs, int n) { - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; if (n >= 0) { swim3_action(fs, SEEK_POSITIVE); @@ -425,9 +425,9 @@ static inline void init_dma(struct dbdma_cmd *cp, int cmd, static inline void setup_transfer(struct floppy_state *fs) { int n; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; struct dbdma_cmd *cp = fs->dma_cmd; - struct dbdma_regs *dr = fs->dma; + struct dbdma_regs __iomem *dr = fs->dma; if (fd_req->current_nr_sectors <= 0) { printk(KERN_ERR "swim3: transfer 0 sectors?\n"); @@ -445,7 +445,7 @@ static inline void setup_transfer(struct floppy_state *fs) out_8(&sw->sector, fs->req_sector); out_8(&sw->nsect, n); out_8(&sw->gap3, 0); - st_le32(&dr->cmdptr, virt_to_bus(cp)); + out_le32(&dr->cmdptr, virt_to_bus(cp)); if (rq_data_dir(fd_req) == WRITE) { /* Set up 3 dma commands: write preamble, data, postamble */ init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); @@ -537,7 +537,7 @@ static void act(struct floppy_state *fs) static void scan_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; fs->timeout_pending = 0; out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); @@ -557,7 +557,7 @@ static void scan_timeout(unsigned long data) static void seek_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; fs->timeout_pending = 0; out_8(&sw->control_bic, DO_SEEK); @@ -572,7 +572,7 @@ static void seek_timeout(unsigned long data) static void settle_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; fs->timeout_pending = 0; if (swim3_readbit(fs, SEEK_COMPLETE)) { @@ -596,14 +596,14 @@ static void settle_timeout(unsigned long data) static void xfer_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; - volatile struct swim3 *sw = fs->swim3; - struct dbdma_regs *dr = fs->dma; + struct swim3 __iomem *sw = fs->swim3; + struct dbdma_regs __iomem *dr = fs->dma; struct dbdma_cmd *cp = fs->dma_cmd; unsigned long s; int n; fs->timeout_pending = 0; - st_le32(&dr->control, RUN << 16); + out_le32(&dr->control, RUN << 16); /* We must wait a bit for dbdma to stop */ for (n = 0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++) udelay(1); @@ -628,10 +628,10 @@ static void xfer_timeout(unsigned long data) static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct floppy_state *fs = (struct floppy_state *) dev_id; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; int intr, err, n; int stat, resid; - struct dbdma_regs *dr; + struct dbdma_regs __iomem *dr; struct dbdma_cmd *cp; intr = in_8(&sw->intr); @@ -866,7 +866,7 @@ static int floppy_ioctl(struct inode *inode, struct file *filp, err = fd_eject(fs); return err; case FDGETPRM: - if (copy_to_user((void *) param, (void *)&floppy_type, + if (copy_to_user((void __user *) param, &floppy_type, sizeof(struct floppy_struct))) return -EFAULT; return 0; @@ -877,7 +877,7 @@ static int floppy_ioctl(struct inode *inode, struct file *filp, static int floppy_open(struct inode *inode, struct file *filp) { struct floppy_state *fs = inode->i_bdev->bd_disk->private_data; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; int n, err = 0; if (fs->ref_count == 0) { @@ -946,7 +946,7 @@ static int floppy_open(struct inode *inode, struct file *filp) static int floppy_release(struct inode *inode, struct file *filp) { struct floppy_state *fs = inode->i_bdev->bd_disk->private_data; - volatile struct swim3 *sw = fs->swim3; + struct swim3 __iomem *sw = fs->swim3; if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, 0xff); @@ -964,7 +964,7 @@ static int floppy_check_change(struct gendisk *disk) static int floppy_revalidate(struct gendisk *disk) { struct floppy_state *fs = disk->private_data; - volatile struct swim3 *sw; + struct swim3 __iomem *sw; int ret, n; if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) @@ -1105,8 +1105,10 @@ static int swim3_add_device(struct device_node *swim) memset(fs, 0, sizeof(*fs)); fs->state = idle; - fs->swim3 = (volatile struct swim3 *) ioremap(swim->addrs[0].address, 0x200); - fs->dma = (struct dbdma_regs *) ioremap(swim->addrs[1].address, 0x200); + fs->swim3 = (struct swim3 __iomem *) + ioremap(swim->addrs[0].address, 0x200); + fs->dma = (struct dbdma_regs __iomem *) + ioremap(swim->addrs[1].address, 0x200); fs->swim3_intr = swim->intrs[0].line; fs->dma_intr = swim->intrs[1].line; fs->cur_cyl = -1; diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 0a0234129..02a541ae7 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -242,7 +242,7 @@ struct carm_request { struct carm_host { unsigned long flags; - void *mmio; + void __iomem *mmio; void *shm; dma_addr_t shm_dma; @@ -283,13 +283,13 @@ struct carm_host { }; struct carm_response { - u32 ret_handle; - u32 status; + __le32 ret_handle; + __le32 status; } __attribute__((packed)); struct carm_msg_sg { - u32 start; - u32 len; + __le32 start; + __le32 len; } __attribute__((packed)); struct carm_msg_rw { @@ -297,10 +297,10 @@ struct carm_msg_rw { u8 id; u8 sg_count; u8 sg_type; - u32 handle; - u32 lba; - u16 lba_count; - u16 lba_high; + __le32 handle; + __le32 lba; + __le16 lba_count; + __le16 lba_high; struct carm_msg_sg sg[32]; } __attribute__((packed)); @@ -309,15 +309,15 @@ struct carm_msg_allocbuf { u8 subtype; u8 n_sg; u8 sg_type; - u32 handle; - u32 addr; - u32 len; - u32 evt_pool; - u32 n_evt; - u32 rbuf_pool; - u32 n_rbuf; - u32 msg_pool; - u32 n_msg; + __le32 handle; + __le32 addr; + __le32 len; + __le32 evt_pool; + __le32 n_evt; + __le32 rbuf_pool; + __le32 n_rbuf; + __le32 msg_pool; + __le32 n_msg; struct carm_msg_sg sg[8]; } __attribute__((packed)); @@ -326,8 +326,8 @@ struct carm_msg_ioctl { u8 subtype; u8 array_id; u8 reserved1; - u32 handle; - u32 data_addr; + __le32 handle; + __le32 data_addr; u32 reserved2; } __attribute__((packed)); @@ -335,48 +335,48 @@ struct carm_msg_sync_time { u8 type; u8 subtype; u16 reserved1; - u32 handle; + __le32 handle; u32 reserved2; - u32 timestamp; + __le32 timestamp; } __attribute__((packed)); struct carm_msg_get_fw_ver { u8 type; u8 subtype; u16 reserved1; - u32 handle; - u32 data_addr; + __le32 handle; + __le32 data_addr; u32 reserved2; } __attribute__((packed)); struct carm_fw_ver { - u32 version; + __le32 version; u8 features; u8 reserved1; u16 reserved2; } __attribute__((packed)); struct carm_array_info { - u32 size; + __le32 size; - u16 size_hi; - u16 stripe_size; + __le16 size_hi; + __le16 stripe_size; - u32 mode; + __le32 mode; - u16 stripe_blk_sz; - u16 reserved1; + __le16 stripe_blk_sz; + __le16 reserved1; - u16 cyl; - u16 head; + __le16 cyl; + __le16 head; - u16 sect; + __le16 sect; u8 array_id; u8 reserved2; char name[40]; - u32 array_status; + __le32 array_status; /* device list continues beyond this point? */ } __attribute__((packed)); @@ -451,7 +451,7 @@ static inline int carm_lookup_bucket(u32 msg_size) return -ENOENT; } -static void carm_init_buckets(void *mmio) +static void carm_init_buckets(void __iomem *mmio) { unsigned int i; @@ -474,7 +474,7 @@ static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host, static int carm_send_msg(struct carm_host *host, struct carm_request *crq) { - void *mmio = host->mmio; + void __iomem *mmio = host->mmio; u32 msg = (u32) carm_ref_msg_dma(host, crq->tag); u32 cm_bucket = crq->msg_bucket; u32 tmp; @@ -965,7 +965,7 @@ static void carm_handle_array_info(struct carm_host *host, port = &host->port[cur_port]; lo = (u64) le32_to_cpu(desc->size); - hi = (u64) le32_to_cpu(desc->size_hi); + hi = (u64) le16_to_cpu(desc->size_hi); port->capacity = lo | (hi << 32); port->dev_geom_head = le16_to_cpu(desc->head); @@ -1060,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host, } static inline void carm_handle_resp(struct carm_host *host, - u32 ret_handle_le, u32 status) + __le32 ret_handle_le, u32 status) { u32 handle = le32_to_cpu(ret_handle_le); unsigned int msg_idx; @@ -1158,7 +1158,7 @@ err_out: static inline void carm_handle_responses(struct carm_host *host) { - void *mmio = host->mmio; + void __iomem *mmio = host->mmio; struct carm_response *resp = (struct carm_response *) host->shm; unsigned int work = 0; unsigned int idx = host->resp_idx % RMSG_Q_LEN; @@ -1176,7 +1176,7 @@ static inline void carm_handle_responses(struct carm_host *host) else if ((status & (1 << 31)) == 0) { VPRINTK("handling msg response on index %u\n", idx); carm_handle_resp(host, resp[idx].ret_handle, status); - resp[idx].status = 0xffffffff; + resp[idx].status = cpu_to_le32(0xffffffff); } /* asynchronous events the hardware throws our way */ @@ -1185,7 +1185,7 @@ static inline void carm_handle_responses(struct carm_host *host) u8 evt_type = *evt_type_ptr; printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n", pci_name(host->pdev), (int) evt_type); - resp[idx].status = 0xffffffff; + resp[idx].status = cpu_to_le32(0xffffffff); } idx = NEXT_RESP(idx); @@ -1199,7 +1199,7 @@ static inline void carm_handle_responses(struct carm_host *host) static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs) { struct carm_host *host = __host; - void *mmio; + void __iomem *mmio; u32 mask; int handled = 0; unsigned long flags; @@ -1364,7 +1364,7 @@ static void carm_fsm_task (void *_data) schedule_work(&host->fsm_task); } -static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit) +static int carm_init_wait(void __iomem *mmio, u32 bits, unsigned int test_bit) { unsigned int i; @@ -1390,19 +1390,19 @@ static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit) static void carm_init_responses(struct carm_host *host) { - void *mmio = host->mmio; + void __iomem *mmio = host->mmio; unsigned int i; struct carm_response *resp = (struct carm_response *) host->shm; for (i = 0; i < RMSG_Q_LEN; i++) - resp[i].status = 0xffffffff; + resp[i].status = cpu_to_le32(0xffffffff); writel(0, mmio + CARM_RESP_IDX); } static int carm_init_host(struct carm_host *host) { - void *mmio = host->mmio; + void __iomem *mmio = host->mmio; u32 tmp; u8 tmp8; int rc; @@ -1414,7 +1414,7 @@ static int carm_init_host(struct carm_host *host) tmp8 = readb(mmio + CARM_INITC); if (tmp8 & 0x01) { tmp8 &= ~0x01; - writeb(tmp8, CARM_INITC); + writeb(tmp8, mmio + CARM_INITC); readb(mmio + CARM_INITC); /* flush */ DPRINTK("snooze...\n"); diff --git a/drivers/block/ub.c b/drivers/block/ub.c index f605535d3..1e6784b5c 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -8,13 +8,11 @@ * and is not licensed separately. See file COPYING for details. * * TODO (sorted by decreasing priority) - * -- ZIP does "ub: resid 18 len 0 act 0" and whole transport quits (toggles?) + * -- Do resets with usb_device_reset (needs a thread context, use khubd) * -- set readonly flag for CDs, set removable flag for CF readers * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) * -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...) * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries - * -- do something about spin-down devices, they are extremely dangerous - * (ZIP is one. Needs spin-up command as well.) * -- verify the 13 conditions and do bulk resets * -- normal pool of commands instead of cmdv[]? * -- kill last_pipe and simply do two-state clearing on both pipes @@ -25,6 +23,7 @@ * -- prune comments, they are too volumnous * -- Exterminate P3 printks * -- Resove XXX's + * -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=? */ #include #include @@ -37,7 +36,7 @@ #define DRV_NAME "ub" #define DEVFS_NAME DRV_NAME -#define UB_MAJOR 125 /* Stolen from Experimental range for a week - XXX */ +#define UB_MAJOR 180 /* * Definitions which have to be scattered once we understand the layout better. @@ -62,9 +61,9 @@ /* command block wrapper */ struct bulk_cb_wrap { - u32 Signature; /* contains 'USBC' */ + __le32 Signature; /* contains 'USBC' */ u32 Tag; /* unique per command id */ - u32 DataTransferLength; /* size of data */ + __le32 DataTransferLength; /* size of data */ u8 Flags; /* direction in bit 0 */ u8 Lun; /* LUN normally 0 */ u8 Length; /* of of the CDB */ @@ -78,9 +77,9 @@ struct bulk_cb_wrap { /* command status wrapper */ struct bulk_cs_wrap { - u32 Signature; /* should = 'USBS' */ + __le32 Signature; /* should = 'USBS' */ u32 Tag; /* same as original command */ - u32 Residue; /* amount not transferred */ + __le32 Residue; /* amount not transferred */ u8 Status; /* see below */ }; @@ -104,13 +103,11 @@ struct ub_dev; #define UB_MAX_SECTORS 64 /* - * A second ought to be enough for a 32K transfer (UB_MAX_SECTORS) - * even if a webcam hogs the bus (famous last words). - * Some CDs need a second to spin up though. - * ZIP drive rejects commands when it's not spinning, - * so it does not need long timeouts either. + * A second is more than enough for a 32K transfer (UB_MAX_SECTORS) + * even if a webcam hogs the bus, but some devices need time to spin up. */ #define UB_URB_TIMEOUT (HZ*2) +#define UB_DATA_TIMEOUT (HZ*5) /* ZIP does spin-ups in the data phase */ #define UB_CTRL_TIMEOUT (HZ/2) /* 500ms ought to be enough to clear a stall */ /* @@ -157,7 +154,8 @@ struct ub_scsi_cmd { struct ub_scsi_cmd *next; int error; /* Return code - valid upon done */ - int act_len; /* Return size */ + unsigned int act_len; /* Return size */ + unsigned char key, asc, ascq; /* May be valid if error==-EIO */ int stat_count; /* Retries getting status. */ @@ -186,7 +184,7 @@ struct ub_capacity { */ #define SCMD_ST_HIST_SZ 8 -#define SCMD_TRACE_SZ 15 /* No more than 256 (trace_index) */ +#define SCMD_TRACE_SZ 63 /* Less than 4KB of 61-byte lines */ struct ub_scsi_cmd_trace { int hcur; @@ -265,6 +263,7 @@ struct ub_dev { int changed; /* Media was changed */ int removable; int readonly; + int first_open; /* Kludge. See ub_bd_open. */ char name[8]; struct usb_device *dev; struct usb_interface *intf; @@ -490,6 +489,18 @@ static void ub_id_put(int id) */ static void ub_cleanup(struct ub_dev *sc) { + + /* + * If we zero disk->private_data BEFORE put_disk, we have to check + * for NULL all over the place in open, release, check_media and + * revalidate, because the block level semaphore is well inside the + * put_disk. But we cannot zero after the call, because *disk is gone. + * The sd.c is blatantly racy in this area. + */ + /* disk->private_data = NULL; */ + put_disk(sc->disk); + sc->disk = NULL; + ub_id_put(sc->id); kfree(sc); } @@ -661,9 +672,12 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q) /* * build the command + * + * The call to blk_queue_hardsect_size() guarantees that request + * is aligned, but it is given in terms of 512 byte units, always. */ - block = rq->sector; - nblks = rq->nr_sectors; + block = rq->sector >> sc->capacity.bshift; + nblks = rq->nr_sectors >> sc->capacity.bshift; memset(cmd, 0, sizeof(struct ub_scsi_cmd)); cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10; @@ -678,7 +692,7 @@ static inline int ub_bd_rq_fn_1(request_queue_t *q) cmd->dir = ub_dir; cmd->state = UB_CMDST_INIT; cmd->data = rq->buffer; - cmd->len = nblks * 512; + cmd->len = rq->nr_sectors * 512; cmd->done = ub_rw_cmd_done; cmd->back = rq; @@ -786,17 +800,16 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); return rc; } + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); + cmd->state = UB_CMDST_CMD; ub_cmdtr_state(sc, cmd); return 0; @@ -836,6 +849,7 @@ static void ub_scsi_action(unsigned long _dev) unsigned long flags; spin_lock_irqsave(&sc->lock, flags); + del_timer(&sc->work_timer); ub_scsi_dispatch(sc); spin_unlock_irqrestore(&sc->lock, flags); } @@ -871,9 +885,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) int pipe; int rc; -/* P3 */ /** printk("ub: urb status %d pipe 0x%08x len %d act %d\n", - urb->status, urb->pipe, urb->transfer_buffer_length, urb->actual_length); **/ - if (atomic_read(&sc->poison)) { /* A little too simplistic, I feel... */ goto Bad_End; @@ -942,9 +953,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ub_cmdtr_state(sc, cmd); return; } - if (urb->status != 0) + if (urb->status != 0) { + printk("ub: cmd #%d cmd status (%d)\n", cmd->tag, urb->status); /* P3 */ goto Bad_End; + } if (urb->actual_length != US_BULK_CB_WRAP_LEN) { + printk("ub: cmd #%d xferred %d\n", cmd->tag, urb->actual_length); /* P3 */ /* XXX Must do reset here to unconfuse the device */ goto Bad_End; } @@ -968,18 +982,17 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; + add_timer(&sc->work_timer); + cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); @@ -1063,19 +1076,18 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC); if (rc != 0) { /* XXX Clear stalls */ printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); return; } @@ -1132,16 +1144,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) (*cmd->done)(sc, cmd); } else if (cmd->state == UB_CMDST_SENSE) { - /* - * We do not look at sense, because even if there was no sense, - * we get into UB_CMDST_SENSE from a STALL or CSW FAIL only. - * We request sense because we want to clear CHECK CONDITION - * on devices with delusions of SCSI, and not because we - * are curious in any way about the sense itself. - */ - /* if ((cmd->top_sense[2] & 0x0F) == NO_SENSE) { foo } */ - ub_state_done(sc, cmd, -EIO); + } else { printk(KERN_WARNING "%s: " "wrong command state %d on device %u\n", @@ -1186,18 +1190,17 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); + cmd->stat_count = 0; cmd->state = UB_CMDST_STAT; ub_cmdtr_state(sc, cmd); @@ -1217,9 +1220,17 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) goto error; } + /* + * ``If the allocation length is eighteen or greater, and a device + * server returns less than eithteen bytes of data, the application + * client should assume that the bytes not transferred would have been + * zeroes had the device server returned those bytes.'' + */ memset(&sc->top_sense, 0, UB_SENSE_SIZE); + scmd = &sc->top_rqs_cmd; scmd->cdb[0] = REQUEST_SENSE; + scmd->cdb[4] = UB_SENSE_SIZE; scmd->cdb_len = 6; scmd->dir = UB_DIR_READ; scmd->state = UB_CMDST_INIT; @@ -1271,14 +1282,13 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - del_timer(&sc->work_timer); ub_complete(&sc->work_done); return rc; } + + sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; + add_timer(&sc->work_timer); return 0; } @@ -1289,8 +1299,15 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) unsigned char *sense = scmd->data; struct ub_scsi_cmd *cmd; + /* + * Ignoring scmd->act_len, because the buffer was pre-zeroed. + */ ub_cmdtr_sense(sc, scmd, sense); + /* + * Find the command which triggered the unit attention or a check, + * save the sense into it, and advance its state machine. + */ if ((cmd = ub_cmdq_peek(sc)) == NULL) { printk(KERN_WARNING "%s: sense done while idle\n", sc->name); return; @@ -1308,6 +1325,10 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) return; } + cmd->key = sense[2] & 0x0F; + cmd->asc = sense[12]; + cmd->ascq = sense[13]; + ub_scsi_urb_compl(sc, cmd); } @@ -1355,12 +1376,7 @@ static void ub_revalidate(struct ub_dev *sc) sc->readonly = 0; /* XXX Query this from the device */ - /* - * XXX sd.c sets capacity to zero in such case. However, it doesn't - * work for us. In case of zero capacity, block layer refuses to - * have the /dev/uba opened (why?) Set capacity to some random value. - */ - sc->capacity.nsec = 50; + sc->capacity.nsec = 0; sc->capacity.bsize = 512; sc->capacity.bshift = 0; @@ -1375,7 +1391,7 @@ static void ub_revalidate(struct ub_dev *sc) * We keep this because sd.c has retries for capacity. */ if (ub_sync_read_cap(sc, &sc->capacity) != 0) { - sc->capacity.nsec = 100; + sc->capacity.nsec = 0; sc->capacity.bsize = 512; sc->capacity.bshift = 0; } @@ -1404,10 +1420,38 @@ static int ub_bd_open(struct inode *inode, struct file *filp) sc->openc++; spin_unlock_irqrestore(&ub_lock, flags); + /* + * This is a workaround for a specific problem in our block layer. + * In 2.6.9, register_disk duplicates the code from rescan_partitions. + * However, if we do add_disk with a device which persistently reports + * a changed media, add_disk calls register_disk, which does do_open, + * which will call rescan_paritions for changed media. After that, + * register_disk attempts to do it all again and causes double kobject + * registration and a eventually an oops on module removal. + * + * The bottom line is, Al Viro says that we should not allow + * bdev->bd_invalidated to be set when doing add_disk no matter what. + */ + if (sc->first_open) { + if (sc->changed) { + sc->first_open = 0; + rc = -ENOMEDIUM; + goto err_open; + } + } + if (sc->removable || sc->readonly) check_disk_change(inode->i_bdev); - /* XXX sd.c and floppy.c bail on open if media is not present. */ + /* + * The sd.c considers ->media_present and ->changed not equivalent, + * under some pretty murky conditions (a failure of READ CAPACITY). + * We may need it one day. + */ + if (sc->removable && sc->changed && !(filp->f_flags & O_NDELAY)) { + rc = -ENOMEDIUM; + goto err_open; + } if (sc->readonly && (filp->f_mode & FMODE_WRITE)) { rc = -EROFS; @@ -1435,6 +1479,8 @@ static int ub_bd_release(struct inode *inode, struct file *filp) spin_lock_irqsave(&ub_lock, flags); --sc->openc; + if (sc->openc == 0) + sc->first_open = 0; if (sc->openc == 0 && atomic_read(&sc->poison)) ub_cleanup(sc); spin_unlock_irqrestore(&ub_lock, flags); @@ -1489,11 +1535,17 @@ static int ub_bd_revalidate(struct gendisk *disk) ub_revalidate(sc); /* This is pretty much a long term P3 */ - printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n", - sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize); + if (!atomic_read(&sc->poison)) { /* Cover sc->dev */ + printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n", + sc->name, sc->dev->devnum, + sc->capacity.nsec, sc->capacity.bsize); + } + /* XXX Support sector size switching like in sr.c */ + blk_queue_hardsect_size(disk->queue, sc->capacity.bsize); set_capacity(disk, sc->capacity.nsec); // set_disk_ro(sdkp->disk, sc->readonly); + return 0; } @@ -1524,13 +1576,9 @@ static int ub_bd_media_changed(struct gendisk *disk) */ if (ub_sync_tur(sc) != 0) { sc->changed = 1; - /* P3 */ printk("%s: made changed\n", sc->name); return 1; } - /* The sd.c clears this before returning (one-shot flag). Why? */ - /* P3 */ printk("%s: %s changed\n", sc->name, - sc->changed? "is": "was not"); return sc->changed; } @@ -1592,6 +1640,9 @@ static int ub_sync_tur(struct ub_dev *sc) rc = cmd->error; + if (rc == -EIO && cmd->key != 0) /* Retries for benh's key */ + rc = cmd->key; + err_submit: kfree(cmd); err_alloc: @@ -1654,8 +1705,8 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret) } /* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */ - nsec = be32_to_cpu(*(u32 *)p) + 1; - bsize = be32_to_cpu(*(u32 *)(p + 4)); + nsec = be32_to_cpu(*(__be32 *)p) + 1; + bsize = be32_to_cpu(*(__be32 *)(p + 4)); switch (bsize) { case 512: shift = 0; break; case 1024: shift = 1; break; @@ -1725,28 +1776,22 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) sc->work_urb.error_count = 0; sc->work_urb.status = 0; - init_timer(&timer); - timer.function = ub_probe_timeout; - timer.data = (unsigned long) &compl; - timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { printk(KERN_WARNING "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); - del_timer_sync(&timer); return rc; } + init_timer(&timer); + timer.function = ub_probe_timeout; + timer.data = (unsigned long) &compl; + timer.expires = jiffies + UB_CTRL_TIMEOUT; + add_timer(&timer); + wait_for_completion(&compl); del_timer_sync(&timer); - /* - * Most of the time, URB was done and dev set to NULL, and so - * the unlink bounces out with ENODEV. We do not call usb_kill_urb - * because we still think about a backport to 2.4. - */ - usb_unlink_urb(&sc->work_urb); + usb_kill_urb(&sc->work_urb); /* reset the endpoint toggle */ usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0); @@ -1813,6 +1858,7 @@ static int ub_probe(struct usb_interface *intf, request_queue_t *q; struct gendisk *disk; int rc; + int i; rc = -ENOMEM; if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) @@ -1879,9 +1925,15 @@ static int ub_probe(struct usb_interface *intf, * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ - ub_sync_tur(sc); + for (i = 0; i < 3; i++) { /* Retries for benh's key */ + if ((rc = ub_sync_tur(sc)) <= 0) break; + if (rc != 0x6) break; + msleep(10); + } sc->removable = 1; /* XXX Query this from the device */ + sc->changed = 1; /* ub_revalidate clears only */ + sc->first_open = 1; ub_revalidate(sc); /* This is pretty much a long term P3 */ @@ -1915,7 +1967,7 @@ static int ub_probe(struct usb_interface *intf, blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY); blk_queue_max_sectors(q, UB_MAX_SECTORS); - // blk_queue_hardsect_size(q, xxxxx); + blk_queue_hardsect_size(q, sc->capacity.bsize); /* * This is a serious infraction, caused by a deficiency in the @@ -2005,17 +2057,6 @@ static void ub_disconnect(struct usb_interface *intf) if (q) blk_cleanup_queue(q); - /* - * If we zero disk->private_data BEFORE put_disk, we have to check - * for NULL all over the place in open, release, check_media and - * revalidate, because the block level semaphore is well inside the - * put_disk. But we cannot zero after the call, because *disk is gone. - * The sd.c is blatantly racy in this area. - */ - /* disk->private_data = NULL; */ - put_disk(disk); - sc->disk = NULL; - /* * We really expect blk_cleanup_queue() to wait, so no amount * of paranoya is too much. @@ -2034,6 +2075,13 @@ static void ub_disconnect(struct usb_interface *intf) } spin_unlock_irqrestore(&sc->lock, flags); + /* + * There is virtually no chance that other CPU runs times so long + * after ub_urb_complete should have called del_timer, but only if HCD + * didn't forget to deliver a callback on unlink. + */ + del_timer_sync(&sc->work_timer); + /* * At this point there must be no commands coming from anyone * and no URBs left in transit. diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 2b126d8d2..86a21e456 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -83,15 +83,15 @@ static int debug; #define DEBUG_LED_ON_TRANSFER 0x01 #define DEBUG_BATTERY_POLLING 0x02 -MODULE_PARM(debug, "i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug bitmask"); static int pci_read_cmd = 0x0C; /* Read Multiple */ -MODULE_PARM(pci_read_cmd, "i"); +module_param(pci_read_cmd, int, 0); MODULE_PARM_DESC(pci_read_cmd, "PCI read command"); static int pci_write_cmd = 0x0F; /* Write and Invalidate */ -MODULE_PARM(pci_write_cmd, "i"); +module_param(pci_write_cmd, int, 0); MODULE_PARM_DESC(pci_write_cmd, "PCI write command"); static int pci_cmds; @@ -108,11 +108,11 @@ struct cardinfo { int irq; unsigned long csr_base; - unsigned char *csr_remap; + unsigned char __iomem *csr_remap; unsigned long csr_len; #ifdef CONFIG_MM_MAP_MEMORY unsigned long mem_base; - unsigned char *mem_remap; + unsigned char __iomem *mem_remap; unsigned long mem_len; #endif @@ -926,7 +926,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i goto failed_req_mem; } - if (!(card->mem_remap = (unsigned char *)ioremap(card->mem_base, cards->mem_len))) { + if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) { printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); ret = -ENOMEM; @@ -1107,12 +1107,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i card->mm_pages[1].page_dma); failed_magic: #ifdef CONFIG_MM_MAP_MEMORY - iounmap((void *) card->mem_remap); + iounmap(card->mem_remap); failed_remap_mem: release_mem_region(card->mem_base, card->mem_len); failed_req_mem: #endif - iounmap((void *) card->csr_remap); + iounmap(card->csr_remap); failed_remap_csr: release_mem_region(card->csr_base, card->csr_len); failed_req_csr: diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 9534c740e..321d53dfe 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -764,8 +764,8 @@ static int viodasd_remove(struct vio_dev *vdev) d = &viodasd_devices[vdev->unit_address]; if (d->disk) { del_gendisk(d->disk); - put_disk(d->disk); blk_cleanup_queue(d->disk->queue); + put_disk(d->disk); d->disk = NULL; } d->dev = NULL; diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 5ca834fcd..e78a177c2 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -266,7 +266,7 @@ Enomem: /* xd_detect: scan the possible BIOS ROM locations for the signature strings */ static u_char __init xd_detect (u_char *controller, unsigned int *address) { - u_char i,j,found = 0; + int i, j; if (xd_override) { @@ -275,15 +275,23 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address) return(1); } - for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++) - for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++) - if (isa_check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) { + for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) { + void __iomem *p = ioremap(xd_bases[i], 0x2000); + if (!p) + continue; + for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) { + const char *s = xd_sigs[j].string; + if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) { *controller = j; xd_type = j; *address = xd_bases[i]; - found++; + iounmap(p); + return 1; } - return (found); + } + iounmap(p); + } + return 0; } /* do_xd_request: handle an incoming request */ diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 958a5e1f7..8dc889498 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -32,9 +32,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 1de33046e..924bf39a4 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -2,6 +2,7 @@ * * Broadcom Blutonium firmware driver * + * Copyright (C) 2003 Maxim Krasnyansky * Copyright (C) 2003 Marcel Holtmann * * @@ -264,7 +265,7 @@ static void bcm203x_disconnect(struct usb_interface *intf) BT_DBG("intf %p", intf); - usb_unlink_urb(data->urb); + usb_kill_urb(data->urb); usb_set_intfdata(intf, NULL); diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 79ff338e9..7803b91ee 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -123,7 +123,7 @@ static void bfusb_unlink_urbs(struct bfusb *bfusb) while ((skb = skb_dequeue(&bfusb->pending_q))) { urb = ((struct bfusb_scb *) skb->cb)->urb; - usb_unlink_urb(urb); + usb_kill_urb(urb); skb_queue_tail(&bfusb->completed_q, skb); } @@ -680,7 +680,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; bfusb->bulk_pkt_size = bulk_out_ep->desc.wMaxPacketSize; - bfusb->lock = RW_LOCK_UNLOCKED; + rwlock_init(&bfusb->lock); bfusb->reassembly = NULL; diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 54ef5f941..4db1feeef 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -34,6 +34,8 @@ #include #include #include +#include + #include #include @@ -54,11 +56,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0x86bc; +static unsigned int irq_mask = 0x86bc; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)"); @@ -90,14 +92,14 @@ typedef struct bluecard_info_t { } bluecard_info_t; -void bluecard_config(dev_link_t *link); -void bluecard_release(dev_link_t *link); -int bluecard_event(event_t event, int priority, event_callback_args_t *args); +static void bluecard_config(dev_link_t *link); +static void bluecard_release(dev_link_t *link); +static int bluecard_event(event_t event, int priority, event_callback_args_t *args); static dev_info_t dev_info = "bluecard_cs"; -dev_link_t *bluecard_attach(void); -void bluecard_detach(dev_link_t *); +static dev_link_t *bluecard_attach(void); +static void bluecard_detach(dev_link_t *); static dev_link_t *dev_list = NULL; @@ -170,7 +172,7 @@ static dev_link_t *dev_list = NULL; /* ======================== LED handling routines ======================== */ -void bluecard_activity_led_timeout(u_long arg) +static void bluecard_activity_led_timeout(u_long arg) { bluecard_info_t *info = (bluecard_info_t *)arg; unsigned int iobase = info->link.io.BasePort1; @@ -719,7 +721,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l /* ======================== Card services HCI interaction ======================== */ -int bluecard_open(bluecard_info_t *info) +static int bluecard_open(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; struct hci_dev *hdev; @@ -837,7 +839,7 @@ int bluecard_open(bluecard_info_t *info) } -int bluecard_close(bluecard_info_t *info) +static int bluecard_close(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; struct hci_dev *hdev = info->hdev; @@ -864,7 +866,7 @@ int bluecard_close(bluecard_info_t *info) return 0; } -dev_link_t *bluecard_attach(void) +static dev_link_t *bluecard_attach(void) { bluecard_info_t *info; client_reg_t client_reg; @@ -922,7 +924,7 @@ dev_link_t *bluecard_attach(void) } -void bluecard_detach(dev_link_t *link) +static void bluecard_detach(dev_link_t *link) { bluecard_info_t *info = link->priv; dev_link_t **linkp; @@ -967,7 +969,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse return pcmcia_parse_tuple(handle, tuple, parse); } -void bluecard_config(dev_link_t *link) +static void bluecard_config(dev_link_t *link) { client_handle_t handle = link->handle; bluecard_info_t *info = link->priv; @@ -1042,7 +1044,7 @@ failed: } -void bluecard_release(dev_link_t *link) +static void bluecard_release(dev_link_t *link) { bluecard_info_t *info = link->priv; @@ -1061,7 +1063,7 @@ void bluecard_release(dev_link_t *link) } -int bluecard_event(event_t event, int priority, event_callback_args_t *args) +static int bluecard_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; bluecard_info_t *info = link->priv; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d67d0385f..a50adb67b 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -34,13 +34,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include @@ -63,11 +64,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann , Jose Orlando Pereira "); MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); @@ -95,14 +96,14 @@ typedef struct bt3c_info_t { } bt3c_info_t; -void bt3c_config(dev_link_t *link); -void bt3c_release(dev_link_t *link); -int bt3c_event(event_t event, int priority, event_callback_args_t *args); +static void bt3c_config(dev_link_t *link); +static void bt3c_release(dev_link_t *link); +static int bt3c_event(event_t event, int priority, event_callback_args_t *args); static dev_info_t dev_info = "bt3c_cs"; -dev_link_t *bt3c_attach(void); -void bt3c_detach(dev_link_t *); +static dev_link_t *bt3c_attach(void); +static void bt3c_detach(dev_link_t *); static dev_link_t *dev_list = NULL; @@ -131,28 +132,28 @@ static dev_link_t *dev_list = NULL; #define CONTROL 4 -inline void bt3c_address(unsigned int iobase, unsigned short addr) +static inline void bt3c_address(unsigned int iobase, unsigned short addr) { outb(addr & 0xff, iobase + ADDR_L); outb((addr >> 8) & 0xff, iobase + ADDR_H); } -inline void bt3c_put(unsigned int iobase, unsigned short value) +static inline void bt3c_put(unsigned int iobase, unsigned short value) { outb(value & 0xff, iobase + DATA_L); outb((value >> 8) & 0xff, iobase + DATA_H); } -inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) +static inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) { bt3c_address(iobase, addr); bt3c_put(iobase, value); } -inline unsigned short bt3c_get(unsigned int iobase) +static inline unsigned short bt3c_get(unsigned int iobase) { unsigned short value = inb(iobase + DATA_L); @@ -162,7 +163,7 @@ inline unsigned short bt3c_get(unsigned int iobase) } -inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) +static inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) { bt3c_address(iobase, addr); @@ -489,13 +490,10 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long static struct device *bt3c_device(void) { - static char *kobj_name = "bt3c"; - static struct device dev = { .bus_id = "pcmcia", }; - dev.kobj.k_name = kmalloc(strlen(kobj_name) + 1, GFP_KERNEL); - strcpy(dev.kobj.k_name, kobj_name); + kobject_set_name(&dev.kobj, "bt3c"); kobject_init(&dev.kobj); return &dev; @@ -586,7 +584,7 @@ error: } -int bt3c_open(bt3c_info_t *info) +static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; @@ -656,7 +654,7 @@ error: } -int bt3c_close(bt3c_info_t *info) +static int bt3c_close(bt3c_info_t *info) { struct hci_dev *hdev = info->hdev; @@ -673,7 +671,7 @@ int bt3c_close(bt3c_info_t *info) return 0; } -dev_link_t *bt3c_attach(void) +static dev_link_t *bt3c_attach(void) { bt3c_info_t *info; client_reg_t client_reg; @@ -731,7 +729,7 @@ dev_link_t *bt3c_attach(void) } -void bt3c_detach(dev_link_t *link) +static void bt3c_detach(dev_link_t *link) { bt3c_info_t *info = link->priv; dev_link_t **linkp; @@ -785,7 +783,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return get_tuple(handle, tuple, parse); } -void bt3c_config(dev_link_t *link) +static void bt3c_config(dev_link_t *link) { static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; client_handle_t handle = link->handle; @@ -898,7 +896,7 @@ failed: } -void bt3c_release(dev_link_t *link) +static void bt3c_release(dev_link_t *link) { bt3c_info_t *info = link->priv; @@ -915,7 +913,7 @@ void bt3c_release(dev_link_t *link) } -int bt3c_event(event_t event, int priority, event_callback_args_t *args) +static int bt3c_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; bt3c_info_t *info = link->priv; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index b44fa7dd3..74644df24 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -33,13 +33,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include @@ -59,11 +60,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth driver for Bluetooth PCMCIA cards with HCI UART interface"); @@ -91,14 +92,14 @@ typedef struct btuart_info_t { } btuart_info_t; -void btuart_config(dev_link_t *link); -void btuart_release(dev_link_t *link); -int btuart_event(event_t event, int priority, event_callback_args_t *args); +static void btuart_config(dev_link_t *link); +static void btuart_release(dev_link_t *link); +static int btuart_event(event_t event, int priority, event_callback_args_t *args); static dev_info_t dev_info = "btuart_cs"; -dev_link_t *btuart_attach(void); -void btuart_detach(dev_link_t *); +static dev_link_t *btuart_attach(void); +static void btuart_detach(dev_link_t *); static dev_link_t *dev_list = NULL; @@ -491,7 +492,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon /* ======================== Card services HCI interaction ======================== */ -int btuart_open(btuart_info_t *info) +static int btuart_open(btuart_info_t *info) { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; @@ -560,7 +561,7 @@ int btuart_open(btuart_info_t *info) } -int btuart_close(btuart_info_t *info) +static int btuart_close(btuart_info_t *info) { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; @@ -589,7 +590,7 @@ int btuart_close(btuart_info_t *info) return 0; } -dev_link_t *btuart_attach(void) +static dev_link_t *btuart_attach(void) { btuart_info_t *info; client_reg_t client_reg; @@ -647,7 +648,7 @@ dev_link_t *btuart_attach(void) } -void btuart_detach(dev_link_t *link) +static void btuart_detach(dev_link_t *link) { btuart_info_t *info = link->priv; dev_link_t **linkp; @@ -701,7 +702,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return get_tuple(handle, tuple, parse); } -void btuart_config(dev_link_t *link) +static void btuart_config(dev_link_t *link) { static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; client_handle_t handle = link->handle; @@ -815,7 +816,7 @@ failed: } -void btuart_release(dev_link_t *link) +static void btuart_release(dev_link_t *link) { btuart_info_t *info = link->priv; @@ -832,7 +833,7 @@ void btuart_release(dev_link_t *link) } -int btuart_event(event_t event, int priority, event_callback_args_t *args) +static int btuart_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; btuart_info_t *info = link->priv; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 79ec1ce78..87ff7966f 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -33,13 +33,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include @@ -59,11 +60,11 @@ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xffff; +static unsigned int irq_mask = 0xffff; static int irq_list[4] = { -1 }; -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); +module_param(irq_mask, uint, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth driver for Nokia Connectivity Card DTL-1"); @@ -94,14 +95,14 @@ typedef struct dtl1_info_t { } dtl1_info_t; -void dtl1_config(dev_link_t *link); -void dtl1_release(dev_link_t *link); -int dtl1_event(event_t event, int priority, event_callback_args_t *args); +static void dtl1_config(dev_link_t *link); +static void dtl1_release(dev_link_t *link); +static int dtl1_event(event_t event, int priority, event_callback_args_t *args); static dev_info_t dev_info = "dtl1_cs"; -dev_link_t *dtl1_attach(void); -void dtl1_detach(dev_link_t *); +static dev_link_t *dtl1_attach(void); +static void dtl1_detach(dev_link_t *); static dev_link_t *dev_list = NULL; @@ -468,7 +469,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long /* ======================== Card services HCI interaction ======================== */ -int dtl1_open(dtl1_info_t *info) +static int dtl1_open(dtl1_info_t *info) { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; @@ -539,7 +540,7 @@ int dtl1_open(dtl1_info_t *info) } -int dtl1_close(dtl1_info_t *info) +static int dtl1_close(dtl1_info_t *info) { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; @@ -568,7 +569,7 @@ int dtl1_close(dtl1_info_t *info) return 0; } -dev_link_t *dtl1_attach(void) +static dev_link_t *dtl1_attach(void) { dtl1_info_t *info; client_reg_t client_reg; @@ -626,7 +627,7 @@ dev_link_t *dtl1_attach(void) } -void dtl1_detach(dev_link_t *link) +static void dtl1_detach(dev_link_t *link) { dtl1_info_t *info = link->priv; dev_link_t **linkp; @@ -680,7 +681,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return get_tuple(handle, tuple, parse); } -void dtl1_config(dev_link_t *link) +static void dtl1_config(dev_link_t *link) { client_handle_t handle = link->handle; dtl1_info_t *info = link->priv; @@ -767,7 +768,7 @@ failed: } -void dtl1_release(dev_link_t *link) +static void dtl1_release(dev_link_t *link) { dtl1_info_t *info = link->priv; @@ -784,7 +785,7 @@ void dtl1_release(dev_link_t *link) } -int dtl1_event(event_t event, int priority, event_callback_args_t *args) +static int dtl1_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; dtl1_info_t *info = link->priv; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 5ba134216..dfb4142a5 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -143,7 +143,7 @@ restart: int len; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - len = tty->driver->write(tty, 0, skb->data, skb->len); + len = tty->driver->write(tty, skb->data, skb->len); hdev->stat.byte_tx += len; skb_pull(skb, len); @@ -188,9 +188,7 @@ static int hci_uart_flush(struct hci_dev *hdev) } /* Flush any pending characters in the driver and discipline. */ - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - + tty_ldisc_flush(tty); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); @@ -280,7 +278,9 @@ static int hci_uart_tty_open(struct tty_struct *tty) spin_lock_init(&hu->rx_lock); - /* Flush any pending characters in the driver and line discipline */ + /* Flush any pending characters in the driver and line discipline. */ + /* FIXME: why is this needed. Note don't use ldisc_ref here as the + open path is before the ldisc is referencable */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); @@ -502,7 +502,7 @@ static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsi { return 0; } -static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char __user *data, size_t count) +static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) { return 0; } diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 9babb21df..88f9a8940 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,10 @@ #define URB_ZERO_PACKET 0 #endif +#ifdef CONFIG_BT_HCIUSB_SCO +static int isoc = 2; +#endif + #define VERSION "2.7" static struct usb_driver hci_usb_driver; @@ -96,13 +101,18 @@ static struct usb_device_id blacklist_ids[] = { { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, /* Broadcom BCM2035 */ - { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET }, + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, + { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, + + /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ + { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, /* ISSC Bluetooth Adapter v3.1 */ { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, - /* Digianswer device */ + /* Digianswer devices */ { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, + { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE }, /* RTX Telecom based adapter with buggy SCO support */ { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, @@ -110,7 +120,7 @@ static struct usb_device_id blacklist_ids[] = { { } /* Terminating entry */ }; -struct _urb *_urb_alloc(int isoc, int gfp) +static struct _urb *_urb_alloc(int isoc, int gfp) { struct _urb *_urb = kmalloc(sizeof(struct _urb) + sizeof(struct usb_iso_packet_descriptor) * isoc, gfp); @@ -121,7 +131,7 @@ struct _urb *_urb_alloc(int isoc, int gfp) return _urb; } -struct _urb *_urb_dequeue(struct _urb_queue *q) +static struct _urb *_urb_dequeue(struct _urb_queue *q) { struct _urb *_urb = NULL; unsigned long flags; @@ -790,7 +800,12 @@ static void hci_usb_destruct(struct hci_dev *hdev) kfree(husb); } -int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt) +{ + BT_DBG("%s evt %d", hdev->name, evt); +} + +static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct usb_host_endpoint *bulk_out_ep = NULL; @@ -856,9 +871,9 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) husb->intr_in_ep = intr_in_ep; if (id->driver_info & HCI_DIGIANSWER) - husb->ctrl_req = HCI_DIGI_REQ; + husb->ctrl_req = USB_TYPE_VENDOR; else - husb->ctrl_req = HCI_CTRL_REQ; + husb->ctrl_req = USB_TYPE_CLASS; /* Find isochronous endpoints that we can use */ size = 0; @@ -867,7 +882,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) isoc_ifnum = 1; #ifdef CONFIG_BT_HCIUSB_SCO - if (!(id->driver_info & HCI_BROKEN_ISOC)) + if (isoc && !(id->driver_info & HCI_BROKEN_ISOC)) isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum); if (isoc_iface) { @@ -883,7 +898,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_ISOC: if (ep->desc.wMaxPacketSize < size || - uif->desc.bAlternateSetting > 2) + uif->desc.bAlternateSetting != isoc) break; size = ep->desc.wMaxPacketSize; @@ -906,7 +921,9 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) BT_ERR("Can't claim isoc interface"); else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) { BT_ERR("Can't set isoc interface settings"); + husb->isoc_iface = isoc_iface; usb_driver_release_interface(&hci_usb_driver, isoc_iface); + husb->isoc_iface = NULL; } else { husb->isoc_iface = isoc_iface; husb->isoc_in_ep = isoc_in_ep; @@ -916,7 +933,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) } #endif - husb->completion_lock = RW_LOCK_UNLOCKED; + rwlock_init(&husb->completion_lock); for (i = 0; i < 4; i++) { skb_queue_head_init(&husb->transmit_q[i]); @@ -942,6 +959,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) hdev->flush = hci_usb_flush; hdev->send = hci_usb_send_frame; hdev->destruct = hci_usb_destruct; + hdev->notify = hci_usb_notify; hdev->owner = THIS_MODULE; @@ -1018,6 +1036,11 @@ static void __exit hci_usb_exit(void) module_init(hci_usb_init); module_exit(hci_usb_exit); +#ifdef CONFIG_BT_HCIUSB_SCO +module_param(isoc, int, 0644); +MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support"); +#endif + MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index da4561ef7..487d0e7cf 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h @@ -28,9 +28,6 @@ #define HCI_DEV_SUBCLASS 0x01 /* RF subclass */ #define HCI_DEV_PROTOCOL 0x01 /* Bluetooth programming protocol */ -#define HCI_CTRL_REQ 0x20 -#define HCI_DIGI_REQ 0x40 - #define HCI_IGNORE 0x01 #define HCI_RESET 0x02 #define HCI_DIGIANSWER 0x04 @@ -59,8 +56,6 @@ struct _urb { struct urb urb; }; -struct _urb *_urb_alloc(int isoc, int gfp); - static inline void _urb_free(struct _urb *_urb) { kfree(_urb); @@ -99,8 +94,6 @@ static inline void _urb_unlink(struct _urb *_urb) } } -struct _urb *_urb_dequeue(struct _urb_queue *q); - struct hci_usb { struct hci_dev *hdev; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index d1df4adff..3b9f7a534 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -338,7 +338,7 @@ static struct miscdevice hci_vhci_miscdev= &hci_vhci_fops }; -int __init hci_vhci_init(void) +static int __init hci_vhci_init(void) { BT_INFO("VHCI driver ver %s", VERSION); @@ -350,7 +350,7 @@ int __init hci_vhci_init(void) return 0; } -void hci_vhci_cleanup(void) +static void hci_vhci_cleanup(void) { misc_deregister(&hci_vhci_miscdev); } diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile index 5c484f3b3..4a8351753 100644 --- a/drivers/cdrom/Makefile +++ b/drivers/cdrom/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BLK_DEV_IDECD) += cdrom.o obj-$(CONFIG_BLK_DEV_SR) += cdrom.o obj-$(CONFIG_PARIDE_PCD) += cdrom.o +obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o obj-$(CONFIG_AZTCD) += aztcd.o obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 2e1ee63d1..fc4e07a4e 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -234,6 +234,12 @@ -- Mt Rainier support -- DVD-RAM write open fixes + Nov 5 2001, Aug 8 2002. Modified by Andy Polyakov + to support MMC-3 compliant DVD+RW units. + + Modified by Nigel Kukard - support DVD+RW + 2.4.x patch by Andy Polyakov + -------------------------------------------------------------------------*/ #define REVISION "Revision: 3.20" @@ -290,12 +296,12 @@ static int lockdoor = 1; static int check_media_type; /* automatically restart mrw format */ static int mrw_format_restart = 1; -MODULE_PARM(debug, "i"); -MODULE_PARM(autoclose, "i"); -MODULE_PARM(autoeject, "i"); -MODULE_PARM(lockdoor, "i"); -MODULE_PARM(check_media_type, "i"); -MODULE_PARM(mrw_format_restart, "i"); +module_param(debug, bool, 0); +module_param(autoclose, bool, 0); +module_param(autoeject, bool, 0); +module_param(lockdoor, bool, 0); +module_param(check_media_type, bool, 0); +module_param(mrw_format_restart, bool, 0); static spinlock_t cdrom_lock = SPIN_LOCK_UNLOCKED; @@ -354,6 +360,19 @@ static void cdrom_sysctl_register(void); #endif /* CONFIG_SYSCTL */ static struct cdrom_device_info *topCdromPtr; +static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi, + struct packet_command *cgc) +{ + if (cgc->sense) { + cgc->sense->sense_key = 0x05; + cgc->sense->asc = 0x20; + cgc->sense->ascq = 0x00; + } + + cgc->stat = -EIO; + return -EIO; +} + /* This macro makes sure we don't have to check on cdrom_device_ops * existence in the run-time routines below. Change_capability is a * hack to have the capability flags defined const, while we can still @@ -411,6 +430,9 @@ int register_cdrom(struct cdrom_device_info *cdi) else cdi->cdda_method = CDDA_OLD; + if (!cdo->generic_packet) + cdo->generic_packet = cdrom_dummy_generic_packet; + cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); spin_lock(&cdrom_lock); cdi->next = topCdromPtr; @@ -472,6 +494,9 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi, if (be16_to_cpu(eh->data_len) < sizeof(*med)) return 1; + if (eh->nea || eh->notification_class != 0x4) + return 1; + memcpy(med, &buffer[sizeof(*eh)], sizeof(*med)); return 0; } @@ -521,6 +546,8 @@ int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write) return ret; mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)]; + if (be16_to_cpu(mfd->feature_code) != CDF_MRW) + return 1; *write = mfd->write; if ((ret = cdrom_mrw_probe_pc(cdi))) { @@ -605,13 +632,16 @@ static int cdrom_flush_cache(struct cdrom_device_info *cdi) static int cdrom_mrw_exit(struct cdrom_device_info *cdi) { disc_information di; - int ret = 0; + int ret; - if (cdrom_get_disc_info(cdi, &di)) + ret = cdrom_get_disc_info(cdi, &di); + if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type)) return 1; + ret = 0; if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) { - printk(KERN_INFO "cdrom: issuing MRW back ground format suspend\n"); + printk(KERN_INFO "cdrom: issuing MRW back ground " + "format suspend\n"); ret = cdrom_mrw_bgformat_susp(cdi, 0); } @@ -715,8 +745,10 @@ int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write) static int cdrom_media_erasable(struct cdrom_device_info *cdi) { disc_information di; + int ret; - if (cdrom_get_disc_info(cdi, &di)) + ret = cdrom_get_disc_info(cdi, &di); + if (ret < 0 || ret < offsetof(typeof(di), n_first_track)) return -1; return di.erasable; @@ -752,7 +784,8 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) return 1; } - if (cdrom_get_disc_info(cdi, &di)) + ret = cdrom_get_disc_info(cdi, &di); + if (ret < 0 || ret < offsetof(typeof(di),disc_type)) return 1; if (!di.erasable) @@ -766,10 +799,12 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) * 3 - MRW formatting complete */ ret = 0; - printk(KERN_INFO "cdrom open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]); + printk(KERN_INFO "cdrom open: mrw_status '%s'\n", + mrw_format_status[di.mrw_status]); if (!di.mrw_status) ret = 1; - else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && mrw_format_restart) + else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && + mrw_format_restart) ret = cdrom_mrw_bgformat(cdi, 1); return ret; @@ -821,6 +856,39 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi) return ret; } +static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) +{ + struct packet_command cgc; + char buffer[32]; + int ret, mmc3_profile; + + init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); + + cgc.cmd[0] = GPCMD_GET_CONFIGURATION; + cgc.cmd[1] = 0; + cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */ + cgc.cmd[8] = sizeof(buffer); /* Allocation Length */ + cgc.quiet = 1; + + if ((ret = cdi->ops->generic_packet(cdi, &cgc))) + mmc3_profile = 0xffff; + else + mmc3_profile = (buffer[6] << 8) | buffer[7]; + + cdi->mmc3_profile = mmc3_profile; +} + +static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi) +{ + switch (cdi->mmc3_profile) { + case 0x12: /* DVD-RAM */ + case 0x1A: /* DVD+RW */ + return 0; + default: + return 1; + } +} + /* * returns 0 for ok to open write, non-0 to disallow */ @@ -862,10 +930,50 @@ static int cdrom_open_write(struct cdrom_device_info *cdi) ret = cdrom_ram_open_write(cdi); else if (CDROM_CAN(CDC_MO_DRIVE)) ret = mo_open_write(cdi); + else if (!cdrom_is_dvd_rw(cdi)) + ret = 0; return ret; } +static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi) +{ + struct packet_command cgc; + + if (cdi->mmc3_profile != 0x1a) { + cdinfo(CD_CLOSE, "%s: No DVD+RW\n", cdi->name); + return; + } + + if (!cdi->media_written) { + cdinfo(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name); + return; + } + + printk(KERN_INFO "cdrom: %s: dirty DVD+RW media, \"finalizing\"\n", + cdi->name); + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.cmd[0] = GPCMD_FLUSH_CACHE; + cgc.timeout = 30*HZ; + cdi->ops->generic_packet(cdi, &cgc); + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.cmd[0] = GPCMD_CLOSE_TRACK; + cgc.timeout = 3000*HZ; + cgc.quiet = 1; + cdi->ops->generic_packet(cdi, &cgc); + + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); + cgc.cmd[0] = GPCMD_CLOSE_TRACK; + cgc.cmd[2] = 2; /* Close session */ + cgc.quiet = 1; + cgc.timeout = 3000*HZ; + cdi->ops->generic_packet(cdi, &cgc); + + cdi->media_written = 0; +} + static int cdrom_close_write(struct cdrom_device_info *cdi) { #if 0 @@ -898,6 +1006,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp) ret = open_for_data(cdi); if (ret) goto err; + cdrom_mmc3_profile(cdi); if (fp->f_mode & FMODE_WRITE) { ret = -EROFS; if (cdrom_open_write(cdi)) @@ -905,6 +1014,7 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp) if (!CDROM_CAN(CDC_RAM)) goto err; ret = 0; + cdi->media_written = 0; } } @@ -1096,6 +1206,8 @@ int cdrom_release(struct cdrom_device_info *cdi, struct file *fp) cdi->use_count--; if (cdi->use_count == 0) cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); + if (cdi->use_count == 0) + cdrom_dvd_rw_close_write(cdi); if (cdi->use_count == 0 && (cdo->capability & CDC_LOCK) && !keeplocked) { cdinfo(CD_CLOSE, "Unlocking door!\n"); @@ -1302,6 +1414,7 @@ int media_changed(struct cdrom_device_info *cdi, int queue) if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) { cdi->mc_flags = 0x3; /* set bit on both queues */ ret |= 1; + cdi->media_written = 0; } cdi->mc_flags &= ~mask; /* clear bit */ return ret; @@ -1763,7 +1876,7 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) s->manufact.len = buf[0] << 8 | buf[1]; if (s->manufact.len < 0 || s->manufact.len > 2048) { cdinfo(CD_WARNING, "Received invalid manufacture info length" - " (%d)\n", s->bca.len); + " (%d)\n", s->manufact.len); ret = -EIO; } else { memcpy(s->manufact.value, &buf[4], s->manufact.len); @@ -1922,7 +2035,8 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, int lba, int nframes) { struct packet_command cgc; - int nr, ret; + int ret = 0; + int nr; cdi->last_sense = 0; @@ -1944,8 +2058,8 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, return -ENOMEM; if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { - kfree(cgc.buffer); - return -EFAULT; + ret = -EFAULT; + goto out; } cgc.data_direction = CGC_DATA_READ; @@ -1956,13 +2070,17 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); if (ret) break; - __copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr); + if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { + ret = -EFAULT; + break; + } ubuf += CD_FRAMESIZE_RAW * nr; nframes -= nr; lba += nr; } +out: kfree(cgc.buffer); - return 0; + return ret; } static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, @@ -2504,7 +2622,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, struct cdrom_device_ops *cdo = cdi->ops; struct packet_command cgc; struct request_sense sense; - char buffer[32]; + unsigned char buffer[32]; int ret = 0; memset(&cgc, 0, sizeof(cgc)); @@ -2631,8 +2749,9 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMVOLCTRL: case CDROMVOLREAD: { struct cdrom_volctrl volctrl; - char mask[32]; + char mask[sizeof(buffer)]; unsigned short offset; + cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); IOCTL_IN(arg, struct cdrom_volctrl, volctrl); @@ -2642,17 +2761,27 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0))) return ret; - /* some drives have longer pages, adjust and reread. */ - if (buffer[1] > cgc.buflen) { - cgc.buflen = buffer[1] + 2; - if ((ret = cdrom_mode_sense(cdi, &cgc, - GPMODE_AUDIO_CTL_PAGE, 0))) - return ret; + /* originally the code depended on buffer[1] to determine + how much data is available for transfer. buffer[1] is + unfortunately ambigious and the only reliable way seem + to be to simply skip over the block descriptor... */ + offset = 8 + be16_to_cpu(*(unsigned short *)(buffer+6)); + + if (offset + 16 > sizeof(buffer)) + return -E2BIG; + + if (offset + 16 > cgc.buflen) { + cgc.buflen = offset+16; + ret = cdrom_mode_sense(cdi, &cgc, + GPMODE_AUDIO_CTL_PAGE, 0); + if (ret) + return ret; } - - /* get the offset from the length of the page. length - is measure from byte 2 an on, thus the 14. */ - offset = buffer[1] - 14; + + /* sanity check */ + if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || + buffer[offset+1] < 14) + return -EINVAL; /* now we have the current volume settings. if it was only a CDROMVOLREAD, return these values */ @@ -2677,7 +2806,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, buffer[offset+15] = volctrl.channel3 & mask[offset+15]; /* set volume */ - cgc.buffer = buffer; + cgc.buffer = buffer + offset - 8; + memset(cgc.buffer, 0, 8); return cdrom_mode_select(cdi, &cgc); } @@ -2760,7 +2890,7 @@ static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8 { struct cdrom_device_ops *cdo = cdi->ops; struct packet_command cgc; - int ret; + int ret, buflen; init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ); cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; @@ -2773,14 +2903,18 @@ static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8 if ((ret = cdo->generic_packet(cdi, &cgc))) return ret; - cgc.buflen = be16_to_cpu(ti->track_information_length) + + buflen = be16_to_cpu(ti->track_information_length) + sizeof(ti->track_information_length); - if (cgc.buflen > sizeof(track_information)) - cgc.buflen = sizeof(track_information); + if (buflen > sizeof(track_information)) + buflen = sizeof(track_information); - cgc.cmd[8] = cgc.buflen; - return cdo->generic_packet(cdi, &cgc); + cgc.cmd[8] = cgc.buflen = buflen; + if ((ret = cdo->generic_packet(cdi, &cgc))) + return ret; + + /* return actual fill size */ + return buflen; } /* requires CD R/RW */ @@ -2788,7 +2922,7 @@ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information * { struct cdrom_device_ops *cdo = cdi->ops; struct packet_command cgc; - int ret; + int ret, buflen; /* set up command and get the disc info */ init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ); @@ -2802,14 +2936,18 @@ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information * /* not all drives have the same disc_info length, so requeue * packet with the length the drive tells us it can supply */ - cgc.buflen = be16_to_cpu(di->disc_information_length) + + buflen = be16_to_cpu(di->disc_information_length) + sizeof(di->disc_information_length); - if (cgc.buflen > sizeof(disc_information)) - cgc.buflen = sizeof(disc_information); + if (buflen > sizeof(disc_information)) + buflen = sizeof(disc_information); - cgc.cmd[8] = cgc.buflen; - return cdo->generic_packet(cdi, &cgc); + cgc.cmd[8] = cgc.buflen = buflen; + if ((ret = cdo->generic_packet(cdi, &cgc))) + return ret; + + /* return actual fill size */ + return buflen; } /* return the last written block on the CD-R media. this is for the udf @@ -2820,27 +2958,37 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written) disc_information di; track_information ti; __u32 last_track; - int ret = -1; + int ret = -1, ti_size; if (!CDROM_CAN(CDC_GENERIC_PACKET)) goto use_toc; - if ((ret = cdrom_get_disc_info(cdi, &di))) + ret = cdrom_get_disc_info(cdi, &di); + if (ret < (int)(offsetof(typeof(di), last_track_lsb) + + sizeof(di.last_track_lsb))) goto use_toc; + /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */ last_track = (di.last_track_msb << 8) | di.last_track_lsb; - if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti))) + ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); + if (ti_size < (int)offsetof(typeof(ti), track_start)) goto use_toc; /* if this track is blank, try the previous. */ if (ti.blank) { - last_track--; - if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti))) + if (last_track==1) goto use_toc; + last_track--; + ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); } + if (ti_size < (int)(offsetof(typeof(ti), track_size) + + sizeof(ti.track_size))) + goto use_toc; + /* if last recorded field is valid, return it. */ - if (ti.lra_v) { + if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address) + + sizeof(ti.last_rec_address))) { *last_written = be32_to_cpu(ti.last_rec_address); } else { /* make it up instead */ @@ -2853,11 +3001,12 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written) /* this is where we end up if the drive either can't do a GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if - it fails. then we return the toc contents. */ + it doesn't give enough information or fails. then we return + the toc contents. */ use_toc: toc.cdte_format = CDROM_MSF; toc.cdte_track = CDROM_LEADOUT; - if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)) + if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))) return ret; sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA); *last_written = toc.cdte_addr.lba; @@ -2870,32 +3019,38 @@ static int cdrom_get_next_writable(struct cdrom_device_info *cdi, long *next_wri disc_information di; track_information ti; __u16 last_track; - int ret = -1; + int ret, ti_size; if (!CDROM_CAN(CDC_GENERIC_PACKET)) goto use_last_written; - if ((ret = cdrom_get_disc_info(cdi, &di))) + ret = cdrom_get_disc_info(cdi, &di); + if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb) + + sizeof(di.last_track_lsb)) goto use_last_written; + /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */ last_track = (di.last_track_msb << 8) | di.last_track_lsb; - if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti))) + ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); + if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start)) goto use_last_written; /* if this track is blank, try the previous. */ if (ti.blank) { + if (last_track == 1) + goto use_last_written; last_track--; - if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti))) + ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti); + if (ti_size < 0) goto use_last_written; } /* if next recordable address field is valid, use it. */ - if (ti.nwa_v) + if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable) + + sizeof(ti.next_writable)) { *next_writable = be32_to_cpu(ti.next_writable); - else - goto use_last_written; - - return 0; + return 0; + } use_last_written: if ((ret = cdrom_get_last_written(cdi, next_writable))) { @@ -3181,7 +3336,6 @@ ctl_table cdrom_cdrom_table[] = { /* Make sure that /proc/sys/dev is there */ ctl_table cdrom_root_table[] = { -#ifdef CONFIG_PROC_FS { .ctl_name = CTL_DEV, .procname = "dev", @@ -3189,7 +3343,6 @@ ctl_table cdrom_root_table[] = { .mode = 0555, .child = cdrom_cdrom_table, }, -#endif /* CONFIG_PROC_FS */ { .ctl_name = 0 } }; static struct ctl_table_header *cdrom_sysctl_header; diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index cbe336429..4a447b750 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -65,14 +65,6 @@ * This section describes features beyond the normal audio and CD-ROM * functions of the drive. * - * 2048 byte buffer mode - * - * If a disk is mounted with -o block=2048, data is copied straight - * from the drive data port to the buffer. Otherwise, the readahead - * buffer must be involved to hold the other 1K of data when a 1K - * block operation is done. Note that with 2048 byte blocks you - * cannot execute files from the CD. - * * XA compatibility * * The driver should support XA disks for both the CDU31A and CDU33A. @@ -147,6 +139,13 @@ * Removed init_module & cleanup_module in favor of * module_init & module_exit. * Torben Mathiasen + * + * 22 October 2004 -- Make the driver work in 2.6.X + * Added workaround to fix hard lockups on eject + * Fixed door locking problem after mounting empty drive + * Set double-speed drives to double speed by default + * Removed all readahead things - not needed anymore + * Ondrej Zary */ #include @@ -179,10 +178,9 @@ #define MAJOR_NR CDU31A_CDROM_MAJOR #include -#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */ #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10 -#define DEBUG 0 +#define DEBUG 1 /* Define the following if you have data corruption problems. */ #undef SONY_POLL_EACH_BYTE @@ -222,7 +220,7 @@ static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left /* The base I/O address of the Sony Interface. This is a variable (not a #define) so it can be easily changed via some future ioctl() */ static unsigned int cdu31a_port = 0; -MODULE_PARM(cdu31a_port, "i"); +module_param(cdu31a_port, uint, 0); /* * The following are I/O addresses of the various registers for the drive. The @@ -279,7 +277,6 @@ static struct task_struct *has_cd_task = NULL; /* The task that is currently NULL if none. */ static int is_double_speed = 0; /* does the drive support double speed ? */ -static int is_a_cdu31a = 1; /* Is the drive a CDU31A? */ static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */ @@ -301,7 +298,7 @@ static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 }; /* What IRQ is the drive using? 0 if none. */ static int cdu31a_irq = 0; -MODULE_PARM(cdu31a_irq, "i"); +module_param(cdu31a_irq, int, 0); /* The interrupt handler will wake this queue up when it gets an interrupts. */ @@ -314,12 +311,8 @@ static int curr_control_reg = 0; /* Current value of the control register */ it will be cleared. */ static char disk_changed; -/* Variable for using the readahead buffer. The readahead buffer - is used for raw sector reads and for blocksizes that are smaller - than 2048 bytes. */ -static char readahead_buffer[CD_FRAMESIZE_RAW]; -static int readahead_dataleft = 0; -static int readahead_bad = 0; +/* This was readahead_buffer once... Now it's used only for audio reads */ +static char audio_buffer[CD_FRAMESIZE_RAW]; /* Used to time a short period to abort an operation after the drive has been idle for a while. This keeps the light on @@ -440,7 +433,6 @@ static inline int is_result_reg_not_empty(void) static inline void reset_drive(void) { curr_control_reg = 0; - readahead_dataleft = 0; sony_toc_read = 0; outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg); } @@ -556,82 +548,47 @@ static unsigned char *translate_error(unsigned char err_code) static unsigned char errbuf[80]; switch (err_code) { - case 0x10: - return "illegal command "; - case 0x11: - return "illegal parameter "; - - case 0x20: - return "not loaded "; - case 0x21: - return "no disc "; - case 0x22: - return "not spinning "; - case 0x23: - return "spinning "; - case 0x25: - return "spindle servo "; - case 0x26: - return "focus servo "; - case 0x29: - return "eject mechanism "; - case 0x2a: - return "audio playing "; - case 0x2c: - return "emergency eject "; - - case 0x30: - return "focus "; - case 0x31: - return "frame sync "; - case 0x32: - return "subcode address "; - case 0x33: - return "block sync "; - case 0x34: - return "header address "; - - case 0x40: - return "illegal track read "; - case 0x41: - return "mode 0 read "; - case 0x42: - return "illegal mode read "; - case 0x43: - return "illegal block size read "; - case 0x44: - return "mode read "; - case 0x45: - return "form read "; - case 0x46: - return "leadout read "; - case 0x47: - return "buffer overrun "; - - case 0x53: - return "unrecoverable CIRC "; - case 0x57: - return "unrecoverable LECC "; - - case 0x60: - return "no TOC "; - case 0x61: - return "invalid subcode data "; - case 0x63: - return "focus on TOC read "; - case 0x64: - return "frame sync on TOC read "; - case 0x65: - return "TOC data "; - - case 0x70: - return "hardware failure "; - case 0x91: - return "leadin "; - case 0x92: - return "leadout "; - case 0x93: - return "data track "; + case 0x10: return "illegal command "; + case 0x11: return "illegal parameter "; + + case 0x20: return "not loaded "; + case 0x21: return "no disc "; + case 0x22: return "not spinning "; + case 0x23: return "spinning "; + case 0x25: return "spindle servo "; + case 0x26: return "focus servo "; + case 0x29: return "eject mechanism "; + case 0x2a: return "audio playing "; + case 0x2c: return "emergency eject "; + + case 0x30: return "focus "; + case 0x31: return "frame sync "; + case 0x32: return "subcode address "; + case 0x33: return "block sync "; + case 0x34: return "header address "; + + case 0x40: return "illegal track read "; + case 0x41: return "mode 0 read "; + case 0x42: return "illegal mode read "; + case 0x43: return "illegal block size read "; + case 0x44: return "mode read "; + case 0x45: return "form read "; + case 0x46: return "leadout read "; + case 0x47: return "buffer overrun "; + + case 0x53: return "unrecoverable CIRC "; + case 0x57: return "unrecoverable LECC "; + + case 0x60: return "no TOC "; + case 0x61: return "invalid subcode data "; + case 0x63: return "focus on TOC read "; + case 0x64: return "frame sync on TOC read "; + case 0x65: return "TOC data "; + + case 0x70: return "hardware failure "; + case 0x91: return "leadin "; + case 0x92: return "leadout "; + case 0x93: return "data track "; } sprintf(errbuf, "unknown 0x%02x ", err_code); return errbuf; @@ -696,8 +653,7 @@ static int scd_select_speed(struct cdrom_device_info *cdi, int speed) */ static int scd_lock_door(struct cdrom_device_info *cdi, int lock) { - if (lock == 0 && sony_usage == 1) { - /* Unlock the door, only if nobody is using the drive */ + if (lock == 0) { is_auto_eject = 1; } else { is_auto_eject = 0; @@ -729,8 +685,7 @@ static void restart_on_error(void) res_reg[1]); } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(2 * HZ); + msleep(2000); sony_get_toc(); } @@ -960,8 +915,7 @@ retry_cd_operation: if (((result_buffer[0] & 0xf0) == 0x20) && (num_retries < MAX_CDU31A_RETRIES)) { num_retries++; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ / 10); /* Wait .1 seconds on retries */ + msleep(100); goto retry_cd_operation; } @@ -1145,10 +1099,9 @@ static void size_to_buf(unsigned int size, unsigned char *buf) operation if the requested sector is not the next one from the drive. */ static int -start_request(unsigned int sector, unsigned int nsect, int read_nsect_only) +start_request(unsigned int sector, unsigned int nsect) { unsigned char params[6]; - unsigned int read_size; unsigned long retry_count; @@ -1156,22 +1109,7 @@ start_request(unsigned int sector, unsigned int nsect, int read_nsect_only) printk("Entering start_request\n"); #endif log_to_msf(sector, params); - /* If requested, read exactly what was asked. */ - if (read_nsect_only) { - read_size = nsect; - } - /* - * If the full read-ahead would go beyond the end of the media, trim - * it back to read just till the end of the media. - */ - else if ((sector + nsect) >= sony_toc.lead_out_start_lba) { - read_size = sony_toc.lead_out_start_lba - sector; - } - /* Read the full readahead amount. */ - else { - read_size = CDU31A_READAHEAD / 4; - } - size_to_buf(read_size, ¶ms[3]); + size_to_buf(nsect, ¶ms[3]); /* * Clear any outstanding attentions and wait for the drive to @@ -1200,10 +1138,8 @@ start_request(unsigned int sector, unsigned int nsect, int read_nsect_only) write_params(params, 6); write_cmd(SONY_READ_BLKERR_STAT_CMD); - sony_blocks_left = read_size * 4; + sony_blocks_left = nsect * 4; sony_next_block = sector * 4; - readahead_dataleft = 0; - readahead_bad = 0; #if DEBUG printk("Leaving start_request at %d\n", __LINE__); #endif @@ -1214,8 +1150,7 @@ start_request(unsigned int sector, unsigned int nsect, int read_nsect_only) #endif } -/* Abort a pending read operation. Clear all the drive status and - readahead variables. */ +/* Abort a pending read operation. Clear all the drive status variables. */ static void abort_read(void) { unsigned char result_reg[2]; @@ -1240,8 +1175,6 @@ static void abort_read(void) } sony_blocks_left = 0; - readahead_dataleft = 0; - readahead_bad = 0; } /* Called when the timer times out. This will abort the @@ -1266,8 +1199,6 @@ static void handle_abort_timeout(unsigned long data) write_cmd(SONY_ABORT_CMD); sony_blocks_left = 0; - readahead_dataleft = 0; - readahead_bad = 0; abort_read_started = 1; } restore_flags(flags); @@ -1276,60 +1207,30 @@ static void handle_abort_timeout(unsigned long data) #endif } -/* Actually get data and status from the drive. */ +/* Actually get one sector of data from the drive. */ static void -input_data(char *buffer, - unsigned int bytesleft, - unsigned int nblocks, unsigned int offset, unsigned int skip) +input_data_sector(char *buffer) { - int i; - volatile unsigned char val; - - #if DEBUG - printk("Entering input_data\n"); + printk("Entering input_data_sector\n"); #endif + /* If an XA disk on a CDU31A, skip the first 12 bytes of data from - the disk. The real data is after that. */ - if (sony_xa_mode) { - for (i = 0; i < CD_XA_HEAD; i++) { - val = read_data_register(); - } - } + the disk. The real data is after that. We can use audio_buffer. */ + if (sony_xa_mode) + insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD); clear_data_ready(); - if (bytesleft == 2048) { /* 2048 byte direct buffer transfer */ - insb(sony_cd_read_reg, buffer, 2048); - readahead_dataleft = 0; - } else { - /* If the input read did not align with the beginning of the block, - skip the necessary bytes. */ - if (skip != 0) { - insb(sony_cd_read_reg, readahead_buffer, skip); - } - - /* Get the data into the buffer. */ - insb(sony_cd_read_reg, &buffer[offset], bytesleft); - - /* Get the rest of the data into the readahead buffer at the - proper location. */ - readahead_dataleft = (2048 - skip) - bytesleft; - insb(sony_cd_read_reg, - readahead_buffer + bytesleft, readahead_dataleft); - } - sony_blocks_left -= nblocks; - sony_next_block += nblocks; + insb(sony_cd_read_reg, buffer, 2048); /* If an XA disk, we have to clear out the rest of the unused - error correction data. */ - if (sony_xa_mode) { - for (i = 0; i < CD_XA_TAIL; i++) { - val = read_data_register(); - } - } + error correction data. We can use audio_buffer for that. */ + if (sony_xa_mode) + insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL); + #if DEBUG - printk("Leaving input_data at %d\n", __LINE__); + printk("Leaving input_data_sector\n"); #endif } @@ -1341,10 +1242,6 @@ read_data_block(char *buffer, unsigned char res_reg[], int *res_size) { unsigned long retry_count; - unsigned int bytesleft; - unsigned int offset; - unsigned int skip; - #if DEBUG printk("Entering read_data_block\n"); @@ -1353,67 +1250,6 @@ read_data_block(char *buffer, res_reg[0] = 0; res_reg[1] = 0; *res_size = 0; - bytesleft = nblocks * 512; - offset = 0; - - /* If the data in the read-ahead does not match the block offset, - then fix things up. */ - if (((block % 4) * 512) != ((2048 - readahead_dataleft) % 2048)) { - sony_next_block += block % 4; - sony_blocks_left -= block % 4; - skip = (block % 4) * 512; - } else { - skip = 0; - } - - /* We have readahead data in the buffer, get that first before we - decide if a read is necessary. */ - if (readahead_dataleft != 0) { - if (bytesleft > readahead_dataleft) { - /* The readahead will not fill the requested buffer, but - get the data out of the readahead into the buffer. */ - memcpy(buffer, - readahead_buffer + (2048 - - readahead_dataleft), - readahead_dataleft); - bytesleft -= readahead_dataleft; - offset += readahead_dataleft; - readahead_dataleft = 0; - } else { - /* The readahead will fill the whole buffer, get the data - and return. */ - memcpy(buffer, - readahead_buffer + (2048 - - readahead_dataleft), - bytesleft); - readahead_dataleft -= bytesleft; - bytesleft = 0; - sony_blocks_left -= nblocks; - sony_next_block += nblocks; - - /* If the data in the readahead is bad, return an error so the - driver will abort the buffer. */ - if (readahead_bad) { - res_reg[0] = 0x20; - res_reg[1] = SONY_BAD_DATA_ERR; - *res_size = 2; - } - - if (readahead_dataleft == 0) { - readahead_bad = 0; - } - - /* Final transfer is done for read command, get final result. */ - if (sony_blocks_left == 0) { - get_result(res_reg, res_size); - } -#if DEBUG - printk("Leaving read_data_block at %d\n", - __LINE__); -#endif - return; - } - } /* Wait for the drive to tell us we have something */ retry_count = jiffies + SONY_JIFFIES_TIMEOUT; @@ -1444,7 +1280,9 @@ read_data_block(char *buffer, abort_read(); } } else { - input_data(buffer, bytesleft, nblocks, offset, skip); + input_data_sector(buffer); + sony_blocks_left -= nblocks; + sony_next_block += nblocks; /* Wait for the status from the drive. */ retry_count = jiffies + SONY_JIFFIES_TIMEOUT; @@ -1475,16 +1313,7 @@ read_data_block(char *buffer, SONY_NO_LECC_ERR_BLK_STAT) || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)) { - /* The data was successful, but if data was read from - the readahead and it was bad, set the whole - buffer as bad. */ - if (readahead_bad) { - readahead_bad = 0; - res_reg[0] = 0x20; - res_reg[1] = - SONY_BAD_DATA_ERR; - *res_size = 2; - } + /* nothing here */ } else { printk ("CDU31A: Data block error: 0x%x\n", @@ -1492,12 +1321,6 @@ read_data_block(char *buffer, res_reg[0] = 0x20; res_reg[1] = SONY_BAD_DATA_ERR; *res_size = 2; - - /* Data is in the readahead buffer but an error was returned. - Make sure future requests don't use the data. */ - if (bytesleft != 2048) { - readahead_bad = 1; - } } /* Final transfer is done for read command, get final result. */ @@ -1533,11 +1356,9 @@ read_data_block(char *buffer, static void do_cdu31a_request(request_queue_t * q) { struct request *req; - int block; - int nblock; + int block, nblock, num_retries; unsigned char res_reg[12]; unsigned int res_size; - int num_retries; unsigned long flags; @@ -1593,7 +1414,10 @@ static void do_cdu31a_request(request_queue_t * q) block = req->sector; nblock = req->nr_sectors; - +#if DEBUG + printk("CDU31A: request at block %d, length %d blocks\n", + block, nblock); +#endif if (!sony_toc_read) { printk("CDU31A: TOC not read\n"); end_request(req, 0); @@ -1613,17 +1437,14 @@ static void do_cdu31a_request(request_queue_t * q) * If the block address is invalid or the request goes beyond the end of * the media, return an error. */ - if ((block / 4) >= sony_toc.lead_out_start_lba) { - printk("CDU31A: Request past end of media\n"); - end_request(req, 0); - continue; - } if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) { printk("CDU31A: Request past end of media\n"); end_request(req, 0); continue; } + if (nblock > 4) + nblock = 4; num_retries = 0; try_read_again: @@ -1638,7 +1459,7 @@ static void do_cdu31a_request(request_queue_t * q) /* If no data is left to be read from the drive, start the next request. */ if (sony_blocks_left == 0) { - if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) { + if (start_request(block / 4, nblock / 4)) { end_request(req, 0); continue; } @@ -1657,7 +1478,7 @@ static void do_cdu31a_request(request_queue_t * q) end_request(req, 0); continue; } - if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) { + if (start_request(block / 4, nblock / 4)) { printk("CDU31a: start request failed\n"); end_request(req, 0); continue; @@ -1667,7 +1488,12 @@ static void do_cdu31a_request(request_queue_t * q) read_data_block(req->buffer, block, nblock, res_reg, &res_size); if (res_reg[0] != 0x20) { - end_request(req, 1); + if (!end_that_request_first(req, 1, nblock)) { + spin_lock_irq(q->queue_lock); + blkdev_dequeue_request(req); + end_that_request_last(req); + spin_unlock_irq(q->queue_lock); + } continue; } @@ -1776,7 +1602,7 @@ static void sony_get_toc(void) /* This seems to slow things down enough to make it work. This * appears to be a problem in do_sony_cd_cmd. This printk seems * to address the symptoms... -Erik */ -#if 1 +#if DEBUG printk("cdu31a: Trying session %d\n", session); #endif parms[0] = session; @@ -2531,8 +2357,7 @@ static int read_audio(struct cdrom_read_audio *ra) return. */ retval = 0; - /* start_request clears out any readahead data, so it should be safe. */ - if (start_request(ra->addr.lba, ra->nframes, 1)) { + if (start_request(ra->addr.lba, ra->nframes)) { retval = -EIO; goto exit_read_audio; } @@ -2540,7 +2365,7 @@ static int read_audio(struct cdrom_read_audio *ra) /* For every requested frame. */ cframe = 0; while (cframe < ra->nframes) { - read_audio_data(readahead_buffer, res_reg, &res_size); + read_audio_data(audio_buffer, res_reg, &res_size); if ((res_reg[0] & 0xf0) == 0x20) { if (res_reg[1] == SONY_BAD_DATA_ERR) { printk @@ -2569,7 +2394,7 @@ static int read_audio(struct cdrom_read_audio *ra) /* Restart the request on the current frame. */ if (start_request (ra->addr.lba + cframe, - ra->nframes - cframe, 1)) { + ra->nframes - cframe)) { retval = -EIO; goto exit_read_audio; } @@ -2577,7 +2402,7 @@ static int read_audio(struct cdrom_read_audio *ra) /* Don't go back to the top because don't want to get into and infinite loop. A lot of code gets duplicated, but that's no big deal, I don't guess. */ - read_audio_data(readahead_buffer, res_reg, + read_audio_data(audio_buffer, res_reg, &res_size); if ((res_reg[0] & 0xf0) == 0x20) { if (res_reg[1] == @@ -2598,7 +2423,7 @@ static int read_audio(struct cdrom_read_audio *ra) } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe), - readahead_buffer, + audio_buffer, CD_FRAMESIZE_RAW)) { retval = -EFAULT; goto exit_read_audio; @@ -2612,7 +2437,7 @@ static int read_audio(struct cdrom_read_audio *ra) goto exit_read_audio; } } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe), - (char *)readahead_buffer, + (char *)audio_buffer, CD_FRAMESIZE_RAW)) { retval = -EFAULT; goto exit_read_audio; @@ -3063,12 +2888,18 @@ static int scd_spinup(void) * Open the drive for operations. Spin the drive up and read the table of * contents if these have not already been done. */ -static int scd_open(struct cdrom_device_info *cdi, int openmode) +static int scd_open(struct cdrom_device_info *cdi, int purpose) { unsigned char res_reg[12]; unsigned int res_size; unsigned char params[2]; + if (purpose == 1) { + /* Open for IOCTLs only - no media check */ + sony_usage++; + return 0; + } + if (sony_usage == 0) { if (scd_spinup() != 0) return -EIO; @@ -3153,8 +2984,7 @@ static struct cdrom_device_ops scd_dops = { .dev_ioctl = scd_dev_ioctl, .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | - CDC_MULTI_SESSION | CDC_MCN | - CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | + CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, .n_minors = 1, }; @@ -3179,7 +3009,19 @@ static int scd_block_release(struct inode *inode, struct file *file) static int scd_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, unsigned long arg) { - return cdrom_ioctl(file, &scd_info, inode, cmd, arg); + /* The eject and close commands should be handled by Uniform CD-ROM + * driver - but I always got hard lockup instead of eject + * until I put this here. + */ + switch (cmd) { + case CDROMEJECT: + scd_lock_door(&scd_info, 0); + return scd_tray_move(&scd_info, 1); + case CDROMCLOSETRAY: + return scd_tray_move(&scd_info, 0); + default: + return cdrom_ioctl(file, &scd_info, inode, cmd, arg); + } } static int scd_block_media_changed(struct gendisk *disk) @@ -3374,6 +3216,7 @@ int __init cdu31a_init(void) tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ cdu31a_irq = 0; + sony_speed = is_double_speed; /* Set 2X drives to 2X by default */ set_drive_params(sony_speed); cdu31a_irq = tmp_irq; @@ -3419,13 +3262,12 @@ int __init cdu31a_init(void) strcat(msg, buf); } strcat(msg, "\n"); - - is_a_cdu31a = - strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; - + printk("%s",msg); + cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock); if (!cdu31a_queue) goto errout0; + blk_queue_hardsect_size(cdu31a_queue, 2048); init_timer(&cdu31a_abort_timer); cdu31a_abort_timer.function = handle_abort_timeout; diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h index a04d0b3a2..61d4768c4 100644 --- a/drivers/cdrom/cdu31a.h +++ b/drivers/cdrom/cdu31a.h @@ -72,10 +72,10 @@ from drive (in 1/100th's of seconds). */ -#define SONY_JIFFIES_TIMEOUT 1000 /* Maximum number of times the +#define SONY_JIFFIES_TIMEOUT (10*HZ) /* Maximum number of times the drive will wait/try for an operation */ -#define SONY_RESET_TIMEOUT 100 /* Maximum number of times the +#define SONY_RESET_TIMEOUT HZ /* Maximum number of times the drive will wait/try a reset operation */ #define SONY_READY_RETRIES 20000 /* How many times to retry a diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index 4cb0fb491..b4f5e0295 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -1021,10 +1021,9 @@ static int mcd_open(struct cdrom_device_info *cdi, int purpose) st = statusCmd(); /* check drive status */ if (st == -1) goto err_out; /* drive doesn't respond */ - if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ); - } + if ((st & MST_READY) == 0) /* no disk? wait a sec... */ + msleep(1000); + } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); if (updateToc() < 0) diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 884674959..8b4a2d4eb 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -1161,11 +1161,11 @@ static void EvaluateStatus(int st) return; } /*==========================================================================*/ +static int cmd_out_T(void); + static int get_state_T(void) { int i; - - static int cmd_out_T(void); clr_cmdbuf(); current_drive->n_bytes=1; @@ -1308,13 +1308,14 @@ static int cc_ReadError(void) return (i); } /*==========================================================================*/ +static int cc_DriveReset(void); + static int cmd_out_T(void) { #undef CMDT_TRIES #define CMDT_TRIES 1000 #define TEST_FALSE_FF 1 - - static int cc_DriveReset(void); + int i, j, l=0, m, ntries; unsigned long flags; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 3a2acc0fb..dde8bfed9 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -121,7 +121,10 @@ struct capability_entry { }; static struct capability_entry capability_table[] __initdata = { - { "6330", CDC_LOCK | CDC_DVD_RAM }, + { "6330", CDC_LOCK | CDC_DVD_RAM | CDC_RAM }, + { "6331", CDC_LOCK | CDC_DVD_RAM | CDC_RAM }, + { "6333", CDC_LOCK | CDC_DVD_RAM | CDC_RAM }, + { "632A", CDC_LOCK | CDC_DVD_RAM | CDC_RAM }, { "6321", CDC_LOCK }, { "632B", 0 }, { NULL , CDC_LOCK }, @@ -151,7 +154,6 @@ static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; #define DEVICE_NR(di) ((di) - &viocd_diskinfo[0]) -static request_queue_t *viocd_queue; static spinlock_t viocd_reqlock; #define MAX_CD_REQ 1 @@ -332,10 +334,19 @@ static int send_request(struct request *req) struct disk_info *diskinfo = req->rq_disk->private_data; u64 len; dma_addr_t dmaaddr; + int direction; + u16 cmd; struct scatterlist sg; BUG_ON(req->nr_phys_segments > 1); - BUG_ON(rq_data_dir(req) != READ); + + if (rq_data_dir(req) == READ) { + direction = DMA_FROM_DEVICE; + cmd = viomajorsubtype_cdio | viocdread; + } else { + direction = DMA_TO_DEVICE; + cmd = viomajorsubtype_cdio | viocdwrite; + } if (blk_rq_map_sg(req->q, req, &sg) == 0) { printk(VIOCD_KERN_WARNING @@ -343,7 +354,7 @@ static int send_request(struct request *req) return -1; } - if (dma_map_sg(diskinfo->dev, &sg, 1, DMA_FROM_DEVICE) == 0) { + if (dma_map_sg(diskinfo->dev, &sg, 1, direction) == 0) { printk(VIOCD_KERN_WARNING "error allocating sg tce\n"); return -1; } @@ -351,8 +362,7 @@ static int send_request(struct request *req) len = sg_dma_len(&sg); hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_cdio | viocdread, + HvLpEvent_Type_VirtualIo, cmd, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, viopath_sourceinst(viopath_hostLp), @@ -457,6 +467,53 @@ static int viocd_lock_door(struct cdrom_device_info *cdi, int locking) return 0; } +static int viocd_packet(struct cdrom_device_info *cdi, + struct packet_command *cgc) +{ + unsigned int buflen = cgc->buflen; + int ret = -EIO; + + switch (cgc->cmd[0]) { + case GPCMD_READ_DISC_INFO: + { + disc_information *di = (disc_information *)cgc->buffer; + + if (buflen >= 2) { + di->disc_information_length = cpu_to_be16(1); + ret = 0; + } + if (buflen >= 3) + di->erasable = + (cdi->ops->capability & ~cdi->mask + & (CDC_DVD_RAM | CDC_RAM)) != 0; + } + break; + default: + if (cgc->sense) { + /* indicate Unknown code */ + cgc->sense->sense_key = 0x05; + cgc->sense->asc = 0x20; + cgc->sense->ascq = 0x00; + } + break; + } + + cgc->stat = ret; + return ret; +} + +static void restart_all_queues(int first_index) +{ + int i; + + for (i = first_index + 1; i < viocd_numdev; i++) + if (viocd_diskinfo[i].viocd_disk) + blk_run_queue(viocd_diskinfo[i].viocd_disk->queue); + for (i = 0; i <= first_index; i++) + if (viocd_diskinfo[i].viocd_disk) + blk_run_queue(viocd_diskinfo[i].viocd_disk->queue); +} + /* This routine handles incoming CD LP events */ static void vio_handle_cd_event(struct HvLpEvent *event) { @@ -486,7 +543,7 @@ static void vio_handle_cd_event(struct HvLpEvent *event) case viocdopen: if (event->xRc == 0) { di = &viocd_diskinfo[bevent->disk]; - blk_queue_hardsect_size(viocd_queue, + blk_queue_hardsect_size(di->viocd_disk->queue, bevent->block_size); set_capacity(di->viocd_disk, bevent->media_size * @@ -510,6 +567,7 @@ return_complete: case viocdclose: break; + case viocdwrite: case viocdread: /* * Since this is running in interrupt mode, we need to @@ -518,7 +576,8 @@ return_complete: di = &viocd_diskinfo[bevent->disk]; spin_lock_irqsave(&viocd_reqlock, flags); dma_unmap_single(di->dev, bevent->token, bevent->len, - DMA_FROM_DEVICE); + ((event->xSubtype & VIOMINOR_SUBTYPE_MASK) == viocdread) + ? DMA_FROM_DEVICE : DMA_TO_DEVICE); req = (struct request *)bevent->event.xCorrelationToken; rwreq--; @@ -536,7 +595,7 @@ return_complete: /* restart handling of incoming requests */ spin_unlock_irqrestore(&viocd_reqlock, flags); - blk_run_queue(viocd_queue); + restart_all_queues(bevent->disk); break; default: @@ -555,7 +614,8 @@ static struct cdrom_device_ops viocd_dops = { .release = viocd_release, .media_changed = viocd_media_changed, .lock_door = viocd_lock_door, - .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM + .generic_packet = viocd_packet, + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM }; static int __init find_capability(const char *type) @@ -575,6 +635,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) struct disk_info *d; struct cdrom_device_info *c; struct cdrom_info *ci; + struct request_queue *q; deviceno = vdev->unit_address; if (deviceno >= viocd_numdev) @@ -594,17 +655,22 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) if (register_cdrom(c) != 0) { printk(VIOCD_KERN_WARNING "Cannot register viocd CD-ROM %s!\n", c->name); - return 0; + goto out; } printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " "type %4.4s, model %3.3s\n", c->name, ci->rsrcname, ci->type, ci->model); + q = blk_init_queue(do_viocd_request, &viocd_reqlock); + if (q == NULL) { + printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", + c->name); + goto out_unregister_cdrom; + } gendisk = alloc_disk(1); if (gendisk == NULL) { printk(VIOCD_KERN_WARNING "Cannot create gendisk for %s!\n", c->name); - unregister_cdrom(c); - return 0; + goto out_cleanup_queue; } gendisk->major = VIOCD_MAJOR; gendisk->first_minor = deviceno; @@ -612,7 +678,10 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) sizeof(gendisk->disk_name)); snprintf(gendisk->devfs_name, sizeof(gendisk->devfs_name), VIOCD_DEVICE_DEVFS "%d", deviceno); - gendisk->queue = viocd_queue; + blk_queue_max_hw_segments(q, 1); + blk_queue_max_phys_segments(q, 1); + blk_queue_max_sectors(q, 4096 / 512); + gendisk->queue = q; gendisk->fops = &viocd_fops; gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE; set_capacity(gendisk, 0); @@ -621,8 +690,14 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) d->dev = &vdev->dev; gendisk->driverfs_dev = d->dev; add_disk(gendisk); - return 0; + +out_cleanup_queue: + blk_cleanup_queue(q); +out_unregister_cdrom: + unregister_cdrom(c); +out: + return -ENODEV; } static int viocd_remove(struct vio_dev *vdev) @@ -634,6 +709,7 @@ static int viocd_remove(struct vio_dev *vdev) "Cannot unregister viocd CD-ROM %s!\n", d->viocd_info.name); del_gendisk(d->viocd_disk); + blk_cleanup_queue(d->viocd_disk->queue); put_disk(d->viocd_disk); return 0; } @@ -693,18 +769,10 @@ static int __init viocd_init(void) goto out_undo_vio; spin_lock_init(&viocd_reqlock); - viocd_queue = blk_init_queue(do_viocd_request, &viocd_reqlock); - if (viocd_queue == NULL) { - ret = -ENOMEM; - goto out_free_info; - } - blk_queue_max_hw_segments(viocd_queue, 1); - blk_queue_max_phys_segments(viocd_queue, 1); - blk_queue_max_sectors(viocd_queue, 4096 / 512); ret = vio_register_driver(&viocd_driver); if (ret) - goto out_cleanup_queue; + goto out_free_info; e = create_proc_entry("iSeries/viocd", S_IFREG|S_IRUGO, NULL); if (e) { @@ -714,8 +782,6 @@ static int __init viocd_init(void) return 0; -out_cleanup_queue: - blk_cleanup_queue(viocd_queue); out_free_info: dma_free_coherent(iSeries_vio_dev, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, @@ -732,7 +798,6 @@ static void __exit viocd_exit(void) { remove_proc_entry("iSeries/viocd", NULL); vio_unregister_driver(&viocd_driver); - blk_cleanup_queue(viocd_queue); if (viocd_unitinfo != NULL) dma_free_coherent(iSeries_vio_dev, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 37e067351..e98239d94 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -59,7 +59,7 @@ config VT_CONSOLE config HW_CONSOLE bool - depends on VT && !S390 && !UM + depends on VT && !S390 && !USERMODE default y config SERIAL_NONSTANDARD @@ -192,7 +192,7 @@ config MOXA_INTELLIO config MOXA_SMARTIO tristate "Moxa SmartIO support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP + depends on SERIAL_NONSTANDARD help Say Y here if you have a Moxa SmartIO multiport serial card. @@ -424,6 +424,14 @@ config A2232 will also be built as a module. This has to be loaded before "ser_a2232". If you want to do this, answer M here. +config SGI_SNSC + bool "SGI Altix system controller communication support" + depends on (IA64_SGI_SN2 || IA64_GENERIC) + help + If you have an SGI Altix and you want to enable system + controller communication from user space (you want this!), + say Y. Otherwise, say N. + source "drivers/serial/Kconfig" config UNIX98_PTYS @@ -470,6 +478,7 @@ config LEGACY_PTYS config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" depends on LEGACY_PTYS + range 1 256 default "256" ---help--- The maximum number of legacy PTYs that can be used at any one time. @@ -587,39 +596,6 @@ config HVCS which will also be compiled when this driver is built as a module. -config QIC02_TAPE - tristate "QIC-02 tape support" - help - If you have a non-SCSI tape drive like that, say Y. - - To compile this driver as a module, choose M here: the - module will be called tpqic02. - -config QIC02_DYNCONF - bool "Do you want runtime configuration for QIC-02" - depends on QIC02_TAPE - help - You can either configure this driver once and for all by editing a - header file (), in which case you - should say N, or you can fetch a program via anonymous FTP which is - able to configure this driver during runtime. The program to do - this is called 'qic02conf' and it is part of the - tpqic02-support-X.Y.tar.gz support package. - - If you want to use the qic02conf program, say Y. - -comment "Edit configuration parameters in ./include/linux/tpqic02.h!" - depends on QIC02_TAPE && !QIC02_DYNCONF - -comment "Setting runtime QIC-02 configuration is done with qic02conf" - depends on QIC02_TAPE && QIC02_DYNCONF - -comment "from the tpqic02-support package. It is available at" - depends on QIC02_TAPE && QIC02_DYNCONF - -comment "metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/" - depends on QIC02_TAPE && QIC02_DYNCONF - source "drivers/char/ipmi/Kconfig" source "drivers/char/watchdog/Kconfig" @@ -778,7 +754,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 + depends on RTC!=y && !IA64 && !ARM ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -805,6 +781,23 @@ config EFI_RTC bool "EFI Real Time Clock Services" depends on IA64 +config DS1302 + tristate "DS1302 RTC support" + depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT) + help + If you say Y here and create a character special file /dev/rtc with + major number 121 and minor number 0 using mknod ("man mknod"), you + will get access to the real time clock (or hardware clock) built + into your computer. + +config S3C2410_RTC + bool "S3C2410 RTC Driver" + depends on ARCH_S3C2410 + help + RTC (Realtime Clock) driver for the clock inbuilt into the + Samsung S3C2410. This can provide periodic interrupt rates + from 1Hz to 64Hz for user programs, and wakeup from Alarm. + config COBALT_LCD bool "Support for Cobalt LCD" depends on MIPS_COBALT @@ -851,7 +844,7 @@ config APPLICOM config SONYPI tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" - depends on EXPERIMENTAL && X86 && PCI && !64BIT + depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT ---help--- This driver enables access to the Sony Programmable I/O Control Device which can be found in many (all ?) Sony Vaio laptops. @@ -1006,5 +999,13 @@ config HANGCHECK_TIMER out to lunch past a certain margin. It can reboot the system or merely print a warning. +config MMTIMER + tristate "MMTIMER Memory mapped RTC for SGI Altix" + depends on IA64_GENERIC || IA64_SGI_SN2 + default y + help + The mmtimer device allows direct userspace access to the + Altix system timer. + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index b927c16bb..1cbbaabda 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -7,8 +7,11 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o +obj-$(CONFIG_LEGACY_PTYS) += pty.o +obj-$(CONFIG_UNIX98_PTYS) += pty.o +obj-y += misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o @@ -39,8 +42,10 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o -obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o +obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o +obj-$(CONFIG_SGI_SNSC) += snsc.o +obj-$(CONFIG_MMTIMER) += mmtimer.o obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o @@ -58,6 +63,8 @@ obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o obj-$(CONFIG_SGI_DS1286) += ds1286.o obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o +obj-$(CONFIG_DS1302) += ds1302.o +obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) obj-$(CONFIG_NVRAM) += generic_nvram.o else diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 773279d48..d9b4a6e7f 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -1,5 +1,5 @@ config AGP - tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K + tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K && !ARM default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to @@ -130,7 +130,7 @@ config AGP_VIA depends on AGP && X86 && !X86_64 help This option gives you AGP support for the GLX component of - XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + XFree86 4.x on VIA MVP3/Apollo Pro chipsets. 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. diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 2128374e7..f83e3e342 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -123,7 +123,7 @@ struct agp_bridge_data { void *current_size; void *dev_private_data; struct pci_dev *dev; - u32 *gatt_table; + u32 __iomem *gatt_table; u32 *gatt_table_real; unsigned long scratch_page; unsigned long scratch_page_real; diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index f1db2f86a..a45d36c3b 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -24,11 +24,11 @@ static struct pci_device_id agp_amdk7_pci_table[]; struct amd_page_map { unsigned long *real; - unsigned long *remapped; + unsigned long __iomem *remapped; }; static struct _amd_irongate_private { - volatile u8 *registers; + volatile u8 __iomem *registers; struct amd_page_map **gatt_pages; int num_tables; } amd_irongate_private; @@ -54,7 +54,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) global_cache_flush(); for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) - page_map->remapped[i] = agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, page_map->remapped+i); return 0; } @@ -151,7 +151,7 @@ static int amd_create_gatt_table(void) } agp_bridge->gatt_table_real = (u32 *)page_dir.real; - agp_bridge->gatt_table = (u32 *)page_dir.remapped; + agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); /* Get the address for the gart region. @@ -165,9 +165,8 @@ static int amd_create_gatt_table(void) /* Calculate the agp offset */ for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = - virt_to_phys(amd_irongate_private.gatt_pages[i]->real); - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1, + page_dir.remapped+GET_PAGE_DIR_OFF(addr)); } return 0; @@ -178,7 +177,7 @@ static int amd_free_gatt_table(void) struct amd_page_map page_dir; page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; - page_dir.remapped = (unsigned long *)agp_bridge->gatt_table; + page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; amd_free_gatt_pages(); amd_free_page_map(&page_dir); @@ -218,7 +217,7 @@ static int amd_irongate_configure(void) /* Get the memory mapped registers */ pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp); temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); - amd_irongate_private.registers = (volatile u8 *) ioremap(temp, 4096); + amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); /* Write out the address of the gatt table */ OUTREG32(amd_irongate_private.registers, AMD_ATTBASE, @@ -263,7 +262,7 @@ static void amd_irongate_cleanup(void) pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp); temp = ((temp & ~(0x0000000f)) | previous_size->size_value); pci_write_config_dword(agp_bridge->dev, AMD_APSIZE, temp); - iounmap((void *) amd_irongate_private.registers); + iounmap((void __iomem *) amd_irongate_private.registers); } /* @@ -282,7 +281,7 @@ static void amd_irongate_tlbflush(struct agp_memory *temp) static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; @@ -297,7 +296,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) + if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr)))) return -EBUSY; j++; } @@ -310,8 +309,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - agp_generic_mask_memory(mem->memory[i], mem->type); + writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); } amd_irongate_tlbflush(mem); return 0; @@ -320,7 +318,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { int i; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; if (type != 0 || mem->type != 0) @@ -329,8 +327,7 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - (unsigned long) agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); } amd_irongate_tlbflush(mem); diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 924ffc3db..2e8b2aee9 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -73,7 +73,7 @@ static void amd64_tlbflush(struct agp_memory *temp) static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; - long tmp; + long long tmp; u32 pte; num_entries = agp_num_entries(); @@ -90,7 +90,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) /* gatt table should be empty. */ while (j < (pg_start + mem->page_count)) { - if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) + if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) return -EBUSY; j++; } @@ -108,7 +108,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) pte |=(tmp & 0x00000000fffff000ULL); pte |= GPTE_VALID | GPTE_COHERENT; - agp_bridge->gatt_table[j] = pte; + writel(pte, agp_bridge->gatt_table+j); } amd64_tlbflush(mem); return 0; @@ -675,4 +675,4 @@ module_exit(agp_amd64_cleanup); MODULE_AUTHOR("Dave Jones , Andi Kleen"); MODULE_PARM(agp_try_unsupported, "1i"); -MODULE_LICENSE("GPL and additional rights"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index bc88d6991..8bf71c182 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -42,11 +42,11 @@ static struct gatt_mask ati_generic_masks[] = typedef struct _ati_page_map { unsigned long *real; - unsigned long *remapped; + unsigned long __iomem *remapped; } ati_page_map; static struct _ati_generic_private { - volatile u8 *registers; + volatile u8 __iomem *registers; ati_page_map **gatt_pages; int num_tables; } ati_generic_private; @@ -76,7 +76,7 @@ static int ati_create_page_map(ati_page_map *page_map) global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) - page_map->remapped[i] = agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, page_map->remapped+i); return 0; } @@ -206,7 +206,7 @@ static void ati_cleanup(void) temp = ((temp & ~(0x0000000f)) | previous_size->size_value); pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp); } - iounmap((void *) ati_generic_private.registers); + iounmap((volatile u8 __iomem *)ati_generic_private.registers); } @@ -217,7 +217,7 @@ static int ati_configure(void) /* Get the memory mapped registers */ pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp); temp = (temp & 0xfffff000); - ati_generic_private.registers = (volatile u8 *) ioremap(temp, 4096); + ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); if (is_r200()) pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000); @@ -261,7 +261,7 @@ static int ati_insert_memory(struct agp_memory * mem, off_t pg_start, int type) { int i, j, num_entries; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; @@ -276,7 +276,7 @@ static int ati_insert_memory(struct agp_memory * mem, while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - if (!PGE_EMPTY(agp_bridge,cur_gatt[GET_GATT_OFF(addr)])) + if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr)))) return -EBUSY; j++; } @@ -290,8 +290,7 @@ static int ati_insert_memory(struct agp_memory * mem, for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->driver->mask_memory(mem->memory[i], mem->type); + writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); } agp_bridge->driver->tlb_flush(mem); return 0; @@ -301,7 +300,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, int type) { int i; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; if (type != 0 || mem->type != 0) { @@ -310,8 +309,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - (unsigned long) agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); } agp_bridge->driver->tlb_flush(mem); @@ -340,7 +338,7 @@ static int ati_create_gatt_table(void) } agp_bridge->gatt_table_real = (u32 *)page_dir.real; - agp_bridge->gatt_table = (u32 *)page_dir.remapped; + agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real); /* Write out the size register */ @@ -371,9 +369,8 @@ static int ati_create_gatt_table(void) /* Calculate the agp offset */ for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = - virt_to_bus(ati_generic_private.gatt_pages[i]->real); - page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1, + page_dir.remapped+GET_PAGE_DIR_OFF(addr)); } return 0; @@ -384,7 +381,7 @@ static int ati_free_gatt_table(void) ati_page_map page_dir; page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; - page_dir.remapped = (unsigned long *)agp_bridge->gatt_table; + page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; ati_free_gatt_pages(); ati_free_page_map(&page_dir); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index ef1fa6db9..471748a71 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -627,8 +627,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) DBG("client vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; - } else if (remap_page_range(vma, vma->vm_start, - (kerninfo.aper_base + offset), + } else if (remap_pfn_range(vma, vma->vm_start, + (kerninfo.aper_base + offset) >> PAGE_SHIFT, size, vma->vm_page_prot)) { goto out_again; } @@ -643,8 +643,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) DBG("controller vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; - } else if (remap_page_range(vma, vma->vm_start, - kerninfo.aper_base, + } else if (remap_pfn_range(vma, vma->vm_start, + kerninfo.aper_base >> PAGE_SHIFT, size, vma->vm_page_prot)) { goto out_again; } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index f65662437..83498820c 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "agp.h" __u32 *agp_gatt_table; @@ -737,7 +738,7 @@ int agp_generic_create_gatt_table(void) /* AK: bogus, should encode addresses > 4GB */ for (i = 0; i < num_entries; i++) - agp_bridge->gatt_table[i] = (unsigned long) agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i); return 0; } @@ -843,9 +844,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) j = pg_start; while (j < (pg_start + mem->page_count)) { - if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) { + if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) return -EBUSY; - } j++; } @@ -855,9 +855,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - agp_bridge->gatt_table[j] = - agp_bridge->driver->mask_memory( - mem->memory[i], mem->type); + writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j); agp_bridge->driver->tlb_flush(mem); return 0; @@ -875,10 +873,8 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) } /* AK: bogus, should encode addresses > 4GB */ - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - agp_bridge->gatt_table[i] = - (unsigned long) agp_bridge->scratch_page; - } + for (i = pg_start; i < (mem->page_count + pg_start); i++) + writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i); agp_bridge->driver->tlb_flush(mem); return 0; diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 5fd2adc96..323a6b68d 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -59,8 +59,8 @@ static struct gatt_mask hp_zx1_masks[] = }; static struct _hp_private { - volatile u8 *ioc_regs; - volatile u8 *lba_regs; + volatile u8 __iomem *ioc_regs; + volatile u8 __iomem *lba_regs; int lba_cap_offset; u64 *io_pdir; // PDIR for entire IOVA u64 *gatt; // PDIR just for GART (subset of above) @@ -97,7 +97,7 @@ static int __init hp_zx1_ioc_shared(void) default: printk(KERN_ERR PFX "Invalid IOTLB page size " "configuration 0x%x\n", hp->io_tlb_ps); - hp->gatt = 0; + hp->gatt = NULL; hp->gatt_entries = 0; return -ENODEV; } @@ -115,7 +115,7 @@ static int __init hp_zx1_ioc_shared(void) if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { /* Normal case when no AGP device in system */ - hp->gatt = 0; + hp->gatt = NULL; hp->gatt_entries = 0; printk(KERN_ERR PFX "No reserved IO PDIR entry found; " "GART disabled\n"); @@ -183,7 +183,7 @@ hp_zx1_ioc_init (u64 hpa) } static int -hp_zx1_lba_find_capability (volatile u8 *hpa, int cap) +hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap) { u16 status; u8 pos, id; @@ -267,10 +267,10 @@ hp_zx1_cleanup (void) if (hp->ioc_regs) { if (hp->io_pdir_owner) OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0); - iounmap((void *) hp->ioc_regs); + iounmap(hp->ioc_regs); } if (hp->lba_regs) - iounmap((void *) hp->lba_regs); + iounmap(hp->lba_regs); } static void @@ -294,7 +294,7 @@ hp_zx1_create_gatt_table (void) if (!hp->io_pdir) { printk(KERN_ERR PFX "Couldn't allocate contiguous " "memory for I/O PDIR\n"); - hp->gatt = 0; + hp->gatt = NULL; hp->gatt_entries = 0; return -ENOMEM; } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index f04527540..75b84d023 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -69,7 +69,7 @@ static struct gatt_mask intel_i810_masks[] = static struct _intel_i810_private { struct pci_dev *i810_dev; /* device one */ - volatile u8 *registers; + volatile u8 __iomem *registers; int num_dcache_entries; } intel_i810_private; @@ -111,7 +111,7 @@ static int intel_i810_configure(void) pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp); temp &= 0xfff80000; - intel_i810_private.registers = (volatile u8 *) ioremap(temp, 128 * 4096); + intel_i810_private.registers = ioremap(temp, 128 * 4096); if (!intel_i810_private.registers) { printk(KERN_ERR PFX "Unable to remap memory.\n"); return -ENOMEM; @@ -142,7 +142,7 @@ static int intel_i810_configure(void) static void intel_i810_cleanup(void) { OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, 0); - iounmap((void *) intel_i810_private.registers); + iounmap(intel_i810_private.registers); } static void intel_i810_tlbflush(struct agp_memory *mem) @@ -162,11 +162,11 @@ static void *i8xx_alloc_pages(void) page = alloc_pages(GFP_KERNEL, 2); if (page == NULL) { - return 0; + return NULL; } if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { - __free_page(page); - return 0; + __free_page(page); + return NULL; } get_page(page); SetPageLocked(page); @@ -180,7 +180,7 @@ static void i8xx_destroy_pages(void *addr) if (addr == NULL) return; - + page = virt_to_page(addr); change_page_attr(page, 4, PAGE_KERNEL); put_page(page); @@ -202,7 +202,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, return -EINVAL; } for (j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) + if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) return -EBUSY; } @@ -330,7 +330,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr) if (curr->page_count == 4) i8xx_destroy_pages(phys_to_virt(curr->memory[0])); else - agp_bridge->driver->agp_destroy_page( + agp_bridge->driver->agp_destroy_page( phys_to_virt(curr->memory[0])); vfree(curr->memory); } @@ -353,8 +353,8 @@ static struct aper_size_info_fixed intel_i830_sizes[] = static struct _intel_i830_private { struct pci_dev *i830_dev; /* device one */ - volatile u8 *registers; - volatile u32 *gtt; /* I915G */ + volatile u8 __iomem *registers; + volatile u32 __iomem *gtt; /* I915G */ int gtt_entries; } intel_i830_private; @@ -371,7 +371,7 @@ static void intel_i830_init_gtt_entries(void) /* We obtain the size of the GTT, which is also stored (for some * reason) at the top of stolen memory. Then we add 4KB to that - * for the video BIOS popup, which is also stored in there. */ + * for the video BIOS popup, which is also stored in there. */ size = agp_bridge->driver->fetch_size() + 4; if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || @@ -461,7 +461,7 @@ static int intel_i830_create_gatt_table(void) pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); temp &= 0xfff80000; - intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); + intel_i830_private.registers = ioremap(temp,128 * 4096); if (!intel_i830_private.registers) return (-ENOMEM); @@ -544,7 +544,7 @@ static int intel_i830_configure(void) static void intel_i830_cleanup(void) { - iounmap((void *) intel_i830_private.registers); + iounmap(intel_i830_private.registers); } static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, @@ -649,8 +649,8 @@ static int intel_i915_configure(void) static void intel_i915_cleanup(void) { - iounmap((void *) intel_i830_private.gtt); - iounmap((void *) intel_i830_private.registers); + iounmap(intel_i830_private.gtt); + iounmap(intel_i830_private.registers); } static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, @@ -746,18 +746,18 @@ static int intel_i915_create_gatt_table(void) size = agp_bridge->current_size; page_order = size->page_order; num_entries = size->num_entries; - agp_bridge->gatt_table_real = 0; + agp_bridge->gatt_table_real = NULL; pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp); pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2); - intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024); - if (!intel_i830_private.gtt) + intel_i830_private.gtt = ioremap(temp2, 256 * 1024); + if (!intel_i830_private.gtt) return (-ENOMEM); temp &= 0xfff80000; - intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); + intel_i830_private.registers = ioremap(temp,128 * 4096); if (!intel_i830_private.registers) return (-ENOMEM); @@ -921,7 +921,7 @@ static int intel_815_configure(void) /* aperture size */ pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, - current_size->size_value); + current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); @@ -933,7 +933,7 @@ static int intel_815_configure(void) pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr); /* agpctrl */ - pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); /* apcont */ pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2); @@ -956,7 +956,7 @@ static void intel_820_cleanup(void) 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, + 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); @@ -966,23 +966,23 @@ static void intel_820_cleanup(void) static int intel_820_configure(void) { u32 temp; - u8 temp2; + u8 temp2; struct 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); + pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_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); + 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); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); /* global enable aperture access */ /* This flag is not accessed through MCHCFG register as in */ @@ -990,7 +990,7 @@ static int intel_820_configure(void) 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); + pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c); return 0; } @@ -1003,23 +1003,23 @@ static int intel_840_configure(void) current_size = A_SIZE_8(agp_bridge->current_size); /* aperture size */ - pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); + pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_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); + 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); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); /* mcgcfg */ pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2); pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9)); /* clear any possible error conditions */ - pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000); + pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000); return 0; } @@ -1032,23 +1032,23 @@ static int intel_845_configure(void) current_size = A_SIZE_8(agp_bridge->current_size); /* aperture size */ - pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); + pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_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); + 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); + 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); + pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); return 0; } @@ -1061,23 +1061,23 @@ static int intel_850_configure(void) current_size = A_SIZE_8(agp_bridge->current_size); /* aperture size */ - pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); + pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); /* address to map to */ pci_read_config_dword(agp_bridge->dev, AGP_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); + 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); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); /* mcgcfg */ pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2); pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9)); /* clear any possible AGP-related error conditions */ - pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c); + pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c); return 0; } @@ -1163,7 +1163,7 @@ static int intel_7505_configure(void) /* mchcfg */ pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2); pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9)); - + return 0; } @@ -1178,7 +1178,7 @@ static struct aper_size_info_8 intel_815_sizes[2] = {64, 16384, 4, 0}, {32, 8192, 3, 8}, }; - + static struct aper_size_info_8 intel_8xx_sizes[7] = { {256, 65536, 6, 0}, @@ -1201,7 +1201,7 @@ static struct aper_size_info_16 intel_generic_sizes[7] = {4, 1024, 0, 63} }; -static struct aper_size_info_8 intel_830mp_sizes[4] = +static struct aper_size_info_8 intel_830mp_sizes[4] = { {256, 65536, 6, 0}, {128, 32768, 5, 32}, @@ -1283,7 +1283,7 @@ static struct agp_bridge_driver intel_830_driver = { .owner = THIS_MODULE, .aperture_sizes = intel_i830_sizes, .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 3, + .num_aperture_sizes = 3, .needs_scratch_page = TRUE, .configure = intel_i830_configure, .fetch_size = intel_i830_fetch_size, @@ -1445,7 +1445,7 @@ static struct agp_bridge_driver intel_915_driver = { .owner = THIS_MODULE, .aperture_sizes = intel_i830_sizes, .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 3, + .num_aperture_sizes = 3, .needs_scratch_page = TRUE, .configure = intel_i915_configure, .fetch_size = intel_i915_fetch_size, @@ -1489,18 +1489,13 @@ static struct agp_bridge_driver intel_7505_driver = { .agp_destroy_page = agp_generic_destroy_page, }; -static int find_i810(u16 device, const char *name) +static int find_i810(u16 device) { struct pci_dev *i810_dev; i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL); - if (!i810_dev) { - printk(KERN_ERR PFX "Detected an Intel %s Chipset, " - "but could not find the secondary device.\n", - name); + if (!i810_dev) return 0; - } - intel_i810_private.i810_dev = i810_dev; return 1; } @@ -1550,29 +1545,29 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, name = "440GX"; break; case PCI_DEVICE_ID_INTEL_82810_MC1: - if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810")) + name = "i810"; + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1)) goto fail; bridge->driver = &intel_810_driver; - name = "i810"; break; case PCI_DEVICE_ID_INTEL_82810_MC3: - if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100")) + name = "i810 DC100"; + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3)) goto fail; bridge->driver = &intel_810_driver; - name = "i810 DC100"; break; case PCI_DEVICE_ID_INTEL_82810E_MC: - if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E")) + name = "i810 E"; + if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG)) goto fail; bridge->driver = &intel_810_driver; - name = "i810 E"; break; case PCI_DEVICE_ID_INTEL_82815_MC: /* * The i815 can operate either as an i810 style * integrated device, or as an AGP4X motherboard. */ - if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815")) + if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC)) bridge->driver = &intel_810_driver; else bridge->driver = &intel_815_driver; @@ -1708,7 +1703,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); - fail: + +fail: + printk(KERN_ERR PFX "Detected an Intel %s chipset, " + "but could not find the secondary device.\n", name); agp_put_bridge(bridge); return -ENODEV; } @@ -1724,8 +1722,8 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - - pci_restore_state(pdev, pdev->saved_config_space); + + pci_restore_state(pdev); if (bridge->driver == &intel_generic_driver) intel_configure(); @@ -1741,7 +1739,7 @@ static int agp_intel_resume(struct pci_dev *pdev) static struct pci_device_id agp_intel_pci_table[] = { #define ID(x) \ - { \ + { \ .class = (PCI_CLASS_BRIDGE_HOST << 8), \ .class_mask = ~0, \ .vendor = PCI_VENDOR_ID_INTEL, \ @@ -1769,7 +1767,8 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82865_HB), ID(PCI_DEVICE_ID_INTEL_82875_HB), ID(PCI_DEVICE_ID_INTEL_7505_0), - ID(PCI_DEVICE_ID_INTEL_7205_0), + ID(PCI_DEVICE_ID_INTEL_7205_0), + ID(PCI_DEVICE_ID_INTEL_82915G_HB), { } }; @@ -1779,20 +1778,12 @@ static struct pci_driver agp_intel_pci_driver = { .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, - .remove = agp_intel_remove, + .remove = __devexit_p(agp_intel_remove), .resume = agp_intel_resume, }; -/* intel_agp_init() must not be declared static for explicit - early initialization to work (ie i810fb) */ -int __init agp_intel_init(void) +static int __init agp_intel_init(void) { - static int agp_initialised=0; - - if (agp_initialised == 1) - return 0; - agp_initialised=1; - return pci_module_init(&agp_intel_pci_driver); } diff --git a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c index c8f230acc..8953009f9 100644 --- a/drivers/char/agp/intel-mch-agp.c +++ b/drivers/char/agp/intel-mch-agp.c @@ -84,7 +84,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] = static struct _intel_i830_private { struct pci_dev *i830_dev; /* device one */ - volatile u8 *registers; + volatile u8 __iomem *registers; int gtt_entries; } intel_i830_private; @@ -172,7 +172,7 @@ static int intel_i830_create_gatt_table(void) pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp); temp &= 0xfff80000; - intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); + intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096); if (!intel_i830_private.registers) return (-ENOMEM); @@ -255,7 +255,7 @@ static int intel_i830_configure(void) static void intel_i830_cleanup(void) { - iounmap((void *) intel_i830_private.registers); + iounmap((void __iomem *) intel_i830_private.registers); } static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, @@ -573,7 +573,7 @@ static int agp_intelmch_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - pci_restore_state(pdev, pdev->saved_config_space); + pci_restore_state(pdev); if (bridge->driver == &intel_845_driver) intel_845_configure(); @@ -633,5 +633,5 @@ module_init(agp_intelmch_init); module_exit(agp_intelmch_cleanup); MODULE_AUTHOR("Dave Jones "); -MODULE_LICENSE("GPL and additional rights"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 28e7fc4bc..16d8bdcb4 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -28,7 +28,7 @@ static struct _nvidia_private { struct pci_dev *dev_1; struct pci_dev *dev_2; struct pci_dev *dev_3; - volatile u32 *aperture; + volatile u32 __iomem *aperture; int num_active_entries; off_t pg_offset; u32 wbc_mask; @@ -154,7 +154,7 @@ static int nvidia_configure(void) /* map aperture */ nvidia_private.aperture = - (volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE); + (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE); return 0; } @@ -173,7 +173,7 @@ static void nvidia_cleanup(void) pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11)); /* unmap aperture */ - iounmap((void *) nvidia_private.aperture); + iounmap((void __iomem *) nvidia_private.aperture); /* restore previous aperture size */ previous_size = A_SIZE_8(agp_bridge->previous_size); @@ -206,7 +206,7 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type return -EINVAL; for(j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j])) + if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j))) return -EBUSY; } @@ -215,9 +215,8 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - agp_bridge->gatt_table[nvidia_private.pg_offset + j] = - agp_bridge->driver->mask_memory(mem->memory[i], mem->type); - + writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), + agp_bridge->gatt_table+nvidia_private.pg_offset+j); agp_bridge->driver->tlb_flush(mem); return 0; } @@ -229,11 +228,9 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type if ((type != 0) || (mem->type != 0)) return -EINVAL; - - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - agp_bridge->gatt_table[nvidia_private.pg_offset + i] = - (unsigned long) agp_bridge->scratch_page; - } + + for (i = pg_start; i < (mem->page_count + pg_start); i++) + writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i); agp_bridge->driver->tlb_flush(mem); return 0; @@ -265,9 +262,9 @@ static void nvidia_tlbflush(struct agp_memory *mem) /* flush TLB entries */ for(i = 0; i < 32 + 1; i++) - temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; + temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32))); for(i = 0; i < 32 + 1; i++) - temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; + temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32))); } diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 2a99c738f..30a01dfe0 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "agp.h" #define SIS_ATTBASE 0x90 @@ -85,7 +86,7 @@ static void sis_delayed_enable(u32 mode) command |= AGPSTAT_AGP_ENABLE; rate = (command & 0x7) << 2; - while ((device = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device)) != NULL) { + for_each_pci_dev(device) { u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP); if (!agp) continue; @@ -102,8 +103,7 @@ static void sis_delayed_enable(u32 mode) */ if (device->device == agp_bridge->dev->device) { printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout (1+(HZ*10)/1000); + msleep(10); } } } @@ -168,6 +168,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata = .device_id = PCI_DEVICE_ID_SI_630, .chipset_name = "630", }, + { + .device_id = PCI_DEVICE_ID_SI_635, + .chipset_name = "635", + }, { .device_id = PCI_DEVICE_ID_SI_645, .chipset_name = "645", diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 44e11acbc..ae20fcaa4 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -27,12 +27,12 @@ struct serverworks_page_map { unsigned long *real; - unsigned long *remapped; + unsigned long __iomem *remapped; }; static struct _serverworks_private { struct pci_dev *svrwrks_dev; /* device one */ - volatile u8 *registers; + volatile u8 __iomem *registers; struct serverworks_page_map **gatt_pages; int num_tables; struct serverworks_page_map scratch_dir; @@ -61,9 +61,8 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) } global_cache_flush(); - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { - page_map->remapped[i] = agp_bridge->scratch_page; - } + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) + writel(agp_bridge->scratch_page, page_map->remapped+i); return 0; } @@ -162,10 +161,8 @@ static int serverworks_create_gatt_table(void) } /* Create a fake scratch directory */ for(i = 0; i < 1024; i++) { - serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge->scratch_page; - page_dir.remapped[i] = - virt_to_phys(serverworks_private.scratch_dir.real); - page_dir.remapped[i] |= 0x00000001; + writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); + writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); } retval = serverworks_create_gatt_pages(value->num_entries / 1024); @@ -176,7 +173,7 @@ static int serverworks_create_gatt_table(void) } agp_bridge->gatt_table_real = (u32 *)page_dir.real; - agp_bridge->gatt_table = (u32 *)page_dir.remapped; + agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); /* Get the address for the gart region. @@ -189,11 +186,8 @@ static int serverworks_create_gatt_table(void) /* Calculate the agp offset */ - for(i = 0; i < value->num_entries / 1024; i++) { - page_dir.remapped[i] = - virt_to_phys(serverworks_private.gatt_pages[i]->real); - page_dir.remapped[i] |= 0x00000001; - } + for(i = 0; i < value->num_entries / 1024; i++) + writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; } @@ -203,7 +197,7 @@ static int serverworks_free_gatt_table(void) struct serverworks_page_map page_dir; page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; - page_dir.remapped = (unsigned long *)agp_bridge->gatt_table; + page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; serverworks_free_gatt_pages(); serverworks_free_page_map(&page_dir); @@ -269,7 +263,7 @@ static int serverworks_configure(void) /* Get the memory mapped registers */ pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp); temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); - serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096); + serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); if (!serverworks_private.registers) { printk (KERN_ERR PFX "Unable to ioremap() memory.\n"); return -ENOMEM; @@ -311,14 +305,14 @@ static int serverworks_configure(void) static void serverworks_cleanup(void) { - iounmap((void *) serverworks_private.registers); + iounmap((void __iomem *) serverworks_private.registers); } static int serverworks_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; @@ -334,9 +328,8 @@ static int serverworks_insert_memory(struct agp_memory *mem, while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) { + if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr)))) return -EBUSY; - } j++; } @@ -348,8 +341,7 @@ static int serverworks_insert_memory(struct agp_memory *mem, for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->driver->mask_memory(mem->memory[i], mem->type); + writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); } serverworks_tlbflush(mem); return 0; @@ -359,7 +351,7 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { int i; - unsigned long *cur_gatt; + unsigned long __iomem *cur_gatt; unsigned long addr; if (type != 0 || mem->type != 0) { @@ -372,8 +364,7 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start, for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - cur_gatt[GET_GATT_OFF(addr)] = - (unsigned long) agp_bridge->scratch_page; + writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); } serverworks_tlbflush(mem); diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index c619722e5..16dea270d 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -438,6 +438,33 @@ static void __devexit agp_via_remove(struct pci_dev *pdev) agp_put_bridge(bridge); } +#ifdef CONFIG_PM + +static int agp_via_suspend(struct pci_dev *pdev, u32 state) +{ + pci_save_state (pdev); + pci_set_power_state (pdev, 3); + + return 0; +} + +static int agp_via_resume(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + pci_set_power_state (pdev, 0); + pci_restore_state(pdev); + + if (bridge->driver == &via_agp3_driver) + return via_configure_agp3(); + else if (bridge->driver == &via_driver) + return via_configure(); + + return 0; +} + +#endif /* CONFIG_PM */ + /* must be the same order as name table above */ static struct pci_device_id agp_via_pci_table[] = { #define ID(x) \ @@ -487,6 +514,10 @@ static struct pci_driver agp_via_pci_driver = { .id_table = agp_via_pci_table, .probe = agp_via_probe, .remove = agp_via_remove, +#ifdef CONFIG_PM + .suspend = agp_via_suspend, + .resume = agp_via_resume, +#endif }; @@ -503,5 +534,5 @@ static void __exit agp_via_cleanup(void) module_init(agp_via_init); module_exit(agp_via_cleanup); -MODULE_LICENSE("GPL and additional rights"); +MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dave Jones "); diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 3dc61d41b..1dc425921 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -32,6 +32,7 @@ */ #include +#include #undef SERIAL_PARANOIA_CHECK #define SERIAL_DO_RESTART @@ -83,14 +84,13 @@ static char *serial_version = "4.30"; #include #include #include -#include +#include #include #include #include -#include #include #include @@ -118,10 +118,6 @@ static struct serial_state rs_table[1]; #define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the copy_from_user blocks while swapping in a page, @@ -430,7 +426,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info) if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttyS%02d CD now %s...", info->line, + printk("ttyS%d CD now %s...", info->line, (!(status & SER_DCD)) ? "on" : "off"); #endif if (!(status & SER_DCD)) @@ -557,9 +553,7 @@ static void do_softint(unsigned long private_) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } } @@ -651,7 +645,7 @@ static int startup(struct async_struct * info) /* * and set the speed of the serial port */ - change_speed(info, 0); + change_speed(info, NULL); info->flags |= ASYNC_INITIALIZED; local_irq_restore(flags); @@ -697,7 +691,7 @@ static void shutdown(struct async_struct * info) if (info->xmit.buf) { free_page((unsigned long) info->xmit.buf); - info->xmit.buf = 0; + info->xmit.buf = NULL; } info->IER = 0; @@ -913,8 +907,7 @@ static void rs_flush_chars(struct tty_struct *tty) local_irq_restore(flags); } -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; struct async_struct *info = (struct async_struct *)tty->driver_data; @@ -927,57 +920,25 @@ static int rs_write(struct tty_struct * tty, int from_user, return 0; local_save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - local_irq_disable(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - local_irq_restore(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - local_irq_disable(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; + local_irq_disable(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SERIAL_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) { + break; } - local_irq_restore(flags); + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = ((info->xmit.head + c) & + (SERIAL_XMIT_SIZE-1)); + buf += c; + count -= c; + ret += c; } + local_irq_restore(flags); + if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped @@ -1023,9 +984,7 @@ static void rs_flush_buffer(struct tty_struct *tty) info->xmit.head = info->xmit.tail = 0; local_irq_restore(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -1213,7 +1172,7 @@ check_and_exit: info->tty->alt_speed = 230400; if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) info->tty->alt_speed = 460800; - change_speed(info, 0); + change_speed(info, NULL); } } else retval = startup(info); @@ -1564,15 +1523,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; - info->tty = 0; + info->tty = NULL; if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -1610,7 +1568,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) if (char_time == 0) char_time = 1; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min_t(unsigned long, char_time, timeout); /* * If the transmitter hasn't cleared in twice the approximate * amount of time to send the entire FIFO, it probably won't @@ -1630,8 +1588,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("serdatr = %d (jiff=%lu)...", lsr, jiffies); #endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -1661,7 +1618,7 @@ static void rs_hangup(struct tty_struct *tty) info->event = 0; state->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -1917,7 +1874,7 @@ static inline int line_info(char *buf, struct serial_state *state) info->magic = SERIAL_MAGIC; info->flags = state->flags; info->quot = 0; - info->tty = 0; + info->tty = NULL; } local_irq_save(flags); status = ciab.pra; @@ -2095,7 +2052,7 @@ static int __init rs_init(void) continue; */ - printk(KERN_INFO "ttyS%02d is the amiga builtin serial port\n", + printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", state->line); /* Hardware set up */ diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 0b2c40e94..2d016858c 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -89,7 +89,7 @@ MODULE_SUPPORTED_DEVICE("ac"); static struct applicom_board { unsigned long PhysIO; - unsigned long RamIO; + void __iomem *RamIO; wait_queue_head_t FlagSleepSend; long irq; spinlock_t mutex; @@ -127,7 +127,7 @@ static struct miscdevice ac_miscdev = { static int dummy; /* dev_id for request_irq() */ -static int ac_register_board(unsigned long physloc, unsigned long loc, +static int ac_register_board(unsigned long physloc, void __iomem *loc, unsigned char boardno) { volatile unsigned char byte_reset_it; @@ -179,11 +179,11 @@ void cleanup_module(void) if (!apbs[i].RamIO) continue; - - iounmap((void *) apbs[i].RamIO); if (apbs[i].irq) free_irq(apbs[i].irq, &dummy); + + iounmap(apbs[i].RamIO); } } @@ -193,14 +193,14 @@ int __init applicom_init(void) { int i, numisa = 0; struct pci_dev *dev = NULL; - void *RamIO; + void __iomem *RamIO; int boardno; printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n"); /* No mem and irq given - check for a PCI card */ - while ( (dev = pci_find_class(PCI_CLASS_OTHERS << 16, dev))) { + while ( (dev = pci_get_class(PCI_CLASS_OTHERS << 16, dev))) { if (dev->vendor != PCI_VENDOR_ID_APPLICOM) continue; @@ -223,8 +223,8 @@ int __init applicom_init(void) applicom_pci_devnames[dev->device-1], dev->resource[0].start, dev->irq); - if (!(boardno = ac_register_board(dev->resource[0].start, - (unsigned long)RamIO,0))) { + boardno = ac_register_board(dev->resource[0].start, RamIO,0); + if (!boardno) { printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n"); iounmap(RamIO); pci_disable_device(dev); @@ -235,7 +235,7 @@ int __init applicom_init(void) printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq); iounmap(RamIO); pci_disable_device(dev); - apbs[boardno - 1].RamIO = 0; + apbs[boardno - 1].RamIO = NULL; continue; } @@ -270,7 +270,7 @@ int __init applicom_init(void) } if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i), - (unsigned long)RamIO,i+1))) { + RamIO,i+1))) { iounmap(RamIO); continue; } @@ -280,8 +280,8 @@ int __init applicom_init(void) if (!numisa) { if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &dummy)) { printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq); - iounmap((void *) RamIO); - apbs[boardno - 1].RamIO = 0; + iounmap(RamIO); + apbs[boardno - 1].RamIO = NULL; } else apbs[boardno - 1].irq = irq; @@ -449,7 +449,7 @@ static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, because it works with 2.2 still */ { unsigned char *from = (unsigned char *) &tmpmailbox; - unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC; + void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC; int c; for (c = 0; c < sizeof(struct mailbox); c++) @@ -470,7 +470,7 @@ static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, static int do_ac_read(int IndexCard, char __user *buf, struct st_ram_io *st_loc, struct mailbox *mailbox) { - unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC; + void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC; unsigned char *to = (unsigned char *)&mailbox; #ifdef DEBUG int c; @@ -685,7 +685,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un { /* @ ADG ou ATO selon le cas */ int i; unsigned char IndexCard; - unsigned long pmem; + void __iomem *pmem; int ret = 0; volatile unsigned char byte_reset_it; struct st_ram_io *adgl; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e69dc6d00..dac1d80cb 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -652,12 +652,12 @@ static char rcsid[] = #include #include #include +#include #include #include #include #include -#include #define CY_LOCK(info,flags) \ do { \ @@ -682,13 +682,13 @@ static void cy_send_xchar (struct tty_struct *tty, char ch); #define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ - ((cy_readl(&((struct RUNTIME_9060 *) \ + ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) -#define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 *) \ +#define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->mail_box_0)) || \ Z_FPGA_CHECK(card)) && \ - (ZFIRM_ID==cy_readl(&((struct FIRM_ID *) \ + (ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \ ((card).base_addr+ID_ADDRESS))->signature))) #ifndef SERIAL_XMIT_SIZE @@ -712,16 +712,16 @@ static struct tty_driver *cy_serial_driver; boot options line. The form is "cyclades=address,address..." */ -static unsigned char *cy_isa_addresses[] = { - (unsigned char *) 0xD0000, - (unsigned char *) 0xD2000, - (unsigned char *) 0xD4000, - (unsigned char *) 0xD6000, - (unsigned char *) 0xD8000, - (unsigned char *) 0xDA000, - (unsigned char *) 0xDC000, - (unsigned char *) 0xDE000, - NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL +static unsigned int cy_isa_addresses[] = { + 0xD0000, + 0xD2000, + 0xD4000, + 0xD6000, + 0xD8000, + 0xDA000, + 0xDC000, + 0xDE000, + 0,0,0,0,0,0,0,0 }; #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*)) @@ -729,8 +729,8 @@ static unsigned char *cy_isa_addresses[] = { static long maddr[NR_CARDS] = { 0, }; static int irq[NR_CARDS] = { 0, }; -MODULE_PARM(maddr, "1-" __MODULE_STRING(NR_CARDS) "l"); -MODULE_PARM(irq, "1-" __MODULE_STRING(NR_CARDS) "i"); +module_param_array(maddr, long, NULL, 0); +module_param_array(irq, int, NULL, 0); #endif #endif /* CONFIG_ISA */ @@ -854,7 +854,7 @@ static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); #ifdef CONFIG_ISA -static unsigned detect_isa_irq (volatile ucchar *); +static unsigned detect_isa_irq(void __iomem *); #endif /* CONFIG_ISA */ static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); @@ -970,10 +970,7 @@ do_softint(void *private_) wake_up_interruptible(&info->delta_msr_wait); } if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup){ - (tty->ldisc.write_wakeup)(tty); - } + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } #ifdef Z_WAKE @@ -995,7 +992,7 @@ do_softint(void *private_) This function is only called from inside spinlock-protected code. */ static int -cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index) +cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index) { volatile int i; @@ -1011,7 +1008,7 @@ cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index) if (i == 100) return (-1); /* Issue the new command */ - cy_writeb((u_long)base_addr+(CyCCR< 0)? irq : 0; @@ -1079,7 +1076,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) int status; struct cyclades_card *cinfo; struct cyclades_port *info; - volatile unsigned char *base_addr, *card_base_addr; + void __iomem *base_addr, *card_base_addr; int chip; int save_xir, channel, save_car; char data; @@ -1098,7 +1095,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; /* spurious interrupt */ } - card_base_addr = (unsigned char *)cinfo->base_addr; + card_base_addr = cinfo->base_addr; index = cinfo->bus_index; @@ -1110,8 +1107,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) do{ had_work = 0; for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) { - base_addr = (unsigned char *) - (cinfo->base_addr + (cy_chip_offset[chip]<base_addr + (cy_chip_offset[chip]<last_active = jiffies; save_car = cy_readb(base_addr+(CyCAR<tty == 0){ @@ -1264,8 +1260,8 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) schedule_delayed_work(&tty->flip.work, 1); } /* end of service */ - cy_writeb((u_long)base_addr+(CyRIR<card_lock); } @@ -1284,18 +1280,18 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) channel = (u_short ) (save_xir & CyIRChannel); i = channel + chip * 4 + cinfo->first_line; save_car = cy_readb(base_addr+(CyCAR<last_active = jiffies; if(info->tty == 0){ - cy_writeb((u_long)base_addr+(CySRER<x_char) { /* send special char */ outch = info->x_char; - cy_writeb((u_long)base_addr+(CyTDR<icount.tx++; info->x_char = 0; @@ -1313,14 +1309,14 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (info->breakon || info->breakoff) { if (info->breakon) { - cy_writeb((u_long)base_addr + (CyTDR<breakon = 0; char_count -= 2; } if (info->breakoff) { - cy_writeb((u_long)base_addr + (CyTDR<breakoff = 0; char_count -= 2; } @@ -1329,11 +1325,11 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) while (char_count-- > 0){ if (!info->xmit_cnt){ if (cy_readb(base_addr+(CySRER<xmit_buf == 0){ - cy_writeb((u_long)base_addr+(CySRER<tty->stopped || info->tty->hw_stopped){ - cy_writeb((u_long)base_addr+(CySRER<xmit_cnt--; info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); - cy_writeb((u_long)base_addr+(CyTDR<icount.tx++; }else{ if(char_count > 1){ info->xmit_cnt--; info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); - cy_writeb((u_long)base_addr+(CyTDR<icount.tx++; char_count--; }else{ @@ -1391,9 +1387,9 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) } txend: /* end of service */ - cy_writeb((u_long)base_addr+(CyTIR<card_lock); } @@ -1407,7 +1403,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) + cinfo->first_line]; info->last_active = jiffies; save_car = cy_readb(base_addr+(CyCAR<tty->hw_stopped = 0; - cy_writeb((u_long)base_addr+(CySRER<tty->hw_stopped = 1; - cy_writeb((u_long)base_addr+(CySRER<card_lock); } } /* end while status != 0 */ @@ -1476,7 +1472,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* clear interrupts */ spin_lock(&cinfo->card_lock); - cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<card_lock); return IRQ_HANDLED; @@ -1491,27 +1487,25 @@ static int cyz_fetch_msg( struct cyclades_card *cinfo, uclong *channel, ucchar *cmd, uclong *param) { - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; unsigned long loc_doorbell; - firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + firm_id = cinfo->base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)){ return (-1); } - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; - loc_doorbell = cy_readl(&((struct RUNTIME_9060 *) + loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->loc_doorbell); if (loc_doorbell){ *cmd = (char)(0xff & loc_doorbell); *channel = cy_readl(&board_ctrl->fwcmd_channel); *param = (uclong)cy_readl(&board_ctrl->fwcmd_param); - cy_writel(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->loc_doorbell, + cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, 0xffffffff); return 1; } @@ -1522,40 +1516,38 @@ static int cyz_issue_cmd( struct cyclades_card *cinfo, uclong channel, ucchar cmd, uclong param) { - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; - volatile uclong *pci_doorbell; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + unsigned long __iomem *pci_doorbell; int index; - firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + firm_id = cinfo->base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)){ return (-1); } - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; index = 0; - pci_doorbell = (uclong *)(&((struct RUNTIME_9060 *) - (cinfo->ctl_addr))->pci_doorbell); + pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell; while( (cy_readl(pci_doorbell) & 0xff) != 0){ if (index++ == 1000){ return((int)(cy_readl(pci_doorbell) & 0xff)); } udelay(50L); } - cy_writel((u_long)&board_ctrl->hcmd_channel, channel); - cy_writel((u_long)&board_ctrl->hcmd_param , param); - cy_writel((u_long)pci_doorbell, (long)cmd); + cy_writel(&board_ctrl->hcmd_channel, channel); + cy_writel(&board_ctrl->hcmd_param , param); + cy_writel(pci_doorbell, (long)cmd); return(0); } /* cyz_issue_cmd */ static void -cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl, - volatile struct BUF_CTRL *buf_ctrl) +cyz_handle_rx(struct cyclades_port *info, + volatile struct CH_CTRL __iomem *ch_ctrl, + volatile struct BUF_CTRL __iomem *buf_ctrl) { struct cyclades_card *cinfo = &cy_card[info->card]; struct tty_struct *tty = info->tty; @@ -1652,8 +1644,9 @@ cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl, } static void -cyz_handle_tx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl, - volatile struct BUF_CTRL *buf_ctrl) +cyz_handle_tx(struct cyclades_port *info, + volatile struct CH_CTRL __iomem *ch_ctrl, + volatile struct BUF_CTRL __iomem *buf_ctrl) { struct cyclades_card *cinfo = &cy_card[info->card]; struct tty_struct *tty = info->tty; @@ -1740,11 +1733,11 @@ cyz_handle_cmd(struct cyclades_card *cinfo) { struct tty_struct *tty; struct cyclades_port *info; - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct BOARD_CTRL *board_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; + static volatile struct FIRM_ID __iomem *firm_id; + static volatile struct ZFW_CTRL __iomem *zfw_ctrl; + static volatile struct BOARD_CTRL __iomem *board_ctrl; + static volatile struct CH_CTRL __iomem *ch_ctrl; + static volatile struct BUF_CTRL __iomem *buf_ctrl; uclong channel; ucchar cmd; uclong param; @@ -1752,13 +1745,11 @@ cyz_handle_cmd(struct cyclades_card *cinfo) int special_count; int delta_count; - firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); - board_ctrl = &(zfw_ctrl->board_ctrl); + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; fw_ver = cy_readl(&board_ctrl->fw_version); - hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0); + hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0); while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { @@ -1925,10 +1916,8 @@ cyz_poll(unsigned long arg) if (!IS_CYC_Z(*cinfo)) continue; if (!ISZLOADED(*cinfo)) continue; - firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ @@ -1972,7 +1961,7 @@ startup(struct cyclades_port * info) { unsigned long flags; int retval = 0; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; unsigned long page; @@ -2011,8 +2000,7 @@ startup(struct cyclades_port * info) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<default_timeout + cy_writeb(base_addr+(CyRTPR<default_timeout ? info->default_timeout : 0x02)); /* 10ms rx timeout */ cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); - cy_writeb((ulong)base_addr+(CyCAR<flags |= ASYNC_INITIALIZED; @@ -2056,22 +2044,20 @@ startup(struct cyclades_port * info) CY_UNLOCK(info, flags); } else { - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; - struct CH_CTRL *ch_ctrl; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; int retval; - base_addr = (unsigned char*) (cy_card[card].base_addr); + base_addr = cy_card[card].base_addr; - firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); + firm_id = base_addr + ID_ADDRESS; if (!ISZLOADED(cy_card[card])){ return -ENODEV; } - zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2163,7 +2149,7 @@ static void start_xmit( struct cyclades_port *info ) { unsigned long flags; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; card = info->card; @@ -2172,13 +2158,11 @@ start_xmit( struct cyclades_port *info ) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<flags & ASYNC_INITIALIZED)){ @@ -2219,9 +2203,7 @@ shutdown(struct cyclades_port * info) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<xmit_buf = NULL; free_page((unsigned long) temp); } - cy_writeb((u_long)base_addr+(CyCAR<tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writeb((u_long)base_addr+(CyMSVR1<flags &= ~ASYNC_INITIALIZED; CY_UNLOCK(info, flags); } else { - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; - struct CH_CTRL *ch_ctrl; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; int retval; - base_addr = (unsigned char*) (cy_card[card].base_addr); + base_addr = cy_card[card].base_addr; #ifdef CY_DEBUG_OPEN printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", card, channel, (long)base_addr); #endif - firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); + firm_id = base_addr + ID_ADDRESS; if (!ISZLOADED(cy_card[card])) { return; } - zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); - board_ctrl = &(zfw_ctrl->board_ctrl); + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; CY_LOCK(info, flags); @@ -2293,7 +2273,7 @@ shutdown(struct cyclades_port * info) } if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writel((u_long)&ch_ctrl[channel].rs_control, + cy_writel(&ch_ctrl[channel].rs_control, (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & ~(C_RS_RTS | C_RS_DTR))); retval = cyz_issue_cmd(&cy_card[info->card], @@ -2337,7 +2317,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, unsigned long flags; int chip, channel,index; int retval; - char *base_addr; + void __iomem *base_addr; cinfo = &cy_card[info->card]; channel = info->line - cinfo->first_line; @@ -2390,15 +2370,14 @@ block_til_ready(struct tty_struct *tty, struct file * filp, chip = channel>>2; channel &= 0x03; index = cinfo->bus_index; - base_addr = (char *)(cinfo->base_addr - + (cy_chip_offset[chip]<base_addr + (cy_chip_offset[chip]<termios->c_cflag & CBAUD)){ - cy_writeb((u_long)base_addr+(CyCAR<flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || (cy_readb(base_addr+(CyMSVR1<base_addr); - firm_id = (struct FIRM_ID *) - (base_addr + ID_ADDRESS); + base_addr = cinfo->base_addr; + firm_id = base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)){ current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); return -EINVAL; } - zfw_ctrl = (struct ZFW_CTRL *) - (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2543,11 +2520,10 @@ cy_open(struct tty_struct *tty, struct file * filp) */ if (IS_CYC_Z(cy_card[info->card])) { struct cyclades_card *cinfo = &cy_card[info->card]; - struct FIRM_ID *firm_id = (struct FIRM_ID *) - (cinfo->base_addr + ID_ADDRESS); + struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)) { - if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 *) + if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->mail_box_0)) && Z_FPGA_CHECK (*cinfo)) && (ZFIRM_HLT == cy_readl (&firm_id->signature))) @@ -2564,12 +2540,10 @@ cy_open(struct tty_struct *tty, struct file * filp) interrupts should be enabled as soon as the first open happens to one of its ports. */ if (!cinfo->intr_enabled) { - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; - zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + - (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; @@ -2661,7 +2635,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) { struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; unsigned long orig_jiffies; int char_time; @@ -2711,26 +2685,21 @@ cy_wait_until_sent(struct tty_struct *tty, int timeout) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char *) - (cy_card[card].base_addr + (cy_chip_offset[chip]<state = TASK_INTERRUPTIBLE; - schedule_timeout(char_time); - if (signal_pending(current)) + if (msleep_interruptible(jiffies_to_msecs(char_time))) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) break; } - current->state = TASK_RUNNING; } else { // Nothing to do! } /* Run one more char cycle */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(char_time * 5); + msleep_interruptible(jiffies_to_msecs(char_time * 5)); #ifdef CY_DEBUG_WAIT_UNTIL_SENT printk("Clean (jiff=%lu)...done\n", jiffies); #endif @@ -2805,13 +2774,11 @@ cy_close(struct tty_struct *tty, struct file *filp) if (!IS_CYC_Z(cy_card[info->card])) { int channel = info->line - cy_card[info->card].first_line; int index = cy_card[info->card].bus_index; - unsigned char *base_addr = (unsigned char *) - (cy_card[info->card].base_addr + - (cy_chip_offset[channel>>2] <card].base_addr + (cy_chip_offset[channel>>2] << index); /* Stop accepting input */ channel &= 0x03; - cy_writeb((ulong)base_addr+(CyCAR<flags & ASYNC_INITIALIZED) { /* Waiting for on-board buffers to be empty before closing @@ -2823,12 +2790,10 @@ cy_close(struct tty_struct *tty, struct file *filp) } else { #ifdef Z_WAKE /* Waiting for on-board buffers to be empty before closing the port */ - unsigned char *base_addr = (unsigned char *) - cy_card[info->card].base_addr; - struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); - struct ZFW_CTRL *zfw_ctrl = (struct ZFW_CTRL *) - (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); - struct CH_CTRL *ch_ctrl = zfw_ctrl->ch_ctrl; + void __iomem *base_addr = cy_card[info->card].base_addr; + struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; + struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; int channel = info->line - cy_card[info->card].first_line; int retval; @@ -2850,8 +2815,7 @@ cy_close(struct tty_struct *tty, struct file *filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); CY_LOCK(info, flags); tty->closing = 0; @@ -2860,8 +2824,7 @@ cy_close(struct tty_struct *tty, struct file *filp) if (info->blocked_open) { CY_UNLOCK(info, flags); if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); CY_LOCK(info, flags); @@ -2892,8 +2855,7 @@ cy_close(struct tty_struct *tty, struct file *filp) * */ static int -cy_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +cy_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; @@ -2911,56 +2873,22 @@ cy_write(struct tty_struct * tty, int from_user, return 0; } - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) { - ret = -EFAULT; - } - break; - } - CY_LOCK(info, flags); - c1 = min(c, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - - if (c1 < c) - c = c1; - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - CY_UNLOCK(info, flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - CY_LOCK(info, flags); - while (1) { - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + CY_LOCK(info, flags); + while (1) { + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - if (c <= 0) - break; + if (c <= 0) + break; - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - CY_UNLOCK(info, flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; } + CY_UNLOCK(info, flags); info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; @@ -3088,10 +3016,8 @@ cy_chars_in_buffer(struct tty_struct *tty) int char_count; volatile uclong tx_put, tx_get, tx_bufsize; - firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); + firm_id = cy_card[card].base_addr + ID_ADDRESS; + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); @@ -3151,7 +3077,7 @@ static void set_line_char(struct cyclades_port * info) { unsigned long flags; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; unsigned cflag, iflag; unsigned short chip_number; @@ -3303,76 +3229,74 @@ set_line_char(struct cyclades_port * info) chip = channel>>2; channel &= 0x03; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<tco); - cy_writeb((u_long)base_addr+(CyTBPR<tbpr); - cy_writeb((u_long)base_addr+(CyRCOR<rco); - cy_writeb((u_long)base_addr+(CyRBPR<rbpr); + cy_writeb(base_addr+(CyTCOR<tco); + cy_writeb(base_addr+(CyTBPR<tbpr); + cy_writeb(base_addr+(CyRCOR<rco); + cy_writeb(base_addr+(CyRBPR<rbpr); /* set line characteristics according configuration */ - cy_writeb((u_long)base_addr+(CySCHR1<tty)); - cy_writeb((u_long)base_addr+(CySCHR2<tty)); - cy_writeb((u_long)base_addr+(CyCOR1<cor1); - cy_writeb((u_long)base_addr+(CyCOR2<cor2); - cy_writeb((u_long)base_addr+(CyCOR3<cor3); - cy_writeb((u_long)base_addr+(CyCOR4<cor4); - cy_writeb((u_long)base_addr+(CyCOR5<cor5); + cy_writeb(base_addr+(CyCOR1<cor1); + cy_writeb(base_addr+(CyCOR2<cor2); + cy_writeb(base_addr+(CyCOR3<cor3); + cy_writeb(base_addr+(CyCOR4<cor4); + cy_writeb(base_addr+(CyCOR5<cor5); cyy_issue_cmd(base_addr, CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index); - cy_writeb((u_long)base_addr+(CyCAR<default_timeout + cy_writeb(base_addr+(CyRTPR<default_timeout ? info->default_timeout : 0x02)); /* 10ms rx timeout */ if (C_CLOCAL(info->tty)) { /* without modem intr */ - cy_writeb((u_long)base_addr+(CySRER<0 modem transitions */ if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb((u_long)base_addr+(CyMCOR1<1 modem transitions */ - cy_writeb((u_long)base_addr+(CyMCOR2<0 modem transitions */ if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb((u_long)base_addr+(CyMCOR1<1 modem transitions */ - cy_writeb((u_long)base_addr+(CyMCOR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; @@ -3617,7 +3538,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) unsigned char status; unsigned int result; unsigned long flags; - unsigned char *base_addr; + void __iomem *base_addr; card = info->card; channel = (info->line) - (cy_card[card].first_line); @@ -3625,8 +3546,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char *) - (cy_card[card].base_addr + (cy_chip_offset[chip]<driver_data; int card,chip,channel,index; - unsigned char *base_addr; + void __iomem *base_addr; unsigned long flags; unsigned char status; unsigned long lstatus; unsigned int result; - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; - struct CH_CTRL *ch_ctrl; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; if (serial_paranoia_check(info, tty->name, __FUNCTION__)) return -ENODEV; @@ -3663,12 +3583,10 @@ cy_tiocmget(struct tty_struct *tty, struct file *file) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; lstatus = cy_readl(&ch_ctrl[channel].rs_status); @@ -3722,12 +3637,12 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, { struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int card,chip,channel,index; - unsigned char *base_addr; + void __iomem *base_addr; unsigned long flags; - struct FIRM_ID *firm_id; - struct ZFW_CTRL *zfw_ctrl; - struct BOARD_CTRL *board_ctrl; - struct CH_CTRL *ch_ctrl; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; int retval; if (serial_paranoia_check(info, tty->name, __FUNCTION__)) @@ -3739,37 +3654,35 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<zfwctrl_addr) & 0xfffff)); + zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -3930,7 +3840,7 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) static int set_threshold(struct cyclades_port * info, unsigned long value) { - unsigned char *base_addr; + void __iomem *base_addr; int card,channel,chip,index; unsigned long flags; @@ -3940,15 +3850,13 @@ set_threshold(struct cyclades_port * info, unsigned long value) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<cor3 &= ~CyREC_FIFO; info->cor3 |= value & CyREC_FIFO; CY_LOCK(info, flags); - cy_writeb((u_long)base_addr+(CyCOR3<cor3); + cy_writeb(base_addr+(CyCOR3<cor3); cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); CY_UNLOCK(info, flags); } else { @@ -3961,7 +3869,7 @@ set_threshold(struct cyclades_port * info, unsigned long value) static int get_threshold(struct cyclades_port * info, unsigned long __user *value) { - unsigned char *base_addr; + void __iomem *base_addr; int card,channel,chip,index; unsigned long tmp; @@ -3971,9 +3879,7 @@ get_threshold(struct cyclades_port * info, unsigned long __user *value) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<driver_data; unsigned long flags; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; #ifdef CY_DEBUG_THROTTLE @@ -4359,16 +4261,14 @@ cy_throttle(struct tty_struct * tty) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<driver_data; unsigned long flags; - unsigned char *base_addr; + void __iomem *base_addr; int card,chip,channel,index; #ifdef CY_DEBUG_THROTTLE @@ -4419,16 +4319,14 @@ cy_unthrottle(struct tty_struct * tty) chip = channel>>2; channel &= 0x03; index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<driver_data; - unsigned char *base_addr; + void __iomem *base_addr; int chip,channel,index; unsigned long flags; @@ -4465,14 +4363,12 @@ cy_stop(struct tty_struct *tty) index = cinfo->bus_index; chip = channel>>2; channel &= 0x03; - base_addr = (unsigned char*) - (cy_card[info->card].base_addr - + (cy_chip_offset[chip]<card].base_addr + (cy_chip_offset[chip]<driver_data; - unsigned char *base_addr; + void __iomem *base_addr; int chip,channel,index; unsigned long flags; @@ -4505,14 +4401,12 @@ cy_start(struct tty_struct *tty) if (!IS_CYC_Z(*cinfo)) { chip = channel>>2; channel &= 0x03; - base_addr = (unsigned char*) - (cy_card[info->card].base_addr - + (cy_chip_offset[chip]<card].base_addr + (cy_chip_offset[chip]<write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); } /* cy_flush_buffer */ @@ -4600,20 +4492,19 @@ cy_hangup(struct tty_struct *tty) /* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ static unsigned short __init -cyy_init_card(volatile ucchar *true_base_addr,int index) +cyy_init_card(void __iomem *true_base_addr,int index) { unsigned int chip_number; - volatile ucchar* base_addr; + void __iomem *base_addr; - cy_writeb((u_long)true_base_addr+(Cy_HwReset<= CD1400_REV_J){ /* It is a CD1400 rev. J or later */ /* Impossible to reach 5ms with this chip. Changed to 2ms instead (f = 500 Hz). */ - cy_writeb((u_long)base_addr+(CyPPR<mail_box_0); if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { @@ -5037,7 +4927,7 @@ cy_detect_pci(void) } if (mailbox == ZE_V1) { - cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win); + cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win); if (ZeIndex == NR_CARDS) { printk("Cyclades-Ze/PCI found at 0x%lx ", (ulong)cy_pci_phys2); @@ -5055,7 +4945,7 @@ cy_detect_pci(void) i--; continue; } else { - cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin); + cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin); } #ifdef CY_PCI_DEBUG @@ -5082,7 +4972,7 @@ cy_detect_pci(void) */ PAUSE if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) - cy_writel((ulong)(cy_pci_addr2+ID_ADDRESS), 0L); + cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); /* This must be a Cyclades-8Zo/PCI. The extendable version will have a different device_id and will @@ -5172,7 +5062,7 @@ cy_detect_pci(void) Ze_pdev[j] = Ze_pdev[j+1]; } ZeIndex--; - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) + mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) cy_pci_addr0)->mail_box_0); #ifdef CY_PCI_DEBUG printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", @@ -5413,7 +5303,7 @@ cy_init(void) for (i = 0; i < NR_CARDS; i++) { /* base_addr=0 indicates board not found */ - cy_card[i].base_addr = 0; + cy_card[i].base_addr = NULL; } /* the code below is responsible to find the boards. Each different @@ -5435,7 +5325,7 @@ cy_init(void) for (i = 0 ; i < NR_CARDS ; i++) { if (cy_card[i].base_addr == 0) { cy_card[i].first_line = -1; - cy_card[i].ctl_addr = 0; + cy_card[i].ctl_addr = NULL; cy_card[i].irq = 0; cy_card[i].bus_index = 0; cy_card[i].first_line = 0; @@ -5453,7 +5343,7 @@ cy_init(void) cinfo = &cy_card[board]; if (cinfo->num_chips == -1) { /* Cyclades-Z */ number_z_boards++; - mailbox = cy_readl(&((struct RUNTIME_9060 *) + mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) cy_card[board].ctl_addr)->mail_box_0); nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; cinfo->intr_enabled = 0; @@ -5623,10 +5513,10 @@ cy_cleanup_module(void) put_tty_driver(cy_serial_driver); for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr != 0) { - iounmap((void *)cy_card[i].base_addr); - if (cy_card[i].ctl_addr != 0) - iounmap((void *)cy_card[i].ctl_addr); + if (cy_card[i].base_addr) { + iounmap(cy_card[i].base_addr); + if (cy_card[i].ctl_addr) + iounmap(cy_card[i].ctl_addr); if (cy_card[i].irq #ifndef CONFIG_CYZ_INTR && cy_card[i].num_chips != -1 /* not a Z card */ @@ -5661,7 +5551,7 @@ cy_setup(char *str, int *ints) } for (j = 1; j <= ints[0]; j++){ if ( i < NR_ISA_ADDRS ){ - cy_isa_addresses[i++] = (unsigned char *)(ints[j]); + cy_isa_addresses[i++] = ints[j]; } } #endif /* CONFIG_ISA */ diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 13797ca0c..0f210ceaf 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig @@ -24,14 +24,14 @@ config DRM_TDFX config DRM_GAMMA tristate "3dlabs GMX 2000" - depends on DRM + depends on DRM && BROKEN help This is the old gamma driver, please tell me if it might actually work. config DRM_R128 tristate "ATI Rage 128" - depends on DRM + depends on DRM && PCI help Choose this option if you have an ATI Rage 128 graphics card. If M is selected, the module will be called r128. AGP support for @@ -39,7 +39,7 @@ config DRM_R128 config DRM_RADEON tristate "ATI Radeon" - depends on DRM + depends on DRM && PCI help Choose this option if you have an ATI Radeon graphics card. There are both PCI and AGP versions. You don't need to choose this to @@ -55,14 +55,29 @@ config DRM_I810 selected, the module will be called i810. AGP support is required for this driver to work. -config DRM_I830 - tristate "Intel 830M, 845G, 852GM, 855GM, 865G" +choice + prompt "Intel 830M, 845G, 852GM, 855GM, 865G" depends on DRM && AGP && AGP_INTEL + optional + +config DRM_I830 + tristate "i830 driver" help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM or 865G integrated graphics. If M is selected, the module will be called i830. AGP support is required for this driver - to work. + to work. This driver will eventually be replaced by the i915 one. + +config DRM_I915 + tristate "i915 driver" + help + Choose this option if you have a system that has Intel 830M, 845G, + 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the + module will be called i915. AGP support is required for this driver + to work. This driver will eventually replace the I830 driver, when + later release of X start to use the new DDX and DRI. + +endchoice config DRM_MGA tristate "Matrox g200/g400" diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index f0acc5e48..d59102e2e 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile @@ -8,6 +8,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o i810-objs := i810_drv.o i810_dma.o i830-objs := i830_drv.o i830_dma.o i830_irq.o +i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o ffb-objs := ffb_drv.o ffb_context.o sis-objs := sis_drv.o sis_ds.o sis_mm.o @@ -19,6 +20,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon.o obj-$(CONFIG_DRM_MGA) += mga.o obj-$(CONFIG_DRM_I810) += i810.o obj-$(CONFIG_DRM_I830) += i830.o +obj-$(CONFIG_DRM_I915) += i915.o obj-$(CONFIG_DRM_FFB) += ffb.o obj-$(CONFIG_DRM_SIS) += sis.o diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 88886cbf9..65351d518 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -73,42 +73,26 @@ #include #include "drm.h" -#include "drm_os_linux.h" +#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) +#define __OS_HAS_MTRR (defined(CONFIG_MTRR)) +#include "drm_os_linux.h" /***********************************************************************/ /** \name DRM template customization defaults */ /*@{*/ -#ifndef __HAVE_AGP -#define __HAVE_AGP 0 -#endif -#ifndef __HAVE_MTRR -#define __HAVE_MTRR 0 -#endif -#ifndef __HAVE_CTX_BITMAP -#define __HAVE_CTX_BITMAP 0 -#endif -#ifndef __HAVE_DMA -#define __HAVE_DMA 0 -#endif -#ifndef __HAVE_IRQ -#define __HAVE_IRQ 0 -#endif -#ifndef __HAVE_DMA_WAITLIST -#define __HAVE_DMA_WAITLIST 0 -#endif -#ifndef __HAVE_DMA_FREELIST -#define __HAVE_DMA_FREELIST 0 -#endif - -#define __REALLY_HAVE_AGP (__HAVE_AGP && (defined(CONFIG_AGP) || \ - defined(CONFIG_AGP_MODULE))) -#define __REALLY_HAVE_MTRR (__HAVE_MTRR && defined(CONFIG_MTRR)) -#define __REALLY_HAVE_SG (__HAVE_SG) - -/*@}*/ - +/* driver capabilities and requirements mask */ +#define DRIVER_USE_AGP 0x1 +#define DRIVER_REQUIRE_AGP 0x2 +#define DRIVER_USE_MTRR 0x4 +#define DRIVER_PCI_DMA 0x8 +#define DRIVER_SG 0x10 +#define DRIVER_HAVE_DMA 0x20 +#define DRIVER_HAVE_IRQ 0x40 +#define DRIVER_IRQ_SHARED 0x80 +#define DRIVER_IRQ_VBL 0x100 +#define DRIVER_DMA_QUEUE 0x200 /***********************************************************************/ /** \name Begin the DRM... */ @@ -265,54 +249,6 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr) /*@}*/ -/***********************************************************************/ -/** \name Mapping helper macros */ -/*@{*/ - -#define DRM_IOREMAP(map, dev) \ - (map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) ) - -#define DRM_IOREMAP_NOCACHE(map, dev) \ - (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev)) - -#define DRM_IOREMAPFREE(map, dev) \ - do { \ - if ( (map)->handle && (map)->size ) \ - DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \ - } while (0) - -/** - * Find mapping. - * - * \param _map matching mapping if found, untouched otherwise. - * \param _o offset. - * - * Expects the existence of a local variable named \p dev pointing to the - * drm_device structure. - */ -#define DRM_FIND_MAP(_map, _o) \ -do { \ - struct list_head *_list; \ - list_for_each( _list, &dev->maplist->head ) { \ - drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head ); \ - if ( _entry->map && \ - _entry->map->offset == (_o) ) { \ - (_map) = _entry->map; \ - break; \ - } \ - } \ -} while(0) - -/** - * Drop mapping. - * - * \sa #DRM_FIND_MAP. - */ -#define DRM_DROP_MAP(_map) - -/*@}*/ - - /***********************************************************************/ /** \name Internal types and structures */ /*@{*/ @@ -473,9 +409,7 @@ typedef struct drm_file { struct drm_device *dev; int remove_auth_on_close; unsigned long lock_count; -#ifdef DRIVER_FILE_FIELDS - DRIVER_FILE_FIELDS; -#endif + void *driver_priv; } drm_file_t; /** Wait queue */ @@ -524,16 +458,8 @@ typedef struct drm_device_dma { _DRM_DMA_USE_SG = 0x02 } flags; - /** \name DMA support */ - /*@{*/ - drm_buf_t *this_buffer; /**< Buffer being sent */ - drm_buf_t *next_buffer; /**< Selected buffer to send */ - drm_queue_t *next_queue; /**< Queue from which buffer selected*/ - wait_queue_head_t waiting; /**< Processes waiting on free bufs */ - /*@}*/ } drm_device_dma_t; -#if __REALLY_HAVE_AGP /** * AGP memory entry. Stored as a doubly linked list. */ @@ -562,7 +488,6 @@ typedef struct drm_agp_head { int cant_use_aperture; unsigned long page_mask; } drm_agp_head_t; -#endif /** * Scatter-gather memory. @@ -599,7 +524,6 @@ typedef struct drm_ctx_list { drm_file_t *tag; /**< associated fd private data */ } drm_ctx_list_t; -#ifdef __HAVE_VBL_IRQ typedef struct drm_vbl_sig { struct list_head head; @@ -608,8 +532,40 @@ typedef struct drm_vbl_sig { struct task_struct *task; } drm_vbl_sig_t; -#endif +/** + * DRM device functions structure + */ +struct drm_device; + +struct drm_driver_fn { + int (*preinit)(struct drm_device *); + int (*postinit)(struct drm_device *); + void (*prerelease)(struct drm_device *, struct file *filp); + void (*pretakedown)(struct drm_device *); + int (*postcleanup)(struct drm_device *); + int (*presetup)(struct drm_device *); + int (*postsetup)(struct drm_device *); + int (*open_helper)(struct drm_device *, drm_file_t *); + void (*free_filp_priv)(struct drm_device *, drm_file_t *); + void (*release)(struct drm_device *, struct file *filp); + void (*dma_ready)(struct drm_device *); + int (*dma_quiescent)(struct drm_device *); + int (*context_ctor)(struct drm_device *dev, int context); + int (*context_dtor)(struct drm_device *dev, int context); + int (*kernel_context_switch)(struct drm_device *dev, int old, int new); + void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock); + int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence); + /* these have to be filled in */ + irqreturn_t (*irq_handler)( DRM_IRQ_ARGS ); + void (*irq_preinstall)(struct drm_device *dev); + void (*irq_postinstall)(struct drm_device *dev); + void (*irq_uninstall)(struct drm_device *dev); + void (*reclaim_buffers)(struct file *filp); + unsigned long (*get_map_ofs)(drm_map_t *map); + unsigned long (*get_reg_ofs)(struct drm_device *dev); + void (*set_version)(struct drm_device *dev, drm_set_version_t *sv); +}; /** * DRM device structure. */ @@ -698,13 +654,13 @@ typedef struct drm_device { struct work_struct work; /** \name VBLANK IRQ support */ /*@{*/ -#ifdef __HAVE_VBL_IRQ + wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ atomic_t vbl_received; spinlock_t vbl_lock; drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */ unsigned int vbl_pending; -#endif + /*@}*/ cycles_t ctx_start; cycles_t lck_start; @@ -717,9 +673,7 @@ typedef struct drm_device { wait_queue_head_t buf_readers; /**< Processes waiting to read */ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */ -#if __REALLY_HAVE_AGP drm_agp_head_t *agp; /**< AGP data */ -#endif struct pci_dev *pdev; /**< PCI device structure */ int pci_domain; /**< PCI bus domain number */ @@ -738,8 +692,37 @@ typedef struct drm_device { void *dev_private; /**< device private data */ drm_sigdata_t sigdata; /**< For block_all_signals */ sigset_t sigmask; + + struct drm_driver_fn fn_tbl; + drm_local_map_t *agp_buffer_map; + int dev_priv_size; + u32 driver_features; } drm_device_t; +static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature) +{ + return ((dev->driver_features & feature) ? 1 : 0); +} + +#if __OS_HAS_AGP +static inline int drm_core_has_AGP(struct drm_device *dev) +{ + return drm_core_check_feature(dev, DRIVER_USE_AGP); +} +#else +#define drm_core_has_AGP(dev) (0) +#endif + +#if __OS_HAS_MTRR +static inline int drm_core_has_MTRR(struct drm_device *dev) +{ + return drm_core_check_feature(dev, DRIVER_USE_MTRR); +} +#else +#define drm_core_has_MTRR(dev) (0) +#endif + +extern void DRM(driver_register_fns)(struct drm_device *dev); /******************************************************************/ /** \name Internal function definitions */ @@ -795,12 +778,10 @@ extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev); extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); -#if __REALLY_HAVE_AGP extern DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type); extern int DRM(free_agp)(DRM_AGP_MEM *handle, int pages); extern int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start); extern int DRM(unbind_agp)(DRM_AGP_MEM *handle); -#endif /* Misc. IOCTL support (drm_ioctl.h) */ extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp, @@ -837,10 +818,8 @@ extern int DRM(rmctx)( struct inode *inode, struct file *filp, extern int DRM(context_switch)(drm_device_t *dev, int old, int new); extern int DRM(context_switch_complete)(drm_device_t *dev, int new); -#if __HAVE_CTX_BITMAP extern int DRM(ctxbitmap_init)( drm_device_t *dev ); extern void DRM(ctxbitmap_cleanup)( drm_device_t *dev ); -#endif extern int DRM(setsareactx)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -884,7 +863,6 @@ extern int DRM(addmap)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int DRM(rmmap)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -#if __HAVE_DMA extern int DRM(addbufs)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int DRM(infobufs)( struct inode *inode, struct file *filp, @@ -901,33 +879,22 @@ extern int DRM(dma_setup)(drm_device_t *dev); extern void DRM(dma_takedown)(drm_device_t *dev); extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf); extern void DRM(reclaim_buffers)( struct file *filp ); -#endif /* __HAVE_DMA */ /* IRQ support (drm_irq.h) */ -#if __HAVE_IRQ || __HAVE_DMA extern int DRM(control)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -#endif -#if __HAVE_IRQ extern int DRM(irq_install)( drm_device_t *dev ); extern int DRM(irq_uninstall)( drm_device_t *dev ); extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ); extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); extern void DRM(driver_irq_uninstall)( drm_device_t *dev ); -#ifdef __HAVE_VBL_IRQ + extern int DRM(wait_vblank)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq); extern void DRM(vbl_send_signals)( drm_device_t *dev ); -#endif -#ifdef __HAVE_IRQ_BH -extern void DRM(irq_immediate_bh)( void *dev ); -#endif -#endif - -#if __REALLY_HAVE_AGP /* AGP/GART support (drm_agpsupport.h) */ extern drm_agp_head_t *DRM(agp_init)(void); extern void DRM(agp_uninit)(void); @@ -952,7 +919,6 @@ extern DRM_AGP_MEM *DRM(agp_allocate_memory)(size_t pages, u32 type); extern int DRM(agp_free_memory)(DRM_AGP_MEM *handle); extern int DRM(agp_bind_memory)(DRM_AGP_MEM *handle, off_t start); extern int DRM(agp_unbind_memory)(DRM_AGP_MEM *handle); -#endif /* Stub support (drm_stub.h) */ int DRM(stub_register)(const char *name, @@ -969,14 +935,12 @@ extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); -#ifdef __HAVE_SG /* Scatter Gather Support (drm_scatter.h) */ extern void DRM(sg_cleanup)(drm_sg_mem_t *entry); extern int DRM(sg_alloc)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int DRM(sg_free)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#endif /* ATI PCIGART support (ati_pcigart.h) */ extern int DRM(ati_pcigart_init)(drm_device_t *dev, @@ -986,7 +950,44 @@ extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev, unsigned long addr, dma_addr_t bus_addr); + +/* Inline replacements for DRM_IOREMAP macros */ +static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) +{ + map->handle = DRM(ioremap)( map->offset, map->size, dev ); +} + +static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev) +{ + map->handle = DRM(ioremap_nocache)(map->offset, map->size, dev); +} + +static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) +{ + if ( map->handle && map->size ) + DRM(ioremapfree)( map->handle, map->size, dev ); +} + +static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset) +{ + struct list_head *_list; + list_for_each( _list, &dev->maplist->head ) { + drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head ); + if ( _entry->map && + _entry->map->offset == offset ) { + return _entry->map; + } + } + return NULL; +} + +static __inline__ void drm_core_dropmap(struct drm_map *map) +{ +} /*@}*/ +extern unsigned long DRM(core_get_map_ofs)(drm_map_t *map); +extern unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev); + #endif /* __KERNEL__ */ #endif diff --git a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h index 491c3051c..81b595e0e 100644 --- a/drivers/char/drm/drm_agpsupport.h +++ b/drivers/char/drm/drm_agpsupport.h @@ -34,8 +34,7 @@ #include "drmP.h" #include -#if __REALLY_HAVE_AGP - +#if __OS_HAS_AGP #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp") #define DRM_AGP_PUT inter_module_put("drm_agp") @@ -466,4 +465,4 @@ int DRM(agp_unbind_memory)(DRM_AGP_MEM *handle) return drm_agp->unbind_memory(handle); } -#endif /* __REALLY_HAVE_AGP */ +#endif /* __OS_HAS_AGP */ diff --git a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h index 6fa862372..19695693f 100644 --- a/drivers/char/drm/drm_bufs.h +++ b/drivers/char/drm/drm_bufs.h @@ -36,26 +36,6 @@ #include #include "drmP.h" -#ifndef __HAVE_PCI_DMA -#define __HAVE_PCI_DMA 0 -#endif - -#ifndef __HAVE_SG -#define __HAVE_SG 0 -#endif - -#ifndef DRIVER_BUF_PRIV_T -#define DRIVER_BUF_PRIV_T u32 -#endif -#ifndef DRIVER_AGP_BUFFERS_MAP -#if __HAVE_AGP && __HAVE_DMA -#error "You must define DRIVER_AGP_BUFFERS_MAP()" -#else -#define DRIVER_AGP_BUFFERS_MAP( dev ) NULL -#endif -#endif - - /** * Compute size order. Returns the exponent of the smaller power of two which * is greater or equal to given number. @@ -142,13 +122,13 @@ int DRM(addmap)( struct inode *inode, struct file *filp, #ifdef __alpha__ map->offset += dev->hose->mem_space->start; #endif -#if __REALLY_HAVE_MTRR - if ( map->type == _DRM_FRAME_BUFFER || - (map->flags & _DRM_WRITE_COMBINING) ) { - map->mtrr = mtrr_add( map->offset, map->size, - MTRR_TYPE_WRCOMB, 1 ); + if (drm_core_has_MTRR(dev)) { + if ( map->type == _DRM_FRAME_BUFFER || + (map->flags & _DRM_WRITE_COMBINING) ) { + map->mtrr = mtrr_add( map->offset, map->size, + MTRR_TYPE_WRCOMB, 1 ); + } } -#endif if (map->type == _DRM_REGISTERS) map->handle = DRM(ioremap)( map->offset, map->size, dev ); @@ -174,15 +154,15 @@ int DRM(addmap)( struct inode *inode, struct file *filp, dev->lock.hw_lock = map->handle; /* Pointer to lock */ } break; -#if __REALLY_HAVE_AGP case _DRM_AGP: + if (drm_core_has_AGP(dev)) { #ifdef __alpha__ - map->offset += dev->hose->mem_space->start; + map->offset += dev->hose->mem_space->start; #endif - map->offset += dev->agp->base; - map->mtrr = dev->agp->agp_mtrr; /* for getmap */ + map->offset += dev->agp->base; + map->mtrr = dev->agp->agp_mtrr; /* for getmap */ + } break; -#endif case _DRM_SCATTER_GATHER: if (!dev->sg) { DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); @@ -282,15 +262,15 @@ int DRM(rmmap)(struct inode *inode, struct file *filp, switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); + if (drm_core_has_MTRR(dev)) { + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } } -#endif DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: @@ -306,8 +286,6 @@ int DRM(rmmap)(struct inode *inode, struct file *filp, return 0; } -#if __HAVE_DMA - /** * Cleanup after an error on one of the addbufs() functions. * @@ -348,15 +326,11 @@ static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) sizeof(*entry->buflist), DRM_MEM_BUFS); -#if __HAVE_DMA_FREELIST - DRM(freelist_destroy)(&entry->freelist); -#endif - entry->buf_count = 0; } } -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP /** * Add AGP buffers for DMA transfers (ioctl). * @@ -473,8 +447,8 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp, init_waitqueue_head( &buf->dma_wait ); buf->filp = NULL; - buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); - buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), + buf->dev_priv_size = dev->dev_priv_size; + buf->dev_private = DRM(alloc)( buf->dev_priv_size, DRM_MEM_BUFS ); if(!buf->dev_private) { /* Set count correctly so we free the proper amount. */ @@ -520,12 +494,6 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp, DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count ); DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count ); -#if __HAVE_DMA_FREELIST - DRM(freelist_create)( &entry->freelist, entry->buf_count ); - for ( i = 0 ; i < entry->buf_count ; i++ ) { - DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); - } -#endif up( &dev->struct_sem ); request.count = entry->buf_count; @@ -539,9 +507,8 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp, atomic_dec( &dev->buf_alloc ); return 0; } -#endif /* __REALLY_HAVE_AGP */ +#endif /* __OS_HAS_AGP */ -#if __HAVE_PCI_DMA int DRM(addbufs_pci)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { @@ -566,6 +533,7 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp, drm_buf_t **temp_buflist; drm_buf_desc_t __user *argp = (void __user *)arg; + if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL; if ( !dma ) return -EINVAL; if ( copy_from_user( &request, argp, sizeof(request) ) ) @@ -697,8 +665,8 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp, init_waitqueue_head( &buf->dma_wait ); buf->filp = NULL; - buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); - buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), + buf->dev_priv_size = dev->dev_priv_size; + buf->dev_private = DRM(alloc)( dev->dev_priv_size, DRM_MEM_BUFS ); if(!buf->dev_private) { /* Set count correctly so we free the proper amount. */ @@ -758,12 +726,6 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp, dma->page_count += entry->seg_count << page_order; dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); -#if __HAVE_DMA_FREELIST - DRM(freelist_create)( &entry->freelist, entry->buf_count ); - for ( i = 0 ; i < entry->buf_count ; i++ ) { - DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); - } -#endif up( &dev->struct_sem ); request.count = entry->buf_count; @@ -776,9 +738,7 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp, return 0; } -#endif /* __HAVE_PCI_DMA */ -#if __HAVE_SG int DRM(addbufs_sg)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { @@ -801,6 +761,8 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp, int i; drm_buf_t **temp_buflist; + if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; + if ( !dma ) return -EINVAL; if ( copy_from_user( &request, argp, sizeof(request) ) ) @@ -881,8 +843,8 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp, init_waitqueue_head( &buf->dma_wait ); buf->filp = NULL; - buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); - buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), + buf->dev_priv_size = dev->dev_priv_size; + buf->dev_private = DRM(alloc)( dev->dev_priv_size, DRM_MEM_BUFS ); if(!buf->dev_private) { /* Set count correctly so we free the proper amount. */ @@ -929,12 +891,6 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp, DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count ); DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count ); -#if __HAVE_DMA_FREELIST - DRM(freelist_create)( &entry->freelist, entry->buf_count ); - for ( i = 0 ; i < entry->buf_count ; i++ ) { - DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); - } -#endif up( &dev->struct_sem ); request.count = entry->buf_count; @@ -948,7 +904,6 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp, atomic_dec( &dev->buf_alloc ); return 0; } -#endif /* __HAVE_SG */ /** * Add buffers for DMA transfers (ioctl). @@ -968,26 +923,25 @@ int DRM(addbufs)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { drm_buf_desc_t request; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + return -EINVAL; if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg, sizeof(request) ) ) return -EFAULT; -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( request.flags & _DRM_AGP_BUFFER ) return DRM(addbufs_agp)( inode, filp, cmd, arg ); else #endif -#if __HAVE_SG if ( request.flags & _DRM_SG_BUFFER ) return DRM(addbufs_sg)( inode, filp, cmd, arg ); else -#endif -#if __HAVE_PCI_DMA return DRM(addbufs_pci)( inode, filp, cmd, arg ); -#else - return -EINVAL; -#endif } @@ -1019,6 +973,9 @@ int DRM(infobufs)( struct inode *inode, struct file *filp, int i; int count; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + return -EINVAL; + if ( !dma ) return -EINVAL; spin_lock( &dev->count_lock ); @@ -1100,6 +1057,9 @@ int DRM(markbufs)( struct inode *inode, struct file *filp, int order; drm_buf_entry_t *entry; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + return -EINVAL; + if ( !dma ) return -EINVAL; if ( copy_from_user( &request, @@ -1147,6 +1107,9 @@ int DRM(freebufs)( struct inode *inode, struct file *filp, int idx; drm_buf_t *buf; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + return -EINVAL; + if ( !dma ) return -EINVAL; if ( copy_from_user( &request, @@ -1204,6 +1167,9 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp, drm_buf_map_t request; int i; + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + return -EINVAL; + if ( !dma ) return -EINVAL; spin_lock( &dev->count_lock ); @@ -1218,9 +1184,9 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp, return -EFAULT; if ( request.count >= dma->buf_count ) { - if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) || - (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) { - drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev ); + if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) || + (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) { + drm_map_t *map = dev->agp_buffer_map; if ( !map ) { retcode = -EINVAL; @@ -1301,4 +1267,3 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp, return retcode; } -#endif /* __HAVE_DMA */ diff --git a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h index d8000cfbf..b99c99475 100644 --- a/drivers/char/drm/drm_context.h +++ b/drivers/char/drm/drm_context.h @@ -42,11 +42,6 @@ #include "drmP.h" -#if !__HAVE_CTX_BITMAP -#error "__HAVE_CTX_BITMAP must be defined" -#endif - - /******************************************************************/ /** \name Context bitmap support */ /*@{*/ @@ -419,10 +414,13 @@ int DRM(addctx)( struct inode *inode, struct file *filp, /* Should this return -EBUSY instead? */ return -ENOMEM; } -#ifdef DRIVER_CTX_CTOR + if ( ctx.handle != DRM_KERNEL_CONTEXT ) - DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */ -#endif + { + if (dev->fn_tbl.context_ctor) + dev->fn_tbl.context_ctor(dev, ctx.handle); + } + ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST ); if ( !ctx_entry ) { DRM_DEBUG("out of memory\n"); @@ -554,9 +552,8 @@ int DRM(rmctx)( struct inode *inode, struct file *filp, priv->remove_auth_on_close = 1; } if ( ctx.handle != DRM_KERNEL_CONTEXT ) { -#ifdef DRIVER_CTX_DTOR - DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */ -#endif + if (dev->fn_tbl.context_dtor) + dev->fn_tbl.context_dtor(dev, ctx.handle); DRM(ctxbitmap_free)( dev, ctx.handle ); } @@ -578,3 +575,4 @@ int DRM(rmctx)( struct inode *inode, struct file *filp, } /*@}*/ + diff --git a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h index 72122754d..5cbdc9315 100644 --- a/drivers/char/drm/drm_dma.h +++ b/drivers/char/drm/drm_dma.h @@ -35,16 +35,6 @@ #include "drmP.h" - -#ifndef __HAVE_DMA_WAITQUEUE -#define __HAVE_DMA_WAITQUEUE 0 -#endif -#ifndef __HAVE_DMA_RECLAIM -#define __HAVE_DMA_RECLAIM 0 -#endif - -#if __HAVE_DMA - /** * Initialize the DMA data. * @@ -116,9 +106,6 @@ void DRM(dma_takedown)(drm_device_t *dev) dma->bufs[i].buf_count * sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS); -#if __HAVE_DMA_FREELIST - DRM(freelist_destroy)(&dma->bufs[i].freelist); -#endif } } @@ -155,22 +142,11 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf) buf->filp = NULL; buf->used = 0; - if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) { + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) { wake_up_interruptible(&buf->dma_wait); } -#if __HAVE_DMA_FREELIST - else { - drm_device_dma_t *dma = dev->dma; - /* If processes are waiting, the last one - to wake will put the buffer on the free - list. If no processes are waiting, we - put the buffer on the freelist here. */ - DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf); - } -#endif } -#if !__HAVE_DMA_RECLAIM /** * Reclaim the buffers. * @@ -178,7 +154,7 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf) * * Frees each buffer associated with \p filp not already on the hardware. */ -void DRM(reclaim_buffers)( struct file *filp ) +void DRM(core_reclaim_buffers)( struct file *filp ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; @@ -202,29 +178,4 @@ void DRM(reclaim_buffers)( struct file *filp ) } } } -#endif - -#if !__HAVE_IRQ -/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require - * IRQs for DMA but no longer do. It maintains compatibility with the X Servers - * that try to use the control ioctl by simply returning success. - */ -int DRM(control)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_control_t ctl; - - if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) ) - return -EFAULT; - - switch ( ctl.func ) { - case DRM_INST_HANDLER: - case DRM_UNINST_HANDLER: - return 0; - default: - return -EINVAL; - } -} -#endif -#endif /* __HAVE_DMA */ diff --git a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h index 389fc7ef2..39a0235a3 100644 --- a/drivers/char/drm/drm_drv.h +++ b/drivers/char/drm/drm_drv.h @@ -52,97 +52,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __MUST_HAVE_AGP -#define __MUST_HAVE_AGP 0 -#endif -#ifndef __HAVE_CTX_BITMAP -#define __HAVE_CTX_BITMAP 0 -#endif -#ifndef __HAVE_IRQ -#define __HAVE_IRQ 0 -#endif -#ifndef __HAVE_DMA_QUEUE -#define __HAVE_DMA_QUEUE 0 -#endif -#ifndef __HAVE_MULTIPLE_DMA_QUEUES -#define __HAVE_MULTIPLE_DMA_QUEUES 0 -#endif -#ifndef __HAVE_DMA_SCHEDULE -#define __HAVE_DMA_SCHEDULE 0 -#endif -#ifndef __HAVE_DMA_FLUSH -#define __HAVE_DMA_FLUSH 0 -#endif -#ifndef __HAVE_DMA_READY -#define __HAVE_DMA_READY 0 -#endif -#ifndef __HAVE_DMA_QUIESCENT -#define __HAVE_DMA_QUIESCENT 0 -#endif -#ifndef __HAVE_RELEASE -#define __HAVE_RELEASE 0 -#endif -#ifndef __HAVE_COUNTERS -#define __HAVE_COUNTERS 0 -#endif -#ifndef __HAVE_SG -#define __HAVE_SG 0 -#endif -/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm modules in - * the DRI cvs tree, but it is required by the kernel tree's sparc - * driver. - */ -#ifndef __HAVE_KERNEL_CTX_SWITCH -#define __HAVE_KERNEL_CTX_SWITCH 0 -#endif -#ifndef __HAVE_DRIVER_FOPS_READ -#define __HAVE_DRIVER_FOPS_READ 0 -#endif -#ifndef __HAVE_DRIVER_FOPS_POLL -#define __HAVE_DRIVER_FOPS_POLL 0 -#endif - -#ifndef DRIVER_PREINIT -#define DRIVER_PREINIT() -#endif -#ifndef DRIVER_POSTINIT -#define DRIVER_POSTINIT() -#endif -#ifndef DRIVER_PRERELEASE -#define DRIVER_PRERELEASE() -#endif -#ifndef DRIVER_PRETAKEDOWN -#define DRIVER_PRETAKEDOWN() -#endif -#ifndef DRIVER_POSTCLEANUP -#define DRIVER_POSTCLEANUP() -#endif -#ifndef DRIVER_PRESETUP -#define DRIVER_PRESETUP() -#endif -#ifndef DRIVER_POSTSETUP -#define DRIVER_POSTSETUP() -#endif #ifndef DRIVER_IOCTLS #define DRIVER_IOCTLS #endif -#ifndef DRIVER_OPEN_HELPER -#define DRIVER_OPEN_HELPER( priv, dev ) -#endif -#ifndef DRIVER_FOPS -#define DRIVER_FOPS \ -static struct file_operations DRM(fops) = { \ - .owner = THIS_MODULE, \ - .open = DRM(open), \ - .flush = DRM(flush), \ - .release = DRM(release), \ - .ioctl = DRM(ioctl), \ - .mmap = DRM(mmap), \ - .fasync = DRM(fasync), \ - .poll = DRM(poll), \ - .read = DRM(read), \ -} -#endif #ifndef MODULE /** Use an additional macro to avoid preprocessor troubles */ @@ -166,16 +78,24 @@ __setup( DRIVER_NAME "=", DRM_OPTIONS_FUNC ); static drm_device_t DRM(device)[MAX_DEVICES]; static int DRM(numdevs) = 0; -DRIVER_FOPS; +struct file_operations DRM(fops) = { + .owner = THIS_MODULE, + .open = DRM(open), + .flush = DRM(flush), + .release = DRM(release), + .ioctl = DRM(ioctl), + .mmap = DRM(mmap), + .fasync = DRM(fasync), + .poll = DRM(poll), + .read = DRM(read), +}; /** Ioctl table */ -static drm_ioctl_desc_t DRM(ioctls)[] = { +drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 }, -#if __HAVE_IRQ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 }, -#endif [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 }, @@ -189,10 +109,8 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { DRM(addmap), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { DRM(rmmap), 1, 0 }, -#if __HAVE_CTX_BITMAP [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 }, -#endif [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { DRM(addctx), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { DRM(rmctx), 1, 1 }, @@ -208,26 +126,18 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { DRM(lock), 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { DRM(unlock), 1, 0 }, -#if __HAVE_DMA_FLUSH - /* Gamma only, really */ - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(finish), 1, 0 }, -#else [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(noop), 1, 0 }, -#endif -#if __HAVE_DMA [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { DRM(addbufs), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { DRM(markbufs), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 }, /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ -#endif -#if __HAVE_IRQ || __HAVE_DMA + [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 }, -#endif -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable), 1, 1 }, @@ -238,14 +148,10 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 }, #endif -#if __HAVE_SG [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 }, -#endif -#ifdef __HAVE_VBL_IRQ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 }, -#endif DRIVER_IOCTLS }; @@ -264,56 +170,26 @@ MODULE_LICENSE("GPL and additional rights"); static int DRM(setup)( drm_device_t *dev ) { int i; + int ret; + + if (dev->fn_tbl.presetup) + { + ret=dev->fn_tbl.presetup(dev); + if (ret!=0) + return ret; + } - DRIVER_PRESETUP(); atomic_set( &dev->ioctl_count, 0 ); atomic_set( &dev->vma_count, 0 ); dev->buf_use = 0; atomic_set( &dev->buf_alloc, 0 ); -#if __HAVE_DMA - i = DRM(dma_setup)( dev ); - if ( i < 0 ) - return i; -#endif - - dev->counters = 6 + __HAVE_COUNTERS; - dev->types[0] = _DRM_STAT_LOCK; - dev->types[1] = _DRM_STAT_OPENS; - dev->types[2] = _DRM_STAT_CLOSES; - dev->types[3] = _DRM_STAT_IOCTLS; - dev->types[4] = _DRM_STAT_LOCKS; - dev->types[5] = _DRM_STAT_UNLOCKS; -#ifdef __HAVE_COUNTER6 - dev->types[6] = __HAVE_COUNTER6; -#endif -#ifdef __HAVE_COUNTER7 - dev->types[7] = __HAVE_COUNTER7; -#endif -#ifdef __HAVE_COUNTER8 - dev->types[8] = __HAVE_COUNTER8; -#endif -#ifdef __HAVE_COUNTER9 - dev->types[9] = __HAVE_COUNTER9; -#endif -#ifdef __HAVE_COUNTER10 - dev->types[10] = __HAVE_COUNTER10; -#endif -#ifdef __HAVE_COUNTER11 - dev->types[11] = __HAVE_COUNTER11; -#endif -#ifdef __HAVE_COUNTER12 - dev->types[12] = __HAVE_COUNTER12; -#endif -#ifdef __HAVE_COUNTER13 - dev->types[13] = __HAVE_COUNTER13; -#endif -#ifdef __HAVE_COUNTER14 - dev->types[14] = __HAVE_COUNTER14; -#endif -#ifdef __HAVE_COUNTER15 - dev->types[14] = __HAVE_COUNTER14; -#endif + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + { + i = DRM(dma_setup)( dev ); + if ( i < 0 ) + return i; + } for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ ) atomic_set( &dev->counts[i], 0 ); @@ -371,7 +247,9 @@ static int DRM(setup)( drm_device_t *dev ) * drm_select_queue fails between the time the interrupt is * initialized and the time the queues are initialized. */ - DRIVER_POSTSETUP(); + if (dev->fn_tbl.postsetup) + dev->fn_tbl.postsetup(dev); + return 0; } @@ -396,10 +274,10 @@ static int DRM(takedown)( drm_device_t *dev ) DRM_DEBUG( "\n" ); - DRIVER_PRETAKEDOWN(); -#if __HAVE_IRQ + if (dev->fn_tbl.pretakedown) + dev->fn_tbl.pretakedown(dev); + if ( dev->irq_enabled ) DRM(irq_uninstall)( dev ); -#endif down( &dev->struct_sem ); del_timer( &dev->timer ); @@ -425,9 +303,8 @@ static int DRM(takedown)( drm_device_t *dev ) dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } -#if __REALLY_HAVE_AGP /* Clear AGP information */ - if ( dev->agp ) { + if (drm_core_has_AGP(dev) && dev->agp) { drm_agp_mem_t *entry; drm_agp_mem_t *nexte; @@ -446,7 +323,6 @@ static int DRM(takedown)( drm_device_t *dev ) dev->agp->acquired = 0; dev->agp->enabled = 0; } -#endif /* Clear vma list (only built for debugging) */ if ( dev->vmalist ) { @@ -465,15 +341,15 @@ static int DRM(takedown)( drm_device_t *dev ) switch ( map->type ) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if ( map->mtrr >= 0 ) { - int retcode; - retcode = mtrr_del( map->mtrr, - map->offset, - map->size ); - DRM_DEBUG( "mtrr_del=%d\n", retcode ); + if (drm_core_has_MTRR(dev)) { + if ( map->mtrr >= 0 ) { + int retcode; + retcode = mtrr_del( map->mtrr, + map->offset, + map->size ); + DRM_DEBUG( "mtrr_del=%d\n", retcode ); + } } -#endif DRM(ioremapfree)( map->handle, map->size, dev ); break; case _DRM_SHM: @@ -486,15 +362,11 @@ static int DRM(takedown)( drm_device_t *dev ) */ break; case _DRM_SCATTER_GATHER: - /* Handle it, but do nothing, if HAVE_SG - * isn't defined. - */ -#if __HAVE_SG - if(dev->sg) { + /* Handle it */ + if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { DRM(sg_cleanup)(dev->sg); dev->sg = NULL; } -#endif break; } DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); @@ -506,12 +378,8 @@ static int DRM(takedown)( drm_device_t *dev ) dev->maplist = NULL; } -#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES - if ( dev->queuelist ) { + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) { for ( i = 0 ; i < dev->queue_count ; i++ ) { -#if __HAVE_DMA_WAITLIST - DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist ); -#endif if ( dev->queuelist[i] ) { DRM(free)( dev->queuelist[i], sizeof(*dev->queuelist[0]), @@ -525,11 +393,10 @@ static int DRM(takedown)( drm_device_t *dev ) dev->queuelist = NULL; } dev->queue_count = 0; -#endif -#if __HAVE_DMA - DRM(dma_takedown)( dev ); -#endif + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + DRM(dma_takedown)( dev ); + if ( dev->lock.hw_lock ) { dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ dev->lock.filp = NULL; @@ -540,6 +407,13 @@ static int DRM(takedown)( drm_device_t *dev ) return 0; } +static void DRM(init_fn_table)(struct drm_device *dev) +{ + dev->fn_tbl.reclaim_buffers = DRM(core_reclaim_buffers); + dev->fn_tbl.get_map_ofs = DRM(core_get_map_ofs); + dev->fn_tbl.get_reg_ofs = DRM(core_get_reg_ofs); +} + #include "drm_pciids.h" static struct pci_device_id DRM(pciidlist)[] = { @@ -549,9 +423,7 @@ static struct pci_device_id DRM(pciidlist)[] = { static int DRM(probe)(struct pci_dev *pdev) { drm_device_t *dev; -#if __HAVE_CTX_BITMAP int retcode; -#endif int i; int is_compat = 0; @@ -569,6 +441,9 @@ static int DRM(probe)(struct pci_dev *pdev) if (DRM(numdevs) >= MAX_DEVICES) return -ENODEV; + if ((retcode=pci_enable_device(pdev))) + return retcode; + dev = &(DRM(device)[DRM(numdevs)]); memset( (void *)dev, 0, sizeof(*dev) ); @@ -594,36 +469,51 @@ static int DRM(probe)(struct pci_dev *pdev) dev->pci_func = PCI_FUNC(pdev->devfn); dev->irq = pdev->irq; - DRIVER_PREINIT(); + /* dev_priv_size can be changed by a driver in driver_register_fns */ + dev->dev_priv_size = sizeof(u32); -#if __REALLY_HAVE_AGP - dev->agp = DRM(agp_init)(); -#if __MUST_HAVE_AGP - if ( dev->agp == NULL ) { - DRM_ERROR( "Cannot initialize the agpgart module.\n" ); - DRM(stub_unregister)(dev->minor); - DRM(takedown)( dev ); - return -EINVAL; + /* the DRM has 6 basic counters - drivers add theirs in register_fns */ + dev->counters = 6; + dev->types[0] = _DRM_STAT_LOCK; + dev->types[1] = _DRM_STAT_OPENS; + dev->types[2] = _DRM_STAT_CLOSES; + dev->types[3] = _DRM_STAT_IOCTLS; + dev->types[4] = _DRM_STAT_LOCKS; + dev->types[5] = _DRM_STAT_UNLOCKS; + + DRM(init_fn_table)(dev); + + DRM(driver_register_fns)(dev); + + if (dev->fn_tbl.preinit) + dev->fn_tbl.preinit(dev); + + if (drm_core_has_AGP(dev)) + { + dev->agp = DRM(agp_init)(); + if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { + DRM_ERROR( "Cannot initialize the agpgart module.\n" ); + DRM(stub_unregister)(dev->minor); + DRM(takedown)( dev ); + return -EINVAL; + } + if (drm_core_has_MTRR(dev)) { + if (dev->agp) + dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size*1024*1024, + MTRR_TYPE_WRCOMB, + 1 ); + } } -#endif -#if __REALLY_HAVE_MTRR - if (dev->agp) - dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, - dev->agp->agp_info.aper_size*1024*1024, - MTRR_TYPE_WRCOMB, - 1 ); -#endif -#endif -#if __HAVE_CTX_BITMAP retcode = DRM(ctxbitmap_init)( dev ); if( retcode ) { DRM_ERROR( "Cannot allocate memory for context bitmap.\n" ); DRM(stub_unregister)(dev->minor); DRM(takedown)( dev ); return retcode; - } -#endif + } + DRM(numdevs)++; /* no errors, mark it reserved */ DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n", @@ -635,7 +525,8 @@ static int DRM(probe)(struct pci_dev *pdev) dev->minor, pci_pretty_name(pdev)); - DRIVER_POSTINIT(); + if (dev->fn_tbl.postinit) + dev->fn_tbl.postinit(dev); return 0; } @@ -665,9 +556,8 @@ static int __init drm_init( void ) DRM(mem_init)(); - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { + for_each_pci_dev(pdev) DRM(probe)(pdev); - } return 0; } @@ -695,31 +585,30 @@ static void __exit drm_cleanup( void ) DRM_INFO( "Module unloaded\n" ); } } -#if __HAVE_CTX_BITMAP + DRM(ctxbitmap_cleanup)( dev ); -#endif -#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR - if ( dev->agp && dev->agp->agp_mtrr >= 0) { + if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && + dev->agp && dev->agp->agp_mtrr >= 0) { int retval; retval = mtrr_del( dev->agp->agp_mtrr, dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size*1024*1024 ); DRM_DEBUG( "mtrr_del=%d\n", retval ); } -#endif DRM(takedown)( dev ); -#if __REALLY_HAVE_AGP - if ( dev->agp ) { + if (drm_core_has_AGP(dev) && dev->agp ) { DRM(agp_uninit)(); DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); dev->agp = NULL; } -#endif + + if (dev->fn_tbl.postcleanup) + dev->fn_tbl.postcleanup(dev); + } - DRIVER_POSTCLEANUP(); DRM(numdevs) = 0; } @@ -834,7 +723,8 @@ int DRM(release)( struct inode *inode, struct file *filp ) DRM_DEBUG( "open_count = %d\n", dev->open_count ); - DRIVER_PRERELEASE(); + if (dev->fn_tbl.prerelease) + dev->fn_tbl.prerelease(dev, filp); /* ======================================================== * Begin inline drm_release @@ -849,9 +739,10 @@ int DRM(release)( struct inode *inode, struct file *filp ) DRM_DEBUG( "File %p released, freeing lock for context %d\n", filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); -#if __HAVE_RELEASE - DRIVER_RELEASE(); -#endif + + if (dev->fn_tbl.release) + dev->fn_tbl.release(dev, filp); + DRM(lock_free)( dev, &dev->lock.hw_lock->lock, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) ); @@ -860,14 +751,13 @@ int DRM(release)( struct inode *inode, struct file *filp ) processed via a callback to the X server. */ } -#if __HAVE_RELEASE - else if ( priv->lock_count && dev->lock.hw_lock ) { + else if ( dev->fn_tbl.release && priv->lock_count && dev->lock.hw_lock ) { /* The lock is required to reclaim buffers */ DECLARE_WAITQUEUE( entry, current ); add_wait_queue( &dev->lock.lock_queue, &entry ); for (;;) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); if ( !dev->lock.hw_lock ) { /* Device has been unregistered */ retcode = -EINTR; @@ -887,17 +777,20 @@ int DRM(release)( struct inode *inode, struct file *filp ) break; } } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue( &dev->lock.lock_queue, &entry ); if( !retcode ) { - DRIVER_RELEASE(); + if (dev->fn_tbl.release) + dev->fn_tbl.release(dev, filp); DRM(lock_free)( dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT ); } } -#elif __HAVE_DMA - DRM(reclaim_buffers)( filp ); -#endif + + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + { + dev->fn_tbl.reclaim_buffers(filp); + } DRM(fasync)( -1, filp, 0 ); @@ -908,14 +801,14 @@ int DRM(release)( struct inode *inode, struct file *filp ) list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) { if ( pos->tag == priv && pos->handle != DRM_KERNEL_CONTEXT ) { -#ifdef DRIVER_CTX_DTOR - DRIVER_CTX_DTOR(pos->handle); -#endif -#if __HAVE_CTX_BITMAP + if (dev->fn_tbl.context_dtor) + dev->fn_tbl.context_dtor(dev, pos->handle); + DRM(ctxbitmap_free)( dev, pos->handle ); -#endif + list_del( &pos->head ); DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + --dev->ctx_count; } } } @@ -941,6 +834,9 @@ int DRM(release)( struct inode *inode, struct file *filp ) } up( &dev->struct_sem ); + if (dev->fn_tbl.free_filp_priv) + dev->fn_tbl.free_filp_priv(dev, priv); + DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES ); /* ======================================================== @@ -1039,9 +935,6 @@ int DRM(lock)( struct inode *inode, struct file *filp, DECLARE_WAITQUEUE( entry, current ); drm_lock_t lock; int ret = 0; -#if __HAVE_MULTIPLE_DMA_QUEUES - drm_queue_t *q; -#endif ++priv->lock_count; @@ -1058,83 +951,61 @@ int DRM(lock)( struct inode *inode, struct file *filp, lock.context, current->pid, dev->lock.hw_lock->lock, lock.flags ); -#if __HAVE_DMA_QUEUE - if ( lock.context < 0 ) - return -EINVAL; -#elif __HAVE_MULTIPLE_DMA_QUEUES - if ( lock.context < 0 || lock.context >= dev->queue_count ) - return -EINVAL; - q = dev->queuelist[lock.context]; -#endif + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) + if ( lock.context < 0 ) + return -EINVAL; -#if __HAVE_DMA_FLUSH - ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags ); -#endif - if ( !ret ) { - add_wait_queue( &dev->lock.lock_queue, &entry ); - for (;;) { - current->state = TASK_INTERRUPTIBLE; - if ( !dev->lock.hw_lock ) { - /* Device has been unregistered */ - ret = -EINTR; - break; - } - if ( DRM(lock_take)( &dev->lock.hw_lock->lock, - lock.context ) ) { - dev->lock.filp = filp; - dev->lock.lock_time = jiffies; - atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); - break; /* Got lock */ - } - - /* Contention */ - schedule(); - if ( signal_pending( current ) ) { - ret = -ERESTARTSYS; - break; - } - } - current->state = TASK_RUNNING; - remove_wait_queue( &dev->lock.lock_queue, &entry ); - } - -#if __HAVE_DMA_FLUSH - DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */ -#endif - - if ( !ret ) { - sigemptyset( &dev->sigmask ); - sigaddset( &dev->sigmask, SIGSTOP ); - sigaddset( &dev->sigmask, SIGTSTP ); - sigaddset( &dev->sigmask, SIGTTIN ); - sigaddset( &dev->sigmask, SIGTTOU ); - dev->sigdata.context = lock.context; - dev->sigdata.lock = dev->lock.hw_lock; - block_all_signals( DRM(notifier), - &dev->sigdata, &dev->sigmask ); - -#if __HAVE_DMA_READY - if ( lock.flags & _DRM_LOCK_READY ) { - DRIVER_DMA_READY(); + add_wait_queue( &dev->lock.lock_queue, &entry ); + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + if ( !dev->lock.hw_lock ) { + /* Device has been unregistered */ + ret = -EINTR; + break; } -#endif -#if __HAVE_DMA_QUIESCENT - if ( lock.flags & _DRM_LOCK_QUIESCENT ) { - DRIVER_DMA_QUIESCENT(); + if ( DRM(lock_take)( &dev->lock.hw_lock->lock, + lock.context ) ) { + dev->lock.filp = filp; + dev->lock.lock_time = jiffies; + atomic_inc( &dev->counts[_DRM_STAT_LOCKS] ); + break; /* Got lock */ } -#endif - /* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the - * drm modules in the DRI cvs tree, but it is required - * by the Sparc driver. - */ -#if __HAVE_KERNEL_CTX_SWITCH - if ( dev->last_context != lock.context ) { - DRM(context_switch)(dev, dev->last_context, - lock.context); + + /* Contention */ + schedule(); + if ( signal_pending( current ) ) { + ret = -ERESTARTSYS; + break; } -#endif - } - + } + __set_current_state(TASK_RUNNING); + remove_wait_queue( &dev->lock.lock_queue, &entry ); + + sigemptyset( &dev->sigmask ); + sigaddset( &dev->sigmask, SIGSTOP ); + sigaddset( &dev->sigmask, SIGTSTP ); + sigaddset( &dev->sigmask, SIGTTIN ); + sigaddset( &dev->sigmask, SIGTTOU ); + dev->sigdata.context = lock.context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals( DRM(notifier), + &dev->sigdata, &dev->sigmask ); + + if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY)) + dev->fn_tbl.dma_ready(dev); + + if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT )) + return dev->fn_tbl.dma_quiescent(dev); + + /* dev->fn_tbl.kernel_context_switch isn't used by any of the x86 + * drivers but is used by the Sparc driver. + */ + + if (dev->fn_tbl.kernel_context_switch && + dev->last_context != lock.context) { + dev->fn_tbl.kernel_context_switch(dev, dev->last_context, + lock.context); + } DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" ); return ret; @@ -1169,40 +1040,20 @@ int DRM(unlock)( struct inode *inode, struct file *filp, atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] ); - /* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm - * modules in the DRI cvs tree, but it is required by the - * Sparc driver. - */ -#if __HAVE_KERNEL_CTX_SWITCH - /* We no longer really hold it, but if we are the next - * agent to request it then we should just be able to - * take it immediately and not eat the ioctl. + /* kernel_context_switch isn't used by any of the x86 drm + * modules but is required by the Sparc driver. */ - dev->lock.filp = NULL; - { - __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; - unsigned int old, new, prev, ctx; - - ctx = lock.context; - do { - old = *plock; - new = ctx; - prev = cmpxchg(plock, old, new); - } while (prev != old); - } - wake_up_interruptible(&dev->lock.lock_queue); -#else - DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ); -#if __HAVE_DMA_SCHEDULE - DRM(dma_schedule)( dev, 1 ); -#endif - - if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock, - DRM_KERNEL_CONTEXT ) ) { - DRM_ERROR( "\n" ); + if (dev->fn_tbl.kernel_context_switch_unlock) + dev->fn_tbl.kernel_context_switch_unlock(dev, &lock); + else { + DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT ); + + if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT ) ) { + DRM_ERROR( "\n" ); + } } -#endif /* !__HAVE_KERNEL_CTX_SWITCH */ unblock_all_signals(); return 0; diff --git a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h index 0aa02444a..6bbb30a15 100644 --- a/drivers/char/drm/drm_fops.h +++ b/drivers/char/drm/drm_fops.h @@ -53,6 +53,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev) { int minor = iminor(inode); drm_file_t *priv; + int ret; if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */ if (!DRM(cpu_valid)()) return -EINVAL; @@ -72,7 +73,11 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev) priv->authenticated = capable(CAP_SYS_ADMIN); priv->lock_count = 0; - DRIVER_OPEN_HELPER( priv, dev ); + if (dev->fn_tbl.open_helper) { + ret=dev->fn_tbl.open_helper(dev, priv); + if (ret < 0) + goto out_free; + } down(&dev->struct_sem); if (!dev->file_last) { @@ -94,8 +99,11 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev) */ if (!dev->hose) { struct pci_dev *pci_dev; - pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); - if (pci_dev) dev->hose = pci_dev->sysdata; + pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); + if (pci_dev) { + dev->hose = pci_dev->sysdata; + pci_dev_put(pci_dev); + } if (!dev->hose) { struct pci_bus *b = pci_bus_b(pci_root_buses.next); if (b) dev->hose = b->sysdata; @@ -104,6 +112,10 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev) #endif return 0; +out_free: + DRM(free)(priv, sizeof(*priv), DRM_MEM_FILES); + filp->private_data=NULL; + return ret; } /** No-op. */ @@ -130,19 +142,15 @@ int DRM(fasync)(int fd, struct file *filp, int on) return 0; } -#if !__HAVE_DRIVER_FOPS_POLL /** No-op. */ unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait) { return 0; } -#endif -#if !__HAVE_DRIVER_FOPS_READ /** No-op. */ ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off) { return 0; } -#endif diff --git a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h index ef6532a31..d1271c166 100644 --- a/drivers/char/drm/drm_ioctl.h +++ b/drivers/char/drm/drm_ioctl.h @@ -341,9 +341,9 @@ int DRM(setversion)(DRM_IOCTL_ARGS) if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR) return EINVAL; -#ifdef DRIVER_SETVERSION - DRIVER_SETVERSION(dev, &sv); -#endif + + if (dev->fn_tbl.set_version) + dev->fn_tbl.set_version(dev, &sv); } return 0; } diff --git a/drivers/char/drm/drm_irq.h b/drivers/char/drm/drm_irq.h index 04bb0ac11..d26c999fe 100644 --- a/drivers/char/drm/drm_irq.h +++ b/drivers/char/drm/drm_irq.h @@ -37,16 +37,6 @@ #include /* For task queue support */ -#ifndef __HAVE_SHARED_IRQ -#define __HAVE_SHARED_IRQ 0 -#endif - -#if __HAVE_SHARED_IRQ -#define DRM_IRQ_TYPE SA_SHIRQ -#else -#define DRM_IRQ_TYPE 0 -#endif - /** * Get interrupt from bus id. * @@ -68,6 +58,9 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp, drm_irq_busid_t __user *argp = (void __user *)arg; drm_irq_busid_t p; + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + return -EINVAL; + if (copy_from_user(&p, argp, sizeof(p))) return -EFAULT; @@ -86,8 +79,6 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp, return 0; } -#if __HAVE_IRQ - /** * Install IRQ handler. * @@ -101,7 +92,11 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp, int DRM(irq_install)( drm_device_t *dev ) { int ret; - + unsigned long sh_flags=0; + + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + return -EINVAL; + if ( dev->irq == 0 ) return -EINVAL; @@ -122,32 +117,25 @@ int DRM(irq_install)( drm_device_t *dev ) DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); -#if __HAVE_DMA - dev->dma->next_buffer = NULL; - dev->dma->next_queue = NULL; - dev->dma->this_buffer = NULL; -#endif - -#ifdef __HAVE_IRQ_BH - INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev); -#endif - -#ifdef __HAVE_VBL_IRQ - init_waitqueue_head(&dev->vbl_queue); - - spin_lock_init( &dev->vbl_lock ); - - INIT_LIST_HEAD( &dev->vbl_sigs.head ); - - dev->vbl_pending = 0; -#endif + if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) { + init_waitqueue_head(&dev->vbl_queue); + + spin_lock_init( &dev->vbl_lock ); + + INIT_LIST_HEAD( &dev->vbl_sigs.head ); + + dev->vbl_pending = 0; + } /* Before installing handler */ - DRM(driver_irq_preinstall)(dev); + dev->fn_tbl.irq_preinstall(dev); /* Install handler */ - ret = request_irq( dev->irq, DRM(irq_handler), - DRM_IRQ_TYPE, dev->devname, dev ); + if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED)) + sh_flags = SA_SHIRQ; + + ret = request_irq( dev->irq, dev->fn_tbl.irq_handler, + sh_flags, dev->devname, dev ); if ( ret < 0 ) { down( &dev->struct_sem ); dev->irq_enabled = 0; @@ -156,7 +144,7 @@ int DRM(irq_install)( drm_device_t *dev ) } /* After installing handler */ - DRM(driver_irq_postinstall)(dev); + dev->fn_tbl.irq_postinstall(dev); return 0; } @@ -172,6 +160,9 @@ int DRM(irq_uninstall)( drm_device_t *dev ) { int irq_enabled; + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + return -EINVAL; + down( &dev->struct_sem ); irq_enabled = dev->irq_enabled; dev->irq_enabled = 0; @@ -182,7 +173,7 @@ int DRM(irq_uninstall)( drm_device_t *dev ) DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); - DRM(driver_irq_uninstall)( dev ); + dev->fn_tbl.irq_uninstall(dev); free_irq( dev->irq, dev ); @@ -206,25 +197,29 @@ int DRM(control)( struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_control_t ctl; + + /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) ) return -EFAULT; switch ( ctl.func ) { case DRM_INST_HANDLER: + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl.irq != dev->irq) return -EINVAL; return DRM(irq_install)( dev ); case DRM_UNINST_HANDLER: + if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + return 0; return DRM(irq_uninstall)( dev ); default: return -EINVAL; } } -#ifdef __HAVE_VBL_IRQ - /** * Wait for VBLANK. * @@ -254,6 +249,9 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) int ret = 0; unsigned int flags; + if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL)) + return -EINVAL; + if (!dev->irq) return -EINVAL; @@ -318,7 +316,8 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS ) spin_unlock_irqrestore( &dev->vbl_lock, irqflags ); } else { - ret = DRM(vblank_wait)( dev, &vblwait.request.sequence ); + if (dev->fn_tbl.vblank_wait) + ret = dev->fn_tbl.vblank_wait( dev, &vblwait.request.sequence ); do_gettimeofday( &now ); vblwait.reply.tval_sec = now.tv_sec; @@ -366,6 +365,4 @@ void DRM(vbl_send_signals)( drm_device_t *dev ) spin_unlock_irqrestore( &dev->vbl_lock, flags ); } -#endif /* __HAVE_VBL_IRQ */ -#endif /* __HAVE_IRQ */ diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index 9adfe790d..c68e8d5eb 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h @@ -44,7 +44,7 @@ */ #define DEBUG_MEMORY 0 -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP #include @@ -130,46 +130,56 @@ drm_follow_page (void *vaddr) return pte_pfn(*ptep) << PAGE_SHIFT; } -#endif /* __REALLY_HAVE_AGP */ +#else /* __OS_HAS_AGP */ + +static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + return NULL; +} + +static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + return NULL; +} + +static inline unsigned long drm_follow_page (void *vaddr) +{ + return 0; +} + +#endif static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev) { -#if __REALLY_HAVE_AGP - if (dev->agp && dev->agp->cant_use_aperture) { + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { drm_map_t *map = drm_lookup_map(offset, size, dev); if (map && map->type == _DRM_AGP) return agp_remap(offset, size, dev); } -#endif - return ioremap(offset, size); } static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size, drm_device_t *dev) { -#if __REALLY_HAVE_AGP - if (dev->agp && dev->agp->cant_use_aperture) { + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { drm_map_t *map = drm_lookup_map(offset, size, dev); if (map && map->type == _DRM_AGP) return agp_remap(offset, size, dev); } -#endif - return ioremap_nocache(offset, size); } static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev) { -#if __REALLY_HAVE_AGP /* * This is a bit ugly. It would be much cleaner if the DRM API would use separate * routines for handling mappings in the AGP space. Hopefully this can be done in * a future revision of the interface... */ - if (dev->agp && dev->agp->cant_use_aperture + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END)) { unsigned long offset; @@ -182,11 +192,11 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d return; } } -#endif iounmap(pt); } + #if DEBUG_MEMORY #include "drm_memory_debug.h" #else @@ -331,7 +341,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) drm_ioremapfree(pt, size, dev); } -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP /** Wrapper around agp_allocate_memory() */ DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type) { diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 74d3c499e..0053679a8 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -352,7 +352,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) } } -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type) { diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 6b69f0aa3..242e311a2 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h @@ -16,13 +16,17 @@ #define DRM_CURRENTPID current->pid #define DRM_UDELAY(d) udelay(d) /** Read a byte from a MMIO region */ -#define DRM_READ8(map, offset) readb(((unsigned long)(map)->handle) + (offset)) +#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset)) +/** Read a word from a MMIO region */ +#define DRM_READ16(map, offset) readw(((void __iomem *)(map)->handle) + (offset)) /** Read a dword from a MMIO region */ -#define DRM_READ32(map, offset) readl(((unsigned long)(map)->handle) + (offset)) +#define DRM_READ32(map, offset) readl(((void __iomem *)(map)->handle) + (offset)) /** Write a byte into a MMIO region */ -#define DRM_WRITE8(map, offset, val) writeb(val, ((unsigned long)(map)->handle) + (offset)) +#define DRM_WRITE8(map, offset, val) writeb(val, ((void __iomem *)(map)->handle) + (offset)) +/** Write a word into a MMIO region */ +#define DRM_WRITE16(map, offset, val) writew(val, ((void __iomem *)(map)->handle) + (offset)) /** Write a dword into a MMIO region */ -#define DRM_WRITE32(map, offset, val) writel(val, ((unsigned long)(map)->handle) + (offset)) +#define DRM_WRITE32(map, offset, val) writel(val, ((void __iomem *)(map)->handle) + (offset)) /** Read memory barrier */ #define DRM_READMEMORYBARRIER() rmb() /** Write memory barrier */ @@ -37,8 +41,34 @@ #define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs /** AGP types */ +#if __OS_HAS_AGP #define DRM_AGP_MEM struct agp_memory #define DRM_AGP_KERN struct agp_kern_info +#else +/* define some dummy types for non AGP supporting kernels */ +struct no_agp_kern { + unsigned long aper_base; + unsigned long aper_size; +}; +#define DRM_AGP_MEM int +#define DRM_AGP_KERN struct no_agp_kern +#endif + +#if !(__OS_HAS_MTRR) +static __inline__ int mtrr_add (unsigned long base, unsigned long size, + unsigned int type, char increment) +{ + return -ENODEV; +} + +static __inline__ int mtrr_del (int reg, unsigned long base, + unsigned long size) +{ + return -ENODEV; +} +#define MTRR_TYPE_WRCOMB 1 + +#endif /** Task queue handler arguments */ #define DRM_TASKQUEUE_ARGS void *arg @@ -104,7 +134,7 @@ do { \ add_wait_queue(&(queue), &entry); \ \ for (;;) { \ - current->state = TASK_INTERRUPTIBLE; \ + __set_current_state(TASK_INTERRUPTIBLE); \ if (condition) \ break; \ if (time_after_eq(jiffies, end)) { \ @@ -117,7 +147,7 @@ do { \ break; \ } \ } \ - current->state = TASK_RUNNING; \ + __set_current_state(TASK_RUNNING); \ remove_wait_queue(&(queue), &entry); \ } while (0) diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 3b5f8d3a2..768c131d2 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -201,3 +201,11 @@ #define ffb_PCI_IDS \ {0, 0, 0} +#define i915_PCI_IDS \ + {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + diff --git a/drivers/char/drm/drm_scatter.h b/drivers/char/drm/drm_scatter.h index e5d829367..436a0170e 100644 --- a/drivers/char/drm/drm_scatter.h +++ b/drivers/char/drm/drm_scatter.h @@ -73,6 +73,9 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp, DRM_DEBUG( "%s\n", __FUNCTION__ ); + if (!drm_core_check_feature(dev, DRIVER_SG)) + return -EINVAL; + if ( dev->sg ) return -EINVAL; @@ -206,6 +209,9 @@ int DRM(sg_free)( struct inode *inode, struct file *filp, drm_scatter_gather_t request; drm_sg_mem_t *entry; + if (!drm_core_check_feature(dev, DRIVER_SG)) + return -EINVAL; + if ( copy_from_user( &request, (drm_scatter_gather_t __user *)arg, sizeof(request) ) ) diff --git a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h index d7dce3ae9..921f3f343 100644 --- a/drivers/char/drm/drm_vm.h +++ b/drivers/char/drm/drm_vm.h @@ -46,10 +46,10 @@ * Find the right map and if it's AGP memory find the real physical page to * map, get the page, increment the use count and return it. */ +#if __OS_HAS_AGP static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma, unsigned long address) { -#if __REALLY_HAVE_AGP drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; drm_map_t *map = NULL; @@ -59,6 +59,8 @@ static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma, /* * Find the right map */ + if (!drm_core_has_AGP(dev)) + goto vm_nopage_error; if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; @@ -107,10 +109,15 @@ static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma, return page; } vm_nopage_error: -#endif /* __REALLY_HAVE_AGP */ - return NOPAGE_SIGBUS; /* Disallow mremap */ } +#else /* __OS_HAS_AGP */ +static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma, + unsigned long address) +{ + return NOPAGE_SIGBUS; +} +#endif /* __OS_HAS_AGP */ /** * \c nopage method for shared virtual memory. @@ -201,15 +208,13 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma) switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if (map->mtrr >= 0) { + if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { int retcode; retcode = mtrr_del(map->mtrr, map->offset, map->size); DRM_DEBUG("mtrr_del = %d\n", retcode); } -#endif DRM(ioremapfree)(map->handle, map->size, dev); break; case _DRM_SHM: @@ -488,18 +493,19 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma) return 0; } -#ifndef DRIVER_GET_MAP_OFS -#define DRIVER_GET_MAP_OFS() (map->offset) -#endif +unsigned long DRM(core_get_map_ofs)(drm_map_t *map) +{ + return map->offset; +} -#ifndef DRIVER_GET_REG_OFS +unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev) +{ #ifdef __alpha__ -#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \ - dev->hose->mem_space->start) + return dev->hose->dense_mem_base - dev->hose->mem_space->start; #else -#define DRIVER_GET_REG_OFS() 0 -#endif + return 0; #endif +} /** * mmap DMA memory. @@ -533,7 +539,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) * --BenH. */ if (!VM_OFFSET(vma) -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) #endif ) @@ -552,7 +558,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) r_list = list_entry(list, drm_map_list_t, head); map = r_list->map; if (!map) continue; - off = DRIVER_GET_MAP_OFS(); + off = dev->fn_tbl.get_map_ofs(map); if (off == VM_OFFSET(vma)) break; } @@ -577,8 +583,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) switch (map->type) { case _DRM_AGP: -#if __REALLY_HAVE_AGP - if (dev->agp->cant_use_aperture) { + if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) { /* * On some platforms we can't talk to bus dma address from the CPU, so for * memory of type DRM_AGP, we'll deal with sorting out the real physical @@ -590,7 +595,6 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &DRM(vm_ops); break; } -#endif /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: @@ -609,15 +613,15 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) if (map->type != _DRM_AGP) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); #endif - offset = DRIVER_GET_REG_OFS(); + offset = dev->fn_tbl.get_reg_ofs(dev); #ifdef __sparc__ if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, VM_OFFSET(vma) + offset, vma->vm_end - vma->vm_start, vma->vm_page_prot, 0)) #else - if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, + if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + (VM_OFFSET(vma) + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) #endif diff --git a/drivers/char/drm/ffb.h b/drivers/char/drm/ffb.h index af35783b2..3691c8652 100644 --- a/drivers/char/drm/ffb.h +++ b/drivers/char/drm/ffb.h @@ -8,9 +8,5 @@ */ #define DRM(x) ffb_##x -/* General customization: - */ -#define __HAVE_KERNEL_CTX_SWITCH 1 -#define __HAVE_RELEASE 1 #endif diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c index 6fae05c8b..f51812078 100644 --- a/drivers/char/drm/ffb_context.c +++ b/drivers/char/drm/ffb_context.c @@ -354,7 +354,7 @@ static void FFBWait(ffb_fbcPtr ffb) } while (--limit); } -int DRM(context_switch)(drm_device_t *dev, int old, int new) +int ffb_driver_context_switch(drm_device_t *dev, int old, int new) { ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; @@ -380,7 +380,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new) return 0; } -int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_ctx_res_t res; @@ -407,7 +407,7 @@ int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd, } -int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -428,7 +428,7 @@ int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -457,7 +457,7 @@ int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -489,7 +489,7 @@ int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; @@ -499,10 +499,10 @@ int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd, if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx))) return -EFAULT; DRM_DEBUG("%d\n", ctx.handle); - return DRM(context_switch)(dev, dev->last_context, ctx.handle); + return ffb_driver_context_switch(dev, dev->last_context, ctx.handle); } -int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_ctx_t ctx; @@ -514,7 +514,7 @@ int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd, +int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_ctx_t ctx; @@ -537,3 +537,15 @@ int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd, } return 0; } + +void ffb_set_context_ioctls(void) +{ + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx; + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx; + +} diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c index 765355999..2e1522e7c 100644 --- a/drivers/char/drm/ffb_drv.c +++ b/drivers/char/drm/ffb_drv.c @@ -26,58 +26,6 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 1 -#define DRIVER_FOPS \ -static struct file_operations DRM(fops) = { \ - .owner = THIS_MODULE, \ - .open = DRM(open), \ - .flush = DRM(flush), \ - .release = DRM(release), \ - .ioctl = DRM(ioctl), \ - .mmap = DRM(mmap), \ - .read = DRM(read), \ - .fasync = DRM(fasync), \ - .poll = DRM(poll), \ - .get_unmapped_area = ffb_get_unmapped_area, \ -} - -#define DRIVER_COUNT_CARDS() ffb_count_card_instances() -/* Allocate private structure and fill it */ -#define DRIVER_PRESETUP() do { \ - int _ret; \ - _ret = ffb_presetup(dev); \ - if (_ret != 0) return _ret; \ -} while(0) - -/* Free private structure */ -#define DRIVER_PRETAKEDOWN() do { \ - if (dev->dev_private) kfree(dev->dev_private); \ -} while(0) - -#define DRIVER_POSTCLEANUP() do { \ - if (ffb_position != NULL) kfree(ffb_position); \ -} while(0) - -/* We have to free up the rogue hw context state holding error or - * else we will leak it. - */ -#define DRIVER_RELEASE() do { \ - ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; \ - int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock); \ - int idx; \ - \ - idx = context - 1; \ - if (fpriv && \ - context != DRM_KERNEL_CONTEXT && \ - fpriv->hw_state[idx] != NULL) { \ - kfree(fpriv->hw_state[idx]); \ - fpriv->hw_state[idx] = NULL; \ - } \ -} while(0) - -/* For mmap customization */ -#define DRIVER_GET_MAP_OFS() (map->offset & 0xffffffff) -#define DRIVER_GET_REG_OFS() ffb_get_reg_offset(dev) - typedef struct _ffb_position_t { int node; int root; @@ -192,63 +140,6 @@ static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node, return 0; } -static int __init ffb_count_siblings(int root) -{ - int node, child, count = 0; - - child = prom_getchild(root); - for (node = prom_searchsiblings(child, "SUNW,ffb"); node; - node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) - count++; - - return count; -} - -static int __init ffb_scan_siblings(int root, int instance) -{ - int node, child; - - child = prom_getchild(root); - for (node = prom_searchsiblings(child, "SUNW,ffb"); node; - node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) { - ffb_position[instance].node = node; - ffb_position[instance].root = root; - instance++; - } - - return instance; -} - -static int ffb_presetup(drm_device_t *); - -static int __init ffb_count_card_instances(void) -{ - int root, total, instance; - - total = ffb_count_siblings(prom_root_node); - root = prom_getchild(prom_root_node); - for (root = prom_searchsiblings(root, "upa"); root; - root = prom_searchsiblings(prom_getsibling(root), "upa")) - total += ffb_count_siblings(root); - - ffb_position = kmalloc(sizeof(ffb_position_t) * total, GFP_KERNEL); - - /* Actual failure will be caught during ffb_presetup b/c we can't catch - * it easily here. - */ - if (!ffb_position) - return -ENOMEM; - - instance = ffb_scan_siblings(prom_root_node, 0); - - root = prom_getchild(prom_root_node); - for (root = prom_searchsiblings(root, "upa"); root; - root = prom_searchsiblings(prom_getsibling(root), "upa")) - instance = ffb_scan_siblings(root, instance); - - return total; -} - static drm_map_t *ffb_find_map(struct file *filp, unsigned long off) { drm_file_t *priv = filp->private_data; @@ -275,11 +166,11 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off) return NULL; } -static unsigned long ffb_get_unmapped_area(struct file *filp, - unsigned long hint, - unsigned long len, - unsigned long pgoff, - unsigned long flags) +unsigned long ffb_get_unmapped_area(struct file *filp, + unsigned long hint, + unsigned long len, + unsigned long pgoff, + unsigned long flags) { drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT); unsigned long addr = -ENOMEM; @@ -319,21 +210,7 @@ static unsigned long ffb_get_unmapped_area(struct file *filp, return addr; } -static unsigned long ffb_get_reg_offset(drm_device_t *dev) -{ - ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private; - - if (ffb_priv) - return ffb_priv->card_phys_base; - - return 0; -} - -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" +#include "drm_core.h" /* This functions must be here since it references DRM(numdevs) * which drm_drv.h declares. @@ -372,11 +249,74 @@ static int ffb_presetup(drm_device_t *dev) return ret; } -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" +static void ffb_driver_release(drm_device_t *dev, struct file *filp) +{ + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private; + int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock); + int idx; + + idx = context - 1; + if (fpriv && + context != DRM_KERNEL_CONTEXT && + fpriv->hw_state[idx] != NULL) { + kfree(fpriv->hw_state[idx]); + fpriv->hw_state[idx] = NULL; + } +} + +static void ffb_driver_pretakedown(drm_device_t *dev) +{ + if (dev->dev_private) kfree(dev->dev_private); +} + +static int ffb_driver_postcleanup(drm_device_t *dev) +{ + if (ffb_position != NULL) kfree(ffb_position); + return 0; +} + +static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock) +{ + dev->lock.filp = 0; + { + __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; + unsigned int old, new, prev, ctx; + + ctx = lock->context; + do { + old = *plock; + new = ctx; + prev = cmpxchg(plock, old, new); + } while (prev != old); + } + wake_up_interruptible(&dev->lock.lock_queue); +} + +static unsigned long ffb_driver_get_map_ofs(drm_map_t *map) +{ + return (map->offset & 0xffffffff); +} + +static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev) +{ + ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private; + + if (ffb_priv) + return ffb_priv->card_phys_base; + + return 0; +} + +void ffb_driver_register_fns(drm_device_t *dev) +{ + ffb_set_context_ioctls(); + DRM(fops).get_unmapped_area = ffb_get_unmapped_area; + dev->fn_tbl.release = ffb_driver_release; + dev->fn_tbl.presetup = ffb_presetup; + dev->fn_tbl.pretakedown = ffb_driver_pretakedown; + dev->fn_tbl.postcleanup = ffb_driver_postcleanup; + dev->fn_tbl.kernel_context_switch = ffb_context_switch; + dev->fn_tbl.kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock; + dev->fn_tbl.get_map_ofs = ffb_driver_get_map_ofs; + dev->fn_tbl.get_reg_ofs = ffb_driver_get_reg_ofs; +} diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h index 094bbce09..3b3546715 100644 --- a/drivers/char/drm/ffb_drv.h +++ b/drivers/char/drm/ffb_drv.h @@ -274,3 +274,13 @@ typedef struct ffb_dev_priv { /* Context table. */ struct ffb_hw_context *hw_state[FFB_MAX_CTXS]; } ffb_dev_priv_t; + +extern struct file_operations DRM(fops); +extern unsigned long ffb_get_unmapped_area(struct file *filp, + unsigned long hint, + unsigned long len, + unsigned long pgoff, + unsigned long flags); +extern void ffb_set_context_ioctls(void); +extern drm_ioctl_desc_t DRM(ioctls)[]; + diff --git a/drivers/char/drm/gamma.h b/drivers/char/drm/gamma.h index dcd649048..cabd4b311 100644 --- a/drivers/char/drm/gamma.h +++ b/drivers/char/drm/gamma.h @@ -36,8 +36,6 @@ /* General customization: */ -#define __HAVE_MTRR 1 - #define DRIVER_AUTHOR "VA Linux Systems Inc." #define DRIVER_NAME "gamma" @@ -71,44 +69,9 @@ /* DMA customization: */ -#define __HAVE_DMA 1 -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 0 -#define __HAVE_OLD_DMA 1 -#define __HAVE_PCI_DMA 1 - -#define __HAVE_DRIVER_FOPS_READ 1 -#define __HAVE_DRIVER_FOPS_POLL 1 - #define __HAVE_MULTIPLE_DMA_QUEUES 1 #define __HAVE_DMA_WAITQUEUE 1 -#define __HAVE_DMA_WAITLIST 1 -#define __HAVE_DMA_FREELIST 1 - -#define __HAVE_DMA_FLUSH 1 -#define __HAVE_DMA_SCHEDULE 1 - -#define __HAVE_DMA_READY 1 -#define DRIVER_DMA_READY() do { \ - gamma_dma_ready(dev); \ -} while (0) - -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - drm_gamma_private_t *dev_priv = \ - (drm_gamma_private_t *)dev->dev_private; \ - if (dev_priv->num_rast == 2) \ - gamma_dma_quiescent_dual(dev); \ - else gamma_dma_quiescent_single(dev); \ - return 0; \ -} while (0) - -#define __HAVE_IRQ 1 -#define __HAVE_IRQ_BH 1 - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_gamma_private_t *)((dev)->dev_private))->buffers - +/* removed from DRM HAVE_DMA_FREELIST & HAVE_DMA_SCHEDULE */ #endif /* __GAMMA_H__ */ diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h index d3c8c29c2..d11b507f8 100644 --- a/drivers/char/drm/gamma_context.h +++ b/drivers/char/drm/gamma_context.h @@ -42,7 +42,7 @@ the circular buffer), is based on Alessandro Rubini's LINUX DEVICE DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */ -ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off) +ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; @@ -128,7 +128,7 @@ int DRM(write_string)(drm_device_t *dev, const char *s) return 0; } -unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait) +unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c index 7802f5156..7e01ca182 100644 --- a/drivers/char/drm/gamma_dma.c +++ b/drivers/char/drm/gamma_dma.c @@ -116,7 +116,7 @@ static inline int gamma_dma_is_ready(drm_device_t *dev) return (!GAMMA_READ(GAMMA_DMACOUNT)); } -irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS ) +irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *)arg; drm_device_dma_t *dma = dev->dma; @@ -639,12 +639,12 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init ) break; } } - - DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 ); - DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 ); - DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 ); - DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 ); - + + dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0); + dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1); + dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2); + dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3); + dev_priv->sarea_priv = (drm_gamma_sarea_t *) ((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); @@ -661,9 +661,8 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init ) buf = dma->buflist[GLINT_DRI_BUF_COUNT]; } else { - DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - - DRM_IOREMAP( dev_priv->buffers, dev ); + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + drm_core_ioremap( dev->agp_buffer_map, dev); buf = dma->buflist[GLINT_DRI_BUF_COUNT]; pgt = buf->address; @@ -690,19 +689,18 @@ int gamma_do_cleanup_dma( drm_device_t *dev ) { DRM_DEBUG( "%s\n", __FUNCTION__ ); -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif + if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) + if ( dev->irq_enabled ) + DRM(irq_uninstall)(dev); if ( dev->dev_private ) { - drm_gamma_private_t *dev_priv = dev->dev_private; - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); + if ( dev->agp_buffer_map != NULL ) + drm_core_ioremapfree( dev->agp_buffer_map, dev ); DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t), DRM_MEM_DRIVER ); @@ -868,7 +866,7 @@ int gamma_setsareactx(struct inode *inode, struct file *filp, return 0; } -void DRM(driver_irq_preinstall)( drm_device_t *dev ) { +void gamma_driver_irq_preinstall( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; @@ -879,7 +877,7 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) { GAMMA_WRITE( GAMMA_GDMACONTROL, 0x00000000 ); } -void DRM(driver_irq_postinstall)( drm_device_t *dev ) { +void gamma_driver_irq_postinstall( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; @@ -891,7 +889,7 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { GAMMA_WRITE( GAMMA_GDELAYTIMER, 0x00039090 ); } -void DRM(driver_irq_uninstall)( drm_device_t *dev ) { +void gamma_driver_irq_uninstall( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; if (!dev_priv) @@ -904,3 +902,45 @@ void DRM(driver_irq_uninstall)( drm_device_t *dev ) { GAMMA_WRITE( GAMMA_COMMANDINTENABLE, 0x00000000 ); GAMMA_WRITE( GAMMA_GINTENABLE, 0x00000000 ); } + +extern drm_ioctl_desc_t DRM(ioctls)[]; + +static int gamma_driver_preinit(drm_device_t *dev) +{ + /* reset the finish ioctl */ + DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish); + return 0; +} + +static void gamma_driver_pretakedown(drm_device_t *dev) +{ + gamma_do_cleanup_dma(dev); +} + +static void gamma_driver_dma_ready(drm_device_t *dev) +{ + gamma_dma_ready(dev); +} + +static int gamma_driver_dma_quiescent(drm_device_t *dev) +{ + drm_gamma_private_t *dev_priv = ( + drm_gamma_private_t *)dev->dev_private; + if (dev_priv->num_rast == 2) + gamma_dma_quiescent_dual(dev); + else gamma_dma_quiescent_single(dev); + return 0; +} + +void gamma_driver_register_fns(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ; + DRM(fops).read = gamma_fops_read; + DRM(fops).poll = gamma_fops_poll; + dev->fn_tbl.preinit = gamma_driver_preinit; + dev->fn_tbl.pretakedown = gamma_driver_pretakedown; + dev->fn_tbl.dma_ready = gamma_driver_dma_ready; + dev->fn_tbl.dma_quiescent = gamma_driver_dma_quiescent; + dev->fn_tbl.dma_flush_block_and_flush = gamma_flush_block_and_flush; + dev->fn_tbl.dma_flush_unblock = gamma_flush_unblock; +} diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c index b1fb05055..e7e64b627 100644 --- a/drivers/char/drm/gamma_drv.c +++ b/drivers/char/drm/gamma_drv.c @@ -56,3 +56,4 @@ #include "drm_proc.h" #include "drm_vm.h" #include "drm_stub.h" +#include "drm_scatter.h" diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h index fc78a11a3..146fcc625 100644 --- a/drivers/char/drm/gamma_drv.h +++ b/drivers/char/drm/gamma_drv.h @@ -35,7 +35,6 @@ typedef struct drm_gamma_private { drm_gamma_sarea_t *sarea_priv; drm_map_t *sarea; - drm_map_t *buffers; drm_map_t *mmio0; drm_map_t *mmio1; drm_map_t *mmio2; @@ -91,6 +90,10 @@ extern int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf); extern drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block); +/* externs for gamma changes to the ops */ +extern struct file_operations DRM(fops); +extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait); +extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off); #define GLINT_DRI_BUF_COUNT 256 diff --git a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h index aee2efff1..2ea83be82 100644 --- a/drivers/char/drm/i810.h +++ b/drivers/char/drm/i810.h @@ -36,10 +36,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 1 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 #define DRIVER_AUTHOR "VA Linux Systems Inc." @@ -78,47 +74,4 @@ [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] = { i810_flip_bufs, 1, 0 } -#define __HAVE_COUNTERS 4 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#define __HAVE_COUNTER9 _DRM_STAT_DMA - -/* Driver customization: - */ -#define __HAVE_RELEASE 1 -#define DRIVER_RELEASE() do { \ - i810_reclaim_buffers( filp ); \ -} while (0) - -#define DRIVER_PRETAKEDOWN() do { \ - i810_dma_cleanup( dev ); \ -} while (0) - -/* DMA customization: - */ -#define __HAVE_DMA 1 -#define __HAVE_DMA_QUEUE 1 -#define __HAVE_DMA_WAITLIST 0 -#define __HAVE_DMA_RECLAIM 1 - -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - i810_dma_quiescent( dev ); \ -} while (0) - -/* Don't need an irq any more. The template code will make sure that - * a noop stub is generated for compatibility. - */ -/* XXX: Add vblank support? */ -#define __HAVE_IRQ 0 - -/* Buffer customization: - */ - -#define DRIVER_BUF_PRIV_T drm_i810_buf_priv_t - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_i810_private_t *)((dev)->dev_private))->buffer_map - #endif diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index 42220efe7..197ef9c0f 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -138,8 +138,8 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) buf_priv->currently_mapped = I810_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma), + if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + VM_OFFSET(vma) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; @@ -232,13 +232,12 @@ int i810_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ - if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif + if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled) + DRM(irq_uninstall)(dev); if (dev->dev_private) { int i; @@ -364,15 +363,15 @@ static int i810_dma_initialize(drm_device_t *dev, DRM_ERROR("can not find sarea!\n"); return -EINVAL; } - DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset ); + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio_map) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); return -EINVAL; } - DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset ); - if (!dev_priv->buffer_map) { + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if (!dev->agp_buffer_map) { dev->dev_private = (void *)dev_priv; i810_dma_cleanup(dev); DRM_ERROR("can not find dma buffer map!\n"); @@ -844,13 +843,10 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev, if (buf_priv->currently_mapped == I810_BUF_MAPPED) { unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); - put_user((GFX_OP_PRIMITIVE | prim | - ((used/4)-2)), - (u32 __user *)buf_priv->virtual); + *(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2))); if (used & 4) { - put_user(0, - (u32 __user *)((u32)buf_priv->virtual + used)); + *(u32 *)((u32)buf_priv->kernel_virtual + used) = 0; used += 4; } @@ -1391,3 +1387,36 @@ int i810_flip_bufs(struct inode *inode, struct file *filp, i810_dma_dispatch_flip( dev ); return 0; } + +static void i810_driver_pretakedown(drm_device_t *dev) +{ + i810_dma_cleanup( dev ); +} + +static void i810_driver_release(drm_device_t *dev, struct file *filp) +{ + i810_reclaim_buffers(filp); +} + +static int i810_driver_dma_quiescent(drm_device_t *dev) +{ + i810_dma_quiescent( dev ); + return 0; +} + +void i810_driver_register_fns(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE; + dev->dev_priv_size = sizeof(drm_i810_buf_priv_t); + dev->fn_tbl.pretakedown = i810_driver_pretakedown; + dev->fn_tbl.release = i810_driver_release; + dev->fn_tbl.dma_quiescent = i810_driver_dma_quiescent; + dev->fn_tbl.reclaim_buffers = i810_reclaim_buffers; + + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; +} + diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index 0bc793864..00ca55166 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -37,19 +37,4 @@ #include "i810_drm.h" #include "i810_drv.h" -#include "drm_agpsupport.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" - -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" +#include "drm_core.h" diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index 736c20d76..67c5c88bf 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h @@ -53,7 +53,6 @@ typedef struct _drm_i810_ring_buffer{ typedef struct drm_i810_private { drm_map_t *sarea_map; - drm_map_t *buffer_map; drm_map_t *mmio_map; drm_i810_sarea_t *sarea_priv; diff --git a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h index b4a361bf0..85a1ac204 100644 --- a/drivers/char/drm/i830.h +++ b/drivers/char/drm/i830.h @@ -36,10 +36,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 1 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 #define DRIVER_AUTHOR "VA Linux Systems Inc." @@ -77,36 +73,6 @@ [DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam, 1, 0 } -#define __HAVE_COUNTERS 4 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY -#define __HAVE_COUNTER9 _DRM_STAT_DMA - -/* Driver customization: - */ -#define __HAVE_RELEASE 1 -#define DRIVER_RELEASE() do { \ - i830_reclaim_buffers( filp ); \ -} while (0) - -#define DRIVER_PRETAKEDOWN() do { \ - i830_dma_cleanup( dev ); \ -} while (0) - -/* DMA customization: - */ -#define __HAVE_DMA 1 -#define __HAVE_DMA_QUEUE 1 -#define __HAVE_DMA_WAITLIST 0 -#define __HAVE_DMA_RECLAIM 1 - -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - i830_dma_quiescent( dev ); \ -} while (0) - - /* Driver will work either way: IRQ's save cpu time when waiting for * the card, but are subject to subtle interactions between bios, * hardware and the driver. @@ -114,20 +80,4 @@ /* XXX: Add vblank support? */ #define USE_IRQS 0 -#if USE_IRQS -#define __HAVE_IRQ 1 -#define __HAVE_SHARED_IRQ 1 -#else -#define __HAVE_IRQ 0 -#endif - - -/* Buffer customization: - */ - -#define DRIVER_BUF_PRIV_T drm_i830_buf_priv_t - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_i830_private_t *)((dev)->dev_private))->buffer_map - #endif diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 856dc81f8..97ee36fbb 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -139,8 +139,8 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) buf_priv->currently_mapped = I830_BUF_MAPPED; unlock_kernel(); - if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma), + if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + VM_OFFSET(vma) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; @@ -233,13 +233,11 @@ int i830_dma_cleanup(drm_device_t *dev) { drm_device_dma_t *dma = dev->dma; -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif if (dev->dev_private) { int i; @@ -371,15 +369,15 @@ static int i830_dma_initialize(drm_device_t *dev, DRM_ERROR("can not find sarea!\n"); return -EINVAL; } - DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset ); + dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if(!dev_priv->mmio_map) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); return -EINVAL; } - DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset ); - if(!dev_priv->buffer_map) { + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if(!dev->agp_buffer_map) { dev->dev_private = (void *)dev_priv; i830_dma_cleanup(dev); DRM_ERROR("can not find dma buffer map!\n"); @@ -1166,19 +1164,19 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev, DRM_DEBUG( "start + used - 4 : %ld\n", start + used - 4); if (buf_priv->currently_mapped == I830_BUF_MAPPED) { - u32 __user *vp = buf_priv->virtual; + u32 *vp = buf_priv->kernel_virtual; - put_user( (GFX_OP_PRIMITIVE | - sarea_priv->vertex_prim | - ((used/4)-2)), &vp[0]); + vp[0] = (GFX_OP_PRIMITIVE | + sarea_priv->vertex_prim | + ((used/4)-2)); if (dev_priv->use_mi_batchbuffer_start) { - put_user(MI_BATCH_BUFFER_END, &vp[used/4]); + vp[used/4] = MI_BATCH_BUFFER_END; used += 4; } if (used & 4) { - put_user(0, &vp[used/4]); + vp[used/4] = 0; used += 4; } @@ -1582,3 +1580,45 @@ int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd, return 0; } + + +static void i830_driver_pretakedown(drm_device_t *dev) +{ + i830_dma_cleanup( dev ); +} + +static void i830_driver_release(drm_device_t *dev, struct file *filp) +{ + i830_reclaim_buffers(filp); +} + +static int i830_driver_dma_quiescent(drm_device_t *dev) +{ + i830_dma_quiescent( dev ); + return 0; +} + +void i830_driver_register_fns(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE; +#if USE_IRQS + dev->driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ; +#endif + dev->dev_priv_size = sizeof(drm_i830_buf_priv_t); + dev->fn_tbl.pretakedown = i830_driver_pretakedown; + dev->fn_tbl.release = i830_driver_release; + dev->fn_tbl.dma_quiescent = i830_driver_dma_quiescent; + dev->fn_tbl.reclaim_buffers = i830_reclaim_buffers; +#if USE_IRQS + dev->fn_tbl.irq_preinstall = i830_driver_irq_preinstall; + dev->fn_tbl.irq_postinstall = i830_driver_irq_postinstall; + dev->fn_tbl.irq_uninstall = i830_driver_irq_uninstall; + dev->fn_tbl.irq_handler = i830_driver_irq_handler; +#endif + dev->counters += 4; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; + dev->types[9] = _DRM_STAT_DMA; +} + diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c index 2f4e81572..eb45b2726 100644 --- a/drivers/char/drm/i830_drv.c +++ b/drivers/char/drm/i830_drv.c @@ -39,20 +39,4 @@ #include "i830_drm.h" #include "i830_drv.h" -#include "drm_agpsupport.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" - -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_irq.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" +#include "drm_core.h" diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index c6d805fc7..c3cab2d83 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h @@ -53,7 +53,6 @@ typedef struct _drm_i830_ring_buffer{ typedef struct drm_i830_private { drm_map_t *sarea_map; - drm_map_t *buffer_map; drm_map_t *mmio_map; drm_i830_sarea_t *sarea_priv; @@ -137,6 +136,10 @@ extern int i830_irq_wait( struct inode *inode, struct file *filp, extern int i830_wait_irq(drm_device_t *dev, int irq_nr); extern int i830_emit_irq(drm_device_t *dev); +extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS ); +extern void i830_driver_irq_preinstall( drm_device_t *dev ); +extern void i830_driver_irq_postinstall( drm_device_t *dev ); +extern void i830_driver_irq_uninstall( drm_device_t *dev ); #define I830_BASE(reg) ((unsigned long) \ dev_priv->mmio_map->handle) diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c index 362d66ef1..6a0e25c26 100644 --- a/drivers/char/drm/i830_irq.c +++ b/drivers/char/drm/i830_irq.c @@ -35,7 +35,7 @@ #include -irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) +irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *)arg; drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; @@ -92,7 +92,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr) add_wait_queue(&dev_priv->irq_queue, &entry); for (;;) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); if (atomic_read(&dev_priv->irq_received) >= irq_nr) break; if((signed)(end - jiffies) <= 0) { @@ -112,7 +112,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr) } } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&dev_priv->irq_queue, &entry); return ret; } @@ -178,7 +178,7 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, /* drm_dma.h hooks */ -void DRM(driver_irq_preinstall)( drm_device_t *dev ) { +void i830_driver_irq_preinstall( drm_device_t *dev ) { drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; @@ -190,14 +190,14 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) { init_waitqueue_head(&dev_priv->irq_queue); } -void DRM(driver_irq_postinstall)( drm_device_t *dev ) { +void i830_driver_irq_postinstall( drm_device_t *dev ) { drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); } -void DRM(driver_irq_uninstall)( drm_device_t *dev ) { +void i830_driver_irq_uninstall( drm_device_t *dev ) { drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; if (!dev_priv) diff --git a/drivers/char/drm/mga.h b/drivers/char/drm/mga.h index 702857a32..5356519e5 100644 --- a/drivers/char/drm/mga.h +++ b/drivers/char/drm/mga.h @@ -36,10 +36,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 1 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 #define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." @@ -64,35 +60,4 @@ [DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam, 1, 0 }, -#define __HAVE_COUNTERS 3 -#define __HAVE_COUNTER6 _DRM_STAT_IRQ -#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY -#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY - -/* Driver customization: - */ -#define DRIVER_PRETAKEDOWN() do { \ - mga_do_cleanup_dma( dev ); \ -} while (0) - -/* DMA customization: - */ -#define __HAVE_DMA 1 -#define __HAVE_IRQ 1 -#define __HAVE_VBL_IRQ 1 -#define __HAVE_SHARED_IRQ 1 - -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - drm_mga_private_t *dev_priv = dev->dev_private; \ - return mga_do_wait_for_idle( dev_priv ); \ -} while (0) - -/* Buffer customization: - */ -#define DRIVER_BUF_PRIV_T drm_mga_buf_priv_t - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_mga_private_t *)((dev)->dev_private))->buffers - #endif diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 76fbf714b..54b64c782 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -500,7 +500,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); + dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if(!dev_priv->mmio) { DRM_ERROR( "failed to find mmio region!\n" ); /* Assign dev_private so we can do cleanup. */ @@ -508,7 +508,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) mga_do_cleanup_dma( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->status, init->status_offset ); + dev_priv->status = drm_core_findmap(dev, init->status_offset); if(!dev_priv->status) { DRM_ERROR( "failed to find status page!\n" ); /* Assign dev_private so we can do cleanup. */ @@ -516,8 +516,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) mga_do_cleanup_dma( dev ); return DRM_ERR(EINVAL); } - - DRM_FIND_MAP( dev_priv->warp, init->warp_offset ); + dev_priv->warp = drm_core_findmap(dev, init->warp_offset); if(!dev_priv->warp) { DRM_ERROR( "failed to find warp microcode region!\n" ); /* Assign dev_private so we can do cleanup. */ @@ -525,7 +524,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) mga_do_cleanup_dma( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->primary, init->primary_offset ); + dev_priv->primary = drm_core_findmap(dev, init->primary_offset); if(!dev_priv->primary) { DRM_ERROR( "failed to find primary dma region!\n" ); /* Assign dev_private so we can do cleanup. */ @@ -533,8 +532,8 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) mga_do_cleanup_dma( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - if(!dev_priv->buffers) { + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if(!dev->agp_buffer_map) { DRM_ERROR( "failed to find dma buffer region!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; @@ -546,13 +545,13 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->warp, dev ); - DRM_IOREMAP( dev_priv->primary, dev ); - DRM_IOREMAP( dev_priv->buffers, dev ); + drm_core_ioremap( dev_priv->warp, dev ); + drm_core_ioremap( dev_priv->primary, dev ); + drm_core_ioremap( dev->agp_buffer_map, dev ); if(!dev_priv->warp->handle || !dev_priv->primary->handle || - !dev_priv->buffers->handle ) { + !dev->agp_buffer_map->handle ) { DRM_ERROR( "failed to ioremap agp regions!\n" ); /* Assign dev_private so we can do cleanup. */ dev->dev_private = (void *)dev_priv; @@ -631,23 +630,21 @@ int mga_do_cleanup_dma( drm_device_t *dev ) { DRM_DEBUG( "\n" ); -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif if ( dev->dev_private ) { drm_mga_private_t *dev_priv = dev->dev_private; if ( dev_priv->warp != NULL ) - DRM_IOREMAPFREE( dev_priv->warp, dev ); + drm_core_ioremapfree( dev_priv->warp, dev ); if ( dev_priv->primary != NULL ) - DRM_IOREMAPFREE( dev_priv->primary, dev ); - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); + drm_core_ioremapfree( dev_priv->primary, dev ); + if ( dev->agp_buffer_map != NULL ) + drm_core_ioremapfree( dev->agp_buffer_map, dev ); if ( dev_priv->head != NULL ) { mga_freelist_cleanup( dev ); @@ -800,3 +797,31 @@ int mga_dma_buffers( DRM_IOCTL_ARGS ) return ret; } + +static void mga_driver_pretakedown(drm_device_t *dev) +{ + mga_do_cleanup_dma( dev ); +} + +static int mga_driver_dma_quiescent(drm_device_t *dev) +{ + drm_mga_private_t *dev_priv = dev->dev_private; + return mga_do_wait_for_idle( dev_priv ); +} + +void mga_driver_register_fns(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL; + dev->fn_tbl.pretakedown = mga_driver_pretakedown; + dev->fn_tbl.dma_quiescent = mga_driver_dma_quiescent; + dev->fn_tbl.vblank_wait = mga_driver_vblank_wait; + dev->fn_tbl.irq_preinstall = mga_driver_irq_preinstall; + dev->fn_tbl.irq_postinstall = mga_driver_irq_postinstall; + dev->fn_tbl.irq_uninstall = mga_driver_irq_uninstall; + dev->fn_tbl.irq_handler = mga_driver_irq_handler; + + dev->counters += 3; + dev->types[6] = _DRM_STAT_IRQ; + dev->types[7] = _DRM_STAT_PRIMARY; + dev->types[8] = _DRM_STAT_SECONDARY; +} diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 6bcad048f..aa27a2c4b 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -35,19 +35,4 @@ #include "drm.h" #include "mga_drm.h" #include "mga_drv.h" -#include "drm_agpsupport.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_irq.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" +#include "drm_core.h" diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 65847165c..75dcb0e93 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h @@ -130,6 +130,12 @@ extern int mga_getparam( DRM_IOCTL_ARGS ); extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); extern int mga_warp_init( drm_mga_private_t *dev_priv ); +extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); +extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ); +extern void mga_driver_irq_preinstall( drm_device_t *dev ); +extern void mga_driver_irq_postinstall( drm_device_t *dev ); +extern void mga_driver_irq_uninstall( drm_device_t *dev ); + #define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() #if defined(__linux__) && defined(__alpha__) diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c index e486618b2..c3185b0b8 100644 --- a/drivers/char/drm/mga_irq.c +++ b/drivers/char/drm/mga_irq.c @@ -36,7 +36,7 @@ #include "mga_drm.h" #include "mga_drv.h" -irqreturn_t mga_irq_handler( DRM_IRQ_ARGS ) +irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_mga_private_t *dev_priv = @@ -56,7 +56,7 @@ irqreturn_t mga_irq_handler( DRM_IRQ_ARGS ) return IRQ_NONE; } -int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence) +int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) { unsigned int cur_vblank; int ret = 0; diff --git a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h index 9dfe18974..1df7042a2 100644 --- a/drivers/char/drm/r128.h +++ b/drivers/char/drm/r128.h @@ -36,13 +36,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 0 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 -#define __HAVE_SG 1 -#define __HAVE_PCI_DMA 1 - #define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." #define DRIVER_NAME "r128" @@ -79,42 +72,4 @@ [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, \ [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)] = { r128_getparam, 1, 0 }, -/* Driver customization: - */ -#define DRIVER_PRERELEASE() do { \ - if ( dev->dev_private ) { \ - drm_r128_private_t *dev_priv = dev->dev_private; \ - if ( dev_priv->page_flipping ) { \ - r128_do_cleanup_pageflip( dev ); \ - } \ - } \ -} while (0) - -#define DRIVER_PRETAKEDOWN() do { \ - r128_do_cleanup_cce( dev ); \ -} while (0) - -/* DMA customization: - */ -#define __HAVE_DMA 1 -#define __HAVE_IRQ 1 -#define __HAVE_VBL_IRQ 1 -#define __HAVE_SHARED_IRQ 1 - -#if 0 -/* GH: Remove this for now... */ -#define __HAVE_DMA_QUIESCENT 1 -#define DRIVER_DMA_QUIESCENT() do { \ - drm_r128_private_t *dev_priv = dev->dev_private; \ - return r128_do_cce_idle( dev_priv ); \ -} while (0) -#endif - -/* Buffer customization: - */ -#define DRIVER_BUF_PRIV_T drm_r128_buf_priv_t - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_r128_private_t *)((dev)->dev_private))->buffers - #endif diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index 22d38b70c..5fbea8ca6 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -322,7 +322,7 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev, /* The manual (p. 2) says this address is in "VM space". This * means it's an offset from the start of AGP space. */ -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) ring_start = dev_priv->cce_ring->offset - dev->agp->base; else @@ -467,29 +467,29 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); + dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset ); + dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); if(!dev_priv->cce_ring) { DRM_ERROR("could not find cce ring region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); + dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if(!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - if(!dev_priv->buffers) { + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if(!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); @@ -497,8 +497,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) } if ( !dev_priv->is_pci ) { - DRM_FIND_MAP( dev_priv->agp_textures, - init->agp_textures_offset ); + dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset); if(!dev_priv->agp_textures) { DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; @@ -511,14 +510,14 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring, dev ); - DRM_IOREMAP( dev_priv->ring_rptr, dev ); - DRM_IOREMAP( dev_priv->buffers, dev ); + drm_core_ioremap( dev_priv->cce_ring, dev ); + drm_core_ioremap( dev_priv->ring_rptr, dev ); + drm_core_ioremap( dev->agp_buffer_map, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || - !dev_priv->buffers->handle) { + !dev->agp_buffer_map->handle) { DRM_ERROR("Could not ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce( dev ); @@ -531,10 +530,10 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) (void *)dev_priv->cce_ring->offset; dev_priv->ring_rptr->handle = (void *)dev_priv->ring_rptr->offset; - dev_priv->buffers->handle = (void *)dev_priv->buffers->offset; + dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset; } -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) dev_priv->cce_buffers_offset = dev->agp->base; else @@ -559,7 +558,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) R128_WRITE( R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch ); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( dev_priv->is_pci ) { #endif if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, @@ -570,7 +569,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) return DRM_ERR(ENOMEM); } R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart ); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP } #endif @@ -587,25 +586,23 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) int r128_do_cleanup_cce( drm_device_t *dev ) { -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { if ( dev_priv->cce_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cce_ring, dev ); + drm_core_ioremapfree( dev_priv->cce_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); + drm_core_ioremapfree( dev_priv->ring_rptr, dev ); + if ( dev->agp_buffer_map != NULL ) + drm_core_ioremapfree( dev->agp_buffer_map, dev ); } else #endif { diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index 1dee16159..8cfc9966c 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -37,20 +37,4 @@ #include "r128_drv.h" #include "ati_pcigart.h" -#include "drm_agpsupport.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_irq.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" -#include "drm_scatter.h" +#include "drm_core.h" diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index 9df32e566..5b91256c1 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h @@ -100,7 +100,6 @@ typedef struct drm_r128_private { drm_local_map_t *mmio; drm_local_map_t *cce_ring; drm_local_map_t *ring_rptr; - drm_local_map_t *buffers; drm_local_map_t *agp_textures; } drm_r128_private_t; @@ -143,6 +142,12 @@ extern int r128_cce_depth( DRM_IOCTL_ARGS ); extern int r128_cce_stipple( DRM_IOCTL_ARGS ); extern int r128_cce_indirect( DRM_IOCTL_ARGS ); +extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); + +extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS ); +extern void r128_driver_irq_preinstall( drm_device_t *dev ); +extern void r128_driver_irq_postinstall( drm_device_t *dev ); +extern void r128_driver_irq_uninstall( drm_device_t *dev ); /* Register definitions, register access macros and drmAddMap constants * for Rage 128 kernel driver. diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c index e77a5538b..be1b9dac6 100644 --- a/drivers/char/drm/r128_irq.c +++ b/drivers/char/drm/r128_irq.c @@ -36,7 +36,7 @@ #include "r128_drm.h" #include "r128_drv.h" -irqreturn_t r128_irq_handler( DRM_IRQ_ARGS ) +irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_r128_private_t *dev_priv = @@ -56,7 +56,7 @@ irqreturn_t r128_irq_handler( DRM_IRQ_ARGS ) return IRQ_NONE; } -int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) { unsigned int cur_vblank; int ret = 0; diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c index 34ebcae1f..adc326698 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c @@ -667,7 +667,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev, */ if ( dwords & 1 ) { u32 *data = (u32 *) - ((char *)dev_priv->buffers->handle + ((char *)dev->agp_buffer_map->handle + buf->offset + start); data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 ); } @@ -713,7 +713,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev, drm_r128_buf_priv_t *buf_priv = buf->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int format = sarea_priv->vc_format; - int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset; + int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset; int prim = buf_priv->prim; u32 *data; int dwords; @@ -733,7 +733,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev, dwords = (end - start + 3) / sizeof(u32); - data = (u32 *)((char *)dev_priv->buffers->handle + data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset + start); data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, @@ -857,7 +857,7 @@ static int r128_cce_dispatch_blit( DRMFILE filp, dwords = (blit->width * blit->height) >> dword_shift; - data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); + data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset); data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) ); data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL | @@ -1694,3 +1694,31 @@ int r128_getparam( DRM_IOCTL_ARGS ) return 0; } + +static void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp) +{ + if ( dev->dev_private ) { + drm_r128_private_t *dev_priv = dev->dev_private; + if ( dev_priv->page_flipping ) { + r128_do_cleanup_pageflip( dev ); + } + } +} + +static void r128_driver_pretakedown(drm_device_t *dev) +{ + r128_do_cleanup_cce( dev ); +} + +void r128_driver_register_fns(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL; + dev->dev_priv_size = sizeof(drm_r128_buf_priv_t); + dev->fn_tbl.prerelease = r128_driver_prerelease; + dev->fn_tbl.pretakedown = r128_driver_pretakedown; + dev->fn_tbl.vblank_wait = r128_driver_vblank_wait; + dev->fn_tbl.irq_preinstall = r128_driver_irq_preinstall; + dev->fn_tbl.irq_postinstall = r128_driver_irq_postinstall; + dev->fn_tbl.irq_uninstall = r128_driver_irq_uninstall; + dev->fn_tbl.irq_handler = r128_driver_irq_handler; +} diff --git a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h index 83902f869..43723d53e 100644 --- a/drivers/char/drm/radeon.h +++ b/drivers/char/drm/radeon.h @@ -37,12 +37,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 0 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 -#define __HAVE_SG 1 -#define __HAVE_PCI_DMA 1 #define DRIVER_AUTHOR "Gareth Hughes, Keith Whitwell, others." @@ -115,59 +109,4 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 }, \ -#define DRIVER_FILE_FIELDS \ - int64_t radeon_fb_delta; \ - -#define DRIVER_OPEN_HELPER( filp_priv, dev ) \ -do { \ - drm_radeon_private_t *dev_priv = dev->dev_private; \ - if ( dev_priv ) \ - filp_priv->radeon_fb_delta = dev_priv->fb_location; \ - else \ - filp_priv->radeon_fb_delta = 0; \ -} while( 0 ) - -/* When a client dies: - * - Check for and clean up flipped page state - * - Free any alloced GART memory. - * - * DRM infrastructure takes care of reclaiming dma buffers. - */ -#define DRIVER_PRERELEASE() \ -do { \ - if ( dev->dev_private ) { \ - drm_radeon_private_t *dev_priv = dev->dev_private; \ - if ( dev_priv->page_flipping ) { \ - radeon_do_cleanup_pageflip( dev ); \ - } \ - radeon_mem_release( filp, dev_priv->gart_heap ); \ - radeon_mem_release( filp, dev_priv->fb_heap ); \ - } \ -} while (0) - -/* When the last client dies, shut down the CP and free dev->dev_priv. - */ -/* #define __HAVE_RELEASE 1 */ -#define DRIVER_PRETAKEDOWN() \ -do { \ - radeon_do_release( dev ); \ -} while (0) - - - -/* DMA customization: - */ -#define __HAVE_DMA 1 -#define __HAVE_IRQ 1 -#define __HAVE_VBL_IRQ 1 -#define __HAVE_SHARED_IRQ 1 - - -/* Buffer customization: - */ -#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t - -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_radeon_private_t *)((dev)->dev_private))->buffers - #endif diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index f6964908a..43834b906 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -858,7 +858,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 ) | ( dev_priv->fb_location >> 16 ) ); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { RADEON_WRITE( RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + @@ -885,7 +885,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, SET_RING_HEAD( dev_priv, cur_read_ptr ); dev_priv->ring.tail = cur_read_ptr; -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset @@ -1118,29 +1118,29 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); + dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset ); + dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); if(!dev_priv->cp_ring) { DRM_ERROR("could not find cp ring region!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); + dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if(!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); - if(!dev_priv->buffers) { + dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); + if(!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); @@ -1148,7 +1148,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) } if ( init->gart_textures_offset ) { - DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset ); + dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset); if ( !dev_priv->gart_textures ) { DRM_ERROR("could not find GART texture region!\n"); dev->dev_private = (void *)dev_priv; @@ -1161,14 +1161,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring, dev ); - DRM_IOREMAP( dev_priv->ring_rptr, dev ); - DRM_IOREMAP( dev_priv->buffers, dev ); + drm_core_ioremap( dev_priv->cp_ring, dev ); + drm_core_ioremap( dev_priv->ring_rptr, dev ); + drm_core_ioremap( dev->agp_buffer_map, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || - !dev_priv->buffers->handle) { + !dev->agp_buffer_map->handle) { DRM_ERROR("could not find ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); @@ -1181,14 +1181,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) (void *)dev_priv->cp_ring->offset; dev_priv->ring_rptr->handle = (void *)dev_priv->ring_rptr->offset; - dev_priv->buffers->handle = (void *)dev_priv->buffers->offset; + dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset; DRM_DEBUG( "dev_priv->cp_ring->handle %p\n", dev_priv->cp_ring->handle ); DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n", dev_priv->ring_rptr->handle ); - DRM_DEBUG( "dev_priv->buffers->handle %p\n", - dev_priv->buffers->handle ); + DRM_DEBUG( "dev->agp_buffer_map->handle %p\n", + dev->agp_buffer_map->handle ); } dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION ) @@ -1211,14 +1211,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->gart_vm_start = dev_priv->fb_location + RADEON_READ( RADEON_CONFIG_APER_SIZE ); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) - dev_priv->gart_buffers_offset = (dev_priv->buffers->offset + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - dev->agp->base + dev_priv->gart_vm_start); else #endif - dev_priv->gart_buffers_offset = (dev_priv->buffers->offset + dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - dev->sg->handle + dev_priv->gart_vm_start); @@ -1240,7 +1240,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); @@ -1275,25 +1275,23 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) { DRM_DEBUG( "\n" ); -#if __HAVE_IRQ /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. */ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); -#endif if ( dev->dev_private ) { drm_radeon_private_t *dev_priv = dev->dev_private; -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); + drm_core_ioremapfree( dev_priv->cp_ring, dev ); if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); + drm_core_ioremapfree( dev_priv->ring_rptr, dev ); + if ( dev->agp_buffer_map != NULL ) + drm_core_ioremapfree( dev->agp_buffer_map, dev ); } else #endif { @@ -1329,7 +1327,7 @@ static int radeon_do_resume_cp( drm_device_t *dev ) DRM_DEBUG("Starting radeon_do_resume_cp()\n"); -#if __REALLY_HAVE_AGP +#if __OS_HAS_AGP if ( !dev_priv->is_pci ) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index 74e32df01..965abc449 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c @@ -38,20 +38,4 @@ #include "radeon_drv.h" #include "ati_pcigart.h" -#include "drm_agpsupport.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_irq.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" -#include "drm_scatter.h" +#include "drm_core.h" diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index e24e0ec09..5df72332e 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -60,6 +60,9 @@ typedef struct drm_radeon_depth_clear_t { u32 se_cntl; } drm_radeon_depth_clear_t; +struct drm_radeon_driver_file_fields { + int64_t radeon_fb_delta; +}; struct mem_block { struct mem_block *next; @@ -138,7 +141,6 @@ typedef struct drm_radeon_private { drm_local_map_t *mmio; drm_local_map_t *cp_ring; drm_local_map_t *ring_rptr; - drm_local_map_t *buffers; drm_local_map_t *gart_textures; struct mem_block *gart_heap; @@ -203,6 +205,11 @@ extern int radeon_wait_irq(drm_device_t *dev, int swi_nr); extern int radeon_emit_irq(drm_device_t *dev); extern void radeon_do_release(drm_device_t *dev); +extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); +extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS ); +extern void radeon_driver_irq_preinstall( drm_device_t *dev ); +extern void radeon_driver_irq_postinstall( drm_device_t *dev ); +extern void radeon_driver_irq_uninstall( drm_device_t *dev ); /* Flags for stats.boxes */ diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index 51d194935..bdb3cc168 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c @@ -54,7 +54,7 @@ * tied to dma at all, this is just a hangover from dri prehistory. */ -irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS ) +irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = @@ -141,7 +141,7 @@ int radeon_emit_and_wait_irq(drm_device_t *dev) } -int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c index 289957406..f82d0c424 100644 --- a/drivers/char/drm/radeon_mem.c +++ b/drivers/char/drm/radeon_mem.c @@ -85,7 +85,7 @@ static struct mem_block *alloc_block( struct mem_block *heap, int size, struct mem_block *p; int mask = (1 << align2)-1; - for (p = heap->next ; p != heap ; p = p->next) { + list_for_each(p, heap) { int start = (p->start + mask) & ~mask; if (p->filp == 0 && start + size <= p->start + p->size) return split_block( p, start, size, filp ); @@ -98,7 +98,7 @@ static struct mem_block *find_block( struct mem_block *heap, int start ) { struct mem_block *p; - for (p = heap->next ; p != heap ; p = p->next) + list_for_each(p, heap) if (p->start == start) return p; @@ -166,7 +166,7 @@ void radeon_mem_release( DRMFILE filp, struct mem_block *heap ) if (!heap || !heap->next) return; - for (p = heap->next ; p != heap ; p = p->next) { + list_for_each(p, heap) { if (p->filp == filp) p->filp = NULL; } @@ -174,7 +174,7 @@ void radeon_mem_release( DRMFILE filp, struct mem_block *heap ) /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ - for (p = heap->next ; p != heap ; p = p->next) { + list_for_each(p, heap) { while (p->filp == 0 && p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 984d74589..f3cc86eea 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -43,12 +43,14 @@ static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_p drm_file_t *filp_priv, u32 *offset ) { u32 off = *offset; + struct drm_radeon_driver_file_fields *radeon_priv; if ( off >= dev_priv->fb_location && off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) ) return 0; - off += filp_priv->radeon_fb_delta; + radeon_priv = filp_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; DRM_DEBUG( "offset fixed up to 0x%x\n", off ); @@ -1247,7 +1249,7 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, */ if ( dwords & 1 ) { u32 *data = (u32 *) - ((char *)dev_priv->buffers->handle + ((char *)dev->agp_buffer_map->handle + buf->offset + start); data[dwords++] = RADEON_CP_PACKET2; } @@ -1301,7 +1303,7 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, dwords = (prim->finish - prim->start + 3) / sizeof(u32); - data = (u32 *)((char *)dev_priv->buffers->handle + + data = (u32 *)((char *)dev->agp_buffer_map->handle + elt_buf->offset + prim->start); data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); @@ -1445,7 +1447,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp, /* Dispatch the indirect buffer. */ - buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset); + buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset); dwords = size / 4; buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | @@ -1665,11 +1667,6 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS ) LOCK_TEST_WITH_RETURN( dev, filp ); - if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data, @@ -2525,6 +2522,7 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; drm_radeon_setparam_t sp; + struct drm_radeon_driver_file_fields *radeon_priv; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); @@ -2538,7 +2536,8 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) { switch( sp.param ) { case RADEON_SETPARAM_FB_LOCATION: - filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value; + radeon_priv = filp_priv->driver_priv; + radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value; break; default: DRM_DEBUG( "Invalid parameter %d\n", sp.param ); @@ -2547,3 +2546,67 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) { return 0; } + +/* When a client dies: + * - Check for and clean up flipped page state + * - Free any alloced GART memory. + * + * DRM infrastructure takes care of reclaiming dma buffers. + */ +static void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp) +{ + if ( dev->dev_private ) { + drm_radeon_private_t *dev_priv = dev->dev_private; + if ( dev_priv->page_flipping ) { + radeon_do_cleanup_pageflip( dev ); + } + radeon_mem_release( filp, dev_priv->gart_heap ); + radeon_mem_release( filp, dev_priv->fb_heap ); + } +} + +static void radeon_driver_pretakedown(drm_device_t *dev) +{ + radeon_do_release(dev); +} + +static int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_driver_file_fields *radeon_priv; + + radeon_priv = (struct drm_radeon_driver_file_fields *)DRM(alloc)(sizeof(*radeon_priv), DRM_MEM_FILES); + + if (!radeon_priv) + return -ENOMEM; + + filp_priv->driver_priv = radeon_priv; + if ( dev_priv ) + radeon_priv->radeon_fb_delta = dev_priv->fb_location; + else + radeon_priv->radeon_fb_delta = 0; + return 0; +} + + +static void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv) +{ + struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv; + + DRM(free)(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES); +} + +void radeon_driver_register_fns(struct drm_device *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL; + dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t); + dev->fn_tbl.prerelease = radeon_driver_prerelease; + dev->fn_tbl.pretakedown = radeon_driver_pretakedown; + dev->fn_tbl.open_helper = radeon_driver_open_helper; + dev->fn_tbl.free_filp_priv = radeon_driver_free_filp_priv; + dev->fn_tbl.vblank_wait = radeon_driver_vblank_wait; + dev->fn_tbl.irq_preinstall = radeon_driver_irq_preinstall; + dev->fn_tbl.irq_postinstall = radeon_driver_irq_postinstall; + dev->fn_tbl.irq_uninstall = radeon_driver_irq_uninstall; + dev->fn_tbl.irq_handler = radeon_driver_irq_handler; +} diff --git a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h index 7bdc99c0a..838e360df 100644 --- a/drivers/char/drm/sis.h +++ b/drivers/char/drm/sis.h @@ -41,10 +41,6 @@ /* General customization: */ -#define __HAVE_AGP 1 -#define __MUST_HAVE_AGP 0 -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 #define DRIVER_AUTHOR "SIS" #define DRIVER_NAME "sis" @@ -62,17 +58,4 @@ [DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)] = { sis_ioctl_agp_free, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)] = { sis_fb_init, 1, 1 } -#define __HAVE_COUNTERS 5 - -/* Buffer customization: - */ -#define DRIVER_AGP_BUFFERS_MAP( dev ) \ - ((drm_sis_private_t *)((dev)->dev_private))->buffers - -extern int sis_init_context(int context); -extern int sis_final_context(int context); - -#define DRIVER_CTX_CTOR sis_init_context -#define DRIVER_CTX_DTOR sis_final_context - #endif diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c index 3dd075d30..f05734374 100644 --- a/drivers/char/drm/sis_drv.c +++ b/drivers/char/drm/sis_drv.c @@ -31,18 +31,4 @@ #include "sis_drm.h" #include "sis_drv.h" -#include "drm_auth.h" -#include "drm_agpsupport.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" +#include "drm_core.h" diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h index 40e7f463e..a87001819 100644 --- a/drivers/char/drm/sis_drv.h +++ b/drivers/char/drm/sis_drv.h @@ -31,8 +31,6 @@ #include "sis_ds.h" typedef struct drm_sis_private { - drm_map_t *buffers; - memHeap_t *AGPHeap; memHeap_t *FBHeap; } drm_sis_private_t; diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 5d29b40be..244471647 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -90,9 +90,10 @@ int sis_fb_alloc( DRM_IOCTL_ARGS ) { drm_sis_mem_t fb; struct sis_memreq req; + drm_sis_mem_t __user *argp = (void __user *)data; int retval = 0; - DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); req.size = fb.size; sis_malloc(&req); @@ -111,7 +112,7 @@ int sis_fb_alloc( DRM_IOCTL_ARGS ) fb.free = 0; } - DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); + DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); @@ -123,7 +124,7 @@ int sis_fb_free( DRM_IOCTL_ARGS ) drm_sis_mem_t fb; int retval = 0; - DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); + DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb)); if (!fb.free) return DRM_ERR(EINVAL); @@ -325,7 +326,7 @@ int sis_ioctl_agp_free( DRM_IOCTL_ARGS ) return 0; } -int sis_init_context(int context) +int sis_init_context(struct drm_device *dev, int context) { int i; @@ -357,7 +358,7 @@ int sis_init_context(int context) return 1; } -int sis_final_context(int context) +int sis_final_context(struct drm_device *dev, int context) { int i; @@ -403,3 +404,10 @@ int sis_final_context(int context) return 1; } + +void DRM(driver_register_fns)(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR; + dev->fn_tbl.context_ctor = sis_init_context; + dev->fn_tbl.context_dtor = sis_final_context; +} diff --git a/drivers/char/drm/tdfx.h b/drivers/char/drm/tdfx.h index 6b067db78..a582a3db4 100644 --- a/drivers/char/drm/tdfx.h +++ b/drivers/char/drm/tdfx.h @@ -36,8 +36,6 @@ /* General customization: */ -#define __HAVE_MTRR 1 -#define __HAVE_CTX_BITMAP 1 #define DRIVER_AUTHOR "VA Linux Systems Inc." diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index fafa1f922..d13144438 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c @@ -34,18 +34,10 @@ #include "tdfx.h" #include "drmP.h" -#include "drm_auth.h" -#include "drm_bufs.h" -#include "drm_context.h" -#include "drm_dma.h" -#include "drm_drawable.h" -#include "drm_drv.h" +#include "drm_core.h" + +void DRM(driver_register_fns)(drm_device_t *dev) +{ + dev->driver_features = DRIVER_USE_MTRR; +} -#include "drm_fops.h" -#include "drm_init.h" -#include "drm_ioctl.h" -#include "drm_lock.h" -#include "drm_memory.h" -#include "drm_proc.h" -#include "drm_vm.h" -#include "drm_stub.h" diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index e2c4ecac7..7def6ad51 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -373,8 +373,7 @@ static int __init ds1620_init(void) th_start.hi = 1; ds1620_write_state(&th_start); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2*HZ); + msleep(2000); ds1620_write_state(&th); diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index b022aca3d..37d664901 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -58,12 +58,6 @@ #define DSP56K_TRANSMIT (dsp56k_host_interface.isr & DSP56K_ISR_TXDE) #define DSP56K_RECEIVE (dsp56k_host_interface.isr & DSP56K_ISR_RXDF) -#define wait_some(n) \ -{ \ - set_current_state(TASK_INTERRUPTIBLE); \ - schedule_timeout(n); \ -} - #define handshake(count, maxio, timeout, ENABLE, f) \ { \ long i, t, m; \ @@ -71,13 +65,13 @@ m = min_t(unsigned long, count, maxio); \ for (i = 0; i < m; i++) { \ for (t = 0; t < timeout && !ENABLE; t++) \ - wait_some(HZ/50); \ + msleep(20); \ if(!ENABLE) \ return -EIO; \ f; \ } \ count -= m; \ - if (m == maxio) wait_some(HZ/50); \ + if (m == maxio) msleep(20); \ } \ } @@ -85,7 +79,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \ - wait_some(HZ/100); \ + msleep(10); \ if(!DSP56K_TRANSMIT) { \ return -EIO; \ } \ @@ -95,7 +89,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_RECEIVE; t++) \ - wait_some(HZ/100); \ + msleep(10); \ if(!DSP56K_RECEIVE) { \ return -EIO; \ } \ diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index e8f15f46e..903e4c3cc 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -107,7 +107,6 @@ static struct file_operations dtlk_fops = }; /* local prototypes */ -static void dtlk_delay(int ms); static int dtlk_dev_probe(void); static struct dtlk_settings *dtlk_interrogate(void); static int dtlk_readable(void); @@ -146,7 +145,7 @@ static ssize_t dtlk_read(struct file *file, char __user *buf, return i; if (file->f_flags & O_NONBLOCK) break; - dtlk_delay(100); + msleep_interruptible(100); } if (retries == loops_per_jiffy) printk(KERN_ERR "dtlk_read times out\n"); @@ -191,7 +190,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, rate to 500 bytes/sec, but that's still enough to keep up with the speech synthesizer. */ - dtlk_delay(1); + msleep_interruptible(1); else { /* the RDY bit goes zero 2-3 usec after writing, and goes 1 again @@ -212,7 +211,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, if (file->f_flags & O_NONBLOCK) break; - dtlk_delay(1); + msleep_interruptible(1); if (++retries > 10 * HZ) { /* wait no more than 10 sec from last write */ @@ -351,8 +350,7 @@ static int __init dtlk_init(void) static void __exit dtlk_cleanup (void) { dtlk_write_bytes("goodbye", 8); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(5 * HZ / 10); /* nap 0.50 sec but + msleep_interruptible(500); /* nap 0.50 sec but could be awakened earlier by signals... */ @@ -368,13 +366,6 @@ module_exit(dtlk_cleanup); /* ------------------------------------------------------------------------ */ -/* sleep for ms milliseconds */ -static void dtlk_delay(int ms) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((ms * HZ + 1000 - HZ) / 1000); -} - static int dtlk_readable(void) { #ifdef TRACING @@ -431,7 +422,7 @@ static int __init dtlk_dev_probe(void) /* posting an index takes 18 msec. Here, we wait up to 100 msec to see whether it appears. */ - dtlk_delay(100); + msleep_interruptible(100); dtlk_has_indexing = dtlk_readable(); #ifdef TRACING printk(", indexing %d\n", dtlk_has_indexing); diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c index 933282df5..452d45c7b 100644 --- a/drivers/char/ec3104_keyb.c +++ b/drivers/char/ec3104_keyb.c @@ -43,9 +43,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -412,7 +412,7 @@ static void ec3104_keyb_clear_state(void) k->last_msr = 0; for (;;) { - schedule_timeout(HZ/10); + msleep(100); msr = ctrl_inb(EC3104_SER4_MSR); diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index 6d0b81298..1845739ee 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -155,7 +155,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, efi_time_t eft; efi_time_cap_t cap; struct rtc_time wtime; - struct rtc_wkalrm *ewp; + struct rtc_wkalrm __user *ewp; unsigned char enabled, pending; switch (cmd) { @@ -189,13 +189,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, convert_from_efi_time(&eft, &wtime); - return copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)) ? - EFAULT : 0; + return copy_to_user((void __user *)arg, &wtime, + sizeof (struct rtc_time)) ? - EFAULT : 0; case RTC_SET_TIME: if (!capable(CAP_SYS_TIME)) return -EACCES; - if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) ) + if (copy_from_user(&wtime, (struct rtc_time __user *)arg, + sizeof(struct rtc_time)) ) return -EFAULT; convert_to_efi_time(&wtime, &eft); @@ -212,19 +214,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (!capable(CAP_SYS_TIME)) return -EACCES; - ewp = (struct rtc_wkalrm *)arg; + ewp = (struct rtc_wkalrm __user *)arg; if ( get_user(enabled, &ewp->enabled) || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) ) return -EFAULT; convert_to_efi_time(&wtime, &eft); - + spin_lock_irqsave(&efi_rtc_lock, flags); /* * XXX Fixme: * As of EFI 0.92 with the firmware I have on my - * machine this call does not seem to work quite + * machine this call does not seem to work quite * right */ status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); @@ -243,14 +245,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (status != EFI_SUCCESS) return -EINVAL; - ewp = (struct rtc_wkalrm *)arg; + ewp = (struct rtc_wkalrm __user *)arg; if ( put_user(enabled, &ewp->enabled) || put_user(pending, &ewp->pending)) return -EFAULT; convert_from_efi_time(&eft, &wtime); - return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0; + return copy_to_user(&ewp->time, &wtime, + sizeof(struct rtc_time)) ? -EFAULT : 0; } return -EINVAL; } diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 854d16a39..6025e1866 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -74,7 +74,6 @@ #define DIGIINFOMAJOR 35 /* For Digi specific ioctl */ -#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAXCARDS 7 #define epcaassert(x, msg) if (!(x)) epca_error(__LINE__, msg) @@ -219,7 +218,7 @@ void epca_setup(char *, int *); void console_print(const char *); static int get_termio(struct tty_struct *, struct termio __user *); -static int pc_write(struct tty_struct *, int, const unsigned char *, int); +static int pc_write(struct tty_struct *, const unsigned char *, int); int pc_init(void); #ifdef ENABLE_PCI @@ -551,9 +550,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - + tty_ldisc_flush(tty); shutdown(ch); tty->closing = 0; ch->event = 0; @@ -564,8 +561,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp) if (ch->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(ch->close_delay); + msleep_interruptible(jiffies_to_msecs(ch->close_delay)); } wake_up_interruptible(&ch->open_wait); @@ -657,10 +653,7 @@ static void pc_hangup(struct tty_struct *tty) cli(); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - + tty_ldisc_flush(tty); shutdown(ch); ch->tty = NULL; @@ -676,7 +669,7 @@ static void pc_hangup(struct tty_struct *tty) /* ------------------ Begin pc_write ------------------------- */ -static int pc_write(struct tty_struct * tty, int from_user, +static int pc_write(struct tty_struct * tty, const unsigned char *buf, int bytesAvailable) { /* Begin pc_write */ @@ -714,162 +707,6 @@ static int pc_write(struct tty_struct * tty, int from_user, bc = ch->brdchan; size = ch->txbufsize; - if (from_user) - { /* Begin from_user */ - - save_flags(flags); - cli(); - - globalwinon(ch); - - /* ----------------------------------------------------------------- - Anding against size will wrap the pointer back to its beginning - position if it is necessary. This will only work if size is - a power of 2 which should always be the case. Size is determined - by the cards on board FEP/OS. - -------------------------------------------------------------------- */ - - /* head refers to the next empty location in which data may be stored */ - - head = bc->tin & (size - 1); - - /* tail refers to the next data byte to be transmitted */ - - tail = bc->tout; - - /* Consider changing this to a do statement to make sure */ - - if (tail != bc->tout) - tail = bc->tout; - - /* ------------------------------------------------------------------ - Anding against size will wrap the pointer back to its beginning - position if it is necessary. This will only work if size is - a power of 2 which should always be the case. Size is determined - by the cards on board FEP/OS. - --------------------------------------------------------------------- */ - - tail &= (size - 1); - - /* ----------------------------------------------------------------- - Two situations can affect how space in the transmit buffer - is calculated. You can have a situation where the transmit - in pointer (tin) head has wrapped around and actually has a - lower address than the transmit out pointer (tout) tail; or - the transmit in pointer (tin) head will not be wrapped around - yet, and have a higher address than the transmit out pointer - (tout) tail. Obviously space available in the transmit buffer - is calculated differently for each case. - - Example 1: - - Consider a 10 byte buffer where head is a pointer to the next - empty location in the buffer and tail is a pointer to the next - byte to transmit. In this example head will not have wrapped - around and therefore head > tail. - - 0 1 2 3 4 5 6 7 8 9 - tail head - - The above diagram shows that buffer locations 2,3,4,5 and 6 have - data to be transmitted, while head points at the next empty - location. To calculate how much space is available first we have - to determine if the head pointer (tin) has wrapped. To do this - compare the head pointer to the tail pointer, If head is equal - or greater than tail; then it has not wrapped; and the space may - be calculated by subtracting tail from head and then subtracting - that value from the buffers size. A one is subtracted from the - new value to indicate how much space is available between the - head pointer and end of buffer; as well as the space between the - beginning of the buffer and the tail. If the head is not greater - or equal to the tail this indicates that the head has wrapped - around to the beginning of the buffer. To calculate the space - available in this case simply subtract head from tail. This new - value minus one represents the space available betwwen the head - and tail pointers. In this example head (7) is greater than tail (2) - and therefore has not wrapped around. We find the space by first - subtracting tail from head (7-2=5). We then subtract this value - from the buffer size of ten and subtract one (10-5-1=4). The space - remaining is 4 bytes. - - Example 2: - - Consider a 10 byte buffer where head is a pointer to the next - empty location in the buffer and tail is a pointer to the next - byte to transmit. In this example head will wrapped around and - therefore head < tail. - - 0 1 2 3 4 5 6 7 8 9 - head tail - - The above diagram shows that buffer locations 7,8,9,0 and 1 have - data to be transmitted, while head points at the next empty - location. To find the space available we compare head to tail. If - head is not equal to, or greater than tail this indicates that head - has wrapped around. In this case head (2) is not equal to, or - greater than tail (7) and therefore has already wrapped around. To - calculate the available space between the two pointers we subtract - head from tail (7-2=5). We then subtract one from this new value - (5-1=4). We have 5 bytes empty remaining in the buffer. Unlike the - previous example these five bytes are located between the head and - tail pointers. - - ----------------------------------------------------------------------- */ - - dataLen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); - - /* ---------------------------------------------------------------------- - In this case bytesAvailable has been passed into pc_write and - represents the amount of data that needs to be written. dataLen - represents the amount of space available on the card. Whichever - value is smaller will be the amount actually written. - bytesAvailable will then take on this newly calculated value. - ---------------------------------------------------------------------- */ - - bytesAvailable = MIN(dataLen, bytesAvailable); - - /* First we read the data in from the file system into a temp buffer */ - - memoff(ch); - restore_flags(flags); - - if (bytesAvailable) - { /* Begin bytesAvailable */ - /* --------------------------------------------------------------- - The below function reads data from user memory. This routine - can not be used in an interrupt routine. (Because it may - generate a page fault) It can only be called while we can the - user context is accessible. - - The prototype is : - inline void copy_from_user(void * to, const void * from, - unsigned long count); - - I also think (Check hackers guide) that optimization must - be turned ON. (Which sounds strange to me...) - - Remember copy_from_user WILL generate a page fault if the - user memory being accessed has been swapped out. This can - cause this routine to temporarily sleep while this page - fault is occurring. - - ----------------------------------------------------------------- */ - - if (copy_from_user(ch->tmp_buf, buf, - bytesAvailable)) - return -EFAULT; - } /* End bytesAvailable */ - - /* ------------------------------------------------------------------ - Set buf to this address for the moment. tmp_buf was allocated in - post_fep_init. - --------------------------------------------------------------------- */ - buf = ch->tmp_buf; - - } /* End from_user */ - - /* All data is now local */ - amountCopied = 0; save_flags(flags); cli(); @@ -912,7 +749,7 @@ static int pc_write(struct tty_struct * tty, int from_user, space; reduce the amount of data to fit the space. ---------------------------------------------------------------------- */ - bytesAvailable = MIN(remain, bytesAvailable); + bytesAvailable = min(remain, bytesAvailable); txwinon(ch); while (bytesAvailable > 0) @@ -923,7 +760,7 @@ static int pc_write(struct tty_struct * tty, int from_user, data copy fills to the end of card buffer. ------------------------------------------------------------------- */ - dataLen = MIN(bytesAvailable, dataLen); + dataLen = min(bytesAvailable, dataLen); memcpy(ch->txptr + head, buf, dataLen); buf += dataLen; head += dataLen; @@ -960,7 +797,7 @@ static void pc_put_char(struct tty_struct *tty, unsigned char c) { /* Begin pc_put_char */ - pc_write(tty, 0, &c, 1); + pc_write(tty, &c, 1); return; } /* End pc_put_char */ @@ -1120,8 +957,7 @@ static void pc_flush_buffer(struct tty_struct *tty) restore_flags(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* End pc_flush_buffer */ @@ -2262,9 +2098,7 @@ static void doevent(int crd) { /* Begin if LOWWAIT */ ch->statusflags &= ~LOWWAIT; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } /* End if LOWWAIT */ @@ -2281,9 +2115,7 @@ static void doevent(int crd) { /* Begin if EMPTYWAIT */ ch->statusflags &= ~EMPTYWAIT; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); @@ -3136,6 +2968,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, } else { + /* ldisc lock already held in ioctl */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); } @@ -3307,7 +3140,6 @@ static void do_softint(void *private_) } } /* End EPCA_MAGIC */ - MOD_DEC_USE_COUNT; } /* End do_softint */ /* ------------------------------------------------------------ @@ -3944,23 +3776,12 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl); int __init init_PCI (void) { /* Begin init_PCI */ - - int pci_count; - memset (&epca_driver, 0, sizeof (epca_driver)); epca_driver.name = "epca"; epca_driver.id_table = epca_pci_tbl; epca_driver.probe = epca_init_one; - pci_count = pci_register_driver (&epca_driver); - - if (pci_count <= 0) { - pci_unregister_driver (&epca_driver); - pci_count = 0; - } - - return(pci_count); - + return pci_register_driver(&epca_driver); } /* End init_PCI */ #endif /* ENABLE_PCI */ diff --git a/drivers/char/epca.h b/drivers/char/epca.h index ee1c98385..52205ef71 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h @@ -149,7 +149,7 @@ struct board_info ushort numports; unchar *port; unchar *membase; - unchar *re_map_port; + unchar __iomem *re_map_port; unchar *re_map_membase; ulong memory_seg; void ( * memwinon ) (struct board_info *, unsigned int) ; diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 663a1e24f..62f8e3087 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -19,7 +19,7 @@ * * rs_set_termios fixed to look also for changes of the input * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. - * Bernd Anhäupl 05/17/96. + * Bernd Anh�pl 05/17/96. * * --- End of notices from serial.c --- * @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,7 @@ #define NR_PORTS 64 /* maximum number of ports */ #define NR_PRIMARY 8 /* maximum number of primary ports */ +#define REGION_SIZE 8 /* size of io region to request */ /* The following variables can be set by giving module options */ static int irq[NR_PRIMARY]; /* IRQ for each base port */ @@ -84,15 +86,15 @@ static unsigned int pio_threshold = ESP_PIO_THRESHOLD; MODULE_LICENSE("GPL"); -MODULE_PARM(irq, "1-8i"); -MODULE_PARM(divisor, "1-8i"); -MODULE_PARM(dma, "i"); -MODULE_PARM(rx_trigger, "i"); -MODULE_PARM(tx_trigger, "i"); -MODULE_PARM(flow_off, "i"); -MODULE_PARM(flow_on, "i"); -MODULE_PARM(rx_timeout, "i"); -MODULE_PARM(pio_threshold, "i"); +module_param_array(irq, int, NULL, 0); +module_param_array(divisor, uint, NULL, 0); +module_param(dma, uint, 0); +module_param(rx_trigger, uint, 0); +module_param(tx_trigger, uint, 0); +module_param(flow_off, uint, 0); +module_param(flow_on, uint, 0); +module_param(rx_timeout, uint, 0); +module_param(pio_threshold, uint, 0); /* END */ @@ -140,7 +142,7 @@ static struct esp_struct *ports; static void change_speed(struct esp_struct *info); static void rs_wait_until_sent(struct tty_struct *, int); - + /* * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE * times the normal 1.8432 Mhz clock of most serial boards). @@ -150,10 +152,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); /* Standard COM flags (except for COM4, because of the 8514 problem) */ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the memcpy_fromfs blocks while swapping in a page, @@ -762,10 +760,7 @@ static void do_softint(void *private_) return; if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } @@ -1270,7 +1265,7 @@ static void rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, t, ret = 0; @@ -1283,9 +1278,6 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit_buf || !tmp_buf) return 0; - if (from_user) - down(&tmp_buf_sem); - while (1) { /* Thanks to R. Wolff for suggesting how to do this with */ /* interrupts enabled */ @@ -1304,18 +1296,7 @@ static int rs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - c -= copy_from_user(tmp_buf, buf, c); - - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1); info->xmit_cnt += c; @@ -1324,9 +1305,6 @@ static int rs_write(struct tty_struct * tty, int from_user, ret += c; } - if (from_user) - up(&tmp_buf_sem); - save_flags(flags); cli(); if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { @@ -1370,10 +1348,7 @@ static void rs_flush_buffer(struct tty_struct *tty) cli(); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; sti(); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -2069,16 +2044,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; info->tty = NULL; if (info->blocked_open) { if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -2109,8 +2082,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) while ((serial_in(info, UART_ESI_STAT1) != 0x03) || (serial_in(info, UART_ESI_STAT2) != 0xff)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; @@ -2355,19 +2327,21 @@ static _INLINE_ void show_serial_version(void) * This routine is called by espserial_init() to initialize a specific serial * port. */ -static _INLINE_ int autoconfig(struct esp_struct * info, int *region_start) +static _INLINE_ int autoconfig(struct esp_struct * info) { int port_detected = 0; unsigned long flags; + if (!request_region(info->port, REGION_SIZE, "esp serial")) + return -EIO; + save_flags(flags); cli(); /* * Check for ESP card */ - if (!check_region(info->port, 8) && - serial_in(info, UART_ESI_BASE) == 0xf3) { + if (serial_in(info, UART_ESI_BASE) == 0xf3) { serial_out(info, UART_ESI_CMD1, 0x00); serial_out(info, UART_ESI_CMD1, 0x01); @@ -2383,19 +2357,6 @@ static _INLINE_ int autoconfig(struct esp_struct * info, int *region_start) info->irq = 4; } - if (ports && (ports->port == (info->port - 8))) { - release_region(*region_start, - info->port - *region_start); - } else - *region_start = info->port; - - if (!request_region(*region_start, - info->port - *region_start + 8, - "esp serial")) - { - restore_flags(flags); - return -EIO; - } /* put card in enhanced mode */ /* this prevents access through */ @@ -2408,6 +2369,8 @@ static _INLINE_ int autoconfig(struct esp_struct * info, int *region_start) serial_out(info, UART_ESI_CMD2, 0x00); } } + if (!port_detected) + release_region(info->port, REGION_SIZE); restore_flags(flags); return (port_detected); @@ -2441,7 +2404,6 @@ static struct tty_operations esp_ops = { int __init espserial_init(void) { int i, offset; - int region_start; struct esp_struct * info; struct esp_struct *last_primary = NULL; int esp[] = {0x100,0x140,0x180,0x200,0x240,0x280,0x300,0x380}; @@ -2527,7 +2489,7 @@ int __init espserial_init(void) info->irq = irq[i]; info->line = (i * 8) + (offset / 8); - if (!autoconfig(info, ®ion_start)) { + if (!autoconfig(info)) { i++; offset = 0; continue; @@ -2603,7 +2565,6 @@ static void __exit espserial_exit(void) { unsigned long flags; int e1; - unsigned int region_start, region_end; struct esp_struct *temp_async; struct esp_pio_buffer *pio_buf; @@ -2618,27 +2579,8 @@ static void __exit espserial_exit(void) while (ports) { if (ports->port) { - region_start = region_end = ports->port; - temp_async = ports; - - while (temp_async) { - if ((region_start - temp_async->port) == 8) { - region_start = temp_async->port; - temp_async->port = 0; - temp_async = ports; - } else if ((temp_async->port - region_end) - == 8) { - region_end = temp_async->port; - temp_async->port = 0; - temp_async = ports; - } else - temp_async = temp_async->next_port; - } - - release_region(region_start, - region_end - region_start + 8); + release_region(ports->port, REGION_SIZE); } - temp_async = ports->next_port; kfree(ports); ports = temp_async; diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c index 3b78eda30..a3b0f510b 100644 --- a/drivers/char/ftape/lowlevel/fdc-io.c +++ b/drivers/char/ftape/lowlevel/fdc-io.c @@ -389,7 +389,7 @@ int fdc_interrupt_wait(unsigned int time) recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&ftape_wait_intr, &wait); while (!ft_interrupt_seen && (current->state == TASK_INTERRUPTIBLE)) { timeout = schedule_timeout(timeout); diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c index 34f0e69d3..956b2586e 100644 --- a/drivers/char/ftape/lowlevel/ftape-calibr.c +++ b/drivers/char/ftape/lowlevel/ftape-calibr.c @@ -31,7 +31,10 @@ #include #if defined(__alpha__) # include -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__x86_64__) +# include +# include +#elif defined(__i386__) # include #endif #include @@ -45,7 +48,7 @@ # error Ftape is not implemented for this architecture! #endif -#if defined(__alpha__) +#if defined(__alpha__) || defined(__x86_64__) static unsigned long ps_per_cycle = 0; #endif @@ -72,7 +75,18 @@ unsigned int ftape_timestamp(void) asm volatile ("rpcc %0" : "=r" (r)); return r; -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__x86_64__) + unsigned long r; + rdtscl(r); + return r; +#elif defined(__i386__) + +/* + * Note that there is some time between counter underflowing and jiffies + * increasing, so the code below won't always give correct output. + * -Vojtech + */ + unsigned long flags; __u16 lo; __u16 hi; @@ -89,9 +103,9 @@ unsigned int ftape_timestamp(void) static unsigned int short_ftape_timestamp(void) { -#if defined(__alpha__) +#if defined(__alpha__) || defined(__x86_64__) return ftape_timestamp(); -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__i386__) unsigned int count; unsigned long flags; @@ -106,9 +120,9 @@ static unsigned int short_ftape_timestamp(void) static unsigned int diff(unsigned int t0, unsigned int t1) { -#if defined(__alpha__) - return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0; -#elif defined(__i386__) || defined(__x86_64__) +#if defined(__alpha__) || defined(__x86_64__) + return (t1 - t0); +#elif defined(__i386__) /* * This is tricky: to work for both short and full ftape_timestamps * we'll have to discriminate between these. @@ -122,9 +136,9 @@ static unsigned int diff(unsigned int t0, unsigned int t1) static unsigned int usecs(unsigned int count) { -#if defined(__alpha__) +#if defined(__alpha__) || defined(__x86_64__) return (ps_per_cycle * count) / 1000000UL; -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__i386__) return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100); #endif } @@ -163,38 +177,13 @@ static void time_inb(void) static void init_clock(void) { -#if defined(__i386__) || defined(__x86_64__) - unsigned int t; - int i; TRACE_FUN(ft_t_any); - /* Haven't studied on why, but there sometimes is a problem - * with the tick timer readout. The two bytes get swapped. - * This hack solves that problem by doing one extra input. - */ - for (i = 0; i < 1000; ++i) { - t = short_ftape_timestamp(); - if (t > LATCH) { - inb_p(0x40); /* get in sync again */ - TRACE(ft_t_warn, "clock counter fixed"); - break; - } - } +#if defined(__x86_64__) + ps_per_cycle = 1000000000UL / cpu_khz; #elif defined(__alpha__) -#if CONFIG_FT_ALPHA_CLOCK == 0 -#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' ! -#endif extern struct hwrpb_struct *hwrpb; - TRACE_FUN(ft_t_any); - - if (hwrpb->cycle_freq != 0) { - ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq; - } else { - /* - * HELP: Linux 2.0.x doesn't set cycle_freq on my noname ! - */ - ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK; - } + ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq; #endif TRACE_EXIT; } @@ -213,7 +202,7 @@ void ftape_calibrate(char *name, unsigned int tc = 0; unsigned int count; unsigned int time; -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) unsigned int old_tc = 0; unsigned int old_count = 1; unsigned int old_time = 1; @@ -255,7 +244,7 @@ void ftape_calibrate(char *name, tc = (1000 * time) / (count - 1); TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns", usecs(once), count - 1, usecs(multiple), tc); -#if defined(__alpha__) +#if defined(__alpha__) || defined(__x86_64__) /* * Increase the calibration count exponentially until the * calibration time exceeds 100 ms. @@ -263,7 +252,7 @@ void ftape_calibrate(char *name, if (time >= 100*1000) { break; } -#elif defined(__i386__) || defined(__x86_64__) +#elif defined(__i386__) /* * increase the count until the resulting time nears 2/HZ, * then the tc will drop sharply because we lose LATCH counts. diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c index 1d4619ab9..f83b60ccc 100644 --- a/drivers/char/ftape/lowlevel/ftape-ctl.c +++ b/drivers/char/ftape/lowlevel/ftape-ctl.c @@ -726,9 +726,12 @@ int ftape_mmap(struct vm_area_struct *vma) ftape_reset_buffer(); } for (i = 0; i < num_buffers; i++) { - TRACE_CATCH(remap_page_range(vma, vma->vm_start + + unsigned long pfn; + + pfn = virt_to_phys(ft_buffer[i]->address) >> PAGE_SHIFT; + TRACE_CATCH(remap_pfn_range(vma, vma->vm_start + i * FT_BUFF_SIZE, - virt_to_phys(ft_buffer[i]->address), + pfn, FT_BUFF_SIZE, vma->vm_page_prot), _res = -EAGAIN); diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c index 17a7f0e0c..68f302f5a 100644 --- a/drivers/char/ftape/lowlevel/ftape-init.c +++ b/drivers/char/ftape/lowlevel/ftape-init.c @@ -122,20 +122,29 @@ KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE); #endif TRACE_EXIT 0; } -#define FT_MOD_PARM(var,type,desc) \ - MODULE_PARM(var,type); MODULE_PARM_DESC(var,desc) - -FT_MOD_PARM(ft_fdc_base, "i", "Base address of FDC controller."); -FT_MOD_PARM(ft_fdc_irq, "i", "IRQ (interrupt channel) to use."); -FT_MOD_PARM(ft_fdc_dma, "i", "DMA channel to use."); -FT_MOD_PARM(ft_fdc_threshold, "i", "Threshold of the FDC Fifo."); -FT_MOD_PARM(ft_fdc_rate_limit, "i", "Maximal data rate for FDC."); -FT_MOD_PARM(ft_probe_fc10, "i", + +module_param(ft_fdc_base, uint, 0); +MODULE_PARM_DESC(ft_fdc_base, "Base address of FDC controller."); +module_param(ft_fdc_irq, uint, 0); +MODULE_PARM_DESC(ft_fdc_irq, "IRQ (interrupt channel) to use."); +module_param(ft_fdc_dma, uint, 0); +MODULE_PARM_DESC(ft_fdc_dma, "DMA channel to use."); +module_param(ft_fdc_threshold, uint, 0); +MODULE_PARM_DESC(ft_fdc_threshold, "Threshold of the FDC Fifo."); +module_param(ft_fdc_rate_limit, uint, 0); +MODULE_PARM_DESC(ft_fdc_rate_limit, "Maximal data rate for FDC."); +module_param(ft_probe_fc10, bool, 0); +MODULE_PARM_DESC(ft_probe_fc10, "If non-zero, probe for a Colorado FC-10/FC-20 controller."); -FT_MOD_PARM(ft_mach2, "i", +module_param(ft_mach2, bool, 0); +MODULE_PARM_DESC(ft_mach2, "If non-zero, probe for a Mountain MACH-2 controller."); -FT_MOD_PARM(ft_tracing, "i", +#if defined(MODULE) && !defined(CONFIG_FT_NO_TRACE_AT_ALL) +module_param(ft_tracing, int, 0644); +MODULE_PARM_DESC(ft_tracing, "Amount of debugging output, 0 <= tracing <= 8, default 3."); +#endif + MODULE_AUTHOR( "(c) 1993-1996 Bas Laarhoven (bas@vimec.nl), " "(c) 1995-1996 Kai Harrekilde-Petersen (khp@dolphinics.no), " diff --git a/drivers/char/ftape/lowlevel/ftape-io.c b/drivers/char/ftape/lowlevel/ftape-io.c index bd3b2f117..b7910d429 100644 --- a/drivers/char/ftape/lowlevel/ftape-io.c +++ b/drivers/char/ftape/lowlevel/ftape-io.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -96,19 +97,12 @@ void ftape_sleep(unsigned int time) timeout = ticks; save_flags(flags); sti(); - set_current_state(TASK_INTERRUPTIBLE); - do { - /* Mmm. Isn't current->blocked == 0xffffffff ? - */ - if (signal_pending(current)) { - TRACE(ft_t_err, - "awoken by non-blocked signal :-("); - break; /* exit on signal */ - } - while (current->state != TASK_RUNNING) { - timeout = schedule_timeout(timeout); - } - } while (timeout); + msleep_interruptible(jiffies_to_msecs(timeout)); + /* Mmm. Isn't current->blocked == 0xffffffff ? + */ + if (signal_pending(current)) { + TRACE(ft_t_err, "awoken by non-blocked signal :-("); + } restore_flags(flags); } TRACE_EXIT; diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c index 3d6483983..ec4fdaabe 100644 --- a/drivers/char/ftape/zftape/zftape-buffers.c +++ b/drivers/char/ftape/zftape/zftape-buffers.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -119,8 +120,7 @@ void *zft_kmalloc(size_t size) void *new; while ((new = kmalloc(size, GFP_KERNEL)) == NULL) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + msleep_interruptible(100); } memset(new, 0, size); used_memory += size; diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 1027eb7c6..d95ad27cb 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ static int gs_debug; #define RS_EVENT_WRITE_WAKEUP 1 -MODULE_PARM(gs_debug, "i"); +module_param(gs_debug, int, 0644); void gs_put_char(struct tty_struct * tty, unsigned char ch) @@ -102,7 +103,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) > -3- Other processes that are also trying to do a "write". */ -int gs_write(struct tty_struct * tty, int from_user, +int gs_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct gs_port *port; @@ -143,15 +144,8 @@ int gs_write(struct tty_struct * tty, int from_user, /* Can't copy more? break out! */ if (c <= 0) break; - if (from_user) { - if (copy_from_user (port->xmit_buf + port->xmit_head, - buf, c)) { - up (& port->port_write_sem); - return -EFAULT; - } - } else - memcpy (port->xmit_buf + port->xmit_head, buf, c); + memcpy (port->xmit_buf + port->xmit_head, buf, c); port -> xmit_cnt += c; port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); @@ -182,7 +176,7 @@ int gs_write(struct tty_struct * tty, int from_user, > -3- Other processes that are also trying to do a "write". */ -int gs_write(struct tty_struct * tty, int from_user, +int gs_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct gs_port *port; @@ -215,79 +209,35 @@ int gs_write(struct tty_struct * tty, int from_user, return -EIO; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - cli(); - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - total += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = count; - - /* This is safe because we "OWN" the "head". Noone else can - change the "head": we own the port_write_sem. */ - /* Don't overrun the end of the buffer */ - t = SERIAL_XMIT_SIZE - port->xmit_head; - if (t < c) c = t; - - /* This is safe because the xmit_cnt can only decrease. This - would increase "t", so we might copy too little chars. */ - /* Don't copy past the "head" of the buffer */ - t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; - if (t < c) c = t; - - /* Can't copy more? break out! */ - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = ((port->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - port->xmit_cnt += c; + while (1) { + cli(); + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_sem. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) { restore_flags(flags); - buf += c; - count -= c; - total += c; + break; } + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = ((port->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + port->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; } if (port->xmit_cnt && @@ -399,8 +349,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " "(%d chars).\n", jiffies_to_transmit, charsleft); - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_to_transmit); + msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit)); if (signal_pending (current)) { gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); rv = -EINTR; @@ -436,9 +385,7 @@ void gs_flush_buffer(struct tty_struct *tty) restore_flags(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); func_exit (); } @@ -578,9 +525,7 @@ void gs_do_softint(void *private_) if (!tty) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } func_exit (); @@ -694,7 +639,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) { unsigned long flags; struct gs_port *port; - + func_enter (); if (!tty) return; @@ -760,8 +705,8 @@ void gs_close(struct tty_struct * tty, struct file * filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); tty->closing = 0; port->event = 0; @@ -771,8 +716,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) if (port->blocked_open) { if (port->close_delay) { - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout(port->close_delay); + msleep_interruptible(jiffies_to_msecs(port->close_delay)); } wake_up_interruptible(&port->open_wait); } diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 5e8c47244..ca7d88a6e 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -28,13 +28,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -60,8 +60,8 @@ static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED; struct hpet_dev { struct hpets *hd_hpets; - struct hpet *hd_hpet; - struct hpet_timer *hd_timer; + struct hpet __iomem *hd_hpet; + struct hpet_timer __iomem *hd_timer; unsigned long hd_ireqfreq; unsigned long hd_irqdata; wait_queue_head_t hd_waitqueue; @@ -75,7 +75,8 @@ struct hpet_dev { struct hpets { struct hpets *hp_next; - struct hpet *hp_hpet; + struct hpet __iomem *hp_hpet; + struct time_interpolator *hp_interpolator; unsigned long hp_period; unsigned long hp_delta; unsigned int hp_ntimer; @@ -98,14 +99,14 @@ static struct hpets *hpets; #endif #ifndef readq -static unsigned long long __inline readq(void *addr) +static unsigned long long __inline readq(void __iomem *addr) { return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL); } #endif #ifndef writeq -static void __inline writeq(unsigned long long v, void *addr) +static void __inline writeq(unsigned long long v, void __iomem *addr) { writel(v & 0xffffffff, addr); writel(v >> 32, addr + 4); @@ -273,9 +274,9 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); addr = __pa(addr); - if (remap_page_range - (vma, vma->vm_start, addr, PAGE_SIZE, vma->vm_page_prot)) { - printk(KERN_ERR "remap_page_range failed in hpet.c\n"); + if (remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot)) { + printk(KERN_ERR "remap_pfn_range failed in hpet.c\n"); return -EAGAIN; } @@ -300,7 +301,7 @@ static int hpet_fasync(int fd, struct file *file, int on) static int hpet_release(struct inode *inode, struct file *file) { struct hpet_dev *devp; - struct hpet_timer *timer; + struct hpet_timer __iomem *timer; int irq = 0; devp = file->private_data; @@ -352,8 +353,8 @@ hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static int hpet_ioctl_ieon(struct hpet_dev *devp) { - struct hpet_timer *timer; - struct hpet *hpet; + struct hpet_timer __iomem *timer; + struct hpet __iomem *hpet; struct hpets *hpetp; int irq; unsigned long g, v, t, m; @@ -435,8 +436,8 @@ static inline unsigned long hpet_time_div(unsigned long dis) static int hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) { - struct hpet_timer *timer; - struct hpet *hpet; + struct hpet_timer __iomem *timer; + struct hpet __iomem *hpet; struct hpets *hpetp; int err; unsigned long v; @@ -547,7 +548,7 @@ int hpet_register(struct hpet_task *tp, int periodic) { unsigned int i; u64 mask; - struct hpet_timer *timer; + struct hpet_timer __iomem *timer; struct hpet_dev *devp; struct hpets *hpetp; @@ -615,7 +616,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp) int hpet_unregister(struct hpet_task *tp) { struct hpet_dev *devp; - struct hpet_timer *timer; + struct hpet_timer __iomem *timer; int err; if ((err = hpet_tpcheck(tp))) @@ -660,46 +661,6 @@ int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) return hpet_ioctl_common(devp, cmd, arg, 1); } -#ifdef CONFIG_TIME_INTERPOLATION - -static unsigned long hpet_offset, last_wall_hpet; -static long hpet_nsecs_per_cycle, hpet_cycles_per_sec; - -static unsigned long hpet_getoffset(void) -{ - return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) - - last_wall_hpet) * hpet_nsecs_per_cycle; -} - -static void hpet_update(long delta) -{ - unsigned long mc; - unsigned long offset; - - mc = read_counter(&hpets->hp_hpet->hpet_mc); - offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle; - - if (delta < 0 || (unsigned long)delta < offset) - hpet_offset = offset - delta; - else - hpet_offset = 0; - last_wall_hpet = mc; -} - -static void hpet_reset(void) -{ - hpet_offset = 0; - last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc); -} - -static struct time_interpolator hpet_interpolator = { - .get_offset = hpet_getoffset, - .update = hpet_update, - .reset = hpet_reset -}; - -#endif - static ctl_table hpet_table[] = { { .ctl_name = 1, @@ -736,6 +697,28 @@ static ctl_table dev_root[] = { static struct ctl_table_header *sysctl_header; +static void hpet_register_interpolator(struct hpets *hpetp) +{ +#ifdef CONFIG_TIME_INTERPOLATION + struct time_interpolator *ti; + + ti = kmalloc(sizeof(*ti), GFP_KERNEL); + if (!ti) + return; + + memset(ti, 0, sizeof(*ti)); + ti->source = TIME_SOURCE_MMIO64; + ti->shift = 10; + ti->addr = &hpetp->hp_hpet->hpet_mc; + ti->frequency = hpet_time_div(hpets->hp_period); + ti->drift = ti->frequency * HPET_DRIFT / 1000000; + ti->mask = -1; + + hpetp->hp_interpolator = ti; + register_time_interpolator(ti); +#endif +} + /* * Adjustment for when arming the timer with * initial conditions. That is, main counter @@ -743,13 +726,13 @@ static struct ctl_table_header *sysctl_header; */ #define TICK_CALIBRATE (1000UL) -static unsigned long __init hpet_calibrate(struct hpets *hpetp) +static unsigned long hpet_calibrate(struct hpets *hpetp) { - struct hpet_timer *timer = NULL; + struct hpet_timer __iomem *timer = NULL; unsigned long t, m, count, i, flags, start; struct hpet_dev *devp; int j; - struct hpet *hpet; + struct hpet __iomem *hpet; for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++) if ((devp->hd_flags & HPET_OPEN) == 0) { @@ -780,15 +763,16 @@ static unsigned long __init hpet_calibrate(struct hpets *hpetp) return (m - start) / i; } -int __init hpet_alloc(struct hpet_data *hdp) +int hpet_alloc(struct hpet_data *hdp) { u64 cap, mcfg; struct hpet_dev *devp; u32 i, ntimer; struct hpets *hpetp; size_t siz; - struct hpet *hpet; - static struct hpets *last __initdata = (struct hpets *)0; + struct hpet __iomem *hpet; + static struct hpets *last = (struct hpets *)0; + unsigned long ns; /* * hpet_alloc can be called by platform dependent code. @@ -796,7 +780,7 @@ int __init hpet_alloc(struct hpet_data *hdp) * ACPI also reports hpet, then we catch it here. */ for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address)) + if (hpetp->hp_hpet == hdp->hd_address) return 0; siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * @@ -810,7 +794,7 @@ int __init hpet_alloc(struct hpet_data *hdp) memset(hpetp, 0, siz); hpetp->hp_which = hpet_nhpet++; - hpetp->hp_hpet = (struct hpet *)hdp->hd_address; + hpetp->hp_hpet = hdp->hd_address; hpetp->hp_ntimer = hdp->hd_nirqs; @@ -840,6 +824,19 @@ int __init hpet_alloc(struct hpet_data *hdp) hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> HPET_COUNTER_CLK_PERIOD_SHIFT; + printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", + hpetp->hp_which, hdp->hd_phys_address, + hpetp->hp_ntimer > 1 ? "s" : ""); + for (i = 0; i < hpetp->hp_ntimer; i++) + printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); + printk("\n"); + + ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ + do_div(ns, 1000000); /* convert to nanoseconds, 10^-9 */ + printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", + hpetp->hp_which, ns, hpetp->hp_ntimer, + cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); + mcfg = readq(&hpet->hpet_config); if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { write_counter(0L, &hpet->hpet_mc); @@ -850,7 +847,7 @@ int __init hpet_alloc(struct hpet_data *hdp) for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, hpet_ntimer++, devp++) { unsigned long v; - struct hpet_timer *timer; + struct hpet_timer __iomem *timer; timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; v = readq(&timer->hpet_config); @@ -872,11 +869,12 @@ int __init hpet_alloc(struct hpet_data *hdp) } hpetp->hp_delta = hpet_calibrate(hpetp); + hpet_register_interpolator(hpetp); return 0; } -static acpi_status __init hpet_resources(struct acpi_resource *res, void *data) +static acpi_status hpet_resources(struct acpi_resource *res, void *data) { struct hpet_data *hdp; acpi_status status; @@ -891,11 +889,11 @@ static acpi_status __init hpet_resources(struct acpi_resource *res, void *data) unsigned long size; size = addr.max_address_range - addr.min_address_range + 1; - hdp->hd_address = - (unsigned long)ioremap(addr.min_address_range, size); + hdp->hd_phys_address = addr.min_address_range; + hdp->hd_address = ioremap(addr.min_address_range, size); for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address)) + if (hpetp->hp_hpet == hdp->hd_address) return -EBUSY; } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { struct acpi_resource_ext_irq *irqp; @@ -917,7 +915,7 @@ static acpi_status __init hpet_resources(struct acpi_resource *res, void *data) return AE_OK; } -static int __init hpet_acpi_add(struct acpi_device *device) +static int hpet_acpi_add(struct acpi_device *device) { acpi_status result; struct hpet_data data; @@ -939,14 +937,14 @@ static int __init hpet_acpi_add(struct acpi_device *device) return hpet_alloc(&data); } -static int __init hpet_acpi_remove(struct acpi_device *device, int type) +static int hpet_acpi_remove(struct acpi_device *device, int type) { - return 0; + /* XXX need to unregister interpolator, dealloc mem, etc */ + return -EINVAL; } -static struct acpi_driver hpet_acpi_driver __initdata = { +static struct acpi_driver hpet_acpi_driver = { .name = "hpet", - .class = "", .ids = "PNP0103", .ops = { .add = hpet_acpi_add, @@ -958,38 +956,32 @@ static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; static int __init hpet_init(void) { - (void)acpi_bus_register_driver(&hpet_acpi_driver); + int result; + + result = misc_register(&hpet_misc); + if (result < 0) + return -ENODEV; - if (hpets) { - if (misc_register(&hpet_misc)) - return -ENODEV; + sysctl_header = register_sysctl_table(dev_root, 0); - sysctl_header = register_sysctl_table(dev_root, 0); + result = acpi_bus_register_driver(&hpet_acpi_driver); + if (result < 0) { + if (sysctl_header) + unregister_sysctl_table(sysctl_header); + misc_deregister(&hpet_misc); + return result; + } -#ifdef CONFIG_TIME_INTERPOLATION - { - struct hpet *hpet; - - hpet = hpets->hp_hpet; - hpet_cycles_per_sec = hpet_time_div(hpets->hp_period); - hpet_interpolator.frequency = hpet_cycles_per_sec; - hpet_interpolator.drift = hpet_cycles_per_sec * - HPET_DRIFT / 1000000; - hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec; - register_time_interpolator(&hpet_interpolator); - } -#endif - return 0; - } else - return -ENODEV; + return 0; } static void __exit hpet_exit(void) { acpi_bus_unregister_driver(&hpet_acpi_driver); - if (hpets) + if (sysctl_header) unregister_sysctl_table(sysctl_header); + misc_deregister(&hpet_misc); return; } diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index d4bf205fd..9d7682c82 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -1,6 +1,11 @@ /* * Copyright (C) 2001 Anton Blanchard , IBM * Copyright (C) 2001 Paul Mackerras , IBM + * Copyright (C) 2004 Benjamin Herrenschmidt , IBM Corp. + * Copyright (C) 2004 IBM Corporation + * + * Additional Author(s): + * Ryan S. Arnold * * 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 @@ -17,38 +22,52 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include #include +#include +#include +#include +#include +#include #include -#include #include -#include #include #include #include #include -#include -#include #include -#include - -extern int hvc_count(int *); -extern int hvc_get_chars(int index, char *buf, int count); -extern int hvc_put_chars(int index, const char *buf, int count); +#include +#include +#include +#include #define HVC_MAJOR 229 #define HVC_MINOR 0 -#define MAX_NR_HVC_CONSOLES 4 +#define TIMEOUT (10) -#define TIMEOUT ((HZ + 99) / 100) +/* + * Wait this long per iteration while trying to push buffered data to the + * hypervisor before allowing the tty to complete a close operation. + */ +#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */ + +/* + * The Linux TTY code does not support dynamic addition of tty derived devices + * so we need to know how many tty devices we might need when space is allocated + * for the tty device. Since this driver supports hotplug of vty adapters we + * need to make sure we have enough allocated. + */ +#define HVC_ALLOC_TTY_ADAPTERS 8 static struct tty_driver *hvc_driver; -static int hvc_offset; #ifdef CONFIG_MAGIC_SYSRQ static int sysrq_pressed; #endif #define N_OUTBUF 16 +#define N_INBUF 16 #define __ALIGNED__ __attribute__((__aligned__(8))) @@ -60,59 +79,257 @@ struct hvc_struct { int do_wakeup; char outbuf[N_OUTBUF] __ALIGNED__; int n_outbuf; + uint32_t vtermno; + int irq_requested; + int irq; + struct list_head next; + struct kobject kobj; /* ref count & hvc_struct lifetime */ + struct vio_dev *vdev; }; -struct hvc_struct hvc_struct[MAX_NR_HVC_CONSOLES]; +/* dynamic list of hvc_struct instances */ +static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs); + +/* + * Protect the list of hvc_struct instances from inserts and removals during + * list traversal. + */ +static spinlock_t hvc_structs_lock = SPIN_LOCK_UNLOCKED; + +/* + * Initial console vtermnos for console API usage prior to full console + * initialization. Any vty adapter outside this range will not have usable + * console interfaces but can still be used as a tty device. This has to be + * static because kmalloc will not work during early console init. + */ +static uint32_t vtermnos[MAX_NR_HVC_CONSOLES]; + +/* Used for accounting purposes */ +static int num_vterms = 0; + +static struct task_struct *hvc_task; + +/* + * This value is used to associate a tty->index value to a hvc_struct based + * upon order of exposure via hvc_probe(). + */ +static int hvc_count = -1; + +/* Picks up late kicks after list walk but before schedule() */ +static int hvc_kicked; +/* Wake the sleeping khvcd */ +static void hvc_kick(void) +{ + hvc_kicked = 1; + wake_up_process(hvc_task); +} + +/* + * NOTE: This API isn't used if the console adapter doesn't support interrupts. + * In this case the console is poll driven. + */ +static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + hvc_kick(); + return IRQ_HANDLED; +} + +static void hvc_unthrottle(struct tty_struct *tty) +{ + hvc_kick(); +} + +/* + * Do not call this function with either the hvc_strucst_lock or the hvc_struct + * lock held. If successful, this function increments the kobject reference + * count against the target hvc_struct so it should be released when finished. + */ +struct hvc_struct *hvc_get_by_index(int index) +{ + struct hvc_struct *hp; + unsigned long flags; + + spin_lock(&hvc_structs_lock); + + list_for_each_entry(hp, &hvc_structs, next) { + spin_lock_irqsave(&hp->lock, flags); + if (hp->index == index) { + kobject_get(&hp->kobj); + spin_unlock_irqrestore(&hp->lock, flags); + spin_unlock(&hvc_structs_lock); + return hp; + } + spin_unlock_irqrestore(&hp->lock, flags); + } + hp = NULL; + + spin_unlock(&hvc_structs_lock); + return hp; +} + +/* + * The TTY interface won't be used until after the vio layer has exposed the vty + * adapter to the kernel. + */ static int hvc_open(struct tty_struct *tty, struct file * filp) { - int line = tty->index; struct hvc_struct *hp; unsigned long flags; + int irq = NO_IRQ; + int rc = 0; + struct kobject *kobjp; - if (line < 0 || line >= MAX_NR_HVC_CONSOLES) + /* Auto increments kobject reference if found. */ + if (!(hp = hvc_get_by_index(tty->index))) { + printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n"); return -ENODEV; - hp = &hvc_struct[line]; + } - tty->driver_data = hp; spin_lock_irqsave(&hp->lock, flags); + /* Check and then increment for fast path open. */ + if (hp->count++ > 0) { + spin_unlock_irqrestore(&hp->lock, flags); + hvc_kick(); + return 0; + } /* else count == 0 */ + + tty->driver_data = hp; hp->tty = tty; - hp->count++; + /* Save for request_irq outside of spin_lock. */ + irq = hp->irq; + if (irq != NO_IRQ) + hp->irq_requested = 1; + + kobjp = &hp->kobj; + spin_unlock_irqrestore(&hp->lock, flags); + /* check error, fallback to non-irq */ + if (irq != NO_IRQ) + rc = request_irq(irq, hvc_handle_interrupt, SA_INTERRUPT, "hvc_console", hp); + + /* + * If the request_irq() fails and we return an error. The tty layer + * will call hvc_close() after a failed open but we don't want to clean + * up there so we'll clean up here and clear out the previously set + * tty fields and return the kobject reference. + */ + if (rc) { + spin_lock_irqsave(&hp->lock, flags); + hp->tty = NULL; + hp->irq_requested = 0; + spin_unlock_irqrestore(&hp->lock, flags); + tty->driver_data = NULL; + kobject_put(kobjp); + printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); + } + /* Force wakeup of the polling thread */ + hvc_kick(); - return 0; + return rc; } static void hvc_close(struct tty_struct *tty, struct file * filp) { - struct hvc_struct *hp = tty->driver_data; + struct hvc_struct *hp; + struct kobject *kobjp; + int irq = NO_IRQ; unsigned long flags; if (tty_hung_up_p(filp)) return; + + /* + * No driver_data means that this close was issued after a failed + * hvc_open by the tty layer's release_dev() function and we can just + * exit cleanly because the kobject reference wasn't made. + */ + if (!tty->driver_data) + return; + + hp = tty->driver_data; spin_lock_irqsave(&hp->lock, flags); - if (--hp->count == 0) + + kobjp = &hp->kobj; + if (--hp->count == 0) { + if (hp->irq_requested) + irq = hp->irq; + hp->irq_requested = 0; + + /* We are done with the tty pointer now. */ hp->tty = NULL; - else if (hp->count < 0) - printk(KERN_ERR "hvc_close %lu: oops, count is %d\n", - hp - hvc_struct, hp->count); - spin_unlock_irqrestore(&hp->lock, flags); + spin_unlock_irqrestore(&hp->lock, flags); + + /* + * Chain calls chars_in_buffer() and returns immediately if + * there is no buffered data otherwise sleeps on a wait queue + * waking periodically to check chars_in_buffer(). + */ + tty_wait_until_sent(tty, HVC_CLOSE_WAIT); + + if (irq != NO_IRQ) + free_irq(irq, hp); + + } else { + if (hp->count < 0) + printk(KERN_ERR "hvc_close %X: oops, count is %d\n", + hp->vtermno, hp->count); + spin_unlock_irqrestore(&hp->lock, flags); + } + + kobject_put(kobjp); } static void hvc_hangup(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; + unsigned long flags; + int irq = NO_IRQ; + int temp_open_count; + struct kobject *kobjp; + + if (!hp) + return; + + spin_lock_irqsave(&hp->lock, flags); + + /* + * The N_TTY line discipline has problems such that in a close vs + * open->hangup case this can be called after the final close so prevent + * that from happening for now. + */ + if (hp->count <= 0) { + spin_unlock_irqrestore(&hp->lock, flags); + return; + } + kobjp = &hp->kobj; + temp_open_count = hp->count; hp->count = 0; + hp->n_outbuf = 0; hp->tty = NULL; + if (hp->irq_requested) + /* Saved for use outside of spin_lock. */ + irq = hp->irq; + hp->irq_requested = 0; + spin_unlock_irqrestore(&hp->lock, flags); + if (irq != NO_IRQ) + free_irq(irq, hp); + while(temp_open_count) { + --temp_open_count; + kobject_put(kobjp); + } } -/* called with hp->lock held */ +/* + * Push buffered characters whether they were just recently buffered or waiting + * on a blocked hypervisor. Call this function with hp->lock held. + */ static void hvc_push(struct hvc_struct *hp) { int n; - n = hvc_put_chars(hp->index + hvc_offset, hp->outbuf, hp->n_outbuf); + n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); if (n <= 0) { if (n == 0) return; @@ -127,77 +344,69 @@ static void hvc_push(struct hvc_struct *hp) hp->do_wakeup = 1; } -static int hvc_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static inline int __hvc_write_kernel(struct hvc_struct *hp, + const unsigned char *buf, int count) { - struct hvc_struct *hp = tty->driver_data; - char *tbuf, *p; - int tbsize, rsize, written = 0; unsigned long flags; + int rsize, written = 0; - if (from_user) { - tbsize = min(count, (int)PAGE_SIZE); - if (!(tbuf = kmalloc(tbsize, GFP_KERNEL))) - return -ENOMEM; - - while ((rsize = count - written) > 0) { - int wsize; - if (rsize > tbsize) - rsize = tbsize; - - p = tbuf; - rsize -= copy_from_user(p, buf, rsize); - if (!rsize) { - if (written == 0) - written = -EFAULT; - break; - } - buf += rsize; - written += rsize; - - spin_lock_irqsave(&hp->lock, flags); - for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize; - wsize = N_OUTBUF - hp->n_outbuf) { - if (wsize > rsize) - wsize = rsize; - memcpy(hp->outbuf + hp->n_outbuf, p, wsize); - hp->n_outbuf += wsize; - hvc_push(hp); - rsize -= wsize; - p += wsize; - } - spin_unlock_irqrestore(&hp->lock, flags); - - if (rsize) - break; + spin_lock_irqsave(&hp->lock, flags); - if (count < tbsize) - tbsize = count; - } + /* Push pending writes */ + if (hp->n_outbuf > 0) + hvc_push(hp); - kfree(tbuf); - } else { - spin_lock_irqsave(&hp->lock, flags); - while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) { - if (rsize > count) - rsize = count; - memcpy(hp->outbuf + hp->n_outbuf, buf, rsize); - count -= rsize; - buf += rsize; - hp->n_outbuf += rsize; - written += rsize; - hvc_push(hp); - } - spin_unlock_irqrestore(&hp->lock, flags); + while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) { + if (rsize > count) + rsize = count; + memcpy(hp->outbuf + hp->n_outbuf, buf, rsize); + count -= rsize; + buf += rsize; + hp->n_outbuf += rsize; + written += rsize; + hvc_push(hp); } + spin_unlock_irqrestore(&hp->lock, flags); + + return written; +} +static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + struct hvc_struct *hp = tty->driver_data; + int written; + + /* This write was probably executed during a tty close. */ + if (!hp) + return -EPIPE; + + if (hp->count <= 0) + return -EIO; + + written = __hvc_write_kernel(hp, buf, count); + + /* + * Racy, but harmless, kick thread if there is still pending data. + * There really is nothing wrong with kicking the thread, even if there + * is no buffered data. + */ + if (hp->n_outbuf) + hvc_kick(); return written; } +/* + * This is actually a contract between the driver and the tty layer outlining + * how much write room the driver can guarentee will be sent OR BUFFERED. This + * driver MUST honor the return value. + */ static int hvc_write_room(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; + if (!hp) + return -1; + return N_OUTBUF - hp->n_outbuf; } @@ -205,57 +414,108 @@ static int hvc_chars_in_buffer(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; + if (!hp) + return -1; return hp->n_outbuf; } -static void hvc_poll(int index) +#define HVC_POLL_READ 0x00000001 +#define HVC_POLL_WRITE 0x00000002 +#define HVC_POLL_QUICK 0x00000004 + +static int hvc_poll(struct hvc_struct *hp) { - struct hvc_struct *hp = &hvc_struct[index]; struct tty_struct *tty; - int i, n; - char buf[16] __ALIGNED__; + int i, n, poll_mask = 0; + char buf[N_INBUF] __ALIGNED__; unsigned long flags; + int read_total = 0; spin_lock_irqsave(&hp->lock, flags); + /* Push pending writes */ if (hp->n_outbuf > 0) hvc_push(hp); + /* Reschedule us if still some write pending */ + if (hp->n_outbuf > 0) + poll_mask |= HVC_POLL_WRITE; + /* No tty attached, just skip */ tty = hp->tty; - if (tty) { - for (;;) { - if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf)) - break; - n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf)); - if (n <= 0) - break; - for (i = 0; i < n; ++i) { -#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (buf[i] == '\x0f') { /* ^O -- should support a sequence */ - sysrq_pressed = 1; - continue; - } else if (sysrq_pressed) { - handle_sysrq(buf[i], NULL, tty); - sysrq_pressed = 0; - continue; - } -#endif - tty_insert_flip_char(tty, buf[i], 0); + if (tty == NULL) + goto bail; + + /* Now check if we can get data (are we throttled ?) */ + if (test_bit(TTY_THROTTLED, &tty->flags)) + goto throttled; + + /* If we aren't interrupt driven and aren't throttled, we always + * request a reschedule + */ + if (hp->irq == NO_IRQ) + poll_mask |= HVC_POLL_READ; + + /* Read data if any */ + for (;;) { + int count = N_INBUF; + if (count > (TTY_FLIPBUF_SIZE - tty->flip.count)) + count = TTY_FLIPBUF_SIZE - tty->flip.count; + + /* If flip is full, just reschedule a later read */ + if (count == 0) { + poll_mask |= HVC_POLL_READ; + break; + } + + n = hvc_get_chars(hp->vtermno, buf, count); + if (n <= 0) { + /* Hangup the tty when disconnected from host */ + if (n == -EPIPE) { + spin_unlock_irqrestore(&hp->lock, flags); + tty_hangup(tty); + spin_lock_irqsave(&hp->lock, flags); } + break; } + for (i = 0; i < n; ++i) { +#ifdef CONFIG_MAGIC_SYSRQ + /* Handle the SysRq Hack */ + if (buf[i] == '\x0f') { /* ^O -- should support a sequence */ + sysrq_pressed = 1; + continue; + } else if (sysrq_pressed) { + handle_sysrq(buf[i], NULL, tty); + sysrq_pressed = 0; + continue; + } +#endif /* CONFIG_MAGIC_SYSRQ */ + tty_insert_flip_char(tty, buf[i], 0); + } + if (tty->flip.count) tty_schedule_flip(tty); - if (hp->do_wakeup) { - hp->do_wakeup = 0; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + /* + * Account for the total amount read in one loop, and if above + * 64 bytes, we do a quick schedule loop to let the tty grok the + * data and eventually throttle us. + */ + read_total += n; + if (read_total >= 64) { + poll_mask |= HVC_POLL_QUICK; + break; } } - + throttled: + /* Wakeup write queue if necessary */ + if (hp->do_wakeup) { + hp->do_wakeup = 0; + tty_wakeup(tty); + } + bail: spin_unlock_irqrestore(&hp->lock, flags); + + return poll_mask; } #if defined(CONFIG_XMON) && defined(CONFIG_SMP) @@ -264,21 +524,47 @@ extern cpumask_t cpus_in_xmon; static const cpumask_t cpus_in_xmon = CPU_MASK_NONE; #endif - +/* + * This kthread is either polling or interrupt driven. This is determined by + * calling hvc_poll() who determines whether a console adapter support + * interrupts. + */ int khvcd(void *unused) { - int i; - - daemonize("khvcd"); + int poll_mask; + struct hvc_struct *hp; - for (;;) { + __set_current_state(TASK_RUNNING); + do { + poll_mask = 0; + hvc_kicked = 0; + wmb(); if (cpus_empty(cpus_in_xmon)) { - for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i) - hvc_poll(i); + spin_lock(&hvc_structs_lock); + list_for_each_entry(hp, &hvc_structs, next) { + /*hp = list_entry(node, struct hvc_struct, * next); */ + poll_mask |= hvc_poll(hp); + } + spin_unlock(&hvc_structs_lock); + } else + poll_mask |= HVC_POLL_READ; + if (hvc_kicked) + continue; + if (poll_mask & HVC_POLL_QUICK) { + yield(); + continue; } set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(TIMEOUT); - } + if (!hvc_kicked) { + if (poll_mask == 0) + schedule(); + else + msleep_interruptible(TIMEOUT); + } + __set_current_state(TASK_RUNNING); + } while (!kthread_should_stop()); + + return 0; } static struct tty_operations hvc_ops = { @@ -286,19 +572,124 @@ static struct tty_operations hvc_ops = { .close = hvc_close, .write = hvc_write, .hangup = hvc_hangup, + .unthrottle = hvc_unthrottle, .write_room = hvc_write_room, .chars_in_buffer = hvc_chars_in_buffer, }; -int __init hvc_init(void) +char hvc_driver_name[] = "hvc_console"; + +static struct vio_device_id hvc_driver_table[] __devinitdata= { + {"serial", "hvterm1"}, + { NULL, } +}; +MODULE_DEVICE_TABLE(vio, hvc_driver_table); + +/* callback when the kboject ref count reaches zero. */ +static void destroy_hvc_struct(struct kobject *kobj) { - int num = hvc_count(&hvc_offset); - int i; + struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj); + unsigned long flags; + + spin_lock(&hvc_structs_lock); + + spin_lock_irqsave(&hp->lock, flags); + list_del(&(hp->next)); + spin_unlock_irqrestore(&hp->lock, flags); + + spin_unlock(&hvc_structs_lock); + + kfree(hp); +} + +static struct kobj_type hvc_kobj_type = { + .release = destroy_hvc_struct, +}; + +static int __devinit hvc_probe( + struct vio_dev *dev, + const struct vio_device_id *id) +{ + struct hvc_struct *hp; + + /* probed with invalid parameters. */ + if (!dev || !id) + return -EPERM; + + hp = kmalloc(sizeof(*hp), GFP_KERNEL); + if (!hp) + return -ENOMEM; + + memset(hp, 0x00, sizeof(*hp)); + hp->vtermno = dev->unit_address; + hp->vdev = dev; + hp->vdev->dev.driver_data = hp; + hp->irq = dev->irq; + + kobject_init(&hp->kobj); + hp->kobj.ktype = &hvc_kobj_type; + + hp->lock = SPIN_LOCK_UNLOCKED; + spin_lock(&hvc_structs_lock); + hp->index = ++hvc_count; + list_add_tail(&(hp->next), &hvc_structs); + spin_unlock(&hvc_structs_lock); + + return 0; +} + +static int __devexit hvc_remove(struct vio_dev *dev) +{ + struct hvc_struct *hp = dev->dev.driver_data; + unsigned long flags; + struct kobject *kobjp; + struct tty_struct *tty; + + spin_lock_irqsave(&hp->lock, flags); + tty = hp->tty; + kobjp = &hp->kobj; + + if (hp->index < MAX_NR_HVC_CONSOLES) + vtermnos[hp->index] = -1; + + /* Don't whack hp->irq because tty_hangup() will need to free the irq. */ + + spin_unlock_irqrestore(&hp->lock, flags); + + /* + * We 'put' the instance that was grabbed when the kobject instance + * was intialized using kobject_init(). Let the last holder of this + * kobject cause it to be removed, which will probably be the tty_hangup + * below. + */ + kobject_put(kobjp); + + /* + * This function call will auto chain call hvc_hangup. The tty should + * always be valid at this time unless a simultaneous tty close already + * cleaned up the hvc_struct. + */ + if (tty) + tty_hangup(tty); + return 0; +} + +static struct vio_driver hvc_vio_driver = { + .name = hvc_driver_name, + .id_table = hvc_driver_table, + .probe = hvc_probe, + .remove = hvc_remove, +}; - if (num > MAX_NR_HVC_CONSOLES) - num = MAX_NR_HVC_CONSOLES; +/* Driver initialization. Follow console initialization. This is where the TTY + * interfaces start to become available. */ +int __init hvc_init(void) +{ + int rc; - hvc_driver = alloc_tty_driver(num); + /* We need more than num_vterms adapters due to hotplug additions. */ + hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); + /* hvc_driver = alloc_tty_driver(num_vterms); */ if (!hvc_driver) return -ENOMEM; @@ -312,31 +703,73 @@ int __init hvc_init(void) hvc_driver->init_termios = tty_std_termios; hvc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hvc_driver, &hvc_ops); - for (i = 0; i < num; i++) { - hvc_struct[i].lock = SPIN_LOCK_UNLOCKED; - hvc_struct[i].index = i; - } if (tty_register_driver(hvc_driver)) panic("Couldn't register hvc console driver\n"); - if (num > 0) - kernel_thread(khvcd, NULL, CLONE_KERNEL); + /* Always start the kthread because there can be hotplug vty adapters + * added later. */ + hvc_task = kthread_run(khvcd, NULL, "khvcd"); + if (IS_ERR(hvc_task)) { + panic("Couldn't create kthread for console.\n"); + put_tty_driver(hvc_driver); + return -EIO; + } - return 0; + /* Register as a vio device to receive callbacks */ + rc = vio_register_driver(&hvc_vio_driver); + + return rc; } +/* This isn't particularily necessary due to this being a console driver but it + * is nice to be thorough */ static void __exit hvc_exit(void) { + kthread_stop(hvc_task); + + vio_unregister_driver(&hvc_vio_driver); + tty_unregister_driver(hvc_driver); + /* return tty_struct instances allocated in hvc_init(). */ + put_tty_driver(hvc_driver); +} + +/* + * Console APIs, NOT TTY. These APIs are available immediately when + * hvc_console_setup() finds adapters. + */ + +/* + * hvc_instantiate() is an early console discovery method which locates consoles + * prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT + * get an hvc_instantiate() callback since the appear after early console init. + */ +int hvc_instantiate(uint32_t vtermno, int index) +{ + if (index < 0 || index >= MAX_NR_HVC_CONSOLES) + return -1; + + if (vtermnos[index] != -1) + return -1; + + vtermnos[index] = vtermno; + return 0; } void hvc_console_print(struct console *co, const char *b, unsigned count) { char c[16] __ALIGNED__; - unsigned i, n; + unsigned i = 0, n = 0; int r, donecr = 0; - i = n = 0; + /* Console access attempt outside of acceptable console range. */ + if (co->index >= MAX_NR_HVC_CONSOLES) + return; + + /* This console adapter was removed so it is not useable. */ + if (vtermnos[co->index] < 0) + return; + while (count > 0 || i > 0) { if (count > 0 && i < sizeof(c)) { if (b[n] == '\n' && !donecr) { @@ -348,7 +781,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count) --count; } } else { - r = hvc_put_chars(co->index + hvc_offset, c, i); + r = hvc_put_chars(vtermnos[co->index], c, i); if (r < 0) { /* throw away chars on error */ i = 0; @@ -369,9 +802,6 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index) static int __init hvc_console_setup(struct console *co, char *options) { - if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES - || co->index >= hvc_count(&hvc_offset)) - return -1; return 0; } @@ -384,8 +814,14 @@ struct console hvc_con_driver = { .index = -1, }; +/* Early console initialization. Preceeds driver initialization. */ static int __init hvc_console_init(void) { + int i; + + for (i=0; i /* - * 1.0.0 -> 1.1.0 Added kernel_thread scheduling methodology to driver to - * replace wait_task constructs. + * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00). + * Removed braces around single statements following conditionals. Removed '= + * 0' after static int declarations since these default to zero. Removed + * list_for_each_safe() and replaced with list_for_each_entry() in + * hvcs_get_by_index(). The 'safe' version is un-needed now that the driver is + * using spinlocks. Changed spin_lock_irqsave() to spin_lock() when locking + * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int + * handler. Initialized hvcs_structs_lock and hvcs_pi_lock to + * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init(). + * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the + * list traversals from a deletion. Removed '= NULL' from pointer declaration + * statements since they are initialized NULL by default. Removed wmb() + * instances from hvcs_try_write(). They probably aren't needed with locking in + * place. Added check and cleanup for hvcs_pi_buff = kmalloc() in + * hvcs_module_init(). Exposed hvcs_struct.index via a sysfs attribute so that + * the coupling between /dev/hvcs* and a vty-server can be automatically + * determined. Moved kobject_put() in hvcs_open outside of the + * spin_unlock_irqrestore(). * - * 1.1.0 -> 1.2.0 Moved pi_buff initialization out of arch code into driver code - * and added locking to share this buffer between hvcs_struct instances. This - * is because the page_size kmalloc can't be done with a spin_lock held. + * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it + * align with how the tty layer always assigns the lowest index available. This + * change resulted in a list of ints that denotes which indexes are available. + * Device additions and removals use the new hvcs_get_index() and + * hvcs_return_index() helper functions. The list is created with + * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list(). + * Without these fixes hotplug vty-server adapter support goes crazy with this + * driver if the user removes a vty-server adapter. Moved free_irq() outside of + * the hvcs_final_close() function in order to get it out of the spinlock. + * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping + * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from + * arch/ppc64/hvcserver.h. * - * Also added sysfs attribute to manually disconnect the vty-server from the vty - * due to stupid firmware behavior when opening the connection then sending data - * then then quickly closing the connection would cause data loss on the - * receiving side. This required some reordering of the termination code. - * - * Fixed the hangup scenario and fixed memory leaks on module_exit. - * - * 1.2.0 -> 1.3.0 Moved from manual kernel thread creation & execution to - * kthread construct which replaced in-kernel IPC for thread termination with - * kthread_stop and kthread_should_stop. Explicit wait_queue handling was - * removed because kthread handles this. Minor bug fix to postpone partner_info - * clearing on hvcs_close until adapter removal to preserve context data for - * printk on partner connection free. Added lock to protect hvcs_structs so - * that hvcs_struct instances aren't added or removed during list traversal. - * Cleaned up comment style, added spaces after commas, and broke function - * declaration lines to be under 80 columns. + * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to + * prevent possible lockup with realtime scheduling as similarily pointed out by + * akpm in hvc_console. Changed resulted in the removal of hvcs_final_close() + * to reorder cleanup operations and prevent discarding of pending data during + * an hvcs_close(). Removed spinlock protection of hvcs_struct data members in + * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed. */ -#define HVCS_DRIVER_VERSION "1.3.0" + +#define HVCS_DRIVER_VERSION "1.3.3" MODULE_AUTHOR("Ryan S. Arnold "); MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(HVCS_DRIVER_VERSION); +/* + * Wait this long per iteration while trying to push buffered data to the + * hypervisor before allowing the tty to complete a close operation. + */ +#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */ + /* * Since the Linux TTY code does not currently (2-04-2004) support dynamic * addition of tty derived devices and we shouldn't allocate thousands of @@ -138,9 +160,9 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); /* * We let Linux assign us a major number and we start the minors at zero. There - * is no intuitive mapping between minor number and the target partition. The - * mapping of minor number is related to the order the vty-servers are exposed - * to this driver via the hvcs_probe function. + * is no intuitive mapping between minor number and the target vty-server + * adapter except that each new vty-server adapter is always assigned to the + * smallest minor number available. */ #define HVCS_MINOR_START 0 @@ -152,9 +174,6 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); */ #define __ALIGNED__ __attribute__((__aligned__(8))) -/* Converged location code string length + 1 null terminator */ -#define CLC_LENGTH 80 - /* * How much data can firmware send with each hvc_put_chars()? Maybe this * should be moved into an architecture specific area. @@ -194,27 +213,41 @@ char hvcs_driver_string[] = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; /* Status of partner info rescan triggered via sysfs. */ -static int hvcs_rescan_status = 0; +static int hvcs_rescan_status; static struct tty_driver *hvcs_tty_driver; /* - * This is used to associate a vty-server, as it is exposed to this driver, with - * a preallocated tty_struct.index. The dev node and hvcs index numbers are not - * re-used after device removal otherwise removing and adding a new one would - * link a /dev/hvcs* entry to a different vty-server than it did before the - * removal. Incidentally, a newly exposed vty-server will always map to an - * incrementally higher /dev/hvcs* entry than the last exposed vty-server. + * In order to be somewhat sane this driver always associates the hvcs_struct + * index element with the numerically equal tty->index. This means that a + * hotplugged vty-server adapter will always map to the lowest index valued + * device node. If vty-servers were hotplug removed from the system and then + * new ones added the new vty-server may have the largest slot number of all + * the vty-server adapters in the partition but it may have the lowest dev node + * index of all the adapters due to the hole left by the hotplug removed + * adapter. There are a set of functions provided to get the lowest index for + * a new device as well as return the index to the list. This list is allocated + * with a number of elements equal to the number of device nodes requested when + * the module was inserted. + */ +static int *hvcs_index_list; + +/* + * How large is the list? This is kept for traversal since the list is + * dynamically created. */ -static int hvcs_struct_count = -1; +static int hvcs_index_count; /* * Used by the khvcsd to pick up I/O operations when the kernel_thread is * already awake but potentially shifted to TASK_INTERRUPTIBLE state. */ -static int hvcs_kicked = 0; +static int hvcs_kicked; -/* Used the the kthread construct for task operations */ +/* + * Use by the kthread construct for task operations like waking the sleeping + * thread and stopping the kthread. + */ static struct task_struct *hvcs_task; /* @@ -223,7 +256,8 @@ static struct task_struct *hvcs_task; */ static unsigned long *hvcs_pi_buff; -static spinlock_t hvcs_pi_lock; +/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */ +static spinlock_t hvcs_pi_lock = SPIN_LOCK_UNLOCKED; /* One vty-server per hvcs_struct */ struct hvcs_struct { @@ -263,9 +297,9 @@ struct hvcs_struct { */ struct kobject kobj; /* ref count & hvcs_struct lifetime */ int connected; /* is the vty-server currently connected to a vty? */ - unsigned int p_unit_address; /* partner unit address */ - unsigned int p_partition_ID; /* partner partition ID */ - char p_location_code[CLC_LENGTH]; + uint32_t p_unit_address; /* partner unit address */ + uint32_t p_partition_ID; /* partner partition ID */ + char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */ struct list_head next; /* list management */ struct vio_dev *vdev; }; @@ -274,14 +308,14 @@ struct hvcs_struct { #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj) static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); -static spinlock_t hvcs_structs_lock; +static spinlock_t hvcs_structs_lock = SPIN_LOCK_UNLOCKED; static void hvcs_unthrottle(struct tty_struct *tty); static void hvcs_throttle(struct tty_struct *tty); static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static int hvcs_write(struct tty_struct *tty, int from_user, +static int hvcs_write(struct tty_struct *tty, const unsigned char *buf, int count); static int hvcs_write_room(struct tty_struct *tty); static int hvcs_chars_in_buffer(struct tty_struct *tty); @@ -297,7 +331,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd); static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, unsigned int irq, struct vio_dev *dev); -static void hvcs_final_close(struct hvcs_struct *hvcsd); static void destroy_hvcs_struct(struct kobject *kobj); static int hvcs_open(struct tty_struct *tty, struct file *filp); @@ -357,12 +390,11 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct hvcs_struct *hvcsd = dev_instance; - unsigned long flags; - spin_lock_irqsave(&hvcsd->lock, flags); + spin_lock(&hvcsd->lock); vio_disable_interrupts(hvcsd->vdev); hvcsd->todo_mask |= HVCS_SCHED_READ; - spin_unlock_irqrestore(&hvcsd->lock, flags); + spin_unlock(&hvcsd->lock); hvcs_kick(); return IRQ_HANDLED; @@ -371,7 +403,7 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance, /* This function must be called with the hvcsd->lock held */ static void hvcs_try_write(struct hvcs_struct *hvcsd) { - unsigned int unit_address = hvcsd->vdev->unit_address; + uint32_t unit_address = hvcsd->vdev->unit_address; struct tty_struct *tty = hvcsd->tty; int sent; @@ -382,9 +414,9 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd) hvcsd->chars_in_buffer ); if (sent > 0) { hvcsd->chars_in_buffer = 0; - wmb(); + /* wmb(); */ hvcsd->todo_mask &= ~(HVCS_TRY_WRITE); - wmb(); + /* wmb(); */ /* * We are still obligated to deliver the data to the @@ -393,10 +425,7 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd) * a non-existent tty. */ if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } } @@ -404,11 +433,11 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd) static int hvcs_io(struct hvcs_struct *hvcsd) { - unsigned int unit_address; + uint32_t unit_address; struct tty_struct *tty; char buf[HVCS_BUFF_LEN] __ALIGNED__; unsigned long flags; - int got; + int got = 0; int i; spin_lock_irqsave(&hvcsd->lock, flags); @@ -461,11 +490,8 @@ static int hvcs_io(struct hvcs_struct *hvcsd) static int khvcsd(void *unused) { - struct hvcs_struct *hvcsd = NULL; - struct list_head *element; - struct list_head *safe_temp; + struct hvcs_struct *hvcsd; int hvcs_todo_mask; - unsigned long structs_flags; __set_current_state(TASK_RUNNING); @@ -474,12 +500,11 @@ static int khvcsd(void *unused) hvcs_kicked = 0; wmb(); - spin_lock_irqsave(&hvcs_structs_lock, structs_flags); - list_for_each_safe(element, safe_temp, &hvcs_structs) { - hvcsd = list_entry(element, struct hvcs_struct, next); - hvcs_todo_mask |= hvcs_io(hvcsd); + spin_lock(&hvcs_structs_lock); + list_for_each_entry(hvcsd, &hvcs_structs, next) { + hvcs_todo_mask |= hvcs_io(hvcsd); } - spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags); + spin_unlock(&hvcs_structs_lock); /* * If any of the hvcs adapters want to try a write or quick read @@ -502,10 +527,23 @@ static int khvcsd(void *unused) static struct vio_device_id hvcs_driver_table[] __devinitdata= { {"serial-server", "hvterm2"}, - { 0, } + { NULL, } }; MODULE_DEVICE_TABLE(vio, hvcs_driver_table); +static void hvcs_return_index(int index) +{ + /* Paranoia check */ + if (!hvcs_index_list) + return; + if (index < 0 || index >= hvcs_index_count) + return; + if (hvcs_index_list[index] == -1) + return; + else + hvcs_index_list[index] = -1; +} + /* callback when the kboject ref count reaches zero */ static void destroy_hvcs_struct(struct kobject *kobj) { @@ -513,6 +551,7 @@ static void destroy_hvcs_struct(struct kobject *kobj) struct vio_dev *vdev; unsigned long flags; + spin_lock(&hvcs_structs_lock); spin_lock_irqsave(&hvcsd->lock, flags); /* the list_del poisons the pointers */ @@ -524,7 +563,7 @@ static void destroy_hvcs_struct(struct kobject *kobj) " partner vty@%X:%d connection.\n", hvcsd->vdev->unit_address, hvcsd->p_unit_address, - (unsigned int)hvcsd->p_partition_ID); + (uint32_t)hvcsd->p_partition_ID); } printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n", hvcsd->vdev->unit_address); @@ -534,55 +573,60 @@ static void destroy_hvcs_struct(struct kobject *kobj) hvcsd->p_unit_address = 0; hvcsd->p_partition_ID = 0; - memset(&hvcsd->p_location_code[0], 0x00, CLC_LENGTH); + hvcs_return_index(hvcsd->index); + memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1); spin_unlock_irqrestore(&hvcsd->lock, flags); + spin_unlock(&hvcs_structs_lock); hvcs_remove_device_attrs(vdev); kfree(hvcsd); } -/* This function must be called with hvcsd->lock held. */ -static void hvcs_final_close(struct hvcs_struct *hvcsd) -{ - vio_disable_interrupts(hvcsd->vdev); - free_irq(hvcsd->vdev->irq, hvcsd); - - hvcsd->todo_mask = 0; - - /* These two may be redundant if the operation was a close. */ - if (hvcsd->tty) { - hvcsd->tty->driver_data = NULL; - hvcsd->tty = NULL; - } - - hvcsd->open_count = 0; - - memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); - hvcsd->chars_in_buffer = 0; -} - static struct kobj_type hvcs_kobj_type = { .release = destroy_hvcs_struct, }; +static int hvcs_get_index(void) +{ + int i; + /* Paranoia check */ + if (!hvcs_index_list) { + printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n"); + return -EFAULT; + } + /* Find the numerically lowest first free index. */ + for(i = 0; i < hvcs_index_count; i++) { + if (hvcs_index_list[i] == -1) { + hvcs_index_list[i] = 0; + return i; + } + } + return -1; +} + static int __devinit hvcs_probe( struct vio_dev *dev, const struct vio_device_id *id) { struct hvcs_struct *hvcsd; - unsigned long structs_flags; + int index; if (!dev || !id) { printk(KERN_ERR "HVCS: probed with invalid parameter.\n"); return -EPERM; } + /* early to avoid cleanup on failure */ + index = hvcs_get_index(); + if (index < 0) { + return -EFAULT; + } + hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL); - if (!hvcsd) { + if (!hvcsd) return -ENODEV; - } /* hvcsd->tty is zeroed out with the memset */ memset(hvcsd, 0x00, sizeof(*hvcsd)); @@ -596,7 +640,9 @@ static int __devinit hvcs_probe( hvcsd->vdev = dev; dev->dev.driver_data = hvcsd; - hvcsd->index = ++hvcs_struct_count; + hvcsd->index = index; + + /* hvcsd->index = ++hvcs_struct_count; */ hvcsd->chars_in_buffer = 0; hvcsd->todo_mask = 0; hvcsd->connected = 0; @@ -617,15 +663,15 @@ static int __devinit hvcs_probe( * will get -ENODEV. */ - spin_lock_irqsave(&hvcs_structs_lock, structs_flags); + spin_lock(&hvcs_structs_lock); list_add_tail(&(hvcsd->next), &hvcs_structs); - spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags); + spin_unlock(&hvcs_structs_lock); hvcs_create_device_attrs(hvcsd); - printk(KERN_INFO "HVCS: Added vty-server@%X.\n", dev->unit_address); + printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address); /* * DON'T enable interrupts here because there is no user to receive the @@ -688,8 +734,8 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) hvcsd->p_unit_address = pi->unit_address; hvcsd->p_partition_ID = pi->partition_ID; clclength = strlen(&pi->location_code[0]); - if (clclength > CLC_LENGTH - 1) - clclength = CLC_LENGTH - 1; + if (clclength > HVCS_CLC_LENGTH) + clclength = HVCS_CLC_LENGTH; /* copy the null-term char too */ strncpy(&hvcsd->p_location_code[0], @@ -711,20 +757,18 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) */ static int hvcs_get_pi(struct hvcs_struct *hvcsd) { - /* struct hvcs_partner_info *head_pi = NULL; */ - struct hvcs_partner_info *pi = NULL; - unsigned int unit_address = hvcsd->vdev->unit_address; + struct hvcs_partner_info *pi; + uint32_t unit_address = hvcsd->vdev->unit_address; struct list_head head; - unsigned long flags; int retval; - spin_lock_irqsave(&hvcs_pi_lock, flags); + spin_lock(&hvcs_pi_lock); if (!hvcs_pi_buff) { - spin_unlock_irqrestore(&hvcs_pi_lock, flags); + spin_unlock(&hvcs_pi_lock); return -EFAULT; } retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff); - spin_unlock_irqrestore(&hvcs_pi_lock, flags); + spin_unlock(&hvcs_pi_lock); if (retval) { printk(KERN_ERR "HVCS: Failed to fetch partner" " info for vty-server@%x.\n", unit_address); @@ -748,11 +792,10 @@ static int hvcs_get_pi(struct hvcs_struct *hvcsd) */ static int hvcs_rescan_devices_list(void) { - struct hvcs_struct *hvcsd = NULL; + struct hvcs_struct *hvcsd; unsigned long flags; - unsigned long structs_flags; - spin_lock_irqsave(&hvcs_structs_lock, structs_flags); + spin_lock(&hvcs_structs_lock); list_for_each_entry(hvcsd, &hvcs_structs, next) { spin_lock_irqsave(&hvcsd->lock, flags); @@ -760,7 +803,7 @@ static int hvcs_rescan_devices_list(void) spin_unlock_irqrestore(&hvcsd->lock, flags); } - spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags); + spin_unlock(&hvcs_structs_lock); return 0; } @@ -848,13 +891,14 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, unsigned int irq, struct vio_dev *vdev) { unsigned long flags; + int rc; /* * It is possible that the vty-server was removed between the time that * the conn was registered and now. */ - if (!request_irq(irq, &hvcs_handle_interrupt, - SA_INTERRUPT, "ibmhvcs", hvcsd)) { + if (!(rc = request_irq(irq, &hvcs_handle_interrupt, + SA_INTERRUPT, "ibmhvcs", hvcsd))) { /* * It is possible the vty-server was removed after the irq was * requested but before we have time to enable interrupts. @@ -874,7 +918,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, hvcs_partner_free(hvcsd); spin_unlock_irqrestore(&hvcsd->lock, flags); - return -ENODEV; + return rc; } @@ -888,22 +932,17 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, struct hvcs_struct *hvcs_get_by_index(int index) { struct hvcs_struct *hvcsd = NULL; - struct list_head *element; - struct list_head *safe_temp; unsigned long flags; - unsigned long structs_flags; - spin_lock_irqsave(&hvcs_structs_lock, structs_flags); + spin_lock(&hvcs_structs_lock); /* We can immediately discard OOB requests */ if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) { - list_for_each_safe(element, safe_temp, &hvcs_structs) { - hvcsd = list_entry(element, struct hvcs_struct, next); + list_for_each_entry(hvcsd, &hvcs_structs, next) { spin_lock_irqsave(&hvcsd->lock, flags); if (hvcsd->index == index) { kobject_get(&hvcsd->kobj); spin_unlock_irqrestore(&hvcsd->lock, flags); - spin_unlock_irqrestore(&hvcs_structs_lock, - structs_flags); + spin_unlock(&hvcs_structs_lock); return hvcsd; } spin_unlock_irqrestore(&hvcsd->lock, flags); @@ -911,7 +950,7 @@ struct hvcs_struct *hvcs_get_by_index(int index) hvcsd = NULL; } - spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags); + spin_unlock(&hvcs_structs_lock); return hvcsd; } @@ -921,12 +960,13 @@ struct hvcs_struct *hvcs_get_by_index(int index) */ static int hvcs_open(struct tty_struct *tty, struct file *filp) { - struct hvcs_struct *hvcsd = NULL; - int retval = 0; + struct hvcs_struct *hvcsd; + int rc, retval = 0; unsigned long flags; unsigned int irq; struct vio_dev *vdev; unsigned long unit_address; + struct kobject *kobjp; if (tty->driver_data) goto fast_open; @@ -936,7 +976,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) * This function increments the kobject index. */ if (!(hvcsd = hvcs_get_by_index(tty->index))) { - printk(KERN_WARNING "HVCS: open failed, no index.\n"); + printk(KERN_WARNING "HVCS: open failed, no device associated" + " with tty->index %d.\n", tty->index); return -ENODEV; } @@ -959,7 +1000,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) */ tty->low_latency = 1; - memset(&hvcsd->buffer[0], 0x3F, HVCS_BUFF_LEN); + memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); /* * Save these in the spinlock for the enable operations that need them @@ -974,12 +1015,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) /* * This must be done outside of the spinlock because it requests irqs - * and will grab the spinlcok and free the connection if it fails. + * and will grab the spinlock and free the connection if it fails. */ - if ((hvcs_enable_device(hvcsd, unit_address, irq, vdev))) { + if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) { kobject_put(&hvcsd->kobj); printk(KERN_WARNING "HVCS: enable device failed.\n"); - return -ENODEV; + return rc; } goto open_success; @@ -1002,16 +1043,17 @@ fast_open: open_success: hvcs_kick(); - printk(KERN_INFO "HVCS: vty-server@%X opened.\n", + printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n", hvcsd->vdev->unit_address ); return 0; error_release: + kobjp = &hvcsd->kobj; spin_unlock_irqrestore(&hvcsd->lock, flags); kobject_put(&hvcsd->kobj); - printk(KERN_WARNING "HVCS: HVCS partner connect failed.\n"); + printk(KERN_WARNING "HVCS: partner connect failed.\n"); return retval; } @@ -1020,6 +1062,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) struct hvcs_struct *hvcsd; unsigned long flags; struct kobject *kobjp; + int irq = NO_IRQ; /* * Is someone trying to close the file associated with this device after @@ -1039,14 +1082,10 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) hvcsd = tty->driver_data; spin_lock_irqsave(&hvcsd->lock, flags); + kobjp = &hvcsd->kobj; if (--hvcsd->open_count == 0) { - /* - * This line is important because it tells hvcs_open that this - * device needs to be re-configured the next time hvcs_open is - * called. - */ - hvcsd->tty->driver_data = NULL; + vio_disable_interrupts(hvcsd->vdev); /* * NULL this early so that the kernel_thread doesn't try to @@ -1055,34 +1094,28 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) */ hvcsd->tty = NULL; - /* - * Block the close until all the buffered data has been - * delivered. - */ - while(hvcsd->chars_in_buffer) { - spin_unlock_irqrestore(&hvcsd->lock, flags); + irq = hvcsd->vdev->irq; + spin_unlock_irqrestore(&hvcsd->lock, flags); - /* - * Give the kernel thread the hvcs_struct so that it can - * try to deliver the remaining data but block the close - * operation by spinning in this function so that other - * tty operations have to wait. - */ - yield(); - spin_lock_irqsave(&hvcsd->lock, flags); - } + tty_wait_until_sent(tty, HVCS_CLOSE_WAIT); - hvcs_final_close(hvcsd); + /* + * This line is important because it tells hvcs_open that this + * device needs to be re-configured the next time hvcs_open is + * called. + */ + tty->driver_data = NULL; + free_irq(irq, hvcsd); + kobject_put(kobjp); + return; } else if (hvcsd->open_count < 0) { printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" " is missmanaged.\n", - hvcsd->vdev->unit_address, hvcsd->open_count); + hvcsd->vdev->unit_address, hvcsd->open_count); } - kobjp = &hvcsd->kobj; spin_unlock_irqrestore(&hvcsd->lock, flags); - kobject_put(kobjp); } @@ -1092,6 +1125,7 @@ static void hvcs_hangup(struct tty_struct * tty) unsigned long flags; int temp_open_count; struct kobject *kobjp; + int irq = NO_IRQ; spin_lock_irqsave(&hvcsd->lock, flags); /* Preserve this so that we know how many kobject refs to put */ @@ -1101,15 +1135,31 @@ static void hvcs_hangup(struct tty_struct * tty) * Don't kobject put inside the spinlock because the destruction * callback may use the spinlock and it may get called before the * spinlock has been released. Get a pointer to the kobject and - * kobject_put on that instead. + * kobject_put on that after releasing the spinlock. */ kobjp = &hvcsd->kobj; - /* Calling this will drop any buffered data on the floor. */ - hvcs_final_close(hvcsd); + vio_disable_interrupts(hvcsd->vdev); + + hvcsd->todo_mask = 0; + + /* I don't think the tty needs the hvcs_struct pointer after a hangup */ + hvcsd->tty->driver_data = NULL; + hvcsd->tty = NULL; + + hvcsd->open_count = 0; + + /* This will drop any buffered data on the floor which is OK in a hangup + * scenario. */ + memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); + hvcsd->chars_in_buffer = 0; + + irq = hvcsd->vdev->irq; spin_unlock_irqrestore(&hvcsd->lock, flags); + free_irq(irq, hvcsd); + /* * We need to kobject_put() for every open_count we have since the * tty_hangup() function doesn't invoke a close per open connection on a @@ -1133,12 +1183,12 @@ static void hvcs_hangup(struct tty_struct * tty) * tty_hangup will allow hvcs_write time to complete execution before it * terminates our device. */ -static int hvcs_write(struct tty_struct *tty, int from_user, +static int hvcs_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvcs_struct *hvcsd = tty->driver_data; unsigned int unit_address; - unsigned char *charbuf; + const unsigned char *charbuf; unsigned long flags; int total_sent = 0; int tosend = 0; @@ -1158,21 +1208,7 @@ static int hvcs_write(struct tty_struct *tty, int from_user, count = HVCS_MAX_FROM_USER; } - if (!from_user) - charbuf = (unsigned char *)buf; - else { - charbuf = kmalloc(count, GFP_KERNEL); - if (!charbuf) { - printk(KERN_WARNING "HVCS: write -ENOMEM.\n"); - return -ENOMEM; - } - - if (copy_from_user(charbuf, buf, count)) { - kfree(charbuf); - printk(KERN_WARNING "HVCS: write -EFAULT.\n"); - return -EFAULT; - } - } + charbuf = buf; spin_lock_irqsave(&hvcsd->lock, flags); @@ -1184,8 +1220,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user, */ if (hvcsd->open_count <= 0) { spin_unlock_irqrestore(&hvcsd->lock, flags); - if (from_user) - kfree(charbuf); return -ENODEV; } @@ -1242,8 +1276,6 @@ static int hvcs_write(struct tty_struct *tty, int from_user, } spin_unlock_irqrestore(&hvcsd->lock, flags); - if (from_user) - kfree(charbuf); if (result == -1) return -EIO; @@ -1259,28 +1291,18 @@ static int hvcs_write(struct tty_struct *tty, int from_user, static int hvcs_write_room(struct tty_struct *tty) { struct hvcs_struct *hvcsd = tty->driver_data; - unsigned long flags; - int retval; if (!hvcsd || hvcsd->open_count <= 0) return 0; - spin_lock_irqsave(&hvcsd->lock, flags); - retval = HVCS_BUFF_LEN - hvcsd->chars_in_buffer; - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; + return HVCS_BUFF_LEN - hvcsd->chars_in_buffer; } static int hvcs_chars_in_buffer(struct tty_struct *tty) { struct hvcs_struct *hvcsd = tty->driver_data; - unsigned long flags; - int retval; - spin_lock_irqsave(&hvcsd->lock, flags); - retval = hvcsd->chars_in_buffer; - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; + return hvcsd->chars_in_buffer; } static struct tty_operations hvcs_ops = { @@ -1294,6 +1316,28 @@ static struct tty_operations hvcs_ops = { .throttle = hvcs_throttle, }; +static int hvcs_alloc_index_list(int n) +{ + int i; + hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL); + if (!hvcs_index_list) + return -ENOMEM; + hvcs_index_count = n; + for(i = 0; i < hvcs_index_count; i++) + hvcs_index_list[i] = -1; + return 0; +} + +static void hvcs_free_index_list(void) +{ + /* Paranoia check to be thorough. */ + if (hvcs_index_list) { + kfree(hvcs_index_list); + hvcs_index_list = NULL; + hvcs_index_count = 0; + } +} + static int __init hvcs_module_init(void) { int rc; @@ -1312,6 +1356,9 @@ static int __init hvcs_module_init(void) if (!hvcs_tty_driver) return -ENOMEM; + if (hvcs_alloc_index_list(num_ttys_to_alloc)) + return -ENOMEM; + hvcs_tty_driver->owner = THIS_MODULE; hvcs_tty_driver->driver_name = hvcs_driver_name; @@ -1342,19 +1389,25 @@ static int __init hvcs_module_init(void) if (tty_register_driver(hvcs_tty_driver)) { printk(KERN_ERR "HVCS: registration " " as a tty driver failed.\n"); + hvcs_free_index_list(); put_tty_driver(hvcs_tty_driver); - return rc; + return -EIO; } - hvcs_structs_lock = SPIN_LOCK_UNLOCKED; - - hvcs_pi_lock = SPIN_LOCK_UNLOCKED; hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!hvcs_pi_buff) { + tty_unregister_driver(hvcs_tty_driver); + hvcs_free_index_list(); + put_tty_driver(hvcs_tty_driver); + return -ENOMEM; + } hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); if (IS_ERR(hvcs_task)) { - printk("khvcsd creation failed. Driver not loaded.\n"); + printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); kfree(hvcs_pi_buff); + tty_unregister_driver(hvcs_tty_driver); + hvcs_free_index_list(); put_tty_driver(hvcs_tty_driver); return -EIO; } @@ -1374,8 +1427,6 @@ static int __init hvcs_module_init(void) static void __exit hvcs_module_exit(void) { - unsigned long flags; - /* * This driver receives hvcs_remove callbacks for each device upon * module removal. @@ -1387,10 +1438,10 @@ static void __exit hvcs_module_exit(void) */ kthread_stop(hvcs_task); - spin_lock_irqsave(&hvcs_pi_lock, flags); + spin_lock(&hvcs_pi_lock); kfree(hvcs_pi_buff); hvcs_pi_buff = NULL; - spin_unlock_irqrestore(&hvcs_pi_lock, flags); + spin_unlock(&hvcs_pi_lock); hvcs_remove_driver_attrs(); @@ -1398,6 +1449,8 @@ static void __exit hvcs_module_exit(void) tty_unregister_driver(hvcs_tty_driver); + hvcs_free_index_list(); + put_tty_driver(hvcs_tty_driver); printk(KERN_INFO "HVCS: driver module removed.\n"); @@ -1499,7 +1552,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf, " partner vty@%X:%d connection.\n", hvcsd->vdev->unit_address, hvcsd->p_unit_address, - (unsigned int)hvcsd->p_partition_ID); + (uint32_t)hvcsd->p_partition_ID); spin_unlock_irqrestore(&hvcsd->lock, flags); return count; @@ -1520,11 +1573,27 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf) static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, hvcs_vterm_state_show, hvcs_vterm_state_store); +static ssize_t hvcs_index_show(struct device *dev, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%d\n", hvcsd->index); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} + +static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL); + static struct attribute *hvcs_attrs[] = { &dev_attr_partner_vtys.attr, &dev_attr_partner_clcs.attr, &dev_attr_current_vty.attr, &dev_attr_vterm_state.attr, + &dev_attr_index.attr, NULL, }; diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 595079c07..35babe644 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -29,11 +29,6 @@ * the OS cannot change the speed of the port through this protocol. */ -/* TODO: - * test FSP reset - * add udbg support for xmon/kdb - */ - #undef DEBUG #include @@ -54,6 +49,7 @@ #include #include #include +#include #define HVSI_MAJOR 229 #define HVSI_MINOR 128 @@ -74,6 +70,7 @@ struct hvsi_struct { struct work_struct writer; + struct work_struct handshaker; wait_queue_head_t emptyq; /* woken when outbuf is emptied */ wait_queue_head_t stateq; /* woken when HVSI state changes */ spinlock_t lock; @@ -109,6 +106,7 @@ enum HVSI_PROTOCOL_STATE { HVSI_WAIT_FOR_VER_QUERY, HVSI_OPEN, HVSI_WAIT_FOR_MCTRL_RESPONSE, + HVSI_FSP_DIED, }; #define HVSI_CONSOLE 0x1 @@ -172,6 +170,13 @@ struct hvsi_query_response { } u; } __attribute__((packed)); + + +static inline int is_console(struct hvsi_struct *hp) +{ + return hp->flags & HVSI_CONSOLE; +} + static inline int is_open(struct hvsi_struct *hp) { /* if we're waiting for an mctrl then we're already open */ @@ -188,6 +193,7 @@ static inline void print_state(struct hvsi_struct *hp) "HVSI_WAIT_FOR_VER_QUERY", "HVSI_OPEN", "HVSI_WAIT_FOR_MCTRL_RESPONSE", + "HVSI_FSP_DIED", }; const char *name = state_names[hp->state]; @@ -296,14 +302,9 @@ static int hvsi_read(struct hvsi_struct *hp, char *buf, int count) return 0; } -/* - * we can't call tty_hangup() directly here because we need to call that - * outside of our lock - */ -static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp, - uint8_t *packet) +static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, + struct tty_struct **to_hangup, struct hvsi_struct **to_handshake) { - struct tty_struct *to_hangup = NULL; struct hvsi_control *header = (struct hvsi_control *)packet; switch (header->verb) { @@ -313,15 +314,14 @@ static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp, pr_debug("hvsi%i: CD dropped\n", hp->index); hp->mctrl &= TIOCM_CD; if (!(hp->tty->flags & CLOCAL)) - to_hangup = hp->tty; + *to_hangup = hp->tty; } break; case VSV_CLOSE_PROTOCOL: - printk(KERN_DEBUG - "hvsi%i: service processor closed connection!\n", hp->index); - __set_state(hp, HVSI_CLOSED); - to_hangup = hp->tty; - hp->tty = NULL; + pr_debug("hvsi%i: service processor came back\n", hp->index); + if (hp->state != HVSI_CLOSED) { + *to_handshake = hp; + } break; default: printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ", @@ -329,8 +329,6 @@ static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp, dump_packet(packet); break; } - - return to_hangup; } static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet) @@ -388,8 +386,8 @@ static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet) switch (hp->state) { case HVSI_WAIT_FOR_VER_QUERY: - __set_state(hp, HVSI_OPEN); hvsi_version_respond(hp, query->seqno); + __set_state(hp, HVSI_OPEN); break; default: printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index); @@ -467,17 +465,20 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp, * incoming data). */ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip, - struct tty_struct **hangup) + struct tty_struct **hangup, struct hvsi_struct **handshake) { uint8_t *packet = hp->inbuf; int chunklen; *flip = NULL; *hangup = NULL; + *handshake = NULL; chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ); - if (chunklen == 0) + if (chunklen == 0) { + pr_debug("%s: 0-length read\n", __FUNCTION__); return 0; + } pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen); dbg_dump_hex(hp->inbuf_end, chunklen); @@ -509,7 +510,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip, *flip = hvsi_recv_data(hp, packet); break; case VS_CONTROL_PACKET_HEADER: - *hangup = hvsi_recv_control(hp, packet); + hvsi_recv_control(hp, packet, hangup, handshake); break; case VS_QUERY_RESPONSE_PACKET_HEADER: hvsi_recv_response(hp, packet); @@ -526,8 +527,8 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip, packet += len_packet(packet); - if (*hangup) { - pr_debug("%s: hangup\n", __FUNCTION__); + if (*hangup || *handshake) { + pr_debug("%s: hangup or handshake\n", __FUNCTION__); /* * we need to send the hangup now before receiving any more data. * If we get "data, hangup, data", we can't deliver the second @@ -560,16 +561,15 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs) struct hvsi_struct *hp = (struct hvsi_struct *)arg; struct tty_struct *flip; struct tty_struct *hangup; + struct hvsi_struct *handshake; unsigned long flags; - irqreturn_t handled = IRQ_NONE; int again = 1; pr_debug("%s\n", __FUNCTION__); while (again) { spin_lock_irqsave(&hp->lock, flags); - again = hvsi_load_chunk(hp, &flip, &hangup); - handled = IRQ_HANDLED; + again = hvsi_load_chunk(hp, &flip, &hangup, &handshake); spin_unlock_irqrestore(&hp->lock, flags); /* @@ -587,6 +587,11 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs) if (hangup) { tty_hangup(hangup); } + + if (handshake) { + pr_debug("hvsi%i: attempting re-handshake\n", handshake->index); + schedule_work(&handshake->handshaker); + } } spin_lock_irqsave(&hp->lock, flags); @@ -603,7 +608,7 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs) tty_flip_buffer_push(flip); } - return handled; + return IRQ_HANDLED; } /* for boot console, before the irq handler is running */ @@ -757,6 +762,23 @@ static int hvsi_handshake(struct hvsi_struct *hp) return 0; } +static void hvsi_handshaker(void *arg) +{ + struct hvsi_struct *hp = (struct hvsi_struct *)arg; + + if (hvsi_handshake(hp) >= 0) + return; + + printk(KERN_ERR "hvsi%i: re-handshaking failed\n", hp->index); + if (is_console(hp)) { + /* + * ttys will re-attempt the handshake via hvsi_open, but + * the console will not. + */ + printk(KERN_ERR "hvsi%i: lost console!\n", hp->index); + } +} + static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count) { struct hvsi_data packet __ALIGNED__; @@ -808,6 +830,10 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) tty->driver_data = hp; tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */ + mb(); + if (hp->state == HVSI_FSP_DIED) + return -EIO; + spin_lock_irqsave(&hp->lock, flags); hp->tty = tty; hp->count++; @@ -815,7 +841,7 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE); spin_unlock_irqrestore(&hp->lock, flags); - if (hp->flags & HVSI_CONSOLE) + if (is_console(hp)) return 0; /* this has already been handshaked as the console */ ret = hvsi_handshake(hp); @@ -889,7 +915,7 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp) hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */ /* only close down connection if it is not the console */ - if (!(hp->flags & HVSI_CONSOLE)) { + if (!is_console(hp)) { h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */ __set_state(hp, HVSI_CLOSED); /* @@ -927,11 +953,17 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp) static void hvsi_hangup(struct tty_struct *tty) { struct hvsi_struct *hp = tty->driver_data; + unsigned long flags; pr_debug("%s\n", __FUNCTION__); + spin_lock_irqsave(&hp->lock, flags); + hp->count = 0; + hp->n_outbuf = 0; hp->tty = NULL; + + spin_unlock_irqrestore(&hp->lock, flags); } /* called with hp->lock held */ @@ -943,12 +975,13 @@ static void hvsi_push(struct hvsi_struct *hp) return; n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf); - if (n != 0) { - /* - * either all data was sent or there was an error, and we throw away - * data on error. - */ + if (n > 0) { + /* success */ + pr_debug("%s: wrote %i chars\n", __FUNCTION__, n); hp->n_outbuf = 0; + } else if (n == -EIO) { + __set_state(hp, HVSI_FSP_DIED); + printk(KERN_ERR "hvsi%i: service processor died\n", hp->index); } } @@ -966,6 +999,19 @@ static void hvsi_write_worker(void *arg) spin_lock_irqsave(&hp->lock, flags); + pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf); + + if (!is_open(hp)) { + /* + * We could have a non-open connection if the service processor died + * while we were busily scheduling ourselves. In that case, it could + * be minutes before the service processor comes back, so only try + * again once a second. + */ + schedule_delayed_work(&hp->writer, HZ); + goto out; + } + hvsi_push(hp); if (hp->n_outbuf > 0) schedule_delayed_work(&hp->writer, 10); @@ -982,6 +1028,7 @@ static void hvsi_write_worker(void *arg) wake_up_interruptible(&hp->tty->write_wait); } +out: spin_unlock_irqrestore(&hp->lock, flags); } @@ -999,29 +1046,19 @@ static int hvsi_chars_in_buffer(struct tty_struct *tty) return hp->n_outbuf; } -static int hvsi_write(struct tty_struct *tty, int from_user, +static int hvsi_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvsi_struct *hp = tty->driver_data; const char *source = buf; - char *kbuf = NULL; unsigned long flags; int total = 0; int origcount = count; - if (from_user) { - kbuf = kmalloc(count, GFP_KERNEL); - if (kbuf == NULL) - return -ENOMEM; - if (copy_from_user(kbuf, buf, count)) { - kfree(kbuf); - return -EFAULT; - } - source = kbuf; - } - spin_lock_irqsave(&hp->lock, flags); + pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf); + if (!is_open(hp)) { /* we're either closing or not yet open; don't accept data */ pr_debug("%s: not open\n", __FUNCTION__); @@ -1057,9 +1094,6 @@ static int hvsi_write(struct tty_struct *tty, int from_user, out: spin_unlock_irqrestore(&hp->lock, flags); - if (from_user) - kfree(kbuf); - if (total != origcount) pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount, total); @@ -1294,6 +1328,7 @@ static int __init hvsi_console_init(void) hp = &hvsi_ports[hvsi_count]; INIT_WORK(&hp->writer, hvsi_write_worker, hp); + INIT_WORK(&hp->handshaker, hvsi_handshaker, hp); init_waitqueue_head(&hp->emptyq); init_waitqueue_head(&hp->stateq); hp->lock = SPIN_LOCK_UNLOCKED; diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c index 090ce07a1..4131e993e 100644 --- a/drivers/char/hw_random.c +++ b/drivers/char/hw_random.c @@ -191,7 +191,7 @@ MODULE_DEVICE_TABLE (pci, rng_pci_tbl); #define INTEL_RNG_ADDR_LEN 3 /* token to our ioremap'd RNG register area */ -static void *rng_mem; +static void __iomem *rng_mem; static inline u8 intel_hwstatus (void) { @@ -581,7 +581,7 @@ static int __init rng_init (void) DPRINTK ("ENTER\n"); /* Probe for Intel, AMD RNGs */ - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { + for_each_pci_dev(pdev) { ent = pci_match_device (rng_pci_tbl, pdev); if (ent) { rng_ops = &rng_vendor_ops[ent->driver_data]; diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index ad4a96704..947a3c7f2 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -65,18 +65,20 @@ static char product_name [48] = "?"; static char bios_version [4] = "?"; static char serial_number[16] = "?"; -static int force = 0; -static int restricted = 0; -static int power_status = 0; - MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); MODULE_LICENSE("GPL"); -MODULE_PARM(force, "i"); -MODULE_PARM(restricted, "i"); -MODULE_PARM(power_status, "i"); + +static int force; +module_param(force, bool, 0); MODULE_PARM_DESC(force, "Force loading without checking for supported models"); + +static int restricted; +module_param(restricted, bool, 0); MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); + +static int power_status; +module_param(power_status, bool, 0600); MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *); diff --git a/drivers/char/ip2.c b/drivers/char/ip2.c index 8e62d6d3d..6cd12f23a 100644 --- a/drivers/char/ip2.c +++ b/drivers/char/ip2.c @@ -38,11 +38,11 @@ static int poll_only = 0; MODULE_AUTHOR("Doug McNash"); MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); -MODULE_PARM(irq,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); +module_param_array(irq, int, NULL, 0); MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); -MODULE_PARM(io,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); +module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); -MODULE_PARM(poll_only,"1i"); +module_param(poll_only, bool, 0); MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h index 8d2b37999..9d67b260b 100644 --- a/drivers/char/ip2/ip2types.h +++ b/drivers/char/ip2/ip2types.h @@ -49,6 +49,9 @@ typedef struct short irq[IP2_MAX_BOARDS]; unsigned short addr[IP2_MAX_BOARDS]; int type[IP2_MAX_BOARDS]; +#ifdef CONFIG_PCI + struct pci_dev *pci_dev[IP2_MAX_BOARDS]; +#endif } ip2config_t; #endif diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index ac97e617a..3d3ae6856 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -112,11 +112,11 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -440,6 +440,12 @@ cleanup_module(void) // free memory for (i = 0; i < IP2_MAX_BOARDS; i++) { void *pB; +#ifdef CONFIG_PCI + if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { + pci_disable_device(ip2config.pci_dev[i]); + ip2config.pci_dev[i] = NULL; + } +#endif if ((pB = i2BoardPtrTable[i]) != 0 ) { kfree ( pB ); i2BoardPtrTable[i] = NULL; @@ -594,9 +600,14 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); if (pci_dev_i != NULL) { unsigned int addr; - unsigned char pci_irq; + if (pci_enable_device(pci_dev_i)) { + printk( KERN_ERR "IP2: can't enable PCI device at %s\n", + pci_name(pci_dev_i)); + break; + } ip2config.type[i] = PCI; + ip2config.pci_dev[i] = pci_dev_i; status = pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); if ( addr & 1 ) { @@ -604,8 +615,6 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - status = - pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); // If the PCI BIOS assigned it, lets try and use it. If we // can't acquire it or it screws up, deal with it then. @@ -614,7 +623,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) // printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); // pci_irq = 0; // } - ip2config.irq[i] = pci_irq; + ip2config.irq[i] = pci_dev_i->irq; } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { @@ -1623,8 +1632,7 @@ ip2_close( PTTY tty, struct file *pFile ) if (pCh->wopen) { if (pCh->ClosingDelay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(pCh->ClosingDelay); + msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); } wake_up_interruptible(&pCh->open_wait); } diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index b632538ff..655a17219 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -57,4 +57,11 @@ config IPMI_WATCHDOG help This enables the IPMI watchdog timer. +config IPMI_POWEROFF + tristate 'IPMI Poweroff' + depends on IPMI_HANDLER + help + This enables a function to power off the system with IPMI if + the IPMI management controller is capable of this. + endmenu diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index b7d823072..553f0a408 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o obj-$(CONFIG_IPMI_SI) += ipmi_si.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o +obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o ipmi_si.o: $(ipmi_si-objs) $(LD) -r -o $@ $(ipmi_si-objs) diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 7295bc559..225b33011 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -31,7 +31,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_BT_VERSION "v32" +#define IPMI_BT_VERSION "v33" static int bt_debug = 0x00; /* Production value 0, see following flags */ diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 8d1a08bcc..49d67f538 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -45,7 +45,7 @@ #include #include -#define IPMI_DEVINTF_VERSION "v32" +#define IPMI_DEVINTF_VERSION "v33" struct ipmi_file_private { diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index d155f9a58..48cce2432 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -42,7 +42,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_KCS_VERSION "v32" +#define IPMI_KCS_VERSION "v33" /* Set this if you want a printout of why the state machine was hosed when it gets hosed. */ diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 83ae6f530..4191db290 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -46,7 +46,8 @@ #include #include -#define IPMI_MSGHANDLER_VERSION "v32" +#define PFX "IPMI message handler: " +#define IPMI_MSGHANDLER_VERSION "v33" struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); @@ -895,6 +896,12 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, return rv; } +void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) +{ + user->intf->handlers->set_run_to_completion(user->intf->send_info, + val); +} + static unsigned char ipmb_checksum(unsigned char *data, int size) { @@ -1686,8 +1693,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) intf->curr_channel = IPMI_MAX_CHANNELS; wake_up(&intf->waitq); - printk(KERN_WARNING "ipmi_msghandler: Error sending" - "channel information: %d\n", + printk(KERN_WARNING PFX + "Error sending channel information: %d\n", rv); } } @@ -2351,7 +2358,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, } else { /* There's too many things in the queue, discard this message. */ - printk(KERN_WARNING "ipmi: Event queue full, discarding an" + printk(KERN_WARNING PFX "Event queue full, discarding an" " incoming event\n"); } @@ -2433,10 +2440,34 @@ static int handle_new_recv_msg(ipmi_smi_t intf, #endif if (msg->rsp_size < 2) { /* Message is too small to be correct. */ - requeue = 0; - } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) - && (msg->rsp[1] == IPMI_SEND_MSG_CMD) - && (msg->user_data != NULL)) + printk(KERN_WARNING PFX "BMC returned to small a message" + " for netfn %x cmd %x, got %d bytes\n", + (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size); + + /* Generate an error response for the message. */ + msg->rsp[0] = msg->data[0] | (1 << 2); + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = IPMI_ERR_UNSPECIFIED; + msg->rsp_size = 3; + } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */ + || (msg->rsp[1] != msg->data[1])) /* Command */ + { + /* The response is not even marginally correct. */ + printk(KERN_WARNING PFX "BMC returned incorrect response," + " expected netfn %x cmd %x, got netfn %x cmd %x\n", + (msg->data[0] >> 2) | 1, msg->data[1], + msg->rsp[0] >> 2, msg->rsp[1]); + + /* Generate an error response for the message. */ + msg->rsp[0] = msg->data[0] | (1 << 2); + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = IPMI_ERR_UNSPECIFIED; + msg->rsp_size = 3; + } + + if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) + && (msg->rsp[1] == IPMI_SEND_MSG_CMD) + && (msg->user_data != NULL)) { /* It's a response to a response we sent. For this we deliver a send message response to the user. */ @@ -2502,7 +2533,9 @@ static int handle_new_recv_msg(ipmi_smi_t intf, requeue = 0; } - } else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) { + } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) + && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) + { /* It's an asyncronous event. */ requeue = handle_read_event_rsp(intf, msg); } else { @@ -3114,7 +3147,7 @@ static int ipmi_init_msghandler(void) proc_ipmi_root = proc_mkdir("ipmi", NULL); if (!proc_ipmi_root) { - printk("Unable to create IPMI proc dir"); + printk(KERN_ERR PFX "Unable to create IPMI proc dir"); return -ENOMEM; } @@ -3166,11 +3199,11 @@ static __exit void cleanup_ipmi(void) /* Check for buffer leaks. */ count = atomic_read(&smi_msg_inuse_count); if (count != 0) - printk("ipmi_msghandler: SMI message count %d at exit\n", + printk(KERN_WARNING PFX "SMI message count %d at exit\n", count); count = atomic_read(&recv_msg_inuse_count); if (count != 0) - printk("ipmi_msghandler: recv message count %d at exit\n", + printk(KERN_WARNING PFX "recv message count %d at exit\n", count); } module_exit(cleanup_ipmi); @@ -3207,3 +3240,4 @@ EXPORT_SYMBOL(ipmi_get_my_address); EXPORT_SYMBOL(ipmi_set_my_LUN); EXPORT_SYMBOL(ipmi_get_my_LUN); EXPORT_SYMBOL(ipmi_smi_add_proc_entry); +EXPORT_SYMBOL(ipmi_user_set_run_to_completion); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ea330f3ff..1d2eedcb5 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -76,7 +76,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) #include "ipmi_si_sm.h" #include -#define IPMI_SI_VERSION "v32" +#define IPMI_SI_VERSION "v33" /* Measure times between events in the driver. */ #undef DEBUG_TIMING @@ -146,6 +146,11 @@ struct smi_info /* The I/O port of an SI interface. */ int port; + /* The space between start addresses of the two ports. For + instance, if the first port is 0xca2 and the spacing is 4, then + the second port is 0xca6. */ + unsigned int spacing; + /* zero if no irq; */ int irq; @@ -452,14 +457,20 @@ static void handle_transaction_done(struct smi_info *smi_info) /* Take off the event flag. */ smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; + handle_flags(smi_info); } else { spin_lock(&smi_info->count_lock); smi_info->events++; spin_unlock(&smi_info->count_lock); + /* Do this before we deliver the message + because delivering the message releases the + lock and something else can mess with the + state. */ + handle_flags(smi_info); + deliver_recv_msg(smi_info, msg); } - handle_flags(smi_info); break; } @@ -482,14 +493,20 @@ static void handle_transaction_done(struct smi_info *smi_info) /* Take off the msg flag. */ smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL; + handle_flags(smi_info); } else { spin_lock(&smi_info->count_lock); smi_info->incoming_messages++; spin_unlock(&smi_info->count_lock); + /* Do this before we deliver the message + because delivering the message releases the + lock and something else can mess with the + state. */ + handle_flags(smi_info); + deliver_recv_msg(smi_info, msg); } - handle_flags(smi_info); break; } @@ -568,6 +585,9 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, smi_info->hosed_count++; spin_unlock(&smi_info->count_lock); + /* Do the before return_hosed_msg, because that + releases the lock. */ + smi_info->si_state = SI_NORMAL; if (smi_info->curr_msg != NULL) { /* If we were handling a user message, format a response to send to the upper layer to @@ -575,7 +595,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, return_hosed_msg(smi_info); } si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); - smi_info->si_state = SI_NORMAL; } /* We prefer handling attn over new messages. */ @@ -872,9 +891,10 @@ static struct smi_info *smi_infos[SI_MAX_DRIVERS] = #define DEVICE_NAME "ipmi_si" -#define DEFAULT_KCS_IO_PORT 0xca2 -#define DEFAULT_SMIC_IO_PORT 0xca9 -#define DEFAULT_BT_IO_PORT 0xe4 +#define DEFAULT_KCS_IO_PORT 0xca2 +#define DEFAULT_SMIC_IO_PORT 0xca9 +#define DEFAULT_BT_IO_PORT 0xe4 +#define DEFAULT_REGSPACING 1 static int si_trydefaults = 1; static char *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL }; @@ -886,6 +906,12 @@ static unsigned int ports[SI_MAX_PARMS] = { 0, 0, 0, 0 }; static int num_ports = 0; static int irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 }; static int num_irqs = 0; +static int regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 }; +static int num_regspacings = 0; +static int regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 }; +static int num_regsizes = 0; +static int regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 }; +static int num_regshifts = 0; module_param_named(trydefaults, si_trydefaults, bool, 0); @@ -897,21 +923,38 @@ MODULE_PARM_DESC(type, "Defines the type of each interface, each" " interface separated by commas. The types are 'kcs'," " 'smic', and 'bt'. For example si_type=kcs,bt will set" " the first interface to kcs and the second to bt"); -module_param_array(addrs, long, num_addrs, 0); +module_param_array(addrs, long, &num_addrs, 0); MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the" " addresses separated by commas. Only use if an interface" " is in memory. Otherwise, set it to zero or leave" " it blank."); -module_param_array(ports, int, num_ports, 0); +module_param_array(ports, int, &num_ports, 0); MODULE_PARM_DESC(ports, "Sets the port address of each interface, the" " addresses separated by commas. Only use if an interface" " is a port. Otherwise, set it to zero or leave" " it blank."); -module_param_array(irqs, int, num_irqs, 0); +module_param_array(irqs, int, &num_irqs, 0); MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the" " addresses separated by commas. Only use if an interface" " has an interrupt. Otherwise, set it to zero or leave" " it blank."); +module_param_array(regspacings, int, &num_regspacings, 0); +MODULE_PARM_DESC(regspacings, "The number of bytes between the start address" + " and each successive register used by the interface. For" + " instance, if the start address is 0xca2 and the spacing" + " is 2, then the second address is at 0xca4. Defaults" + " to 1."); +module_param_array(regsizes, int, &num_regsizes, 0); +MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes." + " This should generally be 1, 2, 4, or 8 for an 8-bit," + " 16-bit, 32-bit, or 64-bit register. Use this if you" + " the 8-bit IPMI register has to be read from a larger" + " register."); +module_param_array(regshifts, int, &num_regshifts, 0); +MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the." + " IPMI register, in bits. For instance, if the data" + " is read from a 32-bit word and the IPMI data is in" + " bit 8-15, then the shift would be 8"); #define IPMI_MEM_ADDR_SPACE 1 #define IPMI_IO_ADDR_SPACE 2 @@ -977,7 +1020,7 @@ static unsigned char port_inb(struct si_sm_io *io, unsigned int offset) { unsigned int *addr = io->info; - return inb((*addr)+offset); + return inb((*addr)+(offset*io->regspacing)); } static void port_outb(struct si_sm_io *io, unsigned int offset, @@ -985,30 +1028,97 @@ static void port_outb(struct si_sm_io *io, unsigned int offset, { unsigned int *addr = io->info; - outb(b, (*addr)+offset); + outb(b, (*addr)+(offset * io->regspacing)); } -static int port_setup(struct smi_info *info) +static unsigned char port_inw(struct si_sm_io *io, unsigned int offset) { - unsigned int *addr = info->io.info; + unsigned int *addr = io->info; - if (!addr || (!*addr)) - return -ENODEV; + return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; +} - if (request_region(*addr, info->io_size, DEVICE_NAME) == NULL) - return -EIO; - return 0; +static void port_outw(struct si_sm_io *io, unsigned int offset, + unsigned char b) +{ + unsigned int *addr = io->info; + + outw(b << io->regshift, (*addr)+(offset * io->regspacing)); +} + +static unsigned char port_inl(struct si_sm_io *io, unsigned int offset) +{ + unsigned int *addr = io->info; + + return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; +} + +static void port_outl(struct si_sm_io *io, unsigned int offset, + unsigned char b) +{ + unsigned int *addr = io->info; + + outl(b << io->regshift, (*addr)+(offset * io->regspacing)); } static void port_cleanup(struct smi_info *info) { unsigned int *addr = info->io.info; + int mapsize; - if (addr && (*addr)) - release_region (*addr, info->io_size); + if (addr && (*addr)) { + mapsize = ((info->io_size * info->io.regspacing) + - (info->io.regspacing - info->io.regsize)); + + release_region (*addr, mapsize); + } kfree(info); } +static int port_setup(struct smi_info *info) +{ + unsigned int *addr = info->io.info; + int mapsize; + + if (!addr || (!*addr)) + return -ENODEV; + + info->io_cleanup = port_cleanup; + + /* Figure out the actual inb/inw/inl/etc routine to use based + upon the register size. */ + switch (info->io.regsize) { + case 1: + info->io.inputb = port_inb; + info->io.outputb = port_outb; + break; + case 2: + info->io.inputb = port_inw; + info->io.outputb = port_outw; + break; + case 4: + info->io.inputb = port_inl; + info->io.outputb = port_outl; + break; + default: + printk("ipmi_si: Invalid register size: %d\n", + info->io.regsize); + return -EINVAL; + } + + /* Calculate the total amount of memory to claim. This is an + * unusual looking calculation, but it avoids claiming any + * more memory than it has to. It will claim everything + * between the first address to the end of the last full + * register. */ + mapsize = ((info->io_size * info->io.regspacing) + - (info->io.regspacing - info->io.regsize)); + + if (request_region(*addr, mapsize, DEVICE_NAME) == NULL) + return -EIO; + return 0; +} + static int try_init_port(int intf_num, struct smi_info **new_info) { struct smi_info *info; @@ -1028,11 +1138,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info) memset(info, 0, sizeof(*info)); info->io_setup = port_setup; - info->io_cleanup = port_cleanup; - info->io.inputb = port_inb; - info->io.outputb = port_outb; info->io.info = &(ports[intf_num]); info->io.addr = NULL; + info->io.regspacing = regspacings[intf_num]; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = regsizes[intf_num]; + if (!info->io.regsize) + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshifts[intf_num]; info->irq = 0; info->irq_setup = NULL; *new_info = info; @@ -1047,44 +1161,125 @@ static int try_init_port(int intf_num, struct smi_info **new_info) static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset) { - return readb((io->addr)+offset); + return readb((io->addr)+(offset * io->regspacing)); } static void mem_outb(struct si_sm_io *io, unsigned int offset, unsigned char b) { - writeb(b, (io->addr)+offset); + writeb(b, (io->addr)+(offset * io->regspacing)); } -static int mem_setup(struct smi_info *info) +static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset) { - unsigned long *addr = info->io.info; + return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) + && 0xff; +} - if (!addr || (!*addr)) - return -ENODEV; +static void mem_outw(struct si_sm_io *io, unsigned int offset, + unsigned char b) +{ + writeb(b << io->regshift, (io->addr)+(offset * io->regspacing)); +} - if (request_mem_region(*addr, info->io_size, DEVICE_NAME) == NULL) - return -EIO; +static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset) +{ + return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) + && 0xff; +} - info->io.addr = ioremap(*addr, info->io_size); - if (info->io.addr == NULL) { - release_mem_region(*addr, info->io_size); - return -EIO; - } - return 0; +static void mem_outl(struct si_sm_io *io, unsigned int offset, + unsigned char b) +{ + writel(b << io->regshift, (io->addr)+(offset * io->regspacing)); +} + +#ifdef readq +static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset) +{ + return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift) + && 0xff; +} + +static void mem_outq(struct si_sm_io *io, unsigned int offset, + unsigned char b) +{ + writeq(b << io->regshift, (io->addr)+(offset * io->regspacing)); } +#endif static void mem_cleanup(struct smi_info *info) { unsigned long *addr = info->io.info; + int mapsize; if (info->io.addr) { iounmap(info->io.addr); - release_mem_region(*addr, info->io_size); + + mapsize = ((info->io_size * info->io.regspacing) + - (info->io.regspacing - info->io.regsize)); + + release_mem_region(*addr, mapsize); } kfree(info); } +static int mem_setup(struct smi_info *info) +{ + unsigned long *addr = info->io.info; + int mapsize; + + if (!addr || (!*addr)) + return -ENODEV; + + info->io_cleanup = mem_cleanup; + + /* Figure out the actual readb/readw/readl/etc routine to use based + upon the register size. */ + switch (info->io.regsize) { + case 1: + info->io.inputb = mem_inb; + info->io.outputb = mem_outb; + break; + case 2: + info->io.inputb = mem_inw; + info->io.outputb = mem_outw; + break; + case 4: + info->io.inputb = mem_inl; + info->io.outputb = mem_outl; + break; +#ifdef readq + case 8: + info->io.inputb = mem_inq; + info->io.outputb = mem_outq; + break; +#endif + default: + printk("ipmi_si: Invalid register size: %d\n", + info->io.regsize); + return -EINVAL; + } + + /* Calculate the total amount of memory to claim. This is an + * unusual looking calculation, but it avoids claiming any + * more memory than it has to. It will claim everything + * between the first address to the end of the last full + * register. */ + mapsize = ((info->io_size * info->io.regspacing) + - (info->io.regspacing - info->io.regsize)); + + if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL) + return -EIO; + + info->io.addr = ioremap(*addr, mapsize); + if (info->io.addr == NULL) { + release_mem_region(*addr, mapsize); + return -EIO; + } + return 0; +} + static int try_init_mem(int intf_num, struct smi_info **new_info) { struct smi_info *info; @@ -1104,11 +1299,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) memset(info, 0, sizeof(*info)); info->io_setup = mem_setup; - info->io_cleanup = mem_cleanup; - info->io.inputb = mem_inb; - info->io.outputb = mem_outb; info->io.info = (void *) addrs[intf_num]; info->io.addr = NULL; + info->io.regspacing = regspacings[intf_num]; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = regsizes[intf_num]; + if (!info->io.regsize) + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshifts[intf_num]; info->irq = 0; info->irq_setup = NULL; *new_info = info; @@ -1132,7 +1331,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) static int acpi_failure = 0; /* For GPE-type interrupts. */ -void ipmi_acpi_gpe(void *context) +u32 ipmi_acpi_gpe(void *context) { struct smi_info *smi_info = context; unsigned long flags; @@ -1156,6 +1355,8 @@ void ipmi_acpi_gpe(void *context) smi_event_handler(smi_info, 0); out: spin_unlock_irqrestore(&(smi_info->si_lock), flags); + + return ACPI_INTERRUPT_HANDLED; } static int acpi_gpe_irq_setup(struct smi_info *info) @@ -1169,7 +1370,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) status = acpi_install_gpe_handler(NULL, info->irq, ACPI_GPE_LEVEL_TRIGGERED, - ipmi_acpi_gpe, + &ipmi_acpi_gpe, info); if (status != AE_OK) { printk(KERN_WARNING @@ -1182,7 +1383,6 @@ static int acpi_gpe_irq_setup(struct smi_info *info) printk(" Using ACPI GPE %d\n", info->irq); return 0; } - } static void acpi_gpe_irq_cleanup(struct smi_info *info) @@ -1190,7 +1390,7 @@ static void acpi_gpe_irq_cleanup(struct smi_info *info) if (!info->irq) return; - acpi_remove_gpe_handler(NULL, info->irq, ipmi_acpi_gpe); + acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); } /* @@ -1310,21 +1510,22 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) info->irq_setup = NULL; } + regspacings[intf_num] = spmi->addr.register_bit_width / 8; + info->io.regspacing = spmi->addr.register_bit_width / 8; + regsizes[intf_num] = regspacings[intf_num]; + info->io.regsize = regsizes[intf_num]; + regshifts[intf_num] = spmi->addr.register_bit_offset; + info->io.regshift = regshifts[intf_num]; + if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { io_type = "memory"; info->io_setup = mem_setup; - info->io_cleanup = mem_cleanup; addrs[intf_num] = spmi->addr.address; - info->io.inputb = mem_inb; - info->io.outputb = mem_outb; info->io.info = &(addrs[intf_num]); } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { io_type = "I/O"; info->io_setup = port_setup; - info->io_cleanup = port_cleanup; ports[intf_num] = spmi->addr.address; - info->io.inputb = port_inb; - info->io.outputb = port_outb; info->io.info = &(ports[intf_num]); } else { kfree(info); @@ -1348,6 +1549,7 @@ typedef struct dmi_ipmi_data u8 addr_space; unsigned long base_addr; u8 irq; + u8 offset; }dmi_ipmi_data_t; typedef struct dmi_header @@ -1361,6 +1563,7 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data) { u8 *data = (u8 *)dm; unsigned long base_addr; + u8 reg_spacing; ipmi_data->type = data[0x04]; @@ -1375,7 +1578,27 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data) ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; } - ipmi_data->base_addr = base_addr; + /* The top two bits of byte 0x10 hold the register spacing. */ + reg_spacing = (data[0x10] & 0xC0) >> 6; + switch(reg_spacing){ + case 0x00: /* Byte boundaries */ + ipmi_data->offset = 1; + break; + case 0x01: /* 32-bit boundaries */ + ipmi_data->offset = 4; + break; + case 0x02: /* 16-bit boundaries */ + ipmi_data->offset = 2; + default: + printk("ipmi_si: Unknown SMBIOS IPMI Base Addr" + " Modifier: 0x%x\n", reg_spacing); + return -EIO; + } + + /* If bit 4 of byte 0x10 is set, then the lsb for the address + is odd. */ + ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); + ipmi_data->irq = data[0x11]; if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) @@ -1500,18 +1723,12 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) if (ipmi_data.addr_space == 1) { io_type = "memory"; info->io_setup = mem_setup; - info->io_cleanup = mem_cleanup; addrs[intf_num] = ipmi_data.base_addr; - info->io.inputb = mem_inb; - info->io.outputb = mem_outb; info->io.info = &(addrs[intf_num]); } else if (ipmi_data.addr_space == 2) { io_type = "I/O"; info->io_setup = port_setup; - info->io_cleanup = port_cleanup; ports[intf_num] = ipmi_data.base_addr; - info->io.inputb = port_inb; - info->io.outputb = port_outb; info->io.info = &(ports[intf_num]); } else { kfree(info); @@ -1519,6 +1736,13 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) return -EIO; } + regspacings[intf_num] = ipmi_data.offset; + info->io.regspacing = regspacings[intf_num]; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshifts[intf_num]; + irqs[intf_num] = ipmi_data.irq; *new_info = info; @@ -1553,10 +1777,10 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) pci_smic_checked = 1; - if ((pci_dev = pci_find_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, + if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL))) ; - else if ((pci_dev = pci_find_class(PCI_ERMC_CLASSCODE, NULL)) && + else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) fe_rmc = 1; else @@ -1565,6 +1789,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); if (error) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: pci_read_config_word() failed (%d).\n", error); @@ -1574,6 +1799,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ if (!(base_addr & 0x0001)) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: memory mapped I/O not supported for PCI" " smic.\n"); @@ -1585,22 +1811,27 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) /* Data register starts at base address + 1 in eRMC */ ++base_addr; - if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) - return -ENODEV; + if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { + pci_dev_put(pci_dev); + return -ENODEV; + } info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); return -ENOMEM; } memset(info, 0, sizeof(*info)); info->io_setup = port_setup; - info->io_cleanup = port_cleanup; ports[intf_num] = base_addr; - info->io.inputb = port_inb; - info->io.outputb = port_outb; info->io.info = &(ports[intf_num]); + info->io.regspacing = regspacings[intf_num]; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshifts[intf_num]; *new_info = info; @@ -1610,6 +1841,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n", (long unsigned int) base_addr); + pci_dev_put(pci_dev); return 0; } #endif /* CONFIG_PCI */ @@ -1860,6 +2092,13 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->timer_stopped = 0; new_smi->stop_operation = 0; + /* Start clearing the flags before we enable interrupts or the + timer to avoid racing with the timer. */ + start_clear_flags(new_smi); + /* IRQ is defined to be set when non-zero. */ + if (new_smi->irq) + new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; + /* The ipmi_register_smi() code does some operations to determine the channel information, so we must be ready to handle operations before it is called. This means we have @@ -1903,12 +2142,6 @@ static int init_one_smi(int intf_num, struct smi_info **smi) goto out_err_stop_timer; } - start_clear_flags(new_smi); - - /* IRQ is defined to be set when non-zero. */ - if (new_smi->irq) - new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; - *smi = new_smi; printk(" IPMI %s interface initialized\n", si_type[intf_num]); @@ -2052,6 +2285,14 @@ void __exit cleanup_one_si(struct smi_info *to_clean) schedule_timeout(1); } + /* Interrupts and timeouts are stopped, now make sure the + interface is in a clean state. */ + while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { + poll(to_clean); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + rv = ipmi_unregister_smi(to_clean->intf); if (rv) { printk(KERN_ERR diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h index f3506552c..a0212b004 100644 --- a/drivers/char/ipmi/ipmi_si_sm.h +++ b/drivers/char/ipmi/ipmi_si_sm.h @@ -52,6 +52,9 @@ struct si_sm_io state machine shouldn't touch these. */ void *info; void *addr; + int regspacing; + int regsize; + int regshift; }; /* Results of SMI events. */ diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index b5c08d6e0..ae18747e6 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c @@ -46,7 +46,7 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -#define IPMI_SMIC_VERSION "v32" +#define IPMI_SMIC_VERSION "v33" /* smic_debug is a bit-field * SMIC_DEBUG_ENABLE - turned on for now diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index fb8492490..db2cf9cb5 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -51,7 +51,9 @@ #include #endif -#define IPMI_WATCHDOG_VERSION "v32" +#define PFX "IPMI Watchdog: " + +#define IPMI_WATCHDOG_VERSION "v33" /* * The IPMI command/response information for the watchdog timer. @@ -160,6 +162,7 @@ static char data_to_read = 0; static DECLARE_WAIT_QUEUE_HEAD(read_q); static struct fasync_struct *fasync_q = NULL; static char pretimeout_since_last_heartbeat = 0; +static char expect_close; /* If true, the driver will start running as soon as it is configured and ready. */ @@ -191,7 +194,7 @@ static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; static int ipmi_ignore_heartbeat = 0; /* Is someone using the watchdog? Only one user is allowed. */ -static int ipmi_wdog_open = 0; +static unsigned long ipmi_wdog_open = 0; /* If set to 1, the heartbeat command will set the state to reset and start the timer. The timer doesn't normally run when the driver is @@ -287,7 +290,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, recv_msg, 1); if (rv) { - printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n", + printk(KERN_WARNING PFX "set timeout error: %d\n", rv); } @@ -464,7 +467,7 @@ static int ipmi_heartbeat(void) 1); if (rv) { up(&heartbeat_lock); - printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n", + printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } @@ -599,6 +602,21 @@ static ssize_t ipmi_write(struct file *file, int rv; if (len) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } rv = ipmi_heartbeat(); if (rv) return rv; @@ -662,11 +680,9 @@ static int ipmi_open(struct inode *ino, struct file *filep) switch (iminor(ino)) { case WATCHDOG_MINOR: - if (ipmi_wdog_open) + if(test_and_set_bit(0, &ipmi_wdog_open)) return -EBUSY; - ipmi_wdog_open = 1; - /* Don't start the timer now, let it start on the first heartbeat. */ ipmi_start_timer_on_heartbeat = 1; @@ -704,14 +720,18 @@ static int ipmi_close(struct inode *ino, struct file *filep) { if (iminor(ino)==WATCHDOG_MINOR) { - if (!nowayout) { + if (expect_close == 42) { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + clear_bit(0, &ipmi_wdog_open); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + ipmi_heartbeat(); } - ipmi_wdog_open = 0; } ipmi_fasync (-1, filep, 0); + expect_close = 0; return 0; } @@ -739,7 +759,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, void *handler_data) { if (msg->msg.data[0] != 0) { - printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n", + printk(KERN_ERR PFX "response: Error %x on cmd %x\n", msg->msg.data[0], msg->msg.cmd); } @@ -784,7 +804,7 @@ static void ipmi_register_watchdog(int ipmi_intf) rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user); if (rv < 0) { - printk("IPMI watchdog: Unable to register with ipmi\n"); + printk(KERN_CRIT PFX "Unable to register with ipmi\n"); goto out; } @@ -796,7 +816,7 @@ static void ipmi_register_watchdog(int ipmi_intf) if (rv < 0) { ipmi_destroy_user(watchdog_user); watchdog_user = NULL; - printk("IPMI watchdog: Unable to register misc device\n"); + printk(KERN_CRIT PFX "Unable to register misc device\n"); } out: @@ -807,7 +827,7 @@ static void ipmi_register_watchdog(int ipmi_intf) start_now = 0; /* Disable this function after first startup. */ ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); - printk("Starting IPMI Watchdog now!\n"); + printk(KERN_INFO PFX "Starting now!\n"); } } @@ -818,7 +838,7 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) /* If no one else handled the NMI, we assume it was the IPMI watchdog. */ if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) - panic("IPMI watchdog pre-timeout"); + panic(PFX "pre-timeout"); /* On some machines, the heartbeat will give an error and not work unless we re-enable @@ -924,7 +944,7 @@ static int __init ipmi_wdog_init(void) { int rv; - printk(KERN_INFO "IPMI watchdog driver version " + printk(KERN_INFO PFX "driver version " IPMI_WATCHDOG_VERSION "\n"); if (strcmp(action, "reset") == 0) { @@ -937,7 +957,7 @@ static int __init ipmi_wdog_init(void) action_val = WDOG_TIMEOUT_POWER_DOWN; } else { action_val = WDOG_TIMEOUT_RESET; - printk("ipmi_watchdog: Unknown action '%s', defaulting to" + printk(KERN_INFO PFX "Unknown action '%s', defaulting to" " reset\n", action); } @@ -953,7 +973,7 @@ static int __init ipmi_wdog_init(void) preaction_val = WDOG_PRETIMEOUT_MSG_INT; } else { preaction_val = WDOG_PRETIMEOUT_NONE; - printk("ipmi_watchdog: Unknown preaction '%s', defaulting to" + printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to" " none\n", preaction); } @@ -965,23 +985,21 @@ static int __init ipmi_wdog_init(void) preop_val = WDOG_PREOP_GIVE_DATA; } else { preop_val = WDOG_PREOP_NONE; - printk("ipmi_watchdog: Unknown preop '%s', defaulting to" + printk(KERN_INFO PFX "Unknown preop '%s', defaulting to" " none\n", preop); } #ifdef HAVE_NMI_HANDLER if (preaction_val == WDOG_PRETIMEOUT_NMI) { if (preop_val == WDOG_PREOP_GIVE_DATA) { - printk(KERN_WARNING - "ipmi_watchdog: Pretimeout op is to give data" + printk(KERN_WARNING PFX "Pretimeout op is to give data" " but NMI pretimeout is enabled, setting" " pretimeout op to none\n"); preop_val = WDOG_PREOP_NONE; } #ifdef CONFIG_X86_LOCAL_APIC if (nmi_watchdog == NMI_IO_APIC) { - printk(KERN_WARNING - "ipmi_watchdog: nmi_watchdog is set to IO APIC" + printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC" " mode (value is %d), that is incompatible" " with using NMI in the IPMI watchdog." " Disabling IPMI nmi pretimeout.\n", @@ -991,8 +1009,7 @@ static int __init ipmi_wdog_init(void) #endif rv = request_nmi(&ipmi_nmi_handler); if (rv) { - printk(KERN_WARNING - "ipmi_watchdog: Can't register nmi handler\n"); + printk(KERN_WARNING PFX "Can't register nmi handler\n"); return rv; } #ifdef CONFIG_X86_LOCAL_APIC @@ -1007,8 +1024,7 @@ static int __init ipmi_wdog_init(void) if (preaction_val == WDOG_PRETIMEOUT_NMI) release_nmi(&ipmi_nmi_handler); #endif - printk(KERN_WARNING - "ipmi_watchdog: can't register smi watcher\n"); + printk(KERN_WARNING PFX "can't register smi watcher\n"); return rv; } @@ -1053,8 +1069,7 @@ static __exit void ipmi_unregister_watchdog(void) /* Disconnect from IPMI. */ rv = ipmi_destroy_user(watchdog_user); if (rv) { - printk(KERN_WARNING - "IPMI Watchdog, error unlinking from IPMI: %d\n", + printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n", rv); } watchdog_user = NULL; diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index e8650449f..b3f40fe9d 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -389,7 +390,7 @@ static void isicom_tx(unsigned long _data) tty = port->tty; save_flags(flags); cli(); - txcount = MIN(TX_SIZE, port->xmit_cnt); + txcount = min_t(short, TX_SIZE, port->xmit_cnt); if ((txcount <= 0) || tty->stopped || tty->hw_stopped) { restore_flags(flags); continue; @@ -421,7 +422,7 @@ static void isicom_tx(unsigned long _data) residue = NO; wrd = 0; while (1) { - cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail)); + cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail)); if (residue == YES) { residue = NO; if (cnt > 0) { @@ -484,10 +485,8 @@ static void isicom_bottomhalf(void * data) if (!tty) return; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } @@ -650,7 +649,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id, } } else { /* Data Packet */ - count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count)); + count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count)); #ifdef ISICOM_DEBUG printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", count, byte_count); @@ -1119,17 +1118,16 @@ static void isicom_close(struct tty_struct * tty, struct file * filp) isicom_shutdown_port(port); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); tty->closing = 0; port->tty = NULL; if (port->blocked_open) { if (port->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); #ifdef ISICOM_DEBUG printk(KERN_DEBUG "ISICOM: scheduling until time out.\n"); #endif - schedule_timeout(port->close_delay); + msleep_interruptible(jiffies_to_msecs(port->close_delay)); } wake_up_interruptible(&port->open_wait); } @@ -1142,7 +1140,7 @@ static void isicom_close(struct tty_struct * tty, struct file * filp) } /* write et all */ -static int isicom_write(struct tty_struct * tty, int from_user, +static int isicom_write(struct tty_struct * tty, const unsigned char * buf, int count) { struct isi_port * port = (struct isi_port *) tty->driver_data; @@ -1157,35 +1155,16 @@ static int isicom_write(struct tty_struct * tty, int from_user, if (!tty || !port->xmit_buf || !tmp_buf) return 0; - if (from_user) - down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */ save_flags(flags); while(1) { cli(); - cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); + cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); if (cnt <= 0) break; - if (from_user) { - /* the following may block for paging... hence - enabling interrupts but tx routine may have - created more space in xmit_buf when the ctrl - gets back here */ - sti(); - if (copy_from_user(tmp_buf, buf, cnt)) { - up(&tmp_buf_sem); - restore_flags(flags); - return -EFAULT; - } - cli(); - cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt); - } - else - memcpy(port->xmit_buf + port->xmit_head, buf, cnt); + memcpy(port->xmit_buf + port->xmit_head, buf, cnt); port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1); port->xmit_cnt += cnt; restore_flags(flags); @@ -1193,8 +1172,6 @@ static int isicom_write(struct tty_struct * tty, int from_user, count -= cnt; total += cnt; } - if (from_user) - up(&tmp_buf_sem); if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped) port->status |= ISI_TXOK; restore_flags(flags); @@ -1563,9 +1540,7 @@ static void isicom_flush_buffer(struct tty_struct * tty) restore_flags(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } @@ -1798,9 +1773,9 @@ static int irq[4]; MODULE_AUTHOR("MultiTech"); MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); MODULE_LICENSE("GPL"); -MODULE_PARM(io, "1-4i"); +module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io, "I/O ports for the cards"); -MODULE_PARM(irq, "1-4i"); +module_param_array(irq, int, NULL, 0); MODULE_PARM_DESC(irq, "Interrupts for the cards"); int init_module(void) @@ -1906,8 +1881,7 @@ int init_module(void) void cleanup_module(void) { re_schedule = 0; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep(1000); #ifdef ISICOM_DEBUG printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4a8b7d51e..06b4572fa 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -660,7 +660,7 @@ static unsigned long stli_atol(char *str); int stli_init(void); static int stli_open(struct tty_struct *tty, struct file *filp); static void stli_close(struct tty_struct *tty, struct file *filp); -static int stli_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); static void stli_putchar(struct tty_struct *tty, unsigned char ch); static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); @@ -691,7 +691,6 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp); static void stli_dohangup(void *arg); -static void stli_delay(int len); static int stli_setport(stliport_t *portp); static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); @@ -749,17 +748,13 @@ static void stli_stalreset(stlibrd_t *brdp); static stliport_t *stli_getport(int brdnr, int panelnr, int portnr); -static inline int stli_initbrds(void); -static inline int stli_initecp(stlibrd_t *brdp); -static inline int stli_initonb(stlibrd_t *brdp); -static inline int stli_findeisabrds(void); -static inline int stli_eisamemprobe(stlibrd_t *brdp); -static inline int stli_initports(stlibrd_t *brdp); -static inline int stli_getbrdnr(void); +static int stli_initecp(stlibrd_t *brdp); +static int stli_initonb(stlibrd_t *brdp); +static int stli_eisamemprobe(stlibrd_t *brdp); +static int stli_initports(stlibrd_t *brdp); #ifdef CONFIG_PCI -static inline int stli_findpcibrds(void); -static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp); +static int stli_initpcibrd(int brdtype, struct pci_dev *devp); #endif /*****************************************************************************/ @@ -1184,7 +1179,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) if (portp->openwaitcnt) { if (portp->close_delay) - stli_delay(portp->close_delay); + msleep_interruptible(jiffies_to_msecs(portp->close_delay)); wake_up_interruptible(&portp->open_wait); } @@ -1481,25 +1476,6 @@ static int stli_setport(stliport_t *portp) /*****************************************************************************/ -/* - * Wait for a specified delay period, this is not a busy-loop. It will - * give up the processor while waiting. Unfortunately this has some - * rather intimate knowledge of the process management stuff. - */ - -static void stli_delay(int len) -{ -#ifdef DEBUG - printk("stli_delay(len=%d)\n", len); -#endif - if (len > 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(len); - } -} - -/*****************************************************************************/ - /* * Possibly need to wait for carrier (DCD signal) to come high. Say * maybe because if we are clocal then we don't need to wait... @@ -1567,7 +1543,7 @@ static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *fil * service bits for this port. */ -static int stli_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count) { volatile cdkasy_t *ap; volatile cdkhdr_t *hdrp; @@ -1579,8 +1555,8 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char unsigned long flags; #ifdef DEBUG - printk("stli_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - (int) tty, from_user, (int) buf, count); + printk("stli_write(tty=%x,buf=%x,count=%d)\n", + (int) tty, (int) buf, count); #endif if ((tty == (struct tty_struct *) NULL) || @@ -1598,38 +1574,6 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char return(0); chbuf = (unsigned char *) buf; -/* - * If copying direct from user space we need to be able to handle page - * faults while we are copying. To do this copy as much as we can now - * into a kernel buffer. From there we copy it into shared memory. The - * big problem is that we do not want shared memory enabled when we are - * sleeping (other boards may be serviced while asleep). Something else - * to note here is the reading of the tail twice. Since the boards - * shared memory can be on an 8-bit bus then we need to be very careful - * reading 16 bit quantities - since both the board (slave) and host - * could be writing and reading at the same time. - */ - if (from_user) { - save_flags(flags); - cli(); - EBRDENABLE(brdp); - ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr); - head = (unsigned int) ap->txq.head; - tail = (unsigned int) ap->txq.tail; - if (tail != ((unsigned int) ap->txq.tail)) - tail = (unsigned int) ap->txq.tail; - len = (head >= tail) ? (portp->txsize - (head - tail) - 1) : - (tail - head - 1); - count = MIN(len, count); - EBRDDISABLE(brdp); - restore_flags(flags); - - down(&stli_tmpwritesem); - if (copy_from_user(stli_tmpwritebuf, chbuf, count)) - return -EFAULT; - chbuf = &stli_tmpwritebuf[0]; - } - /* * All data is now local, shove as much as possible into shared memory. */ @@ -1680,8 +1624,6 @@ static int stli_write(struct tty_struct *tty, int from_user, const unsigned char set_bit(ST_TXBUSY, &portp->state); EBRDDISABLE(brdp); - if (from_user) - up(&stli_tmpwritesem); restore_flags(flags); return(count); @@ -2508,7 +2450,7 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout) while (test_bit(ST_TXBUSY, &portp->state)) { if (signal_pending(current)) break; - stli_delay(2); + msleep_interruptible(20); if (time_after_eq(jiffies, tend)) break; } @@ -2751,7 +2693,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, * more chars to unload. */ -static inline void stli_read(stlibrd_t *brdp, stliport_t *portp) +static void stli_read(stlibrd_t *brdp, stliport_t *portp) { volatile cdkasyrq_t *rp; volatile char *shbuf; @@ -2819,7 +2761,7 @@ static inline void stli_read(stlibrd_t *brdp, stliport_t *portp) * difficult to deal with them here. */ -static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp) +static void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp) { int cmd; @@ -2867,7 +2809,7 @@ static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp) * then port is still busy, otherwise no longer busy. */ -static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) +static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) { volatile cdkasy_t *ap; volatile cdkctrl_t *cp; @@ -3026,7 +2968,7 @@ static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) * at the cdk header structure. */ -static inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp) +static void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp) { stliport_t *portp; unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; @@ -3299,7 +3241,7 @@ static long stli_mktiocm(unsigned long sigvalue) * we need to do here is set up the appropriate per port data structures. */ -static inline int stli_initports(stlibrd_t *brdp) +static int stli_initports(stlibrd_t *brdp) { stliport_t *portp; int i, panelnr, panelport; @@ -3911,7 +3853,7 @@ static void stli_stalreset(stlibrd_t *brdp) * board types. */ -static inline int stli_initecp(stlibrd_t *brdp) +static int stli_initecp(stlibrd_t *brdp) { cdkecpsig_t sig; cdkecpsig_t *sigsp; @@ -4072,7 +4014,7 @@ static inline int stli_initecp(stlibrd_t *brdp) * This handles only these board types. */ -static inline int stli_initonb(stlibrd_t *brdp) +static int stli_initonb(stlibrd_t *brdp) { cdkonbsig_t sig; cdkonbsig_t *sigsp; @@ -4414,7 +4356,7 @@ static int __init stli_brdinit(stlibrd_t *brdp) * might be. This is a bit if hack, but it is the best we can do. */ -static inline int stli_eisamemprobe(stlibrd_t *brdp) +static int stli_eisamemprobe(stlibrd_t *brdp) { cdkecpsig_t ecpsig, *ecpsigp; cdkonbsig_t onbsig, *onbsigp; @@ -4506,7 +4448,7 @@ static inline int stli_eisamemprobe(stlibrd_t *brdp) return(0); } -static inline int stli_getbrdnr(void) +static int stli_getbrdnr(void) { int i; @@ -4532,7 +4474,7 @@ static inline int stli_getbrdnr(void) * do is go probing around in the usual places hoping we can find it. */ -static inline int stli_findeisabrds(void) +static int stli_findeisabrds(void) { stlibrd_t *brdp; unsigned int iobase, eid; @@ -4616,7 +4558,7 @@ static inline int stli_findeisabrds(void) * configuration space. */ -static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp) +static int stli_initpcibrd(int brdtype, struct pci_dev *devp) { stlibrd_t *brdp; @@ -4662,7 +4604,7 @@ static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp) * one as it is found. */ -static inline int stli_findpcibrds(void) +static int stli_findpcibrds(void) { struct pci_dev *dev = NULL; int rc; @@ -4711,7 +4653,7 @@ static stlibrd_t *stli_allocbrd(void) * can find. */ -static inline int stli_initbrds(void) +static int stli_initbrds(void) { stlibrd_t *brdp, *nxtbrdp; stlconf_t *confp; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 3ad30ba46..313789840 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -123,7 +123,7 @@ int shift_state = 0; */ static struct input_handler kbd_handler; -static unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */ +static unsigned long key_down[NBITS(KEY_MAX)]; /* keyboard key bitmap */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static int dead_key_next; static int npadch = -1; /* -1 or number assembled on pad */ @@ -142,7 +142,7 @@ static struct ledptr { /* Simple translation table for the SysRq keys */ #ifdef CONFIG_MAGIC_SYSRQ -unsigned char kbd_sysrq_xlate[128] = +unsigned char kbd_sysrq_xlate[KEY_MAX] = "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ @@ -941,6 +941,9 @@ void kbd_refresh_leds(struct input_handle *handle) #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) +#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ + ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) + static unsigned short x86_keycodes[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, @@ -1007,6 +1010,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, #else +#define HW_RAW(dev) 0 + #warning "Cannot generate rawmode keyboard for your architecture yet." static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) @@ -1019,7 +1024,15 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u } #endif -void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs) +void kbd_rawcode(unsigned char data) +{ + struct vc_data *vc = vc_cons[fg_console].d; + kbd = kbd_table + fg_console; + if (kbd->kbdmode == VC_RAW) + put_queue(vc, data); +} + +void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs) { struct vc_data *vc = vc_cons[fg_console].d; unsigned short keysym, *key_map; @@ -1053,7 +1066,7 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs) return; #endif /* CONFIG_MAC_EMUMOUSEBTN */ - if ((raw_mode = (kbd->kbdmode == VC_RAW))) + if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) if (emulate_raw(vc, keycode, !down << 7)) if (keycode < BTN_MISC) printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); @@ -1119,6 +1132,9 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs) return; } + if (keycode > NR_KEYS) + return; + keysym = key_map[keycode]; type = KTYP(keysym); @@ -1148,11 +1164,12 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs) } static void kbd_event(struct input_handle *handle, unsigned int event_type, - unsigned int keycode, int down) + unsigned int event_code, int value) { - if (event_type != EV_KEY) - return; - kbd_keycode(keycode, down, handle->dev->regs); + if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev)) + kbd_rawcode(value); + if (event_type == EV_KEY) + kbd_keycode(event_code, value, HW_RAW(handle->dev), handle->dev->regs); tasklet_schedule(&keyboard_tasklet); do_poke_blanked_console = 1; schedule_console_callback(); diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 64837783d..717d812c2 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -583,8 +584,7 @@ static long lcd_read(struct inode *inode, struct file *file, char *buf, lcd_waiters++; while (((buttons_now = (long) button_pressed()) == 0) && !(signal_pending(current))) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(2 * HZ); + msleep_interruptible(2000); } lcd_waiters--; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 6110dbf40..093f79828 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -749,8 +749,8 @@ static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; static char *parport[LP_NO] = { NULL, }; static int reset = 0; -MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "s"); -MODULE_PARM(reset, "i"); +module_param_array(parport, charp, NULL, 0); +module_param(reset, bool, 0); #ifndef MODULE static int __init lp_setup (char *str) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 3274c3a73..840a0afae 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -31,9 +31,6 @@ # include #endif -#ifdef CONFIG_FB -extern void fbmem_init(void); -#endif #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) extern void tapechar_init(void); #endif @@ -86,7 +83,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) * above the IO hole... Ah, and of course, XFree86 doesn't pass * O_SYNC when mapping us to tap IO space. Surprised ? */ - return !page_is_ram(addr); + return !page_is_ram(addr >> PAGE_SHIFT); #else /* * Accessing memory above the top the kernel knows about or through a file pointer @@ -195,26 +192,21 @@ static ssize_t write_mem(struct file * file, const char __user * buf, static int mmap_mem(struct file * file, struct vm_area_struct * vma) { +#ifdef pgprot_noncached unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int uncached; uncached = uncached_access(file, offset); -#ifdef pgprot_noncached if (uncached) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #endif - /* Don't try to swap out physical pages.. */ - vma->vm_flags |= VM_RESERVED; - - /* - * Don't dump addresses that are not real memory to a core file. - */ - if (uncached) - vma->vm_flags |= VM_IO; - - if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, - vma->vm_page_prot)) + /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + vma->vm_end-vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; return 0; } @@ -416,7 +408,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size) if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) goto out_up; - if (vma->vm_flags & VM_SHARED) + if (vma->vm_flags & (VM_SHARED | VM_HUGETLB)) break; count = vma->vm_end - addr; if (count > size) @@ -730,9 +722,6 @@ static int __init chr_dev_init(void) S_IFCHR | devlist[i].mode, devlist[i].name); } -#if defined (CONFIG_FB) - fbmem_init(); -#endif return 0; } diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 20aa170db..c254bf7bd 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -13,6 +13,9 @@ * * 11/01/01 - jbarnes - initial revision * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion + * 10/1/04 - Christoph Lameter - provide posix clock CLOCK_SGI_CYCLE + * 10/13/04 - Christoph Lameter, Dimitri Sivanich - provide timer interrupt + * support via the posix timer interface */ #include @@ -25,21 +28,35 @@ #include #include #include +#include +#include + #include #include -#include +#include +#include +#include + +/* This is ugly and jbarnes has promised me to fix this later */ +#include "../../arch/ia64/sn/include/shubio.h" MODULE_AUTHOR("Jesse Barnes "); -MODULE_DESCRIPTION("Multimedia timer support"); +MODULE_DESCRIPTION("SGI Altix RTC Timer"); MODULE_LICENSE("GPL"); /* name of the device, usually in /dev */ #define MMTIMER_NAME "mmtimer" -#define MMTIMER_DESC "IA-PC Multimedia Timer" -#define MMTIMER_VERSION "1.0" +#define MMTIMER_DESC "SGI Altix RTC Timer" +#define MMTIMER_VERSION "2.0" #define RTC_BITS 55 /* 55 bits for this implementation */ +extern unsigned long sn_rtc_cycles_per_second; + +#define RTC_COUNTER_ADDR ((long *)LOCAL_MMR_ADDR(SH_RTC)) + +#define rtc_time() (*RTC_COUNTER_ADDR) + static int mmtimer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma); @@ -55,6 +72,180 @@ static struct file_operations mmtimer_fops = { .ioctl = mmtimer_ioctl, }; +/* + * Comparators and their associated info. Shub has + * three comparison registers. + */ + +/* + * We only have comparison registers RTC1-4 currently available per + * node. RTC0 is used by SAL. + */ +#define NUM_COMPARATORS 3 +/* Check for an RTC interrupt pending */ +static int inline mmtimer_int_pending(int comparator) +{ + if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) & + SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator) + return 1; + else + return 0; +} +/* Clear the RTC interrupt pending bit */ +static void inline mmtimer_clr_int_pending(int comparator) +{ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), + SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator); +} + +/* Setup timer on comparator RTC1 */ +static void inline mmtimer_setup_int_0(u64 expires) +{ + u64 val; + + /* Disable interrupt */ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 0UL); + + /* Initialize comparator value */ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), -1L); + + /* Clear pending bit */ + mmtimer_clr_int_pending(0); + + val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) | + ((u64)cpu_physical_id(smp_processor_id()) << + SH_RTC1_INT_CONFIG_PID_SHFT); + + /* Set configuration */ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_CONFIG), val); + + /* Enable RTC interrupts */ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), 1UL); + + /* Initialize comparator value */ + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPB), expires); + + +} + +/* Setup timer on comparator RTC2 */ +static void inline mmtimer_setup_int_1(u64 expires) +{ + u64 val; + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 0UL); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), -1L); + + mmtimer_clr_int_pending(1); + + val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) | + ((u64)cpu_physical_id(smp_processor_id()) << + SH_RTC2_INT_CONFIG_PID_SHFT); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), 1UL); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPC), expires); +} + +/* Setup timer on comparator RTC3 */ +static void inline mmtimer_setup_int_2(u64 expires) +{ + u64 val; + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 0UL); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), -1L); + + mmtimer_clr_int_pending(2); + + val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) | + ((u64)cpu_physical_id(smp_processor_id()) << + SH_RTC3_INT_CONFIG_PID_SHFT); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), 1UL); + + HUB_S((u64 *)LOCAL_MMR_ADDR(SH_INT_CMPD), expires); +} + +/* + * This function must be called with interrupts disabled and preemption off + * in order to insure that the setup succeeds in a deterministic time frame. + * It will check if the interrupt setup succeeded. + * mmtimer_setup will return the cycles that we were too late if the + * initialization failed. + */ +static int inline mmtimer_setup(int comparator, unsigned long expires) +{ + + long diff; + + switch (comparator) { + case 0: + mmtimer_setup_int_0(expires); + break; + case 1: + mmtimer_setup_int_1(expires); + break; + case 2: + mmtimer_setup_int_2(expires); + break; + } + /* We might've missed our expiration time */ + diff = rtc_time() - expires; + if (diff > 0) { + if (mmtimer_int_pending(comparator)) { + /* We'll get an interrupt for this once we're done */ + return 0; + } + /* Looks like we missed it */ + return diff; + } + + return 0; +} + +static int inline mmtimer_disable_int(long nasid, int comparator) +{ + switch (comparator) { + case 0: + nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC1_INT_ENABLE), + 0UL) : REMOTE_HUB_S(nasid, SH_RTC1_INT_ENABLE, 0UL); + break; + case 1: + nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_ENABLE), + 0UL) : REMOTE_HUB_S(nasid, SH_RTC2_INT_ENABLE, 0UL); + break; + case 2: + nasid == -1 ? HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_ENABLE), + 0UL) : REMOTE_HUB_S(nasid, SH_RTC3_INT_ENABLE, 0UL); + break; + default: + return -EFAULT; + } + return 0; +} + +#define TIMER_OFF 0xbadcabLL + +/* There is one of these for each comparator */ +typedef struct mmtimer { + spinlock_t lock ____cacheline_aligned; + struct k_itimer *timer; + int i; + int cpu; + struct tasklet_struct tasklet; +} mmtimer_t; + +/* + * Total number of comparators is comparators/node * MAX nodes/running kernel + */ +static mmtimer_t timers[NUM_COMPARATORS*MAX_COMPACT_NODES]; + /** * mmtimer_ioctl - ioctl interface for /dev/mmtimer * @inode: inode of the device @@ -100,13 +291,13 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file, break; case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ - if(copy_to_user((unsigned long *)arg, &mmtimer_femtoperiod, - sizeof(unsigned long))) + if(copy_to_user((unsigned long __user *)arg, + &mmtimer_femtoperiod, sizeof(unsigned long))) return -EFAULT; break; case MMTIMER_GETFREQ: /* frequency in Hz */ - if(copy_to_user((unsigned long *)arg, + if(copy_to_user((unsigned long __user *)arg, &sn_rtc_cycles_per_second, sizeof(unsigned long))) return -EFAULT; @@ -122,8 +313,8 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file, break; case MMTIMER_GETCOUNTER: - if(copy_to_user((unsigned long *)arg, RTC_COUNTER_ADDR, - sizeof(unsigned long))) + if(copy_to_user((unsigned long __user *)arg, + RTC_COUNTER_ADDR, sizeof(unsigned long))) return -EFAULT; break; default: @@ -139,7 +330,7 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file, * @file: file structure for the device * @vma: VMA to map the registers into * - * Calls remap_page_range() to map the clock's registers into + * Calls remap_pfn_range() to map the clock's registers into * the calling process' address space. */ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma) @@ -162,9 +353,9 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma) mmtimer_addr &= ~(PAGE_SIZE - 1); mmtimer_addr &= 0xfffffffffffffffUL; - if (remap_page_range(vma, vma->vm_start, mmtimer_addr, PAGE_SIZE, - vma->vm_page_prot)) { - printk(KERN_ERR "remap_page_range failed in mmtimer.c\n"); + if (remap_pfn_range(vma, vma->vm_start, mmtimer_addr >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot)) { + printk(KERN_ERR "remap_pfn_range failed in mmtimer.c\n"); return -EAGAIN; } @@ -177,6 +368,313 @@ static struct miscdevice mmtimer_miscdev = { &mmtimer_fops }; +static struct timespec sgi_clock_offset; +static int sgi_clock_period; + +/* + * Posix Timer Interface + */ + +static struct timespec sgi_clock_offset; +static int sgi_clock_period; + +static int sgi_clock_get(struct timespec *tp) +{ + u64 nsec; + + nsec = rtc_time() * sgi_clock_period + + sgi_clock_offset.tv_nsec; + tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec) + + sgi_clock_offset.tv_sec; + return 0; +}; + +static int sgi_clock_set(struct timespec *tp) +{ + + u64 nsec; + u64 rem; + + nsec = rtc_time() * sgi_clock_period; + + sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem); + + if (rem <= tp->tv_nsec) + sgi_clock_offset.tv_nsec = tp->tv_sec - rem; + else { + sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem; + sgi_clock_offset.tv_sec--; + } + return 0; +} + +/* + * Schedule the next periodic interrupt. This function will attempt + * to schedule a periodic interrupt later if necessary. If the scheduling + * of an interrupt fails then the time to skip is lengthened + * exponentially in order to ensure that the next interrupt + * can be properly scheduled.. + */ +static int inline reschedule_periodic_timer(mmtimer_t *x) +{ + int n; + struct k_itimer *t = x->timer; + + t->it_timer.magic = x->i; + t->it_overrun--; + + n = 0; + do { + + t->it_timer.expires += t->it_incr << n; + t->it_overrun += 1 << n; + n++; + if (n > 20) + return 1; + + } while (mmtimer_setup(x->i, t->it_timer.expires)); + + return 0; +} + +/** + * mmtimer_interrupt - timer interrupt handler + * @irq: irq received + * @dev_id: device the irq came from + * @regs: register state upon receipt of the interrupt + * + * Called when one of the comarators matches the counter, This + * routine will send signals to processes that have requested + * them. + * + * This interrupt is run in an interrupt context + * by the SHUB. It is therefore safe to locally access SHub + * registers. + */ +static irqreturn_t +mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + mmtimer_t *base = timers + cpuid_to_cnodeid(smp_processor_id()) * + NUM_COMPARATORS; + unsigned long expires = 0; + int result = IRQ_NONE; + + /* + * Do this once for each comparison register + */ + for (i = 0; i < NUM_COMPARATORS; i++) { + /* Make sure this doesn't get reused before tasklet_sched */ + spin_lock(&base[i].lock); + if (base[i].cpu == smp_processor_id()) { + if (base[i].timer) + expires = base[i].timer->it_timer.expires; + /* expires test won't work with shared irqs */ + if ((mmtimer_int_pending(i) > 0) || + (expires && (expires < rtc_time()))) { + mmtimer_clr_int_pending(i); + tasklet_schedule(&base[i].tasklet); + result = IRQ_HANDLED; + } + } + spin_unlock(&base[i].lock); + expires = 0; + } + return result; +} + +void mmtimer_tasklet(unsigned long data) { + mmtimer_t *x = (mmtimer_t *)data; + struct k_itimer *t = x->timer; + unsigned long flags; + + if (t == NULL) + return; + + /* Send signal and deal with periodic signals */ + spin_lock_irqsave(&t->it_lock, flags); + spin_lock(&x->lock); + /* If timer was deleted between interrupt and here, leave */ + if (t != x->timer) + goto out; + t->it_overrun = 0; + + if (tasklist_lock.write_lock || posix_timer_event(t, 0) != 0) { + + // printk(KERN_WARNING "mmtimer: cannot deliver signal.\n"); + + t->it_overrun++; + } + if(t->it_incr) { + /* Periodic timer */ + if (reschedule_periodic_timer(x)) { + printk(KERN_WARNING "mmtimer: unable to reschedule\n"); + x->timer = NULL; + } + } else { + /* Ensure we don't false trigger in mmtimer_interrupt */ + t->it_timer.expires = 0; + } + t->it_overrun_last = t->it_overrun; +out: + spin_unlock(&x->lock); + spin_unlock_irqrestore(&t->it_lock, flags); +} + +static int sgi_timer_create(struct k_itimer *timer) +{ + /* Insure that a newly created timer is off */ + timer->it_timer.magic = TIMER_OFF; + return 0; +} + +/* This does not really delete a timer. It just insures + * that the timer is not active + * + * Assumption: it_lock is already held with irq's disabled + */ +static int sgi_timer_del(struct k_itimer *timr) +{ + int i = timr->it_timer.magic; + cnodeid_t nodeid = timr->it_timer.data; + mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i; + unsigned long irqflags; + + if (i != TIMER_OFF) { + spin_lock_irqsave(&t->lock, irqflags); + mmtimer_disable_int(cnodeid_to_nasid(nodeid),i); + t->timer = NULL; + timr->it_timer.magic = TIMER_OFF; + timr->it_timer.expires = 0; + spin_unlock_irqrestore(&t->lock, irqflags); + } + return 0; +} + +#define timespec_to_ns(x) ((x).tv_nsec + (x).tv_sec * NSEC_PER_SEC) +#define ns_to_timespec(ts, nsec) (ts).tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &(ts).tv_nsec) + +/* Assumption: it_lock is already held with irq's disabled */ +static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) +{ + + if (timr->it_timer.magic == TIMER_OFF) { + cur_setting->it_interval.tv_nsec = 0; + cur_setting->it_interval.tv_sec = 0; + cur_setting->it_value.tv_nsec = 0; + cur_setting->it_value.tv_sec =0; + return; + } + + ns_to_timespec(cur_setting->it_interval, timr->it_incr * sgi_clock_period); + ns_to_timespec(cur_setting->it_value, (timr->it_timer.expires - rtc_time())* sgi_clock_period); + return; +} + + +static int sgi_timer_set(struct k_itimer *timr, int flags, + struct itimerspec * new_setting, + struct itimerspec * old_setting) +{ + + int i; + unsigned long when, period, irqflags; + int err = 0; + cnodeid_t nodeid; + mmtimer_t *base; + + if (old_setting) + sgi_timer_get(timr, old_setting); + + sgi_timer_del(timr); + when = timespec_to_ns(new_setting->it_value); + period = timespec_to_ns(new_setting->it_interval); + + if (when == 0) + /* Clear timer */ + return 0; + + if (flags & TIMER_ABSTIME) { + struct timespec n; + + getnstimeofday(&n); + when -= timespec_to_ns(n); + } + + /* + * Convert to sgi clock period. Need to keep rtc_time() as near as possible + * to getnstimeofday() in order to be as faithful as possible to the time + * specified. + */ + when = (when + sgi_clock_period - 1) / sgi_clock_period + rtc_time(); + period = (period + sgi_clock_period - 1) / sgi_clock_period; + + /* + * We are allocating a local SHub comparator. If we would be moved to another + * cpu then another SHub may be local to us. Prohibit that by switching off + * preemption. + */ + preempt_disable(); + + nodeid = cpuid_to_cnodeid(smp_processor_id()); + base = timers + nodeid * NUM_COMPARATORS; +retry: + /* Don't use an allocated timer, or a deleted one that's pending */ + for(i = 0; i< NUM_COMPARATORS; i++) { + if (!base[i].timer && !base[i].tasklet.state) { + break; + } + } + + if (i == NUM_COMPARATORS) { + preempt_enable(); + return -EBUSY; + } + + spin_lock_irqsave(&base[i].lock, irqflags); + + if (base[i].timer || base[i].tasklet.state != 0) { + spin_unlock_irqrestore(&base[i].lock, irqflags); + goto retry; + } + base[i].timer = timr; + base[i].cpu = smp_processor_id(); + + timr->it_timer.magic = i; + timr->it_timer.data = nodeid; + timr->it_incr = period; + timr->it_timer.expires = when; + + if (period == 0) { + if (mmtimer_setup(i, when)) { + mmtimer_disable_int(-1, i); + posix_timer_event(timr, 0); + timr->it_timer.expires = 0; + } + } else { + timr->it_timer.expires -= period; + if (reschedule_periodic_timer(base+i)) + err = -EINVAL; + } + + spin_unlock_irqrestore(&base[i].lock, irqflags); + + preempt_enable(); + + return err; +} + +static struct k_clock sgi_clock = { + .res = 0, + .clock_set = sgi_clock_set, + .clock_get = sgi_clock_get, + .timer_create = sgi_timer_create, + .nsleep = do_posix_clock_nonanosleep, + .timer_set = sgi_timer_set, + .timer_del = sgi_timer_del, + .timer_get = sgi_timer_get +}; + /** * mmtimer_init - device initialization routine * @@ -184,6 +682,8 @@ static struct miscdevice mmtimer_miscdev = { */ static int __init mmtimer_init(void) { + unsigned i; + if (!ia64_platform_is("sn2")) return -1; @@ -199,6 +699,20 @@ static int __init mmtimer_init(void) mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second / 2) / sn_rtc_cycles_per_second; + for (i=0; i< NUM_COMPARATORS*MAX_COMPACT_NODES; i++) { + spin_lock_init(&timers[i].lock); + timers[i].timer = NULL; + timers[i].cpu = 0; + timers[i].i = i % NUM_COMPARATORS; + tasklet_init(&timers[i].tasklet, mmtimer_tasklet, (unsigned long) (timers+i)); + } + + if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, SA_PERCPU_IRQ, MMTIMER_NAME, NULL)) { + printk(KERN_WARNING "%s: unable to allocate interrupt.", + MMTIMER_NAME); + return -1; + } + strcpy(mmtimer_miscdev.devfs_name, MMTIMER_NAME); if (misc_register(&mmtimer_miscdev)) { printk(KERN_ERR "%s: failed to register device\n", @@ -206,6 +720,9 @@ static int __init mmtimer_init(void) return -1; } + sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second; + register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); + printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION, sn_rtc_cycles_per_second/(unsigned long)1E6); diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 0e75a0dc9..10ba9bfb5 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -50,10 +50,10 @@ #include #include #include +#include #include #include -#include #include #define MOXA_VERSION "5.1k" @@ -142,7 +142,7 @@ typedef struct _moxa_board_conf { } moxa_board_conf; static moxa_board_conf moxa_boards[MAX_BOARDS]; -static unsigned long moxaBaseAddr[MAX_BOARDS]; +static void __iomem *moxaBaseAddr[MAX_BOARDS]; struct moxa_str { int type; @@ -201,11 +201,13 @@ static int numports[] = {0, 0, 0, 0}; MODULE_AUTHOR("William Chen"); MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(type, "1-4i"); -MODULE_PARM(baseaddr, "1-4i"); -MODULE_PARM(numports, "1-4i"); -MODULE_PARM(ttymajor, "i"); -MODULE_PARM(verbose, "i"); +#ifdef MODULE +module_param_array(type, int, NULL, 0); +module_param_array(baseaddr, int, NULL, 0); +module_param_array(numports, int, NULL, 0); +#endif +module_param(ttymajor, int, 0); +module_param(verbose, bool, 0644); static struct tty_driver *moxaDriver; static struct moxa_str moxaChannels[MAX_PORTS]; @@ -222,7 +224,7 @@ static struct semaphore moxaBuffSem; static void do_moxa_softint(void *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); -static int moxa_write(struct tty_struct *, int, const unsigned char *, int); +static int moxa_write(struct tty_struct *, const unsigned char *, int); static int moxa_write_room(struct tty_struct *); static void moxa_flush_buffer(struct tty_struct *); static int moxa_chars_in_buffer(struct tty_struct *); @@ -467,7 +469,7 @@ static int __init moxa_init(void) } #endif for (i = 0; i < numBoards; i++) { - moxaBaseAddr[i] = (unsigned long) ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000); + moxaBaseAddr[i] = ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000); } return (0); @@ -492,7 +494,6 @@ static void __exit moxa_exit(void) put_tty_driver(moxaDriver); if (verbose) printk("Done\n"); - } module_init(moxa_init); @@ -618,15 +619,14 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); + tty->closing = 0; ch->event = 0; ch->tty = NULL; if (ch->blocked_open) { if (ch->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ch->close_delay); + msleep_interruptible(jiffies_to_msecs(ch->close_delay)); } wake_up_interruptible(&ch->open_wait); } @@ -634,7 +634,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&ch->close_wait); } -static int moxa_write(struct tty_struct *tty, int from_user, +static int moxa_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct moxa_str *ch; @@ -646,25 +646,9 @@ static int moxa_write(struct tty_struct *tty, int from_user, return (0); port = ch->port; save_flags(flags); - if (from_user) { - if (count > PAGE_SIZE) - count = PAGE_SIZE; - down(&moxaBuffSem); - if (copy_from_user(moxaXmitBuff, buf, count)) { - len = -EFAULT; - } else { - cli(); - len = MoxaPortWriteData(port, moxaXmitBuff, count); - restore_flags(flags); - } - up(&moxaBuffSem); - if (len < 0) - return len; - } else { - cli(); - len = MoxaPortWriteData(port, (unsigned char *) buf, count); - restore_flags(flags); - } + cli(); + len = MoxaPortWriteData(port, (unsigned char *) buf, count); + restore_flags(flags); /********************************************* if ( !(ch->statusflags & LOWWAIT) && @@ -693,10 +677,7 @@ static void moxa_flush_buffer(struct tty_struct *tty) if (ch == NULL) return; MoxaPortFlushData(ch->port, 1); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } static int moxa_chars_in_buffer(struct tty_struct *tty) @@ -954,10 +935,7 @@ static void moxa_poll(unsigned long ignored) if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) { if (!tp->stopped) { ch->statusflags &= ~LOWWAIT; - if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tp->ldisc.write_wakeup) - (tp->ldisc.write_wakeup) (tp); - wake_up_interruptible(&tp->write_wait); + tty_wakeup(tp); } } } @@ -1123,10 +1101,7 @@ static void check_xmit_empty(unsigned long data) if (ch->tty && (ch->statusflags & EMPTYWAIT)) { if (MoxaPortTxQueue(ch->port) == 0) { ch->statusflags &= ~EMPTYWAIT; - if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->tty->ldisc.write_wakeup) - (ch->tty->ldisc.write_wakeup) (ch->tty); - wake_up_interruptible(&ch->tty->write_wait); + tty_wakeup(ch->tty); return; } moxaEmptyTimer[ch->port].expires = jiffies + HZ; @@ -1504,12 +1479,12 @@ typedef struct mon_str mon_st; #define DCD_oldstate 0x80 static unsigned char moxaBuff[10240]; -static unsigned long moxaIntNdx[MAX_BOARDS]; -static unsigned long moxaIntPend[MAX_BOARDS]; -static unsigned long moxaIntTable[MAX_BOARDS]; +static void __iomem *moxaIntNdx[MAX_BOARDS]; +static void __iomem *moxaIntPend[MAX_BOARDS]; +static void __iomem *moxaIntTable[MAX_BOARDS]; static char moxaChkPort[MAX_PORTS]; static char moxaLineCtrl[MAX_PORTS]; -static unsigned long moxaTableAddr[MAX_PORTS]; +static void __iomem *moxaTableAddr[MAX_PORTS]; static long moxaCurBaud[MAX_PORTS]; static char moxaDCDState[MAX_PORTS]; static char moxaLowChkFlag[MAX_PORTS]; @@ -1520,15 +1495,15 @@ static int moxaFuncTout; static ushort moxaBreakCnt[MAX_PORTS]; static void moxadelay(int); -static void moxafunc(unsigned long, int, ushort); -static void wait_finish(unsigned long); -static void low_water_check(unsigned long); +static void moxafunc(void __iomem *, int, ushort); +static void wait_finish(void __iomem *); +static void low_water_check(void __iomem *); static int moxaloadbios(int, unsigned char __user *, int); static int moxafindcard(int); static int moxaload320b(int, unsigned char __user *, int); static int moxaloadcode(int, unsigned char __user *, int); -static int moxaloadc218(int, unsigned long, int); -static int moxaloadc320(int, unsigned long, int, int *); +static int moxaloadc218(int, void __iomem *, int); +static int moxaloadc320(int, void __iomem *, int, int *); /***************************************************************************** * Driver level functions: * @@ -1586,7 +1561,7 @@ static struct dl_str dltmp; void MoxaPortFlushData(int port, int mode) { - unsigned long ofsAddr; + void __iomem *ofsAddr; if ((mode < 0) || (mode > 2)) return; ofsAddr = moxaTableAddr[port]; @@ -1718,7 +1693,8 @@ int MoxaDriverPoll(void) { register ushort temp; register int card; - unsigned long ip, ofsAddr; + void __iomem *ofsAddr; + void __iomem *ip; int port, p, ports; if (moxaCard == 0) @@ -2151,7 +2127,7 @@ int MoxaPortIsValid(int port) void MoxaPortEnable(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int MoxaPortLineStatus(int); short lowwater = 512; @@ -2174,9 +2150,8 @@ void MoxaPortEnable(int port) void MoxaPortDisable(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr = moxaTableAddr[port]; - ofsAddr = moxaTableAddr[port]; moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); writew(0, ofsAddr + HostStat); @@ -2195,7 +2170,7 @@ long MoxaPortGetMaxBaud(int port) long MoxaPortSetBaud(int port, long baud) { - unsigned long ofsAddr; + void __iomem *ofsAddr; long max, clock; unsigned int val; @@ -2219,7 +2194,7 @@ long MoxaPortSetBaud(int port, long baud) int MoxaPortSetTermio(int port, struct termios *termio) { - unsigned long ofsAddr; + void __iomem *ofsAddr; tcflag_t cflag; long baud; tcflag_t mode = 0; @@ -2364,7 +2339,7 @@ int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState) void MoxaPortLineCtrl(int port, int dtr, int rts) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int mode; ofsAddr = moxaTableAddr[port]; @@ -2379,7 +2354,7 @@ void MoxaPortLineCtrl(int port, int dtr, int rts) void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int mode; ofsAddr = moxaTableAddr[port]; @@ -2399,7 +2374,7 @@ void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int tx int MoxaPortLineStatus(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int val; ofsAddr = moxaTableAddr[port]; @@ -2472,7 +2447,7 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len) int cnt; ushort head, tx_mask, spage, epage; ushort pageno, pageofs, bufhead; - unsigned long baseAddr, ofsAddr, ofs; + void __iomem *baseAddr, *ofsAddr, *ofs; ofsAddr = moxaTableAddr[port]; baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; @@ -2535,7 +2510,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space) int i, count, cnt, len, total, remain; ushort tail, rx_mask, spage, epage; ushort pageno, bufhead; - unsigned long baseAddr, ofsAddr, ofs; + void __iomem *baseAddr, *ofsAddr, *ofs; ofsAddr = moxaTableAddr[port]; baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD]; @@ -2601,7 +2576,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space) int MoxaPortTxQueue(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; @@ -2615,7 +2590,7 @@ int MoxaPortTxQueue(int port) int MoxaPortTxFree(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; @@ -2629,7 +2604,7 @@ int MoxaPortTxFree(int port) int MoxaPortRxQueue(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; @@ -2644,7 +2619,7 @@ int MoxaPortRxQueue(int port) void MoxaPortTxDisable(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ofsAddr = moxaTableAddr[port]; moxafunc(ofsAddr, FC_SetXoffState, Magic_code); @@ -2652,7 +2627,7 @@ void MoxaPortTxDisable(int port) void MoxaPortTxEnable(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ofsAddr = moxaTableAddr[port]; moxafunc(ofsAddr, FC_SetXonState, Magic_code); @@ -2670,7 +2645,7 @@ int MoxaPortResetBrkCnt(int port) void MoxaPortSendBreak(int port, int ms100) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ofsAddr = moxaTableAddr[port]; if (ms100) { @@ -2759,7 +2734,7 @@ static void moxadelay(int tick) while (time_before(jiffies, et)); } -static void moxafunc(unsigned long ofsAddr, int cmd, ushort arg) +static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg) { writew(arg, ofsAddr + FuncArg); @@ -2767,7 +2742,7 @@ static void moxafunc(unsigned long ofsAddr, int cmd, ushort arg) wait_finish(ofsAddr); } -static void wait_finish(unsigned long ofsAddr) +static void wait_finish(void __iomem *ofsAddr) { unsigned long i, j; @@ -2780,7 +2755,7 @@ static void wait_finish(unsigned long ofsAddr) } } -static void low_water_check(unsigned long ofsAddr) +static void low_water_check(void __iomem *ofsAddr) { int len; ushort rptr, wptr, mask; @@ -2797,7 +2772,7 @@ static void low_water_check(unsigned long ofsAddr) static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) { - unsigned long baseAddr; + void __iomem *baseAddr; int i; if(copy_from_user(moxaBuff, tmp, len)) @@ -2815,7 +2790,7 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) static int moxafindcard(int cardno) { - unsigned long baseAddr; + void __iomem *baseAddr; ushort tmp; baseAddr = moxaBaseAddr[cardno]; @@ -2844,7 +2819,7 @@ static int moxafindcard(int cardno) static int moxaload320b(int cardno, unsigned char __user *tmp, int len) { - unsigned long baseAddr; + void __iomem *baseAddr; int i; if(len > sizeof(moxaBuff)) @@ -2864,7 +2839,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len) static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) { - unsigned long baseAddr, ofsAddr; + void __iomem *baseAddr, *ofsAddr; int retval, port, i; if(copy_from_user(moxaBuff, tmp, len)) @@ -2944,7 +2919,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) return (0); } -static int moxaloadc218(int cardno, unsigned long baseAddr, int len) +static int moxaloadc218(int cardno, void __iomem *baseAddr, int len) { char retry; int i, j, len1, len2; @@ -3020,7 +2995,7 @@ static int moxaloadc218(int cardno, unsigned long baseAddr, int len) return (0); } -static int moxaloadc320(int cardno, unsigned long baseAddr, int len, int *numPorts) +static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts) { ushort usum; int i, j, wlen, len2, retry; @@ -3125,7 +3100,7 @@ long MoxaPortGetCurBaud(int port) static void MoxaSetFifo(int port, int enable) { - unsigned long ofsAddr = moxaTableAddr[port]; + void __iomem *ofsAddr = moxaTableAddr[port]; if (!enable) { moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0); @@ -3139,7 +3114,7 @@ static void MoxaSetFifo(int port, int enable) #if 0 int MoxaPortSetMode(int port, int databits, int stopbits, int parity) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int val; val = 0; @@ -3198,7 +3173,7 @@ int MoxaPortSetMode(int port, int databits, int stopbits, int parity) int MoxaPortTxBufSize(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int size; ofsAddr = moxaTableAddr[port]; @@ -3208,7 +3183,7 @@ int MoxaPortTxBufSize(int port) int MoxaPortRxBufSize(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int size; ofsAddr = moxaTableAddr[port]; @@ -3218,7 +3193,7 @@ int MoxaPortRxBufSize(int port) int MoxaPortRxFree(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; @@ -3236,7 +3211,7 @@ int MoxaPortGetBrkCnt(int port) void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue) { - unsigned long ofsAddr; + void __iomem *ofsAddr; ofsAddr = moxaTableAddr[port]; writew(xonValue, ofsAddr + FuncArg); @@ -3247,7 +3222,7 @@ void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue) int MoxaPortIsTxHold(int port) { - unsigned long ofsAddr; + void __iomem *ofsAddr; int val; ofsAddr = moxaTableAddr[port]; diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c index 8832ed21d..0dee98b14 100644 --- a/drivers/char/mwave/3780i.c +++ b/drivers/char/mwave/3780i.c @@ -52,11 +52,11 @@ #include #include #include +#include #include #include #include #include -#include #include "smapi.h" #include "mwavedd.h" #include "3780i.h" diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index d4ba62a29..e46b66d9e 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1,8 +1,7 @@ -/*****************************************************************************/ /* - * mxser.c -- MOXA Smartio family multiport serial driver. + * mxser.c -- MOXA Smartio/Industio family multiport serial driver. * - * Copyright (C) 1999-2000 Moxa Technologies (support@moxa.com.tw). + * Copyright (C) 1999-2001 Moxa Technologies (support@moxa.com.tw). * * This code is loosely based on the Linux serial driver, written by * Linus Torvalds, Theodore T'so and others. @@ -10,7 +9,7 @@ * 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. +* (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 @@ -20,27 +19,27 @@ * 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. - */ - -/* - * MOXA Smartio Family Serial Driver * - * Copyright (C) 1999,2000 Moxa Technologies Co., LTD. + * Original release 10/26/00 * - * for : LINUX 2.0.X, 2.2.X, 2.4.X - * date : 2001/05/01 - * version : 1.2 - * - * Fixes for C104H/PCI by Tim Hockin - * Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards - * by Damian Wrobel + * 02/06/01 Support MOXA Industio family boards. + * 02/06/01 Support TIOCGICOUNT. + * 02/06/01 Fix the problem for connecting to serial mouse. + * 02/06/01 Fix the problem for H/W flow control. + * 02/06/01 Fix the compling warning when CONFIG_PCI + * don't be defined. * - * Added support for serial card CP104 - * by James Nelson Provident Solutions + * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox + * . The original 1.8 code is available on www.moxa.com. + * - Fixed x86_64 cleanness + * - Fixed sleep with spinlock held in mxser_send_break */ + #include #include +#include +#include #include #include #include @@ -54,182 +53,235 @@ #include #include #include +#include #include #include #include +#include #include -#include #include #include #include +#include #include #include -#define MXSER_VERSION "1.2.1" - -#define MXSERMAJOR 174 -#define MXSERCUMAJOR 175 +#include "mxser.h" +#define MXSER_VERSION "1.8" +#define MXSERMAJOR 174 +#define MXSERCUMAJOR 175 #define MXSER_EVENT_TXLOW 1 #define MXSER_EVENT_HANGUP 2 +#define MXSER_BOARDS 4 /* Max. boards */ +#define MXSER_PORTS 32 /* Max. ports */ +#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ +#define MXSER_ISR_PASS_LIMIT 256 -#define SERIAL_DO_RESTART - -#define MXSER_BOARDS 4 /* Max. boards */ -#define MXSER_PORTS 32 /* Max. ports */ -#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ -#define MXSER_ISR_PASS_LIMIT 256 - -#define MXSER_ERR_IOADDR -1 -#define MXSER_ERR_IRQ -2 -#define MXSER_ERR_IRQ_CONFLIT -3 -#define MXSER_ERR_VECTOR -4 - -#define SERIAL_TYPE_NORMAL 1 +#define MXSER_ERR_IOADDR -1 +#define MXSER_ERR_IRQ -2 +#define MXSER_ERR_IRQ_CONFLIT -3 +#define MXSER_ERR_VECTOR -4 -#define WAKEUP_CHARS 256 +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 -#define UART_MCR_AFE 0x20 -#define UART_LSR_SPECIAL 0x1E +#define WAKEUP_CHARS 256 -#define PORTNO(x) ((x)->index) +#define UART_MCR_AFE 0x20 +#define UART_LSR_SPECIAL 0x1E -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON|IXOFF)) #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -/* - * Define the Moxa PCI vendor and device IDs. - */ - -#ifndef PCI_VENDOR_ID_MOXA -#define PCI_VENDOR_ID_MOXA 0x1393 -#endif -#ifndef PCI_DEVICE_ID_C168 -#define PCI_DEVICE_ID_C168 0x1680 -#endif -#ifndef PCI_DEVICE_ID_C104 -#define PCI_DEVICE_ID_C104 0x1040 -#endif -#ifndef PCI_DEVICE_ID_CP104 -#define PCI_DEVICE_ID_CP104 0x1041 -#endif -#ifndef PCI_DEVICE_ID_CP132 -#define PCI_DEVICE_ID_CP132 0x1320 -#endif -#ifndef PCI_DEVICE_ID_CP114 -#define PCI_DEVICE_ID_CP114 0x1141 -#endif -#ifndef PCI_DEVICE_ID_CT114 -#define PCI_DEVICE_ID_CT114 0x1140 -#endif - #define C168_ASIC_ID 1 #define C104_ASIC_ID 2 -#define CI134_ASIC_ID 3 -#define CI132_ASIC_ID 4 -#define CI104J_ASIC_ID 5 #define C102_ASIC_ID 0xB +#define CI132_ASIC_ID 4 +#define CI134_ASIC_ID 3 +#define CI104J_ASIC_ID 5 enum { - MXSER_BOARD_C168_ISA = 0, + MXSER_BOARD_C168_ISA = 1, MXSER_BOARD_C104_ISA, MXSER_BOARD_CI104J, MXSER_BOARD_C168_PCI, MXSER_BOARD_C104_PCI, - MXSER_BOARD_CP104_PCI, MXSER_BOARD_C102_ISA, MXSER_BOARD_CI132, MXSER_BOARD_CI134, - MXSER_BOARD_CP132_PCI, - MXSER_BOARD_CP114_PCI, - MXSER_BOARD_CT114_PCI + MXSER_BOARD_CP132, + MXSER_BOARD_CP114, + MXSER_BOARD_CT114, + MXSER_BOARD_CP102, + MXSER_BOARD_CP104U, + MXSER_BOARD_CP168U, + MXSER_BOARD_CP132U, + MXSER_BOARD_CP134U, + MXSER_BOARD_CP104JU, + MXSER_BOARD_RC7000, + MXSER_BOARD_CP118U, + MXSER_BOARD_CP102UL, + MXSER_BOARD_CP102U, }; -static char *mxser_brdname[] = -{ +static char *mxser_brdname[] = { "C168 series", "C104 series", "CI-104J series", "C168H/PCI series", "C104H/PCI series", - "CP104/PCI series", "C102 series", "CI-132 series", "CI-134 series", "CP-132 series", "CP-114 series", - "CT-114 series" + "CT-114 series", + "CP-102 series", + "CP-104U series", + "CP-168U series", + "CP-132U series", + "CP-134U series", + "CP-104JU series", + "Moxa UC7000 Serial", + "CP-118U series", + "CP-102UL series", + "CP-102U series", }; -static int mxser_numports[] = -{ - 8, - 4, - 4, - 8, - 4, - 4, - 2, - 2, - 4, - 2, - 4, - 4 +static int mxser_numports[] = { + 8, // C168-ISA + 4, // C104-ISA + 4, // CI104J + 8, // C168-PCI + 4, // C104-PCI + 2, // C102-ISA + 2, // CI132 + 4, // CI134 + 2, // CP132 + 4, // CP114 + 4, // CT114 + 2, // CP102 + 4, // CP104U + 8, // CP168U + 2, // CP132U + 4, // CP134U + 4, // CP104JU + 8, // RC7000 + 8, // CP118U + 2, // CP102UL + 2, // CP102U +}; + +#define UART_TYPE_NUM 2 + +unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = { + MOXA_MUST_MU150_HWID, + MOXA_MUST_MU860_HWID +}; + +// This is only for PCI +#define UART_INFO_NUM 3 +struct mxpciuart_info { + int type; + int tx_fifo; + int rx_fifo; + int xmit_fifo_size; + int rx_high_water; + int rx_trigger; + int rx_low_water; + long max_baud; +}; + +struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = { + {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, + {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, + {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} }; -/* - * MOXA ioctls - */ -#define MOXA 0x400 -#define MOXA_GETDATACOUNT (MOXA + 23) -#define MOXA_GET_CONF (MOXA + 35) -#define MOXA_DIAGNOSE (MOXA + 50) -#define MOXA_CHKPORTENABLE (MOXA + 60) -#define MOXA_HighSpeedOn (MOXA + 61) -#define MOXA_GET_MAJOR (MOXA + 63) -#define MOXA_GET_CUMAJOR (MOXA + 64) -#define MOXA_GETMSTATUS (MOXA + 65) #ifdef CONFIG_PCI + static struct pci_device_id mxser_pcibrds[] = { - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_C168_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_C104_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_CP104_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_CP132_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_CP114_PCI }, - { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - MXSER_BOARD_CT114_PCI }, - { 0 } + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C168_PCI}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C104_PCI}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP114}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CT114}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104U}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP168U}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132U}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP134U}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104JU}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_RC7000}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP118U}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102UL}, + {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102U}, + {0} }; + MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -#endif /* CONFIG_PCI */ -static int ioaddr[MXSER_BOARDS]; + +#endif + +typedef struct _moxa_pci_info { + unsigned short busNum; + unsigned short devNum; + struct pci_dev *pdev; // add by Victor Yu. 06-23-2003 +} moxa_pci_info; + +static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; static int ttymajor = MXSERMAJOR; -static int verbose; +static int calloutmajor = MXSERCUMAJOR; +static int verbose = 0; /* Variables for insmod */ -MODULE_AUTHOR("William Chen"); -MODULE_DESCRIPTION("MOXA Smartio Family Multiport Board Device Driver"); -MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Casper Yang"); +MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); MODULE_PARM(ioaddr, "1-4i"); MODULE_PARM(ttymajor, "i"); +MODULE_PARM(calloutmajor, "i"); MODULE_PARM(verbose, "i"); +MODULE_LICENSE("GPL"); + +struct mxser_log { + int tick; + unsigned long rxcnt[MXSER_PORTS]; + unsigned long txcnt[MXSER_PORTS]; +}; + +struct mxser_mon { + unsigned long rxcnt; + unsigned long txcnt; + unsigned long up_rxcnt; + unsigned long up_txcnt; + int modem_status; + unsigned char hold_reason; +}; + +struct mxser_mon_ext { + unsigned long rx_cnt[32]; + unsigned long tx_cnt[32]; + unsigned long up_rxcnt[32]; + unsigned long up_txcnt[32]; + int modem_status[32]; + + long baudrate[32]; + int databits[32]; + int stopbits[32]; + int parity[32]; + int flowctrl[32]; + int fifo[32]; + int iftype[32]; +}; struct mxser_hwconf { int board_type; int ports; @@ -239,7 +291,10 @@ struct mxser_hwconf { int uart_type; int ioaddr[MXSER_PORTS_PER_BOARD]; int baud_base[MXSER_PORTS_PER_BOARD]; - struct pci_dev *pdev; + moxa_pci_info pciInfo; + int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002 + int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 09-04-2002 + int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 01-05-2004 }; struct mxser_struct { @@ -248,7 +303,9 @@ struct mxser_struct { int irq; /* port using irq no. */ int vector; /* port irq vector */ int vectormask; /* port vector mask */ + int rx_high_water; int rx_trigger; /* Rx fifo trigger level */ + int rx_low_water; int baud_base; /* max. speed */ int flags; /* defined in tty.h */ int type; /* UART type */ @@ -265,23 +322,31 @@ struct mxser_struct { unsigned long event; int count; /* # of fd on device */ int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ unsigned char *xmit_buf; int xmit_head; int xmit_tail; int xmit_cnt; struct work_struct tqueue; - int cflag; + struct termios normal_termios; + struct termios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; struct async_icount icount; /* kernel counters for the 4 input interrupts */ + int timeout; + int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002 + int MaxCanSetBaudRate; // add by Victor Yu. 09-04-2002 + int opmode_ioaddr; // add by Victor Yu. 01-05-2004 + unsigned char stop_rx; + unsigned char ldisc_stop_rx; + long realbaud; + struct mxser_mon mon_data; + unsigned char err_shadow; + spinlock_t slock; }; -struct mxser_log { - int tick; - int rxcnt[MXSER_PORTS]; - int txcnt[MXSER_PORTS]; -}; struct mxser_mstatus { tcflag_t cflag; @@ -293,49 +358,43 @@ struct mxser_mstatus { static struct mxser_mstatus GMStatus[MXSER_PORTS]; -static int mxserBoardCAP[MXSER_BOARDS] = -{ +static int mxserBoardCAP[MXSER_BOARDS] = { 0, 0, 0, 0 - /* 0x180, 0x280, 0x200, 0x320 */ + /* 0x180, 0x280, 0x200, 0x320 */ }; - static struct tty_driver *mxvar_sdriver; static struct mxser_struct mxvar_table[MXSER_PORTS]; +static struct tty_struct *mxvar_tty[MXSER_PORTS + 1]; +static struct termios *mxvar_termios[MXSER_PORTS + 1]; +static struct termios *mxvar_termios_locked[MXSER_PORTS + 1]; static struct mxser_log mxvar_log; static int mxvar_diagflag; -/* - * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need - * to lock it in case the memcpy_fromfs blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *mxvar_tmp_buf; -static struct semaphore mxvar_tmp_buf_sem; +static unsigned char mxser_msr[MXSER_PORTS + 1]; +static struct mxser_mon_ext mon_data_ext; +static int mxser_set_baud_method[MXSER_PORTS + 1]; +static spinlock_t gm_lock; /* * This is used to figure out the divisor speeds and the timeouts */ -static int mxvar_baud_table[] = -{ - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0}; -struct mxser_hwconf mxsercfg[MXSER_BOARDS]; +static struct mxser_hwconf mxsercfg[MXSER_BOARDS]; /* * static functions: */ static void mxser_getcfg(int board, struct mxser_hwconf *hwconf); +static int mxser_init(void); + +//static void mxser_poll(unsigned long); static int mxser_get_ISA_conf(int, struct mxser_hwconf *); +static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *); static void mxser_do_softint(void *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); -static int mxser_write(struct tty_struct *, int, const unsigned char *, int); +static int mxser_write(struct tty_struct *, const unsigned char *, int); static int mxser_write_room(struct tty_struct *); static void mxser_flush_buffer(struct tty_struct *); static int mxser_chars_in_buffer(struct tty_struct *); @@ -349,109 +408,218 @@ static void mxser_set_termios(struct tty_struct *, struct termios *); static void mxser_stop(struct tty_struct *); static void mxser_start(struct tty_struct *); static void mxser_hangup(struct tty_struct *); +static void mxser_rs_break(struct tty_struct *, int); static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *); -static inline void mxser_receive_chars(struct mxser_struct *, int *); -static inline void mxser_transmit_chars(struct mxser_struct *); -static inline void mxser_check_modem_status(struct mxser_struct *, int); +static void mxser_receive_chars(struct mxser_struct *, int *); +static void mxser_transmit_chars(struct mxser_struct *); +static void mxser_check_modem_status(struct mxser_struct *, int); static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); static int mxser_startup(struct mxser_struct *); static void mxser_shutdown(struct mxser_struct *); static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios); -static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); -static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); -static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); +static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *); +static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *); +static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *); static void mxser_send_break(struct mxser_struct *, int); static int mxser_tiocmget(struct tty_struct *, struct file *); static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); +static int mxser_set_baud(struct mxser_struct *info, long newspd); +static void mxser_wait_until_sent(struct tty_struct *tty, int timeout); + +static void mxser_startrx(struct tty_struct *tty); +static void mxser_stoprx(struct tty_struct *tty); + + +static int CheckIsMoxaMust(int io) +{ + u8 oldmcr, hwid; + int i; + + outb(0, io + UART_LCR); + DISABLE_MOXA_MUST_ENCHANCE_MODE(io); + oldmcr = inb(io + UART_MCR); + outb(0, io + UART_MCR); + SET_MOXA_MUST_XON1_VALUE(io, 0x11); + if ((hwid = inb(io + UART_MCR)) != 0) { + outb(oldmcr, io + UART_MCR); + return (MOXA_OTHER_UART); + } + + GET_MOXA_MUST_HARDWARE_ID(io, &hwid); + for (i = 0; i < UART_TYPE_NUM; i++) { + if (hwid == Gmoxa_uart_id[i]) + return (int) hwid; + } + return MOXA_OTHER_UART; +} + +// above is modified by Victor Yu. 08-15-2002 + +static struct tty_operations mxser_ops = { + .open = mxser_open, + .close = mxser_close, + .write = mxser_write, + .put_char = mxser_put_char, + .flush_chars = mxser_flush_chars, + .write_room = mxser_write_room, + .chars_in_buffer = mxser_chars_in_buffer, + .flush_buffer = mxser_flush_buffer, + .ioctl = mxser_ioctl, + .throttle = mxser_throttle, + .unthrottle = mxser_unthrottle, + .set_termios = mxser_set_termios, + .stop = mxser_stop, + .start = mxser_start, + .hangup = mxser_hangup, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, +}; /* - * The MOXA C168/C104 serial driver boot-time initialization code! + * The MOXA Smartio/Industio serial driver boot-time initialization code! */ +static int __init mxser_module_init(void) +{ + int ret; + + if (verbose) + printk(KERN_DEBUG "Loading module mxser ...\n"); + ret = mxser_init(); + if (verbose) + printk(KERN_DEBUG "Done.\n"); + return ret; +} + static void __exit mxser_module_exit(void) { int i, err = 0; - if (verbose) - printk("Unloading module mxser ...\n"); + printk(KERN_DEBUG "Unloading module mxser ...\n"); + if ((err |= tty_unregister_driver(mxvar_sdriver))) - printk("Couldn't unregister MOXA Smartio family serial driver\n"); - put_tty_driver(mxvar_sdriver); + printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n"); for (i = 0; i < MXSER_BOARDS; i++) { + struct pci_dev *pdev; + if (mxsercfg[i].board_type == -1) continue; else { + pdev = mxsercfg[i].pciInfo.pdev; free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); + if (pdev != NULL) { //PCI + release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); + } else { + release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports); + release_region(mxsercfg[i].vector, 1); + } } } - if (verbose) - printk("Done.\n"); + printk(KERN_DEBUG "Done.\n"); + +} +static void process_txrx_fifo(struct mxser_struct *info) +{ + int i; + + if ((info->type == PORT_16450) || (info->type == PORT_8250)) { + info->rx_trigger = 1; + info->rx_high_water = 1; + info->rx_low_water = 1; + info->xmit_fifo_size = 1; + } else { + for (i = 0; i < UART_INFO_NUM; i++) { + if (info->IsMoxaMustChipFlag == Gpci_uart_info[i].type) { + info->rx_trigger = Gpci_uart_info[i].rx_trigger; + info->rx_low_water = Gpci_uart_info[i].rx_low_water; + info->rx_high_water = Gpci_uart_info[i].rx_high_water; + info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; + break; + } + } + } } -int mxser_initbrd(int board, struct mxser_hwconf *hwconf) +static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) { struct mxser_struct *info; unsigned long flags; int retval; int i, n; - init_MUTEX(&mxvar_tmp_buf_sem); - n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; + /*if (verbose) */ { + printk(KERN_DEBUG " ttyM%d - ttyM%d ", n, n + hwconf->ports - 1); + printk(KERN_DEBUG " max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]); + } + for (i = 0; i < hwconf->ports; i++, n++, info++) { - if (verbose) { - printk(" ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]); - if (hwconf->baud_base[i] == 115200) - printk(" max. baud rate up to 115200 bps.\n"); - else - printk(" max. baud rate up to 921600 bps.\n"); - } info->port = n; info->base = hwconf->ioaddr[i]; info->irq = hwconf->irq; info->vector = hwconf->vector; info->vectormask = hwconf->vector_mask; - info->rx_trigger = 14; - info->baud_base = hwconf->baud_base[i]; + info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004 + info->stop_rx = 0; + info->ldisc_stop_rx = 0; + + info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag; + //Enhance mode enabled here + if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { + ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base); + } + info->flags = ASYNC_SHARE_IRQ; info->type = hwconf->uart_type; - if ((info->type == PORT_16450) || (info->type == PORT_8250)) - info->xmit_fifo_size = 1; - else - info->xmit_fifo_size = 16; + info->baud_base = hwconf->baud_base[i]; + + info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i]; + + process_txrx_fifo(info); + + info->custom_divisor = hwconf->baud_base[i] * 16; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; INIT_WORK(&info->tqueue, mxser_do_softint, info); - info->cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + info->normal_termios = mxvar_sdriver->init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); + memset(&info->mon_data, 0, sizeof(struct mxser_mon)); + info->err_shadow = 0; + spin_lock_init(&info->slock); } - /* * Allocate the IRQ if necessary */ - save_flags(flags); + + + /* before set INT ISR, disable all int */ + for (i = 0; i < hwconf->ports; i++) { + outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, hwconf->ioaddr[i] + UART_IER); + } n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; - cli(); - retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), - "mxser", info); + spin_lock_irqsave(&info->slock, flags); + retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), "mxser", info); if (retval) { - restore_flags(flags); - printk("Board %d: %s", board, mxser_brdname[hwconf->board_type]); + spin_unlock_irqrestore(&info->slock, flags); + printk(KERN_ERR "Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]); printk(" Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq); - return (retval); + return retval; } - restore_flags(flags); + + spin_unlock_irqrestore(&info->slock, flags); + return 0; } @@ -463,82 +631,131 @@ static void mxser_getcfg(int board, struct mxser_hwconf *hwconf) } #ifdef CONFIG_PCI -static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser_hwconf *hwconf) +static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf) { - int i; + int i, j; +// unsigned int val; unsigned int ioaddress; + struct pci_dev *pdev = hwconf->pciInfo.pdev; + //io address hwconf->board_type = board_type; - hwconf->ports = mxser_numports[board_type]; - ioaddress = pci_resource_start (pdev, 2); - for (i = 0; i < hwconf->ports; i++) + hwconf->ports = mxser_numports[board_type - 1]; + ioaddress = pci_resource_start(pdev, 2); + request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), "mxser(IO)"); + + for (i = 0; i < hwconf->ports; i++) { hwconf->ioaddr[i] = ioaddress + 8 * i; + } - ioaddress = pci_resource_start (pdev, 3); + //vector + ioaddress = pci_resource_start(pdev, 3); + request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), "mxser(vector)"); hwconf->vector = ioaddress; - hwconf->irq = pdev->irq; + //irq + hwconf->irq = hwconf->pciInfo.pdev->irq; + hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]); hwconf->uart_type = PORT_16550A; hwconf->vector_mask = 0; + + + for (i = 0; i < hwconf->ports; i++) { + for (j = 0; j < UART_INFO_NUM; j++) { + if (Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) { + hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud; + + //exception....CP-102 + if (board_type == MXSER_BOARD_CP102) + hwconf->MaxCanSetBaudRate[i] = 921600; + break; + } + } + } + + if (hwconf->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID) { + for (i = 0; i < hwconf->ports; i++) { + if (i < 4) + hwconf->opmode_ioaddr[i] = ioaddress + 4; + else + hwconf->opmode_ioaddr[i] = ioaddress + 0x0c; + } + outb(0, ioaddress + 4); // default set to RS232 mode + outb(0, ioaddress + 0x0c); //default set to RS232 mode + } + for (i = 0; i < hwconf->ports; i++) { hwconf->vector_mask |= (1 << i); hwconf->baud_base[i] = 921600; } return (0); } -#endif /* CONFIG_PCI */ - -static struct tty_operations mxser_ops = { - .open = mxser_open, - .close = mxser_close, - .write = mxser_write, - .put_char = mxser_put_char, - .flush_chars = mxser_flush_chars, - .write_room = mxser_write_room, - .chars_in_buffer = mxser_chars_in_buffer, - .flush_buffer = mxser_flush_buffer, - .ioctl = mxser_ioctl, - .throttle = mxser_throttle, - .unthrottle = mxser_unthrottle, - .set_termios = mxser_set_termios, - .stop = mxser_stop, - .start = mxser_start, - .hangup = mxser_hangup, - .tiocmget = mxser_tiocmget, - .tiocmset = mxser_tiocmset, -}; +#endif -static int __init mxser_module_init(void) +static int mxser_init(void) { - int i, m, retval, b; + int i, m, retval, b, n; + int ret1; + struct pci_dev *pdev = NULL; + int index; + unsigned char busnum, devnum; struct mxser_hwconf hwconf; mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); if (!mxvar_sdriver) return -ENOMEM; + spin_lock_init(&gm_lock); + + for (i = 0; i < MXSER_BOARDS; i++) { + mxsercfg[i].board_type = -1; + } - printk("MOXA Smartio family driver version %s\n", MXSER_VERSION); + printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", MXSER_VERSION); /* Initialize the tty_driver structure */ - - mxvar_sdriver->owner = THIS_MODULE; + memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); + mxvar_sdriver->magic = TTY_DRIVER_MAGIC; mxvar_sdriver->name = "ttyM"; - mxvar_sdriver->devfs_name = "tts/M"; mxvar_sdriver->major = ttymajor; mxvar_sdriver->minor_start = 0; + mxvar_sdriver->num = MXSER_PORTS + 1; mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; mxvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mxvar_sdriver, &mxser_ops); - printk("Tty devices major number = %d\n", ttymajor); + mxvar_sdriver->ttys = mxvar_tty; + mxvar_sdriver->termios = mxvar_termios; + mxvar_sdriver->termios_locked = mxvar_termios_locked; + + mxvar_sdriver->open = mxser_open; + mxvar_sdriver->close = mxser_close; + mxvar_sdriver->write = mxser_write; + mxvar_sdriver->put_char = mxser_put_char; + mxvar_sdriver->flush_chars = mxser_flush_chars; + mxvar_sdriver->write_room = mxser_write_room; + mxvar_sdriver->chars_in_buffer = mxser_chars_in_buffer; + mxvar_sdriver->flush_buffer = mxser_flush_buffer; + mxvar_sdriver->ioctl = mxser_ioctl; + mxvar_sdriver->throttle = mxser_throttle; + mxvar_sdriver->unthrottle = mxser_unthrottle; + mxvar_sdriver->set_termios = mxser_set_termios; + mxvar_sdriver->stop = mxser_stop; + mxvar_sdriver->start = mxser_start; + mxvar_sdriver->hangup = mxser_hangup; + mxvar_sdriver->break_ctl = mxser_rs_break; + mxvar_sdriver->wait_until_sent = mxser_wait_until_sent; mxvar_diagflag = 0; memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct)); memset(&mxvar_log, 0, sizeof(struct mxser_log)); + memset(&mxser_msr, 0, sizeof(unsigned char) * (MXSER_PORTS + 1)); + memset(&mon_data_ext, 0, sizeof(struct mxser_mon_ext)); + memset(&mxser_set_baud_method, 0, sizeof(int) * (MXSER_PORTS + 1)); + memset(&hwconf, 0, sizeof(struct mxser_hwconf)); m = 0; /* Start finding ISA boards here */ @@ -550,28 +767,31 @@ static int __init mxser_module_init(void) retval = mxser_get_ISA_conf(cap, &hwconf); if (retval != 0) - printk("Found MOXA %s board (CAP=0x%x)\n", - mxser_brdname[hwconf.board_type], - ioaddr[b]); + printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]); if (retval <= 0) { if (retval == MXSER_ERR_IRQ) - printk("Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk("Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); else if (retval == MXSER_ERR_VECTOR) - printk("Invalid interrupt vector,board not configured\n"); + printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); else if (retval == MXSER_ERR_IOADDR) - printk("Invalid I/O address,board not configured\n"); + printk(KERN_ERR "Invalid I/O address,board not configured\n"); continue; } - hwconf.pdev = NULL; + hwconf.pciInfo.busNum = 0; + hwconf.pciInfo.devNum = 0; + hwconf.pciInfo.pdev = NULL; + + mxser_getcfg(m, &hwconf); + //init mxsercfg first, or mxsercfg data is not correct on ISR. + //mxser_initbrd will hook ISR. if (mxser_initbrd(m, &hwconf) < 0) continue; - mxser_getcfg(m, &hwconf); m++; } @@ -585,89 +805,97 @@ static int __init mxser_module_init(void) retval = mxser_get_ISA_conf(cap, &hwconf); if (retval != 0) - printk("Found MOXA %s board (CAP=0x%x)\n", - mxser_brdname[hwconf.board_type], - ioaddr[b]); + printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]); if (retval <= 0) { if (retval == MXSER_ERR_IRQ) - printk("Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk("Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); else if (retval == MXSER_ERR_VECTOR) - printk("Invalid interrupt vector,board not configured\n"); + printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); else if (retval == MXSER_ERR_IOADDR) - printk("Invalid I/O address,board not configured\n"); + printk(KERN_ERR "Invalid I/O address,board not configured\n"); continue; } - hwconf.pdev = NULL; - if (mxser_initbrd(m, &hwconf) < 0) - continue; + hwconf.pciInfo.busNum = 0; + hwconf.pciInfo.devNum = 0; + hwconf.pciInfo.pdev = NULL; mxser_getcfg(m, &hwconf); + //init mxsercfg first, or mxsercfg data is not correct on ISR. + //mxser_initbrd will hook ISR. + if (mxser_initbrd(m, &hwconf) < 0) + continue; m++; } /* start finding PCI board here */ - -#ifdef CONFIG_PCI - { - struct pci_dev *pdev = NULL; - int n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1; - for (b = 0; b < n; b++) { - while ((pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev))) - { - if (pci_enable_device(pdev)) - continue; - hwconf.pdev = pdev; - printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n", - mxser_brdname[mxser_pcibrds[b].driver_data], - pdev->bus->number, PCI_SLOT(pdev->devfn)); - if (m >= MXSER_BOARDS) { - printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS); - } else { - retval = mxser_get_PCI_conf(pdev, mxser_pcibrds[b].driver_data, &hwconf); - if (retval < 0) { - if (retval == MXSER_ERR_IRQ) - printk("Invalid interrupt number,board not configured\n"); - else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk("Invalid interrupt number,board not configured\n"); - else if (retval == MXSER_ERR_VECTOR) - printk("Invalid interrupt vector,board not configured\n"); - else if (retval == MXSER_ERR_IOADDR) - printk("Invalid I/O address,board not configured\n"); - continue; - } - if (mxser_initbrd(m, &hwconf) < 0) - continue; - mxser_getcfg(m, &hwconf); - m++; - } + n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1; + index = 0; + b = 0; + while (b < n) { + pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev); + if (pdev == NULL) { + b++; + continue; + } + hwconf.pciInfo.busNum = busnum = pdev->bus->number; + hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn) << 3; + hwconf.pciInfo.pdev = pdev; + printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], busnum, devnum >> 3); + index++; + if (m >= MXSER_BOARDS) { + printk(KERN_ERR "Too many Smartio/Industio family boards find (maximum %d),board not configured\n", MXSER_BOARDS); + } else { + if (pci_enable_device(pdev)) { + printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + continue; + } + retval = mxser_get_PCI_conf(busnum, devnum, (int) mxser_pcibrds[b].driver_data, &hwconf); + if (retval < 0) { + if (retval == MXSER_ERR_IRQ) + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + else if (retval == MXSER_ERR_IRQ_CONFLIT) + printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + else if (retval == MXSER_ERR_VECTOR) + printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); + else if (retval == MXSER_ERR_IOADDR) + printk(KERN_ERR "Invalid I/O address,board not configured\n"); + continue; } + mxser_getcfg(m, &hwconf); + //init mxsercfg first, or mxsercfg data is not correct on ISR. + //mxser_initbrd will hook ISR. + if (mxser_initbrd(m, &hwconf) < 0) + continue; + m++; } } -#endif - - for (i = m; i < MXSER_BOARDS; i++) { - mxsercfg[i].board_type = -1; - } - - if (!tty_register_driver(mxvar_sdriver)) + ret1 = 0; + if (!(ret1 = tty_register_driver(mxvar_sdriver))) { return 0; + } else + printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n"); - put_tty_driver(mxvar_sdriver); - printk("Couldn't install MOXA Smartio family driver !\n"); - for (i = 0; i < MXSER_BOARDS; i++) { - if (mxsercfg[i].board_type == -1) - continue; - free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); + if (ret1) { + for (i = 0; i < MXSER_BOARDS; i++) { + if (mxsercfg[i].board_type == -1) + continue; + else { + free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); + //todo: release io, vector + } + } + return -1; } - return -1; + + return (0); } static void mxser_do_softint(void *private_) @@ -676,54 +904,52 @@ static void mxser_do_softint(void *private_) struct tty_struct *tty; tty = info->tty; + if (tty) { - if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); - } - if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) { - tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - } + if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) + tty_wakeup(tty); + if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) + tty_hangup(tty); } } +static unsigned char mxser_get_msr(int baseaddr, int mode, int port, struct mxser_struct *info) +{ + unsigned char status = 0; + + status = inb(baseaddr + UART_MSR); + + mxser_msr[port] &= 0x0F; + mxser_msr[port] |= status; + status = mxser_msr[port]; + if (mode) + mxser_msr[port] = 0; + + return status; +} + /* * This routine is called whenever a serial port is opened. It * enables interrupts for a serial port, linking in its async structure into * the IRQ chain. It also performs the serial-specific * initialization for the tty structure. */ - static int mxser_open(struct tty_struct *tty, struct file *filp) { struct mxser_struct *info; int retval, line; - unsigned long page; - line = PORTNO(tty); + line = tty->index; if (line == MXSER_PORTS) - return (0); - if ((line < 0) || (line > MXSER_PORTS)) - return (-ENODEV); + return 0; + if (line < 0 || line > MXSER_PORTS) + return -ENODEV; info = mxvar_table + line; if (!info->base) return (-ENODEV); - info->count++; tty->driver_data = info; info->tty = tty; - - if (!mxvar_tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return (-ENOMEM); - if (mxvar_tmp_buf) - free_page(page); - else - mxvar_tmp_buf = (unsigned char *) page; - } /* * Start up serial port */ @@ -731,7 +957,31 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) if (retval) return (retval); - return mxser_block_til_ready(tty, filp, info); + retval = mxser_block_til_ready(tty, filp, info); + if (retval) + return (retval); + + info->count++; + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver->subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + mxser_change_speed(info, 0); + } + + info->session = current->signal->session; + info->pgrp = process_group(current); + clear_bit(TTY_DONT_FLIP, &tty->flags); + + //status = mxser_get_msr(info->base, 0, info->port); + //mxser_check_modem_status(info, status); + +/* unmark here for very high baud rate (ex. 921600 bps) used +*/ + tty->low_latency = 1; + return 0; } /* @@ -740,48 +990,52 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) * async structure from the interrupt chain if necessary, and we free * that IRQ if nothing is left in the chain. */ - static void mxser_close(struct tty_struct *tty, struct file *filp) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - unsigned long flags; + unsigned long timeout; + unsigned long flags; + struct tty_ldisc *ld; - if (PORTNO(tty) == MXSER_PORTS) + if (tty->index == MXSER_PORTS) return; if (!info) - return; + BUG(); - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); if (tty_hung_up_p(filp)) { - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); return; } if ((tty->count == 1) && (info->count != 1)) { /* - * Uh, oh. tty->count is 1, which means that the tty + * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ - printk("mxser_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); + printk(KERN_ERR "mxser_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count); info->count = 1; } if (--info->count < 0) { - printk("mxser_close: bad serial port count for ttys%d: %d\n", - info->port, info->count); + printk(KERN_ERR "mxser_close: bad serial port count for ttys%d: %d\n", info->port, info->count); info->count = 0; } if (info->count) { - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); return; } info->flags |= ASYNC_CLOSING; - info->cflag = tty->termios->c_cflag; + spin_unlock_irqrestore(&info->slock, flags); + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -796,9 +1050,11 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) * line status register. */ info->IER &= ~UART_IER_RLSI; - /* by William - info->read_status_mask &= ~UART_LSR_DR; - */ + if (info->IsMoxaMustChipFlag) + info->IER &= ~MOXA_MUST_RECV_ISR; +/* by William + info->read_status_mask &= ~UART_LSR_DR; +*/ if (info->flags & ASYNC_INITIALIZED) { outb(info->IER, info->base + UART_IER); /* @@ -815,13 +1071,20 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) } } mxser_shutdown(info); + if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + ld = tty_ldisc_ref(tty); + if (ld) { + if(ld->flush_buffer) + ld->flush_buffer(tty); + tty_ldisc_deref(ld); + } + tty->closing = 0; info->event = 0; - info->tty = NULL; + info->tty = 0; if (info->blocked_open) { if (info->close_delay) { set_current_state(TASK_INTERRUPTIBLE); @@ -829,80 +1092,47 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) } wake_up_interruptible(&info->open_wait); } + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - restore_flags(flags); } -static int mxser_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, total = 0; struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned long flags; - if (!tty || !info->xmit_buf || !mxvar_tmp_buf) + if (!tty || !info->xmit_buf) return (0); - save_flags(flags); - if (from_user) { - down(&mxvar_tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(mxvar_tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } + while (1) { + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; - restore_flags(flags); - - buf += c; - count -= c; - total += c; - } - up(&mxvar_tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + spin_lock_irqsave(&info->slock, flags); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->slock, flags); - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); - info->xmit_cnt += c; - restore_flags(flags); + buf += c; + count -= c; + total += c; - buf += c; - count -= c; - total += c; - } } - cli(); - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - outb(info->IER, info->base + UART_IER); + if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { + if (!tty->hw_stopped || (info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) { + spin_lock_irqsave(&info->slock, flags); + info->IER |= UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } } - restore_flags(flags); - return (total); + return total; } static void mxser_put_char(struct tty_struct *tty, unsigned char ch) @@ -913,39 +1143,39 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch) if (!tty || !info->xmit_buf) return; - save_flags(flags); - cli(); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - restore_flags(flags); + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) return; - } + + spin_lock_irqsave(&info->slock, flags); info->xmit_buf[info->xmit_head++] = ch; info->xmit_head &= SERIAL_XMIT_SIZE - 1; info->xmit_cnt++; - /********************************************** why ??? *********** - if ( !tty->stopped && !tty->hw_stopped && - !(info->IER & UART_IER_THRI) ) { - info->IER |= UART_IER_THRI; - outb(info->IER, info->base + UART_IER); - } - *****************************************************************/ - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); + if (!tty->stopped && !(info->IER & UART_IER_THRI)) { + if (!tty->hw_stopped || (info->type == PORT_16550A) || info->IsMoxaMustChipFlag) { + spin_lock_irqsave(&info->slock, flags); + info->IER |= UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } } + static void mxser_flush_chars(struct tty_struct *tty) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned long flags; - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) + if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf || (tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) return; - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); + info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); - restore_flags(flags); + + spin_unlock_irqrestore(&info->slock, flags); } static int mxser_write_room(struct tty_struct *tty) @@ -962,40 +1192,75 @@ static int mxser_write_room(struct tty_struct *tty) static int mxser_chars_in_buffer(struct tty_struct *tty) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - - return (info->xmit_cnt); + return info->xmit_cnt; } static void mxser_flush_buffer(struct tty_struct *tty) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + char fcr; unsigned long flags; - save_flags(flags); - cli(); + + spin_lock_irqsave(&info->slock, flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - restore_flags(flags); + + /* below added by shinhay */ + fcr = inb(info->base + UART_FCR); + outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + outb(fcr, info->base + UART_FCR); + + spin_unlock_irqrestore(&info->slock, flags); + /* above added by shinhay */ + wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup) (tty); } -static int mxser_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long flags; struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; int retval; struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; + struct serial_icounter_struct *p_cuser; /* user space */ unsigned long templ; - void __user *argp = (void __user *)arg; + unsigned long flags; - if (PORTNO(tty) == MXSER_PORTS) + if (tty->index == MXSER_PORTS) return (mxser_ioctl_special(cmd, arg)); - if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && - (cmd != TIOCGICOUNT)) { + + // following add by Victor Yu. 01-05-2004 + if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { + int opmode, p; + static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; + int shiftbit; + unsigned char val, mask; + + p = info->port % 4; + if (cmd == MOXA_SET_OP_MODE) { + if (get_user(opmode, (int *) arg)) + return -EFAULT; + if (opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE) + return -EFAULT; + mask = ModeMask[p]; + shiftbit = p * 2; + val = inb(info->opmode_ioaddr); + val &= mask; + val |= (opmode << shiftbit); + outb(val, info->opmode_ioaddr); + } else { + shiftbit = p * 2; + opmode = inb(info->opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + if (copy_to_user((int *) arg, &opmode, sizeof(int))) + return -EFAULT; + } + return 0; + } + // above add by Victor Yu. 01-05-2004 + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return (-EIO); } @@ -1006,7 +1271,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return (retval); tty_wait_until_sent(tty, 0); if (!arg) - mxser_send_break(info, HZ / 4); /* 1/4 second */ + mxser_send_break(info, HZ / 4); /* 1/4 second */ return (0); case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); @@ -1016,50 +1281,53 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); return (0); case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); case TIOCSSOFTCAR: - if(get_user(templ, (unsigned long __user *) arg)) + if (get_user(templ, (unsigned long *) arg)) return -EFAULT; arg = templ; - tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return (0); case TIOCGSERIAL: - return mxser_get_serial_info(info, argp); + return (mxser_get_serial_info(info, (struct serial_struct *) arg)); case TIOCSSERIAL: - return mxser_set_serial_info(info, argp); + return (mxser_set_serial_info(info, (struct serial_struct *) arg)); case TIOCSERGETLSR: /* Get line status register */ - return mxser_get_lsr_info(info, argp); + return (mxser_get_lsr_info(info, (unsigned int *) arg)); /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change * - mask passed in arg for lines of interest * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) * Caller should use TIOCGICOUNT to see which one it was */ - case TIOCMIWAIT: - save_flags(flags); - cli(); - cprev = info->icount; /* note the counters on entry */ - restore_flags(flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return (-ERESTARTSYS); - save_flags(flags); - cli(); - cnow = info->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return (-EIO); /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return (0); + case TIOCMIWAIT:{ + DECLARE_WAITQUEUE(wait, current); + int ret; + spin_lock_irqsave(&info->slock, flags); + cprev = info->icount; /* note the counters on entry */ + spin_unlock_irqrestore(&info->slock, flags); + + add_wait_queue(&info->delta_msr_wait, &wait); + while (1) { + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; /* atomic copy */ + spin_unlock_irqrestore(&info->slock, flags); + + set_current_state(TASK_INTERRUPTIBLE); + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + ret = 0; + break; + } + /* see if a signal did it */ + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + cprev = cnow; } - cprev = cnow; + current->state = TASK_RUNNING; + remove_wait_queue(&info->delta_msr_wait, &wait); + break; } /* NOTREACHED */ /* @@ -1069,45 +1337,139 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, * RI where only 0->1 is counted. */ case TIOCGICOUNT: - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); cnow = info->icount; - restore_flags(flags); - p_cuser = argp; - if(put_user(cnow.cts, &p_cuser->cts)) + spin_unlock_irqrestore(&info->slock, flags); + p_cuser = (struct serial_icounter_struct *) arg; + /* modified by casper 1/11/2000 */ + if (put_user(cnow.frame, &p_cuser->frame)) + return -EFAULT; + if (put_user(cnow.brk, &p_cuser->brk)) + return -EFAULT; + if (put_user(cnow.overrun, &p_cuser->overrun)) + return -EFAULT; + if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) return -EFAULT; - if(put_user(cnow.dsr, &p_cuser->dsr)) + if (put_user(cnow.parity, &p_cuser->parity)) return -EFAULT; - if(put_user(cnow.rng, &p_cuser->rng)) + if (put_user(cnow.rx, &p_cuser->rx)) return -EFAULT; - return put_user(cnow.dcd, &p_cuser->dcd); + if (put_user(cnow.tx, &p_cuser->tx)) + return -EFAULT; + put_user(cnow.cts, &p_cuser->cts); + put_user(cnow.dsr, &p_cuser->dsr); + put_user(cnow.rng, &p_cuser->rng); + put_user(cnow.dcd, &p_cuser->dcd); + +/* */ + return 0; case MOXA_HighSpeedOn: - return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + return put_user(info->baud_base != 115200 ? 1 : 0, (int *) arg); + + case MOXA_SDS_RSTICOUNTER:{ + info->mon_data.rxcnt = 0; + info->mon_data.txcnt = 0; + return 0; + } +// (above) added by James. + case MOXA_ASPP_SETBAUD:{ + long baud; + if (get_user(baud, (long *) arg)) + return -EFAULT; + mxser_set_baud(info, baud); + return 0; + } + case MOXA_ASPP_GETBAUD: + if (copy_to_user((long *) arg, &info->realbaud, sizeof(long))) + return -EFAULT; + + return 0; + + case MOXA_ASPP_OQUEUE:{ + int len, lsr; + + len = mxser_chars_in_buffer(tty); + + lsr = inb(info->base + UART_LSR) & UART_LSR_TEMT; + + len += (lsr ? 0 : 1); + + if (copy_to_user((int *) arg, &len, sizeof(int))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_MON:{ + int mcr, status; +// info->mon_data.ser_param = tty->termios->c_cflag; + + status = mxser_get_msr(info->base, 1, info->port, info); + mxser_check_modem_status(info, status); + + mcr = inb(info->base + UART_MCR); + if (mcr & MOXA_MUST_MCR_XON_FLAG) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; + + if (mcr & MOXA_MUST_MCR_TX_XON) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; + + if (info->tty->hw_stopped) + info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; + else + info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; + + + if (copy_to_user((struct mxser_mon *) arg, &(info->mon_data), sizeof(struct mxser_mon))) + return -EFAULT; + + return 0; + + } + + case MOXA_ASPP_LSTATUS:{ + if (copy_to_user((struct mxser_mon *) arg, &(info->err_shadow), sizeof(unsigned char))) + return -EFAULT; + + info->err_shadow = 0; + return 0; + + } + case MOXA_SET_BAUD_METHOD:{ + int method; + if (get_user(method, (int *) arg)) + return -EFAULT; + mxser_set_baud_method[info->port] = method; + if (copy_to_user((int *) arg, &method, sizeof(int))) + return -EFAULT; + + return 0; + } default: - return (-ENOIOCTLCMD); + return -ENOIOCTLCMD; } - return (0); + return 0; } static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) { int i, result, status; - void __user *argp = (void __user *)arg; switch (cmd) { case MOXA_GET_CONF: - if(copy_to_user(argp, mxsercfg, - sizeof(struct mxser_hwconf) * 4)) - return -EFAULT; + if (copy_to_user((struct mxser_hwconf *) arg, mxsercfg, sizeof(struct mxser_hwconf) * 4)) + return -EFAULT; return 0; case MOXA_GET_MAJOR: - if(copy_to_user(argp, &ttymajor, sizeof(int))) + if (copy_to_user((int *) arg, &ttymajor, sizeof(int))) return -EFAULT; return 0; case MOXA_GET_CUMAJOR: - result = 0; - if(copy_to_user(argp, &result, sizeof(int))) + if (copy_to_user((int *) arg, &calloutmajor, sizeof(int))) return -EFAULT; return 0; @@ -1117,9 +1479,9 @@ static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) if (mxvar_table[i].base) result |= (1 << i); } - return put_user(result, (unsigned long __user *) argp); + return put_user(result, (unsigned long *) arg); case MOXA_GETDATACOUNT: - if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) + if (copy_to_user((struct mxser_log *) arg, &mxvar_log, sizeof(mxvar_log))) return -EFAULT; return (0); case MOXA_GETMSTATUS: @@ -1131,8 +1493,9 @@ static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) GMStatus[i].cts = 0; continue; } + if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios) - GMStatus[i].cflag = mxvar_table[i].cflag; + GMStatus[i].cflag = mxvar_table[i].normal_termios.c_cflag; else GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag; @@ -1153,105 +1516,207 @@ static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) else GMStatus[i].cts = 0; } - if(copy_to_user(argp, GMStatus, - sizeof(struct mxser_mstatus) * MXSER_PORTS)) + if (copy_to_user((struct mxser_mstatus *) arg, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS)) return -EFAULT; return 0; + case MOXA_ASPP_MON_EXT:{ + int status; + int opmode, p; + int shiftbit; + unsigned cflag, iflag; + + for (i = 0; i < MXSER_PORTS; i++) { + + if (!mxvar_table[i].base) + continue; + + status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i])); +// mxser_check_modem_status(&mxvar_table[i], status); + if (status & UART_MSR_TERI) + mxvar_table[i].icount.rng++; + if (status & UART_MSR_DDSR) + mxvar_table[i].icount.dsr++; + if (status & UART_MSR_DDCD) + mxvar_table[i].icount.dcd++; + if (status & UART_MSR_DCTS) + mxvar_table[i].icount.cts++; + + mxvar_table[i].mon_data.modem_status = status; + mon_data_ext.rx_cnt[i] = mxvar_table[i].mon_data.rxcnt; + mon_data_ext.tx_cnt[i] = mxvar_table[i].mon_data.txcnt; + mon_data_ext.up_rxcnt[i] = mxvar_table[i].mon_data.up_rxcnt; + mon_data_ext.up_txcnt[i] = mxvar_table[i].mon_data.up_txcnt; + mon_data_ext.modem_status[i] = mxvar_table[i].mon_data.modem_status; + mon_data_ext.baudrate[i] = mxvar_table[i].realbaud; + + if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios) { + cflag = mxvar_table[i].normal_termios.c_cflag; + iflag = mxvar_table[i].normal_termios.c_iflag; + } else { + cflag = mxvar_table[i].tty->termios->c_cflag; + iflag = mxvar_table[i].tty->termios->c_iflag; + } + + mon_data_ext.databits[i] = cflag & CSIZE; + + mon_data_ext.stopbits[i] = cflag & CSTOPB; + + mon_data_ext.parity[i] = cflag & (PARENB | PARODD | CMSPAR); + + mon_data_ext.flowctrl[i] = 0x00; + + if (cflag & CRTSCTS) + mon_data_ext.flowctrl[i] |= 0x03; + + if (iflag & (IXON | IXOFF)) + mon_data_ext.flowctrl[i] |= 0x0C; + + if (mxvar_table[i].type == PORT_16550A) + mon_data_ext.fifo[i] = 1; + else + mon_data_ext.fifo[i] = 0; + + p = i % 4; + shiftbit = p * 2; + opmode = inb(mxvar_table[i].opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + + mon_data_ext.iftype[i] = opmode; + + } + if (copy_to_user((struct mxser_mon_ext *) arg, &mon_data_ext, sizeof(struct mxser_mon_ext))) + return -EFAULT; + + return 0; + + } default: - return (-ENOIOCTLCMD); + return -ENOIOCTLCMD; } - return (0); + return 0; } -/* - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - */ -static void mxser_throttle(struct tty_struct *tty) + +static void mxser_stoprx(struct tty_struct *tty) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - unsigned long flags; + //unsigned long flags; + + info->ldisc_stop_rx = 1; if (I_IXOFF(tty)) { - info->x_char = STOP_CHAR(tty); - save_flags(flags); - cli(); - outb(info->IER, 0); - info->IER |= UART_IER_THRI; - outb(info->IER, info->base + UART_IER); /* force Tx interrupt */ - restore_flags(flags); + + //MX_LOCK(&info->slock); + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag) { + info->IER &= ~MOXA_MUST_RECV_ISR; + outb(info->IER, info->base + UART_IER); + } else { + // above add by Victor Yu. 09-02-2002 + + info->x_char = STOP_CHAR(tty); + // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 + outb(0, info->base + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->base + UART_IER); /* force Tx interrupt */ + } // add by Victor Yu. 09-02-2002 + //MX_UNLOCK(&info->slock); } + if (info->tty->termios->c_cflag & CRTSCTS) { + //MX_LOCK(&info->slock); info->MCR &= ~UART_MCR_RTS; - save_flags(flags); - cli(); outb(info->MCR, info->base + UART_MCR); - restore_flags(flags); + //MX_UNLOCK(&info->slock); } } -static void mxser_unthrottle(struct tty_struct *tty) +static void mxser_startrx(struct tty_struct *tty) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - unsigned long flags; + //unsigned long flags; + info->ldisc_stop_rx = 0; if (I_IXOFF(tty)) { if (info->x_char) info->x_char = 0; else { - info->x_char = START_CHAR(tty); - save_flags(flags); - cli(); - outb(info->IER, 0); - info->IER |= UART_IER_THRI; /* force Tx interrupt */ - outb(info->IER, info->base + UART_IER); - restore_flags(flags); + //MX_LOCK(&info->slock); + + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag) { + info->IER |= MOXA_MUST_RECV_ISR; + outb(info->IER, info->base + UART_IER); + } else { + // above add by Victor Yu. 09-02-2002 + + info->x_char = START_CHAR(tty); + // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 + outb(0, info->base + UART_IER); // add by Victor Yu. 09-02-2002 + info->IER |= UART_IER_THRI; /* force Tx interrupt */ + outb(info->IER, info->base + UART_IER); + } // add by Victor Yu. 09-02-2002 + //MX_UNLOCK(&info->slock); } } + if (info->tty->termios->c_cflag & CRTSCTS) { + //MX_LOCK(&info->slock); info->MCR |= UART_MCR_RTS; - save_flags(flags); - cli(); outb(info->MCR, info->base + UART_MCR); - restore_flags(flags); + //MX_UNLOCK(&info->slock); } } -static void mxser_set_termios(struct tty_struct *tty, - struct termios *old_termios) +/* + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + */ +static void mxser_throttle(struct tty_struct *tty) +{ + //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; + //unsigned long flags; + //MX_LOCK(&info->slock); + mxser_stoprx(tty); + //MX_UNLOCK(&info->slock); +} + +static void mxser_unthrottle(struct tty_struct *tty) +{ + //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; + //unsigned long flags; + //MX_LOCK(&info->slock); + mxser_startrx(tty); + //MX_UNLOCK(&info->slock); +} + +static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + unsigned long flags; -/* 8-2-99 by William - if ( (tty->termios->c_cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(tty->termios->c_iflag) == - RELEVANT_IFLAG(old_termios->c_iflag)) ) - return; - - mxser_change_speed(info, old_termios); - - if ( (old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS) ) { - tty->hw_stopped = 0; - mxser_start(tty); - } - */ - if ((tty->termios->c_cflag != old_termios->c_cflag) || - (RELEVANT_IFLAG(tty->termios->c_iflag) != - RELEVANT_IFLAG(old_termios->c_iflag))) { + if ((tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { mxser_change_speed(info, old_termios); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; mxser_start(tty); } } + /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && - !(tty->termios->c_iflag & IXON)) { + if ((old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON)) { tty->stopped = 0; + + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag) { + spin_lock_irqsave(&info->slock, flags); + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); + spin_unlock_irqrestore(&info->slock, flags); + } + // above add by Victor Yu. 09-02-2002 + mxser_start(tty); } } @@ -1267,13 +1732,12 @@ static void mxser_stop(struct tty_struct *tty) struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); if (info->IER & UART_IER_THRI) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); } - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); } static void mxser_start(struct tty_struct *tty) @@ -1281,16 +1745,78 @@ static void mxser_start(struct tty_struct *tty) struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned long flags; - save_flags(flags); - cli(); - if (info->xmit_cnt && info->xmit_buf && - !(info->IER & UART_IER_THRI)) { + spin_lock_irqsave(&info->slock, flags); + if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); } - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); +} + +/* + * mxser_wait_until_sent() --- wait until the transmitter is empty + */ +static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (info->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = inb(info->base + UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + set_current_state(TASK_RUNNING); + +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif } + /* * This routine is called by tty_hangup() when a hangup is signaled. */ @@ -1303,23 +1829,46 @@ void mxser_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = NULL; + info->tty = 0; wake_up_interruptible(&info->open_wait); } + +// added by James 03-12-2004. +/* + * mxser_rs_break() --- routine which turns the break handling on or off + */ +static void mxser_rs_break(struct tty_struct *tty, int break_state) +{ + struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (break_state == -1) + outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR); + else + outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); +} + +// (above) added by James. + + /* * This is the serial driver's generic interrupt routine */ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - int status, i; + int status, iir, i; struct mxser_struct *info; struct mxser_struct *port; int max, irqbits, bits, msr; int pass_counter = 0; - int handled = 0; + int handled = IRQ_NONE; + + port = 0; + //spin_lock(&gm_lock); - port = NULL; for (i = 0; i < MXSER_BOARDS; i++) { if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { port = dev_id; @@ -1327,107 +1876,306 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } - if (i == MXSER_BOARDS) - return IRQ_NONE; - if (port == 0) - return IRQ_NONE; - max = mxser_numports[mxsercfg[i].board_type]; - + if (i == MXSER_BOARDS) { + goto irq_stop; + } + if (port == 0) { + goto irq_stop; + } + max = mxser_numports[mxsercfg[i].board_type - 1]; while (1) { irqbits = inb(port->vector) & port->vectormask; - if (irqbits == port->vectormask) + if (irqbits == port->vectormask) { break; - handled = 1; + } + + handled = IRQ_HANDLED; for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == port->vectormask) + if (irqbits == port->vectormask) { break; + } if (bits & irqbits) continue; info = port + i; - if (!info->tty || - (inb(info->base + UART_IIR) & UART_IIR_NO_INT)) + + // following add by Victor Yu. 09-13-2002 + iir = inb(info->base + UART_IIR); + if (iir & UART_IIR_NO_INT) + continue; + iir &= MOXA_MUST_IIR_MASK; + if (!info->tty) { + status = inb(info->base + UART_LSR); + outb(0x27, info->base + UART_FCR); + inb(info->base + UART_MSR); continue; - status = inb(info->base + UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) - mxser_receive_chars(info, &status); + } + // above add by Victor Yu. 09-13-2002 + /* + if ( info->tty->flip.count < TTY_FLIPBUF_SIZE/4 ){ + info->IER |= MOXA_MUST_RECV_ISR; + outb(info->IER, info->base + UART_IER); + } + */ + + + /* mask by Victor Yu. 09-13-2002 + if ( !info->tty || + (inb(info->base + UART_IIR) & UART_IIR_NO_INT) ) + continue; + */ + /* mask by Victor Yu. 09-02-2002 + status = inb(info->base + UART_LSR) & info->read_status_mask; + */ + + // following add by Victor Yu. 09-02-2002 + status = inb(info->base + UART_LSR); + + if (status & UART_LSR_PE) { + info->err_shadow |= NPPI_NOTIFY_PARITY; + } + if (status & UART_LSR_FE) { + info->err_shadow |= NPPI_NOTIFY_FRAMING; + } + if (status & UART_LSR_OE) { + info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN; + } + if (status & UART_LSR_BI) + info->err_shadow |= NPPI_NOTIFY_BREAK; + + if (info->IsMoxaMustChipFlag) { + /* + if ( (status & 0x02) && !(status & 0x01) ) { + outb(info->base+UART_FCR, 0x23); + continue; + } + */ + if (iir == MOXA_MUST_IIR_GDA || iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR) + mxser_receive_chars(info, &status); + + } else { + // above add by Victor Yu. 09-02-2002 + + status &= info->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(info, &status); + } msr = inb(info->base + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) + if (msr & UART_MSR_ANY_DELTA) { mxser_check_modem_status(info, msr); - if (status & UART_LSR_THRE) { + } + // following add by Victor Yu. 09-13-2002 + if (info->IsMoxaMustChipFlag) { + if ((iir == 0x02) && (status & UART_LSR_THRE)) { + mxser_transmit_chars(info); + } + } else { + // above add by Victor Yu. 09-13-2002 + + if (status & UART_LSR_THRE) { /* 8-2-99 by William - if ( info->x_char || (info->xmit_cnt > 0) ) - */ - mxser_transmit_chars(info); + if ( info->x_char || (info->xmit_cnt > 0) ) +*/ + mxser_transmit_chars(info); + } } } if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { -#if 0 - printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n"); -#endif break; /* Prevent infinite loops */ } } - return IRQ_RETVAL(handled); + + irq_stop: + //spin_unlock(&gm_lock); + return handled; } -static inline void mxser_receive_chars(struct mxser_struct *info, - int *status) +static void mxser_receive_chars(struct mxser_struct *info, int *status) { struct tty_struct *tty = info->tty; - unsigned char ch; + unsigned char ch, gdl; int ignored = 0; int cnt = 0; + unsigned char *cp; + char *fp; + int count; + int recv_room; + int max = 256; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + + recv_room = tty->ldisc.receive_room(tty); + if ((recv_room == 0) && (!info->ldisc_stop_rx)) { + //mxser_throttle(tty); + mxser_stoprx(tty); + //return; + } + + cp = tty->flip.char_buf; + fp = tty->flip.flag_buf; + count = 0; + + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { + + if (*status & UART_LSR_SPECIAL) { + goto intr_old; + } + // following add by Victor Yu. 02-11-2004 + if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && (*status & MOXA_MUST_LSR_RERR)) + goto intr_old; + // above add by Victor Yu. 02-14-2004 + if (*status & MOXA_MUST_LSR_RERR) + goto intr_old; + + gdl = inb(info->base + MOXA_MUST_GDL_REGISTER); + + if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID) // add by Victor Yu. 02-11-2004 + gdl &= MOXA_MUST_GDL_MASK; + if (gdl >= recv_room) { + if (!info->ldisc_stop_rx) { + //mxser_throttle(tty); + mxser_stoprx(tty); + } + //return; + } + while (gdl--) { + ch = inb(info->base + UART_RX); + count++; + *cp++ = ch; + *fp++ = 0; + cnt++; + /* + if((count>=HI_WATER) && (info->stop_rx==0)){ + mxser_stoprx(tty); + info->stop_rx=1; + break; + } */ + } + goto end_intr; + } +intr_old: + // above add by Victor Yu. 09-02-2002 do { + if (max-- < 0) + break; + /* + if((count>=HI_WATER) && (info->stop_rx==0)){ + mxser_stoprx(tty); + info->stop_rx=1; + break; + } + */ + ch = inb(info->base + UART_RX); + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag && (*status & UART_LSR_OE) /*&& !(*status&UART_LSR_DR) */ ) + outb(0x23, info->base + UART_FCR); + *status &= info->read_status_mask; + // above add by Victor Yu. 09-02-2002 if (*status & info->ignore_status_mask) { if (++ignored > 100) break; } else { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - tty->flip.count++; + count++; if (*status & UART_LSR_SPECIAL) { if (*status & UART_LSR_BI) { - *tty->flip.flag_buf_ptr++ = TTY_BREAK; + *fp++ = TTY_BREAK; +/* added by casper 1/11/2000 */ + info->icount.brk++; + +/* */ if (info->flags & ASYNC_SAK) do_SAK(tty); } else if (*status & UART_LSR_PE) { - *tty->flip.flag_buf_ptr++ = TTY_PARITY; + *fp++ = TTY_PARITY; +/* added by casper 1/11/2000 */ + info->icount.parity++; +/* */ } else if (*status & UART_LSR_FE) { - *tty->flip.flag_buf_ptr++ = TTY_FRAME; + *fp++ = TTY_FRAME; +/* added by casper 1/11/2000 */ + info->icount.frame++; +/* */ } else if (*status & UART_LSR_OE) { - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + *fp++ = TTY_OVERRUN; +/* added by casper 1/11/2000 */ + info->icount.overrun++; +/* */ } else - *tty->flip.flag_buf_ptr++ = 0; + *fp++ = 0; } else - *tty->flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = ch; + *fp++ = 0; + *cp++ = ch; cnt++; + if (cnt >= recv_room) { + if (!info->ldisc_stop_rx) { + //mxser_throttle(tty); + mxser_stoprx(tty); + } + break; + } + } - *status = inb(info->base + UART_LSR) & info->read_status_mask; + + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag) + break; + // above add by Victor Yu. 09-02-2002 + + /* mask by Victor Yu. 09-02-2002 + *status = inb(info->base + UART_LSR) & info->read_status_mask; + */ + // following add by Victor Yu. 09-02-2002 + *status = inb(info->base + UART_LSR); + // above add by Victor Yu. 09-02-2002 } while (*status & UART_LSR_DR); + + end_intr: // add by Victor Yu. 09-02-2002 + mxvar_log.rxcnt[info->port] += cnt; - schedule_delayed_work(&tty->flip.work, 1); + info->mon_data.rxcnt += cnt; + info->mon_data.up_rxcnt += cnt; + + tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count); + spin_unlock_irqrestore(&info->slock, flags); } -static inline void mxser_transmit_chars(struct mxser_struct *info) +static void mxser_transmit_chars(struct mxser_struct *info) { int count, cnt; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); if (info->x_char) { outb(info->x_char, info->base + UART_TX); info->x_char = 0; mxvar_log.txcnt[info->port]++; + info->mon_data.txcnt++; + info->mon_data.up_txcnt++; + +/* added by casper 1/11/2000 */ + info->icount.tx++; +/* */ + spin_unlock_irqrestore(&info->slock, flags); + return; + } + + if (info->xmit_buf == 0) { + spin_unlock_irqrestore(&info->slock, flags); return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { + + if ((info->xmit_cnt <= 0) || info->tty->stopped || (info->tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); return; } + cnt = info->xmit_cnt; count = info->xmit_fifo_size; do { @@ -1438,6 +2186,15 @@ static inline void mxser_transmit_chars(struct mxser_struct *info) } while (--count > 0); mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt); +// added by James 03-12-2004. + info->mon_data.txcnt += (cnt - info->xmit_cnt); + info->mon_data.up_txcnt += (cnt - info->xmit_cnt); +// (above) added by James. + +/* added by casper 1/11/2000 */ + info->icount.tx += (cnt - info->xmit_cnt); +/* */ + if (info->xmit_cnt < WAKEUP_CHARS) { set_bit(MXSER_EVENT_TXLOW, &info->event); schedule_work(&info->tqueue); @@ -1446,12 +2203,11 @@ static inline void mxser_transmit_chars(struct mxser_struct *info) info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); } + spin_unlock_irqrestore(&info->slock, flags); } -static inline void mxser_check_modem_status(struct mxser_struct *info, - int status) +static void mxser_check_modem_status(struct mxser_struct *info, int status) { - /* update input line counters */ if (status & UART_MSR_TERI) info->icount.rng++; @@ -1461,68 +2217,55 @@ static inline void mxser_check_modem_status(struct mxser_struct *info, info->icount.dcd++; if (status & UART_MSR_DCTS) info->icount.cts++; + info->mon_data.modem_status = status; wake_up_interruptible(&info->delta_msr_wait); + if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { if (status & UART_MSR_DCD) wake_up_interruptible(&info->open_wait); - else - set_bit(MXSER_EVENT_HANGUP, &info->event); schedule_work(&info->tqueue); } + if (info->flags & ASYNC_CTS_FLOW) { if (info->tty->hw_stopped) { if (status & UART_MSR_CTS) { info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - outb(info->IER, info->base + UART_IER); + if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + info->IER |= UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + } set_bit(MXSER_EVENT_TXLOW, &info->event); - schedule_work(&info->tqueue); - } + schedule_work(&info->tqueue); } } else { if (!(status & UART_MSR_CTS)) { info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - outb(info->IER, info->base + UART_IER); + if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + } } } } } -static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, - struct mxser_struct *info) +static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_struct *info) { DECLARE_WAITQUEUE(wait, current); - unsigned long flags; int retval; int do_clocal = 0; + unsigned long flags; - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - return (-EAGAIN); - else - return (-ERESTARTSYS); -#else - return (-EAGAIN); -#endif - } /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { + if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { info->flags |= ASYNC_NORMAL_ACTIVE; return (0); } + if (tty->termios->c_cflag & CLOCAL) do_clocal = 1; @@ -1535,32 +2278,25 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, */ retval = 0; add_wait_queue(&info->open_wait, &wait); - save_flags(flags); - cli(); + + spin_lock_irqsave(&info->slock, flags); if (!tty_hung_up_p(filp)) info->count--; - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); info->blocked_open++; while (1) { - save_flags(flags); - cli(); - outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS, - info->base + UART_MCR); - restore_flags(flags); + spin_lock_irqsave(&info->slock, flags); + outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif break; } - if (!(info->flags & ASYNC_CLOSING) && - (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD))) + if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; @@ -1581,26 +2317,27 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, static int mxser_startup(struct mxser_struct *info) { - unsigned long flags; + unsigned long page; + unsigned long flags; - page = get_zeroed_page(GFP_KERNEL); + page = __get_free_page(GFP_KERNEL); if (!page) return (-ENOMEM); - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); return (0); } + if (!info->base || !info->type) { if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); free_page(page); - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); return (0); } if (info->xmit_buf) @@ -1612,9 +2349,10 @@ static int mxser_startup(struct mxser_struct *info) * Clear the FIFO buffers and disable them * (they will be reenabled in mxser_change_speed()) */ - if (info->xmit_fifo_size == 16) - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), - info->base + UART_FCR); + if (info->IsMoxaMustChipFlag) + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); + else + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); /* * At this point there's no way the LSR could still be 0xFF; @@ -1622,7 +2360,7 @@ static int mxser_startup(struct mxser_struct *info) * here. */ if (inb(info->base + UART_LSR) == 0xff) { - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); if (capable(CAP_SYS_ADMIN)) { if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); @@ -1630,6 +2368,7 @@ static int mxser_startup(struct mxser_struct *info) } else return (-ENODEV); } + /* * Clear the interrupt registers. */ @@ -1649,7 +2388,13 @@ static int mxser_startup(struct mxser_struct *info) * Finally, enable interrupts */ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - outb(info->IER, info->base + UART_IER); /* enable interrupts */ +// info->IER = UART_IER_RLSI | UART_IER_RDI; + + // following add by Victor Yu. 08-30-2002 + if (info->IsMoxaMustChipFlag) + info->IER |= MOXA_MUST_IER_EGDAI; + // above add by Victor Yu. 08-30-2002 + outb(info->IER, info->base + UART_IER); /* enable interrupts */ /* * And clear the interrupt registers again for luck. @@ -1660,17 +2405,16 @@ static int mxser_startup(struct mxser_struct *info) (void) inb(info->base + UART_MSR); if (info->tty) - test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags); - + clear_bit(TTY_IO_ERROR, &info->tty->flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; /* * and set the speed of the serial port */ - mxser_change_speed(info, NULL); + spin_unlock_irqrestore(&info->slock, flags); + mxser_change_speed(info, 0); info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); return (0); } @@ -1685,8 +2429,7 @@ static void mxser_shutdown(struct mxser_struct *info) if (!(info->flags & ASYNC_INITIALIZED)) return; - save_flags(flags); - cli(); /* Disable interrupts */ + spin_lock_irqsave(&info->slock, flags); /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq @@ -1699,17 +2442,24 @@ static void mxser_shutdown(struct mxser_struct *info) */ if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); - info->xmit_buf = NULL; + info->xmit_buf = 0; } + info->IER = 0; - outb(0x00, info->base + UART_IER); /* disable all intrs */ + outb(0x00, info->base + UART_IER); if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); outb(info->MCR, info->base + UART_MCR); /* clear Rx/Tx FIFO's */ - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + // following add by Victor Yu. 08-30-2002 + if (info->IsMoxaMustChipFlag) + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); + else + // above add by Victor Yu. 08-30-2002 + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + /* read data port to reset things */ (void) inb(info->base + UART_RX); @@ -1717,229 +2467,108 @@ static void mxser_shutdown(struct mxser_struct *info) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + + // following add by Victor Yu. 09-23-2002 + if (info->IsMoxaMustChipFlag) { + SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base); + } + // above add by Victor Yu. 09-23-2002 + + spin_unlock_irqrestore(&info->slock, flags); } /* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static int mxser_change_speed(struct mxser_struct *info, - struct termios *old_termios) +static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios) { - int quot = 0; unsigned cflag, cval, fcr; - int i; int ret = 0; + unsigned char status; + long baud; unsigned long flags; + if (!info->tty || !info->tty->termios) return ret; cflag = info->tty->termios->c_cflag; if (!(info->base)) return ret; + #ifndef B921600 #define B921600 (B460800 +1) #endif - switch (cflag & (CBAUD | CBAUDEX)) { - case B921600: - i = 20; - break; - case B460800: - i = 19; - break; - case B230400: - i = 18; - break; - case B115200: - i = 17; - break; - case B57600: - i = 16; - break; - case B38400: - i = 15; - break; - case B19200: - i = 14; - break; - case B9600: - i = 13; - break; - case B4800: - i = 12; - break; - case B2400: - i = 11; - break; - case B1800: - i = 10; - break; - case B1200: - i = 9; - break; - case B600: - i = 8; - break; - case B300: - i = 7; - break; - case B200: - i = 6; - break; - case B150: - i = 5; - break; - case B134: - i = 4; - break; - case B110: - i = 3; - break; - case B75: - i = 2; - break; - case B50: - i = 1; - break; - default: - i = 0; - break; - } - - if (i == 15) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - i = 16; /* 57600 bps */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - i = 17; /* 115200 bps */ - -#ifdef ASYNC_SPD_SHI - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - i = 18; -#endif - -#ifdef ASYNC_SPD_WARP - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - i = 19; -#endif - } - if (mxvar_baud_table[i] == 134) { - quot = (2 * info->baud_base / 269); - } else if (mxvar_baud_table[i]) { - quot = info->baud_base / mxvar_baud_table[i]; - if (!quot && old_termios) { - /* re-calculate */ - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - switch (info->tty->termios->c_cflag & (CBAUD | CBAUDEX)) { - case B921600: - i = 20; - break; - case B460800: - i = 19; - break; - case B230400: - i = 18; - break; - case B115200: - i = 17; - break; - case B57600: - i = 16; - break; - case B38400: - i = 15; - break; - case B19200: - i = 14; - break; - case B9600: - i = 13; - break; - case B4800: - i = 12; - break; - case B2400: - i = 11; - break; - case B1800: - i = 10; - break; - case B1200: - i = 9; - break; - case B600: - i = 8; - break; - case B300: - i = 7; - break; - case B200: - i = 6; - break; - case B150: - i = 5; - break; - case B134: - i = 4; - break; - case B110: - i = 3; - break; - case B75: - i = 2; - break; - case B50: - i = 1; - break; - default: - i = 0; - break; - } - if (i == 15) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - i = 16; /* 57600 bps */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - i = 17; /* 115200 bps */ -#ifdef ASYNC_SPD_SHI - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - i = 18; -#endif -#ifdef ASYNC_SPD_WARP - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - i = 19; -#endif - } - if (mxvar_baud_table[i] == 134) { - quot = (2 * info->baud_base / 269); - } else if (mxvar_baud_table[i]) { - quot = info->baud_base / mxvar_baud_table[i]; - if (quot == 0) - quot = 1; - } else { - quot = 0; - } - } else if (quot == 0) - quot = 1; - } else { - quot = 0; + if (mxser_set_baud_method[info->port] == 0) { + switch (cflag & (CBAUD | CBAUDEX)) { + case B921600: + baud = 921600; + break; + case B460800: + baud = 460800; + break; + case B230400: + baud = 230400; + break; + case B115200: + baud = 115200; + break; + case B57600: + baud = 57600; + break; + case B38400: + baud = 38400; + break; + case B19200: + baud = 19200; + break; + case B9600: + baud = 9600; + break; + case B4800: + baud = 4800; + break; + case B2400: + baud = 2400; + break; + case B1800: + baud = 1800; + break; + case B1200: + baud = 1200; + break; + case B600: + baud = 600; + break; + case B300: + baud = 300; + break; + case B200: + baud = 200; + break; + case B150: + baud = 150; + break; + case B134: + baud = 134; + break; + case B110: + baud = 110; + break; + case B75: + baud = 75; + break; + case B50: + baud = 50; + break; + default: + baud = 0; + break; + } + mxser_set_baud(info, baud); } - if (quot) { - info->MCR |= UART_MCR_DTR; - save_flags(flags); - cli(); - outb(info->MCR, info->base + UART_MCR); - restore_flags(flags); - } else { - info->MCR &= ~UART_MCR_DTR; - save_flags(flags); - cli(); - outb(info->MCR, info->base + UART_MCR); - restore_flags(flags); - return ret; - } /* byte size and parity */ switch (cflag & CSIZE) { case CS5: @@ -1962,24 +2591,45 @@ static int mxser_change_speed(struct mxser_struct *info, cval |= 0x04; if (cflag & PARENB) cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) +#ifndef CMSPAR +#define CMSPAR 010000000000 +#endif + if (!(cflag & PARODD)) { cval |= UART_LCR_EPAR; + } + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; + if ((info->type == PORT_8250) || (info->type == PORT_16450)) { - fcr = 0; + if (info->IsMoxaMustChipFlag) { + fcr = UART_FCR_ENABLE_FIFO; + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else + fcr = 0; } else { fcr = UART_FCR_ENABLE_FIFO; - switch (info->rx_trigger) { - case 1: - fcr |= UART_FCR_TRIGGER_1; - break; - case 4: - fcr |= UART_FCR_TRIGGER_4; - break; - case 8: - fcr |= UART_FCR_TRIGGER_8; - break; - default: - fcr |= UART_FCR_TRIGGER_14; + // following add by Victor Yu. 08-30-2002 + if (info->IsMoxaMustChipFlag) { + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else { + // above add by Victor Yu. 08-30-2002 + + switch (info->rx_trigger) { + case 1: + fcr |= UART_FCR_TRIGGER_1; + break; + case 4: + fcr |= UART_FCR_TRIGGER_4; + break; + case 8: + fcr |= UART_FCR_TRIGGER_8; + break; + default: + fcr |= UART_FCR_TRIGGER_14; + break; + } } } @@ -1989,15 +2639,46 @@ static int mxser_change_speed(struct mxser_struct *info, if (cflag & CRTSCTS) { info->flags |= ASYNC_CTS_FLOW; info->IER |= UART_IER_MSI; - if (info->type == PORT_16550A) + if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) { info->MCR |= UART_MCR_AFE; + //status = mxser_get_msr(info->base, 0, info->port); +/* save_flags(flags); + cli(); + status = inb(baseaddr + UART_MSR); + restore_flags(flags);*/ + //mxser_check_modem_status(info, status); + } else { + //status = mxser_get_msr(info->base, 0, info->port); + + //MX_LOCK(&info->slock); + status = inb(info->base + UART_MSR); + //MX_UNLOCK(&info->slock); + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { + info->tty->hw_stopped = 0; + if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + info->IER |= UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + } + set_bit(MXSER_EVENT_TXLOW, &info->event); + schedule_work(&info->tqueue); } + } else { + if (!(status & UART_MSR_CTS)) { + info->tty->hw_stopped = 1; + if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->base + UART_IER); + } + } + } + } } else { info->flags &= ~ASYNC_CTS_FLOW; } outb(info->MCR, info->base + UART_MCR); - if (cflag & CLOCAL) + if (cflag & CLOCAL) { info->flags &= ~ASYNC_CHECK_CD; - else { + } else { info->flags |= ASYNC_CHECK_CD; info->IER |= UART_IER_MSI; } @@ -2013,13 +2694,7 @@ static int mxser_change_speed(struct mxser_struct *info, info->read_status_mask |= UART_LSR_BI; info->ignore_status_mask = 0; -#if 0 - /* This should be safe, but for some broken bits of hardware... */ - if (I_IGNPAR(info->tty)) { - info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; - } -#endif + if (I_IGNBRK(info->tty)) { info->ignore_status_mask |= UART_LSR_BI; info->read_status_mask |= UART_LSR_BI; @@ -2032,25 +2707,107 @@ static int mxser_change_speed(struct mxser_struct *info, info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE; } } - save_flags(flags); - cli(); + // following add by Victor Yu. 09-02-2002 + if (info->IsMoxaMustChipFlag) { + spin_lock_irqsave(&info->slock, flags); + SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty)); + SET_MOXA_MUST_XOFF1_VALUE(info->base, STOP_CHAR(info->tty)); + if (I_IXON(info->tty)) { + ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); + } else { + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); + } + if (I_IXOFF(info->tty)) { + ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base); + } else { + DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base); + } + /* + if ( I_IXANY(info->tty) ) { + info->MCR |= MOXA_MUST_MCR_XON_ANY; + ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base); + } else { + info->MCR &= ~MOXA_MUST_MCR_XON_ANY; + DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base); + } + */ + spin_unlock_irqrestore(&info->slock, flags); + } + // above add by Victor Yu. 09-02-2002 + + + outb(fcr, info->base + UART_FCR); /* set fcr */ + outb(cval, info->base + UART_LCR); + + return ret; +} + + +static int mxser_set_baud(struct mxser_struct *info, long newspd) +{ + int quot = 0; + unsigned char cval; + int ret = 0; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return ret; + + if (!(info->base)) + return ret; + + if (newspd > info->MaxCanSetBaudRate) + return 0; + + info->realbaud = newspd; + if (newspd == 134) { + quot = (2 * info->baud_base / 269); + } else if (newspd) { + quot = info->baud_base / newspd; + + if (quot == 0) + quot = 1; + + } else { + quot = 0; + } + + info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); + info->timeout += HZ / 50; /* Add .02 seconds of slop */ + + if (quot) { + spin_lock_irqsave(&info->slock, flags); + info->MCR |= UART_MCR_DTR; + outb(info->MCR, info->base + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + } else { + spin_lock_irqsave(&info->slock, flags); + info->MCR &= ~UART_MCR_DTR; + outb(info->MCR, info->base + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return ret; + } + + cval = inb(info->base + UART_LCR); + outb(cval | UART_LCR_DLAB, info->base + UART_LCR); /* set DLAB */ + outb(quot & 0xff, info->base + UART_DLL); /* LS of divisor */ - outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */ + outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */ outb(cval, info->base + UART_LCR); /* reset DLAB */ - outb(fcr, info->base + UART_FCR); /* set fcr */ - restore_flags(flags); + return ret; } + + /* * ------------------------------------------------------------ * friends of mxser_ioctl() * ------------------------------------------------------------ */ -static int mxser_get_serial_info(struct mxser_struct *info, - struct serial_struct __user *retinfo) +static int mxser_get_serial_info(struct mxser_struct *info, struct serial_struct *retinfo) { struct serial_struct tmp; @@ -2067,11 +2824,12 @@ static int mxser_get_serial_info(struct mxser_struct *info, tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; tmp.hub6 = 0; - return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return (0); } -static int mxser_set_serial_info(struct mxser_struct *info, - struct serial_struct __user *new_info) +static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct *new_info) { struct serial_struct new_serial; unsigned int flags; @@ -2082,40 +2840,40 @@ static int mxser_set_serial_info(struct mxser_struct *info, if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) return -EFAULT; - if ((new_serial.irq != info->irq) || - (new_serial.port != info->base) || - (new_serial.type != info->type) || - (new_serial.custom_divisor != info->custom_divisor) || - (new_serial.baud_base != info->baud_base)) + if ((new_serial.irq != info->irq) || (new_serial.port != info->base) || (new_serial.custom_divisor != info->custom_divisor) || (new_serial.baud_base != info->baud_base)) return (-EPERM); flags = info->flags & ASYNC_SPD_MASK; if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || - (new_serial.close_delay != info->close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->flags & ~ASYNC_USR_MASK))) + if ((new_serial.baud_base != info->baud_base) || (new_serial.close_delay != info->close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) return (-EPERM); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); + info->flags = ((info->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); } else { /* * OK, past this point, all the error checking has been done. * At this point, we start making changes..... */ - info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); info->close_delay = new_serial.close_delay * HZ / 100; info->closing_wait = new_serial.closing_wait * HZ / 100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = 0; //(info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; } + /* added by casper, 3/17/2000, for mouse */ + info->type = new_serial.type; + + process_txrx_fifo(info); + + /* */ if (info->flags & ASYNC_INITIALIZED) { if (flags != (info->flags & ASYNC_SPD_MASK)) { - mxser_change_speed(info, NULL); + mxser_change_speed(info, 0); } - } else + } else { retval = mxser_startup(info); + } return (retval); } @@ -2123,22 +2881,21 @@ static int mxser_set_serial_info(struct mxser_struct *info, * mxser_get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. */ -static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int __user *value) +static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int *value) { unsigned char status; unsigned int result; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); status = inb(info->base + UART_LSR); - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); return put_user(result, value); } @@ -2149,15 +2906,17 @@ static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int __user *va static void mxser_send_break(struct mxser_struct *info, int duration) { unsigned long flags; + if (!info->base) return; set_current_state(TASK_INTERRUPTIBLE); - save_flags(flags); - cli(); + spin_lock_irqsave(&info->slock, flags); outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); schedule_timeout(duration); + spin_lock_irqsave(&info->slock, flags); outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR); - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); } static int mxser_tiocmget(struct tty_struct *tty, struct file *file) @@ -2166,39 +2925,36 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file) unsigned char control, status; unsigned long flags; - if (PORTNO(tty) == MXSER_PORTS) + + if (tty->index == MXSER_PORTS) return (-ENOIOCTLCMD); if (tty->flags & (1 << TTY_IO_ERROR)) return (-EIO); control = info->MCR; - save_flags(flags); - cli(); + + spin_lock_irqsave(&info->slock, flags); status = inb(info->base + UART_MSR); if (status & UART_MSR_ANY_DELTA) mxser_check_modem_status(info, status); - restore_flags(flags); + spin_unlock_irqrestore(&info->slock, flags); return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | - ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | - ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | - ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | - ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | - ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); + ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); } -static int mxser_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) +static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned long flags; - if (PORTNO(tty) == MXSER_PORTS) - return (-ENOIOCTLCMD); + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; if (tty->flags & (1 << TTY_IO_ERROR)) - return (-EIO); + return -EIO; + + spin_lock_irqsave(&info->slock, flags); - save_flags(flags); - cli(); if (set & TIOCM_RTS) info->MCR |= UART_MCR_RTS; if (set & TIOCM_DTR) @@ -2210,10 +2966,11 @@ static int mxser_tiocmset(struct tty_struct *tty, struct file *file, info->MCR &= ~UART_MCR_DTR; outb(info->MCR, info->base + UART_MCR); - restore_flags(flags); - return (0); + spin_unlock_irqrestore(&info->slock, flags); + return 0; } + static int mxser_read_register(int, unsigned short *); static int mxser_program_mode(int); static void mxser_normal_mode(int); @@ -2224,33 +2981,56 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf) unsigned short regs[16], irq; unsigned char scratch, scratch2; + hwconf->IsMoxaMustChipFlag = MOXA_OTHER_UART; + id = mxser_read_register(cap, regs); - if (id == C168_ASIC_ID) + if (id == C168_ASIC_ID) { hwconf->board_type = MXSER_BOARD_C168_ISA; - else if (id == C104_ASIC_ID) + hwconf->ports = 8; + } else if (id == C104_ASIC_ID) { hwconf->board_type = MXSER_BOARD_C104_ISA; - else if (id == C102_ASIC_ID) + hwconf->ports = 4; + } else if (id == C102_ASIC_ID) { hwconf->board_type = MXSER_BOARD_C102_ISA; - else if (id == CI132_ASIC_ID) + hwconf->ports = 2; + } else if (id == CI132_ASIC_ID) { hwconf->board_type = MXSER_BOARD_CI132; - else if (id == CI134_ASIC_ID) + hwconf->ports = 2; + } else if (id == CI134_ASIC_ID) { hwconf->board_type = MXSER_BOARD_CI134; - else if (id == CI104J_ASIC_ID) + hwconf->ports = 4; + } else if (id == CI104J_ASIC_ID) { hwconf->board_type = MXSER_BOARD_CI104J; - else + hwconf->ports = 4; + } else return (0); - irq = regs[9] & 0x0F; - irq = irq | (irq << 4); - irq = irq | (irq << 8); - if ((irq != regs[9]) || ((id == 1) && (irq != regs[10]))) { - return (MXSER_ERR_IRQ_CONFLIT); + + irq = 0; + if (hwconf->ports == 2) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + if (irq != (regs[9] & 0xFF00)) + return (MXSER_ERR_IRQ_CONFLIT); + } else if (hwconf->ports == 4) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if (irq != regs[9]) + return (MXSER_ERR_IRQ_CONFLIT); + } else if (hwconf->ports == 8) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if ((irq != regs[9]) || (irq != regs[10])) + return (MXSER_ERR_IRQ_CONFLIT); } + if (!irq) { return (MXSER_ERR_IRQ); } + hwconf->irq = ((int) (irq & 0xF000) >> 12); for (i = 0; i < 8; i++) hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8; - hwconf->irq = (int) (irq & 0x0F); if ((regs[12] & 0x80) == 0) { return (MXSER_ERR_VECTOR); } @@ -2260,10 +3040,13 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf) else hwconf->vector_mask = 0x000F; for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { - if (regs[12] & bits) + if (regs[12] & bits) { hwconf->baud_base[i] = 921600; - else + hwconf->MaxCanSetBaudRate[i] = 921600; // add by Victor Yu. 09-04-2002 + } else { hwconf->baud_base[i] = 115200; + hwconf->MaxCanSetBaudRate[i] = 115200; // add by Victor Yu. 09-04-2002 + } } scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); @@ -2271,6 +3054,7 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf) outb(scratch2, cap + UART_LCR); outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); scratch = inb(cap + UART_IIR); + if (scratch & 0xC0) hwconf->uart_type = PORT_16550A; else @@ -2279,6 +3063,8 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf) hwconf->ports = 8; else hwconf->ports = 4; + request_region(hwconf->ioaddr[0], 8 * hwconf->ports, "mxser(IO)"); + request_region(hwconf->vector, 1, "mxser(vector)"); return (hwconf->ports); } @@ -2333,10 +3119,9 @@ static int mxser_read_register(int port, unsigned short *regs) static int mxser_program_mode(int port) { int id, i, j, n; - unsigned long flags; + //unsigned long flags; - save_flags(flags); - cli(); + spin_lock(&gm_lock); outb(0, port); outb(0, port); outb(0, port); @@ -2344,10 +3129,11 @@ static int mxser_program_mode(int port) (void) inb(port); outb(0, port); (void) inb(port); - restore_flags(flags); + //restore_flags(flags); + spin_unlock(&gm_lock); + id = inb(port + 1) & 0x1F; - if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID) && - (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID)) + if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID) && (id != CI104J_ASIC_ID)) return (-1); for (i = 0, j = 0; i < 4; i++) { n = inb(port + 2); @@ -2384,5 +3170,22 @@ static void mxser_normal_mode(int port) outb(0x00, port + 4); } +// added by James 03-05-2004. +// for secure device server: +// stat = 1, the port8 DTR is set to ON. +// stat = 0, the port8 DTR is set to OFF. +void SDS_PORT8_DTR(int stat) +{ + int _sds_oldmcr; + _sds_oldmcr = inb(mxvar_table[7].base + UART_MCR); // get old MCR + if (stat == 1) { + outb(_sds_oldmcr | 0x01, mxvar_table[7].base + UART_MCR); // set DTR ON + } + if (stat == 0) { + outb(_sds_oldmcr & 0xfe, mxvar_table[7].base + UART_MCR); // set DTR OFF + } + return; +} + module_init(mxser_module_init); module_exit(mxser_module_exit); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 3e10c700d..d60627b34 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -103,9 +103,9 @@ #include /* used in new tty drivers */ #include /* used in new tty drivers */ #include +#include #include -#include #include #include @@ -184,7 +184,7 @@ static ssize_t maxframe = 4096; static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, __u8 __user *buf, size_t nr); static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, - const __u8 __user *buf, size_t nr); + const unsigned char *buf, size_t nr); static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, @@ -402,7 +402,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) /* Send the next block of data to device */ tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = tty->driver->write(tty, 0, tbuf->buf, tbuf->count); + actual = tty->driver->write(tty, tbuf->buf, tbuf->count); /* if transmit error, throw frame away by */ /* pretending it was accepted by driver */ @@ -649,7 +649,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, * Returns the number of bytes written (or error code). */ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, - const __u8 __user *data, size_t count) + const unsigned char *data, size_t count) { struct n_hdlc *n_hdlc = tty2n_hdlc (tty); int error = 0; @@ -704,16 +704,12 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, if (!error) { /* Retrieve the user's buffer */ - if (copy_from_user(tbuf->buf, data, count)) { - /* return tx buffer to free list */ - n_hdlc_buf_put(&n_hdlc->tx_free_buf_list,tbuf); - error = -EFAULT; - } else { - /* Send the data */ - tbuf->count = error = count; - n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); - n_hdlc_send_frames(n_hdlc,tty); - } + memcpy(tbuf->buf, data, count); + + /* Send the data */ + tbuf->count = error = count; + n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); + n_hdlc_send_frames(n_hdlc,tty); } return error; diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index e24b7efaf..3883073ab 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -139,7 +139,7 @@ static void r3964_close(struct tty_struct *tty); static ssize_t r3964_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr); static ssize_t r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char __user * buf, size_t nr); + const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); static void r3964_set_termios(struct tty_struct *tty, struct termios * old); @@ -1246,13 +1246,12 @@ repeat: } static ssize_t r3964_write(struct tty_struct * tty, struct file * file, - const unsigned char __user *data, size_t count) + const unsigned char *data, size_t count) { struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; struct r3964_block_header *pHeader; struct r3964_client_info *pClient; unsigned char *new_data; - int status; int pid; TRACE_L("write request, %d characters", count); @@ -1263,12 +1262,6 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, if(!pInfo) return -EIO; - status = verify_area (VERIFY_READ, data, count); - if (status != 0) - { - return status; - } - /* * Ensure that the caller does not wish to send too much. */ @@ -1283,7 +1276,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, count = R3964_MTU; } /* - * Allocate a buffer for the data and fetch it from the user space. + * Allocate a buffer for the data and copy it from the buffer with header prepended */ new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); TRACE_M("r3964_write - kmalloc %x",(int)new_data); @@ -1310,7 +1303,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, pHeader->owner = pClient; } - __copy_from_user(pHeader->data, data, count); /* We already verified this */ + memcpy(pHeader->data, data, count); /* We already verified this */ if(pInfo->flags & R3964_DEBUG) { diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 072197462..a29dffd94 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -44,10 +44,10 @@ #include #include #include +#include #include #include -#include /* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 @@ -99,11 +99,18 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) spin_unlock_irqrestore(&tty->read_lock, flags); } -/* - * Check whether to call the driver.unthrottle function. - * We test the TTY_THROTTLED bit first so that it always - * indicates the current state. +/** + * check_unthrottle - allow new receive data + * @tty; tty device + * + * Check whether to call the driver.unthrottle function. + * We test the TTY_THROTTLED bit first so that it always + * indicates the current state. The decision about whether + * it is worth allowing more input has been taken by the caller. + * Can sleep, may be called under the atomic_read semaphore but + * this is not guaranteed. */ + static void check_unthrottle(struct tty_struct * tty) { if (tty->count && @@ -112,10 +119,13 @@ static void check_unthrottle(struct tty_struct * tty) tty->driver->unthrottle(tty); } -/* - * Reset the read buffer counters, clear the flags, - * and make sure the driver is unthrottled. Called - * from n_tty_open() and n_tty_flush_buffer(). +/** + * reset_buffer_flags - reset buffer state + * @tty: terminal to reset + * + * Reset the read buffer counters, clear the flags, + * and make sure the driver is unthrottled. Called + * from n_tty_open() and n_tty_flush_buffer(). */ static void reset_buffer_flags(struct tty_struct *tty) { @@ -129,9 +139,19 @@ static void reset_buffer_flags(struct tty_struct *tty) check_unthrottle(tty); } -/* - * Flush the input buffer +/** + * n_tty_flush_buffer - clean input queue + * @tty: terminal device + * + * Flush the input buffer. Called when the line discipline is + * being closed, when the tty layer wants the buffer flushed (eg + * at hangup) or when the N_TTY line discipline internally has to + * clean the pending queue (for example some signals). + * + * FIXME: tty->ctrl_status is not spinlocked and relies on + * lock_kernel() still. */ + void n_tty_flush_buffer(struct tty_struct * tty) { /* clear everything and unthrottle the driver */ @@ -146,9 +166,14 @@ void n_tty_flush_buffer(struct tty_struct * tty) } } -/* - * Return number of characters buffered to be delivered to user +/** + * n_tty_chars_in_buffer - report available bytes + * @tty: tty device + * + * Report the number of characters buffered to be delivered to user + * at this instant in time. */ + ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; @@ -166,20 +191,47 @@ ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) return n; } +/** + * is_utf8_continuation - utf8 multibyte check + * @c: byte to check + * + * Returns true if the utf8 character 'c' is a multibyte continuation + * character. We use this to correctly compute the on screen size + * of the character when printing + */ + static inline int is_utf8_continuation(unsigned char c) { return (c & 0xc0) == 0x80; } +/** + * is_continuation - multibyte check + * @c: byte to check + * + * Returns true if the utf8 character 'c' is a multibyte continuation + * character and the terminal is in unicode mode. + */ + static inline int is_continuation(unsigned char c, struct tty_struct *tty) { return I_IUTF8(tty) && is_utf8_continuation(c); } -/* - * Perform OPOST processing. Returns -1 when the output device is - * full and the character must be retried. +/** + * opost - output post processor + * @c: character (or partial unicode symbol) + * @tty: terminal device + * + * Perform OPOST processing. Returns -1 when the output device is + * full and the character must be retried. Note that Linux currently + * ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't + * relevant in the world today. If you ever need them, add them here. + * + * Called from both the receive and transmit sides and can be called + * re-entrantly. Relies on lock_kernel() still. */ + static int opost(unsigned char c, struct tty_struct *tty) { int space, spaces; @@ -218,7 +270,7 @@ static int opost(unsigned char c, struct tty_struct *tty) if (space < spaces) return -1; tty->column += spaces; - tty->driver->write(tty, 0, " ", spaces); + tty->driver->write(tty, " ", spaces); return 0; } tty->column += spaces; @@ -239,17 +291,26 @@ static int opost(unsigned char c, struct tty_struct *tty) return 0; } -/* - * opost_block --- to speed up block console writes, among other - * things. +/** + * opost_block - block postprocess + * @tty: terminal device + * @inbuf: user buffer + * @nr: number of bytes + * + * This path is used to speed up block console writes, among other + * things when processing blocks of output data. It handles only + * the simple cases normally found and helps to generate blocks of + * symbols for the console driver and thus improve performance. + * + * Called from write_chan under the tty layer write lock. */ + static ssize_t opost_block(struct tty_struct * tty, - const unsigned char __user * inbuf, unsigned int nr) + const unsigned char * buf, unsigned int nr) { - char buf[80]; int space; int i; - char *cp; + const unsigned char *cp; space = tty->driver->write_room(tty); if (!space) @@ -259,9 +320,6 @@ static ssize_t opost_block(struct tty_struct * tty, if (nr > sizeof(buf)) nr = sizeof(buf); - if (copy_from_user(buf, inbuf, nr)) - return -EFAULT; - for (i = 0, cp = buf; i < nr; i++, cp++) { switch (*cp) { case '\n': @@ -274,12 +332,8 @@ static ssize_t opost_block(struct tty_struct * tty, case '\r': if (O_ONOCR(tty) && tty->column == 0) goto break_out; - if (O_OCRNL(tty)) { - *cp = '\n'; - if (O_ONLRET(tty)) - tty->canon_column = tty->column = 0; - break; - } + if (O_OCRNL(tty)) + goto break_out; tty->canon_column = tty->column = 0; break; case '\t': @@ -290,7 +344,7 @@ static ssize_t opost_block(struct tty_struct * tty, break; default: if (O_OLCUC(tty)) - *cp = toupper(*cp); + goto break_out; if (!iscntrl(*cp)) tty->column++; break; @@ -299,18 +353,32 @@ static ssize_t opost_block(struct tty_struct * tty, break_out: if (tty->driver->flush_chars) tty->driver->flush_chars(tty); - i = tty->driver->write(tty, 0, buf, i); + i = tty->driver->write(tty, buf, i); return i; } - +/** + * put_char - write character to driver + * @c: character (or part of unicode symbol) + * @tty: terminal device + * + * Queue a byte to the driver layer for output + */ + static inline void put_char(unsigned char c, struct tty_struct *tty) { tty->driver->put_char(tty, c); } -/* Must be called only when L_ECHO(tty) is true. */ +/** + * echo_char - echo characters + * @c: unicode byte to echo + * @tty: terminal device + * + * Echo user input back onto the screen. This must be called only when + * L_ECHO(tty) is true. Called from the driver receive_buf path. + */ static void echo_char(unsigned char c, struct tty_struct *tty) { @@ -331,6 +399,16 @@ static inline void finish_erasing(struct tty_struct *tty) } } +/** + * eraser - handle erase function + * @c: character input + * @tty: terminal device + * + * Perform erase and neccessary output when an erase character is + * present in the stream from the driver layer. Handles the complexities + * of UTF-8 multibyte symbols. + */ + static void eraser(unsigned char c, struct tty_struct *tty) { enum { ERASE, WERASE, KILL } kill_type; @@ -463,6 +541,18 @@ static void eraser(unsigned char c, struct tty_struct *tty) finish_erasing(tty); } +/** + * isig - handle the ISIG optio + * @sig: signal + * @tty: terminal + * @flush: force flush + * + * Called when a signal is being sent due to terminal input. This + * may caus terminal flushing to take place according to the termios + * settings and character used. Called from the driver receive_buf + * path so serialized. + */ + static inline void isig(int sig, struct tty_struct *tty, int flush) { if (tty->pgrp > 0) @@ -474,6 +564,16 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) } } +/** + * n_tty_receive_break - handle break + * @tty: terminal + * + * An RS232 break event has been hit in the incoming bitstream. This + * can cause a variety of events depending upon the termios settings. + * + * Called from the receive_buf path so single threaded. + */ + static inline void n_tty_receive_break(struct tty_struct *tty) { if (I_IGNBRK(tty)) @@ -490,19 +590,40 @@ static inline void n_tty_receive_break(struct tty_struct *tty) wake_up_interruptible(&tty->read_wait); } +/** + * n_tty_receive_overrun - handle overrun reporting + * @tty: terminal + * + * Data arrived faster than we could process it. While the tty + * driver has flagged this the bits that were missed are gone + * forever. + * + * Called from the receive_buf path so single threaded. Does not + * need locking as num_overrun and overrun_time are function + * private. + */ + static inline void n_tty_receive_overrun(struct tty_struct *tty) { char buf[64]; tty->num_overrun++; if (time_before(tty->overrun_time, jiffies - HZ)) { - printk("%s: %d input overrun(s)\n", tty_name(tty, buf), + printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf), tty->num_overrun); tty->overrun_time = jiffies; tty->num_overrun = 0; } } +/** + * n_tty_receive_parity_error - error notifier + * @tty: terminal device + * @c: character + * + * Process a parity error and queue the right data to indicate + * the error case if neccessary. Locking as per n_tty_receive_buf. + */ static inline void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) { @@ -520,6 +641,16 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty, wake_up_interruptible(&tty->read_wait); } +/** + * n_tty_receive_char - perform processing + * @tty: terminal device + * @c: character + * + * Process an individual character of input received from the driver. + * This is serialized with respect to itself by the rules for the + * driver above. + */ + static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { unsigned long flags; @@ -711,6 +842,16 @@ send_signal: put_tty_queue(c, tty); } +/** + * n_tty_receive_room - receive space + * @tty: terminal + * + * Called by the driver to find out how much data it is + * permitted to feed to the line discipline without any being lost + * and thus to manage flow control. Not serialized. Answers for the + * "instant". + */ + static int n_tty_receive_room(struct tty_struct *tty) { int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; @@ -729,10 +870,13 @@ static int n_tty_receive_room(struct tty_struct *tty) return 0; } -/* - * Required for the ptys, serial driver etc. since processes - * that attach themselves to the master and rely on ASYNC - * IO must be woken up +/** + * n_tty_write_wakeup - asynchronous I/O notifier + * @tty: tty device + * + * Required for the ptys, serial driver etc. since processes + * that attach themselves to the master and rely on ASYNC + * IO must be woken up */ static void n_tty_write_wakeup(struct tty_struct *tty) @@ -745,6 +889,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty) return; } +/** + * n_tty_receive_buf - data receive + * @tty: terminal device + * @cp: buffer + * @fp: flag buffer + * @count: characters + * + * Called by the terminal driver when a block of characters has + * been received. This function must be called from soft contexts + * not from interrupt context. The driver is responsible for making + * calls one at a time and in order (or using flush_to_ldisc) + */ + static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -828,6 +985,18 @@ int is_ignored(int sig) current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); } +/** + * n_tty_set_termios - termios data changed + * @tty: terminal + * @old: previous data + * + * Called by the tty layer when the user changes termios flags so + * that the line discipline can plan ahead. This function cannot sleep + * and is protected from re-entry by the tty layer. The user is + * guaranteed that this function will not be re-entered or in progress + * when the ldisc is closed. + */ + static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) { if (!tty) @@ -843,7 +1012,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || I_PARMRK(tty)) { - local_irq_disable(); // FIXME: is this safe? memset(tty->process_char_map, 0, 256/8); if (I_IGNCR(tty) || I_ICRNL(tty)) @@ -879,7 +1047,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) set_bit(SUSP_CHAR(tty), tty->process_char_map); } clear_bit(__DISABLED_CHAR, tty->process_char_map); - local_irq_enable(); // FIXME: is this safe? tty->raw = 0; tty->real_raw = 0; } else { @@ -893,6 +1060,16 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) } } +/** + * n_tty_close - close the ldisc for this tty + * @tty: device + * + * Called from the terminal layer when this line discipline is + * being shut down, either because of a close or becsuse of a + * discipline change. The function will not be called while other + * ldisc methods are in progress. + */ + static void n_tty_close(struct tty_struct *tty) { n_tty_flush_buffer(tty); @@ -902,11 +1079,22 @@ static void n_tty_close(struct tty_struct *tty) } } +/** + * n_tty_open - open an ldisc + * @tty: terminal to open + * + * Called when this line discipline is being attached to the + * terminal device. Can sleep. Called serialized so that no + * other events will occur in parallel. No further open will occur + * until a close. + */ + static int n_tty_open(struct tty_struct *tty) { if (!tty) return -EINVAL; + /* This one is ugly. Currently a malloc failure here can panic */ if (!tty->read_buf) { tty->read_buf = alloc_buf(); if (!tty->read_buf) @@ -932,14 +1120,23 @@ static inline int input_available_p(struct tty_struct *tty, int amt) return 0; } -/* - * Helper function to speed up read_chan. It is only called when - * ICANON is off; it copies characters straight from the tty queue to - * user space directly. It can be profitably called twice; once to - * drain the space from the tail pointer to the (physical) end of the - * buffer, and once to drain the space from the (physical) beginning of - * the buffer to head pointer. +/** + * copy_from_read_buf - copy read data directly + * @tty: terminal device + * @b: user data + * @nr: size of data + * + * Helper function to speed up read_chan. It is only called when + * ICANON is off; it copies characters straight from the tty queue to + * user space directly. It can be profitably called twice; once to + * drain the space from the tail pointer to the (physical) end of the + * buffer, and once to drain the space from the (physical) beginning of + * the buffer to head pointer. + * + * Called under the tty->atomic_read sem and with TTY_DONT_FLIP set + * */ + static inline int copy_from_read_buf(struct tty_struct *tty, unsigned char __user **b, size_t *nr) @@ -970,25 +1167,18 @@ static inline int copy_from_read_buf(struct tty_struct *tty, extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *); -static ssize_t read_chan(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t nr) +/** + * job_control - check job control + * @tty: tty + * @file: file handle + * + * Perform job control management checks on this file/tty descriptor + * and if appropriate send any needed signals and return a negative + * error code if action should be taken. + */ + +static int job_control(struct tty_struct *tty, struct file *file) { - unsigned char __user *b = buf; - DECLARE_WAITQUEUE(wait, current); - int c; - int minimum, time; - ssize_t retval = 0; - ssize_t size; - long timeout; - unsigned long flags; - -do_it_again: - - if (!tty->read_buf) { - printk("n_tty_read_chan: called with read_buf == NULL?!?\n"); - return -EIO; - } - /* Job control check -- must be done at start and after every sleep (POSIX.1 7.1.1.4). */ /* NOTE: not yet done after every sleep pending a thorough @@ -1006,7 +1196,48 @@ do_it_again: return -ERESTARTSYS; } } + return 0; +} + + +/** + * read_chan - read function for tty + * @tty: tty device + * @file: file object + * @buf: userspace buffer pointer + * @nr: size of I/O + * + * Perform reads for the line discipline. We are guaranteed that the + * line discipline will not be closed under us but we may get multiple + * parallel readers and must handle this ourselves. We may also get + * a hangup. Always called in user context, may sleep. + * + * This code must be sure never to sleep through a hangup. + */ + +static ssize_t read_chan(struct tty_struct *tty, struct file *file, + unsigned char __user *buf, size_t nr) +{ + unsigned char __user *b = buf; + DECLARE_WAITQUEUE(wait, current); + int c; + int minimum, time; + ssize_t retval = 0; + ssize_t size; + long timeout; + unsigned long flags; + +do_it_again: + + if (!tty->read_buf) { + printk("n_tty_read_chan: called with read_buf == NULL?!?\n"); + return -EIO; + } + c = job_control(tty, file); + if(c < 0) + return c; + minimum = time = 0; timeout = MAX_SCHEDULE_TIMEOUT; if (!tty->icanon) { @@ -1028,6 +1259,9 @@ do_it_again: } } + /* + * Internal serialization of reads. + */ if (file->f_flags & O_NONBLOCK) { if (down_trylock(&tty->atomic_read)) return -EAGAIN; @@ -1177,10 +1411,25 @@ do_it_again: return retval; } +/** + * write_chan - write function for tty + * @tty: tty device + * @file: file object + * @buf: userspace buffer pointer + * @nr: size of I/O + * + * Write function of the terminal device. This is serialized with + * respect to other write callers but not to termios changes, reads + * and other such events. We must be careful with N_TTY as the receive + * code will echo characters, thus calling driver write methods. + * + * This code must be sure never to sleep through a hangup. + */ + static ssize_t write_chan(struct tty_struct * tty, struct file * file, - const unsigned char __user * buf, size_t nr) + const unsigned char * buf, size_t nr) { - const unsigned char __user *b = buf; + const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; @@ -1216,7 +1465,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, nr -= num; if (nr == 0) break; - get_user(c, b); + c = *b; if (opost(c, tty) < 0) break; b++; nr--; @@ -1224,7 +1473,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { - c = tty->driver->write(tty, 1, b, nr); + c = tty->driver->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; @@ -1246,7 +1495,25 @@ break_out: return (b - buf) ? b - buf : retval; } -/* Called without the kernel lock held - fine */ +/** + * normal_poll - poll method for N_TTY + * @tty: terminal device + * @file: file accessing it + * @wait: poll table + * + * Called when the line discipline is asked to poll() for data or + * for special events. This code is not serialized with respect to + * other events save open/close. + * + * This code must be sure never to sleep through a hangup. + * Called without the kernel lock held - fine + * + * FIXME: if someone changes the VMIN or discipline settings for the + * terminal while another process is in poll() the poll does not + * recompute the new limits. Possibly set_termios should issue + * a read wakeup to fix this bug. + */ + static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait) { unsigned int mask = 0; @@ -1287,6 +1554,7 @@ struct tty_ldisc tty_ldisc_N_TTY = { n_tty_ioctl, /* ioctl */ n_tty_set_termios, /* set_termios */ normal_poll, /* poll */ + NULL, /* hangup */ n_tty_receive_buf, /* receive_buf */ n_tty_receive_room, /* receive_room */ n_tty_write_wakeup /* write_wakeup */ diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index e75381ec1..62c67cde8 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -60,15 +60,6 @@ static DECLARE_MUTEX(nwflash_sem); extern spinlock_t gpio_lock; -/* - * the delay routine - it is often required to let the flash "breeze"... - */ -void flash_wait(int timeout) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(timeout); -} - static int get_flash_id(void) { volatile unsigned int c1, c2; @@ -401,7 +392,7 @@ static int erase_block(int nBlock) /* * wait 10 ms */ - flash_wait(HZ / 100); + msleep(10); /* * wait while erasing in process (up to 10 sec) @@ -409,7 +400,7 @@ static int erase_block(int nBlock) timeout = jiffies + 10 * HZ; c1 = 0; while (!(c1 & 0x80) && time_before(jiffies, timeout)) { - flash_wait(HZ / 100); + msleep(10); /* * read any address */ @@ -440,7 +431,7 @@ static int erase_block(int nBlock) /* * just to make sure - verify if erased OK... */ - flash_wait(HZ / 100); + msleep(10); pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16))); @@ -587,7 +578,7 @@ static int write_block(unsigned long p, const char __user *buf, int count) /* * wait couple ms */ - flash_wait(HZ / 100); + msleep(10); /* * red LED == write */ @@ -612,7 +603,7 @@ static int write_block(unsigned long p, const char __user *buf, int count) leds_event(led_amber_off); leds_event(led_green_on); - flash_wait(HZ / 100); + msleep(10); pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); @@ -705,7 +696,7 @@ static void __exit nwflash_exit(void) MODULE_LICENSE("GPL"); -MODULE_PARM(flashdebug, "i"); +module_param(flashdebug, bool, 0644); module_init(nwflash_init); module_exit(nwflash_exit); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index cb1cfb0af..f98bb96e3 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.22 2004/06/01 20:27:46 paulkf Exp $ + * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -64,10 +65,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include @@ -76,12 +78,8 @@ #include #include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -239,12 +237,11 @@ typedef struct _mgslpc_info { int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif + } MGSLPC_INFO; #define MGSLPC_MAGIC 0x5402 @@ -262,7 +259,7 @@ typedef struct _mgslpc_info { * FIXME: PPC has PVR defined in asm/reg.h. For now we just undef it. */ #undef PVR - + #define RXFIFO 0 #define TXFIFO 0 #define STAR 0x20 @@ -398,18 +395,12 @@ static void tx_timeout(unsigned long context); static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* SPPP/HDLC stuff */ -static void mgslpc_sppp_init(MGSLPC_INFO *info); -static void mgslpc_sppp_delete(MGSLPC_INFO *info); -static int mgslpc_sppp_open(struct net_device *d); -static int mgslpc_sppp_close(struct net_device *d); -static void mgslpc_sppp_tx_timeout(struct net_device *d); -static int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d); -static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size); -static void mgslpc_sppp_tx_done(MGSLPC_INFO *info); -static int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -struct net_device_stats *mgslpc_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(MGSLPC_INFO *info); +static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size); +static int hdlcdev_init(MGSLPC_INFO *info); +static void hdlcdev_exit(MGSLPC_INFO *info); #endif static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit); @@ -453,8 +444,6 @@ static int tx_abort(MGSLPC_INFO *info); static int set_rxenable(MGSLPC_INFO *info, int enable); static int wait_events(MGSLPC_INFO *info, int __user *mask); -#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) - static MGSLPC_INFO *mgslpc_device_list = NULL; static int mgslpc_device_count = 0; @@ -494,7 +483,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.22 $"; +static char *driver_version = "$Revision: 4.26 $"; static struct tty_driver *serial_driver; @@ -504,10 +493,6 @@ static struct tty_driver *serial_driver; static void mgslpc_change_params(MGSLPC_INFO *info); static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* PCMCIA prototypes */ static void mgslpc_config(dev_link_t *link); @@ -531,6 +516,40 @@ static void* mgslpc_get_text_ptr(void) return mgslpc_get_text_ptr; } +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_flush_buffer - flush line discipline receive buffers + * ldisc_receive_buf - pass receive data to line discipline + */ + +static void ldisc_flush_buffer(struct tty_struct *tty) +{ + struct tty_ldisc *ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->flush_buffer) + ld->flush_buffer(tty); + tty_ldisc_deref(ld); + } +} + +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->receive_buf) + ld->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + static dev_link_t *mgslpc_attach(void) { MGSLPC_INFO *info; @@ -984,13 +1003,7 @@ void bh_transmit(MGSLPC_INFO *info) printk("bh_transmit() entry on %s\n", info->device_name); if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) { - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):calling ldisc.write_wakeup on %s\n", - __FILE__,__LINE__,info->device_name); - (tty->ldisc.write_wakeup)(tty); - } + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } } @@ -1163,9 +1176,9 @@ void tx_done(MGSLPC_INFO *info) info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgslpc_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -1201,7 +1214,7 @@ void tx_ready(MGSLPC_INFO *info) return; while (info->tx_count && fifo_count) { - c = MIN(2, MIN(fifo_count, MIN(info->tx_count, TXBUFSIZE - info->tx_get))); + c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get))); if (c == 1) { write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get)); @@ -1271,13 +1284,13 @@ void dcd_change(MGSLPC_INFO *info) info->icount.dcd++; if (info->serial_signals & SerialSignal_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev); +#endif wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); @@ -1731,16 +1744,15 @@ static void mgslpc_flush_chars(struct tty_struct *tty) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Returns: number of characters written */ -static int mgslpc_write(struct tty_struct * tty, int from_user, +static int mgslpc_write(struct tty_struct * tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; @@ -1764,21 +1776,13 @@ static int mgslpc_write(struct tty_struct * tty, int from_user, } for (;;) { - c = MIN(count, - MIN(TXBUFSIZE - info->tx_count - 1, + c = min(count, + min(TXBUFSIZE - info->tx_count - 1, TXBUFSIZE - info->tx_put)); if (c <= 0) break; - if (from_user) { - COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c); - if (err) { - if (!ret) - ret = -EFAULT; - break; - } - } else - memcpy(info->tx_buf + info->tx_put, buf, c); + memcpy(info->tx_buf + info->tx_put, buf, c); spin_lock_irqsave(&info->lock,flags); info->tx_put = (info->tx_put + c) & (TXBUFSIZE-1); @@ -1875,11 +1879,9 @@ static void mgslpc_flush_buffer(struct tty_struct *tty) info->tx_count = info->tx_put = info->tx_get = 0; del_timer(&info->tx_timer); spin_unlock_irqrestore(&info->lock,flags); - + wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* Send a high-priority XON/XOFF character @@ -2588,9 +2590,8 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + ldisc_flush_buffer(tty); shutdown(info); @@ -2599,8 +2600,7 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -2651,12 +2651,11 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) char_time = 1; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min_t(unsigned long, char_time, timeout); if (info->params.mode == MGSL_MODE_HDLC) { while (info->tx_active) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -2665,8 +2664,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) } else { while ((info->tx_count || info->tx_active) && info->tx_enabled) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -2876,7 +2874,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -2931,7 +2929,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info) if (info->icount.rxover) ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); } else { ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", info->icount.tx, info->icount.rx); @@ -3070,12 +3068,8 @@ void mgslpc_add_device(MGSLPC_INFO *info) printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n", info->device_name, info->io_base, info->irq_level); - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#ifdef MODULE - if (info->dosyncppp) -#endif - mgslpc_sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif } @@ -3090,9 +3084,8 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info) last->next_device = info->next_device; else mgslpc_device_list = info->next_device; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - mgslpc_sppp_delete(info); +#ifdef CONFIG_HDLC + hdlcdev_exit(info); #endif release_resources(info); kfree(info); @@ -3669,7 +3662,7 @@ void tx_start(MGSLPC_INFO *info) } else { info->tx_active = 1; tx_ready(info); - info->tx_timer.expires = jiffies + jiffies_from_ms(5000); + info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); add_timer(&info->tx_timer); } } @@ -4021,9 +4014,12 @@ int rx_get_frame(MGSLPC_INFO *info) return_frame = 1; } framesize = 0; -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } else return_frame = 1; @@ -4052,18 +4048,12 @@ int rx_get_frame(MGSLPC_INFO *info) ++framesize; } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - mgslpc_sppp_rx_done(info, buf->data, framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info, buf->data, framesize); else #endif - { - /* Call the line discipline receive callback directly. */ - if (tty && tty->ldisc.receive_buf) - tty->ldisc.receive_buf(tty, buf->data, info->flag_buf, framesize); - } + ldisc_receive_buf(tty, buf->data, info->flag_buf, framesize); } } @@ -4127,8 +4117,7 @@ BOOLEAN irq_test(MGSLPC_INFO *info) end_time=100; while(end_time-- && !info->irq_occurred) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_from_ms(10)); + msleep_interruptible(10); } info->testing_irq = FALSE; @@ -4215,88 +4204,134 @@ void tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgslpc_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif bh_transmit(info); } -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* syncppp net device routines +#ifdef CONFIG_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code */ - -static void mgslpc_setup(struct net_device *dev) +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - dev->open = mgslpc_sppp_open; - dev->stop = mgslpc_sppp_close; - dev->hard_start_xmit = mgslpc_sppp_tx; - dev->do_ioctl = mgslpc_sppp_ioctl; - dev->get_stats = mgslpc_net_stats; - dev->tx_timeout = mgslpc_sppp_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} + MGSLPC_INFO *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; -void mgslpc_sppp_init(MGSLPC_INFO *info) -{ - struct net_device *d; + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - sprintf(info->netname,"mgslp%d",info->line); - - d = alloc_netdev(0, info->netname, mgslpc_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; - - d->base_addr = info->io_base; - d->irq = info->irq_level; - d->priv = info; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } - sppp_attach(&info->pppdev); - mgslpc_setup(d); + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; - free_netdev(d); - return; - } + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgslpc_program_hw(info); - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_init()\n"); + return 0; } -void mgslpc_sppp_delete(MGSLPC_INFO *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + MGSLPC_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + memcpy(info->tx_buf, skb->data, skb->len); + info->tx_get = 0; + info->tx_put = info->tx_count = skb->len; + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; } -int mgslpc_sppp_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - MGSLPC_INFO *info = d->priv; - int err; + MGSLPC_INFO *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -4304,142 +4339,295 @@ int mgslpc_sppp_open(struct net_device *d) spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; mgslpc_program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -void mgslpc_sppp_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - MGSLPC_INFO *info = dev->priv; + MGSLPC_INFO *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - MGSLPC_INFO *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + MGSLPC_INFO *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->tx_count = skb->len; + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - memcpy(info->tx_buf, skb->data, skb->len); - info->tx_get = 0; - info->tx_put = info->tx_count = skb->len; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - dev->trans_start = jiffies; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; - return 0; + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgslpc_program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -int mgslpc_sppp_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - MGSLPC_INFO *info = d->priv; + MGSLPC_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; + netif_wake_queue(dev); } -void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size) +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(MGSLPC_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->protocol = hdlc_type_trans(skb, info->netdev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -void mgslpc_sppp_tx_done(MGSLPC_INFO *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -struct net_device_stats *mgslpc_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(MGSLPC_INFO *info) { - MGSLPC_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->base_addr = info->io_base; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(MGSLPC_INFO *info) { - MGSLPC_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ + diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index e804fdc73..b20a94194 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -65,6 +65,7 @@ #include #include #include +#include #ifndef MODULE #include /* We only need it for parsing the "digi="-line */ @@ -73,7 +74,6 @@ #include #include #include -#include #include #define VERSION "1.6.3" @@ -112,13 +112,13 @@ static int numports[] = {0, 0, 0, 0}; MODULE_AUTHOR("Bernhard Kaindl"); MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(verbose, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(io, "1-4i"); -MODULE_PARM(membase, "1-4i"); -MODULE_PARM(memsize, "1-4i"); -MODULE_PARM(altpin, "1-4i"); -MODULE_PARM(numports, "1-4i"); +module_param(verbose, bool, 0644); +module_param(debug, bool, 0644); +module_param_array(io, int, NULL, 0); +module_param_array(membase, int, NULL, 0); +module_param_array(memsize, int, NULL, 0); +module_param_array(altpin, int, NULL, 0); +module_param_array(numports, int, NULL, 0); #endif /* MODULE */ @@ -130,7 +130,6 @@ static struct channel *digi_channels; int pcxx_ncook=sizeof(pcxx_cook); int pcxx_nbios=sizeof(pcxx_bios); -#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define pcxxassert(x, msg) if(!(x)) pcxx_error(__LINE__, msg) #define FEPTIMEOUT 200000 @@ -149,7 +148,7 @@ static void pcxx_error(int, char *); static void pcxe_close(struct tty_struct *, struct file *); static int pcxe_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void pcxe_set_termios(struct tty_struct *, struct termios *); -static int pcxe_write(struct tty_struct *, int, const unsigned char *, int); +static int pcxe_write(struct tty_struct *, const unsigned char *, int); static int pcxe_write_room(struct tty_struct *); static int pcxe_chars_in_buffer(struct tty_struct *); static void pcxe_flush_buffer(struct tty_struct *); @@ -206,7 +205,7 @@ static void __exit pcxe_cleanup(void) { unsigned long flags; - int e1, e2; + int e1; printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION); @@ -223,12 +222,6 @@ static void __exit pcxe_cleanup(void) restore_flags(flags); } -/* - * pcxe_init() is our init_module(): - */ -module_init(pcxe_init); -module_cleanup(pcxe_cleanup); - static inline struct channel *chan(register struct tty_struct *tty) { if (tty) { @@ -538,32 +531,14 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp) if(tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if(tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); shutdown(info); tty->closing = 0; info->event = 0; info->tty = NULL; -#ifndef MODULE -/* ldiscs[] is not available in a MODULE -** worth noting that while I'm not sure what this hunk of code is supposed -** to do, it is not present in the serial.c driver. Hmmm. If you know, -** please send me a note. brian@ilinx.com -** Don't know either what this is supposed to do christoph@lameter.com. -*/ - if(tty->ldisc.num != ldiscs[N_TTY].num) { - if(tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if(tty->ldisc.open) - (tty->ldisc.open)(tty); - } -#endif if(info->blocked_open) { if(info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -595,7 +570,7 @@ void pcxe_hangup(struct tty_struct *tty) -static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct channel *ch; volatile struct board_chan *bc; @@ -610,33 +585,6 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha bc = ch->brdchan; size = ch->txbufsize; - if (from_user) { - - down(&ch->tmp_buf_sem); - save_flags(flags); - cli(); - globalwinon(ch); - head = bc->tin & (size - 1); - /* It seems to be necessary to make sure that the value is stable here somehow - This is a rather odd pice of code here. */ - do - { - tail = bc->tout; - } while (tail != bc->tout); - - tail &= (size - 1); - stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); - count = MIN(stlen, count); - memoff(ch); - restore_flags(flags); - - if (count) - if (copy_from_user(ch->tmp_buf, buf, count)) - count = 0; - - buf = ch->tmp_buf; - } - /* * All data is now local */ @@ -658,11 +606,11 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha remain = tail - head - 1; stlen = remain; } - count = MIN(remain, count); + count = min(remain, count); txwinon(ch); while (count > 0) { - stlen = MIN(count, stlen); + stlen = min(count, stlen); memcpy(ch->txptr + head, buf, stlen); buf += stlen; count -= stlen; @@ -683,16 +631,13 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha memoff(ch); restore_flags(flags); - if(from_user) - up(&ch->tmp_buf_sem); - return(total); } static void pcxe_put_char(struct tty_struct *tty, unsigned char c) { - pcxe_write(tty, 0, &c, 1); + pcxe_write(tty, &c, 1); return; } @@ -800,9 +745,7 @@ static void pcxe_flush_buffer(struct tty_struct *tty) memoff(ch); restore_flags(flags); - wake_up_interruptible(&tty->write_wait); - if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } static void pcxe_flush_chars(struct tty_struct *tty) @@ -1013,9 +956,6 @@ void __init pcxx_setup(char *str, int *ints) } #endif -module_init(pcxe_init) -module_exit(pcxe_exit) - static struct tty_operations pcxe_ops = { .open = pcxe_open, .close = pcxe_close, @@ -1561,6 +1501,8 @@ cleanup_boards: return ret; } +module_init(pcxe_init) +module_exit(pcxe_cleanup) static void pcxxpoll(unsigned long dummy) { @@ -1675,10 +1617,7 @@ static void doevent(int crd) if (event & LOWTX_IND) { if (ch->statusflags & LOWWAIT) { ch->statusflags &= ~LOWWAIT; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } @@ -1686,10 +1625,7 @@ static void doevent(int crd) ch->statusflags &= ~TXBUSY; if (ch->statusflags & EMPTYWAIT) { ch->statusflags &= ~EMPTYWAIT; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } } @@ -1995,6 +1931,7 @@ static int pcxe_tiocmget(struct tty_struct *tty, struct file *file) volatile struct board_chan *bc; unsigned long flags; int mflag = 0; + int mstat; if(ch) bc = ch->brdchan; @@ -2069,6 +2006,7 @@ static int pcxe_tiocmset(struct tty_struct *tty, struct file *file, pcxxparam(tty,ch); memoff(ch); restore_flags(flags); + return 0; } @@ -2165,8 +2103,7 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file, tty_wait_until_sent(tty, 0); } else { - if(tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); } /* Fall Thru */ diff --git a/drivers/char/pty.c b/drivers/char/pty.c index fcbb32547..a47386427 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -29,15 +29,9 @@ #include #include -#include +#include #include -#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS) - -#ifdef CONFIG_LEGACY_PTYS -static struct tty_driver *pty_driver, *pty_slave_driver; -#endif - /* These are global because they are accessed in tty_io.c */ #ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver; @@ -61,9 +55,9 @@ static void pty_close(struct tty_struct * tty, struct file * filp) if (!tty->link) return; tty->link->packet = 0; + set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); - set_bit(TTY_OTHER_CLOSED, &tty->link->flags); if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); #ifdef CONFIG_UNIX98_PTYS @@ -91,10 +85,7 @@ static void pty_unthrottle(struct tty_struct * tty) if (!o_tty) return; - if ((o_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - o_tty->ldisc.write_wakeup) - (o_tty->ldisc.write_wakeup)(o_tty); - wake_up_interruptible(&o_tty->write_wait); + tty_wakeup(o_tty); set_bit(TTY_THROTTLED, &tty->flags); } @@ -107,52 +98,23 @@ static void pty_unthrottle(struct tty_struct * tty) * (2) avoid redundant copying for cases where count >> receive_room * N.B. Calls from user space may now return an error code instead of * a count. + * + * FIXME: Our pty_write method is called with our ldisc lock held but + * not our partners. We can't just take the other one blindly without + * risking deadlocks. There is also the small matter of TTY_DONT_FLIP */ -static int pty_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c=0, n, room; - char *temp_buffer; + int c; if (!to || tty->stopped) return 0; - if (from_user) { - down(&tty->flip.pty_sem); - temp_buffer = &tty->flip.char_buf[0]; - while (count > 0) { - /* check space so we don't copy needlessly */ - n = to->ldisc.receive_room(to); - if (n > count) - n = count; - if (!n) break; - - n = min(n, PTY_BUF_SIZE); - n -= copy_from_user(temp_buffer, buf, n); - if (!n) { - if (!c) - c = -EFAULT; - break; - } - - /* check again in case the buffer filled up */ - room = to->ldisc.receive_room(to); - if (n > room) - n = room; - if (!n) break; - buf += n; - c += n; - count -= n; - to->ldisc.receive_buf(to, temp_buffer, NULL, n); - } - up(&tty->flip.pty_sem); - } else { - c = to->ldisc.receive_room(to); - if (c > count) - c = count; - to->ldisc.receive_buf(to, buf, NULL, c); - } + c = to->ldisc.receive_room(to); + if (c > count) + c = count; + to->ldisc.receive_buf(to, buf, NULL, c); return c; } @@ -205,19 +167,6 @@ static int pty_chars_in_buffer(struct tty_struct *tty) return ((count < N_TTY_BUF_SIZE/2) ? 0 : count); } -/* - * Return the device number of a Unix98 PTY (only!). This lets us open a - * master pty with the multi-headed ptmx device, then find out which - * one we got after it is open, with an ioctl. - */ -#ifdef CONFIG_UNIX98_PTYS -static int pty_get_device_number(struct tty_struct *tty, unsigned __user *value) -{ - unsigned int result = tty->index; - return put_user(result, value); -} -#endif - /* Set the lock flag on a pty */ static int pty_set_lock(struct tty_struct *tty, int __user * arg) { @@ -231,41 +180,6 @@ static int pty_set_lock(struct tty_struct *tty, int __user * arg) return 0; } -#ifdef CONFIG_LEGACY_PTYS -static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (!tty) { - printk("pty_ioctl called with NULL tty!\n"); - return -EIO; - } - switch(cmd) { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - return pty_set_lock(tty, (int __user *) arg); - } - return -ENOIOCTLCMD; -} -#endif - -#ifdef CONFIG_UNIX98_PTYS -static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (!tty) { - printk("pty_unix98_ioctl called with NULL tty!\n"); - return -EIO; - } - switch(cmd) { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - return pty_set_lock(tty, (int __user *)arg); - case TIOCGPTN: /* Get PT Number */ - return pty_get_device_number(tty, (unsigned int __user *)arg); - } - - return -ENOIOCTLCMD; -} -#endif - static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; @@ -322,42 +236,22 @@ static struct tty_operations pty_ops = { .set_termios = pty_set_termios, }; -/* sysctl support for setting limits on the number of Unix98 ptys allocated. - Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */ -#ifdef CONFIG_UNIX98_PTYS -int pty_limit = NR_UNIX98_PTY_DEFAULT; -static int pty_limit_min = 0; -static int pty_limit_max = NR_UNIX98_PTY_MAX; +/* Traditional BSD devices */ +#ifdef CONFIG_LEGACY_PTYS +static struct tty_driver *pty_driver, *pty_slave_driver; -ctl_table pty_table[] = { - { - .ctl_name = PTY_MAX, - .procname = "max", - .maxlen = sizeof(int), - .mode = 0644, - .data = &pty_limit, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &pty_limit_min, - .extra2 = &pty_limit_max, - }, { - .ctl_name = PTY_NR, - .procname = "nr", - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec, - }, { - .ctl_name = 0 +static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ + return pty_set_lock(tty, (int __user *) arg); } -}; -#endif - -/* Initialization */ + return -ENOIOCTLCMD; +} -static int __init pty_init(void) +static void __init legacy_pty_init(void) { -#ifdef CONFIG_LEGACY_PTYS - /* Traditional BSD devices */ pty_driver = alloc_tty_driver(NR_PTYS); if (!pty_driver) @@ -404,11 +298,58 @@ static int __init pty_init(void) panic("Couldn't register pty driver"); if (tty_register_driver(pty_slave_driver)) panic("Couldn't register pty slave driver"); +} +#else +static inline void legacy_pty_init(void) { } +#endif -#endif /* CONFIG_LEGACY_PTYS */ - +/* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS - /* Unix98 devices */ +/* + * sysctl support for setting limits on the number of Unix98 ptys allocated. + * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. + */ +int pty_limit = NR_UNIX98_PTY_DEFAULT; +static int pty_limit_min = 0; +static int pty_limit_max = NR_UNIX98_PTY_MAX; + +ctl_table pty_table[] = { + { + .ctl_name = PTY_MAX, + .procname = "max", + .maxlen = sizeof(int), + .mode = 0644, + .data = &pty_limit, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &pty_limit_min, + .extra2 = &pty_limit_max, + }, { + .ctl_name = PTY_NR, + .procname = "nr", + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { + .ctl_name = 0 + } +}; + +static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ + return pty_set_lock(tty, (int __user *)arg); + case TIOCGPTN: /* Get PT Number */ + return put_user(tty->index, (unsigned int __user *)arg); + } + + return -ENOIOCTLCMD; +} + +static void __init unix98_pty_init(void) +{ devfs_mk_dir("pts"); ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!ptm_driver) @@ -455,10 +396,15 @@ static int __init pty_init(void) panic("Couldn't register Unix98 pts driver"); pty_table[1].data = &ptm_driver->refcount; -#endif /* CONFIG_UNIX98_PTYS */ +} +#else +static inline void unix98_pty_init(void) { } +#endif +static int __init pty_init(void) +{ + legacy_pty_init(); + unix98_pty_init(); return 0; } module_init(pty_init); - -#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */ diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c index 4698af2d6..e0bb00f3c 100644 --- a/drivers/char/qtronix.c +++ b/drivers/char/qtronix.c @@ -79,7 +79,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/char/random.c b/drivers/char/random.c index e39179f50..cfd25286c 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -401,6 +401,7 @@ static struct poolinfo { */ static struct entropy_store *random_state; /* The default global store */ static struct entropy_store *sec_random_state; /* secondary store */ +static struct entropy_store *urandom_state; /* For urandom */ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); @@ -493,6 +494,7 @@ struct entropy_store { /* mostly-read data: */ struct poolinfo poolinfo; __u32 *pool; + const char *name; /* read-write data: */ spinlock_t lock ____cacheline_aligned_in_smp; @@ -507,7 +509,8 @@ struct entropy_store { * * Returns an negative error if there is a problem. */ -static int create_entropy_store(int size, struct entropy_store **ret_bucket) +static int create_entropy_store(int size, const char *name, + struct entropy_store **ret_bucket) { struct entropy_store *r; struct poolinfo *p; @@ -538,6 +541,7 @@ static int create_entropy_store(int size, struct entropy_store **ret_bucket) } memset(r->pool, 0, POOLBYTES); r->lock = SPIN_LOCK_UNLOCKED; + r->name = name; *ret_bucket = r; return 0; } @@ -568,8 +572,8 @@ static void free_entropy_store(struct entropy_store *r) * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void add_entropy_words(struct entropy_store *r, const __u32 *in, - int nwords) +static void __add_entropy_words(struct entropy_store *r, const __u32 *in, + int nwords, __u32 out[16]) { static __u32 const twist_table[8] = { 0, 0x3b6e20c8, 0x76dc4190, 0x4db26158, @@ -622,9 +626,23 @@ static void add_entropy_words(struct entropy_store *r, const __u32 *in, r->input_rotate = input_rotate; r->add_ptr = add_ptr; + if (out) { + for (i = 0; i < 16; i++) { + out[i] = r->pool[add_ptr]; + add_ptr = (add_ptr - 1) & wordmask; + } + } + spin_unlock_irqrestore(&r->lock, flags); } +static inline void add_entropy_words(struct entropy_store *r, const __u32 *in, + int nwords) +{ + __add_entropy_words(r, in, nwords, NULL); +} + + /* * Credit (or debit) the entropy store with n bits of entropy */ @@ -643,12 +661,8 @@ static void credit_entropy_store(struct entropy_store *r, int nbits) } else { r->entropy_count += nbits; if (nbits) - DEBUG_ENT("%04d %04d : added %d bits to %s\n", - random_state->entropy_count, - sec_random_state->entropy_count, - nbits, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown"); + DEBUG_ENT("Added %d entropy credits to %s, now %d\n", + nbits, r->name, r->entropy_count); } spin_unlock_irqrestore(&r->lock, flags); @@ -698,7 +712,7 @@ static int __init batch_entropy_init(int size, struct entropy_store *r) * hashing calculations during an interrupt in add_timer_randomness(). * Instead, the entropy is only added to the pool by keventd. */ -void batch_entropy_store(u32 a, u32 b, int num) +static void batch_entropy_store(u32 a, u32 b, int num) { int new; unsigned long flags; @@ -729,8 +743,6 @@ void batch_entropy_store(u32 a, u32 b, int num) spin_unlock_irqrestore(&batch_lock, flags); } -EXPORT_SYMBOL(batch_entropy_store); - /* * Flush out the accumulated entropy operations, adding entropy to the passed * store (normally random_state). If that store has enough entropy, alternate @@ -781,9 +793,9 @@ static void batch_entropy_process(void *private_) /* There is one of these per entropy source */ struct timer_rand_state { - __u32 last_time; - __s32 last_delta,last_delta2; - int dont_count_entropy:1; + cycles_t last_time; + long last_delta,last_delta2; + unsigned dont_count_entropy:1; }; static struct timer_rand_state keyboard_timer_state; @@ -799,37 +811,29 @@ static struct timer_rand_state *irq_timer_state[NR_IRQS]; * The number "num" is also added to the pool - it should somehow describe * the type of event which just happened. This is currently 0-255 for * keyboard scan codes, and 256 upwards for interrupts. - * On the i386, this is assumed to be at most 16 bits, and the high bits - * are used for a high-resolution timer. * */ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) { - __u32 time; - __s32 delta, delta2, delta3; + cycles_t time; + long delta, delta2, delta3; int entropy = 0; + preempt_disable(); /* if over the trickle threshold, use only 1 in 4096 samples */ if ( random_state->entropy_count > trickle_thresh && (__get_cpu_var(trickle_count)++ & 0xfff)) - return; + goto out; -#if defined (__i386__) || defined (__x86_64__) - if (cpu_has_tsc) { - __u32 high; - rdtsc(time, high); - num ^= high; - } else { + /* + * Use get_cycles() if implemented, otherwise fall back to + * jiffies. + */ + time = get_cycles(); + if (time) + num ^= (u32)((time >> 31) >> 1); + else time = jiffies; - } -#elif defined (__sparc_v9__) - unsigned long tick = tick_ops->get_tick(); - - time = (unsigned int) tick; - num ^= (tick >> 32UL); -#else - time = jiffies; -#endif /* * Calculate number of bits of randomness we probably added. @@ -868,6 +872,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) entropy = int_ln_12bits(delta); } batch_entropy_store(num, time, entropy); +out: + preempt_enable(); } void add_keyboard_randomness(unsigned char scancode) @@ -880,8 +886,6 @@ void add_keyboard_randomness(unsigned char scancode) } } -EXPORT_SYMBOL(add_keyboard_randomness); - void add_mouse_randomness(__u32 mouse_data) { add_timer_randomness(&mouse_timer_state, mouse_data); @@ -897,8 +901,6 @@ void add_interrupt_randomness(int irq) add_timer_randomness(irq_timer_state[irq], 0x100+irq); } -EXPORT_SYMBOL(add_interrupt_randomness); - void add_disk_randomness(struct gendisk *disk) { if (!disk || !disk->random) @@ -1328,8 +1330,7 @@ static inline void xfer_secondary_pool(struct entropy_store *r, "(%d of %d requested)\n", random_state->entropy_count, sec_random_state->entropy_count, - r == sec_random_state ? "secondary" : "unknown", - bytes * 8, nbytes * 8, r->entropy_count); + r->name, bytes * 8, nbytes * 8, r->entropy_count); bytes=extract_entropy(random_state, tmp, bytes, EXTRACT_ENTROPY_LIMIT); @@ -1355,7 +1356,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, size_t nbytes, int flags) { ssize_t ret, i; - __u32 tmp[TMP_BUF_SIZE]; + __u32 tmp[TMP_BUF_SIZE], data[16]; __u32 x; unsigned long cpuflags; @@ -1373,9 +1374,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, DEBUG_ENT("%04d %04d : trying to extract %d bits from %s\n", random_state->entropy_count, sec_random_state->entropy_count, - nbytes * 8, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown"); + nbytes * 8, r->name); if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8) nbytes = r->entropy_count / 8; @@ -1388,12 +1387,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, if (r->entropy_count < random_write_wakeup_thresh) wake_up_interruptible(&random_write_wait); - DEBUG_ENT("%04d %04d : debiting %d bits from %s%s\n", - random_state->entropy_count, - sec_random_state->entropy_count, - nbytes * 8, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown", + DEBUG_ENT("Debiting %d entropy credits from %s%s\n", + nbytes * 8, r->name, flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)"); spin_unlock_irqrestore(&r->lock, cpuflags); @@ -1441,7 +1436,15 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, HASH_TRANSFORM(tmp, r->pool+i); add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1); } - + + /* + * To avoid duplicates, we atomically extract a + * portion of the pool while mixing, and hash one + * final time. + */ + __add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1, data); + HASH_TRANSFORM(tmp, data); + /* * In case the hash function has some recognizable * output pattern, we fold it in half. @@ -1482,14 +1485,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, */ void get_random_bytes(void *buf, int nbytes) { - if (sec_random_state) - extract_entropy(sec_random_state, (char *) buf, nbytes, - EXTRACT_ENTROPY_SECONDARY); - else if (random_state) - extract_entropy(random_state, (char *) buf, nbytes, 0); - else + struct entropy_store *r = urandom_state; + int flags = EXTRACT_ENTROPY_SECONDARY; + + if (!r) + r = sec_random_state; + if (!r) { + r = random_state; + flags = 0; + } + if (!r) { printk(KERN_NOTICE "get_random_bytes called before " "random driver initialization\n"); + return; + } + extract_entropy(r, (char *) buf, nbytes, flags); } EXPORT_SYMBOL(get_random_bytes); @@ -1533,15 +1543,22 @@ static int __init rand_initialize(void) { int i; - if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state)) + if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state)) goto err; if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state)) goto err; - if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state)) + if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary", + &sec_random_state)) + goto err; + if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom", + &urandom_state)) goto err; clear_entropy_store(random_state); clear_entropy_store(sec_random_state); + clear_entropy_store(urandom_state); init_std_data(random_state); + init_std_data(sec_random_state); + init_std_data(urandom_state); #ifdef CONFIG_SYSCTL sysctl_init_random(random_state); #endif @@ -1674,9 +1691,15 @@ static ssize_t urandom_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) { - return extract_entropy(sec_random_state, buf, nbytes, - EXTRACT_ENTROPY_USER | - EXTRACT_ENTROPY_SECONDARY); + int flags = EXTRACT_ENTROPY_USER; + unsigned long cpuflags; + + spin_lock_irqsave(&random_state->lock, cpuflags); + if (random_state->entropy_count > random_state->poolinfo.POOLBITS) + flags |= EXTRACT_ENTROPY_SECONDARY; + spin_unlock_irqrestore(&random_state->lock, cpuflags); + + return extract_entropy(urandom_state, buf, nbytes, flags); } static unsigned int @@ -1730,10 +1753,9 @@ static int random_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - int *tmp, size, ent_count; + int size, ent_count; int __user *p = (int __user *)arg; int retval; - unsigned long flags; switch (cmd) { case RNDGETENTCNT: @@ -1754,40 +1776,6 @@ random_ioctl(struct inode * inode, struct file * file, if (random_state->entropy_count >= random_read_wakeup_thresh) wake_up_interruptible(&random_read_wait); return 0; - case RNDGETPOOL: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(size, p) || - put_user(random_state->poolinfo.poolwords, p++)) - return -EFAULT; - if (size < 0) - return -EFAULT; - if (size > random_state->poolinfo.poolwords) - size = random_state->poolinfo.poolwords; - - /* prepare to atomically snapshot pool */ - - tmp = kmalloc(size * sizeof(__u32), GFP_KERNEL); - - if (!tmp) - return -ENOMEM; - - spin_lock_irqsave(&random_state->lock, flags); - ent_count = random_state->entropy_count; - memcpy(tmp, random_state->pool, size * sizeof(__u32)); - spin_unlock_irqrestore(&random_state->lock, flags); - - if (!copy_to_user(p, tmp, size * sizeof(__u32))) { - kfree(tmp); - return -EFAULT; - } - - kfree(tmp); - - if(put_user(ent_count, p++)) - return -EFAULT; - - return 0; case RNDADDENTROPY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1884,7 +1872,8 @@ static int change_poolsize(int poolsize) struct entropy_store *new_store, *old_store; int ret; - if ((ret = create_entropy_store(poolsize, &new_store))) + if ((ret = create_entropy_store(poolsize, random_state->name, + &new_store))) return ret; add_entropy_words(new_store, random_state->pool, @@ -2079,6 +2068,7 @@ static void sysctl_init_random(struct entropy_store *random_state) * ********************************************************************/ +#ifdef CONFIG_INET /* * TCP initial sequence number picking. This uses the random number * generator to pick an initial secret value. This value is hashed @@ -2212,7 +2202,7 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12]) #undef K3 /* This should not be decreased so low that ISNs wrap too fast. */ -#define REKEY_INTERVAL 300 +#define REKEY_INTERVAL (300*HZ) /* * Bit layout of the tcp sequence numbers (before adding current time): * bit 24-31: increased after every key exchange @@ -2238,43 +2228,55 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12]) #define HASH_MASK ( (1<rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = &ip_keydata[1^(ip_cnt&1)]; - keyptr->rekey_time = time; - get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); - keyptr->count = (ip_cnt&COUNT_MASK)<secret, sizeof(keyptr->secret)); + keyptr->count = (ip_cnt&COUNT_MASK)<rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = __check_and_rekey(time); - } + smp_rmb(); return keyptr; } +static __init int seqgen_init(void) +{ + rekey_seq_generator(NULL); + return 0; +} +late_initcall(seqgen_init); + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, __u16 sport, __u16 dport) @@ -2282,14 +2284,12 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, struct timeval tv; __u32 seq; __u32 hash[12]; - struct keydata *keyptr; + struct keydata *keyptr = get_keyptr(); /* The procedure is the same as for IPv4, but addresses are longer. * Thus we must use twothirdsMD4Transform. */ - do_gettimeofday(&tv); /* We need the usecs below... */ - keyptr = check_and_rekey(tv.tv_sec); memcpy(hash, saddr, 16); hash[4]=(sport << 16) + dport; @@ -2297,38 +2297,22 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK; seq += keyptr->count; + + do_gettimeofday(&tv); seq += tv.tv_usec + tv.tv_sec*1000000; return seq; } EXPORT_SYMBOL(secure_tcpv6_sequence_number); - -__u32 secure_ipv6_id(__u32 *daddr) -{ - struct keydata *keyptr; - - keyptr = check_and_rekey(get_seconds()); - - return halfMD4Transform(daddr, keyptr->secret); -} - -EXPORT_SYMBOL(secure_ipv6_id); #endif - __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport) { struct timeval tv; __u32 seq; __u32 hash[4]; - struct keydata *keyptr; - - /* - * Pick a random secret every REKEY_INTERVAL seconds. - */ - do_gettimeofday(&tv); /* We need the usecs below... */ - keyptr = check_and_rekey(tv.tv_sec); + struct keydata *keyptr = get_keyptr(); /* * Pick a unique starting offset for each TCP connection endpoints @@ -2351,6 +2335,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, * That's funny, Linux has one built in! Use it! * (Networks are faster now - should this be increased?) */ + do_gettimeofday(&tv); seq += tv.tv_usec + tv.tv_sec*1000000; #if 0 printk("init_seq(%lx, %lx, %d, %d) = %d\n", @@ -2369,7 +2354,7 @@ __u32 secure_ip_id(__u32 daddr) struct keydata *keyptr; __u32 hash[4]; - keyptr = check_and_rekey(get_seconds()); + keyptr = get_keyptr(); /* * Pick a unique starting offset for each IP destination. @@ -2483,3 +2468,4 @@ __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport, return (cookie - tmp[17]) & COOKIEMASK; /* Leaving the data behind */ } #endif +#endif /* CONFIG_INET */ diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index 26063cb6a..d53843abe 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include #define disable(oldspl) save_flags (oldspl) diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index a11fafbab..aa23b1cba 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -236,9 +236,9 @@ long rio_irqmask = -1; MODULE_AUTHOR("Rogier Wolff , Patrick van de Lageweg "); MODULE_DESCRIPTION("RIO driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(rio_poll, "i"); -MODULE_PARM(rio_debug, "i"); -MODULE_PARM(rio_irqmask, "i"); +module_param(rio_poll, int, 0); +module_param(rio_debug, int, 0644); +module_param(rio_irqmask, long, 0); static struct real_driver rio_real_driver = { rio_disable_tx_interrupts, @@ -330,8 +330,7 @@ int RIODelay (struct Port *PortP, int njiffies) func_enter (); rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(njiffies); + msleep_interruptible(jiffies_to_msecs(njiffies)); func_exit(); if (signal_pending(current)) @@ -347,8 +346,7 @@ int RIODelay_ni (struct Port *PortP, int njiffies) func_enter (); rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(njiffies); + msleep(jiffies_to_msecs(njiffies)); func_exit(); return !RIO_FAIL; } @@ -1138,8 +1136,8 @@ static int __init rio_init(void) hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; - hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; @@ -1196,8 +1194,8 @@ static int __init rio_init(void) if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ - hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; @@ -1242,8 +1240,8 @@ static int __init rio_init(void) hp->PaddrP = rio_probe_addrs[i]; /* There was something about the IRQs of these cards. 'Forget what.--REW */ hp->Ivec = 0; - hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); + hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_AT; hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL * -- YES! this is now a normal copy. Only the diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 69108ceea..55a3a0188 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -75,10 +76,6 @@ ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #define RS_EVENT_WRITE_WAKEUP 0 static struct riscom_board * IRQ_to_board[16]; @@ -107,7 +104,7 @@ static struct riscom_board rc_board[RC_NBOARD] = { }; static struct riscom_port rc_port[RC_NBOARD * RC_NPORT]; - + /* RISCom/8 I/O ports addresses (without address translation) */ static unsigned short rc_ioport[] = { #if 1 @@ -483,7 +480,7 @@ static inline void rc_transmit(struct riscom_board const * bp) rc_out(bp, CD180_TDR, CD180_C_SBRK); port->COR2 &= ~COR2_ETC; } - count = MIN(port->break_length, 0xff); + count = min_t(int, port->break_length, 0xff); rc_out(bp, CD180_TDR, CD180_C_ESC); rc_out(bp, CD180_TDR, CD180_C_DELAY); rc_out(bp, CD180_TDR, count); @@ -1118,8 +1115,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp) */ timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->timeout); + msleep_interruptible(jiffies_to_msecs(port->timeout)); if (time_after(jiffies, timeout)) break; } @@ -1127,15 +1123,14 @@ static void rc_close(struct tty_struct * tty, struct file * filp) rc_shutdown_port(bp, port); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); + tty->closing = 0; port->event = 0; port->tty = NULL; if (port->blocked_open) { if (port->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->close_delay); + msleep_interruptible(jiffies_to_msecs(port->close_delay)); } wake_up_interruptible(&port->open_wait); } @@ -1144,7 +1139,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp) out: restore_flags(flags); } -static int rc_write(struct tty_struct * tty, int from_user, +static int rc_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct riscom_port *port = (struct riscom_port *)tty->driver_data; @@ -1161,54 +1156,23 @@ static int rc_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); @@ -1301,9 +1265,7 @@ static void rc_flush_buffer(struct tty_struct *tty) restore_flags(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } static int rc_tiocmget(struct tty_struct *tty, struct file *file) @@ -1644,9 +1606,7 @@ static void do_softint(void *private_) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 129b8ccd8..5bcbeb0cb 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -91,7 +91,7 @@ #include #include #include -#include +#include #include #include #include @@ -123,7 +123,7 @@ static unsigned long board2; static unsigned long board3; static unsigned long board4; static unsigned long controller; -static unsigned long support_low_speed; +static int support_low_speed; static unsigned long modem1; static unsigned long modem2; static unsigned long modem3; @@ -181,33 +181,33 @@ static void rp_start(struct tty_struct *tty); #ifdef MODULE MODULE_AUTHOR("Theodore Ts'o"); MODULE_DESCRIPTION("Comtrol RocketPort driver"); -MODULE_PARM(board1, "i"); +module_param(board1, ulong, 0); MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1"); -MODULE_PARM(board2, "i"); +module_param(board2, ulong, 0); MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2"); -MODULE_PARM(board3, "i"); +module_param(board3, ulong, 0); MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3"); -MODULE_PARM(board4, "i"); +module_param(board4, ulong, 0); MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4"); -MODULE_PARM(controller, "i"); +module_param(controller, ulong, 0); MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller"); -MODULE_PARM(support_low_speed, "i"); +module_param(support_low_speed, bool, 0); MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud"); -MODULE_PARM(modem1, "i"); +module_param(modem1, ulong, 0); MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem"); -MODULE_PARM(modem2, "i"); +module_param(modem2, ulong, 0); MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem"); -MODULE_PARM(modem3, "i"); +module_param(modem3, ulong, 0); MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem"); -MODULE_PARM(modem4, "i"); +module_param(modem4, ulong, 0); MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem"); -MODULE_PARM(pc104_1, "1-8i"); +module_param_array(pc104_1, ulong, NULL, 0); MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,..."); -MODULE_PARM(pc104_2, "1-8i"); +module_param_array(pc104_2, ulong, NULL, 0); MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,..."); -MODULE_PARM(pc104_3, "1-8i"); +module_param_array(pc104_3, ulong, NULL, 0); MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,..."); -MODULE_PARM(pc104_4, "1-8i"); +module_param_array(pc104_4, ulong, NULL, 0); MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,..."); int rp_init(void); @@ -250,12 +250,16 @@ static void rp_do_receive(struct r_port *info, CHANNEL_t * cp, unsigned int ChanStatus) { unsigned int CharNStat; - int ToRecv, wRecv, space, count; + int ToRecv, wRecv, space = 0, count; unsigned char *cbuf; char *fbuf; + struct tty_ldisc *ld; + + ld = tty_ldisc_ref(tty); ToRecv = sGetRxCnt(cp); - space = tty->ldisc.receive_room(tty); + if (ld) + space = ld->receive_room(tty); if (space > 2 * TTY_FLIPBUF_SIZE) space = 2 * TTY_FLIPBUF_SIZE; cbuf = tty->flip.char_buf; @@ -354,7 +358,8 @@ static void rp_do_receive(struct r_port *info, count += ToRecv; } /* Push the data up to the tty layer */ - tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count); + ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count); + tty_ldisc_deref(ld); } /* @@ -389,7 +394,7 @@ static void rp_do_transmit(struct r_port *info) while (1) { if (tty->stopped || tty->hw_stopped) break; - c = MIN(info->xmit_fifo_room, MIN(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail)); + c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail)); if (c <= 0 || info->xmit_fifo_room <= 0) break; sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2); @@ -408,8 +413,7 @@ static void rp_do_transmit(struct r_port *info) clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); if (info->xmit_cnt < WAKEUP_CHARS) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); @@ -1022,7 +1026,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) unsigned long flags; int timeout; CHANNEL_t *cp; - + if (rocket_paranoia_check(info, "rp_close")) return; @@ -1101,15 +1105,14 @@ static void rp_close(struct tty_struct *tty, struct file *filp) if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty)) TTY_DRIVER_FLUSH_BUFFER(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } else { @@ -1283,11 +1286,7 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) return -EFAULT; -#ifdef CAP_SYS_ADMIN if (!capable(CAP_SYS_ADMIN)) -#else - if (!suser()) -#endif { if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) return -EPERM; @@ -1538,8 +1537,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...", txcnt, jiffies, check_time); #endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(check_time); + msleep_interruptible(jiffies_to_msecs(check_time)); if (signal_pending(current)) break; } @@ -1635,7 +1633,7 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). * Spinlocks protect the info xmit members. */ -static int rp_write(struct tty_struct *tty, int from_user, +static int rp_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct r_port *info = (struct r_port *) tty->driver_data; @@ -1662,18 +1660,8 @@ static int rp_write(struct tty_struct *tty, int from_user, * into FIFO. Use the write queue for temp storage. */ if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) { - c = MIN(count, info->xmit_fifo_room); + c = min(count, info->xmit_fifo_room); b = buf; - if (from_user) { - if (copy_from_user(info->xmit_buf, buf, c)) { - retval = -EFAULT; - goto end; - } - if (info->tty == 0) - goto end; - b = info->xmit_buf; - c = MIN(c, info->xmit_fifo_room); - } /* Push data into FIFO, 2 bytes at a time */ sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2); @@ -1700,19 +1688,12 @@ static int rp_write(struct tty_struct *tty, int from_user, if (info->tty == 0) /* Seemingly obligatory check... */ goto end; - c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head)); + c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head)); if (c <= 0) break; b = buf; - if (from_user) { - if (copy_from_user(info->xmit_buf + info->xmit_head, b, c)) { - retval = -EFAULT; - goto end_intr; - } else { - memcpy(info->xmit_buf + info->xmit_head, b, c); - } - } + memcpy(info->xmit_buf + info->xmit_head, b, c); spin_lock_irqsave(&info->slock, flags); info->xmit_head = @@ -1725,14 +1706,12 @@ static int rp_write(struct tty_struct *tty, int from_user, retval += c; } -end_intr: if ((retval > 0) && !tty->stopped && !tty->hw_stopped) set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); end: if (info->xmit_cnt < WAKEUP_CHARS) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); @@ -1806,8 +1785,7 @@ static void rp_flush_buffer(struct tty_struct *tty) #ifdef ROCKETPORT_HAVE_POLL_WAIT wake_up_interruptible(&tty->poll_wait); #endif - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); cp = &info->channel; sFlushTxFIFO(cp); @@ -2475,30 +2453,6 @@ static void rp_cleanup_module(void) } #endif -/*********************************************************************** - Copyright 1994 Comtrol Corporation. - All Rights Reserved. - -The following source code is subject to Comtrol Corporation's -Developer's License Agreement. - -This source code is protected by United States copyright law and -international copyright treaties. - -This source code may only be used to develop software products that -will operate with Comtrol brand hardware. - -You may not reproduce nor distribute this source code in its original -form but must produce a derivative work which includes portions of -this source code only. - -The portions of this source code which you use in your derivative -work must bear Comtrol's copyright notice: - - Copyright 1994 Comtrol Corporation. - -***********************************************************************/ - #ifndef TRUE #define TRUE 1 #endif diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 9380ff53f..802687290 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h @@ -1241,10 +1241,6 @@ struct r_port { #define TTY_ROCKET_MAJOR 46 #define CUA_ROCKET_MAJOR 47 -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #ifdef PCI_VENDOR_ID_RP #undef PCI_VENDOR_ID_RP #undef PCI_DEVICE_ID_RP8OCTA diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 598f60110..0c265fe67 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -26,10 +26,6 @@ #include #include -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* Don't take this from : 011-015 on the screen aren't spaces */ #define isspace(c) ((c) == ' ') @@ -281,12 +277,15 @@ int paste_selection(struct tty_struct *tty) { struct vt_struct *vt = (struct vt_struct *) tty->driver_data; int pasted = 0, count; + struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); acquire_console_sem(); poke_blanked_console(); release_console_sem(); + ld = tty_ldisc_ref_wait(tty); + add_wait_queue(&vt->paste_wait, &wait); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); @@ -295,14 +294,13 @@ int paste_selection(struct tty_struct *tty) continue; } count = sel_buffer_lth - pasted; - count = MIN(count, tty->ldisc.receive_room(tty)); + count = min(count, tty->ldisc.receive_room(tty)); tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count); pasted += count; } remove_wait_queue(&vt->paste_wait, &wait); current->state = TASK_RUNNING; + + tty_ldisc_deref(ld); return 0; } - -EXPORT_SYMBOL(set_selection); -EXPORT_SYMBOL(paste_selection); diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index f0b966876..6b4e9d155 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -599,10 +599,7 @@ int ch, err, n, p; /* WakeUp if output buffer runs low */ if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){ - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); - } - wake_up_interruptible(&port->gs.tty->write_wait); + tty_wakeup(port->gs.tty); } } // if the port is used } // for every port on the board diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 1b51eecfb..c2deac968 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -39,6 +39,9 @@ * - don't use the panic function in serial167_init * - do resource release on failure on serial167_init * - include missing restore_flags in mvme167_serial_console_setup + * + * Kars de Jong - 2004/09/06 + * - replace bottom half handler with task queue handler */ #include @@ -59,10 +62,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -83,18 +86,12 @@ #undef CYCLOM_16Y_HACK #define CYCLOM_ENABLE_MONITORING -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #define WAKEUP_CHARS 256 #define STD_COM_FLAGS (0) #define SERIAL_TYPE_NORMAL 1 -DECLARE_TASK_QUEUE(tq_cyclades); - static struct tty_driver *cy_serial_driver; extern int serial_console; static struct cyclades_port *serial_console_info = NULL; @@ -377,8 +374,7 @@ static inline void cy_sched_event(struct cyclades_port *info, int event) { info->event |= 1 << event; /* remember what kind of event and who */ - queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */ - mark_bh(CYCLADES_BH); /* then trigger event */ + schedule_work(&info->tqueue); } /* cy_sched_event */ @@ -471,7 +467,7 @@ cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp) and nothing could be done about it!!! */ } } - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_delayed_work(&tty->flip.work, 1); /* end of service */ base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; return IRQ_HANDLED; @@ -706,7 +702,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) udelay(10L); #endif } - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_delayed_work(&tty->flip.work, 1); } /* end of service */ base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; @@ -717,7 +713,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * This routine is used to handle the "bottom half" processing for the * serial driver, known also the "software interrupt" processing. * This processing is done at the kernel interrupt level, after the - * cy_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This * is where time-consuming activities which can not be done in the * interrupt driver proper are done; the interrupt driver schedules * them using cy_sched_event(), and they get done here. @@ -725,9 +721,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * This is done through one level of indirection--the task queue. * When a hardware interrupt service routine wants service by the * driver's bottom half, it enqueues the appropriate tq_struct (one - * per port) to the tq_cyclades work queue and sets a request flag - * via mark_bh for processing that queue. When the time is right, - * do_cyclades_bh is called (because of the mark_bh) and it requests + * per port) to the keventd work queue and sets a request flag * that the work queue be processed. * * Although this may seem unwieldy, it gives the system a way to @@ -735,12 +729,6 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * structure) to the bottom half of the driver. Previous kernels * had to poll every port to see if that port needed servicing. */ -static void -do_cyclades_bh(void) -{ - run_task_queue(&tq_cyclades); -} /* do_cyclades_bh */ - static void do_softint(void *private_) { @@ -760,11 +748,7 @@ do_softint(void *private_) wake_up_interruptible(&info->open_wait); } if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup){ - (tty->ldisc.write_wakeup)(tty); - } - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } /* do_softint */ @@ -1216,7 +1200,7 @@ cy_flush_chars(struct tty_struct *tty) port is already active, there is no need to kick it. */ static int -cy_write(struct tty_struct * tty, int from_user, +cy_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; @@ -1235,53 +1219,23 @@ cy_write(struct tty_struct * tty, int from_user, return 0; } - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - local_irq_save(flags); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; + while (1) { + local_irq_save(flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { local_irq_restore(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - local_irq_save(flags); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - local_irq_restore(flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + local_irq_restore(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } if (info->xmit_cnt @@ -1343,10 +1297,7 @@ cy_flush_buffer(struct tty_struct *tty) local_irq_save(flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; local_irq_restore(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* cy_flush_buffer */ @@ -1846,22 +1797,12 @@ cy_close(struct tty_struct * tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); info->event = 0; info->tty = 0; - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -2329,8 +2270,6 @@ scrn[1] = '\0'; return ret; } - init_bh(CYCLADES_BH, do_cyclades_bh); - port_num = 0; info = cy_port; for (index = 0; index < 1; index++) { @@ -2368,8 +2307,7 @@ scrn[1] = '\0'; info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - info->tqueue.routine = do_softint; - info->tqueue.data = info; + INIT_WORK(&info->tqueue, do_softint, info); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); /* info->session */ @@ -2379,7 +2317,7 @@ scrn[1] = '\0'; | CyPARITY| CyFRAME| CyOVERRUN; /* info->timeout */ - printk("ttyS%1d ", info->line); + printk("ttyS%d ", info->line); port_num++;info++; if(!(port_num & 7)){ printk("\n "); diff --git a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c index 39717ed68..50ed6dfec 100644 --- a/drivers/char/serial_tx3912.c +++ b/drivers/char/serial_tx3912.c @@ -191,12 +191,9 @@ static inline void transmit_char_pio(struct rs_port *port) } if (port->gs.xmit_cnt <= port->gs.wakeup_chars) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - port->gs.tty->ldisc.write_wakeup) - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); + tty_wakeup(port->gs.tty); rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", port->gs.wakeup_chars); - wake_up_interruptible(&port->gs.tty->write_wait); } } diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 25917e08e..9d027ec55 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -21,7 +21,10 @@ #include #include #include +#include #include +#include +#include #include #include "snsc.h" @@ -364,17 +367,15 @@ int __init scdrv_init(void) { geoid_t geoid; - cmoduleid_t cmod; - int i; + cnodeid_t cnode; char devname[32]; char *devnamep; - module_t *m; struct sysctl_data_s *scd; void *salbuf; struct class_simple *snsc_class; dev_t first_dev, dev; - if (alloc_chrdev_region(&first_dev, 0, (MAX_SLABS*nummodules), + if (alloc_chrdev_region(&first_dev, 0, numionodes, SYSCTL_BASENAME) < 0) { printk("%s: failed to register SN system controller device\n", __FUNCTION__); @@ -382,16 +383,8 @@ scdrv_init(void) } snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME); - for (cmod = 0; cmod < nummodules; cmod++) { - m = sn_modules[cmod]; - for (i = 0; i <= MAX_SLABS; i++) { - - if (m->nodes[i] == -1) { - /* node is not alive in module */ - continue; - } - - geoid = m->geoid[i]; + for (cnode = 0; cnode < numionodes; cnode++) { + geoid = cnodeid_get_geoid(cnode); devnamep = devname; format_module_id(devnamep, geo_module(geoid), MODULE_FORMAT_BRIEF); @@ -410,7 +403,7 @@ scdrv_init(void) memset(scd, 0, sizeof (struct sysctl_data_s)); /* initialize sysctl device data fields */ - scd->scd_nasid = cnodeid_to_nasid(m->nodes[i]); + scd->scd_nasid = cnodeid_to_nasid(cnode); if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) { printk("%s: failed to allocate driver buffer" "(%s%s)\n", __FUNCTION__, @@ -431,7 +424,7 @@ scdrv_init(void) continue; } - dev = first_dev + m->nodes[i]; + dev = first_dev + cnode; cdev_init(&scd->scd_cdev, &scdrv_fops); if (cdev_add(&scd->scd_cdev, dev, 1)) { printk("%s: failed to register system" @@ -448,7 +441,6 @@ scdrv_init(void) ia64_sn_irtr_intr_enable(scd->scd_nasid, 0 /*ignored */ , SAL_IROUTER_INTR_RECV); - } } return 0; } diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 28418d57f..27eeed243 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1,7 +1,7 @@ /* * Sony Programmable I/O Control Device driver for VAIO * - * Copyright (C) 2001-2003 Stelian Pop + * Copyright (C) 2001-2004 Stelian Pop * * Copyright (C) 2001-2002 Alcôve * @@ -19,12 +19,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include @@ -53,74 +53,80 @@ #include "sonypi.h" #include -static struct sonypi_device sonypi_device; +MODULE_AUTHOR("Stelian Pop "); +MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(SONYPI_DRIVER_VERSION); + static int minor = -1; -static int verbose; /* = 0 */ -static int fnkeyinit; /* = 0 */ -static int camera; /* = 0 */ -static int compat; /* = 0 */ -static int useinput = 1; -static unsigned long mask = 0xffffffff; +module_param(minor, int, 0); +MODULE_PARM_DESC(minor, + "minor number of the misc device, default is -1 (automatic)"); -/* Inits the queue */ -static inline void sonypi_initq(void) { - sonypi_device.queue.head = sonypi_device.queue.tail = 0; - sonypi_device.queue.len = 0; - sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED; - init_waitqueue_head(&sonypi_device.queue.proc_list); -} +static int verbose; /* = 0 */ +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)"); -/* Pulls an event from the queue */ -static inline unsigned char sonypi_pullq(void) { - unsigned char result; - unsigned long flags; +static int fnkeyinit; /* = 0 */ +module_param(fnkeyinit, int, 0444); +MODULE_PARM_DESC(fnkeyinit, + "set this if your Fn keys do not generate any event"); - spin_lock_irqsave(&sonypi_device.queue.s_lock, flags); - if (!sonypi_device.queue.len) { - spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags); - return 0; - } - result = sonypi_device.queue.buf[sonypi_device.queue.head]; - sonypi_device.queue.head++; - sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1); - sonypi_device.queue.len--; - spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags); - return result; -} - -/* Pushes an event into the queue */ -static inline void sonypi_pushq(unsigned char event) { - unsigned long flags; - - spin_lock_irqsave(&sonypi_device.queue.s_lock, flags); - if (sonypi_device.queue.len == SONYPI_BUF_SIZE) { - /* remove the first element */ - sonypi_device.queue.head++; - sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1); - sonypi_device.queue.len--; - } - sonypi_device.queue.buf[sonypi_device.queue.tail] = event; - sonypi_device.queue.tail++; - sonypi_device.queue.tail &= (SONYPI_BUF_SIZE - 1); - sonypi_device.queue.len++; +static int camera; /* = 0 */ +module_param(camera, int, 0444); +MODULE_PARM_DESC(camera, + "set this if you have a MotionEye camera (PictureBook series)"); - kill_fasync(&sonypi_device.queue.fasync, SIGIO, POLL_IN); - wake_up_interruptible(&sonypi_device.queue.proc_list); - spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags); -} +static int compat; /* = 0 */ +module_param(compat, int, 0444); +MODULE_PARM_DESC(compat, + "set this if you want to enable backward compatibility mode"); -/* Tests if the queue is empty */ -static inline int sonypi_emptyq(void) { - int result; - unsigned long flags; +static unsigned long mask = 0xffffffff; +module_param(mask, ulong, 0644); +MODULE_PARM_DESC(mask, + "set this to the mask of event you want to enable (see doc)"); - spin_lock_irqsave(&sonypi_device.queue.s_lock, flags); - result = (sonypi_device.queue.len == 0); - spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags); - return result; +static int useinput = 1; +module_param(useinput, int, 0444); +MODULE_PARM_DESC(useinput, + "set this if you would like sonypi to feed events to the input subsystem"); + +static struct sonypi_device sonypi_device; + +static int sonypi_ec_write(u8 addr, u8 value) +{ +#ifdef CONFIG_ACPI_EC + if (SONYPI_ACPI_ACTIVE) + return ec_write(addr, value); +#endif + wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); + outb_p(0x81, SONYPI_CST_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(addr, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(value, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + return 0; } -static int ec_read16(u8 addr, u16 *value) { +static int sonypi_ec_read(u8 addr, u8 *value) +{ +#ifdef CONFIG_ACPI_EC + if (SONYPI_ACPI_ACTIVE) + return ec_read(addr, value); +#endif + wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); + outb_p(0x80, SONYPI_CST_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + outb_p(addr, SONYPI_DATA_IOPORT); + wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); + *value = inb_p(SONYPI_DATA_IOPORT); + return 0; +} + +static int ec_read16(u8 addr, u16 *value) +{ u8 val_lb, val_hb; if (sonypi_ec_read(addr, &val_lb)) return -1; @@ -131,21 +137,22 @@ static int ec_read16(u8 addr, u16 *value) { } /* Initializes the device - this comes from the AML code in the ACPI bios */ -static void sonypi_type1_srs(void) { +static void sonypi_type1_srs(void) +{ u32 v; pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v); - v = (v & 0xFFFF0000) | ((u32)sonypi_device.ioport1); + v = (v & 0xFFFF0000) | ((u32) sonypi_device.ioport1); pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v); pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v); - v = (v & 0xFFF0FFFF) | - (((u32)sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16); + v = (v & 0xFFF0FFFF) | + (((u32) sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16); pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v); v = inl(SONYPI_IRQ_PORT); - v &= ~(((u32)0x3) << SONYPI_IRQ_SHIFT); - v |= (((u32)sonypi_device.bits) << SONYPI_IRQ_SHIFT); + v &= ~(((u32) 0x3) << SONYPI_IRQ_SHIFT); + v |= (((u32) sonypi_device.bits) << SONYPI_IRQ_SHIFT); outl(v, SONYPI_IRQ_PORT); pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v); @@ -153,18 +160,20 @@ static void sonypi_type1_srs(void) { pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v); } -static void sonypi_type2_srs(void) { +static void sonypi_type2_srs(void) +{ if (sonypi_ec_write(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8)) printk(KERN_WARNING "ec_write failed\n"); - if (sonypi_ec_write(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF)) + if (sonypi_ec_write(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF)) printk(KERN_WARNING "ec_write failed\n"); - if (sonypi_ec_write(SONYPI_SIRQ, sonypi_device.bits)) + if (sonypi_ec_write(SONYPI_SIRQ, sonypi_device.bits)) printk(KERN_WARNING "ec_write failed\n"); udelay(10); } /* Disables the device - this comes from the AML code in the ACPI bios */ -static void sonypi_type1_dis(void) { +static void sonypi_type1_dis(void) +{ u32 v; pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v); @@ -176,7 +185,8 @@ static void sonypi_type1_dis(void) { outl(v, SONYPI_IRQ_PORT); } -static void sonypi_type2_dis(void) { +static void sonypi_type2_dis(void) +{ if (sonypi_ec_write(SONYPI_SHIB, 0)) printk(KERN_WARNING "ec_write failed\n"); if (sonypi_ec_write(SONYPI_SLOB, 0)) @@ -185,7 +195,8 @@ static void sonypi_type2_dis(void) { printk(KERN_WARNING "ec_write failed\n"); } -static u8 sonypi_call1(u8 dev) { +static u8 sonypi_call1(u8 dev) +{ u8 v1, v2; wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); @@ -195,7 +206,8 @@ static u8 sonypi_call1(u8 dev) { return v2; } -static u8 sonypi_call2(u8 dev, u8 fn) { +static u8 sonypi_call2(u8 dev, u8 fn) +{ u8 v1; wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); @@ -206,7 +218,8 @@ static u8 sonypi_call2(u8 dev, u8 fn) { return v1; } -static u8 sonypi_call3(u8 dev, u8 fn, u8 v) { +static u8 sonypi_call3(u8 dev, u8 fn, u8 v) +{ u8 v1; wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG); @@ -219,7 +232,10 @@ static u8 sonypi_call3(u8 dev, u8 fn, u8 v) { return v1; } -static u8 sonypi_read(u8 fn) { +#if 0 +/* Get brightness, hue etc. Unreliable... */ +static u8 sonypi_read(u8 fn) +{ u8 v1, v2; int n = 100; @@ -231,15 +247,17 @@ static u8 sonypi_read(u8 fn) { } return 0xff; } +#endif /* Set brightness, hue etc */ -static void sonypi_set(u8 fn, u8 v) { - +static void sonypi_set(u8 fn, u8 v) +{ wait_on_command(0, sonypi_call3(0x90, fn, v), ITERATIONS_SHORT); } /* Tests if the camera is ready */ -static int sonypi_camera_ready(void) { +static int sonypi_camera_ready(void) +{ u8 v; v = sonypi_call2(0x8f, SONYPI_CAMERA_STATUS); @@ -247,19 +265,20 @@ static int sonypi_camera_ready(void) { } /* Turns the camera off */ -static void sonypi_camera_off(void) { - +static void sonypi_camera_off(void) +{ sonypi_set(SONYPI_CAMERA_PICTURE, SONYPI_CAMERA_MUTE_MASK); if (!sonypi_device.camera_power) return; - sonypi_call2(0x91, 0); + sonypi_call2(0x91, 0); sonypi_device.camera_power = 0; } /* Turns the camera on */ -static void sonypi_camera_on(void) { +static void sonypi_camera_on(void) +{ int i, j; if (sonypi_device.camera_power) @@ -282,7 +301,7 @@ static void sonypi_camera_on(void) { if (i) break; } - + if (j == 0) { printk(KERN_WARNING "sonypi: failed to power on camera\n"); return; @@ -293,19 +312,42 @@ static void sonypi_camera_on(void) { } /* sets the bluetooth subsystem power state */ -static void sonypi_setbluetoothpower(u8 state) { - +static void sonypi_setbluetoothpower(u8 state) +{ state = !!state; - if (sonypi_device.bluetooth_power == state) + + if (sonypi_device.bluetooth_power == state) return; - + sonypi_call2(0x96, state); sonypi_call1(0x82); sonypi_device.bluetooth_power = state; } +static void input_keyrelease(void *data) +{ + struct input_dev *input_dev; + int key; + + while (1) { + if (kfifo_get(sonypi_device.input_fifo, + (unsigned char *)&input_dev, + sizeof(input_dev)) != sizeof(input_dev)) + return; + if (kfifo_get(sonypi_device.input_fifo, + (unsigned char *)&key, + sizeof(key)) != sizeof(key)) + return; + + msleep(10); + input_report_key(input_dev, key, 0); + input_sync(input_dev); + } +} + /* Interrupt handler: some event is available */ -static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) { +static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) +{ u8 v1, v2, event = 0; int i, j; @@ -315,9 +357,10 @@ static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) { for (i = 0; sonypi_eventtypes[i].model; i++) { if (sonypi_device.model != sonypi_eventtypes[i].model) continue; - if ((v2 & sonypi_eventtypes[i].data) != sonypi_eventtypes[i].data) + if ((v2 & sonypi_eventtypes[i].data) != + sonypi_eventtypes[i].data) continue; - if (! (mask & sonypi_eventtypes[i].mask)) + if (!(mask & sonypi_eventtypes[i].mask)) continue; for (j = 0; sonypi_eventtypes[i].events[j].event; j++) { if (v1 == sonypi_eventtypes[i].events[j].data) { @@ -328,124 +371,131 @@ static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) { } if (verbose) - printk(KERN_WARNING - "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1,v2); + printk(KERN_WARNING + "sonypi: unknown event port1=0x%02x,port2=0x%02x\n", + v1, v2); /* We need to return IRQ_HANDLED here because there *are* - * events belonging to the sonypi device we don't know about, + * events belonging to the sonypi device we don't know about, * but we still don't want those to pollute the logs... */ return IRQ_HANDLED; found: if (verbose > 1) - printk(KERN_INFO + printk(KERN_INFO "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2); -#ifdef SONYPI_USE_INPUT if (useinput) { - struct input_dev *jog_dev = &sonypi_device.jog_dev; - if (event == SONYPI_EVENT_JOGDIAL_PRESSED) - input_report_key(jog_dev, BTN_MIDDLE, 1); - else if (event == SONYPI_EVENT_ANYBUTTON_RELEASED) - input_report_key(jog_dev, BTN_MIDDLE, 0); - else if ((event == SONYPI_EVENT_JOGDIAL_UP) || - (event == SONYPI_EVENT_JOGDIAL_UP_PRESSED)) - input_report_rel(jog_dev, REL_WHEEL, 1); - else if ((event == SONYPI_EVENT_JOGDIAL_DOWN) || - (event == SONYPI_EVENT_JOGDIAL_DOWN_PRESSED)) - input_report_rel(jog_dev, REL_WHEEL, -1); - input_sync(jog_dev); + struct input_dev *input_jog_dev = &sonypi_device.input_jog_dev; + struct input_dev *input_key_dev = &sonypi_device.input_key_dev; + switch (event) { + case SONYPI_EVENT_JOGDIAL_UP: + case SONYPI_EVENT_JOGDIAL_UP_PRESSED: + input_report_rel(input_jog_dev, REL_WHEEL, 1); + break; + case SONYPI_EVENT_JOGDIAL_DOWN: + case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: + input_report_rel(input_jog_dev, REL_WHEEL, -1); + break; + case SONYPI_EVENT_JOGDIAL_PRESSED: { + int key = BTN_MIDDLE; + input_report_key(input_jog_dev, key, 1); + kfifo_put(sonypi_device.input_fifo, + (unsigned char *)&input_jog_dev, + sizeof(input_jog_dev)); + kfifo_put(sonypi_device.input_fifo, + (unsigned char *)&key, sizeof(key)); + break; + } + case SONYPI_EVENT_FNKEY_RELEASED: + /* Nothing, not all VAIOs generate this event */ + break; + } + input_sync(input_jog_dev); + + for (i = 0; sonypi_inputkeys[i].sonypiev; i++) { + int key; + + if (event != sonypi_inputkeys[i].sonypiev) + continue; + + key = sonypi_inputkeys[i].inputev; + input_report_key(input_key_dev, key, 1); + kfifo_put(sonypi_device.input_fifo, + (unsigned char *)&input_key_dev, + sizeof(input_key_dev)); + kfifo_put(sonypi_device.input_fifo, + (unsigned char *)&key, sizeof(key)); + } + input_sync(input_key_dev); + schedule_work(&sonypi_device.input_work); } -#endif /* SONYPI_USE_INPUT */ - sonypi_pushq(event); + + kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); + kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); + wake_up_interruptible(&sonypi_device.fifo_proc_list); + return IRQ_HANDLED; } /* External camera command (exported to the motion eye v4l driver) */ -u8 sonypi_camera_command(int command, u8 value) { - u8 ret = 0; - +int sonypi_camera_command(int command, u8 value) +{ if (!camera) - return 0; + return -EIO; down(&sonypi_device.lock); - switch(command) { - case SONYPI_COMMAND_GETCAMERA: - ret = sonypi_camera_ready(); - break; - case SONYPI_COMMAND_SETCAMERA: - if (value) - sonypi_camera_on(); - else - sonypi_camera_off(); - break; - case SONYPI_COMMAND_GETCAMERABRIGHTNESS: - ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS); - break; - case SONYPI_COMMAND_SETCAMERABRIGHTNESS: - sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value); - break; - case SONYPI_COMMAND_GETCAMERACONTRAST: - ret = sonypi_read(SONYPI_CAMERA_CONTRAST); - break; - case SONYPI_COMMAND_SETCAMERACONTRAST: - sonypi_set(SONYPI_CAMERA_CONTRAST, value); - break; - case SONYPI_COMMAND_GETCAMERAHUE: - ret = sonypi_read(SONYPI_CAMERA_HUE); - break; - case SONYPI_COMMAND_SETCAMERAHUE: - sonypi_set(SONYPI_CAMERA_HUE, value); - break; - case SONYPI_COMMAND_GETCAMERACOLOR: - ret = sonypi_read(SONYPI_CAMERA_COLOR); - break; - case SONYPI_COMMAND_SETCAMERACOLOR: - sonypi_set(SONYPI_CAMERA_COLOR, value); - break; - case SONYPI_COMMAND_GETCAMERASHARPNESS: - ret = sonypi_read(SONYPI_CAMERA_SHARPNESS); - break; - case SONYPI_COMMAND_SETCAMERASHARPNESS: - sonypi_set(SONYPI_CAMERA_SHARPNESS, value); - break; - case SONYPI_COMMAND_GETCAMERAPICTURE: - ret = sonypi_read(SONYPI_CAMERA_PICTURE); - break; - case SONYPI_COMMAND_SETCAMERAPICTURE: - sonypi_set(SONYPI_CAMERA_PICTURE, value); - break; - case SONYPI_COMMAND_GETCAMERAAGC: - ret = sonypi_read(SONYPI_CAMERA_AGC); - break; - case SONYPI_COMMAND_SETCAMERAAGC: - sonypi_set(SONYPI_CAMERA_AGC, value); - break; - case SONYPI_COMMAND_GETCAMERADIRECTION: - ret = sonypi_read(SONYPI_CAMERA_STATUS); - ret &= SONYPI_DIRECTION_BACKWARDS; - break; - case SONYPI_COMMAND_GETCAMERAROMVERSION: - ret = sonypi_read(SONYPI_CAMERA_ROMVERSION); - break; - case SONYPI_COMMAND_GETCAMERAREVISION: - ret = sonypi_read(SONYPI_CAMERA_REVISION); - break; + switch (command) { + case SONYPI_COMMAND_SETCAMERA: + if (value) + sonypi_camera_on(); + else + sonypi_camera_off(); + break; + case SONYPI_COMMAND_SETCAMERABRIGHTNESS: + sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value); + break; + case SONYPI_COMMAND_SETCAMERACONTRAST: + sonypi_set(SONYPI_CAMERA_CONTRAST, value); + break; + case SONYPI_COMMAND_SETCAMERAHUE: + sonypi_set(SONYPI_CAMERA_HUE, value); + break; + case SONYPI_COMMAND_SETCAMERACOLOR: + sonypi_set(SONYPI_CAMERA_COLOR, value); + break; + case SONYPI_COMMAND_SETCAMERASHARPNESS: + sonypi_set(SONYPI_CAMERA_SHARPNESS, value); + break; + case SONYPI_COMMAND_SETCAMERAPICTURE: + sonypi_set(SONYPI_CAMERA_PICTURE, value); + break; + case SONYPI_COMMAND_SETCAMERAAGC: + sonypi_set(SONYPI_CAMERA_AGC, value); + break; + default: + printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n", + command); + break; } up(&sonypi_device.lock); - return ret; + return 0; } -static int sonypi_misc_fasync(int fd, struct file *filp, int on) { +EXPORT_SYMBOL(sonypi_camera_command); + +static int sonypi_misc_fasync(int fd, struct file *filp, int on) +{ int retval; - retval = fasync_helper(fd, filp, on, &sonypi_device.queue.fasync); + retval = fasync_helper(fd, filp, on, &sonypi_device.fifo_async); if (retval < 0) return retval; return 0; } -static int sonypi_misc_release(struct inode * inode, struct file * file) { +static int sonypi_misc_release(struct inode *inode, struct file *file) +{ sonypi_misc_fasync(-1, file, 0); down(&sonypi_device.lock); sonypi_device.open_count--; @@ -453,59 +503,56 @@ static int sonypi_misc_release(struct inode * inode, struct file * file) { return 0; } -static int sonypi_misc_open(struct inode * inode, struct file * file) { +static int sonypi_misc_open(struct inode *inode, struct file *file) +{ down(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) - sonypi_initq(); + kfifo_reset(sonypi_device.fifo); sonypi_device.open_count++; up(&sonypi_device.lock); return 0; } -static ssize_t sonypi_misc_read(struct file * file, char __user * buf, - size_t count, loff_t *pos) +static ssize_t sonypi_misc_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) { - DECLARE_WAITQUEUE(wait, current); - ssize_t i = count; + ssize_t ret; unsigned char c; - if (sonypi_emptyq()) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - add_wait_queue(&sonypi_device.queue.proc_list, &wait); -repeat: - set_current_state(TASK_INTERRUPTIBLE); - if (sonypi_emptyq() && !signal_pending(current)) { - schedule(); - goto repeat; - } - current->state = TASK_RUNNING; - remove_wait_queue(&sonypi_device.queue.proc_list, &wait); + if ((kfifo_len(sonypi_device.fifo) == 0) && + (file->f_flags & O_NONBLOCK)) + return -EAGAIN; + + ret = wait_event_interruptible(sonypi_device.fifo_proc_list, + kfifo_len(sonypi_device.fifo) != 0); + if (ret) + return ret; + + while (ret < count && + (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { + if (put_user(c, buf++)) + return -EFAULT; + ret++; } - while (i > 0 && !sonypi_emptyq()) { - c = sonypi_pullq(); - put_user(c, buf++); - i--; - } - if (count - i) { + + if (ret > 0) file->f_dentry->d_inode->i_atime = CURRENT_TIME; - return count-i; - } - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; + + return ret; } -static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) { - poll_wait(file, &sonypi_device.queue.proc_list, wait); - if (!sonypi_emptyq()) +static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &sonypi_device.fifo_proc_list, wait); + if (kfifo_len(sonypi_device.fifo)) return POLLIN | POLLRDNORM; return 0; } -static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg) { +static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, + unsigned int cmd, unsigned long arg) +{ int ret = 0; void __user *argp = (void __user *)arg; u8 val8; @@ -600,99 +647,119 @@ static struct file_operations sonypi_misc_fops = { }; struct miscdevice sonypi_misc_device = { - -1, "sonypi", &sonypi_misc_fops + .minor = -1, + .name = "sonypi", + .fops = &sonypi_misc_fops, }; -#ifdef CONFIG_PM -static int old_camera_power; - -static int sonypi_suspend(struct sys_device *dev, u32 state) { - sonypi_call2(0x81, 0); /* make sure we don't get any more events */ - if (camera) { - old_camera_power = sonypi_device.camera_power; - sonypi_camera_off(); - } +static void sonypi_enable(unsigned int camera_on) +{ if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_dis(); + sonypi_type2_srs(); else - sonypi_type1_dis(); - /* disable ACPI mode */ - if (!SONYPI_ACPI_ACTIVE && fnkeyinit) - outb(0xf1, 0xb2); - return 0; -} + sonypi_type1_srs(); + + sonypi_call1(0x82); + sonypi_call2(0x81, 0xff); + sonypi_call1(compat ? 0x92 : 0x82); -static int sonypi_resume(struct sys_device *dev) { /* Enable ACPI mode to get Fn key events */ if (!SONYPI_ACPI_ACTIVE && fnkeyinit) outb(0xf0, 0xb2); + + if (camera && camera_on) + sonypi_camera_on(); +} + +static int sonypi_disable(void) +{ + sonypi_call2(0x81, 0); /* make sure we don't get any more events */ + if (camera) + sonypi_camera_off(); + + /* disable ACPI mode */ + if (!SONYPI_ACPI_ACTIVE && fnkeyinit) + outb(0xf1, 0xb2); + if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_srs(); - else - sonypi_type1_srs(); - sonypi_call1(0x82); - sonypi_call2(0x81, 0xff); - if (compat) - sonypi_call1(0x92); + sonypi_type2_dis(); else - sonypi_call1(0x82); - if (camera && old_camera_power) - sonypi_camera_on(); + sonypi_type1_dis(); return 0; } -/* Old PM scheme */ -static int sonypi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) { +#ifdef CONFIG_PM +static int old_camera_power; - switch (rqst) { - case PM_SUSPEND: - sonypi_suspend(NULL, 0); - break; - case PM_RESUME: - sonypi_resume(NULL); - break; +static int sonypi_suspend(struct device *dev, u32 state, u32 level) +{ + if (level == SUSPEND_DISABLE) { + old_camera_power = sonypi_device.camera_power; + sonypi_disable(); } return 0; } -/* New PM scheme (device model) */ -static struct sysdev_class sonypi_sysclass = { - set_kset_name("sonypi"), - .suspend = sonypi_suspend, - .resume = sonypi_resume, -}; +static int sonypi_resume(struct device *dev, u32 level) +{ + if (level == RESUME_ENABLE) + sonypi_enable(old_camera_power); + return 0; +} +#endif -static struct sys_device sonypi_sysdev = { - .id = 0, - .cls = &sonypi_sysclass, -}; +static void sonypi_shutdown(struct device *dev) +{ + sonypi_disable(); +} + +static struct device_driver sonypi_driver = { + .name = "sonypi", + .bus = &platform_bus_type, +#ifdef CONFIG_PM + .suspend = sonypi_suspend, + .resume = sonypi_resume, #endif + .shutdown = sonypi_shutdown, +}; -static int __devinit sonypi_probe(struct pci_dev *pcidev) { +static int __devinit sonypi_probe(void) +{ int i, ret; struct sonypi_ioport_list *ioport_list; struct sonypi_irq_list *irq_list; + struct pci_dev *pcidev; + + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, NULL); sonypi_device.dev = pcidev; - if (pcidev) - sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; - else - sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; - sonypi_initq(); + sonypi_device.model = pcidev ? + SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2; + + sonypi_device.fifo_lock = SPIN_LOCK_UNLOCKED; + sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, + &sonypi_device.fifo_lock); + if (IS_ERR(sonypi_device.fifo)) { + printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); + ret = PTR_ERR(sonypi_device.fifo); + goto out_fifo; + } + + init_waitqueue_head(&sonypi_device.fifo_proc_list); init_MUTEX(&sonypi_device.lock); - sonypi_device.bluetooth_power = 0; - + sonypi_device.bluetooth_power = -1; + if (pcidev && pci_enable_device(pcidev)) { printk(KERN_ERR "sonypi: pci_enable_device failed\n"); ret = -EIO; - goto out1; + goto out_pcienable; } - sonypi_misc_device.minor = (minor == -1) ? - MISC_DYNAMIC_MINOR : minor; + sonypi_misc_device.minor = (minor == -1) ? MISC_DYNAMIC_MINOR : minor; if ((ret = misc_register(&sonypi_misc_device))) { printk(KERN_ERR "sonypi: misc_register failed\n"); - goto out1; + goto out_miscreg; } if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { @@ -700,8 +767,7 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; irq_list = sonypi_type2_irq_list; - } - else { + } else { ioport_list = sonypi_type1_ioport_list; sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; @@ -709,8 +775,8 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { } for (i = 0; ioport_list[i].port1; i++) { - if (request_region(ioport_list[i].port1, - sonypi_device.region_size, + if (request_region(ioport_list[i].port1, + sonypi_device.region_size, "Sony Programable I/O Device")) { /* get the ioport */ sonypi_device.ioport1 = ioport_list[i].port1; @@ -721,7 +787,7 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { if (!sonypi_device.ioport1) { printk(KERN_ERR "sonypi: request_region failed\n"); ret = -ENODEV; - goto out2; + goto out_reqreg; } for (i = 0; irq_list[i].irq; i++) { @@ -729,59 +795,85 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { sonypi_device.irq = irq_list[i].irq; sonypi_device.bits = irq_list[i].bits; - /* Enable sonypi IRQ settings */ - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_srs(); - else - sonypi_type1_srs(); - - sonypi_call1(0x82); - sonypi_call2(0x81, 0xff); - if (compat) - sonypi_call1(0x92); - else - sonypi_call1(0x82); - - /* Now try requesting the irq from the system */ - if (!request_irq(sonypi_device.irq, sonypi_irq, + if (!request_irq(sonypi_device.irq, sonypi_irq, SA_SHIRQ, "sonypi", sonypi_irq)) break; - - /* If request_irq failed, disable sonypi IRQ settings */ - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_dis(); - else - sonypi_type1_dis(); } if (!irq_list[i].irq) { printk(KERN_ERR "sonypi: request_irq failed\n"); ret = -ENODEV; - goto out3; + goto out_reqirq; } -#ifdef CONFIG_PM - sonypi_device.pm = pm_register(PM_PCI_DEV, 0, sonypi_pm_callback); + if (useinput) { + /* Initialize the Input Drivers: jogdial */ + int i; + sonypi_device.input_jog_dev.evbit[0] = + BIT(EV_KEY) | BIT(EV_REL); + sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] = + BIT(BTN_MIDDLE); + sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL); + sonypi_device.input_jog_dev.name = + kmalloc(sizeof(SONYPI_JOG_INPUTNAME), GFP_KERNEL); + if (!sonypi_device.input_jog_dev.name) { + printk(KERN_ERR "sonypi: kmalloc failed\n"); + ret = -ENOMEM; + goto out_inkmallocinput1; + } + sprintf(sonypi_device.input_jog_dev.name, SONYPI_JOG_INPUTNAME); + sonypi_device.input_jog_dev.id.bustype = BUS_ISA; + sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY; + + input_register_device(&sonypi_device.input_jog_dev); + printk(KERN_INFO "%s input method installed.\n", + sonypi_device.input_jog_dev.name); + + /* Initialize the Input Drivers: special keys */ + sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY); + for (i = 0; sonypi_inputkeys[i].sonypiev; i++) + if (sonypi_inputkeys[i].inputev) + set_bit(sonypi_inputkeys[i].inputev, + sonypi_device.input_key_dev.keybit); + sonypi_device.input_key_dev.name = + kmalloc(sizeof(SONYPI_KEY_INPUTNAME), GFP_KERNEL); + if (!sonypi_device.input_key_dev.name) { + printk(KERN_ERR "sonypi: kmalloc failed\n"); + ret = -ENOMEM; + goto out_inkmallocinput2; + } + sprintf(sonypi_device.input_key_dev.name, SONYPI_KEY_INPUTNAME); + sonypi_device.input_key_dev.id.bustype = BUS_ISA; + sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY; + + input_register_device(&sonypi_device.input_key_dev); + printk(KERN_INFO "%s input method installed.\n", + sonypi_device.input_key_dev.name); + + sonypi_device.input_fifo_lock = SPIN_LOCK_UNLOCKED; + sonypi_device.input_fifo = + kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, + &sonypi_device.input_fifo_lock); + if (IS_ERR(sonypi_device.input_fifo)) { + printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); + ret = PTR_ERR(sonypi_device.input_fifo); + goto out_infifo; + } - if (sysdev_class_register(&sonypi_sysclass) != 0) { - printk(KERN_ERR "sonypi: sysdev_class_register failed\n"); - ret = -ENODEV; - goto out4; + INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); } - if (sysdev_register(&sonypi_sysdev) != 0) { - printk(KERN_ERR "sonypi: sysdev_register failed\n"); - ret = -ENODEV; - goto out5; + + sonypi_device.pdev = platform_device_register_simple("sonypi", -1, + NULL, 0); + if (IS_ERR(sonypi_device.pdev)) { + ret = PTR_ERR(sonypi_device.pdev); + goto out_platformdev; } -#endif - /* Enable ACPI mode to get Fn key events */ - if (!SONYPI_ACPI_ACTIVE && fnkeyinit) - outb(0xf0, 0xb2); + sonypi_enable(0); - printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%d.%d.\n", - SONYPI_DRIVER_MAJORVERSION, - SONYPI_DRIVER_MINORVERSION); + printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" + "v%s.\n", SONYPI_DRIVER_VERSION); printk(KERN_INFO "sonypi: detected %s model, " "verbose = %d, fnkeyinit = %s, camera = %s, " "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", @@ -795,76 +887,60 @@ static int __devinit sonypi_probe(struct pci_dev *pcidev) { useinput ? "on" : "off", SONYPI_ACPI_ACTIVE ? "on" : "off"); printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", - sonypi_device.irq, + sonypi_device.irq, sonypi_device.ioport1, sonypi_device.ioport2); if (minor == -1) printk(KERN_INFO "sonypi: device allocated minor is %d\n", sonypi_misc_device.minor); -#ifdef SONYPI_USE_INPUT - if (useinput) { - /* Initialize the Input Drivers: */ - sonypi_device.jog_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - sonypi_device.jog_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE); - sonypi_device.jog_dev.relbit[0] = BIT(REL_WHEEL); - sonypi_device.jog_dev.name = (char *) kmalloc( - sizeof(SONYPI_INPUTNAME), GFP_KERNEL); - sprintf(sonypi_device.jog_dev.name, SONYPI_INPUTNAME); - sonypi_device.jog_dev.id.bustype = BUS_ISA; - sonypi_device.jog_dev.id.vendor = PCI_VENDOR_ID_SONY; - - input_register_device(&sonypi_device.jog_dev); - printk(KERN_INFO "%s installed.\n", sonypi_device.jog_dev.name); - } -#endif /* SONYPI_USE_INPUT */ - return 0; -#ifdef CONFIG_PM -out5: - sysdev_class_unregister(&sonypi_sysclass); -out4: +out_platformdev: + kfifo_free(sonypi_device.input_fifo); +out_infifo: + input_unregister_device(&sonypi_device.input_key_dev); + kfree(sonypi_device.input_key_dev.name); +out_inkmallocinput2: + input_unregister_device(&sonypi_device.input_jog_dev); + kfree(sonypi_device.input_jog_dev.name); +out_inkmallocinput1: free_irq(sonypi_device.irq, sonypi_irq); -#endif -out3: +out_reqirq: release_region(sonypi_device.ioport1, sonypi_device.region_size); -out2: +out_reqreg: misc_deregister(&sonypi_misc_device); -out1: +out_miscreg: + if (pcidev) + pci_disable_device(pcidev); +out_pcienable: + kfifo_free(sonypi_device.fifo); +out_fifo: + pci_dev_put(sonypi_device.dev); return ret; } -static void __devexit sonypi_remove(void) { - -#ifdef CONFIG_PM - pm_unregister(sonypi_device.pm); +static void __devexit sonypi_remove(void) +{ + sonypi_disable(); - sysdev_unregister(&sonypi_sysdev); - sysdev_class_unregister(&sonypi_sysclass); -#endif + platform_device_unregister(sonypi_device.pdev); - sonypi_call2(0x81, 0); /* make sure we don't get any more events */ - -#ifdef SONYPI_USE_INPUT if (useinput) { - input_unregister_device(&sonypi_device.jog_dev); - kfree(sonypi_device.jog_dev.name); + input_unregister_device(&sonypi_device.input_key_dev); + kfree(sonypi_device.input_key_dev.name); + input_unregister_device(&sonypi_device.input_jog_dev); + kfree(sonypi_device.input_jog_dev.name); + kfifo_free(sonypi_device.input_fifo); } -#endif /* SONYPI_USE_INPUT */ - if (camera) - sonypi_camera_off(); - if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) - sonypi_type2_dis(); - else - sonypi_type1_dis(); - /* disable ACPI mode */ - if (!SONYPI_ACPI_ACTIVE && fnkeyinit) - outb(0xf1, 0xb2); free_irq(sonypi_device.irq, sonypi_irq); release_region(sonypi_device.ioport1, sonypi_device.region_size); misc_deregister(&sonypi_misc_device); + if (sonypi_device.dev) + pci_disable_device(sonypi_device.dev); + kfifo_free(sonypi_device.fifo); + pci_dev_put(sonypi_device.dev); printk(KERN_INFO "sonypi: removed.\n"); } @@ -886,78 +962,29 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { { } }; -static int __init sonypi_init_module(void) +static int __init sonypi_init(void) { - struct pci_dev *pcidev = NULL; - if (dmi_check_system(sonypi_dmi_table)) { - pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, - NULL); - return sonypi_probe(pcidev); - } - else - return -ENODEV; -} + int ret; -static void __exit sonypi_cleanup_module(void) { - sonypi_remove(); -} + if (!dmi_check_system(sonypi_dmi_table)) + return -ENODEV; -#ifndef MODULE -static int __init sonypi_setup(char *str) { - int ints[8]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] <= 0) - goto out; - minor = ints[1]; - if (ints[0] == 1) - goto out; - verbose = ints[2]; - if (ints[0] == 2) - goto out; - fnkeyinit = ints[3]; - if (ints[0] == 3) - goto out; - camera = ints[4]; - if (ints[0] == 4) - goto out; - compat = ints[5]; - if (ints[0] == 5) - goto out; - mask = ints[6]; - if (ints[0] == 6) - goto out; - useinput = ints[7]; -out: - return 1; -} - -__setup("sonypi=", sonypi_setup); -#endif /* !MODULE */ - -/* Module entry points */ -module_init(sonypi_init_module); -module_exit(sonypi_cleanup_module); + ret = driver_register(&sonypi_driver); + if (ret) + return ret; -MODULE_AUTHOR("Stelian Pop "); -MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver"); -MODULE_LICENSE("GPL"); + ret = sonypi_probe(); + if (ret) + driver_unregister(&sonypi_driver); + return ret; +} -MODULE_PARM(minor,"i"); -MODULE_PARM_DESC(minor, "minor number of the misc device, default is -1 (automatic)"); -MODULE_PARM(verbose,"i"); -MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)"); -MODULE_PARM(fnkeyinit,"i"); -MODULE_PARM_DESC(fnkeyinit, "set this if your Fn keys do not generate any event"); -MODULE_PARM(camera,"i"); -MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)"); -MODULE_PARM(compat,"i"); -MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode"); -MODULE_PARM(mask, "i"); -MODULE_PARM_DESC(mask, "set this to the mask of event you want to enable (see doc)"); -MODULE_PARM(useinput, "i"); -MODULE_PARM_DESC(useinput, "if you have a jogdial, set this if you would like it to use the modern Linux Input Driver system"); +static void __exit sonypi_exit(void) +{ + driver_unregister(&sonypi_driver); + sonypi_remove(); +} -EXPORT_SYMBOL(sonypi_camera_command); +module_init(sonypi_init); +module_exit(sonypi_exit); diff --git a/drivers/char/sonypi.h b/drivers/char/sonypi.h index 0eb8f46ab..b8f333684 100644 --- a/drivers/char/sonypi.h +++ b/drivers/char/sonypi.h @@ -1,7 +1,7 @@ -/* +/* * Sony Programmable I/O Control Device driver for VAIO * - * Copyright (C) 2001-2003 Stelian Pop + * Copyright (C) 2001-2004 Stelian Pop * * Copyright (C) 2001-2002 Alcôve * @@ -14,30 +14,29 @@ * Copyright (C) 2000 Andrew Tridgell * * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ -#ifndef _SONYPI_PRIV_H_ +#ifndef _SONYPI_PRIV_H_ #define _SONYPI_PRIV_H_ #ifdef __KERNEL__ -#define SONYPI_DRIVER_MAJORVERSION 1 -#define SONYPI_DRIVER_MINORVERSION 23 +#define SONYPI_DRIVER_VERSION "1.25" #define SONYPI_DEVICE_MODEL_TYPE1 1 #define SONYPI_DEVICE_MODEL_TYPE2 2 @@ -46,9 +45,9 @@ #include #include #include -#include #include -#include "linux/sonypi.h" +#include +#include /* type1 models use those */ #define SONYPI_IRQ_PORT 0x8034 @@ -223,6 +222,7 @@ static struct sonypi_event sonypi_fnkeyev[] = { { 0x1a, SONYPI_EVENT_FNKEY_F10 }, { 0x1b, SONYPI_EVENT_FNKEY_F11 }, { 0x1c, SONYPI_EVENT_FNKEY_F12 }, + { 0x1f, SONYPI_EVENT_FNKEY_RELEASED }, { 0x21, SONYPI_EVENT_FNKEY_1 }, { 0x22, SONYPI_EVENT_FNKEY_2 }, { 0x31, SONYPI_EVENT_FNKEY_D }, @@ -340,30 +340,53 @@ struct sonypi_eventtypes { }; #define SONYPI_BUF_SIZE 128 -struct sonypi_queue { - unsigned long head; - unsigned long tail; - unsigned long len; - spinlock_t s_lock; - wait_queue_head_t proc_list; - struct fasync_struct *fasync; - unsigned char buf[SONYPI_BUF_SIZE]; -}; - -/* We enable input subsystem event forwarding if the input - * subsystem is compiled in, but only if sonypi is not into the - * kernel and input as a module... */ -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -#if ! (defined(CONFIG_SONYPI) && defined(CONFIG_INPUT_MODULE)) -#define SONYPI_USE_INPUT -#endif -#endif -/* The name of the Jog Dial for the input device drivers */ -#define SONYPI_INPUTNAME "Sony VAIO Jog Dial" +/* The name of the devices for the input device drivers */ +#define SONYPI_JOG_INPUTNAME "Sony Vaio Jogdial" +#define SONYPI_KEY_INPUTNAME "Sony Vaio Keys" + +/* Correspondance table between sonypi events and input layer events */ +struct { + int sonypiev; + int inputev; +} sonypi_inputkeys[] = { + { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, + { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, + { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, + { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, + { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, + { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, + { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, + { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, + { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, + { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, + { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, + { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, + { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, + { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, + { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, + { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, + { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, + { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, + { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, + { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, + { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, + { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, + { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, + { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, + { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, + { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, + { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, + { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, + { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, + { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, + { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, + { 0, 0 }, +}; struct sonypi_device { struct pci_dev *dev; + struct platform_device *pdev; u16 irq; u16 bits; u16 ioport1; @@ -373,15 +396,17 @@ struct sonypi_device { int camera_power; int bluetooth_power; struct semaphore lock; - struct sonypi_queue queue; + struct kfifo *fifo; + spinlock_t fifo_lock; + wait_queue_head_t fifo_proc_list; + struct fasync_struct *fifo_async; int open_count; int model; -#ifdef SONYPI_USE_INPUT - struct input_dev jog_dev; -#endif -#ifdef CONFIG_PM - struct pm_dev *pm; -#endif + struct input_dev input_jog_dev; + struct input_dev input_key_dev; + struct work_struct input_work; + struct kfifo *input_fifo; + spinlock_t input_fifo_lock; }; #define ITERATIONS_LONG 10000 @@ -399,39 +424,8 @@ struct sonypi_device { #define SONYPI_ACPI_ACTIVE (!acpi_disabled) #else #define SONYPI_ACPI_ACTIVE 0 -#endif /* CONFIG_ACPI */ - -extern int verbose; - -static inline int sonypi_ec_write(u8 addr, u8 value) { -#ifdef CONFIG_ACPI_EC - if (SONYPI_ACPI_ACTIVE) - return ec_write(addr, value); -#endif - wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); - outb_p(0x81, SONYPI_CST_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); - outb_p(addr, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); - outb_p(value, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); - return 0; -} - -static inline int sonypi_ec_read(u8 addr, u8 *value) { -#ifdef CONFIG_ACPI_EC - if (SONYPI_ACPI_ACTIVE) - return ec_read(addr, value); -#endif - wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG); - outb_p(0x80, SONYPI_CST_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); - outb_p(addr, SONYPI_DATA_IOPORT); - wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG); - *value = inb_p(SONYPI_DATA_IOPORT); - return 0; -} +#endif /* CONFIG_ACPI */ -#endif /* __KERNEL__ */ +#endif /* __KERNEL__ */ -#endif /* _SONYPI_PRIV_H_ */ +#endif /* _SONYPI_PRIV_H_ */ diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 0d3763dc6..5a33227cc 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -135,10 +135,6 @@ ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - #undef RS_EVENT_WRITE_WAKEUP #define RS_EVENT_WRITE_WAKEUP 0 @@ -159,7 +155,7 @@ static struct specialix_board sx_board[SX_NBOARD] = { }; static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; - + #ifdef SPECIALIX_TIMER static struct timer_list missed_irq_timer; @@ -715,7 +711,7 @@ static inline void sx_transmit(struct specialix_board * bp) sx_out(bp, CD186x_TDR, CD186x_C_SBRK); port->COR2 &= ~COR2_ETC; } - count = MIN(port->break_length, 0xff); + count = min_t(int, port->break_length, 0xff); sx_out(bp, CD186x_TDR, CD186x_C_ESC); sx_out(bp, CD186x_TDR, CD186x_C_DELAY); sx_out(bp, CD186x_TDR, count); @@ -1456,8 +1452,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) */ timeout = jiffies+HZ; while(port->IER & IER_TXEMPTY) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->timeout); + msleep_interruptible(jiffies_to_msecs(port->timeout)); if (time_after(jiffies, timeout)) { printk (KERN_INFO "Timeout waiting for close\n"); break; @@ -1468,15 +1463,13 @@ static void sx_close(struct tty_struct * tty, struct file * filp) sx_shutdown_port(bp, port); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; port->event = 0; port->tty = NULL; if (port->blocked_open) { if (port->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(port->close_delay); + msleep_interruptible(jiffies_to_msecs(port->close_delay)); } wake_up_interruptible(&port->open_wait); } @@ -1486,7 +1479,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } -static int sx_write(struct tty_struct * tty, int from_user, +static int sx_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; @@ -1503,52 +1496,22 @@ static int sx_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); @@ -1646,10 +1609,8 @@ static void sx_flush_buffer(struct tty_struct *tty) port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; restore_flags(flags); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); } @@ -2052,12 +2013,8 @@ static void do_softint(void *private_) if(!(tty = port->tty)) return; - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) + tty_wakeup(tty); } static struct tty_operations sx_ops = { @@ -2229,8 +2186,8 @@ int iobase[SX_NBOARD] = {0,}; int irq [SX_NBOARD] = {0,}; -MODULE_PARM(iobase,"1-" __MODULE_STRING(SX_NBOARD) "i"); -MODULE_PARM(irq,"1-" __MODULE_STRING(SX_NBOARD) "i"); +module_param_array(iobase, int, NULL, 0); +module_param_array(irq, int, NULL, 0); /* * You can setup up to 4 boards. diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index a0b3ba7b0..9a204da53 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -481,7 +482,7 @@ static unsigned long stl_atol(char *str); int stl_init(void); static int stl_open(struct tty_struct *tty, struct file *filp); static void stl_close(struct tty_struct *tty, struct file *filp); -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count); static void stl_putchar(struct tty_struct *tty, unsigned char ch); static void stl_flushchars(struct tty_struct *tty); static int stl_writeroom(struct tty_struct *tty); @@ -512,7 +513,6 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp); static int stl_getportstruct(stlport_t __user *arg); static int stl_getbrdstruct(stlbrd_t __user *arg); static int stl_waitcarrier(stlport_t *portp, struct file *filp); -static void stl_delay(int len); static void stl_eiointr(stlbrd_t *brdp); static void stl_echatintr(stlbrd_t *brdp); static void stl_echmcaintr(stlbrd_t *brdp); @@ -1197,15 +1197,14 @@ static void stl_close(struct tty_struct *tty, struct file *filp) portp->tx.tail = (char *) NULL; } set_bit(TTY_IO_ERROR, &tty->flags); - if (tty->ldisc.flush_buffer) - (tty->ldisc.flush_buffer)(tty); + tty_ldisc_flush(tty); tty->closing = 0; portp->tty = (struct tty_struct *) NULL; if (portp->openwaitcnt) { if (portp->close_delay) - stl_delay(portp->close_delay); + msleep_interruptible(jiffies_to_msecs(portp->close_delay)); wake_up_interruptible(&portp->open_wait); } @@ -1216,31 +1215,12 @@ static void stl_close(struct tty_struct *tty, struct file *filp) /*****************************************************************************/ -/* - * Wait for a specified delay period, this is not a busy-loop. It will - * give up the processor while waiting. Unfortunately this has some - * rather intimate knowledge of the process management stuff. - */ - -static void stl_delay(int len) -{ -#ifdef DEBUG - printk("stl_delay(len=%d)\n", len); -#endif - if (len > 0) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(len); - } -} - -/*****************************************************************************/ - /* * Write routine. Take data and stuff it in to the TX ring queue. * If transmit interrupts are not running then start them. */ -static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) { stlport_t *portp; unsigned int len, stlen; @@ -1248,8 +1228,8 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char char *head, *tail; #ifdef DEBUG - printk("stl_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - (int) tty, from_user, (int) buf, count); + printk("stl_write(tty=%x,buf=%x,count=%d)\n", + (int) tty, (int) buf, count); #endif if ((tty == (struct tty_struct *) NULL) || @@ -1268,18 +1248,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char * copy it into the TX buffer. */ chbuf = (unsigned char *) buf; - if (from_user) { - head = portp->tx.head; - tail = portp->tx.tail; - len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : - (tail - head - 1); - count = MIN(len, count); - - down(&stl_tmpwritesem); - if (copy_from_user(stl_tmpwritebuf, chbuf, count)) - return -EFAULT; - chbuf = &stl_tmpwritebuf[0]; - } head = portp->tx.head; tail = portp->tx.tail; @@ -1310,9 +1278,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char clear_bit(ASYI_TXLOW, &portp->istate); stl_startrxtx(portp, -1, 1); - if (from_user) - up(&stl_tmpwritesem); - return(count); } @@ -1809,10 +1774,7 @@ static void stl_flushbuffer(struct tty_struct *tty) return; stl_flush(portp); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /*****************************************************************************/ @@ -1858,7 +1820,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) while (stl_datastate(portp)) { if (signal_pending(current)) break; - stl_delay(2); + msleep_interruptible(20); if (time_after_eq(jiffies, tend)) break; } @@ -2193,10 +2155,7 @@ static void stl_offintr(void *private) lock_kernel(); if (test_bit(ASYI_TXLOW, &portp->istate)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } if (test_bit(ASYI_DCDCHANGE, &portp->istate)) { clear_bit(ASYI_DCDCHANGE, &portp->istate); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 1ca3d2543..533d286d7 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -460,9 +460,27 @@ static inline int sx_paranoia_check(struct sx_port const * port, #ifdef DEBUG -static void my_hd (unsigned char *addr, int len) +static void my_hd_io(void __iomem *p, int len) { int i, j, ch; + unsigned char __iomem *addr = p; + + for (i=0;i 0x7f)?'.':ch)); + } + printk ("\n"); + } +} +static void my_hd(void *p, int len) +{ + int i, j, ch; + unsigned char *addr = p; for (i=0;igs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - port->gs.tty->ldisc.write_wakeup) - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); + tty_wakeup(port->gs.tty); sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", port->gs.wakeup_chars); - wake_up_interruptible(&port->gs.tty->write_wait); } clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks); @@ -1455,11 +1470,10 @@ static int sx_open (struct tty_struct * tty, struct file * filp) #if 0 if (sx_debug & SX_DEBUG_OPEN) - my_hd ((unsigned char *)port, sizeof (*port)); + my_hd (port, sizeof (*port)); #else if (sx_debug & SX_DEBUG_OPEN) - my_hd ((unsigned char *)port->board->base + port->ch_base, - sizeof (*port)); + my_hd_io (port->board->base + port->ch_base, sizeof (*port)); #endif if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { @@ -1502,7 +1516,7 @@ static void sx_close (void *ptr) sx_send_command (port, HS_CLOSE, 0, 0); while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (1); if (signal_pending (current)) break; @@ -1678,7 +1692,7 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, kfree (tmp); return -EFAULT; } - memcpy_toio ((char *) (board->base2 + offset + i), tmp, + memcpy_toio(board->base2 + offset + i, tmp, (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); } @@ -1895,9 +1909,9 @@ static int sx_init_board (struct sx_board *board) /* Ok. So now the processor on the card is running. It gathered some info for us... */ sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base), 0x10); + if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base, 0x10); sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base + 0x80), 0x30); + if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base + 0x80, 0x30); sx_dprintk (SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware V%x.%02x,\n", @@ -2050,18 +2064,18 @@ static int probe_sx (struct sx_board *board) func_enter(); if (!IS_CF_BOARD (board)) { - sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %lx.\n", + sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", board->base + SX_VPD_ROM); if (sx_debug & SX_DEBUG_PROBE) - my_hd ((char *)(board->base + SX_VPD_ROM), 0x40); + my_hd_io(board->base + SX_VPD_ROM, 0x40); p = (char *) &vpdp; for (i=0;i< sizeof (struct vpd_prom);i++) *p++ = read_sx_byte (board, SX_VPD_ROM + i*2); if (sx_debug & SX_DEBUG_PROBE) - my_hd ((char *)&vpdp, 0x20); + my_hd (&vpdp, 0x20); sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n"); @@ -2091,8 +2105,8 @@ static int probe_sx (struct sx_board *board) } if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { - if (board->base & 0x8000) { - printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->base); + if (board->hw_base & 0x8000) { + printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base); printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); } } @@ -2124,11 +2138,11 @@ static int probe_si (struct sx_board *board) int i; func_enter(); - sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %lx.\n", board->hw_base, + sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) - my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8); + my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8); if (!IS_EISA_BOARD(board)) { if( IS_SI1_BOARD(board) ) @@ -2362,7 +2376,7 @@ static void __exit sx_release_drivers(void) static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) { unsigned int hwbase; - unsigned long rebase; + void __iomem *rebase; unsigned int t; #define CNTRL_REG_OFFSET 0x50 @@ -2370,13 +2384,13 @@ static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; - rebase = (ulong) ioremap(hwbase, 0x80); + rebase = ioremap(hwbase, 0x80); t = readl (rebase + CNTRL_REG_OFFSET); if (t != CNTRL_REG_GOODVALUE) { printk (KERN_DEBUG "sx: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } - iounmap ((char *) rebase); + iounmap(rebase); } #endif @@ -2444,7 +2458,7 @@ static int __init sx_init(void) else board->hw_base = pci_resource_start (pdev, 2); board->base2 = - board->base = (ulong) ioremap(board->hw_base, WINDOW_LEN (board)); + board->base = ioremap(board->hw_base, WINDOW_LEN (board)); if (!board->base) { printk(KERN_ERR "ioremap failed\n"); /* XXX handle error */ @@ -2456,14 +2470,14 @@ static int __init sx_init(void) board->irq = pdev->irq; - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%lx(%d) %x.\n", + sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n", tint, boards[found].base, board->irq, board->flags); if (probe_sx (board)) { found++; fix_sx_pci (pdev, board); } else - iounmap ((char *) (board->base)); + iounmap(board->base); } #endif @@ -2471,7 +2485,7 @@ static int __init sx_init(void) board = &boards[found]; board->hw_base = sx_probe_addrs[i]; board->base2 = - board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN); + board->base = ioremap(board->hw_base, SX_WINDOW_LEN); board->flags &= ~SX_BOARD_TYPE; board->flags |= SX_ISA_BOARD; board->irq = sx_irqmask?-1:0; @@ -2479,7 +2493,7 @@ static int __init sx_init(void) if (probe_sx (board)) { found++; } else { - iounmap ((char *) (board->base)); + iounmap(board->base); } } @@ -2487,7 +2501,7 @@ static int __init sx_init(void) board = &boards[found]; board->hw_base = si_probe_addrs[i]; board->base2 = - board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); board->flags &= ~SX_BOARD_TYPE; board->flags |= SI_ISA_BOARD; board->irq = sx_irqmask ?-1:0; @@ -2495,14 +2509,14 @@ static int __init sx_init(void) if (probe_si (board)) { found++; } else { - iounmap ((char *) (board->base)); + iounmap (board->base); } } for (i=0;ihw_base = si1_probe_addrs[i]; board->base2 = - board->base = (ulong) ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); board->flags &= ~SX_BOARD_TYPE; board->flags |= SI1_ISA_BOARD; board->irq = sx_irqmask ?-1:0; @@ -2510,7 +2524,7 @@ static int __init sx_init(void) if (probe_si (board)) { found++; } else { - iounmap ((char *) (board->base)); + iounmap (board->base); } } @@ -2530,10 +2544,10 @@ static int __init sx_init(void) board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16); board->base2 = - board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %lx\n", board->base); + sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); board->irq = inb(board->eisa_base+0xc02)>>4; sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); @@ -2562,7 +2576,7 @@ static void __exit sx_exit (void) for (i = 0; i < SX_NBOARDS; i++) { board = &boards[i]; if (board->flags & SX_BOARD_INITIALIZED) { - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %lx\n", board->base); + sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %p\n", board->base); /* The board should stop messing with us. (actually I mean the interrupt) */ sx_reset (board); @@ -2571,11 +2585,11 @@ static void __exit sx_exit (void) /* It is safe/allowed to del_timer a non-active timer */ del_timer (& board->timer); - iounmap ((char *) (board->base)); + iounmap(board->base); } } if (misc_deregister(&sx_fw_device) < 0) { - printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); + printk (KERN_INFO "sx: couldn't deregister firmware loader devic\n"); } sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); if (sx_initialized) diff --git a/drivers/char/sx.h b/drivers/char/sx.h index 9e65004be..e01f83cbe 100644 --- a/drivers/char/sx.h +++ b/drivers/char/sx.h @@ -32,8 +32,8 @@ struct sx_port { struct sx_board { int magic; - unsigned long base; - unsigned long base2; + void __iomem *base; + void __iomem *base2; unsigned long hw_base; int eisa_base; int port_base; /* Number of the first port */ diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 78d4efe6f..73bfe95c9 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.24 2004/06/03 14:50:09 paulkf Exp $ + * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -82,6 +82,7 @@ #include #include #include +#include #include @@ -96,17 +97,14 @@ #include #include #include -#include +#include #include #include #include +#include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -187,7 +185,6 @@ struct tx_holding_buffer { */ struct mgsl_struct { - void *if_ptr; /* General purpose pointer (used by SPPP) */ int magic; int flags; int count; /* count of opens */ @@ -318,15 +315,13 @@ struct mgsl_struct { struct _input_signal_events input_signal_events; - /* SPPP/Cisco HDLC device parts */ + /* generic HDLC device parts */ int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif }; @@ -734,18 +729,12 @@ int usc_loopmode_send_active( struct mgsl_struct * info ); int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* SPPP/HDLC stuff */ -static void mgsl_sppp_init(struct mgsl_struct *info); -static void mgsl_sppp_delete(struct mgsl_struct *info); -int mgsl_sppp_open(struct net_device *d); -int mgsl_sppp_close(struct net_device *d); -void mgsl_sppp_tx_timeout(struct net_device *d); -int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d); -void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size); -void mgsl_sppp_tx_done(struct mgsl_struct *info); -int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -struct net_device_stats *mgsl_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(struct mgsl_struct *info); +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size); +static int hdlcdev_init(struct mgsl_struct *info); +static void hdlcdev_exit(struct mgsl_struct *info); #endif /* @@ -863,8 +852,6 @@ static int mgsl_rxenable(struct mgsl_struct * info, int enable); static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask); static int mgsl_loopmode_send_done( struct mgsl_struct * info ); -#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) - /* set non-zero on successful registration with PCI subsystem */ static int pci_registered; @@ -911,7 +898,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.24 $"; +static char *driver_version = "$Revision: 4.28 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -942,10 +929,6 @@ static struct tty_driver *serial_driver; static void mgsl_change_params(struct mgsl_struct *info); static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* * 1st function defined in .text section. Calling this function in * init_module() followed by a breakpoint allows a remote debugger @@ -993,6 +976,29 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info, return 0; } +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_receive_buf - pass receive data to line discipline + */ + +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->receive_buf) + ld->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + /* mgsl_stop() throttle (stop) transmitter * * Arguments: tty pointer to tty info structure @@ -1153,13 +1159,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info) __FILE__,__LINE__,info->device_name); if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) { - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):calling ldisc.write_wakeup on %s\n", - __FILE__,__LINE__,info->device_name); - (tty->ldisc.write_wakeup)(tty); - } + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } @@ -1289,9 +1289,9 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info ) info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgsl_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -1352,12 +1352,12 @@ void mgsl_isr_io_pin( struct mgsl_struct *info ) icount->dcd++; if (status & MISCSTATUS_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev); +#endif } if (status & MISCSTATUS_CTS_LATCHED) { @@ -2140,16 +2140,15 @@ static void mgsl_flush_chars(struct tty_struct *tty) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Return Value: number of characters written */ -static int mgsl_write(struct tty_struct * tty, int from_user, +static int mgsl_write(struct tty_struct * tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -2186,20 +2185,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user, /* queue transmit frame request */ ret = count; - if (from_user) { - down(&tmp_buf_sem); - COPY_FROM_USER(err,tmp_buf, buf, count); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n", - __FILE__,__LINE__,info->device_name); - ret = -EFAULT; - } else - save_tx_buffer_request(info,tmp_buf,count); - up(&tmp_buf_sem); - } - else - save_tx_buffer_request(info,buf,count); + save_tx_buffer_request(info,buf,count); /* if we have sufficient tx dma buffers, * load the next buffered tx request @@ -2239,70 +2225,26 @@ static int mgsl_write(struct tty_struct * tty, int from_user, __FILE__,__LINE__,info->device_name); ret = count; info->xmit_cnt = count; - if (from_user) { - down(&tmp_buf_sem); - COPY_FROM_USER(err,tmp_buf, buf, count); - if (err) { - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n", - __FILE__,__LINE__,info->device_name); - ret = -EFAULT; - } else - mgsl_load_tx_dma_buffer(info,tmp_buf,count); - up(&tmp_buf_sem); - } - else - mgsl_load_tx_dma_buffer(info,buf,count); + mgsl_load_tx_dma_buffer(info,buf,count); } } else { - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - COPY_FROM_USER(err,tmp_buf, buf, c); - c -= err; - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&info->irq_spinlock,flags); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->irq_spinlock,flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - spin_lock_irqsave(&info->irq_spinlock,flags); - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&info->irq_spinlock,flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; + while (1) { + spin_lock_irqsave(&info->irq_spinlock,flags); + c = min_t(int, count, + min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { spin_unlock_irqrestore(&info->irq_spinlock,flags); - buf += c; - count -= c; - ret += c; + break; } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->irq_spinlock,flags); + buf += c; + count -= c; + ret += c; } } @@ -2415,11 +2357,8 @@ static void mgsl_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&info->irq_spinlock,flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - -} /* end of mgsl_flush_buffer() */ + tty_wakeup(tty); +} /* mgsl_send_xchar() * @@ -3253,9 +3192,8 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); shutdown(info); @@ -3264,8 +3202,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -3326,13 +3263,12 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) char_time = 1; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min_t(unsigned long, char_time, timeout); if ( info->params.mode == MGSL_MODE_HDLC || info->params.mode == MGSL_MODE_RAW ) { while (info->tx_active) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -3341,8 +3277,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) } else { while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) && info->tx_enabled) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -3592,7 +3527,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -4187,7 +4122,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info) info->get_tx_holding_index=0; /* restart transmit timer */ - mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000)); + mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000)); ret = 1; } @@ -4415,12 +4350,10 @@ void mgsl_add_device( struct mgsl_struct *info ) info->max_frame_size ); } -#ifdef CONFIG_SYNCLINK_SYNCPPP -#ifdef MODULE - if (info->dosyncppp) -#endif - mgsl_sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif + } /* end of mgsl_add_device() */ /* mgsl_allocate_device() @@ -4575,9 +4508,8 @@ static void synclink_cleanup(void) info = mgsl_device_list; while(info) { -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - mgsl_sppp_delete(info); +#ifdef CONFIG_HDLC + hdlcdev_exit(info); #endif mgsl_release_resources(info); tmp = info; @@ -5819,7 +5751,7 @@ void usc_start_transmitter( struct mgsl_struct *info ) usc_TCmd( info, TCmd_SendFrame ); - info->tx_timer.expires = jiffies + jiffies_from_ms(5000); + info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); add_timer(&info->tx_timer); } info->tx_active = 1; @@ -6750,9 +6682,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) return_frame = 1; } framesize = 0; -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } else return_frame = 1; @@ -6779,7 +6714,7 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) if ( debug_level >= DEBUG_LEVEL_DATA ) mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr, - MIN(framesize,DMABUFFERSIZE),0); + min_t(int, framesize, DMABUFFERSIZE),0); if (framesize) { if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) && @@ -6823,18 +6758,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info) *ptmp); } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info,info->intermediate_rxbuffer,framesize); else #endif - { - /* Call the line discipline receive callback directly. */ - if ( tty && tty->ldisc.receive_buf ) - tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); - } + ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); } } /* Free the buffers used by this frame. */ @@ -6996,7 +6925,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) if ( debug_level >= DEBUG_LEVEL_DATA ) mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr, - MIN(framesize,DMABUFFERSIZE),0); + min_t(int, framesize, DMABUFFERSIZE),0); if (framesize) { /* copy dma buffer(s) to contiguous intermediate buffer */ @@ -7006,9 +6935,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info) memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize); info->icount.rxok++; - /* Call the line discipline receive callback directly. */ - if ( tty && tty->ldisc.receive_buf ) - tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); + ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize); } /* Free the buffers used by this frame. */ @@ -7056,7 +6983,7 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer, DMABUFFERENTRY *pBufEntry; if ( debug_level >= DEBUG_LEVEL_DATA ) - mgsl_trace_block(info,Buffer, MIN(BufferSize,DMABUFFERSIZE), 1); + mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1); if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) { /* set CMR:13 to start transmit when @@ -7213,8 +7140,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) EndTime=100; while( EndTime-- && !info->irq_occurred ) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_from_ms(10)); + msleep_interruptible(10); } spin_lock_irqsave(&info->irq_spinlock,flags); @@ -7353,7 +7279,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /*************************************************************/ /* Wait 100ms for interrupt. */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); for(;;) { if (time_after(jiffies, EndTime)) { @@ -7409,7 +7335,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /**********************************/ /* Wait 100ms */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); for(;;) { if (time_after(jiffies, EndTime)) { @@ -7451,7 +7377,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /******************************/ /* Wait 100ms */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); /* While timer not expired wait for transmit complete */ @@ -7482,7 +7408,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info ) /* WAIT FOR RECEIVE COMPLETE */ /* Wait 100ms */ - EndTime = jiffies + jiffies_from_ms(100); + EndTime = jiffies + msecs_to_jiffies(100); /* Wait for 16C32 to write receive status to buffer entry. */ status=info->rx_buffer_list[0].status; @@ -7736,9 +7662,9 @@ void mgsl_tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->irq_spinlock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgsl_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif mgsl_bh_transmit(info); @@ -7819,79 +7745,125 @@ int usc_loopmode_send_active( struct mgsl_struct * info ) return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ; } -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* syncppp net device routines - */ -static void mgsl_setup(struct net_device *dev) -{ - dev->open = mgsl_sppp_open; - dev->stop = mgsl_sppp_close; - dev->hard_start_xmit = mgsl_sppp_tx; - dev->do_ioctl = mgsl_sppp_ioctl; - dev->get_stats = mgsl_net_stats; - dev->tx_timeout = mgsl_sppp_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} +#ifdef CONFIG_HDLC -static void mgsl_sppp_init(struct mgsl_struct *info) +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - struct net_device *d; + struct mgsl_struct *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; - sprintf(info->netname,"mgsl%d",info->line); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - d = alloc_netdev(0, info->netname, mgsl_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; - - d->base_addr = info->io_base; - d->irq = info->irq_level; - d->dma = info->dma_level; - d->priv = info; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } - sppp_attach(&info->pppdev); - mgsl_setup(d); + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - free_netdev(d); - return; - } + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_init()\n"); + return 0; } -void mgsl_sppp_delete(struct mgsl_struct *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + struct mgsl_struct *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->xmit_cnt = skb->len; + mgsl_load_tx_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_active) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return 0; } -int mgsl_sppp_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - struct mgsl_struct *info = d->priv; - int err; + struct mgsl_struct *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -7899,141 +7871,299 @@ int mgsl_sppp_open(struct net_device *d) spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; mgsl_program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->irq_spinlock, flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -void mgsl_sppp_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - struct mgsl_struct *info = dev->priv; + struct mgsl_struct *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_stop_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct mgsl_struct *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + struct mgsl_struct *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->xmit_cnt = skb->len; - mgsl_load_tx_dma_buffer(info, skb->data, skb->len); - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - dev->trans_start = jiffies; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_active) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - return 0; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -int mgsl_sppp_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - struct mgsl_struct *info = d->priv; + struct mgsl_struct *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_stop_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; + netif_wake_queue(dev); } -void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size) +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(struct mgsl_struct *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->protocol = hdlc_type_trans(skb, info->netdev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -void mgsl_sppp_tx_done(struct mgsl_struct *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -struct net_device_stats *mgsl_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(struct mgsl_struct *info) { - struct mgsl_struct *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->base_addr = info->io_base; + dev->irq = info->irq_level; + dev->dma = info->dma_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(struct mgsl_struct *info) { - struct mgsl_struct *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ + static int __devinit synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent) diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 1361ea041..eccdcbdef 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.22 2004/06/03 14:50:10 paulkf Exp $ + * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -63,17 +63,14 @@ #include #include #include -#include +#include #include #include #include +#include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -284,12 +281,11 @@ typedef struct _synclinkmp_info { int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif + } SLMP_INFO; #define MGSL_MAGIC 0x5401 @@ -361,12 +357,7 @@ typedef struct _synclinkmp_info { #define TMCS 0x64 #define TEPR 0x65 -/* - * FIXME: DAR here clashed with asm-ppc/reg.h and asm-sh/.../dma.h - */ -#undef DAR /* DMA Controller Register macros */ -#define DAR 0x80 #define DARL 0x80 #define DARH 0x81 #define DARB 0x82 @@ -462,8 +453,6 @@ typedef struct _synclinkmp_info { #define CRCE BIT2 -#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) - /* * Global linked list of SyncLink devices */ @@ -498,7 +487,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.22 $"; +static char *driver_version = "$Revision: 4.29 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -524,10 +513,6 @@ static struct tty_driver *serial_driver; /* number of characters left in xmit buffer before we ask for more */ #define WAKEUP_CHARS 256 -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* tty callbacks */ @@ -536,7 +521,7 @@ static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); static void set_termios(struct tty_struct *tty, struct termios *old_termios); -static int write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); static void send_xchar(struct tty_struct *tty, char ch); static void wait_until_sent(struct tty_struct *tty, int timeout); @@ -553,20 +538,12 @@ static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); static void set_break(struct tty_struct *tty, int break_state); -/* sppp support and callbacks */ - -#ifdef CONFIG_SYNCLINK_SYNCPPP -static void sppp_init(SLMP_INFO *info); -static void sppp_delete(SLMP_INFO *info); -static void sppp_rx_done(SLMP_INFO *info, char *buf, int size); -static void sppp_tx_done(SLMP_INFO *info); - -static int sppp_cb_open(struct net_device *d); -static int sppp_cb_close(struct net_device *d); -static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev); -static void sppp_cb_tx_timeout(struct net_device *dev); -static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(SLMP_INFO *info); +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size); +static int hdlcdev_init(SLMP_INFO *info); +static void hdlcdev_exit(SLMP_INFO *info); #endif /* ioctl handlers */ @@ -668,7 +645,7 @@ static unsigned char tx_active_fifo_level = 16; // tx request FIFO activation le static unsigned char tx_negate_fifo_level = 32; // tx request FIFO negation level in bytes static u32 misc_ctrl_value = 0x007e4040; -static u32 lcr1_brdr_value = 0x0080002d; +static u32 lcr1_brdr_value = 0x00800029; static u32 read_ahead_count = 8; @@ -722,6 +699,29 @@ static inline int sanity_check(SLMP_INFO *info, return 0; } +/** + * line discipline callback wrappers + * + * The wrappers maintain line discipline references + * while calling into the line discipline. + * + * ldisc_receive_buf - pass receive data to line discipline + */ + +static void ldisc_receive_buf(struct tty_struct *tty, + const __u8 *data, char *flags, int count) +{ + struct tty_ldisc *ld; + if (!tty) + return; + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->receive_buf) + ld->receive_buf(tty, data, flags, count); + tty_ldisc_deref(ld); + } +} + /* tty callbacks */ /* Called when a port is opened. Init and enable port. @@ -800,7 +800,7 @@ static int open(struct tty_struct *tty, struct file *filp) cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -869,8 +869,7 @@ static void close(struct tty_struct *tty, struct file *filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); shutdown(info); @@ -879,8 +878,7 @@ static void close(struct tty_struct *tty, struct file *filp) if (info->blocked_open) { if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -973,16 +971,15 @@ static void set_termios(struct tty_struct *tty, struct termios *old_termios) * Arguments: * * tty pointer to tty information structure - * from_user flag: 1 = from user process * buf pointer to buffer containing send data * count size of send data in bytes * * Return Value: number of characters written */ -static int write(struct tty_struct *tty, int from_user, +static int write(struct tty_struct *tty, const unsigned char *buf, int count) { - int c, ret = 0, err; + int c, ret = 0; SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; unsigned long flags; @@ -1009,29 +1006,19 @@ static int write(struct tty_struct *tty, int from_user, tx_load_dma_buffer(info, info->tx_buf, info->tx_count); goto start; } - if (!from_user) { - ret = info->tx_count = count; - tx_load_dma_buffer(info, buf, count); - goto start; - } + ret = info->tx_count = count; + tx_load_dma_buffer(info, buf, count); + goto start; } for (;;) { - c = MIN(count, - MIN(info->max_frame_size - info->tx_count - 1, + c = min_t(int, count, + min(info->max_frame_size - info->tx_count - 1, info->max_frame_size - info->tx_put)); if (c <= 0) break; - if (from_user) { - COPY_FROM_USER(err, info->tx_buf + info->tx_put, buf, c); - if (err) { - if (!ret) - ret = -EFAULT; - break; - } - } else - memcpy(info->tx_buf + info->tx_put, buf, c); + memcpy(info->tx_buf + info->tx_put, buf, c); spin_lock_irqsave(&info->lock,flags); info->tx_put += c; @@ -1161,12 +1148,11 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) char_time = 1; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min_t(unsigned long, char_time, timeout); if ( info->params.mode == MGSL_MODE_HDLC ) { while (info->tx_active) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -1176,8 +1162,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) //TODO: determine if there is something similar to USC16C32 // TXSTATUS_ALL_SENT status while ( info->tx_active && info->tx_enabled) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -1275,9 +1260,7 @@ static void flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&info->lock,flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* throttle (stop) transmitter @@ -1627,79 +1610,125 @@ static void set_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->lock,flags); } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC -/* syncppp support and callbacks */ - -static void cb_setup(struct net_device *dev) -{ - dev->open = sppp_cb_open; - dev->stop = sppp_cb_close; - dev->hard_start_xmit = sppp_cb_tx; - dev->do_ioctl = sppp_cb_ioctl; - dev->get_stats = sppp_cb_net_stats; - dev->tx_timeout = sppp_cb_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} - -static void sppp_init(SLMP_INFO *info) +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - struct net_device *d; + SLMP_INFO *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; - sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - d = alloc_netdev(0, info->netname, cb_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; - - d->irq = info->irq_level; - d->priv = info; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } - sppp_attach(&info->pppdev); - cb_setup(d); + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; - free_netdev(d); - return; - } + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); - if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_init(%s)\n",info->netname); + return 0; } -static void sppp_delete(SLMP_INFO *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + SLMP_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->tx_count = skb->len; + tx_load_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; } -static int sppp_cb_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - SLMP_INFO *info = d->priv; - int err; + SLMP_INFO *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_cb_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_cb_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -1707,141 +1736,298 @@ static int sppp_cb_open(struct net_device *d) spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -static void sppp_cb_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - SLMP_INFO *info = dev->priv; + SLMP_INFO *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - SLMP_INFO *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + SLMP_INFO *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->tx_count = skb->len; - tx_load_dma_buffer(info, skb->data, skb->len); - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - dev->trans_start = jiffies; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - return 0; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -static int sppp_cb_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - SLMP_INFO *info = d->priv; + SLMP_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_cb_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; + netif_wake_queue(dev); } -static void sppp_rx_done(SLMP_INFO *info, char *buf, int size) +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(SLMP_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->protocol = hdlc_type_trans(skb, info->netdev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -static void sppp_tx_done(SLMP_INFO *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(SLMP_INFO *info) { - SLMP_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->mem_start = info->phys_sca_base; + dev->mem_end = info->phys_sca_base + SCA_BASE_SIZE - 1; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(SLMP_INFO *info) { - SLMP_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ /* Return next bottom half action to perform. @@ -1941,13 +2127,7 @@ void bh_transmit(SLMP_INFO *info) __FILE__,__LINE__,info->device_name); if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) { - if ( debug_level >= DEBUG_LEVEL_BH ) - printk( "%s(%d):%s calling ldisc.write_wakeup\n", - __FILE__,__LINE__,info->device_name); - (tty->ldisc.write_wakeup)(tty); - } + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } } @@ -1994,16 +2174,15 @@ void isr_rxint(SLMP_INFO * info) { struct tty_struct *tty = info->tty; struct mgsl_icount *icount = &info->icount; - unsigned char status = read_reg(info, SR1); - unsigned char status2 = read_reg(info, SR2); + unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD); + unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN; /* clear status bits */ - if ( status & (FLGD + IDLD + CDCD + BRKD) ) - write_reg(info, SR1, - (unsigned char)(status & (FLGD + IDLD + CDCD + BRKD))); + if (status) + write_reg(info, SR1, status); - if ( status2 & OVRN ) - write_reg(info, SR2, (unsigned char)(status2 & OVRN)); + if (status2) + write_reg(info, SR2, status2); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_rxint status=%02X %02x\n", @@ -2140,15 +2319,22 @@ void isr_txeom(SLMP_INFO * info, unsigned char status) printk("%s(%d):%s isr_txeom status=%02x\n", __FILE__,__LINE__,info->device_name,status); - /* disable and clear MSCI interrupts */ - info->ie1_value &= ~(IDLE + UDRN); - write_reg(info, IE1, info->ie1_value); - write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); - write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */ write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ + if (status & UDRN) { + write_reg(info, CMD, TXRESET); + write_reg(info, CMD, TXENABLE); + } else + write_reg(info, CMD, TXBUFCLR); + + /* disable and clear tx interrupts */ + info->ie0_value &= ~TXRDYE; + info->ie1_value &= ~(IDLE + UDRN); + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + write_reg(info, SR1, (unsigned char)(UDRN + IDLE)); + if ( info->tx_active ) { if (info->params.mode != MGSL_MODE_ASYNC) { if (status & UDRN) @@ -2168,9 +2354,9 @@ void isr_txeom(SLMP_INFO * info, unsigned char status) set_signals(info); } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -2189,10 +2375,10 @@ void isr_txeom(SLMP_INFO * info, unsigned char status) */ void isr_txint(SLMP_INFO * info) { - unsigned char status = read_reg(info, SR1); + unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS); /* clear status bits */ - write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS))); + write_reg(info, SR1, status); if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):%s isr_txint status=%02x\n", @@ -2221,6 +2407,14 @@ void isr_txrdy(SLMP_INFO * info) printk("%s(%d):%s isr_txrdy() tx_count=%d\n", __FILE__,__LINE__,info->device_name,info->tx_count); + if (info->params.mode != MGSL_MODE_ASYNC) { + /* disable TXRDY IRQ, enable IDLE IRQ */ + info->ie0_value &= ~TXRDYE; + info->ie1_value |= IDLE; + write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value)); + return; + } + if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) { tx_stop(info); return; @@ -2275,13 +2469,6 @@ void isr_rxdmaerror(SLMP_INFO * info) void isr_txdmaok(SLMP_INFO * info) { - /* BIT7 = EOT (end of transfer, used for async mode) - * BIT6 = EOM (end of message/frame, used for sync mode) - * - * We don't look at DMA status because only EOT is enabled - * and we always clear and disable all tx DMA IRQs. - */ -// unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0; unsigned char status_reg1 = read_reg(info, SR1); write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */ @@ -2292,19 +2479,10 @@ void isr_txdmaok(SLMP_INFO * info) printk("%s(%d):%s isr_txdmaok(), status=%02x\n", __FILE__,__LINE__,info->device_name,status_reg1); - /* If transmitter already idle, do end of frame processing, - * otherwise enable interrupt for tx IDLE. - */ - if (status_reg1 & IDLE) - isr_txeom(info, IDLE); - else { - /* disable and clear underrun IRQ, enable IDLE interrupt */ - info->ie1_value |= IDLE; - info->ie1_value &= ~UDRN; - write_reg(info, IE1, info->ie1_value); - - write_reg(info, SR1, UDRN); - } + /* program TXRDY as FIFO empty flag, enable TXRDY IRQ */ + write_reg16(info, TRC0, 0); + info->ie0_value |= TXRDYE; + write_reg(info, IE0, info->ie0_value); } void isr_txdmaerror(SLMP_INFO * info) @@ -2358,12 +2536,12 @@ void isr_io_pin( SLMP_INFO *info, u16 status ) icount->dcd++; if (status & SerialSignal_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(status & SerialSignal_DCD, info->netdev); +#endif } if (status & MISCSTATUS_CTS_LATCHED) { @@ -2577,7 +2755,7 @@ static int startup(SLMP_INFO * info) change_params(info); - info->status_timer.expires = jiffies + jiffies_from_ms(10); + info->status_timer.expires = jiffies + msecs_to_jiffies(10); add_timer(&info->status_timer); if (info->tty) @@ -2988,7 +3166,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) unsigned char oldval = info->ie1_value; unsigned char newval = oldval + (mask & MgslEvent_ExitHuntMode ? FLGD:0) + - (mask & MgslEvent_IdleReceived ? IDLE:0); + (mask & MgslEvent_IdleReceived ? IDLD:0); if ( oldval != newval ) { info->ie1_value = newval; write_reg(info, IE1, info->ie1_value); @@ -3055,7 +3233,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr) spin_lock_irqsave(&info->lock,flags); if (!waitqueue_active(&info->event_wait_q)) { /* disable enable exit hunt mode/idle rcvd IRQs */ - info->ie1_value &= ~(FLGD|IDLE); + info->ie1_value &= ~(FLGD|IDLD); write_reg(info, IE1, info->ie1_value); } spin_unlock_irqrestore(&info->lock,flags); @@ -3449,9 +3627,10 @@ void free_tmp_rx_buf(SLMP_INFO *info) int claim_resources(SLMP_INFO *info) { - if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else @@ -3460,22 +3639,25 @@ int claim_resources(SLMP_INFO *info) if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) { printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else info->lcr_mem_requested = 1; - if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else info->sca_base_requested = 1; - if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) { + if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) { printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_statctrl_base); + info->init_error = DiagStatus_AddressConflict; goto errout; } else @@ -3485,33 +3667,41 @@ int claim_resources(SLMP_INFO *info) if (!info->memory_base) { printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } - if ( !memory_test(info) ) { - printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset; + info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE); if (!info->lcr_base) { printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } + info->lcr_base += info->lcr_offset; - info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset; + info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE); if (!info->sca_base) { printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base ); + info->init_error = DiagStatus_CantAssignPciResources; goto errout; } + info->sca_base += info->sca_offset; - info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset; + info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE); if (!info->statctrl_base) { printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_statctrl_base ); + info->init_error = DiagStatus_CantAssignPciResources; + goto errout; + } + info->statctrl_base += info->statctrl_offset; + + if ( !memory_test(info) ) { + printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + info->init_error = DiagStatus_MemoryError; goto errout; } @@ -3534,7 +3724,7 @@ void release_resources(SLMP_INFO *info) } if ( info->shared_mem_requested ) { - release_mem_region(info->phys_memory_base,0x40000); + release_mem_region(info->phys_memory_base,SCA_MEM_SIZE); info->shared_mem_requested = 0; } if ( info->lcr_mem_requested ) { @@ -3542,11 +3732,11 @@ void release_resources(SLMP_INFO *info) info->lcr_mem_requested = 0; } if ( info->sca_base_requested ) { - release_mem_region(info->phys_sca_base + info->sca_offset,512); + release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE); info->sca_base_requested = 0; } if ( info->sca_statctrl_requested ) { - release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16); + release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE); info->sca_statctrl_requested = 0; } @@ -3616,9 +3806,8 @@ void add_device(SLMP_INFO *info) info->irq_level, info->max_frame_size ); -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif } @@ -3788,7 +3977,6 @@ static struct tty_operations ops = { static void synclinkmp_cleanup(void) { - unsigned long flags; int rc; SLMP_INFO *info; SLMP_INFO *tmp; @@ -3802,34 +3990,24 @@ static void synclinkmp_cleanup(void) put_tty_driver(serial_driver); } + /* reset devices */ info = synclinkmp_device_list; while(info) { -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - sppp_delete(info); -#endif reset_port(info); - if ( info->port_num == 0 ) { - if ( info->irq_requested ) { - free_irq(info->irq_level, info); - info->irq_requested = 0; - } - } info = info->next_device; } - /* port 0 of each adapter originally claimed - * all resources, release those now - */ + /* release devices */ info = synclinkmp_device_list; while(info) { +#ifdef CONFIG_HDLC + hdlcdev_exit(info); +#endif free_dma_bufs(info); free_tmp_rx_buf(info); if ( info->port_num == 0 ) { - spin_lock_irqsave(&info->lock,flags); - reset_adapter(info); - write_reg(info, LPR, 1); /* set low power mode */ - spin_unlock_irqrestore(&info->lock,flags); + if (info->sca_base) + write_reg(info, LPR, 1); /* set low power mode */ release_resources(info); } tmp = info; @@ -4112,6 +4290,9 @@ void tx_start(SLMP_INFO *info) } } + write_reg16(info, TRC0, + (unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level)); + write_reg(info, TXDMA + DSR, 0); /* disable DMA channel */ write_reg(info, TXDMA + DCMD, SWABORT); /* reset/init DMA channel */ @@ -4123,17 +4304,16 @@ void tx_start(SLMP_INFO *info) write_reg16(info, TXDMA + EDA, info->tx_buf_list_ex[info->last_tx_buf].phys_entry); - /* clear IDLE and UDRN status bit */ - info->ie1_value &= ~(IDLE + UDRN); - if (info->params.mode != MGSL_MODE_ASYNC) - info->ie1_value |= UDRN; /* HDLC, IRQ on underrun */ - write_reg(info, IE1, info->ie1_value); /* enable MSCI interrupts */ + /* enable underrun IRQ */ + info->ie1_value &= ~IDLE; + info->ie1_value |= UDRN; + write_reg(info, IE1, info->ie1_value); write_reg(info, SR1, (unsigned char)(IDLE + UDRN)); write_reg(info, TXDMA + DIR, 0x40); /* enable Tx DMA interrupts (EOM) */ write_reg(info, TXDMA + DSR, 0xf2); /* clear Tx DMA IRQs, enable Tx DMA */ - info->tx_timer.expires = jiffies + jiffies_from_ms(5000); + info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); add_timer(&info->tx_timer); } else { @@ -4823,10 +5003,12 @@ CheckAgain: info->icount.rxcrc++; framesize = 0; - -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } @@ -4836,7 +5018,7 @@ CheckAgain: if ( debug_level >= DEBUG_LEVEL_DATA ) trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, - MIN(framesize,SCABUFSIZE),0); + min_t(int, framesize,SCABUFSIZE),0); if (framesize) { if (framesize > info->max_frame_size) @@ -4851,7 +5033,7 @@ CheckAgain: info->icount.rxok++; while(copy_count) { - int partial_count = MIN(copy_count,SCABUFSIZE); + int partial_count = min(copy_count,SCABUFSIZE); memcpy( ptmp, info->rx_buf_list_ex[index].virt_addr, partial_count ); @@ -4862,22 +5044,13 @@ CheckAgain: index = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - sppp_rx_done(info,info->tmp_rx_buf,framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info,info->tmp_rx_buf,framesize); else #endif - { - if ( tty && tty->ldisc.receive_buf ) { - /* Call the line discipline receive callback directly. */ - tty->ldisc.receive_buf(tty, - info->tmp_rx_buf, - info->flag_buf, - framesize); - } - } + ldisc_receive_buf(tty,info->tmp_rx_buf, + info->flag_buf, framesize); } } /* Free the buffers used by this frame. */ @@ -4910,14 +5083,14 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count) SCADESC_EX *desc_ex; if ( debug_level >= DEBUG_LEVEL_DATA ) - trace_block(info,buf, MIN(count,SCABUFSIZE), 1); + trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1); /* Copy source buffer to one or more DMA buffers, starting with * the first transmit dma buffer. */ for(i=0;;) { - copy_count = MIN(count,SCABUFSIZE); + copy_count = min_t(unsigned short,count,SCABUFSIZE); desc = &info->tx_buf_list[i]; desc_ex = &info->tx_buf_list_ex[i]; @@ -5020,8 +5193,7 @@ int irq_test(SLMP_INFO *info) timeout=100; while( timeout-- && !info->irq_occurred ) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_from_ms(10)); + msleep_interruptible(10); } spin_lock_irqsave(&info->lock,flags); @@ -5171,8 +5343,7 @@ int loopback_test(SLMP_INFO *info) /* wait for receive complete */ /* Set a timeout for waiting for interrupt. */ for ( timeout = 100; timeout; --timeout ) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(jiffies_from_ms(10)); + msleep_interruptible(10); if (rx_get_frame(info)) { rc = TRUE; @@ -5384,9 +5555,9 @@ void tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif bh_transmit(info); @@ -5428,7 +5599,7 @@ void status_timeout(unsigned long context) info->status_timer.data = (unsigned long)info; info->status_timer.function = status_timeout; - info->status_timer.expires = jiffies + jiffies_from_ms(10); + info->status_timer.expires = jiffies + msecs_to_jiffies(10); add_timer(&info->status_timer); } diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index da52bff37..fb4c59faa 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -216,6 +216,16 @@ static struct sysrq_key_op sysrq_kill_op = { /* END SIGNAL SYSRQ HANDLERS BLOCK */ +static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, + struct tty_struct *tty) +{ + normalize_rt_tasks(); +} +static struct sysrq_key_op sysrq_unrt_op = { + .handler = sysrq_handle_unrt, + .help_msg = "Nice", + .action_msg = "Nice All RT Tasks" +}; /* Key Operations table and lock */ static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED; @@ -250,7 +260,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = { #endif /* l */ NULL, /* m */ &sysrq_showmem_op, -/* n */ NULL, +/* n */ &sysrq_unrt_op, /* o */ NULL, /* This will often be registered as 'Off' at init time */ /* p */ &sysrq_showregs_op, @@ -283,14 +293,6 @@ static int sysrq_key_table_key2index(int key) { return retval; } -/* - * table lock and unlocking functions, exposed to modules - */ - -void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); } - -void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); } - /* * get and put functions for the table, exposed to modules. */ @@ -323,8 +325,9 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) struct sysrq_key_op *op_p; int orig_log_level; int i, j; + unsigned long flags; - __sysrq_lock_table(); + spin_lock_irqsave(&sysrq_key_table_lock, flags); orig_log_level = console_loglevel; console_loglevel = 7; printk(KERN_INFO "SysRq : "); @@ -346,7 +349,7 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) printk ("\n"); console_loglevel = orig_log_level; } - __sysrq_unlock_table(); + spin_unlock_irqrestore(&sysrq_key_table_lock, flags); } /* @@ -361,8 +364,34 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) __handle_sysrq(key, pt_regs, tty); } +int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, + struct sysrq_key_op *remove_op_p) { + + int retval; + unsigned long flags; + + spin_lock_irqsave(&sysrq_key_table_lock, flags); + if (__sysrq_get_key_op(key) == remove_op_p) { + __sysrq_put_key_op(key, insert_op_p); + retval = 0; + } else { + retval = -1; + } + spin_unlock_irqrestore(&sysrq_key_table_lock, flags); + + return retval; +} + +int register_sysrq_key(int key, struct sysrq_key_op *op_p) +{ + return __sysrq_swap_key_ops(key, op_p, NULL); +} + +int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) +{ + return __sysrq_swap_key_ops(key, NULL, op_p); +} + EXPORT_SYMBOL(handle_sysrq); -EXPORT_SYMBOL(__sysrq_lock_table); -EXPORT_SYMBOL(__sysrq_unlock_table); -EXPORT_SYMBOL(__sysrq_get_key_op); -EXPORT_SYMBOL(__sysrq_put_key_op); +EXPORT_SYMBOL(register_sysrq_key); +EXPORT_SYMBOL(unregister_sysrq_key); diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 48d7a7cc0..2fd2901ff 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include /* DevFs support */ #include /* Our code depend on parport */ #include diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c index 66881e953..d812253b4 100644 --- a/drivers/char/tpqic02.c +++ b/drivers/char/tpqic02.c @@ -554,10 +554,9 @@ static int wait_for_ready(time_t timeout) /* not ready and no exception && timeout not expired yet */ while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) { /* be `nice` to other processes on long operations... */ - current->state = TASK_INTERRUPTIBLE; /* nap 0.30 sec between checks, */ /* but could be woken up earlier by signals... */ - schedule_timeout(3 * HZ / 10); + msleep_interruptible(300); } /* don't use jiffies for this test because it may have changed by now */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 91f530c61..0f752917a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -92,10 +92,11 @@ #include #include #include +#include +#include #include #include -#include #include #include @@ -120,10 +121,14 @@ struct termios tty_std_termios = { /* for the benefit of tty drivers */ EXPORT_SYMBOL(tty_std_termios); +/* This list gets poked at by procfs and various bits of boot up code. This + could do with some rationalisation such as pulling the tty proc function + into this file */ + LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ -/* Semaphore to protect creating and releasing a tty */ +/* Semaphore to protect creating and releasing a tty. This is shared with + vt.c for deeply disgusting hack reasons */ DECLARE_MUTEX(tty_sem); #ifdef CONFIG_UNIX98_PTYS @@ -131,6 +136,7 @@ extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ extern int pty_limit; /* Config limit on Unix98 ptys */ static DEFINE_IDR(allocated_ptys); static DECLARE_MUTEX(allocated_ptys_lock); +static int ptmx_open(struct inode *, struct file *); #endif extern void disable_early_printk(void); @@ -162,6 +168,7 @@ static struct tty_struct *alloc_tty_struct(void) static inline void free_tty_struct(struct tty_struct *tty) { + kfree(tty->write_buf); kfree(tty); } @@ -223,65 +230,323 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) return 0; } +/* + * This is probably overkill for real world processors but + * they are not on hot paths so a little discipline won't do + * any harm. + */ + +static void tty_set_termios_ldisc(struct tty_struct *tty, int num) +{ + down(&tty->termios_sem); + tty->termios->c_line = num; + up(&tty->termios_sem); +} + +/* + * This guards the refcounted line discipline lists. The lock + * must be taken with irqs off because there are hangup path + * callers who will do ldisc lookups and cannot sleep. + */ + +static spinlock_t tty_ldisc_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); +static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ + int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) { + unsigned long flags; + int ret = 0; + if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; + spin_lock_irqsave(&tty_ldisc_lock, flags); if (new_ldisc) { - ldiscs[disc] = *new_ldisc; - ldiscs[disc].flags |= LDISC_FLAG_DEFINED; - ldiscs[disc].num = disc; - } else - memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc)); + tty_ldiscs[disc] = *new_ldisc; + tty_ldiscs[disc].num = disc; + tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; + tty_ldiscs[disc].refcount = 0; + } else { + if(tty_ldiscs[disc].refcount) + ret = -EBUSY; + else + tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); - return 0; + return ret; } EXPORT_SYMBOL(tty_register_ldisc); -/* Set the discipline of a tty line. */ +struct tty_ldisc *tty_ldisc_get(int disc) +{ + unsigned long flags; + struct tty_ldisc *ld; + + if (disc < N_TTY || disc >= NR_LDISCS) + return NULL; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + + ld = &tty_ldiscs[disc]; + /* Check the entry is defined */ + if(ld->flags & LDISC_FLAG_DEFINED) + { + /* If the module is being unloaded we can't use it */ + if (!try_module_get(ld->owner)) + ld = NULL; + else /* lock it */ + ld->refcount++; + } + else + ld = NULL; + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + return ld; +} + +EXPORT_SYMBOL_GPL(tty_ldisc_get); + +void tty_ldisc_put(int disc) +{ + struct tty_ldisc *ld; + unsigned long flags; + + if (disc < N_TTY || disc >= NR_LDISCS) + BUG(); + + spin_lock_irqsave(&tty_ldisc_lock, flags); + ld = &tty_ldiscs[disc]; + if(ld->refcount == 0) + BUG(); + ld->refcount --; + module_put(ld->owner); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); +} + +EXPORT_SYMBOL_GPL(tty_ldisc_put); + +void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) +{ + tty->ldisc = *ld; + tty->ldisc.refcount = 0; +} + +/** + * tty_ldisc_try - internal helper + * @tty: the tty + * + * Make a single attempt to grab and bump the refcount on + * the tty ldisc. Return 0 on failure or 1 on success. This is + * used to implement both the waiting and non waiting versions + * of tty_ldisc_ref + */ + +static int tty_ldisc_try(struct tty_struct *tty) +{ + unsigned long flags; + struct tty_ldisc *ld; + int ret = 0; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + ld = &tty->ldisc; + if(test_bit(TTY_LDISC, &tty->flags)) + { + ld->refcount++; + ret = 1; + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + return ret; +} + +/** + * tty_ldisc_ref_wait - wait for the tty ldisc + * @tty: tty device + * + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then + * wait patiently until it changes. + * + * Note: Must not be called from an IRQ/timer context. The caller + * must also be careful not to hold other locks that will deadlock + * against a discipline change, such as an existing ldisc reference + * (which we check for) + */ + +struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) +{ + /* wait_event is a macro */ + wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); + if(tty->ldisc.refcount == 0) + printk(KERN_ERR "tty_ldisc_ref_wait\n"); + return &tty->ldisc; +} + +EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); + +/** + * tty_ldisc_ref - get the tty ldisc + * @tty: tty device + * + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then + * return NULL. Can be called from IRQ and timer functions. + */ + +struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) +{ + if(tty_ldisc_try(tty)) + return &tty->ldisc; + return NULL; +} + +EXPORT_SYMBOL_GPL(tty_ldisc_ref); + +/** + * tty_ldisc_deref - free a tty ldisc reference + * @ld: reference to free up + * + * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May + * be called in IRQ context. + */ + +void tty_ldisc_deref(struct tty_ldisc *ld) +{ + unsigned long flags; + + if(ld == NULL) + BUG(); + + spin_lock_irqsave(&tty_ldisc_lock, flags); + if(ld->refcount == 0) + printk(KERN_ERR "tty_ldisc_deref: no references.\n"); + else + ld->refcount--; + if(ld->refcount == 0) + wake_up(&tty_ldisc_wait); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); +} + +EXPORT_SYMBOL_GPL(tty_ldisc_deref); + +/** + * tty_ldisc_enable - allow ldisc use + * @tty: terminal to activate ldisc on + * + * Set the TTY_LDISC flag when the line discipline can be called + * again. Do neccessary wakeups for existing sleepers. + * + * Note: nobody should set this bit except via this function. Clearing + * directly is allowed. + */ + +static void tty_ldisc_enable(struct tty_struct *tty) +{ + set_bit(TTY_LDISC, &tty->flags); + wake_up(&tty_ldisc_wait); +} + +/** + * tty_set_ldisc - set line discipline + * @tty: the terminal to set + * @ldisc: the line discipline + * + * Set the discipline of a tty line. Must be called from a process + * context. + */ + static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval = 0; struct tty_ldisc o_ldisc; char buf[64]; + int work; + unsigned long flags; + struct tty_ldisc *ld; if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) return -EINVAL; + +restart: + + if (tty->ldisc.num == ldisc) + return 0; /* We are already in the desired discipline */ + + ld = tty_ldisc_get(ldisc); /* Eduardo Blanco */ /* Cyrus Durgin */ - if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) { + if (ld == NULL) { request_module("tty-ldisc-%d", ldisc); + ld = tty_ldisc_get(ldisc); } - if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) + if (ld == NULL) return -EINVAL; - if (tty->ldisc.num == ldisc) - return 0; /* We are already in the desired discipline */ - - if (!try_module_get(ldiscs[ldisc].owner)) - return -EINVAL; - o_ldisc = tty->ldisc; tty_wait_until_sent(tty, 0); + + /* + * Make sure we don't change while someone holds a + * reference to the line discipline. The TTY_LDISC bit + * prevents anyone taking a reference once it is clear. + * We need the lock to avoid racing reference takers. + */ + + spin_lock_irqsave(&tty_ldisc_lock, flags); + if(tty->ldisc.refcount) + { + /* Free the new ldisc we grabbed. Must drop the lock + first. */ + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(ldisc); + /* + * There are several reasons we may be busy, including + * random momentary I/O traffic. We must therefore + * retry. We could distinguish between blocking ops + * and retries if we made tty_ldisc_wait() smarter. That + * is up for discussion. + */ + if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) + return -ERESTARTSYS; + goto restart; + } + clear_bit(TTY_LDISC, &tty->flags); + clear_bit(TTY_DONT_FLIP, &tty->flags); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + /* + * From this point on we know nobody has an ldisc + * usage reference, nor can they obtain one until + * we say so later on. + */ + + work = cancel_delayed_work(&tty->flip.work); + /* + * Wait for ->hangup_work and ->flip.work handlers to terminate + */ + + flush_scheduled_work(); /* Shutdown the current discipline. */ if (tty->ldisc.close) (tty->ldisc.close)(tty); /* Now set up the new line discipline. */ - tty->ldisc = ldiscs[ldisc]; - tty->termios->c_line = ldisc; + tty_ldisc_assign(tty, ld); + tty_set_termios_ldisc(tty, ldisc); if (tty->ldisc.open) retval = (tty->ldisc.open)(tty); if (retval < 0) { - tty->ldisc = o_ldisc; - tty->termios->c_line = tty->ldisc.num; + tty_ldisc_put(ldisc); + /* There is an outstanding reference here so this is safe */ + tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num)); + tty_set_termios_ldisc(tty, tty->ldisc.num); if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; + tty_ldisc_put(o_ldisc.num); + /* This driver is always present */ + tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); + tty_set_termios_ldisc(tty, N_TTY); if (tty->ldisc.open) { int r = tty->ldisc.open(tty); @@ -291,12 +556,27 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_name(tty, buf), r); } } - } else { - module_put(o_ldisc.owner); } + /* At this point we hold a reference to the new ldisc and a + a reference to the old ldisc. If we ended up flipping back + to the existing ldisc we have two references to it */ if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc) tty->driver->set_ldisc(tty); + + tty_ldisc_put(o_ldisc.num); + + /* + * Allow ldisc referencing to occur as soon as the driver + * ldisc callback completes. + */ + + tty_ldisc_enable(tty); + + /* Restart it in case no characters kick it off. Safe if + already running */ + if(work) + schedule_delayed_work(&tty->flip.work, 1); return retval; } @@ -377,6 +657,19 @@ static struct file_operations tty_fops = { .fasync = tty_fasync, }; +#ifdef CONFIG_UNIX98_PTYS +static struct file_operations ptmx_fops = { + .llseek = no_llseek, + .read = tty_read, + .write = tty_write, + .poll = tty_poll, + .ioctl = tty_ioctl, + .open = ptmx_open, + .release = tty_release, + .fasync = tty_fasync, +}; +#endif + static struct file_operations console_fops = { .llseek = no_llseek, .read = tty_read, @@ -399,6 +692,53 @@ static struct file_operations hung_up_tty_fops = { static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED; static struct file *redirect; + +/** + * tty_wakeup - request more data + * @tty: terminal + * + * Internal and external helper for wakeups of tty. This function + * informs the line discipline if present that the driver is ready + * to receive more output data. + */ + +void tty_wakeup(struct tty_struct *tty) +{ + struct tty_ldisc *ld; + + if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) { + ld = tty_ldisc_ref(tty); + if(ld) { + if(ld->write_wakeup) + ld->write_wakeup(tty); + tty_ldisc_deref(ld); + } + } + wake_up_interruptible(&tty->write_wait); +} + +EXPORT_SYMBOL_GPL(tty_wakeup); + +/** + * tty_ldisc_flush - flush line discipline queue + * @tty: tty + * + * Flush the line discipline queue (if any) for this tty. If there + * is no line discipline active this is a no-op. + */ + +void tty_ldisc_flush(struct tty_struct *tty) +{ + struct tty_ldisc *ld = tty_ldisc_ref(tty); + if(ld) { + if(ld->flush_buffer) + ld->flush_buffer(tty); + tty_ldisc_deref(ld); + } +} + +EXPORT_SYMBOL_GPL(tty_ldisc_flush); + /* * This can be called by the "eventd" kernel thread. That is process synchronous, * but doesn't hold any locks, so we need to make sure we have the appropriate @@ -410,7 +750,7 @@ void do_tty_hangup(void *data) struct file * cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; - struct pid *pid; + struct tty_ldisc *ld; int closecount = 0, n; if (!tty) @@ -428,6 +768,7 @@ void do_tty_hangup(void *data) check_tty_count(tty, "do_tty_hangup"); file_list_lock(); + /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(filp, &tty->tty_files, f_list) { if (filp->f_op->write == redirected_tty_write) cons_filp = filp; @@ -440,21 +781,25 @@ void do_tty_hangup(void *data) file_list_unlock(); /* FIXME! What are the locking issues here? This may me overdoing things.. - * this question is especially important now that we've removed the irqlock. */ - { - unsigned long flags; + * this question is especially important now that we've removed the irqlock. */ - local_irq_save(flags); // FIXME: is this safe? - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + ld = tty_ldisc_ref(tty); + if(ld != NULL) /* We may have no line discipline at this point */ + { + if (ld->flush_buffer) + ld->flush_buffer(tty); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - local_irq_restore(flags); // FIXME: is this safe? + ld->write_wakeup) + ld->write_wakeup(tty); + if (ld->hangup) + ld->hangup(tty); } + /* FIXME: Once we trust the LDISC code better we can wait here for + ldisc completion and fix the driver call race */ + wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); @@ -463,26 +808,21 @@ void do_tty_hangup(void *data) * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) + { + down(&tty->termios_sem); *tty->termios = tty->driver->init_termios; - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - module_put(tty->ldisc.owner); - - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) { - int i = (tty->ldisc.open)(tty); - if (i < 0) - printk(KERN_ERR "do_tty_hangup: N_TTY open: " - "error %d\n", -i); - } + up(&tty->termios_sem); } + /* Defer ldisc switch */ + /* tty_deferred_ldisc_switch(N_TTY); + + This should get done automatically when the port closes and + tty_release is called */ + read_lock(&tasklist_lock); if (tty->session > 0) { - struct list_head *l; - for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { + do_each_task_pid(tty->session, PIDTYPE_SID, p) { if (p->signal->tty == tty) p->signal->tty = NULL; if (!p->signal->leader) @@ -491,7 +831,7 @@ void do_tty_hangup(void *data) send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->signal->tty_old_pgrp = tty->pgrp; - } + } while_each_task_pid(tty->session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); @@ -511,6 +851,17 @@ void do_tty_hangup(void *data) tty->driver->close(tty, cons_filp); } else if (tty->driver->hangup) (tty->driver->hangup)(tty); + + /* We don't want to have driver/ldisc interactions beyond + the ones we did here. The driver layer expects no + calls after ->hangup() from the ldisc side. However we + can't yet guarantee all that */ + + set_bit(TTY_HUPPED, &tty->flags); + if (ld) { + tty_ldisc_enable(tty); + tty_ldisc_deref(ld); + } unlock_kernel(); if (f) fput(f); @@ -563,8 +914,6 @@ void disassociate_ctty(int on_exit) { struct tty_struct *tty; struct task_struct *p; - struct list_head *l; - struct pid *pid; int tty_pgrp = -1; lock_kernel(); @@ -593,8 +942,9 @@ void disassociate_ctty(int on_exit) tty->pgrp = -1; read_lock(&tasklist_lock); - for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid) + do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { p->signal->tty = NULL; + } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); unlock_kernel(); } @@ -627,9 +977,9 @@ void start_tty(struct tty_struct *tty) } if (tty->driver->start) (tty->driver->start)(tty); - if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + + /* If we have a running line discipline it may need kicking */ + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } @@ -641,6 +991,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, int i; struct tty_struct * tty; struct inode *inode; + struct tty_ldisc *ld; tty = (struct tty_struct *)file->private_data; inode = file->f_dentry->d_inode; @@ -649,11 +1000,15 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) return -EIO; + /* We want to wait for the line discipline to sort out in this + situation */ + ld = tty_ldisc_ref_wait(tty); lock_kernel(); - if (tty->ldisc.read) - i = (tty->ldisc.read)(tty,file,buf,count); + if (ld->read) + i = (ld->read)(tty,file,buf,count); else i = -EIO; + tty_ldisc_deref(ld); unlock_kernel(); if (i > 0) inode->i_atime = CURRENT_TIME; @@ -665,41 +1020,72 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, * denial-of-service type attacks */ static inline ssize_t do_tty_write( - ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char __user *, size_t), + ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t), struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, + const char __user *buf, size_t count) { ssize_t ret = 0, written = 0; + unsigned int chunk; if (down_interruptible(&tty->atomic_write)) { return -ERESTARTSYS; } - if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) { + + /* + * We chunk up writes into a temporary buffer. This + * simplifies low-level drivers immensely, since they + * don't have locking issues and user mode accesses. + * + * But if TTY_NO_WRITE_SPLIT is set, we should use a + * big chunk-size.. + */ + chunk = 4096; + if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags)) + chunk = 65536; + if (count < chunk) + chunk = count; + + /* write_buf/write_cnt is protected by the atomic_write semaphore */ + if (tty->write_cnt < chunk) { + unsigned char *buf; + + if (chunk < 1024) + chunk = 1024; + + buf = kmalloc(chunk, GFP_KERNEL); + if (!buf) { + up(&tty->atomic_write); + return -ENOMEM; + } + kfree(tty->write_buf); + tty->write_cnt = chunk; + tty->write_buf = buf; + } + + /* Do the write .. */ + for (;;) { + size_t size = count; + if (size > chunk) + size = chunk; + ret = -EFAULT; + if (copy_from_user(tty->write_buf, buf, size)) + break; lock_kernel(); - written = write(tty, file, buf, count); + ret = write(tty, file, tty->write_buf, size); unlock_kernel(); - } else { - for (;;) { - unsigned long size = max((unsigned long)PAGE_SIZE*2, 16384UL); - if (size > count) - size = count; - lock_kernel(); - ret = write(tty, file, buf, size); - unlock_kernel(); - if (ret <= 0) - break; - written += ret; - buf += ret; - count -= ret; - if (!count) - break; - ret = -ERESTARTSYS; - if (signal_pending(current)) - break; - cond_resched(); - } + if (ret <= 0) + break; + written += ret; + buf += ret; + count -= ret; + if (!count) + break; + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + cond_resched(); } if (written) { file->f_dentry->d_inode->i_mtime = CURRENT_TIME; @@ -715,16 +1101,22 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou { struct tty_struct * tty; struct inode *inode = file->f_dentry->d_inode; - + ssize_t ret; + struct tty_ldisc *ld; + tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags))) return -EIO; - if (!tty->ldisc.write) - return -EIO; - return do_tty_write(tty->ldisc.write, tty, file, - (const unsigned char __user *)buf, count); + + ld = tty_ldisc_ref_wait(tty); + if (!ld->write) + ret = -EIO; + else + ret = do_tty_write(ld->write, tty, file, buf, count); + tty_ldisc_deref(ld); + return ret; } ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count, @@ -749,6 +1141,17 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t return tty_write(file, buf, count, ppos); } +static char ptychar[] = "pqrstuvwxyzabcde"; + +static inline void pty_line_name(struct tty_driver *driver, int index, char *p) +{ + int i = index + driver->name_base; + /* ->name is initialized to "ttyp", but "tty" is expected */ + sprintf(p, "%s%c%x", + driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name, + ptychar[i >> 4 & 0xf], i & 0xf); +} + static inline void tty_line_name(struct tty_driver *driver, int index, char *p) { sprintf(p, "%s%d", driver->name, index + driver->name_base); @@ -910,6 +1313,7 @@ static int init_dev(struct tty_driver *driver, int idx, * If we fail here just call release_mem to clean up. No need * to decrement the use counts, as release_mem doesn't care. */ + if (tty->ldisc.open) { retval = (tty->ldisc.open)(tty); if (retval) @@ -922,7 +1326,9 @@ static int init_dev(struct tty_driver *driver, int idx, (tty->ldisc.close)(tty); goto release_mem_out; } + tty_ldisc_enable(o_tty); } + tty_ldisc_enable(tty); goto success; /* @@ -951,6 +1357,9 @@ fast_track: tty->count++; tty->driver = driver; /* N.B. why do this every time?? */ + /* FIXME */ + if(!test_bit(TTY_LDISC, &tty->flags)) + printk(KERN_ERR "init_dev but no ldisc\n"); success: *ret_tty = tty; @@ -1054,6 +1463,7 @@ static void release_dev(struct file * filp) int devpts_master, devpts; int idx; char buf[64]; + unsigned long flags; tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev")) @@ -1130,7 +1540,6 @@ static void release_dev(struct file * filp) } } #endif - if (tty->driver->close) tty->driver->close(tty, filp); @@ -1235,15 +1644,15 @@ static void release_dev(struct file * filp) */ if (tty_closing || o_tty_closing) { struct task_struct *p; - struct list_head *l; - struct pid *pid; read_lock(&tasklist_lock); - for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) + do_each_task_pid(tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; + } while_each_task_pid(tty->session, PIDTYPE_SID, p); if (o_tty) - for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) + do_each_task_pid(o_tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; + } while_each_task_pid(o_tty->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); } @@ -1254,36 +1663,58 @@ static void release_dev(struct file * filp) #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "freeing tty structure..."); #endif - /* * Prevent flush_to_ldisc() from rescheduling the work for later. Then - * kill any delayed work. + * kill any delayed work. As this is the final close it does not + * race with the set_ldisc code path. */ + clear_bit(TTY_LDISC, &tty->flags); clear_bit(TTY_DONT_FLIP, &tty->flags); cancel_delayed_work(&tty->flip.work); /* * Wait for ->hangup_work and ->flip.work handlers to terminate */ + flush_scheduled_work(); - + + /* + * Wait for any short term users (we know they are just driver + * side waiters as the file is closing so user count on the file + * side is zero. + */ + spin_lock_irqsave(&tty_ldisc_lock, flags); + while(tty->ldisc.refcount) + { + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); + spin_lock_irqsave(&tty_ldisc_lock, flags); + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); /* * Shutdown the current line discipline, and reset it to N_TTY. * N.B. why reset ldisc when we're releasing the memory?? + * + * FIXME: this MUST get fixed for the new reflocking */ if (tty->ldisc.close) (tty->ldisc.close)(tty); - module_put(tty->ldisc.owner); + tty_ldisc_put(tty->ldisc.num); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; + /* + * Switch the line discipline back + */ + tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); + tty_set_termios_ldisc(tty,N_TTY); if (o_tty) { + /* FIXME: could o_tty be in setldisc here ? */ + clear_bit(TTY_LDISC, &o_tty->flags); if (o_tty->ldisc.close) (o_tty->ldisc.close)(o_tty); - module_put(o_tty->ldisc.owner); - o_tty->ldisc = ldiscs[N_TTY]; + tty_ldisc_put(o_tty->ldisc.num); + tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY)); + tty_set_termios_ldisc(o_tty,N_TTY); } - /* * The release_mem function takes care of the details of clearing * the slots and preserving the termios structure. @@ -1323,6 +1754,7 @@ static int tty_open(struct inode * inode, struct file * filp) unsigned short saved_flags = filp->f_flags; nonseekable_open(inode, filp); + retry_open: noctty = filp->f_flags & O_NOCTTY; index = -1; @@ -1358,53 +1790,13 @@ retry_open: return -ENODEV; } -#ifdef CONFIG_UNIX98_PTYS - if (device == MKDEV(TTYAUX_MAJOR,2)) { - int idr_ret; - - /* find a device that is not in use. */ - down(&allocated_ptys_lock); - if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { - up(&allocated_ptys_lock); - return -ENOMEM; - } - idr_ret = idr_get_new(&allocated_ptys, NULL, &index); - if (idr_ret < 0) { - up(&allocated_ptys_lock); - if (idr_ret == -EAGAIN) - return -ENOMEM; - return -EIO; - } - if (index >= pty_limit) { - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - return -EIO; - } - up(&allocated_ptys_lock); - - driver = ptm_driver; - retval = init_dev(driver, index, &tty); - if (retval) { - down(&allocated_ptys_lock); - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - return retval; - } - - set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - if (devpts_pty_new(tty->link)) - retval = -ENOMEM; - } else -#endif - { - driver = get_tty_driver(device, &index); - if (!driver) - return -ENODEV; + driver = get_tty_driver(device, &index); + if (!driver) + return -ENODEV; got_driver: - retval = init_dev(driver, index, &tty); - if (retval) - return retval; - } + retval = init_dev(driver, index, &tty); + if (retval) + return retval; filp->private_data = tty; file_move(filp, &tty->tty_files); @@ -1431,15 +1823,6 @@ got_driver: printk(KERN_DEBUG "error %d in opening %s...", retval, tty->name); #endif - -#ifdef CONFIG_UNIX98_PTYS - if (index != -1) { - down(&allocated_ptys_lock); - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - } -#endif - release_dev(filp); if (retval != -ERESTARTSYS) return retval; @@ -1467,6 +1850,62 @@ got_driver: return 0; } +#ifdef CONFIG_UNIX98_PTYS +static int ptmx_open(struct inode * inode, struct file * filp) +{ + struct tty_struct *tty; + int retval; + int index; + int idr_ret; + + nonseekable_open(inode, filp); + + /* find a device that is not in use. */ + down(&allocated_ptys_lock); + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + up(&allocated_ptys_lock); + return -ENOMEM; + } + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + up(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + return -ENOMEM; + return -EIO; + } + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return -EIO; + } + up(&allocated_ptys_lock); + + retval = init_dev(ptm_driver, index, &tty); + if (retval) + goto out; + + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ + filp->private_data = tty; + file_move(filp, &tty->tty_files); + + retval = -ENOMEM; + if (devpts_pty_new(tty->link)) + goto out1; + + check_tty_count(tty, "tty_open"); + retval = ptm_driver->open(tty, filp); + if (!retval) + return 0; +out1: + release_dev(filp); +out: + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return retval; +} +#endif + static int tty_release(struct inode * inode, struct file * filp) { lock_kernel(); @@ -1479,14 +1918,18 @@ static int tty_release(struct inode * inode, struct file * filp) static unsigned int tty_poll(struct file * filp, poll_table * wait) { struct tty_struct * tty; + struct tty_ldisc *ld; + int ret = 0; tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll")) return 0; - - if (tty->ldisc.poll) - return (tty->ldisc.poll)(tty, filp, wait); - return 0; + + ld = tty_ldisc_ref_wait(tty); + if (ld->poll) + ret = (ld->poll)(tty, filp, wait); + tty_ldisc_deref(ld); + return ret; } static int tty_fasync(int fd, struct file * filp, int on) @@ -1518,12 +1961,15 @@ static int tty_fasync(int fd, struct file * filp, int on) static int tiocsti(struct tty_struct *tty, char __user *p) { char ch, mbz = 0; - + struct tty_ldisc *ld; + if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(ch, p)) return -EFAULT; - tty->ldisc.receive_buf(tty, &ch, &mbz, 1); + ld = tty_ldisc_ref_wait(tty); + ld->receive_buf(tty, &ch, &mbz, 1); + tty_ldisc_deref(ld); return 0; } @@ -1566,10 +2012,10 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, static int tioccons(struct file *file) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; if (file->f_op->write == redirected_tty_write) { struct file *f; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; spin_lock(&redirect_lock); f = redirect; redirect = NULL; @@ -1606,8 +2052,6 @@ static int fionbio(struct file *file, int __user *p) static int tiocsctty(struct tty_struct *tty, int arg) { - struct list_head *l; - struct pid *pid; task_t *p; if (current->signal->leader && @@ -1630,8 +2074,9 @@ static int tiocsctty(struct tty_struct *tty, int arg) */ read_lock(&tasklist_lock); - for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) + do_each_task_pid(tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; + } while_each_task_pid(tty->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); } else return -EPERM; @@ -1703,11 +2148,11 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) static int send_break(struct tty_struct *tty, int duration) { - set_current_state(TASK_INTERRUPTIBLE); - tty->driver->break_ctl(tty, -1); - if (!signal_pending(current)) + if (!signal_pending(current)) { + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(duration); + } tty->driver->break_ctl(tty, 0); if (signal_pending(current)) return -EINTR; @@ -1772,6 +2217,7 @@ int tty_ioctl(struct inode * inode, struct file * file, struct tty_struct *tty, *real_tty; void __user *p = (void __user *)arg; int retval; + struct tty_ldisc *ld; tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_ioctl")) @@ -1861,6 +2307,7 @@ int tty_ioctl(struct inode * inode, struct file * file, case TIOCGSID: return tiocgsid(tty, real_tty, p); case TIOCGETD: + /* FIXME: check this is ok */ return put_user(tty->ldisc.num, (int __user *)p); case TIOCSETD: return tiocsetd(tty, p); @@ -1899,16 +2346,19 @@ int tty_ioctl(struct inode * inode, struct file * file, return tty_tiocmset(tty, file, cmd, p); } if (tty->driver->ioctl) { - int retval = (tty->driver->ioctl)(tty, file, cmd, arg); + retval = (tty->driver->ioctl)(tty, file, cmd, arg); if (retval != -ENOIOCTLCMD) return retval; } - if (tty->ldisc.ioctl) { - int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg); - if (retval != -ENOIOCTLCMD) - return retval; + ld = tty_ldisc_ref_wait(tty); + retval = -EINVAL; + if (ld->ioctl) { + retval = ld->ioctl(tty, file, cmd, arg); + if (retval == -ENOIOCTLCMD) + retval = -EINVAL; } - return -EINVAL; + tty_ldisc_deref(ld); + return retval; } @@ -1938,21 +2388,26 @@ static void __do_SAK(void *arg) #else struct tty_struct *tty = arg; struct task_struct *p; - struct list_head *l; - struct pid *pid; int session; int i; struct file *filp; + struct tty_ldisc *disc; if (!tty) return; session = tty->session; - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + /* We don't want an ldisc switch during this */ + disc = tty_ldisc_ref(tty); + if (disc && disc->flush_buffer) + disc->flush_buffer(tty); + tty_ldisc_deref(disc); + if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); + read_lock(&tasklist_lock); - for_each_task_pid(session, PIDTYPE_SID, p, l, pid) { + do_each_task_pid(session, PIDTYPE_SID, p) { if (p->signal->tty == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): p->signal->session==tty->session\n", @@ -1979,7 +2434,7 @@ static void __do_SAK(void *arg) spin_unlock(&p->files->file_lock); } task_unlock(p); - } + } while_each_task_pid(session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); #endif } @@ -2002,24 +2457,29 @@ EXPORT_SYMBOL(do_SAK); /* * This routine is called out of the software interrupt to flush data - * from the flip buffer to the line discipline. + * from the flip buffer to the line discipline. */ + static void flush_to_ldisc(void *private_) { struct tty_struct *tty = (struct tty_struct *) private_; unsigned char *cp; char *fp; int count; - unsigned long flags; + unsigned long flags; + struct tty_ldisc *disc; + + disc = tty_ldisc_ref(tty); + if (disc == NULL) /* !TTY_LDISC */ + return; if (test_bit(TTY_DONT_FLIP, &tty->flags)) { /* * Do it after the next timer tick: */ schedule_delayed_work(&tty->flip.work, 1); - return; + goto out; } - spin_lock_irqsave(&tty->read_lock, flags); if (tty->flip.buf_num) { cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE; @@ -2038,7 +2498,31 @@ static void flush_to_ldisc(void *private_) tty->flip.count = 0; spin_unlock_irqrestore(&tty->read_lock, flags); - tty->ldisc.receive_buf(tty, cp, fp, count); + disc->receive_buf(tty, cp, fp, count); +out: + tty_ldisc_deref(disc); +} + +/* + * Call the ldisc flush directly from a driver. This function may + * return an error and need retrying by the user. + */ + +int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count) +{ + int ret = 0; + struct tty_ldisc *disc; + + disc = tty_ldisc_ref(tty); + if(test_bit(TTY_DONT_FLIP, &tty->flags)) + ret = -EAGAIN; + else if(disc == NULL) + ret = -EIO; + else + disc->receive_buf(tty, cp, fp, count); + tty_ldisc_deref(disc); + return ret; + } /* @@ -2060,9 +2544,20 @@ static int baud_table[] = { static int n_baud_table = ARRAY_SIZE(baud_table); +/** + * tty_termios_baud_rate + * @termios: termios structure + * + * Convert termios baud rate data into a speed. This should be called + * with the termios lock held if this termios is a terminal termios + * structure. May change the termios data. + */ + int tty_termios_baud_rate(struct termios *termios) { - unsigned int cbaud = termios->c_cflag & CBAUD; + unsigned int cbaud; + + cbaud = termios->c_cflag & CBAUD; if (cbaud & CBAUDEX) { cbaud &= ~CBAUDEX; @@ -2072,12 +2567,20 @@ int tty_termios_baud_rate(struct termios *termios) else cbaud += 15; } - return baud_table[cbaud]; } EXPORT_SYMBOL(tty_termios_baud_rate); +/** + * tty_get_baud_rate - get tty bit rates + * @tty: tty to query + * + * Returns the baud rate as an integer for this terminal. The + * termios lock must be held by the caller and the terminal bit + * flags may be updated. + */ + int tty_get_baud_rate(struct tty_struct *tty) { int baud = tty_termios_baud_rate(tty->termios); @@ -2096,6 +2599,17 @@ int tty_get_baud_rate(struct tty_struct *tty) EXPORT_SYMBOL(tty_get_baud_rate); +/** + * tty_flip_buffer_push - terminal + * @tty: tty to push + * + * Queue a push of the terminal flip buffers to the line discipline. This + * function must not be called from IRQ context if tty->low_latency is set. + * + * In the event of the queue being busy for flipping the work will be + * held off and retried later. + */ + void tty_flip_buffer_push(struct tty_struct *tty) { if (tty->low_latency) @@ -2113,12 +2627,13 @@ static void initialize_tty_struct(struct tty_struct *tty) { memset(tty, 0, sizeof(struct tty_struct)); tty->magic = TTY_MAGIC; - tty->ldisc = ldiscs[N_TTY]; + tty_ldisc_assign(tty, tty_ldisc_get(N_TTY)); tty->pgrp = -1; tty->flip.char_buf_ptr = tty->flip.char_buf; tty->flip.flag_buf_ptr = tty->flip.flag_buf; INIT_WORK(&tty->flip.work, flush_to_ldisc, tty); init_MUTEX(&tty->flip.pty_sem); + init_MUTEX(&tty->termios_sem); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); @@ -2134,7 +2649,7 @@ static void initialize_tty_struct(struct tty_struct *tty) */ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) { - tty->driver->write(tty, 0, &ch, 1); + tty->driver->write(tty, &ch, 1); } static struct class_simple *tty_class; @@ -2154,6 +2669,7 @@ static struct class_simple *tty_class; void tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { + char name[64]; dev_t dev = MKDEV(driver->major, driver->minor_start) + index; if (index >= driver->num) { @@ -2165,13 +2681,11 @@ void tty_register_device(struct tty_driver *driver, unsigned index, devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, "%s%d", driver->devfs_name, index + driver->name_base); - /* we don't care about the ptys */ - /* how nice to hide this behind some crappy interface.. */ - if (driver->type != TTY_DRIVER_TYPE_PTY) { - char name[64]; + if (driver->type == TTY_DRIVER_TYPE_PTY) + pty_line_name(driver, index, name); + else tty_line_name(driver, index, name); - class_simple_device_add(tty_class, dev, device, name); - } + class_simple_device_add(tty_class, dev, device, name); } /** @@ -2441,7 +2955,7 @@ static int __init tty_init(void) class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); #ifdef CONFIG_UNIX98_PTYS - cdev_init(&ptmx_cdev, &tty_fops); + cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index ae924c7cb..7145057e0 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include @@ -98,8 +98,17 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios { int canon_change; struct termios old_termios = *tty->termios; + struct tty_ldisc *ld; + + /* + * Perform the actual termios internal changes under lock. + */ + + + /* FIXME: we need to decide on some locking/ordering semantics + for the set_termios notification eventually */ + down(&tty->termios_sem); - local_irq_disable(); // FIXME: is this safe? *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; @@ -109,12 +118,13 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios tty->canon_data = 0; tty->erasing = 0; } - local_irq_enable(); // FIXME: is this safe? + + if (canon_change && !L_ICANON(tty) && tty->read_cnt) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->read_wait); - /* see if packet mode change of state */ + /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { int old_flow = ((old_termios.c_iflag & IXON) && @@ -132,17 +142,23 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios wake_up_interruptible(&tty->link->read_wait); } } - + if (tty->driver->set_termios) (*tty->driver->set_termios)(tty, &old_termios); - if (tty->ldisc.set_termios) - (*tty->ldisc.set_termios)(tty, &old_termios); + ld = tty_ldisc_ref(tty); + if (ld != NULL) { + if (ld->set_termios) + (ld->set_termios)(tty, &old_termios); + tty_ldisc_deref(ld); + } + up(&tty->termios_sem); } static int set_termios(struct tty_struct * tty, void __user *arg, int opt) { struct termios tmp_termios; + struct tty_ldisc *ld; int retval = tty_check_change(tty); if (retval) @@ -159,9 +175,14 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt) return -EFAULT; } - if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - + ld = tty_ldisc_ref(tty); + + if (ld != NULL) { + if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) + ld->flush_buffer(tty); + tty_ldisc_deref(ld); + } + if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) @@ -226,11 +247,14 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) { struct sgttyb tmp; + down(&tty->termios_sem); tmp.sg_ispeed = 0; tmp.sg_ospeed = 0; tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); + up(&tty->termios_sem); + return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -269,12 +293,16 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) retval = tty_check_change(tty); if (retval) return retval; - termios = *tty->termios; + if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) return -EFAULT; + + down(&tty->termios_sem); + termios = *tty->termios; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); + up(&tty->termios_sem); change_termios(tty, &termios); return 0; } @@ -354,7 +382,7 @@ void send_prio_char(struct tty_struct *tty, char ch) } if (was_stopped) start_tty(tty); - tty->driver->write(tty, 0, &ch, 1); + tty->driver->write(tty, &ch, 1); if (was_stopped) stop_tty(tty); } @@ -365,6 +393,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, struct tty_struct * real_tty; void __user *p = (void __user *)arg; int retval; + struct tty_ldisc *ld; if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) @@ -443,22 +472,26 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, retval = tty_check_change(tty); if (retval) return retval; + + ld = tty_ldisc_ref(tty); switch (arg) { case TCIFLUSH: - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + if (ld->flush_buffer) + ld->flush_buffer(tty); break; case TCIOFLUSH: - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + if (ld->flush_buffer) + ld->flush_buffer(tty); /* fall through */ case TCOFLUSH: if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); break; default: + tty_ldisc_deref(ld); return -EINVAL; } + tty_ldisc_deref(ld); return 0; case TIOCOUTQ: return put_user(tty->driver->chars_in_buffer ? @@ -504,9 +537,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, case TIOCSSOFTCAR: if (get_user(arg, (unsigned int __user *) arg)) return -EFAULT; + down(&tty->termios_sem); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + up(&tty->termios_sem); return 0; default: return -ENOIOCTLCMD; diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index df9d4de9b..945b36891 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -83,15 +83,6 @@ struct viocharlpevent { u8 data[VIOCHAR_MAX_DATA]; }; -/* - * This is a place where we handle the distribution of memory - * for copy_from_user() calls. The buffer_available array is to - * help us determine which buffer to use. - */ -#define VIOCHAR_NUM_CFU_BUFFERS 7 -static struct viocharlpevent viocons_cfu_buffer[VIOCHAR_NUM_CFU_BUFFERS]; -static atomic_t viocons_cfu_buffer_available[VIOCHAR_NUM_CFU_BUFFERS]; - #define VIOCHAR_WINDOW 10 #define VIOCHAR_HIGHWATERMARK 3 @@ -206,50 +197,6 @@ static inline int viotty_paranoia_check(struct port_info *pi, return 0; } -/* - * This function should ONLY be called once from viocons_init2 - */ -static void viocons_init_cfu_buffer(void) -{ - int i; - - for (i = 1; i < VIOCHAR_NUM_CFU_BUFFERS; i++) - atomic_set(&viocons_cfu_buffer_available[i], 1); -} - -static struct viocharlpevent *viocons_get_cfu_buffer(void) -{ - int i; - - /* - * Grab the first available buffer. It doesn't matter if we - * are interrupted during this array traversal as long as we - * get an available space. - */ - for (i = 0; i < VIOCHAR_NUM_CFU_BUFFERS; i++) - if (atomic_dec_if_positive(&viocons_cfu_buffer_available[i]) - == 0 ) - return &viocons_cfu_buffer[i]; - hvlog("\n\rviocons: viocons_get_cfu_buffer : no free buffers found"); - return NULL; -} - -static void viocons_free_cfu_buffer(struct viocharlpevent *buffer) -{ - int i; - - i = buffer - &viocons_cfu_buffer[0]; - if (i >= (sizeof(viocons_cfu_buffer) / sizeof(viocons_cfu_buffer[0]))) { - hvlog("\n\rviocons: viocons_free_cfu_buffer : buffer pointer not found in list."); - return; - } - if (atomic_read(&viocons_cfu_buffer_available[i]) != 0) { - hvlog("\n\rviocons: WARNING : returning unallocated cfu buffer."); - return; - } - atomic_set(&viocons_cfu_buffer_available[i], 1); -} - /* * Add data to our pending-send buffers. * @@ -422,10 +369,7 @@ static void send_buffers(struct port_info *pi) pi->overflowMessage = 0; if (pi->tty) { - if ((pi->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - (pi->tty->ldisc.write_wakeup)) - (pi->tty->ldisc.write_wakeup)(pi->tty); - wake_up_interruptible(&pi->tty->write_wait); + tty_wakeup(pi->tty); } } @@ -441,15 +385,14 @@ static void send_buffers(struct port_info *pi) * NOTE: Don't use printk in here because it gets nastily recursive. hvlog * can be used to log to the hypervisor buffer */ -static int internal_write(struct port_info *pi, const char *buf, - size_t len, struct viocharlpevent *viochar) +static int internal_write(struct port_info *pi, const char *buf, size_t len) { HvLpEvent_Rc hvrc; size_t bleft; size_t curlen; const char *curbuf; unsigned long flags; - int copy_needed = (viochar == NULL); + struct viocharlpevent *viochar; /* * Write to the hvlog of inbound data are now done prior to @@ -465,25 +408,13 @@ static int internal_write(struct port_info *pi, const char *buf, spin_lock_irqsave(&consolelock, flags); - /* - * If the internal_write() was passed a pointer to a - * viocharlpevent then we don't need to allocate a new one - * (this is the case where we are internal_writing user space - * data). If we aren't writing user space data then we need - * to get an event from viopath. - */ - if (copy_needed) { - /* This one is fetched from the viopath data structure */ - viochar = (struct viocharlpevent *) - vio_get_event_buffer(viomajorsubtype_chario); - /* Make sure we got a buffer */ - if (viochar == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - hvlog("\n\rviocons: Can't get viochar buffer in internal_write()."); - return -EAGAIN; - } - initDataEvent(viochar, pi->lp); + viochar = vio_get_event_buffer(viomajorsubtype_chario); + if (viochar == NULL) { + spin_unlock_irqrestore(&consolelock, flags); + hvlog("\n\rviocons: Can't get vio buffer in internal_write()."); + return -EAGAIN; } + initDataEvent(viochar, pi->lp); curbuf = buf; bleft = len; @@ -496,25 +427,16 @@ static int internal_write(struct port_info *pi, const char *buf, curlen = bleft; viochar->event.xCorrelationToken = pi->seq++; - - if (copy_needed) { - memcpy(viochar->data, curbuf, curlen); - viochar->len = curlen; - } - + memcpy(viochar->data, curbuf, curlen); + viochar->len = curlen; viochar->event.xSizeMinus1 = offsetof(struct viocharlpevent, data) + curlen; hvrc = HvCallEvent_signalLpEvent(&viochar->event); if (hvrc) { - spin_unlock_irqrestore(&consolelock, flags); - if (copy_needed) - vio_free_event_buffer(viomajorsubtype_chario, viochar); - hvlog("viocons: error sending event! %d\n", (int)hvrc); - return len - bleft; + goto out; } - curbuf += curlen; bleft -= curlen; } @@ -522,14 +444,9 @@ static int internal_write(struct port_info *pi, const char *buf, /* If we didn't send it all, buffer as much of it as we can. */ if (bleft > 0) bleft -= buffer_add(pi, curbuf, bleft); - /* - * Since we grabbed it from the viopath data structure, return - * it to the data structure. - */ - if (copy_needed) - vio_free_event_buffer(viomajorsubtype_chario, viochar); +out: + vio_free_event_buffer(viomajorsubtype_chario, viochar); spin_unlock_irqrestore(&consolelock, flags); - return len - bleft; } @@ -606,18 +523,8 @@ static void viocons_write(struct console *co, const char *s, unsigned count) hvlogOutput(s, count); - if (!viopath_isactive(pi->lp)) { - /* - * This is a VERY noisy trace message in the case where the - * path manager is not active or in the case where this - * function is called prior to viocons initialization. It is - * being commented out for the sake of a clear trace buffer. - */ -#if 0 - hvlog("\n\rviocons_write: path not active to lp %d", pi->lp); -#endif + if (!viopath_isactive(pi->lp)) return; - } /* * Any newline character found will cause a @@ -630,17 +537,16 @@ static void viocons_write(struct console *co, const char *s, unsigned count) * Newline found. Print everything up to and * including the newline */ - internal_write(pi, &s[begin], index - begin + 1, - NULL); + internal_write(pi, &s[begin], index - begin + 1); begin = index + 1; /* Emit a carriage return as well */ - internal_write(pi, &cr, 1, NULL); + internal_write(pi, &cr, 1); } } /* If any characters left to write, write them now */ if ((index - begin) > 0) - internal_write(pi, &s[begin], index - begin, NULL); + internal_write(pi, &s[begin], index - begin); } /* @@ -724,11 +630,9 @@ static void viotty_close(struct tty_struct *tty, struct file *filp) /* * TTY Write method */ -static int viotty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int viotty_write(struct tty_struct *tty, const unsigned char *buf, + int count) { - int ret; - int total = 0; struct port_info *pi; pi = get_port_data(tty); @@ -749,53 +653,10 @@ static int viotty_write(struct tty_struct *tty, int from_user, * viotty_write call and, since the viopath isn't active to this * partition, return count. */ - if (!viopath_isactive(pi->lp)) { - /* Noisy trace. Commented unless needed. */ -#if 0 - hvlog("\n\rviotty_write: viopath NOT active for lp %d.",pi->lp); -#endif + if (!viopath_isactive(pi->lp)) return count; - } - /* - * If the viotty_write is invoked from user space we want to do the - * copy_from_user() into an event buffer from the cfu buffer before - * internal_write() is called because internal_write may need to buffer - * data which will need to grab a spin_lock and we shouldn't - * copy_from_user() while holding a spin_lock. Should internal_write() - * not need to buffer data then it'll just use the event we created here - * rather than checking one out from vio_get_event_buffer(). - */ - if (from_user) { - struct viocharlpevent *viochar; - int curlen; - const char *curbuf = buf; - - viochar = viocons_get_cfu_buffer(); - if (viochar == NULL) - return -EAGAIN; - initDataEvent(viochar, pi->lp); - while (count > 0) { - if (count > VIOCHAR_MAX_DATA) - curlen = VIOCHAR_MAX_DATA; - else - curlen = count; - viochar->len = curlen; - ret = copy_from_user(viochar->data, curbuf, curlen); - if (ret) - break; - ret = internal_write(pi, viochar->data, - viochar->len, viochar); - total += ret; - if (ret != curlen) - break; - count -= curlen; - curbuf += curlen; - } - viocons_free_cfu_buffer(viochar); - } else - total = internal_write(pi, buf, count, NULL); - return total; + return internal_write(pi, buf, count); } /* @@ -814,7 +675,7 @@ static void viotty_put_char(struct tty_struct *tty, unsigned char ch) hvlogOutput(&ch, 1); if (viopath_isactive(pi->lp)) - internal_write(pi, &ch, 1, NULL); + internal_write(pi, &ch, 1); } /* @@ -923,7 +784,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event) atomic_set(aptr, 1); } else printk(VIOCONS_KERN_WARN - "wierd...got open ack without atomic\n"); + "weird...got open ack without atomic\n"); return; } @@ -1310,8 +1171,6 @@ static int __init viocons_init2(void) viotty_driver = NULL; } - viocons_init_cfu_buffer(); - unregister_console(&viocons_early); register_console(&viocons); diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 34a48d2f2..aea3cbf52 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -938,7 +938,7 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) } break; default: - printk(VIOTAPE_KERN_WARN "wierd ack\n"); + printk(VIOTAPE_KERN_WARN "weird ack\n"); } } diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 6f7833417..19ba83635 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -544,12 +544,8 @@ static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp) SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ port->gs.flags &= ~GS_TX_INTEN; } - if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - port->gs.tty->ldisc.write_wakeup) - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); - wake_up_interruptible(&port->gs.tty->write_wait); - } + if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) + tty_wakeup(port->gs.tty); SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); return IRQ_HANDLED; diff --git a/drivers/char/vt.c b/drivers/char/vt.c index a204572f5..8de27feaa 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -101,11 +101,11 @@ #include #include #include +#include #include #include #include -#include #include "console_macros.h" @@ -136,9 +136,6 @@ extern void prom_con_init(void); #ifdef CONFIG_MDA_CONSOLE extern int mda_console_init(void); #endif -#ifdef CONFIG_FRAMEBUFFER_CONSOLE -extern int fb_console_init(void); -#endif struct vc vc_cons [MAX_NR_CONSOLES]; @@ -600,6 +597,17 @@ static inline void save_screen(int currcons) * Redrawing of screen */ +static void clear_buffer_attributes(int currcons) +{ + unsigned short *p = (unsigned short *) origin; + int count = screenbuf_size/2; + int mask = hi_font_mask | 0xff; + + for (; count > 0; count--, p++) { + scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p); + } +} + void redraw_screen(int new_console, int is_switch) { int redraw = 1; @@ -637,9 +645,21 @@ void redraw_screen(int new_console, int is_switch) if (redraw) { int update; + int old_was_color = vc_cons[currcons].d->vc_can_do_color; + set_origin(currcons); update = sw->con_switch(vc_cons[currcons].d); set_palette(currcons); + /* + * If console changed from mono<->color, the best we can do + * is to clear the buffer attributes. As it currently stands, + * rebuilding new attributes from the old buffer is not doable + * without overly complex code. + */ + if (old_was_color != vc_cons[currcons].d->vc_can_do_color) { + update_attr(currcons); + clear_buffer_attributes(currcons); + } if (update && vcmode != KD_GRAPHICS) do_update_region(currcons, origin, screenbuf_size/2); } @@ -748,6 +768,8 @@ inline int resize_screen(int currcons, int width, int height) * [this is to be used together with some user program * like resize that changes the hardware videomode] */ +#define VC_RESIZE_MAXCOL (32767) +#define VC_RESIZE_MAXROW (32767) int vc_resize(int currcons, unsigned int cols, unsigned int lines) { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; @@ -760,6 +782,9 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) if (!vc_cons_allocated(currcons)) return -ENXIO; + if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW) + return -EINVAL; + new_cols = (cols ? cols : video_num_columns); new_rows = (lines ? lines : video_num_lines); new_row_size = new_cols << 1; @@ -1865,12 +1890,11 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) * since console_init (and thus con_init) are called before any * kernel memory allocation is available. */ -char con_buf[PAGE_SIZE]; +char con_buf[CON_BUF_SIZE]; DECLARE_MUTEX(con_buf_sem); /* acquires console_sem */ -static int do_con_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { #ifdef VT_BUF_VRAM_ONLY #define FLUSH do { } while(0); @@ -1918,22 +1942,6 @@ static int do_con_write(struct tty_struct *tty, int from_user, orig_buf = buf; orig_count = count; - if (from_user) { - - down(&con_buf_sem); - -again: - if (count > CON_BUF_SIZE) - count = CON_BUF_SIZE; - console_conditional_schedule(); - if (copy_from_user(con_buf, buf, count)) { - n = 0; /* ?? are error codes legal here ?? */ - goto out; - } - - buf = con_buf; - } - /* At this point 'buf' is guaranteed to be a kernel buffer * and therefore no access to userspace (and therefore sleeping) * will be needed. The con_buf_sem serializes all tty based @@ -1958,12 +1966,16 @@ again: hide_cursor(currcons); while (!tty->stopped && count) { - c = *buf; + int orig = *buf; + c = orig; buf++; n++; count--; - if (utf) { + /* Do no translation at all in control states */ + if (vc_state != ESnormal) { + tc = c; + } else if (utf) { /* Combine UTF-8 into Unicode */ /* Incomplete characters silently ignored */ if(c > 0x7f) { @@ -2063,29 +2075,13 @@ again: continue; } FLUSH - do_con_trol(tty, currcons, c); + do_con_trol(tty, currcons, orig); } FLUSH console_conditional_schedule(); release_console_sem(); out: - if (from_user) { - /* If the user requested something larger than - * the CON_BUF_SIZE, and the tty is not stopped, - * keep going. - */ - if ((orig_count > CON_BUF_SIZE) && !tty->stopped) { - orig_count -= CON_BUF_SIZE; - orig_buf += CON_BUF_SIZE; - count = orig_count; - buf = orig_buf; - goto again; - } - - up(&con_buf_sem); - } - return n; #undef FLUSH } @@ -2162,8 +2158,6 @@ void vt_console_print(struct console *co, const char *b, unsigned count) if (!printable || test_and_set_bit(0, &printing)) return; - pm_access(pm_con); - if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; @@ -2358,13 +2352,11 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) * /dev/ttyN handling */ -static int con_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int con_write(struct tty_struct *tty, const unsigned char *buf, int count) { int retval; - pm_access(pm_con); - retval = do_con_write(tty, from_user, buf, count); + retval = do_con_write(tty, buf, count); con_flush_chars(tty); return retval; @@ -2374,8 +2366,7 @@ static void con_put_char(struct tty_struct *tty, unsigned char ch) { if (in_interrupt()) return; /* n_r3964 calls put_char() from interrupt context */ - pm_access(pm_con); - do_con_write(tty, 0, &ch, 1); + do_con_write(tty, &ch, 1); } static int con_write_room(struct tty_struct *tty) @@ -2443,8 +2434,6 @@ static void con_flush_chars(struct tty_struct *tty) if (in_interrupt()) /* from flush_to_ldisc */ return; - pm_access(pm_con); - /* if we race with con_close(), vt may be null */ acquire_console_sem(); vt = tty->driver_data; @@ -2645,25 +2634,11 @@ int __init vty_init(void) #ifdef CONFIG_MDA_CONSOLE mda_console_init(); #endif -#ifdef CONFIG_FRAMEBUFFER_CONSOLE - fb_console_init(); -#endif return 0; } #ifndef VT_SINGLE_DRIVER -static void clear_buffer_attributes(int currcons) -{ - unsigned short *p = (unsigned short *) origin; - int count = screenbuf_size/2; - int mask = hi_font_mask | 0xff; - - for (; count > 0; count--, p++) { - scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p); - } -} - /* * If we support more console drivers, this function is used * when a driver wants to take over some existing consoles @@ -3067,6 +3042,10 @@ int con_font_get(int currcons, struct console_font_op *op) if (rc) goto out; + op->height = font.height; + op->width = font.width; + op->charcount = font.charcount; + if (op->data && copy_to_user(op->data, font.data, c)) rc = -EFAULT; @@ -3275,7 +3254,6 @@ EXPORT_SYMBOL(color_table); EXPORT_SYMBOL(default_red); EXPORT_SYMBOL(default_grn); EXPORT_SYMBOL(default_blu); -EXPORT_SYMBOL(vc_cons_allocated); EXPORT_SYMBOL(update_region); EXPORT_SYMBOL(redraw_screen); EXPORT_SYMBOL(vc_resize); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 682b44e9d..dd8e2f781 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -536,8 +536,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, default: return -EINVAL; } - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); return 0; case KDGKBMODE: diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index a9dec9e98..812b50e32 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -106,6 +106,22 @@ config IXP2000_WATCHDOG Say N if you are unsure. +config S3C2410_WATCHDOG + tristate "S3C2410 Watchdog" + depends on WATCHDOG && ARCH_S3C2410 + help + Watchdog timer block in the Samsung S3C2410 chips. This will + reboot the system when the timer expires with the watchdog + enabled. + + The driver is limited by the speed of the system's PCLK + signal, so with reasonbaly fast systems (PCLK around 50-66MHz) + then watchdog intervals of over approximately 20seconds are + unavailable. + + The driver can be built as a module by choosing M, and will + be called s3c2410_wdt + config SA1100_WATCHDOG tristate "SA1100/PXA2xx watchdog" depends on WATCHDOG && ( ARCH_SA1100 || ARCH_PXA ) @@ -319,6 +335,12 @@ config MACHZ_WDT To compile this driver as a module, choose M here: the module will be called machzwd. +# PowerPC Architecture + +config 8xx_WDT + tristate "MPC8xx Watchdog Timer" + depends on WATCHDOG && 8xx + # MIPS Architecture config INDYDOG @@ -330,6 +352,20 @@ config INDYDOG timer expired and no process has written to /dev/watchdog during that time. +# S390 Architecture + +config ZVM_WATCHDOG + tristate "z/VM Watchdog Timer" + depends on WATCHDOG && ARCH_S390 + help + IBM s/390 and zSeries machines running under z/VM 5.1 or later + provide a virtual watchdog timer to their guest that cause a + user define Control Program command to be executed after a + timeout. + + To compile this driver as a module, choose M here. The module + will be called vmwatchdog. + # SUPERH Architecture config SH_WDT diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index c5f99d332..41e2f9482 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_977_WATCHDOG) += wdt977.o obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SH_WDT) += shwdt.o +obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o @@ -37,3 +38,4 @@ obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o +obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c index 7e7b653a2..2865dac0a 100644 --- a/drivers/char/watchdog/cpu5wdt.c +++ b/drivers/char/watchdog/cpu5wdt.c @@ -134,7 +134,7 @@ static int cpu5wdt_open(struct inode *inode, struct file *file) if ( test_and_set_bit(0, &cpu5wdt_device.inuse) ) return -EBUSY; - return 0; + return nonseekable_open(inode, file); } static int cpu5wdt_release(struct inode *inode, struct file *file) @@ -198,6 +198,7 @@ static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t c static struct file_operations cpu5wdt_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .ioctl = cpu5wdt_ioctl, .open = cpu5wdt_open, .write = cpu5wdt_write, diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index 5fc054700..76bf422c3 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c @@ -415,12 +415,15 @@ static unsigned char __init i8xx_tco_getdevice (void) } } /* Set the TCO_EN bit in SMI_EN register */ + if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + SMI_EN + 1); + return 0; + } val1 = inb (SMI_EN + 1); val1 &= 0xdf; outb (val1, SMI_EN + 1); - /* Clear out the (probably old) status */ - outb (0, TCO1_STS); - outb (3, TCO2_STS); + release_region (SMI_EN + 1, 1); return 1; } return 0; @@ -443,6 +446,10 @@ static int __init watchdog_init (void) goto out; } + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + outb (3, TCO2_STS); + /* Check that the heartbeat value is within it's range ; if not reset to the default */ if (tco_timer_set_heartbeat (heartbeat)) { heartbeat = WATCHDOG_HEARTBEAT; @@ -465,7 +472,7 @@ static int __init watchdog_init (void) goto unreg_notifier; } - tco_timer_keepalive (); + tco_timer_stop (); printk (KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n", TCOBASE, heartbeat, nowayout); diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c index cd6467eb4..d974f16e8 100644 --- a/drivers/char/watchdog/ib700wdt.c +++ b/drivers/char/watchdog/ib700wdt.c @@ -263,6 +263,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code, static struct file_operations ibwdt_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = ibwdt_write, .ioctl = ibwdt_ioctl, .open = ibwdt_open, diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c index 4e9093b4a..6af2c799b 100644 --- a/drivers/char/watchdog/indydog.c +++ b/drivers/char/watchdog/indydog.c @@ -162,6 +162,7 @@ static int indydog_notify_sys(struct notifier_block *this, unsigned long code, v static struct file_operations indydog_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = indydog_write, .ioctl = indydog_ioctl, .open = indydog_open, diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index ebcaf79ce..ab659d37b 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c @@ -25,9 +25,9 @@ #include #include #include +#include #include -#include #include #ifdef CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c index b8e3d91d3..82396e06c 100644 --- a/drivers/char/watchdog/ixp4xx_wdt.c +++ b/drivers/char/watchdog/ixp4xx_wdt.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #ifdef CONFIG_WATCHDOG_NOWAYOUT @@ -170,6 +170,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file) static struct file_operations ixp4xx_wdt_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = ixp4xx_wdt_write, .ioctl = ixp4xx_wdt_ioctl, .open = ixp4xx_wdt_open, @@ -215,7 +216,7 @@ static void __exit ixp4xx_wdt_exit(void) module_init(ixp4xx_wdt_init); module_exit(ixp4xx_wdt_exit); -MODULE_AUTHOR("Deepak Saxena ); +MODULE_AUTHOR("Deepak Saxena "); MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog"); module_param(heartbeat, int, 0); diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c index 3782930e6..6e14abbb4 100644 --- a/drivers/char/watchdog/machzwd.c +++ b/drivers/char/watchdog/machzwd.c @@ -425,6 +425,7 @@ static int zf_notify_sys(struct notifier_block *this, unsigned long code, static struct file_operations zf_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = zf_write, .ioctl = zf_ioctl, .open = zf_open, diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index 15a3547f2..3143e4a07 100644 --- a/drivers/char/watchdog/mixcomwd.c +++ b/drivers/char/watchdog/mixcomwd.c @@ -197,6 +197,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, static struct file_operations mixcomwd_fops= { .owner = THIS_MODULE, + .llseek = no_llseek, .write = mixcomwd_write, .ioctl = mixcomwd_ioctl, .open = mixcomwd_open, diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 88bdbda92..592dca108 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -859,8 +859,7 @@ static int __init pcwd_checkcard(int base_addr) /* Not an 'ff' from a floating bus, so must be a card! */ for (i = 0; i < 4; ++i) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 2); + msleep(500); last_port0 = port0; last_port1 = port1; diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 1adf09f83..394ee7ac7 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -27,6 +27,10 @@ #include #include +#ifdef CONFIG_ARCH_PXA +#include +#endif + #include #include #include @@ -162,6 +166,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, static struct file_operations sa1100dog_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = sa1100dog_write, .ioctl = sa1100dog_ioctl, .open = sa1100dog_open, diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 9ddebaebe..d17d485fb 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -301,6 +301,7 @@ static struct notifier_block sc1200wdt_notifier = static struct file_operations sc1200wdt_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = sc1200wdt_write, .ioctl = sc1200wdt_ioctl, .open = sc1200wdt_open, diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c index 8b68721f9..f6d143e19 100644 --- a/drivers/char/watchdog/sc520_wdt.c +++ b/drivers/char/watchdog/sc520_wdt.c @@ -122,7 +122,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON #define WDT_WRST_ENB 0x4000 /* [14] Watchdog Timer Reset Enable */ #define WDT_ENB 0x8000 /* [15] Watchdog Timer Enable */ -static __u16 *wdtmrctl; +static __u16 __iomem *wdtmrctl; static void wdt_timer_ping(unsigned long); static struct timer_list timer; diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index ed1800cff..0c47a4306 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c @@ -201,6 +201,7 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file, static struct file_operations scx200_wdt_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = scx200_wdt_write, .ioctl = scx200_wdt_ioctl, .open = scx200_wdt_open, @@ -216,6 +217,11 @@ static struct miscdevice scx200_wdt_miscdev = { static int __init scx200_wdt_init(void) { int r; + static struct pci_device_id ns_sc[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, + { }, + }; printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n"); @@ -223,12 +229,7 @@ static int __init scx200_wdt_init(void) * First check that this really is a NatSemi SCx200 CPU or a Geode * SC1100 processor */ - if ((pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SCx200_BRIDGE, - NULL)) == NULL - && (pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SC1100_BRIDGE, - NULL)) == NULL) + if (!pci_dev_present(ns_sc)) return -ENODEV; /* More sanity checks, verify that the configuration block is there */ diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c index d3fced33d..52825a1f1 100644 --- a/drivers/char/watchdog/wdt285.c +++ b/drivers/char/watchdog/wdt285.c @@ -180,6 +180,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, static struct file_operations watchdog_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, .write = watchdog_write, .ioctl = watchdog_ioctl, .open = watchdog_open, diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c index 388c548c2..072e9b214 100644 --- a/drivers/char/watchdog/wdt977.c +++ b/drivers/char/watchdog/wdt977.c @@ -392,6 +392,7 @@ static int wdt977_notify_sys(struct notifier_block *this, unsigned long code, static struct file_operations wdt977_fops= { .owner = THIS_MODULE, + .llseek = no_llseek, .write = wdt977_write, .ioctl = wdt977_ioctl, .open = wdt977_open, diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c index 9d5b5f4e5..7651deda9 100644 --- a/drivers/char/watchdog/wdt_pci.c +++ b/drivers/char/watchdog/wdt_pci.c @@ -674,8 +674,8 @@ out: out_misc: #ifdef CONFIG_WDT_501_PCI misc_deregister(&temp_miscdev); -#endif /* CONFIG_WDT_501_PCI */ out_rbt: +#endif /* CONFIG_WDT_501_PCI */ unregister_reboot_notifier(&wdtpci_notifier); out_irq: free_irq(irq, &wdtpci_miscdev); diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 331b5156d..aa8eaca6e 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -1,3 +1,32 @@ +config CPU_FREQ + bool "CPU Frequency scaling" + help + CPU Frequency scaling allows you to change the clock speed of + CPUs on the fly. This is a nice method to save power, because + the lower the CPU clock speed, the less power the CPU consumes. + + Note that this driver doesn't automatically change the CPU + clock speed, you need to either enable a dynamic cpufreq governor + (see below) after boot, or use a userspace tool. + + For details, take a look at . + + If in doubt, say N. + +config CPU_FREQ_DEBUG + bool "Enable CPUfreq debugging" + depends on CPU_FREQ + help + Say Y here to enable CPUfreq subsystem (including drivers) + debugging. You will need to activate it via the kernel + command line by passing + cpufreq.debug= + + To get , add + 1 to activate CPUfreq core debugging, + 2 to activate CPUfreq drivers debugging, and + 4 to activate CPUfreq governor debugging + config CPU_FREQ_PROC_INTF tristate "/proc/cpufreq interface (deprecated)" depends on CPU_FREQ && PROC_FS @@ -33,7 +62,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE help Use the CPUFreq governor 'userspace' as default. This allows you to set the CPU frequency manually or when an userspace - programm shall be able to set the CPU dynamically without having + program shall be able to set the CPU dynamically without having to enable the userspace governor manually. endchoice @@ -42,7 +71,7 @@ config CPU_FREQ_GOV_PERFORMANCE tristate "'performance' governor" depends on CPU_FREQ help - This cpufreq governors set the frequency statically to the + This cpufreq governor sets the frequency statically to the highest available CPU frequency. If in doubt, say Y. @@ -51,7 +80,7 @@ config CPU_FREQ_GOV_POWERSAVE tristate "'powersave' governor" depends on CPU_FREQ help - Theis cpufreq governors set the frequency statically to the + This cpufreq governor sets the frequency statically to the lowest available CPU frequency. If in doubt, say Y. @@ -61,8 +90,8 @@ config CPU_FREQ_GOV_USERSPACE depends on CPU_FREQ help Enable this cpufreq governor when you either want to set the - CPU frequency manually or when an userspace programm shall - be able to set the CPU dynamically, like on LART + CPU frequency manually or when an userspace program shall + be able to set the CPU dynamically, like on LART For details, take a look at . @@ -71,7 +100,8 @@ config CPU_FREQ_GOV_USERSPACE config CPU_FREQ_24_API bool "/proc/sys/cpu/ interface (2.4. / OLD)" - depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE + depends on CPU_FREQ_GOV_USERSPACE + depends on SYSCTL help This enables the /proc/sys/cpu/ sysctl interface for controlling the CPUFreq,"userspace" governor. This is the same interface @@ -82,3 +112,18 @@ config CPU_FREQ_24_API For details, take a look at . If in doubt, say N. + +config CPU_FREQ_GOV_ONDEMAND + tristate "'ondemand' cpufreq policy governor" + depends on CPU_FREQ + help + 'ondemand' - This driver adds a dynamic cpufreq policy governor. + The governor does a periodic polling and + changes frequency based on the CPU utilization. + The support for this governor depends on CPU capability to + do fast frequency switching (i.e, very low latency frequency + transitions). + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 1eebf3c6e..50291abb4 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o +obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a7fa79f5b..c2de232af 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -24,6 +24,8 @@ #include #include +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) + /** * The "cpufreq driver" - the arch- or hardware-dependend low * level driver of CPUFreq support, and its spinlock. This lock @@ -33,6 +35,14 @@ static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED; + +/* we keep a copy of all ->add'ed CPU's struct sys_device here; + * as it is only accessed in ->add and ->remove, no lock or reference + * count is necessary. + */ +static struct sys_device *cpu_sys_devices[NR_CPUS]; + + /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); @@ -99,6 +109,175 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data) module_put(cpufreq_driver->owner); } + +/********************************************************************* + * UNIFIED DEBUG HELPERS * + *********************************************************************/ +#ifdef CONFIG_CPU_FREQ_DEBUG + +/* what part(s) of the CPUfreq subsystem are debugged? */ +static unsigned int debug; + +/* is the debug output ratelimit'ed using printk_ratelimit? User can + * set or modify this value. + */ +static unsigned int debug_ratelimit = 1; + +/* is the printk_ratelimit'ing enabled? It's enabled after a successful + * loading of a cpufreq driver, temporarily disabled when a new policy + * is set, and disabled upon cpufreq driver removal + */ +static unsigned int disable_ratelimit = 1; +static spinlock_t disable_ratelimit_lock = SPIN_LOCK_UNLOCKED; + +static inline void cpufreq_debug_enable_ratelimit(void) +{ + unsigned long flags; + + spin_lock_irqsave(&disable_ratelimit_lock, flags); + if (disable_ratelimit) + disable_ratelimit--; + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); +} + +static inline void cpufreq_debug_disable_ratelimit(void) +{ + unsigned long flags; + + spin_lock_irqsave(&disable_ratelimit_lock, flags); + disable_ratelimit++; + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); +} + +void cpufreq_debug_printk(unsigned int type, const char *prefix, const char *fmt, ...) +{ + char s[256]; + va_list args; + unsigned int len; + unsigned long flags; + + WARN_ON(!prefix); + if (type & debug) { + spin_lock_irqsave(&disable_ratelimit_lock, flags); + if (!disable_ratelimit && debug_ratelimit && !printk_ratelimit()) { + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); + return; + } + spin_unlock_irqrestore(&disable_ratelimit_lock, flags); + + len = snprintf(s, 256, KERN_DEBUG "%s: ", prefix); + + va_start(args, fmt); + len += vsnprintf(&s[len], (256 - len), fmt, args); + va_end(args); + + printk(s); + + WARN_ON(len < 5); + } +} +EXPORT_SYMBOL(cpufreq_debug_printk); + + +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "CPUfreq debugging: add 1 to debug core, 2 to debug drivers, and 4 to debug governors."); + +module_param(debug_ratelimit, uint, 0644); +MODULE_PARM_DESC(debug_ratelimit, "CPUfreq debugging: set to 0 to disable ratelimiting."); + +#else /* !CONFIG_CPU_FREQ_DEBUG */ + +static inline void cpufreq_debug_enable_ratelimit(void) { return; } +static inline void cpufreq_debug_disable_ratelimit(void) { return; } + +#endif /* CONFIG_CPU_FREQ_DEBUG */ + + +/********************************************************************* + * EXTERNALLY AFFECTING FREQUENCY CHANGES * + *********************************************************************/ + +/** + * adjust_jiffies - adjust the system "loops_per_jiffy" + * + * This function alters the system "loops_per_jiffy" for the clock + * speed change. Note that loops_per_jiffy cannot be updated on SMP + * systems as each CPU might be scaled differently. So, use the arch + * per-CPU loops_per_jiffy value wherever possible. + */ +#ifndef CONFIG_SMP +static unsigned long l_p_j_ref; +static unsigned int l_p_j_ref_freq; + +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +{ + if (ci->flags & CPUFREQ_CONST_LOOPS) + return; + + if (!l_p_j_ref_freq) { + l_p_j_ref = loops_per_jiffy; + l_p_j_ref_freq = ci->old; + dprintk("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); + } + if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || + (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || + (val == CPUFREQ_RESUMECHANGE)) { + loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); + dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new); + } +} +#else +static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; } +#endif + + +/** + * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition + * + * This function calls the transition notifiers and the "adjust_jiffies" function. It is called + * twice on all CPU frequency changes that have external effects. + */ +void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) +{ + BUG_ON(irqs_disabled()); + + freqs->flags = cpufreq_driver->flags; + dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); + + down_read(&cpufreq_notifier_rwsem); + switch (state) { + case CPUFREQ_PRECHANGE: + /* detect if the driver reported a value as "old frequency" which + * is not equal to what the cpufreq core thinks is "old frequency". + */ + if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { + if ((likely(cpufreq_cpu_data[freqs->cpu])) && + (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && + (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && + (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) + { + printk(KERN_WARNING "Warning: CPU frequency is %u, " + "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); + freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; + } + } + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); + adjust_jiffies(CPUFREQ_PRECHANGE, freqs); + break; + case CPUFREQ_POSTCHANGE: + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); + if ((likely(cpufreq_cpu_data[freqs->cpu])) && + (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) + cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; + break; + } + up_read(&cpufreq_notifier_rwsem); +} +EXPORT_SYMBOL_GPL(cpufreq_notify_transition); + + + /********************************************************************* * SYSFS INTERFACE * *********************************************************************/ @@ -274,26 +453,37 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, i += sprintf(&buf[i], "\n"); return i; } +/** + * show_affected_cpus - show the CPUs affected by each transition + */ +static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf) +{ + ssize_t i = 0; + unsigned int cpu; + + for_each_cpu_mask(cpu, policy->cpus) { + if (i) + i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " "); + i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu); + if (i >= (PAGE_SIZE - 5)) + break; + } + i += sprintf(&buf[i], "\n"); + return i; +} #define define_one_ro(_name) \ -struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = show_##_name, \ -} +static struct freq_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) #define define_one_ro0400(_name) \ -struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0400 }, \ - .show = show_##_name, \ -} +static struct freq_attr _name = \ +__ATTR(_name, 0400, show_##_name, NULL) #define define_one_rw(_name) \ -struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0644 }, \ - .show = show_##_name, \ - .store = store_##_name, \ -} +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) define_one_ro0400(cpuinfo_cur_freq); define_one_ro(cpuinfo_min_freq); @@ -301,6 +491,7 @@ define_one_ro(cpuinfo_max_freq); define_one_ro(scaling_available_governors); define_one_ro(scaling_driver); define_one_ro(scaling_cur_freq); +define_one_ro(affected_cpus); define_one_rw(scaling_min_freq); define_one_rw(scaling_max_freq); define_one_rw(scaling_governor); @@ -310,6 +501,7 @@ static struct attribute * default_attrs[] = { &cpuinfo_max_freq.attr, &scaling_min_freq.attr, &scaling_max_freq.attr, + &affected_cpus.attr, &scaling_governor.attr, &scaling_driver.attr, &scaling_available_governors.attr, @@ -349,6 +541,7 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr, static void cpufreq_sysfs_release(struct kobject * kobj) { struct cpufreq_policy * policy = to_policy(kobj); + dprintk("last reference is dropped\n"); complete(&policy->kobj_unregister); } @@ -377,9 +570,28 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) struct cpufreq_policy *policy; struct freq_attr **drv_attr; unsigned long flags; + unsigned int j; + + cpufreq_debug_disable_ratelimit(); + dprintk("adding CPU %u\n", cpu); + +#ifdef CONFIG_SMP + /* check whether a different CPU already registered this + * CPU because it is in the same boat. */ + policy = cpufreq_cpu_get(cpu); + if (unlikely(policy)) { + cpu_sys_devices[cpu] = sys_dev; + dprintk("CPU already managed, adding link\n"); + sysfs_create_link(&sys_dev->kobj, &policy->kobj, "cpufreq"); + cpufreq_debug_enable_ratelimit(); + return 0; + } +#endif - if (!try_module_get(cpufreq_driver->owner)) - return -EINVAL; + if (!try_module_get(cpufreq_driver->owner)) { + ret = -EINVAL; + goto module_out; + } policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) { @@ -389,6 +601,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) memset(policy, 0, sizeof(struct cpufreq_policy)); policy->cpu = cpu; + policy->cpus = cpumask_of_cpu(cpu); + init_MUTEX_LOCKED(&policy->lock); init_completion(&policy->kobj_unregister); INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); @@ -397,8 +611,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) * to accept all calls to ->verify and ->setpolicy for this CPU */ ret = cpufreq_driver->init(policy); - if (ret) + if (ret) { + dprintk("initialization failed\n"); goto err_out; + } memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); @@ -423,7 +639,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpufreq_cpu_data[cpu] = policy; + for_each_cpu_mask(j, policy->cpus) + cpufreq_cpu_data[j] = policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); policy->governor = NULL; /* to assure that the starting sequence is * run in cpufreq_set_policy */ @@ -432,16 +649,23 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) /* set default policy */ ret = cpufreq_set_policy(&new_policy); - if (ret) + if (ret) { + dprintk("setting policy failed\n"); goto err_out_unregister; + } module_put(cpufreq_driver->owner); + cpu_sys_devices[cpu] = sys_dev; + dprintk("initialization complete\n"); + cpufreq_debug_enable_ratelimit(); + return 0; err_out_unregister: spin_lock_irqsave(&cpufreq_driver_lock, flags); - cpufreq_cpu_data[cpu] = NULL; + for_each_cpu_mask(j, policy->cpus) + cpufreq_cpu_data[j] = NULL; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); kobject_unregister(&policy->kobj); @@ -452,6 +676,8 @@ err_out: nomem_out: module_put(cpufreq_driver->owner); + module_out: + cpufreq_debug_enable_ratelimit(); return ret; } @@ -466,19 +692,76 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) unsigned int cpu = sys_dev->id; unsigned long flags; struct cpufreq_policy *data; +#ifdef CONFIG_SMP + unsigned int j; +#endif + + cpufreq_debug_disable_ratelimit(); + dprintk("unregistering CPU %u\n", cpu); spin_lock_irqsave(&cpufreq_driver_lock, flags); data = cpufreq_cpu_data[cpu]; if (!data) { spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + cpu_sys_devices[cpu] = NULL; + cpufreq_debug_enable_ratelimit(); return -EINVAL; } cpufreq_cpu_data[cpu] = NULL; + + +#ifdef CONFIG_SMP + /* if this isn't the CPU which is the parent of the kobj, we + * only need to unlink, put and exit + */ + if (unlikely(cpu != data->cpu)) { + dprintk("removing link\n"); + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + sysfs_remove_link(&sys_dev->kobj, "cpufreq"); + cpu_sys_devices[cpu] = NULL; + cpufreq_cpu_put(data); + cpufreq_debug_enable_ratelimit(); + return 0; + } +#endif + + cpu_sys_devices[cpu] = NULL; + + if (!kobject_get(&data->kobj)) { + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); + cpufreq_debug_enable_ratelimit(); + return -EFAULT; + } + +#ifdef CONFIG_SMP + /* if we have other CPUs still registered, we need to unlink them, + * or else wait_for_completion below will lock up. Clean the + * cpufreq_cpu_data[] while holding the lock, and remove the sysfs + * links afterwards. + */ + if (unlikely(cpus_weight(data->cpus) > 1)) { + for_each_cpu_mask(j, data->cpus) { + if (j == cpu) + continue; + cpufreq_cpu_data[j] = NULL; + } + } + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - if (!kobject_get(&data->kobj)) - return -EFAULT; + if (unlikely(cpus_weight(data->cpus) > 1)) { + for_each_cpu_mask(j, data->cpus) { + if (j == cpu) + continue; + dprintk("removing link for cpu %u\n", j); + sysfs_remove_link(&cpu_sys_devices[j]->kobj, "cpufreq"); + cpufreq_cpu_put(data); + } + } +#else + spin_unlock_irqrestore(&cpufreq_driver_lock, flags); +#endif if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); @@ -491,13 +774,17 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) * not referenced anymore by anybody before we proceed with * unloading. */ + dprintk("waiting for dropping of refcount\n"); wait_for_completion(&data->kobj_unregister); + dprintk("wait complete\n"); if (cpufreq_driver->exit) cpufreq_driver->exit(data); kfree(data); + cpufreq_debug_enable_ratelimit(); + return 0; } @@ -505,6 +792,7 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) static void handle_update(void *data) { unsigned int cpu = (unsigned int)(long)data; + dprintk("handle_update for cpu %u called\n", cpu); cpufreq_update_policy(cpu); } @@ -521,9 +809,6 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne { struct cpufreq_freqs freqs; - if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC) - panic("CPU Frequency is out of sync."); - printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " "core thinks of %u, is %u kHz.\n", old_freq, new_freq); @@ -588,6 +873,8 @@ static int cpufreq_resume(struct sys_device * sysdev) unsigned int ret = 0; struct cpufreq_policy *cpu_policy; + dprintk("resuming cpu %u\n", cpu); + if (!cpu_online(cpu)) return 0; @@ -600,6 +887,12 @@ static int cpufreq_resume(struct sys_device * sysdev) if (!cpu_policy) return -EINVAL; + /* only handle each CPU group once */ + if (unlikely(cpu_policy->cpu != cpu)) { + cpufreq_cpu_put(cpu_policy); + return 0; + } + if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { unsigned int cur_freq = 0; @@ -614,11 +907,8 @@ static int cpufreq_resume(struct sys_device * sysdev) if (unlikely(cur_freq != cpu_policy->cur)) { struct cpufreq_freqs freqs; - if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC) - panic("CPU Frequency is out of sync."); - - printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing" - "core thinks of %u, is %u kHz.\n", cpu_policy->cur, cur_freq); + printk(KERN_WARNING "Warning: CPU frequency is %u, " + "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); freqs.cpu = cpu; freqs.old = cpu_policy->cur; @@ -626,6 +916,8 @@ static int cpufreq_resume(struct sys_device * sysdev) notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); + + cpu_policy->cur = cur_freq; } } @@ -724,6 +1016,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, { int retval = -EINVAL; lock_cpu_hotplug(); + dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, + target_freq, relation); if (cpu_online(policy->cpu)) retval = cpufreq_driver->target(policy, target_freq, relation); unlock_cpu_hotplug(); @@ -762,6 +1056,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) if (!try_module_get(policy->governor->owner)) return -EINVAL; + dprintk("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event); ret = policy->governor->governor(policy, event); /* we keep one module reference alive for each CPU governed by this CPU */ @@ -866,6 +1161,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli { int ret = 0; + cpufreq_debug_disable_ratelimit(); + dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, + policy->min, policy->max); + memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); @@ -902,14 +1201,19 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli data->min = policy->min; data->max = policy->max; + dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); + if (cpufreq_driver->setpolicy) { data->policy = policy->policy; + dprintk("setting range\n"); ret = cpufreq_driver->setpolicy(policy); } else { if (policy->governor != data->governor) { /* save old, working values */ struct cpufreq_governor *old_gov = data->governor; + dprintk("governor switch\n"); + /* end old governor */ if (data->governor) __cpufreq_governor(data, CPUFREQ_GOV_STOP); @@ -918,6 +1222,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli data->governor = policy->governor; if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { /* new governor failed, so re-start old one */ + dprintk("starting governor %s failed\n", data->governor->name); if (old_gov) { data->governor = old_gov; __cpufreq_governor(data, CPUFREQ_GOV_START); @@ -927,10 +1232,12 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli } /* might be a policy change, too, so fall through */ } + dprintk("governor: change or update limits\n"); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); } error_out: + cpufreq_debug_enable_ratelimit(); return ret; } @@ -987,6 +1294,7 @@ int cpufreq_update_policy(unsigned int cpu) down(&data->lock); + dprintk("updating policy for CPU %u\n", cpu); memcpy(&policy, data, sizeof(struct cpufreq_policy)); @@ -1005,87 +1313,6 @@ int cpufreq_update_policy(unsigned int cpu) EXPORT_SYMBOL(cpufreq_update_policy); -/********************************************************************* - * EXTERNALLY AFFECTING FREQUENCY CHANGES * - *********************************************************************/ - -/** - * adjust_jiffies - adjust the system "loops_per_jiffy" - * - * This function alters the system "loops_per_jiffy" for the clock - * speed change. Note that loops_per_jiffy cannot be updated on SMP - * systems as each CPU might be scaled differently. So, use the arch - * per-CPU loops_per_jiffy value wherever possible. - */ -#ifndef CONFIG_SMP -static unsigned long l_p_j_ref; -static unsigned int l_p_j_ref_freq; - -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) -{ - if (ci->flags & CPUFREQ_CONST_LOOPS) - return; - - if (!l_p_j_ref_freq) { - l_p_j_ref = loops_per_jiffy; - l_p_j_ref_freq = ci->old; - } - if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || - (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || - (val == CPUFREQ_RESUMECHANGE)) - loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); -} -#else -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; } -#endif - - -/** - * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition - * - * This function calls the transition notifiers and the "adjust_jiffies" function. It is called - * twice on all CPU frequency changes that have external effects. - */ -void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) -{ - BUG_ON(irqs_disabled()); - - freqs->flags = cpufreq_driver->flags; - - down_read(&cpufreq_notifier_rwsem); - switch (state) { - case CPUFREQ_PRECHANGE: - /* detect if the driver reported a value as "old frequency" which - * is not equal to what the cpufreq core thinks is "old frequency". - */ - if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { - if ((likely(cpufreq_cpu_data[freqs->cpu]->cur)) && - (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) - { - if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC) - panic("CPU Frequency is out of sync."); - - printk(KERN_WARNING "Warning: CPU frequency out of sync: " - "cpufreq and timing core thinks of %u, is %u kHz.\n", - cpufreq_cpu_data[freqs->cpu]->cur, freqs->old); - freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; - } - } - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); - adjust_jiffies(CPUFREQ_PRECHANGE, freqs); - break; - case CPUFREQ_POSTCHANGE: - adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); - cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; - break; - } - up_read(&cpufreq_notifier_rwsem); -} -EXPORT_SYMBOL_GPL(cpufreq_notify_transition); - - - /********************************************************************* * REGISTER / UNREGISTER CPUFREQ DRIVER * *********************************************************************/ @@ -1109,6 +1336,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) ((!driver_data->setpolicy) && (!driver_data->target))) return -EINVAL; + dprintk("trying to register driver %s\n", driver_data->name); + if (driver_data->setpolicy) driver_data->flags |= CPUFREQ_CONST_LOOPS; @@ -1133,6 +1362,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) /* if all ->init() calls failed, unregister */ if (ret) { + dprintk("no CPU initialized for driver %s\n", driver_data->name); sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); spin_lock_irqsave(&cpufreq_driver_lock, flags); @@ -1141,6 +1371,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) } } + if (!ret) { + dprintk("driver %s up and running\n", driver_data->name); + cpufreq_debug_enable_ratelimit(); + } + return (ret); } EXPORT_SYMBOL_GPL(cpufreq_register_driver); @@ -1158,8 +1393,14 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) { unsigned long flags; - if (!cpufreq_driver || (driver != cpufreq_driver)) + cpufreq_debug_disable_ratelimit(); + + if (!cpufreq_driver || (driver != cpufreq_driver)) { + cpufreq_debug_enable_ratelimit(); return -EINVAL; + } + + dprintk("unregistering driver %s\n", driver->name); sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver); diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index a9320ae41..bc31cac09 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -10,7 +10,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include @@ -26,7 +25,6 @@ #include #include #include -#include #include #include @@ -83,7 +81,7 @@ struct dbs_tuners { unsigned int down_threshold; }; -struct dbs_tuners dbs_tuners_ins = { +static struct dbs_tuners dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, @@ -101,10 +99,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) } #define define_one_ro(_name) \ -static struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = show_##_name, \ -} +static struct freq_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); define_one_ro(sampling_rate_min); @@ -127,13 +123,13 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf (buf, "%u", &input); - down(&dbs_sem); if (ret != 1 ) - goto out; + return -EINVAL; + down(&dbs_sem); dbs_tuners_ins.sampling_down_factor = input; -out: up(&dbs_sem); + return count; } @@ -143,13 +139,16 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf (buf, "%u", &input); + down(&dbs_sem); - if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) - goto out; + if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { + up(&dbs_sem); + return -EINVAL; + } dbs_tuners_ins.sampling_rate = input; -out: up(&dbs_sem); + return count; } @@ -159,15 +158,18 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf (buf, "%u", &input); + down(&dbs_sem); if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || input < MIN_FREQUENCY_UP_THRESHOLD || - input <= dbs_tuners_ins.down_threshold) - goto out; + input <= dbs_tuners_ins.down_threshold) { + up(&dbs_sem); + return -EINVAL; + } dbs_tuners_ins.up_threshold = input; -out: up(&dbs_sem); + return count; } @@ -177,24 +179,24 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf (buf, "%u", &input); + down(&dbs_sem); if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || input < MIN_FREQUENCY_DOWN_THRESHOLD || - input >= dbs_tuners_ins.up_threshold) - goto out; + input >= dbs_tuners_ins.up_threshold) { + up(&dbs_sem); + return -EINVAL; + } dbs_tuners_ins.down_threshold = input; -out: up(&dbs_sem); + return count; } -#define define_one_rw(_name) \ -static struct freq_attr _name = { \ - .attr = { .name = __stringify(_name), .mode = 0644 }, \ - .show = show_##_name, \ - .store = store_##_name, \ -} +#define define_one_rw(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); define_one_rw(sampling_down_factor); diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index f2348e790..8d536b40d 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -15,12 +15,16 @@ #include #include +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "performance", msg) + + static int cpufreq_governor_performance(struct cpufreq_policy *policy, unsigned int event) { switch (event) { case CPUFREQ_GOV_START: case CPUFREQ_GOV_LIMITS: + dprintk("setting to %u kHz because of event %u\n", policy->max, event); __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); break; default: diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index ec8544885..c85edda7f 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -15,12 +15,15 @@ #include #include +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "powersave", msg) + static int cpufreq_governor_powersave(struct cpufreq_policy *policy, unsigned int event) { switch (event) { case CPUFREQ_GOV_START: case CPUFREQ_GOV_LIMITS: + dprintk("setting to %u kHz because of event %u\n", policy->min, event); __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); break; default: diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 161e8a27c..cf107b052 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -68,12 +68,14 @@ */ static unsigned int cpu_max_freq[NR_CPUS]; static unsigned int cpu_min_freq[NR_CPUS]; -static unsigned int cpu_cur_freq[NR_CPUS]; +static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */ +static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */ static unsigned int cpu_is_managed[NR_CPUS]; static struct cpufreq_policy current_policy[NR_CPUS]; static DECLARE_MUTEX (userspace_sem); +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg) /* keep track of frequency transitions */ static int @@ -82,6 +84,7 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, { struct cpufreq_freqs *freq = data; + dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n", freq->cpu, freq->new); cpu_cur_freq[freq->cpu] = freq->new; return 0; @@ -93,20 +96,24 @@ static struct notifier_block userspace_cpufreq_notifier_block = { /** - * cpufreq_set - set the CPU frequency + * _cpufreq_set - set the CPU frequency * @freq: target frequency in kHz * @cpu: CPU for which the frequency is to be set * * Sets the CPU frequency to freq. */ -int cpufreq_set(unsigned int freq, unsigned int cpu) +static int _cpufreq_set(unsigned int freq, unsigned int cpu) { int ret = -EINVAL; + dprintk("_cpufreq_set for cpu %u, freq %u kHz\n", cpu, freq); + down(&userspace_sem); if (!cpu_is_managed[cpu]) goto err; + cpu_set_freq[cpu] = freq; + if (freq < cpu_min_freq[cpu]) freq = cpu_min_freq[cpu]; if (freq > cpu_max_freq[cpu]) @@ -126,6 +133,18 @@ int cpufreq_set(unsigned int freq, unsigned int cpu) up(&userspace_sem); return ret; } + + +#ifdef CONFIG_CPU_FREQ_24_API + +#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01 + +static unsigned int warning_print = 0; + +int __deprecated cpufreq_set(unsigned int freq, unsigned int cpu) +{ + return _cpufreq_set(freq, cpu); +} EXPORT_SYMBOL_GPL(cpufreq_set); @@ -136,18 +155,14 @@ EXPORT_SYMBOL_GPL(cpufreq_set); * Sets the CPU frequency to the maximum frequency supported by * this CPU. */ -int cpufreq_setmax(unsigned int cpu) +int __deprecated cpufreq_setmax(unsigned int cpu) { if (!cpu_is_managed[cpu] || !cpu_online(cpu)) return -EINVAL; - return cpufreq_set(cpu_max_freq[cpu], cpu); + return _cpufreq_set(cpu_max_freq[cpu], cpu); } EXPORT_SYMBOL_GPL(cpufreq_setmax); - -#ifdef CONFIG_CPU_FREQ_24_API - - /*********************** cpufreq_sysctl interface ********************/ static int cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, @@ -162,6 +177,13 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, return 0; } + if (!warning_print) { + warning_print++; + printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and " + "will be removed from (new) 2.6. kernels soon " + "after 2005-01-01\n"); + } + if (write) { unsigned int freq; @@ -173,7 +195,7 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp, buf[sizeof(buf) - 1] = '\0'; freq = simple_strtoul(buf, &p, 0); - cpufreq_set(freq, cpu); + _cpufreq_set(freq, cpu); } else { len = sprintf(buf, "%d\n", cpufreq_get(cpu)); if (len > left) @@ -197,6 +219,13 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen, if (!cpu_online(cpu)) return -EINVAL; + if (!warning_print) { + warning_print++; + printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and " + "will be removed from (new) 2.6. kernels soon " + "after 2005-01-01\n"); + } + if (oldval && oldlenp) { size_t oldlen; @@ -219,7 +248,7 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen, if (get_user(freq, (unsigned int __user *)newval)) return -EFAULT; - cpufreq_set(freq, cpu); + _cpufreq_set(freq, cpu); } return 1; } @@ -440,7 +469,7 @@ static ctl_table ctl_cpu[2] = { } }; -struct ctl_table_header *cpufreq_sysctl_table; +static struct ctl_table_header *cpufreq_sysctl_table; static inline void cpufreq_sysctl_init(void) { @@ -474,13 +503,14 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) if (ret != 1) return -EINVAL; - cpufreq_set(freq, policy->cpu); + _cpufreq_set(freq, policy->cpu); return count; } -static struct freq_attr freq_attr_scaling_setspeed = { - .attr = { .name = "scaling_setspeed", .mode = 0644 }, +static struct freq_attr freq_attr_scaling_setspeed = +{ + .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE }, .show = show_speed, .store = store_speed, }; @@ -491,7 +521,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE))) + if (!cpu_online(cpu)) return -EINVAL; BUG_ON(!policy->cur); down(&userspace_sem); @@ -499,8 +529,10 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; cpu_cur_freq[cpu] = policy->cur; + cpu_set_freq[cpu] = policy->cur; sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); + dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]); up(&userspace_sem); break; case CPUFREQ_GOV_STOP: @@ -508,20 +540,26 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, cpu_is_managed[cpu] = 0; cpu_min_freq[cpu] = 0; cpu_max_freq[cpu] = 0; + cpu_set_freq[cpu] = 0; sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); + dprintk("managing cpu %u stopped\n", cpu); up(&userspace_sem); - module_put(THIS_MODULE); break; case CPUFREQ_GOV_LIMITS: down(&userspace_sem); cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; - if (policy->max < cpu_cur_freq[cpu]) + dprintk("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu], cpu_set_freq[cpu]); + if (policy->max < cpu_set_freq[cpu]) { __cpufreq_driver_target(¤t_policy[cpu], policy->max, CPUFREQ_RELATION_H); - else if (policy->min > cpu_cur_freq[cpu]) + } else if (policy->min > cpu_set_freq[cpu]) { __cpufreq_driver_target(¤t_policy[cpu], policy->min, CPUFREQ_RELATION_L); + } else { + __cpufreq_driver_target(¤t_policy[cpu], cpu_set_freq[cpu], + CPUFREQ_RELATION_L); + } memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); up(&userspace_sem); break; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index f0e6aaf2c..22e2ba6b1 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -9,6 +9,8 @@ #include #include +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg) + /********************************************************************* * FREQUENCY TABLE HELPERS * *********************************************************************/ @@ -22,8 +24,12 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) + if (freq == CPUFREQ_ENTRY_INVALID) { + dprintk("table entry %u is invalid, skipping\n", i); + continue; + } + dprintk("table entry %u: %u kHz, %u index\n", i, freq, table[i].index); if (freq < min_freq) min_freq = freq; if (freq > max_freq) @@ -48,6 +54,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, unsigned int i = 0; unsigned int count = 0; + dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); + if (!cpu_online(policy->cpu)) return -EINVAL; @@ -72,6 +80,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); + dprintk("verification lead to (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); + return 0; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); @@ -87,6 +97,8 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table suboptimal = { .index = ~0, }; unsigned int i; + dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu); + switch (relation) { case CPUFREQ_RELATION_H: optimal.frequency = 0; @@ -142,7 +154,10 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, *index = suboptimal.index; } else *index = optimal.index; - + + dprintk("target is %u (%u kHz, %u)\n", *index, table[*index].frequency, + table[*index].index); + return 0; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); @@ -175,7 +190,7 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) } struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { - .attr = { .name = "scaling_available_frequencies", .mode = 0444 }, + .attr = { .name = "scaling_available_frequencies", .mode = 0444, .owner=THIS_MODULE }, .show = show_available_freqs, }; EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); @@ -187,12 +202,14 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu) { + dprintk("setting show_table for cpu %u to %p\n", cpu, table); show_table[cpu] = table; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); void cpufreq_frequency_table_put_attr(unsigned int cpu) { + dprintk("clearing show_table for cpu %u\n", cpu); show_table[cpu] = NULL; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c index a0eaf6f1d..673977899 100644 --- a/drivers/cpufreq/proc_intf.c +++ b/drivers/cpufreq/proc_intf.c @@ -12,9 +12,12 @@ #include #include +#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01 #define CPUFREQ_ALL_CPUS ((NR_CPUS)) +static unsigned int warning_print = 0; + /** * cpufreq_parse_policy - parse a policy string * @input_string: the string to parse. @@ -110,6 +113,13 @@ static int cpufreq_proc_read ( if (off != 0) goto end; + if (!warning_print) { + warning_print++; + printk(KERN_INFO "Access to /proc/cpufreq is deprecated and " + "will be removed from (new) 2.6. kernels soon " + "after 2005-01-01\n"); + } + p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n"); for (i=0;i + * Copyright (C) 2004 Jochen Friedrich * * This code has basically these routines at the moment: * int dio_find(u_int deviceid) @@ -9,9 +10,8 @@ * This means that framebuffers should pass it as * DIO_ENCODE_ID(DIO_ID_FBUFFER,DIO_ID2_TOPCAT) * (or whatever); everybody else just uses DIO_ID_FOOBAR. - * void *dio_scodetoviraddr(int scode) - * Return the virtual address corresponding to the given select code. - * NB: DIO-II devices will have to be mapped in in this routine! + * unsigned long dio_scodetophysaddr(int scode) + * Return the physical address corresponding to the given select code. * int dio_scodetoipl(int scode) * Every DIO card has a fixed interrupt priority level. This function * returns it, whatever it is. @@ -24,14 +24,26 @@ * This file is based on the way the Amiga port handles Zorro II cards, * although we aren't so complicated... */ -#include -#include +#include +#include #include +#include +#include #include #include /* kmalloc() */ -#include -#include /* hwreg_present() */ -#include /* readb() */ +#include +#include /* readb() */ + +struct dio_bus dio_bus = { + .resources = { + /* DIO range */ + { .name = "DIO mem", .start = 0x00600000, .end = 0x007fffff }, + /* DIO-II range */ + { .name = "DIO-II mem", .start = 0x01000000, .end = 0x1fffffff } + }, + .name = "DIO bus" +}; + /* not a real config option yet! */ #define CONFIG_DIO_CONSTANTS @@ -59,7 +71,7 @@ static struct dioname names[] = DIONAME(DCA0), DIONAME(DCA0REM), DIONAME(DCA1), DIONAME(DCA1REM), DIONAME(DCM), DIONAME(DCMREM), DIONAME(LAN), - DIONAME(FHPIB), DIONAME(NHPIB), DIONAME(IHPIB), + DIONAME(FHPIB), DIONAME(NHPIB), DIONAME(SCSI0), DIONAME(SCSI1), DIONAME(SCSI2), DIONAME(SCSI3), DIONAME(FBUFFER), DIONAME(PARALLEL), DIONAME(VME), DIONAME(DCL), DIONAME(DCLREM), @@ -79,7 +91,7 @@ static struct dioname names[] = #define NUMNAMES (sizeof(names) / sizeof(struct dioname)) static const char *unknowndioname - = "unknown DIO board -- please email !"; + = "unknown DIO board -- please email !"; static const char *dio_getname(int id) { @@ -88,7 +100,7 @@ static const char *dio_getname(int id) for (i = 0; i < NUMNAMES; i++) if (names[i].id == id) return names[i].name; - + return unknowndioname; } @@ -99,70 +111,59 @@ static char dio_no_name[] = { 0 }; #endif /* CONFIG_DIO_CONSTANTS */ -/* We represent all the DIO boards in the system with a linked list of these structs. */ -struct dioboard -{ - struct dioboard *next; /* link to next struct in list */ - int ipl; /* IPL of this board */ - int configured; /* has this board been configured? */ - int scode; /* select code of this board */ - int id; /* encoded ID */ - const char *name; -}; - -static struct dioboard *blist = NULL; - -static int __init dio_find_slow(int deviceid) +int __init dio_find(int deviceid) { - /* Called to find a DIO device before the full bus scan has run. Basically - * only used by the console driver. - * We don't do the primary+secondary ID encoding thing here. Maybe we should. - * (that would break the topcat detection, though. I need to think about - * the whole primary/secondary ID thing.) - */ - int scode; - u_char prid; + /* Called to find a DIO device before the full bus scan has run. + * Only used by the console driver. + */ + int scode, id; + u_char prid, secid, i; + mm_segment_t fs; - for (scode = 0; scode < DIO_SCMAX; scode++) - { + for (scode = 0; scode < DIO_SCMAX; scode++) { void *va; + unsigned long pa; if (DIO_SCINHOLE(scode)) continue; - - va = dio_scodetoviraddr(scode); - if (!va || !hwreg_present(va + DIO_IDOFF)) + + pa = dio_scodetophysaddr(scode); + + if (!pa) + continue; + + if (scode < DIOII_SCBASE) + va = (void *)(pa + DIO_VIRADDRBASE); + else + va = ioremap(pa, PAGE_SIZE); + + fs = get_fs(); + set_fs(KERNEL_DS); + + if (get_user(i, (unsigned char *)va + DIO_IDOFF)) { + set_fs(fs); + if (scode >= DIOII_SCBASE) + iounmap(va); continue; /* no board present at that select code */ + } - /* We aren't very likely to want to use this to get at the IHPIB, - * but maybe it's returning the same ID as the card we do want... - */ - if (!DIO_ISIHPIB(scode)) - prid = DIO_ID(va); - else - prid = DIO_ID_IHPIB; + set_fs(fs); + prid = DIO_ID(va); - if (prid == deviceid) + if (DIO_NEEDSSECID(prid)) { + secid = DIO_SECID(va); + id = DIO_ENCODE_ID(prid, secid); + } else + id = prid; + + if (id == deviceid) { + if (scode >= DIOII_SCBASE) + iounmap(va); return scode; + } } - return 0; -} -/* Aargh: we use 0 for an error return code, but select code 0 exists! - * FIXME (trivial, use -1, but requires changes to all the drivers :-< ) - */ -int dio_find(int deviceid) -{ - if (blist) - { - /* fast way */ - struct dioboard *b; - for (b = blist; b; b = b->next) - if (b->id == deviceid && b->configured == 0) - return b->scode; - return 0; - } - return dio_find_slow(deviceid); + return -1; } /* This is the function that scans the DIO space and works out what @@ -170,58 +171,92 @@ int dio_find(int deviceid) */ static int __init dio_init(void) { - int scode; - struct dioboard *b, *bprev = NULL; - - printk("Scanning for DIO devices...\n"); - + int scode; + mm_segment_t fs; + int i; + struct dio_dev *dev; + + if (!MACH_IS_HP300) + return 0; + + printk(KERN_INFO "Scanning for DIO devices...\n"); + + /* Initialize the DIO bus */ + INIT_LIST_HEAD(&dio_bus.devices); + strcpy(dio_bus.dev.bus_id, "dio"); + device_register(&dio_bus.dev); + + /* Request all resources */ + dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2); + for (i = 0; i < dio_bus.num_resources; i++) + request_resource(&iomem_resource, &dio_bus.resources[i]); + + /* Register all devices */ for (scode = 0; scode < DIO_SCMAX; ++scode) { u_char prid, secid = 0; /* primary, secondary ID bytes */ u_char *va; + unsigned long pa; if (DIO_SCINHOLE(scode)) continue; - - va = dio_scodetoviraddr(scode); - if (!va || !hwreg_present(va + DIO_IDOFF)) + + pa = dio_scodetophysaddr(scode); + + if (!pa) + continue; + + if (scode < DIOII_SCBASE) + va = (void *)(pa + DIO_VIRADDRBASE); + else + va = ioremap(pa, PAGE_SIZE); + + fs = get_fs(); + set_fs(KERNEL_DS); + + if (get_user(i, (unsigned char *)va + DIO_IDOFF)) { + set_fs(fs); + if (scode >= DIOII_SCBASE) + iounmap(va); continue; /* no board present at that select code */ + } + + set_fs(fs); /* Found a board, allocate it an entry in the list */ - b = kmalloc(sizeof(struct dioboard), GFP_KERNEL); - - /* read the ID byte(s) and encode if necessary. Note workaround - * for broken internal HPIB devices... - */ - if (!DIO_ISIHPIB(scode)) - prid = DIO_ID(va); - else - prid = DIO_ID_IHPIB; - - if (DIO_NEEDSSECID(prid)) - { + dev = kmalloc(sizeof(struct dio_dev), GFP_KERNEL); + if (!dev) + return 0; + + memset(dev, 0, sizeof(struct dio_dev)); + dev->bus = &dio_bus; + dev->dev.parent = &dio_bus.dev; + dev->dev.bus = &dio_bus_type; + dev->scode = scode; + dev->resource.start = pa; + dev->resource.end = pa + DIO_SIZE(scode, va); + sprintf(dev->dev.bus_id,"%02x", scode); + + /* read the ID byte(s) and encode if necessary. */ + prid = DIO_ID(va); + + if (DIO_NEEDSSECID(prid)) { secid = DIO_SECID(va); - b->id = DIO_ENCODE_ID(prid, secid); - } - else - b->id = prid; - - b->configured = 0; - b->scode = scode; - b->ipl = DIO_IPL(va); - b->name = dio_getname(b->id); - printk("select code %3d: ipl %d: ID %02X", scode, b->ipl, prid); - if (DIO_NEEDSSECID(b->id)) + dev->id = DIO_ENCODE_ID(prid, secid); + } else + dev->id = prid; + + dev->ipl = DIO_IPL(va); + strcpy(dev->name,dio_getname(dev->id)); + printk(KERN_INFO "select code %3d: ipl %d: ID %02X", dev->scode, dev->ipl, prid); + if (DIO_NEEDSSECID(prid)) printk(":%02X", secid); - printk(": %s\n", b->name); - - b->next = NULL; + printk(": %s\n", dev->name); - if (bprev) - bprev->next = b; - else - blist = b; - bprev = b; + if (scode >= DIOII_SCBASE) + iounmap(va); + device_register(&dev->dev); + dio_create_sysfs_dev_files(dev); } return 0; } @@ -229,84 +264,16 @@ static int __init dio_init(void) subsys_initcall(dio_init); /* Bear in mind that this is called in the very early stages of initialisation - * in order to get the virtual address of the serial port for the console... + * in order to get the address of the serial port for the console... */ -void *dio_scodetoviraddr(int scode) +unsigned long dio_scodetophysaddr(int scode) { - if (scode > DIOII_SCBASE) - { - printk("dio_scodetoviraddr: don't support DIO-II yet!\n"); - return 0; - } - else if (scode > DIO_SCMAX || scode < 0) + if (scode >= DIOII_SCBASE) { + return (DIOII_BASE + (scode - 132) * DIOII_DEVSIZE); + } else if (scode > DIO_SCMAX || scode < 0) return 0; else if (DIO_SCINHOLE(scode)) return 0; - else if (DIO_ISIHPIB(scode)) - return (void*)DIO_IHPIBADDR; - return (void*)(DIO_VIRADDRBASE + DIO_BASE + scode * 0x10000); -} - -int dio_scodetoipl(int scode) -{ - struct dioboard *b; - for (b = blist; b; b = b->next) - if (b->scode == scode) - break; - - if (!b) - { - printk("dio_scodetoipl: bad select code %d\n", scode); - return 0; - } - else - return b->ipl; -} - -const char *dio_scodetoname(int scode) -{ - struct dioboard *b; - for (b = blist; b; b = b->next) - if (b->scode == scode) - break; - - if (!b) - { - printk("dio_scodetoname: bad select code %d\n", scode); - return NULL; - } - else - return b->name; -} - -void dio_config_board(int scode) -{ - struct dioboard *b; - for (b = blist; b; b = b->next) - if (b->scode == scode) - break; - - if (!b) - printk("dio_config_board: bad select code %d\n", scode); - else if (b->configured) - printk("dio_config_board: board at select code %d already configured\n", scode); - else - b->configured = 1; -} - -void dio_unconfig_board(int scode) -{ - struct dioboard *b; - for (b = blist; b; b = b->next) - if (b->scode == scode) - break; - - if (!b) - printk("dio_unconfig_board: bad select code %d\n", scode); - else if (!b->configured) - printk("dio_unconfig_board: board at select code %d not configured\n", - scode); - else - b->configured = 0; + return (DIO_BASE + scode * DIO_DEVSIZE); } diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index af825fc30..6381ba538 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -418,8 +418,8 @@ static int __init eisa_init (void) return 0; } -module_param_array(enable_dev, int, enable_dev_count, 0444); -module_param_array(disable_dev, int, disable_dev_count, 0444); +module_param_array(enable_dev, int, &enable_dev_count, 0444); +module_param_array(disable_dev, int, &disable_dev_count, 0444); postcore_initcall (eisa_init); diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index 3f8b4c151..e7be415b2 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -32,7 +32,7 @@ static char *version = #include #include #include -#include +#include #include #include #include @@ -671,10 +671,10 @@ static inline void soc_init(struct sbus_dev *sdev, int no) cq[0].address = s->req_dvma; s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE; - s->req[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET); - s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq)); - s->rsp[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq)); + s->req[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET); + s->req[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq)); + s->rsp[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET); + s->rsp[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq)); cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req)); cq[4].address = 1; diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h index 7015eb7ba..c4edefd03 100644 --- a/drivers/fc4/soc.h +++ b/drivers/fc4/soc.h @@ -81,29 +81,29 @@ do { (s)->imask = (i); \ * That's why here are the following inline functions... */ -typedef unsigned long xram_p; +typedef void __iomem *xram_p; /* Get 32bit number from XRAM */ -static inline u32 xram_get_32 (xram_p x) +static inline u32 xram_get_32(xram_p x) { return ((sbus_readw(x + 0x00UL) << 16) | (sbus_readw(x + 0x02UL))); } /* Like the above, but when we don't care about the high 16 bits */ -static inline u32 xram_get_32low (xram_p x) +static inline u32 xram_get_32low(xram_p x) { return (u32) sbus_readw(x + 0x02UL); } -static inline u16 xram_get_16 (xram_p x) +static inline u16 xram_get_16(xram_p x) { return sbus_readw(x); } -static inline u8 xram_get_8 (xram_p x) +static inline u8 xram_get_8(xram_p x) { - if (x & (xram_p)0x1) { + if ((unsigned long)x & 0x1UL) { x = x - 1; return (u8) sbus_readw(x); } else { @@ -111,7 +111,7 @@ static inline u8 xram_get_8 (xram_p x) } } -static inline void xram_copy_from (void *p, xram_p x, int len) +static inline void xram_copy_from(void *p, xram_p x, int len) { for (len >>= 2; len > 0; len--, x += sizeof(u32)) { u32 val, *p32 = p; @@ -123,7 +123,7 @@ static inline void xram_copy_from (void *p, xram_p x, int len) } } -static inline void xram_copy_to (xram_p x, void *p, int len) +static inline void xram_copy_to(xram_p x, void *p, int len) { for (len >>= 2; len > 0; len--, x += sizeof(u32)) { u32 tmp, *p32 = p; @@ -135,7 +135,7 @@ static inline void xram_copy_to (xram_p x, void *p, int len) } } -static inline void xram_bzero (xram_p x, int len) +static inline void xram_bzero(xram_p x, int len) { for (len >>= 1; len > 0; len--, x += sizeof(u16)) sbus_writew(0, x); @@ -260,7 +260,7 @@ typedef struct { } soc_port; typedef struct { - soc_hw_cq *hw_cq; /* Related XRAM cq */ + soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */ soc_req *pool; u8 in; u8 out; @@ -274,7 +274,7 @@ struct soc { soc_cq req[2]; /* Request CQs */ soc_cq rsp[2]; /* Response CQs */ int soc_no; - unsigned long regs; + void __iomem *regs; xram_p xram; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index e158d7d26..b2377dbd8 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -27,8 +27,8 @@ static char *version = #include #include #include +#include #include -#include #include #include #include @@ -60,7 +60,7 @@ static char *version = #define for_each_socal(s) for (s = socals; s; s = s->next) struct socal *socals = NULL; -static void socal_copy_from_xram(void *d, unsigned long xram, long size) +static void socal_copy_from_xram(void *d, void __iomem *xram, long size) { u32 *dp = (u32 *) d; while (size) { @@ -70,7 +70,7 @@ static void socal_copy_from_xram(void *d, unsigned long xram, long size) } } -static void socal_copy_to_xram(unsigned long xram, void *s, long size) +static void socal_copy_to_xram(void __iomem *xram, void *s, long size) { u32 *sp = (u32 *) s; while (size) { @@ -800,11 +800,11 @@ static inline void socal_init(struct sbus_dev *sdev, int no) s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE; s->rsp[2].pool = s->rsp[1].pool + SOCAL_CQ_RSP1_SIZE; - s->req[0].hw_cq = (socal_hw_cq *)(s->xram + SOCAL_CQ_REQ_OFFSET); - s->req[1].hw_cq = (socal_hw_cq *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq)); - s->rsp[0].hw_cq = (socal_hw_cq *)(s->xram + SOCAL_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (socal_hw_cq *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq)); - s->rsp[2].hw_cq = (socal_hw_cq *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq)); + s->req[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET); + s->req[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq)); + s->rsp[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET); + s->rsp[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq)); + s->rsp[2].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq)); cq[1].address = cq[0].address + (SOCAL_CQ_REQ0_SIZE * sizeof(socal_req)); cq[4].address = cq[1].address + (SOCAL_CQ_REQ1_SIZE * sizeof(socal_req)); diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h index a853fad92..774edf68e 100644 --- a/drivers/fc4/socal.h +++ b/drivers/fc4/socal.h @@ -281,7 +281,7 @@ typedef struct { } socal_port; typedef struct { - socal_hw_cq *hw_cq; /* Related XRAM cq */ + socal_hw_cq __iomem *hw_cq; /* Related XRAM cq */ socal_req *pool; u8 in; u8 out; @@ -295,9 +295,9 @@ struct socal { socal_cq req[4]; /* Request CQs */ socal_cq rsp[4]; /* Response CQs */ int socal_no; - unsigned long regs; - unsigned long xram; - unsigned long eeprom; + void __iomem *regs; + void __iomem *xram; + void __iomem *eeprom; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ u32 cfg; /* Our copy of regs->cfg */ diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index a6504dbd3..019fa45d7 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -14,8 +14,9 @@ config EDD Services real mode BIOS calls to determine which disk BIOS tries boot from. This information is then exported via sysfs. - This option is experimental, but believed to be safe, - and most disk controller BIOS vendors do not yet implement this feature. + This option is experimental and is known to fail to boot on some + obscure configurations. Most disk controller BIOS vendors do + not yet implement this feature. config EFI_VARS tristate "EFI Variable Support via sysfs" @@ -47,7 +48,11 @@ config EFI_PCDP use the first serial port it describes as the Linux console, say Y here. If your EFI ConOut path contains only a UART device, it will become the console automatically. Otherwise, - you must specify the "console=ttyS0" kernel boot argument. + you must specify the "console=hcdp" kernel boot argument. + + Neither the PCDP nor the HCDP affects naming of serial devices, + so a serial console may be /dev/ttyS0, /dev/ttyS1, etc, depending + on how the driver discovers devices. You must also enable the appropriate drivers (serial, VGA, etc.) diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 47d430a33..33b669e6f 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -70,7 +70,7 @@ struct edd_attribute { static int edd_dev_is_type(struct edd_device *edev, const char *type); static struct pci_dev *edd_get_pci_dev(struct edd_device *edev); -static struct edd_device *edd_devices[EDDMAXNR]; +static struct edd_device *edd_devices[EDD_MBR_SIG_MAX]; #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ struct edd_attribute edd_attr_##_name = { \ @@ -728,9 +728,9 @@ edd_device_register(struct edd_device *edev, int i) static inline int edd_num_devices(void) { - return min_t(unsigned char, - max_t(unsigned char, edd.edd_info_nr, edd.mbr_signature_nr), - max_t(unsigned char, EDD_MBR_SIG_MAX, EDDMAXNR)); + return max_t(unsigned char, + min_t(unsigned char, EDD_MBR_SIG_MAX, edd.mbr_signature_nr), + min_t(unsigned char, EDDMAXNR, edd.edd_info_nr)); } /** diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 4f9284956..bac72bbaf 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -640,7 +640,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, *(short_name + strlen(short_name)) = '-'; efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); - kobject_set_name(&new_efivar->kobj, short_name); + kobject_set_name(&new_efivar->kobj, "%s", short_name); kobj_set_kset_s(new_efivar, vars_subsys); kobject_register(&new_efivar->kobj); diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 09e4f68d0..ca751f573 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -14,127 +14,45 @@ #include #include #include -#include #include -#include -#include -#include #include "pcdp.h" -static inline int -uart_irq_supported(int rev, struct pcdp_uart *uart) -{ - if (rev < 3) - return uart->pci_func & PCDP_UART_IRQ; - return uart->flags & PCDP_UART_IRQ; -} - -static inline int -uart_pci(int rev, struct pcdp_uart *uart) -{ - if (rev < 3) - return uart->pci_func & PCDP_UART_PCI; - return uart->flags & PCDP_UART_PCI; -} - -static inline int -uart_active_high_low(int rev, struct pcdp_uart *uart) -{ - if (uart_pci(rev, uart) || uart->flags & PCDP_UART_ACTIVE_LOW) - return ACPI_ACTIVE_LOW; - return ACPI_ACTIVE_HIGH; -} - -static inline int -uart_edge_level(int rev, struct pcdp_uart *uart) -{ - if (uart_pci(rev, uart)) - return ACPI_LEVEL_SENSITIVE; - if (rev < 3 || uart->flags & PCDP_UART_EDGE_SENSITIVE) - return ACPI_EDGE_SENSITIVE; - return ACPI_LEVEL_SENSITIVE; -} - -static void __init -setup_serial_console(int rev, struct pcdp_uart *uart) +static int __init +setup_serial_console(struct pcdp_uart *uart) { #ifdef CONFIG_SERIAL_8250_CONSOLE - struct uart_port port; - static char options[16]; - int mapsize = 64; - - memset(&port, 0, sizeof(port)); - port.uartclk = uart->clock_rate; - if (!port.uartclk) /* some FW doesn't supply this */ - port.uartclk = BASE_BAUD * 16; - - if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - port.mapbase = uart->addr.address; - port.membase = ioremap(port.mapbase, mapsize); - if (!port.membase) { - printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n", - __FUNCTION__, port.mapbase, port.mapbase + mapsize); - return; - } - port.iotype = UPIO_MEM; - } else if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - port.iobase = uart->addr.address; - port.iotype = UPIO_PORT; - } else - return; - - switch (uart->pci_prog_intfc) { - case 0x0: port.type = PORT_8250; break; - case 0x1: port.type = PORT_16450; break; - case 0x2: port.type = PORT_16550; break; - case 0x3: port.type = PORT_16650; break; - case 0x4: port.type = PORT_16750; break; - case 0x5: port.type = PORT_16850; break; - case 0x6: port.type = PORT_16C950; break; - default: port.type = PORT_UNKNOWN; break; - } - - port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - - if (uart_irq_supported(rev, uart)) { - port.irq = acpi_register_gsi(uart->gsi, - uart_active_high_low(rev, uart), - uart_edge_level(rev, uart)); - port.flags |= UPF_AUTO_IRQ; /* some FW reported wrong GSI */ - if (uart_pci(rev, uart)) - port.flags |= UPF_SHARE_IRQ; - } - - if (early_serial_setup(&port) < 0) - return; + int mmio; + static char options[64]; - snprintf(options, sizeof(options), "%lun%d", uart->baud, + mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); + snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d", + mmio ? "mmio" : "io", uart->addr.address, uart->baud, uart->bits ? uart->bits : 8); - add_preferred_console("ttyS", port.line, options); - printk(KERN_INFO "PCDP: serial console at %s 0x%lx (ttyS%d, options %s)\n", - port.iotype == UPIO_MEM ? "MMIO" : "I/O", - uart->addr.address, port.line, options); + return early_serial_console_init(options); +#else + return -ENODEV; #endif } -static void __init +static int __init setup_vga_console(struct pcdp_vga *vga) { -#ifdef CONFIG_VT -#ifdef CONFIG_VGA_CONSOLE +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) { printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n"); - return; + return -ENODEV; } conswitchp = &vga_con; printk(KERN_INFO "PCDP: VGA console\n"); -#endif + return 0; +#else + return -ENODEV; #endif } -void __init +int __init efi_setup_pcdp_console(char *cmdline) { struct pcdp *pcdp; @@ -144,20 +62,25 @@ efi_setup_pcdp_console(char *cmdline) pcdp = efi.hcdp; if (!pcdp) - return; + return -ENODEV; - printk(KERN_INFO "PCDP: v%d at 0x%p\n", pcdp->rev, pcdp); + printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); - if (pcdp->rev < 3) { - if (strstr(cmdline, "console=ttyS0") || efi_uart_console_only()) + if (strstr(cmdline, "console=hcdp")) { + if (pcdp->rev < 3) serial = 1; + } else if (strstr(cmdline, "console=")) { + printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); + return -ENODEV; } + if (pcdp->rev < 3 && efi_uart_console_only()) + serial = 1; + for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) { if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) { if (uart->type == PCDP_CONSOLE_UART) { - setup_serial_console(pcdp->rev, uart); - return; + return setup_serial_console(uart); } } } @@ -168,11 +91,12 @@ efi_setup_pcdp_console(char *cmdline) dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { - setup_vga_console((struct pcdp_vga *) dev); - return; + return setup_vga_console((struct pcdp_vga *) dev); } } } + + return -ENODEV; } #ifdef CONFIG_IA64_EARLY_PRINTK_UART diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 2b48079f5..cd170395a 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -7,6 +7,9 @@ obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o obj-y += busses/ chips/ algos/ +i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o + + ifeq ($(CONFIG_I2C_DEBUG_CORE),y) EXTRA_CFLAGS += -DDEBUG endif diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 88982cd31..cf9832bdc 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -27,6 +27,17 @@ config I2C_ALGOPCF This support is also available as a module. If so, the module will be called i2c-algo-pcf. +config I2C_ALGOPCA + tristate "I2C PCA 9564 interfaces" + depends on I2C + help + This allows you to use a range of I2C adapters called PCA adapters. + Say Y if you own an I2C adapter belonging to this class and then say + Y to the specific driver for you adapter below. + + This support is also available as a module. If so, the module + will be called i2c-algo-pca. + config I2C_ALGOITE tristate "ITE I2C Algorithm" depends on MIPS_ITE8172 && I2C diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile index df88f3f01..3545644be 100644 --- a/drivers/i2c/algos/Makefile +++ b/drivers/i2c/algos/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o +obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index afbd48fe8..4ea4c7928 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -565,8 +565,8 @@ MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); MODULE_LICENSE("GPL"); -MODULE_PARM(bit_test, "i"); -MODULE_PARM(i2c_debug,"i"); +module_param(bit_test, bool, 0); +module_param(i2c_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); MODULE_PARM_DESC(i2c_debug, diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c index acc7ab6a9..1b2c67c7f 100644 --- a/drivers/i2c/algos/i2c-algo-ite.c +++ b/drivers/i2c/algos/i2c-algo-ite.c @@ -52,21 +52,15 @@ #define PM_IBSR IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 #define GPIO_CCR IT8172_PCI_IO_BASE + IT_GPCCR -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) if (i2c_debug>=1) x #define DEB2(x) if (i2c_debug>=2) x #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ -#define DEBPROTO(x) if (i2c_debug>=9) x; - /* debug the protocol by showing transferred bits */ #define DEF_TIMEOUT 16 -/* ----- global variables --------------------------------------------- */ - /* module parameters: */ -static int i2c_debug=1; -static int iic_test=0; /* see if the line-setting functions work */ +static int i2c_debug; +static int iic_test; /* see if the line-setting functions work */ /* --- setting states on the bus with the right timing: --------------- */ @@ -113,14 +107,6 @@ static int wait_for_bb(struct i2c_algo_iic_data *adap) return(timeout<=0); } -/* - * Puts this process to sleep for a period equal to timeout - */ -static inline void iic_sleep(unsigned long timeout) -{ - schedule_timeout( timeout * HZ); -} - /* After we issue a transaction on the IIC bus, this function * is called. It puts this process to sleep until we get an interrupt from * from the controller telling us that the transaction we requested in complete. @@ -804,8 +790,8 @@ MODULE_AUTHOR("MontaVista Software "); MODULE_DESCRIPTION("ITE iic algorithm"); MODULE_LICENSE("GPL"); -MODULE_PARM(iic_test, "i"); -MODULE_PARM(i2c_debug,"i"); +module_param(iic_test, bool, 0); +module_param(i2c_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); MODULE_PARM_DESC(i2c_debug, diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 38092b7a7..aaad68602 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -249,7 +249,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, break; case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */ - DEB2("NOT ACK recieved after SLA+W\n"); + DEB2("NOT ACK received after SLA+W\n"); pca_stop(adap); return -EREMOTEIO; @@ -277,7 +277,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, return -EREMOTEIO; case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */ - DEB2("NOT ACK recieved after data byte\n"); + DEB2("NOT ACK received after data byte\n"); return -EREMOTEIO; case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */ diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index b53f65a12..6dc807abc 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -38,8 +38,6 @@ #include "i2c-algo-pcf.h" -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) if (i2c_debug>=1) x #define DEB2(x) if (i2c_debug>=2) x #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ #define DEBPROTO(x) if (i2c_debug>=9) x; @@ -48,7 +46,7 @@ /* module parameters: */ -static int i2c_debug=0; +static int i2c_debug; /* --- setting states on the bus with the right timing: --------------- */ @@ -101,12 +99,6 @@ static int wait_for_bb(struct i2c_algo_pcf_data *adap) { } -static inline void pcf_sleep(unsigned long timeout) -{ - schedule_timeout( timeout * HZ); -} - - static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { int timeout = DEF_TIMEOUT; @@ -472,6 +464,6 @@ MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); MODULE_LICENSE("GPL"); -MODULE_PARM(i2c_debug,"i"); +module_param(i2c_debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 3628b099f..d0e7da455 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -40,21 +40,36 @@ config I2C_ALI15X3 will be called i2c-ali15x3. config I2C_AMD756 - tristate "AMD 756/766" - depends on I2C && EXPERIMENTAL + tristate "AMD 756/766/768/8111 and nVidia nForce" + depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the AMD - 756/766/768 mainboard I2C interfaces. + 756/766/768 mainboard I2C interfaces. The driver also includes + support for the first (SMBus 1.0) I2C interface of the AMD 8111 and + the nVidia nForce I2C interface. This driver can also be built as a module. If so, the module will be called i2c-amd756. +config I2C_AMD756_S4882 + tristate "SMBus multiplexing on the Tyan S4882" + depends on I2C_AMD756 && EXPERIMENTAL + help + Enabling this option will add specific SMBus support for the Tyan + S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed + over 8 different channels, where the various memory module EEPROMs + and temperature sensors live. Saying yes here will give you access + to these in addition to the trunk. + + This driver can also be built as a module. If so, the module + will be called i2c-amd756-s4882. + config I2C_AMD8111 tristate "AMD 8111" - depends on I2C && EXPERIMENTAL + depends on I2C && PCI && EXPERIMENTAL help - If you say yes to this option, support will be included for the AMD - 8111 mainboard I2C interfaces. + If you say yes to this option, support will be included for the + second (SMBus 2.0) AMD 8111 mainboard I2C interface. This driver can also be built as a module. If so, the module will be called i2c-amd8111. @@ -164,6 +179,17 @@ config I2C_IXP4XX This support is also available as a module. If so, the module will be called i2c-ixp4xx. +config I2C_IXP2000 + tristate "IXP2000 GPIO-Based I2C Interface" + depends on I2C && ARCH_IXP2000 + select I2C_ALGOBIT + help + Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based + system and are using GPIO lines for an I2C bus. + + This support is also available as a module. If so, the module + will be called i2c-ixp2000. + config I2C_KEYWEST tristate "Powermac Keywest I2C interface" depends on I2C && PPC_PMAC @@ -174,12 +200,25 @@ config I2C_KEYWEST This support is also available as a module. If so, the module will be called i2c-keywest. +config I2C_MPC + tristate "MPC107/824x/85xx/52xx" + depends on I2C && FSL_OCP + help + If you say yes to this option, support will be included for the + built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and + MPC85xx family processors. The driver may also work on 52xx + family processors, though interrupts are known not to work. + + This driver can also be built as a module. If so, the module + will be called i2c-mpc. + config I2C_NFORCE2 tristate "Nvidia Nforce2" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Nvidia Nforce2 family of mainboard I2C interfaces. + This driver also supports the nForce3 Pro 150 MCP. This driver can also be built as a module. If so, the module will be called i2c-nforce2. @@ -266,6 +305,13 @@ config I2C_RPXLITE depends on (RPXLITE || RPXCLASSIC) && I2C select I2C_ALGO8XX +config I2C_S3C2410 + tristate "S3C2410 I2C Driver" + depends on I2C && ARCH_S3C2410 + help + Say Y here to include support for I2C controller in the + Samsung S3C2410 based System-on-Chip devices. + config I2C_SAVAGE4 tristate "S3 Savage 4" depends on I2C && PCI && EXPERIMENTAL @@ -307,7 +353,7 @@ config SCx200_I2C_SDA config SCx200_ACB tristate "NatSemi SCx200 ACCESS.bus" - depends on I2C + depends on I2C && PCI help Enable the use of the ACCESS.bus controllers of a SCx200 processor. @@ -353,6 +399,19 @@ config I2C_SIS96X This driver can also be built as a module. If so, the module will be called i2c-sis96x. +config I2C_STUB + tristate "I2C/SMBus Test Stub" + depends on I2C && EXPERIMENTAL && 'm' + default 'n' + help + This module may be useful to developers of SMBus client drivers, + especially for certain kinds of sensor chips. + + If you do build this module, be sure to read the notes and warnings + in Documentation/i2c/i2c-stub. + + If you don't know what to do here, definitely say N. + config I2C_VIA tristate "VIA 82C586B" depends on I2C && PCI && EXPERIMENTAL @@ -396,4 +455,15 @@ config I2C_VOODOO3 This driver can also be built as a module. If so, the module will be called i2c-voodoo3. +config I2C_PCA_ISA + tristate "PCA9564 on an ISA bus" + depends on I2C + select I2C_ALGOPCA + help + This driver supports ISA boards using the Philips PCA 9564 + Parallel bus to I2C bus controller + + This driver can also be built as a module. If so, the module + will be called i2c-pca-isa. + endmenu diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 83391986c..e414a1d1e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o +obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o @@ -15,18 +16,23 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_ISA) += i2c-isa.o obj-$(CONFIG_I2C_ITE) += i2c-ite.o +obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o +obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o +obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o +obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o +obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index c0a85e2b8..dcc936567 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -137,7 +137,7 @@ static unsigned short ali1535_smba; -DECLARE_MUTEX(i2c_ali1535_sem); +static DECLARE_MUTEX(i2c_ali1535_sem); /* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and @@ -465,7 +465,7 @@ EXIT: } -u32 ali1535_func(struct i2c_adapter *adapter) +static u32 ali1535_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | @@ -496,6 +496,8 @@ static struct pci_device_id ali1535_ids[] = { { }, }; +MODULE_DEVICE_TABLE (pci, ali1535_ids); + static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (ali1535_setup(dev)) { @@ -527,7 +529,7 @@ static struct pci_driver ali1535_driver = { static int __init i2c_ali1535_init(void) { - return pci_module_init(&ali1535_driver); + return pci_register_driver(&ali1535_driver); } static void __exit i2c_ali1535_exit(void) diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index f77ae846e..b3ee9a812 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -394,8 +394,10 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = { {}, }; +MODULE_DEVICE_TABLE (pci, ali1563_id_table); + static struct pci_driver ali1563_pci_driver = { - .name = "i2c-ali1563", + .name = "ali1563_i2c", .id_table = ali1563_id_table, .probe = ali1563_probe, .remove = ali1563_remove, @@ -403,7 +405,7 @@ static struct pci_driver ali1563_pci_driver = { static int __init ali1563_init(void) { - return pci_module_init(&ali1563_pci_driver); + return pci_register_driver(&ali1563_pci_driver); } module_init(ali1563_init); diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index ef4a62524..8e13b8341 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -126,8 +126,8 @@ /* If force_addr is set to anything different from 0, we forcibly enable the device at the given address. */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); +static u16 force_addr = 0; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"); @@ -486,6 +486,8 @@ static struct pci_device_id ali15x3_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, ali15x3_ids); + static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (ali15x3_setup(dev)) { @@ -509,7 +511,7 @@ static void __devexit ali15x3_remove(struct pci_dev *dev) } static struct pci_driver ali15x3_driver = { - .name = "ali15x3 smbus", + .name = "ali15x3_smbus", .id_table = ali15x3_ids, .probe = ali15x3_probe, .remove = __devexit_p(ali15x3_remove), @@ -517,7 +519,7 @@ static struct pci_driver ali15x3_driver = { static int __init i2c_ali15x3_init(void) { - return pci_module_init(&ali15x3_driver); + return pci_register_driver(&ali15x3_driver); } static void __exit i2c_ali15x3_exit(void) diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 4b1151373..35a183519 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -116,14 +116,14 @@ static int amd756_transaction(struct i2c_adapter *adap) int result = 0; int timeout = 0; - dev_dbg(&adap->dev, ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " + dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); /* Make sure the SMBus host is ready to start transmitting */ if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { - dev_dbg(&adap->dev, ": SMBus busy (%04x). Waiting... \n", temp); + dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp); do { msleep(1); temp = inw_p(SMB_GLOBAL_STATUS); @@ -131,7 +131,7 @@ static int amd756_transaction(struct i2c_adapter *adap) (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - dev_dbg(&adap->dev, ": Busy wait timeout (%04x)\n", temp); + dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); goto abort; } timeout = 0; @@ -148,46 +148,46 @@ static int amd756_transaction(struct i2c_adapter *adap) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - dev_dbg(&adap->dev, ": Completion timeout!\n"); + dev_dbg(&adap->dev, "Completion timeout!\n"); goto abort; } if (temp & GS_PRERR_STS) { result = -1; - dev_dbg(&adap->dev, ": SMBus Protocol error (no response)!\n"); + dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); } if (temp & GS_COL_STS) { result = -1; - dev_warn(&adap->dev, " SMBus collision!\n"); + dev_warn(&adap->dev, "SMBus collision!\n"); } if (temp & GS_TO_STS) { result = -1; - dev_dbg(&adap->dev, ": SMBus protocol timeout!\n"); + dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); } if (temp & GS_HCYC_STS) - dev_dbg(&adap->dev, " SMBus protocol success!\n"); + dev_dbg(&adap->dev, "SMBus protocol success!\n"); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); #ifdef DEBUG if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { dev_dbg(&adap->dev, - ": Failed reset at end of transaction (%04x)\n", temp); + "Failed reset at end of transaction (%04x)\n", temp); } #endif dev_dbg(&adap->dev, - ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", + "Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); return result; abort: - dev_warn(&adap->dev, ": Sending abort.\n"); + dev_warn(&adap->dev, "Sending abort\n"); outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); msleep(100); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); @@ -204,7 +204,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, /** TODO: Should I supporte the 10-bit transfers? */ switch (size) { case I2C_SMBUS_PROC_CALL: - dev_dbg(&adap->dev, ": I2C_SMBUS_PROC_CALL not supported!\n"); + dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); /* TODO: Well... It is supported, I'm just not sure what to do here... */ return -1; case I2C_SMBUS_QUICK: @@ -302,7 +302,7 @@ static struct i2c_algorithm smbus_algorithm = { .functionality = amd756_func, }; -static struct i2c_adapter amd756_adapter = { +struct i2c_adapter amd756_smbus = { .owner = THIS_MODULE, .class = I2C_CLASS_HWMON, .algo = &smbus_algorithm, @@ -310,6 +310,10 @@ static struct i2c_adapter amd756_adapter = { }; enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; +static const char* chipname[] = { + "AMD756", "AMD766", "AMD768", + "nVidia nForce", "AMD8111", +}; static struct pci_device_id amd756_ids[] = { {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 }, @@ -320,6 +324,8 @@ static struct pci_device_id amd756_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, amd756_ids); + static int __devinit amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -328,8 +334,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev, u8 temp; if (amd756_ioport) { - dev_err(&pdev->dev, ": Only one device supported. " - "(you have a strange motherboard, btw..)\n"); + dev_err(&pdev->dev, "Only one device supported " + "(you have a strange motherboard, btw)\n"); return -ENODEV; } @@ -346,7 +352,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, pci_read_config_byte(pdev, SMBGCFG, &temp); if ((temp & 128) == 0) { dev_err(&pdev->dev, - ": Error: SMBus controller I/O not enabled!\n"); + "Error: SMBus controller I/O not enabled!\n"); return -ENODEV; } @@ -358,25 +364,25 @@ static int __devinit amd756_probe(struct pci_dev *pdev, } if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) { - dev_err(&pdev->dev, ": SMB region 0x%x already in use!\n", + dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", amd756_ioport); return -ENODEV; } pci_read_config_byte(pdev, SMBREV, &temp); - dev_dbg(&pdev->dev, ": SMBREV = 0x%X\n", temp); - dev_dbg(&pdev->dev, ": AMD756_smba = 0x%X\n", amd756_ioport); + dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); + dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport); /* set up the driverfs linkage to our parent device */ - amd756_adapter.dev.parent = &pdev->dev; + amd756_smbus.dev.parent = &pdev->dev; - snprintf(amd756_adapter.name, I2C_NAME_SIZE, - "SMBus AMD756 adapter at %04x", amd756_ioport); + sprintf(amd756_smbus.name, "SMBus %s adapter at %04x", + chipname[id->driver_data], amd756_ioport); - error = i2c_add_adapter(&amd756_adapter); + error = i2c_add_adapter(&amd756_smbus); if (error) { dev_err(&pdev->dev, - ": Adapter registration failed, module not inserted.\n"); + "Adapter registration failed, module not inserted\n"); goto out_err; } @@ -389,12 +395,12 @@ static int __devinit amd756_probe(struct pci_dev *pdev, static void __devexit amd756_remove(struct pci_dev *dev) { - i2c_del_adapter(&amd756_adapter); + i2c_del_adapter(&amd756_smbus); release_region(amd756_ioport, SMB_IOSIZE); } static struct pci_driver amd756_driver = { - .name = "amd756 smbus", + .name = "amd756_smbus", .id_table = amd756_ids, .probe = amd756_probe, .remove = __devexit_p(amd756_remove), @@ -402,7 +408,7 @@ static struct pci_driver amd756_driver = { static int __init amd756_init(void) { - return pci_module_init(&amd756_driver); + return pci_register_driver(&amd756_driver); } static void __exit amd756_exit(void) @@ -414,5 +420,7 @@ MODULE_AUTHOR("Merlin Hughes "); MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(amd756_smbus); + module_init(amd756_init) module_exit(amd756_exit) diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index b0e597049..5eb4d38bc 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -67,7 +67,7 @@ struct amd_smbus { * ACPI 2.0 chapter 13 access of registers of the EC */ -unsigned int amd_ec_wait_write(struct amd_smbus *smbus) +static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) { int timeout = 500; @@ -82,7 +82,7 @@ unsigned int amd_ec_wait_write(struct amd_smbus *smbus) return 0; } -unsigned int amd_ec_wait_read(struct amd_smbus *smbus) +static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) { int timeout = 500; @@ -97,7 +97,7 @@ unsigned int amd_ec_wait_read(struct amd_smbus *smbus) return 0; } -unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) +static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) { if (amd_ec_wait_write(smbus)) return -1; @@ -114,7 +114,7 @@ unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigne return 0; } -unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) +static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) { if (amd_ec_wait_write(smbus)) return -1; @@ -174,7 +174,7 @@ unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsign #define AMD_SMB_PRTCL_PEC 0x80 -s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, +static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { struct amd_smbus *smbus = adap->algo_data; @@ -315,7 +315,7 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, } -u32 amd8111_func(struct i2c_adapter *adapter) +static u32 amd8111_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | @@ -336,6 +336,8 @@ static struct pci_device_id amd8111_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, amd8111_ids); + static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct amd_smbus *smbus; @@ -392,7 +394,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev) } static struct pci_driver amd8111_driver = { - .name = "amd8111 smbus 2", + .name = "amd8111_smbus2", .id_table = amd8111_ids, .probe = amd8111_probe, .remove = __devexit_p(amd8111_remove), @@ -400,7 +402,7 @@ static struct pci_driver amd8111_driver = { static int __init i2c_amd8111_init(void) { - return pci_module_init(&amd8111_driver); + return pci_register_driver(&amd8111_driver); } diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 768c901a8..2fda2b844 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -59,6 +59,7 @@ static int mmapped; static wait_queue_head_t pcf_wait; static int pcf_pending; +static spinlock_t lock; /* ----- local functions ---------------------------------------------- */ @@ -79,10 +80,10 @@ static void pcf_isa_setbyte(void *data, int ctl, int val) break; case 2: /* double mapped I/O needed for UP2000 board, I don't know why this... */ - writeb(val, address); + writeb(val, (void *)address); /* fall */ case 1: /* memory mapped I/O */ - writeb(val, address); + writeb(val, (void *)address); break; } } @@ -90,7 +91,7 @@ static void pcf_isa_setbyte(void *data, int ctl, int val) static int pcf_isa_getbyte(void *data, int ctl) { int address = ctl ? (base + 1) : base; - int val = mmapped ? readb(address) : inb(address); + int val = mmapped ? readb((void *)address) : inb(address); pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val); @@ -111,14 +112,24 @@ static int pcf_isa_getclock(void *data) static void pcf_isa_waitforpin(void) { int timeout = 2; + long flags; if (irq > 0) { - cli(); + spin_lock_irqsave(&lock, flags); if (pcf_pending == 0) { - interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ ); - } else + spin_unlock_irqrestore(&lock, flags); + if (interruptible_sleep_on_timeout(&pcf_wait, + timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (pcf_pending == 1) { + pcf_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + } else { pcf_pending = 0; - sti(); + spin_unlock_irqrestore(&lock, flags); + } } else { udelay(100); } @@ -126,7 +137,9 @@ static void pcf_isa_waitforpin(void) { static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) { + spin_lock(&lock); pcf_pending = 1; + spin_unlock(&lock); wake_up_interruptible(&pcf_wait); return IRQ_HANDLED; } @@ -134,6 +147,7 @@ static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *r static int pcf_isa_init(void) { + spin_lock_init(&lock); if (!mmapped) { if (!request_region(base, 2, "i2c (isa bus adapter)")) { printk(KERN_ERR @@ -180,11 +194,10 @@ static int __init i2c_pcfisa_init(void) /* check to see we have memory mapped PCF8584 connected to the Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ if (base == 0) { + struct pci_dev *cy693_dev; - struct pci_dev *cy693_dev = - pci_find_device(PCI_VENDOR_ID_CONTAQ, - PCI_DEVICE_ID_CONTAQ_82C693, NULL); - + cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ, + PCI_DEVICE_ID_CONTAQ_82C693, NULL); if (cy693_dev) { char config; /* yeap, we've found cypress, let's check config */ @@ -215,6 +228,7 @@ static int __init i2c_pcfisa_init(void) printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n"); } } + pci_dev_put(cy693_dev); } } #endif @@ -269,11 +283,11 @@ MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); MODULE_LICENSE("GPL"); -MODULE_PARM(base, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(clock, "i"); -MODULE_PARM(own, "i"); -MODULE_PARM(mmapped, "i"); +module_param(base, int, 0); +module_param(irq, int, 0); +module_param(clock, int, 0); +module_param(own, int, 0); +module_param(mmapped, int, 0); module_init(i2c_pcfisa_init); module_exit(i2c_pcfisa_exit); diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index 7d6d69182..7480fd0b4 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -120,6 +120,8 @@ static struct pci_device_id hydra_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, hydra_ids); + static int __devinit hydra_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -158,7 +160,7 @@ static void __devexit hydra_remove(struct pci_dev *dev) static struct pci_driver hydra_driver = { - .name = "hydra smbus", + .name = "hydra_smbus", .id_table = hydra_ids, .probe = hydra_probe, .remove = __devexit_p(hydra_remove), @@ -166,7 +168,7 @@ static struct pci_driver hydra_driver = { static int __init i2c_hydra_init(void) { - return pci_module_init(&hydra_driver); + return pci_register_driver(&hydra_driver); } diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4689bd01d..8d6ec1525 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -98,8 +98,8 @@ /* If force_addr is set to anything different from 0, we forcibly enable the I801 at the given address. VERY DANGEROUS! */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); +static u16 force_addr; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Forcibly enable the I801 at the given address. " "EXTREMELY DANGEROUS!"); @@ -599,6 +599,8 @@ static struct pci_device_id i801_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, i801_ids); + static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -623,7 +625,7 @@ static void __devexit i801_remove(struct pci_dev *dev) } static struct pci_driver i801_driver = { - .name = "i801 smbus", + .name = "i801_smbus", .id_table = i801_ids, .probe = i801_probe, .remove = __devexit_p(i801_remove), @@ -631,7 +633,7 @@ static struct pci_driver i801_driver = { static int __init i2c_i801_init(void) { - return pci_module_init(&i801_driver); + return pci_register_driver(&i801_driver); } static void __exit i2c_i801_exit(void) diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c index fd11366cc..ef358bd9c 100644 --- a/drivers/i2c/busses/i2c-i810.c +++ b/drivers/i2c/busses/i2c-i810.c @@ -70,7 +70,7 @@ #define CYCLE_DELAY 10 #define TIMEOUT (HZ / 2) -static void *ioaddr; +static void __iomem *ioaddr; /* The i810 GPIO registers have individual masks for each bit so we never have to read before writing. Nice. */ @@ -201,6 +201,8 @@ static struct pci_device_id i810_ids[] __devinitdata = { { 0, }, }; +MODULE_DEVICE_TABLE (pci, i810_ids); + static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; @@ -231,7 +233,7 @@ static void __devexit i810_remove(struct pci_dev *dev) } static struct pci_driver i810_driver = { - .name = "i810 smbus", + .name = "i810_smbus", .id_table = i810_ids, .probe = i810_probe, .remove = __devexit_p(i810_remove), @@ -239,7 +241,7 @@ static struct pci_driver i810_driver = { static int __init i2c_i810_init(void) { - return pci_module_init(&i810_driver); + return pci_register_driver(&i810_driver); } static void __exit i2c_i810_exit(void) diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index a25218dba..8168f2d3b 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -50,12 +50,12 @@ MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); MODULE_LICENSE("GPL"); -static int iic_force_poll = 0; -MODULE_PARM(iic_force_poll, "i"); +static int iic_force_poll; +module_param(iic_force_poll, bool, 0); MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); -static int iic_force_fast = 0; -MODULE_PARM(iic_force_fast, "i"); +static int iic_force_fast; +module_param(iic_force_fast, bool, 0); MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)"); #define DBG_LEVEL 0 @@ -81,7 +81,7 @@ MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)"); #if DBG_LEVEL > 2 static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" @@ -132,7 +132,7 @@ static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) */ static void iic_dev_init(struct ibm_iic_private* dev) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; DBG("%d: init\n", dev->idx); @@ -177,7 +177,7 @@ static void iic_dev_init(struct ibm_iic_private* dev) */ static void iic_dev_reset(struct ibm_iic_private* dev) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; int i; u8 dc; @@ -225,7 +225,7 @@ static void iic_dev_reset(struct ibm_iic_private* dev) */ /* Wait for SCL and/or SDA to be high */ -static int iic_dc_wait(volatile struct iic_regs *iic, u8 mask) +static int iic_dc_wait(volatile struct iic_regs __iomem *iic, u8 mask) { unsigned long x = jiffies + HZ / 28 + 2; while ((in_8(&iic->directcntl) & mask) != mask){ @@ -238,7 +238,7 @@ static int iic_dc_wait(volatile struct iic_regs *iic, u8 mask) static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p) { - volatile struct iic_regs* iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0]; u8 mask, v, sda; int i, res; @@ -324,7 +324,7 @@ err: static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) { struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; - volatile struct iic_regs* iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", dev->idx, in_8(&iic->sts), in_8(&iic->extsts)); @@ -342,7 +342,7 @@ static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) */ static int iic_xfer_result(struct ibm_iic_private* dev) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; if (unlikely(in_8(&iic->sts) & STS_ERR)){ DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, @@ -375,7 +375,7 @@ static int iic_xfer_result(struct ibm_iic_private* dev) */ static void iic_abort_xfer(struct ibm_iic_private* dev) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; unsigned long x; DBG("%d: iic_abort_xfer\n", dev->idx); @@ -407,25 +407,17 @@ static void iic_abort_xfer(struct ibm_iic_private* dev) */ static int iic_wait_for_tc(struct ibm_iic_private* dev){ - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; int ret = 0; if (dev->irq >= 0){ /* Interrupt mode */ - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - add_wait_queue(&dev->wq, &wait); - set_current_state(TASK_INTERRUPTIBLE); - if (in_8(&iic->sts) & STS_PT) - schedule_timeout(dev->adap.timeout * HZ); - set_current_state(TASK_RUNNING); - remove_wait_queue(&dev->wq, &wait); - - if (unlikely(signal_pending(current))){ + ret = wait_event_interruptible_timeout(dev->wq, + !(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ); + + if (unlikely(ret < 0)) DBG("%d: wait interrupted\n", dev->idx); - ret = -ERESTARTSYS; - } else if (unlikely(in_8(&iic->sts) & STS_PT)){ + else if (unlikely(in_8(&iic->sts) & STS_PT)){ DBG("%d: wait timeout\n", dev->idx); ret = -ETIMEDOUT; } @@ -466,7 +458,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, int combined_xfer) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; char* buf = pm->buf; int i, j, loops, ret = 0; int len = pm->len; @@ -482,7 +474,7 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, if (!(cntl & CNTL_RW)) for (j = 0; j < count; ++j) - out_8((volatile u8*)&iic->mdbuf, *buf++); + out_8((void __iomem *)&iic->mdbuf, *buf++); if (i < loops - 1) cmd |= CNTL_CHT; @@ -513,7 +505,7 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, if (cntl & CNTL_RW) for (j = 0; j < count; ++j) - *buf++ = in_8((volatile u8*)&iic->mdbuf); + *buf++ = in_8((void __iomem *)&iic->mdbuf); } return ret > 0 ? 0 : ret; @@ -524,7 +516,7 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, */ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) { - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; u16 addr = msg->addr; DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, @@ -560,7 +552,7 @@ static inline int iic_address_neq(const struct i2c_msg* p1, static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap)); - volatile struct iic_regs *iic = dev->vaddr; + volatile struct iic_regs __iomem *iic = dev->vaddr; int i, ret = 0; DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num); @@ -763,9 +755,9 @@ fail: free_irq(dev->irq, dev); } - iounmap((void*)dev->vaddr); + iounmap(dev->vaddr); fail2: - ocp_set_drvdata(ocp, 0); + ocp_set_drvdata(ocp, NULL); kfree(dev); return ret; } @@ -791,7 +783,7 @@ static void __devexit iic_remove(struct ocp_device *ocp) iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); } - iounmap((void*)dev->vaddr); + iounmap(dev->vaddr); kfree(dev); } } diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h index d365498ab..d819a955d 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.h +++ b/drivers/i2c/busses/i2c-ibm_iic.h @@ -45,7 +45,7 @@ struct iic_regs { struct ibm_iic_private { struct i2c_adapter adap; - volatile struct iic_regs *vaddr; + volatile struct iic_regs __iomem *vaddr; wait_queue_head_t wq; int idx; int irq; diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 917759c42..62638115c 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -54,14 +54,15 @@ #define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ #define DEFAULT_OWN 0x55 -static int base = 0; -static int irq = 0; -static int clock = 0; -static int own = 0; +static int base; +static int irq; +static int clock; +static int own; static struct iic_ite gpi; static wait_queue_head_t iic_wait; static int iic_pending; +static spinlock_t lock; /* ----- local functions ---------------------------------------------- */ @@ -102,20 +103,13 @@ static int iic_ite_getclock(void *data) } -#if 0 -static void iic_ite_sleep(unsigned long timeout) -{ - schedule_timeout( timeout * HZ); -} -#endif - - /* Put this process to sleep. We will wake up when the * IIC controller interrupts. */ static void iic_ite_waitforpin(void) { int timeout = 2; + long flags; /* If interrupts are enabled (which they are), then put the process to * sleep. This process will be awakened by two events -- either the @@ -124,24 +118,36 @@ static void iic_ite_waitforpin(void) { * of time and return. */ if (gpi.iic_irq > 0) { - cli(); + spin_lock_irqsave(&lock, flags); if (iic_pending == 0) { - interruptible_sleep_on_timeout(&iic_wait, timeout*HZ ); - } else + spin_unlock_irqrestore(&lock, flags); + if (interruptible_sleep_on_timeout(&iic_wait, timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (iic_pending == 1) { + iic_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + } else { iic_pending = 0; - sti(); + spin_unlock_irqrestore(&lock, flags); + } } else { udelay(100); } } -static void iic_ite_handler(int this_irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t iic_ite_handler(int this_irq, void *dev_id, + struct pt_regs *regs) { - - iic_pending = 1; + spin_lock(&lock); + iic_pending = 1; + spin_unlock(&lock); + + wake_up_interruptible(&iic_wait); - wake_up_interruptible(&iic_wait); + return IRQ_HANDLED; } @@ -229,6 +235,7 @@ static int __init iic_ite_init(void) iic_ite_data.data = (void *)piic; init_waitqueue_head(&iic_wait); + spin_lock_init(&lock); if (iic_hw_resrc_init() == 0) { if (i2c_iic_add_bus(&iic_ite_ops) < 0) return -ENODEV; @@ -254,10 +261,10 @@ MODULE_AUTHOR("MontaVista Software "); MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); MODULE_LICENSE("GPL"); -MODULE_PARM(base, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(clock, "i"); -MODULE_PARM(own, "i"); +module_param(base, int, 0); +module_param(irq, int, 0); +module_param(clock, int, 0); +module_param(own, int, 0); /* Called when module is loaded or when kernel is initialized. diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c index 0b606e88d..bc94b8cd3 100644 --- a/drivers/i2c/busses/i2c-keywest.c +++ b/drivers/i2c/busses/i2c-keywest.c @@ -88,12 +88,12 @@ static const char *__kw_state_names[] = { }; #endif /* DEBUG */ +static int probe; + MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("I2C driver for Apple's Keywest"); MODULE_LICENSE("GPL"); -MODULE_PARM(probe, "i"); - -static int probe = 0; +module_param(probe, bool, 0); #ifdef POLLED_MODE /* Don't schedule, the g5 fan controller is too @@ -552,9 +552,9 @@ create_iface(struct device_node *np, struct device *dev) iface->irq = np->intrs[0].line; iface->channels = (struct keywest_chan *) (((unsigned long)(iface + 1) + 3UL) & ~3UL); - iface->base = (unsigned long)ioremap(np->addrs[0].address + addroffset, + iface->base = ioremap(np->addrs[0].address + addroffset, np->addrs[0].size); - if (iface->base == 0) { + if (!iface->base) { printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); kfree(iface); pmac_low_i2c_unlock(np); @@ -600,7 +600,7 @@ create_iface(struct device_node *np, struct device *dev) rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface); if (rc) { printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); - iounmap((void *)iface->base); + iounmap(iface->base); kfree(iface); pmac_low_i2c_unlock(np); return -ENODEV; @@ -662,8 +662,7 @@ dispose_iface(struct device *dev) spin_lock_irq(&iface->lock); while (iface->state != state_idle) { spin_unlock_irq(&iface->lock); - set_task_state(current,TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); spin_lock_irq(&iface->lock); } #endif /* POLLED_MODE */ @@ -686,7 +685,7 @@ dispose_iface(struct device *dev) if (rc) printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); } - iounmap((void *)iface->base); + iounmap(iface->base); dev_set_drvdata(dev, NULL); of_node_put(iface->node); kfree(iface); diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h index ecc279d5c..c5022e1ca 100644 --- a/drivers/i2c/busses/i2c-keywest.h +++ b/drivers/i2c/busses/i2c-keywest.h @@ -52,7 +52,7 @@ typedef enum { struct keywest_iface { struct device_node *node; - unsigned long base; + void __iomem * base; unsigned bsteps; int irq; spinlock_t lock; @@ -89,13 +89,13 @@ struct keywest_chan static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg) { - return in_8(((volatile u8 *)iface->base) + return in_8(iface->base + (((unsigned)reg) << iface->bsteps)); } static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val) { - out_8(((volatile u8 *)iface->base) + out_8(iface->base + (((unsigned)reg) << iface->bsteps), val); (void)__read_reg(iface, reg_subaddr); } diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index f77245e56..ca9e203b7 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -23,6 +23,7 @@ #include #include #include +#include #define MPC_I2C_ADDR 0x00 #define MPC_I2C_FDR 0x04 @@ -91,9 +92,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) x = readb(i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR); } else { + set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&i2c->queue, &wait); while (!(i2c->interrupt & CSR_MIF)) { - set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { pr_debug("I2C: Interrupted\n"); result = -EINTR; @@ -104,9 +105,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) result = -EIO; break; } - schedule_timeout(timeout); + msleep_interruptible(jiffies_to_msecs(timeout)); } - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&i2c->queue, &wait); x = i2c->interrupt; i2c->interrupt = 0; diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 774a7ef52..cc7ab3143 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -1,6 +1,7 @@ /* SMBus driver for nVidia nForce2 MCP + Added nForce3 Pro 150 Thomas Leibold , Ported to 2.5 Patrick Dreker , Copyright (c) 2003 Hans-Frieder Vogt , Based on @@ -23,8 +24,10 @@ */ /* - SUPPORTED DEVICES PCI ID - nForce2 MCP 0064 + SUPPORTED DEVICES PCI ID + nForce2 MCP 0064 + nForce2 Ultra 400 MCP 0084 + nForce3 Pro150 MCP 00D4 This driver supports the 2 SMBuses that are included in the MCP2 of the nForce2 chipset. @@ -49,11 +52,6 @@ MODULE_AUTHOR ("Hans-Frieder Vogt "); MODULE_DESCRIPTION("nForce2 SMBus driver"); -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 -#endif - - struct nforce2_smbus { struct pci_dev *dev; struct i2c_adapter adapter; @@ -244,8 +242,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, temp = inb_p(NVIDIA_SMB_STS); } if (~temp & NVIDIA_SMB_STS_DONE) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/100); + msleep(10); temp = inb_p(NVIDIA_SMB_STS); } @@ -295,10 +292,17 @@ static u32 nforce2_func(struct i2c_adapter *adapter) static struct pci_device_id nforce2_ids[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0 } }; +MODULE_DEVICE_TABLE (pci, nforce2_ids); + + static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, struct nforce2_smbus *smbus, char *name) { @@ -384,7 +388,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev) } static struct pci_driver nforce2_driver = { - .name = "nForce2 SMBus", + .name = "nForce2_smbus", .id_table = nforce2_ids, .probe = nforce2_probe, .remove = __devexit_p(nforce2_remove), @@ -392,7 +396,7 @@ static struct pci_driver nforce2_driver = { static int __init nforce2_init(void) { - return pci_module_init(&nforce2_driver); + return pci_register_driver(&nforce2_driver); } static void __exit nforce2_exit(void) diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 6798954f0..cb5e72230 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -36,8 +36,8 @@ #define DEFAULT_BASE 0x378 -static int base; -MODULE_PARM(base, "i"); +static u16 base; +module_param(base, ushort, 0); MODULE_PARM_DESC(base, "Base I/O address"); /* ----- Low-level parallel port access ----------------------------------- */ diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h index 284d3f5d3..f63a53779 100644 --- a/drivers/i2c/busses/i2c-parport.h +++ b/drivers/i2c/busses/i2c-parport.h @@ -83,7 +83,7 @@ static struct adapter_parm adapter_parm[] = { }; static int type; -MODULE_PARM(type, "i"); +module_param(type, int, 0); MODULE_PARM_DESC(type, "Type of adapter:\n" " 0 = Philips adapter\n" diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index e7c0262b0..8bb467ade 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -459,6 +459,8 @@ static struct pci_device_id piix4_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, piix4_ids); + static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -493,7 +495,7 @@ static void __devexit piix4_remove(struct pci_dev *dev) } static struct pci_driver piix4_driver = { - .name = "piix4-smbus", + .name = "piix4_smbus", .id_table = piix4_ids, .probe = piix4_probe, .remove = __devexit_p(piix4_remove), @@ -501,7 +503,7 @@ static struct pci_driver piix4_driver = { static int __init i2c_piix4_init(void) { - return pci_module_init(&piix4_driver); + return pci_register_driver(&piix4_driver); } static void __exit i2c_piix4_exit(void) diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c index 0aabe49e5..f5804568b 100644 --- a/drivers/i2c/busses/i2c-prosavage.c +++ b/drivers/i2c/busses/i2c-prosavage.c @@ -68,7 +68,7 @@ #define MAX_BUSSES 2 struct s_i2c_bus { - void *mmvga; + void __iomem *mmvga; int i2c_reg; int adap_ok; struct i2c_adapter adap; @@ -76,7 +76,7 @@ struct s_i2c_bus { }; struct s_i2c_chip { - void *mmio; + void __iomem *mmio; struct s_i2c_bus i2c_bus[MAX_BUSSES]; }; @@ -181,7 +181,7 @@ static int bit_s3via_getsda(void *bus) /* * adapter initialisation */ -static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg) +static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg) { int ret; p->adap.owner = THIS_MODULE; @@ -228,7 +228,7 @@ static void prosavage_remove(struct pci_dev *dev) ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); if (ret) { - dev_err(&dev->dev, ": %s not removed\n", + dev_err(&dev->dev, "%s not removed\n", chip->i2c_bus[i].adap.name); } } @@ -298,7 +298,7 @@ static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_devic } return 0; err_adap: - dev_err(&dev->dev, ": %s failed\n", bus->adap.name); + dev_err(&dev->dev, "%s failed\n", bus->adap.name); prosavage_remove(dev); return ret; } @@ -313,8 +313,10 @@ static struct pci_device_id prosavage_pci_tbl[] = { { 0, }, }; +MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); + static struct pci_driver prosavage_driver = { - .name = "prosavage-smbus", + .name = "prosavage_smbus", .id_table = prosavage_pci_tbl, .probe = prosavage_probe, .remove = prosavage_remove, @@ -322,7 +324,7 @@ static struct pci_driver prosavage_driver = { static int __init i2c_prosavage_init(void) { - return pci_module_init(&prosavage_driver); + return pci_register_driver(&prosavage_driver); } static void __exit i2c_prosavage_exit(void) diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c index 33972a779..092d0323c 100644 --- a/drivers/i2c/busses/i2c-savage4.c +++ b/drivers/i2c/busses/i2c-savage4.c @@ -73,7 +73,7 @@ #define TIMEOUT (HZ / 2) -static void *ioaddr; +static void __iomem *ioaddr; /* The sav GPIO registers don't have individual masks for each bit so we always have to read before writing. */ @@ -157,6 +157,8 @@ static struct pci_device_id savage4_ids[] __devinitdata = { { 0, } }; +MODULE_DEVICE_TABLE (pci, savage4_ids); + static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; @@ -178,7 +180,7 @@ static void __devexit savage4_remove(struct pci_dev *dev) } static struct pci_driver savage4_driver = { - .name = "savage4 smbus", + .name = "savage4_smbus", .id_table = savage4_ids, .probe = savage4_probe, .remove = __devexit_p(savage4_remove), @@ -186,7 +188,7 @@ static struct pci_driver savage4_driver = { static int __init i2c_savage4_init(void) { - return pci_module_init(&savage4_driver); + return pci_register_driver(&savage4_driver); } static void __exit i2c_savage4_exit(void) diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index a5040cca3..9836b1ee0 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -124,8 +124,8 @@ static int blacklist[] = { /* If force_addr is set to anything different from 0, we forcibly enable the device at the given address. */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); +static u16 force_addr = 0; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"); static unsigned short sis5595_base = 0; @@ -371,6 +371,8 @@ static struct pci_device_id sis5595_ids[] __devinitdata = { { 0, } }; +MODULE_DEVICE_TABLE (pci, sis5595_ids); + static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (sis5595_setup(dev)) { @@ -393,7 +395,7 @@ static void __devexit sis5595_remove(struct pci_dev *dev) } static struct pci_driver sis5595_driver = { - .name = "sis5595 smbus", + .name = "sis5595_smbus", .id_table = sis5595_ids, .probe = sis5595_probe, .remove = __devexit_p(sis5595_remove), @@ -401,7 +403,7 @@ static struct pci_driver sis5595_driver = { static int __init i2c_sis5595_init(void) { - return pci_module_init(&sis5595_driver); + return pci_register_driver(&sis5595_driver); } static void __exit i2c_sis5595_exit(void) diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 437ee28d3..58df63df1 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -94,11 +94,11 @@ #define SIS630_BLOCK_DATA 0x05 /* insmod parameters */ -static int high_clock = 0; -static int force = 0; -MODULE_PARM(high_clock, "i"); +static int high_clock; +static int force; +module_param(high_clock, bool, 0); MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); -MODULE_PARM(force, "i"); +module_param(force, bool, 0); MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); /* acpi base address */ @@ -145,7 +145,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock); /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */ - if (high_clock > 0) + if (high_clock) sis630_write(SMB_CNT, 0x20); else sis630_write(SMB_CNT, (*oldclock & ~0x40)); @@ -210,7 +210,7 @@ static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock) * restore old Host Master Clock if high_clock is set * and oldclock was not 56KHz */ - if (high_clock > 0 && !(oldclock & 0x20)) + if (high_clock && !(oldclock & 0x20)) sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20)); dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); @@ -401,7 +401,7 @@ static int sis630_setup(struct pci_dev *sis630_dev) if (dummy) { pci_dev_put(dummy); } - else if (force > 0) { + else if (force) { dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but " "loading because of force option enabled\n"); } @@ -464,9 +464,12 @@ static struct i2c_adapter sis630_adapter = { static struct pci_device_id sis630_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, { 0, } }; +MODULE_DEVICE_TABLE (pci, sis630_ids); + static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (sis630_setup(dev)) { @@ -494,7 +497,7 @@ static void __devexit sis630_remove(struct pci_dev *dev) static struct pci_driver sis630_driver = { - .name = "sis630 smbus", + .name = "sis630_smbus", .id_table = sis630_ids, .probe = sis630_probe, .remove = __devexit_p(sis630_remove), @@ -502,7 +505,7 @@ static struct pci_driver sis630_driver = { static int __init i2c_sis630_init(void) { - return pci_module_init(&sis630_driver); + return pci_register_driver(&sis630_driver); } diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index c71daa347..69a2e7d7e 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -278,6 +278,8 @@ static struct pci_device_id sis96x_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, sis96x_ids); + static int __devinit sis96x_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -339,7 +341,7 @@ static void __devexit sis96x_remove(struct pci_dev *dev) } static struct pci_driver sis96x_driver = { - .name = "sis96x smbus", + .name = "sis96x_smbus", .id_table = sis96x_ids, .probe = sis96x_probe, .remove = __devexit_p(sis96x_remove), @@ -348,7 +350,7 @@ static struct pci_driver sis96x_driver = { static int __init i2c_sis96x_init(void) { printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION); - return pci_module_init(&sis96x_driver); + return pci_register_driver(&sis96x_driver); } static void __exit i2c_sis96x_exit(void) diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index fba8f0eae..2cbc4cd22 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -99,6 +99,8 @@ static struct pci_device_id vt586b_ids[] __devinitdata = { { 0, } }; +MODULE_DEVICE_TABLE (pci, vt586b_ids); + static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) { u16 base; @@ -158,7 +160,7 @@ static void __devexit vt586b_remove(struct pci_dev *dev) static struct pci_driver vt586b_driver = { - .name = "vt586b smbus", + .name = "vt586b_smbus", .id_table = vt586b_ids, .probe = vt586b_probe, .remove = __devexit_p(vt586b_remove), @@ -166,7 +168,7 @@ static struct pci_driver vt586b_driver = { static int __init i2c_vt586b_init(void) { - return pci_module_init(&vt586b_driver); + return pci_register_driver(&vt586b_driver); } static void __exit i2c_vt586b_exit(void) diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index fbd4a15d8..83a77ba97 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -92,13 +92,13 @@ static unsigned short smb_cf_hstcfg = 0xD2; /* If force is set to anything different from 0, we forcibly enable the VT596. DANGEROUS! */ static int force; -MODULE_PARM(force, "i"); +module_param(force, bool, 0); MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!"); /* If force_addr is set to anything different from 0, we forcibly enable the VT596 at the given address. VERY DANGEROUS! */ -static int force_addr; -MODULE_PARM(force_addr, "i"); +static u16 force_addr; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Forcibly enable the SMBus at the given address. " "EXTREMELY DANGEROUS!"); @@ -454,8 +454,10 @@ static struct pci_device_id vt596_ids[] = { { 0, } }; +MODULE_DEVICE_TABLE (pci, vt596_ids); + static struct pci_driver vt596_driver = { - .name = "vt596 smbus", + .name = "vt596_smbus", .id_table = vt596_ids, .probe = vt596_probe, .remove = __devexit_p(vt596_remove), @@ -463,7 +465,7 @@ static struct pci_driver vt596_driver = { static int __init i2c_vt596_init(void) { - return pci_module_init(&vt596_driver); + return pci_register_driver(&vt596_driver); } diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c index efb677d24..3edf0e341 100644 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ b/drivers/i2c/busses/i2c-voodoo3.c @@ -61,7 +61,7 @@ #define TIMEOUT (HZ / 2) -static void *ioaddr; +static void __iomem *ioaddr; /* The voo GPIO registers don't have individual masks for each bit so we always have to read before writing. */ @@ -195,6 +195,8 @@ static struct pci_device_id voodoo3_ids[] __devinitdata = { { 0, } }; +MODULE_DEVICE_TABLE (pci, voodoo3_ids); + static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; @@ -224,7 +226,7 @@ static void __devexit voodoo3_remove(struct pci_dev *dev) } static struct pci_driver voodoo3_driver = { - .name = "voodoo3 smbus", + .name = "voodoo3_smbus", .id_table = voodoo3_ids, .probe = voodoo3_probe, .remove = __devexit_p(voodoo3_remove), @@ -232,7 +234,7 @@ static struct pci_driver voodoo3_driver = { static int __init i2c_voodoo3_init(void) { - return pci_module_init(&voodoo3_driver); + return pci_register_driver(&voodoo3_driver); } static void __exit i2c_voodoo3_exit(void) diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index b3cbbb9ea..1c4159a93 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ MODULE_LICENSE("GPL"); #define MAX_DEVICES 4 static int base[MAX_DEVICES] = { 0x820, 0x840 }; -MODULE_PARM(base, "1-4i"); +module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); #ifdef DEBUG @@ -254,7 +255,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - schedule_timeout(HZ/100+1); + msleep(10); } scx200_acb_timeout(iface); @@ -401,9 +402,9 @@ static struct i2c_algorithm scx200_acb_algorithm = { .functionality = scx200_acb_func, }; -struct scx200_acb_iface *scx200_acb_list; +static struct scx200_acb_iface *scx200_acb_list; -int scx200_acb_probe(struct scx200_acb_iface *iface) +static int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; @@ -501,6 +502,12 @@ static int __init scx200_acb_create(int base, int index) return rc; } +static struct pci_device_id scx200[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, + { }, +}; + static int __init scx200_acb_init(void) { int i; @@ -509,12 +516,7 @@ static int __init scx200_acb_init(void) pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); /* Verify that this really is a SCx200 processor */ - if (pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SCx200_BRIDGE, - NULL) == NULL - && pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SC1100_BRIDGE, - NULL) == NULL) + if (pci_dev_present(scx200) == 0) return -ENODEV; rc = -ENXIO; diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c index b472fe81a..27fbfecc4 100644 --- a/drivers/i2c/busses/scx200_i2c.c +++ b/drivers/i2c/busses/scx200_i2c.c @@ -38,14 +38,14 @@ MODULE_AUTHOR("Christer Weinigel "); MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(scl, "i"); -MODULE_PARM_DESC(scl, "GPIO line for SCL"); -MODULE_PARM(sda, "i"); -MODULE_PARM_DESC(sda, "GPIO line for SDA"); - static int scl = CONFIG_SCx200_I2C_SCL; static int sda = CONFIG_SCx200_I2C_SDA; +module_param(scl, int, 0); +MODULE_PARM_DESC(scl, "GPIO line for SCL"); +module_param(sda, int, 0); +MODULE_PARM_DESC(sda, "GPIO line for SDA"); + static void scx200_i2c_setscl(void *data, int state) { scx200_gpio_set(scl, state); @@ -86,7 +86,7 @@ static struct i2c_adapter scx200_i2c_ops = { .name = "NatSemi SCx200 I2C", }; -int scx200_i2c_init(void) +static int scx200_i2c_init(void) { pr_debug(NAME ": NatSemi SCx200 I2C Driver\n"); @@ -115,7 +115,7 @@ int scx200_i2c_init(void) return 0; } -void scx200_i2c_cleanup(void) +static void scx200_i2c_cleanup(void) { i2c_bit_del_bus(&scx200_i2c_ops); } diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index af8d273d0..f1f35409a 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -32,6 +32,15 @@ config SENSORS_ADM1025 This driver can also be built as a module. If so, the module will be called adm1025. +config SENSORS_ADM1026 + tristate "Analog Devices ADM1026 and compatibles" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for Analog Devices ADM1026 + This driver can also be built as a module. If so, the module + will be called adm1026. + config SENSORS_ADM1031 tristate "Analog Devices ADM1031 and compatibles" depends on I2C && EXPERIMENTAL @@ -97,6 +106,19 @@ config SENSORS_IT87 This driver can also be built as a module. If so, the module will be called it87. +config SENSORS_LM63 + tristate "National Semiconductor LM63" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for the National Semiconductor + LM63 remote diode digital temperature sensor with integrated fan + control. Such chips are found on the Tyan S4882 (Thunder K8QS Pro) + motherboard, among others. + + This driver can also be built as a module. If so, the module + will be called lm63. + config SENSORS_LM75 tristate "National Semiconductor LM75 and compatibles" depends on I2C && EXPERIMENTAL @@ -149,7 +171,7 @@ config SENSORS_LM80 config SENSORS_LM83 tristate "National Semiconductor LM83" - depends on I2C && EXPERIMENTAL + depends on I2C select I2C_SENSOR help If you say yes here you get support for National Semiconductor @@ -169,6 +191,17 @@ config SENSORS_LM85 This driver can also be built as a module. If so, the module will be called lm85. +config SENSORS_LM87 + tristate "National Semiconductor LM87" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for National Semiconductor LM87 + sensor chips. + + This driver can also be built as a module. If so, the module + will be called lm87. + config SENSORS_LM90 tristate "National Semiconductor LM90 and compatibles" depends on I2C @@ -191,6 +224,34 @@ config SENSORS_MAX1619 This driver can also be built as a module. If so, the module will be called max1619. +config SENSORS_PC87360 + tristate "National Semiconductor PC87360 family" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + select I2C_ISA + help + If you say yes here you get access to the hardware monitoring + functions of the National Semiconductor PC8736x Super-I/O chips. + The PC87360, PC87363 and PC87364 only have fan monitoring and + control. The PC87365 and PC87366 additionally have voltage and + temperature monitoring. + + This driver can also be built as a module. If so, the module + will be called pc87360. + +config SENSORS_SMSC47M1 + tristate "SMSC LPC47M10x and compatibles" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + select I2C_ISA + help + If you say yes here you get support for the integrated fan + monitoring and control capabilities of the SMSC LPC47B27x, + LPC47M10x, LPC47M13x and LPC47M14x chips. + + This driver can also be built as a module. If so, the module + will be called smsc47m1. + config SENSORS_VIA686A tristate "VIA686A" depends on I2C && PCI && EXPERIMENTAL @@ -286,4 +347,16 @@ config SENSORS_RTC8564 This driver can also be built as a module. If so, the module will be called i2c-rtc8564. +config ISP1301_OMAP + tristate "Philips ISP1301 with OMAP OTG" + depends on I2C && ARCH_OMAP_OTG + help + If you say yes here you get support for the Philips ISP1301 + USB-On-The-Go transceiver working with the OMAP OTG controller. + The ISP1301 is used in products including H2 and H3 development + boards for Texas Instruments OMAP processors. + + This driver can also be built as a module. If so, the module + will be called isp1301_omap. + endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index f024e71a5..90dd7dd0c 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -9,26 +9,33 @@ obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o +obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_IT87) += it87.o +obj-$(CONFIG_SENSORS_LM63) += lm63.o obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM77) += lm77.o obj-$(CONFIG_SENSORS_LM78) += lm78.o obj-$(CONFIG_SENSORS_LM80) += lm80.o obj-$(CONFIG_SENSORS_LM83) += lm83.o obj-$(CONFIG_SENSORS_LM85) += lm85.o +obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o +obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o +obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o +obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG endif + diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 73ca01db6..714b4aba9 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -40,12 +40,11 @@ #define ADM1021_ALARM_RTEMP_NA 0x04 /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b, - 0x4c, 0x4e, I2C_CLIENT_END -}; +static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, + 0x29, 0x2a, 0x2b, + 0x4c, 0x4d, 0x4e, + I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066); @@ -148,7 +147,7 @@ static struct i2c_driver adm1021_driver = { .detach_client = adm1021_detach_client, }; -static int adm1021_id = 0; +static int adm1021_id; #define show(value) \ static ssize_t show_##value(struct device *dev, char *buf) \ @@ -418,7 +417,7 @@ MODULE_AUTHOR ("Frodo Looijaard and " MODULE_DESCRIPTION("adm1021 driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(read_only, "i"); +module_param(read_only, bool, 0); MODULE_PARM_DESC(read_only, "Don't set any values, read only mode"); module_init(sensors_adm1021_init) diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c index d38336fbc..4f410885b 100644 --- a/drivers/i2c/chips/adm1025.c +++ b/drivers/i2c/chips/adm1025.c @@ -59,10 +59,8 @@ * NE1619 has two possible addresses: 0x2c and 0x2d. */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* * Insmod parameters @@ -153,7 +151,7 @@ struct adm1025_data { * Internal variables */ -static int adm1025_id = 0; +static int adm1025_id; /* * Sysfs stuff @@ -212,8 +210,8 @@ static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct adm1025_data *data = i2c_get_clientdata(client); \ - data->in_min[offset] = IN_TO_REG(simple_strtol(buf, NULL, 10), \ - in_scale[offset]); \ + long val = simple_strtol(buf, NULL, 10); \ + data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ data->in_min[offset]); \ return count; \ @@ -223,8 +221,8 @@ static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct adm1025_data *data = i2c_get_clientdata(client); \ - data->in_max[offset] = IN_TO_REG(simple_strtol(buf, NULL, 10), \ - in_scale[offset]); \ + long val = simple_strtol(buf, NULL, 10); \ + data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ data->in_max[offset]); \ return count; \ @@ -246,7 +244,8 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct adm1025_data *data = i2c_get_clientdata(client); \ - data->temp_min[offset-1] = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->temp_min[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ data->temp_min[offset-1]); \ return count; \ @@ -256,7 +255,8 @@ static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct adm1025_data *data = i2c_get_clientdata(client); \ - data->temp_max[offset-1] = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->temp_max[offset-1] = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ data->temp_max[offset-1]); \ return count; \ @@ -455,7 +455,7 @@ static void adm1025_init_client(struct i2c_client *client) struct adm1025_data *data = i2c_get_clientdata(client); int i; - data->vrm = 82; + data->vrm = i2c_which_vrm(); /* * Set high limits diff --git a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c index 23c323e80..69f4d1e29 100644 --- a/drivers/i2c/chips/adm1031.c +++ b/drivers/i2c/chips/adm1031.c @@ -57,10 +57,8 @@ #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_2(adm1030, adm1031); @@ -298,12 +296,12 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr) #define fan_auto_channel_offset(offset) \ static ssize_t show_fan_auto_channel_##offset (struct device *dev, char *buf) \ { \ - return show_fan_auto_channel(dev, buf, 0x##offset - 1); \ + return show_fan_auto_channel(dev, buf, offset - 1); \ } \ static ssize_t set_fan_auto_channel_##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_auto_channel(dev, buf, count, 0x##offset - 1); \ + return set_fan_auto_channel(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(auto_fan##offset##_channel, S_IRUGO | S_IWUSR, \ show_fan_auto_channel_##offset, \ @@ -365,25 +363,25 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr) #define auto_temp_reg(offset) \ static ssize_t show_auto_temp_##offset##_off (struct device *dev, char *buf) \ { \ - return show_auto_temp_off(dev, buf, 0x##offset - 1); \ + return show_auto_temp_off(dev, buf, offset - 1); \ } \ static ssize_t show_auto_temp_##offset##_min (struct device *dev, char *buf) \ { \ - return show_auto_temp_min(dev, buf, 0x##offset - 1); \ + return show_auto_temp_min(dev, buf, offset - 1); \ } \ static ssize_t show_auto_temp_##offset##_max (struct device *dev, char *buf) \ { \ - return show_auto_temp_max(dev, buf, 0x##offset - 1); \ + return show_auto_temp_max(dev, buf, offset - 1); \ } \ static ssize_t set_auto_temp_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_auto_temp_min(dev, buf, count, 0x##offset - 1); \ + return set_auto_temp_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_auto_temp_##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_auto_temp_max(dev, buf, count, 0x##offset - 1); \ + return set_auto_temp_max(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ show_auto_temp_##offset##_off, NULL); \ @@ -429,14 +427,14 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr) #define pwm_reg(offset) \ static ssize_t show_pwm_##offset (struct device *dev, char *buf) \ { \ - return show_pwm(dev, buf, 0x##offset - 1); \ + return show_pwm(dev, buf, offset - 1); \ } \ static ssize_t set_pwm_##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_pwm(dev, buf, count, 0x##offset - 1); \ + return set_pwm(dev, buf, count, offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ +static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_pwm_##offset, set_pwm_##offset) pwm_reg(1); @@ -565,25 +563,25 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr) #define fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset - 1); \ + return show_fan(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset - 1); \ + return show_fan_min(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ { \ - return show_fan_div(dev, buf, 0x##offset - 1); \ + return show_fan_div(dev, buf, offset - 1); \ } \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_fan_##offset##_div (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_div(dev, buf, count, 0x##offset - 1); \ + return set_fan_div(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, \ NULL); \ @@ -675,34 +673,34 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr) #define temp_reg(offset) \ static ssize_t show_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset - 1); \ + return show_temp(dev, buf, offset - 1); \ } \ static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \ { \ - return show_temp_min(dev, buf, 0x##offset - 1); \ + return show_temp_min(dev, buf, offset - 1); \ } \ static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \ { \ - return show_temp_max(dev, buf, 0x##offset - 1); \ + return show_temp_max(dev, buf, offset - 1); \ } \ static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf) \ { \ - return show_temp_crit(dev, buf, 0x##offset - 1); \ + return show_temp_crit(dev, buf, offset - 1); \ } \ static ssize_t set_temp_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_min(dev, buf, count, 0x##offset - 1); \ + return set_temp_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_temp_##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_max(dev, buf, count, 0x##offset - 1); \ + return set_temp_max(dev, buf, count, offset - 1); \ } \ static ssize_t set_temp_##offset##_crit (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_crit(dev, buf, count, 0x##offset - 1); \ + return set_temp_crit(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, \ NULL); \ @@ -799,7 +797,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(&new_client->dev, &dev_attr_fan1_input); device_create_file(&new_client->dev, &dev_attr_fan1_div); device_create_file(&new_client->dev, &dev_attr_fan1_min); - device_create_file(&new_client->dev, &dev_attr_fan1_pwm); + device_create_file(&new_client->dev, &dev_attr_pwm1); device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel); device_create_file(&new_client->dev, &dev_attr_temp1_input); device_create_file(&new_client->dev, &dev_attr_temp1_min); @@ -826,7 +824,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(&new_client->dev, &dev_attr_fan2_input); device_create_file(&new_client->dev, &dev_attr_fan2_div); device_create_file(&new_client->dev, &dev_attr_fan2_min); - device_create_file(&new_client->dev, &dev_attr_fan2_pwm); + device_create_file(&new_client->dev, &dev_attr_pwm2); device_create_file(&new_client->dev, &dev_attr_auto_fan2_channel); device_create_file(&new_client->dev, &dev_attr_temp3_input); diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c index a416e4ee5..eba1584d7 100644 --- a/drivers/i2c/chips/asb100.c +++ b/drivers/i2c/chips/asb100.c @@ -56,15 +56,11 @@ #define ASB100_VERSION "1.0.0" /* I2C addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x28, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, I2C_CLIENT_END }; /* ISA addresses to scan (none) */ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; - -/* default VRM to 9.0 instead of 8.2 */ -#define ASB100_DEFAULT_VRM 90 /* Insmod parameters */ SENSORS_INSMOD_1(asb100); @@ -269,29 +265,29 @@ set_in_reg(MAX, max) static ssize_t \ show_in##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ show_in##offset, NULL); \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ - return show_in_min(dev, buf, 0x##offset); \ + return show_in_min(dev, buf, offset); \ } \ static ssize_t \ show_in##offset##_max (struct device *dev, char *buf) \ { \ - return show_in_max(dev, buf, 0x##offset); \ + return show_in_max(dev, buf, offset); \ } \ static ssize_t set_in##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_min(dev, buf, count, 0x##offset); \ + return set_in_min(dev, buf, count, offset); \ } \ static ssize_t set_in##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_max(dev, buf, count, 0x##offset); \ + return set_in_max(dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ show_in##offset##_min, set_in##offset##_min); \ @@ -523,9 +519,9 @@ static ssize_t show_vid(struct device *dev, char *buf) return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref) +device_create_file(&client->dev, &dev_attr_cpu0_vid) /* VRM */ static ssize_t show_vrm(struct device *dev, char *buf) @@ -594,12 +590,12 @@ static ssize_t set_pwm_enable1(struct device *dev, const char *buf, return count; } -static DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); -static DEVICE_ATTR(fan1_pwm_enable, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); +static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable1, set_pwm_enable1); #define device_create_file_pwm1(client) do { \ - device_create_file(&new_client->dev, &dev_attr_fan1_pwm); \ - device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); \ + device_create_file(&new_client->dev, &dev_attr_pwm1); \ + device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \ } while (0) /* This function is called when: @@ -959,7 +955,7 @@ static void asb100_init_client(struct i2c_client *client) vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f; vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4; - data->vrm = ASB100_DEFAULT_VRM; + data->vrm = i2c_which_vrm(); vid = vid_from_reg(vid, data->vrm); /* Start monitoring */ diff --git a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c index bf3e21495..bb0df88a9 100644 --- a/drivers/i2c/chips/ds1621.c +++ b/drivers/i2c/chips/ds1621.c @@ -29,15 +29,14 @@ #include "lm75.h" /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(ds1621); static int polarity = -1; -MODULE_PARM(polarity, "i"); +module_param(polarity, int, 0); MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); /* Many DS1621 constants specified below */ @@ -96,7 +95,7 @@ static struct i2c_driver ds1621_driver = { .detach_client = ds1621_detach_client, }; -static int ds1621_id = 0; +static int ds1621_id; /* All registers are word-sized, except for the configuration register. DS1621 uses a high-byte first convention, which is exactly opposite to diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 6617ff76c..94c8698ab 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -36,16 +36,15 @@ #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x50, 0x57, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(eeprom); static int checksum = 0; -MODULE_PARM(checksum, "i"); +module_param(checksum, bool, 0); MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct"); @@ -86,7 +85,7 @@ static struct i2c_driver eeprom_driver = { .detach_client = eeprom_detach_client, }; -static int eeprom_id = 0; +static int eeprom_id; static void eeprom_update_client(struct i2c_client *client, u8 slice) { diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c index ab5b70f86..f41ab9fd6 100644 --- a/drivers/i2c/chips/fscher.c +++ b/drivers/i2c/chips/fscher.c @@ -38,9 +38,7 @@ */ static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* * Insmod parameters @@ -156,7 +154,7 @@ struct fscher_data { * Internal variables */ -static int fscher_id = 0; +static int fscher_id; /* * Sysfs stuff diff --git a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c index 3481ddbf0..c4e914ba2 100644 --- a/drivers/i2c/chips/gl518sm.c +++ b/drivers/i2c/chips/gl518sm.c @@ -45,9 +45,7 @@ /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80); @@ -164,7 +162,7 @@ static struct i2c_driver gl518_driver = { * Internal variables */ -static int gl518_id = 0; +static int gl518_id; /* * Sysfs stuff @@ -217,7 +215,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct gl518_data *data = i2c_get_clientdata(client); \ - data->value = type##_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = type##_TO_REG(val); \ gl518_write_value(client, reg, data->value); \ return count; \ } @@ -229,7 +228,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \ struct i2c_client *client = to_i2c_client(dev); \ struct gl518_data *data = i2c_get_clientdata(client); \ int regvalue = gl518_read_value(client, reg); \ - data->value = type##_TO_REG(simple_strtoul(buf, NULL, 10)); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + data->value = type##_TO_REG(val); \ regvalue = (regvalue & ~mask) | (data->value << shift); \ gl518_write_value(client, reg, regvalue); \ return count; \ diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index ef6562987..36d84634d 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -37,17 +37,19 @@ #include #include #include +#include #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x20, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ -SENSORS_INSMOD_1(it87); +SENSORS_INSMOD_2(it87, it8712); #define REG 0x2e /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ @@ -55,13 +57,6 @@ SENSORS_INSMOD_1(it87); #define PME 0x04 /* The device with the fan registers in it */ #define DEVID 0x20 /* Register: Device ID */ -static inline void -superio_outb(int reg, int val) -{ - outb(reg, REG); - outb(val, VAL); -} - static inline int superio_inb(int reg) { @@ -104,6 +99,10 @@ static int update_vbat; /* Reset the registers on init if true */ static int reset; +/* Chip Type */ + +static u16 chip_type; + /* Many IT87 constants specified below */ /* Length of ISA address segment */ @@ -163,8 +162,6 @@ static inline u8 FAN_TO_REG(long rpm, int div) ((val)+500)/1000),-128,127)) #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) -#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\ - 205-(val)*5) #define ALARMS_FROM_REG(val) (val) static int DIV_TO_REG(int val) @@ -201,6 +198,7 @@ struct it87_data { u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ + int vrm; u32 alarms; /* Register encoding, combined */ }; @@ -226,7 +224,7 @@ static struct i2c_driver it87_driver = { .detach_client = it87_detach_client, }; -static int it87_id = 0; +static int it87_id; static ssize_t show_in(struct device *dev, char *buf, int nr) { @@ -273,7 +271,7 @@ static ssize_t set_in_max(struct device *dev, const char *buf, static ssize_t \ show_in##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); @@ -281,22 +279,22 @@ static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ - return show_in_min(dev, buf, 0x##offset); \ + return show_in_min(dev, buf, offset); \ } \ static ssize_t \ show_in##offset##_max (struct device *dev, char *buf) \ { \ - return show_in_max(dev, buf, 0x##offset); \ + return show_in_max(dev, buf, offset); \ } \ static ssize_t set_in##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_min(dev, buf, count, 0x##offset); \ + return set_in_min(dev, buf, count, offset); \ } \ static ssize_t set_in##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_max(dev, buf, count, 0x##offset); \ + return set_in_max(dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ show_in##offset##_min, set_in##offset##_min); \ @@ -360,27 +358,27 @@ static ssize_t set_temp_min(struct device *dev, const char *buf, #define show_temp_offset(offset) \ static ssize_t show_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset - 1); \ + return show_temp(dev, buf, offset - 1); \ } \ static ssize_t \ show_temp_##offset##_max (struct device *dev, char *buf) \ { \ - return show_temp_max(dev, buf, 0x##offset - 1); \ + return show_temp_max(dev, buf, offset - 1); \ } \ static ssize_t \ show_temp_##offset##_min (struct device *dev, char *buf) \ { \ - return show_temp_min(dev, buf, 0x##offset - 1); \ + return show_temp_min(dev, buf, offset - 1); \ } \ static ssize_t set_temp_##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_max(dev, buf, count, 0x##offset - 1); \ + return set_temp_max(dev, buf, count, offset - 1); \ } \ static ssize_t set_temp_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_min(dev, buf, count, 0x##offset - 1); \ + return set_temp_min(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ @@ -423,12 +421,12 @@ static ssize_t set_sensor(struct device *dev, const char *buf, #define show_sensor_offset(offset) \ static ssize_t show_sensor_##offset (struct device *dev, char *buf) \ { \ - return show_sensor(dev, buf, 0x##offset - 1); \ + return show_sensor(dev, buf, offset - 1); \ } \ static ssize_t set_sensor_##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_sensor(dev, buf, count, 0x##offset - 1); \ + return set_sensor(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ show_sensor_##offset, set_sensor_##offset); @@ -505,25 +503,25 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, #define show_fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset - 1); \ + return show_fan(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset - 1); \ + return show_fan_min(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ { \ - return show_fan_div(dev, buf, 0x##offset - 1); \ + return show_fan_div(dev, buf, offset - 1); \ } \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_fan_##offset##_div (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_div(dev, buf, count, 0x##offset - 1); \ + return set_fan_div(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ @@ -543,6 +541,38 @@ static ssize_t show_alarms(struct device *dev, char *buf) } static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL); +static ssize_t +show_vrm_reg(struct device *dev, char *buf) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%ld\n", (long) data->vrm); +} +static ssize_t +store_vrm_reg(struct device *dev, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + u32 val; + + val = simple_strtoul(buf, NULL, 10); + data->vrm = val; + + return count; +} +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); +#define device_create_file_vrm(client) \ +device_create_file(&client->dev, &dev_attr_vrm) + +static ssize_t +show_vid_reg(struct device *dev, char *buf) +{ + struct it87_data *data = it87_update_device(dev); + return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); +#define device_create_file_vid(client) \ +device_create_file(&client->dev, &dev_attr_cpu0_vid) + /* This function is called when: * it87_driver is inserted (when this module is loaded), for each available adapter @@ -560,9 +590,9 @@ static int it87_find(int *address) u16 val; superio_enter(); - val = (superio_inb(DEVID) << 8) | + chip_type = (superio_inb(DEVID) << 8) | superio_inb(DEVID + 1); - if (val != IT8712F_DEVID) { + if (chip_type != IT8712F_DEVID) { superio_exit(); return -ENODEV; } @@ -660,6 +690,8 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) i = it87_read_value(new_client, IT87_REG_CHIPID); if (i == 0x90) { kind = it87; + if ((is_isa) && (chip_type == IT8712F_DEVID)) + kind = it8712; } else { if (kind == 0) @@ -674,6 +706,8 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) if (kind == it87) { name = "it87"; + } else if (kind == it8712) { + name = "it8712"; } /* Fill in the remaining client fields and put it into the global list */ @@ -741,6 +775,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(&new_client->dev, &dev_attr_fan3_div); device_create_file(&new_client->dev, &dev_attr_alarms); + if (data->type == it8712) { + device_create_file_vrm(new_client); + device_create_file_vid(new_client); + data->vrm = i2c_which_vrm(); + } + return 0; ERROR2: @@ -910,7 +950,11 @@ static struct it87_data *it87_update_device(struct device *dev) (it87_read_value(client, IT87_REG_ALARM3) << 16); data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); - + /* The 8705 does not have VID capability */ + if (data->type == it8712) { + data->vid = it87_read_value(client, IT87_REG_VID); + data->vid &= 0x1f; + } data->last_updated = jiffies; data->valid = 1; } @@ -938,9 +982,9 @@ static void __exit sm_it87_exit(void) MODULE_AUTHOR("Chris Gauthron "); MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver"); -MODULE_PARM(update_vbat, "i"); +module_param(update_vbat, bool, 0); MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); -MODULE_PARM(reset, "i"); +module_param(reset, bool, 0); MODULE_PARM_DESC(reset, "Reset the chip's registers, default no"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c index 3752a2706..a5d32245f 100644 --- a/drivers/i2c/chips/lm75.c +++ b/drivers/i2c/chips/lm75.c @@ -28,10 +28,9 @@ /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(lm75); @@ -74,7 +73,7 @@ static struct i2c_driver lm75_driver = { .detach_client = lm75_detach_client, }; -static int lm75_id = 0; +static int lm75_id; #define show(value) \ static ssize_t show_##value(struct device *dev, char *buf) \ diff --git a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c index a6fc78105..71cf3799c 100644 --- a/drivers/i2c/chips/lm77.c +++ b/drivers/i2c/chips/lm77.c @@ -34,10 +34,8 @@ /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x48, 0x4b, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(lm77); @@ -83,7 +81,7 @@ static struct i2c_driver lm77_driver = { .detach_client = lm77_detach_client, }; -static int lm77_id = 0; +static int lm77_id; /* straight from the datasheet */ #define LM77_TEMP_MIN (-55000) diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c index 40385ffd8..a145346b3 100644 --- a/drivers/i2c/chips/lm78.c +++ b/drivers/i2c/chips/lm78.c @@ -27,10 +27,11 @@ #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x20, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_3(lm78, lm78j, lm79); @@ -229,29 +230,29 @@ static ssize_t set_in_max(struct device *dev, const char *buf, static ssize_t \ show_in##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ show_in##offset, NULL); \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ - return show_in_min(dev, buf, 0x##offset); \ + return show_in_min(dev, buf, offset); \ } \ static ssize_t \ show_in##offset##_max (struct device *dev, char *buf) \ { \ - return show_in_max(dev, buf, 0x##offset); \ + return show_in_max(dev, buf, offset); \ } \ static ssize_t set_in##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_min(dev, buf, count, 0x##offset); \ + return set_in_min(dev, buf, count, offset); \ } \ static ssize_t set_in##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_max(dev, buf, count, 0x##offset); \ + return set_in_max(dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ show_in##offset##_min, set_in##offset##_min); \ @@ -375,20 +376,20 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, #define show_fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset - 1); \ + return show_fan(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset - 1); \ + return show_fan_min(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ { \ - return show_fan_div(dev, buf, 0x##offset - 1); \ + return show_fan_div(dev, buf, offset - 1); \ } \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ @@ -423,7 +424,7 @@ static ssize_t show_vid(struct device *dev, char *buf) struct lm78_data *data = lm78_update_device(dev); return sprintf(buf, "%d\n", VID_FROM_REG(data->vid)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); /* Alarms */ static ssize_t show_alarms(struct device *dev, char *buf) @@ -615,7 +616,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(&new_client->dev, &dev_attr_fan3_min); device_create_file(&new_client->dev, &dev_attr_fan3_div); device_create_file(&new_client->dev, &dev_attr_alarms); - device_create_file(&new_client->dev, &dev_attr_in0_ref); + device_create_file(&new_client->dev, &dev_attr_cpu0_vid); return 0; @@ -692,26 +693,12 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) /* Called when we have found a new LM78. It should set limits, etc. */ static void lm78_init_client(struct i2c_client *client) { - struct lm78_data *data = i2c_get_clientdata(client); - int vid; - - /* Reset all except Watchdog values and last conversion values - This sets fan-divs to 2, among others */ - lm78_write_value(client, LM78_REG_CONFIG, 0x80); - - vid = lm78_read_value(client, LM78_REG_VID_FANDIV) & 0x0f; - if (data->type == lm79) - vid |= - (lm78_read_value(client, LM78_REG_CHIPID) & 0x01) << 4; - else - vid |= 0x10; - vid = VID_FROM_REG(vid); + u8 config = lm78_read_value(client, LM78_REG_CONFIG); /* Start monitoring */ - lm78_write_value(client, LM78_REG_CONFIG, - (lm78_read_value(client, LM78_REG_CONFIG) & 0xf7) - | 0x01); - + if (!(config & 0x01)) + lm78_write_value(client, LM78_REG_CONFIG, + (config & 0xf7) | 0x01); } static struct lm78_data *lm78_update_device(struct device *dev) diff --git a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c index fe78d98a6..c13d515c5 100644 --- a/drivers/i2c/chips/lm80.c +++ b/drivers/i2c/chips/lm80.c @@ -29,10 +29,9 @@ #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x28, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(lm80); @@ -145,7 +144,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); * Internal variables */ -static int lm80_id = 0; +static int lm80_id; /* * Driver data (common to all clients) @@ -262,14 +261,15 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, { struct i2c_client *client = to_i2c_client(dev); struct lm80_data *data = i2c_get_clientdata(client); - unsigned long min; + unsigned long min, val; u8 reg; /* Save fan_min */ min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10)); + val = simple_strtoul(buf, NULL, 10); + data->fan_div[nr] = DIV_TO_REG(val); reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1))); diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c index f6023e989..552321e05 100644 --- a/drivers/i2c/chips/lm83.c +++ b/drivers/i2c/chips/lm83.c @@ -40,11 +40,11 @@ * addresses. */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b, - 0x4c, 0x4e, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, + 0x29, 0x2a, 0x2b, + 0x4c, 0x4d, 0x4e, + I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* * Insmod parameters @@ -80,11 +80,14 @@ SENSORS_INSMOD_1(lm83); /* * Conversions and various macros - * The LM83 uses signed 8-bit values. + * The LM83 uses signed 8-bit values with LSB = 1 degree Celcius. */ -#define TEMP_FROM_REG(val) ((val > 127 ? val-256 : val) * 1000) -#define TEMP_TO_REG(val) ((val < 0 ? val+256 : val) / 1000) +#define TEMP_FROM_REG(val) ((val) * 1000) +#define TEMP_TO_REG(val) ((val) <= -128000 ? -128 : \ + (val) >= 127000 ? 127 : \ + (val) < 0 ? ((val) - 500) / 1000 : \ + ((val) + 500) / 1000) static const u8 LM83_REG_R_TEMP[] = { LM83_REG_R_LOCAL_TEMP, @@ -140,9 +143,9 @@ struct lm83_data { unsigned long last_updated; /* in jiffies */ /* registers values */ - u8 temp_input[4]; - u8 temp_high[4]; - u8 temp_crit; + s8 temp_input[4]; + s8 temp_high[4]; + s8 temp_crit; u16 alarms; /* bitvector, combined */ }; @@ -150,7 +153,7 @@ struct lm83_data { * Internal variables */ -static int lm83_id = 0; +static int lm83_id; /* * Sysfs stuff @@ -178,7 +181,8 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct lm83_data *data = i2c_get_clientdata(client); \ - data->value = TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ return count; \ } @@ -206,8 +210,11 @@ static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_high3, set_temp_high3); static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4, set_temp_high4); -static DEVICE_ATTR(temp_crit, S_IWUSR | S_IRUGO, show_temp_crit, +static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL); +static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL); +static DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp_crit, set_temp_crit); +static DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); /* @@ -259,6 +266,11 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) * means that the driver was loaded with the force parameter and a * given kind of chip is requested, so both the detection and the * identification steps are skipped. */ + + /* Default to an LM83 if forced */ + if (kind == 0) + kind = lm83; + if (kind < 0) { /* detection */ if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) != 0x00) || @@ -322,7 +334,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev, &dev_attr_temp3_max); device_create_file(&new_client->dev, &dev_attr_temp4_max); - device_create_file(&new_client->dev, &dev_attr_temp_crit); + device_create_file(&new_client->dev, &dev_attr_temp1_crit); + device_create_file(&new_client->dev, &dev_attr_temp2_crit); + device_create_file(&new_client->dev, &dev_attr_temp3_crit); + device_create_file(&new_client->dev, &dev_attr_temp4_crit); device_create_file(&new_client->dev, &dev_attr_alarms); return 0; diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c index 11f850431..60e71d36f 100644 --- a/drivers/i2c/chips/lm85.c +++ b/drivers/i2c/chips/lm85.c @@ -4,6 +4,7 @@ Copyright (c) 1998, 1999 Frodo Looijaard Copyright (c) 2002, 2003 Philip Pokorny Copyright (c) 2003 Margit Schubert-While + Copyright (c) 2004 Justin Thiessen Chip details at @@ -29,17 +30,10 @@ #include #include #include -/* -#include -*/ - -#undef LM85EXTENDEDFUNC /* Extended functionality */ /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463); @@ -163,8 +157,6 @@ static int lm85_scaling[] = { /* .001 Volts */ #define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03) -#ifdef LM85EXTENDEDFUNC /* Extended functionality */ - /* ZONEs have the following parameters: * Limit (low) temp, 1. degC * Hysteresis (below limit), 1. degC (0-15) @@ -183,20 +175,32 @@ static int lm85_scaling[] = { /* .001 Volts */ * Filter constant (or disabled) .1 seconds */ -/* These are the zone temperature range encodings */ -static int lm85_range_map[] = { /* .1 degC */ - 20, 25, 33, 40, 50, 66, - 80, 100, 133, 160, 200, 266, - 320, 400, 533, 800 +/* These are the zone temperature range encodings in .001 degree C */ +static int lm85_range_map[] = { + 2000, 2500, 3300, 4000, 5000, 6600, + 8000, 10000, 13300, 16000, 20000, 26600, + 32000, 40000, 53300, 80000 }; static int RANGE_TO_REG( int range ) { int i; - if( range >= lm85_range_map[15] ) { return 15 ; } - for( i = 0 ; i < 15 ; ++i ) - if( range <= lm85_range_map[i] ) - break ; + if ( range < lm85_range_map[0] ) { + return 0 ; + } else if ( range > lm85_range_map[15] ) { + return 15 ; + } else { /* find closest match */ + for ( i = 14 ; i >= 0 ; --i ) { + if ( range > lm85_range_map[i] ) { /* range bracketed */ + if ((lm85_range_map[i+1] - range) < + (range - lm85_range_map[i])) { + i++; + break; + } + break; + } + } + } return( i & 0x0f ); } #define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f]) @@ -206,41 +210,9 @@ static int RANGE_TO_REG( int range ) * MSB (bit 3, value 8). If the enable bit is 0, the encoded value * is ignored, or set to 0. */ -static int lm85_smooth_map[] = { /* .1 sec */ - 350, 176, 118, 70, 44, 30, 16, 8 -/* 35.4 * 1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48 */ - }; -static int SMOOTH_TO_REG( int smooth ) -{ - int i; - - if( smooth <= 0 ) { return 0 ; } /* Disabled */ - for( i = 0 ; i < 7 ; ++i ) - if( smooth >= lm85_smooth_map[i] ) - break ; - return( (i & 0x07) | 0x08 ); -} -#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0) - -/* These are the fan spinup delay time encodings */ -static int lm85_spinup_map[] = { /* .1 sec */ - 0, 1, 2, 4, 7, 10, 20, 40 - }; -static int SPINUP_TO_REG( int spinup ) -{ - int i; - - if( spinup >= lm85_spinup_map[7] ) { return 7 ; } - for( i = 0 ; i < 7 ; ++i ) - if( spinup <= lm85_spinup_map[i] ) - break ; - return( i & 0x07 ); -} -#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07]) - /* These are the PWM frequency encodings */ static int lm85_freq_map[] = { /* .1 Hz */ - 100, 150, 230, 300, 380, 470, 620, 980 + 100, 150, 230, 300, 380, 470, 620, 940 }; static int FREQ_TO_REG( int freq ) { @@ -266,13 +238,9 @@ static int FREQ_TO_REG( int freq ) * -2 -- PWM responds to manual control */ -#endif /* Extended functionality */ - static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 }; #define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07]) -#ifdef LM85EXTENDEDFUNC /* Extended functionality */ - static int ZONE_TO_REG( int zone ) { int i; @@ -285,10 +253,8 @@ static int ZONE_TO_REG( int zone ) return( (i & 0x07)<<5 ); } -#endif /* Extended functionality */ - -#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15)) -#define HYST_FROM_REG(val) (-(val)*10) +#define HYST_TO_REG(val) (SENSORS_LIMIT(((val)+500)/1000,0,15)) +#define HYST_FROM_REG(val) ((val)*1000) #define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127)) #define OFFSET_FROM_REG(val) ((val)*25) @@ -308,9 +274,6 @@ static int ZONE_TO_REG( int zone ) * version of the driver. */ -/* Typically used with Pentium 4 systems v9.1 VRM spec */ -#define LM85_INIT_VRM 91 - /* Chip sampling rates * * Some sensors are not updated more frequently than once per second @@ -341,6 +304,14 @@ struct lm85_zone { u8 hyst; /* Low limit hysteresis. (0-15) */ u8 range; /* Temp range, encoded */ s8 critical; /* "All fans ON" temp limit */ + u8 off_desired; /* Actual "off" temperature specified. Preserved + * to prevent "drift" as other autofan control + * values change. + */ + u8 max_desired; /* Actual "max" temperature specified. Preserved + * to prevent "drift" as other autofan control + * values change. + */ }; struct lm85_autofan { @@ -408,7 +379,7 @@ static struct i2c_driver lm85_driver = { }; /* Unique ID assigned to each LM85 detected */ -static int lm85_id = 0; +static int lm85_id; /* 4 Fans */ @@ -440,18 +411,19 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, #define show_fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset - 1); \ + return show_fan(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset - 1); \ + return show_fan_min(dev, buf, offset - 1); \ } \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ +static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, \ + NULL); \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_fan_##offset##_min, set_fan_##offset##_min); @@ -468,7 +440,7 @@ static ssize_t show_vid_reg(struct device *dev, char *buf) return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, char *buf) { @@ -530,20 +502,21 @@ static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) #define show_pwm_reg(offset) \ static ssize_t show_pwm_##offset (struct device *dev, char *buf) \ { \ - return show_pwm(dev, buf, 0x##offset - 1); \ + return show_pwm(dev, buf, offset - 1); \ } \ static ssize_t set_pwm_##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_pwm(dev, buf, count, 0x##offset - 1); \ + return set_pwm(dev, buf, count, offset - 1); \ } \ static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \ { \ - return show_pwm_enable(dev, buf, 0x##offset - 1); \ + return show_pwm_enable(dev, buf, offset - 1); \ } \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ +static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_pwm_##offset, set_pwm_##offset); \ -static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO, show_pwm_enable##offset, NULL); +static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO, \ + show_pwm_enable##offset, NULL); show_pwm_reg(1); show_pwm_reg(2); @@ -597,27 +570,28 @@ static ssize_t set_in_max(struct device *dev, const char *buf, #define show_in_reg(offset) \ static ssize_t show_in_##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static ssize_t show_in_##offset##_min (struct device *dev, char *buf) \ { \ - return show_in_min(dev, buf, 0x##offset); \ + return show_in_min(dev, buf, offset); \ } \ static ssize_t show_in_##offset##_max (struct device *dev, char *buf) \ { \ - return show_in_max(dev, buf, 0x##offset); \ + return show_in_max(dev, buf, offset); \ } \ static ssize_t set_in_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_min(dev, buf, count, 0x##offset); \ + return set_in_min(dev, buf, count, offset); \ } \ static ssize_t set_in_##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_max(dev, buf, count, 0x##offset); \ + return set_in_max(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, NULL); \ +static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, \ + NULL); \ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ show_in_##offset##_min, set_in_##offset##_min); \ static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ @@ -677,27 +651,28 @@ static ssize_t set_temp_max(struct device *dev, const char *buf, #define show_temp_reg(offset) \ static ssize_t show_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset - 1); \ + return show_temp(dev, buf, offset - 1); \ } \ static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \ { \ - return show_temp_min(dev, buf, 0x##offset - 1); \ + return show_temp_min(dev, buf, offset - 1); \ } \ static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \ { \ - return show_temp_max(dev, buf, 0x##offset - 1); \ + return show_temp_max(dev, buf, offset - 1); \ } \ static ssize_t set_temp_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_min(dev, buf, count, 0x##offset - 1); \ + return set_temp_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_temp_##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_max(dev, buf, count, 0x##offset - 1); \ + return set_temp_max(dev, buf, count, offset - 1); \ } \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \ +static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, \ + NULL); \ static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ show_temp_##offset##_min, set_temp_##offset##_min); \ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ @@ -708,8 +683,334 @@ show_temp_reg(2); show_temp_reg(3); +/* Automatic PWM control */ + +static ssize_t show_pwm_auto_channels(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", ZONE_FROM_REG(data->autofan[nr].config)); +} +static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) + | ZONE_TO_REG(val) ; + lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), + data->autofan[nr].config); + up(&data->update_lock); + return count; +} +static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", PWM_FROM_REG(data->autofan[nr].min_pwm)); +} +static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->autofan[nr].min_pwm = PWM_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), + data->autofan[nr].min_pwm); + up(&data->update_lock); + return count; +} +static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", data->autofan[nr].min_off); +} +static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->autofan[nr].min_off = val; + lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] + | data->syncpwm3 + | (data->autofan[0].min_off ? 0x20 : 0) + | (data->autofan[1].min_off ? 0x40 : 0) + | (data->autofan[2].min_off ? 0x80 : 0) + ); + up(&data->update_lock); + return count; +} +static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", FREQ_FROM_REG(data->autofan[nr].freq)); +} +static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->autofan[nr].freq = FREQ_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), + (data->zone[nr].range << 4) + | data->autofan[nr].freq + ); + up(&data->update_lock); + return count; +} +#define pwm_auto(offset) \ +static ssize_t show_pwm##offset##_auto_channels (struct device *dev, \ + char *buf) \ +{ \ + return show_pwm_auto_channels(dev, buf, offset - 1); \ +} \ +static ssize_t set_pwm##offset##_auto_channels (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_pwm_auto_channels(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev, \ + char *buf) \ +{ \ + return show_pwm_auto_pwm_min(dev, buf, offset - 1); \ +} \ +static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_pwm_auto_pwm_min(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev, \ + char *buf) \ +{ \ + return show_pwm_auto_pwm_minctl(dev, buf, offset - 1); \ +} \ +static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_pwm_auto_pwm_minctl(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev, \ + char *buf) \ +{ \ + return show_pwm_auto_pwm_freq(dev, buf, offset - 1); \ +} \ +static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_pwm_auto_pwm_freq(dev, buf, count, offset - 1); \ +} \ +static DEVICE_ATTR(pwm##offset##_auto_channels, S_IRUGO | S_IWUSR, \ + show_pwm##offset##_auto_channels, \ + set_pwm##offset##_auto_channels); \ +static DEVICE_ATTR(pwm##offset##_auto_pwm_min, S_IRUGO | S_IWUSR, \ + show_pwm##offset##_auto_pwm_min, \ + set_pwm##offset##_auto_pwm_min); \ +static DEVICE_ATTR(pwm##offset##_auto_pwm_minctl, S_IRUGO | S_IWUSR, \ + show_pwm##offset##_auto_pwm_minctl, \ + set_pwm##offset##_auto_pwm_minctl); \ +static DEVICE_ATTR(pwm##offset##_auto_pwm_freq, S_IRUGO | S_IWUSR, \ + show_pwm##offset##_auto_pwm_freq, \ + set_pwm##offset##_auto_pwm_freq); +pwm_auto(1); +pwm_auto(2); +pwm_auto(3); + +/* Temperature settings for automatic PWM control */ + +static ssize_t show_temp_auto_temp_off(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) - + HYST_FROM_REG(data->zone[nr].hyst)); +} +static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int min, val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + min = TEMP_FROM_REG(data->zone[nr].limit); + data->zone[nr].off_desired = TEMP_TO_REG(val); + data->zone[nr].hyst = HYST_TO_REG(min - val); + if ( nr == 0 || nr == 1 ) { + lm85_write_value(client, LM85_REG_AFAN_HYST1, + (data->zone[0].hyst << 4) + | data->zone[1].hyst + ); + } else { + lm85_write_value(client, LM85_REG_AFAN_HYST2, + (data->zone[2].hyst << 4) + ); + } + up(&data->update_lock); + return count; +} +static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) ); +} +static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->zone[nr].limit = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), + data->zone[nr].limit); + +/* Update temp_auto_max and temp_auto_range */ + data->zone[nr].range = RANGE_TO_REG( + TEMP_FROM_REG(data->zone[nr].max_desired) - + TEMP_FROM_REG(data->zone[nr].limit)); + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), + ((data->zone[nr].range & 0x0f) << 4) + | (data->autofan[nr].freq & 0x07)); + +/* Update temp_auto_hyst and temp_auto_off */ + data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG( + data->zone[nr].limit) - TEMP_FROM_REG( + data->zone[nr].off_desired)); + if ( nr == 0 || nr == 1 ) { + lm85_write_value(client, LM85_REG_AFAN_HYST1, + (data->zone[0].hyst << 4) + | data->zone[1].hyst + ); + } else { + lm85_write_value(client, LM85_REG_AFAN_HYST2, + (data->zone[2].hyst << 4) + ); + } + up(&data->update_lock); + return count; +} +static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) + + RANGE_FROM_REG(data->zone[nr].range)); +} +static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int min, val; + + down(&data->update_lock); + min = TEMP_FROM_REG(data->zone[nr].limit); + val = simple_strtol(buf, NULL, 10); + data->zone[nr].max_desired = TEMP_TO_REG(val); + data->zone[nr].range = RANGE_TO_REG( + val - min); + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), + ((data->zone[nr].range & 0x0f) << 4) + | (data->autofan[nr].freq & 0x07)); + up(&data->update_lock); + return count; +} +static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) +{ + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].critical)); +} +static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm85_data *data = i2c_get_clientdata(client); + int val; + + down(&data->update_lock); + val = simple_strtol(buf, NULL, 10); + data->zone[nr].critical = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), + data->zone[nr].critical); + up(&data->update_lock); + return count; +} +#define temp_auto(offset) \ +static ssize_t show_temp##offset##_auto_temp_off (struct device *dev, \ + char *buf) \ +{ \ + return show_temp_auto_temp_off(dev, buf, offset - 1); \ +} \ +static ssize_t set_temp##offset##_auto_temp_off (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_temp_auto_temp_off(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_temp##offset##_auto_temp_min (struct device *dev, \ + char *buf) \ +{ \ + return show_temp_auto_temp_min(dev, buf, offset - 1); \ +} \ +static ssize_t set_temp##offset##_auto_temp_min (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_temp_auto_temp_min(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_temp##offset##_auto_temp_max (struct device *dev, \ + char *buf) \ +{ \ + return show_temp_auto_temp_max(dev, buf, offset - 1); \ +} \ +static ssize_t set_temp##offset##_auto_temp_max (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_temp_auto_temp_max(dev, buf, count, offset - 1); \ +} \ +static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev, \ + char *buf) \ +{ \ + return show_temp_auto_temp_crit(dev, buf, offset - 1); \ +} \ +static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_temp_auto_temp_crit(dev, buf, count, offset - 1); \ +} \ +static DEVICE_ATTR(temp##offset##_auto_temp_off, S_IRUGO | S_IWUSR, \ + show_temp##offset##_auto_temp_off, \ + set_temp##offset##_auto_temp_off); \ +static DEVICE_ATTR(temp##offset##_auto_temp_min, S_IRUGO | S_IWUSR, \ + show_temp##offset##_auto_temp_min, \ + set_temp##offset##_auto_temp_min); \ +static DEVICE_ATTR(temp##offset##_auto_temp_max, S_IRUGO | S_IWUSR, \ + show_temp##offset##_auto_temp_max, \ + set_temp##offset##_auto_temp_max); \ +static DEVICE_ATTR(temp##offset##_auto_temp_crit, S_IRUGO | S_IWUSR, \ + show_temp##offset##_auto_temp_crit, \ + set_temp##offset##_auto_temp_crit); +temp_auto(1); +temp_auto(2); +temp_auto(3); + int lm85_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; return i2c_detect(adapter, &addr_data, lm85_detect); } @@ -832,7 +1133,7 @@ int lm85_detect(struct i2c_adapter *adapter, int address, goto ERROR1; /* Set the VRM version */ - data->vrm = LM85_INIT_VRM ; + data->vrm = i2c_which_vrm(); /* Initialize the LM85 chip */ lm85_init_client(new_client); @@ -846,12 +1147,12 @@ int lm85_detect(struct i2c_adapter *adapter, int address, device_create_file(&new_client->dev, &dev_attr_fan2_min); device_create_file(&new_client->dev, &dev_attr_fan3_min); device_create_file(&new_client->dev, &dev_attr_fan4_min); - device_create_file(&new_client->dev, &dev_attr_fan1_pwm); - device_create_file(&new_client->dev, &dev_attr_fan2_pwm); - device_create_file(&new_client->dev, &dev_attr_fan3_pwm); - device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); - device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable); - device_create_file(&new_client->dev, &dev_attr_fan3_pwm_enable); + device_create_file(&new_client->dev, &dev_attr_pwm1); + device_create_file(&new_client->dev, &dev_attr_pwm2); + device_create_file(&new_client->dev, &dev_attr_pwm3); + device_create_file(&new_client->dev, &dev_attr_pwm1_enable); + device_create_file(&new_client->dev, &dev_attr_pwm2_enable); + device_create_file(&new_client->dev, &dev_attr_pwm3_enable); device_create_file(&new_client->dev, &dev_attr_in0_input); device_create_file(&new_client->dev, &dev_attr_in1_input); device_create_file(&new_client->dev, &dev_attr_in2_input); @@ -877,8 +1178,32 @@ int lm85_detect(struct i2c_adapter *adapter, int address, device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev, &dev_attr_temp3_max); device_create_file(&new_client->dev, &dev_attr_vrm); - device_create_file(&new_client->dev, &dev_attr_in0_ref); + device_create_file(&new_client->dev, &dev_attr_cpu0_vid); device_create_file(&new_client->dev, &dev_attr_alarms); + device_create_file(&new_client->dev, &dev_attr_pwm1_auto_channels); + device_create_file(&new_client->dev, &dev_attr_pwm2_auto_channels); + device_create_file(&new_client->dev, &dev_attr_pwm3_auto_channels); + device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_min); + device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_minctl); + device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_minctl); + device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_minctl); + device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_freq); + device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_freq); + device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_freq); + device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_off); + device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_min); + device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_max); + device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_crit); + device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit); + device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit); return 0; @@ -1162,7 +1487,7 @@ static void __exit sm_lm85_exit(void) * post 2.7.0 CVS changes. */ MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Philip Pokorny , Margit Schubert-While "); +MODULE_AUTHOR("Philip Pokorny , Margit Schubert-While , Justin Thiessen > 5) * 125) -#define TEMP2_TO_REG(val) ((((val / 125) << 5) + (val < 0 ? 0x10000 : 0)) & 0xFFE0) -#define HYST_FROM_REG(val) (val * 1000) -#define HYST_TO_REG(val) (val <= 0 ? 0 : val >= 31000 ? 31 : val / 1000) +#define TEMP1_FROM_REG(val) ((val) * 1000) +#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \ + (val) >= 127000 ? 127 : \ + (val) < 0 ? ((val) - 500) / 1000 : \ + ((val) + 500) / 1000) +#define TEMP2_FROM_REG(val) ((val) / 32 * 125) +#define TEMP2_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ + (val) >= 127875 ? 0x7FE0 : \ + (val) < 0 ? ((val) - 62) / 125 * 32 : \ + ((val) + 62) / 125 * 32) +#define HYST_TO_REG(val) ((val) <= 0 ? 0 : (val) >= 30500 ? 31 : \ + ((val) + 500) / 1000) /* * Functions declaration @@ -176,18 +179,18 @@ struct lm90_data { unsigned long last_updated; /* in jiffies */ /* registers values */ - u8 temp_input1, temp_low1, temp_high1; /* local */ - u16 temp_input2, temp_low2, temp_high2; /* remote, combined */ - u8 temp_crit1, temp_crit2; + s8 temp_input1, temp_low1, temp_high1; /* local */ + s16 temp_input2, temp_low2, temp_high2; /* remote, combined */ + s8 temp_crit1, temp_crit2; u8 temp_hyst; - u16 alarms; /* bitvector, combined */ + u8 alarms; /* bitvector */ }; /* * Internal variables */ -static int lm90_id = 0; +static int lm90_id; /* * Sysfs stuff @@ -214,7 +217,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct lm90_data *data = i2c_get_clientdata(client); \ - data->value = TEMP1_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = TEMP1_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ return count; \ } @@ -224,7 +228,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct lm90_data *data = i2c_get_clientdata(client); \ - data->value = TEMP2_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = TEMP2_TO_REG(val); \ i2c_smbus_write_byte_data(client, regh, data->value >> 8); \ i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \ return count; \ @@ -241,7 +246,7 @@ static ssize_t show_##value(struct device *dev, char *buf) \ { \ struct lm90_data *data = lm90_update_device(dev); \ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->basereg) \ - - HYST_FROM_REG(data->temp_hyst)); \ + - TEMP1_FROM_REG(data->temp_hyst)); \ } show_temp_hyst(temp_hyst1, temp_crit1); show_temp_hyst(temp_hyst2, temp_crit2); diff --git a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c index 0f8a5ac5c..bc7e22f0c 100644 --- a/drivers/i2c/chips/max1619.c +++ b/drivers/i2c/chips/max1619.c @@ -34,11 +34,11 @@ #include -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b, - 0x4c, 0x4e, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, + 0x29, 0x2a, 0x2b, + 0x4c, 0x4d, 0x4e, + I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* * Insmod parameters @@ -120,7 +120,7 @@ struct max1619_data { * Internal variables */ -static int max1619_id = 0; +static int max1619_id; /* * Sysfs stuff @@ -145,7 +145,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct max1619_data *data = i2c_get_clientdata(client); \ - data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ + long val = simple_strtol(buf, NULL, 10); \ + data->value = TEMP_TO_REG(val); \ i2c_smbus_write_byte_data(client, reg, data->value); \ return count; \ } diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c index 78c6693f3..794393858 100644 --- a/drivers/i2c/chips/pcf8574.c +++ b/drivers/i2c/chips/pcf8574.c @@ -42,10 +42,10 @@ #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x20, 0x27, 0x38, 0x3f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_2(pcf8574, pcf8574a); @@ -77,7 +77,7 @@ static struct i2c_driver pcf8574_driver = { .detach_client = pcf8574_detach_client, }; -static int pcf8574_id = 0; +static int pcf8574_id; /* following are the sysfs callback functions */ static ssize_t show_read(struct device *dev, char *buf) diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index 87ad9b973..8f3b8588c 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c @@ -27,16 +27,15 @@ #include /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(pcf8591); static int input_mode; -MODULE_PARM(input_mode, "i"); +module_param(input_mode, int, 0); MODULE_PARM_DESC(input_mode, "Analog input mode:\n" " 0 = four single ended inputs\n" @@ -99,7 +98,7 @@ static struct i2c_driver pcf8591_driver = { .detach_client = pcf8591_detach_client, }; -static int pcf8591_id = 0; +static int pcf8591_id; /* following are the sysfs callback functions */ #define show_in_channel(channel) \ diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c index 0fa55d45e..acfd3f804 100644 --- a/drivers/i2c/chips/rtc8564.c +++ b/drivers/i2c/chips/rtc8564.c @@ -56,8 +56,8 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client) #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) -static int debug = 0; -MODULE_PARM(debug, "i"); +static int debug;; +module_param(debug, int, S_IRUGO | S_IWUSR); static struct i2c_driver rtc8564_driver; diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c index 078c65fe3..39c6871bd 100644 --- a/drivers/i2c/chips/smsc47m1.c +++ b/drivers/i2c/chips/smsc47m1.c @@ -34,22 +34,14 @@ #include static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* Address is autodetected, there is no default value */ static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; static struct i2c_force_data forces[] = {{NULL}}; enum chips { any_chip, smsc47m1 }; static struct i2c_address_data addr_data = { .normal_i2c = normal_i2c, - .normal_i2c_range = normal_i2c_range, .normal_isa = normal_isa, - .normal_isa_range = normal_isa_range, - .probe = normal_i2c, /* cheat */ - .probe_range = normal_i2c_range, /* cheat */ - .ignore = normal_i2c, /* cheat */ - .ignore_range = normal_i2c_range, /* cheat */ .forces = forces, }; @@ -182,13 +174,13 @@ static ssize_t get_fan_div(struct device *dev, char *buf, int nr) return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); } -static ssize_t get_fan_pwm(struct device *dev, char *buf, int nr) +static ssize_t get_pwm(struct device *dev, char *buf, int nr) { struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); } -static ssize_t get_fan_pwm_en(struct device *dev, char *buf, int nr) +static ssize_t get_pwm_en(struct device *dev, char *buf, int nr) { struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr])); @@ -256,7 +248,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, return count; } -static ssize_t set_fan_pwm(struct device *dev, const char *buf, +static ssize_t set_pwm(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); @@ -275,7 +267,7 @@ static ssize_t set_fan_pwm(struct device *dev, const char *buf, return count; } -static ssize_t set_fan_pwm_en(struct device *dev, const char *buf, +static ssize_t set_pwm_en(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); @@ -298,43 +290,43 @@ static ssize_t set_fan_pwm_en(struct device *dev, const char *buf, #define fan_present(offset) \ static ssize_t get_fan##offset (struct device *dev, char *buf) \ { \ - return get_fan(dev, buf, 0x##offset - 1); \ + return get_fan(dev, buf, offset - 1); \ } \ static ssize_t get_fan##offset##_min (struct device *dev, char *buf) \ { \ - return get_fan_min(dev, buf, 0x##offset - 1); \ + return get_fan_min(dev, buf, offset - 1); \ } \ static ssize_t set_fan##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ static ssize_t get_fan##offset##_div (struct device *dev, char *buf) \ { \ - return get_fan_div(dev, buf, 0x##offset - 1); \ + return get_fan_div(dev, buf, offset - 1); \ } \ static ssize_t set_fan##offset##_div (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_div(dev, buf, count, 0x##offset - 1); \ + return set_fan_div(dev, buf, count, offset - 1); \ } \ -static ssize_t get_fan##offset##_pwm (struct device *dev, char *buf) \ +static ssize_t get_pwm##offset (struct device *dev, char *buf) \ { \ - return get_fan_pwm(dev, buf, 0x##offset - 1); \ + return get_pwm(dev, buf, offset - 1); \ } \ -static ssize_t set_fan##offset##_pwm (struct device *dev, \ +static ssize_t set_pwm##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_pwm(dev, buf, count, 0x##offset - 1); \ + return set_pwm(dev, buf, count, offset - 1); \ } \ -static ssize_t get_fan##offset##_pwm_en (struct device *dev, char *buf) \ +static ssize_t get_pwm##offset##_en (struct device *dev, char *buf) \ { \ - return get_fan_pwm_en(dev, buf, 0x##offset - 1); \ + return get_pwm_en(dev, buf, offset - 1); \ } \ -static ssize_t set_fan##offset##_pwm_en (struct device *dev, \ +static ssize_t set_pwm##offset##_en (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_pwm_en(dev, buf, count, 0x##offset - 1); \ + return set_pwm_en(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset, \ NULL); \ @@ -342,10 +334,10 @@ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ get_fan##offset##_min, set_fan##offset##_min); \ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ get_fan##offset##_div, set_fan##offset##_div); \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ - get_fan##offset##_pwm, set_fan##offset##_pwm); \ -static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, \ - get_fan##offset##_pwm_en, set_fan##offset##_pwm_en); +static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ + get_pwm##offset, set_pwm##offset); \ +static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ + get_pwm##offset##_en, set_pwm##offset##_en); fan_present(1); fan_present(2); @@ -402,6 +394,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) struct i2c_client *new_client; struct smsc47m1_data *data; int err = 0; + int fan1, fan2, pwm1, pwm2; if (!i2c_is_isa_adapter(adapter)) { return 0; @@ -431,6 +424,22 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) new_client->id = smsc47m1_id++; init_MUTEX(&data->update_lock); + /* If no function is properly configured, there's no point in + actually registering the chip. */ + fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05) + == 0x05; + fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05) + == 0x05; + pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05) + == 0x04; + pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) + == 0x04; + if (!(fan1 || fan2 || pwm1 || pwm2)) { + dev_warn(&new_client->dev, "Device is not configured, will not use\n"); + err = -ENODEV; + goto error_free; + } + if ((err = i2c_attach_client(new_client))) goto error_free; @@ -442,8 +451,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) function. */ smsc47m1_update_device(&new_client->dev, 1); - if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05) - == 0x05) { + if (fan1) { device_create_file(&new_client->dev, &dev_attr_fan1_input); device_create_file(&new_client->dev, &dev_attr_fan1_min); device_create_file(&new_client->dev, &dev_attr_fan1_div); @@ -451,8 +459,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, " "skipping\n"); - if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05) - == 0x05) { + if (fan2) { device_create_file(&new_client->dev, &dev_attr_fan2_input); device_create_file(&new_client->dev, &dev_attr_fan2_min); device_create_file(&new_client->dev, &dev_attr_fan2_div); @@ -460,17 +467,15 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " "skipping\n"); - if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05) - == 0x04) { - device_create_file(&new_client->dev, &dev_attr_fan1_pwm); - device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable); + if (pwm1) { + device_create_file(&new_client->dev, &dev_attr_pwm1); + device_create_file(&new_client->dev, &dev_attr_pwm1_enable); } else dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " "skipping\n"); - if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) - == 0x04) { - device_create_file(&new_client->dev, &dev_attr_fan2_pwm); - device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable); + if (pwm2) { + device_create_file(&new_client->dev, &dev_attr_pwm2); + device_create_file(&new_client->dev, &dev_attr_pwm2_enable); } else dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " "skipping\n"); diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c index 3aa334583..d4938fa32 100644 --- a/drivers/i2c/chips/via686a.c +++ b/drivers/i2c/chips/via686a.c @@ -43,8 +43,8 @@ /* If force_addr is set to anything different from 0, we forcibly enable the device at the given address. */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); +static unsigned short force_addr = 0; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); @@ -52,9 +52,7 @@ MODULE_PARM_DESC(force_addr, Note that we can't determine the ISA address until we have initialized our module */ static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(via686a); @@ -383,27 +381,27 @@ static ssize_t set_in_max(struct device *dev, const char *buf, static ssize_t \ show_in##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ - return show_in_min(dev, buf, 0x##offset); \ + return show_in_min(dev, buf, offset); \ } \ static ssize_t \ show_in##offset##_max (struct device *dev, char *buf) \ { \ - return show_in_max(dev, buf, 0x##offset); \ + return show_in_max(dev, buf, offset); \ } \ static ssize_t set_in##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_min(dev, buf, count, 0x##offset); \ + return set_in_min(dev, buf, count, offset); \ } \ static ssize_t set_in##offset##_max (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_in_max(dev, buf, count, 0x##offset); \ + return set_in_max(dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\ static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ @@ -451,27 +449,27 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, #define show_temp_offset(offset) \ static ssize_t show_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset - 1); \ + return show_temp(dev, buf, offset - 1); \ } \ static ssize_t \ show_temp_##offset##_over (struct device *dev, char *buf) \ { \ - return show_temp_over(dev, buf, 0x##offset - 1); \ + return show_temp_over(dev, buf, offset - 1); \ } \ static ssize_t \ show_temp_##offset##_hyst (struct device *dev, char *buf) \ { \ - return show_temp_hyst(dev, buf, 0x##offset - 1); \ + return show_temp_hyst(dev, buf, offset - 1); \ } \ static ssize_t set_temp_##offset##_over (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_over(dev, buf, count, 0x##offset - 1); \ + return set_temp_over(dev, buf, count, offset - 1); \ } \ static ssize_t set_temp_##offset##_hyst (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_temp_hyst(dev, buf, count, 0x##offset - 1); \ + return set_temp_hyst(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\ static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ @@ -522,25 +520,25 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, #define show_fan_offset(offset) \ static ssize_t show_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset - 1); \ + return show_fan(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset - 1); \ + return show_fan_min(dev, buf, offset - 1); \ } \ static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \ { \ - return show_fan_div(dev, buf, 0x##offset - 1); \ + return show_fan_div(dev, buf, offset - 1); \ } \ static ssize_t set_fan_##offset##_min (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_min(dev, buf, count, 0x##offset - 1); \ + return set_fan_min(dev, buf, count, offset - 1); \ } \ static ssize_t set_fan_##offset##_div (struct device *dev, \ const char *buf, size_t count) \ { \ - return set_fan_div(dev, buf, count, 0x##offset - 1); \ + return set_fan_div(dev, buf, count, offset - 1); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ @@ -838,7 +836,7 @@ static struct pci_driver via686a_pci_driver = { static int __init sm_via686a_init(void) { - return pci_module_init(&via686a_pci_driver); + return pci_register_driver(&via686a_pci_driver); } static void __exit sm_via686a_exit(void) diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c index 5d1a31bcb..cf9e88749 100644 --- a/drivers/i2c/chips/w83627hf.c +++ b/drivers/i2c/chips/w83627hf.c @@ -46,26 +46,24 @@ #include #include "lm75.h" -static int force_addr; -MODULE_PARM(force_addr, "i"); +static u16 force_addr; +module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); -static int force_i2c = 0x1f; -MODULE_PARM(force_i2c, "i"); +static u8 force_i2c = 0x1f; +module_param(force_i2c, byte, 0); MODULE_PARM_DESC(force_i2c, "Initialize the i2c address of the sensors"); /* Addresses to scan */ static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf); static int init = 1; -MODULE_PARM(init, "i"); +module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); /* modified from kernel/include/traps.c */ @@ -369,20 +367,20 @@ store_in_reg(MAX, max) static ssize_t \ show_regs_in_##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); #define sysfs_in_reg_offset(reg, offset) \ static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ { \ - return show_in_##reg (dev, buf, 0x##offset); \ + return show_in_##reg (dev, buf, offset); \ } \ static ssize_t \ store_regs_in_##reg##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return store_in_##reg (dev, buf, count, 0x##offset); \ + return store_in_##reg (dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, \ show_regs_in_##reg##offset, store_regs_in_##reg##offset); @@ -521,19 +519,19 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) #define sysfs_fan_offset(offset) \ static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset); \ + return show_fan(dev, buf, offset); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); #define sysfs_fan_min_offset(offset) \ static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset); \ + return show_fan_min(dev, buf, offset); \ } \ static ssize_t \ store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \ { \ - return store_fan_min(dev, buf, count, 0x##offset); \ + return store_fan_min(dev, buf, count, offset); \ } \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ show_regs_fan_min##offset, store_regs_fan_min##offset); @@ -595,20 +593,20 @@ store_temp_reg(HYST, max_hyst); static ssize_t \ show_regs_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset); \ + return show_temp(dev, buf, offset); \ } \ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); #define sysfs_temp_reg_offset(reg, offset) \ static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \ { \ - return show_temp_##reg (dev, buf, 0x##offset); \ + return show_temp_##reg (dev, buf, offset); \ } \ static ssize_t \ store_regs_temp_##reg##offset (struct device *dev, \ const char *buf, size_t count) \ { \ - return store_temp_##reg (dev, buf, count, 0x##offset); \ + return store_temp_##reg (dev, buf, count, offset); \ } \ static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); @@ -635,9 +633,9 @@ show_vid_reg(struct device *dev, char *buf) struct w83627hf_data *data = w83627hf_update_device(dev); return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref) +device_create_file(&client->dev, &dev_attr_cpu0_vid) static ssize_t show_vrm_reg(struct device *dev, char *buf) @@ -845,7 +843,7 @@ store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \ { \ return store_pwm_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, \ +static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ show_regs_pwm_##offset, store_regs_pwm_##offset); sysfs_pwm(1); @@ -854,7 +852,7 @@ sysfs_pwm(3); #define device_create_file_pwm(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \ +device_create_file(&client->dev, &dev_attr_pwm##offset); \ } while (0) static ssize_t @@ -1281,7 +1279,7 @@ static void w83627hf_init_client(struct i2c_client *client) data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82; } else { /* Convert VID to voltage based on default VRM */ - data->vrm = DEFAULT_VRM; + data->vrm = i2c_which_vrm(); } tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index 785203d39..3a44fe9e5 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -49,10 +49,10 @@ #define W83781D_RT 1 /* Addresses to scan */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { 0x20, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf); @@ -60,7 +60,7 @@ I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " "{bus, clientaddr, subclientaddr1, subclientaddr2}"); static int init = 1; -MODULE_PARM(init, "i"); +module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); /* Constants specified below */ @@ -318,18 +318,18 @@ store_in_reg(MAX, max); static ssize_t \ show_regs_in_##offset (struct device *dev, char *buf) \ { \ - return show_in(dev, buf, 0x##offset); \ + return show_in(dev, buf, offset); \ } \ static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL); #define sysfs_in_reg_offset(reg, offset) \ static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \ { \ - return show_in_##reg (dev, buf, 0x##offset); \ + return show_in_##reg (dev, buf, offset); \ } \ static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \ { \ - return store_in_##reg (dev, buf, count, 0x##offset); \ + return store_in_##reg (dev, buf, count, offset); \ } \ static DEVICE_ATTR(in##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset); @@ -384,18 +384,18 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) #define sysfs_fan_offset(offset) \ static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \ { \ - return show_fan(dev, buf, 0x##offset); \ + return show_fan(dev, buf, offset); \ } \ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); #define sysfs_fan_min_offset(offset) \ static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \ { \ - return show_fan_min(dev, buf, 0x##offset); \ + return show_fan_min(dev, buf, offset); \ } \ static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \ { \ - return store_fan_min(dev, buf, count, 0x##offset); \ + return store_fan_min(dev, buf, count, offset); \ } \ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset); @@ -464,18 +464,18 @@ store_temp_reg(HYST, max_hyst); static ssize_t \ show_regs_temp_##offset (struct device *dev, char *buf) \ { \ - return show_temp(dev, buf, 0x##offset); \ + return show_temp(dev, buf, offset); \ } \ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); #define sysfs_temp_reg_offset(reg, offset) \ static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \ { \ - return show_temp_##reg (dev, buf, 0x##offset); \ + return show_temp_##reg (dev, buf, offset); \ } \ static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \ { \ - return store_temp_##reg (dev, buf, count, 0x##offset); \ + return store_temp_##reg (dev, buf, count, offset); \ } \ static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); @@ -503,9 +503,9 @@ show_vid_reg(struct device *dev, char *buf) } static -DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref); +device_create_file(&client->dev, &dev_attr_cpu0_vid); static ssize_t show_vrm_reg(struct device *dev, char *buf) { @@ -740,22 +740,26 @@ static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \ { \ return show_pwm_reg(dev, buf, offset); \ } \ -static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \ +static ssize_t store_regs_pwm_##offset (struct device *dev, \ + const char *buf, size_t count) \ { \ return store_pwm_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset); +static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ + show_regs_pwm_##offset, store_regs_pwm_##offset); #define sysfs_pwmenable(offset) \ static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \ { \ return show_pwmenable_reg(dev, buf, offset); \ } \ -static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *buf, size_t count) \ +static ssize_t store_regs_pwmenable_##offset (struct device *dev, \ + const char *buf, size_t count) \ { \ return store_pwmenable_reg(dev, buf, count, offset); \ } \ -static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); +static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ + show_regs_pwmenable_##offset, store_regs_pwmenable_##offset); sysfs_pwm(1); sysfs_pwm(2); @@ -765,12 +769,12 @@ sysfs_pwm(4); #define device_create_file_pwm(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \ +device_create_file(&client->dev, &dev_attr_pwm##offset); \ } while (0) #define device_create_file_pwmenable(client, offset) \ do { \ -device_create_file(&client->dev, &dev_attr_fan##offset##_pwm_enable); \ +device_create_file(&client->dev, &dev_attr_pwm##offset##_enable); \ } while (0) static ssize_t @@ -815,8 +819,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) data->sens[nr - 1] = val; break; default: - dev_err(&client->dev, - "Invalid sensor type %ld; must be 1, 2, or %d\n", + dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", (long) val, W83781D_DEFAULT_BETA); break; } @@ -1063,6 +1066,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) if (is_isa) if (!request_region(address, W83781D_EXTENT, "w83781d")) { + dev_dbg(&adapter->dev, "Request of region " + "0x%x-0x%x for w83781d failed\n", address, + address + W83781D_EXTENT - 1); err = -EBUSY; goto ERROR0; } @@ -1076,15 +1082,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) /* We need the timeouts for at least some LM78-like chips. But only if we read 'undefined' registers. */ i = inb_p(address + 1); - if (inb_p(address + 2) != i) { - err = -ENODEV; - goto ERROR1; - } - if (inb_p(address + 3) != i) { - err = -ENODEV; - goto ERROR1; - } - if (inb_p(address + 7) != i) { + if (inb_p(address + 2) != i + || inb_p(address + 3) != i + || inb_p(address + 7) != i) { + dev_dbg(&adapter->dev, "Detection of w83781d " + "chip failed at step 1\n"); err = -ENODEV; goto ERROR1; } @@ -1093,8 +1095,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) /* Let's just hope nothing breaks here */ i = inb_p(address + 5) & 0x7f; outb_p(~i & 0x7f, address + 5); - if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { + val2 = inb_p(address + 5) & 0x7f; + if (val2 != (~i & 0x7f)) { outb_p(i, address + 5); + dev_dbg(&adapter->dev, "Detection of w83781d " + "chip failed at step 2 (0x%x != " + "0x%x at 0x%x)\n", val2, ~i & 0x7f, + address + 5); err = -ENODEV; goto ERROR1; } @@ -1126,7 +1133,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) force_*=... parameter, and the Winbond will be reset to the right bank. */ if (kind < 0) { - if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){ + if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80) { + dev_dbg(&new_client->dev, "Detection failed at step " + "3\n"); err = -ENODEV; goto ERROR2; } @@ -1136,6 +1145,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) if ((!(val1 & 0x07)) && (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { + dev_dbg(&new_client->dev, "Detection failed at step " + "4\n"); err = -ENODEV; goto ERROR2; } @@ -1145,6 +1156,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ((val1 & 0x80) && (val2 == 0x5c)))) { if (w83781d_read_value (new_client, W83781D_REG_I2C_ADDR) != address) { + dev_dbg(&new_client->dev, "Detection failed " + "at step 5\n"); err = -ENODEV; goto ERROR2; } @@ -1167,6 +1180,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) else if (val2 == 0x12) vendid = asus; else { + dev_dbg(&new_client->dev, "Chip was made by neither " + "Winbond nor Asus?\n"); err = -ENODEV; goto ERROR2; } @@ -1187,10 +1202,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) kind = w83697hf; else { if (kind == 0) - dev_warn(&new_client->dev, - "Ignoring 'force' parameter for unknown chip at" - "adapter %d, address 0x%02x\n", - i2c_adapter_id(adapter), address); + dev_warn(&new_client->dev, "Ignoring 'force' " + "parameter for unknown chip at " + "adapter %d, address 0x%02x\n", + i2c_adapter_id(adapter), address); err = -EINVAL; goto ERROR2; } @@ -1513,7 +1528,7 @@ w83781d_init_client(struct i2c_client *client) w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); } - data->vrm = 82; + data->vrm = i2c_which_vrm(); if ((type != w83781d) && (type != as99127f)) { tmp = w83781d_read_value(client, W83781D_REG_SCFG1); @@ -1593,7 +1608,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) if (time_after (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2)) || time_before(jiffies, data->last_updated) || !data->valid) { - pr_debug("Starting device update\n"); + dev_dbg(dev, "Starting device update\n"); for (i = 0; i <= 8; i++) { if ((data->type == w83783s || data->type == w83697hf) diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c index 58575861f..66b3b8da0 100644 --- a/drivers/i2c/chips/w83l785ts.c +++ b/drivers/i2c/chips/w83l785ts.c @@ -47,9 +47,7 @@ */ static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END }; -static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; -static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; /* * Insmod parameters @@ -282,14 +280,17 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) * default value requested by the caller. */ for (i = 1; i <= MAX_RETRIES; i++) { value = i2c_smbus_read_byte_data(client, reg); - if (value >= 0) + if (value >= 0) { + dev_dbg(&client->dev, "Read 0x%02x from register " + "0x%02x.\n", value, reg); return value; + } dev_dbg(&client->dev, "Read failed, will retry in %d.\n", i); msleep(i); } - dev_err(&client->dev, "Couldn't read value from register. " - "Please report.\n"); + dev_err(&client->dev, "Couldn't read value from register 0x%02x. " + "Please report.\n", reg); return defval; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2583ecaa9..42776f1a8 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -177,12 +177,25 @@ out_unlock: int i2c_del_adapter(struct i2c_adapter *adap) { struct list_head *item, *_n; + struct i2c_adapter *adap_from_list; struct i2c_driver *driver; struct i2c_client *client; int res = 0; down(&core_lists); + /* First make sure that this adapter was ever added */ + list_for_each_entry(adap_from_list, &adapters, list) { + if (adap_from_list == adap) + break; + } + if (adap_from_list != adap) { + pr_debug("I2C: Attempting to delete an unregistered " + "adapter\n"); + res = -EINVAL; + goto out_unlock; + } + list_for_each(item,&drivers) { driver = list_entry(item, struct i2c_driver, list); if (driver->detach_adapter) @@ -517,9 +530,29 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) return 1; } +static int i2c_bus_suspend(struct device * dev, u32 state) +{ + int rc = 0; + + if (dev->driver && dev->driver->suspend) + rc = dev->driver->suspend(dev,state,0); + return rc; +} + +static int i2c_bus_resume(struct device * dev) +{ + int rc = 0; + + if (dev->driver && dev->driver->resume) + rc = dev->driver->resume(dev,0); + return rc; +} + struct bus_type i2c_bus_type = { .name = "i2c", .match = i2c_device_match, + .suspend = i2c_bus_suspend, + .resume = i2c_bus_resume, }; static int __init i2c_init(void) @@ -727,7 +760,7 @@ int i2c_probe(struct i2c_adapter *adapter, if (addr == address_data->normal_i2c[i]) { found = 1; dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, " - "addr %02x", adap_id,addr); + "addr %02x\n", adap_id, addr); } } @@ -988,35 +1021,8 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) I2C_SMBUS_WORD_DATA,&data); } -s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value) -{ - union i2c_smbus_data data; - data.word = value; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_WRITE,command, - I2C_SMBUS_PROC_CALL, &data)) - return -1; - else - return 0x0FFFF & data.word; -} - -/* Returns the number of read bytes */ -s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values) -{ - union i2c_smbus_data data; - int i; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, - I2C_SMBUS_BLOCK_DATA,&data)) - return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } -} - -s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) +s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, + u8 length, u8 *values) { union i2c_smbus_data data; int i; @@ -1026,27 +1032,8 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, data.block[i] = values[i-1]; data.block[0] = length; return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_WRITE,command, - I2C_SMBUS_BLOCK_DATA,&data); -} - -/* Returns the number of read bytes */ -s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values) -{ - union i2c_smbus_data data; - int i; - if (length > I2C_SMBUS_BLOCK_MAX - 1) - return -1; - data.block[0] = length; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; - if(i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BLOCK_PROC_CALL, &data)) - return -1; - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; + I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_DATA,&data); } /* Returns the number of read bytes */ @@ -1065,20 +1052,6 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val } } -s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) -{ - union i2c_smbus_data data; - int i; - if (length > I2C_SMBUS_I2C_BLOCK_MAX) - length = I2C_SMBUS_I2C_BLOCK_MAX; - for (i = 1; i <= length; i++) - data.block[i] = values[i-1]; - data.block[0] = length; - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_WRITE,command, - I2C_SMBUS_I2C_BLOCK_DATA,&data); -} - /* Simulate a SMBus command using the i2c protocol No checking of parameters is done! */ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, @@ -1302,11 +1275,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data); EXPORT_SYMBOL(i2c_smbus_write_byte_data); EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_write_word_data); -EXPORT_SYMBOL(i2c_smbus_process_call); -EXPORT_SYMBOL(i2c_smbus_read_block_data); EXPORT_SYMBOL(i2c_smbus_write_block_data); EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); -EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); EXPORT_SYMBOL(i2c_get_functionality); EXPORT_SYMBOL(i2c_check_functionality); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index af17f14e0..fcb62f335 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -539,7 +539,7 @@ out_unreg_class: out_unreg_chrdev: unregister_chrdev(I2C_MAJOR, "i2c"); out: - printk(KERN_ERR "%s: Driver Initialisation failed", __FILE__); + printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); return res; } diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c index 70e82f23e..44a4a3546 100644 --- a/drivers/i2c/i2c-sensor-detect.c +++ b/drivers/i2c/i2c-sensor-detect.c @@ -31,6 +31,8 @@ #include #include +static unsigned short empty[] = {I2C_CLIENT_END}; +static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END}; /* Very inefficient for ISA detects, and won't work for 10-bit addresses! */ int i2c_detect(struct i2c_adapter *adapter, @@ -42,11 +44,27 @@ int i2c_detect(struct i2c_adapter *adapter, int is_isa = i2c_is_isa_adapter(adapter); int adapter_id = is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter); + unsigned short *normal_i2c; + unsigned int *normal_isa; + unsigned short *probe; + unsigned short *ignore; /* Forget it if we can't probe using SMBUS_QUICK */ if ((!is_isa) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) return -1; + + /* Use default "empty" list if the adapter doesn't specify any */ + normal_i2c = probe = ignore = empty; + normal_isa = empty_isa; + if (address_data->normal_i2c) + normal_i2c = address_data->normal_i2c; + if (address_data->normal_isa) + normal_isa = address_data->normal_isa; + if (address_data->probe) + probe = address_data->probe; + if (address_data->ignore) + ignore = address_data->ignore; for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { if (!is_isa && i2c_check_addr(adapter, addr)) @@ -72,81 +90,46 @@ int i2c_detect(struct i2c_adapter *adapter, /* If this address is in one of the ignores, we can forget about it right now */ - for (i = 0; !found && (address_data->ignore[i] != I2C_CLIENT_END); i += 2) { - if ( ((adapter_id == address_data->ignore[i]) || - ((address_data->ignore[i] == ANY_I2C_BUS) && + for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) { + if ( ((adapter_id == ignore[i]) || + ((ignore[i] == ANY_I2C_BUS) && !is_isa)) && - (addr == address_data->ignore[i + 1])) { + (addr == ignore[i + 1])) { dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; !found && (address_data->ignore_range[i] != I2C_CLIENT_END); i += 3) { - if ( ((adapter_id == address_data->ignore_range[i]) || - ((address_data-> ignore_range[i] == ANY_I2C_BUS) & - !is_isa)) && - (addr >= address_data->ignore_range[i + 1]) && - (addr <= address_data->ignore_range[i + 2])) { - dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr); - found = 1; - } - } if (found) continue; /* Now, we will do a detection, but only if it is in the normal or probe entries */ if (is_isa) { - for (i = 0; !found && (address_data->normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) { - if (addr == address_data->normal_isa[i]) { + for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) { + if (addr == normal_isa[i]) { dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; !found && (address_data->normal_isa_range[i] != I2C_CLIENT_ISA_END); i += 3) { - if ((addr >= address_data->normal_isa_range[i]) && - (addr <= address_data->normal_isa_range[i + 1]) && - ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) { - dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr); - found = 1; - } - } } else { - for (i = 0; !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); i += 1) { - if (addr == address_data->normal_i2c[i]) { - found = 1; - dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr); - } - } - for (i = 0; !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); i += 2) { - if ((addr >= address_data->normal_i2c_range[i]) && - (addr <= address_data->normal_i2c_range[i + 1])) { - dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr); + for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) { + if (addr == normal_i2c[i]) { found = 1; + dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr); } } } for (i = 0; - !found && (address_data->probe[i] != I2C_CLIENT_END); + !found && (probe[i] != I2C_CLIENT_END); i += 2) { - if (((adapter_id == address_data->probe[i]) || - ((address_data-> - probe[i] == ANY_I2C_BUS) && !is_isa)) - && (addr == address_data->probe[i + 1])) { + if (((adapter_id == probe[i]) || + ((probe[i] == ANY_I2C_BUS) && !is_isa)) + && (addr == probe[i + 1])) { dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr); found = 1; } } - for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) { - if ( ((adapter_id == address_data->probe_range[i]) || - ((address_data->probe_range[i] == ANY_I2C_BUS) && !is_isa)) && - (addr >= address_data->probe_range[i + 1]) && - (addr <= address_data->probe_range[i + 2])) { - found = 1; - dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr); - } - } if (!found) continue; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index f28496bd2..cc5aeb202 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -273,15 +273,6 @@ config IDE_TASK_IOCTL If you are unsure, say N here. -config IDE_TASKFILE_IO - bool 'IDE Taskfile IO (EXPERIMENTAL)' - depends on EXPERIMENTAL - default n - ---help--- - Use new taskfile IO code. - - It is safe to say Y to this question, in most cases. - comment "IDE chipset support/bugfixes" config IDE_GENERIC @@ -457,11 +448,6 @@ config IDEDMA_ONLYDISK Generally say N here. -config BLK_DEV_ADMA - bool - depends on PCI && BLK_DEV_IDEPCI - default BLK_DEV_IDEDMA_PCI - config BLK_DEV_AEC62XX tristate "AEC62XX chipset support" help @@ -786,17 +772,6 @@ config BLK_DEV_IDE_PMAC_BLINK This option enables the use of the sleep LED as a hard drive activity LED. -config BLK_DEV_IDEDMA_PMAC_AUTO - bool "Use DMA by default" - depends on BLK_DEV_IDEDMA_PMAC - help - This option allows the driver for the built-in IDE controller on - Power Macintoshes and PowerBooks to use DMA automatically, without - it having to be explicitly enabled. This option is provided because - of concerns about a couple of cases where using DMA on buggy PC - hardware may have caused damage. Saying Y should be safe on all - Apple machines. - config IDE_ARM def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) @@ -835,6 +810,13 @@ config BLK_DEV_IDE_RAPIDE Say Y here if you want to support the Yellowstone RapIDE controller manufactured for use with Acorn computers. +config BLK_DEV_IDE_BAST + tristate "Simtec BAST / Thorcom VR1000 IDE support" + depends on ARM && (ARCH_BAST || MACH_VR100) + help + Say Y here if you want to support the onboard IDE channels on the + Simtec BAST or the Thorcom VR1000 + config BLK_DEV_GAYLE bool "Amiga Gayle IDE interface support" depends on AMIGA @@ -1005,19 +987,6 @@ config BLK_DEV_HT6560B See the and files for more info. -config BLK_DEV_PDC4030 - tristate "PROMISE DC4030 support (EXPERIMENTAL)" - depends on BLK_DEV_IDEDISK && EXPERIMENTAL - help - This driver provides support for the secondary IDE interface and - cache of the original Promise IDE chipsets, e.g. DC4030 and DC5030. - It is nothing to do with the later range of Promise UDMA chipsets - - see the PDC_202XX support for these. CD-ROM and TAPE devices are not - supported (and probably never will be since I don't think the cards - support them). This driver is enabled at runtime using the "ide0=dc4030" - or "ide1=dc4030" kernel boot parameter. See the - file for more info. - config BLK_DEV_QD65XX tristate "QDI QD65xx support" help @@ -1057,7 +1026,7 @@ config IDEDMA_IVB It is normally safe to answer Y; however, the default is N. config IDEDMA_AUTO - def_bool IDEDMA_PCI_AUTO || BLK_DEV_IDEDMA_PMAC_AUTO || IDEDMA_ICS_AUTO + def_bool IDEDMA_PCI_AUTO || IDEDMA_ICS_AUTO endif diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index aeac73d8a..eb3c80877 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ obj-$(CONFIG_BLK_DEV_HD) += legacy/ +obj-$(CONFIG_ETRAX_IDE) += cris/ diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile index ba897493d..6a78f0755 100644 --- a/drivers/ide/arm/Makefile +++ b/drivers/ide/arm/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o +obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index f40a61320..a90f41e4d 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -1,7 +1,9 @@ /* * linux/drivers/ide/arm/icside.c * - * Copyright (c) 1996-2003 Russell King. + * Copyright (c) 1996-2004 Russell King. + * + * Please note that this platform does not support 32-bit IDE IO. */ #include @@ -16,6 +18,7 @@ #include #include #include +#include #include #include @@ -23,21 +26,21 @@ #define ICS_IDENT_OFFSET 0x2280 -#define ICS_ARCIN_V5_INTRSTAT 0x000 -#define ICS_ARCIN_V5_INTROFFSET 0x001 -#define ICS_ARCIN_V5_IDEOFFSET 0xa00 -#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0 -#define ICS_ARCIN_V5_IDESTEPPING 4 - -#define ICS_ARCIN_V6_IDEOFFSET_1 0x800 -#define ICS_ARCIN_V6_INTROFFSET_1 0x880 -#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4 -#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0 -#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00 -#define ICS_ARCIN_V6_INTROFFSET_2 0xc80 -#define ICS_ARCIN_V6_INTRSTAT_2 0xca4 -#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0 -#define ICS_ARCIN_V6_IDESTEPPING 4 +#define ICS_ARCIN_V5_INTRSTAT 0x0000 +#define ICS_ARCIN_V5_INTROFFSET 0x0004 +#define ICS_ARCIN_V5_IDEOFFSET 0x2800 +#define ICS_ARCIN_V5_IDEALTOFFSET 0x2b80 +#define ICS_ARCIN_V5_IDESTEPPING 6 + +#define ICS_ARCIN_V6_IDEOFFSET_1 0x2000 +#define ICS_ARCIN_V6_INTROFFSET_1 0x2200 +#define ICS_ARCIN_V6_INTRSTAT_1 0x2290 +#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x2380 +#define ICS_ARCIN_V6_IDEOFFSET_2 0x3000 +#define ICS_ARCIN_V6_INTROFFSET_2 0x3200 +#define ICS_ARCIN_V6_INTRSTAT_2 0x3290 +#define ICS_ARCIN_V6_IDEALTOFFSET_2 0x3380 +#define ICS_ARCIN_V6_IDESTEPPING 6 struct cardinfo { unsigned int dataoffset; @@ -46,28 +49,28 @@ struct cardinfo { }; static struct cardinfo icside_cardinfo_v5 = { - ICS_ARCIN_V5_IDEOFFSET, - ICS_ARCIN_V5_IDEALTOFFSET, - ICS_ARCIN_V5_IDESTEPPING + .dataoffset = ICS_ARCIN_V5_IDEOFFSET, + .ctrloffset = ICS_ARCIN_V5_IDEALTOFFSET, + .stepping = ICS_ARCIN_V5_IDESTEPPING, }; static struct cardinfo icside_cardinfo_v6_1 = { - ICS_ARCIN_V6_IDEOFFSET_1, - ICS_ARCIN_V6_IDEALTOFFSET_1, - ICS_ARCIN_V6_IDESTEPPING + .dataoffset = ICS_ARCIN_V6_IDEOFFSET_1, + .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_1, + .stepping = ICS_ARCIN_V6_IDESTEPPING, }; static struct cardinfo icside_cardinfo_v6_2 = { - ICS_ARCIN_V6_IDEOFFSET_2, - ICS_ARCIN_V6_IDEALTOFFSET_2, - ICS_ARCIN_V6_IDESTEPPING + .dataoffset = ICS_ARCIN_V6_IDEOFFSET_2, + .ctrloffset = ICS_ARCIN_V6_IDEALTOFFSET_2, + .stepping = ICS_ARCIN_V6_IDESTEPPING, }; struct icside_state { unsigned int channel; unsigned int enabled; - unsigned long irq_port; - unsigned long slot_port; + void __iomem *irq_port; + void __iomem *ioc_base; unsigned int type; /* parent device... until the IDE core gets one of its own */ struct device *dev; @@ -87,9 +90,8 @@ struct icside_state { static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) { struct icside_state *state = ec->irq_data; - unsigned int base = state->irq_port; - outb(0, base + ICS_ARCIN_V5_INTROFFSET); + writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET); } /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) @@ -98,9 +100,8 @@ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) { struct icside_state *state = ec->irq_data; - unsigned int base = state->irq_port; - inb(base + ICS_ARCIN_V5_INTROFFSET); + readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET); } static const expansioncard_ops_t icside_ops_arcin_v5 = { @@ -116,18 +117,18 @@ static const expansioncard_ops_t icside_ops_arcin_v5 = { static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) { struct icside_state *state = ec->irq_data; - unsigned int base = state->irq_port; + void __iomem *base = state->irq_port; state->enabled = 1; switch (state->channel) { case 0: - outb(0, base + ICS_ARCIN_V6_INTROFFSET_1); - inb(base + ICS_ARCIN_V6_INTROFFSET_2); + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); + readb(base + ICS_ARCIN_V6_INTROFFSET_2); break; case 1: - outb(0, base + ICS_ARCIN_V6_INTROFFSET_2); - inb(base + ICS_ARCIN_V6_INTROFFSET_1); + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); + readb(base + ICS_ARCIN_V6_INTROFFSET_1); break; } } @@ -141,8 +142,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) state->enabled = 0; - inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); } /* Prototype: icside_irqprobe(struct expansion_card *ec) @@ -152,8 +153,8 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec) { struct icside_state *state = ec->irq_data; - return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || - inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; + return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; } static const expansioncard_ops_t icside_ops_arcin_v6 = { @@ -179,23 +180,28 @@ static void icside_maskproc(ide_drive_t *drive, int mask) if (state->enabled && !mask) { switch (hwif->channel) { case 0: - outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); break; case 1: - outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); break; } } else { - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); } local_irq_restore(flags); } #ifdef CONFIG_BLK_DEV_IDEDMA_ICS + +#ifndef CONFIG_IDEDMA_ICS_AUTO +#warning CONFIG_IDEDMA_ICS_AUTO=n support is obsolete, and will be removed soon. +#endif + /* * SG-DMA support. * @@ -205,46 +211,24 @@ static void icside_maskproc(ide_drive_t *drive, int mask) * here, but we rely on the main IDE driver spotting that both * interfaces use the same IRQ, which should guarantee this. */ -#define NR_ENTRIES 256 -#define TABLE_SIZE (NR_ENTRIES * 8) static void icside_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct icside_state *state = hwif->hwif_data; struct scatterlist *sg = hwif->sg_table; - int nents; - BUG_ON(hwif->sg_dma_active); - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - hwif->sg_dma_direction = DMA_TO_DEVICE; - else - hwif->sg_dma_direction = DMA_FROM_DEVICE; - - memset(sg, 0, sizeof(*sg)); - sg->page = virt_to_page(rq->buffer); - sg->offset = offset_in_page(rq->buffer); - sg->length = rq->nr_sectors * SECTOR_SIZE; - nents = 1; - } else { - nents = blk_rq_map_sg(drive->queue, rq, sg); + ide_map_sg(drive, rq); - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; - } - - nents = dma_map_sg(state->dev, sg, nents, hwif->sg_dma_direction); + if (rq_data_dir(rq) == READ) + hwif->sg_dma_direction = DMA_FROM_DEVICE; + else + hwif->sg_dma_direction = DMA_TO_DEVICE; - hwif->sg_nents = nents; + hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents, + hwif->sg_dma_direction); } - /* * Configure the IOMD to give the appropriate timings for the transfer * mode being requested. We take the advice of the ATA standards, and @@ -401,19 +385,16 @@ static int icside_dma_end(ide_drive_t *drive) dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); - hwif->sg_dma_active = 0; - return get_dma_residue(hwif->hw.dma) != 0; } -static int icside_dma_begin(ide_drive_t *drive) +static void icside_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); /* We can not enable DMA on both channels simultaneously. */ BUG_ON(dma_channel_active(hwif->hw.dma)); enable_dma(hwif->hw.dma); - return 0; } /* @@ -445,16 +426,20 @@ static ide_startstop_t icside_dmaintr(ide_drive_t *drive) return DRIVER(drive)->error(drive, __FUNCTION__, stat); } -static int -icside_dma_common(ide_drive_t *drive, struct request *rq, - unsigned int dma_mode) +static int icside_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); + struct request *rq = hwif->hwgroup->rq; + unsigned int dma_mode; + + if (rq_data_dir(rq)) + dma_mode = DMA_MODE_WRITE; + else + dma_mode = DMA_MODE_READ; /* * We can not enable DMA on both channels. */ - BUG_ON(hwif->sg_dma_active); BUG_ON(dma_channel_active(hwif->hw.dma)); icside_build_sglist(drive, rq); @@ -467,7 +452,7 @@ icside_dma_common(ide_drive_t *drive, struct request *rq, /* * Route the DMA signals to the correct interface. */ - outb(hwif->select_data, hwif->config_data); + writeb(hwif->select_data, hwif->config_data); /* * Select the correct timing for this drive. @@ -486,79 +471,10 @@ icside_dma_common(ide_drive_t *drive, struct request *rq, return 0; } -static int icside_dma_read(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd; - - if (icside_dma_common(drive, rq, DMA_MODE_READ)) - return 1; - - if (drive->media != ide_disk) - return 0; - - BUG_ON(HWGROUP(drive)->handler != NULL); - - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } else if (drive->addressing == 1) { - cmd = WIN_READDMA_EXT; - } else { - cmd = WIN_READDMA; - } -#endif - /* issue cmd to drive */ - ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); - - return icside_dma_begin(drive); -} - -static int icside_dma_write(ide_drive_t *drive) +static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd) { - struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd; - - if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) - return 1; - - if (drive->media != ide_disk) - return 0; - - BUG_ON(HWGROUP(drive)->handler != NULL); - - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - cmd = args->tfRegister[IDE_COMMAND_OFFSET]; - } else if (drive->addressing == 1) { - cmd = WIN_WRITEDMA_EXT; - } else { - cmd = WIN_WRITEDMA; - } -#endif - /* issue cmd to drive */ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); - - return icside_dma_begin(drive); } static int icside_dma_test_irq(ide_drive_t *drive) @@ -566,20 +482,12 @@ static int icside_dma_test_irq(ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); struct icside_state *state = hwif->hwif_data; - return inb(state->irq_port + - (hwif->channel ? + return readb(state->irq_port + + (hwif->channel ? ICS_ARCIN_V6_INTRSTAT_2 : ICS_ARCIN_V6_INTRSTAT_1)) & 1; } -static int icside_dma_verbose(ide_drive_t *drive) -{ - printk(", %s (peak %dMB/s)", - ide_xfer_verbose(drive->current_speed), - 2000 / drive->drive_data); - return 1; -} - static int icside_dma_timeout(ide_drive_t *drive) { printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); @@ -599,7 +507,7 @@ static int icside_dma_lostirq(ide_drive_t *drive) return 1; } -static int icside_dma_init(ide_hwif_t *hwif) +static void icside_dma_init(ide_hwif_t *hwif) { int autodma = 0; @@ -609,11 +517,6 @@ static int icside_dma_init(ide_hwif_t *hwif) printk(" %s: SG-DMA", hwif->name); - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, - GFP_KERNEL); - if (!hwif->sg_table) - goto failed; - hwif->atapi_dma = 1; hwif->mwdma_mask = 7; /* MW0..2 */ hwif->swdma_mask = 7; /* SW0..2 */ @@ -628,12 +531,11 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->ide_dma_off_quietly = icside_dma_off_quietly; hwif->ide_dma_host_on = icside_dma_host_on; hwif->ide_dma_on = icside_dma_on; - hwif->ide_dma_read = icside_dma_read; - hwif->ide_dma_write = icside_dma_write; - hwif->ide_dma_begin = icside_dma_begin; + hwif->dma_setup = icside_dma_setup; + hwif->dma_exec_cmd = icside_dma_exec_cmd; + hwif->dma_start = icside_dma_start; hwif->ide_dma_end = icside_dma_end; hwif->ide_dma_test_irq = icside_dma_test_irq; - hwif->ide_dma_verbose = icside_dma_verbose; hwif->ide_dma_timeout = icside_dma_timeout; hwif->ide_dma_lostirq = icside_dma_lostirq; @@ -641,24 +543,9 @@ static int icside_dma_init(ide_hwif_t *hwif) hwif->drives[1].autodma = hwif->autodma; printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); - - return 1; - -failed: - printk(" disabled, unable to allocate DMA table\n"); - return 0; -} - -static void icside_dma_exit(ide_hwif_t *hwif) -{ - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } } #else #define icside_dma_init(hwif) (0) -#define icside_dma_exit(hwif) do { } while (0) #endif static ide_hwif_t *icside_find_hwif(unsigned long dataport) @@ -684,24 +571,30 @@ found: } static ide_hwif_t * -icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec) +icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec) { - unsigned long port = base + info->dataoffset; + unsigned long port = (unsigned long)base + info->dataoffset; ide_hwif_t *hwif; - hwif = icside_find_hwif(base); + hwif = icside_find_hwif(port); if (hwif) { int i; memset(&hwif->hw, 0, sizeof(hw_regs_t)); + /* + * Ensure we're using MMIO + */ + default_hwif_mmiops(hwif); + hwif->mmio = 2; + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { hwif->hw.io_ports[i] = port; hwif->io_ports[i] = port; port += 1 << info->stepping; } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; - hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset; + hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset; hwif->hw.irq = ec->irq; hwif->irq = ec->irq; hwif->noprobe = 0; @@ -715,14 +608,17 @@ icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *e static int __init icside_register_v5(struct icside_state *state, struct expansion_card *ec) { - unsigned long slot_port; ide_hwif_t *hwif; + void __iomem *base; - slot_port = ecard_address(ec, ECARD_MEMC, 0); + base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!base) + return -ENOMEM; - state->irq_port = slot_port; + state->irq_port = base; - ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); + ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT; ec->irqmask = 1; ec->irq_data = state; ec->ops = &icside_ops_arcin_v5; @@ -730,61 +626,86 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) /* * Be on the safe side - disable interrupts */ - inb(slot_port + ICS_ARCIN_V5_INTROFFSET); + icside_irqdisable_arcin_v5(ec, 0); - hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec); + hwif = icside_setup(base, &icside_cardinfo_v5, ec); + if (!hwif) { + iounmap(base); + return -ENODEV; + } state->hwif[0] = hwif; - return hwif ? 0 : -ENODEV; + probe_hwif_init(hwif); + create_proc_ide_interfaces(); + + return 0; } static int __init icside_register_v6(struct icside_state *state, struct expansion_card *ec) { - unsigned long slot_port, port; ide_hwif_t *hwif, *mate; + void __iomem *ioc_base, *easi_base; unsigned int sel = 0; + int ret; - slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); - port = ecard_address(ec, ECARD_EASI, ECARD_FAST); + ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), + ecard_resource_len(ec, ECARD_RES_IOCFAST)); + if (!ioc_base) { + ret = -ENOMEM; + goto out; + } - if (port == 0) - port = slot_port; - else + easi_base = ioc_base; + + if (ecard_resource_flags(ec, ECARD_RES_EASI)) { + easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI), + ecard_resource_len(ec, ECARD_RES_EASI)); + if (!easi_base) { + ret = -ENOMEM; + goto unmap_slot; + } + + /* + * Enable access to the EASI region. + */ sel = 1 << 5; + } - outb(sel, slot_port); + writeb(sel, ioc_base); + + ec->irq_data = state; + ec->ops = &icside_ops_arcin_v6; + + state->irq_port = easi_base; + state->ioc_base = ioc_base; /* * Be on the safe side - disable interrupts */ - inb(port + ICS_ARCIN_V6_INTROFFSET_1); - inb(port + ICS_ARCIN_V6_INTROFFSET_2); + icside_irqdisable_arcin_v6(ec, 0); /* * Find and register the interfaces. */ - hwif = icside_setup(port, &icside_cardinfo_v6_1, ec); - mate = icside_setup(port, &icside_cardinfo_v6_2, ec); + hwif = icside_setup(easi_base, &icside_cardinfo_v6_1, ec); + mate = icside_setup(easi_base, &icside_cardinfo_v6_2, ec); - if (!hwif || !mate) - return -ENODEV; + if (!hwif || !mate) { + ret = -ENODEV; + goto unmap_port; + } - state->irq_port = port; - state->slot_port = slot_port; state->hwif[0] = hwif; state->hwif[1] = mate; - ec->irq_data = state; - ec->ops = &icside_ops_arcin_v6; - hwif->maskproc = icside_maskproc; hwif->channel = 0; hwif->hwif_data = state; hwif->mate = mate; hwif->serialized = 1; - hwif->config_data = slot_port; + hwif->config_data = (unsigned long)ioc_base; hwif->select_data = sel; hwif->hw.dma = ec->dma; @@ -793,7 +714,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) mate->hwif_data = state; mate->mate = hwif; mate->serialized = 1; - mate->config_data = slot_port; + mate->config_data = (unsigned long)ioc_base; mate->select_data = sel | 1; mate->hw.dma = ec->dma; @@ -802,7 +723,19 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) icside_dma_init(mate); } + probe_hwif_init(hwif); + probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; + + unmap_port: + if (easi_base != ioc_base) + iounmap(easi_base); + unmap_slot: + iounmap(ioc_base); + out: + return ret; } static int __devinit @@ -812,10 +745,14 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id) void *idmem; int ret; + ret = ecard_request_resources(ec); + if (ret) + goto out; + state = kmalloc(sizeof(struct icside_state), GFP_KERNEL); if (!state) { ret = -ENOMEM; - goto out; + goto release; } memset(state, 0, sizeof(state)); @@ -838,12 +775,12 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id) switch (state->type) { case ICS_TYPE_A3IN: - printk(KERN_WARNING "icside: A3IN unsupported\n"); + dev_warn(&ec->dev, "A3IN unsupported\n"); ret = -ENODEV; break; case ICS_TYPE_A3USER: - printk(KERN_WARNING "icside: A3USER unsupported\n"); + dev_warn(&ec->dev, "A3USER unsupported\n"); ret = -ENODEV; break; @@ -856,15 +793,19 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id) break; default: - printk(KERN_WARNING "icside: unknown interface type\n"); + dev_warn(&ec->dev, "unknown interface type\n"); ret = -ENODEV; break; } - if (ret == 0) + if (ret == 0) { ecard_set_drvdata(ec, state); - else - kfree(state); + goto out; + } + + kfree(state); + release: + ecard_release_resources(ec); out: return ret; } @@ -878,23 +819,19 @@ static void __devexit icside_remove(struct expansion_card *ec) /* FIXME: tell IDE to stop using the interface */ /* Disable interrupts */ - inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); + icside_irqdisable_arcin_v5(ec, 0); break; case ICS_TYPE_V6: /* FIXME: tell IDE to stop using the interface */ - icside_dma_exit(state->hwif[1]); - icside_dma_exit(state->hwif[0]); - if (ec->dma != NO_DMA) free_dma(ec->dma); /* Disable interrupts */ - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + icside_irqdisable_arcin_v6(ec, 0); /* Reset the ROM pointer/EASI selection */ - outb(0, state->slot_port); + writeb(0, state->ioc_base); break; } @@ -902,28 +839,36 @@ static void __devexit icside_remove(struct expansion_card *ec) ec->ops = NULL; ec->irq_data = NULL; + if (state->ioc_base) + iounmap(state->ioc_base); + if (state->ioc_base != state->irq_port) + iounmap(state->irq_port); + kfree(state); + ecard_release_resources(ec); } static void icside_shutdown(struct expansion_card *ec) { struct icside_state *state = ecard_get_drvdata(ec); + unsigned long flags; - switch (state->type) { - case ICS_TYPE_V5: - /* Disable interrupts */ - inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET); - break; - - case ICS_TYPE_V6: - /* Disable interrupts */ - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); - inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + /* + * Disable interrupts from this card. We need to do + * this before disabling EASI since we may be accessing + * this register via that region. + */ + local_irq_save(flags); + ec->ops->irqdisable(ec, 0); + local_irq_restore(flags); - /* Reset the ROM pointer/EASI selection */ - outb(0, state->slot_port); - break; - } + /* + * Reset the ROM pointer so that we can read the ROM + * after a soft reboot. This also disables access to + * the IDE taskfile via the EASI region. + */ + if (state->ioc_base) + writeb(0, state->ioc_base); } static const struct ecard_id icside_ids[] = { diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index 2269c28d0..b0a115d1a 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -13,32 +13,91 @@ #include -static int __devinit -rapide_probe(struct expansion_card *ec, const struct ecard_id *id) +/* + * Something like this really should be in generic code, but isn't. + */ +static ide_hwif_t * +rapide_locate_hwif(void __iomem *base, void *ctrl, unsigned int sz, int irq) { - unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - hw_regs_t hw; - int i, ret; + unsigned long port = (unsigned long)base; + ide_hwif_t *hwif; + int index, i; + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = ide_hwifs + index; + if (hwif->io_ports[IDE_DATA_OFFSET] == port) + goto found; + } + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = ide_hwifs + index; + if (hwif->io_ports[IDE_DATA_OFFSET] == 0) + goto found; + } - memset(&hw, 0, sizeof(hw)); + return NULL; + found: for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw.io_ports[i] = port; - port += 1 << 4; + hwif->hw.io_ports[i] = port; + hwif->io_ports[i] = port; + port += sz; } - hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; - hw.irq = ec->irq; + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hwif->hw.irq = hwif->irq = irq; + hwif->mmio = 2; + default_hwif_mmiops(hwif); + + return hwif; +} - ret = ide_register_hw(&hw, NULL); +static int __devinit +rapide_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + ide_hwif_t *hwif; + void __iomem *base; + int ret; + ret = ecard_request_resources(ec); if (ret) - ecard_release(ec); + goto out; + + base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!base) { + ret = -ENOMEM; + goto release; + } + + hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq); + if (hwif) { + hwif->hwif_data = base; + hwif->gendev.parent = &ec->dev; + hwif->noprobe = 0; + probe_hwif_init(hwif); + create_proc_ide_interfaces(); + ecard_set_drvdata(ec, hwif); + goto out; + } + + iounmap(base); + release: + ecard_release_resources(ec); + out: return ret; } static void __devexit rapide_remove(struct expansion_card *ec) { - /* need to do more */ + ide_hwif_t *hwif = ecard_get_drvdata(ec); + + ecard_set_drvdata(ec, NULL); + + /* there must be a better way */ + ide_unregister(hwif - ide_hwifs); + iounmap(hwif->hwif_data); + ecard_release_resources(ec); } static struct ecard_id rapide_ids[] = { diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c3d6286eb..2dae7b293 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -562,7 +562,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, /* * ide_error() takes action based on the error returned by the drive. */ -ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) +static ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) { struct request *rq; byte err; @@ -598,7 +598,7 @@ ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) return ide_stopped; } -ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg) +static ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg) { struct request *rq; @@ -865,20 +865,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, { ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; /* Wait for the controller to be idle. */ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->ide_dma_read(drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->ide_dma_write(drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } - } + if (info->dma) + info->dma = !hwif->dma_setup(drive); /* Set up the controller registers. */ /* FIXME: for Virtual DMA we must check harder */ @@ -896,8 +890,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; } else { + unsigned long flags; + /* packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + spin_lock_irqsave(&ide_lock, flags); + hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG); + ndelay(400); + spin_unlock_irqrestore(&ide_lock, flags); + return (*handler) (drive); } } @@ -916,6 +916,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct request *rq, ide_handler_t *handler) { + ide_hwif_t *hwif = drive->hwif; int cmd_len; struct cdrom_info *info = drive->driver_data; ide_startstop_t startstop; @@ -947,7 +948,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, /* Start the DMA if need be */ if (info->dma) - (void) HWIF(drive)->ide_dma_begin(drive); + hwif->dma_start(drive); return ide_started; } @@ -1932,6 +1933,8 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) info->dma = drive->using_dma ? 1 : 0; info->cmd = WRITE; + info->devinfo.media_written = 1; + /* Start sending the write request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); } @@ -1999,7 +2002,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) } CDROM_CONFIG_FLAGS(drive)->seeking = 0; } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { + if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { action = cdrom_start_seek(drive, block); } else { if (rq_data_dir(rq) == READ) @@ -2356,25 +2359,31 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) /* Read the multisession information. */ if (toc->hdr.first_track != CDROM_LEADOUT) { /* Read the multisession information. */ - stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); if (stat) return stat; + + toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; + toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ } #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) + if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { + /* Re-read multisession information using MSF format */ + stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + sizeof(ms_tmp), sense); + if (stat) + return stat; + msf_from_bcd (&ms_tmp.ent.addr.msf); + toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute, + ms_tmp.ent.addr.msf.second, + ms_tmp.ent.addr.msf.frame); + } #endif /* not STANDARD_ATAPI */ - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); /* Now try to get the total cdrom capacity. */ @@ -2719,8 +2728,10 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) if (!cdrom_get_media_event(cdi, &med)) { if (med.media_present) return CDS_DISC_OK; - if (med.door_open) + else if (med.door_open) return CDS_TRAY_OPEN; + else + return CDS_NO_DISC; } if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04) @@ -2732,10 +2743,12 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) * any other way to detect this... */ if (sense.sense_key == NOT_READY) { - if (sense.asc == 0x3a && sense.ascq == 1) - return CDS_NO_DISC; - else - return CDS_TRAY_OPEN; + if (sense.asc == 0x3a) { + if (sense.ascq == 0 || sense.ascq == 1) + return CDS_NO_DISC; + else if (sense.ascq == 2) + return CDS_TRAY_OPEN; + } } return CDS_DRIVE_NOT_READY; @@ -2956,8 +2969,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) CDROM_CONFIG_FLAGS(drive)->no_eject = 0; if (cap.cd_r_write) CDROM_CONFIG_FLAGS(drive)->cd_r = 1; - if (cap.cd_rw_write) + if (cap.cd_rw_write) { CDROM_CONFIG_FLAGS(drive)->cd_rw = 1; + CDROM_CONFIG_FLAGS(drive)->ram = 1; + } if (cap.test_write) CDROM_CONFIG_FLAGS(drive)->test_write = 1; if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom) @@ -3036,10 +3051,9 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) - (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ + ide_dma_verbose(drive); + printk("\n"); return nslots; @@ -3428,9 +3442,9 @@ static struct block_device_operations idecd_ops = { }; /* options */ -char *ignore = NULL; +static char *ignore = NULL; -MODULE_PARM(ignore, "s"); +module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); static int ide_cdrom_attach (ide_drive_t *drive) diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 8305bcab8..20a01dfa0 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -519,7 +519,7 @@ struct cdrom_info { /* The generic packet command opcodes for CD/DVD Logical Units, * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { +static const struct { unsigned short packet_command; const char * const text; } packet_command_texts[] = { @@ -577,7 +577,7 @@ const struct { /* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const char * const sense_key_texts[16] = { +static const char * const sense_key_texts[16] = { "No sense data", "Recovered error", "Not ready", @@ -597,7 +597,7 @@ const char * const sense_key_texts[16] = { }; /* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -const struct { +static const struct { unsigned long asc_ascq; const char * const text; } sense_data_texts[] = { diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c index ef6e2c8c2..a6bea5d0d 100644 --- a/drivers/ide/ide-default.c +++ b/drivers/ide/ide-default.c @@ -23,13 +23,13 @@ #include #include #include +#include #include #include #include #include #include -#include #define IDEDEFAULT_VERSION "0.9.newide" /* diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 7b3bf05cb..44a49da84 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -71,10 +71,6 @@ #include #include -/* FIXME: some day we shouldn't need to look in here! */ - -#include "legacy/pdc4030.h" - /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" * value for this drive (from its reported identification information). @@ -120,218 +116,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id) return 0; /* lba_capacity value may be bad */ } -#ifndef CONFIG_IDE_TASKFILE_IO - -/* - * read_intr() is the handler for disk read/multread interrupts - */ -static ide_startstop_t read_intr (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u32 i = 0, nsect = 0, msect = drive->mult_count; - struct request *rq; - unsigned long flags; - u8 stat; - char *to; - - /* new way for dealing with premature shared PCI interrupts */ - if (!OK_STAT(stat=hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) { - if (stat & (ERR_STAT|DRQ_STAT)) { - return DRIVER(drive)->error(drive, "read_intr", stat); - } - /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - -read_next: - rq = HWGROUP(drive)->rq; - if (msect) { - if ((nsect = rq->current_nr_sectors) > msect) - nsect = msect; - msect -= nsect; - } else - nsect = 1; - to = ide_map_buffer(rq, &flags); - taskfile_input_data(drive, to, nsect * SECTOR_WORDS); -#ifdef DEBUG - printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, rq->sector+nsect-1, - (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect); -#endif - ide_unmap_buffer(rq, to, &flags); - rq->sector += nsect; - rq->errors = 0; - i = (rq->nr_sectors -= nsect); - if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(drive, 1, rq->hard_cur_sectors); - /* - * Another BH Page walker and DATA INTEGRITY Questioned on ERROR. - * If passed back up on multimode read, BAD DATA could be ACKED - * to FILE SYSTEMS above ... - */ - if (i > 0) { - if (msect) - goto read_next; - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; -} - -/* - * write_intr() is the handler for disk write interrupts - */ -static ide_startstop_t write_intr (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = hwgroup->rq; - u32 i = 0; - u8 stat; - - if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), - DRIVE_READY, drive->bad_wstat)) { - printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", - drive->name, rq->nr_sectors, stat); - } else { -#ifdef DEBUG - printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n", - drive->name, rq->sector, (unsigned long) rq->buffer, - rq->nr_sectors-1); -#endif - if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) { - rq->sector++; - rq->errors = 0; - i = --rq->nr_sectors; - --rq->current_nr_sectors; - if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(drive, 1, rq->hard_cur_sectors); - if (i > 0) { - unsigned long flags; - char *to = ide_map_buffer(rq, &flags); - taskfile_output_data(drive, to, SECTOR_WORDS); - ide_unmap_buffer(rq, to, &flags); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; - } - /* the original code did this here (?) */ - return ide_stopped; - } - return DRIVER(drive)->error(drive, "write_intr", stat); -} - -/* - * ide_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multiple-sector write operation. - * - * Note that we may be called from two contexts - __ide_do_rw_disk() context - * and IRQ context. The IRQ can happen any time after we've output the - * full "mcount" number of sectors, so we must make sure we update the - * state _before_ we output the final part of the data! - * - * The update and return to BH is a BLOCK Layer Fakey to get more data - * to satisfy the hardware atomic segment. If the hardware atomic segment - * is shorter or smaller than the BH segment then we should be OKAY. - * This is only valid if we can rewind the rq->current_nr_sectors counter. - */ -static void ide_multwrite(ide_drive_t *drive, unsigned int mcount) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct request *rq = &hwgroup->wrq; - - do { - char *buffer; - int nsect = rq->current_nr_sectors; - unsigned long flags; - - if (nsect > mcount) - nsect = mcount; - mcount -= nsect; - buffer = ide_map_buffer(rq, &flags); - - rq->sector += nsect; - rq->nr_sectors -= nsect; - rq->current_nr_sectors -= nsect; - - /* Do we move to the next bh after this? */ - if (!rq->current_nr_sectors) { - struct bio *bio = rq->bio; - - /* - * only move to next bio, when we have processed - * all bvecs in this one. - */ - if (++bio->bi_idx >= bio->bi_vcnt) { - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - bio = bio->bi_next; - } - - /* end early early we ran out of requests */ - if (!bio) { - mcount = 0; - } else { - rq->bio = bio; - rq->nr_cbio_segments = bio_segments(bio); - rq->current_nr_sectors = bio_cur_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - } - } - - /* - * Ok, we're all setup for the interrupt - * re-entering us on the last transfer. - */ - taskfile_output_data(drive, buffer, nsect<<7); - ide_unmap_buffer(rq, buffer, &flags); - } while (mcount); -} - -/* - * multwrite_intr() is the handler for disk multwrite interrupts - */ -static ide_startstop_t multwrite_intr (ide_drive_t *drive) -{ - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = &hwgroup->wrq; - struct bio *bio = rq->bio; - u8 stat; - - stat = hwif->INB(IDE_STATUS_REG); - if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) { - if (stat & DRQ_STAT) { - /* - * The drive wants data. Remember rq is the copy - * of the request - */ - if (rq->nr_sectors) { - ide_multwrite(drive, drive->mult_count); - ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - return ide_started; - } - } else { - /* - * If the copy has all the blocks completed then - * we can end the original request. - */ - if (!rq->nr_sectors) { /* all done? */ - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - rq = hwgroup->rq; - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; - } - } - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - /* the original code did this here (?) */ - return ide_stopped; - } - bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments; - return DRIVER(drive)->error(drive, "multwrite_intr", stat); -} - /* * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. @@ -340,15 +124,28 @@ static ide_startstop_t multwrite_intr (ide_drive_t *drive) ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) { ide_hwif_t *hwif = HWIF(drive); + unsigned int dma = drive->using_dma; u8 lba48 = (drive->addressing == 1) ? 1 : 0; task_ioreg_t command = WIN_NOP; ata_nsector_t nsectors; nsectors.all = (u16) rq->nr_sectors; + if (hwif->no_lba48_dma && lba48 && dma) { + if (rq->sector + rq->nr_sectors > 1ULL << 28) + dma = 0; + } + + if (!dma) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } + if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + /* FIXME: SELECT_MASK(drive, 0) ? */ + if (drive->select.b.lba) { if (drive->addressing == 1) { task_ioreg_t tasklets[10]; @@ -413,163 +210,54 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); } - if (rq_data_dir(rq) == READ) { - if (drive->using_dma && !hwif->ide_dma_read(drive)) - return ide_started; - - command = ((drive->mult_count) ? - ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : - ((lba48) ? WIN_READ_EXT : WIN_READ)); - ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); - return ide_started; - } else { - ide_startstop_t startstop; - - if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive))) + if (dma) { + if (!hwif->dma_setup(drive)) { + if (rq_data_dir(rq)) { + command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; + if (drive->vdma) + command = lba48 ? WIN_WRITE_EXT: WIN_WRITE; + } else { + command = lba48 ? WIN_READDMA_EXT : WIN_READDMA; + if (drive->vdma) + command = lba48 ? WIN_READ_EXT: WIN_READ; + } + hwif->dma_exec_cmd(drive, command); + hwif->dma_start(drive); return ide_started; - - command = ((drive->mult_count) ? - ((lba48) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE) : - ((lba48) ? WIN_WRITE_EXT : WIN_WRITE)); - hwif->OUTB(command, IDE_COMMAND_REG); - - if (ide_wait_stat(&startstop, drive, DATA_READY, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - if (!drive->unmask) - local_irq_disable(); - if (drive->mult_count) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - - hwgroup->wrq = *rq; /* scratchpad */ - ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); - ide_multwrite(drive, drive->mult_count); - } else { - unsigned long flags; - char *to = ide_map_buffer(rq, &flags); - ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); - taskfile_output_data(drive, to, SECTOR_WORDS); - ide_unmap_buffer(rq, to, &flags); } - return ide_started; + /* fallback to PIO */ + ide_init_sg_cmd(drive, rq); } -} -EXPORT_SYMBOL_GPL(__ide_do_rw_disk); -#else /* CONFIG_IDE_TASKFILE_IO */ - -static ide_startstop_t chs_rw_disk(ide_drive_t *, struct request *, unsigned long); -static ide_startstop_t lba_28_rw_disk(ide_drive_t *, struct request *, unsigned long); -static ide_startstop_t lba_48_rw_disk(ide_drive_t *, struct request *, unsigned long long); - -/* - * __ide_do_rw_disk() issues READ and WRITE commands to a disk, - * using LBA if supported, or CHS otherwise, to address sectors. - * It also takes care of issuing special DRIVE_CMDs. - */ -ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) -{ - /* - * 268435455 == 137439 MB or 28bit limit - * - * need to add split taskfile operations based on 28bit threshold. - */ - if (drive->addressing == 1) /* 48-bit LBA */ - return lba_48_rw_disk(drive, rq, (unsigned long long) block); - if (drive->select.b.lba) /* 28-bit LBA */ - return lba_28_rw_disk(drive, rq, (unsigned long) block); - - /* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */ - return chs_rw_disk(drive, rq, (unsigned long) block); -} -EXPORT_SYMBOL_GPL(__ide_do_rw_disk); - -static u8 get_command(ide_drive_t *drive, int cmd, ide_task_t *task) -{ - unsigned int lba48 = (drive->addressing == 1) ? 1 : 0; + if (rq_data_dir(rq) == READ) { - if (cmd == READ) { - task->command_type = IDE_DRIVE_TASK_IN; - if (drive->using_dma) - return lba48 ? WIN_READDMA_EXT : WIN_READDMA; if (drive->mult_count) { - task->handler = &task_mulin_intr; - return lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; + hwif->data_phase = TASKFILE_MULTI_IN; + command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD; + } else { + hwif->data_phase = TASKFILE_IN; + command = lba48 ? WIN_READ_EXT : WIN_READ; } - task->handler = &task_in_intr; - return lba48 ? WIN_READ_EXT : WIN_READ; + + ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL); + return ide_started; } else { - task->command_type = IDE_DRIVE_TASK_RAW_WRITE; - if (drive->using_dma) - return lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->mult_count) { - task->prehandler = &pre_task_mulout_intr; - task->handler = &task_mulout_intr; - return lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; + hwif->data_phase = TASKFILE_MULTI_OUT; + command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE; + } else { + hwif->data_phase = TASKFILE_OUT; + command = lba48 ? WIN_WRITE_EXT : WIN_WRITE; } - task->prehandler = &pre_task_out_intr; - task->handler = &task_out_intr; - return lba48 ? WIN_WRITE_EXT : WIN_WRITE; - } -} - -static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_task_t args; - int sectors; - ata_nsector_t nsectors; - unsigned int track = (block / drive->sect); - unsigned int sect = (block % drive->sect) + 1; - unsigned int head = (track % drive->head); - unsigned int cyl = (track / drive->head); - - nsectors.all = (u16) rq->nr_sectors; - - pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); - memset(&args, 0, sizeof(ide_task_t)); - - sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; - - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - args.tfRegister[IDE_SECTOR_OFFSET] = sect; - args.tfRegister[IDE_LCYL_OFFSET] = cyl; - args.tfRegister[IDE_HCYL_OFFSET] = (cyl>>8); - args.tfRegister[IDE_SELECT_OFFSET] = head; - args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; - args.tfRegister[IDE_COMMAND_OFFSET] = get_command(drive, rq_data_dir(rq), &args); - args.rq = (struct request *) rq; - rq->special = (ide_task_t *)&args; - return do_rw_taskfile(drive, &args); -} - -static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) -{ - ide_task_t args; - int sectors; - ata_nsector_t nsectors; - - nsectors.all = (u16) rq->nr_sectors; - - memset(&args, 0, sizeof(ide_task_t)); + /* FIXME: ->OUTBSYNC ? */ + hwif->OUTB(command, IDE_COMMAND_REG); - sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; - - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - args.tfRegister[IDE_SECTOR_OFFSET] = block; - args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); - args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); - args.tfRegister[IDE_SELECT_OFFSET] = ((block>>8)&0x0f); - args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; - args.tfRegister[IDE_COMMAND_OFFSET] = get_command(drive, rq_data_dir(rq), &args); - args.rq = (struct request *) rq; - rq->special = (ide_task_t *)&args; - return do_rw_taskfile(drive, &args); + pre_task_out_intr(drive, rq); + return ide_started; + } } +EXPORT_SYMBOL_GPL(__ide_do_rw_disk); /* * 268435455 == 137439 MB or 28bit limit @@ -577,37 +265,6 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u * 1073741822 == 549756 MB or 48bit addressing fake drive */ -static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block) -{ - ide_task_t args; - int sectors; - ata_nsector_t nsectors; - - nsectors.all = (u16) rq->nr_sectors; - - memset(&args, 0, sizeof(ide_task_t)); - - sectors = (rq->nr_sectors == 65536) ? 0 : rq->nr_sectors; - - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - args.hobRegister[IDE_NSECTOR_OFFSET] = sectors >> 8; - args.tfRegister[IDE_SECTOR_OFFSET] = block; /* low lba */ - args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); /* mid lba */ - args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); /* hi lba */ - args.tfRegister[IDE_SELECT_OFFSET] = drive->select.all; - args.tfRegister[IDE_COMMAND_OFFSET] = get_command(drive, rq_data_dir(rq), &args); - args.hobRegister[IDE_SECTOR_OFFSET] = (block>>=8); /* low lba */ - args.hobRegister[IDE_LCYL_OFFSET] = (block>>=8); /* mid lba */ - args.hobRegister[IDE_HCYL_OFFSET] = (block>>=8); /* hi lba */ - args.hobRegister[IDE_SELECT_OFFSET] = drive->select.all; - args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); - args.rq = (struct request *) rq; - rq->special = (ide_task_t *)&args; - return do_rw_taskfile(drive, &args); -} - -#endif /* CONFIG_IDE_TASKFILE_IO */ - static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) { ide_hwif_t *hwif = HWIF(drive); @@ -638,7 +295,6 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS printk(" { "); if (stat & BUSY_STAT) printk("Busy "); @@ -652,12 +308,10 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) if (stat & ERR_STAT) printk("Error "); } printk("}"); -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); if (err & ICRC_ERR) @@ -700,13 +354,43 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) (unsigned long long)HWGROUP(drive)->rq->sector); } } -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); + { + struct request *rq; + unsigned char opcode = 0; + int found = 0; + + spin_lock(&ide_lock); + rq = HWGROUP(drive)->rq; + spin_unlock(&ide_lock); + if (!rq) + goto out; + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + char *args = rq->buffer; + if (args) { + opcode = args[0]; + found = 1; + } + } else if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + if (args) { + task_struct_t *tf = (task_struct_t *) args->tfRegister; + opcode = tf->command; + found = 1; + } + } + printk("ide: failed opcode was: "); + if (!found) + printk("unknown\n"); + else + printk("0x%02x\n", opcode); + } +out: local_irq_restore(flags); return err; } -ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) +static ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) { ide_hwif_t *hwif; struct request *rq; @@ -724,10 +408,6 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) ide_end_drive_cmd(drive, stat, err); return ide_stopped; } -#ifdef CONFIG_IDE_TASKFILE_IO - /* make rq completion pointers new submission pointers */ - blk_rq_prep_restart(rq); -#endif if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ @@ -770,7 +450,7 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) return ide_stopped; } -ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg) +static ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg) { ide_hwif_t *hwif; struct request *rq; @@ -963,9 +643,6 @@ static inline void idedisk_check_hpa(ide_drive_t *drive) capacity, sectors_to_MB(capacity), set_max, sectors_to_MB(set_max)); - if (!drive->stroke) - return; - if (lba48) set_max = idedisk_set_max_address_ext(drive, set_max); else @@ -1023,6 +700,8 @@ static sector_t idedisk_capacity (ide_drive_t *drive) return drive->capacity64 - drive->sect0; } +#define IS_PDC4030_DRIVE 0 + static ide_startstop_t idedisk_special (ide_drive_t *drive) { special_t *s = &drive->special; @@ -1117,6 +796,7 @@ static int get_smart_values(ide_drive_t *drive, u8 *buf) args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; args.command_type = IDE_DRIVE_TASK_IN; + args.data_phase = TASKFILE_IN; args.handler = &task_in_intr; (void) smart_enable(drive); return ide_raw_taskfile(drive, &args, buf); @@ -1132,6 +812,7 @@ static int get_smart_thresholds(ide_drive_t *drive, u8 *buf) args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; args.command_type = IDE_DRIVE_TASK_IN; + args.data_phase = TASKFILE_IN; args.handler = &task_in_intr; (void) smart_enable(drive); return ide_raw_taskfile(drive, &args, buf); @@ -1203,6 +884,42 @@ static ide_proc_entry_t idedisk_proc[] = { #endif /* CONFIG_PROC_FS */ +static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + ide_drive_t *drive = q->queuedata; + struct request *rq; + int ret; + + if (!drive->wcache) + return 0; + + rq = blk_get_request(q, WRITE, __GFP_WAIT); + + memset(rq->cmd, 0, sizeof(rq->cmd)); + + if (ide_id_has_flush_cache_ext(drive->id) && + (drive->capacity64 >= (1UL << 28))) + rq->cmd[0] = WIN_FLUSH_CACHE_EXT; + else + rq->cmd[0] = WIN_FLUSH_CACHE; + + + rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER; + rq->buffer = rq->cmd; + + ret = blk_execute_rq(q, disk, rq); + + /* + * if we failed and caller wants error offset, get it + */ + if (ret && error_sector) + *error_sector = ide_get_error_location(drive, rq->cmd); + + blk_put_request(rq); + return ret; +} + /* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. @@ -1231,16 +948,10 @@ static int set_nowerr(ide_drive_t *drive, int arg) return 0; } -/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ -#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) - -/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ -#define ide_id_has_flush_cache_ext(id) \ - (((id)->cfs_enable_2 & 0x2400) == 0x2400) - -static int write_cache (ide_drive_t *drive, int arg) +static int write_cache(ide_drive_t *drive, int arg) { ide_task_t args; + int err; if (!ide_id_has_flush_cache(drive->id)) return 1; @@ -1251,7 +962,10 @@ static int write_cache (ide_drive_t *drive, int arg) args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; args.command_type = IDE_DRIVE_TASK_NO_DATA; args.handler = &task_no_data_intr; - (void) ide_raw_taskfile(drive, &args, NULL); + + err = ide_raw_taskfile(drive, &args, NULL); + if (err) + return err; drive->wcache = arg; return 0; @@ -1412,6 +1126,7 @@ static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; unsigned long long capacity; + int barrier; idedisk_add_settings(drive); @@ -1443,7 +1158,7 @@ static void idedisk_setup (ide_drive_t *drive) blk_queue_max_sectors(drive->queue, max_s); } - printk("%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2); + printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2); /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { @@ -1472,13 +1187,22 @@ static void idedisk_setup (ide_drive_t *drive) /* limit drive capacity to 137GB if LBA48 cannot be used */ if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) { - printk("%s: cannot use LBA48 - full capacity " + printk(KERN_WARNING "%s: cannot use LBA48 - full capacity " "%llu sectors (%llu MB)\n", drive->name, (unsigned long long)drive->capacity64, sectors_to_MB(drive->capacity64)); drive->capacity64 = 1ULL << 28; } + if (drive->hwif->no_lba48_dma && drive->addressing) { + if (drive->capacity64 > 1ULL << 28) { + printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will" + " be used for accessing sectors > %u\n", + drive->name, 1 << 28); + } else + drive->addressing = 0; + } + /* * if possible, give fdisk access to more of the drive, * by correcting bios_cyls: @@ -1518,7 +1242,7 @@ static void idedisk_setup (ide_drive_t *drive) printk(", CHS=%d/%d/%d", drive->bios_cyl, drive->bios_head, drive->bios_sect); if (drive->using_dma) - (void) HWIF(drive)->ide_dma_verbose(drive); + ide_dma_verbose(drive); printk("\n"); drive->mult_count = 0; @@ -1543,6 +1267,29 @@ static void idedisk_setup (ide_drive_t *drive) drive->wcache = 1; write_cache(drive, 1); + + /* + * We must avoid issuing commands a drive does not understand + * or we may crash it. We check flush cache is supported. We also + * check we have the LBA48 flush cache if the drive capacity is + * too large. By this time we have trimmed the drive capacity if + * LBA48 is not available so we don't need to recheck that. + */ + barrier = 0; + if (ide_id_has_flush_cache(id)) + barrier = 1; + if (drive->addressing == 1) { + /* Can't issue the correct flush ? */ + if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id)) + barrier = 0; + } + + printk(KERN_DEBUG "%s: cache flushes %ssupported\n", + drive->name, barrier ? "" : "not "); + if (barrier) { + blk_queue_ordered(drive->queue, 1); + blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush); + } } static void ide_cacheflush_p(ide_drive_t *drive) @@ -1723,11 +1470,9 @@ static int idedisk_attach(ide_drive_t *drive) if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - ide_cacheflush_p(drive); - ide_unregister_subdriver(drive); - DRIVER(drive)->busy--; - goto failed; - } + drive->attach = 0; + } else + drive->attach = 1; DRIVER(drive)->busy--; g->minors = 1 << PARTN_BITS; strcpy(g->devfs_name, drive->devfs_name); @@ -1735,7 +1480,6 @@ static int idedisk_attach(ide_drive_t *drive) g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0; set_capacity(g, current_capacity(drive)); g->fops = &idedisk_ops; - drive->attach = 1; add_disk(g); return 0; failed: diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 6ed4de8a5..aeaed74f9 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include @@ -128,14 +129,11 @@ static const struct drive_list_entry drive_blacklist [] = { { "CD-532E-A" , "ALL" }, { "E-IDE CD-ROM CR-840", "ALL" }, { "CD-ROM Drive/F5A", "ALL" }, - { "RICOH CD-R/RW MP7083A", "ALL" }, { "WPI CDD-820", "ALL" }, { "SAMSUNG CD-ROM SC-148C", "ALL" }, - { "SAMSUNG CD-ROM SC-148F", "ALL" }, { "SAMSUNG CD-ROM SC", "ALL" }, { "SanDisk SDP3B-64" , "ALL" }, { "SAMSUNG CD-ROM SN-124", "ALL" }, - { "PLEXTOR CD-R PX-W8432T", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, { NULL , NULL } @@ -206,75 +204,22 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); struct scatterlist *sg = hwif->sg_table; - int nents; - if (hwif->sg_dma_active) + if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256) BUG(); - nents = blk_rq_map_sg(drive->queue, rq, hwif->sg_table); - + ide_map_sg(drive, rq); + if (rq_data_dir(rq) == READ) hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; else hwif->sg_dma_direction = PCI_DMA_TODEVICE; - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); + return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_build_sglist); -/** - * ide_raw_build_sglist - map IDE scatter gather for DMA - * @drive: the drive to build the DMA table for - * @rq: the request holding the sg list - * - * Perform the PCI mapping magic necessary to access the source or - * target buffers of a taskfile request via PCI DMA. The lower layers - * of the kernel provide the necessary cache management so that we can - * operate in a portable fashion - */ - -int ide_raw_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = HWIF(drive); - struct scatterlist *sg = hwif->sg_table; - int nents = 0; - ide_task_t *args = rq->special; - u8 *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - hwif->sg_dma_direction = PCI_DMA_TODEVICE; - else - hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - -#if 1 - if (sector_count > 256) - BUG(); - - if (sector_count > 128) { -#else - while (sector_count > 128) { -#endif - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; - - return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); -} - -EXPORT_SYMBOL_GPL(ide_raw_build_sglist); - /** * ide_build_dmatable - build IDE DMA table * @@ -296,10 +241,7 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq) int i; struct scatterlist *sg; - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) - hwif->sg_nents = i = ide_raw_build_sglist(drive, rq); - else - hwif->sg_nents = i = ide_build_sglist(drive, rq); + hwif->sg_nents = i = ide_build_sglist(drive, rq); if (!i) return 0; @@ -366,7 +308,6 @@ use_pio_instead: hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); - hwif->sg_dma_active = 0; return 0; /* revert to PIO for this request */ } @@ -390,7 +331,6 @@ void ide_destroy_dmatable (ide_drive_t *drive) int nents = HWIF(drive)->sg_nents; pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction); - HWIF(drive)->sg_dma_active = 0; } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); @@ -412,10 +352,6 @@ static int config_drive_for_dma (ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); if ((id->capability & 1) && hwif->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - return __ide_dma_off(drive); - /* * Enable DMA on any drive that has * UltraDMA (mode 0/1/2/3/4/5/6) enabled @@ -569,6 +505,10 @@ EXPORT_SYMBOL(__ide_dma_host_on); int __ide_dma_on (ide_drive_t *drive) { + /* consult the list of known "bad" drives */ + if (__ide_dma_bad_drive(drive)) + return 1; + drive->using_dma = 1; ide_toggle_bounce(drive, 1); @@ -595,10 +535,8 @@ int __ide_dma_check (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_check); /** - * ide_start_dma - begin a DMA phase - * @hwif: interface + * ide_dma_setup - begin a DMA phase * @drive: target device - * @reading: set if reading, clear if writing * * Build an IDE DMA PRD (IDE speak for scatter gather table) * and then set up the DMA transfer registers for a device @@ -608,15 +546,24 @@ EXPORT_SYMBOL(__ide_dma_check); * Returns 0 on success. If a PIO fallback is required then 1 * is returned. */ - -int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) + +int ide_dma_setup(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; + unsigned int reading; u8 dma_stat; + if (rq_data_dir(rq)) + reading = 0; + else + reading = 1 << 3; + /* fall back to pio! */ - if (!ide_build_dmatable(drive, rq)) + if (!ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); return 1; + } /* PRD table */ hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable); @@ -633,73 +580,15 @@ int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) return 0; } -EXPORT_SYMBOL(ide_start_dma); +EXPORT_SYMBOL_GPL(ide_dma_setup); -int __ide_dma_read (ide_drive_t *drive /*, struct request *rq */) +static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; - unsigned int reading = 1 << 3; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - /* try pio */ - if (ide_start_dma(hwif, drive, reading)) - return 1; - - if (drive->media != ide_disk) - return 0; - - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; - - if (drive->vdma) - command = (lba48) ? WIN_READ_EXT: WIN_READ; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - /* issue cmd to drive */ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - return hwif->ide_dma_begin(drive); } -EXPORT_SYMBOL(__ide_dma_read); - -int __ide_dma_write (ide_drive_t *drive /*, struct request *rq */) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; - unsigned int reading = 0; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - /* try PIO instead of DMA */ - if (ide_start_dma(hwif, drive, reading)) - return 1; - - if (drive->media != ide_disk) - return 0; - - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (drive->vdma) - command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - - return hwif->ide_dma_begin(drive); -} - -EXPORT_SYMBOL(__ide_dma_write); - -int __ide_dma_begin (ide_drive_t *drive) +void ide_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_cmd = hwif->INB(hwif->dma_command); @@ -713,10 +602,9 @@ int __ide_dma_begin (ide_drive_t *drive) hwif->OUTB(dma_cmd|1, hwif->dma_command); hwif->dma = 1; wmb(); - return 0; } -EXPORT_SYMBOL(__ide_dma_begin); +EXPORT_SYMBOL_GPL(ide_dma_start); /* returns 1 on error, 0 otherwise */ int __ide_dma_end (ide_drive_t *drive) @@ -790,17 +678,46 @@ int __ide_dma_good_drive (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_good_drive); -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI -int __ide_dma_verbose (ide_drive_t *drive) +int ide_use_dma(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = drive->hwif; + + /* consult the list of known "bad" drives */ + if (__ide_dma_bad_drive(drive)) + return 0; + + /* capable of UltraDMA modes */ + if (id->field_valid & 4) { + if (hwif->ultra_mask & id->dma_ultra) + return 1; + } + + /* capable of regular DMA modes */ + if (id->field_valid & 2) { + if (hwif->mwdma_mask & id->dma_mword) + return 1; + if (hwif->swdma_mask & id->dma_1word) + return 1; + } + + /* consult the list of known "good" drives */ + if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150) + return 1; + + return 0; +} + +EXPORT_SYMBOL_GPL(ide_use_dma); + +void ide_dma_verbose(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); if (id->field_valid & 4) { - if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) { - printk(", BUG DMA OFF"); - return hwif->ide_dma_off_quietly(drive); - } + if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) + goto bug_dma_off; if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) { if (((id->dma_ultra >> 11) & 0x1F) && eighty_ninty_three(drive)) { @@ -830,19 +747,22 @@ int __ide_dma_verbose (ide_drive_t *drive) printk(", (U)DMA"); /* Can be BIOS-enabled! */ } } else if (id->field_valid & 2) { - if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) { - printk(", BUG DMA OFF"); - return hwif->ide_dma_off_quietly(drive); - } + if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) + goto bug_dma_off; printk(", DMA"); } else if (id->field_valid & 1) { printk(", BUG"); } - return 1; + return; +bug_dma_off: + printk(", BUG DMA OFF"); + hwif->ide_dma_off_quietly(drive); + return; } -EXPORT_SYMBOL(__ide_dma_verbose); +EXPORT_SYMBOL(ide_dma_verbose); +#ifdef CONFIG_BLK_DEV_IDEDMA_PCI int __ide_dma_lostirq (ide_drive_t *drive) { printk("%s: DMA interrupt recovery\n", drive->name); @@ -874,10 +794,6 @@ int ide_release_dma_engine (ide_hwif_t *hwif) hwif->dmatable_dma); hwif->dmatable_cpu = NULL; } - if (hwif->sg_table) { - kfree(hwif->sg_table); - hwif->sg_table = NULL; - } return 1; } @@ -910,15 +826,12 @@ int ide_allocate_dma_engine (ide_hwif_t *hwif) hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES, &hwif->dmatable_dma); - hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, - GFP_KERNEL); - if ((hwif->dmatable_cpu) && (hwif->sg_table)) + if (hwif->dmatable_cpu) return 0; - printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n", + printk(KERN_ERR "%s: -- Error, unable to allocate%s DMA table(s).\n", (hwif->dmatable_cpu == NULL) ? " CPU" : "", - (hwif->sg_table == NULL) ? " SG DMA" : " DMA", hwif->cds->name); ide_release_dma_engine(hwif); @@ -1014,18 +927,16 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->ide_dma_host_on = &__ide_dma_host_on; if (!hwif->ide_dma_check) hwif->ide_dma_check = &__ide_dma_check; - if (!hwif->ide_dma_read) - hwif->ide_dma_read = &__ide_dma_read; - if (!hwif->ide_dma_write) - hwif->ide_dma_write = &__ide_dma_write; - if (!hwif->ide_dma_begin) - hwif->ide_dma_begin = &__ide_dma_begin; + if (!hwif->dma_setup) + hwif->dma_setup = &ide_dma_setup; + if (!hwif->dma_exec_cmd) + hwif->dma_exec_cmd = &ide_dma_exec_cmd; + if (!hwif->dma_start) + hwif->dma_start = &ide_dma_start; if (!hwif->ide_dma_end) hwif->ide_dma_end = &__ide_dma_end; if (!hwif->ide_dma_test_irq) hwif->ide_dma_test_irq = &__ide_dma_test_irq; - if (!hwif->ide_dma_verbose) - hwif->ide_dma_verbose = &__ide_dma_verbose; if (!hwif->ide_dma_timeout) hwif->ide_dma_timeout = &__ide_dma_timeout; if (!hwif->ide_dma_lostirq) diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 7383f44a2..39819daed 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -97,13 +97,13 @@ #include #include #include +#include #include #include #include #include #include -#include /* * The following are used to debug the driver. @@ -989,12 +989,27 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive) return ide_started; } +/** + * idefloppy_should_report_error() + * + * Supresses error messages resulting from Medium not present + */ +static inline int idefloppy_should_report_error(idefloppy_floppy_t *floppy) +{ + if (floppy->sense_key == 0x02 && + floppy->asc == 0x3a && + floppy->ascq == 0x00) + return 0; + return 1; +} + /* * Issue a packet command */ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) { idefloppy_floppy_t *floppy = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; atapi_feature_t feature; atapi_bcount_t bcount; ide_handler_t *pkt_xfer_routine; @@ -1021,12 +1036,13 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p */ if (!test_bit(PC_ABORT, &pc->flags)) { if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) { - printk(KERN_ERR "ide-floppy: %s: I/O error, " - "pc = %2x, key = %2x, " - "asc = %2x, ascq = %2x\n", - drive->name, pc->c[0], - floppy->sense_key, - floppy->asc, floppy->ascq); + if (idefloppy_should_report_error(floppy)) + printk(KERN_ERR "ide-floppy: %s: I/O error, " + "pc = %2x, key = %2x, " + "asc = %2x, ascq = %2x\n", + drive->name, pc->c[0], + floppy->sense_key, + floppy->asc, floppy->ascq); } /* Giving up */ pc->error = IDEFLOPPY_ERROR_GENERAL; @@ -1049,13 +1065,8 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p } feature.all = 0; - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit(PC_WRITING, &pc->flags)) { - feature.b.dma = !HWIF(drive)->ide_dma_write(drive); - } else { - feature.b.dma = !HWIF(drive)->ide_dma_read(drive); - } - } + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + feature.b.dma = !hwif->dma_setup(drive); if (IDE_CONTROL_REG) HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); @@ -1067,7 +1078,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p if (feature.b.dma) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); } /* Can we transfer the packet when we get the interrupt or wait? */ @@ -1242,11 +1253,13 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request rq->nr_sectors, rq->current_nr_sectors); if (rq->errors >= ERROR_MAX) { - if (floppy->failed_pc != NULL) - printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x," - " key = %2x, asc = %2x, ascq = %2x\n", - drive->name, floppy->failed_pc->c[0], - floppy->sense_key, floppy->asc, floppy->ascq); + if (floppy->failed_pc != NULL) { + if (idefloppy_should_report_error(floppy)) + printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x," + " key = %2x, asc = %2x, ascq = %2x\n", + drive->name, floppy->failed_pc->c[0], + floppy->sense_key, floppy->asc, floppy->ascq); + } else printk(KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ff5b16a87..5eff90ebe 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -54,38 +55,77 @@ #include #include -/** - * ide_end_request - complete an IDE I/O - * @drive: IDE device for the I/O - * @uptodate: - * @nr_sectors: number of sectors completed - * - * This is our end_request wrapper function. We complete the I/O - * update random number input and dequeue the request, which if - * it was tagged may be out of order. +static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq) +{ + char *buf = rq->cmd; + + /* + * reuse cdb space for ata command + */ + memset(buf, 0, sizeof(rq->cmd)); + + rq->flags |= REQ_DRIVE_TASK | REQ_STARTED; + rq->buffer = buf; + rq->buffer[0] = WIN_FLUSH_CACHE; + + if (ide_id_has_flush_cache_ext(drive->id) && + (drive->capacity64 >= (1UL << 28))) + rq->buffer[0] = WIN_FLUSH_CACHE_EXT; +} + +/* + * preempt pending requests, and store this cache flush for immediate + * execution */ - -int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +static struct request *ide_queue_flush_cmd(ide_drive_t *drive, + struct request *rq, int post) { - struct request *rq; - unsigned long flags; - int ret = 1; + struct request *flush_rq = &HWGROUP(drive)->wrq; - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; + /* + * write cache disabled, clear the barrier bit and treat it like + * an ordinary write + */ + if (!drive->wcache) { + rq->flags |= REQ_BAR_PREFLUSH; + return rq; + } - BUG_ON(!(rq->flags & REQ_STARTED)); + ide_init_drive_cmd(flush_rq); + ide_fill_flush_cmd(drive, flush_rq); - if (!nr_sectors) - nr_sectors = rq->hard_cur_sectors; + flush_rq->special = rq; + flush_rq->nr_sectors = rq->nr_sectors; + + if (!post) { + drive->doing_barrier = 1; + flush_rq->flags |= REQ_BAR_PREFLUSH; + blkdev_dequeue_request(rq); + } else + flush_rq->flags |= REQ_BAR_POSTFLUSH; + + __elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0); + HWGROUP(drive)->rq = NULL; + return flush_rq; +} + +static int __ide_end_request(ide_drive_t *drive, struct request *rq, + int uptodate, int nr_sectors) +{ + int ret = 1; + + BUG_ON(!(rq->flags & REQ_STARTED)); /* * if failfast is set on a request, override number of sectors and * complete the whole request right now */ - if (blk_noretry_request(rq) && !uptodate) + if (blk_noretry_request(rq) && end_io_error(uptodate)) nr_sectors = rq->hard_nr_sectors; + if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) + rq->errors = -EIO; + /* * decide whether to reenable DMA -- 3 is a random magic for now, * if we DMA timeout more than 3 times, just stay in PIO @@ -97,15 +137,56 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) if (!end_that_request_first(rq, uptodate, nr_sectors)) { add_disk_randomness(rq->rq_disk); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(drive->queue, rq); + blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; end_that_request_last(rq); ret = 0; } - spin_unlock_irqrestore(&ide_lock, flags); return ret; } +/** + * ide_end_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * This is our end_request wrapper function. We complete the I/O + * update random number input and dequeue the request, which if + * it was tagged may be out of order. + */ + +int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + + if (!nr_sectors) + nr_sectors = rq->hard_cur_sectors; + + if (!blk_barrier_rq(rq) || !drive->wcache) + ret = __ide_end_request(drive, rq, uptodate, nr_sectors); + else { + struct request *flush_rq = &HWGROUP(drive)->wrq; + + flush_rq->nr_sectors -= nr_sectors; + if (!flush_rq->nr_sectors) { + ide_queue_flush_cmd(drive, rq, 1); + ret = 0; + } + } + + spin_unlock_irqrestore(&ide_lock, flags); + return ret; +} EXPORT_SYMBOL(ide_end_request); /** @@ -137,6 +218,113 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) spin_unlock_irqrestore(&ide_lock, flags); } +/* + * FIXME: probably move this somewhere else, name is bad too :) + */ +u64 ide_get_error_location(ide_drive_t *drive, char *args) +{ + u32 high, low; + u8 hcyl, lcyl, sect; + u64 sector; + + high = 0; + hcyl = args[5]; + lcyl = args[4]; + sect = args[3]; + + if (ide_id_has_flush_cache_ext(drive->id)) { + low = (hcyl << 16) | (lcyl << 8) | sect; + HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); + high = ide_read_24(drive); + } else { + u8 cur = HWIF(drive)->INB(IDE_SELECT_REG); + if (cur & 0x40) + low = (hcyl << 16) | (lcyl << 8) | sect; + else { + low = hcyl * drive->head * drive->sect; + low += lcyl * drive->sect; + low += sect - 1; + } + } + + sector = ((u64) high << 24) | low; + return sector; +} +EXPORT_SYMBOL(ide_get_error_location); + +static void ide_complete_barrier(ide_drive_t *drive, struct request *rq, + int error) +{ + struct request *real_rq = rq->special; + int good_sectors, bad_sectors; + sector_t sector; + + if (!error) { + if (blk_barrier_postflush(rq)) { + /* + * this completes the barrier write + */ + __ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors); + drive->doing_barrier = 0; + } else { + /* + * just indicate that we did the pre flush + */ + real_rq->flags |= REQ_BAR_PREFLUSH; + elv_requeue_request(drive->queue, real_rq); + } + /* + * all is fine, return + */ + return; + } + + /* + * we need to end real_rq, but it's not on the queue currently. + * put it back on the queue, so we don't have to special case + * anything else for completing it + */ + if (!blk_barrier_postflush(rq)) + elv_requeue_request(drive->queue, real_rq); + + /* + * drive aborted flush command, assume FLUSH_CACHE_* doesn't + * work and disable barrier support + */ + if (error & ABRT_ERR) { + printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name); + __ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors); + blk_queue_ordered(drive->queue, 0); + blk_queue_issue_flush_fn(drive->queue, NULL); + } else { + /* + * find out what part of the request failed + */ + good_sectors = 0; + if (blk_barrier_postflush(rq)) { + sector = ide_get_error_location(drive, rq->buffer); + + if ((sector >= real_rq->hard_sector) && + (sector < real_rq->hard_sector + real_rq->hard_nr_sectors)) + good_sectors = sector - real_rq->hard_sector; + } else + sector = real_rq->hard_sector; + + bad_sectors = real_rq->hard_nr_sectors - good_sectors; + if (good_sectors) + __ide_end_request(drive, real_rq, 1, good_sectors); + if (bad_sectors) + __ide_end_request(drive, real_rq, 0, bad_sectors); + + printk(KERN_ERR "%s: failed barrier write: " + "sector=%Lx(good=%d/bad=%d)\n", + drive->name, (unsigned long long)sector, + good_sectors, bad_sectors); + } + + drive->doing_barrier = 0; +} + /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -197,6 +385,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF; } args->tfRegister[IDE_ERROR_OFFSET] = err; + /* be sure we're looking at the low order bits */ + hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG); args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); @@ -226,6 +416,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) spin_lock_irqsave(&ide_lock, flags); blkdev_dequeue_request(rq); + + if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq)) + ide_complete_barrier(drive, rq, err); + HWGROUP(drive)->rq = NULL; end_that_request_last(rq); spin_unlock_irqrestore(&ide_lock, flags); @@ -349,8 +543,6 @@ media_out: return ide_stopped; } -EXPORT_SYMBOL(ide_error); - /** * ide_abort - abort pending IDE operatins * @drive: drive the error occurred on @@ -391,8 +583,6 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) return ide_stopped; } -EXPORT_SYMBOL(ide_abort); - /** * ide_cmd - issue a simple drive command * @drive: drive the command is for @@ -404,7 +594,8 @@ EXPORT_SYMBOL(ide_abort); * The drive must be selected beforehand. */ -void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) +static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, + ide_handler_t *handler) { ide_hwif_t *hwif = HWIF(drive); if (IDE_CONTROL_REG) @@ -414,8 +605,6 @@ void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); } -EXPORT_SYMBOL(ide_cmd); - /** * drive_cmd_intr - drive command completion interrupt * @drive: drive the completion interrupt occurred on @@ -426,7 +615,7 @@ EXPORT_SYMBOL(ide_cmd); * the request */ -ide_startstop_t drive_cmd_intr (ide_drive_t *drive) +static ide_startstop_t drive_cmd_intr (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; ide_hwif_t *hwif = HWIF(drive); @@ -451,8 +640,6 @@ ide_startstop_t drive_cmd_intr (ide_drive_t *drive) return ide_stopped; } -EXPORT_SYMBOL(drive_cmd_intr); - /** * do_special - issue some special commands * @drive: drive the command is for @@ -462,7 +649,7 @@ EXPORT_SYMBOL(drive_cmd_intr); * back. */ -ide_startstop_t do_special (ide_drive_t *drive) +static ide_startstop_t do_special (ide_drive_t *drive) { special_t *s = &drive->special; @@ -479,7 +666,33 @@ ide_startstop_t do_special (ide_drive_t *drive) return DRIVER(drive)->special(drive); } -EXPORT_SYMBOL(do_special); +void ide_map_sg(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg = hwif->sg_table; + + if (hwif->sg_mapped) /* needed by ide-scsi */ + return; + + if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) { + hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); + } else { + sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); + hwif->sg_nents = 1; + } +} + +EXPORT_SYMBOL_GPL(ide_map_sg); + +void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = drive->hwif; + + hwif->nsect = hwif->nleft = rq->nr_sectors; + hwif->cursg = hwif->cursg_ofs = 0; +} + +EXPORT_SYMBOL_GPL(ide_init_sg_cmd); /** * execute_drive_command - issue special drive command @@ -493,7 +706,8 @@ EXPORT_SYMBOL(do_special); * all commands to finish. Don't do this as that is due to change */ -ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) +static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, + struct request *rq) { ide_hwif_t *hwif = HWIF(drive); if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -501,7 +715,20 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) if (!args) goto done; - + + hwif->data_phase = args->data_phase; + + switch (hwif->data_phase) { + case TASKFILE_MULTI_OUT: + case TASKFILE_OUT: + case TASKFILE_MULTI_IN: + case TASKFILE_IN: + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + default: + break; + } + if (args->tf_out_flags.all != 0) return flagged_taskfile(drive, args); return do_rw_taskfile(drive, args); @@ -570,8 +797,6 @@ done: return ide_stopped; } -EXPORT_SYMBOL(execute_drive_cmd); - /** * start_request - start of I/O and command issuing for IDE * @@ -583,7 +808,7 @@ EXPORT_SYMBOL(execute_drive_cmd); * FIXME: this function needs a rename */ -ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) +static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; sector_t block; @@ -674,8 +899,6 @@ kill_rq: return ide_stopped; } -EXPORT_SYMBOL(start_request); - /** * ide_stall_queue - pause an IDE device * @drive: drive to stall @@ -712,6 +935,22 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) repeat: best = NULL; drive = hwgroup->drive; + + /* + * drive is doing pre-flush, ordered write, post-flush sequence. even + * though that is 3 requests, it must be seen as a single transaction. + * we must not preempt this drive until that is complete + */ + if (drive->doing_barrier) { + /* + * small race where queue could get replugged during + * the 3-request flush cycle, just yank the plug since + * we want it to finish asap + */ + blk_remove_plug(drive->queue); + return drive; + } + do { if ((!drive->sleep || time_after_eq(jiffies, drive->sleep)) && !elv_queue_empty(drive->queue)) { @@ -782,10 +1021,7 @@ repeat: * the driver. This makes the driver much more friendlier to shared IRQs * than previous designs, while remaining 100% (?) SMP safe and capable. */ -/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back - * into life on wakeup from machine sleep. - */ -void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) { ide_drive_t *drive; ide_hwif_t *hwif; @@ -867,6 +1103,13 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) break; } + /* + * if rq is a barrier write, issue pre cache flush if not + * already done + */ + if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq)) + rq = ide_queue_flush_cmd(drive, rq, 0); + /* * Sanity: don't accept a request that isn't a PM request * if we are currently power managed. This is very important as @@ -910,14 +1153,14 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) } } -EXPORT_SYMBOL(ide_do_request); - /* * Passes the stuff to ide_do_request */ void do_ide_request(request_queue_t *q) { - ide_do_request(q->queuedata, IDE_NO_IRQ); + ide_drive_t *drive = q->queuedata; + + ide_do_request(HWGROUP(drive), IDE_NO_IRQ); } /* @@ -962,12 +1205,15 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) HWGROUP(drive)->rq = NULL; rq->errors = 0; + + if (!rq->bio) + goto out; + rq->sector = rq->bio->bi_sector; rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; rq->hard_cur_sectors = rq->current_nr_sectors; - if (rq->bio) - rq->buffer = NULL; - + rq->buffer = NULL; +out: return ret; } @@ -1071,8 +1317,6 @@ void ide_timer_expiry (unsigned long data) spin_unlock_irqrestore(&ide_lock, flags); } -EXPORT_SYMBOL(ide_timer_expiry); - /** * unexpected_intr - handle an unexpected IDE interrupt * @irq: interrupt line @@ -1270,8 +1514,6 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -EXPORT_SYMBOL(ide_intr); - /** * ide_init_drive_cmd - initialize a drive command request * @rq: request object @@ -1286,6 +1528,7 @@ void ide_init_drive_cmd (struct request *rq) { memset(rq, 0, sizeof(*rq)); rq->flags = REQ_DRIVE_CMD; + rq->ref_count = 1; } EXPORT_SYMBOL(ide_init_drive_cmd); @@ -1329,18 +1572,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio int where = ELEVATOR_INSERT_BACK, err; int must_wait = (action == ide_wait || action == ide_head_wait); -#ifdef CONFIG_BLK_DEV_PDC4030 - /* - * FIXME: there should be a drive or hwif->special - * handler that points here by default, not hacks - * in the ide-io.c code - * - * FIXME2: That code breaks power management if used with - * this chipset, that really doesn't belong here ! - */ - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif rq->errors = 0; rq->rq_status = RQ_ACTIVE; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b7c47d235..68adac6a4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -23,12 +23,12 @@ #include #include #include +#include #include #include #include #include -#include /* * Conventional PIO operations for ATA devices @@ -112,57 +112,57 @@ EXPORT_SYMBOL(default_hwif_iops); static u8 ide_mm_inb (unsigned long port) { - return (u8) readb(port); + return (u8) readb((void __iomem *) port); } static u16 ide_mm_inw (unsigned long port) { - return (u16) readw(port); + return (u16) readw((void __iomem *) port); } static void ide_mm_insw (unsigned long port, void *addr, u32 count) { - __ide_mm_insw(port, addr, count); + __ide_mm_insw((void __iomem *) port, addr, count); } static u32 ide_mm_inl (unsigned long port) { - return (u32) readl(port); + return (u32) readl((void __iomem *) port); } static void ide_mm_insl (unsigned long port, void *addr, u32 count) { - __ide_mm_insl(port, addr, count); + __ide_mm_insl((void __iomem *) port, addr, count); } static void ide_mm_outb (u8 value, unsigned long port) { - writeb(value, port); + writeb(value, (void __iomem *) port); } static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port) { - writeb(value, port); + writeb(value, (void __iomem *) port); } static void ide_mm_outw (u16 value, unsigned long port) { - writew(value, port); + writew(value, (void __iomem *) port); } static void ide_mm_outsw (unsigned long port, void *addr, u32 count) { - __ide_mm_outsw(port, addr, count); + __ide_mm_outsw((void __iomem *) port, addr, count); } static void ide_mm_outl (u32 value, unsigned long port) { - writel(value, port); + writel(value, (void __iomem *) port); } static void ide_mm_outsl (unsigned long port, void *addr, u32 count) { - __ide_mm_outsl(port, addr, count); + __ide_mm_outsl((void __iomem *) port, addr, count); } void default_hwif_mmiops (ide_hwif_t *hwif) @@ -221,24 +221,18 @@ void SELECT_INTERRUPT (ide_drive_t *drive) HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG); } -EXPORT_SYMBOL(SELECT_INTERRUPT); - void SELECT_MASK (ide_drive_t *drive, int mask) { if (HWIF(drive)->maskproc) HWIF(drive)->maskproc(drive, mask); } -EXPORT_SYMBOL(SELECT_MASK); - void QUIRK_LIST (ide_drive_t *drive) { if (HWIF(drive)->quirkproc) drive->quirk_list = HWIF(drive)->quirkproc(drive); } -EXPORT_SYMBOL(QUIRK_LIST); - /* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this @@ -253,8 +247,6 @@ void ata_vlb_sync (ide_drive_t *drive, unsigned long port) (void) HWIF(drive)->INB(port); } -EXPORT_SYMBOL(ata_vlb_sync); - /* * This is used for most PIO data transfers *from* the IDE interface */ @@ -277,8 +269,6 @@ void ata_input_data (ide_drive_t *drive, void *buffer, u32 wcount) } } -EXPORT_SYMBOL(ata_input_data); - /* * This is used for most PIO data transfers *to* the IDE interface */ @@ -301,8 +291,6 @@ void ata_output_data (ide_drive_t *drive, void *buffer, u32 wcount) } } -EXPORT_SYMBOL(ata_output_data); - /* * The following routines are mainly used by the ATAPI drivers. * @@ -685,8 +673,6 @@ int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) return 0; } -EXPORT_SYMBOL(ide_ata66_check); - /* * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. * 1 : Safe to update drive->id DMA registers. @@ -705,9 +691,8 @@ int set_transfer (ide_drive_t *drive, ide_task_t *args) return 0; } -EXPORT_SYMBOL(set_transfer); - -u8 ide_auto_reduce_xfer (ide_drive_t *drive) +#ifdef CONFIG_BLK_DEV_IDEDMA +static u8 ide_auto_reduce_xfer (ide_drive_t *drive) { if (!drive->crc_count) return drive->current_speed; @@ -731,8 +716,7 @@ u8 ide_auto_reduce_xfer (ide_drive_t *drive) default: return XFER_PIO_4; } } - -EXPORT_SYMBOL(ide_auto_reduce_xfer); +#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Update the @@ -807,8 +791,6 @@ int ide_driveid_update (ide_drive_t *drive) #endif } -EXPORT_SYMBOL(ide_driveid_update); - /* * Similar to ide_wait_stat(), except it never calls ide_error internally. * This is a kludge to handle the new ide_config_drive_speed() function, @@ -948,7 +930,7 @@ EXPORT_SYMBOL(ide_config_drive_speed); * * See also ide_execute_command */ -void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, +static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry) { ide_hwgroup_t *hwgroup = HWGROUP(drive); @@ -964,8 +946,6 @@ void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, add_timer(&hwgroup->timer); } -EXPORT_SYMBOL(__ide_set_handler); - void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry) { @@ -1096,7 +1076,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) drive->failures = 0; } else { drive->failures++; -#if FANCY_STATUS_DUMPS printk("master: "); switch (tmp & 0x7f) { case 1: printk("passed"); @@ -1114,9 +1093,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) if (tmp & 0x80) printk("; slave: failed"); printk("\n"); -#else - printk("failed\n"); -#endif /* FANCY_STATUS_DUMPS */ } } hwgroup->poll_timeout = 0; /* done polling */ diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 073c3fb82..1050de226 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -15,12 +15,12 @@ #include #include #include +#include #include #include #include #include -#include /* * IDE library routines. These are plug in code that most @@ -421,8 +421,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) blk_queue_bounce_limit(drive->queue, addr); } -EXPORT_SYMBOL(ide_toggle_bounce); - /** * ide_set_xfer_rate - set transfer rate * @drive: drive to set @@ -465,7 +463,6 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat) status.all = stat; local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS printk(" { "); if (status.b.bsy) printk("Busy "); @@ -479,19 +476,16 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat) if (status.b.check) printk("Error "); } printk("}"); -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) { error.all = HWIF(drive)->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, error.all); -#if FANCY_STATUS_DUMPS if (error.b.ili) printk("IllegalLengthIndication "); if (error.b.eom) printk("EndOfMedia "); if (error.b.abrt) printk("Aborted Command "); if (error.b.mcr) printk("MediaChangeRequested "); if (error.b.sense_key) printk("LastFailedSense 0x%02x ", error.b.sense_key); -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); } local_irq_restore(flags); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 4ffaf9016..d0ffc54b6 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -180,12 +180,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) if (cmd == WIN_PIDENTIFY) { u8 type = (id->config >> 8) & 0x1f; printk("ATAPI "); -#ifdef CONFIG_BLK_DEV_PDC4030 - if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) { - printk(" -- not supported on 2nd Promise port\n"); - goto err_misc; - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ switch (type) { case ide_floppy: if (!strstr(id->model, "CD-ROM")) { @@ -297,13 +291,9 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* disable dma & overlap */ hwif->OUTB(0, IDE_FEATURE_REG); - if (hwif->identify != NULL) { - if (hwif->identify(drive)) - return 1; - } else { - /* ask drive for ID */ - hwif->OUTB(cmd, IDE_COMMAND_REG); - } + /* ask drive for ID */ + hwif->OUTB(cmd, IDE_COMMAND_REG); + timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { @@ -389,15 +379,6 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) */ printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); -#ifdef CONFIG_BLK_DEV_CMD640 -#ifdef CMD640_DUMP_REGS - if (hwif->chipset == ide_cmd640) { - printk("%s: Hmmm.. probably a driver " - "problem.\n", drive->name); - CMD640_DUMP_REGS; - } -#endif /* CMD640_DUMP_REGS */ -#endif /* CONFIG_BLK_DEV_CMD640 */ } } } @@ -635,12 +616,11 @@ static void hwif_register (ide_hwif_t *hwif) device_register(&hwif->gendev); } -#ifdef CONFIG_PPC static int wait_hwif_ready(ide_hwif_t *hwif) { int rc; - printk(KERN_INFO "Probing IDE interface %s...\n", hwif->name); + printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name); /* Let HW settle down a bit from whatever init state we * come from */ @@ -671,7 +651,43 @@ static int wait_hwif_ready(ide_hwif_t *hwif) return rc; } -#endif + +/** + * ide_undecoded_slave - look for bad CF adapters + * @hwif: interface + * + * Analyse the drives on the interface and attempt to decide if we + * have the same drive viewed twice. This occurs with crap CF adapters + * and PCMCIA sometimes. + */ + +void ide_undecoded_slave(ide_hwif_t *hwif) +{ + ide_drive_t *drive0 = &hwif->drives[0]; + ide_drive_t *drive1 = &hwif->drives[1]; + + if (drive0->present == 0 || drive1->present == 0) + return; + + /* If the models don't match they are not the same product */ + if (strcmp(drive0->id->model, drive1->id->model)) + return; + + /* Serial numbers do not match */ + if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20)) + return; + + /* No serial number, thankfully very rare for CF */ + if (drive0->id->serial_no[0] == 0) + return; + + /* Appears to be an IDE flash adapter with decode bugs */ + printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n"); + + drive1->present = 0; +} + +EXPORT_SYMBOL_GPL(ide_undecoded_slave); /* * This routine only knows how to look for drive units 0 and 1 @@ -687,9 +703,6 @@ static void probe_hwif(ide_hwif_t *hwif) return; if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && -#ifdef CONFIG_BLK_DEV_PDC4030 - (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && -#endif /* CONFIG_BLK_DEV_PDC4030 */ (ide_hwif_request_regions(hwif))) { u16 msgout = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { @@ -717,7 +730,6 @@ static void probe_hwif(ide_hwif_t *hwif) local_irq_set(flags); -#ifdef CONFIG_PPC /* This is needed on some PPCs and a bunch of BIOS-less embedded * platforms. Typical cases are: * @@ -738,8 +750,7 @@ static void probe_hwif(ide_hwif_t *hwif) * BenH. */ if (wait_hwif_ready(hwif)) - printk(KERN_WARNING "%s: Wait for ready failed before probe !\n", hwif->name); -#endif /* CONFIG_PPC */ + printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); /* * Second drive should only exist if first drive was found, @@ -822,9 +833,14 @@ static void probe_hwif(ide_hwif_t *hwif) } static int hwif_init(ide_hwif_t *hwif); -int probe_hwif_init (ide_hwif_t *hwif) + +int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) { probe_hwif(hwif); + + if (fixup) + fixup(hwif); + hwif_init(hwif); if (hwif->present) { @@ -842,6 +858,11 @@ int probe_hwif_init (ide_hwif_t *hwif) return 0; } +int probe_hwif_init(ide_hwif_t *hwif) +{ + return probe_hwif_init_with_fixup(hwif, NULL); +} + EXPORT_SYMBOL(probe_hwif_init); #if MAX_HWIFS > 1 @@ -893,11 +914,15 @@ static int ide_init_queue(ide_drive_t *drive) if (!q) return 1; - q->queuedata = HWGROUP(drive); + q->queuedata = drive; blk_queue_segment_boundary(q, 0xffff); - if (!hwif->rqsize) - hwif->rqsize = hwif->no_lba48 ? 256 : 65536; + if (!hwif->rqsize) { + if (hwif->no_lba48 || hwif->no_lba48_dma) + hwif->rqsize = 256; + else + hwif->rqsize = 65536; + } if (hwif->rqsize < max_sectors) max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); @@ -906,11 +931,11 @@ static int ide_init_queue(ide_drive_t *drive) /* When we have an IOMMU, we may have a problem where pci_map_sg() * creates segments that don't completely match our boundary * requirements and thus need to be broken up again. Because it - * doesn't align properly neither, we may actually have to break up + * doesn't align properly either, we may actually have to break up * to more segments than what was we got in the first place, a max * worst case is twice as many. * This will be fixed once we teach pci_map_sg() about our boundary - * requirements, hopefully soon + * requirements, hopefully soon. *FIXME* */ if (!PCI_DMA_BUS_IS_PHYS) max_sg_entries >>= 1; @@ -1124,7 +1149,7 @@ static int ata_lock(dev_t dev, void *data) extern ide_driver_t idedefault_driver; -struct kobject *ata_probe(dev_t dev, int *part, void *data) +static struct kobject *ata_probe(dev_t dev, int *part, void *data) { ide_hwif_t *hwif = data; int unit = *part >> PARTN_BITS; @@ -1243,6 +1268,16 @@ static int hwif_init(ide_hwif_t *hwif) if (register_blkdev(hwif->major, hwif->name)) return 0; + if (!hwif->sg_max_nents) + hwif->sg_max_nents = PRD_ENTRIES; + + hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, + GFP_KERNEL); + if (!hwif->sg_table) { + printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); + goto out; + } + if (alloc_disks(hwif) < 0) goto out; @@ -1292,9 +1327,6 @@ int ideprobe_init (void) for (index = 0; index < MAX_HWIFS; ++index) probe[index] = !ide_hwifs[index].present; - /* - * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports - */ for (index = 0; index < MAX_HWIFS; ++index) if (probe[index]) probe_hwif(&ide_hwifs[index]); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a3ebd9e12..601011dda 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -8,37 +8,6 @@ /* * This is the /proc/ide/ filesystem implementation. * - * The major reason this exists is to provide sufficient access - * to driver and config data, such that user-mode programs can - * be developed to handle chipset tuning for most PCI interfaces. - * This should provide better utilities, and less kernel bloat. - * - * The entire pci config space for a PCI interface chipset can be - * retrieved by just reading it. e.g. "cat /proc/ide3/config" - * - * To modify registers *safely*, do something like: - * echo "P40:88" >/proc/ide/ide3/config - * That expression writes 0x88 to pci config register 0x40 - * on the chip which controls ide3. Multiple tuples can be issued, - * and the writes will be completed as an atomic set: - * echo "P40:88 P41:35 P42:00 P43:00" >/proc/ide/ide3/config - * - * All numbers must be specified using pairs of ascii hex digits. - * It is important to note that these writes will be performed - * after waiting for the IDE controller (both interfaces) - * to be completely idle, to ensure no corruption of I/O in progress. - * - * Non-PCI registers can also be written, using "R" in place of "P" - * in the above examples. The size of the port transfer is determined - * by the number of pairs of hex digits given for the data. If a two - * digit value is given, the write will be a byte operation; if four - * digits are used, the write will be performed as a 16-bit operation; - * and if eight digits are specified, a 32-bit "dword" write will be - * performed. Odd numbers of digits are not permitted. - * - * If there is an error *anywhere* in the string of registers/data - * then *none* of the writes will be performed. - * * Drive/Driver settings can be retrieved by reading the drive's * "settings" files. e.g. "cat /proc/ide0/hda/settings" * To write a new value "val" into a specific setting "name", use: @@ -51,10 +20,6 @@ * returned data as 256 16-bit words. The "hdparm" utility will * be updated someday soon to use this mechanism. * - * Feel free to develop and distribute fancy GUI configuration - * utilities for your favorite PCI chipsets. I'll be working on - * one for the Promise 20246 someday soon. -ml - * */ #include @@ -74,227 +39,6 @@ #include -static int proc_ide_write_config(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - ide_hwif_t *hwif = (ide_hwif_t *)data; - ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup); - ide_hwgroup_t *mategroup = NULL; - unsigned long timeout; - unsigned long flags; - const char *start = NULL, *msg = NULL; - struct entry { u32 val; u16 reg; u8 size; u8 pci; } *prog, *q, *r; - int want_pci = 0; - char *buf, *s; - int err; - - if (hwif->mate && hwif->mate->hwgroup) - mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup); - - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) - return -EACCES; - - if (count >= PAGE_SIZE) - return -EINVAL; - - s = buf = (char *)__get_free_page(GFP_USER); - if (!buf) - return -ENOMEM; - - err = -ENOMEM; - q = prog = (struct entry *)__get_free_page(GFP_USER); - if (!prog) - goto out; - - err = -EFAULT; - if (copy_from_user(buf, buffer, count)) - goto out1; - - buf[count] = '\0'; - - while (isspace(*s)) - s++; - - while (*s) { - char *p; - int digits; - - start = s; - - if ((char *)(q + 1) > (char *)prog + PAGE_SIZE) { - msg = "too many entries"; - goto parse_error; - } - - switch (*s++) { - case 'R': q->pci = 0; - break; - case 'P': q->pci = 1; - want_pci = 1; - break; - default: msg = "expected 'R' or 'P'"; - goto parse_error; - } - - q->reg = simple_strtoul(s, &p, 16); - digits = p - s; - if (!digits || digits > 4 || (q->pci && q->reg > 0xff)) { - msg = "bad/missing register number"; - goto parse_error; - } - if (*p++ != ':') { - msg = "missing ':'"; - goto parse_error; - } - q->val = simple_strtoul(p, &s, 16); - digits = s - p; - if (digits != 2 && digits != 4 && digits != 8) { - msg = "bad data, 2/4/8 digits required"; - goto parse_error; - } - q->size = digits / 2; - - if (q->pci) { -#ifdef CONFIG_BLK_DEV_IDEPCI - if (q->reg & (q->size - 1)) { - msg = "misaligned access"; - goto parse_error; - } -#else - msg = "not a PCI device"; - goto parse_error; -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - - q++; - - if (*s && !isspace(*s++)) { - msg = "expected whitespace after data"; - goto parse_error; - } - while (isspace(*s)) - s++; - } - - /* - * What follows below is fucking insane, even for IDE people. - * For now I've dealt with the obvious problems on the parsing - * side, but IMNSHO we should simply remove the write access - * to /proc/ide/.../config, killing that FPOS completely. - */ - - err = -EBUSY; - timeout = jiffies + (3 * HZ); - spin_lock_irqsave(&ide_lock, flags); - while (mygroup->busy || - (mategroup && mategroup->busy)) { - spin_unlock_irqrestore(&ide_lock, flags); - if (time_after(jiffies, timeout)) { - printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name); - goto out1; - } - spin_lock_irqsave(&ide_lock, flags); - } - -#ifdef CONFIG_BLK_DEV_IDEPCI - if (want_pci && (!hwif->pci_dev || hwif->pci_dev->vendor)) { - spin_unlock_irqrestore(&ide_lock, flags); - printk("proc_ide: PCI registers not accessible for %s\n", - hwif->name); - err = -EINVAL; - goto out1; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - - for (r = prog; r < q; r++) { - unsigned int reg = r->reg, val = r->val; - if (r->pci) { -#ifdef CONFIG_BLK_DEV_IDEPCI - int rc = 0; - struct pci_dev *dev = hwif->pci_dev; - switch (q->size) { - case 1: msg = "byte"; - rc = pci_write_config_byte(dev, reg, val); - break; - case 2: msg = "word"; - rc = pci_write_config_word(dev, reg, val); - break; - case 4: msg = "dword"; - rc = pci_write_config_dword(dev, reg, val); - break; - } - if (rc) { - spin_unlock_irqrestore(&ide_lock, flags); - printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", - msg, dev->bus->number, dev->devfn, reg, val); - printk("proc_ide_write_config: error %d\n", rc); - err = -EIO; - goto out1; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } else { /* not pci */ - switch (r->size) { - case 1: hwif->OUTB(val, reg); - break; - case 2: hwif->OUTW(val, reg); - break; - case 4: hwif->OUTL(val, reg); - break; - } - } - } - spin_unlock_irqrestore(&ide_lock, flags); - err = count; -out1: - free_page((unsigned long)prog); -out: - free_page((unsigned long)buf); - return err; - -parse_error: - printk("parse error\n"); - printk("proc_ide: error: %s: '%s'\n", msg, start); - err = -EINVAL; - goto out1; -} - -static int proc_ide_read_config - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - char *out = page; - int len; - -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_hwif_t *hwif = (ide_hwif_t *)data; - struct pci_dev *dev = hwif->pci_dev; - if ((hwif->pci_dev && hwif->pci_dev->vendor) && dev && dev->bus) { - int reg = 0; - - out += sprintf(out, "pci bus %02x device %02x vendor %04x " - "device %04x channel %d\n", - dev->bus->number, dev->devfn, - hwif->pci_dev->vendor, hwif->pci_dev->device, - hwif->channel); - do { - u8 val; - int rc = pci_read_config_byte(dev, reg, &val); - if (rc) { - printk("proc_ide_read_config: error %d reading" - " bus %02x dev %02x reg 0x%02x\n", - rc, dev->bus->number, dev->devfn, reg); - out += sprintf(out, "??%c", - (++reg & 0xf) ? ' ' : '\n'); - } else - out += sprintf(out, "%02x%c", - val, (++reg & 0xf) ? ' ' : '\n'); - } while (reg < 0x100); - } else -#endif /* CONFIG_BLK_DEV_IDEPCI */ - out += sprintf(out, "(none)\n"); - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - static int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -314,7 +58,6 @@ static int proc_ide_read_imodel case ide_qd65xx: name = "qd65xx"; break; case ide_umc8672: name = "umc8672"; break; case ide_ht6560b: name = "ht6560b"; break; - case ide_pdc4030: name = "pdc4030"; break; case ide_rz1000: name = "rz1000"; break; case ide_trm290: name = "trm290"; break; case ide_cmd646: name = "cmd646"; break; @@ -360,27 +103,14 @@ static int proc_ide_read_identify int err = 0; len = sprintf(page, "\n"); - - if (drive) - { + + if (drive) { unsigned short *val = (unsigned short *) page; - - /* - * The current code can't handle a driverless - * identify query taskfile. Now the right fix is - * to add a 'default' driver but that is a bit - * more work. - * - * FIXME: this has to be fixed for hotswap devices - */ - - if(DRIVER(drive)) - err = taskfile_lib_get_identify(drive, page); - else /* This relies on the ID changes */ - val = (unsigned short *)drive->id; - - if(!err) - { + + BUG_ON(!drive->driver); + + err = taskfile_lib_get_identify(drive, page); + if (!err) { char *out = ((char *)page) + (SECTOR_WORDS * 4); page = out; do { @@ -394,6 +124,18 @@ static int proc_ide_read_identify PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static void proc_ide_settings_warn(void) +{ + static int warned = 0; + + if (warned) + return; + + printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is " + "obsolete, and will be removed soon!\n"); + warned = 1; +} + static int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -402,6 +144,8 @@ static int proc_ide_read_settings char *out = page; int len, rc, mul_factor, div_factor; + proc_ide_settings_warn(); + down(&ide_setting_sem); out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); @@ -441,6 +185,8 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, if (!capable(CAP_SYS_ADMIN)) return -EACCES; + proc_ide_settings_warn(); + if (count >= PAGE_SIZE) return -EINVAL; @@ -688,7 +434,7 @@ static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) } } -void destroy_proc_ide_drives(ide_hwif_t *hwif) +static void destroy_proc_ide_drives(ide_hwif_t *hwif) { int d; @@ -701,7 +447,6 @@ void destroy_proc_ide_drives(ide_hwif_t *hwif) static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, - { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, { "model", S_IFREG|S_IRUGO, proc_ide_read_imodel, NULL }, { NULL, 0, NULL, NULL } @@ -737,29 +482,30 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info) EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); #endif -void destroy_proc_ide_interfaces(void) +void destroy_proc_ide_interface(ide_hwif_t *hwif) +{ + if (hwif->proc) { + destroy_proc_ide_drives(hwif); + ide_remove_proc_entries(hwif->proc, hwif_entries); + remove_proc_entry(hwif->name, proc_ide_root); + hwif->proc = NULL; + } +} + +static void destroy_proc_ide_interfaces(void) { int h; for (h = 0; h < MAX_HWIFS; h++) { ide_hwif_t *hwif = &ide_hwifs[h]; - int exist = (hwif->proc != NULL); #if 0 if (!hwif->present) continue; #endif - if (exist) { - destroy_proc_ide_drives(hwif); - ide_remove_proc_entries(hwif->proc, hwif_entries); - remove_proc_entry(hwif->name, proc_ide_root); - hwif->proc = NULL; - } else - continue; + destroy_proc_ide_interface(hwif); } } -EXPORT_SYMBOL(destroy_proc_ide_interfaces); - extern struct seq_operations ide_drivers_op; static int ide_drivers_open(struct inode *inode, struct file *file) { diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d19ee543e..82e471ffd 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -442,13 +442,13 @@ #include #include #include +#include #include #include #include #include #include -#include /* * partition @@ -530,7 +530,6 @@ typedef struct os_dat_s { */ #define IDETAPE_DEBUG_INFO 0 #define IDETAPE_DEBUG_LOG 0 -#define IDETAPE_DEBUG_LOG_VERBOSE 0 #define IDETAPE_DEBUG_BUGS 1 /* @@ -1260,70 +1259,6 @@ typedef struct { */ static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES]; -#if IDETAPE_DEBUG_LOG_VERBOSE - -/* - * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI - */ - -char *idetape_sense_key_verbose(u8 idetape_sense_key) -{ - switch (idetape_sense_key) { - default: { - char buf[22]; - sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key); - return(buf); - } - - } -} - -char *idetape_command_key_verbose(u8 idetape_command_key) -{ - switch (idetape_command_key) { - case IDETAPE_TEST_UNIT_READY_CMD: - return("TEST_UNIT_READY_CMD"); - case IDETAPE_REWIND_CMD: - return("REWIND_CMD"); - case IDETAPE_REQUEST_SENSE_CMD: - return("REQUEST_SENSE_CMD"); - case IDETAPE_READ_CMD: - return("READ_CMD"); - case IDETAPE_WRITE_CMD: - return("WRITE_CMD"); - case IDETAPE_WRITE_FILEMARK_CMD: - return("WRITE_FILEMARK_CMD"); - case IDETAPE_SPACE_CMD: - return("SPACE_CMD"); - case IDETAPE_INQUIRY_CMD: - return("INQUIRY_CMD"); - case IDETAPE_ERASE_CMD: - return("ERASE_CMD"); - case IDETAPE_MODE_SENSE_CMD: - return("MODE_SENSE_CMD"); - case IDETAPE_MODE_SELECT_CMD: - return("MODE_SELECT_CMD"); - case IDETAPE_LOAD_UNLOAD_CMD: - return("LOAD_UNLOAD_CMD"); - case IDETAPE_PREVENT_CMD: - return("PREVENT_CMD"); - case IDETAPE_LOCATE_CMD: - return("LOCATE_CMD"); - case IDETAPE_READ_POSITION_CMD: - return("READ_POSITION_CMD"); - case IDETAPE_READ_BUFFER_CMD: - return("READ_BUFFER_CMD"); - case IDETAPE_SET_SPEED_CMD: - return("SET_SPEED_CMD"); - default: { - char buf[20]; - sprintf(buf, "CMD (0x%02x)", idetape_command_key); - return(buf); - } - } -} -#endif /* IDETAPE_DEBUG_LOG_VERBOSE */ - /* * Function declarations * @@ -1507,15 +1442,6 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res "asc = %x, ascq = %x\n", pc->c[0], result->sense_key, result->asc, result->ascq); -#if IDETAPE_DEBUG_LOG_VERBOSE - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: pc = %s, sense key = %x, " - "asc = %x, ascq = %x\n", - idetape_command_key_verbose((byte) pc->c[0]), - result->sense_key, - result->asc, - result->ascq); -#endif /* IDETAPE_DEBUG_LOG_VERBOSE */ #endif /* IDETAPE_DEBUG_LOG */ /* @@ -2141,7 +2067,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) #ifdef CONFIG_BLK_DEV_IDEDMA /* Begin DMA, if necessary */ if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); #endif /* Send the actual packet */ HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); @@ -2209,12 +2135,8 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape "reverting to PIO\n"); (void)__ide_dma_off(drive); } - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit(PC_WRITING, &pc->flags)) - dma_ok = !HWIF(drive)->ide_dma_write(drive); - else - dma_ok = !HWIF(drive)->ide_dma_read(drive); - } + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !hwif->dma_setup(drive); if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index e83c9a9eb..182980eec 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -5,7 +5,7 @@ * Copyright (C) 2000-2002 Andre Hedrick * Copyright (C) 2001-2002 Klaus Smolin * IBM Storage Technology Division - * Copyright (C) 2003 Bartlomiej Zolnierkiewicz + * Copyright (C) 2003-2004 Bartlomiej Zolnierkiewicz * * The big the bad and the ugly. * @@ -44,12 +44,12 @@ #include #include #include +#include #include #include #include #include -#include #define DEBUG_TASKFILE 0 /* unset when fixed */ @@ -63,17 +63,14 @@ static void ata_bswap_data (void *buffer, int wcount) } } - -void taskfile_input_data (ide_drive_t *drive, void *buffer, u32 wcount) +static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount) { HWIF(drive)->ata_input_data(drive, buffer, wcount); if (drive->bswap) ata_bswap_data(buffer, wcount); } -EXPORT_SYMBOL(taskfile_input_data); - -void taskfile_output_data (ide_drive_t *drive, void *buffer, u32 wcount) +static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount) { if (drive->bswap) { ata_bswap_data(buffer, wcount); @@ -84,8 +81,6 @@ void taskfile_output_data (ide_drive_t *drive, void *buffer, u32 wcount) } } -EXPORT_SYMBOL(taskfile_output_data); - int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) { ide_task_t args; @@ -96,36 +91,11 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) else args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; args.command_type = IDE_DRIVE_TASK_IN; + args.data_phase = TASKFILE_IN; args.handler = &task_in_intr; return ide_raw_taskfile(drive, &args, buf); } -EXPORT_SYMBOL(taskfile_lib_get_identify); - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -void debug_taskfile (ide_drive_t *drive, ide_task_t *args) -{ - printk(KERN_INFO "%s: ", drive->name); -// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); - printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); - printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); - printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); - printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); - printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); - printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); - printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); - printk(KERN_INFO "%s: ", drive->name); -// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET]); - printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET]); - printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET]); - printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET]); - printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET]); - printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET]); - printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET]); - printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); -} -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { ide_hwif_t *hwif = HWIF(drive); @@ -133,10 +103,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - void debug_taskfile(drive, task); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ if (IDE_CONTROL_REG) { /* clear nIEN */ @@ -177,15 +143,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA: case WIN_WRITEDMA_EXT: - if (!hwif->ide_dma_write(drive)) - return ide_started; - break; case WIN_READDMA_ONCE: case WIN_READDMA: case WIN_READDMA_EXT: case WIN_IDENTIFY_DMA: - if (!hwif->ide_dma_read(drive)) + if (!hwif->dma_setup(drive)) { + hwif->dma_exec_cmd(drive, taskfile->command); + hwif->dma_start(drive); return ide_started; + } break; default: if (task->handler == NULL) @@ -280,108 +246,125 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive) EXPORT_SYMBOL(task_no_data_intr); -static void task_buffer_sectors(ide_drive_t *drive, struct request *rq, - unsigned nsect, unsigned rw) +static u8 wait_drive_not_busy(ide_drive_t *drive) { - char *buf = rq->buffer + blk_rq_offset(rq); + ide_hwif_t *hwif = HWIF(drive); + int retries = 100; + u8 stat; - rq->sector += nsect; - rq->current_nr_sectors -= nsect; - rq->nr_sectors -= nsect; - __task_sectors(drive, buf, nsect, rw); + /* + * Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec, but we will wait max 1 ms + * (drive_cmd_intr() waits that long). + */ + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(10); + + if (!retries) + printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); + + return stat; } -static inline void task_buffer_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) +static void ide_pio_sector(ide_drive_t *drive, unsigned int write) { - unsigned int msect = drive->mult_count, nsect; + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg = hwif->sg_table; + struct page *page; +#ifdef CONFIG_HIGHMEM + unsigned long flags; +#endif + unsigned int offset; + u8 *buf; - nsect = rq->current_nr_sectors; - if (nsect > msect) - nsect = msect; + page = sg[hwif->cursg].page; + offset = sg[hwif->cursg].offset + hwif->cursg_ofs * SECTOR_SIZE; - task_buffer_sectors(drive, rq, nsect, rw); -} + /* get the current page and offset */ + page = nth_page(page, (offset >> PAGE_SHIFT)); + offset %= PAGE_SIZE; -#ifdef CONFIG_IDE_TASKFILE_IO -static void task_sectors(ide_drive_t *drive, struct request *rq, - unsigned nsect, unsigned rw) -{ - if (rq->cbio) { /* fs request */ - rq->errors = 0; - task_bio_sectors(drive, rq, nsect, rw); - } else /* task request */ - task_buffer_sectors(drive, rq, nsect, rw); -} +#ifdef CONFIG_HIGHMEM + local_irq_save(flags); +#endif + buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; -static inline void task_bio_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) -{ - unsigned int nsect, msect = drive->mult_count; + hwif->nleft--; + hwif->cursg_ofs++; - do { - nsect = rq->current_nr_sectors; - if (nsect > msect) - nsect = msect; + if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) { + hwif->cursg++; + hwif->cursg_ofs = 0; + } - task_bio_sectors(drive, rq, nsect, rw); + /* do the actual data transfer */ + if (write) + taskfile_output_data(drive, buf, SECTOR_WORDS); + else + taskfile_input_data(drive, buf, SECTOR_WORDS); - if (!rq->nr_sectors) - msect = 0; - else - msect -= nsect; - } while (msect); + kunmap_atomic(buf, KM_BIO_SRC_IRQ); +#ifdef CONFIG_HIGHMEM + local_irq_restore(flags); +#endif } -static void task_multi_sectors(ide_drive_t *drive, - struct request *rq, unsigned rw) +static void ide_pio_multi(ide_drive_t *drive, unsigned int write) { - if (rq->cbio) { /* fs request */ - rq->errors = 0; - task_bio_multi_sectors(drive, rq, rw); - } else /* task request */ - task_buffer_multi_sectors(drive, rq, rw); + unsigned int nsect; + + nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); + while (nsect--) + ide_pio_sector(drive, write); } -#else -# define task_sectors(d, rq, nsect, rw) task_buffer_sectors(d, rq, nsect, rw) -# define task_multi_sectors(d, rq, rw) task_buffer_multi_sectors(d, rq, rw) -#endif /* CONFIG_IDE_TASKFILE_IO */ -static u8 wait_drive_not_busy(ide_drive_t *drive) +static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, + unsigned int write) { - ide_hwif_t *hwif = HWIF(drive); - int retries = 100; - u8 stat; - - /* - * Last sector was transfered, wait until drive is ready. - * This can take up to 10 usec, but we will wait max 1 ms - * (drive_cmd_intr() waits that long). - */ - while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) - udelay(10); - - if (!retries) - printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); + if (rq->bio) /* fs request */ + rq->errors = 0; - return stat; + switch (drive->hwif->data_phase) { + case TASKFILE_MULTI_IN: + case TASKFILE_MULTI_OUT: + ide_pio_multi(drive, write); + break; + default: + ide_pio_sector(drive, write); + break; + } } -#ifdef CONFIG_IDE_TASKFILE_IO static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, - const char *s, u8 stat, unsigned cur_bad) + const char *s, u8 stat) { if (rq->bio) { - int sectors = rq->hard_nr_sectors - rq->nr_sectors - cur_bad; + ide_hwif_t *hwif = drive->hwif; + int sectors = hwif->nsect - hwif->nleft; + + switch (hwif->data_phase) { + case TASKFILE_IN: + if (hwif->nleft) + break; + /* fall through */ + case TASKFILE_OUT: + sectors--; + break; + case TASKFILE_MULTI_IN: + if (hwif->nleft) + break; + /* fall through */ + case TASKFILE_MULTI_OUT: + sectors -= drive->mult_count; + default: + break; + } if (sectors > 0) drive->driver->end_request(drive, 1, sectors); } return drive->driver->error(drive, s, stat); } -#else -# define task_error(d, rq, s, stat, cur_bad) drive->driver->error(d, s, stat) -#endif static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { @@ -398,28 +381,30 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) } /* - * Handler for command with PIO data-in phase (Read). + * Handler for command with PIO data-in phase (Read/Read Multiple). */ ide_startstop_t task_in_intr (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG); + u8 stat = hwif->INB(IDE_STATUS_REG); + /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) - return task_error(drive, rq, __FUNCTION__, stat, 0); + return task_error(drive, rq, __FUNCTION__, stat); /* No data yet, so wait for another IRQ. */ ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); return ide_started; } - task_sectors(drive, rq, 1, IDE_PIO_IN); + ide_pio_datablock(drive, rq, 0); /* If it was the last datablock check status and finish transfer. */ - if (!rq->nr_sectors) { + if (!hwif->nleft) { stat = wait_drive_not_busy(drive); if (!OK_STAT(stat, 0, BAD_R_STAT)) - return task_error(drive, rq, __FUNCTION__, stat, 1); + return task_error(drive, rq, __FUNCTION__, stat); task_end_request(drive, rq, stat); return ide_stopped; } @@ -432,77 +417,43 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) EXPORT_SYMBOL(task_in_intr); /* - * Handler for command with PIO data-in phase (Read Multiple). + * Handler for command with PIO data-out phase (Write/Write Multiple). */ -ide_startstop_t task_mulin_intr (ide_drive_t *drive) +static ide_startstop_t task_out_intr (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = HWGROUP(drive)->rq; - u8 stat = HWIF(drive)->INB(IDE_STATUS_REG); + u8 stat = hwif->INB(IDE_STATUS_REG); - if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { - if (stat & (ERR_STAT | DRQ_STAT)) - return task_error(drive, rq, __FUNCTION__, stat, 0); - /* No data yet, so wait for another IRQ. */ - ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); - return ide_started; - } - - task_multi_sectors(drive, rq, IDE_PIO_IN); - - /* If it was the last datablock check status and finish transfer. */ - if (!rq->nr_sectors) { - stat = wait_drive_not_busy(drive); - if (!OK_STAT(stat, 0, BAD_R_STAT)) - return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Still data left to transfer. */ - ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} -EXPORT_SYMBOL(task_mulin_intr); - -/* - * Handler for command with PIO data-out phase (Write). - */ -ide_startstop_t task_out_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - u8 stat; - - stat = HWIF(drive)->INB(IDE_STATUS_REG); if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) - return task_error(drive, rq, __FUNCTION__, stat, 1); + return task_error(drive, rq, __FUNCTION__, stat); /* Deal with unexpected ATA data phase. */ - if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors) - return task_error(drive, rq, __FUNCTION__, stat, 1); + if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft) + return task_error(drive, rq, __FUNCTION__, stat); - if (!rq->nr_sectors) { + if (!hwif->nleft) { task_end_request(drive, rq, stat); return ide_stopped; } /* Still data left to transfer. */ - task_sectors(drive, rq, 1, IDE_PIO_OUT); + ide_pio_datablock(drive, rq, 1); ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); return ide_started; } -EXPORT_SYMBOL(task_out_intr); - ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n", - drive->name, drive->addressing ? "_EXT" : ""); + printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n", + drive->name, + drive->hwif->data_phase ? "MULT" : "", + drive->addressing ? "_EXT" : ""); return startstop; } @@ -510,63 +461,13 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) local_irq_disable(); ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); - task_sectors(drive, rq, 1, IDE_PIO_OUT); + ide_pio_datablock(drive, rq, 1); return ide_started; } EXPORT_SYMBOL(pre_task_out_intr); -/* - * Handler for command with PIO data-out phase (Write Multiple). - */ -ide_startstop_t task_mulout_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - u8 stat; - - stat = HWIF(drive)->INB(IDE_STATUS_REG); - if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) - return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); - - /* Deal with unexpected ATA data phase. */ - if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors) - return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); - - if (!rq->nr_sectors) { - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Still data left to transfer. */ - task_multi_sectors(drive, rq, IDE_PIO_OUT); - ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); - - return ide_started; -} -EXPORT_SYMBOL(task_mulout_intr); - -ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - - if (ide_wait_stat(&startstop, drive, DATA_READY, - drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing MULTWRITE%s\n", - drive->name, drive->addressing ? "_EXT" : ""); - return startstop; - } - - if (!drive->unmask) - local_irq_disable(); - - ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); - task_multi_sectors(drive, rq, IDE_PIO_OUT); - - return ide_started; -} -EXPORT_SYMBOL(pre_task_mulout_intr); - -int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) +static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) { struct request rq; @@ -594,14 +495,15 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_ rq.hard_nr_sectors = rq.nr_sectors; rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors; + + if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) + rq.flags |= REQ_RW; } rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait); } -EXPORT_SYMBOL(ide_diag_taskfile); - int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf) { return ide_diag_taskfile(drive, args, 0, buf); @@ -609,10 +511,6 @@ int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf) EXPORT_SYMBOL(ide_raw_taskfile); -#define MAX_DMA (256*SECTOR_WORDS) - -ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *); - int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { ide_task_request_t *req_task; @@ -688,19 +586,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) case TASKFILE_IN_DMA: err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; - case TASKFILE_IN_OUT: -#if 0 - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - err = ide_diag_taskfile(drive, &args, taskout, outbuf); - args.prehandler = NULL; - args.handler = &task_in_intr; - err = ide_diag_taskfile(drive, &args, taskin, inbuf); - break; -#else - err = -EFAULT; - goto abort; -#endif case TASKFILE_MULTI_OUT: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ @@ -710,10 +595,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) err = -EPERM; goto abort; } - args.prehandler = &pre_task_mulout_intr; - args.handler = &task_mulout_intr; - err = ide_diag_taskfile(drive, &args, taskout, outbuf); - break; + /* fall through */ case TASKFILE_OUT: args.prehandler = &pre_task_out_intr; args.handler = &task_out_intr; @@ -728,9 +610,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) err = -EPERM; goto abort; } - args.handler = &task_mulin_intr; - err = ide_diag_taskfile(drive, &args, taskin, inbuf); - break; + /* fall through */ case TASKFILE_IN: args.handler = &task_in_intr; err = ide_diag_taskfile(drive, &args, taskin, inbuf); @@ -781,8 +661,6 @@ abort: return err; } -EXPORT_SYMBOL(ide_taskfile_ioctl); - int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf) { struct request rq; @@ -800,8 +678,6 @@ int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, return ide_do_drive_cmd(drive, &rq, ide_wait); } -EXPORT_SYMBOL(ide_wait_cmd); - /* * FIXME : this needs to map into at taskfile. */ @@ -859,9 +735,7 @@ abort: return err; } -EXPORT_SYMBOL(ide_cmd_ioctl); - -int ide_wait_cmd_task (ide_drive_t *drive, u8 *buf) +static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf) { struct request rq; @@ -871,8 +745,6 @@ int ide_wait_cmd_task (ide_drive_t *drive, u8 *buf) return ide_do_drive_cmd(drive, &rq, ide_wait); } -EXPORT_SYMBOL(ide_wait_cmd_task); - /* * FIXME : this needs to map into at taskfile. */ @@ -891,8 +763,6 @@ int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) return err; } -EXPORT_SYMBOL(ide_task_ioctl); - /* * NOTICE: This is additions from IBM to provide a discrete interface, * for selective taskregister access operations. Nice JOB Klaus!!! @@ -907,11 +777,6 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) u8 status; #endif - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - void debug_taskfile(drive, task); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - if (task->data_phase == TASKFILE_MULTI_IN || task->data_phase == TASKFILE_MULTI_OUT) { if (!drive->mult_count) { @@ -996,12 +861,11 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: - hwif->ide_dma_write(drive); - break; - case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: - hwif->ide_dma_read(drive); + hwif->dma_setup(drive); + hwif->dma_exec_cmd(drive, taskfile->command); + hwif->dma_start(drive); break; default: @@ -1019,5 +883,3 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) return ide_started; } - -EXPORT_SYMBOL(flagged_taskfile); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index e99d9ec19..467b73482 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -153,12 +153,12 @@ #include #include #include +#include #include #include #include #include -#include /* default maximum number of failures */ @@ -320,20 +320,31 @@ static void __init init_ide_data (void) #endif } -/* - * ide_system_bus_speed() returns what we think is the system VESA/PCI - * bus speed (in MHz). This is used for calculating interface PIO timings. - * The default is 40 for known PCI systems, 50 otherwise. - * The "idebus=xx" parameter can be used to override this value. - * The actual value to be used is computed/displayed the first time through. +/** + * ide_system_bus_speed - guess bus speed + * + * ide_system_bus_speed() returns what we think is the system VESA/PCI + * bus speed (in MHz). This is used for calculating interface PIO timings. + * The default is 40 for known PCI systems, 50 otherwise. + * The "idebus=xx" parameter can be used to override this value. + * The actual value to be used is computed/displayed the first time + * through. Drivers should only use this as a last resort. + * + * Returns a guessed speed in MHz. */ + int ide_system_bus_speed (void) { + static struct pci_device_id pci_default[] = { + { PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) }, + { } + }; + if (!system_bus_speed) { if (idebus_parameter) { /* user supplied value */ system_bus_speed = idebus_parameter; - } else if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) != NULL) { + } else if (pci_dev_present(pci_default)) { /* safe default value for PCI */ system_bus_speed = 33; } else { @@ -347,10 +358,15 @@ int ide_system_bus_speed (void) return system_bus_speed; } -/* - * current_capacity() returns the capacity (in sectors) of a drive - * according to its current geometry/LBA settings. +/** + * current_capacity - drive capacity + * @drive: drive to query + * + * Return the current capacity (in sectors) of a drive according to + * its current geometry/LBA settings. Empty removables are reported + * as size zero. */ + sector_t current_capacity (ide_drive_t *drive) { if (!drive->present) @@ -360,9 +376,17 @@ sector_t current_capacity (ide_drive_t *drive) EXPORT_SYMBOL(current_capacity); -/* - * Error reporting, in human readable form (luxurious, but a memory hog). +/** + * ide_dump_status - translate ATA error + * @drive: drive the error occured on + * @msg: information string + * @stat: status byte + * + * Error reporting, in human readable form (luxurious, but a memory hog). + * Combines the drive name, message and status byte to provide a + * user understandable explanation of the device error. */ + u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) { ide_hwif_t *hwif = HWIF(drive); @@ -371,7 +395,6 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) local_irq_set(flags); printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat); -#if FANCY_STATUS_DUMPS printk(" { "); if (stat & BUSY_STAT) { printk("Busy "); @@ -385,12 +408,10 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) if (stat & ERR_STAT) printk("Error "); } printk("}"); -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x", drive->name, msg, err); -#if FANCY_STATUS_DUMPS if (drive->media == ide_disk) { printk(" { "); if (err & ABRT_ERR) printk("DriveStatusError "); @@ -434,9 +455,34 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector); } } -#endif /* FANCY_STATUS_DUMPS */ printk("\n"); } + { + struct request *rq; + int opcode = 0x100; + + spin_lock(&ide_lock); + rq = NULL; + if (HWGROUP(drive)) + rq = HWGROUP(drive)->rq; + spin_unlock(&ide_lock); + if (!rq) + goto out; + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + char *args = rq->buffer; + if (args) + opcode = args[0]; + } else if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + if (args) { + task_struct_t *tf = (task_struct_t *) args->tfRegister; + opcode = tf->command; + } + } + + printk("ide: failed opcode was %x\n", opcode); + } +out: local_irq_restore(flags); return err; } @@ -448,11 +494,17 @@ static int ide_open (struct inode * inode, struct file * filp) return -ENXIO; } +/* + * drives_lock protects the list of drives, drivers_lock the + * list of drivers. Currently nobody takes both at once. + */ + static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED; static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(drivers); -/* Iterator */ +/* Iterator for the driver list. */ + static void *m_start(struct seq_file *m, loff_t *pos) { struct list_head *p; @@ -463,22 +515,26 @@ static void *m_start(struct seq_file *m, loff_t *pos) return list_entry(p, ide_driver_t, drivers); return NULL; } + static void *m_next(struct seq_file *m, void *v, loff_t *pos) { struct list_head *p = ((ide_driver_t *)v)->drivers.next; (*pos)++; return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers); } + static void m_stop(struct seq_file *m, void *v) { spin_unlock(&drivers_lock); } + static int show_driver(struct seq_file *m, void *v) { ide_driver_t *driver = v; seq_printf(m, "%s version %s\n", driver->name, driver->version); return 0; } + struct seq_operations ide_drivers_op = { .start = m_start, .next = m_next, @@ -515,6 +571,7 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif, * MMIO leaves it to the controller driver, * PIO will migrate this way over time. */ + int ide_hwif_request_regions(ide_hwif_t *hwif) { unsigned long addr; @@ -564,6 +621,7 @@ control_region_busy: * importantly our caller should be doing this so we need to * restructure this as a helper function for drivers. */ + void ide_hwif_release_regions(ide_hwif_t *hwif) { u32 i = 0; @@ -581,7 +639,15 @@ void ide_hwif_release_regions(ide_hwif_t *hwif) release_region(hwif->io_ports[i], 1); } -/* restore hwif to a sane state */ +/** + * ide_hwif_restore - restore hwif to template + * @hwif: hwif to update + * @tmp_hwif: template + * + * Restore hwif to a previous state by copying most settngs + * from the template. + */ + static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) { hwif->hwgroup = tmp_hwif->hwgroup; @@ -607,7 +673,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->cds = tmp_hwif->cds; #endif - hwif->identify = tmp_hwif->identify; hwif->tuneproc = tmp_hwif->tuneproc; hwif->speedproc = tmp_hwif->speedproc; hwif->selectproc = tmp_hwif->selectproc; @@ -624,9 +689,9 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes; hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes; - hwif->ide_dma_read = tmp_hwif->ide_dma_read; - hwif->ide_dma_write = tmp_hwif->ide_dma_write; - hwif->ide_dma_begin = tmp_hwif->ide_dma_begin; + hwif->dma_setup = tmp_hwif->dma_setup; + hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; + hwif->dma_start = tmp_hwif->dma_start; hwif->ide_dma_end = tmp_hwif->ide_dma_end; hwif->ide_dma_check = tmp_hwif->ide_dma_check; hwif->ide_dma_on = tmp_hwif->ide_dma_on; @@ -634,7 +699,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; hwif->ide_dma_host_on = tmp_hwif->ide_dma_host_on; hwif->ide_dma_host_off = tmp_hwif->ide_dma_host_off; - hwif->ide_dma_verbose = tmp_hwif->ide_dma_verbose; hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq; hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout; @@ -651,6 +715,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->INSW = tmp_hwif->INSW; hwif->INSL = tmp_hwif->INSL; + hwif->sg_max_nents = tmp_hwif->sg_max_nents; + hwif->mmio = tmp_hwif->mmio; hwif->rqsize = tmp_hwif->rqsize; hwif->no_lba48 = tmp_hwif->no_lba48; @@ -702,18 +768,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) void ide_unregister(unsigned int index) { ide_drive_t *drive; - ide_hwif_t *hwif, *g, *tmp_hwif; + ide_hwif_t *hwif, *g; + static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */ ide_hwgroup_t *hwgroup; int irq_count = 0, unit, i; BUG_ON(index >= MAX_HWIFS); - tmp_hwif = kmalloc(sizeof(*tmp_hwif), GFP_KERNEL|__GFP_NOFAIL); - if (!tmp_hwif) { - printk(KERN_ERR "%s: unable to allocate memory\n", __FUNCTION__); - return; - } - BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); down(&ide_cfg_sem); @@ -740,9 +801,7 @@ void ide_unregister(unsigned int index) DRIVER(drive)->cleanup(drive); } -#ifdef CONFIG_PROC_FS - destroy_proc_ide_drives(hwif); -#endif + destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; /* @@ -844,6 +903,7 @@ void ide_unregister(unsigned int index) hwif->drives[i].disk = NULL; put_disk(disk); } + kfree(hwif->sg_table); unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); @@ -860,19 +920,17 @@ void ide_unregister(unsigned int index) } /* copy original settings */ - *tmp_hwif = *hwif; + tmp_hwif = *hwif; /* restore hwif data to pristine status */ init_hwif_data(hwif, index); init_hwif_default(hwif, index); - ide_hwif_restore(hwif, tmp_hwif); + ide_hwif_restore(hwif, &tmp_hwif); abort: spin_unlock_irq(&ide_lock); up(&ide_cfg_sem); - - kfree(tmp_hwif); } EXPORT_SYMBOL(ide_unregister); @@ -931,11 +989,19 @@ void ide_setup_ports ( hw_regs_t *hw, */ } -/* - * Register an IDE interface, specifying exactly the registers etc - * Set init=1 iff calling before probes have taken place. +/** + * ide_register_hw_with_fixup - register IDE interface + * @hw: hardware registers + * @hwifp: pointer to returned hwif + * @fixup: fixup function + * + * Register an IDE interface, specifying exactly the registers etc. + * Set init=1 iff calling before probes have taken place. + * + * Returns -1 on error. */ -int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp) + +int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) { int index, retry = 1; ide_hwif_t *hwif; @@ -974,7 +1040,7 @@ found: hwif->chipset = hw->chipset; if (!initializing) { - probe_hwif_init(hwif); + probe_hwif_init_with_fixup(hwif, fixup); create_proc_ide_interfaces(); } @@ -984,6 +1050,13 @@ found: return (initializing || hwif->present) ? index : -1; } +EXPORT_SYMBOL(ide_register_hw_with_fixup); + +int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp) +{ + return ide_register_hw_with_fixup(hw, hwifp, NULL); +} + EXPORT_SYMBOL(ide_register_hw); /* @@ -1188,6 +1261,15 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) return val; } +/** + * ide_spin_wait_hwgroup - wait for group + * @drive: drive in the group + * + * Wait for an IDE device group to go non busy and then return + * holding the ide_lock which guards the hwgroup->busy status + * and right to use it. + */ + int ide_spin_wait_hwgroup (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); @@ -1229,6 +1311,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); * to the driver to change settings, and then wait on a sema for completion. * The current scheme of polling is kludgy, though safe enough. */ + int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { int i; @@ -1322,22 +1405,14 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) return err; } -int ide_atapi_to_scsi (ide_drive_t *drive, int arg) -{ - if (drive->media == ide_disk) { - drive->scsi = 0; - return 0; - } - - if (DRIVER(drive)->cleanup(drive)) { - drive->scsi = 0; - return 0; - } - - drive->scsi = (u8) arg; - ata_attach(drive); - return 0; -} +/** + * ide_add_generic_settings - generic ide settings + * @drive: drive being configured + * + * Add the generic parts of the system settings to the /proc files and + * ioctls for this IDE device. The caller must not be holding the + * ide_setting_sem. + */ void ide_add_generic_settings (ide_drive_t *drive) { @@ -1353,10 +1428,15 @@ void ide_add_generic_settings (ide_drive_t *drive) ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate); ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); - if (drive->media != ide_disk) - ide_add_setting(drive, "ide-scsi", SETTING_RW, -1, HDIO_SET_IDE_SCSI, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, ide_atapi_to_scsi); } +/** + * system_bus_clock - clock guess + * + * External version of the bus clock guess used by very old IDE drivers + * for things like VLB timings. Should not be used. + */ + int system_bus_clock (void) { return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed )); @@ -1391,6 +1471,22 @@ abort: return 1; } +/** + * ata_attach - attach an ATA/ATAPI device + * @drive: drive to attach + * + * Takes a drive that is as yet not assigned to any midlayer IDE + * driver (or is assigned to the default driver) and figures out + * which driver would like to own it. If nobody claims the drive + * then it is automatically attached to the default driver used for + * unclaimed objects. + * + * A return of zero indicates attachment to a driver, of one + * attachment to the default driver. + * + * Takes drivers_lock. + */ + int ata_attach(ide_drive_t *drive) { struct list_head *p; @@ -1691,9 +1787,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -#ifdef CONFIG_BLK_DEV_PDC4030 -static int __initdata probe_pdc4030; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX static int __initdata probe_ali14xx; extern int ali14xx_init(void); @@ -1753,7 +1846,7 @@ int __init ide_setup (char *s) #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ if (!strcmp(s, "ide=nodma")) { - printk("IDE: Prevented DMA\n"); + printk(" : Prevented DMA\n"); noautodma = 1; return 1; } @@ -1772,7 +1865,7 @@ int __init ide_setup (char *s) if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "serialize", - "autotune", "noautotune", "stroke", "swapdata", "bswap", + "autotune", "noautotune", "minus8", "swapdata", "bswap", "minus11", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; @@ -1802,13 +1895,10 @@ int __init ide_setup (char *s) goto do_serialize; case -6: /* "autotune" */ drive->autotune = IDE_TUNE_AUTO; - goto done; + goto obsolete_option; case -7: /* "noautotune" */ drive->autotune = IDE_TUNE_NOAUTO; - goto done; - case -8: /* stroke */ - drive->stroke = 1; - goto done; + goto obsolete_option; case -9: /* "swapdata" */ case -10: /* "bswap" */ drive->bswap = 1; @@ -1862,7 +1952,7 @@ int __init ide_setup (char *s) "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; + "dtc2278", "umc8672", "ali14xx", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -1888,11 +1978,6 @@ int __init ide_setup (char *s) } switch (i) { -#ifdef CONFIG_BLK_DEV_PDC4030 - case -18: /* "dc4030" */ - probe_pdc4030 = 1; - goto done; -#endif #ifdef CONFIG_BLK_DEV_ALI14XX case -17: /* "ali14xx" */ probe_ali14xx = 1; @@ -1945,30 +2030,30 @@ int __init ide_setup (char *s) case -7: /* ata66 */ #ifdef CONFIG_BLK_DEV_IDEPCI hwif->udma_four = 1; - goto done; + goto obsolete_option; #else goto bad_hwif; #endif case -6: /* dma */ hwif->autodma = 1; - goto done; + goto obsolete_option; case -5: /* "reset" */ hwif->reset = 1; - goto done; + goto obsolete_option; case -4: /* "noautotune" */ hwif->drives[0].autotune = IDE_TUNE_NOAUTO; hwif->drives[1].autotune = IDE_TUNE_NOAUTO; - goto done; + goto obsolete_option; case -3: /* "autotune" */ hwif->drives[0].autotune = IDE_TUNE_AUTO; hwif->drives[1].autotune = IDE_TUNE_AUTO; - goto done; + goto obsolete_option; case -2: /* "serialize" */ do_serialize: hwif->mate = &ide_hwifs[hw^1]; hwif->mate->mate = hwif; hwif->serialized = hwif->mate->serialized = 1; - goto done; + goto obsolete_option; case -1: /* "noprobe" */ hwif->noprobe = 1; @@ -1985,7 +2070,7 @@ int __init ide_setup (char *s) hwif->irq = vals[2]; hwif->noprobe = 0; hwif->chipset = ide_forced; - goto done; + goto obsolete_option; case 0: goto bad_option; default: @@ -1996,6 +2081,9 @@ int __init ide_setup (char *s) bad_option: printk(" -- BAD OPTION\n"); return 1; +obsolete_option: + printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); + return 1; bad_hwif: printk("-- NOT SUPPORTED ON ide%d", hw); done: @@ -2027,13 +2115,6 @@ static void __init probe_for_hwifs (void) ide_probe_for_cmd640x(); } #endif /* CONFIG_BLK_DEV_CMD640 */ -#ifdef CONFIG_BLK_DEV_PDC4030 - { - extern int pdc4030_init(void); - if (probe_pdc4030) - (void)pdc4030_init(); - } -#endif /* CONFIG_BLK_DEV_PDC4030 */ #ifdef CONFIG_BLK_DEV_IDE_PMAC { extern void pmac_ide_probe(void); @@ -2199,6 +2280,20 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) EXPORT_SYMBOL(ide_register_subdriver); +/** + * ide_unregister_subdriver - disconnect drive from driver + * @drive: drive to unplug + * + * Disconnect a drive from the driver it was attached to and then + * clean up the various proc files and other objects attached to it. + * + * Takes ide_setting_sem, ide_lock and drives_lock. + * Caller must hold none of the locks. + * + * No locking versus subdriver unload because we are moving to the + * default driver anyway. Wants double checking. + */ + int ide_unregister_subdriver (ide_drive_t *drive) { unsigned long flags; @@ -2234,6 +2329,17 @@ static int ide_drive_remove(struct device * dev) return 0; } +/** + * ide_register_driver - register IDE device driver + * @driver: the IDE device driver + * + * Register a new device driver and then scan the devices + * on the IDE bus in case any should be attached to the + * driver we have just registered. If so attach them. + * + * Takes drivers_lock and drives_lock. + */ + int ide_register_driver(ide_driver_t *driver) { struct list_head list; @@ -2265,6 +2371,17 @@ int ide_register_driver(ide_driver_t *driver) EXPORT_SYMBOL(ide_register_driver); +/** + * ide_unregister_driver - unregister IDE device driver + * @driver: the IDE device driver + * + * Called when a driver module is being unloaded. We reattach any + * devices to whatever driver claims them next (typically the default + * driver). + * + * Takes drivers_lock and called functions will take ide_setting_sem. + */ + void ide_unregister_driver(ide_driver_t *driver) { ide_drive_t *drive; @@ -2357,7 +2474,7 @@ int __init ide_init (void) #ifdef MODULE char *options = NULL; -MODULE_PARM(options,"s"); +module_param(options, charp, 0); MODULE_LICENSE("GPL"); static void __init parse_options (char *line) diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index ad8ae32b8..c79710617 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o -obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o @@ -10,6 +9,5 @@ obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o # Last of all obj-$(CONFIG_BLK_DEV_HD) += hd.o -obj-$(CONFIG_BLK_DEV_HD98) += hd98.o EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 537c87c5d..fb8871181 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -226,6 +226,8 @@ static int __init ali14xx_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index 65a1e7f4f..20eb5b872 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -141,6 +141,8 @@ static int __init probe_dtc2278(void) probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 5d35808ac..67d54d787 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -174,7 +174,7 @@ unsigned long read_timer(void) } #endif -void __init hd_setup(char *str, int *ints) +static void __init hd_setup(char *str, int *ints) { int hdind = 0; @@ -239,7 +239,7 @@ static void dump_status (const char *msg, unsigned int stat) #endif } -void check_status(void) +static void check_status(void) { int i = inb_p(HD_STATUS); @@ -386,7 +386,7 @@ repeat: * drive enters "idle", "standby", or "sleep" mode, so if the status looks * "good", we just ignore the interrupt completely. */ -void unexpected_hd_interrupt(void) +static void unexpected_hd_interrupt(void) { unsigned int stat = inb_p(HD_STATUS); @@ -551,7 +551,7 @@ static void hd_times_out(unsigned long dummy) enable_irq(HD_IRQ); } -int do_special_op(struct hd_i_struct *disk, struct request *req) +static int do_special_op(struct hd_i_struct *disk, struct request *req) { if (disk->recalibrate) { disk->recalibrate = 0; diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index eb1c448b4..a77fb249d 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -352,6 +352,8 @@ int __init ht6560b_init(void) probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; release_region: diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 3147d9099..36426f72c 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -206,7 +206,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq ide_init_hwif_ports(&hw, io, ctl, NULL); hw.irq = irq; hw.chipset = ide_pci; - return ide_register_hw(&hw, NULL); + return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); } /*====================================================================== @@ -412,12 +412,6 @@ void ide_release(dev_link_t *link) /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); - /* deal with brain dead IDE resource management */ - request_region(link->io.BasePort1, link->io.NumPorts1, - info->node.dev_name); - if (link->io.NumPorts2) - request_region(link->io.BasePort2, link->io.NumPorts2, - info->node.dev_name); } info->ndev = 0; link->dev = NULL; diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 2e6267c41..563fab009 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -101,7 +101,7 @@ static void qd_write_reg (u8 content, unsigned long reg) spin_unlock_irqrestore(&ide_lock, flags); } -u8 __init qd_read_reg (unsigned long reg) +static u8 __init qd_read_reg (unsigned long reg) { unsigned long flags; u8 read; @@ -429,6 +429,9 @@ static int __init qd_probe(int base) qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); + + create_proc_ide_interfaces(); + return 1; } @@ -459,6 +462,8 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + create_proc_ide_interfaces(); + return 1; } else { ide_hwif_t *mate; @@ -477,6 +482,8 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); + create_proc_ide_interfaces(); + return 0; /* no other qd65xx possible */ } } diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h index 1557a47ff..633a42456 100644 --- a/drivers/ide/legacy/qd65xx.h +++ b/drivers/ide/legacy/qd65xx.h @@ -46,11 +46,11 @@ /* Drive specific timing taken from DOS driver v3.7 */ -struct qd65xx_timing_s { - char offset; /* ofset from the beginning of Model Number" */ +static struct qd65xx_timing_s { + s8 offset; /* ofset from the beginning of Model Number" */ char model[4]; /* 4 chars from Model number, no conversion */ - short active; /* active time */ - short recovery; /* recovery time */ + s16 active; /* active time */ + s16 recovery; /* recovery time */ } qd65xx_timing [] = { { 30, "2040", 110, 225 }, /* Conner CP30204 */ { 30, "2045", 135, 225 }, /* Conner CP30254 */ diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 68961c2cf..cdbdb2ff9 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -161,6 +161,8 @@ static int __init umc8672_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); + create_proc_ide_interfaces(); + return 0; } diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index b032d2459..36b19c867 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -18,57 +18,7 @@ #include "aec62xx.h" -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 aec62xx_proc = 0; - -#define AEC_MAX_DEVS 5 - -static struct pci_dev *aec_devs[AEC_MAX_DEVS]; -static int n_aec_devs; - -#undef DEBUG_AEC_REGS - -static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - char *chipset_nums[] = {"error", "error", "error", "error", - "error", "error", "850UF", "860", - "860R", "865", "865R", "error" }; - int len; - int i; - - for (i = 0; i < n_aec_devs; i++) { - struct pci_dev *dev = aec_devs[i]; - unsigned long iobase = pci_resource_start(dev, 4); - u8 c0 = 0, c1 = 0, art = 0; -#ifdef DEBUG_AEC_REGS - u8 uart = 0; -#endif /* DEBUG_AEC_REGS */ - - c0 = inb(iobase + 0x02); - c1 = inb(iobase + 0x0a); - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - (void) pci_read_config_byte(dev, 0x4a, &art); - p += sprintf(p, " %sabled ", - (art&0x02)?" en":"dis"); - p += sprintf(p, " %sabled\n", - (art&0x04)?" en":"dis"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s ", - (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no "); - p += sprintf(p, " %s %s\n", - (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); - +#if 0 if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { (void) pci_read_config_byte(dev, 0x54, &art); p += sprintf(p, "DMA Mode: %s(%s)", @@ -83,100 +33,8 @@ static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) p += sprintf(p, " %s(%s)\n", (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", (art&0x80)?"2":(art&0x40)?"1":"0"); -#ifdef DEBUG_AEC_REGS - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Active: 0x%02x", art); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x44, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x46, &art); - p += sprintf(p, " 0x%02x\n", art); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, "Recovery: 0x%02x", art); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x45, &art); - p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(dev, 0x47, &art); - p += sprintf(p, " 0x%02x\n", art); -#endif /* DEBUG_AEC_REGS */ } else { - /* - * case PCI_DEVICE_ID_ARTOP_ATP860: - * case PCI_DEVICE_ID_ARTOP_ATP860R: - * case PCI_DEVICE_ID_ARTOP_ATP865: - * case PCI_DEVICE_ID_ARTOP_ATP865R: - */ - (void) pci_read_config_byte(dev, 0x44, &art); - p += sprintf(p, "DMA Mode: %s(%s)", - (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x07)==0x07)?"6": - ((art&0x06)==0x06)?"5": - ((art&0x05)==0x05)?"4": - ((art&0x04)==0x04)?"3": - ((art&0x03)==0x03)?"2": - ((art&0x02)==0x02)?"1": - ((art&0x01)==0x01)?"0":"?"); - p += sprintf(p, " %s(%s)", - (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x70)==0x70)?"6": - ((art&0x60)==0x60)?"5": - ((art&0x50)==0x50)?"4": - ((art&0x40)==0x40)?"3": - ((art&0x30)==0x30)?"2": - ((art&0x20)==0x20)?"1": - ((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(dev, 0x45, &art); - p += sprintf(p, " %s(%s)", - (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x07)==0x07)?"6": - ((art&0x06)==0x06)?"5": - ((art&0x05)==0x05)?"4": - ((art&0x04)==0x04)?"3": - ((art&0x03)==0x03)?"2": - ((art&0x02)==0x02)?"1": - ((art&0x01)==0x01)?"0":"?"); - p += sprintf(p, " %s(%s)\n", - (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x70)==0x70)?"6": - ((art&0x60)==0x60)?"5": - ((art&0x50)==0x50)?"4": - ((art&0x40)==0x40)?"3": - ((art&0x30)==0x30)?"2": - ((art&0x20)==0x20)?"1": - ((art&0x10)==0x10)?"0":"?"); -#ifdef DEBUG_AEC_REGS - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Active: 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x\n", HIGH_4(art)); - (void) pci_read_config_byte(dev, 0x40, &art); - p += sprintf(p, "Recovery: 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x41, &art); - p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x42, &art); - p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x43, &art); - p += sprintf(p, " 0x%02x\n", LOW_4(art)); - (void) pci_read_config_byte(dev, 0x49, &uart); - p += sprintf(p, "reg49h = 0x%02x ", uart); - (void) pci_read_config_byte(dev, 0x4a, &uart); - p += sprintf(p, "reg4ah = 0x%02x\n", uart); -#endif /* DEBUG_AEC_REGS */ - } - } - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif /* * TO DO: active tuning and correction of cards without a bios. @@ -240,6 +98,7 @@ static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed) unsigned long flags; local_irq_save(flags); + /* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */ pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev)); SPLIT_BYTE(tmp0,tmp1,tmp2); @@ -268,6 +127,7 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed) unsigned long flags; local_irq_save(flags); + /* high 4-bits: Active, low 4-bits: Recovery */ pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev)); pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); @@ -329,36 +189,16 @@ static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) struct hd_driveid *id = drive->id; if ((id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: aec62xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -418,15 +258,6 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); } -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) - aec_devs[n_aec_devs++] = dev; - - if (!aec62xx_proc) { - aec62xx_proc = 1; - ide_pci_create_host_proc("aec62xx", aec62xx_get_info); - } -#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ - if (bus_speed <= 33) pci_set_drvdata(dev, (void *) aec6xxx_33_base); else @@ -540,7 +371,7 @@ static struct pci_device_id aec62xx_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl); static struct pci_driver driver = { - .name = "AEC62xx IDE", + .name = "AEC62xx_IDE", .id_table = aec62xx_pci_tbl, .probe = aec62xx_init_one, }; diff --git a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h index 3f272752c..b7d0ee3fa 100644 --- a/drivers/ide/pci/aec62xx.h +++ b/drivers/ide/pci/aec62xx.h @@ -5,15 +5,13 @@ #include #include -#define DISPLAY_AEC62XX_TIMINGS - struct chipset_bus_clock_list_entry { byte xfer_speed; byte chipset_settings; byte ultra_settings; }; -struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { +static struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { { XFER_UDMA_6, 0x31, 0x07 }, { XFER_UDMA_5, 0x31, 0x06 }, { XFER_UDMA_4, 0x31, 0x05 }, @@ -33,7 +31,7 @@ struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { { 0, 0x00, 0x00 } }; -struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { +static struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { { XFER_UDMA_6, 0x41, 0x06 }, { XFER_UDMA_5, 0x41, 0x05 }, { XFER_UDMA_4, 0x41, 0x04 }, @@ -53,13 +51,6 @@ struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { { 0, 0x00, 0x00 } }; - -#ifndef HIGH_4 -#define HIGH_4(H) ((H)=(H>>4)) -#endif -#ifndef LOW_4 -#define LOW_4(L) ((L)=(L-((L>>4)<<4))) -#endif #ifndef SPLIT_BYTE #define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) #endif diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 2a343679a..095ea1e3a 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -8,6 +8,7 @@ * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License * Copyright (C) 2002 Alan Cox + * ALi (now ULi M5228) support by Clear Zhang * * (U)DMA capable version of ali 1533/1543(C), 1535(D) * @@ -558,18 +559,19 @@ no_dma_set: } /** - * ali15x3_dma_write - do a DMA IDE write - * @drive: drive to issue write for + * ali15x3_dma_setup - begin a DMA phase + * @drive: target device * - * Returns 1 if the DMA write cannot be performed, zero on - * success. + * Returns 1 if the DMA cannot be performed, zero on success. */ - -static int ali15x3_dma_write (ide_drive_t *drive) + +static int ali15x3_dma_setup(ide_drive_t *drive) { - if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) - return 1; /* try PIO instead of DMA */ - return __ide_dma_write(drive); + if (m5229_revision < 0xC2 && drive->media != ide_disk) { + if (rq_data_dir(drive->hwif->hwgroup->rq)) + return 1; /* try PIO instead of DMA */ + } + return ide_dma_setup(drive); } /** @@ -752,8 +754,8 @@ static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->tuneproc = &ali15x3_tune_drive; hwif->speedproc = &ali15x3_tune_chipset; - /* Don't use LBA48 on ALi devices before rev 0xC5 */ - hwif->no_lba48 = (m5229_revision <= 0xC4) ? 1 : 0; + /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ + hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0; if (!hwif->dma_base) { hwif->drives[0].autotune = 1; @@ -773,7 +775,7 @@ static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif) * M1543C or newer for DMAing */ hwif->ide_dma_check = &ali15x3_config_drive_for_dma; - hwif->ide_dma_write = &ali15x3_dma_write; + hwif->dma_setup = &ali15x3_dma_setup; if (!noautodma) hwif->autodma = 1; if (!(hwif->udma_four)) @@ -798,8 +800,9 @@ static void __init init_hwif_ali15x3 (ide_hwif_t *hwif) s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; int irq = -1; - - hwif->irq = hwif->channel ? 15 : 14; + + if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229) + hwif->irq = hwif->channel ? 15 : 14; if (isa_dev) { /* @@ -888,12 +891,13 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev static struct pci_device_id alim15x3_pci_tbl[] = { { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); static struct pci_driver driver = { - .name = "ALI15x3 IDE", + .name = "ALI15x3_IDE", .id_table = alim15x3_pci_tbl, .probe = alim15x3_init_one, }; diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 30bdcb3ec..fc7b59481 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -416,6 +416,9 @@ static void __init init_hwif_amd74xx(ide_hwif_t *hwif) { int i; + if (hwif->irq == 0) /* 0 is bogus but will do for now */ + hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel); + hwif->autodma = 0; hwif->tuneproc = &amd74xx_tune_drive; @@ -520,7 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); static struct pci_driver driver = { - .name = "AMD IDE", + .name = "AMD_IDE", .id_table = amd74xx_pci_tbl, .probe = amd74xx_probe, }; diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index bd3708568..f7deea91a 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -47,102 +47,6 @@ static atiixp_ide_timing mdma_timing[] = { static int save_mdma_mode[4]; -#define DISPLAY_ATIIXP_TIMINGS - -#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) - -#include -#include - -static u8 atiixp_proc; -static struct pci_dev *bmide_dev; - -/** - * atiixp_get_info - fill in /proc for ATIIXP IDE - * @buffer: buffer to fill - * @addr: address of user start in buffer - * @offset: offset into 'file' - * @count: buffer count - * - * Output summary data on the tuning. - */ - -static int atiixp_get_info(char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - struct pci_dev *dev = bmide_dev; - unsigned long bibma = pci_resource_start(dev, 4); - u32 mdma_timing = 0; - u16 udma_mode = 0, pio_mode = 0; - u8 c0, c1, udma_control = 0; - - p += sprintf(p, "\n ATI "); - p += sprintf(p, "ATIIXP Ultra100 IDE Chipset.\n"); - - pci_read_config_byte(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_control); - pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &udma_mode); - pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode); - pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &mdma_timing); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb(bibma + 0x02); - c1 = inb(bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0 & 0x80) ? "dis" : " en", - (c1 & 0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0 & 0x20) ? "yes" : "no ", - (c0 & 0x40) ? "yes" : "no ", - (c1 & 0x20) ? "yes" : "no ", - (c1 & 0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - (udma_control & 0x01) ? "yes" : "no ", - (udma_control & 0x02) ? "yes" : "no ", - (udma_control & 0x04) ? "yes" : "no ", - (udma_control & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA mode: %c %c " - " %c %c\n", - (udma_control & 0x01) ? - ((udma_mode & 0x07) + 48) : 'X', - (udma_control & 0x02) ? - (((udma_mode >> 4) & 0x07) + 48) : 'X', - (udma_control & 0x04) ? - (((udma_mode >> 8) & 0x07) + 48) : 'X', - (udma_control & 0x08) ? - (((udma_mode >> 12) & 0x07) + 48) : 'X'); - p += sprintf(p, "MDMA mode: %c %c " - " %c %c\n", - (save_mdma_mode[0] && (c0 & 0x20)) ? - ((save_mdma_mode[0] & 0xf) + 48) : 'X', - (save_mdma_mode[1] && (c0 & 0x40)) ? - ((save_mdma_mode[1] & 0xf) + 48) : 'X', - (save_mdma_mode[2] && (c1 & 0x20)) ? - ((save_mdma_mode[2] & 0xf) + 48) : 'X', - (save_mdma_mode[3] && (c1 & 0x40)) ? - ((save_mdma_mode[3] & 0xf) + 48) : 'X'); - p += sprintf(p, "PIO mode: %c %c " - " %c %c\n", - (c0 & 0x20) ? 'X' : ((pio_mode & 0x07) + 48), - (c0 & 0x40) ? 'X' : (((pio_mode >> 4) & 0x07) + 48), - (c1 & 0x20) ? 'X' : (((pio_mode >> 8) & 0x07) + 48), - (c1 & 0x40) ? 'X' : (((pio_mode >> 12) & 0x07) + 48)); - - return p - buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) */ - /** * atiixp_ratemask - compute rate mask for ATIIXP IDE * @drive: IDE drive to compute for @@ -357,36 +261,16 @@ static int atiixp_dma_check(ide_drive_t *drive) drive->init_speed = 0; if ((id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - if ((id->field_valid & 2) && - (!atiixp_config_drive_for_dma(drive))) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!atiixp_config_drive_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!atiixp_config_drive_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (atiixp_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0; hwif->speedproc(drive, speed); @@ -396,27 +280,6 @@ no_dma_set: return 0; } -/** - * init_chipset_atiixp - set up the ATIIXP chipset - * @dev: PCI device to set up - * @name: Name of the device - * - * Initialize the PCI device as required. For the ATIIXP this turns - * out to be nice and simple - */ - -static unsigned int __devinit init_chipset_atiixp(struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) - if (!atiixp_proc) { - atiixp_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("atiixp", atiixp_get_info); - } -#endif /* DISPLAY_ATIIXP_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - /** * init_hwif_atiixp - fill in the hwif for the ATIIXP * @hwif: IDE interface @@ -459,7 +322,6 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) static ide_pci_device_t atiixp_pci_info[] __devinitdata = { { /* 0 */ .name = "ATIIXP", - .init_chipset = init_chipset_atiixp, .init_hwif = init_hwif_atiixp, .channels = 2, .autodma = AUTODMA, @@ -485,12 +347,13 @@ static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_devic static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); static struct pci_driver driver = { - .name = "ATIIXP IDE", + .name = "ATIIXP_IDE", .id_table = atiixp_pci_tbl, .probe = atiixp_init_one, }; diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 0eac8ee64..92a2b7cae 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -101,6 +101,8 @@ #undef REALLY_SLOW_IO /* most systems can safely undef this */ #define CMD640_PREFETCH_MASKS 1 +//#define CMD640_DUMP_REGS + #include #include #include @@ -748,7 +750,7 @@ int __init ide_probe_for_cmd640x (void) put_cmd640_reg(0x5b, 0); #ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; + cmd640_dump_regs(); #endif /* @@ -870,7 +872,7 @@ int __init ide_probe_for_cmd640x (void) } #ifdef CMD640_DUMP_REGS - CMD640_DUMP_REGS; + cmd640_dump_regs(); #endif return 1; } diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 06b00a3c3..aaadb17cd 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -38,8 +38,6 @@ static u8 cmd64x_proc = 0; static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; static int n_cmd_devs; -#undef DEBUG_CMD_REGS - static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) { char *p = buf; @@ -49,9 +47,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) u8 reg72 = 0, reg73 = 0; /* primary */ u8 reg7a = 0, reg7b = 0; /* secondary */ u8 reg50 = 0, reg71 = 0; /* extra */ -#ifdef DEBUG_CMD_REGS - u8 hi_byte = 0, lo_byte = 0; -#endif /* DEBUG_CMD_REGS */ p += sprintf(p, "\nController: %d\n", index); p += sprintf(p, "CMD%x Chipset.\n", dev->device); @@ -127,18 +122,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); -#ifdef DEBUG_CMD_REGS - SPLIT_BYTE(reg50, hi_byte, lo_byte); - p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg50, hi_byte, lo_byte); - SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg57, hi_byte, lo_byte); - SPLIT_BYTE(reg71, hi_byte, lo_byte); - p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, " - "LOW = 0x%02x\n", reg71, hi_byte, lo_byte); -#endif /* DEBUG_CMD_REGS */ - return (char *)p; } @@ -458,36 +441,16 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive) struct hd_driveid *id = drive->id; if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if ((id->field_valid & 4) && cmd64x_ratemask(drive)) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: config_chipset_for_pio(drive, 1); return hwif->ide_dma_off_quietly(drive); } @@ -760,7 +723,7 @@ static struct pci_device_id cmd64x_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl); static struct pci_driver driver = { - .name = "CMD64x IDE", + .name = "CMD64x_IDE", .id_table = cmd64x_pci_tbl, .probe = cmd64x_init_one, }; diff --git a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h index f5dde235a..78490275d 100644 --- a/drivers/ide/pci/cmd64x.h +++ b/drivers/ide/pci/cmd64x.h @@ -15,10 +15,6 @@ #define cmdprintk(x...) #endif -#ifndef SPLIT_BYTE -#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) -#endif - /* * CMD64x specific registers definition. */ diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 5882693d0..5cc037e10 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -51,57 +51,6 @@ #include #include -#define DISPLAY_CS5520_TIMINGS - -#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5520_proc = 0; -static struct pci_dev *bmide_dev; - -static int cs5520_get_info(char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - unsigned long bmiba = pci_resource_start(bmide_dev, 2); - int len; - u8 c0 = 0, c1 = 0; - u16 reg16; - u32 reg32; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb(bmiba + 0x02); - c1 = inb(bmiba + 0x0a); - - p += sprintf(p, "\nCyrix CS55x0 IDE\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - - p += sprintf(p, "\n\nTimings: \n"); - - pci_read_config_word(bmide_dev, 0x62, ®16); - p += sprintf(p, "8bit CAT/CRT : %04x\n", reg16); - pci_read_config_dword(bmide_dev, 0x64, ®32); - p += sprintf(p, "16bit Primary : %08x\n", reg32); - pci_read_config_dword(bmide_dev, 0x68, ®32); - p += sprintf(p, "16bit Secondary: %08x\n", reg32); - - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} - -#endif - struct pio_clocks { int address; @@ -109,7 +58,7 @@ struct pio_clocks int recovery; }; -struct pio_clocks cs5520_pio_clocks[]={ +static struct pio_clocks cs5520_pio_clocks[]={ {3, 6, 11}, {2, 5, 6}, {1, 4, 3}, @@ -144,12 +93,14 @@ static int cs5520_tune_chipset(ide_drive_t *drive, u8 xferspeed) printk("PIO clocking = %d\n", pio); /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */ - - /* 8bit command timing for channel */ + + /* 8bit CAT/CRT - 8bit command timing for channel */ pci_write_config_byte(pdev, 0x62 + controller, (cs5520_pio_clocks[pio].recovery << 4) | (cs5520_pio_clocks[pio].assert)); - + + /* 0x64 - 16bit Primary, 0x68 - 16bit Secondary */ + /* FIXME: should these use address ? */ /* Data read timing */ pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1), @@ -188,19 +139,6 @@ static int cs5520_config_drive_xfer_rate(ide_drive_t *drive) /* Then tell the core to use DMA operations */ return hwif->ide_dma_on(drive); } - - -static unsigned int __devinit init_chipset_cs5520(struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cs5520_proc) { - cs5520_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("cs5520", cs5520_get_info); - } -#endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */ - return 0; -} /* * We provide a callback for our nonstandard DMA location @@ -255,7 +193,6 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) #define DECLARE_CS_DEV(name_str) \ { \ .name = name_str, \ - .init_chipset = init_chipset_cs5520, \ .init_setup_dma = cs5520_init_setup_dma, \ .init_hwif = init_hwif_cs5520, \ .channels = 2, \ @@ -290,8 +227,10 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic return 1; } pci_set_master(dev); - pci_set_dma_mask(dev, 0xFFFFFFFF); - init_chipset_cs5520(dev, d->name); + if (pci_set_dma_mask(dev, 0xFFFFFFFF)) { + printk(KERN_WARNING "cs5520: No suitable DMA available.\n"); + return -ENODEV; + } index.all = 0xf0f0; @@ -300,10 +239,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic * do all the device setup for us */ - ide_pci_setup_ports(dev, d, 1, 14, &index); + ide_pci_setup_ports(dev, d, 14, &index); - printk("Index.b %d %d\n", index.b.low, index.b.high); - mdelay(2000); if((index.b.low & 0xf0) != 0xf0) probe_hwif_init(&ide_hwifs[index.b.low]); if((index.b.high & 0xf0) != 0xf0) @@ -319,7 +256,7 @@ static struct pci_device_id cs5520_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl); static struct pci_driver driver = { - .name = "CyrixIDE", + .name = "Cyrix_IDE", .id_table = cs5520_pci_tbl, .probe = cs5520_init_one, }; diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index b63e2d611..0457a8ea0 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -31,56 +31,6 @@ #include #include -#define DISPLAY_CS5530_TIMINGS - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5530_proc = 0; - -static struct pci_dev *bmide_dev; - -static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - unsigned long bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - - c0 = inb_p((u16)bibma + 0x02); - c1 = inb_p((u16)bibma + 0x0a); - - p += sprintf(p, "\n " - "Cyrix 5530 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - return p-buffer; -} -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - /** * cs5530_xfer_set_mode - set a new transfer mode at the drive * @drive: drive to tune @@ -272,14 +222,6 @@ static unsigned int __init init_chipset_cs5530 (struct pci_dev *dev, const char struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; unsigned long flags; -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cs5530_proc) { - cs5530_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("cs5530", cs5530_get_info); - } -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - dev = NULL; while ((dev = pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { switch (dev->device) { @@ -411,7 +353,6 @@ static ide_pci_device_t cs5530_chipset __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, - .flags = IDEPCI_FLAG_FORCE_MASTER, }; static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index fe840cbe0..ec4860818 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -183,7 +183,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) /* * used to set DMA mode for CY82C693 (single and multi modes) */ -int cy82c693_ide_dma_on (ide_drive_t *drive) +static int cy82c693_ide_dma_on (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -444,7 +444,7 @@ static struct pci_device_id cy82c693_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl); static struct pci_driver driver = { - .name = "Cypress IDE", + .name = "Cypress_IDE", .id_table = cy82c693_pci_tbl, .probe = cy82c693_init_one, }; diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 2150a18a8..e826f730a 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -41,12 +41,12 @@ #include "generic.h" -static unsigned int __init init_chipset_generic (struct pci_dev *dev, const char *name) +static unsigned int __devinit init_chipset_generic (struct pci_dev *dev, const char *name) { return 0; } -static void __init init_hwif_generic (ide_hwif_t *hwif) +static void __devinit init_hwif_generic (ide_hwif_t *hwif) { switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_UMC_UM8673F: @@ -138,7 +138,7 @@ static struct pci_device_id generic_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, generic_pci_tbl); static struct pci_driver driver = { - .name = "PCI IDE", + .name = "PCI_IDE", .id_table = generic_pci_tbl, .probe = generic_init_one, }; diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index f9c9ab664..59abcf084 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -42,66 +42,7 @@ #include #include -#include "hpt34x.h" - -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 hpt34x_proc = 0; - -#define HPT34X_MAX_DEVS 8 -static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS]; -static int n_hpt34x_devs; - -static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i, len; - - p += sprintf(p, "\n " - "HPT34X Chipset.\n"); - for (i = 0; i < n_hpt34x_devs; i++) { - struct pci_dev *dev = hpt34x_devs[i]; - unsigned long bibma = pci_resource_start(dev, 4); - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((u16)bibma + 0x02); - c1 = inb_p((u16)bibma + 0x0a); - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - } - p += sprintf(p, "\n"); - - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ +#define HPT343_DEBUG_DRIVE_INFO 0 static u8 hpt34x_ratemask (ide_drive_t *drive) { @@ -128,7 +69,8 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; u8 hi_speed, lo_speed; - SPLIT_BYTE(speed, hi_speed, lo_speed); + hi_speed = speed >> 4; + lo_speed = speed & 0x0f; if (hi_speed & 7) { hi_speed = (hi_speed & 4) ? 0x01 : 0x10; @@ -189,40 +131,20 @@ static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; - } + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) #ifndef CONFIG_HPT34X_AUTODMA - return hwif->ide_dma_off_quietly(drive); + return hwif->ide_dma_off_quietly(drive); #else - return hwif->ide_dma_on(drive); + return hwif->ide_dma_on(drive); #endif + } + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: hpt34x_tune_drive(drive, 255); return hwif->ide_dma_off_quietly(drive); } @@ -277,15 +199,6 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha local_irq_restore(flags); -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) - hpt34x_devs[n_hpt34x_devs++] = dev; - - if (!hpt34x_proc) { - hpt34x_proc = 1; - ide_pci_create_host_proc("hpt34x", hpt34x_get_info); - } -#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ - return dev->irq; } @@ -317,9 +230,19 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) hwif->drives[1].autodma = hwif->autodma; } +static ide_pci_device_t hpt34x_chipset __devinitdata = { + .name = "HPT34X", + .init_chipset = init_chipset_hpt34x, + .init_hwif = init_hwif_hpt34x, + .channels = 2, + .autodma = NOAUTODMA, + .bootable = NEVER_BOARD, + .extra = 16 +}; + static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &hpt34x_chipsets[id->driver_data]; + ide_pci_device_t *d = &hpt34x_chipset; static char *chipset_names[] = {"HPT343", "HPT345"}; u16 pcicmd = 0; @@ -339,7 +262,7 @@ static struct pci_device_id hpt34x_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl); static struct pci_driver driver = { - .name = "HPT34x IDE", + .name = "HPT34x_IDE", .id_table = hpt34x_pci_tbl, .probe = hpt34x_init_one, }; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 5f5bc3b6e..462bf1164 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -72,49 +72,6 @@ #include "hpt366.h" -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static unsigned int hpt_revision(struct pci_dev *dev); -static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision); - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - -static u8 hpt366_proc = 0; -static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; -static int n_hpt_devs; - -static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - char *chipset_nums[] = {"366", "366", "368", - "370", "370A", "372", - "302", "371", "374" }; - int i, len; - - p += sprintf(p, "\n " - "HighPoint HPT366/368/370/372/374\n"); - for (i = 0; i < n_hpt_devs; i++) { - struct pci_dev *dev = hpt_devs[i]; - unsigned long iobase = dev->resource[4].start; - u32 class_rev = hpt_revision(dev); - u8 c0, c1; - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]); - p += sprintf(p, "--------------- Primary Channel " - "--------------- Secondary Channel " - "--------------\n"); - - /* get the bus master status registers */ - c0 = inb(iobase + 0x2); - c1 = inb(iobase + 0xa); - p += sprintf(p, "Enabled: %s" - " %s\n", - (c0 & 0x80) ? "no" : "yes", - (c1 & 0x80) ? "no" : "yes"); #if 0 if (hpt_minimum_revision(dev, 3)) { u8 cbl; @@ -128,16 +85,6 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) (cbl & 0x01) ? 33 : 66); p += sprintf(p, "\n"); } -#endif - p += sprintf(p, "--------------- drive0 --------- drive1 " - "------- drive0 ---------- drive1 -------\n"); - p += sprintf(p, "DMA capable: %s %s" - " %s %s\n", - (c0 & 0x20) ? "yes" : "no ", - (c0 & 0x40) ? "yes" : "no ", - (c1 & 0x20) ? "yes" : "no ", - (c1 & 0x40) ? "yes" : "no "); - { u8 c2, c3; /* older revs don't have these registers mapped @@ -159,15 +106,7 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) (c3 & 0x80) ? "PIO " : "off "); } } - p += sprintf(p, "\n"); - - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ +#endif static u32 hpt_revision (struct pci_dev *dev) { @@ -521,35 +460,16 @@ static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if (id->dma_mword & hwif->mwdma_mask) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: hpt3xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -577,7 +497,7 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive) /* how about we flush and reset, mmmkay? */ pci_write_config_byte(dev, 0x51, 0x1F); /* fall through to a reset */ - case ide_dma_begin: + case dma_start: case ide_dma_end: /* reset the chips state over and over.. */ pci_write_config_byte(dev, 0x51, 0x13); @@ -592,12 +512,12 @@ static void hpt370_clear_engine (ide_drive_t *drive) udelay(10); } -static int hpt370_ide_dma_begin (ide_drive_t *drive) +static void hpt370_ide_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive); #endif - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int hpt370_ide_dma_end (ide_drive_t *drive) @@ -777,9 +697,6 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state) u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; - if (!hwif) - return -EINVAL; - // hwif->bus_state = state; pci_read_config_byte(dev, 0x59, ®59h); @@ -813,9 +730,6 @@ static int hpt370_busproc(ide_drive_t * drive, int state) u8 tristate = 0, resetmask = 0, bus_reg = 0; u16 tri_reg; - if (!hwif) - return -EINVAL; - hwif->bus_state = state; if (hwif->channel) { @@ -958,7 +872,7 @@ static int __devinit init_hpt37x(struct pci_dev *dev) /* Unsupported */ } else if (pll == F_LOW_PCI_50) { if (hpt_minimum_revision(dev,8)) - pci_set_drvdata(dev, NULL); + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); else if (hpt_minimum_revision(dev,5)) pci_set_drvdata(dev, (void *) fifty_base_hpt372); else if (hpt_minimum_revision(dev,4)) @@ -991,11 +905,6 @@ static int __devinit init_hpt37x(struct pci_dev *dev) if (pci_get_drvdata(dev)) goto init_hpt37X_done; - if (hpt_minimum_revision(dev,8)) - { - printk(KERN_ERR "HPT374: Only 33MHz PCI timings are supported.\n"); - return -EOPNOTSUPP; - } /* * adjust PLL based upon PCI clock, enable it, and wait for * stabilization. @@ -1116,15 +1025,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha } if (ret) return ret; - -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - hpt_devs[n_hpt_devs++] = dev; - - if (!hpt366_proc) { - hpt366_proc = 1; - ide_pci_create_host_proc("hpt366", hpt366_get_info); - } -#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ return dev->irq; } @@ -1241,7 +1141,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; } else if (hpt_minimum_revision(dev,3)) { - hwif->ide_dma_begin = &hpt370_ide_dma_begin; + hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; @@ -1403,7 +1303,7 @@ static struct pci_device_id hpt366_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); static struct pci_driver driver = { - .name = "HPT366 IDE", + .name = "HPT366_IDE", .id_table = hpt366_pci_tbl, .probe = hpt366_init_one, }; diff --git a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h index 388d6ae49..91e2f8eaf 100644 --- a/drivers/ide/pci/hpt366.h +++ b/drivers/ide/pci/hpt366.h @@ -5,14 +5,12 @@ #include #include -#define DISPLAY_HPT366_TIMINGS - /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE #undef HPT_DELAY_INTERRUPT #undef HPT_SERIALIZE_IO -const char *quirk_drives[] = { +static const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", "QUANTUM FIREBALLP LM20.4", @@ -20,7 +18,7 @@ const char *quirk_drives[] = { NULL }; -const char *bad_ata100_5[] = { +static const char *bad_ata100_5[] = { "IBM-DTLA-307075", "IBM-DTLA-307060", "IBM-DTLA-307045", @@ -39,7 +37,7 @@ const char *bad_ata100_5[] = { NULL }; -const char *bad_ata66_4[] = { +static const char *bad_ata66_4[] = { "IBM-DTLA-307075", "IBM-DTLA-307060", "IBM-DTLA-307045", @@ -58,12 +56,12 @@ const char *bad_ata66_4[] = { NULL }; -const char *bad_ata66_3[] = { +static const char *bad_ata66_3[] = { "WDC AC310200R", NULL }; -const char *bad_ata33[] = { +static const char *bad_ata33[] = { "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", @@ -101,7 +99,7 @@ struct chipset_bus_clock_list_entry { * PIO. * 31 FIFO enable. */ -struct chipset_bus_clock_list_entry forty_base_hpt366[] = { +static struct chipset_bus_clock_list_entry forty_base_hpt366[] = { { XFER_UDMA_4, 0x900fd943 }, { XFER_UDMA_3, 0x900ad943 }, { XFER_UDMA_2, 0x900bd943 }, @@ -120,7 +118,7 @@ struct chipset_bus_clock_list_entry forty_base_hpt366[] = { { 0, 0x0120d9d9 } }; -struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { +static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { { XFER_UDMA_4, 0x90c9a731 }, { XFER_UDMA_3, 0x90cfa731 }, { XFER_UDMA_2, 0x90caa731 }, @@ -139,7 +137,7 @@ struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { { 0, 0x0120a7a7 } }; -struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { +static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { { XFER_UDMA_4, 0x90c98521 }, { XFER_UDMA_3, 0x90cf8521 }, @@ -160,7 +158,7 @@ struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { }; /* from highpoint documentation. these are old values */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { +static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { /* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ { XFER_UDMA_5, 0x16454e31 }, { XFER_UDMA_4, 0x16454e31 }, @@ -181,7 +179,7 @@ struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { { 0, 0x06514e57 } }; -struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { +static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { { XFER_UDMA_5, 0x14846231 }, { XFER_UDMA_4, 0x14886231 }, { XFER_UDMA_3, 0x148c6231 }, @@ -202,7 +200,7 @@ struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { }; /* these are the current (4 sep 2001) timings from highpoint */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { +static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { { XFER_UDMA_5, 0x12446231 }, { XFER_UDMA_4, 0x12446231 }, { XFER_UDMA_3, 0x126c6231 }, @@ -223,7 +221,7 @@ struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { }; /* 2x 33MHz timings */ -struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { +static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { { XFER_UDMA_5, 0x1488e673 }, { XFER_UDMA_4, 0x1488e673 }, { XFER_UDMA_3, 0x1498e673 }, @@ -243,7 +241,7 @@ struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { { 0, 0x0d02bf5f } }; -struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { +static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, { XFER_UDMA_3, 0x128c8242 }, @@ -263,7 +261,7 @@ struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { { 0, 0x0ac1f48a } }; -struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { +static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { { XFER_UDMA_6, 0x1c81dc62 }, { XFER_UDMA_5, 0x1c6ddc62 }, { XFER_UDMA_4, 0x1c8ddc62 }, @@ -284,7 +282,7 @@ struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { { 0, 0x0d029d5e } }; -struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { +static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, { XFER_UDMA_3, 0x128c8242 }, @@ -304,7 +302,7 @@ struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { { 0, 0x0a81f443 } }; -struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { +static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { { XFER_UDMA_6, 0x1c869c62 }, { XFER_UDMA_5, 0x1cae9c62 }, { XFER_UDMA_4, 0x1c8a9c62 }, @@ -325,7 +323,7 @@ struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { { 0, 0x0d029d26 } }; -struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { +static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { { XFER_UDMA_6, 0x12808242 }, { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, @@ -347,7 +345,7 @@ struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { }; #if 0 -struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { +static struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { { XFER_UDMA_6, }, { XFER_UDMA_5, }, { XFER_UDMA_4, }, @@ -367,7 +365,7 @@ struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { }; #endif #if 0 -struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { +static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { { XFER_UDMA_6, 0x12406231 }, /* checkme */ { XFER_UDMA_5, 0x12446231 }, 0x14846231 diff --git a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c index b65ce0877..86f763dd6 100644 --- a/drivers/ide/pci/it8172.c +++ b/drivers/ide/pci/it8172.c @@ -201,36 +201,16 @@ static int it8172_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = it8172_config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!it8172_config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!it8172_config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (it8172_config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: it8172_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -302,7 +282,7 @@ static struct pci_device_id it8172_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, it8172_pci_tbl); static struct pci_driver driver = { - .name = "IT8172IDE", + .name = "IT8172_IDE", .id_table = it8172_pci_tbl, .probe = it8172_init_one, }; diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index a5b6e7e5c..bae33e385 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -4,6 +4,7 @@ * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 1998 Eddie C. Dost * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 2004 Grant Grundler * * Inspired by an earlier effort from David S. Miller */ @@ -25,6 +26,81 @@ #include +#ifdef CONFIG_SUPERIO +/* SUPERIO 87560 is a PoS chip that NatSem denies exists. + * Unfortunately, it's built-in on all Astro-based PA-RISC workstations + * which use the integrated NS87514 cell for CD-ROM support. + * i.e we have to support for CD-ROM installs. + * See drivers/parisc/superio.c for more gory details. + */ +#include + +static unsigned long superio_ide_status[2]; +static unsigned long superio_ide_select[2]; +static unsigned long superio_ide_dma_status[2]; + +#define SUPERIO_IDE_MAX_RETRIES 25 + +/* Because of a defect in Super I/O, all reads of the PCI DMA status + * registers, IDE status register and the IDE select register need to be + * retried + */ +static u8 superio_ide_inb (unsigned long port) +{ + if (port == superio_ide_status[0] || + port == superio_ide_status[1] || + port == superio_ide_select[0] || + port == superio_ide_select[1] || + port == superio_ide_dma_status[0] || + port == superio_ide_dma_status[1]) { + u8 tmp; + int retries = SUPERIO_IDE_MAX_RETRIES; + + /* printk(" [ reading port 0x%x with retry ] ", port); */ + + do { + tmp = inb(port); + if (tmp == 0) + udelay(50); + } while (tmp == 0 && retries-- > 0); + + return tmp; + } + + return inb(port); +} + +static void __devinit superio_ide_init_iops (struct hwif_s *hwif) +{ + u32 base, dmabase; + u8 tmp; + struct pci_dev *pdev = hwif->pci_dev; + u8 port = hwif->channel; + + base = pci_resource_start(pdev, port * 2) & ~3; + dmabase = pci_resource_start(pdev, 4) & ~3; + + superio_ide_status[port] = base + IDE_STATUS_OFFSET; + superio_ide_select[port] = base + IDE_SELECT_OFFSET; + superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); + + /* Clear error/interrupt, enable dma */ + tmp = superio_ide_inb(superio_ide_dma_status[port]); + outb(tmp | 0x66, superio_ide_dma_status[port]); + + /* We need to override inb to workaround a SuperIO errata */ + hwif->INB = superio_ide_inb; +} + +static void __devinit init_iops_ns87415(ide_hwif_t *hwif) +{ + if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) { + /* Built-in - assume it's under superio. */ + superio_ide_init_iops(hwif); + } +} +#endif + static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; /* @@ -101,22 +177,11 @@ static int ns87415_ide_dma_end (ide_drive_t *drive) return (dma_stat & 7) != 4; } -static int ns87415_ide_dma_read (ide_drive_t *drive) -{ - /* select DMA xfer */ - ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_read(drive))) - return 0; - /* DMA failed: select PIO xfer */ - ns87415_prepare_drive(drive, 0); - return 1; -} - -static int ns87415_ide_dma_write (ide_drive_t *drive) +static int ns87415_ide_dma_setup(ide_drive_t *drive) { /* select DMA xfer */ ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_write(drive))) + if (!ide_dma_setup(drive)) return 0; /* DMA failed: select PIO xfer */ ns87415_prepare_drive(drive, 0); @@ -143,10 +208,6 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) hwif->autodma = 0; hwif->selectproc = &ns87415_selectproc; - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - /* FIXME: use pci_set_master() to ensure good latency timer value */ - /* * We cannot probe for IRQ: both ports share common IRQ on INTA. * Also, leave IRQ masked during drive probing, to prevent infinite @@ -204,8 +265,7 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) return; hwif->OUTB(0x60, hwif->dma_status); - hwif->ide_dma_read = &ns87415_ide_dma_read; - hwif->ide_dma_write = &ns87415_ide_dma_write; + hwif->dma_setup = &ns87415_ide_dma_setup; hwif->ide_dma_check = &ns87415_ide_dma_check; hwif->ide_dma_end = &ns87415_ide_dma_end; @@ -217,6 +277,9 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) static ide_pci_device_t ns87415_chipset __devinitdata = { .name = "NS87415", +#ifdef CONFIG_SUPERIO + .init_iops = init_iops_ns87415, +#endif .init_hwif = init_hwif_ns87415, .channels = 2, .autodma = AUTODMA, @@ -236,7 +299,7 @@ static struct pci_device_id ns87415_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); static struct pci_driver driver = { - .name = "NS87415IDE", + .name = "NS87415_IDE", .id_table = ns87415_pci_tbl, .probe = ns87415_init_one, }; diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 3ca7db7d5..ab76641ae 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -367,7 +367,7 @@ static struct pci_device_id opti621_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, opti621_pci_tbl); static struct pci_driver driver = { - .name = "Opti621 IDE", + .name = "Opti621_IDE", .id_table = opti621_pci_tbl, .probe = opti621_init_one, }; diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index f493b29ce..5da146012 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -41,61 +41,6 @@ #define PDC202_DEBUG_CABLE 0 -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdcnew_proc = 0; -#define PDC202_MAX_DEVS 5 -static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; -static int n_pdc202_devs; - -static char * pdcnew_info(char *buf, struct pci_dev *dev) -{ - char *p = buf; - - p += sprintf(p, "\n "); - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20277: - p += sprintf(p, "SBFastTrak 133 Lite"); break; - case PCI_DEVICE_ID_PROMISE_20276: - p += sprintf(p, "MBFastTrak 133 Lite"); break; - case PCI_DEVICE_ID_PROMISE_20275: - p += sprintf(p, "MBUltra133"); break; - case PCI_DEVICE_ID_PROMISE_20271: - p += sprintf(p, "FastTrak TX2000"); break; - case PCI_DEVICE_ID_PROMISE_20270: - p += sprintf(p, "FastTrak LP/TX2/TX4"); break; - case PCI_DEVICE_ID_PROMISE_20269: - p += sprintf(p, "Ultra133 TX2"); break; - case PCI_DEVICE_ID_PROMISE_20268: - p += sprintf(p, "Ultra100 TX2"); break; - default: - p += sprintf(p, "Ultra series"); break; - break; - } - p += sprintf(p, " Chipset.\n"); - return (char *)p; -} - -static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i, len; - - for (i = 0; i < n_pdc202_devs; i++) { - struct pci_dev *dev = pdc202_devs[i]; - p = pdcnew_info(buffer, dev); - } - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ - - static u8 pdcnew_ratemask (ide_drive_t *drive) { u8 mode; @@ -244,37 +189,16 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - goto no_dma_set; - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -310,68 +234,12 @@ static void pdcnew_new_reset (ide_drive_t *drive) HWIF(drive)->channel ? "Secondary" : "Primary"); } -static void pdcnew_reset_host (ide_hwif_t *hwif) -{ -// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); - unsigned long high_16 = hwif->dma_master; - u8 udma_speed_flag = hwif->INB(high_16|0x001f); - - hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); - mdelay(100); - hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f)); - mdelay(2000); /* 2 seconds ?! */ - - printk(KERN_WARNING "PDC202XX: %s channel reset.\n", - hwif->channel ? "Secondary" : "Primary"); -} - -void pdcnew_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_hwif_t *mate = hwif->mate; - - pdcnew_reset_host(hwif); - pdcnew_reset_host(mate); -#if 0 - /* - * FIXME: Have to kick all the drives again :-/ - * What a pain in the ACE! - */ - if (hwif->present) { - u16 hunit = 0; - for (hunit = 0; hunit < MAX_DRIVES; ++hunit) { - ide_drive_t *hdrive = &hwif->drives[hunit]; - if (hdrive->present) { - if (hwif->ide_dma_check) - hwif->ide_dma_check(hdrive); - else - hwif->tuneproc(hdrive, 5); - } - } - } - if (mate->present) { - u16 munit = 0; - for (munit = 0; munit < MAX_DRIVES; ++munit) { - ide_drive_t *mdrive = &mate->drives[munit]; - if (mdrive->present) { - if (mate->ide_dma_check) - mate->ide_dma_check(mdrive); - else - mate->tuneproc(mdrive, 5); - } - } - } -#else - hwif->tuneproc(drive, 5); -#endif -} - #ifdef CONFIG_PPC_PMAC static void __devinit apple_kiwi_init(struct pci_dev *pdev) { struct device_node *np = pci_device_to_OF_node(pdev); unsigned int class_rev = 0; - unsigned long mmio; + void __iomem *mmio; u8 conf; if (np == NULL || !device_is_compatible(np, "kiwi-root")) @@ -385,7 +253,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) pci_read_config_byte(pdev, 0x40, &conf); pci_write_config_byte(pdev, 0x40, conf | 0x01); } - mmio = (unsigned long)ioremap(pci_resource_start(pdev, 5), + mmio = ioremap(pci_resource_start(pdev, 5), pci_resource_len(pdev, 5)); /* Setup some PLL stuffs */ @@ -400,7 +268,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) break; } - iounmap((void *)mmio); + iounmap(mmio); } #endif /* CONFIG_PPC_PMAC */ @@ -417,15 +285,6 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha apple_kiwi_init(dev); #endif -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) - pdc202_devs[n_pdc202_devs++] = dev; - - if (!pdcnew_proc) { - pdcnew_proc = 1; - ide_pci_create_host_proc("pdcnew", pdcnew_get_info); - } -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - return dev->irq; } @@ -531,7 +390,7 @@ static struct pci_device_id pdc202new_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl); static struct pci_driver driver = { - .name = "Promise IDE", + .name = "Promise_IDE", .id_table = pdc202new_pci_tbl, .probe = pdc202new_init_one, }; diff --git a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h index 0abec0ed7..7cfad9552 100644 --- a/drivers/ide/pci/pdc202xx_new.h +++ b/drivers/ide/pci/pdc202xx_new.h @@ -43,8 +43,6 @@ const static char *pdc_quirk_drives[] = { set_2regs(0x13,(c)); \ } while(0) -#define DISPLAY_PDC202XX_TIMINGS - static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d); diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 3b4379c63..fe3ac7553 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -50,68 +50,14 @@ #define PDC202_DEBUG_CABLE 0 -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdc202xx_proc = 0; -#define PDC202_MAX_DEVS 5 -static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; -static int n_pdc202_devs; - -static char * pdc202xx_info (char *buf, struct pci_dev *dev) -{ - char *p = buf; - +#if 0 unsigned long bibma = pci_resource_start(dev, 4); - u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; - u16 reg50h = 0, pmask = (1<<10), smask = (1<<11); u8 hi = 0, lo = 0; - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - u8 c0 = inb_p((u16)bibma + 0x02); - u8 c1 = inb_p((u16)bibma + 0x0a); - - u8 sc11 = inb_p((u16)bibma + 0x11); - u8 sc1a = inb_p((u16)bibma + 0x1a); - u8 sc1b = inb_p((u16)bibma + 0x1b); u8 sc1c = inb_p((u16)bibma + 0x1c); - u8 sc1d = inb_p((u16)bibma + 0x1d); u8 sc1e = inb_p((u16)bibma + 0x1e); u8 sc1f = inb_p((u16)bibma + 0x1f); - pci_read_config_word(dev, 0x50, ®50h); - pci_read_config_dword(dev, 0x60, ®60h); - pci_read_config_dword(dev, 0x64, ®64h); - pci_read_config_dword(dev, 0x68, ®68h); - pci_read_config_dword(dev, 0x6c, ®6ch); - - p += sprintf(p, "\n "); - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20267: - p += sprintf(p, "Ultra100"); break; - case PCI_DEVICE_ID_PROMISE_20265: - p += sprintf(p, "Ultra100 on M/B"); break; - case PCI_DEVICE_ID_PROMISE_20263: - p += sprintf(p, "FastTrak 66"); break; - case PCI_DEVICE_ID_PROMISE_20262: - p += sprintf(p, "Ultra66"); break; - case PCI_DEVICE_ID_PROMISE_20246: - p += sprintf(p, "Ultra33"); - reg50h |= 0x0c00; - break; - default: - p += sprintf(p, "Ultra Series"); break; - } - p += sprintf(p, " Chipset.\n"); - - p += sprintf(p, "------------------------------- General Status " - "---------------------------------\n"); - p += sprintf(p, "Burst Mode : %sabled\n", - (sc1f & 0x01) ? "en" : "dis"); p += sprintf(p, "Host Mode : %s\n", (sc1f & 0x08) ? "Tri-Stated" : "Normal"); p += sprintf(p, "Bus Clocking : %s\n", @@ -126,70 +72,7 @@ static char * pdc202xx_info (char *buf, struct pci_dev *dev) SPLIT_BYTE(sc1e, hi, lo); p += sprintf(p, "Status Polling Period : %d\n", hi); p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %s %s\n", - (c0&0x80)?"disabled":"enabled ", - (c1&0x80)?"disabled":"enabled "); - p += sprintf(p, "66 Clocking %s %s\n", - (sc11&0x02)?"enabled ":"disabled", - (sc11&0x08)?"enabled ":"disabled"); - p += sprintf(p, " Mode %s Mode %s\n", - (sc1a & 0x01) ? "MASTER" : "PCI ", - (sc1b & 0x01) ? "MASTER" : "PCI "); - p += sprintf(p, " %s %s\n", - (sc1d & 0x08) ? "Error " : - ((sc1d & 0x05) == 0x05) ? "Not My INTR " : - (sc1d & 0x04) ? "Interrupting" : - (sc1d & 0x02) ? "FIFO Full " : - (sc1d & 0x01) ? "FIFO Empty " : "????????????", - (sc1d & 0x80) ? "Error " : - ((sc1d & 0x50) == 0x50) ? "Not My INTR " : - (sc1d & 0x40) ? "Interrupting" : - (sc1d & 0x20) ? "FIFO Full " : - (sc1d & 0x10) ? "FIFO Empty " : "????????????"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20)?"yes":"no ", (c0&0x40)?"yes":"no ", - (c1&0x20)?"yes":"no ", (c1&0x40)?"yes":"no "); - p += sprintf(p, "DMA Mode: %s %s " - " %s %s\n", - pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)), - pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)), - pdc202xx_ultra_verbose(reg68h, (reg50h & smask)), - pdc202xx_ultra_verbose(reg6ch, (reg50h & smask))); - p += sprintf(p, "PIO Mode: %s %s " - " %s %s\n", - pdc202xx_pio_verbose(reg60h), - pdc202xx_pio_verbose(reg64h), - pdc202xx_pio_verbose(reg68h), - pdc202xx_pio_verbose(reg6ch)); -#if 0 - p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n"); #endif - return (char *)p; -} - -static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i, len; - - for (i = 0; i < n_pdc202_devs; i++) { - struct pci_dev *dev = pdc202_devs[i]; - p = pdc202xx_info(buffer, dev); - } - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ - static u8 pdc202xx_ratemask (ide_drive_t *drive) { @@ -314,17 +197,6 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); } -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - - decode_registers(REG_A, AP); - decode_registers(REG_B, BP); - decode_registers(REG_C, CP); - decode_registers(REG_D, DP); -#endif /* PDC202XX_DECODE_REGISTER_INFO */ #if PDC202XX_DEBUG_DRIVE_INFO printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), @@ -358,7 +230,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) { u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); pci_read_config_word(hwif->pci_dev, 0x50, &CIS); - return ((u8)(CIS & mask)); + return (CIS & mask) ? 1 : 0; } /* @@ -462,37 +334,16 @@ static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - goto no_dma_set; - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -505,7 +356,7 @@ static int pdc202xx_quirkproc (ide_drive_t *drive) return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); } -static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive) +static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) { if (drive->current_speed > XFER_UDMA_2) pdc_old_enable_66MHz_clock(drive->hwif); @@ -526,7 +377,7 @@ static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive) word_count | 0x06000000; hwif->OUTL(word_count, atapi_reg); } - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) @@ -557,11 +408,13 @@ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) u8 sc1d = hwif->INB((high_16 + 0x001d)); if (hwif->channel) { + /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ if ((sc1d & 0x50) == 0x50) goto somebody_else; else if ((sc1d & 0x40) == 0x40) return (dma_stat & 4) == 4; } else { + /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */ if ((sc1d & 0x05) == 0x05) goto somebody_else; else if ((sc1d & 0x04) == 0x04) @@ -604,7 +457,7 @@ static void pdc202xx_reset_host (ide_hwif_t *hwif) hwif->channel ? "Secondary" : "Primary"); } -void pdc202xx_reset (ide_drive_t *drive) +static void pdc202xx_reset (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *mate = hwif->mate; @@ -679,15 +532,6 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, const c name, dev->resource[PCI_ROM_RESOURCE].start); } -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) - pdc202_devs[n_pdc202_devs++] = dev; - - if (!pdc202xx_proc) { - pdc202xx_proc = 1; - ide_pci_create_host_proc("pdc202xx", pdc202xx_get_info); - } -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - /* * software reset - this is required because the bios * will set UDMA timing on if the hdd supports it. The @@ -720,7 +564,8 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) struct pci_dev *dev = hwif->pci_dev; /* PDC20265 has problems with large LBA48 requests */ - if (dev->device == PCI_DEVICE_ID_PROMISE_20265) + if ((dev->device == PCI_DEVICE_ID_PROMISE_20267) || + (dev->device == PCI_DEVICE_ID_PROMISE_20265)) hwif->rqsize = 256; hwif->autodma = 0; @@ -747,7 +592,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { if (!(hwif->udma_four)) hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1; - hwif->ide_dma_begin = &pdc202xx_old_ide_dma_begin; + hwif->dma_start = &pdc202xx_old_ide_dma_start; hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; } hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq; @@ -905,7 +750,7 @@ static struct pci_device_id pdc202xx_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl); static struct pci_driver driver = { - .name = "Promise Old IDE", + .name = "Promise_Old_IDE", .id_table = pdc202xx_pci_tbl, .probe = pdc202xx_init_one, }; diff --git a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h index 95ea2c8aa..84aab2ae9 100644 --- a/drivers/ide/pci/pdc202xx_old.h +++ b/drivers/ide/pci/pdc202xx_old.h @@ -10,7 +10,6 @@ #endif #define PDC202XX_DEBUG_DRIVE_INFO 0 -#define PDC202XX_DECODE_REGISTER_INFO 0 static const char *pdc_quirk_drives[] = { "QUANTUM FIREBALLlct08 08", @@ -24,41 +23,6 @@ static const char *pdc_quirk_drives[] = { NULL }; -static inline u8 *pdc202xx_pio_verbose (u32 drive_pci) -{ - if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET"); - if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4"); - if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3"); - if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2"); - if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1"); - if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0"); - return("PIO ?"); -} - -static inline u8 *pdc202xx_dma_verbose (u32 drive_pci) -{ - if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2"); - if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1"); - if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0"); - if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2"); - if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1"); - if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0"); - return("PIO---"); -} - -static inline u8 *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable) -{ - if ((drive_pci & 0x000ff000) == 0x000ff000) - return("NOTSET"); - if ((drive_pci & 0x00012000) == 0x00012000) - return((slow_cable) ? "UDMA 2" : "UDMA 4"); - if ((drive_pci & 0x00024000) == 0x00024000) - return((slow_cable) ? "UDMA 1" : "UDMA 3"); - if ((drive_pci & 0x00036000) == 0x00036000) - return("UDMA 0"); - return(pdc202xx_dma_verbose(drive_pci)); -} - /* A Register */ #define SYNC_ERRDY_EN 0xC0 @@ -99,78 +63,6 @@ static inline u8 *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable) #define MC1 0x02 /* DMA"C" timing */ #define MC0 0x01 /* DMA"C" timing */ -#if PDC202XX_DECODE_REGISTER_INFO - -#define REG_A 0x01 -#define REG_B 0x02 -#define REG_C 0x04 -#define REG_D 0x08 - -static void decode_registers (u8 registers, u8 value) -{ - u8 bit = 0, bit1 = 0, bit2 = 0; - - switch(registers) { - case REG_A: - bit2 = 0; - printk("A Register "); - if (value & 0x80) printk("SYNC_IN "); - if (value & 0x40) printk("ERRDY_EN "); - if (value & 0x20) printk("IORDY_EN "); - if (value & 0x10) printk("PREFETCH_EN "); - if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; } - printk("PIO(A) = %d ", bit2); - break; - case REG_B: - bit1 = 0;bit2 = 0; - printk("B Register "); - if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; } - if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; } - if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; } - printk("DMA(B) = %d ", bit1 >> 5); - if (value & 0x10) printk("PIO_FORCED/PB4 "); - if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; } - printk("PIO(B) = %d ", bit2); - break; - case REG_C: - bit2 = 0; - printk("C Register "); - if (value & 0x80) printk("DMARQp "); - if (value & 0x40) printk("IORDYp "); - if (value & 0x20) printk("DMAR_EN "); - if (value & 0x10) printk("DMAW_EN "); - - if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; } - if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; } - if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; } - if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; } - printk("DMA(C) = %d ", bit2); - break; - case REG_D: - printk("D Register "); - break; - default: - return; - } - printk("\n %s ", (registers & REG_D) ? "DP" : - (registers & REG_C) ? "CP" : - (registers & REG_B) ? "BP" : - (registers & REG_A) ? "AP" : "ERROR"); - for (bit=128;bit>0;bit/=2) - printk("%s", (value & bit) ? "1" : "0"); - printk("\n"); -} - -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - -#define DISPLAY_PDC202XX_TIMINGS - static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d); static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc202xx(struct pci_dev *, ide_pci_device_t *); diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 26719f2c7..52939725b 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -106,165 +106,6 @@ #include "piix.h" static int no_piix_dma; -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 piix_proc = 0; -#define PIIX_MAX_DEVS 5 -static struct pci_dev *piix_devs[PIIX_MAX_DEVS]; -static int n_piix_devs; - -/** - * piix_get_info - fill in /proc for PIIX ide - * @buffer: buffer to fill - * @addr: address of user start in buffer - * @offset: offset into 'file' - * @count: buffer count - * - * Walks the PIIX devices and outputs summary data on the tuning and - * anything else that will help with debugging - */ - -static int piix_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i; - - for (i = 0; i < n_piix_devs; i++) { - struct pci_dev *dev = piix_devs[i]; - unsigned long bibma = pci_resource_start(dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0, reg54 = 0, reg55 = 0; - u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0; - - p += sprintf(p, "\nController: %d\n", i); - p += sprintf(p, "\n Intel "); - switch(dev->device) { - case PCI_DEVICE_ID_INTEL_82801EB_1: - p += sprintf(p, "PIIX4 SATA 150 "); - break; - case PCI_DEVICE_ID_INTEL_82801BA_8: - case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: - case PCI_DEVICE_ID_INTEL_82801DB_10: - case PCI_DEVICE_ID_INTEL_82801DB_11: - case PCI_DEVICE_ID_INTEL_82801EB_11: - case PCI_DEVICE_ID_INTEL_82801E_11: - case PCI_DEVICE_ID_INTEL_ESB_2: - case PCI_DEVICE_ID_INTEL_ICH6_19: - p += sprintf(p, "PIIX4 Ultra 100 "); - break; - case PCI_DEVICE_ID_INTEL_82372FB_1: - case PCI_DEVICE_ID_INTEL_82801AA_1: - p += sprintf(p, "PIIX4 Ultra 66 "); - break; - case PCI_DEVICE_ID_INTEL_82451NX: - case PCI_DEVICE_ID_INTEL_82801AB_1: - case PCI_DEVICE_ID_INTEL_82443MX_1: - case PCI_DEVICE_ID_INTEL_82371AB: - p += sprintf(p, "PIIX4 Ultra 33 "); - break; - case PCI_DEVICE_ID_INTEL_82371SB_1: - p += sprintf(p, "PIIX3 "); - break; - case PCI_DEVICE_ID_INTEL_82371MX: - p += sprintf(p, "MPIIX "); - break; - case PCI_DEVICE_ID_INTEL_82371FB_1: - case PCI_DEVICE_ID_INTEL_82371FB_0: - default: - p += sprintf(p, "PIIX "); - break; - } - p += sprintf(p, "Chipset.\n"); - - if (dev->device == PCI_DEVICE_ID_INTEL_82371MX) - continue; - - pci_read_config_word(dev, 0x40, ®40); - pci_read_config_word(dev, 0x42, ®42); - pci_read_config_byte(dev, 0x44, ®44); - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x4a, ®4a); - pci_read_config_byte(dev, 0x4b, ®4b); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb(bibma + 0x02); - c1 = inb(bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - ((reg54&0x11) && - (reg55&0x10) && (reg4a&0x01)) ? "5" : - ((reg54&0x11) && (reg4a&0x02)) ? "4" : - ((reg54&0x11) && (reg4a&0x01)) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x22) && - (reg55&0x20) && (reg4a&0x10)) ? "5" : - ((reg54&0x22) && (reg4a&0x20)) ? "4" : - ((reg54&0x22) && (reg4a&0x10)) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg54&0x44) && - (reg55&0x40) && (reg4b&0x03)) ? "5" : - ((reg54&0x44) && (reg4b&0x02)) ? "4" : - ((reg54&0x44) && (reg4b&0x01)) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg54&0x88) && - (reg55&0x80) && (reg4b&0x30)) ? "5" : - ((reg54&0x88) && (reg4b&0x20)) ? "4" : - ((reg54&0x88) && (reg4b&0x10)) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - /* - * FIXME.... Add configuration junk data....blah blah...... - */ - } - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ /** * piix_ratemask - compute rate mask for PIIX IDE @@ -561,36 +402,17 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if ((id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - if ((id->field_valid & 2) && - (!piix_config_drive_for_dma(drive))) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!piix_config_drive_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!piix_config_drive_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (piix_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: + /* Find best PIO mode. */ hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } @@ -632,14 +454,6 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char break; } -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) - piix_devs[n_piix_devs++] = dev; - - if (!piix_proc) { - piix_proc = 1; - ide_pci_create_host_proc("piix", piix_get_info); - } -#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ return 0; } @@ -803,7 +617,7 @@ static struct pci_device_id piix_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, piix_pci_tbl); static struct pci_driver driver = { - .name = "PIIX IDE", + .name = "PIIX_IDE", .id_table = piix_pci_tbl, .probe = piix_init_one, }; diff --git a/drivers/ide/pci/piix.h b/drivers/ide/pci/piix.h index f71db14ae..5a445d795 100644 --- a/drivers/ide/pci/piix.h +++ b/drivers/ide/pci/piix.h @@ -5,10 +5,6 @@ #include #include -#define PIIX_DEBUG_DRIVE_INFO 0 - -#define DISPLAY_PIIX_TIMINGS - static void init_setup_piix(struct pci_dev *, ide_pci_device_t *); static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *); static void init_hwif_piix(ide_hwif_t *); diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index 3405e6a1b..ca42bdc6f 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -33,7 +33,7 @@ #include -static void __init init_hwif_rz1000 (ide_hwif_t *hwif) +static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif) { u16 reg; struct pci_dev *dev = hwif->pci_dev; @@ -74,7 +74,7 @@ static struct pci_device_id rz1000_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl); static struct pci_driver driver = { - .name = "RZ1000 IDE", + .name = "RZ1000_IDE", .id_table = rz1000_pci_tbl, .probe = rz1000_init_one, }; diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 902408d18..61a3a2f1d 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -67,61 +67,12 @@ static unsigned short sc1200_get_pci_clock (void) return pci_clock; } -#define DISPLAY_SC1200_TIMINGS - -#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int sc1200_get_info(char *, char **, off_t, int); -extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static u8 sc1200_proc = 0; - -static struct pci_dev *bmide_dev; - -static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - unsigned long bibma = pci_resource_start(bmide_dev, 4); - int len; - u8 c0 = 0, c1 = 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - - c0 = inb_p(bibma + 0x02); - c1 = inb_p(bibma + 0x0a); - - p += sprintf(p, "\n National SCx200 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ - extern char *ide_xfer_verbose (byte xfer_rate); /* * Set a new transfer mode at the drive */ -int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode) +static int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode) { printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); return ide_config_drive_speed(drive, mode); @@ -312,7 +263,7 @@ static int sc1200_config_dma (ide_drive_t *drive) * * returns 1 on error, 0 otherwise */ -int sc1200_ide_dma_end (ide_drive_t *drive) +static int sc1200_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; @@ -504,21 +455,6 @@ printk("%s: SC1200: resume\n", hwif->name); return 0; } -/* - * Initialize the sc1200 bridge for reliable IDE DMA operation. - */ -static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) - if (!bmide_dev) { - sc1200_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("sc1200", sc1200_get_info); - } -#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - /* * This gets invoked by the IDE driver once for each channel, * and performs channel-specific pre-initialization before drive probing. @@ -545,7 +481,6 @@ static void __init init_hwif_sc1200 (ide_hwif_t *hwif) static ide_pci_device_t sc1200_chipset __devinitdata = { .name = "SC1200", - .init_chipset = init_chipset_sc1200, .init_hwif = init_hwif_sc1200, .channels = 2, .autodma = AUTODMA, @@ -565,7 +500,7 @@ static struct pci_device_id sc1200_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); static struct pci_driver driver = { - .name = "SC1200 IDE", + .name = "SC1200_IDE", .id_table = sc1200_pci_tbl, .probe = sc1200_init_one, .suspend = sc1200_suspend, diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index 27d907c9b..dabeb96f7 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -44,164 +44,6 @@ static u8 svwks_revision = 0; static struct pci_dev *isa_dev; -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 svwks_proc = 0; -#define SVWKS_MAX_DEVS 2 -static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS]; -static int n_svwks_devs; - -static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int i, len; - - p += sprintf(p, "\n " - "ServerWorks OSB4/CSB5/CSB6\n"); - - for (i = 0; i < n_svwks_devs; i++) { - struct pci_dev *dev = svwks_devs[i]; - unsigned long bibma = pci_resource_start(dev, 4); - u32 reg40, reg44; - u16 reg48, reg56; - u8 reg54, c0=0, c1=0; - - pci_read_config_dword(dev, 0x40, ®40); - pci_read_config_dword(dev, 0x44, ®44); - pci_read_config_word(dev, 0x48, ®48); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_word(dev, 0x56, ®56); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p(bibma + 0x02); - c1 = inb_p(bibma + 0x0a); - - p += sprintf(p, "\n ServerWorks "); - switch(dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: - case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: - p += sprintf(p, "CSB6 "); - break; - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - p += sprintf(p, "CSB5 "); - break; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - p += sprintf(p, "OSB4 "); - break; - default: - p += sprintf(p, "%04x ", dev->device); - break; - } - p += sprintf(p, "Chipset (rev %02x)\n", svwks_revision); - - p += sprintf(p, "------------------------------- " - "General Status " - "---------------------------------\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled" - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s" - " %s %s\n", - (reg54 & 0x01) ? "yes" : "no ", - (reg54 & 0x02) ? "yes" : "no ", - (reg54 & 0x04) ? "yes" : "no ", - (reg54 & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s" - " %s %s\n", - ((reg56&0x0005)==0x0005)?"5": - ((reg56&0x0004)==0x0004)?"4": - ((reg56&0x0003)==0x0003)?"3": - ((reg56&0x0002)==0x0002)?"2": - ((reg56&0x0001)==0x0001)?"1": - ((reg56&0x000F))?"?":"0", - ((reg56&0x0050)==0x0050)?"5": - ((reg56&0x0040)==0x0040)?"4": - ((reg56&0x0030)==0x0030)?"3": - ((reg56&0x0020)==0x0020)?"2": - ((reg56&0x0010)==0x0010)?"1": - ((reg56&0x00F0))?"?":"0", - ((reg56&0x0500)==0x0500)?"5": - ((reg56&0x0400)==0x0400)?"4": - ((reg56&0x0300)==0x0300)?"3": - ((reg56&0x0200)==0x0200)?"2": - ((reg56&0x0100)==0x0100)?"1": - ((reg56&0x0F00))?"?":"0", - ((reg56&0x5000)==0x5000)?"5": - ((reg56&0x4000)==0x4000)?"4": - ((reg56&0x3000)==0x3000)?"3": - ((reg56&0x2000)==0x2000)?"2": - ((reg56&0x1000)==0x1000)?"1": - ((reg56&0xF000))?"?":"0"); - p += sprintf(p, "DMA enabled: %s %s" - " %s %s\n", - ((reg44&0x00002000)==0x00002000)?"2": - ((reg44&0x00002100)==0x00002100)?"1": - ((reg44&0x00007700)==0x00007700)?"0": - ((reg44&0x0000FF00)==0x0000FF00)?"X":"?", - ((reg44&0x00000020)==0x00000020)?"2": - ((reg44&0x00000021)==0x00000021)?"1": - ((reg44&0x00000077)==0x00000077)?"0": - ((reg44&0x000000FF)==0x000000FF)?"X":"?", - ((reg44&0x20000000)==0x20000000)?"2": - ((reg44&0x21000000)==0x21000000)?"1": - ((reg44&0x77000000)==0x77000000)?"0": - ((reg44&0xFF000000)==0xFF000000)?"X":"?", - ((reg44&0x00200000)==0x00200000)?"2": - ((reg44&0x00210000)==0x00210000)?"1": - ((reg44&0x00770000)==0x00770000)?"0": - ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); - - p += sprintf(p, "PIO enabled: %s %s" - " %s %s\n", - ((reg40&0x00002000)==0x00002000)?"4": - ((reg40&0x00002200)==0x00002200)?"3": - ((reg40&0x00003400)==0x00003400)?"2": - ((reg40&0x00004700)==0x00004700)?"1": - ((reg40&0x00005D00)==0x00005D00)?"0":"?", - ((reg40&0x00000020)==0x00000020)?"4": - ((reg40&0x00000022)==0x00000022)?"3": - ((reg40&0x00000034)==0x00000034)?"2": - ((reg40&0x00000047)==0x00000047)?"1": - ((reg40&0x0000005D)==0x0000005D)?"0":"?", - ((reg40&0x20000000)==0x20000000)?"4": - ((reg40&0x22000000)==0x22000000)?"3": - ((reg40&0x34000000)==0x34000000)?"2": - ((reg40&0x47000000)==0x47000000)?"1": - ((reg40&0x5D000000)==0x5D000000)?"0":"?", - ((reg40&0x00200000)==0x00200000)?"4": - ((reg40&0x00220000)==0x00220000)?"3": - ((reg40&0x00340000)==0x00340000)?"2": - ((reg40&0x00470000)==0x00470000)?"1": - ((reg40&0x005D0000)==0x005D0000)?"0":"?"); - - } - p += sprintf(p, "\n"); - - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ - static int check_in_drive_lists (ide_drive_t *drive, const char **list) { while (*list) @@ -463,38 +305,16 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if ((id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } else - /* UDMA disabled by mask, try other DMA modes */ - goto try_dma_modes; - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto no_dma_set; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: config_chipset_for_pio(drive); // hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); @@ -617,16 +437,6 @@ static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char * pci_write_config_byte(dev, 0x5A, btr); } - -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) - svwks_devs[n_svwks_devs++] = dev; - - if (!svwks_proc) { - svwks_proc = 1; - ide_pci_create_host_proc("svwks", svwks_get_info); - } -#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ - return (dev->irq) ? dev->irq : 0; } @@ -812,7 +622,7 @@ static struct pci_device_id svwks_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); static struct pci_driver driver = { - .name = "Serverworks IDE", + .name = "Serverworks_IDE", .id_table = svwks_pci_tbl, .probe = svwks_init_one, #if 0 /* FIXME: implement */ diff --git a/drivers/ide/pci/serverworks.h b/drivers/ide/pci/serverworks.h index aa8bd8b9d..3711bbd65 100644 --- a/drivers/ide/pci/serverworks.h +++ b/drivers/ide/pci/serverworks.h @@ -13,7 +13,7 @@ /* Seagate Barracuda ATA IV Family drives in UDMA mode 5 * can overrun their FIFOs when used with the CSB5 */ -const char *svwks_bad_ata100[] = { +static const char *svwks_bad_ata100[] = { "ST320011A", "ST340016A", "ST360021A", @@ -21,8 +21,6 @@ const char *svwks_bad_ata100[] = { NULL }; -#define DISPLAY_SVWKS_TIMINGS 1 - static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *); static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *); static unsigned int init_chipset_svwks(struct pci_dev *, const char *); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 0187aafac..e484786be 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -192,16 +192,13 @@ sgiioc4_clearirq(ide_drive_t * drive) return intr_reg & 3; } -static int -sgiioc4_ide_dma_begin(ide_drive_t * drive) +static void sgiioc4_ide_dma_start(ide_drive_t * drive) { ide_hwif_t *hwif = HWIF(drive); unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4); unsigned int temp_reg = reg | IOC4_S_DMA_START; hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4); - - return 0; } static u32 @@ -334,17 +331,6 @@ sgiioc4_ide_dma_host_off(ide_drive_t * drive) return 0; } -static int -sgiioc4_ide_dma_verbose(ide_drive_t * drive) -{ - if (drive->using_dma == 1) - printk(", UDMA(16)"); - else - printk(", PIO"); - - return 1; -} - static int sgiioc4_ide_dma_lostirq(ide_drive_t * drive) { @@ -382,7 +368,7 @@ sgiioc4_INB(unsigned long port) } /* Creates a dma map for the scatter-gather list entries */ -static void __init +static void __devinit ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) { int num_ports = sizeof (ioc4_dma_regs_t); @@ -407,11 +393,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) if (!hwif->dmatable_cpu) goto dma_alloc_failure; - hwif->sg_table = - kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL); - - if (!hwif->sg_table) - goto dma_sgalloc_failure; + hwif->sg_max_nents = IOC4_PRD_ENTRIES; hwif->dma_base2 = (unsigned long) pci_alloc_consistent(hwif->pci_dev, @@ -424,9 +406,6 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) return; dma_base2alloc_failure: - kfree(hwif->sg_table); - -dma_sgalloc_failure: pci_free_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, hwif->dmatable_cpu, hwif->dmatable_dma); @@ -511,10 +490,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) unsigned int count = 0, i = 1; struct scatterlist *sg; - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) - hwif->sg_nents = i = ide_raw_build_sglist(drive, rq); - else - hwif->sg_nents = i = ide_build_sglist(drive, rq); + hwif->sg_nents = i = ide_build_sglist(drive, rq); if (!i) return 0; /* sglist of length Zero */ @@ -570,45 +546,40 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir) use_pio_instead: pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents, hwif->sg_dma_direction); - hwif->sg_dma_active = 0; return 0; /* revert to PIO for this request */ } -static int -sgiioc4_ide_dma_read(ide_drive_t * drive) +static int sgiioc4_ide_dma_setup(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; unsigned int count = 0; + int ddir; - if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) { - /* try PIO instead of DMA */ - return 1; - } - /* Writes FROM the IOC4 TO Main Memory */ - sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive); - - return 0; -} - -static int -sgiioc4_ide_dma_write(ide_drive_t * drive) -{ - struct request *rq = HWGROUP(drive)->rq; - unsigned int count = 0; + if (rq_data_dir(rq)) + ddir = PCI_DMA_TODEVICE; + else + ddir = PCI_DMA_FROMDEVICE; - if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) { + if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) { /* try PIO instead of DMA */ + ide_map_sg(drive, rq); return 1; } - sgiioc4_configure_for_dma(IOC4_DMA_READ, drive); - /* Writes TO the IOC4 FROM Main Memory */ + if (rq_data_dir(rq)) + /* Writes TO the IOC4 FROM Main Memory */ + ddir = IOC4_DMA_READ; + else + /* Writes FROM the IOC4 TO Main Memory */ + ddir = IOC4_DMA_WRITE; + + sgiioc4_configure_for_dma(ddir, drive); return 0; } -static void __init +static void __devinit ide_init_sgiioc4(ide_hwif_t * hwif) { hwif->mmio = 2; @@ -617,7 +588,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ultra_mask = 0x0; /* Disable Ultra DMA */ hwif->mwdma_mask = 0x2; /* Multimode-2 DMA */ hwif->swdma_mask = 0x2; - hwif->identify = NULL; hwif->tuneproc = NULL; /* Sets timing for PIO mode */ hwif->speedproc = NULL; /* Sets timing for DMA &/or PIO modes */ hwif->selectproc = NULL;/* Use the default routine to select drive */ @@ -630,9 +600,8 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->quirkproc = NULL; hwif->busproc = NULL; - hwif->ide_dma_read = &sgiioc4_ide_dma_read; - hwif->ide_dma_write = &sgiioc4_ide_dma_write; - hwif->ide_dma_begin = &sgiioc4_ide_dma_begin; + hwif->dma_setup = &sgiioc4_ide_dma_setup; + hwif->dma_start = &sgiioc4_ide_dma_start; hwif->ide_dma_end = &sgiioc4_ide_dma_end; hwif->ide_dma_check = &sgiioc4_ide_dma_check; hwif->ide_dma_on = &sgiioc4_ide_dma_on; @@ -640,13 +609,12 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on; hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off; - hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose; hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; hwif->ide_dma_timeout = &__ide_dma_timeout; hwif->INB = &sgiioc4_INB; } -static int __init +static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) { unsigned long base, ctl, dma_base, irqport; @@ -702,25 +670,17 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) hwif->name, d->name); probe_hwif_init(hwif); + + /* Create /proc/ide entries */ + create_proc_ide_interfaces(); + return 0; } -/* This ensures that we can build this for generic kernels without - * having all the SN2 code sync'd and merged. - */ -typedef enum pciio_endian_e { - PCIDMA_ENDIAN_BIG, - PCIDMA_ENDIAN_LITTLE -} pciio_endian_t; -pciio_endian_t snia_pciio_endian_set(struct pci_dev - *pci_dev, pciio_endian_t device_end, - pciio_endian_t desired_end); - -static unsigned int __init +static unsigned int __devinit pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d) { unsigned int class_rev; - pciio_endian_t endian_status; if (pci_enable_device(dev)) { printk(KERN_ERR @@ -740,17 +700,6 @@ pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d) "46 or higher\n", d->name, dev->slot_name); return -ENODEV; } - - /* Enable Byte Swapping in the PIC... */ - endian_status = snia_pciio_endian_set(dev, PCIDMA_ENDIAN_LITTLE, - PCIDMA_ENDIAN_BIG); - if (endian_status != PCIDMA_ENDIAN_BIG) { - printk(KERN_ERR - "Failed to set endianness for device %s at slot %s\n", - d->name, dev->slot_name); - return -ENODEV; - } - return sgiioc4_ide_setup_pci_device(dev, d); } @@ -781,13 +730,13 @@ static struct pci_device_id sgiioc4_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl); -static struct pci_driver driver = { - .name = "SGI-IOC4 IDE", +static struct pci_driver __devinitdata driver = { + .name = "SGI-IOC4_IDE", .id_table = sgiioc4_pci_tbl, .probe = sgiioc4_init_one, }; -static int +static int __devinit sgiioc4_ide_init(void) { return ide_pci_register_driver(&driver); diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 91b039826..17089f3eb 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -420,37 +420,16 @@ static int siimage_config_drive_for_dma (ide_drive_t *drive) struct hd_driveid *id = drive->id; if ((id->capability & 1) != 0 && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - - if ((id->field_valid & 4) && siimage_ratemask(drive)) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: config_chipset_for_pio(drive, 1); return hwif->ide_dma_off_quietly(drive); } @@ -554,12 +533,6 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) return 0; } -static int siimage_mmio_ide_dma_verbose (ide_drive_t *drive) -{ - int temp = __ide_dma_verbose(drive); - return temp; -} - /** * siimage_busproc - bus isolation ioctl * @drive: drive to isolate/restore @@ -727,8 +700,7 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) unsigned long bar5 = pci_resource_start(dev, 5); unsigned long barsize = pci_resource_len(dev, 5); u8 tmpbyte = 0; - unsigned long addr; - void *ioaddr; + void __iomem *ioaddr; /* * Drop back to PIO if we can't map the mmio. Some @@ -751,22 +723,21 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) } pci_set_master(dev); - pci_set_drvdata(dev, ioaddr); - addr = (unsigned long) ioaddr; + pci_set_drvdata(dev, (void *) ioaddr); if (pdev_is_sata(dev)) { - writel(0, addr + 0x148); - writel(0, addr + 0x1C8); + writel(0, ioaddr + 0x148); + writel(0, ioaddr + 0x1C8); } - writeb(0, addr + 0xB4); - writeb(0, addr + 0xF4); - tmpbyte = readb(addr + 0x4A); + writeb(0, ioaddr + 0xB4); + writeb(0, ioaddr + 0xF4); + tmpbyte = readb(ioaddr + 0x4A); switch(tmpbyte & 0x30) { case 0x00: /* In 100 MHz clocking, try and switch to 133 */ - writeb(tmpbyte|0x10, addr + 0x4A); + writeb(tmpbyte|0x10, ioaddr + 0x4A); break; case 0x10: /* On 133Mhz clocking */ @@ -777,29 +748,29 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) case 0x30: /* Clocking is disabled */ /* 133 clock attempt to force it on */ - writeb(tmpbyte & ~0x20, addr + 0x4A); + writeb(tmpbyte & ~0x20, ioaddr + 0x4A); break; } - writeb( 0x72, addr + 0xA1); - writew( 0x328A, addr + 0xA2); - writel(0x62DD62DD, addr + 0xA4); - writel(0x43924392, addr + 0xA8); - writel(0x40094009, addr + 0xAC); - writeb( 0x72, addr + 0xE1); - writew( 0x328A, addr + 0xE2); - writel(0x62DD62DD, addr + 0xE4); - writel(0x43924392, addr + 0xE8); - writel(0x40094009, addr + 0xEC); + writeb( 0x72, ioaddr + 0xA1); + writew( 0x328A, ioaddr + 0xA2); + writel(0x62DD62DD, ioaddr + 0xA4); + writel(0x43924392, ioaddr + 0xA8); + writel(0x40094009, ioaddr + 0xAC); + writeb( 0x72, ioaddr + 0xE1); + writew( 0x328A, ioaddr + 0xE2); + writel(0x62DD62DD, ioaddr + 0xE4); + writel(0x43924392, ioaddr + 0xE8); + writel(0x40094009, ioaddr + 0xEC); if (pdev_is_sata(dev)) { - writel(0xFFFF0000, addr + 0x108); - writel(0xFFFF0000, addr + 0x188); - writel(0x00680000, addr + 0x148); - writel(0x00680000, addr + 0x1C8); + writel(0xFFFF0000, ioaddr + 0x108); + writel(0xFFFF0000, ioaddr + 0x188); + writel(0x00680000, ioaddr + 0x148); + writel(0x00680000, ioaddr + 0x1C8); } - tmpbyte = readb(addr + 0x4A); + tmpbyte = readb(ioaddr + 0x4A); proc_reports_siimage(dev, (tmpbyte>>4), name); return 1; @@ -900,12 +871,11 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) * the MMIO layout isnt the same as the the standard port * based I/O */ - + memset(&hw, 0, sizeof(hw_regs_t)); - hw.priv = addr; - base = (unsigned long)addr; - if(ch) + base = (unsigned long)addr; + if (ch) base += 0xC0; else base += 0x80; @@ -930,16 +900,16 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) hw.io_ports[IDE_IRQ_OFFSET] = 0; - if (pdev_is_sata(dev)) { - base = (unsigned long) addr; - if(ch) - base += 0x80; - hw.sata_scr[SATA_STATUS_OFFSET] = base + 0x104; - hw.sata_scr[SATA_ERROR_OFFSET] = base + 0x108; - hw.sata_scr[SATA_CONTROL_OFFSET]= base + 0x100; - hw.sata_misc[SATA_MISC_OFFSET] = base + 0x140; - hw.sata_misc[SATA_PHY_OFFSET] = base + 0x144; - hw.sata_misc[SATA_IEN_OFFSET] = base + 0x148; + if (pdev_is_sata(dev)) { + base = (unsigned long)addr; + if (ch) + base += 0x80; + hwif->sata_scr[SATA_STATUS_OFFSET] = base + 0x104; + hwif->sata_scr[SATA_ERROR_OFFSET] = base + 0x108; + hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100; + hwif->sata_misc[SATA_MISC_OFFSET] = base + 0x140; + hwif->sata_misc[SATA_PHY_OFFSET] = base + 0x144; + hwif->sata_misc[SATA_IEN_OFFSET] = base + 0x148; } hw.irq = hwif->pci_dev->irq; @@ -947,11 +917,6 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) memcpy(&hwif->hw, &hw, sizeof(hw)); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); - if (is_sata(hwif)) { - memcpy(hwif->sata_scr, hwif->hw.sata_scr, sizeof(hwif->hw.sata_scr)); - memcpy(hwif->sata_misc, hwif->hw.sata_misc, sizeof(hwif->hw.sata_misc)); - } - hwif->irq = hw.irq; base = (unsigned long) addr; @@ -989,6 +954,22 @@ static int is_dev_seagate_sata(ide_drive_t *drive) return 0; } +/** + * siimage_fixup - post probe fixups + * @hwif: interface to fix up + * + * Called after drive probe we use this to decide whether the + * Seagate fixup must be applied. This used to be in init_iops but + * that can occur before we know what drives are present. + */ + +static void __devinit siimage_fixup(ide_hwif_t *hwif) +{ + /* Try and raise the rqsize */ + if (!is_sata(hwif) || !is_dev_seagate_sata(&hwif->drives[0])) + hwif->rqsize = 128; +} + /** * init_iops_siimage - set up iops * @hwif: interface to set up @@ -1009,9 +990,8 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif) hwif->hwif_data = NULL; - hwif->rqsize = 128; - if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0])) - hwif->rqsize = 15; + /* Pessimal until we finish probing */ + hwif->rqsize = 15; if (pci_get_drvdata(dev) == NULL) return; @@ -1079,7 +1059,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) if (hwif->mmio) { hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq; - hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose; } else { hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq; } @@ -1100,6 +1079,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) .init_chipset = init_chipset_siimage, \ .init_iops = init_iops_siimage, \ .init_hwif = init_hwif_siimage, \ + .fixup = siimage_fixup, \ .channels = 2, \ .autodma = AUTODMA, \ .bootable = ON_BOARD, \ @@ -1137,7 +1117,7 @@ static struct pci_device_id siimage_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, siimage_pci_tbl); static struct pci_driver driver = { - .name = "SiI IDE", + .name = "SiI_IDE", .id_table = siimage_pci_tbl, .probe = siimage_init_one, }; diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index d06b1fd8c..e4dd05847 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -671,36 +671,16 @@ static int sis5513_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = config_chipset_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!config_chipset_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: sis5513_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -788,6 +768,15 @@ static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char if (trueid == 0x5518) { printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n"); chipset_family = ATA_133; + + /* Check for 5513 compability mapping + * We must use this, else the port enabled code will fail, + * as it expects the enablebits at 0x4a. + */ + if ((idemisc & 0x40000000) == 0) { + pci_write_config_dword(dev, 0x54, idemisc | 0x40000000); + printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n"); + } } } @@ -963,12 +952,13 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi static struct pci_device_id sis5513_pci_tbl[] = { { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); static struct pci_driver driver = { - .name = "SIS IDE", + .name = "SIS_IDE", .id_table = sis5513_pci_tbl, .probe = sis5513_init_one, }; diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 38bd8077b..d0cfec055 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -236,15 +236,13 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive) * The generic IDE core will have disabled the BMEN bit before this * function is called. */ -static int sl82c105_ide_dma_begin(ide_drive_t *drive) +static void sl82c105_ide_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; -// DBG(("sl82c105_ide_dma_begin(drive:%s)\n", drive->name)); - sl82c105_reset_host(dev); - return __ide_dma_begin(drive); + ide_dma_start(drive); } static int sl82c105_ide_dma_timeout(ide_drive_t *drive) @@ -469,7 +467,7 @@ static void __init init_hwif_sl82c105(ide_hwif_t *hwif) hwif->ide_dma_on = &sl82c105_ide_dma_on; hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; - hwif->ide_dma_begin = &sl82c105_ide_dma_begin; + hwif->dma_start = &sl82c105_ide_dma_start; hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; if (!noautodma) @@ -503,7 +501,7 @@ static struct pci_device_id sl82c105_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); static struct pci_driver driver = { - .name = "W82C105 IDE", + .name = "W82C105_IDE", .id_table = sl82c105_pci_tbl, .probe = sl82c105_init_one, }; diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 1a0183d1b..55c5c4450 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -21,103 +21,6 @@ #include -#define DISPLAY_SLC90E66_TIMINGS - -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 slc90e66_proc = 0; -static struct pci_dev *bmide_dev; - -static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; - int len; - unsigned long bibma = pci_resource_start(bmide_dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; - u8 c0 = 0, c1 = 0; - u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0; - - pci_read_config_word(bmide_dev, 0x40, ®40); - pci_read_config_word(bmide_dev, 0x42, ®42); - pci_read_config_byte(bmide_dev, 0x44, ®44); - pci_read_config_byte(bmide_dev, 0x47, ®47); - pci_read_config_byte(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x4a, ®4a); - pci_read_config_byte(bmide_dev, 0x4b, ®4b); - - psitre = (reg40 & 0x4000) ? 1 : 0; - ssitre = (reg42 & 0x4000) ? 1 : 0; - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p(bibma + 0x02); - c1 = inb_p(bibma + 0x0a); - - p += sprintf(p, " SLC90E66 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - (reg48&0x01) ? "yes" : "no ", - (reg48&0x02) ? "yes" : "no ", - (reg48&0x04) ? "yes" : "no ", - (reg48&0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s " - " %s %s\n", - ((reg4a&0x04)==0x04) ? "4" : - ((reg4a&0x03)==0x03) ? "3" : - (reg4a&0x02) ? "2" : - (reg4a&0x01) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg4a&0x40)==0x40) ? "4" : - ((reg4a&0x30)==0x30) ? "3" : - (reg4a&0x20) ? "2" : - (reg4a&0x10) ? "1" : - (reg4a&0x00) ? "0" : "X", - ((reg4b&0x04)==0x04) ? "4" : - ((reg4b&0x03)==0x03) ? "3" : - (reg4b&0x02) ? "2" : - (reg4b&0x01) ? "1" : - (reg4b&0x00) ? "0" : "X", - ((reg4b&0x40)==0x40) ? "4" : - ((reg4b&0x30)==0x30) ? "3" : - (reg4b&0x20) ? "2" : - (reg4b&0x10) ? "1" : - (reg4b&0x00) ? "0" : "X"); - - p += sprintf(p, "UDMA\n"); - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - -/* - * FIXME.... Add configuration junk data....blah blah...... - */ - - /* p - buffer must be less than 4k! */ - len = (p - buffer) - offset; - *addr = buffer + offset; - - return len > count ? count : len; -} -#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ - static u8 slc90e66_ratemask (ide_drive_t *drive) { u8 mode = 2; @@ -236,6 +139,7 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); + /* FIXME: (reg4a & a_speed) ? */ if ((reg4a & u_speed) != u_speed) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_read_config_word(dev, 0x4a, ®4a); @@ -274,37 +178,16 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { - /* Consult the list of known "bad" drives */ - if (__ide_dma_bad_drive(drive)) - goto fast_ata_pio; - - if (id->field_valid & 4) { - if (id->dma_ultra & hwif->ultra_mask) { - /* Force if Capable UltraDMA */ - int dma = slc90e66_config_drive_for_dma(drive); - if ((id->field_valid & 2) && !dma) - goto try_dma_modes; - } - } else if (id->field_valid & 2) { -try_dma_modes: - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - /* Force if Capable regular DMA modes */ - if (!slc90e66_config_drive_for_dma(drive)) - goto no_dma_set; - } - } else if (__ide_dma_good_drive(drive) && - (id->eide_dma_time < 150)) { - /* Consult the list of known "good" drives */ - if (!slc90e66_config_drive_for_dma(drive)) - goto no_dma_set; - } else { - goto fast_ata_pio; + + if (ide_use_dma(drive)) { + if (slc90e66_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); } - return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: -no_dma_set: hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } @@ -313,18 +196,6 @@ no_dma_set: } #endif /* CONFIG_BLK_DEV_IDEDMA */ -static unsigned int __init init_chipset_slc90e66 (struct pci_dev *dev, const char *name) -{ -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) - if (!slc90e66_proc) { - slc90e66_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("slc90e66", slc90e66_get_info); - } -#endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */ - return 0; -} - static void __init init_hwif_slc90e66 (ide_hwif_t *hwif) { u8 reg47 = 0; @@ -366,7 +237,6 @@ static void __init init_hwif_slc90e66 (ide_hwif_t *hwif) static ide_pci_device_t slc90e66_chipset __devinitdata = { .name = "SLC90E66", - .init_chipset = init_chipset_slc90e66, .init_hwif = init_hwif_slc90e66, .channels = 2, .autodma = AUTODMA, @@ -387,7 +257,7 @@ static struct pci_device_id slc90e66_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl); static struct pci_driver driver = { - .name = "SLC90e66 IDE", + .name = "SLC90e66_IDE", .id_table = slc90e66_pci_tbl, .probe = slc90e66_init_one, }; diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index 52e088e25..28c19bcce 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -41,57 +41,6 @@ #include #include -static struct pci_dev *triflex_dev; - -#ifdef CONFIG_PROC_FS -static int triflex_get_info(char *buf, char **addr, off_t offset, int count) -{ - char *p = buf; - int len; - - struct pci_dev *dev = triflex_dev; - unsigned long bibma = pci_resource_start(dev, 4); - u8 c0 = 0, c1 = 0; - u32 pri_timing, sec_timing; - - p += sprintf(p, "\n Compaq Triflex Chipset\n"); - - pci_read_config_dword(dev, 0x70, &pri_timing); - pci_read_config_dword(dev, 0x74, &sec_timing); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb((unsigned short)bibma + 0x02); - c1 = inb((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel " - "---------------- Secondary Channel " - "-------------\n"); - p += sprintf(p, " %sabled " - " %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 " - "-------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s " - " %s %s\n", - (c0&0x20) ? "yes" : "no ", - (c0&0x40) ? "yes" : "no ", - (c1&0x20) ? "yes" : "no ", - (c1&0x40) ? "yes" : "no " ); - - p += sprintf(p, "DMA\n"); - p += sprintf(p, "PIO\n"); - - len = (p - buf) - offset; - *addr = buf + offset; - - return len > count ? count : len; -} -#endif - static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -169,25 +118,16 @@ static int triflex_config_drive_xfer_rate(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; - - if (id && (id->capability & 1) && drive->autodma) { - if (__ide_dma_bad_drive(drive)) - goto tune_pio; - if (id->field_valid & 2) { - if ((id->dma_mword & hwif->mwdma_mask) || - (id->dma_1word & hwif->swdma_mask)) { - if (!triflex_config_drive_for_dma(drive)) - goto tune_pio; - } - } else - goto tune_pio; - } else { -tune_pio: - hwif->tuneproc(drive, 255); - return hwif->ide_dma_off_quietly(drive); + + if ((id->capability & 1) && drive->autodma) { + if (ide_use_dma(drive)) { + if (triflex_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); + } } - return hwif->ide_dma_on(drive); + hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); } static void __init init_hwif_triflex(ide_hwif_t *hwif) @@ -206,18 +146,8 @@ static void __init init_hwif_triflex(ide_hwif_t *hwif) hwif->drives[1].autodma = hwif->autodma; } -static unsigned int __init init_chipset_triflex(struct pci_dev *dev, - const char *name) -{ -#ifdef CONFIG_PROC_FS - ide_pci_create_host_proc("triflex", triflex_get_info); -#endif - return 0; -} - static ide_pci_device_t triflex_device __devinitdata = { .name = "TRIFLEX", - .init_chipset = init_chipset_triflex, .init_hwif = init_hwif_triflex, .channels = 2, .autodma = AUTODMA, @@ -229,7 +159,6 @@ static int __devinit triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_setup_pci_device(dev, &triflex_device); - triflex_dev = dev; return 0; } @@ -242,7 +171,7 @@ static struct pci_device_id triflex_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, triflex_pci_tbl); static struct pci_driver driver = { - .name = "TRIFLEX IDE", + .name = "TRIFLEX_IDE", .id_table = triflex_pci_tbl, .probe = triflex_init_one, }; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index d4c753930..d830b60f6 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -179,64 +179,32 @@ static void trm290_selectproc (ide_drive_t *drive) } #ifdef CONFIG_BLK_DEV_IDEDMA -static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) +static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; -// ide_task_t *args = rq->special; - task_ioreg_t command = WIN_NOP; - unsigned int count, reading = 2, writing = 0; - reading = 0; - writing = 1; -#ifdef TRM290_NO_DMA_WRITES - /* always use PIO for writes */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; -#endif - if (!(count = ide_build_dmatable(drive, rq))) { - /* try PIO instead of DMA */ - trm290_prepare_drive(drive, 0); /* select PIO xfer */ - return 1; - } - /* select DMA xfer */ - trm290_prepare_drive(drive, 1); - hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); - drive->waiting_for_dma = 1; - /* start DMA */ - hwif->OUTW((count * 2) - 1, hwif->dma_status); - if (drive->media != ide_disk) - return 0; if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - command = /* (lba48) ? WIN_READDMA_EXT : */ WIN_READDMA; - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#endif /* issue cmd to drive */ hwif->OUTB(command, IDE_COMMAND_REG); - return hwif->ide_dma_begin(drive); } -static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) +static int trm290_ide_dma_setup(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct request *rq = HWGROUP(drive)->rq; -// ide_task_t *args = rq->special; - task_ioreg_t command = WIN_NOP; - unsigned int count, reading = 2, writing = 0; + ide_hwif_t *hwif = drive->hwif; + struct request *rq = hwif->hwgroup->rq; + unsigned int count, rw; + + if (rq_data_dir(rq)) { +#ifdef TRM290_NO_DMA_WRITES + /* always use PIO for writes */ + trm290_prepare_drive(drive, 0); /* select PIO xfer */ + return 1; +#endif + rw = 1; + } else + rw = 2; if (!(count = ide_build_dmatable(drive, rq))) { /* try PIO instead of DMA */ @@ -245,38 +213,15 @@ static int trm290_ide_dma_read (ide_drive_t *drive /*, struct request *rq */) } /* select DMA xfer */ trm290_prepare_drive(drive, 1); - hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command); + hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command); drive->waiting_for_dma = 1; /* start DMA */ hwif->OUTW((count * 2) - 1, hwif->dma_status); - if (drive->media != ide_disk) - return 0; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - /* - * FIX ME to use only ACB ide_task_t args Struct - */ -#if 0 - { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#else - command = /* (lba48) ? WIN_WRITEDMA_EXT : */ WIN_WRITEDMA; - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } -#endif - /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); - return hwif->ide_dma_begin(drive); + return 0; } -static int trm290_ide_dma_begin (ide_drive_t *drive) +static void trm290_ide_dma_start(ide_drive_t *drive) { - return 0; } static int trm290_ide_dma_end (ide_drive_t *drive) @@ -304,7 +249,7 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive) /* * Invoked from ide-dma.c at boot time. */ -void __devinit init_hwif_trm290(ide_hwif_t *hwif) +static void __devinit init_hwif_trm290(ide_hwif_t *hwif) { unsigned int cfgbase = 0; unsigned long flags; @@ -347,9 +292,9 @@ void __devinit init_hwif_trm290(ide_hwif_t *hwif) ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); #ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_write = &trm290_ide_dma_write; - hwif->ide_dma_read = &trm290_ide_dma_read; - hwif->ide_dma_begin = &trm290_ide_dma_begin; + hwif->dma_setup = &trm290_ide_dma_setup; + hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd; + hwif->dma_start = &trm290_ide_dma_start; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -408,7 +353,7 @@ static struct pci_device_id trm290_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, trm290_pci_tbl); static struct pci_driver driver = { - .name = "TRM290 IDE", + .name = "TRM290_IDE", .id_table = trm290_pci_tbl, .probe = trm290_init_one, }; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 9aa563300..c83d5e5e8 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -632,7 +632,7 @@ static struct pci_device_id via_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, via_pci_tbl); static struct pci_driver driver = { - .name = "VIA IDE", + .name = "VIA_IDE", .id_table = via_pci_tbl, .probe = via_init_one, }; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 7030168e6..011d3f27e 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -51,8 +52,6 @@ #include "ide-timing.h" -extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); - #define IDE_PMAC_DEBUG #define DMA_WAIT_TIMEOUT 50 @@ -62,10 +61,10 @@ typedef struct pmac_ide_hwif { int irq; int kind; int aapl_bus_id; - int cable_80 : 1; - int mediabay : 1; - int broken_dma : 1; - int broken_dma_warn : 1; + unsigned cable_80 : 1; + unsigned mediabay : 1; + unsigned broken_dma : 1; + unsigned broken_dma_warn : 1; struct device_node* node; struct macio_dev *mdev; u32 timings[4]; @@ -75,12 +74,8 @@ typedef struct pmac_ide_hwif { * beeing done by the generic code about the kind of dma controller * and format of the dma table. This will have to be fixed though. */ - volatile struct dbdma_regs* dma_regs; + volatile struct dbdma_regs __iomem * dma_regs; struct dbdma_cmd* dma_table_cpu; - dma_addr_t dma_table_dma; - struct scatterlist* sg_table; - int sg_nents; - int sg_dma_direction; #endif } pmac_ide_hwif_t; @@ -361,7 +356,6 @@ static int pmac_ide_tune_chipset(ide_drive_t *drive, u8 speed); static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio); static void pmac_ide_selectproc(ide_drive_t *drive); static void pmac_ide_kauai_selectproc(ide_drive_t *drive); -static int pmac_ide_dma_begin (ide_drive_t *drive); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ @@ -497,6 +491,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, *irq = pmac_ide[ix].irq; } +#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x))) + /* * Apply the timings of the proper unit (master/slave) to the shared * timing register when selecting that unit. This version is for @@ -511,12 +507,10 @@ pmac_ide_selectproc(ide_drive_t *drive) return; if (drive->select.b.unit & 0x01) - writel(pmif->timings[1], - (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG)); else - writel(pmif->timings[0], - (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); - (void)readl((unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); + writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG)); + (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); } /* @@ -533,17 +527,13 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive) return; if (drive->select.b.unit & 0x01) { - writel(pmif->timings[1], - (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); - writel(pmif->timings[3], - (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG)); + writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); } else { - writel(pmif->timings[0], - (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); - writel(pmif->timings[2], - (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG)); + writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); + writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); } - (void)readl((unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG)); + (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); } /* @@ -568,8 +558,8 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port) { u32 tmp; - writeb(value, port); - tmp = readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)); + writeb(value, (void __iomem *) port); + tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); } /* @@ -792,7 +782,7 @@ static int __pmac set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, u8 speed, int drive_cycle_time) { - int cycleTime, accessTime, recTime; + int cycleTime, accessTime = 0, recTime = 0; unsigned accessTicks, recTicks; struct mdma_timings_t* tm = NULL; int i; @@ -1249,6 +1239,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->noprobe = 0; #endif /* CONFIG_PMAC_PBOOK */ + hwif->sg_max_nents = MAX_DCMDS; + #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* has a DBDMA controller channel */ if (pmif->dma_regs) @@ -1281,7 +1273,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) static int __devinit pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match) { - unsigned long base, regbase; + void __iomem *base; + unsigned long regbase; int irq; ide_hwif_t *hwif; pmac_ide_hwif_t *pmif; @@ -1324,8 +1317,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match) } else irq = macio_irq(mdev, 0); - base = (unsigned long)ioremap(macio_resource_start(mdev, 0), 0x400); - regbase = base; + base = ioremap(macio_resource_start(mdev, 0), 0x400); + regbase = (unsigned long) base; hwif->pci_dev = mdev->bus->pdev; hwif->gendev.parent = &mdev->ofdev.dev; @@ -1339,8 +1332,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match) if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i); else - pmif->dma_regs = (volatile struct dbdma_regs*) - ioremap(macio_resource_start(mdev, 1), 0x1000); + pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); } else pmif->dma_regs = NULL; #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ @@ -1350,9 +1342,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match) if (rc != 0) { /* The inteface is released to the common IDE layer */ dev_set_drvdata(&mdev->ofdev.dev, NULL); - iounmap((void *)base); + iounmap(base); if (pmif->dma_regs) - iounmap((void *)pmif->dma_regs); + iounmap(pmif->dma_regs); memset(pmif, 0, sizeof(*pmif)); macio_release_resource(mdev, 0); if (pmif->dma_regs) @@ -1368,10 +1360,10 @@ pmac_ide_macio_suspend(struct macio_dev *mdev, u32 state) ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; - if (state != mdev->ofdev.dev.power_state && state >= 2) { + if (state != mdev->ofdev.dev.power.power_state && state >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) - mdev->ofdev.dev.power_state = state; + mdev->ofdev.dev.power.power_state = state; } return rc; @@ -1383,10 +1375,10 @@ pmac_ide_macio_resume(struct macio_dev *mdev) ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); int rc = 0; - if (mdev->ofdev.dev.power_state != 0) { + if (mdev->ofdev.dev.power.power_state != 0) { rc = pmac_ide_do_resume(hwif); if (rc == 0) - mdev->ofdev.dev.power_state = 0; + mdev->ofdev.dev.power.power_state = 0; } return rc; @@ -1401,7 +1393,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) ide_hwif_t *hwif; struct device_node *np; pmac_ide_hwif_t *pmif; - unsigned long base; + void __iomem *base; unsigned long rbase, rlen; int i, rc; @@ -1444,10 +1436,10 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) rbase = pci_resource_start(pdev, 0); rlen = pci_resource_len(pdev, 0); - base = (unsigned long) ioremap(rbase, rlen); - pmif->regbase = base + 0x2000; + base = ioremap(rbase, rlen); + pmif->regbase = (unsigned long) base + 0x2000; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000); + pmif->dma_regs = base + 0x1000; #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ /* We use the OF node irq mapping */ @@ -1462,7 +1454,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) if (rc != 0) { /* The inteface is released to the common IDE layer */ pci_set_drvdata(pdev, NULL); - iounmap((void *)base); + iounmap(base); memset(pmif, 0, sizeof(*pmif)); pci_release_regions(pdev); } @@ -1476,10 +1468,10 @@ pmac_ide_pci_suspend(struct pci_dev *pdev, u32 state) ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; - if (state != pdev->dev.power_state && state >= 2) { + if (state != pdev->dev.power.power_state && state >= 2) { rc = pmac_ide_do_suspend(hwif); if (rc == 0) - pdev->dev.power_state = state; + pdev->dev.power.power_state = state; } return rc; @@ -1491,10 +1483,10 @@ pmac_ide_pci_resume(struct pci_dev *pdev) ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev); int rc = 0; - if (pdev->dev.power_state != 0) { + if (pdev->dev.power.power_state != 0) { rc = pmac_ide_do_resume(hwif); if (rc == 0) - pdev->dev.power_state = 0; + pdev->dev.power.power_state = 0; } return rc; @@ -1565,69 +1557,6 @@ pmac_ide_probe(void) #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC -/* - * This is very close to the generic ide-dma version of the function except - * that we don't use the fields in the hwif but our own copies for sg_table - * and friends. We build & map the sglist for a given request - */ -static int __pmac -pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = HWIF(drive); - pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; - struct scatterlist *sg = pmif->sg_table; - int nents; - - if (hwif->sg_dma_active) - BUG(); - - nents = blk_rq_map_sg(drive->queue, rq, sg); - - if (rq_data_dir(rq) == READ) - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - else - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - -/* - * Same as above but for a "raw" taskfile request - */ -static int __pmac -pmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = HWIF(drive); - pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; - struct scatterlist *sg = pmif->sg_table; - int nents = 0; - ide_task_t *args = rq->special; - unsigned char *virt_addr = rq->buffer; - int sector_count = rq->nr_sectors; - - if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) - pmif->sg_dma_direction = PCI_DMA_TODEVICE; - else - pmif->sg_dma_direction = PCI_DMA_FROMDEVICE; - - if (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - } - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = offset_in_page(virt_addr); - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; - - return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction); -} - /* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. @@ -1639,7 +1568,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) int i, count = 0; ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; - volatile struct dbdma_regs *dma = pmif->dma_regs; + volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; struct scatterlist *sg; int wr = (rq_data_dir(rq) == WRITE); @@ -1651,16 +1580,13 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) while (readl(&dma->status) & RUN) udelay(1); - /* Build sglist */ - if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) - pmif->sg_nents = i = pmac_ide_raw_build_sglist(drive, rq); - else - pmif->sg_nents = i = pmac_ide_build_sglist(drive, rq); + hwif->sg_nents = i = ide_build_sglist(drive, rq); + if (!i) return 0; /* Build DBDMA commands list */ - sg = pmif->sg_table; + sg = hwif->sg_table; while (i && sg_dma_len(sg)) { u32 cur_addr; u32 cur_len; @@ -1705,17 +1631,16 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) memset(table, 0, sizeof(struct dbdma_cmd)); st_le16(&table->command, DBDMA_STOP); mb(); - writel(pmif->dma_table_dma, &dma->cmdptr); + writel(hwif->dmatable_dma, &dma->cmdptr); return 1; } printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); use_pio_instead: pci_unmap_sg(hwif->pci_dev, - pmif->sg_table, - pmif->sg_nents, - pmif->sg_dma_direction); - hwif->sg_dma_active = 0; + hwif->sg_table, + hwif->sg_nents, + hwif->sg_dma_direction); return 0; /* revert to PIO for this request */ } @@ -1723,15 +1648,14 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) static void __pmac pmac_ide_destroy_dmatable (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = HWIF(drive)->pci_dev; - pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; - struct scatterlist *sg = pmif->sg_table; - int nents = pmif->sg_nents; + struct scatterlist *sg = hwif->sg_table; + int nents = hwif->sg_nents; if (nents) { - pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction); - pmif->sg_nents = 0; - HWIF(drive)->sg_dma_active = 0; + pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction); + hwif->sg_nents = 0; } } @@ -1894,7 +1818,7 @@ pmac_ide_dma_check(ide_drive_t *drive) * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion */ static int __pmac -pmac_ide_dma_start(ide_drive_t *drive, int reading) +pmac_ide_dma_setup(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; @@ -1906,14 +1830,16 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading) return 1; ata4 = (pmif->kind == controller_kl_ata4); - if (!pmac_ide_build_dmatable(drive, rq)) + if (!pmac_ide_build_dmatable(drive, rq)) { + ide_map_sg(drive, rq); return 1; + } /* Apple adds 60ns to wrDataSetup on reads */ if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { - writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0), - (unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG)); - (void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG)); + writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0), + PMAC_IDE_REG(IDE_TIMING_CONFIG)); + (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); } drive->waiting_for_dma = 1; @@ -1921,87 +1847,28 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading) return 0; } -/* - * Start a DMA READ command - */ -static int __pmac -pmac_ide_dma_read(ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - if (pmac_ide_dma_start(drive, 1)) - return 1; - - if (drive->media != ide_disk) - return 0; - - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; - - if (drive->vdma) - command = (lba48) ? WIN_READ_EXT: WIN_READ; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - - /* issue cmd to drive */ - ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); - - return pmac_ide_dma_begin(drive); -} - -/* - * Start a DMA WRITE command - */ -static int __pmac -pmac_ide_dma_write (ide_drive_t *drive) +static void __pmac +pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - struct request *rq = HWGROUP(drive)->rq; - u8 lba48 = (drive->addressing == 1) ? 1 : 0; - task_ioreg_t command = WIN_NOP; - - if (pmac_ide_dma_start(drive, 0)) - return 1; - - if (drive->media != ide_disk) - return 0; - - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; - if (drive->vdma) - command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; - - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; - } - /* issue cmd to drive */ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); - - return pmac_ide_dma_begin(drive); } /* * Kick the DMA controller into life after the DMA command has been issued * to the drive. */ -static int __pmac -pmac_ide_dma_begin (ide_drive_t *drive) +static void __pmac +pmac_ide_dma_start(ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; - volatile struct dbdma_regs *dma; + volatile struct dbdma_regs __iomem *dma; - if (pmif == NULL) - return 1; dma = pmif->dma_regs; writel((RUN << 16) | RUN, &dma->control); /* Make sure it gets to the controller right now */ (void)readl(&dma->control); - return 0; } /* @@ -2011,7 +1878,7 @@ static int __pmac pmac_ide_dma_end (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; - volatile struct dbdma_regs *dma; + volatile struct dbdma_regs __iomem *dma; u32 dstat; if (pmif == NULL) @@ -2039,7 +1906,7 @@ static int __pmac pmac_ide_dma_test_irq (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; - volatile struct dbdma_regs *dma; + volatile struct dbdma_regs __iomem *dma; unsigned long status, timeout; if (pmif == NULL) @@ -2107,7 +1974,7 @@ static int __pmac pmac_ide_dma_lostirq (ide_drive_t *drive) { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; - volatile struct dbdma_regs *dma; + volatile struct dbdma_regs __iomem *dma; unsigned long status; if (pmif == NULL) @@ -2139,42 +2006,26 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( hwif->pci_dev, (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - &pmif->dma_table_dma); + &hwif->dmatable_dma); if (pmif->dma_table_cpu == NULL) { printk(KERN_ERR "%s: unable to allocate DMA command list\n", hwif->name); return; } - pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS, - GFP_KERNEL); - if (pmif->sg_table == NULL) { - pci_free_consistent( hwif->pci_dev, - (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), - pmif->dma_table_cpu, pmif->dma_table_dma); - return; - } hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; hwif->ide_dma_on = &__ide_dma_on; hwif->ide_dma_check = &pmac_ide_dma_check; - hwif->ide_dma_read = &pmac_ide_dma_read; - hwif->ide_dma_write = &pmac_ide_dma_write; - hwif->ide_dma_begin = &pmac_ide_dma_begin; + hwif->dma_setup = &pmac_ide_dma_setup; + hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; + hwif->dma_start = &pmac_ide_dma_start; hwif->ide_dma_end = &pmac_ide_dma_end; hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; hwif->ide_dma_host_off = &pmac_ide_dma_host_off; hwif->ide_dma_host_on = &pmac_ide_dma_host_on; - hwif->ide_dma_verbose = &__ide_dma_verbose; hwif->ide_dma_timeout = &__ide_dma_timeout; hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO - if (!noautodma) - hwif->autodma = 1; -#endif - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; - hwif->atapi_dma = 1; switch(pmif->kind) { case controller_un_ata6: diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index b485e6b70..5ccb60e40 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -185,19 +185,16 @@ static unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif) second_chance_to_dma: #endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */ - if ((hwif->mmio) && (hwif->dma_base)) + if (hwif->mmio) return hwif->dma_base; if (hwif->mate && hwif->mate->dma_base) { dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); } else { - dma_base = (hwif->mmio) ? - ((unsigned long) hwif->hwif_data) : - (pci_resource_start(dev, 4)); + dma_base = pci_resource_start(dev, 4); if (!dma_base) { - printk(KERN_ERR "%s: dma_base is invalid (0x%04lx)\n", - hwif->cds->name, dma_base); - dma_base = 0; + printk(KERN_ERR "%s: dma_base is invalid\n", + hwif->cds->name); } } @@ -251,7 +248,6 @@ second_chance_to_dma: simplex_stat = hwif->INB(dma_base + 2); if (simplex_stat & 0x80) { /* simplex device? */ -#if 0 /* * At this point we haven't probed the drives so we can't make the * appropriate decision. Really we should defer this problem @@ -259,18 +255,7 @@ second_chance_to_dma: * to be the DMA end. This has to be become dynamic to handle hot * plug. */ - /* Don't enable DMA on a simplex channel with no drives */ - if (!hwif->drives[0].present && !hwif->drives[1].present) - { - printk(KERN_INFO "%s: simplex device with no drives: DMA disabled\n", - hwif->cds->name); - dma_base = 0; - } - /* If our other channel has DMA then we cannot */ - else -#endif - if(hwif->mate && hwif->mate->dma_base) - { + if (hwif->mate && hwif->mate->dma_base) { printk(KERN_INFO "%s: simplex device: " "DMA disabled\n", hwif->cds->name); @@ -488,13 +473,8 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi * Set up BM-DMA capability * (PnP BIOS should have done this) */ - if ((d->flags & IDEPCI_FLAG_FORCE_MASTER) == 0) { - /* - * default DMA off if we had to - * configure it here - */ - hwif->autodma = 0; - } + /* default DMA off if we had to configure it here */ + hwif->autodma = 0; pci_set_master(dev); if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { printk(KERN_ERR "%s: %s error updating PCICMD\n", @@ -514,6 +494,11 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi } } } + +#ifndef CONFIG_IDEDMA_PCI_AUTO +#warning CONFIG_IDEDMA_PCI_AUTO=n support is obsolete, and will be removed soon. +#endif + #endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/ /** @@ -530,13 +515,9 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwi static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, int noisy, int *config) { - int ret = 0; u32 class_rev; u16 pcicmd; - if (!noautodma) - ret = 1; - if (noisy) ide_setup_pci_noise(dev, d); @@ -550,8 +531,6 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ if (ide_pci_configure(dev, d)) return -ENODEV; - /* default DMA off if we had to configure it here */ - ret = 0; *config = 1; printk(KERN_INFO "%s: device enabled (Linux)\n", d->name); } @@ -560,14 +539,13 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in class_rev &= 0xff; if (noisy) printk(KERN_INFO "%s: chipset revision %d\n", d->name, class_rev); - return ret; + return 0; } /** * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device * @d: IDE pci device info - * @autodma: Should we enable DMA * @pciirq: IRQ line * @index: ata index to update * @@ -580,7 +558,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in * where the chipset setup is not the default PCI IDE one. */ -void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, int pciirq, ata_index_t *index) +void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, ata_index_t *index) { int port; int at_least_one_hwif_enabled = 0; @@ -634,11 +612,7 @@ controller_ok: if (d->autodma == NODMA) goto bypass_legacy_dma; - if (d->autodma == NOAUTODMA) - autodma = 0; - if (autodma) - hwif->autodma = 1; - + if(d->init_setup_dma) d->init_setup_dma(dev, d, hwif); else @@ -671,12 +645,11 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports); */ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy) { - int autodma = 0; int pciirq = 0; int tried_config = 0; ata_index_t index = { .b = { .low = 0xff, .high = 0xff } }; - if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0) + if (ide_setup_pci_controller(dev, d, noisy, &tried_config) < 0) return index; /* @@ -724,7 +697,7 @@ static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_ if(pciirq < 0) /* Error not an IRQ */ return index; - ide_pci_setup_ports(dev, d, autodma, pciirq, &index); + ide_pci_setup_ports(dev, d, pciirq, &index); return index; } @@ -734,9 +707,9 @@ void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) ata_index_t index_list = do_ide_setup_pci_device(dev, d, 1); if ((index_list.b.low & 0xf0) != 0xf0) - probe_hwif_init(&ide_hwifs[index_list.b.low]); + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup); if ((index_list.b.high & 0xf0) != 0xf0) - probe_hwif_init(&ide_hwifs[index_list.b.high]); + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup); create_proc_ide_interfaces(); } diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index a9709b846..1c8d1c813 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -132,7 +132,7 @@ struct eth1394_node_info { }; /* Our ieee1394 highlevel driver */ -#define ETH1394_DRIVER_NAME "ip1394" +#define ETH1394_DRIVER_NAME "eth1394" static const char driver_name[] = ETH1394_DRIVER_NAME; static kmem_cache_t *packet_task_cache; @@ -190,8 +190,7 @@ static inline void purge_partial_datagram(struct list_head *old); static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); static void ether1394_iso(struct hpsb_iso *iso); -static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr); +static struct ethtool_ops ethtool_ops; static int ether1394_write(struct hpsb_host *host, int srcid, int destid, quadlet_t *data, u64 addr, size_t len, u16 flags); @@ -216,7 +215,7 @@ static struct hpsb_highlevel eth1394_highlevel = { /* This is called after an "ifup" */ static int ether1394_open (struct net_device *dev) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); int ret = 0; /* Something bad happened, don't even try */ @@ -261,7 +260,7 @@ static int ether1394_stop (struct net_device *dev) /* Return statistics to the caller */ static struct net_device_stats *ether1394_stats (struct net_device *dev) { - return &(((struct eth1394_priv *)dev->priv)->stats); + return &(((struct eth1394_priv *)netdev_priv(dev))->stats); } /* What to do if we timeout. I think a host reset is probably in order, so @@ -269,16 +268,16 @@ static struct net_device_stats *ether1394_stats (struct net_device *dev) static void ether1394_tx_timeout (struct net_device *dev) { ETH1394_PRINT (KERN_ERR, dev->name, "Timeout, resetting host %s\n", - ((struct eth1394_priv *)(dev->priv))->host->driver->name); + ((struct eth1394_priv *)netdev_priv(dev))->host->driver->name); - highlevel_host_reset (((struct eth1394_priv *)(dev->priv))->host); + highlevel_host_reset (((struct eth1394_priv *)netdev_priv(dev))->host); netif_wake_queue (dev); } static int ether1394_change_mtu(struct net_device *dev, int new_mtu) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, @@ -379,7 +378,7 @@ static int eth1394_probe(struct device *dev) ud->device.driver_data = node_info; new_node->ud = ud; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); list_add_tail(&new_node->list, &priv->ip_node_list); return 0; @@ -400,7 +399,7 @@ static int eth1394_remove(struct device *dev) if (!hi) return -ENOENT; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); old_node = eth1394_find_node(&priv->ip_node_list, ud); @@ -435,7 +434,7 @@ static int eth1394_update(struct unit_directory *ud) if (!hi) return -ENOENT; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); node = eth1394_find_node(&priv->ip_node_list, ud); @@ -459,7 +458,7 @@ static int eth1394_update(struct unit_directory *ud) ud->device.driver_data = node_info; node->ud = ud; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); list_add_tail(&node->list, &priv->ip_node_list); } @@ -496,7 +495,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) { unsigned long flags; int i; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); struct hpsb_host *host = priv->host; u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); u16 maxpayload = 1 << (host->csr.max_rec + 1); @@ -547,7 +546,7 @@ static void ether1394_init_dev (struct net_device *dev) dev->header_cache_update= ether1394_header_cache_update; dev->hard_header_parse = ether1394_header_parse; dev->set_mac_address = ether1394_mac_addr; - dev->do_ioctl = ether1394_do_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); /* Some constants */ dev->watchdog_timeo = ETHER1394_TIMEOUT; @@ -601,8 +600,9 @@ static void ether1394_add_host (struct hpsb_host *host) } SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &host->device); - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); INIT_LIST_HEAD(&priv->ip_node_list); @@ -672,7 +672,7 @@ static void ether1394_remove_host (struct hpsb_host *host) hi = hpsb_get_hostinfo(ð1394_highlevel, host); if (hi != NULL) { - struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; + struct eth1394_priv *priv = netdev_priv(hi->dev); hpsb_unregister_addrspace(ð1394_highlevel, host, priv->local_fifo); @@ -707,7 +707,7 @@ static void ether1394_host_reset (struct hpsb_host *host) return; dev = hi->dev; - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); /* Reset our private host data, but not our mtu */ netif_stop_queue (dev); @@ -850,7 +850,7 @@ static inline u16 ether1394_type_trans(struct sk_buff *skb, skb->mac.raw = skb->data; skb_pull (skb, ETH1394_HLEN); - eth = (struct eth1394hdr*)skb->mac.raw; + eth = eth1394_hdr(skb); if (*eth->h_dest & 1) { if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) @@ -882,7 +882,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, nodeid_t srcid, nodeid_t destid, u16 ether_type) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); u64 dest_hw; unsigned short ret = 0; @@ -1112,7 +1112,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, { struct sk_buff *skb; unsigned long flags; - struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); union eth1394_hdr *hdr = (union eth1394_hdr *)buf; u16 ether_type = 0; /* initialized to clear warning */ int hdr_len; @@ -1350,7 +1350,7 @@ static void ether1394_iso(struct hpsb_iso *iso) ((be32_to_cpu(data[1]) & 0xff000000) >> 24)); source_id = be32_to_cpu(data[0]) >> 16; - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) || specifier_id != ETHER1394_GASP_SPECIFIER_ID) { @@ -1384,7 +1384,7 @@ static void ether1394_iso(struct hpsb_iso *iso) static inline void ether1394_arp_to_1394arp(struct sk_buff *skb, struct net_device *dev) { - struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); + struct eth1394_priv *priv = netdev_priv(dev); struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); @@ -1582,7 +1582,7 @@ static inline void ether1394_dg_complete(struct packet_task *ptask, int fail) { struct sk_buff *skb = ptask->skb; struct net_device *dev = skb->dev; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); unsigned long flags; /* Statistics */ @@ -1635,7 +1635,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) { int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; struct eth1394hdr *eth; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); int proto; unsigned long flags; nodeid_t dest_node; @@ -1768,53 +1768,17 @@ fail: return 0; /* returning non-zero causes serious problems */ } -static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - switch(cmd) { - case SIOCETHTOOL: - return ether1394_ethtool_ioctl(dev, ifr->ifr_data); - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCSMIIREG: /* Write MII PHY register. */ - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr) -{ - u32 ethcmd; - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, driver_name); - strcpy (info.version, "$Rev: 1224 $"); - /* FIXME XXX provide sane businfo */ - strcpy (info.bus_info, "ieee1394"); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - break; - } - case ETHTOOL_GSET: - case ETHTOOL_SSET: - case ETHTOOL_NWAY_RST: - case ETHTOOL_GLINK: - case ETHTOOL_GMSGLVL: - case ETHTOOL_SMSGLVL: - default: - return -EOPNOTSUPP; - } - - return 0; + strcpy (info->driver, driver_name); + strcpy (info->version, "$Rev: 1224 $"); + /* FIXME XXX provide sane businfo */ + strcpy (info->bus_info, "ieee1394"); } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = ether1394_get_drvinfo +}; static int __init ether1394_init_module (void) { diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index 015f8178c..ed8f1c4b7 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -81,7 +81,14 @@ struct eth1394hdr { unsigned short h_proto; /* packet type ID field */ } __attribute__((packed)); +#ifdef __KERNEL__ +#include +static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb) +{ + return (struct eth1394hdr *)skb->mac.raw; +} +#endif typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index cc9c999f9..a2859c0a6 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -70,8 +70,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, if (!ret) break; - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout (HZ/3)) + if (msleep_interruptible(334)) return -EINTR; } @@ -1489,14 +1488,16 @@ static int nodemgr_host_thread(void *__hi) break; } - if (hi->kill_me) + if (hi->kill_me) { + up(&nodemgr_serialize); break; + } /* Pause for 1/4 second in 1/16 second intervals, * to make sure things settle down. */ for (i = 0; i < 4 ; i++) { set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(HZ/16)) { + if (msleep_interruptible(63)) { up(&nodemgr_serialize); goto caught_signal; } @@ -1514,8 +1515,10 @@ static int nodemgr_host_thread(void *__hi) i = 0; /* Check the kill_me again */ - if (hi->kill_me) + if (hi->kill_me) { + up(&nodemgr_serialize); goto caught_signal; + } } if (!nodemgr_check_irm_capability(host, reset_cycles)) { diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index afcf7f89e..7c3f6e7bc 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -94,7 +94,6 @@ #include #include #include -#include #include #include #include @@ -103,6 +102,7 @@ #include #include +#include #include #include #include @@ -2933,8 +2933,8 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, d->ctrlClear = 0; d->cmdPtr = 0; - d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); - d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); + d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_ATOMIC); + d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC); if (d->buf_cpu == NULL || d->buf_bus == NULL) { PRINT(KERN_ERR, "Failed to allocate dma buffer"); @@ -2945,8 +2945,8 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t)); d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*), - GFP_KERNEL); - d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); + GFP_ATOMIC); + d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC); if (d->prg_cpu == NULL || d->prg_bus == NULL) { PRINT(KERN_ERR, "Failed to allocate dma prg"); @@ -2956,7 +2956,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*)); memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t)); - d->spb = kmalloc(d->split_buf_size, GFP_KERNEL); + d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC); if (d->spb == NULL) { PRINT(KERN_ERR, "Failed to allocate split buffer"); diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h index e2e6194c9..d1758d409 100644 --- a/drivers/ieee1394/ohci1394.h +++ b/drivers/ieee1394/ohci1394.h @@ -163,7 +163,7 @@ struct ti_ohci { } init_state; /* remapped memory spaces */ - void *registers; + void __iomem *registers; /* dma buffer for self-id packets */ quadlet_t *selfid_buf_cpu; diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 13722daca..dc78e2183 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -42,12 +42,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include "csr1212.h" #include "ieee1394.h" diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h index 9c784ccb5..644ec55d3 100644 --- a/drivers/ieee1394/pcilynx.h +++ b/drivers/ieee1394/pcilynx.h @@ -49,10 +49,10 @@ struct ti_lynx { have_1394_buffers, have_iomappings, is_host } state; /* remapped memory spaces */ - void *registers; - void *local_rom; - void *local_ram; - void *aux_port; + void __iomem *registers; + void __iomem *local_rom; + void __iomem *local_ram; + void __iomem *aux_port; quadlet_t bus_info_block[5]; #ifdef CONFIG_IEEE1394_PCILYNX_PORTS diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 47de79f21..aa9ab3378 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -357,8 +357,7 @@ static int sbp2util_down_timeout(atomic_t *done, int timeout) int i; for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) { - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(HZ/10)) /* 100ms */ + if (msleep_interruptible(100)) /* 100ms */ return(1); } return ((i > 0) ? 0:1); @@ -1088,7 +1087,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized"); - scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(QUERY_LOGINS_REQUEST); + scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) { scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); @@ -1199,7 +1198,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized"); - scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST); + scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */ scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */ scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */ @@ -1325,7 +1324,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) scsi_id->logout_orb->reserved3 = 0x0; scsi_id->logout_orb->reserved4 = 0x0; - scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(LOGOUT_REQUEST); + scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST); scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); /* Notify us when complete */ @@ -1390,7 +1389,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) scsi_id->reconnect_orb->reserved3 = 0x0; scsi_id->reconnect_orb->reserved4 = 0x0; - scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(RECONNECT_REQUEST); + scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST); scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index d12f8e160..94b59f80b 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -52,15 +52,15 @@ struct sbp2_command_orb { u8 cdb[12]; }; -#define LOGIN_REQUEST 0x0 -#define QUERY_LOGINS_REQUEST 0x1 -#define RECONNECT_REQUEST 0x3 -#define SET_PASSWORD_REQUEST 0x4 -#define LOGOUT_REQUEST 0x7 -#define ABORT_TASK_REQUEST 0xb -#define ABORT_TASK_SET 0xc -#define LOGICAL_UNIT_RESET 0xe -#define TARGET_RESET_REQUEST 0xf +#define SBP2_LOGIN_REQUEST 0x0 +#define SBP2_QUERY_LOGINS_REQUEST 0x1 +#define SBP2_RECONNECT_REQUEST 0x3 +#define SBP2_SET_PASSWORD_REQUEST 0x4 +#define SBP2_LOGOUT_REQUEST 0x7 +#define SBP2_ABORT_TASK_REQUEST 0xb +#define SBP2_ABORT_TASK_SET 0xc +#define SBP2_LOGICAL_UNIT_RESET 0xe +#define SBP2_TARGET_RESET_REQUEST 0xf #define ORB_SET_LUN(value) (value & 0xffff) #define ORB_SET_FUNCTION(value) ((value & 0xf) << 16) diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index fd40358ae..28d286b06 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1157,7 +1157,7 @@ static int video1394_ioctl(struct inode *inode, struct file *file, * * FIXME: * - PAGE_READONLY should suffice!? - * - remap_page_range is kind of inefficient for page by page remapping. + * - remap_pfn_range is kind of inefficient for page by page remapping. * But e.g. pte_alloc() does not work in modules ... :-( */ diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 3737e5abc..39c497e5f 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -91,8 +91,6 @@ static int evdev_flush(struct file * file) static void evdev_free(struct evdev *evdev) { - devfs_remove("input/event%d", evdev->minor); - class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); evdev_table[evdev->minor] = NULL; kfree(evdev); } @@ -441,6 +439,8 @@ static void evdev_disconnect(struct input_handle *handle) { struct evdev *evdev = handle->private; + class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor)); + devfs_remove("input/event%d", evdev->minor); evdev->exist = 0; if (evdev->open) { diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c index 71fcad10c..8459e05c6 100644 --- a/drivers/input/gameport/cs461x.c +++ b/drivers/input/gameport/cs461x.c @@ -312,7 +312,7 @@ static void __devexit cs461x_pci_remove(struct pci_dev *pdev) } static struct pci_driver cs461x_pci_driver = { - .name = "CS461x Gameport", + .name = "CS461x_gameport", .id_table = cs461x_pci_tbl, .probe = cs461x_pci_probe, .remove = __devexit_p(cs461x_pci_remove), diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index 89d469378..8f1461ad2 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -50,8 +50,11 @@ struct emu { }; static struct pci_device_id emu_tbl[] = { + { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ + { 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */ + { 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */ { 0, } }; @@ -109,7 +112,7 @@ static void __devexit emu_remove(struct pci_dev *pdev) } static struct pci_driver emu_driver = { - .name = "Emu10k1 Gameport", + .name = "Emu10k1_gameport", .id_table = emu_tbl, .probe = emu_probe, .remove = __devexit_p(emu_remove), diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index ff3b620b8..ab0a151bd 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -98,8 +98,8 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device pci_enable_device(pci); gp->gameport.io = pci_resource_start(pci, 0); if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) { - kfree(gp); printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f); + kfree(gp); return -1; } @@ -137,7 +137,7 @@ static struct pci_device_id fm801_gp_id_table[] = { }; static struct pci_driver fm801_gp_driver = { - .name = "FM801 GP", + .name = "FM801_gameport", .id_table = fm801_gp_id_table, .probe = fm801_gp_probe, .remove = __devexit_p(fm801_gp_remove), diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c index 02c31b779..e0a1c3eb5 100644 --- a/drivers/input/gameport/vortex.c +++ b/drivers/input/gameport/vortex.c @@ -55,8 +55,8 @@ MODULE_LICENSE("GPL"); struct vortex { struct gameport gameport; struct pci_dev *dev; - unsigned char *base; - unsigned char *io; + unsigned char __iomem *base; + unsigned char __iomem *io; char phys[32]; }; @@ -166,7 +166,7 @@ static struct pci_device_id vortex_id_table[] = { 0 }}; static struct pci_driver vortex_driver = { - .name = "vortex", + .name = "vortex_gameport", .id_table = vortex_id_table, .probe = vortex_probe, .remove = __devexit_p(vortex_remove), diff --git a/drivers/input/input.c b/drivers/input/input.c index 416084b80..2fdb2092f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 5eb884656..4fe982d63 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -143,9 +143,7 @@ static int joydev_fasync(int fd, struct file *file, int on) static void joydev_free(struct joydev *joydev) { - devfs_remove("input/js%d", joydev->minor); joydev_table[joydev->minor] = NULL; - class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); kfree(joydev); } @@ -232,8 +230,10 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo && list->head == list->tail && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->joydev->wait, list->joydev->exist - && (list->startup < joydev->nabs + joydev->nkey || list->head != list->tail)); + retval = wait_event_interruptible(list->joydev->wait, + !list->joydev->exist || + list->startup < joydev->nabs + joydev->nkey || + list->head != list->tail); if (retval) return retval; @@ -464,6 +464,8 @@ static void joydev_disconnect(struct input_handle *handle) { struct joydev *joydev = handle->private; + class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); + devfs_remove("input/js%d", joydev->minor); joydev->exist = 0; if (joydev->open) diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 7d506f1f7..8f62f70d0 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -247,9 +247,9 @@ config JOYSTICK_AMIGA To compile this driver as a module, choose M here: the module will be called amijoy. -config INPUT_JOYDUMP +config JOYSTICK_JOYDUMP tristate "Gameport data dumper" - depends on INPUT && INPUT_JOYSTICK + depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you want to dump data from your joystick into the system log for debugging purposes. Say N if you are making a production diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 8b5fc358d..cf36ca9b9 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -46,8 +46,7 @@ MODULE_DESCRIPTION("Driver for Amiga joysticks"); MODULE_LICENSE("GPL"); static int amijoy[2] = { 0, 1 }; -static int amijoy_nargs; -module_param_array_named(map, amijoy, uint, amijoy_nargs, 0); +module_param_array_named(map, amijoy, uint, NULL, 0); MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is 0,1)"); __obsolete_setup("amijoy="); diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 7e52f9609..df7b2aadb 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); static char *js[ANALOG_PORTS]; static int js_nargs; static int analog_options[ANALOG_PORTS]; -module_param_array_named(map, js, charp, js_nargs, 0); +module_param_array_named(map, js, charp, &js_nargs, 0); MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities"); __obsolete_setup("js="); diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 5ad612751..c5c6115dc 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -45,17 +45,17 @@ MODULE_LICENSE("GPL"); static int db9[] __initdata = { -1, 0 }; static int db9_nargs __initdata = 0; -module_param_array_named(dev, db9, int, db9_nargs, 0); +module_param_array_named(dev, db9, int, &db9_nargs, 0); MODULE_PARM_DESC(dev, "Describes first attached device (,)"); static int db9_2[] __initdata = { -1, 0 }; static int db9_nargs_2 __initdata = 0; -module_param_array_named(dev2, db9_2, int, db9_nargs_2, 0); +module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0); MODULE_PARM_DESC(dev2, "Describes second attached device (,)"); static int db9_3[] __initdata = { -1, 0 }; static int db9_nargs_3 __initdata = 0; -module_param_array_named(dev3, db9_3, int, db9_nargs_3, 0); +module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0); MODULE_PARM_DESC(dev3, "Describes third attached device (,)"); __obsolete_setup("db9="); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 555fb362b..3f2cdb6a3 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -1,17 +1,14 @@ /* - * $Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $ + * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux * - * Copyright (c) 1999-2001 Vojtech Pavlik + * Copyright (c) 1999-2004 Vojtech Pavlik + * Copyright (c) 2004 Peter Nelson * * Based on the work of: * Andree Borrmann John Dahlstrom * David Kuder Nathan Hand */ -/* - * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux - */ - /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,17 +43,17 @@ MODULE_LICENSE("GPL"); static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs __initdata = 0; -module_param_array_named(map, gc, int, gc_nargs, 0); +module_param_array_named(map, gc, int, &gc_nargs, 0); MODULE_PARM_DESC(map, "Describers first set of devices (,,,..)"); static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs_2 __initdata = 0; -module_param_array_named(map2, gc_2, int, gc_nargs_2, 0); +module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0); MODULE_PARM_DESC(map2, "Describers second set of devices"); static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 }; static int gc_nargs_3 __initdata = 0; -module_param_array_named(map3, gc_3, int, gc_nargs_3, 0); +module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0); MODULE_PARM_DESC(map3, "Describers third set of devices"); __obsolete_setup("gc="); @@ -72,8 +69,9 @@ __obsolete_setup("gc_3="); #define GC_MULTI2 5 #define GC_N64 6 #define GC_PSX 7 +#define GC_DDR 8 -#define GC_MAX 7 +#define GC_MAX 8 #define GC_REFRESH_TIME HZ/100 @@ -91,7 +89,8 @@ static struct gc *gc_base[3]; static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", - "Multisystem 2-button joystick", "N64 controller", "PSX controller" }; + "Multisystem 2-button joystick", "N64 controller", "PSX controller" + "PSX DDR controller" }; /* * N64 support. */ @@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) #define GC_PSX_RUMBLE 7 /* Rumble in Red mode */ #define GC_PSX_CLOCK 0x04 /* Pin 4 */ -#define GC_PSX_COMMAND 0x01 /* Pin 1 */ +#define GC_PSX_COMMAND 0x01 /* Pin 2 */ #define GC_PSX_POWER 0xf8 /* Pins 5-9 */ #define GC_PSX_SELECT 0x02 /* Pin 3 */ @@ -253,25 +252,29 @@ __obsolete_setup("gc_psx_delay="); static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y }; static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR }; +static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; /* * gc_psx_command() writes 8bit command and reads 8bit data from * the psx pad. */ -static int gc_psx_command(struct gc *gc, int b) +static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH]) { - int i, cmd, data = 0; + int i, j, cmd, read; + for (i = 0; i < 5; i++) + data[i] = 0; for (i = 0; i < 8; i++, b >>= 1) { cmd = (b & 1) ? GC_PSX_COMMAND : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); udelay(gc_psx_delay); - data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0; + read = parport_read_status(gc->pd->port) ^ 0x80; + for (j = 0; j < 5; j++) + data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); udelay(gc_psx_delay); } - return data; } /* @@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b) * device identifier code. */ -static int gc_psx_read_packet(struct gc *gc, unsigned char *data) +static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5]) { - int i, id; + int i, j, max_len = 0; unsigned long flags; + unsigned char data2[5]; parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */ - udelay(gc_psx_delay * 2); + udelay(gc_psx_delay); parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */ - udelay(gc_psx_delay * 2); + udelay(gc_psx_delay); local_irq_save(flags); - gc_psx_command(gc, 0x01); /* Access pad */ - id = gc_psx_command(gc, 0x42); /* Get device id */ - if (gc_psx_command(gc, 0) == 0x5a) { /* Okay? */ - for (i = 0; i < GC_PSX_LEN(id) * 2; i++) - data[i] = gc_psx_command(gc, 0); - } else id = 0; + gc_psx_command(gc, 0x01, data2); /* Access pad */ + gc_psx_command(gc, 0x42, id); /* Get device ids */ + gc_psx_command(gc, 0, data2); /* Dump status */ + + for (i =0; i < 5; i++) /* Find the longest pad */ + if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len)) + max_len = GC_PSX_LEN(id[i]); + + for (i = 0; i < max_len * 2; i++) { /* Read in all the data */ + gc_psx_command(gc, 0, data2); + for (j = 0; j < 5; j++) + data[j][i] = data2[j]; + } local_irq_restore(flags); parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); - return GC_PSX_ID(id); + for(i = 0; i < 5; i++) /* Set id's to the real value */ + id[i] = GC_PSX_ID(id[i]); } /* @@ -316,6 +328,7 @@ static void gc_timer(unsigned long private) struct gc *gc = (void *) private; struct input_dev *dev = gc->dev; unsigned char data[GC_MAX_LENGTH]; + unsigned char data_psx[5][GC_PSX_LENGTH]; int i, j, s; /* @@ -412,53 +425,72 @@ static void gc_timer(unsigned long private) * PSX controllers */ - if (gc->pads[GC_PSX]) { + if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) { - for (i = 0; i < 5; i++) - if (gc->pads[GC_PSX] & gc_status_bit[i]) - break; + gc_psx_read_packet(gc, data_psx, data); - switch (gc_psx_read_packet(gc, data)) { + for (i = 0; i < 5; i++) { + switch (data[i]) { - case GC_PSX_RUMBLE: + case GC_PSX_RUMBLE: - input_report_key(dev + i, BTN_THUMBL, ~data[0] & 0x04); - input_report_key(dev + i, BTN_THUMBR, ~data[0] & 0x02); - input_sync(dev + i); + input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04); + input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02); - case GC_PSX_NEGCON: - case GC_PSX_ANALOG: + case GC_PSX_NEGCON: + case GC_PSX_ANALOG: - for (j = 0; j < 4; j++) - input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]); + if(gc->pads[GC_DDR] & gc_status_bit[i]) { + for(j = 0; j < 4; j++) + input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); + } else { + for (j = 0; j < 4; j++) + input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]); - input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80)); - input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10)); + input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); + input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); + } - for (j = 0; j < 8; j++) - input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j)); + for (j = 0; j < 8; j++) + input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); - input_report_key(dev + i, BTN_START, ~data[0] & 0x08); - input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01); + input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); + input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); - input_sync(dev + i); + input_sync(dev + i); - break; + break; - case GC_PSX_NORMAL: + case GC_PSX_NORMAL: + if(gc->pads[GC_DDR] & gc_status_bit[i]) { + for(j = 0; j < 4; j++) + input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); + } else { + input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); + input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); - input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128); - input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128); + /* for some reason if the extra axes are left unset they drift */ + /* for (j = 0; j < 4; j++) + input_report_abs(dev + i, gc_psx_abs[j+2], 128); + * This needs to be debugged properly, + * maybe fuzz processing needs to be done in input_sync() + * --vojtech + */ + } - for (j = 0; j < 8; j++) - input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j)); + for (j = 0; j < 8; j++) + input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); - input_report_key(dev + i, BTN_START, ~data[0] & 0x08); - input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01); + input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); + input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); - input_sync(dev + i); + input_sync(dev + i); - break; + break; + + case 0: /* not a pad, ignore */ + break; + } } } @@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs) { struct gc *gc; struct parport *pp; - int i, j, psx; - unsigned char data[32]; + int i, j; if (config[0] < 0) return NULL; @@ -588,43 +619,22 @@ static struct gc __init *gc_probe(int *config, int nargs) break; case GC_PSX: - - psx = gc_psx_read_packet(gc, data); - - switch(psx) { - case GC_PSX_NEGCON: - case GC_PSX_NORMAL: - case GC_PSX_ANALOG: - case GC_PSX_RUMBLE: - - for (j = 0; j < 6; j++) { - psx = gc_psx_abs[j]; - set_bit(psx, gc->dev[i].absbit); - if (j < 4) { - gc->dev[i].absmin[psx] = 4; - gc->dev[i].absmax[psx] = 252; - gc->dev[i].absflat[psx] = 2; - } else { - gc->dev[i].absmin[psx] = -1; - gc->dev[i].absmax[psx] = 1; - } - } - - for (j = 0; j < 12; j++) - set_bit(gc_psx_btn[j], gc->dev[i].keybit); - - break; - - case 0: - gc->pads[GC_PSX] &= ~gc_status_bit[i]; - printk(KERN_ERR "gamecon.c: No PSX controller found.\n"); - break; - - default: - gc->pads[GC_PSX] &= ~gc_status_bit[i]; - printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x," - " please report to .\n", psx); + case GC_DDR: + if(config[i + 1] == GC_DDR) { + for (j = 0; j < 4; j++) + set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit); + } else { + for (j = 0; j < 6; j++) { + set_bit(gc_psx_abs[j], gc->dev[i].absbit); + gc->dev[i].absmin[gc_psx_abs[j]] = 4; + gc->dev[i].absmax[gc_psx_abs[j]] = 252; + gc->dev[i].absflat[gc_psx_abs[j]] = 2; + } } + + for (j = 0; j < 12; j++) + set_bit(gc_psx_btn[j], gc->dev[i].keybit); + break; } diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 8e1949683..849d0de04 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -107,6 +107,8 @@ static const int init_seq[] = { static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 }; +static void register_slot(int i, struct grip_mp *grip); + /* * Returns whether an odd or even number of bits are on in pkt. */ @@ -355,7 +357,6 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags) u32 packet; int joytype = 0; int slot = 0; - static void register_slot(int i, struct grip_mp *grip); /* Get a packet and check for validity */ diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 71cb7db75..cf815c7ee 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -524,7 +524,7 @@ static int __init iforce_init(void) usb_register(&iforce_usb_driver); #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 - serio_register_device(&iforce_serio_dev); + serio_register_driver(&iforce_serio_drv); #endif return 0; } @@ -535,7 +535,7 @@ static void __exit iforce_exit(void) usb_deregister(&iforce_usb_driver); #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 - serio_unregister_device(&iforce_serio_dev); + serio_unregister_driver(&iforce_serio_drv); #endif } diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 0665b5460..9422407c2 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -124,7 +124,7 @@ out: return IRQ_HANDLED; } -static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev) +static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv) { struct iforce *iforce; if (serio->type != (SERIO_RS232 | SERIO_IFORCE)) @@ -137,7 +137,7 @@ static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev) iforce->serio = serio; serio->private = iforce; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(iforce); return; } @@ -158,9 +158,13 @@ static void iforce_serio_disconnect(struct serio *serio) kfree(iforce); } -struct serio_dev iforce_serio_dev = { - .write_wakeup = iforce_serio_write_wakeup, - .interrupt = iforce_serio_irq, - .connect = iforce_serio_connect, - .disconnect = iforce_serio_disconnect, +struct serio_driver iforce_serio_drv = { + .driver = { + .name = "iforce", + }, + .description = "RS232 I-Force joysticks and wheels driver", + .write_wakeup = iforce_serio_write_wakeup, + .interrupt = iforce_serio_irq, + .connect = iforce_serio_connect, + .disconnect = iforce_serio_disconnect, }; diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index a8586abf5..bce247bc3 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -187,5 +187,5 @@ int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update); int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update); /* Public variables */ -extern struct serio_dev iforce_serio_dev; +extern struct serio_driver iforce_serio_drv; extern struct usb_driver iforce_usb_driver; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index f326299b4..2b303bac5 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -35,8 +35,10 @@ #include #include +#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -146,7 +148,7 @@ static void magellan_disconnect(struct serio *serio) * it as an input device. */ -static void magellan_connect(struct serio *serio, struct serio_dev *dev) +static void magellan_connect(struct serio *serio, struct serio_driver *drv) { struct magellan *magellan; int i, t; @@ -184,7 +186,7 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev) serio->private = magellan; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(magellan); return; } @@ -199,10 +201,14 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev magellan_dev = { - .interrupt = magellan_interrupt, - .connect = magellan_connect, - .disconnect = magellan_disconnect, +static struct serio_driver magellan_drv = { + .driver = { + .name = "magellan", + }, + .description = DRIVER_DESC, + .interrupt = magellan_interrupt, + .connect = magellan_connect, + .disconnect = magellan_disconnect, }; /* @@ -211,13 +217,13 @@ static struct serio_dev magellan_dev = { int __init magellan_init(void) { - serio_register_device(&magellan_dev); + serio_register_driver(&magellan_drv); return 0; } void __exit magellan_exit(void) { - serio_unregister_device(&magellan_dev); + serio_unregister_driver(&magellan_drv); } module_init(magellan_init); diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index eb5b6f76c..40412528e 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -39,8 +39,10 @@ #include #include +#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -201,7 +203,7 @@ static void spaceball_disconnect(struct serio *serio) * it as an input device. */ -static void spaceball_connect(struct serio *serio, struct serio_dev *dev) +static void spaceball_connect(struct serio *serio, struct serio_driver *drv) { struct spaceball *spaceball; int i, t, id; @@ -254,7 +256,7 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev) serio->private = spaceball; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(spaceball); return; } @@ -269,10 +271,14 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev spaceball_dev = { - .interrupt = spaceball_interrupt, - .connect = spaceball_connect, - .disconnect = spaceball_disconnect, +static struct serio_driver spaceball_drv = { + .driver = { + .name = "spaceball", + }, + .description = DRIVER_DESC, + .interrupt = spaceball_interrupt, + .connect = spaceball_connect, + .disconnect = spaceball_disconnect, }; /* @@ -281,13 +287,13 @@ static struct serio_dev spaceball_dev = { int __init spaceball_init(void) { - serio_register_device(&spaceball_dev); + serio_register_driver(&spaceball_drv); return 0; } void __exit spaceball_exit(void) { - serio_unregister_device(&spaceball_dev); + serio_unregister_driver(&spaceball_drv); } module_init(spaceball_init); diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index 00da66c4b..c20091a6e 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -38,8 +38,10 @@ #include #include +#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -162,7 +164,7 @@ static void spaceorb_disconnect(struct serio *serio) * it as an input device. */ -static void spaceorb_connect(struct serio *serio, struct serio_dev *dev) +static void spaceorb_connect(struct serio *serio, struct serio_driver *drv) { struct spaceorb *spaceorb; int i, t; @@ -201,7 +203,7 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev) serio->private = spaceorb; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(spaceorb); return; } @@ -213,10 +215,14 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev spaceorb_dev = { - .interrupt = spaceorb_interrupt, - .connect = spaceorb_connect, - .disconnect = spaceorb_disconnect, +static struct serio_driver spaceorb_drv = { + .driver = { + .name = "spaceorb", + }, + .description = DRIVER_DESC, + .interrupt = spaceorb_interrupt, + .connect = spaceorb_connect, + .disconnect = spaceorb_disconnect, }; /* @@ -225,13 +231,13 @@ static struct serio_dev spaceorb_dev = { int __init spaceorb_init(void) { - serio_register_device(&spaceorb_dev); + serio_register_driver(&spaceorb_drv); return 0; } void __exit spaceorb_exit(void) { - serio_unregister_device(&spaceorb_dev); + serio_unregister_driver(&spaceorb_drv); } module_init(spaceorb_init); diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index ce9be4563..580e32375 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -36,8 +36,10 @@ #include #include +#define DRIVER_DESC "Gravis Stinger gamepad driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Gravis Stinger gamepad driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -134,7 +136,7 @@ static void stinger_disconnect(struct serio *serio) * it as an input device. */ -static void stinger_connect(struct serio *serio, struct serio_dev *dev) +static void stinger_connect(struct serio *serio, struct serio_driver *drv) { struct stinger *stinger; int i; @@ -172,7 +174,7 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev) stinger->dev.private = stinger; serio->private = stinger; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(stinger); return; } @@ -187,10 +189,14 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev stinger_dev = { - .interrupt = stinger_interrupt, - .connect = stinger_connect, - .disconnect = stinger_disconnect, +static struct serio_driver stinger_drv = { + .driver = { + .name = "stinger", + }, + .description = DRIVER_DESC, + .interrupt = stinger_interrupt, + .connect = stinger_connect, + .disconnect = stinger_disconnect, }; /* @@ -199,13 +205,13 @@ static struct serio_dev stinger_dev = { int __init stinger_init(void) { - serio_register_device(&stinger_dev); + serio_register_driver(&stinger_drv); return 0; } void __exit stinger_exit(void) { - serio_unregister_device(&stinger_dev); + serio_unregister_driver(&stinger_drv); } module_init(stinger_init); diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 6ed46ec46..e11d29148 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -322,7 +322,7 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev) tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) { - if (tmdc->abs[i] < 0) continue; + if (tmdc->abs[j][i] < 0) continue; set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit); tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8; tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248; diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 123ff5f9d..0e620cb88 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -44,17 +44,17 @@ MODULE_LICENSE("GPL"); static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs __initdata = 0; -module_param_array_named(map, tgfx, int, tgfx_nargs, 0); +module_param_array_named(map, tgfx, int, &tgfx_nargs, 0); MODULE_PARM_DESC(map, "Describes first set of devices (,,,.."); static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs_2 __initdata = 0; -module_param_array_named(map2, tgfx_2, int, tgfx_nargs_2, 0); +module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0); MODULE_PARM_DESC(map2, "Describes second set of devices"); static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 }; static int tgfx_nargs_3 __initdata = 0; -module_param_array_named(map3, tgfx_3, int, tgfx_nargs_3, 0); +module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0); MODULE_PARM_DESC(map3, "Describes third set of devices"); __obsolete_setup("tgfx="); diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index eb5c935a6..909b6b54a 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -187,7 +187,7 @@ static void twidjoy_disconnect(struct serio *serio) * it as an input device. */ -static void twidjoy_connect(struct serio *serio, struct serio_dev *dev) +static void twidjoy_connect(struct serio *serio, struct serio_driver *drv) { struct twidjoy_button_spec *bp; struct twidjoy *twidjoy; @@ -232,7 +232,7 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev) twidjoy->dev.private = twidjoy; serio->private = twidjoy; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(twidjoy); return; } @@ -246,10 +246,14 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev twidjoy_dev = { - .interrupt = twidjoy_interrupt, - .connect = twidjoy_connect, - .disconnect = twidjoy_disconnect, +static struct serio_driver twidjoy_drv = { + .driver = { + .name = "twidjoy", + }, + .description = DRIVER_DESC, + .interrupt = twidjoy_interrupt, + .connect = twidjoy_connect, + .disconnect = twidjoy_disconnect, }; /* @@ -258,13 +262,13 @@ static struct serio_dev twidjoy_dev = { int __init twidjoy_init(void) { - serio_register_device(&twidjoy_dev); + serio_register_driver(&twidjoy_drv); return 0; } void __exit twidjoy_exit(void) { - serio_unregister_device(&twidjoy_dev); + serio_unregister_driver(&twidjoy_drv); } module_init(twidjoy_init); diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 32ec90e81..5f19b2a51 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -35,8 +35,10 @@ #include #include +#define DRIVER_DESC "Logitech WingMan Warrior joystick driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -139,7 +141,7 @@ static void warrior_disconnect(struct serio *serio) * it as an input device. */ -static void warrior_connect(struct serio *serio, struct serio_dev *dev) +static void warrior_connect(struct serio *serio, struct serio_driver *drv) { struct warrior *warrior; int i; @@ -185,7 +187,7 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev) serio->private = warrior; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(warrior); return; } @@ -199,10 +201,14 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev warrior_dev = { - .interrupt = warrior_interrupt, - .connect = warrior_connect, - .disconnect = warrior_disconnect, +static struct serio_driver warrior_drv = { + .driver = { + .name = "warrior", + }, + .description = DRIVER_DESC, + .interrupt = warrior_interrupt, + .connect = warrior_connect, + .disconnect = warrior_disconnect, }; /* @@ -211,13 +217,13 @@ static struct serio_dev warrior_dev = { int __init warrior_init(void) { - serio_register_device(&warrior_dev); + serio_register_driver(&warrior_drv); return 0; } void __exit warrior_exit(void) { - serio_unregister_device(&warrior_dev); + serio_unregister_driver(&warrior_drv); } module_init(warrior_init); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 00ec1f86a..ec97ae7d5 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -27,8 +27,10 @@ #include #include +#define DRIVER_DESC "AT and PS/2 keyboard driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static int atkbd_set = 2; @@ -47,6 +49,10 @@ static int atkbd_softrepeat; module_param_named(softrepeat, atkbd_softrepeat, bool, 0); MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat"); +static int atkbd_softraw = 1; +module_param_named(softraw, atkbd_softraw, bool, 0); +MODULE_PARM_DESC(softraw, "Use software generated rawmode"); + static int atkbd_scroll; module_param_named(scroll, atkbd_scroll, bool, 0); MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); @@ -164,36 +170,64 @@ static unsigned char atkbd_scroll_keys[5][2] = { { ATKBD_SCR_CLICK, 0x60 }, }; +#define ATKBD_FLAG_ACK 0 /* Waiting for ACK/NAK */ +#define ATKBD_FLAG_CMD 1 /* Waiting for command to finish */ +#define ATKBD_FLAG_CMD1 2 /* First byte of command response */ +#define ATKBD_FLAG_ENABLED 3 /* Waining for init to finish */ + /* * The atkbd control structure */ struct atkbd { - unsigned char keycode[512]; - struct input_dev dev; - struct serio *serio; + /* Written only during init */ char name[64]; char phys[32]; - unsigned short id; + struct serio *serio; + struct input_dev dev; + unsigned char set; - unsigned int translated:1; - unsigned int extra:1; - unsigned int write:1; + unsigned short id; + unsigned char keycode[512]; + unsigned char translated; + unsigned char extra; + unsigned char write; + + /* Protected by FLAG_ACK */ + unsigned char nak; + /* Protected by FLAG_CMD */ unsigned char cmdbuf[4]; unsigned char cmdcnt; - volatile signed char ack; - unsigned char emul; - unsigned int resend:1; - unsigned int release:1; - unsigned int bat_xl:1; - unsigned int enabled:1; + /* Accessed only from interrupt */ + unsigned char emul; + unsigned char resend; + unsigned char release; + unsigned char bat_xl; unsigned int last; unsigned long time; + + /* Ensures that only one command is executing at a time */ + struct semaphore cmd_sem; + + /* Used to signal completion from interrupt handler */ + wait_queue_head_t wait; + + /* Flags */ + unsigned long flags; +}; + +/* Work structure to schedule execution of a command */ +struct atkbd_work { + struct work_struct work; + struct atkbd *atkbd; + int command; + unsigned char param[0]; }; + static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value) { input_regs(dev, regs); @@ -224,7 +258,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, #if !defined(__i386__) && !defined (__x86_64__) if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { - printk("atkbd.c: frame/parity error: %02x\n", flags); + printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags); serio_write(serio, ATKBD_CMD_RESEND); atkbd->resend = 1; goto out; @@ -234,24 +268,46 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, atkbd->resend = 0; #endif - if (!atkbd->ack) + if (test_bit(ATKBD_FLAG_ACK, &atkbd->flags)) { switch (code) { case ATKBD_RET_ACK: - atkbd->ack = 1; - goto out; + atkbd->nak = 0; + if (atkbd->cmdcnt) { + set_bit(ATKBD_FLAG_CMD, &atkbd->flags); + set_bit(ATKBD_FLAG_CMD1, &atkbd->flags); + } + clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); + wake_up_interruptible(&atkbd->wait); + break; case ATKBD_RET_NAK: - atkbd->ack = -1; - goto out; + atkbd->nak = 1; + clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); + wake_up_interruptible(&atkbd->wait); + break; } + goto out; + } + + if (test_bit(ATKBD_FLAG_CMD, &atkbd->flags)) { + + if (atkbd->cmdcnt) + atkbd->cmdbuf[--atkbd->cmdcnt] = code; - if (atkbd->cmdcnt) { - atkbd->cmdbuf[--atkbd->cmdcnt] = code; + if (test_and_clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags) && atkbd->cmdcnt) + wake_up_interruptible(&atkbd->wait); + + if (!atkbd->cmdcnt) { + clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); + wake_up_interruptible(&atkbd->wait); + } goto out; } - if (!atkbd->enabled) + if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags)) goto out; + input_event(&atkbd->dev, EV_MSC, MSC_RAW, code); + if (atkbd->translated) { if (atkbd->emul || @@ -270,6 +326,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, switch (code) { case ATKBD_RET_BAT: + clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); serio_rescan(atkbd->serio); goto out; case ATKBD_RET_EMUL0: @@ -300,6 +357,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, code |= (atkbd->set != 3) ? 0x80 : 0x100; } + if (atkbd->keycode[code] != ATKBD_KEY_NULL) + input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code); + switch (atkbd->keycode[code]) { case ATKBD_KEY_NULL: break; @@ -372,83 +432,147 @@ out: * acknowledge. It doesn't handle resends according to the keyboard * protocol specs, because if these are needed, the keyboard needs * replacement anyway, and they only make a mess in the protocol. + * + * atkbd_sendbyte() can only be called from a process context */ static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte) { - int timeout = 20000; /* 200 msec */ - atkbd->ack = 0; - #ifdef ATKBD_DEBUG printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte); #endif - if (serio_write(atkbd->serio, byte)) - return -1; + atkbd->nak = 1; + set_bit(ATKBD_FLAG_ACK, &atkbd->flags); - while (!atkbd->ack && timeout--) udelay(10); + if (serio_write(atkbd->serio, byte) == 0) + wait_event_interruptible_timeout(atkbd->wait, + !test_bit(ATKBD_FLAG_ACK, &atkbd->flags), + msecs_to_jiffies(200)); - return -(atkbd->ack <= 0); + clear_bit(ATKBD_FLAG_ACK, &atkbd->flags); + return -atkbd->nak; } /* * atkbd_command() sends a command, and its parameters to the keyboard, * then waits for the response and puts it in the param array. + * + * atkbd_command() can only be called from a process context */ static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command) { - int timeout = 500000; /* 500 msec */ + int timeout; int send = (command >> 12) & 0xf; int receive = (command >> 8) & 0xf; + int rc = -1; int i; - atkbd->cmdcnt = receive; + timeout = msecs_to_jiffies(command == ATKBD_CMD_RESET_BAT ? 4000 : 500); - if (command == ATKBD_CMD_RESET_BAT) - timeout = 2000000; /* 2 sec */ + down(&atkbd->cmd_sem); + clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); if (receive && param) for (i = 0; i < receive; i++) atkbd->cmdbuf[(receive - 1) - i] = param[i]; + atkbd->cmdcnt = receive; + if (command & 0xff) if (atkbd_sendbyte(atkbd, command & 0xff)) - return (atkbd->cmdcnt = 0) - 1; + goto out; for (i = 0; i < send; i++) if (atkbd_sendbyte(atkbd, param[i])) - return (atkbd->cmdcnt = 0) - 1; - - while (atkbd->cmdcnt && timeout--) { - - if (atkbd->cmdcnt == 1 && - command == ATKBD_CMD_RESET_BAT && timeout > 100000) - timeout = 100000; + goto out; - if (atkbd->cmdcnt == 1 && command == ATKBD_CMD_GETID && - atkbd->cmdbuf[1] != 0xab && atkbd->cmdbuf[1] != 0xac) { + timeout = wait_event_interruptible_timeout(atkbd->wait, + !test_bit(ATKBD_FLAG_CMD1, &atkbd->flags), timeout); + + if (atkbd->cmdcnt && timeout > 0) { + if (command == ATKBD_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100) + timeout = msecs_to_jiffies(100); + + if (command == ATKBD_CMD_GETID && + atkbd->cmdbuf[receive - 1] != 0xab && atkbd->cmdbuf[receive - 1] != 0xac) { + /* + * Device behind the port is not a keyboard + * so we don't need to wait for the 2nd byte + * of ID response. + */ + clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); atkbd->cmdcnt = 0; - break; } - udelay(1); + wait_event_interruptible_timeout(atkbd->wait, + !test_bit(ATKBD_FLAG_CMD, &atkbd->flags), timeout); } if (param) for (i = 0; i < receive; i++) param[i] = atkbd->cmdbuf[(receive - 1) - i]; - if (command == ATKBD_CMD_RESET_BAT && atkbd->cmdcnt == 1) - atkbd->cmdcnt = 0; + if (atkbd->cmdcnt && (command != ATKBD_CMD_RESET_BAT || atkbd->cmdcnt != 1)) + goto out; + + rc = 0; + +out: + clear_bit(ATKBD_FLAG_CMD, &atkbd->flags); + clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags); + up(&atkbd->cmd_sem); + + return rc; +} + +/* + * atkbd_execute_scheduled_command() sends a command, previously scheduled by + * atkbd_schedule_command(), to the keyboard. + */ + +static void atkbd_execute_scheduled_command(void *data) +{ + struct atkbd_work *atkbd_work = data; + + atkbd_command(atkbd_work->atkbd, atkbd_work->param, atkbd_work->command); + + kfree(atkbd_work); +} + +/* + * atkbd_schedule_command() allows to schedule delayed execution of a keyboard + * command and can be used to issue a command from an interrupt or softirq + * context. + */ + +static int atkbd_schedule_command(struct atkbd *atkbd, unsigned char *param, int command) +{ + struct atkbd_work *atkbd_work; + int send = (command >> 12) & 0xf; + int receive = (command >> 8) & 0xf; + + if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags)) + return -1; + + if (!(atkbd_work = kmalloc(sizeof(struct atkbd_work) + max(send, receive), GFP_ATOMIC))) + return -1; + + memset(atkbd_work, 0, sizeof(struct atkbd_work)); + atkbd_work->atkbd = atkbd; + atkbd_work->command = command; + memcpy(atkbd_work->param, param, send); + INIT_WORK(&atkbd_work->work, atkbd_execute_scheduled_command, atkbd_work); - if (atkbd->cmdcnt) { - atkbd->cmdcnt = 0; + if (!schedule_work(&atkbd_work->work)) { + kfree(atkbd_work); return -1; } return 0; } + /* * Event callback from the input module. Events that change the state of * the hardware are processed here. @@ -475,7 +599,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) | (test_bit(LED_NUML, dev->led) ? 2 : 0) | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); - atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS); + atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETLEDS); if (atkbd->extra) { param[0] = 0; @@ -484,7 +608,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); - atkbd_command(atkbd, param, ATKBD_CMD_EX_SETLEDS); + atkbd_schedule_command(atkbd, param, ATKBD_CMD_EX_SETLEDS); } return 0; @@ -500,7 +624,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co dev->rep[REP_PERIOD] = period[i]; dev->rep[REP_DELAY] = delay[j]; param[0] = i | (j << 5); - atkbd_command(atkbd, param, ATKBD_CMD_SETREP); + atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETREP); return 0; } @@ -672,6 +796,11 @@ static void atkbd_cleanup(struct serio *serio) static void atkbd_disconnect(struct serio *serio) { struct atkbd *atkbd = serio->private; + + clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + synchronize_kernel(); + flush_scheduled_work(); + input_unregister_device(&atkbd->dev); serio_close(serio); kfree(atkbd); @@ -684,7 +813,7 @@ static void atkbd_disconnect(struct serio *serio) * to the input module. */ -static void atkbd_connect(struct serio *serio, struct serio_dev *dev) +static void atkbd_connect(struct serio *serio, struct serio_driver *drv) { struct atkbd *atkbd; int i; @@ -693,6 +822,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) return; memset(atkbd, 0, sizeof(struct atkbd)); + init_MUTEX(&atkbd->cmd_sem); + init_waitqueue_head(&atkbd->wait); + switch (serio->type & SERIO_TYPE) { case SERIO_8042_XL: @@ -709,17 +841,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) return; } + if (!atkbd->write) + atkbd_softrepeat = 1; + if (atkbd_softrepeat) + atkbd_softraw = 1; + if (atkbd->write) { - atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); + atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP) | BIT(EV_MSC); atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - } else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + } else atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC); + atkbd->dev.mscbit[0] = atkbd_softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN); if (!atkbd_softrepeat) { atkbd->dev.rep[REP_DELAY] = 250; atkbd->dev.rep[REP_PERIOD] = 33; - } + } else atkbd_softraw = 1; - atkbd->ack = 1; atkbd->serio = serio; init_input_dev(&atkbd->dev); @@ -732,7 +869,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) serio->private = atkbd; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(atkbd); return; } @@ -754,8 +891,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) atkbd->id = 0xab00; } - atkbd->enabled = 1; - if (atkbd->extra) { atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); sprintf(atkbd->name, "AT Set 2 Extra keyboard"); @@ -797,6 +932,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) input_register_device(&atkbd->dev); + set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys); } @@ -808,10 +945,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = serio->private; - struct serio_dev *dev = serio->dev; + struct serio_driver *drv = serio->drv; unsigned char param[1]; - if (!dev) { + if (!drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } @@ -832,26 +969,32 @@ static int atkbd_reconnect(struct serio *serio) return -1; } + set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags); + return 0; } -static struct serio_dev atkbd_dev = { - .interrupt = atkbd_interrupt, - .connect = atkbd_connect, - .reconnect = atkbd_reconnect, - .disconnect = atkbd_disconnect, - .cleanup = atkbd_cleanup, +static struct serio_driver atkbd_drv = { + .driver = { + .name = "atkbd", + }, + .description = DRIVER_DESC, + .interrupt = atkbd_interrupt, + .connect = atkbd_connect, + .reconnect = atkbd_reconnect, + .disconnect = atkbd_disconnect, + .cleanup = atkbd_cleanup, }; int __init atkbd_init(void) { - serio_register_device(&atkbd_dev); + serio_register_driver(&atkbd_drv); return 0; } void __exit atkbd_exit(void) { - serio_unregister_device(&atkbd_dev); + serio_unregister_driver(&atkbd_drv); } module_init(atkbd_init); diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 8dc51e296..a04cf3efd 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -76,8 +76,10 @@ #include #include +#define DRIVER_DESC "LK keyboard driver" + MODULE_AUTHOR ("Jan-Benedict Glaw "); -MODULE_DESCRIPTION ("LK keyboard driver"); +MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE ("GPL"); /* @@ -622,7 +624,7 @@ lkkbd_reinit (void *data) * lkkbd_connect() probes for a LK keyboard and fills the necessary structures. */ static void -lkkbd_connect (struct serio *serio, struct serio_dev *dev) +lkkbd_connect (struct serio *serio, struct serio_driver *drv) { struct lkkbd *lk; int i; @@ -665,7 +667,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev) serio->private = lk; - if (serio_open (serio, dev)) { + if (serio_open (serio, drv)) { kfree (lk); return; } @@ -703,10 +705,14 @@ lkkbd_disconnect (struct serio *serio) kfree (lk); } -static struct serio_dev lkkbd_dev = { - .connect = lkkbd_connect, - .disconnect = lkkbd_disconnect, - .interrupt = lkkbd_interrupt, +static struct serio_driver lkkbd_drv = { + .driver = { + .name = "lkkbd", + }, + .description = DRIVER_DESC, + .connect = lkkbd_connect, + .disconnect = lkkbd_disconnect, + .interrupt = lkkbd_interrupt, }; /* @@ -715,14 +721,14 @@ static struct serio_dev lkkbd_dev = { int __init lkkbd_init (void) { - serio_register_device (&lkkbd_dev); + serio_register_driver(&lkkbd_drv); return 0; } void __exit lkkbd_exit (void) { - serio_unregister_device (&lkkbd_dev); + serio_unregister_driver(&lkkbd_drv); } module_init (lkkbd_init); diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index dc47acb0a..caa92dd8b 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -32,8 +32,10 @@ #include #include +#define DRIVER_DESC "Newton keyboard driver" + MODULE_AUTHOR("Justin Cormack "); -MODULE_DESCRIPTION("Newton keyboard driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); #define NKBD_KEY 0x7f @@ -82,7 +84,7 @@ irqreturn_t nkbd_interrupt(struct serio *serio, } -void nkbd_connect(struct serio *serio, struct serio_dev *dev) +void nkbd_connect(struct serio *serio, struct serio_driver *drv) { struct nkbd *nkbd; int i; @@ -106,7 +108,7 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev) nkbd->dev.private = nkbd; serio->private = nkbd; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(nkbd); return; } @@ -138,21 +140,25 @@ void nkbd_disconnect(struct serio *serio) kfree(nkbd); } -struct serio_dev nkbd_dev = { - .interrupt = nkbd_interrupt, - .connect = nkbd_connect, - .disconnect = nkbd_disconnect +struct serio_driver nkbd_drv = { + .driver = { + .name = "newtonkbd", + }, + .description = DRIVER_DESC, + .interrupt = nkbd_interrupt, + .connect = nkbd_connect, + .disconnect = nkbd_disconnect, }; int __init nkbd_init(void) { - serio_register_device(&nkbd_dev); + serio_register_driver(&nkbd_drv); return 0; } void __exit nkbd_exit(void) { - serio_unregister_device(&nkbd_dev); + serio_unregister_driver(&nkbd_drv); } module_init(nkbd_init); diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index c281e726b..7f0342c56 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -37,8 +37,10 @@ #include #include +#define DRIVER_DESC "Sun keyboard driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Sun keyboard driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static unsigned char sunkbd_keycode[128] = { @@ -221,7 +223,7 @@ static void sunkbd_reinit(void *data) * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures. */ -static void sunkbd_connect(struct serio *serio, struct serio_dev *dev) +static void sunkbd_connect(struct serio *serio, struct serio_driver *drv) { struct sunkbd *sunkbd; int i; @@ -257,7 +259,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev) serio->private = sunkbd; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(sunkbd); return; } @@ -301,10 +303,14 @@ static void sunkbd_disconnect(struct serio *serio) kfree(sunkbd); } -static struct serio_dev sunkbd_dev = { - .interrupt = sunkbd_interrupt, - .connect = sunkbd_connect, - .disconnect = sunkbd_disconnect +static struct serio_driver sunkbd_drv = { + .driver = { + .name = "sunkbd", + }, + .description = DRIVER_DESC, + .interrupt = sunkbd_interrupt, + .connect = sunkbd_connect, + .disconnect = sunkbd_disconnect, }; /* @@ -313,13 +319,13 @@ static struct serio_dev sunkbd_dev = { int __init sunkbd_init(void) { - serio_register_device(&sunkbd_dev); + serio_register_driver(&sunkbd_drv); return 0; } void __exit sunkbd_exit(void) { - serio_unregister_device(&sunkbd_dev); + serio_unregister_driver(&sunkbd_drv); } module_init(sunkbd_init); diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 56adfa1cc..eb8a9b72b 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -34,8 +34,10 @@ #include #include +#define DRIVER_DESC "XT keyboard driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("XT keyboard driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); #define XTKBD_EMUL0 0xe0 @@ -86,7 +88,7 @@ irqreturn_t xtkbd_interrupt(struct serio *serio, return IRQ_HANDLED; } -void xtkbd_connect(struct serio *serio, struct serio_dev *dev) +void xtkbd_connect(struct serio *serio, struct serio_driver *drv) { struct xtkbd *xtkbd; int i; @@ -111,7 +113,7 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev) serio->private = xtkbd; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(xtkbd); return; } @@ -143,21 +145,25 @@ void xtkbd_disconnect(struct serio *serio) kfree(xtkbd); } -struct serio_dev xtkbd_dev = { - .interrupt = xtkbd_interrupt, - .connect = xtkbd_connect, - .disconnect = xtkbd_disconnect +struct serio_driver xtkbd_drv = { + .driver = { + .name = "xtkbd", + }, + .description = DRIVER_DESC, + .interrupt = xtkbd_interrupt, + .connect = xtkbd_connect, + .disconnect = xtkbd_disconnect, }; int __init xtkbd_init(void) { - serio_register_device(&xtkbd_dev); + serio_register_driver(&xtkbd_drv); return 0; } void __exit xtkbd_exit(void) { - serio_unregister_device(&xtkbd_dev); + serio_unregister_driver(&xtkbd_drv); } module_init(xtkbd_init); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index d3e5d841e..a89050e12 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -14,7 +14,7 @@ config INPUT_MISC config INPUT_PCSPKR tristate "PC Speaker support" - depends on (ALPHA || X86 || X86_64 || MIPS) && INPUT && INPUT_MISC + depends on (ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES) && INPUT && INPUT_MISC help Say Y here if you want the standard PC Speaker to be used for bells and whistles. diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index b86acf04d..477579b9e 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -279,6 +279,9 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait) { struct uinput_device *udev = file->private_data; + if (!test_bit(UIST_CREATED, &(udev->state))) + return 0; + poll_wait(file, &udev->waitq, wait); if (udev->head != udev->tail) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 1274cb68b..070c58e33 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -30,8 +30,6 @@ config MOUSE_PS2 and a new verion of GPM at: http://www.geocities.com/dt_or/gpm/gpm.html to take advantage of the advanced features of the touchpad. - If you do not want install specialized drivers but want tapping - working please use option psmouse.proto=imps. If unsure, say Y. @@ -127,6 +125,6 @@ config MOUSE_VSXXXAA puck) or a VSXXX-GA (rectangular) mouse. Theses mice are typically used on DECstations or VAXstations, but can also be used on any box capable of RS232 (with some adaptor - described in the source file). This driver should, in theory, - also work with the digitizer DEC produced, but it isn't tested - with that (I don't have the hardware yet). + described in the source file). This driver also works with the + digitizer (VSXXX-AB) DEC produced. + diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 0063af037..6af1455fd 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) protocol = PSMOUSE_PS2TPP; } - } else if (get_model_info(model) != NULL) { + } else if (model_info != NULL) { param[0] = param[1] = param[2] = 0; ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */ diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 526a11e70..0c74918fe 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -107,11 +108,25 @@ static int pc110pad_open(struct input_dev *dev) return 0; } +/* + * We try to avoid enabling the hardware if it's not + * there, but we don't know how to test. But we do know + * that the PC110 is not a PCI system. So if we find any + * PCI devices in the machine, we don't have a PC110. + */ static int __init pc110pad_init(void) { - if (request_region(pc110pad_io, 4, "pc110pad")) - { - printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4); + struct pci_dev *dev; + + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + pci_dev_put(dev); + return -ENOENT; + } + + if (!request_region(pc110pad_io, 4, "pc110pad")) { + printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", + pc110pad_io, pc110pad_io + 4); return -EBUSY; } diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 0b3826724..7fbd926dd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -22,8 +22,10 @@ #include "synaptics.h" #include "logips2pp.h" +#define DRIVER_DESC "PS/2 mouse driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("PS/2 mouse driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static char *psmouse_proto; @@ -142,37 +144,67 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_PARITY ? " bad parity" : ""); - if (psmouse->acking) { - psmouse->ack = -1; - psmouse->acking = 0; - } - psmouse->pktcnt = 0; + psmouse->nak = 1; + clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); + clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); + wake_up_interruptible(&psmouse->wait); goto out; } - if (psmouse->acking) { + if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags)) { switch (data) { case PSMOUSE_RET_ACK: - psmouse->ack = 1; + psmouse->nak = 0; break; + case PSMOUSE_RET_NAK: - psmouse->ack = -1; + psmouse->nak = 1; break; + + /* + * Workaround for mice which don't ACK the Get ID command. + * These are valid mouse IDs that we recognize. + */ + case 0x00: + case 0x03: + case 0x04: + if (test_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags)) { + psmouse->nak = 0; + break; + } + /* Fall through */ default: - psmouse->ack = 1; /* Workaround for mice which don't ACK the Get ID command */ - if (psmouse->cmdcnt) - psmouse->cmdbuf[--psmouse->cmdcnt] = data; - break; + goto out; } - psmouse->acking = 0; - goto out; + + if (!psmouse->nak && psmouse->cmdcnt) { + set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); + set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags); + } + clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); + wake_up_interruptible(&psmouse->wait); + + if (data == PSMOUSE_RET_ACK || data == PSMOUSE_RET_NAK) + goto out; } - if (psmouse->cmdcnt) { - psmouse->cmdbuf[--psmouse->cmdcnt] = data; + if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) { + if (psmouse->cmdcnt) + psmouse->cmdbuf[--psmouse->cmdcnt] = data; + + if (test_and_clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags) && psmouse->cmdcnt) + wake_up_interruptible(&psmouse->wait); + + if (!psmouse->cmdcnt) { + clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); + wake_up_interruptible(&psmouse->wait); + } goto out; } + if (psmouse->state == PSMOUSE_INITIALIZING) + goto out; + if (psmouse->state == PSMOUSE_ACTIVATED && psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", @@ -238,78 +270,96 @@ out: * psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge. * It doesn't handle retransmission, though it could - because when there would * be need for retransmissions, the mouse has to be replaced anyway. + * + * psmouse_sendbyte() can only be called from a process context */ static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte) { - int timeout = 10000; /* 100 msec */ - psmouse->ack = 0; - psmouse->acking = 1; - - if (serio_write(psmouse->serio, byte)) { - psmouse->acking = 0; - return -1; - } + psmouse->nak = 1; + set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); - while (!psmouse->ack && timeout--) udelay(10); + if (serio_write(psmouse->serio, byte) == 0) + wait_event_interruptible_timeout(psmouse->wait, + !test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags), + msecs_to_jiffies(200)); - return -(psmouse->ack <= 0); + clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags); + return -psmouse->nak; } /* * psmouse_command() sends a command and its parameters to the mouse, * then waits for the response and puts it in the param array. + * + * psmouse_command() can only be called from a process context */ int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) { - int timeout = 500000; /* 500 msec */ + int timeout; int send = (command >> 12) & 0xf; int receive = (command >> 8) & 0xf; + int rc = -1; int i; - psmouse->cmdcnt = receive; + timeout = msecs_to_jiffies(command == PSMOUSE_CMD_RESET_BAT ? 4000 : 500); - if (command == PSMOUSE_CMD_RESET_BAT) - timeout = 4000000; /* 4 sec */ + clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); + if (command == PSMOUSE_CMD_GETID) + set_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags); - /* initialize cmdbuf with preset values from param */ - if (receive) - for (i = 0; i < receive; i++) - psmouse->cmdbuf[(receive - 1) - i] = param[i]; + if (receive && param) + for (i = 0; i < receive; i++) + psmouse->cmdbuf[(receive - 1) - i] = param[i]; + + psmouse->cmdcnt = receive; if (command & 0xff) if (psmouse_sendbyte(psmouse, command & 0xff)) - return (psmouse->cmdcnt = 0) - 1; + goto out; for (i = 0; i < send; i++) if (psmouse_sendbyte(psmouse, param[i])) - return (psmouse->cmdcnt = 0) - 1; - - while (psmouse->cmdcnt && timeout--) { - - if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT && - timeout > 100000) /* do not run in a endless loop */ - timeout = 100000; /* 1 sec */ + goto out; - if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_GETID && - psmouse->cmdbuf[1] != 0xab && psmouse->cmdbuf[1] != 0xac) { + timeout = wait_event_interruptible_timeout(psmouse->wait, + !test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags), timeout); + + if (psmouse->cmdcnt && timeout > 0) { + if (command == PSMOUSE_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100) + timeout = msecs_to_jiffies(100); + + if (command == PSMOUSE_CMD_GETID && + psmouse->cmdbuf[receive - 1] != 0xab && psmouse->cmdbuf[receive - 1] != 0xac) { + /* + * Device behind the port is not a keyboard + * so we don't need to wait for the 2nd byte + * of ID response. + */ + clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); psmouse->cmdcnt = 0; - break; } - udelay(1); + wait_event_interruptible_timeout(psmouse->wait, + !test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags), timeout); } - for (i = 0; i < receive; i++) - param[i] = psmouse->cmdbuf[(receive - 1) - i]; + if (param) + for (i = 0; i < receive; i++) + param[i] = psmouse->cmdbuf[(receive - 1) - i]; - if (psmouse->cmdcnt) - return (psmouse->cmdcnt = 0) - 1; + if (psmouse->cmdcnt && (command != PSMOUSE_CMD_RESET_BAT || psmouse->cmdcnt != 1)) + goto out; - return 0; -} + rc = 0; +out: + clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags); + clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags); + clear_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags); + return rc; +} /* * psmouse_sliced_command() sends an extended PS/2 command to the mouse @@ -394,6 +444,8 @@ static int im_explorer_detect(struct psmouse *psmouse) { unsigned char param[2]; + intellimouse_detect(psmouse); + param[0] = 200; psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE); param[0] = 200; @@ -597,6 +649,21 @@ static void psmouse_initialize(struct psmouse *psmouse) psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM); } +/* + * psmouse_set_state() sets new psmouse state and resets all flags and + * counters while holding serio lock so fighting with interrupt handler + * is not a concern. + */ + +static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) +{ + serio_pause_rx(psmouse->serio); + psmouse->state = new_state; + psmouse->pktcnt = psmouse->cmdcnt = psmouse->out_of_sync = 0; + psmouse->flags = 0; + serio_continue_rx(psmouse->serio); +} + /* * psmouse_activate() enables the mouse so that we get motion reports from it. */ @@ -606,9 +673,24 @@ static void psmouse_activate(struct psmouse *psmouse) if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys); - psmouse->state = PSMOUSE_ACTIVATED; + psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); +} + + +/* + * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion + * reports from it unless we explicitely request it. + */ + +static void psmouse_deactivate(struct psmouse *psmouse) +{ + if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE)) + printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", psmouse->serio->phys); + + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); } + /* * psmouse_cleanup() resets the mouse into power-on state. */ @@ -626,22 +708,21 @@ static void psmouse_cleanup(struct serio *serio) static void psmouse_disconnect(struct serio *serio) { - struct psmouse *psmouse = serio->private; + struct psmouse *psmouse, *parent; - psmouse->state = PSMOUSE_CMD_MODE; + psmouse = serio->private; + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - if (psmouse->ptport) { - if (psmouse->ptport->deactivate) - psmouse->ptport->deactivate(psmouse); - __serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */ - kfree(psmouse->ptport); - psmouse->ptport = NULL; + if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) { + parent = serio->parent->private; + if (parent->pt_deactivate) + parent->pt_deactivate(parent); } if (psmouse->disconnect) psmouse->disconnect(psmouse); - psmouse->state = PSMOUSE_IGNORE; + psmouse_set_state(psmouse, PSMOUSE_IGNORE); input_unregister_device(&psmouse->dev); serio_close(serio); @@ -652,39 +733,49 @@ static void psmouse_disconnect(struct serio *serio) * psmouse_connect() is a callback from the serio module when * an unhandled serio port is found. */ -static void psmouse_connect(struct serio *serio, struct serio_dev *dev) +static void psmouse_connect(struct serio *serio, struct serio_driver *drv) { - struct psmouse *psmouse; + struct psmouse *psmouse, *parent = NULL; if ((serio->type & SERIO_TYPE) != SERIO_8042 && (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU) return; + /* + * If this is a pass-through port deactivate parent so the device + * connected to this port can be successfully identified + */ + if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) { + parent = serio->parent->private; + psmouse_deactivate(parent); + } + if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) - return; + goto out; memset(psmouse, 0, sizeof(struct psmouse)); + init_waitqueue_head(&psmouse->wait); init_input_dev(&psmouse->dev); psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - psmouse->state = PSMOUSE_CMD_MODE; psmouse->serio = serio; psmouse->dev.private = psmouse; + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); serio->private = psmouse; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(psmouse); serio->private = NULL; - return; + goto out; } if (psmouse_probe(psmouse) < 0) { serio_close(serio); kfree(psmouse); serio->private = NULL; - return; + goto out; } psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); @@ -711,63 +802,88 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev) printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + psmouse_initialize(psmouse); - if (psmouse->ptport) { - printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys); - __serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */ - if (psmouse->ptport->activate) - psmouse->ptport->activate(psmouse); + if (parent && parent->pt_activate) + parent->pt_activate(parent); + + if (serio->child) { + /* + * Nothing to be done here, serio core will detect that + * the driver set serio->child and will register it for us. + */ + printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys); } psmouse_activate(psmouse); + +out: + /* If this is a pass-through port the parent awaits to be activated */ + if (parent) + psmouse_activate(parent); } static int psmouse_reconnect(struct serio *serio) { struct psmouse *psmouse = serio->private; - struct serio_dev *dev = serio->dev; + struct psmouse *parent = NULL; + struct serio_driver *drv = serio->drv; + int rc = -1; - if (!dev || !psmouse) { + if (!drv || !psmouse) { printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } - psmouse->state = PSMOUSE_CMD_MODE; - psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0; + if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) { + parent = serio->parent->private; + psmouse_deactivate(parent); + } + + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) - return -1; + goto out; } else if (psmouse_probe(psmouse) < 0 || psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) - return -1; + goto out; /* ok, the device type (and capabilities) match the old one, * we can continue using it, complete intialization */ + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + psmouse_initialize(psmouse); - if (psmouse->ptport) { - if (psmouse_reconnect(&psmouse->ptport->serio)) { - __serio_unregister_port(&psmouse->ptport->serio); - __serio_register_port(&psmouse->ptport->serio); - if (psmouse->ptport->activate) - psmouse->ptport->activate(psmouse); - } - } + if (parent && parent->pt_activate) + parent->pt_activate(parent); psmouse_activate(psmouse); - return 0; + rc = 0; + +out: + /* If this is a pass-through port the parent waits to be activated */ + if (parent) + psmouse_activate(parent); + + return rc; } -static struct serio_dev psmouse_dev = { - .interrupt = psmouse_interrupt, - .connect = psmouse_connect, - .reconnect = psmouse_reconnect, - .disconnect = psmouse_disconnect, - .cleanup = psmouse_cleanup, +static struct serio_driver psmouse_drv = { + .driver = { + .name = "psmouse", + }, + .description = DRIVER_DESC, + .interrupt = psmouse_interrupt, + .connect = psmouse_connect, + .reconnect = psmouse_reconnect, + .disconnect = psmouse_disconnect, + .cleanup = psmouse_cleanup, }; static inline void psmouse_parse_proto(void) @@ -787,13 +903,13 @@ static inline void psmouse_parse_proto(void) int __init psmouse_init(void) { psmouse_parse_proto(); - serio_register_device(&psmouse_dev); + serio_register_driver(&psmouse_drv); return 0; } void __exit psmouse_exit(void) { - serio_unregister_device(&psmouse_dev); + serio_unregister_driver(&psmouse_drv); } module_init(psmouse_init); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 47fbc48f6..20bbab42d 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -9,6 +9,7 @@ #define PSMOUSE_CMD_GETID 0x02f2 #define PSMOUSE_CMD_SETRATE 0x10f3 #define PSMOUSE_CMD_ENABLE 0x00f4 +#define PSMOUSE_CMD_DISABLE 0x00f5 #define PSMOUSE_CMD_RESET_DIS 0x00f6 #define PSMOUSE_CMD_RESET_BAT 0x02ff @@ -17,10 +18,17 @@ #define PSMOUSE_RET_ACK 0xfa #define PSMOUSE_RET_NAK 0xfe -/* psmouse states */ -#define PSMOUSE_CMD_MODE 0 -#define PSMOUSE_ACTIVATED 1 -#define PSMOUSE_IGNORE 2 +#define PSMOUSE_FLAG_ACK 0 /* Waiting for ACK/NAK */ +#define PSMOUSE_FLAG_CMD 1 /* Waiting for command to finish */ +#define PSMOUSE_FLAG_CMD1 2 /* Waiting for the first byte of command response */ +#define PSMOUSE_FLAG_WAITID 3 /* Command execiting is GET ID */ + +enum psmouse_state { + PSMOUSE_IGNORE, + PSMOUSE_INITIALIZING, + PSMOUSE_CMD_MODE, + PSMOUSE_ACTIVATED, +}; /* psmouse protocol handler return codes */ typedef enum { @@ -29,20 +37,10 @@ typedef enum { PSMOUSE_FULL_PACKET } psmouse_ret_t; -struct psmouse; - -struct psmouse_ptport { - struct serio serio; - - void (*activate)(struct psmouse *parent); - void (*deactivate)(struct psmouse *parent); -}; - struct psmouse { void *private; struct input_dev dev; struct serio *serio; - struct psmouse_ptport *ptport; char *vendor; char *name; unsigned char cmdbuf[8]; @@ -53,16 +51,22 @@ struct psmouse { unsigned char model; unsigned long last; unsigned long out_of_sync; - unsigned char state; - char acking; - volatile char ack; + enum psmouse_state state; + unsigned char nak; char error; char devname[64]; char phys[32]; + unsigned long flags; - psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); + /* Used to signal completion from interrupt handler */ + wait_queue_head_t wait; + + psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); int (*reconnect)(struct psmouse *psmouse); void (*disconnect)(struct psmouse *psmouse); + + void (*pt_activate)(struct psmouse *psmouse); + void (*pt_deactivate)(struct psmouse *psmouse); }; #define PSMOUSE_PS2 1 diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 9c97a0a40..e1db6e078 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -37,8 +37,10 @@ #include #include +#define DRIVER_DESC "Serial mouse driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Serial mouse driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse", @@ -237,7 +239,7 @@ static void sermouse_disconnect(struct serio *serio) * an unhandled serio port is found. */ -static void sermouse_connect(struct serio *serio, struct serio_dev *dev) +static void sermouse_connect(struct serio *serio, struct serio_driver *drv) { struct sermouse *sermouse; unsigned char c; @@ -279,7 +281,7 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev) sermouse->dev.id.product = c; sermouse->dev.id.version = 0x0100; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(sermouse); return; } @@ -289,21 +291,25 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev) printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys); } -static struct serio_dev sermouse_dev = { - .interrupt = sermouse_interrupt, - .connect = sermouse_connect, - .disconnect = sermouse_disconnect +static struct serio_driver sermouse_drv = { + .driver = { + .name = "sermouse", + }, + .description = DRIVER_DESC, + .interrupt = sermouse_interrupt, + .connect = sermouse_connect, + .disconnect = sermouse_disconnect, }; int __init sermouse_init(void) { - serio_register_device(&sermouse_dev); + serio_register_driver(&sermouse_drv); return 0; } void __exit sermouse_exit(void) { - serio_unregister_device(&sermouse_dev); + serio_unregister_driver(&sermouse_drv); } module_init(sermouse_init); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 2bd152fe0..101b80947 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -212,9 +212,9 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode) /***************************************************************************** * Synaptics pass-through PS/2 port support ****************************************************************************/ -static int synaptics_pt_write(struct serio *port, unsigned char c) +static int synaptics_pt_write(struct serio *serio, unsigned char c) { - struct psmouse *parent = port->driver; + struct psmouse *parent = serio->parent->private; char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ if (psmouse_sliced_command(parent, c)) @@ -233,22 +233,19 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet { struct psmouse *child = ptport->private; - if (child) { - if (child->state == PSMOUSE_ACTIVATED) { - serio_interrupt(ptport, packet[1], 0, NULL); - serio_interrupt(ptport, packet[4], 0, NULL); - serio_interrupt(ptport, packet[5], 0, NULL); - if (child->type >= PSMOUSE_GENPS) - serio_interrupt(ptport, packet[2], 0, NULL); - } else if (child->state != PSMOUSE_IGNORE) { - serio_interrupt(ptport, packet[1], 0, NULL); - } - } + if (child && child->state == PSMOUSE_ACTIVATED) { + serio_interrupt(ptport, packet[1], 0, NULL); + serio_interrupt(ptport, packet[4], 0, NULL); + serio_interrupt(ptport, packet[5], 0, NULL); + if (child->type >= PSMOUSE_GENPS) + serio_interrupt(ptport, packet[2], 0, NULL); + } else + serio_interrupt(ptport, packet[1], 0, NULL); } static void synaptics_pt_activate(struct psmouse *psmouse) { - struct psmouse *child = psmouse->ptport->serio.private; + struct psmouse *child = psmouse->serio->child->private; /* adjust the touchpad to child's choice of protocol */ if (child && child->type >= PSMOUSE_GENPS) { @@ -259,23 +256,25 @@ static void synaptics_pt_activate(struct psmouse *psmouse) static void synaptics_pt_create(struct psmouse *psmouse) { - struct psmouse_ptport *port; + struct serio *serio; - psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL); - if (!port) { + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!serio) { printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n"); return; } - memset(port, 0, sizeof(struct psmouse_ptport)); + memset(serio, 0, sizeof(struct serio)); + + serio->type = SERIO_PS_PSTHRU; + strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); + strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); + serio->write = synaptics_pt_write; + serio->parent = psmouse->serio; - port->serio.type = SERIO_PS_PSTHRU; - port->serio.name = "Synaptics pass-through"; - port->serio.phys = "synaptics-pt/serio0"; - port->serio.write = synaptics_pt_write; - port->serio.driver = psmouse; + psmouse->pt_activate = synaptics_pt_activate; - port->activate = synaptics_pt_activate; + psmouse->serio->child = serio; } /***************************************************************************** @@ -470,9 +469,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r if (unlikely(priv->pkt_type == SYN_NEWABS)) priv->pkt_type = synaptics_detect_pkt_type(psmouse); - if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet)) - synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet); - else + if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { + if (psmouse->serio->child) + synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet); + } else synaptics_process_packet(psmouse); return PSMOUSE_FULL_PACKET; diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index c26d907e8..3845ca458 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -82,8 +82,10 @@ #include #include +#define DRIVER_DESC "Serial DEC VSXXX-AA/GA mouse / DEC tablet driver" + MODULE_AUTHOR ("Jan-Benedict Glaw "); -MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"); +MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE ("GPL"); #undef VSXXXAA_DEBUG @@ -482,7 +484,7 @@ vsxxxaa_disconnect (struct serio *serio) } static void -vsxxxaa_connect (struct serio *serio, struct serio_dev *dev) +vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) { struct vsxxxaa *mouse; @@ -524,7 +526,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev) mouse->dev.id.bustype = BUS_RS232; mouse->serio = serio; - if (serio_open (serio, dev)) { + if (serio_open (serio, drv)) { kfree (mouse); return; } @@ -540,23 +542,27 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev) printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys); } -static struct serio_dev vsxxxaa_dev = { - .connect = vsxxxaa_connect, - .interrupt = vsxxxaa_interrupt, - .disconnect = vsxxxaa_disconnect, +static struct serio_driver vsxxxaa_drv = { + .driver = { + .name = "vsxxxaa", + }, + .description = DRIVER_DESC, + .connect = vsxxxaa_connect, + .interrupt = vsxxxaa_interrupt, + .disconnect = vsxxxaa_disconnect, }; int __init vsxxxaa_init (void) { - serio_register_device (&vsxxxaa_dev); + serio_register_driver(&vsxxxaa_drv); return 0; } void __exit vsxxxaa_exit (void) { - serio_unregister_device (&vsxxxaa_dev); + serio_unregister_driver(&vsxxxaa_drv); } module_init (vsxxxaa_init); diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index f266b7ef5..19dea5ed1 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -48,8 +48,15 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; module_param(yres, uint, 0); MODULE_PARM_DESC(yres, "Vertical screen resolution"); -struct mousedev_motion { +static unsigned tap_time = 200; +module_param(tap_time, uint, 0); +MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)"); + +struct mousedev_hw_data { int dx, dy, dz; + int x, y; + int abs_event; + unsigned long buttons; }; struct mousedev { @@ -61,22 +68,38 @@ struct mousedev { struct list_head list; struct input_handle handle; - struct mousedev_motion packet; - unsigned long buttons; + struct mousedev_hw_data packet; unsigned int pkt_count; int old_x[4], old_y[4]; - unsigned int touch; + unsigned long touch; }; +enum mousedev_emul { + MOUSEDEV_EMUL_PS2, + MOUSEDEV_EMUL_IMPS, + MOUSEDEV_EMUL_EXPS +}; + +struct mousedev_motion { + int dx, dy, dz; + unsigned long buttons; +}; + +#define PACKET_QUEUE_LEN 16 struct mousedev_list { struct fasync_struct *fasync; struct mousedev *mousedev; struct list_head node; - int dx, dy, dz; - unsigned long buttons; + + struct mousedev_motion packets[PACKET_QUEUE_LEN]; + unsigned int head, tail; + spinlock_t packet_lock; + int pos_x, pos_y; + signed char ps2[6]; unsigned char ready, buffer, bufsiz; - unsigned char mode, imexseq, impsseq; + unsigned char imexseq, impsseq; + enum mousedev_emul mode; }; #define MOUSEDEV_SEQ_LEN 6 @@ -119,15 +142,19 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, case ABS_X: size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; if (size == 0) size = xres; - mousedev->packet.dx = (value * xres - mousedev->old_x[0]) / size; - mousedev->old_x[0] = mousedev->packet.dx * size; + if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X]; + if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X]; + mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; + mousedev->packet.abs_event = 1; break; case ABS_Y: size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; if (size == 0) size = yres; - mousedev->packet.dy = (value * yres - mousedev->old_y[0]) / size; - mousedev->old_y[0] = mousedev->packet.dy * size; + if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y]; + if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y]; + mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; + mousedev->packet.abs_event = 1; break; } } @@ -165,30 +192,82 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int } if (value) { - set_bit(index, &mousedev->buttons); - set_bit(index, &mousedev_mix.buttons); + set_bit(index, &mousedev->packet.buttons); + set_bit(index, &mousedev_mix.packet.buttons); } else { - clear_bit(index, &mousedev->buttons); - clear_bit(index, &mousedev_mix.buttons); + clear_bit(index, &mousedev->packet.buttons); + clear_bit(index, &mousedev_mix.packet.buttons); } } -static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet) +static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet) { struct mousedev_list *list; + struct mousedev_motion *p; + unsigned long flags; list_for_each_entry(list, &mousedev->list, node) { - list->dx += packet->dx; - list->dy += packet->dy; - list->dz += packet->dz; - list->buttons = mousedev->buttons; + spin_lock_irqsave(&list->packet_lock, flags); + + p = &list->packets[list->head]; + if (list->ready && p->buttons != packet->buttons) { + unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN; + if (new_head != list->tail) { + p = &list->packets[list->head = new_head]; + memset(p, 0, sizeof(struct mousedev_motion)); + } + } + + if (packet->abs_event) { + p->dx += packet->x - list->pos_x; + p->dy += packet->y - list->pos_y; + list->pos_x = packet->x; + list->pos_y = packet->y; + } + + list->pos_x += packet->dx; + list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x); + list->pos_y += packet->dy; + list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y); + + p->dx += packet->dx; + p->dy += packet->dy; + p->dz += packet->dz; + p->buttons = mousedev->packet.buttons; + list->ready = 1; + + spin_unlock_irqrestore(&list->packet_lock, flags); kill_fasync(&list->fasync, SIGIO, POLL_IN); } wake_up_interruptible(&mousedev->wait); } +static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) +{ + if (!value) { + if (mousedev->touch && + time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) { + /* + * Toggle left button to emulate tap. + * We rely on the fact that mousedev_mix always has 0 + * motion packet so we won't mess current position. + */ + set_bit(0, &mousedev->packet.buttons); + set_bit(0, &mousedev_mix.packet.buttons); + mousedev_notify_readers(mousedev, &mousedev_mix.packet); + mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet); + clear_bit(0, &mousedev->packet.buttons); + clear_bit(0, &mousedev_mix.packet.buttons); + } + mousedev->touch = mousedev->pkt_count = 0; + } + else + if (!mousedev->touch) + mousedev->touch = jiffies; +} + static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { struct mousedev *mousedev = handle->private; @@ -212,12 +291,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig case EV_KEY: if (value != 2) { - if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) { - /* Handle touchpad data */ - mousedev->touch = value; - if (!mousedev->touch) - mousedev->pkt_count = 0; - } + if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) + mousedev_touchpad_touch(mousedev, value); else mousedev_key_event(mousedev, code, value); } @@ -237,7 +312,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig mousedev_notify_readers(mousedev, &mousedev->packet); mousedev_notify_readers(&mousedev_mix, &mousedev->packet); - memset(&mousedev->packet, 0, sizeof(struct mousedev_motion)); + mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0; + mousedev->packet.abs_event = 0; } break; } @@ -253,8 +329,6 @@ static int mousedev_fasync(int fd, struct file *file, int on) static void mousedev_free(struct mousedev *mousedev) { - devfs_remove("input/mouse%d", mousedev->minor); - class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); mousedev_table[mousedev->minor] = NULL; kfree(mousedev); } @@ -322,6 +396,9 @@ static int mousedev_open(struct inode * inode, struct file * file) return -ENOMEM; memset(list, 0, sizeof(struct mousedev_list)); + spin_lock_init(&list->packet_lock); + list->pos_x = xres / 2; + list->pos_y = yres / 2; list->mousedev = mousedev_table[i]; list_add_tail(&list->node, &mousedev_table[i]->list); file->private_data = list; @@ -341,32 +418,56 @@ static int mousedev_open(struct inode * inode, struct file * file) return 0; } -static void mousedev_packet(struct mousedev_list *list, unsigned char off) +static inline int mousedev_limit_delta(int delta, int limit) { - list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07); - list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx)); - list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy)); - list->dx -= list->ps2[off + 1]; - list->dy -= list->ps2[off + 2]; - list->bufsiz = off + 3; - - if (list->mode == 2) { - list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz)); - list->dz -= list->ps2[off + 3]; - list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); - list->bufsiz++; - } else { - list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1); + return delta > limit ? limit : (delta < -limit ? -limit : delta); +} + +static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data) +{ + struct mousedev_motion *p; + unsigned long flags; + + spin_lock_irqsave(&list->packet_lock, flags); + p = &list->packets[list->tail]; + + ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); + ps2_data[1] = mousedev_limit_delta(p->dx, 127); + ps2_data[2] = mousedev_limit_delta(p->dy, 127); + p->dx -= ps2_data[1]; + p->dy -= ps2_data[2]; + + switch (list->mode) { + case MOUSEDEV_EMUL_EXPS: + ps2_data[3] = mousedev_limit_delta(p->dz, 127); + p->dz -= ps2_data[3]; + ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); + list->bufsiz = 4; + break; + + case MOUSEDEV_EMUL_IMPS: + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); + ps2_data[3] = mousedev_limit_delta(p->dz, 127); + p->dz -= ps2_data[3]; + list->bufsiz = 4; + break; + + case MOUSEDEV_EMUL_PS2: + default: + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); + p->dz = 0; + list->bufsiz = 3; + break; } - if (list->mode == 1) { - list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); - list->dz -= list->ps2[off + 3]; - list->bufsiz++; + if (!p->dx && !p->dy && !p->dz) { + if (list->tail != list->head) + list->tail = (list->tail + 1) % PACKET_QUEUE_LEN; + if (list->tail == list->head) + list->ready = 0; } - if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0; - list->buffer = list->bufsiz; + spin_unlock_irqrestore(&list->packet_lock, flags); } @@ -384,31 +485,31 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si if (c == mousedev_imex_seq[list->imexseq]) { if (++list->imexseq == MOUSEDEV_SEQ_LEN) { list->imexseq = 0; - list->mode = 2; + list->mode = MOUSEDEV_EMUL_EXPS; } } else list->imexseq = 0; if (c == mousedev_imps_seq[list->impsseq]) { if (++list->impsseq == MOUSEDEV_SEQ_LEN) { list->impsseq = 0; - list->mode = 1; + list->mode = MOUSEDEV_EMUL_IMPS; } } else list->impsseq = 0; list->ps2[0] = 0xfa; - list->bufsiz = 1; switch (c) { case 0xeb: /* Poll */ - mousedev_packet(list, 1); + mousedev_packet(list, &list->ps2[1]); + list->bufsiz++; /* account for leading ACK */ break; case 0xf2: /* Get ID */ switch (list->mode) { - case 0: list->ps2[1] = 0; break; - case 1: list->ps2[1] = 3; break; - case 2: list->ps2[1] = 4; break; + case MOUSEDEV_EMUL_PS2: list->ps2[1] = 0; break; + case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break; + case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break; } list->bufsiz = 2; break; @@ -419,13 +520,15 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si break; case 0xff: /* Reset */ - list->impsseq = 0; - list->imexseq = 0; - list->mode = 0; - list->ps2[1] = 0xaa; - list->ps2[2] = 0x00; + list->impsseq = list->imexseq = 0; + list->mode = MOUSEDEV_EMUL_PS2; + list->ps2[1] = 0xaa; list->ps2[2] = 0x00; list->bufsiz = 3; break; + + default: + list->bufsiz = 1; + break; } list->buffer = list->bufsiz; @@ -446,13 +549,19 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK)) return -EAGAIN; - retval = wait_event_interruptible(list->mousedev->wait, list->ready || list->buffer); + retval = wait_event_interruptible(list->mousedev->wait, + !list->mousedev->exist || list->ready || list->buffer); if (retval) return retval; - if (!list->buffer && list->ready) - mousedev_packet(list, 0); + if (!list->mousedev->exist) + return -ENODEV; + + if (!list->buffer && list->ready) { + mousedev_packet(list, list->ps2); + list->buffer = list->bufsiz; + } if (count > list->buffer) count = list->buffer; @@ -529,6 +638,8 @@ static void mousedev_disconnect(struct input_handle *handle) { struct mousedev *mousedev = handle->private; + class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor)); + devfs_remove("input/mouse%d", mousedev->minor); mousedev->exist = 0; if (mousedev->open) { diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index cd74954bd..d9addd820 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -20,7 +20,7 @@ config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y select SERIO - depends on !PARISC + depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K ---help--- i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, @@ -130,3 +130,19 @@ config SERIO_MACEPS2 To compile this driver as a module, choose M here: the module will be called maceps2. + +config SERIO_RAW + tristate "Raw access to serio ports" + depends on SERIO + help + Say Y here if you want to have raw access to serio ports, such as + AUX ports on i8042 keyboard controller. Each serio port that is + bound to this driver will be accessible via a char device with + major 10 and dynamically allocated minor. The driver will try + allocating minor 1 (that historically corresponds to /dev/psaux) + first. To bind this driver to a serio port use sysfs interface: + + echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver + + To compile this driver as a module, choose M here: the + module will be called serio_raw. diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index a47dec255..cf52b6141 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o +obj-$(CONFIG_SERIO_RAW) += serio_raw.o diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 6a780c10f..4b3b5135f 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -29,7 +29,7 @@ #define KMI_BASE (kmi->base) struct amba_kmi_port { - struct serio io; + struct serio *io; struct clk *clk; unsigned char *base; unsigned int irq; @@ -44,7 +44,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) int handled = IRQ_NONE; while (status & KMIIR_RXINTR) { - serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs); + serio_interrupt(kmi->io, readb(KMIDATA), 0, regs); status = readb(KMIIR); handled = IRQ_HANDLED; } @@ -54,7 +54,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) static int amba_kmi_write(struct serio *io, unsigned char val) { - struct amba_kmi_port *kmi = io->driver; + struct amba_kmi_port *kmi = io->port_data; unsigned int timeleft = 10000; /* timeout in 100ms */ while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) @@ -68,7 +68,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val) static int amba_kmi_open(struct serio *io) { - struct amba_kmi_port *kmi = io->driver; + struct amba_kmi_port *kmi = io->port_data; unsigned int divisor; int ret; @@ -105,7 +105,7 @@ static int amba_kmi_open(struct serio *io) static void amba_kmi_close(struct serio *io) { - struct amba_kmi_port *kmi = io->driver; + struct amba_kmi_port *kmi = io->port_data; writeb(0, KMICR); @@ -117,6 +117,7 @@ static void amba_kmi_close(struct serio *io) static int amba_kmi_probe(struct amba_device *dev, void *id) { struct amba_kmi_port *kmi; + struct serio *io; int ret; ret = amba_request_regions(dev, NULL); @@ -124,21 +125,25 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) return ret; kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL); - if (!kmi) { + io = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!kmi || !io) { ret = -ENOMEM; goto out; } memset(kmi, 0, sizeof(struct amba_kmi_port)); - - kmi->io.type = SERIO_8042; - kmi->io.write = amba_kmi_write; - kmi->io.open = amba_kmi_open; - kmi->io.close = amba_kmi_close; - kmi->io.name = dev->dev.bus_id; - kmi->io.phys = dev->dev.bus_id; - kmi->io.driver = kmi; - + memset(io, 0, sizeof(struct serio)); + + io->type = SERIO_8042; + io->write = amba_kmi_write; + io->open = amba_kmi_open; + io->close = amba_kmi_close; + strlcpy(io->name, dev->dev.bus_id, sizeof(io->name)); + strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys)); + io->port_data = kmi; + io->dev.parent = &dev->dev; + + kmi->io = io; kmi->base = ioremap(dev->res.start, KMI_SIZE); if (!kmi->base) { ret = -ENOMEM; @@ -154,13 +159,14 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) kmi->irq = dev->irq[0]; amba_set_drvdata(dev, kmi); - serio_register_port(&kmi->io); + serio_register_port(kmi->io); return 0; unmap: iounmap(kmi->base); out: kfree(kmi); + kfree(io); amba_release_regions(dev); return ret; } @@ -171,7 +177,7 @@ static int amba_kmi_remove(struct amba_device *dev) amba_set_drvdata(dev, NULL); - serio_unregister_port(&kmi->io); + serio_unregister_port(kmi->io); clk_put(kmi->clk); iounmap(kmi->base); kfree(kmi); @@ -184,7 +190,7 @@ static int amba_kmi_resume(struct amba_device *dev) struct amba_kmi_port *kmi = amba_get_drvdata(dev); /* kick the serio layer to rescan this port */ - serio_rescan(&kmi->io); + serio_reconnect(kmi->io); return 0; } @@ -214,7 +220,7 @@ static int __init amba_kmi_init(void) static void __exit amba_kmi_exit(void) { - return amba_driver_unregister(&ambakmi_driver); + amba_driver_unregister(&ambakmi_driver); } module_init(amba_kmi_init); diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 2234ff39d..ee785460b 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -43,9 +44,6 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("82C710 C&T mouse port chip driver"); MODULE_LICENSE("GPL"); -static char ct82c710_name[] = "C&T 82c710 mouse port"; -static char ct82c710_phys[16]; - /* * ct82c710 interface */ @@ -61,10 +59,22 @@ static char ct82c710_phys[16]; #define CT82C710_IRQ 12 -static int ct82c710_data; -static int ct82c710_status; +#define CT82C710_DATA ct82c710_iores.start +#define CT82C710_STATUS (ct82c710_iores.start + 1) + +static struct serio *ct82c710_port; +static struct platform_device *ct82c710_device; +static struct resource ct82c710_iores; + +/* + * Interrupt handler for the 82C710 mouse port. A character + * is waiting in the 82C710. + */ -static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs); +static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs) +{ + return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs); +} /* * Wait for device to send output char and flush any input char. @@ -74,10 +84,10 @@ static int ct82c170_wait(void) { int timeout = 60000; - while ((inb(ct82c710_status) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE)) + while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE)) != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) { - if (inb_p(ct82c710_status) & CT82C710_RX_FULL) inb_p(ct82c710_data); + if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA); udelay(1); timeout--; @@ -91,7 +101,7 @@ static void ct82c710_close(struct serio *serio) if (ct82c170_wait()) printk(KERN_WARNING "ct82c710.c: Device busy in close()\n"); - outb_p(inb_p(ct82c710_status) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), ct82c710_status); + outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS); if (ct82c170_wait()) printk(KERN_WARNING "ct82c710.c: Device busy in close()\n"); @@ -106,21 +116,21 @@ static int ct82c710_open(struct serio *serio) if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL)) return -1; - status = inb_p(ct82c710_status); + status = inb_p(CT82C710_STATUS); status |= (CT82C710_ENABLE | CT82C710_RESET); - outb_p(status, ct82c710_status); + outb_p(status, CT82C710_STATUS); status &= ~(CT82C710_RESET); - outb_p(status, ct82c710_status); + outb_p(status, CT82C710_STATUS); status |= CT82C710_INTS_ON; - outb_p(status, ct82c710_status); /* Enable interrupts */ + outb_p(status, CT82C710_STATUS); /* Enable interrupts */ while (ct82c170_wait()) { printk(KERN_ERR "ct82c710: Device busy in open()\n"); status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); - outb_p(status, ct82c710_status); + outb_p(status, CT82C710_STATUS); free_irq(CT82C710_IRQ, NULL); return -1; } @@ -135,30 +145,10 @@ static int ct82c710_open(struct serio *serio) static int ct82c710_write(struct serio *port, unsigned char c) { if (ct82c170_wait()) return -1; - outb_p(c, ct82c710_data); + outb_p(c, CT82C710_DATA); return 0; } -static struct serio ct82c710_port = -{ - .type = SERIO_8042, - .name = ct82c710_name, - .phys = ct82c710_phys, - .write = ct82c710_write, - .open = ct82c710_open, - .close = ct82c710_close, -}; - -/* - * Interrupt handler for the 82C710 mouse port. A character - * is waiting in the 82C710. - */ - -static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs) -{ - return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs); -} - /* * See if we can find a 82C710 device. Read mouse address. */ @@ -175,36 +165,60 @@ static int __init ct82c710_probe(void) return -1; /* No: no 82C710 here */ outb_p(0x0d, 0x390); /* Write index */ - ct82c710_data = inb_p(0x391) << 2; /* Get mouse I/O address */ - ct82c710_status = ct82c710_data + 1; + ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */ + ct82c710_iores.end = ct82c710_iores.start + 1; + ct82c710_iores.flags = IORESOURCE_IO; outb_p(0x0f, 0x390); outb_p(0x0f, 0x391); /* Close config mode */ return 0; } +static struct serio * __init ct82c710_allocate_port(void) +{ + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->open = ct82c710_open; + serio->close = ct82c710_close; + serio->write = ct82c710_write; + serio->dev.parent = &ct82c710_device->dev; + strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name)); + snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA); + } + + return serio; +} + int __init ct82c710_init(void) { if (ct82c710_probe()) return -ENODEV; - if (request_region(ct82c710_data, 2, "ct82c710")) - return -EBUSY; + ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1); + if (IS_ERR(ct82c710_device)) + return PTR_ERR(ct82c710_device); - sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data); + if (!(ct82c710_port = ct82c710_allocate_port())) { + platform_device_unregister(ct82c710_device); + return -ENOMEM; + } - serio_register_port(&ct82c710_port); + serio_register_port(ct82c710_port); - printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n", - ct82c710_data, CT82C710_IRQ); + printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n", + CT82C710_DATA, CT82C710_IRQ); return 0; } void __exit ct82c710_exit(void) { - serio_unregister_port(&ct82c710_port); - release_region(ct82c710_data, 2); + serio_unregister_port(ct82c710_port); + platform_device_unregister(ct82c710_device); } module_init(ct82c710_init); diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 48a0ad587..cd9f987fb 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -6,7 +6,7 @@ * Copyright (c) 2002 Thibaut Varene * * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries + * Copyright (c) 1999 Alex deVries * Copyright (c) 1999-2000 Philipp Rumpf * Copyright (c) 2000 Xavier Debacker * Copyright (c) 2000-2001 Thomas Marteau @@ -91,7 +91,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs); struct gscps2port { struct list_head node; struct parisc_device *padev; - struct serio port; + struct serio *port; spinlock_t lock; char *addr; u8 act, append; /* position in buffer[] */ @@ -100,7 +100,6 @@ struct gscps2port { u8 str; } buffer[BUFFER_SIZE+1]; int id; - char name[32]; }; /* @@ -272,7 +271,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs) rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); - serio_interrupt(&ps2port->port, data, rxflags, regs); + serio_interrupt(ps2port->port, data, rxflags, regs); } /* while() */ @@ -288,7 +287,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs) static int gscps2_write(struct serio *port, unsigned char data) { - struct gscps2port *ps2port = port->driver; + struct gscps2port *ps2port = port->port_data; if (!gscps2_writeb_output(ps2port, data)) { printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data); @@ -304,7 +303,7 @@ static int gscps2_write(struct serio *port, unsigned char data) static int gscps2_open(struct serio *port) { - struct gscps2port *ps2port = port->driver; + struct gscps2port *ps2port = port->port_data; gscps2_reset(ps2port); @@ -319,7 +318,7 @@ static int gscps2_open(struct serio *port) static void gscps2_close(struct serio *port) { - struct gscps2port *ps2port = port->driver; + struct gscps2port *ps2port = port->port_data; gscps2_enable(ps2port, DISABLE); } @@ -343,7 +342,8 @@ static struct serio gscps2_serio_port = static int __init gscps2_probe(struct parisc_device *dev) { - struct gscps2port *ps2port; + struct gscps2port *ps2port; + struct serio *serio; unsigned long hpa = dev->hpa; int ret; @@ -355,34 +355,45 @@ static int __init gscps2_probe(struct parisc_device *dev) hpa += GSC_DINO_OFFSET; ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL); - if (!ps2port) - return -ENOMEM; + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!ps2port || !serio) { + ret = -ENOMEM; + goto fail_nomem; + } dev_set_drvdata(&dev->dev, ps2port); memset(ps2port, 0, sizeof(struct gscps2port)); + memset(serio, 0, sizeof(struct serio)); + ps2port->port = serio; ps2port->padev = dev; ps2port->addr = ioremap(hpa, GSC_STATUS + 4); spin_lock_init(&ps2port->lock); gscps2_reset(ps2port); - ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f; - snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s", - gscps2_serio_port.name, - (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" ); - - memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port)); - ps2port->port.driver = ps2port; - ps2port->port.name = ps2port->name; - ps2port->port.phys = dev->dev.bus_id; + ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f; + + snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", + (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); + strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + serio->idbus = BUS_GSC; + serio->idvendor = PCI_VENDOR_ID_HP; + serio->idproduct = 0x0001; + serio->idversion = 0x0010; + serio->type = SERIO_8042; + serio->write = gscps2_write; + serio->open = gscps2_open; + serio->close = gscps2_close; + serio->port_data = ps2port; + serio->dev.parent = &dev->dev; list_add_tail(&ps2port->node, &ps2port_list); ret = -EBUSY; - if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port)) + if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port)) goto fail_miserably; - if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) { + if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) { printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n", hpa, ps2port->id); ret = -ENODEV; @@ -395,12 +406,12 @@ static int __init gscps2_probe(struct parisc_device *dev) #endif printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n", - ps2port->name, + ps2port->port->name, ps2port->addr, ps2port->padev->irq, - ps2port->port.phys); + ps2port->port->phys); - serio_register_port(&ps2port->port); + serio_register_port(ps2port->port); return 0; @@ -411,7 +422,10 @@ fail_miserably: list_del(&ps2port->node); iounmap(ps2port->addr); release_mem_region(dev->hpa, GSC_STATUS + 4); + +fail_nomem: kfree(ps2port); + kfree(serio); return ret; } @@ -424,7 +438,7 @@ static int __devexit gscps2_remove(struct parisc_device *dev) { struct gscps2port *ps2port = dev_get_drvdata(&dev->dev); - serio_unregister_port(&ps2port->port); + serio_unregister_port(ps2port->port); free_irq(dev->irq, ps2port); gscps2_flush(ps2port); list_del(&ps2port->node); diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 2cba08840..0d5716a21 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -35,6 +35,7 @@ # define I8042_AUX_IRQ 12 #endif + /* * Register numbers. */ @@ -65,13 +66,38 @@ static inline void i8042_write_command(int val) return; } +#if defined(__i386__) + +#include + +static struct dmi_system_id __initdata i8042_dmi_table[] = { + { + .ident = "Compaq Proliant 8500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), + DMI_MATCH(DMI_PRODUCT_VERSION, "8500"), + }, + }, + { + .ident = "Compaq Proliant DL760", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), + DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"), + }, + }, + { } +}; +#endif + static inline int i8042_platform_init(void) { /* * On ix86 platforms touching the i8042 data register region can do really * bad things. Because of this the region is always reserved on ix86 boxes. */ -#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) +#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) && !defined (CONFIG_PPC64) if (!request_region(I8042_DATA_REG, 16, "i8042")) return -1; #endif @@ -79,12 +105,24 @@ static inline int i8042_platform_init(void) #if !defined(__i386__) && !defined(__x86_64__) i8042_reset = 1; #endif + +#if defined(__i386__) + if (dmi_check_system(i8042_dmi_table)) + i8042_noloop = 1; +#endif + +#if defined(CONFIG_PPC64) + if (check_legacy_ioport(I8042_DATA_REG)) + return -1; + if (!request_region(I8042_DATA_REG, 16, "i8042")) + return -1; +#endif return 0; } static inline void i8042_platform_exit(void) { -#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) +#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(CONFIG_PPC64) release_region(I8042_DATA_REG, 16); #endif } diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index e0b8f3219..da2a19812 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -18,7 +18,7 @@ static int i8042_aux_irq = -1; #define I8042_AUX_PHYS_DESC "sparcps2/serio1" #define I8042_MUX_PHYS_DESC "sparcps2/serio%d" -static unsigned long kbd_iobase; +static void __iomem *kbd_iobase; #define I8042_COMMAND_REG (kbd_iobase + 0x64UL) #define I8042_DATA_REG (kbd_iobase + 0x60UL) @@ -64,7 +64,7 @@ static int i8042_platform_init(void) if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { /* Hardcoded values for MrCoffee. */ i8042_kbd_irq = i8042_aux_irq = 13 | 0x20; - kbd_iobase = (unsigned long) ioremap(0x71300060, 8); + kbd_iobase = ioremap(0x71300060, 8); if (!kbd_iobase) return -1; } else { @@ -85,7 +85,7 @@ static int i8042_platform_init(void) if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) || !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) { i8042_kbd_irq = child->irqs[0]; - kbd_iobase = (unsigned long) + kbd_iobase = ioremap(child->resource[0].start, 8); } if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) || @@ -109,7 +109,7 @@ static int i8042_platform_init(void) static inline void i8042_platform_exit(void) { #ifdef CONFIG_PCI - iounmap((void *)kbd_iobase); + iounmap(kbd_iobase); #endif } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index e9d8dabd1..6730e1ae0 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1,7 +1,7 @@ /* * i8042 keyboard and mouse controller driver for Linux * - * Copyright (c) 1999-2002 Vojtech Pavlik + * Copyright (c) 1999-2004 Vojtech Pavlik */ /* @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -52,6 +53,10 @@ static unsigned int i8042_dumbkbd; module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); +static unsigned int i8042_noloop; +module_param_named(noloop, i8042_noloop, bool, 0); +MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port"); + __obsolete_setup("i8042_noaux"); __obsolete_setup("i8042_nomux"); __obsolete_setup("i8042_unlock"); @@ -70,19 +75,35 @@ struct i8042_values { unsigned char irqen; unsigned char exists; signed char mux; - unsigned char *name; - unsigned char *phys; + char name[8]; +}; + +static struct i8042_values i8042_kbd_values = { + .disable = I8042_CTR_KBDDIS, + .irqen = I8042_CTR_KBDINT, + .mux = -1, + .name = "KBD", }; -static struct serio i8042_kbd_port; -static struct serio i8042_aux_port; +static struct i8042_values i8042_aux_values = { + .disable = I8042_CTR_AUXDIS, + .irqen = I8042_CTR_AUXINT, + .mux = -1, + .name = "AUX", +}; + +static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS]; + +static struct serio *i8042_kbd_port; +static struct serio *i8042_aux_port; +static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS]; static unsigned char i8042_initial_ctr; static unsigned char i8042_ctr; static unsigned char i8042_mux_open; static unsigned char i8042_mux_present; -static unsigned char i8042_sysdev_initialized; static struct pm_dev *i8042_pm_dev; -struct timer_list i8042_timer; +static struct timer_list i8042_timer; +static struct platform_device *i8042_platform_device; /* * Shared IRQ's require a device pointer, but this driver doesn't support @@ -95,6 +116,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * be ready for reading values from it / writing values to it. + * Called always with i8042_lock held. */ static int i8042_wait_read(void) @@ -131,6 +153,7 @@ static int i8042_flush(void) spin_lock_irqsave(&i8042_lock, flags); while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_SIZE)) { + udelay(50); data = i8042_read_data(); dbg("%02x <- i8042 (flush, %s)", data, i8042_read_status() & I8042_STR_AUXDATA ? "aux" : "kbd"); @@ -154,6 +177,9 @@ static int i8042_command(unsigned char *param, int command) unsigned long flags; int retval = 0, i = 0; + if (i8042_noloop && command == I8042_CMD_AUX_LOOP) + return -1; + spin_lock_irqsave(&i8042_lock, flags); retval = i8042_wait_write(); @@ -214,7 +240,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) static int i8042_aux_write(struct serio *port, unsigned char c) { - struct i8042_values *values = port->driver; + struct i8042_values *values = port->port_data; int retval; /* @@ -242,7 +268,7 @@ static int i8042_aux_write(struct serio *port, unsigned char c) static int i8042_activate_port(struct serio *port) { - struct i8042_values *values = port->driver; + struct i8042_values *values = port->port_data; i8042_flush(); @@ -270,7 +296,7 @@ static int i8042_activate_port(struct serio *port) static int i8042_open(struct serio *port) { - struct i8042_values *values = port->driver; + struct i8042_values *values = port->port_data; if (values->mux != -1) if (i8042_mux_open++) @@ -309,7 +335,7 @@ irq_fail: static void i8042_close(struct serio *port) { - struct i8042_values *values = port->driver; + struct i8042_values *values = port->port_data; if (values->mux != -1) if (--i8042_mux_open) @@ -327,52 +353,6 @@ static void i8042_close(struct serio *port) i8042_flush(); } -/* - * Structures for registering the devices in the serio.c module. - */ - -static struct i8042_values i8042_kbd_values = { - .irqen = I8042_CTR_KBDINT, - .disable = I8042_CTR_KBDDIS, - .name = "KBD", - .mux = -1, -}; - -static struct serio i8042_kbd_port = -{ - .type = SERIO_8042_XL, - .write = i8042_kbd_write, - .open = i8042_open, - .close = i8042_close, - .driver = &i8042_kbd_values, - .name = "i8042 Kbd Port", - .phys = I8042_KBD_PHYS_DESC, -}; - -static struct i8042_values i8042_aux_values = { - .irqen = I8042_CTR_AUXINT, - .disable = I8042_CTR_AUXDIS, - .name = "AUX", - .mux = -1, -}; - -static struct serio i8042_aux_port = -{ - .type = SERIO_8042, - .write = i8042_aux_write, - .open = i8042_open, - .close = i8042_close, - .driver = &i8042_aux_values, - .name = "i8042 Aux Port", - .phys = I8042_AUX_PHYS_DESC, -}; - -static struct i8042_values i8042_mux_values[4]; -static struct serio i8042_mux_port[4]; -static char i8042_mux_names[4][32]; -static char i8042_mux_short[4][16]; -static char i8042_mux_phys[4][32]; - /* * i8042_interrupt() is the most important function in this driver - * it handles the interrupts from the i8042, and sends incoming bytes @@ -384,6 +364,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) unsigned long flags; unsigned char str, data = 0; unsigned int dfl; + unsigned int aux_idx; int ret; mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); @@ -400,44 +381,67 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) goto out; } - dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | - ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); - - if (i8042_mux_values[0].exists && (str & I8042_STR_AUXDATA)) { + if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { + static unsigned long last_transmit; + static unsigned char last_str; + dfl = 0; if (str & I8042_STR_MUXERR) { + dbg("MUX error, status is %02x, data is %02x", str, data); switch (data) { + default: +/* + * When MUXERR condition is signalled the data register can only contain + * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately + * it is not always the case. Some KBC just get confused which port the + * data came from and signal error leaving the data intact. They _do not_ + * revert to legacy mode (actually I've never seen KBC reverting to legacy + * mode yet, when we see one we'll add proper handling). + * Anyway, we will assume that the data came from the same serio last byte + * was transmitted (if transmission happened not too long ago). + */ + if (time_before(jiffies, last_transmit + HZ/10)) { + str = last_str; + break; + } + /* fall through - report timeout */ case 0xfd: - case 0xfe: dfl = SERIO_TIMEOUT; break; - case 0xff: dfl = SERIO_PARITY; break; + case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; + case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; } - data = 0xfe; - } else dfl = 0; + } + + aux_idx = (str >> 6) & 3; dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)", - data, (str >> 6), irq, + data, aux_idx, irq, dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); - serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs); + if (likely(i8042_mux_values[aux_idx].exists)) + serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs); + last_str = str; + last_transmit = jiffies; goto irq_ret; } + dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | + ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); + dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); - if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) { - serio_interrupt(&i8042_aux_port, data, dfl, regs); - goto irq_ret; - } - if (!i8042_kbd_values.exists) - goto irq_ret; - - serio_interrupt(&i8042_kbd_port, data, dfl, regs); + if (str & I8042_STR_AUXDATA) { + if (likely(i8042_aux_values.exists)) + serio_interrupt(i8042_aux_port, data, dfl, regs); + } else { + if (likely(i8042_kbd_values.exists)) + serio_interrupt(i8042_kbd_port, data, dfl, regs); + } irq_ret: ret = 1; @@ -474,17 +478,8 @@ static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9) return -1; param = 0xa4; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b) { - -/* - * Do another loop test with the 0x5a value. Doing anything else upsets - * Profusion/ServerWorks OSB4 chipsets. - */ - - param = 0x5a; - i8042_command(¶m, I8042_CMD_AUX_LOOP); + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b) return -1; - } if (mux_version) *mux_version = ~param; @@ -639,8 +634,10 @@ static int __init i8042_check_aux(struct i8042_values *values) * registers it, and reports to the user. */ -static int __init i8042_port_register(struct i8042_values *values, struct serio *port) +static int __init i8042_port_register(struct serio *port) { + struct i8042_values *values = port->port_data; + values->exists = 1; i8042_ctr &= ~values->disable; @@ -677,6 +674,7 @@ static void i8042_timer_func(unsigned long data) static int i8042_controller_init(void) { + unsigned long flags; /* * Test the i8042. We need to know if it thinks it's working correctly @@ -723,12 +721,14 @@ static int i8042_controller_init(void) * Handle keylock. */ + spin_lock_irqsave(&i8042_lock, flags); if (~i8042_read_status() & I8042_STR_KEYLOCK) { if (i8042_unlock) i8042_ctr |= I8042_CTR_IGNKEYLOCK; else printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n"); } + spin_unlock_irqrestore(&i8042_lock, flags); /* * If the chip is configured into nontranslated mode by the BIOS, don't @@ -745,10 +745,8 @@ static int i8042_controller_init(void) * BIOSes. */ - if (i8042_direct) { + if (i8042_direct) i8042_ctr &= ~I8042_CTR_XLATE; - i8042_kbd_port.type = SERIO_8042; - } /* * Write CTR back. @@ -802,19 +800,54 @@ void i8042_controller_cleanup(void) */ if (i8042_kbd_values.exists) - serio_cleanup(&i8042_kbd_port); + serio_cleanup(i8042_kbd_port); if (i8042_aux_values.exists) - serio_cleanup(&i8042_aux_port); + serio_cleanup(i8042_aux_port); - for (i = 0; i < 4; i++) + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) if (i8042_mux_values[i].exists) - serio_cleanup(i8042_mux_port + i); + serio_cleanup(i8042_mux_port[i]); i8042_controller_reset(); } +static int blink_frequency = 500; +module_param_named(panicblink, blink_frequency, int, 0600); + +/* Catch the case when the kbd interrupt is off */ +#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) + +/* Tell the user who may be running in X and not see the console that we have + panic'ed. This is to distingush panics from "real" lockups. */ +static long i8042_panic_blink(long count) +{ + long delay = 0; + static long last_blink; + static char led; + /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is + different. */ + if (!blink_frequency) + return 0; + if (count - last_blink < blink_frequency) + return 0; + led ^= 0x01 | 0x04; + while (i8042_read_status() & I8042_STR_IBF) + DELAY; + i8042_write_data(0xed); /* set leds */ + DELAY; + while (i8042_read_status() & I8042_STR_IBF) + DELAY; + DELAY; + i8042_write_data(led); + DELAY; + last_blink = count; + return delay; +} + +#undef DELAY + /* * Here we try to restore the original BIOS settings */ @@ -851,20 +884,22 @@ static int i8042_controller_resume(void) * Reconnect anything that was connected to the ports. */ - if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0) - serio_reconnect(&i8042_kbd_port); + if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0) + serio_reconnect(i8042_kbd_port); - if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0) - serio_reconnect(&i8042_aux_port); + if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0) + serio_reconnect(i8042_aux_port); - for (i = 0; i < 4; i++) - if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0) - serio_reconnect(i8042_mux_port + i); + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) + if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0) + serio_reconnect(i8042_mux_port[i]); /* * Restart timer (for polling "stuck" data) */ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); + panic_blink = i8042_panic_blink; + return 0; } @@ -882,7 +917,7 @@ static int i8042_notify_sys(struct notifier_block *this, unsigned long code, return NOTIFY_DONE; } -static struct notifier_block i8042_notifier= +static struct notifier_block i8042_notifier = { i8042_notify_sys, NULL, @@ -892,25 +927,27 @@ static struct notifier_block i8042_notifier= /* * Suspend/resume handlers for the new PM scheme (driver model) */ -static int i8042_suspend(struct sys_device *dev, u32 state) +static int i8042_suspend(struct device *dev, u32 state, u32 level) { - return i8042_controller_suspend(); + return level == SUSPEND_DISABLE ? i8042_controller_suspend() : 0; } -static int i8042_resume(struct sys_device *dev) +static int i8042_resume(struct device *dev, u32 level) { - return i8042_controller_resume(); + return level == RESUME_ENABLE ? i8042_controller_resume() : 0; } -static struct sysdev_class kbc_sysclass = { - set_kset_name("i8042"), - .suspend = i8042_suspend, - .resume = i8042_resume, -}; +static void i8042_shutdown(struct device *dev) +{ + i8042_controller_cleanup(); +} -static struct sys_device device_i8042 = { - .id = 0, - .cls = &kbc_sysclass, +static struct device_driver i8042_driver = { + .name = "i8042", + .bus = &platform_bus_type, + .suspend = i8042_suspend, + .resume = i8042_resume, + .shutdown = i8042_shutdown, }; /* @@ -929,23 +966,75 @@ static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dum return 0; } -static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index) +static struct serio * __init i8042_allocate_kbd_port(void) { - memcpy(port, &i8042_aux_port, sizeof(struct serio)); - memcpy(values, &i8042_aux_values, sizeof(struct i8042_values)); - sprintf(i8042_mux_names[index], "i8042 Aux-%d Port", index); - sprintf(i8042_mux_phys[index], I8042_MUX_PHYS_DESC, index + 1); - sprintf(i8042_mux_short[index], "AUX%d", index); - port->name = i8042_mux_names[index]; - port->phys = i8042_mux_phys[index]; - port->driver = values; - values->name = i8042_mux_short[index]; - values->mux = index; + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = i8042_direct ? SERIO_8042 : SERIO_8042_XL, + serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write, + serio->open = i8042_open, + serio->close = i8042_close, + serio->port_data = &i8042_kbd_values, + serio->dev.parent = &i8042_platform_device->dev; + strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); + strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); + } + + return serio; +} + +static struct serio * __init i8042_allocate_aux_port(void) +{ + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + serio->port_data = &i8042_aux_values, + serio->dev.parent = &i8042_platform_device->dev; + strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); + strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); + } + + return serio; +} + +static struct serio * __init i8042_allocate_mux_port(int index) +{ + struct serio *serio; + struct i8042_values *values = &i8042_mux_values[index]; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + *values = i8042_aux_values; + snprintf(values->name, sizeof(values->name), "AUX%d", index); + values->mux = index; + + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + serio->port_data = values; + serio->dev.parent = &i8042_platform_device->dev; + snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); + snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); + } + + return serio; } int __init i8042_init(void) { int i; + int err; dbg_init(); @@ -961,30 +1050,36 @@ int __init i8042_init(void) if (i8042_controller_init()) return -ENODEV; - if (i8042_dumbkbd) - i8042_kbd_port.write = NULL; + err = driver_register(&i8042_driver); + if (err) + return err; + + i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); + if (IS_ERR(i8042_platform_device)) { + driver_unregister(&i8042_driver); + return PTR_ERR(i8042_platform_device); + } if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) { if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values)) - for (i = 0; i < 4; i++) { - i8042_init_mux_values(i8042_mux_values + i, i8042_mux_port + i, i); - i8042_port_register(i8042_mux_values + i, i8042_mux_port + i); + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { + i8042_mux_port[i] = i8042_allocate_mux_port(i); + if (i8042_mux_port[i]) + i8042_port_register(i8042_mux_port[i]); } - else - i8042_port_register(&i8042_aux_values, &i8042_aux_port); + else { + i8042_aux_port = i8042_allocate_aux_port(); + if (i8042_aux_port) + i8042_port_register(i8042_aux_port); + } } - i8042_port_register(&i8042_kbd_values, &i8042_kbd_port); + i8042_kbd_port = i8042_allocate_kbd_port(); + if (i8042_kbd_port) + i8042_port_register(i8042_kbd_port); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); - if (sysdev_class_register(&kbc_sysclass) == 0) { - if (sysdev_register(&device_i8042) == 0) - i8042_sysdev_initialized = 1; - else - sysdev_class_unregister(&kbc_sysclass); - } - i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback); register_reboot_notifier(&i8042_notifier); @@ -1001,25 +1096,26 @@ void __exit i8042_exit(void) if (i8042_pm_dev) pm_unregister(i8042_pm_dev); - if (i8042_sysdev_initialized) { - sysdev_unregister(&device_i8042); - sysdev_class_unregister(&kbc_sysclass); - } - i8042_controller_cleanup(); if (i8042_kbd_values.exists) - serio_unregister_port(&i8042_kbd_port); + serio_unregister_port(i8042_kbd_port); if (i8042_aux_values.exists) - serio_unregister_port(&i8042_aux_port); + serio_unregister_port(i8042_aux_port); - for (i = 0; i < 4; i++) + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) if (i8042_mux_values[i].exists) - serio_unregister_port(i8042_mux_port + i); + serio_unregister_port(i8042_mux_port[i]); + del_timer_sync(&i8042_timer); + platform_device_unregister(i8042_platform_device); + driver_unregister(&i8042_driver); + i8042_platform_exit(); + + panic_blink = NULL; } module_init(i8042_init); diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h index f0f637483..cea24034d 100644 --- a/drivers/input/serio/i8042.h +++ b/drivers/input/serio/i8042.h @@ -103,6 +103,13 @@ #define I8042_BUFFER_SIZE 32 +/* + * Number of AUX ports on controllers supporting active multiplexing + * specification + */ + +#define I8042_NUM_MUX_PORTS 4 + /* * Debug. */ diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c index c7db1de49..78f4d9b5a 100644 --- a/drivers/input/serio/maceps2.c +++ b/drivers/input/serio/maceps2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -46,15 +47,18 @@ MODULE_LICENSE("GPL"); #define PS2_CONTROL_RX_CLOCK_ENABLE BIT(4) /* pause reception if set to 0 */ #define PS2_CONTROL_RESET BIT(5) /* reset */ - struct maceps2_data { struct mace_ps2port *port; int irq; }; +static struct maceps2_data port_data[2]; +static struct serio *maceps2_port[2]; +static struct platform_device *maceps2_device; + static int maceps2_write(struct serio *dev, unsigned char val) { - struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port; + struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port; unsigned int timeout = MACE_PS2_TIMEOUT; do { @@ -68,11 +72,10 @@ static int maceps2_write(struct serio *dev, unsigned char val) return -1; } -static irqreturn_t maceps2_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct serio *dev = dev_id; - struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port; + struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port; unsigned int byte; if (mace_read(port->status) & PS2_STATUS_RX_FULL) { @@ -85,7 +88,7 @@ static irqreturn_t maceps2_interrupt(int irq, void *dev_id, static int maceps2_open(struct serio *dev) { - struct maceps2_data *data = (struct maceps2_data *)dev->driver; + struct maceps2_data *data = (struct maceps2_data *)dev->port_data; if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) { printk(KERN_ERR "Could not allocate PS/2 IRQ\n"); @@ -106,7 +109,7 @@ static int maceps2_open(struct serio *dev) static void maceps2_close(struct serio *dev) { - struct maceps2_data *data = (struct maceps2_data *)dev->driver; + struct maceps2_data *data = (struct maceps2_data *)dev->port_data; mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET, data->port->control); @@ -114,46 +117,59 @@ static void maceps2_close(struct serio *dev) free_irq(data->irq, dev); } -static struct maceps2_data port0_data, port1_data; -static struct serio maceps2_port0 = +static struct serio * __init maceps2_allocate_port(int idx) { - .type = SERIO_8042, - .open = maceps2_open, - .close = maceps2_close, - .write = maceps2_write, - .name = "MACE PS/2 port0", - .phys = "mace/serio0", - .driver = &port0_data, -}; + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->write = maceps2_write; + serio->open = maceps2_open; + serio->close = maceps2_close; + snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx); + snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx); + serio->port_data = &port_data[idx]; + serio->dev.parent = &maceps2_device->dev; + } + + return serio; +} -static struct serio maceps2_port1 = -{ - .type = SERIO_8042, - .open = maceps2_open, - .close = maceps2_close, - .write = maceps2_write, - .name = "MACE PS/2 port1", - .phys = "mace/serio1", - .driver = &port1_data, -}; static int __init maceps2_init(void) { - port0_data.port = &mace->perif.ps2.keyb; - port0_data.irq = MACEISA_KEYB_IRQ; - port1_data.port = &mace->perif.ps2.mouse; - port1_data.irq = MACEISA_MOUSE_IRQ; - serio_register_port(&maceps2_port0); - serio_register_port(&maceps2_port1); + maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0); + if (IS_ERR(maceps2_device)) + return PTR_ERR(maceps2_device); + + port_data[0].port = &mace->perif.ps2.keyb; + port_data[0].irq = MACEISA_KEYB_IRQ; + port_data[1].port = &mace->perif.ps2.mouse; + port_data[1].irq = MACEISA_MOUSE_IRQ; + + maceps2_port[0] = maceps2_allocate_port(0); + maceps2_port[1] = maceps2_allocate_port(1); + if (!maceps2_port[0] || !maceps2_port[1]) { + kfree(maceps2_port[0]); + kfree(maceps2_port[1]); + platform_device_unregister(maceps2_device); + return -ENOMEM; + } + + serio_register_port(maceps2_port[0]); + serio_register_port(maceps2_port[1]); return 0; } static void __exit maceps2_exit(void) { - serio_unregister_port(&maceps2_port0); - serio_unregister_port(&maceps2_port1); + serio_unregister_port(maceps2_port[0]); + serio_unregister_port(maceps2_port[1]); + platform_device_unregister(maceps2_device); } module_init(maceps2_init); diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index 5f25b21be..a859df676 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -53,9 +53,7 @@ static int parkbd_writing; static unsigned long parkbd_start; static struct pardevice *parkbd_dev; - -static char parkbd_name[] = "PARKBD AT/XT keyboard adapter"; -static char parkbd_phys[32]; +static struct serio *parkbd_port; static int parkbd_readlines(void) { @@ -86,13 +84,6 @@ static int parkbd_write(struct serio *port, unsigned char c) return 0; } -static struct serio parkbd_port = -{ - .write = parkbd_write, - .name = parkbd_name, - .phys = parkbd_phys, -}; - static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -125,7 +116,7 @@ static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++; if (parkbd_counter == parkbd_mode + 10) - serio_interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs); + serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs); } parkbd_last = jiffies; @@ -163,16 +154,39 @@ static int parkbd_getport(void) return 0; } +static struct serio * __init parkbd_allocate_serio(void) +{ + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = parkbd_mode; + serio->write = parkbd_write, + strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name)); + snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name); + } + + return serio; +} int __init parkbd_init(void) { - if (parkbd_getport()) return -1; - parkbd_writelines(3); - parkbd_port.type = parkbd_mode; + int err; + + err = parkbd_getport(); + if (err) + return err; - sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name); + parkbd_port = parkbd_allocate_serio(); + if (!parkbd_port) { + parport_release(parkbd_dev); + return -ENOMEM; + } + + parkbd_writelines(3); - serio_register_port(&parkbd_port); + serio_register_port(parkbd_port); printk(KERN_INFO "serio: PARKBD %s adapter on %s\n", parkbd_mode ? "AT" : "XT", parkbd_dev->port->name); @@ -183,7 +197,7 @@ int __init parkbd_init(void) void __exit parkbd_exit(void) { parport_release(parkbd_dev); - serio_unregister_port(&parkbd_port); + serio_unregister_port(parkbd_port); parport_unregister_device(parkbd_dev); } diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 2b4acac94..489749e7c 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -38,14 +38,14 @@ #define PS2_STAT_TXEMPTY (1<<7) struct pcips2_data { - struct serio io; + struct serio *io; unsigned int base; struct pci_dev *dev; }; static int pcips2_write(struct serio *io, unsigned char val) { - struct pcips2_data *ps2if = io->driver; + struct pcips2_data *ps2if = io->port_data; unsigned int stat; do { @@ -80,7 +80,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs) if (hweight8(scancode) & 1) flag ^= SERIO_PARITY; - serio_interrupt(&ps2if->io, scancode, flag, regs); + serio_interrupt(ps2if->io, scancode, flag, regs); } while (1); return IRQ_RETVAL(handled); } @@ -101,7 +101,7 @@ static void pcips2_flush_input(struct pcips2_data *ps2if) static int pcips2_open(struct serio *io) { - struct pcips2_data *ps2if = io->driver; + struct pcips2_data *ps2if = io->port_data; int ret, val = 0; outb(PS2_CTRL_ENABLE, ps2if->base); @@ -119,7 +119,7 @@ static int pcips2_open(struct serio *io) static void pcips2_close(struct serio *io) { - struct pcips2_data *ps2if = io->driver; + struct pcips2_data *ps2if = io->port_data; outb(0, ps2if->base); @@ -129,46 +129,51 @@ static void pcips2_close(struct serio *io) static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct pcips2_data *ps2if; + struct serio *serio; int ret; ret = pci_enable_device(dev); if (ret) - return ret; + goto out; - if (!request_region(pci_resource_start(dev, 0), - pci_resource_len(dev, 0), "pcips2")) { - ret = -EBUSY; + ret = pci_request_regions(dev, "pcips2"); + if (ret) goto disable; - } ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL); - if (!ps2if) { + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!ps2if || !serio) { ret = -ENOMEM; goto release; } memset(ps2if, 0, sizeof(struct pcips2_data)); - - ps2if->io.type = SERIO_8042; - ps2if->io.write = pcips2_write; - ps2if->io.open = pcips2_open; - ps2if->io.close = pcips2_close; - ps2if->io.name = pci_name(dev); - ps2if->io.phys = dev->dev.bus_id; - ps2if->io.driver = ps2if; + memset(serio, 0, sizeof(struct serio)); + + serio->type = SERIO_8042; + serio->write = pcips2_write; + serio->open = pcips2_open; + serio->close = pcips2_close; + strlcpy(serio->name, pci_name(dev), sizeof(serio->name)); + strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + serio->port_data = ps2if; + serio->dev.parent = &dev->dev; + ps2if->io = serio; ps2if->dev = dev; ps2if->base = pci_resource_start(dev, 0); pci_set_drvdata(dev, ps2if); - serio_register_port(&ps2if->io); + serio_register_port(ps2if->io); return 0; release: - release_region(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); + kfree(ps2if); + kfree(serio); + pci_release_regions(dev); disable: pci_disable_device(dev); + out: return ret; } @@ -176,11 +181,10 @@ static void __devexit pcips2_remove(struct pci_dev *dev) { struct pcips2_data *ps2if = pci_get_drvdata(dev); - serio_unregister_port(&ps2if->io); - release_region(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); + serio_unregister_port(ps2if->io); pci_set_drvdata(dev, NULL); kfree(ps2if); + pci_release_regions(dev); pci_disable_device(dev); } diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 7f4a26287..a56ea2b73 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -35,8 +35,9 @@ #include #include #include +#include +#include -#include #include #include #include @@ -47,43 +48,106 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); MODULE_LICENSE("GPL"); -static struct serio q40kbd_port = -{ - .type = SERIO_8042, - .name = "Q40 kbd port", - .phys = "Q40", - .write = NULL, -}; - -static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED; +static struct serio *q40kbd_port; +static struct platform_device *q40kbd_device; + +static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + unsigned long flags; + + spin_lock_irqsave(&q40kbd_lock, flags); + if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)) - serio_interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0, regs); + serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs); master_outb(-1, KEYBOARD_UNLOCK_REG); + + spin_unlock_irqrestore(&q40kbd_lock, flags); + return IRQ_HANDLED; } -static int __init q40kbd_init(void) +/* + * q40kbd_flush() flushes all data that may be in the keyboard buffers + */ + +static void q40kbd_flush(void) +{ + int maxread = 100; + unsigned long flags; + + spin_lock_irqsave(&q40kbd_lock, flags); + + while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) + master_inb(KEYCODE_REG); + + spin_unlock_irqrestore(&q40kbd_lock, flags); +} + +/* + * q40kbd_open() is called when a port is open by the higher layer. + * It allocates the interrupt and enables in in the chip. + */ + +static int q40kbd_open(struct serio *port) { - int maxread = 100; + q40kbd_flush(); + if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) { + printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD); + return -1; + } + + /* off we go */ + master_outb(-1, KEYBOARD_UNLOCK_REG); + master_outb(1, KEY_IRQ_ENABLE_REG); + + return 0; +} + +static void q40kbd_close(struct serio *port) +{ + master_outb(0, KEY_IRQ_ENABLE_REG); + master_outb(-1, KEYBOARD_UNLOCK_REG); + free_irq(Q40_IRQ_KEYBOARD, NULL); + + q40kbd_flush(); +} + +static struct serio * __init q40kbd_allocate_port(void) +{ + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->open = q40kbd_open; + serio->close = q40kbd_close; + serio->dev.parent = &q40kbd_device->dev; + strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name)); + strlcpy(serio->phys, "Q40", sizeof(serio->phys)); + } + + return serio; +} + +static int __init q40kbd_init(void) +{ if (!MACH_IS_Q40) return -EIO; - /* allocate the IRQ */ - request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL); - - /* flush any pending input */ - while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) - master_inb(KEYCODE_REG); + q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0); + if (IS_ERR(q40kbd_device)) + return PTR_ERR(q40kbd_device); - /* off we go */ - master_outb(-1,KEYBOARD_UNLOCK_REG); - master_outb(1,KEY_IRQ_ENABLE_REG); + if (!(q40kbd_port = q40kbd_allocate_port())) { + platform_device_unregister(q40kbd_device); + return -ENOMEM; + } - serio_register_port(&q40kbd_port); + serio_register_port(q40kbd_port); printk(KERN_INFO "serio: Q40 kbd registered\n"); return 0; @@ -91,11 +155,8 @@ static int __init q40kbd_init(void) static void __exit q40kbd_exit(void) { - master_outb(0,KEY_IRQ_ENABLE_REG); - master_outb(-1,KEYBOARD_UNLOCK_REG); - - serio_unregister_port(&q40kbd_port); - free_irq(Q40_IRQ_KEYBOARD, NULL); + serio_unregister_port(q40kbd_port); + platform_device_unregister(q40kbd_device); } module_init(q40kbd_init); diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index a2e4be7ae..49a584102 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -101,25 +102,54 @@ static void rpckbd_close(struct serio *port) free_irq(IRQ_KEYBOARDTX, port); } -static struct serio rpckbd_port = +/* + * Allocate and initialize serio structure for subsequent registration + * with serio core. + */ +static int __devinit rpckbd_probe(struct device *dev) +{ + struct serio *serio; + + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + memset(serio, 0, sizeof(struct serio)); + serio->type = SERIO_8042; + serio->write = rpckbd_write; + serio->open = rpckbd_open; + serio->close = rpckbd_close; + serio->dev.parent = dev; + strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name)); + strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys)); + + dev_set_drvdata(dev, serio); + serio_register_port(serio); + return 0; +} + +static int __devexit rpckbd_remove(struct device *dev) { - .type = SERIO_8042, - .open = rpckbd_open, - .close = rpckbd_close, - .write = rpckbd_write, - .name = "RiscPC PS/2 kbd port", - .phys = "rpckbd/serio0", + struct serio *serio = dev_get_drvdata(dev); + serio_unregister_port(serio); + return 0; +} + +static struct device_driver rpckbd_driver = { + .name = "kart", + .bus = &platform_bus_type, + .probe = rpckbd_probe, + .remove = __devexit_p(rpckbd_remove), }; static int __init rpckbd_init(void) { - serio_register_port(&rpckbd_port); - return 0; + return driver_register(&rpckbd_driver); } static void __exit rpckbd_exit(void) { - serio_unregister_port(&rpckbd_port); + driver_unregister(&rpckbd_driver); } module_init(rpckbd_init); diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 9beb7575c..62937f5b3 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -26,7 +26,7 @@ #include struct ps2if { - struct serio io; + struct serio *io; struct sa1111_dev *dev; unsigned long base; unsigned int open; @@ -59,7 +59,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) if (hweight8(scancode) & 1) flag ^= SERIO_PARITY; - serio_interrupt(&ps2if->io, scancode, flag, regs); + serio_interrupt(ps2if->io, scancode, flag, regs); status = sa1111_readl(ps2if->base + SA1111_PS2STAT); } @@ -95,7 +95,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs) */ static int ps2_write(struct serio *io, unsigned char val) { - struct ps2if *ps2if = io->driver; + struct ps2if *ps2if = io->port_data; unsigned long flags; unsigned int head; @@ -122,7 +122,7 @@ static int ps2_write(struct serio *io, unsigned char val) static int ps2_open(struct serio *io) { - struct ps2if *ps2if = io->driver; + struct ps2if *ps2if = io->port_data; int ret; sa1111_enable_device(ps2if->dev); @@ -154,7 +154,7 @@ static int ps2_open(struct serio *io) static void ps2_close(struct serio *io) { - struct ps2if *ps2if = io->driver; + struct ps2if *ps2if = io->port_data; sa1111_writel(0, ps2if->base + SA1111_PS2CR); @@ -232,22 +232,28 @@ static int __init ps2_test(struct ps2if *ps2if) static int ps2_probe(struct sa1111_dev *dev) { struct ps2if *ps2if; + struct serio *serio; int ret; ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL); - if (!ps2if) { - return -ENOMEM; + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (!ps2if || !serio) { + ret = -ENOMEM; + goto free; } memset(ps2if, 0, sizeof(struct ps2if)); - - ps2if->io.type = SERIO_8042; - ps2if->io.write = ps2_write; - ps2if->io.open = ps2_open; - ps2if->io.close = ps2_close; - ps2if->io.name = dev->dev.bus_id; - ps2if->io.phys = dev->dev.bus_id; - ps2if->io.driver = ps2if; + memset(serio, 0, sizeof(struct serio)); + + serio->type = SERIO_8042; + serio->write = ps2_write; + serio->open = ps2_open; + serio->close = ps2_close; + strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name)); + strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); + serio->port_data = ps2if; + serio->dev.parent = &dev->dev; + ps2if->io = serio; ps2if->dev = dev; sa1111_set_drvdata(dev, ps2if); @@ -292,7 +298,7 @@ static int ps2_probe(struct sa1111_dev *dev) ps2_clear_input(ps2if); sa1111_disable_device(ps2if->dev); - serio_register_port(&ps2if->io); + serio_register_port(ps2if->io); return 0; out: @@ -302,6 +308,7 @@ static int ps2_probe(struct sa1111_dev *dev) free: sa1111_set_drvdata(dev, NULL); kfree(ps2if); + kfree(serio); return ret; } @@ -312,7 +319,7 @@ static int ps2_remove(struct sa1111_dev *dev) { struct ps2if *ps2if = sa1111_get_drvdata(dev); - serio_unregister_port(&ps2if->io); + serio_unregister_port(ps2if->io); release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); sa1111_set_drvdata(dev, NULL); diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 6f003197b..deb6014b9 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -1,11 +1,9 @@ -/* - * $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $ - * - * Copyright (c) 1999-2001 Vojtech Pavlik - */ - /* * The Serio abstraction module + * + * Copyright (c) 1999-2004 Vojtech Pavlik + * Copyright (c) 2004 Dmitry Torokhov + * Copyright (c) 2003 Daniele Bellucci */ /* @@ -26,10 +24,6 @@ * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - * - * Changes: - * 20 Jul. 2003 Daniele Bellucci - * Minor cleanups. */ #include @@ -50,100 +44,178 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(serio_register_port); EXPORT_SYMBOL(serio_register_port_delayed); -EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_port_delayed); -EXPORT_SYMBOL(__serio_unregister_port); -EXPORT_SYMBOL(serio_register_device); -EXPORT_SYMBOL(serio_unregister_device); +EXPORT_SYMBOL(serio_register_driver); +EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_close); EXPORT_SYMBOL(serio_rescan); EXPORT_SYMBOL(serio_reconnect); +static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_diriver_list */ +static LIST_HEAD(serio_list); +static LIST_HEAD(serio_driver_list); +static unsigned int serio_no; + +struct bus_type serio_bus = { + .name = "serio", +}; + +static void serio_find_driver(struct serio *serio); +static void serio_create_port(struct serio *serio); +static void serio_destroy_port(struct serio *serio); +static void serio_connect_port(struct serio *serio, struct serio_driver *drv); +static void serio_reconnect_port(struct serio *serio); +static void serio_disconnect_port(struct serio *serio); + +static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) +{ + get_driver(&drv->driver); + + drv->connect(serio, drv); + if (serio->drv) { + down_write(&serio_bus.subsys.rwsem); + serio->dev.driver = &drv->driver; + device_bind_driver(&serio->dev); + up_write(&serio_bus.subsys.rwsem); + return 1; + } + + put_driver(&drv->driver); + return 0; +} + +/* serio_find_driver() must be called with serio_sem down. */ +static void serio_find_driver(struct serio *serio) +{ + struct serio_driver *drv; + + list_for_each_entry(drv, &serio_driver_list, node) + if (!drv->manual_bind) + if (serio_bind_driver(serio, drv)) + break; +} + +/* + * Serio event processing. + */ + struct serio_event { int type; struct serio *serio; struct list_head node; }; -static DECLARE_MUTEX(serio_sem); -static LIST_HEAD(serio_list); -static LIST_HEAD(serio_dev_list); +enum serio_event_type { + SERIO_RESCAN, + SERIO_RECONNECT, + SERIO_REGISTER_PORT, + SERIO_UNREGISTER_PORT, +}; + +static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED; /* protects serio_event_list */ static LIST_HEAD(serio_event_list); +static DECLARE_WAIT_QUEUE_HEAD(serio_wait); +static DECLARE_COMPLETION(serio_exited); static int serio_pid; -static void serio_find_dev(struct serio *serio) +static void serio_queue_event(struct serio *serio, int event_type) { - struct serio_dev *dev; + unsigned long flags; + struct serio_event *event; - list_for_each_entry(dev, &serio_dev_list, node) { - if (serio->dev) - break; - if (dev->connect) - dev->connect(serio, dev); - } -} + spin_lock_irqsave(&serio_event_lock, flags); -#define SERIO_RESCAN 1 -#define SERIO_RECONNECT 2 -#define SERIO_REGISTER_PORT 3 -#define SERIO_UNREGISTER_PORT 4 + if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { + event->type = event_type; + event->serio = serio; -static DECLARE_WAIT_QUEUE_HEAD(serio_wait); -static DECLARE_COMPLETION(serio_exited); + list_add_tail(&event->node, &serio_event_list); + wake_up(&serio_wait); + } + + spin_unlock_irqrestore(&serio_event_lock, flags); +} -static void serio_invalidate_pending_events(struct serio *serio) +static struct serio_event *serio_get_event(void) { struct serio_event *event; + struct list_head *node; + unsigned long flags; + + spin_lock_irqsave(&serio_event_lock, flags); + + if (list_empty(&serio_event_list)) { + spin_unlock_irqrestore(&serio_event_lock, flags); + return NULL; + } + + node = serio_event_list.next; + event = container_of(node, struct serio_event, node); + list_del_init(node); + + spin_unlock_irqrestore(&serio_event_lock, flags); - list_for_each_entry(event, &serio_event_list, node) - if (event->serio == serio) - event->serio = NULL; + return event; } -void serio_handle_events(void) +static void serio_handle_events(void) { - struct list_head *node, *next; struct serio_event *event; - list_for_each_safe(node, next, &serio_event_list) { - event = container_of(node, struct serio_event, node); + while ((event = serio_get_event())) { down(&serio_sem); - if (event->serio == NULL) - goto event_done; switch (event->type) { case SERIO_REGISTER_PORT : - __serio_register_port(event->serio); + serio_create_port(event->serio); + serio_connect_port(event->serio, NULL); break; case SERIO_UNREGISTER_PORT : - __serio_unregister_port(event->serio); + serio_disconnect_port(event->serio); + serio_destroy_port(event->serio); break; case SERIO_RECONNECT : - if (event->serio->dev && event->serio->dev->reconnect) - if (event->serio->dev->reconnect(event->serio) == 0) - break; - /* reconnect failed - fall through to rescan */ + serio_reconnect_port(event->serio); + break; case SERIO_RESCAN : - if (event->serio->dev && event->serio->dev->disconnect) - event->serio->dev->disconnect(event->serio); - serio_find_dev(event->serio); + serio_disconnect_port(event->serio); + serio_connect_port(event->serio, NULL); break; default: break; } -event_done: + up(&serio_sem); - list_del_init(node); kfree(event); } } +static void serio_remove_pending_events(struct serio *serio) +{ + struct list_head *node, *next; + struct serio_event *event; + unsigned long flags; + + spin_lock_irqsave(&serio_event_lock, flags); + + list_for_each_safe(node, next, &serio_event_list) { + event = container_of(node, struct serio_event, node); + if (event->serio == serio) { + list_del_init(node); + kfree(event); + } + } + + spin_unlock_irqrestore(&serio_event_lock, flags); +} + + static int serio_thread(void *nothing) { lock_kernel(); @@ -163,52 +235,234 @@ static int serio_thread(void *nothing) complete_and_exit(&serio_exited, 0); } -static void serio_queue_event(struct serio *serio, int event_type) + +/* + * Serio port operations + */ + +static ssize_t serio_show_description(struct device *dev, char *buf) { - struct serio_event *event; + struct serio *serio = to_serio_port(dev); + return sprintf(buf, "%s\n", serio->name); +} - if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { - event->type = event_type; - event->serio = serio; +static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count) +{ + struct serio *serio = to_serio_port(dev); + struct device_driver *drv; + int retval; + + retval = down_interruptible(&serio_sem); + if (retval) + return retval; + + retval = count; + if (!strncmp(buf, "none", count)) { + serio_disconnect_port(serio); + } else if (!strncmp(buf, "reconnect", count)) { + serio_reconnect_port(serio); + } else if (!strncmp(buf, "rescan", count)) { + serio_disconnect_port(serio); + serio_connect_port(serio, NULL); + } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { + serio_disconnect_port(serio); + serio_connect_port(serio, to_serio_driver(drv)); + put_driver(drv); + } else { + retval = -EINVAL; + } - list_add_tail(&event->node, &serio_event_list); - wake_up(&serio_wait); + up(&serio_sem); + + return retval; +} + +static ssize_t serio_show_bind_mode(struct device *dev, char *buf) +{ + struct serio *serio = to_serio_port(dev); + return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto"); +} + +static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count) +{ + struct serio *serio = to_serio_port(dev); + int retval; + + retval = count; + if (!strncmp(buf, "manual", count)) { + serio->manual_bind = 1; + } else if (!strncmp(buf, "auto", count)) { + serio->manual_bind = 0; + } else { + retval = -EINVAL; } + + return retval; } -void serio_rescan(struct serio *serio) +static struct device_attribute serio_device_attrs[] = { + __ATTR(description, S_IRUGO, serio_show_description, NULL), + __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver), + __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode), + __ATTR_NULL +}; + + +static void serio_release_port(struct device *dev) { - serio_queue_event(serio, SERIO_RESCAN); + struct serio *serio = to_serio_port(dev); + + kfree(serio); + module_put(THIS_MODULE); } -void serio_reconnect(struct serio *serio) +static void serio_create_port(struct serio *serio) { - serio_queue_event(serio, SERIO_RECONNECT); + try_module_get(THIS_MODULE); + + spin_lock_init(&serio->lock); + list_add_tail(&serio->node, &serio_list); + snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++); + serio->dev.bus = &serio_bus; + serio->dev.release = serio_release_port; + if (serio->parent) + serio->dev.parent = &serio->parent->dev; + device_register(&serio->dev); } -irqreturn_t serio_interrupt(struct serio *serio, - unsigned char data, unsigned int flags, struct pt_regs *regs) +/* + * serio_destroy_port() completes deregistration process and removes + * port from the system + */ +static void serio_destroy_port(struct serio *serio) { - irqreturn_t ret = IRQ_NONE; + struct serio_driver *drv = serio->drv; + unsigned long flags; - if (serio->dev && serio->dev->interrupt) { - ret = serio->dev->interrupt(serio, data, flags, regs); - } else { - if (!flags) { - if ((serio->type == SERIO_8042 || - serio->type == SERIO_8042_XL) && (data != 0xaa)) - return ret; - serio_rescan(serio); - ret = IRQ_HANDLED; + serio_remove_pending_events(serio); + list_del_init(&serio->node); + + if (drv) { + drv->disconnect(serio); + down_write(&serio_bus.subsys.rwsem); + device_release_driver(&serio->dev); + up_write(&serio_bus.subsys.rwsem); + put_driver(&drv->driver); + } + + if (serio->parent) { + spin_lock_irqsave(&serio->parent->lock, flags); + serio->parent->child = NULL; + spin_unlock_irqrestore(&serio->parent->lock, flags); + } + + device_unregister(&serio->dev); +} + +/* + * serio_connect_port() tries to bind the port and possible all its + * children to appropriate drivers. If driver passed in the function will not + * try otehr drivers when binding parent port. + */ +static void serio_connect_port(struct serio *serio, struct serio_driver *drv) +{ + WARN_ON(serio->drv); + WARN_ON(serio->child); + + if (drv) + serio_bind_driver(serio, drv); + else if (!serio->manual_bind) + serio_find_driver(serio); + + /* Ok, now bind children, if any */ + while (serio->child) { + serio = serio->child; + + WARN_ON(serio->drv); + WARN_ON(serio->child); + + serio_create_port(serio); + + if (!serio->manual_bind) { + /* + * With children we just _prefer_ passed in driver, + * but we will try other options in case preferred + * is not the one + */ + if (!drv || !serio_bind_driver(serio, drv)) + serio_find_driver(serio); } } - return ret; +} + +/* + * + */ +static void serio_reconnect_port(struct serio *serio) +{ + do { + if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { + serio_disconnect_port(serio); + serio_connect_port(serio, NULL); + /* Ok, old children are now gone, we are done */ + break; + } + serio = serio->child; + } while (serio); +} + +/* + * serio_disconnect_port() unbinds a port from its driver. As a side effect + * all child ports are unbound and destroyed. + */ +static void serio_disconnect_port(struct serio *serio) +{ + struct serio_driver *drv = serio->drv; + struct serio *s; + + if (serio->child) { + /* + * Children ports should be disconnected and destroyed + * first, staring with the leaf one, since we don't want + * to do recursion + */ + do { + s = serio->child; + } while (s->child); + + while (s != serio) { + s = s->parent; + serio_destroy_port(s->child); + } + } + + /* + * Ok, no children left, now disconnect this port + */ + if (drv) { + drv->disconnect(serio); + down_write(&serio_bus.subsys.rwsem); + device_release_driver(&serio->dev); + up_write(&serio_bus.subsys.rwsem); + put_driver(&drv->driver); + } +} + +void serio_rescan(struct serio *serio) +{ + serio_queue_event(serio, SERIO_RESCAN); +} + +void serio_reconnect(struct serio *serio) +{ + serio_queue_event(serio, SERIO_RECONNECT); } void serio_register_port(struct serio *serio) { down(&serio_sem); - __serio_register_port(serio); + serio_create_port(serio); + serio_connect_port(serio, NULL); up(&serio_sem); } @@ -222,21 +476,11 @@ void serio_register_port_delayed(struct serio *serio) serio_queue_event(serio, SERIO_REGISTER_PORT); } -/* - * Should only be called directly if serio_sem has already been taken, - * for example when unregistering a serio from other input device's - * connect() function. - */ -void __serio_register_port(struct serio *serio) -{ - list_add_tail(&serio->node, &serio_list); - serio_find_dev(serio); -} - void serio_unregister_port(struct serio *serio) { down(&serio_sem); - __serio_unregister_port(serio); + serio_disconnect_port(serio); + serio_destroy_port(serio); up(&serio_sem); } @@ -250,82 +494,171 @@ void serio_unregister_port_delayed(struct serio *serio) serio_queue_event(serio, SERIO_UNREGISTER_PORT); } + /* - * Should only be called directly if serio_sem has already been taken, - * for example when unregistering a serio from other input device's - * disconnect() function. + * Serio driver operations */ -void __serio_unregister_port(struct serio *serio) + +static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf) { - serio_invalidate_pending_events(serio); - list_del_init(&serio->node); - if (serio->dev && serio->dev->disconnect) - serio->dev->disconnect(serio); + struct serio_driver *driver = to_serio_driver(drv); + return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)"); +} + +static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf) +{ + struct serio_driver *serio_drv = to_serio_driver(drv); + return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto"); } -void serio_register_device(struct serio_dev *dev) +static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count) +{ + struct serio_driver *serio_drv = to_serio_driver(drv); + int retval; + + retval = count; + if (!strncmp(buf, "manual", count)) { + serio_drv->manual_bind = 1; + } else if (!strncmp(buf, "auto", count)) { + serio_drv->manual_bind = 0; + } else { + retval = -EINVAL; + } + + return retval; +} + + +static struct driver_attribute serio_driver_attrs[] = { + __ATTR(description, S_IRUGO, serio_driver_show_description, NULL), + __ATTR(bind_mode, S_IWUSR | S_IRUGO, + serio_driver_show_bind_mode, serio_driver_set_bind_mode), + __ATTR_NULL +}; + +void serio_register_driver(struct serio_driver *drv) { struct serio *serio; + down(&serio_sem); - list_add_tail(&dev->node, &serio_dev_list); - list_for_each_entry(serio, &serio_list, node) - if (!serio->dev && dev->connect) - dev->connect(serio, dev); + + list_add_tail(&drv->node, &serio_driver_list); + + drv->driver.bus = &serio_bus; + driver_register(&drv->driver); + + if (drv->manual_bind) + goto out; + +start_over: + list_for_each_entry(serio, &serio_list, node) { + if (!serio->drv) { + serio_connect_port(serio, drv); + /* + * if new child appeared then the list is changed, + * we need to start over + */ + if (serio->child) + goto start_over; + } + } + +out: up(&serio_sem); } -void serio_unregister_device(struct serio_dev *dev) +void serio_unregister_driver(struct serio_driver *drv) { struct serio *serio; down(&serio_sem); - list_del_init(&dev->node); + list_del_init(&drv->node); + +start_over: list_for_each_entry(serio, &serio_list, node) { - if (serio->dev == dev && dev->disconnect) - dev->disconnect(serio); - serio_find_dev(serio); + if (serio->drv == drv) { + serio_disconnect_port(serio); + serio_connect_port(serio, NULL); + /* we could've deleted some ports, restart */ + goto start_over; + } } + + driver_unregister(&drv->driver); + up(&serio_sem); } -/* called from serio_dev->connect/disconnect methods under serio_sem */ -int serio_open(struct serio *serio, struct serio_dev *dev) +/* called from serio_driver->connect/disconnect methods under serio_sem */ +int serio_open(struct serio *serio, struct serio_driver *drv) { - serio->dev = dev; + serio_pause_rx(serio); + serio->drv = drv; + serio_continue_rx(serio); + if (serio->open && serio->open(serio)) { - serio->dev = NULL; + serio_pause_rx(serio); + serio->drv = NULL; + serio_continue_rx(serio); return -1; } return 0; } -/* called from serio_dev->connect/disconnect methods under serio_sem */ +/* called from serio_driver->connect/disconnect methods under serio_sem */ void serio_close(struct serio *serio) { if (serio->close) serio->close(serio); - serio->dev = NULL; + + serio_pause_rx(serio); + serio->drv = NULL; + serio_continue_rx(serio); } -static int __init serio_init(void) +irqreturn_t serio_interrupt(struct serio *serio, + unsigned char data, unsigned int dfl, struct pt_regs *regs) { - int pid; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + + spin_lock_irqsave(&serio->lock, flags); + + if (likely(serio->drv)) { + ret = serio->drv->interrupt(serio, data, dfl, regs); + } else { + if (!dfl) { + if ((serio->type != SERIO_8042 && + serio->type != SERIO_8042_XL) || (data == 0xaa)) { + serio_rescan(serio); + ret = IRQ_HANDLED; + } + } + } + + spin_unlock_irqrestore(&serio->lock, flags); - pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL); + return ret; +} - if (!pid) { +static int __init serio_init(void) +{ + if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { printk(KERN_WARNING "serio: Failed to start kseriod\n"); return -1; } - serio_pid = pid; + serio_bus.dev_attrs = serio_device_attrs; + serio_bus.drv_attrs = serio_driver_attrs; + bus_register(&serio_bus); return 0; } static void __exit serio_exit(void) { + bus_unregister(&serio_bus); kill_proc(serio_pid, SIGTERM, 1); wait_for_completion(&serio_exited); } diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 19e269249..4a8b7b72c 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -31,28 +31,25 @@ MODULE_ALIAS_LDISC(N_MOUSE); struct serport { struct tty_struct *tty; wait_queue_head_t wait; - struct serio serio; + struct serio *serio; unsigned long flags; - char phys[32]; }; -char serport_name[] = "Serial port"; - /* * Callback functions from the serio code. */ static int serport_serio_write(struct serio *serio, unsigned char data) { - struct serport *serport = serio->driver; - return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1); + struct serport *serport = serio->port_data; + return -(serport->tty->driver->write(serport->tty, &data, 1) != 1); } static void serport_serio_close(struct serio *serio) { - struct serport *serport = serio->driver; + struct serport *serport = serio->port_data; - serport->serio.type = 0; + serport->serio->type = 0; wake_up_interruptible(&serport->wait); } @@ -64,26 +61,30 @@ static void serport_serio_close(struct serio *serio) static int serport_ldisc_open(struct tty_struct *tty) { struct serport *serport; + struct serio *serio; char name[64]; serport = kmalloc(sizeof(struct serport), GFP_KERNEL); - if (unlikely(!serport)) + serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (unlikely(!serport || !serio)) { + kfree(serport); + kfree(serio); return -ENOMEM; - memset(serport, 0, sizeof(struct serport)); + } + memset(serport, 0, sizeof(struct serport)); + serport->serio = serio; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); serport->tty = tty; tty->disc_data = serport; - snprintf(serport->phys, sizeof(serport->phys), "%s/serio0", tty_name(tty, name)); - - serport->serio.name = serport_name; - serport->serio.phys = serport->phys; - - serport->serio.type = SERIO_RS232; - serport->serio.write = serport_serio_write; - serport->serio.close = serport_serio_close; - serport->serio.driver = serport; + memset(serio, 0, sizeof(struct serio)); + strlcpy(serio->name, "Serial port", sizeof(serio->name)); + snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name)); + serio->type = SERIO_RS232; + serio->write = serport_serio_write; + serio->close = serport_serio_close; + serio->port_data = serport; init_waitqueue_head(&serport->wait); @@ -114,7 +115,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c struct serport *serport = (struct serport*) tty->disc_data; int i; for (i = 0; i < count; i++) - serio_interrupt(&serport->serio, cp[i], 0, NULL); + serio_interrupt(serport->serio, cp[i], 0, NULL); } /* @@ -142,10 +143,10 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) return -EBUSY; - serio_register_port(&serport->serio); + serio_register_port(serport->serio); printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name)); - wait_event_interruptible(serport->wait, !serport->serio.type); - serio_unregister_port(&serport->serio); + wait_event_interruptible(serport->wait, !serport->serio->type); + serio_unregister_port(serport->serio); clear_bit(SERPORT_BUSY, &serport->flags); @@ -161,7 +162,7 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsi struct serport *serport = (struct serport*) tty->disc_data; if (cmd == SPIOCSTYPE) - return get_user(serport->serio.type, (unsigned long __user *) arg); + return get_user(serport->serio->type, (unsigned long __user *) arg); return -EINVAL; } @@ -170,7 +171,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty) { struct serport *sp = (struct serport *) tty->disc_data; - serio_dev_write_wakeup(&sp->serio); + serio_drv_write_wakeup(sp->serio); } /* diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 775914980..e5e38dd4a 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -36,8 +36,10 @@ #include #include +#define DRIVER_DESC "Gunze AHL-51S touchscreen driver" + MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -111,7 +113,7 @@ static void gunze_disconnect(struct serio *serio) * and if yes, registers it as an input device. */ -static void gunze_connect(struct serio *serio, struct serio_dev *dev) +static void gunze_connect(struct serio *serio, struct serio_driver *drv) { struct gunze *gunze; @@ -142,7 +144,7 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev) gunze->dev.id.product = 0x0051; gunze->dev.id.version = 0x0100; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { kfree(gunze); return; } @@ -156,10 +158,14 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev) * The serio device structure. */ -static struct serio_dev gunze_dev = { - .interrupt = gunze_interrupt, - .connect = gunze_connect, - .disconnect = gunze_disconnect, +static struct serio_driver gunze_drv = { + .driver = { + .name = "gunze", + }, + .description = DRIVER_DESC, + .interrupt = gunze_interrupt, + .connect = gunze_connect, + .disconnect = gunze_disconnect, }; /* @@ -168,13 +174,13 @@ static struct serio_dev gunze_dev = { int __init gunze_init(void) { - serio_register_device(&gunze_dev); + serio_register_driver(&gunze_drv); return 0; } void __exit gunze_exit(void) { - serio_unregister_device(&gunze_dev); + serio_unregister_driver(&gunze_drv); } module_init(gunze_init); diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 7b4c16d6f..5d719671c 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -45,8 +45,10 @@ #include #include +#define DRIVER_DESC "H3600 touchscreen driver" + MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("H3600 touchscreen driver"); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); /* @@ -373,7 +375,7 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, * new serio device. It looks whether it was registered as a H3600 touchscreen * and if yes, registers it as an input device. */ -static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) +static void h3600ts_connect(struct serio *serio, struct serio_driver *drv) { struct h3600_dev *ts; @@ -441,7 +443,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev) ts->dev.id.product = 0x0666; /* FIXME !!! We can ask the hardware */ ts->dev.id.version = 0x0100; - if (serio_open(serio, dev)) { + if (serio_open(serio, drv)) { free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); kfree(ts); @@ -478,10 +480,14 @@ static void h3600ts_disconnect(struct serio *serio) * The serio device structure. */ -static struct serio_dev h3600ts_dev = { - .interrupt = h3600ts_interrupt, - .connect = h3600ts_connect, - .disconnect = h3600ts_disconnect, +static struct serio_driver h3600ts_drv = { + .driver = { + .name = "h3600ts", + }, + .description = DRIVER_DESC, + .interrupt = h3600ts_interrupt, + .connect = h3600ts_connect, + .disconnect = h3600ts_disconnect, }; /* @@ -490,13 +496,13 @@ static struct serio_dev h3600ts_dev = { static int __init h3600ts_init(void) { - serio_register_device(&h3600ts_dev); + serio_register_driver(&h3600ts_drv); return 0; } static void __exit h3600ts_exit(void) { - serio_unregister_device(&h3600ts_dev); + serio_unregister_driver(&h3600ts_drv); } module_init(h3600ts_init); diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index ac072d37c..9c00dbd39 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c @@ -1,34 +1,44 @@ /* * $Id: tsdev.c,v 1.15 2002/04/10 16:50:19 jsimmons Exp $ * - * Copyright (c) 2001 "Crazy" james Simmons + * Copyright (c) 2001 "Crazy" james Simmons * - * Input driver to Touchscreen device driver module. + * Compaq touchscreen protocol driver. The protocol emulated by this driver + * is obsolete; for new programs use the tslib library which can read directly + * from evdev and perform dejittering, variance filtering and calibration - + * all in user space, not at kernel level. The meaning of this driver is + * to allow usage of newer input drivers with old applications that use the + * old /dev/h3600_ts and /dev/h3600_tsraw devices. * - * Sponsored by Transvirtual Technology + * 09-Apr-2004: Andrew Zabolotny + * Fixed to actually work, not just output random numbers. + * Added support for both h3600_ts and h3600_tsraw protocol + * emulation. */ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to . + * e-mail - mail your message to . */ #define TSDEV_MINOR_BASE 128 #define TSDEV_MINORS 32 +/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ +#define TSDEV_MINOR_MASK 15 #define TSDEV_BUFFER_SIZE 64 #include @@ -52,48 +62,84 @@ #define CONFIG_INPUT_TSDEV_SCREEN_Y 320 #endif +/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw + * devices. The first one must output X/Y data in 'cooked' format, e.g. + * filtered, dejittered and calibrated. Second device just outputs raw + * data received from the hardware. + * + * This driver doesn't support filtering and dejittering; it supports only + * calibration. Filtering and dejittering must be done in the low-level + * driver, if needed, because it may gain additional benefits from knowing + * the low-level details, the nature of noise and so on. + * + * The driver precomputes a calibration matrix given the initial xres and + * yres values (quite innacurate for most touchscreens) that will result + * in a more or less expected range of output values. The driver supports + * the TS_SET_CAL ioctl, which will replace the calibration matrix with a + * new one, supposedly generated from the values taken from the raw device. + */ + MODULE_AUTHOR("James Simmons "); MODULE_DESCRIPTION("Input driver to touchscreen converter"); MODULE_LICENSE("GPL"); static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; module_param(xres, uint, 0); -MODULE_PARM_DESC(xres, "Horizontal screen resolution"); +MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; module_param(yres, uint, 0); -MODULE_PARM_DESC(yres, "Vertical screen resolution"); +MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); + +/* From Compaq's Touch Screen Specification version 0.2 (draft) */ +struct ts_event { + short pressure; + short x; + short y; + short millisecs; +}; + +struct ts_calibration { + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; struct tsdev { int exist; int open; int minor; - char name[16]; + char name[8]; wait_queue_head_t wait; struct list_head list; struct input_handle handle; + int x, y, pressure; + struct ts_calibration cal; }; -/* From Compaq's Touch Screen Specification version 0.2 (draft) */ -typedef struct { - short pressure; - short x; - short y; - short millisecs; -} TS_EVENT; - struct tsdev_list { struct fasync_struct *fasync; struct list_head node; struct tsdev *tsdev; int head, tail; - int oldx, oldy, pendown; - TS_EVENT event[TSDEV_BUFFER_SIZE]; + struct ts_event event[TSDEV_BUFFER_SIZE]; + int raw; }; +/* The following ioctl codes are defined ONLY for backward compatibility. + * Don't use tsdev for new developement; use the tslib library instead. + * Touchscreen calibration is a fully userspace task. + */ +/* Use 'f' as magic number */ +#define IOC_H3600_TS_MAGIC 'f' +#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) +#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) + static struct input_handler tsdev_handler; -static struct tsdev *tsdev_table[TSDEV_MINORS]; +static struct tsdev *tsdev_table[TSDEV_MINORS/2]; static int tsdev_fasync(int fd, struct file *file, int on) { @@ -109,13 +155,16 @@ static int tsdev_open(struct inode *inode, struct file *file) int i = iminor(inode) - TSDEV_MINOR_BASE; struct tsdev_list *list; - if (i >= TSDEV_MINORS || !tsdev_table[i]) + if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) return -ENODEV; if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL))) return -ENOMEM; memset(list, 0, sizeof(struct tsdev_list)); + list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; + + i &= TSDEV_MINOR_MASK; list->tsdev = tsdev_table[i]; list_add_tail(&list->node, &tsdev_table[i]->list); file->private_data = list; @@ -128,8 +177,6 @@ static int tsdev_open(struct inode *inode, struct file *file) static void tsdev_free(struct tsdev *tsdev) { - devfs_remove("input/ts%d", tsdev->minor); - class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); tsdev_table[tsdev->minor] = NULL; kfree(tsdev); } @@ -161,7 +208,7 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, return -EAGAIN; retval = wait_event_interruptible(list->tsdev->wait, - (list->head != list->tail) && list->tsdev->exist); + list->head != list->tail || !list->tsdev->exist); if (retval) return retval; @@ -169,11 +216,13 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count, if (!list->tsdev->exist) return -ENODEV; - while (list->head != list->tail && retval + sizeof(TS_EVENT) <= count) { - if (copy_to_user (buffer + retval, list->event + list->tail, sizeof(TS_EVENT))) + while (list->head != list->tail && + retval + sizeof (struct ts_event) <= count) { + if (copy_to_user (buffer + retval, list->event + list->tail, + sizeof (struct ts_event))) return -EFAULT; list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); - retval += sizeof(TS_EVENT); + retval += sizeof (struct ts_event); } return retval; @@ -193,22 +242,27 @@ static unsigned int tsdev_poll(struct file *file, poll_table * wait) static int tsdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { -/* struct tsdev_list *list = file->private_data; - struct tsdev *evdev = list->tsdev; - struct input_dev *dev = tsdev->handle.dev; - int retval; - + struct tsdev *tsdev = list->tsdev; + int retval = 0; + switch (cmd) { - case HHEHE: - return 0; - case hjff: - return 0; - default: - return 0; + case TS_GET_CAL: + if (copy_to_user ((void __user *)arg, &tsdev->cal, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + case TS_SET_CAL: + if (copy_from_user (&tsdev->cal, (void __user *)arg, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + default: + retval = -EINVAL; + break; } -*/ - return -EINVAL; + + return retval; } struct file_operations tsdev_fops = { @@ -227,82 +281,85 @@ static void tsdev_event(struct input_handle *handle, unsigned int type, struct tsdev *tsdev = handle->private; struct tsdev_list *list; struct timeval time; - int size; - list_for_each_entry(list, &tsdev->list, node) { - switch (type) { - case EV_ABS: - switch (code) { - case ABS_X: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - if (size > 0) - list->oldx = ((value - handle->dev->absmin[ABS_X]) * xres / size); - else - list->oldx = ((value - handle->dev->absmin[ABS_X])); - break; - case ABS_Y: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; - if (size > 0) - list->oldy = ((value - handle->dev->absmin[ABS_Y]) * yres / size); - else - list->oldy = ((value - handle->dev->absmin[ABS_Y])); - break; - case ABS_PRESSURE: - list->pendown = ((value > handle->dev-> absmin[ABS_PRESSURE])) ? - value - handle->dev->absmin[ABS_PRESSURE] : 0; - break; - } + switch (type) { + case EV_ABS: + switch (code) { + case ABS_X: + tsdev->x = value; + break; + case ABS_Y: + tsdev->y = value; + break; + case ABS_PRESSURE: + if (value > handle->dev->absmax[ABS_PRESSURE]) + value = handle->dev->absmax[ABS_PRESSURE]; + value -= handle->dev->absmin[ABS_PRESSURE]; + if (value < 0) + value = 0; + tsdev->pressure = value; + break; + } + break; + + case EV_REL: + switch (code) { + case REL_X: + tsdev->x += value; + if (tsdev->x < 0) + tsdev->x = 0; + else if (tsdev->x > xres) + tsdev->x = xres; + break; + case REL_Y: + tsdev->y += value; + if (tsdev->y < 0) + tsdev->y = 0; + else if (tsdev->y > yres) + tsdev->y = yres; break; + } + break; - case EV_REL: - switch (code) { - case REL_X: - if (!list->pendown) - return; - list->oldx += value; - if (list->oldx < 0) - list->oldx = 0; - else if (list->oldx > xres) - list->oldx = xres; + case EV_KEY: + if (code == BTN_TOUCH || code == BTN_MOUSE) { + switch (value) { + case 0: + tsdev->pressure = 0; break; - case REL_Y: - if (!list->pendown) - return; - list->oldy += value; - if (list->oldy < 0) - list->oldy = 0; - else if (list->oldy > xres) - list->oldy = xres; + case 1: + if (!tsdev->pressure) + tsdev->pressure = 1; break; } - break; - - case EV_KEY: - if (code == BTN_TOUCH || code == BTN_MOUSE) { - switch (value) { - case 0: - list->pendown = 0; - break; - case 1: - if (!list->pendown) - list->pendown = 1; - break; - case 2: - return; - } - } else - return; - break; } + break; + } + + if (type != EV_SYN || code != SYN_REPORT) + return; + + list_for_each_entry(list, &tsdev->list, node) { + int x, y, tmp; + do_gettimeofday(&time); list->event[list->head].millisecs = time.tv_usec / 100; - list->event[list->head].pressure = list->pendown; - list->event[list->head].x = list->oldx; - list->event[list->head].y = list->oldy; + list->event[list->head].pressure = tsdev->pressure; + + x = tsdev->x; + y = tsdev->y; + + /* Calibration */ + if (!list->raw) { + x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; + y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; + if (tsdev->cal.xyswap) { + tmp = x; x = y; y = tmp; + } + } + + list->event[list->head].x = x; + list->event[list->head].y = y; list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } @@ -314,11 +371,11 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, struct input_device_id *id) { struct tsdev *tsdev; - int minor; + int minor, delta; - for (minor = 0; minor < TSDEV_MINORS && tsdev_table[minor]; + for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor]; minor++); - if (minor == TSDEV_MINORS) { + if (minor >= TSDEV_MINORS/2) { printk(KERN_ERR "tsdev: You have way too many touchscreens\n"); return NULL; @@ -340,11 +397,26 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, tsdev->handle.handler = handler; tsdev->handle.private = tsdev; + /* Precompute the rough calibration matrix */ + delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.xscale = (xres << 8) / delta; + tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); + + delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.yscale = (yres << 8) / delta; + tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); + tsdev_table[minor] = tsdev; - + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor); - class_simple_device_add(input_class, + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2), + S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor); + class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), dev->dev, "ts%d", minor); @@ -355,6 +427,9 @@ static void tsdev_disconnect(struct input_handle *handle) { struct tsdev *tsdev = handle->private; + class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); + devfs_remove("input/ts%d", tsdev->minor); + devfs_remove("input/tsraw%d", tsdev->minor); tsdev->exist = 0; if (tsdev->open) { @@ -379,6 +454,12 @@ static struct input_device_id tsdev_ids[] = { .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, },/* A tablet like device, at least touch detection, two absolute axes */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, + },/* A tablet like device with several gradations of pressure */ + {},/* Terminating entry */ }; diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c index e84aa5fb3..df7923c5b 100644 --- a/drivers/isdn/act2000/act2000_isa.c +++ b/drivers/isdn/act2000/act2000_isa.c @@ -18,13 +18,6 @@ static act2000_card *irq2card_map[16]; -static void -act2000_isa_delay(long t) -{ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(t); -} - /* * Reset Controller, then try to read the Card's signature. + Return: @@ -419,7 +412,7 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb) if (!act2000_isa_reset(card->port)) return -ENXIO; - act2000_isa_delay(HZ / 2); + msleep_interruptible(500); if(copy_from_user(&cblock, cb, sizeof(cblock))) return -EFAULT; length = cblock.length; @@ -434,7 +427,10 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb) l = (length > 1024) ? 1024 : length; c = 0; b = buf; - copy_from_user(buf, p, l); + if (copy_from_user(buf, p, l)) { + kfree(buf); + return -EFAULT; + } while (c < l) { if (act2000_isa_writeb(card, *b++)) { printk(KERN_WARNING @@ -449,6 +445,6 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb) p += l; } kfree(buf); - act2000_isa_delay(HZ / 2); + msleep_interruptible(500); return (act2000_isa_getid(card)); } diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3429d57e2..e1eae8287 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -67,10 +68,10 @@ int capi_ttymajor = 191; int capi_ttyminors = CAPINC_NR_PORTS; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -MODULE_PARM(capi_major, "i"); +module_param_named(major, capi_major, uint, 0); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -MODULE_PARM(capi_ttymajor, "i"); -MODULE_PARM(capi_ttyminors, "i"); +module_param_named(ttymajor, capi_ttymajor, uint, 0); +module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- defines ------------------------------------------------- */ @@ -436,51 +437,62 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) struct sk_buff *nskb; int datalen; u16 errcode, datahandle; - + struct tty_ldisc *ld; + datalen = skb->len - CAPIMSG_LEN(skb->data); - if (mp->tty) { - if (mp->tty->ldisc.receive_buf == 0) { - printk(KERN_ERR "capi: ldisc has no receive_buf function\n"); - return -1; - } - if (mp->ttyinstop) { + if (mp->tty == NULL) + { +#ifdef _DEBUG_DATAFLOW + printk(KERN_DEBUG "capi: currently no receiver\n"); +#endif + return -1; + } + + ld = tty_ldisc_ref(mp->tty); + if (ld == NULL) + return -1; + if (ld->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: recv tty throttled\n"); + printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - return -1; - } - if (mp->tty->ldisc.receive_room && - mp->tty->ldisc.receive_room(mp->tty) < datalen) { + goto bad; + } + if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: no room in tty\n"); + printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - return -1; - } - if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) { - printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - return -1; - } - datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); - errcode = capi20_put_message(mp->ap, nskb); - if (errcode != CAPI_NOERROR) { - printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", - errcode); - kfree_skb(nskb); - return -1; - } - (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); + goto bad; + } + if (ld->receive_room && + ld->receive_room(mp->tty) < datalen) { +#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) + printk(KERN_DEBUG "capi: no room in tty\n"); #endif - mp->tty->ldisc.receive_buf(mp->tty, skb->data, NULL, skb->len); - kfree_skb(skb); - return 0; - + goto bad; + } + if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) { + printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); + goto bad; + } + datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); + errcode = capi20_put_message(mp->ap, nskb); + if (errcode != CAPI_NOERROR) { + printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", + errcode); + kfree_skb(nskb); + goto bad; } + (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); #ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: currently no receiver\n"); + printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); #endif + ld->receive_buf(mp->tty, skb->data, NULL, skb->len); + kfree_skb(skb); + tty_ldisc_deref(ld); + return 0; +bad: + tty_ldisc_deref(ld); return -1; } @@ -614,6 +626,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { + datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", @@ -633,10 +646,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif kfree_skb(skb); (void)capiminor_del_ack(mp, datahandle); - if (mp->tty) { - if (mp->tty->ldisc.write_wakeup) - mp->tty->ldisc.write_wakeup(mp->tty); - } + if (mp->tty) + tty_wakeup(mp->tty); (void)handle_minor_send(mp); } else { @@ -1034,16 +1045,14 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #endif } -static int capinc_tty_write(struct tty_struct * tty, int from_user, +static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb; - int retval; #ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n", - from_user, count); + printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif if (!mp || !mp->nccip) { @@ -1067,18 +1076,7 @@ static int capinc_tty_write(struct tty_struct * tty, int from_user, } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - if (from_user) { - retval = copy_from_user(skb_put(skb, count), buf, count); - if (retval) { - kfree_skb(skb); -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval); -#endif - return -EFAULT; - } - } else { - memcpy(skb_put(skb, count), buf, count); - } + memcpy(skb_put(skb, count), buf, count); skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 150e31d32..3eae6a563 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -MODULE_PARM(debugmode, "i"); +module_param(debugmode, uint, 0); /* -------- type definitions ----------------------------------------- */ @@ -512,7 +513,8 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg) len = CAPIMSG_LEN(cmsg->buf); skb = alloc_skb(len, GFP_ATOMIC); memcpy(skb_put(skb, len), cmsg->buf, len); - capi20_put_message(&global.ap, skb); + if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR) + kfree_skb(skb); } /* -------- state machine -------------------------------------------- */ @@ -2056,6 +2058,10 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) return -1; } card->myid = card->interface.channels; + memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan); + for (i = 0; i < card->nbchan; i++) { + card->bchans[i].contr = card; + } spin_lock_irqsave(&global_lock, flags); card->next = global.contr_list; @@ -2063,11 +2069,6 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) global.ncontr++; spin_unlock_irqrestore(&global_lock, flags); - memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan); - for (i = 0; i < card->nbchan; i++) { - card->bchans[i].contr = card; - } - cmd.command = ISDN_STAT_RUN; cmd.driver = card->myid; card->interface.statcallb(&cmd); @@ -2075,10 +2076,9 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) card->cipmask = 0x1FFF03FF; /* any */ card->cipmask2 = 0; - send_listen(card); - card->listentimer.data = (unsigned long)card; card->listentimer.function = listentimerfunc; + send_listen(card); mod_timer(&card->listentimer, jiffies + 60*HZ); printk(KERN_INFO "%s: now up (%d B channels)\n", diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 8d58cfd45..e3f603c6c 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,7 +42,7 @@ static int showcapimsgs = 0; MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -MODULE_PARM(showcapimsgs, "i"); +module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ @@ -148,7 +150,10 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param { card = capi_ctr_get(card); - card->register_appl(card, applid, rparam); + if (card) + card->register_appl(card, applid, rparam); + else + printk(KERN_WARNING "%s: cannot get card resources\n", __FUNCTION__); } @@ -171,10 +176,15 @@ static void notify_up(u32 contr) if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); } - + if (!card) { + printk(KERN_WARNING "%s: invalid contr %d\n", __FUNCTION__, contr); + return; + } for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && ap->callback && !ap->release_in_progress) + if (!ap || ap->release_in_progress) continue; + register_appl(card, applid, &ap->rparam); + if (ap->callback && !ap->release_in_progress) ap->callback(KCI_CONTRUP, contr, &card->profile); } } @@ -317,19 +327,8 @@ EXPORT_SYMBOL(capi_ctr_handle_message); void capi_ctr_ready(struct capi_ctr * card) { - u16 appl; - struct capi20_appl *ap; - card->cardstate = CARD_RUNNING; - down(&controller_sem); - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - ap = get_capi_appl_by_nr(appl); - if (!ap || ap->release_in_progress) continue; - register_appl(card, appl, &ap->rparam); - } - up(&controller_sem); - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", card->cnr, card->name); @@ -831,8 +830,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) while (card->cardstate != CARD_RUNNING) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); /* 0.1 sec */ + msleep_interruptible(100); /* 0.1 sec */ if (signal_pending(current)) { capi_ctr_put(card); @@ -856,8 +854,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) while (card->cardstate > CARD_DETECTED) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); /* 0.1 sec */ + msleep_interruptible(100); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index ede2b7eb7..434e684f5 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -12,17 +12,14 @@ #include #include #include +#include + #include "isdn_divert.h" MODULE_DESCRIPTION("ISDN4Linux: Call diversion support"); MODULE_AUTHOR("Werner Cornelius"); MODULE_LICENSE("GPL"); -/********************/ -/* needed externals */ -/********************/ -extern int printk(const char *fmt,...); - /****************************************/ /* structure containing interface to hl */ /****************************************/ @@ -59,23 +56,23 @@ static int __init divert_init(void) /* Module deinit code */ /**********************/ static void __exit divert_exit(void) -{ unsigned long flags; +{ + unsigned long flags; int i; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); divert_if.cmd = DIVERT_CMD_REL; /* release */ if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); return; } if (divert_dev_deinit()) { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); return; } - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); deleterule(-1); /* delete all rules and free mem */ deleteprocs(); printk(KERN_INFO "dss1_divert module successfully removed \n"); diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index d3506ee85..9571f0392 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -22,6 +22,7 @@ #include #include "isdn_divert.h" + /*********************************/ /* Variables for interface queue */ /*********************************/ @@ -76,7 +77,7 @@ put_info_buffer(char *cp) /* deflection device read routine */ /**********************************/ static ssize_t -isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off) +isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t * off) { struct divert_info *inf; int len; @@ -90,7 +91,7 @@ isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off) return (0); inf->usage_cnt--; /* new usage count */ - (struct divert_info **) file->private_data = &inf->next; /* next structure */ + file->private_data = &inf->next; /* next structure */ if ((len = strlen(inf->info_start)) <= count) { if (copy_to_user(buf, inf->info_start, len)) return -EFAULT; @@ -104,7 +105,7 @@ isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off) /* deflection device write routine */ /**********************************/ static ssize_t -isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t * off) +isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t * off) { return (-ENODEV); } /* isdn_divert_write */ @@ -137,9 +138,9 @@ isdn_divert_open(struct inode *ino, struct file *filep) spin_lock_irqsave( &divert_info_lock, flags ); if_used++; if (divert_info_head) - (struct divert_info **) filep->private_data = &(divert_info_tail->next); + filep->private_data = &(divert_info_tail->next); else - (struct divert_info **) filep->private_data = &divert_info_head; + filep->private_data = &divert_info_head; spin_unlock_irqrestore( &divert_info_lock, flags ); /* start_divert(); */ return nonseekable_open(ino, filep); @@ -184,7 +185,7 @@ isdn_divert_ioctl(struct inode *inode, struct file *file, divert_rule *rulep; char *cp; - if (copy_from_user(&dioctl, (char *) arg, sizeof(dioctl))) + if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl))) return -EFAULT; switch (cmd) { @@ -215,10 +216,9 @@ isdn_divert_ioctl(struct inode *inode, struct file *file, case IIOCMODRULE: if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) return (-EINVAL); - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); *rulep = dioctl.getsetrule.rule; /* copy data */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); return (0); /* no copy required */ break; @@ -253,7 +253,7 @@ isdn_divert_ioctl(struct inode *inode, struct file *file, default: return (-EINVAL); } /* switch cmd */ - return copy_to_user((char *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; + return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; } /* isdn_divert_ioctl */ diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 568530d54..89c72c842 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -11,6 +11,7 @@ #include #include + #include "isdn_divert.h" /**********************************/ @@ -47,54 +48,53 @@ static struct deflect_struc *table_head = NULL; static struct deflect_struc *table_tail = NULL; static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ +spinlock_t divert_lock = SPIN_LOCK_UNLOCKED; + /***************************/ /* timer callback function */ /***************************/ static void deflect_timer_expire(ulong arg) -{ unsigned long flags; +{ + unsigned long flags; struct call_struc *cs = (struct call_struc *) arg; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); del_timer(&cs->timer); /* delete active timer */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); switch(cs->akt_state) { case DEFLECT_PROCEED: cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ divert_if.ll_cmd(&cs->ics); - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); break; case DEFLECT_ALERT: cs->ics.command = ISDN_CMD_REDIR; /* protocol */ strcpy(cs->ics.parm.setup.phone,cs->deflect_dest); strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed"); - divert_if.ll_cmd(&cs->ics); - save_flags(flags); - cli(); + divert_if.ll_cmd(&cs->ics); + spin_lock_irqsave(&divert_lock, flags); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); break; case DEFLECT_AUTODEL: default: - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); if (cs->prev) cs->prev->next = cs->next; /* forward link */ else divert_head = cs->next; if (cs->next) cs->next->prev = cs->prev; /* back link */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); kfree(cs); return; @@ -166,10 +166,9 @@ int cf_command(int drvid, int mode, cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); *procid = cs->ics.parm.dss1_io.ll_id; sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n", @@ -187,11 +186,10 @@ int cf_command(int drvid, int mode, if (!retval) { cs->prev = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs->next = divert_head; divert_head = cs; - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); } else kfree(cs); @@ -224,13 +222,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) { case 0: /* hangup */ del_timer(&cs->timer); ic.command = ISDN_CMD_HANGUP; - i = divert_if.ll_cmd(&ic); - save_flags(flags); - cli(); + i = divert_if.ll_cmd(&ic); + spin_lock_irqsave(&divert_lock, flags); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); break; case 1: /* alert */ @@ -239,12 +236,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) del_timer(&cs->timer); ic.command = ISDN_CMD_ALERT; if ((i = divert_if.ll_cmd(&ic))) - { save_flags(flags); - cli(); + { + spin_lock_irqsave(&divert_lock, flags); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); } else cs->akt_state = DEFLECT_ALERT; @@ -256,12 +253,12 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); ic.command = ISDN_CMD_REDIR; if ((i = divert_if.ll_cmd(&ic))) - { save_flags(flags); - cli(); + { + spin_lock_irqsave(&divert_lock, flags); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); } else cs->akt_state = DEFLECT_ALERT; @@ -284,8 +281,7 @@ int insertrule(int idx, divert_rule *newrule) ds->rule = *newrule; /* set rule */ - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); if (idx >= 0) { ds1 = table_head; @@ -313,7 +309,7 @@ int insertrule(int idx, divert_rule *newrule) table_head = ds; /* first element */ } - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); return(0); } /* insertrule */ @@ -325,12 +321,11 @@ int deleterule(int idx) unsigned long flags; if (idx < 0) - { save_flags(flags); - cli(); + { spin_lock_irqsave(&divert_lock, flags); ds = table_head; table_head = NULL; table_tail = NULL; - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); while (ds) { ds1 = ds; ds = ds->next; @@ -339,8 +334,7 @@ int deleterule(int idx) return(0); } - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); ds = table_head; while ((ds) && (idx > 0)) @@ -349,7 +343,8 @@ int deleterule(int idx) } if (!ds) - { restore_flags(flags); + { + spin_unlock_irqrestore(&divert_lock, flags); return(-EINVAL); } @@ -363,7 +358,7 @@ int deleterule(int idx) else table_head = ds->next; /* start of chain */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); kfree(ds); return(0); } /* deleterule */ @@ -474,10 +469,9 @@ int isdn_divert_icall(isdn_ctrl *ic) else cs->timer.expires = 0; cs->akt_state = dv->rule.action; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs->divert_id = next_id++; /* new sequence number */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); cs->prev = NULL; if (cs->akt_state == DEFLECT_ALERT) { strcpy(cs->deflect_dest,dv->rule.to_nr); @@ -525,12 +519,11 @@ int isdn_divert_icall(isdn_ctrl *ic) if (cs) { cs->prev = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs->next = divert_head; divert_head = cs; if (cs->timer.expires) add_timer(&cs->timer); - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); put_info_buffer(cs->info); return(retval); @@ -544,8 +537,7 @@ void deleteprocs(void) { struct call_struc *cs, *cs1; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); cs = divert_head; divert_head = NULL; while (cs) @@ -554,7 +546,7 @@ void deleteprocs(void) cs = cs->next; kfree(cs1); } - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); } /* deleteprocs */ /****************************************************/ @@ -769,8 +761,8 @@ int prot_stat_callback(isdn_ctrl *ic) } if (cs1->ics.driver == -1) - { save_flags(flags); - cli(); + { + spin_lock_irqsave(&divert_lock, flags); del_timer(&cs1->timer); if (cs1->prev) cs1->prev->next = cs1->next; /* forward link */ @@ -778,7 +770,7 @@ int prot_stat_callback(isdn_ctrl *ic) divert_head = cs1->next; if (cs1->next) cs1->next->prev = cs1->prev; /* back link */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); kfree(cs1); } @@ -826,15 +818,14 @@ int isdn_divert_stat_callback(isdn_ctrl *ic) cs = cs->next; if (cs1->ics.driver == -1) { - save_flags(flags); - cli(); + spin_lock_irqsave(&divert_lock, flags); if (cs1->prev) cs1->prev->next = cs1->next; /* forward link */ else divert_head = cs1->next; if (cs1->next) cs1->next->prev = cs1->prev; /* back link */ - restore_flags(flags); + spin_unlock_irqrestore(&divert_lock, flags); kfree(cs1); } } diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h index 08df6f492..19439a617 100644 --- a/drivers/isdn/divert/isdn_divert.h +++ b/drivers/isdn/divert/isdn_divert.h @@ -114,6 +114,8 @@ struct divert_info /**************/ /* Prototypes */ /**************/ +extern spinlock_t divert_lock; + extern ulong if_used; /* number of interface users */ extern int divert_dev_deinit(void); extern int divert_dev_init(void); diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig index 25f494aed..29a32a883 100644 --- a/drivers/isdn/hardware/avm/Kconfig +++ b/drivers/isdn/hardware/avm/Kconfig @@ -12,13 +12,13 @@ config CAPI_AVM config ISDN_DRV_AVMB1_B1ISA tristate "AVM B1 ISA support" - depends on CAPI_AVM && ISDN_CAPI && ISA && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI && ISA help Enable support for the ISA version of the AVM B1 card. config ISDN_DRV_AVMB1_B1PCI tristate "AVM B1 PCI support" - depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI && PCI help Enable support for the PCI version of the AVM B1 card. @@ -30,14 +30,14 @@ config ISDN_DRV_AVMB1_B1PCIV4 config ISDN_DRV_AVMB1_T1ISA tristate "AVM T1/T1-B ISA support" - depends on CAPI_AVM && ISDN_CAPI && ISA && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI && ISA help Enable support for the AVM T1 T1B card. Note: This is a PRI card and handle 30 B-channels. config ISDN_DRV_AVMB1_B1PCMCIA tristate "AVM B1/M1/M2 PCMCIA support" - depends on CAPI_AVM && ISDN_CAPI && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI help Enable support for the PCMCIA version of the AVM B1 card. @@ -50,14 +50,14 @@ config ISDN_DRV_AVMB1_AVM_CS config ISDN_DRV_AVMB1_T1PCI tristate "AVM T1/T1-B PCI support" - depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI && PCI help Enable support for the AVM T1 T1B card. Note: This is a PRI card and handle 30 B-channels. config ISDN_DRV_AVMB1_C4 tristate "AVM C4/C2 support" - depends on CAPI_AVM && ISDN_CAPI && PCI && BROKEN_ON_SMP + depends on CAPI_AVM && ISDN_CAPI && PCI help Enable support for the AVM C4/C2 PCI cards. These cards handle 4/2 BRI ISDN lines (8/4 channels). diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index c87516ab2..0c7061d55 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -389,7 +389,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) CAPIMSG_NCCI(skb->data), CAPIMSG_MSGID(skb->data)); if (retval != CAPI_NOERROR) - goto out; + return retval; dlen = CAPIMSG_DATALEN(skb->data); @@ -399,16 +399,14 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) b1_put_slice(port, skb->data + len, dlen); spin_unlock_irqrestore(&card->lock, flags); } else { - retval = CAPI_NOERROR; - spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); b1_put_slice(port, skb->data, len); spin_unlock_irqrestore(&card->lock, flags); } - out: + dev_kfree_skb_any(skb); - return retval; + return CAPI_NOERROR; } /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index d2c69b727..55bed00ca 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -839,8 +839,6 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) } if (retval == CAPI_NOERROR) b1dma_queue_tx(card, skb); - else - dev_kfree_skb_any(skb); return retval; } diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 9e1285ca5..0e40acac7 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -662,15 +662,16 @@ static void c4_handle_rx(avmcard *card) static irqreturn_t c4_handle_interrupt(avmcard *card) { + unsigned long flags; u32 status; - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); status = c4inmeml(card->mbase+DOORBELL); if (status & DBELL_RESET_HOST) { u_int i; c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); if (card->nlogcontr == 0) return IRQ_HANDLED; printk(KERN_ERR "%s: unexpected reset\n", card->name); @@ -686,7 +687,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); if (!status) { - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return IRQ_HANDLED; } c4outmeml(card->mbase+DOORBELL, status); @@ -709,7 +710,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) c4_dispatch_tx(card); } } - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return IRQ_HANDLED; } @@ -1029,8 +1030,6 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); spin_unlock_irqrestore(&card->lock, flags); - } else { - dev_kfree_skb_any(skb); } return retval; } diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index 9d777ebc8..cb9d9cee2 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -472,7 +472,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) CAPIMSG_NCCI(skb->data), CAPIMSG_MSGID(skb->data)); if (retval != CAPI_NOERROR) - goto out; + return retval; dlen = CAPIMSG_DATALEN(skb->data); @@ -482,16 +482,15 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) t1_put_slice(port, skb->data + len, dlen); spin_unlock_irqrestore(&card->lock, flags); } else { - retval = CAPI_NOERROR; spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); t1_put_slice(port, skb->data, len); spin_unlock_irqrestore(&card->lock, flags); } - out: + dev_kfree_skb_any(skb); - return retval; + return CAPI_NOERROR; } /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c index 15d081a09..7235d2170 100644 --- a/drivers/isdn/hardware/eicon/capifunc.c +++ b/drivers/isdn/hardware/eicon/capifunc.c @@ -1,4 +1,4 @@ -/* $Id: capifunc.c,v 1.61.4.2 2004/05/05 16:09:25 armin Exp $ +/* $Id: capifunc.c,v 1.61.4.5 2004/08/27 20:10:12 armin Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface common functions @@ -240,13 +240,13 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...) DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)", appl->Id, command, (byte *) format)) - WRITE_WORD(&msg.header.appl_id, appl->Id); - WRITE_WORD(&msg.header.command, command); + PUT_WORD(&msg.header.appl_id, appl->Id); + PUT_WORD(&msg.header.command, command); if ((byte) (command >> 8) == 0x82) Number = appl->Number++; - WRITE_WORD(&msg.header.number, Number); + PUT_WORD(&msg.header.number, Number); - WRITE_DWORD(((byte *) & msg.header.controller), Id); + PUT_DWORD(&msg.header.controller, Id); write = (byte *) & msg; write += 12; @@ -261,13 +261,13 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...) break; case 'w': tmp = va_arg(ap, dword); - WRITE_WORD(write, (tmp & 0xffff)); + PUT_WORD(write, (tmp & 0xffff)); write += 2; length += 2; break; case 'd': tmp = va_arg(ap, dword); - WRITE_DWORD(write, tmp); + PUT_DWORD(write, tmp); write += 4; length += 4; break; @@ -282,11 +282,11 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...) } va_end(ap); - WRITE_WORD(&msg.header.length, length); + PUT_WORD(&msg.header.length, length); msg.header.controller = UnMapController(msg.header.controller); if (command == _DATA_B3_I) - dlength = READ_WORD( + dlength = GET_WORD( ((byte *) & msg.info.data_b3_ind.Data_Length)); if (!(dmb = diva_os_alloc_message_buffer(length + dlength, @@ -300,7 +300,7 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...) /* if DATA_B3_IND, copy data too */ if (command == _DATA_B3_I) { - dword data = READ_DWORD(&msg.info.data_b3_ind.Data); + dword data = GET_DWORD(&msg.info.data_b3_ind.Data); memcpy(write + length, (void *) data, dlength); } @@ -318,7 +318,7 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...) if (myDriverDebugHandle.dbgMask & DL_BLK) { xlog("\x00\x02", &msg, 0x81, length); for (i = 0; i < dlength; i += 256) { - DBG_BLK((((char *) READ_DWORD(&msg.info.data_b3_ind.Data)) + i, + DBG_BLK((((char *) GET_DWORD(&msg.info.data_b3_ind.Data)) + i, ((dlength - i) < 256) ? (dlength - i) : 256)) if (!(myDriverDebugHandle.dbgMask & DL_PRV0)) break; /* not more if not explicitely requested */ @@ -700,7 +700,7 @@ static int diva_add_card(DESCRIPTOR * d) } /* profile information */ - WRITE_WORD(&ctrl->profile.nbchannel, card->d.channels); + PUT_WORD(&ctrl->profile.nbchannel, card->d.channels); ctrl->profile.goptions = a->profile.Global_Options; ctrl->profile.support1 = a->profile.B1_Protocols; ctrl->profile.support2 = a->profile.B2_Protocols; @@ -882,11 +882,11 @@ static u16 diva_send_message(struct capi_ctr *ctrl, word ret = 0; diva_os_spin_lock_magic_t old_irql; CAPI_MSG *msg = (CAPI_MSG *) DIVA_MESSAGE_BUFFER_DATA(dmb); - APPL *this = &application[READ_WORD(&msg->header.appl_id) - 1]; + APPL *this = &application[GET_WORD(&msg->header.appl_id) - 1]; diva_card *card = ctrl->driverdata; __u32 length = DIVA_MESSAGE_BUFFER_LEN(dmb); - word clength = READ_WORD(&msg->header.length); - word command = READ_WORD(&msg->header.command); + word clength = GET_WORD(&msg->header.length); + word command = GET_WORD(&msg->header.command); u16 retval = CAPI_NOERROR; if (diva_os_in_irq()) { @@ -932,9 +932,9 @@ static u16 diva_send_message(struct capi_ctr *ctrl, if (clength == 24) clength = 22; /* workaround for PPcom bug */ /* header is always 22 */ - if (READ_WORD(&msg->info.data_b3_req.Data_Length) > + if (GET_WORD(&msg->info.data_b3_req.Data_Length) > this->MaxDataLength - || READ_WORD(&msg->info.data_b3_req.Data_Length) > + || GET_WORD(&msg->info.data_b3_req.Data_Length) > (length - clength)) { DBG_ERR(("Write - invalid message size")) retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL; @@ -952,18 +952,18 @@ static u16 diva_send_message(struct capi_ctr *ctrl, this->xbuffer_internal[i] = NULL; memcpy(this->xbuffer_ptr[i], &((__u8 *) msg)[clength], - READ_WORD(&msg->info.data_b3_req.Data_Length)); + GET_WORD(&msg->info.data_b3_req.Data_Length)); #ifndef DIVA_NO_DEBUGLIB if ((myDriverDebugHandle.dbgMask & DL_BLK) && (myDriverDebugHandle.dbgMask & DL_XLOG)) { int j; for (j = 0; j < - READ_WORD(&msg->info.data_b3_req.Data_Length); + GET_WORD(&msg->info.data_b3_req.Data_Length); j += 256) { DBG_BLK((((char *) this->xbuffer_ptr[i]) + j, - ((READ_WORD(&msg->info.data_b3_req.Data_Length) - j) < - 256) ? (READ_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256)) + ((GET_WORD(&msg->info.data_b3_req.Data_Length) - j) < + 256) ? (GET_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256)) if (!(myDriverDebugHandle.dbgMask & DL_PRV0)) break; /* not more if not explicitely requested */ } @@ -976,7 +976,7 @@ static u16 diva_send_message(struct capi_ctr *ctrl, mapped_msg->header.controller = MapController(mapped_msg->header.controller); mapped_msg->header.length = clength; mapped_msg->header.command = command; - mapped_msg->header.number = READ_WORD(&msg->header.number); + mapped_msg->header.number = GET_WORD(&msg->header.number); ret = api_put(this, mapped_msg); switch (ret) { @@ -998,7 +998,8 @@ static u16 diva_send_message(struct capi_ctr *ctrl, write_end: diva_os_leave_spin_lock(&api_lock, &old_irql, "send message"); - diva_os_free_message_buffer(dmb); + if (retval == CAPI_NOERROR) + diva_os_free_message_buffer(dmb); return retval; } diff --git a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h index 13f6ad242..bd256f297 100644 --- a/drivers/isdn/hardware/eicon/capifunc.h +++ b/drivers/isdn/hardware/eicon/capifunc.h @@ -1,4 +1,4 @@ -/* $Id: capifunc.h,v 1.11 2004/03/20 17:19:58 armin Exp $ +/* $Id: capifunc.h,v 1.11.4.1 2004/08/28 20:03:53 armin Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface common functions @@ -13,8 +13,6 @@ #ifndef __CAPIFUNC_H__ #define __CAPIFUNC_H__ -#define MAX_DESCRIPTORS 32 - #define DRRELMAJOR 2 #define DRRELMINOR 0 #define DRRELEXTRA "" diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index e8e99ad35..6851c6270 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -5,6 +5,7 @@ #include "divasync.h" #include "kst_ifc.h" #include "maintidi.h" +#include "man_defs.h" /* LOCALS @@ -13,17 +14,23 @@ static void DI_register (void *arg); static void DI_deregister (pDbgHandle hDbg); -static void DI_format (int do_lock, word id, int type, char *format, va_list ap); +static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list); static void DI_format_locked (word id, int type, char *format, va_list argument_list); static void DI_format_old (word id, char *format, va_list ap) { } -static void DiProcessEventLog (word id, dword msgID, va_list ap) { } +static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { } static void single_p (byte * P, word * PLength, byte Id); static void diva_maint_xdi_cb (ENTITY* e); static word SuperTraceCreateReadReq (byte* P, const char* path); +static int diva_mnt_cmp_nmbr (const char* nmbr); +static void diva_free_dma_descriptor (IDI_CALL request, int nr); +static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic); void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...); static dword MaxDumpSize = 256 ; static dword MaxXlogSize = 2 + 128 ; +static char TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1]; +static int TraceFilterIdent = -1; +static int TraceFilterChannel = -1; typedef struct _diva_maint_client { dword sec; @@ -40,9 +47,10 @@ typedef struct _diva_maint_client { BUFFERS XData; char xbuffer[2048+512]; byte* pmem; - int request_pending; + int request_pending; + int dma_handle; } diva_maint_client_t; -static diva_maint_client_t clients[64]; +static diva_maint_client_t clients[MAX_DESCRIPTORS]; static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask); @@ -201,6 +209,10 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) { return (-1); } + TraceFilter[0] = 0; + TraceFilterIdent = -1; + TraceFilterChannel = -1; + dbg_base = base; diva_os_get_time (&start_sec, &start_usec); @@ -249,7 +261,6 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) { return (-1); } - return (0); } @@ -302,16 +313,16 @@ diva_dbg_entry_head_t* diva_maint_get_message (word* size, diva_os_spin_lock_magic_t* old_irql) { diva_dbg_entry_head_t* pmsg = NULL; - diva_os_enter_spin_lock_hard (&dbg_q_lock, old_irql, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read"); if (dbg_q_busy) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_busy"); + diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_busy"); return NULL; } dbg_q_busy = 1; if (!(pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, size))) { dbg_q_busy = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_empty"); + diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty"); } return (pmsg); @@ -330,7 +341,7 @@ void diva_maint_ack_message (int do_release, queueFreeMsg (dbg_queue); } dbg_q_busy = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack"); } @@ -378,14 +389,14 @@ static void DI_register (void *arg) { return ; } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register"); for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) { if (clients[id].hDbg == hDbg) { /* driver already registered */ - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); return; } if (clients[id].hDbg) { /* slot is busy */ @@ -468,7 +479,7 @@ static void DI_register (void *arg) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); } static void DI_deregister (pDbgHandle hDbg) { @@ -480,8 +491,8 @@ static void DI_deregister (pDbgHandle hDbg) { diva_os_get_time (&sec, &usec); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read"); for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { if (clients[i].hDbg == hDbg) { @@ -543,8 +554,8 @@ static void DI_deregister (pDbgHandle hDbg) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack"); if (pmem) { diva_os_free (0, pmem); @@ -572,13 +583,22 @@ static void DI_format (int do_lock, char *data; unsigned short code; - if (!format) + if (diva_os_in_irq()) { + dbg_sequence++; return; + } + + if ((!format) || + ((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) { + return; + } + + diva_os_get_time (&sec, &usec); if (do_lock) { - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "format"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "format"); } switch (type) { @@ -703,7 +723,7 @@ static void DI_format (int do_lock, } if (do_lock) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "format"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "format"); } } @@ -720,7 +740,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info"); if (clients[id].hDbg) { *p++ = 1; @@ -757,7 +777,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { } *p++ = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info"); return (p - data); } @@ -769,7 +789,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) { if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info"); if (clients[id].hDbg) { ret = 4; @@ -779,7 +799,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) { *data++= (byte)(clients[id].hDbg->dbgMask >> 24); } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info"); return (ret); } @@ -793,8 +813,8 @@ int diva_set_driver_dbg_mask (dword id, dword mask) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "dbg mask"); if (clients[id].hDbg) { dword old_mask = clients[id].hDbg->dbgMask; @@ -806,14 +826,14 @@ int diva_set_driver_dbg_mask (dword id, dword mask) { } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "dbg mask"); if (clients[id].request_pending) { clients[id].request_pending = 0; (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib)); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); return (ret); } @@ -851,12 +871,12 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { diva_os_get_time (&sec, &usec); diva_get_idi_adapter_info (d->request, &serial, &logical); if (serial & 0xff000000) { - sprintf (tmp, "ADAPTER:%d SN:%d-%d", + sprintf (tmp, "ADAPTER:%d SN:%u-%d", (int)logical, serial & 0x00ffffff, (byte)(((serial & 0xff000000) >> 24) + 1)); } else { - sprintf (tmp, "ADAPTER:%d SN:%d", (int)logical, serial); + sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial); } if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) { @@ -864,13 +884,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { } memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels)); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register"); for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) { if (clients[id].hDbg && (clients[id].request == d->request)) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_free(0, pmem); return; } if (clients[id].hDbg) { /* slot is busy */ @@ -891,8 +912,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { } if (free_id < 0) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_os_free (0, pmem); return; } @@ -908,6 +929,7 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { clients[id].Dbg.drvTag[0] = 0; clients[id].logical = (int)logical; clients[id].channels = (int)d->channels; + clients[id].dma_handle = -1; clients[id].Dbg.dbgMask = 0; clients[id].dbgMask = clients[id].Dbg.dbgMask; @@ -949,8 +971,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { clients[id].request = NULL; clients[id].request_pending = 0; clients[id].hDbg = NULL; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_os_free (0, pmem); return; } @@ -988,14 +1010,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { org_mask = clients[id].Dbg.dbgMask; clients[id].Dbg.dbgMask = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); if (clients[id].request_pending) { clients[id].request_pending = 0; (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib)); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_set_driver_dbg_mask (id, org_mask); } @@ -1012,8 +1034,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { diva_os_get_time (&sec, &usec); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read"); for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { if (clients[i].hDbg && (clients[i].request == d->request)) { @@ -1030,8 +1052,15 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { } clients[i].hDbg = NULL; - clients[i].request = NULL; clients[i].request_pending = 0; + if (clients[i].dma_handle >= 0) { + /* + Free DMA handle + */ + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } + clients[i].request = NULL; /* Log driver register, MAINT driver ID is '0' @@ -1069,8 +1098,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack"); if (pmem) { diva_os_free (0, pmem); @@ -1142,6 +1171,42 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { if (pC && pC->pIdiLib && pC->request) { ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); + IDI_SYNC_REQ* preq; + char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)]; + char features[4]; + word assign_data_length = 1; + + features[0] = 0; + pC->xbuffer[0] = 0; + preq = (IDI_SYNC_REQ*)&buffer[0]; + preq->xdi_extended_features.Req = 0; + preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES; + preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features); + preq->xdi_extended_features.info.features = &features[0]; + + (*(pC->request))((ENTITY*)preq); + + if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && + (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { + dword rx_dma_magic; + if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { + pC->xbuffer[0] = LLI; + pC->xbuffer[1] = 8; + pC->xbuffer[2] = 0x40; + pC->xbuffer[3] = (byte)pC->dma_handle; + pC->xbuffer[4] = (byte)rx_dma_magic; + pC->xbuffer[5] = (byte)(rx_dma_magic >> 8); + pC->xbuffer[6] = (byte)(rx_dma_magic >> 16); + pC->xbuffer[7] = (byte)(rx_dma_magic >> 24); + pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE; + pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8); + pC->xbuffer[10] = 0; + + assign_data_length = 11; + } + } else { + pC->dma_handle = -1; + } e->Id = MAN_ID; e->callback = diva_maint_xdi_cb; @@ -1149,9 +1214,8 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { e->X = &pC->XData; e->Req = ASSIGN; e->ReqCh = 0; - e->X->PLength = 1; + e->X->PLength = assign_data_length; e->X->P = (byte*)&pC->xbuffer[0]; - pC->xbuffer[0] = 0; pC->request_pending = 1; @@ -1300,16 +1364,25 @@ static void diva_maint_xdi_cb (ENTITY* e) { diva_os_spin_lock_magic_t old_irql, old_irql1; - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); pC = (diva_maint_client_t*)pLib->hAdapter; - if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { - diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error"); + if ((e->complete == 255) || (pC->dma_handle < 0)) { + if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { + diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error"); + } + } else { + /* + Process combined management interface indication + */ + if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { + diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)"); + } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); if (pC->request_pending) { @@ -1317,7 +1390,7 @@ static void diva_maint_xdi_cb (ENTITY* e) { (*(pC->request))(e); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); } @@ -1365,8 +1438,42 @@ static void diva_maint_state_change_notify (void* user_context, } switch (notify_subject) { - case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: - if (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS) { + case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: { + int view = (TraceFilter[0] == 0); + /* + Process selective Trace + */ + if (channel->Line[0] == 'I' && channel->Line[1] == 'd' && + channel->Line[2] == 'l' && channel->Line[3] == 'e') { + if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) { + (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0); + (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0); + diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d", + (int)channel->ChannelNumber); + TraceFilterIdent = -1; + TraceFilterChannel = -1; + view = 1; + } + } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) && + diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) { + + if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */ + (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1); + } + if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */ + (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1); + } + + TraceFilterIdent = pC->hDbg->id; + TraceFilterChannel = (int)channel->ChannelNumber; + + if (TraceFilterIdent >= 0) { + diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d", + (int)channel->ChannelNumber); + view = 1; + } + } + if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) { diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch = %d", (int)channel->ChannelNumber); diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]); @@ -1392,10 +1499,26 @@ static void diva_maint_state_change_notify (void* user_context, channel->LastDisconnecCause); diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner = <%s>", &channel->UserID[0]); } - break; + + } break; case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE: if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) { + { + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + if (ch != (int)modem->ChannelNumber) { + break; + } + } else if (TraceFilter[0] != 0) { + break; + } + } + + diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch = %lu", (int)modem->ChannelNumber); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu", modem->Event); @@ -1428,6 +1551,20 @@ static void diva_maint_state_change_notify (void* user_context, case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE: if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) { + { + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + if (ch != (int)fax->ChannelNumber) { + break; + } + } else if (TraceFilter[0] != 0) { + break; + } + } + diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch = %lu",(int)fax->ChannelNumber); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu", fax->Event); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu", fax->Page_Counter); @@ -1660,6 +1797,52 @@ static void diva_maint_trace_notify (void* user_context, diva_dbg_entry_head_t* pmsg; word size; dword sec, usec; + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + /* + Selective trace + */ + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + const char* p = NULL; + int ch_value = -1; + MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer; + + if (Adapter != clients[id].logical) { + return; /* Ignore all trace messages from other adapters */ + } + + if (TrcData->code == 24) { + p = (char*)&TrcData->code; + p += 2; + } + + /* + All L1 messages start as [dsp,ch], so we can filter this information + and filter out all messages that use different channel + */ + if (p && p[0] == '[') { + if (p[2] == ',') { + p += 3; + ch_value = *p - '0'; + } else if (p[3] == ',') { + p += 4; + ch_value = *p - '0'; + } + if (ch_value >= 0) { + if (p[2] == ']') { + ch_value = ch_value * 10 + p[1] - '0'; + } + if (ch_value != ch) { + return; /* Ignore other channels */ + } + } + } + + } else if (TraceFilter[0] != 0) { + return; /* Ignore trace if trace filter is activated, but idle */ + } diva_os_get_time (&sec, &usec); @@ -1705,18 +1888,20 @@ static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword ol (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib, (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0); } - if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) { - int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); + if (!TraceFilter[0]) { + if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) { + int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); - for (i = 0; i < pC->channels; i++) { - (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state); + for (i = 0; i < pC->channels; i++) { + (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state); + } } - } - if (changed & DIVA_MGT_DBG_IFC_AUDIO) { - int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); + if (changed & DIVA_MGT_DBG_IFC_AUDIO) { + int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); - for (i = 0; i < pC->channels; i++) { - (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state); + for (i = 0; i < pC->channels; i++) { + (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state); + } } } } @@ -1743,8 +1928,8 @@ int diva_mnt_shutdown_xdi_adapters (void) { for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { pmem = NULL; - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "unload"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload"); if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) { if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) { @@ -1759,19 +1944,31 @@ int diva_mnt_shutdown_xdi_adapters (void) { clients[i].pmem = NULL; } clients[i].hDbg = NULL; - clients[i].request = NULL; clients[i].request_pending = 0; + + if (clients[i].dma_handle >= 0) { + /* + Free DMA handle + */ + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } + clients[i].request = NULL; } else { fret = -1; } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "unload"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload"); if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) { clients[i].request_pending = 0; (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib)); + if (clients[i].dma_handle >= 0) { + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); if (pmem) { diva_os_free (0, pmem); @@ -1781,3 +1978,156 @@ int diva_mnt_shutdown_xdi_adapters (void) { return (fret); } +/* + Set/Read the trace filter used for selective tracing. + Affects B- and Audio Tap trace mask at run time + */ +int diva_set_trace_filter (int filter_length, const char* filter) { + diva_os_spin_lock_magic_t old_irql, old_irql1; + int i, ch, on, client_b_on, client_atap_on; + + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); + + if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) { + memcpy (&TraceFilter[0], filter, filter_length); + if (TraceFilter[filter_length]) { + TraceFilter[filter_length] = 0; + } + if (TraceFilter[0] == '*') { + TraceFilter[0] = 0; + } + } else { + filter_length = -1; + } + + TraceFilterIdent = -1; + TraceFilterChannel = -1; + + on = (TraceFilter[0] == 0); + + for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { + if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) { + client_b_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); + client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); + for (ch = 0; ch < clients[i].channels; ch++) { + (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on); + (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on); + } + } + } + + for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { + if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) { + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); + clients[i].request_pending = 0; + (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib)); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); + } + } + + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); + + return (filter_length); +} + +int diva_get_trace_filter (int max_length, char* filter) { + diva_os_spin_lock_magic_t old_irql; + int len; + + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter"); + len = strlen (&TraceFilter[0]) + 1; + if (max_length >= len) { + memcpy (filter, &TraceFilter[0], len); + } + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter"); + + return (len); +} + +static int diva_dbg_cmp_key (const char* ref, const char* key) { + while (*key && (*ref++ == *key++)); + return (!*key && !*ref); +} + +/* + In case trace filter starts with "C" character then + all following characters are interpreted as command. + Followings commands are available: + - single, trace single call at time, independent from CPN/CiPN + */ +static int diva_mnt_cmp_nmbr (const char* nmbr) { + const char* ref = &TraceFilter[0]; + int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr); + + if (ref[0] == 'C') { + if (diva_dbg_cmp_key (&ref[1], "single")) { + return (0); + } + return (-1); + } + + if (!ref_len || (ref_len > nmbr_len)) { + return (-1); + } + + nmbr = nmbr + nmbr_len - 1; + ref = ref + ref_len - 1; + + while (ref_len--) { + if (*nmbr-- != *ref--) { + return (-1); + } + } + + return (0); +} + +static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) { + ENTITY e; + IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; + + if (!request) { + return (-1); + } + + pReq->xdi_dma_descriptor_operation.Req = 0; + pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; + + pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC; + pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1; + pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; + pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; + + (*request)((ENTITY*)pReq); + + if (!pReq->xdi_dma_descriptor_operation.info.operation && + (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) && + pReq->xdi_dma_descriptor_operation.info.descriptor_magic) { + *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic; + return (pReq->xdi_dma_descriptor_operation.info.descriptor_number); + } else { + return (-1); + } +} + +static void diva_free_dma_descriptor (IDI_CALL request, int nr) { + ENTITY e; + IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; + + if (!request || (nr < 0)) { + return; + } + + pReq->xdi_dma_descriptor_operation.Req = 0; + pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; + + pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE; + pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr; + pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; + pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; + + (*request)((ENTITY*)pReq); +} + diff --git a/drivers/isdn/hardware/eicon/debug_if.h b/drivers/isdn/hardware/eicon/debug_if.h index 0136eea12..4db739d58 100644 --- a/drivers/isdn/hardware/eicon/debug_if.h +++ b/drivers/isdn/hardware/eicon/debug_if.h @@ -57,12 +57,18 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d); void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d); int diva_mnt_shutdown_xdi_adapters (void); +#define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127 +int diva_set_trace_filter (int filter_length, const char* filter); +int diva_get_trace_filter (int max_length, char* filter); + #define DITRACE_CMD_GET_DRIVER_INFO 1 #define DITRACE_READ_DRIVER_DBG_MASK 2 #define DITRACE_WRITE_DRIVER_DBG_MASK 3 #define DITRACE_READ_TRACE_ENTRY 4 #define DITRACE_READ_TRACE_ENTRYS 5 +#define DITRACE_WRITE_SELECTIVE_TRACE_FILTER 6 +#define DITRACE_READ_SELECTIVE_TRACE_FILTER 7 /* Trace lavels for debug via management interface diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h index 516d2bd8b..11b3b9edd 100644 --- a/drivers/isdn/hardware/eicon/debuglib.h +++ b/drivers/isdn/hardware/eicon/debuglib.h @@ -232,7 +232,7 @@ typedef struct _DbgHandle_ *pDbgHandle ; typedef void ( * DbgEnd) (pDbgHandle) ; typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ; typedef void ( * DbgOld) (unsigned short, char *, va_list) ; -typedef void ( * DbgEv) (unsigned short, unsigned int, va_list) ; +typedef void ( * DbgEv) (unsigned short, unsigned long, va_list) ; typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ; typedef struct _DbgHandle_ { char Registered ; /* driver successfull registered */ @@ -259,7 +259,7 @@ typedef struct _DbgHandle_ void *pReserved3 ; } _DbgHandle_ ; extern _DbgHandle_ myDriverDebugHandle ; -typedef struct +typedef struct _OldDbgHandle_ { struct _OldDbgHandle_ *next ; void *pIrp ; long regTime[2] ; @@ -310,7 +310,7 @@ typedef struct unsigned long B_ChannelMask; unsigned long LogBufferSize; } CardTrace; - } u1; + }Data; } _DbgExtendedInfo_; #ifndef DIVA_NO_DEBUGLIB /* ------------------------------------------------------------- diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c index 24fa5943b..8b10c7889 100644 --- a/drivers/isdn/hardware/eicon/di.c +++ b/drivers/isdn/hardware/eicon/di.c @@ -952,10 +952,10 @@ static void xdi_xlog_rc_event (byte Adapter, byte Id, byte Ch, byte Rc, byte cb, byte type) { #if defined(XDI_USE_XLOG) word LogInfo[4]; - WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); - WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); - WRITE_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8))); - WRITE_WORD(&LogInfo[3], cb); + PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + PUT_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8))); + PUT_WORD(&LogInfo[3], cb); xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo)); #endif } @@ -976,9 +976,9 @@ static void xdi_xlog_request (byte Adapter, byte Id, byte Ch, byte Req, byte type) { #if defined(XDI_USE_XLOG) word LogInfo[3]; - WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); - WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); - WRITE_WORD(&LogInfo[2], ((word)Req | (word)(type << 8))); + PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + PUT_WORD(&LogInfo[2], ((word)Req | (word)(type << 8))); xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo)); #endif } @@ -1020,10 +1020,10 @@ static void xdi_xlog_ind (byte Adapter, byte type) { #if defined(XDI_USE_XLOG) word LogInfo[4]; - WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); - WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); - WRITE_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8))); - WRITE_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8))); + PUT_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + PUT_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + PUT_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8))); + PUT_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8))); xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo)); #endif } diff --git a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c index 33172c1d6..302923417 100644 --- a/drivers/isdn/hardware/eicon/diddfunc.c +++ b/drivers/isdn/hardware/eicon/diddfunc.c @@ -1,4 +1,4 @@ -/* $Id: diddfunc.c,v 1.14 2003/08/25 10:06:37 schindler Exp $ +/* $Id: diddfunc.c,v 1.14.6.2 2004/08/28 20:03:53 armin Exp $ * * DIDD Interface module for Eicon active cards. * @@ -16,8 +16,6 @@ #include "dadapter.h" #include "divasync.h" -#define MAX_DESCRIPTORS 32 - #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c index 0afd015e0..48b3f15bc 100644 --- a/drivers/isdn/hardware/eicon/diva_didd.c +++ b/drivers/isdn/hardware/eicon/diva_didd.c @@ -1,4 +1,4 @@ -/* $Id: diva_didd.c,v 1.13 2003/08/27 10:11:21 schindler Exp $ +/* $Id: diva_didd.c,v 1.13.6.1 2004/08/28 20:03:53 armin Exp $ * * DIDD Interface module for Eicon active cards. * @@ -23,7 +23,7 @@ #include "divasync.h" #include "did_vers.h" -static char *main_revision = "$Revision: 1.13 $"; +static char *main_revision = "$Revision: 1.13.6.1 $"; static char *DRIVERNAME = "Eicon DIVA - DIDD table (http://www.melware.net)"; @@ -37,8 +37,6 @@ MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); MODULE_SUPPORTED_DEVICE("Eicon diva drivers"); MODULE_LICENSE("GPL"); -#define MAX_DESCRIPTORS 32 - #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) @@ -50,8 +48,8 @@ extern void DIVA_DIDD_Read(void *, int); static struct proc_dir_entry *proc_didd; struct proc_dir_entry *proc_net_eicon = NULL; -EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read); -EXPORT_SYMBOL_NOVERS(proc_net_eicon); +EXPORT_SYMBOL(DIVA_DIDD_Read); +EXPORT_SYMBOL(proc_net_eicon); static char *getrev(const char *revision) { diff --git a/drivers/isdn/hardware/eicon/diva_pci.h b/drivers/isdn/hardware/eicon/diva_pci.h index b09e23e3f..cc0d51027 100644 --- a/drivers/isdn/hardware/eicon/diva_pci.h +++ b/drivers/isdn/hardware/eicon/diva_pci.h @@ -3,11 +3,11 @@ #ifndef __DIVA_PCI_INTERFACE_H__ #define __DIVA_PCI_INTERFACE_H__ -void *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, +void __iomem *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, int id, unsigned long bar, unsigned long area_length); -void divasa_unmap_pci_bar(void *bar); +void divasa_unmap_pci_bar(void __iomem *bar); unsigned long divasa_get_pci_irq(unsigned char bus, unsigned char func, void *pci_dev_handle); unsigned long divasa_get_pci_bar(unsigned char bus, diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c index 6b22a8a5f..989cdef60 100644 --- a/drivers/isdn/hardware/eicon/divamnt.c +++ b/drivers/isdn/hardware/eicon/divamnt.c @@ -1,4 +1,4 @@ -/* $Id: divamnt.c,v 1.32 2004/01/15 09:48:13 armin Exp $ +/* $Id: divamnt.c,v 1.32.6.5 2004/08/28 20:03:53 armin Exp $ * * Driver for Eicon DIVA Server ISDN cards. * Maint module @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include "platform.h" @@ -26,7 +24,7 @@ #include "divasync.h" #include "debug_if.h" -static char *main_revision = "$Revision: 1.32 $"; +static char *main_revision = "$Revision: 1.32.6.5 $"; static int major; @@ -47,8 +45,7 @@ static char *DEVNAME = "DivasMAINT"; char *DRIVERRELEASE_MNT = "2.0"; static wait_queue_head_t msgwaitq; -static DECLARE_MUTEX(opened_sem); -static int opened; +static unsigned long opened; static struct timeval start_time; extern int mntfunc_init(int *, void **, unsigned long); @@ -73,20 +70,6 @@ static char *getrev(const char *revision) return rev; } -/* - * buffer alloc - */ -void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size) -{ - return (kmalloc(size, GFP_KERNEL)); -} -void diva_os_free_tbuffer(unsigned long flags, void *ptr) -{ - if (ptr) { - kfree(ptr); - } -} - /* * kernel/user space copy functions */ @@ -131,154 +114,8 @@ void diva_os_get_time(dword * sec, dword * usec) } /* - * /proc entries + * device node operations */ - -extern struct proc_dir_entry *proc_net_eicon; -static struct proc_dir_entry *maint_proc_entry = NULL; - -/* - Read function is provided for compatibility reason - this allows - to read unstructured traces, formated as ascii string only - */ -static ssize_t -maint_read(struct file *file, char __user *buf, size_t count, loff_t * off) -{ - diva_dbg_entry_head_t *pmsg = NULL; - diva_os_spin_lock_magic_t old_irql; - word size; - char *pstr, *dli_label = "UNK"; - int str_length; - int *str_msg; - - if (!file->private_data) { - for (;;) { - while ( - (pmsg = - diva_maint_get_message(&size, - &old_irql))) { - if (!(pmsg->facility == MSG_TYPE_STRING)) { - diva_maint_ack_message(1, - &old_irql); - } else { - break; - } - } - - if (!pmsg) { - if (file->f_flags & O_NONBLOCK) { - return (-EAGAIN); - } - interruptible_sleep_on(&msgwaitq); - if (signal_pending(current)) { - return (-ERESTARTSYS); - } - } else { - break; - } - } - /* - The length of message that shoule be read is: - pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero - */ - if (! - (str_msg = - (int *) diva_os_malloc_tbuffer(0, - pmsg->data_length + - 29 + 2 * sizeof(int)))) { - diva_maint_ack_message(0, &old_irql); - return (-ENOMEM); - } - pstr = (char *) &str_msg[2]; - - switch (pmsg->dli) { - case DLI_LOG: - dli_label = "LOG"; - break; - case DLI_FTL: - dli_label = "FTL"; - break; - case DLI_ERR: - dli_label = "ERR"; - break; - case DLI_TRC: - dli_label = "TRC"; - break; - case DLI_REG: - dli_label = "REG"; - break; - case DLI_MEM: - dli_label = "MEM"; - break; - case DLI_SPL: - dli_label = "SPL"; - break; - case DLI_IRP: - dli_label = "IRP"; - break; - case DLI_TIM: - dli_label = "TIM"; - break; - case DLI_TAPI: - dli_label = "TAPI"; - break; - case DLI_NDIS: - dli_label = "NDIS"; - break; - case DLI_CONN: - dli_label = "CONN"; - break; - case DLI_STAT: - dli_label = "STAT"; - break; - case DLI_PRV0: - dli_label = "PRV0"; - break; - case DLI_PRV1: - dli_label = "PRV1"; - break; - case DLI_PRV2: - dli_label = "PRV2"; - break; - case DLI_PRV3: - dli_label = "PRV3"; - break; - } - str_length = sprintf(pstr, "%s %02x %s\n", - dli_label, (byte) pmsg->drv_id, - (char *) &pmsg[1]); - str_msg[0] = str_length; - str_msg[1] = 0; - file->private_data = str_msg; - diva_maint_ack_message(1, &old_irql); - } else { - str_msg = (int *) file->private_data; - pstr = (char *) &str_msg[2]; - pstr += str_msg[1]; /* head + offset */ - str_length = str_msg[0] - str_msg[1]; /* length - offset */ - } - str_length = MIN(str_length, count); - - if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) { - diva_os_free_tbuffer(0, str_msg); - file->private_data = NULL; - return (-EFAULT); - } - str_msg[1] += str_length; - if ((str_msg[0] - str_msg[1]) <= 0) { - diva_os_free_tbuffer(0, str_msg); - file->private_data = NULL; - } - - return (str_length); -} - -static ssize_t -maint_write(struct file *file, const char __user *buf, size_t count, loff_t * off) -{ - return (-ENODEV); -} - static unsigned int maint_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; @@ -293,13 +130,10 @@ static unsigned int maint_poll(struct file *file, poll_table * wait) static int maint_open(struct inode *ino, struct file *filep) { - down(&opened_sem); - if (opened) { - up(&opened_sem); + /* only one open is allowed, so we test + it atomically */ + if (test_and_set_bit(0, &opened)) return (-EBUSY); - } - opened++; - up(&opened_sem); filep->private_data = NULL; @@ -309,54 +143,16 @@ static int maint_open(struct inode *ino, struct file *filep) static int maint_close(struct inode *ino, struct file *filep) { if (filep->private_data) { - diva_os_free_tbuffer(0, filep->private_data); + diva_os_free(0, filep->private_data); filep->private_data = NULL; } - down(&opened_sem); - opened--; - up(&opened_sem); + /* clear 'used' flag */ + clear_bit(0, &opened); + return (0); } -/* - * fops - */ -static struct file_operations maint_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = maint_read, - .write = maint_write, - .poll = maint_poll, - .open = maint_open, - .release = maint_close -}; - -static int DIVA_INIT_FUNCTION create_maint_proc(void) -{ - maint_proc_entry = - create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR, - proc_net_eicon); - if (!maint_proc_entry) - return (0); - - maint_proc_entry->proc_fops = &maint_fops; - maint_proc_entry->owner = THIS_MODULE; - - return (1); -} - -static void remove_maint_proc(void) -{ - if (maint_proc_entry) { - remove_proc_entry("maint", proc_net_eicon); - maint_proc_entry = NULL; - } -} - -/* - * device node operations - */ static ssize_t divas_maint_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { @@ -427,18 +223,10 @@ static int DIVA_INIT_FUNCTION maint_init(void) ret = -EIO; goto out; } - if (!create_maint_proc()) { - printk(KERN_ERR "%s: failed to create proc entry.\n", - DRIVERLNAME); - divas_maint_unregister_chrdev(); - ret = -EIO; - goto out; - } if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) { printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME); - remove_maint_proc(); divas_maint_unregister_chrdev(); ret = -EIO; goto out; @@ -457,7 +245,6 @@ static int DIVA_INIT_FUNCTION maint_init(void) */ static void DIVA_EXIT_FUNCTION maint_exit(void) { - remove_maint_proc(); divas_maint_unregister_chrdev(); mntfunc_finit(); @@ -466,3 +253,4 @@ static void DIVA_EXIT_FUNCTION maint_exit(void) module_init(maint_init); module_exit(maint_exit); + diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c index 4ee56d4bb..df61e510a 100644 --- a/drivers/isdn/hardware/eicon/divasfunc.c +++ b/drivers/isdn/hardware/eicon/divasfunc.c @@ -1,4 +1,4 @@ -/* $Id: divasfunc.c,v 1.23 2004/04/08 01:17:57 armin Exp $ +/* $Id: divasfunc.c,v 1.23.4.2 2004/08/28 20:03:53 armin Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * @@ -27,8 +27,6 @@ extern void DIVA_DIDD_Read(void *, int); extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; -#define MAX_DESCRIPTORS 32 - extern char *DRIVERRELEASE_DIVAS; static dword notify_handle; @@ -76,10 +74,10 @@ void diva_xdi_didd_register_adapter(int card) d.features = IoAdapters[card - 1]->Properties.Features; DBG_TRC(("DIDD register A(%d) channels=%d", card, d.channels)) - /* workaround for different Name in structure */ - strlcpy(IoAdapters[card - 1]->Name, - IoAdapters[card - 1]->Properties.Name, - sizeof(IoAdapters[card - 1]->Name)); + /* workaround for different Name in structure */ + strlcpy(IoAdapters[card - 1]->Name, + IoAdapters[card - 1]->Properties.Name, + sizeof(IoAdapters[card - 1]->Name)); req.didd_remove_adapter.e.Req = 0; req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER; req.didd_add_adapter.info.descriptor = (void *) &d; diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index 866ae64d2..e849864ed 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -435,16 +435,14 @@ diva_os_register_io_port(void *adapter, int on, unsigned long port, return (0); } -void *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, int id, unsigned long bar, unsigned long area_length) +void __iomem *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, int id, unsigned long bar, unsigned long area_length) { - void *ret; - - ret = (void *) ioremap(bar, area_length); - DBG_TRC(("remap(%08x)->%08x", bar, ret)); + void __iomem *ret = ioremap(bar, area_length); + DBG_TRC(("remap(%08x)->%p", bar, ret)); return (ret); } -void divasa_unmap_pci_bar(void *bar) +void divasa_unmap_pci_bar(void __iomem *bar) { if (bar) { iounmap(bar); @@ -454,32 +452,32 @@ void divasa_unmap_pci_bar(void *bar) /********************************************************* ** I/O port access *********************************************************/ -byte __inline__ inpp(void *addr) +byte __inline__ inpp(void __iomem *addr) { return (inb((unsigned long) addr)); } -word __inline__ inppw(void *addr) +word __inline__ inppw(void __iomem *addr) { return (inw((unsigned long) addr)); } -void __inline__ inppw_buffer(void *addr, void *P, int length) +void __inline__ inppw_buffer(void __iomem *addr, void *P, int length) { insw((unsigned long) addr, (word *) P, length >> 1); } -void __inline__ outppw_buffer(void *addr, void *P, int length) +void __inline__ outppw_buffer(void __iomem *addr, void *P, int length) { outsw((unsigned long) addr, (word *) P, length >> 1); } -void __inline__ outppw(void *addr, word w) +void __inline__ outppw(void __iomem *addr, word w) { outw(w, (unsigned long) addr); } -void __inline__ outpp(void *addr, word p) +void __inline__ outpp(void __iomem *addr, word p) { outb(p, (unsigned long) addr); } diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h index 81c444828..0a5be7f96 100644 --- a/drivers/isdn/hardware/eicon/divasync.h +++ b/drivers/isdn/hardware/eicon/divasync.h @@ -31,33 +31,31 @@ #define IDI_SYNC_REQ_SET_POSTCALL 0x03 #define IDI_SYNC_REQ_GET_XLOG 0x04 #define IDI_SYNC_REQ_GET_FEATURES 0x05 -/* Added for DIVA USB support */ #define IDI_SYNC_REQ_USB_REGISTER 0x06 #define IDI_SYNC_REQ_USB_RELEASE 0x07 #define IDI_SYNC_REQ_USB_ADD_DEVICE 0x08 #define IDI_SYNC_REQ_USB_START_DEVICE 0x09 #define IDI_SYNC_REQ_USB_STOP_DEVICE 0x0A #define IDI_SYNC_REQ_USB_REMOVE_DEVICE 0x0B -/* Added for Diva Server Monitor */ #define IDI_SYNC_REQ_GET_CARDTYPE 0x0C #define IDI_SYNC_REQ_GET_DBG_XLOG 0x0D -#define IDI_SYNC_REQ_GET_LINE_IDX 0x0E #define DIVA_USB #define DIVA_USB_REQ 0xAC #define DIVA_USB_TEST 0xAB #define DIVA_USB_ADD_ADAPTER 0xAC #define DIVA_USB_REMOVE_ADAPTER 0xAD -/******************************************************************************/ #define IDI_SYNC_REQ_SERIAL_HOOK 0x80 #define IDI_SYNC_REQ_XCHANGE_STATUS 0x81 #define IDI_SYNC_REQ_USB_HOOK 0x82 #define IDI_SYNC_REQ_PORTDRV_HOOK 0x83 -#define IDI_SYNC_REQ_SLI (0x84) /* SLI request from 3signal modem drivers */ +#define IDI_SYNC_REQ_SLI 0x84 /* SLI request from 3signal modem drivers */ #define IDI_SYNC_REQ_RECONFIGURE 0x85 #define IDI_SYNC_REQ_RESET 0x86 +#define IDI_SYNC_REQ_GET_85X_DEVICE_DATA 0x87 #define IDI_SYNC_REQ_LOCK_85X 0x88 +#define IDI_SYNC_REQ_DIVA_85X_USB_DATA_EXCHANGE 0x99 +#define IDI_SYNC_REQ_DIPORT_EXCHANGE_REQ 0x98 #define IDI_SYNC_REQ_GET_85X_EXT_PORT_TYPE 0xA0 -#define IDI_SYNC_REQ_DIPORT_GET_85X_TX_CTRL_FN 0x98 /******************************************************************************/ #define IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES 0x92 /* @@ -87,6 +85,8 @@ typedef struct _diva_xdi_get_extended_xdi_features { #define DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS 0x08 #define DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC 0x10 #define DIVA_XDI_EXTENDED_FEATURE_RX_DMA 0x20 +#define DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA 0x40 +#define DIVA_XDI_EXTENDED_FEATURE_WIDE_ID 0x80 #define DIVA_XDI_EXTENDED_FEATURES_MAX_SZ 1 /******************************************************************************/ #define IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR 0x93 @@ -115,6 +115,7 @@ typedef struct _diva_xdi_get_capi_parameters { typedef struct _diva_xdi_get_logical_adapter_number { dword logical_adapter_number; dword controller; + dword total_controllers; } diva_xdi_get_logical_adapter_number_s_t; /******************************************************************************/ #define IDI_SYNC_REQ_UP1DM_OPERATION 0x96 @@ -134,6 +135,7 @@ typedef struct _diva_xdi_dma_descriptor_operation { #define IDI_SYNC_REQ_DIDD_ADD_ADAPTER 0x03 #define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER 0x04 #define IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY 0x05 +#define IDI_SYNC_REQ_DIDD_GET_CFG_LIB_IFC 0x10 typedef struct _diva_didd_adapter_notify { dword handle; /* Notification handle */ void * callback; @@ -149,6 +151,9 @@ typedef struct _diva_didd_read_adapter_array { void * buffer; dword length; } diva_didd_read_adapter_array_t; +typedef struct _diva_didd_get_cfg_lib_ifc { + void* ifc; +} diva_didd_get_cfg_lib_ifc_t; /******************************************************************************/ #define IDI_SYNC_REQ_XDI_GET_STREAM 0x91 #define DIVA_XDI_SYNCHRONOUS_SERVICE 0x01 @@ -466,6 +471,10 @@ typedef union ENTITY e; diva_didd_read_adapter_array_t info; } didd_read_adapter_array; + struct { + ENTITY e; + diva_didd_get_cfg_lib_ifc_t info; + } didd_get_cfg_lib_ifc; struct { unsigned char Req; unsigned char Rc; diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c index 63746f401..4cbc68cf4 100644 --- a/drivers/isdn/hardware/eicon/idifunc.c +++ b/drivers/isdn/hardware/eicon/idifunc.c @@ -1,4 +1,4 @@ -/* $Id: idifunc.c,v 1.14.4.2 2004/05/09 16:42:20 armin Exp $ +/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $ * * Driver for Eicon DIVA Server ISDN cards. * User Mode IDI Interface @@ -25,8 +25,6 @@ extern void DIVA_DIDD_Read(void *, int); extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int); extern void diva_user_mode_idi_remove_adapter(int); -#define MAX_DESCRIPTORS 32 - static dword notify_handle; static DESCRIPTOR DAdapter; static DESCRIPTOR MAdapter; diff --git a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c index 6f94ee932..8bdf97148 100644 --- a/drivers/isdn/hardware/eicon/io.c +++ b/drivers/isdn/hardware/eicon/io.c @@ -77,6 +77,7 @@ static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ+1] = { #if defined(DIVA_IDI_RX_DMA) DIVA_XDI_EXTENDED_FEATURE_CMA | DIVA_XDI_EXTENDED_FEATURE_RX_DMA | + DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA | #endif DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC), 0 @@ -94,13 +95,13 @@ dump_xlog_buffer (PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc) DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0])) for ( ; logCnt > 0 ; --logCnt ) { - if ( !READ_WORD(&Xlog[logOut]) ) + if ( !GET_WORD(&Xlog[logOut]) ) { if ( --logCnt == 0 ) break ; logOut = 0 ; } - if ( READ_WORD(&Xlog[logOut]) <= (logOut * sizeof(*Xlog)) ) + if ( GET_WORD(&Xlog[logOut]) <= (logOut * sizeof(*Xlog)) ) { if ( logCnt > 2 ) { @@ -109,9 +110,9 @@ dump_xlog_buffer (PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc) } break ; } - logLen = (dword)(READ_WORD(&Xlog[logOut]) - (logOut * sizeof(*Xlog))) ; + logLen = (dword)(GET_WORD(&Xlog[logOut]) - (logOut * sizeof(*Xlog))) ; DBG_FTL_MXLOG(( (char *)&Xlog[logOut + 1], (dword)(logLen - 2) )) - logOut = (READ_WORD(&Xlog[logOut]) + 1) / sizeof(*Xlog) ; + logOut = (GET_WORD(&Xlog[logOut]) + 1) / sizeof(*Xlog) ; } DBG_FTL(("%s: ***************** end of XLOG *****************", &IoAdapter->Name[0])) @@ -153,10 +154,10 @@ char *(ExceptionCauseTable[]) = "VCED" } ; void -dump_trap_frame (PISDN_ADAPTER IoAdapter, byte *exceptionFrame) +dump_trap_frame (PISDN_ADAPTER IoAdapter, byte __iomem *exceptionFrame) { - MP_XCPTC *xcept = (MP_XCPTC *)exceptionFrame ; - dword *regs; + MP_XCPTC __iomem *xcept = (MP_XCPTC __iomem *)exceptionFrame ; + dword __iomem *regs; regs = &xcept->regs[0] ; DBG_FTL(("%s: ***************** CPU TRAPPED *****************", &IoAdapter->Name[0])) @@ -226,8 +227,10 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) if (pI->descriptor_number >= 0) { dword dma_magic; void* local_addr; +#if 0 DBG_TRC(("A(%d) dma_alloc(%d)", IoAdapter->ANum, pI->descriptor_number)) +#endif diva_get_dma_map_entry (\ (struct _diva_dma_map_entry*)IoAdapter->dma_map, pI->descriptor_number, @@ -240,7 +243,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) } } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) && (pI->descriptor_number >= 0)) { +#if 0 DBG_TRC(("A(%d) dma_free(%d)", IoAdapter->ANum, pI->descriptor_number)) +#endif diva_free_dma_map_entry((struct _diva_dma_map_entry*)IoAdapter->dma_map, pI->descriptor_number); pI->descriptor_number = -1; @@ -257,6 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) &syncReq->xdi_logical_adapter_number.info; pI->logical_adapter_number = IoAdapter->ANum; pI->controller = IoAdapter->ControllerNumber; + pI->total_controllers = IoAdapter->Properties.Adapters; } return; case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: { diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info; @@ -318,6 +324,16 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) } syncReq->GetSerial.serial = 0 ; break ; + case IDI_SYNC_REQ_GET_CARDTYPE: + if ( IoAdapter ) + { + syncReq->GetCardType.cardtype = IoAdapter->cardType ; + DBG_TRC(("xdi: Adapter %d / CardType %ld", + IoAdapter->ANum, IoAdapter->cardType)) + return ; + } + syncReq->GetCardType.cardtype = 0 ; + break ; case IDI_SYNC_REQ_GET_XLOG: if ( IoAdapter ) { @@ -326,6 +342,14 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) } e->Ind = 0 ; break ; + case IDI_SYNC_REQ_GET_DBG_XLOG: + if ( IoAdapter ) + { + pcm_req (IoAdapter, e) ; + return ; + } + e->Ind = 0 ; + break ; case IDI_SYNC_REQ_GET_FEATURES: if ( IoAdapter ) { @@ -345,7 +369,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) } if ( IoAdapter ) { +#if 0 DBG_FTL(("xdi: unknown Req 0 / Rc %d !", e->Rc)) +#endif return ; } } @@ -496,7 +522,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e) diva_os_enter_spin_lock (&IoAdapter->data_spin_lock, &OldIrql, "data_pcm_1"); - IoAdapter->pcm_data = (unsigned long)pcm; + IoAdapter->pcm_data = (void *)pcm; IoAdapter->pcm_pending = 1; diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr); diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, @@ -510,7 +536,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e) &OldIrql, "data_pcm_3"); IoAdapter->pcm_pending = 0; - IoAdapter->pcm_data = 0; + IoAdapter->pcm_data = NULL ; diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &OldIrql, "data_pcm_3"); @@ -528,7 +554,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e) &OldIrql, "data_pcm_4"); IoAdapter->pcm_pending = 0; - IoAdapter->pcm_data = 0; + IoAdapter->pcm_data = NULL ; diva_os_leave_spin_lock (&IoAdapter->data_spin_lock, &OldIrql, "data_pcm_4"); @@ -569,26 +595,22 @@ Trapped: byte mem_in (ADAPTER *a, void *addr) { byte val; - volatile byte* Base; - - Base = (volatile byte *)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); - val = *(Base + (unsigned long)addr); + volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + val = READ_BYTE(Base + (unsigned long)addr); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); return (val); } word mem_inw (ADAPTER *a, void *addr) { word val; - volatile byte* Base; - - Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); val = READ_WORD((Base + (unsigned long)addr)); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); return (val); } void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); while (dwords--) { *data++ = READ_DWORD((Base + (unsigned long)addr)); addr+=4; @@ -597,8 +619,8 @@ void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords) } void mem_in_buffer (ADAPTER *a, void *addr, void *buffer, word length) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); - memcpy (buffer, (void *)(Base + (unsigned long)addr), length); + volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + memcpy_fromio(buffer, (Base + (unsigned long)addr), length); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_look_ahead (ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) @@ -611,19 +633,19 @@ void mem_look_ahead (ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) } void mem_out (ADAPTER *a, void *addr, byte data) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); - *(Base + (unsigned long)addr) = data ; + volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + WRITE_BYTE(Base + (unsigned long)addr, data); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_outw (ADAPTER *a, void *addr, word data) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); WRITE_WORD((Base + (unsigned long)addr), data); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); while (dwords--) { WRITE_DWORD((Base + (unsigned long)addr), *data); addr+=4; @@ -633,15 +655,15 @@ void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords) } void mem_out_buffer (ADAPTER *a, void *addr, void *buffer, word length) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); - memcpy ((void *)(Base + (unsigned long)addr), buffer, length) ; + volatile byte __iomem * Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + memcpy_toio((Base + (unsigned long)addr), buffer, length) ; DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_inc (ADAPTER *a, void *addr) { - volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); - byte x = *(Base + (unsigned long)addr); - *(Base + (unsigned long)addr) = x + 1 ; + volatile byte __iomem *Base = DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + byte x = READ_BYTE(Base + (unsigned long)addr); + WRITE_BYTE(Base + (unsigned long)addr, x + 1); DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } /*------------------------------------------------------------------*/ @@ -650,7 +672,7 @@ void mem_inc (ADAPTER *a, void *addr) byte io_in(ADAPTER * a, void * adr) { byte val; - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port + 4, (word)(unsigned long)adr); val = inpp(Port); DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); @@ -659,7 +681,7 @@ byte io_in(ADAPTER * a, void * adr) word io_inw(ADAPTER * a, void * adr) { word val; - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port + 4, (word)(unsigned long)adr); val = inppw(Port); DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); @@ -667,8 +689,8 @@ word io_inw(ADAPTER * a, void * adr) } void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len) { - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); - byte* P = (byte*)buffer; + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte* P = (byte*)buffer; if ((long)adr & 1) { outppw(Port+4, (word)(unsigned long)adr); *P = inpp(Port); @@ -678,7 +700,7 @@ void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len) if (!len) { DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); return; - } + } } outppw(Port+4, (word)(unsigned long)adr); inppw_buffer (Port, P, len+1); @@ -686,7 +708,7 @@ void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len) } void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e) { - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port+4, (word)(unsigned long)RBuffer); ((PISDN_ADAPTER)a->io)->RBuffer.length = inppw(Port); inppw_buffer (Port, ((PISDN_ADAPTER)a->io)->RBuffer.P, ((PISDN_ADAPTER)a->io)->RBuffer.length + 1); @@ -695,22 +717,22 @@ void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e) } void io_out(ADAPTER * a, void * adr, byte data) { - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port+4, (word)(unsigned long)adr); outpp(Port, data); DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_outw(ADAPTER * a, void * adr, word data) { - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port+4, (word)(unsigned long)adr); outppw(Port, data); DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len) { - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); - byte* P = (byte*)buffer; + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte* P = (byte*)buffer; if ((long)adr & 1) { outppw(Port+4, (word)(unsigned long)adr); outpp(Port, *P); @@ -729,7 +751,7 @@ void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len) void io_inc(ADAPTER * a, void * adr) { byte x; - byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + byte __iomem *Port = DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); outppw(Port+4, (word)(unsigned long)adr); x = inpp(Port); outppw(Port+4, (word)(unsigned long)adr); @@ -839,21 +861,21 @@ void CALLBACK(ADAPTER * a, ENTITY * e) /* -------------------------------------------------------------------------- routines for aligned reading and writing on RISC -------------------------------------------------------------------------- */ -void outp_words_from_buffer (word* adr, byte* P, word len) +void outp_words_from_buffer (word __iomem * adr, byte* P, dword len) { - word i = 0; + dword i = 0; word w; - while (i < (len & 0xfffe)) { + while (i < (len & 0xfffffffe)) { w = P[i++]; w += (P[i++])<<8; outppw (adr, w); } } -void inp_words_to_buffer (word* adr, byte* P, word len) +void inp_words_to_buffer (word __iomem * adr, byte* P, dword len) { - word i = 0; + dword i = 0; word w; - while (i < (len & 0xfffe)) { + while (i < (len & 0xfffffffe)) { w = inppw (adr); P[i++] = (byte)(w); P[i++] = (byte)(w>>8); diff --git a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h index 3e5403983..a6f2e8aad 100644 --- a/drivers/isdn/hardware/eicon/io.h +++ b/drivers/isdn/hardware/eicon/io.h @@ -39,6 +39,14 @@ typedef struct { DEVICE_NAME DeviceName[4] ; PISDN_ADAPTER QuadroAdapter[4] ; } ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ; +/* -------------------------------------------------------------------------- + Special OS memory support structures + -------------------------------------------------------------------------- */ +#define MAX_MAPPED_ENTRIES 8 +typedef struct { + void * Address; + dword Length; +} ADAPTER_MEMORY ; /* -------------------------------------------------------------------------- Configuration of XDI clients carried by XDI -------------------------------------------------------------------------- */ @@ -52,6 +60,7 @@ typedef struct _diva_xdi_capi_cfg { -------------------------------------------------------------------------- */ struct _ISDN_ADAPTER { void (* DIRequest)(PISDN_ADAPTER, ENTITY *) ; + int State ; /* from NT4 1.srv, a good idea, but a poor achievment */ int Initialized ; int RegisteredWithDidd ; int Unavailable ; /* callback function possible? */ @@ -63,6 +72,7 @@ struct _ISDN_ADAPTER { /* remember mapped memory areas */ + ADAPTER_MEMORY MappedMemory[MAX_MAPPED_ENTRIES] ; CARD_PROPERTIES Properties ; dword cardType ; dword protocol_id ; /* configured protocol identifier */ @@ -87,15 +97,15 @@ struct _ISDN_ADAPTER { dword downloadAddrTable[4] ; /* add. for MultiMaster */ dword MemoryBase ; dword MemorySize ; - byte *Address ; - byte *Config ; - byte *Control ; - byte *reset ; - byte *port ; - byte *ram ; - byte *cfg ; - byte *prom ; - byte *ctlReg ; + byte __iomem *Address ; + byte __iomem *Config ; + byte __iomem *Control ; + byte __iomem *reset ; + byte __iomem *port ; + byte __iomem *ram ; + byte __iomem *cfg ; + byte __iomem *prom ; + byte __iomem *ctlReg ; struct pc_maint *pcm ; diva_os_dependent_devica_name_t os_name; byte Name[32] ; @@ -105,6 +115,7 @@ struct _ISDN_ADAPTER { char *ProtocolSuffix ; /* internal protocolfile table */ char Archive[32] ; char Protocol[32] ; + char AddDownload[32] ; /* Dsp- or other additional download files */ char Oad1[ISDN_MAX_NUM_LEN] ; char Osa1[ISDN_MAX_NUM_LEN] ; char Oad2[ISDN_MAX_NUM_LEN] ; @@ -153,8 +164,26 @@ struct _ISDN_ADAPTER { byte ModemCarrierWaitTimeSec; byte ModemCarrierLossWaitTimeTenthSec; byte PiafsLinkTurnaroundInFrames; + byte DiscAfterProgress; + byte AniDniLimiter[3]; + byte TxAttenuation; /* PRI/E1 only: attenuate TX signal */ word QsigFeatures; dword GenerateRingtone ; + dword SupplementaryServicesFeatures; + dword R2Dialect; + dword R2CasOptions; + dword FaxV34Options; + dword DisabledDspMask; + dword AdapterTestMask; + dword DspImageLength; + word AlertToIn20mSecTicks; + word ModemEyeSetup; + byte R2CtryLength; + byte CCBSRelTimer; + byte *PcCfgBufferFile;/* flexible parameter via file */ + byte *PcCfgBuffer ; /* flexible parameter via multistring */ + diva_os_dump_file_t dump_file; /* dump memory to file at lowest irq level */ + diva_os_board_trace_t board_trace ; /* traces from the board */ diva_os_spin_lock_t isr_spin_lock; diva_os_spin_lock_t data_spin_lock; diva_os_soft_isr_t req_soft_isr; @@ -180,15 +209,21 @@ struct _ISDN_ADAPTER { void (* stop)(PISDN_ADAPTER) ; void (* rstFnc)(PISDN_ADAPTER) ; void (* trapFnc)(PISDN_ADAPTER) ; + dword (* DetectDsps)(PISDN_ADAPTER) ; void (* os_trap_nfy_Fnc)(PISDN_ADAPTER, dword) ; diva_os_isr_callback_t diva_isr_handler; - dword sdram_bar; + dword sdram_bar; /* must be 32 bit */ dword fpga_features; volatile int pcm_pending; - volatile unsigned long pcm_data; + volatile void * pcm_data; diva_xdi_capi_cfg_t capi_cfg; dword tasks; - void* dma_map; + void *dma_map; + int (*DivaAdapterTestProc)(PISDN_ADAPTER); + void *AdapterTestMemoryStart; + dword AdapterTestMemoryLength; + const byte* cfg_lib_memory_init; + dword cfg_lib_memory_init_length; }; /* --------------------------------------------------------------------- Entity table @@ -219,8 +254,8 @@ struct s_load { /* --------------------------------------------------------------------- Functions for port io --------------------------------------------------------------------- */ -void outp_words_from_buffer (word* adr, byte* P, word len); -void inp_words_to_buffer (word* adr, byte* P, word len); +void outp_words_from_buffer (word __iomem * adr, byte* P, dword len); +void inp_words_to_buffer (word __iomem * adr, byte* P, dword len); /* --------------------------------------------------------------------- platform specific conversions --------------------------------------------------------------------- */ @@ -240,6 +275,10 @@ void io_out(ADAPTER * a, void * adr, byte data); void io_outw(ADAPTER * a, void * adr, word data); void io_out_buffer(ADAPTER * a, void * adr, void * P, word length); void io_inc(ADAPTER * a, void * adr); +void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos, + void *Buf, dword Len); +int bri_out_buffer (PISDN_ADAPTER IoAdapter, dword Pos, + void *Buf, dword Len, int Verify); /* --------------------------------------------------------------------- ram access functions for memory mapped cards --------------------------------------------------------------------- */ @@ -268,7 +307,7 @@ typedef struct { word cnt ; word out ; } Xdesc ; -extern void dump_trap_frame (PISDN_ADAPTER IoAdapter, byte *exception) ; +extern void dump_trap_frame (PISDN_ADAPTER IoAdapter, byte __iomem *exception) ; extern void dump_xlog_buffer (PISDN_ADAPTER IoAdapter, Xdesc *xlogDesc) ; /* --------------------------------------------------------------------- */ #endif /* } __DIVA_XDI_COMMON_IO_H_INC__ */ diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c index 8bef29b8b..23960cb6e 100644 --- a/drivers/isdn/hardware/eicon/maintidi.c +++ b/drivers/isdn/hardware/eicon/maintidi.c @@ -115,7 +115,7 @@ diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter, return NULL; } - pmem += sizeof(*pLib); + pmem += sizeof(*pLib); memset(pLib, 0x00, sizeof(*pLib)); pLib->Adapter = Adapter; @@ -337,13 +337,60 @@ static int SuperTraceMessageInput (void* hLib) { pLib->e.RNum = 1; pLib->e.R->P = (byte*)&pLib->buffer[0]; pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1); + } else { /* Indication reception complete, process it now */ byte* p = (byte*)&pLib->buffer[0]; pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */ + switch (Ind) { + case MAN_COMBI_IND: { + int total_length = pLib->e.R->PLength; + word this_ind_length; + + while (total_length > 3 && *p) { + Ind = *p++; + this_ind_length = (word)p[0] | ((word)p[1] << 8); + p += 2; + + switch (Ind) { + case MAN_INFO_IND: + if (process_idi_info (pLib, (diva_man_var_header_t*)p)) { + return (-1); + } + break; + case MAN_EVENT_IND: + if (process_idi_event (pLib, (diva_man_var_header_t*)p)) { + return (-1); + } + break; + case MAN_TRACE_IND: + if (pLib->trace_on == 1) { + /* + Ignore first trace event that is result of + EVENT_ON operation + */ + pLib->trace_on++; + } else { + /* + Delivery XLOG buffer to application + */ + if (pLib->user_proc_table.trace_proc) { + (*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context, + &pLib->instance, pLib->Adapter, + p, this_ind_length); + } + } + break; + default: + diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind); + } + p += (this_ind_length+1); + total_length -= (4 + this_ind_length); + } + } break; case MAN_INFO_IND: if (process_idi_info (pLib, (diva_man_var_header_t*)p)) { return (-1); @@ -806,7 +853,7 @@ static int ScheduleNextTraceRequest (diva_strace_context_t* pLib) { } static int process_idi_event (diva_strace_context_t* pLib, - diva_man_var_header_t* pVar) { + diva_man_var_header_t* pVar) { const char* path = (char*)&pVar->path_length+1; char name[64]; int i; @@ -1872,11 +1919,11 @@ static int diva_strace_read_int (diva_man_var_header_t* pVar, int* var) { break; case 2: - value = (short)READ_WORD(ptr); + value = (short)GET_WORD(ptr); break; case 4: - value = (int)READ_DWORD(ptr); + value = (int)GET_DWORD(ptr); break; default: @@ -1900,16 +1947,16 @@ static int diva_strace_read_uint (diva_man_var_header_t* pVar, dword* var) { break; case 2: - value = (word)READ_WORD(ptr); + value = (word)GET_WORD(ptr); break; case 3: - value = (dword)READ_DWORD(ptr); + value = (dword)GET_DWORD(ptr); value &= 0x00ffffff; break; case 4: - value = (dword)READ_DWORD(ptr); + value = (dword)GET_DWORD(ptr); break; default: diff --git a/drivers/isdn/hardware/eicon/maintidi.h b/drivers/isdn/hardware/eicon/maintidi.h index 184142cdf..4f0629496 100644 --- a/drivers/isdn/hardware/eicon/maintidi.h +++ b/drivers/isdn/hardware/eicon/maintidi.h @@ -49,6 +49,8 @@ typedef struct _diva_strace_path2action { void* variable; /* Variable that will receive value */ } diva_strace_path2action_t; +#define DIVA_MAX_MANAGEMENT_TRANSFER_SIZE 4096 + typedef struct _diva_strace_context { diva_strace_library_interface_t instance; @@ -62,7 +64,7 @@ typedef struct _diva_strace_context { IDI_CALL request; BUFFERS XData; BUFFERS RData; - byte buffer[2048+512+1]; + byte buffer[DIVA_MAX_MANAGEMENT_TRANSFER_SIZE + 1]; int removal_state; int general_b_ch_event; int general_fax_event; diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index 5ce359aac..9d32d3bb7 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -419,7 +419,7 @@ word api_put(APPL * appl, CAPI_MSG * msg) { dbug(1,dprintf("plci=%x",msg->header.plci)); plci = &a->plci[msg->header.plci-1]; - ncci = READ_WORD(&msg->header.ncci); + ncci = GET_WORD(&msg->header.ncci); if (plci->Id && (plci->appl || (plci->State == INC_CON_PENDING) @@ -574,7 +574,7 @@ word api_put(APPL * appl, CAPI_MSG * msg) } - c = ftable[i].function(READ_DWORD(&msg->header.controller), + c = ftable[i].function(GET_DWORD(&msg->header.controller), msg->header.number, a, plci, @@ -1264,7 +1264,7 @@ byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, ch = 0; if(ai_parms[0].length) { - ch = READ_WORD(ai_parms[0].info+1); + ch = GET_WORD(ai_parms[0].info+1); if(ch>4) ch=0; /* safety -> ignore ChannelID */ if(ch==4) /* explizit CHI in message */ { @@ -1289,7 +1289,7 @@ byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36) { - dir = READ_WORD(ai_parms[0].info+3); + dir = GET_WORD(ai_parms[0].info+3); ch_mask = 0; m = 0x3f; for(i=0; i+5<=ai_parms[0].length; i++) @@ -1348,15 +1348,15 @@ byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, add_s(plci,BC,&parms[6]); add_s(plci,LLC,&parms[7]); add_s(plci,HLC,&parms[8]); - CIP = READ_WORD(parms[0].info); + CIP = GET_WORD(parms[0].info); if (a->Info_Mask[appl->Id-1] & 0x200) { /* early B3 connect (CIP mask bit 9) no release after a disc */ add_p(plci,LLI,"\x01\x01"); } - if(READ_WORD(parms[0].info)<29) { - add_p(plci,BC,cip_bc[READ_WORD(parms[0].info)][a->u_law]); - add_p(plci,HLC,cip_hlc[READ_WORD(parms[0].info)]); + if(GET_WORD(parms[0].info)<29) { + add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]); + add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]); } add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30"); sig_req(plci,ASSIGN,DSIG_ID); @@ -1442,11 +1442,11 @@ byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, { if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms)) { - dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,READ_WORD(ai_parms[0].info+1))); + dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1))); ch = 0; if(ai_parms[0].length) { - ch = READ_WORD(ai_parms[0].info+1); + ch = GET_WORD(ai_parms[0].info+1); dbug(1,dprintf("BCH-I=0x%x",ch)); } } @@ -1470,7 +1470,7 @@ byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) { clear_c_ind_mask_bit (plci, (word)(appl->Id-1)); dump_c_ind_mask (plci); - Reject = READ_WORD(parms[0].info); + Reject = GET_WORD(parms[0].info); dbug(1,dprintf("Reject=0x%x",Reject)); if(Reject) { @@ -1672,15 +1672,15 @@ byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, A Info = _WRONG_IDENTIFIER; if(a) { Info = 0; - a->Info_Mask[appl->Id-1] = READ_DWORD(parms[0].info); - a->CIP_Mask[appl->Id-1] = READ_DWORD(parms[1].info); - dbug(1,dprintf("CIP_MASK=0x%lx",READ_DWORD(parms[1].info))); + a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info); + a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info); + dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info))); if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */ a->Info_Mask[appl->Id-1] |= 0x10; /* call progression infos */ } /* check if external controller listen and switch listen on or off*/ - if(Id&EXT_CONTROLLER && READ_DWORD(parms[1].info)){ + if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){ if(a->profile.Global_Options & ON_BOARD_CODEC) { dummy_plci.State = IDLE; a->codec_listen[appl->Id-1] = &dummy_plci; @@ -1886,7 +1886,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, Info = _WRONG_IDENTIFIER; } - selector = READ_WORD(msg[0].info); + selector = GET_WORD(msg[0].info); if(!Info) { @@ -1902,8 +1902,8 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, Info = _WRONG_MESSAGE_FORMAT; break; } - SSreq = READ_WORD(&(msg[1].info[1])); - WRITE_WORD(&RCparms[1],SSreq); + SSreq = GET_WORD(&(msg[1].info[1])); + PUT_WORD(&RCparms[1],SSreq); SSparms = RCparms; switch(SSreq) { @@ -1919,7 +1919,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, } else { - WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); + PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); SSparms = (byte *)SSstruct; break; } @@ -1946,7 +1946,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, Info = _WRONG_MESSAGE_FORMAT; break; } - a->Notification_Mask[appl->Id-1] = READ_DWORD(ss_parms[2].info); + a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info); if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */ { if((i=get_plci(a))) @@ -2096,7 +2096,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, } if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD))) { - d = READ_DWORD(ss_parms[2].info); + d = GET_DWORD(ss_parms[2].info); if(d>=0x80) { dbug(1,dprintf("format wrong")); @@ -2171,7 +2171,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, Info = _WRONG_IDENTIFIER; break; } - relatedPLCIvalue = READ_DWORD(ss_parms[2].info); + relatedPLCIvalue = GET_DWORD(ss_parms[2].info); relatedPLCIvalue &= 0x0000FFFF; dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue)); /* controller starts with 0 up to (max_adapter - 1) */ @@ -2294,7 +2294,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, break; } /* reuse unused screening indicator */ - ss_parms[3].info[3] = (byte)READ_WORD(&(ss_parms[2].info[0])); + ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0])); plci->command = 0; plci->internal_command = CD_REQ_PEND; appl->CDEnable = TRUE; @@ -2334,10 +2334,10 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, rplci->internal_command = CF_START_PEND; rplci->appl = appl; rplci->number = Number; - appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0])); + appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); cai[0] = 2; - cai[1] = 0x70|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */ - cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */ + cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ + cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ add_p(rplci,CAI,cai); add_p(rplci,OAD,ss_parms[5].info); add_p(rplci,CPN,ss_parms[6].info); @@ -2393,7 +2393,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, switch(SSreq) { case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */ - cai[1] = 0x60|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */ + cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */ break; case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */ @@ -2402,7 +2402,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, break; case S_CALL_FORWARDING_STOP: rplci->internal_command = CF_STOP_PEND; - cai[1] = 0x80|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */ + cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */ break; case S_CCBS_REQUEST: cai[1] = CCBS_REQUEST; @@ -2433,7 +2433,7 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, break; } - appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0])); + appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0])); switch(SSreq) { case S_INTERROGATE_NUMBERS: @@ -2443,18 +2443,18 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, case S_CCBS_REQUEST: case S_CCBS_DEACTIVATE: cai[0] = 3; - WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0]))); + PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); add_p(rplci,CAI,cai); break; case S_CCBS_INTERROGATE: cai[0] = 3; - WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0]))); + PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0]))); add_p(rplci,CAI,cai); add_p(rplci,OAD,ss_parms[4].info); break; default: cai[0] = 2; - cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */ + cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */ add_p(rplci,CAI,cai); add_p(rplci,OAD,ss_parms[5].info); break; @@ -2503,11 +2503,11 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, cai[0] = 13; cai[1] = ACTIVATION_MWI; /* Function */ - WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ - WRITE_DWORD(&cai[4],READ_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */ - WRITE_WORD(&cai[8],READ_WORD(&(ss_parms[4].info[0]))); /* Message Status */ - WRITE_WORD(&cai[10],READ_WORD(&(ss_parms[5].info[0]))); /* Message Reference */ - WRITE_WORD(&cai[12],READ_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */ + PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ + PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */ + PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */ + PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */ + PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */ add_p(rplci,CAI,cai); add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */ add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */ @@ -2555,8 +2555,8 @@ byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, cai[0] = 5; cai[1] = DEACTIVATION_MWI; /* Function */ - WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ - WRITE_WORD(&cai[4],READ_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */ + PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */ + PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */ add_p(rplci,CAI,cai); add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */ add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */ @@ -2684,8 +2684,8 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc { if (plci->NL.Id && !plci->nl_remove_id) { - fax_control_bits = READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low); - fax_feature_bits = READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low); + fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low); + fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low); if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS) || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)) { @@ -2693,7 +2693,7 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc fax_info_change = FALSE; if (ncpi->length >= 4) { - w = READ_WORD(&ncpi->info[3]); + w = GET_WORD(&ncpi->info[3]); if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001))) { ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution = @@ -2711,7 +2711,7 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc } if (ncpi->length >= 6) { - w = READ_WORD(&ncpi->info[5]); + w = GET_WORD(&ncpi->info[5]); if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format) { ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w; @@ -2719,12 +2719,12 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc } if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) - && (READ_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */ + && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */ { plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD); } if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) - && (READ_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */ + && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */ { plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD); } @@ -2775,7 +2775,7 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc else { if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) - plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]); + plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); for (i = 0; i < fax_parms[7].length; i++) plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; @@ -2790,9 +2790,9 @@ byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc fax_info_change = TRUE; } - if (fax_control_bits != READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low)) + if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low)) { - WRITE_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits); + PUT_WORD (&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits); fax_info_change = TRUE; } } @@ -2865,7 +2865,7 @@ byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc ncci = (word)(Id>>16); if(plci && ncci) { if(a->ncci_state[ncci]==INC_CON_PENDING) { - if (READ_WORD (&parms[0].info[0]) != 0) + if (GET_WORD (&parms[0].info[0]) != 0) { a->ncci_state[ncci] = OUTG_REJ_PENDING; channel_request_xon (plci, a->ncci_ch[ncci]); @@ -2907,7 +2907,7 @@ byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plc plci->fax_connect_info_buffer[len] = 0; len += 1 + plci->fax_connect_info_buffer[len]; if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) - plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]); + plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); for (i = 0; i < fax_parms[7].length; i++) plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; @@ -3129,9 +3129,9 @@ byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, } else data->P = TransmitBufferSet(appl,*(dword *)parms[0].info); - data->Length = READ_WORD(parms[1].info); - data->Handle = READ_WORD(parms[2].info); - data->Flags = READ_WORD(parms[3].info); + data->Length = GET_WORD(parms[1].info); + data->Handle = GET_WORD(parms[2].info); + data->Flags = GET_WORD(parms[3].info); (ncci_ptr->data_pending)++; /* check for delivery confirmation */ @@ -3165,7 +3165,7 @@ byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, _DATA_B3_R|CONFIRM, Id, Number, - "ww",READ_WORD(parms[2].info),Info); + "ww",GET_WORD(parms[2].info),Info); } return FALSE; } @@ -3180,7 +3180,7 @@ byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, ncci = (word)(Id>>16); if(plci && ncci) { - n = READ_WORD(parms[0].info); + n = GET_WORD(parms[0].info); dbug(1,dprintf("free(%d)",n)); NCCIcode = ncci | (((word) a->Id) << 8); if(nMaxBuffer && @@ -3443,10 +3443,10 @@ byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * p dbug(1,dprintf("manufacturer_req")); for(i=0;i<5;i++) m_parms[i].length = 0; - if(READ_DWORD(parms[0].info)!=_DI_MANU_ID) { + if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) { Info = _WRONG_MESSAGE_FORMAT; } - command = READ_WORD(parms[1].info); + command = GET_WORD(parms[1].info); m = &parms[2]; if (!Info) { @@ -3456,7 +3456,7 @@ byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * p Info = _WRONG_MESSAGE_FORMAT; break; } - codec = READ_WORD(m_parms[0].info); + codec = GET_WORD(m_parms[0].info); ch = m_parms[1].info[0]; dir = m_parms[2].info[0]; if((i=get_plci(a))) { @@ -3724,12 +3724,12 @@ byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * p Info = _WRONG_MESSAGE_FORMAT; break; } - if (READ_DWORD (m_parms[0].info) & ~a->man_profile.private_options) + if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options) { Info = _FACILITY_NOT_SUPPORTED; break; } - a->requested_options_table[appl->Id-1] = READ_DWORD (m_parms[0].info); + a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info); break; @@ -3764,11 +3764,11 @@ byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * p if ((msg[0].length == 0) || (msg[1].length == 0) - || (READ_DWORD(msg[0].info)!=_DI_MANU_ID)) + || (GET_DWORD(msg[0].info)!=_DI_MANU_ID)) { return FALSE; } - indication = READ_WORD(msg[1].info); + indication = GET_WORD(msg[1].info); switch (indication) { @@ -3806,7 +3806,7 @@ byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * p plci->fax_connect_info_buffer[len] = 0; len += 1 + plci->fax_connect_info_buffer[len]; if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2)) - plci->nsf_control_bits = READ_WORD(&fax_parms[7].info[2]); + plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]); plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length); for (i = 0; i < fax_parms[7].length; i++) plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i]; @@ -4290,7 +4290,7 @@ void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte { break; } - WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); + PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY); sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct); plci_remove(plci); break; @@ -4495,14 +4495,14 @@ void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte dbug(1,dprintf("MWI_REQ not supported")); } /* 0x3010: Request not allowed in this state */ - WRITE_WORD(&SSparms[4],0x300E); /* SS not supported */ + PUT_WORD(&SSparms[4],0x300E); /* SS not supported */ } if(plci->internal_command==MWI_ACTIVATE_REQ_PEND) { - WRITE_WORD(&SSparms[1],S_MWI_ACTIVATE); + PUT_WORD(&SSparms[1],S_MWI_ACTIVATE); } - else WRITE_WORD(&SSparms[1],S_MWI_DEACTIVATE); + else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE); if(plci->cr_enquiry) { @@ -4875,7 +4875,7 @@ void sig_ind(PLCI * plci) a = plci->adapter; Id = ((word)plci->Id<<8)|a->Id; - WRITE_WORD(&SS_Ind[4],0x0000); + PUT_WORD(&SS_Ind[4],0x0000); if (plci->sig_remove_id) { @@ -4987,21 +4987,21 @@ void sig_ind(PLCI * plci) if (esc_profile[0]) { dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx", - UnMapController (a->Id), READ_DWORD (&esc_profile[6]), - READ_DWORD (&esc_profile[10]), READ_DWORD (&esc_profile[14]), - READ_DWORD (&esc_profile[18]), READ_DWORD (&esc_profile[46]))); + UnMapController (a->Id), GET_DWORD (&esc_profile[6]), + GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]), + GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46]))); a->profile.Global_Options &= 0x000000ffL; a->profile.B1_Protocols &= 0x000003ffL; a->profile.B2_Protocols &= 0x00001fdfL; a->profile.B3_Protocols &= 0x000000b7L; - a->profile.Global_Options &= READ_DWORD (&esc_profile[6]) | + a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) | GL_BCHANNEL_OPERATION_SUPPORTED; - a->profile.B1_Protocols &= READ_DWORD (&esc_profile[10]); - a->profile.B2_Protocols &= READ_DWORD (&esc_profile[14]); - a->profile.B3_Protocols &= READ_DWORD (&esc_profile[18]); - a->manufacturer_features = READ_DWORD (&esc_profile[46]); + a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]); + a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]); + a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]); + a->manufacturer_features = GET_DWORD (&esc_profile[46]); a->man_profile.private_options = 0; if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER) @@ -5013,8 +5013,8 @@ void sig_ind(PLCI * plci) if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP) a->man_profile.private_options |= 1L << PRIVATE_RTP; - a->man_profile.rtp_primary_payloads = READ_DWORD (&esc_profile[50]); - a->man_profile.rtp_additional_payloads = READ_DWORD (&esc_profile[54]); + a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]); + a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]); if (a->manufacturer_features & MANUFACTURER_FEATURE_T38) @@ -5099,14 +5099,14 @@ void sig_ind(PLCI * plci) if(!plci->appl) break; if(pty_cai[0]==4) { - WRITE_DWORD(&CF_Ind[6],READ_DWORD(&pty_cai[1]) ); + PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) ); } else { - WRITE_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE); + PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE); } - WRITE_WORD (&CF_Ind[1], 0); - WRITE_WORD (&CF_Ind[4], 0); + PUT_WORD (&CF_Ind[1], 0); + PUT_WORD (&CF_Ind[4], 0); sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind); plci_remove(plci); break; @@ -5126,7 +5126,7 @@ void sig_ind(PLCI * plci) if(tplci->tel) rId|=EXT_CONTROLLER; if(pty_cai[5]==ECT_EXECUTE) { - WRITE_WORD(&SS_Ind[1],S_ECT); + PUT_WORD(&SS_Ind[1],S_ECT); plci->vswitchstate=0; plci->relatedPTYPLCI->vswitchstate=0; @@ -5134,15 +5134,15 @@ void sig_ind(PLCI * plci) } else { - WRITE_WORD(&SS_Ind[1],pty_cai[5]+3); + PUT_WORD(&SS_Ind[1],pty_cai[5]+3); } if(pty_cai[2]!=0xff) { - WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); + PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); } else { - WRITE_WORD(&SS_Ind[4],0x300E); + PUT_WORD(&SS_Ind[4],0x300E); } plci->relatedPTYPLCI = NULL; plci->ptyState = 0; @@ -5152,13 +5152,13 @@ void sig_ind(PLCI * plci) case CALL_DEFLECTION: if(pty_cai[2]!=0xff) { - WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); + PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); } else { - WRITE_WORD(&SS_Ind[4],0x300E); + PUT_WORD(&SS_Ind[4],0x300E); } - WRITE_WORD(&SS_Ind[1],pty_cai[5]); + PUT_WORD(&SS_Ind[1],pty_cai[5]); for(i=0; iappl) break; if(pty_cai[2]!=0xff) { - WRITE_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]); + PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]); } else { - WRITE_WORD(&Interr_Err_Ind[4],0x300E); + PUT_WORD(&Interr_Err_Ind[4],0x300E); } switch (pty_cai[5]) { @@ -5193,13 +5193,13 @@ void sig_ind(PLCI * plci) dbug(1,dprintf("Deact_Div")); Interr_Err_Ind[0]=0x9; Interr_Err_Ind[3]=0x6; - WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP); + PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP); break; case ACTIVATION_DIVERSION: dbug(1,dprintf("Act_Div")); Interr_Err_Ind[0]=0x9; Interr_Err_Ind[3]=0x6; - WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START); + PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START); break; case DIVERSION_INTERROGATE_CFU: case DIVERSION_INTERROGATE_CFB: @@ -5207,34 +5207,34 @@ void sig_ind(PLCI * plci) dbug(1,dprintf("Interr_Div")); Interr_Err_Ind[0]=0xa; Interr_Err_Ind[3]=0x7; - WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION); + PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION); break; case DIVERSION_INTERROGATE_NUM: dbug(1,dprintf("Interr_Num")); Interr_Err_Ind[0]=0xa; Interr_Err_Ind[3]=0x7; - WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS); + PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS); break; case CCBS_REQUEST: dbug(1,dprintf("CCBS Request")); Interr_Err_Ind[0]=0xd; Interr_Err_Ind[3]=0xa; - WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST); + PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST); break; case CCBS_DEACTIVATE: dbug(1,dprintf("CCBS Deactivate")); Interr_Err_Ind[0]=0x9; Interr_Err_Ind[3]=0x6; - WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE); + PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE); break; case CCBS_INTERROGATE: dbug(1,dprintf("CCBS Interrogate")); Interr_Err_Ind[0]=0xb; Interr_Err_Ind[3]=0x8; - WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE); + PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE); break; } - WRITE_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle); + PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle); sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind); plci_remove(plci); break; @@ -5242,17 +5242,17 @@ void sig_ind(PLCI * plci) case DEACTIVATION_MWI: if(pty_cai[5]==ACTIVATION_MWI) { - WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE); + PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); } - else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); + else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); if(pty_cai[2]!=0xff) { - WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); + PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]); } else { - WRITE_WORD(&SS_Ind[4],0x300E); + PUT_WORD(&SS_Ind[4],0x300E); } if(plci->cr_enquiry) @@ -5275,29 +5275,29 @@ void sig_ind(PLCI * plci) switch(pty_cai[5]) { case CONF_BEGIN: - WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN); + PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); plci->ptyState = 0; break; case CONF_DROP: CONF_Ind[0]=5; CONF_Ind[3]=2; - WRITE_WORD(&CONF_Ind[1],S_CONF_DROP); + PUT_WORD(&CONF_Ind[1],S_CONF_DROP); plci->ptyState = CONNECTED; break; case CONF_ISOLATE: CONF_Ind[0]=5; CONF_Ind[3]=2; - WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE); + PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); plci->ptyState = CONNECTED; break; case CONF_REATTACH: CONF_Ind[0]=5; CONF_Ind[3]=2; - WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH); + PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); plci->ptyState = CONNECTED; break; case CONF_ADD: - WRITE_WORD(&CONF_Ind[1],S_CONF_ADD); + PUT_WORD(&CONF_Ind[1],S_CONF_ADD); plci->relatedPTYPLCI = NULL; tplci=plci->relatedPTYPLCI; if(tplci) tplci->ptyState = CONNECTED; @@ -5307,15 +5307,15 @@ void sig_ind(PLCI * plci) if(pty_cai[2]!=0xff) { - WRITE_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]); + PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]); } else { - WRITE_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond + PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond within the required time */ } - WRITE_DWORD(&CONF_Ind[6],0x0); + PUT_DWORD(&CONF_Ind[6],0x0); sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind); break; } @@ -5324,7 +5324,7 @@ void sig_ind(PLCI * plci) /* Supplementary Service indicates success */ case S_SERVICE: dbug(1,dprintf("Service_Ind")); - WRITE_WORD (&CF_Ind[4], 0); + PUT_WORD (&CF_Ind[4], 0); switch (pty_cai[5]) { case THREE_PTY_END: @@ -5336,7 +5336,7 @@ void sig_ind(PLCI * plci) if(tplci->tel) rId|=EXT_CONTROLLER; if(pty_cai[5]==ECT_EXECUTE) { - WRITE_WORD(&SS_Ind[1],S_ECT); + PUT_WORD(&SS_Ind[1],S_ECT); if(plci->vswitchstate!=3) { @@ -5369,13 +5369,13 @@ void sig_ind(PLCI * plci) dbug(1,dprintf("3PTY OFF")); break; } - WRITE_WORD(&SS_Ind[1],pty_cai[5]+3); + PUT_WORD(&SS_Ind[1],pty_cai[5]+3); sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind); } break; case CALL_DEFLECTION: - WRITE_WORD(&SS_Ind[1],pty_cai[5]); + PUT_WORD(&SS_Ind[1],pty_cai[5]); for(i=0; iappl) break; - WRITE_WORD(&CF_Ind[1],pty_cai[5]+2); - WRITE_DWORD(&CF_Ind[6],plci->appl->S_Handle); + PUT_WORD(&CF_Ind[1],pty_cai[5]+2); + PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle); sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind); plci_remove(plci); break; @@ -5409,32 +5409,32 @@ void sig_ind(PLCI * plci) case DIVERSION_INTERROGATE_CFB: case DIVERSION_INTERROGATE_CFNR: dbug(1,dprintf("Interr_Div")); - WRITE_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION); + PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION); pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ break; case DIVERSION_INTERROGATE_NUM: dbug(1,dprintf("Interr_Num")); - WRITE_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS); + PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS); pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ break; case CCBS_REQUEST: dbug(1,dprintf("CCBS Request")); - WRITE_WORD(&pty_cai[1],S_CCBS_REQUEST); + PUT_WORD(&pty_cai[1],S_CCBS_REQUEST); pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ break; case CCBS_DEACTIVATE: dbug(1,dprintf("CCBS Deactivate")); - WRITE_WORD(&pty_cai[1],S_CCBS_DEACTIVATE); + PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE); pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ break; case CCBS_INTERROGATE: dbug(1,dprintf("CCBS Interrogate")); - WRITE_WORD(&pty_cai[1],S_CCBS_INTERROGATE); + PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE); pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */ break; } - WRITE_WORD(&pty_cai[4],0); /* Supplementary Service Reason */ - WRITE_DWORD(&pty_cai[6],plci->appl->S_Handle); + PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */ + PUT_DWORD(&pty_cai[6],plci->appl->S_Handle); sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai); plci_remove(plci); break; @@ -5443,9 +5443,9 @@ void sig_ind(PLCI * plci) case DEACTIVATION_MWI: if(pty_cai[5]==ACTIVATION_MWI) { - WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE); + PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE); } - else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); + else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE); if(plci->cr_enquiry) { sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind); @@ -5459,7 +5459,7 @@ void sig_ind(PLCI * plci) case MWI_INDICATION: if(pty_cai[0]>=0x12) { - WRITE_WORD(&pty_cai[3],S_MWI_INDICATE); + PUT_WORD(&pty_cai[3],S_MWI_INDICATE); pty_cai[2]=pty_cai[0]-2; /* len Parameter */ pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */ if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI)) @@ -5516,45 +5516,45 @@ void sig_ind(PLCI * plci) switch(pty_cai[5]) { case CONF_BEGIN: - WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN); + PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN); if(pty_cai[0]==6) { d=pty_cai[6]; - WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */ + PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ } else { - WRITE_DWORD(&CONF_Ind[6],0x0); + PUT_DWORD(&CONF_Ind[6],0x0); } break; case CONF_ISOLATE: - WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE); + PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE); CONF_Ind[0]=5; CONF_Ind[3]=2; break; case CONF_REATTACH: - WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH); + PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH); CONF_Ind[0]=5; CONF_Ind[3]=2; break; case CONF_DROP: - WRITE_WORD(&CONF_Ind[1],S_CONF_DROP); + PUT_WORD(&CONF_Ind[1],S_CONF_DROP); CONF_Ind[0]=5; CONF_Ind[3]=2; break; case CONF_ADD: - WRITE_WORD(&CONF_Ind[1],S_CONF_ADD); + PUT_WORD(&CONF_Ind[1],S_CONF_ADD); d=pty_cai[6]; - WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */ + PUT_DWORD(&CONF_Ind[6],d); /* PartyID */ tplci=plci->relatedPTYPLCI; if(tplci) tplci->ptyState = CONNECTED; break; case CONF_PARTYDISC: CONF_Ind[0]=7; CONF_Ind[3]=4; - WRITE_WORD(&CONF_Ind[1],S_CONF_PARTYDISC); + PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC); d=pty_cai[6]; - WRITE_DWORD(&CONF_Ind[4],d); /* PartyID */ + PUT_DWORD(&CONF_Ind[4],d); /* PartyID */ break; } plci->ptyState = CONNECTED; @@ -5568,13 +5568,13 @@ void sig_ind(PLCI * plci) switch(pty_cai[5]) { case CCBS_INFO_RETAIN: - WRITE_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN); + PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN); break; case CCBS_STOP_ALERTING: - WRITE_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING); + PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING); break; case CCBS_ERASECALLLINKAGEID: - WRITE_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID); + PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID); CONF_Ind[0]=7; CONF_Ind[3]=4; CONF_Ind[6]=0; @@ -5582,7 +5582,7 @@ void sig_ind(PLCI * plci) break; } w=pty_cai[6]; - WRITE_WORD(&CONF_Ind[4],w); /* PartyID */ + PUT_WORD(&CONF_Ind[4],w); /* PartyID */ if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS)) { @@ -5608,8 +5608,8 @@ void sig_ind(PLCI * plci) { i = 0x3603; } - WRITE_WORD(&SS_Ind[1],S_HOLD); - WRITE_WORD(&SS_Ind[4],i); + PUT_WORD(&SS_Ind[1],S_HOLD); + PUT_WORD(&SS_Ind[4],i); if(plci->SuppState == HOLD_REQUEST) { plci->SuppState = IDLE; @@ -5637,8 +5637,8 @@ void sig_ind(PLCI * plci) { i = 0x3603; } - WRITE_WORD(&SS_Ind[1],S_RETRIEVE); - WRITE_WORD(&SS_Ind[4],i); + PUT_WORD(&SS_Ind[1],S_RETRIEVE); + PUT_WORD(&SS_Ind[4],i); if(plci->SuppState == RETRIEVE_REQUEST) { plci->SuppState = CALL_HELD; @@ -5648,7 +5648,7 @@ void sig_ind(PLCI * plci) break; case CALL_RETRIEVE_ACK: - WRITE_WORD(&SS_Ind[1],S_RETRIEVE); + PUT_WORD(&SS_Ind[1],S_RETRIEVE); if(plci->SuppState == RETRIEVE_REQUEST) { plci->SuppState = IDLE; @@ -5919,7 +5919,7 @@ void sig_ind(PLCI * plci) a->AdvSignalPLCI = &a->plci[i-1]; tplci = a->AdvSignalPLCI; tplci->tel = ADV_VOICE; - WRITE_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength); + PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength); if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){ /* early B3 connect (CIP mask bit 9) no release after a disc */ add_p(tplci,LLI,"\x01\x01"); @@ -5985,7 +5985,7 @@ void sig_ind(PLCI * plci) case RESUME: clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1)); - WRITE_WORD(&resume_cau[4],GOOD); + PUT_WORD(&resume_cau[4],GOOD); sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); break; @@ -6070,7 +6070,7 @@ void sig_ind(PLCI * plci) { if(plci->State==RESUMING) { - WRITE_WORD(&resume_cau[4],i); + PUT_WORD(&resume_cau[4],i); sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau); } plci->State = INC_DIS_PENDING; @@ -6624,10 +6624,10 @@ void nl_ind(PLCI * plci) if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN)) ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED); data++; /* connected norm */ - conn_opt = READ_WORD(data); + conn_opt = GET_WORD(data); data += 2; /* connected options */ - WRITE_WORD (&(plci->ncpi_buffer[1]), (word)(READ_DWORD(data) & 0x0000FFFF)); + PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF)); if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42) { @@ -6645,7 +6645,7 @@ void nl_ind(PLCI * plci) { ncpi_opt |= MDM_NCPI_COMPRESSED; } - WRITE_WORD (&(plci->ncpi_buffer[3]), ncpi_opt); + PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt); plci->ncpi_buffer[0] = 4; plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND; @@ -6788,8 +6788,8 @@ void nl_ind(PLCI * plci) { dbug(1,dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code)); len = 9; - WRITE_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400); - fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); + PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400); + fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000; if (plci->B3_prot == 5) { @@ -6805,8 +6805,8 @@ void nl_ind(PLCI * plci) i |= 0x0002; /* Fax-polling indication */ } dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i)); - WRITE_WORD(&(plci->ncpi_buffer[3]),i); - WRITE_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format); + PUT_WORD(&(plci->ncpi_buffer[3]),i); + PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO *)plci->NL.RBuffer->P)->data_format); plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low; plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high; plci->ncpi_buffer[len] = 0; @@ -6833,8 +6833,8 @@ void nl_ind(PLCI * plci) } plci->ncpi_buffer[0] = len; - fax_feature_bits = READ_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); - WRITE_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits); + fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low); + PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits); plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND; if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK) @@ -6902,7 +6902,7 @@ void nl_ind(PLCI * plci) { case EDATA_T30_DIS: if ((a->ncci_state[ncci] == OUTG_CON_PENDING) - && !(READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING) + && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING) && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT) && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT)) { @@ -7063,11 +7063,11 @@ void nl_ind(PLCI * plci) { len = 9; i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400; - WRITE_WORD (&plci->ncpi_buffer[1], i); - WRITE_WORD (&plci->ncpi_buffer[3], 0); + PUT_WORD (&plci->ncpi_buffer[1], i); + PUT_WORD (&plci->ncpi_buffer[3], 0); i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format; - WRITE_WORD (&plci->ncpi_buffer[5], i); - WRITE_WORD (&plci->ncpi_buffer[7], 0); + PUT_WORD (&plci->ncpi_buffer[5], i); + PUT_WORD (&plci->ncpi_buffer[7], 0); plci->ncpi_buffer[len] = 0; plci->ncpi_buffer[0] = len; if(plci->B3_prot == 4) @@ -7493,7 +7493,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE)); adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE)); voice_cai[1] = plci->B1_resource; - WRITE_WORD (&voice_cai[5], plci->appl->MaxDataLength); + PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength); add_p(plci, CAI, voice_cai); dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1])); return 0; @@ -7534,7 +7534,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti { return _WRONG_MESSAGE_FORMAT; } - switch(READ_WORD(global_config[0].info)) + switch(GET_WORD(global_config[0].info)) { case 1: plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; @@ -7547,7 +7547,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti dbug(1,dprintf("call_dir=%04x", plci->call_dir)); - if ((READ_WORD(bp_parms[0].info) == B1_RTP) + if ((GET_WORD(bp_parms[0].info) == B1_RTP) && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) { plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE)); @@ -7556,7 +7556,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[2] = 0; cai[3] = 0; cai[4] = 0; - WRITE_WORD(&cai[5],plci->appl->MaxDataLength); + PUT_WORD(&cai[5],plci->appl->MaxDataLength); for (i = 0; i < bp_parms[3].length; i++) cai[7+i] = bp_parms[3].info[1+i]; cai[0] = 6 + bp_parms[3].length; @@ -7565,7 +7565,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti } - if ((READ_WORD(bp_parms[0].info) == B1_PIAFS) + if ((GET_WORD(bp_parms[0].info) == B1_PIAFS) && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))) { plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE)); @@ -7574,31 +7574,31 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[2] = 0; cai[3] = 0; cai[4] = 0; - WRITE_WORD(&cai[5],plci->appl->MaxDataLength); + PUT_WORD(&cai[5],plci->appl->MaxDataLength); cai[0] = 6; add_p(plci, CAI, cai); return 0; } - if ((READ_WORD(bp_parms[0].info) >= 32) - || (!((1L << READ_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols) - && ((READ_WORD(bp_parms[0].info) != 3) + if ((GET_WORD(bp_parms[0].info) >= 32) + || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols) + && ((GET_WORD(bp_parms[0].info) != 3) || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols) - || ((bp_parms[3].length != 0) && (READ_WORD(&bp_parms[3].info[1]) != 0) && (READ_WORD(&bp_parms[3].info[1]) != 56000))))) + || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000))))) { return _B1_NOT_SUPPORTED; } - plci->B1_resource = add_b1_facilities (plci, resource[READ_WORD(bp_parms[0].info)], + plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)], (word)(b1_facilities & ~B1_FACILITY_VOICE)); adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE)); cai[0] = 6; cai[1] = plci->B1_resource; for (i=2;i", READ_WORD(mdm_cfg[0].info))); + dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info))); - WRITE_WORD (&cai[13], 0); /* Min Tx speed */ - WRITE_WORD (&cai[15], READ_WORD(mdm_cfg[0].info)); /* Max Tx speed */ - WRITE_WORD (&cai[17], 0); /* Min Rx speed */ - WRITE_WORD (&cai[19], READ_WORD(mdm_cfg[0].info)); /* Max Rx speed */ + PUT_WORD (&cai[13], 0); /* Min Tx speed */ + PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */ + PUT_WORD (&cai[17], 0); /* Min Rx speed */ + PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */ cai[3] = 0; /* Async framing parameters */ - switch (READ_WORD (mdm_cfg[2].info)) + switch (GET_WORD (mdm_cfg[2].info)) { /* Parity */ case 1: /* odd parity */ cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); @@ -7636,7 +7636,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti break; } - switch (READ_WORD (mdm_cfg[3].info)) + switch (GET_WORD (mdm_cfg[3].info)) { /* stop bits */ case 1: /* 2 stop bits */ cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; @@ -7648,7 +7648,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti break; } - switch (READ_WORD (mdm_cfg[1].info)) + switch (GET_WORD (mdm_cfg[1].info)) { /* char length */ case 5: cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; @@ -7680,40 +7680,40 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti dbug(1, dprintf("MDM: Reverse direction")); } - if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN) + if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN) { cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN; dbug(1, dprintf("MDM: Disable retrain")); } - if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE) + if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE) { cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE; dbug(1, dprintf("MDM: Disable ring tone")); } - if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800) + if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800) { cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ; dbug(1, dprintf("MDM: 1800 guard tone")); } - else if (READ_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 ) + else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 ) { cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ; dbug(1, dprintf("MDM: 550 guard tone")); } - if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100) + if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100) { cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100; dbug(1, dprintf("MDM: V100")); } - else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS) + else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS) { cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS; dbug(1, dprintf("MDM: IN CLASS")); } - else if ((READ_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED) + else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED) { cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED; dbug(1, dprintf("MDM: DISABLED")); @@ -7721,11 +7721,11 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[0] = 20; if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18)) - && (READ_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */ + && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */ { plci->requested_options |= 1L << PRIVATE_V18; } - if (READ_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */ + if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */ plci->requested_options |= 1L << PRIVATE_VOWN; if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1]) @@ -7736,19 +7736,19 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti i = 27; if (mdm_cfg[6].length >= 4) { - d = READ_DWORD(&mdm_cfg[6].info[1]); + d = GET_DWORD(&mdm_cfg[6].info[1]); cai[7] |= (byte) d; /* line taking options */ cai[9] |= (byte)(d >> 8); /* modulation options */ cai[++i] = (byte)(d >> 16); /* vown modulation options */ cai[++i] = (byte)(d >> 24); if (mdm_cfg[6].length >= 8) { - d = READ_DWORD(&mdm_cfg[6].info[5]); + d = GET_DWORD(&mdm_cfg[6].info[5]); cai[10] |= (byte) d; /* disabled modulations mask */ cai[11] |= (byte)(d >> 8); if (mdm_cfg[6].length >= 12) { - d = READ_DWORD(&mdm_cfg[6].info[9]); + d = GET_DWORD(&mdm_cfg[6].info[9]); cai[12] = (byte) d; /* enabled modulations mask */ cai[++i] = (byte)(d >> 8); /* vown enabled modulations */ cai[++i] = (byte)(d >> 16); @@ -7756,31 +7756,31 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[++i] = 0; if (mdm_cfg[6].length >= 14) { - w = READ_WORD(&mdm_cfg[6].info[13]); + w = GET_WORD(&mdm_cfg[6].info[13]); if (w != 0) - WRITE_WORD(&cai[13], w); /* min tx speed */ + PUT_WORD(&cai[13], w); /* min tx speed */ if (mdm_cfg[6].length >= 16) { - w = READ_WORD(&mdm_cfg[6].info[15]); + w = GET_WORD(&mdm_cfg[6].info[15]); if (w != 0) - WRITE_WORD(&cai[15], w); /* max tx speed */ + PUT_WORD(&cai[15], w); /* max tx speed */ if (mdm_cfg[6].length >= 18) { - w = READ_WORD(&mdm_cfg[6].info[17]); + w = GET_WORD(&mdm_cfg[6].info[17]); if (w != 0) - WRITE_WORD(&cai[17], w); /* min rx speed */ + PUT_WORD(&cai[17], w); /* min rx speed */ if (mdm_cfg[6].length >= 20) { - w = READ_WORD(&mdm_cfg[6].info[19]); + w = GET_WORD(&mdm_cfg[6].info[19]); if (w != 0) - WRITE_WORD(&cai[19], w); /* max rx speed */ + PUT_WORD(&cai[19], w); /* max rx speed */ if (mdm_cfg[6].length >= 22) { - w = READ_WORD(&mdm_cfg[6].info[21]); + w = GET_WORD(&mdm_cfg[6].info[21]); cai[23] = (byte)(-((short) w)); /* transmit level */ if (mdm_cfg[6].length >= 24) { - w = READ_WORD(&mdm_cfg[6].info[23]); + w = GET_WORD(&mdm_cfg[6].info[23]); cai[22] |= (byte) w; /* info options mask */ cai[21] |= (byte)(w >> 8); /* disabled symbol rates */ } @@ -7813,21 +7813,21 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti } } - if(READ_WORD(bp_parms[0].info)==2 || /* V.110 async */ - READ_WORD(bp_parms[0].info)==3 ) /* V.110 sync */ + if(GET_WORD(bp_parms[0].info)==2 || /* V.110 async */ + GET_WORD(bp_parms[0].info)==3 ) /* V.110 sync */ { if(bp_parms[3].length){ - dbug(1,dprintf("V.110,%d",READ_WORD(&bp_parms[3].info[1]))); - switch(READ_WORD(&bp_parms[3].info[1])){ /* Rate */ + dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1]))); + switch(GET_WORD(&bp_parms[3].info[1])){ /* Rate */ case 0: case 56000: - if(READ_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */ + if(GET_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */ dbug(1,dprintf("56k sync HSCX")); cai[1] = 8; cai[2] = 0; cai[3] = 0; } - else if(READ_WORD(bp_parms[0].info)==2){ + else if(GET_WORD(bp_parms[0].info)==2){ dbug(1,dprintf("56k async DSP")); cai[2] = 9; } @@ -7863,7 +7863,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti { if (bp_parms[3].length >= 8) { - switch (READ_WORD (&bp_parms[3].info[3])) + switch (GET_WORD (&bp_parms[3].info[3])) { /* char length */ case 5: cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5; @@ -7875,7 +7875,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7; break; } - switch (READ_WORD (&bp_parms[3].info[5])) + switch (GET_WORD (&bp_parms[3].info[5])) { /* Parity */ case 1: /* odd parity */ cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD); @@ -7884,7 +7884,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN); break; } - switch (READ_WORD (&bp_parms[3].info[7])) + switch (GET_WORD (&bp_parms[3].info[7])) { /* stop bits */ case 1: /* 2 stop bits */ cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS; @@ -7893,7 +7893,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti } } } - else if(cai[1]==8 || READ_WORD(bp_parms[0].info)==3 ){ + else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){ dbug(1,dprintf("V.110 default 56k sync")); cai[1] = 8; cai[2] = 0; @@ -7904,7 +7904,7 @@ word add_b1(PLCI * plci, API_PARSE * bp, word b_channel_info, word b1_faciliti cai[2] = 5; } } - WRITE_WORD(&cai[5],plci->appl->MaxDataLength); + PUT_WORD(&cai[5],plci->appl->MaxDataLength); dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6])); /* HexDump ("CAI", sizeof(cai), &cai[0]); */ @@ -7987,7 +7987,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) llc[2] = 4; add_p(plci, LLC, llc); dlc[0] = 2; - WRITE_WORD(&dlc[1],plci->appl->MaxDataLength); + PUT_WORD(&dlc[1],plci->appl->MaxDataLength); add_p(plci, DLC, dlc); return 0; } @@ -8002,7 +8002,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) llc[2] = 4; add_p(plci, LLC, llc); dlc[0] = 2; - WRITE_WORD(&dlc[1],plci->appl->MaxDataLength); + PUT_WORD(&dlc[1],plci->appl->MaxDataLength); add_p(plci, DLC, dlc); return 0; } @@ -8026,25 +8026,25 @@ word add_b23(PLCI * plci, API_PARSE * bp) if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */ { - if(READ_WORD(bp_parms[1].info)!=1 - || READ_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED; + if(GET_WORD(bp_parms[1].info)!=1 + || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED; plci->adv_nl = TRUE; } else if(plci->tel) return _B2_NOT_SUPPORTED; - if ((READ_WORD(bp_parms[1].info) == B2_RTP) - && (READ_WORD(bp_parms[2].info) == B3_RTP) + if ((GET_WORD(bp_parms[1].info) == B2_RTP) + && (GET_WORD(bp_parms[2].info) == B3_RTP) && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP))) { add_p(plci,LLI,lli); - plci->B2_prot = (byte) READ_WORD(bp_parms[1].info); - plci->B3_prot = (byte) READ_WORD(bp_parms[2].info); + plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); + plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13; llc[2] = 4; add_p(plci, LLC, llc); dlc[0] = 2; - WRITE_WORD(&dlc[1],plci->appl->MaxDataLength); + PUT_WORD(&dlc[1],plci->appl->MaxDataLength); dlc[3] = 3; /* Addr A */ dlc[4] = 1; /* Addr B */ dlc[5] = 7; /* modulo mode */ @@ -8064,31 +8064,31 @@ word add_b23(PLCI * plci, API_PARSE * bp) - if ((READ_WORD(bp_parms[1].info) >= 32) - || (!((1L << READ_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols) - && ((READ_WORD(bp_parms[1].info) != B2_PIAFS) + if ((GET_WORD(bp_parms[1].info) >= 32) + || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols) + && ((GET_WORD(bp_parms[1].info) != B2_PIAFS) || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS))))) { return _B2_NOT_SUPPORTED; } - if ((READ_WORD(bp_parms[2].info) >= 32) - || !((1L << READ_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols)) + if ((GET_WORD(bp_parms[2].info) >= 32) + || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols)) { return _B3_NOT_SUPPORTED; } - if ((READ_WORD(bp_parms[1].info) != B2_SDLC) - && ((READ_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) - || (READ_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) - || (READ_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))) + if ((GET_WORD(bp_parms[1].info) != B2_SDLC) + && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE) + || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC) + || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))) { return (add_modem_b23 (plci, bp_parms)); } add_p(plci,LLI,lli); - plci->B2_prot = (byte) READ_WORD(bp_parms[1].info); - plci->B3_prot = (byte) READ_WORD(bp_parms[2].info); + plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); + plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */ if(bp_parms[6].length) @@ -8097,7 +8097,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) { return _WRONG_MESSAGE_FORMAT; } - switch(READ_WORD(global_config[0].info)) + switch(GET_WORD(global_config[0].info)) { case 1: plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE; @@ -8116,15 +8116,15 @@ word add_b23(PLCI * plci, API_PARSE * bp) /* IMPLEMENT_PIAFS */ { llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? - llc2_out[READ_WORD(bp_parms[1].info)] : llc2_in[READ_WORD(bp_parms[1].info)]; + llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)]; } - llc[2] = llc3[READ_WORD(bp_parms[2].info)]; + llc[2] = llc3[GET_WORD(bp_parms[2].info)]; add_p(plci, LLC, llc); dlc[0] = 2; - WRITE_WORD(&dlc[1], plci->appl->MaxDataLength + - header[READ_WORD(bp_parms[2].info)]); + PUT_WORD(&dlc[1], plci->appl->MaxDataLength + + header[GET_WORD(bp_parms[2].info)]); b1_config = &bp_parms[3]; nlc[0] = 0; @@ -8138,7 +8138,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff; if(b1_config->length>=2) { - ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(READ_WORD(&b1_config->info[1])/2400); + ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400); } } b2_config = &bp_parms[4]; @@ -8153,7 +8153,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) { return _WRONG_MESSAGE_FORMAT; } - WRITE_WORD(&dlc[1],plci->appl->MaxDataLength); + PUT_WORD(&dlc[1],plci->appl->MaxDataLength); dlc[3] = 0; /* Addr A */ dlc[4] = 0; /* Addr B */ dlc[5] = 0; /* modulo mode */ @@ -8200,7 +8200,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) return _B_STACK_NOT_SUPPORTED; dlc[0] = 6; - WRITE_WORD (&dlc[1], READ_WORD (&dlc[1]) + 2); + PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2); dlc[3] = 0x08; dlc[4] = 0x01; dlc[5] = 127; @@ -8320,7 +8320,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) } else { - WRITE_WORD(&dlc[7], (word)b2_config_parms[4].length); + PUT_WORD(&dlc[7], (word)b2_config_parms[4].length); for(i=0; iresolution = (byte)(((i & 0x0001) || - ((plci->B3_prot == 4) && (((byte)(READ_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0); - ((T30_INFO *)&nlc[1])->data_format = (byte)(READ_WORD((byte *)b3_config_parms[1].info)); + ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0); + ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info)); fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES; if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6)) fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX; @@ -8377,7 +8377,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution; ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format; ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties; - fax_control_bits |= READ_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & + fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS); } } @@ -8435,12 +8435,12 @@ word add_b23(PLCI * plci, API_PARSE * bp) if(plci->B3_prot == 5) { if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD)) - && (READ_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */ + && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */ { plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD; } if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD)) - && (READ_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */ + && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */ { plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD; } @@ -8476,7 +8476,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0)) { if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2)) - plci->nsf_control_bits = READ_WORD(&plci->fax_connect_info_buffer[pos+2]); + plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]); for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) nlc[++len] = plci->fax_connect_info_buffer[pos++]; } @@ -8490,7 +8490,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) else { if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2)) - plci->nsf_control_bits = READ_WORD(&b3_config_parms[4].info[2]); + plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]); nlc[++len] = (byte)(b3_config_parms[4].length); for (i = 0; i < b3_config_parms[4].length; i++) nlc[++len] = b3_config_parms[4].info[1+i]; @@ -8506,7 +8506,7 @@ word add_b23(PLCI * plci, API_PARSE * bp) } } - WRITE_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); + PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); len = ((byte)(((T30_INFO *) 0)->station_id + 20)); for (i = 0; i < len; i++) plci->fax_connect_info_buffer[i] = nlc[1+i]; @@ -8522,10 +8522,10 @@ word add_b23(PLCI * plci, API_PARSE * bp) if(b3_config->length!=16) return _B3_PARM_NOT_SUPPORTED; for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i]; - if(READ_WORD(&b3_config->info[13])!=8 && READ_WORD(&b3_config->info[13])!=128) + if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128) return _B3_PARM_NOT_SUPPORTED; nlc[13] = b3_config->info[13]; - if(READ_WORD(&b3_config->info[15])>=nlc[13]) + if(GET_WORD(&b3_config->info[15])>=nlc[13]) return _B3_PARM_NOT_SUPPORTED; nlc[14] = b3_config->info[15]; } @@ -8566,23 +8566,23 @@ static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms) for(i=0;i<2;i++) mdm_config[i].length = 0; for(i=0;iB2_prot = (byte) READ_WORD(bp_parms[1].info); - plci->B3_prot = (byte) READ_WORD(bp_parms[2].info); + plci->B2_prot = (byte) GET_WORD(bp_parms[1].info); + plci->B3_prot = (byte) GET_WORD(bp_parms[2].info); - if ((READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length) + if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length) { if (api_parse (&bp_parms[4].info[1], (word)bp_parms[4].length, "w", @@ -8590,7 +8590,7 @@ static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms) { return (_WRONG_MESSAGE_FORMAT); } - b2_config = READ_WORD(mdm_config[0].info); + b2_config = GET_WORD(mdm_config[0].info); } /* OK, L2 is modem */ @@ -8630,9 +8630,9 @@ static word add_modem_b23 (PLCI * plci, API_PARSE* bp_parms) add_p(plci, LLI, lli); add_p(plci, LLC, llc); i = 1; - WRITE_WORD (&dlc[i], plci->appl->MaxDataLength); + PUT_WORD (&dlc[i], plci->appl->MaxDataLength); i += 2; - if (READ_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) + if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) { if (bp_parms[4].length) { @@ -8702,7 +8702,7 @@ void sig_req(PLCI * plci, byte req, byte Id) plci->req_in +=2; plci->RBuffer[plci->req_in++] = 0; } - WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); + PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); plci->RBuffer[plci->req_in++] = Id; /* sig/nl flag */ plci->RBuffer[plci->req_in++] = req; /* request */ plci->RBuffer[plci->req_in++] = 0; /* channel */ @@ -8728,7 +8728,7 @@ void nl_req_ncci(PLCI * plci, byte req, byte ncci) plci->req_in +=2; plci->RBuffer[plci->req_in++] = 0; } - WRITE_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); + PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2); plci->RBuffer[plci->req_in++] = 1; /* sig/nl flag */ plci->RBuffer[plci->req_in++] = req; /* request */ plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci]; /* channel */ @@ -8751,7 +8751,7 @@ void send_req(PLCI * plci) if(plci->nl_req || plci->sig_req) return; - l = READ_WORD(&plci->RBuffer[plci->req_out]); + l = GET_WORD(&plci->RBuffer[plci->req_out]); plci->req_out += 2; plci->XData[0].P = &plci->RBuffer[plci->req_out]; plci->req_out += l; @@ -9586,11 +9586,11 @@ static void dtmf_enable_receiver (PLCI *plci, byte enable_mask) min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms; min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms; plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER; - WRITE_WORD (&plci->internal_req_buffer[1], min_digit_duration); - WRITE_WORD (&plci->internal_req_buffer[3], min_gap_duration); + PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration); + PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration); plci->NData[0].PLength = 5; - WRITE_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE); + PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE); plci->NData[0].PLength += 2; capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration); @@ -9621,9 +9621,9 @@ static void dtmf_send_digits (PLCI *plci, byte *digit_buffer, word digit_cou plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS; w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms; - WRITE_WORD (&plci->internal_req_buffer[1], w); + PUT_WORD (&plci->internal_req_buffer[1], w); w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms; - WRITE_WORD (&plci->internal_req_buffer[3], w); + PUT_WORD (&plci->internal_req_buffer[3], w); for (i = 0; i < digit_count; i++) { w = 0; @@ -9744,7 +9744,7 @@ static void dtmf_command (dword Id, PLCI *plci, byte Rc) Info = GOOD; result[0] = 2; - WRITE_WORD (&result[1], DTMF_SUCCESS); + PUT_WORD (&result[1], DTMF_SUCCESS); internal_command = plci->internal_command; plci->internal_command = 0; mask = 0x01; @@ -9915,7 +9915,7 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = GOOD; result[0] = 2; - WRITE_WORD (&result[1], DTMF_SUCCESS); + PUT_WORD (&result[1], DTMF_SUCCESS); if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED)) { dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported", @@ -9929,21 +9929,21 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = _WRONG_MESSAGE_FORMAT; } - else if ((READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) - || (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES)) + else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) + || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES)) { if (!((a->requested_options_table[appl->Id-1]) & (1L << PRIVATE_DTMF_TONE))) { dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", - UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info))); - WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST); + UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); + PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); } else { for (i = 0; i < 32; i++) result[4 + i] = 0; - if (READ_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) + if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES) { for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++) { @@ -9982,7 +9982,7 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI else { plci->command = 0; - plci->dtmf_cmd = READ_WORD (dtmf_parms[0].info); + plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info); mask = 0x01; switch (plci->dtmf_cmd) { @@ -9997,8 +9997,8 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI & (1L << PRIVATE_DTMF_TONE))) { dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", - UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info))); - WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST); + UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); + PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); break; } @@ -10021,8 +10021,8 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI } else { - plci->dtmf_rec_pulse_ms = READ_WORD (dtmf_parms[1].info); - plci->dtmf_rec_pause_ms = READ_WORD (dtmf_parms[2].info); + plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info); + plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info); } } start_internal_command (Id, plci, dtmf_command); @@ -10037,8 +10037,8 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI & (1L << PRIVATE_DTMF_TONE))) { dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", - UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (dtmf_parms[0].info))); - WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST); + UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info))); + PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); break; } @@ -10052,8 +10052,8 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI } if (mask & DTMF_LISTEN_ACTIVE_FLAG) { - plci->dtmf_send_pulse_ms = READ_WORD (dtmf_parms[1].info); - plci->dtmf_send_pause_ms = READ_WORD (dtmf_parms[2].info); + plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info); + plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info); } i = 0; j = 0; @@ -10072,7 +10072,7 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x", UnMapId (Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i])); - WRITE_WORD (&result[1], DTMF_INCORRECT_DIGIT); + PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT); break; } if (plci->dtmf_send_requests >= @@ -10090,7 +10090,7 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI default: dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x", UnMapId (Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd)); - WRITE_WORD (&result[1], DTMF_UNKNOWN_REQUEST); + PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST); } } } @@ -10111,7 +10111,7 @@ static void dtmf_confirmation (dword Id, PLCI *plci) Info = GOOD; result[0] = 2; - WRITE_WORD (&result[1], DTMF_SUCCESS); + PUT_WORD (&result[1], DTMF_SUCCESS); if (plci->dtmf_send_requests != 0) { sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0], @@ -11075,7 +11075,7 @@ static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc) if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) { - w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); + w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); } if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) w |= MIXER_FEATURE_ENABLE_TX_DATA; @@ -11181,7 +11181,7 @@ static byte xconnect_write_coefs_process (dword Id, PLCI *plci, byte Rc) if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI) && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)) { - w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); + w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); } if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) w |= MIXER_FEATURE_ENABLE_TX_DATA; @@ -11293,7 +11293,7 @@ static void mixer_notify_update (PLCI *plci, byte others) ((CAPI_MSG *) msg)->header.ncci = 0; ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT; ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3; - WRITE_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE); + PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE); ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0; w = api_put (notify_plci->appl, (CAPI_MSG *) msg); if (w != _QUEUE_FULL) @@ -11910,7 +11910,7 @@ static PLCI *li_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); + PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); return (NULL); } ctlr_b = 0; @@ -11926,7 +11926,7 @@ static PLCI *li_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _WRONG_IDENTIFIER); + PUT_WORD (p_result, _WRONG_IDENTIFIER); return (NULL); } plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); @@ -11936,7 +11936,7 @@ static PLCI *li_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); + PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); return (NULL); } li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b; @@ -11947,7 +11947,7 @@ static PLCI *li_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _WRONG_IDENTIFIER); + PUT_WORD (p_result, _WRONG_IDENTIFIER); return (NULL); } if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, @@ -11955,7 +11955,7 @@ static PLCI *li_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource)); - WRITE_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); + PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE); return (NULL); } return (plci_b); @@ -11973,7 +11973,7 @@ static PLCI *li2_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (p_result, _WRONG_STATE); + PUT_WORD (p_result, _WRONG_STATE); return (NULL); } ctlr_b = 0; @@ -11989,7 +11989,7 @@ static PLCI *li2_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _WRONG_IDENTIFIER); + PUT_WORD (p_result, _WRONG_IDENTIFIER); return (NULL); } plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]); @@ -12000,7 +12000,7 @@ static PLCI *li2_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _WRONG_STATE); + PUT_WORD (p_result, _WRONG_STATE); return (NULL); } if (((byte)(plci_b_id & ~EXT_CONTROLLER)) != @@ -12010,7 +12010,7 @@ static PLCI *li2_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b_id)); - WRITE_WORD (p_result, _WRONG_IDENTIFIER); + PUT_WORD (p_result, _WRONG_IDENTIFIER); return (NULL); } if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource, @@ -12018,7 +12018,7 @@ static PLCI *li2_check_plci_b (dword Id, PLCI *plci, { dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d", UnMapId (Id), (char *)(FILE_), __LINE__, plci_b->B1_resource)); - WRITE_WORD (p_result, _WRONG_STATE); + PUT_WORD (p_result, _WRONG_STATE); return (NULL); } return (plci_b); @@ -12062,16 +12062,16 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI else { result_buffer[0] = 3; - WRITE_WORD (&result_buffer[1], READ_WORD (li_parms[0].info)); + PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info)); result_buffer[3] = 0; - switch (READ_WORD (li_parms[0].info)) + switch (GET_WORD (li_parms[0].info)) { case LI_GET_SUPPORTED_SERVICES: if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC) { result_buffer[0] = 17; result_buffer[3] = 14; - WRITE_WORD (&result_buffer[4], GOOD); + PUT_WORD (&result_buffer[4], GOOD); d = 0; if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH) d |= LI_CONFERENCING_SUPPORTED; @@ -12081,7 +12081,7 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED; if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) d |= LI_CROSS_CONTROLLER_SUPPORTED; - WRITE_DWORD (&result_buffer[6], d); + PUT_DWORD (&result_buffer[6], d); if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) { d = 0; @@ -12099,14 +12099,14 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; } - WRITE_DWORD (&result_buffer[10], d / 2); - WRITE_DWORD (&result_buffer[14], d); + PUT_DWORD (&result_buffer[10], d / 2); + PUT_DWORD (&result_buffer[14], d); } else { result_buffer[0] = 25; result_buffer[3] = 22; - WRITE_WORD (&result_buffer[4], GOOD); + PUT_WORD (&result_buffer[4], GOOD); d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED; if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC) d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED; @@ -12116,10 +12116,10 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI d |= LI2_PC_LOOPING_SUPPORTED; if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) d |= LI2_CROSS_CONTROLLER_SUPPORTED; - WRITE_DWORD (&result_buffer[6], d); + PUT_DWORD (&result_buffer[6], d); d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI; - WRITE_DWORD (&result_buffer[10], d / 2); - WRITE_DWORD (&result_buffer[14], d - 1); + PUT_DWORD (&result_buffer[10], d / 2); + PUT_DWORD (&result_buffer[14], d - 1); if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT) { d = 0; @@ -12133,8 +12133,8 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI } } } - WRITE_DWORD (&result_buffer[18], d / 2); - WRITE_DWORD (&result_buffer[22], d - 1); + PUT_DWORD (&result_buffer[18], d / 2); + PUT_DWORD (&result_buffer[22], d - 1); } break; @@ -12149,13 +12149,13 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = _WRONG_MESSAGE_FORMAT; break; } - plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff; - li_flags = READ_DWORD (li_req_parms[1].info); + plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; + li_flags = GET_DWORD (li_req_parms[1].info); Info = li_check_main_plci (Id, plci); result_buffer[0] = 9; result_buffer[3] = 6; - WRITE_DWORD (&result_buffer[4], plci_b_id); - WRITE_WORD (&result_buffer[8], GOOD); + PUT_DWORD (&result_buffer[4], plci_b_id); + PUT_WORD (&result_buffer[8], GOOD); if (Info != GOOD) break; result = plci->saved_msg.info; @@ -12180,11 +12180,11 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = _WRONG_MESSAGE_FORMAT; break; } - li_flags = READ_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A); + li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A); Info = li_check_main_plci (Id, plci); result_buffer[0] = 7; result_buffer[3] = 4; - WRITE_WORD (&result_buffer[4], Info); + PUT_WORD (&result_buffer[4], Info); result_buffer[6] = 0; if (Info != GOOD) break; @@ -12199,14 +12199,14 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { result[result_pos] = 6; result_pos += 7; - WRITE_DWORD (&result[result_pos - 6], 0); - WRITE_WORD (&result[result_pos - 2], GOOD); + PUT_DWORD (&result[result_pos - 6], 0); + PUT_WORD (&result[result_pos - 2], GOOD); if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos], (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) { dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); + PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); break; } if (api_parse (&li_participant_struct[0].info[1], @@ -12214,17 +12214,17 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); + PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); break; } - plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff; - li_flags = READ_DWORD (li_participant_parms[1].info); - WRITE_DWORD (&result[result_pos - 6], plci_b_id); + plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; + li_flags = GET_DWORD (li_participant_parms[1].info); + PUT_DWORD (&result[result_pos - 6], plci_b_id); if (sizeof(result) - result_pos < 7) { dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_STATE); + PUT_WORD (&result[result_pos - 2], _WRONG_STATE); break; } plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); @@ -12259,7 +12259,7 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); plci->command = 0; - plci->li_cmd = READ_WORD (li_parms[0].info); + plci->li_cmd = GET_WORD (li_parms[0].info); start_internal_command (Id, plci, mixer_command); return (FALSE); @@ -12274,12 +12274,12 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = _WRONG_MESSAGE_FORMAT; break; } - plci_b_id = READ_DWORD (li_req_parms[0].info) & 0xffff; + plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff; Info = li_check_main_plci (Id, plci); result_buffer[0] = 9; result_buffer[3] = 6; - WRITE_DWORD (&result_buffer[4], READ_DWORD (li_req_parms[0].info)); - WRITE_WORD (&result_buffer[8], GOOD); + PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info)); + PUT_WORD (&result_buffer[8], GOOD); if (Info != GOOD) break; result = plci->saved_msg.info; @@ -12307,7 +12307,7 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI Info = li_check_main_plci (Id, plci); result_buffer[0] = 7; result_buffer[3] = 4; - WRITE_WORD (&result_buffer[4], Info); + PUT_WORD (&result_buffer[4], Info); result_buffer[6] = 0; if (Info != GOOD) break; @@ -12321,14 +12321,14 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { result[result_pos] = 6; result_pos += 7; - WRITE_DWORD (&result[result_pos - 6], 0); - WRITE_WORD (&result[result_pos - 2], GOOD); + PUT_DWORD (&result[result_pos - 6], 0); + PUT_WORD (&result[result_pos - 2], GOOD); if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos], (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct)) { dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); + PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); break; } if (api_parse (&li_participant_struct[0].info[1], @@ -12336,16 +12336,16 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI { dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); + PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT); break; } - plci_b_id = READ_DWORD (li_participant_parms[0].info) & 0xffff; - WRITE_DWORD (&result[result_pos - 6], plci_b_id); + plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff; + PUT_DWORD (&result[result_pos - 6], plci_b_id); if (sizeof(result) - result_pos < 7) { dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun", UnMapId (Id), (char *)(FILE_), __LINE__)); - WRITE_WORD (&result[result_pos - 2], _WRONG_STATE); + PUT_WORD (&result[result_pos - 2], _WRONG_STATE); break; } plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]); @@ -12378,7 +12378,7 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number, "wwS", Info, SELECTOR_LINE_INTERCONNECT, result); plci->command = 0; - plci->li_cmd = READ_WORD (li_parms[0].info); + plci->li_cmd = GET_WORD (li_parms[0].info); start_internal_command (Id, plci, mixer_command); return (FALSE); @@ -12412,13 +12412,13 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI plci->li_plci_b_write_pos = plci_b_write_pos; plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel; plci->command = 0; - plci->li_cmd = READ_WORD (li_parms[0].info); + plci->li_cmd = GET_WORD (li_parms[0].info); start_internal_command (Id, plci, mixer_command); return (FALSE); default: dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x", - UnMapId (Id), (char *)(FILE_), __LINE__, READ_WORD (li_parms[0].info))); + UnMapId (Id), (char *)(FILE_), __LINE__, GET_WORD (li_parms[0].info))); Info = _FACILITY_NOT_SUPPORTED; } } @@ -12450,16 +12450,16 @@ static void mixer_indication_coefs_set (dword Id, PLCI *plci) if (d & LI_PLCI_B_DISC_FLAG) { result[0] = 5; - WRITE_WORD (&result[1], LI_IND_DISCONNECT); + PUT_WORD (&result[1], LI_IND_DISCONNECT); result[3] = 2; - WRITE_WORD (&result[4], _LI_USER_INITIATED); + PUT_WORD (&result[4], _LI_USER_INITIATED); } else { result[0] = 7; - WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE); + PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); result[3] = 4; - WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); + PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); } } else @@ -12467,17 +12467,17 @@ static void mixer_indication_coefs_set (dword Id, PLCI *plci) if (d & LI_PLCI_B_DISC_FLAG) { result[0] = 9; - WRITE_WORD (&result[1], LI_IND_DISCONNECT); + PUT_WORD (&result[1], LI_IND_DISCONNECT); result[3] = 6; - WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); - WRITE_WORD (&result[8], _LI_USER_INITIATED); + PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); + PUT_WORD (&result[8], _LI_USER_INITIATED); } else { result[0] = 7; - WRITE_WORD (&result[1], LI_IND_CONNECT_ACTIVE); + PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE); result[3] = 4; - WRITE_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); + PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK); } } sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, @@ -12627,10 +12627,10 @@ static void ec_write_parameters (PLCI *plci) parameter_buffer[0] = 5; parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS; - WRITE_WORD (¶meter_buffer[2], plci->ec_idi_options); + PUT_WORD (¶meter_buffer[2], plci->ec_idi_options); plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS; w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length; - WRITE_WORD (¶meter_buffer[4], w); + PUT_WORD (¶meter_buffer[4], w); add_p (plci, FTY, parameter_buffer); sig_req (plci, TEL_CTRL, 0); send_req (plci); @@ -12719,14 +12719,14 @@ static void ec_command (dword Id, PLCI *plci, byte Rc) if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) { result[0] = 2; - WRITE_WORD (&result[1], EC_SUCCESS); + PUT_WORD (&result[1], EC_SUCCESS); } else { result[0] = 5; - WRITE_WORD (&result[1], plci->ec_cmd); + PUT_WORD (&result[1], plci->ec_cmd); result[3] = 2; - WRITE_WORD (&result[4], GOOD); + PUT_WORD (&result[4], GOOD); } internal_command = plci->internal_command; plci->internal_command = 0; @@ -12864,13 +12864,13 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p else { plci->command = 0; - plci->ec_cmd = READ_WORD (ec_parms[0].info); + plci->ec_cmd = GET_WORD (ec_parms[0].info); plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); result[0] = 2; - WRITE_WORD (&result[1], EC_SUCCESS); + PUT_WORD (&result[1], EC_SUCCESS); if (msg[1].length >= 4) { - opt = READ_WORD (&ec_parms[0].info[2]); + opt = GET_WORD (&ec_parms[0].info[2]); plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING)) @@ -12881,7 +12881,7 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; if (msg[1].length >= 6) { - plci->ec_tail_length = READ_WORD (&ec_parms[0].info[4]); + plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]); } } switch (plci->ec_cmd) @@ -12916,7 +12916,7 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p default: dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd)); - WRITE_WORD (&result[1], EC_UNSUPPORTED_OPERATION); + PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION); } } } @@ -12931,15 +12931,15 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p } else { - if (READ_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES) + if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES) { result[0] = 11; - WRITE_WORD (&result[1], EC_GET_SUPPORTED_SERVICES); + PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES); result[3] = 8; - WRITE_WORD (&result[4], GOOD); - WRITE_WORD (&result[6], 0x0007); - WRITE_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH); - WRITE_WORD (&result[10], 0); + PUT_WORD (&result[4], GOOD); + PUT_WORD (&result[6], 0x0007); + PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH); + PUT_WORD (&result[10], 0); } else if (plci == NULL) { @@ -12956,18 +12956,18 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p else { plci->command = 0; - plci->ec_cmd = READ_WORD (ec_parms[0].info); + plci->ec_cmd = GET_WORD (ec_parms[0].info); plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS); result[0] = 5; - WRITE_WORD (&result[1], plci->ec_cmd); + PUT_WORD (&result[1], plci->ec_cmd); result[3] = 2; - WRITE_WORD (&result[4], GOOD); + PUT_WORD (&result[4], GOOD); plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING | LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS); plci->ec_tail_length = 0; if (ec_parms[1].length >= 2) { - opt = READ_WORD (&ec_parms[1].info[1]); + opt = GET_WORD (&ec_parms[1].info[1]); if (opt & EC_ENABLE_NON_LINEAR_PROCESSING) plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING; if (opt & EC_DETECT_DISABLE_TONE) @@ -12976,7 +12976,7 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS; if (ec_parms[1].length >= 4) { - plci->ec_tail_length = READ_WORD (&ec_parms[1].info[3]); + plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]); } } switch (plci->ec_cmd) @@ -12996,7 +12996,7 @@ static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *p default: dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x", UnMapId (Id), (char *)(FILE_), __LINE__, plci->ec_cmd)); - WRITE_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP); + PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP); } } } @@ -13021,36 +13021,36 @@ static void ec_indication (dword Id, PLCI *plci, byte *msg, word length) if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) { result[0] = 2; - WRITE_WORD (&result[1], 0); + PUT_WORD (&result[1], 0); switch (msg[1]) { case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: - WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); + PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); break; case LEC_DISABLE_TYPE_REVERSED_2100HZ: - WRITE_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ); + PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ); break; case LEC_DISABLE_RELEASED: - WRITE_WORD (&result[1], EC_BYPASS_RELEASED); + PUT_WORD (&result[1], EC_BYPASS_RELEASED); break; } } else { result[0] = 5; - WRITE_WORD (&result[1], EC_BYPASS_INDICATION); + PUT_WORD (&result[1], EC_BYPASS_INDICATION); result[3] = 2; - WRITE_WORD (&result[4], 0); + PUT_WORD (&result[4], 0); switch (msg[1]) { case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ: - WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); + PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ); break; case LEC_DISABLE_TYPE_REVERSED_2100HZ: - WRITE_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ); + PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ); break; case LEC_DISABLE_RELEASED: - WRITE_WORD (&result[4], EC_BYPASS_RELEASED); + PUT_WORD (&result[4], EC_BYPASS_RELEASED); break; } } @@ -13086,13 +13086,13 @@ static void adv_voice_write_coefs (PLCI *plci, word write_command) i = 0; while (i + sizeof(word) <= a->adv_voice_coef_length) { - WRITE_WORD (p, READ_WORD (a->adv_voice_coef_buffer + i)); + PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i)); p += 2; i += 2; } while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word)) { - WRITE_WORD (p, 0x8000); + PUT_WORD (p, 0x8000); p += 2; i += 2; } @@ -13172,7 +13172,7 @@ static void adv_voice_write_coefs (PLCI *plci, word write_command) { w = 0; if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length) - w = READ_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); + w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE); if (li_config_table[i].channel & LI_CHANNEL_TX_DATA) w |= MIXER_FEATURE_ENABLE_TX_DATA; if (li_config_table[i].channel & LI_CHANNEL_RX_DATA) diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c index c94229904..29492451a 100644 --- a/drivers/isdn/hardware/eicon/mntfunc.c +++ b/drivers/isdn/hardware/eicon/mntfunc.c @@ -1,4 +1,4 @@ -/* $Id: mntfunc.c,v 1.19 2004/01/09 21:22:03 armin Exp $ +/* $Id: mntfunc.c,v 1.19.6.2 2004/08/28 20:03:53 armin Exp $ * * Driver for Eicon DIVA Server ISDN cards. * Maint module @@ -23,17 +23,12 @@ extern char *DRIVERRELEASE_MNT; extern void DIVA_DIDD_Read(void *, int); -#define MAX_DESCRIPTORS 32 - static dword notify_handle; static DESCRIPTOR DAdapter; static DESCRIPTOR MAdapter; static DESCRIPTOR MaintDescriptor = { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp }; -extern void *diva_os_malloc_tbuffer(unsigned long flags, - unsigned long size); -extern void diva_os_free_tbuffer(unsigned long flags, void *ptr); extern int diva_os_copy_to_user(void *os_handle, void __user *dst, const void *src, int length); extern int diva_os_copy_from_user(void *os_handle, void *dst, @@ -46,16 +41,6 @@ static void no_printf(unsigned char *x, ...) #include "debuglib.c" -/* - * stop debug - */ -static void stop_dbg(void) -{ - DbgDeregister(); - memset(&MAdapter, 0, sizeof(MAdapter)); - dprintf = no_printf; -} - /* * DIDD callback function */ @@ -66,7 +51,9 @@ static void *didd_callback(void *context, DESCRIPTOR * adapter, DBG_ERR(("cb: Change in DAdapter ? Oops ?.")); } else if (adapter->type == IDI_DIMAINT) { if (removal) { - stop_dbg(); + DbgDeregister(); + memset(&MAdapter, 0, sizeof(MAdapter)); + dprintf = no_printf; } else { memcpy(&MAdapter, adapter, sizeof(MAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; @@ -131,8 +118,6 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void) { IDI_SYNC_REQ req; - stop_dbg(); - req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY; req.didd_notify.info.handle = notify_handle; @@ -193,34 +178,63 @@ int maint_read_write(void __user *buf, int count) } break; + /* + Filter commands will ignore the ID due to fact that filtering affects + the B- channel and Audio Tap trace levels only. Also MAINT driver will + select the right trace ID by itself + */ + case DITRACE_WRITE_SELECTIVE_TRACE_FILTER: + if (!mask) { + ret = diva_set_trace_filter (1, "*"); + } else if (mask < sizeof(data)) { + if (copy_from_user(data, (char __user *)buf+12, mask)) { + ret = -EFAULT; + } else { + ret = diva_set_trace_filter ((int)mask, data); + } + } else { + ret = -EINVAL; + } + break; + + case DITRACE_READ_SELECTIVE_TRACE_FILTER: + if ((ret = diva_get_trace_filter (sizeof(data), data)) > 0) { + if (copy_to_user (buf, data, ret)) + ret = -EFAULT; + } else { + ret = -ENODEV; + } + break; + case DITRACE_READ_TRACE_ENTRY:{ diva_os_spin_lock_magic_t old_irql; word size; diva_dbg_entry_head_t *pmsg; byte *pbuf; - if ((pmsg = diva_maint_get_message(&size, &old_irql))) { + if (!(pbuf = diva_os_malloc(0, mask))) { + return (-ENOMEM); + } + + for(;;) { + if (!(pmsg = + diva_maint_get_message(&size, &old_irql))) { + break; + } if (size > mask) { diva_maint_ack_message(0, &old_irql); ret = -EINVAL; - } else { - if (!(pbuf = diva_os_malloc_tbuffer(0, size))) - { - diva_maint_ack_message(0, &old_irql); - ret = -ENOMEM; - } else { - ret = size; - memcpy(pbuf, pmsg, size); - diva_maint_ack_message(1, &old_irql); - if ((count < size) || diva_os_copy_to_user (NULL, buf, - (void *) pbuf, size)) - ret = -EFAULT; - diva_os_free_tbuffer(0, pbuf); - } + break; } - } else { - ret = 0; + ret = size; + memcpy(pbuf, pmsg, size); + diva_maint_ack_message(1, &old_irql); + if ((count < size) || + diva_os_copy_to_user (NULL, buf, (void *) pbuf, size)) + ret = -EFAULT; + break; } + diva_os_free(0, pbuf); } break; @@ -235,7 +249,7 @@ int maint_read_write(void __user *buf, int count) ret = -EINVAL; break; } - if (!(pbuf = diva_os_malloc_tbuffer(0, mask))) { + if (!(pbuf = diva_os_malloc(0, mask))) { return (-ENOMEM); } @@ -273,7 +287,7 @@ int maint_read_write(void __user *buf, int count) } else { ret = written; } - diva_os_free_tbuffer(0, pbuf); + diva_os_free(0, pbuf); } break; @@ -302,7 +316,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer, } else { while ((*buffer_length >= (64 * 1024)) && - (!(*buffer = diva_os_malloc_tbuffer(0, *buffer_length)))) { + (!(*buffer = diva_os_malloc (0, *buffer_length)))) { *buffer_length -= 1024; } @@ -314,7 +328,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer, if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) { if (!diva_dbg_mem) { - diva_os_free_tbuffer(0, *buffer); + diva_os_free (0, *buffer); } DBG_ERR(("init: maint init failed")); return (0); @@ -324,7 +338,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer, DBG_ERR(("init: failed to connect to DIDD.")); diva_maint_finit(); if (!diva_dbg_mem) { - diva_os_free_tbuffer(0, *buffer); + diva_os_free (0, *buffer); } return (0); } @@ -339,6 +353,8 @@ void DIVA_EXIT_FUNCTION mntfunc_finit(void) void *buffer; int i = 100; + DbgDeregister(); + while (diva_mnt_shutdown_xdi_adapters() && i--) { diva_os_sleep(10); } @@ -346,6 +362,9 @@ void DIVA_EXIT_FUNCTION mntfunc_finit(void) disconnect_didd(); if ((buffer = diva_maint_finit())) { - diva_os_free_tbuffer(0, buffer); + diva_os_free (0, buffer); } + + memset(&MAdapter, 0, sizeof(MAdapter)); + dprintf = no_printf; } diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c index e6016f924..f6325c0ae 100644 --- a/drivers/isdn/hardware/eicon/os_4bri.c +++ b/drivers/isdn/hardware/eicon/os_4bri.c @@ -143,7 +143,7 @@ static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a) int diva_4bri_init_card(diva_os_xdi_adapter_t * a) { int bar, i; - byte *p; + byte __iomem *p; PADAPTER_LIST_ENTRY quadro_list; diva_os_xdi_adapter_t *diva_current; diva_os_xdi_adapter_t *adapter_list[4]; @@ -424,7 +424,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a) reset contains the base address for the PLX 9054 register set */ p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); - p[PLX9054_INTCSR] = 0x00; /* disable PCI interrupts */ + WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */ DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); /* @@ -788,15 +788,15 @@ diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, a->xdi_mbox. data_length); if (a->xdi_mbox.data) { - byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); - byte *src = p; + byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); + byte __iomem *src = p; byte *dst = a->xdi_mbox.data; dword len = a->xdi_mbox.data_length; src += cmd->command_data.read_sdram.offset; while (len--) { - *dst++ = *src++; + *dst++ = READ_BYTE(src++); } DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; @@ -910,8 +910,8 @@ diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, dword address, const byte * data, dword length, dword limit) { - byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); - byte *mem = p; + byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + byte __iomem *mem = p; if (((address + length) >= limit) || !mem) { DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); @@ -922,7 +922,7 @@ diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, mem += address; while (length--) { - *mem++ = *data++; + WRITE_BYTE(mem++, *data++); } DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); @@ -933,10 +933,10 @@ static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, dword start_address, dword features) { - volatile word *signature; + volatile word __iomem *signature; int started = 0; int i; - byte *p; + byte __iomem *p; /* start adapter @@ -947,7 +947,7 @@ diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, /* wait for signature in shared memory (max. 3 seconds) */ - signature = (volatile word *) (&p[0x1E]); + signature = (volatile word __iomem *) (&p[0x1E]); for (i = 0; i < 300; ++i) { diva_os_wait(10); @@ -1011,7 +1011,7 @@ static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter) #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI int i; ADAPTER *a = &IoAdapter->a; - byte *p; + byte __iomem *p; IoAdapter->IrqCount = 0; @@ -1019,7 +1019,7 @@ static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter) return (-1); p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - p[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE); DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); /* interrupt test @@ -1031,14 +1031,14 @@ static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter) return ((IoAdapter->IrqCount > 0) ? 0 : -1); #else - dword volatile *qBriIrq; - byte *p; + dword volatile __iomem *qBriIrq; + byte __iomem *p; /* Reset on-board interrupt register */ IoAdapter->IrqCount = 0; p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); - qBriIrq = (dword volatile *) (&p[_4bri_is_rev_2_card + qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card (IoAdapter-> cardType) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); @@ -1047,7 +1047,7 @@ static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter) DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - p[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE); DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); diva_os_wait(100); diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c index e8f023d2d..4cc44a5dd 100644 --- a/drivers/isdn/hardware/eicon/os_bri.c +++ b/drivers/isdn/hardware/eicon/os_bri.c @@ -78,7 +78,7 @@ int diva_bri_init_card(diva_os_xdi_adapter_t * a) word cmd = 0, cmd_org; byte Bus, Slot; void *hdev; - byte *p; + byte __iomem *p; /* Set properties @@ -331,10 +331,11 @@ void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter) static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a) { dword serNo = 0; - byte *confIO; - word serHi, serLo, *confMem; + byte __iomem *confIO; + word serHi, serLo; + word __iomem *confMem; - confIO = (byte *) DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter); + confIO = DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter); serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF); serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF); serNo = ((dword) serHi << 16) | (dword) serLo; @@ -343,7 +344,7 @@ static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a) if ((serNo == 0) || (serNo == 0xFFFFFFFF)) { DBG_FTL(("W: BRI use BAR[0] to get card serial number")) - confMem = (word *) DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter); + confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter); serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF); serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF); serNo = (((dword) serHi) << 16) | ((dword) serLo); @@ -513,9 +514,9 @@ diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter) { - byte *addrHi, *addrLo, *ioaddr; + byte __iomem *addrHi, *addrLo, *ioaddr; dword i; - byte *Port; + byte __iomem *Port; if (!IoAdapter->port) { return (-1); @@ -602,8 +603,8 @@ static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, dword address, const byte * data, dword length) { - byte *addrHi, *addrLo, *ioaddr; - byte *Port; + byte __iomem *addrHi, *addrLo, *ioaddr; + byte __iomem *Port; if (!IoAdapter->port) { return (-1); @@ -630,9 +631,9 @@ static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, dword start_address, dword features) { - byte *Port; + byte __iomem *Port; dword i, test; - byte *addrHi, *addrLo, *ioaddr; + byte __iomem *addrHi, *addrLo, *ioaddr; int started = 0; ADAPTER *a = &IoAdapter->a; diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c index 28e9df236..8ac207f75 100644 --- a/drivers/isdn/hardware/eicon/os_pri.c +++ b/drivers/isdn/hardware/eicon/os_pri.c @@ -332,7 +332,7 @@ static int diva_pri_cleanup_adapter(diva_os_xdi_adapter_t * a) static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter) { dword i; - struct mp_load *boot; + struct mp_load __iomem *boot; if (!IoAdapter->Address || !IoAdapter->reset) { return (-1); @@ -343,7 +343,7 @@ static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter) return (-1); } - boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); WRITE_DWORD(&boot->err, 0); DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); @@ -351,7 +351,7 @@ static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter) diva_os_wait(10); - boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); i = READ_DWORD(&boot->live); diva_os_wait(10); @@ -408,8 +408,8 @@ diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter, dword address, const byte * data, dword length, dword limit) { - byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); - byte *mem = p; + byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + byte __iomem *mem = p; if (((address + length) >= limit) || !mem) { DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); @@ -419,8 +419,9 @@ diva_pri_write_sdram_block(PISDN_ADAPTER IoAdapter, } mem += address; + /* memcpy_toio(), maybe? */ while (length--) { - *mem++ = *data++; + WRITE_BYTE(mem++, *data++); } DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); @@ -433,8 +434,8 @@ diva_pri_start_adapter(PISDN_ADAPTER IoAdapter, { dword i; int started = 0; - byte *p; - struct mp_load *boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + byte __iomem *p; + struct mp_load __iomem *boot = (struct mp_load __iomem *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); ADAPTER *a = &IoAdapter->a; if (IoAdapter->Initialized) { @@ -468,7 +469,7 @@ diva_pri_start_adapter(PISDN_ADAPTER IoAdapter, } if (!started) { - byte *p = (byte *)boot; + byte __iomem *p = (byte __iomem *)boot; dword TrapId; dword debug; TrapId = READ_DWORD(&p[0x80]); @@ -492,7 +493,7 @@ diva_pri_start_adapter(PISDN_ADAPTER IoAdapter, */ IoAdapter->IrqCount = 0; p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); - WRITE_DWORD(((dword volatile *) p), (dword) ~ 0x03E00000); + WRITE_DWORD(p, (dword) ~ 0x03E00000); DIVA_OS_MEM_DETACH_CFG(IoAdapter, p); a->ReadyInt = 1; a->ram_out(a, &PR_RAM->ReadyInt, 1); @@ -729,15 +730,15 @@ diva_pri_cmd_card_proc(struct _diva_os_xdi_adapter *a, a->xdi_mbox. data_length); if (a->xdi_mbox.data) { - byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); - byte *src = p; + byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); + byte __iomem *src = p; byte *dst = a->xdi_mbox.data; dword len = a->xdi_mbox.data_length; src += cmd->command_data.read_sdram.offset; while (len--) { - *dst++ = *src++; + *dst++ = READ_BYTE(src++); } a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); @@ -764,18 +765,20 @@ static int pri_get_serial_number(diva_os_xdi_adapter_t * a) byte data[64]; int i; dword len = sizeof(data); - volatile byte *config; - volatile byte *flash; + volatile byte __iomem *config; + volatile byte __iomem *flash; + byte c; /* * First set some GT6401x config registers before accessing the BOOT-ROM */ config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); - if (!(config[0xc3c] & 0x08)) { - config[0xc3c] |= 0x08; /* Base Address enable register */ + c = READ_BYTE(&config[0xc3c]); + if (!(c & 0x08)) { + WRITE_BYTE(&config[0xc3c], c); /* Base Address enable register */ } - config[LOW_BOOTCS_DREG] = 0x00; - config[HI_BOOTCS_DREG] = 0xFF; + WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0x00); + WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF); DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); /* * Read only the last 64 bytes of manufacturing data @@ -783,13 +786,13 @@ static int pri_get_serial_number(diva_os_xdi_adapter_t * a) memset(data, '\0', len); flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter); for (i = 0; i < len; i++) { - data[i] = flash[0x8000 - len + i]; + data[i] = READ_BYTE(&flash[0x8000 - len + i]); } DIVA_OS_MEM_DETACH_PROM(&a->xdi_adapter, flash); config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); - config[LOW_BOOTCS_DREG] = 0xFC; /* Disable FLASH EPROM access */ - config[HI_BOOTCS_DREG] = 0xFF; + WRITE_BYTE(&config[LOW_BOOTCS_DREG], 0xFC); /* Disable FLASH EPROM access */ + WRITE_BYTE(&config[HI_BOOTCS_DREG], 0xFF); DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); if (memcmp(&data[48], "DIVAserverPR", 12)) { @@ -905,7 +908,7 @@ void diva_os_prepare_pri_functions(PISDN_ADAPTER IoAdapter) ** Checks presence of DSP on board */ static int -dsp_check_presence(volatile byte * addr, volatile byte * data, int dsp) +dsp_check_presence(volatile byte __iomem * addr, volatile byte __iomem * data, int dsp) { word pattern; @@ -950,8 +953,8 @@ dsp_check_presence(volatile byte * addr, volatile byte * data, int dsp) */ static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) { - byte *base; - byte *p; + byte __iomem *base; + byte __iomem *p; dword ret = 0; dword row_offset[7] = { 0x00000000, @@ -962,7 +965,9 @@ static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) 0x00000000 /* 5 - ROW 0 */ }; - byte *dsp_addr_port, *dsp_data_port, row_state; + byte __iomem *dsp_addr_port; + byte __iomem *dsp_data_port; + byte row_state; int dsp_row = 0, dsp_index, dsp_num; if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) { @@ -970,7 +975,7 @@ static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) } p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); - *(volatile byte *) p = _MP_RISC_RESET | _MP_DSP_RESET; + WRITE_BYTE(p, _MP_RISC_RESET | _MP_DSP_RESET); DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); diva_os_wait(5); @@ -997,7 +1002,7 @@ static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base); p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); - *(volatile byte *) p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; + WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2); DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); diva_os_wait(5); diff --git a/drivers/isdn/hardware/eicon/pc.h b/drivers/isdn/hardware/eicon/pc.h index a65550605..1c6945768 100644 --- a/drivers/isdn/hardware/eicon/pc.h +++ b/drivers/isdn/hardware/eicon/pc.h @@ -143,6 +143,7 @@ struct dual #define N_DATA_ACK 12 /* data ack ind for D-bit procedure */ #define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */ #define N_XON 15 /* clear RNR state */ +#define N_COMBI_IND N_XON /* combined indication */ #define N_Q_BIT 0x10 /* Q-bit for req/ind */ #define N_M_BIT 0x20 /* M-bit for req/ind */ #define N_D_BIT 0x40 /* D-bit for req/ind */ @@ -228,6 +229,10 @@ struct dual #define VSWITCH_IND 66 /* capifunctions for D-CH-switching */ #define MWI_POLL 67 /* Message Waiting Status Request fkt */ #define CALL_PEND_NOTIFY 68 /* notify capi to set new listen */ +#define DO_NOTHING 69 /* dont do somethin if you get this */ +#define INT_CT_REJ 70 /* ECT rejected internal command */ +#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete */ +#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete */ /*------------------------------------------------------------------*/ /* management service primitives */ /*------------------------------------------------------------------*/ @@ -241,6 +246,7 @@ struct dual #define MAN_INFO_IND 2 #define MAN_EVENT_IND 3 #define MAN_TRACE_IND 4 +#define MAN_COMBI_IND 9 #define MAN_ESC 0x80 /*------------------------------------------------------------------*/ /* return code coding */ @@ -265,6 +271,7 @@ struct dual /*------------------------------------------------------------------*/ #define SHIFT 0x90 /* codeset shift */ #define MORE 0xa0 /* more data */ +#define SDNCMPL 0xa1 /* sending complete */ #define CL 0xb0 /* congestion level */ /* codeset 0 */ #define SMSG 0x00 /* segmented message */ @@ -288,6 +295,8 @@ struct dual #define RDX 0x73 /* redirecting number extended */ #define RDN 0x74 /* redirecting number */ #define RIN 0x76 /* redirection number */ +#define IUP 0x76 /* VN6 rerouter->PCS (codeset 6) */ +#define IPU 0x77 /* VN6 PCS->rerouter (codeset 6) */ #define RI 0x79 /* restart indicator */ #define MIE 0x7a /* management info element */ #define LLC 0x7c /* low layer compatibility */ @@ -296,6 +305,8 @@ struct dual #define ESC 0x7f /* escape extension */ #define DLC 0x20 /* data link layer configuration */ #define NLC 0x21 /* network layer configuration */ +#define REDIRECT_IE 0x22 /* redirection request/indication data */ +#define REDIRECT_NET_IE 0x23 /* redirection network override data */ /* codeset 6 */ #define SIN 0x01 /* service indicator */ #define CIF 0x02 /* charging information */ @@ -306,6 +317,7 @@ struct dual /*------------------------------------------------------------------*/ #define MSGTYPEIE 0x7a /* Messagetype info element */ #define CRIE 0x7b /* INFO info element */ +#define CODESET6IE 0xec /* Tunnel for Codeset 6 IEs */ #define VSWITCHIE 0xed /* VSwitch info element */ #define SSEXTIE 0xee /* Supplem. Service info element */ #define PROFILEIE 0xef /* Profile info element */ @@ -344,6 +356,13 @@ struct dual #define CCBS_REQUEST 0x32 #define CCBS_DEACTIVATE 0x33 #define CCBS_INTERROGATE 0x34 +#define CCBS_STATUS 0x35 +#define CCBS_ERASE 0x36 +#define CCBS_B_FREE 0x37 +#define CCNR_INFO_RETAIN 0x38 +#define CCBS_REMOTE_USER_FREE 0x39 +#define CCNR_REQUEST 0x3a +#define CCNR_INTERROGATE 0x3b #define GET_SUPPORTED_SERVICES 0xff #define DIVERSION_PROCEDURE_CFU 0x70 #define DIVERSION_PROCEDURE_CFB 0x71 @@ -362,6 +381,7 @@ struct dual #define SMASK_3PTY 0x00000008 #define SMASK_CALL_FORWARDING 0x00000010 #define SMASK_CALL_DEFLECTION 0x00000020 +#define SMASK_MCID 0x00000040 #define SMASK_CCBS 0x00000080 #define SMASK_MWI 0x00000100 #define SMASK_CCNR 0x00000200 @@ -406,6 +426,8 @@ struct dual #define RTPL2_IN 13 /* RTP layer-2 protocol, incomming */ #define RTPL2 14 /* RTP layer-2 protocol */ #define V120_V42BIS 15 /* V.120 asynchronous mode supporting V.42bis compression */ +#define LISTENER 27 /* Layer 2 to listen line */ +#define MTP2 28 /* MTP2 Layer 2 */ #define PIAFS_CRC 29 /* PIAFS Layer 2 with CRC calculation at L2 */ /* ------------------------------------------------------ PIAFS DLC DEFINITIONS @@ -506,6 +528,22 @@ Byte | 8 7 6 5 4 3 2 1 | | | data transfer. | +---------------------+------+-----------------------------------------+ */ +/* ------------------------------------------------------ + LISTENER DLC DEFINITIONS + ------------------------------------------------------ */ +#define LISTENER_FEATURE_MASK_CUMMULATIVE 0x0001 +/* ------------------------------------------------------ + LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS + ------------------------------------------------------ */ +#define META_CODE_LL_UDATA_RX 0x01 +#define META_CODE_LL_UDATA_TX 0x02 +#define META_CODE_LL_DATA_RX 0x03 +#define META_CODE_LL_DATA_TX 0x04 +#define META_CODE_LL_MDATA_RX 0x05 +#define META_CODE_LL_MDATA_TX 0x06 +#define META_CODE_EMPTY 0x10 +#define META_CODE_LOST_FRAMES 0x11 +#define META_FLAG_TRUNCATED 0x0001 /*------------------------------------------------------------------*/ /* CAPI-like profile to indicate features on LAW_REQ */ /*------------------------------------------------------------------*/ @@ -577,6 +615,14 @@ Byte | 8 7 6 5 4 3 2 1 #define MANUFACTURER_FEATURE_DMACONNECT 0x04000000L #define MANUFACTURER_FEATURE_AUDIO_TAP 0x08000000L #define MANUFACTURER_FEATURE_FAX_NONSTANDARD 0x10000000L +#define MANUFACTURER_FEATURE_SS7 0x20000000L +#define MANUFACTURER_FEATURE_MADAPTER 0x40000000L +#define MANUFACTURER_FEATURE_MEASURE 0x80000000L +#define MANUFACTURER_FEATURE2_LISTENING 0x00000001L +#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L +#define MANUFACTURER_FEATURE2_GENERIC_TONE 0x00000004L +#define MANUFACTURER_FEATURE2_COLOR_FAX 0x00000008L +#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L #define RTP_PRIM_PAYLOAD_PCMU_8000 0 #define RTP_PRIM_PAYLOAD_1016_8000 1 #define RTP_PRIM_PAYLOAD_G726_32_8000 2 @@ -624,6 +670,15 @@ Byte | 8 7 6 5 4 3 2 1 #define VSINVOKEID 4 #define VSCLMRKS 5 #define VSTBCTIDENT 6 +#define VSETSILINKID 7 +#define VSSAMECONTROLLER 8 +/* Errorcodes for VSETSILINKID begin */ +#define VSETSILINKIDRRWC 1 +#define VSETSILINKIDREJECT 2 +#define VSETSILINKIDTIMEOUT 3 +#define VSETSILINKIDFAILCOUNT 4 +#define VSETSILINKIDERROR 5 +/* Errorcodes for VSETSILINKID end */ /* -----------------------------------------------------------** ** The PROTOCOL_FEATURE_STRING in feature.h (included ** ** in prstart.sx and astart.sx) defines capabilities and ** @@ -647,5 +702,37 @@ Byte | 8 7 6 5 4 3 2 1 #define PROTCAP_FREE13 0x2000 /* not used */ #define PROTCAP_FREE14 0x4000 /* not used */ #define PROTCAP_EXTENSION 0x8000 /* used for future extentions */ +/* -----------------------------------------------------------* */ +/* Onhook data transmission ETS30065901 */ +/* Message Type */ +/*#define RESERVED4 0x4*/ +#define CALL_SETUP 0x80 +#define MESSAGE_WAITING_INDICATOR 0x82 +/*#define RESERVED84 0x84*/ +/*#define RESERVED85 0x85*/ +#define ADVICE_OF_CHARGE 0x86 +/*1111 0001 +to +1111 1111 +F1H - Reserved for network operator use +to +FFH*/ +/* Parameter Types */ +#define DATE_AND_TIME 1 +#define CLI_PARAMETER_TYPE 2 +#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE 3 +#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE 4 +#define NAME_PARAMETER_TYPE 7 +#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8 +#define VISUAL_INDICATOR_PARAMETER_TYPE 0xb +#define COMPLEMENTARY_CLI_PARAMETER_TYPE 0x10 +#define CALL_TYPE_PARAMETER_TYPE 0x11 +#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE 0x12 +#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE 0x13 +#define FORWARDED_CALL_TYPE_PARAMETER_TYPE 0x15 +#define TYPE_OF_CALLING_USER_PARAMETER_TYPE 0x16 +#define REDIRECTING_NUMBER_PARAMETER_TYPE 0x1a +#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE 0xe0 +/* -----------------------------------------------------------* */ #else #endif /* PC_H_INCLUDED } */ diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h index 31299feb7..3e279e116 100644 --- a/drivers/isdn/hardware/eicon/platform.h +++ b/drivers/isdn/hardware/eicon/platform.h @@ -1,4 +1,4 @@ -/* $Id: platform.h,v 1.37.4.1 2004/07/28 14:47:21 armin Exp $ +/* $Id: platform.h,v 1.37.4.2 2004/08/28 20:03:53 armin Exp $ * * platform.h * @@ -235,12 +235,12 @@ int diva_os_register_io_port (void *adapter, int register, unsigned long port, /* ** I/O port access abstraction */ -byte inpp (void*); -word inppw (void*); -void inppw_buffer (void*, void*, int); -void outppw (void*, word); -void outppw_buffer (void* , void*, int); -void outpp (void*, word); +byte inpp (void __iomem *); +word inppw (void __iomem *); +void inppw_buffer (void __iomem *, void*, int); +void outppw (void __iomem *, word); +void outppw_buffer (void __iomem * , void*, int); +void outpp (void __iomem *, word); /* ** IRQ @@ -269,20 +269,6 @@ static __inline__ void diva_os_leave_spin_lock (diva_os_spin_lock_t* a, \ diva_os_spin_lock_magic_t* old_irql, \ void* dbg) { spin_unlock_bh(a); } -static __inline__ void diva_os_enter_spin_lock_hard (diva_os_spin_lock_t* a, \ - diva_os_spin_lock_magic_t* old_irql, \ - void* dbg) { \ - unsigned long flags; \ - spin_lock_irqsave (a, flags); \ - *old_irql = (diva_os_spin_lock_magic_t)flags; \ -} -static __inline__ void diva_os_leave_spin_lock_hard (diva_os_spin_lock_t* a, \ - diva_os_spin_lock_magic_t* old_irql, \ - void* dbg) { \ - unsigned long flags = (unsigned long)*old_irql; \ - spin_unlock_irqrestore (a, flags); \ -} - #define diva_os_destroy_spin_lock(a,b) do { } while(0) /* @@ -347,12 +333,40 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv) #define DIVA_IDI_RX_DMA 1 +/* +** endian macros +** +** If only... In some cases we did use them for endianness conversion; +** unfortunately, other uses were real iomem accesses. +*/ +#define READ_BYTE(addr) readb(addr) #define READ_WORD(addr) readw(addr) #define READ_DWORD(addr) readl(addr) +#define WRITE_BYTE(addr,v) writeb(v,addr) #define WRITE_WORD(addr,v) writew(v,addr) #define WRITE_DWORD(addr,v) writel(v,addr) +static inline __u16 GET_WORD(void *addr) +{ + return le16_to_cpu(*(__le16 *)addr); +} +static inline __u32 GET_DWORD(void *addr) +{ + return le32_to_cpu(*(__le32 *)addr); +} +static inline void PUT_WORD(void *addr, __u16 v) +{ + *(__le16 *)addr = cpu_to_le16(v); +} +static inline void PUT_DWORD(void *addr, __u32 v) +{ + *(__le32 *)addr = cpu_to_le32(v); +} + +/* +** 32/64 bit macors +*/ #ifdef BITS_PER_LONG #if BITS_PER_LONG > 32 #define PLATFORM_GT_32BIT @@ -360,8 +374,23 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv) #endif #endif +/* +** undef os definitions of macros we use +*/ #undef ID_MASK #undef N_DATA #undef ADDR +/* +** dump file +*/ +#define diva_os_dump_file_t char +#define diva_os_board_trace_t char +#define diva_os_dump_file(__x__) do { } while(0) + +/* +** size of internal arrays +*/ +#define MAX_DESCRIPTORS 64 + #endif /* __PLATFORM_H__ */ diff --git a/drivers/isdn/hardware/eicon/s_4bri.c b/drivers/isdn/hardware/eicon/s_4bri.c index b869651da..62e305535 100644 --- a/drivers/isdn/hardware/eicon/s_4bri.c +++ b/drivers/isdn/hardware/eicon/s_4bri.c @@ -45,7 +45,7 @@ Recovery XLOG from QBRI Card -------------------------------------------------------------------------- */ static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) { - byte *base ; + byte __iomem *base ; word *Xlog ; dword regs[4], TrapID, offset, size ; Xdesc xlogDesc ; @@ -66,10 +66,10 @@ static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) { IoAdapter->trapped = 1 ; } - regs[0] = READ_DWORD((&base + offset) + 0x70); - regs[1] = READ_DWORD((&base + offset) + 0x74); - regs[2] = READ_DWORD((&base + offset) + 0x78); - regs[3] = READ_DWORD((&base + offset) + 0x7c); + regs[0] = READ_DWORD((base + offset) + 0x70); + regs[1] = READ_DWORD((base + offset) + 0x74); + regs[2] = READ_DWORD((base + offset) + 0x78); + regs[3] = READ_DWORD((base + offset) + 0x7c); regs[0] &= IoAdapter->MemorySize - 1 ; if ( (regs[0] >= offset) @@ -83,7 +83,7 @@ static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) { size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ; if ( size > MAX_XLOG_SIZE ) size = MAX_XLOG_SIZE ; - memcpy (Xlog, &base[regs[0]], size) ; + memcpy_fromio (Xlog, &base[regs[0]], size) ; xlogDesc.buf = Xlog ; xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ; xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ; @@ -98,11 +98,11 @@ static void qBri_cpu_trapped (PISDN_ADAPTER IoAdapter) { Reset QBRI Hardware -------------------------------------------------------------------------- */ static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) { - word volatile *qBriReset ; - byte volatile *qBriCntrl ; - byte volatile *p ; + word volatile __iomem *qBriReset ; + byte volatile __iomem *qBriCntrl ; + byte volatile __iomem *p ; - qBriReset = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); + qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ; diva_os_wait (1) ; WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ; @@ -126,10 +126,10 @@ static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) { Start Card CPU -------------------------------------------------------------------------- */ void start_qBri_hardware (PISDN_ADAPTER IoAdapter) { - byte volatile *qBriReset ; - byte volatile *p ; + byte volatile __iomem *qBriReset ; + byte volatile __iomem *p ; - p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)]; WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK) ; diva_os_wait (2) ; @@ -144,10 +144,10 @@ void start_qBri_hardware (PISDN_ADAPTER IoAdapter) { Stop Card CPU -------------------------------------------------------------------------- */ static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) { - byte volatile *p ; - dword volatile *qBriReset ; - dword volatile *qBriIrq ; - dword volatile *qBriIsacDspReset ; + byte volatile __iomem *p ; + dword volatile __iomem *qBriReset ; + dword volatile __iomem *qBriIrq ; + dword volatile __iomem *qBriIsacDspReset ; int rev2 = DIVA_4BRI_REVISION(IoAdapter); int reset_offset = rev2 ? (MQ2_BREG_RISC) : (MQ_BREG_RISC); int irq_offset = rev2 ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST); @@ -155,9 +155,9 @@ static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) { if ( IoAdapter->ControllerNumber > 0 ) return ; - p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); - qBriReset = (dword volatile *)&p[reset_offset]; - qBriIsacDspReset = (dword volatile *)&p[hw_offset]; + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriReset = (dword volatile __iomem *)&p[reset_offset]; + qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset]; /* * clear interrupt line (reset Local Interrupt Test Register) */ @@ -165,12 +165,12 @@ static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) { WRITE_DWORD(qBriIsacDspReset, 0) ; DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); - p = (byte volatile *)DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - p[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */ DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); - p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); - qBriIrq = (dword volatile *)&p[irq_offset]; + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriIrq = (dword volatile __iomem *)&p[irq_offset]; WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); @@ -276,7 +276,7 @@ int qBri_FPGA_download (PISDN_ADAPTER IoAdapter) { int bit ; byte *File ; dword code, FileLength ; - word volatile *addr = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); + word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); word val, baseval = FPGA_CS | FPGA_PROG ; @@ -864,17 +864,17 @@ static int load_qBri_hardware (PISDN_ADAPTER IoAdapter) { Card ISR -------------------------------------------------------------------------- */ static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) { - dword volatile *qBriIrq ; + dword volatile __iomem *qBriIrq ; PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList ; word i ; int serviced = 0 ; - byte *p; + byte __iomem *p; p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - if ( !(p[PLX9054_INTCSR] & 0x80) ) { + if ( !(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80) ) { DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); return (0) ; } @@ -884,7 +884,7 @@ static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) { * clear interrupt line (reset Local Interrupt Test Register) */ p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); - qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); + qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); @@ -908,8 +908,8 @@ static int qBri_ISR (struct _ISDN_ADAPTER* IoAdapter) { Does disable the interrupt on the card -------------------------------------------------------------------------- */ static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) { - dword volatile *qBriIrq ; - byte *p; + dword volatile __iomem *qBriIrq ; + byte __iomem *p; if ( IoAdapter->ControllerNumber > 0 ) return ; @@ -917,11 +917,11 @@ static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) { * clear interrupt line (reset Local Interrupt Test Register) */ p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - p[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */ DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); - qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); + qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } diff --git a/drivers/isdn/hardware/eicon/s_bri.c b/drivers/isdn/hardware/eicon/s_bri.c index 7b5495f46..693316ce0 100644 --- a/drivers/isdn/hardware/eicon/s_bri.c +++ b/drivers/isdn/hardware/eicon/s_bri.c @@ -41,11 +41,11 @@ Investigate card state, recovery trace buffer -------------------------------------------------------------------------- */ static void bri_cpu_trapped (PISDN_ADAPTER IoAdapter) { - byte *addrHi, *addrLo, *ioaddr ; + byte __iomem *addrHi, *addrLo, *ioaddr ; word *Xlog ; dword regs[4], i, size ; Xdesc xlogDesc ; - byte *Port; + byte __iomem *Port; /* * first read pointers and trap frame */ @@ -61,15 +61,15 @@ static void bri_cpu_trapped (PISDN_ADAPTER IoAdapter) { /* * check for trapped MIPS 3xxx CPU, dump only exception frame */ - if ( READ_DWORD(&Xlog[0x80 / sizeof(Xlog[0])]) == 0x99999999 ) + if ( GET_DWORD(&Xlog[0x80 / sizeof(Xlog[0])]) == 0x99999999 ) { dump_trap_frame (IoAdapter, &((byte *)Xlog)[0x90]) ; IoAdapter->trapped = 1 ; } - regs[0] = READ_DWORD(&((byte *)Xlog)[0x70]); - regs[1] = READ_DWORD(&((byte *)Xlog)[0x74]); - regs[2] = READ_DWORD(&((byte *)Xlog)[0x78]); - regs[3] = READ_DWORD(&((byte *)Xlog)[0x7c]); + regs[0] = GET_DWORD(&((byte *)Xlog)[0x70]); + regs[1] = GET_DWORD(&((byte *)Xlog)[0x74]); + regs[2] = GET_DWORD(&((byte *)Xlog)[0x78]); + regs[3] = GET_DWORD(&((byte *)Xlog)[0x7c]); outpp (addrHi, (regs[1] >> 16) & 0x7F) ; outppw (addrLo, regs[1] & 0xFFFF) ; xlogDesc.cnt = inppw(ioaddr) ; @@ -102,7 +102,7 @@ static void bri_cpu_trapped (PISDN_ADAPTER IoAdapter) { Reset hardware --------------------------------------------------------------------- */ static void reset_bri_hardware (PISDN_ADAPTER IoAdapter) { - byte *p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + byte __iomem *p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); outpp (p, 0x00) ; DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } @@ -110,7 +110,7 @@ static void reset_bri_hardware (PISDN_ADAPTER IoAdapter) { Halt system --------------------------------------------------------------------- */ static void stop_bri_hardware (PISDN_ADAPTER IoAdapter) { - byte *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + byte __iomem *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); if (p) { outpp (p, 0x00) ; /* disable interrupts ! */ } @@ -471,7 +471,7 @@ static int load_bri_hardware (PISDN_ADAPTER IoAdapter) { #endif /* } */ /******************************************************************************/ static int bri_ISR (struct _ISDN_ADAPTER* IoAdapter) { - byte *p; + byte __iomem *p; p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); if ( !(inpp (p) & 0x01) ) { @@ -493,7 +493,7 @@ static int bri_ISR (struct _ISDN_ADAPTER* IoAdapter) { Disable IRQ in the card hardware -------------------------------------------------------------------------- */ static void disable_bri_interrupt (PISDN_ADAPTER IoAdapter) { - byte *p; + byte __iomem *p; p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); if ( p ) { diff --git a/drivers/isdn/hardware/eicon/s_pri.c b/drivers/isdn/hardware/eicon/s_pri.c index e1f13e05e..bdc031b71 100644 --- a/drivers/isdn/hardware/eicon/s_pri.c +++ b/drivers/isdn/hardware/eicon/s_pri.c @@ -47,7 +47,7 @@ static dword pri_ram_offset (ADAPTER* a) { Recovery XLOG buffer from the card ------------------------------------------------------------------------- */ static void pri_cpu_trapped (PISDN_ADAPTER IoAdapter) { - byte *base ; + byte __iomem *base ; word *Xlog ; dword regs[4], TrapID, size ; Xdesc xlogDesc ; @@ -75,7 +75,7 @@ static void pri_cpu_trapped (PISDN_ADAPTER IoAdapter) { size = IoAdapter->MemorySize - regs[0] ; if ( size > MAX_XLOG_SIZE ) size = MAX_XLOG_SIZE ; - memcpy (Xlog, &base[regs[0]], size) ; + memcpy_fromio(Xlog, &base[regs[0]], size) ; xlogDesc.buf = Xlog ; xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]) ; xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]) ; @@ -89,10 +89,10 @@ static void pri_cpu_trapped (PISDN_ADAPTER IoAdapter) { Hardware reset of PRI card ------------------------------------------------------------------------- */ static void reset_pri_hardware (PISDN_ADAPTER IoAdapter) { - byte *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; + byte __iomem *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2); diva_os_wait (50) ; - *p = 0x00 ; + WRITE_BYTE(p, 0x00); diva_os_wait (50) ; DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); } @@ -101,10 +101,10 @@ static void reset_pri_hardware (PISDN_ADAPTER IoAdapter) { ------------------------------------------------------------------------- */ static void stop_pri_hardware (PISDN_ADAPTER IoAdapter) { dword i; - byte *p; - dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); - cfgReg[3] = 0x00000000 ; - cfgReg[1] = 0x00000000 ; + byte __iomem *p; + dword volatile __iomem *cfgReg = (void __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); + WRITE_DWORD(&cfgReg[3], 0); + WRITE_DWORD(&cfgReg[1], 0); DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); IoAdapter->a.ram_out (&IoAdapter->a, &RAM->SWReg, SWREG_HALT_CPU) ; i = 0 ; @@ -114,12 +114,12 @@ static void stop_pri_hardware (PISDN_ADAPTER IoAdapter) { i++ ; } DBG_TRC(("%s: PRI stopped (%d)", IoAdapter->Name, i)) - cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); + cfgReg = (void __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); WRITE_DWORD(&cfgReg[0],((dword)(~0x03E00000))); DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); diva_os_wait (1) ; p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; + WRITE_BYTE(p, _MP_RISC_RESET | _MP_LED1 | _MP_LED2); DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); } #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */ @@ -491,15 +491,15 @@ static int load_pri_hardware (PISDN_ADAPTER IoAdapter) { PRI Adapter interrupt Service Routine -------------------------------------------------------------------------- */ static int pri_ISR (struct _ISDN_ADAPTER* IoAdapter) { - byte *cfg = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); - if ( !((READ_DWORD((dword *)cfg)) & 0x80000000) ) { + byte __iomem *cfg = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); + if ( !(READ_DWORD(cfg) & 0x80000000) ) { DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg); return (0) ; } /* clear interrupt line */ - WRITE_DWORD(((dword *)cfg), (dword)~0x03E00000) ; + WRITE_DWORD(cfg, (dword)~0x03E00000) ; DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg); IoAdapter->IrqCount++ ; if ( IoAdapter->Initialized ) @@ -512,9 +512,9 @@ static int pri_ISR (struct _ISDN_ADAPTER* IoAdapter) { Disable interrupt in the card hardware ------------------------------------------------------------------------- */ static void disable_pri_interrupt (PISDN_ADAPTER IoAdapter) { - dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter) ; - cfgReg[3] = 0x00000000 ; - cfgReg[1] = 0x00000000 ; + dword volatile __iomem *cfgReg = (dword volatile __iomem *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter) ; + WRITE_DWORD(&cfgReg[3], 0); + WRITE_DWORD(&cfgReg[1], 0); WRITE_DWORD(&cfgReg[0], (dword)(~0x03E00000)) ; DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); } diff --git a/drivers/isdn/hardware/eicon/xdi_adapter.h b/drivers/isdn/hardware/eicon/xdi_adapter.h index e7d9bbc42..a3bd163af 100644 --- a/drivers/isdn/hardware/eicon/xdi_adapter.h +++ b/drivers/isdn/hardware/eicon/xdi_adapter.h @@ -12,7 +12,7 @@ typedef struct _divas_pci_card_resources { void *hdev; dword bar[8]; /* contains context of appropriate BAR Register */ - void *addr[8]; /* same bar, but mapped into memory */ + void __iomem *addr[8]; /* same bar, but mapped into memory */ dword length[8]; /* bar length */ int mem_type_id[MAX_MEM_TYPE]; unsigned int qoffset; diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index 779122330..c4f861a5d 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -316,14 +316,14 @@ Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) QuickHex(t, cs->rcvbuf, cs->rcvidx); debugl1(cs, cs->dlog); } - /* moves recieved data in sk-buffer */ + /* moves received data in sk-buffer */ memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); skb_queue_tail(&cs->rq, skb); } } } - /* throw damaged packets away, reset recieve-buffer, indicate RX */ + /* throw damaged packets away, reset receive-buffer, indicate RX */ ptr = cs->rcvbuf; cs->rcvidx = 0; schedule_event(cs, D_RCVBUFREADY); diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 235f28a46..6fcb2cf7b 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -752,70 +752,70 @@ setup_avm_pcipnp(struct IsdnCard *card) cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; cs->subtyp = AVM_FRITZ_PNP; - } else { + goto ready; + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_dev *pnp_avm_d = NULL; - if ((pnp_avm_c = pnp_find_card( + if (isapnp_present()) { + struct pnp_dev *pnp_avm_d = NULL; + if ((pnp_avm_c = pnp_find_card( + ISAPNP_VENDOR('A', 'V', 'M'), + ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { + if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { - if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, - ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { - int err; - - pnp_disable_dev(pnp_avm_d); - err = pnp_activate_dev(pnp_avm_d); - if (err<0) { - printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", - __FUNCTION__, err); - return(0); - } - cs->hw.avm.cfg_reg = - pnp_port_start(pnp_avm_d, 0); - cs->irq = pnp_irq(pnp_avm_d, 0); - if (!cs->irq) { - printk(KERN_ERR "FritzPnP:No IRQ\n"); - return(0); - } - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPnP:No IO address\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PNP; - goto ready; + ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { + int err; + + pnp_disable_dev(pnp_avm_d); + err = pnp_activate_dev(pnp_avm_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + cs->hw.avm.cfg_reg = + pnp_port_start(pnp_avm_d, 0); + cs->irq = pnp_irq(pnp_avm_d, 0); + if (!cs->irq) { + printk(KERN_ERR "FritzPnP:No IRQ\n"); + return(0); } + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPnP:No IO address\n"); + return(0); + } + cs->subtyp = AVM_FRITZ_PNP; + goto ready; } - } else { - printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } + } else { + printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); + } #endif #ifdef CONFIG_PCI - if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, - PCI_DEVICE_ID_AVM_A1, dev_avm))) { - cs->irq = dev_avm->irq; - if (!cs->irq) { - printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); - return(0); - } - if (pci_enable_device(dev_avm)) - return(0); - cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - } else { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, + PCI_DEVICE_ID_AVM_A1, dev_avm))) { + if (pci_enable_device(dev_avm)) + return(0); + cs->irq = dev_avm->irq; + if (!cs->irq) { + printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); return(0); } - cs->irq_flags |= SA_SHIRQ; + cs->subtyp = AVM_FRITZ_PCI; + } else { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; #else - printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); - return (0); + printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ - } ready: cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; if (!request_region(cs->hw.avm.cfg_reg, 32, diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index f6a21dffa..f410f628a 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c @@ -265,7 +265,7 @@ setup_bkm_a4t(struct IsdnCard *card) char tmp[64]; u_int pci_memaddr = 0, found = 0; I20_REGISTER_FILE *pI20_Regs; -#if CONFIG_PCI +#ifdef CONFIG_PCI #endif strcpy(tmp, bkm_a4t_revision); @@ -275,7 +275,7 @@ setup_bkm_a4t(struct IsdnCard *card) } else return (0); -#if CONFIG_PCI +#ifdef CONFIG_PCI while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { u16 sub_sys; diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index 0c32d3700..94bb83ce7 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -21,7 +21,7 @@ #include #include "bkm_ax.h" -#if CONFIG_PCI +#ifdef CONFIG_PCI #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ @@ -285,7 +285,7 @@ static u_char pci_irq __initdata = 0; int __init setup_sct_quadro(struct IsdnCard *card) { -#if CONFIG_PCI +#ifdef CONFIG_PCI struct IsdnCardState *cs = card->cs; char tmp[64]; u_char pci_rev_id; diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 26bb71d96..15b80c844 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -843,9 +843,8 @@ static int init_card(struct IsdnCardState *cs) } while (cnt) { cs->cardmsg(cs, CARD_INIT, NULL); - set_current_state(TASK_UNINTERRUPTIBLE); /* Timeout 10ms */ - schedule_timeout((10 * HZ) / 1000); + msleep(10); printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, kstat_irqs(cs->irq)); if (kstat_irqs(cs->irq) == irq_cnt) { diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 2b54e7d6f..394d481e0 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1027,7 +1027,7 @@ setup_diva(struct IsdnCard *card) } } #endif -#if CONFIG_PCI +#ifdef CONFIG_PCI cs->subtyp = 0; if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index b33678129..21271465b 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -691,8 +691,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); byteout(cs->hw.elsa.timer, 0); spin_unlock_irqrestore(&cs->lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((110*HZ)/1000); + msleep(110); spin_lock_irqsave(&cs->lock, flags); cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); @@ -1022,7 +1021,7 @@ setup_elsa(struct IsdnCard *card) cs->hw.elsa.base, cs->irq); } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { -#if CONFIG_PCI +#ifdef CONFIG_PCI cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c index a7acf9bd6..1cc4d11e0 100644 --- a/drivers/isdn/hisax/enternow_pci.c +++ b/drivers/isdn/hisax/enternow_pci.c @@ -299,7 +299,7 @@ setup_enternow_pci(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; char tmp[64]; -#if CONFIG_PCI +#ifdef CONFIG_PCI #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index 0d5931798..24a05a43f 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -634,7 +634,7 @@ setup_gazel(struct IsdnCard *card) return (0); } else { -#if CONFIG_PCI +#ifdef CONFIG_PCI if (setup_gazelpci(cs)) return (0); #else diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 20042fda8..c2db52696 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -65,7 +65,7 @@ static const PCI_ENTRY id_list[] = }; -#if CONFIG_PCI +#ifdef CONFIG_PCI /******************************************/ /* free hardware resources used by driver */ @@ -1619,8 +1619,7 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) inithfcpci(cs); reset_hfcpci(cs); spin_unlock_irqrestore(&cs->lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + msleep(80); /* Timeout 80ms */ /* now switch timer interrupt off */ spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; @@ -1655,7 +1654,7 @@ setup_hfcpci(struct IsdnCard *card) #endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); -#if CONFIG_PCI +#ifdef CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 07a07aab7..685fcc2d7 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -314,8 +314,7 @@ release_io_hfcsx(struct IsdnCardState *cs) cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + msleep(30); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ del_timer(&cs->hw.hfcsx.timer); release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ @@ -1367,8 +1366,7 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) spin_lock_irqsave(&cs->lock, flags); inithfcsx(cs); spin_unlock_irqrestore(&cs->lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + msleep(80); /* Timeout 80ms */ /* now switch timer interrupt off */ spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index ea8da9970..6fc55fea1 100644 --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -125,8 +125,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) init2bds0(cs); spin_unlock_irqrestore(&cs->lock, flags); delay = (80*HZ)/1000 +1; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80*HZ)/1000); + msleep(80); spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcD.ctmt |= HFCD_TIM800; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 221d3d72f..dc5791728 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -580,7 +580,7 @@ struct teles3_hw { struct teles0_hw { unsigned int cfg_reg; - unsigned long membase; + void __iomem *membase; unsigned long phymem; }; @@ -751,8 +751,8 @@ struct hfcD_hw { struct isurf_hw { unsigned int reset; unsigned long phymem; - unsigned long isac; - unsigned long isar; + void __iomem *isac; + void __iomem *isar; struct isar_reg isar_r; }; diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index 98c408e3f..987d441c9 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -996,28 +996,18 @@ static struct pci_driver fcpci_driver = { static int __init hisax_fcpcipnp_init(void) { - int retval, pci_nr_found; + int retval; printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); retval = pci_register_driver(&fcpci_driver); - if (retval < 0) + if (retval) goto out; - pci_nr_found = retval; - retval = 0; - #ifdef __ISAPNP__ retval = pnp_register_driver(&fcpnp_driver); if (retval < 0) goto out_unregister_pci; #endif - -#if !defined(CONFIG_HOTPLUG) || defined(MODULE) - if (pci_nr_found + retval == 0) { - retval = -ENODEV; - goto out_unregister_isapnp; - } -#endif return 0; #if !defined(CONFIG_HOTPLUG) || defined(MODULE) diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c index c2759f7ee..af5171da7 100644 --- a/drivers/isdn/hisax/isurf.c +++ b/drivers/isdn/hisax/isurf.c @@ -126,7 +126,7 @@ void release_io_isurf(struct IsdnCardState *cs) { release_region(cs->hw.isurf.reset, 1); - iounmap((unsigned char *)cs->hw.isurf.isar); + iounmap(cs->hw.isurf.isar); release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); } @@ -272,8 +272,7 @@ setup_isurf(struct IsdnCard *card) release_region(cs->hw.isurf.reset, 1); return (0); } - cs->hw.isurf.isar = - (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); + cs->hw.isurf.isar = ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index 88cce430c..cf77d8360 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -309,7 +309,7 @@ setup_niccy(struct IsdnCard *card) return (0); } } else { -#if CONFIG_PCI +#ifdef CONFIG_PCI u_int pci_ioaddr; cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index 8b5822c42..fd664697f 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -167,7 +167,7 @@ setup_netjet_s(struct IsdnCard *card) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); -#if CONFIG_PCI +#ifdef CONFIG_PCI for ( ;; ) { diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index efb5d8fbf..3d6441e96 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c @@ -137,7 +137,7 @@ setup_netjet_u(struct IsdnCard *card) int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; -#if CONFIG_PCI +#ifdef CONFIG_PCI #endif #ifdef __BIG_ENDIAN #error "not running on big endian machines now" @@ -148,7 +148,7 @@ setup_netjet_u(struct IsdnCard *card) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); -#if CONFIG_PCI +#ifdef CONFIG_PCI for ( ;; ) { diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 863bfa50b..3393370ce 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -618,7 +618,7 @@ setup_sedlbauer(struct IsdnCard *card) } #endif /* Probe for Sedlbauer speed pci */ -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { if (pci_enable_device(dev_sedl)) diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 04f9c5ce2..478b1a17b 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -143,9 +143,6 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs) if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) { /* Special case handling for pipe reset */ le16_to_cpus(&ctrl_msg->dr.wIndex); - usb_endpoint_running(adapter->usb_dev, - ctrl_msg->dr.wIndex & ~USB_DIR_IN, - (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0); /* toggle is reset on clear */ usb_settoggle(adapter->usb_dev, diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c index d7ca3423d..5ec5ec3e1 100644 --- a/drivers/isdn/hisax/teles0.c +++ b/drivers/isdn/hisax/teles0.c @@ -30,65 +30,65 @@ const char *teles0_revision = "$Revision: 2.15.2.4 $"; #define bytein(addr) inb(addr) static inline u_char -readisac(unsigned long adr, u_char off) +readisac(void __iomem *adr, u_char off) { return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off); } static inline void -writeisac(unsigned long adr, u_char off, u_char data) +writeisac(void __iomem *adr, u_char off, u_char data) { writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb(); } static inline u_char -readhscx(unsigned long adr, int hscx, u_char off) +readhscx(void __iomem *adr, int hscx, u_char off) { return readb(adr + (hscx ? 0x1c0 : 0x180) + ((off & 1) ? 0x1ff : 0) + off); } static inline void -writehscx(unsigned long adr, int hscx, u_char off, u_char data) +writehscx(void __iomem *adr, int hscx, u_char off, u_char data) { writeb(data, adr + (hscx ? 0x1c0 : 0x180) + ((off & 1) ? 0x1ff : 0) + off); mb(); } static inline void -read_fifo_isac(unsigned long adr, u_char * data, int size) +read_fifo_isac(void __iomem *adr, u_char * data, int size) { register int i; - register u_char *ad = (u_char *)adr + 0x100; + register u_char __iomem *ad = adr + 0x100; for (i = 0; i < size; i++) data[i] = readb(ad); } static inline void -write_fifo_isac(unsigned long adr, u_char * data, int size) +write_fifo_isac(void __iomem *adr, u_char * data, int size) { register int i; - register u_char *ad = (u_char *)adr + 0x100; + register u_char __iomem *ad = adr + 0x100; for (i = 0; i < size; i++) { writeb(data[i], ad); mb(); } } static inline void -read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) { register int i; - register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); + register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180); for (i = 0; i < size; i++) data[i] = readb(ad); } static inline void -write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) { int i; - register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); + register u_char __iomem *ad = adr + (hscx ? 0x1c0 : 0x180); for (i = 0; i < size; i++) { writeb(data[i], ad); mb(); } @@ -188,7 +188,7 @@ release_io_teles0(struct IsdnCardState *cs) { if (cs->hw.teles0.cfg_reg) release_region(cs->hw.teles0.cfg_reg, 8); - iounmap((unsigned char *)cs->hw.teles0.membase); + iounmap(cs->hw.teles0.membase); release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); } @@ -336,10 +336,9 @@ setup_teles0(struct IsdnCard *card) release_region(cs->hw.teles0.cfg_reg, 8); return (0); } - cs->hw.teles0.membase = - (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); + cs->hw.teles0.membase = ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); printk(KERN_INFO - "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n", + "HiSax: %s config irq:%d mem:%p cfg:0x%X\n", CardType[cs->typ], cs->irq, cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); if (reset_teles0(cs)) { diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 5e305554d..0661c6c31 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -43,7 +43,7 @@ const char *telespci_revision = "$Revision: 2.23.2.3 $"; } while (portdata & ZORAN_PO_RQ_PEN) static inline u_char -readisac(unsigned long adr, u_char off) +readisac(void __iomem *adr, u_char off) { register unsigned int portdata; @@ -60,7 +60,7 @@ readisac(unsigned long adr, u_char off) } static inline void -writeisac(unsigned long adr, u_char off, u_char data) +writeisac(void __iomem *adr, u_char off, u_char data) { register unsigned int portdata; @@ -76,7 +76,7 @@ writeisac(unsigned long adr, u_char off, u_char data) } static inline u_char -readhscx(unsigned long adr, int hscx, u_char off) +readhscx(void __iomem *adr, int hscx, u_char off) { register unsigned int portdata; @@ -92,7 +92,7 @@ readhscx(unsigned long adr, int hscx, u_char off) } static inline void -writehscx(unsigned long adr, int hscx, u_char off, u_char data) +writehscx(void __iomem *adr, int hscx, u_char off, u_char data) { register unsigned int portdata; @@ -107,7 +107,7 @@ writehscx(unsigned long adr, int hscx, u_char off, u_char data) } static inline void -read_fifo_isac(unsigned long adr, u_char * data, int size) +read_fifo_isac(void __iomem *adr, u_char * data, int size) { register unsigned int portdata; register int i; @@ -125,7 +125,7 @@ read_fifo_isac(unsigned long adr, u_char * data, int size) } static void -write_fifo_isac(unsigned long adr, u_char * data, int size) +write_fifo_isac(void __iomem *adr, u_char * data, int size) { register unsigned int portdata; register int i; @@ -142,7 +142,7 @@ write_fifo_isac(unsigned long adr, u_char * data, int size) } static inline void -read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) { register unsigned int portdata; register int i; @@ -160,7 +160,7 @@ read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) } static inline void -write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) { unsigned int portdata; register int i; @@ -260,7 +260,7 @@ telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs) void release_io_telespci(struct IsdnCardState *cs) { - iounmap((void *)cs->hw.teles0.membase); + iounmap(cs->hw.teles0.membase); } static int @@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card) printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_TELESPCI) return (0); -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { if (pci_enable_device(dev_tel)) return(0); @@ -309,7 +309,7 @@ setup_telespci(struct IsdnCard *card) printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); return(0); } - cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0), + cs->hw.teles0.membase = ioremap(pci_resource_start(dev_tel, 0), PAGE_SIZE); printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", pci_resource_start(dev_tel, 0), dev_tel->irq); @@ -333,7 +333,7 @@ setup_telespci(struct IsdnCard *card) /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ printk(KERN_INFO - "HiSax: %s config irq:%d mem:%lx\n", + "HiSax: %s config irq:%d mem:%p\n", CardType[cs->typ], cs->irq, cs->hw.teles0.membase); diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index cfe876043..36cfc4a48 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -1012,7 +1012,7 @@ setup_w6692(struct IsdnCard *card) printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_W6692) return (0); -#if CONFIG_PCI +#ifdef CONFIG_PCI while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index 2f2731520..e19a01a30 100644 --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "hysdn_defs.h" @@ -246,8 +247,7 @@ ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs) /* the interrupts are still masked */ sti(); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + msleep_interruptible(20); /* Timeout 20ms */ if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) { if (card->debug_flags & LOG_POF_CARD) @@ -386,8 +386,7 @@ ergo_waitpofready(struct HYSDN_CARD *card) return (0); /* success */ } /* data has arrived */ sti(); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */ + msleep_interruptible(50); /* Timeout 50ms */ } /* wait until timeout */ if (card->debug_flags & LOG_POF_CARD) diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 4f639037f..8ee25b2cc 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -246,8 +246,6 @@ hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, rp->level3cnt = MaxLogicalConnections; memcpy(&hycapi_applications[appl-1].rp, rp, sizeof(capi_register_params)); - -/* MOD_INC_USE_COUNT; */ } /********************************************************************* @@ -311,7 +309,6 @@ hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl) { hycapi_release_internal(ctrl, appl); } -/* MOD_DEC_USE_COUNT; */ } diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 1a2015ecf..4fa3b0170 100644 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "hysdn_defs.h" @@ -160,8 +161,7 @@ hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan) if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg delayed"); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + msleep_interruptible(20); /* Timeout 20ms */ if (!--cnt) { restore_flags(flags); return (-ERR_ASYNC_TIME); /* timed out */ @@ -190,8 +190,7 @@ hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan) if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg waiting for tx-ready"); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + msleep_interruptible(20); /* Timeout 20ms */ if (!--cnt) { restore_flags(flags); return (-ERR_ASYNC_TIME); /* timed out */ diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 4071c4377..3ac15d97f 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -99,7 +99,7 @@ config ISDN_DRV_LOOP config ISDN_DIVERSION tristate "Support isdn diversion services" - depends on BROKEN && BROKEN_ON_SMP + depends on ISDN && ISDN_I4L help This option allows you to use some supplementary diversion services in conjunction with the HiSax driver on an EURO/DSS1 diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c index 16fda695f..baf4bcad9 100644 --- a/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/drivers/isdn/i4l/isdn_bsdcomp.c @@ -68,9 +68,9 @@ #include #include /* used in new tty drivers */ #include /* used in new tty drivers */ +#include #include -#include #include #include @@ -364,7 +364,7 @@ static void *bsd_alloc (struct isdn_ppp_comp_data *data) db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) * sizeof (db->lens[0])); if (!db->lens) { - bsd_free (db); /* calls MOD_DEC_USE_COUNT; */ + bsd_free (db); return (NULL); } } diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 69c6884e9..964d5c975 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1369,7 +1369,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev) skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN); - eth = skb->mac.ethernet; + eth = eth_hdr(skb); if (*eth->h_dest & 1) { if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 02b912ab1..e21007eca 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -13,6 +13,7 @@ #include #include +#include #include "isdn_common.h" #include "isdn_tty.h" #ifdef CONFIG_ISDN_AUDIO @@ -26,8 +27,8 @@ /* Prototypes */ -static int isdn_tty_edit_at(const char *, int, modem_info *, int); -static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *, int); +static int isdn_tty_edit_at(const char *, int, modem_info *); +static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *); static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); @@ -296,10 +297,7 @@ isdn_tty_tint(modem_info * info) info->send_outstanding++; info->msr &= ~UART_MSR_CTS; info->lsr &= ~UART_LSR_TEMT; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); return; } if (slen < 0) { @@ -393,15 +391,12 @@ isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len) * ^S or ^Q is sent. */ static int -isdn_tty_end_vrx(const char *buf, int c, int from_user) +isdn_tty_end_vrx(const char *buf, int c) { char ch; while (c--) { - if (from_user) - get_user(ch, buf); - else - ch = *buf; + ch = *buf; if ((ch != 0x11) && (ch != 0x13)) return 1; buf++; @@ -1129,7 +1124,7 @@ isdn_tty_shutdown(modem_info * info) * - If dialing, abort dial. */ static int -isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) +isdn_tty_write(struct tty_struct *tty, const u_char * buf, int count) { int c; int total = 0; @@ -1138,8 +1133,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write")) return 0; - if (from_user) - down(&info->write_sem); /* See isdn_tty_senddown() */ atomic_inc(&info->xmit_lock); while (1) { @@ -1160,12 +1153,8 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co #endif isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, &(m->pluscount), - &(m->lastplus), - from_user); - if (from_user) - copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); - else - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); + &(m->lastplus)); + memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1174,10 +1163,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co /* If DLE decoding results in zero-transmit, but * c originally was non-zero, do a wakeup. */ - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); info->msr |= UART_MSR_CTS; info->lsr |= UART_LSR_TEMT; } @@ -1187,7 +1173,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co /* Do NOT handle Ctrl-Q or Ctrl-S * when in full-duplex audio mode. */ - if (isdn_tty_end_vrx(buf, c, from_user)) { + if (isdn_tty_end_vrx(buf, c)) { info->vonline &= ~1; #ifdef ISDN_DEBUG_MODEM_VOICE printk(KERN_DEBUG @@ -1230,7 +1216,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co isdn_tty_modem_result(RESULT_NO_CARRIER, info); isdn_tty_modem_hup(info, 1); } else - c = isdn_tty_edit_at(buf, c, info, from_user); + c = isdn_tty_edit_at(buf, c, info); } buf += c; count -= c; @@ -1244,8 +1230,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co } isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } - if (from_user) - up(&info->write_sem); return total; } @@ -1290,9 +1274,7 @@ isdn_tty_flush_buffer(struct tty_struct *tty) isdn_tty_cleanup_xmit(info); info->xmit_count = 0; wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); } static void @@ -1747,17 +1729,16 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) } dev->modempoll--; isdn_tty_shutdown(info); + if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); info->tty = NULL; info->ncarrier = 0; tty->closing = 0; module_put(info->owner); if (info->blocked_open) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); + msleep_interruptible(500); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING); @@ -2475,10 +2456,8 @@ isdn_tty_off_hook(void) */ static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, - u_long *lastplus, int from_user) + u_long *lastplus) { - char cbuf[3]; - if (plus > 127) return; if (count > 3) { @@ -2486,10 +2465,6 @@ isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, count = 3; *pluscount = 0; } - if (from_user) { - copy_from_user(cbuf, p, count); - p = cbuf; - } while (count > 0) { if (*(p++) == plus) { if ((*pluscount)++) { @@ -2681,8 +2656,7 @@ isdn_tty_modem_result(int code, modem_info * info) if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { return; } - if (info->tty->ldisc.flush_buffer) - info->tty->ldisc.flush_buffer(info->tty); + tty_ldisc_flush(info->tty); if ((info->flags & ISDN_ASYNC_CHECK_CD) && (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { @@ -3770,10 +3744,9 @@ isdn_tty_parse_at(modem_info * info) * p inputbuffer * count length of buffer * channel index to line (minor-device) - * user flag: buffer is in userspace */ static int -isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) +isdn_tty_edit_at(const char *p, int count, modem_info * info) { atemu *m = &info->emu; int total = 0; @@ -3782,10 +3755,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) int cnt; for (cnt = count; cnt > 0; p++, cnt--) { - if (user) - get_user(c, p); - else - c = *p; + c = *p; total++; if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { /* Separator (CR or LF) */ diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c index da1d2fb9f..4ab7600cf 100644 --- a/drivers/isdn/i4l/isdn_x25iface.c +++ b/drivers/isdn/i4l/isdn_x25iface.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "isdn_x25iface.h" /* for debugging messages not to cause an oops when device pointer is NULL*/ @@ -191,12 +192,9 @@ int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb) IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) ); if ( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state == WAN_CONNECTED ){ - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; if( skb_push(skb, 1)){ skb -> data[0]=0x00; - skb -> mac.raw = skb -> data; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } @@ -224,10 +222,7 @@ int isdn_x25iface_connect_ind(struct concap_proto *cprot) *state_p = WAN_CONNECTED; if( skb ){ *( skb_put(skb, 1) ) = 0x01; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } else { @@ -256,10 +251,7 @@ int isdn_x25iface_disconn_ind(struct concap_proto *cprot) skb = dev_alloc_skb(1); if( skb ){ *( skb_put(skb, 1) ) = 0x02; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; + skb->protocol = x25_type_trans(skb, cprot->net_dev); netif_rx(skb); return 0; } else { diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 0c256d698..70989aa4c 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -762,8 +762,7 @@ icn_check_loader(int cardnumber) #ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d TO?\n", cardnumber); #endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(ICN_BOOT_TIMEOUT1); + msleep_interruptible(ICN_BOOT_TIMEOUT1); } else { #ifdef BOOT_DEBUG printk(KERN_DEBUG "Loader %d OK\n", cardnumber); @@ -788,8 +787,7 @@ icn_check_loader(int cardnumber) int slsec = sec; \ printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \ while (slsec) { \ - current->state = TASK_INTERRUPTIBLE; \ - schedule_timeout(HZ); \ + msleep_interruptible(1000); \ slsec--; \ } \ } @@ -950,7 +948,7 @@ icn_loadproto(u_char __user * buffer, icn_card * card) icn_maprelease_channel(card, 0); return -EIO; } - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(10); } } @@ -974,8 +972,7 @@ icn_loadproto(u_char __user * buffer, icn_card * card) #ifdef BOOT_DEBUG printk(KERN_DEBUG "Proto TO?\n"); #endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(ICN_BOOT_TIMEOUT1); + msleep_interruptible(ICN_BOOT_TIMEOUT1); } else { if ((card->secondhalf) || (!card->doubleS0)) { #ifdef BOOT_DEBUG @@ -1271,9 +1268,9 @@ icn_command(isdn_ctrl * c, icn_card * card) if (!card->leased) { card->leased = 1; while (card->ptype == ISDN_PTYPE_UNKNOWN) { - schedule_timeout(ICN_BOOT_TIMEOUT1); + msleep_interruptible(ICN_BOOT_TIMEOUT1); } - schedule_timeout(ICN_BOOT_TIMEOUT1); + msleep_interruptible(ICN_BOOT_TIMEOUT1); sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", (a & 1)?'1':'C', (a & 2)?'2':'C'); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 4ab15c917..28548318a 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -70,8 +70,7 @@ typedef struct icn_cdef { #define ICN_FLAGS_RUNNING 4 /* Cards driver activated */ #define ICN_FLAGS_RBTIMER 8 /* cyclic scheduling of B-Channel-poll */ -#define ICN_BOOT_TIMEOUT1 (HZ) /* Delay for Boot-download (jiffies) */ -#define ICN_CHANLOCK_DELAY (HZ/10) /* Delay for Channel-mapping (jiffies) */ +#define ICN_BOOT_TIMEOUT1 1000 /* Delay for Boot-download (msecs) */ #define ICN_TIMER_BCREAD (HZ/100) /* B-Channel poll-cycle */ #define ICN_TIMER_DCREAD (HZ/2) /* D-Channel poll-cycle */ diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 544f41b41..7f17ab1ac 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "isdnloop.h" static char *revision = "$Revision: 1.11.6.7 $"; @@ -1161,8 +1162,10 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) if (!card->leased) { card->leased = 1; while (card->ptype == ISDN_PTYPE_UNKNOWN) { + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(10); } + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(10); sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n"); i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index ed8af7ff0..dfd9379d6 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -859,7 +859,7 @@ static int set_protocol_running(struct pcbit_dev * dev) printk(KERN_DEBUG "Bank3 = %02x\n", readb(dev->sh_mem + BANK3)); #endif - *(dev->sh_mem + BANK4) = 0x40U; + writeb(0x40, dev->sh_mem + BANK4); /* warn the upper layer */ ctl.driver = dev->id; diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h index bdb27fae6..8e44928cd 100644 --- a/drivers/isdn/sc/card.h +++ b/drivers/isdn/sc/card.h @@ -24,24 +24,25 @@ * We need these if they're not already included */ #include +#include #include #include "message.h" /* * Amount of time to wait for a reset to complete */ -#define CHECKRESET_TIME milliseconds(4000) +#define CHECKRESET_TIME msecs_to_jiffies(4000) /* * Amount of time between line status checks */ -#define CHECKSTAT_TIME milliseconds(8000) +#define CHECKSTAT_TIME msecs_to_jiffies(8000) /* * The maximum amount of time to wait for a message response * to arrive. Use exclusively by send_and_receive */ -#define SAR_TIMEOUT milliseconds(10000) +#define SAR_TIMEOUT msecs_to_jiffies(10000) /* * Macro to determine is a card id is valid diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index adde8fb14..9e6d5302b 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h @@ -104,9 +104,6 @@ * Some handy macros */ -/* Return the number of jiffies in a given number of msecs */ -#define milliseconds(x) (((x)*HZ)/1000) - /* Determine if a channel number is valid for the adapter */ #define IS_VALID_CHANNEL(y,x) ((x>0) && (x <= sc_adapter[y]->channels)) diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 930845cff..a10c6af42 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "includes.h" #include "hardware.h" #include "card.h" @@ -167,8 +168,7 @@ static int __init sc_init(void) if(do_reset) { pr_debug("Doing a SAFE probe reset\n"); outb(0xFF, io[b] + RESET_OFFSET); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(milliseconds(10000)); + msleep_interruptible(10000); } pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], ram[b] == 0 ? "will" : "won't"); @@ -500,8 +500,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(PRI_BASEPG_VAL, pgport); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible(1000); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); if(sig == SIGNATURE) @@ -511,8 +510,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(BRI_BASEPG_VAL, pgport); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible(1000); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); if(sig == SIGNATURE) diff --git a/drivers/isdn/tpam/tpam.h b/drivers/isdn/tpam/tpam.h index c1456d4b6..5b92b9561 100644 --- a/drivers/isdn/tpam/tpam.h +++ b/drivers/isdn/tpam/tpam.h @@ -14,6 +14,8 @@ #ifndef _TPAM_PRIV_H_ #define _TPAM_PRIV_H_ +//#define DEBUG /* uncomment if you want debugging output */ +#include #include #include #include @@ -75,7 +77,7 @@ typedef struct tpam_channel { typedef struct tpam_card { struct tpam_card *next; /* next card in list */ unsigned int irq; /* IRQ used by this board */ - unsigned long bar0; /* ioremapped bar0 */ + void __iomem *bar0; /* ioremapped bar0 */ int id; /* id of the board */ isdn_if interface; /* isdn link-level pointer */ int channels_used; /* number of channels actually used */ @@ -169,12 +171,12 @@ extern tpam_card *tpam_findcard(int); extern u32 tpam_findchannel(tpam_card *, u32); /* Function prototypes from tpam_memory.c */ -extern void copy_to_pam_dword(tpam_card *, const void *, u32); -extern void copy_to_pam(tpam_card *, void *, const void *, u32); -extern u32 copy_from_pam_dword(tpam_card *, const void *); -extern void copy_from_pam(tpam_card *, void *, const void *, u32); -extern int copy_from_pam_to_user(tpam_card *, void __user *, const void *, u32); -extern int copy_from_user_to_pam(tpam_card *, void *, const void __user *, u32); +extern void copy_to_pam_dword(tpam_card *, u32, u32); +extern void copy_to_pam(tpam_card *, u32, const void *, u32); +extern u32 copy_from_pam_dword(tpam_card *, u32); +extern void copy_from_pam(tpam_card *, void *, u32, u32); +extern int copy_from_pam_to_user(tpam_card *, void __user *, u32, u32); +extern int copy_from_user_to_pam(tpam_card *, u32, const void __user *, u32); extern int tpam_verify_area(u32, u32); /* Function prototypes from tpam_nco.c */ @@ -224,13 +226,4 @@ extern void hdlc_encode_modem(u8 *, u32, u8 *, u32 *); extern void hdlc_no_accm_encode(u8 *, u32, u8 *, u32 *); extern u32 hdlc_no_accm_decode(u8 *, u32); -/* Define this to enable debug tracing prints */ -#undef DEBUG - -#ifdef DEBUG -#define dprintk printk -#else -#define dprintk while(0) printk -#endif - #endif /* _TPAM_H_ */ diff --git a/drivers/isdn/tpam/tpam_commands.c b/drivers/isdn/tpam/tpam_commands.c index 9cf6ef14f..3f8e79393 100644 --- a/drivers/isdn/tpam/tpam_commands.c +++ b/drivers/isdn/tpam/tpam_commands.c @@ -21,8 +21,8 @@ #include "tpam.h" /* Local functions prototypes */ -static int tpam_command_ioctl_dspload(tpam_card *, u32); -static int tpam_command_ioctl_dspsave(tpam_card *, u32); +static int tpam_command_ioctl_dspload(tpam_card *, unsigned long); +static int tpam_command_ioctl_dspsave(tpam_card *, unsigned long); static int tpam_command_ioctl_dsprun(tpam_card *); static int tpam_command_ioctl_loopmode(tpam_card *, u8); static int tpam_command_dial(tpam_card *, u32, u8 *); @@ -45,7 +45,7 @@ int tpam_command(isdn_ctrl *c) { tpam_card *card; unsigned long argp; - dprintk("TurboPAM(tpam_command) card=%d, command=%d\n", + pr_debug("TurboPAM(tpam_command) card=%d, command=%d\n", c->driver, c->command); /* search for the board */ @@ -75,7 +75,7 @@ int tpam_command(isdn_ctrl *c) { return tpam_command_ioctl_loopmode(card, 0); default: - dprintk("TurboPAM(tpam_command): " + pr_debug("TurboPAM(tpam_command): " "invalid tpam ioctl %ld\n", c->arg); return -EINVAL; @@ -95,7 +95,7 @@ int tpam_command(isdn_ctrl *c) { case ISDN_CMD_PROCEED: return tpam_command_proceed(card, c->arg); default: - dprintk("TurboPAM(tpam_command): " + pr_debug("TurboPAM(tpam_command): " "unknown or unused isdn ioctl %d\n", c->command); return -EINVAL; @@ -114,10 +114,10 @@ int tpam_command(isdn_ctrl *c) { * * Return: 0 if OK, <0 on errors. */ -static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) { +static int tpam_command_ioctl_dspload(tpam_card *card, unsigned long arg) { tpam_dsp_ioctl tdl; - dprintk("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id); /* get the IOCTL parameter from userspace */ if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl))) @@ -130,7 +130,7 @@ static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) { return -EPERM; /* write the data in the board's memory */ - return copy_from_user_to_pam(card, (void *)tdl.address, + return copy_from_user_to_pam(card, tdl.address, (void __user *)arg + sizeof(tpam_dsp_ioctl), tdl.data_len); } @@ -144,10 +144,10 @@ static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) { * * Return: 0 if OK, <0 on errors. */ -static int tpam_command_ioctl_dspsave(tpam_card *card, u32 arg) { +static int tpam_command_ioctl_dspsave(tpam_card *card, unsigned long arg) { tpam_dsp_ioctl tdl; - dprintk("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id); /* get the IOCTL parameter from userspace */ if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl))) @@ -159,7 +159,7 @@ static int tpam_command_ioctl_dspsave(tpam_card *card, u32 arg) { /* read the data from the board's memory */ return copy_from_pam_to_user(card, (void __user *)arg + sizeof(tpam_dsp_ioctl), - (void *)tdl.address, tdl.data_len); + tdl.address, tdl.data_len); } /* @@ -178,7 +178,7 @@ static int tpam_command_ioctl_dsprun(tpam_card *card) { isdn_ctrl ctrl; struct sk_buff *skb; - dprintk("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id); /* board must _not_ be running */ if (card->running) @@ -186,7 +186,7 @@ static int tpam_command_ioctl_dsprun(tpam_card *card) { /* reset the board */ spin_lock_irq(&card->lock); - copy_to_pam_dword(card, (void *)TPAM_MAGICNUMBER_REGISTER, 0xdeadface); + copy_to_pam_dword(card, TPAM_MAGICNUMBER_REGISTER, 0xdeadface); readl(card->bar0 + TPAM_DSPINT_REGISTER); readl(card->bar0 + TPAM_HINTACK_REGISTER); spin_unlock_irq(&card->lock); @@ -196,7 +196,7 @@ static int tpam_command_ioctl_dsprun(tpam_card *card) { while (time_before(jiffies, timeout)) { spin_lock_irq(&card->lock); signature = copy_from_pam_dword(card, - (void *)TPAM_MAGICNUMBER_REGISTER); + TPAM_MAGICNUMBER_REGISTER); spin_unlock_irq(&card->lock); if (signature == TPAM_MAGICNUMBER) break; @@ -297,7 +297,7 @@ static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) { struct sk_buff *skb; isdn_ctrl ctrl; - dprintk("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n", + pr_debug("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n", card->id, (unsigned long)channel, phone); /* board must be running */ @@ -341,7 +341,7 @@ static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) { */ static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) { - dprintk("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n", + pr_debug("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n", card->id, (unsigned long)channel, proto); /* board must be running */ @@ -376,7 +376,7 @@ static int tpam_command_acceptd(tpam_card *card, u32 channel) { isdn_ctrl ctrl; struct sk_buff *skb; - dprintk("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n", + pr_debug("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n", card->id, (unsigned long)channel); /* board must be running */ @@ -410,7 +410,7 @@ static int tpam_command_acceptd(tpam_card *card, u32 channel) { static int tpam_command_acceptb(tpam_card *card, u32 channel) { isdn_ctrl ctrl; - dprintk("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n", + pr_debug("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n", card->id, (unsigned long)channel); /* board must be running */ @@ -437,7 +437,7 @@ static int tpam_command_acceptb(tpam_card *card, u32 channel) { static int tpam_command_hangup(tpam_card *card, u32 channel) { struct sk_buff *skb; - dprintk("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n", + pr_debug("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n", card->id, (unsigned long)channel); /* board must be running */ @@ -464,7 +464,7 @@ static int tpam_command_hangup(tpam_card *card, u32 channel) { static int tpam_command_proceed(tpam_card *card, u32 channel) { struct sk_buff *skb; - dprintk("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n", + pr_debug("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n", card->id, (unsigned long)channel); /* board must be running */ @@ -496,7 +496,7 @@ int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) { void *finaldata; u32 finallen; - dprintk("TurboPAM(tpam_writebuf_skb): " + pr_debug("TurboPAM(tpam_writebuf_skb): " "card=%d, channel=%ld, ack=%d, data size=%d\n", driverId, (unsigned long)channel, ack, skb->len); @@ -531,14 +531,14 @@ int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) { if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) { printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): " "get_free_page failed\n"); - free_page((u32)finaldata); + free_page((unsigned long)finaldata); return -ENOMEM; } hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen); finallen = tpam_hdlc_encode(tempdata, finaldata, &card->channels[channel].hdlcshift, templen); - free_page((u32)tempdata); + free_page((unsigned long)tempdata); } /* free the old sk_buff */ @@ -548,13 +548,13 @@ int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) { skb = build_U3DataReq(card->channels[channel].ncoid, finaldata, finallen, ack, orig_size); if (!skb) { - free_page((u32)finaldata); + free_page((unsigned long)finaldata); return -ENOMEM; } tpam_enqueue_data(&card->channels[channel], skb); /* free the temporary memory */ - free_page((u32)finaldata); + free_page((unsigned long)finaldata); return orig_size; } @@ -569,7 +569,7 @@ void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) { u8 status; u32 channel; - dprintk("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id); /* parse the message contents */ if (parse_ACreateNCOCnf(skb, &status, &ncoid)) @@ -614,7 +614,7 @@ void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) { u8 status; u32 channel; - dprintk("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id); /* parse the message contents */ if (parse_ADestroyNCOCnf(skb, &status, &ncoid)) @@ -647,7 +647,7 @@ void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) { u32 channel; isdn_ctrl ctrl; - dprintk("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id); /* parse the message contents */ if (parse_CConnectCnf(skb, &ncoid)) @@ -685,7 +685,7 @@ void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) { isdn_ctrl ctrl; int status; - dprintk("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id); /* parse the message contents */ if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen)) @@ -720,13 +720,13 @@ void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) { case 4: /* call accepted, link layer will send us a ACCEPTD * command later */ - dprintk("TurboPAM(tpam_recv_CConnectInd): " + pr_debug("TurboPAM(tpam_recv_CConnectInd): " "card=%d, channel=%d, icall waiting, status=%d\n", card->id, channel, status); break; default: /* call denied, we build and send a CDisconnectReq */ - dprintk("TurboPAM(tpam_recv_CConnectInd): " + pr_debug("TurboPAM(tpam_recv_CConnectInd): " "card=%d, channel=%d, icall denied, status=%d\n", card->id, channel, status); skb = build_CDisconnectReq(ncoid); @@ -749,7 +749,7 @@ void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) { u32 cause; isdn_ctrl ctrl; - dprintk("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id); /* parse the message contents */ if (parse_CDisconnectInd(skb, &ncoid, &cause)) @@ -794,7 +794,7 @@ void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) { u32 cause; isdn_ctrl ctrl; - dprintk("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id); /* parse the message contents */ if (parse_CDisconnectCnf(skb, &ncoid, &cause)) @@ -835,7 +835,7 @@ void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) { u16 len; struct sk_buff *result; - dprintk("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n", + pr_debug("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n", card->id, skb->len); /* parse the message contents */ @@ -865,11 +865,11 @@ void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) { if (!(result = alloc_skb(templen, GFP_ATOMIC))) { printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): " "alloc_skb failed\n"); - free_page((u32)tempdata); + free_page((unsigned long)tempdata); return; } memcpy(skb_put(result, templen), tempdata, templen); - free_page((u32)tempdata); + free_page((unsigned long)tempdata); } else { /* modem mode */ @@ -914,7 +914,7 @@ void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) { u32 channel; u8 ready; - dprintk("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id); /* parse the message contents */ if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready)) @@ -943,7 +943,7 @@ void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) { static void tpam_statcallb_run(unsigned long parm) { tpam_statcallb_data *ds = (tpam_statcallb_data *)parm; - dprintk("TurboPAM(tpam_statcallb_run)\n"); + pr_debug("TurboPAM(tpam_statcallb_run)\n"); (* ds->card->interface.statcallb)(&ds->ctrl); @@ -961,7 +961,7 @@ static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) { struct timer_list *timer; tpam_statcallb_data *ds; - dprintk("TurboPAM(tpam_statcallb): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_statcallb): card=%d\n", card->id); if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list), GFP_ATOMIC))) { diff --git a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c index 91392c469..7788f42a5 100644 --- a/drivers/isdn/tpam/tpam_main.c +++ b/drivers/isdn/tpam/tpam_main.c @@ -23,7 +23,7 @@ /* Local functions prototypes */ static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit tpam_unregister_card(tpam_card *); +static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *); static void __devexit tpam_remove(struct pci_dev *); static int __init tpam_init(void); static void __exit tpam_exit(void); @@ -86,13 +86,20 @@ u32 tpam_findchannel(tpam_card *card, u32 ncoid) { */ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { tpam_card *card, *c; - int i; + int i, err; + + if ((err = pci_enable_device(dev))) { + printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n", + pci_name(dev)); + return err; + } /* allocate memory for the board structure */ if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "kmalloc failed!\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_out_disable_dev; } memset((char *)card, 0, sizeof(tpam_card)); @@ -106,30 +113,29 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id card->interface.id, card)) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "could not request irq %d\n", card->irq); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_card; } /* remap board memory */ - if (!(card->bar0 = (unsigned long) ioremap(pci_resource_start(dev, 0), + if (!(card->bar0 = ioremap(pci_resource_start(dev, 0), 0x800000))) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "unable to remap bar0\n"); - free_irq(card->irq, card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_irq; } /* reset the board */ readl(card->bar0 + TPAM_RESETPAM_REGISTER); /* initialisation magic :-( */ - copy_to_pam_dword(card, (void *)0x01800008, 0x00000030); - copy_to_pam_dword(card, (void *)0x01800010, 0x00000030); - copy_to_pam_dword(card, (void *)0x01800014, 0x42240822); - copy_to_pam_dword(card, (void *)0x01800018, 0x07114000); - copy_to_pam_dword(card, (void *)0x0180001c, 0x00000400); - copy_to_pam_dword(card, (void *)0x01840070, 0x00000010); + copy_to_pam_dword(card, 0x01800008, 0x00000030); + copy_to_pam_dword(card, 0x01800010, 0x00000030); + copy_to_pam_dword(card, 0x01800014, 0x42240822); + copy_to_pam_dword(card, 0x01800018, 0x07114000); + copy_to_pam_dword(card, 0x0180001c, 0x00000400); + copy_to_pam_dword(card, 0x01840070, 0x00000010); /* fill the ISDN link layer structure */ card->interface.owner = THIS_MODULE; @@ -150,10 +156,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id if (!register_isdn(&card->interface)) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "unable to register %s\n", card->interface.id); - free_irq(card->irq, card); - iounmap((void *)card->bar0); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } card->id = card->interface.channels; @@ -195,6 +199,19 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id pci_set_drvdata(dev, card); return 0; + +err_out_iounmap: + iounmap(card->bar0); + +err_out_free_irq: + free_irq(card->irq, card); + +err_out_free_card: + kfree(card); + +err_out_disable_dev: + pci_disable_device(dev); + return err; } /* @@ -202,7 +219,7 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id * * card: the board. */ -static void __devexit tpam_unregister_card(tpam_card *card) { +static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) { isdn_ctrl cmd; /* prevent the ISDN link layer that the driver will be unloaded */ @@ -214,7 +231,9 @@ static void __devexit tpam_unregister_card(tpam_card *card) { free_irq(card->irq, card); /* release mapped memory */ - iounmap((void *)card->bar0); + iounmap(card->bar0); + + pci_disable_device(pcidev); } /* @@ -235,7 +254,7 @@ static void __devexit tpam_remove(struct pci_dev *pcidev) { } /* unregister each board */ - tpam_unregister_card(card); + tpam_unregister_card(pcidev, card); /* and free the board structure itself */ kfree(card); diff --git a/drivers/isdn/tpam/tpam_memory.c b/drivers/isdn/tpam/tpam_memory.c index ae690b7ce..854f574f5 100644 --- a/drivers/isdn/tpam/tpam_memory.c +++ b/drivers/isdn/tpam/tpam_memory.c @@ -23,14 +23,14 @@ * addr: the address (in the board memory) * val: the value to put into the memory. */ -void copy_to_pam_dword(tpam_card *card, const void *addr, u32 val) { +void copy_to_pam_dword(tpam_card *card, u32 addr, u32 val) { /* set the page register */ - writel(((unsigned long)addr) | TPAM_PAGE_SIZE, + writel(addr | TPAM_PAGE_SIZE, card->bar0 + TPAM_PAGE_REGISTER); /* write the value */ - writel(val, card->bar0 + (((unsigned long)addr) & TPAM_PAGE_SIZE)); + writel(val, card->bar0 + (addr & TPAM_PAGE_SIZE)); } /* @@ -42,15 +42,15 @@ void copy_to_pam_dword(tpam_card *card, const void *addr, u32 val) { * from: the source address (in the kernel memory) * n: number of bytes */ -void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) { +void copy_to_pam(tpam_card *card, u32 to, const void *from, u32 n) { u32 page, offset, count; /* need to write in dword ! */ while (n & 3) n++; while (n) { - page = ((u32)to) | TPAM_PAGE_SIZE; - offset = ((u32)to) & TPAM_PAGE_SIZE; + page = to | TPAM_PAGE_SIZE; + offset = to & TPAM_PAGE_SIZE; count = n < TPAM_PAGE_SIZE - offset ? n : TPAM_PAGE_SIZE - offset; @@ -59,7 +59,7 @@ void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) { writel(page, card->bar0 + TPAM_PAGE_REGISTER); /* copy the data */ - memcpy_toio((void *)(card->bar0 + offset), from, count); + memcpy_toio(card->bar0 + offset, from, count); from += count; to += count; @@ -75,14 +75,14 @@ void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) { * * Return: the value read into the memory. */ -u32 copy_from_pam_dword(tpam_card *card, const void *addr) { +u32 copy_from_pam_dword(tpam_card *card, u32 addr) { /* set the page register */ writel(((u32)addr) | TPAM_PAGE_SIZE, card->bar0 + TPAM_PAGE_REGISTER); /* read the data */ - return readl(card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE)); + return readl(card->bar0 + (addr & TPAM_PAGE_SIZE)); } /* @@ -93,12 +93,12 @@ u32 copy_from_pam_dword(tpam_card *card, const void *addr) { * from: the source address (in the board memory) * n: number of bytes */ -void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) { +void copy_from_pam(tpam_card *card, void *to, u32 from, u32 n) { u32 page, offset, count; while (n) { - page = ((u32)from) | TPAM_PAGE_SIZE; - offset = ((u32)from) & TPAM_PAGE_SIZE; + page = from | TPAM_PAGE_SIZE; + offset = from & TPAM_PAGE_SIZE; count = n < TPAM_PAGE_SIZE - offset ? n : TPAM_PAGE_SIZE - offset; @@ -107,7 +107,7 @@ void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) { writel(page, card->bar0 + TPAM_PAGE_REGISTER); /* read the data */ - memcpy_fromio(to, (void *)(card->bar0 + offset), count); + memcpy_fromio(to, card->bar0 + offset, count); from += count; to += count; @@ -125,7 +125,7 @@ void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) { * * Return: 0 if OK, <0 if error. */ -int copy_from_pam_to_user(tpam_card *card, void __user *to, const void *from, u32 n) { +int copy_from_pam_to_user(tpam_card *card, void __user *to, u32 from, u32 n) { void *page; u32 count; @@ -148,7 +148,7 @@ int copy_from_pam_to_user(tpam_card *card, void __user *to, const void *from, u3 if (copy_to_user(to, page, count)) { /* this can fail... */ - free_page((u32)page); + free_page((unsigned long)page); return -EFAULT; } from += count; @@ -157,7 +157,7 @@ int copy_from_pam_to_user(tpam_card *card, void __user *to, const void *from, u3 } /* release allocated memory */ - free_page((u32)page); + free_page((unsigned long)page); return 0; } @@ -171,7 +171,7 @@ int copy_from_pam_to_user(tpam_card *card, void __user *to, const void *from, u3 * * Return: 0 if OK, <0 if error. */ -int copy_from_user_to_pam(tpam_card *card, void *to, const void __user *from, u32 n) { +int copy_from_user_to_pam(tpam_card *card, u32 to, const void __user *from, u32 n) { void *page; u32 count; @@ -188,7 +188,7 @@ int copy_from_user_to_pam(tpam_card *card, void *to, const void __user *from, u3 /* copy data from the user memory into the kernel memory */ if (copy_from_user(page, from, count)) { /* this can fail... */ - free_page((u32)page); + free_page((unsigned long)page); return -EFAULT; } @@ -203,7 +203,7 @@ int copy_from_user_to_pam(tpam_card *card, void *to, const void __user *from, u3 } /* release allocated memory */ - free_page((u32)page); + free_page((unsigned long)page); return 0; } diff --git a/drivers/isdn/tpam/tpam_nco.c b/drivers/isdn/tpam/tpam_nco.c index 69a6bd4ba..de4904f35 100644 --- a/drivers/isdn/tpam/tpam_nco.c +++ b/drivers/isdn/tpam/tpam_nco.c @@ -84,7 +84,7 @@ struct sk_buff *build_ACreateNCOReq(const u8 *phone) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone); + pr_debug("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone); /* build the NCO packet */ if (!(skb = build_NCOpacket(ID_ACreateNCOReq, 23 + strlen(phone), 0, 0, 0))) @@ -141,7 +141,7 @@ struct sk_buff *build_ADestroyNCOReq(u32 ncoid) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n", + pr_debug("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n", (unsigned long)ncoid); /* build the NCO packet */ @@ -170,7 +170,7 @@ struct sk_buff *build_CConnectReq(u32 ncoid, const u8 *called, u8 hdlc) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n", + pr_debug("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n", (unsigned long)ncoid, called, hdlc); /* build the NCO packet */ @@ -220,7 +220,7 @@ struct sk_buff *build_CConnectRsp(u32 ncoid) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_CConnectRsp): ncoid=%lu\n", + pr_debug("TurboPAM(build_CConnectRsp): ncoid=%lu\n", (unsigned long)ncoid); /* build the NCO packet */ @@ -247,7 +247,7 @@ struct sk_buff *build_CDisconnectReq(u32 ncoid) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_CDisconnectReq): ncoid=%lu\n", + pr_debug("TurboPAM(build_CDisconnectReq): ncoid=%lu\n", (unsigned long)ncoid); /* build the NCO packet */ @@ -274,7 +274,7 @@ struct sk_buff *build_CDisconnectRsp(u32 ncoid) { struct sk_buff *skb; u8 *tlv; - dprintk("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n", + pr_debug("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n", (unsigned long)ncoid); /* build the NCO packet */ @@ -307,7 +307,7 @@ struct sk_buff *build_U3DataReq(u32 ncoid, void *data, u16 len, u8 *tlv; void *p; - dprintk("TurboPAM(build_U3DataReq): " + pr_debug("TurboPAM(build_U3DataReq): " "ncoid=%lu, len=%d, ack=%d, ack_size=%d\n", (unsigned long)ncoid, len, ack, ack_size); @@ -397,7 +397,7 @@ int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { } if (*status) { - dprintk("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status); + pr_debug("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status); return 0; } @@ -408,7 +408,7 @@ int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { return -1; } - dprintk("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n", + pr_debug("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n", (unsigned long)*ncoid, *status); return 0; } @@ -432,7 +432,7 @@ int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { } if (*status) { - dprintk("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status); + pr_debug("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status); return 0; } @@ -443,7 +443,7 @@ int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) { return -1; } - dprintk("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n", + pr_debug("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n", (unsigned long)*ncoid, *status); return 0; } @@ -464,7 +464,7 @@ int parse_CConnectCnf(struct sk_buff *skb, u32 *ncoid) { "NCOID not found\n"); return -1; } - dprintk("TurboPAM(parse_CConnectCnf): ncoid=%lu\n", + pr_debug("TurboPAM(parse_CConnectCnf): ncoid=%lu\n", (unsigned long)*ncoid); return 0; } @@ -522,7 +522,7 @@ int parse_CConnectInd(struct sk_buff *skb, u32 *ncoid, u8 *hdlc, } memcpy(called, phone + 2, PHONE_MAXIMUMSIZE); - dprintk("TurboPAM(parse_CConnectInd): " + pr_debug("TurboPAM(parse_CConnectInd): " "ncoid=%lu, hdlc=%d, plan=%d, scr=%d, calling=%s, called=%s\n", (unsigned long)*ncoid, *hdlc, *plan, *screen, calling, called); return 0; @@ -553,7 +553,7 @@ int parse_CDisconnectCnf(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) { return -1; } - dprintk("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n", + pr_debug("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n", (unsigned long)*ncoid, (unsigned long)*causetopuf); return 0; } @@ -583,7 +583,7 @@ int parse_CDisconnectInd(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) { return -1; } - dprintk("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n", + pr_debug("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n", (unsigned long)*ncoid, (unsigned long)*causetopuf); return 0; } @@ -613,7 +613,7 @@ int parse_U3ReadyToReceiveInd(struct sk_buff *skb, u32 *ncoid, u8 *ready) { return -1; } - dprintk("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n", + pr_debug("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n", (unsigned long)*ncoid, *ready); return 0; } @@ -644,7 +644,7 @@ int parse_U3DataInd(struct sk_buff *skb, u32 *ncoid, u8 **data, u16 *len) { sizeof(skb_header) + sizeof(pci_mpb) + p->actualBlockTLVSize); *data = skb->data; - dprintk("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n", + pr_debug("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n", (unsigned long)*ncoid, *len); return 0; } diff --git a/drivers/isdn/tpam/tpam_queues.c b/drivers/isdn/tpam/tpam_queues.c index 9b55684dd..35add91b8 100644 --- a/drivers/isdn/tpam/tpam_queues.c +++ b/drivers/isdn/tpam/tpam_queues.c @@ -30,7 +30,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel); */ void tpam_enqueue(tpam_card *card, struct sk_buff *skb) { - dprintk("TurboPAM(tpam_enqueue): card=%d\n", card->id); + pr_debug("TurboPAM(tpam_enqueue): card=%d\n", card->id); /* queue the sk_buff on the board's send queue */ skb_queue_tail(&card->sendq, skb); @@ -49,7 +49,7 @@ void tpam_enqueue(tpam_card *card, struct sk_buff *skb) { */ void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) { - dprintk("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n", + pr_debug("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n", channel->card->id, channel->num); /* if existant, queue the sk_buff on the channel's send queue */ @@ -84,30 +84,30 @@ irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs) pci_mpb mpb; skb_header *skbh; - dprintk("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id); + pr_debug("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id); /* grab the board lock */ spin_lock(&card->lock); /* get the message type */ - ackupload = copy_from_pam_dword(card, (void *)TPAM_ACKUPLOAD_REGISTER); + ackupload = copy_from_pam_dword(card, TPAM_ACKUPLOAD_REGISTER); /* acknowledge the interrupt */ - copy_to_pam_dword(card, (void *)TPAM_INTERRUPTACK_REGISTER, 0); + copy_to_pam_dword(card, TPAM_INTERRUPTACK_REGISTER, 0); readl(card->bar0 + TPAM_HINTACK_REGISTER); if (!ackupload) { /* it is a new message from the board */ - dprintk("TurboPAM(tpam_irq): message received, card=%d\n", + pr_debug("TurboPAM(tpam_irq): message received, card=%d\n", card->id); /* get the upload pointer */ uploadptr = copy_from_pam_dword(card, - (void *)TPAM_UPLOADPTR_REGISTER); + TPAM_UPLOADPTR_REGISTER); /* get the beginning of the message (pci_mpb part) */ - copy_from_pam(card, &mpb, (void *)uploadptr, sizeof(pci_mpb)); + copy_from_pam(card, &mpb, uploadptr, sizeof(pci_mpb)); /* allocate the sk_buff */ if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) + @@ -131,13 +131,13 @@ irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs) /* copy the TLV block into the sk_buff */ copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize), - (void *)uploadptr + sizeof(pci_mpb), + uploadptr + sizeof(pci_mpb), mpb.actualBlockTLVSize); /* if existent, copy the data block into the sk_buff */ if (mpb.actualDataSize) copy_from_pam(card, skb_put(skb, mpb.actualDataSize), - (void *)uploadptr + sizeof(pci_mpb) + 4096, + uploadptr + sizeof(pci_mpb) + 4096, mpb.actualDataSize); /* wait for the board to become ready */ @@ -154,7 +154,7 @@ irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs) } while (hpic & 0x00000002); /* acknowledge the message */ - copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, + copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER, 0xffffffff); readl(card->bar0 + TPAM_DSPINT_REGISTER); @@ -176,7 +176,7 @@ irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs) else { /* it is a ack from the board */ - dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n", + pr_debug("TurboPAM(tpam_irq): message acknowledged, card=%d\n", card->id); /* board is not busy anymore */ @@ -231,7 +231,7 @@ void tpam_recv_tq(tpam_card *card) { tpam_recv_U3DataInd(card, skb); break; default: - dprintk("TurboPAM(tpam_recv_tq): " + pr_debug("TurboPAM(tpam_recv_tq): " "unknown messageID %d, card=%d\n", p->messageID, card->id); break; @@ -286,13 +286,13 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { skb_header *skbh; u32 waiting_too_long; - dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n", + pr_debug("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n", card->id, channel ? channel->num : -1); if (channel) { /* dequeue a packet from the channel's send queue */ if (!(skb = skb_dequeue(&channel->sendq))) { - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, channel=%d, no packet\n", card->id, channel->num); return 0; @@ -301,7 +301,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { /* if the channel is not ready to receive, requeue the packet * and return 0 to give a chance to another channel */ if (!channel->readytoreceive) { - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, channel=%d, channel not ready\n", card->id, channel->num); skb_queue_head(&channel->sendq, skb); @@ -314,7 +314,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { /* if the board is busy, requeue the packet and return 1 since * there is no need to try another channel */ if (card->busy) { - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, channel=%d, card busy\n", card->id, channel->num); skb_queue_head(&channel->sendq, skb); @@ -325,7 +325,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { else { /* dequeue a packet from the board's send queue */ if (!(skb = skb_dequeue(&card->sendq))) { - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, no packet\n", card->id); return 0; } @@ -336,7 +336,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { /* if the board is busy, requeue the packet and return 1 since * there is no need to try another channel */ if (card->busy) { - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, card busy\n", card->id); skb_queue_head(&card->sendq, skb); spin_unlock_irq(&card->lock); @@ -357,20 +357,19 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { } while (hpic & 0x00000002); skbh = (skb_header *)skb->data; - dprintk("TurboPAM(tpam_sendpacket): " + pr_debug("TurboPAM(tpam_sendpacket): " "card=%d, card ready, sending %d/%d bytes\n", card->id, skbh->size, skbh->data_size); /* get the board's download pointer */ - downloadptr = copy_from_pam_dword(card, - (void *)TPAM_DOWNLOADPTR_REGISTER); + downloadptr = copy_from_pam_dword(card, TPAM_DOWNLOADPTR_REGISTER); /* copy the packet to the board at the downloadptr location */ - copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header), + copy_to_pam(card, downloadptr, skb->data + sizeof(skb_header), skbh->size); if (skbh->data_size) /* if there is some data in the packet, copy it too */ - copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096, + copy_to_pam(card, downloadptr + sizeof(pci_mpb) + 4096, skb->data + sizeof(skb_header) + skbh->size, skbh->data_size); @@ -378,7 +377,7 @@ static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) { card->busy = 1; /* interrupt the board */ - copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0); + copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER, 0); readl(card->bar0 + TPAM_DSPINT_REGISTER); /* release the lock */ diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index c0ab8589b..d3b8f819e 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -74,15 +74,135 @@ static struct notifier_block adbhid_adb_notifier = { #define ADB_KEY_POWER_OLD 0x7e #define ADB_KEY_POWER 0x7f -unsigned char adb_to_linux_keycodes[128] = { - 30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19, - 21, 20, 2, 3, 4, 5, 7, 6, 13, 10, 8, 12, 9, 11, 27, 24, - 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52, - 15, 57, 41, 14, 96, 1, 29,125, 42, 58, 56,105,106,108,103, 0, - 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 98, 96, 0, 74, 0, - 0,117, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73,124, 89,121, - 63, 64, 65, 61, 66, 67,123, 87,122, 99, 0, 70, 0, 68,101, 88, - 0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116 +u8 adb_to_linux_keycodes[128] = { + /* 0x00 */ KEY_A, /* 30 */ + /* 0x01 */ KEY_S, /* 31 */ + /* 0x02 */ KEY_D, /* 32 */ + /* 0x03 */ KEY_F, /* 33 */ + /* 0x04 */ KEY_H, /* 35 */ + /* 0x05 */ KEY_G, /* 34 */ + /* 0x06 */ KEY_Z, /* 44 */ + /* 0x07 */ KEY_X, /* 45 */ + /* 0x08 */ KEY_C, /* 46 */ + /* 0x09 */ KEY_V, /* 47 */ + /* 0x0a */ KEY_102ND, /* 86 */ + /* 0x0b */ KEY_B, /* 48 */ + /* 0x0c */ KEY_Q, /* 16 */ + /* 0x0d */ KEY_W, /* 17 */ + /* 0x0e */ KEY_E, /* 18 */ + /* 0x0f */ KEY_R, /* 19 */ + /* 0x10 */ KEY_Y, /* 21 */ + /* 0x11 */ KEY_T, /* 20 */ + /* 0x12 */ KEY_1, /* 2 */ + /* 0x13 */ KEY_2, /* 3 */ + /* 0x14 */ KEY_3, /* 4 */ + /* 0x15 */ KEY_4, /* 5 */ + /* 0x16 */ KEY_6, /* 7 */ + /* 0x17 */ KEY_5, /* 6 */ + /* 0x18 */ KEY_EQUAL, /* 13 */ + /* 0x19 */ KEY_9, /* 10 */ + /* 0x1a */ KEY_7, /* 8 */ + /* 0x1b */ KEY_MINUS, /* 12 */ + /* 0x1c */ KEY_8, /* 9 */ + /* 0x1d */ KEY_0, /* 11 */ + /* 0x1e */ KEY_RIGHTBRACE, /* 27 */ + /* 0x1f */ KEY_O, /* 24 */ + /* 0x20 */ KEY_U, /* 22 */ + /* 0x21 */ KEY_LEFTBRACE, /* 26 */ + /* 0x22 */ KEY_I, /* 23 */ + /* 0x23 */ KEY_P, /* 25 */ + /* 0x24 */ KEY_ENTER, /* 28 */ + /* 0x25 */ KEY_L, /* 38 */ + /* 0x26 */ KEY_J, /* 36 */ + /* 0x27 */ KEY_APOSTROPHE, /* 40 */ + /* 0x28 */ KEY_K, /* 37 */ + /* 0x29 */ KEY_SEMICOLON, /* 39 */ + /* 0x2a */ KEY_BACKSLASH, /* 43 */ + /* 0x2b */ KEY_COMMA, /* 51 */ + /* 0x2c */ KEY_SLASH, /* 53 */ + /* 0x2d */ KEY_N, /* 49 */ + /* 0x2e */ KEY_M, /* 50 */ + /* 0x2f */ KEY_DOT, /* 52 */ + /* 0x30 */ KEY_TAB, /* 15 */ + /* 0x31 */ KEY_SPACE, /* 57 */ + /* 0x32 */ KEY_GRAVE, /* 41 */ + /* 0x33 */ KEY_BACKSPACE, /* 14 */ + /* 0x34 */ KEY_KPENTER, /* 96 */ + /* 0x35 */ KEY_ESC, /* 1 */ + /* 0x36 */ KEY_LEFTCTRL, /* 29 */ + /* 0x37 */ KEY_LEFTMETA, /* 125 */ + /* 0x38 */ KEY_LEFTSHIFT, /* 42 */ + /* 0x39 */ KEY_CAPSLOCK, /* 58 */ + /* 0x3a */ KEY_LEFTALT, /* 56 */ + /* 0x3b */ KEY_LEFT, /* 105 */ + /* 0x3c */ KEY_RIGHT, /* 106 */ + /* 0x3d */ KEY_DOWN, /* 108 */ + /* 0x3e */ KEY_UP, /* 103 */ + /* 0x3f */ 0, + /* 0x40 */ 0, + /* 0x41 */ KEY_KPDOT, /* 83 */ + /* 0x42 */ 0, + /* 0x43 */ KEY_KPASTERISK, /* 55 */ + /* 0x44 */ 0, + /* 0x45 */ KEY_KPPLUS, /* 78 */ + /* 0x46 */ 0, + /* 0x47 */ KEY_NUMLOCK, /* 69 */ + /* 0x48 */ 0, + /* 0x49 */ 0, + /* 0x4a */ 0, + /* 0x4b */ KEY_KPSLASH, /* 98 */ + /* 0x4c */ KEY_KPENTER, /* 96 */ + /* 0x4d */ 0, + /* 0x4e */ KEY_KPMINUS, /* 74 */ + /* 0x4f */ 0, + /* 0x50 */ 0, + /* 0x51 */ KEY_KPEQUAL, /* 117 */ + /* 0x52 */ KEY_KP0, /* 82 */ + /* 0x53 */ KEY_KP1, /* 79 */ + /* 0x54 */ KEY_KP2, /* 80 */ + /* 0x55 */ KEY_KP3, /* 81 */ + /* 0x56 */ KEY_KP4, /* 75 */ + /* 0x57 */ KEY_KP5, /* 76 */ + /* 0x58 */ KEY_KP6, /* 77 */ + /* 0x59 */ KEY_KP7, /* 71 */ + /* 0x5a */ 0, + /* 0x5b */ KEY_KP8, /* 72 */ + /* 0x5c */ KEY_KP9, /* 73 */ + /* 0x5d */ KEY_YEN, /* 124 */ + /* 0x5e */ KEY_RO, /* 89 */ + /* 0x5f */ KEY_KPCOMMA, /* 121 */ + /* 0x60 */ KEY_F5, /* 63 */ + /* 0x61 */ KEY_F6, /* 64 */ + /* 0x62 */ KEY_F7, /* 65 */ + /* 0x63 */ KEY_F3, /* 61 */ + /* 0x64 */ KEY_F8, /* 66 */ + /* 0x65 */ KEY_F9, /* 67 */ + /* 0x66 */ KEY_HANJA, /* 123 */ + /* 0x67 */ KEY_F11, /* 87 */ + /* 0x68 */ KEY_HANGUEL, /* 122 */ + /* 0x69 */ KEY_SYSRQ, /* 99 */ + /* 0x6a */ 0, + /* 0x6b */ KEY_SCROLLLOCK, /* 70 */ + /* 0x6c */ 0, + /* 0x6d */ KEY_F10, /* 68 */ + /* 0x6e */ KEY_COMPOSE, /* 127 */ + /* 0x6f */ KEY_F12, /* 88 */ + /* 0x70 */ 0, + /* 0x71 */ KEY_PAUSE, /* 119 */ + /* 0x72 */ KEY_INSERT, /* 110 */ + /* 0x73 */ KEY_HOME, /* 102 */ + /* 0x74 */ KEY_PAGEUP, /* 104 */ + /* 0x75 */ KEY_DELETE, /* 111 */ + /* 0x76 */ KEY_F4, /* 62 */ + /* 0x77 */ KEY_END, /* 107 */ + /* 0x78 */ KEY_F2, /* 60 */ + /* 0x79 */ KEY_PAGEDOWN, /* 109 */ + /* 0x7a */ KEY_F1, /* 59 */ + /* 0x7b */ KEY_RIGHTSHIFT, /* 54 */ + /* 0x7c */ KEY_RIGHTALT, /* 100 */ + /* 0x7d */ KEY_RIGHTCTRL, /* 97 */ + /* 0x7e */ KEY_RIGHTMETA, /* 126 */ + /* 0x7f */ KEY_POWER, /* 116 */ }; struct adbhid { @@ -326,7 +446,7 @@ adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopo input_report_key(&adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1)); input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1)); - if (nb >= 4) + if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD) input_report_key(&adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1)); input_report_rel(&adbhid[id]->input, REL_X, @@ -453,7 +573,7 @@ static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED; static void leds_done(struct adb_request *req) { - int leds, device; + int leds = 0, device = 0, pending = 0; unsigned long flags; spin_lock_irqsave(&leds_lock, flags); @@ -464,11 +584,11 @@ static void leds_done(struct adb_request *req) leds_pending[device] = 0; pending_led_start++; pending_led_start = (pending_led_start < 16) ? pending_led_start : 0; + pending = leds_req_pending; } else leds_req_pending = 0; - spin_unlock_irqrestore(&leds_lock, flags); - if (leds_req_pending) + if (pending) adb_request(&led_request, leds_done, 0, 3, ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds); } diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c index 0e130f598..c5adb05e3 100644 --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -9,6 +9,8 @@ #include #include #include +#include + #include #include #include @@ -21,7 +23,7 @@ static unsigned long anslcd_short_delay = 80; static unsigned long anslcd_long_delay = 3280; -static volatile unsigned char* anslcd_ptr; +static volatile unsigned char __iomem *anslcd_ptr; #undef DEBUG @@ -149,7 +151,7 @@ anslcd_init(void) if (strcmp(node->parent->name, "gc")) return -ENODEV; - anslcd_ptr = (volatile unsigned char*)ioremap(ANSLCD_ADDR, 0x20); + anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20); retval = misc_register(&anslcd_dev); if(retval < 0){ diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 5283a6d11..d4e651b01 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -57,7 +57,7 @@ struct adb_regs { /* Bits in autopoll register */ #define APE 1 /* autopoll enable */ -static volatile struct adb_regs *adb; +static volatile struct adb_regs __iomem *adb; static struct adb_request *current_req, *last_req; static spinlock_t macio_lock = SPIN_LOCK_UNLOCKED; @@ -105,8 +105,7 @@ int macio_init(void) printk("\n"); } #endif - adb = (volatile struct adb_regs *) - ioremap(adbs->addrs->address, sizeof(struct adb_regs)); + adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); out_8(&adb->ctrl.r, 0); out_8(&adb->intr.r, 0); @@ -202,7 +201,7 @@ static irqreturn_t macio_adb_interrupt(int irq, void *arg, struct pt_regs *regs) { int i, n, err; - struct adb_request *req; + struct adb_request *req = NULL; unsigned char ibuf[16]; int ibuf_len = 0; int complete = 0; diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index 1d61a9af6..ad0f620f0 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -32,6 +32,7 @@ #include #endif #include +#include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -713,12 +713,8 @@ static void do_softint(void *private_) if (!tty) return; - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) + tty_wakeup(tty); } static int startup(struct mac_serial * info) @@ -1465,7 +1461,7 @@ static void rs_flush_chars(struct tty_struct *tty) spin_unlock_irqrestore(&info->lock, flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -1478,51 +1474,22 @@ static int rs_write(struct tty_struct * tty, int from_user, if (!tty || !info->xmit_buf || !tmp_buf) return 0; - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&info->lock, flags); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - spin_unlock_irqrestore(&info->lock, flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - spin_lock_irqsave(&info->lock, flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - spin_unlock_irqrestore(&info->lock, flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; + while (1) { + spin_lock_irqsave(&info->lock, flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { spin_unlock_irqrestore(&info->lock, flags); - buf += c; - count -= c; - ret += c; + break; } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->lock, flags); + buf += c; + count -= c; + ret += c; } spin_lock_irqsave(&info->lock, flags); if (info->xmit_cnt && !tty->stopped && !info->tx_stopped @@ -1564,10 +1531,7 @@ static void rs_flush_buffer(struct tty_struct *tty) spin_lock_irqsave(&info->lock, flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; spin_unlock_irqrestore(&info->lock, flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -1994,16 +1958,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; info->tty = 0; if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -2048,8 +2010,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) if (timeout) char_time = min_t(unsigned long, char_time, timeout); while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index aa0719775..9f0e47d28 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -45,7 +45,7 @@ #endif #define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2)) -#define MB_FCR8(bay, r) (((volatile u8*)((bay)->base)) + (r)) +#define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r)) #define MB_IN32(bay,r) (in_le32(MB_FCR32(bay,r))) #define MB_OUT32(bay,r,v) (out_le32(MB_FCR32(bay,r), (v))) @@ -67,7 +67,7 @@ struct mb_ops { }; struct media_bay_info { - volatile u32* base; + u32 __iomem *base; int content_id; int state; int last_value; @@ -80,7 +80,7 @@ struct media_bay_info { int sleeping; struct semaphore lock; #ifdef CONFIG_BLK_DEV_IDE - unsigned long cd_base; + void __iomem *cd_base; int cd_index; int cd_irq; int cd_retry; @@ -443,7 +443,7 @@ int __pmac check_media_bay_by_base(unsigned long base, int what) int i; for (i=0; ilock); - bay->cd_base = base; + bay->cd_base = (void __iomem *) base; bay->cd_irq = irq; if ((MB_CD != bay->content_id) || bay->state != mb_up) { @@ -553,7 +553,7 @@ static void __pmac media_bay_step(int i) break; case mb_ide_waiting: - if (bay->cd_base == 0) { + if (bay->cd_base == NULL) { bay->timer = 0; bay->state = mb_up; MBDBG("mediabay%d: up before IDE init\n", i); @@ -651,7 +651,7 @@ static int __pmac media_bay_task(void *x) static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_match *match) { struct media_bay_info* bay; - volatile u32 *regbase; + u32 __iomem *regbase; struct device_node *ofnode; int i; @@ -664,7 +664,8 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma /* Media bay registers are located at the beginning of the * mac-io chip, we get the parent address for now (hrm...) */ - regbase = (volatile u32 *)ioremap(ofnode->parent->addrs[0].address, 0x100); + regbase = (u32 __iomem *) + ioremap(ofnode->parent->addrs[0].address, 0x100); if (regbase == NULL) { macio_release_resources(mdev); return -ENOMEM; @@ -713,13 +714,13 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state) { struct media_bay_info *bay = macio_get_drvdata(mdev); - if (state != mdev->ofdev.dev.power_state && state >= 2) { + if (state != mdev->ofdev.dev.power.power_state && state == PM_SUSPEND_MEM) { down(&bay->lock); bay->sleeping = 1; set_mb_power(bay, 0); up(&bay->lock); msleep(MB_POLL_DELAY); - mdev->ofdev.dev.power_state = state; + mdev->ofdev.dev.power.power_state = state; } return 0; } @@ -728,8 +729,8 @@ static int __pmac media_bay_resume(struct macio_dev *mdev) { struct media_bay_info *bay = macio_get_drvdata(mdev); - if (mdev->ofdev.dev.power_state != 0) { - mdev->ofdev.dev.power_state = 0; + if (mdev->ofdev.dev.power.power_state != 0) { + mdev->ofdev.dev.power.power_state = 0; /* We re-enable the bay using it's previous content only if it did not change. Note those bozo timings, diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 37f06c81d..cce6b3642 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include + #include #include #include @@ -49,32 +53,37 @@ static int limit_adjust = 0; static int fan_speed = -1; MODULE_AUTHOR("Colin Leroy "); -MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and Powerbook G4 Alu"); +MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and " + "Powerbook G4 Alu"); MODULE_LICENSE("GPL"); -MODULE_PARM(limit_adjust,"i"); -MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50°C cpu, 70°C gpu) by N °C."); -MODULE_PARM(fan_speed,"i"); -MODULE_PARM_DESC(fan_speed,"Specify fan speed (0-255) when lim < temp < lim+8 (default 128)"); +module_param(limit_adjust, int, 0644); +MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) " + "by N degrees."); + +module_param(fan_speed, int, 0644); +MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) " + "(default 64)"); struct thermostat { struct i2c_client clt; + u8 temps[3]; u8 cached_temp[3]; u8 initial_limits[3]; u8 limits[3]; int last_speed[2]; - int overriding[2]; + int last_var[2]; }; static enum {ADT7460, ADT7467} therm_type; static int therm_bus, therm_address; static struct of_device * of_dev; static struct thermostat* thermostat; -static pid_t monitor_thread_id; -static int monitor_running; -static struct completion monitor_task_compl; +static struct task_struct *thread_therm = NULL; + +static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, + int busno); -static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno); static void write_both_fan_speed(struct thermostat *th, int speed); static void write_fan_speed(struct thermostat *th, int speed, int fan); @@ -136,15 +145,15 @@ detach_thermostat(struct i2c_adapter *adapter) th = thermostat; - if (monitor_running) { - monitor_running = 0; - wait_for_completion(&monitor_task_compl); + if (thread_therm != NULL) { + kthread_stop(thread_therm); } - printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d," - " to %d, %d, %d, (°C)\n", + printk(KERN_INFO "adt746x: Putting max temperatures back from " + "%d, %d, %d to %d, %d, %d\n", th->limits[0], th->limits[1], th->limits[2], - th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]); + th->initial_limits[0], th->initial_limits[1], + th->initial_limits[2]); for (i = 0; i < 3; i++) write_reg(th, LIMIT_REG[i], th->initial_limits[i]); @@ -161,11 +170,11 @@ detach_thermostat(struct i2c_adapter *adapter) } static struct i2c_driver thermostat_driver = { - .name ="Apple Thermostat ADT746x", - .id =0xDEAD7467, - .flags =I2C_DF_NOTIFY, - .attach_adapter =&attach_thermostat, - .detach_adapter =&detach_thermostat, + .owner = THIS_MODULE, + .name = "therm_adt746x", + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach_thermostat, + .detach_adapter = detach_thermostat, }; static int read_fan_speed(struct thermostat *th, u8 addr) @@ -178,7 +187,8 @@ static int read_fan_speed(struct thermostat *th, u8 addr) tmp[0] = read_reg(th, addr + 1); res = tmp[1] + (tmp[0] << 8); - return (90000*60)/res; + /* "a value of 0xffff means that the fan has stopped" */ + return (res == 0xffff ? 0 : (90000*60)/res); } static void write_both_fan_speed(struct thermostat *th, int speed) @@ -202,11 +212,11 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) if (th->last_speed[fan] != speed) { if (speed == -1) - printk(KERN_INFO "adt746x: Setting speed to: automatic for %s fan.\n", - fan?"GPU":"CPU"); + printk(KERN_DEBUG "adt746x: Setting speed to automatic " + "for %s fan.\n", fan?"GPU":"CPU"); else - printk(KERN_INFO "adt746x: Setting speed to: %d for %s fan.\n", - speed, fan?"GPU":"CPU"); + printk(KERN_DEBUG "adt746x: Setting speed to %d " + "for %s fan.\n", speed, fan?"GPU":"CPU"); } else return; @@ -217,8 +227,11 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) } else { /* back to automatic */ if(therm_type == ADT7460) { - manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK); - write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]); + manual = read_reg(th, + MANUAL_MODE[fan]) & (~MANUAL_MASK); + + write_reg(th, + MANUAL_MODE[fan], manual|REM_CONTROL[fan]); } else { manual = read_reg(th, MANUAL_MODE[fan]); write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); @@ -228,105 +241,117 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) th->last_speed[fan] = speed; } -static int monitor_task(void *arg) +static void read_sensors(struct thermostat *th) { - struct thermostat* th = arg; - u8 temps[3]; - u8 lims[3]; - int i; + int i = 0; + + for (i = 0; i < 3; i++) + th->temps[i] = read_reg(th, TEMP_REG[i]); +} + #ifdef DEBUG - int mfan_speed; -#endif - - lock_kernel(); - daemonize("kfand"); - unlock_kernel(); - strcpy(current->comm, "thermostat"); - monitor_running = 1; - - while(monitor_running) - { - msleep(2000); - - /* Check status */ - /* local : chip */ - /* remote 1: CPU ?*/ - /* remote 2: GPU ?*/ -#ifndef DEBUG - if (fan_speed != -1) { +static void display_stats(struct thermostat *th) +{ + if (th->temps[0] != th->cached_temp[0] + || th->temps[1] != th->cached_temp[1] + || th->temps[2] != th->cached_temp[2]) { + printk(KERN_INFO "adt746x: Temperature infos:" + " thermostats: %d,%d,%d;" + " limits: %d,%d,%d;" + " fan speed: %d RPM\n", + th->temps[0], th->temps[1], th->temps[2], + th->limits[0], th->limits[1], th->limits[2], + read_fan_speed(th, FAN_SPEED[0])); + } + th->cached_temp[0] = th->temps[0]; + th->cached_temp[1] = th->temps[1]; + th->cached_temp[2] = th->temps[2]; +} #endif - for (i = 0; i < 3; i++) { - temps[i] = read_reg(th, TEMP_REG[i]); - lims[i] = th->limits[i]; + +static void update_fans_speed (struct thermostat *th) +{ + int lastvar = 0; /* last variation, for iBook */ + int i = 0; + + /* we don't care about local sensor, so we start at sensor 1 */ + for (i = 1; i < 3; i++) { + int started = 0; + int fan_number = (therm_type == ADT7460 && i == 2); + int var = th->temps[i] - th->limits[i]; + + if (var > -1) { + int step = (255 - fan_speed) / 7; + int new_speed = 0; + + /* hysteresis : change fan speed only if variation is + * more than two degrees */ + if (abs(var - th->last_var[fan_number]) < 2) + continue; + + started = 1; + new_speed = fan_speed + ((var-1)*step); + + if (new_speed < fan_speed) + new_speed = fan_speed; + if (new_speed > 255) + new_speed = 255; + + printk(KERN_DEBUG "adt746x: setting fans speed to %d " + "(limit exceeded by %d on %s) \n", + new_speed, var, + fan_number?"GPU/pwr":"CPU"); + write_both_fan_speed(th, new_speed); + th->last_var[fan_number] = var; + } else if (var < -2) { + /* don't stop fan if GPU/power is cold and CPU is not + * so cold (lastvar >= -1) */ + if (i == 2 && lastvar < -1) { + if (th->last_speed[fan_number] != 0) + printk(KERN_DEBUG "adt746x: Stopping " + "fans.\n"); + write_both_fan_speed(th, 0); } -#ifndef DEBUG } + + lastvar = var; + + if (started) + return; /* we don't want to re-stop the fan + * if CPU is heating and GPU/power is not */ + } +} + +static int monitor_task(void *arg) +{ + struct thermostat* th = arg; + + while(!kthread_should_stop()) { + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); + + msleep_interruptible(2000); + +#ifndef DEBUG + if (fan_speed != -1) + read_sensors(th); +#else + read_sensors(th); #endif - if (fan_speed != -1) { - int lastvar = 0; /* for iBook */ - for (i = 1; i < 3; i++) { /* we don't care about local sensor */ - int started = 0; - int fan_number = (therm_type == ADT7460 && i == 2); - int var = temps[i] - lims[i]; - if (var > 8) { - if (th->overriding[fan_number] == 0) - printk(KERN_INFO "adt746x: Limit exceeded by %d°C, overriding specified fan speed for %s.\n", - var, fan_number?"GPU":"CPU"); - th->overriding[fan_number] = 1; - write_fan_speed(th, 255, fan_number); - started = 1; - } else if ((!th->overriding[fan_number] || var < 6) && var > 0) { - if (th->overriding[fan_number] == 1) - printk(KERN_INFO "adt746x: Limit exceeded by %d°C, setting speed to specified for %s.\n", - var, fan_number?"GPU":"CPU"); - th->overriding[fan_number] = 0; - write_fan_speed(th, fan_speed, fan_number); - started = 1; - } else if (var < -1) { - /* don't stop iBook fan if GPU is cold and CPU is not - * so cold (lastvar >= -1) */ - if (therm_type == ADT7460 || lastvar < -1 || i == 1) { - if (th->last_speed[fan_number] != 0) - printk(KERN_INFO "adt746x: Stopping %s fan.\n", - fan_number?"GPU":"CPU"); - write_fan_speed(th, 0, fan_number); - } - } - - lastvar = var; - - if (started && therm_type == ADT7467) - break; /* we don't want to re-stop the fan - * if CPU is heating and GPU is not */ - } - } + + if (fan_speed != -1) + update_fans_speed(th); + #ifdef DEBUG - mfan_speed = read_fan_speed(th, FAN_SPEED[0]); - /* only one fan in the iBook G4 */ - - if (temps[0] != th->cached_temp[0] - || temps[1] != th->cached_temp[1] - || temps[2] != th->cached_temp[2]) { - printk(KERN_INFO "adt746x: Temperature infos:" - " thermostats: %d,%d,%d °C;" - " limits: %d,%d,%d °C;" - " fan speed: %d RPM\n", - temps[0], temps[1], temps[2], - lims[0], lims[1], lims[2], - mfan_speed); - } - th->cached_temp[0] = temps[0]; - th->cached_temp[1] = temps[1]; - th->cached_temp[2] = temps[2]; -#endif + display_stats(th); +#endif + } - complete_and_exit(&monitor_task_compl, 0); return 0; } -static void -set_limit(struct thermostat *th, int i) +static void set_limit(struct thermostat *th, int i) { /* Set CPU limit higher to avoid powerdowns */ th->limits[i] = default_limits_chip[i] + limit_adjust; @@ -335,9 +360,9 @@ set_limit(struct thermostat *th, int i) /* set our limits to normal */ th->limits[i] = default_limits_local[i] + limit_adjust; } - -static int -attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno) + +static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, + int busno) { struct thermostat* th; int rc; @@ -345,27 +370,31 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno) if (thermostat) return 0; - th = (struct thermostat *)kmalloc(sizeof(struct thermostat), GFP_KERNEL); + + th = (struct thermostat *) + kmalloc(sizeof(struct thermostat), GFP_KERNEL); + if (!th) return -ENOMEM; + memset(th, 0, sizeof(*th)); th->clt.addr = addr; th->clt.adapter = adapter; th->clt.driver = &thermostat_driver; - th->clt.id = 0xDEAD7467; strcpy(th->clt.name, "thermostat"); rc = read_reg(th, 0); if (rc < 0) { - printk(KERN_ERR "adt746x: Thermostat failed to read config from bus %d !\n", - busno); + printk(KERN_ERR "adt746x: Thermostat failed to read config " + "from bus %d !\n", + busno); kfree(th); return -ENODEV; } + /* force manual control to start the fan quieter */ - if (fan_speed == -1) - fan_speed=128; + fan_speed = 64; if(therm_type == ADT7460) { printk(KERN_INFO "adt746x: ADT7460 initializing\n"); @@ -380,14 +409,16 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno) } printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d" - " to %d, %d, %d (°C)\n", - th->initial_limits[0], th->initial_limits[1], th->initial_limits[2], - th->limits[0], th->limits[1], th->limits[2]); + " to %d, %d, %d\n", + th->initial_limits[0], th->initial_limits[1], + th->initial_limits[2], th->limits[0], th->limits[1], + th->limits[2]); thermostat = th; if (i2c_attach_client(&th->clt)) { - printk("adt746x: Thermostat failed to attach client !\n"); + printk(KERN_INFO "adt746x: Thermostat failed to attach " + "client !\n"); thermostat = NULL; kfree(th); return -ENODEV; @@ -396,17 +427,24 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno) /* be sure to really write fan speed the first time */ th->last_speed[0] = -2; th->last_speed[1] = -2; - + th->last_var[0] = -80; + th->last_var[1] = -80; + if (fan_speed != -1) { + /* manual mode, stop fans */ write_both_fan_speed(th, 0); } else { + /* automatic mode */ write_both_fan_speed(th, -1); } - init_completion(&monitor_task_compl); - - monitor_thread_id = kernel_thread(monitor_task, th, - SIGCHLD | CLONE_KERNEL); + thread_therm = kthread_run(monitor_task, th, "kfand"); + + if (thread_therm == ERR_PTR(-ENOMEM)) { + printk(KERN_INFO "adt746x: Kthread creation failed\n"); + thread_therm = NULL; + return -ENOMEM; + } return 0; } @@ -417,17 +455,21 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno) * choice but implement a bunch of them... * */ -#define BUILD_SHOW_FUNC_DEG(name, data) \ -static ssize_t show_##name(struct device *dev, char *buf) \ -{ \ - return sprintf(buf, "%d°C\n", data); \ -} #define BUILD_SHOW_FUNC_INT(name, data) \ static ssize_t show_##name(struct device *dev, char *buf) \ { \ return sprintf(buf, "%d\n", data); \ } +#define BUILD_SHOW_FUNC_FAN(name, data) \ +static ssize_t show_##name(struct device *dev, char *buf) \ +{ \ + return sprintf(buf, "%d (%d rpm)\n", \ + thermostat->last_speed[data], \ + read_fan_speed(thermostat, FAN_SPEED[data]) \ + ); \ +} + #define BUILD_STORE_FUNC_DEG(name, data) \ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ { \ @@ -448,19 +490,19 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \ val = simple_strtoul(buf, NULL, 10); \ if (val < 0 || val > 255) \ return -EINVAL; \ - printk(KERN_INFO "Setting fan speed to %d\n", val); \ + printk(KERN_INFO "Setting specified fan speed to %d\n", val); \ data = val; \ return n; \ } -BUILD_SHOW_FUNC_DEG(cpu_temperature, (read_reg(thermostat, TEMP_REG[1]))) -BUILD_SHOW_FUNC_DEG(gpu_temperature, (read_reg(thermostat, TEMP_REG[2]))) -BUILD_SHOW_FUNC_DEG(cpu_limit, thermostat->limits[1]) -BUILD_SHOW_FUNC_DEG(gpu_limit, thermostat->limits[2]) +BUILD_SHOW_FUNC_INT(cpu_temperature, (read_reg(thermostat, TEMP_REG[1]))) +BUILD_SHOW_FUNC_INT(gpu_temperature, (read_reg(thermostat, TEMP_REG[2]))) +BUILD_SHOW_FUNC_INT(cpu_limit, thermostat->limits[1]) +BUILD_SHOW_FUNC_INT(gpu_limit, thermostat->limits[2]) BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed) -BUILD_SHOW_FUNC_INT(cpu_fan_speed, (read_fan_speed(thermostat, FAN_SPEED[0]))) -BUILD_SHOW_FUNC_INT(gpu_fan_speed, (read_fan_speed(thermostat, FAN_SPEED[1]))) +BUILD_SHOW_FUNC_FAN(cpu_fan_speed, 0) +BUILD_SHOW_FUNC_FAN(gpu_fan_speed, 1) BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed) BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust) @@ -509,8 +551,9 @@ thermostat_init(void) therm_bus = ((*prop) >> 8) & 0x0f; therm_address = ((*prop) & 0xff) >> 1; - printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, limit_adjust: %d, fan_speed: %d\n", - therm_bus, therm_address, limit_adjust, fan_speed); + printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, " + "limit_adjust: %d, fan_speed: %d\n", + therm_bus, therm_address, limit_adjust, fan_speed); of_dev = of_platform_device_create(np, "temperatures"); @@ -547,8 +590,11 @@ thermostat_exit(void) device_remove_file(&of_dev->dev, &dev_attr_limit_adjust); device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed); device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed); + if(therm_type == ADT7460) - device_remove_file(&of_dev->dev, &dev_attr_gpu_fan_speed); + device_remove_file(&of_dev->dev, + &dev_attr_gpu_fan_speed); + of_device_unregister(of_dev); } i2c_del_driver(&thermostat_driver); diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 32333f27d..3c606ef98 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -46,6 +46,9 @@ * overtemp conditions so userland can take some policy * decisions, like slewing down CPUs * - Deal with fan and i2c failures in a better way + * - Maybe do a generic PID based on params used for + * U3 and Drives ? + * - Add RackMac3,1 support (XServe g5) * * History: * @@ -73,6 +76,15 @@ * values in the configuration register * - Switch back to use of target fan speed for PID, thus lowering * pressure on i2c + * + * Oct. 20, 2004 : 1.1 + * - Add device-tree lookup for fan IDs, should detect liquid cooling + * pumps when present + * - Enable driver for PowerMac7,3 machines + * - Split the U3/Backside cooling on U3 & U3H versions as Darwin does + * - Add new CPU cooling algorithm for machines with liquid cooling + * - Workaround for some PowerMac7,3 with empty "fan" node in the devtree + * - Fix a signed/unsigned compare issue in some PID loops */ #include @@ -101,7 +113,7 @@ #include "therm_pm72.h" -#define VERSION "0.9" +#define VERSION "1.1" #undef DEBUG @@ -121,15 +133,99 @@ static struct i2c_adapter * u3_0; static struct i2c_adapter * u3_1; static struct i2c_client * fcu; static struct cpu_pid_state cpu_state[2]; +static struct basckside_pid_params backside_params; static struct backside_pid_state backside_state; static struct drives_pid_state drives_state; static int state; static int cpu_count; +static int cpu_pid_type; static pid_t ctrl_task; static struct completion ctrl_complete; static int critical_state; static DECLARE_MUTEX(driver_lock); +/* + * We have 2 types of CPU PID control. One is "split" old style control + * for intake & exhaust fans, the other is "combined" control for both + * CPUs that also deals with the pumps when present. To be "compatible" + * with OS X at this point, we only use "COMBINED" on the machines that + * are identified as having the pumps (though that identification is at + * least dodgy). Ultimately, we could probably switch completely to this + * algorithm provided we hack it to deal with the UP case + */ +#define CPU_PID_TYPE_SPLIT 0 +#define CPU_PID_TYPE_COMBINED 1 + +/* + * This table describes all fans in the FCU. The "id" and "type" values + * are defaults valid for all earlier machines. Newer machines will + * eventually override the table content based on the device-tree + */ +struct fcu_fan_table +{ + char* loc; /* location code */ + int type; /* 0 = rpm, 1 = pwm, 2 = pump */ + int id; /* id or -1 */ +}; + +#define FCU_FAN_RPM 0 +#define FCU_FAN_PWM 1 + +#define FCU_FAN_ABSENT_ID -1 + +#define FCU_FAN_COUNT ARRAY_SIZE(fcu_fans) + +struct fcu_fan_table fcu_fans[] = { + [BACKSIDE_FAN_PWM_INDEX] = { + .loc = "BACKSIDE", + .type = FCU_FAN_PWM, + .id = BACKSIDE_FAN_PWM_DEFAULT_ID, + }, + [DRIVES_FAN_RPM_INDEX] = { + .loc = "DRIVE BAY", + .type = FCU_FAN_RPM, + .id = DRIVES_FAN_RPM_DEFAULT_ID, + }, + [SLOTS_FAN_PWM_INDEX] = { + .loc = "SLOT", + .type = FCU_FAN_PWM, + .id = SLOTS_FAN_PWM_DEFAULT_ID, + }, + [CPUA_INTAKE_FAN_RPM_INDEX] = { + .loc = "CPU A INTAKE", + .type = FCU_FAN_RPM, + .id = CPUA_INTAKE_FAN_RPM_DEFAULT_ID, + }, + [CPUA_EXHAUST_FAN_RPM_INDEX] = { + .loc = "CPU A EXHAUST", + .type = FCU_FAN_RPM, + .id = CPUA_EXHAUST_FAN_RPM_DEFAULT_ID, + }, + [CPUB_INTAKE_FAN_RPM_INDEX] = { + .loc = "CPU B INTAKE", + .type = FCU_FAN_RPM, + .id = CPUB_INTAKE_FAN_RPM_DEFAULT_ID, + }, + [CPUB_EXHAUST_FAN_RPM_INDEX] = { + .loc = "CPU B EXHAUST", + .type = FCU_FAN_RPM, + .id = CPUB_EXHAUST_FAN_RPM_DEFAULT_ID, + }, + /* pumps aren't present by default, have to be looked up in the + * device-tree + */ + [CPUA_PUMP_RPM_INDEX] = { + .loc = "CPU A PUMP", + .type = FCU_FAN_RPM, + .id = FCU_FAN_ABSENT_ID, + }, + [CPUB_PUMP_RPM_INDEX] = { + .loc = "CPU B PUMP", + .type = FCU_FAN_RPM, + .id = FCU_FAN_ABSENT_ID, + }, +}; + /* * i2c_driver structure to attach to the host i2c controller */ @@ -139,8 +235,8 @@ static int therm_pm72_detach(struct i2c_adapter *adapter); static struct i2c_driver therm_pm72_driver = { + .owner = THIS_MODULE, .name = "therm_pm72", - .id = 0xDEADBEEF, .flags = I2C_DF_NOTIFY, .attach_adapter = therm_pm72_attach, .detach_adapter = therm_pm72_detach, @@ -170,7 +266,6 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name) clt->addr = (id >> 1) & 0x7f; clt->adapter = adap; clt->driver = &therm_pm72_driver; - clt->id = 0xDEADBEEF; strncpy(clt->name, name, I2C_NAME_SIZE-1); if (i2c_attach_client(clt)) { @@ -331,10 +426,16 @@ static int start_fcu(void) return 0; } -static int set_rpm_fan(int fan, int rpm) +static int set_rpm_fan(int fan_index, int rpm) { unsigned char buf[2]; - int rc; + int rc, id; + + if (fcu_fans[fan_index].type != FCU_FAN_RPM) + return -EINVAL; + id = fcu_fans[fan_index].id; + if (id == FCU_FAN_ABSENT_ID) + return -EINVAL; if (rpm < 300) rpm = 300; @@ -342,43 +443,55 @@ static int set_rpm_fan(int fan, int rpm) rpm = 8191; buf[0] = rpm >> 5; buf[1] = rpm << 3; - rc = fan_write_reg(0x10 + (fan * 2), buf, 2); + rc = fan_write_reg(0x10 + (id * 2), buf, 2); if (rc < 0) return -EIO; return 0; } -static int get_rpm_fan(int fan, int programmed) +static int get_rpm_fan(int fan_index, int programmed) { unsigned char failure; unsigned char active; unsigned char buf[2]; - int rc, reg_base; + int rc, id, reg_base; + + if (fcu_fans[fan_index].type != FCU_FAN_RPM) + return -EINVAL; + id = fcu_fans[fan_index].id; + if (id == FCU_FAN_ABSENT_ID) + return -EINVAL; rc = fan_read_reg(0xb, &failure, 1); if (rc != 1) return -EIO; - if ((failure & (1 << fan)) != 0) + if ((failure & (1 << id)) != 0) return -EFAULT; rc = fan_read_reg(0xd, &active, 1); if (rc != 1) return -EIO; - if ((active & (1 << fan)) == 0) + if ((active & (1 << id)) == 0) return -ENXIO; /* Programmed value or real current speed */ reg_base = programmed ? 0x10 : 0x11; - rc = fan_read_reg(reg_base + (fan * 2), buf, 2); + rc = fan_read_reg(reg_base + (id * 2), buf, 2); if (rc != 2) return -EIO; return (buf[0] << 5) | buf[1] >> 3; } -static int set_pwm_fan(int fan, int pwm) +static int set_pwm_fan(int fan_index, int pwm) { unsigned char buf[2]; - int rc; + int rc, id; + + if (fcu_fans[fan_index].type != FCU_FAN_PWM) + return -EINVAL; + id = fcu_fans[fan_index].id; + if (id == FCU_FAN_ABSENT_ID) + return -EINVAL; if (pwm < 10) pwm = 10; @@ -386,32 +499,38 @@ static int set_pwm_fan(int fan, int pwm) pwm = 100; pwm = (pwm * 2559) / 1000; buf[0] = pwm; - rc = fan_write_reg(0x30 + (fan * 2), buf, 1); + rc = fan_write_reg(0x30 + (id * 2), buf, 1); if (rc < 0) return rc; return 0; } -static int get_pwm_fan(int fan) +static int get_pwm_fan(int fan_index) { unsigned char failure; unsigned char active; unsigned char buf[2]; - int rc; + int rc, id; + + if (fcu_fans[fan_index].type != FCU_FAN_PWM) + return -EINVAL; + id = fcu_fans[fan_index].id; + if (id == FCU_FAN_ABSENT_ID) + return -EINVAL; rc = fan_read_reg(0x2b, &failure, 1); if (rc != 1) return -EIO; - if ((failure & (1 << fan)) != 0) + if ((failure & (1 << id)) != 0) return -EFAULT; rc = fan_read_reg(0x2d, &active, 1); if (rc != 1) return -EIO; - if ((active & (1 << fan)) == 0) + if ((active & (1 << id)) == 0) return -ENXIO; /* Programmed value or real current speed */ - rc = fan_read_reg(0x30 + (fan * 2), buf, 1); + rc = fan_read_reg(0x30 + (id * 2), buf, 1); if (rc != 1) return -EIO; @@ -513,80 +632,84 @@ static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); /* * CPUs fans control loop */ -static void do_monitor_cpu(struct cpu_pid_state *state) + +static int do_read_one_cpu_values(struct cpu_pid_state *state, s32 *temp, s32 *power) { - s32 temp, voltage, current_a, power, power_target; - s32 integral, derivative, proportional, adj_in_target, sval; - s64 integ_p, deriv_p, prop_p, sum; - int i, intake, rc; + s32 ltemp, volts, amps; + int rc = 0; - DBG("cpu %d:\n", state->index); + /* Default (in case of error) */ + *temp = state->cur_temp; + *power = state->cur_power; /* Read current fan status */ if (state->index == 0) - rc = get_rpm_fan(CPUA_EXHAUST_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED); + rc = get_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED); else - rc = get_rpm_fan(CPUB_EXHAUST_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED); + rc = get_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED); if (rc < 0) { - printk(KERN_WARNING "Error %d reading CPU %d exhaust fan !\n", - rc, state->index); - /* XXX What do we do now ? */ - } else + /* XXX What do we do now ? Nothing for now, keep old value, but + * return error upstream + */ + DBG(" cpu %d, fan reading error !\n", state->index); + } else { state->rpm = rc; - DBG(" current rpm: %d\n", state->rpm); + DBG(" cpu %d, exhaust RPM: %d\n", state->index, state->rpm); + } /* Get some sensor readings and scale it */ - temp = read_smon_adc(state, 1); - if (temp == -1) { + ltemp = read_smon_adc(state, 1); + if (ltemp == -1) { + /* XXX What do we do now ? */ state->overtemp++; - return; + if (rc == 0) + rc = -EIO; + DBG(" cpu %d, temp reading error !\n", state->index); + } else { + /* Fixup temperature according to diode calibration + */ + DBG(" cpu %d, temp raw: %04x, m_diode: %04x, b_diode: %04x\n", + state->index, + ltemp, state->mpu.mdiode, state->mpu.bdiode); + *temp = ((s32)ltemp * (s32)state->mpu.mdiode + ((s32)state->mpu.bdiode << 12)) >> 2; + state->last_temp = *temp; + DBG(" temp: %d.%03d\n", FIX32TOPRINT((*temp))); } - voltage = read_smon_adc(state, 3); - current_a = read_smon_adc(state, 4); - /* Fixup temperature according to diode calibration + /* + * Read voltage & current and calculate power */ - DBG(" temp raw: %04x, m_diode: %04x, b_diode: %04x\n", - temp, state->mpu.mdiode, state->mpu.bdiode); - temp = ((s32)temp * (s32)state->mpu.mdiode + ((s32)state->mpu.bdiode << 12)) >> 2; - state->last_temp = temp; - DBG(" temp: %d.%03d\n", FIX32TOPRINT(temp)); + volts = read_smon_adc(state, 3); + amps = read_smon_adc(state, 4); - /* Check tmax, increment overtemp if we are there. At tmax+8, we go - * full blown immediately and try to trigger a shutdown - */ - if (temp >= ((state->mpu.tmax + 8) << 16)) { - printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum" - " (%d) !\n", - state->index, temp >> 16); - state->overtemp = CPU_MAX_OVERTEMP; - } else if (temp > (state->mpu.tmax << 16)) - state->overtemp++; - else - state->overtemp = 0; - if (state->overtemp >= CPU_MAX_OVERTEMP) - critical_state = 1; - if (state->overtemp > 0) { - state->rpm = state->mpu.rmaxn_exhaust_fan; - state->intake_rpm = intake = state->mpu.rmaxn_intake_fan; - goto do_set_fans; - } - - /* Scale other sensor values according to fixed scales + /* Scale voltage and current raw sensor values according to fixed scales * obtained in Darwin and calculate power from I and V */ - state->voltage = voltage *= ADC_CPU_VOLTAGE_SCALE; - state->current_a = current_a *= ADC_CPU_CURRENT_SCALE; - power = (((u64)current_a) * ((u64)voltage)) >> 16; + volts *= ADC_CPU_VOLTAGE_SCALE; + amps *= ADC_CPU_CURRENT_SCALE; + *power = (((u64)volts) * ((u64)amps)) >> 16; + state->voltage = volts; + state->current_a = amps; + state->last_power = *power; + + DBG(" cpu %d, current: %d.%03d, voltage: %d.%03d, power: %d.%03d W\n", + state->index, FIX32TOPRINT(state->current_a), + FIX32TOPRINT(state->voltage), FIX32TOPRINT(*power)); + + return 0; +} + +static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power) +{ + s32 power_target, integral, derivative, proportional, adj_in_target, sval; + s64 integ_p, deriv_p, prop_p, sum; + int i; /* Calculate power target value (could be done once for all) * and convert to a 16.16 fp number */ power_target = ((u32)(state->mpu.pmaxh - state->mpu.padjmax)) << 16; - - DBG(" current: %d.%03d, voltage: %d.%03d\n", - FIX32TOPRINT(current_a), FIX32TOPRINT(voltage)); - DBG(" power: %d.%03d W, target: %d.%03d, error: %d.%03d\n", FIX32TOPRINT(power), + DBG(" power target: %d.%03d, error: %d.%03d\n", FIX32TOPRINT(power_target), FIX32TOPRINT(power_target - power)); /* Store temperature and power in history array */ @@ -626,7 +749,7 @@ static void do_monitor_cpu(struct cpu_pid_state *state) * input target is mpu.ttarget, input max is mpu.tmax */ integ_p = ((s64)state->mpu.pid_gr) * (s64)integral; - DBG(" integ_p: %d\n", (int)(deriv_p >> 36)); + DBG(" integ_p: %d\n", (int)(integ_p >> 36)); sval = (state->mpu.tmax << 16) - ((integ_p >> 20) & 0xffffffff); adj_in_target = (state->mpu.ttarget << 16); if (adj_in_target > sval) @@ -655,15 +778,136 @@ static void do_monitor_cpu(struct cpu_pid_state *state) DBG(" sum: %d\n", (int)sum); state->rpm += (s32)sum; - if (state->rpm < state->mpu.rminn_exhaust_fan) + if (state->rpm < (int)state->mpu.rminn_exhaust_fan) state->rpm = state->mpu.rminn_exhaust_fan; - if (state->rpm > state->mpu.rmaxn_exhaust_fan) + if (state->rpm > (int)state->mpu.rmaxn_exhaust_fan) + state->rpm = state->mpu.rmaxn_exhaust_fan; +} + +static void do_monitor_cpu_combined(void) +{ + struct cpu_pid_state *state0 = &cpu_state[0]; + struct cpu_pid_state *state1 = &cpu_state[1]; + s32 temp0, power0, temp1, power1; + s32 temp_combi, power_combi; + int rc, intake, pump; + + rc = do_read_one_cpu_values(state0, &temp0, &power0); + if (rc < 0) { + /* XXX What do we do now ? */ + } + state1->overtemp = 0; + rc = do_read_one_cpu_values(state1, &temp1, &power1); + if (rc < 0) { + /* XXX What do we do now ? */ + } + if (state1->overtemp) + state0->overtemp++; + + temp_combi = max(temp0, temp1); + power_combi = max(power0, power1); + + /* Check tmax, increment overtemp if we are there. At tmax+8, we go + * full blown immediately and try to trigger a shutdown + */ + if (temp_combi >= ((state0->mpu.tmax + 8) << 16)) { + printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n", + temp_combi >> 16); + state0->overtemp = CPU_MAX_OVERTEMP; + } else if (temp_combi > (state0->mpu.tmax << 16)) + state0->overtemp++; + else + state0->overtemp = 0; + if (state0->overtemp >= CPU_MAX_OVERTEMP) + critical_state = 1; + if (state0->overtemp > 0) { + state0->rpm = state0->mpu.rmaxn_exhaust_fan; + state0->intake_rpm = intake = state0->mpu.rmaxn_intake_fan; + pump = CPU_PUMP_OUTPUT_MAX; + goto do_set_fans; + } + + /* Do the PID */ + do_cpu_pid(state0, temp_combi, power_combi); + + /* Calculate intake fan speed */ + intake = (state0->rpm * CPU_INTAKE_SCALE) >> 16; + if (intake < (int)state0->mpu.rminn_intake_fan) + intake = state0->mpu.rminn_intake_fan; + if (intake > (int)state0->mpu.rmaxn_intake_fan) + intake = state0->mpu.rmaxn_intake_fan; + state0->intake_rpm = intake; + + /* Calculate pump speed */ + pump = (state0->rpm * CPU_PUMP_OUTPUT_MAX) / + state0->mpu.rmaxn_exhaust_fan; + if (pump > CPU_PUMP_OUTPUT_MAX) + pump = CPU_PUMP_OUTPUT_MAX; + if (pump < CPU_PUMP_OUTPUT_MIN) + pump = CPU_PUMP_OUTPUT_MIN; + + do_set_fans: + /* We copy values from state 0 to state 1 for /sysfs */ + state1->rpm = state0->rpm; + state1->intake_rpm = state0->intake_rpm; + + DBG("** CPU %d RPM: %d Ex, %d, Pump: %d, In, overtemp: %d\n", + state1->index, (int)state1->rpm, intake, pump, state1->overtemp); + + /* We should check for errors, shouldn't we ? But then, what + * do we do once the error occurs ? For FCU notified fan + * failures (-EFAULT) we probably want to notify userland + * some way... + */ + set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake); + set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state0->rpm); + set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake); + set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state0->rpm); + + if (fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) + set_rpm_fan(CPUA_PUMP_RPM_INDEX, pump); + if (fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) + set_rpm_fan(CPUB_PUMP_RPM_INDEX, pump); +} + +static void do_monitor_cpu_split(struct cpu_pid_state *state) +{ + s32 temp, power; + int rc, intake; + + /* Read current fan status */ + rc = do_read_one_cpu_values(state, &temp, &power); + if (rc < 0) { + /* XXX What do we do now ? */ + } + + /* Check tmax, increment overtemp if we are there. At tmax+8, we go + * full blown immediately and try to trigger a shutdown + */ + if (temp >= ((state->mpu.tmax + 8) << 16)) { + printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum" + " (%d) !\n", + state->index, temp >> 16); + state->overtemp = CPU_MAX_OVERTEMP; + } else if (temp > (state->mpu.tmax << 16)) + state->overtemp++; + else + state->overtemp = 0; + if (state->overtemp >= CPU_MAX_OVERTEMP) + critical_state = 1; + if (state->overtemp > 0) { state->rpm = state->mpu.rmaxn_exhaust_fan; + state->intake_rpm = intake = state->mpu.rmaxn_intake_fan; + goto do_set_fans; + } + + /* Do the PID */ + do_cpu_pid(state, temp, power); intake = (state->rpm * CPU_INTAKE_SCALE) >> 16; - if (intake < state->mpu.rminn_intake_fan) + if (intake < (int)state->mpu.rminn_intake_fan) intake = state->mpu.rminn_intake_fan; - if (intake > state->mpu.rmaxn_intake_fan) + if (intake > (int)state->mpu.rmaxn_intake_fan) intake = state->mpu.rmaxn_intake_fan; state->intake_rpm = intake; @@ -677,11 +921,11 @@ static void do_monitor_cpu(struct cpu_pid_state *state) * some way... */ if (state->index == 0) { - set_rpm_fan(CPUA_INTAKE_FAN_RPM_ID, intake); - set_rpm_fan(CPUA_EXHAUST_FAN_RPM_ID, state->rpm); + set_rpm_fan(CPUA_INTAKE_FAN_RPM_INDEX, intake); + set_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, state->rpm); } else { - set_rpm_fan(CPUB_INTAKE_FAN_RPM_ID, intake); - set_rpm_fan(CPUB_EXHAUST_FAN_RPM_ID, state->rpm); + set_rpm_fan(CPUB_INTAKE_FAN_RPM_INDEX, intake); + set_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, state->rpm); } } @@ -696,6 +940,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index) state->overtemp = 0; state->adc_config = 0x00; + if (index == 0) state->monitor = attach_i2c_chip(SUPPLY_MONITOR_ID, "CPU0_monitor"); else if (index == 1) @@ -778,7 +1023,7 @@ static void do_monitor_backside(struct backside_pid_state *state) DBG("backside:\n"); /* Check fan status */ - rc = get_pwm_fan(BACKSIDE_FAN_PWM_ID); + rc = get_pwm_fan(BACKSIDE_FAN_PWM_INDEX); if (rc < 0) { printk(KERN_WARNING "Error %d reading backside fan !\n", rc); /* XXX What do we do now ? */ @@ -790,12 +1035,12 @@ static void do_monitor_backside(struct backside_pid_state *state) temp = i2c_smbus_read_byte_data(state->monitor, MAX6690_EXT_TEMP) << 16; state->last_temp = temp; DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), - FIX32TOPRINT(BACKSIDE_PID_INPUT_TARGET)); + FIX32TOPRINT(backside_params.input_target)); /* Store temperature and error in history array */ state->cur_sample = (state->cur_sample + 1) % BACKSIDE_PID_HISTORY_SIZE; state->sample_history[state->cur_sample] = temp; - state->error_history[state->cur_sample] = temp - BACKSIDE_PID_INPUT_TARGET; + state->error_history[state->cur_sample] = temp - backside_params.input_target; /* If first loop, fill the history table */ if (state->first) { @@ -804,7 +1049,7 @@ static void do_monitor_backside(struct backside_pid_state *state) BACKSIDE_PID_HISTORY_SIZE; state->sample_history[state->cur_sample] = temp; state->error_history[state->cur_sample] = - temp - BACKSIDE_PID_INPUT_TARGET; + temp - backside_params.input_target; } state->first = 0; } @@ -816,7 +1061,7 @@ static void do_monitor_backside(struct backside_pid_state *state) integral += state->error_history[i]; integral *= BACKSIDE_PID_INTERVAL; DBG(" integral: %08x\n", integral); - integ_p = ((s64)BACKSIDE_PID_G_r) * (s64)integral; + integ_p = ((s64)backside_params.G_r) * (s64)integral; DBG(" integ_p: %d\n", (int)(integ_p >> 36)); sum += integ_p; @@ -825,12 +1070,12 @@ static void do_monitor_backside(struct backside_pid_state *state) state->error_history[(state->cur_sample + BACKSIDE_PID_HISTORY_SIZE - 1) % BACKSIDE_PID_HISTORY_SIZE]; derivative /= BACKSIDE_PID_INTERVAL; - deriv_p = ((s64)BACKSIDE_PID_G_d) * (s64)derivative; + deriv_p = ((s64)backside_params.G_d) * (s64)derivative; DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); sum += deriv_p; /* Calculate the proportional term */ - prop_p = ((s64)BACKSIDE_PID_G_p) * (s64)(state->error_history[state->cur_sample]); + prop_p = ((s64)backside_params.G_p) * (s64)(state->error_history[state->cur_sample]); DBG(" prop_p: %d\n", (int)(prop_p >> 36)); sum += prop_p; @@ -839,13 +1084,13 @@ static void do_monitor_backside(struct backside_pid_state *state) DBG(" sum: %d\n", (int)sum); state->pwm += (s32)sum; - if (state->pwm < BACKSIDE_PID_OUTPUT_MIN) - state->pwm = BACKSIDE_PID_OUTPUT_MIN; - if (state->pwm > BACKSIDE_PID_OUTPUT_MAX) - state->pwm = BACKSIDE_PID_OUTPUT_MAX; + if (state->pwm < backside_params.output_min) + state->pwm = backside_params.output_min; + if (state->pwm > backside_params.output_max) + state->pwm = backside_params.output_max; DBG("** BACKSIDE PWM: %d\n", (int)state->pwm); - set_pwm_fan(BACKSIDE_FAN_PWM_ID, state->pwm); + set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, state->pwm); } /* @@ -853,6 +1098,35 @@ static void do_monitor_backside(struct backside_pid_state *state) */ static int init_backside_state(struct backside_pid_state *state) { + struct device_node *u3; + int u3h = 1; /* conservative by default */ + + /* + * There are different PID params for machines with U3 and machines + * with U3H, pick the right ones now + */ + u3 = of_find_node_by_path("/u3@0,f8000000"); + if (u3 != NULL) { + u32 *vers = (u32 *)get_property(u3, "device-rev", NULL); + if (vers) + if (((*vers) & 0x3f) < 0x34) + u3h = 0; + of_node_put(u3); + } + + backside_params.G_p = BACKSIDE_PID_G_p; + backside_params.G_r = BACKSIDE_PID_G_r; + backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX; + if (u3h) { + backside_params.G_d = BACKSIDE_PID_U3H_G_d; + backside_params.input_target = BACKSIDE_PID_U3H_INPUT_TARGET; + backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN; + } else { + backside_params.G_d = BACKSIDE_PID_U3_G_d; + backside_params.input_target = BACKSIDE_PID_U3_INPUT_TARGET; + backside_params.output_min = BACKSIDE_PID_U3_OUTPUT_MIN; + } + state->ticks = 1; state->first = 1; state->pwm = 50; @@ -898,7 +1172,7 @@ static void do_monitor_drives(struct drives_pid_state *state) DBG("drives:\n"); /* Check fan status */ - rc = get_rpm_fan(DRIVES_FAN_RPM_ID, !RPM_PID_USE_ACTUAL_SPEED); + rc = get_rpm_fan(DRIVES_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED); if (rc < 0) { printk(KERN_WARNING "Error %d reading drives fan !\n", rc); /* XXX What do we do now ? */ @@ -965,7 +1239,7 @@ static void do_monitor_drives(struct drives_pid_state *state) state->rpm = DRIVES_PID_OUTPUT_MAX; DBG("** DRIVES RPM: %d\n", (int)state->rpm); - set_rpm_fan(DRIVES_FAN_RPM_ID, state->rpm); + set_rpm_fan(DRIVES_FAN_RPM_INDEX, state->rpm); } /* @@ -1032,7 +1306,7 @@ static int main_control_loop(void *x) } /* Set the PCI fan once for now */ - set_pwm_fan(SLOTS_FAN_PWM_ID, SLOTS_FAN_DEFAULT_PWM); + set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); /* Initialize ADCs */ initialize_adc(&cpu_state[0]); @@ -1047,9 +1321,13 @@ static int main_control_loop(void *x) start = jiffies; down(&driver_lock); - do_monitor_cpu(&cpu_state[0]); - if (cpu_state[1].monitor != NULL) - do_monitor_cpu(&cpu_state[1]); + if (cpu_pid_type == CPU_PID_TYPE_COMBINED) + do_monitor_cpu_combined(); + else { + do_monitor_cpu_split(&cpu_state[0]); + if (cpu_state[1].monitor != NULL) + do_monitor_cpu_split(&cpu_state[1]); + } do_monitor_backside(&backside_state); do_monitor_drives(&drives_state); up(&driver_lock); @@ -1113,6 +1391,19 @@ static int create_control_loops(void) DBG("counted %d CPUs in the device-tree\n", cpu_count); + /* Decide the type of PID algorithm to use based on the presence of + * the pumps, though that may not be the best way, that is good enough + * for now + */ + if (machine_is_compatible("PowerMac7,3") + && (cpu_count > 1) + && fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID + && fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) { + printk(KERN_INFO "Liquid cooling pumps detected, using new algorithm !\n"); + cpu_pid_type = CPU_PID_TYPE_COMBINED; + } else + cpu_pid_type = CPU_PID_TYPE_SPLIT; + /* Create control loops for everything. If any fail, everything * fails */ @@ -1257,12 +1548,91 @@ static int therm_pm72_detach(struct i2c_adapter *adapter) return 0; } +static void fcu_lookup_fans(struct device_node *fcu_node) +{ + struct device_node *np = NULL; + int i; + + /* The table is filled by default with values that are suitable + * for the old machines without device-tree informations. We scan + * the device-tree and override those values with whatever is + * there + */ + + DBG("Looking up FCU controls in device-tree...\n"); + + while ((np = of_get_next_child(fcu_node, np)) != NULL) { + int type = -1; + char *loc; + u32 *reg; + + DBG(" control: %s, type: %s\n", np->name, np->type); + + /* Detect control type */ + if (!strcmp(np->type, "fan-rpm-control") || + !strcmp(np->type, "fan-rpm")) + type = FCU_FAN_RPM; + if (!strcmp(np->type, "fan-pwm-control") || + !strcmp(np->type, "fan-pwm")) + type = FCU_FAN_PWM; + /* Only care about fans for now */ + if (type == -1) + continue; + + /* Lookup for a matching location */ + loc = (char *)get_property(np, "location", NULL); + reg = (u32 *)get_property(np, "reg", NULL); + if (loc == NULL || reg == NULL) + continue; + DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); + + for (i = 0; i < FCU_FAN_COUNT; i++) { + int fan_id; + + if (strcmp(loc, fcu_fans[i].loc)) + continue; + DBG(" location match, index: %d\n", i); + fcu_fans[i].id = FCU_FAN_ABSENT_ID; + if (type != fcu_fans[i].type) { + printk(KERN_WARNING "therm_pm72: Fan type mismatch " + "in device-tree for %s\n", np->full_name); + break; + } + if (type == FCU_FAN_RPM) + fan_id = ((*reg) - 0x10) / 2; + else + fan_id = ((*reg) - 0x30) / 2; + if (fan_id > 7) { + printk(KERN_WARNING "therm_pm72: Can't parse " + "fan ID in device-tree for %s\n", np->full_name); + break; + } + DBG(" fan id -> %d, type -> %d\n", fan_id, type); + fcu_fans[i].id = fan_id; + } + } + + /* Now dump the array */ + printk(KERN_INFO "Detected fan controls:\n"); + for (i = 0; i < FCU_FAN_COUNT; i++) { + if (fcu_fans[i].id == FCU_FAN_ABSENT_ID) + continue; + printk(KERN_INFO " %d: %s fan, id %d, location: %s\n", i, + fcu_fans[i].type == FCU_FAN_RPM ? "RPM" : "PWM", + fcu_fans[i].id, fcu_fans[i].loc); + } +} + static int fcu_of_probe(struct of_device* dev, const struct of_match *match) { int rc; state = state_detached; + /* Lookup the fans in the device tree */ + fcu_lookup_fans(dev->node); + + /* Add the driver */ rc = i2c_add_driver(&therm_pm72_driver); if (rc < 0) return rc; @@ -1301,15 +1671,20 @@ static int __init therm_pm72_init(void) { struct device_node *np; - if (!machine_is_compatible("PowerMac7,2")) + if (!machine_is_compatible("PowerMac7,2") && + !machine_is_compatible("PowerMac7,3")) return -ENODEV; printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION); np = of_find_node_by_type(NULL, "fcu"); if (np == NULL) { - printk(KERN_ERR "Can't find FCU in device-tree !\n"); - return -ENODEV; + /* Some machines have strangely broken device-tree */ + np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); + if (np == NULL) { + printk(KERN_ERR "Can't find FCU in device-tree !\n"); + return -ENODEV; + } } of_dev = of_platform_device_create(np, "temperature"); if (of_dev == NULL) { diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h index eda488a7c..1a4c71ad3 100644 --- a/drivers/macintosh/therm_pm72.h +++ b/drivers/macintosh/therm_pm72.h @@ -119,18 +119,33 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp"; #define ADC_CPU_CURRENT_SCALE 0x1f40 /* _AD4 */ /* - * PID factors for the U3/Backside fan control loop + * PID factors for the U3/Backside fan control loop. We have 2 sets + * of values here, one set for U3 and one set for U3H */ -#define BACKSIDE_FAN_PWM_ID 1 -#define BACKSIDE_PID_G_d 0x02800000 +#define BACKSIDE_FAN_PWM_DEFAULT_ID 1 +#define BACKSIDE_FAN_PWM_INDEX 0 +#define BACKSIDE_PID_U3_G_d 0x02800000 +#define BACKSIDE_PID_U3H_G_d 0x01400000 #define BACKSIDE_PID_G_p 0x00500000 #define BACKSIDE_PID_G_r 0x00000000 -#define BACKSIDE_PID_INPUT_TARGET 0x00410000 +#define BACKSIDE_PID_U3_INPUT_TARGET 0x00410000 +#define BACKSIDE_PID_U3H_INPUT_TARGET 0x004b0000 #define BACKSIDE_PID_INTERVAL 5 #define BACKSIDE_PID_OUTPUT_MAX 100 -#define BACKSIDE_PID_OUTPUT_MIN 20 +#define BACKSIDE_PID_U3_OUTPUT_MIN 20 +#define BACKSIDE_PID_U3H_OUTPUT_MIN 30 #define BACKSIDE_PID_HISTORY_SIZE 2 +struct basckside_pid_params +{ + s32 G_d; + s32 G_p; + s32 G_r; + s32 input_target; + s32 output_min; + s32 output_max; +}; + struct backside_pid_state { int ticks; @@ -146,7 +161,8 @@ struct backside_pid_state /* * PID factors for the Drive Bay fan control loop */ -#define DRIVES_FAN_RPM_ID 2 +#define DRIVES_FAN_RPM_DEFAULT_ID 2 +#define DRIVES_FAN_RPM_INDEX 1 #define DRIVES_PID_G_d 0x01e00000 #define DRIVES_PID_G_p 0x00500000 #define DRIVES_PID_G_r 0x00000000 @@ -168,7 +184,8 @@ struct drives_pid_state int first; }; -#define SLOTS_FAN_PWM_ID 2 +#define SLOTS_FAN_PWM_DEFAULT_ID 2 +#define SLOTS_FAN_PWM_INDEX 2 #define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */ /* @@ -191,10 +208,15 @@ struct drives_pid_state * CPU B FAKE POWER 49 (I_V_inputs: 18, 19) */ -#define CPUA_INTAKE_FAN_RPM_ID 3 -#define CPUA_EXHAUST_FAN_RPM_ID 4 -#define CPUB_INTAKE_FAN_RPM_ID 5 -#define CPUB_EXHAUST_FAN_RPM_ID 6 +#define CPUA_INTAKE_FAN_RPM_DEFAULT_ID 3 +#define CPUA_EXHAUST_FAN_RPM_DEFAULT_ID 4 +#define CPUB_INTAKE_FAN_RPM_DEFAULT_ID 5 +#define CPUB_EXHAUST_FAN_RPM_DEFAULT_ID 6 + +#define CPUA_INTAKE_FAN_RPM_INDEX 3 +#define CPUA_EXHAUST_FAN_RPM_INDEX 4 +#define CPUB_INTAKE_FAN_RPM_INDEX 5 +#define CPUB_EXHAUST_FAN_RPM_INDEX 6 #define CPU_INTAKE_SCALE 0x0000f852 #define CPU_TEMP_HISTORY_SIZE 2 @@ -202,6 +224,11 @@ struct drives_pid_state #define CPU_PID_INTERVAL 1 #define CPU_MAX_OVERTEMP 30 +#define CPUA_PUMP_RPM_INDEX 7 +#define CPUB_PUMP_RPM_INDEX 8 +#define CPU_PUMP_OUTPUT_MAX 3700 +#define CPU_PUMP_OUTPUT_MIN 1000 + struct cpu_pid_state { int index; @@ -219,6 +246,7 @@ struct cpu_pid_state s32 voltage; s32 current_a; s32 last_temp; + s32 last_power; int first; u8 adc_config; }; diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index f4a1777c6..897902b82 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -292,8 +292,7 @@ control_loop( void *dummy ) while( x.running ) { up( &x.lock ); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout( 8*HZ ); + msleep_interruptible(8000); down( &x.lock ); poll_temp(); @@ -354,12 +353,12 @@ do_detach( struct i2c_client *client ) } static struct i2c_driver g4fan_driver = { - .name = "Apple G4 Thermostat/Fan", + .owner = THIS_MODULE, + .name = "therm_windtunnel", .id = I2C_DRIVERID_G4FAN, .flags = I2C_DF_NOTIFY, - .attach_adapter = &do_attach, - .detach_client = &do_detach, - .command = NULL, + .attach_adapter = do_attach, + .detach_client = do_detach, }; static int diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 70723139f..e5e3d0202 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -32,7 +32,7 @@ #include #include -static volatile unsigned char *via; +static volatile unsigned char __iomem *via; static spinlock_t cuda_lock = SPIN_LOCK_UNLOCKED; #ifdef CONFIG_MAC @@ -160,7 +160,7 @@ find_via_cuda(void) if (vias->n_addrs < 1 || vias->n_intrs < 1) return 0; } - via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000); + via = ioremap(vias->addrs->address, 0x2000); cuda_state = idle; sys_ctrler = SYS_CTRLER_CUDA; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 27e14a726..85e375692 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -73,7 +72,7 @@ /* How many iterations between battery polls */ #define BATTERY_POLLING_COUNT 2 -static volatile unsigned char *via; +static volatile unsigned char __iomem *via; /* VIA registers - spaced 0x200 bytes apart */ #define RS 0x200 /* skip between registers */ @@ -138,12 +137,11 @@ static int data_len; static volatile int adb_int_pending; static volatile int disable_poll; static struct adb_request bright_req_1, bright_req_2; -static unsigned long async_req_locks; static struct device_node *vias; static int pmu_kind = PMU_UNKNOWN; static int pmu_fully_inited = 0; static int pmu_has_adb; -static unsigned char *gpio_reg = NULL; +static unsigned char __iomem *gpio_reg = NULL; static int gpio_irq = -1; static int gpio_irq_enabled = -1; static volatile int pmu_suspended = 0; @@ -156,6 +154,7 @@ static int option_lid_wakeup = 1; static int sleep_in_progress; static int can_sleep; #endif /* CONFIG_PMAC_PBOOK */ +static unsigned long async_req_locks; static unsigned int pmu_irq_stats[11]; static struct proc_dir_entry *proc_pmu_root; @@ -353,7 +352,7 @@ find_via_pmu(void) } else pmu_kind = PMU_UNKNOWN; - via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000); + via = ioremap(vias->addrs->address, 0x2000); out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ out_8(&via[IFR], 0x7f); /* clear IFR */ @@ -494,12 +493,9 @@ static int __init via_pmu_dev_init(void) /* Create /proc/pmu */ proc_pmu_root = proc_mkdir("pmu", NULL); if (proc_pmu_root) { - int i; - proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root, - proc_get_info, NULL); - proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root, - proc_get_irqstats, NULL); #ifdef CONFIG_PMAC_PBOOK + int i; + for (i=0; inlink = 1; @@ -746,6 +747,8 @@ done_battery_state_smart(struct adb_request* req) pmu_power_flags &= ~PMU_PWR_AC_PRESENT; + capa = max = amperage = voltage = 0; + if (req->reply[1] & 0x04) { bat_flags |= PMU_BATT_PRESENT; switch(req->reply[0]) { @@ -765,8 +768,7 @@ done_battery_state_smart(struct adb_request* req) req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]); break; } - } else - capa = max = amperage = voltage = 0; + } if ((req->reply[1] & 0x01) && (amperage > 0)) bat_flags |= PMU_BATT_CHARGING; @@ -1162,7 +1164,7 @@ wait_for_ack(void) static inline void send_byte(int x) { - volatile unsigned char *v = via; + volatile unsigned char __iomem *v = via; out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT); out_8(&v[SR], x); @@ -1173,7 +1175,7 @@ send_byte(int x) static inline void recv_byte(void) { - volatile unsigned char *v = via; + volatile unsigned char __iomem *v = via; out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT); in_8(&v[SR]); /* resets SR */ @@ -1445,7 +1447,7 @@ static struct adb_request* __pmac pmu_sr_intr(struct pt_regs *regs) { struct adb_request *req; - int bite; + int bite = 0; if (via[B] & TREQ) { printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]); @@ -2628,8 +2630,8 @@ powerbook_sleep_3400(void) unsigned int hid0; unsigned long p; struct adb_request sleep_req; - char *mem_ctrl; - unsigned int *mem_ctrl_sleep; + void __iomem *mem_ctrl; + unsigned int __iomem *mem_ctrl_sleep; /* first map in the memory controller registers */ mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100); @@ -2637,7 +2639,7 @@ powerbook_sleep_3400(void) printk("powerbook_sleep_3400: ioremap failed\n"); return -ENOMEM; } - mem_ctrl_sleep = (unsigned int *) (mem_ctrl + PB3400_MEM_CTRL_SLEEP); + mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP; /* Allocate room for PCI save */ pbook_alloc_pci_save(); @@ -2975,7 +2977,7 @@ void pmu_device_init(void) #ifdef DEBUG_SLEEP static inline void __pmac -polled_handshake(volatile unsigned char *via) +polled_handshake(volatile unsigned char __iomem *via) { via[B] &= ~TREQ; eieio(); while ((via[B] & TACK) != 0) @@ -2986,7 +2988,7 @@ polled_handshake(volatile unsigned char *via) } static inline void __pmac -polled_send_byte(volatile unsigned char *via, int x) +polled_send_byte(volatile unsigned char __iomem *via, int x) { via[ACR] |= SR_OUT | SR_EXT; eieio(); via[SR] = x; eieio(); @@ -2994,7 +2996,7 @@ polled_send_byte(volatile unsigned char *via, int x) } static inline int __pmac -polled_recv_byte(volatile unsigned char *via) +polled_recv_byte(volatile unsigned char __iomem *via) { int x; @@ -3010,7 +3012,7 @@ pmu_polled_request(struct adb_request *req) { unsigned long flags; int i, l, c; - volatile unsigned char *v = via; + volatile unsigned char __iomem *v = via; req->complete = 1; c = req->data[0]; diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 87261d37f..72d0bf2b7 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -85,6 +85,24 @@ config MD_RAID1 If unsure, say Y. +config MD_RAID10 + tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)" + depends on BLK_DEV_MD && EXPERIMENTAL + ---help--- + RAID-10 provides a combination of striping (RAID-0) and + mirroring (RAID-1) with easier configuration and more flexable + layout. + Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to + be the same size (or atleast, only as much as the smallest device + will be used). + RAID-10 provides a variety of layouts that provide different levels + of redundancy and performance. + + RAID-10 requires mdadm-1.7.0 or later, available at: + + ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/ + + config MD_RAID5 tristate "RAID-4/RAID-5 mode" depends on BLK_DEV_MD @@ -146,6 +164,15 @@ config MD_MULTIPATH If unsure, say N. +config MD_FAULTY + tristate "Faulty test module for MD" + depends on BLK_DEV_MD + help + The "faulty" module allows for a block device that occasionally returns + read or write errors. It is useful for testing. + + In unsure, say N. + config BLK_DEV_DM tristate "Device mapper support" depends on MD diff --git a/drivers/md/Makefile b/drivers/md/Makefile index c8feb8346..b9e64e876 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -10,7 +10,7 @@ raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \ raid6int8.o raid6int16.o raid6int32.o \ raid6mmx.o raid6sse1.o raid6sse2.o -host-progs := mktables +hostprogs-y := mktables # Note: link order is important. All raid personalities # and xor.o must come before md.o, as they each initialise @@ -20,9 +20,11 @@ host-progs := mktables obj-$(CONFIG_MD_LINEAR) += linear.o obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o +obj-$(CONFIG_MD_RAID10) += raid10.o obj-$(CONFIG_MD_RAID5) += raid5.o xor.o obj-$(CONFIG_MD_RAID6) += raid6.o xor.o obj-$(CONFIG_MD_MULTIPATH) += multipath.o +obj-$(CONFIG_MD_FAULTY) += faulty.o obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a17b25380..ebf735107 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 Christophe Saout + * Copyright (C) 2004 Clemens Fruhwirth * * This file is released under the GPL. */ @@ -15,6 +16,7 @@ #include #include #include +#include #include "dm.h" @@ -40,12 +42,22 @@ struct convert_context { struct bio *bio_out; unsigned int offset_in; unsigned int offset_out; - int idx_in; - int idx_out; + unsigned int idx_in; + unsigned int idx_out; sector_t sector; int write; }; +struct crypt_config; + +struct crypt_iv_operations { + int (*ctr)(struct crypt_config *cc, struct dm_target *ti, + const char *opts); + void (*dtr)(struct crypt_config *cc); + const char *(*status)(struct crypt_config *cc); + int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); +}; + /* * Crypt: maps a linear range of a block device * and encrypts / decrypts at the same time. @@ -64,11 +76,14 @@ struct crypt_config { /* * crypto related data */ - struct crypto_tfm *tfm; + struct crypt_iv_operations *iv_gen_ops; + char *iv_mode; + void *iv_gen_private; sector_t iv_offset; - int (*iv_generator)(struct crypt_config *cc, u8 *iv, sector_t sector); - int iv_size; - int key_size; + unsigned int iv_size; + + struct crypto_tfm *tfm; + unsigned int key_size; u8 key[0]; }; @@ -93,18 +108,129 @@ static void mempool_free_page(void *page, void *data) /* - * Different IV generation algorithms + * Different IV generation algorithms: + * + * plain: the initial vector is the 32-bit low-endian version of the sector + * number, padded with zeros if neccessary. + * + * ess_iv: "encrypted sector|salt initial vector", the sector number is + * encrypted with the bulk cipher using a salt as key. The salt + * should be derived from the bulk cipher's key via hashing. + * + * plumb: unimplemented, see: + * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 */ -static int crypt_iv_plain(struct crypt_config *cc, u8 *iv, sector_t sector) + +static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) { + memset(iv, 0, cc->iv_size); *(u32 *)iv = cpu_to_le32(sector & 0xffffffff); - if (cc->iv_size > sizeof(u32) / sizeof(u8)) - memset(iv + (sizeof(u32) / sizeof(u8)), 0, - cc->iv_size - (sizeof(u32) / sizeof(u8))); return 0; } +static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, + const char *opts) +{ + struct crypto_tfm *essiv_tfm; + struct crypto_tfm *hash_tfm; + struct scatterlist sg; + unsigned int saltsize; + u8 *salt; + + if (opts == NULL) { + ti->error = PFX "Digest algorithm missing for ESSIV mode"; + return -EINVAL; + } + + /* Hash the cipher key with the given hash algorithm */ + hash_tfm = crypto_alloc_tfm(opts, 0); + if (hash_tfm == NULL) { + ti->error = PFX "Error initializing ESSIV hash"; + return -EINVAL; + } + + if (crypto_tfm_alg_type(hash_tfm) != CRYPTO_ALG_TYPE_DIGEST) { + ti->error = PFX "Expected digest algorithm for ESSIV hash"; + crypto_free_tfm(hash_tfm); + return -EINVAL; + } + + saltsize = crypto_tfm_alg_digestsize(hash_tfm); + salt = kmalloc(saltsize, GFP_KERNEL); + if (salt == NULL) { + ti->error = PFX "Error kmallocing salt storage in ESSIV"; + crypto_free_tfm(hash_tfm); + return -ENOMEM; + } + + sg.page = virt_to_page(cc->key); + sg.offset = offset_in_page(cc->key); + sg.length = cc->key_size; + crypto_digest_digest(hash_tfm, &sg, 1, salt); + crypto_free_tfm(hash_tfm); + + /* Setup the essiv_tfm with the given salt */ + essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm), + CRYPTO_TFM_MODE_ECB); + if (essiv_tfm == NULL) { + ti->error = PFX "Error allocating crypto tfm for ESSIV"; + kfree(salt); + return -EINVAL; + } + if (crypto_tfm_alg_blocksize(essiv_tfm) + != crypto_tfm_alg_ivsize(cc->tfm)) { + ti->error = PFX "Block size of ESSIV cipher does " + "not match IV size of block cipher"; + crypto_free_tfm(essiv_tfm); + kfree(salt); + return -EINVAL; + } + if (crypto_cipher_setkey(essiv_tfm, salt, saltsize) < 0) { + ti->error = PFX "Failed to set key for ESSIV cipher"; + crypto_free_tfm(essiv_tfm); + kfree(salt); + return -EINVAL; + } + kfree(salt); + + cc->iv_gen_private = (void *)essiv_tfm; + return 0; +} + +static void crypt_iv_essiv_dtr(struct crypt_config *cc) +{ + crypto_free_tfm((struct crypto_tfm *)cc->iv_gen_private); + cc->iv_gen_private = NULL; +} + +static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) +{ + struct scatterlist sg = { NULL, }; + + memset(iv, 0, cc->iv_size); + *(u64 *)iv = cpu_to_le64(sector); + + sg.page = virt_to_page(iv); + sg.offset = offset_in_page(iv); + sg.length = cc->iv_size; + crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private, + &sg, &sg, cc->iv_size); + + return 0; +} + +static struct crypt_iv_operations crypt_iv_plain_ops = { + .generator = crypt_iv_plain_gen +}; + +static struct crypt_iv_operations crypt_iv_essiv_ops = { + .ctr = crypt_iv_essiv_ctr, + .dtr = crypt_iv_essiv_dtr, + .generator = crypt_iv_essiv_gen +}; + + static inline int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, @@ -113,8 +239,8 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, u8 iv[cc->iv_size]; int r; - if (cc->iv_generator) { - r = cc->iv_generator(cc, iv, sector); + if (cc->iv_gen_ops) { + r = cc->iv_gen_ops->generator(cc, iv, sector); if (r < 0) return r; @@ -200,13 +326,13 @@ static int crypt_convert(struct crypt_config *cc, */ static struct bio * crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, - struct bio *base_bio, int *bio_vec_idx) + struct bio *base_bio, unsigned int *bio_vec_idx) { struct bio *bio; - int nr_iovecs = dm_div_up(size, PAGE_SIZE); + unsigned int nr_iovecs = dm_div_up(size, PAGE_SIZE); int gfp_mask = GFP_NOIO | __GFP_HIGHMEM; - int flags = current->flags; - int i; + unsigned long flags = current->flags; + unsigned int i; /* * Tell VM to act less aggressively and fail earlier. @@ -280,9 +406,8 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *bio, unsigned int bytes) { - unsigned int start, end; + unsigned int i, start, end; struct bio_vec *bv; - int i; /* * This is ugly, but Jens Axboe thinks that using bi_idx in the @@ -366,11 +491,11 @@ static void kcryptd_queue_io(struct crypt_io *io) /* * Decode key from its hex representation */ -static int crypt_decode_key(u8 *key, char *hex, int size) +static int crypt_decode_key(u8 *key, char *hex, unsigned int size) { char buffer[3]; char *endp; - int i; + unsigned int i; buffer[2] = '\0'; @@ -393,9 +518,9 @@ static int crypt_decode_key(u8 *key, char *hex, int size) /* * Encode key into its hex representation */ -static void crypt_encode_key(char *hex, u8 *key, int size) +static void crypt_encode_key(char *hex, u8 *key, unsigned int size) { - int i; + unsigned int i; for(i = 0; i < size; i++) { sprintf(hex, "%02x", *key); @@ -414,9 +539,11 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) struct crypto_tfm *tfm; char *tmp; char *cipher; - char *mode; - int crypto_flags; - int key_size; + char *chainmode; + char *ivmode; + char *ivopts; + unsigned int crypto_flags; + unsigned int key_size; if (argc != 5) { ti->error = PFX "Not enough arguments"; @@ -425,7 +552,9 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) tmp = argv[0]; cipher = strsep(&tmp, "-"); - mode = strsep(&tmp, "-"); + chainmode = strsep(&tmp, "-"); + ivopts = strsep(&tmp, "-"); + ivmode = strsep(&ivopts, ":"); if (tmp) DMWARN(PFX "Unexpected additional cipher options"); @@ -439,19 +568,33 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -ENOMEM; } - if (!mode || strcmp(mode, "plain") == 0) - cc->iv_generator = crypt_iv_plain; - else if (strcmp(mode, "ecb") == 0) - cc->iv_generator = NULL; - else { - ti->error = PFX "Invalid chaining mode"; + cc->key_size = key_size; + if ((!key_size && strcmp(argv[1], "-") != 0) || + (key_size && crypt_decode_key(cc->key, argv[1], key_size) < 0)) { + ti->error = PFX "Error decoding key"; goto bad1; } - if (cc->iv_generator) + /* Compatiblity mode for old dm-crypt cipher strings */ + if (!chainmode || (strcmp(chainmode, "plain") == 0 && !ivmode)) { + chainmode = "cbc"; + ivmode = "plain"; + } + + /* Choose crypto_flags according to chainmode */ + if (strcmp(chainmode, "cbc") == 0) crypto_flags = CRYPTO_TFM_MODE_CBC; - else + else if (strcmp(chainmode, "ecb") == 0) crypto_flags = CRYPTO_TFM_MODE_ECB; + else { + ti->error = PFX "Unknown chaining mode"; + goto bad1; + } + + if (crypto_flags != CRYPTO_TFM_MODE_ECB && !ivmode) { + ti->error = PFX "This chaining mode requires an IV mechanism"; + goto bad1; + } tfm = crypto_alloc_tfm(cipher, crypto_flags); if (!tfm) { @@ -463,15 +606,39 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad2; } + cc->tfm = tfm; + + /* + * Choose ivmode. Valid modes: "plain", "essiv:". + * See comments at iv code + */ + + if (ivmode == NULL) + cc->iv_gen_ops = NULL; + else if (strcmp(ivmode, "plain") == 0) + cc->iv_gen_ops = &crypt_iv_plain_ops; + else if (strcmp(ivmode, "essiv") == 0) + cc->iv_gen_ops = &crypt_iv_essiv_ops; + else { + ti->error = PFX "Invalid IV mode"; + goto bad2; + } + + if (cc->iv_gen_ops && cc->iv_gen_ops->ctr && + cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) + goto bad2; + if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv) - /* at least a 32 bit sector number should fit in our buffer */ + /* at least a 64 bit sector number should fit in our buffer */ cc->iv_size = max(crypto_tfm_alg_ivsize(tfm), - (unsigned int)(sizeof(u32) / sizeof(u8))); + (unsigned int)(sizeof(u64) / sizeof(u8))); else { cc->iv_size = 0; - if (cc->iv_generator) { + if (cc->iv_gen_ops) { DMWARN(PFX "Selected cipher does not support IVs"); - cc->iv_generator = NULL; + if (cc->iv_gen_ops->dtr) + cc->iv_gen_ops->dtr(cc); + cc->iv_gen_ops = NULL; } } @@ -479,52 +646,59 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) mempool_free_slab, _crypt_io_pool); if (!cc->io_pool) { ti->error = PFX "Cannot allocate crypt io mempool"; - goto bad2; + goto bad3; } cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page, mempool_free_page, NULL); if (!cc->page_pool) { ti->error = PFX "Cannot allocate page mempool"; - goto bad3; - } - - cc->tfm = tfm; - cc->key_size = key_size; - if ((key_size == 0 && strcmp(argv[1], "-") != 0) - || crypt_decode_key(cc->key, argv[1], key_size) < 0) { - ti->error = PFX "Error decoding key"; goto bad4; } if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) { ti->error = PFX "Error setting key"; - goto bad4; + goto bad5; } if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) { ti->error = PFX "Invalid iv_offset sector"; - goto bad4; + goto bad5; } if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) { ti->error = PFX "Invalid device sector"; - goto bad4; + goto bad5; } if (dm_get_device(ti, argv[3], cc->start, ti->len, dm_table_get_mode(ti->table), &cc->dev)) { ti->error = PFX "Device lookup failed"; - goto bad4; + goto bad5; } + if (ivmode && cc->iv_gen_ops) { + if (ivopts) + *(ivopts - 1) = ':'; + cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); + if (!cc->iv_mode) { + ti->error = PFX "Error kmallocing iv_mode string"; + goto bad5; + } + strcpy(cc->iv_mode, ivmode); + } else + cc->iv_mode = NULL; + ti->private = cc; return 0; -bad4: +bad5: mempool_destroy(cc->page_pool); -bad3: +bad4: mempool_destroy(cc->io_pool); +bad3: + if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) + cc->iv_gen_ops->dtr(cc); bad2: crypto_free_tfm(tfm); bad1: @@ -539,6 +713,10 @@ static void crypt_dtr(struct dm_target *ti) mempool_destroy(cc->page_pool); mempool_destroy(cc->io_pool); + if (cc->iv_mode) + kfree(cc->iv_mode); + if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) + cc->iv_gen_ops->dtr(cc); crypto_free_tfm(cc->tfm); dm_put_device(ti, cc->dev); kfree(cc); @@ -577,7 +755,8 @@ static int crypt_endio(struct bio *bio, unsigned int done, int error) static inline struct bio * crypt_clone(struct crypt_config *cc, struct crypt_io *io, struct bio *bio, - sector_t sector, int *bvec_idx, struct convert_context *ctx) + sector_t sector, unsigned int *bvec_idx, + struct convert_context *ctx) { struct bio *clone; @@ -630,7 +809,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, struct bio *clone; unsigned int remaining = bio->bi_size; sector_t sector = bio->bi_sector - ti->begin; - int bvec_idx = 0; + unsigned int bvec_idx = 0; io->target = ti; io->bio = bio; @@ -692,8 +871,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type, struct crypt_config *cc = (struct crypt_config *) ti->private; char buffer[32]; const char *cipher; - const char *mode = NULL; - int offset; + const char *chainmode = NULL; + unsigned int sz = 0; switch (type) { case STATUSTYPE_INFO: @@ -705,34 +884,35 @@ static int crypt_status(struct dm_target *ti, status_type_t type, switch(cc->tfm->crt_cipher.cit_mode) { case CRYPTO_TFM_MODE_CBC: - mode = "plain"; + chainmode = "cbc"; break; case CRYPTO_TFM_MODE_ECB: - mode = "ecb"; + chainmode = "ecb"; break; default: BUG(); } - snprintf(result, maxlen, "%s-%s ", cipher, mode); - offset = strlen(result); + if (cc->iv_mode) + DMEMIT("%s-%s-%s ", cipher, chainmode, cc->iv_mode); + else + DMEMIT("%s-%s ", cipher, chainmode); if (cc->key_size > 0) { - if ((maxlen - offset) < ((cc->key_size << 1) + 1)) + if ((maxlen - sz) < ((cc->key_size << 1) + 1)) return -ENOMEM; - crypt_encode_key(result + offset, cc->key, cc->key_size); - offset += cc->key_size << 1; + crypt_encode_key(result + sz, cc->key, cc->key_size); + sz += cc->key_size << 1; } else { - if (offset >= maxlen) + if (sz >= maxlen) return -ENOMEM; - result[offset++] = '-'; + result[sz++] = '-'; } format_dev_t(buffer, cc->dev->bdev->bd_dev); - snprintf(result + offset, maxlen - offset, " " SECTOR_FORMAT - " %s " SECTOR_FORMAT, cc->iv_offset, - buffer, cc->start); + DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT, + cc->iv_offset, buffer, cc->start); break; } return 0; @@ -740,7 +920,7 @@ static int crypt_status(struct dm_target *ti, status_type_t type, static struct target_type crypt_target = { .name = "crypt", - .version= {1, 0, 0}, + .version= {1, 1, 0}, .module = THIS_MODULE, .ctr = crypt_ctr, .dtr = crypt_dtr, diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 9f3fb61fd..cb7a43fde 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -267,7 +267,7 @@ static int resize_pool(unsigned int new_ios) /* create new pool */ _io_pool = mempool_create(new_ios, alloc_io, free_io, NULL); if (!_io_pool) - r = -ENOMEM; + return -ENOMEM; r = bio_set_init(&_bios, "dm-io", 512, 1); if (r) { diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index e1703f77c..9f0073f4e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -17,7 +18,7 @@ #include -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" +#define DM_DRIVER_EMAIL "dm-devel@redhat.com" /*----------------------------------------------------------------- * The ioctl interface needs to be able to look up devices by @@ -224,6 +225,7 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi } register_with_devfs(cell); dm_get(md); + dm_set_mdptr(md, cell); up_write(&_hash_lock); return 0; @@ -240,6 +242,7 @@ static void __hash_remove(struct hash_cell *hc) list_del(&hc->uuid_list); list_del(&hc->name_list); unregister_with_devfs(hc); + dm_set_mdptr(hc->md, NULL); dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); @@ -579,12 +582,16 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) } /* - * Always use UUID for lookups if it's present, otherwise use name. + * Always use UUID for lookups if it's present, otherwise use name or dev. */ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { - return *param->uuid ? - __get_uuid_cell(param->uuid) : __get_name_cell(param->name); + if (*param->uuid) + return __get_uuid_cell(param->uuid); + else if (*param->name) + return __get_name_cell(param->name); + else + return dm_get_mdptr(huge_decode_dev(param->dev)); } static inline struct mapped_device *find_device(struct dm_ioctl *param) @@ -596,6 +603,7 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) hc = __find_device_hash_cell(param); if (hc) { md = hc->md; + dm_get(md); /* * Sneakily write in both the name and the uuid @@ -611,8 +619,6 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) param->flags |= DM_INACTIVE_PRESENT_FLAG; else param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - dm_get(md); } up_read(&_hash_lock); @@ -1097,6 +1103,67 @@ static int table_status(struct dm_ioctl *param, size_t param_size) return r; } +/* + * Pass a message to the target that's at the supplied device offset. + */ +static int target_message(struct dm_ioctl *param, size_t param_size) +{ + int r, argc; + char **argv; + struct mapped_device *md; + struct dm_table *table; + struct dm_target *ti; + struct dm_target_msg *tmsg = (void *) param + param->data_start; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + if (tmsg < (struct dm_target_msg *) (param + 1) || + invalid_str(tmsg->message, (void *) param + param_size)) { + DMWARN("Invalid target message parameters."); + r = -EINVAL; + goto out; + } + + r = dm_split_args(&argc, &argv, tmsg->message); + if (r) { + DMWARN("Failed to split target message parameters"); + goto out; + } + + table = dm_get_table(md); + if (!table) + goto out_argv; + + if (tmsg->sector >= dm_table_get_size(table)) { + DMWARN("Target message sector outside device."); + r = -EINVAL; + goto out_table; + } + + ti = dm_table_find_target(table, tmsg->sector); + if (ti->type->message) + r = ti->type->message(ti, argc, argv); + else { + DMWARN("Target type does not support messages"); + r = -EINVAL; + } + + out_table: + dm_table_put(table); + out_argv: + kfree(argv); + out: + param->data_size = 0; + dm_put(md); + return r; +} + /*----------------------------------------------------------------- * Implementation of open/close/ioctl on the special char * device. @@ -1123,7 +1190,9 @@ static ioctl_fn lookup_ioctl(unsigned int cmd) {DM_TABLE_DEPS_CMD, table_deps}, {DM_TABLE_STATUS_CMD, table_status}, - {DM_LIST_VERSIONS_CMD, list_versions} + {DM_LIST_VERSIONS_CMD, list_versions}, + + {DM_TARGET_MSG_CMD, target_message} }; return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; @@ -1202,14 +1271,14 @@ static int validate_params(uint cmd, struct dm_ioctl *param) cmd == DM_LIST_VERSIONS_CMD) return 0; - /* Unless creating, either name or uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied, cmd(%u)", - cmd); + if ((cmd == DM_DEV_CREATE_CMD)) { + if (!*param->name) { + DMWARN("name not supplied when creating device"); return -EINVAL; } + } else if ((*param->uuid && *param->name)) { + DMWARN("only supply one of name or uuid, cmd(%u)", cmd); + return -EINVAL; } /* Ensure strings are terminated */ diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 7a1c77dee..43a12285d 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -140,6 +140,13 @@ struct log_c { int sync_search; + /* Resync flag */ + enum sync { + DEFAULTSYNC, /* Synchronize if necessary */ + NOSYNC, /* Devices known to be already in sync */ + FORCESYNC, /* Force a sync to happen */ + } sync; + /* * Disk log fields */ @@ -205,7 +212,8 @@ static int read_header(struct log_c *log) header_from_disk(&log->header, log->disk_header); - if (log->header.magic != MIRROR_MAGIC) { + /* New log required? */ + if (log->sync != DEFAULTSYNC || log->header.magic != MIRROR_MAGIC) { log->header.magic = MIRROR_MAGIC; log->header.version = MIRROR_DISK_VERSION; log->header.nr_regions = 0; @@ -273,22 +281,38 @@ static int write_bits(struct log_c *log) } /*---------------------------------------------------------------- - * constructor/destructor + * core log constructor/destructor + * + * argv contains region_size followed optionally by [no]sync *--------------------------------------------------------------*/ #define BYTE_SHIFT 3 static int core_ctr(struct dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv) { + enum sync sync = DEFAULTSYNC; + struct log_c *lc; sector_t region_size; unsigned int region_count; size_t bitset_size; - if (argc != 1) { - DMWARN("wrong number of arguments to log_c"); + if (argc < 1 || argc > 2) { + DMWARN("wrong number of arguments to mirror log"); return -EINVAL; } + if (argc > 1) { + if (!strcmp(argv[1], "sync")) + sync = FORCESYNC; + else if (!strcmp(argv[1], "nosync")) + sync = NOSYNC; + else { + DMWARN("unrecognised sync argument to mirror log: %s", + argv[1]); + return -EINVAL; + } + } + if (sscanf(argv[0], SECTOR_FORMAT, ®ion_size) != 1) { DMWARN("invalid region size string"); return -EINVAL; @@ -306,6 +330,7 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti, lc->touched = 0; lc->region_size = region_size; lc->region_count = region_count; + lc->sync = sync; /* * Work out how many words we need to hold the bitset. @@ -330,8 +355,8 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti, kfree(lc); return -ENOMEM; } - memset(lc->sync_bits, 0, bitset_size); - lc->sync_count = 0; + memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size); + lc->sync_count = (sync == NOSYNC) ? region_count : 0; lc->recovering_bits = vmalloc(bitset_size); if (!lc->recovering_bits) { @@ -356,6 +381,11 @@ static void core_dtr(struct dirty_log *log) kfree(lc); } +/*---------------------------------------------------------------- + * disk log constructor/destructor + * + * argv contains log_device region_size followed optionally by [no]sync + *--------------------------------------------------------------*/ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv) { @@ -364,8 +394,8 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti, struct log_c *lc; struct dm_dev *dev; - if (argc != 2) { - DMWARN("wrong number of arguments to log_d"); + if (argc < 2 || argc > 3) { + DMWARN("wrong number of arguments to disk mirror log"); return -EINVAL; } @@ -452,10 +482,15 @@ static int disk_resume(struct dirty_log *log) if (r) return r; - /* zero any new bits if the mirror has grown */ - for (i = lc->header.nr_regions; i < lc->region_count; i++) - /* FIXME: amazingly inefficient */ - log_clear_bit(lc, lc->clean_bits, i); + /* set or clear any new bits */ + if (lc->sync == NOSYNC) + for (i = lc->header.nr_regions; i < lc->region_count; i++) + /* FIXME: amazingly inefficient */ + log_set_bit(lc, lc->clean_bits, i); + else + for (i = lc->header.nr_regions; i < lc->region_count; i++) + /* FIXME: amazingly inefficient */ + log_clear_bit(lc, lc->clean_bits, i); /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); @@ -566,6 +601,51 @@ static region_t core_get_sync_count(struct dirty_log *log) return lc->sync_count; } +#define DMEMIT_SYNC \ + if (lc->sync != DEFAULTSYNC) \ + DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "") + +static int core_status(struct dirty_log *log, status_type_t status, + char *result, unsigned int maxlen) +{ + int sz = 0; + struct log_c *lc = log->context; + + switch(status) { + case STATUSTYPE_INFO: + break; + + case STATUSTYPE_TABLE: + DMEMIT("%s %u " SECTOR_FORMAT " ", log->type->name, + lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size); + DMEMIT_SYNC; + } + + return sz; +} + +static int disk_status(struct dirty_log *log, status_type_t status, + char *result, unsigned int maxlen) +{ + int sz = 0; + char buffer[16]; + struct log_c *lc = log->context; + + switch(status) { + case STATUSTYPE_INFO: + break; + + case STATUSTYPE_TABLE: + format_dev_t(buffer, lc->log_dev->bdev->bd_dev); + DMEMIT("%s %u %s " SECTOR_FORMAT " ", log->type->name, + lc->sync == DEFAULTSYNC ? 2 : 3, buffer, + lc->region_size); + DMEMIT_SYNC; + } + + return sz; +} + static struct dirty_log_type _core_type = { .name = "core", .module = THIS_MODULE, @@ -579,7 +659,8 @@ static struct dirty_log_type _core_type = { .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, .complete_resync_work = core_complete_resync_work, - .get_sync_count = core_get_sync_count + .get_sync_count = core_get_sync_count, + .status = core_status, }; static struct dirty_log_type _disk_type = { @@ -597,7 +678,8 @@ static struct dirty_log_type _disk_type = { .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, .complete_resync_work = core_complete_resync_work, - .get_sync_count = core_get_sync_count + .get_sync_count = core_get_sync_count, + .status = disk_status, }; int __init dm_dirty_log_init(void) diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index ced4ebacd..05ef594b5 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h @@ -101,6 +101,12 @@ struct dirty_log_type { * Returns the number of regions that are in sync. */ region_t (*get_sync_count)(struct dirty_log *log); + + /* + * Support function for mirror status requests. + */ + int (*status)(struct dirty_log *log, status_type_t status_type, + char *result, unsigned int maxlen); }; int dm_register_dirty_log_type(struct dirty_log_type *type); diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 92792bb7d..abab26516 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1009,8 +1009,8 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, * log_type #log_params * #mirrors [mirror_path offset]{2,} * - * For now, #log_params = 1, log_type = "core" - * + * log_type is "core" or "disk" + * #log_params is between 1 and 3 */ #define DM_IO_PAGES 64 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) @@ -1182,35 +1182,30 @@ static int mirror_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { char buffer[32]; - unsigned int m, sz = 0; + unsigned int m, sz; struct mirror_set *ms = (struct mirror_set *) ti->private; -#define EMIT(x...) sz += ((sz >= maxlen) ? \ - 0 : scnprintf(result + sz, maxlen - sz, x)) + sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); switch (type) { case STATUSTYPE_INFO: - EMIT("%d ", ms->nr_mirrors); - + DMEMIT("%d ", ms->nr_mirrors); for (m = 0; m < ms->nr_mirrors; m++) { format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev); - EMIT("%s ", buffer); + DMEMIT("%s ", buffer); } - EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT, - ms->rh.log->type->get_sync_count(ms->rh.log), - ms->nr_regions); + DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT, + ms->rh.log->type->get_sync_count(ms->rh.log), + ms->nr_regions); break; case STATUSTYPE_TABLE: - EMIT("%s 1 " SECTOR_FORMAT " %d ", - ms->rh.log->type->name, ms->rh.region_size, - ms->nr_mirrors); - + DMEMIT("%d ", ms->nr_mirrors); for (m = 0; m < ms->nr_mirrors; m++) { format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev); - EMIT("%s " SECTOR_FORMAT " ", - buffer, ms->mirror[m].offset); + DMEMIT("%s " SECTOR_FORMAT " ", + buffer, ms->mirror[m].offset); } } diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index b5bacd717..6a3b9454c 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -191,20 +191,17 @@ static int stripe_status(struct dm_target *ti, unsigned int i; char buffer[32]; -#define EMIT(x...) sz += ((sz >= maxlen) ? \ - 0 : scnprintf(result + sz, maxlen - sz, x)) - switch (type) { case STATUSTYPE_INFO: result[0] = '\0'; break; case STATUSTYPE_TABLE: - EMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); + DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); for (i = 0; i < sc->stripes; i++) { format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev); - EMIT(" %s " SECTOR_FORMAT, buffer, - sc->stripe[i].physical_start); + DMEMIT(" %s " SECTOR_FORMAT, buffer, + sc->stripe[i].physical_start); } break; } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index d189f8549..764c74ad6 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -575,7 +576,7 @@ static char **realloc_argv(unsigned *array_size, char **old_argv) /* * Destructively splits up the argument list to pass to ctr. */ -static int split_args(int *argc, char ***argvp, char *input) +int dm_split_args(int *argc, char ***argvp, char *input) { char *start, *end = input, *out, **argv = NULL; unsigned array_size = 0; @@ -663,14 +664,14 @@ int dm_table_add_target(struct dm_table *t, const char *type, if (!len) { tgt->error = "zero-length target"; - DMERR(": %s\n", tgt->error); + DMERR("%s", tgt->error); return -EINVAL; } tgt->type = dm_get_target_type(type); if (!tgt->type) { tgt->error = "unknown target type"; - DMERR(": %s\n", tgt->error); + DMERR("%s", tgt->error); return -EINVAL; } @@ -688,7 +689,7 @@ int dm_table_add_target(struct dm_table *t, const char *type, goto bad; } - r = split_args(&argc, &argv, params); + r = dm_split_args(&argc, &argv, params); if (r) { tgt->error = "couldn't split parameters (insufficient memory)"; goto bad; @@ -707,7 +708,7 @@ int dm_table_add_target(struct dm_table *t, const char *type, return 0; bad: - DMERR(": %s\n", tgt->error); + DMERR("%s", tgt->error); dm_put_target_type(tgt->type); return r; } @@ -825,7 +826,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) * Make sure we obey the optimistic sub devices * restrictions. */ - q->max_sectors = t->limits.max_sectors; + blk_queue_max_sectors(q, t->limits.max_sectors); q->max_phys_segments = t->limits.max_phys_segments; q->max_hw_segments = t->limits.max_hw_segments; q->hardsect_size = t->limits.hardsect_size; @@ -900,6 +901,28 @@ void dm_table_unplug_all(struct dm_table *t) } } +int dm_table_flush_all(struct dm_table *t) +{ + struct list_head *d, *devices = dm_table_get_devices(t); + int ret = 0; + + for (d = devices->next; d != devices; d = d->next) { + struct dm_dev *dd = list_entry(d, struct dm_dev, list); + request_queue_t *q = bdev_get_queue(dd->bdev); + int err; + + if (!q->issue_flush_fn) + err = -EOPNOTSUPP; + else + err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL); + + if (!ret) + ret = err; + } + + return ret; +} + EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); @@ -908,3 +931,4 @@ EXPORT_SYMBOL(dm_table_get_mode); EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_unplug_all); +EXPORT_SYMBOL(dm_table_flush_all); diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 2f67b4d68..aecd9e0c2 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c @@ -120,10 +120,9 @@ int dm_register_target(struct target_type *t) return -ENOMEM; down_write(&_lock); - if (__find_target_type(t->name)) { - kfree(ti); + if (__find_target_type(t->name)) rv = -EEXIST; - } else + else list_add(&ti->list, &_targets); up_write(&_lock); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 01794ed39..bf99fec5d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -15,15 +16,13 @@ #include #include #include +#include static const char *_name = DM_NAME; static unsigned int major = 0; static unsigned int _major = 0; -static int realloc_minor_bits(unsigned long requested_minor); -static void free_minor_bits(void); - /* * One of these is allocated per bio. */ @@ -61,6 +60,8 @@ struct mapped_device { request_queue_t *queue; struct gendisk *disk; + void *interface_ptr; + /* * A list of ios that arrived while we were suspended. */ @@ -113,19 +114,11 @@ static int __init local_init(void) return -ENOMEM; } - r = realloc_minor_bits(1024); - if (r < 0) { - kmem_cache_destroy(_tio_cache); - kmem_cache_destroy(_io_cache); - return r; - } - _major = major; r = register_blkdev(_major, _name); if (r < 0) { kmem_cache_destroy(_tio_cache); kmem_cache_destroy(_io_cache); - free_minor_bits(); return r; } @@ -139,7 +132,6 @@ static void local_exit(void) { kmem_cache_destroy(_tio_cache); kmem_cache_destroy(_io_cache); - free_minor_bits(); if (unregister_blkdev(_major, _name) < 0) DMERR("devfs_unregister_blkdev failed"); @@ -149,23 +141,20 @@ static void local_exit(void) DMINFO("cleaned up"); } -/* - * We have a lot of init/exit functions, so it seems easier to - * store them in an array. The disposable macro 'xx' - * expands a prefix into a pair of function names. - */ -static struct { - int (*init) (void); - void (*exit) (void); - -} _inits[] = { -#define xx(n) {n ## _init, n ## _exit}, - xx(local) - xx(dm_target) - xx(dm_linear) - xx(dm_stripe) - xx(dm_interface) -#undef xx +int (*_inits[])(void) __initdata = { + local_init, + dm_target_init, + dm_linear_init, + dm_stripe_init, + dm_interface_init, +}; + +void (*_exits[])(void) = { + local_exit, + dm_target_exit, + dm_linear_exit, + dm_stripe_exit, + dm_interface_exit, }; static int __init dm_init(void) @@ -175,7 +164,7 @@ static int __init dm_init(void) int r, i; for (i = 0; i < count; i++) { - r = _inits[i].init(); + r = _inits[i](); if (r) goto bad; } @@ -184,17 +173,17 @@ static int __init dm_init(void) bad: while (i--) - _inits[i].exit(); + _exits[i](); return r; } static void __exit dm_exit(void) { - int i = ARRAY_SIZE(_inits); + int i = ARRAY_SIZE(_exits); while (i--) - _inits[i].exit(); + _exits[i](); } /* @@ -597,6 +586,21 @@ static int dm_request(request_queue_t *q, struct bio *bio) return 0; } +static int dm_flush_all(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct mapped_device *md = q->queuedata; + struct dm_table *map = dm_get_table(md); + int ret = -ENXIO; + + if (map) { + ret = dm_table_flush_all(md->map); + dm_table_put(map); + } + + return ret; +} + static void dm_unplug_all(request_queue_t *q) { struct mapped_device *md = q->queuedata; @@ -624,109 +628,86 @@ static int dm_any_congested(void *congested_data, int bdi_bits) } /*----------------------------------------------------------------- - * A bitset is used to keep track of allocated minor numbers. + * An IDR is used to keep track of allocated minor numbers. *---------------------------------------------------------------*/ static DECLARE_MUTEX(_minor_lock); -static unsigned long *_minor_bits = NULL; -static unsigned long _max_minors = 0; - -#define MINORS_SIZE(minors) ((minors / BITS_PER_LONG) * sizeof(unsigned long)) - -static int realloc_minor_bits(unsigned long requested_minor) -{ - unsigned long max_minors; - unsigned long *minor_bits, *tmp; - - if (requested_minor < _max_minors) - return -EINVAL; - - /* Round up the requested minor to the next power-of-2. */ - max_minors = 1 << fls(requested_minor - 1); - if (max_minors > (1 << MINORBITS)) - return -EINVAL; - - minor_bits = kmalloc(MINORS_SIZE(max_minors), GFP_KERNEL); - if (!minor_bits) - return -ENOMEM; - memset(minor_bits, 0, MINORS_SIZE(max_minors)); - - /* Copy the existing bit-set to the new one. */ - if (_minor_bits) - memcpy(minor_bits, _minor_bits, MINORS_SIZE(_max_minors)); - - tmp = _minor_bits; - _minor_bits = minor_bits; - _max_minors = max_minors; - if (tmp) - kfree(tmp); - - return 0; -} - -static void free_minor_bits(void) -{ - down(&_minor_lock); - kfree(_minor_bits); - _minor_bits = NULL; - _max_minors = 0; - up(&_minor_lock); -} +static DEFINE_IDR(_minor_idr); static void free_minor(unsigned int minor) { down(&_minor_lock); - if (minor < _max_minors) - clear_bit(minor, _minor_bits); + idr_remove(&_minor_idr, minor); up(&_minor_lock); } /* * See if the device with a specific minor # is free. */ -static int specific_minor(unsigned int minor) +static int specific_minor(struct mapped_device *md, unsigned int minor) { - int r = 0; + int r, m; - if (minor > (1 << MINORBITS)) + if (minor >= (1 << MINORBITS)) return -EINVAL; down(&_minor_lock); - if (minor >= _max_minors) { - r = realloc_minor_bits(minor); - if (r) { - up(&_minor_lock); - return r; - } + + if (idr_find(&_minor_idr, minor)) { + r = -EBUSY; + goto out; + } + + r = idr_pre_get(&_minor_idr, GFP_KERNEL); + if (!r) { + r = -ENOMEM; + goto out; + } + + r = idr_get_new_above(&_minor_idr, md, minor, &m); + if (r) { + goto out; } - if (test_and_set_bit(minor, _minor_bits)) + if (m != minor) { + idr_remove(&_minor_idr, m); r = -EBUSY; - up(&_minor_lock); + goto out; + } +out: + up(&_minor_lock); return r; } -static int next_free_minor(unsigned int *minor) +static int next_free_minor(struct mapped_device *md, unsigned int *minor) { int r; unsigned int m; down(&_minor_lock); - m = find_first_zero_bit(_minor_bits, _max_minors); - if (m >= _max_minors) { - r = realloc_minor_bits(_max_minors * 2); - if (r) { - up(&_minor_lock); - return r; - } - m = find_first_zero_bit(_minor_bits, _max_minors); + + r = idr_pre_get(&_minor_idr, GFP_KERNEL); + if (!r) { + r = -ENOMEM; + goto out; + } + + r = idr_get_new(&_minor_idr, md, &m); + if (r) { + goto out; + } + + if (m >= (1 << MINORBITS)) { + idr_remove(&_minor_idr, m); + r = -ENOSPC; + goto out; } - set_bit(m, _minor_bits); *minor = m; - up(&_minor_lock); - return 0; +out: + up(&_minor_lock); + return r; } static struct block_device_operations dm_blk_dops; @@ -745,7 +726,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) } /* get a minor number for the dev */ - r = persistent ? specific_minor(minor) : next_free_minor(&minor); + r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor); if (r < 0) goto bad1; @@ -764,6 +745,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) md->queue->backing_dev_info.congested_data = md; blk_queue_make_request(md->queue, dm_request); md->queue->unplug_fn = dm_unplug_all; + md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, mempool_free_slab, _io_cache); @@ -823,7 +805,7 @@ static void event_callback(void *context) { struct mapped_device *md = (struct mapped_device *) context; - atomic_inc(&md->event_nr);; + atomic_inc(&md->event_nr); wake_up(&md->eventq); } @@ -901,6 +883,32 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result) return create_aux(minor, 1, result); } +void *dm_get_mdptr(dev_t dev) +{ + struct mapped_device *md; + void *mdptr = NULL; + unsigned minor = MINOR(dev); + + if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) + return NULL; + + down(&_minor_lock); + + md = idr_find(&_minor_idr, minor); + + if (md && (dm_disk(md)->first_minor == minor)) + mdptr = md->interface_ptr; + + up(&_minor_lock); + + return mdptr; +} + +void dm_set_mdptr(struct mapped_device *md, void *ptr) +{ + md->interface_ptr = ptr; +} + void dm_get(struct mapped_device *md) { atomic_inc(&md->holders); @@ -1160,5 +1168,5 @@ module_exit(dm_exit); module_param(major, uint, 0); MODULE_PARM_DESC(major, "The major number of the device mapper"); MODULE_DESCRIPTION(DM_NAME " driver"); -MODULE_AUTHOR("Joe Thornber "); +MODULE_AUTHOR("Joe Thornber "); MODULE_LICENSE("GPL"); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index b4b915fbd..4ff5be590 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -2,6 +2,7 @@ * Internal header file for device mapper * * Copyright (C) 2001, 2002 Sistina Software + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -19,6 +20,9 @@ #define DMERR(f, x...) printk(KERN_ERR DM_NAME ": " f "\n" , ## x) #define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x) +#define DMEMIT(x...) sz += ((sz >= maxlen) ? \ + 0 : scnprintf(result + sz, maxlen - sz, x)) + /* * FIXME: I think this should be with the definition of sector_t * in types.h. @@ -51,6 +55,8 @@ struct mapped_device; *---------------------------------------------------------------*/ int dm_create(struct mapped_device **md); int dm_create_with_minor(unsigned int minor, struct mapped_device **md); +void dm_set_mdptr(struct mapped_device *md, void *ptr); +void *dm_get_mdptr(dev_t dev); /* * Reference counting for md. @@ -113,6 +119,7 @@ void dm_table_suspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); +int dm_table_flush_all(struct dm_table *t); /*----------------------------------------------------------------- * A registry of target types. @@ -161,6 +168,8 @@ static inline unsigned long to_bytes(sector_t n) return (n << 9); } +int dm_split_args(int *argc, char ***argvp, char *input); + /* * The device-mapper can be driven through one of two interfaces; * ioctl or filesystem, depending which patch you have applied. diff --git a/drivers/md/linear.c b/drivers/md/linear.c index e0aa017a2..735651144 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) return hash->dev0; } - /** * linear_mergeable_bvec -- tell bio layer if a two requests can be merged * @q: request queue @@ -93,14 +92,33 @@ static void linear_unplug(request_queue_t *q) } } +static int linear_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + linear_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; i < mddev->raid_disks && ret == 0; i++) { + struct block_device *bdev = conf->disks[i].rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + } + return ret; +} static int linear_run (mddev_t *mddev) { linear_conf_t *conf; struct linear_hash *table; mdk_rdev_t *rdev; - int size, i, nb_zone, cnt; - unsigned int curr_offset; + int i, nb_zone, cnt; + sector_t start; + sector_t curr_offset; struct list_head *tmp; conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t), @@ -137,7 +155,7 @@ static int linear_run (mddev_t *mddev) */ if (rdev->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->size = rdev->size; mddev->array_size += rdev->size; @@ -175,23 +193,24 @@ static int linear_run (mddev_t *mddev) * Here we generate the linear hash table */ table = conf->hash_table; - size = 0; + start = 0; curr_offset = 0; for (i = 0; i < cnt; i++) { dev_info_t *disk = conf->disks + i; + if (start > curr_offset) + table[-1].dev1 = disk; + disk->offset = curr_offset; curr_offset += disk->size; - if (size < 0) { - table[-1].dev1 = disk; - } - size += disk->size; - - while (size>0) { + /* 'curr_offset' is the end of this disk + * 'start' is the start of table + */ + while (start < curr_offset) { table->dev0 = disk; table->dev1 = NULL; - size -= conf->smallest->size; + start += conf->smallest->size; table++; } } @@ -200,6 +219,7 @@ static int linear_run (mddev_t *mddev) blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; + mddev->queue->issue_flush_fn = linear_issue_flush; return 0; out: @@ -212,6 +232,7 @@ static int linear_stop (mddev_t *mddev) { linear_conf_t *conf = mddev_to_conf(mddev); + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ kfree(conf->hash_table); kfree(conf); @@ -247,10 +268,11 @@ static int linear_make_request (request_queue_t *q, struct bio *bio) char b[BDEVNAME_SIZE]; printk("linear_make_request: Block %llu out of bounds on " - "dev %s size %ld offset %ld\n", + "dev %s size %llu offset %llu\n", (unsigned long long)block, bdevname(tmp_dev->rdev->bdev, b), - tmp_dev->size, tmp_dev->offset); + (unsigned long long)tmp_dev->size, + (unsigned long long)tmp_dev->offset); bio_io_error(bio, bio->bi_size); return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 77cd6e9f3..6ec07fc7c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -154,6 +154,7 @@ static spinlock_t all_mddevs_lock = SPIN_LOCK_UNLOCKED; tmp = tmp->next;}) \ ) + static int md_fail_request (request_queue_t *q, struct bio *bio) { bio_io_error(bio, bio->bi_size); @@ -373,7 +374,7 @@ static int read_disk_sb(mdk_rdev_t * rdev) return 0; fail: - printk(KERN_ERR "md: disabled device %s, could not read superblock.\n", + printk(KERN_WARNING "md: disabled device %s, could not read superblock.\n", bdevname(rdev->bdev,b)); return -EINVAL; } @@ -439,6 +440,7 @@ static unsigned int calc_sb_csum(mdp_super_t * sb) return csum; } + /* * Handle superblock details. * We want to be able to handle multiple superblock formats @@ -521,7 +523,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version if (sb->raid_disks <= 0) goto abort; - if (calc_sb_csum(sb) != sb->sb_csum) { + if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) { printk(KERN_WARNING "md: invalid superblock checksum on %s\n", b); goto abort; @@ -745,13 +747,23 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) { unsigned int disk_csum, csum; - int size = 256 + sb->max_dev*2; + unsigned long long newcsum; + int size = 256 + le32_to_cpu(sb->max_dev)*2; + unsigned int *isuper = (unsigned int*)sb; + int i; disk_csum = sb->sb_csum; sb->sb_csum = 0; - csum = csum_partial((void *)sb, size, 0); + newcsum = 0; + for (i=0; size>=4; size -= 4 ) + newcsum += le32_to_cpu(*isuper++); + + if (size == 2) + newcsum += le16_to_cpu(*(unsigned short*) isuper); + + csum = (newcsum & 0xffffffff) + (newcsum >> 32); sb->sb_csum = disk_csum; - return csum; + return cpu_to_le32(csum); } static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) @@ -773,7 +785,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) case 0: sb_offset = rdev->bdev->bd_inode->i_size >> 9; sb_offset -= 8*2; - sb_offset &= ~(4*2); + sb_offset &= ~(4*2-1); /* convert from sectors to K */ sb_offset /= 2; break; @@ -806,6 +818,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) bdevname(rdev->bdev,b)); return -EINVAL; } + if (le64_to_cpu(sb->data_size) < 10) { + printk("md: data_size too small on %s\n", + bdevname(rdev->bdev,b)); + return -EINVAL; + } rdev->preferred_minor = 0xffff; rdev->data_offset = le64_to_cpu(sb->data_offset); @@ -850,7 +867,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) if (mddev->raid_disks == 0) { mddev->major_version = 1; - mddev->minor_version = 0; mddev->patch_version = 0; mddev->persistent = 1; mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; @@ -859,7 +875,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->level = le32_to_cpu(sb->level); mddev->layout = le32_to_cpu(sb->layout); mddev->raid_disks = le32_to_cpu(sb->raid_disks); - mddev->size = (u32)le64_to_cpu(sb->size); + mddev->size = le64_to_cpu(sb->size)/2; mddev->events = le64_to_cpu(sb->events); mddev->recovery_cp = le64_to_cpu(sb->resync_offset); @@ -927,7 +943,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) if (rdev2->desc_nr > max_dev) max_dev = rdev2->desc_nr; - sb->max_dev = max_dev; + sb->max_dev = cpu_to_le32(max_dev); for (i=0; idev_roles[max_dev] = cpu_to_le16(0xfffe); @@ -1042,20 +1058,24 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) /* * prevent the device from being mounted, repartitioned or * otherwise reused by a RAID array (or any other kernel - * subsystem), by opening the device. [simply getting an - * inode is not enough, the SCSI module usage code needs - * an explicit open() on the device] + * subsystem), by bd_claiming the device. */ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) { int err = 0; struct block_device *bdev; + char b[BDEVNAME_SIZE]; bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); - if (IS_ERR(bdev)) + if (IS_ERR(bdev)) { + printk(KERN_ERR "md: could not open %s.\n", + __bdevname(dev, b)); return PTR_ERR(bdev); + } err = bd_claim(bdev, rdev); if (err) { + printk(KERN_ERR "md: could not bd_claim %s.\n", + bdevname(bdev, b)); blkdev_put(bdev); return err; } @@ -1117,10 +1137,7 @@ static void export_array(mddev_t *mddev) static void print_desc(mdp_disk_t *desc) { - char b[BDEVNAME_SIZE]; - - printk(" DISK\n", desc->number, - __bdevname(MKDEV(desc->major, desc->minor), b), + printk(" DISK\n", desc->number, desc->major,desc->minor,desc->raid_disk,desc->state); } @@ -1312,8 +1329,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { - printk(KERN_ERR "md: could not alloc mem for %s!\n", - __bdevname(newdev, b)); + printk(KERN_ERR "md: could not alloc mem for new device!\n"); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -1322,11 +1338,9 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi goto abort_free; err = lock_rdev(rdev, newdev); - if (err) { - printk(KERN_ERR "md: could not lock %s.\n", - __bdevname(newdev, b)); + if (err) goto abort_free; - } + rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; @@ -1424,17 +1438,6 @@ static int analyze_sbs(mddev_t * mddev) } - /* - * Check if we can support this RAID array - */ - if (mddev->major_version != MD_MAJOR_VERSION || - mddev->minor_version > MD_MINOR_VERSION) { - printk(KERN_ALERT - "md: %s: unsupported raid array version %d.%d.%d\n", - mdname(mddev), mddev->major_version, - mddev->minor_version, mddev->patch_version); - goto abort; - } if ((mddev->recovery_cp != MaxSector) && ((mddev->level == 1) || @@ -1444,8 +1447,6 @@ static int analyze_sbs(mddev_t * mddev) mdname(mddev)); return 0; -abort: - return 1; } int mdp_major = 0; @@ -1615,6 +1616,8 @@ static int do_md_run(mddev_t * mddev) mddev->pers = pers[pnum]; spin_unlock(&pers_lock); + mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ + err = mddev->pers->run(mddev); if (err) { printk(KERN_ERR "md: pers->run() failed ...\n"); @@ -1776,7 +1779,7 @@ static void autorun_array(mddev_t *mddev) err = do_md_run (mddev); if (err) { - printk(KERN_WARNING "md :do_md_run() returned %d\n", err); + printk(KERN_WARNING "md: do_md_run() returned %d\n", err); do_md_stop (mddev, 0); } } @@ -1881,11 +1884,9 @@ static int autostart_array(dev_t startdev) mdk_rdev_t *start_rdev = NULL, *rdev; start_rdev = md_import_device(startdev, 0, 0); - if (IS_ERR(start_rdev)) { - printk(KERN_WARNING "md: could not import %s!\n", - __bdevname(startdev, b)); + if (IS_ERR(start_rdev)) return err; - } + /* NOTE: this can only work for 0.90.0 superblocks */ sb = (mdp_super_t*)page_address(start_rdev->sb_page); @@ -1916,12 +1917,9 @@ static int autostart_array(dev_t startdev) if (MAJOR(dev) != desc->major || MINOR(dev) != desc->minor) continue; rdev = md_import_device(dev, 0, 0); - if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: could not import %s," - " trying to run array nevertheless.\n", - __bdevname(dev, b)); + if (IS_ERR(rdev)) continue; - } + list_add(&rdev->same_set, &pending_raid_disks); } @@ -1971,7 +1969,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg) info.major_version = mddev->major_version; info.minor_version = mddev->minor_version; - info.patch_version = 1; + info.patch_version = MD_PATCHLEVEL_VERSION; info.ctime = mddev->ctime; info.level = mddev->level; info.size = mddev->size; @@ -2153,42 +2151,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) return 0; } -static int hot_generate_error(mddev_t * mddev, dev_t dev) -{ - char b[BDEVNAME_SIZE]; - struct request_queue *q; - mdk_rdev_t *rdev; - - if (!mddev->pers) - return -ENODEV; - - printk(KERN_INFO "md: trying to generate %s error in %s ... \n", - __bdevname(dev, b), mdname(mddev)); - - rdev = find_rdev(mddev, dev); - if (!rdev) { - /* MD_BUG(); */ /* like hell - it's not a driver bug */ - return -ENXIO; - } - - if (rdev->desc_nr == -1) { - MD_BUG(); - return -EINVAL; - } - if (!rdev->in_sync) - return -ENODEV; - - q = bdev_get_queue(rdev->bdev); - if (!q) { - MD_BUG(); - return -ENODEV; - } - printk(KERN_INFO "md: okay, generating error!\n"); -// q->oneshot_error = 1; // disabled for now - - return 0; -} - static int hot_remove_disk(mddev_t * mddev, dev_t dev) { char b[BDEVNAME_SIZE]; @@ -2197,9 +2159,6 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to remove %s from %s ... \n", - __bdevname(dev, b), mdname(mddev)); - rdev = find_rdev(mddev, dev); if (!rdev) return -ENXIO; @@ -2227,9 +2186,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to hot-add %s to %s ... \n", - __bdevname(dev, b), mdname(mddev)); - if (mddev->major_version != 0) { printk(KERN_WARNING "%s: HOT_ADD may only be used with" " version-0 superblocks.\n", @@ -2395,16 +2351,27 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) /* mddev->patch_version != info->patch_version || */ mddev->ctime != info->ctime || mddev->level != info->level || - mddev->layout != info->layout || +/* mddev->layout != info->layout || */ !mddev->persistent != info->not_persistent|| mddev->chunk_size != info->chunk_size ) return -EINVAL; /* Check there is only one change */ if (mddev->size != info->size) cnt++; if (mddev->raid_disks != info->raid_disks) cnt++; + if (mddev->layout != info->layout) cnt++; if (cnt == 0) return 0; if (cnt > 1) return -EINVAL; + if (mddev->layout != info->layout) { + /* Change layout + * we don't need to do anything at the md level, the + * personality will take care of it all. + */ + if (mddev->pers->reconfig == NULL) + return -EINVAL; + else + return mddev->pers->reconfig(mddev, info->layout, -1); + } if (mddev->size != info->size) { mdk_rdev_t * rdev; struct list_head *tmp; @@ -2413,7 +2380,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) /* The "size" is the amount of each device that is used. * This can only make sense for arrays with redundancy. * linear and raid0 always use whatever space is available - * We can only consider changing the size of no resync + * We can only consider changing the size if no resync * or reconstruction is happening, and if the new size * is acceptable. It must fit before the sb_offset or, * if that is tsk) { MD_BUG(); @@ -2919,6 +2882,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) if (!mddev->pers->error_handler) return; mddev->pers->error_handler(mddev,rdev); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); } @@ -2951,7 +2915,11 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) unsigned long max_blocks, resync, res, dt, db, rt; resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; - max_blocks = mddev->size; + + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + max_blocks = mddev->resync_max_sectors >> 1; + else + max_blocks = mddev->size; /* * Should not happen. @@ -3187,11 +3155,6 @@ int unregister_md_personality(int pnum) return 0; } -void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors) -{ - rdev->bdev->bd_contains->bd_disk->sync_io += nr_sectors; -} - static int is_mddev_idle(mddev_t *mddev) { mdk_rdev_t * rdev; @@ -3204,8 +3167,12 @@ static int is_mddev_idle(mddev_t *mddev) struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; curr_events = disk_stat_read(disk, read_sectors) + disk_stat_read(disk, write_sectors) - - disk->sync_io; - if ((curr_events - rdev->last_events) > 32) { + atomic_read(&disk->sync_io); + /* Allow some slack between valud of curr_events and last_events, + * as there are some uninteresting races. + * Note: the following is an unsigned comparison. + */ + if ((curr_events - rdev->last_events + 32) > 64) { rdev->last_events = curr_events; idle = 0; } @@ -3308,38 +3275,66 @@ static void md_do_sync(mddev_t *mddev) * 1 == like 2, but have yielded to allow conflicting resync to * commense * other == active in resync - this many blocks + * + * Before starting a resync we must have set curr_resync to + * 2, and then checked that every "conflicting" array has curr_resync + * less than ours. When we find one that is the same or higher + * we wait on resync_wait. To avoid deadlock, we reduce curr_resync + * to 1 if we choose to yield (based arbitrarily on address of mddev structure). + * This will mean we have to start checking from the beginning again. + * */ + do { mddev->curr_resync = 2; + try_again: + if (signal_pending(current)) { + flush_signals(current); + goto skip; + } ITERATE_MDDEV(mddev2,tmp) { + printk("."); if (mddev2 == mddev) continue; if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { - printk(KERN_INFO "md: delaying resync of %s" - " until %s has finished resync (they" - " share one or more physical units)\n", - mdname(mddev), mdname(mddev2)); - if (mddev < mddev2) {/* arbitrarily yield */ + DEFINE_WAIT(wq); + if (mddev < mddev2 && mddev->curr_resync == 2) { + /* arbitrarily yield */ mddev->curr_resync = 1; wake_up(&resync_wait); } - if (wait_event_interruptible(resync_wait, - mddev2->curr_resync < mddev->curr_resync)) { - flush_signals(current); + if (mddev > mddev2 && mddev->curr_resync == 1) + /* no need to wait here, we can wait the next + * time 'round when curr_resync == 2 + */ + continue; + prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); + if (!signal_pending(current) + && mddev2->curr_resync >= mddev->curr_resync) { + printk(KERN_INFO "md: delaying resync of %s" + " until %s has finished resync (they" + " share one or more physical units)\n", + mdname(mddev), mdname(mddev2)); mddev_put(mddev2); - goto skip; + schedule(); + finish_wait(&resync_wait, &wq); + goto try_again; } - } - if (mddev->curr_resync == 1) { - mddev_put(mddev2); - break; + finish_wait(&resync_wait, &wq); } } } while (mddev->curr_resync < 2); - max_sectors = mddev->size << 1; + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + /* resync follows the size requested by the personality, + * which default to physical size, but can be virtual size + */ + max_sectors = mddev->resync_max_sectors; + else + /* recovery follows the physical size of devices */ + max_sectors = mddev->size << 1; printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" @@ -3365,7 +3360,7 @@ static void md_do_sync(mddev_t *mddev) * Tune reconstruction: */ window = 32*(PAGE_SIZE/512); - printk(KERN_INFO "md: using %dk window, over a total of %Lu blocks.\n", + printk(KERN_INFO "md: using %dk window, over a total of %llu blocks.\n", window/2,(unsigned long long) max_sectors/2); atomic_set(&mddev->recovery_active, 0); @@ -3399,7 +3394,7 @@ static void md_do_sync(mddev_t *mddev) break; repeat: - if (jiffies >= mark[last_mark] + SYNC_MARK_STEP ) { + if (time_after_eq(jiffies, mark[last_mark] + SYNC_MARK_STEP )) { /* step marks */ int next = (last_mark+1) % SYNC_MARKS; @@ -3438,8 +3433,7 @@ static void md_do_sync(mddev_t *mddev) if (currspeed > sysctl_speed_limit_min) { if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/4); + msleep_interruptible(250); goto repeat; } } @@ -3471,6 +3465,7 @@ static void md_do_sync(mddev_t *mddev) md_enter_safemode(mddev); skip: mddev->curr_resync = 0; + wake_up(&resync_wait); set_bit(MD_RECOVERY_DONE, &mddev->recovery); md_wakeup_thread(mddev->thread); } @@ -3538,14 +3533,11 @@ void md_check_recovery(mddev_t *mddev) mddev->recovery = 0; /* flag recovery needed just to double check */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - wake_up(&resync_wait); goto unlock; } - if (mddev->recovery) { + if (mddev->recovery) /* probably just the RECOVERY_NEEDED flag */ mddev->recovery = 0; - wake_up(&resync_wait); - } /* no recovery is running. * remove any failed drives, then @@ -3697,7 +3689,6 @@ void md_autodetect_dev(dev_t dev) static void autostart_arrays(int part) { - char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; int i; @@ -3707,11 +3698,9 @@ static void autostart_arrays(int part) dev_t dev = detected_devices[i]; rdev = md_import_device(dev,0, 0); - if (IS_ERR(rdev)) { - printk(KERN_ALERT "md: could not import %s!\n", - __bdevname(dev, b)); + if (IS_ERR(rdev)) continue; - } + if (rdev->faulty) { MD_BUG(); continue; @@ -3762,7 +3751,6 @@ module_exit(md_exit) EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); EXPORT_SYMBOL(md_error); -EXPORT_SYMBOL(md_sync_acct); EXPORT_SYMBOL(md_done_sync); EXPORT_SYMBOL(md_write_start); EXPORT_SYMBOL(md_write_end); @@ -3771,6 +3759,5 @@ EXPORT_SYMBOL(md_register_thread); EXPORT_SYMBOL(md_unregister_thread); EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_print_devices); -EXPORT_SYMBOL(md_interrupt_thread); EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index a9df710da..309398219 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -36,8 +36,6 @@ static mdk_personality_t multipath_personality; -static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED; -struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail; static void *mp_pool_alloc(int gfp_flags, void *data) @@ -63,16 +61,16 @@ static int multipath_map (multipath_conf_t *conf) * now we use the first available disk. */ - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); for (i = 0; i < disks; i++) { mdk_rdev_t *rdev = conf->multipaths[i].rdev; if (rdev && rdev->in_sync) { atomic_inc(&rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); return i; } } - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); printk(KERN_ERR "multipath_map(): no more operational IO paths?\n"); return (-1); @@ -82,14 +80,11 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh) { unsigned long flags; mddev_t *mddev = mp_bh->mddev; + multipath_conf_t *conf = mddev_to_conf(mddev); - spin_lock_irqsave(&retry_list_lock, flags); - if (multipath_retry_list == NULL) - multipath_retry_tail = &multipath_retry_list; - *multipath_retry_tail = mp_bh; - multipath_retry_tail = &mp_bh->next_mp; - mp_bh->next_mp = NULL; - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); + list_add(&mp_bh->retry_list, &conf->retry_list); + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); } @@ -99,12 +94,12 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh) * operation and are ready to return a success/failure code to the buffer * cache layer. */ -static void multipath_end_bh_io (struct multipath_bh *mp_bh, int uptodate) +static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err) { struct bio *bio = mp_bh->master_bio; multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev); - bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO); + bio_endio(bio, bio->bi_size, err); mempool_free(mp_bh, conf->pool); } @@ -119,8 +114,8 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error) return 1; if (uptodate) - multipath_end_bh_io(mp_bh, uptodate); - else if ((bio->bi_rw & (1 << BIO_RW_AHEAD)) == 0) { + multipath_end_bh_io(mp_bh, 0); + else if (!bio_rw_ahead(bio)) { /* * oops, IO error: */ @@ -131,7 +126,7 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error) (unsigned long long)bio->bi_sector); multipath_reschedule_retry(mp_bh); } else - multipath_end_bh_io(mp_bh, 0); + multipath_end_bh_io(mp_bh, error); rdev_dec_pending(rdev, conf->mddev); return 0; } @@ -140,26 +135,26 @@ static void unplug_slaves(mddev_t *mddev) { multipath_conf_t *conf = mddev_to_conf(mddev); int i; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); + rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = conf->multipaths[i].rdev; - if (rdev && !rdev->faulty) { + if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); - spin_lock_irqsave(&conf->device_lock, flags); - atomic_dec(&rdev->nr_pending); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); } + static void multipath_unplug(request_queue_t *q) { unplug_slaves(q->queuedata); @@ -195,6 +190,7 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio) multipath = conf->multipaths + mp_bh->path; mp_bh->bio = *bio; + mp_bh->bio.bi_sector += multipath->rdev->data_offset; mp_bh->bio.bi_bdev = multipath->rdev->bdev; mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST); mp_bh->bio.bi_end_io = multipath_end_request; @@ -217,6 +213,35 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) seq_printf (seq, "]"); } +static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + multipath_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = conf->multipaths[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} /* * Careful, this can execute in IRQ contexts as well! @@ -285,10 +310,9 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) struct multipath_info *p; print_multipath_conf(conf); - spin_lock_irq(&conf->device_lock); + for (path=0; pathraid_disks; path++) if ((p=conf->multipaths+path)->rdev == NULL) { - p->rdev = rdev; blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); @@ -300,14 +324,14 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ if (rdev->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); conf->working_disks++; rdev->raid_disk = path; rdev->in_sync = 1; + p->rdev = rdev; found = 1; } - spin_unlock_irq(&conf->device_lock); print_multipath_conf(conf); return found; @@ -316,26 +340,29 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) static int multipath_remove_disk(mddev_t *mddev, int number) { multipath_conf_t *conf = mddev->private; - int err = 1; + int err = 0; + mdk_rdev_t *rdev; struct multipath_info *p = conf->multipaths + number; print_multipath_conf(conf); - spin_lock_irq(&conf->device_lock); - if (p->rdev) { - if (p->rdev->in_sync || - atomic_read(&p->rdev->nr_pending)) { + rdev = p->rdev; + if (rdev) { + if (rdev->in_sync || + atomic_read(&rdev->nr_pending)) { printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number); err = -EBUSY; goto abort; } p->rdev = NULL; - err = 0; + synchronize_kernel(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + p->rdev = rdev; + } } - if (err) - MD_BUG(); abort: - spin_unlock_irq(&conf->device_lock); print_multipath_conf(conf); return err; @@ -357,18 +384,18 @@ static void multipathd (mddev_t *mddev) struct bio *bio; unsigned long flags; multipath_conf_t *conf = mddev_to_conf(mddev); + struct list_head *head = &conf->retry_list; md_check_recovery(mddev); for (;;) { char b[BDEVNAME_SIZE]; - spin_lock_irqsave(&retry_list_lock, flags); - mp_bh = multipath_retry_list; - if (!mp_bh) + spin_lock_irqsave(&conf->device_lock, flags); + if (list_empty(head)) break; - multipath_retry_list = mp_bh->next_mp; - spin_unlock_irqrestore(&retry_list_lock, flags); + mp_bh = list_entry(head->prev, struct multipath_bh, retry_list); + list_del(head->prev); + spin_unlock_irqrestore(&conf->device_lock, flags); - mddev = mp_bh->mddev; bio = &mp_bh->bio; bio->bi_sector = mp_bh->master_bio->bi_sector; @@ -377,13 +404,14 @@ static void multipathd (mddev_t *mddev) " error for block %llu\n", bdevname(bio->bi_bdev,b), (unsigned long long)bio->bi_sector); - multipath_end_bh_io(mp_bh, 0); + multipath_end_bh_io(mp_bh, -EIO); } else { printk(KERN_ERR "multipath: %s: redirecting sector %llu" " to another IO path\n", bdevname(bio->bi_bdev,b), (unsigned long long)bio->bi_sector); *bio = *(mp_bh->master_bio); + bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset; bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev; bio->bi_rw |= (1 << BIO_RW_FAILFAST); bio->bi_end_io = multipath_end_request; @@ -391,7 +419,7 @@ static void multipathd (mddev_t *mddev) generic_make_request(bio); } } - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); } static int multipath_run (mddev_t *mddev) @@ -435,6 +463,8 @@ static int multipath_run (mddev_t *mddev) mddev->queue->unplug_fn = multipath_unplug; + mddev->queue->issue_flush_fn = multipath_issue_flush; + conf->working_disks = 0; ITERATE_RDEV(mddev,rdev,tmp) { disk_idx = rdev->raid_disk; @@ -452,7 +482,7 @@ static int multipath_run (mddev_t *mddev) * a merge_bvec_fn to be involved in multipath */ if (rdev->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); if (!rdev->faulty) conf->working_disks++; @@ -462,6 +492,7 @@ static int multipath_run (mddev_t *mddev) mddev->sb_dirty = 1; conf->mddev = mddev; conf->device_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&conf->retry_list); if (!conf->working_disks) { printk(KERN_ERR "multipath: no operational IO paths for %s\n", @@ -516,6 +547,7 @@ static int multipath_stop (mddev_t *mddev) md_unregister_thread(mddev->thread); mddev->thread = NULL; + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ mempool_destroy(conf->pool); kfree(conf->multipaths); kfree(conf); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 5f4b8bfef..e7d934eca 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -40,6 +40,27 @@ static void raid0_unplug(request_queue_t *q) } } +static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t **devlist = conf->strip_zone[0].dev; + int i, ret = 0; + + for (i=0; iraid_disks && ret == 0; i++) { + struct block_device *bdev = devlist[i]->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + } + return ret; +} + + static int create_strip_zones (mddev_t *mddev) { int i, c, j; @@ -137,7 +158,7 @@ static int create_strip_zones (mddev_t *mddev) if (rdev1->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); if (!smallest || (rdev1->size size)) smallest = rdev1; @@ -219,6 +240,8 @@ static int create_strip_zones (mddev_t *mddev) mddev->queue->unplug_fn = raid0_unplug; + mddev->queue->issue_flush_fn = raid0_issue_flush; + printk("raid0: done.\n"); return 0; abort: @@ -362,6 +385,7 @@ static int raid0_stop (mddev_t *mddev) { raid0_conf_t *conf = mddev_to_conf(mddev); + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ kfree (conf->hash_table); conf->hash_table = NULL; kfree (conf->strip_zone); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 04b2aef4a..4e25ebd53 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -24,18 +24,12 @@ #include -#define MAJOR_NR MD_MAJOR -#define MD_DRIVER -#define MD_PERSONALITY - /* * Number of guaranteed r1bios in case of extreme VM load: */ #define NR_RAID1_BIOS 256 static mdk_personality_t raid1_personality; -static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(retry_list_head); static void unplug_slaves(mddev_t *mddev); @@ -44,13 +38,12 @@ static void * r1bio_pool_alloc(int gfp_flags, void *data) { struct pool_info *pi = data; r1bio_t *r1_bio; + int size = offsetof(r1bio_t, bios[pi->raid_disks]); /* allocate a r1bio with room for raid_disks entries in the bios array */ - r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks, - gfp_flags); + r1_bio = kmalloc(size, gfp_flags); if (r1_bio) - memset(r1_bio, 0, sizeof(*r1_bio) + - sizeof(struct bio*) * pi->raid_disks); + memset(r1_bio, 0, size); else unplug_slaves(pi->mddev); @@ -104,7 +97,7 @@ static void * r1buf_pool_alloc(int gfp_flags, void *data) bio->bi_io_vec[i].bv_page = page; } - r1_bio->master_bio = bio; + r1_bio->master_bio = NULL; return r1_bio; @@ -189,40 +182,15 @@ static inline void put_buf(r1bio_t *r1_bio) spin_unlock_irqrestore(&conf->resync_lock, flags); } -static int map(mddev_t *mddev, mdk_rdev_t **rdevp) -{ - conf_t *conf = mddev_to_conf(mddev); - int i, disks = conf->raid_disks; - - /* - * Later we do read balancing on the read side - * now we use the first available disk. - */ - - spin_lock_irq(&conf->device_lock); - for (i = 0; i < disks; i++) { - mdk_rdev_t *rdev = conf->mirrors[i].rdev; - if (rdev && rdev->in_sync) { - *rdevp = rdev; - atomic_inc(&rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); - return i; - } - } - spin_unlock_irq(&conf->device_lock); - - printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n"); - return -1; -} - static void reschedule_retry(r1bio_t *r1_bio) { unsigned long flags; mddev_t *mddev = r1_bio->mddev; + conf_t *conf = mddev_to_conf(mddev); - spin_lock_irqsave(&retry_list_lock, flags); - list_add(&r1_bio->retry_list, &retry_list_head); - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); + list_add(&r1_bio->retry_list, &conf->retry_list); + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); } @@ -292,8 +260,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int * oops, read error: */ char b[BDEVNAME_SIZE]; - printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", - bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); + if (printk_ratelimit()) + printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", + bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); reschedule_retry(r1_bio); } @@ -363,14 +332,14 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int * * The rdev for the device selected will have nr_pending incremented. */ -static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio) +static int read_balance(conf_t *conf, r1bio_t *r1_bio) { const unsigned long this_sector = r1_bio->sector; int new_disk = conf->last_used, disk = new_disk; - const int sectors = bio->bi_size >> 9; + const int sectors = r1_bio->sectors; sector_t new_distance, current_distance; - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); /* * Check if it if we can balance. We can balance on the whole * device if no resync is going on, or below the resync window. @@ -378,14 +347,14 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio) */ if (conf->mddev->recovery_cp < MaxSector && (this_sector + sectors >= conf->next_resync)) { - /* make sure that disk is operational */ + /* Choose the first operation device, for consistancy */ new_disk = 0; while (!conf->mirrors[new_disk].rdev || !conf->mirrors[new_disk].rdev->in_sync) { new_disk++; if (new_disk == conf->raid_disks) { - new_disk = 0; + new_disk = -1; break; } } @@ -400,7 +369,7 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio) new_disk = conf->raid_disks; new_disk--; if (new_disk == disk) { - new_disk = conf->last_used; + new_disk = -1; goto rb_out; } } @@ -440,14 +409,14 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio) } while (disk != conf->last_used); rb_out: - r1_bio->read_disk = new_disk; - conf->next_seq_sect = this_sector + sectors; - conf->last_used = new_disk; - if (conf->mirrors[new_disk].rdev) + if (new_disk >= 0) { + conf->next_seq_sect = this_sector + sectors; + conf->last_used = new_disk; atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + } + rcu_read_unlock(); return new_disk; } @@ -456,31 +425,61 @@ static void unplug_slaves(mddev_t *mddev) { conf_t *conf = mddev_to_conf(mddev); int i; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); + rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = conf->mirrors[i].rdev; - if (rdev && atomic_read(&rdev->nr_pending)) { + if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); - spin_lock_irqsave(&conf->device_lock, flags); - atomic_dec(&rdev->nr_pending); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); } + static void raid1_unplug(request_queue_t *q) { unplug_slaves(q->queuedata); } +static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + /* * Throttle resync depth, so that we can both get proper overlapping of * requests, but are still able to handle normal requests quickly. @@ -545,15 +544,26 @@ static int make_request(request_queue_t *q, struct bio * bio) r1_bio->mddev = mddev; r1_bio->sector = bio->bi_sector; + r1_bio->state = 0; + if (bio_data_dir(bio) == READ) { /* * read balancing logic: */ - mirror = conf->mirrors + read_balance(conf, bio, r1_bio); + int rdisk = read_balance(conf, r1_bio); + + if (rdisk < 0) { + /* couldn't find anywhere to read from */ + raid_end_bio_io(r1_bio); + return 0; + } + mirror = conf->mirrors + rdisk; + + r1_bio->read_disk = rdisk; read_bio = bio_clone(bio, GFP_NOIO); - r1_bio->bios[r1_bio->read_disk] = read_bio; + r1_bio->bios[rdisk] = read_bio; read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; @@ -573,7 +583,7 @@ static int make_request(request_queue_t *q, struct bio * bio) * bios[x] to bio */ disks = conf->raid_disks; - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); for (i = 0; i < disks; i++) { if (conf->mirrors[i].rdev && !conf->mirrors[i].rdev->faulty) { @@ -582,7 +592,7 @@ static int make_request(request_queue_t *q, struct bio * bio) } else r1_bio->bios[i] = NULL; } - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); atomic_set(&r1_bio->remaining, 1); md_write_start(mddev); @@ -704,7 +714,6 @@ static int raid1_spare_active(mddev_t *mddev) conf_t *conf = mddev->private; mirror_info_t *tmp; - spin_lock_irq(&conf->device_lock); /* * Find all failed disks within the RAID1 configuration * and mark them readable @@ -719,7 +728,6 @@ static int raid1_spare_active(mddev_t *mddev) tmp->rdev->in_sync = 1; } } - spin_unlock_irq(&conf->device_lock); print_conf(conf); return 0; @@ -733,10 +741,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) int mirror; mirror_info_t *p; - spin_lock_irq(&conf->device_lock); for (mirror=0; mirror < mddev->raid_disks; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { - p->rdev = rdev; blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); @@ -746,14 +752,14 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ if (rdev->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); p->head_position = 0; rdev->raid_disk = mirror; found = 1; + p->rdev = rdev; break; } - spin_unlock_irq(&conf->device_lock); print_conf(conf); return found; @@ -762,24 +768,27 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) static int raid1_remove_disk(mddev_t *mddev, int number) { conf_t *conf = mddev->private; - int err = 1; + int err = 0; + mdk_rdev_t *rdev; mirror_info_t *p = conf->mirrors+ number; print_conf(conf); - spin_lock_irq(&conf->device_lock); - if (p->rdev) { - if (p->rdev->in_sync || - atomic_read(&p->rdev->nr_pending)) { + rdev = p->rdev; + if (rdev) { + if (rdev->in_sync || + atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; } p->rdev = NULL; - err = 0; + synchronize_kernel(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + p->rdev = rdev; + } } - if (err) - MD_BUG(); abort: - spin_unlock_irq(&conf->device_lock); print_conf(conf); return err; @@ -877,7 +886,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) atomic_inc(&conf->mirrors[i].rdev->nr_pending); atomic_inc(&r1_bio->remaining); - md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9); + md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9); generic_make_request(wbio); } @@ -897,11 +906,11 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) static void raid1d(mddev_t *mddev) { - struct list_head *head = &retry_list_head; r1bio_t *r1_bio; struct bio *bio; unsigned long flags; conf_t *conf = mddev_to_conf(mddev); + struct list_head *head = &conf->retry_list; int unplug=0; mdk_rdev_t *rdev; @@ -910,12 +919,12 @@ static void raid1d(mddev_t *mddev) for (;;) { char b[BDEVNAME_SIZE]; - spin_lock_irqsave(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) break; r1_bio = list_entry(head->prev, r1bio_t, retry_list); list_del(head->prev); - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); mddev = r1_bio->mddev; conf = mddev_to_conf(mddev); @@ -925,7 +934,7 @@ static void raid1d(mddev_t *mddev) } else { int disk; bio = r1_bio->bios[r1_bio->read_disk]; - if ((disk=map(mddev, &rdev)) == -1) { + if ((disk=read_balance(conf, r1_bio)) == -1) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" " read error for block %llu\n", bdevname(bio->bi_bdev,b), @@ -934,20 +943,26 @@ static void raid1d(mddev_t *mddev) } else { r1_bio->bios[r1_bio->read_disk] = NULL; r1_bio->read_disk = disk; + bio_put(bio); + bio = bio_clone(r1_bio->master_bio, GFP_NOIO); r1_bio->bios[r1_bio->read_disk] = bio; - printk(KERN_ERR "raid1: %s: redirecting sector %llu to" - " another mirror\n", - bdevname(rdev->bdev,b), - (unsigned long long)r1_bio->sector); - bio->bi_bdev = rdev->bdev; + rdev = conf->mirrors[disk].rdev; + if (printk_ratelimit()) + printk(KERN_ERR "raid1: %s: redirecting sector %llu to" + " another mirror\n", + bdevname(rdev->bdev,b), + (unsigned long long)r1_bio->sector); bio->bi_sector = r1_bio->sector + rdev->data_offset; + bio->bi_bdev = rdev->bdev; + bio->bi_end_io = raid1_end_read_request; bio->bi_rw = READ; + bio->bi_private = r1_bio; unplug = 1; generic_make_request(bio); } } } - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); if (unplug) unplug_slaves(mddev); } @@ -1004,7 +1019,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) * put in a delay to throttle resync. */ if (!go_faster && waitqueue_active(&conf->wait_resume)) - schedule_timeout(HZ); + msleep_interruptible(1000); device_barrier(conf, sector_nr + RESYNC_SECTORS); /* @@ -1014,7 +1029,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) */ disk = conf->last_used; /* make sure disk is operational */ - spin_lock_irq(&conf->device_lock); + while (conf->mirrors[disk].rdev == NULL || !conf->mirrors[disk].rdev->in_sync) { if (disk <= 0) @@ -1025,7 +1040,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) } conf->last_used = disk; atomic_inc(&conf->mirrors[disk].rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + mirror = conf->mirrors + disk; @@ -1078,7 +1093,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) int rv = max_sector - sector_nr; md_done_sync(mddev, rv, 1); put_buf(r1_bio); - atomic_dec(&conf->mirrors[disk].rdev->nr_pending); + rdev_dec_pending(conf->mirrors[disk].rdev, mddev); return rv; } @@ -1117,7 +1132,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) bio = r1_bio->bios[disk]; r1_bio->sectors = nr_sectors; - md_sync_acct(mirror->rdev, nr_sectors); + md_sync_acct(mirror->rdev->bdev, nr_sectors); generic_make_request(bio); @@ -1168,6 +1183,7 @@ static int run(mddev_t *mddev) mddev->queue->unplug_fn = raid1_unplug; + mddev->queue->issue_flush_fn = raid1_issue_flush; ITERATE_RDEV(mddev, rdev, tmp) { disk_idx = rdev->raid_disk; @@ -1186,7 +1202,7 @@ static int run(mddev_t *mddev) */ if (rdev->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->head_position = 0; if (!rdev->faulty && rdev->in_sync) @@ -1195,6 +1211,7 @@ static int run(mddev_t *mddev) conf->raid_disks = mddev->raid_disks; conf->mddev = mddev; conf->device_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&conf->retry_list); if (conf->working_disks == 1) mddev->recovery_cp = MaxSector; @@ -1276,6 +1293,7 @@ static int stop(mddev_t *mddev) md_unregister_thread(mddev->thread); mddev->thread = NULL; + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); if (conf->mirrors) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 6c3fde9ba..596df3cb9 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -36,7 +36,7 @@ * device of the previous section. * Thus there are (near_copies*far_copies) of each chunk, and each is on a different * drive. - * near_copies and far_copies must be at least one, and there product is at most + * near_copies and far_copies must be at least one, and their product is at most * raid_disks. */ @@ -498,7 +498,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) sector_t new_distance, current_distance; raid10_find_phys(conf, r10_bio); - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); /* * Check if we can balance. We can balance on the whole * device if no resync is going on, or below the resync window. @@ -570,7 +570,7 @@ rb_out: if (disk >= 0 && conf->mirrors[disk].rdev) atomic_inc(&conf->mirrors[disk].rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); return disk; } @@ -579,26 +579,26 @@ static void unplug_slaves(mddev_t *mddev) { conf_t *conf = mddev_to_conf(mddev); int i; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); + rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = conf->mirrors[i].rdev; - if (rdev && atomic_read(&rdev->nr_pending)) { + if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); - spin_lock_irqsave(&conf->device_lock, flags); - atomic_dec(&rdev->nr_pending); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); } + static void raid10_unplug(request_queue_t *q) { unplug_slaves(q->queuedata); @@ -609,24 +609,28 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, { mddev_t *mddev = q->queuedata; conf_t *conf = mddev_to_conf(mddev); - unsigned long flags; int i, ret = 0; - spin_lock_irqsave(&conf->device_lock, flags); - for (i=0; iraid_disks; i++) { + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = conf->mirrors[i].rdev; if (rdev && !rdev->faulty) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); - if (r_queue->issue_flush_fn) { - ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); - if (ret) - break; + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); return ret; } @@ -757,7 +761,7 @@ static int make_request(request_queue_t *q, struct bio * bio) * bios[x] to bio */ raid10_find_phys(conf, r10_bio); - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); for (i = 0; i < conf->copies; i++) { int d = r10_bio->devs[i].devnum; if (conf->mirrors[d].rdev && @@ -767,7 +771,7 @@ static int make_request(request_queue_t *q, struct bio * bio) } else r10_bio->devs[i].bio = NULL; } - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); atomic_set(&r10_bio->remaining, 1); md_write_start(mddev); @@ -900,7 +904,6 @@ static int raid10_spare_active(mddev_t *mddev) conf_t *conf = mddev->private; mirror_info_t *tmp; - spin_lock_irq(&conf->device_lock); /* * Find all non-in_sync disks within the RAID10 configuration * and mark them in_sync @@ -915,7 +918,6 @@ static int raid10_spare_active(mddev_t *mddev) tmp->rdev->in_sync = 1; } } - spin_unlock_irq(&conf->device_lock); print_conf(conf); return 0; @@ -934,10 +936,9 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) * very different from resync */ return 0; - spin_lock_irq(&conf->device_lock); + for (mirror=0; mirror < mddev->raid_disks; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { - p->rdev = rdev; blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); @@ -952,9 +953,9 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) p->head_position = 0; rdev->raid_disk = mirror; found = 1; + p->rdev = rdev; break; } - spin_unlock_irq(&conf->device_lock); print_conf(conf); return found; @@ -963,24 +964,27 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) static int raid10_remove_disk(mddev_t *mddev, int number) { conf_t *conf = mddev->private; - int err = 1; + int err = 0; + mdk_rdev_t *rdev; mirror_info_t *p = conf->mirrors+ number; print_conf(conf); - spin_lock_irq(&conf->device_lock); - if (p->rdev) { - if (p->rdev->in_sync || - atomic_read(&p->rdev->nr_pending)) { + rdev = p->rdev; + if (rdev) { + if (rdev->in_sync || + atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; } p->rdev = NULL; - err = 0; + synchronize_kernel(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + p->rdev = rdev; + } } - if (err) - MD_BUG(); abort: - spin_unlock_irq(&conf->device_lock); print_conf(conf); return err; @@ -1145,6 +1149,8 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio) atomic_inc(&r10_bio->remaining); md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9); + tbio->bi_sector += conf->mirrors[d].rdev->data_offset; + tbio->bi_bdev = conf->mirrors[d].rdev->bdev; generic_make_request(tbio); } @@ -1233,8 +1239,8 @@ static void raid10d(mddev_t *mddev) int mirror; bio = r10_bio->devs[r10_bio->read_slot].bio; r10_bio->devs[r10_bio->read_slot].bio = NULL; + bio_put(bio); mirror = read_balance(conf, r10_bio); - r10_bio->devs[r10_bio->read_slot].bio = bio; if (mirror == -1) { printk(KERN_ALERT "raid10: %s: unrecoverable I/O" " read error for block %llu\n", @@ -1248,15 +1254,14 @@ static void raid10d(mddev_t *mddev) " another mirror\n", bdevname(rdev->bdev,b), (unsigned long long)r10_bio->sector); - bio->bi_bdev = rdev->bdev; + bio = bio_clone(r10_bio->master_bio, GFP_NOIO); + r10_bio->devs[r10_bio->read_slot].bio = bio; bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr + rdev->data_offset; - bio->bi_next = NULL; - bio->bi_flags &= (1<bi_flags |= 1 << BIO_UPTODATE; - bio->bi_idx = 0; - bio->bi_size = r10_bio->sectors << 9; + bio->bi_bdev = rdev->bdev; bio->bi_rw = READ; + bio->bi_private = r10_bio; + bio->bi_end_io = raid10_end_read_request; unplug = 1; generic_make_request(bio); } @@ -1358,7 +1363,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) * put in a delay to throttle resync. */ if (!go_faster && waitqueue_active(&conf->wait_resume)) - schedule_timeout(HZ); + msleep_interruptible(1000); device_barrier(conf, sector_nr + RESYNC_SECTORS); /* Again, very different code for resync and recovery. @@ -1468,7 +1473,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) set_bit(R10BIO_IsSync, &r10_bio->state); raid10_find_phys(conf, r10_bio); r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1; - spin_lock_irq(&conf->device_lock); + for (i=0; icopies; i++) { int d = r10_bio->devs[i].devnum; bio = r10_bio->devs[i].bio; @@ -1488,14 +1493,15 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) bio->bi_bdev = conf->mirrors[d].rdev->bdev; count++; } - spin_unlock_irq(&conf->device_lock); + if (count < 2) { for (i=0; icopies; i++) { int d = r10_bio->devs[i].devnum; if (r10_bio->devs[i].bio->bi_end_io) - atomic_dec(&conf->mirrors[d].rdev->nr_pending); + rdev_dec_pending(conf->mirrors[d].rdev, mddev); } put_buf(r10_bio); + biolist = NULL; goto giveup; } } @@ -1557,7 +1563,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) } } - return nr_sectors; + return sectors_skipped + nr_sectors; giveup: /* There is nowhere to write, so all non-sync * drives must be failed, so try the next chunk... @@ -1739,6 +1745,7 @@ static int stop(mddev_t *mddev) md_unregister_thread(mddev->thread); mddev->thread = NULL; + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ if (conf->r10bio_pool) mempool_destroy(conf->r10bio_pool); if (conf->mirrors) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b28f29005..1dceb098a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include /* @@ -477,8 +477,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) if (!rdev->faulty) { mddev->sb_dirty = 1; - conf->working_disks--; if (rdev->in_sync) { + conf->working_disks--; mddev->degraded++; conf->failed_disks++; rdev->in_sync = 0; @@ -1071,7 +1071,8 @@ static void handle_stripe(struct stripe_head *sh) PRINTK("Reading block %d (sync=%d)\n", i, syncing); if (syncing) - md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS); + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1246,17 +1247,17 @@ static void handle_stripe(struct stripe_head *sh) else bi->bi_end_io = raid5_end_read_request; - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); rdev = conf->disks[i].rdev; if (rdev && rdev->faulty) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); if (rdev) { if (test_bit(R5_Syncio, &sh->dev[i].flags)) - md_sync_acct(rdev, STRIPE_SECTORS); + md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", @@ -1301,25 +1302,24 @@ static void unplug_slaves(mddev_t *mddev) { raid5_conf_t *conf = mddev_to_conf(mddev); int i; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); + rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = conf->disks[i].rdev; - if (rdev && atomic_read(&rdev->nr_pending)) { + if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); - if (r_queue && r_queue->unplug_fn) + if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); - spin_lock_irqsave(&conf->device_lock, flags); - atomic_dec(&rdev->nr_pending); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); } static void raid5_unplug_device(request_queue_t *q) @@ -1339,6 +1339,36 @@ static void raid5_unplug_device(request_queue_t *q) unplug_slaves(mddev); } +static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid5_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + static inline void raid5_plug_device(raid5_conf_t *conf) { spin_lock_irq(&conf->device_lock); @@ -1376,7 +1406,7 @@ static int make_request (request_queue_t *q, struct bio * bi) new_sector = raid5_compute_sector(logical_sector, raid_disks, data_disks, &dd_idx, &pd_idx, conf); - PRINTK("raid5: make_request, sector %Lu logical %Lu\n", + PRINTK("raid5: make_request, sector %llu logical %llu\n", (unsigned long long)new_sector, (unsigned long long)logical_sector); @@ -1545,6 +1575,7 @@ static int run (mddev_t *mddev) atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid5_unplug_device; + mddev->queue->issue_flush_fn = raid5_issue_flush; PRINTK("raid5: run(%s) called.\n", mdname(mddev)); @@ -1676,6 +1707,7 @@ static int stop (mddev_t *mddev) mddev->thread = NULL; shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ kfree(conf); mddev->private = NULL; return 0; @@ -1764,7 +1796,6 @@ static int raid5_spare_active(mddev_t *mddev) raid5_conf_t *conf = mddev->private; struct disk_info *tmp; - spin_lock_irq(&conf->device_lock); for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev @@ -1776,7 +1807,6 @@ static int raid5_spare_active(mddev_t *mddev) tmp->rdev->in_sync = 1; } } - spin_unlock_irq(&conf->device_lock); print_raid5_conf(conf); return 0; } @@ -1784,25 +1814,28 @@ static int raid5_spare_active(mddev_t *mddev) static int raid5_remove_disk(mddev_t *mddev, int number) { raid5_conf_t *conf = mddev->private; - int err = 1; + int err = 0; + mdk_rdev_t *rdev; struct disk_info *p = conf->disks + number; print_raid5_conf(conf); - spin_lock_irq(&conf->device_lock); - - if (p->rdev) { - if (p->rdev->in_sync || - atomic_read(&p->rdev->nr_pending)) { + rdev = p->rdev; + if (rdev) { + if (rdev->in_sync || + atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; } p->rdev = NULL; - err = 0; + synchronize_kernel(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + p->rdev = rdev; + } } - if (err) - MD_BUG(); abort: - spin_unlock_irq(&conf->device_lock); + print_raid5_conf(conf); return err; } @@ -1814,19 +1847,17 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) int disk; struct disk_info *p; - spin_lock_irq(&conf->device_lock); /* * find the disk ... */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - p->rdev = rdev; rdev->in_sync = 0; rdev->raid_disk = disk; found = 1; + p->rdev = rdev; break; } - spin_unlock_irq(&conf->device_lock); print_raid5_conf(conf); return found; } diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 1ad99be9c..9a27f8f88 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include "raid6.h" @@ -498,8 +498,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) if (!rdev->faulty) { mddev->sb_dirty = 1; - conf->working_disks--; if (rdev->in_sync) { + conf->working_disks--; mddev->degraded++; conf->failed_disks++; rdev->in_sync = 0; @@ -734,7 +734,6 @@ static void compute_parity(struct stripe_head *sh, int method) case READ_MODIFY_WRITE: BUG(); /* READ_MODIFY_WRITE N/A for RAID-6 */ case RECONSTRUCT_WRITE: - case UPDATE_PARITY: /* Is this right? */ for (i= disks; i-- ;) if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) { chosen = sh->dev[i].towrite; @@ -770,7 +769,8 @@ static void compute_parity(struct stripe_head *sh, int method) i = d0_idx; do { ptrs[count++] = page_address(sh->dev[i].page); - + if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags)) + printk("block %d/%d not uptodate on parity calc\n", i,count); i = raid6_next_disk(i, disks); } while ( i != d0_idx ); // break; @@ -818,7 +818,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx) if (test_bit(R5_UPTODATE, &sh->dev[i].flags)) ptr[count++] = p; else - PRINTK("compute_block() %d, stripe %llu, %d" + printk("compute_block() %d, stripe %llu, %d" " not present\n", dd_idx, (unsigned long long)sh->sector, i); @@ -875,6 +875,9 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) do { ptrs[count++] = page_address(sh->dev[i].page); i = raid6_next_disk(i, disks); + if (i != dd_idx1 && i != dd_idx2 && + !test_bit(R5_UPTODATE, &sh->dev[i].flags)) + printk("compute_2 with missing block %d/%d\n", count, i); } while ( i != d0_idx ); if ( failb == disks-2 ) { @@ -1157,17 +1160,15 @@ static void handle_stripe(struct stripe_head *sh) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (syncing && (uptodate < disks))) { + if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { for (i=disks; i--;) { dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread || (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || syncing || - (failed >= 1 && (sh->dev[failed_num[0]].toread || - (sh->dev[failed_num[0]].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num[0]].flags)))) || - (failed >= 2 && (sh->dev[failed_num[1]].toread || - (sh->dev[failed_num[1]].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num[1]].flags)))) + (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || + (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) ) ) { /* we would like to get this block, possibly @@ -1208,7 +1209,8 @@ static void handle_stripe(struct stripe_head *sh) PRINTK("Reading block %d (sync=%d)\n", i, syncing); if (syncing) - md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS); + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1408,17 +1410,17 @@ static void handle_stripe(struct stripe_head *sh) else bi->bi_end_io = raid6_end_read_request; - spin_lock_irq(&conf->device_lock); + rcu_read_lock(); rdev = conf->disks[i].rdev; if (rdev && rdev->faulty) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); + rcu_read_unlock(); if (rdev) { if (test_bit(R5_Syncio, &sh->dev[i].flags)) - md_sync_acct(rdev, STRIPE_SECTORS); + md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", @@ -1463,25 +1465,24 @@ static void unplug_slaves(mddev_t *mddev) { raid6_conf_t *conf = mddev_to_conf(mddev); int i; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); + rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = conf->disks[i].rdev; - if (rdev && atomic_read(&rdev->nr_pending)) { + if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); - if (r_queue && r_queue->unplug_fn) + if (r_queue->unplug_fn) r_queue->unplug_fn(r_queue); - spin_lock_irqsave(&conf->device_lock, flags); - atomic_dec(&rdev->nr_pending); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); } } - spin_unlock_irqrestore(&conf->device_lock, flags); + rcu_read_unlock(); } static void raid6_unplug_device(request_queue_t *q) @@ -1501,6 +1502,36 @@ static void raid6_unplug_device(request_queue_t *q) unplug_slaves(mddev); } +static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid6_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i=0; iraid_disks && ret == 0; i++) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else { + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, + error_sector); + rdev_dec_pending(rdev, mddev); + rcu_read_lock(); + } + } + } + rcu_read_unlock(); + return ret; +} + static inline void raid6_plug_device(raid6_conf_t *conf) { spin_lock_irq(&conf->device_lock); @@ -1539,7 +1570,7 @@ static int make_request (request_queue_t *q, struct bio * bi) new_sector = raid6_compute_sector(logical_sector, raid_disks, data_disks, &dd_idx, &pd_idx, conf); - PRINTK("raid6: make_request, sector %Lu logical %Lu\n", + PRINTK("raid6: make_request, sector %llu logical %llu\n", (unsigned long long)new_sector, (unsigned long long)logical_sector); @@ -1708,6 +1739,7 @@ static int run (mddev_t *mddev) atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid6_unplug_device; + mddev->queue->issue_flush_fn = raid6_issue_flush; PRINTK("raid6: run(%s) called.\n", mdname(mddev)); @@ -1846,6 +1878,7 @@ static int stop (mddev_t *mddev) mddev->thread = NULL; shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ kfree(conf); mddev->private = NULL; return 0; @@ -1933,7 +1966,6 @@ static int raid6_spare_active(mddev_t *mddev) raid6_conf_t *conf = mddev->private; struct disk_info *tmp; - spin_lock_irq(&conf->device_lock); for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev @@ -1945,7 +1977,6 @@ static int raid6_spare_active(mddev_t *mddev) tmp->rdev->in_sync = 1; } } - spin_unlock_irq(&conf->device_lock); print_raid6_conf(conf); return 0; } @@ -1953,25 +1984,29 @@ static int raid6_spare_active(mddev_t *mddev) static int raid6_remove_disk(mddev_t *mddev, int number) { raid6_conf_t *conf = mddev->private; - int err = 1; + int err = 0; + mdk_rdev_t *rdev; struct disk_info *p = conf->disks + number; print_raid6_conf(conf); - spin_lock_irq(&conf->device_lock); - - if (p->rdev) { - if (p->rdev->in_sync || - atomic_read(&p->rdev->nr_pending)) { + rdev = p->rdev; + if (rdev) { + if (rdev->in_sync || + atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; } p->rdev = NULL; - err = 0; + synchronize_kernel(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + p->rdev = rdev; + } } - if (err) - MD_BUG(); + abort: - spin_unlock_irq(&conf->device_lock); + print_raid6_conf(conf); return err; } @@ -1983,19 +2018,17 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) int disk; struct disk_info *p; - spin_lock_irq(&conf->device_lock); /* * find the disk ... */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - p->rdev = rdev; rdev->in_sync = 0; rdev->raid_disk = disk; found = 1; + p->rdev = rdev; break; } - spin_unlock_irq(&conf->device_lock); print_raid6_conf(conf); return found; } diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 79d29ef1e..508cc0569 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -34,27 +34,18 @@ source "drivers/media/common/Kconfig" config VIDEO_TUNER tristate - default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_MXB=y || VIDEO_CX88=y - default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_MXB=m || VIDEO_CX88=m - depends on VIDEO_DEV config VIDEO_BUF tristate - default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_SAA7146=y || VIDEO_CX88=y - default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_SAA7146=m || VIDEO_CX88=m - depends on VIDEO_DEV + +config VIDEO_BUF_DVB + tristate config VIDEO_BTCX tristate - default y if VIDEO_BT848=y || VIDEO_CX88=y - default m if VIDEO_BT848=m || VIDEO_CX88=m - depends on VIDEO_DEV config VIDEO_IR tristate - default y if VIDEO_BT848=y || VIDEO_SAA7134=y - default m if VIDEO_BT848=m || VIDEO_SAA7134=m - depends on VIDEO_DEV endmenu diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 2c007571a..25d3945cd 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -1,4 +1,6 @@ /* + * $Id: ir-common.c,v 1.5 2004/11/07 13:17:15 kraxel Exp $ + * * some common structs and functions to handle infrared remotes via * input layer ... * @@ -29,11 +31,11 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); static int repeat = 1; -MODULE_PARM(repeat,"i"); +module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); static int debug = 0; /* debug level (0,1,2) */ -MODULE_PARM(debug,"i"); +module_param(debug, int, 0644); #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG fmt , ## arg) @@ -100,7 +102,7 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x2a ] = KEY_RESERVED, // timed page/channel clck [ 0x2b ] = KEY_RESERVED, // increment (USA) [ 0x2c ] = KEY_RESERVED, // decrement (USA) - [ 0x2d ] = KEY_RESERVED, // + [ 0x2d ] = KEY_RESERVED, // [ 0x2f ] = KEY_RESERVED, // PIP shift [ 0x31 ] = KEY_RESERVED, // erase [ 0x34 ] = KEY_RESERVED, // wind @@ -141,7 +143,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, IR_KEYTAB_TYPE *ir_codes) { int i; - + ir->ir_type = ir_type; if (ir_codes) memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); @@ -171,7 +173,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, u32 ir_key, u32 ir_raw) { u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); - + if (ir->keypressed && ir->keycode != keycode) { ir->keypressed = 0; ir_input_key_event(dev,ir); diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 369d949fd..5c3a549a5 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -25,11 +25,11 @@ struct list_head saa7146_devices; struct semaphore saa7146_devices_lock; static int initialized = 0; -int saa7146_num = 0; +static int saa7146_num = 0; unsigned int saa7146_debug = 0; -MODULE_PARM(saa7146_debug,"i"); +module_param(saa7146_debug, int, 0644); MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)"); #if 0 @@ -48,7 +48,7 @@ static void dump_registers(struct saa7146_dev* dev) * gpio and debi helper functions ****************************************************************************/ -/* write "data" to the gpio-pin "pin" */ +/* write "data" to the gpio-pin "pin" -- unused */ void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data) { u32 value = 0; @@ -67,7 +67,7 @@ void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data) } /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ -int saa7146_wait_for_debi_done(struct saa7146_dev *dev) +int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) { unsigned long start; @@ -80,6 +80,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev) DEB_S(("timed out while waiting for registers getting programmed\n")); return -ETIMEDOUT; } + if (nobusyloop) + msleep(1); } /* wait for transfer to complete */ @@ -92,6 +94,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev) DEB_S(("timed out while waiting for transfer completion\n")); return -ETIMEDOUT; } + if (nobusyloop) + msleep(1); } return 0; @@ -133,8 +137,6 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) /********************************************************************************/ /* common page table functions */ -#define SAA7146_PGTABLE_SIZE 4096 - char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt) { int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; @@ -182,11 +184,11 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) u32 *cpu; dma_addr_t dma_addr; - cpu = pci_alloc_consistent(pci, SAA7146_PGTABLE_SIZE, &dma_addr); + cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); if (NULL == cpu) { return -ENOMEM; } - pt->size = SAA7146_PGTABLE_SIZE; + pt->size = PAGE_SIZE; pt->cpu = cpu; pt->dma = dma_addr; @@ -201,11 +203,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt int i,p; BUG_ON( 0 == sglen); - - if (list->offset > PAGE_SIZE) { - DEB_D(("offset > PAGE_SIZE. this should not happen.")); - return -EINVAL; - } + BUG_ON(list->offset > PAGE_SIZE); /* if we have a user buffer, the first page may not be aligned to a page boundary. */ @@ -217,7 +215,7 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset); */ for (p = 0; p * 4096 < list->length; p++, ptr++) { - *ptr = sg_dma_address(list) + p * 4096; + *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096); nr_pages++; } } @@ -254,10 +252,9 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) /********************************************************************************/ /* interrupt handler */ - static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) { - struct saa7146_dev *dev = (struct saa7146_dev*)dev_id; + struct saa7146_dev *dev = dev_id; u32 isr = 0; /* read out the interrupt status register */ @@ -295,7 +292,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) if (0 != (isr & (MASK_16|MASK_17))) { u32 status = saa7146_read(dev, I2C_STATUS); if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { - IER_DISABLE(dev, MASK_16|MASK_17); + SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); /* only wake up if we expect something */ if( 0 != dev->i2c_op ) { u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; @@ -314,7 +311,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) if( 0 != isr ) { ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr)); ERR(("disabling interrupt source(s)!\n")); - IER_DISABLE(dev,isr); + SAA7146_IER_DISABLE(dev,isr); } return IRQ_HANDLED; } @@ -324,16 +321,15 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) { - unsigned long adr = 0, len = 0; - struct saa7146_dev* dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL); - struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data; struct saa7146_extension* ext = pci_ext->ext; - int err = 0; + struct saa7146_dev *dev; + int err = -ENOMEM; - if (!(dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL))) { + dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL); + if (!dev) { ERR(("out of memory.\n")); - return -ENOMEM; + goto out; } /* clear out mem for sure */ @@ -341,38 +337,37 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent DEB_EE(("pci:%p\n",pci)); - if (pci_enable_device(pci)) { + err = pci_enable_device(pci); + if (err < 0) { ERR(("pci_enable_device() failed.\n")); - err = -EIO; - goto pci_error; + goto err_free; } /* enable bus-mastering */ pci_set_master(pci); dev->pci = pci; + /* get chip-revision; this is needed to enable bug-fixes */ - if( 0 > pci_read_config_dword(dev->pci, PCI_CLASS_REVISION, &dev->revision)) { + err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); + if (err < 0) { ERR(("pci_read_config_dword() failed.\n")); - err = -ENODEV; - goto pci_error; + goto err_disable; } dev->revision &= 0xf; /* remap the memory from virtual to physical adress */ - adr = pci_resource_start(pci,0); - len = pci_resource_len(pci,0); - if (!request_mem_region(pci_resource_start(pci,0), pci_resource_len(pci,0), "saa7146")) { - ERR(("request_mem_region() failed.\n")); - err = -ENODEV; - goto pci_error; - } + err = pci_request_region(pci, 0, "saa7146"); + if (err < 0) + goto err_disable; - if (!(dev->mem = ioremap(adr,len))) { + dev->mem = ioremap(pci_resource_start(pci, 0), + pci_resource_len(pci, 0)); + if (!dev->mem) { ERR(("ioremap() failed.\n")); err = -ENODEV; - goto ioremap_error; + goto err_release; } /* we don't do a master reset here anymore, it screws up @@ -392,42 +387,40 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent saa7146_write(dev, MC2, 0xf8000000); /* request an interrupt for the saa7146 */ - if (request_irq(dev->pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT, - dev->name, dev)) - { + err = request_irq(pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT, + dev->name, dev); + if (err < 0) { ERR(("request_irq() failed.\n")); - err = -ENODEV; - goto irq_error; + goto err_unmap; } - /* get memory for various stuff */ - dev->d_rps0.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps0.dma_handle); - if( NULL == dev->d_rps0.cpu_addr ) { err = -ENOMEM; - goto kmalloc_error_1; - } + + /* get memory for various stuff */ + dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_rps0.dma_handle); + if (!dev->d_rps0.cpu_addr) + goto err_free_irq; memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->d_rps1.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps1.dma_handle); - if( NULL == dev->d_rps1.cpu_addr ) { - err = -ENOMEM; - goto kmalloc_error_2; - } + dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_rps1.dma_handle); + if (!dev->d_rps1.cpu_addr) + goto err_free_rps0; memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->d_i2c.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_i2c.dma_handle); - if( NULL == dev->d_i2c.cpu_addr ) { - err = -ENOMEM; - goto kmalloc_error_3; - } + dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, + &dev->d_i2c.dma_handle); + if (!dev->d_i2c.cpu_addr) + goto err_free_rps1; memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); /* the rest + print status message */ /* create a nice device name */ - sprintf(&dev->name[0], "saa7146 (%d)",saa7146_num); + sprintf(dev->name, "saa7146 (%d)", saa7146_num); - INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device)); + INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); dev->ext = ext; pci_set_drvdata(pci,dev); @@ -444,18 +437,18 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent /* set some sane pci arbitrition values */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); - if( 0 != ext->probe) { - if( 0 != ext->probe(dev) ) { - DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + /* TODO: use the status code of the callback */ + err = -ENODEV; - goto probe_error; - } + + if (ext->probe && ext->probe(dev)) { + DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + goto err_free_i2c; } - if( 0 != ext->attach(dev,pci_ext) ) { + if (ext->attach(dev, pci_ext)) { DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); - err = -ENODEV; - goto attach_error; + goto err_unprobe; } INIT_LIST_HEAD(&dev->item); @@ -463,30 +456,46 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent saa7146_num++; err = 0; - goto out; -attach_error: -probe_error: +out: + return err; + +err_unprobe: pci_set_drvdata(pci,NULL); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); -kmalloc_error_3: - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); -kmalloc_error_2: - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); -kmalloc_error_1: - free_irq(dev->pci->irq, (void *)dev); -irq_error: +err_free_i2c: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, + dev->d_i2c.dma_handle); +err_free_rps1: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, + dev->d_rps1.dma_handle); +err_free_rps0: + pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, + dev->d_rps0.dma_handle); +err_free_irq: + free_irq(pci->irq, (void *)dev); +err_unmap: iounmap(dev->mem); -ioremap_error: - release_mem_region(adr,len); -pci_error: +err_release: + pci_release_region(pci, 0); +err_disable: + pci_disable_device(pci); +err_free: kfree(dev); -out: - return err; + goto out; } static void saa7146_remove_one(struct pci_dev *pdev) { - struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); + struct saa7146_dev* dev = pci_get_drvdata(pdev); + struct { + void *addr; + dma_addr_t dma; + } dev_map[] = { + { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle }, + { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle }, + { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle }, + { NULL, 0 } + }, *p; + DEB_EE(("dev:%p\n",dev)); dev->ext->detach(dev); @@ -497,17 +506,15 @@ static void saa7146_remove_one(struct pci_dev *pdev) /* disable all irqs, release irq-routine */ saa7146_write(dev, IER, 0); - free_irq(dev->pci->irq, (void *)dev); + free_irq(pdev->irq, dev); - /* free kernel memory */ - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); - pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); + for (p = dev_map; p->addr; p++) + pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma); iounmap(dev->mem); - release_mem_region(pci_resource_start(dev->pci,0), pci_resource_len(dev->pci,0)); - + pci_release_region(pdev, 0); list_del(&dev->item); + pci_disable_device(pdev); kfree(dev); saa7146_num--; diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index a5621d7ac..a6dd055b7 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -1,4 +1,5 @@ #include +#include #define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) @@ -32,17 +33,6 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) return 1; } -int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit) -{ - return (fh->resources & bit); -} - -int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit) -{ - struct saa7146_vv *vv = dev->vv_data; - return (vv->resources & bit); -} - void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) { struct saa7146_dev *dev = fh->dev; @@ -88,10 +78,7 @@ int saa7146_buffer_queue(struct saa7146_dev *dev, #endif DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf)); - if( NULL == q ) { - ERR(("internal error: fatal NULL pointer for q.\n")); - return 0; - } + BUG_ON(!q); if (NULL == q->curr) { q->curr = buf; @@ -112,14 +99,11 @@ void saa7146_buffer_finish(struct saa7146_dev *dev, #ifdef DEBUG_SPINLOCKS BUG_ON(!spin_is_locked(&dev->slock)); #endif - if( NULL == q->curr ) { - ERR(("internal error: fatal NULL pointer for q->curr.\n")); - return; - } - DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state)); DEB_EE(("q->curr:%p\n",q->curr)); + BUG_ON(!q->curr); + /* finish current buffer */ if (NULL == q->curr) { DEB_D(("aiii. no current buffer\n")); @@ -138,10 +122,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev, { struct saa7146_buf *buf,*next = NULL; - if( NULL == q ) { - ERR(("internal error: fatal NULL pointer for q.\n")); - return; - } + BUG_ON(!q); DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi)); @@ -358,7 +339,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma) BUG(); return 0; } - return videobuf_mmap_mapper(vma,q); + return videobuf_mmap_mapper(q,vma); } static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) @@ -515,45 +496,58 @@ int saa7146_vv_release(struct saa7146_dev* dev) return 0; } -int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type) +int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, + char *name, int type) { struct saa7146_vv *vv = dev->vv_data; + struct video_device *vfd; DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); - *vid = device_template; - strlcpy(vid->name, name, sizeof(vid->name)); - vid->priv = dev; + // released by vfd->release + vfd = video_device_alloc(); + if (vfd == NULL) + return -ENOMEM; + + memcpy(vfd, &device_template, sizeof(struct video_device)); + strlcpy(vfd->name, name, sizeof(vfd->name)); + vfd->release = video_device_release; + vfd->priv = dev; // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); - if (video_register_device(vid,type,-1) < 0) { + if (video_register_device(vfd, type, -1) < 0) { ERR(("cannot register v4l2 device. skipping.\n")); return -1; } if( VFL_TYPE_GRABBER == type ) { - vv->video_minor = vid->minor; - INFO(("%s: registered device video%d [v4l2]\n", dev->name,vid->minor & 0x1f)); + vv->video_minor = vfd->minor; + INFO(("%s: registered device video%d [v4l2]\n", + dev->name, vfd->minor & 0x1f)); } else { - vv->vbi_minor = vid->minor; - INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,vid->minor & 0x1f)); + vv->vbi_minor = vfd->minor; + INFO(("%s: registered device vbi%d [v4l2]\n", + dev->name, vfd->minor & 0x1f)); } + *vid = vfd; return 0; } -int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev) +int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) { struct saa7146_vv *vv = dev->vv_data; DEB_EE(("dev:%p\n",dev)); - if( VFL_TYPE_GRABBER == vid->type ) { + if( VFL_TYPE_GRABBER == (*vid)->type ) { vv->video_minor = -1; } else { vv->vbi_minor = -1; } - video_unregister_device(vid); + + video_unregister_device(*vid); + *vid = NULL; return 0; } diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index bdae7fab3..7bf6316b3 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -9,11 +9,6 @@ static void calculate_output_format_register(struct saa7146_dev* saa, u32 palett *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16)); } -static void calculate_bcs_ctrl_register(struct saa7146_dev *dev, int brightness, int contrast, int colour, u32 *bcs_ctrl) -{ - *bcs_ctrl = ((brightness << 24) | (contrast << 16) | (colour << 0)); -} - static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl) { *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28); @@ -62,7 +57,7 @@ static struct { }; /* table of attenuation values for horizontal scaling */ -u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; +static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; /* calculate horizontal scale registers */ static int calculate_h_scale_registers(struct saa7146_dev *dev, @@ -208,7 +203,7 @@ static struct { }; /* table of attenuation values for vertical scaling */ -u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; +static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; /* calculate vertical scale registers */ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field, @@ -413,10 +408,10 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa /* fill up cliptable */ for(i = 0; i < cnt_pixel; i++) { - clipping[2*i] |= (pixel_list[i] << 16); + clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16); } for(i = 0; i < cnt_line; i++) { - clipping[(2*i)+1] |= (line_list[i] << 16); + clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16); } /* fill up cliptable with the display infos */ @@ -430,7 +425,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa if( pixel_list[i] < (x[j] + w[j])) { if ( pixel_list[i] >= x[j] ) { - clipping[2*i] |= (1 << j); + clipping[2*i] |= cpu_to_le32(1 << j); } } } @@ -442,7 +437,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa if( line_list[i] < (y[j] + h[j]) ) { if( line_list[i] >= y[j] ) { - clipping[(2*i)+1] |= (1 << j); + clipping[(2*i)+1] |= cpu_to_le32(1 << j); } } } @@ -560,9 +555,10 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e } /* calculate the new memory offsets for a desired position */ -static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field) +static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat) { struct saa7146_vv *vv = dev->vv_data; + struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat); int b_depth = vv->ov_fmt->depth; int b_bpl = vv->ov_fb.fmt.bytesperline; @@ -601,7 +597,7 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int vdma1.pitch *= -1; } - vdma1.base_page = 0; + vdma1.base_page = sfmt->swap; vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels; saa7146_write_out_dma(dev, 1, &vdma1); @@ -619,18 +615,6 @@ static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long pal saa7146_write(dev, MC2, (MASK_05 | MASK_21)); } -void saa7146_set_picture_prop(struct saa7146_dev *dev, int brightness, int contrast, int colour) -{ - u32 bcs_ctrl = 0; - - calculate_bcs_ctrl_register(dev, brightness, contrast, colour, &bcs_ctrl); - saa7146_write(dev, BCS_CTRL, bcs_ctrl); - - /* update the bcs register */ - saa7146_write(dev, MC2, (MASK_06 | MASK_22)); -} - - /* select input-source */ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync) { @@ -657,7 +641,7 @@ int saa7146_enable_overlay(struct saa7146_fh *fh) struct saa7146_vv *vv = dev->vv_data; saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field); - saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field); + saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field, vv->ov_fmt->pixelformat); saa7146_set_output_format(dev, vv->ov_fmt->trans); saa7146_set_clipping_rect(fh); @@ -727,7 +711,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71 vdma1.pitch = (width*depth*2)/8; } vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); - vdma1.base_page = buf->pt[0].dma | ME1; + vdma1.base_page = buf->pt[0].dma | ME1 | sfmt->swap; if( 0 != vv->vflip ) { vdma1.prot_addr = buf->pt[0].offset; diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 18bc5b671..875ebd466 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -1,14 +1,7 @@ #include #include -/* helper function */ -static void my_wait(struct saa7146_dev *dev, long ms) -{ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((((ms+10)/10)*HZ)/1000); -} - -u32 saa7146_i2c_func(struct i2c_adapter *adapter) +static u32 saa7146_i2c_func(struct i2c_adapter *adapter) { //fm DEB_I2C(("'%s'.\n", adapter->name)); @@ -136,12 +129,12 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev) /* set "ABORT-OPERATION"-bit (bit 7)*/ saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - my_wait(dev,SAA7146_I2C_DELAY); + msleep(SAA7146_I2C_DELAY); /* clear all error-bits pending; this is needed because p.123, note 1 */ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - my_wait(dev,SAA7146_I2C_DELAY); + msleep(SAA7146_I2C_DELAY); } /* check if any error is (still) present. (this can be necessary because p.123, note 1) */ @@ -155,18 +148,18 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev) after serious protocol errors caused by e.g. the SAA7740 */ saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - my_wait(dev,SAA7146_I2C_DELAY); + msleep(SAA7146_I2C_DELAY); /* clear all error-bits pending */ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - my_wait(dev,SAA7146_I2C_DELAY); + msleep(SAA7146_I2C_DELAY); /* the data sheet says it might be necessary to clear the status twice after an abort */ saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); - my_wait(dev,SAA7146_I2C_DELAY); + msleep(SAA7146_I2C_DELAY); } /* if any error is still present, a fatal error has occured ... */ @@ -197,7 +190,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d saa7146_write(dev, I2C_TRANSFER, *dword); dev->i2c_op = 1; - IER_ENABLE(dev, MASK_16|MASK_17); + SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); @@ -243,7 +236,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d if ((++trial < 20) && short_delay) udelay(10); else - my_wait(dev,1); + msleep(1); } } @@ -345,7 +338,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i } /* delay a bit before retrying */ - my_wait(dev, 10); + msleep(10); } while (err != num && retries--); @@ -400,7 +393,7 @@ static struct i2c_algorithm saa7146_algo = { .functionality = saa7146_i2c_func, }; -int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, unsigned int class, u32 bitrate) +int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) { DEB_EE(("bitrate: 0x%08x\n",bitrate)); @@ -411,13 +404,11 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c saa7146_i2c_reset(dev); if( NULL != i2c_adapter ) { - memset(i2c_adapter,0,sizeof(struct i2c_adapter)); - strcpy(i2c_adapter->name, dev->name); #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) i2c_adapter->data = dev; #else + BUG_ON(!i2c_adapter->class); i2c_set_adapdata(i2c_adapter,dev); - i2c_adapter->class = class; #endif i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo_data = NULL; diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 6c4f0bedd..55884d935 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -91,7 +91,7 @@ static int vbi_workaround(struct saa7146_dev *dev) saa7146_write(dev, MC2, MASK_04|MASK_20); /* enable rps1 irqs */ - IER_ENABLE(dev,MASK_28); + SAA7146_IER_ENABLE(dev,MASK_28); /* prepare to wait to be woken up by the irq-handler */ add_wait_queue(&vv->vbi_wq, &wait); @@ -109,7 +109,7 @@ static int vbi_workaround(struct saa7146_dev *dev) current->state = TASK_RUNNING; /* disable rps1 irqs */ - IER_DISABLE(dev,MASK_28); + SAA7146_IER_DISABLE(dev,MASK_28); /* stop video-dma3 */ saa7146_write(dev, MC1, MASK_20); @@ -130,7 +130,7 @@ static int vbi_workaround(struct saa7146_dev *dev) return 0; } -void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) +static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { struct saa7146_vv *vv = dev->vv_data; @@ -190,7 +190,7 @@ void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, s WRITE_RPS1(CMD_STOP); /* enable rps1 irqs */ - IER_ENABLE(dev, MASK_28); + SAA7146_IER_ENABLE(dev, MASK_28); /* write the address of the rps-program */ saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); @@ -213,8 +213,9 @@ static int buffer_activate(struct saa7146_dev *dev, return 0; } -static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,enum v4l2_field field) +static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_buf *buf = (struct saa7146_buf *)vb; @@ -264,7 +265,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,enum v4l return err; } -static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { int llength,lines; @@ -279,8 +280,9 @@ static int buffer_setup(struct file *file, unsigned int *count, unsigned int *si return 0; } -static void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -290,8 +292,9 @@ static void buffer_queue(struct file *file, struct videobuf_buffer *vb) saa7146_buffer_queue(dev,&vv->vbi_q,buf); } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_buf *buf = (struct saa7146_buf *)vb; @@ -322,7 +325,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file) saa7146_write(dev, MC1, MASK_29); /* disable rps1 irqs */ - IER_DISABLE(dev, MASK_28); + SAA7146_IER_DISABLE(dev, MASK_28); /* shut down dma 3 transfers */ saa7146_write(dev, MC1, MASK_20); @@ -331,7 +334,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file) saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE); } - videobuf_queue_cancel(file,&fh->vbi_q); + videobuf_queue_cancel(&fh->vbi_q); vv->vbi_streaming = NULL; @@ -404,7 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) dev->pci, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? - sizeof(struct saa7146_buf)); + sizeof(struct saa7146_buf), + file); init_MUTEX(&fh->vbi_q.lock); init_timer(&fh->vbi_read_timeout); @@ -480,7 +484,8 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff } mod_timer(&fh->vbi_read_timeout, jiffies+BUFFER_TIMEOUT); - ret = videobuf_read_stream(file, &fh->vbi_q, data, count, ppos, 1); + ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1, + file->f_flags & O_NONBLOCK); /* printk("BASE_ODD3: 0x%08x\n", saa7146_read(dev, BASE_ODD3)); printk("BASE_EVEN3: 0x%08x\n", saa7146_read(dev, BASE_EVEN3)); diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index e89713195..87b0f6465 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -2,7 +2,7 @@ static int max_memory = 32; -MODULE_PARM(max_memory,"i"); +module_param(max_memory, int, 0644); MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)"); #define IS_CAPTURE_ACTIVE(fh) \ @@ -37,6 +37,13 @@ static struct saa7146_format formats[] = { .trans = RGB32_COMPOSED, .depth = 32, .flags = 0, + }, { + .name = "RGB-32 (R-G-B)", + .pixelformat = V4L2_PIX_FMT_RGB32, + .trans = RGB32_COMPOSED, + .depth = 32, + .flags = 0, + .swap = 0x2, }, { .name = "Greyscale-8", .pixelformat = V4L2_PIX_FMT_GREY, @@ -634,7 +641,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu /* walk all pages, copy all page addresses to ptr1 */ for (i = 0; i < length; i++, list++) { for (p = 0; p * 4096 < list->length; p++, ptr1++) { - *ptr1 = sg_dma_address(list) - list->offset; + *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset); } } /* @@ -753,7 +760,7 @@ static int video_begin(struct saa7146_fh *fh) saa7146_write(dev, MC2, MASK_27 ); /* enable rps0 irqs */ - IER_ENABLE(dev, MASK_27); + SAA7146_IER_ENABLE(dev, MASK_27); vv->video_fh = fh; vv->video_status = STATUS_CAPTURE; @@ -798,7 +805,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file) saa7146_write(dev, MC1, MASK_28); /* disable rps0 irqs */ - IER_DISABLE(dev, MASK_27); + SAA7146_IER_DISABLE(dev, MASK_27); /* shut down all used video dma transfers */ saa7146_write(dev, MC1, dmas); @@ -1130,7 +1137,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *req = arg; DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type)); - return videobuf_reqbufs(file,q,req); + return videobuf_reqbufs(q,req); } case VIDIOC_QUERYBUF: { struct v4l2_buffer *buf = arg; @@ -1140,14 +1147,14 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int case VIDIOC_QBUF: { struct v4l2_buffer *buf = arg; int ret = 0; - ret = videobuf_qbuf(file,q,buf); + ret = videobuf_qbuf(q,buf); DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index)); return ret; } case VIDIOC_DQBUF: { struct v4l2_buffer *buf = arg; int ret = 0; - ret = videobuf_dqbuf(file,q,buf); + ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK); DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index)); return ret; } @@ -1159,7 +1166,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int if( 0 != err) { return err; } - err = videobuf_streamon(file,q); + err = videobuf_streamon(q); return err; } case VIDIOC_STREAMOFF: { @@ -1180,7 +1187,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return -EBUSY; } - err = videobuf_streamoff(file,q); + err = videobuf_streamoff(q); if (0 != err) { DEB_D(("warning: videobuf_streamoff() failed.\n")); video_end(fh, file); @@ -1203,7 +1210,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int q = &fh->video_q; down(&q->lock); - err = videobuf_mmap_setup(file,q,gbuffers,gbufsize, + err = videobuf_mmap_setup(q,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (err < 0) { up(&q->lock); @@ -1240,8 +1247,10 @@ static int buffer_activate (struct saa7146_dev *dev, return 0; } -static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4l2_field field) +static int buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, enum v4l2_field field) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -1322,8 +1331,9 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4 return err; } -static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS) @@ -1341,8 +1351,9 @@ static int buffer_setup(struct file *file, unsigned int *count, unsigned int *si return 0; } -static void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -1353,8 +1364,9 @@ static void buffer_queue(struct file *file, struct videobuf_buffer *vb) } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { + struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_buf *buf = (struct saa7146_buf *)vb; @@ -1408,7 +1420,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file) dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct saa7146_buf)); + sizeof(struct saa7146_buf), + file); init_MUTEX(&fh->video_q.lock); @@ -1474,7 +1487,8 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo goto out; } - ret = videobuf_read_one(file,&fh->video_q , data, count, ppos); + ret = videobuf_read_one(&fh->video_q, data, count, ppos, + file->f_flags & O_NONBLOCK); if (ret != 0) { video_end(fh, file); } else { diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index f0f152013..c9a5138e4 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -12,26 +12,15 @@ config DVB own a DVB adapter and want to use it or if you compile Linux for a digital SetTopBox. - API specs and user tools are available from - . + API specs and user tools are available from . Please report problems regarding this driver to the LinuxDVB mailing list. - You might want add the following lines to your /etc/modules.conf: - - alias char-major-250 dvb - alias dvb dvb-ttpci - below dvb-ttpci alps_bsru6 alps_bsrv2 \ - grundig_29504-401 grundig_29504-491 \ - ves1820 - If unsure say N. source "drivers/media/dvb/dvb-core/Kconfig" -source "drivers/media/dvb/frontends/Kconfig" - comment "Supported SAA7146 based PCI Adapters" depends on DVB_CORE && PCI source "drivers/media/dvb/ttpci/Kconfig" @@ -40,6 +29,8 @@ comment "Supported USB Adapters" depends on DVB_CORE && USB source "drivers/media/dvb/ttusb-budget/Kconfig" source "drivers/media/dvb/ttusb-dec/Kconfig" +source "drivers/media/dvb/dibusb/Kconfig" +source "drivers/media/dvb/cinergyT2/Kconfig" comment "Supported FlexCopII (B2C2) Adapters" depends on DVB_CORE && PCI @@ -49,5 +40,8 @@ comment "Supported BT878 Adapters" depends on DVB_CORE && PCI source "drivers/media/dvb/bt8xx/Kconfig" -endmenu +comment "Supported DVB Frontends" + depends on DVB_CORE +source "drivers/media/dvb/frontends/Kconfig" +endmenu diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 2263ebf72..520fc3902 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -2,5 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ - +obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/ diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index b3a45b4fc..354f9dfc4 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -1,8 +1,24 @@ config DVB_B2C2_SKYSTAR - tristate "Technisat Skystar2 PCI" + tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI" depends on DVB_CORE && PCI + select DVB_STV0299 + select DVB_MT352 + select DVB_MT312 help Support for the Skystar2 PCI DVB card by Technisat, which is equipped with the FlexCopII chipset by B2C2. Say Y if you own such a device and want to use it. + +config DVB_B2C2_USB + tristate "B2C2/Technisat Air/Sky/Cable2PC USB" + depends on DVB_CORE && USB && EXPERIMENTAL + select DVB_STV0299 + select DVB_MT352 + help + Support for the Air/Sky/Cable2PC USB DVB device by B2C2. Currently + this does nothing, but providing basic function for the used usb + protocol. + + Say Y if you own such a device and want to use it. + diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile index df86d99af..9fb1247bf 100644 --- a/drivers/media/dvb/b2c2/Makefile +++ b/drivers/media/dvb/b2c2/Makefile @@ -1,3 +1,6 @@ +obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o + obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o +obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c index 940f6a862..bfebb3d68 100644 --- a/drivers/media/dvb/b2c2/skystar2.c +++ b/drivers/media/dvb/b2c2/skystar2.c @@ -30,14 +30,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include +#include #include #include #include +#include #include -#include "dvb_i2c.h" #include "dvb_frontend.h" #include @@ -48,13 +50,21 @@ #include "dvbdev.h" #include "demux.h" #include "dvb_net.h" +#include "stv0299.h" +#include "mt352.h" +#include "mt312.h" + -#include "dvb_functions.h" +static int debug; +static int enable_hw_filters = 2; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Set debugging level (0 = default, 1 = most messages, 2 = all messages)."); +module_param(enable_hw_filters, int, 0444); +MODULE_PARM_DESC(enable_hw_filters, "enable hardware filters: supported values: 0 (none), 1, 2"); -static int debug = 0; #define dprintk(x...) do { if (debug>=1) printk(x); } while (0) #define ddprintk(x...) do { if (debug>=2) printk(x); } while (0) -static int enable_hw_filters = 2; #define SIZE_OF_BUF_DMA1 0x3ac00 #define SIZE_OF_BUF_DMA2 0x758 @@ -70,6 +80,9 @@ struct dmaq { u8 *buffer; }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +#define __iomem +#endif struct adapter { struct pci_dev *pdev; @@ -79,7 +92,7 @@ struct adapter { u32 pid_filter_max; u32 mac_filter_max; u32 irq; - unsigned long io_mem; + void __iomem *io_mem; unsigned long io_port; u8 mac_addr[8]; u32 dw_sram_type; @@ -89,7 +102,7 @@ struct adapter { struct dmxdev dmxdev; struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; - struct dvb_i2c_bus *i2c_bus; + struct i2c_adapter i2c_adap; struct dvb_net dvbnet; struct semaphore i2c_sem; @@ -111,6 +124,9 @@ struct adapter { int pid_count; int whole_bandwidth_count; u32 mac_filter; + + struct dvb_frontend* fe; + int (*fe_sleep)(struct dvb_frontend* fe); }; #define write_reg_dw(adapter,reg,value) writel(value, adapter->io_mem + reg) @@ -277,9 +293,9 @@ static u32 flex_i2c_write(struct adapter *adapter, u32 device, u32 bus, u32 addr return buf - start; } -static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int num) +static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msgs[], int num) { - struct adapter *tmp = i2c->data; + struct adapter *tmp = i2c_get_adapdata(adapter); int i, ret = 0; if (down_interruptible(&tmp->i2c_sem)) @@ -290,13 +306,6 @@ static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int for (i = 0; i < num; i++) { ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); - - /* allow only the mt312 and stv0299 frontends to access the bus */ - if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && (msgs[i].addr != 0x61)) { - up(&tmp->i2c_sem); - - return -EREMOTEIO; - } } // read command @@ -307,10 +316,10 @@ static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int up(&tmp->i2c_sem); if (ret != msgs[1].len) { - printk("%s: read error !\n", __FUNCTION__); + dprintk("%s: read error !\n", __FUNCTION__); for (i = 0; i < 2; i++) { - printk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, + dprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); } @@ -330,9 +339,9 @@ static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int up(&tmp->i2c_sem); if (ret != msgs[0].len - 1) { - printk("%s: write error %i !\n", __FUNCTION__, ret); + dprintk("%s: write error %i !\n", __FUNCTION__, ret); - printk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i, + dprintk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len); return -EREMOTEIO; @@ -778,7 +787,7 @@ static int eeprom_read(struct adapter *adapter, u16 addr, u8 *buf, u16 len) return flex_i2c_read(adapter, 0x20000000, 0x50, addr, buf, len); } -u8 calc_lrc(u8 *buf, int len) +static u8 calc_lrc(u8 *buf, int len) { int i; u8 sum; @@ -1763,11 +1772,11 @@ static void free_adapter_object(struct adapter *adapter) free_dma_queue(adapter); - if (adapter->io_mem != 0) - iounmap((void *) adapter->io_mem); + if (adapter->io_mem) + iounmap(adapter->io_mem); if (adapter != 0) - kfree(adapter); + kfree(adapter); } static struct pci_driver skystar2_pci_driver; @@ -1798,15 +1807,15 @@ static int claim_adapter(struct adapter *adapter) adapter->io_port = pdev->resource[1].start; - adapter->io_mem = (unsigned long) ioremap(pdev->resource[0].start, 0x800); + adapter->io_mem = ioremap(pdev->resource[0].start, 0x800); - if (adapter->io_mem == 0) { + if (!adapter->io_mem) { dprintk("%s: can not map io memory\n", __FUNCTION__); return 2; } - dprintk("%s: io memory maped at %lx\n", __FUNCTION__, adapter->io_mem); + dprintk("%s: io memory maped at %p\n", __FUNCTION__, adapter->io_mem); return 1; } @@ -2122,18 +2131,17 @@ static int send_diseqc_msg(struct adapter *adapter, int len, u8 *msg, unsigned l udelay(12500); set_tuner_tone(adapter, 0); } - dvb_delay(20); + msleep(20); } return 0; } - -int soft_diseqc(struct adapter *adapter, unsigned int cmd, void *arg) +static int flexcop_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + + switch(tone) { case SEC_TONE_ON: set_tuner_tone(adapter, 1); break; @@ -2143,91 +2151,312 @@ int soft_diseqc(struct adapter *adapter, unsigned int cmd, void *arg) default: return -EINVAL; }; - break; - case FE_DISEQC_SEND_MASTER_CMD: + return 0; +} + +static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; send_diseqc_msg(adapter, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - send_diseqc_msg(adapter, 0, NULL, (unsigned long) arg); - break; +static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct adapter* adapter = (struct adapter*) fe->dvb->priv; - default: - return -EOPNOTSUPP; - }; + send_diseqc_msg(adapter, 0, NULL, minicmd); return 0; } -static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int flexcop_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - struct adapter *adapter = fe->before_after_data; - - struct dvb_frontend_info info; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; - fe->ioctl(fe, FE_GET_INFO, &info); + dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); - // we must use different DiSEqC hw + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13); + set_tuner_polarity(adapter, 1); + return 0; - if (strcmp(info.name, "Zarlink MT312") == 0) { - //VP310 using mt312 driver for tuning only: diseqc not wired - //use FCII instead - if (!soft_diseqc(adapter, cmd, arg)) + case SEC_VOLTAGE_18: + dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18); + set_tuner_polarity(adapter, 2); return 0; + + default: + return -EINVAL; + } } - switch (cmd) { - case FE_SLEEP: +static int flexcop_sleep(struct dvb_frontend* fe) { - dprintk("%s: FE_SLEEP\n", __FUNCTION__); + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + dprintk("%s: FE_SLEEP\n", __FUNCTION__); set_tuner_polarity(adapter, 0); - // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend. - return -EOPNOTSUPP; + if (adapter->fe_sleep) return adapter->fe_sleep(fe); + return 0; } - case FE_SET_VOLTAGE: +static u32 flexcop_i2c_func(struct i2c_adapter *adapter) { - dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); + printk("flexcop_i2c_func\n"); - switch ((fe_sec_voltage_t) arg) { - case SEC_VOLTAGE_13: + return I2C_FUNC_I2C; +} - dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13); +static struct i2c_algorithm flexcop_algo = { + .name = "flexcop i2c algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = master_xfer, + .functionality = flexcop_i2c_func, +}; - set_tuner_polarity(adapter, 1); - return 0; - case SEC_VOLTAGE_18: - dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18); +static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; - set_tuner_polarity(adapter, 2); + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - return 0; + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); - default: + return 0; +} - return -EINVAL; +static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + + div = params->frequency / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x84; // 0xC4 + buf[3] = 0x08; + + if (params->frequency < 1500000) buf[3] |= 0x10; + + if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static u8 samsung_tbmu24112_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7D, + 0x05, 0x35, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0xC3, + 0x0C, 0x00, + 0x0D, 0x81, + 0x0E, 0x23, + 0x0F, 0x12, + 0x10, 0x7E, + 0x11, 0x84, + 0x12, 0xB9, + 0x13, 0x88, + 0x14, 0x89, + 0x15, 0xC9, + 0x16, 0x00, + 0x17, 0x5C, + 0x18, 0x00, + 0x19, 0x00, + 0x1A, 0x00, + 0x1C, 0x00, + 0x1D, 0x00, + 0x1E, 0x00, + 0x1F, 0x3A, + 0x20, 0x2E, + 0x21, 0x80, + 0x22, 0xFF, + 0x23, 0xC1, + 0x28, 0x00, + 0x29, 0x1E, + 0x2A, 0x14, + 0x2B, 0x0F, + 0x2C, 0x09, + 0x2D, 0x05, + 0x31, 0x1F, + 0x32, 0x19, + 0x33, 0xFE, + 0x34, 0x93, + 0xff, 0xff, }; - } +static struct stv0299_config samsung_tbmu24112_config = { + .demod_address = 0x68, + .inittab = samsung_tbmu24112_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_LK, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, + .pll_set = samsung_tbmu24112_pll_set, +}; - default: - return -EOPNOTSUPP; - }; + + + +static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) +{ + static u8 mt352_clock_config [] = { 0x89, 0x10, 0x2d }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); return 0; } +int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +{ + u32 div; + unsigned char bs = 0; + + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; + + if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; + if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; + if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; + + pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = 0xcc; + pllbuf[4] = bs; + + return 0; +} + +static struct mt352_config samsung_tdtc9251dh0_config = { + + .demod_address = 0x0f, + .demod_init = samsung_tdtc9251dh0_demod_init, + .pll_set = samsung_tdtc9251dh0_pll_set, +}; + +static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct adapter* adapter = (struct adapter*) fe->dvb->priv; + + div = (params->frequency + (125/2)) / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + buf[2] = 0x84 | ((div >> 10) & 0x60); + buf[3] = 0x80; + + if (params->frequency < 1550000) + buf[3] |= 0x02; + + if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct mt312_config skystar23_samsung_tbdu18132_config = { + + .demod_address = 0x0e, + .pll_set = skystar23_samsung_tbdu18132_pll_set, +}; + + + + +static void frontend_init(struct adapter *skystar2) +{ + switch(skystar2->pdev->device) { + case 0x2103: // Technisat Skystar2 OR Technisat Airstar2 + + // try the skystar2 v2.6 first (stv0299/Samsung tbmu24112(sl1935)) + skystar2->fe = stv0299_attach(&samsung_tbmu24112_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->set_voltage = flexcop_set_voltage; + skystar2->fe_sleep = skystar2->fe->ops->sleep; + skystar2->fe->ops->sleep = flexcop_sleep; + break; +} + + // try the airstar2 (mt352/Samsung tdtc9251dh0(??)) + skystar2->fe = mt352_attach(&samsung_tdtc9251dh0_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->info.frequency_min = 474000000; + skystar2->fe->ops->info.frequency_max = 858000000; + break; + } + + // try the skystar2 v2.3 (vp310/Samsung tbdu18132(tsa5059)) + skystar2->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &skystar2->i2c_adap); + if (skystar2->fe != NULL) { + skystar2->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; + skystar2->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst; + skystar2->fe->ops->set_tone = flexcop_set_tone; + skystar2->fe->ops->set_voltage = flexcop_set_voltage; + skystar2->fe_sleep = skystar2->fe->ops->sleep; + skystar2->fe->ops->sleep = flexcop_sleep; + break; + } + break; + } + + if (skystar2->fe == NULL) { + printk("skystar2: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + skystar2->pdev->vendor, + skystar2->pdev->device, + skystar2->pdev->subsystem_vendor, + skystar2->pdev->subsystem_device); + } else { + if (dvb_register_frontend(skystar2->dvb_adapter, skystar2->fe)) { + printk("skystar2: Frontend registration failed!\n"); + if (skystar2->fe->ops->release) + skystar2->fe->ops->release(skystar2->fe); + skystar2->fe = NULL; + } + } +} + + static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct adapter *adapter; @@ -2254,16 +2483,31 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter = (struct adapter *) pci_get_drvdata(pdev); + dvb_adapter->priv = adapter; adapter->dvb_adapter = dvb_adapter; + init_MUTEX(&adapter->i2c_sem); - adapter->i2c_bus = dvb_register_i2c_bus(master_xfer, adapter, adapter->dvb_adapter, 0); - if (!adapter->i2c_bus) - return -ENOMEM; + memset(&adapter->i2c_adap, 0, sizeof(struct i2c_adapter)); + strcpy(adapter->i2c_adap.name, "SkyStar2"); + + i2c_set_adapdata(&adapter->i2c_adap, adapter); - dvb_add_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL, adapter); +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + adapter->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; +#else + adapter->i2c_adap.class = I2C_CLASS_TV_DIGITAL; +#endif + adapter->i2c_adap.algo = &flexcop_algo; + adapter->i2c_adap.algo_data = NULL; + adapter->i2c_adap.id = I2C_ALGO_BIT; + + if (i2c_add_adapter(&adapter->i2c_adap) < 0) { + dvb_unregister_adapter (adapter->dvb_adapter); + return -ENOMEM; + } dvbdemux = &adapter->demux; @@ -2300,6 +2544,9 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return ret; dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); + + frontend_init(adapter); + return 0; } @@ -2324,11 +2571,10 @@ static void skystar2_remove(struct pci_dev *pdev) dvb_dmxdev_release(&adapter->dmxdev); dvb_dmx_release(&adapter->demux); - if (adapter->dvb_adapter != NULL) { - dvb_remove_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL); + if (adapter->fe != NULL) dvb_unregister_frontend(adapter->fe); - if (adapter->i2c_bus != NULL) - dvb_unregister_i2c_bus(master_xfer, adapter->i2c_bus->adapter, adapter->i2c_bus->id); + if (adapter->dvb_adapter != NULL) { + i2c_del_adapter(&adapter->i2c_adap); dvb_unregister_adapter(adapter->dvb_adapter); } @@ -2338,14 +2584,14 @@ static void skystar2_remove(struct pci_dev *pdev) static struct pci_device_id skystar2_pci_tbl[] = { {0x000013d0, 0x00002103, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, - {0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, //FCIII +/* {0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, UNDEFINED HARDWARE - mail linuxtv.org list */ //FCIII {0,}, }; MODULE_DEVICE_TABLE(pci, skystar2_pci_tbl); static struct pci_driver skystar2_pci_driver = { - .name = "Technisat SkyStar2 driver", + .name = "SkyStar2", .id_table = skystar2_pci_tbl, .probe = skystar2_probe, .remove = skystar2_remove, @@ -2364,10 +2610,5 @@ static void skystar2_cleanup(void) module_init(skystar2_init); module_exit(skystar2_cleanup); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "enable verbose debug messages: supported values: 1 and 2"); -MODULE_PARM(enable_hw_filters, "i"); -MODULE_PARM_DESC(enable_hw_filters, "enable hardware filters: supported values: 0 (none), 1, 2"); - MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 572bd491c..114787f92 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -1,13 +1,18 @@ config DVB_BT8XX - tristate "Nebula/Pinnacle PCTV PCI cards" + tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards" depends on DVB_CORE && PCI && VIDEO_BT848 + select DVB_MT352 + select DVB_SP887X help Support for PCI cards based on the Bt8xx PCI bridge. Examples are - the Nebula cards, the Pinnacle PCTV cards, and Twinhan DST cards. + the Nebula cards, the Pinnacle PCTV cards and Twinhan DST cards. Since these cards have no MPEG decoder onboard, they transmit only compressed MPEG data over the PCI bus, so you need an external software decoder to watch TV on your computer. + If you have a Twinhan card, don't forget to select + "Twinhan DST based DVB-S/-T frontend". + Say Y if you own such a device and want to use it. diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile index 6db28906a..9da8604b9 100644 --- a/drivers/media/dvb/bt8xx/Makefile +++ b/drivers/media/dvb/bt8xx/Makefile @@ -1,5 +1,5 @@ -obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o +obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 1619f4c3f..7968bfef3 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -27,8 +27,8 @@ * */ -#include #include +#include #include #include #include @@ -44,22 +44,21 @@ #include "dmxdev.h" #include "dvbdev.h" #include "bt878.h" -#include "dst-bt878.h" +#include "dst_priv.h" -#include "dvb_functions.h" /**************************************/ /* Miscellaneous utility definitions */ /**************************************/ -unsigned int bt878_verbose = 1; -unsigned int bt878_debug = 0; -MODULE_PARM(bt878_verbose, "i"); +static unsigned int bt878_verbose = 1; +static unsigned int bt878_debug; + +module_param_named(verbose, bt878_verbose, int, 0444); MODULE_PARM_DESC(bt878_verbose, "verbose startup messages, default is 1 (yes)"); -MODULE_PARM(bt878_debug, "i"); -MODULE_PARM_DESC(bt878_debug, "debug messages, default is 0 (no)"); -MODULE_LICENSE("GPL"); +module_param_named(debug, bt878_debug, int, 0644); +MODULE_PARM_DESC(bt878_debug, "Turn on/off debugging (default:off)."); int bt878_num; struct bt878 bt878[BT878_MAX]; @@ -339,10 +338,6 @@ static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -extern int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data); -extern int bttv_read_gpio(unsigned int card, unsigned long *data); -extern int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data); - int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp) { @@ -386,20 +381,20 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * EXPORT_SYMBOL(bt878_device_control); -struct bt878 *bt878_find_by_dvb_adap(struct dvb_adapter *adap) +struct bt878 *bt878_find_by_i2c_adap(struct i2c_adapter *adapter) { unsigned int card_nr; - printk("bt878 find by dvb adap: checking \"%s\"\n",adap->name); + printk("bt878 find by dvb adap: checking \"%s\"\n",adapter->name); for (card_nr = 0; card_nr < bt878_num; card_nr++) { - if (bt878[card_nr].adap_ptr == adap) + if (bt878[card_nr].adapter == adapter) return &bt878[card_nr]; } - printk("bt878 find by dvb adap: NOT found \"%s\"\n",adap->name); + printk("bt878 find by dvb adap: NOT found \"%s\"\n",adapter->name); return NULL; } -EXPORT_SYMBOL(bt878_find_by_dvb_adap); +EXPORT_SYMBOL(bt878_find_by_i2c_adap); /***********************/ /* PCI device handling */ @@ -417,6 +412,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); + if (pci_enable_device(dev)) + return -EIO; bt = &bt878[bt878_num]; bt->dev = dev; @@ -426,11 +423,10 @@ static int __devinit bt878_probe(struct pci_dev *dev, bt->id = dev->device; bt->irq = dev->irq; bt->bt878_adr = pci_resource_start(dev, 0); - if (pci_enable_device(dev)) - return -EIO; if (!request_mem_region(pci_resource_start(dev, 0), pci_resource_len(dev, 0), "bt878")) { - return -EBUSY; + result = -EBUSY; + goto fail0; } pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); @@ -501,6 +497,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, fail1: release_mem_region(pci_resource_start(bt->dev, 0), pci_resource_len(bt->dev, 0)); + fail0: + pci_disable_device(dev); return result; } @@ -513,11 +511,11 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev) printk("bt878(%d): unloading\n", bt->nr); /* turn off all capturing, DMA and IRQs */ - btand(~13, BT878_AGPIO_DMA_CTL); + btand(~0x13, BT878_AGPIO_DMA_CTL); /* first disable interrupts before unmapping the memory! */ btwrite(0, BT878_AINT_MASK); - btwrite(~0x0UL, BT878_AINT_STAT); + btwrite(~0U, BT878_AINT_STAT); /* disable PCI bus-mastering */ pci_read_config_byte(bt->dev, PCI_COMMAND, &command); @@ -540,6 +538,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev) bt878_mem_free(bt); pci_set_drvdata(pci_dev, NULL); + pci_disable_device(pci_dev); return; } @@ -560,22 +559,11 @@ static struct pci_driver bt878_pci_driver = { static int bt878_pci_driver_registered = 0; -/* This will be used later by dvb-bt8xx to only use the audio - * dma of certain cards */ -int bt878_find_audio_dma(void) -{ - // pci_register_driver(&bt878_pci_driver); - bt878_pci_driver_registered = 1; - return 0; -} - -EXPORT_SYMBOL(bt878_find_audio_dma); - /*******************************/ /* Module management functions */ /*******************************/ -int bt878_init_module(void) +static int bt878_init_module(void) { bt878_num = 0; bt878_pci_driver_registered = 0; @@ -587,13 +575,13 @@ int bt878_init_module(void) /* bt878_check_chipset(); */ - /* later we register inside of bt878_find_audio_dma + /* later we register inside of bt878_find_audio_dma() * because we may want to ignore certain cards */ bt878_pci_driver_registered = 1; return pci_module_init(&bt878_pci_driver); } -void bt878_cleanup_module(void) +static void bt878_cleanup_module(void) { if (bt878_pci_driver_registered) { bt878_pci_driver_registered = 0; @@ -602,11 +590,12 @@ void bt878_cleanup_module(void) return; } -EXPORT_SYMBOL(bt878_init_module); -EXPORT_SYMBOL(bt878_cleanup_module); module_init(bt878_init_module); module_exit(bt878_cleanup_module); +//MODULE_AUTHOR("XXX"); +MODULE_LICENSE("GPL"); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h index ebffd121a..22fa5211c 100644 --- a/drivers/media/dvb/bt8xx/bt878.h +++ b/drivers/media/dvb/bt8xx/bt878.h @@ -26,6 +26,7 @@ #include #include #include "bt848.h" +#include "bttv.h" #define BT878_VERSION_CODE 0x000000 @@ -94,14 +95,14 @@ struct bt878 { struct semaphore gpio_lock; unsigned int nr; unsigned int bttv_nr; - struct dvb_adapter *adap_ptr; + struct i2c_adapter *adapter; struct pci_dev *dev; unsigned int id; unsigned int TS_Size; unsigned char revision; unsigned int irq; unsigned long bt878_adr; - unsigned char *bt878_mem; /* function 1 */ + volatile void __iomem *bt878_mem; /* function 1 */ volatile u32 finished_block; volatile u32 last_block; @@ -128,17 +129,17 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin, void bt878_stop(struct bt878 *bt); #if defined(__powerpc__) /* big-endian */ -extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) +extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val) { __asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val), "r"(addr)); __asm__ __volatile__("eieio":::"memory"); } -#define bmtwrite(dat,adr) io_st_le32((unsigned *)(adr),(dat)) -#define bmtread(adr) ld_le32((unsigned *)(adr)) +#define bmtwrite(dat,adr) io_st_le32((adr),(dat)) +#define bmtread(adr) ld_le32((adr)) #else -#define bmtwrite(dat,adr) writel((dat), (char *) (adr)) +#define bmtwrite(dat,adr) writel((dat), (adr)) #define bmtread(adr) readl(adr) #endif diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index bd8323072..d199c596b 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -19,9 +19,11 @@ * */ -#include +#include #include +#include #include +#include #include #include #include @@ -33,33 +35,32 @@ #include "dvb-bt8xx.h" -#include "dvb_functions.h" - #include "bt878.h" -/* ID THAT MUST GO INTO i2c ids */ -#ifndef I2C_DRIVERID_DVB_BT878A -# define I2C_DRIVERID_DVB_BT878A I2C_DRIVERID_EXP0+10 -#endif - +static int debug; -#define dprintk if (debug) printk +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); -extern int bttv_get_cardinfo(unsigned int card, int *type, int *cardid); -extern struct pci_dev* bttv_get_pcidev(unsigned int card); - -static LIST_HEAD(card_list); -static int debug = 0; +#define dprintk( args... ) \ + do { \ + if (debug) printk(KERN_DEBUG args); \ + } while (0) static void dvb_bt8xx_task(unsigned long data) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data; - //printk("%d ", finished_block); + //printk("%d ", card->bt->finished_block); while (card->bt->last_block != card->bt->finished_block) { - (card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)(&card->demux, &card->bt->buf_cpu[card->bt->last_block * card->bt->block_bytes], card->bt->block_bytes); - card->bt->last_block = (card->bt->last_block + 1) % card->bt->block_count; + (card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) + (&card->demux, + &card->bt->buf_cpu[card->bt->last_block * + card->bt->block_bytes], + card->bt->block_bytes); + card->bt->last_block = (card->bt->last_block + 1) % + card->bt->block_count; } } @@ -67,20 +68,21 @@ static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct dvb_bt8xx_card *card = dvbdmx->priv; + int rc; dprintk("dvb_bt8xx: start_feed\n"); if (!dvbdmx->dmx.frontend) return -EINVAL; - if (card->active) - return 0; - - card->active = 1; - -// bt878_start(card->bt, card->gpio_mode); - - return 0; + down(&card->lock); + card->nfeeds++; + rc = card->nfeeds; + if (card->nfeeds == 1) + bt878_start(card->bt, card->gpio_mode, + card->op_sync_orin, card->irq_err_ignore); + up(&card->lock); + return rc; } static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) @@ -93,33 +95,15 @@ static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (!dvbdmx->dmx.frontend) return -EINVAL; - if (!card->active) - return 0; - -// bt878_stop(card->bt); - - card->active = 0; + down(&card->lock); + card->nfeeds--; + if (card->nfeeds == 0) + bt878_stop(card->bt); + up(&card->lock); return 0; } -static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) -{ - struct dvb_bt8xx_card *card = i2c->data; - int retval; - - if (down_interruptible (&card->bt->gpio_lock)) - return -ERESTARTSYS; - - retval = i2c_transfer(card->i2c_adapter, - (struct i2c_msg*) msgs, - num); - - up(&card->bt->gpio_lock); - - return retval; -} - static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev) { if ((adev->subsystem_vendor == bdev->subsystem_vendor) && @@ -142,168 +126,298 @@ static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci return NULL; } -static int __init dvb_bt8xx_card_match(unsigned int bttv_nr, char *card_name, u32 gpio_mode, u32 op_sync_orin, u32 irq_err_ignore) + +static int thomson_dtt7579_demod_init(struct dvb_frontend* fe) { - struct dvb_bt8xx_card *card; - struct pci_dev* bttv_pci_dev; + static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 }; + static u8 mt352_gpp_ctl_cfg [] = { 0x75, 0x33 }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); + mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); - dprintk("dvb_bt8xx: identified card%d as %s\n", bttv_nr, card_name); - - if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL))) - return -ENOMEM; + return 0; +} - memset(card, 0, sizeof(*card)); - card->bttv_nr = bttv_nr; - strncpy(card->card_name, card_name, sizeof(card_name) - 1); - - if (!(bttv_pci_dev = bttv_get_pcidev(bttv_nr))) { - printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr); - kfree(card); - return -EFAULT; - } +static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +{ + u32 div; + unsigned char bs = 0; + unsigned char cp = 0; - if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) { - printk("dvb_bt8xx: unable to determine DMA core of card %d\n", card->bttv_nr); - - kfree(card); - return -EFAULT; - - } - init_MUTEX(&card->bt->gpio_lock); - card->bt->bttv_nr = bttv_nr; - card->gpio_mode = gpio_mode; - card->op_sync_orin = op_sync_orin; - card->irq_err_ignore = irq_err_ignore; - list_add_tail(&card->list, &card_list); + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; + + if (params->frequency < 542000000) cp = 0xb4; + else if (params->frequency < 771000000) cp = 0xbc; + else cp = 0xf4; + + if (params->frequency == 0) bs = 0x03; + else if (params->frequency < 443250000) bs = 0x02; + else bs = 0x08; + + pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = cp; + pllbuf[4] = bs; return 0; } -static struct dvb_bt8xx_card *dvb_bt8xx_find_by_i2c_adap(struct i2c_adapter *adap) +static struct mt352_config thomson_dtt7579_config = { + + .demod_address = 0x0f, + .demod_init = thomson_dtt7579_demod_init, + .pll_set = thomson_dtt7579_pll_set, +}; + + + +static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct dvb_bt8xx_card *card; - struct list_head *item; - - printk("find by i2c adap: checking \"%s\"\n",adap->name); - list_for_each(item, &card_list) { - card = list_entry(item, struct dvb_bt8xx_card, list); - if (card->i2c_adapter == adap) - return card; - } - return NULL; + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + u8 cfg, cpump, band_select; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (36000000 + params->frequency + 83333) / 166666; + cfg = 0x88; + + if (params->frequency < 175000000) cpump = 2; + else if (params->frequency < 390000000) cpump = 1; + else if (params->frequency < 470000000) cpump = 2; + else if (params->frequency < 750000000) cpump = 2; + else cpump = 3; + + if (params->frequency < 175000000) band_select = 0x0e; + else if (params->frequency < 470000000) band_select = 0x05; + else band_select = 0x03; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | cfg; + data[3] = cpump | band_select; + + i2c_transfer(card->i2c_adapter, &msg, 1); + return (div * 166666 - 36000000); } -static struct dvb_bt8xx_card *dvb_bt8xx_find_by_pci(struct i2c_adapter *adap) +static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) { - struct dvb_bt8xx_card *card; - struct list_head *item; - struct device *dev; - struct pci_dev *pci; - - printk("find by pci: checking \"%s\"\n",adap->name); - dev = adap->dev.parent; - if (NULL == dev) { - /* shoudn't happen with 2.6.0-test7 + newer */ - printk("attach: Huh? i2c adapter not in sysfs tree?\n"); - return NULL; - } - pci = to_pci_dev(dev); - list_for_each(item, &card_list) { - card = list_entry(item, struct dvb_bt8xx_card, list); - if (is_pci_slot_eq(pci, card->bt->dev)) { - return card; - } - } - return NULL; + struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv; + + return request_firmware(fw, name, &bt->bt->dev->dev); } -static int dvb_bt8xx_attach(struct i2c_adapter *adap) +struct sp887x_config microtune_mt7202dtf_config = { + + .demod_address = 0x70, + .pll_set = microtune_mt7202dtf_pll_set, + .request_firmware = microtune_mt7202dtf_request_firmware, +}; + + + +static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) { - struct dvb_bt8xx_card *card; - - printk("attach: checking \"%s\"\n",adap->name); - - /* looking for bt878 cards ... */ - if (adap->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return 0; - card = dvb_bt8xx_find_by_pci(adap); - if (!card) - return 0; - card->i2c_adapter = adap; - printk("attach: \"%s\", to card %d\n", - adap->name, card->bttv_nr); - try_module_get(adap->owner); + static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d }; + static u8 mt352_reset [] = { 0x50, 0x80 }; + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; + static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x40, 0x40 }; + static u8 mt352_av771_extra[] = { 0xB5, 0x7A }; + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; + + + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); + udelay(2000); + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); + + mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg)); + udelay(2000); + mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra)); + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); return 0; } -static void dvb_bt8xx_i2c_adap_free(struct i2c_adapter *adap) +static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) { - module_put(adap->owner); + u32 div; + unsigned char bs = 0; + unsigned char cp = 0; + + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; + + if (params->frequency < 150000000) cp = 0xB4; + else if (params->frequency < 173000000) cp = 0xBC; + else if (params->frequency < 250000000) cp = 0xB4; + else if (params->frequency < 400000000) cp = 0xBC; + else if (params->frequency < 420000000) cp = 0xF4; + else if (params->frequency < 470000000) cp = 0xFC; + else if (params->frequency < 600000000) cp = 0xBC; + else if (params->frequency < 730000000) cp = 0xF4; + else cp = 0xFC; + + if (params->frequency < 150000000) bs = 0x01; + else if (params->frequency < 173000000) bs = 0x01; + else if (params->frequency < 250000000) bs = 0x02; + else if (params->frequency < 400000000) bs = 0x02; + else if (params->frequency < 420000000) bs = 0x02; + else if (params->frequency < 470000000) bs = 0x02; + else if (params->frequency < 600000000) bs = 0x08; + else if (params->frequency < 730000000) bs = 0x08; + else bs = 0x08; + + pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[1] = div >> 8; + pllbuf[2] = div & 0xff; + pllbuf[3] = cp; + pllbuf[4] = bs; + + return 0; } -static int dvb_bt8xx_detach(struct i2c_adapter *adap) -{ - struct dvb_bt8xx_card *card; +static struct mt352_config advbt771_samsung_tdtc9251dh0_config = { - card = dvb_bt8xx_find_by_i2c_adap(adap); - if (!card) - return 0; + .demod_address = 0x0f, + .demod_init = advbt771_samsung_tdtc9251dh0_demod_init, + .pll_set = advbt771_samsung_tdtc9251dh0_pll_set, +}; - /* This should not happen. We have locked the module! */ - printk("detach: \"%s\", for card %d removed\n", - adap->name, card->bttv_nr); - return 0; -} -static struct i2c_driver dvb_bt8xx_driver = { - .owner = THIS_MODULE, - .name = "dvb_bt8xx", - .id = I2C_DRIVERID_DVB_BT878A, - .flags = I2C_DF_NOTIFY, - .attach_adapter = dvb_bt8xx_attach, - .detach_adapter = dvb_bt8xx_detach, +static struct dst_config dst_config = { + + .demod_address = 0x55, }; -static void __init dvb_bt8xx_get_adaps(void) -{ - i2c_add_driver(&dvb_bt8xx_driver); -} -static void __exit dvb_bt8xx_exit_adaps(void) +static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - i2c_del_driver(&dvb_bt8xx_driver); + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) }; + + div = (params->frequency + 36166667) / 166667; + + buf[0] = (div >> 8) & 0x7F; + buf[1] = div & 0xFF; + buf[2] = 0x85; + if ((params->frequency >= 47000000) && (params->frequency < 153000000)) + buf[3] = 0x01; + else if ((params->frequency >= 153000000) && (params->frequency < 430000000)) + buf[3] = 0x02; + else if ((params->frequency >= 430000000) && (params->frequency < 824000000)) + buf[3] = 0x0C; + else if ((params->frequency >= 824000000) && (params->frequency < 863000000)) + buf[3] = 0x8C; + else + return -EINVAL; + + i2c_transfer(card->i2c_adapter, &msg, 1); + return 0; } -static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) +static struct nxt6000_config vp3021_alps_tded4_config = { + + .demod_address = 0x0a, + .clock_inversion = 1, + .pll_set = vp3021_alps_tded4_pll_set, +}; + + +static void frontend_init(struct dvb_bt8xx_card *card, u32 type) { - int result; + switch(type) { +#ifdef BTTV_DVICO_DVBT_LITE + case BTTV_DVICO_DVBT_LITE: + card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); + if (card->fe != NULL) { + card->fe->ops->info.frequency_min = 174000000; + card->fe->ops->info.frequency_max = 862000000; + break; + } + break; +#endif - if (!card->i2c_adapter) { - printk("dvb_bt8xx: unable to determine i2c adaptor of card %d, deleting\n", card->bttv_nr); +#ifdef BTTV_TWINHAN_VP3021 + case BTTV_TWINHAN_VP3021: +#else + case BTTV_NEBULA_DIGITV: +#endif + card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter); + if (card->fe != NULL) { + break; + } + break; - return -EFAULT; - + case BTTV_AVDVBT_761: + card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); + if (card->fe != NULL) { + break; + } + break; + + case BTTV_AVDVBT_771: + card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); + if (card->fe != NULL) { + card->fe->ops->info.frequency_min = 174000000; + card->fe->ops->info.frequency_max = 862000000; + break; + } + break; + + case BTTV_TWINHAN_DST: + card->fe = dst_attach(&dst_config, card->i2c_adapter, card->bt); + if (card->fe != NULL) { + break; + } + break; } - if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) { - + if (card->fe == NULL) { + printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + card->bt->dev->vendor, + card->bt->dev->device, + card->bt->dev->subsystem_vendor, + card->bt->dev->subsystem_device); + } else { + if (dvb_register_frontend(card->dvb_adapter, card->fe)) { + printk("dvb-bt8xx: Frontend registration failed!\n"); + if (card->fe->ops->release) + card->fe->ops->release(card->fe); + card->fe = NULL; + } + } +} + +static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) +{ + int result; + + if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, + THIS_MODULE)) < 0) { printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result); - - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); return result; } - card->bt->adap_ptr = card->dvb_adapter; + card->dvb_adapter->priv = card; - if (!(dvb_register_i2c_bus(master_xfer, card, card->dvb_adapter, 0))) { - printk("dvb_bt8xx: dvb_register_i2c_bus of card%d failed\n", card->bttv_nr); - - dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - - return -EFAULT; - } + card->bt->adapter = card->i2c_adapter; memset(&card->demux, 0, sizeof(struct dvb_demux)); @@ -319,10 +433,7 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) if ((result = dvb_dmx_init(&card->demux)) < 0) { printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - return result; } @@ -334,10 +445,7 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result); dvb_dmx_release(&card->demux); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - return result; } @@ -348,10 +456,7 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - return result; } @@ -363,10 +468,7 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - return result; } @@ -377,10 +479,7 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); dvb_unregister_adapter(card->dvb_adapter); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); - return result; } @@ -388,72 +487,65 @@ static int __init dvb_bt8xx_load_card( struct dvb_bt8xx_card *card) tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card); - bt878_start(card->bt, card->gpio_mode, card->op_sync_orin, card->irq_err_ignore); + frontend_init(card, type); return 0; } -static int __init dvb_bt8xx_load_all(void) +static int dvb_bt8xx_probe(struct device *dev) { + struct bttv_sub_device *sub = to_bttv_sub_dev(dev); struct dvb_bt8xx_card *card; - struct list_head *entry, *entry_safe; - - list_for_each_safe(entry, entry_safe, &card_list) { - card = list_entry(entry, struct dvb_bt8xx_card, list); - if (dvb_bt8xx_load_card(card) < 0) { - list_del(&card->list); - kfree(card); - continue; - } - } - return 0; - -} - -#define BT878_NEBULA 0x68 -#define BT878_TWINHAN_DST 0x71 + struct pci_dev* bttv_pci_dev; + int ret; -static int __init dvb_bt8xx_init(void) -{ - unsigned int card_nr = 0; - int card_id; - int card_type; + if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL))) + return -ENOMEM; - dprintk("dvb_bt8xx: enumerating available bttv cards...\n"); - - while (bttv_get_cardinfo(card_nr, &card_type, &card_id) == 0) { - switch(card_id) { - case 0x001C11BD: - dvb_bt8xx_card_match(card_nr, "Pinnacle PCTV DVB-S", - 0x0400C060, 0, 0); + memset(card, 0, sizeof(*card)); + init_MUTEX(&card->lock); + card->bttv_nr = sub->core->nr; + strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); + card->i2c_adapter = &sub->core->i2c_adap; + + switch(sub->core->type) + { +/* case BTTV_PINNACLESAT: UNDEFINED HARDWARE */ +#ifdef BTTV_DVICO_DVBT_LITE + case BTTV_DVICO_DVBT_LITE: +#endif + card->gpio_mode = 0x0400C060; + card->op_sync_orin = 0; + card->irq_err_ignore = 0; /* 26, 15, 14, 6, 5 - * A_G2X DA_DPM DA_SBR DA_IOM_DA + * A_PWRDN DA_DPM DA_SBR DA_IOM_DA * DA_APP(parallel) */ break; - case 0x01010071: -nebula: - dvb_bt8xx_card_match(card_nr, "Nebula DigiTV DVB-T", - (1 << 26) | (1 << 14) | (1 << 5), - 0, 0); + +#ifdef BTTV_TWINHAN_VP3021 + case BTTV_TWINHAN_VP3021: +#else + case BTTV_NEBULA_DIGITV: +#endif + case BTTV_AVDVBT_761: + card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5); + card->op_sync_orin = 0; + card->irq_err_ignore = 0; /* A_PWRDN DA_SBR DA_APP (high speed serial) */ break; - case 0x07611461: - dvb_bt8xx_card_match(card_nr, "Avermedia DVB-T", - (1 << 26) | (1 << 14) | (1 << 5), - 0, 0); - /* A_PWRDN DA_SBR DA_APP (high speed serial) */ + + case BTTV_AVDVBT_771: //case 0x07711461: + card->gpio_mode = 0x0400402B; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = 0; + /* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/ break; - case 0x0: - if (card_type == BT878_NEBULA || - card_type == BT878_TWINHAN_DST) - goto dst; - goto unknown_card; - case 0x2611BD: - case 0x11822: -dst: - dvb_bt8xx_card_match(card_nr, "DST DVB-S", 0x2204f2c, - BT878_RISC_SYNC_MASK, - BT878_APABORT | BT878_ARIPERR | BT878_APPERR | BT878_AFBUS); + + case BTTV_TWINHAN_DST: + card->gpio_mode = 0x2204f2c; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR | + BT878_APPERR | BT878_AFBUS; /* 25,21,14,11,10,9,8,3,2 then * 0x33 = 5,4,1,0 * A_SEL=SML, DA_MLB, DA_SBR, @@ -466,42 +558,48 @@ dst: * ACAP_EN = 1, * RISC+FIFO ENABLE */ break; + default: -unknown_card: - printk("%s: unknown card_id found %0X\n", - __FUNCTION__, card_id); - if (card_type == BT878_NEBULA) { - printk("%s: bttv type set to nebula\n", - __FUNCTION__); - goto nebula; - } - if (card_type == BT878_TWINHAN_DST) { - printk("%s: bttv type set to Twinhan DST\n", - __FUNCTION__); - goto dst; - } - printk("%s: unknown card_type found %0X, NOT LOADED\n", - __FUNCTION__, card_type); - printk("%s: unknown card_nr found %0X\n", - __FUNCTION__, card_nr); + printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n", + sub->core->type); + kfree(card); + return -ENODEV; } - card_nr++; + + dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name); + + if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) { + printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr); + kfree(card); + return -EFAULT; } - dvb_bt8xx_get_adaps(); - dvb_bt8xx_load_all(); - return 0; + if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) { + printk("dvb_bt8xx: unable to determine DMA core of card %d,\n", + card->bttv_nr); + printk("dvb_bt8xx: if you have the ALSA bt87x audio driver " + "installed, try removing it.\n"); + + kfree(card); + return -EFAULT; } -static void __exit dvb_bt8xx_exit(void) -{ - struct dvb_bt8xx_card *card; - struct list_head *entry, *entry_safe; + init_MUTEX(&card->bt->gpio_lock); + card->bt->bttv_nr = sub->core->nr; + + if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) { + kfree(card); + return ret; + } - dvb_bt8xx_exit_adaps(); - list_for_each_safe(entry, entry_safe, &card_list) { - card = list_entry(entry, struct dvb_bt8xx_card, list); + dev_set_drvdata(dev, card); + return 0; +} + +static int dvb_bt8xx_remove(struct device *dev) +{ + struct dvb_bt8xx_card *card = dev_get_drvdata(dev); dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); @@ -512,14 +610,35 @@ static void __exit dvb_bt8xx_exit(void) card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); dvb_dmx_release(&card->demux); - dvb_unregister_i2c_bus(master_xfer, card->dvb_adapter, 0); - dvb_bt8xx_i2c_adap_free(card->i2c_adapter); + if (card->fe) dvb_unregister_frontend(card->fe); dvb_unregister_adapter(card->dvb_adapter); - list_del(&card->list); kfree(card); + + return 0; } +static struct bttv_sub_driver driver = { + .drv = { + .name = "dvb-bt8xx", + .probe = dvb_bt8xx_probe, + .remove = dvb_bt8xx_remove, + /* FIXME: + * .shutdown = dvb_bt8xx_shutdown, + * .suspend = dvb_bt8xx_suspend, + * .resume = dvb_bt8xx_resume, + */ + }, +}; + +static int __init dvb_bt8xx_init(void) +{ + return bttv_sub_register(&driver, "dvb"); +} + +static void __exit dvb_bt8xx_exit(void) +{ + bttv_sub_unregister(&driver); } module_init(dvb_bt8xx_init); @@ -527,4 +646,4 @@ module_exit(dvb_bt8xx_exit); MODULE_DESCRIPTION("Bt8xx based DVB adapter driver"); MODULE_AUTHOR("Florian Schirmer "); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); + diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 969606ecc..f25a25144 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -25,11 +25,15 @@ #include #include "dvbdev.h" #include "dvb_net.h" +#include "bttv.h" +#include "mt352.h" +#include "sp887x.h" +#include "dst.h" +#include "nxt6000.h" struct dvb_bt8xx_card { - - struct list_head list; - u8 active; + struct semaphore lock; + int nfeeds; char card_name[32]; struct dvb_adapter *dvb_adapter; struct bt878 *bt; @@ -44,4 +48,5 @@ struct dvb_bt8xx_card { struct i2c_adapter *i2c_adapter; struct dvb_net dvbnet; + struct dvb_frontend* fe; }; diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile index 712778914..c6baac20f 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb/dvb-core/Makefile @@ -3,7 +3,7 @@ # dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_functions.o dvb_frontend.o \ - dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o + dvb_ca_en50221.o dvb_frontend.o \ + dvb_net.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 1d685f6bc..cdbfb15b7 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -33,25 +34,20 @@ #include #include "dmxdev.h" -#include "dvb_functions.h" -MODULE_PARM(debug,"i"); -static int debug = 0; +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk if (debug) printk -inline struct dmxdev_filter * +static inline struct dmxdev_filter * dvb_dmxdev_file_to_filter(struct file *file) { return (struct dmxdev_filter *) file->private_data; } -inline struct dmxdev_dvr * -dvb_dmxdev_file_to_dvr(struct dmxdev *dmxdev, struct file *file) -{ - return (struct dmxdev_dvr *) file->private_data; -} - static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) { buffer->data=NULL; @@ -844,7 +840,7 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, } -ssize_t +static ssize_t dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file); @@ -1120,6 +1116,7 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) return 0; } +EXPORT_SYMBOL(dvb_dmxdev_init); void dvb_dmxdev_release(struct dmxdev *dmxdev) @@ -1136,5 +1133,5 @@ dvb_dmxdev_release(struct dmxdev *dmxdev) } dmxdev->demux->close(dmxdev->demux); } - +EXPORT_SYMBOL(dvb_dmxdev_release); diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index a4c3794a1..63eccd4b6 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -32,16 +32,19 @@ #include #include #include +#include #include #include -#include -#include +#include #include "dvb_ca_en50221.h" -#include "dvb_functions.h" #include "dvb_ringbuffer.h" -static int dvb_ca_en50221_debug = 0; +static int dvb_ca_en50221_debug; + +module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644); +MODULE_PARM_DESC(cam_debug, "enable verbose debug messages"); + #define dprintk if (dvb_ca_en50221_debug) printk #define INIT_TIMEOUT_SECS 5 @@ -108,7 +111,7 @@ struct dvb_ca_slot { int link_buf_size; /* semaphore for syncing access to slot structure */ - struct semaphore sem; + struct rw_semaphore sem; /* buffer for incoming packets */ struct dvb_ringbuffer rx_buffer; @@ -178,10 +181,12 @@ static u8* findstr(u8* haystack, int hlen, u8* needle, int nlen) { int i; - if (hlen < nlen) return NULL; + if (hlen < nlen) + return NULL; for(i=0; i<= hlen - nlen; i++) { - if (!strncmp(haystack+i, needle, nlen)) return haystack+i; + if (!strncmp(haystack + i, needle, nlen)) + return haystack + i; } return NULL; @@ -199,7 +204,6 @@ static u8* findstr(u8* haystack, int hlen, u8* needle, int nlen) static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot) { int slot_status; - int status; int cam_present_now; int cam_changed; @@ -209,9 +213,7 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot) } /* poll mode */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; - slot_status = ca->pub->poll_slot_status(ca->pub, slot); - up(&ca->slot_info[slot].sem); + slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open); cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0; cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0; @@ -250,7 +252,8 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot) * * @return 0 on success, nonzero on error. */ -static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 waitfor, int timeout_hz) +static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot, + u8 waitfor, int timeout_hz) { unsigned long timeout; unsigned long start; @@ -263,7 +266,8 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 while(1) { /* read the status and check for error */ int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); - if (res < 0) return -EIO; + if (res < 0) + return -EIO; /* if we got the flags, it was successful! */ if (res & waitfor) { @@ -277,7 +281,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 } /* wait for a bit */ - dvb_delay(1); + msleep(1); } dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start); @@ -306,33 +310,38 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot) /* we'll be determining these during this function */ ca->slot_info[slot].da_irq_supported = 0; - /* reset the link interface. Note CAM IRQs are disabled */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret; - /* set the host link buffer size temporarily. it will be overwritten with the * real negotiated size later. */ ca->slot_info[slot].link_buf_size = 2; /* read the buffer size from the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ/10)) != 0) return ret; - if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return -EIO; - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) + return ret; + if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) + return ret; + if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) + return -EIO; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) + return ret; /* store it, and choose the minimum of our buffer and the CAM's buffer size */ buf_size = (buf[0] << 8) | buf[1]; - if (buf_size > HOST_LINK_BUF_SIZE) buf_size = HOST_LINK_BUF_SIZE; + if (buf_size > HOST_LINK_BUF_SIZE) + buf_size = HOST_LINK_BUF_SIZE; ca->slot_info[slot].link_buf_size = buf_size; buf[0] = buf_size >> 8; buf[1] = buf_size & 0xff; dprintk("Chosen link buffer size of %i\n", buf_size); /* write the buffer size to the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret; - if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) return -EIO; - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) + return ret; + if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) + return ret; + if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) + return -EIO; + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) + return ret; /* success */ return 0; @@ -359,8 +368,17 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private* ca, int slot, int _address = *address; /* grab the next tuple length and type */ - if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) return _tupleType; - if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address+2)) < 0) return _tupleLength; + if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) + return _tupleType; + if (_tupleType == 0xff) { + dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType); + *address += 2; + *tupleType = _tupleType; + *tupleLength = 0; + return 0; + } + if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0) + return _tupleLength; _address += 4; dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength); @@ -368,7 +386,9 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private* ca, int slot, /* read in the whole tuple */ for(i=0; i< _tupleLength; i++) { tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i*2)); - dprintk(" 0x%02x: 0x%02x %c\n", i, tuple[i] & 0xff, ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); + dprintk(" 0x%02x: 0x%02x %c\n", + i, tuple[i] & 0xff, + ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.'); } _address += (_tupleLength*2); @@ -406,40 +426,58 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot) // CISTPL_DEVICE_0A - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1D) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1D) + return -EINVAL; // CISTPL_DEVICE_0C - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1C) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1C) + return -EINVAL; // CISTPL_VERS_1 - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x15) return -EINVAL; + if ((status = + dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x15) + return -EINVAL; // CISTPL_MANFID - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x20) return -EINVAL; - if (tupleLength != 4) return -EINVAL; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x20) + return -EINVAL; + if (tupleLength != 4) + return -EINVAL; manfid = (tuple[1] << 8) | tuple[0]; devid = (tuple[3] << 8) | tuple[2]; // CISTPL_CONFIG - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; - if (tupleType != 0x1A) return -EINVAL; - if (tupleLength < 3) return -EINVAL; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; + if (tupleType != 0x1A) + return -EINVAL; + if (tupleLength < 3) + return -EINVAL; /* extract the configbase */ rasz = tuple[0] & 3; - if (tupleLength < (3 + rasz + 14)) return -EINVAL; + if (tupleLength < (3 + rasz + 14)) + return -EINVAL; ca->slot_info[slot].config_base = 0; for(i=0; i< rasz+1; i++) { ca->slot_info[slot].config_base |= (tuple[2+i] << (8*i)); @@ -447,32 +485,39 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot) /* check it contains the correct DVB string */ dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8); - if (dvb_str == NULL) return -EINVAL; - if (tupleLength < ((dvb_str - (char*) tuple) + 12)) return -EINVAL; + if (dvb_str == NULL) + return -EINVAL; + if (tupleLength < ((dvb_str - (char *) tuple) + 12)) + return -EINVAL; /* is it a version we support? */ if (strncmp(dvb_str + 8, "1.00", 4)) { - printk("dvb_ca: Unsupported DVB CAM module version %c%c%c%c\n", - dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); + printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n", + ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]); return -EINVAL; } /* process the CFTABLE_ENTRY tuples, and any after those */ while((!end_chain) && (address < 0x1000)) { - if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status; + if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, + &tupleLength, tuple)) < 0) + return status; switch(tupleType) { case 0x1B: // CISTPL_CFTABLE_ENTRY - if (tupleLength < (2+11+17)) break; + if (tupleLength < (2 + 11 + 17)) + break; /* if we've already parsed one, just use it */ - if (got_cftableentry) break; + if (got_cftableentry) + break; /* get the config option */ ca->slot_info[slot].config_option = tuple[0] & 0x3f; /* OK, check it contains the correct strings */ if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) || - (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) break; + (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) + break; got_cftableentry = 1; break; @@ -485,17 +530,17 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot) break; default: /* Unknown tuple type - just skip this tuple and move to the next one */ - dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, tupleLength); + dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, + tupleLength); break; } } - if ((address > 0x1000) || (!got_cftableentry)) return -EINVAL; + if ((address > 0x1000) || (!got_cftableentry)) + return -EINVAL; dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n", - manfid, devid, - ca->slot_info[slot].config_base, - ca->slot_info[slot].config_option); + manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); // success! return 0; @@ -515,7 +560,9 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private* ca, int slot) dprintk ("%s\n", __FUNCTION__); /* set the config option */ - ca->pub->write_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option); + ca->pub->write_attribute_mem(ca->pub, slot, + ca->slot_info[slot].config_base, + ca->slot_info[slot].config_option); /* check it */ configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base); @@ -550,25 +597,28 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu dprintk ("%s\n", __FUNCTION__); - /* acquire the slot */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; - /* check if we have space for a link buf in the rx_buffer */ if (ebuf == NULL) { - if (dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer) < - (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { + int buf_free; + + down_read(&ca->slot_info[slot].sem); + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + status = -EIO; + goto exit; + } + buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); + up_read(&ca->slot_info[slot].sem); + + if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { status = -EAGAIN; goto exit; } } - /* reset the interface if there's been a tx error */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; - if (status & STATUSREG_TXERR) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; - } + /* check if there is data available */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (!(status & STATUSREG_DA)) { /* no data */ status = 0; @@ -576,28 +626,33 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu } /* read the amount of data */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) + goto exit; bytes_read = status << 8; - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) + goto exit; bytes_read |= status; /* check it will fit */ if (ebuf == NULL) { if (bytes_read > ca->slot_info[slot].link_buf_size) { - printk("dvb_ca: CAM tried to send a buffer larger than the link buffer size!\n"); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", + ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } if (bytes_read < 2) { - printk("dvb_ca: CAM sent a buffer that was less than 2 bytes!\n"); + printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } } else { if (bytes_read > ecount) { - printk("dvb_ca: CAM tried to send a buffer larger than the ecount size!\n"); + printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", + ca->dvbdev->adapter->num); status = -EIO; goto exit; } @@ -606,26 +661,39 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu /* fill the buffer */ for(i=0; i < bytes_read; i++) { /* read byte and check */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) + goto exit; /* OK, store it in the buffer */ buf[i] = status; } - /* check for read error (RE should now go to 0) */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + /* check for read error (RE should now be 0) */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (status & STATUSREG_RE) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } /* OK, add it to the receive buffer, or copy into external buffer if supplied */ if (ebuf == NULL) { + down_read(&ca->slot_info[slot].sem); + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + status = -EIO; + goto exit; + } dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read); + up_read(&ca->slot_info[slot].sem); } else { memcpy(ebuf, buf, bytes_read); } + dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, + buf[0], (buf[1] & 0x80) == 0, bytes_read); + /* wake up readers when a last_fragment is received */ if ((buf[1] & 0x80) == 0x00) { wake_up_interruptible(&ca->wait_queue); @@ -634,7 +702,6 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu status = bytes_read; exit: - up(&ca->slot_info[slot].sem); return status; } @@ -660,30 +727,25 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* bu // sanity check - if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; - - /* acquire the slot */ - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; - - /* reset the interface if there's been a tx error */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite; - if (status & STATUSREG_TXERR) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exitnowrite; - } + if (bytes_write > ca->slot_info[slot].link_buf_size) + return -EINVAL; - /* check if interface is actually waiting for us to read from it */ - if (status & STATUSREG_DA) { + /* check if interface is actually waiting for us to read from it, or if a read is in progress */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exitnowrite; + if (status & (STATUSREG_DA|STATUSREG_RE)) { status = -EAGAIN; goto exitnowrite; } /* OK, set HC bit */ - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_HC)) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, + IRQEN | CMDREG_HC)) != 0) + goto exit; /* check if interface is still free */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (!(status & STATUSREG_FR)) { /* it wasn't free => try again later */ status = -EAGAIN; @@ -691,29 +753,38 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* bu } /* send the amount of data */ - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) goto exit; - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, bytes_write & 0xff)) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) + goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, + bytes_write & 0xff)) != 0) + goto exit; /* send the buffer */ for(i=0; i < bytes_write; i++) { - if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) + goto exit; } /* check for write error (WE should now be 0) */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; if (status & STATUSREG_WE) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; status = -EIO; goto exit; } status = bytes_write; + dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, + buf[0], (buf[1] & 0x80) == 0, bytes_write); + exit: ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); exitnowrite: - up(&ca->slot_info[slot].sem); return status; } +EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); @@ -729,16 +800,15 @@ exitnowrite: */ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private* ca, int slot) { - int status; - dprintk ("%s\n", __FUNCTION__); - if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status; + down_write(&ca->slot_info[slot].sem); ca->pub->slot_shutdown(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; - if (ca->slot_info[slot].rx_buffer.data) vfree(ca->slot_info[slot].rx_buffer.data); + if (ca->slot_info[slot].rx_buffer.data) + vfree(ca->slot_info[slot].rx_buffer.data); ca->slot_info[slot].rx_buffer.data = NULL; - up(&ca->slot_info[slot].sem); + up_write(&ca->slot_info[slot].sem); /* need to wake up all processes to check if they're now trying to write to a defunct CAM */ @@ -749,6 +819,7 @@ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private* ca, int slot) /* success */ return 0; } +EXPORT_SYMBOL(dvb_ca_en50221_camready_irq); /** @@ -777,6 +848,7 @@ void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int ch atomic_inc(&ca->slot_info[slot].camchange_count); dvb_ca_en50221_thread_wakeup(ca); } +EXPORT_SYMBOL(dvb_ca_en50221_frda_irq); /** @@ -821,10 +893,8 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* pubca, int slot) break; case DVB_CA_SLOTSTATE_RUNNING: - flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS); - if (flags & STATUSREG_DA) { - dvb_ca_en50221_thread_wakeup(ca); - } + if (ca->open) + dvb_ca_en50221_read_data(ca, slot, NULL, 0); break; } } @@ -860,7 +930,8 @@ static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private* ca) ca->wakeup = 0; return 1; } - if (ca->exit) return 1; + if (ca->exit) + return 1; return 0; } @@ -910,7 +981,8 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private* ca) break; } - if (delay < curdelay) curdelay = delay; + if (delay < curdelay) + curdelay = delay; } ca->delay = curdelay; @@ -927,6 +999,7 @@ static int dvb_ca_en50221_thread(void* data) char name[15]; int slot; int flags; + int status; int pktcount; void* rxbuf; @@ -934,7 +1007,11 @@ static int dvb_ca_en50221_thread(void* data) /* setup kernel thread */ snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id); - dvb_kernel_thread_setup(name); + + lock_kernel (); + daemonize (name); + sigfillset (¤t->blocked); + unlock_kernel (); /* choose the correct initial delay */ dvb_ca_en50221_thread_update_delay(ca); @@ -943,7 +1020,9 @@ static int dvb_ca_en50221_thread(void* data) while(!ca->exit) { /* sleep for a bit */ if (!ca->wakeup) { - flags = wait_event_interruptible_timeout(ca->thread_queue, dvb_ca_en50221_thread_should_wakeup(ca), ca->delay); + flags = wait_event_interruptible_timeout(ca->thread_queue, + dvb_ca_en50221_thread_should_wakeup(ca), + ca->delay); if ((flags == -ERESTARTSYS) || ca->exit) { /* got signal or quitting */ break; @@ -957,7 +1036,8 @@ static int dvb_ca_en50221_thread(void* data) // check the cam status + deal with CAMCHANGEs while(dvb_ca_en50221_check_camstatus(ca, slot)) { /* clear down an old CI slot if necessary */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) dvb_ca_en50221_slot_shutdown(ca, slot); + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) + dvb_ca_en50221_slot_shutdown(ca, slot); /* if a CAM is NOW present, initialise it */ if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { @@ -984,7 +1064,8 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_WAITREADY: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca: PC card did not respond :(\n"); + printk("dvb_ca adaptor %d: PC card did not respond :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -993,14 +1074,25 @@ static int dvb_ca_en50221_thread(void* data) break; case DVB_CA_SLOTSTATE_VALIDATE: - if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { - printk("dvb_ca: Invalid PC card inserted :(\n"); + if (dvb_ca_en50221_parse_attributes(ca, slot) + != 0) { + printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; - dvb_ca_en50221_thread_update_delay(ca); + dvb_ca_en50221_thread_update_delay(ca); break; } if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { - printk("dvb_ca: Unable to initialise CAM :(\n"); + printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (ca->pub->write_cam_control(ca->pub, slot, + CTRLIF_COMMAND, CMDREG_RS) != 0) { + printk("dvb_ca adapter %d: Unable to reset CAM IF\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1015,7 +1107,8 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_WAITFR: if (time_after(jiffies, ca->slot_info[slot].timeout)) { - printk("dvb_ca: DVB CAM did not respond :(\n"); + printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", + ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1030,7 +1123,7 @@ static int dvb_ca_en50221_thread(void* data) case DVB_CA_SLOTSTATE_LINKINIT: if (dvb_ca_en50221_link_init(ca, slot) != 0) { - printk("dvb_ca: DVB CAM link initialisation failed :(\n"); + printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; @@ -1038,25 +1131,34 @@ static int dvb_ca_en50221_thread(void* data) rxbuf = vmalloc(RX_BUFFER_SIZE); if (rxbuf == NULL) { - printk("dvb_ca: Unable to allocate CAM rx buffer :(\n"); + printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); break; } + down_write(&ca->slot_info[slot].sem); dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE); + up_write(&ca->slot_info[slot].sem); ca->pub->slot_ts_enable(ca->pub, slot); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; dvb_ca_en50221_thread_update_delay(ca); - printk("dvb_ca: DVB CAM detected and initialised successfully\n"); + printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num); break; case DVB_CA_SLOTSTATE_RUNNING: - if (!ca->open) break; + if (!ca->open) + continue; + + // no need to poll if the CAM supports IRQs + if (ca->slot_info[slot].da_irq_supported) + break; + // poll mode pktcount = 0; - while(dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) { - if (!ca->open) break; + while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { + if (!ca->open) + break; /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ if (dvb_ca_en50221_check_camstatus(ca, slot)) { @@ -1100,7 +1202,8 @@ static int dvb_ca_en50221_thread(void* data) * * @return 0 on success, <0 on error. */ -static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) +static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *parg) { struct dvb_device* dvbdev=(struct dvb_device*) file->private_data; struct dvb_ca_private* ca = (struct dvb_ca_private*) dvbdev->priv; @@ -1115,15 +1218,16 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, un if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { dvb_ca_en50221_slot_shutdown(ca, slot); if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) - dvb_ca_en50221_camchange_irq(ca->pub, slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); + dvb_ca_en50221_camchange_irq(ca->pub, + slot, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } } ca->next_read_slot = 0; dvb_ca_en50221_thread_wakeup(ca); break; - case CA_GET_CAP: - { + case CA_GET_CAP: { struct ca_caps *caps = (struct ca_caps*) parg; caps->slot_num=ca->slot_count; @@ -1133,9 +1237,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, un break; } - - case CA_GET_SLOT_INFO: - { + case CA_GET_SLOT_INFO: { struct ca_slot_info *info=(struct ca_slot_info *)parg; if ((info->num > ca->slot_count) || (info->num < 0)) @@ -1143,8 +1245,8 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, un info->type = CA_CI_LINK; info->flags = 0; - if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) && - (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { + if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) + && (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) { info->flags = CA_CI_MODULE_PRESENT; } if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) { @@ -1172,7 +1274,8 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, un * * @return 0 on success, <0 on error. */ -static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { return dvb_usercopy(inode, file, cmd, arg, dvb_ca_en50221_io_do_ioctl); } @@ -1188,7 +1291,8 @@ static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, unsig * * @return Number of bytes read, or <0 on error. */ -static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +static ssize_t dvb_ca_en50221_io_write(struct file *file, + const char __user * buf, size_t count, loff_t * ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; @@ -1203,37 +1307,50 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf dprintk ("%s\n", __FUNCTION__); /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) return -EINVAL; + if (count < 2) + return -EINVAL; /* extract slot & connection id */ - if (copy_from_user(&slot, buf, 1)) return -EFAULT; - if (copy_from_user(&connection_id, buf+1, 1)) return -EFAULT; + if (copy_from_user(&slot, buf, 1)) + return -EFAULT; + if (copy_from_user(&connection_id, buf + 1, 1)) + return -EFAULT; buf+=2; count-=2; /* check if the slot is actually running */ - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) return -EINVAL; + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + return -EINVAL; /* fragment the packets & store in the buffer */ while(fragpos < count) { fraglen = ca->slot_info[slot].link_buf_size - 2; - if ((count - fragpos) < fraglen) fraglen = count - fragpos; + if ((count - fragpos) < fraglen) + fraglen = count - fragpos; fragbuf[0] = connection_id; fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00; - if ((status = copy_from_user(fragbuf+2, buf+fragpos, fraglen)) != 0) goto exit; + if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0) + goto exit; timeout = jiffies + HZ/2; written = 0; while(!time_after(jiffies, timeout)) { + /* check the CAM hasn't been removed/reset in the meantime */ + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) { + status = -EIO; + goto exit; + } + status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen+2); if (status == (fraglen+2)) { written = 1; break; } - if (status != -EAGAIN) goto exit; + if (status != -EAGAIN) + goto exit; - dvb_delay(1); + msleep(1); } if (!written) { status = -EIO; @@ -1264,14 +1381,21 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu slot = ca->next_read_slot; while((slot_count < ca->slot_count) && (!found)) { - if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot; + if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) + goto nextslot; - if ((*result = down_interruptible(&ca->slot_info[slot].sem)) != 0) return 1; + down_read(&ca->slot_info[slot].sem); + + if (ca->slot_info[slot].rx_buffer.data == NULL) { + up_read(&ca->slot_info[slot].sem); + return 0; + } idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); while(idx != -1) { dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); - if (connection_id == -1) connection_id = hdr[0]; + if (connection_id == -1) + connection_id = hdr[0]; if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { *_slot = slot; found = 1; @@ -1281,7 +1405,8 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); } - if (!found) up(&ca->slot_info[slot].sem); + if (!found) + up_read(&ca->slot_info[slot].sem); nextslot: slot = (slot + 1) % ca->slot_count; @@ -1303,7 +1428,8 @@ nextslot: * * @return Number of bytes read, or <0 on error. */ -static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, + size_t count, loff_t * ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; @@ -1321,19 +1447,24 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_ dprintk ("%s\n", __FUNCTION__); /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */ - if (count < 2) return -EINVAL; + if (count < 2) + return -EINVAL; /* wait for some data */ if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) { /* if we're in nonblocking mode, exit immediately */ - if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; /* wait for some data */ - status = wait_event_interruptible(ca->wait_queue, dvb_ca_en50221_io_read_condition(ca, &result, &slot)); + status = wait_event_interruptible(ca->wait_queue, + dvb_ca_en50221_io_read_condition + (ca, &result, &slot)); } if ((status < 0) || (result < 0)) { - if (result) return result; + if (result) + return result; return status; } @@ -1341,13 +1472,14 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_ pktlen = 2; do { if (idx == -1) { - printk("dvb_ca: BUG: read packet ended before last_fragment encountered\n"); + printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num); status = -EIO; goto exit; } dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); - if (connection_id == -1) connection_id = hdr[0]; + if (connection_id == -1) + connection_id = hdr[0]; if (hdr[0] == connection_id) { if (pktlen < count) { if ((pktlen + fraglen - 2) > count) { @@ -1356,29 +1488,33 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_ fraglen -= 2; } - if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, buf + pktlen, fraglen, 1)) < 0) { + if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, + buf + pktlen, fraglen, 1)) < 0) { goto exit; } pktlen += fraglen; } - if ((hdr[1] & 0x80) == 0) last_fragment = 1; + if ((hdr[1] & 0x80) == 0) + last_fragment = 1; dispose = 1; } idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen); - if (dispose) dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); + if (dispose) + dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx); idx = idx2; dispose = 0; } while (!last_fragment); hdr[0] = slot; hdr[1] = connection_id; - if ((status = copy_to_user(buf, hdr, 2)) != 0) goto exit; + if ((status = copy_to_user(buf, hdr, 2)) != 0) + goto exit; status = pktlen; exit: - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); return status; } @@ -1400,13 +1536,21 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) dprintk ("%s\n", __FUNCTION__); + if (!try_module_get(ca->pub->owner)) + return -EIO; + err=dvb_generic_open(inode, file); if (err<0) return err; for(i=0; i< ca->slot_count; i++) { + if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) { + down_write(&ca->slot_info[i].sem); + if (ca->slot_info[i].rx_buffer.data != NULL) { dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer); + } + up_write(&ca->slot_info[i].sem); } } @@ -1430,7 +1574,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv; - int err; + int err = 0; dprintk ("%s\n", __FUNCTION__); @@ -1439,8 +1583,9 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) dvb_ca_en50221_thread_update_delay(ca); err=dvb_generic_release(inode, file); - if (err<0) - return err; + + module_put(ca->pub->owner); + return 0; } @@ -1464,44 +1609,45 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait) dprintk ("%s\n", __FUNCTION__); if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); mask |= POLLIN; } /* if there is something, return now */ - if (mask) return mask; + if (mask) + return mask; /* wait for something to happen */ poll_wait(file, &ca->wait_queue, wait); if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) { - up(&ca->slot_info[slot].sem); + up_read(&ca->slot_info[slot].sem); mask |= POLLIN; } return mask; } +EXPORT_SYMBOL(dvb_ca_en50221_init); static struct file_operations dvb_ca_fops = { - owner: THIS_MODULE, - read: dvb_ca_en50221_io_read, - write: dvb_ca_en50221_io_write, - ioctl: dvb_ca_en50221_io_ioctl, - open: dvb_ca_en50221_io_open, - release: dvb_ca_en50221_io_release, - poll: dvb_ca_en50221_io_poll, + .owner = THIS_MODULE, + .read = dvb_ca_en50221_io_read, + .write = dvb_ca_en50221_io_write, + .ioctl = dvb_ca_en50221_io_ioctl, + .open = dvb_ca_en50221_io_open, + .release= dvb_ca_en50221_io_release, + .poll = dvb_ca_en50221_io_poll, }; static struct dvb_device dvbdev_ca = { - priv: NULL, - users: 1, - readers: 1, - writers: 1, - fops: &dvb_ca_fops, + .priv = NULL, + .users = 1, + .readers= 1, + .writers= 1, + .fops = &dvb_ca_fops, }; - /* ******************************************************************************** */ /* Initialisation/shutdown functions */ @@ -1516,7 +1662,8 @@ static struct dvb_device dvbdev_ca = { * * @return 0 on success, nonzero on failure */ -int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* pubca, int flags, int slot_count) +int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, + struct dvb_ca_en50221 *pubca, int flags, int slot_count) { int ret; struct dvb_ca_private* ca = NULL; @@ -1524,10 +1671,13 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* dprintk ("%s\n", __FUNCTION__); - if (slot_count < 1) return -EINVAL; + if (slot_count < 1) + return -EINVAL; /* initialise the system data */ - if ((ca = (struct dvb_ca_private*) kmalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) { + if ((ca = + (struct dvb_ca_private *) kmalloc(sizeof(struct dvb_ca_private), + GFP_KERNEL)) == NULL) { ret = -ENOMEM; goto error; } @@ -1551,7 +1701,8 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* /* register the DVB device */ ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA); - if (ret) goto error; + if (ret) + goto error; /* now initialise each slot */ for(i=0; i< slot_count; i++) { @@ -1559,7 +1710,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; atomic_set(&ca->slot_info[i].camchange_count, 0); ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; - init_MUTEX(&ca->slot_info[i].sem); + init_rwsem(&ca->slot_info[i].sem); } if (signal_pending(current)) { @@ -1579,13 +1730,16 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* error: if (ca != NULL) { - if (ca->dvbdev != NULL) dvb_unregister_device(ca->dvbdev); - if (ca->slot_info != NULL) kfree(ca->slot_info); + if (ca->dvbdev != NULL) + dvb_unregister_device(ca->dvbdev); + if (ca->slot_info != NULL) + kfree(ca->slot_info); kfree(ca); } pubca->private = NULL; return ret; } +EXPORT_SYMBOL(dvb_ca_en50221_release); @@ -1605,7 +1759,8 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221* pubca) /* shutdown the thread if there was one */ if (ca->thread_pid) { if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) { - printk("dvb_ca_release: thread PID %d already died\n", ca->thread_pid); + printk("dvb_ca_release adapter %d: thread PID %d already died\n", + ca->dvbdev->adapter->num, ca->thread_pid); } else { ca->exit = 1; mb(); @@ -1623,6 +1778,3 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221* pubca) pubca->private = NULL; } -MODULE_PARM(dvb_ca_en50221_debug,"i"); - -MODULE_PARM_DESC(dvb_ca_en50221_debug, "enable verbose debug messages"); diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h index 8458f7afd..8467e63dd 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h @@ -42,6 +42,12 @@ /* Structure describing a CA interface */ struct dvb_ca_en50221 { + /* the module owning this structure */ + struct module* owner; + + /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as + * they may be called from several threads at once */ + /* functions for accessing attribute memory on the CAM */ int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value); @@ -59,7 +65,7 @@ struct dvb_ca_en50221 { * Poll slot status. * Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set */ - int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot); + int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open); /* private data, used by caller */ void* data; diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 657d5579b..62d1efc0c 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -31,7 +31,6 @@ #include #include "dvb_demux.h" -#include "dvb_functions.h" #define NOBUFS /* @@ -425,7 +424,7 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); } } - +EXPORT_SYMBOL(dvb_dmx_swfilter_packet); void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count) { @@ -440,6 +439,7 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t cou spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_packets); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) @@ -479,6 +479,7 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter); void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) { @@ -523,6 +524,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) bailout: spin_unlock(&demux->lock); } +EXPORT_SYMBOL(dvb_dmx_swfilter_204); static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux) @@ -570,24 +572,30 @@ static int dvb_demux_feed_find(struct dvb_demux_feed *feed) static void dvb_demux_feed_add(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (dvb_demux_feed_find(feed)) { printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; + goto out; } list_add(&feed->list_head, &feed->demux->feed_list); +out: + spin_unlock_irq(&feed->demux->lock); } static void dvb_demux_feed_del(struct dvb_demux_feed *feed) { + spin_lock_irq(&feed->demux->lock); if (!(dvb_demux_feed_find(feed))) { printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n", __FUNCTION__, feed->type, feed->state, feed->pid); - return; + goto out; } list_del(&feed->list_head); +out: + spin_unlock_irq(&feed->demux->lock); } static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, @@ -789,7 +797,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_ feed->pid = 0xffff; - if (feed->ts_type & TS_DECODER) + if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER) demux->pesfilter[feed->pes_type] = NULL; up(&demux->mutex); @@ -1158,6 +1166,7 @@ int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *fronte up(&dvbdemux->mutex); return 0; } +EXPORT_SYMBOL(dvbdmx_connect_frontend); int dvbdmx_disconnect_frontend(struct dmx_demux *demux) @@ -1171,6 +1180,7 @@ int dvbdmx_disconnect_frontend(struct dmx_demux *demux) up(&dvbdemux->mutex); return 0; } +EXPORT_SYMBOL(dvbdmx_disconnect_frontend); static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids) @@ -1251,6 +1261,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) return 0; } +EXPORT_SYMBOL(dvb_dmx_init); int dvb_dmx_release(struct dvb_demux *dvbdemux) @@ -1264,3 +1275,5 @@ int dvb_dmx_release(struct dvb_demux *dvbdemux) vfree(dvbdemux->feed); return 0; } +EXPORT_SYMBOL(dvb_dmx_release); + diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c index 829c43820..5ce4f6569 100644 --- a/drivers/media/dvb/dvb-core/dvb_filter.c +++ b/drivers/media/dvb/dvb-core/dvb_filter.c @@ -3,19 +3,20 @@ #include #include "dvb_filter.h" -unsigned int bitrates[3][16] = +#if 0 +static unsigned int bitrates[3][16] = {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; +#endif -u32 freq[4] = {441, 480, 320, 0}; +static u32 freq[4] = {480, 441, 320, 0}; -unsigned int ac3_bitrates[32] = +static unsigned int ac3_bitrates[32] = {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, 0,0,0,0,0,0,0,0,0,0,0,0,0}; -u32 ac3_freq[4] = {480, 441, 320, 0}; -u32 ac3_frames[3][32] = +static u32 ac3_frames[3][32] = {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, @@ -389,6 +390,7 @@ int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int p return 0; } +EXPORT_SYMBOL(dvb_filter_get_ac3info); #if 0 @@ -563,6 +565,7 @@ void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, p2ts->cb=cb; p2ts->priv=priv; } +EXPORT_SYMBOL(dvb_filter_pes2ts_init); int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len, int payload_start) @@ -597,4 +600,5 @@ int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, memcpy(buf+5+rest, pes, len); return p2ts->cb(p2ts->priv, buf); } +EXPORT_SYMBOL(dvb_filter_pes2ts); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 94d6cfabf..151160815 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1,5 +1,6 @@ /* - * dvb-core.c: DVB core driver + * dvb_frontend.c: DVB frontend tuning interface/thread + * * * Copyright (C) 1999-2001 Ralph Metzler * Marcus Metzler @@ -31,13 +32,33 @@ #include #include #include +#include #include +#include #include #include #include "dvb_frontend.h" #include "dvbdev.h" -#include "dvb_functions.h" + +static int dvb_frontend_debug; +static int dvb_shutdown_timeout = 5; +static int dvb_force_auto_inversion; +static int dvb_override_tune_delay; +static int dvb_powerdown_on_sleep = 1; + +module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); +MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging (default:off)."); +module_param(dvb_shutdown_timeout, int, 0444); +MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); +module_param(dvb_force_auto_inversion, int, 0444); +MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); +module_param(dvb_override_tune_delay, int, 0444); +MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); +module_param(dvb_powerdown_on_sleep, int, 0444); +MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)"); + +#define dprintk if (dvb_frontend_debug) printk #define FESTATE_IDLE 1 #define FESTATE_RETUNE 2 @@ -66,189 +87,9 @@ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ - -static int dvb_frontend_debug = 0; -static int dvb_shutdown_timeout = 5; -static int dvb_override_frequency_bending = 0; -static int dvb_force_auto_inversion = 0; -static int dvb_override_tune_delay = 0; - -static int do_frequency_bending = 0; - -#define dprintk if (dvb_frontend_debug) printk - -#define MAX_EVENT 8 - -struct dvb_fe_events { - struct dvb_frontend_event events[MAX_EVENT]; - int eventw; - int eventr; - int overflow; - wait_queue_head_t wait_queue; - struct semaphore sem; -}; - - -struct dvb_frontend_data { - struct dvb_frontend_info *info; - struct dvb_frontend frontend; - struct dvb_device *dvbdev; - struct dvb_frontend_parameters parameters; - struct dvb_fe_events events; - struct semaphore sem; - struct list_head list_head; - wait_queue_head_t wait_queue; - pid_t thread_pid; - unsigned long release_jiffies; - int state; - int bending; - int lnb_drift; - int inversion; - int auto_step; - int auto_sub_step; - int started_auto_step; - int min_delay; - int max_drift; - int step_size; - int exit; - int wakeup; - fe_status_t status; -}; - - -struct dvb_frontend_ioctl_data { - struct list_head list_head; - struct dvb_adapter *adapter; - int (*before_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg); - int (*after_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg); - void *before_after_data; -}; - - -struct dvb_frontend_notifier_data { - struct list_head list_head; - struct dvb_adapter *adapter; - void (*callback) (fe_status_t s, void *data); - void *data; -}; - - -static LIST_HEAD(frontend_list); -static LIST_HEAD(frontend_ioctl_list); -static LIST_HEAD(frontend_notifier_list); - static DECLARE_MUTEX(frontend_mutex); - -static int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend, - unsigned int cmd, void *arg) -{ - int err = -EOPNOTSUPP; - - dprintk ("%s\n", __FUNCTION__); - - if (frontend->before_ioctl) - err = frontend->before_ioctl (frontend, cmd, arg); - - if (err == -EOPNOTSUPP) { - err = frontend->ioctl (frontend, cmd, arg); - - if ((err == -EOPNOTSUPP) && frontend->after_ioctl) - err = frontend->after_ioctl (frontend, cmd, arg); - } - - return err; -} - - -/** - * if 2 tuners are located side by side you can get interferences when - * they try to tune to the same frequency, so both lose sync. - * We will slightly mistune in this case. The AFC of the demodulator - * should make it still possible to receive the requested transponder - * on both tuners... - */ -static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive) -{ - struct list_head *entry; - int stepsize = this_fe->info->frequency_stepsize; - int this_fe_adap_num = this_fe->frontend.i2c->adapter->num; - int frequency; - - if (!stepsize || recursive > 10) { - printk ("%s: too deep recursion, check frequency_stepsize " - "in your frontend code!\n", __FUNCTION__); - return; - } - - dprintk ("%s\n", __FUNCTION__); - - if (!recursive) { - if (down_interruptible (&frontend_mutex)) - return; - - this_fe->bending = 0; - } - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - int f; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.i2c->adapter->num != this_fe_adap_num) - continue; - - f = fe->parameters.frequency; - f += fe->lnb_drift; - f += fe->bending; - - frequency = this_fe->parameters.frequency; - frequency += this_fe->lnb_drift; - frequency += this_fe->bending; - - if (this_fe != fe && (fe->state != FESTATE_IDLE) && - frequency > f - stepsize && frequency < f + stepsize) - { - if (recursive % 2) - this_fe->bending += stepsize; - else - this_fe->bending = -this_fe->bending; - - dvb_bend_frequency (this_fe, recursive + 1); - goto done; - } - } -done: - if (!recursive) - up (&frontend_mutex); -} - - -static void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe, - fe_status_t s) -{ - dprintk ("%s\n", __FUNCTION__); - - if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK)) - dvb_delay (fe->info->notifier_delay); - - fe->status = s; - - if (!(s & FE_HAS_LOCK) && (fe->info->caps & FE_CAN_MUTE_TS)) - return; - - /** - * now tell the Demux about the TS status changes... - */ - if (fe->frontend.notifier_callback) - fe->frontend.notifier_callback(fe->status, fe->frontend.notifier_data); -} - - -static void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t status) +static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) { struct dvb_fe_events *events = &fe->events; struct dvb_frontend_event *e; @@ -272,21 +113,19 @@ static void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t st sizeof (struct dvb_frontend_parameters)); if (status & FE_HAS_LOCK) - dvb_frontend_internal_ioctl (&fe->frontend, - FE_GET_FRONTEND, - &e->parameters); + if (fe->ops->get_frontend) + fe->ops->get_frontend(fe, &e->parameters); + events->eventw = wp; up (&events->sem); e->status = status; - dvb_call_frontend_notifiers (fe, status); wake_up_interruptible (&events->wait_queue); } - -static int dvb_frontend_get_event (struct dvb_frontend_data *fe, +static int dvb_frontend_get_event(struct dvb_frontend *fe, struct dvb_frontend_event *event, int flags) { struct dvb_fe_events *events = &fe->events; @@ -329,15 +168,14 @@ static int dvb_frontend_get_event (struct dvb_frontend_data *fe, return 0; } -static void dvb_frontend_init (struct dvb_frontend_data *fe) +static void dvb_frontend_init(struct dvb_frontend *fe) { - struct dvb_frontend *frontend = &fe->frontend; + dprintk ("DVB: initialising frontend %i (%s)...\n", + fe->dvb->num, + fe->ops->info.name); - dprintk ("DVB: initialising frontend %i:%i (%s)...\n", - frontend->i2c->adapter->num, frontend->i2c->id, - fe->info->name); - - dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL); + if (fe->ops->init) + fe->ops->init(fe); } static void update_delay (int *quality, int *delay, int min_delay, int locked) @@ -364,32 +202,33 @@ static void update_delay (int *quality, int *delay, int min_delay, int locked) * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT * @returns Number of complete iterations that have been performed. */ -static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped) +static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) { int autoinversion; int ready = 0; int original_inversion = fe->parameters.inversion; u32 original_frequency = fe->parameters.frequency; - // are we using autoinversion? - autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)); + /* are we using autoinversion? */ + autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && + (fe->parameters.inversion == INVERSION_AUTO)); - // setup parameters correctly + /* setup parameters correctly */ while(!ready) { - // calculate the lnb_drift + /* calculate the lnb_drift */ fe->lnb_drift = fe->auto_step * fe->step_size; - // wrap the auto_step if we've exceeded the maximum drift + /* wrap the auto_step if we've exceeded the maximum drift */ if (fe->lnb_drift > fe->max_drift) { fe->auto_step = 0; fe->auto_sub_step = 0; fe->lnb_drift = 0; } - // perform inversion and +/- zigzag + /* perform inversion and +/- zigzag */ switch(fe->auto_sub_step) { case 0: - // try with the current inversion and current drift setting + /* try with the current inversion and current drift setting */ ready = 1; break; @@ -418,42 +257,40 @@ static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped default: fe->auto_step++; - fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment + fe->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */ break; } if (!ready) fe->auto_sub_step++; } - // if this attempt would hit where we started, indicate a complete iteration has occurred - if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) { + /* if this attempt would hit where we started, indicate a complete + * iteration has occurred */ + if ((fe->auto_step == fe->started_auto_step) && + (fe->auto_sub_step == 0) && check_wrapped) { return 1; } - // perform frequency bending if necessary - if ((dvb_override_frequency_bending != 1) && do_frequency_bending) - dvb_bend_frequency(fe, 0); - - // instrumentation - dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n", - __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, fe->auto_step, fe->auto_sub_step, - fe->started_auto_step); + dprintk("%s: drift:%i inversion:%i auto_step:%i " + "auto_sub_step:%i started_auto_step:%i\n", + __FUNCTION__, fe->lnb_drift, fe->inversion, + fe->auto_step, fe->auto_sub_step, fe->started_auto_step); - // set the frontend itself - fe->parameters.frequency += fe->lnb_drift + fe->bending; - if (autoinversion) fe->parameters.inversion = fe->inversion; - dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters); + /* set the frontend itself */ + fe->parameters.frequency += fe->lnb_drift; + if (autoinversion) + fe->parameters.inversion = fe->inversion; + if (fe->ops->set_frontend) + fe->ops->set_frontend(fe, &fe->parameters); + fe->parameters.frequency = original_frequency; fe->parameters.inversion = original_inversion; - // normal return fe->auto_sub_step++; return 0; } - - -static int dvb_frontend_is_exiting (struct dvb_frontend_data *fe) +static int dvb_frontend_is_exiting(struct dvb_frontend *fe) { if (fe->exit) return 1; @@ -465,7 +302,7 @@ static int dvb_frontend_is_exiting (struct dvb_frontend_data *fe) return 0; } -static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe) +static int dvb_frontend_should_wakeup(struct dvb_frontend *fe) { if (fe->wakeup) { fe->wakeup = 0; @@ -474,14 +311,18 @@ static int dvb_frontend_should_wakeup (struct dvb_frontend_data *fe) return dvb_frontend_is_exiting(fe); } -static void dvb_frontend_wakeup (struct dvb_frontend_data *fe) { +static void dvb_frontend_wakeup(struct dvb_frontend *fe) +{ fe->wakeup = 1; wake_up_interruptible(&fe->wait_queue); } +/* + * FIXME: use linux/kthread.h + */ static int dvb_frontend_thread (void *data) { - struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data; + struct dvb_frontend *fe = (struct dvb_frontend *) data; unsigned long timeout; char name [15]; int quality = 0, delay = 3*HZ; @@ -490,86 +331,101 @@ static int dvb_frontend_thread (void *data) dprintk ("%s\n", __FUNCTION__); - snprintf (name, sizeof(name), "kdvb-fe-%i:%i", - fe->frontend.i2c->adapter->num, fe->frontend.i2c->id); + snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num); - dvb_kernel_thread_setup (name); + lock_kernel (); + daemonize (name); + sigfillset (¤t->blocked); + unlock_kernel (); - dvb_call_frontend_notifiers (fe, 0); + fe->status = 0; dvb_frontend_init (fe); fe->wakeup = 0; while (1) { up (&fe->sem); /* is locked when we enter the thread... */ - timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay); - if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) { + timeout = wait_event_interruptible_timeout(fe->wait_queue, + dvb_frontend_should_wakeup(fe), + delay); + if (0 != dvb_frontend_is_exiting (fe)) { /* got signal or quitting */ break; } + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); + if (down_interruptible (&fe->sem)) break; - // if we've got no parameters, just keep idling + /* if we've got no parameters, just keep idling */ if (fe->state & FESTATE_IDLE) { delay = 3*HZ; quality = 0; continue; } - // get the frontend status - dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s); - if (s != fe->status) +retune: + /* get the frontend status */ + if (fe->state & FESTATE_RETUNE) { + s = 0; + } else { + if (fe->ops->read_status) + fe->ops->read_status(fe, &s); + if (s != fe->status) { dvb_frontend_add_event (fe, s); - - // if we're not tuned, and we have a lock, move to the TUNED state + fe->status = s; + } + } + /* if we're not tuned, and we have a lock, move to the TUNED state */ if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); fe->state = FESTATE_TUNED; - // if we're tuned, then we have determined the correct inversion - if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) { + /* if we're tuned, then we have determined the correct inversion */ + if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && + (fe->parameters.inversion == INVERSION_AUTO)) { fe->parameters.inversion = fe->inversion; } continue; } - // if we are tuned already, check we're still locked + /* if we are tuned already, check we're still locked */ if (fe->state & FESTATE_TUNED) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); - // we're tuned, and the lock is still good... - if (s & FE_HAS_LOCK) { + /* we're tuned, and the lock is still good... */ + if (s & FE_HAS_LOCK) continue; - } else { - // if we _WERE_ tuned, but now don't have a lock, need to zigzag + else { + /* if we _WERE_ tuned, but now don't have a lock, + * need to zigzag */ fe->state = FESTATE_ZIGZAG_FAST; fe->started_auto_step = fe->auto_step; check_wrapped = 0; - // fallthrough } } - // don't actually do anything if we're in the LOSTLOCK state, the frontend is set to - // FE_CAN_RECOVER, and the max_drift is 0 + /* don't actually do anything if we're in the LOSTLOCK state, + * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ if ((fe->state & FESTATE_LOSTLOCK) && - (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) { + (fe->ops->info.caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); continue; } - // don't do anything if we're in the DISEQC state, since this might be someone - // with a motorized dish controlled by DISEQC. If its actually a re-tune, there will - // be a SET_FRONTEND soon enough. + /* don't do anything if we're in the DISEQC state, since this + * might be someone with a motorized dish controlled by DISEQC. + * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ if (fe->state & FESTATE_DISEQC) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); continue; } - // if we're in the RETUNE state, set everything up for a brand new scan, - // keeping the current inversion setting, as the next tune is _very_ likely - // to require the same + /* if we're in the RETUNE state, set everything up for a brand + * new scan, keeping the current inversion setting, as the next + * tune is _very_ likely to require the same */ if (fe->state & FESTATE_RETUNE) { fe->lnb_drift = 0; fe->auto_step = 0; @@ -578,43 +434,47 @@ static int dvb_frontend_thread (void *data) check_wrapped = 0; } - // fast zigzag. + /* fast zigzag. */ if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) { delay = fe->min_delay; - // peform a tune + /* peform a tune */ if (dvb_frontend_autotune(fe, check_wrapped)) { - // OK, if we've run out of trials at the fast speed. Drop back to - // slow for the _next_ attempt + /* OK, if we've run out of trials at the fast speed. + * Drop back to slow for the _next_ attempt */ fe->state = FESTATE_SEARCHING_SLOW; fe->started_auto_step = fe->auto_step; continue; } check_wrapped = 1; - // if we've just retuned, enter the ZIGZAG_FAST state. This ensures - // we cannot return from an FE_SET_FRONTEND ioctl before the first frontend - // tune occurs + /* if we've just retuned, enter the ZIGZAG_FAST state. + * This ensures we cannot return from an + * FE_SET_FRONTEND ioctl before the first frontend tune + * occurs */ if (fe->state & FESTATE_RETUNE) { fe->state = FESTATE_TUNING_FAST; - wake_up_interruptible(&fe->wait_queue); + goto retune; } } - // slow zigzag + /* slow zigzag */ if (fe->state & FESTATE_SEARCHING_SLOW) { update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK); - // Note: don't bother checking for wrapping; we stay in this state - // until we get a lock + /* Note: don't bother checking for wrapping; we stay in this + * state until we get a lock */ dvb_frontend_autotune(fe, 0); } - }; - - if (dvb_shutdown_timeout) - dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); + } - up (&fe->sem); + if (dvb_shutdown_timeout) { + if (dvb_powerdown_on_sleep) + if (fe->ops->set_voltage) + fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF); + if (fe->ops->sleep) + fe->ops->sleep(fe); + } fe->thread_pid = 0; mb(); @@ -623,8 +483,7 @@ static int dvb_frontend_thread (void *data) return 0; } - -static void dvb_frontend_stop (struct dvb_frontend_data *fe) +static void dvb_frontend_stop(struct dvb_frontend *fe) { unsigned long ret; @@ -662,8 +521,7 @@ static void dvb_frontend_stop (struct dvb_frontend_data *fe) fe->thread_pid); } - -static int dvb_frontend_start (struct dvb_frontend_data *fe) +static int dvb_frontend_start(struct dvb_frontend *fe) { int ret; @@ -702,30 +560,120 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; - struct dvb_frontend_tune_settings fetunesettings; - int err = 0; + struct dvb_frontend *fe = dvbdev->priv; + int err = -EOPNOTSUPP; dprintk ("%s\n", __FUNCTION__); - if (!fe || !fe->frontend.ioctl || fe->exit) + if (!fe || fe->exit) return -ENODEV; + if ((file->f_flags & O_ACCMODE) == O_RDONLY && + (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT || + cmd == FE_DISEQC_RECV_SLAVE_REPLY)) + return -EPERM; + if (down_interruptible (&fe->sem)) return -ERESTARTSYS; switch (cmd) { + case FE_GET_INFO: { + struct dvb_frontend_info* info = (struct dvb_frontend_info*) parg; + memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info)); + + /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't + * do it, it is done for it. */ + info->caps |= FE_CAN_INVERSION_AUTO; + err = 0; + break; + } + + case FE_READ_STATUS: + if (fe->ops->read_status) + err = fe->ops->read_status(fe, (fe_status_t*) parg); + break; + + case FE_READ_BER: + if (fe->ops->read_ber) + err = fe->ops->read_ber(fe, (__u32*) parg); + break; + + case FE_READ_SIGNAL_STRENGTH: + if (fe->ops->read_signal_strength) + err = fe->ops->read_signal_strength(fe, (__u16*) parg); + break; + + case FE_READ_SNR: + if (fe->ops->read_snr) + err = fe->ops->read_snr(fe, (__u16*) parg); + break; + + case FE_READ_UNCORRECTED_BLOCKS: + if (fe->ops->read_ucblocks) + err = fe->ops->read_ucblocks(fe, (__u32*) parg); + break; + + + case FE_DISEQC_RESET_OVERLOAD: + if (fe->ops->diseqc_reset_overload) { + err = fe->ops->diseqc_reset_overload(fe); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_DISEQC_SEND_MASTER_CMD: + if (fe->ops->diseqc_send_master_cmd) { + err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_DISEQC_SEND_BURST: + if (fe->ops->diseqc_send_burst) { + err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + case FE_SET_TONE: - if (fe->status) - dvb_call_frontend_notifiers (fe, 0); - dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg); + if (fe->ops->set_tone) { + err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + + case FE_SET_VOLTAGE: + if (fe->ops->set_voltage) { + err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); fe->state = FESTATE_DISEQC; + fe->status = 0; + } break; - case FE_SET_FRONTEND: - fe->state = FESTATE_RETUNE; + case FE_DISHNETWORK_SEND_LEGACY_CMD: + if (fe->ops->dishnetwork_send_legacy_command) { + err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg); + fe->state = FESTATE_DISEQC; + fe->status = 0; + } + break; + + case FE_DISEQC_RECV_SLAVE_REPLY: + if (fe->ops->diseqc_recv_slave_reply) + err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); + break; + + case FE_ENABLE_HIGH_LNB_VOLTAGE: + if (fe->ops->enable_high_lnb_voltage); + err = fe->ops->enable_high_lnb_voltage(fe, (int) parg); + break; + + case FE_SET_FRONTEND: { + struct dvb_frontend_tune_settings fetunesettings; memcpy (&fe->parameters, parg, sizeof (struct dvb_frontend_parameters)); @@ -734,75 +682,73 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, memcpy(&fetunesettings.parameters, parg, sizeof (struct dvb_frontend_parameters)); - // force auto frequency inversion if requested + /* force auto frequency inversion if requested */ if (dvb_force_auto_inversion) { fe->parameters.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } + if (fe->ops->info.type == FE_OFDM) { + /* without hierachical coding code_rate_LP is irrelevant, + * so we tolerate the otherwise invalid FEC_NONE setting */ + if (fe->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && + fe->parameters.u.ofdm.code_rate_LP == FEC_NONE) + fe->parameters.u.ofdm.code_rate_LP = FEC_AUTO; + } - // get frontend-specific tuning settings - if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) { + /* get frontend-specific tuning settings */ + if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) { fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; fe->max_drift = fetunesettings.max_drift; fe->step_size = fetunesettings.step_size; } else { - // default values - switch(fe->info->type) { + /* default values */ + switch(fe->ops->info.type) { case FE_QPSK: - fe->min_delay = HZ/20; // default mindelay of 50ms + fe->min_delay = HZ/20; fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000; fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000; break; case FE_QAM: - fe->min_delay = HZ/20; // default mindelay of 50ms - fe->step_size = 0; - fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends + fe->min_delay = HZ/20; + fe->step_size = 0; /* no zigzag */ + fe->max_drift = 0; break; case FE_OFDM: - fe->min_delay = HZ/20; // default mindelay of 50ms - fe->step_size = fe->info->frequency_stepsize * 2; - fe->max_drift = (fe->info->frequency_stepsize * 2) + 1; + fe->min_delay = HZ/20; + fe->step_size = fe->ops->info.frequency_stepsize * 2; + fe->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1; + break; + case FE_ATSC: + printk("dvb-core: FE_ATSC not handled yet.\n"); break; } } - if (dvb_override_tune_delay > 0) { + if (dvb_override_tune_delay > 0) fe->min_delay = (dvb_override_tune_delay * HZ) / 1000; - } + fe->state = FESTATE_RETUNE; + dvb_frontend_wakeup(fe); dvb_frontend_add_event (fe, 0); + fe->status = 0; + err = 0; break; + } case FE_GET_EVENT: err = dvb_frontend_get_event (fe, parg, file->f_flags); break; + case FE_GET_FRONTEND: - memcpy (parg, &fe->parameters, - sizeof (struct dvb_frontend_parameters)); - /* fall-through... */ - default: - err = dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg); + if (fe->ops->get_frontend) { + memcpy (parg, &fe->parameters, sizeof (struct dvb_frontend_parameters)); + err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); + } + break; }; up (&fe->sem); - if (err < 0) - return err; - - // Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't do it, it is done for it. - if ((cmd == FE_GET_INFO) && (err == 0)) { - struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg; - tmp->caps |= FE_CAN_INVERSION_AUTO; - } - - // if the frontend has just been set, wait until the first tune has finished. - // This ensures the app doesn't start reading data too quickly, perhaps from the - // previous lock, which is REALLY CONFUSING TO DEBUG! - if ((cmd == FE_SET_FRONTEND) && (err == 0)) { - dvb_frontend_wakeup(fe); - err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE); - } - return err; } @@ -810,7 +756,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file, static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; + struct dvb_frontend *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); @@ -826,7 +772,7 @@ static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_stru static int dvb_frontend_open (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; + struct dvb_frontend *fe = dvbdev->priv; int ret; dprintk ("%s\n", __FUNCTION__); @@ -850,7 +796,7 @@ static int dvb_frontend_open (struct inode *inode, struct file *file) static int dvb_frontend_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; - struct dvb_frontend_data *fe = dvbdev->priv; + struct dvb_frontend *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); @@ -861,193 +807,6 @@ static int dvb_frontend_release (struct inode *inode, struct file *file) } - -int -dvb_add_frontend_ioctls (struct dvb_adapter *adapter, - int (*before_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - int (*after_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - void *before_after_data) -{ - struct dvb_frontend_ioctl_data *ioctl; - struct list_head *entry; - - dprintk ("%s\n", __FUNCTION__); - - if (down_interruptible (&frontend_mutex)) - return -ERESTARTSYS; - - ioctl = kmalloc (sizeof(struct dvb_frontend_ioctl_data), GFP_KERNEL); - - if (!ioctl) { - up (&frontend_mutex); - return -ENOMEM; - } - - ioctl->adapter = adapter; - ioctl->before_ioctl = before_ioctl; - ioctl->after_ioctl = after_ioctl; - ioctl->before_after_data = before_after_data; - - list_add_tail (&ioctl->list_head, &frontend_ioctl_list); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.i2c->adapter == adapter && - fe->frontend.before_ioctl == NULL && - fe->frontend.after_ioctl == NULL) - { - fe->frontend.before_ioctl = before_ioctl; - fe->frontend.after_ioctl = after_ioctl; - fe->frontend.before_after_data = before_after_data; - } - } - - up (&frontend_mutex); - - return 0; -} - - -void -dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, - int (*before_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - int (*after_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg)) -{ - struct list_head *entry, *n; - - dprintk ("%s\n", __FUNCTION__); - - down (&frontend_mutex); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.i2c->adapter == adapter && - fe->frontend.before_ioctl == before_ioctl && - fe->frontend.after_ioctl == after_ioctl) - { - fe->frontend.before_ioctl = NULL; - fe->frontend.after_ioctl = NULL; - - } - } - - list_for_each_safe (entry, n, &frontend_ioctl_list) { - struct dvb_frontend_ioctl_data *ioctl; - - ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head); - - if (ioctl->adapter == adapter && - ioctl->before_ioctl == before_ioctl && - ioctl->after_ioctl == after_ioctl) - { - list_del (&ioctl->list_head); - kfree (ioctl); - - break; - } - } - - up (&frontend_mutex); -} - - -int -dvb_add_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data), - void *data) -{ - struct dvb_frontend_notifier_data *notifier; - struct list_head *entry; - - dprintk ("%s\n", __FUNCTION__); - - if (down_interruptible (&frontend_mutex)) - return -ERESTARTSYS; - - notifier = kmalloc (sizeof(struct dvb_frontend_notifier_data), GFP_KERNEL); - - if (!notifier) { - up (&frontend_mutex); - return -ENOMEM; - } - - notifier->adapter = adapter; - notifier->callback = callback; - notifier->data = data; - - list_add_tail (¬ifier->list_head, &frontend_notifier_list); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.i2c->adapter == adapter && - fe->frontend.notifier_callback == NULL) - { - fe->frontend.notifier_callback = callback; - fe->frontend.notifier_data = data; - } - } - - up (&frontend_mutex); - - return 0; -} - - -void -dvb_remove_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data)) -{ - struct list_head *entry, *n; - - dprintk ("%s\n", __FUNCTION__); - - down (&frontend_mutex); - - list_for_each (entry, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.i2c->adapter == adapter && - fe->frontend.notifier_callback == callback) - { - fe->frontend.notifier_callback = NULL; - - } - } - - list_for_each_safe (entry, n, &frontend_notifier_list) { - struct dvb_frontend_notifier_data *notifier; - - notifier = list_entry (entry, struct dvb_frontend_notifier_data, list_head); - - if (notifier->adapter == adapter && - notifier->callback == callback) - { - list_del (¬ifier->list_head); - kfree (notifier); - - break; - } - } - - up (&frontend_mutex); -} - - static struct file_operations dvb_frontend_fops = { .owner = THIS_MODULE, .ioctl = dvb_generic_ioctl, @@ -1056,17 +815,9 @@ static struct file_operations dvb_frontend_fops = { .release = dvb_frontend_release }; - - -int -dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c, - void *data, - struct dvb_frontend_info *info) +int dvb_register_frontend(struct dvb_adapter* dvb, + struct dvb_frontend* fe) { - struct list_head *entry; - struct dvb_frontend_data *fe; static const struct dvb_device dvbdev_template = { .users = ~0, .writers = 1, @@ -1080,110 +831,39 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, if (down_interruptible (&frontend_mutex)) return -ERESTARTSYS; - if (!(fe = kmalloc (sizeof (struct dvb_frontend_data), GFP_KERNEL))) { - up (&frontend_mutex); - return -ENOMEM; - } - - memset (fe, 0, sizeof (struct dvb_frontend_data)); - init_MUTEX (&fe->sem); init_waitqueue_head (&fe->wait_queue); init_waitqueue_head (&fe->events.wait_queue); init_MUTEX (&fe->events.sem); fe->events.eventw = fe->events.eventr = 0; fe->events.overflow = 0; - - fe->frontend.ioctl = ioctl; - fe->frontend.i2c = i2c; - fe->frontend.data = data; - fe->info = info; + fe->dvb = dvb; fe->inversion = INVERSION_OFF; - list_for_each (entry, &frontend_ioctl_list) { - struct dvb_frontend_ioctl_data *ioctl; - - ioctl = list_entry (entry, - struct dvb_frontend_ioctl_data, - list_head); - - if (ioctl->adapter == i2c->adapter) { - fe->frontend.before_ioctl = ioctl->before_ioctl; - fe->frontend.after_ioctl = ioctl->after_ioctl; - fe->frontend.before_after_data = ioctl->before_after_data; - break; - } - } - - list_for_each (entry, &frontend_notifier_list) { - struct dvb_frontend_notifier_data *notifier; - - notifier = list_entry (entry, - struct dvb_frontend_notifier_data, - list_head); + printk ("DVB: registering frontend %i (%s)...\n", + fe->dvb->num, + fe->ops->info.name); - if (notifier->adapter == i2c->adapter) { - fe->frontend.notifier_callback = notifier->callback; - fe->frontend.notifier_data = notifier->data; - break; - } - } - - list_add_tail (&fe->list_head, &frontend_list); - - printk ("DVB: registering frontend %i:%i (%s)...\n", - fe->frontend.i2c->adapter->num, fe->frontend.i2c->id, - fe->info->name); - - dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template, + dvb_register_device (fe->dvb, &fe->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); - if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2)) - do_frequency_bending = 1; - up (&frontend_mutex); - return 0; } +EXPORT_SYMBOL(dvb_register_frontend); - -int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c) +int dvb_unregister_frontend(struct dvb_frontend* fe) { - struct list_head *entry, *n; - dprintk ("%s\n", __FUNCTION__); down (&frontend_mutex); - - list_for_each_safe (entry, n, &frontend_list) { - struct dvb_frontend_data *fe; - - fe = list_entry (entry, struct dvb_frontend_data, list_head); - - if (fe->frontend.ioctl == ioctl && fe->frontend.i2c == i2c) { dvb_unregister_device (fe->dvbdev); - list_del (entry); - up (&frontend_mutex); dvb_frontend_stop (fe); - kfree (fe); - return 0; - } - } - + if (fe->ops->release) + fe->ops->release(fe); + else + printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); up (&frontend_mutex); - return -EINVAL; + return 0; } - -MODULE_PARM(dvb_frontend_debug,"i"); -MODULE_PARM(dvb_shutdown_timeout,"i"); -MODULE_PARM(dvb_override_frequency_bending,"i"); -MODULE_PARM(dvb_force_auto_inversion,"i"); -MODULE_PARM(dvb_override_tune_delay,"i"); - -MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages"); -MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); -MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending"); -MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); -MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); +EXPORT_SYMBOL(dvb_unregister_frontend); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 8d8e21fa8..038abac17 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -1,9 +1,12 @@ /* * dvb_frontend.h * - * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH - * overhauled by Holger Waechtler for Convergence GmbH + * Copyright (C) 2001 convergence integrated media GmbH + * Copyright (C) 2004 convergence GmbH * + * Written by Ralph Metzler + * Overhauled by Holger Waechtler + * Kernel I2C stuff by Michael Hunold * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -31,31 +34,34 @@ #include #include #include +#include #include -#include "dvb_i2c.h" #include "dvbdev.h" +/* FIXME: Move to i2c-id.h */ +#define I2C_DRIVERID_DVBFE_SP8870 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_CX22700 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_CX24110 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_CX22702 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_DIB3000MB I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_DST I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_DUMMY I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_L64781 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_MT312 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_MT352 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_NXT6000 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_SP887X I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_STV0299 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA1004X I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA8083 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_VES1820 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_VES1X93 I2C_DRIVERID_EXP2 +#define I2C_DRIVERID_DVBFE_TDA80XX I2C_DRIVERID_EXP2 - -/** - * when before_ioctl is registered and returns value 0, ioctl and after_ioctl - * are not executed. - */ - -struct dvb_frontend { - int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); - void (*notifier_callback) (fe_status_t s, void *data); - struct dvb_i2c_bus *i2c; - void *before_after_data; /* can be used by hardware module... */ - void *notifier_data; /* can be used by hardware module... */ - void *data; /* can be used by hardware module... */ -}; - struct dvb_frontend_tune_settings { int min_delay_ms; int step_size; @@ -63,65 +69,79 @@ struct dvb_frontend_tune_settings { struct dvb_frontend_parameters parameters; }; +struct dvb_frontend; -/** - * private frontend command ioctl's. - * keep them in sync with the public ones defined in linux/dvb/frontend.h - * - * FE_SLEEP. Ioctl used to put frontend into a low power mode. - * FE_INIT. Ioctl used to initialise the frontend. - * FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters. - */ -#define FE_SLEEP _IO('v', 80) -#define FE_INIT _IO('v', 81) -#define FE_GET_TUNE_SETTINGS _IOWR('v', 83, struct dvb_frontend_tune_settings) - - -extern int -dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c, - void *data, - struct dvb_frontend_info *info); - -extern int -dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - struct dvb_i2c_bus *i2c); - - -/** - * Add special ioctl code performed before and after the main ioctl - * to all frontend devices on the specified DVB adapter. - * This is necessairy because the 22kHz/13V-18V/DiSEqC stuff depends - * heavily on the hardware around the frontend, the same tuner can create - * these signals on about a million different ways... - * - * Return value: number of frontends where the ioctl's were applied. - */ -extern int -dvb_add_frontend_ioctls (struct dvb_adapter *adapter, - int (*before_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - int (*after_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - void *before_after_data); - - -extern void -dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, - int (*before_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg), - int (*after_ioctl) (struct dvb_frontend *frontend, - unsigned int cmd, void *arg)); - -extern int -dvb_add_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data), - void *data); -extern void -dvb_remove_frontend_notifier (struct dvb_adapter *adapter, - void (*callback) (fe_status_t s, void *data)); +struct dvb_frontend_ops { -#endif + struct dvb_frontend_info info; + + void (*release)(struct dvb_frontend* fe); + + int (*init)(struct dvb_frontend* fe); + int (*sleep)(struct dvb_frontend* fe); + + int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); + int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); + int (*read_ber)(struct dvb_frontend* fe, u32* ber); + int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); + int (*read_snr)(struct dvb_frontend* fe, u16* snr); + int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks); + + int (*diseqc_reset_overload)(struct dvb_frontend* fe); + int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); + int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply); + int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); + int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); + int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); + int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg); + int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); +}; + +#define MAX_EVENT 8 + +struct dvb_fe_events { + struct dvb_frontend_event events[MAX_EVENT]; + int eventw; + int eventr; + int overflow; + wait_queue_head_t wait_queue; + struct semaphore sem; +}; + +struct dvb_frontend { + struct dvb_frontend_ops* ops; + struct dvb_adapter *dvb; + void* demodulator_priv; + + struct dvb_device *dvbdev; + struct dvb_frontend_parameters parameters; + struct dvb_fe_events events; + struct semaphore sem; + struct list_head list_head; + wait_queue_head_t wait_queue; + pid_t thread_pid; + unsigned long release_jiffies; + int state; + int bending; + int lnb_drift; + int inversion; + int auto_step; + int auto_sub_step; + int started_auto_step; + int min_delay; + int max_drift; + int step_size; + int exit; + int wakeup; + fe_status_t status; +}; + +extern int dvb_register_frontend(struct dvb_adapter* dvb, + struct dvb_frontend* fe); + +extern int dvb_unregister_frontend(struct dvb_frontend* fe); + +#endif diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index dfa5be4e2..805cf3c5d 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -6,13 +6,13 @@ * Copyright (C) 2002 Ralph Metzler * * ULE Decapsulation code: - * Copyright (C) 2003 gcs - Global Communication & Services GmbH. - * and Institute for Computer Sciences - * Salzburg University. + * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH. + * and Department of Scientific Computing + * Paris Lodron University of Salzburg. * Hilmar Linder * and Wolfram Stering * - * ULE Decaps according to draft-fair-ipdvb-ule-01.txt. + * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,6 +30,31 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +/* + * ULE ChangeLog: + * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt + * + * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt: + * ULE Extension header handling. + * Bugreports by Moritz Vieth and Hanno Tersteegen, + * Fraunhofer Institute for Open Communication Systems + * Competence Center for Advanced Satellite Communications. + * Bugfixes and robustness improvements. + * Filtering on dest MAC addresses, if present (D-Bit = 0) + * ULE_DEBUG compile-time option. + */ + +/* + * FIXME / TODO (dvb_net.c): + * + * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. + * + * TS_FEED callback is called once for every single TS cell although it is + * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()). + * + */ + +#include #include #include #include @@ -37,10 +62,16 @@ #include #include #include +#include #include "dvb_demux.h" #include "dvb_net.h" -#include "dvb_functions.h" + +static int dvb_net_debug; +module_param(dvb_net_debug, int, 0444); +MODULE_PARM_DESC(dvb_net_debug, "enable debug messages"); + +#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0) static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) @@ -52,14 +83,11 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) } -#if 1 -#define dprintk(x...) printk(x) -#else -#define dprintk(x...) -#endif +#define DVB_NET_MULTICAST_MAX 10 +#undef ULE_DEBUG -#define DVB_NET_MULTICAST_MAX 10 +#ifdef ULE_DEBUG #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) @@ -90,6 +118,7 @@ static void hexdump( const unsigned char *buf, unsigned short len ) } } +#endif struct dvb_net_priv { int in_use; @@ -111,18 +140,19 @@ struct dvb_net_priv { #define RX_MODE_PROMISC 3 struct work_struct set_multicast_list_wq; struct work_struct restart_net_feed_wq; - unsigned char feedtype; - int need_pusi; - unsigned char tscc; /* TS continuity counter after sync. */ - struct sk_buff *ule_skb; - unsigned short ule_sndu_len; - unsigned short ule_sndu_type; - unsigned char ule_sndu_type_1; - unsigned char ule_dbit; /* whether the DestMAC address present - * bit is set or not. */ - unsigned char ule_ethhdr_complete; /* whether we have completed the Ethernet - * header for the current ULE SNDU. */ - int ule_sndu_remain; + unsigned char feedtype; /* Either FEED_TYPE_ or FEED_TYPE_ULE */ + int need_pusi; /* Set to 1, if synchronization on PUSI required. */ + unsigned char tscc; /* TS continuity counter after sync on PUSI. */ + struct sk_buff *ule_skb; /* ULE SNDU decodes into this buffer. */ + unsigned char *ule_next_hdr; /* Pointer into skb to next ULE extension header. */ + unsigned short ule_sndu_len; /* ULE SNDU length in bytes, w/o D-Bit. */ + unsigned short ule_sndu_type; /* ULE SNDU type field, complete. */ + unsigned char ule_sndu_type_1; /* ULE SNDU type field, if split across 2 TS cells. */ + unsigned char ule_dbit; /* Whether the DestMAC address present + * or not (bit is set). */ + unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */ + int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */ + unsigned long ts_count; /* Current ts cell counter. */ }; @@ -142,7 +172,11 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); - eth= skb->mac.ethernet; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8) + eth = skb->mac.ethernet; +#else + eth = eth_hdr(skb); +#endif if (*eth->h_dest & 1) { if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) @@ -174,78 +208,194 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, #define TS_SZ 188 #define TS_SYNC 0x47 #define TS_TEI 0x80 +#define TS_SC 0xC0 #define TS_PUSI 0x40 #define TS_AF_A 0x20 #define TS_AF_D 0x10 +/* ULE Extension Header handlers. */ + #define ULE_TEST 0 #define ULE_BRIDGED 1 -#define ULE_LLC 2 +int ule_test_sndu( struct dvb_net_priv *p ) +{ + return -1; +} + +int ule_bridged_sndu( struct dvb_net_priv *p ) +{ + /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt. + * This has to be the last extension header, otherwise it won't work. + * Blame the authors! + */ + p->ule_bridged = 1; + return 0; +} + + +/** Handle ULE extension headers. + * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. + * Returns: >= 0: nr. of bytes consumed by next extension header + * -1: Mandatory extension header that is not recognized or TEST SNDU; discard. + */ +static int handle_one_ule_extension( struct dvb_net_priv *p ) +{ + /* Table of mandatory extension header handlers. The header type is the index. */ + static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) = + { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; + + /* Table of optional extension header handlers. The header type is the index. */ + static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, }; + + int ext_len = 0; + unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; + unsigned char htype = p->ule_sndu_type & 0x00FF; + + /* Discriminate mandatory and optional extension headers. */ + if (hlen == 0) { + /* Mandatory extension header */ + if (ule_mandatory_ext_handlers[htype]) { + ext_len = ule_mandatory_ext_handlers[htype]( p ); + p->ule_next_hdr += ext_len; + if (! p->ule_bridged) { + p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); + p->ule_next_hdr += 2; + } else { + p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) ); + /* This assures the extension handling loop will terminate. */ + } + } else + ext_len = -1; /* SNDU has to be discarded. */ + } else { + /* Optional extension header. Calculate the length. */ + ext_len = hlen << 2; + /* Process the optional extension header according to its type. */ + if (ule_optional_ext_handlers[htype]) + (void)ule_optional_ext_handlers[htype]( p ); + p->ule_next_hdr += ext_len; + p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); + p->ule_next_hdr += 2; + } + + return ext_len; +} + +static int handle_ule_extensions( struct dvb_net_priv *p ) +{ + int total_ext_len = 0, l; + + p->ule_next_hdr = p->ule_skb->data; + do { + l = handle_one_ule_extension( p ); + if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */ + total_ext_len += l; + + } while (p->ule_sndu_type < 1536); + + return total_ext_len; +} + + +/** Prepare for a new ULE SNDU: reset the decoder state. */ static inline void reset_ule( struct dvb_net_priv *p ) { p->ule_skb = NULL; + p->ule_next_hdr = NULL; p->ule_sndu_len = 0; p->ule_sndu_type = 0; p->ule_sndu_type_1 = 0; p->ule_sndu_remain = 0; p->ule_dbit = 0xFF; - p->ule_ethhdr_complete = 0; + p->ule_bridged = 0; } -static const char eth_dest_addr[] = { 0x0b, 0x0a, 0x09, 0x08, 0x04, 0x03 }; - +/** + * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of + * TS cells of a single PID. + */ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) { struct dvb_net_priv *priv = (struct dvb_net_priv *)dev->priv; - unsigned long skipped = 0L, skblen = 0L; + unsigned long skipped = 0L; u8 *ts, *ts_end, *from_where = NULL, ts_remain = 0, how_much = 0, new_ts = 1; struct ethhdr *ethh = NULL; - unsigned int emergency_count = 0; + +#ifdef ULE_DEBUG + /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ + static unsigned char ule_hist[100*TS_SZ]; + static unsigned char *ule_where = ule_hist, ule_dump = 0; +#endif if (dev == NULL) { printk( KERN_ERR "NO netdev struct!\n" ); return; } - for (ts = (char *)buf, ts_end = (char *)buf + buf_len; ts < ts_end; ) { + /* For all TS cells in current buffer. + * Appearently, we are called for every single TS cell. + */ + for (ts = (char *)buf, ts_end = (char *)buf + buf_len; ts < ts_end; /* no default incr. */ ) { - if (emergency_count++ > 200) { - /* Huh?? */ - hexdump(ts, TS_SZ); - printk(KERN_WARNING "*** LOOP ALERT! ts %p ts_remain %u " - "how_much %u, ule_skb %p, ule_len %u, ule_remain %u\n", - ts, ts_remain, how_much, priv->ule_skb, - priv->ule_sndu_len, priv->ule_sndu_remain); - break; + if (new_ts) { + /* We are about to process a new TS cell. */ + +#ifdef ULE_DEBUG + if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist; + memcpy( ule_where, ts, TS_SZ ); + if (ule_dump) { + hexdump( ule_where, TS_SZ ); + ule_dump = 0; } + ule_where += TS_SZ; +#endif - if (new_ts) { - if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI)) { - printk(KERN_WARNING "Invalid TS cell: SYNC %#x, TEI %u.\n", - ts[0], ts[1] & TS_TEI >> 7); + /* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */ + if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) { + printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n", + priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6); + + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (priv->ule_skb) { + dev_kfree_skb( priv->ule_skb ); + /* Prepare for next SNDU. */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + } + reset_ule(priv); + priv->need_pusi = 1; + + /* Continue with next TS cell. */ + ts += TS_SZ; + priv->ts_count++; continue; } + ts_remain = 184; from_where = ts + 4; } /* Synchronize on PUSI, if required. */ if (priv->need_pusi) { if (ts[1] & TS_PUSI) { - /* Find beginning of first ULE SNDU in current TS cell. - * priv->need_pusi = 0; */ + /* Find beginning of first ULE SNDU in current TS cell. */ + /* Synchronize continuity counter. */ priv->tscc = ts[3] & 0x0F; /* There is a pointer field here. */ if (ts[4] > ts_remain) { - printk(KERN_ERR "Invalid ULE packet " - "(pointer field %d)\n", ts[4]); + printk(KERN_ERR "%lu: Invalid ULE packet " + "(pointer field %d)\n", priv->ts_count, ts[4]); + ts += TS_SZ; + priv->ts_count++; continue; } + /* Skip to destination of pointer field. */ from_where = &ts[5] + ts[4]; ts_remain -= 1 + ts[4]; skipped = 0; } else { skipped++; + ts += TS_SZ; + priv->ts_count++; continue; } } @@ -256,32 +406,45 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) priv->tscc = (priv->tscc + 1) & 0x0F; else { /* TS discontinuity handling: */ + printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " + "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ - reset_ule(priv); + // reset_ule(priv); moved to below. ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; } + reset_ule(priv); /* skip to next PUSI. */ - printk(KERN_WARNING "TS discontinuity: got %#x, " - "exptected %#x.\n", ts[3] & 0x0F, priv->tscc); priv->need_pusi = 1; + ts += TS_SZ; + priv->ts_count++; continue; } /* If we still have an incomplete payload, but PUSI is - * set, some TS cells are missing. + * set; some TS cells are missing. * This is only possible here, if we missed exactly 16 TS - * cells (continuity counter). */ + * cells (continuity counter wrap). */ if (ts[1] & TS_PUSI) { if (! priv->need_pusi) { - /* printk(KERN_WARNING "Skipping pointer field %u.\n", *from_where); */ if (*from_where > 181) { - printk(KERN_WARNING "*** Invalid pointer " - "field: %u. Current TS cell " - "follows:\n", *from_where); - hexdump( ts, TS_SZ ); - printk(KERN_WARNING "-------------------\n"); + /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ + printk(KERN_WARNING "%lu: Invalid pointer " + "field: %u.\n", priv->ts_count, *from_where); + + /* Drop partly decoded SNDU, reset state, resync on PUSI. */ + if (priv->ule_skb) { + dev_kfree_skb( priv->ule_skb ); + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + } + reset_ule(priv); + priv->need_pusi = 1; + ts += TS_SZ; + priv->ts_count++; + continue; } /* Skip pointer field (we're processing a * packed payload). */ @@ -291,21 +454,26 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) priv->need_pusi = 0; if (priv->ule_sndu_remain > 183) { + /* Current SNDU lacks more data than there could be available in the + * current TS cell. */ ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; - printk(KERN_WARNING "Expected %d more SNDU bytes, but " - "got PUSI. Flushing incomplete payload.\n", - priv->ule_sndu_remain); + printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " + "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", + priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); dev_kfree_skb(priv->ule_skb); /* Prepare for next SNDU. */ reset_ule(priv); + /* Resync: go to where pointer field points to: start of next ULE SNDU. */ + from_where += ts[4]; + ts_remain -= ts[4]; } } } /* Check if new payload needs to be started. */ if (priv->ule_skb == NULL) { - /* Start a new payload w/ skb. + /* Start a new payload with skb. * Find ULE header. It is only guaranteed that the * length field (2 bytes) is contained in the current * TS. @@ -319,6 +487,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) } if (! priv->ule_sndu_len) { + /* Got at least two bytes, thus extrace the SNDU length. */ priv->ule_sndu_len = from_where[0] << 8 | from_where[1]; if (priv->ule_sndu_len & 0x8000) { /* D-Bit is set: no dest mac present. */ @@ -327,17 +496,14 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) } else priv->ule_dbit = 0; - /* printk(KERN_WARNING "ULE D-Bit: %d, SNDU len %u.\n", - priv->ule_dbit, priv->ule_sndu_len); */ - if (priv->ule_sndu_len > 32763) { - printk(KERN_WARNING "Invalid ULE SNDU length %u. " - "Resyncing.\n", priv->ule_sndu_len); - hexdump(ts, TS_SZ); + printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " + "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); priv->ule_sndu_len = 0; priv->need_pusi = 1; new_ts = 1; ts += TS_SZ; + priv->ts_count++; continue; } ts_remain -= 2; /* consume the 2 bytes SNDU length. */ @@ -355,11 +521,12 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) case 1: priv->ule_sndu_type = from_where[0] << 8; priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ - /* ts_remain -= 1; from_where += 1; - * here not necessary, because we continue. */ + ts_remain -= 1; from_where += 1; + /* Continue w/ next TS. */ case 0: new_ts = 1; ts += TS_SZ; + priv->ts_count++; continue; default: /* complete ULE header is present in current TS. */ @@ -377,24 +544,9 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) break; } - if (priv->ule_sndu_type == ULE_TEST) { - /* Test SNDU, discarded by the receiver. */ - printk(KERN_WARNING "Discarding ULE Test SNDU (%d bytes). " - "Resyncing.\n", priv->ule_sndu_len); - priv->ule_sndu_len = 0; - priv->need_pusi = 1; - continue; - } - - skblen = priv->ule_sndu_len; /* Including CRC32 */ - if (priv->ule_sndu_type != ULE_BRIDGED) { - skblen += ETH_HLEN; -#if 1 - if (! priv->ule_dbit) - skblen -= ETH_ALEN; -#endif - } - priv->ule_skb = dev_alloc_skb(skblen); + /* Allocate the skb (decoder target buffer) with the correct size, as follows: + * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */ + priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN ); if (priv->ule_skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); @@ -402,130 +554,129 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) return; } -#if 0 - if (priv->ule_sndu_type != ULE_BRIDGED) { - // skb_reserve(priv->ule_skb, 2); /* longword align L3 header */ - // Create Ethernet header. - ethh = (struct ethhdr *)skb_put( priv->ule_skb, ETH_HLEN ); - memset( ethh->h_source, 0x00, ETH_ALEN ); - if (priv->ule_dbit) { - // Dest MAC address not present --> generate our own. - memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN ); - } else { - // Dest MAC address could be split across two TS cells. - // FIXME: implement. - - printk( KERN_WARNING "%s: got destination MAC " - "address.\n", dev->name ); - memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN ); - } - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : priv->ule_sndu_type); - } -#endif - /* this includes the CRC32 _and_ dest mac, if !dbit! */ + /* This includes the CRC32 _and_ dest mac, if !dbit. */ priv->ule_sndu_remain = priv->ule_sndu_len; priv->ule_skb->dev = dev; + /* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */ + skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN ); } /* Copy data into our current skb. */ how_much = min(priv->ule_sndu_remain, (int)ts_remain); - if ((priv->ule_ethhdr_complete < ETH_ALEN) && - (priv->ule_sndu_type != ULE_BRIDGED)) { - ethh = (struct ethhdr *)priv->ule_skb->data; - if (! priv->ule_dbit) { - if (how_much >= (ETH_ALEN - priv->ule_ethhdr_complete)) { - /* copy dest mac address. */ - memcpy(skb_put(priv->ule_skb, - (ETH_ALEN - priv->ule_ethhdr_complete)), - from_where, - (ETH_ALEN - priv->ule_ethhdr_complete)); - memset(ethh->h_source, 0x00, ETH_ALEN); - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : - priv->ule_sndu_type); - skb_put(priv->ule_skb, ETH_ALEN + 2); - - how_much -= (ETH_ALEN - priv->ule_ethhdr_complete); - priv->ule_sndu_remain -= (ETH_ALEN - - priv->ule_ethhdr_complete); - ts_remain -= (ETH_ALEN - priv->ule_ethhdr_complete); - from_where += (ETH_ALEN - priv->ule_ethhdr_complete); - priv->ule_ethhdr_complete = ETH_ALEN; - } - } else { - /* Generate whole Ethernet header. */ - memcpy(ethh->h_dest, eth_dest_addr, ETH_ALEN); - memset(ethh->h_source, 0x00, ETH_ALEN); - ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ? - priv->ule_sndu_len : priv->ule_sndu_type); - skb_put(priv->ule_skb, ETH_HLEN); - priv->ule_ethhdr_complete = ETH_ALEN; - } - } - /* printk(KERN_WARNING "Copying %u bytes, ule_sndu_remain = %u, " - "ule_sndu_len = %u.\n", how_much, priv->ule_sndu_remain, - priv->ule_sndu_len); */ memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much); priv->ule_sndu_remain -= how_much; ts_remain -= how_much; from_where += how_much; - if ((priv->ule_ethhdr_complete < ETH_ALEN) && - (priv->ule_sndu_type != ULE_BRIDGED)) { - priv->ule_ethhdr_complete += how_much; - } - /* Check for complete payload. */ if (priv->ule_sndu_remain <= 0) { /* Check CRC32, we've got it in our skb already. */ unsigned short ulen = htons(priv->ule_sndu_len); unsigned short utype = htons(priv->ule_sndu_type); - struct kvec iov[4] = { + struct kvec iov[3] = { { &ulen, sizeof ulen }, { &utype, sizeof utype }, - { NULL, 0 }, - { priv->ule_skb->data + ETH_HLEN, - priv->ule_skb->len - ETH_HLEN - 4 } + { priv->ule_skb->data, priv->ule_skb->len - 4 } }; unsigned long ule_crc = ~0L, expected_crc; if (priv->ule_dbit) { /* Set D-bit for CRC32 verification, * if it was set originally. */ ulen |= 0x0080; - } else { - iov[2].iov_base = priv->ule_skb->data; - iov[2].iov_len = ETH_ALEN; } - ule_crc = iov_crc32(ule_crc, iov, 4); + + ule_crc = iov_crc32(ule_crc, iov, 3); expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 | *((u8 *)priv->ule_skb->tail - 3) << 16 | *((u8 *)priv->ule_skb->tail - 2) << 8 | *((u8 *)priv->ule_skb->tail - 1); if (ule_crc != expected_crc) { - printk(KERN_WARNING "CRC32 check %s: %#lx / %#lx.\n", - ule_crc != expected_crc ? "FAILED" : "OK", - ule_crc, expected_crc); - hexdump(priv->ule_skb->data + ETH_HLEN, - priv->ule_skb->len - ETH_HLEN); + printk(KERN_WARNING "%lu: CRC32 check FAILED: %#lx / %#lx, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n", + priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0); + +#ifdef ULE_DEBUG + hexdump( iov[0].iov_base, iov[0].iov_len ); + hexdump( iov[1].iov_base, iov[1].iov_len ); + hexdump( iov[2].iov_base, iov[2].iov_len ); + + if (ule_where == ule_hist) { + hexdump( &ule_hist[98*TS_SZ], TS_SZ ); + hexdump( &ule_hist[99*TS_SZ], TS_SZ ); + } else if (ule_where == &ule_hist[TS_SZ]) { + hexdump( &ule_hist[99*TS_SZ], TS_SZ ); + hexdump( ule_hist, TS_SZ ); + } else { + hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ ); + hexdump( ule_where - TS_SZ, TS_SZ ); + } + ule_dump = 1; +#endif ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; dev_kfree_skb(priv->ule_skb); } else { + /* CRC32 verified OK. */ + /* Handle ULE Extension Headers. */ + if (priv->ule_sndu_type < 1536) { + /* There is an extension header. Handle it accordingly. */ + int l = handle_ule_extensions( priv ); + if (l < 0) { + /* Mandatory extension header unknown or TEST SNDU. Drop it. */ + // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); + dev_kfree_skb( priv->ule_skb ); + goto sndu_done; + } + skb_pull( priv->ule_skb, l ); + } + /* CRC32 was OK. Remove it from skb. */ priv->ule_skb->tail -= 4; priv->ule_skb->len -= 4; + + /* Filter on receiver's destination MAC address, if present. */ + if (!priv->ule_dbit) { + /* The destination MAC address is the next data in the skb. */ + if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) { + /* MAC addresses don't match. Drop SNDU. */ + // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" ); + dev_kfree_skb( priv->ule_skb ); + goto sndu_done; + } + if (! priv->ule_bridged) { + skb_push( priv->ule_skb, ETH_ALEN + 2 ); + ethh = (struct ethhdr *)priv->ule_skb->data; + memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN ); + memset( ethh->h_source, 0, ETH_ALEN ); + ethh->h_proto = htons( priv->ule_sndu_type ); + } else { + /* Skip the Receiver destination MAC address. */ + skb_pull( priv->ule_skb, ETH_ALEN ); + } + } else { + if (! priv->ule_bridged) { + skb_push( priv->ule_skb, ETH_HLEN ); + ethh = (struct ethhdr *)priv->ule_skb->data; + memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN ); + memset( ethh->h_source, 0, ETH_ALEN ); + ethh->h_proto = htons( priv->ule_sndu_type ); + } else { + /* skb is in correct state; nothing to do. */ + } + } + priv->ule_bridged = 0; + /* Stuff into kernel's protocol stack. */ priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev); /* If D-bit is set (i.e. destination MAC address not present), - * receive the packet anyhw. */ - /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) */ - priv->ule_skb->pkt_type = PACKET_HOST; + * receive the packet anyhow. */ + /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) + priv->ule_skb->pkt_type = PACKET_HOST; */ ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++; ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len; netif_rx(priv->ule_skb); } + sndu_done: /* Prepare for next SNDU. */ reset_ule(priv); } @@ -545,6 +696,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) } else { new_ts = 1; ts += TS_SZ; + priv->ts_count++; if (priv->ule_skb == NULL) { priv->need_pusi = 1; priv->ule_sndu_type_1 = 0; @@ -563,7 +715,7 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len, if (buffer2 != 0) printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2); if (buffer1_len > 32768) - printk(KERN_WARNING "length > 32k: %u.\n", buffer1_len); + printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len); /* printk("TS callback: %u bytes, %u TS cells @ %p.\n", buffer1_len, buffer1_len / TS_SZ, buffer1); */ dvb_net_ule(dev, buffer1, buffer1_len); @@ -662,6 +814,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) { + dev_kfree_skb(skb); return 0; } @@ -723,7 +876,7 @@ static int dvb_net_feed_start(struct net_device *dev) unsigned char *mac = (unsigned char *) dev->dev_addr; dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); - if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) + if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) printk("%s: BUG %d\n", __FUNCTION__, __LINE__); priv->secfeed=NULL; @@ -919,14 +1072,6 @@ static void dvb_net_set_multicast_list (struct net_device *dev) } -static int dvb_net_set_config(struct net_device *dev, struct ifmap *map) -{ - if (netif_running(dev)) - return -EBUSY; - return 0; -} - - static void wq_restart_net_feed (void *data) { struct net_device *dev = data; @@ -985,7 +1130,6 @@ static void dvb_net_setup(struct net_device *dev) dev->hard_start_xmit = dvb_net_tx; dev->get_stats = dvb_net_get_stats; dev->set_multicast_list = dvb_net_set_multicast_list; - dev->set_config = dvb_net_set_config; dev->set_mac_address = dvb_net_set_mac; dev->mtu = 4096; dev->mc_count = 0; @@ -1057,13 +1201,14 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) } -static int dvb_net_remove_if(struct dvb_net *dvbnet, int num) +static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num) { struct net_device *net = dvbnet->device[num]; - struct dvb_net_priv *priv = net->priv; + struct dvb_net_priv *priv; if (!dvbnet->state[num]) return -EINVAL; + priv = net->priv; if (priv->in_use) return -EBUSY; @@ -1124,10 +1269,18 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file, break; } case NET_REMOVE_IF: + { + int ret; + if (!capable(CAP_SYS_ADMIN)) return -EPERM; - module_put(dvbdev->adapter->module); - return dvb_net_remove_if(dvbnet, (int) (long) parg); + if ((unsigned int) parg >= DVB_NET_DEVICES_MAX) + return -EINVAL; + ret = dvb_net_remove_if(dvbnet, (unsigned int) parg); + if (!ret) + module_put(dvbdev->adapter->module); + return ret; + } /* binary compatiblity cruft */ case __NET_ADD_IF_OLD: @@ -1203,6 +1356,7 @@ void dvb_net_release (struct dvb_net *dvbnet) dvb_net_remove_if(dvbnet, i); } } +EXPORT_SYMBOL(dvb_net_release); int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, @@ -1220,4 +1374,4 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, return 0; } - +EXPORT_SYMBOL(dvb_net_init); diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 686ffc229..837d16a34 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -25,22 +25,26 @@ #include #include #include +#include #include #include #include #include +#include #include "dvbdev.h" -#include "dvb_functions.h" -static int dvbdev_debug = 0; +static int dvbdev_debug; + +module_param(dvbdev_debug, int, 0644); +MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); + #define dprintk if (dvbdev_debug) printk static LIST_HEAD(dvb_adapter_list); static DECLARE_MUTEX(dvbdev_register_lock); - -static char *dnames[] = { +static const char * const dnames[] = { "video", "audio", "sec", "frontend", "demux", "dvr", "ca", "net", "osd" }; @@ -49,6 +53,9 @@ static char *dnames[] = { #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +struct class_simple *dvb_class; +EXPORT_SYMBOL(dvb_class); + static struct dvb_device* dvbdev_find_device (int minor) { struct list_head *entry; @@ -125,6 +132,7 @@ int dvb_generic_open(struct inode *inode, struct file *file) dvbdev->users--; return 0; } +EXPORT_SYMBOL(dvb_generic_open); int dvb_generic_release(struct inode *inode, struct file *file) @@ -143,6 +151,7 @@ int dvb_generic_release(struct inode *inode, struct file *file) dvbdev->users++; return 0; } +EXPORT_SYMBOL(dvb_generic_release); int dvb_generic_ioctl(struct inode *inode, struct file *file, @@ -158,6 +167,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file, return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } +EXPORT_SYMBOL(dvb_generic_ioctl); static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) @@ -219,12 +229,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, S_IFCHR | S_IRUSR | S_IWUSR, "dvb/adapter%d/%s%d", adap->num, dnames[type], id); + class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + NULL, "dvb%d.%s%d", adap->num, dnames[type], id); + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", adap->num, dnames[type], id, nums2minor(adap->num, type, id), nums2minor(adap->num, type, id)); return 0; } +EXPORT_SYMBOL(dvb_register_device); void dvb_unregister_device(struct dvb_device *dvbdev) @@ -235,9 +249,13 @@ void dvb_unregister_device(struct dvb_device *dvbdev) devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); + class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, + dvbdev->type, dvbdev->id))); + list_del(&dvbdev->list_head); kfree(dvbdev); } +EXPORT_SYMBOL(dvb_unregister_device); static int dvbdev_get_free_adapter_num (void) @@ -296,28 +314,101 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo return num; } +EXPORT_SYMBOL(dvb_register_adapter); int dvb_unregister_adapter(struct dvb_adapter *adap) { + devfs_remove("dvb/adapter%d", adap->num); + if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; - devfs_remove("dvb/adapter%d", adap->num); list_del (&adap->list_head); up (&dvbdev_register_lock); kfree (adap); return 0; } +EXPORT_SYMBOL(dvb_unregister_adapter); + +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + + return err; +} static int __init init_dvbdev(void) { int retval; + + if ((retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops))) + printk("dvb-core: unable to get major %d\n", DVB_MAJOR); + devfs_mk_dir("dvb"); - retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops); - if (retval) - printk("video_dev: unable to get major %d\n", DVB_MAJOR); + dvb_class = class_simple_create(THIS_MODULE, "dvb"); + if (IS_ERR(dvb_class)) + return PTR_ERR(dvb_class); return retval; } @@ -327,6 +418,7 @@ static void __exit exit_dvbdev(void) { unregister_chrdev(DVB_MAJOR, "DVB"); devfs_remove("dvb"); + class_simple_destroy(dvb_class); } module_init(init_dvbdev); @@ -336,6 +428,3 @@ MODULE_DESCRIPTION("DVB Core Driver"); MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); -MODULE_PARM(dvbdev_debug,"i"); -MODULE_PARM_DESC(dvbdev_debug, "enable verbose debug messages"); - diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index fc4700f05..333ada77c 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -28,6 +28,7 @@ #include #include #include +#include #define DVB_MAJOR 212 @@ -48,6 +49,7 @@ struct dvb_adapter { struct list_head device_list; const char *name; u8 proposed_mac [6]; + void* priv; struct module *module; }; @@ -92,5 +94,15 @@ extern int dvb_generic_open (struct inode *inode, struct file *file); extern int dvb_generic_release (struct inode *inode, struct file *file); extern int dvb_generic_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefully become +generic_usercopy() someday... */ + +extern int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + #endif /* #ifndef _DVBDEV_H_ */ diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 812fff15c..226a59bfa 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -1,187 +1,148 @@ -comment "Supported Frontend Modules" - depends on DVB - -config DVB_TWINHAN_DST - tristate "TWINHAN DST based DVB-S frontend (QPSK)" - depends on DVB_CORE && DVB_BT8XX - help - Used in such cards as the VP-1020/1030, Twinhan DST, - VVmer TV@SAT. Say Y when you want to support frontends - using this asic. +menu "Customise DVB Frontends" + depends on DVB_CORE - This module requires the dvb-bt8xx driver and dvb bt878 - module. +comment "DVB-S (satellite) frontends" + depends on DVB_CORE config DVB_STV0299 - tristate "STV0299 based DVB-S frontend (QPSK)" + tristate "ST STV0299 based" depends on DVB_CORE help - The stv0299 by ST is used in many DVB-S tuner modules, - say Y when you want to support frontends based on this - DVB-S demodulator. - - Some examples are the Alps BSRU6, the Philips SU1278 and - the LG TDQB-S00x. - - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. + A DVB-S tuner module. Say Y when you want to support this frontend. -config DVB_SP887X - tristate "Frontends with sp887x demodulators, e.g. Microtune DTF7072" +config DVB_CX24110 + tristate "Conexant CX24110 based" depends on DVB_CORE help - A DVB-T demodulator driver. Say Y when you want to support the sp887x. + A DVB-S tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +config DVB_TDA8083 + tristate "Philips TDA8083 based" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_TDA80XX + tristate "Philips TDA8044 or TDA8083 based" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. -config DVB_SP887X_FIRMWARE_FILE - string "Full pathname of sp887x firmware file" - depends on DVB_SP887X - default "/usr/lib/hotplug/firmware/sc_main.mc" - help - This driver needs a copy of the Avermedia firmware. The version tested - is part of the Avermedia DVB-T 1.3.26.3 Application. This can be downloaded - from the Avermedia web site. - If the software is installed in Windows the file will be in the - /Program Files/AVerTV DVB-T/ directory and is called sc_main.mc. - Alternatively it can "extracted" from the install cab files but this will have - to be done in windows as I don't know of a linux version of extract.exe. - Copy this file to /usr/lib/hotplug/firmware/sc_main.mc. - With this version of the file the first 10 bytes are discarded and the next - 0x4000 loaded. This may change in future versions. +config DVB_MT312 + tristate "Zarlink MT312 based" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. -config DVB_ALPS_TDLB7 - tristate "Alps TDLB7 (OFDM)" +config DVB_VES1X93 + tristate "VLSI VES1893 or VES1993 based" depends on DVB_CORE help - A DVB-T tuner module. Say Y when you want to support this frontend. + A DVB-S tuner module. Say Y when you want to support this frontend. - This tuner module needs some microcode located in a file called - "Sc_main.mc" in the windows driver. Please pass the module parameter - mcfile="/PATH/FILENAME" when loading alps_tdlb7.o. +comment "DVB-T (terrestrial) frontends" + depends on DVB_CORE - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +config DVB_SP8870 + tristate "Spase sp8870 based" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + This driver needs external firmware. Please use the command + "/Documentation/dvb/get_dvb_firmware sp8870" to + download/extract it, and then copy it to /usr/lib/hotplug/firmware. -config DVB_ALPS_TDMB7 - tristate "Alps TDMB7 (OFDM)" +config DVB_SP887X + tristate "Spase sp887x based" depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. + This driver needs external firmware. Please use the command + "/Documentation/dvb/get_dvb_firmware sp887x" to + download/extract it, and then copy it to /usr/lib/hotplug/firmware. -config DVB_ATMEL_AT76C651 - tristate "Atmel AT76C651 (QAM)" +config DVB_CX22700 + tristate "Conexant CX22700 based" depends on DVB_CORE help - The AT76C651 Demodulator is used in some DVB-C SetTopBoxes. Say Y - when you see this demodulator chip near your tuner module. + A DVB-T tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +config DVB_CX22702 + tristate "Conexant cx22702 demodulator (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. -config DVB_CX24110 - tristate "Frontends with Connexant CX24110 demodulator (QPSK)" +config DVB_L64781 + tristate "LSI L64781" depends on DVB_CORE help - The CX24110 Demodulator is used in some DVB-S frontends. - Say Y if you want support for this chip in your kernel. - - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. + A DVB-T tuner module. Say Y when you want to support this frontend. -config DVB_GRUNDIG_29504_491 - tristate "Grundig 29504-491 (QPSK)" +config DVB_TDA1004X + tristate "Philips TDA10045H/TDA10046H based" depends on DVB_CORE help - A DVB-S tuner module. Say Y when you want to support this frontend. + A DVB-T tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. + This driver needs external firmware. Please use the commands + "/Documentation/dvb/get_dvb_firmware tda10045", + "/Documentation/dvb/get_dvb_firmware tda10046" to + download/extract them, and then copy them to /usr/lib/hotplug/firmware. -config DVB_GRUNDIG_29504_401 - tristate "Grundig 29504-401 (OFDM)" +config DVB_NXT6000 + tristate "NxtWave Communications NXT6000 based" depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. - -config DVB_MT312 - tristate "Zarlink MT312 Satellite Channel Decoder (QPSK)" +config DVB_MT352 + tristate "Zarlink MT352 based" depends on DVB_CORE help - A DVB-S tuner module. Say Y when you want to support this frontend. - - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. + A DVB-T tuner module. Say Y when you want to support this frontend. -config DVB_VES1820 - tristate "Frontends with external VES1820 demodulator (QAM)" +config DVB_DIB3000MB + tristate "DiBcom 3000-MB" depends on DVB_CORE help - The VES1820 Demodulator is used on many DVB-C PCI cards and in some - DVB-C SetTopBoxes. Say Y when you see this demodulator chip near your - tuner module. + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. - -config DVB_VES1X93 - tristate "Frontends with VES1893 or VES1993 demodulator (QPSK)" +config DVB_DIB3000MC + tristate "DiBcom 3000-MC/P" depends on DVB_CORE help - A DVB-S tuner module. Say Y when you want to support this frontend. + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +comment "DVB-C (cable) frontends" + depends on DVB_CORE -config DVB_TDA1004X - tristate "Frontends with external TDA10045H or TDA10046H demodulators (OFDM)" +config DVB_ATMEL_AT76C651 + tristate "Atmel AT76C651 based" depends on DVB_CORE - help - A DVB-T tuner module. Say Y when you want to support this frontend. + help + A DVB-C tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +config DVB_VES1820 + tristate "VLSI VES1820 based" + depends on DVB_CORE + help + A DVB-C tuner module. Say Y when you want to support this frontend. -config DVB_TDA1004X_FIRMWARE_FILE - string "Full pathname of tda1004x.bin firmware file" - depends on DVB_TDA1004X - default "/usr/lib/hotplug/firmware/tda1004x.bin" - help - The TDA1004X requires additional firmware in order to function. - The firmware file can obtained as follows: - wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip - unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll - mv ttlcdacc.dll /usr/lib/hotplug/firmware/tda1004x.bin - Note: even if you're using a USB device, you MUST get the file from the - TechnoTrend PCI drivers. +config DVB_TDA10021 + tristate "Philips TDA10021 based" + depends on DVB_CORE + help + A DVB-C tuner module. Say Y when you want to support this frontend. -config DVB_NXT6000 - tristate "Frontends with NxtWave Communications NXT6000 demodulator (OFDM)" +config DVB_STV0297 + tristate "ST STV0297 based" depends on DVB_CORE help - A DVB-T tuner module. Say Y when you want to support this frontend. + A DVB-C tuner module. Say Y when you want to support this frontend. - If you don't know what tuner module is soldered on your - DVB adapter simply enable all supported frontends, the - right one will get autodetected. +endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index e536b0de7..f84a49802 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -4,17 +4,23 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -obj-$(CONFIG_DVB_TWINHAN_DST) += dst.o obj-$(CONFIG_DVB_STV0299) += stv0299.o -obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o -obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o +obj-$(CONFIG_DVB_SP8870) += sp8870.o +obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o obj-$(CONFIG_DVB_CX24110) += cx24110.o -obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o -obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o +obj-$(CONFIG_DVB_TDA8083) += tda8083.o +obj-$(CONFIG_DVB_L64781) += l64781.o +obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o +obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o +obj-$(CONFIG_DVB_MT352) += mt352.o +obj-$(CONFIG_DVB_CX22702) += cx22702.o +obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o +obj-$(CONFIG_DVB_TDA10021) += tda10021.o +obj-$(CONFIG_DVB_STV0297) += stv0297.o diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c index 01d438a4f..4b6c539a0 100644 --- a/drivers/media/dvb/frontends/at76c651.c +++ b/drivers/media/dvb/frontends/at76c651.c @@ -1,10 +1,10 @@ /* * at76c651.c * - * Atmel DVB-C Frontend Driver (at76c651/dat7021) + * Atmel DVB-C Frontend Driver (at76c651/tua6010xs) * * Copyright (C) 2001 fnbrd - * & 2002 Andreas Oberritter + * & 2002-2004 Andreas Oberritter * & 2003 Wolfram Joost * * This program is free software; you can redistribute it and/or modify @@ -21,59 +21,46 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * AT76C651 + * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf + * http://www.atmel.com/atmel/acrobat/doc1320.pdf */ #include #include +#include #include #include #include +#include +#include "dvb_frontend.h" +#include "at76c651.h" -#if defined(__powerpc__) -#include -#endif -#include "dvb_frontend.h" -#include "dvb_i2c.h" -#include "dvb_functions.h" +struct at76c651_state { -static int debug = 0; -static u8 at76c651_qam; -static u8 at76c651_revision; + struct i2c_adapter* i2c; -#define dprintk if (debug) printk + struct dvb_frontend_ops ops; -/* - * DAT7021 - * ------- - * Input Frequency Range (RF): 48.25 MHz to 863.25 MHz - * Band Width: 8 MHz - * Level Input (Range for Digital Signals): -61 dBm to -41 dBm - * Output Frequency (IF): 36 MHz - * - * (see http://www.atmel.com/atmel/acrobat/doc1320.pdf) - */ + const struct at76c651_config* config; + + struct dvb_frontend frontend; + + /* revision of the chip */ + u8 revision; -static struct dvb_frontend_info at76c651_info = { - - .name = "Atmel AT76C651(B) with DAT7021", - .type = FE_QAM, - .frequency_min = 48250000, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER + /* last QAM value set */ + u8 qam; }; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "at76c651: " args); \ + } while (0) + + #if ! defined(__powerpc__) static __inline__ int __ilog2(unsigned long x) { @@ -89,229 +76,150 @@ static __inline__ int __ilog2(unsigned long x) } #endif -static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data) { - int ret; u8 buf[] = { reg, data }; - struct i2c_msg msg = { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 }; + struct i2c_msg msg = + { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c->xfer(i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error " "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); - dvb_delay(10); + msleep(10); return (ret != 1) ? -EREMOTEIO : 0; - } -static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg) +static u8 at76c651_readreg(struct at76c651_state* state, u8 reg) { - int ret; - u8 b0[] = { reg }; - u8 b1[] = { 0 }; - struct i2c_msg msg[] = { {.addr = 0x1a >> 1, .flags = 0, .buf = b0, .len = 1}, - {.addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1} }; + u8 val; + struct i2c_msg msg[] = { + { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; - ret = i2c->xfer(i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - return b1[0]; - + return val; } -static int at76c651_reset(struct dvb_i2c_bus *i2c) +static int at76c651_reset(struct at76c651_state* state) { - - return at76c651_writereg(i2c, 0x07, 0x01); - + return at76c651_writereg(state, 0x07, 0x01); } -static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) +static void at76c651_disable_interrupts(struct at76c651_state* state) { - - return at76c651_writereg(i2c, 0x0b, 0x00); - + at76c651_writereg(state, 0x0b, 0x00); } -static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) +static int at76c651_set_auto_config(struct at76c651_state *state) { - /* * Autoconfig */ - at76c651_writereg(i2c, 0x06, 0x01); + at76c651_writereg(state, 0x06, 0x01); /* * Performance optimizations, should be done after autoconfig */ - at76c651_writereg(i2c, 0x10, 0x06); - at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10); - at76c651_writereg(i2c, 0x15, 0x28); - at76c651_writereg(i2c, 0x20, 0x09); - at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90); - at76c651_writereg(i2c, 0x30, 0x90); - if (at76c651_qam == 5) - at76c651_writereg(i2c, 0x35, 0x2A); + at76c651_writereg(state, 0x10, 0x06); + at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10); + at76c651_writereg(state, 0x15, 0x28); + at76c651_writereg(state, 0x20, 0x09); + at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90); + at76c651_writereg(state, 0x30, 0x90); + if (state->qam == 5) + at76c651_writereg(state, 0x35, 0x2A); /* * Initialize A/D-converter */ - if (at76c651_revision == 0x11) { - at76c651_writereg(i2c, 0x2E, 0x38); - at76c651_writereg(i2c, 0x2F, 0x13); + if (state->revision == 0x11) { + at76c651_writereg(state, 0x2E, 0x38); + at76c651_writereg(state, 0x2F, 0x13); } - at76c651_disable_interrupts(i2c); + at76c651_disable_interrupts(state); /* * Restart operation */ - at76c651_reset(i2c); - - return 0; - -} - -static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) -{ - - at76c651_writereg(i2c, 0x04, 0x3f); - at76c651_writereg(i2c, 0x05, 0xee); - - return 0; - -} - -static int at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable) -{ - - if (enable) - return at76c651_writereg(i2c, 0x0c, 0xc2 | 0x01); - else - return at76c651_writereg(i2c, 0x0c, 0xc2); - -} - -static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) -{ - - int ret; - struct i2c_msg msg = - { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) }; - -#ifdef __LITTLE_ENDIAN - tw = __cpu_to_be32(tw); -#endif - - at76c651_switch_tuner_i2c(i2c, 1); - - ret = i2c->xfer(i2c, &msg, 1); - - at76c651_switch_tuner_i2c(i2c, 0); - - if (ret != 4) - return -EFAULT; - - at76c651_reset(i2c); + at76c651_reset(state); return 0; - } -static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq) +static void at76c651_set_bbfreq(struct at76c651_state* state) { - - u32 dw; - - freq /= 1000; - - if ((freq < 48250) || (freq > 863250)) - return -EINVAL; - - /* - * formula: dw=0x17e28e06+(freq-346000UL)/8000UL*0x800000 - * or: dw=0x4E28E06+(freq-42000) / 125 * 0x20000 - */ - - dw = (freq - 42000) * 4096; - dw = dw / 125; - dw = dw * 32; - - if (freq > 394000) - dw += 0x4E28E85; - else - dw += 0x4E28E06; - - return dat7021_write(i2c, dw); - + at76c651_writereg(state, 0x04, 0x3f); + at76c651_writereg(state, 0x05, 0xee); } -static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate) +static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate) { - u8 exponent; u32 mantissa; - if (symbolrate > 9360000) + if (symbol_rate > 9360000) return -EINVAL; /* * FREF = 57800 kHz - * exponent = 10 + floor ( log2 ( symbolrate / FREF ) ) - * mantissa = ( symbolrate / FREF) * ( 1 << ( 30 - exponent ) ) + * exponent = 10 + floor (log2(symbol_rate / FREF)) + * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent)) */ - exponent = __ilog2((symbolrate << 4) / 903125); - mantissa = ((symbolrate / 3125) * (1 << (24 - exponent))) / 289; + exponent = __ilog2((symbol_rate << 4) / 903125); + mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289; - at76c651_writereg(i2c, 0x00, mantissa >> 13); - at76c651_writereg(i2c, 0x01, mantissa >> 5); - at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent); + at76c651_writereg(state, 0x00, mantissa >> 13); + at76c651_writereg(state, 0x01, mantissa >> 5); + at76c651_writereg(state, 0x02, (mantissa << 3) | exponent); return 0; - } -static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) +static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam) { - switch (qam) { case QPSK: - at76c651_qam = 0x02; + state->qam = 0x02; break; case QAM_16: - at76c651_qam = 0x04; + state->qam = 0x04; break; case QAM_32: - at76c651_qam = 0x05; + state->qam = 0x05; break; case QAM_64: - at76c651_qam = 0x06; + state->qam = 0x06; break; case QAM_128: - at76c651_qam = 0x07; + state->qam = 0x07; break; case QAM_256: - at76c651_qam = 0x08; + state->qam = 0x08; break; #if 0 case QAM_512: - at76c651_qam = 0x09; + state->qam = 0x09; break; case QAM_1024: - at76c651_qam = 0x0A; + state->qam = 0x0A; break; #endif default: @@ -319,15 +227,12 @@ static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) } - return at76c651_writereg(i2c, 0x03, at76c651_qam); - + return at76c651_writereg(state, 0x03, state->qam); } -static int at76c651_set_inversion(struct dvb_i2c_bus *i2c, - fe_spectral_inversion_t inversion) +static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion) { - - u8 feciqinv = at76c651_readreg(i2c, 0x60); + u8 feciqinv = at76c651_readreg(state, 0x60); switch (inversion) { case INVERSION_OFF: @@ -347,56 +252,63 @@ static int at76c651_set_inversion(struct dvb_i2c_bus *i2c, return -EINVAL; } - return at76c651_writereg(i2c, 0x60, feciqinv); - + return at76c651_writereg(state, 0x60, feciqinv); } -static int at76c651_set_parameters(struct dvb_i2c_bus *i2c, - struct dvb_frontend_parameters *p) -{ - dat7021_set_tv_freq(i2c, p->frequency); - at76c651_set_symbolrate(i2c, p->u.qam.symbol_rate); - at76c651_set_inversion(i2c, p->inversion); - at76c651_set_auto_config(i2c); - at76c651_reset(i2c); - return 0; -} -static int at76c651_set_defaults(struct dvb_i2c_bus *i2c) + + + + +static int at76c651_set_parameters(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) { + int ret; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - at76c651_set_symbolrate(i2c, 6900000); - at76c651_set_qam(i2c, QAM_64); - at76c651_set_bbfreq(i2c); - at76c651_set_auto_config(i2c); + at76c651_writereg(state, 0x0c, 0xc3); + state->config->pll_set(fe, p); + at76c651_writereg(state, 0x0c, 0xc2); - return 0; + if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate))) + return ret; + if ((ret = at76c651_set_inversion(state, p->inversion))) + return ret; + + return at76c651_set_auto_config(state); } -static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int at76c651_set_defaults(struct dvb_frontend* fe) { + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - switch (cmd) { + at76c651_set_symbol_rate(state, 6900000); + at76c651_set_qam(state, QAM_64); + at76c651_set_bbfreq(state); + at76c651_set_auto_config(state); - case FE_GET_INFO: - memcpy(arg, &at76c651_info, sizeof (struct dvb_frontend_info)); - break; + if (state->config->pll_init) { + at76c651_writereg(state, 0x0c, 0xc3); + state->config->pll_init(fe); + at76c651_writereg(state, 0x0c, 0xc2); +} - case FE_READ_STATUS: - { + return 0; +} - fe_status_t *status = (fe_status_t *) arg; +static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status) + { + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; u8 sync; /* * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) */ - sync = at76c651_readreg(fe->i2c, 0x80); - + sync = at76c651_readreg(state, 0x80); *status = 0; if (sync & (0x04 | 0x10)) /* AGC1 || TIM */ @@ -414,122 +326,138 @@ static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */ *status |= FE_HAS_LOCK; - break; - + return 0; } - case FE_READ_BER: +static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - *ber = (at76c651_readreg(fe->i2c, 0x81) & 0x0F) << 16; - *ber |= at76c651_readreg(fe->i2c, 0x82) << 8; - *ber |= at76c651_readreg(fe->i2c, 0x83); + *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16; + *ber |= at76c651_readreg(state, 0x82) << 8; + *ber |= at76c651_readreg(state, 0x83); *ber *= 10; - break; + return 0; } - case FE_READ_SIGNAL_STRENGTH: +static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 gain = ~at76c651_readreg(fe->i2c, 0x91); - - *(u16 *) arg = (gain << 8) | gain; - break; - } + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - case FE_READ_SNR: - *(u16 *) arg = - 0xFFFF - - ((at76c651_readreg(fe->i2c, 0x8F) << 8) | - at76c651_readreg(fe->i2c, 0x90)); - break; + u8 gain = ~at76c651_readreg(state, 0x91); + *strength = (gain << 8) | gain; - case FE_READ_UNCORRECTED_BLOCKS: - *(u32 *) arg = at76c651_readreg(fe->i2c, 0x82); - break; + return 0; +} - case FE_SET_FRONTEND: - return at76c651_set_parameters(fe->i2c, arg); +static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr) +{ + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - case FE_GET_FRONTEND: - break; + *snr = 0xFFFF - + ((at76c651_readreg(state, 0x8F) << 8) | + at76c651_readreg(state, 0x90)); - case FE_SLEEP: - break; - case FE_INIT: - return at76c651_set_defaults(fe->i2c); + return 0; +} - case FE_GET_TUNE_SETTINGS: +static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; - fesettings->min_delay_ms = 50; - fesettings->step_size = 0; - fesettings->max_drift = 0; - return 0; - } + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; - default: - return -ENOIOCTLCMD; - } + *ucblocks = at76c651_readreg(state, 0x82); return 0; - } -static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data) +static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings) { - if ( (at76c651_readreg(i2c, 0x0E) != 0x65) || - ( ( (at76c651_revision = at76c651_readreg(i2c, 0x0F)) & 0xFE) != 0x10) ) -{ - dprintk("no AT76C651(B) found\n"); - return -ENODEV; + fesettings->min_delay_ms = 50; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; } - if (at76c651_revision == 0x10) - { - dprintk("AT76C651A found\n"); - strcpy(at76c651_info.name,"Atmel AT76C651A with DAT7021"); - } - else - { - strcpy(at76c651_info.name,"Atmel AT76C651B with DAT7021"); - dprintk("AT76C651B found\n"); +static void at76c651_release(struct dvb_frontend* fe) +{ + struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv; + kfree(state); } - at76c651_set_defaults(i2c); - - return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info); +static struct dvb_frontend_ops at76c651_ops; -} - -static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data) +struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, + struct i2c_adapter* i2c) { + struct at76c651_state* state = NULL; - dvb_unregister_frontend(at76c651_ioctl, i2c); + /* allocate memory for the internal state */ + state = (struct at76c651_state*) kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); + if (state == NULL) goto error; -} + /* setup the state */ + state->config = config; + state->qam = 0; -static int __init at76c651_init(void) -{ + /* check if the demod is there */ + if (at76c651_readreg(state, 0x0e) != 0x65) goto error; - return dvb_register_i2c_device(THIS_MODULE, at76c651_attach, - at76c651_detach); + /* finalise state setup */ + state->i2c = i2c; + state->revision = at76c651_readreg(state, 0x0f) & 0xfe; + memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops)); -} - -static void __exit at76c651_exit(void) -{ - - dvb_unregister_i2c_device(at76c651_attach); + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; +error: + if (state) kfree(state); + return NULL; } -module_init(at76c651_init); -module_exit(at76c651_exit); +static struct dvb_frontend_ops at76c651_ops = { + + .info = { + .name = "Atmel AT76C651B DVB-C", + .type = FE_QAM, + .frequency_min = 48250000, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + /*.frequency_tolerance = */ /* FIXME: 12% of SR */ + .symbol_rate_min = 0, /* FIXME */ + .symbol_rate_max = 9360000, /* FIXME */ + .symbol_rate_tolerance = 4000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | + FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER + }, + + .release = at76c651_release, + + .init = at76c651_set_defaults, + + .set_frontend = at76c651_set_parameters, + .get_tune_settings = at76c651_get_tune_settings, + + .read_status = at76c651_read_status, + .read_ber = at76c651_read_ber, + .read_signal_strength = at76c651_read_signal_strength, + .read_snr = at76c651_read_snr, + .read_ucblocks = at76c651_read_ucblocks, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("at76c651/dat7021 dvb-c frontend driver"); +MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); + +EXPORT_SYMBOL(at76c651_attach); diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index ee4d9a868..f8d5ec9ea 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -1,6 +1,5 @@ /* cx24110 - Single Chip Satellite Channel Receiver driver module - used on the the Pinnacle PCTV Sat cards Copyright (C) 2002 Peter Hettkamp based on work @@ -23,46 +22,36 @@ */ -/* currently drives the Conexant cx24110 and cx24106 QPSK decoder chips, - connected via i2c to a Conexant Fusion 878 (this uses the standard - linux bttv driver). The tuner chip is supposed to be the Conexant - cx24108 digital satellite tuner, driven through the tuner interface - of the cx24110. SEC is also supplied by the cx24110. - - Oct-2002: Migrate to API V3 (formerly known as NEWSTRUCT) -*/ - #include #include #include +#include #include #include "dvb_frontend.h" -#include "dvb_functions.h" - -static int debug = 0; -#define dprintk if (debug) printk - - -static struct dvb_frontend_info cx24110_info = { - .name = "Conexant CX24110 with CX24108 tuner, aka HM1221/HM1811", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 1011, /* kHz for QPSK frontends, can be reduced - to 253kHz on the cx24108 tuner */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_RECOVER +#include "cx24110.h" + + +struct cx24110_state { + + struct i2c_adapter* i2c; + + struct dvb_frontend_ops ops; + + const struct cx24110_config* config; + + struct dvb_frontend frontend; + + u32 lastber; + u32 lastbler; + u32 lastesn0; }; -/* fixme: are these values correct? especially ..._tolerance and caps */ +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "cx24110: " args); \ + } while (0) static struct {u8 reg; u8 data;} cx24110_regdata[]= /* Comments beginning with @ denote this value should @@ -127,16 +116,15 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]= }; -static int cx24110_writereg (struct dvb_i2c_bus *i2c, int reg, int data) +static int cx24110_writereg (struct cx24110_state* state, int reg, int data) { u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 }; -/* fixme (medium): HW allows any i2c address. 0x55 is the default, but the - cx24110 might show up at any address */ + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; int err; - if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { - dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { + dprintk ("%s: writereg error (err == %i, reg == 0x%02x," + " data == 0x%02x)\n", __FUNCTION__, err, reg, data); return -EREMOTEIO; } @@ -144,161 +132,46 @@ static int cx24110_writereg (struct dvb_i2c_bus *i2c, int reg, int data) } -static u8 cx24110_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static int cx24110_readreg (struct cx24110_state* state, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, - { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; -/* fixme (medium): address might be different from 0x55 */ - ret = i2c->xfer (i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return b1[0]; -} - - -static int cx24108_write (struct dvb_i2c_bus *i2c, u32 data) -{ -/* tuner data is 21 bits long, must be left-aligned in data */ -/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ -/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ - -dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); - - cx24110_writereg(i2c,0x6d,0x30); /* auto mode at 62kHz */ - cx24110_writereg(i2c,0x70,0x15); /* auto mode 21 bits */ - /* if the auto tuner writer is still busy, clear it out */ - while (cx24110_readreg(i2c,0x6d)&0x80) - cx24110_writereg(i2c,0x72,0); - /* write the topmost 8 bits */ - cx24110_writereg(i2c,0x72,(data>>24)&0xff); - /* wait for the send to be completed */ - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* send another 8 bytes */ - cx24110_writereg(i2c,0x72,(data>>16)&0xff); - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* and the topmost 5 bits of this byte */ - cx24110_writereg(i2c,0x72,(data>>8)&0xff); - while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) - ; - /* now strobe the enable line once */ - cx24110_writereg(i2c,0x6d,0x32); - cx24110_writereg(i2c,0x6d,0x30); - - return 0; -} - - -static int cx24108_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) -{ -/* fixme (low): error handling */ - int i, a, n, pump; - u32 band, pll; - - - static const u32 osci[]={ 950000,1019000,1075000,1178000, - 1296000,1432000,1576000,1718000, - 1856000,2036000,2150000}; - static const u32 bandsel[]={0,0x00020000,0x00040000,0x00100800, - 0x00101000,0x00102000,0x00104000, - 0x00108000,0x00110000,0x00120000, - 0x00140000}; - -#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ - dprintk("cx24110 debug: cx24108_set_tv_freq, freq=%d\n",freq); - - if (freq<950000) - freq=950000; /* kHz */ - if (freq>2150000) - freq=2150000; /* satellite IF is 950..2150MHz */ - /* decide which VCO to use for the input frequency */ - for (i=1;(iconfig->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - dprintk("%s: init chip\n", __FUNCTION__); + ret = i2c_transfer(state->i2c, msg, 2); - for(i=0;i0) { - cx24110_writereg(i2c,0x05,(cx24110_readreg(i2c,0x05)&0xf0)|rate[fec]); + cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]); /* set nominal Viterbi rate */ - cx24110_writereg(i2c,0x22,(cx24110_readreg(i2c,0x22)&0xf0)|rate[fec]); + cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]); /* set current Viterbi rate */ - cx24110_writereg(i2c,0x1a,g1[fec]); - cx24110_writereg(i2c,0x1b,g2[fec]); + cx24110_writereg(state,0x1a,g1[fec]); + cx24110_writereg(state,0x1b,g2[fec]); /* not sure if this is the right way: I always used AutoAcq mode */ } else return -EOPNOTSUPP; @@ -355,11 +228,11 @@ static int cx24110_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) } -static fe_code_rate_t cx24110_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state) { int i; - i=cx24110_readreg(i2c,0x22)&0x0f; + i=cx24110_readreg(state,0x22)&0x0f; if(!(i&0x08)) { return FEC_1_2 + i - 1; } else { @@ -372,16 +245,13 @@ static fe_code_rate_t cx24110_get_fec (struct dvb_i2c_bus *i2c) } -static int cx24110_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) { /* fixme (low): add error handling */ u32 ratio; u32 tmp, fclk, BDRI; static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; - static const u32 vca[]={0x80f03800,0x81f0f800,0x83f1f800}; - static const u32 vga[]={0x5f8fc000,0x580f0000,0x500c0000}; - static const u8 filtune[]={0xa2,0xcc,0x66}; int i; dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); @@ -395,22 +265,22 @@ dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, R06[3:0] PLLphaseDetGain */ - tmp=cx24110_readreg(i2c,0x07)&0xfc; + tmp=cx24110_readreg(state,0x07)&0xfc; if(srate<90999000UL/4) { /* sample rate 45MHz*/ - cx24110_writereg(i2c,0x07,tmp); - cx24110_writereg(i2c,0x06,0x78); + cx24110_writereg(state,0x07,tmp); + cx24110_writereg(state,0x06,0x78); fclk=90999000UL/2; } else if(srate<60666000UL/2) { /* sample rate 60MHz */ - cx24110_writereg(i2c,0x07,tmp|0x1); - cx24110_writereg(i2c,0x06,0xa5); + cx24110_writereg(state,0x07,tmp|0x1); + cx24110_writereg(state,0x06,0xa5); fclk=60666000UL; } else if(srate<80888000UL/2) { /* sample rate 80MHz */ - cx24110_writereg(i2c,0x07,tmp|0x2); - cx24110_writereg(i2c,0x06,0x87); + cx24110_writereg(state,0x07,tmp|0x2); + cx24110_writereg(state,0x06,0x87); fclk=80888000UL; } else { /* sample rate 90MHz */ - cx24110_writereg(i2c,0x07,tmp|0x3); - cx24110_writereg(i2c,0x06,0x78); + cx24110_writereg(state,0x07,tmp|0x3); + cx24110_writereg(state,0x06,0x78); fclk=90999000UL; }; dprintk("cx24110 debug: fclk %d Hz\n",fclk); @@ -439,62 +309,123 @@ dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); dprintk("fclk = %d\n", fclk); dprintk("ratio= %08x\n", ratio); - cx24110_writereg(i2c, 0x1, (ratio>>16)&0xff); - cx24110_writereg(i2c, 0x2, (ratio>>8)&0xff); - cx24110_writereg(i2c, 0x3, (ratio)&0xff); + cx24110_writereg(state, 0x1, (ratio>>16)&0xff); + cx24110_writereg(state, 0x2, (ratio>>8)&0xff); + cx24110_writereg(state, 0x3, (ratio)&0xff); + + return 0; + +} + + + + + + + + + + + + +int cx24110_pll_write (struct dvb_frontend* fe, u32 data) +{ + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + +/* tuner data is 21 bits long, must be left-aligned in data */ +/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ +/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ + + dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); + + cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */ + cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */ + + /* if the auto tuner writer is still busy, clear it out */ + while (cx24110_readreg(state,0x6d)&0x80) + cx24110_writereg(state,0x72,0); + + /* write the topmost 8 bits */ + cx24110_writereg(state,0x72,(data>>24)&0xff); + + /* wait for the send to be completed */ + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; + + /* send another 8 bytes */ + cx24110_writereg(state,0x72,(data>>16)&0xff); + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; - /* please see the cx24108 data sheet, this controls tuner gain - and bandwidth settings depending on the symbol rate */ - cx24108_write(i2c,vga[i]); - cx24108_write(i2c,vca[i]); /* gain is set on tuner chip */ - cx24110_writereg(i2c,0x56,filtune[i]); /* bw is contolled by filtune voltage */ + /* and the topmost 5 bits of this byte */ + cx24110_writereg(state,0x72,(data>>8)&0xff); + while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) + ; + + /* now strobe the enable line once */ + cx24110_writereg(state,0x6d,0x32); + cx24110_writereg(state,0x6d,0x30); return 0; +} + + + +static int cx24110_initfe(struct dvb_frontend* fe) +{ + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; +/* fixme (low): error handling */ + int i; + + dprintk("%s: init chip\n", __FUNCTION__); + for(i=0;iconfig->pll_init) state->config->pll_init(fe); + + return 0; } -static int cx24110_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + switch (voltage) { case SEC_VOLTAGE_13: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0xc0); + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0); case SEC_VOLTAGE_18: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0x40); + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40); default: return -EINVAL; }; } -static void sendDiSEqCMessage(struct dvb_i2c_bus *i2c, struct dvb_diseqc_master_cmd *pCmd) +static int cx24110_send_diseqc_msg(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *cmd) { int i, rv; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - for (i = 0; i < pCmd->msg_len; i++) - cx24110_writereg(i2c, 0x79 + i, pCmd->msg[i]); + for (i = 0; i < cmd->msg_len; i++) + cx24110_writereg(state, 0x79 + i, cmd->msg[i]); - rv = cx24110_readreg(i2c, 0x76); + rv = cx24110_readreg(state, 0x76); - cx24110_writereg(i2c, 0x76, ((rv & 0x90) | 0x40) | ((pCmd->msg_len-3) & 3)); - for (i=500; i-- > 0 && !(cx24110_readreg(i2c,0x76)&0x40);) + cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); + for (i=500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40);) ; /* wait for LNB ready */ -} + return 0; +} -static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct dvb_i2c_bus *i2c = fe->i2c; - static int lastber=0, lastbyer=0,lastbler=0, lastesn0=0, sum_bler=0; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &cx24110_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: - { - fe_status_t *status = arg; - int sync = cx24110_readreg (i2c, 0x55); + int sync = cx24110_readreg (state, 0x55); *status = 0; @@ -504,7 +435,7 @@ static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if (sync & 0x08) *status |= FE_HAS_CARRIER; - sync = cx24110_readreg (i2c, 0x08); + sync = cx24110_readreg (state, 0x08); if (sync & 0x40) *status |= FE_HAS_VITERBI; @@ -515,87 +446,97 @@ static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if ((sync & 0x60) == 0x60) *status |= FE_HAS_LOCK; - if(cx24110_readreg(i2c,0x10)&0x40) { - /* the RS error counter has finished one counting window */ - cx24110_writereg(i2c,0x10,0x60); /* select the byer reg */ - lastbyer=cx24110_readreg(i2c,0x12)| - (cx24110_readreg(i2c,0x13)<<8)| - (cx24110_readreg(i2c,0x14)<<16); - cx24110_writereg(i2c,0x10,0x70); /* select the bler reg */ - lastbler=cx24110_readreg(i2c,0x12)| - (cx24110_readreg(i2c,0x13)<<8)| - (cx24110_readreg(i2c,0x14)<<16); - cx24110_writereg(i2c,0x10,0x20); /* start new count window */ - sum_bler += lastbler; - } - if(cx24110_readreg(i2c,0x24)&0x10) { - /* the Viterbi error counter has finished one counting window */ - cx24110_writereg(i2c,0x24,0x04); /* select the ber reg */ - lastber=cx24110_readreg(i2c,0x25)| - (cx24110_readreg(i2c,0x26)<<8); - cx24110_writereg(i2c,0x24,0x04); /* start new count window */ - cx24110_writereg(i2c,0x24,0x14); - } - if(cx24110_readreg(i2c,0x6a)&0x80) { - /* the Es/N0 error counter has finished one counting window */ - lastesn0=cx24110_readreg(i2c,0x69)| - (cx24110_readreg(i2c,0x68)<<8); - cx24110_writereg(i2c,0x6a,0x84); /* start new count window */ - } - break; + return 0; } - case FE_READ_BER: +static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - *ber = lastber; /* fixme (maybe): value range is 16 bit. Scale? */ - break; + if(cx24110_readreg(state,0x24)&0x10) { + /* the Viterbi error counter has finished one counting window */ + cx24110_writereg(state,0x24,0x04); /* select the ber reg */ + state->lastber=cx24110_readreg(state,0x25)| + (cx24110_readreg(state,0x26)<<8); + cx24110_writereg(state,0x24,0x04); /* start new count window */ + cx24110_writereg(state,0x24,0x14); } + *ber = state->lastber; - case FE_READ_SIGNAL_STRENGTH: + return 0; + } + +static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + /* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */ - u8 signal = cx24110_readreg (i2c, 0x27)+128; - *((u16*) arg) = (signal << 8) | signal; - break; + u8 signal = cx24110_readreg (state, 0x27)+128; + *signal_strength = (signal << 8) | signal; + + return 0; } - case FE_READ_SNR: +static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr) { + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + /* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */ - *(u16*) arg = lastesn0; - break; + if(cx24110_readreg(state,0x6a)&0x80) { + /* the Es/N0 error counter has finished one counting window */ + state->lastesn0=cx24110_readreg(state,0x69)| + (cx24110_readreg(state,0x68)<<8); + cx24110_writereg(state,0x6a,0x84); /* start new count window */ } + *snr = state->lastesn0; - case FE_READ_UNCORRECTED_BLOCKS: + return 0; + } + +static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - *(u16*) arg = sum_bler&0xffff; - sum_bler=0; - break; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; + u32 lastbyer; + + if(cx24110_readreg(state,0x10)&0x40) { + /* the RS error counter has finished one counting window */ + cx24110_writereg(state,0x10,0x60); /* select the byer reg */ + lastbyer=cx24110_readreg(state,0x12)| + (cx24110_readreg(state,0x13)<<8)| + (cx24110_readreg(state,0x14)<<16); + cx24110_writereg(state,0x10,0x70); /* select the bler reg */ + state->lastbler=cx24110_readreg(state,0x12)| + (cx24110_readreg(state,0x13)<<8)| + (cx24110_readreg(state,0x14)<<16); + cx24110_writereg(state,0x10,0x20); /* start new count window */ } + *ucblocks = state->lastbler; - case FE_SET_FRONTEND: + return 0; +} + +static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - cx24108_set_tv_freq (i2c, p->frequency); - cx24110_set_inversion (i2c, p->inversion); - cx24110_set_fec (i2c, p->u.qpsk.fec_inner); - cx24110_set_symbolrate (i2c, p->u.qpsk.symbol_rate); - cx24110_writereg(i2c,0x04,0x05); /* start aquisition */ - break; + state->config->pll_set(fe, p); + cx24110_set_inversion (state, p->inversion); + cx24110_set_fec (state, p->u.qpsk.fec_inner); + cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate); + cx24110_writereg(state,0x04,0x05); /* start aquisition */ + + return 0; } - case FE_GET_FRONTEND: +static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; s32 afc; unsigned sclk; /* cannot read back tuner settings (freq). Need to have some private storage */ - sclk = cx24110_readreg (i2c, 0x07) & 0x03; + sclk = cx24110_readreg (state, 0x07) & 0x03; /* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz. * Need 64 bit arithmetic. Is thiss possible in the kernel? */ if (sclk==0) sclk=90999000L/2L; @@ -603,76 +544,104 @@ static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) else if (sclk==2) sclk=80888000L; else sclk=90999000L; sclk>>=8; - afc = sclk*(cx24110_readreg (i2c, 0x44)&0x1f)+ - ((sclk*cx24110_readreg (i2c, 0x45))>>8)+ - ((sclk*cx24110_readreg (i2c, 0x46))>>16); + afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+ + ((sclk*cx24110_readreg (state, 0x45))>>8)+ + ((sclk*cx24110_readreg (state, 0x46))>>16); p->frequency += afc; - p->inversion = (cx24110_readreg (i2c, 0x22) & 0x10) ? + p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = cx24110_get_fec (i2c); - break; - } - - case FE_SLEEP: -/* cannot do this from the FE end. How to communicate this to the place where it can be done? */ - break; - case FE_INIT: - return cx24110_init (i2c); - - case FE_SET_TONE: - return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&~0x10)|((((fe_sec_tone_mode_t) arg)==SEC_TONE_ON)?0x10:0)); - case FE_SET_VOLTAGE: - return cx24110_set_voltage (i2c, (fe_sec_voltage_t) arg); - - case FE_DISEQC_SEND_MASTER_CMD: - sendDiSEqCMessage(i2c, (struct dvb_diseqc_master_cmd*) arg); - return 0; - - default: - return -EOPNOTSUPP; - }; + p->u.qpsk.fec_inner = cx24110_get_fec (state); return 0; } - -static int cx24110_attach (struct dvb_i2c_bus *i2c, void **data) +static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - u8 sig; - - sig=cx24110_readreg (i2c, 0x00); - if ( sig != 0x5a && sig != 0x69 ) - return -ENODEV; + struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv; - return dvb_register_frontend (cx24110_ioctl, i2c, NULL, &cx24110_info); + return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0)); } - -static void cx24110_detach (struct dvb_i2c_bus *i2c, void *data) +static void cx24110_release(struct dvb_frontend* fe) { - dvb_unregister_frontend (cx24110_ioctl, i2c); + struct cx24110_state* state = (struct cx24110_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops cx24110_ops; -static int __init init_cx24110 (void) +struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, + struct i2c_adapter* i2c) { - return dvb_register_i2c_device (THIS_MODULE, cx24110_attach, cx24110_detach); -} - + struct cx24110_state* state = NULL; + int ret; -static void __exit exit_cx24110 (void) -{ - dvb_unregister_i2c_device (cx24110_attach); + /* allocate memory for the internal state */ + state = (struct cx24110_state*) kmalloc(sizeof(struct cx24110_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops)); + state->lastber = 0; + state->lastbler = 0; + state->lastesn0 = 0; + + /* check if the demod is there */ + ret = cx24110_readreg(state, 0x00); + if ((ret != 0x5a) && (ret != 0x69)) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops cx24110_ops = { + + .info = { + .name = "Conexant CX24110 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_RECOVER + }, + + .release = cx24110_release, + + .init = cx24110_initfe, + .set_frontend = cx24110_set_frontend, + .get_frontend = cx24110_get_frontend, + .read_status = cx24110_read_status, + .read_ber = cx24110_read_ber, + .read_signal_strength = cx24110_read_signal_strength, + .read_snr = cx24110_read_snr, + .read_ucblocks = cx24110_read_ucblocks, + + .diseqc_send_master_cmd = cx24110_send_diseqc_msg, + .set_tone = cx24110_set_tone, + .set_voltage = cx24110_set_voltage, +}; -module_init(init_cx24110); -module_exit(exit_cx24110); - +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("DVB Frontend driver module for the Conexant cx24108/cx24110 chipset"); +MODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver"); MODULE_AUTHOR("Peter Hettkamp"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); +EXPORT_SYMBOL(cx24110_attach); +EXPORT_SYMBOL(cx24110_pll_write); diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index 6d9e6108e..b17a19526 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -20,186 +20,262 @@ */ #include +#include #include #include "dvb_frontend.h" +#include "dvb_dummy_fe.h" -static int sct = 0; - - -/* depending on module parameter sct deliver different infos - */ - -static struct dvb_frontend_info dvb_s_dummyfe_info = { - .name = "DVB-S dummy frontend", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 250, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK -}; -static struct dvb_frontend_info dvb_c_dummyfe_info = { - .name = "DVB-C dummy frontend", - .type = FE_QAM, - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, - .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ -#if 0 - .frequency_tolerance = ???, - .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ - .notifier_delay = ?, -#endif - .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO -}; -static struct dvb_frontend_info dvb_t_dummyfe_info = { - .name = "DVB-T dummy frontend", - .type = FE_OFDM, - .frequency_min = 0, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - -struct dvb_frontend_info *frontend_info(void) -{ - switch(sct) - { - case 2: - return &dvb_t_dummyfe_info; - case 1: - return &dvb_c_dummyfe_info; - case 0: - default: - return &dvb_s_dummyfe_info; - } -} +struct dvb_dummy_fe_state { + struct dvb_frontend_ops ops; -static int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, frontend_info(), - sizeof(struct dvb_frontend_info)); - break; + struct dvb_frontend frontend; +}; - case FE_READ_STATUS: +static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) { - fe_status_t *status = arg; *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - break; + + return 0; } - case FE_READ_BER: +static int dvb_dummy_fe_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; *ber = 0; - break; + return 0; } - case FE_READ_SIGNAL_STRENGTH: +static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 signal = 0xff; - *((u16*) arg) = (signal << 8) | signal; - break; + *strength = 0; + return 0; } - case FE_READ_SNR: +static int dvb_dummy_fe_read_snr(struct dvb_frontend* fe, u16* snr) { - u8 snr = 0xf0; - *(u16*) arg = (snr << 8) | snr; - break; + *snr = 0; + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: - *(u32*) arg = 0; - break; - - case FE_SET_FRONTEND: - break; - - case FE_GET_FRONTEND: - break; - - case FE_SLEEP: +static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + *ucblocks = 0; return 0; +} - case FE_INIT: +static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ return 0; +} - case FE_SET_TONE: - return -EOPNOTSUPP; +static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + return 0; +} - case FE_SET_VOLTAGE: +static int dvb_dummy_fe_sleep(struct dvb_frontend* fe) +{ return 0; +} - default: - return -EOPNOTSUPP; +static int dvb_dummy_fe_init(struct dvb_frontend* fe) +{ + return 0; } + +static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ return 0; } +static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + return 0; +} -static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c, void **data) +static void dvb_dummy_fe_release(struct dvb_frontend* fe) { - return dvb_register_frontend (dvbdummyfe_ioctl, i2c, NULL, frontend_info()); + struct dvb_dummy_fe_state* state = (struct dvb_dummy_fe_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops; -static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c, void *data) +struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void) { - dvb_unregister_frontend (dvbdummyfe_ioctl, i2c); + struct dvb_dummy_fe_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; -static int __init init_dvbdummyfe (void) +struct dvb_frontend* dvb_dummy_fe_qpsk_attach() { - return dvb_register_i2c_device (THIS_MODULE, - dvbdummyfe_attach, - dvbdummyfe_detach); + struct dvb_dummy_fe_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; -static void __exit exit_dvbdummyfe (void) +struct dvb_frontend* dvb_dummy_fe_qam_attach() { - dvb_unregister_i2c_device (dvbdummyfe_attach); + struct dvb_dummy_fe_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { + + .info = { + .name = "Dummy DVB-T", + .type = FE_OFDM, + .frequency_min = 0, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, +}; -module_init(init_dvbdummyfe); -module_exit(exit_dvbdummyfe); +static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = { + + .info = { + .name = "Dummy DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ + .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ + .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | + FE_CAN_QAM_128 | FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, +}; +static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = { + + .info = { + .name = "Dummy DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 250, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK + }, + + .release = dvb_dummy_fe_release, + + .init = dvb_dummy_fe_init, + .sleep = dvb_dummy_fe_sleep, + + .set_frontend = dvb_dummy_fe_set_frontend, + .get_frontend = dvb_dummy_fe_get_frontend, + + .read_status = dvb_dummy_fe_read_status, + .read_ber = dvb_dummy_fe_read_ber, + .read_signal_strength = dvb_dummy_fe_read_signal_strength, + .read_snr = dvb_dummy_fe_read_snr, + .read_ucblocks = dvb_dummy_fe_read_ucblocks, + + .set_voltage = dvb_dummy_fe_set_voltage, + .set_tone = dvb_dummy_fe_set_tone, +}; MODULE_DESCRIPTION("DVB DUMMY Frontend"); MODULE_AUTHOR("Emard"); MODULE_LICENSE("GPL"); -MODULE_PARM(sct, "i"); + +EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach); +EXPORT_SYMBOL(dvb_dummy_fe_qam_attach); +EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach); diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index b3d5ddf80..a5dcc8766 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -1,5 +1,5 @@ /* - Driver for Zarlink MT312 Satellite Channel Decoder + Driver for Zarlink VP310/MT312 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter @@ -28,236 +28,235 @@ #include #include #include +#include #include "dvb_frontend.h" +#include "mt312_priv.h" #include "mt312.h" -#define I2C_ADDR_MT312 0x0e -#define I2C_ADDR_SL1935 0x61 -#define I2C_ADDR_TSA5059 0x61 -#define MT312_DEBUG 0 +struct mt312_state { + + struct i2c_adapter* i2c; + + struct dvb_frontend_ops ops; + + /* configuration settings */ + const struct mt312_config* config; + + struct dvb_frontend frontend; + + u8 id; + u8 frequency; +}; + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "mt312: " args); \ + } while (0) #define MT312_SYS_CLK 90000000UL /* 90 MHz */ #define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */ #define MT312_PLL_CLK 10000000UL /* 10 MHz */ -/* number of active frontends */ -static int mt312_count = 0; - -#if MT312_DEBUG == 0 -#define dprintk(x...) -#else -static int debug = 0; -#define dprintk if(debug == 1) printk -#endif - -static struct dvb_frontend_info mt312_info = { - .name = "Zarlink MT312", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, - /*.frequency_tolerance = 29500, FIXME: binary compatibility waste? */ - .symbol_rate_min = MT312_SYS_CLK / 128, - .symbol_rate_max = MT312_SYS_CLK / 2, - /*.symbol_rate_tolerance = 500, FIXME: binary compatibility waste? 2% */ - .notifier_delay = 0, - .caps = - FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS | - FE_CAN_RECOVER -}; - -static int mt312_read(struct dvb_i2c_bus *i2c, - const enum mt312_reg_addr reg, void *buf, - const size_t count) +static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg, + void *buf, const size_t count) { int ret; struct i2c_msg msg[2]; u8 regbuf[1] = { reg }; - msg[0].addr = I2C_ADDR_MT312; + msg[0].addr = state->config->demod_address; msg[0].flags = 0; msg[0].buf = regbuf; msg[0].len = 1; - msg[1].addr = I2C_ADDR_MT312; + msg[1].addr = state->config->demod_address; msg[1].flags = I2C_M_RD; msg[1].buf = buf; msg[1].len = count; - ret = i2c->xfer(i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); - if ((ret != 2) && (mt312_count != 0)) { + if (ret != 2) { printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); return -EREMOTEIO; } -#if MT312_DEBUG + if(debug) { int i; - printk(KERN_INFO "R(%d):", reg & 0x7f); + dprintk("R(%d):", reg & 0x7f); for (i = 0; i < count; i++) printk(" %02x", ((const u8 *) buf)[i]); printk("\n"); } -#endif return 0; } -static int mt312_write(struct dvb_i2c_bus *i2c, - const enum mt312_reg_addr reg, const void *src, - const size_t count) +static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg, + const void *src, const size_t count) { int ret; u8 buf[count + 1]; struct i2c_msg msg; -#if MT312_DEBUG if(debug) { int i; - printk(KERN_INFO "W(%d):", reg & 0x7f); + dprintk("W(%d):", reg & 0x7f); for (i = 0; i < count; i++) printk(" %02x", ((const u8 *) src)[i]); printk("\n"); } -#endif buf[0] = reg; memcpy(&buf[1], src, count); - msg.addr = I2C_ADDR_MT312; + msg.addr = state->config->demod_address; msg.flags = 0; msg.buf = buf; msg.len = count + 1; - ret = i2c->xfer(i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) { - printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); + dprintk("%s: ret == %d\n", __FUNCTION__, ret); return -EREMOTEIO; } return 0; } -static inline int mt312_readreg(struct dvb_i2c_bus *i2c, +static inline int mt312_readreg(struct mt312_state* state, const enum mt312_reg_addr reg, u8 * val) { - return mt312_read(i2c, reg, val, 1); + return mt312_read(state, reg, val, 1); } -static inline int mt312_writereg(struct dvb_i2c_bus *i2c, +static inline int mt312_writereg(struct mt312_state* state, const enum mt312_reg_addr reg, const u8 val) { - return mt312_write(i2c, reg, &val, 1); + return mt312_write(state, reg, &val, 1); } -static int mt312_pll_write(struct dvb_i2c_bus *i2c, const u8 addr, - u8 * buf, const u8 len) +static inline u32 mt312_div(u32 a, u32 b) +{ + return (a + (b / 2)) / b; +} + +static int mt312_reset(struct mt312_state* state, const u8 full) +{ + return mt312_writereg(state, RESET, full ? 0x80 : 0x40); +} + +static int mt312_get_inversion(struct mt312_state* state, + fe_spectral_inversion_t *i) { int ret; - struct i2c_msg msg; + u8 vit_mode; - msg.addr = addr; - msg.flags = 0; - msg.buf = buf; - msg.len = len; + if ((ret = mt312_readreg(state, VIT_MODE, &vit_mode)) < 0) + return ret; - if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x40)) < 0) + if (vit_mode & 0x80) /* auto inversion was used */ + *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; + + return 0; +} + +static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr) +{ + int ret; + u8 sym_rate_h; + u8 dec_ratio; + u16 sym_rat_op; + u16 monitor; + u8 buf[2]; + + if ((ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h)) < 0) return ret; - if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) - printk(KERN_ERR "%s: i/o error (ret == %d)\n", __FUNCTION__, ret); + if (sym_rate_h & 0x80) { /* symbol rate search was used */ + if ((ret = mt312_writereg(state, MON_CTRL, 0x03)) < 0) + return ret; - if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x00)) < 0) + if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0) return ret; - return 0; + monitor = (buf[0] << 8) | buf[1]; + + dprintk(KERN_DEBUG "sr(auto) = %u\n", + mt312_div(monitor * 15625, 4)); + } else { + if ((ret = mt312_writereg(state, MON_CTRL, 0x05)) < 0) + return ret; + + if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0) + return ret; + + dec_ratio = ((buf[0] >> 5) & 0x07) * 32; + + if ((ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf))) < 0) + return ret; + + sym_rat_op = (buf[0] << 8) | buf[1]; + + dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n", + sym_rat_op, dec_ratio); + dprintk(KERN_DEBUG "*sr(manual) = %lu\n", + (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * + 2) - dec_ratio); } -static inline u32 mt312_div(u32 a, u32 b) -{ - return (a + (b / 2)) / b; + return 0; } -static int sl1935_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr) +static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr) { - /* 155 uA, Baseband Path B */ - u8 buf[4] = { 0x00, 0x00, 0x80, 0x00 }; - - u8 exp; - u32 ref; - u32 div; - - if (sr < 10000000) { /* 1-10 MSym/s: ratio 2 ^ 3 */ - exp = 3; - buf[2] |= 0x40; /* 690 uA */ - } else if (sr < 15000000) { /* 10-15 MSym/s: ratio 2 ^ 4 */ - exp = 4; - buf[2] |= 0x20; /* 330 uA */ - } else { /* 15-45 MSym/s: ratio 2 ^ 7 */ - exp = 7; - buf[3] |= 0x08; /* Baseband Path A */ + const fe_code_rate_t fec_tab[8] = + { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, + FEC_AUTO, FEC_AUTO }; + + int ret; + u8 fec_status; + + if ((ret = mt312_readreg(state, FEC_STATUS, &fec_status)) < 0) + return ret; + + *cr = fec_tab[(fec_status >> 4) & 0x07]; + + return 0; } - div = mt312_div(MT312_PLL_CLK, 1 << exp); - ref = mt312_div(freq * 1000, div); - mt312_info.frequency_stepsize = mt312_div(div, 1000); - buf[0] = (ref >> 8) & 0x7f; - buf[1] = (ref >> 0) & 0xff; - buf[2] |= (exp - 1); - if (freq < 1550000) - buf[3] |= 0x10; - dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], - buf[1], buf[2], buf[3]); - return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf)); -} -static int tsa5059_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr) -{ - u8 buf[4]; - u32 ref = mt312_div(freq, 125); - buf[0] = (ref >> 8) & 0x7f; - buf[1] = (ref >> 0) & 0xff; - buf[2] = 0x84 | ((ref >> 10) & 0x60); - buf[3] = 0x80; - if (freq < 1550000) - buf[3] |= 0x02; - dprintk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], - buf[1], buf[2], buf[3]); - return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf)); -} -static int mt312_reset(struct dvb_i2c_bus *i2c, const u8 full) -{ - return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40); -} -static int mt312_init(struct dvb_i2c_bus *i2c, const long id, u8 pll) + + +static int mt312_initfe(struct dvb_frontend* fe) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; /* wake up */ - if ((ret = mt312_writereg(i2c, CONFIG, (pll == 60 ? 0x88 : 0x8c))) < 0) + if ((ret = mt312_writereg(state, CONFIG, (state->frequency == 60 ? 0x88 : 0x8c))) < 0) return ret; /* wait at least 150 usec */ udelay(150); /* full reset */ - if ((ret = mt312_reset(i2c, 1)) < 0) + if ((ret = mt312_reset(state, 1)) < 0) return ret; // Per datasheet, write correct values. 09/28/03 ACCJr. @@ -265,56 +264,63 @@ static int mt312_init(struct dvb_i2c_bus *i2c, const long id, u8 pll) { u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00}; - if ((ret = mt312_write(i2c, VIT_SETUP, buf_def, sizeof(buf_def))) < 0) + if ((ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def))) < 0) return ret; } /* SYS_CLK */ - buf[0] = mt312_div((pll == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000); + buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000); /* DISEQC_RATIO */ buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4); - if ((ret = mt312_write(i2c, SYS_CLK, buf, sizeof(buf))) < 0) + if ((ret = mt312_write(state, SYS_CLK, buf, sizeof(buf))) < 0) return ret; - if ((ret = mt312_writereg(i2c, SNR_THS_HIGH, 0x32)) < 0) + if ((ret = mt312_writereg(state, SNR_THS_HIGH, 0x32)) < 0) return ret; - if ((ret = mt312_writereg(i2c, OP_CTRL, 0x53)) < 0) + if ((ret = mt312_writereg(state, OP_CTRL, 0x53)) < 0) return ret; /* TS_SW_LIM */ buf[0] = 0x8c; buf[1] = 0x98; - if ((ret = mt312_write(i2c, TS_SW_LIM_L, buf, sizeof(buf))) < 0) + if ((ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf))) < 0) return ret; - if ((ret = mt312_writereg(i2c, CS_SW_LIM, 0x69)) < 0) + if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0) return ret; + if (state->config->pll_init) { + mt312_writereg(state, GPP_CTRL, 0x40); + state->config->pll_init(fe); + mt312_writereg(state, GPP_CTRL, 0x00); + } + return 0; } -static int mt312_send_master_cmd(struct dvb_i2c_bus *i2c, - const struct dvb_diseqc_master_cmd *c) +static int mt312_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *c) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 diseqc_mode; if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg))) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_write(i2c, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0) + mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3) | 0x04)) < 0) return ret; @@ -322,21 +328,15 @@ static int mt312_send_master_cmd(struct dvb_i2c_bus *i2c, /* set DISEQC_MODE[2:0] to zero if a return message is expected */ if (c->msg[0] & 0x02) if ((ret = - mt312_writereg(i2c, DISEQC_MODE, (diseqc_mode & 0x40))) < 0) + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40))) < 0) return ret; return 0; } -static int mt312_recv_slave_reply(struct dvb_i2c_bus *i2c, - struct dvb_diseqc_slave_reply *r) -{ - /* TODO */ - return -EOPNOTSUPP; -} - -static int mt312_send_burst(struct dvb_i2c_bus *i2c, const fe_sec_mini_cmd_t c) +static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 mini_tab[2] = { 0x02, 0x03 }; int ret; @@ -345,19 +345,20 @@ static int mt312_send_burst(struct dvb_i2c_bus *i2c, const fe_sec_mini_cmd_t c) if (c > SEC_MINI_B) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | mini_tab[c])) < 0) return ret; return 0; } -static int mt312_set_tone(struct dvb_i2c_bus *i2c, const fe_sec_tone_mode_t t) +static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 tone_tab[2] = { 0x01, 0x00 }; int ret; @@ -366,35 +367,37 @@ static int mt312_set_tone(struct dvb_i2c_bus *i2c, const fe_sec_tone_mode_t t) if (t > SEC_TONE_OFF) return -EINVAL; - if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0) return ret; if ((ret = - mt312_writereg(i2c, DISEQC_MODE, + mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) | tone_tab[t])) < 0) return ret; return 0; } -static int mt312_set_voltage(struct dvb_i2c_bus *i2c, const fe_sec_voltage_t v) +static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; if (v > SEC_VOLTAGE_OFF) return -EINVAL; - return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]); + return mt312_writereg(state, DISEQC_MODE, volt_tab[v]); } -static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s, const long id) +static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; - u8 status[3], vit_mode; + u8 status[3]; *s = 0; - if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0) + if ((ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status))) < 0) return ret; dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]); @@ -409,26 +412,17 @@ static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t *s, const long *s |= FE_HAS_SYNC; /* byte align lock */ if (status[0] & 0x01) *s |= FE_HAS_LOCK; /* qpsk lock */ - // VP310 doesn't have AUTO, so we "implement it here" ACCJr - if ((id == ID_VP310) && !(status[0] & 0x01)) { - if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0) - return ret; - vit_mode ^= 0x40; - if ((ret = mt312_writereg(i2c, VIT_MODE, vit_mode)) < 0) - return ret; - if ((ret = mt312_writereg(i2c, GO, 0x01)) < 0) - return ret; - } return 0; } -static int mt312_read_bercnt(struct dvb_i2c_bus *i2c, u32 * ber) +static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[3]; - if ((ret = mt312_read(i2c, RS_BERCNT_H, buf, 3)) < 0) + if ((ret = mt312_read(state, RS_BERCNT_H, buf, 3)) < 0) return ret; *ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64; @@ -436,14 +430,15 @@ static int mt312_read_bercnt(struct dvb_i2c_bus *i2c, u32 * ber) return 0; } -static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 * signal_strength) +static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_strength) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[3]; u16 agc; s16 err_db; - if ((ret = mt312_read(i2c, AGC_H, buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, AGC_H, buf, sizeof(buf))) < 0) return ret; agc = (buf[0] << 6) | (buf[1] >> 2); @@ -456,12 +451,13 @@ static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 * signal_strength) return 0; } -static int mt312_read_snr(struct dvb_i2c_bus *i2c, u16 * snr) +static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; - if ((ret = mt312_read(i2c, M_SNR_H, &buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf))) < 0) return ret; *snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1); @@ -469,12 +465,13 @@ static int mt312_read_snr(struct dvb_i2c_bus *i2c, u16 * snr) return 0; } -static int mt312_read_ubc(struct dvb_i2c_bus *i2c, u32 * ubc) +static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[2]; - if ((ret = mt312_read(i2c, RS_UBC_H, &buf, sizeof(buf))) < 0) + if ((ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf))) < 0) return ret; *ubc = (buf[0] << 8) | buf[1]; @@ -482,10 +479,10 @@ static int mt312_read_ubc(struct dvb_i2c_bus *i2c, u32 * ubc) return 0; } -static int mt312_set_frontend(struct dvb_i2c_bus *i2c, - const struct dvb_frontend_parameters *p, - const long id) +static int mt312_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 buf[5], config_val; u16 sr; @@ -494,20 +491,18 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c, { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; - int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr); - dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); - if ((p->frequency < mt312_info.frequency_min) - || (p->frequency > mt312_info.frequency_max)) + if ((p->frequency < fe->ops->info.frequency_min) + || (p->frequency > fe->ops->info.frequency_max)) return -EINVAL; if ((p->inversion < INVERSION_OFF) - || (p->inversion > INVERSION_AUTO)) + || (p->inversion > INVERSION_ON)) return -EINVAL; - if ((p->u.qpsk.symbol_rate < mt312_info.symbol_rate_min) - || (p->u.qpsk.symbol_rate > mt312_info.symbol_rate_max)) + if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min) + || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max)) return -EINVAL; if ((p->u.qpsk.fec_inner < FEC_NONE) @@ -518,35 +513,40 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c, || (p->u.qpsk.fec_inner == FEC_8_9)) return -EINVAL; - switch (id) { + switch (state->id) { case ID_VP310: // For now we will do this only for the VP310. // It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03 - if ((ret = mt312_readreg(i2c, CONFIG, &config_val) < 0)) + if ((ret = mt312_readreg(state, CONFIG, &config_val) < 0)) return ret; if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz { - if ((config_val & 0x0c) == 0x08) //We are running 60MHz - if ((ret = mt312_init(i2c, id, (u8) 90)) < 0) + if ((config_val & 0x0c) == 0x08) { //We are running 60MHz + state->frequency = 90; + if ((ret = mt312_initfe(fe)) < 0) return ret; } + } else { - if ((config_val & 0x0c) == 0x0C) //We are running 90MHz - if ((ret = mt312_init(i2c, id, (u8) 60)) < 0) + if ((config_val & 0x0c) == 0x0C) { //We are running 90MHz + state->frequency = 60; + if ((ret = mt312_initfe(fe)) < 0) return ret; } - set_tv_freq = tsa5059_set_tv_freq; + } break; + case ID_MT312: - set_tv_freq = sl1935_set_tv_freq; break; + default: return -EINVAL; } - if ((ret = set_tv_freq(i2c, p->frequency, p->u.qpsk.symbol_rate)) < 0) - return ret; + mt312_writereg(state, GPP_CTRL, 0x40); + state->config->pll_set(fe, p); + mt312_writereg(state, GPP_CTRL, 0x00); /* sr = (u16)(sr * 256.0 / 1000000.0) */ sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625); @@ -567,259 +567,182 @@ static int mt312_set_frontend(struct dvb_i2c_bus *i2c, /* GO */ buf[4] = 0x01; - if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0) - return ret; - - mt312_reset(i2c, 0); - - return 0; -} - -static int mt312_get_inversion(struct dvb_i2c_bus *i2c, - fe_spectral_inversion_t * i) -{ - int ret; - u8 vit_mode; - - if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0) + if ((ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf))) < 0) return ret; - if (vit_mode & 0x80) /* auto inversion was used */ - *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; + mt312_reset(state, 0); return 0; } -static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 * sr) -{ - int ret; - u8 sym_rate_h; - u8 dec_ratio; - u16 sym_rat_op; - u16 monitor; - u8 buf[2]; - - if ((ret = mt312_readreg(i2c, SYM_RATE_H, &sym_rate_h)) < 0) - return ret; - - if (sym_rate_h & 0x80) { /* symbol rate search was used */ - if ((ret = mt312_writereg(i2c, MON_CTRL, 0x03)) < 0) - return ret; - - if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) - return ret; - - monitor = (buf[0] << 8) | buf[1]; - - dprintk(KERN_DEBUG "sr(auto) = %u\n", - mt312_div(monitor * 15625, 4)); - } else { - if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0) - return ret; - - if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) - return ret; - - dec_ratio = ((buf[0] >> 5) & 0x07) * 32; - - if ((ret = mt312_read(i2c, SYM_RAT_OP_H, buf, sizeof(buf))) < 0) - return ret; - - sym_rat_op = (buf[0] << 8) | buf[1]; - - dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n", - sym_rat_op, dec_ratio); - dprintk(KERN_DEBUG "*sr(manual) = %lu\n", - (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * - 2) - dec_ratio); - } - - return 0; -} - -static int mt312_get_code_rate(struct dvb_i2c_bus *i2c, fe_code_rate_t * cr) -{ - const fe_code_rate_t fec_tab[8] = - { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, - FEC_AUTO, FEC_AUTO }; - - int ret; - u8 fec_status; - - if ((ret = mt312_readreg(i2c, FEC_STATUS, &fec_status)) < 0) - return ret; - - *cr = fec_tab[(fec_status >> 4) & 0x07]; - - return 0; -} - -static int mt312_get_frontend(struct dvb_i2c_bus *i2c, +static int mt312_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; - if ((ret = mt312_get_inversion(i2c, &p->inversion)) < 0) + if ((ret = mt312_get_inversion(state, &p->inversion)) < 0) return ret; - if ((ret = mt312_get_symbol_rate(i2c, &p->u.qpsk.symbol_rate)) < 0) + if ((ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate)) < 0) return ret; - if ((ret = mt312_get_code_rate(i2c, &p->u.qpsk.fec_inner)) < 0) + if ((ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner)) < 0) return ret; return 0; } -static int mt312_sleep(struct dvb_i2c_bus *i2c) +static int mt312_sleep(struct dvb_frontend* fe) { + struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv; int ret; u8 config; /* reset all registers to defaults */ - if ((ret = mt312_reset(i2c, 1)) < 0) + if ((ret = mt312_reset(state, 1)) < 0) return ret; - if ((ret = mt312_readreg(i2c, CONFIG, &config)) < 0) + if ((ret = mt312_readreg(state, CONFIG, &config)) < 0) return ret; /* enter standby */ - if ((ret = mt312_writereg(i2c, CONFIG, config & 0x7f)) < 0) + if ((ret = mt312_writereg(state, CONFIG, config & 0x7f)) < 0) return ret; return 0; } -static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct dvb_i2c_bus *i2c = fe->i2c; - - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &mt312_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_DISEQC_RESET_OVERLOAD: - return -EOPNOTSUPP; - - case FE_DISEQC_SEND_MASTER_CMD: - return mt312_send_master_cmd(i2c, arg); - - case FE_DISEQC_RECV_SLAVE_REPLY: - if ((long) fe->data == ID_MT312) - return mt312_recv_slave_reply(i2c, arg); - else - return -EOPNOTSUPP; - - case FE_DISEQC_SEND_BURST: - return mt312_send_burst(i2c, (fe_sec_mini_cmd_t) arg); - - case FE_SET_TONE: - return mt312_set_tone(i2c, (fe_sec_tone_mode_t) arg); - - case FE_SET_VOLTAGE: - return mt312_set_voltage(i2c, (fe_sec_voltage_t) arg); - - case FE_ENABLE_HIGH_LNB_VOLTAGE: - return -EOPNOTSUPP; - - case FE_READ_STATUS: - return mt312_read_status(i2c, arg, (long) fe->data); - - case FE_READ_BER: - return mt312_read_bercnt(i2c, arg); - - case FE_READ_SIGNAL_STRENGTH: - return mt312_read_agc(i2c, arg); - - case FE_READ_SNR: - return mt312_read_snr(i2c, arg); - - case FE_READ_UNCORRECTED_BLOCKS: - return mt312_read_ubc(i2c, arg); - - case FE_SET_FRONTEND: - return mt312_set_frontend(i2c, arg, (long) fe->data); - - case FE_GET_FRONTEND: - return mt312_get_frontend(i2c, arg); - - case FE_GET_EVENT: - return -EOPNOTSUPP; - - case FE_SLEEP: - return mt312_sleep(i2c); - - case FE_INIT: - //For the VP310 we should run at 60MHz when ever possible. - //It should be better to run the mt312 ar lower speed when ever possible, but tunning will be slower. ACCJr 09/29/03 - if ((long)fe->data == ID_MT312) - return mt312_init(i2c, (long) fe->data, (u8) 90); - else - return mt312_init(i2c, (long) fe->data, (u8) 60); - - case FE_GET_TUNE_SETTINGS: +static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; fesettings->min_delay_ms = 50; fesettings->step_size = 0; fesettings->max_drift = 0; return 0; } - default: - return -ENOIOCTLCMD; - } - - return 0; -} - -static int mt312_attach(struct dvb_i2c_bus *i2c, void **data) +static void mt312_release(struct dvb_frontend* fe) { - int ret; - u8 id; - - if ((ret = mt312_readreg(i2c, ID, &id)) < 0) - return ret; + struct mt312_state* state = (struct mt312_state*) fe->demodulator_priv; + kfree(state); +} - if ((id != ID_VP310) && (id != ID_MT312)) - return -ENODEV; +static struct dvb_frontend_ops vp310_mt312_ops; - if ((ret = dvb_register_frontend(mt312_ioctl, i2c, - (void *)(long)id, &mt312_info)) < 0) - return ret; +struct dvb_frontend* vp310_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) +{ + struct mt312_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); + + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + if (state->id != ID_VP310) { + goto error; + } - mt312_count++; + /* create dvb_frontend */ + state->frequency = 90; + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - return 0; +error: + if (state) + kfree(state); + return NULL; } -static void mt312_detach(struct dvb_i2c_bus *i2c, void *data) +struct dvb_frontend* mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) { - dvb_unregister_frontend(mt312_ioctl, i2c); - - if (mt312_count) - mt312_count--; + struct mt312_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); + + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + if (state->id != ID_MT312) { + goto error; } -static int __init mt312_module_init(void) -{ - return dvb_register_i2c_device(THIS_MODULE, mt312_attach, mt312_detach); -} + /* create dvb_frontend */ + state->frequency = 60; + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; -static void __exit mt312_module_exit(void) -{ - dvb_unregister_i2c_device(mt312_attach); +error: + if (state) + kfree(state); + return NULL; } -module_init(mt312_module_init); -module_exit(mt312_module_exit); +static struct dvb_frontend_ops vp310_mt312_ops = { + + .info = { + .name = "Zarlink ???? DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, + .symbol_rate_min = MT312_SYS_CLK / 128, + .symbol_rate_max = MT312_SYS_CLK / 2, + .caps = + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS | + FE_CAN_RECOVER + }, + + .release = mt312_release, + + .init = mt312_initfe, + .sleep = mt312_sleep, + + .set_frontend = mt312_set_frontend, + .get_frontend = mt312_get_frontend, + .get_tune_settings = mt312_get_tune_settings, + + .read_status = mt312_read_status, + .read_ber = mt312_read_ber, + .read_signal_strength = mt312_read_signal_strength, + .read_snr = mt312_read_snr, + .read_ucblocks = mt312_read_ucblocks, + + .diseqc_send_master_cmd = mt312_send_master_cmd, + .diseqc_send_burst = mt312_send_burst, + .set_tone = mt312_set_tone, + .set_voltage = mt312_set_voltage, +}; -#if MT312_DEBUG != 0 -MODULE_PARM(debug,"i"); -MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#endif +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver"); +MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(mt312_attach); +EXPORT_SYMBOL(vp310_attach); diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index 222c6ecbd..1f58f0c9d 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -1,5 +1,5 @@ /* - Driver for Zarlink MT312 QPSK Frontend + Driver for Zarlink MT312 Satellite Channel Decoder Copyright (C) 2003 Andreas Oberritter @@ -18,145 +18,30 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + References: + http://products.zarlink.com/product_profiles/MT312.htm + http://products.zarlink.com/product_profiles/SL1935.htm */ -#ifndef _DVB_FRONTENDS_MT312 -#define _DVB_FRONTENDS_MT312 +#ifndef MT312_H +#define MT312_H -enum mt312_reg_addr { - QPSK_INT_H = 0, - QPSK_INT_M = 1, - QPSK_INT_L = 2, - FEC_INT = 3, - QPSK_STAT_H = 4, - QPSK_STAT_L = 5, - FEC_STATUS = 6, - LNB_FREQ_H = 7, - LNB_FREQ_L = 8, - M_SNR_H = 9, - M_SNR_L = 10, - VIT_ERRCNT_H = 11, - VIT_ERRCNT_M = 12, - VIT_ERRCNT_L = 13, - RS_BERCNT_H = 14, - RS_BERCNT_M = 15, - RS_BERCNT_L = 16, - RS_UBC_H = 17, - RS_UBC_L = 18, - SIG_LEVEL = 19, - GPP_CTRL = 20, - RESET = 21, - DISEQC_MODE = 22, - SYM_RATE_H = 23, - SYM_RATE_L = 24, - VIT_MODE = 25, - QPSK_CTRL = 26, - GO = 27, - IE_QPSK_H = 28, - IE_QPSK_M = 29, - IE_QPSK_L = 30, - IE_FEC = 31, - QPSK_STAT_EN = 32, - FEC_STAT_EN = 33, - SYS_CLK = 34, - DISEQC_RATIO = 35, - DISEQC_INSTR = 36, - FR_LIM = 37, - FR_OFF = 38, - AGC_CTRL = 39, - AGC_INIT = 40, - AGC_REF = 41, - AGC_MAX = 42, - AGC_MIN = 43, - AGC_LK_TH = 44, - TS_AGC_LK_TH = 45, - AGC_PWR_SET = 46, - QPSK_MISC = 47, - SNR_THS_LOW = 48, - SNR_THS_HIGH = 49, - TS_SW_RATE = 50, - TS_SW_LIM_L = 51, - TS_SW_LIM_H = 52, - CS_SW_RATE_1 = 53, - CS_SW_RATE_2 = 54, - CS_SW_RATE_3 = 55, - CS_SW_RATE_4 = 56, - CS_SW_LIM = 57, - TS_LPK = 58, - TS_LPK_M = 59, - TS_LPK_L = 60, - CS_KPROP_H = 61, - CS_KPROP_L = 62, - CS_KINT_H = 63, - CS_KINT_L = 64, - QPSK_SCALE = 65, - TLD_OUTCLK_TH = 66, - TLD_INCLK_TH = 67, - FLD_TH = 68, - PLD_OUTLK3 = 69, - PLD_OUTLK2 = 70, - PLD_OUTLK1 = 71, - PLD_OUTLK0 = 72, - PLD_INLK3 = 73, - PLD_INLK2 = 74, - PLD_INLK1 = 75, - PLD_INLK0 = 76, - PLD_ACC_TIME = 77, - SWEEP_PAR = 78, - STARTUP_TIME = 79, - LOSSLOCK_TH = 80, - FEC_LOCK_TM = 81, - LOSSLOCK_TM = 82, - VIT_ERRPER_H = 83, - VIT_ERRPER_M = 84, - VIT_ERRPER_L = 85, - VIT_SETUP = 86, - VIT_REF0 = 87, - VIT_REF1 = 88, - VIT_REF2 = 89, - VIT_REF3 = 90, - VIT_REF4 = 91, - VIT_REF5 = 92, - VIT_REF6 = 93, - VIT_MAXERR = 94, - BA_SETUPT = 95, - OP_CTRL = 96, - FEC_SETUP = 97, - PROG_SYNC = 98, - AFC_SEAR_TH = 99, - CSACC_DIF_TH = 100, - QPSK_LK_CT = 101, - QPSK_ST_CT = 102, - MON_CTRL = 103, - QPSK_RESET = 104, - QPSK_TST_CT = 105, - QPSK_TST_ST = 106, - TEST_R = 107, - AGC_H = 108, - AGC_M = 109, - AGC_L = 110, - FREQ_ERR1_H = 111, - FREQ_ERR1_M = 112, - FREQ_ERR1_L = 113, - FREQ_ERR2_H = 114, - FREQ_ERR2_L = 115, - SYM_RAT_OP_H = 116, - SYM_RAT_OP_L = 117, - DESEQC2_INT = 118, - DISEQC2_STAT = 119, - DISEQC2_FIFO = 120, - DISEQC2_CTRL1 = 121, - DISEQC2_CTRL2 = 122, - MONITOR_H = 123, - MONITOR_L = 124, - TEST_MODE = 125, - ID = 126, - CONFIG = 127 -}; +#include + +struct mt312_config +{ + /* the demodulator's i2c address */ + u8 demod_address; -enum mt312_model_id { - ID_VP310 = 1, - ID_MT312 = 3 + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend* fe); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; -#endif /* DVB_FRONTENDS_MT312 */ +extern struct dvb_frontend* mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); + +extern struct dvb_frontend* vp310_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); + +#endif // MT312_H diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index 7116b0ba5..a55fd99a6 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -1,13 +1,6 @@ /* - NxtWave Communications - NXT6000 demodulator driver - This driver currently supports: - - Alps TDME7 (Tuner: MITEL SP5659) - Alps TDED4 (Tuner: TI ALP510, external Nxt6000) - Comtech DVBT-6k07 (PLL IC: SP5730) - Copyright (C) 2002-2003 Florian Schirmer Copyright (C) 2003 Paul Andreassen @@ -34,241 +27,69 @@ #include #include "dvb_frontend.h" +#include "nxt6000_priv.h" #include "nxt6000.h" -static int debug = 0; -MODULE_DESCRIPTION("NxtWave NXT6000 DVB demodulator driver"); -MODULE_AUTHOR("Florian Schirmer"); -MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); - -static struct dvb_frontend_info nxt6000_info = { - - .name = "NxtWave NXT6000", - .type = FE_OFDM, - .frequency_min = 0, - .frequency_max = 863250000, - .frequency_stepsize = 62500, - /*.frequency_tolerance = */ /* FIXME: 12% of SR */ - .symbol_rate_min = 0, /* FIXME */ - .symbol_rate_max = 9360000, /* FIXME */ - .symbol_rate_tolerance = 4000, - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | - FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; -struct nxt6000_config { - u8 demod_addr; - u8 tuner_addr; - u8 tuner_type; - u8 clock_inversion; -}; +struct nxt6000_state { + + struct i2c_adapter *i2c; -#define TUNER_TYPE_ALP510 0 -#define TUNER_TYPE_SP5659 1 -#define TUNER_TYPE_SP5730 2 + struct dvb_frontend_ops ops; -#define FE2NXT(fe) ((struct nxt6000_config *)((fe)->data)) -#define FREQ2DIV(freq) ((freq + 36166667) / 166667) + /* configuration settings */ + const struct nxt6000_config* config; + + struct dvb_frontend frontend; + +}; +static int debug = 0; #define dprintk if (debug) printk -static int nxt6000_write(struct dvb_i2c_bus *i2c, u8 addr, u8 reg, u8 data) +static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) { - u8 buf[] = {reg, data}; - struct i2c_msg msg = {.addr = addr >> 1, .flags = 0, .buf = buf, .len = 2}; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 }; int ret; - if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) - dprintk("nxt6000: nxt6000_write error (.addr = 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)\n", addr, reg, data, ret); + if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) + dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret); return (ret != 1) ? -EFAULT : 0; - } -static u8 nxt6000_writereg(struct dvb_frontend *fe, u8 reg, u8 data) +static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg) { - - struct nxt6000_config *nxt = FE2NXT(fe); - - return nxt6000_write(fe->i2c, nxt->demod_addr, reg, data); - -} - -static u8 nxt6000_read(struct dvb_i2c_bus *i2c, u8 addr, u8 reg) -{ - int ret; u8 b0[] = {reg}; u8 b1[] = {0}; struct i2c_msg msgs[] = { - {.addr = addr >> 1,.flags = 0,.buf = b0,.len = 1}, - {.addr = addr >> 1,.flags = I2C_M_RD,.buf = b1,.len = 1} + {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} }; - ret = i2c->xfer(i2c, msgs, 2); + ret = i2c_transfer(state->i2c, msgs, 2); if (ret != 2) - dprintk("nxt6000: nxt6000_read error (.addr = 0x%02X, reg: 0x%02X, ret: %d)\n", addr, reg, ret); + dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret); return b1[0]; - } -static u8 nxt6000_readreg(struct dvb_frontend *fe, u8 reg) +static void nxt6000_reset(struct nxt6000_state* state) { - - struct nxt6000_config *nxt = FE2NXT(fe); - - return nxt6000_read(fe->i2c, nxt->demod_addr, reg); -} - -static int pll_test(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr) -{ - u8 buf [1]; - struct i2c_msg msg = {.addr = tuner_addr >> 1,.flags = I2C_M_RD,.buf = buf,.len = 1 }; - int ret; - - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - ret = i2c->xfer(i2c, &msg, 1); - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - - return (ret != 1) ? -EFAULT : 0; -} - -static int pll_write(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr, u8 *buf, u8 len) -{ - - struct i2c_msg msg = {.addr = tuner_addr >> 1, .flags = 0, .buf = buf, .len = len}; - int ret; - - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - ret = i2c->xfer(i2c, &msg, 1); - nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - - if (ret != 1) - dprintk("nxt6000: pll_write error %d\n", ret); - - return (ret != 1) ? -EFAULT : 0; - -} - -static int sp5659_set_tv_freq(struct dvb_frontend *fe, u32 freq) -{ - - u8 buf[4]; - struct nxt6000_config *nxt = FE2NXT(fe); - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = (((FREQ2DIV(freq) >> 15) & 0x03) << 5) | 0x85; - - if ((freq >= 174000000) && (freq < 230000000)) - buf[3] = 0x82; - else if ((freq >= 470000000) && (freq < 782000000)) - buf[3] = 0x85; - else if ((freq >= 782000000) && (freq < 863000000)) - buf[3] = 0xC5; - else - return -EINVAL; - - return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); - -} - -static int alp510_set_tv_freq(struct dvb_frontend *fe, u32 freq) -{ - - u8 buf[4]; - struct nxt6000_config *nxt = FE2NXT(fe); - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = 0x85; - -#if 0 - if ((freq >= 47000000) && (freq < 153000000)) - buf[3] = 0x01; - else if ((freq >= 153000000) && (freq < 430000000)) - buf[3] = 0x02; - else if ((freq >= 430000000) && (freq < 824000000)) - buf[3] = 0x08; - else if ((freq >= 824000000) && (freq < 863000000)) - buf[3] = 0x88; - else - return -EINVAL; -#else - if ((freq >= 47000000) && (freq < 153000000)) - buf[3] = 0x01; - else if ((freq >= 153000000) && (freq < 430000000)) - buf[3] = 0x02; - else if ((freq >= 430000000) && (freq < 824000000)) - buf[3] = 0x0C; - else if ((freq >= 824000000) && (freq < 863000000)) - buf[3] = 0x8C; - else - return -EINVAL; -#endif - - return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); - -} - -static int sp5730_set_tv_freq(struct dvb_frontend *fe, u32 freq) -{ - - u8 buf[4]; - struct nxt6000_config *nxt = FE2NXT(fe); - - buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; - buf[1] = FREQ2DIV(freq) & 0xFF; - buf[2] = 0x93; - - if ((freq >= 51000000) && (freq < 132100000)) - buf[3] = 0x05; - else if ((freq >= 132100000) && (freq < 143000000)) - buf[3] = 0x45; - else if ((freq >= 146000000) && (freq < 349100000)) - buf[3] = 0x06; - else if ((freq >= 349100000) && (freq < 397100000)) - buf[3] = 0x46; - else if ((freq >= 397100000) && (freq < 426000000)) - buf[3] = 0x86; - else if ((freq >= 430000000) && (freq < 659100000)) - buf[3] = 0x03; - else if ((freq >= 659100000) && (freq < 759100000)) - buf[3] = 0x43; - else if ((freq >= 759100000) && (freq < 858000000)) - buf[3] = 0x83; - else - return -EINVAL; - - return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); - -} - -static void nxt6000_reset(struct dvb_frontend *fe) -{ - u8 val; - val = nxt6000_readreg(fe, OFDM_COR_CTL); - - nxt6000_writereg(fe, OFDM_COR_CTL, val & ~COREACT); - nxt6000_writereg(fe, OFDM_COR_CTL, val | COREACT); + val = nxt6000_readreg(state, OFDM_COR_CTL); + nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT); + nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT); } -static int nxt6000_set_bandwidth(struct dvb_frontend *fe, fe_bandwidth_t bandwidth) +static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth) { - u16 nominal_rate; int result; @@ -293,132 +114,115 @@ static int nxt6000_set_bandwidth(struct dvb_frontend *fe, fe_bandwidth_t bandwid break; default: - return -EINVAL; - } - if ((result = nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) + if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) return result; - return nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); - + return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); } -static int nxt6000_set_guard_interval(struct dvb_frontend *fe, fe_guard_interval_t guard_interval) +static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval) { - switch(guard_interval) { case GUARD_INTERVAL_1_32: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_1_16: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_AUTO: case GUARD_INTERVAL_1_8: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); case GUARD_INTERVAL_1_4: - - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x03)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); default: - return -EINVAL; - } - } -static int nxt6000_set_inversion(struct dvb_frontend *fe, fe_spectral_inversion_t inversion) +static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion) { - switch(inversion) { case INVERSION_OFF: - - return nxt6000_writereg(fe, OFDM_ITB_CTL, 0x00); + return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00); case INVERSION_ON: - - return nxt6000_writereg(fe, OFDM_ITB_CTL, ITBINV); + return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV); default: - return -EINVAL; } - } -static int nxt6000_set_transmission_mode(struct dvb_frontend *fe, fe_transmit_mode_t transmission_mode) +static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode) { - int result; switch(transmission_mode) { case TRANSMISSION_MODE_2K: - - if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0) + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) return result; - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); case TRANSMISSION_MODE_8K: case TRANSMISSION_MODE_AUTO: - - if ((result = nxt6000_writereg(fe, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(fe, EN_DMD_RACQ) & ~0x03))) < 0) + if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) return result; - return nxt6000_writereg(fe, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(fe, OFDM_COR_MODEGUARD) & ~0x04)); + return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); default: - return -EINVAL; } - } -static void nxt6000_setup(struct dvb_frontend *fe) +static void nxt6000_setup(struct dvb_frontend* fe) { - - struct nxt6000_config *nxt = FE2NXT(fe); - - nxt6000_writereg(fe, RS_COR_SYNC_PARAM, SYNC_PARAM); - nxt6000_writereg(fe, BER_CTRL, /*(1 << 2) |*/ (0x01 << 1) | 0x01); - nxt6000_writereg(fe, VIT_COR_CTL, VIT_COR_RESYNC); - nxt6000_writereg(fe, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(fe, OFDM_COR_CTL) & 0x0F)); - nxt6000_writereg(fe, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02); - nxt6000_writereg(fe, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW); - nxt6000_writereg(fe, OFDM_ITB_FREQ_1, 0x06); - nxt6000_writereg(fe, OFDM_ITB_FREQ_2, 0x31); - nxt6000_writereg(fe, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04); - nxt6000_writereg(fe, CAS_FREQ, 0xBB); /* CHECKME */ - nxt6000_writereg(fe, OFDM_SYR_CTL, 1 << 2); - nxt6000_writereg(fe, OFDM_PPM_CTL_1, PPM256); - nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_1, 0x49); - nxt6000_writereg(fe, OFDM_TRL_NOMINALRATE_2, 0x72); - nxt6000_writereg(fe, ANALOG_CONTROL_0, 1 << 5); - nxt6000_writereg(fe, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2); - nxt6000_writereg(fe, DIAG_CONFIG, TB_SET); - - if (nxt->clock_inversion) - nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, CLKINVERSION); + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; + + nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM); + nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01); + nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC); + nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F)); + nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02); + nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW); + nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06); + nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31); + nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04); + nxt6000_writereg(state, CAS_FREQ, 0xBB); /* CHECKME */ + nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2); + nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256); + nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49); + nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72); + nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5); + nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2); + nxt6000_writereg(state, DIAG_CONFIG, TB_SET); + + if (state->config->clock_inversion) + nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION); else - nxt6000_writereg(fe, SUB_DIAG_MODE_SEL, 0); - - nxt6000_writereg(fe, TS_FORMAT, 0); + nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0); + nxt6000_writereg(state, TS_FORMAT, 0); + + if (state->config->pll_init) { + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + state->config->pll_init(fe); + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ + } } -static void nxt6000_dump_status(struct dvb_frontend *fe) +static void nxt6000_dump_status(struct nxt6000_state *state) { u8 val; @@ -436,12 +240,12 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) */ printk("NXT6000 status:"); - val = nxt6000_readreg(fe, RS_COR_STAT); + val = nxt6000_readreg(state, RS_COR_STAT); printk(" DATA DESCR LOCK: %d,", val & 0x01); printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01); - val = nxt6000_readreg(fe, VIT_SYNC_STATUS); + val = nxt6000_readreg(state, VIT_SYNC_STATUS); printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01); @@ -479,7 +283,7 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) } - val = nxt6000_readreg(fe, OFDM_COR_STAT); + val = nxt6000_readreg(state, OFDM_COR_STAT); printk(" CHCTrack: %d,", (val >> 7) & 0x01); printk(" TPSLock: %d,", (val >> 6) & 0x01); @@ -532,7 +336,7 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) } - val = nxt6000_readreg(fe, OFDM_SYR_STAT); + val = nxt6000_readreg(state, OFDM_SYR_STAT); printk(" SYRLock: %d,", (val >> 4) & 0x01); printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K"); @@ -558,14 +362,11 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) break; case 0x03: - printk(" SYRGuard: 1/4,"); - break; - } - val = nxt6000_readreg(fe, OFDM_TPS_RCVD_3); + val = nxt6000_readreg(state, OFDM_TPS_RCVD_3); switch((val >> 4) & 0x07) { @@ -635,7 +436,7 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) } - val = nxt6000_readreg(fe, OFDM_TPS_RCVD_4); + val = nxt6000_readreg(state, OFDM_TPS_RCVD_4); printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K"); @@ -668,253 +469,156 @@ static void nxt6000_dump_status(struct dvb_frontend *fe) } /* Strange magic required to gain access to RF_AGC_STATUS */ - nxt6000_readreg(fe, RF_AGC_VAL_1); - val = nxt6000_readreg(fe, RF_AGC_STATUS); - val = nxt6000_readreg(fe, RF_AGC_STATUS); + nxt6000_readreg(state, RF_AGC_VAL_1); + val = nxt6000_readreg(state, RF_AGC_STATUS); + val = nxt6000_readreg(state, RF_AGC_STATUS); printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01); - printk("\n"); - } -static int nxt6000_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - switch (cmd) { - case FE_GET_INFO: - memcpy(arg, &nxt6000_info, sizeof (struct dvb_frontend_info)); - return 0; - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *)arg; + + + + +static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ u8 core_status; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; *status = 0; - core_status = nxt6000_readreg(fe, OFDM_COR_STAT); + core_status = nxt6000_readreg(state, OFDM_COR_STAT); if (core_status & AGCLOCKED) *status |= FE_HAS_SIGNAL; - if (nxt6000_readreg(fe, OFDM_SYR_STAT) & GI14_SYR_LOCK) + if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK) *status |= FE_HAS_CARRIER; - if (nxt6000_readreg(fe, VIT_SYNC_STATUS) & VITINSYNC) + if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC) *status |= FE_HAS_VITERBI; - if (nxt6000_readreg(fe, RS_COR_STAT) & RSCORESTATUS) + if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS) *status |= FE_HAS_SYNC; if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))) *status |= FE_HAS_LOCK; if (debug) - nxt6000_dump_status(fe); + nxt6000_dump_status(state); return 0; - } - case FE_READ_BER: +static int nxt6000_init(struct dvb_frontend* fe) { - u32 *ber = (u32 *)arg; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; - *ber=0; - - return 0; - - } + nxt6000_reset(state); + nxt6000_setup(fe); - case FE_READ_SIGNAL_STRENGTH: - { - s16 *signal = (s16 *) arg; -/* - *signal=(((signed char)readreg(client, 0x16))+128)<<8; -*/ - *signal = 0; return 0; - - } - - case FE_READ_SNR: - { - s16 *snr = (s16 *) arg; -/* - *snr=readreg(client, 0x24)<<8; - *snr|=readreg(client, 0x25); -*/ - *snr = 0; - break; - } - - case FE_READ_UNCORRECTED_BLOCKS: - { - u32 *ublocks = (u32 *)arg; - - *ublocks = 0; - - break; } - case FE_INIT: - nxt6000_reset(fe); - nxt6000_setup(fe); - break; - case FE_SET_FRONTEND: +static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { - struct nxt6000_config *nxt = FE2NXT(fe); - struct dvb_frontend_parameters *param = (struct dvb_frontend_parameters *)arg; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; int result; - switch(nxt->tuner_type) { - - case TUNER_TYPE_ALP510: - - if ((result = alp510_set_tv_freq(fe, param->frequency)) < 0) - return result; - - break; - - case TUNER_TYPE_SP5659: - - if ((result = sp5659_set_tv_freq(fe, param->frequency)) < 0) - return result; - - break; - - case TUNER_TYPE_SP5730: + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ + state->config->pll_set(fe, param); + nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - if ((result = sp5730_set_tv_freq(fe, param->frequency)) < 0) + if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0) return result; - - break; - - default: - - return -EFAULT; - - } - - if ((result = nxt6000_set_bandwidth(fe, param->u.ofdm.bandwidth)) < 0) - return result; - if ((result = nxt6000_set_guard_interval(fe, param->u.ofdm.guard_interval)) < 0) + if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0) return result; - if ((result = nxt6000_set_transmission_mode(fe, param->u.ofdm.transmission_mode)) < 0) + if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0) return result; - if ((result = nxt6000_set_inversion(fe, param->inversion)) < 0) + if ((result = nxt6000_set_inversion(state, param->inversion)) < 0) return result; - - break; - } - - default: - - return -EOPNOTSUPP; - - } return 0; - } -static u8 demod_addr_tbl[] = {0x14, 0x18, 0x24, 0x28}; -static int nxt6000_attach(struct dvb_i2c_bus *i2c, void **data) +static void nxt6000_release(struct dvb_frontend* fe) { - u8 addr_nr; - u8 fe_count = 0; - struct nxt6000_config *pnxt; - - dprintk("nxt6000: attach\n"); - - pnxt = kmalloc(sizeof(demod_addr_tbl)*sizeof(struct nxt6000_config), GFP_KERNEL); - if (NULL == pnxt) { - dprintk("nxt6000: no memory for private data.\n"); - return -ENOMEM; + struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv; + kfree(state); } - *data = pnxt; - - for (addr_nr = 0; addr_nr < sizeof(demod_addr_tbl); addr_nr++) { - struct nxt6000_config *nxt = &pnxt[addr_nr]; - if (nxt6000_read(i2c, demod_addr_tbl[addr_nr], OFDM_MSC_REV) != NXT6000ASICDEVICE) - continue; - - if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { - nxt->tuner_addr = 0xC0; - nxt->tuner_type = TUNER_TYPE_ALP510; - nxt->clock_inversion = 1; +static struct dvb_frontend_ops nxt6000_ops; - dprintk("nxt6000: detected TI ALP510 tuner at 0x%02X\n", nxt->tuner_addr); - - } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC2) == 0) { - nxt->tuner_addr = 0xC2; - nxt->tuner_type = TUNER_TYPE_SP5659; - nxt->clock_inversion = 0; +struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, + struct i2c_adapter* i2c) +{ + struct nxt6000_state* state = NULL; - dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt->tuner_addr); - - } else if (pll_test(i2c, demod_addr_tbl[addr_nr], 0xC0) == 0) { - nxt->tuner_addr = 0xC0; - nxt->tuner_type = TUNER_TYPE_SP5730; - nxt->clock_inversion = 0; + /* allocate memory for the internal state */ + state = (struct nxt6000_state*) kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL); + if (state == NULL) goto error; - dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt->tuner_addr); - - } else { - printk("nxt6000: unable to detect tuner\n"); - continue; - } - - nxt->demod_addr = demod_addr_tbl[addr_nr]; - - dprintk("nxt6000: attached at %d:%d\n", i2c->adapter->num, i2c->id); - - dvb_register_frontend(nxt6000_ioctl, i2c, (void *)nxt, &nxt6000_info); - - fe_count++; - } - - if (fe_count == 0) { - kfree(pnxt); - return -ENODEV; - } - - return 0; -} - -static void nxt6000_detach(struct dvb_i2c_bus *i2c, void *data) -{ - struct nxt6000_config *pnxt = (struct nxt6000_config *)data; - dprintk("nxt6000: detach\n"); - dvb_unregister_frontend(nxt6000_ioctl, i2c); - kfree(pnxt); -} + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops)); -static __init int nxt6000_init(void) -{ + /* check if the demod is there */ + if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error; - dprintk("nxt6000: init\n"); - - return dvb_register_i2c_device(THIS_MODULE, nxt6000_attach, nxt6000_detach); - -} + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; -static __exit void nxt6000_exit(void) -{ +error: + if (state) kfree(state); + return NULL; + } - dprintk("nxt6000: cleanup\n"); +static struct dvb_frontend_ops nxt6000_ops = { + + .info = { + .name = "NxtWave NXT6000 DVB-T", + .type = FE_OFDM, + .frequency_min = 0, + .frequency_max = 863250000, + .frequency_stepsize = 62500, + /*.frequency_tolerance = *//* FIXME: 12% of SR */ + .symbol_rate_min = 0, /* FIXME */ + .symbol_rate_max = 9360000, /* FIXME */ + .symbol_rate_tolerance = 4000, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = nxt6000_release, + + .init = nxt6000_init, + + .set_frontend = nxt6000_set_frontend, + + .read_status = nxt6000_read_status, +}; - dvb_unregister_i2c_device(nxt6000_attach); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -} +MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver"); +MODULE_AUTHOR("Florian Schirmer"); +MODULE_LICENSE("GPL"); -module_init(nxt6000_init); -module_exit(nxt6000_exit); +EXPORT_SYMBOL(nxt6000_attach); diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h index b47d25f91..b7d9bead3 100644 --- a/drivers/media/dvb/frontends/nxt6000.h +++ b/drivers/media/dvb/frontends/nxt6000.h @@ -1,266 +1,43 @@ /* - * Public Include File for DRV6000 users - * (ie. NxtWave Communications - NXT6000 demodulator driver) - * - * Copyright (C) 2001 NxtWave Communications, Inc. - * - */ + NxtWave Communications - NXT6000 demodulator driver -/* Nxt6000 Register Addresses and Bit Masks */ + Copyright (C) 2002-2003 Florian Schirmer + Copyright (C) 2003 Paul Andreassen -/* Maximum Register Number */ -#define MAXNXT6000REG (0x9A) + 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. -/* 0x1B A_VIT_BER_0 aka 0x3A */ -#define A_VIT_BER_0 (0x1B) + 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. -/* 0x1D A_VIT_BER_TIMER_0 aka 0x38 */ -#define A_VIT_BER_TIMER_0 (0x1D) + 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. +*/ -/* 0x21 RS_COR_STAT */ -#define RS_COR_STAT (0x21) -#define RSCORESTATUS (0x03) +#ifndef NXT6000_H +#define NXT6000_H -/* 0x22 RS_COR_INTEN */ -#define RS_COR_INTEN (0x22) +#include -/* 0x23 RS_COR_INSTAT */ -#define RS_COR_INSTAT (0x23) -#define INSTAT_ERROR (0x04) -#define LOCK_LOSS_BITS (0x03) +struct nxt6000_config +{ + /* the demodulator's i2c address */ + u8 demod_address; -/* 0x24 RS_COR_SYNC_PARAM */ -#define RS_COR_SYNC_PARAM (0x24) -#define SYNC_PARAM (0x03) + /* should clock inversion be used? */ + u8 clock_inversion:1; -/* 0x25 BER_CTRL */ -#define BER_CTRL (0x25) -#define BER_ENABLE (0x02) -#define BER_RESET (0x01) + /* PLL maintenance */ + int (*pll_init)(struct dvb_frontend* fe); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); +}; -/* 0x26 BER_PAY */ -#define BER_PAY (0x26) - -/* 0x27 BER_PKT_L */ -#define BER_PKT_L (0x27) -#define BER_PKTOVERFLOW (0x80) - -/* 0x30 VIT_COR_CTL */ -#define VIT_COR_CTL (0x30) -#define BER_CONTROL (0x02) -#define VIT_COR_MASK (0x82) -#define VIT_COR_RESYNC (0x80) - - -/* 0x32 VIT_SYNC_STATUS */ -#define VIT_SYNC_STATUS (0x32) -#define VITINSYNC (0x80) - -/* 0x33 VIT_COR_INTEN */ -#define VIT_COR_INTEN (0x33) -#define GLOBAL_ENABLE (0x80) - -/* 0x34 VIT_COR_INTSTAT */ -#define VIT_COR_INTSTAT (0x34) -#define BER_DONE (0x08) -#define BER_OVERFLOW (0x10) - -/* 0x38 OFDM_BERTimer */ /* Use the alias registers */ -#define A_VIT_BER_TIMER_0 (0x1D) - -/* 0x3A VIT_BER_TIMER_0 */ /* Use the alias registers */ -#define A_VIT_BER_0 (0x1B) - -/* 0x40 OFDM_COR_CTL */ -#define OFDM_COR_CTL (0x40) -#define COREACT (0x20) -#define HOLDSM (0x10) -#define WAIT_AGC (0x02) -#define WAIT_SYR (0x03) - -/* 0x41 OFDM_COR_STAT */ -#define OFDM_COR_STAT (0x41) -#define COR_STATUS (0x0F) -#define MONITOR_TPS (0x06) -#define TPSLOCKED (0x40) -#define AGCLOCKED (0x10) - -/* 0x42 OFDM_COR_INTEN */ -#define OFDM_COR_INTEN (0x42) -#define TPSRCVBAD (0x04) -#define TPSRCVCHANGED (0x02) -#define TPSRCVUPDATE (0x01) - -/* 0x43 OFDM_COR_INSTAT */ -#define OFDM_COR_INSTAT (0x43) - -/* 0x44 OFDM_COR_MODEGUARD */ -#define OFDM_COR_MODEGUARD (0x44) -#define FORCEMODE (0x08) -#define FORCEMODE8K (0x04) - -/* 0x45 OFDM_AGC_CTL */ -#define OFDM_AGC_CTL (0x45) -#define INITIAL_AGC_BW (0x08) -#define AGCNEG (0x02) -#define AGCLAST (0x10) - -/* 0x48 OFDM_AGC_TARGET */ -#define OFDM_AGC_TARGET (0x48) -#define OFDM_AGC_TARGET_DEFAULT (0x28) -#define OFDM_AGC_TARGET_IMPULSE (0x38) - -/* 0x49 OFDM_AGC_GAIN_1 */ -#define OFDM_AGC_GAIN_1 (0x49) - -/* 0x4B OFDM_ITB_CTL */ -#define OFDM_ITB_CTL (0x4B) -#define ITBINV (0x01) - -/* 0x4C OFDM_ITB_FREQ_1 */ -#define OFDM_ITB_FREQ_1 (0x4C) - -/* 0x4D OFDM_ITB_FREQ_2 */ -#define OFDM_ITB_FREQ_2 (0x4D) - -/* 0x4E OFDM_CAS_CTL */ -#define OFDM_CAS_CTL (0x4E) -#define ACSDIS (0x40) -#define CCSEN (0x80) - -/* 0x4F CAS_FREQ */ -#define CAS_FREQ (0x4F) - -/* 0x51 OFDM_SYR_CTL */ -#define OFDM_SYR_CTL (0x51) -#define SIXTH_ENABLE (0x80) -#define SYR_TRACKING_DISABLE (0x01) - -/* 0x52 OFDM_SYR_STAT */ -#define OFDM_SYR_STAT (0x52) -#define GI14_2K_SYR_LOCK (0x13) -#define GI14_8K_SYR_LOCK (0x17) -#define GI14_SYR_LOCK (0x10) - -/* 0x55 OFDM_SYR_OFFSET_1 */ -#define OFDM_SYR_OFFSET_1 (0x55) - -/* 0x56 OFDM_SYR_OFFSET_2 */ -#define OFDM_SYR_OFFSET_2 (0x56) - -/* 0x58 OFDM_SCR_CTL */ -#define OFDM_SCR_CTL (0x58) -#define SYR_ADJ_DECAY_MASK (0x70) -#define SYR_ADJ_DECAY (0x30) - -/* 0x59 OFDM_PPM_CTL_1 */ -#define OFDM_PPM_CTL_1 (0x59) -#define PPMMAX_MASK (0x30) -#define PPM256 (0x30) - -/* 0x5B OFDM_TRL_NOMINALRATE_1 */ -#define OFDM_TRL_NOMINALRATE_1 (0x5B) - -/* 0x5C OFDM_TRL_NOMINALRATE_2 */ -#define OFDM_TRL_NOMINALRATE_2 (0x5C) - -/* 0x5D OFDM_TRL_TIME_1 */ -#define OFDM_TRL_TIME_1 (0x5D) - -/* 0x60 OFDM_CRL_FREQ_1 */ -#define OFDM_CRL_FREQ_1 (0x60) - -/* 0x63 OFDM_CHC_CTL_1 */ -#define OFDM_CHC_CTL_1 (0x63) -#define MANMEAN1 (0xF0); -#define CHCFIR (0x01) - -/* 0x64 OFDM_CHC_SNR */ -#define OFDM_CHC_SNR (0x64) - -/* 0x65 OFDM_BDI_CTL */ -#define OFDM_BDI_CTL (0x65) -#define LP_SELECT (0x02) - -/* 0x67 OFDM_TPS_RCVD_1 */ -#define OFDM_TPS_RCVD_1 (0x67) -#define TPSFRAME (0x03) - -/* 0x68 OFDM_TPS_RCVD_2 */ -#define OFDM_TPS_RCVD_2 (0x68) - -/* 0x69 OFDM_TPS_RCVD_3 */ -#define OFDM_TPS_RCVD_3 (0x69) - -/* 0x6A OFDM_TPS_RCVD_4 */ -#define OFDM_TPS_RCVD_4 (0x6A) - -/* 0x6B OFDM_TPS_RESERVED_1 */ -#define OFDM_TPS_RESERVED_1 (0x6B) - -/* 0x6C OFDM_TPS_RESERVED_2 */ -#define OFDM_TPS_RESERVED_2 (0x6C) - -/* 0x73 OFDM_MSC_REV */ -#define OFDM_MSC_REV (0x73) - -/* 0x76 OFDM_SNR_CARRIER_2 */ -#define OFDM_SNR_CARRIER_2 (0x76) -#define MEAN_MASK (0x80) -#define MEANBIT (0x80) - -/* 0x80 ANALOG_CONTROL_0 */ -#define ANALOG_CONTROL_0 (0x80) -#define POWER_DOWN_ADC (0x40) - -/* 0x81 ENABLE_TUNER_IIC */ -#define ENABLE_TUNER_IIC (0x81) -#define ENABLE_TUNER_BIT (0x01) - -/* 0x82 EN_DMD_RACQ */ -#define EN_DMD_RACQ (0x82) -#define EN_DMD_RACQ_REG_VAL (0x81) -#define EN_DMD_RACQ_REG_VAL_14 (0x01) - -/* 0x84 SNR_COMMAND */ -#define SNR_COMMAND (0x84) -#define SNRStat (0x80) - -/* 0x85 SNRCARRIERNUMBER_LSB */ -#define SNRCARRIERNUMBER_LSB (0x85) - -/* 0x87 SNRMINTHRESHOLD_LSB */ -#define SNRMINTHRESHOLD_LSB (0x87) - -/* 0x89 SNR_PER_CARRIER_LSB */ -#define SNR_PER_CARRIER_LSB (0x89) - -/* 0x8B SNRBELOWTHRESHOLD_LSB */ -#define SNRBELOWTHRESHOLD_LSB (0x8B) - -/* 0x91 RF_AGC_VAL_1 */ -#define RF_AGC_VAL_1 (0x91) - -/* 0x92 RF_AGC_STATUS */ -#define RF_AGC_STATUS (0x92) - -/* 0x98 DIAG_CONFIG */ -#define DIAG_CONFIG (0x98) -#define DIAG_MASK (0x70) -#define TB_SET (0x10) -#define TRAN_SELECT (0x07) -#define SERIAL_SELECT (0x01) - -/* 0x99 SUB_DIAG_MODE_SEL */ -#define SUB_DIAG_MODE_SEL (0x99) -#define CLKINVERSION (0x01) - -/* 0x9A TS_FORMAT */ -#define TS_FORMAT (0x9A) -#define ERROR_SENSE (0x08) -#define VALID_SENSE (0x04) -#define SYNC_SENSE (0x02) -#define GATED_CLOCK (0x01) - -#define NXT6000ASICDEVICE (0x0b) +extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, + struct i2c_adapter* i2c); +#endif // NXT6000_H diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index 53ebf4a69..ac2c86db4 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -1,109 +1,69 @@ /* - Driver for the Microtune 7202D Frontend + Driver for the Spase sp887x demodulator */ /* - This driver needs a copy of the Avermedia firmware. The version tested - is part of the Avermedia DVB-T 1.3.26.3 Application. If the software is - installed in Windows the file will be in the /Program Files/AVerTV DVB-T/ - directory and is called sc_main.mc. Alternatively it can "extracted" from - the install cab files. Copy this file to '/usr/lib/hotplug/firmware/sc_main.mc'. - With this version of the file the first 10 bytes are discarded and the - next 0x4000 loaded. This may change in future versions. + * This driver needs external firmware. Please use the command + * "/Documentation/dvb/get_dvb_firmware sp887x" to + * download/extract it, and then copy it to /usr/lib/hotplug/firmware. */ +#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw" -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include "dvb_frontend.h" -#include "dvb_functions.h" - -#ifndef DVB_SP887X_FIRMWARE_FILE -#define DVB_SP887X_FIRMWARE_FILE "/usr/lib/hotplug/firmware/sc_main.mc" -#endif - -static char *sp887x_firmware = DVB_SP887X_FIRMWARE_FILE; - -#if 0 -#define dprintk(x...) printk(x) -#else -#define dprintk(x...) -#endif - -#if 0 -#define LOG(dir,addr,buf,len) \ - do { \ - int i; \ - printk("%s (%02x):", dir, addr & 0xff); \ - for (i=0; ii2c; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = len }; int err; - LOG("i2c_writebytes", msg.addr, msg.buf, msg.len); - - if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { printk ("%s: i2c write error (addr %02x, err == %i)\n", - __FUNCTION__, addr, err); + __FUNCTION__, state->config->demod_address, err); return -EREMOTEIO; } return 0; } - - -static -int sp887x_writereg (struct dvb_frontend *fe, u16 reg, u16 data) +static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data) { - struct dvb_i2c_bus *i2c = fe->i2c; u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff }; - struct i2c_msg msg = { .addr = 0x70, .flags = 0, .buf = b0, .len = 4 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 4 }; int ret; - LOG("sp887x_writereg", msg.addr, msg.buf, msg.len); - - if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) { + if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { /** * in case of soft reset we ignore ACK errors... */ - if (!(reg == 0xf1a && data == 0x000 && + if (!(reg == 0xf1a && data == 0x000 && (ret == -EREMOTEIO || ret == -EFAULT))) { printk("%s: writereg error " @@ -116,153 +76,103 @@ int sp887x_writereg (struct dvb_frontend *fe, u16 reg, u16 data) return 0; } - -static -u16 sp887x_readreg (struct dvb_frontend *fe, u16 reg) +static int sp887x_readreg (struct sp887x_state* state, u16 reg) { - struct dvb_i2c_bus *i2c = fe->i2c; u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b1 [2]; int ret; - struct i2c_msg msg[] = {{ .addr = 0x70, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x70, .flags = I2C_M_RD, .buf = b1, .len = 2 }}; - - LOG("sp887x_readreg (w)", msg[0].addr, msg[0].buf, msg[0].len); - LOG("sp887x_readreg (r)", msg[1].addr, msg[1].buf, msg[1].len); + struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }}; - if ((ret = i2c->xfer(i2c, msg, 2)) != 2) + if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + return -1; + } return (((b1[0] << 8) | b1[1]) & 0xfff); } - -static -void sp887x_microcontroller_stop (struct dvb_frontend *fe) +static void sp887x_microcontroller_stop (struct sp887x_state* state) { dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(state, 0xf08, 0x000); + sp887x_writereg(state, 0xf09, 0x000); /* microcontroller STOP */ - sp887x_writereg(fe, 0xf00, 0x000); + sp887x_writereg(state, 0xf00, 0x000); } - -static -void sp887x_microcontroller_start (struct dvb_frontend *fe) +static void sp887x_microcontroller_start (struct sp887x_state* state) { dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0xf08, 0x000); - sp887x_writereg(fe, 0xf09, 0x000); + sp887x_writereg(state, 0xf08, 0x000); + sp887x_writereg(state, 0xf09, 0x000); /* microcontroller START */ - sp887x_writereg(fe, 0xf00, 0x001); + sp887x_writereg(state, 0xf00, 0x001); } - -static -void sp887x_setup_agc (struct dvb_frontend *fe) +static void sp887x_setup_agc (struct sp887x_state* state) { /* setup AGC parameters */ dprintk("%s\n", __FUNCTION__); - sp887x_writereg(fe, 0x33c, 0x054); - sp887x_writereg(fe, 0x33b, 0x04c); - sp887x_writereg(fe, 0x328, 0x000); - sp887x_writereg(fe, 0x327, 0x005); - sp887x_writereg(fe, 0x326, 0x001); - sp887x_writereg(fe, 0x325, 0x001); - sp887x_writereg(fe, 0x324, 0x001); - sp887x_writereg(fe, 0x318, 0x050); - sp887x_writereg(fe, 0x317, 0x3fe); - sp887x_writereg(fe, 0x316, 0x001); - sp887x_writereg(fe, 0x313, 0x005); - sp887x_writereg(fe, 0x312, 0x002); - sp887x_writereg(fe, 0x306, 0x000); - sp887x_writereg(fe, 0x303, 0x000); + sp887x_writereg(state, 0x33c, 0x054); + sp887x_writereg(state, 0x33b, 0x04c); + sp887x_writereg(state, 0x328, 0x000); + sp887x_writereg(state, 0x327, 0x005); + sp887x_writereg(state, 0x326, 0x001); + sp887x_writereg(state, 0x325, 0x001); + sp887x_writereg(state, 0x324, 0x001); + sp887x_writereg(state, 0x318, 0x050); + sp887x_writereg(state, 0x317, 0x3fe); + sp887x_writereg(state, 0x316, 0x001); + sp887x_writereg(state, 0x313, 0x005); + sp887x_writereg(state, 0x312, 0x002); + sp887x_writereg(state, 0x306, 0x000); + sp887x_writereg(state, 0x303, 0x000); } - #define BLOCKSIZE 30 - +#define FW_SIZE 0x4000 /** * load firmware and setup MPEG interface... */ -static -int sp887x_initial_setup (struct dvb_frontend *fe) +static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw) { + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; u8 buf [BLOCKSIZE+2]; - unsigned char *firmware = NULL; int i; - int fd; - int filesize; - int fw_size; - mm_segment_t fs; + int fw_size = fw->size; + unsigned char *mem = fw->data; dprintk("%s\n", __FUNCTION__); - /* soft reset */ - sp887x_writereg(fe, 0xf1a, 0x000); - - sp887x_microcontroller_stop (fe); + /* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */ + if (fw_size < FW_SIZE+10) + return -ENODEV; - fs = get_fs(); + mem = fw->data + 10; - // Load the firmware - set_fs(get_ds()); - fd = sys_open(sp887x_firmware, 0, 0); - if (fd < 0) { - printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__, - sp887x_firmware); - return -EIO; - } - filesize = sys_lseek(fd, 0L, 2); - if (filesize <= 0) { - printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__, - sp887x_firmware); - sys_close(fd); - return -EIO; - } - - fw_size = 0x4000; - - // allocate buffer for it - firmware = vmalloc(fw_size); - if (firmware == NULL) { - printk(KERN_WARNING "%s: Out of memory loading firmware\n", - __FUNCTION__); - sys_close(fd); - return -EIO; - } + /* soft reset */ + sp887x_writereg(state, 0xf1a, 0x000); - // read it! - // read the first 16384 bytes from the file - // ignore the first 10 bytes - sys_lseek(fd, 10, 0); - if (sys_read(fd, firmware, fw_size) != fw_size) { - printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__); - vfree(firmware); - sys_close(fd); - return -EIO; - } - sys_close(fd); - set_fs(fs); + sp887x_microcontroller_stop (state); printk ("%s: firmware upload... ", __FUNCTION__); /* setup write pointer to -1 (end of memory) */ /* bit 0x8000 in address is set to enable 13bit mode */ - sp887x_writereg(fe, 0x8f08, 0x1fff); + sp887x_writereg(state, 0x8f08, 0x1fff); /* dummy write (wrap around to start of memory) */ - sp887x_writereg(fe, 0x8f0a, 0x0000); + sp887x_writereg(state, 0x8f0a, 0x0000); - for (i=0; i fw_size) - c = fw_size - i; + if (i+c > FW_SIZE) + c = FW_SIZE - i; /* bit 0x8000 in address is set to enable 13bit mode */ /* bit 0x4000 enables multibyte read/write transfers */ @@ -270,83 +180,51 @@ int sp887x_initial_setup (struct dvb_frontend *fe) buf[0] = 0xcf; buf[1] = 0x0a; - memcpy(&buf[2], firmware + i, c); + memcpy(&buf[2], mem + i, c); - if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) { + if ((err = i2c_writebytes (state, buf, c+2)) < 0) { printk ("failed.\n"); printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); - vfree(firmware); return err; } } - vfree(firmware); - /* don't write RS bytes between packets */ - sp887x_writereg(fe, 0xc13, 0x001); + sp887x_writereg(state, 0xc13, 0x001); /* suppress clock if (!data_valid) */ - sp887x_writereg(fe, 0xc14, 0x000); + sp887x_writereg(state, 0xc14, 0x000); /* setup MPEG interface... */ - sp887x_writereg(fe, 0xc1a, 0x872); - sp887x_writereg(fe, 0xc1b, 0x001); - sp887x_writereg(fe, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */ - sp887x_writereg(fe, 0xc1a, 0x871); + sp887x_writereg(state, 0xc1a, 0x872); + sp887x_writereg(state, 0xc1b, 0x001); + sp887x_writereg(state, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */ + sp887x_writereg(state, 0xc1a, 0x871); /* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */ - sp887x_writereg(fe, 0x301, 0x002); + sp887x_writereg(state, 0x301, 0x002); - sp887x_setup_agc(fe); + sp887x_setup_agc(state); /* bit 0x010: enable data valid signal */ - sp887x_writereg(fe, 0xd00, 0x010); - sp887x_writereg(fe, 0x0d1, 0x000); + sp887x_writereg(state, 0xd00, 0x010); + sp887x_writereg(state, 0x0d1, 0x000); + + /* setup the PLL */ + if (state->config->pll_init) { + sp887x_writereg(state, 0x206, 0x001); + state->config->pll_init(fe); + sp887x_writereg(state, 0x206, 0x000); + } printk ("done.\n"); return 0; }; - -/** - * returns the actual tuned center frequency which can be used - * to initialise the AFC registers - */ -static -int tsa5060_setup_pll (struct dvb_frontend *fe, int freq) -{ - u8 cfg, cpump, band_select; - u8 buf [4]; - u32 div; - - div = (36000000 + freq + 83333) / 166666; - cfg = 0x88; - - cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 : - freq < 470000000 ? 2 : freq < 750000000 ? 2 : 3; - - band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03; - - buf [0] = (div >> 8) & 0x7f; - buf [1] = div & 0xff; - buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = cpump | band_select; - - /* open i2c gate for PLL message transmission... */ - sp887x_writereg(fe, 0x206, 0x001); - i2c_writebytes(fe, 0x60, buf, 4); - sp887x_writereg(fe, 0x206, 0x000); - - return (div * 166666 - 36000000); -} - - - -static -int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) +static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) { int known_parameters = 1; - + *reg0xc05 = 0x000; switch (p->u.ofdm.constellation) { @@ -414,13 +292,11 @@ int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05) return 0; } - /** * estimates division of two 24bit numbers, * derived from the ves1820/stv0299 driver code */ -static -void divide (int n, int d, int *quotient_i, int *quotient_f) +static void divide (int n, int d, int *quotient_i, int *quotient_f) { unsigned int q, r; @@ -438,9 +314,7 @@ void divide (int n, int d, int *quotient_i, int *quotient_f) } } - -static -void sp887x_correct_offsets (struct dvb_frontend *fe, +static void sp887x_correct_offsets (struct sp887x_state* state, struct dvb_frontend_parameters *p, int actual_freq) { @@ -463,19 +337,31 @@ void sp887x_correct_offsets (struct dvb_frontend *fe, frequency_shift = -frequency_shift; /* sample rate correction */ - sp887x_writereg(fe, 0x319, srate_correction[bw_index] >> 12); - sp887x_writereg(fe, 0x31a, srate_correction[bw_index] & 0xfff); + sp887x_writereg(state, 0x319, srate_correction[bw_index] >> 12); + sp887x_writereg(state, 0x31a, srate_correction[bw_index] & 0xfff); /* carrier offset correction */ - sp887x_writereg(fe, 0x309, frequency_shift >> 12); - sp887x_writereg(fe, 0x30a, frequency_shift & 0xfff); + sp887x_writereg(state, 0x309, frequency_shift >> 12); + sp887x_writereg(state, 0x30a, frequency_shift & 0xfff); } -static -int sp887x_setup_frontend_parameters (struct dvb_frontend *fe, + + + + + + + + + + + + +static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; int actual_freq, err; u16 val, reg0xc05; @@ -483,18 +369,21 @@ int sp887x_setup_frontend_parameters (struct dvb_frontend *fe, p->u.ofdm.bandwidth != BANDWIDTH_7_MHZ && p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ) return -EINVAL; - + if ((err = configure_reg0xc05(p, ®0xc05))) return err; - sp887x_microcontroller_stop(fe); + sp887x_microcontroller_stop(state); - actual_freq = tsa5060_setup_pll(fe, p->frequency); + /* setup the PLL */ + sp887x_writereg(state, 0x206, 0x001); + actual_freq = state->config->pll_set(fe, p); + sp887x_writereg(state, 0x206, 0x000); - /* read status reg in order to clear pending irqs */ - sp887x_readreg(fe, 0x200); + /* read status reg in order to clear u.ofdm.bandwidth == BANDWIDTH_6_MHZ) @@ -504,15 +393,15 @@ int sp887x_setup_frontend_parameters (struct dvb_frontend *fe, else val = 0; - sp887x_writereg(fe, 0x311, val); + sp887x_writereg(state, 0x311, val); /* scan order: 2k first = 0, 8k first = 1 */ if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K) - sp887x_writereg(fe, 0x338, 0x000); + sp887x_writereg(state, 0x338, 0x000); else - sp887x_writereg(fe, 0x338, 0x001); + sp887x_writereg(state, 0x338, 0x001); - sp887x_writereg(fe, 0xc05, reg0xc05); + sp887x_writereg(state, 0xc05, reg0xc05); if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) val = 2 << 3; @@ -524,28 +413,19 @@ int sp887x_setup_frontend_parameters (struct dvb_frontend *fe, /* enable OFDM and SAW bits as lock indicators in sync register 0xf17, * optimize algorithm for given bandwidth... */ - sp887x_writereg(fe, 0xf14, 0x160 | val); - sp887x_writereg(fe, 0xf15, 0x000); + sp887x_writereg(state, 0xf14, 0x160 | val); + sp887x_writereg(state, 0xf15, 0x000); - sp887x_microcontroller_start(fe); + sp887x_microcontroller_start(state); return 0; } - -static -int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &sp887x_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: +static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status) { - u16 snr12 = sp887x_readreg(fe, 0xf16); - u16 sync0x200 = sp887x_readreg(fe, 0x200); - u16 sync0xf17 = sp887x_readreg(fe, 0xf17); - fe_status_t *status = arg; + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + u16 snr12 = sp887x_readreg(state, 0xf16); + u16 sync0x200 = sp887x_readreg(state, 0x200); + u16 sync0xf17 = sp887x_readreg(state, 0xf17); *status = 0; @@ -571,128 +451,172 @@ int sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) steps); } - break; - + return 0; } - case FE_READ_BER: +static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber) { - u32* ber = arg; - *ber = (sp887x_readreg(fe, 0xc08) & 0x3f) | - (sp887x_readreg(fe, 0xc07) << 6); - sp887x_writereg(fe, 0xc08, 0x000); - sp887x_writereg(fe, 0xc07, 0x000); + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + *ber = (sp887x_readreg(state, 0xc08) & 0x3f) | + (sp887x_readreg(state, 0xc07) << 6); + sp887x_writereg(state, 0xc08, 0x000); + sp887x_writereg(state, 0xc07, 0x000); if (*ber >= 0x3fff0) *ber = ~0; - break; + return 0; } - case FE_READ_SIGNAL_STRENGTH: // FIXME: correct registers ? +static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u16 snr12 = sp887x_readreg(fe, 0xf16); + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + u16 snr12 = sp887x_readreg(state, 0xf16); u32 signal = 3 * (snr12 << 4); - *((u16*) arg) = (signal < 0xffff) ? signal : 0xffff; - break; - } + *strength = (signal < 0xffff) ? signal : 0xffff; - case FE_READ_SNR: - { - u16 snr12 = sp887x_readreg(fe, 0xf16); - *(u16*) arg = (snr12 << 4) | (snr12 >> 8); - break; + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: +static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr) { - u32 *ublocks = (u32 *) arg; - *ublocks = sp887x_readreg(fe, 0xc0c); - if (*ublocks == 0xfff) - *ublocks = ~0; - break; - } - - case FE_SET_FRONTEND: - return sp887x_setup_frontend_parameters(fe, arg); - - case FE_GET_FRONTEND: // FIXME: read known values back from Hardware... - break; + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; - case FE_SLEEP: - /* tristate TS output and disable interface pins */ - sp887x_writereg(fe, 0xc18, 0x000); - break; - - case FE_INIT: - if (fe->data == NULL) { /* first time initialisation... */ - fe->data = (void*) ~0; - sp887x_initial_setup (fe); - } - /* enable TS output and interface pins */ - sp887x_writereg(fe, 0xc18, 0x00d); - break; + u16 snr12 = sp887x_readreg(state, 0xf16); + *snr = (snr12 << 4) | (snr12 >> 8); - case FE_GET_TUNE_SETTINGS: - { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; - fesettings->min_delay_ms = 50; - fesettings->step_size = 0; - fesettings->max_drift = 0; return 0; - } + } - default: - return -EOPNOTSUPP; - }; +static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + + *ucblocks = sp887x_readreg(state, 0xc0c); + if (*ucblocks == 0xfff) + *ucblocks = ~0; return 0; } +static int sp887x_sleep(struct dvb_frontend* fe) +{ + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + /* tristate TS output and disable interface pins */ + sp887x_writereg(state, 0xc18, 0x000); -static -int sp887x_attach (struct dvb_i2c_bus *i2c, void **data) + return 0; + } + +static int sp887x_init(struct dvb_frontend* fe) { - struct i2c_msg msg = {.addr = 0x70, .flags = 0, .buf = NULL, .len = 0 }; + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + const struct firmware *fw = NULL; + int ret; - dprintk ("%s\n", __FUNCTION__); + if (!state->initialised) { + /* request the firmware, this will block until someone uploads it */ + printk("sp887x: waiting for firmware upload...\n"); + ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE); + if (ret) { + printk("sp887x: no firmware upload (timeout or file not found?)\n"); + return ret; + } - if (i2c->xfer (i2c, &msg, 1) != 1) - return -ENODEV; + ret = sp887x_initial_setup(fe, fw); + if (ret) { + printk("sp887x: writing firmware to device failed\n"); + release_firmware(fw); + return ret; + } + state->initialised = 1; + } - return dvb_register_frontend (sp887x_ioctl, i2c, NULL, &sp887x_info); -} + /* enable TS output and interface pins */ + sp887x_writereg(state, 0xc18, 0x00d); + return 0; +} -static -void sp887x_detach (struct dvb_i2c_bus *i2c, void *data) +static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - dprintk ("%s\n", __FUNCTION__); - dvb_unregister_frontend (sp887x_ioctl, i2c); + fesettings->min_delay_ms = 350; + fesettings->step_size = 166666*2; + fesettings->max_drift = (166666*2)+1; + return 0; } - -static -int __init init_sp887x (void) +static void sp887x_release(struct dvb_frontend* fe) { - dprintk ("%s\n", __FUNCTION__); - return dvb_register_i2c_device (NULL, sp887x_attach, sp887x_detach); + struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops sp887x_ops; -static -void __exit exit_sp887x (void) +struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, + struct i2c_adapter* i2c) { - dprintk ("%s\n", __FUNCTION__); - dvb_unregister_i2c_device (sp887x_attach); -} + struct sp887x_state* state = NULL; + /* allocate memory for the internal state */ + state = (struct sp887x_state*) kmalloc(sizeof(struct sp887x_state), GFP_KERNEL); + if (state == NULL) goto error; -module_init(init_sp887x); -module_exit(exit_sp887x); + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + /* check if the demod is there */ + if (sp887x_readreg(state, 0x0200) < 0) goto error; -MODULE_DESCRIPTION("sp887x DVB-T demodulator driver"); -MODULE_LICENSE("GPL"); + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; +} +static struct dvb_frontend_ops sp887x_ops = { + + .info = { + .name = "Spase SP887x DVB-T", + .type = FE_OFDM, + .frequency_min = 50500000, + .frequency_max = 858000000, + .frequency_stepsize = 166666, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_RECOVER + }, + + .release = sp887x_release, + + .init = sp887x_init, + .sleep = sp887x_sleep, + + .set_frontend = sp887x_setup_frontend_parameters, + .get_tune_settings = sp887x_get_tune_settings, + + .read_status = sp887x_read_status, + .read_ber = sp887x_read_ber, + .read_signal_strength = sp887x_read_signal_strength, + .read_snr = sp887x_read_snr, + .read_ucblocks = sp887x_read_ucblocks, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(sp887x_attach); diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index c6a98de01..bf5de1031 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -1,8 +1,5 @@ /* - Universal driver for STV0299/TDA5059/SL1935 based - DVB QPSK frontends - - Alps BSRU6, LG TDQB-S00x + Driver for ST STV0299 demodulator Copyright (C) 2001-2002 Convergence Integrated Media GmbH , @@ -48,250 +45,73 @@ #include #include #include +#include #include #include #include #include "dvb_frontend.h" -#include "dvb_functions.h" - -#if 0 -#define dprintk(x...) printk(x) -#else -#define dprintk(x...) -#endif +#include "stv0299.h" -static int stv0299_status = 0; -static int disable_typhoon = 0; +struct stv0299_state { -#define STATUS_BER 0 -#define STATUS_UCBLOCKS 1 + struct i2c_adapter* i2c; + struct dvb_frontend_ops ops; -/* frontend types */ -#define UNKNOWN_FRONTEND -1 -#define PHILIPS_SU1278_TSA 0 // SU1278 with TSA5059 synth and datasheet recommended settings -#define ALPS_BSRU6 1 -#define LG_TDQF_S001F 2 -#define PHILIPS_SU1278_TUA 3 // SU1278 with TUA6100 synth -#define SAMSUNG_TBMU24112IMB 4 -#define PHILIPS_SU1278_TSA_TT 5 // SU1278 with TSA5059 synth and TechnoTrend settings -#define PHILIPS_SU1278_TSA_TY 6 // SU1278 with TUA5059 synth and Typhoon wiring - -/* Master Clock = 88 MHz */ -#define M_CLK (88000000UL) - -/* Master Clock for TT cards = 64 MHz */ -#define M_CLK_SU1278_TSA_TT (64000000UL) - -static struct dvb_frontend_info uni0299_info = { - .name = "STV0299/TSA5059/SL1935 based", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, /* kHz for QPSK frontends */ - .frequency_tolerance = M_CLK/2000, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - .symbol_rate_tolerance = 500, /* ppm */ - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_QPSK | - FE_CAN_FEC_AUTO -}; + const struct stv0299_config* config; + struct dvb_frontend frontend; -struct stv0299_state { - u8 tuner_type; u8 initialised:1; u32 tuner_frequency; u32 symbol_rate; fe_code_rate_t fec_inner; + int errmode; }; +#define STATUS_BER 0 +#define STATUS_UCBLOCKS 1 -static u8 init_tab [] = { - 0x04, 0x7d, /* F22FR = 0x7d */ - /* F22 = f_VCO / 128 / 0x7d = 22 kHz */ - - /* I2C bus repeater */ - 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ - - /* general purpose DAC registers */ - 0x06, 0x40, /* DAC not used, set to high impendance mode */ - 0x07, 0x00, /* DAC LSB */ - - /* DiSEqC registers */ - 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ - 0x09, 0x00, /* FIFO */ - - /* Input/Output configuration register */ - 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ - /* OP0 ctl = Normal, OP0 val = 1 (18 V) */ - /* Nyquist filter = 00, QPSK reverse = 0 */ - - /* AGC1 control register */ - 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ - - /* Timing loop register */ - 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ - - 0x10, 0x3f, // AGC2 0x3d - - 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on - - 0x15, 0xc9, // lock detector threshold - - 0x16, 0x00, - 0x17, 0x00, - 0x18, 0x00, - 0x19, 0x00, - 0x1a, 0x00, - - 0x1f, 0x50, - - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - - 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 - - 0x29, 0x1e, // 1/2 threshold - 0x2a, 0x14, // 2/3 threshold - 0x2b, 0x0f, // 3/4 threshold - 0x2c, 0x09, // 5/6 threshold - 0x2d, 0x05, // 7/8 threshold - 0x2e, 0x01, - - 0x31, 0x1f, // test all FECs - - 0x32, 0x19, // viterbi and synchro search - 0x33, 0xfc, // rs control - 0x34, 0x93, // error control -}; - - -static u8 init_tab_samsung [] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7D, - 0x05, 0x35, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0xC3, - 0x0C, 0x00, - 0x0D, 0x81, - 0x0E, 0x23, - 0x0F, 0x12, - 0x10, 0x7E, - 0x11, 0x84, - 0x12, 0xB9, - 0x13, 0x88, - 0x14, 0x89, - 0x15, 0xC9, - 0x16, 0x00, - 0x17, 0x5C, - 0x18, 0x00, - 0x19, 0x00, - 0x1A, 0x00, - 0x1C, 0x00, - 0x1D, 0x00, - 0x1E, 0x00, - 0x1F, 0x3A, - 0x20, 0x2E, - 0x21, 0x80, - 0x22, 0xFF, - 0x23, 0xC1, - 0x28, 0x00, - 0x29, 0x1E, - 0x2A, 0x14, - 0x2B, 0x0F, - 0x2C, 0x09, - 0x2D, 0x05, - 0x31, 0x1F, - 0x32, 0x19, - 0x33, 0xFE, - 0x34, 0x93 -}; - - -static u8 init_tab_su1278_tsa_tt [] = { - 0x01, 0x0f, - 0x02, 0x30, - 0x03, 0x00, - 0x04, 0x5b, - 0x05, 0x85, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0x02, - 0x09, 0x00, - 0x0C, 0x01, - 0x0D, 0x81, - 0x0E, 0x44, - 0x0f, 0x14, - 0x10, 0x3c, - 0x11, 0x84, - 0x12, 0xda, - 0x13, 0x97, - 0x14, 0x95, - 0x15, 0xc9, - 0x16, 0x19, - 0x17, 0x8c, - 0x18, 0x59, - 0x19, 0xf8, - 0x1a, 0xfe, - 0x1c, 0x7f, - 0x1d, 0x00, - 0x1e, 0x00, - 0x1f, 0x50, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x28, 0x00, - 0x29, 0x28, - 0x2a, 0x14, - 0x2b, 0x0f, - 0x2c, 0x09, - 0x2d, 0x09, - 0x31, 0x1f, - 0x32, 0x19, - 0x33, 0xfc, - 0x34, 0x13 -}; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "stv0299: " args); \ + } while (0) -static int stv0299_set_FEC (struct dvb_i2c_bus *i2c, fe_code_rate_t fec); -static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type); -static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { .addr = 0x68, .flags = 0, .buf = buf, .len = 2 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer (state->i2c, &msg, 1); if (ret != 1) dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " "ret == %i)\n", __FUNCTION__, reg, data, ret); - return (ret != 1) ? -1 : 0; + return (ret != 1) ? -EREMOTEIO : 0; +} + +int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + return stv0299_writeregI(state, reg, data); } -static u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 stv0299_readreg (struct stv0299_state* state, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = b0, .len = 1 }, - { .addr = 0x68, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", @@ -301,13 +121,13 @@ static u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg) } -static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) +static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len) { int ret; - struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = ®1, .len = 1 }, - { .addr = 0x68, .flags = I2C_M_RD, .buf = b, .len = len } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = ®1, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } }; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); @@ -316,372 +136,44 @@ static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) } -static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len) -{ - int ret; - struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len }; - - - stv0299_writereg(i2c, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - - ret = i2c->xfer (i2c, &msg, 1); - - stv0299_writereg(i2c, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - - if (ret != 1) - dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -1 : 0; -} - - -static int sl1935_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) -{ - u8 buf[4]; - u32 div; - - div = freq / 125; - - dprintk("%s : freq = %i, div = %i\n", __FUNCTION__, freq, div); - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x84; // 0xC4 - buf[3] = 0x08; - - if (freq < 1500000) buf[3] |= 0x10; - - return pll_write (i2c, 0x61, buf, sizeof(buf)); -} - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 125 kHz. - */ -static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) -{ - u8 addr; - u32 div; - u8 buf[4]; - int divisor, regcode; - - dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype); - - if ((freq < 950000) || (freq > 2150000)) return -EINVAL; - - if (ftype == PHILIPS_SU1278_TSA_TT) { - divisor = 500; - regcode = 2; - } else { - divisor = 125; - regcode = 4; - } - - // setup frequency divisor - div = (freq + (divisor - 1)) / divisor; // round correctly - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode; - buf[3] = 0; - - // tuner-specific settings - switch(ftype) { - case PHILIPS_SU1278_TSA: - case PHILIPS_SU1278_TSA_TT: - case PHILIPS_SU1278_TSA_TY: - if (ftype == PHILIPS_SU1278_TSA_TY) - addr = 0x61; - else - addr = 0x60; - - buf[3] |= 0x20; - - if (srate < 4000000) buf[3] |= 1; - - if (freq < 1250000) buf[3] |= 0; - else if (freq < 1550000) buf[3] |= 0x40; - else if (freq < 2050000) buf[3] |= 0x80; - else if (freq < 2150000) buf[3] |= 0xC0; - break; - - case ALPS_BSRU6: - addr = 0x61; - buf[3] = 0xC4; - if (freq > 1530000) buf[3] = 0xc0; - break; - - default: - return -EINVAL; - } - - return pll_write (i2c, addr, buf, sizeof(buf)); -} - - -#define MIN2(a,b) ((a) < (b) ? (a) : (b)) -#define MIN3(a,b,c) MIN2(MIN2(a,b),c) - -static int tua6100_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, - int ftype, int srate) -{ - u8 reg0 [2] = { 0x00, 0x00 }; - u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; - u8 reg2 [3] = { 0x02, 0x00, 0x00 }; - int _fband; - int first_ZF; - int R, A, N, P, M; - int err; - - first_ZF = (freq) / 1000; - - if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) < - abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890)))) - _fband = 2; - else - _fband = 3; - - if (_fband == 2) { - if (((first_ZF >= 950) && (first_ZF < 1350)) || - ((first_ZF >= 1430) && (first_ZF < 1950))) - reg0[1] = 0x07; - else if (((first_ZF >= 1350) && (first_ZF < 1430)) || - ((first_ZF >= 1950) && (first_ZF < 2150))) - reg0[1] = 0x0B; - } - - if(_fband == 3) { - if (((first_ZF >= 950) && (first_ZF < 1350)) || - ((first_ZF >= 1455) && (first_ZF < 1950))) - reg0[1] = 0x07; - else if (((first_ZF >= 1350) && (first_ZF < 1420)) || - ((first_ZF >= 1950) && (first_ZF < 2150))) - reg0[1] = 0x0B; - else if ((first_ZF >= 1420) && (first_ZF < 1455)) - reg0[1] = 0x0F; -} - - if (first_ZF > 1525) - reg1[1] |= 0x80; - else - reg1[1] &= 0x7F; - - if (_fband == 2) { - if (first_ZF > 1430) { /* 1430MHZ */ - reg1[1] &= 0xCF; /* N2 */ - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } else { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } -} - - if (_fband == 3) { - if ((first_ZF >= 1455) && - (first_ZF < 1630)) { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - } else { - if (first_ZF < 1455) { - reg1[1] &= 0xCF; /* N2 */ - reg1[1] |= 0x20; - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } else { - if (first_ZF >= 1630) { - reg1[1] &= 0xCF; /* N2 */ - reg2[1] &= 0xCF; /* R2 */ - reg2[1] |= 0x10; - } - } - } - } - - /* set ports, enable P0 for symbol rates > 4Ms/s */ - if (srate >= 4000000) - reg1[1] |= 0x0c; - else - reg1[1] |= 0x04; - - reg2[1] |= 0x0c; - - R = 64; - A = 64; - P = 64; //32 - - M = (freq * R) / 4; /* in Mhz */ - N = (M - A * 1000) / (P * 1000); - - reg1[1] |= (N >> 9) & 0x03; - reg1[2] = (N >> 1) & 0xff; - reg1[3] = (N << 7) & 0x80; - - reg2[1] |= (R >> 8) & 0x03; - reg2[2] = R & 0xFF; /* R */ - - reg1[3] |= A & 0x7f; /* A */ - - if (P == 64) - reg1[1] |= 0x40; /* Prescaler 64/65 */ - - reg0[1] |= 0x03; - - if ((err = pll_write(i2c, 0x60, reg0, sizeof(reg0)))) - return err; - - if ((err = pll_write(i2c, 0x60, reg1, sizeof(reg1)))) - return err; - - if ((err = pll_write(i2c, 0x60, reg2, sizeof(reg2)))) - return err; - - return 0; -} - - -static int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) -{ - switch(ftype) { - case SAMSUNG_TBMU24112IMB: - return sl1935_set_tv_freq(i2c, freq, ftype); - - case LG_TDQF_S001F: - return sl1935_set_tv_freq(i2c, freq, ftype); - - case PHILIPS_SU1278_TUA: - return tua6100_set_tv_freq(i2c, freq, ftype, srate); - - default: - return tsa5059_set_tv_freq(i2c, freq, ftype, srate); -} -} - -#if 0 -static int tsa5059_read_status (struct dvb_i2c_bus *i2c) -{ - int ret; - u8 rpt1 [] = { 0x05, 0xb5 }; - u8 stat [] = { 0 }; - - struct i2c_msg msg [] = {{ .addr = 0x68, .flags = 0, .buf = rpt1, .len = 2 }, - { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - - dprintk ("%s\n", __FUNCTION__); - - ret = i2c->xfer (i2c, msg, 2); - - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - - return stat[0]; -} -#endif - - -static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) -{ - int i; - - dprintk("stv0299: init chip\n"); - - switch(ftype) { - case SAMSUNG_TBMU24112IMB: - dprintk("%s: init stv0299 chip for Samsung TBMU24112IMB\n", __FUNCTION__); - - for (i=0; i 4) @@ -699,136 +191,191 @@ static fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c) } -static int stv0299_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout) +static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; dprintk ("%s\n", __FUNCTION__); - while (stv0299_readreg(i2c, 0x0a) & 1) { + while (stv0299_readreg(state, 0x0a) & 1) { if (jiffies - start > timeout) { dprintk ("%s: timeout!!\n", __FUNCTION__); return -ETIMEDOUT; } - dvb_delay(10); + msleep(10); }; return 0; } -static int stv0299_wait_diseqc_idle (struct dvb_i2c_bus *i2c, int timeout) +static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout) { unsigned long start = jiffies; dprintk ("%s\n", __FUNCTION__); - while ((stv0299_readreg(i2c, 0x0a) & 3) != 2 ) { + while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) { if (jiffies - start > timeout) { dprintk ("%s: timeout!!\n", __FUNCTION__); return -ETIMEDOUT; } - dvb_delay(10); + msleep(10); }; return 0; } +static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + u64 big = srate; + u32 ratio; + + // check rate is within limits + if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + + // calculate value to program + big = big << 20; + big += (state->config->mclk-1); // round correctly + do_div(big, state->config->mclk); + ratio = big << 4; + + return state->config->set_symbol_rate(fe, srate, ratio); +} + + +static int stv0299_get_symbolrate (struct stv0299_state* state) +{ + u32 Mclk = state->config->mclk / 4096L; + u32 srate; + s32 offset; + u8 sfr[3]; + s8 rtf; + + dprintk ("%s\n", __FUNCTION__); + + stv0299_readregs (state, 0x1f, sfr, 3); + stv0299_readregs (state, 0x1a, &rtf, 1); + + srate = (sfr[0] << 8) | sfr[1]; + srate *= Mclk; + srate /= 16; + srate += (sfr[2] >> 4) * Mclk / 256; + offset = (s32) rtf * (srate / 4096L); + offset /= 128; + + dprintk ("%s : srate = %i\n", __FUNCTION__, srate); + dprintk ("%s : ofset = %i\n", __FUNCTION__, offset); + + srate += offset; + + srate += 1000; + srate /= 2000; + srate *= 2000; + + return srate; +} + + + + + + + -static int stv0299_send_diseqc_msg (struct dvb_i2c_bus *i2c, + + + + + + +static int stv0299_send_diseqc_msg (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *m) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; int i; dprintk ("%s\n", __FUNCTION__); - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); - if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ + if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ return -EREMOTEIO; for (i=0; imsg_len; i++) { - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_fifo (state, 100) < 0) return -ETIMEDOUT; - if (stv0299_writereg (i2c, 0x09, m->msg[i])) + if (stv0299_writeregI (state, 0x09, m->msg[i])) return -EREMOTEIO; } - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; return 0; } -static int stv0299_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) +static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; dprintk ("%s\n", __FUNCTION__); - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); - if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ + if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ return -EREMOTEIO; - if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) + if (stv0299_writeregI (state, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) return -EREMOTEIO; - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - if (stv0299_writereg (i2c, 0x08, val)) + if (stv0299_writeregI (state, 0x08, val)) return -EREMOTEIO; return 0; } -static int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) +static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 val; - dprintk("%s: %s\n", __FUNCTION__, - tone == SEC_TONE_ON ? "SEC_TONE_ON" : - tone == SEC_TONE_OFF ? "SEC_TONE_OFF" : "??"); - - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (state, 100) < 0) return -ETIMEDOUT; - val = stv0299_readreg (i2c, 0x08); + val = stv0299_readreg (state, 0x08); switch (tone) { case SEC_TONE_ON: - { - dprintk("%s: TONE_ON\n", __FUNCTION__); - return stv0299_writereg (i2c, 0x08, val | 0x3); - } + return stv0299_writeregI (state, 0x08, val | 0x3); + case SEC_TONE_OFF: - { - dprintk("%s: TONE_OFF\n", __FUNCTION__); - return stv0299_writereg (i2c, 0x08, (val & ~0x3) | 0x02); - } + return stv0299_writeregI (state, 0x08, (val & ~0x3) | 0x02); + default: - { - dprintk("%s: TONE INVALID\n", __FUNCTION__); return -EINVAL; } - }; } -static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage, - int tuner_type) +static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; u8 reg0x08; u8 reg0x0c; @@ -836,8 +383,8 @@ static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); - reg0x08 = stv0299_readreg (i2c, 0x08); - reg0x0c = stv0299_readreg (i2c, 0x0c); + reg0x08 = stv0299_readreg (state, 0x08); + reg0x0c = stv0299_readreg (state, 0x0c); /** * H/V switching over OP0, OP1 and OP2 are LNB power enable bits @@ -845,181 +392,91 @@ static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltag reg0x0c &= 0x0f; if (voltage == SEC_VOLTAGE_OFF) { - stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */ - return stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ + stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */ + return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */ } - stv0299_writereg (i2c, 0x08, reg0x08 | 0x40); + stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6)); switch (voltage) { case SEC_VOLTAGE_13: - if (tuner_type == PHILIPS_SU1278_TSA_TY) - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x10); - else - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x40); + if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10; + else reg0x0c |= 0x40; - case SEC_VOLTAGE_18: - return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x50); + return stv0299_writeregI(state, 0x0c, reg0x0c); + case SEC_VOLTAGE_18: + return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50); default: return -EINVAL; }; } -static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate, int tuner_type) +static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd) { - u64 big = srate; - u32 ratio; - u8 aclk = 0; - u8 bclk = 0; - u8 m1; - int Mclk = M_CLK; + u8 last = 1; + int i; - // check rate is within limits - if ((srate < 1000000) || (srate > 45000000)) return -EINVAL; + /* reset voltage at the end + if((0x50 & stv0299_readreg (i2c, 0x0c)) == 0x50) + cmd |= 0x80; + else + cmd &= 0x7F; + */ - // calculate value to program - if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; - big = big << 20; - big += (Mclk-1); // round correctly - do_div(big, Mclk); - ratio = big << 4; - - // program registers - switch(tuner_type) { - case PHILIPS_SU1278_TSA_TT: - stv0299_writereg (i2c, 0x0e, 0x44); - if (srate >= 10000000) { - stv0299_writereg (i2c, 0x13, 0x97); - stv0299_writereg (i2c, 0x14, 0x95); - stv0299_writereg (i2c, 0x15, 0xc9); - stv0299_writereg (i2c, 0x17, 0x8c); - stv0299_writereg (i2c, 0x1a, 0xfe); - stv0299_writereg (i2c, 0x1c, 0x7f); - stv0299_writereg (i2c, 0x2d, 0x09); - } else { - stv0299_writereg (i2c, 0x13, 0x99); - stv0299_writereg (i2c, 0x14, 0x8d); - stv0299_writereg (i2c, 0x15, 0xce); - stv0299_writereg (i2c, 0x17, 0x43); - stv0299_writereg (i2c, 0x1a, 0x1d); - stv0299_writereg (i2c, 0x1c, 0x12); - stv0299_writereg (i2c, 0x2d, 0x05); + cmd = cmd << 1; + dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd); + + stv0299_set_voltage(fe,SEC_VOLTAGE_18); + msleep(32); + + for (i=0; i<9; i++) { + if((cmd & 0x01) != last) { + stv0299_set_voltage(fe, + last ? SEC_VOLTAGE_13 : + SEC_VOLTAGE_18); + last = (last) ? 0 : 1; } - stv0299_writereg (i2c, 0x0e, 0x23); - stv0299_writereg (i2c, 0x0f, 0x94); - stv0299_writereg (i2c, 0x10, 0x39); - stv0299_writereg (i2c, 0x15, 0xc9); - - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - break; - - case PHILIPS_SU1278_TSA_TY: - case PHILIPS_SU1278_TSA: - aclk = 0xb5; - if (srate < 2000000) bclk = 0x86; - else if (srate < 5000000) bclk = 0x89; - else if (srate < 15000000) bclk = 0x8f; - else if (srate < 45000000) bclk = 0x95; - - m1 = 0x14; - if (srate < 4000000) m1 = 0x10; - - stv0299_writereg (i2c, 0x13, aclk); - stv0299_writereg (i2c, 0x14, bclk); - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1); - break; - - case ALPS_BSRU6: - default: - if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } - else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } - else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } - else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } - else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } - else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } - - stv0299_writereg (i2c, 0x13, aclk); - stv0299_writereg (i2c, 0x14, bclk); - stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); - break; - } + cmd = cmd >> 1; + + if (i != 8) + msleep(8); + } return 0; } -static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c, int tuner_type) +static int stv0299_init (struct dvb_frontend* fe) { - u32 Mclk = M_CLK / 4096L; - u32 srate; - s32 offset; - u8 sfr[3]; - s8 rtf; - - dprintk ("%s\n", __FUNCTION__); - - if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT / 4096L; - - stv0299_readregs (i2c, 0x1f, sfr, 3); - stv0299_readregs (i2c, 0x1a, &rtf, 1); - - srate = (sfr[0] << 8) | sfr[1]; - srate *= Mclk; - srate /= 16; - srate += (sfr[2] >> 4) * Mclk / 256; - - offset = (s32) rtf * (srate / 4096L); - offset /= 128; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + int i; - dprintk ("%s : srate = %i\n", __FUNCTION__, srate); - dprintk ("%s : ofset = %i\n", __FUNCTION__, offset); + dprintk("stv0299: init chip\n"); - srate += offset; + for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2) + stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]); - srate += 1000; - srate /= 2000; - srate *= 2000; + if (state->config->pll_init) { + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_init(fe); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + } - return srate; + return 0; } -static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct dvb_i2c_bus *i2c = fe->i2c; - struct stv0299_state *state = (struct stv0299_state *) fe->data; - - dprintk ("%s\n", __FUNCTION__); - switch (cmd) { - case FE_GET_INFO: +static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) arg; - memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - if (state->tuner_type == PHILIPS_SU1278_TSA_TT) { - tmp->frequency_tolerance = M_CLK_SU1278_TSA_TT / 2000; - } - break; - } - - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; - u8 signal = 0xff - stv0299_readreg (i2c, 0x18); - u8 sync = stv0299_readreg (i2c, 0x1b); + u8 signal = 0xff - stv0299_readreg (state, 0x18); + u8 sync = stv0299_readreg (state, 0x1b); dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync); - *status = 0; if (signal > 10) @@ -1037,53 +494,61 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if ((sync & 0x98) == 0x98) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: - if (stv0299_status == STATUS_BER) { - *((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8) - | stv0299_readreg (i2c, 0x1e); - } else { - *((u32*) arg) = 0; +static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + if (state->errmode != STATUS_BER) return 0; + *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); + + return 0; } - break; - case FE_READ_SIGNAL_STRENGTH: +static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - s32 signal = 0xffff - ((stv0299_readreg (i2c, 0x18) << 8) - | stv0299_readreg (i2c, 0x19)); + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8) + | stv0299_readreg (state, 0x19)); dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__, - stv0299_readreg (i2c, 0x18), - stv0299_readreg (i2c, 0x19), (int) signal); + stv0299_readreg (state, 0x18), + stv0299_readreg (state, 0x19), (int) signal); signal = signal * 5 / 4; - *((u16*) arg) = (signal > 0xffff) ? 0xffff : - (signal < 0) ? 0 : signal; - break; - } - case FE_READ_SNR: - { - s32 snr = 0xffff - ((stv0299_readreg (i2c, 0x24) << 8) - | stv0299_readreg (i2c, 0x25)); - snr = 3 * (snr - 0xa100); - *((u16*) arg) = (snr > 0xffff) ? 0xffff : - (snr < 0) ? 0 : snr; - break; - } - case FE_READ_UNCORRECTED_BLOCKS: - if (stv0299_status == STATUS_UCBLOCKS) { - *((u32*) arg) = (stv0299_readreg (i2c, 0x1d) << 8) - | stv0299_readreg (i2c, 0x1e); - } else { - *((u32*) arg) = 0; + *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal; + + return 0; } - break; - case FE_SET_FRONTEND: +static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr) { - struct dvb_frontend_parameters *p = arg; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8) + | stv0299_readreg (state, 0x25)); + xsnr = 3 * (xsnr - 0xa100); + *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; + + return 0; +} + +static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + + if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; + else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); + + return 0; +} + +static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; int invval = 0; dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__); @@ -1095,12 +560,10 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) printk("stv0299 does not support auto-inversion\n"); return -EINVAL; } - if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1; - stv0299_writereg(i2c, 0x0c, (stv0299_readreg(i2c, 0x0c) & 0xfe) | invval); + if (state->config->invert) invval = (~invval) & 1; + stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - { + if (state->config->enhanced_tuning) { /* check if we should do a finetune */ int frequency_delta = p->frequency - state->tuner_frequency; int minmax = p->u.qpsk.symbol_rate / 2000; @@ -1109,125 +572,88 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) && (state->fec_inner == p->u.qpsk.fec_inner) && (state->symbol_rate == p->u.qpsk.symbol_rate)) { - int Drot_freq = (frequency_delta << 16) / (M_CLK_SU1278_TSA_TT / 1000); + int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000); // zap the derotator registers first - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); // now set them as we want - stv0299_writereg (i2c, 0x22, Drot_freq >> 8); - stv0299_writereg (i2c, 0x23, Drot_freq); + stv0299_writeregI(state, 0x22, Drot_freq >> 8); + stv0299_writeregI(state, 0x23, Drot_freq); } else { /* A "normal" tune is requested */ - pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate); - stv0299_writereg (i2c, 0x32, 0x80); - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); - stv0299_writereg (i2c, 0x32, 0x19); - stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type); - stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); - } - break; + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_set(fe, p); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + + stv0299_writeregI(state, 0x32, 0x80); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + stv0299_writeregI(state, 0x32, 0x19); + stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); + stv0299_set_FEC (state, p->u.qpsk.fec_inner); } - - default: - pll_set_tv_freq (i2c, p->frequency, state->tuner_type, p->u.qpsk.symbol_rate); - stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); - stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, state->tuner_type); - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); - stv0299_readreg (i2c, 0x23); - stv0299_writereg (i2c, 0x12, 0xb9); - break; + } else { + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_set(fe, p); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + + stv0299_set_FEC (state, p->u.qpsk.fec_inner); + stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + stv0299_readreg (state, 0x23); + stv0299_writeregI(state, 0x12, 0xb9); } state->tuner_frequency = p->frequency; state->fec_inner = p->u.qpsk.fec_inner; state->symbol_rate = p->u.qpsk.symbol_rate; - break; + + return 0; } - case FE_GET_FRONTEND: +static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p) { - struct dvb_frontend_parameters *p = arg; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; s32 derot_freq; - int Mclk = M_CLK; int invval; - if (state->tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; - - derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8) - | stv0299_readreg (i2c, 0x23)); + derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8) + | stv0299_readreg (state, 0x23)); - derot_freq *= (Mclk >> 16); + derot_freq *= (state->config->mclk >> 16); derot_freq += 500; derot_freq /= 1000; p->frequency += derot_freq; - invval = stv0299_readreg (i2c, 0x0c) & 1; - if (state->tuner_type == ALPS_BSRU6) invval = (~invval) & 1; + invval = stv0299_readreg (state, 0x0c) & 1; + if (state->config->invert) invval = (~invval) & 1; p->inversion = invval ? INVERSION_ON : INVERSION_OFF; - p->u.qpsk.fec_inner = stv0299_get_fec (i2c); - p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c, state->tuner_type); - break; - } + p->u.qpsk.fec_inner = stv0299_get_fec (state); + p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state); - case FE_SLEEP: - stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */ - stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ - stv0299_writereg (i2c, 0x02, 0x80); - state->initialised = 0; - break; - - case FE_INIT: - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - state->tuner_frequency = 0; - if (!state->initialised) { - state->initialised = 1; - return stv0299_init (i2c, state->tuner_type); - } - break; - - default: - return stv0299_init (i2c, state->tuner_type); + return 0; } - break; - case FE_DISEQC_SEND_MASTER_CMD: - return stv0299_send_diseqc_msg (i2c, arg); - - case FE_DISEQC_SEND_BURST: - return stv0299_send_diseqc_burst (i2c, (fe_sec_mini_cmd_t) arg); +static int stv0299_sleep(struct dvb_frontend* fe) +{ + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - case FE_SET_TONE: - return stv0299_set_tone (i2c, (fe_sec_tone_mode_t) arg); + stv0299_writeregI(state, 0x02, 0x80); + state->initialised = 0; - case FE_SET_VOLTAGE: - return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg, - state->tuner_type); + return 0; +} - case FE_GET_TUNE_SETTINGS: +static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; - - switch(state->tuner_type) { - case PHILIPS_SU1278_TSA_TT: - fesettings->min_delay_ms = 50; - if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; - fesettings->max_drift = 5000; - } else { - fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; - fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; - } - break; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; - default: - fesettings->min_delay_ms = 100; + fesettings->min_delay_ms = state->config->min_delay_ms; if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) { fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000; fesettings->max_drift = 5000; @@ -1235,166 +661,103 @@ static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000; fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000; } - break; - } - - return 0; - } - - default: - return -EOPNOTSUPP; - }; - return 0; } -static long probe_tuner (struct dvb_i2c_bus *i2c) -{ - struct dvb_adapter * adapter = (struct dvb_adapter *) i2c->adapter; - - /* read the status register of TSA5059 */ - u8 rpt[] = { 0x05, 0xb5 }; - u8 stat [] = { 0 }; - u8 tda6100_buf [] = { 0, 0 }; - int ret; - struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }}; - - stv0299_writereg (i2c, 0x01, 0x15); - stv0299_writereg (i2c, 0x02, 0x30); - stv0299_writereg (i2c, 0x03, 0x00); - - - printk ("%s: try to attach to %s\n", __FUNCTION__, adapter->name); - - if ( strcmp(adapter->name, "Technisat SkyStar2 driver") == 0 ) - { - printk ("%s: setup for tuner Samsung TBMU24112IMB\n", __FILE__); - - return SAMSUNG_TBMU24112IMB; - } - - if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) { - if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) { - // technotrend cards require non-datasheet settings - printk ("%s: setup for tuner SU1278 (TSA5059 synth) on" - " TechnoTrend hardware\n", __FILE__); - return PHILIPS_SU1278_TSA_TT; - } else { - // fall back to datasheet-recommended settings - printk ("%s: setup for tuner SU1278 (TSA5059 synth)\n", - __FILE__); - return PHILIPS_SU1278_TSA; - } - } - - if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) { - if ( strcmp(adapter->name, "KNC1 DVB-S") == 0 && - !disable_typhoon ) +static void stv0299_release(struct dvb_frontend* fe) { - // Typhoon cards have unusual wiring. - printk ("%s: setup for tuner SU1278 (TSA5059 synth) on" - " Typhoon hardware\n", __FILE__); - return PHILIPS_SU1278_TSA_TY; - } - //else if ((stat[0] & 0x3f) == 0) { - else if (0) { - printk ("%s: setup for tuner TDQF-S001F\n", __FILE__); - return LG_TDQF_S001F; - } else { - printk ("%s: setup for tuner BSRU6, TDQB-S00x\n", - __FILE__); - return ALPS_BSRU6; - } - } - - /** - * setup i2c timing for SU1278... - */ - stv0299_writereg (i2c, 0x02, 0x00); - - if ((ret = i2c->xfer(i2c, msg3, 2)) == 2) { - printk ("%s: setup for tuner Philips SU1278 (TUA6100 synth)\n", - __FILE__); - return PHILIPS_SU1278_TUA; - } - - printk ("%s: unknown PLL synthesizer (ret == %i), " - "please report to !!\n", - __FILE__, ret); - - return UNKNOWN_FRONTEND; + struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops stv0299_ops; -static int uni0299_attach (struct dvb_i2c_bus *i2c, void **data) +struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, + struct i2c_adapter* i2c) { - struct stv0299_state* state; - int tuner_type; - u8 id; + struct stv0299_state* state = NULL; + int id; - stv0299_writereg (i2c, 0x02, 0x34); /* standby off */ - dvb_delay(200); - id = stv0299_readreg (i2c, 0x00); + /* allocate memory for the internal state */ + state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->tuner_frequency = 0; + state->symbol_rate = 0; + state->fec_inner = 0; + state->errmode = STATUS_BER; - dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id); + /* check if the demod is there */ + stv0299_writeregI(state, 0x02, 0x34); /* standby off */ + msleep(200); + id = stv0299_readreg(state, 0x00); /* register 0x00 contains 0xa1 for STV0299 and STV0299B */ /* register 0x00 might contain 0x80 when returning from standby */ - if (id != 0xa1 && id != 0x80) - return -ENODEV; + if (id != 0xa1 && id != 0x80) goto error; - if ((tuner_type = probe_tuner(i2c)) < 0) - return -ENODEV; + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; - if ((state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - - *data = state; - state->tuner_type = tuner_type; - state->tuner_frequency = 0; - state->initialised = 0; - return dvb_register_frontend (uni0299_ioctl, i2c, (void *) state, - &uni0299_info); +error: + if (state) kfree(state); + return NULL; } +static struct dvb_frontend_ops stv0299_ops = { + + .info = { + .name = "ST STV0299 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + + .release = stv0299_release, + + .init = stv0299_init, + .sleep = stv0299_sleep, + + .set_frontend = stv0299_set_frontend, + .get_frontend = stv0299_get_frontend, + .get_tune_settings = stv0299_get_tune_settings, + + .read_status = stv0299_read_status, + .read_ber = stv0299_read_ber, + .read_signal_strength = stv0299_read_signal_strength, + .read_snr = stv0299_read_snr, + .read_ucblocks = stv0299_read_ucblocks, + + .diseqc_send_master_cmd = stv0299_send_diseqc_msg, + .diseqc_send_burst = stv0299_send_diseqc_burst, + .set_tone = stv0299_set_tone, + .set_voltage = stv0299_set_voltage, + .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd, +}; -static void uni0299_detach (struct dvb_i2c_bus *i2c, void *data) -{ - dprintk ("%s\n", __FUNCTION__); - kfree(data); - dvb_unregister_frontend (uni0299_ioctl, i2c); -} - - -static int __init init_uni0299 (void) -{ - dprintk ("%s\n", __FUNCTION__); - return dvb_register_i2c_device (NULL, uni0299_attach, uni0299_detach); -} - - -static void __exit exit_uni0299 (void) -{ - dprintk ("%s\n", __FUNCTION__); - - dvb_unregister_i2c_device (uni0299_attach); -} - -module_init (init_uni0299); -module_exit (exit_uni0299); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("Universal STV0299/TSA5059/SL1935 DVB Frontend driver"); -MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter, Andrew de Quincey"); +MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver"); +MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, " + "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy"); MODULE_LICENSE("GPL"); -MODULE_PARM(stv0299_status, "i"); -MODULE_PARM_DESC(stv0299_status, "Which status value to support (0: BER, 1: UCBLOCKS)"); - -MODULE_PARM(disable_typhoon, "i"); -MODULE_PARM_DESC(disable_typhoon, "Disable support for Philips SU1278 on Typhoon hardware."); +EXPORT_SYMBOL(stv0299_writereg); +EXPORT_SYMBOL(stv0299_attach); diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 28dc299a8..1e38162c2 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -1,5 +1,5 @@ /* - Driver for Philips tda1004xh OFDM Frontend + Driver for Philips tda1004xh OFDM Demodulator (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach @@ -19,179 +19,128 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* - This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend - windows driver saved as '/usr/lib/hotplug/firmware/tda1004x.bin'. - You can also pass the complete file name with the module parameter 'tda1004x_firmware'. - - Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can - be added reasonably painlessly. - - Windows driver URL: http://www.technotrend.de/ + * This driver needs external firmware. Please use the commands + * "/Documentation/dvb/get_dvb_firmware tda10045", + * "/Documentation/dvb/get_dvb_firmware tda10046" to + * download/extract them, and then copy them to /usr/lib/hotplug/firmware. */ +#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw" +#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw" - -#include -#include -#include #include -#include -#include -#include -#include -#include -#include - +#include +#include +#include #include "dvb_frontend.h" -#include "dvb_functions.h" - -#ifndef DVB_TDA1004X_FIRMWARE_FILE -#define DVB_TDA1004X_FIRMWARE_FILE "/usr/lib/hotplug/firmware/tda1004x.bin" -#endif - -static int tda1004x_debug = 0; -static char *tda1004x_firmware = DVB_TDA1004X_FIRMWARE_FILE; - -#define MC44BC374_ADDRESS 0x65 - -#define TDA1004X_CHIPID 0x00 -#define TDA1004X_AUTO 0x01 -#define TDA1004X_IN_CONF1 0x02 -#define TDA1004X_IN_CONF2 0x03 -#define TDA1004X_OUT_CONF1 0x04 -#define TDA1004X_OUT_CONF2 0x05 -#define TDA1004X_STATUS_CD 0x06 -#define TDA1004X_CONFC4 0x07 -#define TDA1004X_DSSPARE2 0x0C -#define TDA10045H_CODE_IN 0x0D -#define TDA10045H_FWPAGE 0x0E -#define TDA1004X_SCAN_CPT 0x10 -#define TDA1004X_DSP_CMD 0x11 -#define TDA1004X_DSP_ARG 0x12 -#define TDA1004X_DSP_DATA1 0x13 -#define TDA1004X_DSP_DATA2 0x14 -#define TDA1004X_CONFADC1 0x15 -#define TDA1004X_CONFC1 0x16 -#define TDA10045H_S_AGC 0x1a -#define TDA10046H_AGC_TUN_LEVEL 0x1a -#define TDA1004X_SNR 0x1c -#define TDA1004X_CONF_TS1 0x1e -#define TDA1004X_CONF_TS2 0x1f -#define TDA1004X_CBER_RESET 0x20 -#define TDA1004X_CBER_MSB 0x21 -#define TDA1004X_CBER_LSB 0x22 -#define TDA1004X_CVBER_LUT 0x23 -#define TDA1004X_VBER_MSB 0x24 -#define TDA1004X_VBER_MID 0x25 -#define TDA1004X_VBER_LSB 0x26 -#define TDA1004X_UNCOR 0x27 - -#define TDA10045H_CONFPLL_P 0x2D -#define TDA10045H_CONFPLL_M_MSB 0x2E -#define TDA10045H_CONFPLL_M_LSB 0x2F -#define TDA10045H_CONFPLL_N 0x30 - -#define TDA10046H_CONFPLL1 0x2D -#define TDA10046H_CONFPLL2 0x2F -#define TDA10046H_CONFPLL3 0x30 -#define TDA10046H_TIME_WREF1 0x31 -#define TDA10046H_TIME_WREF2 0x32 -#define TDA10046H_TIME_WREF3 0x33 -#define TDA10046H_TIME_WREF4 0x34 -#define TDA10046H_TIME_WREF5 0x35 - -#define TDA10045H_UNSURW_MSB 0x31 -#define TDA10045H_UNSURW_LSB 0x32 -#define TDA10045H_WREF_MSB 0x33 -#define TDA10045H_WREF_MID 0x34 -#define TDA10045H_WREF_LSB 0x35 -#define TDA10045H_MUXOUT 0x36 -#define TDA1004X_CONFADC2 0x37 - -#define TDA10045H_IOFFSET 0x38 +#include "tda1004x.h" -#define TDA10046H_CONF_TRISTATE1 0x3B -#define TDA10046H_CONF_TRISTATE2 0x3C -#define TDA10046H_CONF_POLARITY 0x3D -#define TDA10046H_FREQ_OFFSET 0x3E -#define TDA10046H_GPIO_OUT_SEL 0x41 -#define TDA10046H_GPIO_SELECT 0x42 -#define TDA10046H_AGC_CONF 0x43 -#define TDA10046H_AGC_GAINS 0x46 -#define TDA10046H_AGC_TUN_MIN 0x47 -#define TDA10046H_AGC_TUN_MAX 0x48 -#define TDA10046H_AGC_IF_MIN 0x49 -#define TDA10046H_AGC_IF_MAX 0x4A - -#define TDA10046H_FREQ_PHY2_MSB 0x4D -#define TDA10046H_FREQ_PHY2_LSB 0x4E - -#define TDA10046H_CVBER_CTRL 0x4F -#define TDA10046H_AGC_IF_LEVEL 0x52 -#define TDA10046H_CODE_CPT 0x57 -#define TDA10046H_CODE_IN 0x58 - - -#define FE_TYPE_TDA10045H 0 -#define FE_TYPE_TDA10046H 1 - -#define TUNER_TYPE_TD1344 0 -#define TUNER_TYPE_TD1316 1 - -#define dprintk if (tda1004x_debug) printk - -static struct dvb_frontend_info tda10045h_info = { - .name = "Philips TDA10045H", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, - .caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO -}; +#define TDA1004X_DEMOD_TDA10045 0 +#define TDA1004X_DEMOD_TDA10046 1 -static struct dvb_frontend_info tda10046h_info = { - .name = "Philips TDA10046H", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 166667, - .caps = - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO -}; +struct tda1004x_state +{ + struct i2c_adapter* i2c; -struct tda1004x_state { - u8 tda1004x_address; - u8 tuner_address; - u8 initialised:1; - u8 tuner_type:2; - u8 fe_type:2; -}; + struct dvb_frontend_ops ops; + const struct tda1004x_config* config; -struct fwinfo { - int file_size; - int fw_offset; - int fw_size; -}; -static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555} }; -static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo); + struct dvb_frontend frontend; + + /* private demod data */ + u8 initialised:1; -static struct fwinfo tda10046h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x3c4f9,.fw_size = 24479} }; -static int tda10046h_fwinfo_count = sizeof(tda10046h_fwinfo) / sizeof(struct fwinfo); + u8 demod_type; +}; -static int errno; +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "tda1004x: " args); \ + } while (0) + +#define TDA1004X_CHIPID 0x00 +#define TDA1004X_AUTO 0x01 +#define TDA1004X_IN_CONF1 0x02 +#define TDA1004X_IN_CONF2 0x03 +#define TDA1004X_OUT_CONF1 0x04 +#define TDA1004X_OUT_CONF2 0x05 +#define TDA1004X_STATUS_CD 0x06 +#define TDA1004X_CONFC4 0x07 +#define TDA1004X_DSSPARE2 0x0C +#define TDA10045H_CODE_IN 0x0D +#define TDA10045H_FWPAGE 0x0E +#define TDA1004X_SCAN_CPT 0x10 +#define TDA1004X_DSP_CMD 0x11 +#define TDA1004X_DSP_ARG 0x12 +#define TDA1004X_DSP_DATA1 0x13 +#define TDA1004X_DSP_DATA2 0x14 +#define TDA1004X_CONFADC1 0x15 +#define TDA1004X_CONFC1 0x16 +#define TDA10045H_S_AGC 0x1a +#define TDA10046H_AGC_TUN_LEVEL 0x1a +#define TDA1004X_SNR 0x1c +#define TDA1004X_CONF_TS1 0x1e +#define TDA1004X_CONF_TS2 0x1f +#define TDA1004X_CBER_RESET 0x20 +#define TDA1004X_CBER_MSB 0x21 +#define TDA1004X_CBER_LSB 0x22 +#define TDA1004X_CVBER_LUT 0x23 +#define TDA1004X_VBER_MSB 0x24 +#define TDA1004X_VBER_MID 0x25 +#define TDA1004X_VBER_LSB 0x26 +#define TDA1004X_UNCOR 0x27 + +#define TDA10045H_CONFPLL_P 0x2D +#define TDA10045H_CONFPLL_M_MSB 0x2E +#define TDA10045H_CONFPLL_M_LSB 0x2F +#define TDA10045H_CONFPLL_N 0x30 + +#define TDA10046H_CONFPLL1 0x2D +#define TDA10046H_CONFPLL2 0x2F +#define TDA10046H_CONFPLL3 0x30 +#define TDA10046H_TIME_WREF1 0x31 +#define TDA10046H_TIME_WREF2 0x32 +#define TDA10046H_TIME_WREF3 0x33 +#define TDA10046H_TIME_WREF4 0x34 +#define TDA10046H_TIME_WREF5 0x35 + +#define TDA10045H_UNSURW_MSB 0x31 +#define TDA10045H_UNSURW_LSB 0x32 +#define TDA10045H_WREF_MSB 0x33 +#define TDA10045H_WREF_MID 0x34 +#define TDA10045H_WREF_LSB 0x35 +#define TDA10045H_MUXOUT 0x36 +#define TDA1004X_CONFADC2 0x37 + +#define TDA10045H_IOFFSET 0x38 -static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data) +#define TDA10046H_CONF_TRISTATE1 0x3B +#define TDA10046H_CONF_TRISTATE2 0x3C +#define TDA10046H_CONF_POLARITY 0x3D +#define TDA10046H_FREQ_OFFSET 0x3E +#define TDA10046H_GPIO_OUT_SEL 0x41 +#define TDA10046H_GPIO_SELECT 0x42 +#define TDA10046H_AGC_CONF 0x43 +#define TDA10046H_AGC_GAINS 0x46 +#define TDA10046H_AGC_TUN_MIN 0x47 +#define TDA10046H_AGC_TUN_MAX 0x48 +#define TDA10046H_AGC_IF_MIN 0x49 +#define TDA10046H_AGC_IF_MAX 0x4A + +#define TDA10046H_FREQ_PHY2_MSB 0x4D +#define TDA10046H_FREQ_PHY2_LSB 0x4E + +#define TDA10046H_CVBER_CTRL 0x4F +#define TDA10046H_AGC_IF_LEVEL 0x52 +#define TDA10046H_CODE_CPT 0x57 +#define TDA10046H_CODE_IN 0x58 + + +static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data) { int ret; u8 buf[] = { reg, data }; @@ -199,35 +148,35 @@ static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *t dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data); - msg.addr = tda_state->tda1004x_address; - ret = i2c->xfer(i2c, &msg, 1); + msg.addr = state->config->demod_address; + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", - __FUNCTION__, reg, data, ret); + __FUNCTION__, reg, data, ret); dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__, reg, data, ret); return (ret != 1) ? -1 : 0; } -static int tda1004x_read_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg) +static int tda1004x_read_byte(struct tda1004x_state *state, int reg) { int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; struct i2c_msg msg[] = {{ .addr=0, .flags=0, .buf=b0, .len=1}, - { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}}; + { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}}; dprintk("%s: reg=0x%x\n", __FUNCTION__, reg); - msg[0].addr = tda_state->tda1004x_address; - msg[1].addr = tda_state->tda1004x_address; - ret = i2c->xfer(i2c, msg, 2); + msg[0].addr = state->config->demod_address; + msg[1].addr = state->config->demod_address; + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, - ret); + ret); return -1; } @@ -236,14 +185,14 @@ static int tda1004x_read_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *td return b1[0]; } -static int tda1004x_write_mask(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int mask, int data) +static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data) { - int val; + int val; dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg, mask, data); // read a byte and check - val = tda1004x_read_byte(i2c, tda_state, reg); + val = tda1004x_read_byte(state, reg); if (val < 0) return val; @@ -252,10 +201,10 @@ static int tda1004x_write_mask(struct dvb_i2c_bus *i2c, struct tda1004x_state *t val |= data & 0xff; // write it out again - return tda1004x_write_byte(i2c, tda_state, reg, val); + return tda1004x_write_byteI(state, reg, val); } -static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, unsigned char *buf, int len) +static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len) { int i; int result; @@ -264,7 +213,7 @@ static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *td result = 0; for (i = 0; i < len; i++) { - result = tda1004x_write_byte(i2c, tda_state, reg + i, buf[i]); + result = tda1004x_write_byteI(state, reg + i, buf[i]); if (result != 0) break; } @@ -272,357 +221,218 @@ static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *td return result; } -static int tda1004x_enable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state) { - int result; + int result; dprintk("%s\n", __FUNCTION__); - result = tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 2); - dvb_delay(1); + result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2); + msleep(1); return result; } -static int tda1004x_disable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state) { - dprintk("%s\n", __FUNCTION__); - return tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 0); + return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0); } - -static int tda10045h_set_bandwidth(struct dvb_i2c_bus *i2c, - struct tda1004x_state *tda_state, - fe_bandwidth_t bandwidth) +static int tda10045h_set_bandwidth(struct tda1004x_state *state, + fe_bandwidth_t bandwidth) { - static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; - static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; - static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; + static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; + static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; + static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; - switch (bandwidth) { + switch (bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x80); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); break; default: return -EINVAL; } - tda1004x_write_byte(i2c, tda_state, TDA10045H_IOFFSET, 0); + tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0); - // done - return 0; + return 0; } - -static int tda10046h_set_bandwidth(struct dvb_i2c_bus *i2c, - struct tda1004x_state *tda_state, - fe_bandwidth_t bandwidth) +static int tda10046h_set_bandwidth(struct tda1004x_state *state, + fe_bandwidth_t bandwidth) { - static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e }; - static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 }; - static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd }; - - switch (bandwidth) { - case BANDWIDTH_6_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); - break; - - case BANDWIDTH_7_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); - break; - - case BANDWIDTH_8_MHZ: - tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0xFF); - break; - - default: - return -EINVAL; - } - - // done - return 0; -} + static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e }; + static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 }; + static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd }; + switch (bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + break; -static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) + case BANDWIDTH_7_MHZ: + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int tda1004x_do_upload(struct tda1004x_state *state, + unsigned char *mem, unsigned int len, + u8 dspCodeCounterReg, u8 dspCodeInReg) { - u8 fw_buf[65]; - struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 }; - unsigned char *firmware = NULL; - int filesize; - int fd; - int fwinfo_idx; - int fw_size = 0; - int fw_pos, fw_offset; + u8 buf[65]; + struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = buf,.len = 0 }; int tx_size; - mm_segment_t fs = get_fs(); - int dspCodeCounterReg=0, dspCodeInReg=0, dspVersion=0; - int fwInfoCount=0; - struct fwinfo* fwInfo = NULL; - unsigned long timeout; - - // DSP parameters - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - dspCodeCounterReg = TDA10045H_FWPAGE; - dspCodeInReg = TDA10045H_CODE_IN; - dspVersion = 0x2c; - fwInfoCount = tda10045h_fwinfo_count; - fwInfo = tda10045h_fwinfo; - break; - - case FE_TYPE_TDA10046H: - dspCodeCounterReg = TDA10046H_CODE_CPT; - dspCodeInReg = TDA10046H_CODE_IN; - dspVersion = 0x20; - fwInfoCount = tda10046h_fwinfo_count; - fwInfo = tda10046h_fwinfo; - break; - } - - // Load the firmware - set_fs(get_ds()); - fd = sys_open(tda1004x_firmware, 0, 0); - if (fd < 0) { - printk("%s: Unable to open firmware %s\n", __FUNCTION__, - tda1004x_firmware); - return -EIO; - } - filesize = sys_lseek(fd, 0L, 2); - if (filesize <= 0) { - printk("%s: Firmware %s is empty\n", __FUNCTION__, - tda1004x_firmware); - sys_close(fd); - return -EIO; - } + int pos = 0; - // find extraction parameters for firmware - for (fwinfo_idx = 0; fwinfo_idx < fwInfoCount; fwinfo_idx++) { - if (fwInfo[fwinfo_idx].file_size == filesize) - break; - } - if (fwinfo_idx >= fwInfoCount) { - printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware); - sys_close(fd); - return -EIO; - } - fw_size = fwInfo[fwinfo_idx].fw_size; - fw_offset = fwInfo[fwinfo_idx].fw_offset; - - // allocate buffer for it - firmware = vmalloc(fw_size); - if (firmware == NULL) { - printk("%s: Out of memory loading firmware\n", - __FUNCTION__); - sys_close(fd); - return -EIO; - } + /* clear code counter */ + tda1004x_write_byteI(state, dspCodeCounterReg, 0); + fw_msg.addr = state->config->demod_address; - // read it! - sys_lseek(fd, fw_offset, 0); - if (sys_read(fd, firmware, fw_size) != fw_size) { - printk("%s: Failed to read firmware\n", __FUNCTION__); - vfree(firmware); - sys_close(fd); - return -EIO; - } - sys_close(fd); - set_fs(fs); - - // set some valid bandwith parameters before uploading - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - // reset chip - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); - dvb_delay(10); - - // set parameters - tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); - break; - - case FE_TYPE_TDA10046H: - // reset chip - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0); - dvb_delay(10); - - // set parameters - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST - break; - } - - // do the firmware upload - tda1004x_write_byte(i2c, tda_state, dspCodeCounterReg, 0); // clear code counter - fw_msg.addr = tda_state->tda1004x_address; - fw_pos = 0; - while (fw_pos != fw_size) { + buf[0] = dspCodeInReg; + while (pos != len) { // work out how much to send this time - tx_size = fw_size - fw_pos; - if (tx_size > 0x10) { - tx_size = 0x10; + tx_size = len - pos; + if (tx_size > 0x10) { + tx_size = 0x10; } // send the chunk - fw_buf[0] = dspCodeInReg; - memcpy(fw_buf + 1, firmware + fw_pos, tx_size); + memcpy(buf + 1, mem + pos, tx_size); fw_msg.len = tx_size + 1; - if (i2c->xfer(i2c, &fw_msg, 1) != 1) { - printk("tda1004x: Error during firmware upload\n"); - vfree(firmware); + if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) { + printk("tda1004x: Error during firmware upload\n"); return -EIO; } - fw_pos += tx_size; + pos += tx_size; - dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos); + dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos); } - vfree(firmware); - - // wait for DSP to initialise - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - // DSPREADY doesn't seem to work on the TDA10045H - dvb_delay(100); - break; - - case FE_TYPE_TDA10046H: - timeout = jiffies + HZ; - while(!(tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD) & 0x20)) { - if (time_after(jiffies, timeout)) { - printk("tda1004x: DSP failed to initialised.\n"); - return -EIO; - } - - dvb_delay(1); - } - break; - } - - // check upload was OK - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP - tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67); - if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) || - (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != dspVersion)) { - printk("%s: firmware upload failed!\n", __FUNCTION__); + return 0; +} + +static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion) +{ + u8 data1, data2; + + // check upload was OK + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP + tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67); + + data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1); + data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2); + if (data1 != 0x67 || data2 != dspVersion) { return -EIO; } - // success - return 0; + return 0; } -static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +static int tda10045_fwupload(struct dvb_frontend* fe) { - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = NULL,.len = 0 }; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + struct tda1004x_state* state = fe->demodulator_priv; + int ret; + const struct firmware *fw; + - dprintk("%s\n", __FUNCTION__); + /* don't re-upload unless necessary */ + if (tda1004x_check_upload_ok(state, 0x2c) == 0) return 0; - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC + /* request the firmware, this will block until someone uploads it */ + printk("tda1004x: waiting for firmware upload...\n"); + ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE); + if (ret) { + printk("tda1004x: no firmware upload (timeout or file not found?)\n"); + return ret; + } - // Disable the MC44BC374C - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = MC44BC374_ADDRESS; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { - i2c->xfer(i2c, &tuner_msg, 1); - } - tda1004x_disable_tuner_i2c(i2c, tda_state); + /* reset chip */ + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); + msleep(10); - // tda setup - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); // no frequency inversion - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface - tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); - - // done - return 0; -} + /* set parameters */ + tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ); + ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN); + if (ret) + return ret; + /* wait for DSP to initialise */ + /* DSPREADY doesn't seem to work on the TDA10045H */ + msleep(100); -static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) -{ - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = NULL,.len = 0 }; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; - - dprintk("%s\n", __FUNCTION__); - - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 0); // wake up the chip - - // Disable the MC44BC374C - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = MC44BC374_ADDRESS; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { - i2c->xfer(i2c, &tuner_msg, 1); - } - tda1004x_disable_tuner_i2c(i2c, tda_state); - - // tda setup - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0x40); // TT TDA10046H needs inversion ON - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); // PLL M = 10 - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 - tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_CONF, 0); // AGC setup - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MIN, 0); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MIN, 0); // } - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MAX, 0xff); // } - tda1004x_write_mask(i2c, tda_state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits - tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm - tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config - tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN - tda1004x_write_byte(i2c, tda_state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup - tda1004x_write_byte(i2c, tda_state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config - tda1004x_write_mask(i2c, tda_state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select - tda10046h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz - - // done - return 0; + return tda1004x_check_upload_ok(state, 0x2c); } +static int tda10046_fwupload(struct dvb_frontend* fe) +{ + struct tda1004x_state* state = fe->demodulator_priv; + unsigned long timeout; + int ret; + const struct firmware *fw; + + /* reset + wake up chip */ + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); + msleep(100); + + /* don't re-upload unless necessary */ + if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0; + + /* request the firmware, this will block until someone uploads it */ + printk("tda1004x: waiting for firmware upload...\n"); + ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE); + if (ret) { + printk("tda1004x: no firmware upload (timeout or file not found?)\n"); + return ret; + } + + /* set parameters */ + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); + tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST + + ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN); + if (ret) + return ret; + + /* wait for DSP to initialise */ + timeout = jiffies + HZ; + while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) { + if (time_after(jiffies, timeout)) { + printk("tda1004x: DSP failed to initialised.\n"); + return -EIO; + } + msleep(1); + } + return tda1004x_check_upload_ok(state, 0x20); +} static int tda1004x_encode_fec(int fec) { @@ -664,217 +474,194 @@ static int tda1004x_decode_fec(int tdafec) return -1; } -static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c, - struct tda1004x_state *tda_state, - struct dvb_frontend_parameters *fe_params) -{ - u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; - int tuner_frequency = 0; - u8 band, cp, filter; - int counter, counter2; - dprintk("%s\n", __FUNCTION__); - // setup the frequency buffer - switch (tda_state->tuner_type) { - case TUNER_TYPE_TD1344: - - // setup tuner buffer - // ((Fif+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217502) / 1000; - tuner_buf[0] = tuner_frequency >> 8; - tuner_buf[1] = tuner_frequency & 0xff; - tuner_buf[2] = 0x88; - if (fe_params->frequency < 550000000) { - tuner_buf[3] = 0xab; - } else { - tuner_buf[3] = 0xeb; - } - // tune it - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = tda_state->tuner_address; - tuner_msg.len = 4; - i2c->xfer(i2c, &tuner_msg, 1); - - // wait for it to finish - tuner_msg.len = 1; - tuner_msg.flags = I2C_M_RD; - counter = 0; - counter2 = 0; - while (counter++ < 100) { - if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - if (tuner_buf[0] & 0x40) { - counter2++; - } else { - counter2 = 0; - } - } - - if (counter2 > 10) { - break; - } - } - tda1004x_disable_tuner_i2c(i2c, tda_state); - break; - case TUNER_TYPE_TD1316: - // determine charge pump - tuner_frequency = fe_params->frequency + 36130000; - if (tuner_frequency < 87000000) { - return -EINVAL; - } else if (tuner_frequency < 130000000) { - cp = 3; - } else if (tuner_frequency < 160000000) { - cp = 5; - } else if (tuner_frequency < 200000000) { - cp = 6; - } else if (tuner_frequency < 290000000) { - cp = 3; - } else if (tuner_frequency < 420000000) { - cp = 5; - } else if (tuner_frequency < 480000000) { - cp = 6; - } else if (tuner_frequency < 620000000) { - cp = 3; - } else if (tuner_frequency < 830000000) { - cp = 5; - } else if (tuner_frequency < 895000000) { - cp = 7; - } else { - return -EINVAL; - } - // determine band - if (fe_params->frequency < 49000000) { - return -EINVAL; - } else if (fe_params->frequency < 159000000) { - band = 1; - } else if (fe_params->frequency < 444000000) { - band = 2; - } else if (fe_params->frequency < 861000000) { - band = 4; - } else { - return -EINVAL; + + + + + + + + + + + + +int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data) +{ + struct tda1004x_state* state = fe->demodulator_priv; + + return tda1004x_write_byteI(state, reg, data); } - // work out filter - switch (fe_params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - filter = 0; - break; +static int tda10045_init(struct dvb_frontend* fe) +{ + struct tda1004x_state* state = fe->demodulator_priv; - case BANDWIDTH_7_MHZ: - filter = 0; - break; + dprintk("%s\n", __FUNCTION__); - case BANDWIDTH_8_MHZ: - filter = 1; - break; + if (state->initialised) return 0; - default: - return -EINVAL; + if (tda10045_fwupload(fe)) { + printk("tda1004x: firmware upload failed\n"); + return -EIO; } - // calculate divisor - // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) - tuner_frequency = - (((fe_params->frequency / 1000) * 6) + 217280) / 1000; - - // setup tuner buffer - tuner_buf[0] = tuner_frequency >> 8; - tuner_buf[1] = tuner_frequency & 0xff; - tuner_buf[2] = 0xca; - tuner_buf[3] = (cp << 5) | (filter << 3) | band; - - // tune it - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - // setup auto offset - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0); - - // disable agc_conf[2] - tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 0); - } - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = tda_state->tuner_address; - tuner_msg.len = 4; - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC + + // Init the PLL + if (state->config->pll_init) { + tda1004x_enable_tuner_i2c(state); + state->config->pll_init(fe); + tda1004x_disable_tuner_i2c(state); + } + + // tda setup + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer + tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset + tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface + tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface + tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity + tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e); + + tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk); + + state->initialised = 1; + return 0; + } + +static int tda10046_init(struct dvb_frontend* fe) +{ + struct tda1004x_state* state = fe->demodulator_priv; + dprintk("%s\n", __FUNCTION__); + + if (state->initialised) return 0; + + if (tda10046_fwupload(fe)) { + printk("tda1004x: firmware upload failed\n"); return -EIO; } - dvb_delay(1); - tda1004x_disable_tuner_i2c(i2c, tda_state); - if (tda_state->fe_type == FE_TYPE_TDA10046H) - tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 4); - break; - default: - return -EINVAL; - } + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); // wake up the chip - dprintk("%s: success\n", __FUNCTION__); + // Init the PLL + if (state->config->pll_init) { + tda1004x_enable_tuner_i2c(state); + state->config->pll_init(fe); + tda1004x_disable_tuner_i2c(state); + } - // done + // tda setup + tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0x40); + tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10 + tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 + tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 + tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } + tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0); // AGC setup + tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities + tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // } + tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values + tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // } + tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // } + tda1004x_write_mask(state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits + tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 + tda1004x_write_mask(state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm + tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config + tda1004x_write_mask(state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN + tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup + tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config + tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select + tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + + tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7); + + state->initialised = 1; return 0; } -static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, - struct tda1004x_state *tda_state, - struct dvb_frontend_parameters *fe_params) +static int tda1004x_set_fe(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fe_params) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; - int inversion; + int inversion; dprintk("%s\n", __FUNCTION__); - // set frequency - if ((tmp = tda1004x_set_frequency(i2c, tda_state, fe_params)) < 0) - return tmp; + if (state->demod_type == TDA1004X_DEMOD_TDA10046) { + // setup auto offset + tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0); - // hardcoded to use auto as much as possible - fe_params->u.ofdm.code_rate_HP = FEC_AUTO; - fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; - fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + // disable agc_conf[2] + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0); + } + + // set frequency + tda1004x_enable_tuner_i2c(state); + state->config->pll_set(fe, fe_params); + tda1004x_disable_tuner_i2c(state); + + if (state->demod_type == TDA1004X_DEMOD_TDA10046) + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4); + + // Hardcoded to use auto as much as possible on the TDA10045 as it + // is very unreliable if AUTO mode is _not_ used. + if (state->demod_type == TDA1004X_DEMOD_TDA10045) { + fe_params->u.ofdm.code_rate_HP = FEC_AUTO; + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + } // Set standard params.. or put them to auto if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || (fe_params->u.ofdm.constellation == QAM_AUTO) || (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1); // enable auto - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits } else { - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0); // disable auto + tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto // set HP FEC tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP); if (tmp < 0) return tmp; - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp); + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp); // set LP FEC - if (fe_params->u.ofdm.code_rate_LP != FEC_NONE) { - tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); - if (tmp < 0) return tmp; - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3); - } + tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); + if (tmp < 0) return tmp; + tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3); // set constellation switch (fe_params->u.ofdm.constellation) { case QPSK: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0); break; case QAM_16: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1); break; case QAM_64: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2); break; default: @@ -884,19 +671,19 @@ static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, // set hierarchy switch (fe_params->u.ofdm.hierarchy_information) { case HIERARCHY_NONE: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5); break; case HIERARCHY_1: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5); break; case HIERARCHY_2: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5); break; case HIERARCHY_4: - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5); break; default: @@ -904,31 +691,27 @@ static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, } } - // set bandwidth - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); - break; - - case FE_TYPE_TDA10046H: - tda10046h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); - break; - } + // set bandwidth + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); + break; - // need to invert the inversion for TT TDA10046H - inversion = fe_params->inversion; - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - inversion = inversion ? INVERSION_OFF : INVERSION_ON; - } + case TDA1004X_DEMOD_TDA10046: + tda10046h_set_bandwidth(state, fe_params->u.ofdm.bandwidth); + break; + } // set inversion - switch (inversion) { + inversion = fe_params->inversion; + if (state->config->invert) inversion = inversion ? INVERSION_OFF : INVERSION_ON; + switch (inversion) { case INVERSION_OFF: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0); break; case INVERSION_ON: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20); + tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20); break; default: @@ -938,28 +721,28 @@ static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, // set guard interval switch (fe_params->u.ofdm.guard_interval) { case GUARD_INTERVAL_1_32: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; case GUARD_INTERVAL_1_16: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); break; case GUARD_INTERVAL_1_8: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); break; case GUARD_INTERVAL_1_4: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); break; case GUARD_INTERVAL_AUTO: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); break; default: @@ -969,98 +752,92 @@ static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, // set transmission mode switch (fe_params->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4); break; case TRANSMISSION_MODE_8K: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4); break; case TRANSMISSION_MODE_AUTO: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0); + tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4); + tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0); break; default: return -EINVAL; } - // start the lock - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); - dvb_delay(10); - break; - - case FE_TYPE_TDA10046H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x40, 0x40); - dvb_delay(10); - break; - } - - // done + // start the lock + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0); + msleep(10); + break; + + case TDA1004X_DEMOD_TDA10046: + tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40); + msleep(10); + break; + } + return 0; } - -static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params) +static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) { - + struct tda1004x_state* state = fe->demodulator_priv; dprintk("%s\n", __FUNCTION__); // inversion status fe_params->inversion = INVERSION_OFF; - if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) { + if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) { fe_params->inversion = INVERSION_ON; } - - // need to invert the inversion for TT TDA10046H - if (tda_state->fe_type == FE_TYPE_TDA10046H) { - fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; - } + if (state->config->invert) fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; // bandwidth - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - switch (tda1004x_read_byte(i2c, tda_state, TDA10045H_WREF_LSB)) { - case 0x14: - fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; - break; - case 0xdb: - fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) { + case 0x14: + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + break; + case 0xdb: + fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + break; + case 0x4f: + fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + break; + } break; - case 0x4f: - fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + + case TDA1004X_DEMOD_TDA10046: + switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) { + case 0x60: + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + break; + case 0x6e: + fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + break; + case 0x80: + fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + break; + } break; } - break; - - case FE_TYPE_TDA10046H: - switch (tda1004x_read_byte(i2c, tda_state, TDA10046H_TIME_WREF1)) { - case 0x60: - fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; - break; - case 0x6e: - fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; - break; - case 0x80: - fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; - break; - } - break; - } // FEC fe_params->u.ofdm.code_rate_HP = - tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7); + tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7); fe_params->u.ofdm.code_rate_LP = - tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7); + tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7); // constellation - switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) { + switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) { case 0: fe_params->u.ofdm.constellation = QPSK; break; @@ -1074,12 +851,12 @@ static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_s // transmission mode fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; - if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) { + if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) { fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; } // guard interval - switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { case 0: fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; @@ -1095,7 +872,7 @@ static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_s } // hierarchy - switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { + switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { case 0: fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; break; @@ -1110,125 +887,124 @@ static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_s break; } - // done return 0; } - -static int tda1004x_read_status(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status) +static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status) { + struct tda1004x_state* state = fe->demodulator_priv; int status; - int cber; - int vber; + int cber; + int vber; dprintk("%s\n", __FUNCTION__); // read status - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD); + status = tda1004x_read_byte(state, TDA1004X_STATUS_CD); if (status == -1) { return -EIO; } - // decode + // decode *fe_status = 0; - if (status & 4) *fe_status |= FE_HAS_SIGNAL; - if (status & 2) *fe_status |= FE_HAS_CARRIER; - if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; - - // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi - // is getting anything valid - if (!(*fe_status & FE_HAS_VITERBI)) { - // read the CBER - cber = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); - if (cber == -1) return -EIO; - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); - if (status == -1) return -EIO; - cber |= (status << 8); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); - - if (cber != 65535) { - *fe_status |= FE_HAS_VITERBI; - } - } - - // if we DO have some valid VITERBI output, but don't already have SYNC - // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. - if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { - // read the VBER - vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB); - if (vber == -1) return -EIO; - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID); - if (status == -1) return -EIO; - vber |= (status << 8); - status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB); - if (status == -1) return -EIO; - vber |= ((status << 16) & 0x0f); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT); - - // if RS has passed some valid TS packets, then we must be - // getting some SYNC bytes - if (vber < 16632) { - *fe_status |= FE_HAS_SYNC; - } - } + if (status & 4) *fe_status |= FE_HAS_SIGNAL; + if (status & 2) *fe_status |= FE_HAS_CARRIER; + if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + + // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi + // is getting anything valid + if (!(*fe_status & FE_HAS_VITERBI)) { + // read the CBER + cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB); + if (cber == -1) return -EIO; + status = tda1004x_read_byte(state, TDA1004X_CBER_MSB); + if (status == -1) return -EIO; + cber |= (status << 8); + tda1004x_read_byte(state, TDA1004X_CBER_RESET); + + if (cber != 65535) { + *fe_status |= FE_HAS_VITERBI; + } + } + + // if we DO have some valid VITERBI output, but don't already have SYNC + // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. + if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { + // read the VBER + vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB); + if (vber == -1) return -EIO; + status = tda1004x_read_byte(state, TDA1004X_VBER_MID); + if (status == -1) return -EIO; + vber |= (status << 8); + status = tda1004x_read_byte(state, TDA1004X_VBER_MSB); + if (status == -1) return -EIO; + vber |= ((status << 16) & 0x0f); + tda1004x_read_byte(state, TDA1004X_CVBER_LUT); + + // if RS has passed some valid TS packets, then we must be + // getting some SYNC bytes + if (vber < 16632) { + *fe_status |= FE_HAS_SYNC; + } + } // success dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status); return 0; } -static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal) +static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; - int reg = 0; + int reg = 0; dprintk("%s\n", __FUNCTION__); - // determine the register to use - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - reg = TDA10045H_S_AGC; - break; + // determine the register to use + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + reg = TDA10045H_S_AGC; + break; - case FE_TYPE_TDA10046H: - reg = TDA10046H_AGC_IF_LEVEL; - break; - } + case TDA1004X_DEMOD_TDA10046: + reg = TDA10046H_AGC_IF_LEVEL; + break; + } // read it - tmp = tda1004x_read_byte(i2c, tda_state, reg); + tmp = tda1004x_read_byte(state, reg); if (tmp < 0) return -EIO; - // done *signal = (tmp << 8) | tmp; dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal); return 0; } - -static int tda1004x_read_snr(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * snr) +static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; dprintk("%s\n", __FUNCTION__); // read it - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR); + tmp = tda1004x_read_byte(state, TDA1004X_SNR); if (tmp < 0) return -EIO; - if (tmp) { - tmp = 255 - tmp; - } + if (tmp) { + tmp = 255 - tmp; + } - // done *snr = ((tmp << 8) | tmp); dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr); return 0; } -static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ucblocks) +static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { + struct tda1004x_state* state = fe->demodulator_priv; int tmp; int tmp2; int counter; @@ -1237,16 +1013,16 @@ static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state // read the UCBLOCKS and reset counter = 0; - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + tmp = tda1004x_read_byte(state, TDA1004X_UNCOR); if (tmp < 0) return -EIO; - tmp &= 0x7f; + tmp &= 0x7f; while (counter++ < 5) { - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0); - tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR); if (tmp2 < 0) return -EIO; tmp2 &= 0x7f; @@ -1254,7 +1030,6 @@ static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state break; } - // done if (tmp != 0x7f) { *ucblocks = tmp; } else { @@ -1264,278 +1039,189 @@ static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state return 0; } -static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ber) +static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber) { - int tmp; + struct tda1004x_state* state = fe->demodulator_priv; + int tmp; dprintk("%s\n", __FUNCTION__); // read it in - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); - if (tmp < 0) return -EIO; - *ber = tmp << 1; - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); - if (tmp < 0) return -EIO; - *ber |= (tmp << 9); - tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); - - // done - dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); - return 0; -} - -static int tda1004x_sleep(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state) -{ - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFADC1, 0x10, 0x10); - break; - - case FE_TYPE_TDA10046H: - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 1, 1); - break; - } + tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB); + if (tmp < 0) return -EIO; + *ber = tmp << 1; + tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB); + if (tmp < 0) return -EIO; + *ber |= (tmp << 9); + tda1004x_read_byte(state, TDA1004X_CBER_RESET); + dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); return 0; } - -static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int tda1004x_sleep(struct dvb_frontend* fe) { - int status = 0; - struct dvb_i2c_bus *i2c = fe->i2c; - struct tda1004x_state *tda_state = (struct tda1004x_state *) fe->data; - - dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd); - - switch (cmd) { - case FE_GET_INFO: - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_TYPE_TDA10046H: - memcpy(arg, &tda10046h_info, sizeof(struct dvb_frontend_info)); - break; - } - break; - - case FE_READ_STATUS: - return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg); - - case FE_READ_BER: - return tda1004x_read_ber(i2c, tda_state, (u32 *) arg); + struct tda1004x_state* state = fe->demodulator_priv; - case FE_READ_SIGNAL_STRENGTH: - return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg); - - case FE_READ_SNR: - return tda1004x_read_snr(i2c, tda_state, (u16 *) arg); - - case FE_READ_UNCORRECTED_BLOCKS: - return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg); - - case FE_SET_FRONTEND: - return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); - - case FE_GET_FRONTEND: - return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); - - case FE_SLEEP: - tda_state->initialised = 0; - return tda1004x_sleep(i2c, tda_state); + switch(state->demod_type) { + case TDA1004X_DEMOD_TDA10045: + tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10); + break; - case FE_INIT: + case TDA1004X_DEMOD_TDA10046: + tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); + break; + } + state->initialised = 0; - // don't bother reinitialising - if (tda_state->initialised) return 0; + } - // OK, perform initialisation - switch(tda_state->fe_type) { - case FE_TYPE_TDA10045H: - status = tda10045h_init(i2c, tda_state); - break; - - case FE_TYPE_TDA10046H: - status = tda10046h_init(i2c, tda_state); - break; - } - if (status == 0) - tda_state->initialised = 1; - return status; - - case FE_GET_TUNE_SETTINGS: +static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg; fesettings->min_delay_ms = 800; fesettings->step_size = 166667; fesettings->max_drift = 166667*2; return 0; } - - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int tda1004x_attach(struct dvb_i2c_bus *i2c, void **data) +static void tda1004x_release(struct dvb_frontend* fe) { - int tda1004x_address = -1; - int tuner_address = -1; - int fe_type = -1; - int tuner_type = -1; - struct tda1004x_state tda_state; - struct tda1004x_state* ptda_state; - struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=NULL, .len=0 }; - static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; - static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; - static u8 td1316_init_tda10046h[] = { 0x0b, 0xf5, 0x80, 0xab }; - int status; - - dprintk("%s\n", __FUNCTION__); - - // probe for tda10045h - if (tda1004x_address == -1) { - tda_state.tda1004x_address = 0x08; - if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) { - tda1004x_address = 0x08; - fe_type = FE_TYPE_TDA10045H; - printk("tda1004x: Detected Philips TDA10045H.\n"); - } - } - - // probe for tda10046h - if (tda1004x_address == -1) { - tda_state.tda1004x_address = 0x08; - if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x46) { - tda1004x_address = 0x08; - fe_type = FE_TYPE_TDA10046H; - printk("tda1004x: Detected Philips TDA10046H.\n"); - } - } - - // did we find a frontend? - if (tda1004x_address == -1) { - return -ENODEV; - } - - // enable access to the tuner - tda1004x_enable_tuner_i2c(i2c, &tda_state); - - // check for a TD1344 first - if (tuner_address == -1) { - tuner_msg.addr = 0x61; - tuner_msg.buf = td1344_init; - tuner_msg.len = sizeof(td1344_init); - if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - dvb_delay(1); - tuner_address = 0x61; - tuner_type = TUNER_TYPE_TD1344; - printk("tda1004x: Detected Philips TD1344 tuner.\n"); - } - } - - // OK, try a TD1316 on address 0x63 - if (tuner_address == -1) { - tuner_msg.addr = 0x63; - tuner_msg.buf = td1316_init; - tuner_msg.len = sizeof(td1316_init); - if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - dvb_delay(1); - tuner_address = 0x63; - tuner_type = TUNER_TYPE_TD1316; - printk("tda1004x: Detected Philips TD1316 tuner.\n"); - } - } - - // OK, TD1316 again, on address 0x60 (TDA10046H) - if (tuner_address == -1) { - tuner_msg.addr = 0x60; - tuner_msg.buf = td1316_init_tda10046h; - tuner_msg.len = sizeof(td1316_init_tda10046h); - if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { - dvb_delay(1); - tuner_address = 0x60; - tuner_type = TUNER_TYPE_TD1316; - printk("tda1004x: Detected Philips TD1316 tuner.\n"); - } - } - tda1004x_disable_tuner_i2c(i2c, &tda_state); - - // did we find a tuner? - if (tuner_address == -1) { - printk("tda1004x: Detected, but with unknown tuner.\n"); - return -ENODEV; + struct tda1004x_state* state = (struct tda1004x_state*) fe->demodulator_priv; + kfree(state); } - // create state - tda_state.tda1004x_address = tda1004x_address; - tda_state.fe_type = fe_type; - tda_state.tuner_address = tuner_address; - tda_state.tuner_type = tuner_type; - tda_state.initialised = 0; - - // upload firmware - if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status; - - // create the real state we'll be passing about - if ((ptda_state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - memcpy(ptda_state, &tda_state, sizeof(struct tda1004x_state)); - *data = ptda_state; +static struct dvb_frontend_ops tda10045_ops; - // register - switch(tda_state.fe_type) { - case FE_TYPE_TDA10045H: - return dvb_register_frontend(tda1004x_ioctl, i2c, ptda_state, &tda10045h_info); - - case FE_TYPE_TDA10046H: - return dvb_register_frontend(tda1004x_ioctl, i2c, ptda_state, &tda10046h_info); - } - - // should not get here - return -EINVAL; -} - - -static -void tda1004x_detach(struct dvb_i2c_bus *i2c, void *data) +struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) { - dprintk("%s\n", __FUNCTION__); - - kfree(data); - dvb_unregister_frontend(tda1004x_ioctl, i2c); -} + struct tda1004x_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->demod_type = TDA1004X_DEMOD_TDA10045; + + /* check if the demod is there */ + if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } +static struct dvb_frontend_ops tda10046_ops; -static -int __init init_tda1004x(void) +struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) { - return dvb_register_i2c_device(THIS_MODULE, tda1004x_attach, tda1004x_detach); -} + struct tda1004x_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + state->demod_type = TDA1004X_DEMOD_TDA10046; + + /* check if the demod is there */ + if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) goto error; + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } +static struct dvb_frontend_ops tda10045_ops = { + + .info = { + .name = "Philips TDA10045H DVB-T", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .caps = + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = tda1004x_release, + + .init = tda10045_init, + .sleep = tda1004x_sleep, + + .set_frontend = tda1004x_set_fe, + .get_frontend = tda1004x_get_fe, + .get_tune_settings = tda1004x_get_tune_settings, + + .read_status = tda1004x_read_status, + .read_ber = tda1004x_read_ber, + .read_signal_strength = tda1004x_read_signal_strength, + .read_snr = tda1004x_read_snr, + .read_ucblocks = tda1004x_read_ucblocks, +}; -static -void __exit exit_tda1004x(void) -{ - dvb_unregister_i2c_device(tda1004x_attach); -} +static struct dvb_frontend_ops tda10046_ops = { + + .info = { + .name = "Philips TDA10046H DVB-T", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .caps = + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = tda1004x_release, + + .init = tda10046_init, + .sleep = tda1004x_sleep, + + .set_frontend = tda1004x_set_fe, + .get_frontend = tda1004x_get_fe, + .get_tune_settings = tda1004x_get_tune_settings, + + .read_status = tda1004x_read_status, + .read_ber = tda1004x_read_ber, + .read_signal_strength = tda1004x_read_signal_strength, + .read_snr = tda1004x_read_snr, + .read_ucblocks = tda1004x_read_ucblocks, +}; -module_init(init_tda1004x); -module_exit(exit_tda1004x); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); -MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Frontend"); +MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator"); MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); MODULE_LICENSE("GPL"); -MODULE_PARM(tda1004x_debug, "i"); -MODULE_PARM_DESC(tda1004x_debug, "enable verbose debug messages"); - -MODULE_PARM(tda1004x_firmware, "s"); -MODULE_PARM_DESC(tda1004x_firmware, "Where to find the firmware file"); +EXPORT_SYMBOL(tda10045_attach); +EXPORT_SYMBOL(tda10046_attach); +EXPORT_SYMBOL(tda1004x_write_byte); diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c index d01d28361..3d8e7804c 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb/frontends/ves1820.c @@ -1,6 +1,5 @@ /* VES1820 - Single Chip Cable Channel Receiver driver module - used on the the Siemens DVB-C cards Copyright (C) 1999 Convergence Integrated Media GmbH @@ -27,98 +26,34 @@ #include #include #include +#include #include "dvb_frontend.h" -#include "dvb_functions.h" +#include "ves1820.h" -#if 0 -#define dprintk(x...) printk(x) -#else -#define dprintk(x...) -#endif -#define MAX_UNITS 4 -static int pwm[MAX_UNITS] = { -1, -1, -1, -1 }; -static int verbose; +struct ves1820_state { + + struct i2c_adapter *i2c; + + struct dvb_frontend_ops ops; + + /* configuration settings */ + const struct ves1820_config* config; -/** - * since we need only a few bits to store internal state we don't allocate - * extra memory but use frontend->data as bitfield - */ - -#define SET_PWM(data,pwm) do { \ - long d = (long)data; \ - d &= ~0xff; \ - d |= pwm; \ - data = (void *)d; \ -} while (0) - -#define SET_REG0(data,reg0) do { \ - long d = (long)data; \ - d &= ~(0xff << 8); \ - d |= reg0 << 8; \ - data = (void *)d; \ -} while (0) - -#define SET_TUNER(data,type) do { \ - long d = (long)data; \ - d &= ~(0xff << 16); \ - d |= type << 16; \ - data = (void *)d; \ -} while (0) - -#define SET_DEMOD_ADDR(data,type) do { \ - long d = (long)data; \ - d &= ~(0xff << 24); \ - d |= type << 24; \ - data = (void *)d; \ -} while (0) - -#define GET_PWM(data) ((u8) ((long) data & 0xff)) -#define GET_REG0(data) ((u8) (((long) data >> 8) & 0xff)) -#define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff)) -#define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff)) - -#if defined(CONFIG_DBOX2) -#define XIN 69600000UL -#define DISABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) -#define ENABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) -#define HAS_INVERSION(reg0) (reg0 & 0x20) -#else /* PCI cards */ -#define XIN 57840000UL -#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0) -#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0) -#define HAS_INVERSION(reg0) (!(reg0 & 0x20)) -#endif - -#define FIN (XIN >> 4) - - - -static struct dvb_frontend_info ves1820_info = { - .name = "VES1820 based DVB-C frontend", - .type = FE_QAM, - .frequency_stepsize = 62500, - .frequency_min = 51000000, - .frequency_max = 858000000, - .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ -#if 0 - .frequency_tolerance = ???, - .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ - .notifier_delay = ?, -#endif - .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | - FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO, + struct dvb_frontend frontend; + + /* private demodulator data */ + u8 reg0; + u8 pwm; }; +static int verbose; -static u8 ves1820_inittab [] = -{ - 0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, +static u8 ves1820_inittab[] = { + 0x69, 0x6A, 0x93, 0x12, 0x12, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, @@ -127,189 +62,123 @@ static u8 ves1820_inittab [] = 0x00, 0x00, 0x00, 0x00, 0x40 }; - -static int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data) +static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data) { - u8 addr = GET_DEMOD_ADDR(fe->data); u8 buf[] = { 0x00, reg, data }; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; - struct dvb_i2c_bus *i2c = fe->i2c; + struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 }; int ret; - ret = i2c->xfer (i2c, &msg, 1); + ret = i2c_transfer(state->i2c, &msg, 1); if (ret != 1) - printk("DVB: VES1820(%d): %s, writereg error " - "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", - fe->i2c->adapter->num, __FUNCTION__, reg, data, ret); + printk("ves1820: %s(): writereg error (reg == 0x%02x," + "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); - dvb_delay(10); + msleep(10); return (ret != 1) ? -EREMOTEIO : 0; } - -static u8 ves1820_readreg (struct dvb_frontend *fe, u8 reg) +static u8 ves1820_readreg(struct ves1820_state *state, u8 reg) { u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; - u8 addr = GET_DEMOD_ADDR(fe->data); - struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 }, - { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - struct dvb_i2c_bus *i2c = fe->i2c; + struct i2c_msg msg[] = { + {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} + }; int ret; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) - printk("DVB: VES1820(%d): %s: readreg error (ret == %i)\n", - fe->i2c->adapter->num, __FUNCTION__, ret); + printk("ves1820: %s(): readreg error (reg == 0x%02x," + "ret == %i)\n", __FUNCTION__, reg, ret); return b1[0]; } -static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4]) +static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion) { - int ret; - struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; - - ret = i2c->xfer (i2c, &msg, 1); - - if (ret != 1) - printk("DVB: VES1820(%d): %s: i/o error (ret == %i)\n", - i2c->adapter->num, __FUNCTION__, ret); - - return (ret != 1) ? -EREMOTEIO : 0; -} - - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 62.5 kHz. - */ -static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq) -{ - u32 div, ifreq; - static u8 addr [] = { 0x61, 0x62 }; - static u8 byte3 [] = { 0x8e, 0x85 }; - int tuner_type = GET_TUNER(fe->data); - u8 buf [4]; - - if (tuner_type == 0xff) /* PLL not reachable over i2c ... */ - return 0; - - if (strstr (fe->i2c->adapter->name, "Technotrend") || - strstr (fe->i2c->adapter->name, "TT-Budget")) - ifreq = 35937500; - else - ifreq = 36125000; - - div = (freq + ifreq + 31250) / 62500; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = byte3[tuner_type]; - - if (tuner_type == 1) { - buf[2] |= (div >> 10) & 0x60; - buf[3] = (freq < 174000000 ? 0x88 : - freq < 470000000 ? 0x84 : 0x81); - } else { - buf[3] = (freq < 174000000 ? 0xa1 : - freq < 454000000 ? 0x92 : 0x34); - } - - return tuner_write (fe->i2c, addr[tuner_type], buf); -} - - -static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0, - fe_spectral_inversion_t inversion) -{ - reg0 |= GET_REG0(fe->data) & 0x62; + reg0 |= state->reg0 & 0x62; - if (INVERSION_ON == inversion) - ENABLE_INVERSION(reg0); - else if (INVERSION_OFF == inversion) - DISABLE_INVERSION(reg0); + if (INVERSION_ON == inversion) { + if (!state->config->invert) reg0 |= 0x20; + else reg0 &= ~0x20; - ves1820_writereg (fe, 0x00, reg0 & 0xfe); - ves1820_writereg (fe, 0x00, reg0 | 0x01); - - /** - * check lock and toggle inversion bit if required... - */ - if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) { - mdelay(50); - if (!(ves1820_readreg (fe, 0x11) & 0x08)) { - reg0 ^= 0x20; - ves1820_writereg (fe, 0x00, reg0 & 0xfe); - ves1820_writereg (fe, 0x00, reg0 | 0x01); - } - } - - SET_REG0(fe->data, reg0); - - return 0; -} + } else if (INVERSION_OFF == inversion) { + if (!state->config->invert) reg0 &= ~0x20; + else reg0 |= 0x20; + } -static int ves1820_init (struct dvb_frontend *fe) -{ - int i; - - dprintk("DVB: VES1820(%d): init chip\n", fe->i2c->adapter->num); - - ves1820_writereg (fe, 0, 0); - -#if defined(CONFIG_DBOX2) - ves1820_inittab[2] &= ~0x08; -#endif - - for (i=0; i<53; i++) - ves1820_writereg (fe, i, ves1820_inittab[i]); + ves1820_writereg(state, 0x00, reg0 & 0xfe); + ves1820_writereg(state, 0x00, reg0 | 0x01); - ves1820_writereg (fe, 0x34, GET_PWM(fe->data)); + state->reg0 = reg0; return 0; } - -static int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate) +static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) { s32 BDR; s32 BDRI; s16 SFIL=0; u16 NDEC = 0; - u32 tmp, ratio; + u32 ratio; + u32 fin; + u32 tmp; + u64 fptmp; + u64 fpxin; - if (symbolrate > XIN/2) - symbolrate = XIN/2; + if (symbolrate > state->config->xin / 2) + symbolrate = state->config->xin / 2; if (symbolrate < 500000) symbolrate = 500000; - if (symbolrate < XIN/16) NDEC = 1; - if (symbolrate < XIN/32) NDEC = 2; - if (symbolrate < XIN/64) NDEC = 3; - - if (symbolrate < (u32)(XIN/12.3)) SFIL = 1; - if (symbolrate < (u32)(XIN/16)) SFIL = 0; - if (symbolrate < (u32)(XIN/24.6)) SFIL = 1; - if (symbolrate < (u32)(XIN/32)) SFIL = 0; - if (symbolrate < (u32)(XIN/49.2)) SFIL = 1; - if (symbolrate < (u32)(XIN/64)) SFIL = 0; - if (symbolrate < (u32)(XIN/98.4)) SFIL = 1; + if (symbolrate < state->config->xin / 16) + NDEC = 1; + if (symbolrate < state->config->xin / 32) + NDEC = 2; + if (symbolrate < state->config->xin / 64) + NDEC = 3; + + /* yeuch! */ + fpxin = state->config->xin * 10; + fptmp = fpxin; do_div(fptmp, 123); + if (symbolrate < fptmp); + SFIL = 1; + fptmp = fpxin; do_div(fptmp, 160); + if (symbolrate < fptmp); + SFIL = 0; + fptmp = fpxin; do_div(fptmp, 246); + if (symbolrate < fptmp); + SFIL = 1; + fptmp = fpxin; do_div(fptmp, 320); + if (symbolrate < fptmp); + SFIL = 0; + fptmp = fpxin; do_div(fptmp, 492); + if (symbolrate < fptmp); + SFIL = 1; + fptmp = fpxin; do_div(fptmp, 640); + if (symbolrate < fptmp); + SFIL = 0; + fptmp = fpxin; do_div(fptmp, 984); + if (symbolrate < fptmp); + SFIL = 1; + fin = state->config->xin >> 4; symbolrate <<= NDEC; - ratio = (symbolrate << 4) / FIN; - tmp = ((symbolrate << 4) % FIN) << 8; - ratio = (ratio << 8) + tmp / FIN; - tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; + ratio = (symbolrate << 4) / fin; + tmp = ((symbolrate << 4) % fin) << 8; + ratio = (ratio << 8) + tmp / fin; + tmp = (tmp % fin) << 8; + ratio = (ratio << 8) + (tmp + fin / 2) / fin; BDR = ratio; - BDRI = (((XIN << 5) / symbolrate) + 1) / 2; + BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; if (BDRI > 0xFF) BDRI = 0xFF; @@ -318,21 +187,53 @@ static int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate) NDEC = (NDEC << 6) | ves1820_inittab[0x03]; - ves1820_writereg (fe, 0x03, NDEC); - ves1820_writereg (fe, 0x0a, BDR&0xff); - ves1820_writereg (fe, 0x0b, (BDR>> 8)&0xff); - ves1820_writereg (fe, 0x0c, (BDR>>16)&0x3f); + ves1820_writereg(state, 0x03, NDEC); + ves1820_writereg(state, 0x0a, BDR & 0xff); + ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff); + ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f); - ves1820_writereg (fe, 0x0d, BDRI); - ves1820_writereg (fe, 0x0e, SFIL); + ves1820_writereg(state, 0x0d, BDRI); + ves1820_writereg(state, 0x0e, SFIL); return 0; } -static int ves1820_set_parameters (struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) + + + + + + + + + + + +static int ves1820_init(struct dvb_frontend* fe) { + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + int i; + int val; + + ves1820_writereg(state, 0, 0); + + for (i = 0; i < 53; i++) { + val = ves1820_inittab[i]; + if ((i == 2) && (state->config->selagc)) val |= 0x08; + ves1820_writereg(state, i, val); + } + + ves1820_writereg(state, 0x34, state->pwm); + + if (state->config->pll_init) state->config->pll_init(fe); + + return 0; +} + +static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) +{ + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 }; static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 }; static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 }; @@ -343,41 +244,28 @@ static int ves1820_set_parameters (struct dvb_frontend *fe, if (real_qam < 0 || real_qam > 4) return -EINVAL; - tuner_set_tv_freq (fe, p->frequency); - ves1820_set_symbolrate (fe, p->u.qam.symbol_rate); - ves1820_writereg (fe, 0x34, GET_PWM(fe->data)); - - ves1820_writereg (fe, 0x01, reg0x01[real_qam]); - ves1820_writereg (fe, 0x05, reg0x05[real_qam]); - ves1820_writereg (fe, 0x08, reg0x08[real_qam]); - ves1820_writereg (fe, 0x09, reg0x09[real_qam]); + state->config->pll_set(fe, p); + ves1820_set_symbolrate(state, p->u.qam.symbol_rate); + ves1820_writereg(state, 0x34, state->pwm); - ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion); + ves1820_writereg(state, 0x01, reg0x01[real_qam]); + ves1820_writereg(state, 0x05, reg0x05[real_qam]); + ves1820_writereg(state, 0x08, reg0x08[real_qam]); + ves1820_writereg(state, 0x09, reg0x09[real_qam]); - /* yes, this speeds things up: userspace reports lock in about 8 ms - instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */ - mdelay(50); + ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion); return 0; } - - -static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status) { - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &ves1820_info, sizeof(struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: - { - fe_status_t *status = (fe_status_t *) arg; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; int sync; *status = 0; - sync = ves1820_readreg (fe, 0x11); + sync = ves1820_readreg(state, 0x11); if (sync & 1) *status |= FE_HAS_SIGNAL; @@ -394,201 +282,189 @@ static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if (sync & 8) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: +static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 ber = ves1820_readreg(fe, 0x14) | - (ves1820_readreg(fe, 0x15) << 8) | - ((ves1820_readreg(fe, 0x16) & 0x0f) << 16); - *((u32*) arg) = 10 * ber; - break; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + u32 _ber = ves1820_readreg(state, 0x14) | + (ves1820_readreg(state, 0x15) << 8) | + ((ves1820_readreg(state, 0x16) & 0x0f) << 16); + *ber = 10 * _ber; + + return 0; } - case FE_READ_SIGNAL_STRENGTH: + +static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 gain = ves1820_readreg(fe, 0x17); - *((u16*) arg) = (gain << 8) | gain; - break; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + u8 gain = ves1820_readreg(state, 0x17); + *strength = (gain << 8) | gain; + + return 0; } - case FE_READ_SNR: +static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr) { - u8 quality = ~ves1820_readreg(fe, 0x18); - *((u16*) arg) = (quality << 8) | quality; - break; + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + u8 quality = ~ves1820_readreg(state, 0x18); + *snr = (quality << 8) | quality; + + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: - *((u32*) arg) = ves1820_readreg (fe, 0x13) & 0x7f; - if (*((u32*) arg) == 0x7f) - *((u32*) arg) = 0xffffffff; +static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + + *ucblocks = ves1820_readreg(state, 0x13) & 0x7f; + if (*ucblocks == 0x7f) + *ucblocks = 0xffffffff; + /* reset uncorrected block counter */ - ves1820_writereg (fe, 0x10, ves1820_inittab[0x10] & 0xdf); - ves1820_writereg (fe, 0x10, ves1820_inittab[0x10]); - break; + ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf); + ves1820_writereg(state, 0x10, ves1820_inittab[0x10]); - case FE_SET_FRONTEND: - return ves1820_set_parameters (fe, arg); + return 0; +} - case FE_GET_FRONTEND: +static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *)arg; - u8 reg0 = GET_REG0(fe->data); + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; int sync; s8 afc = 0; - sync = ves1820_readreg (fe, 0x11); - afc = ves1820_readreg(fe, 0x19); + sync = ves1820_readreg(state, 0x11); + afc = ves1820_readreg(state, 0x19); if (verbose) { /* AFC only valid when carrier has been recovered */ - printk(sync & 2 ? "DVB: VES1820(%d): AFC (%d) %dHz\n" : - "DVB: VES1820(%d): [AFC (%d) %dHz]\n", - fe->i2c->adapter->num, afc, - -((s32)p->u.qam.symbol_rate * afc) >> 10); + printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" : + "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10); } - p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF; - p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16; + if (!state->config->invert) { + p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF; + } else { + p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF; + } + + p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16; p->u.qam.fec_inner = FEC_NONE; p->frequency = ((p->frequency + 31250) / 62500) * 62500; if (sync & 2) p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; - break; - } - case FE_SLEEP: - ves1820_writereg (fe, 0x1b, 0x02); /* pdown ADC */ - ves1820_writereg (fe, 0x00, 0x80); /* standby */ - break; - - case FE_INIT: - return ves1820_init (fe); - - default: - return -EINVAL; - } return 0; } - -static long probe_tuner (struct dvb_i2c_bus *i2c) +static int ves1820_sleep(struct dvb_frontend* fe) { - static const struct i2c_msg msg1 = - { .addr = 0x61, .flags = 0, .buf = NULL, .len = 0 }; - static const struct i2c_msg msg2 = - { .addr = 0x62, .flags = 0, .buf = NULL, .len = 0 }; - int type; - - if (i2c->xfer(i2c, &msg1, 1) == 1) { - type = 0; - printk ("DVB: VES1820(%d): setup for tuner spXXXX\n", i2c->adapter->num); - } else if (i2c->xfer(i2c, &msg2, 1) == 1) { - type = 1; - printk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num); - } else { - type = -1; - } - - return type; -} + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */ + ves1820_writereg(state, 0x00, 0x80); /* standby */ -static u8 read_pwm (struct dvb_i2c_bus *i2c) -{ - u8 b = 0xff; - u8 pwm; - struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 }, - { .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } }; - - if ((i2c->xfer(i2c, msg, 2) != 2) || (pwm == 0xff)) - pwm = 0x48; - - printk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm); - - return pwm; -} - - -static long probe_demod_addr (struct dvb_i2c_bus *i2c) -{ - u8 b [] = { 0x00, 0x1a }; - u8 id; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b, .len = 2 }, - { .addr = 0x08, .flags = I2C_M_RD, .buf = &id, .len = 1 } }; - - if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) - return msg[0].addr; - - msg[0].addr = msg[1].addr = 0x09; - - if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) - return msg[0].addr; - - return -1; + return 0; } - -static int ves1820_attach (struct dvb_i2c_bus *i2c, void **data) +static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { - void *priv = NULL; - long demod_addr; - long tuner_type; - if ((demod_addr = probe_demod_addr(i2c)) < 0) - return -ENODEV; - - tuner_type = probe_tuner(i2c); - - if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) { - printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n", - i2c->adapter->num, pwm[i2c->adapter->num]); - SET_PWM(priv, pwm[i2c->adapter->num]); - } - else - SET_PWM(priv, read_pwm(i2c)); - SET_REG0(priv, ves1820_inittab[0]); - SET_TUNER(priv, tuner_type); - SET_DEMOD_ADDR(priv, demod_addr); - - return dvb_register_frontend (ves1820_ioctl, i2c, priv, &ves1820_info); -} - - -static void ves1820_detach (struct dvb_i2c_bus *i2c, void *data) -{ - dvb_unregister_frontend (ves1820_ioctl, i2c); + fesettings->min_delay_ms = 200; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; } - -static int __init init_ves1820 (void) +static void ves1820_release(struct dvb_frontend* fe) { - int i; - for (i = 0; i < MAX_UNITS; i++) - if (pwm[i] < -1 || pwm[i] > 255) - return -EINVAL; - return dvb_register_i2c_device (THIS_MODULE, - ves1820_attach, ves1820_detach); + struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops ves1820_ops; -static void __exit exit_ves1820 (void) +struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, + struct i2c_adapter* i2c, + u8 pwm) { - dvb_unregister_i2c_device (ves1820_attach); -} - + struct ves1820_state* state = NULL; + + /* allocate memory for the internal state */ + state = (struct ves1820_state*) kmalloc(sizeof(struct ves1820_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops)); + state->reg0 = ves1820_inittab[0]; + state->config = config; + state->i2c = i2c; + state->pwm = pwm; + + /* check if the demod is there */ + if ((ves1820_readreg(state, 0x1a) & 0xf0) != 0x70) + goto error; + + if (verbose) + printk("ves1820: pwm=0x%02x\n", state->pwm); + + state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */ + state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */ + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) kfree(state); + return NULL; + } -module_init(init_ves1820); -module_exit(exit_ves1820); +static struct dvb_frontend_ops ves1820_ops = { + + .info = { + .name = "VLSI VES1820 DVB-C", + .type = FE_QAM, + .frequency_stepsize = 62500, + .frequency_min = 51000000, + .frequency_max = 858000000, + .caps = FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_FEC_AUTO + }, + + .release = ves1820_release, + + .init = ves1820_init, + .sleep = ves1820_sleep, + + .set_frontend = ves1820_set_parameters, + .get_frontend = ves1820_get_frontend, + .get_tune_settings = ves1820_get_tune_settings, + + .read_status = ves1820_read_status, + .read_ber = ves1820_read_ber, + .read_signal_strength = ves1820_read_signal_strength, + .read_snr = ves1820_read_snr, + .read_ucblocks = ves1820_read_ucblocks, +}; -MODULE_PARM(pwm, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM_DESC(pwm, "override PWM value stored in EEPROM (tuner calibration)"); -MODULE_PARM(verbose, "i"); +module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting"); -MODULE_DESCRIPTION("VES1820 DVB-C frontend driver"); +MODULE_DESCRIPTION("VLSI VES1820 DVB-C Demodulator driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(ves1820_attach); diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index 876246d24..4a13dcea9 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -1,5 +1,5 @@ /* - Driver for VES1893 and VES1993 QPSK Frontends + Driver for VES1893 and VES1993 QPSK Demodulators Copyright (C) 1999 Convergence Integrated Media GmbH Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de> @@ -28,44 +28,36 @@ #include #include #include +#include #include "dvb_frontend.h" -#include "dvb_functions.h" +#include "ves1x93.h" -static int debug = 0; -#define dprintk if (debug) printk -static int board_type = 0; -#define BOARD_SIEMENS_PCI 0 -#define BOARD_NOKIA_DBOX2 1 -#define BOARD_SAGEM_DBOX2 2 +struct ves1x93_state { + + struct i2c_adapter* i2c; -static int demod_type = 0; -#define DEMOD_VES1893 0 -#define DEMOD_VES1993 1 + struct dvb_frontend_ops ops; -static struct dvb_frontend_info ves1x93_info = { - .name = "VES1x93", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 250, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, - .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 50, /* 1/20 s */ - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK + /* configuration settings */ + const struct ves1x93_config* config; + + struct dvb_frontend frontend; + + /* previous uncorrected block counter */ + fe_spectral_inversion_t inversion; + u8 *init_1x93_tab; + u8 *init_1x93_wtab; + u8 tab_size; + u8 demod_type; }; +static int debug = 0; +#define dprintk if (debug) printk -/** - * nokia dbox2 (ves1893) and sagem dbox2 (ves1993) - * need bit AGCR[PWMS] set to 1 - */ +#define DEMOD_VES1893 0 +#define DEMOD_VES1993 1 static u8 init_1893_tab [] = { 0x01, 0xa4, 0x35, 0x80, 0x2a, 0x0b, 0x55, 0xc4, @@ -89,10 +81,6 @@ static u8 init_1993_tab [] = { 0x00, 0x00, 0x0e, 0x80, 0x00 }; - -static u8 * init_1x93_tab; - - static u8 init_1893_wtab[] = { 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, @@ -110,19 +98,13 @@ static u8 init_1993_wtab[] = 1,1,1,0,1,1,1,1, 1,1,1,1,1 }; -struct ves1x93_state { - fe_spectral_inversion_t inversion; -}; - - - -static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data) { u8 buf [] = { 0x00, reg, data }; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 }; int err; - if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); return -EREMOTEIO; } @@ -131,142 +113,31 @@ static int ves1x93_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) } -static u8 ves1x93_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 ves1x93_readreg (struct ves1x93_state* state, u8 reg) { int ret; u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, - { .addr = 0x08, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - ret = i2c->xfer (i2c, msg, 2); + ret = i2c_transfer (state->i2c, msg, 2); - if (ret != 2) - dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + if (ret != 2) return ret; return b1[0]; } - -static int tuner_write (struct dvb_i2c_bus *i2c, u8 *data, u8 len) -{ - int ret; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = len }; - - ves1x93_writereg(i2c, 0x00, 0x11); - ret = i2c->xfer (i2c, &msg, 1); - ves1x93_writereg(i2c, 0x00, 0x01); - - if (ret != 1) - printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 1) ? -1 : 0; -} - - - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 125 kHz. - */ -static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) -{ - u32 div = (freq + 479500) / 125; - u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x95, (pwr << 5) | 0x30 }; - - return tuner_write (i2c, buf, sizeof(buf)); -} - - -static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) -{ - int ret; - u8 buf [2]; - - freq /= 1000; - - buf[0] = (freq >> 8) & 0x7F; - buf[1] = freq & 0xFF; - - ret = tuner_write(i2c, buf, sizeof(buf)); - - return ret; -} - - -static int tuner_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) -{ - if ((demod_type == DEMOD_VES1893) && (board_type == BOARD_SIEMENS_PCI)) - return sp5659_set_tv_freq (i2c, freq, pwr); - else if (demod_type == DEMOD_VES1993) - return tsa5059_set_tv_freq (i2c, freq); - - return -EINVAL; -} - - -static int ves1x93_init (struct dvb_i2c_bus *i2c) -{ - int i; - int size; - u8 *init_1x93_wtab; - - dprintk("%s: init chip\n", __FUNCTION__); - - switch (demod_type) { - case DEMOD_VES1893: - init_1x93_tab = init_1893_tab; - init_1x93_wtab = init_1893_wtab; - size = sizeof(init_1893_tab); - if (board_type == BOARD_NOKIA_DBOX2) - init_1x93_tab[0x05] |= 0x20; /* invert PWM */ - break; - - case DEMOD_VES1993: - init_1x93_tab = init_1993_tab; - init_1x93_wtab = init_1993_wtab; - size = sizeof(init_1993_tab); - if (board_type == BOARD_SAGEM_DBOX2) - init_1x93_tab[0x05] |= 0x20; /* invert PWM */ - break; - - default: - return -EINVAL; - } - - for (i = 0; i < size; i++) - if (init_1x93_wtab[i]) - ves1x93_writereg (i2c, i, init_1x93_tab[i]); - - if (demod_type == DEMOD_VES1993) { - if (board_type == BOARD_NOKIA_DBOX2) - tuner_write(i2c, "\x06\x5c\x83\x60", 4); - else if (board_type == BOARD_SAGEM_DBOX2) - tuner_write(i2c, "\x25\x70\x92\x40", 4); - } - - return 0; -} - - -static int ves1x93_clr_bit (struct dvb_i2c_bus *i2c) +static int ves1x93_clr_bit (struct ves1x93_state* state) { - ves1x93_writereg (i2c, 0, init_1x93_tab[0] & 0xfe); - ves1x93_writereg (i2c, 0, init_1x93_tab[0]); - dvb_delay(5); + msleep(10); + ves1x93_writereg (state, 0, state->init_1x93_tab[0] & 0xfe); + ves1x93_writereg (state, 0, state->init_1x93_tab[0]); + msleep(50); return 0; } -static int ves1x93_init_aquire (struct dvb_i2c_bus *i2c) -{ - ves1x93_writereg (i2c, 3, 0x00); - ves1x93_writereg (i2c, 3, init_1x93_tab[3]); - dvb_delay(5); - return 0; -} - - -static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inversion_t inversion) { u8 val; @@ -289,66 +160,47 @@ static int ves1x93_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion return -EINVAL; } - return ves1x93_writereg (i2c, 0x0c, (init_1x93_tab[0x0c] & 0x3f) | val); + return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val); } -static int ves1x93_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec) { if (fec == FEC_AUTO) - return ves1x93_writereg (i2c, 0x0d, 0x08); + return ves1x93_writereg (state, 0x0d, 0x08); else if (fec < FEC_1_2 || fec > FEC_8_9) return -EINVAL; else - return ves1x93_writereg (i2c, 0x0d, fec - FEC_1_2); + return ves1x93_writereg (state, 0x0d, fec - FEC_1_2); } -static fe_code_rate_t ves1x93_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state) { - return FEC_1_2 + ((ves1x93_readreg (i2c, 0x0d) >> 4) & 0x7); + return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7); } -static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate) { u32 BDR; u32 ratio; u8 ADCONF, FCONF, FNR; u32 BDRI; u32 tmp; - u32 XIN, FIN; + u32 FIN; dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate); - switch (board_type) { - case BOARD_SIEMENS_PCI: - XIN = 90100000UL; - break; - case BOARD_NOKIA_DBOX2: - if (demod_type == DEMOD_VES1893) - XIN = 91000000UL; - else if (demod_type == DEMOD_VES1993) - XIN = 96000000UL; - else - return -EINVAL; - break; - case BOARD_SAGEM_DBOX2: - XIN = 92160000UL; - break; - default: - return -EINVAL; - } - - if (srate > XIN/2) - srate = XIN/2; + if (srate > state->config->xin/2) + srate = state->config->xin/2; if (srate < 500000) srate = 500000; #define MUL (1UL<<26) - FIN = (XIN + 6000) >> 4; + FIN = (state->config->xin + 6000) >> 4; tmp = srate << 6; ratio = tmp / FIN; @@ -393,75 +245,102 @@ static int ves1x93_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) if (BDRI > 0xff) BDRI = 0xff; - ves1x93_writereg (i2c, 0x06, 0xff & BDR); - ves1x93_writereg (i2c, 0x07, 0xff & (BDR >> 8)); - ves1x93_writereg (i2c, 0x08, 0x0f & (BDR >> 16)); + ves1x93_writereg (state, 0x06, 0xff & BDR); + ves1x93_writereg (state, 0x07, 0xff & (BDR >> 8)); + ves1x93_writereg (state, 0x08, 0x0f & (BDR >> 16)); - ves1x93_writereg (i2c, 0x09, BDRI); - ves1x93_writereg (i2c, 0x20, ADCONF); - ves1x93_writereg (i2c, 0x21, FCONF); + ves1x93_writereg (state, 0x09, BDRI); + ves1x93_writereg (state, 0x20, ADCONF); + ves1x93_writereg (state, 0x21, FCONF); if (srate < 6000000) - ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] | 0x80); + ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] | 0x80); else - ves1x93_writereg (i2c, 0x05, init_1x93_tab[0x05] & 0x7f); + ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] & 0x7f); /* ves1993 hates this, will lose lock */ - if (demod_type != DEMOD_VES1993) - ves1x93_clr_bit (i2c); + if (state->demod_type != DEMOD_VES1993) + ves1x93_clr_bit (state); return 0; } -static int ves1x93_afc (struct dvb_i2c_bus *i2c, u32 freq, u32 srate) + + + + + + + + + + + + + +static int ves1x93_init (struct dvb_frontend* fe) { - int afc; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + int i; + int val; - afc = ((int)((ves1x93_readreg (i2c, 0x0a) << 1) & 0xff))/2; - afc = (afc * (int)(srate/1000/8))/16; - - if (afc) { - - freq -= afc; + dprintk("%s: init chip\n", __FUNCTION__); - tuner_set_tv_freq (i2c, freq, 0); + for (i = 0; i < state->tab_size; i++) { + if (state->init_1x93_wtab[i]) { + val = state->init_1x93_tab[i]; + + if (state->config->invert_pwm && (i == 0x05)) val |= 0x20; /* invert PWM */ + ves1x93_writereg (state, i, val); + } + } - ves1x93_init_aquire (i2c); + if (state->config->pll_init) { + ves1x93_writereg(state, 0x00, 0x11); + state->config->pll_init(fe); + ves1x93_writereg(state, 0x00, 0x01); } - + return 0; } -static int ves1x93_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + switch (voltage) { case SEC_VOLTAGE_13: - return ves1x93_writereg (i2c, 0x1f, 0x20); + return ves1x93_writereg (state, 0x1f, 0x20); case SEC_VOLTAGE_18: - return ves1x93_writereg (i2c, 0x1f, 0x30); + return ves1x93_writereg (state, 0x1f, 0x30); case SEC_VOLTAGE_OFF: - return ves1x93_writereg (i2c, 0x1f, 0x00); + return ves1x93_writereg (state, 0x1f, 0x00); default: return -EINVAL; } } - -static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct dvb_i2c_bus *i2c = fe->i2c; - struct ves1x93_state *state = (struct ves1x93_state*) fe->data; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - switch (cmd) { - case FE_GET_INFO: - memcpy (arg, &ves1x93_info, sizeof(struct dvb_frontend_info)); - break; + u8 sync = ves1x93_readreg (state, 0x0e); - case FE_READ_STATUS: - { - fe_status_t *status = arg; - u8 sync = ves1x93_readreg (i2c, 0x0e); + /* + * The ves1893 sometimes returns sync values that make no sense, + * because, e.g., the SIGNAL bit is 0, while some of the higher + * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?). + * Tests showed that the the VITERBI and SYNC bits are returned + * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong. + * If such a case occurs, we read the value again, until we get a + * valid value. + */ + int maxtry = 10; /* just for safety - let's not get stuck here */ + while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) { + msleep(10); + sync = ves1x93_readreg (state, 0x0e); + } *status = 0; @@ -480,65 +359,78 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) if ((sync & 0x1f) == 0x1f) *status |= FE_HAS_LOCK; - break; + return 0; } - case FE_READ_BER: + +static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber) { - u32 *ber = (u32 *) arg; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - *ber = ves1x93_readreg (i2c, 0x15); - *ber |= (ves1x93_readreg (i2c, 0x16) << 8); - *ber |= ((ves1x93_readreg (i2c, 0x17) & 0x0F) << 16); + *ber = ves1x93_readreg (state, 0x15); + *ber |= (ves1x93_readreg (state, 0x16) << 8); + *ber |= ((ves1x93_readreg (state, 0x17) & 0x0F) << 16); *ber *= 10; - break; + + return 0; } - case FE_READ_SIGNAL_STRENGTH: +static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength) { - u8 signal = ~ves1x93_readreg (i2c, 0x0b); - *((u16*) arg) = (signal << 8) | signal; - break; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + + u8 signal = ~ves1x93_readreg (state, 0x0b); + *strength = (signal << 8) | signal; + + return 0; } - case FE_READ_SNR: +static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr) { - u8 snr = ~ves1x93_readreg (i2c, 0x1c); - *(u16*) arg = (snr << 8) | snr; - break; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + + u8 _snr = ~ves1x93_readreg (state, 0x1c); + *snr = (_snr << 8) | _snr; + + return 0; } - case FE_READ_UNCORRECTED_BLOCKS: +static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - *(u32*) arg = ves1x93_readreg (i2c, 0x18) & 0x7f; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - if (*(u32*) arg == 0x7f) - *(u32*) arg = 0xffffffff; /* counter overflow... */ + *ucblocks = ves1x93_readreg (state, 0x18) & 0x7f; - ves1x93_writereg (i2c, 0x18, 0x00); /* reset the counter */ - ves1x93_writereg (i2c, 0x18, 0x80); /* dto. */ - break; + if (*ucblocks == 0x7f) + *ucblocks = 0xffffffff; /* counter overflow... */ + + ves1x93_writereg (state, 0x18, 0x00); /* reset the counter */ + ves1x93_writereg (state, 0x18, 0x80); /* dto. */ + + return 0; } - case FE_SET_FRONTEND: +static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; - - tuner_set_tv_freq (i2c, p->frequency, 0); - ves1x93_set_inversion (i2c, p->inversion); - ves1x93_set_fec (i2c, p->u.qpsk.fec_inner); - ves1x93_set_symbolrate (i2c, p->u.qpsk.symbol_rate); - ves1x93_afc (i2c, p->frequency, p->u.qpsk.symbol_rate); + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + + ves1x93_writereg(state, 0x00, 0x11); + state->config->pll_set(fe, p); + ves1x93_writereg(state, 0x00, 0x01); + ves1x93_set_inversion (state, p->inversion); + ves1x93_set_fec (state, p->u.qpsk.fec_inner); + ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate); state->inversion = p->inversion; - break; + + return 0; } - case FE_GET_FRONTEND: +static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { - struct dvb_frontend_parameters *p = arg; + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; int afc; - afc = ((int)((char)(ves1x93_readreg (i2c, 0x0a) << 1)))/2; + afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2; afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; p->frequency -= afc; @@ -548,113 +440,125 @@ static int ves1x93_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) * if auto inversion was used */ if (state->inversion == INVERSION_AUTO) - p->inversion = (ves1x93_readreg (i2c, 0x0f) & 2) ? + p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ? INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = ves1x93_get_fec (i2c); + p->u.qpsk.fec_inner = ves1x93_get_fec (state); /* XXX FIXME: timing offset !! */ - break; - } - - case FE_SLEEP: - if (board_type == BOARD_SIEMENS_PCI) - ves1x93_writereg (i2c, 0x1f, 0x00); /* LNB power off */ - return ves1x93_writereg (i2c, 0x00, 0x08); - - case FE_INIT: - return ves1x93_init (i2c); - case FE_SET_TONE: - return -EOPNOTSUPP; /* the ves1893 can generate the 22k */ - /* let's implement this when we have */ - /* a box that uses the 22K_0 pin... */ + return 0; +} - case FE_SET_VOLTAGE: - return ves1x93_set_voltage (i2c, (fe_sec_voltage_t) arg); +static int ves1x93_sleep(struct dvb_frontend* fe) +{ + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; - default: - return -EOPNOTSUPP; - }; + return ves1x93_writereg (state, 0x00, 0x08); +} - return 0; +static void ves1x93_release(struct dvb_frontend* fe) +{ + struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv; + kfree(state); } +static struct dvb_frontend_ops ves1x93_ops; -static int ves1x93_attach (struct dvb_i2c_bus *i2c, void **data) +struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, + struct i2c_adapter* i2c) { - u8 identity = ves1x93_readreg(i2c, 0x1e); - struct ves1x93_state* state; + struct ves1x93_state* state = NULL; + u8 identity; + + /* allocate memory for the internal state */ + state = (struct ves1x93_state*) kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL); + if (state == NULL) goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops)); + state->inversion = INVERSION_OFF; + /* check if the demod is there + identify it */ + identity = ves1x93_readreg(state, 0x1e); switch (identity) { case 0xdc: /* VES1893A rev1 */ printk("ves1x93: Detected ves1893a rev1\n"); - demod_type = DEMOD_VES1893; - ves1x93_info.name[4] = '8'; + state->demod_type = DEMOD_VES1893; + state->init_1x93_tab = init_1893_tab; + state->init_1x93_wtab = init_1893_wtab; + state->tab_size = sizeof(init_1893_tab); break; + case 0xdd: /* VES1893A rev2 */ printk("ves1x93: Detected ves1893a rev2\n"); - demod_type = DEMOD_VES1893; - ves1x93_info.name[4] = '8'; + state->demod_type = DEMOD_VES1893; + state->init_1x93_tab = init_1893_tab; + state->init_1x93_wtab = init_1893_wtab; + state->tab_size = sizeof(init_1893_tab); break; + case 0xde: /* VES1993 */ printk("ves1x93: Detected ves1993\n"); - demod_type = DEMOD_VES1993; - ves1x93_info.name[4] = '9'; + state->demod_type = DEMOD_VES1993; + state->init_1x93_tab = init_1993_tab; + state->init_1x93_wtab = init_1993_wtab; + state->tab_size = sizeof(init_1993_tab); break; - default: - dprintk("VES1x93 not found (identity %02x)\n", identity); - return -ENODEV; - } - if ((state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL)) == NULL) { - return -ENOMEM; - } - state->inversion = INVERSION_OFF; - *data = state; - - return dvb_register_frontend (ves1x93_ioctl, i2c, (void*) state, &ves1x93_info); -} - - -static void ves1x93_detach (struct dvb_i2c_bus *i2c, void *data) -{ - kfree(data); - dvb_unregister_frontend (ves1x93_ioctl, i2c); -} - - -static int __init init_ves1x93 (void) -{ - switch (board_type) { - case BOARD_NOKIA_DBOX2: - dprintk("%s: NOKIA_DBOX2\n", __FILE__); - break; - case BOARD_SAGEM_DBOX2: - dprintk("%s: SAGEM_DBOX2\n", __FILE__); - break; - case BOARD_SIEMENS_PCI: - dprintk("%s: SIEMENS_PCI\n", __FILE__); - break; default: - return -EIO; + goto error; } - return dvb_register_i2c_device (THIS_MODULE, ves1x93_attach, ves1x93_detach); -} - - -static void __exit exit_ves1x93 (void) -{ - dvb_unregister_i2c_device (ves1x93_attach); -} + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; +error: + if (state) kfree(state); + return NULL; + } -module_init(init_ves1x93); -module_exit(exit_ves1x93); +static struct dvb_frontend_ops ves1x93_ops = { + + .info = { + .name = "VLSI VES1x93 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + /* .symbol_rate_tolerance = ???,*/ + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK + }, + + .release = ves1x93_release, + + .init = ves1x93_init, + .sleep = ves1x93_sleep, + + .set_frontend = ves1x93_set_frontend, + .get_frontend = ves1x93_get_frontend, + + .read_status = ves1x93_read_status, + .read_ber = ves1x93_read_ber, + .read_signal_strength = ves1x93_read_signal_strength, + .read_snr = ves1x93_read_snr, + .read_ucblocks = ves1x93_read_ucblocks, + + .set_voltage = ves1x93_set_voltage, +}; +module_param(debug, int, 0644); -MODULE_DESCRIPTION("VES1x93 DVB-S Frontend"); +MODULE_DESCRIPTION("VLSI VES1x93 DVB-S Demodulator driver"); MODULE_AUTHOR("Ralph Metzler"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); -MODULE_PARM(board_type,"i"); +EXPORT_SYMBOL(ves1x93_attach); diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 99647b5ff..edb9c730e 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,9 +1,15 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE + depends on DVB_CORE && PCI select FW_LOADER select VIDEO_DEV select VIDEO_SAA7146_VV + select DVB_VES1820 + select DVB_VES1X93 + select DVB_STV0299 + select DVB_TDA8083 + select DVB_SP8870 + select DVB_STV0297 help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -11,11 +17,16 @@ config DVB_AV7110 This driver only supports the fullfeatured cards with onboard MPEG2 decoder. + This driver needs an external firmware. Please use the script + "/Documentation/dvb/get_dvb_firmware av7110" to + download/extract it, and then copy it to /usr/lib/hotplug/firmware. + Say Y if you own such a card and want to use it. config DVB_AV7110_FIRMWARE bool "Compile AV7110 firmware into the driver" depends on DVB_AV7110 && !STANDALONE + default y if DVB_AV7110=y help The AV7110 firmware is normally loaded by the firmware hotplug manager. If you want to compile the firmware into the driver you need to say @@ -33,6 +44,7 @@ config DVB_AV7110_FIRMWARE_FILE config DVB_AV7110_OSD bool "AV7110 OSD support" depends on DVB_AV7110 + default y if DVB_AV7110=y || DVB_AV7110=m help The AV7110 firmware provides some code to generate an OnScreenDisplay on the video output. This is kind of nonstandard and not guaranteed to @@ -45,8 +57,14 @@ config DVB_AV7110_OSD config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_SAA7146 + select DVB_STV0299 + select DVB_VES1X93 + select DVB_VES1820 + select DVB_L64781 + select DVB_TDA8083 + select DVB_TDA10021 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -59,8 +77,10 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_SAA7146 + select DVB_STV0299 + select DVB_TDA1004X help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -76,9 +96,10 @@ config DVB_BUDGET_CI config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_DEV select VIDEO_SAA7146_VV + select DVB_STV0299 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -91,8 +112,11 @@ config DVB_BUDGET_AV config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" - depends on DVB_BUDGET + depends on DVB_CORE && DVB_BUDGET select DVB_AV7110 + select DVB_STV0299 + select DVB_VES1X93 + select DVB_TDA8083 help Support for Budget Patch (full TS) modification on SAA7146+AV7110 based cards (DVB-S cards). This diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile index 2e8403b89..825ab1c38 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/dvb/ttpci/Makefile @@ -11,9 +11,9 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -host-progs := fdump +hostprogs-y := fdump ifdef CONFIG_DVB_AV7110_FIRMWARE $(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 11e9ba768..41ade3783 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -50,18 +51,14 @@ #include #include #include +#include #include #include #include -#include "dvb_i2c.h" #include "dvb_frontend.h" -#include "dvb_functions.h" - - - #define DEBUG_VARIABLE av7110_debug #include "ttpci-eeprom.h" #include "av7110.h" @@ -70,33 +67,112 @@ #include "av7110_ca.h" #include "av7110_ipack.h" - -static void restart_feeds(struct av7110 *av7110); - -int av7110_debug = 0; +int av7110_debug; static int vidmode=CVBS_RGB_OUT; static int pids_off; static int adac=DVB_ADAC_TI; -static int hw_sections = 0; -static int rgb_on = 0; +static int hw_sections; +static int rgb_on; +static int volume = 255; + +module_param_named(debug, av7110_debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); +module_param(vidmode, int, 0444); +MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); +module_param(pids_off, int, 0444); +MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed"); +module_param(adac, int, 0444); +MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)"); +module_param(hw_sections, int, 0444); +MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware"); +module_param(rgb_on, int, 0444); +MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control" + " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB"); +module_param(volume, int, 0444); +MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); + +static void restart_feeds(struct av7110 *av7110); + +static int av7110_num = 0; + +#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \ +{\ + if (fe_func != NULL) { \ + av7110_copy = fe_func; \ + fe_func = av7110_func; \ + } \ +} + + +static void init_av7110_av(struct av7110 *av7110) +{ + struct saa7146_dev *dev=av7110->dev; + + /* set internal volume control to maximum */ + av7110->adac_type = DVB_ADAC_TI; + av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); + + av7710_set_video_mode(av7110, vidmode); + + /* handle different card types */ + /* remaining inits according to card and frontend type */ + av7110->analog_tuner_flags = 0; + av7110->current_input = 0; + if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { + printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_CRYSTAL; + i2c_writereg(av7110, 0x20, 0x01, 0xd2); + i2c_writereg(av7110, 0x20, 0x02, 0x49); + i2c_writereg(av7110, 0x20, 0x03, 0x00); + i2c_writereg(av7110, 0x20, 0x04, 0x00); + + /** + * some special handling for the Siemens DVB-C cards... + */ + } else if (0 == av7110_init_analog_module(av7110)) { + /* done. */ + } + else if (dev->pci->subsystem_vendor == 0x110a) { + printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_NONE; + } + else { + av7110->adac_type = adac; + printk("dvb-ttpci: adac type set to %d @ card %d\n", + av7110->dvb_adapter->num, av7110->adac_type); + } -int av7110_num = 0; + if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { + // switch DVB SCART on + av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); + av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); + if (rgb_on && + (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 + //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 + } + } + av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right); + av7110_setup_irc_config(av7110, 0); +} static void recover_arm(struct av7110 *av7110) { - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n",av7110); av7110_bootarm(av7110); - dvb_delay(100); + msleep(100); restart_feeds(av7110); av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); } static void arm_error(struct av7110 *av7110) { - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n",av7110); av7110->arm_errors++; av7110->arm_ready=0; @@ -106,17 +182,22 @@ static void arm_error(struct av7110 *av7110) static int arm_thread(void *data) { struct av7110 *av7110 = data; - unsigned long timeout; u16 newloops = 0; + int timeout; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n",av7110); - dvb_kernel_thread_setup ("arm_mon"); + lock_kernel (); + daemonize ("arm_mon"); + sigfillset (¤t->blocked); + unlock_kernel (); + av7110->arm_thread = current; - while (1) { - timeout = wait_event_interruptible_timeout(av7110->arm_wait,0 != av7110->arm_rmmod, 5*HZ); - if (-ERESTARTSYS == timeout || 0 != av7110->arm_rmmod) { + for (;;) { + timeout = wait_event_interruptible_timeout(av7110->arm_wait, + av7110->arm_rmmod, 5 * HZ); + if (-ERESTARTSYS == timeout || av7110->arm_rmmod) { /* got signal or told to quit*/ break; } @@ -131,10 +212,13 @@ static int arm_thread(void *data) up(&av7110->dcomlock); if (newloops==av7110->arm_loops) { - printk(KERN_ERR "av7110%d: ARM crashed!\n", + printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n", av7110->dvb_adapter->num); arm_error(av7110); + av7710_set_video_mode(av7110, vidmode); + + init_av7110_av(av7110); if (down_interruptible(&av7110->dcomlock)) break; @@ -160,7 +244,7 @@ void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config) { static struct av7110 *last; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n",av7110); if (!av7110) av7110 = last; @@ -177,27 +261,27 @@ static void (*irc_handler)(u32); void av7110_register_irc_handler(void (*func)(u32)) { - DEB_EE(("registering %p\n", func)); + dprintk(4, "registering %p\n", func); irc_handler = func; } void av7110_unregister_irc_handler(void (*func)(u32)) { - DEB_EE(("unregistering %p\n", func)); + dprintk(4, "unregistering %p\n", func); irc_handler = NULL; } -void run_handlers(unsigned long ircom) +static void run_handlers(unsigned long ircom) { if (irc_handler != NULL) (*irc_handler)((u32) ircom); } -DECLARE_TASKLET(irtask,run_handlers,0); +static DECLARE_TASKLET(irtask, run_handlers, 0); -void IR_handle(struct av7110 *av7110, u32 ircom) +static void IR_handle(struct av7110 *av7110, u32 ircom) { - DEB_S(("av7110: ircommand = %08x\n", ircom)); + dprintk(4, "ircommand = %08x\n", ircom); irtask.data = (unsigned long) ircom; tasklet_schedule(&irtask); } @@ -206,14 +290,12 @@ void IR_handle(struct av7110 *av7110, u32 ircom) * IRQ handling ****************************************************************************/ -static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, +static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, struct dvb_demux_filter *dvbdmxfilter, enum dmx_success success, struct av7110 *av7110) { - DEB_INT(("av7110: %p\n",av7110)); - if (!dvbdmxfilter->feed->demux->dmx.frontend) return 0; if (dvbdmxfilter->feed->demux->dmx.frontend->source==DMX_MEMORY_FE) @@ -273,12 +355,11 @@ static void debiirq (unsigned long data) int type=av7110->debitype; int handle=(type>>8)&0x1f; -// DEB_EE(("av7110: %p\n",av7110)); +// dprintk(4, "%p\n",av7110); print_time("debi"); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); if (type==-1) { printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n", @@ -405,10 +486,8 @@ static void gpioirq (unsigned long data) u32 rxbuf, txbuf; int len; - //printk("GPIO0 irq\n"); - if (av7110->debitype !=-1) - printk("GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n", + printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n", jiffies, saa7146_read(av7110->dev, PSR), saa7146_read(av7110->dev, SSR)); @@ -416,9 +495,8 @@ static void gpioirq (unsigned long data) ARM_ClearIrq(av7110); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_19 ); - saa7146_write(av7110->dev, ISR, MASK_19 ); + SAA7146_IER_DISABLE(av7110->dev, MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19); av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2); av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); @@ -426,10 +504,10 @@ static void gpioirq (unsigned long data) txbuf=irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); len = (av7110->debilen + 3) & ~3; -// DEB_D(("GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen)); +// dprintk(8, "GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen); print_time("gpio"); -// DEB_D(("GPIO0 irq %02x\n", av7110->debitype&0xff)); +// dprintk(8, "GPIO0 irq %02x\n", av7110->debitype&0xff); switch (av7110->debitype&0xff) { case DATA_TS_PLAY: @@ -448,10 +526,10 @@ static void gpioirq (unsigned long data) iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); av7110->video_size.h = h_ar & 0xfff; - DEB_D(("GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", + dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", av7110->video_size.w, av7110->video_size.h, - av7110->video_size.aspect_ratio)); + av7110->video_size.aspect_ratio); event.type = VIDEO_EVENT_SIZE_CHANGED; event.u.size.w = av7110->video_size.w; @@ -504,7 +582,7 @@ static void gpioirq (unsigned long data) wake_up(&cibuf->queue); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); if (len < 5) @@ -539,10 +617,10 @@ static void gpioirq (unsigned long data) iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2); break; } - DEB_D(("GPIO0 PES_PLAY len=%04x\n", len)); + dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len); iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); @@ -569,7 +647,7 @@ static void gpioirq (unsigned long data) memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len); av7110->bmpp+=len; av7110->bmplen-=len; - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19 ); if (len < 5) @@ -591,7 +669,7 @@ static void gpioirq (unsigned long data) case DATA_TS_RECORD: case DATA_PES_RECORD: - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); saa7146_write(av7110->dev, IER, saa7146_read(av7110->dev, IER) | MASK_19); irdebi(av7110, DEBISWAB, DPRAM_BASE+rxbuf, 0, len); @@ -599,7 +677,7 @@ static void gpioirq (unsigned long data) return; case DATA_DEBUG_MESSAGE: - saa7146_wait_for_debi_done(av7110->dev); + saa7146_wait_for_debi_done(av7110->dev, 0); if (!len || len>0xff) { iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; @@ -617,7 +695,7 @@ static void gpioirq (unsigned long data) break; default: - printk("gpioirq unknown type=%d len=%d\n", + printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n", av7110->debitype, av7110->debilen); break; } @@ -634,10 +712,12 @@ static int dvb_osd_ioctl(struct inode *inode, struct file *file, struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (cmd == OSD_SEND_CMD) return av7110_osd_cmd(av7110, (osd_cmd_t *) parg); + if (cmd == OSD_GET_CAPABILITY) + return av7110_osd_capability(av7110, (osd_cap_t *) parg); return -EINVAL; } @@ -663,7 +743,7 @@ static struct dvb_device dvbdev_osd = { static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (vpid == 0x1fff || apid == 0x1fff || ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) { @@ -681,7 +761,7 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (down_interruptible(&av7110->pid_mutex)) return; @@ -720,7 +800,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) // u16 mode=0x0320; u16 mode=0xb96a; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (dvbdmxfilter->type == DMX_TYPE_SEC) { if (hw_sections) { @@ -743,9 +823,13 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) buf[3] = mode; ret = av7110_fw_request(av7110, buf, 20, &handle, 1); - if (ret < 0) { - printk("StartHWFilter error\n"); - return ret; + if (ret != 0 || handle >= 32) { + printk("dvb-ttpci: %s error buf %04x %04x %04x %04x " + "ret %x handle %04x\n", + __FUNCTION__, buf[0], buf[1], buf[2], buf[3], + ret, handle); + dvbdmxfilter->hw_handle = 0xffff; + return -1; } av7110->handle2filter[handle] = dvbdmxfilter; @@ -762,13 +846,12 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) int ret; u16 handle; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); handle = dvbdmxfilter->hw_handle; - if (handle > 32) { - DEB_S(("dvb: StopHWFilter tried to stop invalid filter %d.\n", - handle)); - DEB_S(("dvb: filter type = %d\n", dvbdmxfilter->type)); + if (handle >= 32) { + printk("%s tried to stop invalid filter %04x, filter type = %x\n", + __FUNCTION__, handle, dvbdmxfilter->type); return 0; } @@ -778,11 +861,11 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) buf[1] = 1; buf[2] = handle; ret = av7110_fw_request(av7110, buf, 3, answ, 2); - if (ret) - printk("StopHWFilter error\n"); - - if (answ[1] != handle) { - DEB_S(("dvb: filter %d shutdown error :%d\n", handle, answ[1])); + if (ret != 0 || answ[1] != handle) { + printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x " + "resp %04x %04x pid %d\n", + __FUNCTION__, buf[0], buf[1], buf[2], ret, + answ[0], answ[1], dvbdmxfilter->feed->pid); ret = -1; } return ret; @@ -796,7 +879,7 @@ static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) u16 *pid = dvbdmx->pids, npids[5]; int i; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff; i = dvbdmxfeed->pes_type; @@ -829,7 +912,7 @@ static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) u16 *pid = dvbdmx->pids, npids[5]; int i; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (dvbdmxfeed->pes_type <= 1) { av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO); @@ -860,9 +943,9 @@ static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) static int av7110_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (!demux->dmx.frontend) return -EINVAL; @@ -918,9 +1001,9 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) static int av7110_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (feed->type == DMX_TYPE_TS) { if (feed->ts_type & TS_DECODER) { @@ -962,7 +1045,7 @@ static void restart_feeds(struct av7110 *av7110) int mode; int i; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); mode = av7110->playing; av7110->playing = 0; @@ -995,7 +1078,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, BUG(); av7110 = (struct av7110 *) dvbdemux->priv; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (num != 0) return -EINVAL; @@ -1005,14 +1088,14 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__); return -EIO; } - DEB_EE(("av7110: fwstc = %04hx %04hx %04hx %04hx\n", - fwstc[0], fwstc[1], fwstc[2], fwstc[3])); + dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n", + fwstc[0], fwstc[1], fwstc[2], fwstc[3]); *stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) | (((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]); *base = 1; - DEB_EE(("av7110: stc = %lu\n", (unsigned long)*stc)); + dprintk(4, "stc = %lu\n", (unsigned long)*stc); return 0; } @@ -1022,71 +1105,44 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, * SEC device file operations ******************************************************************************/ -static int av7110_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct av7110 *av7110 = fe->before_after_data; - DEB_EE(("av7110: %p\n", av7110)); +static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + switch (tone) { case SEC_TONE_ON: Set22K(av7110, 1); break; case SEC_TONE_OFF: Set22K(av7110, 0); break; + default: return -EINVAL; -}; - break; - - case FE_DISEQC_SEND_MASTER_CMD: - { - struct dvb_diseqc_master_cmd *cmd = arg; - av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1); - break; } - case FE_DISEQC_SEND_BURST: - av7110_diseqc_send(av7110, 0, NULL, (unsigned long) arg); - break; - - default: - return -EOPNOTSUPP; -}; - return 0; } - -static void av7110_before_after_tune (fe_status_t s, void *data) +static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) { - struct av7110 *av7110 = data; - - DEB_EE(("av7110: %p\n",av7110)); + struct av7110* av7110 = fe->dvb->priv; - av7110->fe_synced = (s & FE_HAS_LOCK) ? 1 : 0; + av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1); - if (av7110->playing) - return; + return 0; +} - if (down_interruptible(&av7110->pid_mutex)) - return; +static int av7110_diseqc_send_burst(struct dvb_frontend* fe, + fe_sec_mini_cmd_t minicmd) +{ + struct av7110* av7110 = fe->dvb->priv; - if (av7110->fe_synced) { - SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO], - av7110->pids[DMX_PES_AUDIO], - av7110->pids[DMX_PES_TELETEXT], 0, - av7110->pids[DMX_PES_PCR]); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); - } else { - SetPIDs(av7110, 0, 0, 0, 0, 0); - av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, FlushTSQueue, 0); - } + av7110_diseqc_send(av7110, 0, NULL, minicmd); - up(&av7110->pid_mutex); + return 0; } @@ -1095,22 +1151,13 @@ static int av7110_register(struct av7110 *av7110) int ret, i; struct dvb_demux *dvbdemux=&av7110->demux; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (av7110->registered) return -1; av7110->registered=1; - dvb_add_frontend_notifier (av7110->dvb_adapter, - av7110_before_after_tune, av7110); - - /** - * init DiSEqC stuff - */ - dvb_add_frontend_ioctls (av7110->dvb_adapter, - av7110_diseqc_ioctl, NULL, av7110); - dvbdemux->priv = (void *) av7110; for (i=0; i<32; i++) @@ -1170,7 +1217,7 @@ static void dvb_unregister(struct av7110 *av7110) { struct dvb_demux *dvbdemux=&av7110->demux; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (!av7110->registered) return; @@ -1184,12 +1231,8 @@ static void dvb_unregister(struct av7110 *av7110) dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - dvb_remove_frontend_notifier (av7110->dvb_adapter, - av7110_before_after_tune); - - dvb_remove_frontend_ioctls (av7110->dvb_adapter, - av7110_diseqc_ioctl, NULL); - + if (av7110->fe != NULL) + dvb_unregister_frontend(av7110->fe); dvb_unregister_device(av7110->osd_dev); av7110_av_unregister(av7110); av7110_ca_unregister(av7110); @@ -1203,19 +1246,18 @@ static void dvb_unregister(struct av7110 *av7110) int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) { u8 msg[2] = { reg, val }; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs; msgs.flags = 0; msgs.addr = id / 2; msgs.len = 2; msgs.buf = msg; - return i2c->xfer(i2c, &msgs, 1); + return i2c_transfer(&av7110->i2c_adap, &msgs, 1); } +#if 0 u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) { - struct dvb_i2c_bus *i2c = av7110->i2c_bus; u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; struct i2c_msg msgs[2]; @@ -1226,16 +1268,11 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) mm1[0] = reg; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = mm2; - i2c->xfer(i2c, msgs, 2); + i2c_transfer(&av7110->i2c_adap, msgs, 2); return mm2[0]; } - -static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) -{ - struct saa7146_dev *dev = i2c->data; - return saa7146_i2c_transfer(dev, msgs, num, 6); -} +#endif /**************************************************************************** * INITIALIZATION @@ -1310,44 +1347,616 @@ static int get_firmware(struct av7110* av7110) /* request the av7110 firmware, this will block until someone uploads it */ ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev); if (ret) { - printk("dvb-ttpci: cannot request firmware!\n"); + if (ret == -ENOENT) { + printk(KERN_ERR "dvb-ttpci: could not load firmware," + " file not found: dvb-ttpci-01.fw\n"); + printk(KERN_ERR "dvb-ttpci: usually this should be in" + " /usr/lib/hotplug/firmware\n"); + printk(KERN_ERR "dvb-ttpci: and can be downloaded here" + " http://www.linuxtv.org/download/dvb/firmware/\n"); + } else + printk(KERN_ERR "dvb-ttpci: cannot request firmware" + " (error %i)\n", ret); return -EINVAL; } + if (fw->size <= 200000) { printk("dvb-ttpci: this firmware is way too small.\n"); + release_firmware(fw); return -EINVAL; } + /* check if the firmware is available */ av7110->bin_fw = (unsigned char*) vmalloc(fw->size); if (NULL == av7110->bin_fw) { - DEB_D(("out of memory\n")); + dprintk(1, "out of memory\n"); + release_firmware(fw); return -ENOMEM; } + memcpy(av7110->bin_fw, fw->data, fw->size); av7110->size_fw = fw->size; if ((ret = check_firmware(av7110))) vfree(av7110->bin_fw); + + release_firmware(fw); return ret; } #endif + +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; + + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct ves1x93_config alps_bsrv2_config = { + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; + + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + int ret; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + ret = i2c_transfer (&av7110->i2c_adap, &msg, 1); + if (ret != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + + + +static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (params->frequency + 35937500 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85 | ((div >> 10) & 0x60); + data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct ves1820_config alps_tdbe2_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = alps_tdbe2_pll_set, +}; + + + + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + + + +static int philips_cd1516_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u32 f = params->frequency; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (f + 36125000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34); + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct ves1820_config philips_cd1516_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = philips_cd1516_pll_set, +}; + + + +static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div, pwr; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (params->frequency + 36200000) / 166666; + + if (params->frequency <= 782000000) + pwr = 1; + else + pwr = 2; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85; + data[3] = pwr << 6; + + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct av7110* av7110 = (struct av7110*) fe->dvb->priv; + + return request_firmware(fw, name, &av7110->dev->pci->dev); +} + +static struct sp8870_config alps_tdlb7_config = { + + .demod_address = 0x71, + .pll_set = alps_tdlb7_pll_set, + .request_firmware = alps_tdlb7_request_firmware, +}; + + + +static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) }; + struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 }; + int i; + + div = (params->frequency + 36150000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0xce; + + if (params->frequency < 45000000) + return -EINVAL; + else if (params->frequency < 137000000) + data[3] = 0x01; + else if (params->frequency < 403000000) + data[3] = 0x02; + else if (params->frequency < 860000000) + data[3] = 0x04; + else + return -EINVAL; + + stv0297_enable_plli2c(fe); + if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) { + printk("nexusca: pll transfer failed!\n"); + return -EIO; + } + + // wait for PLL lock + for(i=0; i< 20; i++) { + + stv0297_enable_plli2c(fe); + if (i2c_transfer (&av7110->i2c_adap, &readmsg, 1) == 1) + if (data[0] & 0x40) break; + msleep(10); + } + + return 0; +} + +static struct stv0297_config nexusca_stv0297_config = { + + .demod_address = 0x1C, + .pll_set = nexusca_stv0297_pll_set, +}; + + +static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status) +{ + int synced = (status & FE_HAS_LOCK) ? 1 : 0; + + av7110->fe_status = status; + + if (av7110->fe_synced == synced) + return; + + av7110->fe_synced = synced; + + if (av7110->playing) + return; + + if (down_interruptible(&av7110->pid_mutex)) + return; + + if (av7110->fe_synced) { + SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO], + av7110->pids[DMX_PES_AUDIO], + av7110->pids[DMX_PES_TELETEXT], 0, + av7110->pids[DMX_PES_PCR]); + av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0); + } else { + SetPIDs(av7110, 0, 0, 0, 0, 0); + av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0); + av7110_wait_msgstate(av7110, GPMQBusy); + } + + up(&av7110->pid_mutex); +} + +static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct av7110* av7110 = fe->dvb->priv; + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_frontend(fe, params); +} + +static int av7110_fe_init(struct dvb_frontend* fe) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_init(fe); +} + +static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct av7110* av7110 = fe->dvb->priv; + int ret; + + /* call the real implementation */ + ret = av7110->fe_read_status(fe, status); + if (ret) + return ret; + + if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK)) { + av7110_fe_lock_fix(av7110, *status); + } + + return 0; +} + +static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_reset_overload(fe); +} + +static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd* cmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_send_master_cmd(fe, cmd); +} + +static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_diseqc_send_burst(fe, minicmd); +} + +static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_tone(fe, tone); +} + +static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_set_voltage(fe, voltage); +} + +static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd) +{ + struct av7110* av7110 = fe->dvb->priv; + + av7110_fe_lock_fix(av7110, 0); + return av7110->fe_dishnetwork_send_legacy_command(fe, cmd); +} + +static u8 read_pwm(struct av7110* av7110) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, + { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; + + if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static void frontend_init(struct av7110 *av7110) +{ + if (av7110->dev->pci->subsystem_vendor == 0x110a) { + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??)) + av7110->fe = ves1820_attach(&philips_cd1516_config, + &av7110->i2c_adap, read_pwm(av7110)); + break; + } + + } else if (av7110->dev->pci->subsystem_vendor == 0x13c2) { + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X + case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X + case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE + + // try the ALPS BSRV2 first of all + av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + // try the ALPS BSRU6 now + av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + // Try the grundig 29504-451 + av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops->set_tone = av7110_set_tone; + break; + } + + /* Try DVB-C cards */ + switch(av7110->dev->pci->subsystem_device) { + case 0x0000: + /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ + av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + case 0x0003: + /* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */ + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, + read_pwm(av7110)); + break; + } + break; + + case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X + + // ALPS TDLB7 + av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + break; + + case 0x0002: // Hauppauge/TT DVB-C premium rev2.X + + av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + break; + + case 0x000A: // Hauppauge/TT Nexus-CA rev1.X + + av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b); + if (av7110->fe) { + /* set TDA9819 into DVB mode */ + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + + /* tuner on this needs a slower i2c bus speed */ + av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; + break; + } + } + } + + if (av7110->fe == NULL) { + printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + av7110->dev->pci->vendor, + av7110->dev->pci->device, + av7110->dev->pci->subsystem_vendor, + av7110->dev->pci->subsystem_device); + } else { + FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init); + FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd); + FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;) + FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); + FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); + + if (dvb_register_frontend(av7110->dvb_adapter, av7110->fe)) { + printk("av7110: Frontend registration failed!\n"); + if (av7110->fe->ops->release) + av7110->fe->ops->release(av7110->fe); + av7110->fe = NULL; + } + } +} + static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) { struct av7110 *av7110 = NULL; int ret = 0; - DEB_EE(("dev: %p\n", dev)); + dprintk(4, "dev: %p\n", dev); /* prepare the av7110 device struct */ if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) { - printk ("%s: out of memory!\n", __FUNCTION__); + dprintk(1, "out of memory\n"); return -ENOMEM; } - DEB_EE(("av7110: %p\n", av7110)); + memset(av7110, 0, sizeof(struct av7110)); av7110->card_name = (char*)pci_ext->ext_priv; - av7110->dev=(struct saa7146_dev *)dev; + av7110->dev = dev; dev->ext_priv = av7110; if ((ret = get_firmware(av7110))) { @@ -1361,18 +1970,22 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d get recognized before the main driver is fully loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - saa7146_i2c_adapter_prepare(dev, NULL, 0, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; +#else + av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL; +#endif + strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); - av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, - av7110->dvb_adapter, 0); + saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ - if (!av7110->i2c_bus) { + if (i2c_add_adapter(&av7110->i2c_adap) < 0) { dvb_unregister_adapter (av7110->dvb_adapter); kfree(av7110); return -ENOMEM; } - ttpci_eeprom_parse_mac(av7110->i2c_bus); + ttpci_eeprom_parse_mac(&av7110->i2c_adap, av7110->dvb_adapter->proposed_mac); saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -1394,11 +2007,11 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d /* locks for data transfers from/to AV7110 */ spin_lock_init (&av7110->debilock); sema_init(&av7110->dcomlock, 1); - av7110->debilock=SPIN_LOCK_UNLOCKED; av7110->debitype=-1; /* default OSD window */ av7110->osdwin=1; + sema_init(&av7110->osd_sema, 1); /* ARM "watchdog" */ init_waitqueue_head(&av7110->arm_wait); @@ -1434,63 +2047,21 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d } if (FW_VERSION(av7110->arm_app)<0x2501) - printk ("av7110: Warning, firmware version 0x%04x is too old. " + printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. " "System might be unstable!\n", FW_VERSION(av7110->arm_app)); if (kernel_thread(arm_thread, (void *) av7110, 0) < 0) { - printk(KERN_ERR "av7110(%d): faile to start arm_mon kernel thread\n", + printk("dvb-ttpci: failed to start arm_mon kernel thread @ card %d\n", av7110->dvb_adapter->num); goto err2; } - /* set internal volume control to maximum */ - av7110->adac_type = DVB_ADAC_TI; - av7110_set_volume(av7110, 0xff, 0xff); - - av7710_set_video_mode(av7110, vidmode); - - /* handle different card types */ - /* remaining inits according to card and frontend type */ - av7110->has_analog_tuner = 0; - av7110->current_input = 0; - if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) { - printk ("av7110(%d): Crystal audio DAC detected\n", - av7110->dvb_adapter->num); - av7110->adac_type = DVB_ADAC_CRYSTAL; - i2c_writereg(av7110, 0x20, 0x01, 0xd2); - i2c_writereg(av7110, 0x20, 0x02, 0x49); - i2c_writereg(av7110, 0x20, 0x03, 0x00); - i2c_writereg(av7110, 0x20, 0x04, 0x00); + /* set initial volume in mixer struct */ + av7110->mixer.volume_left = volume; + av7110->mixer.volume_right = volume; - /** - * some special handling for the Siemens DVB-C cards... - */ - } else if (0 == av7110_init_analog_module(av7110)) { - /* done. */ - } - else if (dev->pci->subsystem_vendor == 0x110a) { - printk("av7110(%d): DVB-C w/o analog module detected\n", - av7110->dvb_adapter->num); - av7110->adac_type = DVB_ADAC_NONE; - } - else { - av7110->adac_type = adac; - printk("av7110(%d): adac type set to %d\n", - av7110->dvb_adapter->num, av7110->adac_type); - } + init_av7110_av(av7110); - if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { - // switch DVB SCART on - av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); - av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - if (rgb_on) - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 - //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 - } - - av7110_set_volume(av7110, 0xff, 0xff); - - av7110_setup_irc_config (av7110, 0); av7110_register(av7110); /* special case DVB-C: these cards have an analog tuner @@ -1501,7 +2072,10 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d if (ret) goto err3; - printk(KERN_INFO "av7110: found av7110-%d.\n",av7110_num); + av7110->dvb_adapter->priv = av7110; + frontend_init(av7110); + + printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num); av7110->device_initialized = 1; av7110_num++; return 0; @@ -1510,13 +2084,12 @@ err3: av7110->arm_rmmod = 1; wake_up_interruptible(&av7110->arm_wait); while (av7110->arm_thread) - dvb_delay(1); + msleep(1); err2: av7110_ca_exit(av7110); av7110_av_exit(av7110); err: - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, - av7110->i2c_bus->id); + i2c_del_adapter(&av7110->i2c_adap); dvb_unregister_adapter (av7110->dvb_adapter); @@ -1534,7 +2107,7 @@ err: static int av7110_detach (struct saa7146_dev* saa) { struct av7110 *av7110 = (struct av7110*)saa->ext_priv; - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if( 0 == av7110->device_initialized ) { return 0; @@ -1546,15 +2119,12 @@ static int av7110_detach (struct saa7146_dev* saa) wake_up_interruptible(&av7110->arm_wait); while (av7110->arm_thread) - dvb_delay(1); + msleep(1); dvb_unregister(av7110); - IER_DISABLE(saa, (MASK_19 | MASK_03)); -// saa7146_write (av7110->dev, IER, -// saa7146_read(av7110->dev, IER) & ~(MASK_19 | MASK_03)); - - saa7146_write(av7110->dev, ISR,(MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03); av7110_ca_exit(av7110); av7110_av_exit(av7110); @@ -1563,7 +2133,8 @@ static int av7110_detach (struct saa7146_dev* saa) pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); + i2c_del_adapter(&av7110->i2c_adap); + dvb_unregister_adapter (av7110->dvb_adapter); av7110_num--; @@ -1580,9 +2151,7 @@ static int av7110_detach (struct saa7146_dev* saa) static void av7110_irq(struct saa7146_dev* dev, u32 *isr) { - struct av7110 *av7110 = (struct av7110*)dev->ext_priv; - -// DEB_INT(("dev: %p, av7110: %p\n",dev,av7110)); + struct av7110 *av7110 = dev->ext_priv; if (*isr & MASK_19) tasklet_schedule (&av7110->debi_tasklet); @@ -1599,33 +2168,29 @@ static struct saa7146_pci_extension_data x_var = { \ .ext_priv = x_name, \ .ext = &av7110_extension } -MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5"); -MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3"); -MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6"); -MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1"); -MAKE_AV7110_INFO(tt_t, "Technotrend/Hauppauge PCI DVB-T"); -MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?"); -MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?"); -MAKE_AV7110_INFO(unkwn2, "Technotrend/Hauppauge PCI rev?(unknown2)?"); -MAKE_AV7110_INFO(nexus, "Technotrend/Hauppauge Nexus PCI DVB-S"); -MAKE_AV7110_INFO(dvboc11,"Octal/Technotrend DVB-C for iTV"); +MAKE_AV7110_INFO(tts_1_X, "Technotrend/Hauppauge WinTV DVB-S rev1.X"); +MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X"); +MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X"); +MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X"); +MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X"); +MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV Nexus-S rev1.3"); +MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); static struct pci_device_id pci_tbl[] = { - MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff), - MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000), - MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000), - MAKE_EXTENSION_PCI(unkwn0, 0x13c2, 0x1002), - MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0001), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0002), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0003), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004), - MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006), - MAKE_EXTENSION_PCI(tt_t, 0x13c2, 0x0008), - MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102), - MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000), - MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1), - MAKE_EXTENSION_PCI(nexus, 0x00a1, 0xa1a0), - MAKE_EXTENSION_PCI(dvboc11,0x13c2, 0x000a), + MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000), + MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), + MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), + MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), + MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), + MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), + MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), + +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0006), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-S v???? +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0008), UNDEFINED CARD */ // TT/Hauppauge WinTV DVB-T v???? +/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? + { .vendor = 0, } @@ -1684,15 +2249,3 @@ MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by " MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); MODULE_LICENSE("GPL"); -MODULE_PARM(av7110_debug,"i"); -MODULE_PARM(vidmode,"i"); -MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); -MODULE_PARM(pids_off,"i"); -MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed"); -MODULE_PARM(adac,"i"); -MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)"); -MODULE_PARM(hw_sections, "i"); -MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware"); -MODULE_PARM(rgb_on, "i"); -MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control" - " signal on SCART pin 16 to switch SCART video mode from CVBS to RGB"); diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index c9485eeef..f25a825d7 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h @@ -4,13 +4,12 @@ #include #include #include +#include #ifdef CONFIG_DEVFS_FS #include #endif -#include - #include #include #include @@ -25,7 +24,25 @@ #include "dvb_filter.h" #include "dvb_net.h" #include "dvb_ringbuffer.h" +#include "dvb_frontend.h" +#include "ves1820.h" +#include "ves1x93.h" +#include "stv0299.h" +#include "tda8083.h" +#include "sp8870.h" +#include "stv0297.h" + +#include + +#define ANALOG_TUNER_VES1820 1 +#define ANALOG_TUNER_STV0297 2 +#define ANALOG_TUNER_VBI 0x100 + +extern int av7110_debug; + +#define dprintk(level,args...) \ + do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0) #define MAXFILT 32 @@ -60,16 +77,17 @@ struct av7110 { struct dvb_device dvb_dev; struct dvb_net dvb_net; - struct video_device v4l_dev; - struct video_device vbi_dev; + struct video_device *v4l_dev; + struct video_device *vbi_dev; struct saa7146_dev *dev; - struct dvb_i2c_bus *i2c_bus; + struct i2c_adapter i2c_adap; + char *card_name; /* support for analog module of dvb-c */ - int has_analog_tuner; + int analog_tuner_flags; int current_input; u32 current_freq; @@ -109,8 +127,8 @@ struct av7110 { spinlock_t debilock; struct semaphore dcomlock; - int debitype; - int debilen; + volatile int debitype; + volatile int debilen; /* Recording and playback flags */ @@ -127,7 +145,7 @@ struct av7110 { int osdwin; /* currently active window */ u16 osdbpp[8]; - + struct semaphore osd_sema; /* CA */ @@ -187,6 +205,7 @@ struct av7110 { struct dvb_ringbuffer ci_rbuffer; struct dvb_ringbuffer ci_wbuffer; + struct audio_mixer mixer; struct dvb_adapter *dvb_adapter; struct dvb_device *video_dev; @@ -210,6 +229,18 @@ struct av7110 { unsigned char *bin_root; unsigned long size_root; + + struct dvb_frontend* fe; + fe_status_t fe_status; + int (*fe_init)(struct dvb_frontend* fe); + int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status); + int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe); + int (*fe_diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd); + int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd); + int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone); + int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); + int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd); + int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index b922851d8..f875efcf5 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -37,14 +37,10 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - #include "av7110.h" #include "av7110_hw.h" #include "av7110_av.h" #include "av7110_ipack.h" -#include "dvb_functions.h" /* MPEG-2 (ISO 13818 / H.222.0) stream types */ #define PROG_STREAM_MAP 0xBC @@ -102,8 +98,6 @@ int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) { struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv; -// DEB_EE(("struct dvb_filter_pes2ts:%p\n", p2t)); - if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; if (buf[3] == 0xe0) // video PES do not have a length in TS @@ -119,8 +113,6 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data) { struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv; -// DEB_EE(("dvb_demux_feed:%p\n", dvbdmxfeed)); - dvbdmxfeed->cb.ts(data, 188, NULL, 0, &dvbdmxfeed->feed.ts, DMX_OK); return 0; @@ -131,7 +123,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av, { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - DEB_EE(("av7110: %p, dvb_demux_feed:%p\n", av7110, dvbdmxfeed)); + dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed); if (av7110->playing || (av7110->rec_mode & av)) return -EBUSY; @@ -173,7 +165,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av, int av7110_av_start_play(struct av7110 *av7110, int av) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (av7110->rec_mode) return -EBUSY; @@ -206,7 +198,7 @@ int av7110_av_start_play(struct av7110 *av7110, int av) void av7110_av_stop(struct av7110 *av7110, int av) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (!(av7110->playing & av) && !(av7110->rec_mode & av)) return; @@ -247,8 +239,6 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) u32 sync; u16 blen; - DEB_EE(("dvb_ring_buffer_t: %p\n", buf)); - if (!dlen) { wake_up(&buf->queue); return -1; @@ -279,8 +269,8 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) dvb_ringbuffer_read(buf, dest, (size_t) blen, 0); - DEB_S(("pread=0x%08lx, pwrite=0x%08lx\n", - (unsigned long) buf->pread, (unsigned long) buf->pwrite)); + dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n", + (unsigned long) buf->pread, (unsigned long) buf->pwrite); wake_up(&buf->queue); return blen; } @@ -290,7 +280,10 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright) { int err, vol, val, balance = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); + + av7110->mixer.volume_left = volleft; + av7110->mixer.volume_right = volright; switch (av7110->adac_type) { case DVB_ADAC_TI: @@ -326,7 +319,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright) void av7110_set_vidmode(struct av7110 *av7110, int mode) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode); @@ -354,7 +347,7 @@ static void get_video_format(struct av7110 *av7110, u8 *buf, int count) int sw; u8 *p; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (av7110->sinfo) return; @@ -367,7 +360,7 @@ static void get_video_format(struct av7110 *av7110, u8 *buf, int count) vsize = ((p[1] &0x0F) << 8) | (p[2]); sw = (p[3] & 0x0F); av7110_set_vidmode(av7110, sw2mode[sw]); - DEB_S(("dvb: playback %dx%d fr=%d\n", hsize, vsize, sw)); + dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw); av7110->sinfo = 1; break; } @@ -404,7 +397,7 @@ static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf, static void play_video_cb(u8 *buf, int count, void *priv) { struct av7110 *av7110 = (struct av7110 *) priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((buf[3] & 0xe0) == 0xe0) { get_video_format(av7110, buf, count); @@ -416,7 +409,7 @@ static void play_video_cb(u8 *buf, int count, void *priv) static void play_audio_cb(u8 *buf, int count, void *priv) { struct av7110 *av7110 = (struct av7110 *) priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); aux_ring_buffer_write(&av7110->aout, buf, count); } @@ -428,7 +421,7 @@ static ssize_t dvb_play(struct av7110 *av7110, const u8 __user *buf, unsigned long count, int nonblock, int type) { unsigned long todo = count, n; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (!av7110->kbuf[type]) return -ENOBUFS; @@ -461,7 +454,7 @@ static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf, unsigned long count, int nonblock, int type) { unsigned long todo = count, n; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (!av7110->kbuf[type]) return -ENOBUFS; @@ -491,7 +484,7 @@ static ssize_t dvb_aplay(struct av7110 *av7110, const u8 __user *buf, unsigned long count, int nonblock, int type) { unsigned long todo = count, n; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (!av7110->kbuf[type]) return -ENOBUFS; @@ -681,7 +674,7 @@ void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t } -int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length) +static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length) { int i; int c = 0; @@ -770,7 +763,7 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l struct av7110 *av7110 = (struct av7110 *) demux->priv; struct ipack *ipack = &av7110->ipack[feed->pes_type]; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); switch (feed->pes_type) { case 0: @@ -811,8 +804,6 @@ void dvb_video_add_event(struct av7110 *av7110, struct video_event *event) struct dvb_video_events *events = &av7110->video_events; int wp; - DEB_D(("\n")); - spin_lock_bh(&events->lock); wp = (events->eventw + 1) % MAX_VIDEO_EVENT; @@ -835,8 +826,6 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event { struct dvb_video_events *events = &av7110->video_events; - DEB_D(("\n")); - if (events->overflow) { events->overflow = 0; return -EOVERFLOW; @@ -875,7 +864,7 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned int mask = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((file->f_flags & O_ACCMODE) != O_RDONLY) poll_wait(file, &av7110->avout.queue, wait); @@ -902,7 +891,7 @@ static ssize_t dvb_video_write(struct file *file, const char __user *buf, struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((file->f_flags & O_ACCMODE) == O_RDONLY) return -EPERM; @@ -919,7 +908,7 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned int mask = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); poll_wait(file, &av7110->aout.queue, wait); @@ -938,7 +927,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) { printk(KERN_ERR "not audio source memory\n"); @@ -947,7 +936,7 @@ static ssize_t dvb_audio_write(struct file *file, const char __user *buf, return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0); } -u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; +static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 }; #define MIN_IFRAME 400000 @@ -955,7 +944,7 @@ static int play_iframe(struct av7110 *av7110, u8 __user *buf, unsigned int len, { int i, n; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (!(av7110->playing & RP_VIDEO)) { if (av7110_av_start_play(av7110, RP_VIDEO) < 0) @@ -985,7 +974,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file, unsigned long arg = (unsigned long) parg; int ret = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT && @@ -1181,7 +1170,7 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file, unsigned long arg = (unsigned long) parg; int ret = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (((file->f_flags & O_ACCMODE) == O_RDONLY) && (cmd != AUDIO_GET_STATUS)) @@ -1297,7 +1286,7 @@ static int dvb_video_open(struct inode *inode, struct file *file) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; int err; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((err = dvb_generic_open(inode, file)) < 0) return err; @@ -1321,7 +1310,7 @@ static int dvb_video_release(struct inode *inode, struct file *file) struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if ((file->f_flags & O_ACCMODE) != O_RDONLY) { av7110_av_stop(av7110, RP_VIDEO); @@ -1336,7 +1325,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; int err=dvb_generic_open(inode, file); - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); if (err < 0) return err; @@ -1350,7 +1339,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file) struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(2, "av7110:%p, \n", av7110); av7110_av_stop(av7110, RP_AUDIO); return dvb_generic_release(inode, file); diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 2d169d630..0bd0da28d 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -38,18 +38,13 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - -#include "dvb_i2c.h" #include "av7110.h" #include "av7110_hw.h" -#include "dvb_functions.h" void CI_handle(struct av7110 *av7110, u8 *data, u16 len) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); if (len < 3) return; @@ -94,20 +89,20 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) * CI link layer file ops ******************************************************************************/ -int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) +static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) { dvb_ringbuffer_init(cirbuf, vmalloc(size), size); dvb_ringbuffer_init(ciwbuf, vmalloc(size), size); return 0; } -void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { dvb_ringbuffer_flush_spinlock_wakeup(cirbuf); dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); } -void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { vfree(cirbuf->data); cirbuf->data = NULL; @@ -115,7 +110,7 @@ void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) ciwbuf->data = NULL; } -int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, +static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, int slots, ca_slot_info_t *slot) { int i; @@ -212,7 +207,7 @@ static int dvb_ca_open(struct inode *inode, struct file *file) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; int err = dvb_generic_open(inode, file); - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); if (err < 0) return err; @@ -228,13 +223,16 @@ static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; unsigned int mask = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); poll_wait(file, &rbuf->queue, wait); + poll_wait(file, &wbuf->queue, wait); + if (!dvb_ringbuffer_empty(rbuf)) - mask |= POLLIN; - if (dvb_ringbuffer_avail(wbuf) > 1024) - mask |= POLLOUT; + mask |= (POLLIN | POLLRDNORM); + + if (dvb_ringbuffer_free(wbuf) > 1024) + mask |= (POLLOUT | POLLWRNORM); return mask; } @@ -246,7 +244,7 @@ static int dvb_ca_ioctl(struct inode *inode, struct file *file, struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned long arg = (unsigned long) parg; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); switch (cmd) { case CA_RESET: @@ -323,7 +321,7 @@ static ssize_t dvb_ca_write(struct file *file, const char __user *buf, struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); } @@ -333,7 +331,7 @@ static ssize_t dvb_ca_read(struct file *file, char __user *buf, struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); } diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 054018b3f..c6f0160f8 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -38,12 +38,8 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - #include "av7110.h" #include "av7110_hw.h" -#include "dvb_functions.h" /**************************************************************************** * DEBI functions @@ -57,10 +53,14 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config, { struct saa7146_dev *dev = av7110->dev; - if (count <= 0 || count > 32764) + if (count <= 0 || count > 32764) { + printk("%s: invalid count %d\n", __FUNCTION__, count); return -1; - if (saa7146_wait_for_debi_done(av7110->dev) < 0) + } + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done failed\n", __FUNCTION__); return -1; + } saa7146_write(dev, DEBI_CONFIG, config); if (count <= 4) /* immediate transfer */ saa7146_write(dev, DEBI_AD, val); @@ -76,10 +76,14 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) struct saa7146_dev *dev = av7110->dev; u32 result = 0; - if (count > 32764 || count <= 0) + if (count > 32764 || count <= 0) { + printk("%s: invalid count %d\n", __FUNCTION__, count); return 0; - if (saa7146_wait_for_debi_done(av7110->dev) < 0) + } + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__); return 0; + } saa7146_write(dev, DEBI_AD, av7110->debi_bus); saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); @@ -87,7 +91,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) saa7146_write(dev, MC2, (2 << 16) | 2); if (count > 4) return count; - saa7146_wait_for_debi_done(av7110->dev); + if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) { + printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__); + return 0; + } + result = saa7146_read(dev, DEBI_AD); result &= (0xffffffffUL >> ((4 - count) * 8)); return result; @@ -102,19 +110,19 @@ void av7110_reset_arm(struct av7110 *av7110) saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, (MASK_19 | MASK_03)); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); - dvb_delay(30); /* the firmware needs some time to initialize */ + msleep(30); /* the firmware needs some time to initialize */ ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_ready = 1; - printk("av7110: ARM RESET\n"); + dprintk(1, "reset ARM\n"); } @@ -122,7 +130,7 @@ static int waitdebi(struct av7110 *av7110, int adr, int state) { int k; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); for (k = 0; k < 100; k++) { if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state) @@ -138,7 +146,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) int blocks, rest; u32 base, bootblock = BOOT_BLOCK; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); blocks = len / BOOT_MAX_SIZE; rest = len % BOOT_MAX_SIZE; @@ -147,7 +155,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) for (i = 0; i < blocks; i++) { if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) return -1; - DEB_D(("Writing DRAM block %d\n", i)); + dprintk(4, "writing DRAM block %d\n", i); mwdebi(av7110, DEBISWAB, bootblock, ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE); bootblock ^= 0x1400; @@ -210,13 +218,13 @@ int av7110_bootarm(struct av7110 *av7110) u32 ret; int i; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ - IER_DISABLE(av7110->dev, MASK_03 | MASK_19); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); + SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); /* enable DEBI */ saa7146_write(av7110->dev, MC1, 0x08800880); @@ -226,17 +234,17 @@ int av7110_bootarm(struct av7110 *av7110) /* test DEBI */ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) { - printk(KERN_ERR "dvb: debi test in av7110_bootarm() failed: " - "%08x != %08x (check your BIOS hotplug settings)\n", + printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: " + "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n", ret, 0x10325476); return -1; } for (i = 0; i < 8192; i += 4) iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4); - DEB_D(("av7110_bootarm: debi test OK\n")); + dprintk(2, "debi test OK\n"); /* boot */ - DEB_D(("av7110_bootarm: load boot code\n")); + dprintk(1, "load boot code\n"); saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO); //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); @@ -244,36 +252,36 @@ int av7110_bootarm(struct av7110 *av7110) mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); - if (saa7146_wait_for_debi_done(av7110->dev)) { - printk(KERN_ERR "dvb: av7110_bootarm(): " + if (saa7146_wait_for_debi_done(av7110->dev, 1)) { + printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " "saa7146_wait_for_debi_done() timed out\n"); return -1; } saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); mdelay(1); - DEB_D(("av7110_bootarm: load dram code\n")); + dprintk(1, "load dram code\n"); if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) return -1; saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); mdelay(1); - DEB_D(("av7110_bootarm: load dpram code\n")); + dprintk(1, "load dpram code\n"); mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram); - if (saa7146_wait_for_debi_done(av7110->dev)) { - printk(KERN_ERR "dvb: av7110_bootarm(): " + if (saa7146_wait_for_debi_done(av7110->dev, 1)) { + printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); return -1; } saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); - dvb_delay(30); /* the firmware needs some time to initialize */ + msleep(30); /* the firmware needs some time to initialize */ //ARM_ClearIrq(av7110); ARM_ResetMailBox(av7110); - saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); - IER_ENABLE(av7110->dev, MASK_03); + SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03); + SAA7146_IER_ENABLE(av7110->dev, MASK_03); av7110->arm_errors = 0; av7110->arm_ready = 1; @@ -285,49 +293,113 @@ int av7110_bootarm(struct av7110 *av7110) * DEBI command polling ****************************************************************************/ +int av7110_wait_msgstate(struct av7110 *av7110, u16 flags) +{ + unsigned long start; + u32 stat; + + if (FW_VERSION(av7110->arm_app) <= 0x261c) { + /* not supported by old firmware */ + msleep(50); + return 0; + } + + /* new firmware */ + start = jiffies; + for (;;) { + if (down_interruptible(&av7110->dcomlock)) + return -ERESTARTSYS; + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + up(&av7110->dcomlock); + if ((stat & flags) == 0) { + break; + } + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n", + __FUNCTION__, stat & flags); + return -1; + } + msleep(1); + } + return 0; +} + int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) { int i; unsigned long start; -#ifdef COM_DEBUG + char *type = NULL; + u16 flags[2] = {0, 0}; u32 stat; -#endif -// DEB_EE(("av7110: %p\n", av7110)); +// dprintk(4, "%p\n", av7110); if (!av7110->arm_ready) { - DEB_D(("arm not ready.\n")); + dprintk(1, "arm not ready.\n"); return -1; } start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_FREE)) { - printk(KERN_ERR "%s: timeout waiting for COMMAND idle\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__); return -1; } } + wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2); + #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { - printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); return -1; } } #endif + switch ((buf[0] >> 8) & 0xff) { + case COMTYPE_PIDFILTER: + case COMTYPE_ENCODER: + case COMTYPE_REC_PLAY: + case COMTYPE_MPEGDECODER: + type = "MSG"; + flags[0] = GPMQOver; + flags[1] = GPMQFull; + break; + case COMTYPE_OSD: + type = "OSD"; + flags[0] = OSDQOver; + flags[1] = OSDQFull; + break; + default: + break; + } + + if (type != NULL) { + /* non-immediate COMMAND type */ start = jiffies; - while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) { - dvb_delay(1); - if (time_after(jiffies, start + ARM_WAIT_OSD)) { - printk(KERN_ERR "%s: timeout waiting for !OSDQFull\n", __FUNCTION__); + for (;;) { + stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); + if (stat & flags[0]) { + printk(KERN_ERR "%s: %s QUEUE overflow\n", + __FUNCTION__, type); + return -1; + } + if ((stat & flags[1]) == 0) + break; + if (time_after(jiffies, start + ARM_WAIT_FREE)) { + printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", + __FUNCTION__, type); return -1; } + msleep(1); + } } + for (i = 2; i < length; i++) wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2); @@ -338,12 +410,14 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2); + wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2); + #ifdef COM_DEBUG start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_FREE)) { - printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n", __FUNCTION__); return -1; } @@ -351,11 +425,11 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2); if (stat & GPMQOver) { - printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__); return -1; } else if (stat & OSDQOver) { - printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__); + printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__); return -1; } #endif @@ -367,10 +441,10 @@ int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) { int ret; -// DEB_EE(("av7110: %p\n", av7110)); +// dprintk(4, "%p\n", av7110); if (!av7110->arm_ready) { - DEB_D(("arm not ready.\n")); + dprintk(1, "arm not ready.\n"); return -1; } if (down_interruptible(&av7110->dcomlock)) @@ -379,7 +453,7 @@ int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) ret = __av7110_send_fw_cmd(av7110, buf, length); up(&av7110->dcomlock); if (ret) - printk("av7110_send_fw_cmd error\n"); + printk("dvb-ttpci: %s(): av7110_send_fw_cmd error\n", __FUNCTION__); return ret; } @@ -389,7 +463,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...) u16 buf[num + 2]; int i, ret; -// DEB_EE(("av7110: %p\n",av7110)); +// dprintk(4, "%p\n", av7110); buf[0] = ((type << 8) | com); buf[1] = num; @@ -403,7 +477,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...) ret = av7110_send_fw_cmd(av7110, buf, num + 2); if (ret) - printk("av7110_fw_cmd error\n"); + printk("dvb-ttpci: av7110_fw_cmd error\n"); return ret; } @@ -413,7 +487,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len) u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); for(i = 0; i < len && i < 32; i++) { @@ -425,7 +499,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len) ret = av7110_send_fw_cmd(av7110, cmd, 18); if (ret) - printk("av7110_send_ci_cmd error\n"); + printk("dvb-ttpci: av7110_send_ci_cmd error\n"); return ret; } @@ -439,10 +513,10 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, u32 stat; #endif - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (!av7110->arm_ready) { - DEB_D(("arm not ready.\n")); + dprintk(1, "arm not ready.\n"); return -1; } @@ -451,17 +525,17 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) { up(&av7110->dcomlock); - printk("av7110_fw_request error\n"); + printk("dvb-ttpci: av7110_fw_request error\n"); return err; } start = jiffies; while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) { #ifdef _NOHANDSHAKE - dvb_delay(1); + msleep(1); #endif if (time_after(jiffies, start + ARM_WAIT_FREE)) { - printk("%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); + printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); up(&av7110->dcomlock); return -1; } @@ -470,7 +544,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); @@ -505,7 +579,7 @@ int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length) int ret; ret = av7110_fw_request(av7110, &tag, 0, buf, length); if (ret) - printk("av7110_fw_query error\n"); + printk("dvb-ttpci: av7110_fw_query error\n"); return ret; } @@ -520,10 +594,10 @@ int av7110_firmversion(struct av7110 *av7110) u16 buf[20]; u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion); - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (av7110_fw_query(av7110, tag, buf, 16)) { - printk("DVB: AV7110-%d: ERROR: Failed to boot firmware\n", + printk("dvb-ttpci: failed to boot firmware @ card %d\n", av7110->dvb_adapter->num); return -EIO; } @@ -534,17 +608,17 @@ int av7110_firmversion(struct av7110 *av7110) av7110->arm_app = (buf[6] << 16) + buf[7]; av7110->avtype = (buf[8] << 16) + buf[9]; - printk("DVB: AV711%d(%d) - firm %08x, rtsl %08x, vid %08x, app %08x\n", - av7110->avtype, av7110->dvb_adapter->num, av7110->arm_fw, + printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n", + av7110->dvb_adapter->num, av7110->arm_fw, av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); /* print firmware capabilities */ if (FW_CI_LL_SUPPORT(av7110->arm_app)) - printk("DVB: AV711%d(%d) - firmware supports CI link layer interface\n", - av7110->avtype, av7110->dvb_adapter->num); + printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n", + av7110->dvb_adapter->num); else - printk("DVB: AV711%d(%d) - no firmware support for CI link layer interface\n", - av7110->avtype, av7110->dvb_adapter->num); + printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n", + av7110->dvb_adapter->num); return 0; } @@ -556,7 +630,7 @@ int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long bu u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if (len > 10) len = 10; @@ -573,7 +647,7 @@ int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long bu buf[i + 4] = msg[i]; if (av7110_send_fw_cmd(av7110, buf, 18)) - printk("av7110_diseqc_send error\n"); + printk("dvb-ttpci: av7110_diseqc_send error\n"); return 0; } @@ -630,9 +704,9 @@ static int FlushText(struct av7110 *av7110) return -ERESTARTSYS; start = jiffies; while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_OSD)) { - printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", + printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); up(&av7110->dcomlock); return -1; @@ -654,9 +728,9 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) start = jiffies; while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_OSD)) { - printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", + printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); up(&av7110->dcomlock); return -1; @@ -665,9 +739,9 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) #ifndef _NOHANDSHAKE start = jiffies; while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) { - dvb_delay(1); + msleep(1); if (time_after(jiffies, start + ARM_WAIT_SHAKE)) { - printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", + printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); return -1; @@ -682,7 +756,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) ret = __av7110_send_fw_cmd(av7110, cbuf, 5); up(&av7110->dcomlock); if (ret) - printk("WriteText error\n"); + printk("dvb-ttpci: WriteText error\n"); return ret; } @@ -721,7 +795,7 @@ static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr) } static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, - enum av7110_window_display_type disptype, + osd_raw_window_t disptype, u16 width, u16 height) { return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4, @@ -732,8 +806,8 @@ static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, static enum av7110_osd_palette_type bpp2pal[8] = { Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit }; -static enum av7110_window_display_type bpp2bit[8] = { - BITMAP1, BITMAP2, 0, BITMAP4, 0, 0, 0, BITMAP8 +static osd_raw_window_t bpp2bit[8] = { + OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8 }; static inline int LoadBitmap(struct av7110 *av7110, u16 format, @@ -743,32 +817,26 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, int i; int d, delta; u8 c; - DECLARE_WAITQUEUE(wait, current); + int ret; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); - if (av7110->bmp_state == BMP_LOADING) { - add_wait_queue(&av7110->bmpq, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (av7110->bmp_state != BMP_LOADING - || signal_pending(current)) - break; - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&av7110->bmpq, &wait); - } - if (av7110->bmp_state == BMP_LOADING) + ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ); + if (ret == -ERESTARTSYS || ret == 0) { + printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__); + av7110->bmp_state = BMP_NONE; return -1; + } + BUG_ON (av7110->bmp_state == BMP_LOADING); + av7110->bmp_state = BMP_LOADING; - if (format == BITMAP8) { + if (format == OSD_BITMAP8) { bpp=8; delta = 1; - } else if (format == BITMAP4) { + } else if (format == OSD_BITMAP4) { bpp=4; delta = 2; - } else if (format == BITMAP2) { + } else if (format == OSD_BITMAP2) { bpp=2; delta = 4; - } else if (format == BITMAP1) { + } else if (format == OSD_BITMAP1) { bpp=1; delta = 8; } else { av7110->bmp_state = BMP_NONE; @@ -786,7 +854,7 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, return -1; } } - if (format != BITMAP8) { + if (format != OSD_BITMAP8) { for (i = 0; i < dx * dy / delta; i++) { c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1]; for (d = delta - 2; d >= 0; d--) { @@ -802,32 +870,27 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format, static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans) { - DECLARE_WAITQUEUE(wait, current); + int ret; + + dprintk(4, "%p\n", av7110); - DEB_EE(("av7110: %p\n", av7110)); + BUG_ON (av7110->bmp_state == BMP_NONE); - if (av7110->bmp_state == BMP_NONE) + ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ); + if (ret == -ERESTARTSYS || ret == 0) { + printk("dvb-ttpci: warning: timeout waiting in %s()\n", __FUNCTION__); + av7110->bmp_state = BMP_NONE; return -1; - if (av7110->bmp_state == BMP_LOADING) { - add_wait_queue(&av7110->bmpq, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (av7110->bmp_state != BMP_LOADING - || signal_pending(current)) - break; - schedule(); } - set_current_state(TASK_RUNNING); - remove_wait_queue(&av7110->bmpq, &wait); - } - if (av7110->bmp_state == BMP_LOADED) + + BUG_ON (av7110->bmp_state != BMP_LOADED); + return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans); - return -1; } static inline int ReleaseBitmap(struct av7110 *av7110) { - DEB_EE(("av7110: %p\n",av7110)); + dprintk(4, "%p\n", av7110); if (av7110->bmp_state != BMP_LOADED) return -1; @@ -865,18 +928,22 @@ static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 bl color, ((blend >> 4) & 0x0f)); } -static int OSDSetPalette(struct av7110 *av7110, u32 *colors, u8 first, u8 last) +static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last) { int i; int length = last - first + 1; if (length * 4 > DATA_BUFF3_SIZE) - return -1; + return -EINVAL; for (i = 0; i < length; i++) { - u32 blend = (colors[i] & 0xF0000000) >> 4; - u32 yuv = blend ? RGB2YUV(colors[i] & 0xFF, (colors[i] >> 8) & 0xFF, - (colors[i] >> 16) & 0xFF) | blend : 0; + u32 color, blend, yuv; + + if (get_user(color, colors + i)) + return -EFAULT; + blend = (color & 0xF0000000) >> 4; + yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF, + (color >> 16) & 0xFF) | blend : 0; yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4); } @@ -922,10 +989,19 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) { + int ret; + + ret = down_interruptible(&av7110->osd_sema); + if (ret) + return -ERESTARTSYS; + + /* stupid, but OSD functions don't provide a return code anyway */ + ret = 0; + switch (dc->cmd) { case OSD_Close: DestroyOSDWindow(av7110, av7110->osdwin); - return 0; + goto out; case OSD_Open: av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7; CreateOSDWindow(av7110, av7110->osdwin, @@ -935,90 +1011,84 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); SetColorBlend(av7110, av7110->osdwin); } - return 0; + goto out; case OSD_Show: MoveWindowRel(av7110, av7110->osdwin, 0, 0); - return 0; + goto out; case OSD_Hide: HideWindow(av7110, av7110->osdwin); - return 0; + goto out; case OSD_Clear: DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0); - return 0; + goto out; case OSD_Fill: DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color); - return 0; + goto out; case OSD_SetColor: OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1); - return 0; + goto out; case OSD_SetPalette: { - int len = dc->x0-dc->color+1; - void *buf; - if (len <= 0) - return 0; - - buf = kmalloc(len * 4, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, dc->data, len * 4)) { - kfree(buf); - return -EFAULT; + if (FW_VERSION(av7110->arm_app) >= 0x2618) { + ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0); + goto out; + } else { + int i, len = dc->x0-dc->color+1; + u8 __user *colors = (u8 *)dc->data; + u8 r, g, b, blend; + + for (i = 0; iarm_app) >= 0x2618) - OSDSetPalette(av7110, buf, dc->color, dc->x0); - else { - int i; - u8 *colors = buf; - - for (i = 0; icolor + i, - colors[i * 4], colors[i * 4 + 1], - colors[i * 4 + 2], colors[i * 4 + 3]); + OSDSetColor(av7110, dc->color + i, r, g, b, blend); } - kfree(buf); - return 0; + } + ret = 0; + goto out; } case OSD_SetTrans: - return 0; + goto out; case OSD_SetPixel: DrawLine(av7110, av7110->osdwin, dc->x0, dc->y0, 0, 0, dc->color); - return 0; + goto out; case OSD_GetPixel: - return 0; - + goto out; case OSD_SetRow: dc->y1 = dc->y0; /* fall through */ case OSD_SetBlock: OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); - return 0; - + goto out; case OSD_FillRow: DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1-dc->x0+1, dc->y1, dc->color); - return 0; + goto out; case OSD_FillBlock: DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color); - return 0; + goto out; case OSD_Line: DrawLine(av7110, av7110->osdwin, dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color); - return 0; + goto out; case OSD_Query: - return 0; + goto out; case OSD_Test: - return 0; + goto out; case OSD_Text: { char textbuf[240]; - if (strncpy_from_user(textbuf, dc->data, 240) < 0) - return -EFAULT; + if (strncpy_from_user(textbuf, dc->data, 240) < 0) { + ret = -EFAULT; + goto out; + } textbuf[239] = 0; if (dc->x1 > 3) dc->x1 = 3; @@ -1026,16 +1096,55 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) (u16) (dc->color & 0xffff), (u16) (dc->color >> 16)); FlushText(av7110); WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf); - return 0; + goto out; } case OSD_SetWindow: - if (dc->x0 < 1 || dc->x0 > 7) - return -EINVAL; + if (dc->x0 < 1 || dc->x0 > 7) { + ret = -EINVAL; + goto out; + } av7110->osdwin = dc->x0; - return 0; + goto out; case OSD_MoveWindow: MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); SetColorBlend(av7110, av7110->osdwin); + goto out; + case OSD_OpenRaw: + if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) { + ret = -EINVAL; + goto out; + } + if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) { + av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1; + } + else { + av7110->osdbpp[av7110->osdwin] = 0; + } + CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color, + dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1); + if (!dc->data) { + MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0); + SetColorBlend(av7110, av7110->osdwin); + } + goto out; + default: + ret = -EINVAL; + goto out; + } + +out: + up(&av7110->osd_sema); + return ret; +} + +int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap) +{ + switch (cap->cmd) { + case OSD_CAP_MEMSIZE: + if (FW_4M_SDRAM(av7110->arm_app)) + cap->val = 1000000; + else + cap->val = 92000; return 0; default: return -EINVAL; diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h index 826ea877b..bf901c624 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/dvb/ttpci/av7110_hw.h @@ -39,29 +39,6 @@ enum av7110_osd_palette_type Pal8Bit = 256 /* 256 colors for 16 bit palette */ }; -enum av7110_window_display_type { - BITMAP1, /* 1 bit bitmap */ - BITMAP2, /* 2 bit bitmap */ - BITMAP4, /* 4 bit bitmap */ - BITMAP8, /* 8 bit bitmap */ - BITMAP1HR, /* 1 Bit bitmap half resolution */ - BITMAP2HR, /* 2 bit bitmap half resolution */ - BITMAP4HR, /* 4 bit bitmap half resolution */ - BITMAP8HR, /* 8 bit bitmap half resolution */ - YCRCB422, /* 4:2:2 YCRCB Graphic Display */ - YCRCB444, /* 4:4:4 YCRCB Graphic Display */ - YCRCB444HR, /* 4:4:4 YCRCB graphic half resolution */ - VIDEOTSIZE, /* True Size Normal MPEG Video Display */ - VIDEOHSIZE, /* MPEG Video Display Half Resolution */ - VIDEOQSIZE, /* MPEG Video Display Quarter Resolution */ - VIDEODSIZE, /* MPEG Video Display Double Resolution */ - VIDEOTHSIZE, /* True Size MPEG Video Display Half Resolution */ - VIDEOTQSIZE, /* True Size MPEG Video Display Quarter Resolution*/ - VIDEOTDSIZE, /* True Size MPEG Video Display Double Resolution */ - VIDEONSIZE, /* Full Size MPEG Video Display */ - CURSOR /* Cursor */ -}; - /* switch defines */ #define SB_GPIO 3 #define SB_OFF SAA7146_GPIO_OUTLO /* SlowBlank off (TV-Mode) */ @@ -88,6 +65,9 @@ enum av7110_video_output_mode #define HPQOver 0x0008 #define OSDQFull 0x0010 /* OSD Queue Full */ #define OSDQOver 0x0020 +#define GPMQBusy 0x0040 /* Queue not empty, FW >= 261d */ +#define HPQBusy 0x0080 +#define OSDQBusy 0x0100 /* hw section filter flags */ #define SECTION_EIT 0x01 @@ -388,8 +368,10 @@ extern void av7110_reset_arm(struct av7110 *av7110); extern int av7110_bootarm(struct av7110 *av7110); extern int av7110_firmversion(struct av7110 *av7110); #define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000) +#define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000) #define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) +extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags); extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...); extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length); @@ -495,7 +477,7 @@ static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg) static int inline audcom(struct av7110 *av7110, u32 com) { - return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 4, + return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 2, (com>>16), (com&0xffff)); } @@ -510,6 +492,7 @@ extern int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned #ifdef CONFIG_DVB_AV7110_OSD extern int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc); +extern int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap); #endif /* CONFIG_DVB_AV7110_OSD */ diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 22039beb4..eaf3cb2c9 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -1,23 +1,16 @@ #include #include #include +#include #include #include #include #include "av7110.h" -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif - - #define UP_TIMEOUT (HZ/4) -static int av7110_ir_debug = 0; - -#define dprintk(x...) do { if (av7110_ir_debug) printk (x); } while (0) - +/* enable ir debugging by or'ing av7110_debug with 16 */ static struct input_dev input_dev; @@ -80,7 +73,7 @@ static void av7110_emit_key (u32 ircom) keycode = key_map[data]; - dprintk ("#########%08x######### addr %i data 0x%02x (keycode %i)\n", + dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n", ircom, addr, data, keycode); /* check device address (if selected) */ @@ -205,6 +198,7 @@ int __init av7110_ir_init (void) void __exit av7110_ir_exit (void) { + del_timer_sync(&keyup_timer); remove_proc_entry ("av7110_ir", NULL); av7110_unregister_irc_handler (av7110_emit_key); input_unregister_device(&input_dev); @@ -213,6 +207,3 @@ void __exit av7110_ir_exit (void) //MODULE_AUTHOR("Holger Waechtler "); //MODULE_LICENSE("GPL"); -MODULE_PARM(av7110_ir_debug,"i"); -MODULE_PARM_DESC(av7110_ir_debug, "enable AV7110 IR receiver debug messages"); - diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index fef348e13..822ccda93 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -35,25 +35,18 @@ #include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - -#include "dvb_i2c.h" #include "av7110.h" #include "av7110_hw.h" #include "av7110_av.h" -#include "dvb_functions.h" - int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val) { u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff }; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg }; - if (i2c->xfer(i2c, &msgs, 1) != 1) { - printk("av7110(%d): %s(%u = %u) failed\n", - av7110->dvb_adapter->num, __FUNCTION__, reg, val); + if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) { + dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n", + av7110->dvb_adapter->num, reg, val); return -EIO; } return 0; @@ -63,15 +56,14 @@ int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val) { u8 msg1[3] = { dev, reg >> 8, reg & 0xff }; u8 msg2[2]; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; struct i2c_msg msgs[2] = { { .flags = 0, .addr = 0x40, .len = 3, .buf = msg1 }, { .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 } }; - if (i2c->xfer(i2c, msgs, 2) != 2) { - printk("av7110(%d): %s(%u) failed\n", - av7110->dvb_adapter->num, __FUNCTION__, reg); + if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) { + dprintk(1, "dvb-ttpci: failed @ card %d, %u\n", + av7110->dvb_adapter->num, reg); return -EIO; } *val = (msg2[0] << 8) | msg2[1]; @@ -100,43 +92,47 @@ static struct v4l2_input inputs[2] = { } }; -/* for Siemens DVB-C analog module: (taken from ves1820.c) */ -static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data) +static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) { - u8 addr = 0x09; u8 buf[] = { 0x00, reg, data }; struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; - DEB_EE(("av7710: dev: %p\n", dev)); + dprintk(4, "dev: %p\n", dev); + + if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) + return -1; + return 0; +} + +static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data) +{ + u8 buf [] = { reg, data }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 }; if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) return -1; return 0; } + static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) { struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; - DEB_EE(("av7710: dev: %p\n", dev)); + dprintk(4, "dev: %p\n", dev); if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) return -1; return 0; } - -/** - * set up the downconverter frequency divisor for a - * reference clock comparision frequency of 62.5 kHz. - */ -static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq) +static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq) { u32 div; u8 config; u8 buf[4]; - DEB_EE(("av7710: freq: 0x%08x\n", freq)); + dprintk(4, "freq: 0x%08x\n", freq); /* magic number: 614. tuning with the frequency given by v4l2 is always off by 614*62.5 = 38375 kHz...*/ @@ -159,6 +155,34 @@ static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq) return tuner_write(dev, 0x61, buf); } +static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq) +{ + u32 div; + u8 data[4]; + + div = (freq + 38900000 + 31250) / 62500; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0xce; + + if (freq < 45000000) + return -EINVAL; + else if (freq < 137000000) + data[3] = 0x01; + else if (freq < 403000000) + data[3] = 0x02; + else if (freq < 860000000) + data[3] = 0x04; + else + return -EINVAL; + + stv0297_writereg(dev, 0x1C, 0x87, 0x78); + stv0297_writereg(dev, 0x1C, 0x86, 0xc8); + return tuner_write(dev, 0x63, data); +} + + static struct saa7146_standard analog_standard[]; static struct saa7146_standard dvb_standard[]; @@ -170,60 +194,71 @@ static struct v4l2_audio msp3400_v4l2_audio = { .capability = V4L2_AUDCAP_STEREO }; -int av7110_dvb_c_switch(struct saa7146_fh *fh) +static int av7110_dvb_c_switch(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; struct av7110 *av7110 = (struct av7110*)dev->ext_priv; u16 adswitch; - u8 band = 0; int source, sync, err; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(4, "%p\n", av7110); if ((vv->video_status & STATUS_OVERLAY) != 0) { vv->ov_suspend = vv->video_fh; err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ if (err != 0) { - DEB_D(("warning: suspending video failed\n")); + dprintk(2, "suspending video failed\n"); vv->ov_suspend = NULL; } } if (0 != av7110->current_input) { adswitch = 1; - band = 0x60; /* analog band */ source = SAA7146_HPS_SOURCE_PORT_B; sync = SAA7146_HPS_SYNC_PORT_B; memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2); - printk("av7110: switching to analog TV\n"); + dprintk(1, "switching to analog TV\n"); msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x60)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF) + } } else { adswitch = 0; - band = 0x20; /* digital band */ source = SAA7146_HPS_SOURCE_PORT_A; sync = SAA7146_HPS_SYNC_PORT_A; memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2); - printk("av7110: switching DVB mode\n"); + dprintk(1, "switching DVB mode\n"); msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume + + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } } /* hmm, this does not do anything!? */ if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch)) - printk("ADSwitch error\n"); + dprintk(1, "ADSwitch error\n"); - if (ves1820_writereg(dev, 0x0f, band)) - printk("setting band in demodulator failed.\n"); saa7146_set_hps_source_and_sync(dev, source, sync); if (vv->ov_suspend != NULL) { @@ -234,11 +269,11 @@ int av7110_dvb_c_switch(struct saa7146_fh *fh) return 0; } -int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct av7110 *av7110 = (struct av7110*) dev->ext_priv; - DEB_EE(("saa7146_dev: %p\n", dev)); + dprintk(4, "saa7146_dev: %p\n", dev); switch (cmd) { case VIDIOC_G_TUNER: @@ -247,9 +282,9 @@ int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) u16 stereo_det; s8 stereo; - DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); + dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || t->index != 0) + if (!av7110->analog_tuner_flags || t->index != 0) return -EINVAL; memset(t, 0, sizeof(*t)); @@ -266,10 +301,10 @@ int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) // FIXME: standard / stereo detection is still broken msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det); -printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); + dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det); - printk("VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det); + dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det); stereo = (s8)(stereo_det >> 8); if (stereo > 0x10) { /* stereo */ @@ -290,29 +325,29 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { struct v4l2_tuner *t = arg; u16 fm_matrix, src; - DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index)); + dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; switch (t->audmode) { case V4L2_TUNER_MODE_STEREO: - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"); fm_matrix = 0x3001; // stereo src = 0x0020; break; case V4L2_TUNER_MODE_LANG1: - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); fm_matrix = 0x3000; // mono src = 0x0000; break; case V4L2_TUNER_MODE_LANG2: - DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"); fm_matrix = 0x3000; // mono src = 0x0010; break; default: /* case V4L2_TUNER_MODE_MONO: {*/ - DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); + dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n"); fm_matrix = 0x3000; // mono src = 0x0030; break; @@ -327,9 +362,9 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { struct v4l2_frequency *f = arg; - DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency)); + dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; memset(f, 0, sizeof(*f)); @@ -341,9 +376,9 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { struct v4l2_frequency *f = arg; - DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency)); + dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); - if (!av7110->has_analog_tuner || av7110->current_input != 1) + if (!av7110->analog_tuner_flags || av7110->current_input != 1) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) @@ -353,7 +388,11 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); /* tune in desired frequency */ - tuner_set_tv_freq(dev, f->frequency); + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + ves1820_set_tv_freq(dev, f->frequency); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + stv0297_set_tv_freq(dev, f->frequency); + } av7110->current_freq = f->frequency; msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection @@ -366,9 +405,9 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { struct v4l2_input *i = arg; - DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index)); + dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); - if (av7110->has_analog_tuner ) { + if (av7110->analog_tuner_flags) { if (i->index < 0 || i->index >= 2) return -EINVAL; } else { @@ -384,16 +423,16 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { int *input = (int *)arg; *input = av7110->current_input; - DEB_EE(("VIDIOC_G_INPUT: %d\n", *input)); + dprintk(2, "VIDIOC_G_INPUT: %d\n", *input); return 0; } case VIDIOC_S_INPUT: { int input = *(int *)arg; - DEB_EE(("VIDIOC_S_INPUT: %d\n", input)); + dprintk(2, "VIDIOC_S_INPUT: %d\n", input); - if (!av7110->has_analog_tuner ) + if (!av7110->analog_tuner_flags) return 0; if (input < 0 || input >= 2) @@ -407,7 +446,7 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); { struct v4l2_audio *a = arg; - DEB_EE(("VIDIOC_G_AUDIO: %d\n", a->index)); + dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index); if (a->index != 0) return -EINVAL; memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio)); @@ -416,7 +455,7 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); case VIDIOC_S_AUDIO: { struct v4l2_audio *a = arg; - DEB_EE(("VIDIOC_S_AUDIO: %d\n", a->index)); + dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); break; } default: @@ -431,7 +470,7 @@ printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); * INITIALIZATION ****************************************************************************/ -struct saa7146_extension_ioctls ioctls[] = { +static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, @@ -514,13 +553,13 @@ int av7110_init_analog_module(struct av7110 *av7110) || i2c_writereg(av7110, 0x80, 0x0, 0) != 1) return -ENODEV; - printk("av7110(%d): DVB-C analog module detected, initializing MSP3400\n", + printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n", av7110->dvb_adapter->num); av7110->adac_type = DVB_ADAC_MSP; - dvb_delay(100); // the probing above resets the msp... + msleep(100); // the probing above resets the msp... msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1); msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2); - printk("av7110(%d): MSP3400 version 0x%04x 0x%04x\n", + dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n", av7110->dvb_adapter->num, version1, version2); msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00); msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone @@ -535,12 +574,31 @@ int av7110_init_analog_module(struct av7110 *av7110) INFO(("saa7113 not accessible.\n")); } else { u8 *i = saa7113_init_regs; - av7110->has_analog_tuner = 1; + + if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) { + /* Fujitsu/Siemens DVB-Cable */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820; + } else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) { + /* Hauppauge/TT DVB-C premium */ + av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297; + } + + /* setup for DVB by default */ + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { + if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20)) + dprintk(1, "setting band in demodulator failed.\n"); + } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) + } + /* init the saa7113 */ while (*i != 0xff) { if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) { - printk("av7110(%d): saa7113 initialization failed", - av7110->dvb_adapter->num); + dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter->num); break; } i += 2; @@ -587,7 +645,7 @@ int av7110_init_v4l(struct av7110 *av7110) /* special case DVB-C: these cards have an analog tuner plus need some special handling, so we have separate saa7146_ext_vv data for these... */ - if (av7110->has_analog_tuner) + if (av7110->analog_tuner_flags) ret = saa7146_vv_init(dev, &av7110_vv_data_c); else ret = saa7146_vv_init(dev, &av7110_vv_data_st); @@ -602,12 +660,12 @@ int av7110_init_v4l(struct av7110 *av7110) saa7146_vv_release(dev); return -ENODEV; } - if (av7110->has_analog_tuner) { + if (av7110->analog_tuner_flags) { if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); - } else - /* we use this to remember that this dvb-c card can do vbi */ - av7110->has_analog_tuner = 2; + } else { + av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; + } } return 0; } @@ -615,7 +673,7 @@ int av7110_init_v4l(struct av7110 *av7110) int av7110_exit_v4l(struct av7110 *av7110) { saa7146_unregister_device(&av7110->v4l_dev, av7110->dev); - if (2 == av7110->has_analog_tuner) + if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI) saa7146_unregister_device(&av7110->vbi_dev, av7110->dev); return 0; } @@ -692,7 +750,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = { .flags = 0, .stds = &standard[0], - .num_stds = sizeof(standard) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, .ioctls = &ioctls[0], @@ -706,7 +764,7 @@ static struct saa7146_ext_vv av7110_vv_data_c = { .flags = SAA7146_USE_PORT_B_FOR_VBI, .stds = &standard[0], - .num_stds = sizeof(standard) / sizeof(struct saa7146_standard), + .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, .ioctls = &ioctls[0], diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 6203be434..ae9260094 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -4,6 +4,9 @@ * * Compiled from various sources by Michael Hunold * + * CI interface support (c) 2004 Olivier Gournet & + * Andrew de Quincey + * * Copyright (C) 2002 Ralph Metzler * * Copyright (C) 1999-2002 Ralph Metzler @@ -30,24 +33,41 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ +#include "budget.h" +#include "stv0299.h" +#include "tda10021.h" +#include "tda1004x.h" #include +#include +#include +#include +#include +#include +#include -#include "budget.h" -#include "dvb_functions.h" +#include "dvb_ca_en50221.h" + +#define DEBICICAM 0x02420000 struct budget_av { struct budget budget; - struct video_device vd; + struct video_device *vd; int cur_input; int has_saa7113; + struct tasklet_struct ciintf_irq_tasklet; + int slot_status; + struct dvb_ca_en50221 ca; }; +int enable_ci = 0; + + /**************************************************************************** * INITIALIZATION ****************************************************************************/ -static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) +static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg) { u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; @@ -57,15 +77,17 @@ static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) msgs[1].flags = I2C_M_RD; msgs[0].addr = msgs[1].addr=id/2; mm1[0] = reg; - msgs[0].len = 1; msgs[1].len = 1; - msgs[0].buf = mm1; msgs[1].buf = mm2; + msgs[0].len = 1; + msgs[1].len = 1; + msgs[0].buf = mm1; + msgs[1].buf = mm2; - i2c->xfer(i2c, msgs, 2); + i2c_transfer(i2c, msgs, 2); return mm2[0]; } -static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len) +static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len) { u8 mm1[] = { reg }; struct i2c_msg msgs[2] = { @@ -73,13 +95,14 @@ static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len) { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len } }; - if (i2c->xfer(i2c, msgs, 2) != 2) + if (i2c_transfer(i2c, msgs, 2) != 2) return -EIO; + return 0; } -static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) +static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct i2c_msg msgs; @@ -88,7 +111,212 @@ static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) msgs.addr=id/2; msgs.len=2; msgs.buf=msg; - return i2c->xfer (i2c, &msgs, 1); + return i2c_transfer(i2c, &msgs, 1); +} + +static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); + result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + if (slot != 0) + return -EINVAL; + + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); + + if (result == -ETIMEDOUT) + budget_av->slot_status = 0; + return result; +} + +static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_reset\n"); + + /* reset the card */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); + msleep(100); + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + msleep(2000); /* horrendous I know, but its the only way to be absolutely sure without an IRQ line! */ + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + return 0; +} + +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_shutdown\n"); + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + budget_av->slot_status = 0; + return 0; +} + +static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + + if (slot != 0) + return -EINVAL; + + dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); + + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); + return 0; +} + +static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + struct saa7146_dev *saa = budget_av->budget.dev; + int cam = 0; + + if (slot != 0) + return -EINVAL; + + if (!budget_av->slot_status) { + saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); + udelay(1); + cam = saa7146_read(saa, PSR) & MASK_06; + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + + if (cam) + budget_av->slot_status = 1; + } else if (!open) { + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) + budget_av->slot_status = 0; + } + + if (budget_av->slot_status == 1) + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + + return 0; +} + +static int ciintf_init(struct budget_av *budget_av) +{ + struct saa7146_dev *saa = budget_av->budget.dev; + int result; + + memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); + + /* setup GPIOs */ + saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); + saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); + saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + + /* Reset the card */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); + msleep(50); + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + msleep(100); + + /* Enable DEBI pins */ + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); + + /* register CI interface */ + budget_av->ca.owner = THIS_MODULE; + budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem; + budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem; + budget_av->ca.read_cam_control = ciintf_read_cam_control; + budget_av->ca.write_cam_control = ciintf_write_cam_control; + budget_av->ca.slot_reset = ciintf_slot_reset; + budget_av->ca.slot_shutdown = ciintf_slot_shutdown; + budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_av->ca.poll_slot_status = ciintf_poll_slot_status; + budget_av->ca.data = budget_av; + if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter, + &budget_av->ca, 0, 1)) != 0) { + printk("budget_av: CI interface detected, but initialisation failed.\n"); + goto error; + } + // success! + printk("ciintf_init: CI interface initialised\n"); + budget_av->budget.ci_present = 1; + return 0; + +error: + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); + return result; +} + +static void ciintf_deinit(struct budget_av *budget_av) +{ + struct saa7146_dev *saa = budget_av->budget.dev; + + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT); + saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); + + /* release the CA device */ + dvb_ca_en50221_release(&budget_av->ca); + + /* disable DEBI pins */ + saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16)); } @@ -127,20 +355,19 @@ static int saa7113_init (struct budget_av *budget_av) struct budget *budget = &budget_av->budget; const u8 *data = saa7113_tab; - if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) { - DEB_D(("saa7113: not found on KNC card\n")); + if (i2c_writereg (&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) { + dprintk(1, "saa7113 not found on KNC card\n"); return -ENODEV; } - INFO(("saa7113: detected and initializing\n")); + dprintk(1, "saa7113 detected and initializing\n"); while (*data != 0xff) { - i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1)); + i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data+1)); data += 2; } - DEB_D(("saa7113: status=%02x\n", - i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f)); return 0; } @@ -154,11 +381,11 @@ static int saa7113_setinput (struct budget_av *budget_av, int input) return -ENODEV; if (input == 1) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80); } else if (input == 0) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0); + i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00); } else return -EINVAL; @@ -167,21 +394,405 @@ static int saa7113_setinput (struct budget_av *budget_av, int input) } +static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + u8 m1; + + aclk = 0xb5; + if (srate < 2000000) + bclk = 0x86; + else if (srate < 5000000) + bclk = 0x89; + else if (srate < 15000000) + bclk = 0x8f; + else if (srate < 45000000) + bclk = 0x95; + + m1 = 0x14; + if (srate < 4000000) + m1 = 0x10; + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + stv0299_writereg(fe, 0x0f, 0x80 | m1); + + return 0; +} + +static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv; + u32 div; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0x20; + + if (params->u.qpsk.symbol_rate < 4000000) + buf[3] |= 1; + + if (params->frequency < 1250000) + buf[3] |= 0; + else if (params->frequency < 1550000) + buf[3] |= 0x40; + else if (params->frequency < 2050000) + buf[3] |= 0x80; + else if (params->frequency < 2150000) + buf[3] |= 0xC0; + + if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static u8 typhoon_cinergy1200s_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x92, + 0xff, 0xff +}; + +static struct stv0299_config typhoon_config = { + .demod_address = 0x68, + .inittab = typhoon_cinergy1200s_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, + .pll_set = philips_su1278_ty_ci_pll_set, +}; + + +static struct stv0299_config cinergy_1200s_config = { + .demod_address = 0x68, + .inittab = typhoon_cinergy1200s_inittab, + .mclk = 88000000UL, + .invert = 0, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, + .pll_set = philips_su1278_ty_ci_pll_set, +}; + + +static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + +#define TUNER_MUL 62500 + + u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + buf[3] = (params->frequency < 174500000 ? 0xa1 : + params->frequency < 454000000 ? 0x92 : 0x34); + + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct tda10021_config philips_cu1216_config = { + .demod_address = 0x0c, + .pll_set = philips_cu1216_pll_set, +}; + + + + +static int philips_tu1216_pll_init(struct dvb_frontend *fe) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; + + // setup PLL configuration + if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + msleep(1); + + return 0; +} + +static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = + sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36166000; + if (tuner_frequency < 87000000) + return -EINVAL; + else if (tuner_frequency < 130000000) + cp = 3; + else if (tuner_frequency < 160000000) + cp = 5; + else if (tuner_frequency < 200000000) + cp = 6; + else if (tuner_frequency < 290000000) + cp = 3; + else if (tuner_frequency < 420000000) + cp = 5; + else if (tuner_frequency < 480000000) + cp = 6; + else if (tuner_frequency < 620000000) + cp = 3; + else if (tuner_frequency < 830000000) + cp = 5; + else if (tuner_frequency < 895000000) + cp = 7; + else + return -EINVAL; + + // determine band + if (params->frequency < 49000000) + return -EINVAL; + else if (params->frequency < 161000000) + band = 1; + else if (params->frequency < 444000000) + band = 2; + else if (params->frequency < 861000000) + band = 4; + else + return -EINVAL; + + // setup PLL filter + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; + + // setup tuner buffer + tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); + return 0; +} + +static int philips_tu1216_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char *name) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + + return request_firmware(fw, name, &budget->dev->pci->dev); +} + +struct tda1004x_config philips_tu1216_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 1, + .pll_init = philips_tu1216_pll_init, + .pll_set = philips_tu1216_pll_set, + .request_firmware = philips_tu1216_request_firmware, +}; + + + + +static u8 read_pwm(struct budget_av *budget_av) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + }; + + if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + + +static void frontend_init(struct budget_av *budget_av) +{ + switch (budget_av->budget.dev->pci->subsystem_device) { + case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059)) + budget_av->budget.dvb_frontend = + stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034)) + budget_av->budget.dvb_frontend = + tda10021_attach(&philips_cu1216_config, + &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt)) + budget_av->budget.dvb_frontend = + tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059)) + budget_av->budget.dvb_frontend = + stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend != NULL) { + break; + } + break; + + case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034)) + budget_av->budget.dvb_frontend = + tda10021_attach(&philips_cu1216_config, + &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (budget_av->budget.dvb_frontend) { + break; + } + break; + + case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt)) + budget_av->budget.dvb_frontend = + tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (budget_av->budget.dvb_frontend) { + break; + } + break; + } + + if (budget_av->budget.dvb_frontend == NULL) { + printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget_av->budget.dev->pci->vendor, + budget_av->budget.dev->pci->device, + budget_av->budget.dev->pci->subsystem_vendor, + budget_av->budget.dev->pci->subsystem_device); + } else { + if (dvb_register_frontend + (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { + printk("budget-av: Frontend registration failed!\n"); + if (budget_av->budget.dvb_frontend->ops->release) + budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); + budget_av->budget.dvb_frontend = NULL; + } + } +} + + +static void budget_av_irq(struct saa7146_dev *dev, u32 * isr) +{ + struct budget_av *budget_av = (struct budget_av *) dev->ext_priv; + + dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av); + + if (*isr & MASK_10) + ttpci_budget_irq10_handler(dev, isr); +} + static int budget_av_detach (struct saa7146_dev *dev) { struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; int err; - DEB_EE(("dev: %p\n",dev)); + dprintk(2, "dev: %p\n", dev); if ( 1 == budget_av->has_saa7113 ) { saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); - dvb_delay(200); + msleep(200); saa7146_unregister_device (&budget_av->vd, dev); } + if (budget_av->budget.ci_present) + ciintf_deinit(budget_av); + + if (budget_av->budget.dvb_frontend != NULL) + dvb_unregister_frontend(budget_av->budget.dvb_frontend); err = ttpci_budget_deinit (&budget_av->budget); kfree (budget_av); @@ -191,41 +802,35 @@ static int budget_av_detach (struct saa7146_dev *dev) static struct saa7146_ext_vv vv_data; -static int budget_av_attach (struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct budget_av *budget_av; - struct budget_info *bi = info->ext_priv; u8 *mac; int err; - DEB_EE(("dev: %p\n",dev)); - - if (bi->type != BUDGET_KNC1) { - return -ENODEV; - } + dprintk(2, "dev: %p\n", dev); if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL))) return -ENOMEM; memset(budget_av, 0, sizeof(struct budget_av)); - if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) { + budget_av->budget.ci_present = 0; + + dev->ext_priv = budget_av; + + if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) { kfree(budget_av); return err; } - dev->ext_priv = budget_av; - /* knc1 initialization */ saa7146_write(dev, DD1_STREAM_B, 0x04000000); saa7146_write(dev, DD1_INIT, 0x07000600); saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); - //test_knc_ci(av7110); - saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); - dvb_delay(500); + msleep(500); if ( 0 == saa7113_init(budget_av) ) { budget_av->has_saa7113 = 1; @@ -236,9 +841,7 @@ static int budget_av_attach (struct saa7146_dev* dev, return err; } - if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", - VFL_TYPE_GRABBER))) - { + if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { /* fixme: proper cleanup here */ ERR(("cannot register capture v4l2 device.\n")); return err; @@ -259,19 +862,24 @@ static int budget_av_attach (struct saa7146_dev* dev, saa7146_write(dev, PCI_BT_V1, 0x1c00101f); mac = budget_av->budget.dvb_adapter->proposed_mac; - if (i2c_readregs(budget_av->budget.i2c_bus, 0xa0, 0x30, mac, 6)) { + if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { printk("KNC1-%d: Could not read MAC from KNC1 card\n", budget_av->budget.dvb_adapter->num); memset(mac, 0, 6); - } - else + } else { printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", budget_av->budget.dvb_adapter->num, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return 0; } + budget_av->budget.dvb_adapter->priv = budget_av; + frontend_init(budget_av); + + if (enable_ci) + ciintf_init(budget_av); + return 0; +} #define KNC1_INPUTS 2 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { @@ -292,57 +900,47 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; -/* - struct saa7146_vv *vv = dev->vv_data; -*/ + switch(cmd) { - case VIDIOC_ENUMINPUT: - { + case VIDIOC_ENUMINPUT:{ struct v4l2_input *i = arg; - DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); + dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); if( i->index < 0 || i->index >= KNC1_INPUTS) { return -EINVAL; } memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; } - case VIDIOC_G_INPUT: - { + case VIDIOC_G_INPUT:{ int *input = (int *)arg; *input = budget_av->cur_input; - DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); + dprintk(1, "VIDIOC_G_INPUT %d.\n", *input); return 0; } - case VIDIOC_S_INPUT: - { + case VIDIOC_S_INPUT:{ int input = *(int *)arg; - DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + dprintk(1, "VIDIOC_S_INPUT %d.\n", input); return saa7113_setinput (budget_av, input); } default: -/* - DEB2(printk("does not handle this ioctl.\n")); -*/ return -ENOIOCTLCMD; } return 0; } static struct saa7146_standard standard[] = { - { - .name = "PAL", .id = V4L2_STD_PAL, + {.name = "PAL",.id = V4L2_STD_PAL, .v_offset = 0x17, .v_field = 288, .h_offset = 0x14, .h_pixels = 680, - .v_max_out = 576, .h_max_out = 768 - }, { - .name = "NTSC", .id = V4L2_STD_NTSC, + .v_max_out = 576,.h_max_out = 768 }, + + {.name = "NTSC",.id = V4L2_STD_NTSC, .v_offset = 0x16, .v_field = 240, .h_offset = 0x06, .h_pixels = 708, - .v_max_out = 480, .h_max_out = 640, - } + .v_max_out = 480,.h_max_out = 640, }, }; static struct saa7146_ext_vv vv_data = { @@ -355,15 +953,22 @@ static struct saa7146_ext_vv vv_data = { .ioctl = av_ioctl, }; - - static struct saa7146_extension budget_extension; - -MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); +MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S); +MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C); +MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); +MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S); +MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C); +MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T); static struct pci_device_id pci_tbl [] = { - MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), + MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56), + MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), + MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), + MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154), + MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156), + MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157), { .vendor = 0, } @@ -380,24 +985,16 @@ static struct saa7146_extension budget_extension = { .detach = budget_av_detach, .irq_mask = MASK_10, - .irq_func = ttpci_budget_irq10_handler, + .irq_func = budget_av_irq, }; - static int __init budget_av_init(void) { - DEB_EE((".\n")); - - if (saa7146_register_extension(&budget_extension)) - return -ENODEV; - - return 0; + return saa7146_register_extension(&budget_extension); } - static void __exit budget_av_exit(void) { - DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } @@ -407,5 +1004,6 @@ module_exit(budget_av_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); MODULE_DESCRIPTION("driver for the SAA7146 based so-called " - "budget PCI DVB w/ analog input (e.g. the KNC cards)"); - + "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)"); +module_param_named(enable_ci, enable_ci, int, 0644); +MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off)."); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 30c806599..898a8bf3b 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -38,12 +38,9 @@ #include #include -#include "dvb_functions.h" #include "dvb_ca_en50221.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif +#include "stv0299.h" +#include "tda1004x.h" #define DEBIADDR_IR 0x1234 #define DEBIADDR_CICONTROL 0x0000 @@ -69,70 +66,11 @@ struct budget_ci { struct input_dev input_dev; struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; - spinlock_t debilock; int slot_status; struct dvb_ca_en50221 ca; char ir_dev_name[50]; }; -static u32 budget_debiread (struct budget_ci* budget_ci, u32 config, int addr, int count) -{ - struct saa7146_dev *saa = budget_ci->budget.dev; - u32 result = 0; - - if (count > 4 || count <= 0) - return 0; - - spin_lock(&budget_ci->debilock); - - if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); - return 0; - } - - saa7146_write (saa, DEBI_COMMAND, - (count << 17) | 0x10000 | (addr & 0xffff)); - saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); - saa7146_write(saa, MC2, (2 << 16) | 2); - - saa7146_wait_for_debi_done(saa); - - result = saa7146_read(saa, 0x88); - result &= (0xffffffffUL >> ((4 - count) * 8)); - - spin_unlock(&budget_ci->debilock); - return result; -} - -static u8 budget_debiwrite (struct budget_ci* budget_ci, u32 config, int addr, int count, u32 value) -{ - struct saa7146_dev *saa = budget_ci->budget.dev; - - if (count > 4 || count <= 0) - return 0; - - spin_lock(&budget_ci->debilock); - - if (saa7146_wait_for_debi_done(saa) < 0) { - spin_unlock(&budget_ci->debilock); - return 0; - } - - saa7146_write (saa, DEBI_COMMAND, - (count << 17) | 0x00000 | (addr & 0xffff)); - saa7146_write(saa, DEBI_CONFIG, config); - saa7146_write(saa, DEBI_PAGE, 0); - saa7146_write(saa, DEBI_AD, value); - saa7146_write(saa, MC2, (2 << 16) | 2); - - saa7146_wait_for_debi_done(saa); - - spin_unlock(&budget_ci->debilock); - return 0; -} - - /* from reading the following remotes: Zenith Universal 7 / TV Mode 807 / VCR Mode 837 Hauppauge (from NOVA-CI-s box product) @@ -209,7 +147,8 @@ static void msp430_ir_interrupt (unsigned long data) { struct budget_ci *budget_ci = (struct budget_ci*) data; struct input_dev *dev = &budget_ci->input_dev; - unsigned int code = budget_debiread(budget_ci, DEBINOSWAP, DEBIADDR_IR, 2) >> 8; + unsigned int code = + ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; if (code & 0x40) { code &= 0x3f; @@ -224,8 +163,7 @@ static void msp430_ir_interrupt (unsigned long data) } if (!key_map[code]) { - printk ("DVB (%s): no key for %02x!\n", - __FUNCTION__, code); + printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code); return; } @@ -284,79 +222,98 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci) input_unregister_device(dev); } -static int ciintf_read_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address) { +static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1); + return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM, + DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0); } -static int ciintf_write_attribute_mem(struct dvb_ca_en50221* ca, int slot, int address, u8 value) { +static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_ATTR | (address & 0xfff), 1, value); + return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM, + DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0); } -static int ciintf_read_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address) { +static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiread(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1); + return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM, + DEBIADDR_IO | (address & 3), 1, 1, 0); } -static int ciintf_write_cam_control(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value) { +static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; - return budget_debiwrite(budget_ci, DEBICICAM, DEBIADDR_IO | (address & 3), 1, value); + return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM, + DEBIADDR_IO | (address & 3), 1, value, 1, 0); } -static int ciintf_slot_reset(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; // trigger on RISING edge during reset so we know when READY is re-asserted saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); budget_ci->slot_status = SLOTSTATUS_RESET; - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); - dvb_delay(1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); + msleep(1); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); return 0; } -static int ciintf_slot_shutdown(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; - if (slot != 0) return -EINVAL; + if (slot != 0) + return -EINVAL; saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); return 0; } -static int ciintf_slot_ts_enable(struct dvb_ca_en50221* ca, int slot) { +static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) +{ struct budget_ci* budget_ci = (struct budget_ci*) ca->data; struct saa7146_dev *saa = budget_ci->budget.dev; int tmp; - if (slot != 0) return -EINVAL; - + if (slot != 0) + return -EINVAL; saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO); - tmp = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, tmp | CICONTROL_ENABLETS); + tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + tmp | CICONTROL_ENABLETS, 1, 0); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); return 0; @@ -370,20 +327,21 @@ static void ciintf_interrupt (unsigned long data) unsigned int flags; // ensure we don't get spurious IRQs during initialisation - if (!budget_ci->budget.ci_present) return; + if (!budget_ci->budget.ci_present) + return; - flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + // read the CAM status + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + if (flags & CICONTROL_CAMDETECT) { - // always set the GPIO mode back to "normal", in case the card is - // yanked at an inopportune moment + // GPIO should be set to trigger on falling edge if a CAM is present saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - if (flags & CICONTROL_CAMDETECT) { - if (budget_ci->slot_status & SLOTSTATUS_NONE) { // CAM insertion IRQ budget_ci->slot_status = SLOTSTATUS_PRESENT; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } else if (budget_ci->slot_status & SLOTSTATUS_RESET) { // CAM ready (reset completed) @@ -395,9 +353,18 @@ static void ciintf_interrupt (unsigned long data) dvb_ca_en50221_frda_irq(&budget_ci->ca, 0); } } else { + + // trigger on rising edge if a CAM is not present - when a CAM is inserted, we + // only want to get the IRQ when it sets READY. If we trigger on the falling edge, + // the CAM might not actually be ready yet. + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + + // generate a CAM removal IRQ if we haven't already if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) { + // CAM removal IRQ budget_ci->slot_status = SLOTSTATUS_NONE; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, DVB_CA_EN50221_CAMCHANGE_REMOVED); + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } } } @@ -414,18 +381,18 @@ static int ciintf_init(struct budget_ci* budget_ci) saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there - if ((budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CIVERSION, 1) & 0xa0) != 0xa0) { + if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) { result = -ENODEV; goto error; } - // determine whether a CAM is present or not - flags = budget_debiread(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1); + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); budget_ci->slot_status = SLOTSTATUS_NONE; - if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; - + if (flags & CICONTROL_CAMDETECT) + budget_ci->slot_status = SLOTSTATUS_PRESENT; // register CI interface + budget_ci->ca.owner = THIS_MODULE; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem; budget_ci->ca.read_cam_control = ciintf_read_cam_control; @@ -438,17 +405,21 @@ static int ciintf_init(struct budget_ci* budget_ci) &budget_ci->ca, DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA, - 1)) != 0) { + DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) { printk("budget_ci: CI interface detected, but initialisation failed.\n"); goto error; } // Setup CI slot IRQ tasklet_init (&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + if (budget_ci->slot_status != SLOTSTATUS_NONE) { saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + } else { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); // success! printk("budget_ci: CI interface initialised\n"); @@ -456,7 +427,8 @@ static int ciintf_init(struct budget_ci* budget_ci) // forge a fake CI IRQ so the CAM state is setup correctly flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; - if (budget_ci->slot_status != SLOTSTATUS_NONE) flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) + flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); return 0; @@ -474,9 +446,10 @@ static void ciintf_deinit(struct budget_ci* budget_ci) saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ciintf_irq_tasklet); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, 0); - dvb_delay(1); - budget_debiwrite(budget_ci, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); + msleep(1); + ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, + CICONTROL_RESET, 1, 0); // disable TS data stream to CI interface saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT); @@ -492,7 +465,7 @@ static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) { struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; - DEB_EE(("dev: %p, budget_ci: %p\n", dev, budget_ci)); + dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci); if (*isr & MASK_06) tasklet_schedule (&budget_ci->msp430_irq_tasklet); @@ -505,9 +478,426 @@ static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) } +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + + + + +static u8 philips_su1278_tt_inittab[] = { + 0x01, 0x0f, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x5b, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x02, + 0x09, 0x00, + 0x0C, 0x01, + 0x0D, 0x81, + 0x0E, 0x44, + 0x0f, 0x14, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xda, + 0x13, 0x97, + 0x14, 0x95, + 0x15, 0xc9, + 0x16, 0x19, + 0x17, 0x8c, + 0x18, 0x59, + 0x19, 0xf8, + 0x1a, 0xfe, + 0x1c, 0x7f, + 0x1d, 0x00, + 0x1e, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x09, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x93, + 0xff, 0xff +}; + +static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + stv0299_writereg(fe, 0x0e, 0x44); + if (srate >= 10000000) { + stv0299_writereg(fe, 0x13, 0x97); + stv0299_writereg(fe, 0x14, 0x95); + stv0299_writereg(fe, 0x15, 0xc9); + stv0299_writereg(fe, 0x17, 0x8c); + stv0299_writereg(fe, 0x1a, 0xfe); + stv0299_writereg(fe, 0x1c, 0x7f); + stv0299_writereg(fe, 0x2d, 0x09); + } else { + stv0299_writereg(fe, 0x13, 0x99); + stv0299_writereg(fe, 0x14, 0x8d); + stv0299_writereg(fe, 0x15, 0xce); + stv0299_writereg(fe, 0x17, 0x43); + stv0299_writereg(fe, 0x1a, 0x1d); + stv0299_writereg(fe, 0x1c, 0x12); + stv0299_writereg(fe, 0x2d, 0x05); + } + stv0299_writereg(fe, 0x0e, 0x23); + stv0299_writereg(fe, 0x0f, 0x94); + stv0299_writereg(fe, 0x10, 0x39); + stv0299_writereg(fe, 0x15, 0xc9); + + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int philips_su1278_tt_pll_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u32 div; + u8 buf[4]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (500 - 1)) / 500; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2; + buf[3] = 0x20; + + if (params->u.qpsk.symbol_rate < 4000000) + buf[3] |= 1; + + if (params->frequency < 1250000) + buf[3] |= 0; + else if (params->frequency < 1550000) + buf[3] |= 0x40; + else if (params->frequency < 2050000) + buf[3] |= 0x80; + else if (params->frequency < 2150000) + buf[3] |= 0xC0; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static struct stv0299_config philips_su1278_tt_config = { + + .demod_address = 0x68, + .inittab = philips_su1278_tt_inittab, + .mclk = 64000000UL, + .invert = 0, + .enhanced_tuning = 1, + .skip_reinit = 1, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 50, + .set_symbol_rate = philips_su1278_tt_set_symbol_rate, + .pll_set = philips_su1278_tt_pll_set, +}; + + + +static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = td1316_init,.len = + sizeof(td1316_init) }; + + // setup PLL configuration + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + msleep(1); + + // disable the mc44BC374c (do not check for errors) + tuner_msg.addr = 0x65; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) { + i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1); + } + + return 0; +} + +static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36130000; + if (tuner_frequency < 87000000) + return -EINVAL; + else if (tuner_frequency < 130000000) + cp = 3; + else if (tuner_frequency < 160000000) + cp = 5; + else if (tuner_frequency < 200000000) + cp = 6; + else if (tuner_frequency < 290000000) + cp = 3; + else if (tuner_frequency < 420000000) + cp = 5; + else if (tuner_frequency < 480000000) + cp = 6; + else if (tuner_frequency < 620000000) + cp = 3; + else if (tuner_frequency < 830000000) + cp = 5; + else if (tuner_frequency < 895000000) + cp = 7; + else + return -EINVAL; + + // determine band + if (params->frequency < 49000000) + return -EINVAL; + else if (params->frequency < 159000000) + band = 1; + else if (params->frequency < 444000000) + band = 2; + else if (params->frequency < 861000000) + band = 4; + else + return -EINVAL; + + // setup PLL filter and TDA9889 + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x14); + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x80); + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_byte(fe, 0x0C, 0x14); + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; + + // setup tuner buffer + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); + return 0; +} + +static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe, + const struct firmware **fw, char *name) +{ + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; + + return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev); +} + +static struct tda1004x_config philips_tdm1316l_config = { + + .demod_address = 0x8, + .invert = 0, + .invert_oclk = 0, + .pll_init = philips_tdm1316l_pll_init, + .pll_set = philips_tdm1316l_pll_set, + .request_firmware = philips_tdm1316l_request_firmware, +}; + + + +static void frontend_init(struct budget_ci *budget_ci) +{ + switch (budget_ci->budget.dev->pci->subsystem_device) { + case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059)) + budget_ci->budget.dvb_frontend = + stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + + case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059)) + budget_ci->budget.dvb_frontend = + stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + + case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889) + budget_ci->budget.dvb_frontend = + tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + if (budget_ci->budget.dvb_frontend) { + break; + } + break; + } + + if (budget_ci->budget.dvb_frontend == NULL) { + printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget_ci->budget.dev->pci->vendor, + budget_ci->budget.dev->pci->device, + budget_ci->budget.dev->pci->subsystem_vendor, + budget_ci->budget.dev->pci->subsystem_device); + } else { + if (dvb_register_frontend + (budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { + printk("budget-ci: Frontend registration failed!\n"); + if (budget_ci->budget.dvb_frontend->ops->release) + budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); + budget_ci->budget.dvb_frontend = NULL; + } + } +} -static int budget_ci_attach (struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) { struct budget_ci *budget_ci; int err; @@ -515,25 +905,26 @@ static int budget_ci_attach (struct saa7146_dev* dev, if (!(budget_ci = kmalloc (sizeof(struct budget_ci), GFP_KERNEL))) return -ENOMEM; - DEB_EE(("budget_ci: %p\n", budget_ci)); + dprintk(2, "budget_ci: %p\n", budget_ci); - spin_lock_init(&budget_ci->debilock); budget_ci->budget.ci_present = 0; - if ((err = ttpci_budget_init (&budget_ci->budget, dev, info))) { + dev->ext_priv = budget_ci; + + if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) { kfree (budget_ci); return err; } - dev->ext_priv = budget_ci; - tasklet_init (&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); msp430_ir_init (budget_ci); - // UNCOMMENT TO TEST CI INTERFACE -// ciintf_init(budget_ci); + ciintf_init(budget_ci); + + budget_ci->budget.dvb_adapter->priv = budget_ci; + frontend_init(budget_ci); return 0; } @@ -546,8 +937,10 @@ static int budget_ci_detach (struct saa7146_dev* dev) struct saa7146_dev *saa = budget_ci->budget.dev; int err; - if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); - + if (budget_ci->budget.ci_present) + ciintf_deinit(budget_ci); + if (budget_ci->budget.dvb_frontend) + dvb_unregister_frontend(budget_ci->budget.dvb_frontend); err = ttpci_budget_deinit (&budget_ci->budget); tasklet_kill (&budget_ci->msp430_irq_tasklet); @@ -599,10 +992,8 @@ static int __init budget_ci_init(void) return saa7146_register_extension(&budget_extension); } - static void __exit budget_ci_exit(void) { - DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 15cf74422..bba2822e9 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -34,10 +34,15 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ +#include + #include "budget.h" #include "ttpci-eeprom.h" -int budget_debug = 0; +int budget_debug; + +module_param_named(debug, budget_debug, int, 0644); +MODULE_PARM_DESC(budget_debug, "Turn on/off budget debugging (default:off)."); /**************************************************************************** * TT budget / WinTV Nova @@ -45,13 +50,13 @@ int budget_debug = 0; static int stop_ts_capture(struct budget *budget) { - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); if (--budget->feeding) return budget->feeding; saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off - IER_DISABLE(budget->dev, MASK_10); + SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; } @@ -60,7 +65,7 @@ static int start_ts_capture (struct budget *budget) { struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); if (budget->feeding) return ++budget->feeding; @@ -69,8 +74,7 @@ static int start_ts_capture (struct budget *budget) memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); - saa7146_write(dev, PCI_BT_V1, 0x001c0000 | - (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); + saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); budget->tsf=0xff; budget->ttbp=0; @@ -120,7 +124,7 @@ static int start_ts_capture (struct budget *budget) saa7146_write(dev, MC2, (MASK_04 | MASK_20)); saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on - IER_ENABLE(budget->dev, MASK_10); // VPE + SAA7146_IER_ENABLE(budget->dev, MASK_10); // VPE return ++budget->feeding; } @@ -145,14 +149,87 @@ static void vpeirq (unsigned long data) return; if (newdma > olddma) { /* no wraparound, dump olddma..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (newdma-olddma) / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188); } else { /* wraparound, dump olddma..buflen and 0..newdma */ - dvb_dmx_swfilter_packets(&budget->demux, - mem+olddma, (TS_BUFLEN-olddma) / 188); - dvb_dmx_swfilter_packets(&budget->demux, - mem, newdma / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188); + dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188); + } } + + +int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, + int uselocks, int nobusyloop) +{ + struct saa7146_dev *saa = budget->dev; + int result = 0; + unsigned long flags = 0; + + if (count > 4 || count <= 0) + return 0; + + if (uselocks) + spin_lock_irqsave(&budget->debilock, flags); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff)); + saa7146_write(saa, DEBI_CONFIG, config); + saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, MC2, (2 << 16) | 2); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + result = saa7146_read(saa, DEBI_AD); + result &= (0xffffffffUL >> ((4 - count) * 8)); + + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + + return result; +} + +int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, + int count, u32 value, int uselocks, int nobusyloop) +{ + struct saa7146_dev *saa = budget->dev; + unsigned long flags = 0; + int result; + + if (count > 4 || count <= 0) + return 0; + + if (uselocks) + spin_lock_irqsave(&budget->debilock, flags); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff)); + saa7146_write(saa, DEBI_CONFIG, config); + saa7146_write(saa, DEBI_PAGE, 0); + saa7146_write(saa, DEBI_AD, value); + saa7146_write(saa, MC2, (2 << 16) | 2); + + if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) { + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return result; + } + + if (uselocks) + spin_unlock_irqrestore(&budget->debilock, flags); + return 0; } @@ -166,7 +243,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) struct budget *budget = (struct budget*) demux->priv; int status; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); if (!demux->dmx.frontend) return -EINVAL; @@ -183,7 +260,7 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) struct budget *budget = (struct budget *) demux->priv; int status; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); spin_lock(&budget->feedlock); status = stop_ts_capture (budget); @@ -197,7 +274,7 @@ static int budget_register(struct budget *budget) struct dvb_demux *dvbdemux=&budget->demux; int ret; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); dvbdemux->priv = (void *) budget; @@ -226,13 +303,11 @@ static int budget_register(struct budget *budget) return ret; budget->mem_frontend.source = DMX_MEMORY_FE; - ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, - &budget->mem_frontend); + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend); if (ret<0) return ret; - ret=dvbdemux->dmx.connect_frontend (&dvbdemux->dmx, - &budget->hw_frontend); + ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend); if (ret < 0) return ret; @@ -246,7 +321,7 @@ static void budget_unregister(struct budget *budget) { struct dvb_demux *dvbdemux=&budget->demux; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); dvb_net_release(&budget->dvb_net); @@ -258,17 +333,9 @@ static void budget_unregister(struct budget *budget) dvb_dmx_release(&budget->demux); } - -static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) -{ - struct saa7146_dev *dev = i2c->data; - return saa7146_i2c_transfer(dev, msgs, num, 6); -} - - -int ttpci_budget_init (struct budget *budget, - struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info) +int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, + struct saa7146_pci_extension_data *info, + struct module *owner) { int length = TS_WIDTH*TS_HEIGHT; int ret = 0; @@ -276,12 +343,12 @@ int ttpci_budget_init (struct budget *budget, memset(budget, 0, sizeof(struct budget)); - DEB_EE(("dev: %p, budget: %p\n", dev, budget)); + dprintk(2, "dev: %p, budget: %p\n", dev, budget); budget->card = bi; budget->dev = (struct saa7146_dev *) dev; - dvb_register_adapter(&budget->dvb_adapter, budget->card->name, THIS_MODULE); + dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner); /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); @@ -295,25 +362,33 @@ int ttpci_budget_init (struct budget *budget, else budget->video_port = BUDGET_VIDEO_PORTA; spin_lock_init(&budget->feedlock); + spin_lock_init(&budget->debilock); /* the Siemens DVB needs this if you want to have the i2c chips get recognized before the main driver is loaded */ if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ - saa7146_i2c_adapter_prepare(dev, NULL, 0, SAA7146_I2C_BUS_BIT_RATE_120); +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; +#else + budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL; +#endif + + strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); - budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, - budget->dvb_adapter, 0); + saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); + strcpy(budget->i2c_adap.name, budget->card->name); - if (!budget->i2c_bus) { + if (i2c_add_adapter(&budget->i2c_adap) < 0) { dvb_unregister_adapter (budget->dvb_adapter); return -ENOMEM; } - ttpci_eeprom_parse_mac(budget->i2c_bus); + ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac); - if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) { + if (NULL == + (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) { ret = -ENOMEM; goto err; } @@ -334,12 +409,11 @@ int ttpci_budget_init (struct budget *budget, return 0; } err: + i2c_del_adapter(&budget->i2c_adap); + if (budget->grabbing) vfree(budget->grabbing); - dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, - budget->i2c_bus->id); - dvb_unregister_adapter (budget->dvb_adapter); return ret; @@ -350,12 +424,11 @@ int ttpci_budget_deinit (struct budget *budget) { struct saa7146_dev *dev = budget->dev; - DEB_EE(("budget: %p\n", budget)); + dprintk(2, "budget: %p\n", budget); budget_unregister (budget); - dvb_unregister_i2c_bus (master_xfer, budget->i2c_bus->adapter, - budget->i2c_bus->id); + i2c_del_adapter(&budget->i2c_adap); dvb_unregister_adapter (budget->dvb_adapter); @@ -372,7 +445,7 @@ void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr) { struct budget *budget = (struct budget*)dev->ext_priv; - DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + dprintk(8, "dev: %p, budget: %p\n",dev,budget); if (*isr & MASK_10) tasklet_schedule (&budget->vpe_tasklet); @@ -394,15 +467,13 @@ void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port) spin_unlock(&budget->feedlock); } - - +EXPORT_SYMBOL_GPL(ttpci_budget_debiread); +EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite); EXPORT_SYMBOL_GPL(ttpci_budget_init); EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); EXPORT_SYMBOL_GPL(budget_debug); -MODULE_PARM(budget_debug,"i"); MODULE_LICENSE("GPL"); - diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 44118ec6c..7a9c68291 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -30,9 +30,12 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ -#include "budget.h" #include "av7110.h" #include "av7110_hw.h" +#include "budget.h" +#include "stv0299.h" +#include "ves1x93.h" +#include "tda8083.h" #define budget_patch budget @@ -51,7 +54,7 @@ static int budget_wdebi(struct budget_patch *budget, u32 config, int addr, u32 v { struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n", budget)); + dprintk(2, "budget: %p\n", budget); if (count <= 0 || count > 4) return -1; @@ -71,7 +74,7 @@ static int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int { int i; - DEB_EE(("budget: %p\n", budget)); + dprintk(2, "budget: %p\n", budget); for (i = 2; i < length; i++) budget_wdebi(budget, DEBINOSWAP, COMMAND + 2*i, (u32) buf[i], 2); @@ -90,7 +93,7 @@ static void av7110_set22k(struct budget_patch *budget, int state) { u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0}; - DEB_EE(("budget: %p\n", budget)); + dprintk(2, "budget: %p\n", budget); budget_av7110_send_fw_cmd(budget, buf, 2); } @@ -101,7 +104,7 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - DEB_EE(("budget: %p\n", budget)); + dprintk(2, "budget: %p\n", budget); if (len>10) len=10; @@ -121,16 +124,11 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, return 0; } - -int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { - struct budget_patch *budget = fe->before_after_data; + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; - DEB_EE(("budget: %p\n", budget)); - - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { + switch (tone) { case SEC_TONE_ON: av7110_set22k (budget, 1); break; @@ -140,27 +138,232 @@ int budget_patch_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void * default: return -EINVAL; } - break; - case FE_DISEQC_SEND_MASTER_CMD: + return 0; +} + +static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - av7110_send_diseqc_msg (budget, 0, NULL, (int) (long) arg); - break; +static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; - default: - return -EOPNOTSUPP; + av7110_send_diseqc_msg (budget, 0, NULL, minicmd); + + return 0; } +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; + + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct ves1x93_config alps_bsrv2_config = { + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + +static void frontend_init(struct budget_patch* budget) +{ + switch(budget->dev->pci->subsystem_device) { + case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X + + // try the ALPS BSRV2 first of all + budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + + // try the ALPS BSRU6 now + budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + + // Try the grundig 29504-451 + budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + break; + } + break; + } + + if (budget->dvb_frontend == NULL) { + printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget->dev->pci->vendor, + budget->dev->pci->device, + budget->dev->pci->subsystem_vendor, + budget->dev->pci->subsystem_device); + } else { + if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + printk("budget-av: Frontend registration failed!\n"); + if (budget->dvb_frontend->ops->release) + budget->dvb_frontend->ops->release(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } +} static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -171,9 +374,9 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) return -ENOMEM; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); - if ((err = ttpci_budget_init (budget, dev, info))) { + if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { kfree (budget); return err; } @@ -221,11 +424,11 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte // Enable RPS1 (rFC p33) saa7146_write(dev, MC1, (MASK_13 | MASK_29)); - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_patch_diseqc_ioctl, NULL, budget); - dev->ext_priv = budget; + budget->dvb_adapter->priv = budget; + frontend_init(budget); + return 0; } @@ -235,8 +438,7 @@ static int budget_patch_detach (struct saa7146_dev* dev) struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; int err; - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_patch_diseqc_ioctl, NULL); + if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); err = ttpci_budget_deinit (budget); @@ -251,10 +453,8 @@ static int __init budget_patch_init(void) return saa7146_register_extension(&budget_extension); } - static void __exit budget_patch_exit(void) { - DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index fbf1d5a6d..9488c7238 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -35,12 +35,16 @@ */ #include "budget.h" -#include "dvb_functions.h" +#include "stv0299.h" +#include "ves1x93.h" +#include "ves1820.h" +#include "l64781.h" +#include "tda8083.h" static void Set22K (struct budget *budget, int state) { struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); } @@ -52,7 +56,7 @@ static void Set22K (struct budget *budget, int state) static void DiseqcSendBit (struct budget *budget, int data) { struct saa7146_dev *dev=budget->dev; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); udelay(data ? 500 : 1000); @@ -65,7 +69,7 @@ static void DiseqcSendByte (struct budget *budget, int data) { int i, par=1, d; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); for (i=7; i>=0; i--) { d = (data>>i)&1; @@ -82,7 +86,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long struct saa7146_dev *dev=budget->dev; int i; - DEB_EE(("budget: %p\n",budget)); + dprintk(2, "budget: %p\n", budget); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); mdelay(16); @@ -100,95 +104,374 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long udelay(12500); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); } - dvb_delay(20); + msleep(20); } return 0; } +/* + * Routines for the Fujitsu Siemens Activy budget card + * 22 kHz tone and DiSEqC are handled by the frontend. + * Voltage must be set here. + */ +static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) +{ + struct saa7146_dev *dev=budget->dev; + + dprintk(2, "budget: %p\n", budget); + + switch (voltage) { + case SEC_VOLTAGE_13: + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); + break; + case SEC_VOLTAGE_18: + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); + break; + default: + return -EINVAL; + } + + return 0; +} -int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { - struct budget *budget = fe->before_after_data; + struct budget* budget = (struct budget*) fe->dvb->priv; - DEB_EE(("budget: %p\n",budget)); + return SetVoltage_Activy (budget, voltage); +} - switch (cmd) { - case FE_SET_TONE: - switch ((fe_sec_tone_mode_t) arg) { +static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + + switch (tone) { case SEC_TONE_ON: Set22K (budget, 1); break; case SEC_TONE_OFF: Set22K (budget, 0); break; + default: return -EINVAL; - }; - break; + } - case FE_DISEQC_SEND_MASTER_CMD: + return 0; +} + +static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) { - struct dvb_diseqc_master_cmd *cmd = arg; + struct budget* budget = (struct budget*) fe->dvb->priv; SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); - break; + + return 0; } - case FE_DISEQC_SEND_BURST: - SendDiSEqCMsg (budget, 0, NULL, (unsigned long)arg); - break; +static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; - default: - return -EOPNOTSUPP; - }; + SendDiSEqCMsg (budget, 0, NULL, minicmd); return 0; } +static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u8 pwr = 0; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + u32 div = (params->frequency + 479500) / 125; + + if (params->frequency > 2000000) pwr = 3; + else if (params->frequency > 1800000) pwr = 2; + else if (params->frequency > 1600000) pwr = 1; + else if (params->frequency > 1200000) pwr = 0; + else if (params->frequency >= 1100000) pwr = 1; + else pwr = 2; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = ((div & 0x18000) >> 10) | 0x95; + buf[3] = (pwr << 6) | 0x30; + + // NOTE: since we're using a prescaler of 2, we set the + // divisor frequency to 62.5kHz and divide by 125 above + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} -/* - * Routines for the Fujitsu Siemens Activy budget card - * 22 kHz tone and DiSEqC are handled by the frontend. - * Voltage must be set here. - */ -static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) +static struct ves1x93_config alps_bsrv2_config = { - struct saa7146_dev *dev=budget->dev; + .demod_address = 0x08, + .xin = 90100000UL, + .invert_pwm = 0, + .pll_set = alps_bsrv2_pll_set, +}; - DEB_EE(("budget: %p\n",budget)); +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; - switch (voltage) { - case SEC_VOLTAGE_13: - saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); - break; - case SEC_VOLTAGE_18: - saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - break; - default: - return -EINVAL; +static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } + + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; } +static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = 0xC4; + + if (params->frequency > 1530000) data[3] = 0xc0; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; -static int budget_ioctl_activy (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { - struct budget *budget = fe->before_after_data; + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; - DEB_EE(("budget: %p\n",budget)); + div = (params->frequency + 35937500 + 31250) / 62500; - switch (cmd) { - case FE_SET_VOLTAGE: - return SetVoltage_Activy (budget, (fe_sec_voltage_t) arg); - default: - return -EOPNOTSUPP; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x85 | ((div >> 10) & 0x60); + data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +static struct ves1820_config alps_tdbe2_config = { + .demod_address = 0x09, + .xin = 57840000UL, + .invert = 1, + .selagc = VES1820_SELAGC_SIGNAMPERR, + .pll_set = alps_tdbe2_pll_set, +}; + +static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 cfg, cpump, band_select; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = (36125000 + params->frequency) / 166666; + + cfg = 0x88; + + if (params->frequency < 175000000) cpump = 2; + else if (params->frequency < 390000000) cpump = 1; + else if (params->frequency < 470000000) cpump = 2; + else if (params->frequency < 750000000) cpump = 1; + else cpump = 3; + + if (params->frequency < 175000000) band_select = 0x0e; + else if (params->frequency < 470000000) band_select = 0x05; + else band_select = 0x03; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | cfg; + data[3] = (cpump << 6) | band_select; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; } +static struct l64781_config grundig_29504_401_config = { + .demod_address = 0x55, + .pll_set = grundig_29504_401_pll_set, +}; + +static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct budget* budget = (struct budget*) fe->dvb->priv; + u32 div; + u8 data[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + div = params->frequency / 125; + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x8e; + data[3] = 0x00; + + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } +static struct tda8083_config grundig_29504_451_config = { + .demod_address = 0x68, + .pll_set = grundig_29504_451_pll_set, +}; + +static u8 read_pwm(struct budget* budget) +{ + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, + { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; + + if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static void frontend_init(struct budget *budget) +{ + switch(budget->dev->pci->subsystem_device) { + case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) + + // try the ALPS BSRV2 first of all + budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_set_tone; + break; + } + + // try the ALPS BSRU6 now + budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops->set_tone = budget_set_tone; + break; + } + break; + + case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) + + budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); + if (budget->dvb_frontend) break; + break; + + case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) + + budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap); + if (budget->dvb_frontend) break; + break; + + case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI (tda8083/Grundig 29504-451(tsa5522)) + + // grundig 29504-451 + budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; + break; + } + break; + } + + if (budget->dvb_frontend == NULL) { + printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", + budget->dev->pci->vendor, + budget->dev->pci->device, + budget->dev->pci->subsystem_vendor, + budget->dev->pci->subsystem_device); + } else { + if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) { + printk("budget: Frontend registration failed!\n"); + if (budget->dvb_frontend->ops->release) + budget->dvb_frontend->ops->release(budget->dvb_frontend); + budget->dvb_frontend = NULL; + } + } +} static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -200,22 +483,18 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ return -ENOMEM; } - DEB_EE(("dev:%p, info:%p, budget:%p\n",dev,info,budget)); + dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget); - if ((err = ttpci_budget_init (budget, dev, info))) { + dev->ext_priv = budget; + + if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { printk("==> failed\n"); kfree (budget); return err; } - if (budget->card->type == BUDGET_FS_ACTIVY) - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_ioctl_activy, NULL, budget); - else - dvb_add_frontend_ioctls (budget->dvb_adapter, - budget_diseqc_ioctl, NULL, budget); - - dev->ext_priv = budget; + budget->dvb_adapter->priv = budget; + frontend_init(budget); return 0; } @@ -226,12 +505,7 @@ static int budget_detach (struct saa7146_dev* dev) struct budget *budget = (struct budget*) dev->ext_priv; int err; - if (budget->card->type == BUDGET_FS_ACTIVY) - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_ioctl_activy, NULL); - else - dvb_remove_frontend_ioctls (budget->dvb_adapter, - budget_diseqc_ioctl, NULL); + if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); err = ttpci_budget_deinit (budget); @@ -248,18 +522,14 @@ static struct saa7146_extension budget_extension; MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); -MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); +/* MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); UNDEFINED HARDWARE - mail linuxtv.org list */ MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY); -/* Uncomment for Budget Patch */ -/*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/ static struct pci_device_id pci_tbl[] = { - /* Uncomment for Budget Patch */ - /*MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),*/ MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), - MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), +/* MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), UNDEFINED HARDWARE */ MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61), { .vendor = 0, @@ -290,7 +560,6 @@ static int __init budget_init(void) static void __exit budget_exit(void) { - DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index 6be1d3bcd..726394cab 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h @@ -1,9 +1,6 @@ #ifndef __BUDGET_DVB__ #define __BUDGET_DVB__ -#include - -#include "dvb_i2c.h" #include "dvb_frontend.h" #include "dvbdev.h" #include "demux.h" @@ -12,8 +9,18 @@ #include "dvb_filter.h" #include "dvb_net.h" +#include +#include + extern int budget_debug; +#ifdef dprintk +#undef dprintk +#endif + +#define dprintk(level,args...) \ + do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0) + struct budget_info { char *name; int type; @@ -28,7 +35,7 @@ struct budget { struct saa7146_dev *dev; - struct dvb_i2c_bus *i2c_bus; + struct i2c_adapter i2c_adap; struct budget_info *card; unsigned char *grabbing; @@ -55,7 +62,10 @@ struct budget { spinlock_t feedlock; + spinlock_t debilock; + struct dvb_adapter *dvb_adapter; + struct dvb_frontend *dvb_frontend; void *priv; }; @@ -76,19 +86,27 @@ static struct saa7146_pci_extension_data x_var = { \ #define BUDGET_TT 0 #define BUDGET_TT_HW_DISEQC 1 -#define BUDGET_KNC1 2 #define BUDGET_PATCH 3 #define BUDGET_FS_ACTIVY 4 +#define BUDGET_CIN1200S 5 +#define BUDGET_CIN1200C 6 +#define BUDGET_CIN1200T 7 +#define BUDGET_KNC1S 8 +#define BUDGET_KNC1C 9 +#define BUDGET_KNC1T 10 #define BUDGET_VIDEO_PORTA 0 #define BUDGET_VIDEO_PORTB 1 -extern int ttpci_budget_init (struct budget *budget, - struct saa7146_dev* dev, - struct saa7146_pci_extension_data *info); +extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, + struct saa7146_pci_extension_data *info, + struct module *owner); extern int ttpci_budget_deinit (struct budget *budget); extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr); extern void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port); +extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count, + int uselocks, int nobusyloop); +extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value, + int uselocks, int nobusyloop); #endif - diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c index a17c828fd..0659c53f9 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.c +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c @@ -35,9 +35,8 @@ #include #include #include +#include -#include "dvb_i2c.h" -#include "dvb_functions.h" #if 1 #define dprintk(x...) do { printk(x); } while (0) @@ -85,7 +84,7 @@ static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC) return 0; } -static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC) +static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC) { int ret; u8 b0[] = { 0xcc }; @@ -97,7 +96,7 @@ static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC /* dprintk("%s\n", __FUNCTION__); */ - ret = i2c->xfer(i2c, msg, 2); + ret = i2c_transfer(adapter, msg, 2); if (ret != 2) /* Assume EEPROM isn't there */ return (-ENODEV); @@ -106,36 +105,34 @@ static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC } -int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c) +int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac) { int ret, i; u8 encodedMAC[20]; u8 decodedMAC[6]; - ret = ttpci_eeprom_read_encodedMAC(i2c, encodedMAC); + ret = ttpci_eeprom_read_encodedMAC(adapter, encodedMAC); if (ret != 0) { /* Will only be -ENODEV */ dprintk("Couldn't read from EEPROM: not there?\n"); - memset(i2c->adapter->proposed_mac, 0, 6); + memset(proposed_mac, 0, 6); return ret; } ret = getmac_tt(decodedMAC, encodedMAC); if( ret != 0 ) { - dprintk("%s adapter %i failed MAC signature check\n", - i2c->adapter->name, i2c->adapter->num); + dprintk("adapter failed MAC signature check\n"); dprintk("encoded MAC from EEPROM was " ); for(i=0; i<19; i++) { dprintk( "%.2x:", encodedMAC[i]); } dprintk("%.2x\n", encodedMAC[19]); - memset(i2c->adapter->proposed_mac, 0, 6); + memset(proposed_mac, 0, 6); return ret; } - memcpy(i2c->adapter->proposed_mac, decodedMAC, 6); - dprintk("%s adapter %i has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", - i2c->adapter->name, i2c->adapter->num, + memcpy(proposed_mac, decodedMAC, 6); + dprintk("adapter has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", decodedMAC[0], decodedMAC[1], decodedMAC[2], decodedMAC[3], decodedMAC[4], decodedMAC[5]); return 0; diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h index 48df7ce53..e2dc6cfe2 100644 --- a/drivers/media/dvb/ttpci/ttpci-eeprom.h +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h @@ -25,8 +25,9 @@ #ifndef __TTPCI_EEPROM_H__ #define __TTPCI_EEPROM_H__ -#include "dvb_i2c.h" +#include +#include -extern int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c); +extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac); #endif diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig index c8bbbcc68..b4d3322b3 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/dvb/ttusb-budget/Kconfig @@ -1,6 +1,10 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" depends on DVB_CORE && USB + select DVB_CX22700 + select DVB_TDA1004X + select DVB_TDA8083 + select DVB_STV0299 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile index a57b9aee6..6ab97f6b5 100644 --- a/drivers/media/dvb/ttusb-budget/Makefile +++ b/drivers/media/dvb/ttusb-budget/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o -EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index cc14ec76d..91a00d99f 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,13 +24,15 @@ #include "dmxdev.h" #include "dvb_demux.h" #include "dvb_net.h" +#include "cx22700.h" +#include "tda1004x.h" +#include "stv0299.h" +#include "tda8083.h" #include #include #include -#include "dvb_functions.h" - /* TTUSB_HWSECTIONS: the DSP supports filtering in hardware, however, since the "muxstream" @@ -49,7 +52,10 @@ this unless the device doesn't load at all. > 2 for bandwidth statistics. */ -static int debug = 0; +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0) @@ -80,6 +86,8 @@ struct ttusb { struct dvb_adapter *adapter; struct usb_device *dev; + struct i2c_adapter i2c_adap; + int disconnecting; int iso_streaming; @@ -128,6 +136,8 @@ struct ttusb { #if 0 devfs_handle_t stc_devfs_handle; #endif + + struct dvb_frontend* fe; }; /* ugly workaround ... don't know why it's neccessary to read */ @@ -242,10 +252,9 @@ static int ttusb_i2c_msg(struct ttusb *ttusb, return rcv_len; } -static int ttusb_i2c_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msg[], - int num) +static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num) { - struct ttusb *ttusb = i2c->data; + struct ttusb *ttusb = i2c_get_adapdata(adapter); int i = 0; int inc; @@ -458,9 +467,10 @@ static int ttusb_init_controller(struct ttusb *ttusb) } #ifdef TTUSB_DISEQC -static int ttusb_send_diseqc(struct ttusb *ttusb, +static int ttusb_send_diseqc(struct dvb_frontend* fe, const struct dvb_diseqc_master_cmd *cmd) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 b[12] = { 0xaa, ++ttusb->c, 0x18 }; int err; @@ -498,41 +508,24 @@ static int ttusb_update_lnb(struct ttusb *ttusb) return err; } -static int ttusb_set_voltage(struct ttusb *ttusb, fe_sec_voltage_t voltage) +static int ttusb_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + ttusb->voltage = voltage; return ttusb_update_lnb(ttusb); } #ifdef TTUSB_TONE -static int ttusb_set_tone(struct ttusb *ttusb, fe_sec_tone_mode_t tone) +static int ttusb_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + ttusb->tone = tone; return ttusb_update_lnb(ttusb); } #endif -static int ttusb_lnb_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) -{ - struct ttusb *ttusb = fe->i2c->data; - - switch (cmd) { - case FE_SET_VOLTAGE: - return ttusb_set_voltage(ttusb, (fe_sec_voltage_t) arg); -#ifdef TTUSB_TONE - case FE_SET_TONE: - return ttusb_set_tone(ttusb, (fe_sec_tone_mode_t) arg); -#endif -#ifdef TTUSB_DISEQC - case FE_DISEQC_SEND_MASTER_CMD: - return ttusb_send_diseqc(ttusb, - (struct dvb_diseqc_master_cmd *) - arg); -#endif - default: - return -EOPNOTSUPP; - }; -} #if 0 static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq) @@ -557,7 +550,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data, int len); #endif -int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid; +static int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid; static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, int len) @@ -787,7 +780,7 @@ static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs) ttusb_process_frame(ttusb, data, len); } } - usb_submit_urb(urb, GFP_KERNEL); + usb_submit_urb(urb, GFP_ATOMIC); } static void ttusb_free_iso_urbs(struct ttusb *ttusb) @@ -822,7 +815,7 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) if (! (urb = - usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) { + usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) { ttusb_free_iso_urbs(ttusb); return -ENOMEM; } @@ -880,7 +873,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb) } for (i = 0; i < ISO_BUF_COUNT; i++) { - if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) { + if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) { ttusb_stop_iso_xfer(ttusb); printk ("%s: failed urb submission (%i: err = %i)!\n", @@ -1068,6 +1061,347 @@ static struct file_operations stc_fops = { }; #endif +static u32 functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + + + +static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 data[4]; + struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) }; + u32 div; + + div = (params->frequency + 36166667) / 166667; + + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = ((div >> 10) & 0x60) | 0x85; + data[3] = params->frequency < 592000000 ? 0x40 : 0x80; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; + return 0; +} + +struct cx22700_config alps_tdmb7_config = { + .demod_address = 0x43, + .pll_set = alps_tdmb7_pll_set, +}; + + + + + +static int philips_tdm1316l_pll_init(struct dvb_frontend* fe) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) }; + + // setup PLL configuration + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; + msleep(1); + + // disable the mc44BC374c (do not check for errors) + tuner_msg.addr = 0x65; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { + i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1); + } + + return 0; +} + +static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency + 36130000; + if (tuner_frequency < 87000000) return -EINVAL; + else if (tuner_frequency < 130000000) cp = 3; + else if (tuner_frequency < 160000000) cp = 5; + else if (tuner_frequency < 200000000) cp = 6; + else if (tuner_frequency < 290000000) cp = 3; + else if (tuner_frequency < 420000000) cp = 5; + else if (tuner_frequency < 480000000) cp = 6; + else if (tuner_frequency < 620000000) cp = 3; + else if (tuner_frequency < 830000000) cp = 5; + else if (tuner_frequency < 895000000) cp = 7; + else return -EINVAL; + + // determine band + if (params->frequency < 49000000) return -EINVAL; + else if (params->frequency < 159000000) band = 1; + else if (params->frequency < 444000000) band = 2; + else if (params->frequency < 861000000) band = 4; + else return -EINVAL; + + // setup PLL filter + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_byte(fe, 0x0C, 0); + filter = 0; + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_byte(fe, 0x0C, 0); + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_byte(fe, 0x0C, 0xFF); + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate divisor + // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) + tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000; + + // setup tuner buffer + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; + + msleep(1); + return 0; +} + +static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + + return request_firmware(fw, name, &ttusb->dev->dev); +} + +static struct tda1004x_config philips_tdm1316l_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 0, + .pll_init = philips_tdm1316l_pll_init, + .pll_set = philips_tdm1316l_pll_set, + .request_firmware = philips_tdm1316l_request_firmware, +}; + + +static u8 alps_bsru6_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x52, + 0xff, 0xff +}; + +static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, (ratio) & 0xf0); + + return 0; +} + +static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + buf[3] = 0xC4; + + if (params->frequency > 1530000) + buf[3] = 0xc0; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct stv0299_config alps_bsru6_config = { + + .demod_address = 0x68, + .inittab = alps_bsru6_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_1, + .volt13_op0_op1 = STV0299_VOLT13_OP1, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsru6_pll_set, +}; + +static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; + u8 buf[4]; + u32 div; + struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; + + div = params->frequency / 125; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + buf[3] = 0x00; + + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static struct tda8083_config ttusb_novas_grundig_29504_491_config = { + + .demod_address = 0x68, + .pll_set = ttusb_novas_grundig_29504_491_pll_set, +}; + + + +static void frontend_init(struct ttusb* ttusb) +{ + switch(ttusb->dev->descriptor.idProduct) { + case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059) + // try the ALPS BSRU6 first + ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + // Grundig 29504-491 + ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops->set_voltage = ttusb_set_voltage; + break; + } + + break; + + case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??)) + // try the ALPS TDMB7 first + ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) + break; + + // Philips td1316 + ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) + break; + break; + } + + if (ttusb->fe == NULL) { + printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n", + ttusb->dev->descriptor.idVendor, + ttusb->dev->descriptor.idProduct); + } else { + if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) { + printk("dvb-ttusb-budget: Frontend registration failed!\n"); + if (ttusb->fe->ops->release) + ttusb->fe->ops->release(ttusb->fe); + ttusb->fe = NULL; + } + } +} + + + +static struct i2c_algorithm ttusb_dec_algo = { + .name = "ttusb dec i2c algorithm", + .id = I2C_ALGO_BIT, + .master_xfer = master_xfer, + .functionality = functionality, +}; + static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; @@ -1078,17 +1412,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i udev = interface_to_usbdev(intf); - /* Device has already been reset; its configuration was chosen. - * If this fault happens, use a hotplug script to choose the - * right configuration (write bConfigurationValue in sysfs). - */ - if (udev->actconfig->desc.bConfigurationValue != 1) { - dev_err(&intf->dev, "device config is #%d, need #1\n", - udev->actconfig->desc.bConfigurationValue); - return -ENODEV; - } - - if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV; if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL))) @@ -1116,10 +1439,28 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i up(&ttusb->sem); dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); + ttusb->adapter->priv = ttusb; - dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0); - dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL, - ttusb); + /* i2c */ + memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter)); + strcpy(ttusb->i2c_adap.name, "TTUSB DEC"); + + i2c_set_adapdata(&ttusb->i2c_adap, ttusb); + +#ifdef I2C_ADAP_CLASS_TV_DIGITAL + ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL; +#else + ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; +#endif + ttusb->i2c_adap.algo = &ttusb_dec_algo; + ttusb->i2c_adap.algo_data = NULL; + ttusb->i2c_adap.id = I2C_ALGO_BIT; + + result = i2c_add_adapter(&ttusb->i2c_adap); + if (result) { + dvb_unregister_adapter (ttusb->adapter); + return result; + } memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux)); @@ -1137,9 +1478,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb->dvb_demux.write_to_decoder = NULL; if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) { - printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", - result); - goto err; + printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result); + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } //FIXME dmxdev (nur WAS?) ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum; @@ -1150,15 +1492,20 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n", result); dvb_dmx_release(&ttusb->dvb_demux); - goto err; + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } - if (dvb_net_init - (ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { + if (dvb_net_init(ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { printk("ttusb_dvb: dvb_net_init failed!\n"); + dvb_dmxdev_release(&ttusb->dmxdev); + dvb_dmx_release(&ttusb->dvb_demux); + i2c_del_adapter(&ttusb->i2c_adap); + dvb_unregister_adapter (ttusb->adapter); + return -ENODEV; } - err: #if 0 ttusb->stc_devfs_handle = devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME, @@ -1166,9 +1513,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &stc_fops, ttusb); #endif - usb_set_intfdata(intf, (void *) ttusb); + frontend_init(ttusb); + return 0; } @@ -1186,8 +1534,8 @@ static void ttusb_disconnect(struct usb_interface *intf) dvb_net_release(&ttusb->dvbnet); dvb_dmxdev_release(&ttusb->dmxdev); dvb_dmx_release(&ttusb->dvb_demux); - - dvb_unregister_i2c_bus(ttusb_i2c_xfer, ttusb->adapter, 0); + if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe); + i2c_del_adapter(&ttusb->i2c_adap); dvb_unregister_adapter(ttusb->adapter); ttusb_free_iso_urbs(ttusb); @@ -1199,7 +1547,7 @@ static void ttusb_disconnect(struct usb_interface *intf) static struct usb_device_id ttusb_table[] = { {USB_DEVICE(0xb48, 0x1003)}, - {USB_DEVICE(0xb48, 0x1004)}, /* to be confirmed ???? */ +/* {USB_DEVICE(0xb48, 0x1004)},UNDEFINED HARDWARE - mail linuxtv.org list*/ /* to be confirmed ???? */ {USB_DEVICE(0xb48, 0x1005)}, {} }; @@ -1234,9 +1582,6 @@ static void __exit ttusb_exit(void) module_init(ttusb_init); module_exit(ttusb_exit); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug or not"); - MODULE_AUTHOR("Holger Waechtler "); MODULE_DESCRIPTION("TTUSB DVB Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h index 287645d8a..95ee79954 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h @@ -1,7 +1,7 @@ #include -u8 dsp_bootcode [] = { +static u8 dsp_bootcode [] = { 0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f, 0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb, diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig index 139d71eb0..61fabb668 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/dvb/ttusb-dec/Kconfig @@ -12,8 +12,10 @@ config DVB_TTUSB_DEC only compressed MPEG data over the USB bus, so you need an external software decoder to watch TV on your computer. - The DEC devices require firmware in order to boot into a mode in - which they are slaves to the PC. See - for details. + This driver needs external firmware. Please use the commands + "/Documentation/dvb/get_dvb_firmware dec2000t", + "/Documentation/dvb/get_dvb_firmware dec2540t", + "/Documentation/dvb/get_dvb_firmware dec3000s", + download/extract them, and then copy them to /usr/lib/hotplug/firmware. Say Y if you own such a device and want to use it. diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile index bf4e38740..b41bf1f06 100644 --- a/drivers/media/dvb/ttusb-dec/Makefile +++ b/drivers/media/dvb/ttusb-dec/Makefile @@ -1,3 +1,3 @@ -obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o +obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 5e3f5eacc..b51a96141 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -22,28 +22,31 @@ #include #include #include +#include #include #include #include #include +#include #include #include -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) #include -#else -#warning "CRC checking of firmware not available" -#endif #include #include "dmxdev.h" #include "dvb_demux.h" -#include "dvb_i2c.h" #include "dvb_filter.h" #include "dvb_frontend.h" #include "dvb_net.h" +#include "ttusbdecfe.h" -static int debug = 0; -static int output_pva = 0; +static int debug; +static int output_pva; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); +module_param(output_pva, int, 0444); +MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); #define dprintk if (debug) printk @@ -63,9 +66,6 @@ static int output_pva = 0; #define MAX_PVA_LENGTH 6144 -#define LOF_HI 10600000 -#define LOF_LO 9750000 - enum ttusb_dec_model { TTUSB_DEC2000T, TTUSB_DEC2540T, @@ -95,14 +95,10 @@ struct ttusb_dec { struct dmxdev dmxdev; struct dvb_demux demux; struct dmx_frontend frontend; - struct dvb_i2c_bus i2c_bus; struct dvb_net dvb_net; - struct dvb_frontend_info *frontend_info; - int (*frontend_ioctl) (struct dvb_frontend *, unsigned int, void *); + struct dvb_frontend* fe; u16 pid[DMX_PES_OTHER]; - int hi_band; - int voltage; /* USB bits */ struct usb_device *udev; @@ -161,32 +157,6 @@ struct filter_info { struct list_head filter_info_list; }; -static struct dvb_frontend_info dec2000t_frontend_info = { - .name = "TechnoTrend/Hauppauge DEC2000-t Frontend", - .type = FE_OFDM, - .frequency_min = 51000000, - .frequency_max = 858000000, - .frequency_stepsize = 62500, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - -static struct dvb_frontend_info dec3000s_frontend_info = { - .name = "TechnoTrend/Hauppauge DEC3000-s Frontend", - .type = FE_QPSK, - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; - static void ttusb_dec_set_model(struct ttusb_dec *dec, enum ttusb_dec_model model); @@ -1100,7 +1070,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) &dec->iso_dma_handle); memset(dec->iso_buffer, 0, - sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT))); + ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); for (i = 0; i < ISO_BUF_COUNT; i++) { struct urb *urb; @@ -1165,10 +1135,9 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) u16 firmware_csum = 0; u16 firmware_csum_ns; u32 firmware_size_nl; -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) u32 crc32_csum, crc32_check, tmp; -#endif const struct firmware *fw_entry = NULL; + dprintk("%s\n", __FUNCTION__); if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) { @@ -1181,7 +1150,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) firmware_size = fw_entry->size; if (firmware_size < 60) { - printk("%s: firmware size too small for DSP code (%u < 60).\n", + printk("%s: firmware size too small for DSP code (%zu < 60).\n", __FUNCTION__, firmware_size); return -1; } @@ -1189,7 +1158,6 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored at offset 56 of file, so use it to check if the firmware file is valid. */ -#if defined(CONFIG_CRC32) || defined(CONFIG_CRC32_MODULE) crc32_csum = crc32(~0L, firmware, 56) ^ ~0L; memcpy(&tmp, &firmware[56], 4); crc32_check = htonl(tmp); @@ -1199,7 +1167,6 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) __FUNCTION__, crc32_csum, crc32_check); return -1; } -#endif memcpy(idstring, &firmware[36], 20); idstring[20] = '\0'; printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring); @@ -1288,6 +1255,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec) ttusb_dec_set_model(dec, TTUSB_DEC3000S); break; case 0x00070009: + case 0x00070013: ttusb_dec_set_model(dec, TTUSB_DEC2000T); break; case 0x00070011: @@ -1398,6 +1366,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); + if (dec->fe) dvb_unregister_frontend(dec->fe); dvb_unregister_adapter(dec->adapter); } @@ -1429,257 +1398,6 @@ static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec) } } -static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd, - void *arg) -{ - struct ttusb_dec *dec = fe->data; - - dprintk("%s\n", __FUNCTION__); - - switch (cmd) { - - case FE_GET_INFO: - dprintk("%s: FE_GET_INFO\n", __FUNCTION__); - memcpy(arg, dec->frontend_info, - sizeof (struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } - - case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } - - case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } - - case FE_READ_SNR: - dprintk("%s: FE_READ_SNR\n", __FUNCTION__); - *(s32 *)arg = 0; - return -ENOSYS; - break; - - case FE_READ_UNCORRECTED_BLOCKS: - dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__); - *(u32 *)arg = 0; - return -ENOSYS; - break; - - case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff }; - u32 freq; - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); - - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency / 1000); - memcpy(&b[4], &freq, sizeof (u32)); - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - - break; - } - - case FE_GET_FRONTEND: - dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); - break; - - case FE_SLEEP: - dprintk("%s: FE_SLEEP\n", __FUNCTION__); - return -ENOSYS; - break; - - case FE_INIT: - dprintk("%s: FE_INIT\n", __FUNCTION__); - break; - - default: - dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); - return -EINVAL; - - } - - return 0; -} - -static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, - unsigned int cmd, void *arg) -{ - struct ttusb_dec *dec = fe->data; - - dprintk("%s\n", __FUNCTION__); - - switch (cmd) { - - case FE_GET_INFO: - dprintk("%s: FE_GET_INFO\n", __FUNCTION__); - memcpy(arg, dec->frontend_info, - sizeof (struct dvb_frontend_info)); - break; - - case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } - - case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } - - case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } - - case FE_READ_SNR: - dprintk("%s: FE_READ_SNR\n", __FUNCTION__); - *(s32 *)arg = 0; - return -ENOSYS; - break; - - case FE_READ_UNCORRECTED_BLOCKS: - dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__); - *(u32 *)arg = 0; - return -ENOSYS; - break; - - case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 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 }; - u32 freq; - u32 sym_rate; - u32 band; - u32 lnb_voltage; - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); - - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency * 1000 + - (dec->hi_band ? LOF_HI : LOF_LO)); - memcpy(&b[4], &freq, sizeof(u32)); - sym_rate = htonl(p->u.qam.symbol_rate); - memcpy(&b[12], &sym_rate, sizeof(u32)); - band = htonl(dec->hi_band ? LOF_HI : LOF_LO); - memcpy(&b[24], &band, sizeof(u32)); - lnb_voltage = htonl(dec->voltage); - memcpy(&b[28], &lnb_voltage, sizeof(u32)); - - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - - break; - } - - case FE_GET_FRONTEND: - dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); - break; - - case FE_SLEEP: - dprintk("%s: FE_SLEEP\n", __FUNCTION__); - return -ENOSYS; - break; - - case FE_INIT: - dprintk("%s: FE_INIT\n", __FUNCTION__); - break; - - case FE_DISEQC_SEND_MASTER_CMD: - dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__); - break; - - case FE_DISEQC_SEND_BURST: - dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__); - break; - - case FE_SET_TONE: { - fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg; - dprintk("%s: FE_SET_TONE\n", __FUNCTION__); - dec->hi_band = (SEC_TONE_ON == tone); - break; - } - - case FE_SET_VOLTAGE: - dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); - switch ((fe_sec_voltage_t) arg) { - case SEC_VOLTAGE_13: - dec->voltage = 13; - break; - case SEC_VOLTAGE_18: - dec->voltage = 18; - break; - default: - return -EINVAL; - break; - } - break; - - default: - dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); - return -EINVAL; - - } - - return 0; -} - -static void ttusb_dec_init_frontend(struct ttusb_dec *dec) -{ - dec->i2c_bus.adapter = dec->adapter; - - dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec, - dec->frontend_info); -} - -static void ttusb_dec_exit_frontend(struct ttusb_dec *dec) -{ - dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus); -} - static void ttusb_dec_init_filters(struct ttusb_dec *dec) { INIT_LIST_HEAD(&dec->filter_info_list); @@ -1698,6 +1416,18 @@ static void ttusb_dec_exit_filters(struct ttusb_dec *dec) } } +int fe_send_command(struct dvb_frontend* fe, const u8 command, + int param_length, const u8 params[], + int *result_length, u8 cmd_result[]) +{ + struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv; + return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); +} + +struct ttusbdecfe_config fe_config = { + .send_command = fe_send_command +}; + static int ttusb_dec_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1739,7 +1469,32 @@ static int ttusb_dec_probe(struct usb_interface *intf, return 0; } ttusb_dec_init_dvb(dec); - ttusb_dec_init_frontend(dec); + + dec->adapter->priv = dec; + switch (id->idProduct) { + case 0x1006: + dec->fe = ttusbdecfe_dvbs_attach(&fe_config); + break; + + case 0x1008: + case 0x1009: + dec->fe = ttusbdecfe_dvbt_attach(&fe_config); + break; + } + + if (dec->fe == NULL) { + printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n", + dec->udev->descriptor.idVendor, + dec->udev->descriptor.idProduct); + } else { + if (dvb_register_frontend(dec->adapter, dec->fe)) { + printk("budget-ci: Frontend registration failed!\n"); + if (dec->fe->ops->release) + dec->fe->ops->release(dec->fe); + dec->fe = NULL; + } + } + ttusb_dec_init_v_pes(dec); ttusb_dec_init_filters(dec); ttusb_dec_init_tasklet(dec); @@ -1763,7 +1518,6 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) ttusb_dec_exit_tasklet(dec); ttusb_dec_exit_filters(dec); ttusb_dec_exit_usb(dec); - ttusb_dec_exit_frontend(dec); ttusb_dec_exit_dvb(dec); } @@ -1779,22 +1533,16 @@ static void ttusb_dec_set_model(struct ttusb_dec *dec, case TTUSB_DEC2000T: dec->model_name = "DEC2000-t"; dec->firmware_name = "dvb-ttusb-dec-2000t.fw"; - dec->frontend_info = &dec2000t_frontend_info; - dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; break; case TTUSB_DEC2540T: dec->model_name = "DEC2540-t"; dec->firmware_name = "dvb-ttusb-dec-2540t.fw"; - dec->frontend_info = &dec2000t_frontend_info; - dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; break; case TTUSB_DEC3000S: dec->model_name = "DEC3000-s"; dec->firmware_name = "dvb-ttusb-dec-3000s.fw"; - dec->frontend_info = &dec3000s_frontend_info; - dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl; break; } } @@ -1840,7 +1588,3 @@ MODULE_DESCRIPTION(DRIVER_NAME); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(usb, ttusb_dec_table); -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug level"); -MODULE_PARM(output_pva, "i"); -MODULE_PARM_DESC(output_pva, "Output PVA from dvr device"); diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index 6b11044e7..df79d5e0a 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "miropcm20-rds-core.h" @@ -60,8 +61,7 @@ static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, char c; char bits[8]; - current->state=TASK_UNINTERRUPTIBLE; - schedule_timeout(2*HZ); + msleep(2000); aci_rds_cmd(RDS_STATUS, &c, 1); print_matrix(&c, bits); if (copy_to_user(buffer, bits, 8)) diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index c6e648753..7aab2ed62 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -63,12 +63,7 @@ static void sleep_delay(long n) if(!d) udelay(n); else - { - /* Yield CPU time */ - unsigned long x=jiffies; - while((jiffies-x)<=d) - schedule(); - } + msleep(jiffies_to_msecs(d)); } static void rt_decvol(void) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 8cc5191ac..abb03c53d 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -69,8 +69,7 @@ static int cadet_getrds(void) outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ spin_unlock(&cadet_io_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); spin_lock(&cadet_io_lock); outb(3,io); /* Select Decoder Control/Status */ @@ -243,8 +242,7 @@ static void cadet_setfreq(unsigned freq) outb(curvol,io+1); spin_unlock(&cadet_io_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); cadet_gettune(); if((tunestat & 0x40) == 0) { /* Tuned */ diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 6a18c0088..b226aa437 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -93,27 +93,6 @@ static struct radio_device struct semaphore lock; } radio_unit = {0, 0, 0, 0, }; -static void sleep_125ms(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ >> 3); -} - -static void udelay2(void) -{ - udelay(2); -} - -static void udelay4(void) -{ - udelay(4); -} - -static void udelay16(void) -{ - udelay(16); -} - static __u32 radio_bits_get(struct radio_device *dev) { register __u16 io=dev->io, l, rdata; @@ -122,14 +101,15 @@ static __u32 radio_bits_get(struct radio_device *dev) omask = inw(io + IO_MASK); outw(~(STR_CLK | STR_WREN), io + IO_MASK); outw(0, io); - udelay16(); + udelay(16); + for (l=24;l--;) { outw(STR_CLK, io); /* HI state */ - udelay2(); + udelay(2); if(!l) dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff; outw(0, io); /* LO state */ - udelay2(); + udelay(2); data <<= 1; /* shift data */ rdata = inw(io); if(!l) @@ -138,11 +118,11 @@ static __u32 radio_bits_get(struct radio_device *dev) else if(rdata & STR_DATA) data++; - udelay2(); + udelay(2); } if(dev->muted) outw(STR_WREN, io); - udelay4(); + udelay(4); outw(omask, io + IO_MASK); return data & 0x3ffe; } @@ -155,23 +135,23 @@ static void radio_bits_set(struct radio_device *dev, __u32 data) odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); outw(odir | STR_DATA, io + IO_DIR); outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); - udelay16(); + udelay(16); for (l=25;l;l--) { bits = ((data >> 18) & STR_DATA) | STR_WREN ; data <<= 1; /* shift data */ outw(bits, io); /* start strobe */ - udelay2(); + udelay(2); outw(bits | STR_CLK, io); /* HI level */ - udelay2(); + udelay(2); outw(bits, io); /* LO level */ - udelay4(); + udelay(4); } if(!dev->muted) outw(0, io); - udelay4(); + udelay(4); outw(omask, io + IO_MASK); outw(odir, io + IO_DIR); - sleep_125ms(); + msleep(125); } inline static int radio_function(struct inode *inode, struct file *file, @@ -238,9 +218,9 @@ inline static int radio_function(struct inode *inode, struct file *file, outw(~STR_WREN, io + IO_MASK); outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ? STR_WREN : 0, io); - udelay4(); + udelay(4); outw(omask, io + IO_MASK); - sleep_125ms(); + msleep(125); return 0; } } @@ -270,7 +250,7 @@ static int radio_ioctl(struct inode *inode, struct file *file, return ret; } -inline static __u16 radio_install(struct pci_dev *pcidev); +static __u16 radio_install(struct pci_dev *pcidev); MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); @@ -315,7 +295,7 @@ inline static __u16 radio_power_on(struct radio_device *dev) outw(odir, io + IO_DIR); outw(~(STR_WREN | STR_CLK), io + IO_MASK); outw(dev->muted ? 0 : STR_WREN, io); - udelay16(); + udelay(16); outw(omask, io + IO_MASK); ofreq = radio_bits_get(dev); if((ofreqFREQ2BITS(FREQ_HI))) @@ -324,7 +304,7 @@ inline static __u16 radio_power_on(struct radio_device *dev) return (ofreq == radio_bits_get(dev)); } -inline static __u16 radio_install(struct pci_dev *pcidev) +static __u16 radio_install(struct pci_dev *pcidev) { if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO) return 0; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index c2fa20d77..c3c62095f 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -104,13 +104,6 @@ static struct radio_device } radio_unit = {0, 0, 0, 0, }; -static void sleep_125ms(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ >> 3); -} - - static void outbit(unsigned long bit, __u16 io) { if(bit != 0) @@ -228,7 +221,7 @@ inline static int radio_function(struct inode *inode, struct file *file, return -EINVAL; card->freq = *freq; set_freq(card->io, FREQ2BITS(card->freq)); - sleep_125ms(); + msleep(125); return 0; } case VIDIOCGAUDIO: { diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 9962c43c7..f0575fb2c 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -89,8 +89,7 @@ static inline int fmi_setfreq(struct fmi_device *dev) outbits(16, RSF16_ENCODE(freq), myport); outbits(8, 0xC0, myport); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/7); + msleep(143); /* was schedule_timeout(HZ/7) */ up(&lock); if (dev->curvol) fmi_unmute(myport); return 0; @@ -107,8 +106,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); outb(val | 0x10, myport); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/7); + msleep(143); /* was schedule_timeout(HZ/7) */ res = (int)inb(myport+1); outb(val, myport); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index aa49c8e5c..7e980d15f 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -55,19 +55,6 @@ static int radio_nr = -1; #define RSF16_MINFREQ 87*16000 #define RSF16_MAXFREQ 108*16000 -/* from radio-aimslab */ -static void sleep_delay(unsigned long n) -{ - unsigned d=n/(1000000U/HZ); - if (!d) - udelay(n); - else - { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(d); - } -} - static inline void wait(int n,int port) { for (;n;--n) inb(port); @@ -153,7 +140,7 @@ static int fmr2_setfreq(struct fmr2_device *dev) fmr2_unmute(port); /* wait 0.11 sec */ - sleep_delay(110000LU); + msleep(110); /* NOTE if mute this stop radio you must set freq on unmute */ diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index db5270b73..9332b9c8b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -9,8 +9,13 @@ comment "Video Adapters" config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && SOUND + depends on VIDEO_DEV && PCI && I2C select I2C_ALGOBIT + select FW_LOADER + select VIDEO_BTCX + select VIDEO_BUF + select VIDEO_IR + select VIDEO_TUNER ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in @@ -155,7 +160,7 @@ config VIDEO_STRADIS config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C_ALGOBIT help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega @@ -214,8 +219,8 @@ config VIDEO_ZR36120 module will be called zr36120. config VIDEO_MEYE - tristate "Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)" - depends on VIDEO_DEV && SONYPI && !HIGHMEM64G + tristate "Sony Vaio Picturebook Motion Eye Video For Linux" + depends on VIDEO_DEV && PCI && SONYPI ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in @@ -230,6 +235,9 @@ config VIDEO_MEYE config VIDEO_SAA7134 tristate "Philips SAA7134 support" depends on VIDEO_DEV && PCI && I2C + select VIDEO_BUF + select VIDEO_IR + select VIDEO_TUNER ---help--- This is a video4linux driver for Philips SAA7130/7134 based TV cards. @@ -237,10 +245,18 @@ config VIDEO_SAA7134 To compile this driver as a module, choose M here: the module will be called saa7134. +config VIDEO_SAA7134_DVB + tristate "DVB Support for saa7134 based TV cards" + depends on VIDEO_SAA7134 && DVB_CORE && BROKEN + ---help--- + This adds support for DVB cards based on the + Philips saa7134 chip. + config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" depends on VIDEO_DEV && PCI select VIDEO_SAA7146_VV + select VIDEO_TUNER ---help--- This is a video4linux driver for the 'Multimedia eXtension Board' TV card by Siemens-Nixdorf. @@ -287,7 +303,11 @@ config VIDEO_HEXIUM_GEMINI config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C_ALGOBIT && EXPERIMENTAL + depends on VIDEO_DEV && PCI && EXPERIMENTAL + select I2C_ALGOBIT + select VIDEO_BTCX + select VIDEO_BUF + select VIDEO_TUNER ---help--- This is a video4linux driver for Conexant 2388x based TV cards. @@ -295,6 +315,14 @@ config VIDEO_CX88 To compile this driver as a module, choose M here: the module will be called cx8800 +config VIDEO_CX88_DVB + tristate "DVB Support for cx2388x based TV cards" + depends on VIDEO_CX88 && DVB_CORE && BROKEN + select VIDEO_BUF_DVB + ---help--- + This adds support for DVB cards based on the + Connexant 2388x chip. + config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" depends on VIDEO_DEV && I2C @@ -306,5 +334,18 @@ config VIDEO_OVCAMCHIP To compile this driver as a module, choose M here: the module will be called ovcamchip -endmenu +config VIDEO_M32R_AR + tristate "AR devices" + depends on M32R + ---help--- + This is a video4linux driver for the Renesas AR (Artificial Retina) + camera module. +config VIDEO_M32R_AR_M64278 + tristate "Use Colour AR module M64278(VGA)" + depends on VIDEO_M32R_AR + ---help--- + Say Y here to use the Renesas M64278E-800 camera module, + which supports VGA(640x480 pixcels) size of images. + +endmenu diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 6a14ce96f..7982c2ed1 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -46,4 +46,9 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o obj-$(CONFIG_VIDEO_BUF) += video-buf.o +obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o + +obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o + +EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 16bfdb9ec..74fefc2df 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -156,6 +156,22 @@ adv7175_write_block (struct i2c_client *client, return ret; } +static void +set_subcarrier_freq (struct i2c_client *client, + int pass_through) +{ + /* for some reason pass_through NTSC needs + * a different sub-carrier freq to remain stable. */ + if(pass_through) + adv7175_write(client, 0x02, 0x00); + else + adv7175_write(client, 0x02, 0x55); + + adv7175_write(client, 0x03, 0x55); + adv7175_write(client, 0x04, 0x55); + adv7175_write(client, 0x05, 0x25); +} + #ifdef ENCODER_DUMP static void dump (struct i2c_client *client) @@ -322,6 +338,10 @@ adv7175_command (struct i2c_client *client, case 0: adv7175_write(client, 0x01, 0x00); + + if (encoder->norm == VIDEO_MODE_NTSC) + set_subcarrier_freq(client, 1); + adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ if (encoder->norm == VIDEO_MODE_SECAM) adv7175_write(client, 0x0d, 0x49); // Disable genlock @@ -334,6 +354,10 @@ adv7175_command (struct i2c_client *client, case 1: adv7175_write(client, 0x01, 0x00); + + if (encoder->norm == VIDEO_MODE_NTSC) + set_subcarrier_freq(client, 0); + adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ adv7175_write(client, 0x0d, 0x49); adv7175_write(client, 0x07, TR0MODE | TR0RST); @@ -343,6 +367,10 @@ adv7175_command (struct i2c_client *client, case 2: adv7175_write(client, 0x01, 0x80); + + if (encoder->norm == VIDEO_MODE_NTSC) + set_subcarrier_freq(client, 0); + adv7175_write(client, 0x0d, 0x49); adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); diff --git a/drivers/media/video/bt848.h b/drivers/media/video/bt848.h index a1a3a0dad..0bcd95303 100644 --- a/drivers/media/video/bt848.h +++ b/drivers/media/video/bt848.h @@ -1,4 +1,4 @@ -/* +/* bt848.h - Bt848 register offsets Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -22,10 +22,10 @@ #define _BT848_H_ #ifndef PCI_VENDOR_ID_BROOKTREE -#define PCI_VENDOR_ID_BROOKTREE 0x109e +#define PCI_VENDOR_ID_BROOKTREE 0x109e #endif #ifndef PCI_DEVICE_ID_BT848 -#define PCI_DEVICE_ID_BT848 0x350 +#define PCI_DEVICE_ID_BT848 0x350 #endif #ifndef PCI_DEVICE_ID_BT849 #define PCI_DEVICE_ID_BT849 0x351 @@ -50,7 +50,7 @@ #define BT848_DSTATUS_LOF (1<<1) #define BT848_DSTATUS_COF (1<<0) -#define BT848_IFORM 0x004 +#define BT848_IFORM 0x004 #define BT848_IFORM_HACTIVE (1<<7) #define BT848_IFORM_MUXSEL (3<<5) #define BT848_IFORM_MUX0 (2<<5) @@ -71,7 +71,7 @@ #define BT848_IFORM_AUTO 0 #define BT848_IFORM_NORM 7 -#define BT848_TDEC 0x008 +#define BT848_TDEC 0x008 #define BT848_TDEC_DEC_FIELD (1<<7) #define BT848_TDEC_FLDALIGN (1<<6) #define BT848_TDEC_DEC_RAT (0x1f) diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index 3a0320ecf..6f735d43b 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c @@ -1,4 +1,6 @@ /* + $Id: btcx-risc.c,v 1.4 2004/11/07 13:17:14 kraxel Exp $ + btcx-risc.c bt848/bt878/cx2388x risc code generator. @@ -36,7 +38,7 @@ MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); static unsigned int debug = 0; -MODULE_PARM(debug,"i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)"); /* ---------------------------------------------------------- */ @@ -187,7 +189,7 @@ btcx_calc_skips(int line, int width, unsigned int *maxy, { unsigned int clip,skip; int end,maxline; - + skip=0; maxline = 9999; for (clip = 0; clip < nclips; clip++) { @@ -197,7 +199,7 @@ btcx_calc_skips(int line, int width, unsigned int *maxy, continue; if (clips[clip].c.left > (signed)width) break; - + /* vertical range */ if (line > clips[clip].c.top+clips[clip].c.height-1) continue; diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h index 49daaadb0..41f60395a 100644 --- a/drivers/media/video/btcx-risc.h +++ b/drivers/media/video/btcx-risc.h @@ -1,4 +1,6 @@ - +/* + * $Id: btcx-risc.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $ + */ struct btcx_riscmem { unsigned int size; u32 *cpu; diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 7ea762f35..6c119fd6e 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1,4 +1,6 @@ /* + $Id: bttv-cards.c,v 1.32 2004/11/07 13:17:14 kraxel Exp $ + bttv-cards.c this file has configuration informations - card-specific stuff @@ -31,7 +33,7 @@ #include #include #include -#ifdef CONFIG_FW_LOADER +#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) # include #endif @@ -74,6 +76,9 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input); static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input); static void picolo_tetra_init(struct bttv *btv); +static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); +static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -101,53 +106,31 @@ static unsigned int audioall = UNSET; static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET }; /* insmod options */ -MODULE_PARM(triton1,"i"); +module_param(triton1, int, 0444); +module_param(vsfx, int, 0444); +module_param(no_overlay, int, 0444); +module_param(latency, int, 0444); +module_param(gpiomask, int, 0444); +module_param(audioall, int, 0444); +module_param(autoload, int, 0444); + +module_param_array(card, int, NULL, 0444); +module_param_array(pll, int, NULL, 0444); +module_param_array(tuner, int, NULL, 0444); +module_param_array(svhs, int, NULL, 0444); +module_param_array(remote, int, NULL, 0444); +module_param_array(audiomux, int, NULL, 0444); + MODULE_PARM_DESC(triton1,"set ETBF pci config bit " "[enable bug compatibility for triton1 + others]"); -MODULE_PARM(vsfx,"i"); MODULE_PARM_DESC(vsfx,"set VSFX pci config bit " "[yet another chipset flaw workaround]"); -MODULE_PARM(no_overlay,"i"); -MODULE_PARM(latency,"i"); MODULE_PARM_DESC(latency,"pci latency timer"); -MODULE_PARM(card,"1-" __stringify(BTTV_MAX) "i"); MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); -MODULE_PARM(pll,"1-" __stringify(BTTV_MAX) "i"); MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); -MODULE_PARM(tuner,"1-" __stringify(BTTV_MAX) "i"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); -MODULE_PARM(autoload,"i"); MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); -MODULE_PARM(svhs,"1-" __stringify(BTTV_MAX) "i"); -MODULE_PARM(remote,"1-" __stringify(BTTV_MAX) "i"); - -MODULE_PARM(gpiomask,"i"); -MODULE_PARM(audioall,"i"); -MODULE_PARM(audiomux,"1-6i"); - -/* kernel args */ -#ifndef MODULE -static int __init p_card(char *str) { return bttv_parse(str,BTTV_MAX,card); } -static int __init p_pll(char *str) { return bttv_parse(str,BTTV_MAX,pll); } -static int __init p_tuner(char *str) { return bttv_parse(str,BTTV_MAX,tuner); } -__setup("bttv.card=", p_card); -__setup("bttv.pll=", p_pll); -__setup("bttv.tuner=", p_tuner); - -int __init bttv_parse(char *str, int max, int *vals) -{ - int i,number,res = 2; - - for (i = 0; res == 2 && i < max; i++) { - res = get_option(&str,&number); - if (res) - vals[i] = number; - } - return 1; -} -#endif - /* ----------------------------------------------------------------------- */ /* list of card IDs for bt878+ cards */ @@ -170,6 +153,7 @@ static struct CARD { { 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0x6607107d, BTTV_WINFASTVC100, "Leadtek WinFast VC 100" }, + { 0x6609107d, BTTV_WINFAST2000, "Leadtek TV 2000 XP" }, { 0x263610b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x264510b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, @@ -178,7 +162,6 @@ static struct CARD { { 0xd01810fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, { 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" }, - { 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" }, // some cards ship with byteswapped IDs ... { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, @@ -186,8 +169,9 @@ static struct CARD { { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, { 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, { 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" }, - + { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, + { 0xa005144f, BTTV_MAGICTVIEW063, "CPH06X TView99-Card" }, { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" }, @@ -204,7 +188,7 @@ static struct CARD { { 0x1118153b, BTTV_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, { 0x1119153b, BTTV_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, { 0x111a153b, BTTV_TERRATVALUE, "Terratec TValue (Temic PAL I)" }, - + { 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV Radio+" }, { 0x1127153b, BTTV_TERRATV, "Terratec TV+ (V1.05)" }, // clashes with FlyVideo @@ -224,6 +208,7 @@ static struct CARD { { 0x1431aa00, BTTV_PV143, "Provideo PV143B" }, { 0x1432aa00, BTTV_PV143, "Provideo PV143C" }, { 0x1433aa00, BTTV_PV143, "Provideo PV143D" }, + { 0x1433aa03, BTTV_PV143, "Security Eyes" }, { 0x1460aa00, BTTV_PV150, "Provideo PV150A-1" }, { 0x1461aa01, BTTV_PV150, "Provideo PV150A-2" }, @@ -239,7 +224,7 @@ static struct CARD { { 0xa1550000, BTTV_IVC200, "IVC-200" }, { 0xa1550001, BTTV_IVC200, "IVC-200" }, { 0xa1550002, BTTV_IVC200, "IVC-200" }, - { 0xa1550003, BTTV_IVC200, "IVC-200" }, + { 0xa1550003, BTTV_IVC200, "IVC-200" }, { 0xa1550100, BTTV_IVC200, "IVC-200G" }, { 0xa1550101, BTTV_IVC200, "IVC-200G" }, { 0xa1550102, BTTV_IVC200, "IVC-200G" }, @@ -260,11 +245,12 @@ static struct CARD { { 0xa182ff0d, BTTV_IVC120, "IVC-120G" }, { 0xa182ff0e, BTTV_IVC120, "IVC-120G" }, { 0xa182ff0f, BTTV_IVC120, "IVC-120G" }, - + { 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" }, { 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" }, - + { 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, + { 0xa0501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, { 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, { 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, @@ -294,15 +280,17 @@ static struct CARD { // likely broken, vendor id doesn't match the other magic views ... //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, - + // DVB cards (using pci function .1 for mpeg data xfer) { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, - { 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" }, + { 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T" }, + { 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" }, { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" }, { 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, { 0x07711461, BTTV_AVDVBT_771, "AVermedia DVB-T 771" }, - + { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DVICO FusionHDTV DVB-T Lite" }, + { 0, -1, NULL } }; @@ -693,7 +681,7 @@ struct tvcard bttv_tvcards[] = { 10000 : ext. Video audio input 20000 : TV Mono a0000 : TV Mono/2 - 1a0000 : TV Stereo + 1a0000 : TV Stereo 30000 : Radio 40000 : Mute */ @@ -1108,7 +1096,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 5, },{ - /* This is the ultimate cheapo capture card + /* This is the ultimate cheapo capture card * just a BT848A on a small PCB! * Steve Hosgood */ .name = "GrandTec 'Grand Video Capture' (Bt848)", @@ -1179,7 +1167,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, },{ /* Miguel Angel Alvarez - new Easy TV BT878 version (model CPH061) + new Easy TV BT878 version (model CPH061) special thanks to Informatica Mieres for providing the card */ .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", .video_inputs = 3, @@ -1383,7 +1371,7 @@ struct tvcard bttv_tvcards[] = { },{ .name = "Powercolor MTV878/ MTV878R/ MTV878F", .video_inputs = 3, - .audio_inputs = 2, + .audio_inputs = 2, .tuner = 0, .svhs = 2, .gpiomask = 0x1C800F, // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset @@ -1561,7 +1549,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, },{ - + /* ---- card 0x58 ---------------------------------- */ .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ .video_inputs = 2, @@ -1654,13 +1642,14 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .no_msp34xx = 1, .no_tda9875 = 1, - .no_tda7432 = 1, + .no_tda7432 = 1, .gpiomask = 0x01, .audiomux = { 0, 0, 0, 0, 1 }, .muxsel = { 3, 0, 1, 2}, - .needs_tvaudio = 0, + .needs_tvaudio = 0, .pll = PLL_28, .no_gpioirq = 1, + .has_dvb = 1, },{ .name = "Formac ProTV II (bt878)", .video_inputs = 4, @@ -1670,7 +1659,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 2, // TV, Comp1, Composite over SVID con, SVID .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 2, 0, 0, 0 }, + .audiomux = { 2, 2, 0, 0, 0 }, .pll = PLL_28, .has_radio = 1, .tuner_type = TUNER_PHILIPS_PAL, @@ -1755,7 +1744,7 @@ struct tvcard bttv_tvcards[] = { /* Notes: - card lacks subsystem ID - stereo variant w/ daughter board with tda9874a @0xb0 - - Audio Routing: + - Audio Routing: always from tda9874 independent of GPIO (?) external line in: unknown - Other chips: em78p156elp @ 0x96 (probably IR remote control) @@ -1839,7 +1828,7 @@ struct tvcard bttv_tvcards[] = { .audio_inputs = 0, .tuner = -1, /* card has no tuner */ .svhs = 3, - .gpiomask = 0x00, + .gpiomask = 0x00, .muxsel = { 2, 3, 1, 0}, .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, @@ -1912,7 +1901,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, .gpiomask = 0x00, - .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, .muxsel_hook = ivc120_muxsel, .pll = PLL_28, @@ -2075,9 +2064,98 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .has_dvb = 1, .no_gpioirq = 1, -#if 0 /* untested */ .has_remote = 1, -#endif +},{ + /* ---- card 0x7c ---------------------------------- */ + /* Matt Jesson */ + /* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */ + .name = "AverMedia AverTV DVB-T 761", + .video_inputs = 2, + .tuner = -1, + .svhs = 1, + .muxsel = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = -1, + .has_dvb = 1, + .no_gpioirq = 1, + .has_remote = 1, +},{ + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SQ", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel_hook = sigmaSQ_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, +},{ + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SLC", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2 }, + .muxsel_hook = sigmaSLC_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, +},{ + /* BTTV_APAC_VIEWCOMP */ + /* Attila Kondoros */ + /* bt878 TV + FM 0x00000000 subsystem ID */ + .name = "APAC Viewcomp 878(AMAX)", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 0xFF, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 0, 0, 0, 10}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ + .has_radio = 1, /* not every card has radio */ +},{ + + /* ---- card 0x80 ---------------------------------- */ + /* Chris Pascoe */ + .name = "DVICO FusionHDTV DVB-T Lite", + .tuner = -1, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .no_video = 1, + .has_dvb = 1, + .tuner_type = -1, +},{ + /* Steven */ + .name = "V-Gear MyVCD", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = {2, 3, 1, 0}, + .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .has_radio = 0, + // .has_remote = 1, }}; const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -2106,7 +2184,7 @@ void __devinit bttv_idcard(struct bttv *btv) for (type = -1, i = 0; cards[i].id != 0; i++) if (cards[i].id == btv->cardid) type = i; - + if (type != -1) { /* found it */ printk(KERN_INFO "bttv%d: detected: %s [card=%d], " @@ -2123,12 +2201,12 @@ void __devinit bttv_idcard(struct bttv *btv) printk(KERN_DEBUG "please mail id, board name and " "the correct card= insmod option to kraxel@bytesex.org\n"); } - } + } /* let the user override the autodetected type */ if (card[btv->c.nr] < bttv_num_tvcards) btv->c.type=card[btv->c.nr]; - + /* print which card config we are using */ printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type, @@ -2168,7 +2246,7 @@ void __devinit bttv_idcard(struct bttv *btv) void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) { int type = -1; - + if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13)) type = BTTV_MODTEC_205; else if (0 == strncmp(eeprom_data+20,"Picolo",7)) @@ -2184,7 +2262,7 @@ void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) } static void flyvideo_gpio(struct bttv *btv) -{ +{ int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; int tuner=-1,ttype; @@ -2198,10 +2276,10 @@ static void flyvideo_gpio(struct bttv *btv) // CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1. // GPIO14-12: n.c. // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878) - + // lowest 3 bytes are remote control codes (no handshake needed) // xxxFFF: No remote control chip soldered - // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered + // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered // Note: Some bits are Audio_Mask ! ttype=(gpio&0x0f0000)>>16; @@ -2229,18 +2307,18 @@ static void flyvideo_gpio(struct bttv *btv) is_lr90 = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only) // gpio & 0x001000 // output bit for audio routing - if(is_capture_only) - tuner=4; // No tuner present + if(is_capture_only) + tuner=4; // No tuner present - printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", - btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); + printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", + btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n", - btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", + btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", is_capture_only?"yes":"no "); if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through btv->tuner_type = tuner; - btv->has_radio = has_radio; + btv->has_radio = has_radio; // LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 @@ -2339,13 +2417,13 @@ static void init_ids_eagle(struct bttv *btv) { gpio_inout(0xffffff,0xFFFF37); gpio_write(0x200020); - + /* flash strobe inverter ?! */ gpio_write(0x200024); - + /* switch sync drive off */ gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); - + /* set BT848 muxel to 2 */ btaor((2)<<5, ~(2<<5), BT848_IFORM); } @@ -2405,6 +2483,19 @@ static void init_lmlbt4x(struct bttv *btv) gpio_write(0x000000); } +static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 8; + gpio_inout( 0xf, 0xf ); + gpio_bits( 0xf, inmux ); +} + +static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 4; + gpio_inout( 3<<9, 3<<9 ); + gpio_bits( 3<<9, inmux<<9 ); +} /* ----------------------------------------------------------------------- */ @@ -2421,7 +2512,7 @@ void bttv_reset_audio(struct bttv *btv) */ if (btv->id != 878) return; - + if (bttv_debug) printk("bttv%d: BT878A ARESET\n",btv->c.nr); btwrite((1<<7), 0x058); @@ -2456,6 +2547,7 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { + int tda9887; btv->tuner_type = -1; if (BTTV_UNKNOWN == btv->c.type) { @@ -2467,7 +2559,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_MIRO: case BTTV_MIROPRO: case BTTV_PINNACLE: - case BTTV_PINNACLEPRO: + case BTTV_PINNACLEPRO: /* miro/pinnacle */ miro_pinnacle_gpio(btv); break; @@ -2591,7 +2683,7 @@ void __devinit bttv_init_card2(struct bttv *btv) /* tuner configuration (from card list / autodetect / insmod option) */ if (UNSET != bttv_tvcards[btv->c.type].tuner_type) - if(UNSET == btv->tuner_type) + if(UNSET == btv->tuner_type) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; @@ -2623,57 +2715,52 @@ void __devinit bttv_init_card2(struct bttv *btv) boot_bt832(btv); } + if (!autoload) + return; + /* try to detect audio/fader chips */ if (!bttv_tvcards[btv->c.type].no_msp34xx && - bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) { - if (autoload) - request_module("msp3400"); - } + bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) + request_module("msp3400"); if (bttv_tvcards[btv->c.type].msp34xx_alt && - bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) { - if (autoload) - request_module("msp3400"); - } + bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) + request_module("msp3400"); if (!bttv_tvcards[btv->c.type].no_tda9875 && - bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { - if (autoload) - request_module("tda9875"); - } + bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) + request_module("tda9875"); - if (!bttv_tvcards[btv->c.type].no_tda7432 && - bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { - if (autoload) - request_module("tda7432"); - } + if (!bttv_tvcards[btv->c.type].no_tda7432 && + bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) + request_module("tda7432"); - if (bttv_tvcards[btv->c.type].needs_tvaudio) { - if (autoload) - request_module("tvaudio"); - } + if (bttv_tvcards[btv->c.type].needs_tvaudio) + request_module("tvaudio"); /* tuner modules */ - if (btv->pinnacle_id != UNSET) { - if (autoload) - request_module("tda9887"); - } - if (btv->tuner_type != UNSET) { - if (autoload) - request_module("tuner"); - } + tda9887 = 0; + if (btv->pinnacle_id != UNSET) + tda9887 = 1; + if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && + bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) + tda9887 = 1; + if (tda9887) + request_module("tda9887"); + if (btv->tuner_type != UNSET) + request_module("tuner"); } /* ----------------------------------------------------------------------- */ /* some hauppauge specific stuff */ -static struct HAUPPAUGE_TUNER +static struct HAUPPAUGE_TUNER { int id; char *name; -} -hauppauge_tuner[] __devinitdata = +} +hauppauge_tuner[] __devinitdata = { { TUNER_ABSENT, "" }, { TUNER_ABSENT, "External" }, @@ -2723,7 +2810,7 @@ hauppauge_tuner[] __devinitdata = { TUNER_ABSENT, "Philips TD1536D_FH_44"}, { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"}, { TUNER_LG_PAL_FM, "LG TPI8PSB01D"}, - { TUNER_LG_PAL, "LG TPI8PSB11D"}, + { TUNER_LG_PAL, "LG TPI8PSB11D"}, { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"}, { TUNER_LG_PAL_I, "LG TAPC-I701D"} }; @@ -2763,16 +2850,17 @@ static void __devinit hauppauge_eeprom(struct bttv *btv) model = eeprom_data[12] << 8 | eeprom_data[11]; tuner = eeprom_data[9]; radio = eeprom_data[blk2-1] & 0x01; - + if (tuner < ARRAY_SIZE(hauppauge_tuner)) btv->tuner_type = hauppauge_tuner[tuner].id; if (radio) btv->has_radio = 1; - + if (bttv_verbose) printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, " "tuner=%s (%d), radio=%s\n", - btv->c.nr, model, hauppauge_tuner[tuner].name, + btv->c.nr, model, (tuner < ARRAY_SIZE(hauppauge_tuner) + ? hauppauge_tuner[tuner].name : "?"), btv->tuner_type, radio ? "yes" : "no"); } @@ -2804,7 +2892,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) btv->has_matchbox = 0; } return 0; -} +} /* ----------------------------------------------------------------------- */ @@ -2831,7 +2919,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); gpio_write(0); udelay(PVR_GPIO_DELAY); - + gpio_write(BTTV_ALT_NCONFIG); udelay(PVR_GPIO_DELAY); @@ -2841,7 +2929,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) gpio_bits(BTTV_ALT_DCLK,0); if (bits & 0x01) gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA); - else + else gpio_bits(BTTV_ALT_DATA,0); gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); bits >>= 1; @@ -2849,7 +2937,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) } gpio_bits(BTTV_ALT_DCLK,0); udelay(PVR_GPIO_DELAY); - + /* begin Altera init loop (Not necessary,but doesn't hurt) */ for (i = 0 ; i < 30 ; i++) { gpio_bits(BTTV_ALT_DCLK,0); @@ -2859,40 +2947,6 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) return 0; } -#ifndef CONFIG_FW_LOADER -/* old 2.4.x way -- via soundcore's mod_firmware_load */ - -static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf"; -MODULE_PARM(firm_altera,"s"); -MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware " - "(driver CD => unzip pvr45xxx.exe => hcwamc.rbf)"); - -extern int mod_firmware_load(const char *fn, char **fp); - -int __devinit pvr_boot(struct bttv *btv) -{ - u32 microlen; - u8 *micro; - int result; - - microlen = mod_firmware_load(firm_altera, (char**) µ); - if (!microlen) { - printk(KERN_WARNING "bttv%d: altera firmware not found [%s]\n", - btv->c.nr, firm_altera); - return -1; - } - - printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n", - btv->c.nr, firm_altera); - result = pvr_altera_load(btv, micro, microlen); - printk(KERN_INFO "bttv%d: ... upload %s\n", - btv->c.nr, (result < 0) ? "failed" : "ok"); - vfree(micro); - return result; -} -#else -/* new 2.5.x way -- via hotplug firmware loader */ - int __devinit pvr_boot(struct bttv *btv) { const struct firmware *fw_entry; @@ -2909,8 +2963,7 @@ int __devinit pvr_boot(struct bttv *btv) btv->c.nr, (rc < 0) ? "failed" : "ok"); release_firmware(fw_entry); return rc; -} -#endif +} /* ----------------------------------------------------------------------- */ /* some osprey specific stuff */ @@ -2920,7 +2973,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) int i = 0; unsigned char *ee = eeprom_data; unsigned long serial = 0; - + if (btv->c.type == 0) { /* this might be an antique... check for MMAC label in eeprom */ if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { @@ -2936,7 +2989,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) } else { unsigned short type; int offset = 4*16; - + for(; offset < 8*16; offset += 16) { unsigned short checksum = 0; /* verify the checksum */ @@ -2947,13 +3000,13 @@ static void __devinit osprey_eeprom(struct bttv *btv) break; } } - + if (offset >= 8*16) return; /* found a valid descriptor */ type = (ee[offset+4]<<8) | (ee[offset+5]); - + switch(type) { /* 848 based */ @@ -2963,7 +3016,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) case 0x0005: btv->c.type = BTTV_OSPREY101_848; break; - + /* 878 based */ case 0x0012: case 0x0013: @@ -3011,10 +3064,10 @@ static void __devinit osprey_eeprom(struct bttv *btv) | (ee[offset+8] << 8) | (ee[offset+9]); } - + printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); -} +} /* ----------------------------------------------------------------------- */ /* AVermedia specific stuff, from bktr_card.c */ @@ -3056,7 +3109,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv) if (tuner_make == 1) if(tuner_format <=9) tuner = tuner_1_table[tuner_format]; - + printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=", btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]); if(tuner) { @@ -3146,8 +3199,8 @@ static void __devinit boot_bt832(struct bttv *btv) /* ----------------------------------------------------------------------- */ /* Imagenation L-Model PXC200 Framegrabber */ -/* This is basically the same procedure as - * used by Alessandro Rubini in his pxc200 +/* This is basically the same procedure as + * used by Alessandro Rubini in his pxc200 * driver, but using BTTV functions */ static void __devinit init_PXC200(struct bttv *btv) @@ -3158,13 +3211,13 @@ static void __devinit init_PXC200(struct bttv *btv) unsigned int i; int tmp; u32 val; - + /* Initialise GPIO-connevted stuff */ gpio_inout(0xffffff, (1<<13)); gpio_write(0); udelay(3); gpio_write(1<<13); - /* GPIO inputs are pulled up, so no need to drive + /* GPIO inputs are pulled up, so no need to drive * reset pin any longer */ gpio_bits(0xffffff, 0); if (bttv_gpio) @@ -3179,16 +3232,16 @@ static void __devinit init_PXC200(struct bttv *btv) */ btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC); - + /* Initialise MAX517 DAC */ printk(KERN_INFO "Setting DAC reference voltage level ...\n"); bttv_I2CWrite(btv,0x5E,0,0x80,1); - + /* Initialise 12C508 PIC */ - /* The I2CWrite and I2CRead commmands are actually to the + /* The I2CWrite and I2CRead commmands are actually to the * same chips - but the R/W bit is included in the address * argument so the numbers are different */ - + printk(KERN_INFO "Initialising 12C508 PIC chip ...\n"); @@ -3196,7 +3249,7 @@ static void __devinit init_PXC200(struct bttv *btv) val = btread(BT848_GPIO_DMA_CTL); val |= BT848_GPIO_DMA_CTL_GPCLKMODE; btwrite(val, BT848_GPIO_DMA_CTL); - + /* Then, push to 0 the reset pin long enough to reset the * * device same as above for the reset line, but not the same * value sent to the GPIO-connected stuff @@ -3308,7 +3361,7 @@ static int tea5757_read(struct bttv *btv) unsigned long timeout; int value = 0; int i; - + /* better safe than sorry */ gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we); @@ -3320,10 +3373,10 @@ static int tea5757_read(struct bttv *btv) if (bttv_gpio) bttv_gpio_tracking(btv,"tea5757 read"); - + bus_low(btv,btv->mbox_we); bus_low(btv,btv->mbox_clk); - + udelay(10); timeout= jiffies + HZ; @@ -3355,7 +3408,7 @@ static int tea5757_write(struct bttv *btv, int value) { int i; int reg = value; - + gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data); if (btv->mbox_ior) { @@ -3410,7 +3463,7 @@ void winview_audio(struct bttv *btv, struct video_audio *v, int set) v->flags |= VIDEO_AUDIO_VOLUME; return; } - + /* 32 levels logarithmic */ vol = 32 - ((v->volume>>11)); /* units */ @@ -3437,7 +3490,7 @@ void winview_audio(struct bttv *btv, struct video_audio *v, int set) data |= WINVIEW_PT2254_STROBE; data &= ~WINVIEW_PT2254_DATA; gpio_write(data); - udelay(10); + udelay(10); data &= ~WINVIEW_PT2254_STROBE; gpio_write(data); } @@ -3562,7 +3615,7 @@ static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) { int val = 0; - + if (set) { if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ val = 0x01; @@ -3697,7 +3750,7 @@ pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set) /* * Dariusz Kowalewski - * sound control for FlyVideo 2000S (with tda9874 decoder) + * sound control for FlyVideo 2000S (with tda9874 decoder) * based on pvbt878p9b_audio() - this is not tested, please fix!!! */ static void @@ -3880,13 +3933,13 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) * ivc120_muxsel [Added by Alan Garfield ] * * The IVC120G security card has 4 i2c controlled TDA8540 matrix - * swichers to provide 16 channels to MUX0. The TDA8540's have - * 4 indepedant outputs and as such the IVC120G also has the - * optional "Monitor Out" bus. This allows the card to be looking + * swichers to provide 16 channels to MUX0. The TDA8540's have + * 4 indepedant outputs and as such the IVC120G also has the + * optional "Monitor Out" bus. This allows the card to be looking * at one input while the monitor is looking at another. * * Since I've couldn't be bothered figuring out how to add an - * independant muxsel for the monitor bus, I've just set it to + * independant muxsel for the monitor bus, I've just set it to * whatever the card is looking at. * * OUT0 of the TDA8540's is connected to MUX0 (0x03) @@ -3911,12 +3964,12 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input) static void ivc120_muxsel(struct bttv *btv, unsigned int input) { // Simple maths - int key = input % 4; + int key = input % 4; int matrix = input / 4; - + dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n", btv->c.nr, input, matrix, key); - + // Handles the input selection on the TDA8540's bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00, ((matrix == 3) ? (key | key << 2) : 0x00), 1); @@ -3926,22 +3979,102 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input) ((matrix == 1) ? (key | key << 2) : 0x00), 1); bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00, ((matrix == 2) ? (key | key << 2) : 0x00), 1); - + // Handles the output enables on the TDA8540's bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02, ((matrix == 3) ? 0x03 : 0x00), 1); // 13 - 16 bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02, ((matrix == 0) ? 0x03 : 0x00), 1); // 1-4 bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02, - ((matrix == 1) ? 0x03 : 0x00), 1); // 5-8 + ((matrix == 1) ? 0x03 : 0x00), 1); // 5-8 bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02, ((matrix == 2) ? 0x03 : 0x00), 1); // 9-12 - + // Selects MUX0 for input on the 878 btaor((0)<<5, ~(3<<5), BT848_IFORM); } +/* PXC200 muxsel helper + * luke@syseng.anu.edu.au + * another transplant + * from Alessandro Rubini (rubini@linux.it) + * + * There are 4 kinds of cards: + * PXC200L which is bt848 + * PXC200F which is bt848 with PIC controlling mux + * PXC200AL which is bt878 + * PXC200AF which is bt878 with PIC controlling mux + */ +#define PX_CFG_PXC200F 0x01 +#define PX_FLAG_PXC200A 0x00001000 /* a pxc200A is bt-878 based */ +#define PX_I2C_PIC 0x0f +#define PX_PXC200A_CARDID 0x200a1295 +#define PX_I2C_CMD_CFG 0x00 + +static void PXC200_muxsel(struct bttv *btv, unsigned int input) +{ + int rc; + long mux; + int bitmask; + unsigned char buf[2]; + + /* Read PIC config to determine if this is a PXC200F */ + /* PX_I2C_CMD_CFG*/ + buf[0]=0; + buf[1]=0; + rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1); + if (rc) { + printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc); + /* not PXC ? do nothing */ + return; + } + + rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL); + if (!(rc & PX_CFG_PXC200F)) { + printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc); + return; + } + + + /* The multiplexer in the 200F is handled by the GPIO port */ + /* get correct mapping between inputs */ + /* mux = bttv_tvcards[btv->type].muxsel[input] & 3; */ + /* ** not needed!? */ + mux = input; + + /* make sure output pins are enabled */ + /* bitmask=0x30f; */ + bitmask=0x302; + /* check whether we have a PXC200A */ + if (btv->cardid == PX_PXC200A_CARDID) { + bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ + bitmask |= 7<<4; /* the DAC */ + } + btwrite(bitmask, BT848_GPIO_OUT_EN); + + bitmask = btread(BT848_GPIO_DATA); + if (btv->cardid == PX_PXC200A_CARDID) + bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); + else /* older device */ + bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); + btwrite(bitmask,BT848_GPIO_DATA); + + /* + * Was "to be safe, set the bt848 to input 0" + * Actually, since it's ok at load time, better not messing + * with these bits (on PXC200AF you need to set mux 2 here) + * + * needed because bttv-driver sets mux before calling this function + */ + if (btv->cardid == PX_PXC200A_CARDID) + btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); + else /* older device */ + btand(~BT848_IFORM_MUXSEL,BT848_IFORM); + + printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux); +} + /* ----------------------------------------------------------------------- */ /* motherboard chipset specific stuff */ @@ -4028,86 +4161,6 @@ int __devinit bttv_handle_chipset(struct bttv *btv) } -/* PXC200 muxsel helper - * luke@syseng.anu.edu.au - * another transplant - * from Alessandro Rubini (rubini@linux.it) - * - * There are 4 kinds of cards: - * PXC200L which is bt848 - * PXC200F which is bt848 with PIC controlling mux - * PXC200AL which is bt878 - * PXC200AF which is bt878 with PIC controlling mux - */ -#define PX_CFG_PXC200F 0x01 -#define PX_FLAG_PXC200A 0x00001000 /* a pxc200A is bt-878 based */ -#define PX_I2C_PIC 0x0f -#define PX_PXC200A_CARDID 0x200a1295 -#define PX_I2C_CMD_CFG 0x00 - -static void PXC200_muxsel(struct bttv *btv, unsigned int input) -{ - int rc; - long mux; - int bitmask; - unsigned char buf[2]; - - /* Read PIC config to determine if this is a PXC200F */ - /* PX_I2C_CMD_CFG*/ - buf[0]=0; - buf[1]=0; - rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1); - if (rc) { - printk(KERN_DEBUG "bttv%d: PXC200_muxsel: pic cfg write failed:%d\n", btv->c.nr,rc); - /* not PXC ? do nothing */ - return; - } - - rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL); - if (!(rc & PX_CFG_PXC200F)) { - printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc); - return; - } - - - /* The multiplexer in the 200F is handled by the GPIO port */ - /* get correct mapping between inputs */ - /* mux = bttv_tvcards[btv->type].muxsel[input] & 3; */ - /* ** not needed!? */ - mux = input; - - /* make sure output pins are enabled */ - /* bitmask=0x30f; */ - bitmask=0x302; - /* check whether we have a PXC200A */ - if (btv->cardid == PX_PXC200A_CARDID) { - bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ - bitmask |= 7<<4; /* the DAC */ - } - btwrite(bitmask, BT848_GPIO_OUT_EN); - - bitmask = btread(BT848_GPIO_DATA); - if (btv->cardid == PX_PXC200A_CARDID) - bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); - else /* older device */ - bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); - btwrite(bitmask,BT848_GPIO_DATA); - - /* - * Was "to be safe, set the bt848 to input 0" - * Actually, since it's ok at load time, better not messing - * with these bits (on PXC200AF you need to set mux 2 here) - * - * needed because bttv-driver sets mux before calling this function - */ - if (btv->cardid == PX_PXC200A_CARDID) - btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); - else /* older device */ - btand(~BT848_IFORM_MUXSEL,BT848_IFORM); - - printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux); -} - /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index e7ffe1841..ab82636c1 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1,23 +1,25 @@ /* + $Id: bttv-driver.c,v 1.27 2004/11/07 14:44:59 kraxel Exp $ + bttv - Bt848 frame grabber driver - + Copyright (C) 1996,97,98 Ralph Metzler & Marcus Metzler (c) 1999-2002 Gerd Knorr - + some v4l2 code lines are taken from Justin's bttv2 driver which is (c) 2000 Justin Schoeman - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -75,63 +77,56 @@ static unsigned int vcr_hack = 0; static unsigned int irq_iswitch = 0; /* API features (turn on/off stuff for testing) */ -static unsigned int v4l2 = 1; +static unsigned int v4l2 = 1; /* insmod args */ -MODULE_PARM(radio,"1-" __stringify(BTTV_MAX) "i"); +module_param(bttv_verbose, int, 0644); +module_param(bttv_gpio, int, 0644); +module_param(bttv_debug, int, 0644); +module_param(irq_debug, int, 0644); +module_param(debug_latency, int, 0644); + +module_param(fdsr, int, 0444); +module_param(video_nr, int, 0444); +module_param(radio_nr, int, 0444); +module_param(vbi_nr, int, 0444); +module_param(gbuffers, int, 0444); +module_param(gbufsize, int, 0444); + +module_param(v4l2, int, 0644); +module_param(bigendian, int, 0644); +module_param(irq_iswitch, int, 0644); +module_param(combfilter, int, 0444); +module_param(lumafilter, int, 0444); +module_param(automute, int, 0444); +module_param(chroma_agc, int, 0444); +module_param(adc_crush, int, 0444); +module_param(whitecrush_upper, int, 0444); +module_param(whitecrush_lower, int, 0444); +module_param(vcr_hack, int, 0444); +module_param_array(radio, int, NULL, 0444); + MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); -MODULE_PARM(bigendian,"i"); MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); -MODULE_PARM(bttv_verbose,"i"); MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); -MODULE_PARM(bttv_gpio,"i"); MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); -MODULE_PARM(bttv_debug,"i"); MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); -MODULE_PARM(irq_debug,"i"); MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); -MODULE_PARM(gbuffers,"i"); MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); -MODULE_PARM(gbufsize,"i"); MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); - -MODULE_PARM(video_nr,"i"); -MODULE_PARM(radio_nr,"i"); -MODULE_PARM(vbi_nr,"i"); -MODULE_PARM(debug_latency,"i"); - -MODULE_PARM(fdsr,"i"); - -MODULE_PARM(combfilter,"i"); -MODULE_PARM(lumafilter,"i"); -MODULE_PARM(automute,"i"); MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)"); -MODULE_PARM(chroma_agc,"i"); MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); -MODULE_PARM(adc_crush,"i"); MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); -MODULE_PARM(whitecrush_upper,"i"); MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207"); -MODULE_PARM(whitecrush_lower,"i"); MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127"); -MODULE_PARM(vcr_hack,"i"); MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)"); -MODULE_PARM(irq_iswitch,"i"); MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); -MODULE_PARM(v4l2,"i"); - MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); MODULE_LICENSE("GPL"); -/* kernel args */ -#ifndef MODULE -static int __init p_radio(char *str) { return bttv_parse(str,BTTV_MAX,radio); } -__setup("bttv.radio=", p_radio); -#endif - /* ----------------------------------------------------------------------- */ /* sysfs */ @@ -192,7 +187,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { .sheight = 576, .totalwidth = 1135, .adelay = 0x7f, - .bdelay = 0x72, + .bdelay = 0x72, .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), .scaledtwidth = 1135, .hdelayx1 = 186, @@ -680,20 +675,20 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) /* ----------------------------------------------------------------------- */ /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */ -/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C - PLL_X = Reference pre-divider (0=1, 1=2) +/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C + PLL_X = Reference pre-divider (0=1, 1=2) PLL_C = Post divider (0=6, 1=4) - PLL_I = Integer input - PLL_F = Fractional input - - F_input = 28.636363 MHz: + PLL_I = Integer input + PLL_F = Fractional input + + F_input = 28.636363 MHz: PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0 */ static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) { unsigned char fl, fh, fi; - + /* prevent overflows */ fin/=4; fout/=4; @@ -743,9 +738,8 @@ static void set_pll(struct bttv *btv) for (i=0; i<10; i++) { /* Let other people run while the PLL stabilizes */ vprintk("."); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/50); - + msleep(10); + if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) { btwrite(0,BT848_DSTATUS); } else { @@ -808,7 +802,7 @@ static void bt848_bright(struct bttv *btv, int bright) static void bt848_hue(struct bttv *btv, int hue) { int value; - + btv->hue = hue; /* -128 to 127 */ @@ -819,9 +813,9 @@ static void bt848_hue(struct bttv *btv, int hue) static void bt848_contrast(struct bttv *btv, int cont) { int value,hibit; - + btv->contrast = cont; - + /* 0-511 */ value = (cont >> 7); hibit = (value >> 6) & 4; @@ -833,7 +827,7 @@ static void bt848_contrast(struct bttv *btv, int cont) static void bt848_sat(struct bttv *btv, int color) { int val_u,val_v,hibits; - + btv->saturation = color; /* 0-511 for the color */ @@ -975,11 +969,11 @@ static void set_input(struct bttv *btv, unsigned int input) { unsigned long flags; - + btv->input = input; if (irq_iswitch) { spin_lock_irqsave(&btv->s_lock,flags); - if (btv->curr.irqflags) { + if (btv->curr.frame_irq) { /* active capture -> delayed input switch */ btv->new_input = input; } else { @@ -992,6 +986,7 @@ set_input(struct bttv *btv, unsigned int input) audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? AUDIO_TUNER : AUDIO_EXTERN)); set_tvnorm(btv,btv->tvnorm); + i2c_vidiocschan(btv); } static void init_irqreg(struct bttv *btv) @@ -1019,7 +1014,7 @@ static void init_irqreg(struct bttv *btv) static void init_bt848(struct bttv *btv) { int val; - + if (bttv_tvcards[btv->c.type].no_video) { /* very basic init only */ init_irqreg(btv); @@ -1036,7 +1031,7 @@ static void init_bt848(struct bttv *btv) BT848_GPIO_DMA_CTL_PLTP1_16| BT848_GPIO_DMA_CTL_PLTP23_16| BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL_GPINTI, BT848_GPIO_DMA_CTL); val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; @@ -1051,11 +1046,6 @@ static void init_bt848(struct bttv *btv) btwrite(whitecrush_upper, BT848_WC_UP); btwrite(whitecrush_lower, BT848_WC_DOWN); - bt848_bright(btv, btv->bright); - bt848_hue(btv, btv->hue); - bt848_contrast(btv, btv->contrast); - bt848_sat(btv, btv->saturation); - if (btv->opt_lumafilter) { btwrite(0, BT848_E_CONTROL); btwrite(0, BT848_O_CONTROL); @@ -1064,6 +1054,11 @@ static void init_bt848(struct bttv *btv) btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL); } + bt848_bright(btv, btv->bright); + bt848_hue(btv, btv->hue); + bt848_contrast(btv, btv->contrast); + bt848_sat(btv, btv->saturation); + /* interrupt */ init_irqreg(btv); } @@ -1076,7 +1071,7 @@ void bttv_reinit_bt848(struct bttv *btv) printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr); spin_lock_irqsave(&btv->s_lock,flags); btv->errors=0; - bttv_set_dma(btv,0,0); + bttv_set_dma(btv,0); spin_unlock_irqrestore(&btv->s_lock,flags); init_bt848(btv); @@ -1088,7 +1083,7 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) { struct video_audio va; int i; - + for (i = 0; i < BTTV_CTLS; i++) if (bttv_ctls[i].id == c->id) break; @@ -1334,8 +1329,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, spin_lock_irqsave(&btv->s_lock,flags); old = btv->screen; btv->screen = new; - btv->curr.irqflags |= 1; - bttv_set_dma(btv, 0x03, btv->curr.irqflags); + btv->loop_irq |= 1; + bttv_set_dma(btv, 0x03); spin_unlock_irqrestore(&btv->s_lock,flags); if (NULL == new) free_btres(btv,fh,RESOURCE_OVERLAY); @@ -1358,7 +1353,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, { int redo_dma_risc = 0; int rc; - + /* check settings */ if (NULL == fmt) return -EINVAL; @@ -1378,7 +1373,7 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; } - + /* alloc + fill struct bttv_buffer (if changed) */ if (buf->vb.width != width || buf->vb.height != height || buf->vb.field != field || @@ -1411,10 +1406,10 @@ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, } static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - struct bttv_fh *fh = file->private_data; - + struct bttv_fh *fh = q->priv_data; + *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = gbuffers; @@ -1424,32 +1419,35 @@ buffer_setup(struct file *file, unsigned int *count, unsigned int *size) } static int -buffer_prepare(struct file *file, struct videobuf_buffer *vb, +buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { - struct bttv_buffer *buf = (struct bttv_buffer*)vb; - struct bttv_fh *fh = file->private_data; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; return bttv_prepare_buffer(fh->btv, buf, fh->fmt, fh->width, fh->height, field); } static void -buffer_queue(struct file *file, struct videobuf_buffer *vb) +buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct bttv_buffer *buf = (struct bttv_buffer*)vb; - struct bttv_fh *fh = file->private_data; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; + struct bttv *btv = fh->btv; buf->vb.state = STATE_QUEUED; - list_add_tail(&buf->vb.queue,&fh->btv->capture); - fh->btv->curr.irqflags |= 1; - bttv_set_dma(fh->btv, 0x03, fh->btv->curr.irqflags); + list_add_tail(&buf->vb.queue,&btv->capture); + if (!btv->curr.frame_irq) { + btv->loop_irq |= 1; + bttv_set_dma(btv, 0x03); + } } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct bttv_buffer *buf = (struct bttv_buffer*)vb; - struct bttv_fh *fh = file->private_data; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + struct bttv_fh *fh = q->priv_data; bttv_dma_free(fh->btv,buf); } @@ -1497,7 +1495,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) case VIDIOCGTUNER: { struct video_tuner *v = arg; - + if (UNSET == bttv_tvcards[btv->c.type].tuner) return -EINVAL; if (v->tuner) /* Only tuner 0 */ @@ -1526,7 +1524,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) up(&btv->lock); return 0; } - + case VIDIOCGCHAN: { struct video_channel *v = arg; @@ -1608,7 +1606,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) /* card specific hooks */ if (btv->audio_hook) btv->audio_hook(btv,v,1); - + up(&btv->lock); return 0; } @@ -1618,7 +1616,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { struct v4l2_standard *e = arg; unsigned int index = e->index; - + if (index >= BTTV_TVNORMS) return -EINVAL; v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id, @@ -1652,7 +1650,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) case VIDIOC_QUERYSTD: { v4l2_std_id *id = arg; - + if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) *id = V4L2_STD_625_50; else @@ -1664,7 +1662,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { struct v4l2_input *i = arg; unsigned int n; - + n = i->index; if (n >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; @@ -1701,16 +1699,15 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { unsigned int *i = arg; - + if (*i > bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; down(&btv->lock); set_input(btv,*i); - i2c_vidiocschan(btv); up(&btv->lock); return 0; } - + case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; @@ -1806,7 +1803,7 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) default: return -ENOIOCTLCMD; - + } return 0; } @@ -1861,6 +1858,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, if (NULL == fh->ovfmt) return -EINVAL; + if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup); if (0 != retval) return retval; @@ -1899,25 +1898,25 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, default: BUG(); } - + down(&fh->cap.lock); if (fh->ov.clips) kfree(fh->ov.clips); fh->ov.clips = clips; fh->ov.nclips = n; - + fh->ov.w = win->w; fh->ov.field = win->field; fh->ov.setup_ok = 1; btv->init.ov.w.width = win->w.width; btv->init.ov.w.height = win->w.height; btv->init.ov.field = win->field; - + /* update overlay if needed */ retval = 0; if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - + new = videobuf_alloc(sizeof(*new)); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); @@ -1931,7 +1930,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, static struct videobuf_queue* bttv_queue(struct bttv_fh *fh) { struct videobuf_queue* q = NULL; - + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: q = &fh->cap; @@ -1948,7 +1947,7 @@ static struct videobuf_queue* bttv_queue(struct bttv_fh *fh) static int bttv_resource(struct bttv_fh *fh) { int res = 0; - + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: res = RESOURCE_VIDEO; @@ -2052,11 +2051,12 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, f->fmt.pix.width = maxw; if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; + f->fmt.pix.width &= ~0x03; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - + return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -2074,7 +2074,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, struct v4l2_format *f) { int retval; - + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { @@ -2087,7 +2087,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, if (0 != retval) return retval; fmt = format_by_fourcc(f->fmt.pix.pixelformat); - + /* update our state informations */ down(&fh->cap.lock); fh->fmt = fmt; @@ -2099,7 +2099,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, btv->init.width = f->fmt.pix.width; btv->init.height = f->fmt.pix.height; up(&fh->cap.lock); - + return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -2146,7 +2146,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (btv->errors) bttv_reinit_bt848(btv); -#ifdef VIDIOC_G_PRIORITY switch (cmd) { case VIDIOCSFREQ: case VIDIOCSTUNER: @@ -2160,7 +2159,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 != retval) return retval; }; -#endif + switch (cmd) { /* *** v4l1 *** ************************************************ */ @@ -2209,7 +2208,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, { struct video_picture *pic = arg; const struct bttv_format *fmt; - + fmt = format_by_palette(pic->palette); if (NULL == fmt) return -EINVAL; @@ -2356,7 +2355,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) return -EBUSY; - + down(&fh->cap.lock); if (*on) { fh->ov.tvnorm = btv->tvnorm; @@ -2378,7 +2377,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, unsigned int i; down(&fh->cap.lock); - retval = videobuf_mmap_setup(file,&fh->cap,gbuffers,gbufsize, + retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, V4L2_MEMORY_MMAP); if (retval < 0) goto fh_unlock_and_return; @@ -2409,7 +2408,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (buf->vb.state == STATE_QUEUED || buf->vb.state == STATE_ACTIVE) goto fh_unlock_and_return; - + field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; @@ -2419,7 +2418,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 != retval) goto fh_unlock_and_return; spin_lock_irqsave(&btv->s_lock,flags); - buffer_queue(file,&buf->vb); + buffer_queue(&fh->cap,&buf->vb); spin_unlock_irqrestore(&btv->s_lock,flags); up(&fh->cap.lock); return 0; @@ -2533,7 +2532,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_READWRITE | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; return 0; } @@ -2618,7 +2617,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, { struct v4l2_framebuffer *fb = arg; const struct bttv_format *fmt; - + if(!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) return -EPERM; @@ -2647,7 +2646,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline; else btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8; - + retval = 0; fh->ovfmt = fmt; btv->init.ovfmt = fmt; @@ -2665,7 +2664,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - + new = videobuf_alloc(sizeof(*new)); bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); retval = bttv_switch_overlay(btv,fh,new); @@ -2676,16 +2675,17 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_REQBUFS: - return videobuf_reqbufs(file,bttv_queue(fh),arg); + return videobuf_reqbufs(bttv_queue(fh),arg); case VIDIOC_QUERYBUF: return videobuf_querybuf(bttv_queue(fh),arg); case VIDIOC_QBUF: - return videobuf_qbuf(file,bttv_queue(fh),arg); + return videobuf_qbuf(bttv_queue(fh),arg); case VIDIOC_DQBUF: - return videobuf_dqbuf(file,bttv_queue(fh),arg); + return videobuf_dqbuf(bttv_queue(fh),arg, + file->f_flags & O_NONBLOCK); case VIDIOC_STREAMON: { @@ -2693,13 +2693,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (!check_alloc_btres(btv,fh,res)) return -EBUSY; - return videobuf_streamon(file,bttv_queue(fh)); + return videobuf_streamon(bttv_queue(fh)); } case VIDIOC_STREAMOFF: { int res = bttv_resource(fh); - retval = videobuf_streamoff(file,bttv_queue(fh)); + retval = videobuf_streamoff(bttv_queue(fh)); if (retval < 0) return retval; free_btres(btv,fh,res); @@ -2768,7 +2768,6 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } -#ifdef VIDIOC_G_PRIORITY case VIDIOC_G_PRIORITY: { enum v4l2_priority *p = arg; @@ -2782,9 +2781,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return v4l2_prio_change(&btv->prio, &fh->prio, *prio); } -#endif - case VIDIOC_ENUMSTD: case VIDIOC_G_STD: case VIDIOC_S_STD: @@ -2836,12 +2833,14 @@ static ssize_t bttv_read(struct file *file, char __user *data, case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (locked_btres(fh->btv,RESOURCE_VIDEO)) return -EBUSY; - retval = videobuf_read_one(file, &fh->cap, data, count, ppos); + retval = videobuf_read_one(&fh->cap, data, count, ppos, + file->f_flags & O_NONBLOCK); break; case V4L2_BUF_TYPE_VBI_CAPTURE: if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) return -EBUSY; - retval = videobuf_read_stream(file, &fh->vbi, data, count, ppos, 1); + retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1, + file->f_flags & O_NONBLOCK); break; default: BUG(); @@ -2857,7 +2856,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) - return -EBUSY; + return POLLERR; return videobuf_poll_stream(file, &fh->vbi, wait); } @@ -2882,17 +2881,17 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) } fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; field = videobuf_next_field(&fh->cap); - if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,field)) { + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { up(&fh->cap.lock); return POLLERR; } - fh->cap.ops->buf_queue(file,fh->cap.read_buf); + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } up(&fh->cap.lock); buf = (struct bttv_buffer*)fh->cap.read_buf; } - + poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == STATE_DONE || buf->vb.state == STATE_ERROR) @@ -2938,20 +2937,20 @@ static int bttv_open(struct inode *inode, struct file *file) *fh = btv->init; fh->type = type; fh->ov.setup_ok = 0; -#ifdef VIDIOC_G_PRIORITY v4l2_prio_open(&btv->prio,&fh->prio); -#endif videobuf_queue_init(&fh->cap, &bttv_video_qops, btv->c.pci, &btv->s_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct bttv_buffer)); + sizeof(struct bttv_buffer), + fh); videobuf_queue_init(&fh->vbi, &bttv_vbi_qops, btv->c.pci, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, - sizeof(struct bttv_buffer)); + sizeof(struct bttv_buffer), + fh); i2c_vidiocschan(btv); btv->users++; @@ -2969,29 +2968,27 @@ static int bttv_release(struct inode *inode, struct file *file) /* turn off overlay */ if (check_btres(fh, RESOURCE_OVERLAY)) bttv_switch_overlay(btv,fh,NULL); - + /* stop video capture */ if (check_btres(fh, RESOURCE_VIDEO)) { - videobuf_streamoff(file,&fh->cap); + videobuf_streamoff(&fh->cap); free_btres(btv,fh,RESOURCE_VIDEO); } if (fh->cap.read_buf) { - buffer_release(file,fh->cap.read_buf); + buffer_release(&fh->cap,fh->cap.read_buf); kfree(fh->cap.read_buf); } /* stop vbi capture */ if (check_btres(fh, RESOURCE_VBI)) { if (fh->vbi.streaming) - videobuf_streamoff(file,&fh->vbi); + videobuf_streamoff(&fh->vbi); if (fh->vbi.reading) - videobuf_read_stop(file,&fh->vbi); + videobuf_read_stop(&fh->vbi); free_btres(btv,fh,RESOURCE_VBI); } -#ifdef VIDIOC_G_PRIORITY v4l2_prio_close(&btv->prio,&fh->prio); -#endif file->private_data = NULL; kfree(fh); @@ -3008,7 +3005,7 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma) dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n", fh->btv->c.nr, v4l2_type_names[fh->type], vma->vm_start, vma->vm_end - vma->vm_start); - return videobuf_mmap_mapper(vma,bttv_queue(fh)); + return videobuf_mmap_mapper(bttv_queue(fh),vma); } static struct file_operations bttv_fops = @@ -3124,7 +3121,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOCSTUNER: /* nothing to do */ return 0; - + case BTTV_VERSION: case VIDIOCGFREQ: case VIDIOCSFREQ: @@ -3190,7 +3187,7 @@ static char *irq_name[] = { static void bttv_print_irqbits(u32 print, u32 mark) { unsigned int i; - + printk("bits:"); for (i = 0; i < ARRAY_SIZE(irq_name); i++) { if (print & (1 << i)) @@ -3246,7 +3243,7 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) /* capture request ? */ if (!list_empty(&btv->capture)) { - set->irqflags = 1; + set->frame_irq = 1; item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); if (V4L2_FIELD_HAS_TOP(item->vb.field)) set->top = item; @@ -3267,7 +3264,7 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) set->bottom = item; } if (NULL != set->top && NULL != set->bottom) - set->topirq = 2; + set->top_irq = 2; } } } @@ -3293,7 +3290,7 @@ bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set) dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n", btv->c.nr,set->top, set->bottom, - btv->screen,set->irqflags,set->topirq); + btv->screen,set->frame_irq,set->top_irq); return 0; } @@ -3357,7 +3354,7 @@ static void bttv_irq_timeout(unsigned long data) struct bttv_buffer *ovbi; struct bttv_buffer *item; unsigned long flags; - + if (bttv_verbose) { printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ", btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total, @@ -3367,16 +3364,17 @@ static void bttv_irq_timeout(unsigned long data) } spin_lock_irqsave(&btv->s_lock,flags); - + /* deactivate stuff */ memset(&new,0,sizeof(new)); old = btv->curr; ovbi = btv->cvbi; btv->curr = new; btv->cvbi = NULL; + btv->loop_irq = 0; bttv_buffer_activate_video(btv, &new); bttv_buffer_activate_vbi(btv, NULL); - bttv_set_dma(btv, 0, 0); + bttv_set_dma(btv, 0); /* wake up */ bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR); @@ -3395,7 +3393,7 @@ static void bttv_irq_timeout(unsigned long data) item->vb.state = STATE_ERROR; wake_up(&item->vb.done); } - + btv->errors++; spin_unlock_irqrestore(&btv->s_lock,flags); } @@ -3409,7 +3407,7 @@ bttv_irq_wakeup_top(struct bttv *btv) return; spin_lock(&btv->s_lock); - btv->curr.topirq = 0; + btv->curr.top_irq = 0; btv->curr.top = NULL; bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); @@ -3449,12 +3447,13 @@ bttv_irq_switch_video(struct bttv *btv) spin_unlock(&btv->s_lock); return; } - + /* switch over */ old = btv->curr; btv->curr = new; + btv->loop_irq &= ~1; bttv_buffer_activate_video(btv, &new); - bttv_set_dma(btv, 0, new.irqflags); + bttv_set_dma(btv, 0); /* switch input */ if (UNSET != btv->new_input) { @@ -3492,8 +3491,9 @@ bttv_irq_switch_vbi(struct bttv *btv) /* switch */ btv->cvbi = new; + btv->loop_irq &= ~4; bttv_buffer_activate_vbi(btv, new); - bttv_set_dma(btv, 0, btv->curr.irqflags); + bttv_set_dma(btv, 0); bttv_irq_wakeup_vbi(btv, old, STATE_DONE); spin_unlock(&btv->s_lock); @@ -3539,7 +3539,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) printk("\n"); } - if (astat&BT848_INT_VSYNC) + if (astat&BT848_INT_VSYNC) btv->field_count++; if (astat & BT848_INT_GPINT) { @@ -3584,7 +3584,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) count++; if (count > 4) { btwrite(0, BT848_INT_MASK); - printk(KERN_ERR + printk(KERN_ERR "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); bttv_print_irqbits(stat,astat); printk("]\n"); @@ -3692,9 +3692,9 @@ static void pci_set_command(struct pci_dev *dev) { #if defined(__powerpc__) unsigned int cmd; - + pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); + cmd = (cmd | PCI_COMMAND_MEMORY ); pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif } @@ -3724,21 +3724,19 @@ static int __devinit bttv_probe(struct pci_dev *dev, INIT_LIST_HEAD(&btv->c.subs); INIT_LIST_HEAD(&btv->capture); INIT_LIST_HEAD(&btv->vcapture); -#ifdef VIDIOC_G_PRIORITY v4l2_prio_init(&btv->prio); -#endif init_timer(&btv->timeout); btv->timeout.function = bttv_irq_timeout; btv->timeout.data = (unsigned long)btv; - + btv->i2c_rc = -1; btv->tuner_type = UNSET; btv->pinnacle_id = UNSET; btv->new_input = UNSET; btv->gpioirq = 1; btv->has_radio=radio[btv->c.nr]; - + /* pci stuff (init, get irq/mmio, ... */ btv->c.pci = dev; btv->id = dev->device; @@ -3775,7 +3773,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, printk("irq: %d, latency: %d, mmio: 0x%lx\n", btv->c.pci->irq, lat, pci_resource_start(dev,0)); schedule(); - + btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000); if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) { printk("bttv%d: ioremap() failed\n", btv->c.nr); @@ -3810,7 +3808,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->opt_vcr_hack = vcr_hack; btv->opt_whitecrush_upper = whitecrush_upper; btv->opt_whitecrush_lower = whitecrush_lower; - + /* fill struct bttv with some useful defaults */ btv->init.btv = btv; btv->init.ov.w.width = 320; @@ -3867,7 +3865,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, fail2: free_irq(btv->c.pci->irq,btv); - + fail1: if (btv->bt848_mmio) iounmap(btv->bt848_mmio); @@ -3896,7 +3894,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) btv->shutdown=1; wake_up(&btv->gpioq); bttv_sub_del_devices(&btv->c); - + /* unregister i2c_bus + input */ fini_bttv_i2c(btv); @@ -3922,17 +3920,19 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state) struct bttv_buffer_set idle; unsigned long flags; - printk("bttv%d: suspend %d\n", btv->c.nr, state); + dprintk("bttv%d: suspend %d\n", btv->c.nr, state); /* stop dma + irqs */ spin_lock_irqsave(&btv->s_lock,flags); memset(&idle, 0, sizeof(idle)); btv->state.video = btv->curr; btv->state.vbi = btv->cvbi; + btv->state.loop_irq = btv->loop_irq; btv->curr = idle; + btv->loop_irq = 0; bttv_buffer_activate_video(btv, &idle); bttv_buffer_activate_vbi(btv, NULL); - bttv_set_dma(btv, 0, 0); + bttv_set_dma(btv, 0); btwrite(0, BT848_INT_MASK); spin_unlock_irqrestore(&btv->s_lock,flags); @@ -3941,7 +3941,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state) btv->state.gpio_data = gpio_read(); /* save pci state */ - pci_save_state(pci_dev, btv->state.pci_cfg); + pci_save_state(pci_dev); if (0 != pci_set_power_state(pci_dev, state)) { pci_disable_device(pci_dev); btv->state.disabled = 1; @@ -3954,7 +3954,7 @@ static int bttv_resume(struct pci_dev *pci_dev) struct bttv *btv = pci_get_drvdata(pci_dev); unsigned long flags; - printk("bttv%d: resume\n", btv->c.nr); + dprintk("bttv%d: resume\n", btv->c.nr); /* restore pci state */ if (btv->state.disabled) { @@ -3962,7 +3962,7 @@ static int bttv_resume(struct pci_dev *pci_dev) btv->state.disabled = 0; } pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, btv->state.pci_cfg); + pci_restore_state(pci_dev); /* restore bt878 state */ bttv_reinit_bt848(btv); @@ -3973,9 +3973,10 @@ static int bttv_resume(struct pci_dev *pci_dev) spin_lock_irqsave(&btv->s_lock,flags); btv->curr = btv->state.video; btv->cvbi = btv->state.vbi; + btv->loop_irq = btv->state.loop_irq; bttv_buffer_activate_video(btv, &btv->curr); bttv_buffer_activate_vbi(btv, btv->cvbi); - bttv_set_dma(btv, 0, btv->curr.irqflags); + bttv_set_dma(btv, 0); spin_unlock_irqrestore(&btv->s_lock,flags); return 0; } @@ -3999,14 +4000,12 @@ static struct pci_driver bttv_pci_driver = { .id_table = bttv_pci_tbl, .probe = bttv_probe, .remove = __devexit_p(bttv_remove), - - .suspend = bttv_suspend, - .resume = bttv_resume, + .suspend = bttv_suspend, + .resume = bttv_resume, }; static int bttv_init_module(void) { - int rc; bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", @@ -4029,13 +4028,7 @@ static int bttv_init_module(void) bttv_check_chipset(); bus_register(&bttv_sub_bus_type); - rc = pci_module_init(&bttv_pci_driver); - if (-ENODEV == rc) { - /* plenty of people trying to use bttv for the cx2388x ... */ - if (NULL != pci_find_device(0x14f1, 0x8800, NULL)) - printk("bttv doesn't support your Conexant 2388x card.\n"); - } - return rc; + return pci_module_init(&bttv_pci_driver); } static void bttv_cleanup_module(void) diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 01ce7bc32..ef6744232 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -1,4 +1,6 @@ /* + $Id: bttv-gpio.c,v 1.6 2004/11/03 09:04:50 kraxel Exp $ + bttv-gpio.c -- gpio sub drivers sysfs-based sub driver interface for bttv @@ -22,7 +24,7 @@ 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. - + */ #include @@ -61,6 +63,7 @@ static void release_sub_device(struct device *dev) int bttv_sub_add_device(struct bttv_core *core, char *name) { struct bttv_sub_device *sub; + int err; sub = kmalloc(sizeof(*sub),GFP_KERNEL); if (NULL == sub) @@ -74,9 +77,13 @@ int bttv_sub_add_device(struct bttv_core *core, char *name) snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d", name, core->nr); + err = device_register(&sub->dev); + if (0 != err) { + kfree(sub); + return err; + } printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id); list_add_tail(&sub->list,&core->subs); - device_register(&sub->dev); return 0; } @@ -106,6 +113,20 @@ void bttv_gpio_irq(struct bttv_core *core) } } +void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach) +{ + struct bttv_sub_driver *drv; + struct bttv_sub_device *dev; + struct list_head *item; + + list_for_each(item,&core->subs) { + dev = list_entry(item,struct bttv_sub_device,list); + drv = to_bttv_sub_drv(dev->dev.driver); + if (drv && drv->i2c_info) + drv->i2c_info(dev,client,attach); + } +} + /* ----------------------------------------------------------------------- */ /* external: sub-driver register/unregister */ @@ -113,8 +134,7 @@ int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted) { sub->drv.bus = &bttv_sub_bus_type; snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted); - driver_register(&sub->drv); - return 0; + return driver_register(&sub->drv); } EXPORT_SYMBOL(bttv_sub_register); diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index c07a0d9c0..a7fb01843 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -1,4 +1,6 @@ /* + $Id: bttv-i2c.c,v 1.13 2004/11/07 13:17:15 kraxel Exp $ + bttv-i2c.c -- all the i2c code is here bttv - Bt848 frame grabber driver @@ -20,7 +22,7 @@ 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. - + */ #include @@ -35,16 +37,16 @@ static struct i2c_adapter bttv_i2c_adap_sw_template; static struct i2c_adapter bttv_i2c_adap_hw_template; static struct i2c_client bttv_i2c_client_template; -#ifndef I2C_PEC -static void bttv_inc_use(struct i2c_adapter *adap); -static void bttv_dec_use(struct i2c_adapter *adap); -#endif static int attach_inform(struct i2c_client *client); +static int detach_inform(struct i2c_client *client); static int i2c_debug = 0; static int i2c_hw = 0; -MODULE_PARM(i2c_debug,"i"); -MODULE_PARM(i2c_hw,"i"); +static int i2c_scan = 0; +module_param(i2c_debug, int, 0644); +module_param(i2c_hw, int, 0444); +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); /* ----------------------------------------------------------------------- */ /* I2C functions - bitbanging adapter (software i2c) */ @@ -77,7 +79,7 @@ static int bttv_bit_getscl(void *data) { struct bttv *btv = (struct bttv*)data; int state; - + state = btread(BT848_I2C) & 0x02 ? 1 : 0; return state; } @@ -102,24 +104,20 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { }; static struct i2c_adapter bttv_i2c_adap_sw_template = { -#ifdef I2C_PEC .owner = THIS_MODULE, -#else - .inc_use = bttv_inc_use, - .dec_use = bttv_dec_use, -#endif #ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, #endif I2C_DEVNAME("bt848"), .id = I2C_HW_B_BT848, .client_register = attach_inform, + .client_unregister = detach_inform, }; /* ----------------------------------------------------------------------- */ /* I2C functions - hardware i2c */ -static int algo_control(struct i2c_adapter *adapter, +static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) { return 0; @@ -135,12 +133,10 @@ bttv_i2c_wait_done(struct bttv *btv) { DECLARE_WAITQUEUE(wait, current); int rc = 0; - + add_wait_queue(&btv->i2c_queue, &wait); - set_current_state(TASK_INTERRUPTIBLE); if (0 == btv->i2c_done) - schedule_timeout(HZ/50+1); - set_current_state(TASK_RUNNING); + msleep_interruptible(20); remove_wait_queue(&btv->i2c_queue, &wait); if (0 == btv->i2c_done) @@ -285,12 +281,7 @@ static struct i2c_algorithm bttv_algo = { }; static struct i2c_adapter bttv_i2c_adap_hw_template = { -#ifdef I2C_PEC .owner = THIS_MODULE, -#else - .inc_use = bttv_inc_use, - .dec_use = bttv_dec_use, -#endif #ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, #endif @@ -298,23 +289,12 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, .algo = &bttv_algo, .client_register = attach_inform, + .client_unregister = detach_inform, }; /* ----------------------------------------------------------------------- */ /* I2C functions - common stuff */ -#ifndef I2C_PEC -static void bttv_inc_use(struct i2c_adapter *adap) -{ - MOD_INC_USE_COUNT; -} - -static void bttv_dec_use(struct i2c_adapter *adap) -{ - MOD_DEC_USE_COUNT; -} -#endif - static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); @@ -324,6 +304,7 @@ static int attach_inform(struct i2c_client *client) if (btv->pinnacle_id != UNSET) bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); + bttv_i2c_info(&btv->c, client, 1); if (bttv_debug) printk("bttv%d: i2c attach [client=%s]\n", @@ -331,6 +312,14 @@ static int attach_inform(struct i2c_client *client) return 0; } +static int detach_inform(struct i2c_client *client) +{ + struct bttv *btv = i2c_get_adapdata(client->adapter); + + bttv_i2c_info(&btv->c, client, 0); + return 0; +} + void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) { if (0 != btv->i2c_rc) @@ -352,7 +341,7 @@ static struct i2c_client bttv_i2c_client_template = { /* read I2C */ -int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { unsigned char buffer = 0; @@ -397,7 +386,7 @@ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; - + if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) { printk(KERN_WARNING "bttv: readee error\n"); return; @@ -411,6 +400,30 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) } } +static char *i2c_devs[128] = { + [ 0x30 >> 1 ] = "IR (hauppauge)", + [ 0x80 >> 1 ] = "msp34xx", + [ 0x86 >> 1 ] = "tda9887", + [ 0xa0 >> 1 ] = "eeprom", + [ 0xc0 >> 1 ] = "tuner (analog)", + [ 0xc2 >> 1 ] = "tuner (analog)", +}; + +static void do_i2c_scan(char *name, struct i2c_client *c) +{ + unsigned char buf; + int i,rc; + + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c,&buf,0); + if (rc < 0) + continue; + printk("%s: i2c scan: found device @ 0x%x [%s]\n", + name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } +} + /* init + register i2c algo-bit adapter */ int __devinit init_bttv_i2c(struct bttv *btv) { @@ -441,6 +454,13 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, btv); btv->i2c_client.adapter = &btv->c.i2c_adap; +#ifdef I2C_CLASS_TV_ANALOG + if (bttv_tvcards[btv->c.type].no_video) + btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; + if (bttv_tvcards[btv->c.type].has_dvb) + btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; +#endif + if (btv->use_i2c_hw) { btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); } else { @@ -448,6 +468,8 @@ int __devinit init_bttv_i2c(struct bttv *btv) bttv_bit_setsda(btv,1); btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); } + if (0 == btv->i2c_rc && i2c_scan) + do_i2c_scan(btv->c.name,&btv->i2c_client); return btv->i2c_rc; } diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c index 74da71195..935feb756 100644 --- a/drivers/media/video/bttv-if.c +++ b/drivers/media/video/bttv-if.c @@ -1,4 +1,6 @@ /* + $Id: bttv-if.c,v 1.3 2004/10/13 10:39:00 kraxel Exp $ + bttv-if.c -- old gpio interface to other kernel modules don't use in new code, will go away in 2.7 have a look at bttv-gpio.c instead. @@ -22,7 +24,7 @@ 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. - + */ #include @@ -80,7 +82,7 @@ int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) if (card >= bttv_num) { return -EINVAL; } - + btv = &bttvs[card]; gpio_inout(mask,data); if (bttv_gpio) @@ -91,7 +93,7 @@ int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) int bttv_read_gpio(unsigned int card, unsigned long *data) { struct bttv *btv; - + if (card >= bttv_num) { return -EINVAL; } @@ -102,7 +104,7 @@ int bttv_read_gpio(unsigned int card, unsigned long *data) return -ENODEV; } -/* prior setting BT848_GPIO_REG_INP is (probably) not needed +/* prior setting BT848_GPIO_REG_INP is (probably) not needed because we set direct input on init */ *data = gpio_read(); return 0; @@ -111,14 +113,14 @@ int bttv_read_gpio(unsigned int card, unsigned long *data) int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) { struct bttv *btv; - + if (card >= bttv_num) { return -EINVAL; } btv = &bttvs[card]; -/* prior setting BT848_GPIO_REG_INP is (probably) not needed +/* prior setting BT848_GPIO_REG_INP is (probably) not needed because direct input is set on init */ gpio_bits(mask,data); if (bttv_gpio) diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 769c7e365..8ef610c34 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -1,4 +1,6 @@ /* + $Id: bttv-risc.c,v 1.9 2004/10/13 10:39:00 kraxel Exp $ + bttv-risc.c -- interfaces to other kernel modules bttv risc code handling @@ -100,10 +102,10 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, } offset += padding; } - dprintk("bttv%d: risc planar: %d sglist elems\n", btv->c.nr, (int)(sg-sglist)); /* save pointer to jmp instruction address */ risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); return 0; } @@ -121,6 +123,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, struct scatterlist *ysg; struct scatterlist *usg; struct scatterlist *vsg; + int topfield = (0 == yoffset); int rc; /* estimate risc mem: worst case is one write per page border + @@ -145,11 +148,26 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, (line >= (ylines - VCR_HACK_LINES))) continue; switch (vshift) { - case 0: chroma = 1; break; - case 1: chroma = !(line & 1); break; - case 2: chroma = !(line & 3); break; - default: chroma = 0; + case 0: + chroma = 1; + break; + case 1: + if (topfield) + chroma = ((line & 1) == 0); + else + chroma = ((line & 1) == 1); + break; + case 2: + if (topfield) + chroma = ((line & 3) == 0); + else + chroma = ((line & 3) == 2); + break; + default: + chroma = 0; + break; } + for (todo = ybpl; todo > 0; todo -= ylen) { /* go to next sg entry if needed */ while (yoffset && yoffset >= sg_dma_len(ysg)) { @@ -205,6 +223,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); return 0; } @@ -221,7 +240,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, /* skip list for window clipping */ if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) return -ENOMEM; - + /* estimate risc mem: worst case is (clip+1) * lines instructions + sync + jump (all 2 dwords) */ instructions = (ov->nclips + 1) * @@ -274,7 +293,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, ra = addr + (fmt->depth>>3)*start; else ra = 0; - + if (0 == start) ri |= BT848_RISC_SOL; if (ov->w.width == end) @@ -289,6 +308,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); kfree(skips); return 0; } @@ -371,7 +391,7 @@ bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) /* risc group / risc main loop / dma management */ void -bttv_set_dma(struct bttv *btv, int override, int irqflags) +bttv_set_dma(struct bttv *btv, int override) { unsigned long cmd; int capctl; @@ -387,26 +407,26 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) capctl |= override; d2printk(KERN_DEBUG - "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", - btv->c.nr,capctl,irqflags, + "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", + btv->c.nr,capctl,btv->loop_irq, btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0, btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0, btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); - + cmd = BT848_RISC_JUMP; - if (irqflags) { + if (btv->loop_irq) { cmd |= BT848_RISC_IRQ; - cmd |= (irqflags & 0x0f) << 16; - cmd |= (~irqflags & 0x0f) << 20; + cmd |= (btv->loop_irq & 0x0f) << 16; + cmd |= (~btv->loop_irq & 0x0f) << 20; } - if (irqflags || btv->cvbi) { + if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) { mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); } else { del_timer(&btv->timeout); } btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); - + btaor(capctl, ~0x0f, BT848_CAP_CTL); if (capctl) { if (btv->dma_on) @@ -427,7 +447,7 @@ int bttv_risc_init_main(struct bttv *btv) { int rc; - + if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0) return rc; dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", @@ -539,8 +559,10 @@ bttv_buffer_activate_video(struct bttv *btv, } bttv_apply_geo(btv, &set->top->geo, 1); bttv_apply_geo(btv, &set->bottom->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, set->topirq); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, + set->top_irq); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, + set->frame_irq); btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f), ~0xff, BT848_COLOR_FMT); btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05), @@ -551,7 +573,8 @@ bttv_buffer_activate_video(struct bttv *btv, list_del(&set->top->vb.queue); bttv_apply_geo(btv, &set->top->geo,1); bttv_apply_geo(btv, &set->top->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, 0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, + set->frame_irq); bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT); btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); @@ -561,8 +584,9 @@ bttv_buffer_activate_video(struct bttv *btv, list_del(&set->bottom->vb.queue); bttv_apply_geo(btv, &set->bottom->geo,1); bttv_apply_geo(btv, &set->bottom->geo,0); - bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0); + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); + bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, + set->frame_irq); btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT); btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); } else { @@ -592,7 +616,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); - + switch (buf->vb.field) { case V4L2_FIELD_TOP: bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c index ad655c8aa..ecdd9bfd6 100644 --- a/drivers/media/video/bttv-vbi.c +++ b/drivers/media/video/bttv-vbi.c @@ -1,19 +1,21 @@ /* + $Id: bttv-vbi.c,v 1.7 2004/11/07 13:17:15 kraxel Exp $ + bttv - Bt848 frame grabber driver vbi interface - + (c) 2002 Gerd Knorr - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -35,9 +37,9 @@ static unsigned int vbibufs = 4; static unsigned int vbi_debug = 0; -MODULE_PARM(vbibufs,"i"); +module_param(vbibufs, int, 0444); +module_param(vbi_debug, int, 0644); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4"); -MODULE_PARM(vbi_debug,"i"); MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)"); #ifdef dprintk @@ -61,10 +63,10 @@ vbi_buffer_risc(struct bttv *btv, struct bttv_buffer *buf, int lines) return 0; } -static int vbi_buffer_setup(struct file *file, +static int vbi_buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - struct bttv_fh *fh = file->private_data; + struct bttv_fh *fh = q->priv_data; struct bttv *btv = fh->btv; if (0 == *count) @@ -74,14 +76,15 @@ static int vbi_buffer_setup(struct file *file, return 0; } -static int vbi_buffer_prepare(struct file *file, struct videobuf_buffer *vb, +static int vbi_buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, enum v4l2_field field) { - struct bttv_fh *fh = file->private_data; + struct bttv_fh *fh = q->priv_data; struct bttv *btv = fh->btv; - struct bttv_buffer *buf = (struct bttv_buffer*)vb; + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); int rc; - + buf->vb.size = fh->lines * 2 * 2048; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) return -EINVAL; @@ -105,27 +108,27 @@ static int vbi_buffer_prepare(struct file *file, struct videobuf_buffer *vb, } static void -vbi_buffer_queue(struct file *file, struct videobuf_buffer *vb) +vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct bttv_fh *fh = file->private_data; + struct bttv_fh *fh = q->priv_data; struct bttv *btv = fh->btv; - struct bttv_buffer *buf = (struct bttv_buffer*)vb; - + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + dprintk("queue %p\n",vb); buf->vb.state = STATE_QUEUED; list_add_tail(&buf->vb.queue,&btv->vcapture); if (NULL == btv->cvbi) { - fh->btv->curr.irqflags |= 4; - bttv_set_dma(btv,0x0c,fh->btv->curr.irqflags); + fh->btv->loop_irq |= 4; + bttv_set_dma(btv,0x0c); } } -static void vbi_buffer_release(struct file *file, struct videobuf_buffer *vb) +static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct bttv_fh *fh = file->private_data; + struct bttv_fh *fh = q->priv_data; struct bttv *btv = fh->btv; - struct bttv_buffer *buf = (struct bttv_buffer*)vb; - + struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb); + dprintk("free %p\n",vb); bttv_dma_free(fh->btv,buf); } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 33d56aa9d..fa96757f4 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -1,4 +1,6 @@ /* + * $Id: bttv.h,v 1.10 2004/10/13 10:39:00 kraxel Exp $ + * * bttv - Bt848 frame grabber driver * * card ID's and external interfaces of the bttv driver @@ -24,9 +26,9 @@ #define BTTV_HAUPPAUGE 0x02 #define BTTV_STB 0x03 #define BTTV_INTEL 0x04 -#define BTTV_DIAMOND 0x05 -#define BTTV_AVERMEDIA 0x06 -#define BTTV_MATRIX_VISION 0x07 +#define BTTV_DIAMOND 0x05 +#define BTTV_AVERMEDIA 0x06 +#define BTTV_MATRIX_VISION 0x07 #define BTTV_FLYVIDEO 0x08 #define BTTV_TURBOTV 0x09 #define BTTV_HAUPPAUGE878 0x0a @@ -126,6 +128,11 @@ #define BTTV_LMLBT4 0x76 #define BTTV_PICOLO_TETRA_CHIP 0x79 #define BTTV_AVDVBT_771 0x7b +#define BTTV_AVDVBT_761 0x7c +#define BTTV_MATRIX_VISIONSQ 0x7d +#define BTTV_MATRIX_VISIONSLC 0x7e +#define BTTV_APAC_VIEWCOMP 0x7f +#define BTTV_DVICO_DVBT_LITE 0x80 /* i2c address list */ #define I2C_TSA5522 0xc2 @@ -223,9 +230,6 @@ extern void bttv_init_card2(struct bttv *btv); extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); -/* kernel cmd line parse helper */ -extern int bttv_parse(char *str, int max, int *vals); - /* extra tweaks for some chipsets */ extern void bttv_check_chipset(void); extern int bttv_handle_chipset(struct bttv *btv); @@ -238,7 +242,7 @@ extern int bttv_handle_chipset(struct bttv *btv); /* returns card type + card ID (for bt878-based ones) for possible values see lines below beginning with #define BTTV_UNKNOWN - returns negative value if error occurred + returns negative value if error occurred */ extern int bttv_get_cardinfo(unsigned int card, int *type, unsigned int *cardid); @@ -261,18 +265,18 @@ extern int bttv_read_gpio(unsigned int card, unsigned long *data); /* sets GPDATA register to new value: (data & mask) | (current_GPDATA_value & ~mask) - returns negative value if error occurred + returns negative value if error occurred */ extern int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data); -/* returns pointer to task queue which can be used as parameter to +/* returns pointer to task queue which can be used as parameter to interruptible_sleep_on in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated - (wake_up_interruptible) and following call to the function bttv_read_gpio + (wake_up_interruptible) and following call to the function bttv_read_gpio should return new value of GPDATA, returns NULL value if error occurred or queue is not available - WARNING: because there is no buffer for GPIO data, one MUST + WARNING: because there is no buffer for GPIO data, one MUST process data ASAP */ extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); @@ -298,6 +302,8 @@ struct bttv_sub_driver { struct device_driver drv; char wanted[BUS_ID_SIZE]; void (*gpio_irq)(struct bttv_sub_device *sub); + void (*i2c_info)(struct bttv_sub_device *sub, + struct i2c_client *client, int attach); }; #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index fae428ea4..bf6ac447b 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -1,4 +1,6 @@ /* + $Id: bttvp.h,v 1.12 2004/10/25 11:26:36 kraxel Exp $ + bttv - Bt848 frame grabber driver bttv's *private* header file -- nobody other than bttv itself @@ -127,8 +129,8 @@ struct bttv_buffer { struct bttv_buffer_set { struct bttv_buffer *top; /* top field buffer */ struct bttv_buffer *bottom; /* bottom field buffer */ - unsigned int irqflags; - unsigned int topirq; + unsigned int top_irq; + unsigned int frame_irq; }; struct bttv_overlay { @@ -143,7 +145,7 @@ struct bttv_overlay { struct bttv_fh { struct bttv *btv; int resources; -#ifdef VIDIOC_G_PRIORITY +#ifdef VIDIOC_G_PRIORITY enum v4l2_priority prio; #endif enum v4l2_buf_type type; @@ -189,7 +191,7 @@ void bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, void bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int top); /* control dma register + risc main loop */ -void bttv_set_dma(struct bttv *btv, int override, int irqflags); +void bttv_set_dma(struct bttv *btv, int override); int bttv_risc_init_main(struct bttv *btv); int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, int irqflags); @@ -225,6 +227,7 @@ extern struct bus_type bttv_sub_bus_type; int bttv_sub_add_device(struct bttv_core *core, char *name); int bttv_sub_del_devices(struct bttv_core *core); void bttv_gpio_irq(struct bttv_core *core); +void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach); /* ---------------------------------------------------------- */ @@ -276,10 +279,10 @@ struct bttv_input { }; struct bttv_suspend_state { - u32 pci_cfg[64 / sizeof(u32)]; u32 gpio_enable; u32 gpio_data; int disabled; + int loop_irq; struct bttv_buffer_set video; struct bttv_buffer *vbi; }; @@ -290,7 +293,7 @@ struct bttv { /* pci device config */ unsigned short id; unsigned char revision; - unsigned char *bt848_mmio; /* pointer to mmio */ + unsigned char __iomem *bt848_mmio; /* pointer to mmio */ /* card configuration info */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ @@ -331,10 +334,10 @@ struct bttv { struct semaphore lock; int resources; struct semaphore reslock; -#ifdef VIDIOC_G_PRIORITY +#ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif - + /* video state */ unsigned int input; unsigned int audio; @@ -380,6 +383,7 @@ struct bttv { struct list_head vcapture; /* vbi capture queue */ struct bttv_buffer_set curr; /* active buffers */ struct bttv_buffer *cvbi; /* active vbi buffer */ + int loop_irq; int new_input; unsigned long cap_ctl; @@ -403,7 +407,7 @@ struct bttv { #endif -#define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mmio+(adr))) +#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) #define btread(adr) readl(btv->bt848_mmio+(adr)) #define btand(dat,adr) btwrite((dat) & btread(adr), adr) diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 31412e8d3..356bde0e3 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -91,11 +91,6 @@ static inline int read_lpstatus(struct qcam_device *q) return parport_read_status(q->pport); } -static inline int read_lpcontrol(struct qcam_device *q) -{ - return parport_read_control(q->pport); -} - static inline int read_lpdata(struct qcam_device *q) { return parport_read_data(q->pport); @@ -249,8 +244,7 @@ static int qc_waithand(struct qcam_device *q, int val) if(runs++>maxpoll) { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); + msleep_interruptible(5); } if(runs>(maxpoll+1000)) /* 5 seconds */ return -1; @@ -269,8 +263,7 @@ static int qc_waithand(struct qcam_device *q, int val) if(runs++>maxpoll) { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); + msleep_interruptible(5); } if(runs++>(maxpoll+1000)) /* 5 seconds */ return -1; @@ -302,8 +295,7 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val) if(runs++>maxpoll) { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); + msleep_interruptible(5); } if(runs++>(maxpoll+1000)) /* 5 seconds */ return 0; @@ -669,8 +661,7 @@ long qc_capture(struct qcam_device * q, char __user *buf, unsigned long len) time will be 240 / 200 = 1.2 seconds. The compile-time default is to yield every 4 lines. */ if (i >= yield) { - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/200); + msleep_interruptible(5); yield = i + yieldlines; } } diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index bd9fef419..703c4cba9 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -103,8 +103,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, { if (qcam_ready1(qcam) == value) return 0; - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + msleep_interruptible(100); } /* Probably somebody pulled the plug out. Not much we can do. */ @@ -129,8 +128,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) { if (qcam_ready2(qcam) == value) return 0; - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + msleep_interruptible(100); } /* Probably somebody pulled the plug out. Not much we can do. */ diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 02c012dbc..f3206751a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include @@ -62,6 +64,15 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("video"); #endif +static unsigned short colorspace_conv = 0; +module_param(colorspace_conv, ushort, 0444); +MODULE_PARM_DESC(colorspace_conv, + "\n Colorspace conversion:" + "\n0 = disable" + "\n1 = enable" + "\nDefault value is 0" + "\n"); + #define ABOUT "V4L-Driver for Vision CPiA based cameras" #ifndef VID_HARDWARE_CPIA @@ -205,20 +216,6 @@ static void set_flicker(struct cam_params *params, volatile u32 *command_flags, * Memory management * **********************************************************************/ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - static void *rvmalloc(unsigned long size) { void *mem; @@ -1428,14 +1425,19 @@ static void __exit proc_cpia_destroy(void) /* supported frame palettes and depths */ static inline int valid_mode(u16 palette, u16 depth) { - return (palette == VIDEO_PALETTE_GREY && depth == 8) || - (palette == VIDEO_PALETTE_RGB555 && depth == 16) || - (palette == VIDEO_PALETTE_RGB565 && depth == 16) || - (palette == VIDEO_PALETTE_RGB24 && depth == 24) || - (palette == VIDEO_PALETTE_RGB32 && depth == 32) || - (palette == VIDEO_PALETTE_YUV422 && depth == 16) || - (palette == VIDEO_PALETTE_YUYV && depth == 16) || - (palette == VIDEO_PALETTE_UYVY && depth == 16); + if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) || + (palette == VIDEO_PALETTE_YUYV && depth == 16)) + return 1; + + if (colorspace_conv) + return (palette == VIDEO_PALETTE_GREY && depth == 8) || + (palette == VIDEO_PALETTE_RGB555 && depth == 16) || + (palette == VIDEO_PALETTE_RGB565 && depth == 16) || + (palette == VIDEO_PALETTE_RGB24 && depth == 24) || + (palette == VIDEO_PALETTE_RGB32 && depth == 32) || + (palette == VIDEO_PALETTE_UYVY && depth == 16); + + return 0; } static int match_videosize( int width, int height ) @@ -2871,9 +2873,7 @@ static int fetch_frame(void *data) cond_resched(); /* sleep for 10 ms, hopefully ;) */ - current->state = TASK_INTERRUPTIBLE; - - schedule_timeout(10*HZ/1000); + msleep_interruptible(10); if (signal_pending(current)) return -EINTR; @@ -2936,8 +2936,7 @@ static int fetch_frame(void *data) CPIA_GRAB_SINGLE, 0, 0, 0); /* FIXME: Trial & error - need up to 70ms for the grab mode change to complete ? */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(70*HZ / 1000); + msleep_interruptible(70); if (signal_pending(current)) return -EINTR; } @@ -2988,8 +2987,7 @@ static int goto_high_power(struct cam_data *cam) { if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) return -EIO; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(40*HZ/1000); /* windows driver does it too */ + msleep_interruptible(40); /* windows driver does it too */ if(signal_pending(current)) return -EINTR; if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) @@ -3059,10 +3057,8 @@ static int set_camera_state(struct cam_data *cam) /* Wait 6 frames for the sensor to get all settings and AEC/ACB to settle */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((6*(cam->params.sensorFps.baserate ? 33 : 40) * - (1 << cam->params.sensorFps.divisor) + 10) * - HZ / 1000); + msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) * + (1 << cam->params.sensorFps.divisor) + 10); if(signal_pending(current)) return -EINTR; @@ -3785,8 +3781,8 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) pos = (unsigned long)(cam->frame_buf); while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { up(&cam->busy_lock); return -EAGAIN; } @@ -4040,19 +4036,16 @@ static int __init cpia_init(void) { printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); -#ifdef CONFIG_PROC_FS - proc_cpia_create(); -#endif -#ifdef CONFIG_KMOD -#ifdef CONFIG_VIDEO_CPIA_PP_MODULE - request_module("cpia_pp"); -#endif + printk(KERN_WARNING "Since in-kernel colorspace conversion is not " + "allowed, it is disabled by default now. Users should fix the " + "applications in case they don't work without conversion " + "reenabled by setting the 'colorspace_conv' module " + "parameter to 1"); -#ifdef CONFIG_VIDEO_CPIA_USB_MODULE - request_module("cpia_usb"); +#ifdef CONFIG_PROC_FS + proc_cpia_create(); #endif -#endif /* CONFIG_KMOD */ #ifdef CONFIG_VIDEO_CPIA_PP cpia_pp_init(); @@ -4060,6 +4053,7 @@ static int __init cpia_init(void) #ifdef CONFIG_VIDEO_CPIA_USB cpia_usb_init(); #endif + return 0; } diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 9f71bef75..de2b190a5 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -1,6 +1,10 @@ -cx88xx-objs := cx88-cards.o cx88-core.o -cx8800-objs := cx88-video.o cx88-tvaudio.o cx88-i2c.o cx88-vbi.o +cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o +cx8800-objs := cx88-video.o cx88-vbi.o +cx8802-objs := cx88-mpeg.o -obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o +obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o +obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o -EXTRA_CFLAGS = -I$(src)/.. +EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core +EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 1e183aae0..01413b045 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1,4 +1,6 @@ /* + * $Id: cx88-cards.c,v 1.47 2004/11/03 09:04:50 kraxel Exp $ + * * device driver for Conexant 2388x based TV cards * card-specific stuff. * @@ -22,8 +24,16 @@ #include #include #include +#include + +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) +# define WITH_DVB 1 +#endif #include "cx88.h" +#ifdef WITH_DVB +#include "cx22702.h" +#endif /* ------------------------------------------------------------------ */ /* board config info */ @@ -85,6 +95,7 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio0 = 0xff00, // internal decoder },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, @@ -92,30 +103,33 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_SVIDEO, .vmux = 2, }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xff10, + }, }, [CX88_BOARD_ATI_WONDER_PRO] = { .name = "ATI TV Wonder Pro", .tuner_type = 44, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x000003ff, - .gpio1 = 0x000000ff, - .gpio2 = 0x000000ff, - .gpio3 = 0x00000000, + .gpio0 = 0x03ff, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, + .gpio0 = 0x03fe, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - + .gpio0 = 0x03fe, }}, }, [CX88_BOARD_WINFAST2000XP] = { .name = "Leadtek Winfast 2000XP Expert", .tuner_type = 44, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -148,48 +162,58 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_AVERTV_303] = { .name = "AverTV Studio 303 (M126)", - .tuner_type = TUNER_PHILIPS_PAL_DK, + .tuner_type = 38, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio1 = 0x309f, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio1 = 0x305f, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio1 = 0x305f, }}, + .radio = { + .type = CX88_RADIO, + }, }, [CX88_BOARD_MSI_TVANYWHERE_MASTER] = { - //added gpio values thanks to Torsten Seeboth - //values for PAL from DScaler + // added gpio values thanks to Michal + // values for PAL from DScaler .name = "MSI TV-@nywhere Master", .tuner_type = 33, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - .gpio3 = 0x00000000, }}, .radio = { - .type = CX88_RADIO, + .type = CX88_RADIO, }, }, [CX88_BOARD_WINFAST_DV2000] = { .name = "Leadtek Winfast DV2000", .tuner_type = 38, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -214,11 +238,11 @@ struct cx88_board cx88_boards[] = { .radio = { .type = CX88_RADIO, }, + .blackbird = 1, }, [CX88_BOARD_IODATA_GVVCP3PCI] = { .name = "IODATA GV-VCP3/PCI", .tuner_type = TUNER_ABSENT, - .needs_tda9887 = 0, .input = {{ .type = CX88_VMUX_COMPOSITE1, .vmux = 0, @@ -233,7 +257,7 @@ struct cx88_board cx88_boards[] = { [CX88_BOARD_PROLINK_PLAYTVPVR] = { .name = "Prolink PlayTV PVR", .tuner_type = 43, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -255,57 +279,179 @@ struct cx88_board cx88_boards[] = { [CX88_BOARD_ASUS_PVR_416] = { .name = "ASUS PVR-416", .tuner_type = 43, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000fde6, - .gpio1 = 0x00000000, // possibly for mpeg data - .gpio2 = 0x000000e9, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? - .gpio1 = 0x00000000, // possibly for mpeg data - .gpio2 = 0x000000e9, - .gpio3 = 0x00000000, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x0000fde2, - .gpio1 = 0x00000000, - .gpio2 = 0x000000e9, - .gpio3 = 0x00000000, }, + .blackbird = 1, }, [CX88_BOARD_MSI_TVANYWHERE] = { .name = "MSI TV-@nywhere", .tuner_type = 33, - .needs_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x00000fbf, - .gpio1 = 0x000000c0, .gpio2 = 0x0000fc08, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00000fbf, - .gpio1 = 0x000000c0, .gpio2 = 0x0000fc68, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x00000fbf, - .gpio1 = 0x000000c0, .gpio2 = 0x0000fc68, - .gpio3 = 0x00000000, }}, }, + [CX88_BOARD_KWORLD_DVB_T] = { + .name = "KWorld/VStream XPert DVB-T", + .tuner_type = TUNER_ABSENT, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + .dvb = 1, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { + .name = "DVICO FusionHDTV DVB-T1", + .tuner_type = TUNER_ABSENT, /* No analog tuner */ + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, + }}, + .dvb = 1, + }, + [CX88_BOARD_KWORLD_LTV883] = { + .name = "KWorld LTV883RF", + .tuner_type = 48, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x07f8, + },{ + .type = CX88_VMUX_DEBUG, + .vmux = 0, + .gpio0 = 0x07f9, // mono from tuner chip + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000007fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000007fa, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000007f8, + }, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = { + .name = "DViCO - FusionHDTV 3 Gold", + .tuner_type = TUNER_MICROTUNE_4042FI5, + /* + GPIO[0] resets DT3302 DTV receiver + 0 - reset asserted + 1 - normal operation + GPIO[1] mutes analog audio output connector + 0 - enable selected source + 1 - mute + GPIO[2] selects source for analog audio output connector + 0 - analog audio input connector on tab + 1 - analog DAC output from CX23881 chip + GPIO[3] selects RF input connector on tuner module + 0 - RF connector labeled CABLE + 1 - RF connector labeled ANT + */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0f0d, + },{ + .type = CX88_VMUX_CABLE, + .vmux = 0, + .gpio0 = 0x0f05, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0f00, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0f00, + }}, +#if 0 + .ts = { + .type = CX88_TS, + .gpio0 = 0x00000f01, /* Hooked to tuner reset bit */ + } +#endif + }, + [CX88_BOARD_HAUPPAUGE_DVB_T1] = { + .name = "Hauppauge Nova-T DVB-T", + .tuner_type = TUNER_ABSENT, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, + .dvb = 1, + }, + [CX88_BOARD_CONEXANT_DVB_T1] = { + .name = "Conexant DVB-T reference design", + .tuner_type = TUNER_ABSENT, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, + .dvb = 1, + }, + [CX88_BOARD_PROVIDEO_PV259] = { + .name = "Provideo PV259", + .tuner_type = TUNER_PHILIPS_FQ1216ME, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + }}, + .blackbird = 1, + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { + .name = "DVICO FusionHDTV DVB-T Plus", + .tuner_type = TUNER_ABSENT, /* No analog tuner */ + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, + }}, + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -369,14 +515,42 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1043, .subdevice = 0x4823, /* with mpeg encoder */ .card = CX88_BOARD_ASUS_PVR_416, - } + },{ + .subvendor = 0x17de, + .subdevice = 0x08a6, + .card = CX88_BOARD_KWORLD_DVB_T, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd810, + .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD, + },{ + .subvendor = 0x18AC, + .subdevice = 0xDB00, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, + },{ + .subvendor = 0x0070, + .subdevice = 0x9002, + .card = CX88_BOARD_HAUPPAUGE_DVB_T1, + },{ + .subvendor = 0x14f1, + .subdevice = 0x0187, + .card = CX88_BOARD_CONEXANT_DVB_T1, + },{ + .subvendor = 0x1540, + .subdevice = 0x2580, + .card = CX88_BOARD_PROVIDEO_PV259, + },{ + .subvendor = 0x18AC, + .subdevice = 0xDB10, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, + } }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); /* ----------------------------------------------------------------------- */ /* some leadtek specific stuff */ -static void __devinit leadtek_eeprom(struct cx8800_dev *dev, u8 *eeprom_data) +static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) { /* This is just for the Winfast 2000 XP board ATM; I don't have data on * any others. @@ -387,16 +561,17 @@ static void __devinit leadtek_eeprom(struct cx8800_dev *dev, u8 *eeprom_data) if (eeprom_data[4] != 0x7d || eeprom_data[5] != 0x10 || eeprom_data[7] != 0x66) { - printk(KERN_WARNING "%s Leadtek eeprom invalid.\n", dev->name); + printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n", + core->name); return; } - dev->has_radio = 1; - dev->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38; + core->has_radio = 1; + core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38; printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: " "tuner=%d, eeprom[0]=0x%02x\n", - dev->name, dev->tuner_type, eeprom_data[0]); + core->name, core->tuner_type, eeprom_data[0]); } @@ -455,18 +630,18 @@ static struct { { TUNER_ABSENT, "Philips TD1536D_FH_44"}, { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"}, { TUNER_LG_PAL_FM, "LG TPI8PSB01D"}, - { TUNER_LG_PAL, "LG TPI8PSB11D"}, + { TUNER_LG_PAL, "LG TPI8PSB11D"}, { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"}, { TUNER_LG_PAL_I, "LG TAPC-I701D"} }; -static void __devinit hauppauge_eeprom(struct cx8800_dev *dev, u8 *eeprom_data) +static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) { unsigned int blk2,tuner,radio,model; if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) { printk(KERN_WARNING "%s: Hauppauge eeprom: invalid\n", - dev->name); + core->name); return; } @@ -477,17 +652,63 @@ static void __devinit hauppauge_eeprom(struct cx8800_dev *dev, u8 *eeprom_data) model = eeprom_data[12] << 8 | eeprom_data[11]; tuner = eeprom_data[9]; radio = eeprom_data[blk2-1] & 0x01; - + if (tuner < ARRAY_SIZE(hauppauge_tuner)) - dev->tuner_type = hauppauge_tuner[tuner].id; + core->tuner_type = hauppauge_tuner[tuner].id; if (radio) - dev->has_radio = 1; - + core->has_radio = 1; + printk(KERN_INFO "%s: hauppauge eeprom: model=%d, " "tuner=%s (%d), radio=%s\n", - dev->name, model, hauppauge_tuner[tuner].name, - dev->tuner_type, radio ? "yes" : "no"); + core->name, model, (tuner < ARRAY_SIZE(hauppauge_tuner) + ? hauppauge_tuner[tuner].name : "?"), + core->tuner_type, radio ? "yes" : "no"); +} + +#ifdef WITH_DVB +static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee) +{ + int model; + int tuner; + char *tname; + + /* Make sure we support the board model */ + model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c]; + switch(model) { + case 90002: + case 90500: + case 90501: + /* known */ + break; + default: + printk("%s: warning: unknown hauppauge model #%d\n", + core->name, model); + break; + } + + /* Make sure we support the tuner */ + tuner = ee[0x2d]; + switch(tuner) { + case 0x4B: + tname = "Thomson DTT 7595"; + core->pll_type = PLLTYPE_DTT7595; + break; + case 0x4C: + tname = "Thomson DTT 7592"; + core->pll_type = PLLTYPE_DTT7592; + break; + default: + printk("%s: error: unknown hauppauge tuner 0x%02x\n", + core->name, tuner); + return -ENODEV; + } + printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%s (%d)\n", + core->name, model, tname, tuner); + + core->pll_addr = 0x61; + core->demod_addr = 0x43; } +#endif /* ----------------------------------------------------------------------- */ /* some GDI (was: Modular Technology) specific stuff */ @@ -527,17 +748,17 @@ static struct { .name = "PHILIPS_FI1216_MK3" }, }; -static void __devinit gdi_eeprom(struct cx8800_dev *dev, u8 *eeprom_data) +static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) { char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) ? gdi_tuner[eeprom_data[0x0d]].name : NULL; - printk(KERN_INFO "%s: GDI: tuner=%s\n", dev->name, + printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name, name ? name : "unknown"); if (NULL == name) return; - dev->tuner_type = gdi_tuner[eeprom_data[0x0d]].id; - dev->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; + core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id; + core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; } /* ----------------------------------------------------------------------- */ @@ -572,56 +793,74 @@ i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len) return 0; } -void cx88_card_list(struct cx8800_dev *dev) +void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) { int i; - if (0 == dev->pci->subsystem_vendor && - 0 == dev->pci->subsystem_device) { + if (0 == pci->subsystem_vendor && + 0 == pci->subsystem_device) { printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n" "%s: be autodetected. Please pass card= insmod option to\n" "%s: workaround that. Redirect complaints to the vendor of\n" "%s: the TV card. Best regards,\n" "%s: -- tux\n", - dev->name,dev->name,dev->name,dev->name,dev->name); + core->name,core->name,core->name,core->name,core->name); } else { printk("%s: Your board isn't known (yet) to the driver. You can\n" "%s: try to pick one of the existing card configs via\n" "%s: card= insmod option. Updating to the latest\n" "%s: version might help as well.\n", - dev->name,dev->name,dev->name,dev->name); + core->name,core->name,core->name,core->name); } printk("%s: Here is a list of valid choices for the card= insmod option:\n", - dev->name); + core->name); for (i = 0; i < cx88_bcount; i++) printk("%s: card=%d -> %s\n", - dev->name, i, cx88_boards[i].name); + core->name, i, cx88_boards[i].name); } -void cx88_card_setup(struct cx8800_dev *dev) +void cx88_card_setup(struct cx88_core *core) { static u8 eeprom[128]; - - switch (dev->board) { + + switch (core->board) { case CX88_BOARD_HAUPPAUGE: - if (0 == dev->i2c_rc) - i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom)); - hauppauge_eeprom(dev,eeprom+8); + if (0 == core->i2c_rc) + i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); + hauppauge_eeprom(core,eeprom+8); break; case CX88_BOARD_GDI: - if (0 == dev->i2c_rc) - i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom)); - gdi_eeprom(dev,eeprom); + if (0 == core->i2c_rc) + i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); + gdi_eeprom(core,eeprom); break; case CX88_BOARD_WINFAST2000XP: - if (0 == dev->i2c_rc) - i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom)); - leadtek_eeprom(dev,eeprom); + if (0 == core->i2c_rc) + i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); + leadtek_eeprom(core,eeprom); + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: + /* Tuner reset is hooked to the tuner out of reset */ + cx_set(MO_GP0_IO, 0x00000101); + cx_clear(MO_GP0_IO, 0x00000001); + msleep(1); + cx_set(MO_GP0_IO, 0x00000101); break; - case CX88_BOARD_ASUS_PVR_416: - dev->has_radio = 1; - break; +#ifdef WITH_DVB + case CX88_BOARD_HAUPPAUGE_DVB_T1: + if (0 == core->i2c_rc) + i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); + hauppauge_eeprom_dvb(core,eeprom); + break; + case CX88_BOARD_CONEXANT_DVB_T1: + core->pll_type = PLLTYPE_DTT7579; + core->pll_addr = 0x60; + core->demod_addr = 0x43; + break; +#endif } + if (cx88_boards[core->board].radio.type == CX88_RADIO) + core->has_radio = 1; } /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 800556791..3239c81ab 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1,4 +1,6 @@ /* + * $Id: cx88-core.c,v 1.15 2004/10/25 11:26:36 kraxel Exp $ + * * device driver for Conexant 2388x based TV cards * driver core * @@ -28,6 +30,7 @@ #include #include #include +#include #include #include "cx88.h" @@ -38,42 +41,33 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -#if 0 -static unsigned int gpio_tracking = 0; -MODULE_PARM(gpio_tracking,"i"); -MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); +static unsigned int core_debug = 0; +module_param(core_debug,int,0644); +MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int ts_nr = -1; -MODULE_PARM(ts_nr,"i"); -MODULE_PARM_DESC(ts_nr,"ts device number"); +static unsigned int latency = UNSET; +module_param(latency,int,0444); +MODULE_PARM_DESC(latency,"pci latency timer"); -static unsigned int vbi_nr = -1; -MODULE_PARM(vbi_nr,"i"); -MODULE_PARM_DESC(vbi_nr,"vbi device number"); +static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr = -1; -MODULE_PARM(radio_nr,"i"); -MODULE_PARM_DESC(radio_nr,"radio device number"); +module_param_array(tuner, int, NULL, 0444); +module_param_array(card, int, NULL, 0444); -static unsigned int oss = 0; -MODULE_PARM(oss,"i"); -MODULE_PARM_DESC(oss,"register oss devices (default: no)"); +MODULE_PARM_DESC(tuner,"tuner type"); +MODULE_PARM_DESC(card,"card type"); -static unsigned int dsp_nr = -1; -MODULE_PARM(dsp_nr,"i"); -MODULE_PARM_DESC(dsp_nr,"oss dsp device number"); +static unsigned int nicam = 0; +module_param(nicam,int,0644); +MODULE_PARM_DESC(nicam,"tv audio is nicam"); -static unsigned int mixer_nr = -1; -MODULE_PARM(mixer_nr,"i"); -MODULE_PARM_DESC(mixer_nr,"oss mixer device number"); -#endif +#define dprintk(level,fmt, arg...) if (core_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) -static unsigned int core_debug = 0; -MODULE_PARM(core_debug,"i"); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); - -#define dprintk(fmt, arg...) if (core_debug) \ - printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) +static unsigned int cx88_devcount; +static LIST_HEAD(cx88_devlist); +static DECLARE_MUTEX(devlist); /* ------------------------------------------------------------------ */ /* debug help functions */ @@ -129,6 +123,7 @@ void cx88_print_ioctl(char *name, unsigned int cmd) } /* ------------------------------------------------------------------ */ +#define NO_SYNC_LINE (-1U) static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, @@ -139,8 +134,9 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, unsigned int line,todo; /* sync instruction */ - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - + if (sync_line != NO_SYNC_LINE) + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + /* scan lines */ sg = sglist; for (line = 0; line < lines; line++) { @@ -212,6 +208,32 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, /* save pointer to jmp instruction address */ risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); + return 0; +} + +int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, + struct scatterlist *sglist, unsigned int bpl, + unsigned int lines) +{ + u32 instructions; + u32 *rp; + int rc; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + syncs + jump (all 2 dwords) */ + instructions = (bpl * lines) / PAGE_SIZE + lines; + instructions += 3 + 4; + if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) + return rc; + + /* write risc instructions */ + rp = risc->cpu; + rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size); return 0; } @@ -259,14 +281,16 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) * * FIFO space allocations: * channel 21 (y video) - 10.0k + * channel 22 (u video) - 2.0k + * channel 23 (v video) - 2.0k * channel 24 (vbi) - 4.0k * channels 25+26 (audio) - 0.5k - * everything else - 2.0k - * TOTAL = 29.0k + * channel 28 (mpeg) - 4.0k + * TOTAL = 25.5k * * Every channel has 160 bytes control data (64 bytes instruction * queue and 6 CDT entries), which is close to 2k total. - * + * * Address layout: * 0x0000 - 0x03ff CMDs / reserved * 0x0400 - 0x0bff instruction queues + CDs @@ -346,9 +370,21 @@ struct sram_channel cx88_sram_channels[] = { .cnt1_reg = MO_DMA26_CNT1, .cnt2_reg = MO_DMA26_CNT2, }, + [SRAM_CH28] = { + .name = "mpeg", + .cmds_start = 0x180200, + .ctrl_start = 0x1807C0, + .cdt = 0x1807C0 + 64, + .fifo_start = 0x185600, + .fifo_size = 0x001000, + .ptr1_reg = MO_DMA28_PTR1, + .ptr2_reg = MO_DMA28_PTR2, + .cnt1_reg = MO_DMA28_CNT1, + .cnt2_reg = MO_DMA28_CNT2, + }, }; -int cx88_sram_channel_setup(struct cx8800_dev *dev, +int cx88_sram_channel_setup(struct cx88_core *core, struct sram_channel *ch, unsigned int bpl, u32 risc) { @@ -378,10 +414,10 @@ int cx88_sram_channel_setup(struct cx8800_dev *dev, /* fill registers */ cx_write(ch->ptr1_reg, ch->fifo_start); cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt1_reg, bpl >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) -1); cx_write(ch->cnt2_reg, (lines*16) >> 3); - dprintk("sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines); + dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines); return 0; } @@ -426,25 +462,25 @@ int cx88_risc_decode(u32 risc) return incr[risc >> 28] ? incr[risc >> 28] : 1; } -void cx88_risc_disasm(struct cx8800_dev *dev, +void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc) { unsigned int i,j,n; - + printk("%s: risc disasm: %p [dma=0x%08lx]\n", - dev->name, risc->cpu, (unsigned long)risc->dma); + core->name, risc->cpu, (unsigned long)risc->dma); for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: %04d: ", dev->name, i); + printk("%s: %04d: ", core->name, i); n = cx88_risc_decode(risc->cpu[i]); for (j = 1; j < n; j++) printk("%s: %04d: 0x%08x [ arg #%d ]\n", - dev->name, i+j, risc->cpu[i+j], j); + core->name, i+j, risc->cpu[i+j], j); if (risc->cpu[i] == RISC_JUMP) break; } } -void cx88_sram_channel_dump(struct cx8800_dev *dev, +void cx88_sram_channel_dump(struct cx88_core *core, struct sram_channel *ch) { static char *name[] = { @@ -463,54 +499,63 @@ void cx88_sram_channel_dump(struct cx8800_dev *dev, u32 risc; unsigned int i,j,n; - printk("%s: %s - dma channel status dump\n",dev->name,ch->name); + printk("%s: %s - dma channel status dump\n", + core->name,ch->name); for (i = 0; i < ARRAY_SIZE(name); i++) printk("%s: cmds: %-12s: 0x%08x\n", - dev->name,name[i], + core->name,name[i], cx_read(ch->cmds_start + 4*i)); for (i = 0; i < 4; i++) { risc = cx_read(ch->cmds_start + 4 * (i+11)); - printk("%s: risc%d: ", dev->name, i); + printk("%s: risc%d: ", core->name, i); cx88_risc_decode(risc); } for (i = 0; i < 16; i += n) { risc = cx_read(ch->ctrl_start + 4 * i); - printk("%s: iq %x: ", dev->name, i); + printk("%s: iq %x: ", core->name, i); n = cx88_risc_decode(risc); for (j = 1; j < n; j++) { risc = cx_read(ch->ctrl_start + 4 * (i+j)); printk("%s: iq %x: 0x%08x [ arg #%d ]\n", - dev->name, i+j, risc, j); + core->name, i+j, risc, j); } } printk("%s: fifo: 0x%08x -> 0x%x\n", - dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); + core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); printk("%s: ctrl: 0x%08x -> 0x%x\n", - dev->name, ch->ctrl_start, ch->ctrl_start+6*16); + core->name, ch->ctrl_start, ch->ctrl_start+6*16); printk("%s: ptr1_reg: 0x%08x\n", - dev->name,cx_read(ch->ptr1_reg)); + core->name,cx_read(ch->ptr1_reg)); printk("%s: ptr2_reg: 0x%08x\n", - dev->name,cx_read(ch->ptr2_reg)); + core->name,cx_read(ch->ptr2_reg)); printk("%s: cnt1_reg: 0x%08x\n", - dev->name,cx_read(ch->cnt1_reg)); + core->name,cx_read(ch->cnt1_reg)); printk("%s: cnt2_reg: 0x%08x\n", - dev->name,cx_read(ch->cnt2_reg)); + core->name,cx_read(ch->cnt2_reg)); } char *cx88_pci_irqs[32] = { - "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1", + "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1", "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err", "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err", "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1" }; char *cx88_vid_irqs[32] = { - "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", + "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", "y_oflow", "u_oflow", "v_oflow", "vbi_oflow", "y_sync", "u_sync", "v_sync", "vbi_sync", "opc_err", "par_err", "rip_err", "pci_abort", }; +char *cx88_mpeg_irqs[32] = { + "ts_risci1", NULL, NULL, NULL, + "ts_risci2", NULL, NULL, NULL, + "ts_oflow", NULL, NULL, NULL, + "ts_sync", NULL, NULL, NULL, + "opc_err", "par_err", "rip_err", "pci_abort", + "ts_err?", +}; void cx88_print_irqbits(char *name, char *tag, char **strings, u32 bits, u32 mask) @@ -521,7 +566,10 @@ void cx88_print_irqbits(char *name, char *tag, char **strings, for (i = 0; i < 32; i++) { if (!(bits & (1 << i))) continue; - printk(" %s",strings[i]); + if (strings[i]) + printk(" %s", strings[i]); + else + printk(" %d", i); if (!(mask & (1 << i))) continue; printk("*"); @@ -531,14 +579,429 @@ void cx88_print_irqbits(char *name, char *tag, char **strings, /* ------------------------------------------------------------------ */ -int cx88_pci_quirks(char *name, struct pci_dev *pci, unsigned int *latency) +void cx88_irq(struct cx88_core *core, u32 status, u32 mask) { - u8 ctrl = 0; - u8 value; + cx88_print_irqbits(core->name, "irq pci", + cx88_pci_irqs, status, mask); +} + +void cx88_wakeup(struct cx88_core *core, + struct cx88_dmaqueue *q, u32 count) +{ + struct cx88_buffer *buf; + int bc; + + for (bc = 0;; bc++) { + if (list_empty(&q->active)) + break; + buf = list_entry(q->active.next, + struct cx88_buffer, vb.queue); +#if 0 + if (buf->count > count) + break; +#else + /* count comes from the hw and is is 16bit wide -- + * this trick handles wrap-arounds correctly for + * up to 32767 buffers in flight... */ + if ((s16) (count - buf->count) < 0) + break; +#endif + do_gettimeofday(&buf->vb.ts); + dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i, + count, buf->count); + buf->vb.state = STATE_DONE; + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); + } + if (list_empty(&q->active)) { + del_timer(&q->timeout); + } else { + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + } + if (bc != 1) + printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); +} + +void cx88_shutdown(struct cx88_core *core) +{ + /* disable RISC controller + IRQs */ + cx_write(MO_DEV_CNTRL2, 0); + + /* stop dma transfers */ + cx_write(MO_VID_DMACNTRL, 0x0); + cx_write(MO_AUD_DMACNTRL, 0x0); + cx_write(MO_TS_DMACNTRL, 0x0); + cx_write(MO_VIP_DMACNTRL, 0x0); + cx_write(MO_GPHST_DMACNTRL, 0x0); + + /* stop interrupts */ + cx_write(MO_PCI_INTMSK, 0x0); + cx_write(MO_VID_INTMSK, 0x0); + cx_write(MO_AUD_INTMSK, 0x0); + cx_write(MO_TS_INTMSK, 0x0); + cx_write(MO_VIP_INTMSK, 0x0); + cx_write(MO_GPHST_INTMSK, 0x0); - if (0 == pci_pci_problems) + /* stop capturing */ + cx_write(VID_CAPTURE_CONTROL, 0); +} + +int cx88_reset(struct cx88_core *core) +{ + dprintk(1,"%s\n",__FUNCTION__); + cx88_shutdown(core); + + /* clear irq status */ + cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int + cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int + cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int + + /* wait a bit */ + msleep(100); + + /* init sram */ + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); + cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0); + + /* misc init ... */ + cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable + (1 << 12) | // agc gain + (1 << 11) | // adaptibe agc + (0 << 10) | // chroma agc + (0 << 9) | // ckillen + (7))); + + /* setup image format */ + cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000); + + /* setup FIFO Threshholds */ + cx_write(MO_PDMA_STHRSH, 0x0807); + cx_write(MO_PDMA_DTHRSH, 0x0807); + + /* fixes flashing of image */ + cx_write(MO_AGC_SYNC_TIP1, 0x0380000F); + cx_write(MO_AGC_BACK_VBI, 0x00E00555); + + cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int + cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int + cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int + + /* Reset on-board parts */ + cx_write(MO_SRST_IO, 0); + msleep(10); + cx_write(MO_SRST_IO, 1); + + return 0; +} + +/* ------------------------------------------------------------------ */ + +static unsigned int inline norm_swidth(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 922 : 754; +} + +static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 186 : 135; +} + +static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18; +} + +static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm) +{ + static const unsigned int ntsc = 28636360; + static const unsigned int pal = 35468950; + + return (norm->id & V4L2_STD_625_50) ? pal : ntsc; +} + +static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) + ? HLNotchFilter135PAL + : HLNotchFilter135NTSC; +} + +static unsigned int inline norm_htotal(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 1135 : 910; +} + +static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 511 : 288; +} + +int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, + enum v4l2_field field) +{ + unsigned int swidth = norm_swidth(core->tvnorm); + unsigned int sheight = norm_maxh(core->tvnorm); + u32 value; + + dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, + V4L2_FIELD_HAS_TOP(field) ? "T" : "", + V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", + core->tvnorm->name); + if (!V4L2_FIELD_HAS_BOTH(field)) + height *= 2; + + // recalc H delay and scale registers + value = (width * norm_hdelay(core->tvnorm)) / swidth; + value &= 0x3fe; + cx_write(MO_HDELAY_EVEN, value); + cx_write(MO_HDELAY_ODD, value); + dprintk(1,"set_scale: hdelay 0x%04x\n", value); + + value = (swidth * 4096 / width) - 4096; + cx_write(MO_HSCALE_EVEN, value); + cx_write(MO_HSCALE_ODD, value); + dprintk(1,"set_scale: hscale 0x%04x\n", value); + + cx_write(MO_HACTIVE_EVEN, width); + cx_write(MO_HACTIVE_ODD, width); + dprintk(1,"set_scale: hactive 0x%04x\n", width); + + // recalc V scale Register (delay is constant) + cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm)); + cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm)); + dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm)); + + value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff; + cx_write(MO_VSCALE_EVEN, value); + cx_write(MO_VSCALE_ODD, value); + dprintk(1,"set_scale: vscale 0x%04x\n", value); + + cx_write(MO_VACTIVE_EVEN, sheight); + cx_write(MO_VACTIVE_ODD, sheight); + dprintk(1,"set_scale: vactive 0x%04x\n", sheight); + + // setup filters + value = 0; + value |= (1 << 19); // CFILT (default) + if (core->tvnorm->id & V4L2_STD_SECAM) { + value |= (1 << 15); + value |= (1 << 16); + } + if (INPUT(core->input)->type == CX88_VMUX_SVIDEO) + value |= (1 << 13) | (1 << 5); + if (V4L2_FIELD_INTERLACED == field) + value |= (1 << 3); // VINT (interlaced vertical scaling) + if (width < 385) + value |= (1 << 0); // 3-tap interpolation + if (width < 193) + value |= (1 << 1); // 5-tap interpolation + + cx_write(MO_FILTER_EVEN, value); + cx_write(MO_FILTER_ODD, value); + dprintk(1,"set_scale: filter 0x%04x\n", value); + + return 0; +} + +static const u32 xtal = 28636363; + +static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) +{ + static u32 pre[] = { 0, 0, 0, 3, 2, 1 }; + u64 pll; + u32 reg; + int i; + + if (prescale < 2) + prescale = 2; + if (prescale > 5) + prescale = 5; + + pll = ofreq * 8 * prescale * (u64)(1 << 20); + do_div(pll,xtal); + reg = (pll & 0x3ffffff) | (pre[prescale] << 26); + if (((reg >> 20) & 0x3f) < 14) { + printk("%s/0: pll out of range\n",core->name); + return -1; + } + + dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n", + reg, cx_read(MO_PLL_REG), ofreq); + cx_write(MO_PLL_REG, reg); + for (i = 0; i < 100; i++) { + reg = cx_read(MO_DEVICE_STATUS); + if (reg & (1<<2)) { + dprintk(1,"pll locked [pre=%d,ofreq=%d]\n", + prescale,ofreq); + return 0; + } + dprintk(1,"pll not locked yet, waiting ...\n"); + msleep(10); + } + dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq); + return -1; +} + +static int set_tvaudio(struct cx88_core *core) +{ + struct cx88_tvnorm *norm = core->tvnorm; + + if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) + return 0; + + if (V4L2_STD_PAL_BG & norm->id) { + core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG; + + } else if (V4L2_STD_PAL_DK & norm->id) { + core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK; + + } else if (V4L2_STD_PAL_I & norm->id) { + core->tvaudio = WW_NICAM_I; + + } else if (V4L2_STD_SECAM_L & norm->id) { + core->tvaudio = WW_SYSTEM_L_AM; + + } else if (V4L2_STD_SECAM_DK & norm->id) { + core->tvaudio = WW_A2_DK; + + } else if ((V4L2_STD_NTSC_M & norm->id) || + (V4L2_STD_PAL_M & norm->id)) { + core->tvaudio = WW_BTSC; + + } else if (V4L2_STD_NTSC_M_JP & norm->id) { + core->tvaudio = WW_EIAJ; + + } else { + printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n", + core->name, norm->name); + core->tvaudio = 0; return 0; + } + + cx_andor(MO_AFECFG_IO, 0x1f, 0x0); + cx88_set_tvaudio(core); + // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); + + cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */ + cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */ + cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */ + return 0; +} + +int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm) +{ + u32 fsc8; + u32 adc_clock; + u32 vdec_clock; + u32 step_db,step_dr; + u64 tmp64; + u32 bdelay,agcdelay,htotal; + + core->tvnorm = norm; + fsc8 = norm_fsc8(norm); + adc_clock = xtal; + vdec_clock = fsc8; + step_db = fsc8; + step_dr = fsc8; + + if (norm->id & V4L2_STD_SECAM) { + step_db = 4250000 * 8; + step_dr = 4406250 * 8; + } + + dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n", + norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr); + set_pll(core,2,vdec_clock); + dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", + norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); + cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat); + +#if 1 + // FIXME: as-is from DScaler + dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", + norm->cxoformat, cx_read(MO_OUTPUT_FORMAT)); + cx_write(MO_OUTPUT_FORMAT, norm->cxoformat); +#endif + + // MO_SCONV_REG = adc clock / video dec clock * 2^17 + tmp64 = adc_clock * (u64)(1 << 17); + do_div(tmp64, vdec_clock); + dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n", + (u32)tmp64, cx_read(MO_SCONV_REG)); + cx_write(MO_SCONV_REG, (u32)tmp64); + + // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22 + tmp64 = step_db * (u64)(1 << 22); + do_div(tmp64, vdec_clock); + dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n", + (u32)tmp64, cx_read(MO_SUB_STEP)); + cx_write(MO_SUB_STEP, (u32)tmp64); + + // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22 + tmp64 = step_dr * (u64)(1 << 22); + do_div(tmp64, vdec_clock); + dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n", + (u32)tmp64, cx_read(MO_SUB_STEP_DR)); + cx_write(MO_SUB_STEP_DR, (u32)tmp64); + + // bdelay + agcdelay + bdelay = vdec_clock * 65 / 20000000 + 21; + agcdelay = vdec_clock * 68 / 20000000 + 15; + dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n", + (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay); + cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay); + + // htotal + tmp64 = norm_htotal(norm) * (u64)vdec_clock; + do_div(tmp64, fsc8); + htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11); + dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n", + htotal, cx_read(MO_HTOTAL), (u32)tmp64); + cx_write(MO_HTOTAL, htotal); + + // vbi stuff + cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ + norm_vbipack(norm))); + + // audio + set_tvaudio(core); + + // tell i2c chips +#ifdef V4L2_I2C_CLIENTS + cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id); +#else + { + struct video_channel c; + memset(&c,0,sizeof(c)); + c.channel = core->input; + c.norm = VIDEO_MODE_PAL; + if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP))) + c.norm = VIDEO_MODE_NTSC; + if (norm->id & V4L2_STD_SECAM) + c.norm = VIDEO_MODE_SECAM; + cx88_call_i2c_clients(core,VIDIOCSCHAN,&c); + } +#endif + + // done + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int cx88_pci_quirks(char *name, struct pci_dev *pci) +{ + unsigned int lat = UNSET; + u8 ctrl = 0; + u8 value; + + /* check pci quirks */ if (pci_pci_problems & PCIPCI_TRITON) { printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", name); @@ -563,25 +1026,174 @@ int cx88_pci_quirks(char *name, struct pci_dev *pci, unsigned int *latency) if (pci_pci_problems & PCIPCI_ALIMAGIK) { printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", name); - *latency = 0x0A; + lat = 0x0A; } #endif + + /* check insmod options */ + if (UNSET != latency) + lat = latency; + + /* apply stuff */ if (ctrl) { pci_read_config_byte(pci, CX88X_DEVCTRL, &value); value |= ctrl; pci_write_config_byte(pci, CX88X_DEVCTRL, value); } + if (UNSET != lat) { + printk(KERN_INFO "%s: setting pci latency timer to %d\n", + name, latency); + pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency); + } return 0; } /* ------------------------------------------------------------------ */ +struct video_device *cx88_vdev_init(struct cx88_core *core, + struct pci_dev *pci, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->dev = &pci->dev; + vfd->release = video_device_release; + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", + core->name, type, cx88_boards[core->board].name); + return vfd; +} + +static int get_ressources(struct cx88_core *core, struct pci_dev *pci) +{ + if (request_mem_region(pci_resource_start(pci,0), + pci_resource_len(pci,0), + core->name)) + return 0; + printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n", + core->name,pci_resource_start(pci,0)); + return -EBUSY; +} + +struct cx88_core* cx88_core_get(struct pci_dev *pci) +{ + struct cx88_core *core; + struct list_head *item; + int i; + + down(&devlist); + list_for_each(item,&cx88_devlist) { + core = list_entry(item, struct cx88_core, devlist); + if (pci->bus->number != core->pci_bus) + continue; + if (PCI_SLOT(pci->devfn) != core->pci_slot) + continue; + + if (0 != get_ressources(core,pci)) + goto fail_unlock; + atomic_inc(&core->refcount); + up(&devlist); + return core; + } + core = kmalloc(sizeof(*core),GFP_KERNEL); + if (NULL == core) + goto fail_unlock; + + memset(core,0,sizeof(*core)); + core->pci_bus = pci->bus->number; + core->pci_slot = PCI_SLOT(pci->devfn); + atomic_inc(&core->refcount); + + core->nr = cx88_devcount++; + sprintf(core->name,"cx88[%d]",core->nr); + if (0 != get_ressources(core,pci)) { + cx88_devcount--; + goto fail_free; + } + list_add_tail(&core->devlist,&cx88_devlist); + + /* PCI stuff */ + cx88_pci_quirks(core->name, pci); + core->lmmio = ioremap(pci_resource_start(pci,0), + pci_resource_len(pci,0)); + core->bmmio = (u8 __iomem *)core->lmmio; + + /* board config */ + core->board = UNSET; + if (card[core->nr] < cx88_bcount) + core->board = card[core->nr]; + for (i = 0; UNSET == core->board && i < cx88_idcount; i++) + if (pci->subsystem_vendor == cx88_subids[i].subvendor && + pci->subsystem_device == cx88_subids[i].subdevice) + core->board = cx88_subids[i].card; + if (UNSET == core->board) { + core->board = CX88_BOARD_UNKNOWN; + cx88_card_list(core,pci); + } + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + core->name,pci->subsystem_vendor, + pci->subsystem_device,cx88_boards[core->board].name, + core->board, card[core->nr] == core->board ? + "insmod option" : "autodetected"); + + core->tuner_type = tuner[core->nr]; + if (UNSET == core->tuner_type) + core->tuner_type = cx88_boards[core->board].tuner_type; + core->tda9887_conf = cx88_boards[core->board].tda9887_conf; + + /* init hardware */ + cx88_reset(core); + cx88_i2c_init(core,pci); + cx88_card_setup(core); + + up(&devlist); + return core; + +fail_free: + kfree(core); +fail_unlock: + up(&devlist); + return NULL; +} + +void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) +{ + release_mem_region(pci_resource_start(pci,0), + pci_resource_len(pci,0)); + + if (!atomic_dec_and_test(&core->refcount)) + return; + + down(&devlist); + if (0 == core->i2c_rc) + i2c_bit_del_bus(&core->i2c_adap); + list_del(&core->devlist); + iounmap(core->lmmio); + cx88_devcount--; + up(&devlist); + kfree(core); +} + +/* ------------------------------------------------------------------ */ + EXPORT_SYMBOL(cx88_print_ioctl); EXPORT_SYMBOL(cx88_pci_irqs); EXPORT_SYMBOL(cx88_vid_irqs); +EXPORT_SYMBOL(cx88_mpeg_irqs); EXPORT_SYMBOL(cx88_print_irqbits); +EXPORT_SYMBOL(cx88_irq); +EXPORT_SYMBOL(cx88_wakeup); +EXPORT_SYMBOL(cx88_reset); +EXPORT_SYMBOL(cx88_shutdown); + EXPORT_SYMBOL(cx88_risc_buffer); +EXPORT_SYMBOL(cx88_risc_databuffer); EXPORT_SYMBOL(cx88_risc_stopper); EXPORT_SYMBOL(cx88_free_buffer); @@ -591,7 +1203,12 @@ EXPORT_SYMBOL(cx88_sram_channels); EXPORT_SYMBOL(cx88_sram_channel_setup); EXPORT_SYMBOL(cx88_sram_channel_dump); -EXPORT_SYMBOL(cx88_pci_quirks); +EXPORT_SYMBOL(cx88_set_tvnorm); +EXPORT_SYMBOL(cx88_set_scale); + +EXPORT_SYMBOL(cx88_vdev_init); +EXPORT_SYMBOL(cx88_core_get); +EXPORT_SYMBOL(cx88_core_put); /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index a04aad36c..866bf4463 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -1,4 +1,6 @@ /* + $Id: cx88-i2c.c,v 1.18 2004/10/13 10:39:00 kraxel Exp $ + cx88-i2c.c -- all the i2c code is here Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -19,7 +21,7 @@ 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. - + */ #include @@ -29,44 +31,55 @@ #include "cx88.h" +static unsigned int i2c_debug = 0; +module_param(i2c_debug, int, 0644); +MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); + +static unsigned int i2c_scan = 0; +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); + +#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) + /* ----------------------------------------------------------------------- */ void cx8800_bit_setscl(void *data, int state) { - struct cx8800_dev *dev = data; + struct cx88_core *core = data; if (state) - dev->i2c_state |= 0x02; + core->i2c_state |= 0x02; else - dev->i2c_state &= ~0x02; - cx_write(MO_I2C, dev->i2c_state); + core->i2c_state &= ~0x02; + cx_write(MO_I2C, core->i2c_state); cx_read(MO_I2C); } void cx8800_bit_setsda(void *data, int state) { - struct cx8800_dev *dev = data; + struct cx88_core *core = data; if (state) - dev->i2c_state |= 0x01; + core->i2c_state |= 0x01; else - dev->i2c_state &= ~0x01; - cx_write(MO_I2C, dev->i2c_state); + core->i2c_state &= ~0x01; + cx_write(MO_I2C, core->i2c_state); cx_read(MO_I2C); } static int cx8800_bit_getscl(void *data) { - struct cx8800_dev *dev = data; + struct cx88_core *core = data; u32 state; - + state = cx_read(MO_I2C); return state & 0x02 ? 1 : 0; } static int cx8800_bit_getsda(void *data) { - struct cx8800_dev *dev = data; + struct cx88_core *core = data; u32 state; state = cx_read(MO_I2C); @@ -75,36 +88,35 @@ static int cx8800_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -#ifndef I2C_PEC -static void cx8800_inc_use(struct i2c_adapter *adap) -{ - MOD_INC_USE_COUNT; -} - -static void cx8800_dec_use(struct i2c_adapter *adap) +static int attach_inform(struct i2c_client *client) { - MOD_DEC_USE_COUNT; + struct cx88_core *core = i2c_get_adapdata(client->adapter); + + dprintk(1, "i2c attach [addr=0x%x,client=%s]\n", + client->addr, i2c_clientname(client)); + if (!client->driver->command) + return 0; + + if (core->tuner_type != UNSET) + client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type); + if (core->tda9887_conf) + client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); + return 0; } -#endif -static int attach_inform(struct i2c_client *client) +static int detach_inform(struct i2c_client *client) { - struct cx8800_dev *dev = i2c_get_adapdata(client->adapter); + struct cx88_core *core = i2c_get_adapdata(client->adapter); - if (dev->tuner_type != UNSET) - cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type); - - if (1 /* fixme: debug */) - printk("%s: i2c attach [client=%s]\n", - dev->name, i2c_clientname(client)); - return 0; + dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client)); + return 0; } -void cx8800_call_i2c_clients(struct cx8800_dev *dev, unsigned int cmd, void *arg) +void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) { - if (0 != dev->i2c_rc) + if (0 != core->i2c_rc) return; - i2c_clients_command(&dev->i2c_adap, cmd, arg); + i2c_clients_command(&core->i2c_adap, cmd, arg); } static struct i2c_algo_bit_data cx8800_i2c_algo_template = { @@ -120,18 +132,11 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = { /* ----------------------------------------------------------------------- */ static struct i2c_adapter cx8800_i2c_adap_template = { -#ifdef I2C_PEC - .owner = THIS_MODULE, -#else - .inc_use = cx8800_inc_use, - .dec_use = cx8800_dec_use, -#endif -#ifdef I2C_CLASS_TV_ANALOG - .class = I2C_CLASS_TV_ANALOG, -#endif I2C_DEVNAME("cx2388x"), + .owner = THIS_MODULE, .id = I2C_HW_B_BT848, .client_register = attach_inform, + .client_unregister = detach_inform, }; static struct i2c_client cx8800_i2c_client_template = { @@ -139,32 +144,68 @@ static struct i2c_client cx8800_i2c_client_template = { .id = -1, }; +static char *i2c_devs[128] = { + [ 0x86 >> 1 ] = "tda9887/cx22702", + [ 0xa0 >> 1 ] = "eeprom", + [ 0xc0 >> 1 ] = "tuner (analog)", + [ 0xc2 >> 1 ] = "tuner (analog/dvb)", +}; + +static void do_i2c_scan(char *name, struct i2c_client *c) +{ + unsigned char buf; + int i,rc; + + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c,&buf,0); + if (rc < 0) + continue; + printk("%s: i2c scan: found device @ 0x%x [%s]\n", + name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } +} + /* init + register i2c algo-bit adapter */ -int __devinit cx8800_i2c_init(struct cx8800_dev *dev) +int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) { - memcpy(&dev->i2c_adap, &cx8800_i2c_adap_template, - sizeof(dev->i2c_adap)); - memcpy(&dev->i2c_algo, &cx8800_i2c_algo_template, - sizeof(dev->i2c_algo)); - memcpy(&dev->i2c_client, &cx8800_i2c_client_template, - sizeof(dev->i2c_client)); - - dev->i2c_adap.dev.parent = &dev->pci->dev; - strlcpy(dev->i2c_adap.name,dev->name,sizeof(dev->i2c_adap.name)); - dev->i2c_algo.data = dev; - i2c_set_adapdata(&dev->i2c_adap,dev); - dev->i2c_adap.algo_data = &dev->i2c_algo; - dev->i2c_client.adapter = &dev->i2c_adap; - - cx8800_bit_setscl(dev,1); - cx8800_bit_setsda(dev,1); - - dev->i2c_rc = i2c_bit_add_bus(&dev->i2c_adap); - printk("%s: i2c register %s\n", dev->name, - (0 == dev->i2c_rc) ? "ok" : "FAILED"); - return dev->i2c_rc; + memcpy(&core->i2c_adap, &cx8800_i2c_adap_template, + sizeof(core->i2c_adap)); + memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, + sizeof(core->i2c_algo)); + memcpy(&core->i2c_client, &cx8800_i2c_client_template, + sizeof(core->i2c_client)); + + if (core->tuner_type != TUNER_ABSENT) + core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; + if (cx88_boards[core->board].dvb) + core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; + + core->i2c_adap.dev.parent = &pci->dev; + strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); + core->i2c_algo.data = core; + i2c_set_adapdata(&core->i2c_adap,core); + core->i2c_adap.algo_data = &core->i2c_algo; + core->i2c_client.adapter = &core->i2c_adap; + + cx8800_bit_setscl(core,1); + cx8800_bit_setsda(core,1); + + core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); + if (0 == core->i2c_rc) { + dprintk(1, "i2c register ok\n"); + if (i2c_scan) + do_i2c_scan(core->name,&core->i2c_client); + } else + printk("%s: i2c register FAILED\n", core->name); + return core->i2c_rc; } +/* ----------------------------------------------------------------------- */ + +EXPORT_SYMBOL(cx88_call_i2c_clients); +EXPORT_SYMBOL(cx88_i2c_init); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index a80b7519e..8638ce57d 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -1,4 +1,6 @@ -/* +/* + $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $ + cx88x-hw.h - CX2388x register offsets Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -502,12 +504,6 @@ #define MO_GPHSTD_DMA 0x350000 // {64}RWp Host downstream #define MO_GPHSTU_DMA 0x350008 // {64}RWp Host upstream -#define MO_GPHSTD_GPCNT 0x35C020 // Host down general purpose counter -#define MO_GPHSTU_GPCNT 0x35C024 // Host up general purpose counter -#define MO_GPHSTD_GPCNTRL 0x38C030 // Host down general purpose control -#define MO_GPHSTU_GPCNTRL 0x38C034 // Host up general purpose control -#define MO_GPHST_DMACNTRL 0x38C040 // Host DMA control -#define MO_GPHST_XFR_STAT 0x38C044 // Host transfer status #define MO_GPHSTU_CNTRL 0x380048 // Host upstream control #1 #define MO_GPHSTD_CNTRL 0x38004C // Host downstream control #2 #define MO_GPHSTD_LNGTH 0x380050 // Host downstream line length @@ -518,6 +514,14 @@ #define MO_GPHST_MUX16 0x380064 // Host muxed 16-bit transfer parameters #define MO_GPHST_MODE 0x380068 // Host mode select +#define MO_GPHSTD_GPCNT 0x35C020 // Host down general purpose counter +#define MO_GPHSTU_GPCNT 0x35C024 // Host up general purpose counter +#define MO_GPHSTD_GPCNTRL 0x38C030 // Host down general purpose control +#define MO_GPHSTU_GPCNTRL 0x38C034 // Host up general purpose control +#define MO_GPHST_DMACNTRL 0x38C040 // Host DMA control +#define MO_GPHST_XFR_STAT 0x38C044 // Host transfer status +#define MO_GPHST_SOFT_RST 0x38C06C // Host software reset + /* ---------------------------------------------------------------------- */ /* RISC instructions */ @@ -555,11 +559,11 @@ /* ---------------------------------------------------------------------- */ /* various constants */ -#define SEL_BTSC 0x01 -#define SEL_EIAJ 0x02 -#define SEL_A2 0x04 +#define SEL_BTSC 0x01 +#define SEL_EIAJ 0x02 +#define SEL_A2 0x04 #define SEL_SAP 0x08 -#define SEL_NICAM 0x10 +#define SEL_NICAM 0x10 #define SEL_FMRADIO 0x20 // AUD_CTL @@ -614,7 +618,7 @@ #define EN_DMTRX_BYPASS (1 << 11) #endif -// Video +// Video #define VID_CAPTURE_CONTROL 0x310180 #define CX23880_CAP_CTL_CAPTURE_VBI_ODD (1<<3) @@ -626,10 +630,10 @@ #define VideoInputMux1 0x1 #define VideoInputMux2 0x2 #define VideoInputMux3 0x3 -#define VideoInputTuner 0x0 -#define VideoInputComposite 0x1 +#define VideoInputTuner 0x0 +#define VideoInputComposite 0x1 #define VideoInputSVideo 0x2 -#define VideoInputOther 0x3 +#define VideoInputOther 0x3 #define Xtal0 0x1 #define Xtal1 0x2 @@ -640,12 +644,12 @@ #define VideoFormatNTSCJapan 0x2 #define VideoFormatNTSC443 0x3 #define VideoFormatPAL 0x4 -#define VideoFormatPALB 0x4 -#define VideoFormatPALD 0x4 -#define VideoFormatPALG 0x4 -#define VideoFormatPALH 0x4 -#define VideoFormatPALI 0x4 -#define VideoFormatPALBDGHI 0x4 +#define VideoFormatPALB 0x4 +#define VideoFormatPALD 0x4 +#define VideoFormatPALG 0x4 +#define VideoFormatPALH 0x4 +#define VideoFormatPALI 0x4 +#define VideoFormatPALBDGHI 0x4 #define VideoFormatPALM 0x5 #define VideoFormatPALN 0x6 #define VideoFormatPALNC 0x7 @@ -657,12 +661,12 @@ #define VideoFormatNTSCJapan27MHz 0x12 #define VideoFormatNTSC44327MHz 0x13 #define VideoFormatPAL27MHz 0x14 -#define VideoFormatPALB27MHz 0x14 -#define VideoFormatPALD27MHz 0x14 -#define VideoFormatPALG27MHz 0x14 -#define VideoFormatPALH27MHz 0x14 -#define VideoFormatPALI27MHz 0x14 -#define VideoFormatPALBDGHI27MHz 0x14 +#define VideoFormatPALB27MHz 0x14 +#define VideoFormatPALD27MHz 0x14 +#define VideoFormatPALG27MHz 0x14 +#define VideoFormatPALH27MHz 0x14 +#define VideoFormatPALI27MHz 0x14 +#define VideoFormatPALBDGHI27MHz 0x14 #define VideoFormatPALM27MHz 0x15 #define VideoFormatPALN27MHz 0x16 #define VideoFormatPALNC27MHz 0x17 @@ -741,8 +745,8 @@ #define CHANNEL_VIP_UP 0xA #define CHANNEL_HOST_DN 0xB #define CHANNEL_HOST_UP 0xC -#define CHANNEL_FIRST 0x1 -#define CHANNEL_LAST 0xC +#define CHANNEL_FIRST 0x1 +#define CHANNEL_LAST 0xC #define GP_COUNT_CONTROL_NONE 0x0 #define GP_COUNT_CONTROL_INC 0x1 @@ -769,15 +773,15 @@ #define DEFAULT_SAT_U_NTSC 0x7F #define DEFAULT_SAT_V_NTSC 0x5A -typedef enum -{ - SOURCE_TUNER = 0, - SOURCE_COMPOSITE, - SOURCE_SVIDEO, - SOURCE_OTHER1, - SOURCE_OTHER2, - SOURCE_COMPVIASVIDEO, - SOURCE_CCIR656 +typedef enum +{ + SOURCE_TUNER = 0, + SOURCE_COMPOSITE, + SOURCE_SVIDEO, + SOURCE_OTHER1, + SOURCE_OTHER2, + SOURCE_COMPVIASVIDEO, + SOURCE_CCIR656 } VIDEOSOURCETYPE; #endif /* _CX88_REG_H_ */ diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index f6def3df9..874d2974d 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -1,4 +1,6 @@ /* + $Id: cx88-tvaudio.c,v 1.24 2004/10/25 11:51:00 kraxel Exp $ + cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version] @@ -16,9 +18,9 @@ Some comes from the dscaler sources, one of the dscaler driver guy works for Conexant ... - + ----------------------------------------------------------------------- - + 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 @@ -49,15 +51,17 @@ #include #include #include +#include +#include #include "cx88.h" static unsigned int audio_debug = 1; -MODULE_PARM(audio_debug,"i"); +module_param(audio_debug,int,0644); MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]"); #define dprintk(fmt, arg...) if (audio_debug) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) + printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) /* ----------------------------------------------------------- */ @@ -93,7 +97,7 @@ struct rlist { u32 val; }; -static void set_audio_registers(struct cx8800_dev *dev, +static void set_audio_registers(struct cx88_core *core, const struct rlist *l) { int i; @@ -115,7 +119,7 @@ static void set_audio_registers(struct cx8800_dev *dev, } } -static void set_audio_start(struct cx8800_dev *dev, +static void set_audio_start(struct cx88_core *core, u32 mode, u32 ctl) { // mute @@ -133,7 +137,7 @@ static void set_audio_start(struct cx8800_dev *dev, cx_write(AUD_CTL, ctl); } -static void set_audio_finish(struct cx8800_dev *dev) +static void set_audio_finish(struct cx88_core *core) { u32 volume; @@ -150,7 +154,7 @@ static void set_audio_finish(struct cx8800_dev *dev) /* ----------------------------------------------------------- */ -static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap) +static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap) { static const struct rlist btsc[] = { /* from dscaler */ @@ -247,19 +251,19 @@ static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap) // dscaler: don't know why to set EN_FMRADIO_EN_RDS if (sap) { dprintk("%s SAP (status: unknown)\n",__FUNCTION__); - set_audio_start(dev, 0x0001, + set_audio_start(core, 0x0001, EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP); - set_audio_registers(dev, btsc_sap); + set_audio_registers(core, btsc_sap); } else { dprintk("%s (status: known-good)\n",__FUNCTION__); - set_audio_start(dev, 0x0001, + set_audio_start(core, 0x0001, EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO); - set_audio_registers(dev, btsc); + set_audio_registers(core, btsc); } - set_audio_finish(dev); + set_audio_finish(core); } -static void set_audio_standard_NICAM(struct cx8800_dev *dev) +static void set_audio_standard_NICAM(struct cx88_core *core) { static const struct rlist nicam_common[] = { /* from dscaler */ @@ -316,24 +320,25 @@ static void set_audio_standard_NICAM(struct cx8800_dev *dev) { /* end of list */ }, }; - set_audio_start(dev, 0x0010, + set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO); - set_audio_registers(dev, nicam_common); - switch (dev->tvaudio) { + set_audio_registers(core, nicam_common); + switch (core->tvaudio) { case WW_NICAM_I: dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__); - set_audio_registers(dev, nicam_pal_i); + set_audio_registers(core, nicam_pal_i); + break; case WW_NICAM_BGDKL: - dprintk("%s PAL NICAM (status: unknown)\n",__FUNCTION__); - set_audio_registers(dev, nicam_default); + dprintk("%s PAL-BGDK NICAM (status: unknown)\n",__FUNCTION__); + set_audio_registers(core, nicam_default); break; }; - set_audio_finish(dev); + set_audio_finish(core); } -static void set_audio_standard_NICAM_L(struct cx8800_dev *dev) +static void set_audio_standard_NICAM_L(struct cx88_core *core) { - /* This is officially wierd.. register dumps indicate windows + /* This is officially weird.. register dumps indicate windows * uses audio mode 4.. A2. Let's operate and find out. */ static const struct rlist nicam_l[] = { @@ -449,13 +454,13 @@ static void set_audio_standard_NICAM_L(struct cx8800_dev *dev) }; dprintk("%s (status: unknown)\n",__FUNCTION__); - set_audio_start(dev, 0x0004, + set_audio_start(core, 0x0004, 0 /* FIXME */); - set_audio_registers(dev, nicam_l); - set_audio_finish(dev); + set_audio_registers(core, nicam_l); + set_audio_finish(core); } -static void set_audio_standard_A2(struct cx8800_dev *dev) +static void set_audio_standard_A2(struct cx88_core *core) { /* from dscaler cvs */ static const struct rlist a2_common[] = { @@ -545,26 +550,33 @@ static void set_audio_standard_A2(struct cx8800_dev *dev) { /* end of list */ }, }; - set_audio_start(dev, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO); - set_audio_registers(dev, a2_common); - switch (dev->tvaudio) { + set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO); + set_audio_registers(core, a2_common); + switch (core->tvaudio) { + case WW_NICAM_I: + /* gives at least mono according to the dscaler guys */ + /* so use use that while nicam is broken ... */ + dprintk("%s PAL-I mono (status: unknown)\n",__FUNCTION__); + set_audio_registers(core, a2_table1); + cx_write(AUD_CTL, EN_A2_FORCE_MONO1); + break; case WW_A2_BG: dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__); - set_audio_registers(dev, a2_table1); + set_audio_registers(core, a2_table1); break; case WW_A2_DK: dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__); - set_audio_registers(dev, a2_table2); + set_audio_registers(core, a2_table2); break; case WW_A2_M: dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__); - set_audio_registers(dev, a2_table3); + set_audio_registers(core, a2_table3); break; }; - set_audio_finish(dev); + set_audio_finish(core); } -static void set_audio_standard_EIAJ(struct cx8800_dev *dev) +static void set_audio_standard_EIAJ(struct cx88_core *core) { static const struct rlist eiaj[] = { /* TODO: eiaj register settings are not there yet ... */ @@ -573,12 +585,12 @@ static void set_audio_standard_EIAJ(struct cx8800_dev *dev) }; dprintk("%s (status: unknown)\n",__FUNCTION__); - set_audio_start(dev, 0x0002, EN_EIAJ_AUTO_STEREO); - set_audio_registers(dev, eiaj); - set_audio_finish(dev); + set_audio_start(core, 0x0002, EN_EIAJ_AUTO_STEREO); + set_audio_registers(core, eiaj); + set_audio_finish(core); } -static void set_audio_standard_FM(struct cx8800_dev *dev) +static void set_audio_standard_FM(struct cx88_core *core) { #if 0 /* FIXME */ switch (dev->audio_properties.FM_deemphasis) @@ -596,7 +608,7 @@ static void set_audio_standard_FM(struct cx8800_dev *dev) cx_write(AUD_DEEMPH1_B0, 0x1C29); cx_write(AUD_DEEMPH1_A1, 0x3FC66); cx_write(AUD_DEEMPH1_B1, 0x399A); - + break; case WW_FM_DEEMPH_75: @@ -618,50 +630,51 @@ static void set_audio_standard_FM(struct cx8800_dev *dev) #endif dprintk("%s (status: unknown)\n",__FUNCTION__); - set_audio_start(dev, 0x0020, EN_FMRADIO_AUTO_STEREO); + set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO); // AB: 10/2/01: this register is not being reset appropriately on occasion. cx_write(AUD_POLYPH80SCALEFAC,3); - set_audio_finish(dev); + set_audio_finish(core); } /* ----------------------------------------------------------- */ -void cx88_set_tvaudio(struct cx8800_dev *dev) +void cx88_set_tvaudio(struct cx88_core *core) { - switch (dev->tvaudio) { + switch (core->tvaudio) { case WW_BTSC: - set_audio_standard_BTSC(dev,0); + set_audio_standard_BTSC(core,0); break; - case WW_NICAM_I: + // case WW_NICAM_I: case WW_NICAM_BGDKL: - set_audio_standard_NICAM(dev); + set_audio_standard_NICAM(core); break; + case WW_NICAM_I: case WW_A2_BG: case WW_A2_DK: case WW_A2_M: - set_audio_standard_A2(dev); + set_audio_standard_A2(core); break; case WW_EIAJ: - set_audio_standard_EIAJ(dev); + set_audio_standard_EIAJ(core); break; case WW_FM: - set_audio_standard_FM(dev); + set_audio_standard_FM(core); break; case WW_SYSTEM_L_AM: - set_audio_standard_NICAM_L(dev); + set_audio_standard_NICAM_L(core); break; case WW_NONE: default: - printk("%s: unknown tv audio mode [%d]\n", - dev->name, dev->tvaudio); + printk("%s/0: unknown tv audio mode [%d]\n", + core->name, core->tvaudio); break; } return; } -void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t) +void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) { static char *m[] = {"stereo", "dual mono", "mono", "sap"}; static char *p[] = {"no pilot", "pilot c1", "pilot c2", "?"}; @@ -670,16 +683,28 @@ void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t) reg = cx_read(AUD_STATUS); mode = reg & 0x03; pilot = (reg >> 2) & 0x03; - dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", - reg, m[mode], p[pilot], - aud_ctl_names[cx_read(AUD_CTL) & 63]); + + if (core->astat != reg) + dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", + reg, m[mode], p[pilot], + aud_ctl_names[cx_read(AUD_CTL) & 63]); + core->astat = reg; t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; t->rxsubchans = V4L2_TUNER_SUB_MONO; t->audmode = V4L2_TUNER_MODE_MONO; - switch (dev->tvaudio) { + switch (core->tvaudio) { + case WW_BTSC: + t->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_SAP; + t->rxsubchans = V4L2_TUNER_SUB_STEREO; + if (1 == pilot) { + /* SAP */ + t->rxsubchans |= V4L2_TUNER_SUB_SAP; + } + break; case WW_A2_BG: case WW_A2_DK: case WW_A2_M: @@ -707,17 +732,33 @@ void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t) return; } -void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) +void cx88_set_stereo(struct cx88_core *core, u32 mode) { u32 ctl = UNSET; u32 mask = UNSET; - switch (dev->tvaudio) { + switch (core->tvaudio) { + case WW_BTSC: + switch (mode) { + case V4L2_TUNER_MODE_MONO: + ctl = EN_BTSC_FORCE_MONO; + mask = 0x3f; + break; + case V4L2_TUNER_MODE_SAP: + ctl = EN_BTSC_FORCE_SAP; + mask = 0x3f; + break; + case V4L2_TUNER_MODE_STEREO: + ctl = EN_BTSC_AUTO_STEREO; + mask = 0x3f; + break; + } + break; case WW_A2_BG: case WW_A2_DK: case WW_A2_M: switch (mode) { - case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: ctl = EN_A2_FORCE_MONO1; mask = 0x3f; @@ -734,7 +775,7 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) break; case WW_NICAM_BGDKL: switch (mode) { - case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_MONO: ctl = EN_NICAM_FORCE_MONO1; mask = 0x3f; break; @@ -747,10 +788,10 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) mask = 0x93f; break; } - break; + break; case WW_FM: switch (mode) { - case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_MONO: ctl = EN_FMRADIO_FORCE_MONO; mask = 0x3f; break; @@ -759,7 +800,7 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) mask = 0x3f; break; } - break; + break; } if (UNSET != ctl) { @@ -774,32 +815,33 @@ void cx88_set_stereo(struct cx8800_dev *dev, u32 mode) return; } -/* just monitor the audio status for now ... */ int cx88_audio_thread(void *data) { - struct cx8800_dev *dev = data; + struct cx88_core *core = data; struct v4l2_tuner t; - daemonize("msp3400"); - allow_signal(SIGTERM); dprintk("cx88: tvaudio thread started\n"); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ*3); - if (signal_pending(current)) - break; - if (dev->shutdown) + if (kthread_should_stop()) break; + /* just monitor the audio status for now ... */ memset(&t,0,sizeof(t)); - cx88_get_stereo(dev,&t); + cx88_get_stereo(core,&t); + msleep_interruptible(1000); } dprintk("cx88: tvaudio thread exiting\n"); - complete_and_exit(&dev->texit, 0); + return 0; } +/* ----------------------------------------------------------- */ + +EXPORT_SYMBOL(cx88_set_tvaudio); +EXPORT_SYMBOL(cx88_set_stereo); +EXPORT_SYMBOL(cx88_get_stereo); +EXPORT_SYMBOL(cx88_audio_thread); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 3c3806ebc..672d1b456 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -1,3 +1,6 @@ +/* + * $Id: cx88-vbi.c,v 1.14 2004/11/07 13:17:15 kraxel Exp $ + */ #include #include #include @@ -6,15 +9,15 @@ #include "cx88.h" static unsigned int vbibufs = 4; -MODULE_PARM(vbibufs,"i"); +module_param(vbibufs,int,0644); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); static unsigned int vbi_debug = 0; -MODULE_PARM(vbi_debug,"i"); -MODULE_PARM_DESC(vbi_debug,"enable debug messages [video]"); +module_param(vbi_debug,int,0644); +MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); #define dprintk(level,fmt, arg...) if (vbi_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) + printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg) /* ------------------------------------------------------------------ */ @@ -28,13 +31,13 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f) f->fmt.vbi.count[0] = VBI_LINE_COUNT; f->fmt.vbi.count[1] = VBI_LINE_COUNT; - if (dev->tvnorm->id & V4L2_STD_525_60) { + if (dev->core->tvnorm->id & V4L2_STD_525_60) { /* ntsc */ f->fmt.vbi.sampling_rate = 28636363; f->fmt.vbi.start[0] = 10 -1; f->fmt.vbi.start[1] = 273 -1; - } else if (V4L2_STD_625_50) { + } else if (dev->core->tvnorm->id & V4L2_STD_625_50) { /* pal */ f->fmt.vbi.sampling_rate = 35468950; f->fmt.vbi.start[0] = 7 -1; @@ -46,8 +49,10 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev, struct cx88_dmaqueue *q, struct cx88_buffer *buf) { + struct cx88_core *core = dev->core; + /* setup fifo + format */ - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH24], + cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24], buf->vb.width, buf->risc.dma); cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup @@ -55,7 +60,7 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev, (1 << 11) )); /* reset counter */ - cx_write(MO_VBI_GPCNTRL,0x3); + cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET); q->count = 1; /* enable irqs */ @@ -72,6 +77,22 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev, return 0; } +int cx8800_stop_vbi_dma(struct cx8800_dev *dev) +{ + struct cx88_core *core = dev->core; + + /* stop dma */ + cx_clear(MO_VID_DMACNTRL, 0x88); + + /* disable capture */ + cx_clear(VID_CAPTURE_CONTROL,0x18); + + /* disable irqs */ + cx_clear(MO_PCI_INTMSK, 0x000001); + cx_clear(MO_VID_INTMSK, 0x0f0088); + return 0; +} + int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q) { @@ -96,11 +117,12 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, void cx8800_vbi_timeout(unsigned long data) { struct cx8800_dev *dev = (struct cx8800_dev*)data; + struct cx88_core *core = dev->core; struct cx88_dmaqueue *q = &dev->vbiq; struct cx88_buffer *buf; unsigned long flags; - cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH24]); + cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]); cx_clear(MO_VID_DMACNTRL, 0x88); cx_clear(VID_CAPTURE_CONTROL, 0x18); @@ -111,7 +133,7 @@ void cx8800_vbi_timeout(unsigned long data) list_del(&buf->vb.queue); buf->vb.state = STATE_ERROR; wake_up(&buf->vb.done); - printk("%s: [%p/%d] timeout - dma=0x%08lx\n", dev->name, + printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name, buf, buf->vb.i, (unsigned long)buf->risc.dma); } cx8800_restart_vbi_queue(dev,q); @@ -121,7 +143,7 @@ void cx8800_vbi_timeout(unsigned long data) /* ------------------------------------------------------------------ */ static int -vbi_setup(struct file *file, unsigned int *count, unsigned int *size) +vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; if (0 == *count) @@ -134,12 +156,12 @@ vbi_setup(struct file *file, unsigned int *count, unsigned int *size) } static int -vbi_prepare(struct file *file, struct videobuf_buffer *vb, +vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { - struct cx8800_fh *fh = file->private_data; + struct cx8800_fh *fh = q->priv_data; struct cx8800_dev *dev = fh->dev; - struct cx88_buffer *buf = (struct cx88_buffer*)vb; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); unsigned int size; int rc; @@ -170,16 +192,16 @@ vbi_prepare(struct file *file, struct videobuf_buffer *vb, } static void -vbi_queue(struct file *file, struct videobuf_buffer *vb) +vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx88_buffer *buf = (struct cx88_buffer*)vb; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); struct cx88_buffer *prev; - struct cx8800_fh *fh = file->private_data; + struct cx8800_fh *fh = vq->priv_data; struct cx8800_dev *dev = fh->dev; struct cx88_dmaqueue *q = &dev->vbiq; /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | 0x10000); + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); if (list_empty(&q->active)) { @@ -202,10 +224,10 @@ vbi_queue(struct file *file, struct videobuf_buffer *vb) } } -static void vbi_release(struct file *file, struct videobuf_buffer *vb) +static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx88_buffer *buf = (struct cx88_buffer*)vb; - struct cx8800_fh *fh = file->private_data; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); + struct cx8800_fh *fh = q->priv_data; cx88_free_buffer(fh->dev->pci,buf); } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index e73b8ce4e..5892e5139 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1,4 +1,6 @@ /* + * $Id: cx88-video.c,v 1.46 2004/11/07 14:44:59 kraxel Exp $ + * * device driver for Conexant 2388x based TV cards * video4linux video interface * @@ -26,12 +28,12 @@ #include #include #include +#include +#include #include #include "cx88.h" -#define V4L2_I2C_CLIENTS 1 - MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -39,108 +41,40 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(video_nr,"1-" __stringify(CX88_MAXBOARDS) "i"); -MODULE_PARM_DESC(video_nr,"video device numbers"); +static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(vbi_nr,"1-" __stringify(CX88_MAXBOARDS) "i"); -MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); +module_param_array(video_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); -static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(radio_nr,"1-" __stringify(CX88_MAXBOARDS) "i"); +MODULE_PARM_DESC(video_nr,"video device numbers"); +MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); MODULE_PARM_DESC(radio_nr,"radio device numbers"); -static unsigned int latency = UNSET; -MODULE_PARM(latency,"i"); -MODULE_PARM_DESC(latency,"pci latency timer"); - static unsigned int video_debug = 0; -MODULE_PARM(video_debug,"i"); +module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); static unsigned int irq_debug = 0; -MODULE_PARM(irq_debug,"i"); +module_param(irq_debug,int,0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); static unsigned int vid_limit = 16; -MODULE_PARM(vid_limit,"i"); +module_param(vid_limit,int,0644); MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); -static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(tuner,"1-" __stringify(CX88_MAXBOARDS) "i"); -MODULE_PARM_DESC(tuner,"tuner type"); - -static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(card,"1-" __stringify(CX88_MAXBOARDS) "i"); -MODULE_PARM_DESC(card,"card type"); - -static unsigned int nicam = 0; -MODULE_PARM(nicam,"i"); -MODULE_PARM_DESC(nicam,"tv audio is nicam"); - #define dprintk(level,fmt, arg...) if (video_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) + printk(KERN_DEBUG "%s/0: " fmt, dev->core->name , ## arg) /* ------------------------------------------------------------------ */ -static struct list_head cx8800_devlist; -static unsigned int cx8800_devcount; +static LIST_HEAD(cx8800_devlist); /* ------------------------------------------------------------------- */ /* static data */ -static unsigned int inline norm_swidth(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 922 : 754; -} - -static unsigned int inline norm_hdelay(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 186 : 135; -} - -static unsigned int inline norm_vdelay(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 0x24 : 0x18; -} - -static unsigned int inline norm_maxw(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 768 : 640; -// return (norm->id & V4L2_STD_625_50) ? 720 : 640; -} - -static unsigned int inline norm_maxh(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 576 : 480; -} - -static unsigned int inline norm_fsc8(struct cx8800_tvnorm *norm) -{ - static const unsigned int ntsc = 28636360; - static const unsigned int pal = 35468950; - - return (norm->id & V4L2_STD_625_50) ? pal : ntsc; -} - -static unsigned int inline norm_notchfilter(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) - ? HLNotchFilter135PAL - : HLNotchFilter135NTSC; -} - -static unsigned int inline norm_htotal(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 1135 : 910; -} - -static unsigned int inline norm_vbipack(struct cx8800_tvnorm *norm) -{ - return (norm->id & V4L2_STD_625_50) ? 511 : 288; -} - -static struct cx8800_tvnorm tvnorms[] = { +static struct cx88_tvnorm tvnorms[] = { { .name = "NTSC-M", .id = V4L2_STD_NTSC_M, @@ -273,7 +207,7 @@ static struct cx8800_fmt formats[] = { static struct cx8800_fmt* format_by_fourcc(unsigned int fourcc) { unsigned int i; - + for (i = 0; i < ARRAY_SIZE(formats); i++) if (formats[i].fourcc == fourcc) return formats+i; @@ -443,264 +377,33 @@ void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) /* ------------------------------------------------------------------ */ -static const u32 xtal = 28636363; - -static int set_pll(struct cx8800_dev *dev, int prescale, u32 ofreq) -{ - static u32 pre[] = { 0, 0, 0, 3, 2, 1 }; - u64 pll; - u32 reg; - int i; - - if (prescale < 2) - prescale = 2; - if (prescale > 5) - prescale = 5; - - pll = ofreq * 8 * prescale * (u64)(1 << 20); - do_div(pll,xtal); - reg = (pll & 0x3ffffff) | (pre[prescale] << 26); - if (((reg >> 20) & 0x3f) < 14) { - printk("%s: pll out of range\n",dev->name); - return -1; - } - - dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n", - reg, cx_read(MO_PLL_REG), ofreq); - cx_write(MO_PLL_REG, reg); - for (i = 0; i < 10; i++) { - reg = cx_read(MO_DEVICE_STATUS); - if (reg & (1<<2)) { - dprintk(1,"pll locked [pre=%d,ofreq=%d]\n", - prescale,ofreq); - return 0; - } - dprintk(1,"pll not locked yet, waiting ...\n"); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); - } - dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq); - return -1; -} - -static int set_tvaudio(struct cx8800_dev *dev) -{ - if (CX88_VMUX_TELEVISION != INPUT(dev->input)->type) - return 0; - - if (V4L2_STD_PAL_BG & dev->tvnorm->id) { - dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG; - - } else if (V4L2_STD_PAL_DK & dev->tvnorm->id) { - dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK; - - } else if (V4L2_STD_PAL_I & dev->tvnorm->id) { - dev->tvaudio = WW_NICAM_I; - - } else if (V4L2_STD_SECAM_L & dev->tvnorm->id) { - dev->tvaudio = WW_SYSTEM_L_AM; - - } else if (V4L2_STD_SECAM_DK & dev->tvnorm->id) { - dev->tvaudio = WW_A2_DK; - - } else if ((V4L2_STD_NTSC_M & dev->tvnorm->id) || - (V4L2_STD_PAL_M & dev->tvnorm->id)) { - dev->tvaudio = WW_BTSC; - - } else if (V4L2_STD_NTSC_M_JP & dev->tvnorm->id) { - dev->tvaudio = WW_EIAJ; - - } else { - printk("%s: tvaudio support needs work for this tv norm [%s], sorry\n", - dev->name, dev->tvnorm->name); - dev->tvaudio = 0; - return 0; - } - - cx_andor(MO_AFECFG_IO, 0x1f, 0x0); - cx88_set_tvaudio(dev); - // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); - - cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */ - cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */ - cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */ - return 0; -} - -static int set_tvnorm(struct cx8800_dev *dev, struct cx8800_tvnorm *norm) -{ - u32 fsc8; - u32 adc_clock; - u32 vdec_clock; - u64 tmp64; - u32 bdelay,agcdelay,htotal; - - dev->tvnorm = norm; - fsc8 = norm_fsc8(norm); - adc_clock = xtal; - vdec_clock = fsc8; - - dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d\n", - norm->name, fsc8, adc_clock, vdec_clock); - set_pll(dev,2,vdec_clock); - - dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", - norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); - cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat); - -#if 1 - // FIXME: as-is from DScaler - dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", - norm->cxoformat, cx_read(MO_OUTPUT_FORMAT)); - cx_write(MO_OUTPUT_FORMAT, norm->cxoformat); -#endif - - // MO_SCONV_REG = adc clock / video dec clock * 2^17 - tmp64 = adc_clock * (u64)(1 << 17); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SCONV_REG)); - cx_write(MO_SCONV_REG, (u32)tmp64); - - // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22 - tmp64 = fsc8 * (u64)(1 << 22); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SUB_STEP)); - cx_write(MO_SUB_STEP, (u32)tmp64); - - // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22 - tmp64 = 4406250 * 8 * (u64)(1 << 22); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SUB_STEP_DR)); - cx_write(MO_SUB_STEP_DR, (u32)tmp64); - - // bdelay + agcdelay - bdelay = vdec_clock * 65 / 20000000 + 21; - agcdelay = vdec_clock * 68 / 20000000 + 15; - dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n", - (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay); - cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay); - - // htotal - tmp64 = norm_htotal(norm) * (u64)vdec_clock; - do_div(tmp64, fsc8); - htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11); - dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n", - htotal, cx_read(MO_HTOTAL), (u32)tmp64); - cx_write(MO_HTOTAL, htotal); - - // vbi stuff - cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ - norm_vbipack(norm))); - - // audio - set_tvaudio(dev); - - // tell i2c chips -#ifdef V4L2_I2C_CLIENTS - cx8800_call_i2c_clients(dev,VIDIOC_S_STD,&norm->id); -#else - { - struct video_channel c; - memset(&c,0,sizeof(c)); - c.channel = dev->input; - c.norm = VIDEO_MODE_PAL; - if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP))) - c.norm = VIDEO_MODE_NTSC; - if (norm->id & V4L2_STD_SECAM) - c.norm = VIDEO_MODE_SECAM; - cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c); - } -#endif - - // done - return 0; -} - -static int set_scale(struct cx8800_dev *dev, unsigned int width, unsigned int height, - enum v4l2_field field) -{ - unsigned int swidth = norm_swidth(dev->tvnorm); - unsigned int sheight = norm_maxh(dev->tvnorm); - u32 value; - - dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, - V4L2_FIELD_HAS_TOP(field) ? "T" : "", - V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", - dev->tvnorm->name); - if (!V4L2_FIELD_HAS_BOTH(field)) - height *= 2; - - // recalc H delay and scale registers - value = (width * norm_hdelay(dev->tvnorm)) / swidth; - value &= 0x3fe; - cx_write(MO_HDELAY_EVEN, value); - cx_write(MO_HDELAY_ODD, value); - dprintk(1,"set_scale: hdelay 0x%04x\n", value); - - value = (swidth * 4096 / width) - 4096; - cx_write(MO_HSCALE_EVEN, value); - cx_write(MO_HSCALE_ODD, value); - dprintk(1,"set_scale: hscale 0x%04x\n", value); - - cx_write(MO_HACTIVE_EVEN, width); - cx_write(MO_HACTIVE_ODD, width); - dprintk(1,"set_scale: hactive 0x%04x\n", width); - - // recalc V scale Register (delay is constant) - cx_write(MO_VDELAY_EVEN, norm_vdelay(dev->tvnorm)); - cx_write(MO_VDELAY_ODD, norm_vdelay(dev->tvnorm)); - dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(dev->tvnorm)); - - value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff; - cx_write(MO_VSCALE_EVEN, value); - cx_write(MO_VSCALE_ODD, value); - dprintk(1,"set_scale: vscale 0x%04x\n", value); - - cx_write(MO_VACTIVE_EVEN, sheight); - cx_write(MO_VACTIVE_ODD, sheight); - dprintk(1,"set_scale: vactive 0x%04x\n", sheight); - - // setup filters - value = 0; - value |= (1 << 19); // CFILT (default) - if (V4L2_FIELD_INTERLACED == field) - value |= (1 << 3); // VINT (interlaced vertical scaling) - if (width < 385) - value |= (1 << 0); // 3-tap interpolation - if (width < 193) - value |= (1 << 1); // 5-tap interpolation - - cx_write(MO_FILTER_EVEN, value); - cx_write(MO_FILTER_ODD, value); - dprintk(1,"set_scale: filter 0x%04x\n", value); - - return 0; -} - static int video_mux(struct cx8800_dev *dev, unsigned int input) { + struct cx88_core *core = dev->core; + dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n", input, INPUT(input)->vmux, INPUT(input)->gpio0,INPUT(input)->gpio1, INPUT(input)->gpio2,INPUT(input)->gpio3); - dev->input = input; + dev->core->input = input; cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14); + cx_write(MO_GP3_IO, INPUT(input)->gpio3); cx_write(MO_GP0_IO, INPUT(input)->gpio0); cx_write(MO_GP1_IO, INPUT(input)->gpio1); cx_write(MO_GP2_IO, INPUT(input)->gpio2); - cx_write(MO_GP3_IO, INPUT(input)->gpio3); switch (INPUT(input)->type) { case CX88_VMUX_SVIDEO: cx_set(MO_AFECFG_IO, 0x00000001); cx_set(MO_INPUT_FORMAT, 0x00010010); + cx_set(MO_FILTER_EVEN, 0x00002020); + cx_set(MO_FILTER_ODD, 0x00002020); break; default: cx_clear(MO_AFECFG_IO, 0x00000001); cx_clear(MO_INPUT_FORMAT, 0x00010010); + cx_clear(MO_FILTER_EVEN, 0x00002020); + cx_clear(MO_FILTER_ODD, 0x00002020); break; } return 0; @@ -712,23 +415,25 @@ static int start_video_dma(struct cx8800_dev *dev, struct cx88_dmaqueue *q, struct cx88_buffer *buf) { + struct cx88_core *core = dev->core; + /* setup fifo + format */ - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21], + cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH21], buf->bpl, buf->risc.dma); - set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field); + cx88_set_scale(dev->core, buf->vb.width, buf->vb.height, buf->vb.field); cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma); /* reset counter */ - cx_write(MO_VIDY_GPCNTRL,0x3); + cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); q->count = 1; /* enable irqs */ cx_set(MO_PCI_INTMSK, 0x00fc01); cx_set(MO_VID_INTMSK, 0x0f0011); - + /* enable capture */ cx_set(VID_CAPTURE_CONTROL,0x06); - + /* start dma */ cx_set(MO_DEV_CNTRL2, (1<<5)); cx_set(MO_VID_DMACNTRL, 0x11); @@ -736,12 +441,28 @@ static int start_video_dma(struct cx8800_dev *dev, return 0; } +static int stop_video_dma(struct cx8800_dev *dev) +{ + struct cx88_core *core = dev->core; + + /* stop dma */ + cx_clear(MO_VID_DMACNTRL, 0x11); + + /* disable capture */ + cx_clear(VID_CAPTURE_CONTROL,0x06); + + /* disable irqs */ + cx_clear(MO_PCI_INTMSK, 0x000001); + cx_clear(MO_VID_INTMSK, 0x0f0011); + return 0; +} + static int restart_video_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q) { struct cx88_buffer *buf, *prev; struct list_head *item; - + if (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); dprintk(2,"restart_queue [%p/%d]: restart dma\n", @@ -790,10 +511,10 @@ static int restart_video_queue(struct cx8800_dev *dev, /* ------------------------------------------------------------------ */ static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - struct cx8800_fh *fh = file->private_data; - + struct cx8800_fh *fh = q->priv_data; + *size = fh->fmt->depth*fh->width*fh->height >> 3; if (0 == *count) *count = 32; @@ -803,17 +524,17 @@ buffer_setup(struct file *file, unsigned int *count, unsigned int *size) } static int -buffer_prepare(struct file *file, struct videobuf_buffer *vb, +buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { - struct cx8800_fh *fh = file->private_data; + struct cx8800_fh *fh = q->priv_data; struct cx8800_dev *dev = fh->dev; - struct cx88_buffer *buf = (struct cx88_buffer*)vb; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); int rc, init_buffer = 0; BUG_ON(NULL == fh->fmt); - if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || - fh->height < 32 || fh->height > norm_maxh(dev->tvnorm)) + if (fh->width < 48 || fh->width > norm_maxw(dev->core->tvnorm) || + fh->height < 32 || fh->height > norm_maxh(dev->core->tvnorm)) return -EINVAL; buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) @@ -887,16 +608,16 @@ buffer_prepare(struct file *file, struct videobuf_buffer *vb, } static void -buffer_queue(struct file *file, struct videobuf_buffer *vb) +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx88_buffer *buf = (struct cx88_buffer*)vb; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); struct cx88_buffer *prev; - struct cx8800_fh *fh = file->private_data; + struct cx8800_fh *fh = vq->priv_data; struct cx8800_dev *dev = fh->dev; struct cx88_dmaqueue *q = &dev->vidq; /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | 0x10000); + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); if (!list_empty(&q->queued)) { @@ -935,10 +656,10 @@ buffer_queue(struct file *file, struct videobuf_buffer *vb) } } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx88_buffer *buf = (struct cx88_buffer*)vb; - struct cx8800_fh *fh = file->private_data; + struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); + struct cx8800_fh *fh = q->priv_data; cx88_free_buffer(fh->dev->pci,buf); } @@ -998,7 +719,7 @@ static u32* ov_risc_field(struct cx8800_dev *dev, struct cx8800_fh *fh, ra = addr + (fh->fmt->depth>>3)*start; else ra = 0; - + if (0 == start) ri |= RISC_SOL; if (fh->win.w.width == end) @@ -1021,11 +742,11 @@ static int ov_risc_frame(struct cx8800_dev *dev, struct cx8800_fh *fh, u32 instructions,fields; u32 *rp; int rc; - + /* skip list for window clipping */ if (NULL == (skips = kmalloc(sizeof(*skips) * fh->nclips,GFP_KERNEL))) return -ENOMEM; - + fields = 0; if (V4L2_FIELD_HAS_TOP(fh->win.field)) fields++; @@ -1077,8 +798,8 @@ static int verify_window(struct cx8800_dev *dev, struct v4l2_window *win) return -EINVAL; field = win->field; - maxw = norm_maxw(dev->tvnorm); - maxh = norm_maxh(dev->tvnorm); + maxw = norm_maxw(core->tvnorm); + maxh = norm_maxh(core->tvnorm); if (V4L2_FIELD_ANY == field) { field = (win->w.height > maxh/2) @@ -1151,7 +872,7 @@ static int setup_window(struct cx8800_dev *dev, struct cx8800_fh *fh, default: BUG(); } - + down(&fh->vidq.lock); if (fh->clips) kfree(fh->clips); @@ -1161,13 +882,13 @@ static int setup_window(struct cx8800_dev *dev, struct cx8800_fh *fh, #if 0 fh->ov.setup_ok = 1; #endif - + /* update overlay if needed */ retval = 0; #if 0 if (check_btres(fh, RESOURCE_OVERLAY)) { struct bttv_buffer *new; - + new = videobuf_alloc(sizeof(*new)); bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); @@ -1214,7 +935,7 @@ static int video_open(struct inode *inode, struct file *file) struct list_head *list; enum v4l2_buf_type type = 0; int radio = 0; - + list_for_each(list,&cx8800_devlist) { h = list_entry(list, struct cx8800_dev, devlist); if (h->video_dev->minor == minor) { @@ -1254,25 +975,27 @@ static int video_open(struct inode *inode, struct file *file) dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct cx88_buffer)); + sizeof(struct cx88_buffer), + fh); videobuf_queue_init(&fh->vbiq, &cx8800_vbi_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, - sizeof(struct cx88_buffer)); - init_MUTEX(&fh->vidq.lock); - init_MUTEX(&fh->vbiq.lock); + sizeof(struct cx88_buffer), + fh); if (fh->radio) { + struct cx88_core *core = dev->core; + int board = core->board; dprintk(1,"video_open: setting radio device\n"); - cx_write(MO_GP0_IO, cx88_boards[dev->board].radio.gpio0); - cx_write(MO_GP1_IO, cx88_boards[dev->board].radio.gpio1); - cx_write(MO_GP2_IO, cx88_boards[dev->board].radio.gpio2); - cx_write(MO_GP3_IO, cx88_boards[dev->board].radio.gpio3); - dev->tvaudio = WW_FM; - cx88_set_tvaudio(dev); - cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); - cx8800_call_i2c_clients(dev,AUDC_SET_RADIO,NULL); + cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); + cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); + cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); + cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); + dev->core->tvaudio = WW_FM; + cx88_set_tvaudio(core); + cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO); + cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL); } return 0; @@ -1287,11 +1010,13 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (res_locked(fh->dev,RESOURCE_VIDEO)) return -EBUSY; - return videobuf_read_one(file, &fh->vidq, data, count, ppos); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); case V4L2_BUF_TYPE_VBI_CAPTURE: if (!res_get(fh->dev,fh,RESOURCE_VBI)) return -EBUSY; - return videobuf_read_stream(file, &fh->vbiq, data, count, ppos, 1); + return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, + file->f_flags & O_NONBLOCK); default: BUG(); return 0; @@ -1302,12 +1027,30 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) { struct cx8800_fh *fh = file->private_data; + struct cx88_buffer *buf; - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + if (!res_get(fh->dev,fh,RESOURCE_VBI)) + return POLLERR; return videobuf_poll_stream(file, &fh->vbiq, wait); + } - /* FIXME */ - return POLLERR; + if (res_check(fh,RESOURCE_VIDEO)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream); + } else { + /* read() capture */ + buf = (struct cx88_buffer*)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == STATE_DONE || + buf->vb.state == STATE_ERROR) + return POLLIN|POLLRDNORM; + return 0; } static int video_release(struct inode *inode, struct file *file) @@ -1323,20 +1066,20 @@ static int video_release(struct inode *inode, struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO)) { - videobuf_queue_cancel(file,&fh->vidq); + videobuf_queue_cancel(&fh->vidq); res_free(dev,fh,RESOURCE_VIDEO); } if (fh->vidq.read_buf) { - buffer_release(file,fh->vidq.read_buf); + buffer_release(&fh->vidq,fh->vidq.read_buf); kfree(fh->vidq.read_buf); } /* stop vbi capture */ if (res_check(fh, RESOURCE_VBI)) { if (fh->vbiq.streaming) - videobuf_streamoff(file,&fh->vbiq); + videobuf_streamoff(&fh->vbiq); if (fh->vbiq.reading) - videobuf_read_stop(file,&fh->vbiq); + videobuf_read_stop(&fh->vbiq); res_free(dev,fh,RESOURCE_VBI); } @@ -1350,17 +1093,18 @@ video_mmap(struct file *file, struct vm_area_struct * vma) { struct cx8800_fh *fh = file->private_data; - return videobuf_mmap_mapper(vma, get_queue(fh)); + return videobuf_mmap_mapper(get_queue(fh), vma); } /* ------------------------------------------------------------------ */ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) { + struct cx88_core *core = dev->core; struct cx88_ctrl *c = NULL; u32 value; int i; - + for (i = 0; i < CX8800_CTLS; i++) if (cx8800_ctls[i].v.id == ctl->id) c = &cx8800_ctls[i]; @@ -1384,6 +1128,7 @@ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) { + struct cx88_core *core = dev->core; struct cx88_ctrl *c = NULL; u32 v_sat_value; u32 value; @@ -1484,8 +1229,8 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, return -EINVAL; field = f->fmt.pix.field; - maxw = norm_maxw(dev->tvnorm); - maxh = norm_maxh(dev->tvnorm); + maxw = norm_maxw(dev->core->tvnorm); + maxh = norm_maxh(dev->core->tvnorm); if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) @@ -1533,7 +1278,7 @@ static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, struct v4l2_format *f) { int err; - + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: err = cx8800_try_fmt(dev,fh,f); @@ -1561,23 +1306,24 @@ static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh, static int video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct cx8800_fh *fh = file->private_data; - struct cx8800_dev *dev = fh->dev; + struct cx8800_fh *fh = file->private_data; + struct cx8800_dev *dev = fh->dev; + struct cx88_core *core = dev->core; #if 0 unsigned long flags; #endif int err; if (video_debug > 1) - cx88_print_ioctl(dev->name,cmd); + cx88_print_ioctl(core->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; - + memset(cap,0,sizeof(*cap)); strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, cx88_boards[dev->board].name, + strlcpy(cap->card, cx88_boards[core->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; @@ -1590,7 +1336,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_OVERLAY | #endif 0; - if (UNSET != dev->tuner_type) + if (UNSET != core->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0; @@ -1616,7 +1362,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { v4l2_std_id *id = arg; - *id = dev->tvnorm->id; + *id = core->tvnorm->id; return 0; } case VIDIOC_S_STD: @@ -1631,7 +1377,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return -EINVAL; down(&dev->lock); - set_tvnorm(dev,&tvnorms[i]); + cx88_set_tvnorm(dev->core,&tvnorms[i]); up(&dev->lock); return 0; } @@ -1644,8 +1390,10 @@ static int video_do_ioctl(struct inode *inode, struct file *file, [ CX88_VMUX_COMPOSITE2 ] = "Composite2", [ CX88_VMUX_COMPOSITE3 ] = "Composite3", [ CX88_VMUX_COMPOSITE4 ] = "Composite4", - [ CX88_VMUX_TELEVISION ] = "Television", [ CX88_VMUX_SVIDEO ] = "S-Video", + [ CX88_VMUX_TELEVISION ] = "Television", + [ CX88_VMUX_CABLE ] = "Cable TV", + [ CX88_VMUX_DVB ] = "DVB", [ CX88_VMUX_DEBUG ] = "for debug only", }; struct v4l2_input *i = arg; @@ -1660,7 +1408,8 @@ static int video_do_ioctl(struct inode *inode, struct file *file, i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name,iname[INPUT(n)->type]); - if (CX88_VMUX_TELEVISION == INPUT(n)->type) + if ((CX88_VMUX_TELEVISION == INPUT(n)->type) || + (CX88_VMUX_CABLE == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; for (n = 0; n < ARRAY_SIZE(tvnorms); n++) i->std |= tvnorms[n].id; @@ -1670,13 +1419,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { unsigned int *i = arg; - *i = dev->input; + *i = dev->core->input; return 0; } case VIDIOC_S_INPUT: { unsigned int *i = arg; - + if (*i >= 4) return -EINVAL; down(&dev->lock); @@ -1685,6 +1434,38 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return 0; } + +#if 0 + /* needs review */ + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *a = arg; + unsigned int n = a->index; + + memset(a,0,sizeof(*a)); + a->index = n; + switch (n) { + case 0: + if ((CX88_VMUX_TELEVISION == INPUT(n)->type) + || (CX88_VMUX_CABLE == INPUT(n)->type)) { + strcpy(a->name,"Television"); + // FIXME figure out if stereo received and set V4L2_AUDCAP_STEREO. + return 0; + } + break; + case 1: + if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD == core->board) { + strcpy(a->name,"Line In"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; + } + break; + } + // Audio input not available. + return -EINVAL; + } +#endif + /* --- capture ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: { @@ -1748,14 +1529,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return get_control(dev,arg); case VIDIOC_S_CTRL: return set_control(dev,arg); - + /* --- tuner ioctls ------------------------------------------ */ case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; u32 reg; - - if (UNSET == dev->tuner_type) + + if (UNSET == core->tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1766,7 +1547,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; - cx88_get_stereo(dev ,t); + cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; return 0; @@ -1775,18 +1556,18 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { struct v4l2_tuner *t = arg; - if (UNSET == dev->tuner_type) + if (UNSET == core->tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL; - cx88_set_stereo(dev,t->audmode); + cx88_set_stereo(core, t->audmode); return 0; } case VIDIOC_G_FREQUENCY: { struct v4l2_frequency *f = arg; - if (UNSET == dev->tuner_type) + if (UNSET == core->tuner_type) return -EINVAL; if (f->tuner != 0) return -EINVAL; @@ -1799,7 +1580,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { struct v4l2_frequency *f = arg; - if (UNSET == dev->tuner_type) + if (UNSET == core->tuner_type) return -EINVAL; if (f->tuner != 0) return -EINVAL; @@ -1810,9 +1591,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file, down(&dev->lock); dev->freq = f->frequency; #ifdef V4L2_I2C_CLIENTS - cx8800_call_i2c_clients(dev,VIDIOC_S_FREQUENCY,f); + cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f); #else - cx8800_call_i2c_clients(dev,VIDIOCSFREQ,&dev->freq); + cx88_call_i2c_clients(dev->core,VIDIOCSFREQ,&dev->freq); #endif up(&dev->lock); return 0; @@ -1831,7 +1612,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, req.type = q->type; req.count = 8; req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(file,q,&req); + err = videobuf_reqbufs(q,&req); if (err < 0) return err; memset(mbuf,0,sizeof(*mbuf)); @@ -1844,16 +1625,17 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return 0; } case VIDIOC_REQBUFS: - return videobuf_reqbufs(file, get_queue(fh), arg); + return videobuf_reqbufs(get_queue(fh), arg); case VIDIOC_QUERYBUF: return videobuf_querybuf(get_queue(fh), arg); case VIDIOC_QBUF: - return videobuf_qbuf(file, get_queue(fh), arg); + return videobuf_qbuf(get_queue(fh), arg); case VIDIOC_DQBUF: - return videobuf_dqbuf(file, get_queue(fh), arg); + return videobuf_dqbuf(get_queue(fh), arg, + file->f_flags & O_NONBLOCK); case VIDIOC_STREAMON: { @@ -1861,13 +1643,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (!res_get(dev,fh,res)) return -EBUSY; - return videobuf_streamon(file, get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } case VIDIOC_STREAMOFF: { int res = get_ressource(fh); - err = videobuf_streamoff(file, get_queue(fh)); + err = videobuf_streamoff(get_queue(fh)); if (err < 0) return err; res_free(dev,fh,res); @@ -1892,20 +1674,21 @@ static int video_ioctl(struct inode *inode, struct file *file, static int radio_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct cx8800_fh *fh = file->private_data; - struct cx8800_dev *dev = fh->dev; - + struct cx8800_fh *fh = file->private_data; + struct cx8800_dev *dev = fh->dev; + struct cx88_core *core = dev->core; + if (video_debug > 1) - cx88_print_ioctl(dev->name,cmd); + cx88_print_ioctl(core->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; - + memset(cap,0,sizeof(*cap)); strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, cx88_boards[dev->board].name, + strlcpy(cap->card, cx88_boards[core->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; @@ -1923,14 +1706,14 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, strcpy(t->name, "Radio"); t->rangelow = (int)(65*16); t->rangehigh = (int)(108*16); - + #ifdef V4L2_I2C_CLIENTS - cx8800_call_i2c_clients(dev,VIDIOC_G_TUNER,t); + cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t); #else { struct video_tuner vt; memset(&vt,0,sizeof(vt)); - cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt); + cx88_call_i2c_clients(dev,VIDIOCGTUNER,&vt); t->signal = vt.signal; } #endif @@ -1939,7 +1722,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; - + if (i->index != 0) return -EINVAL; strcpy(i->name,"Radio"); @@ -1996,7 +1779,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: return video_do_ioctl(inode,file,cmd,arg); - + default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, radio_do_ioctl); @@ -2015,13 +1798,13 @@ static int radio_ioctl(struct inode *inode, struct file *file, static void cx8800_vid_timeout(unsigned long data) { struct cx8800_dev *dev = (struct cx8800_dev*)data; + struct cx88_core *core = dev->core; struct cx88_dmaqueue *q = &dev->vidq; struct cx88_buffer *buf; unsigned long flags; - cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH21]); - //cx88_risc_disasm(dev,&dev->vidq.stopper); - + cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]); + cx_clear(MO_VID_DMACNTRL, 0x11); cx_clear(VID_CAPTURE_CONTROL, 0x06); @@ -2031,41 +1814,16 @@ static void cx8800_vid_timeout(unsigned long data) list_del(&buf->vb.queue); buf->vb.state = STATE_ERROR; wake_up(&buf->vb.done); - printk("%s: [%p/%d] timeout - dma=0x%08lx\n", dev->name, + printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name, buf, buf->vb.i, (unsigned long)buf->risc.dma); } restart_video_queue(dev,q); spin_unlock_irqrestore(&dev->slock,flags); } -static void cx8800_wakeup(struct cx8800_dev *dev, - struct cx88_dmaqueue *q, u32 count) -{ - struct cx88_buffer *buf; - - for (;;) { - if (list_empty(&q->active)) - break; - buf = list_entry(q->active.next, - struct cx88_buffer, vb.queue); - if (buf->count > count) - break; - do_gettimeofday(&buf->vb.ts); - dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i, - count, buf->count); - buf->vb.state = STATE_DONE; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - } - if (list_empty(&q->active)) { - del_timer(&q->timeout); - } else { - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - } -} - static void cx8800_vid_irq(struct cx8800_dev *dev) { + struct cx88_core *core = dev->core; u32 status, mask, count; status = cx_read(MO_VID_INTSTAT); @@ -2074,22 +1832,22 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) return; cx_write(MO_VID_INTSTAT, status); if (irq_debug || (status & mask & ~0xff)) - cx88_print_irqbits(dev->name, "irq vid", + cx88_print_irqbits(core->name, "irq vid", cx88_vid_irqs, status, mask); /* risc op code error */ if (status & (1 << 16)) { - printk(KERN_WARNING "%s: video risc op code error\n",dev->name); + printk(KERN_WARNING "%s/0: video risc op code error\n",core->name); cx_clear(MO_VID_DMACNTRL, 0x11); cx_clear(VID_CAPTURE_CONTROL, 0x06); - cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH21]); + cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]); } - + /* risc1 y */ if (status & 0x01) { spin_lock(&dev->slock); count = cx_read(MO_VIDY_GPCNT); - cx8800_wakeup(dev, &dev->vidq, count); + cx88_wakeup(dev->core, &dev->vidq, count); spin_unlock(&dev->slock); } @@ -2097,7 +1855,7 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) if (status & 0x08) { spin_lock(&dev->slock); count = cx_read(MO_VBI_GPCNT); - cx8800_wakeup(dev, &dev->vbiq, count); + cx88_wakeup(dev->core, &dev->vbiq, count); spin_unlock(&dev->slock); } @@ -2121,29 +1879,29 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs) { struct cx8800_dev *dev = dev_id; + struct cx88_core *core = dev->core; u32 status, mask; int loop, handled = 0; for (loop = 0; loop < 10; loop++) { - status = cx_read(MO_PCI_INTSTAT); + status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x01); mask = cx_read(MO_PCI_INTMSK); if (0 == (status & mask)) goto out; - handled = 1; cx_write(MO_PCI_INTSTAT, status); - if (irq_debug || (status & mask & ~0x1f)) - cx88_print_irqbits(dev->name, "irq pci", - cx88_pci_irqs, status, mask); + handled = 1; - if (status & 1) + if (status & mask & ~0x1f) + cx88_irq(core,status,mask); + if (status & 0x01) cx8800_vid_irq(dev); }; if (10 == loop) { - printk(KERN_WARNING "%s: irq loop -- clearing mask\n", - dev->name); + printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", + core->name); cx_write(MO_PCI_INTMSK,0); } - + out: return IRQ_RETVAL(handled); } @@ -2201,97 +1959,6 @@ struct video_device cx8800_radio_template = /* ----------------------------------------------------------- */ -static void cx8800_shutdown(struct cx8800_dev *dev) -{ - /* disable RISC controller + IRQs */ - cx_write(MO_DEV_CNTRL2, 0); - - /* stop dma transfers */ - cx_write(MO_VID_DMACNTRL, 0x0); - cx_write(MO_AUD_DMACNTRL, 0x0); - cx_write(MO_TS_DMACNTRL, 0x0); - cx_write(MO_VIP_DMACNTRL, 0x0); - cx_write(MO_GPHST_DMACNTRL, 0x0); - - /* stop interupts */ - cx_write(MO_PCI_INTMSK, 0x0); - cx_write(MO_VID_INTMSK, 0x0); - cx_write(MO_AUD_INTMSK, 0x0); - cx_write(MO_TS_INTMSK, 0x0); - cx_write(MO_VIP_INTMSK, 0x0); - cx_write(MO_GPHST_INTMSK, 0x0); - - /* stop capturing */ - cx_write(VID_CAPTURE_CONTROL, 0); -} - -static int cx8800_reset(struct cx8800_dev *dev) -{ - dprintk(1,"cx8800_reset\n"); - - cx8800_shutdown(dev); - - /* clear irq status */ - cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int - cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int - cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int - - /* wait a bit */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); - - /* init sram */ - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21], 720*4, 0); - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH22], 128, 0); - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH23], 128, 0); - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH24], 128, 0); - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH25], 128, 0); - cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH26], 128, 0); - - /* misc init ... */ - cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable - (1 << 12) | // agc gain - (1 << 11) | // adaptibe agc - (0 << 10) | // chroma agc - (0 << 9) | // ckillen - (7))); - - /* setup image format */ - cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000); - - /* setup FIFO Threshholds */ - cx_write(MO_PDMA_STHRSH, 0x0807); - cx_write(MO_PDMA_DTHRSH, 0x0807); - - /* fixes flashing of image */ - cx_write(MO_AGC_SYNC_TIP1, 0x0380000F); - cx_write(MO_AGC_BACK_VBI, 0x00E00555); - - cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int - cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int - cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int - - return 0; -} - -static struct video_device *vdev_init(struct cx8800_dev *dev, - struct video_device *template, - char *type) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template; - vfd->minor = -1; - vfd->dev = &dev->pci->dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", - dev->name, type, cx88_boards[dev->board].name); - return vfd; -} - static void cx8800_unregister_video(struct cx8800_dev *dev) { if (dev->radio_dev) { @@ -2321,7 +1988,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct cx8800_dev *dev; - unsigned int i; + struct cx88_core *core; int err; dev = kmalloc(sizeof(*dev),GFP_KERNEL); @@ -2333,70 +2000,34 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; - goto fail1; + goto fail_free; } - sprintf(dev->name,"cx%x[%d]",pci_dev->device,cx8800_devcount); - - /* pci quirks */ - cx88_pci_quirks(dev->name, dev->pci, &latency); - if (UNSET != latency) { - printk(KERN_INFO "%s: setting pci latency timer to %d\n", - dev->name,latency); - pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency); + core = cx88_core_get(dev->pci); + if (NULL == core) { + err = -EINVAL; + goto fail_free; } + dev->core = core; /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%lx\n", dev->name, + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + "latency: %d, mmio: 0x%lx\n", core->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); if (!pci_dma_supported(pci_dev,0xffffffff)) { - printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name); + printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name); err = -EIO; - goto fail1; - } - - /* board config */ - dev->board = card[cx8800_devcount]; - for (i = 0; UNSET == dev->board && i < cx88_idcount; i++) - if (pci_dev->subsystem_vendor == cx88_subids[i].subvendor && - pci_dev->subsystem_device == cx88_subids[i].subdevice) - dev->board = cx88_subids[i].card; - if (UNSET == dev->board) { - dev->board = CX88_BOARD_UNKNOWN; - cx88_card_list(dev); - } - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - dev->name,pci_dev->subsystem_vendor, - pci_dev->subsystem_device,cx88_boards[dev->board].name, - dev->board, card[cx8800_devcount] == dev->board ? - "insmod option" : "autodetected"); - - dev->tuner_type = tuner[cx8800_devcount]; - if (UNSET == dev->tuner_type) - dev->tuner_type = cx88_boards[dev->board].tuner_type; - - /* get mmio */ - if (!request_mem_region(pci_resource_start(pci_dev,0), - pci_resource_len(pci_dev,0), - dev->name)) { - err = -EBUSY; - printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n", - dev->name,pci_resource_start(pci_dev,0)); - goto fail1; - } - dev->lmmio = ioremap(pci_resource_start(pci_dev,0), - pci_resource_len(pci_dev,0)); - dev->bmmio = (u8*)dev->lmmio; + goto fail_core; + } /* initialize driver struct */ init_MUTEX(&dev->lock); dev->slock = SPIN_LOCK_UNLOCKED; - dev->tvnorm = tvnorms; + core->tvnorm = tvnorms; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); @@ -2416,92 +2047,85 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, cx88_risc_stopper(dev->pci,&dev->vbiq.stopper, MO_VID_DMACNTRL,0x88,0x00); - /* initialize hardware */ - cx8800_reset(dev); - /* get irq */ err = request_irq(pci_dev->irq, cx8800_irq, - SA_SHIRQ | SA_INTERRUPT, dev->name, dev); + SA_SHIRQ | SA_INTERRUPT, core->name, dev); if (err < 0) { printk(KERN_ERR "%s: can't get IRQ %d\n", - dev->name,pci_dev->irq); - goto fail2; + core->name,pci_dev->irq); + goto fail_core; } - /* register i2c bus + load i2c helpers */ - cx8800_i2c_init(dev); - cx88_card_setup(dev); - /* load and configure helper modules */ - if (TUNER_ABSENT != dev->tuner_type) + if (TUNER_ABSENT != core->tuner_type) request_module("tuner"); - if (cx88_boards[dev->board].needs_tda9887) + if (core->tda9887_conf) request_module("tda9887"); - if (dev->tuner_type != UNSET) - cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type); + if (core->tuner_type != UNSET) + cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type); + if (core->tda9887_conf) + cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf); /* register v4l devices */ - dev->video_dev = vdev_init(dev,&cx8800_video_template,"video"); + dev->video_dev = cx88_vdev_init(core,dev->pci, + &cx8800_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, - video_nr[cx8800_devcount]); + video_nr[core->nr]); if (err < 0) { printk(KERN_INFO "%s: can't register video device\n", - dev->name); - goto fail3; + core->name); + goto fail_unreg; } - printk(KERN_INFO "%s: registered device video%d [v4l2]\n", - dev->name,dev->video_dev->minor & 0x1f); + printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", + core->name,dev->video_dev->minor & 0x1f); - dev->vbi_dev = vdev_init(dev,&cx8800_vbi_template,"vbi"); + dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, - vbi_nr[cx8800_devcount]); + vbi_nr[core->nr]); if (err < 0) { - printk(KERN_INFO "%s: can't register vbi device\n", - dev->name); - goto fail3; + printk(KERN_INFO "%s/0: can't register vbi device\n", + core->name); + goto fail_unreg; } - printk(KERN_INFO "%s: registered device vbi%d\n", - dev->name,dev->vbi_dev->minor & 0x1f); + printk(KERN_INFO "%s/0: registered device vbi%d\n", + core->name,dev->vbi_dev->minor & 0x1f); - if (dev->has_radio) { - dev->radio_dev = vdev_init(dev,&cx8800_radio_template,"radio"); + if (core->has_radio) { + dev->radio_dev = cx88_vdev_init(core,dev->pci, + &cx8800_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, - radio_nr[cx8800_devcount]); + radio_nr[core->nr]); if (err < 0) { - printk(KERN_INFO "%s: can't register radio device\n", - dev->name); - goto fail3; + printk(KERN_INFO "%s/0: can't register radio device\n", + core->name); + goto fail_unreg; } - printk(KERN_INFO "%s: registered device radio%d\n", - dev->name,dev->radio_dev->minor & 0x1f); + printk(KERN_INFO "%s/0: registered device radio%d\n", + core->name,dev->radio_dev->minor & 0x1f); } /* everything worked */ list_add_tail(&dev->devlist,&cx8800_devlist); pci_set_drvdata(pci_dev,dev); - cx8800_devcount++; /* initial device configuration */ down(&dev->lock); init_controls(dev); - set_tvnorm(dev,tvnorms); + cx88_set_tvnorm(dev->core,tvnorms); video_mux(dev,0); up(&dev->lock); /* start tvaudio thread */ - init_completion(&dev->texit); - dev->tpid = kernel_thread(cx88_audio_thread, dev, 0); + if (core->tuner_type != TUNER_ABSENT) + core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); return 0; - fail3: +fail_unreg: cx8800_unregister_video(dev); - if (0 == dev->i2c_rc) - i2c_bit_del_bus(&dev->i2c_adap); free_irq(pci_dev->irq, dev); - fail2: - release_mem_region(pci_resource_start(pci_dev,0), - pci_resource_len(pci_dev,0)); - fail1: +fail_core: + cx88_core_put(core,dev->pci); +fail_free: kfree(dev); return err; } @@ -2511,41 +2135,52 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) struct cx8800_dev *dev = pci_get_drvdata(pci_dev); /* stop thread */ - dev->shutdown = 1; - if (dev->tpid >= 0) - wait_for_completion(&dev->texit); + if (dev->core->kthread) { + kthread_stop(dev->core->kthread); + dev->core->kthread = NULL; + } - cx8800_shutdown(dev); + cx88_shutdown(dev->core); /* FIXME */ pci_disable_device(pci_dev); - /* unregister stuff */ - if (0 == dev->i2c_rc) - i2c_bit_del_bus(&dev->i2c_adap); + /* unregister stuff */ free_irq(pci_dev->irq, dev); - release_mem_region(pci_resource_start(pci_dev,0), - pci_resource_len(pci_dev,0)); - cx8800_unregister_video(dev); pci_set_drvdata(pci_dev, NULL); /* free memory */ btcx_riscmem_free(dev->pci,&dev->vidq.stopper); list_del(&dev->devlist); - cx8800_devcount--; + cx88_core_put(dev->core,dev->pci); kfree(dev); } static int cx8800_suspend(struct pci_dev *pci_dev, u32 state) { struct cx8800_dev *dev = pci_get_drvdata(pci_dev); + struct cx88_core *core = dev->core; - printk("%s: suspend %d\n", dev->name, state); + /* stop video+vbi capture */ + spin_lock(&dev->slock); + if (!list_empty(&dev->vidq.active)) { + printk("%s: suspend video\n", core->name); + stop_video_dma(dev); + del_timer(&dev->vidq.timeout); + } + if (!list_empty(&dev->vbiq.active)) { + printk("%s: suspend vbi\n", core->name); + cx8800_stop_vbi_dma(dev); + del_timer(&dev->vbiq.timeout); + } + spin_unlock(&dev->slock); + +#if 1 + /* FIXME -- shutdown device */ + cx88_shutdown(dev->core); +#endif - cx8800_shutdown(dev); - del_timer(&dev->vidq.timeout); - - pci_save_state(pci_dev, dev->state.pci_cfg); + pci_save_state(pci_dev); if (0 != pci_set_power_state(pci_dev, state)) { pci_disable_device(pci_dev); dev->state.disabled = 1; @@ -2556,22 +2191,30 @@ static int cx8800_suspend(struct pci_dev *pci_dev, u32 state) static int cx8800_resume(struct pci_dev *pci_dev) { struct cx8800_dev *dev = pci_get_drvdata(pci_dev); - - printk("%s: resume\n", dev->name); + struct cx88_core *core = dev->core; if (dev->state.disabled) { pci_enable_device(pci_dev); dev->state.disabled = 0; } pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, dev->state.pci_cfg); + pci_restore_state(pci_dev); - /* re-initialize hardware */ - cx8800_reset(dev); +#if 1 + /* FIXME: re-initialize hardware */ + cx88_reset(dev->core); +#endif - /* restart video capture */ + /* restart video+vbi capture */ spin_lock(&dev->slock); - restart_video_queue(dev,&dev->vidq); + if (!list_empty(&dev->vidq.active)) { + printk("%s: resume video\n", core->name); + restart_video_queue(dev,&dev->vidq); + } + if (!list_empty(&dev->vbiq.active)) { + printk("%s: resume vbi\n", core->name); + cx8800_restart_vbi_queue(dev,&dev->vbiq); + } spin_unlock(&dev->slock); return 0; @@ -2595,7 +2238,7 @@ static struct pci_driver cx8800_pci_driver = { .name = "cx8800", .id_table = cx8800_pci_tbl, .probe = cx8800_initdev, - .remove = cx8800_finidev, + .remove = __devexit_p(cx8800_finidev), .suspend = cx8800_suspend, .resume = cx8800_resume, @@ -2603,7 +2246,6 @@ static struct pci_driver cx8800_pci_driver = { static int cx8800_init(void) { - INIT_LIST_HEAD(&cx8800_devlist); printk(KERN_INFO "cx2388x v4l2 driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index f7e6f0b7e..926eaf7f0 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -1,4 +1,6 @@ /* + * $Id: cx88.h,v 1.40 2004/11/03 09:04:51 kraxel Exp $ + * * v4l2 device driver for cx2388x based TV cards * * (c) 2003,04 Gerd Knorr [SUSE Labs] @@ -24,9 +26,10 @@ #include #include -#include #include #include +#include +#include #include "btcx-risc.h" #include "cx88-reg.h" @@ -47,6 +50,8 @@ /* ----------------------------------------------------------- */ /* defines and enums */ +#define V4L2_I2C_CLIENTS 1 + #define FORMAT_FLAGS_PACKED 0x01 #define FORMAT_FLAGS_PLANAR 0x02 @@ -59,15 +64,29 @@ #define SHADOW_MAX 2 /* ----------------------------------------------------------- */ -/* static data */ +/* tv norms */ -struct cx8800_tvnorm { +struct cx88_tvnorm { char *name; v4l2_std_id id; u32 cxiformat; u32 cxoformat; }; +static unsigned int inline norm_maxw(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 768 : 640; +// return (norm->id & V4L2_STD_625_50) ? 720 : 640; +} + +static unsigned int inline norm_maxh(struct cx88_tvnorm *norm) +{ + return (norm->id & V4L2_STD_625_50) ? 576 : 480; +} + +/* ----------------------------------------------------------- */ +/* static data */ + struct cx8800_fmt { char *name; u32 fourcc; /* v4l2 format id */ @@ -94,6 +113,7 @@ struct cx88_ctrl { #define SRAM_CH24 3 /* vbi */ #define SRAM_CH25 4 /* audio */ #define SRAM_CH26 5 +#define SRAM_CH28 6 /* mpeg */ /* more */ struct sram_channel { @@ -113,31 +133,41 @@ extern struct sram_channel cx88_sram_channels[]; /* ----------------------------------------------------------- */ /* card configuration */ -#define CX88_BOARD_NOAUTO UNSET -#define CX88_BOARD_UNKNOWN 0 -#define CX88_BOARD_HAUPPAUGE 1 -#define CX88_BOARD_GDI 2 -#define CX88_BOARD_PIXELVIEW 3 -#define CX88_BOARD_ATI_WONDER_PRO 4 -#define CX88_BOARD_WINFAST2000XP 5 -#define CX88_BOARD_AVERTV_303 6 -#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 -#define CX88_BOARD_WINFAST_DV2000 8 -#define CX88_BOARD_LEADTEK_PVR2000 9 -#define CX88_BOARD_IODATA_GVVCP3PCI 10 -#define CX88_BOARD_PROLINK_PLAYTVPVR 11 -#define CX88_BOARD_ASUS_PVR_416 12 -#define CX88_BOARD_MSI_TVANYWHERE 13 +#define CX88_BOARD_NOAUTO UNSET +#define CX88_BOARD_UNKNOWN 0 +#define CX88_BOARD_HAUPPAUGE 1 +#define CX88_BOARD_GDI 2 +#define CX88_BOARD_PIXELVIEW 3 +#define CX88_BOARD_ATI_WONDER_PRO 4 +#define CX88_BOARD_WINFAST2000XP 5 +#define CX88_BOARD_AVERTV_303 6 +#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 +#define CX88_BOARD_WINFAST_DV2000 8 +#define CX88_BOARD_LEADTEK_PVR2000 9 +#define CX88_BOARD_IODATA_GVVCP3PCI 10 +#define CX88_BOARD_PROLINK_PLAYTVPVR 11 +#define CX88_BOARD_ASUS_PVR_416 12 +#define CX88_BOARD_MSI_TVANYWHERE 13 +#define CX88_BOARD_KWORLD_DVB_T 14 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15 +#define CX88_BOARD_KWORLD_LTV883 16 +#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD 17 +#define CX88_BOARD_HAUPPAUGE_DVB_T1 18 +#define CX88_BOARD_CONEXANT_DVB_T1 19 +#define CX88_BOARD_PROVIDEO_PV259 20 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, - CX88_VMUX_COMPOSITE2 = 2, - CX88_VMUX_COMPOSITE3 = 3, - CX88_VMUX_COMPOSITE4 = 4, - CX88_VMUX_TELEVISION = 5, - CX88_VMUX_SVIDEO = 6, - CX88_VMUX_DEBUG = 7, - CX88_RADIO = 8, + CX88_VMUX_COMPOSITE2, + CX88_VMUX_COMPOSITE3, + CX88_VMUX_COMPOSITE4, + CX88_VMUX_SVIDEO, + CX88_VMUX_TELEVISION, + CX88_VMUX_CABLE, + CX88_VMUX_DVB, + CX88_VMUX_DEBUG, + CX88_RADIO, }; struct cx88_input { @@ -149,9 +179,11 @@ struct cx88_input { struct cx88_board { char *name; unsigned int tuner_type; - int needs_tda9887:1; + int tda9887_conf; struct cx88_input input[8]; struct cx88_input radio; + int blackbird:1; + int dvb:1; }; struct cx88_subid { @@ -160,7 +192,7 @@ struct cx88_subid { u32 card; }; -#define INPUT(nr) (&cx88_boards[dev->board].input[nr]) +#define INPUT(nr) (&cx88_boards[core->board].input[nr]) /* ----------------------------------------------------------- */ /* device / file handle status */ @@ -169,10 +201,8 @@ struct cx88_subid { #define RESOURCE_VIDEO 2 #define RESOURCE_VBI 4 -//#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ -#define BUFFER_TIMEOUT (HZ*2) - -struct cx8800_dev; +#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ +//#define BUFFER_TIMEOUT (HZ*2) /* buffer for one video frame */ struct cx88_buffer { @@ -194,7 +224,52 @@ struct cx88_dmaqueue { u32 count; }; -/* video filehandle status */ +struct cx88_core { + struct list_head devlist; + atomic_t refcount; + + /* board name */ + int nr; + char name[32]; + + /* pci stuff */ + int pci_bus; + int pci_slot; + u32 __iomem *lmmio; + u8 __iomem *bmmio; + u32 shadow[SHADOW_MAX]; + + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_state, i2c_rc; + + /* config info -- analog */ + unsigned int board; + unsigned int tuner_type; + unsigned int tda9887_conf; + unsigned int has_radio; + + /* config info -- dvb */ + unsigned int pll_type; + unsigned int pll_addr; + unsigned int demod_addr; + + /* state info */ + struct task_struct *kthread; + struct cx88_tvnorm *tvnorm; + u32 tvaudio; + u32 input; + u32 astat; +}; + +struct cx8800_dev; +struct cx8802_dev; + +/* ----------------------------------------------------------- */ +/* function 0: video stuff */ + struct cx8800_fh { struct cx8800_dev *dev; enum v4l2_buf_type type; @@ -216,12 +291,11 @@ struct cx8800_fh { }; struct cx8800_suspend_state { - u32 pci_cfg[64 / sizeof(u32)]; int disabled; }; -/* global device status */ struct cx8800_dev { + struct cx88_core *core; struct list_head devlist; struct semaphore lock; spinlock_t slock; @@ -233,99 +307,150 @@ struct cx8800_dev { struct video_device *radio_dev; /* pci i/o */ - char name[32]; struct pci_dev *pci; unsigned char pci_rev,pci_lat; - u32 *lmmio; - u8 *bmmio; - - /* config info */ - unsigned int board; - unsigned int tuner_type; - unsigned int has_radio; - - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - u32 i2c_state, i2c_rc; +#if 0 /* video overlay */ struct v4l2_framebuffer fbuf; struct cx88_buffer *screen; +#endif /* capture queues */ struct cx88_dmaqueue vidq; struct cx88_dmaqueue vbiq; /* various v4l controls */ - struct cx8800_tvnorm *tvnorm; - u32 tvaudio; - u32 input; u32 freq; /* other global state info */ - u32 shadow[SHADOW_MAX]; - int shutdown; - pid_t tpid; - struct completion texit; struct cx8800_suspend_state state; }; +/* ----------------------------------------------------------- */ +/* function 1: audio/alsa stuff */ + +struct cx8801_dev { + struct cx88_core *core; + + /* pci i/o */ + struct pci_dev *pci; + unsigned char pci_rev,pci_lat; +}; + +/* ----------------------------------------------------------- */ +/* function 2: mpeg stuff */ + +struct cx8802_fh { + struct cx8802_dev *dev; + struct videobuf_queue mpegq; +}; + +struct cx8802_suspend_state { + int disabled; +}; + +struct cx8802_dev { + struct cx88_core *core; + struct semaphore lock; + spinlock_t slock; + + /* pci i/o */ + struct pci_dev *pci; + unsigned char pci_rev,pci_lat; + + /* dma queues */ + struct cx88_dmaqueue mpegq; + u32 ts_packet_size; + u32 ts_packet_count; + + /* other global state info */ + struct cx8802_suspend_state state; + + /* for blackbird only */ + struct list_head devlist; + struct video_device *mpeg_dev; + u32 mailbox; + + /* for dvb only */ + struct videobuf_dvb dvb; + void* fe_handle; + int (*fe_release)(void *handle); +}; + /* ----------------------------------------------------------- */ -#define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) -#define cx_write(reg,value) writel((value), dev->lmmio + ((reg)>>2)); -#define cx_writeb(reg,value) writeb((value), dev->bmmio + (reg)); +#define cx_read(reg) readl(core->lmmio + ((reg)>>2)) +#define cx_write(reg,value) writel((value), core->lmmio + ((reg)>>2)) +#define cx_writeb(reg,value) writeb((value), core->bmmio + (reg)) #define cx_andor(reg,mask,value) \ - writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ - ((value) & (mask)), dev->lmmio+((reg)>>2)) + writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\ + ((value) & (mask)), core->lmmio+((reg)>>2)) #define cx_set(reg,bit) cx_andor((reg),(bit),(bit)) #define cx_clear(reg,bit) cx_andor((reg),(bit),0) #define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); } /* shadow registers */ -#define cx_sread(sreg) (dev->shadow[sreg]) +#define cx_sread(sreg) (core->shadow[sreg]) #define cx_swrite(sreg,reg,value) \ - (dev->shadow[sreg] = value, \ - writel(dev->shadow[sreg], dev->lmmio + ((reg)>>2))) + (core->shadow[sreg] = value, \ + writel(core->shadow[sreg], core->lmmio + ((reg)>>2))) #define cx_sandor(sreg,reg,mask,value) \ - (dev->shadow[sreg] = (dev->shadow[sreg] & ~(mask)) | ((value) & (mask)), \ - writel(dev->shadow[sreg], dev->lmmio + ((reg)>>2))) + (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \ + writel(core->shadow[sreg], core->lmmio + ((reg)>>2))) /* ----------------------------------------------------------- */ /* cx88-core.c */ extern char *cx88_pci_irqs[32]; extern char *cx88_vid_irqs[32]; +extern char *cx88_mpeg_irqs[32]; extern void cx88_print_irqbits(char *name, char *tag, char **strings, u32 bits, u32 mask); extern void cx88_print_ioctl(char *name, unsigned int cmd); +extern void cx88_irq(struct cx88_core *core, u32 status, u32 mask); +extern void cx88_wakeup(struct cx88_core *core, + struct cx88_dmaqueue *q, u32 count); +extern void cx88_shutdown(struct cx88_core *core); +extern int cx88_reset(struct cx88_core *core); + extern int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, unsigned int padding, unsigned int lines); extern int +cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, + struct scatterlist *sglist, unsigned int bpl, + unsigned int lines); +extern int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value); extern void cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf); -extern void cx88_risc_disasm(struct cx8800_dev *dev, +extern void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc); - -extern int cx88_sram_channel_setup(struct cx8800_dev *dev, +extern int cx88_sram_channel_setup(struct cx88_core *core, struct sram_channel *ch, unsigned int bpl, u32 risc); -extern void cx88_sram_channel_dump(struct cx8800_dev *dev, +extern void cx88_sram_channel_dump(struct cx88_core *core, struct sram_channel *ch); -extern int cx88_pci_quirks(char *name, struct pci_dev *pci, - unsigned int *latency); +extern int cx88_set_scale(struct cx88_core *core, unsigned int width, + unsigned int height, enum v4l2_field field); +extern int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm); + +extern struct video_device *cx88_vdev_init(struct cx88_core *core, + struct pci_dev *pci, + struct video_device *template, + char *type); +extern struct cx88_core* cx88_core_get(struct pci_dev *pci); +extern void cx88_core_put(struct cx88_core *core, + struct pci_dev *pci); /* ----------------------------------------------------------- */ /* cx88-vbi.c */ @@ -334,6 +459,7 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f); int cx8800_start_vbi_dma(struct cx8800_dev *dev, struct cx88_dmaqueue *q, struct cx88_buffer *buf); +int cx8800_stop_vbi_dma(struct cx8800_dev *dev); int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q); void cx8800_vbi_timeout(unsigned long data); @@ -343,9 +469,9 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; /* ----------------------------------------------------------- */ /* cx88-i2c.c */ -extern int cx8800_i2c_init(struct cx8800_dev *dev); -extern void cx8800_call_i2c_clients(struct cx8800_dev *dev, - unsigned int cmd, void *arg); +extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); +extern void cx88_call_i2c_clients(struct cx88_core *core, + unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ @@ -357,8 +483,8 @@ extern const unsigned int cx88_bcount; extern struct cx88_subid cx88_subids[]; extern const unsigned int cx88_idcount; -extern void cx88_card_list(struct cx8800_dev *dev); -extern void cx88_card_setup(struct cx8800_dev *dev); +extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci); +extern void cx88_card_setup(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ @@ -376,11 +502,24 @@ extern void cx88_card_setup(struct cx8800_dev *dev); #define WW_I2SPT 11 #define WW_FM 12 -void cx88_set_tvaudio(struct cx8800_dev *dev); -void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t); -void cx88_set_stereo(struct cx8800_dev *dev, u32 mode); +void cx88_set_tvaudio(struct cx88_core *core); +void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); +void cx88_set_stereo(struct cx88_core *core, u32 mode); int cx88_audio_thread(void *data); +/* ----------------------------------------------------------- */ +/* cx88-mpeg.c */ + +int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf); +void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); +void cx8802_cancel_buffers(struct cx8802_dev *dev); + +int cx8802_init_common(struct cx8802_dev *dev); +void cx8802_fini_common(struct cx8802_dev *dev); + +int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state); +int cx8802_resume_common(struct pci_dev *pci_dev); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c index 3944f3f6a..054708879 100644 --- a/drivers/media/video/dpc7146.c +++ b/drivers/media/video/dpc7146.c @@ -79,8 +79,8 @@ static struct saa7146_extension_ioctls ioctls[] = { struct dpc { - struct video_device video_dev; - struct video_device vbi_dev; + struct video_device *video_dev; + struct video_device *vbi_dev; struct i2c_adapter i2c_adapter; struct i2c_client *saa7111a; @@ -106,7 +106,11 @@ static int dpc_probe(struct saa7146_dev* dev) video port pins should be enabled here ?! */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + dpc->i2c_adapter = (struct i2c_adapter) { + .class = I2C_CLASS_TV_ANALOG, + .name = "dpc7146", + }; + saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&dpc->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(dpc); @@ -123,6 +127,7 @@ static int dpc_probe(struct saa7146_dev* dev) /* check if all devices are present */ if( 0 == dpc->saa7111a ) { DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); + i2c_del_adapter(&dpc->i2c_adapter); kfree(dpc); return -ENODEV; } diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 885e504de..50c436d03 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -78,7 +78,8 @@ static struct v4l2_queryctrl hexium_controls[] = { struct hexium { int type; - struct video_device video_dev; + + struct video_device *video_dev; struct i2c_adapter i2c_adapter; int cur_input; /* current input */ @@ -250,7 +251,11 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d /* enable i2c-port pins */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + hexium->i2c_adapter = (struct i2c_adapter) { + .class = I2C_CLASS_TV_ANALOG, + .name = "hexium gemini", + }; + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(hexium); diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 8a577d718..fba27bb40 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -68,8 +68,9 @@ static struct saa7146_extension_ioctls ioctls[] = { struct hexium { int type; - struct video_device video_dev; + struct video_device *video_dev; struct i2c_adapter i2c_adapter; + int cur_input; /* current input */ }; @@ -237,7 +238,11 @@ static int hexium_probe(struct saa7146_dev *dev) saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + hexium->i2c_adapter = (struct i2c_adapter) { + .class = I2C_CLASS_TV_ANALOG, + .name = "hexium orion", + }; + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(hexium); diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index 30cce6bec..a43568b11 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -1,5 +1,6 @@ - /* + * $Id: ir-kbd-gpio.c,v 1.10 2004/09/15 16:15:24 kraxel Exp $ + * * Copyright (c) 2003 Gerd Knorr * Copyright (c) 2003 Pavel Machek * @@ -45,7 +46,7 @@ static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [ 60 ] = KEY_KP9, [ 48 ] = KEY_EJECTCD, // Unmarked on my controller - [ 0 ] = KEY_POWER, + [ 0 ] = KEY_POWER, [ 18 ] = BTN_LEFT, // DISPLAY/L [ 50 ] = BTN_RIGHT, // LOOP/R [ 10 ] = KEY_MUTE, @@ -74,6 +75,45 @@ static IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [ 1 ] = KEY_BLUE, // unmarked }; +/* Matt Jesson >' + [ 0x3a ] = KEY_RECORD, // 'capture' + [ 0x0a ] = KEY_MUTE, // 'mute' + [ 0x2c ] = KEY_RECORD, // 'record' + [ 0x1c ] = KEY_PAUSE, // 'pause' + [ 0x3c ] = KEY_STOP, // 'stop' + [ 0x0c ] = KEY_PLAY, // 'play' + [ 0x2e ] = KEY_RED, // 'red' + [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' + [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' + [ 0x21 ] = KEY_GREEN, // 'green' + [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' + [ 0x31 ] = KEY_CHANNELUP, // 'channel +' + [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' + [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' +}; + static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = { [ 5 ] = KEY_KP1, [ 6 ] = KEY_KP2, @@ -130,7 +170,7 @@ static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [ 6 ] = KEY_KP7, [ 10 ] = KEY_KP8, [ 18 ] = KEY_KP9, - + [ 3 ] = KEY_TUNER, // TV/FM [ 7 ] = KEY_SEARCH, // scan [ 28 ] = KEY_ZOOM, // full screen @@ -140,7 +180,7 @@ static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [ 20 ] = KEY_CHANNELDOWN, [ 22 ] = KEY_CHANNELUP, [ 24 ] = KEY_MUTE, - + [ 0 ] = KEY_LIST, // source [ 19 ] = KEY_INFO, // loop [ 16 ] = KEY_LAST, // +100 @@ -151,6 +191,47 @@ static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [ 15 ] = KEY_STOP, // freeze }; +/* Attila Kondoros */ +static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { + + [ 1 ] = KEY_KP1, + [ 2 ] = KEY_KP2, + [ 3 ] = KEY_KP3, + [ 4 ] = KEY_KP4, + [ 5 ] = KEY_KP5, + [ 6 ] = KEY_KP6, + [ 7 ] = KEY_KP7, + [ 8 ] = KEY_KP8, + [ 9 ] = KEY_KP9, + [ 0 ] = KEY_KP0, + [ 23 ] = KEY_LAST, // +100 + [ 10 ] = KEY_LIST, // recall + + + [ 28 ] = KEY_TUNER, // TV/FM + [ 21 ] = KEY_SEARCH, // scan + [ 18 ] = KEY_POWER, // power + [ 31 ] = KEY_VOLUMEDOWN, // vol up + [ 27 ] = KEY_VOLUMEUP, // vol down + [ 30 ] = KEY_CHANNELDOWN, // chn up + [ 26 ] = KEY_CHANNELUP, // chn down + + [ 17 ] = KEY_VIDEO, // video + [ 15 ] = KEY_ZOOM, // full screen + [ 19 ] = KEY_MUTE, // mute/unmute + [ 16 ] = KEY_TEXT, // min + + [ 13 ] = KEY_STOP, // freeze + [ 14 ] = KEY_RECORD, // record + [ 29 ] = KEY_PLAYPAUSE, // stop + [ 25 ] = KEY_PLAY, // play + + [ 22 ] = KEY_GOTO, // osd + [ 20 ] = KEY_REFRESH, // default + [ 12 ] = KEY_KPPLUS, // fine tune >>>> + [ 24 ] = KEY_KPMINUS // fine tune <<<< +}; + /* ---------------------------------------------------------------------- */ struct IR { @@ -202,7 +283,7 @@ static void ir_handle_key(struct IR *ir) return; ir->last_gpio = gpio; } - + /* extract data */ data = ir_extract_bits(gpio, ir->mask_keycode); dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n", @@ -284,6 +365,14 @@ static int ir_probe(struct device *dev) ir->polling = 50; // ms break; + case BTTV_AVDVBT_761: + /* case BTTV_AVDVBT_771: */ + ir_codes = ir_codes_avermedia_dvbt; + ir->mask_keycode = 0x0f00c0; + ir->mask_keydown = 0x000020; + ir->polling = 50; // ms + break; + case BTTV_PXELVWPLTVPAK: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x003e00; @@ -308,6 +397,12 @@ static int ir_probe(struct device *dev) ir->mask_keycode = 0x0008e000; ir->mask_keydown = 0x00200000; break; + case BTTV_APAC_VIEWCOMP: + ir_codes = ir_codes_apac_viewcomp; + ir->mask_keycode = 0x001f00; + ir->mask_keyup = 0x008000; + ir->polling = 50; // ms + break; } if (NULL == ir_codes) { kfree(ir); @@ -317,7 +412,7 @@ static int ir_probe(struct device *dev) /* init hardware-specific stuff */ bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); ir->sub = sub; - + /* init input device */ snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", sub->core->type); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 958906373..849686426 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -1,4 +1,6 @@ /* + * $Id: ir-kbd-i2c.c,v 1.8 2004/09/15 16:15:24 kraxel Exp $ + * * keyboard input driver for i2c IR remote controls * * Copyright (c) 2000-2003 Gerd Knorr @@ -156,7 +158,7 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */ static inline int reverse(int data, int bits) { int i,c; - + for (c=0,i=0; ic,&b,1)) { dprintk(1,"read error\n"); @@ -207,7 +209,7 @@ static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; - + /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { dprintk(1,"read error\n"); @@ -218,7 +220,7 @@ static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) if (b==0xaa) return 0; dprintk(2,"key %02x\n", b); - + *ir_key = b; *ir_raw = b; return 1; @@ -227,26 +229,26 @@ static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; - + /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { dprintk(1,"read error\n"); return -EIO; } - + /* it seems that 0xFE indicates that a button is still hold down, while 0xFF indicates that no button is hold down. 0xFE sequences are sometimes interrupted by 0xFF */ - + dprintk(2,"key %02x\n", b); - + if (b == 0xFF) return 0; - + if (b == 0xFE) /* keep old data */ return 1; - + *ir_key = b; *ir_raw = b; return 1; @@ -323,7 +325,7 @@ static struct i2c_driver driver = { .detach_client = ir_detach, }; -static struct i2c_client client_template = +static struct i2c_client client_template = { I2C_DEVNAME("unset"), .driver = &driver @@ -336,7 +338,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, char *name; int ir_type; struct IR *ir; - + if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL))) return -ENOMEM; memset(ir,0,sizeof(*ir)); @@ -400,14 +402,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr, input_register_device(&ir->input); printk(DEVNAME ": %s detected at %s [%s]\n", ir->input.name,ir->input.phys,adap->name); - + /* start polling via eventd */ INIT_WORK(&ir->work, ir_work, ir); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; schedule_work(&ir->work); - + return 0; } @@ -430,16 +432,16 @@ static int ir_detach(struct i2c_client *client) static int ir_probe(struct i2c_adapter *adap) { - + /* The external IR receiver is at i2c address 0x34 (0x35 for reads). Future Hauppauge cards will have an internal receiver at 0x30 (0x31 for reads). In theory, both can be fitted, and Hauppauge suggest an external overrides an - internal. - - That's why we probe 0x1a (~0x34) first. CB + internal. + + That's why we probe 0x1a (~0x34) first. CB */ - + static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, -1}; const int *probe = NULL; @@ -478,13 +480,12 @@ MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Muell MODULE_DESCRIPTION("input driver for i2c IR remote controls"); MODULE_LICENSE("GPL"); -static int ir_init(void) +static int __init ir_init(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void ir_fini(void) +static void __exit ir_fini(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 6f3fe234e..2618f20af 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1,7 +1,7 @@ -/* +/* * Motion Eye video4linux driver for Sony Vaio PictureBook * - * Copyright (C) 2001-2003 Stelian Pop + * Copyright (C) 2001-2004 Stelian Pop * * Copyright (C) 2001-2002 Alcôve * @@ -11,17 +11,17 @@ * * Some parts borrowed from various video4linux drivers, especially * bttv-driver.c and zoran.c, see original files for credits. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -39,104 +39,50 @@ #include #include "meye.h" -#include "linux/meye.h" +#include + +MODULE_AUTHOR("Stelian Pop "); +MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(MEYE_DRIVER_VERSION); + +/* force usage of V4L1 API */ +static int forcev4l1; /* = 0 */ +module_param(forcev4l1, int, 0644); +MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2"); -/* driver structure - only one possible */ -static struct meye meye; /* number of grab buffers */ static unsigned int gbuffers = 2; +module_param(gbuffers, int, 0444); +MODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)"); + /* size of a grab buffer */ static unsigned int gbufsize = MEYE_MAX_BUFSIZE; +module_param(gbufsize, int, 0444); +MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400" + " (will be rounded up to a page multiple)"); + /* /dev/videoX registration number */ static int video_nr = -1; +module_param(video_nr, int, 0444); +MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)"); -/****************************************************************************/ -/* Queue routines */ -/****************************************************************************/ - -/* Inits the queue */ -static inline void meye_initq(struct meye_queue *queue) { - queue->head = queue->tail = 0; - queue->len = 0; - queue->s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED; - init_waitqueue_head(&queue->proc_list); -} - -/* Pulls an element from the queue */ -static inline int meye_pullq(struct meye_queue *queue) { - int result; - unsigned long flags; - - spin_lock_irqsave(&queue->s_lock, flags); - if (!queue->len) { - spin_unlock_irqrestore(&queue->s_lock, flags); - return -1; - } - result = queue->buf[queue->head]; - queue->head++; - queue->head &= (MEYE_QUEUE_SIZE - 1); - queue->len--; - spin_unlock_irqrestore(&queue->s_lock, flags); - return result; -} - -/* Pushes an element into the queue */ -static inline void meye_pushq(struct meye_queue *queue, int element) { - unsigned long flags; - - spin_lock_irqsave(&queue->s_lock, flags); - if (queue->len == MEYE_QUEUE_SIZE) { - /* remove the first element */ - queue->head++; - queue->head &= (MEYE_QUEUE_SIZE - 1); - queue->len--; - } - queue->buf[queue->tail] = element; - queue->tail++; - queue->tail &= (MEYE_QUEUE_SIZE - 1); - queue->len++; - - spin_unlock_irqrestore(&queue->s_lock, flags); -} - -/* Tests if the queue is empty */ -static inline int meye_emptyq(struct meye_queue *queue, int *elem) { - int result; - unsigned long flags; - - spin_lock_irqsave(&queue->s_lock, flags); - result = (queue->len == 0); - if (!result && elem) - *elem = queue->buf[queue->head]; - spin_unlock_irqrestore(&queue->s_lock, flags); - return result; -} +/* driver structure - only one possible */ +static struct meye meye; /****************************************************************************/ /* Memory allocation routines (stolen from bttv-driver.c) */ /****************************************************************************/ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) { - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - -static void *rvmalloc(unsigned long size) { +static void *rvmalloc(unsigned long size) +{ void *mem; unsigned long adr; size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (mem) { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long)mem; + memset(mem, 0, size); + adr = (unsigned long) mem; while (size > 0) { SetPageReserved(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; @@ -146,11 +92,12 @@ static void *rvmalloc(unsigned long size) { return mem; } -static void rvfree(void * mem, unsigned long size) { - unsigned long adr; +static void rvfree(void * mem, unsigned long size) +{ + unsigned long adr; if (mem) { - adr = (unsigned long) mem; + adr = (unsigned long) mem; while ((long) size > 0) { ClearPageReserved(vmalloc_to_page((void *)adr)); adr += PAGE_SIZE; @@ -163,18 +110,20 @@ static void rvfree(void * mem, unsigned long size) { /* * return a page table pointing to N pages of locked memory * - * NOTE: The meye device expects dma_addr_t size to be 32 bits - * (the toc must be exactly 1024 entries each of them being 4 bytes - * in size, the whole result being 4096 bytes). We're using here - * dma_addr_t for correctness but the compilation of this driver is - * disabled for HIGHMEM64G=y, where sizeof(dma_addr_t) != 4 + * NOTE: The meye device expects DMA addresses on 32 bits, we build + * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes. */ -static int ptable_alloc(void) { - dma_addr_t *pt; +static int ptable_alloc(void) +{ + u32 *pt; int i; memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable)); + /* give only 32 bit DMA addresses */ + if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff)) + return -1; + meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev, PAGE_SIZE, &meye.mchip_dmahandle, @@ -186,17 +135,19 @@ static int ptable_alloc(void) { pt = meye.mchip_ptable_toc; for (i = 0; i < MCHIP_NB_PAGES; i++) { - meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev, + dma_addr_t dma; + meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev, PAGE_SIZE, - pt, + &dma, GFP_KERNEL); if (!meye.mchip_ptable[i]) { int j; pt = meye.mchip_ptable_toc; for (j = 0; j < i; ++j) { + dma = (dma_addr_t) *pt; dma_free_coherent(&meye.mchip_dev->dev, PAGE_SIZE, - meye.mchip_ptable[j], *pt); + meye.mchip_ptable[j], dma); pt++; } dma_free_coherent(&meye.mchip_dev->dev, @@ -207,27 +158,30 @@ static int ptable_alloc(void) { meye.mchip_dmahandle = 0; return -1; } + *pt = (u32) dma; pt++; } return 0; } -static void ptable_free(void) { - dma_addr_t *pt; +static void ptable_free(void) +{ + u32 *pt; int i; pt = meye.mchip_ptable_toc; for (i = 0; i < MCHIP_NB_PAGES; i++) { + dma_addr_t dma = (dma_addr_t) *pt; if (meye.mchip_ptable[i]) - dma_free_coherent(&meye.mchip_dev->dev, - PAGE_SIZE, - meye.mchip_ptable[i], *pt); + dma_free_coherent(&meye.mchip_dev->dev, + PAGE_SIZE, + meye.mchip_ptable[i], dma); pt++; } if (meye.mchip_ptable_toc) - dma_free_coherent(&meye.mchip_dev->dev, - PAGE_SIZE, + dma_free_coherent(&meye.mchip_dev->dev, + PAGE_SIZE, meye.mchip_ptable_toc, meye.mchip_dmahandle); @@ -237,9 +191,10 @@ static void ptable_free(void) { } /* copy data from ptable into buf */ -static void ptable_copy(u8 *buf, int start, int size, int pt_pages) { +static void ptable_copy(u8 *buf, int start, int size, int pt_pages) +{ int i; - + for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) { memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE); if (start >= pt_pages) @@ -248,224 +203,193 @@ static void ptable_copy(u8 *buf, int start, int size, int pt_pages) { memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE); } - /****************************************************************************/ /* JPEG tables at different qualities to load into the VRJ chip */ /****************************************************************************/ /* return a set of quantisation tables based on a quality from 1 to 10 */ -static u16 *jpeg_quantisation_tables(int *size, int quality) { - static u16 tables0[] = { - 0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, - 0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, - }; - static u16 tables1[] = { - 0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46, - 0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, - 0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, - }; - static u16 tables2[] = { - 0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23, - 0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164, - 0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad, - 0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff, - 0xe6ff, 0xfffd, 0xfff8, - 0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876, - 0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, - 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, - 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, - 0xf8f8, 0xf8f8, 0xfff8, - }; - static u16 tables3[] = { - 0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17, - 0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042, - 0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73, - 0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba, - 0x99c7, 0xaba8, 0xffa4, - 0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e, - 0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, - 0xa4a4, 0xa4a4, 0xffa4, - }; - static u16 tables4[] = { - 0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712, - 0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932, - 0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556, - 0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c, - 0x7396, 0x817e, 0xff7c, - 0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b, - 0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, - 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, - 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, - 0x7c7c, 0x7c7c, 0xff7c, - }; - static u16 tables5[] = { - 0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e, - 0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28, - 0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745, - 0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470, - 0x5c78, 0x6765, 0xff63, - 0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f, - 0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, - 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, - 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, - 0x6363, 0x6363, 0xff63, - }; - static u16 tables6[] = { - 0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b, - 0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20, - 0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37, - 0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a, - 0x4a60, 0x5251, 0xff4f, - 0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26, - 0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, - 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, - 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, - 0x4f4f, 0x4f4f, 0xff4f, - }; - static u16 tables7[] = { - 0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08, - 0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318, - 0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129, - 0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43, - 0x3748, 0x3e3d, 0xff3b, - 0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c, - 0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, - 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, - 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, - 0x3b3b, 0x3b3b, 0xff3b, - }; - static u16 tables8[] = { - 0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706, - 0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710, - 0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c, - 0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d, - 0x2530, 0x2928, 0xff28, - 0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813, - 0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, - 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, - 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, - 0x2828, 0x2828, 0xff28, - }; - static u16 tables9[] = { - 0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403, - 0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08, - 0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e, - 0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416, - 0x1218, 0x1514, 0xff14, - 0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409, - 0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, - 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, - 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, - 0x1414, 0x1414, 0xff14, - }; - static u16 tables10[] = { - 0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0xff01, - 0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0101, 0x0101, 0xff01, - }; - - switch (quality) { - case 0: - *size = sizeof(tables0); - return tables0; - case 1: - *size = sizeof(tables1); - return tables1; - case 2: - *size = sizeof(tables2); - return tables2; - case 3: - *size = sizeof(tables3); - return tables3; - case 4: - *size = sizeof(tables4); - return tables4; - case 5: - *size = sizeof(tables5); - return tables5; - case 6: - *size = sizeof(tables6); - return tables6; - case 7: - *size = sizeof(tables7); - return tables7; - case 8: - *size = sizeof(tables8); - return tables8; - case 9: - *size = sizeof(tables9); - return tables9; - case 10: - *size = sizeof(tables10); - return tables10; - default: - printk(KERN_WARNING "meye: invalid quality level %d - using 8\n", quality); - *size = sizeof(tables8); - return tables8; +static u16 *jpeg_quantisation_tables(int *length, int quality) +{ + static u16 jpeg_tables[][70] = { { + 0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, + 0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, + }, + { + 0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46, + 0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, + 0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, + }, + { + 0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23, + 0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164, + 0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad, + 0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff, + 0xe6ff, 0xfffd, 0xfff8, + 0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876, + 0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, + 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, + 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, + 0xf8f8, 0xf8f8, 0xfff8, + }, + { + 0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17, + 0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042, + 0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73, + 0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba, + 0x99c7, 0xaba8, 0xffa4, + 0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e, + 0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, + 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, + 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, + 0xa4a4, 0xa4a4, 0xffa4, + }, + { + 0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712, + 0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932, + 0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556, + 0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c, + 0x7396, 0x817e, 0xff7c, + 0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b, + 0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, + 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, + 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, + 0x7c7c, 0x7c7c, 0xff7c, + }, + { + 0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e, + 0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28, + 0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745, + 0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470, + 0x5c78, 0x6765, 0xff63, + 0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f, + 0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, + 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, + 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, + 0x6363, 0x6363, 0xff63, + }, + { + 0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b, + 0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20, + 0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37, + 0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a, + 0x4a60, 0x5251, 0xff4f, + 0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26, + 0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, + 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, + 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, + 0x4f4f, 0x4f4f, 0xff4f, + }, + { + 0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08, + 0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318, + 0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129, + 0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43, + 0x3748, 0x3e3d, 0xff3b, + 0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c, + 0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, + 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, + 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, + 0x3b3b, 0x3b3b, 0xff3b, + }, + { + 0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706, + 0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710, + 0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c, + 0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d, + 0x2530, 0x2928, 0xff28, + 0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813, + 0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, + 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, + 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, + 0x2828, 0x2828, 0xff28, + }, + { + 0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403, + 0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08, + 0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e, + 0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416, + 0x1218, 0x1514, 0xff14, + 0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409, + 0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, + 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, + 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, + 0x1414, 0x1414, 0xff14, + }, + { + 0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0xff01, + 0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0101, 0x0101, 0xff01, + } }; + + if (quality < 0 || quality > 10) { + printk(KERN_WARNING + "meye: invalid quality level %d - using 8\n", quality); + quality = 8; } - return NULL; + + *length = ARRAY_SIZE(jpeg_tables[quality]); + return jpeg_tables[quality]; } /* return a generic set of huffman tables */ -static u16 *jpeg_huffman_tables(int *size) { +static u16 *jpeg_huffman_tables(int *length) +{ static u16 tables[] = { - 0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405, - 0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131, - 0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142, - 0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918, - 0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443, - 0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463, - 0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483, - 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A, - 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8, - 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6, - 0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2, - 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA, - 0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405, - 0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206, - 0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1, - 0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125, - 0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A, - 0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A, - 0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A, - 0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, - 0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, - 0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, - 0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2, - 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA, - 0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09, - 0xFF0B, - 0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101, - 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09, + 0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405, + 0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131, + 0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142, + 0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918, + 0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443, + 0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463, + 0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483, + 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A, + 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8, + 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6, + 0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2, + 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA, + 0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405, + 0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206, + 0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1, + 0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125, + 0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A, + 0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A, + 0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A, + 0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, + 0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, + 0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, + 0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2, + 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA, + 0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09, + 0xFF0B, + 0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101, + 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09, 0xFF0B }; - *size = sizeof(tables); + *length = ARRAY_SIZE(tables); return tables; } @@ -474,23 +398,27 @@ static u16 *jpeg_huffman_tables(int *size) { /****************************************************************************/ /* returns the horizontal capture size */ -static inline int mchip_hsize(void) { +static inline int mchip_hsize(void) +{ return meye.params.subsample ? 320 : 640; } /* returns the vertical capture size */ -static inline int mchip_vsize(void) { +static inline int mchip_vsize(void) +{ return meye.params.subsample ? 240 : 480; } /* waits for a register to be available */ -static void mchip_sync(int reg) { +static void mchip_sync(int reg) +{ u32 status; int i; if (reg == MCHIP_MM_FIFO_DATA) { for (i = 0; i < MCHIP_REG_TIMEOUT; i++) { - status = readl(meye.mchip_mmregs + MCHIP_MM_FIFO_STATUS); + status = readl(meye.mchip_mmregs + + MCHIP_MM_FIFO_STATUS); if (!(status & MCHIP_MM_FIFO_WAIT)) { printk(KERN_WARNING "meye: fifo not ready\n"); return; @@ -499,44 +427,48 @@ static void mchip_sync(int reg) { return; udelay(1); } - } - else if (reg > 0x80) { + } else if (reg > 0x80) { u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY - : MCHIP_HIC_STATUS_VRJ_RDY; + : MCHIP_HIC_STATUS_VRJ_RDY; for (i = 0; i < MCHIP_REG_TIMEOUT; i++) { status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS); if (status & mask) return; udelay(1); } - } - else + } else return; - printk(KERN_WARNING "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n", reg, status); + printk(KERN_WARNING + "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n", + reg, status); } /* sets a value into the register */ -static inline void mchip_set(int reg, u32 v) { +static inline void mchip_set(int reg, u32 v) +{ mchip_sync(reg); writel(v, meye.mchip_mmregs + reg); } /* get the register value */ -static inline u32 mchip_read(int reg) { +static inline u32 mchip_read(int reg) +{ mchip_sync(reg); return readl(meye.mchip_mmregs + reg); } /* wait for a register to become a particular value */ -static inline int mchip_delay(u32 reg, u32 v) { +static inline int mchip_delay(u32 reg, u32 v) +{ int n = 10; - while (--n && mchip_read(reg) != v) + while (--n && mchip_read(reg) != v) udelay(1); return n; } /* setup subsampling */ -static void mchip_subsample(void) { +static void mchip_subsample(void) +{ mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample); mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize()); mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize()); @@ -546,29 +478,31 @@ static void mchip_subsample(void) { } /* set the framerate into the mchip */ -static void mchip_set_framerate(void) { +static void mchip_set_framerate(void) +{ mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate); } /* load some huffman and quantisation tables into the VRJ chip ready for JPEG compression */ -static void mchip_load_tables(void) { +static void mchip_load_tables(void) +{ int i; - int size; + int length; u16 *tables; - tables = jpeg_huffman_tables(&size); - for (i = 0; i < size / 2; i++) + tables = jpeg_huffman_tables(&length); + for (i = 0; i < length; i++) writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA); - tables = jpeg_quantisation_tables(&size, meye.params.quality); - for (i = 0; i < size / 2; i++) + tables = jpeg_quantisation_tables(&length, meye.params.quality); + for (i = 0; i < length; i++) writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA); } /* setup the VRJ parameters in the chip */ -static void mchip_vrj_setup(u8 mode) { - +static void mchip_vrj_setup(u8 mode) +{ mchip_set(MCHIP_VRJ_BUS_MODE, 5); mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f); mchip_set(MCHIP_VRJ_PDAT_USE, 1); @@ -585,23 +519,25 @@ static void mchip_vrj_setup(u8 mode) { mchip_set(MCHIP_VRJ_SOF2, 0x1502); mchip_set(MCHIP_VRJ_SOF3, 0x1503); mchip_set(MCHIP_VRJ_SOF4, 0x1596); - mchip_set(MCHIP_VRJ_SOS, 0x0ed0); + mchip_set(MCHIP_VRJ_SOS, 0x0ed0); mchip_load_tables(); } /* sets the DMA parameters into the chip */ -static void mchip_dma_setup(u32 dma_addr) { +static void mchip_dma_setup(dma_addr_t dma_addr) +{ int i; - mchip_set(MCHIP_MM_PT_ADDR, dma_addr); + mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr); for (i = 0; i < 4; i++) mchip_set(MCHIP_MM_FIR(i), 0); meye.mchip_fnum = 0; } /* setup for DMA transfers - also zeros the framebuffer */ -static int mchip_dma_alloc(void) { +static int mchip_dma_alloc(void) +{ if (!meye.mchip_dmahandle) if (ptable_alloc()) return -1; @@ -609,7 +545,8 @@ static int mchip_dma_alloc(void) { } /* frees the DMA buffer */ -static void mchip_dma_free(void) { +static void mchip_dma_free(void) +{ if (meye.mchip_dmahandle) { mchip_dma_setup(0); ptable_free(); @@ -618,7 +555,8 @@ static void mchip_dma_free(void) { /* stop any existing HIC action and wait for any dma to complete then reset the dma engine */ -static void mchip_hic_stop(void) { +static void mchip_hic_stop(void) +{ int i, j; meye.mchip_mode = MCHIP_HIC_MODE_NOOP; @@ -628,12 +566,13 @@ static void mchip_hic_stop(void) { mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP); mchip_delay(MCHIP_HIC_CMD, 0); for (j = 0; j < 100; ++j) { - if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) + if (mchip_delay(MCHIP_HIC_STATUS, + MCHIP_HIC_STATUS_IDLE)) return; msleep(1); } printk(KERN_ERR "meye: need to reset HIC!\n"); - + mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET); msleep(250); } @@ -645,15 +584,17 @@ static void mchip_hic_stop(void) { /****************************************************************************/ /* get the next ready frame from the dma engine */ -static u32 mchip_get_frame(void) { +static u32 mchip_get_frame(void) +{ u32 v; - + v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum)); return v; } /* frees the current frame from the dma engine */ -static void mchip_free_frame(void) { +static void mchip_free_frame(void) +{ mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0); meye.mchip_fnum++; meye.mchip_fnum %= 4; @@ -661,17 +602,18 @@ static void mchip_free_frame(void) { /* read one frame from the framebuffer assuming it was captured using a uncompressed transfer */ -static void mchip_cont_read_frame(u32 v, u8 *buf, int size) { +static void mchip_cont_read_frame(u32 v, u8 *buf, int size) +{ int pt_id; pt_id = (v >> 17) & 0x3FF; ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES); - } /* read a compressed frame from the framebuffer */ -static int mchip_comp_read_frame(u32 v, u8 *buf, int size) { +static int mchip_comp_read_frame(u32 v, u8 *buf, int size) +{ int pt_start, pt_end, trailer; int fsize; int i; @@ -687,18 +629,17 @@ static int mchip_comp_read_frame(u32 v, u8 *buf, int size) { fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4; if (fsize > size) { - printk(KERN_WARNING "meye: oversized compressed frame %d\n", + printk(KERN_WARNING "meye: oversized compressed frame %d\n", fsize); return -1; } ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG); - #ifdef MEYE_JPEG_CORRECTION /* Some mchip generated jpeg frames are incorrect. In most - * (all ?) of those cases, the final EOI (0xff 0xd9) marker + * (all ?) of those cases, the final EOI (0xff 0xd9) marker * is not present at the end of the frame. * * Since adding the final marker is not enough to restore @@ -716,9 +657,10 @@ static int mchip_comp_read_frame(u32 v, u8 *buf, int size) { } /* take a picture into SDRAM */ -static void mchip_take_picture(void) { +static void mchip_take_picture(void) +{ int i; - + mchip_hic_stop(); mchip_subsample(); mchip_dma_setup(meye.mchip_dmahandle); @@ -736,7 +678,8 @@ static void mchip_take_picture(void) { } /* dma a previously taken picture into a buffer */ -static void mchip_get_picture(u8 *buf, int bufsize) { +static void mchip_get_picture(u8 *buf, int bufsize) +{ u32 v; int i; @@ -749,7 +692,7 @@ static void mchip_get_picture(u8 *buf, int bufsize) { break; msleep(1); } - for (i = 0; i < 4 ; ++i) { + for (i = 0; i < 4; ++i) { v = mchip_get_frame(); if (v & MCHIP_MM_FIR_RDY) { mchip_cont_read_frame(v, buf, bufsize); @@ -760,7 +703,8 @@ static void mchip_get_picture(u8 *buf, int bufsize) { } /* start continuous dma capture */ -static void mchip_continuous_start(void) { +static void mchip_continuous_start(void) +{ mchip_hic_stop(); mchip_subsample(); mchip_set_framerate(); @@ -775,7 +719,8 @@ static void mchip_continuous_start(void) { } /* compress one frame into a buffer */ -static int mchip_compress_frame(u8 *buf, int bufsize) { +static int mchip_compress_frame(u8 *buf, int bufsize) +{ u32 v; int len = -1, i; @@ -784,7 +729,7 @@ static int mchip_compress_frame(u8 *buf, int bufsize) { mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); - + mchip_delay(MCHIP_HIC_CMD, 0); for (i = 0; i < 100; ++i) { if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE)) @@ -792,7 +737,7 @@ static int mchip_compress_frame(u8 *buf, int bufsize) { msleep(1); } - for (i = 0; i < 4 ; ++i) { + for (i = 0; i < 4; ++i) { v = mchip_get_frame(); if (v & MCHIP_MM_FIR_RDY) { len = mchip_comp_read_frame(v, buf, bufsize); @@ -805,13 +750,14 @@ static int mchip_compress_frame(u8 *buf, int bufsize) { #if 0 /* uncompress one image into a buffer */ -static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize) { +static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize) +{ mchip_vrj_setup(0x3f); udelay(50); mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP); mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START); - + mchip_delay(MCHIP_HIC_CMD, 0); return mchip_comp_read_frame(buf, bufsize); @@ -819,7 +765,8 @@ static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize) { #endif /* start continuous compressed capture */ -static void mchip_cont_compression_start(void) { +static void mchip_cont_compression_start(void) +{ mchip_hic_stop(); mchip_vrj_setup(0x3f); mchip_subsample(); @@ -838,88 +785,100 @@ static void mchip_cont_compression_start(void) { /* Interrupt handling */ /****************************************************************************/ -static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs) { +static irqreturn_t meye_irq(int irq, void *dev_id, struct pt_regs *regs) +{ u32 v; int reqnr; - v = mchip_read(MCHIP_MM_INTA); - - while (1) { - v = mchip_get_frame(); - if (!(v & MCHIP_MM_FIR_RDY)) - return IRQ_NONE; - switch (meye.mchip_mode) { + static int sequence = 0; - case MCHIP_HIC_MODE_CONT_OUT: - if (!meye_emptyq(&meye.grabq, NULL)) { - int nr = meye_pullq(&meye.grabq); - mchip_cont_read_frame( - v, - meye.grab_fbuffer + gbufsize * nr, - mchip_hsize() * mchip_vsize() * 2); - meye.grab_buffer[nr].state = MEYE_BUF_DONE; - wake_up_interruptible(&meye.grabq.proc_list); - } - break; + v = mchip_read(MCHIP_MM_INTA); - case MCHIP_HIC_MODE_CONT_COMP: - if (!meye_emptyq(&meye.grabq, &reqnr)) { - int size; - size = mchip_comp_read_frame( - v, - meye.grab_fbuffer + gbufsize * reqnr, - gbufsize); - if (size == -1) - break; - reqnr = meye_pullq(&meye.grabq); - meye.grab_buffer[reqnr].size = size; - meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; - wake_up_interruptible(&meye.grabq.proc_list); - } - break; + if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT && + meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) + return IRQ_NONE; - default: - /* do not free frame, since it can be a snap */ - return IRQ_NONE; - } /* switch */ +again: + v = mchip_get_frame(); + if (!(v & MCHIP_MM_FIR_RDY)) + return IRQ_HANDLED; - mchip_free_frame(); + if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { + if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + sizeof(int)) != sizeof(int)) { + mchip_free_frame(); + return IRQ_HANDLED; + } + mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr, + mchip_hsize() * mchip_vsize() * 2); + meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2; + meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; + do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); + meye.grab_buffer[reqnr].sequence = sequence++; + kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + wake_up_interruptible(&meye.proc_list); + } else { + int size; + size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize); + if (size == -1) { + mchip_free_frame(); + goto again; + } + if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + sizeof(int)) != sizeof(int)) { + mchip_free_frame(); + goto again; + } + memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp, + size); + meye.grab_buffer[reqnr].size = size; + meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; + do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); + meye.grab_buffer[reqnr].sequence = sequence++; + kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + wake_up_interruptible(&meye.proc_list); } - return IRQ_HANDLED; + mchip_free_frame(); + goto again; } /****************************************************************************/ /* video4linux integration */ /****************************************************************************/ -static int meye_open(struct inode *inode, struct file *file) { +static int meye_open(struct inode *inode, struct file *file) +{ int i, err; - err = video_exclusive_open(inode,file); + err = video_exclusive_open(inode, file); if (err < 0) return err; - + + mchip_hic_stop(); + if (mchip_dma_alloc()) { printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); - video_exclusive_release(inode,file); + video_exclusive_release(inode, file); return -ENOBUFS; } - mchip_hic_stop(); - meye_initq(&meye.grabq); + for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; + kfifo_reset(meye.grabq); + kfifo_reset(meye.doneq); return 0; } -static int meye_release(struct inode *inode, struct file *file) { +static int meye_release(struct inode *inode, struct file *file) +{ mchip_hic_stop(); mchip_dma_free(); - video_exclusive_release(inode,file); + video_exclusive_release(inode, file); return 0; } static int meye_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) { - + unsigned int cmd, void *arg) +{ switch (cmd) { case VIDIOCGCAP: { @@ -961,18 +920,18 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case VIDIOCSPICT: { struct video_picture *p = arg; - if (p->depth != 2) + if (p->depth != 16) return -EINVAL; if (p->palette != VIDEO_PALETTE_YUV422) return -EINVAL; down(&meye.lock); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, + sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, p->brightness >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, + sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, p->hue >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, + sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, p->colour >> 10); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, + sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, p->contrast >> 10); meye.picture = *p; up(&meye.lock); @@ -981,22 +940,34 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case VIDIOCSYNC: { int *i = arg; + int unused; if (*i < 0 || *i >= gbuffers) return -EINVAL; + down(&meye.lock); + switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: + up(&meye.lock); return -EINVAL; case MEYE_BUF_USING: - if (wait_event_interruptible(meye.grabq.proc_list, - (meye.grab_buffer[*i].state != MEYE_BUF_USING))) + if (file->f_flags & O_NONBLOCK) { + up(&meye.lock); + return -EAGAIN; + } + if (wait_event_interruptible(meye.proc_list, + (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { + up(&meye.lock); return -EINTR; + } /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; + kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } + up(&meye.lock); break; } @@ -1021,14 +992,12 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, meye.params.subsample = 0; restart = 1; } - } - else if (vm->width == 320 && vm->height == 240) { + } else if (vm->width == 320 && vm->height == 240) { if (!meye.params.subsample) { meye.params.subsample = 1; restart = 1; } - } - else { + } else { up(&meye.lock); return -EINVAL; } @@ -1036,7 +1005,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT) mchip_continuous_start(); meye.grab_buffer[vm->frame].state = MEYE_BUF_USING; - meye_pushq(&meye.grabq, vm->frame); + kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int)); up(&meye.lock); break; } @@ -1087,7 +1056,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case MEYEIOC_QBUF_CAPT: { int *nb = arg; - if (!meye.grab_fbuffer) + if (!meye.grab_fbuffer) return -EINVAL; if (*nb >= gbuffers) return -EINVAL; @@ -1102,36 +1071,47 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - meye_pushq(&meye.grabq, *nb); + kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); up(&meye.lock); break; } case MEYEIOC_SYNC: { int *i = arg; + int unused; if (*i < 0 || *i >= gbuffers) return -EINVAL; + down(&meye.lock); switch (meye.grab_buffer[*i].state) { case MEYE_BUF_UNUSED: + up(&meye.lock); return -EINVAL; case MEYE_BUF_USING: - if (wait_event_interruptible(meye.grabq.proc_list, - (meye.grab_buffer[*i].state != MEYE_BUF_USING))) + if (file->f_flags & O_NONBLOCK) { + up(&meye.lock); + return -EAGAIN; + } + if (wait_event_interruptible(meye.proc_list, + (meye.grab_buffer[*i].state != MEYE_BUF_USING))) { + up(&meye.lock); return -EINTR; + } /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; + kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; + up(&meye.lock); break; } case MEYEIOC_STILLCAPT: { - if (!meye.grab_fbuffer) + if (!meye.grab_fbuffer) return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; @@ -1149,7 +1129,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, case MEYEIOC_STILLJCAPT: { int *len = arg; - if (!meye.grab_fbuffer) + if (!meye.grab_fbuffer) return -EINVAL; if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED) return -EBUSY; @@ -1165,10 +1145,518 @@ static int meye_do_ioctl(struct inode *inode, struct file *file, break; } + case VIDIOC_QUERYCAP: { + struct v4l2_capability *cap = arg; + + if (forcev4l1) + return -EINVAL; + + memset(cap, 0, sizeof(*cap)); + strcpy(cap->driver, "meye"); + strcpy(cap->card, "meye"); + sprintf(cap->bus_info, "PCI:%s", meye.mchip_dev->slot_name); + cap->version = (MEYE_DRIVER_MAJORVERSION << 8) + + MEYE_DRIVER_MINORVERSION; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING; + break; + } + + case VIDIOC_ENUMINPUT: { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + memset(i, 0, sizeof(*i)); + i->index = 0; + strcpy(i->name, "Camera"); + i->type = V4L2_INPUT_TYPE_CAMERA; + break; + } + + case VIDIOC_G_INPUT: { + int *i = arg; + + *i = 0; + break; + } + + case VIDIOC_S_INPUT: { + int *i = arg; + + if (*i != 0) + return -EINVAL; + break; + } + + case VIDIOC_QUERYCTRL: { + struct v4l2_queryctrl *c = arg; + + switch (c->id) { + + case V4L2_CID_BRIGHTNESS: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Brightness"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_HUE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Hue"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_CONTRAST: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Contrast"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_SATURATION: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Saturation"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_AGC: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Agc"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 48; + c->flags = 0; + break; + case V4L2_CID_SHARPNESS: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Sharpness"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 32; + c->flags = 0; + break; + case V4L2_CID_PICTURE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Picture"); + c->minimum = 0; + c->maximum = 63; + c->step = 1; + c->default_value = 0; + c->flags = 0; + break; + case V4L2_CID_JPEGQUAL: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "JPEG quality"); + c->minimum = 0; + c->maximum = 10; + c->step = 1; + c->default_value = 8; + c->flags = 0; + break; + case V4L2_CID_FRAMERATE: + c->type = V4L2_CTRL_TYPE_INTEGER; + strcpy(c->name, "Framerate"); + c->minimum = 0; + c->maximum = 31; + c->step = 1; + c->default_value = 0; + c->flags = 0; + break; + default: + return -EINVAL; + } + break; + } + + case VIDIOC_S_CTRL: { + struct v4l2_control *c = arg; + + down(&meye.lock); + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERABRIGHTNESS, c->value); + meye.picture.brightness = c->value << 10; + break; + case V4L2_CID_HUE: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERAHUE, c->value); + meye.picture.hue = c->value << 10; + break; + case V4L2_CID_CONTRAST: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERACONTRAST, c->value); + meye.picture.contrast = c->value << 10; + break; + case V4L2_CID_SATURATION: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERACOLOR, c->value); + meye.picture.colour = c->value << 10; + break; + case V4L2_CID_AGC: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERAAGC, c->value); + meye.params.agc = c->value; + break; + case V4L2_CID_SHARPNESS: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERASHARPNESS, c->value); + meye.params.sharpness = c->value; + break; + case V4L2_CID_PICTURE: + sonypi_camera_command( + SONYPI_COMMAND_SETCAMERAPICTURE, c->value); + meye.params.picture = c->value; + break; + case V4L2_CID_JPEGQUAL: + meye.params.quality = c->value; + break; + case V4L2_CID_FRAMERATE: + meye.params.framerate = c->value; + break; + default: + up(&meye.lock); + return -EINVAL; + } + up(&meye.lock); + break; + } + + case VIDIOC_G_CTRL: { + struct v4l2_control *c = arg; + + down(&meye.lock); + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + c->value = meye.picture.brightness >> 10; + break; + case V4L2_CID_HUE: + c->value = meye.picture.hue >> 10; + break; + case V4L2_CID_CONTRAST: + c->value = meye.picture.contrast >> 10; + break; + case V4L2_CID_SATURATION: + c->value = meye.picture.colour >> 10; + break; + case V4L2_CID_AGC: + c->value = meye.params.agc; + break; + case V4L2_CID_SHARPNESS: + c->value = meye.params.sharpness; + break; + case V4L2_CID_PICTURE: + c->value = meye.params.picture; + break; + case V4L2_CID_JPEGQUAL: + c->value = meye.params.quality; + break; + case V4L2_CID_FRAMERATE: + c->value = meye.params.framerate; + break; + default: + up(&meye.lock); + return -EINVAL; + } + up(&meye.lock); + break; + } + + case VIDIOC_ENUM_FMT: { + struct v4l2_fmtdesc *f = arg; + + if (f->index > 1) + return -EINVAL; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (f->index == 0) { + /* standard YUV 422 capture */ + memset(f, 0, sizeof(*f)); + f->index = 0; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = 0; + strcpy(f->description, "YUV422"); + f->pixelformat = V4L2_PIX_FMT_YUYV; + } else { + /* compressed MJPEG capture */ + memset(f, 0, sizeof(*f)); + f->index = 1; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strcpy(f->description, "MJPEG"); + f->pixelformat = V4L2_PIX_FMT_MJPEG; + } + break; + } + + case VIDIOC_TRY_FMT: { + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && + f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + f->fmt.pix.field = V4L2_FIELD_NONE; + if (f->fmt.pix.width <= 320) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + } else { + f->fmt.pix.width = 640; + f->fmt.pix.height = 480; + } + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + break; + } + + case VIDIOC_G_FMT: { + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + switch (meye.mchip_mode) { + case MCHIP_HIC_MODE_CONT_OUT: + default: + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + break; + case MCHIP_HIC_MODE_CONT_COMP: + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; + break; + } + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.width = mchip_hsize(); + f->fmt.pix.height = mchip_vsize(); + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + break; + } + + case VIDIOC_S_FMT: { + struct v4l2_format *f = arg; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && + f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; + if (f->fmt.pix.field != V4L2_FIELD_ANY && + f->fmt.pix.field != V4L2_FIELD_NONE) + return -EINVAL; + f->fmt.pix.field = V4L2_FIELD_NONE; + down(&meye.lock); + if (f->fmt.pix.width <= 320) { + f->fmt.pix.width = 320; + f->fmt.pix.height = 240; + meye.params.subsample = 1; + } else { + f->fmt.pix.width = 640; + f->fmt.pix.height = 480; + meye.params.subsample = 0; + } + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUYV: + meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT; + break; + case V4L2_PIX_FMT_MJPEG: + meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP; + break; + } + up(&meye.lock); + f->fmt.pix.bytesperline = f->fmt.pix.width * 2; + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = 0; + f->fmt.pix.priv = 0; + + break; + } + + case VIDIOC_REQBUFS: { + struct v4l2_requestbuffers *req = arg; + int i; + + if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (req->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (meye.grab_fbuffer && req->count == gbuffers) { + /* already allocated, no modifications */ + break; + } + down(&meye.lock); + if (meye.grab_fbuffer) { + for (i = 0; i < gbuffers; i++) + if (meye.vma_use_count[i]) { + up(&meye.lock); + return -EINVAL; + } + rvfree(meye.grab_fbuffer, gbuffers * gbufsize); + meye.grab_fbuffer = NULL; + } + gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS)); + req->count = gbuffers; + meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize); + if (!meye.grab_fbuffer) { + printk(KERN_ERR "meye: v4l framebuffer allocation" + " failed\n"); + up(&meye.lock); + return -ENOMEM; + } + for (i = 0; i < gbuffers; i++) + meye.vma_use_count[i] = 0; + up(&meye.lock); + break; + } + + case VIDIOC_QUERYBUF: { + struct v4l2_buffer *buf = arg; + int index = buf->index; + + if (index < 0 || index >= gbuffers) + return -EINVAL; + memset(buf, 0, sizeof(*buf)); + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->index = index; + buf->bytesused = meye.grab_buffer[index].size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + if (meye.grab_buffer[index].state == MEYE_BUF_USING) + buf->flags |= V4L2_BUF_FLAG_QUEUED; + if (meye.grab_buffer[index].state == MEYE_BUF_DONE) + buf->flags |= V4L2_BUF_FLAG_DONE; + buf->field = V4L2_FIELD_NONE; + buf->timestamp = meye.grab_buffer[index].timestamp; + buf->sequence = meye.grab_buffer[index].sequence; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = index * gbufsize; + buf->length = gbufsize; + break; + } + + case VIDIOC_QBUF: { + struct v4l2_buffer *buf = arg; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (buf->index < 0 || buf->index >= gbuffers) + return -EINVAL; + if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) + return -EINVAL; + down(&meye.lock); + buf->flags |= V4L2_BUF_FLAG_QUEUED; + buf->flags &= ~V4L2_BUF_FLAG_DONE; + meye.grab_buffer[buf->index].state = MEYE_BUF_USING; + kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + up(&meye.lock); + break; + } + + case VIDIOC_DQBUF: { + struct v4l2_buffer *buf = arg; + int reqnr; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + down(&meye.lock); + if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + up(&meye.lock); + return -EAGAIN; + } + if (wait_event_interruptible(meye.proc_list, + kfifo_len(meye.doneq) != 0) < 0) { + up(&meye.lock); + return -EINTR; + } + if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, + sizeof(int))) { + up(&meye.lock); + return -EBUSY; + } + if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) { + up(&meye.lock); + return -EINVAL; + } + buf->index = reqnr; + buf->bytesused = meye.grab_buffer[reqnr].size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->field = V4L2_FIELD_NONE; + buf->timestamp = meye.grab_buffer[reqnr].timestamp; + buf->sequence = meye.grab_buffer[reqnr].sequence; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = reqnr * gbufsize; + buf->length = gbufsize; + meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED; + up(&meye.lock); + break; + } + + case VIDIOC_STREAMON: { + down(&meye.lock); + switch (meye.mchip_mode) { + case MCHIP_HIC_MODE_CONT_OUT: + mchip_continuous_start(); + break; + case MCHIP_HIC_MODE_CONT_COMP: + mchip_cont_compression_start(); + break; + default: + up(&meye.lock); + return -EINVAL; + } + up(&meye.lock); + break; + } + + case VIDIOC_STREAMOFF: { + int i; + + down(&meye.lock); + mchip_hic_stop(); + kfifo_reset(meye.grabq); + kfifo_reset(meye.doneq); + for (i = 0; i < MEYE_MAX_BUFNBRS; i++) + meye.grab_buffer[i].state = MEYE_BUF_UNUSED; + up(&meye.lock); + break; + } + + /* + * XXX what about private snapshot ioctls ? + * Do they need to be converted to V4L2 ? + */ + default: return -ENOIOCTLCMD; - - } /* switch */ + } return 0; } @@ -1179,9 +1667,40 @@ static int meye_ioctl(struct inode *inode, struct file *file, return video_usercopy(inode, file, cmd, arg, meye_do_ioctl); } -static int meye_mmap(struct file *file, struct vm_area_struct *vma) { +static unsigned int meye_poll(struct file *file, poll_table *wait) +{ + unsigned int res = 0; + + down(&meye.lock); + poll_wait(file, &meye.proc_list, wait); + if (kfifo_len(meye.doneq)) + res = POLLIN | POLLRDNORM; + up(&meye.lock); + return res; +} + +static void meye_vm_open(struct vm_area_struct *vma) +{ + int idx = (int)vma->vm_private_data; + meye.vma_use_count[idx]++; +} + +static void meye_vm_close(struct vm_area_struct *vma) +{ + int idx = (int)vma->vm_private_data; + meye.vma_use_count[idx]--; +} + +static struct vm_operations_struct meye_vm_ops = { + .open = meye_vm_open, + .close = meye_vm_close, +}; + +static int meye_mmap(struct file *file, struct vm_area_struct *vma) +{ unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long page, pos; down(&meye.lock); @@ -1190,6 +1709,8 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) { return -EINVAL; } if (!meye.grab_fbuffer) { + int i; + /* lazy allocation */ meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize); if (!meye.grab_fbuffer) { @@ -1197,19 +1718,31 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) { up(&meye.lock); return -ENOMEM; } + for (i = 0; i < gbuffers; i++) + meye.vma_use_count[i] = 0; } - pos = (unsigned long)meye.grab_fbuffer; + pos = (unsigned long)meye.grab_fbuffer + offset; while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { up(&meye.lock); return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; - size -= PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; } + + vma->vm_ops = &meye_vm_ops; + vma->vm_flags &= ~VM_IO; /* not I/O memory */ + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + vma->vm_private_data = (void *) (offset / gbufsize); + meye_vm_open(vma); + up(&meye.lock); return 0; } @@ -1220,6 +1753,7 @@ static struct file_operations meye_fops = { .release = meye_release, .mmap = meye_mmap, .ioctl = meye_ioctl, + .poll = meye_poll, .llseek = no_llseek, }; @@ -1236,7 +1770,7 @@ static struct video_device meye_template = { #ifdef CONFIG_PM static int meye_suspend(struct pci_dev *pdev, u32 state) { - pci_save_state(pdev, meye.pm_state); + pci_save_state(pdev); meye.pm_mchip_mode = meye.mchip_mode; mchip_hic_stop(); mchip_set(MCHIP_MM_INTA, 0x0); @@ -1245,7 +1779,7 @@ static int meye_suspend(struct pci_dev *pdev, u32 state) static int meye_resume(struct pci_dev *pdev) { - pci_restore_state(pdev, meye.pm_state); + pci_restore_state(pdev); pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1); mchip_delay(MCHIP_HIC_CMD, 0); @@ -1269,70 +1803,93 @@ static int meye_resume(struct pci_dev *pdev) } #endif -static int __devinit meye_probe(struct pci_dev *pcidev, - const struct pci_device_id *ent) { - int ret; +static int __devinit meye_probe(struct pci_dev *pcidev, + const struct pci_device_id *ent) +{ + int ret = -EBUSY; unsigned long mchip_adr; u8 revision; if (meye.mchip_dev != NULL) { printk(KERN_ERR "meye: only one device allowed!\n"); - ret = -EBUSY; - goto out1; + goto outnotdev; } meye.mchip_dev = pcidev; meye.video_dev = video_device_alloc(); if (!meye.video_dev) { printk(KERN_ERR "meye: video_device_alloc() failed!\n"); - ret = -EBUSY; - goto out1; + goto outnotdev; + } + + ret = -ENOMEM; + meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); + if (!meye.grab_temp) { + printk(KERN_ERR "meye: grab buffer allocation failed\n"); + goto outvmalloc; } + + meye.grabq_lock = SPIN_LOCK_UNLOCKED; + meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.grabq_lock); + if (IS_ERR(meye.grabq)) { + printk(KERN_ERR "meye: fifo allocation failed\n"); + goto outkfifoalloc1; + } + meye.doneq_lock = SPIN_LOCK_UNLOCKED; + meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.doneq_lock); + if (IS_ERR(meye.doneq)) { + printk(KERN_ERR "meye: fifo allocation failed\n"); + goto outkfifoalloc2; + } + memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); meye.video_dev->dev = &meye.mchip_dev->dev; - sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1); + if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) { + printk(KERN_ERR "meye: unable to power on the camera\n"); + printk(KERN_ERR "meye: did you enable the camera in " + "sonypi using the module options ?\n"); + goto outsonypienable; + } + ret = -EIO; if ((ret = pci_enable_device(meye.mchip_dev))) { printk(KERN_ERR "meye: pci_enable_device failed\n"); - goto out2; + goto outenabledev; } - meye.mchip_irq = pcidev->irq; mchip_adr = pci_resource_start(meye.mchip_dev,0); if (!mchip_adr) { printk(KERN_ERR "meye: mchip has no device base address\n"); - ret = -EIO; - goto out3; + goto outregions; } if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0), - pci_resource_len(meye.mchip_dev, 0), + pci_resource_len(meye.mchip_dev, 0), "meye")) { - ret = -EIO; printk(KERN_ERR "meye: request_mem_region failed\n"); - goto out3; + goto outregions; + } + meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); + if (!meye.mchip_mmregs) { + printk(KERN_ERR "meye: ioremap failed\n"); + goto outremap; } - pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); - - pci_set_master(meye.mchip_dev); + meye.mchip_irq = pcidev->irq; + if (request_irq(meye.mchip_irq, meye_irq, + SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq)) { + printk(KERN_ERR "meye: request_irq failed\n"); + goto outreqirq; + } + pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8); pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64); - if ((ret = request_irq(meye.mchip_irq, meye_irq, - SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq))) { - printk(KERN_ERR "meye: request_irq failed (ret=%d)\n", ret); - goto out4; - } + pci_set_master(meye.mchip_dev); - meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS); - if (!meye.mchip_mmregs) { - printk(KERN_ERR "meye: ioremap failed\n"); - ret = -EIO; - goto out5; - } - /* Ask the camera to perform a soft reset. */ pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1); @@ -1348,23 +1905,15 @@ static int __devinit meye_probe(struct pci_dev *pcidev, msleep(1); mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK); - if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER, video_nr) < 0) { - + if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER, + video_nr) < 0) { printk(KERN_ERR "meye: video_register_device failed\n"); - ret = -EIO; - goto out6; + goto outvideoreg; } - - printk(KERN_INFO "meye: Motion Eye Camera Driver v%d.%d.\n", - MEYE_DRIVER_MAJORVERSION, - MEYE_DRIVER_MINORVERSION); - printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", - revision, mchip_adr, meye.mchip_irq); - /* init all fields */ init_MUTEX(&meye.lock); - - meye.picture.depth = 2; + init_waitqueue_head(&meye.proc_list); + meye.picture.depth = 16; meye.picture.palette = VIDEO_PALETTE_YUV422; meye.picture.brightness = 32 << 10; meye.picture.hue = 32 << 10; @@ -1372,11 +1921,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev, meye.picture.contrast = 32 << 10; meye.picture.whiteness = 0; meye.params.subsample = 0; - meye.params.quality = 7; + meye.params.quality = 8; meye.params.sharpness = 32; meye.params.agc = 48; meye.params.picture = 0; meye.params.framerate = 0; + sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 32); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 32); sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 32); @@ -1385,27 +1935,38 @@ static int __devinit meye_probe(struct pci_dev *pcidev, sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 0); sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48); + printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", + MEYE_DRIVER_VERSION); + printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", + revision, mchip_adr, meye.mchip_irq); + return 0; -out6: - iounmap(meye.mchip_mmregs); -out5: + +outvideoreg: free_irq(meye.mchip_irq, meye_irq); -out4: +outreqirq: + iounmap(meye.mchip_mmregs); +outremap: release_mem_region(pci_resource_start(meye.mchip_dev, 0), pci_resource_len(meye.mchip_dev, 0)); -out3: +outregions: pci_disable_device(meye.mchip_dev); -out2: - video_device_release(meye.video_dev); - meye.video_dev = NULL; - +outenabledev: sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); -out1: +outsonypienable: + kfifo_free(meye.doneq); +outkfifoalloc2: + kfifo_free(meye.grabq); +outkfifoalloc1: + vfree(meye.grab_temp); +outvmalloc: + video_device_release(meye.video_dev); +outnotdev: return ret; } -static void __devexit meye_remove(struct pci_dev *pcidev) { - +static void __devexit meye_remove(struct pci_dev *pcidev) +{ video_unregister_device(meye.video_dev); mchip_hic_stop(); @@ -1424,16 +1985,23 @@ static void __devexit meye_remove(struct pci_dev *pcidev) { pci_disable_device(meye.mchip_dev); - if (meye.grab_fbuffer) - rvfree(meye.grab_fbuffer, gbuffers*gbufsize); - sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0); + kfifo_free(meye.doneq); + kfifo_free(meye.grabq); + + vfree(meye.grab_temp); + + if (meye.grab_fbuffer) { + rvfree(meye.grab_fbuffer, gbuffers*gbufsize); + meye.grab_fbuffer = NULL; + } + printk(KERN_INFO "meye: removed\n"); } static struct pci_device_id meye_pci_tbl[] = { - { PCI_VENDOR_ID_KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002, + { PCI_VENDOR_ID_KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { } }; @@ -1451,54 +2019,23 @@ static struct pci_driver meye_driver = { #endif }; -static int __init meye_init_module(void) { - if (gbuffers < 2) - gbuffers = 2; - if (gbuffers > MEYE_MAX_BUFNBRS) - gbuffers = MEYE_MAX_BUFNBRS; +static int __init meye_init(void) +{ + gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS)); if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE) gbufsize = MEYE_MAX_BUFSIZE; - printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) for capture\n", - gbuffers, gbufsize/1024, gbuffers*gbufsize/1024); - return pci_module_init(&meye_driver); + gbufsize = PAGE_ALIGN(gbufsize); + printk(KERN_INFO "meye: using %d buffers with %dk (%dk total)" + "for capture\n", + gbuffers, + gbufsize / 1024, gbuffers * gbufsize / 1024); + return pci_register_driver(&meye_driver); } -static void __exit meye_cleanup_module(void) { +static void __exit meye_exit(void) +{ pci_unregister_driver(&meye_driver); } -#ifndef MODULE -static int __init meye_setup(char *str) { - int ints[4]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] <= 0) - goto out; - gbuffers = ints[1]; - if (ints[0] == 1) - goto out; - gbufsize = ints[2]; - if (ints[0] == 2) - goto out; - video_nr = ints[3]; -out: - return 1; -} - -__setup("meye=", meye_setup); -#endif - -MODULE_AUTHOR("Stelian Pop "); -MODULE_DESCRIPTION("video4linux driver for the MotionEye camera"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(gbuffers,"i"); -MODULE_PARM_DESC(gbuffers,"number of capture buffers, default is 2 (32 max)"); -MODULE_PARM(gbufsize,"i"); -MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 614400"); -MODULE_PARM(video_nr,"i"); -MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)"); - -/* Module entry points */ -module_init(meye_init_module); -module_exit(meye_cleanup_module); +module_init(meye_init); +module_exit(meye_exit); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 0983b8e57..e8cd897b0 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -1,27 +1,27 @@ -/* +/* * Motion Eye video4linux driver for Sony Vaio PictureBook * - * Copyright (C) 2001-2003 Stelian Pop + * Copyright (C) 2001-2004 Stelian Pop * * Copyright (C) 2001-2002 Alcôve * * Copyright (C) 2000 Andrew Tridgell * * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras. - * + * * Some parts borrowed from various video4linux drivers, especially * bttv-driver.c and zoran.c, see original files for credits. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -30,12 +30,16 @@ #ifndef _MEYE_PRIV_H_ #define _MEYE_PRIV_H_ -#define MEYE_DRIVER_MAJORVERSION 1 -#define MEYE_DRIVER_MINORVERSION 10 +#define MEYE_DRIVER_MAJORVERSION 1 +#define MEYE_DRIVER_MINORVERSION 13 + +#define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \ + __stringify(MEYE_DRIVER_MINORVERSION) #include #include #include +#include /****************************************************************************/ /* Motion JPEG chip registers */ @@ -43,7 +47,7 @@ /* Motion JPEG chip PCI configuration registers */ #define MCHIP_PCI_POWER_CSR 0x54 -#define MCHIP_PCI_MCORE_STATUS 0x60 /* see HIC_STATUS */ +#define MCHIP_PCI_MCORE_STATUS 0x60 /* see HIC_STATUS */ #define MCHIP_PCI_HOSTUSEREQ_SET 0x64 #define MCHIP_PCI_HOSTUSEREQ_CLR 0x68 #define MCHIP_PCI_LOWPOWER_SET 0x6c @@ -73,7 +77,7 @@ #define MCHIP_MM_INTA_PCI_ERR 0x00000040 /* PCI error */ #define MCHIP_MM_INTA_PCI_ERR_MASK 0x00004000 -#define MCHIP_MM_PT_ADDR 0x08 /* page table address */ +#define MCHIP_MM_PT_ADDR 0x08 /* page table address*/ /* n*4kB */ #define MCHIP_NB_PAGES 1024 /* pages for display */ #define MCHIP_NB_PAGES_MJPEG 256 /* pages for mjpeg */ @@ -275,47 +279,38 @@ struct meye_grab_buffer { int state; /* state of buffer */ unsigned long size; /* size of jpg frame */ + struct timeval timestamp; /* timestamp */ + unsigned long sequence; /* sequence number */ }; -/* queues containing the buffer indices */ +/* size of kfifos containings buffer indices */ #define MEYE_QUEUE_SIZE MEYE_MAX_BUFNBRS -struct meye_queue { - unsigned int head; /* queue head */ - unsigned int tail; /* queue tail */ - unsigned int len; /* queue length */ - spinlock_t s_lock; /* spinlock protecting the queue */ - wait_queue_head_t proc_list; /* wait queue */ - int buf[MEYE_QUEUE_SIZE]; /* queue contents */ -}; /* Motion Eye device structure */ struct meye { - - /* mchip related */ struct pci_dev *mchip_dev; /* pci device */ u8 mchip_irq; /* irq */ u8 mchip_mode; /* actual mchip mode: HIC_MODE... */ u8 mchip_fnum; /* current mchip frame number */ - - unsigned char *mchip_mmregs; /* mchip: memory mapped registers */ + unsigned char __iomem *mchip_mmregs;/* mchip: memory mapped registers */ u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */ - dma_addr_t *mchip_ptable_toc; /* mchip: ptable toc */ + void *mchip_ptable_toc; /* mchip: ptable toc */ dma_addr_t mchip_dmahandle; /* mchip: dma handle to ptable toc */ - unsigned char *grab_fbuffer; /* capture framebuffer */ + unsigned char *grab_temp; /* temporary buffer */ /* list of buffers */ struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; - - /* other */ + int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ struct semaphore lock; /* semaphore for open/mmap... */ - - struct meye_queue grabq; /* queue for buffers to be grabbed */ - + struct kfifo *grabq; /* queue for buffers to be grabbed */ + spinlock_t grabq_lock; /* lock protecting the queue */ + struct kfifo *doneq; /* queue for grabbed buffers */ + spinlock_t doneq_lock; /* lock protecting the queue */ + wait_queue_head_t proc_list; /* wait queue */ struct video_device *video_dev; /* video device parameters */ struct video_picture picture; /* video picture parameters */ struct meye_params params; /* additional parameters */ #ifdef CONFIG_PM - u32 pm_state[16]; /* PCI configuration space */ u8 pm_mchip_mode; /* old mchip mode */ #endif }; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 41adfef5c..386963798 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include @@ -54,54 +56,53 @@ #include #include "msp3400.h" +#define OPMODE_AUTO -1 +#define OPMODE_MANUAL 0 +#define OPMODE_SIMPLE 1 /* use short programming (>= msp3410 only) */ +#define OPMODE_SIMPLER 2 /* use shorter programming (>= msp34xxG) */ + /* insmod parameters */ +static int opmode = OPMODE_AUTO; static int debug = 0; /* debug output */ static int once = 0; /* no continous stereo monitoring */ static int amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), - the autoscan seems work well only with FM... */ -static int simple = -1; /* use short programming (>= msp3410 only) */ + the autoscan seems work well only with FM... */ +static int standard = 1; /* Override auto detect of audio standard, if needed. */ static int dolby = 0; -#define DFP_COUNT 0x41 -static const int bl_dfp[] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a, - 0x0b, 0x0d, 0x0e, 0x10 -}; +static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual + (msp34xxg only) 0x00a0-0x03c0 */ struct msp3400c { int rev1,rev2; - - int simple; + + int opmode; int mode; int norm; - int stereo; int nicam_on; int acb; int main, second; /* sound carrier */ int input; + int source; /* see msp34xxg_set_source */ + + /* v4l2 */ + int audmode; + int rxsubchans; int muted; int volume, balance; int bass, treble; - /* shadow register set */ - int dfp_regs[DFP_COUNT]; - /* thread */ - pid_t tpid; - struct completion texit; + struct task_struct *kthread; wait_queue_head_t wq; - - int active:1; int restart:1; - int rmmod:1; - - int watch_stereo; - struct timer_list wake_stereo; + int watch_stereo:1; }; #define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00) #define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@') +#define HAVE_SIMPLER(msp) ((msp->rev1 & 0xff) >= 'G'-'@') #define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@') #define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */ @@ -111,11 +112,21 @@ struct msp3400c { #define dprintk if (debug >= 1) printk #define d2printk if (debug >= 2) printk -MODULE_PARM(once,"i"); -MODULE_PARM(debug,"i"); -MODULE_PARM(simple,"i"); -MODULE_PARM(amsound,"i"); -MODULE_PARM(dolby,"i"); +/* read-only */ +module_param(opmode, int, 0444); + +/* read-write */ +module_param(once, int, 0644); +module_param(debug, int, 0644); +module_param(stereo_threshold, int, 0644); +module_param(standard, int, 0644); +module_param(amsound, int, 0644); +module_param(dolby, int, 0644); + +MODULE_PARM_DESC(once, "No continuous stereo monitoring"); +MODULE_PARM_DESC(debug, "Enable debug messages"); +MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect"); +MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan"); MODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); MODULE_AUTHOR("Gerd Knorr"); @@ -141,10 +152,6 @@ I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ /* functions for talking to the MSP3400C Sound processor */ -#ifndef I2C_M_IGNORE_NAK -# define I2C_M_IGNORE_NAK 0x1000 -#endif - static int msp3400c_reset(struct i2c_client *client) { /* reset and read revision code */ @@ -160,14 +167,14 @@ static int msp3400c_reset(struct i2c_client *client) { client->addr, 0, 3, write }, { client->addr, I2C_M_RD, 2, read }, }; - + if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) || (1 != i2c_transfer(client->adapter,&reset[1],1)) || (2 != i2c_transfer(client->adapter,test,2)) ) { printk(KERN_ERR "msp3400: chip reset failed\n"); return -1; } - return 0; + return 0; } static int @@ -191,15 +198,14 @@ msp3400c_read(struct i2c_client *client, int dev, int addr) err++; printk(KERN_WARNING "msp34xx: I/O error #%d (read 0x%02x/0x%02x)\n", err, dev, addr); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(10); } if (3 == err) { printk(KERN_WARNING "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); msp3400c_reset(client); return -1; } - return read[0] << 8 | read[1]; + return read[0] << 8 | read[1]; } static int @@ -220,8 +226,7 @@ msp3400c_write(struct i2c_client *client, int dev, int addr, int val) err++; printk(KERN_WARNING "msp34xx: I/O error #%d (write 0x%02x/0x%02x)\n", err, dev, addr); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(10); } if (3 == err) { printk(KERN_WARNING "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); @@ -305,15 +310,15 @@ struct CARRIER_DETECT { static struct CARRIER_DETECT carrier_detect_main[] = { /* main carrier */ - { MSP_CARRIER(4.5), "4.5 NTSC" }, - { MSP_CARRIER(5.5), "5.5 PAL B/G" }, + { MSP_CARRIER(4.5), "4.5 NTSC" }, + { MSP_CARRIER(5.5), "5.5 PAL B/G" }, { MSP_CARRIER(6.0), "6.0 PAL I" }, { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } }; static struct CARRIER_DETECT carrier_detect_55[] = { /* PAL B/G */ - { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, + { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } }; @@ -331,16 +336,6 @@ static struct CARRIER_DETECT carrier_detect_65[] = { /* ----------------------------------------------------------------------- */ -#define SCART_MASK 0 -#define SCART_IN1 1 -#define SCART_IN2 2 -#define SCART_IN1_DA 3 -#define SCART_IN2_DA 4 -#define SCART_IN3 5 -#define SCART_IN4 6 -#define SCART_MONO 7 -#define SCART_MUTE 8 - static int scarts[3][9] = { /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, @@ -394,8 +389,8 @@ static void msp3400c_setvolume(struct i2c_client *client, muted ? "on" : "off", volume, balance, val>>8, bal); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ - /* scart - on/off only */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, + muted ? 0x01 : (val | 0x01)); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, bal << 8); } @@ -419,31 +414,32 @@ static void msp3400c_setmode(struct i2c_client *client, int type) { struct msp3400c *msp = i2c_get_clientdata(client); int i; - + dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type); - msp->mode = type; - msp->stereo = VIDEO_SOUND_MONO; + msp->mode = type; + msp->audmode = V4L2_TUNER_MODE_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */ msp_init_data[type].ad_cv); - + for (i = 5; i >= 0; i--) /* fir 1 */ msp3400c_write(client,I2C_MSP3400C_DEM, 0x0001, msp_init_data[type].fir1[i]); - + msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */ msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0040); msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0000); for (i = 5; i >= 0; i--) msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, msp_init_data[type].fir2[i]); - + msp3400c_write(client,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */ msp_init_data[type].mode_reg); - + msp3400c_setcarrier(client, msp_init_data[type].cdo1, msp_init_data[type].cdo2); - + msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/ if (dolby) { @@ -472,51 +468,67 @@ static void msp3400c_setmode(struct i2c_client *client, int type) } } +static int best_audio_mode(int rxsubchans) +{ + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + return V4L2_TUNER_MODE_LANG1; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + return V4L2_TUNER_MODE_LANG2; + return V4L2_TUNER_MODE_MONO; +} + /* turn on/off nicam + stereo */ -static void msp3400c_setstereo(struct i2c_client *client, int mode) +static void msp3400c_set_audmode(struct i2c_client *client, int audmode) { static char *strmode[16] = { #if __GNUC__ >= 3 - [ 0 ... 15 ] = "invalid", + [ 0 ... 15 ] = "invalid", #endif - [ VIDEO_SOUND_MONO ] = "mono", - [ VIDEO_SOUND_STEREO ] = "stereo", - [ VIDEO_SOUND_LANG1 ] = "lang1", - [ VIDEO_SOUND_LANG2 ] = "lang2", + [ V4L2_TUNER_MODE_MONO ] = "mono", + [ V4L2_TUNER_MODE_STEREO ] = "stereo", + [ V4L2_TUNER_MODE_LANG1 ] = "lang1", + [ V4L2_TUNER_MODE_LANG2 ] = "lang2", }; struct msp3400c *msp = i2c_get_clientdata(client); int nicam=0; /* channel source: FM/AM or nicam */ int src=0; + BUG_ON(msp->opmode == OPMODE_SIMPLER); + msp->audmode = audmode; + /* switch demodulator */ switch (msp->mode) { case MSP_MODE_FM_TERRA: - dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); break; - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_LANG2: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000); break; } break; case MSP_MODE_FM_SAT: - dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",strmode[mode]); - switch (mode) { - case VIDEO_SOUND_MONO: + dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n", + strmode[audmode]); + switch (audmode) { + case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; } @@ -524,21 +536,25 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); if (msp->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n", + strmode[audmode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n", + strmode[audmode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n", + strmode[audmode]); break; default: dprintk(KERN_DEBUG "msp3400: mono setstereo\n"); @@ -546,15 +562,15 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) } /* switch audio */ - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: src = 0x0020 | nicam; -#if 0 +#if 0 /* spatial effect */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000); #endif break; - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: if (msp->mode == MSP_MODE_AM_NICAM) { dprintk("msp3400: switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ @@ -563,10 +579,10 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) src = 0x0200; break; } - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: src = 0x0000 | nicam; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: src = 0x0010 | nicam; break; } @@ -610,19 +626,6 @@ msp3400c_print_mode(struct msp3400c *msp) } } -static void -msp3400c_restore_dfp(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - for (i = 0; i < DFP_COUNT; i++) { - if (-1 == msp->dfp_regs[i]) - continue; - msp3400c_write(client,I2C_MSP3400C_DFP, i, msp->dfp_regs[i]); - } -} - /* ----------------------------------------------------------------------- */ struct REGISTER_DUMP { @@ -643,8 +646,8 @@ autodetect_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); int val; - int newstereo = msp->stereo; - int newnicam = msp->nicam_on; + int rxsubchans = msp->rxsubchans; + int newnicam = msp->nicam_on; int update = 0; switch (msp->mode) { @@ -655,11 +658,11 @@ autodetect_stereo(struct i2c_client *client) dprintk(KERN_DEBUG "msp34xx: stereo detect register: %d\n",val); if (val > 4096) { - newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; } else if (val < -4096) { - newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } newnicam = 0; break; @@ -676,27 +679,27 @@ autodetect_stereo(struct i2c_client *client) switch ((val & 0x1e) >> 1) { case 0: case 8: - newstereo = VIDEO_SOUND_STEREO; + rxsubchans = V4L2_TUNER_SUB_STEREO; break; case 1: case 9: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1; break; case 2: case 10: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1 - | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; break; default: - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; break; } newnicam=1; } else { newnicam = 0; - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } break; case MSP_MODE_BTSC: @@ -709,16 +712,16 @@ autodetect_stereo(struct i2c_client *client) (val & 0x0040) ? "stereo" : "mono", (val & 0x0080) ? ", nicam 2nd mono" : "", (val & 0x0100) ? ", bilingual/SAP" : ""); - newstereo = VIDEO_SOUND_MONO; - if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO; - if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO; + if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; + if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; break; } - if (newstereo != msp->stereo) { + if (rxsubchans != msp->rxsubchans) { update = 1; - dprintk(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n", - msp->stereo,newstereo); - msp->stereo = newstereo; + dprintk(KERN_DEBUG "msp34xx: watch: rxsubchans %d => %d\n", + msp->rxsubchans,rxsubchans); + msp->rxsubchans = rxsubchans; } if (newnicam != msp->nicam_on) { update = 1; @@ -739,22 +742,24 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) DECLARE_WAITQUEUE(wait, current); add_wait_queue(&msp->wq, &wait); - if (!msp->rmmod) { - set_current_state(TASK_INTERRUPTIBLE); - if (timeout < 0) + if (!kthread_should_stop()) { + if (timeout < 0) { + set_current_state(TASK_INTERRUPTIBLE); schedule(); - else - schedule_timeout(timeout); + } else { +#if 0 + /* hmm, that one doesn't return on wakeup ... */ + msleep_interruptible(timeout); +#else + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(timeout)); +#endif + } } + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); remove_wait_queue(&msp->wq, &wait); - return msp->rmmod || signal_pending(current); -} - -static void msp3400c_stereo_wake(unsigned long data) -{ - struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */ - - wake_up_interruptible(&msp->wq); + return msp->restart; } /* stereo/multilang monitoring */ @@ -762,53 +767,31 @@ static void watch_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); - if (autodetect_stereo(client)) { - if (msp->stereo & VIDEO_SOUND_STEREO) - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); - else if (msp->stereo & VIDEO_SOUND_LANG1) - msp3400c_setstereo(client,VIDEO_SOUND_LANG1); - else if (msp->stereo & VIDEO_SOUND_LANG2) - msp3400c_setstereo(client,VIDEO_SOUND_LANG2); - else - msp3400c_setstereo(client,VIDEO_SOUND_MONO); - } + if (autodetect_stereo(client)) + msp3400c_set_audmode(client,best_audio_mode(msp->rxsubchans)); if (once) msp->watch_stereo = 0; - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+5*HZ); } static int msp3400c_thread(void *data) { struct i2c_client *client = data; struct msp3400c *msp = i2c_get_clientdata(client); - struct CARRIER_DETECT *cd; int count, max1,max2,val1,val2, val,this; - - daemonize("msp3400"); - allow_signal(SIGTERM); - printk("msp3400: daemon started\n"); + printk("msp3400: kthread started\n"); for (;;) { d2printk("msp3400: thread: sleep\n"); - if (msp34xx_sleep(msp,-1)) - goto done; - + msp34xx_sleep(msp,-1); d2printk("msp3400: thread: wakeup\n"); - msp->active = 1; - - if (msp->watch_stereo) { - watch_stereo(client); - msp->active = 0; - continue; - } - /* some time for the tuner to sync */ - if (msp34xx_sleep(msp,HZ/5)) - goto done; - restart: + dprintk("msp3410: thread: restart scan\n"); + msp->restart = 0; + if (kthread_should_stop()) + break; + if (VIDEO_MODE_RADIO == msp->norm || MSP_MODE_EXTERN == msp->mode) { /* no carrier scan, just unmute */ @@ -817,14 +800,18 @@ static int msp3400c_thread(void *data) msp->volume, msp->balance); continue; } - msp->restart = 0; + + /* mute */ msp3400c_setvolume(client, msp->muted, 0, 0); msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); val1 = val2 = 0; max1 = max2 = -1; - del_timer(&msp->wake_stereo); msp->watch_stereo = 0; + /* some time for the tuner to sync */ + if (msp34xx_sleep(msp,200)) + goto restart; + /* carrier detect pass #1 -- main carrier */ cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main); @@ -837,12 +824,8 @@ static int msp3400c_thread(void *data) for (this = 0; this < count; this++) { msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); - - if (msp34xx_sleep(msp,HZ/10)) - goto done; - if (msp->restart) - msp->restart = 0; - + if (msp34xx_sleep(msp,100)) + goto restart; val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); if (val > 32767) val -= 65536; @@ -850,14 +833,16 @@ static int msp3400c_thread(void *data) val1 = val, max1 = this; dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name); } - + /* carrier detect pass #2 -- second (stereo) carrier */ switch (max1) { case 1: /* 5.5 */ - cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55); + cd = carrier_detect_55; + count = CARRIER_COUNT(carrier_detect_55); break; case 3: /* 6.5 */ - cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65); + cd = carrier_detect_65; + count = CARRIER_COUNT(carrier_detect_65); break; case 0: /* 4.5 */ case 2: /* 6.0 */ @@ -865,19 +850,15 @@ static int msp3400c_thread(void *data) cd = NULL; count = 0; break; } - + if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { /* autodetect doesn't work well with AM ... */ cd = NULL; count = 0; max2 = 0; } for (this = 0; this < count; this++) { msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); - - if (msp34xx_sleep(msp,HZ/10)) - goto done; - if (msp->restart) + if (msp34xx_sleep(msp,100)) goto restart; - val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); if (val > 32767) val -= 65536; @@ -895,7 +876,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 1 && HAVE_NICAM(msp)) { /* B/G NICAM */ @@ -922,7 +903,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 0 && msp->norm == VIDEO_MODE_SECAM) { @@ -930,7 +911,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp3400c_setcarrier(client, msp->second, msp->main); /* volume prescale for SCART (AM mono input) */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); @@ -953,29 +934,26 @@ static int msp3400c_thread(void *data) msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; msp3400c_setcarrier(client, msp->second, msp->main); - msp->stereo = VIDEO_SOUND_MONO; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); break; } - /* unmute + restore dfp registers */ + /* unmute */ msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance); - msp3400c_restore_dfp(client); - - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+5*HZ); - if (debug) msp3400c_print_mode(msp); - - msp->active = 0; - } -done: - msp->active = 0; + /* monitor tv audio mode */ + while (msp->watch_stereo) { + if (msp34xx_sleep(msp,5000)) + goto restart; + watch_stereo(client); + } + } dprintk(KERN_DEBUG "msp3400: thread: exit\n"); - complete_and_exit(&msp->texit, 0); + return 0; } /* ----------------------------------------------------------------------- */ @@ -1008,36 +986,68 @@ static struct MODES { { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, { -1, 0, 0, NULL }, /* EOF */ }; - + +static inline const char *msp34xx_standard_mode_name(int mode) +{ + int i; + for (i = 0; modelist[i].name != NULL; i++) + if (modelist[i].retval == mode) + return modelist[i].name; + return "unknown"; +} + +static int msp34xx_modus(int norm) +{ + switch (norm) { + case VIDEO_MODE_PAL: + return 0x1003; + case VIDEO_MODE_NTSC: /* BTSC */ + return 0x2003; + case VIDEO_MODE_SECAM: + return 0x0003; + case VIDEO_MODE_RADIO: + return 0x0003; + case VIDEO_MODE_AUTO: + return 0x2003; + default: + return 0x0003; + } +} + +static int msp34xx_standard(int norm) +{ + switch (norm) { + case VIDEO_MODE_PAL: + return 1; + case VIDEO_MODE_NTSC: /* BTSC */ + return 0x0020; + case VIDEO_MODE_SECAM: + return 1; + case VIDEO_MODE_RADIO: + return 0x0040; + default: + return 1; + } +} + static int msp3410d_thread(void *data) { struct i2c_client *client = data; struct msp3400c *msp = i2c_get_clientdata(client); int mode,val,i,std; - - daemonize("msp3410 [auto]"); - allow_signal(SIGTERM); - printk("msp3410: daemon started\n"); + printk("msp3410: daemon started\n"); for (;;) { d2printk(KERN_DEBUG "msp3410: thread: sleep\n"); - if (msp34xx_sleep(msp,-1)) - goto done; - + msp34xx_sleep(msp,-1); d2printk(KERN_DEBUG "msp3410: thread: wakeup\n"); - msp->active = 1; - - if (msp->watch_stereo) { - watch_stereo(client); - msp->active = 0; - continue; - } - - /* some time for the tuner to sync */ - if (msp34xx_sleep(msp,HZ/5)) - goto done; restart: + dprintk("msp3410: thread: restart scan\n"); + msp->restart = 0; + if (kthread_should_stop()) + break; + if (msp->mode == MSP_MODE_EXTERN) { /* no carrier scan needed, just unmute */ dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n"); @@ -1045,47 +1055,24 @@ static int msp3410d_thread(void *data) msp->volume, msp->balance); continue; } - msp->restart = 0; - del_timer(&msp->wake_stereo); - msp->watch_stereo = 0; /* put into sane state (and mute) */ msp3400c_reset(client); + /* some time for the tuner to sync */ + if (msp34xx_sleep(msp,200)) + goto restart; + /* start autodetect */ - switch (msp->norm) { - case VIDEO_MODE_PAL: - mode = 0x1003; - std = 1; - break; - case VIDEO_MODE_NTSC: /* BTSC */ - mode = 0x2003; - std = 0x0020; - break; - case VIDEO_MODE_SECAM: - mode = 0x0003; - std = 1; - break; - case VIDEO_MODE_RADIO: - mode = 0x0003; - std = 0x0040; - break; - default: - mode = 0x0003; - std = 1; - break; - } + mode = msp34xx_modus(msp->norm); + std = msp34xx_standard(msp->norm); msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode); msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std); + msp->watch_stereo = 0; - if (debug) { - int i; - for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == std) - break; + if (debug) printk(KERN_DEBUG "msp3410: setting mode: %s (0x%04x)\n", - modelist[i].name ? modelist[i].name : "unknown",std); - } + msp34xx_standard_mode_name(std) ,std); if (std != 1) { /* programmed some specific mode */ @@ -1093,9 +1080,7 @@ static int msp3410d_thread(void *data) } else { /* triggered autodetect */ for (;;) { - if (msp34xx_sleep(msp,HZ/10)) - goto done; - if (msp->restart) + if (msp34xx_sleep(msp,100)) goto restart; /* check results */ @@ -1137,29 +1122,30 @@ static int msp3410d_thread(void *data) else msp->mode = MSP_MODE_FM_NICAM2; /* just turn on stereo */ - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 1; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; - case 0x0009: + case 0x0009: msp->mode = MSP_MODE_AM_NICAM; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp->nicam_on = 1; - msp3400c_setstereo(client,VIDEO_SOUND_MONO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; break; case 0x0020: /* BTSC */ /* just turn on stereo */ - msp->mode = MSP_MODE_BTSC; - msp->stereo = VIDEO_SOUND_STEREO; + msp->mode = MSP_MODE_BTSC; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 0; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; case 0x0040: /* FM radio */ msp->mode = MSP_MODE_FM_RADIO; - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp->nicam_on = 0; msp->watch_stereo = 0; /* not needed in theory if HAVE_RADIO(), but @@ -1185,32 +1171,251 @@ static int msp3410d_thread(void *data) case 0x0004: case 0x0005: msp->mode = MSP_MODE_FM_TERRA; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp->audmode = V4L2_TUNER_MODE_MONO; msp->nicam_on = 0; msp->watch_stereo = 1; break; } - - /* unmute + restore dfp registers */ + + /* unmute, restore misc registers */ msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance); - msp3400c_restore_dfp(client); - - if (msp->watch_stereo) - mod_timer(&msp->wake_stereo, jiffies+HZ); + msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); - msp->active = 0; + /* monitor tv audio mode */ + while (msp->watch_stereo) { + if (msp34xx_sleep(msp,5000)) + goto restart; + watch_stereo(client); + } } - -done: - msp->active = 0; dprintk(KERN_DEBUG "msp3410: thread: exit\n"); - complete_and_exit(&msp->texit, 0); return 0; } +/* ----------------------------------------------------------------------- */ +/* msp34xxG + (simpler no-thread) */ +/* this one uses both automatic standard detection and automatic sound */ +/* select which are available in the newer G versions */ +/* struct msp: only norm, acb and source are really used in this mode */ + +static void msp34xxg_set_source(struct i2c_client *client, int source); + +/* (re-)initialize the msp34xxg, according to the current norm in msp->norm + * return 0 if it worked, -1 if it failed + */ +static int msp34xxg_init(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + int modus; + + if (msp3400c_reset(client)) + return -1; + + /* make sure that input/output is muted (paranoid mode) */ + if (msp3400c_write(client, + I2C_MSP3400C_DFP, + 0x13, /* ACB */ + 0x0f20 /* mute DSP input, mute SCART 1 */)) + return -1; + + /* step-by-step initialisation, as described in the manual */ + modus = msp34xx_modus(msp->norm); + modus &= ~0x03; /* STATUS_CHANGE=0 */ + modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION=1 */ + if (msp3400c_write(client, + I2C_MSP3400C_DEM, + 0x30/*MODUS*/, + modus)) + return -1; + + /* write the dfps that may have an influence on + standard/audio autodetection right now */ + msp34xxg_set_source(client, msp->source); + + if (msp3400c_write(client, I2C_MSP3400C_DFP, + 0x0e, /* AM/FM Prescale */ + 0x3000 /* default: [15:8] 75khz deviation */)) + return -1; + + if (msp3400c_write(client, I2C_MSP3400C_DFP, + 0x10, /* NICAM Prescale */ + 0x5a00 /* default: 9db gain (as recommended) */)) + return -1; + + if (msp3400c_write(client, + I2C_MSP3400C_DEM, + 0x20, /* STANDARD SELECT */ + standard /* default: 0x01 for automatic standard select*/)) + return -1; + return 0; +} + +static int msp34xxg_thread(void *data) +{ + struct i2c_client *client = data; + struct msp3400c *msp = i2c_get_clientdata(client); + int val, std, i; + + printk("msp34xxg: daemon started\n"); + for (;;) { + d2printk(KERN_DEBUG "msp34xxg: thread: sleep\n"); + msp34xx_sleep(msp,-1); + d2printk(KERN_DEBUG "msp34xxg: thread: wakeup\n"); + + restart: + dprintk("msp34xxg: thread: restart scan\n"); + msp->restart = 0; + if (kthread_should_stop()) + break; + + /* setup the chip*/ + msp34xxg_init(client); + std = standard; + if (std != 0x01) + goto unmute; + + /* watch autodetect */ + dprintk("msp34xxg: triggered autodetect, waiting for result\n"); + for (i = 0; i < 10; i++) { + if (msp34xx_sleep(msp,100)) + goto restart; + + /* check results */ + val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); + if (val < 0x07ff) { + std = val; + break; + } + dprintk("msp34xxg: detection still in progress\n"); + } + if (0x01 == std) { + dprintk("msp34xxg: detection still in progress after 10 tries. giving up.\n"); + continue; + } + + unmute: + dprintk("msp34xxg: current mode: %s (0x%04x)\n", + msp34xx_standard_mode_name(std), std); + + /* unmute: dispatch sound to scart output, set scart volume */ + dprintk("msp34xxg: unmute\n"); + + msp3400c_setbass(client, msp->bass); + msp3400c_settreble(client, msp->treble); + msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance); + + /* restore ACB */ + if (msp3400c_write(client, + I2C_MSP3400C_DFP, + 0x13, /* ACB */ + msp->acb)) + return -1; + } + dprintk(KERN_DEBUG "msp34xxg: thread: exit\n"); + return 0; +} + +/* set the same 'source' for the loudspeaker, scart and quasi-peak detector + * the value for source is the same as bit 15:8 of DFP registers 0x08, + * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B + * + * this function replaces msp3400c_setstereo + */ +static void msp34xxg_set_source(struct i2c_client *client, int source) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + /* fix matrix mode to stereo and let the msp choose what + * to output according to 'source', as recommended + */ + int value = (source&0x07)<<8|(source==0 ? 0x00:0x20); + dprintk("msp34xxg: set source to %d (0x%x)\n", source, value); + msp3400c_write(client, + I2C_MSP3400C_DFP, + 0x08, /* Loudspeaker Output */ + value); + msp3400c_write(client, + I2C_MSP3400C_DFP, + 0x0a, /* SCART1 DA Output */ + value); + msp3400c_write(client, + I2C_MSP3400C_DFP, + 0x0c, /* Quasi-peak detector */ + value); + /* + * set identification threshold. Personally, I + * I set it to a higher value that the default + * of 0x190 to ignore noisy stereo signals. + * this needs tuning. (recommended range 0x00a0-0x03c0) + * 0x7f0 = forced mono mode + */ + msp3400c_write(client, + I2C_MSP3400C_DEM, + 0x22, /* a2 threshold for stereo/bilingual */ + source==0 ? 0x7f0:stereo_threshold); + msp->source=source; +} + +static void msp34xxg_detect_stereo(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + int status = msp3400c_read(client, + I2C_MSP3400C_DEM, + 0x0200 /* STATUS */); + int is_bilingual = status&0x100; + int is_stereo = status&0x40; + + msp->rxsubchans = 0; + if (is_stereo) + msp->rxsubchans |= V4L2_TUNER_SUB_STEREO; + else + msp->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (is_bilingual) { + msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; + /* I'm supposed to check whether it's SAP or not + * and set only LANG2/SAP in this case. Yet, the MSP + * does a lot of work to hide this and handle everything + * the same way. I don't want to work around it so unless + * this is a problem, I'll handle SAP just like lang1/lang2. + */ + } + dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", + status, is_stereo, is_bilingual, msp->rxsubchans); +} + +static void msp34xxg_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + int source = 0; + + switch (audmode) { + case V4L2_TUNER_MODE_MONO: + source=0; /* mono only */ + break; + case V4L2_TUNER_MODE_STEREO: + source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ + /* problem: that could also mean 2 (scart input) */ + break; + case V4L2_TUNER_MODE_LANG1: + source=3; /* stereo or A */ + break; + case V4L2_TUNER_MODE_LANG2: + source=4; /* stereo or B */ + break; + default: /* doing nothing: a safe, sane default */ + audmode = 0; + return; + } + msp->audmode = audmode; + msp34xxg_set_source(client, source); +} + + /* ----------------------------------------------------------------------- */ static int msp_attach(struct i2c_adapter *adap, int addr, int kind); @@ -1218,17 +1423,26 @@ static int msp_detach(struct i2c_client *client); static int msp_probe(struct i2c_adapter *adap); static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); +static int msp_suspend(struct device * dev, u32 state, u32 level); +static int msp_resume(struct device * dev, u32 level); + +static void msp_wake_thread(struct i2c_client *client); + static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c msp3400 driver", + .name = "i2c msp3400 driver", .id = I2C_DRIVERID_MSP3400, .flags = I2C_DF_NOTIFY, .attach_adapter = msp_probe, .detach_client = msp_detach, .command = msp_command, + .driver = { + .suspend = msp_suspend, + .resume = msp_resume, + }, }; -static struct i2c_client client_template = +static struct i2c_client client_template = { I2C_DEVNAME("(unset)"), .flags = I2C_CLIENT_ALLOW_USE, @@ -1239,7 +1453,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) { struct msp3400c *msp; struct i2c_client *c; - int i; + int (*thread_func)(void *data) = NULL; client_template.adapter = adap; client_template.addr = addr; @@ -1248,7 +1462,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) dprintk("msp3400: no chip found\n"); return -1; } - + if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) return -ENOMEM; memcpy(c,&client_template,sizeof(struct i2c_client)); @@ -1256,16 +1470,14 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) kfree(c); return -ENOMEM; } - + memset(msp,0,sizeof(struct msp3400c)); - msp->volume = 65535; + msp->volume = 58880; /* 0db gain */ msp->balance = 32768; - msp->bass = 32768; - msp->treble = 32768; - msp->input = -1; - msp->muted = 1; - for (i = 0; i < DFP_COUNT; i++) - msp->dfp_regs[i] = -1; + msp->bass = 32768; + msp->treble = 32768; + msp->input = -1; + msp->muted = 1; i2c_set_clientdata(c, msp); init_waitqueue_head(&msp->wq); @@ -1276,7 +1488,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) dprintk("msp3400: no chip found\n"); return -1; } - + msp->rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e); if (-1 != msp->rev1) msp->rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f); @@ -1297,36 +1509,54 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@', ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f); - if (simple == -1) { - /* default mode */ - msp->simple = HAVE_SIMPLE(msp); - } else { - /* use insmod option */ - msp->simple = simple; + msp->opmode = opmode; + if (OPMODE_AUTO == msp->opmode) { +#if 0 /* seems to work for ivtv only, disable by default for now ... */ + if (HAVE_SIMPLER(msp)) + msp->opmode = OPMODE_SIMPLER; + else +#endif + if (HAVE_SIMPLE(msp)) + msp->opmode = OPMODE_SIMPLE; + else + msp->opmode = OPMODE_MANUAL; } - /* timer for stereo checking */ - init_timer(&msp->wake_stereo); - msp->wake_stereo.function = msp3400c_stereo_wake; - msp->wake_stereo.data = (unsigned long)msp; - /* hello world :-) */ printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c)); if (HAVE_NICAM(msp)) printk(" +nicam"); if (HAVE_SIMPLE(msp)) printk(" +simple"); + if (HAVE_SIMPLER(msp)) + printk(" +simpler"); if (HAVE_RADIO(msp)) printk(" +radio"); + + /* version-specific initialization */ + switch (msp->opmode) { + case OPMODE_MANUAL: + printk(" mode=manual"); + thread_func = msp3400c_thread; + break; + case OPMODE_SIMPLE: + printk(" mode=simple"); + thread_func = msp3410d_thread; + break; + case OPMODE_SIMPLER: + printk(" mode=simpler"); + thread_func = msp34xxg_thread; + break; + } printk("\n"); - /* startup control thread */ - init_completion(&msp->texit); - msp->tpid = kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread, - (void *)c, 0); - if (msp->tpid < 0) - printk(KERN_WARNING "msp34xx: kernel_thread() failed\n"); - wake_up_interruptible(&msp->wq); + /* startup control thread if needed */ + if (thread_func) { + msp->kthread = kthread_run(thread_func, c, "msp34xx"); + if (NULL == msp->kthread) + printk(KERN_WARNING "msp34xx: kernel_thread() failed\n"); + msp_wake_thread(c); + } /* done */ i2c_attach_client(c); @@ -1336,13 +1566,11 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) static int msp_detach(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); - + /* shutdown control thread */ - del_timer_sync(&msp->wake_stereo); - if (msp->tpid >= 0) { - msp->rmmod = 1; - wake_up_interruptible(&msp->wq); - wait_for_completion(&msp->texit); + if (msp->kthread >= 0) { + msp->restart = 1; + kthread_stop(msp->kthread); } msp3400c_reset(client); @@ -1354,18 +1582,8 @@ static int msp_detach(struct i2c_client *client) static int msp_probe(struct i2c_adapter *adap) { -#ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, msp_attach); -#else - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3: - case I2C_ALGO_BIT | I2C_HW_B_BT848: - //case I2C_ALGO_SAA7134: - return i2c_probe(adap, &addr_data, msp_attach); - break; - } -#endif return 0; } @@ -1373,14 +1591,73 @@ static void msp_wake_thread(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); + if (NULL == msp->kthread) + return; msp3400c_setvolume(client,msp->muted,0,0); - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - if (msp->active) - msp->restart = 1; + msp->watch_stereo = 0; + msp->restart = 1; wake_up_interruptible(&msp->wq); } +/* ----------------------------------------------------------------------- */ + +static int mode_v4l2_to_v4l1(int rxsubchans) +{ + int mode = 0; + + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + mode |= VIDEO_SOUND_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + mode |= VIDEO_SOUND_LANG2; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + mode |= VIDEO_SOUND_LANG1; + if (0 == mode) + mode |= VIDEO_SOUND_MONO; + return mode; +} + +static int mode_v4l1_to_v4l2(int mode) +{ + if (mode & VIDEO_SOUND_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (mode & VIDEO_SOUND_LANG2) + return V4L2_TUNER_MODE_LANG2; + if (mode & VIDEO_SOUND_LANG1) + return V4L2_TUNER_MODE_LANG1; + return V4L2_TUNER_MODE_MONO; +} + +static void msp_any_detect_stereo(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + autodetect_stereo(client); + break; + case OPMODE_SIMPLER: + msp34xxg_detect_stereo(client); + break; + } +} + +static void msp_any_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + msp->watch_stereo = 0; + msp3400c_set_audmode(client, audmode); + break; + case OPMODE_SIMPLER: + msp34xxg_set_audmode(client, audmode); + break; + } +} + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1412,7 +1689,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case AUDIO_TUNER: msp->mode = -1; - msp_wake_thread(client); break; default: if (*sarg & AUDIO_MUTE) @@ -1420,63 +1696,38 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } if (scart) { - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); - msp3400c_setstereo(client,msp->stereo); + if (msp->opmode != OPMODE_SIMPLER) + msp3400c_set_audmode(client, msp->audmode); } - if (msp->active) - msp->restart = 1; + msp_wake_thread(client); break; case AUDC_SET_RADIO: dprintk(KERN_DEBUG "msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n"); - if (msp->simple) { - /* the thread will do for us */ - msp_wake_thread(client); - } else { + msp->watch_stereo = 0; + switch (msp->opmode) { + case OPMODE_MANUAL: /* set msp3400 to FM radio mode */ msp3400c_setmode(client,MSP_MODE_FM_RADIO); msp3400c_setcarrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance); + break; + case OPMODE_SIMPLE: + case OPMODE_SIMPLER: + /* the thread will do for us */ + msp_wake_thread(client); + break; } - if (msp->active) - msp->restart = 1; break; -#if 1 - /* work-in-progress: hook to control the DFP registers */ - case MSP_SET_DFPREG: - { - struct msp_dfpreg *r = arg; - unsigned int i; - - if (r->reg < 0 || r->reg >= DFP_COUNT) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(bl_dfp); i++) - if (r->reg == bl_dfp[i]) - return -EINVAL; - msp->dfp_regs[r->reg] = r->value; - msp3400c_write(client,I2C_MSP3400C_DFP,r->reg,r->value); - return 0; - } - case MSP_GET_DFPREG: - { - struct msp_dfpreg *r = arg; - - if (r->reg < 0 || r->reg >= DFP_COUNT) - return -EINVAL; - r->value = msp3400c_read(client,I2C_MSP3400C_DFP,r->reg); - return 0; - } -#endif - /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -1497,10 +1748,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) va->bass = msp->bass; va->treble = msp->treble; - if (msp->norm != VIDEO_MODE_RADIO) { - autodetect_stereo(client); - va->mode = msp->stereo; - } + msp_any_detect_stereo(client); + va->mode = mode_v4l2_to_v4l1(msp->rxsubchans); break; } case VIDIOCSAUDIO: @@ -1519,23 +1768,22 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); - if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) { - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp->stereo = va->mode & 0x0f; - msp3400c_setstereo(client,va->mode & 0x0f); - } + if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) + msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); break; } case VIDIOCSCHAN: { struct video_channel *vc = arg; - + dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; + msp_wake_thread(client); break; } + case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ dprintk(KERN_DEBUG "msp34xx: VIDIOCSFREQ\n"); @@ -1543,6 +1791,39 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } + /* --- v4l2 ioctls --- */ + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *vt = arg; + + msp_any_detect_stereo(client); + vt->audmode = msp->audmode; + vt->rxsubchans = msp->rxsubchans; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1| + V4L2_TUNER_CAP_LANG2; + break; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; + + /* only set audmode */ + if (vt->audmode != -1 && vt->audmode != 0) + msp_any_set_audmode(client, vt->audmode); + break; + } + + /* msp34xx specific */ + case MSP_SET_MATRIX: + { + struct msp_matrix *mspm = arg; + + dprintk(KERN_DEBUG "msp34xx: MSP_SET_MATRIX\n"); + msp3400c_set_scart(client, mspm->input, mspm->output); + break; + } + default: /* nothing */ break; @@ -1550,15 +1831,32 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } -/* ----------------------------------------------------------------------- */ +static int msp_suspend(struct device * dev, u32 state, u32 level) +{ + struct i2c_client *c = container_of(dev, struct i2c_client, dev); -static int msp3400_init_module(void) + dprintk("msp34xx: suspend\n"); + msp3400c_reset(c); + return 0; +} + +static int msp_resume(struct device * dev, u32 level) { - i2c_add_driver(&driver); + struct i2c_client *c = container_of(dev, struct i2c_client, dev); + + dprintk("msp34xx: resume\n"); + msp_wake_thread(c); return 0; } -static void msp3400_cleanup_module(void) +/* ----------------------------------------------------------------------- */ + +static int __init msp3400_init_module(void) +{ + return i2c_add_driver(&driver); +} + +static void __exit msp3400_cleanup_module(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 9673133f2..d70a954e1 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -8,7 +8,29 @@ struct msp_dfpreg { int value; }; +struct msp_matrix { + int input; + int output; +}; + #define MSP_SET_DFPREG _IOW('m',15,struct msp_dfpreg) #define MSP_GET_DFPREG _IOW('m',16,struct msp_dfpreg) +/* ioctl for MSP_SET_MATRIX will have to be registered */ +#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) + +#define SCART_MASK 0 +#define SCART_IN1 1 +#define SCART_IN2 2 +#define SCART_IN1_DA 3 +#define SCART_IN2_DA 4 +#define SCART_IN3 5 +#define SCART_IN4 6 +#define SCART_MONO 7 +#define SCART_MUTE 8 + +#define SCART_DSP_IN 0 +#define SCART1_OUT 1 +#define SCART2_OUT 2 + #endif /* MSP3400_H */ diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 121d626f0..5c785191b 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -1,5 +1,5 @@ /* - mxb.c - v4l2 driver for the Multimedia eXtension Board + mxb - v4l2 driver for the Multimedia eXtension Board Copyright (C) 1998-2003 Michael Hunold @@ -43,12 +43,12 @@ static int mxb_num = 0; in verden (lower saxony, germany) 4148 is a channel called "phoenix" */ static int freq = 4148; -MODULE_PARM(freq,"i"); +module_param(freq, int, 0644); MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup"); static int debug = 0; -MODULE_PARM(debug,"i"); -MODULE_PARM_DESC(debug, "debug verbosity"); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); #define MXB_INPUTS 4 enum { TUNER, AUX1, AUX3, AUX3_YC }; @@ -128,8 +128,8 @@ static struct saa7146_extension_ioctls ioctls[] = { struct mxb { - struct video_device video_dev; - struct video_device vbi_dev; + struct video_device *video_dev; + struct video_device *vbi_dev; struct i2c_adapter i2c_adapter; @@ -183,7 +183,12 @@ static int mxb_probe(struct saa7146_dev* dev) } memset(mxb, 0x0, sizeof(struct mxb)); - saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); + mxb->i2c_adapter = (struct i2c_adapter) { + .class = I2C_CLASS_TV_ANALOG, + .name = "mxb", + }; + + saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(mxb); diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index d88956a26..67f2fc4a4 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "ovcamchip_priv.h" #define DRIVER_VERSION "v2.27 for Linux 2.6" @@ -128,8 +129,7 @@ static int init_camchip(struct i2c_client *c) ov_write(c, 0x12, 0x80); /* Wait for it to initialize */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1 + 150 * HZ / 1000); + msleep(150); for (i = 0, success = 0; i < I2C_DETECT_RETRIES && !success; i++) { if (ov_read(c, GENERIC_REG_ID_HIGH, &high) >= 0) { @@ -145,8 +145,7 @@ static int init_camchip(struct i2c_client *c) ov_write(c, 0x12, 0x80); /* Wait for it to initialize */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1 + 150 * HZ / 1000); + msleep(150); /* Dummy read to sync I2C */ ov_read(c, 0x00, &low); diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index ebf130f16..10eb49b5b 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -178,8 +178,7 @@ static unsigned char saa_status(int byte, struct planb *pb) saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]); /* Let's wait 30msec for this one */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(30 * HZ / 1000); + msleep_interruptible(30); return (unsigned char)in_8 (&planb_regs->saa_status); } @@ -1996,8 +1995,10 @@ static int planb_mmap(struct vm_area_struct *vma, struct video_device *dev, cons return err; } for (i = 0; i < pb->rawbuf_size; i++) { - if (remap_page_range(vma, start, virt_to_phys((void *)pb->rawbuf[i]), - PAGE_SIZE, PAGE_SHARED)) + unsigned long pfn; + + pfn = virt_to_phys((void *)pb->rawbuf[i]) >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; if (size <= PAGE_SIZE) diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index d127e291f..3ad4bddd7 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -68,6 +68,7 @@ static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */ static int io_port = 0x250; static int data_port = 0x251; static int mem_base = 0xC8000; +static void __iomem *mem; static int video_nr = -1; @@ -629,7 +630,6 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int { int y; int dw = 2*dev->width; - u32 src = mem_base; char tmp[dw+32]; /* using a temp buffer is faster than direct */ int cnt = 0; @@ -644,14 +644,14 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int for (y = 0; y < dev->height; y++ ) { - isa_writeb(0, src); /* synchronisiert neue Zeile */ + writeb(0, mem); /* synchronisiert neue Zeile */ /* * This is in truth a fifo, be very careful as if you * forgot this odd things will occur 8) */ - isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word */ + memcpy_fromio(tmp, mem, dw+32); /* discard 16 word */ cnt -= dev->height; while (cnt <= 0) { @@ -865,7 +865,7 @@ static int pms_ioctl(struct inode *inode, struct file *file, return video_usercopy(inode, file, cmd, arg, pms_do_ioctl); } -static int pms_read(struct file *file, char __user *buf, +static ssize_t pms_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *v = video_devdata(file); @@ -918,16 +918,22 @@ static int init_mediavision(void) 0x34,0x0A,0xF4,0xCE, 0xE4 }; + + mem = ioremap(mem_base, 0x800); + if (!mem) + return -ENOMEM; if (!request_region(0x9A01, 1, "Mediavision PMS config")) { printk(KERN_WARNING "mediavision: unable to detect: 0x9A01 in use.\n"); + iounmap(mem); return -EBUSY; } if (!request_region(io_port, 3, "Mediavision PMS")) { printk(KERN_WARNING "mediavision: I/O port %d in use.\n", io_port); release_region(0x9A01, 1); + iounmap(mem); return -EBUSY; } outb(0xB8, 0x9A01); /* Unlock */ @@ -950,6 +956,7 @@ static int init_mediavision(void) if(idec == 0) { release_region(io_port, 3); release_region(0x9A01, 1); + iounmap(mem); return -ENODEV; } @@ -1045,6 +1052,7 @@ static void __exit cleanup_pms_module(void) { shutdown_mediavision(); video_unregister_device((struct video_device *)&pms_device); + iounmap(mem); } module_init(init_pms_cards); diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index d486fb7fa..7d5ca87c1 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -273,8 +273,7 @@ static void jdelay(unsigned long delay) sigfillset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(delay); + msleep_interruptible(jiffies_to_msecs(delay)); spin_lock_irq(¤t->sighand->siglock); current->blocked = oldblocked; diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 5202dcc5a..cb53427d3 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -60,7 +60,7 @@ MODULE_LICENSE("GPL"); #include static int debug = 0; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define dprintk(num, format, args...) \ @@ -342,7 +342,7 @@ saa7111_command (struct i2c_client *client, case VIDEO_MODE_SECAM: saa7111_write(client, 0x08, - (decoder->reg[0x0e] & 0x3f) | 0x00); + (decoder->reg[0x08] & 0x3f) | 0x00); saa7111_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f) | 0x50); break; diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 95f8938c5..25028cead 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -3,6 +3,8 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ saa7134-vbi.o saa7134-video.o saa7134-input.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa6752hs.o +obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o saa6752hs.o +obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o -EXTRA_CFLAGS = -I$(src)/.. +EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 3343e4133..5fdff4829 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -36,7 +36,7 @@ enum saa6752hs_command { SAA6752HS_COMMAND_RECONFIGURE = 4, SAA6752HS_COMMAND_SLEEP = 5, SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6, - + SAA6752HS_COMMAND_MAX }; @@ -46,24 +46,24 @@ enum saa6752hs_command { static u8 PAT[] = { 0xc2, // i2c register 0x00, // table number for encoder - + 0x47, // sync 0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) 0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) - + 0x00, // PSI pointer to start of table - + 0x00, // tid(0) 0xb0, 0x0d, // section_syntax_indicator(1), section_length(13) - + 0x00, 0x01, // transport_stream_id(1) - + 0xc1, // version_number(0), current_next_indicator(1) - + 0x00, 0x00, // section_number(0), last_section_number(0) 0x00, 0x01, // program_number(1) - + 0xe0, 0x10, // PMT PID(0x10) 0x76, 0xf1, 0x44, 0xd1 // CRC32 @@ -72,29 +72,29 @@ static u8 PAT[] = { static u8 PMT[] = { 0xc2, // i2c register 0x01, // table number for encoder - + 0x47, // sync 0x40, 0x10, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0x10) 0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) - + 0x00, // PSI pointer to start of table - + 0x02, // tid(2) 0xb0, 0x17, // section_syntax_indicator(1), section_length(23) 0x00, 0x01, // program_number(1) - + 0xc1, // version_number(0), current_next_indicator(1) - + 0x00, 0x00, // section_number(0), last_section_number(0) - + 0xe1, 0x04, // PCR_PID (0x104) - + 0xf0, 0x00, // program_info_length(0) - + 0x02, 0xe1, 0x00, 0xf0, 0x00, // video stream type(2), pid(0x100) 0x04, 0xe1, 0x03, 0xf0, 0x00, // audio stream type(4), pid(0x103) - + 0xa1, 0xca, 0x0f, 0x82 // CRC32 }; @@ -106,7 +106,7 @@ static struct mpeg_params mpeg_params_template = .total_bitrate = 6000, }; - + /* ---------------------------------------------------------------------- */ @@ -122,11 +122,11 @@ static int saa6752hs_chip_command(struct i2c_client* client, case SAA6752HS_COMMAND_RESET: buf[0] = 0x00; break; - + case SAA6752HS_COMMAND_STOP: buf[0] = 0x03; break; - + case SAA6752HS_COMMAND_START: buf[0] = 0x02; break; @@ -134,11 +134,11 @@ static int saa6752hs_chip_command(struct i2c_client* client, case SAA6752HS_COMMAND_PAUSE: buf[0] = 0x04; break; - + case SAA6752HS_COMMAND_RECONFIGURE: buf[0] = 0x05; break; - + case SAA6752HS_COMMAND_SLEEP: buf[0] = 0x06; break; @@ -146,11 +146,11 @@ static int saa6752hs_chip_command(struct i2c_client* client, case SAA6752HS_COMMAND_RECONFIGURE_FORCE: buf[0] = 0x07; break; - + default: - return -EINVAL; + return -EINVAL; } - + // set it and wait for it to be so i2c_master_send(client, buf, 1); timeout = jiffies + HZ * 3; @@ -166,16 +166,14 @@ static int saa6752hs_chip_command(struct i2c_client* client, status = -ETIMEDOUT; break; } - + // wait a bit - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); } // delay a bit to let encoder settle - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/20); - + msleep(50); + // done return status; } @@ -185,12 +183,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, struct mpeg_params* params) { u8 buf[3]; - + // set the bitrate mode buf[0] = 0x71; buf[1] = params->bitrate_mode; i2c_master_send(client, buf, 2); - + // set the video bitrate if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR) { // set the target bitrate @@ -211,24 +209,24 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, buf[2] = params->video_target_bitrate & 0xff; i2c_master_send(client, buf, 3); } - + // set the audio bitrate buf[0] = 0x94; buf[1] = params->audio_bitrate; i2c_master_send(client, buf, 2); - + // set the total bitrate buf[0] = 0xb1; buf[1] = params->total_bitrate >> 8; buf[2] = params->total_bitrate & 0xff; i2c_master_send(client, buf, 3); - + return 0; } static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params) -{ +{ unsigned char buf[3]; void *data; @@ -246,41 +244,41 @@ static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params) return -EINVAL; if (params->bitrate_mode == MPEG_BITRATE_MODE_MAX && params->video_target_bitrate <= params->video_max_bitrate) - return -EINVAL; + return -EINVAL; } - + // Set GOP structure {3, 13} buf[0] = 0x72; buf[1] = 0x03; buf[2] = 0x0D; i2c_master_send(client,buf,3); - + // Set minimum Q-scale {4} buf[0] = 0x82; buf[1] = 0x04; i2c_master_send(client,buf,2); - + // Set maximum Q-scale {12} buf[0] = 0x83; buf[1] = 0x0C; i2c_master_send(client,buf,2); - + // Set Output Protocol buf[0] = 0xD0; buf[1] = 0x01; i2c_master_send(client,buf,2); - + // Set video output stream format {TS} buf[0] = 0xB0; buf[1] = 0x05; i2c_master_send(client,buf,2); - + // Set Audio PID {0x103} buf[0] = 0xC1; buf[1] = 0x01; buf[2] = 0x03; i2c_master_send(client,buf,3); - + // setup bitrate settings data = i2c_get_clientdata(client); if (params) { @@ -290,18 +288,18 @@ static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params) // parameters were not supplied. use the previous set saa6752hs_set_bitrate(client, (struct mpeg_params*) data); } - + // Send SI tables i2c_master_send(client,PAT,sizeof(PAT)); i2c_master_send(client,PMT,sizeof(PMT)); - + // mute then unmute audio. This removes buzzing artefacts buf[0] = 0xa4; buf[1] = 1; i2c_master_send(client, buf, 2); buf[1] = 0; i2c_master_send(client, buf, 2); - + // start it going saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); @@ -322,14 +320,14 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; memcpy(client,&client_template,sizeof(struct i2c_client)); strlcpy(client->name, "saa6752hs", sizeof(client->name)); - + if (NULL == (params = kmalloc(sizeof(struct mpeg_params), GFP_KERNEL))) return -ENOMEM; memcpy(params,&mpeg_params_template,sizeof(struct mpeg_params)); i2c_set_clientdata(client, params); i2c_attach_client(client); - + return 0; } @@ -364,7 +362,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) /* nothing */ break; } - + return 0; } @@ -387,13 +385,12 @@ static struct i2c_client client_template = .driver = &driver, }; -static int saa6752hs_init_module(void) +static int __init saa6752hs_init_module(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void saa6752hs_cleanup_module(void) +static void __exit saa6752hs_cleanup_module(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 5bb99d716..53bce030f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-cards.c,v 1.35 2004/11/07 14:44:59 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * card-specific stuff. * @@ -154,6 +156,26 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x8000, }, }, + [SAA7134_BOARD_FLYTVPLATINUM] = { + /* "Arnaud Quette" */ + .name = "LifeView FlyTV Platinum", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_SECAM, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + }, [SAA7134_BOARD_EMPRESS] = { /* "Gert Vervoort" */ .name = "EMPRESS", @@ -177,8 +199,7 @@ struct saa7134_board saa7134_boards[] = { .name = name_radio, .amux = LINE2, }, - .i2s_rate = 48000, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_MONSTERTV] = { @@ -243,7 +264,7 @@ struct saa7134_board saa7134_boards[] = { .name = "KNC One TV-Station RDS / Typhoon TV Tuner RDS", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -278,7 +299,7 @@ struct saa7134_board saa7134_boards[] = { .name = "KNC One TV-Station DVR", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x820000, .inputs = {{ .name = name_tv, @@ -302,8 +323,7 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, .gpio = 0x20000, }, - .i2s_rate = 48000, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_CINERGY400] = { @@ -333,7 +353,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Medion 5044", .audio_clock = 0x00187de7, // was: 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -386,6 +406,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Terratec Cinergy 600 TV", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -414,7 +435,7 @@ struct saa7134_board saa7134_boards[] = { //.audio_clock = 0x00200000, .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -440,7 +461,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Typhoon TV+Radio 90031", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -503,7 +524,7 @@ struct saa7134_board saa7134_boards[] = { .name = "ASUS TV-FM 7134", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -607,8 +628,7 @@ struct saa7134_board saa7134_boards[] = { .vmux = 8, .amux = LINE1, }}, - .i2s_rate = 48000, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_VIDEOMATE_TV] = { @@ -630,6 +650,29 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }}, }, + [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = { + .name = "Compro VideoMate TV Gold+", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .gpiomask = 0x800c0000, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x06c00012, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x0ac20012, + },{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .gpio = 0x08c20012, + .tv = 1, + }}, + }, [SAA7134_BOARD_CRONOS_PLUS] = { /* gpio pins: 0 .. 3 BASE_ID @@ -666,7 +709,7 @@ struct saa7134_board saa7134_boards[] = { .name = "AverMedia M156 / Medion 2819", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -709,8 +752,7 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, .tv = 1, }}, - .i2s_rate = 48000, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_ASUSTEK_TVFM7133] = { @@ -719,7 +761,7 @@ struct saa7134_board saa7134_boards[] = { // probably wrong, the 7133 one is the NTSC version ... // .tuner_type = TUNER_PHILIPS_FM1236_MK3 .tuner_type = TUNER_LG_NTSC_NEW_TAPC, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -743,7 +785,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Pinnacle PCTV Stereo (saa7134)", .audio_clock = 0x00187de7, .tuner_type = TUNER_MT2032, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, .inputs = {{ .name = name_tv, .vmux = 3, @@ -796,7 +838,7 @@ struct saa7134_board saa7134_boards[] = { .name = name_svideo, .vmux = 8, .amux = LINE1, - },{ + },{ .name = name_comp1, .vmux = 1, .amux = LINE1, @@ -957,7 +999,7 @@ struct saa7134_board saa7134_boards[] = { .name = "AverMedia 305", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 1, @@ -989,7 +1031,7 @@ struct saa7134_board saa7134_boards[] = { .name = "UPMOST PURPLE TV", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .need_tda9887 = 1, + .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, .vmux = 7, @@ -1000,7 +1042,7 @@ struct saa7134_board saa7134_boards[] = { .vmux = 7, .amux = LINE1, }}, - }, + }, [SAA7134_BOARD_ITEMS_MTV005] = { /* Norman Jonas */ .name = "Items MuchTV Plus / IT-005", @@ -1025,6 +1067,217 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_CINERGY200] = { + .name = "Terratec Cinergy 200 TV", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_PAL, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 4, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp2, // CVideo over SVideo Connector + .vmux = 0, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_VIDEOMATE_TV_PVR] = { + /* Alain St-Denis */ + .name = "Compro VideoMate TV PVR/FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .gpiomask = 0x808c0080, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00080 + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00080 + },{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + .gpio = 0x00080 + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x80000 + }, + .mute = { + .name = name_mute, + .amux = LINE2, + .gpio = 0x40000, + }, + }, + [SAA7134_BOARD_SABRENT_SBTTVFM] = { + /* Michael Rodriguez-Torrent */ + .name = "Sabrent SBT-TVFM (saa7130)", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, + [SAA7134_BOARD_ZOLID_XPERT_TV7134] = { + /* Helge Jensen */ + .name = ":Zolid Xpert TV7134", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_NTSC, + .inputs = {{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + }}, + }, + [SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = { + /* "Matteo Az" ;-) */ + .name = "Empire PCI TV-Radio LE", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_PAL, + .gpiomask = 0x4000, + .inputs = {{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x8000, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x8000, + },{ + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + .gpio = 0x8000, + }}, + .radio = { + .name = name_radio, + .amux = LINE1, + .gpio = 0x8000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio =0x8000, + } + }, + [SAA7134_BOARD_AVERMEDIA_307] = { + /* Nickolay V. Shmyrev */ + .name = "Avermedia AVerTV Studio 307", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + },{ + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS] = { + /* Jon Westgate */ + .name = "AVerMedia Cardbus TV/Radio", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_PAL, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, + [SAA7134_BOARD_CINERGY400_CARDBUS] = { + .name = "Terratec Cinergy 400 mobile", + .audio_clock = 0x187de7, + .tuner_type = UNSET /* not supported yet :/ */, + .inputs = {{ + .name = name_tv, + .vmux = 5, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 4, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -1068,6 +1321,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x153B, .subdevice = 0x1143, .driver_data = SAA7134_BOARD_CINERGY600, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x153b, + .subdevice = 0x1162, + .driver_data = SAA7134_BOARD_CINERGY400_CARDBUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -1086,6 +1345,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0138, .driver_data = SAA7134_BOARD_FLYVIDEO2000, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7135, + .subvendor = 0x5168, + .subdevice = 0x0212, + .driver_data = SAA7134_BOARD_FLYTVPLATINUM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -1164,6 +1429,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x185b, .subdevice = 0xc100, .driver_data = SAA7134_BOARD_VIDEOMATE_TV, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x185b, + .subdevice = 0xc100, + .driver_data = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -1189,6 +1460,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x10ff, .driver_data = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER, },{ + /* AVerMedia CardBus */ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xd6ee, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS, + },{ /* TransGear 3000TV */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -1201,6 +1479,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x11bd, .subdevice = 0x002b, .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x11bd, + .subdevice = 0x002d, /* 300i DVB-T + PAL */ + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -1219,7 +1503,27 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x12ab, .subdevice = 0x0800, .driver_data = SAA7133_BOARD_UPMOST_PURPLE_TV, - + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x153B, + .subdevice = 0x1152, + .driver_data = SAA7134_BOARD_CINERGY200, + + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x185b, + .subdevice = 0xc100, + .driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR, + + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0x9715, + .driver_data = SAA7134_BOARD_AVERMEDIA_307, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -1234,7 +1538,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0, .driver_data = SAA7134_BOARD_NOAUTO, },{ - + /* --- default catch --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, @@ -1297,6 +1601,7 @@ static struct { static void board_flyvideo(struct saa7134_dev *dev) { #if 0 + /* non-working attempt to detect the correct tuner type ... */ u32 value; int index; @@ -1307,11 +1612,15 @@ static void board_flyvideo(struct saa7134_dev *dev) fly_list[index].tuner_type); dev->tuner_type = fly_list[index].tuner_type; #endif + printk("%s: there are different flyvideo cards with different tuners\n" + "%s: out there, you might have to use the tuner= insmod\n" + "%s: option to override the default value.\n", + dev->name, dev->name, dev->name); } /* ----------------------------------------------------------- */ -int saa7134_board_init(struct saa7134_dev *dev) +int saa7134_board_init1(struct saa7134_dev *dev) { // Always print gpio, often manufacturers encode tuner type and other info. saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0); @@ -1321,18 +1630,58 @@ int saa7134_board_init(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - board_flyvideo(dev); dev->has_remote = 1; + /* fall throuth */ + case SAA7134_BOARD_FLYTVPLATINUM: + board_flyvideo(dev); break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: + case SAA7134_BOARD_MD2819: + case SAA7134_BOARD_AVERMEDIA_307: dev->has_remote = 1; break; case SAA7134_BOARD_AVACSSMARTTV: dev->has_remote = 1; break; + case SAA7134_BOARD_MD5044: + printk("%s: seems there are two different versions of the MD5044\n" + "%s: (with the same ID) out there. If sound doesn't work for\n" + "%s: you try the audio_clock_override=0x200000 insmod option.\n", + dev->name,dev->name,dev->name); + break; + case SAA7134_BOARD_CINERGY400_CARDBUS: + /* power-up tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); + break; + } + return 0; +} + +/* stuff which needs working i2c */ +int saa7134_board_init2(struct saa7134_dev *dev) +{ + unsigned char buf; + int board; + + switch (dev->board) { + case SAA7134_BOARD_BMK_MPEX_NOTUNER: + case SAA7134_BOARD_BMK_MPEX_TUNER: + dev->i2c_client.addr = 0x60; + board = (i2c_master_recv(&dev->i2c_client,&buf,0) < 0) + ? SAA7134_BOARD_BMK_MPEX_NOTUNER + : SAA7134_BOARD_BMK_MPEX_TUNER; + if (board == dev->board) + break; + printk("%s: board type fixup: %s\n", dev->name, + saa7134_boards[dev->board].name); + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + if (TUNER_ABSENT != dev->tuner_type) + saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&dev->tuner_type); + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index cf87dda32..10699b490 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-core.c,v 1.15 2004/11/07 14:44:59 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * driver core * @@ -27,6 +29,7 @@ #include #include #include +#include #include "saa7134-reg.h" #include "saa7134.h" @@ -35,64 +38,56 @@ MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -#define SAA7134_MAXBOARDS 8 - /* ------------------------------------------------------------------ */ static unsigned int irq_debug = 0; -MODULE_PARM(irq_debug,"i"); +module_param(irq_debug, int, 0644); MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); static unsigned int core_debug = 0; -MODULE_PARM(core_debug,"i"); +module_param(core_debug, int, 0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); static unsigned int gpio_tracking = 0; -MODULE_PARM(gpio_tracking,"i"); +module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(video_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(video_nr,"video device number"); - -static unsigned int ts_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(ts_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(ts_nr,"ts device number"); - -static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(vbi_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(vbi_nr,"vbi device number"); - -static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(radio_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(radio_nr,"radio device number"); - static unsigned int oss = 0; -MODULE_PARM(oss,"i"); +module_param(oss, int, 0444); MODULE_PARM_DESC(oss,"register oss devices (default: no)"); -static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(dsp_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(dsp_nr,"oss dsp device number"); - -static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(mixer_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(mixer_nr,"oss mixer device number"); - -static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(tuner,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(tuner,"tuner type"); - -static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(card,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(card,"card type"); - static unsigned int latency = UNSET; -MODULE_PARM(latency,"i"); +module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); -struct list_head saa7134_devlist; -unsigned int saa7134_devcount; +static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; + +module_param_array(video_nr, int, NULL, 0444); +module_param_array(vbi_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); +module_param_array(dsp_nr, int, NULL, 0444); +module_param_array(mixer_nr, int, NULL, 0444); +module_param_array(tuner, int, NULL, 0444); +module_param_array(card, int, NULL, 0444); + +MODULE_PARM_DESC(video_nr, "video device number"); +MODULE_PARM_DESC(vbi_nr, "vbi device number"); +MODULE_PARM_DESC(radio_nr, "radio device number"); +MODULE_PARM_DESC(dsp_nr, "oss dsp device number"); +MODULE_PARM_DESC(mixer_nr, "oss mixer device number"); +MODULE_PARM_DESC(tuner, "tuner type"); +MODULE_PARM_DESC(card, "card type"); + +static DECLARE_MUTEX(devlist_lock); +LIST_HEAD(saa7134_devlist); +static LIST_HEAD(mops_list); +unsigned int saa7134_devcount; #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) @@ -243,7 +238,7 @@ int saa7134_buffer_pages(int size) int saa7134_buffer_count(unsigned int size, unsigned int count) { unsigned int maxcount; - + maxcount = 1024 / saa7134_buffer_pages(size); if (count > maxcount) count = maxcount; @@ -270,7 +265,7 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) { u32 *cpu; dma_addr_t dma_addr; - + cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); if (NULL == cpu) return -ENOMEM; @@ -327,7 +322,7 @@ int saa7134_buffer_queue(struct saa7134_dev *dev, #ifdef DEBUG_SPINLOCKS BUG_ON(!spin_is_locked(&dev->slock)); #endif - + dprintk("buffer_queue %p\n",buf); if (NULL == q->curr) { if (!q->need_two) { @@ -357,7 +352,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, BUG_ON(!spin_is_locked(&dev->slock)); #endif dprintk("buffer_finish %p\n",q->curr); - + /* finish current buffer */ q->curr->vb.state = state; do_gettimeofday(&q->curr->vb.ts); @@ -480,7 +475,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; } - + /* set task conditions + field handling */ if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) { /* default config -- use full frames */ @@ -504,7 +499,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x01); split = 1; } - + /* irqs */ saa_writeb(SAA7134_REGION_ENABLE, task); saa_writel(SAA7134_IRQ1, irq); @@ -538,7 +533,7 @@ static void print_irqstatus(struct saa7134_dev *dev, int loop, unsigned long report, unsigned long status) { unsigned int i; - + printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx", dev->name,loop,jiffies,report,status); for (i = 0; i < IRQBITS; i++) { @@ -593,7 +588,7 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) saa7134_irq_vbi_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA2) && - card_has_ts(dev)) + card_has_mpeg(dev)) saa7134_irq_ts_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) @@ -640,7 +635,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa7134_track_gpio(dev,"pre-init"); saa7134_video_init1(dev); saa7134_vbi_init1(dev); - if (card_has_ts(dev)) + if (card_has_mpeg(dev)) saa7134_ts_init1(dev); saa7134_input_init1(dev); @@ -651,11 +646,11 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa7134_oss_init1(dev); break; } - + /* RAM FIFO config */ saa_writel(SAA7134_FIFO_SIZE, 0x08070503); saa_writel(SAA7134_THRESHOULD,0x02020202); - + /* enable audio + video processing */ saa_writel(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_VPLLE | @@ -672,7 +667,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) /* set vertical line numbering start (vbi needs this) */ saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); - + return 0; } @@ -716,7 +711,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev) saa7134_oss_fini(dev); break; } - if (card_has_ts(dev)) + if (card_has_mpeg(dev)) saa7134_ts_fini(dev); saa7134_input_fini(dev); saa7134_vbi_fini(dev); @@ -757,7 +752,7 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, char *type) { struct video_device *vfd; - + vfd = video_device_alloc(); if (NULL == vfd) return NULL; @@ -779,13 +774,6 @@ static void saa7134_unregister_video(struct saa7134_dev *dev) video_device_release(dev->video_dev); dev->video_dev = NULL; } - if (dev->ts_dev) { - if (-1 != dev->ts_dev->minor) - video_unregister_device(dev->ts_dev); - else - video_device_release(dev->ts_dev); - dev->ts_dev = NULL; - } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); @@ -802,10 +790,38 @@ static void saa7134_unregister_video(struct saa7134_dev *dev) } } +static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + int err; + + if (NULL != dev->mops) + return; + if (saa7134_boards[dev->board].mpeg != ops->type) + return; + err = ops->init(dev); + if (0 != err) + return; + dev->mops = ops; +} + +static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + if (NULL == dev->mops) + return; + if (dev->mops != ops) + return; + dev->mops->fini(dev); + dev->mops = NULL; +} + static int __devinit saa7134_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct saa7134_dev *dev; + struct list_head *item; + struct saa7134_mpeg_ops *mops; int err; dev = kmalloc(sizeof(*dev),GFP_KERNEL); @@ -819,7 +835,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, err = -EIO; goto fail1; } - sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount); + + dev->nr = saa7134_devcount; + sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr); /* pci quirks */ if (pci_pci_problems) { @@ -861,20 +879,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* board config */ dev->board = pci_id->driver_data; - if (card[saa7134_devcount] >= 0 && - card[saa7134_devcount] < saa7134_bcount) - dev->board = card[saa7134_devcount]; + if (card[dev->nr] >= 0 && + card[dev->nr] < saa7134_bcount) + dev->board = card[dev->nr]; if (SAA7134_BOARD_NOAUTO == dev->board) { must_configure_manually(); dev->board = SAA7134_BOARD_UNKNOWN; } - dev->tuner_type = saa7134_boards[dev->board].tuner_type; - if (UNSET != tuner[saa7134_devcount]) - dev->tuner_type = tuner[saa7134_devcount]; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; + if (UNSET != tuner[dev->nr]) + dev->tuner_type = tuner[dev->nr]; printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, - dev->board, card[saa7134_devcount] == dev->board ? + dev->board, card[dev->nr] == dev->board ? "insmod option" : "autodetected"); /* get mmio */ @@ -887,7 +906,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, goto fail1; } dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000); - dev->bmmio = (__u8*)dev->lmmio; + dev->bmmio = (__u8 __iomem *)dev->lmmio; if (NULL == dev->lmmio) { err = -EIO; printk(KERN_ERR "%s: can't ioremap() MMIO memory\n", @@ -896,7 +915,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } /* initialize hardware #1 */ - saa7134_board_init(dev); + saa7134_board_init1(dev); saa7134_hwinit1(dev); /* get irq */ @@ -909,29 +928,31 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } /* wait a bit, register i2c bus */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); saa7134_i2c_register(dev); /* initialize hardware #2 */ + saa7134_board_init2(dev); saa7134_hwinit2(dev); /* load i2c helpers */ if (TUNER_ABSENT != dev->tuner_type) request_module("tuner"); - if (saa7134_boards[dev->board].need_tda9887) + if (dev->tda9887_conf) request_module("tda9887"); - if (card_has_ts(dev)) + if (card_is_empress(dev)) { + request_module("saa7134-empress"); request_module("saa6752hs"); + } + if (card_is_dvb(dev)) + request_module("saa7134-dvb"); -#ifdef VIDIOC_G_PRIORITY v4l2_prio_init(&dev->prio); -#endif /* register v4l devices */ dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, - video_nr[saa7134_devcount]); + video_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s: can't register video device\n", dev->name); @@ -940,22 +961,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev->minor & 0x1f); - if (card_has_ts(dev)) { - dev->ts_dev = vdev_init(dev,&saa7134_ts_template,"ts"); - err = video_register_device(dev->ts_dev,VFL_TYPE_GRABBER, - ts_nr[saa7134_devcount]); - if (err < 0) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - goto fail4; - } - printk(KERN_INFO "%s: registered device video%d [ts]\n", - dev->name,dev->ts_dev->minor & 0x1f); - } - dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, - vbi_nr[saa7134_devcount]); + vbi_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device vbi%d\n", @@ -964,7 +972,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (card_has_radio(dev)) { dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, - radio_nr[saa7134_devcount]); + radio_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device radio%d\n", @@ -979,16 +987,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (oss) { err = dev->oss.minor_dsp = register_sound_dsp(&saa7134_dsp_fops, - dsp_nr[saa7134_devcount]); + dsp_nr[dev->nr]); if (err < 0) { goto fail4; } printk(KERN_INFO "%s: registered device dsp%d\n", dev->name,dev->oss.minor_dsp >> 4); - + err = dev->oss.minor_mixer = register_sound_mixer(&saa7134_mixer_fops, - mixer_nr[saa7134_devcount]); + mixer_nr[dev->nr]); if (err < 0) goto fail5; printk(KERN_INFO "%s: registered device mixer%d\n", @@ -998,9 +1006,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } /* everything worked */ - list_add_tail(&dev->devlist,&saa7134_devlist); pci_set_drvdata(pci_dev,dev); saa7134_devcount++; + + down(&devlist_lock); + list_for_each(item,&mops_list) { + mops = list_entry(item, struct saa7134_mpeg_ops, next); + mpeg_ops_attach(mops, dev); + } + list_add_tail(&dev->devlist,&saa7134_devlist); + up(&devlist_lock); return 0; fail5: @@ -1030,6 +1045,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct list_head *item; + struct saa7134_mpeg_ops *mops; /* debugging ... */ if (irq_debug) { @@ -1050,6 +1067,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_hwfini(dev); /* unregister */ + down(&devlist_lock); + list_del(&dev->devlist); + list_for_each(item,&mops_list) { + mops = list_entry(item, struct saa7134_mpeg_ops, next); + mpeg_ops_detach(mops, dev); + } + up(&devlist_lock); + saa7134_devcount--; + saa7134_i2c_unregister(dev); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: @@ -1075,16 +1101,50 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); /* free memory */ - list_del(&dev->devlist); - saa7134_devcount--; kfree(dev); } +/* ----------------------------------------------------------- */ + +int saa7134_ts_register(struct saa7134_mpeg_ops *ops) +{ + struct list_head *item; + struct saa7134_dev *dev; + + down(&devlist_lock); + list_for_each(item,&saa7134_devlist) { + dev = list_entry(item, struct saa7134_dev, devlist); + mpeg_ops_attach(ops, dev); + } + list_add_tail(&ops->next,&mops_list); + up(&devlist_lock); + return 0; +} + +void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) +{ + struct list_head *item; + struct saa7134_dev *dev; + + down(&devlist_lock); + list_del(&ops->next); + list_for_each(item,&saa7134_devlist) { + dev = list_entry(item, struct saa7134_dev, devlist); + mpeg_ops_detach(ops, dev); + } + up(&devlist_lock); +} + +EXPORT_SYMBOL(saa7134_ts_register); +EXPORT_SYMBOL(saa7134_ts_unregister); + +/* ----------------------------------------------------------- */ + static struct pci_driver saa7134_pci_driver = { .name = "saa7134", .id_table = saa7134_pci_tbl, .probe = saa7134_initdev, - .remove = saa7134_finidev, + .remove = __devexit_p(saa7134_finidev), }; static int saa7134_init(void) @@ -1109,6 +1169,13 @@ static void saa7134_fini(void) module_init(saa7134_init); module_exit(saa7134_fini); +/* ----------------------------------------------------------- */ + +EXPORT_SYMBOL(saa7134_print_ioctl); +EXPORT_SYMBOL(saa7134_i2c_call_clients); +EXPORT_SYMBOL(saa7134_devlist); +EXPORT_SYMBOL(saa7134_boards); + /* ----------------------------------------------------------- */ /* * Local variables: diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 61305cf18..fa6cfbb90 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-i2c.c,v 1.7 2004/11/07 13:17:15 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * i2c interface support * @@ -32,11 +34,11 @@ /* ----------------------------------------------------------- */ static unsigned int i2c_debug = 0; -MODULE_PARM(i2c_debug,"i"); +module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]"); static unsigned int i2c_scan = 0; -MODULE_PARM(i2c_scan,"i"); +module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); #define d1printk if (1 == i2c_debug) printk @@ -86,7 +88,7 @@ enum i2c_attr { static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev) { enum i2c_status status; - + status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f; d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name, str_i2c_status[status]); @@ -182,7 +184,7 @@ static int i2c_reset(struct saa7134_dev *dev) if (!i2c_is_idle(status)) return FALSE; - + i2c_set_attr(dev,NOP); return TRUE; } @@ -208,7 +210,7 @@ static inline int i2c_send_byte(struct saa7134_dev *dev, saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword); #endif d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data); - + if (!i2c_is_busy_wait(dev)) return -EIO; status = i2c_get_status(dev); @@ -221,7 +223,7 @@ static inline int i2c_recv_byte(struct saa7134_dev *dev) { enum i2c_status status; unsigned char data; - + i2c_set_attr(dev,CONTINUE); if (!i2c_is_busy_wait(dev)) return -EIO; @@ -300,7 +302,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, /* ----------------------------------------------------------- */ -static int algo_control(struct i2c_adapter *adapter, +static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) { return 0; @@ -327,8 +329,10 @@ static int attach_inform(struct i2c_client *client) { struct saa7134_dev *dev = client->adapter->algo_data; int tuner = dev->tuner_type; + int conf = dev->tda9887_conf; saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner); + saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&conf); return 0; } @@ -391,21 +395,26 @@ saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len) return 0; } -static int -saa7134_i2c_scan(struct saa7134_dev *dev) +static char *i2c_devs[128] = { + [ 0x20 ] = "mpeg encoder (saa6752hs)", + [ 0xa0 >> 1 ] = "eeprom", + [ 0xc0 >> 1 ] = "tuner (analog)", + [ 0x86 >> 1 ] = "tda9887", +}; + +static void do_i2c_scan(char *name, struct i2c_client *c) { unsigned char buf; int i,rc; - for (i = 0; i < 256; i+= 2) { - dev->i2c_client.addr = i >> 1; - rc = i2c_master_recv(&dev->i2c_client,&buf,0); + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c,&buf,0); if (rc < 0) continue; - printk("%s: i2c scan: found device @ %x%s\n", - dev->name, i, (i == 0xa0) ? " [eeprom]" : ""); + printk("%s: i2c scan: found device @ 0x%x [%s]\n", + name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); } - return 0; } void saa7134_i2c_call_clients(struct saa7134_dev *dev, @@ -422,13 +431,13 @@ int saa7134_i2c_register(struct saa7134_dev *dev) strcpy(dev->i2c_adap.name,dev->name); dev->i2c_adap.algo_data = dev; i2c_add_adapter(&dev->i2c_adap); - + dev->i2c_client = saa7134_client_template; dev->i2c_client.adapter = &dev->i2c_adap; - + saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata)); if (i2c_scan) - saa7134_i2c_scan(dev); + do_i2c_scan(dev->name,&dev->i2c_client); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index a34447d6b..a732935d8 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-input.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $ + * * handle saa7134 IR remotes via linux kernel input layer. * * This program is free software; you can redistribute it and/or modify @@ -28,11 +30,11 @@ #include "saa7134.h" static unsigned int disable_ir = 0; -MODULE_PARM(disable_ir,"i"); +module_param(disable_ir, int, 0444); MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); static unsigned int ir_debug = 0; -MODULE_PARM(ir_debug,"i"); +module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define dprintk(fmt, arg...) if (ir_debug) \ @@ -61,7 +63,7 @@ static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = { [ 20 ] = KEY_VOLUMEUP, [ 23 ] = KEY_VOLUMEDOWN, [ 18 ] = KEY_CHANNELUP, // Channel + - [ 19 ] = KEY_CHANNELDOWN, // Channel - + [ 19 ] = KEY_CHANNELDOWN, // Channel - [ 6 ] = KEY_AGAIN, // Recal [ 16 ] = KEY_KPENTER, // Enter @@ -209,6 +211,53 @@ static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { [ 15 ] = KEY_F22, // min [ 26 ] = KEY_F23, // freeze }; + +/* Alex Hermann */ +static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = { + [ 40 ] = KEY_KP1, + [ 24 ] = KEY_KP2, + [ 56 ] = KEY_KP3, + [ 36 ] = KEY_KP4, + [ 20 ] = KEY_KP5, + [ 52 ] = KEY_KP6, + [ 44 ] = KEY_KP7, + [ 28 ] = KEY_KP8, + [ 60 ] = KEY_KP9, + [ 34 ] = KEY_KP0, + + [ 32 ] = KEY_TV, // TV/FM + [ 16 ] = KEY_CD, // CD + [ 48 ] = KEY_TEXT, // TELETEXT + [ 0 ] = KEY_POWER, // POWER + + [ 8 ] = KEY_VIDEO, // VIDEO + [ 4 ] = KEY_AUDIO, // AUDIO + [ 12 ] = KEY_ZOOM, // FULL SCREEN + + [ 18 ] = KEY_SUBTITLE, // DISPLAY - ??? + [ 50 ] = KEY_REWIND, // LOOP - ??? + [ 2 ] = KEY_PRINT, // PREVIEW - ??? + + [ 42 ] = KEY_SEARCH, // AUTOSCAN + [ 26 ] = KEY_SLEEP, // FREEZE - ??? + [ 58 ] = KEY_SHUFFLE, // SNAPSHOT - ??? + [ 10 ] = KEY_MUTE, // MUTE + + [ 38 ] = KEY_RECORD, // RECORD + [ 22 ] = KEY_PAUSE, // PAUSE + [ 54 ] = KEY_STOP, // STOP + [ 6 ] = KEY_PLAY, // PLAY + + [ 46 ] = KEY_RED, // + [ 33 ] = KEY_GREEN, // + [ 14 ] = KEY_YELLOW, // + [ 1 ] = KEY_BLUE, // + + [ 30 ] = KEY_VOLUMEDOWN, // VOLUME- + [ 62 ] = KEY_VOLUMEUP, // VOLUME+ + [ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE- + [ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+ +}; /* ---------------------------------------------------------------------- */ static int build_key(struct saa7134_dev *dev) @@ -303,6 +352,16 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x000020; polling = 50; // ms break; + case SAA7134_BOARD_MD2819: + case SAA7134_BOARD_AVERMEDIA_307: + ir_codes = md2819_codes; + mask_keycode = 0x0007C8; + mask_keydown = 0x000010; + polling = 50; // ms + /* Set GPIO pin2 to high to enable the IR controller */ + saa_setb(SAA7134_GPIO_GPMODE0, 0x4); + saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", @@ -320,7 +379,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; ir->polling = polling; - + /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", saa7134_boards[dev->board].name); @@ -359,7 +418,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) { if (NULL == dev->remote) return; - + input_unregister_device(&dev->remote->dev); if (dev->remote->polling) del_timer_sync(&dev->remote->timer); diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index 63b32ab17..55a4548cf 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-oss.c,v 1.11 2004/11/07 13:17:15 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * oss dsp interface * @@ -32,11 +34,11 @@ /* ------------------------------------------------------------------ */ static unsigned int oss_debug = 0; -MODULE_PARM(oss_debug,"i"); +module_param(oss_debug, int, 0644); MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); static unsigned int oss_rate = 0; -MODULE_PARM(oss_rate,"i"); +module_param(oss_rate, int, 0444); MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); #define dprintk(fmt, arg...) if (oss_debug) \ @@ -138,7 +140,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) } switch (dev->oss.afmt) { - case AFMT_S8: + case AFMT_S8: case AFMT_S16_LE: case AFMT_S16_BE: sign = 1; break; default: sign = 0; break; @@ -159,7 +161,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) if (sign) fmt |= 0x04; fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; - + saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff)); saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8); saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16); @@ -191,7 +193,7 @@ static int dsp_rec_start(struct saa7134_dev *dev) saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); saa_writel(SAA7134_RS_PITCH(6),0); saa_writel(SAA7134_RS_CONTROL(6),control); - + /* start dma */ dev->oss.recording_on = 1; spin_lock_irqsave(&dev->slock,flags); @@ -367,7 +369,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, void __user *argp = (void __user *) arg; int __user *p = argp; int val = 0; - + if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); switch (cmd) { @@ -410,7 +412,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, /* fall through */ case SOUND_PCM_READ_CHANNELS: return put_user(dev->oss.channels, p); - + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | @@ -533,7 +535,7 @@ static int mixer_recsrc_7134(struct saa7134_dev *dev) { int analog_io,rate; - + switch (dev->oss.input) { case TV: saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); @@ -555,7 +557,7 @@ static int mixer_recsrc_7133(struct saa7134_dev *dev) { u32 value = 0xbbbbbb; - + switch (dev->oss.input) { case TV: value = 0xbbbb10; /* MAIN */ @@ -653,7 +655,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, int val,ret; void __user *argp = (void __user *) arg; int __user *p = argp; - + if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); switch (cmd) { @@ -776,8 +778,6 @@ int saa7134_oss_init1(struct saa7134_dev *dev) dev->oss.rate = 32000; if (oss_rate) dev->oss.rate = oss_rate; - if (saa7134_boards[dev->board].i2s_rate) - dev->oss.rate = saa7134_boards[dev->board].i2s_rate; dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000; /* mixer */ @@ -786,7 +786,7 @@ int saa7134_oss_init1(struct saa7134_dev *dev) mixer_level(dev,LINE1,dev->oss.line1); mixer_level(dev,LINE2,dev->oss.line2); mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2); - + return 0; } @@ -840,7 +840,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; dev->oss.read_count += dev->oss.blksize; wake_up(&dev->oss.wq); - + done: spin_unlock(&dev->slock); } diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index c39ea875a..87734f22a 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -1,4 +1,6 @@ /* + * $Id: saa7134-reg.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $ + * * philips saa7134 registers */ diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index f969b2747..ed73f71a4 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-ts.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * video4linux video interface * @@ -29,24 +31,12 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include - /* ------------------------------------------------------------------ */ -#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ - static unsigned int ts_debug = 0; -MODULE_PARM(ts_debug,"i"); +module_param(ts_debug, int, 0644); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); -static unsigned int tsbufs = 4; -MODULE_PARM(tsbufs,"i"); -MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); - -static unsigned int ts_nr_packets = 30; -MODULE_PARM(ts_nr_packets,"i"); -MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); - #define dprintk(fmt, arg...) if (ts_debug) \ printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg) @@ -57,11 +47,11 @@ static int buffer_activate(struct saa7134_dev *dev, struct saa7134_buf *next) { u32 control; - + dprintk("buffer_activate [%p]",buf); buf->vb.state = STATE_ACTIVE; buf->top_seen = 0; - + /* dma: setup channel 5 (= TS) */ control = SAA7134_RS_CONTROL_BURST_16 | SAA7134_RS_CONTROL_ME | @@ -83,24 +73,24 @@ static int buffer_activate(struct saa7134_dev *dev, /* start DMA */ saa7134_set_dmabits(dev); - + mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); return 0; } -static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, +static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { - struct saa7134_dev *dev = file->private_data; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; + struct saa7134_dev *dev = q->priv_data; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); unsigned int lines, llength, size; int err; - + dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); llength = TS_PACKET_SIZE; - lines = ts_nr_packets; - + lines = dev->ts.nr_packets; + size = lines * llength; if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; @@ -136,320 +126,51 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, } static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - *size = TS_PACKET_SIZE * ts_nr_packets; + struct saa7134_dev *dev = q->priv_data; + + *size = TS_PACKET_SIZE * dev->ts.nr_packets; if (0 == *count) - *count = tsbufs; + *count = dev->ts.nr_bufs; *count = saa7134_buffer_count(*size,*count); return 0; } -static void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_dev *dev = file->private_data; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_dev *dev = q->priv_data; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_buffer_queue(dev,&dev->ts_q,buf); } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_dev *dev = file->private_data; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_dev *dev = q->priv_data; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_dma_free(dev,buf); } -static struct videobuf_queue_ops ts_qops = { +struct videobuf_queue_ops saa7134_ts_qops = { .buf_setup = buffer_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, .buf_release = buffer_release, }; - - -/* ------------------------------------------------------------------ */ - -static void ts_reset_encoder(struct saa7134_dev* dev) -{ - saa_writeb(SAA7134_SPECIAL_MODE, 0x00); - mdelay(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); -} - -static int ts_init_encoder(struct saa7134_dev* dev, void* arg) -{ - ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg); - return 0; -} - - -/* ------------------------------------------------------------------ */ - -static int ts_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct saa7134_dev *h,*dev = NULL; - struct list_head *list; - int err; - - list_for_each(list,&saa7134_devlist) { - h = list_entry(list, struct saa7134_dev, devlist); - if (h->ts_dev && h->ts_dev->minor == minor) - dev = h; - } - if (NULL == dev) - return -ENODEV; - - dprintk("open minor=%d\n",minor); - down(&dev->ts.ts.lock); - err = -EBUSY; - if (dev->ts.users) - goto done; - - dev->ts.started = 0; - dev->ts.users++; - file->private_data = dev; - err = 0; - - done: - up(&dev->ts.ts.lock); - return err; -} - -static int ts_release(struct inode *inode, struct file *file) -{ - struct saa7134_dev *dev = file->private_data; - - if (dev->ts.ts.streaming) - videobuf_streamoff(file,&dev->ts.ts); - down(&dev->ts.ts.lock); - if (dev->ts.ts.reading) - videobuf_read_stop(file,&dev->ts.ts); - dev->ts.users--; - - /* stop the encoder */ - if (dev->ts.started) - ts_reset_encoder(dev); - - up(&dev->ts.ts.lock); - return 0; -} - -static ssize_t -ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct saa7134_dev *dev = file->private_data; - - if (!dev->ts.started) { - ts_init_encoder(dev, NULL); - dev->ts.started = 1; - } - - return videobuf_read_stream(file, &dev->ts.ts, data, count, ppos, 0); -} - -static unsigned int -ts_poll(struct file *file, struct poll_table_struct *wait) -{ - struct saa7134_dev *dev = file->private_data; - - return videobuf_poll_stream(file, &dev->ts.ts, wait); -} - - -static int -ts_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct saa7134_dev *dev = file->private_data; - - return videobuf_mmap_mapper(vma, &dev->ts.ts); -} - -/* - * This function is _not_ called directly, but from - * video_generic_ioctl (and maybe others). userspace - * copying is done already, arg is a kernel pointer. - */ -static int ts_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct saa7134_dev *dev = file->private_data; - - if (ts_debug > 1) - saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); - strlcpy(cap->card, saa7134_boards[dev->board].name, - sizeof(cap->card)); - sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); - cap->version = SAA7134_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - return 0; - } - - /* --- input switching --------------------------------------- */ - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name,"CCIR656"); - return 0; - } - case VIDIOC_G_INPUT: - { - int *i = arg; - *i = 0; - return 0; - } - case VIDIOC_S_INPUT: - { - int *i = arg; - - if (*i != 0) - return -EINVAL; - return 0; - } - /* --- capture ioctls ---------------------------------------- */ - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - int index; - - index = f->index; - if (index != 0) - return -EINVAL; - - memset(f,0,sizeof(*f)); - f->index = index; - strlcpy(f->description, "MPEG TS", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->pixelformat = V4L2_PIX_FMT_MPEG; - return 0; - } - - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - - memset(f,0,sizeof(*f)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - /* FIXME: translate subsampling type EMPRESS into - * width/height: */ - f->fmt.pix.width = 720; /* D1 */ - f->fmt.pix.height = 576; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; - return 0; - } - - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - /* - FIXME: translate and round width/height into EMPRESS - subsample type: - - type | PAL | NTSC - --------------------------- - SIF | 352x288 | 352x240 - 1/2 D1 | 352x576 | 352x480 - 2/3 D1 | 480x576 | 480x480 - D1 | 720x576 | 720x480 - */ - - f->fmt.pix.width = 720; /* D1 */ - f->fmt.pix.height = 576; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; - return 0; - } - - case VIDIOC_REQBUFS: - return videobuf_reqbufs(file,&dev->ts.ts,arg); - - case VIDIOC_QUERYBUF: - return videobuf_querybuf(&dev->ts.ts,arg); - - case VIDIOC_QBUF: - return videobuf_qbuf(file,&dev->ts.ts,arg); - - case VIDIOC_DQBUF: - return videobuf_dqbuf(file,&dev->ts.ts,arg); - - case VIDIOC_STREAMON: - return videobuf_streamon(file,&dev->ts.ts); - - case VIDIOC_STREAMOFF: - return videobuf_streamoff(file,&dev->ts.ts); - - case VIDIOC_QUERYCTRL: - case VIDIOC_G_CTRL: - case VIDIOC_S_CTRL: - return saa7134_common_ioctl(dev, cmd, arg); - - case MPEG_SETPARAMS: - return ts_init_encoder(dev, arg); - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int ts_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, ts_do_ioctl); -} - - -static struct file_operations ts_fops = -{ - .owner = THIS_MODULE, - .open = ts_open, - .release = ts_release, - .read = ts_read, - .poll = ts_poll, - .mmap = ts_mmap, - .ioctl = ts_ioctl, - .llseek = no_llseek, -}; - +EXPORT_SYMBOL_GPL(saa7134_ts_qops); /* ----------------------------------------------------------- */ /* exported stuff */ -struct video_device saa7134_ts_template = -{ - .name = "saa7134-ts", - .type = 0 /* FIXME */, - .type2 = 0 /* FIXME */, - .hardware = 0, - .fops = &ts_fops, - .minor = -1, -}; +static unsigned int tsbufs = 4; +module_param(tsbufs, int, 0444); +MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); + +static unsigned int ts_nr_packets = 30; +module_param(ts_nr_packets, int, 0444); +MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); int saa7134_ts_init1(struct saa7134_dev *dev) { @@ -462,6 +183,8 @@ int saa7134_ts_init1(struct saa7134_dev *dev) ts_nr_packets = 4; if (ts_nr_packets > 312) ts_nr_packets = 312; + dev->ts.nr_bufs = tsbufs; + dev->ts.nr_packets = ts_nr_packets; INIT_LIST_HEAD(&dev->ts_q.queue); init_timer(&dev->ts_q.timeout); @@ -469,26 +192,21 @@ int saa7134_ts_init1(struct saa7134_dev *dev) dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); dev->ts_q.dev = dev; dev->ts_q.need_two = 1; - videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_ALTERNATE, - sizeof(struct saa7134_buf)); saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); /* init TS hw */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); - saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff)); - saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff)); - saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ - + saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); + saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); + saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + return 0; } int saa7134_ts_fini(struct saa7134_dev *dev) { - /* nothing */ saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 261d92040..7461f8a19 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-tvaudio.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * tv audio decoder (fm stereo, nicam, ...) * @@ -34,18 +36,18 @@ /* ------------------------------------------------------------------ */ static unsigned int audio_debug = 0; -MODULE_PARM(audio_debug,"i"); +module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); static unsigned int audio_ddep = 0; -MODULE_PARM(audio_ddep,"i"); +module_param(audio_ddep, int, 0644); MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); static int audio_clock_override = UNSET; -MODULE_PARM(audio_clock_override, "i"); +module_param(audio_clock_override, int, 0644); static int audio_clock_tweak = 0; -MODULE_PARM(audio_clock_tweak, "i"); +module_param(audio_clock_tweak, int, 0644); MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); #define dprintk(fmt, arg...) if (audio_debug) \ @@ -56,9 +58,10 @@ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with #define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \ dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg))) -#define SCAN_INITIAL_DELAY (HZ) -#define SCAN_SAMPLE_DELAY (HZ/5) -#define SCAN_SUBCARRIER_DELAY (HZ*2) +/* msecs */ +#define SCAN_INITIAL_DELAY 1000 +#define SCAN_SAMPLE_DELAY 200 +#define SCAN_SUBCARRIER_DELAY 2000 /* ------------------------------------------------------------------ */ /* saa7134 code */ @@ -281,7 +284,7 @@ static void tvaudio_setmode(struct saa7134_dev *dev, saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD1, (acpf & 0x00ff00) >> 8); saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD2, (acpf & 0x030000) >> 16); tvaudio_setcarrier(dev,audio->carr1,audio->carr2); - + switch (audio->mode) { case TVAUDIO_FM_MONO: case TVAUDIO_FM_BG_STEREO: @@ -321,14 +324,21 @@ static void tvaudio_setmode(struct saa7134_dev *dev, static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) { DECLARE_WAITQUEUE(wait, current); - + add_wait_queue(&dev->thread.wq, &wait); if (dev->thread.scan1 == dev->thread.scan2 && !dev->thread.shutdown) { - set_current_state(TASK_INTERRUPTIBLE); - if (timeout < 0) + if (timeout < 0) { + set_current_state(TASK_INTERRUPTIBLE); schedule(); - else - schedule_timeout(timeout); + } else { +#if 0 + /* hmm, that one doesn't return on wakeup ... */ + msleep_interruptible(timeout); +#else + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(timeout)); +#endif + } } remove_wait_queue(&dev->thread.wq, &wait); return dev->thread.scan1 != dev->thread.scan2; @@ -404,7 +414,7 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au { __u32 idp,nicam; int retval = -1; - + switch (audio->mode) { case TVAUDIO_FM_MONO: return V4L2_TUNER_SUB_MONO; @@ -504,7 +514,8 @@ static int tvaudio_thread(void *data) dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1); dev->tvaudio = NULL; tvaudio_init(dev); - dev->automute = 1; + if (dev->ctl_automute) + dev->automute = 1; mute_input_7134(dev); /* give the tuner some time */ @@ -601,7 +612,7 @@ static int tvaudio_thread(void *data) lastmode = 42; for (;;) { - if (tvaudio_sleep(dev,5*HZ)) + if (tvaudio_sleep(dev,5000)) goto restart; if (dev->thread.shutdown || signal_pending(current)) break; @@ -640,7 +651,7 @@ static char *stdres[0x20] = { [0x09] = "D/K NICAM", [0x0a] = "L NICAM", [0x0b] = "I NICAM", - + [0x0c] = "M Korea", [0x0d] = "M BTSC ", [0x0e] = "M EIAJ", @@ -734,7 +745,8 @@ static int getstereo_7133(struct saa7134_dev *dev) static int mute_input_7133(struct saa7134_dev *dev) { u32 reg = 0; - + int mask; + switch (dev->input->amux) { case TV: reg = 0x02; break; case LINE1: reg = 0x00; break; @@ -743,6 +755,14 @@ static int mute_input_7133(struct saa7134_dev *dev) if (dev->ctl_mute) reg = 0x07; saa_writel(0x594 >> 2, reg); + + /* switch gpio-connected external audio mux */ + if (0 != card(dev).gpiomask) { + mask = card(dev).gpiomask; + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, dev->input->gpio); + saa7134_track_gpio(dev,dev->input->name); + } return 0; } @@ -776,7 +796,10 @@ static int tvaudio_thread_ddep(void *data) /* insmod option override */ norms = (audio_ddep << 2) | 0x01; dprintk("ddep override: %s\n",stdres[audio_ddep]); - } else{ + } else if (&card(dev).radio == dev->input) { + dprintk("FM Radio\n"); + norms = (0x0f << 2) | 0x01; + } else { /* (let chip) scan for sound carrier */ norms = 0; if (dev->tvnorm->id & V4L2_STD_PAL) { @@ -809,7 +832,7 @@ static int tvaudio_thread_ddep(void *data) saa_dsp_writel(dev, 0x464 >> 2, 0x000000); saa_dsp_writel(dev, 0x470 >> 2, 0x101010); - if (tvaudio_sleep(dev,3*HZ)) + if (tvaudio_sleep(dev,3000)) goto restart; value = saa_readl(0x528 >> 2) & 0xffffff; @@ -829,12 +852,12 @@ static int tvaudio_thread_ddep(void *data) (value & 0x002000) ? " BTSC stereo noise mute " : "", (value & 0x004000) ? " SAP noise mute " : "", (value & 0x008000) ? " VDSP " : "", - + (value & 0x010000) ? " NICST " : "", (value & 0x020000) ? " NICDU " : "", (value & 0x040000) ? " NICAM muted " : "", (value & 0x080000) ? " NICAM reserve sound " : "", - + (value & 0x100000) ? " init done " : ""); } @@ -849,7 +872,7 @@ static int tvaudio_thread_ddep(void *data) int saa7134_tvaudio_rx2mode(u32 rx) { u32 mode; - + mode = V4L2_TUNER_MODE_MONO; if (rx & V4L2_TUNER_SUB_STEREO) mode = V4L2_TUNER_MODE_STEREO; @@ -859,7 +882,7 @@ int saa7134_tvaudio_rx2mode(u32 rx) mode = V4L2_TUNER_MODE_LANG2; return mode; } - + void saa7134_tvaudio_setmute(struct saa7134_dev *dev) { switch (dev->pci->device) { @@ -924,13 +947,14 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) int (*my_thread)(void *data) = NULL; /* enable I2S audio output */ - if (saa7134_boards[dev->board].i2s_rate) { - int i2sform = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x00 : 0x01; - + if (card_is_empress(dev)) { + int i2sform = (48000 == dev->oss.rate) + ? 0x01 : 0x00; + /* enable I2S output */ - saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); - saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2sform); - saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); + saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); + saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2sform); + saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); } diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c index 01451b37a..5707e9021 100644 --- a/drivers/media/video/saa7134/saa7134-vbi.c +++ b/drivers/media/video/saa7134/saa7134-vbi.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-vbi.c,v 1.5 2004/11/07 13:17:15 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * video4linux video interface * @@ -31,11 +33,11 @@ /* ------------------------------------------------------------------ */ static unsigned int vbi_debug = 0; -MODULE_PARM(vbi_debug,"i"); +module_param(vbi_debug, int, 0644); MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); static unsigned int vbibufs = 4; -MODULE_PARM(vbibufs,"i"); +module_param(vbibufs, int, 0444); MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); #define dprintk(fmt, arg...) if (vbi_debug) \ @@ -51,7 +53,7 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf, int task) { struct saa7134_tvnorm *norm = dev->tvnorm; - + /* setup video scaler */ saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start & 0xff); saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8); @@ -113,12 +115,13 @@ static int buffer_activate(struct saa7134_dev *dev, return 0; } -static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, +static int buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, enum v4l2_field field) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; struct saa7134_dev *dev = fh->dev; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); struct saa7134_tvnorm *norm = dev->tvnorm; unsigned int lines, llength, size; int err; @@ -167,12 +170,12 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, } static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; struct saa7134_dev *dev = fh->dev; int llength,lines; - + lines = dev->tvnorm->vbi_v_stop - dev->tvnorm->vbi_v_start +1; #if 1 llength = VBI_LINE_LENGTH; @@ -188,21 +191,21 @@ buffer_setup(struct file *file, unsigned int *count, unsigned int *size) return 0; } -static void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; struct saa7134_dev *dev = fh->dev; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_buffer_queue(dev,&dev->vbi_q,buf); } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; struct saa7134_dev *dev = fh->dev; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_dma_free(dev,buf); } diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index ec4c286df..2bbe9ebdd 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1,4 +1,6 @@ /* + * $Id: saa7134-video.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $ + * * device driver for philips saa7134 based TV cards * video4linux video interface * @@ -37,11 +39,11 @@ static unsigned int gbuffers = 8; static unsigned int noninterlaced = 0; static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; -MODULE_PARM(video_debug,"i"); +module_param(video_debug, int, 0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); -MODULE_PARM(gbuffers,"i"); +module_param(gbuffers, int, 0444); MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32"); -MODULE_PARM(noninterlaced,"i"); +module_param(noninterlaced, int, 0644); MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced"); #define dprintk(fmt, arg...) if (video_debug) \ @@ -53,7 +55,7 @@ MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced"); static int video_out[][9] = { [CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 }, }; - + static struct saa7134_format formats[] = { { .name = "8 bpp gray", @@ -272,7 +274,8 @@ static struct saa7134_tvnorm tvnorms[] = { #define V4L2_CID_PRIVATE_INVERT (V4L2_CID_PRIVATE_BASE + 0) #define V4L2_CID_PRIVATE_Y_ODD (V4L2_CID_PRIVATE_BASE + 1) #define V4L2_CID_PRIVATE_Y_EVEN (V4L2_CID_PRIVATE_BASE + 2) -#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PRIVATE_AUTOMUTE (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 4) static const struct v4l2_queryctrl no_ctrl = { .name = "42", @@ -356,6 +359,13 @@ static const struct v4l2_queryctrl video_ctrls[] = { .maximum = 128, .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_PRIVATE_AUTOMUTE, + .name = "automute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, } }; static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls); @@ -363,7 +373,7 @@ static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls); static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id) { unsigned int i; - + for (i = 0; i < CTRLS; i++) if (video_ctrls[i].id == id) return video_ctrls+i; @@ -433,10 +443,11 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits) static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) { - int luma_control,sync_control,mux; + int luma_control,sync_control,mux,nosignal; dprintk("set tv norm = %s\n",norm->name); dev->tvnorm = norm; + nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03)); mux = card_in(dev,dev->ctl_input).vmux; luma_control = norm->luma_control; @@ -444,7 +455,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) if (mux > 5) luma_control |= 0x80; /* svideo */ - if (noninterlaced) + if (noninterlaced || nosignal) sync_control |= 0x20; /* setup cropping */ @@ -471,12 +482,12 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm) saa_writeb(SAA7134_HSYNC_START, 0xeb); saa_writeb(SAA7134_HSYNC_STOP, 0xe0); saa_writeb(SAA7134_SOURCE_TIMING1, norm->src_timing); - + saa_writeb(SAA7134_SYNC_CTRL, sync_control); saa_writeb(SAA7134_LUMA_CTRL, luma_control); saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright); saa_writeb(SAA7134_DEC_LUMA_CONTRAST, dev->ctl_contrast); - + saa_writeb(SAA7134_DEC_CHROMA_SATURATION, dev->ctl_saturation); saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue); saa_writeb(SAA7134_CHROMA_CTRL1, norm->chroma_ctrl1); @@ -559,7 +570,7 @@ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) static void set_v_scale(struct saa7134_dev *dev, int task, int yscale) { int val,mirror; - + saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale & 0xff); saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8); @@ -613,7 +624,7 @@ static void set_size(struct saa7134_dev *dev, int task, saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8); set_v_scale(dev,task,yscale); - + saa_writeb(SAA7134_VIDEO_PIXELS1(task), width & 0xff); saa_writeb(SAA7134_VIDEO_PIXELS2(task), width >> 8); saa_writeb(SAA7134_VIDEO_LINES1(task), height/div & 0xff); @@ -640,7 +651,7 @@ static void sort_cliplist(struct cliplist *cl, int entries) { struct cliplist swap; int i,j,n; - + for (i = entries-2; i >= 0; i--) { for (n = 0, j = 0; j <= i; j++) { if (cl[j].position > cl[j+1].position) { @@ -835,7 +846,7 @@ static int buffer_activate(struct saa7134_dev *dev, dprintk("buffer_activate buf=%p\n",buf); buf->vb.state = STATE_ACTIVE; buf->top_seen = 0; - + set_size(dev,TASK_A,buf->vb.width,buf->vb.height, V4L2_FIELD_HAS_BOTH(buf->vb.field)); if (buf->fmt->yuv) @@ -907,15 +918,16 @@ static int buffer_activate(struct saa7134_dev *dev, return 0; } -static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, +static int buffer_prepare(struct videobuf_queue *q, + struct videobuf_buffer *vb, enum v4l2_field field) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; struct saa7134_dev *dev = fh->dev; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); unsigned int size; int err; - + /* sanity checks */ if (NULL == fh->fmt) return -EINVAL; @@ -969,9 +981,9 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, } static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { - struct saa7134_fh *fh = file->private_data; + struct saa7134_fh *fh = q->priv_data; *size = fh->fmt->depth * fh->width * fh->height >> 3; if (0 == *count) @@ -980,19 +992,19 @@ buffer_setup(struct file *file, unsigned int *count, unsigned int *size) return 0; } -static void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = file->private_data; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_fh *fh = q->priv_data; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf); } -static void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct saa7134_fh *fh = file->private_data; - struct saa7134_buf *buf = (struct saa7134_buf *)vb; - + struct saa7134_fh *fh = q->priv_data; + struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); + saa7134_dma_free(fh->dev,buf); } @@ -1043,6 +1055,9 @@ static int get_control(struct saa7134_dev *dev, struct v4l2_control *c) case V4L2_CID_PRIVATE_Y_ODD: c->value = dev->ctl_y_odd; break; + case V4L2_CID_PRIVATE_AUTOMUTE: + c->value = dev->ctl_automute; + break; default: return -EINVAL; } @@ -1118,6 +1133,17 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh, dev->ctl_y_odd = c->value; restart_overlay = 1; break; + case V4L2_CID_PRIVATE_AUTOMUTE: + dev->ctl_automute = c->value; + if (dev->tda9887_conf) { + if (dev->ctl_automute) + dev->tda9887_conf |= TDA9887_AUTOMUTE; + else + dev->tda9887_conf &= ~TDA9887_AUTOMUTE; + saa7134_i2c_call_clients(dev, TDA9887_SET_CONFIG, + &dev->tda9887_conf); + } + break; default: return -EINVAL; } @@ -1135,7 +1161,7 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh, static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) { struct videobuf_queue* q = NULL; - + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: q = &fh->cap; @@ -1152,7 +1178,7 @@ static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) static int saa7134_resource(struct saa7134_fh *fh) { int res = 0; - + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: res = RESOURCE_VIDEO; @@ -1174,7 +1200,7 @@ static int video_open(struct inode *inode, struct file *file) struct list_head *list; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int radio = 0; - + list_for_each(list,&saa7134_devlist) { h = list_entry(list, struct saa7134_dev, devlist); if (h->video_dev && (h->video_dev->minor == minor)) @@ -1206,24 +1232,21 @@ static int video_open(struct inode *inode, struct file *file) fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); fh->width = 720; fh->height = 576; -#ifdef VIDIOC_G_PRIORITY v4l2_prio_open(&dev->prio,&fh->prio); -#endif videobuf_queue_init(&fh->cap, &video_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct saa7134_buf)); - init_MUTEX(&fh->cap.lock); - saa7134_pgtable_alloc(dev->pci,&fh->pt_cap); - + sizeof(struct saa7134_buf), + fh); videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, - sizeof(struct saa7134_buf)); - init_MUTEX(&fh->vbi.lock); + sizeof(struct saa7134_buf), + fh); + saa7134_pgtable_alloc(dev->pci,&fh->pt_cap); saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi); if (fh->radio) { @@ -1246,13 +1269,15 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (res_locked(fh->dev,RESOURCE_VIDEO)) return -EBUSY; - return videobuf_read_one(file, saa7134_queue(fh), - data, count, ppos); + return videobuf_read_one(saa7134_queue(fh), + data, count, ppos, + file->f_flags & O_NONBLOCK); case V4L2_BUF_TYPE_VBI_CAPTURE: if (!res_get(fh->dev,fh,RESOURCE_VBI)) return -EBUSY; - return videobuf_read_stream(file, saa7134_queue(fh), - data, count, ppos, 1); + return videobuf_read_stream(saa7134_queue(fh), + data, count, ppos, 1, + file->f_flags & O_NONBLOCK); break; default: BUG(); @@ -1280,11 +1305,11 @@ video_poll(struct file *file, struct poll_table_struct *wait) up(&fh->cap.lock); return POLLERR; } - if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,fh->cap.field)) { + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { up(&fh->cap.lock); return POLLERR; } - fh->cap.ops->buf_queue(file,fh->cap.read_buf); + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } up(&fh->cap.lock); @@ -1317,29 +1342,27 @@ static int video_release(struct inode *inode, struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO)) { - videobuf_streamoff(file,&fh->cap); + videobuf_streamoff(&fh->cap); res_free(dev,fh,RESOURCE_VIDEO); } if (fh->cap.read_buf) { - buffer_release(file,fh->cap.read_buf); + buffer_release(&fh->cap,fh->cap.read_buf); kfree(fh->cap.read_buf); } /* stop vbi capture */ if (res_check(fh, RESOURCE_VBI)) { if (fh->vbi.streaming) - videobuf_streamoff(file,&fh->vbi); + videobuf_streamoff(&fh->vbi); if (fh->vbi.reading) - videobuf_read_stop(file,&fh->vbi); + videobuf_read_stop(&fh->vbi); res_free(dev,fh,RESOURCE_VBI); } saa7134_pgtable_free(dev->pci,&fh->pt_cap); saa7134_pgtable_free(dev->pci,&fh->pt_vbi); -#ifdef VIDIOC_G_PRIORITY v4l2_prio_close(&dev->prio,&fh->prio); -#endif file->private_data = NULL; kfree(fh); return 0; @@ -1349,8 +1372,8 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma) { struct saa7134_fh *fh = file->private_data; - - return videobuf_mmap_mapper(vma,saa7134_queue(fh)); + + return videobuf_mmap_mapper(saa7134_queue(fh), vma); } /* ------------------------------------------------------------------ */ @@ -1408,7 +1431,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_format *f) { int err; - + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { @@ -1423,7 +1446,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, field = f->fmt.pix.field; maxw = min(dev->crop_current.width*4, dev->crop_bounds.width); maxh = min(dev->crop_current.height*4, dev->crop_bounds.height); - + if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) ? V4L2_FIELD_INTERLACED @@ -1453,7 +1476,7 @@ int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - + return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -1474,13 +1497,13 @@ int saa7134_s_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh, { unsigned long flags; int err; - + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: err = saa7134_try_fmt(dev,fh,f); if (0 != err) return err; - + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; @@ -1522,7 +1545,7 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, unsigned int cmd, void *arg) { int err; - + switch (cmd) { case VIDIOC_QUERYCTRL: { @@ -1589,7 +1612,7 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, case VIDIOC_S_INPUT: { int *i = arg; - + if (*i < 0 || *i >= SAA7134_INPUT_MAX) return -EINVAL; if (NULL == card_in(dev,*i).name) @@ -1603,6 +1626,7 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, } return 0; } +EXPORT_SYMBOL(saa7134_common_ioctl); /* * This function is _not_ called directly, but from @@ -1620,7 +1644,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (video_debug > 1) saa7134_print_ioctl(dev->name,cmd); -#ifdef VIDIOC_G_PRIORITY switch (cmd) { case VIDIOC_S_CTRL: case VIDIOC_S_STD: @@ -1631,13 +1654,12 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (0 != err) return err; } -#endif switch (cmd) { case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; - + memset(cap,0,sizeof(*cap)); strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, @@ -1649,7 +1671,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_READWRITE | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; return 0; } @@ -1699,7 +1721,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, set_tvnorm(dev,&tvnorms[i]); start_preview(dev,fh); spin_unlock_irqrestore(&dev->slock,flags); - } else + } else set_tvnorm(dev,&tvnorms[i]); saa7134_tvaudio_do_scan(dev); up(&dev->lock); @@ -1820,7 +1842,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_frequency *f = arg; memset(f,0,sizeof(*f)); - f->type = V4L2_TUNER_ANALOG_TV; + f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; return 0; } @@ -1830,7 +1852,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (0 != f->tuner) return -EINVAL; - if (V4L2_TUNER_ANALOG_TV != f->type) + if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; + if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) return -EINVAL; down(&dev->lock); dev->ctl_freq = f->frequency; @@ -1843,7 +1867,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, up(&dev->lock); return 0; } - + /* --- control ioctls ---------------------------------------- */ case VIDIOC_ENUMINPUT: case VIDIOC_G_INPUT: @@ -1870,7 +1894,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return 0; } -#ifdef VIDIOC_G_PRIORITY case VIDIOC_G_PRIORITY: { enum v4l2_priority *p = arg; @@ -1884,7 +1907,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return v4l2_prio_change(&dev->prio, &fh->prio, *prio); } -#endif /* --- preview ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: @@ -1919,7 +1941,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, strcpy(f->description,"vbi data"); break; default: - return -EINVAL; + return -EINVAL; } return 0; } @@ -1935,7 +1957,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { struct v4l2_framebuffer *fb = arg; struct saa7134_format *fmt; - + if(!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) return -EPERM; @@ -1991,7 +2013,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } - + case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -2004,7 +2026,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, req.type = q->type; req.count = gbuffers; req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(file,q,&req); + err = videobuf_reqbufs(q,&req); if (err < 0) return err; memset(mbuf,0,sizeof(*mbuf)); @@ -2017,16 +2039,17 @@ static int video_do_ioctl(struct inode *inode, struct file *file, return 0; } case VIDIOC_REQBUFS: - return videobuf_reqbufs(file,saa7134_queue(fh),arg); + return videobuf_reqbufs(saa7134_queue(fh),arg); case VIDIOC_QUERYBUF: return videobuf_querybuf(saa7134_queue(fh),arg); case VIDIOC_QBUF: - return videobuf_qbuf(file,saa7134_queue(fh),arg); + return videobuf_qbuf(saa7134_queue(fh),arg); case VIDIOC_DQBUF: - return videobuf_dqbuf(file,saa7134_queue(fh),arg); + return videobuf_dqbuf(saa7134_queue(fh),arg, + file->f_flags & O_NONBLOCK); case VIDIOC_STREAMON: { @@ -2034,13 +2057,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, if (!res_get(dev,fh,res)) return -EBUSY; - return videobuf_streamon(file,saa7134_queue(fh)); + return videobuf_streamon(saa7134_queue(fh)); } case VIDIOC_STREAMOFF: { int res = saa7134_resource(fh); - err = videobuf_streamoff(file,saa7134_queue(fh)); + err = videobuf_streamoff(saa7134_queue(fh)); if (err < 0) return err; res_free(dev,fh,res); @@ -2065,7 +2088,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - + if (video_debug > 1) saa7134_print_ioctl(dev->name,cmd); switch (cmd) { @@ -2109,7 +2132,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; - + if (i->index != 0) return -EINVAL; strcpy(i->name,"Radio"); @@ -2163,7 +2186,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: return video_do_ioctl(inode,file,cmd,arg); - + default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, radio_do_ioctl); @@ -2244,9 +2267,12 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value; dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value; dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value; + dev->ctl_mute = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value; + dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value; + dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value; - dev->ctl_invert = 0; - dev->ctl_mute = 1; + if (dev->tda9887_conf && dev->ctl_automute) + dev->tda9887_conf |= TDA9887_AUTOMUTE; dev->automute = 0; INIT_LIST_HEAD(&dev->video_q.queue); @@ -2268,7 +2294,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); } - + return 0; } @@ -2296,21 +2322,25 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev) norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03; dprintk("DCSDT: %s\n",st[norm]); - + if (0 != norm) { /* wake up tvaudio audio carrier scan thread */ saa7134_tvaudio_do_scan(dev); + if (!noninterlaced) + saa_clearb(SAA7134_SYNC_CTRL, 0x20); } else { /* no video signal -> mute audio */ - dev->automute = 1; + if (dev->ctl_automute) + dev->automute = 1; saa7134_tvaudio_setmute(dev); + saa_setb(SAA7134_SYNC_CTRL, 0x20); } } void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status) { enum v4l2_field field; - + spin_lock(&dev->slock); if (dev->video_q.curr) { dev->video_fieldcount++; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f4d346949..a4e68b3fc 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -1,4 +1,6 @@ /* + * $Id: saa7134.h,v 1.27 2004/11/04 11:03:52 kraxel Exp $ + * * v4l2 device driver for philips saa7134 based TV cards * * (c) 2001,02 Gerd Knorr @@ -29,11 +31,12 @@ #include -#include #include #include #include #include +#include +#include #ifndef TRUE # define TRUE (1==1) @@ -156,7 +159,18 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_305 35 #define SAA7133_BOARD_UPMOST_PURPLE_TV 36 #define SAA7134_BOARD_ITEMS_MTV005 37 - +#define SAA7134_BOARD_CINERGY200 38 +#define SAA7134_BOARD_FLYTVPLATINUM 39 +#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40 +#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41 +#define SAA7134_BOARD_SABRENT_SBTTVFM 42 +#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43 +#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44 +#define SAA7134_BOARD_AVERMEDIA_307 45 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46 +#define SAA7134_BOARD_CINERGY400_CARDBUS 47 + +#define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 struct saa7134_input { @@ -167,6 +181,12 @@ struct saa7134_input { unsigned int tv:1; }; +enum saa7134_mpeg_type { + SAA7134_MPEG_UNUSED, + SAA7134_MPEG_EMPRESS, + SAA7134_MPEG_DVB, +}; + struct saa7134_board { char *name; unsigned int audio_clock; @@ -176,19 +196,20 @@ struct saa7134_board { struct saa7134_input inputs[SAA7134_INPUT_MAX]; struct saa7134_input radio; struct saa7134_input mute; - - /* peripheral I/O */ - unsigned int i2s_rate; - unsigned int has_ts; - enum saa7134_video_out video_out; /* i2c chip info */ unsigned int tuner_type; - unsigned int need_tda9887:1; + unsigned int tda9887_conf; + + /* peripheral I/O */ + enum saa7134_video_out video_out; + enum saa7134_mpeg_type mpeg; }; #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) -#define card_has_ts(dev) (saa7134_boards[dev->board].has_ts) +#define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) +#define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) +#define card_has_mpeg(dev) (SAA7134_MPEG_UNUSED != saa7134_boards[dev->board].mpeg) #define card(dev) (saa7134_boards[dev->board]) #define card_in(dev,n) (saa7134_boards[dev->board].inputs[n]) @@ -256,7 +277,7 @@ struct saa7134_fh { unsigned int radio; enum v4l2_buf_type type; unsigned int resources; -#ifdef VIDIOC_G_PRIORITY +#ifdef VIDIOC_G_PRIORITY enum v4l2_priority prio; #endif @@ -276,16 +297,6 @@ struct saa7134_fh { struct saa7134_pgtable pt_vbi; }; -/* TS status */ -struct saa7134_ts { - unsigned int users; - - /* TS capture */ - struct videobuf_queue ts; - struct saa7134_pgtable pt_ts; - int started; -}; - /* oss dsp status */ struct saa7134_oss { struct semaphore lock; @@ -330,23 +341,37 @@ struct saa7134_ir { struct timer_list timer; }; +/* ts/mpeg status */ +struct saa7134_ts { + /* TS capture */ + struct saa7134_pgtable pt_ts; + int nr_packets; + int nr_bufs; +}; + +/* ts/mpeg ops */ +struct saa7134_mpeg_ops { + enum saa7134_mpeg_type type; + struct list_head next; + int (*init)(struct saa7134_dev *dev); + int (*fini)(struct saa7134_dev *dev); +}; + /* global device status */ struct saa7134_dev { struct list_head devlist; struct semaphore lock; spinlock_t slock; -#ifdef VIDIOC_G_PRIORITY +#ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif /* various device info */ unsigned int resources; struct video_device *video_dev; - struct video_device *ts_dev; struct video_device *radio_dev; struct video_device *vbi_dev; struct saa7134_oss oss; - struct saa7134_ts ts; /* infrared remote */ int has_remote; @@ -354,14 +379,16 @@ struct saa7134_dev { /* pci i/o */ char name[32]; + int nr; struct pci_dev *pci; unsigned char pci_rev,pci_lat; - __u32 *lmmio; - __u8 *bmmio; + __u32 __iomem *lmmio; + __u8 __iomem *bmmio; /* config info */ unsigned int board; unsigned int tuner_type; + unsigned int tda9887_conf; unsigned int gpio_value; /* i2c i/o */ @@ -377,7 +404,6 @@ struct saa7134_dev { /* video+ts+vbi capture */ struct saa7134_dmaqueue video_q; - struct saa7134_dmaqueue ts_q; struct saa7134_dmaqueue vbi_q; unsigned int video_fieldcount; unsigned int vbi_fieldcount; @@ -397,6 +423,7 @@ struct saa7134_dev { int ctl_mirror; int ctl_y_odd; int ctl_y_even; + int ctl_automute; /* crop */ struct v4l2_rect crop_bounds; @@ -410,6 +437,19 @@ struct saa7134_dev { struct saa7134_input *hw_input; unsigned int hw_mute; int last_carrier; + + /* SAA7134_MPEG_* */ + struct saa7134_ts ts; + struct saa7134_dmaqueue ts_q; + struct saa7134_mpeg_ops *mops; + + /* SAA7134_MPEG_EMPRESS only */ + struct video_device *empress_dev; + struct videobuf_queue empress_tsq; + unsigned int empress_users; + + /* SAA7134_MPEG_DVB only */ + struct videobuf_dvb dvb; }; /* ----------------------------------------------------------- */ @@ -430,7 +470,7 @@ struct saa7134_dev { #define saa_setb(reg,bit) saa_andorb((reg),(bit),(bit)) #define saa_clearb(reg,bit) saa_andorb((reg),(bit),0) -#define saa_wait(d) { udelay(d); } +#define saa_wait(us) { udelay(us); } /* ----------------------------------------------------------- */ /* saa7134-core.c */ @@ -470,7 +510,8 @@ extern struct saa7134_board saa7134_boards[]; extern const unsigned int saa7134_bcount; extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; -extern int saa7134_board_init(struct saa7134_dev *dev); +extern int saa7134_board_init1(struct saa7134_dev *dev); +extern int saa7134_board_init2(struct saa7134_dev *dev); /* ----------------------------------------------------------- */ @@ -501,11 +542,16 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status); /* ----------------------------------------------------------- */ /* saa7134-ts.c */ -extern struct video_device saa7134_ts_template; +#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ + +extern struct videobuf_queue_ops saa7134_ts_qops; + int saa7134_ts_init1(struct saa7134_dev *dev); int saa7134_ts_fini(struct saa7134_dev *dev); void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status); +int saa7134_ts_register(struct saa7134_mpeg_ops *ops); +void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); /* ----------------------------------------------------------- */ /* saa7134-vbi.c */ diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h index e131ca212..f305ec802 100644 --- a/drivers/media/video/saa7146.h +++ b/drivers/media/video/saa7146.h @@ -78,7 +78,7 @@ struct saa7146 unsigned char boardcfg[64]; /* 64 bytes of config from eeprom */ unsigned long saa7146_adr; /* bus address of IO mem from PCI BIOS */ struct saa7146_window win; - unsigned char *saa7146_mem; /* pointer to mapped IO memory */ + unsigned char __iomem *saa7146_mem; /* pointer to mapped IO memory */ struct device_open open_data[MAX_OPENS]; #define MAX_MARKS 16 /* for a/v sync */ @@ -95,10 +95,10 @@ struct saa7146 #endif #ifdef _ALPHA_SAA7146 -#define saawrite(dat,adr) writel((dat),(char *) (saa->saa7146_adr+(adr))) +#define saawrite(dat,adr) writel((dat), saa->saa7146_adr+(adr)) #define saaread(adr) readl(saa->saa7146_adr+(adr)) #else -#define saawrite(dat,adr) writel((dat), (char *) (saa->saa7146_mem+(adr))) +#define saawrite(dat,adr) writel((dat), saa->saa7146_mem+(adr)) #define saaread(adr) readl(saa->saa7146_mem+(adr)) #endif diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 4365d9485..de47c94d9 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -1,8 +1,8 @@ /* * For the STS-Thompson TDA7432 audio processor chip - * + * * Handles audio functions: volume, balance, tone, loudness - * This driver will not complain if used with any + * This driver will not complain if used with any * other i2c device with the same address. * * Muting and tone control by Jonathan Isom @@ -106,7 +106,7 @@ static struct i2c_client client_template; * output (for front and rear). Since most vidcap cards probably * don't have 4 channel output, this driver will set front & rear * together (no independent control). - */ + */ /* Subaddresses for TDA7432 */ @@ -132,13 +132,13 @@ static struct i2c_client client_template; * 0x03 - Mute (Using Attenuators Plays better with modules) * Mono probably isn't used - I'm guessing only the stereo * input is connected on most cards, so we'll set it to stereo. - * + * * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut * Bit 4 controls bass range: 0/1 is extended/standard bass range - * + * * Highest 3 bits not used */ - + #define TDA7432_STEREO_IN 0 #define TDA7432_MONO_IN 2 /* Probably won't be used */ #define TDA7432_BASS_SYM 1 << 3 @@ -161,7 +161,7 @@ static struct i2c_client client_template; #define TDA7432_LD_ON 1 << 7 -/* Subaddress 0x02 - Tone control */ +/* Subaddress 0x02 - Tone control */ /* Bits 0,1,2 control absolute treble gain from 0dB to 14dB * 0x0 is 14dB, 0x7 is 0dB @@ -173,23 +173,23 @@ static struct i2c_client client_template; * Bits 4,5,6 control absolute bass gain from 0dB to 14dB * (This is only true for normal base range, set in 0x00) * 0x0 << 4 is 14dB, 0x7 is 0dB - * + * * Bit 7 controls bass attenuation/gain (sign) * 1 << 7 = gain (+) - * 0 << 7 = attenuation (-) + * 0 << 7 = attenuation (-) * * Example: * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble */ -#define TDA7432_TREBLE_0DB 0xf +#define TDA7432_TREBLE_0DB 0xf #define TDA7432_TREBLE 7 #define TDA7432_TREBLE_GAIN 1 << 3 #define TDA7432_BASS_0DB 0xf #define TDA7432_BASS 7 << 4 #define TDA7432_BASS_GAIN 1 << 7 - + /* Subaddress 0x03 - Left Front attenuation */ /* Subaddress 0x04 - Left Rear attenuation */ /* Subaddress 0x05 - Right Front attenuation */ @@ -202,7 +202,7 @@ static struct i2c_client client_template; * 0x1f is -37.5dB * * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) - * We'll use the mute on the input, though (above) + * We'll use the mute on the input, though (above) * Bits 6,7 unused */ @@ -223,8 +223,8 @@ static struct i2c_client client_template; * * Bits 5,6,7 unused */ - - + + /* Begin code */ @@ -253,7 +253,7 @@ static int tda7432_read(struct i2c_client *client) printk(KERN_WARNING "tda7432: I/O error, trying (read)\n"); return -1; } - dprintk("tda7432: Read 0x%02x\n", buffer); + dprintk("tda7432: Read 0x%02x\n", buffer); return buffer; } #endif @@ -263,8 +263,8 @@ static int tda7432_set(struct i2c_client *client) struct tda7432 *t = i2c_get_clientdata(client); unsigned char buf[16]; d2printk("tda7432: In tda7432_set\n"); - - dprintk(KERN_INFO + + dprintk(KERN_INFO "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud); buf[0] = TDA7432_IN; @@ -292,10 +292,10 @@ static void do_tda7432_init(struct i2c_client *client) t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ TDA7432_BASS_SYM | /* Symmetric bass cut */ - TDA7432_BASS_NORM; /* Normal bass range */ + TDA7432_BASS_NORM; /* Normal bass range */ t->volume = 0x3b ; /* -27dB Volume */ if (loudness) /* Turn loudness on? */ - t->volume |= TDA7432_LD_ON; + t->volume |= TDA7432_LD_ON; t->muted = VIDEO_AUDIO_MUTE; t->treble = TDA7432_TREBLE_0DB; /* 0dB Treble */ t->bass = TDA7432_BASS_0DB; /* 0dB Bass */ @@ -328,7 +328,7 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) client->adapter = adap; client->addr = addr; i2c_set_clientdata(client, t); - + do_tda7432_init(client); printk(KERN_INFO "tda7432: init\n"); @@ -354,7 +354,7 @@ static int tda7432_detach(struct i2c_client *client) do_tda7432_init(client); i2c_detach_client(client); - + kfree(t); return 0; } @@ -369,7 +369,7 @@ static int tda7432_command(struct i2c_client *client, /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ - + /* Query card - scale from TDA7432 settings to V4L settings */ case VIDIOCGAUDIO: { @@ -385,7 +385,7 @@ static int tda7432_command(struct i2c_client *client, va->mode |= VIDEO_SOUND_STEREO; /* Master volume control * V4L volume is min 0, max 65535 - * TDA7432 Volume: + * TDA7432 Volume: * Min (-79dB) is 0x6f * Max (+20dB) is 0x07 (630) * Max (0dB) is 0x20 (829) @@ -396,7 +396,7 @@ static int tda7432_command(struct i2c_client *client, } else { /* max 0db */ va->volume = ( 0x6f - (t->volume & 0x7F) ) * 829; } - + /* Balance depends on L,R attenuation * V4L balance is 0 to 65535, middle is 32768 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f @@ -404,15 +404,15 @@ static int tda7432_command(struct i2c_client *client, * attenuation exists for lf, lr, rf, rr * we use only lf and rf (front channels) */ - + if ( (t->lf) < (t->rf) ) /* right is attenuated, balance shifted left */ va->balance = (32768 - 1057*(t->rf)); else /* left is attenuated, balance shifted right */ va->balance = (32768 + 1057*(t->lf)); - - /* Bass/treble 4 bits each */ + + /* Bass/treble 4 bits each */ va->bass=t->bass; if(va->bass >= 0x8) va->bass = ~(va->bass - 0x8) & 0xf; @@ -421,7 +421,7 @@ static int tda7432_command(struct i2c_client *client, if(va->treble >= 0x8) va->treble = ~(va->treble - 0x8) & 0xf; va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble); - + break; /* VIDIOCGAUDIO case */ } @@ -437,13 +437,13 @@ static int tda7432_command(struct i2c_client *client, } else { /* max 0db */ t->volume = 0x6f - ((va->volume)/829); } - + if (loudness) /* Turn on the loudness bit */ t->volume |= TDA7432_LD_ON; - + tda7432_write(client,TDA7432_VL, t->volume); } - + if(va->flags & VIDEO_AUDIO_BASS) { t->bass = va->bass >> 12; @@ -458,15 +458,15 @@ static int tda7432_command(struct i2c_client *client, } if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS)) tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble ); - + if(va->flags & VIDEO_AUDIO_BALANCE) { - if (va->balance < 32768) + if (va->balance < 32768) { /* shifted to left, attenuate right */ t->rr = (32768 - va->balance)/1057; t->rf = t->rr; t->lr = TDA7432_ATTEN_0DB; - t->lf = TDA7432_ATTEN_0DB; + t->lf = TDA7432_ATTEN_0DB; } else if(va->balance > 32769) { @@ -474,22 +474,22 @@ static int tda7432_command(struct i2c_client *client, t->lf = (va->balance - 32768)/1057; t->lr = t->lf; t->rr = TDA7432_ATTEN_0DB; - t->rf = TDA7432_ATTEN_0DB; + t->rf = TDA7432_ATTEN_0DB; } - else + else { - /* centered */ + /* centered */ t->rr = TDA7432_ATTEN_0DB; t->rf = TDA7432_ATTEN_0DB; t->lf = TDA7432_ATTEN_0DB; t->lr = TDA7432_ATTEN_0DB; } } - - t->muted=(va->flags & VIDEO_AUDIO_MUTE); + + t->muted=(va->flags & VIDEO_AUDIO_MUTE); if (t->muted) { - /* Mute & update balance*/ + /* Mute & update balance*/ tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE); tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE); tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE); @@ -500,7 +500,7 @@ static int tda7432_command(struct i2c_client *client, tda7432_write(client,TDA7432_RF, t->rf); tda7432_write(client,TDA7432_RR, t->rr); } - + break; } /* end of VIDEOCSAUDIO case */ @@ -529,20 +529,20 @@ static struct i2c_client client_template = { I2C_DEVNAME("tda7432"), .id = -1, - .driver = &driver, + .driver = &driver, }; -static int tda7432_init(void) +static int __init tda7432_init(void) { if ( (loudness < 0) || (loudness > 15) ) { printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n"); return -EINVAL; } - i2c_add_driver(&driver); - return 0; + + return i2c_add_driver(&driver); } -static void tda7432_fini(void) +static void __exit tda7432_fini(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index fd8ac116c..c0438989d 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -1,5 +1,5 @@ /* - tda9840.h - i2c-driver for the tda9840 by SGS Thomson + tda9840 - i2c-driver for the tda9840 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold @@ -8,7 +8,7 @@ For detailed informations download the specifications directly from SGS Thomson at http://www.st.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 @@ -22,21 +22,19 @@ 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. - */ + */ -#include #include -#include -#include -#include +#include #include -#include #include "tda9840.h" -static int debug = 0; /* insmod parameter */ -MODULE_PARM(debug,"i"); -#define dprintk if (debug) printk +static int debug = 0; /* insmod parameter */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); +#define dprintk(args...) \ + do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0) #define SWITCH 0x00 #define LEVEL_ADJUST 0x02 @@ -44,168 +42,146 @@ MODULE_PARM(debug,"i"); #define TEST 0x04 /* addresses to scan, found only at 0x42 (7-Bit) */ -static unsigned short normal_i2c[] = {I2C_TDA9840, I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; +static struct i2c_driver driver; +static struct i2c_client client_template; + /* unique ID allocation */ static int tda9840_id = 0; -static struct i2c_driver driver; - -static int tda9840_command(struct i2c_client *client, unsigned int cmd, void* arg) +static int command(struct i2c_client *client, unsigned int cmd, void *arg) { - int result = 0; + int result; + int byte = *(int *)arg; switch (cmd) { - case TDA9840_SWITCH: - { - int byte = *(int*)arg; - - dprintk("tda9840.o: TDA9840_SWITCH: 0x%02x\n",byte); - - if ( byte != TDA9840_SET_MONO - && byte != TDA9840_SET_MUTE - && byte != TDA9840_SET_STEREO - && byte != TDA9840_SET_LANG1 - && byte != TDA9840_SET_LANG2 - && byte != TDA9840_SET_BOTH - && byte != TDA9840_SET_BOTH_R - && byte != TDA9840_SET_EXTERNAL ) { - return -EINVAL; - } - - if ( 0 != (result = i2c_smbus_write_byte_data(client, SWITCH, byte))) { - printk("tda9840.o: TDA9840_SWITCH error.\n"); - return -EFAULT; - } - - return 0; + case TDA9840_SWITCH: + + dprintk("TDA9840_SWITCH: 0x%02x\n", byte); + + if (byte != TDA9840_SET_MONO + && byte != TDA9840_SET_MUTE + && byte != TDA9840_SET_STEREO + && byte != TDA9840_SET_LANG1 + && byte != TDA9840_SET_LANG2 + && byte != TDA9840_SET_BOTH + && byte != TDA9840_SET_BOTH_R + && byte != TDA9840_SET_EXTERNAL) { + return -EINVAL; } - case TDA9840_LEVEL_ADJUST: - { - int byte = *(int*)arg; - - dprintk("tda9840.o: TDA9840_LEVEL_ADJUST: %d\n",byte); - - /* check for correct range */ - if ( byte > 25 || byte < -20 ) - return -EINVAL; - - /* calculate actual value to set, see specs, page 18 */ - byte /= 5; - if ( 0 < byte ) - byte += 0x8; - else - byte = -byte; - - if ( 0 != (result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte))) { - printk("tda9840.o: TDA9840_LEVEL_ADJUST error.\n"); - return -EFAULT; - } - - return 0; - } + result = i2c_smbus_write_byte_data(client, SWITCH, byte); + if (result) + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + break; - case TDA9840_STEREO_ADJUST: - { - int byte = *(int*)arg; - - dprintk("tda9840.o: TDA9840_STEREO_ADJUST: %d\n",byte); - - /* check for correct range */ - if ( byte > 25 || byte < -24 ) - return -EINVAL; - - /* calculate actual value to set */ - byte /= 5; - if ( 0 < byte ) - byte += 0x20; - else - byte = -byte; - - if ( 0 != (result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte))) { - printk("tda9840.o: TDA9840_STEREO_ADJUST error.\n"); - return -EFAULT; - } - - return 0; - } + case TDA9840_LEVEL_ADJUST: - case TDA9840_DETECT: - { - int byte = 0x0; + dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte); - if ( -1 == (byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST))) { - printk("tda9840.o: TDA9840_DETECT error while reading.\n"); - return -EFAULT; - } + /* check for correct range */ + if (byte > 25 || byte < -20) + return -EINVAL; - if( 0 != (byte & 0x80)) { - dprintk("tda9840.o: TDA9840_DETECT, register contents invalid.\n"); - return -EFAULT; - } + /* calculate actual value to set, see specs, page 18 */ + byte /= 5; + if (0 < byte) + byte += 0x8; + else + byte = -byte; - dprintk("tda9840.o: TDA9840_DETECT, result: 0x%02x (original byte)\n",byte); + result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte); + if (result) + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + break; - return ((byte & 0x60) >> 5); - } + case TDA9840_STEREO_ADJUST: + + dprintk("TDA9840_STEREO_ADJUST: %d\n", byte); - case TDA9840_TEST: - { - int byte = *(int*)arg; + /* check for correct range */ + if (byte > 25 || byte < -24) + return -EINVAL; - dprintk("tda9840.o: TDA9840_TEST: 0x%02x\n",byte); + /* calculate actual value to set */ + byte /= 5; + if (0 < byte) + byte += 0x20; + else + byte = -byte; - /* mask out irrelevant bits */ - byte &= 0x3; + result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte); + if (result) + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + break; - if ( 0 != (result = i2c_smbus_write_byte_data(client, TEST, byte))) { - printk("tda9840.o: TDA9840_TEST error.\n"); - return -EFAULT; - } - - return 0; + case TDA9840_DETECT: + + byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST); + if (byte == -1) { + dprintk("i2c_smbus_read_byte_data() failed\n"); + return -EIO; } - default: - return -ENOIOCTLCMD; + if (0 != (byte & 0x80)) { + dprintk("TDA9840_DETECT: register contents invalid\n"); + return -EINVAL; + } + + dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte); + return ((byte & 0x60) >> 5); + + case TDA9840_TEST: + dprintk("TDA9840_TEST: 0x%02x\n", byte); + + /* mask out irrelevant bits */ + byte &= 0x3; + + result = i2c_smbus_write_byte_data(client, TEST, byte); + if (result) + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); + break; + default: + return -ENOIOCTLCMD; } + if (result) + return -EIO; + return 0; } -static int tda9840_detect(struct i2c_adapter *adapter, int address, int kind) +static int detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *client; + struct i2c_client *client; int result = 0; int byte = 0x0; - + /* let's see whether this adapter can support what we need */ - if ( 0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA|I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + if (0 == i2c_check_functionality(adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA | + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { return 0; } /* allocate memory for client structure */ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (0 == client) { - printk("tda9840.o: not enough kernel memory.\n"); + if (0 == client) { + printk("not enough kernel memory\n"); return -ENOMEM; } - memset(client, 0, sizeof(struct i2c_client)); - + /* fill client structure */ - sprintf(client->name,"tda9840 (0x%02x)", address); + memcpy(client, &client_template, sizeof(struct i2c_client)); client->id = tda9840_id++; - client->flags = 0; client->addr = address; client->adapter = adapter; - client->driver = &driver; - i2c_set_clientdata(client, NULL); /* tell the i2c layer a new client has arrived */ if (0 != (result = i2c_attach_client(client))) { @@ -215,71 +191,64 @@ static int tda9840_detect(struct i2c_adapter *adapter, int address, int kind) /* set initial values for level & stereo - adjustment, mode */ byte = 0; - if ( 0 != (result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte))) { - printk("tda9840.o: could not initialize ic #1. continuing anyway. (result:%d)\n",result); - } - - if ( 0 != (result = tda9840_command(client, TDA9840_STEREO_ADJUST, &byte))) { - printk("tda9840.o: could not initialize ic #2. continuing anyway. (result:%d)\n",result); - } - + result = command(client, TDA9840_LEVEL_ADJUST, &byte); + result += command(client, TDA9840_STEREO_ADJUST, &byte); byte = TDA9840_SET_MONO; - if ( 0 != (result = tda9840_command(client, TDA9840_SWITCH, &byte))) { - printk("tda9840.o: could not initialize ic #3. continuing anyway. (result:%d)\n",result); - } - - printk("tda9840.o: detected @ 0x%02x on adapter %s\n",2*address,&client->adapter->name[0]); + result = command(client, TDA9840_SWITCH, &byte); + if (result) { + dprintk("could not initialize tda9840\n"); + return -ENODEV; + } + printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); return 0; } -static int tda9840_attach(struct i2c_adapter *adapter) +static int attach(struct i2c_adapter *adapter) { /* let's see whether this is a know adapter we can attach to */ - if( adapter->id != I2C_ALGO_SAA7146 ) { - dprintk("tda9840.o: refusing to probe on unknown adapter [name='%s',id=0x%x]\n",adapter->name,adapter->id); + if (adapter->id != I2C_ALGO_SAA7146) { + dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); return -ENODEV; } - return i2c_probe(adapter,&addr_data,&tda9840_detect); + return i2c_probe(adapter, &addr_data, &detect); } -static int tda9840_detach(struct i2c_client *client) +static int detach(struct i2c_client *client) { - int err = 0; - - if ( 0 != (err = i2c_detach_client(client))) { - printk("tda9840.o: Client deregistration failed, client not detached.\n"); - return err; - } - + int ret = i2c_detach_client(client); kfree(client); - - return 0; + return ret; } static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "tda9840 driver", - .id = I2C_DRIVERID_TDA9840, - .flags = I2C_DF_NOTIFY, - .attach_adapter = tda9840_attach, - .detach_client = tda9840_detach, - .command = tda9840_command, + .owner = THIS_MODULE, + .name = "tda9840", + .id = I2C_DRIVERID_TDA9840, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach, + .detach_client = detach, + .command = command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("tda9840"), + .driver = &driver, }; -static int __init tda9840_init_module(void) +static int __init this_module_init(void) { - return i2c_add_driver(&driver); + return i2c_add_driver(&driver); } -static void __exit tda9840_cleanup_module(void) +static void __exit this_module_exit(void) { - i2c_del_driver(&driver); + i2c_del_driver(&driver); } -module_init(tda9840_init_module); -module_exit(tda9840_cleanup_module); +module_init(this_module_init); +module_exit(this_module_exit); MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("tda9840 driver"); diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index ae5fd316f..fe2b03821 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -1,19 +1,19 @@ /* * For the TDA9875 chip - * (The TDA9875 is used on the Diamond DTV2000 french version + * (The TDA9875 is used on the Diamond DTV2000 french version * Other cards probably use these chips as well.) - * This driver will not complain if used with any + * This driver will not complain if used with any * other i2c device with the same address. * * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and - * Eric Sandeen + * Eric Sandeen * This code is placed under the terms of the GNU General Public License * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Which was based on tda8425.c by Greg Alexander (c) 1998 * * OPTIONS: * debug - set to 1 if you'd like to see debug messages - * + * * Revision: 0.1 - original version */ @@ -64,7 +64,7 @@ static struct i2c_client client_template; * http://www.semiconductors.philips.com * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator * - */ + */ /* subaddresses for TDA9875 */ #define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ @@ -133,7 +133,7 @@ static int tda9875_read(struct i2c_client *client) printk(KERN_WARNING "tda9875: I/O error, trying (read)\n"); return -1; } - dprintk("Read 0x%02x\n", buffer); + dprintk("Read 0x%02x\n", buffer); return buffer; } #endif @@ -178,7 +178,7 @@ static void tda9875_set(struct i2c_client *client) static void do_tda9875_init(struct i2c_client *client) { struct tda9875 *t = i2c_get_clientdata(client); - dprintk("In tda9875_init\n"); + dprintk("In tda9875_init\n"); tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ @@ -192,7 +192,7 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_FMAT, 0x00 ); /*FM Matrix reg 0x00*/ tda9875_write(client, TDA9875_SC1, 0x00 ); /* SCART 1 (SC1)*/ tda9875_write(client, TDA9875_SC2, 0x01 ); /* SCART 2 (sc2)*/ - + tda9875_write(client, TDA9875_CH1V, 0x10 ); /* Channel volume 1 mute*/ tda9875_write(client, TDA9875_CH2V, 0x10 ); /* Channel volume 2 mute */ tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ @@ -204,14 +204,14 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ tda9875_write(client, TDA9875_MBA, 0x00 ); /* Main Bass Main 0dB*/ tda9875_write(client, TDA9875_MTR, 0x00 ); /* Main Treble Main 0dB*/ - tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ + tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ tda9875_write(client, TDA9875_AVL, 0x00 ); /* Vol Aux left 0dB*/ tda9875_write(client, TDA9875_AVR, 0x00 ); /* Vol Aux right 0dB*/ tda9875_write(client, TDA9875_ABA, 0x00 ); /* Aux Bass Main 0dB*/ tda9875_write(client, TDA9875_ATR, 0x00 ); /* Aux Aigus Main 0dB*/ - + tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ - + t->mode=AUDIO_UNMUTE; t->lvol=t->rvol =0; /* 0dB */ t->bass=0; /* 0dB */ @@ -262,7 +262,7 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) kfree(t); return 1; } - + do_tda9875_init(client); printk(KERN_INFO "tda9875: init\n"); @@ -288,7 +288,7 @@ static int tda9875_detach(struct i2c_client *client) do_tda9875_init(client); i2c_detach_client(client); - + kfree(t); return 0; } @@ -298,9 +298,9 @@ static int tda9875_command(struct i2c_client *client, { struct tda9875 *t = i2c_get_clientdata(client); - dprintk("In tda9875_command...\n"); + dprintk("In tda9875_command...\n"); - switch (cmd) { + switch (cmd) { /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -335,7 +335,7 @@ static int tda9875_command(struct i2c_client *client, struct video_audio *va = arg; int left,right; - dprintk("VIDEOCSAUDIO...\n"); + dprintk("VIDEOCSAUDIO...\n"); left = (min(65536 - va->balance,32768) * va->volume) / 32768; right = (min(va->balance,(__u16)32768) * @@ -357,7 +357,7 @@ static int tda9875_command(struct i2c_client *client, t->bass = 15; if (t->bass < -12) t->bass = -12 & 0xff; - + t->treble = ((va->treble/2700)-12) & 0xff; if (t->treble > 12) t->treble = 12; @@ -367,7 +367,7 @@ static int tda9875_command(struct i2c_client *client, //printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - + tda9875_set(client); @@ -403,13 +403,12 @@ static struct i2c_client client_template = .driver = &driver, }; -static int tda9875_init(void) +static int __init tda9875_init(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void tda9875_fini(void) +static void __exit tda9875_fini(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 9768829bd..98ecffc3e 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -6,8 +6,10 @@ #include #include #include +#include #include +#include #include /* Chips: @@ -34,7 +36,7 @@ I2C_CLIENT_INSMOD; /* insmod options */ static unsigned int debug = 0; -MODULE_PARM(debug,"i"); +module_param(debug, int, 0644); MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ @@ -47,6 +49,7 @@ struct tda9887 { struct i2c_client client; v4l2_std_id std; unsigned int radio; + unsigned int config; unsigned int pinnacle_id; unsigned int using_v4l2; }; @@ -243,6 +246,7 @@ static void dump_read_message(unsigned char *buf) printk(PREFIX "read: 0x%2x\n", buf[0]); printk(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); printk(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); + printk(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); printk(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); printk(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } @@ -374,10 +378,10 @@ static unsigned int port1 = 1; static unsigned int port2 = 1; static unsigned int qss = UNSET; static unsigned int adjust = 0x10; -MODULE_PARM(port1,"i"); -MODULE_PARM(port2,"i"); -MODULE_PARM(qss,"i"); -MODULE_PARM(adjust,"i"); +module_param(port1, int, 0644); +module_param(port2, int, 0644); +module_param(qss, int, 0644); +module_param(adjust, int, 0644); static int tda9887_set_insmod(struct tda9887 *t, char *buf) { @@ -397,6 +401,36 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) return 0; } +static int tda9887_set_config(struct tda9887 *t, char *buf) +{ + if (t->config & TDA9887_PORT1) + buf[1] |= cOutputPort1Inactive; + if (t->config & TDA9887_PORT2) + buf[1] |= cOutputPort2Inactive; + if (t->config & TDA9887_QSS) + buf[1] |= cQSS; + if (t->config & TDA9887_INTERCARRIER) + buf[1] &= ~cQSS; + + if (t->config & TDA9887_AUTOMUTE) + buf[1] |= cAutoMuteFmActive; + if (t->config & TDA9887_DEEMPHASIS_MASK) { + buf[2] &= ~0x60; + switch (t->config & TDA9887_DEEMPHASIS_MASK) { + case TDA9887_DEEMPHASIS_NONE: + buf[2] |= cDeemphasisOFF; + break; + case TDA9887_DEEMPHASIS_50: + buf[2] |= cDeemphasisON | cDeemphasis50; + break; + case TDA9887_DEEMPHASIS_75: + buf[2] |= cDeemphasisON | cDeemphasis75; + break; + } + } + return 0; +} + /* ---------------------------------------------------------------------- */ static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) @@ -427,10 +461,10 @@ static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) /* ---------------------------------------------------------------------- */ -static char *pal = "-"; -MODULE_PARM(pal,"s"); -static char *secam = "-"; -MODULE_PARM(secam,"s"); +static char pal[] = "-"; +module_param_string(pal, pal, 0644, sizeof(pal)); +static char secam[] = "-"; +module_param_string(secam, secam, 0644, sizeof(secam)); static int tda9887_fixup_std(struct tda9887 *t) { @@ -499,8 +533,14 @@ static int tda9887_configure(struct tda9887 *t) if (UNSET != t->pinnacle_id) { tda9887_set_pinnacle(t,buf); } + tda9887_set_config(t,buf); tda9887_set_insmod(t,buf); + if (t->std & V4L2_STD_SECAM_L) { + /* secam fixup (FIXME: move this to tvnorms array?) */ + buf[1] &= ~cOutputPort2Inactive; + } + dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n", buf[1],buf[2],buf[3]); if (debug > 1) @@ -510,8 +550,7 @@ static int tda9887_configure(struct tda9887 *t) printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible(1000); tda9887_status(t); } return 0; @@ -532,11 +571,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - t->std = 0;; + t->std = 0; t->pinnacle_id = UNSET; i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); - + return 0; } @@ -585,7 +624,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) t->radio = 1; tda9887_configure(t); break; - + case AUDC_CONFIG_PINNACLE: { int *i = arg; @@ -594,6 +633,14 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) tda9887_configure(t); break; } + case TDA9887_SET_CONFIG: + { + int *i = arg; + + t->config = *i; + tda9887_configure(t); + break; + } /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -644,6 +691,25 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) t->radio = 1; } tda9887_configure(t); + break; + } + case VIDIOC_G_TUNER: + { + static int AFC_BITS_2_kHz[] = { + -12500, -37500, -62500, -97500, + -112500, -137500, -162500, -187500, + 187500, 162500, 137500, 112500, + 97500 , 62500, 37500 , 12500 + }; + struct v4l2_tuner* tuner = arg; + + if (t->radio) { + __u8 reg = 0; + tuner->afc=0; + if (1 == i2c_master_recv(&t->client,®,1)) + tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; + } + break; } default: /* nothing */ @@ -652,6 +718,22 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } +static int tda9887_suspend(struct device * dev, u32 state, u32 level) +{ + dprintk("tda9887: suspend\n"); + return 0; +} + +static int tda9887_resume(struct device * dev, u32 level) +{ + struct i2c_client *c = container_of(dev, struct i2c_client, dev); + struct tda9887 *t = i2c_get_clientdata(c); + + dprintk("tda9887: resume\n"); + tda9887_configure(t); + return 0; +} + /* ----------------------------------------------------------------------- */ static struct i2c_driver driver = { @@ -662,6 +744,10 @@ static struct i2c_driver driver = { .attach_adapter = tda9887_probe, .detach_client = tda9887_detach, .command = tda9887_command, + .driver = { + .suspend = tda9887_suspend, + .resume = tda9887_resume, + }, }; static struct i2c_client client_template = { @@ -670,13 +756,12 @@ static struct i2c_client client_template = .driver = &driver, }; -static int tda9887_init_module(void) +static int __init tda9887_init_module(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void tda9887_cleanup_module(void) +static void __exit tda9887_cleanup_module(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index fe64e64e3..807fd7ecd 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -1,5 +1,5 @@ /* - tea6415c.h - i2c-driver for the tea6415c by SGS Thomson + tea6415c - i2c-driver for the tea6415c by SGS Thomson Copyright (C) 1998-2003 Michael Hunold @@ -7,10 +7,10 @@ with 8 inputs and 6 outputs. It is cascadable, i.e. it can be found at the addresses 0x86 and 0x06 on the i2c-bus. - + For detailed informations download the specifications directly from SGS Thomson at http://www.st.com - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License vs published by the Free Software Foundation; either version 2 of the License, or @@ -24,61 +24,58 @@ 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 Mvss Ave, Cambridge, MA 02139, USA. - */ + */ -#include #include -#include -#include -#include +#include #include -#include + #include "tea6415c.h" -static int debug = 0; /* insmod parameter */ -MODULE_PARM(debug,"i"); -#define dprintk if (debug) printk +static int debug = 0; /* insmod parameter */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); +#define dprintk(args...) \ + do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0) #define TEA6415C_NUM_INPUTS 8 #define TEA6415C_NUM_OUTPUTS 6 /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ -static unsigned short normal_i2c[] = {I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; static struct i2c_driver driver; +static struct i2c_client client_template; /* unique ID allocation */ static int tea6415c_id = 0; /* this function is called by i2c_probe */ -static int tea6415c_detect(struct i2c_adapter *adapter, int address, int kind) +static int detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *client = NULL; + struct i2c_client *client = NULL; int err = 0; /* let's see whether this adapter can support what we need */ - if ( 0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { + if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { return 0; } /* allocate memory for client structure */ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (0 == client) { + if (0 == client) { return -ENOMEM; } - memset(client, 0, sizeof(struct i2c_client)); /* fill client structure */ - sprintf(client->name,"tea6415c (0x%02x)", address); + memcpy(client, &client_template, sizeof(struct i2c_client)); client->id = tea6415c_id++; - client->flags = 0; client->addr = address; client->adapter = adapter; - client->driver = &driver; /* tell the i2c layer a new client has arrived */ if (0 != (err = i2c_attach_client(client))) { @@ -86,151 +83,145 @@ static int tea6415c_detect(struct i2c_adapter *adapter, int address, int kind) return err; } - printk("tea6415c.o: detected @ 0x%02x on adapter %s\n",2*address,&client->adapter->name[0]); + printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); return 0; } -static int tea6415c_attach(struct i2c_adapter *adapter) +static int attach(struct i2c_adapter *adapter) { /* let's see whether this is a know adapter we can attach to */ - if( adapter->id != I2C_ALGO_SAA7146 ) { - dprintk("tea6415c.o: refusing to probe on unknown adapter [name='%s',id=0x%x]\n",adapter->name,adapter->id); + if (adapter->id != I2C_ALGO_SAA7146) { + dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); return -ENODEV; } - return i2c_probe(adapter,&addr_data,&tea6415c_detect); + return i2c_probe(adapter, &addr_data, &detect); } -static int tea6415c_detach(struct i2c_client *client) +static int detach(struct i2c_client *client) { - int err = 0; - - if ( 0 != (err = i2c_detach_client(client))) { - printk("tea6415c.o: Client deregistration failed, client not detached.\n"); - return err; - } - + int ret = i2c_detach_client(client); kfree(client); - - return 0; + return ret; } /* makes a connection between the input-pin 'i' and the output-pin 'o' for the tea6415c-client 'client' */ -static int tea6415c_switch(struct i2c_client *client, int i, int o) +static int switch_matrix(struct i2c_client *client, int i, int o) { - u8 byte = 0; + u8 byte = 0; + int ret; - dprintk("tea6415c.o: tea6415c_switch: adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); - + dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); + /* check if the pins are valid */ - if ( 0 == (( 1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i ) && - (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o ))) + if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) + && (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o))) return -1; /* to understand this, have a look at the tea6415c-specs (p.5) */ - switch(o) { - case 18: - byte = 0x00; - break; - case 14: - byte = 0x20; - break; - case 16: - byte = 0x10; - break; - case 17: - byte = 0x08; - break; - case 15: - byte = 0x18; - break; - case 13: - byte = 0x28; - break; + switch (o) { + case 18: + byte = 0x00; + break; + case 14: + byte = 0x20; + break; + case 16: + byte = 0x10; + break; + case 17: + byte = 0x08; + break; + case 15: + byte = 0x18; + break; + case 13: + byte = 0x28; + break; }; - - switch(i) { - case 5: - byte |= 0x00; - break; - case 8: - byte |= 0x04; - break; - case 3: - byte |= 0x02; - break; - case 20: - byte |= 0x06; - break; - case 6: - byte |= 0x01; - break; - case 10: - byte |= 0x05; - break; - case 1: - byte |= 0x03; - break; - case 11: - byte |= 0x07; - break; + + switch (i) { + case 5: + byte |= 0x00; + break; + case 8: + byte |= 0x04; + break; + case 3: + byte |= 0x02; + break; + case 20: + byte |= 0x06; + break; + case 6: + byte |= 0x01; + break; + case 10: + byte |= 0x05; + break; + case 1: + byte |= 0x03; + break; + case 11: + byte |= 0x07; + break; }; - if ( 0 != i2c_smbus_write_byte(client,byte)) { - dprintk("tea6415c.o: tea6415c_switch: could not write to tea6415c\n"); - return -1; + ret = i2c_smbus_write_byte(client, byte); + if (ret) { + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); + return -EIO; } - return 0; + return ret; } -static int tea6415c_command(struct i2c_client *client, unsigned int cmd, void* arg) +static int command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tea6415c_multiplex *v = (struct tea6415c_multiplex*)arg; + struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; int result = 0; switch (cmd) { - case TEA6415C_SWITCH: { - result = tea6415c_switch(client,v->in,v->out); - break; - } - default: { - return -ENOIOCTLCMD; - } + case TEA6415C_SWITCH: + result = switch_matrix(client, v->in, v->out); + break; + default: + return -ENOIOCTLCMD; } - if ( 0 != result ) - return result; - - return 0; + return result; } static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "tea6415c driver", - .id = I2C_DRIVERID_TEA6415C, - .flags = I2C_DF_NOTIFY, - .attach_adapter = tea6415c_attach, - .detach_client = tea6415c_detach, - .command = tea6415c_command, + .owner = THIS_MODULE, + .name = "tea6415c", + .id = I2C_DRIVERID_TEA6415C, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach, + .detach_client = detach, + .command = command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("tea6415c"), + .driver = &driver, }; -static int __init tea6415c_init_module(void) +static int __init this_module_init(void) { return i2c_add_driver(&driver); } -static void __exit tea6415c_cleanup_module(void) +static void __exit this_module_exit(void) { - i2c_del_driver(&driver); + i2c_del_driver(&driver); } -module_init(tea6415c_init_module); -module_exit(tea6415c_cleanup_module); +module_init(this_module_init); +module_exit(this_module_exit); MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("tea6415c driver"); MODULE_LICENSE("GPL"); - diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 93acdc635..f46b21964 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -1,5 +1,5 @@ /* - tea6420.o - i2c-driver for the tea6420 by SGS Thomson + tea6420 - i2c-driver for the tea6420 by SGS Thomson Copyright (C) 1998-2003 Michael Hunold @@ -7,10 +7,10 @@ 4 stereo outputs and gain control for each output. It is cascadable, i.e. it can be found at the adresses 0x98 and 0x9a on the i2c-bus. - + For detailed informations download the specifications directly from SGS Thomson at http://www.st.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 @@ -24,30 +24,29 @@ 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. - */ + */ -#include #include -#include -#include -#include +#include #include -#include #include "tea6420.h" -static int debug = 0; /* insmod parameter */ -MODULE_PARM(debug,"i"); -#define dprintk if (debug) printk +static int debug = 0; /* insmod parameter */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); +#define dprintk(args...) \ + do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0) /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ -static unsigned short normal_i2c[] = {I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; /* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; static struct i2c_driver driver; +static struct i2c_client client_template; /* unique ID allocation */ static int tea6420_id = 0; @@ -56,39 +55,37 @@ static int tea6420_id = 0; with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) { - u8 byte = 0; - - int result = 0; - - dprintk("tea6420.o: tea6420_switch: adr:0x%02x, i:%d, o:%d, g:%d\n",client->addr,i,o,g); + u8 byte = 0; + int ret; + + dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g); /* check if the paramters are valid */ - if ( i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g%2 != 0 ) + if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) return -1; - byte = ((o-1)<<5); - byte |= (i-1); + byte = ((o - 1) << 5); + byte |= (i - 1); /* to understand this, have a look at the tea6420-specs (p.5) */ - switch(g) { - case 0: - byte |= (3<<3); - break; - case 2: - byte |= (2<<3); - break; - case 4: - byte |= (1<<3); - break; - case 6: - break; + switch (g) { + case 0: + byte |= (3 << 3); + break; + case 2: + byte |= (2 << 3); + break; + case 4: + byte |= (1 << 3); + break; + case 6: + break; } - /* fixme?: 1 != ... => 0 != */ - if ( 0 != (result = i2c_smbus_write_byte(client,byte))) { - printk("tea6402:%d\n",result); - dprintk(KERN_ERR "tea6420.o: could not switch, result:%d\n",result); - return -EFAULT; + ret = i2c_smbus_write_byte(client, byte); + if (ret) { + dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); + return -EIO; } return 0; @@ -97,29 +94,26 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) /* this function is called by i2c_probe */ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) { - struct i2c_client *client; + struct i2c_client *client; int err = 0, i = 0; /* let's see whether this adapter can support what we need */ - if ( 0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { + if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { return 0; } /* allocate memory for client structure */ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (0 == client) { + if (0 == client) { return -ENOMEM; } - memset(client, 0x0, sizeof(struct i2c_client)); + memset(client, 0x0, sizeof(struct i2c_client)); /* fill client structure */ - sprintf(client->name,"tea6420 (0x%02x)", address); + memcpy(client, &client_template, sizeof(struct i2c_client)); client->id = tea6420_id++; - client->flags = 0; client->addr = address; client->adapter = adapter; - client->driver = &driver; - i2c_set_clientdata(client, NULL); /* tell the i2c layer a new client has arrived */ if (0 != (err = i2c_attach_client(client))) { @@ -129,86 +123,81 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) /* set initial values: set "mute"-input to all outputs at gain 0 */ err = 0; - for(i = 1; i < 5; i++) { + for (i = 1; i < 5; i++) { err += tea6420_switch(client, 6, i, 0); } - if( 0 != err) { - printk("tea6420.o: could not initialize chipset. continuing anyway.\n"); + if (err) { + dprintk("could not initialize tea6420\n"); + kfree(client); + return -ENODEV; } - - printk("tea6420.o: detected @ 0x%02x on adapter %s\n",2*address,&client->adapter->name[0]); + + printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); return 0; } -static int tea6420_attach(struct i2c_adapter *adapter) +static int attach(struct i2c_adapter *adapter) { /* let's see whether this is a know adapter we can attach to */ - if( adapter->id != I2C_ALGO_SAA7146 ) { - dprintk("tea6420.o: refusing to probe on unknown adapter [name='%s',id=0x%x]\n",adapter->name,adapter->id); + if (adapter->id != I2C_ALGO_SAA7146) { + dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); return -ENODEV; } - return i2c_probe(adapter,&addr_data,&tea6420_detect); + return i2c_probe(adapter, &addr_data, &tea6420_detect); } -static int tea6420_detach(struct i2c_client *client) +static int detach(struct i2c_client *client) { - int err = 0; - - if ( 0 != (err = i2c_detach_client(client))) { - printk("tea6420.o: Client deregistration failed, client not detached.\n"); - return err; - } - + int ret = i2c_detach_client(client); kfree(client); - - return 0; + return ret; } -static int tea6420_command(struct i2c_client *client, unsigned int cmd, void* arg) +static int command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct tea6420_multiplex *a = (struct tea6420_multiplex*)arg; + struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; int result = 0; switch (cmd) { - case TEA6420_SWITCH: { - result = tea6420_switch(client,a->in,a->out,a->gain); - break; - } - default: { - return -ENOIOCTLCMD; - } + case TEA6420_SWITCH: + result = tea6420_switch(client, a->in, a->out, a->gain); + break; + default: + return -ENOIOCTLCMD; } - if ( 0 != result ) - return result; - - return 0; + return result; } static struct i2c_driver driver = { - .owner = THIS_MODULE, - .name = "tea6420 driver", - .id = I2C_DRIVERID_TEA6420, - .flags = I2C_DF_NOTIFY, - .attach_adapter = tea6420_attach, - .detach_client = tea6420_detach, - .command = tea6420_command, + .owner = THIS_MODULE, + .name = "tea6420", + .id = I2C_DRIVERID_TEA6420, + .flags = I2C_DF_NOTIFY, + .attach_adapter = attach, + .detach_client = detach, + .command = command, +}; + +static struct i2c_client client_template = { + I2C_DEVNAME("tea6420"), + .driver = &driver, }; -static int __init tea6420_init_module(void) +static int __init this_module_init(void) { return i2c_add_driver(&driver); } -static void __exit tea6420_cleanup_module(void) +static void __exit this_module_exit(void) { - i2c_del_driver(&driver); + i2c_del_driver(&driver); } -module_init(tea6420_init_module); -module_exit(tea6420_cleanup_module); +module_init(this_module_init); +module_exit(this_module_exit); MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("tea6420 driver"); diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c index 18e1118df..ec6eb43ca 100644 --- a/drivers/media/video/tuner.c +++ b/drivers/media/video/tuner.c @@ -1,4 +1,9 @@ +/* + * $Id: tuner.c,v 1.31 2004/11/10 11:07:24 kraxel Exp $ + */ + #include +#include #include #include #include @@ -15,30 +20,34 @@ #include #include -/* Addresses to scan */ +#define UNSET (-1U) + +/* standard i2c insmod options */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END}; I2C_CLIENT_INSMOD; -#define UNSET (-1U) - -/* insmod options */ -static unsigned int debug = 0; +/* insmod options used at init time => read/only */ static unsigned int type = UNSET; static unsigned int addr = 0; +module_param(type, int, 0444); +module_param(addr, int, 0444); + +/* insmod options used at runtime => read/write */ +static unsigned int debug = 0; +static unsigned int tv_antenna = 1; +static unsigned int radio_antenna = 0; +static unsigned int optimize_vco = 1; +module_param(debug, int, 0644); +module_param(tv_antenna, int, 0644); +module_param(radio_antenna, int, 0644); +module_param(optimize_vco, int, 0644); + static unsigned int tv_range[2] = { 44, 958 }; static unsigned int radio_range[2] = { 65, 108 }; -static unsigned int tv_antenna = 1; -static unsigned int radio_antenna = 0; -MODULE_PARM(debug,"i"); -MODULE_PARM(type,"i"); -MODULE_PARM(addr,"i"); -MODULE_PARM(tv_range,"2i"); -MODULE_PARM(radio_range,"2i"); -MODULE_PARM(tv_antenna,"i"); -MODULE_PARM(radio_antenna,"i"); -#define optimize_vco 1 +module_param_array(tv_range, int, NULL, 0644); +module_param_array(radio_range, int, NULL, 0644); MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); @@ -52,10 +61,10 @@ struct tuner { unsigned int freq; /* keep track of the current settings */ v4l2_std_id std; int using_v4l2; - + unsigned int radio; unsigned int input; - + // only for MT2032 unsigned int xogc; unsigned int radio_if2; @@ -71,11 +80,11 @@ static struct i2c_client client_template; /* tv standard selection for Temic 4046 FM5 this value takes the low bits of control byte 2 - from datasheet Rev.01, Feb.00 + from datasheet Rev.01, Feb.00 standard BG I L L2 D picture IF 38.9 38.9 38.9 33.95 38.9 sound 1 33.4 32.9 32.4 40.45 32.4 - sound 2 33.16 + sound 2 33.16 NICAM 33.05 32.348 33.05 33.05 */ #define TEMIC_SET_PAL_I 0x05 @@ -97,7 +106,7 @@ static struct i2c_client client_template; #define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/ #define PHILIPS_SET_PAL_BGDK 0x09 #define PHILIPS_SET_PAL_L2 0x0a -#define PHILIPS_SET_PAL_L 0x0b +#define PHILIPS_SET_PAL_L 0x0b /* system switching for Philips FI1216MF MK2 from datasheet "1996 Jul 09", @@ -115,21 +124,22 @@ static struct i2c_client client_template; /* ---------------------------------------------------------------------- */ -struct tunertype +struct tunertype { char *name; unsigned char Vendor; unsigned char Type; - + unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */ unsigned short thresh2; /* band switch VHF_HI <=> UHF */ unsigned char VHF_L; unsigned char VHF_H; unsigned char UHF; - unsigned char config; - unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, - 732 =16*45.75 NTSCi, - 940 =58.75 NTSC-Japan */ + unsigned char config; + unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, + 732 =16*45.75 NTSCi, + 940 =16*58.75 NTSC-Japan + 704 =16*44 ATSC */ }; /* @@ -170,7 +180,7 @@ static struct tunertype tuners[] = { { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, { "Temic PAL_BG (4006FH5)", TEMIC, PAL, - 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, + 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, { "Alps TSCH6",Alps,NTSC, 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, @@ -208,7 +218,7 @@ static struct tunertype tuners[] = { { "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL, 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ - 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,732 }, // Corrected to NTSC=732 (was:940) + 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, @@ -229,7 +239,7 @@ static struct tunertype tuners[] = { 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, { "HITACHI V7-J180AT", HITACHI, NTSC, - 16*170.00, 16*450.00, 0x01,0x02,0x00,0x8e,940 }, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 }, { "Philips PAL_MK (FI1216 MK)", Philips, PAL, 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC, @@ -241,6 +251,19 @@ static struct tunertype tuners[] = { 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, { "Microtune 4049 FM5",Microtune,PAL, 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, + { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, + 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, + { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, + + { "Tenna TNF 8831 BGFF)", Philips, PAL, + 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, + { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, + 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, + { "TCL 2002N", TCL, NTSC, + 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, + { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, }; #define TUNERS ARRAY_SIZE(tuners) @@ -409,7 +432,7 @@ static int mt2032_compute_freq(unsigned int rfin, if(rfin >400*1000*1000) buf[6]=0xe4; else - buf[6]=0xf4; // set PKEN per rev 1.2 + buf[6]=0xf4; // set PKEN per rev 1.2 buf[7]=8+xogc; buf[8]=0xc3; //reserved buf[9]=0x4e; //reserved @@ -430,10 +453,10 @@ static int mt2032_check_lo_lock(struct i2c_client *c) i2c_master_recv(c,buf,1); dprintk("mt2032 Reg.E=0x%02x\n",buf[0]); lock=buf[0] &0x06; - + if (lock==6) break; - + dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } @@ -455,7 +478,7 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) if(tad1 ==1) return lock; if(tad1==2) { - if(sel==0) + if(sel==0) return lock; else sel--; } @@ -508,13 +531,13 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, // wait for PLLs to lock (per manual), retry LINT if not. for(lint_try=0; lint_try<2; lint_try++) { lock=mt2032_check_lo_lock(c); - + if(optimize_vco) lock=mt2032_optimize_vco(c,sel,lock); if(lock==6) break; - - printk("mt2032: re-init PLLs by LINT\n"); - buf[0]=7; + + printk("mt2032: re-init PLLs by LINT\n"); + buf[0]=7; buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs i2c_master_send(c,buf,2); mdelay(10); @@ -639,46 +662,46 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; int ret; unsigned char buf[6]; - + dprintk("mt2050_set_if_freq freq=%d\n",freq); - + f_lo1=freq+if1; f_lo1=(f_lo1/1000000)*1000000; - + f_lo2=f_lo1-freq-if2; f_lo2=(f_lo2/50000)*50000; - + lo1=f_lo1/4000000; lo2=f_lo2/4000000; - + f_lo1_modulo= f_lo1-(lo1*4000000); f_lo2_modulo= f_lo2-(lo2*4000000); - + num1=4*f_lo1_modulo/4000000; num2=4096*(f_lo2_modulo/1000)/4000; - + // todo spurchecks - + div1a=(lo1/12)-1; div1b=lo1-(div1a+1)*12; - + div2a=(lo2/8)-1; div2b=lo2-(div2a+1)*8; - + dprintk("lo1 lo2 = %d %d\n", lo1, lo2); dprintk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b); - - + + buf[0]=1; buf[1]= 4*div1b + num1; if(freq<275*1000*1000) buf[1] = buf[1]|0x80; - + buf[2]=div1a; buf[3]=32*div2b + num2/256; buf[4]=num2-(num2/256)*256; buf[5]=div2a; if(num2!=0) buf[5]=buf[5]|0x40; - + if(debug) { int i; printk("bufs is: "); @@ -686,7 +709,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned printk("%x ",buf[i]); printk("\n"); } - + ret=i2c_master_send(c,buf,6); if (ret!=6) printk("mt2050_set_if_freq failed with %d\n",ret); @@ -696,7 +719,7 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); unsigned int if2; - + if (t->std & V4L2_STD_525_60) { // NTSC if2 = 45750*1000; @@ -712,7 +735,7 @@ static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); int if2 = t->radio_if2; - + mt2050_set_if_freq(c, freq*62500, if2); mt2050_set_antenna(c, radio_antenna); } @@ -722,19 +745,19 @@ static int mt2050_init(struct i2c_client *c) struct tuner *t = i2c_get_clientdata(c); unsigned char buf[2]; int ret; - + buf[0]=6; buf[1]=0x10; ret=i2c_master_send(c,buf,2); // power - + buf[0]=0x0f; buf[1]=0x0f; ret=i2c_master_send(c,buf,2); // m1lo - + buf[0]=0x0d; ret=i2c_master_send(c,buf,1); i2c_master_recv(c,buf,1); - + dprintk("mt2050: sro is %x\n",buf[0]); t->tv_freq = mt2050_set_tv_freq; t->radio_freq = mt2050_set_radio_freq; @@ -747,7 +770,7 @@ static int microtune_init(struct i2c_client *c) char *name; unsigned char buf[21]; int company_code; - + memset(buf,0,sizeof(buf)); t->tv_freq = NULL; t->radio_freq = NULL; @@ -816,13 +839,17 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) unsigned char buffer[4]; int rc; - tun=&tuners[t->type]; - if (freq < tun->thresh1) + tun = &tuners[t->type]; + if (freq < tun->thresh1) { config = tun->VHF_L; - else if (freq < tun->thresh2) + dprintk("tv: VHF lowrange\n"); + } else if (freq < tun->thresh2) { config = tun->VHF_H; - else + dprintk("tv: VHF high range\n"); + } else { config = tun->UHF; + dprintk("tv: UHF range\n"); + } /* tv norm specific stuff for multi-norm tuners */ @@ -875,13 +902,17 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x02 -> NTSC antenna input 1 */ /* 0x03 -> NTSC antenna input 2 */ config &= ~0x03; - if (t->std & V4L2_STD_ATSC) + if (!(t->std & V4L2_STD_ATSC)) config |= 2; /* FIXME: input */ break; + + case TUNER_MICROTUNE_4042FI5: + /* Set the charge pump for fast tuning */ + tun->config |= 0x40; + break; } - /* * Philips FI1216MK2 remark from specification : * for channel selection involving band switching, and to ensure @@ -914,6 +945,37 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) if (4 != (rc = i2c_master_send(c,buffer,4))) printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); + if (t->type == TUNER_MICROTUNE_4042FI5) { + // FIXME - this may also work for other tuners + unsigned long timeout = jiffies + msecs_to_jiffies(1); + u8 status_byte = 0; + + /* Wait until the PLL locks */ + for (;;) { + if (time_after(jiffies,timeout)) + return; + if (1 != (rc = i2c_master_recv(c,&status_byte,1))) { + dprintk("tuner: i2c i/o read error: rc == %d (should be 1)\n",rc); + break; + } + /* bit 6 is PLL locked indicator */ + if (status_byte & 0x40) + break; + udelay(10); + } + + /* Set the charge pump for optimized phase noise figure */ + tun->config &= ~0x40; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + buffer[2] = tun->config; + buffer[3] = config; + dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n", + buffer[0],buffer[1],buffer[2],buffer[3]); + + if (4 != (rc = i2c_master_send(c,buffer,4))) + dprintk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc); + } } static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -926,18 +988,27 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) tun=&tuners[t->type]; div = freq + (int)(16*10.7); - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; buffer[2] = tun->config; + switch (t->type) { case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: buffer[3] = 0x19; break; + case TUNER_PHILIPS_FM1256_IH3: + div = (20 * freq)/16 + 333 * 2; + buffer[2] = 0x80; + buffer[3] = 0x19; + break; + case TUNER_LG_PAL_FM: + buffer[3] = 0xa5; + break; default: buffer[3] = 0xa4; break; } + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; dprintk("tuner: radio 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); @@ -1014,7 +1085,7 @@ static void set_type(struct i2c_client *c, unsigned int type, char *source) { struct tuner *t = i2c_get_clientdata(c); - if (t->type != UNSET) { + if (t->type != UNSET && t->type != TUNER_ABSENT) { if (t->type != type) printk("tuner: type already set to %d, " "ignoring request for %d\n", t->type, type); @@ -1039,8 +1110,8 @@ static void set_type(struct i2c_client *c, unsigned int type, char *source) } } -static char *pal = "-"; -MODULE_PARM(pal,"s"); +static char pal[] = "-"; +module_param_string(pal, pal, 0644, sizeof(pal)); static int tuner_fixup_std(struct tuner *t) { @@ -1081,7 +1152,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) if (this_adap > 0) return -1; this_adap++; - + client_template.adapter = adap; client_template.addr = addr; @@ -1183,7 +1254,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } break; - + /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -1278,7 +1349,25 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) /* nothing */ break; } - + + return 0; +} + +static int tuner_suspend(struct device * dev, u32 state, u32 level) +{ + dprintk("tuner: suspend\n"); + /* FIXME: power down ??? */ + return 0; +} + +static int tuner_resume(struct device * dev, u32 level) +{ + struct i2c_client *c = container_of(dev, struct i2c_client, dev); + struct tuner *t = i2c_get_clientdata(c); + + dprintk("tuner: resume\n"); + if (t->freq) + set_freq(c,t->freq); return 0; } @@ -1292,6 +1381,10 @@ static struct i2c_driver driver = { .attach_adapter = tuner_probe, .detach_client = tuner_detach, .command = tuner_command, + .driver = { + .suspend = tuner_suspend, + .resume = tuner_resume, + }, }; static struct i2c_client client_template = { @@ -1300,13 +1393,12 @@ static struct i2c_client client_template = .driver = &driver, }; -static int tuner_init_module(void) +static int __init tuner_init_module(void) { - i2c_add_driver(&driver); - return 0; + return i2c_add_driver(&driver); } -static void tuner_cleanup_module(void) +static void __exit tuner_cleanup_module(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index bf5017a77..89ae292b0 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -3,12 +3,12 @@ * * Copyright (c) 2000 Gerd Knorr * based on code by: - * Eric Sandeen (eric_sandeen@bigfoot.com) + * Eric Sandeen (eric_sandeen@bigfoot.com) * Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Greg Alexander (galexand@acm.org) * * This code is placed under the terms of the GNU General Public License - * + * * OPTIONS: * debug - set to 1 if you'd like to see debug messages * @@ -37,8 +37,8 @@ /* ---------------------------------------------------------------------- */ /* insmod args */ -MODULE_PARM(debug,"i"); static int debug = 0; /* insmod parameter */ +module_param(debug, int, 0644); MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips"); MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr"); @@ -207,7 +207,7 @@ static int chip_read(struct CHIPSTATE *chip) i2c_clientname(&chip->c)); return -1; } - dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer); + dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer); return buffer; } @@ -227,14 +227,14 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr) return -1; } dprintk("%s: chip_read2: reg%d=0x%x\n", - i2c_clientname(&chip->c),subaddr,read[0]); + i2c_clientname(&chip->c),subaddr,read[0]); return read[0]; } static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) { int i; - + if (0 == cmd->count) return 0; @@ -273,7 +273,7 @@ static int chip_thread(void *data) DECLARE_WAITQUEUE(wait, current); struct CHIPSTATE *chip = data; struct CHIPDESC *desc = chiplist + chip->type; - + daemonize("%s",i2c_clientname(&chip->c)); allow_signal(SIGTERM); dprintk("%s: thread started\n", i2c_clientname(&chip->c)); @@ -292,10 +292,10 @@ static int chip_thread(void *data) /* don't do anything for radio or if mode != auto */ if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0) continue; - + /* have a look what's going on */ desc->checkmode(chip); - + /* schedule next check */ mod_timer(&chip->wt, jiffies+2*HZ); } @@ -352,14 +352,14 @@ static void generic_checkmode(struct CHIPSTATE *chip) static int tda9840_getmode(struct CHIPSTATE *chip) { int val, mode; - + val = chip_read(chip); mode = VIDEO_SOUND_MONO; if (val & TDA9840_DS_DUAL) mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; if (val & TDA9840_ST_STEREO) mode |= VIDEO_SOUND_STEREO; - + dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n", val, mode); return mode; @@ -369,7 +369,7 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) { int update = 1; int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e; - + switch (mode) { case VIDEO_SOUND_MONO: t |= TDA9840_MONO; @@ -419,7 +419,7 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) * in 1dB steps - mute is 0x27 */ -/* 0x02 - BA in TDA9855 */ +/* 0x02 - BA in TDA9855 */ /* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) * in .5dB steps - 0 is 0x0E */ @@ -433,7 +433,7 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) /* Unique to TDA9855: */ /* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf) * in 3dB steps - mute is 0x0 */ - + /* Unique to TDA9850: */ /* lower 4 bits control stereo noise threshold, over which stereo turns off * set to values of 0x00 through 0x0f for Ster1 through Ster16 */ @@ -446,7 +446,7 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) #define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ #define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ /* Bits 0 to 3 select various combinations - * of line in and line out, only the + * of line in and line out, only the * interesting ones are defined */ #define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ #define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ @@ -499,7 +499,7 @@ static int tda985x_getmode(struct CHIPSTATE *chip) { int mode; - mode = ((TDA985x_STP | TDA985x_SAPP) & + mode = ((TDA985x_STP | TDA985x_SAPP) & chip_read(chip)) >> 4; /* Add mono mode regardless of SAP and stereo */ /* Allows forced mono */ @@ -510,7 +510,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) { int update = 1; int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f; - + switch (mode) { case VIDEO_SOUND_MONO: c6 |= TDA985x_MONO; @@ -538,7 +538,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_AD 0x01 /* Adjust */ #define TDA9873_PT 0x02 /* Port */ -/* Subaddress 0x00: Switching Data +/* Subaddress 0x00: Switching Data * B7..B0: * * B1, B0: Input source selection @@ -552,10 +552,10 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_EXT_MONO 1 /* B3, B2: output signal select - * B4 : transmission mode + * B4 : transmission mode * 0, 0, 1 Mono * 1, 0, 0 Stereo - * 1, 1, 1 Stereo (reversed channel) + * 1, 1, 1 Stereo (reversed channel) * 0, 0, 0 Dual AB * 0, 0, 1 Dual AA * 0, 1, 0 Dual BB @@ -587,7 +587,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_STEREO_ADJ 0x06 /* 0dB gain */ -/* Bits C6..C4 control FM stantard +/* Bits C6..C4 control FM stantard * C6, C5, C4 * 0, 0, 0 B/G (PAL FM) * 0, 0, 1 M @@ -609,7 +609,7 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) #define TDA9873_IDR_FAST 1 << 7 -/* Subaddress 0x02: Port data */ +/* Subaddress 0x02: Port data */ /* E1, E0 free programmable ports P1/P2 0, 0 both ports low @@ -632,11 +632,11 @@ static void tda985x_setmode(struct CHIPSTATE *chip, int mode) */ #define TDA9873_MOUT_MONO 0 #define TDA9873_MOUT_FMONO 0 -#define TDA9873_MOUT_DUALA 0 -#define TDA9873_MOUT_DUALB 1 << 3 -#define TDA9873_MOUT_ST 1 << 4 +#define TDA9873_MOUT_DUALA 0 +#define TDA9873_MOUT_DUALB 1 << 3 +#define TDA9873_MOUT_ST 1 << 4 #define TDA9873_MOUT_EXTM (1 << 4 ) & (1 << 3) -#define TDA9873_MOUT_EXTL 1 << 5 +#define TDA9873_MOUT_EXTL 1 << 5 #define TDA9873_MOUT_EXTR (1 << 5 ) & (1 << 3) #define TDA9873_MOUT_EXTLR (1 << 5 ) & (1 << 4) #define TDA9873_MOUT_MUTE (1 << 5 ) & (1 << 4) & (1 << 3) @@ -670,13 +670,13 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode) dprintk("tda9873_setmode(): external input\n"); return; } - + dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); dprintk("tda9873_setmode(): sw_data = %d\n", sw_data); switch (mode) { case VIDEO_SOUND_MONO: - sw_data |= TDA9873_TR_MONO; + sw_data |= TDA9873_TR_MONO; break; case VIDEO_SOUND_STEREO: sw_data |= TDA9873_TR_STEREO; @@ -764,9 +764,9 @@ static int tda9874a_dic = -1; /* device id. code */ static unsigned int tda9874a_SIF = UNSET; static unsigned int tda9874a_AMSEL = UNSET; static unsigned int tda9874a_STD = UNSET; -MODULE_PARM(tda9874a_SIF,"i"); -MODULE_PARM(tda9874a_AMSEL,"i"); -MODULE_PARM(tda9874a_STD,"i"); +module_param(tda9874a_SIF, int, 0444); +module_param(tda9874a_AMSEL, int, 0444); +module_param(tda9874a_STD, int, 0444); /* * initialization table for tda9874 decoder: @@ -871,7 +871,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip) if(nsr & 0x02) /* NSR.S/MB=1 */ mode |= VIDEO_SOUND_STEREO; #endif - if(nsr & 0x01) /* NSR.D/SB=1 */ + if(nsr & 0x01) /* NSR.D/SB=1 */ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; } else { if(dsr & 0x02) /* DSR.IDSTE=1 */ @@ -1082,7 +1082,7 @@ static int tda8425_initialize(struct CHIPSTATE *chip) static void tda8425_setmode(struct CHIPSTATE *chip, int mode) { int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1; - + if (mode & VIDEO_SOUND_LANG1) { s1 |= TDA8425_S1_ML_SOUND_A; s1 |= TDA8425_S1_STEREO_PSEUDO; @@ -1090,10 +1090,10 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) } else if (mode & VIDEO_SOUND_LANG2) { s1 |= TDA8425_S1_ML_SOUND_B; s1 |= TDA8425_S1_STEREO_PSEUDO; - + } else { s1 |= TDA8425_S1_ML_STEREO; - + if (mode & VIDEO_SOUND_MONO) s1 |= TDA8425_S1_STEREO_MONO; if (mode & VIDEO_SOUND_STEREO) @@ -1152,7 +1152,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) static int ta8874z_getmode(struct CHIPSTATE *chip) { int val, mode; - + val = chip_read(chip); mode = VIDEO_SOUND_MONO; if (val & TA8874Z_B1){ @@ -1218,16 +1218,16 @@ int tea6420 = 1; int pic16c54 = 1; int ta8874z = 0; // address clash with tda9840 -MODULE_PARM(tda8425,"i"); -MODULE_PARM(tda9840,"i"); -MODULE_PARM(tda9850,"i"); -MODULE_PARM(tda9855,"i"); -MODULE_PARM(tda9873,"i"); -MODULE_PARM(tda9874a,"i"); -MODULE_PARM(tea6300,"i"); -MODULE_PARM(tea6420,"i"); -MODULE_PARM(pic16c54,"i"); -MODULE_PARM(ta8874z,"i"); +module_param(tda8425, int, 0444); +module_param(tda9840, int, 0444); +module_param(tda9850, int, 0444); +module_param(tda9855, int, 0444); +module_param(tda9873, int, 0444); +module_param(tda9874a, int, 0444); +module_param(tea6300, int, 0444); +module_param(tea6420, int, 0444); +module_param(pic16c54, int, 0444); +module_param(ta8874z, int, 0444); static struct CHIPDESC chiplist[] = { { @@ -1264,7 +1264,7 @@ static struct CHIPDESC chiplist[] = { .inputmute = TDA9873_MUTE | TDA9873_AUTOMUTE, .inputmap = {0xa0, 0xa2, 0xa0, 0xa0, 0xc0}, .inputmask = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE, - + }, { .name = "tda9874h/a", @@ -1497,6 +1497,10 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) static int chip_probe(struct i2c_adapter *adap) { + /* don't attach on saa7146 based cards, + because dedicated drivers are used */ + if ((adap->id & I2C_ALGO_SAA7146)) + return 0; #ifdef I2C_CLASS_TV_ANALOG if (adap->class & I2C_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, chip_attach); @@ -1522,7 +1526,7 @@ static int chip_detach(struct i2c_client *client) wake_up_interruptible(&chip->wq); wait_for_completion(&chip->texit); } - + i2c_detach_client(&chip->c); kfree(chip); return 0; @@ -1587,7 +1591,7 @@ static int chip_command(struct i2c_client *client, case VIDIOCSAUDIO: { struct video_audio *va = arg; - + if (desc->flags & CHIP_HAS_VOLUME) { chip->left = (min(65536 - va->balance,32768) * va->volume) / 32768; @@ -1613,7 +1617,7 @@ static int chip_command(struct i2c_client *client, case VIDIOCSCHAN: { struct video_channel *vc = arg; - + dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n"); chip->norm = vc->norm; break; @@ -1651,7 +1655,7 @@ static struct i2c_client client_template = .driver = &driver, }; -static int audiochip_init_module(void) +static int __init audiochip_init_module(void) { struct CHIPDESC *desc; printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); @@ -1659,11 +1663,11 @@ static int audiochip_init_module(void) for (desc = chiplist; desc->name != NULL; desc++) printk("%s%s", (desc == chiplist) ? "" : ",",desc->name); printk("\n"); - i2c_add_driver(&driver); - return 0; + + return i2c_add_driver(&driver); } -static void audiochip_cleanup_module(void) +static void __exit audiochip_cleanup_module(void) { i2c_del_driver(&driver); } diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 48b2f822e..7c2ac03df 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -20,7 +20,7 @@ #define DEV_MAX 4 static int devnr = -1; -MODULE_PARM(devnr,"i"); +module_param(devnr, int, 0644); MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); @@ -82,7 +82,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm if (NULL == client) return -ENODEV; - + if (cmd == SOUND_MIXER_INFO) { mixer_info info; strlcpy(info.id, "tv card", sizeof(info.id)); @@ -148,7 +148,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm va.volume) / 32768; ret = v4l_to_mix2(left,right); break; - + case MIXER_WRITE(SOUND_MIXER_BASS): va.bass = mix_to_v4l(val); client->driver->command(client,VIDIOCSAUDIO,&va); @@ -324,26 +324,26 @@ static int tvmixer_clients(struct i2c_client *client) devices[i].dev = client; printk("tvmixer: %s (%s) registered with minor %d\n", client->name,client->adapter->name,minor); - + return 0; } /* ----------------------------------------------------------------------- */ -static int tvmixer_init_module(void) +static int __init tvmixer_init_module(void) { int i; - + for (i = 0; i < DEV_MAX; i++) devices[i].minor = -1; - i2c_add_driver(&driver); - return 0; + + return i2c_add_driver(&driver); } -static void tvmixer_cleanup_module(void) +static void __exit tvmixer_cleanup_module(void) { int i; - + i2c_del_driver(&driver); for (i = 0; i < DEV_MAX; i++) { if (devices[i].minor != -1) { diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index c75ca87b0..b0d4bcb02 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -44,7 +44,7 @@ #endif static unsigned int debug = 0; -MODULE_PARM(debug,"i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages"); MODULE_AUTHOR("Bill Dirks"); MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers."); @@ -116,7 +116,7 @@ set_v4l_control(struct inode *inode, if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN) value = 65535; ctrl2.id = qctrl2.id; - ctrl2.value = + ctrl2.value = (value * (qctrl2.maximum - qctrl2.minimum) + 32767) / 65535; @@ -256,7 +256,7 @@ static int check_size(struct inode *inode, memset(&desc2,0,sizeof(desc2)); memset(&fmt2,0,sizeof(fmt2)); - + desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2)) goto done; @@ -326,7 +326,7 @@ v4l_compat_translate_ioctl(struct inode *inode, err = 0; } - memcpy(cap->name, cap2->card, + memcpy(cap->name, cap2->card, min(sizeof(cap->name), sizeof(cap2->card))); cap->name[sizeof(cap->name) - 1] = 0; if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) @@ -383,7 +383,7 @@ v4l_compat_translate_ioctl(struct inode *inode, if (0 != fbuf2.fmt.bytesperline) buffer->bytesperline = fbuf2.fmt.bytesperline; else { - buffer->bytesperline = + buffer->bytesperline = (buffer->width * buffer->depth + 7) & 7; buffer->bytesperline >>= 3; } @@ -633,7 +633,7 @@ v4l_compat_translate_ioctl(struct inode *inode, err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err); - if (fmt2->fmt.pix.pixelformat != + if (fmt2->fmt.pix.pixelformat != palette_to_pixelformat(pict->palette)) { fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); @@ -807,7 +807,7 @@ v4l_compat_translate_ioctl(struct inode *inode, memset(&aud2,0,sizeof(aud2)); memset(&tun2,0,sizeof(tun2)); - + aud2.index = aud->audio; err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { @@ -815,7 +815,7 @@ v4l_compat_translate_ioctl(struct inode *inode, break; } - set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, + set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, aud->volume, drv); set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, aud->bass, drv); @@ -863,16 +863,16 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(&buf2,0,sizeof(buf2)); memset(fmt2,0,sizeof(*fmt2)); - + fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err); break; } - if (mm->width != fmt2->fmt.pix.width || + if (mm->width != fmt2->fmt.pix.width || mm->height != fmt2->fmt.pix.height || - palette_to_pixelformat(mm->format) != + palette_to_pixelformat(mm->format) != fmt2->fmt.pix.pixelformat) {/* New capture format... */ fmt2->fmt.pix.width = mm->width; @@ -955,11 +955,11 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCGVBIFMT: /* query VBI data capture format */ { struct vbi_format *fmt = arg; - + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2, 0, sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - + err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); @@ -979,7 +979,7 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSVBIFMT: { struct vbi_format *fmt = arg; - + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2, 0, sizeof(*fmt2)); @@ -987,10 +987,10 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - fmt2->fmt.vbi.start[0] = fmt->start[0]; - fmt2->fmt.vbi.count[0] = fmt->count[0]; - fmt2->fmt.vbi.start[1] = fmt->start[1]; - fmt2->fmt.vbi.count[1] = fmt->count[1]; + fmt2->fmt.vbi.start[0] = fmt->start[0]; + fmt2->fmt.vbi.count[0] = fmt->count[0]; + fmt2->fmt.vbi.start[1] = fmt->start[1]; + fmt2->fmt.vbi.count[1] = fmt->count[1]; fmt2->fmt.vbi.flags = fmt->flags; err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); if (err < 0) { @@ -1014,7 +1014,7 @@ v4l_compat_translate_ioctl(struct inode *inode, dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); break; } - + default: err = -ENOIOCTLCMD; break; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 6f079fdad..b5e0cf344 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -36,7 +36,7 @@ /* * Video4linux 1/2 integration by Justin Schoeman * - * 2.4 PROCFS support ported from 2.4 kernels by + * 2.4 PROCFS support ported from 2.4 kernels by * Iñaki García Etxebarria * Makefile fix by "W. Michael Petullo" * 2.4 devfs support ported from 2.4 kernels by @@ -84,17 +84,20 @@ MODULE_LICENSE("GPL"); * Video Standard Operations (contributed by Michael Schimek) */ -/* This is the recommended method to deal with the framerate fields. More +#if 0 /* seems to have no users */ +/* This is the recommended method to deal with the framerate fields. More sophisticated drivers will access the fields directly. */ unsigned int v4l2_video_std_fps(struct v4l2_standard *vs) -{ +{ if (vs->frameperiod.numerator > 0) - return (((vs->frameperiod.denominator << 8) / - vs->frameperiod.numerator) + + return (((vs->frameperiod.denominator << 8) / + vs->frameperiod.numerator) + (1 << 7)) / (1 << 8); return 0; } +EXPORT_SYMBOL(v4l2_video_std_fps); +#endif /* Fill in the fields of a v4l2_standard structure according to the 'id' and 'transmission' parameters. Returns negative on error. */ @@ -132,7 +135,7 @@ int v4l2_prio_init(struct v4l2_prio_state *global) memset(global,0,sizeof(*global)); return 0; } - + int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, enum v4l2_priority new) { @@ -259,7 +262,6 @@ char *v4l2_ioctl_names[256] = { /* ----------------------------------------------------------------- */ -EXPORT_SYMBOL(v4l2_video_std_fps); EXPORT_SYMBOL(v4l2_video_std_construct); EXPORT_SYMBOL(v4l2_prio_init); diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index c7c746550..7aa20cbce 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -1,4 +1,6 @@ /* + * $Id: video-buf.c,v 1.15 2004/11/07 14:45:00 kraxel Exp $ + * * generic helper functions for video4linux capture buffers, to handle * memory management and PCI DMA. Right now bttv + saa7134 use it. * @@ -7,7 +9,7 @@ * into PAGE_SIZE chunks). They also assume the driver does not need * to touch the video data (thus it is probably not useful for USB 1.1 * as data often must be uncompressed by the drivers). - * + * * (c) 2001-2004 Gerd Knorr [SUSE Labs] * * This program is free software; you can redistribute it and/or modify @@ -34,11 +36,11 @@ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); } static int debug = 0; +module_param(debug, int, 0644); MODULE_DESCRIPTION("helper module to manage video4linux pci dma buffers"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug,"i"); #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "vbuf: " fmt , ## arg) @@ -64,7 +66,7 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) sglist[i].length = PAGE_SIZE; } return sglist; - + err: kfree(sglist); return NULL; @@ -191,7 +193,7 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma) { MAGIC_CHECK(dma->magic,MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); - + if (dma->pages) { dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, dma->offset); @@ -287,7 +289,7 @@ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr) { int retval = 0; DECLARE_WAITQUEUE(wait, current); - + MAGIC_CHECK(vb->magic,MAGIC_BUFFER); add_wait_queue(&vb->done, &wait); while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) { @@ -353,39 +355,39 @@ videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb, err = videobuf_dma_pci_map(pci,&vb->dma); if (0 != err) return err; - + return 0; } /* --------------------------------------------------------------------- */ -void -videobuf_queue_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, - struct pci_dev *pci, - spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, - unsigned int msize) +void videobuf_queue_init(struct videobuf_queue* q, + struct videobuf_queue_ops *ops, + struct pci_dev *pci, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv) { memset(q,0,sizeof(*q)); - q->irqlock = irqlock; q->pci = pci; q->type = type; q->field = field; q->msize = msize; q->ops = ops; + q->priv_data = priv; init_MUTEX(&q->lock); INIT_LIST_HEAD(&q->stream); } -int +int videobuf_queue_is_busy(struct videobuf_queue *q) { int i; - + if (q->streaming) { dprintk(1,"busy: streaming active\n"); return 1; @@ -418,7 +420,7 @@ videobuf_queue_is_busy(struct videobuf_queue *q) } void -videobuf_queue_cancel(struct file *file, struct videobuf_queue *q) +videobuf_queue_cancel(struct videobuf_queue *q) { unsigned long flags; int i; @@ -439,7 +441,7 @@ videobuf_queue_cancel(struct file *file, struct videobuf_queue *q) for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - q->ops->buf_release(file,q->bufs[i]); + q->ops->buf_release(q,q->bufs[i]); } INIT_LIST_HEAD(&q->stream); } @@ -521,7 +523,7 @@ videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, } int -videobuf_reqbufs(struct file *file, struct videobuf_queue *q, +videobuf_reqbufs(struct videobuf_queue *q, struct v4l2_requestbuffers *req) { unsigned int size,count; @@ -546,12 +548,12 @@ videobuf_reqbufs(struct file *file, struct videobuf_queue *q, if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; size = 0; - q->ops->buf_setup(file,&count,&size); + q->ops->buf_setup(q,&count,&size); size = PAGE_ALIGN(size); dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", count, size, (count*size)>>PAGE_SHIFT); - retval = videobuf_mmap_setup(file,q,count,size,req->memory); + retval = videobuf_mmap_setup(q,count,size,req->memory); if (retval < 0) goto done; @@ -576,7 +578,7 @@ videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) } int -videobuf_qbuf(struct file *file, struct videobuf_queue *q, +videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) { struct videobuf_buffer *buf; @@ -620,7 +622,7 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, if (b->length < buf->bsize) goto done; if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr) - q->ops->buf_release(file,buf); + q->ops->buf_release(q,buf); buf->baddr = b->m.userptr; break; case V4L2_MEMORY_OVERLAY: @@ -631,30 +633,30 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, } field = videobuf_next_field(q); - retval = q->ops->buf_prepare(file,buf,field); + retval = q->ops->buf_prepare(q,buf,field); if (0 != retval) goto done; - + list_add_tail(&buf->stream,&q->stream); if (q->streaming) { spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(file,buf); + q->ops->buf_queue(q,buf); spin_unlock_irqrestore(q->irqlock,flags); } retval = 0; - + done: up(&q->lock); return retval; } int -videobuf_dqbuf(struct file *file, struct videobuf_queue *q, - struct v4l2_buffer *b) +videobuf_dqbuf(struct videobuf_queue *q, + struct v4l2_buffer *b, int nonblocking) { struct videobuf_buffer *buf; int retval; - + down(&q->lock); retval = -EBUSY; if (q->reading) @@ -665,7 +667,7 @@ videobuf_dqbuf(struct file *file, struct videobuf_queue *q, if (list_empty(&q->stream)) goto done; buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - retval = videobuf_waiton(buf, file->f_flags & O_NONBLOCK, 1); + retval = videobuf_waiton(buf, nonblocking, 1); if (retval < 0) goto done; switch (buf->state) { @@ -689,13 +691,13 @@ videobuf_dqbuf(struct file *file, struct videobuf_queue *q, return retval; } -int videobuf_streamon(struct file *file, struct videobuf_queue *q) +int videobuf_streamon(struct videobuf_queue *q) { struct videobuf_buffer *buf; struct list_head *list; unsigned long flags; int retval; - + down(&q->lock); retval = -EBUSY; if (q->reading) @@ -708,7 +710,7 @@ int videobuf_streamon(struct file *file, struct videobuf_queue *q) list_for_each(list,&q->stream) { buf = list_entry(list, struct videobuf_buffer, stream); if (buf->state == STATE_PREPARED) - q->ops->buf_queue(file,buf); + q->ops->buf_queue(q,buf); } spin_unlock_irqrestore(q->irqlock,flags); @@ -717,14 +719,14 @@ int videobuf_streamon(struct file *file, struct videobuf_queue *q) return retval; } -int videobuf_streamoff(struct file *file, struct videobuf_queue *q) +int videobuf_streamoff(struct videobuf_queue *q) { int retval = -EINVAL; down(&q->lock); if (!q->streaming) goto done; - videobuf_queue_cancel(file,q); + videobuf_queue_cancel(q); q->streaming = 0; retval = 0; @@ -734,8 +736,8 @@ int videobuf_streamoff(struct file *file, struct videobuf_queue *q) } static ssize_t -videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos) +videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, + size_t count, loff_t *ppos) { enum v4l2_field field; unsigned long flags; @@ -751,13 +753,13 @@ videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, q->read_buf->baddr = (unsigned long)data; q->read_buf->bsize = count; field = videobuf_next_field(q); - retval = q->ops->buf_prepare(file,q->read_buf,field); + retval = q->ops->buf_prepare(q,q->read_buf,field); if (0 != retval) goto done; - + /* start capture & wait */ spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(file,q->read_buf); + q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { @@ -770,14 +772,15 @@ videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, done: /* cleanup */ - q->ops->buf_release(file,q->read_buf); + q->ops->buf_release(q,q->read_buf); kfree(q->read_buf); q->read_buf = NULL; return retval; } -ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, - char __user *data, size_t count, loff_t *ppos) +ssize_t videobuf_read_one(struct videobuf_queue *q, + char __user *data, size_t count, loff_t *ppos, + int nonblocking) { enum v4l2_field field; unsigned long flags; @@ -787,11 +790,11 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, down(&q->lock); nbufs = 1; size = 0; - q->ops->buf_setup(file,&nbufs,&size); + q->ops->buf_setup(q,&nbufs,&size); if (NULL == q->read_buf && count >= size && - !(file->f_flags & O_NONBLOCK)) { - retval = videobuf_read_zerocopy(file,q,data,count,ppos); + !nonblocking) { + retval = videobuf_read_zerocopy(q,data,count,ppos); if (retval >= 0 || retval == -EIO) /* ok, all done */ goto done; @@ -806,24 +809,24 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; field = videobuf_next_field(q); - retval = q->ops->buf_prepare(file,q->read_buf,field); + retval = q->ops->buf_prepare(q,q->read_buf,field); if (0 != retval) goto done; spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(file,q->read_buf); + q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); q->read_off = 0; } /* wait until capture is done */ - retval = videobuf_waiton(q->read_buf, file->f_flags & O_NONBLOCK, 1); + retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) { /* catch I/O errors */ - q->ops->buf_release(file,q->read_buf); + q->ops->buf_release(q,q->read_buf); kfree(q->read_buf); q->read_buf = NULL; retval = -EIO; @@ -842,7 +845,7 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, q->read_off += bytes; if (q->read_off == q->read_buf->size) { /* all data copied, cleanup */ - q->ops->buf_release(file,q->read_buf); + q->ops->buf_release(q,q->read_buf); kfree(q->read_buf); q->read_buf = NULL; } @@ -852,43 +855,43 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, return retval; } -int videobuf_read_start(struct file *file, struct videobuf_queue *q) +int videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; unsigned long flags; int count = 0, size = 0; int err, i; - q->ops->buf_setup(file,&count,&size); + q->ops->buf_setup(q,&count,&size); if (count < 2) count = 2; if (count > VIDEO_MAX_FRAME) count = VIDEO_MAX_FRAME; size = PAGE_ALIGN(size); - err = videobuf_mmap_setup(file, q, count, size, V4L2_MEMORY_USERPTR); + err = videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); if (err) return err; for (i = 0; i < count; i++) { field = videobuf_next_field(q); - err = q->ops->buf_prepare(file,q->bufs[i],field); + err = q->ops->buf_prepare(q,q->bufs[i],field); if (err) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); } spin_lock_irqsave(q->irqlock,flags); for (i = 0; i < count; i++) - q->ops->buf_queue(file,q->bufs[i]); + q->ops->buf_queue(q,q->bufs[i]); spin_unlock_irqrestore(q->irqlock,flags); q->reading = 1; return 0; } -void videobuf_read_stop(struct file *file, struct videobuf_queue *q) +void videobuf_read_stop(struct videobuf_queue *q) { int i; - - videobuf_queue_cancel(file,q); + + videobuf_queue_cancel(q); INIT_LIST_HEAD(&q->stream); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) @@ -900,20 +903,21 @@ void videobuf_read_stop(struct file *file, struct videobuf_queue *q) q->reading = 0; } -ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, +ssize_t videobuf_read_stream(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos, - int vbihack) + int vbihack, int nonblocking) { unsigned int *fc, bytes; int err, retval; unsigned long flags; - + + dprintk(2,"%s\n",__FUNCTION__); down(&q->lock); retval = -EBUSY; if (q->streaming) goto done; if (!q->reading) { - retval = videobuf_read_start(file,q); + retval = videobuf_read_start(q); if (retval < 0) goto done; } @@ -928,8 +932,7 @@ ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, list_del(&q->read_buf->stream); q->read_off = 0; } - err = videobuf_waiton(q->read_buf, - file->f_flags & O_NONBLOCK,1); + err = videobuf_waiton(q->read_buf, nonblocking, 1); if (err < 0) { if (0 == retval) retval = err; @@ -947,7 +950,7 @@ ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, *fc = q->read_buf->field_count >> 1; dprintk(1,"vbihack: %d\n",*fc); } - + /* copy stuff */ bytes = count; if (bytes > q->read_buf->size - q->read_off) @@ -974,7 +977,7 @@ ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, list_add_tail(&q->read_buf->stream, &q->stream); spin_lock_irqsave(q->irqlock,flags); - q->ops->buf_queue(file,q->read_buf); + q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); q->read_buf = NULL; } @@ -1001,7 +1004,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer, stream); } else { if (!q->reading) - videobuf_read_start(file,q); + videobuf_read_start(q); if (!q->reading) { rc = POLLERR; } else if (NULL == q->read_buf) { @@ -1042,29 +1045,30 @@ static void videobuf_vm_close(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; int i; dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map, map->count,vma->vm_start,vma->vm_end); - /* down(&fh->lock); FIXME */ map->count--; if (0 == map->count) { - dprintk(1,"munmap %p\n",map); + dprintk(1,"munmap %p q=%p\n",map,q); + down(&q->lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { - if (NULL == map->q->bufs[i]) + if (NULL == q->bufs[i]) continue; - if (map->q->bufs[i]) + if (q->bufs[i]) ; - if (map->q->bufs[i]->map != map) + if (q->bufs[i]->map != map) continue; - map->q->bufs[i]->map = NULL; - map->q->bufs[i]->baddr = 0; - map->q->ops->buf_release(vma->vm_file,map->q->bufs[i]); + q->bufs[i]->map = NULL; + q->bufs[i]->baddr = 0; + q->ops->buf_release(q,q->bufs[i]); } + up(&q->lock); kfree(map); } - /* up(&fh->lock); FIXME */ return; } @@ -1100,14 +1104,14 @@ static struct vm_operations_struct videobuf_vm_ops = .nopage = videobuf_vm_nopage, }; -int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, +int videobuf_mmap_setup(struct videobuf_queue *q, unsigned int bcount, unsigned int bsize, enum v4l2_memory memory) { unsigned int i; int err; - err = videobuf_mmap_free(file,q); + err = videobuf_mmap_free(q); if (0 != err) return err; @@ -1132,7 +1136,7 @@ int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, return 0; } -int videobuf_mmap_free(struct file *file, struct videobuf_queue *q) +int videobuf_mmap_free(struct videobuf_queue *q) { int i; @@ -1142,15 +1146,15 @@ int videobuf_mmap_free(struct file *file, struct videobuf_queue *q) for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; - q->ops->buf_release(file,q->bufs[i]); + q->ops->buf_release(q,q->bufs[i]); kfree(q->bufs[i]); q->bufs[i] = NULL; } return 0; } -int videobuf_mmap_mapper(struct vm_area_struct *vma, - struct videobuf_queue *q) +int videobuf_mmap_mapper(struct videobuf_queue *q, + struct vm_area_struct *vma) { struct videobuf_mapping *map; unsigned int first,last,size,i; @@ -1219,8 +1223,8 @@ int videobuf_mmap_mapper(struct vm_area_struct *vma, vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ vma->vm_private_data = map; - dprintk(1,"mmap %p: %08lx-%08lx pgoff %08lx bufs %d-%d\n", - map,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); + dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n", + map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last); retval = 0; done: diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index 081eb06a4..ae1063e09 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -43,11 +43,6 @@ #include #endif -#include -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) -#endif - #include "videocodec.h" static int debug = 0; diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index fbc5cb1e2..9d4c74f25 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -254,7 +254,7 @@ int video_exclusive_release(struct inode *inode, struct file *file) return 0; } -extern struct file_operations video_fops; +static struct file_operations video_fops; /** * video_register_device - register video4linux devices diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 8656d58d1..9fe6ad3b6 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -407,7 +407,7 @@ struct zoran { struct pci_dev *pci_dev; /* PCI device */ unsigned char revision; /* revision of zr36057 */ unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */ - unsigned char *zr36057_mem; /* pointer to mapped IO memory */ + unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ spinlock_t spinlock; /* Spinlock */ @@ -499,10 +499,10 @@ struct zoran { of _ALPHA_BUZ in the Makefile.*/ #ifdef _ALPHA_BUZ -#define btwrite(dat,adr) writel((dat),(char *) (zr->zr36057_adr+(adr))) +#define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr)) #define btread(adr) readl(zr->zr36057_adr+(adr)) #else -#define btwrite(dat,adr) writel((dat), (char *) (zr->zr36057_mem+(adr))) +#define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) #define btread(adr) readl(zr->zr36057_mem+(adr)) #endif diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 705cff870..a35d518e2 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -1105,8 +1105,7 @@ zr36057_enable_jpg (struct zoran *zr, ZR36057_ISR); btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ / 20); + msleep(50); set_videobus_dir(zr, 0); set_frame(zr, 1); // /FRAME diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 28f1a8d05..0cb6cd28b 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -265,7 +265,7 @@ get_high_mem (unsigned long size) * if more than one driver at a time has the idea to use this memory!!!! */ - volatile unsigned char *mem; + volatile unsigned char __iomem *mem; unsigned char c; unsigned long hi_mem_ph; unsigned long i; @@ -285,21 +285,21 @@ get_high_mem (unsigned long size) for (i = 0; i < size; i++) { /* Check if it is memory */ c = i & 0xff; - mem[i] = c; - if (mem[i] != c) + writeb(c, mem + i); + if (readb(mem + i) != c) break; c = 255 - c; - mem[i] = c; - if (mem[i] != c) + writeb(c, mem + i); + if (readb(mem + i) != c) break; - mem[i] = 0; /* zero out memory */ + writeb(0, mem + i); /* zero out memory */ /* give the kernel air to breath */ if ((i & 0x3ffff) == 0x3ffff) schedule(); } - iounmap((void *) mem); + iounmap(mem); if (i != size) { dprintk(1, @@ -1917,8 +1917,7 @@ zoran_set_norm (struct zoran *zr, decoder_command(zr, DECODER_SET_NORM, &norm); /* let changes come into effect */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(2 * HZ); + ssleep(2); decoder_command(zr, DECODER_GET_STATUS, &status); if (!(status & DECODER_STATUS_GOOD)) { @@ -2265,8 +2264,8 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG - "%s: VIDIOCSFBUF - base=0x%x, w=%d, h=%d, depth=%d, bpl=%d\n", - ZR_DEVNAME(zr), (u32) vbuf->base, vbuf->width, + "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n", + ZR_DEVNAME(zr), vbuf->base, vbuf->width, vbuf->height, vbuf->depth, vbuf->bytesperline); for (i = 0; i < zoran_num_formats; i++) @@ -2639,8 +2638,7 @@ zoran_do_ioctl (struct inode *inode, decoder_command(zr, DECODER_SET_NORM, &norm); /* sleep 1 second */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(1 * HZ); + ssleep(1); /* Get status of video decoder */ decoder_command(zr, DECODER_GET_STATUS, &status); @@ -4450,12 +4448,6 @@ static struct vm_operations_struct zoran_vm_ops = { .close = zoran_vm_close, }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -#define zr_remap_page_range(a,b,c,d,e) remap_page_range(b,c,d,e) -#else -#define zr_remap_page_range(a,b,c,d,e) remap_page_range(a,b,c,d,e) -#endif - static int zoran_mmap (struct file *file, struct vm_area_struct *vma) @@ -4555,12 +4547,14 @@ zoran_mmap (struct file *file, pos = (unsigned long) fh->jpg_buffers. buffer[i].frag_tab[2 * j]; - page = virt_to_phys(bus_to_virt(pos)); /* should just be pos on i386 */ - if (zr_remap_page_range - (vma, start, page, todo, PAGE_SHARED)) { + /* should just be pos on i386 */ + page = virt_to_phys(bus_to_virt(pos)) + >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, page, + todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L) - remap_page_range failed\n", + "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", ZR_DEVNAME(zr)); res = -EAGAIN; goto jpg_mmap_unlock_and_return; @@ -4641,11 +4635,11 @@ zoran_mmap (struct file *file, if (todo > fh->v4l_buffers.buffer_size) todo = fh->v4l_buffers.buffer_size; page = fh->v4l_buffers.buffer[i].fbuffer_phys; - if (zr_remap_page_range - (vma, start, page, todo, PAGE_SHARED)) { + if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, + todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L)i - remap_page_range failed\n", + "%s: zoran_mmap(V4L)i - remap_pfn_range failed\n", ZR_DEVNAME(zr)); res = -EAGAIN; goto v4l_mmap_unlock_and_return; diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c index 9b55341ba..9780261c5 100644 --- a/drivers/media/video/zr36120.c +++ b/drivers/media/video/zr36120.c @@ -145,14 +145,11 @@ static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { static void __init handle_chipset(void) { - struct pci_dev *dev = NULL; - /* Just in case some nut set this to something dangerous */ if (triton1) triton1 = ZORAN_VDC_TRICOM; - while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev))) - { + if (pci_pci_problems & PCIPCI_TRITON) { printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); triton1 = ZORAN_VDC_TRICOM; } @@ -819,8 +816,7 @@ void zoran_close(struct video_device* dev) * be sure its safe to free the buffer. We wait 5-6 fields * which is more than sufficient to be sure. */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + msleep(100); /* Wait 1/10th of a second */ /* free the allocated framebuffer */ if (ztv->fbuffer) @@ -1475,8 +1471,8 @@ int zoran_mmap(struct vm_area_struct *vma, struct video_device* dev, const char* /* start mapping the whole shabang to user memory */ pos = (unsigned long)ztv->fbuffer; while (size>0) { - unsigned long page = virt_to_phys((void*)pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + unsigned long pfn = virt_to_phys((void*)pos) >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; @@ -1568,8 +1564,7 @@ void vbi_close(struct video_device *dev) * be sure its safe to free the buffer. We wait 5-6 fields * which is more than sufficient to be sure. */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + msleep(100); /* Wait 1/10th of a second */ for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) { diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index aa1c657dd..452418b24 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -27,42 +27,9 @@ config FUSION_MAX_SGE necessary (or recommended) unless the user will be running large I/O's via the raw interface. -config FUSION_ISENSE - tristate "Enhanced SCSI error reporting" - depends on MODULES && FUSION && m - ---help--- - 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. - - NOTE: Support for building this feature into the kernel is not - available, due to kernel size considerations. - config FUSION_CTL tristate "Fusion MPT misc device (ioctl) driver" - depends on MODULES && FUSION && m + depends on FUSION ---help--- The Fusion MPT misc device driver provides specialized control of MPT adapters via system ioctl calls. Use of ioctl calls to diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index b709839fe..f6fdcaaef 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -2,7 +2,7 @@ # Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers. # # Note! If you want to turn on various debug defines for an extended period of -# time but don't want them lingering around in the Makefile when you pass it on +# time but don't want them lingering around in the Makefile when you pass it on # to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC @@ -48,6 +48,5 @@ EXTRA_CFLAGS += ${MPT_CFLAGS} #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o -obj-$(CONFIG_FUSION_ISENSE) += isense.o obj-$(CONFIG_FUSION_CTL) += mptctl.o obj-$(CONFIG_FUSION_LAN) += mptlan.o diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 75c07f89e..e13a041ce 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -137,13 +137,6 @@ int mpt_stm_index = -1; struct proc_dir_entry *mpt_proc_root_dir; -DmpServices_t *DmpService; - -void *mpt_v_ASCQ_TablePtr; -const char **mpt_ScsiOpcodesPtr; -int mpt_ASCQ_TableSz; - - #define WHOINIT_UNKNOWN 0xAA /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -162,10 +155,8 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; -static int FusionInitCalled = 0; static int mpt_base_index = -1; static int last_drv_idx = -1; -static int isense_idx = -1; static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); @@ -175,10 +166,12 @@ static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); */ static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r); static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); - +static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, + u32 *req, int replyBytes, u16 *u16reply, int maxwait, + int sleepFlag); static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); -static void mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev); -static void mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup); +static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev); +static void mpt_adapter_disable(MPT_ADAPTER *ioc); static void mpt_adapter_dispose(MPT_ADAPTER *ioc); static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); @@ -291,7 +284,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) int type; int freeme; - ioc = bus_id; + ioc = (MPT_ADAPTER *)bus_id; /* * Drain the reply FIFO! @@ -333,8 +326,8 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n", - ioc->name, mr)); + dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n", + ioc->name, mr, req_idx)); DBG_DUMP_REPLY_FRAME(mr) /* NEW! 20010301 -sralston @@ -343,22 +336,20 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - if ((int)ioc->chip_type <= (int)FC929) + if (ioc->bus_type == FC) mpt_fc_log_info(ioc, log_info); - else + else if (ioc->bus_type == SCSI) mpt_sp_log_info(ioc, log_info); } if (ioc_stat & MPI_IOCSTATUS_MASK) { - if ((int)ioc->chip_type <= (int)FC929) - ; - else + if (ioc->bus_type == SCSI) mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); } } else { /* * Process turbo (context) reply... */ - dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa)); + dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT); if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) { cb_idx = mpt_stm_index; @@ -398,7 +389,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) } #ifdef MPT_DEBUG_IRQ - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { /* Verify mf, mr are reasonable. */ if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) @@ -443,7 +434,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT ioc->mfcnt--; #endif @@ -506,7 +497,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) results = ProcessEventNotification(ioc, pEvReply, &evHandlers); if (results != evHandlers) { /* CHECKME! Any special handling needed here? */ - dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", + devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", ioc->name, evHandlers, results)); } @@ -539,7 +530,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) del_timer(&pCfg->timer); spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_DEL_ITEM(&pCfg->linkage); + list_del(&pCfg->linkage); spin_unlock_irqrestore(&ioc->FreeQlock, flags); /* @@ -609,22 +600,6 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) last_drv_idx = -1; -#ifndef MODULE - /* - * Handle possibility of the mptscsih_detect() routine getting - * called *before* fusion_init! - */ - if (!FusionInitCalled) { - dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n")); - /* - * NOTE! We'll get recursion here, as fusion_init() - * calls mpt_register()! - */ - fusion_init(); - FusionInitCalled++; - } -#endif - /* * Search for empty callback slot in this order: {N,...,7,6,5,...,1} * (slot/handle 0 is reserved!) @@ -659,8 +634,6 @@ mpt_deregister(int cb_idx) MptEvHandlers[cb_idx] = NULL; last_drv_idx++; - if (isense_idx != -1 && isense_idx <= cb_idx) - isense_idx++; } } @@ -803,56 +776,61 @@ mpt_device_driver_deregister(int cb_idx) * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) + * @ioc: Pointer to MPT adapter structure * * Returns pointer to a MPT request frame or %NULL if none are available * or IOC is not active. */ MPT_FRAME_HDR* -mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp) +mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) { MPT_FRAME_HDR *mf; unsigned long flags; + u16 req_idx; /* Request index */ + + /* validate handle and ioc identifier */ #ifdef MFCNT - if (!iocp->active) + if (!ioc->active) printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n"); #endif /* If interrupts are not attached, do not return a request frame */ - if (!iocp->active) + if (!ioc->active) return NULL; - spin_lock_irqsave(&iocp->FreeQlock, flags); - if (! Q_IS_EMPTY(&iocp->FreeQ)) { + spin_lock_irqsave(&ioc->FreeQlock, flags); + if (!list_empty(&ioc->FreeQ)) { int req_offset; - mf = iocp->FreeQ.head; - Q_DEL_ITEM(&mf->u.frame.linkage); + mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, + u.frame.linkage.list); + list_del(&mf->u.frame.linkage.list); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ - req_offset = (u8 *)mf - (u8 *)iocp->req_frames; + req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ - mf->u.frame.hwhdr.msgctxu.fld.req_idx = - cpu_to_le16(req_offset / iocp->req_sz); + req_idx = cpu_to_le16(req_offset / ioc->req_sz); + mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; + ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */ #ifdef MFCNT - iocp->mfcnt++; + ioc->mfcnt++; #endif } else mf = NULL; - spin_unlock_irqrestore(&iocp->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); #ifdef MFCNT if (mf == NULL) - printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth); + printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth); mfcounter++; if (mfcounter == PRINT_MF_COUNT) - printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth); + printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth); #endif dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", - iocp->name, handle, iocid, mf)); + ioc->name, handle, ioc->id, mf)); return mf; } @@ -861,23 +839,25 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp) * mpt_put_msg_frame - Send a protocol specific MPT request frame * to a IOC. * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) + * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine posts a MPT request frame to the request post FIFO of a * specific MPT adapter. */ void -mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) +mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { u32 mf_dma_addr; int req_offset; + u16 req_idx; /* Request index */ /* ensure values are reset properly! */ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ - req_offset = (u8 *)mf - (u8 *)iocp->req_frames; - /* u16! */ - mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); + req_offset = (u8 *)mf - (u8 *)ioc->req_frames; + /* u16! */ + req_idx = cpu_to_le16(req_offset / ioc->req_sz); + mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx; mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; #ifdef MPT_DEBUG_MSG_FRAME @@ -886,8 +866,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) int ii, n; printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", - iocp->name, m); - n = iocp->req_sz/4 - 1; + ioc->name, m); + n = ioc->req_sz/4 - 1; while (m[n] == 0) n--; for (ii=0; ii<=n; ii++) { @@ -899,32 +879,33 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) } #endif - mf_dma_addr = iocp->req_frames_low_dma + req_offset; - CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); + mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; + dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); + CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) + * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */ void -mpt_free_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf) +mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { unsigned long flags; /* Put Request back on FreeQ! */ - spin_lock_irqsave(&iocp->FreeQlock, flags); - Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); + spin_lock_irqsave(&ioc->FreeQlock, flags); + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT - iocp->mfcnt--; + ioc->mfcnt--; #endif - spin_unlock_irqrestore(&iocp->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -956,47 +937,12 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) } } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_add_chain - Place a chain SGE at address pAddr. - * @pAddr: virtual address for SGE - * @next: nextChainOffset value (u32's) - * @length: length of next SGL segment - * @dma_addr: Physical address - * - * This routine places a MPT request frame back on the MPT adapter's - * FreeQ. - */ -void -mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) -{ - if (sizeof(dma_addr_t) == sizeof(u64)) { - SGEChain64_t *pChain = (SGEChain64_t *) pAddr; - u32 tmp = dma_addr & 0xFFFFFFFF; - - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - - pChain->NextChainOffset = next; - - pChain->Address.Low = cpu_to_le32(tmp); - tmp = (u32) ((u64)dma_addr >> 32); - pChain->Address.High = cpu_to_le32(tmp); - } else { - SGEChain32_t *pChain = (SGEChain32_t *) pAddr; - pChain->Length = cpu_to_le16(length); - pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); - pChain->NextChainOffset = next; - pChain->Address = cpu_to_le32(dma_addr); - } -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_send_handshake_request - Send MPT request via doorbell * handshake method. * @handle: Handle of registered MPT protocol driver - * @iocid: IOC unique identifier (integer) + * @ioc: Pointer to MPT adapter structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. @@ -1010,7 +956,7 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) * Returns 0 for success, non-zero for failure. */ int -mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req, int sleepFlag) +mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { int r = 0; u8 *req_as_bytes; @@ -1026,37 +972,38 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req * setting cb_idx/req_idx. But ONLY if this request * is in proper (pre-alloc'd) request buffer range... */ - ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); - if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) { + ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req); + if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) { MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; } /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); - CHIPREG_WRITE32(&iocp->chip->Doorbell, + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + + CHIPREG_WRITE32(&ioc->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<chip->Doorbell) & MPI_DOORBELL_ACTIVE)) + if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", - iocp->name, ii)); + ioc->name, ii)); - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - r = WaitForDoorbellAck(iocp, 5, sleepFlag); - if (r < 0) + if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { return -2; - + } + /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (ii = 0; ii < reqBytes/4; ii++) { @@ -1066,21 +1013,21 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req (req_as_bytes[(ii*4) + 1] << 8) | (req_as_bytes[(ii*4) + 2] << 16) | (req_as_bytes[(ii*4) + 3] << 24)); - CHIPREG_WRITE32(&iocp->chip->Doorbell, word); - r = WaitForDoorbellAck(iocp, 5, sleepFlag); - if (r < 0) { + CHIPREG_WRITE32(&ioc->chip->Doorbell, word); + if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { r = -3; break; } } - if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0) + if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0) r = 0; else r = -4; /* Make sure there are no doorbells */ - CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + return r; } @@ -1130,7 +1077,7 @@ static int __devinit mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) { MPT_ADAPTER *ioc; - u8 *mem; + u8 __iomem *mem; unsigned long mem_phys; unsigned long port; u32 msize; @@ -1141,11 +1088,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) u8 revision; u8 pcixcmd; static int mpt_ids = 0; +#ifdef CONFIG_PROC_FS struct proc_dir_entry *dent, *ent; +#endif if (pci_enable_device(pdev)) return r; + dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n")); + if (!pci_set_dma_mask(pdev, mask)) { dprintk((KERN_INFO MYNAM ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); @@ -1170,9 +1121,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; - + ioc->pcidev = pdev; - ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); @@ -1195,7 +1145,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Initialize the running configQ head. */ - Q_INIT(&ioc->configQ, Q_ITEM); + INIT_LIST_HEAD(&ioc->configQ); /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); @@ -1223,8 +1173,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -EINVAL; } - dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize)); - dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize)); + dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize)); + dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize)); mem = NULL; /* Get logical ptr for PciMem0 space */ @@ -1236,37 +1186,36 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -EINVAL; } ioc->memmap = mem; - dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); + dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); - dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", + dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", &ioc->facts, &ioc->pfacts[0])); ioc->mem_phys = mem_phys; - ioc->chip = (SYSIF_REGS*)mem; + ioc->chip = (SYSIF_REGS __iomem *)mem; - /* Save Port IO values incase we need to do downloadboot */ + /* Save Port IO values in case we need to do downloadboot */ { u8 *pmem = (u8*)port; ioc->pio_mem_phys = port; - ioc->pio_chip = (SYSIF_REGS*)pmem; + ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; } - ioc->chip_type = FCUNK; if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) { - ioc->chip_type = FC909; ioc->prod_name = "LSIFC909"; + ioc->bus_type = FC; } if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929) { - ioc->chip_type = FC929; ioc->prod_name = "LSIFC929"; + ioc->bus_type = FC; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919) { - ioc->chip_type = FC919; ioc->prod_name = "LSIFC919"; + ioc->bus_type = FC; } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) { - ioc->chip_type = FC929X; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + ioc->bus_type = FC; if (revision < XL_929) { ioc->prod_name = "LSIFC929X"; /* 929X Chip Fix. Set Split transactions level @@ -1285,8 +1234,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) { - ioc->chip_type = FC919X; ioc->prod_name = "LSIFC919X"; + ioc->bus_type = FC; /* 919X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ @@ -1295,8 +1244,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_write_config_byte(pdev, 0x6a, pcixcmd); } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { - ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; + ioc->bus_type = SCSI; /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ @@ -1308,13 +1257,12 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { - ioc->chip_type = C1035; ioc->prod_name = "LSI53C1035"; + ioc->bus_type = SCSI; } sprintf(ioc->name, "ioc%d", ioc->id); - Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); spin_lock_init(&ioc->FreeQlock); /* Disable all! */ @@ -1337,7 +1285,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", ioc->name, __irq_itoa(pdev->irq)); #endif - Q_DEL_ITEM(ioc); list_del(&ioc->list); iounmap(mem); kfree(ioc); @@ -1359,9 +1306,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* NEW! 20010220 -sralston * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) - || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) - mpt_detect_bound_ports(ioc, pdev); + mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { @@ -1369,7 +1314,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); - Q_DEL_ITEM(ioc); list_del(&ioc->list); free_irq(ioc->pci_irq, ioc); iounmap(mem); @@ -1386,6 +1330,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } +#ifdef CONFIG_PROC_FS /* * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter. */ @@ -1402,6 +1347,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id) ent->data = ioc; } } +#endif return 0; } @@ -1515,7 +1461,7 @@ mptbase_suspend(struct pci_dev *pdev, u32 state) } } - pci_save_state(pdev, ioc->PciState); + pci_save_state(pdev); /* put ioc into READY_STATE */ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { @@ -1555,7 +1501,7 @@ mptbase_resume(struct pci_dev *pdev) ioc->name, pdev, pci_name(pdev), device_state); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, ioc->PciState); + pci_restore_state(pdev); pci_enable_device(pdev); /* enable interrupts */ @@ -1625,7 +1571,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int hard_reset_done = 0; int alt_ioc_ready = 0; int hard; - int r; + int rc=0; int ii; int handlers; int ret = 0; @@ -1675,39 +1621,37 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and 1 if a hard reset was performed. */ if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { - if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) + if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) alt_ioc_ready = 1; else printk(KERN_WARNING MYNAM - ": alt-%s: (%d) Not ready WARNING!\n", - ioc->alt_ioc->name, r); + ": alt-%s: Not ready WARNING!\n", + ioc->alt_ioc->name); } for (ii=0; ii<5; ii++) { - /* Get IOC facts! Allow 1 retry */ - if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) { - dinitprintk((MYIOC_s_INFO_FMT - "ii=%d IocFacts failed r=%x\n", ioc->name, ii, r)); - } else + /* Get IOC facts! Allow 5 retries */ + if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) break; } + - if (r) { - dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed r=%x\n", ioc->name, r)); + if (ii == 5) { + dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); ret = -2; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); } - + if (alt_ioc_ready) { - if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { - dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed r=%x\n", ioc->name, r)); + if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { + dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); /* Retry - alt IOC was initialized once */ - r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); + rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); } - if (r) { - dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed r=%x\n", ioc->name, r)); + if (rc) { + dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { @@ -1720,29 +1664,29 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * init as upper addresses are needed for init. * If fails, continue with alt-ioc processing */ - if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0)) + if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) ret = -3; /* May need to check/upload firmware & data here! * If fails, continue with alt-ioc processing */ - if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0)) + if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) ret = -4; // NEW! - if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) { + if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", - ioc->alt_ioc->name, r); + ioc->alt_ioc->name, rc); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } if (alt_ioc_ready) { - if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { + if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { alt_ioc_ready = 0; reset_alt_ioc_active = 0; printk(KERN_WARNING MYNAM ": alt-%s: (%d) init failure WARNING!\n", - ioc->alt_ioc->name, r); + ioc->alt_ioc->name, rc); } } @@ -1754,18 +1698,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* Controller is not operational, cannot do upload */ if (ret == 0) { - r = mpt_do_upload(ioc, sleepFlag); - if (r != 0) - printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); - } - - /* Handle the alt IOC too */ - if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){ - ddlprintk((MYIOC_s_INFO_FMT - "Alt-ioc firmware upload required!\n", - ioc->name)); - r = mpt_do_upload(ioc->alt_ioc, sleepFlag); - if (r != 0) + rc = mpt_do_upload(ioc, sleepFlag); + if (rc != 0) printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); } } @@ -1804,7 +1738,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) @@ -1859,19 +1793,19 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * MptResetHandlers[] registered yet. */ if (hard_reset_done) { - r = handlers = 0; + rc = handlers = 0; for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if ((ret == 0) && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); + rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); handlers++; } if (alt_ioc_ready && MptResetHandlers[ii]) { dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ioc->name, ioc->alt_ioc->name, ii)); - r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); + rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } @@ -1932,84 +1866,90 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) /* * mpt_adapter_disable - Disable misbehaving MPT adapter. * @this: Pointer to MPT adapter structure - * @free: Free up alloc'd reply, request, etc. */ static void -mpt_adapter_disable(MPT_ADAPTER *this, int freeup) +mpt_adapter_disable(MPT_ADAPTER *ioc) { - if (this != NULL) { - int sz=0; - int ret; - - if (this->cached_fw != NULL) { - ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n")); + int sz; + int ret; - if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) { - printk(KERN_WARNING MYNAM - ": firmware downloadboot failure (%d)!\n", ret); - } + if (ioc->cached_fw != NULL) { + ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); + if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) { + printk(KERN_WARNING MYNAM + ": firmware downloadboot failure (%d)!\n", ret); } + } - /* Disable adapter interrupts! */ - CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); - this->active = 0; - /* Clear any lingering interrupt */ - CHIPREG_WRITE32(&this->chip->IntStatus, 0); - - if (freeup && this->fifo_pool != NULL) { - pci_free_consistent(this->pcidev, - this->fifo_pool_sz, - this->fifo_pool, this->fifo_pool_dma); - this->reply_frames = NULL; - this->reply_alloc = NULL; - this->req_frames = NULL; - this->req_alloc = NULL; - this->chain_alloc = NULL; - this->fifo_pool = NULL; - this->alloc_total -= this->fifo_pool_sz; - } - if (freeup && this->sense_buf_pool != NULL) { - sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC); - pci_free_consistent(this->pcidev, sz, - this->sense_buf_pool, this->sense_buf_pool_dma); - this->sense_buf_pool = NULL; - this->alloc_total -= sz; - } + /* Disable adapter interrupts! */ + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); + ioc->active = 0; + /* Clear any lingering interrupt */ + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - if (freeup && this->events != NULL){ - sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); - kfree(this->events); - this->events = NULL; - this->alloc_total -= sz; - } + if (ioc->alloc != NULL) { + sz = ioc->alloc_sz; + dexitprintk((KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n", + ioc->name, ioc->alloc, ioc->alloc_sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->alloc, ioc->alloc_dma); + ioc->reply_frames = NULL; + ioc->req_frames = NULL; + ioc->alloc = NULL; + ioc->alloc_total -= sz; + } - if (freeup && this->cached_fw != NULL) { + if (ioc->sense_buf_pool != NULL) { + sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); + pci_free_consistent(ioc->pcidev, sz, + ioc->sense_buf_pool, ioc->sense_buf_pool_dma); + ioc->sense_buf_pool = NULL; + ioc->alloc_total -= sz; + } - sz = this->facts.FWImageSize; - pci_free_consistent(this->pcidev, sz, - this->cached_fw, this->cached_fw_dma); - this->cached_fw = NULL; - this->alloc_total -= sz; - } + if (ioc->events != NULL){ + sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); + kfree(ioc->events); + ioc->events = NULL; + ioc->alloc_total -= sz; + } - if (freeup && this->spi_data.nvram != NULL) { - kfree(this->spi_data.nvram); - this->spi_data.nvram = NULL; - } + if (ioc->cached_fw != NULL) { + sz = ioc->facts.FWImageSize; + pci_free_consistent(ioc->pcidev, sz, + ioc->cached_fw, ioc->cached_fw_dma); + ioc->cached_fw = NULL; + ioc->alloc_total -= sz; + } - if (freeup && this->spi_data.pIocPg3 != NULL) { - kfree(this->spi_data.pIocPg3); - this->spi_data.pIocPg3 = NULL; - } + if (ioc->spi_data.nvram != NULL) { + kfree(ioc->spi_data.nvram); + ioc->spi_data.nvram = NULL; + } - if (freeup && this->spi_data.pIocPg4 != NULL) { - sz = this->spi_data.IocPg4Sz; - pci_free_consistent(this->pcidev, sz, - this->spi_data.pIocPg4, - this->spi_data.IocPg4_dma); - this->spi_data.pIocPg4 = NULL; - this->alloc_total -= sz; - } + if (ioc->spi_data.pIocPg3 != NULL) { + kfree(ioc->spi_data.pIocPg3); + ioc->spi_data.pIocPg3 = NULL; + } + + if (ioc->spi_data.pIocPg4 != NULL) { + sz = ioc->spi_data.IocPg4Sz; + pci_free_consistent(ioc->pcidev, sz, + ioc->spi_data.pIocPg4, + ioc->spi_data.IocPg4_dma); + ioc->spi_data.pIocPg4 = NULL; + ioc->alloc_total -= sz; + } + + if (ioc->ReqToChain != NULL) { + kfree(ioc->ReqToChain); + kfree(ioc->RequestNB); + ioc->ReqToChain = NULL; + } + + if (ioc->ChainToChain != NULL) { + kfree(ioc->ChainToChain); + ioc->ChainToChain = NULL; } } @@ -2017,43 +1957,43 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup) /* * mpt_adapter_dispose - Free all resources associated with a MPT * adapter. - * @this: Pointer to MPT adapter structure + * @ioc: Pointer to MPT adapter structure * * This routine unregisters h/w resources and frees all alloc'd memory * associated with a MPT adapter structure. */ static void -mpt_adapter_dispose(MPT_ADAPTER *this) +mpt_adapter_dispose(MPT_ADAPTER *ioc) { - if (this != NULL) { + if (ioc != NULL) { int sz_first, sz_last; - sz_first = this->alloc_total; + sz_first = ioc->alloc_total; - mpt_adapter_disable(this, 1); + mpt_adapter_disable(ioc); - if (this->pci_irq != -1) { - free_irq(this->pci_irq, this); - this->pci_irq = -1; + if (ioc->pci_irq != -1) { + free_irq(ioc->pci_irq, ioc); + ioc->pci_irq = -1; } - if (this->memmap != NULL) - iounmap((u8 *) this->memmap); + if (ioc->memmap != NULL) + iounmap(ioc->memmap); #if defined(CONFIG_MTRR) && 0 - if (this->mtrr_reg > 0) { - mtrr_del(this->mtrr_reg, 0, 0); - dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name)); + if (ioc->mtrr_reg > 0) { + mtrr_del(ioc->mtrr_reg, 0, 0); + dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); } #endif /* Zap the adapter lookup ptr! */ - list_del(&this->list); + list_del(&ioc->list); - sz_last = this->alloc_total; + sz_last = ioc->alloc_total; dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", - this->name, sz_first-sz_last+(int)sizeof(*this), sz_first)); - kfree(this); + ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); + kfree(ioc); } } @@ -2141,20 +2081,8 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } /* Is it already READY? */ - if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) { - if ((int)ioc->chip_type <= (int)FC929) - return 0; - else { - return 0; - /* Workaround from broken 1030 FW. - * Force a diagnostic reset if fails. - */ -/* if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) - return 0; - else - statefault = 4; */ - } - } + if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) + return 0; /* * Check to see if IOC is in FAULT state. @@ -2228,13 +2156,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) ii++; cntdn--; if (!cntdn) { printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", - ioc->name, (ii+5)/HZ); + ioc->name, (int)((ii+5)/HZ)); return -ETIME; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible(1); } else { mdelay (1); /* 1 msec delay */ } @@ -2292,7 +2219,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) int r; int req_sz; int reply_sz; - u32 status; + int sz; + u32 status, vv; + u8 shiftFactor=1; /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { @@ -2315,7 +2244,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) get_facts.Function = MPI_FUNCTION_IOC_FACTS; /* Assert: All other get_facts fields are zero! */ - dinitprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name)); + dinitprintk((MYIOC_s_INFO_FMT + "Sending get IocFacts request req_sz=%d reply_sz=%d\n", + ioc->name, req_sz, reply_sz)); /* No non-zero fields in the get_facts request are greater than * 1 byte in size, so we can just fire it off as is. @@ -2388,6 +2319,13 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) facts->FWImageSize = le32_to_cpu(facts->FWImageSize); } + sz = facts->FWImageSize; + if ( sz & 0x01 ) + sz += 1; + if ( sz & 0x02 ) + sz += 2; + facts->FWImageSize = sz; + if (!facts->RequestFrameSize) { /* Something is wrong! */ printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n", @@ -2395,6 +2333,18 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) return -55; } + r = sz = le32_to_cpu(facts->BlockSize); + vv = ((63 / (sz * 4)) + 1) & 0x03; + ioc->NB_for_64_byte_frame = vv; + while ( sz ) + { + shiftFactor++; + sz = sz >> 1; + } + ioc->NBShiftFactor = shiftFactor; + dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", + ioc->name, vv, shiftFactor, r)); + if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* * Set values for this IOC's request & reply frame sizes, @@ -2405,9 +2355,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) ioc->reply_sz = MPT_REPLY_FRAME_SIZE; ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); - dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", + dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); - dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", + dinitprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", ioc->name, ioc->req_sz, ioc->req_depth)); /* Get port facts! */ @@ -2416,7 +2366,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) } } else { printk(MYIOC_s_ERR_FMT - "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n", + "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n", ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32))); return -66; @@ -2465,7 +2415,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) get_pfacts.PortNumber = portnum; /* Assert: All other get_pfacts fields are zero! */ - dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n", + dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n", ioc->name, portnum)); /* No non-zero fields in the get_pfacts request are greater than @@ -2516,43 +2466,33 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) memset(&init_reply, 0, sizeof(init_reply)); ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER; -/* ioc_init.ChainOffset = 0; */ ioc_init.Function = MPI_FUNCTION_IOC_INIT; -/* ioc_init.Flags = 0; */ /* If we are in a recovery mode and we uploaded the FW image, * then this pointer is not NULL. Skip the upload a second time. * Set this flag if cached_fw set for either IOC. */ - ioc->upload_fw = 0; - ioc_init.Flags = 0; - if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) { - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) - ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE; - else - ioc->upload_fw = 1; - } - ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n", - ioc->name, ioc_init.Flags, ioc->upload_fw)); + if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) + ioc->upload_fw = 1; + else + ioc->upload_fw = 0; + ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", + ioc->name, ioc->upload_fw, ioc->facts.Flags)); - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - } else { + else ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - } + ioc_init.MaxBuses = MPT_MAX_BUS; -/* ioc_init.MsgFlags = 0; */ -/* ioc_init.MsgContext = cpu_to_le32(0x00000000); */ ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ - - ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize; if (sizeof(dma_addr_t) == sizeof(u64)) { /* Save the upper 32-bits of the request * (reply) and sense buffers. */ - ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); + ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32)); ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); } else { /* Force 32-bit addressing */ @@ -2590,15 +2530,14 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible(1); } else { mdelay(1); } if (!cntdn) { printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n", - ioc->name, (count+5)/HZ); + ioc->name, (int)((count+5)/HZ)); return -9; } @@ -2644,12 +2583,12 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* port_enable.MsgFlags = 0; */ /* port_enable.MsgContext = 0; */ - dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n", + dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n", ioc->name, portnum, &port_enable)); /* RAID FW may take a long time to enable */ - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); } else { @@ -2668,20 +2607,22 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) } /* - * Inputs: size - total FW bytes - * Outputs: frags - number of fragments needed - * Return NULL if failed. + * ioc: Pointer to MPT_ADAPTER structure + * size - total FW bytes */ void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) { - /* cached_fw - */ - - if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) ) - ioc->alloc_total += size; + if (ioc->cached_fw) + return; /* use already allocated memory */ + if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { + ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */ + ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma; + } else { + if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) ) + ioc->alloc_total += size; + } } - /* * If alt_img is NULL, delete from ioc structure. * Else, delete a secondary image in same format. @@ -2692,6 +2633,8 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; + dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); ioc->cached_fw = NULL; @@ -2725,30 +2668,24 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) int sgeoffset; u32 flagsLength; int ii, sz, reply_sz; - int cmdStatus, freeMem = 0; + int cmdStatus; - /* If the image size is 0 or if the pointer is - * not NULL (error), we are done. + /* If the image size is 0, we are done. */ - if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw) + if ((sz = ioc->facts.FWImageSize) == 0) return 0; - if ( sz & 0x01 ) - sz += 1; - if ( sz & 0x02 ) - sz += 2; - mpt_alloc_fw_memory(ioc, sz); + dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", + ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); + if (ioc->cached_fw == NULL) { /* Major Failure. */ return -ENOMEM; } - dinitprintk((KERN_WARNING MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", - ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); - prequest = (FWUpload_t *)&request; preply = (FWUploadReply_t *)&reply; @@ -2797,23 +2734,11 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n", ioc->name, cmdStatus)); - /* Check to see if we have a copy of this image in - * host memory already. - */ - if (cmdStatus == 0) { - ioc->upload_fw = 0; - if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) - freeMem = 1; - } - - /* We already have a copy of this image or - * we had some type of an error - either the handshake - * failed (i != 0) or the command did not complete successfully. - */ - if (cmdStatus || freeMem) { + + if (cmdStatus) { - ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n", - ioc->name, cmdStatus ? "incomplete" : "duplicate")); + ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n", + ioc->name)); mpt_free_fw_memory(ioc); } @@ -2841,28 +2766,26 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) MpiExtImageHeader_t *pExtImage; u32 fwSize; u32 diag0val; -#ifdef MPT_DEBUG - u32 diag1val = 0; -#endif - int count = 0; + int count; u32 *ptrFw; u32 diagRwData; u32 nextImage; u32 load_addr; - u32 ioc_state; + u32 ioc_state=0; ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); - /* Get dma_addr and data transfer size. - */ if ( ioc->facts.FWImageSize == 0 ) return -1; - /* Get the DMA from ioc or ioc->alt_ioc */ if (ioc->cached_fw == NULL) return -2; + /* prevent a second downloadboot and memory free with alt_ioc */ + if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) + ioc->alt_ioc->cached_fw = NULL; + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); @@ -2870,18 +2793,16 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - diag0val |= (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM)); - /* wait 100 msec */ + /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); + msleep_interruptible(1); } else { - mdelay (100); + mdelay (1); } + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); for (count = 0; count < 30; count ++) { @@ -2893,8 +2814,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) } /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible (1000); } else { mdelay (1000); } @@ -2914,8 +2834,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); /* Set the DiagRwEn and Disable ARM bits */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, (diag0val | MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; fwSize = (pFwHeader->ImageSize + 3)/4; @@ -2961,15 +2880,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue); - /* clear the PREVENT_IOC_BOOT bit */ - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT\n", - ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", - ioc->name, diag0val)); - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - /* Clear the internal flash bad bit - autoincrementing register, * so must do two writes. */ @@ -2980,28 +2890,13 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off DISABLE_ARM, RW_ENABLE, RESET_HISTORY\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_RESET_HISTORY); + diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", ioc->name, diag0val)); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - /* wait 100 msec */ - if (sleepFlag == CAN_SLEEP) { - ddlprintk((MYIOC_s_INFO_FMT "CAN_SLEEP 100 msec before reset the sequencer\n", ioc->name)); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); - } else { - ddlprintk((MYIOC_s_INFO_FMT "mdelay 100 msec before reset the sequencer\n", ioc->name)); - mdelay (100); - } - - diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - if ( diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM) ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed, diag0val=%x FLASH_BAD_SIG | DISABLE_ARM on\n ", - ioc->name, diag0val)); - } /* Write 0xFF to reset the sequencer */ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); @@ -3009,26 +2904,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", ioc->name, count, ioc_state)); -/* if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { - if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) { - ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed\n", - ioc->name)); - return -EFAULT; - } - } */ - /* wait 2 sec */ -/* if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(5000 * HZ / 1000); - } else { - mdelay (5000); - } */ - + if ((SendIocInit(ioc, sleepFlag)) != 0) { + ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", + ioc->name)); + return -EFAULT; + } + ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n", + ioc->name)); return 0; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible (10); } else { mdelay (10); } @@ -3068,19 +2954,18 @@ static int KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) { int hard_reset_done = 0; - u32 ioc_state; - int cntdn, cnt = 0; + u32 ioc_state=0; + int cnt,cntdn; dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. */ SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible (1000); } else { mdelay (1000); } @@ -3090,26 +2975,26 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) if (hard_reset_done < 0) return hard_reset_done; - dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n", + dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n", ioc->name)); - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20; /* 20 seconds */ + cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */ for (cnt=0; cntname, cnt)); + ioc_state = mpt_GetIocState(ioc, 1); + if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) { + dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n", + ioc->name, cnt)); return hard_reset_done; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible (10); } else { mdelay (10); } } - printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n", - ioc->name); + printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n", + ioc->name, ioc_state); return -1; } @@ -3173,8 +3058,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); + msleep_interruptible (100); } else { mdelay (100); } @@ -3199,12 +3083,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n", ioc->name, diag0val, diag1val)); #endif - /* Write the PreventIocBoot bit */ - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) { - diag0val |= MPI_DIAG_PREVENT_IOC_BOOT; - CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); - } - /* * Disable the ARM (Bug fix) * @@ -3246,20 +3124,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* FIXME? Examine results here? */ } - if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) { + if (ioc->cached_fw) { /* If the DownloadBoot operation fails, the * IOC will be left unusable. This is a fatal error * case. _diag_reset will return < 0 */ for (count = 0; count < 30; count ++) { diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); -#ifdef MPT_DEBUG - if (ioc->alt_ioc) - diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); - dprintk((MYIOC_s_INFO_FMT - "DbG2b: diag0=%08x, diag1=%08x\n", - ioc->name, diag0val, diag1val)); -#endif if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { break; } @@ -3267,7 +3138,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout(1000 * HZ / 1000); } else { mdelay (1000); } @@ -3294,8 +3165,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep_interruptible (1000); } else { mdelay (1000); } @@ -3329,8 +3199,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100 * HZ / 1000); + msleep_interruptible (100); } else { mdelay (100); } @@ -3419,13 +3288,12 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) count *= 10; printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", - ioc->name, (count+5)/HZ); + ioc->name, (int)((count+5)/HZ)); return -ETIME; } if (sleepFlag == CAN_SLEEP) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible(1); } else { mdelay (1); /* 1 msec delay */ } @@ -3443,35 +3311,45 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * PrimeIocFifos - Initialize IOC request and reply FIFOs. - * @ioc: Pointer to MPT_ADAPTER structure - * - * This routine allocates memory for the MPT reply and request frame - * pools (if necessary), and primes the IOC reply FIFO with - * reply frames. - * - * Returns 0 for success, non-zero for failure. + * initChainBuffers - Allocate memory for and initialize + * chain buffers, chain buffer control arrays and spinlock. + * @hd: Pointer to MPT_SCSI_HOST structure + * @init: If set, initialize the spin lock. */ static int -PrimeIocFifos(MPT_ADAPTER *ioc) +initChainBuffers(MPT_ADAPTER *ioc) { - MPT_FRAME_HDR *mf; - unsigned long b; - unsigned long flags; - dma_addr_t aligned_mem_dma; - u8 *aligned_mem; - int i, sz; - int chain_buffer_sz, reply_buffer_sz, request_buffer_sz; - int scale, num_sge, num_chain; + u8 *mem; + int sz, ii, num_chain; + int scale, num_sge, numSGE; + + /* ReqToChain size must equal the req_depth + * index = req_idx + */ + if (ioc->ReqToChain == NULL) { + sz = ioc->req_depth * sizeof(int); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) + return -1; - /* request buffer size, rounding UP to nearest 4-kB boundary */ - request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128; - request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; + ioc->ReqToChain = (int *) mem; + dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc @ %p, sz=%d bytes\n", + ioc->name, mem, sz)); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) + return -1; - /* reply buffer size */ - reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128; + ioc->RequestNB = (int *) mem; + dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc @ %p, sz=%d bytes\n", + ioc->name, mem, sz)); + } + for (ii = 0; ii < ioc->req_depth; ii++) { + ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN; + } - /* chain buffer size, copied from from mptscsih_initChainBuffers() + /* ChainToChain size must equal the total number + * of chain buffers to be allocated. + * index = chain_idx * * Calculate the number of chain buffers needed(plus 1) per I/O * then multiply the the maximum number of simultaneous cmds @@ -3479,79 +3357,134 @@ PrimeIocFifos(MPT_ADAPTER *ioc) * num_sge = num sge in request frame + last chain buffer * scale = num sge per chain buffer if no chain element */ - scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); if (sizeof(dma_addr_t) == sizeof(u64)) num_sge = scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); else - num_sge = 1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); + num_sge = 1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); + + if (sizeof(dma_addr_t) == sizeof(u64)) { + numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); + } else { + numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); + } + dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n", + ioc->name, num_sge, numSGE)); + + if ( numSGE > MPT_SCSI_SG_DEPTH ) + numSGE = MPT_SCSI_SG_DEPTH; num_chain = 1; - while (MPT_SCSI_SG_DEPTH - num_sge > 0) { + while (numSGE - num_sge > 0) { num_chain++; num_sge += (scale - 1); } num_chain++; - if ((int)ioc->chip_type > (int) FC929) + dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n", + ioc->name, numSGE, num_sge, num_chain)); + + if (ioc->bus_type == SCSI) num_chain *= MPT_SCSI_CAN_QUEUE; else num_chain *= MPT_FC_CAN_QUEUE; - chain_buffer_sz = num_chain * ioc->req_sz; + ioc->num_chain = num_chain; + + sz = num_chain * sizeof(int); + if (ioc->ChainToChain == NULL) { + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) + return -1; + + ioc->ChainToChain = (int *) mem; + dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n", + ioc->name, mem, sz)); + } else { + mem = (u8 *) ioc->ChainToChain; + } + memset(mem, 0xFF, sz); + return num_chain; +} - if(ioc->fifo_pool == NULL) { +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * PrimeIocFifos - Initialize IOC request and reply FIFOs. + * @ioc: Pointer to MPT_ADAPTER structure + * + * This routine allocates memory for the MPT reply and request frame + * pools (if necessary), and primes the IOC reply FIFO with + * reply frames. + * + * Returns 0 for success, non-zero for failure. + */ +static int +PrimeIocFifos(MPT_ADAPTER *ioc) +{ + MPT_FRAME_HDR *mf; + unsigned long flags; + dma_addr_t alloc_dma; + u8 *mem; + int i, reply_sz, sz, total_size, num_chain; - ioc->fifo_pool_sz = request_buffer_sz + - reply_buffer_sz + chain_buffer_sz; + /* Prime reply FIFO... */ - ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev, - ioc->fifo_pool_sz, &ioc->fifo_pool_dma); + if (ioc->reply_frames == NULL) { + if ( (num_chain = initChainBuffers(ioc)) < 0) + return -1; - if( ioc->fifo_pool == NULL) + total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); + dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", + ioc->name, ioc->reply_sz, ioc->reply_depth)); + dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n", + ioc->name, reply_sz, reply_sz)); + + sz = (ioc->req_sz * ioc->req_depth); + dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n", + ioc->name, ioc->req_sz, ioc->req_depth)); + dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n", + ioc->name, sz, sz)); + total_size += sz; + + sz = num_chain * ioc->req_sz; /* chain buffer pool size */ + dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n", + ioc->name, ioc->req_sz, num_chain)); + dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n", + ioc->name, sz, sz, num_chain)); + + total_size += sz; + mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma); + if (mem == NULL) { + printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n", + ioc->name); goto out_fail; + } + + dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n", + ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size)); + + memset(mem, 0, total_size); + ioc->alloc_total += total_size; + ioc->alloc = mem; + ioc->alloc_dma = alloc_dma; + ioc->alloc_sz = total_size; + ioc->reply_frames = (MPT_FRAME_HDR *) mem; + ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); + + alloc_dma += reply_sz; + mem += reply_sz; - ioc->alloc_total += ioc->fifo_pool_sz; - memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz); - - /* reply fifo pointers */ - ioc->reply_alloc = ioc->fifo_pool; - ioc->reply_alloc_dma = ioc->fifo_pool_dma; - /* request fifo pointers */ - ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz; - ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz; - /* chain buffer pointers */ - ioc->chain_alloc = ioc->req_alloc+request_buffer_sz; - ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz; - ioc->chain_alloc_sz = chain_buffer_sz; - - /* Prime reply FIFO... */ - dprintk((KERN_INFO MYNAM ": %s.reply_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, ioc->reply_alloc, - (void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz)); - - b = (unsigned long) ioc->reply_alloc; - b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ - aligned_mem = (u8 *) b; - ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem; - ioc->reply_frames_dma = - (ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc)); - - ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF); - /* Request FIFO - WE manage this! */ - dprintk((KERN_INFO MYNAM ": %s.req_alloc @ %p[%p], sz=%d bytes\n", - ioc->name, ioc->req_alloc, - (void *)(ulong)ioc->req_alloc_dma, request_buffer_sz)); - b = (unsigned long) ioc->req_alloc; - b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */ - aligned_mem = (u8 *) b; - ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem; - ioc->req_frames_dma = - (ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc)); + ioc->req_frames = (MPT_FRAME_HDR *) mem; + ioc->req_frames_dma = alloc_dma; - ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF); + dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n", + ioc->name, mem, (void *)(ulong)alloc_dma)); + + ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); #if defined(CONFIG_MTRR) && 0 /* @@ -3559,79 +3492,94 @@ PrimeIocFifos(MPT_ADAPTER *ioc) * (at least as much as we can; "size and base must be * multiples of 4 kiB" */ - ioc->mtrr_reg = mtrr_add(ioc->fifo_pool, - ioc->fifo_pool_sz, + ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma, + sz, MTRR_TYPE_WRCOMB, 1); dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n", - ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz)); + ioc->name, ioc->req_frames_dma, sz)); #endif - } /* ioc->fifo_pool == NULL */ - - /* Post Reply frames to FIFO - */ - aligned_mem_dma = ioc->reply_frames_dma; - dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n", - ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma)); + for (i = 0; i < ioc->req_depth; i++) { + alloc_dma += ioc->req_sz; + mem += ioc->req_sz; + } - for (i = 0; i < ioc->reply_depth; i++) { - /* Write each address to the IOC! */ - CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma); - aligned_mem_dma += ioc->reply_sz; - } + ioc->ChainBuffer = mem; + ioc->ChainBufferDMA = alloc_dma; + dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n", + ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); - /* Initialize Request frames linked list - */ - aligned_mem_dma = ioc->req_frames_dma; - aligned_mem = (u8 *) ioc->req_frames; - dprintk((KERN_INFO MYNAM ": %s.req_frames @ %p[%p]\n", - ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma)); + /* Initialize the free chain Q. + */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR); - for (i = 0; i < ioc->req_depth; i++) { - mf = (MPT_FRAME_HDR *) aligned_mem; + INIT_LIST_HEAD(&ioc->FreeChainQ); - /* Queue REQUESTs *internally*! */ - Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR); - aligned_mem += ioc->req_sz; - } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + /* Post the chain buffers to the FreeChainQ. + */ + mem = (u8 *)ioc->ChainBuffer; + for (i=0; i < num_chain; i++) { + mf = (MPT_FRAME_HDR *) mem; + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ); + mem += ioc->req_sz; + } + + /* Initialize Request frames linked list + */ + alloc_dma = ioc->req_frames_dma; + mem = (u8 *) ioc->req_frames; + + spin_lock_irqsave(&ioc->FreeQlock, flags); + INIT_LIST_HEAD(&ioc->FreeQ); + for (i = 0; i < ioc->req_depth; i++) { + mf = (MPT_FRAME_HDR *) mem; + + /* Queue REQUESTs *internally*! */ + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); + mem += ioc->req_sz; + } + spin_unlock_irqrestore(&ioc->FreeQlock, flags); - if (ioc->sense_buf_pool == NULL) { sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); ioc->sense_buf_pool = - pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma); - if (ioc->sense_buf_pool == NULL) + pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma); + if (ioc->sense_buf_pool == NULL) { + printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n", + ioc->name); goto out_fail; + } ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF); ioc->alloc_total += sz; + dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n", + ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma)); + + } + + /* Post Reply frames to FIFO + */ + alloc_dma = ioc->alloc_dma; + dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n", + ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); + + for (i = 0; i < ioc->reply_depth; i++) { + /* Write each address to the IOC! */ + CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma); + alloc_dma += ioc->reply_sz; } return 0; out_fail: - if (ioc->fifo_pool != NULL) { + if (ioc->alloc != NULL) { + sz = ioc->alloc_sz; pci_free_consistent(ioc->pcidev, - ioc->fifo_pool_sz, - ioc->fifo_pool, ioc->fifo_pool_dma); + sz, + ioc->alloc, ioc->alloc_dma); ioc->reply_frames = NULL; - ioc->reply_alloc = NULL; ioc->req_frames = NULL; - ioc->req_alloc = NULL; - ioc->chain_alloc = NULL; - ioc->fifo_pool = NULL; - ioc->alloc_total -= ioc->fifo_pool_sz; -#if defined(CONFIG_MTRR) && 0 - if (ioc->mtrr_reg > 0) { - mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n", - ioc->name)); - } -#endif + ioc->alloc_total -= sz; } if (ioc->sense_buf_pool != NULL) { sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); @@ -3662,7 +3610,7 @@ out_fail: * * Returns 0 for success, non-zero for failure. */ -int +static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) { @@ -3693,8 +3641,8 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) failcnt++; - dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n", - ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); + dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n", + ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); /* Read doorbell and check for active bit */ if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) @@ -3728,7 +3676,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, failcnt++; } - dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req)); + dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req)); DBG_DUMP_REQUEST_FRAME_HDR(req) dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n", @@ -3782,8 +3730,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible (1); count++; } } else { @@ -3832,8 +3779,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + msleep_interruptible(1); count++; } } else { @@ -3935,7 +3881,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } #endif - dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name)); + dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name)); DBG_DUMP_REPLY_FRAME(mptReply) dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", @@ -4282,9 +4228,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities); pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface); - if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) + if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; - + dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", + ioc->name, pPP0->Capabilities)); + } ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK; if (data) { @@ -4875,7 +4823,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Add to end of Q, set timer and then issue this command */ spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); + list_add_tail(&pCfg->linkage, &ioc->configQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); @@ -4907,8 +4855,8 @@ int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) { ToolboxIstwiReadWriteRequest_t *pReq; - struct pci_dev *pdev; MPT_FRAME_HDR *mf; + struct pci_dev *pdev; unsigned long flags; int rc; u32 flagsLength; @@ -4986,7 +4934,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) /* Add to end of Q, set timer and then issue this command */ spin_lock_irqsave(&ioc->FreeQlock, flags); - Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM); + list_add_tail(&pCfg->linkage, &ioc->configQ); spin_unlock_irqrestore(&ioc->FreeQlock, flags); add_timer(&pCfg->timer); @@ -5053,13 +5001,8 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * the FIFO's are primed. */ spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&ioc->configQ)){ - pCfg = (CONFIGPARMS *)ioc->configQ.head; - do { - del_timer(&pCfg->timer); - pCfg = (CONFIGPARMS *) (pCfg->linkage.forw); - } while (pCfg != (CONFIGPARMS *)&ioc->configQ); - } + list_for_each_entry(pCfg, &ioc->configQ, linkage) + del_timer(&pCfg->timer); spin_unlock_irqrestore(&ioc->FreeQlock, flags); } else { @@ -5069,19 +5012,12 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * Flush the Q, and wake up all suspended threads. */ spin_lock_irqsave(&ioc->FreeQlock, flags); - if (! Q_IS_EMPTY(&ioc->configQ)){ - pCfg = (CONFIGPARMS *)ioc->configQ.head; - do { - pNext = (CONFIGPARMS *) pCfg->linkage.forw; + list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) { + list_del(&pCfg->linkage); - Q_DEL_ITEM(&pCfg->linkage); - - pCfg->status = MPT_CONFIG_ERROR; - pCfg->wait_done = 1; - wake_up(&mpt_waitq); - - pCfg = pNext; - } while (pCfg != (CONFIGPARMS *)&ioc->configQ); + pCfg->status = MPT_CONFIG_ERROR; + pCfg->wait_done = 1; + wake_up(&mpt_waitq); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); } @@ -5219,19 +5155,10 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo case MPTCTL_DRIVER: if (!ctl++) drvname = "ioctl"; break; - case MPTDMP_DRIVER: - if (!dmp++) drvname = "DMP"; - break; } if (drvname) len += sprintf(buf+len, " Fusion MPT %s driver\n", drvname); - /* - * Handle isense special case, because it - * doesn't do a formal mpt_register call. - */ - if (isense_idx == ii) - len += sprintf(buf+len, " Fusion MPT isense driver\n"); } } @@ -5286,7 +5213,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo len += sprintf(buf+len, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); len += sprintf(buf+len, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", - (void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma); + (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); /* * Rounding UP to nearest 4-kB boundary here... */ @@ -5298,8 +5225,8 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo 4*ioc->facts.RequestFrameSize, ioc->facts.GlobalCredits); - len += sprintf(buf+len, " ReplyFrames @ 0x%p (Dma @ 0x%p)\n", - (void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma); + len += sprintf(buf+len, " Frames @ 0x%p (Dma @ 0x%p)\n", + (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); sz = (ioc->reply_sz * ioc->reply_depth) + 128; len += sprintf(buf+len, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); @@ -5316,7 +5243,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo len += sprintf(buf+len, " PortNumber = %d (of %d)\n", p+1, ioc->facts.NumberOfPorts); - if ((int)ioc->chip_type <= (int)FC929) { + if (ioc->bus_type == FC) { if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; len += sprintf(buf+len, " LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -5592,7 +5519,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } evStr = EventDescriptionStr(event, evData0); - dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", + devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", ioc->name, evStr, event)); @@ -5664,7 +5591,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptEvHandlers[ii]) { - dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", + devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", ioc->name, ii)); r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; @@ -5677,8 +5604,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n", - ioc->name, ii); + devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + ioc->name, ii)); } } @@ -5702,9 +5629,8 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) "FC Link", "Context Manager", "Invalid Field Offset", "State Change Info" }; u8 subcl = (log_info >> 24) & 0x7; -// u32 SubCl = log_info & 0x27000000; - printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}", + printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n", ioc->name, log_info, subcl_str[subcl]); } @@ -5907,53 +5833,8 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI - * OpCode strings from the (optional) isense module. - * @ascqTable: Pointer to ASCQ_Table_t structure - * @ascqtbl_sz: Number of entries in ASCQ_Table - * @opsTable: Pointer to array of SCSI OpCode strings (char pointers) - * - * Specialized driver registration routine for the isense driver. - */ -int -mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable) -{ - int r = 0; - - if (ascqTable && ascqtbl_sz && opsTable) { - mpt_v_ASCQ_TablePtr = ascqTable; - mpt_ASCQ_TableSz = ascqtbl_sz; - mpt_ScsiOpcodesPtr = opsTable; - printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n"); - isense_idx = last_drv_idx; - r = 1; - } - return r; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI - * OpCode strings from the isense driver. - * - * Specialized driver deregistration routine for the isense driver. - */ -void -mpt_deregister_ascqops_strings(void) -{ - mpt_v_ASCQ_TablePtr = NULL; - mpt_ASCQ_TableSz = 0; - mpt_ScsiOpcodesPtr = NULL; - printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n"); - isense_idx = -1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - EXPORT_SYMBOL(ioc_list); EXPORT_SYMBOL(mpt_proc_root_dir); -EXPORT_SYMBOL(DmpService); EXPORT_SYMBOL(mpt_register); EXPORT_SYMBOL(mpt_deregister); EXPORT_SYMBOL(mpt_event_register); @@ -5966,9 +5847,7 @@ EXPORT_SYMBOL(mpt_get_msg_frame); EXPORT_SYMBOL(mpt_put_msg_frame); EXPORT_SYMBOL(mpt_free_msg_frame); EXPORT_SYMBOL(mpt_add_sge); -EXPORT_SYMBOL(mpt_add_chain); EXPORT_SYMBOL(mpt_send_handshake_request); -EXPORT_SYMBOL(mpt_handshake_req_reply_wait); EXPORT_SYMBOL(mpt_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); @@ -5982,13 +5861,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); -EXPORT_SYMBOL(mpt_register_ascqops_strings); -EXPORT_SYMBOL(mpt_deregister_ascqops_strings); -EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr); -EXPORT_SYMBOL(mpt_ASCQ_TableSz); -EXPORT_SYMBOL(mpt_ScsiOpcodesPtr); - - static struct pci_driver mptbase_driver = { .name = "mptbase", .id_table = mptbase_pci_table, @@ -6015,11 +5887,6 @@ fusion_init(void) int i; int r; - if (FusionInitCalled++) { - dprintk((KERN_INFO MYNAM ": INFO - Driver late-init entry point called\n")); - return 0; - } - show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); @@ -6030,8 +5897,6 @@ fusion_init(void) MptResetHandlers[i] = NULL; } - DmpService = NULL; - /* NEW! 20010120 -sralston * Register ourselves (mptbase) in order to facilitate * EventNotification handling. diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 8a84b72a3..d9184ac01 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -60,8 +60,6 @@ #include #include -#include "scsi3.h" /* SCSI defines */ - #include "lsi/mpi_type.h" #include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */ #include "lsi/mpi_ioc.h" /* Fusion MPT IOC(ontroller) defs */ @@ -85,8 +83,8 @@ #define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.01.09" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.09" +#define MPT_LINUX_VERSION_COMMON "3.01.18" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.18" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -208,7 +206,6 @@ typedef enum { MPTSCSIH_DRIVER, /* MPT SCSI host (initiator) class */ MPTLAN_DRIVER, /* MPT LAN class */ MPTSTM_DRIVER, /* MPT SCSI target mode class */ - MPTDMP_DRIVER, /* MPT Dynamic Multi-pathing class */ MPTUNKNOWN_DRIVER } MPT_DRIVER_CLASS; @@ -228,8 +225,7 @@ struct mpt_pci_driver{ typedef union _MPT_FRAME_TRACKER { struct { - struct _MPT_FRAME_HDR *forw; - struct _MPT_FRAME_HDR *back; + struct list_head list; u32 arg1; u32 pad; void *argp1; @@ -292,15 +288,6 @@ typedef struct _MPT_FRAME_HDR { #define MPT_REQ_MSGFLAGS_DROPME 0x80 -/* Used for tracking the free request frames - * and free reply frames. - */ -typedef struct _MPT_Q_TRACKER { - MPT_FRAME_HDR *head; - MPT_FRAME_HDR *tail; -} MPT_Q_TRACKER; - - typedef struct _MPT_SGL_HDR { SGESimple32_t sge[1]; } MPT_SGL_HDR; @@ -309,44 +296,6 @@ typedef struct _MPT_SGL64_HDR { SGESimple64_t sge[1]; } MPT_SGL64_HDR; - -typedef struct _Q_ITEM { - struct _Q_ITEM *forw; - struct _Q_ITEM *back; -} Q_ITEM; - -typedef struct _Q_TRACKER { - struct _Q_ITEM *head; - struct _Q_ITEM *tail; -} Q_TRACKER; - -typedef struct _MPT_DONE_Q { - struct _MPT_DONE_Q *forw; - struct _MPT_DONE_Q *back; - void *argp; -} MPT_DONE_Q; - -typedef struct _DONE_Q_TRACKER { - MPT_DONE_Q *head; - MPT_DONE_Q *tail; -} DONE_Q_TRACKER; - -/* - * Chip-specific stuff... FC929 delineates break between - * FC and Parallel SCSI parts. Do NOT re-order. - */ - -typedef enum { - FC919X = 0x0819, - FC929X = 0x0829, - FC909 = 0x0909, - FC919 = 0x0919, - FC929 = 0x0929, - C1030 = 0x1030, - C1035 = 0x1035, - FCUNK = 0xFBAD -} CHIP_TYPE; - /* * System interface register set */ @@ -381,62 +330,32 @@ typedef struct _SYSIF_REGS /* * Dynamic Multi-Pathing specific stuff... */ -#define DMP_MAX_PATHS 8 - -typedef struct _PathInfo { - u8 ioc; - u8 target; - u8 pad; - u8 pflags; -} PathInfo; - -#define PATHINFO_FLAGS_OWNED 0x01 -#define PATHINFO_FLAGS_EXISTS 0x02 -#define PATHINFO_FLAGS_AVAILABLE 0x04 -#define PATHINFO_FLAGS_SECONDARY 0x08 - -#define PFLAGS_EXISTS_AND_AVAIL (PATHINFO_FLAGS_EXISTS|PATHINFO_FLAGS_AVAILABLE) -#define PFLAGS_AVAIL_AND_OWNED (PATHINFO_FLAGS_AVAILABLE|PATHINFO_FLAGS_OWNED) - -typedef struct _ScsiCmndTracker { - void *head; - void *tail; -} ScsiCmndTracker; +/* VirtDevice negoFlags field */ +#define MPT_TARGET_NO_NEGO_WIDE 0x01 +#define MPT_TARGET_NO_NEGO_SYNC 0x02 +#define MPT_TARGET_NO_NEGO_QAS 0x04 +#define MPT_TAPE_NEGO_IDP 0x08 /* * VirtDevice - FC LUN device or SCSI target device - * (used to be FCSCSI_TARGET) */ typedef struct _VirtDevice { - struct _VirtDevice *forw; - struct _VirtDevice *back; struct scsi_device *device; - rwlock_t VdevLock; - int ref_cnt; u8 tflags; u8 ioc_id; u8 target_id; u8 bus_id; u8 minSyncFactor; /* 0xFF is async */ u8 maxOffset; /* 0 if async */ - u8 maxWidth; /* 0 if narrow, 1 if wide*/ - u8 negoFlags; /* bit field, 0 if WDTR/SDTR/QAS allowed */ + u8 maxWidth; /* 0 if narrow, 1 if wide */ + u8 negoFlags; /* bit field, see above */ u8 raidVolume; /* set, if RAID Volume */ u8 type; /* byte 0 of Inquiry data */ u8 cflags; /* controller flags */ u8 rsvd1raid; - int npaths; u16 fc_phys_lun; u16 fc_xlat_lun; - int stall_detected; - PathInfo path[DMP_MAX_PATHS]; - struct timer_list stall_timer; - struct timer_list retry_timer; - struct timer_list gone_timer; - ScsiCmndTracker WaitQ; - ScsiCmndTracker SentQ; - ScsiCmndTracker DoneQ; u32 num_luns; u32 luns[8]; /* Max LUNs is 256 */ u8 pad[4]; @@ -460,18 +379,6 @@ typedef struct _VirtDevice { #define MPT_TARGET_FLAGS_VALID_56 0x10 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20 -#define MPT_TARGET_NO_NEGO_WIDE 0x01 -#define MPT_TARGET_NO_NEGO_SYNC 0x02 -#define MPT_TARGET_NO_NEGO_QAS 0x04 - -typedef struct _VirtDevTracker { - struct _VirtDevice *head; - struct _VirtDevice *tail; - rwlock_t VlistLock; - int pad; -} VirtDevTracker; - - /* * /proc/mpt interface */ @@ -523,6 +430,7 @@ typedef struct _MPT_IOCTL { u8 target; /* target for reset */ void *tmPtr; struct timer_list TMtimer; /* timer function for this adapter */ + struct semaphore sem_ioc; } MPT_IOCTL; /* @@ -586,44 +494,47 @@ typedef struct _ScsiCfgData { */ typedef struct _MPT_ADAPTER { - struct _MPT_ADAPTER *forw; - struct _MPT_ADAPTER *back; int id; /* Unique adapter id N {0,1,2,...} */ int pci_irq; /* This irq */ char name[MPT_NAME_LENGTH]; /* "iocN" */ char *prod_name; /* "LSIFC9x9" */ - volatile SYSIF_REGS *chip; /* == c8817000 (mmap) */ - volatile SYSIF_REGS *pio_chip; /* Programmed IO (downloadboot) */ + SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */ + SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ + u8 bus_type; u32 mem_phys; /* == f4020000 (mmap) */ u32 pio_mem_phys; /* Programmed IO (downloadboot) */ int mem_size; /* mmap memory size */ int alloc_total; u32 last_state; int active; - u8 *fifo_pool; /* dma pool for fifo's */ - dma_addr_t fifo_pool_dma; - int fifo_pool_sz; /* allocated size */ - u8 *chain_alloc; /* chain buffer alloc ptr */ - dma_addr_t chain_alloc_dma; - int chain_alloc_sz; - u8 *reply_alloc; /* Reply frames alloc ptr */ - dma_addr_t reply_alloc_dma; + u8 *alloc; /* frames alloc ptr */ + dma_addr_t alloc_dma; + u32 alloc_sz; MPT_FRAME_HDR *reply_frames; /* Reply msg frames - rounded up! */ - dma_addr_t reply_frames_dma; u32 reply_frames_low_dma; int reply_depth; /* Num Allocated reply frames */ int reply_sz; /* Reply frame size */ - CHIP_TYPE chip_type; + int num_chain; /* Number of chain buffers */ + /* Pool of buffers for chaining. ReqToChain + * and ChainToChain track index of chain buffers. + * ChainBuffer (DMA) virt/phys addresses. + * FreeChainQ (lock) locking mechanisms. + */ + int *ReqToChain; + int *RequestNB; + int *ChainToChain; + u8 *ChainBuffer; + dma_addr_t ChainBufferDMA; + struct list_head FreeChainQ; + spinlock_t FreeChainQlock; /* We (host driver) get to manage our own RequestQueue! */ - u8 *req_alloc; /* Request frames alloc ptr */ - dma_addr_t req_alloc_dma; - MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */ dma_addr_t req_frames_dma; + MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */ u32 req_frames_low_dma; int req_depth; /* Number of request frames */ int req_sz; /* Request frame size (bytes) */ spinlock_t FreeQlock; - MPT_Q_TRACKER FreeQ; + struct list_head FreeQ; /* Pool of SCSI sense buffers for commands coming from * the SCSI mid-layer. We have one 256 byte sense buffer * for each REQ entry. @@ -633,7 +544,7 @@ typedef struct _MPT_ADAPTER u32 sense_buf_low_dma; int mtrr_reg; struct pci_dev *pcidev; /* struct pci_dev pointer */ - u8 *memmap; /* mmap address */ + u8 __iomem *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */ ScsiCfgData spi_data; /* Scsi config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ @@ -645,22 +556,17 @@ typedef struct _MPT_ADAPTER int eventTypes; /* Event logging parameters */ int eventContext; /* Next event context */ int eventLogSize; /* Max number of cached events */ -#ifdef MPTSCSIH_DBG_TIMEOUT - int timeout_hard; - int timeout_delta; - int timeout_cnt; - int timeout_maxcnt; -#endif struct _mpt_ioctl_events *events; /* pointer to event log */ u8 *cached_fw; /* Pointer to FW */ dma_addr_t cached_fw_dma; - Q_TRACKER configQ; /* linked list of config. requests */ + struct list_head configQ; /* linked list of config. requests */ int hs_reply_idx; #ifndef MFCNT u32 pad0; #else u32 mfcnt; #endif + u32 NB_for_64_byte_frame; u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; IOCFactsReply_t facts; @@ -668,22 +574,15 @@ typedef struct _MPT_ADAPTER FCPortPage0_t fc_port_page0[2]; LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; -#ifdef CONFIG_PM - u32 PciState[64]; /* save PCI state to this area */ -#endif u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ - u8 pad1[5]; + u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ + u8 pad1[4]; struct list_head list; + struct net_device *netdev; } MPT_ADAPTER; - -typedef struct _MPT_ADAPTER_TRACKER { - MPT_ADAPTER *head; - MPT_ADAPTER *tail; -} MPT_ADAPTER_TRACKER; - /* * New return value convention: * 1 = Ok to free associated request frame @@ -757,10 +656,10 @@ typedef struct _mpt_sge { #define dexitprintk(x) #endif -#ifdef MPT_DEBUG_RESET -#define drsprintk(x) printk x +#if defined MPT_DEBUG_FAIL || defined (MPT_DEBUG_SG) +#define dfailprintk(x) printk x #else -#define drsprintk(x) +#define dfailprintk(x) #endif #ifdef MPT_DEBUG_HANDSHAKE @@ -769,11 +668,34 @@ typedef struct _mpt_sge { #define dhsprintk(x) #endif +#ifdef MPT_DEBUG_EVENTS +#define devtprintk(x) printk x +#else +#define devtprintk(x) +#endif + +#ifdef MPT_DEBUG_RESET +#define drsprintk(x) printk x +#else +#define drsprintk(x) +#endif + //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) #if defined(MPT_DEBUG_MSG_FRAME) #define dmfprintk(x) printk x +#define DBG_DUMP_REQUEST_FRAME(mfp) \ + { int i, n = 24; \ + u32 *m = (u32 *)(mfp); \ + for (i=0; i> 16; \ + printk("TM_REPLY MessageLength=%d:\n", n); \ + for (i=0; ireply_frames + (ioc)->req_sz * (idx) ) -#define Q_INIT(q,type) (q)->head = (q)->tail = (type*)(q) -#define Q_IS_EMPTY(q) ((Q_ITEM*)(q)->head == (Q_ITEM*)(q)) - -#define Q_ADD_TAIL(qt,i,type) { \ - Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ - Q_ITEM *oldTail = _qt->tail; \ - (i)->forw = (type*)_qt; \ - (i)->back = (type*)oldTail; \ - oldTail->forw = (Q_ITEM*)(i); \ - _qt->tail = (Q_ITEM*)(i); \ -} - -#define Q_ADD_HEAD(qt,i,type) { \ - Q_TRACKER *_qt = (Q_TRACKER*)(qt); \ - Q_ITEM *oldHead = _qt->head; \ - (i)->forw = (type*)oldHead; \ - (i)->back = (type*)_qt; \ - oldHead->back = (Q_ITEM*)(i); \ - _qt->head = (Q_ITEM*)(i); \ -} - -#define Q_DEL_ITEM(i) { \ - Q_ITEM *_forw = (Q_ITEM*)(i)->forw; \ - Q_ITEM *_back = (Q_ITEM*)(i)->back; \ - _back->forw = _forw; \ - _forw->back = _back; \ -} - -#define SWAB4(value) \ - (u32)( (((value) & 0x000000ff) << 24) \ - | (((value) & 0x0000ff00) << 8) \ - | (((value) & 0x00ff0000) >> 8) \ - | (((value) & 0xff000000) >> 24) ) - - #if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) #define DBG_DUMP_REPLY_FRAME(mfp) \ { u32 *m = (u32 *)(mfp); \ @@ -907,6 +829,10 @@ typedef struct _mpt_sge { /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +#define SCSI_STD_SENSE_BYTES 18 +#define SCSI_STD_INQUIRY_BYTES 36 +#define SCSI_MAX_INQUIRY_BYTES 96 + /* * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers * Private to the driver. @@ -945,22 +871,17 @@ typedef struct _MPT_LOCAL_REPLY { #define TM_STATE_IN_PROGRESS (1) #define TM_STATE_ERROR (2) +typedef enum { + FC, + SCSI, + SAS +} BUS_TYPE; + typedef struct _MPT_SCSI_HOST { MPT_ADAPTER *ioc; int port; u32 pad0; struct scsi_cmnd **ScsiLookup; - /* Pool of buffers for chaining. ReqToChain - * and ChainToChain track index of chain buffers. - * ChainBuffer (DMA) virt/phys addresses. - * FreeChainQ (lock) locking mechanisms. - */ - int *ReqToChain; - int *ChainToChain; - u8 *ChainBuffer; - dma_addr_t ChainBufferDMA; - MPT_Q_TRACKER FreeChainQ; - spinlock_t FreeChainQlock; u32 qtag_tick; VirtDevice **Targets; MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ @@ -969,23 +890,12 @@ typedef struct _MPT_SCSI_HOST { /* Pool of memory for holding SCpnts before doing * OS callbacks. freeQ is the free pool. */ - u8 *memQ; - DONE_Q_TRACKER freeQ; - DONE_Q_TRACKER doneQ; /* Holds Linux formmatted requests */ - DONE_Q_TRACKER pendingQ; /* Holds MPI formmatted requests */ - MPT_Q_TRACKER taskQ; /* TM request Q */ - spinlock_t freedoneQlock; - int taskQcnt; - int num_chain; /* Number of chain buffers */ - int max_sge; /* Max No of SGE*/ - u8 numTMrequests; u8 tmPending; u8 resetPending; - u8 is_spi; /* Parallel SCSI i/f */ u8 negoNvram; /* DV disabled, nego NVRAM */ - u8 is_multipath; /* Multi-path compatible */ + u8 pad1; u8 tmState; - u8 rsvd[1]; + u8 rsvd[2]; MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; @@ -1004,32 +914,12 @@ typedef struct _MPT_SCSI_HOST { /* Forward decl, a strange C thing, to prevent gcc compiler warnings */ struct scsi_cmnd; -/* - * DMP service layer structure / API interface - */ -typedef struct _DmpServices { - VirtDevTracker VdevList; - struct semaphore *Daemon; - int (*ScsiPathSelect) - (struct scsi_cmnd *, MPT_SCSI_HOST **hd, int *target, int *lun); - int (*DmpIoDoneChk) - (MPT_SCSI_HOST *, struct scsi_cmnd *, - SCSIIORequest_t *, - SCSIIOReply_t *); - void (*mptscsih_scanVlist) - (MPT_SCSI_HOST *, int portnum); - int (*ScsiAbort) - (struct scsi_cmnd *); - int (*ScsiBusReset) - (struct scsi_cmnd *); -} DmpServices_t; - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Generic structure passed to the base mpt_config function. */ typedef struct _x_config_parms { - Q_ITEM linkage; /* linked list */ + struct list_head linkage; /* linked list */ struct timer_list timer; /* timer function for this request */ ConfigPageHeader_t *hdr; dma_addr_t physAddr; @@ -1055,16 +945,12 @@ extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func); extern void mpt_reset_deregister(int cb_idx); extern int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx); extern void mpt_device_driver_deregister(int cb_idx); -extern int mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable); -extern void mpt_deregister_ascqops_strings(void); extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc); -extern void mpt_free_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); +extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); -extern void mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr); extern int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); -extern int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag); extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); @@ -1081,25 +967,13 @@ extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); */ extern struct list_head ioc_list; extern struct proc_dir_entry *mpt_proc_root_dir; -extern DmpServices_t *DmpService; extern int mpt_lan_index; /* needed by mptlan.c */ extern int mpt_stm_index; /* needed by mptstm.c */ -extern void *mpt_v_ASCQ_TablePtr; -extern const char **mpt_ScsiOpcodesPtr; -extern int mpt_ASCQ_TableSz; - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* } __KERNEL__ */ -/* - * More (public) macros... - */ -#ifndef offsetof -#define offsetof(t, m) ((size_t) (&((t *)0)->m)) -#endif - #if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) #define CAST_U32_TO_PTR(x) ((void *)(u64)x) #define CAST_PTR_TO_U32(x) ((u32)(u64)x) diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index c6163a424..91153cf47 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -111,7 +111,6 @@ MODULE_LICENSE("GPL"); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int mptctl_id = -1; -static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS]; static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); @@ -140,6 +139,9 @@ static int mptctl_do_reset(unsigned long arg); static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd); static int mptctl_hp_targetinfo(unsigned long arg); +static int mptctl_probe(struct pci_dev *, const struct pci_device_id *); +static void mptctl_remove(struct pci_dev *); + /* * Private function calls. */ @@ -208,10 +210,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) } if (nonblock) { - if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id])) + if (down_trylock(&ioc->ioctl->sem_ioc)) rc = -EAGAIN; } else { - if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id])) + if (down_interruptible(&ioc->ioctl->sem_ioc)) rc = -ERESTARTSYS; } dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); @@ -445,7 +447,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) mptctl_free_tm_flags(ioctl->ioc); del_timer(&ioctl->TMtimer); - mpt_free_msg_frame(mptctl_id, ioctl->ioc, mf); + mpt_free_msg_frame(ioctl->ioc, mf); ioctl->tmPtr = NULL; } @@ -482,7 +484,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc) spin_lock_irqsave(&ioc->FreeQlock, flags); - hd->tmState = TM_STATE_ERROR; + hd->tmState = TM_STATE_NONE; hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -520,7 +522,7 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){ ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE; del_timer(&ioctl->TMtimer); - mpt_free_msg_frame(mptctl_id, ioc, ioctl->tmPtr); + mpt_free_msg_frame(ioc, ioctl->tmPtr); } } else { @@ -630,8 +632,7 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned else ret = -EINVAL; - - up(&mptctl_syscall_sem_ioc[iocp->id]); + up(&iocp->ioctl->sem_ioc); return ret; } @@ -1217,7 +1218,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Fill in the data and return the structure to the calling * program */ - if ((int)ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) karg->adapterType = MPT_IOCTL_INTERFACE_FC; else karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; @@ -1517,7 +1518,7 @@ mptctl_readtest (unsigned long arg) #ifdef MFCNT karg.chip_type = ioc->mfcnt; #else - karg.chip_type = ioc->chip_type; + karg.chip_type = ioc->pcidev->device; #endif strncpy (karg.name, ioc->name, MPT_MAX_NAME); karg.name[MPT_MAX_NAME-1]='\0'; @@ -1807,7 +1808,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) struct buflist bufOut; /* data Out buffer */ dma_addr_t dma_addr_in; dma_addr_t dma_addr_out; - int dir; /* PCI data direction */ int sgSize = 0; /* Num SG elements */ int iocnum, flagsLength; int sz, rc = 0; @@ -2117,9 +2117,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) /* Set up the dataOut memory allocation */ if (karg.dataOutSize > 0) { - dir = PCI_DMA_TODEVICE; if (karg.dataInSize > 0) { flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_DIRECTION | mpt_addr_size() ) << MPI_SGE_FLAGS_SHIFT; @@ -2158,7 +2158,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) } if (karg.dataInSize > 0) { - dir = PCI_DMA_FROMDEVICE; flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; flagsLength |= karg.dataInSize; @@ -2196,6 +2195,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) add_timer(&ioc->ioctl->timer); if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { + DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); rc = mpt_send_handshake_request(mptctl_id, ioc, sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); if (rc == 0) { @@ -2206,7 +2206,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) del_timer(&ioc->ioctl->timer); ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE; ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED; - mpt_free_msg_frame(mptctl_id, ioc, mf); + mpt_free_msg_frame(ioc, mf); } } else { mpt_put_msg_frame(mptctl_id, ioc, mf); @@ -2324,7 +2324,7 @@ done_free_mem: * otherwise, failure occured after mf acquired. */ if (mf) - mpt_free_msg_frame(mptctl_id, ioc, mf); + mpt_free_msg_frame(ioc, mf); return rc; } @@ -2470,7 +2470,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) karg.base_io_addr = pci_resource_start(pdev, 0); - if ((int)ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) karg.bus_phys_width = HP_BUS_WIDTH_UNK; else karg.bus_phys_width = HP_BUS_WIDTH_16; @@ -2559,7 +2559,7 @@ mptctl_hp_targetinfo(unsigned long arg) /* There is nothing to do for FCP parts. */ - if ((int) ioc->chip_type <= (int) FC929) + if (ioc->bus_type == FC) return 0; if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) @@ -2738,7 +2738,7 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd, ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); - up(&mptctl_syscall_sem_ioc[iocp->id]); + up(&iocp->ioctl->sem_ioc); return ret; } @@ -2792,55 +2792,91 @@ compat_mpt_command(unsigned int fd, unsigned int cmd, */ ret = mptctl_do_mpt_command (karg, &uarg->MF); - up(&mptctl_syscall_sem_ioc[iocp->id]); + up(&iocp->ioctl->sem_ioc); return ret; } #endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -int __init mptctl_init(void) +/* + * mptctl_probe - Installs ioctl devices per bus. + * @pdev: Pointer to pci_dev structure + * + * Returns 0 for success, non-zero for failure. + * + */ + +static int +mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int err; - int i; - int where = 1; int sz; u8 *mem; - MPT_ADAPTER *ioc = NULL; - int iocnum; + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - show_mptmod_ver(my_NAME, my_VERSION); + /* + * Allocate and inite a MPT_IOCTL structure + */ + sz = sizeof (MPT_IOCTL); + mem = kmalloc(sz, GFP_KERNEL); + if (mem == NULL) { + err = -ENOMEM; + goto out_fail; + } - for (i=0; iioctl = (MPT_IOCTL *) mem; + ioc->ioctl->ioc = ioc; + init_timer (&ioc->ioctl->timer); + ioc->ioctl->timer.data = (unsigned long) ioc->ioctl; + ioc->ioctl->timer.function = mptctl_timer_expired; + init_timer (&ioc->ioctl->TMtimer); + ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl; + ioc->ioctl->TMtimer.function = mptctl_timer_expired; + sema_init(&ioc->ioctl->sem_ioc, 1); + return 0; - ioc = NULL; - if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) || - (ioc == NULL)) { - continue; - } - else { - /* This adapter instance is found. - * Allocate and inite a MPT_IOCTL structure - */ - sz = sizeof (MPT_IOCTL); - mem = kmalloc(sz, GFP_KERNEL); - if (mem == NULL) { - err = -ENOMEM; - goto out_fail; - } +out_fail: - memset(mem, 0, sz); - ioc->ioctl = (MPT_IOCTL *) mem; - ioc->ioctl->ioc = ioc; - init_timer (&ioc->ioctl->timer); - ioc->ioctl->timer.data = (unsigned long) ioc->ioctl; - ioc->ioctl->timer.function = mptctl_timer_expired; - init_timer (&ioc->ioctl->TMtimer); - ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl; - ioc->ioctl->TMtimer.function = mptctl_timer_expired; - } + mptctl_remove(pdev); + return err; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mptctl_remove - Removed ioctl devices + * @pdev: Pointer to pci_dev structure + * + * + */ +static void +mptctl_remove(struct pci_dev *pdev) +{ + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + + kfree ( ioc->ioctl ); +} + +static struct mpt_pci_driver mptctl_driver = { + .probe = mptctl_probe, + .remove = mptctl_remove, +}; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static int __init mptctl_init(void) +{ + int err; + int where = 1; + + show_mptmod_ver(my_NAME, my_VERSION); + + if(mpt_device_driver_register(&mptctl_driver, + MPTCTL_DRIVER) != 0 ) { + dprintk((KERN_INFO MYNAM + ": failed to register dd callbacks\n")); } #ifdef CONFIG_COMPAT @@ -2922,29 +2958,14 @@ out_fail: unregister_ioctl32_conversion(HP_GETTARGETINFO); #endif - for (i=0; iioctl) { - kfree ( ioc->ioctl ); - ioc->ioctl = NULL; - } - } - } + mpt_device_driver_deregister(MPTCTL_DRIVER); + return err; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -void mptctl_exit(void) +static void mptctl_exit(void) { - int i; - MPT_ADAPTER *ioc; - int iocnum; - misc_deregister(&mptctl_miscdev); printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n", mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor); @@ -2957,6 +2978,8 @@ void mptctl_exit(void) mpt_deregister(mptctl_id); printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n"); + mpt_device_driver_deregister(MPTCTL_DRIVER); + #ifdef CONFIG_COMPAT unregister_ioctl32_conversion(MPTIOCINFO); unregister_ioctl32_conversion(MPTIOCINFO1); @@ -2973,20 +2996,6 @@ void mptctl_exit(void) unregister_ioctl32_conversion(HP_GETTARGETINFO); #endif - /* Free allocated memory */ - for (i=0; iioctl) { - kfree ( ioc->ioctl ); - ioc->ioctl = NULL; - } - } - } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 80c9b97eb..5327c9215 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -177,11 +177,9 @@ static int LanCtx = -1; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; -static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1]; - #ifdef QLOGIC_NAA_WORKAROUND static struct NAA_Hosed *mpt_bad_naa = NULL; -rwlock_t bad_naa_lock; +rwlock_t bad_naa_lock = RW_LOCK_UNLOCKED; #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -203,7 +201,7 @@ extern int mpt_lan_index; static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) { - struct net_device *dev = mpt_landev[ioc->id]; + struct net_device *dev = ioc->netdev; int FreeReqFrame = 0; dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n", @@ -336,7 +334,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - struct net_device *dev = mpt_landev[ioc->id]; + struct net_device *dev = ioc->netdev; struct mpt_lan_priv *priv = netdev_priv(dev); dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", @@ -1334,7 +1332,7 @@ mpt_lan_post_receive_buckets(void *dev_id) if (pSimple == NULL) { /**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n", /**/ __FUNCTION__); - mpt_free_msg_frame(LanCtx, mpt_dev, mf); + mpt_free_msg_frame(mpt_dev, mf); goto out; } @@ -1451,20 +1449,74 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) return dev; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int __init mpt_lan_init (void) +static int +mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct net_device *dev; - MPT_ADAPTER *p; - int i, j; + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + struct net_device *dev; + int i; + + for (i = 0; i < ioc->facts.NumberOfPorts; i++) { + printk(KERN_INFO MYNAM ": %s: PortNum=%x, " + "ProtocolFlags=%02Xh (%c%c%c%c)\n", + ioc->name, ioc->pfacts[i].PortNumber, + ioc->pfacts[i].ProtocolFlags, + MPT_PROTOCOL_FLAGS_c_c_c_c( + ioc->pfacts[i].ProtocolFlags)); + + if (!(ioc->pfacts[i].ProtocolFlags & + MPI_PORTFACTS_PROTOCOL_LAN)) { + printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol " + "seems to be disabled on this adapter port!\n", + ioc->name); + continue; + } - show_mptmod_ver(LANAME, LANVER); + dev = mpt_register_lan_device(ioc, i); + if (!dev) { + printk(KERN_ERR MYNAM ": %s: Unable to register " + "port%d as a LAN device\n", ioc->name, + ioc->pfacts[i].PortNumber); + continue; + } + + printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device " + "registered as '%s'\n", ioc->name, dev->name); + printk(KERN_INFO MYNAM ": %s/%s: " + "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); + + ioc->netdev = dev; -#ifdef QLOGIC_NAA_WORKAROUND - /* Init the global r/w lock for the bad_naa list. We want to do this - before any boards are initialized and may be used. */ - rwlock_init(&bad_naa_lock); -#endif + return 0; + } + + return -ENODEV; +} + +static void +mptlan_remove(struct pci_dev *pdev) +{ + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + struct net_device *dev = ioc->netdev; + + if(dev != NULL) { + unregister_netdev(dev); + free_netdev(dev); + } +} + +static struct mpt_pci_driver mptlan_driver = { + .probe = mptlan_probe, + .remove = mptlan_remove, +}; + +static int __init mpt_lan_init (void) +{ + show_mptmod_ver(LANAME, LANVER); if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) { printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n"); @@ -1476,88 +1528,32 @@ static int __init mpt_lan_init (void) dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); - if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) { - dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); - } else { + if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) { printk(KERN_ERR MYNAM ": Eieee! unable to register a reset " "handler with mptbase! The world is at an end! " "Everything is fading to black! Goodbye.\n"); return -EBUSY; } - for (j = 0; j < MPT_MAX_ADAPTERS; j++) { - mpt_landev[j] = NULL; - } - - list_for_each_entry(p, &ioc_list, list) { - for (i = 0; i < p->facts.NumberOfPorts; i++) { - printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n", - p->name, - p->pfacts[i].PortNumber, - p->pfacts[i].ProtocolFlags, - MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags)); - - if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { - printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n", - p->name); - continue; - } - - dev = mpt_register_lan_device (p, i); - if (!dev) { - printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n", - p->name, - p->pfacts[i].PortNumber); - } - printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n", - p->name, dev->name); - printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5]); -// printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n", -// IOC_AND_NETDEV_NAMES_s_s(dev), -// NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out); - j = p->id; - mpt_landev[j] = dev; - dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n", - dev, j, mpt_landev[j])); - - } - } - + dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); + + if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER)) + dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n")); return 0; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static void __exit mpt_lan_exit(void) { - int i; - + mpt_device_driver_deregister(MPTLAN_DRIVER); mpt_reset_deregister(LanCtx); - for (i = 0; mpt_landev[i] != NULL; i++) { - struct net_device *dev = mpt_landev[i]; - - printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - unregister_netdev(dev); - free_netdev(dev); - mpt_landev[i] = NULL; - } - if (LanCtx >= 0) { mpt_deregister(LanCtx); LanCtx = -1; mpt_lan_index = 0; } - - /* deregister any send/receive handler structs. I2Oism? */ } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - module_init(mpt_lan_init); module_exit(mpt_lan_exit); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 8c82254b4..65ffd15fa 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -86,7 +86,6 @@ #include "mptbase.h" #include "mptscsih.h" -#include "isense.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #define my_NAME "Fusion MPT SCSI Host driver" @@ -97,9 +96,22 @@ MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); -/* Set string for command line args from insmod */ #ifdef MODULE -char *mptscsih = NULL; +static int dv = MPTSCSIH_DOMAIN_VALIDATION; +module_param(dv, int, 0); +MODULE_PARM_DESC(dv, "DV Algorithm: enhanced = 1, basic = 0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); + +static int width = MPTSCSIH_MAX_WIDTH; +module_param(width, int, 0); +MODULE_PARM_DESC(width, "Max Bus Width: wide = 1, narrow = 0 (default=MPTSCSIH_MAX_WIDTH=1)"); + +static ushort factor = MPTSCSIH_MIN_SYNC; +module_param(factor, ushort, 0); +MODULE_PARM_DESC(factor, "Min Sync Factor: (default=MPTSCSIH_MIN_SYNC=0x08)"); + +static int saf_te = MPTSCSIH_SAF_TE; +module_param(saf_te, int, 0); +MODULE_PARM_DESC(saf_te, "Force enabling SEP Processor: (default=MPTSCSIH_SAF_TE=0)"); #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -114,6 +126,7 @@ typedef struct _BIG_SENSE_BUF { #define MPT_SCANDV_SOME_ERROR (0x00000004) #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) #define MPT_SCANDV_ISSUE_SENSE (0x00000010) +#define MPT_SCANDV_FALLBACK (0x00000020) #define MPT_SCANDV_MAX_RETRIES (10) @@ -161,15 +174,12 @@ static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR * static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); -static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt, +static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, SCSIIORequest_t *pReq, int req_idx); -static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx); -static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init); +static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx); -static void post_pendingQ_commands(MPT_SCSI_HOST *hd); static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag); @@ -178,7 +188,7 @@ static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); +static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq); static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id); @@ -202,9 +212,6 @@ static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); #endif -#ifdef MODULE -static int mptscsih_setup(char *str); -#endif /* module entry point */ static int __init mptscsih_init (void); static void __exit mptscsih_exit (void); @@ -246,15 +253,10 @@ static struct work_struct mptscsih_dvTask; static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq); static int scandv_wait_done = 1; -/* Driver default setup - */ -static struct mptscsih_driver_setup - driver_setup = MPTSCSIH_DRIVER_SETUP; - -#ifdef MPTSCSIH_DBG_TIMEOUT -static struct scsi_cmnd *foo_to[8]; -#endif +/* Driver command line structure + */ +static struct mptscsih_driver_setup driver_setup; static struct scsi_host_template driver_template; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -323,44 +325,44 @@ mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptscsih_getFreeChainBuffes - Function to get a free chain + * mptscsih_getFreeChainBuffer - Function to get a free chain * from the MPT_SCSI_HOST FreeChainQ. - * @hd: Pointer to the MPT_SCSI_HOST instance + * @ioc: Pointer to MPT_ADAPTER structure * @req_idx: Index of the SCSI IO request frame. (output) * * return SUCCESS or FAILED */ static inline int -mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex) +mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) { MPT_FRAME_HDR *chainBuf; unsigned long flags; int rc; int chain_idx; - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (!Q_IS_EMPTY(&hd->FreeChainQ)) { - + dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n", + ioc->name)); + spin_lock_irqsave(&ioc->FreeQlock, flags); + if (!list_empty(&ioc->FreeChainQ)) { int offset; - chainBuf = hd->FreeChainQ.head; - Q_DEL_ITEM(&chainBuf->u.frame.linkage); - offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer; - chain_idx = offset / hd->ioc->req_sz; + chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR, + u.frame.linkage.list); + list_del(&chainBuf->u.frame.linkage.list); + offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; + chain_idx = offset / ioc->req_sz; rc = SUCCESS; - } - else { + dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n", + ioc->name, *retIndex, chainBuf)); + } else { rc = FAILED; chain_idx = MPT_HOST_NO_CHAIN; + dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n", + ioc->name)); } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - + spin_unlock_irqrestore(&ioc->FreeQlock, flags); *retIndex = chain_idx; - - dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n", - hd->ioc->name, *retIndex, chainBuf)); - return rc; } /* mptscsih_getFreeChainBuffer() */ @@ -368,14 +370,14 @@ mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex) /* * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the * SCSIIORequest_t Message Frame. - * @hd: Pointer to MPT_SCSI_HOST structure + * @ioc: Pointer to MPT_ADAPTER structure * @SCpnt: Pointer to scsi_cmnd structure * @pReq: Pointer to SCSIIORequest_t structure * * Returns ... */ static int -mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt, +mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, SCSIIORequest_t *pReq, int req_idx) { char *psge; @@ -391,6 +393,7 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt, int newIndex; int ii; dma_addr_t v2; + u32 RequestNB; sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK; if (sgdir == MPI_SCSIIO_CONTROL_WRITE) { @@ -400,25 +403,25 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt, } psge = (char *) &pReq->SGL; - frm_sz = hd->ioc->req_sz; + frm_sz = ioc->req_sz; /* Map the data portion, if any. * sges_left = 0 if no data transfer. */ if ( (sges_left = SCpnt->use_sg) ) { - sges_left = pci_map_sg(hd->ioc->pcidev, + sges_left = pci_map_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction); if (sges_left == 0) return FAILED; } else if (SCpnt->request_bufflen) { - SCpnt->SCp.dma_handle = pci_map_single(hd->ioc->pcidev, + SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->sc_data_direction); dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n", - hd->ioc->name, SCpnt, SCpnt->request_bufflen)); + ioc->name, SCpnt, SCpnt->request_bufflen)); mptscsih_add_sge((char *) &pReq->SGL, 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen, SCpnt->SCp.dma_handle); @@ -493,12 +496,16 @@ nextSGEset: * Update the chain element * Offset and Length fields. */ - mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off); + mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); } else { /* The current buffer is the original MF * and there is no Chain buffer. */ pReq->ChainOffset = 0; + RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; + dsgprintk((MYIOC_s_ERR_FMT + "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); + ioc->RequestNB[req_idx] = RequestNB; } } else { /* At least one chain buffer is needed. @@ -513,7 +520,7 @@ nextSGEset: */ dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n", - hd->ioc->name, sg_done)); + ioc->name, sg_done)); /* Set LAST_ELEMENT flag for last non-chain element * in the buffer. Since psge points at the NEXT @@ -537,13 +544,16 @@ nextSGEset: */ u8 nextChain = (u8) (sgeOffset >> 2); sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); - mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off); + mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); } else { /* The original MF buffer requires a chain buffer - * set the offset. * Last element in this MF is a chain element. */ pReq->ChainOffset = (u8) (sgeOffset >> 2); + RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; + dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); + ioc->RequestNB[req_idx] = RequestNB; } sges_left -= sg_done; @@ -552,19 +562,22 @@ nextSGEset: /* NOTE: psge points to the beginning of the chain element * in current buffer. Get a chain buffer. */ - if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED) + dsgprintk((MYIOC_s_INFO_FMT + "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n", + ioc->name, pReq->CDB[0], SCpnt)); + if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) return FAILED; /* Update the tracking arrays. * If chainSge == NULL, update ReqToChain, else ChainToChain */ if (chainSge) { - hd->ChainToChain[chain_idx] = newIndex; + ioc->ChainToChain[chain_idx] = newIndex; } else { - hd->ReqToChain[req_idx] = newIndex; + ioc->ReqToChain[req_idx] = newIndex; } chain_idx = newIndex; - chain_dma_off = hd->ioc->req_sz * chain_idx; + chain_dma_off = ioc->req_sz * chain_idx; /* Populate the chainSGE for the current buffer. * - Set chain buffer pointer to psge and fill @@ -576,7 +589,7 @@ nextSGEset: /* Start the SGE for the next buffer */ - psge = (char *) (hd->ChainBuffer + chain_dma_off); + psge = (char *) (ioc->ChainBuffer + chain_dma_off); sgeOffset = 0; sg_done = 0; @@ -631,7 +644,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", ioc->name); - mptscsih_freeChainBuffers(hd, req_idx); + mptscsih_freeChainBuffers(ioc, req_idx); return 1; } @@ -643,27 +656,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) pScsiReq = (SCSIIORequest_t *) mf; pScsiReply = (SCSIIOReply_t *) mr; -#ifdef MPTSCSIH_DBG_TIMEOUT - if (ioc->timeout_cnt > 0) { - int ii, left = 0; - - for (ii=0; ii < 8; ii++) { - if (sc == foo_to[ii]) { - printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n", - ioc->name, sc, jiffies); - foo_to[ii] = NULL; - } - if (foo_to[ii] != NULL) - left++; - } - - if (left == 0) { - ioc->timeout_maxcnt = 0; - ioc->timeout_cnt = 0; - } - } -#endif - if (pScsiReply == NULL) { /* special context reply handling */ ; @@ -674,14 +666,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_state = pScsiReply->SCSIState; + scsi_status = pScsiReply->SCSIStatus; + xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); + sc->resid = sc->request_bufflen - xfer_cnt; - dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n", - ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], - mf, mr, sc)); - dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh" - ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n", - status, scsi_state, pScsiReply->SCSIStatus, - le32_to_cpu(pScsiReply->IOCLogInfo))); + dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" + "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" + "resid=%d bufflen=%d xfer_cnt=%d\n", + ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], + status, scsi_state, scsi_status, sc->resid, + sc->request_bufflen, xfer_cnt)); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) copy_sense_data(sc, hd, mf, pScsiReply); @@ -701,7 +695,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) * But not: DID_BUS_BUSY lest one risk * killing interrupt handler:-( */ - sc->result = STS_BUSY; + sc->result = SAM_STAT_BUSY; break; case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ @@ -726,18 +720,26 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->result = DID_RESET << 16; /* GEM Workaround. */ - if (hd->is_spi) + if (ioc->bus_type == SCSI) mptscsih_no_negotiate(hd, sc->device->id); break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | + if ( xfer_cnt >= sc->underflow ) { + /* Sufficient data transfer occurred */ + sc->result = (DID_OK << 16) | scsi_status; + } else if ( xfer_cnt == 0 ) { + /* A CRC Error causes this condition; retry */ + sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | (CHECK_CONDITION << 1); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NO_SENSE; - sc->sense_buffer[12] = 0; - sc->sense_buffer[13] = 0; - dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); + sc->sense_buffer[0] = 0x70; + sc->sense_buffer[2] = NO_SENSE; + sc->sense_buffer[12] = 0; + sc->sense_buffer[13] = 0; + } else { + sc->result = DID_SOFT_ERROR << 16; + } + dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -745,15 +747,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) * Do upfront check for valid SenseData and give it * precedence! */ - scsi_status = pScsiReply->SCSIStatus; sc->result = (DID_OK << 16) | scsi_status; - xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { /* Have already saved the status and sense data */ ; } else { - if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) { + if (xfer_cnt < sc->underflow) { sc->result = DID_SOFT_ERROR << 16; } if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { @@ -767,15 +767,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } } - /* Give report and update residual count. - */ - dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", + dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow)); - dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); - - sc->resid = sc->request_bufflen - xfer_cnt; - dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid)); - + dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); /* Report Queue Full */ if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) @@ -785,7 +779,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus; + scsi_status = pScsiReply->SCSIStatus; + sc->result = (DID_OK << 16) | scsi_status; if (scsi_state == 0) { ; } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { @@ -829,7 +824,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - sc->result = DID_SOFT_ERROR << 16; + sc->result = DID_SOFT_ERROR << 16; break; case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ @@ -851,7 +846,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ - dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result)); + dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result)); } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ @@ -868,88 +863,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->scsi_done(sc); /* Issue the command callback */ /* Free Chain buffers */ - mptscsih_freeChainBuffers(hd, req_idx); + mptscsih_freeChainBuffers(ioc, req_idx); return 1; } -/* - * Flush all commands on the doneQ. - * Lock Q when deleting/adding members - * Lock io_request_lock for OS callback. - */ -static void -flush_doneQ(MPT_SCSI_HOST *hd) -{ - MPT_DONE_Q *buffer; - struct scsi_cmnd *SCpnt; - unsigned long flags; - - /* Flush the doneQ. - */ - dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n")); - while (1) { - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (Q_IS_EMPTY(&hd->doneQ)) { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - break; - } - - buffer = hd->doneQ.head; - /* Delete from Q - */ - Q_DEL_ITEM(buffer); - - /* Set the struct scsi_cmnd pointer - */ - SCpnt = (struct scsi_cmnd *) buffer->argp; - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - - /* Do the OS callback. - */ - SCpnt->scsi_done(SCpnt); - } - - return; -} - -/* - * Search the doneQ for a specific command. If found, delete from Q. - * Calling function will finish processing. - */ -static void -search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt) -{ - unsigned long flags; - MPT_DONE_Q *buffer; - - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->doneQ)) { - buffer = hd->doneQ.head; - do { - struct scsi_cmnd *sc = (struct scsi_cmnd *) buffer->argp; - if (SCpnt == sc) { - Q_DEL_ITEM(buffer); - SCpnt->result = sc->result; - - /* Set the struct scsi_cmnd pointer - */ - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - break; - } - } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ); - } - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - return; -} /* * mptscsih_flush_running_cmds - For each command found, search @@ -964,12 +881,11 @@ search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt) static void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) { + MPT_ADAPTER *ioc = hd->ioc; struct scsi_cmnd *SCpnt; MPT_FRAME_HDR *mf; - MPT_DONE_Q *buffer; int ii; - int max = hd->ioc->req_depth; - unsigned long flags; + int max = ioc->req_depth; dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); for (ii= 0; ii < max; ii++) { @@ -978,16 +894,11 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) /* Command found. */ - /* Search pendingQ, if found, - * delete from Q. - */ - mptscsih_search_pendingQ(hd, ii); - /* Null ScsiLookup index */ hd->ScsiLookup[ii] = NULL; - mf = MPT_INDEX_2_MFPTR(hd->ioc, ii); + mf = MPT_INDEX_2_MFPTR(ioc, ii); dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt)); @@ -997,12 +908,12 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) */ if (scsi_device_online(SCpnt->device)) { if (SCpnt->use_sg) { - pci_unmap_sg(hd->ioc->pcidev, + pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction); } else if (SCpnt->request_bufflen) { - pci_unmap_single(hd->ioc->pcidev, + pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle, SCpnt->request_bufflen, SCpnt->sc_data_direction); @@ -1012,37 +923,12 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) SCpnt->host_scribble = NULL; /* Free Chain buffers */ - mptscsih_freeChainBuffers(hd, ii); + mptscsih_freeChainBuffers(ioc, ii); /* Free Message frames */ - mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf); - -#if 1 - /* Post to doneQ, do not reply until POST phase - * of reset handler....prevents new commands from - * being queued. - */ - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Set the struct scsi_cmnd pointer - */ - buffer->argp = (void *)SCpnt; + mpt_free_msg_frame(ioc, mf); - /* Add to the doneQ - */ - Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->scsi_done(SCpnt); - } -#else SCpnt->scsi_done(SCpnt); /* Issue the command callback */ -#endif - } } @@ -1087,119 +973,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) /* Cleanup */ hd->ScsiLookup[ii] = NULL; - mptscsih_freeChainBuffers(hd, ii); - mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, (MPT_FRAME_HDR *)mf); + mptscsih_freeChainBuffers(hd->ioc, ii); + mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); } } return; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initChainBuffers - Allocate memory for and initialize - * chain buffers, chain buffer control arrays and spinlock. - * @hd: Pointer to MPT_SCSI_HOST structure - * @init: If set, initialize the spin lock. - */ -static int -mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init) -{ - MPT_FRAME_HDR *chain; - u8 *mem; - unsigned long flags; - int sz, ii, num_chain; - int scale, num_sge; - - /* chain buffer allocation done from PrimeIocFifos */ - if (hd->ioc->fifo_pool == NULL) - return -1; - - hd->ChainBuffer = hd->ioc->chain_alloc; - hd->ChainBufferDMA = hd->ioc->chain_alloc_dma; - - dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n", - hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz)); - - /* ReqToChain size must equal the req_depth - * index = req_idx - */ - if (hd->ReqToChain == NULL) { - sz = hd->ioc->req_depth * sizeof(int); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return -1; - - hd->ReqToChain = (int *) mem; - } - for (ii = 0; ii < hd->ioc->req_depth; ii++) - hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN; - - /* ChainToChain size must equal the total number - * of chain buffers to be allocated. - * index = chain_idx - * - * Calculate the number of chain buffers needed(plus 1) per I/O - * then multiply the the maximum number of simultaneous cmds - * - * num_sge = num sge in request frame + last chain buffer - * scale = num sge per chain buffer if no chain element - */ - scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); - if (sizeof(dma_addr_t) == sizeof(u64)) - num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); - else - num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); - - num_chain = 1; - while (hd->max_sge - num_sge > 0) { - num_chain++; - num_sge += (scale - 1); - } - num_chain++; - - if ((int) hd->ioc->chip_type > (int) FC929) - num_chain *= MPT_SCSI_CAN_QUEUE; - else - num_chain *= MPT_FC_CAN_QUEUE; - - hd->num_chain = num_chain; - - sz = num_chain * sizeof(int); - if (hd->ChainToChain == NULL) { - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) - return -1; - - hd->ChainToChain = (int *) mem; - } else { - mem = (u8 *) hd->ChainToChain; - } - memset(mem, 0xFF, sz); - - - /* Initialize the free chain Q. - */ - if (init) { - spin_lock_init(&hd->FreeChainQlock); - } - - spin_lock_irqsave (&hd->FreeChainQlock, flags); - Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR); - - /* Post the chain buffers to the FreeChainQ. - */ - mem = (u8 *)hd->ChainBuffer; - for (ii=0; ii < num_chain; ii++) { - chain = (MPT_FRAME_HDR *) mem; - Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR); - mem += hd->ioc->req_sz; - } - spin_unlock_irqrestore(&hd->FreeChainQlock, flags); - - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Hack! It might be nice to report if a device is returning QUEUE_FULL @@ -1254,7 +1035,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct Scsi_Host *sh; MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - MPT_DONE_Q *freedoneQ; unsigned long flags; int sz, ii; int numSGE = 0; @@ -1328,7 +1108,7 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) * max_lun = 1 + actual last lun, * see hosts.h :o( */ - if ((int)ioc->chip_type > (int)FC929) { + if (ioc->bus_type == SCSI) { sh->max_id = MPT_MAX_SCSI_DEVICES; } else { /* For FC, increase the queue depth @@ -1386,20 +1166,11 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; - hd->max_sge = sh->sg_tablesize; - - if ((int)ioc->chip_type > (int)FC929) - hd->is_spi = 1; - - if (DmpService && (ioc->chip_type == FC919 || - ioc->chip_type == FC929)) { - hd->is_multipath = 1; - } /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - sz = hd->ioc->req_depth * sizeof(void *); + sz = ioc->req_depth * sizeof(void *); mem = kmalloc(sz, GFP_ATOMIC); if (mem == NULL) { error = -ENOMEM; @@ -1412,43 +1183,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", ioc->name, hd->ScsiLookup, sz)); - if (mptscsih_initChainBuffers(hd, 1) < 0) { - error = -EINVAL; - goto mptscsih_probe_failed; - } - - /* Allocate memory for free and doneQ's - */ - sz = sh->can_queue * sizeof(MPT_DONE_Q); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { - error = -ENOMEM; - goto mptscsih_probe_failed; - } - - memset(mem, 0xFF, sz); - hd->memQ = mem; - - /* Initialize the free, done and pending Qs. - */ - Q_INIT(&hd->freeQ, MPT_DONE_Q); - Q_INIT(&hd->doneQ, MPT_DONE_Q); - Q_INIT(&hd->pendingQ, MPT_DONE_Q); - spin_lock_init(&hd->freedoneQlock); - - mem = hd->memQ; - for (ii=0; ii < sh->can_queue; ii++) { - freedoneQ = (MPT_DONE_Q *) mem; - Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q); - mem += sizeof(MPT_DONE_Q); - } - - /* Initialize this Scsi_Host - * internal task Q. - */ - Q_INIT(&hd->taskQ, MPT_FRAME_HDR); - hd->taskQcnt = 0; - /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. @@ -1474,8 +1208,7 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) hd->resetPending = 0; hd->abortSCpnt = NULL; hd->tmPtr = NULL; - hd->numTMrequests = 0; - + /* Clear the pointer used to store * single-threaded commands, i.e., those * issued during a bus scan, dv and @@ -1499,61 +1232,47 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Moved Earlier Pam D */ /* ioc->sh = sh; */ -#ifdef MPTSCSIH_DBG_TIMEOUT - hd->ioc->timeout_hard = 0; - hd->ioc->timeout_delta = 30 * HZ; - hd->ioc->timeout_maxcnt = 0; - hd->ioc->timeout_cnt = 0; - for (ii=0; ii < 8; ii++) - foo_to[ii] = NULL; -#endif - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { /* Update with the driver setup * values. */ - if (hd->ioc->spi_data.maxBusWidth > + if (ioc->spi_data.maxBusWidth > driver_setup.max_width) { - hd->ioc->spi_data.maxBusWidth = + ioc->spi_data.maxBusWidth = driver_setup.max_width; } - if (hd->ioc->spi_data.minSyncFactor < - driver_setup.min_sync_fac) { - hd->ioc->spi_data.minSyncFactor = - driver_setup.min_sync_fac; + if (ioc->spi_data.minSyncFactor < + driver_setup.min_sync_factor) { + ioc->spi_data.minSyncFactor = + driver_setup.min_sync_factor; } - if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) { - hd->ioc->spi_data.maxSyncOffset = 0; + if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { + ioc->spi_data.maxSyncOffset = 0; } - hd->ioc->spi_data.Saf_Te = driver_setup.saf_te; + ioc->spi_data.Saf_Te = driver_setup.saf_te; hd->negoNvram = 0; #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION hd->negoNvram = MPT_SCSICFG_USE_NVRAM; #endif - if (driver_setup.dv == 0) { - hd->negoNvram = MPT_SCSICFG_USE_NVRAM; - } - - hd->ioc->spi_data.forceDv = 0; + ioc->spi_data.forceDv = 0; for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - hd->ioc->spi_data.dvStatus[ii] = + ioc->spi_data.dvStatus[ii] = MPT_SCSICFG_NEGOTIATE; } - if (hd->negoNvram == 0) { - for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) - hd->ioc->spi_data.dvStatus[ii] |= - MPT_SCSICFG_DV_NOT_DONE; - } + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) + ioc->spi_data.dvStatus[ii] |= + MPT_SCSICFG_DV_NOT_DONE; ddvprintk((MYIOC_s_INFO_FMT "dv %x width %x factor %x saf_te %x\n", - hd->ioc->name, driver_setup.dv, + ioc->name, driver_setup.dv, driver_setup.max_width, - driver_setup.min_sync_fac, + driver_setup.min_sync_factor, driver_setup.saf_te)); } @@ -1620,14 +1339,11 @@ mptscsih_remove(struct pci_dev *pdev) hd = (MPT_SCSI_HOST *)host->hostdata; if (hd != NULL) { - int sz1, sz2, sz3, sztarget=0; - int szr2chain = 0; - int szc2chain = 0; - int szQ = 0; + int sz1; mptscsih_shutdown(&pdev->dev); - sz1 = sz2 = sz3 = 0; + sz1=0; if (hd->ScsiLookup != NULL) { sz1 = hd->ioc->req_depth * sizeof(void *); @@ -1635,55 +1351,17 @@ mptscsih_remove(struct pci_dev *pdev) hd->ScsiLookup = NULL; } - if (hd->ReqToChain != NULL) { - szr2chain = hd->ioc->req_depth * sizeof(int); - kfree(hd->ReqToChain); - hd->ReqToChain = NULL; - } - - if (hd->ChainToChain != NULL) { - szc2chain = hd->num_chain * sizeof(int); - kfree(hd->ChainToChain); - hd->ChainToChain = NULL; - } - - if (hd->memQ != NULL) { - szQ = host->can_queue * sizeof(MPT_DONE_Q); - kfree(hd->memQ); - hd->memQ = NULL; - } - if (hd->Targets != NULL) { - int max, ii; - - /* - * Free any target structures that were allocated. - */ - if (hd->is_spi) { - max = MPT_MAX_SCSI_DEVICES; - } else { - max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; - } - for (ii=0; ii < max; ii++) { - if (hd->Targets[ii]) { - kfree(hd->Targets[ii]); - hd->Targets[ii] = NULL; - sztarget += sizeof(VirtDevice); - } - } - /* * Free pointer array. */ - sz3 = max * sizeof(void *); kfree(hd->Targets); hd->Targets = NULL; } - dprintk((MYIOC_s_INFO_FMT - "Free'd ScsiLookup (%d) Target (%d+%d) memory\n", - hd->ioc->name, sz1, sz3, sztarget)); - dprintk(("Free'd done and free Q (%d) memory\n", szQ)); + dprintk((MYIOC_s_INFO_FMT + "Free'd ScsiLookup (%d) memory\n", + hd->ioc->name, sz1)); /* NULL the Scsi_Host pointer */ @@ -1802,7 +1480,7 @@ mptscsih_init(void) ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { - dprintk((KERN_INFO MYNAM + devtprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } @@ -1812,9 +1490,15 @@ mptscsih_init(void) } #ifdef MODULE - /* Evaluate the command line arguments, if any */ - if (mptscsih) - mptscsih_setup(mptscsih); + dinitprintk((KERN_INFO MYNAM + ": Command Line Args: dv=%d max_width=%d " + "factor=0x%x saf_te=%d\n", + dv, width, factor, saf_te)); + + driver_setup.dv = (dv) ? 1 : 0; + driver_setup.max_width = (width) ? 1 : 0; + driver_setup.min_sync_factor = factor; + driver_setup.saf_te = (saf_te) ? 1 : 0;; #endif if(mpt_device_driver_register(&mptscsih_driver, @@ -1864,7 +1548,7 @@ mptscsih_exit(void) * * Returns pointer to buffer where information was written. */ -const char * +static const char * mptscsih_info(struct Scsi_Host *SChost) { MPT_SCSI_HOST *h; @@ -1943,129 +1627,6 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le return ((info.pos > info.offset) ? info.pos - info.offset : 0); } -#ifndef MPTSCSIH_DBG_TIMEOUT -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len) -{ - /* Not yet implemented */ - return len; -} -#else -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define digit_to_bin(c) ((c) - '0') -#define is_space(c) ((c) == ' ' || (c) == '\t') - -#define UC_DBG_TIMEOUT 0x01 -#define UC_DBG_HARDRESET 0x02 - -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, ulong *pv) -{ - int cnt, c; - ulong 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; - -static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length) -{ - char *ptr = buffer; - char btmp[24]; /* REMOVE */ - int arg_len; - int len = length; - int cmd; - ulong number = 1; - ulong delta = 10; - - if ((len > 0) && (ptr[len -1] == '\n')) - --len; - - if (len < 22) { - strncpy(btmp, buffer, len); - btmp[len+1]='\0'; - } else { - strncpy(btmp, buffer, 22); - btmp[23]='\0'; - } - printk("user_command: ioc %d, buffer %s, length %d\n", - ioc->id, btmp, length); - - if ((arg_len = is_keyword(ptr, len, "timeout")) != 0) - cmd = UC_DBG_TIMEOUT; - else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0) - cmd = UC_DBG_HARDRESET; - else - return -EINVAL; - - ptr += arg_len; - len -= arg_len; - - switch(cmd) { - case UC_DBG_TIMEOUT: - SKIP_SPACES(1); - GET_INT_ARG(number); - SKIP_SPACES(1); - GET_INT_ARG(delta); - break; - } - - printk("user_command: cnt=%ld delta=%ld\n", number, delta); - - if (len) - return -EINVAL; - else { - if (cmd == UC_DBG_HARDRESET) { - ioc->timeout_hard = 1; - } else if (cmd == UC_DBG_TIMEOUT) { - /* process this command ... - */ - ioc->timeout_maxcnt = 0; - ioc->timeout_delta = delta < 2 ? 2 : delta; - ioc->timeout_cnt = 0; - ioc->timeout_maxcnt = number < 8 ? number: 8; - } - } - /* Not yet implemented */ - return length; -} -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_proc_info - Return information about MPT adapter @@ -2079,7 +1640,8 @@ static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length) * hostno: scsi host number * func: if write = 1; if read = 0 */ -int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, +static int +mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; @@ -2087,7 +1649,9 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t int size = 0; if (func) { - size = mptscsih_user_command(ioc, buffer, length); + /* + * write is not supported + */ } else { if (start) *start = buffer; @@ -2098,7 +1662,6 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t return size; } - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #define ADD_INDEX_LOG(req_ent) do { } while(0) @@ -2114,15 +1677,13 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t * * Returns 0. (rtn value discarded by linux scsi mid-layer) */ -int +static int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; VirtDevice *pTarget; - MPT_DONE_Q *buffer; - unsigned long flags; int target; int lun; u32 datalen; @@ -2131,11 +1692,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) u32 cmd_len; int my_idx; int ii; - int rc; - int did_errcode; - int issueCmd; - did_errcode = 0; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; target = SCpnt->device->id; lun = SCpnt->device->lun; @@ -2147,16 +1704,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); if (hd->resetPending) { - /* Prevent new commands from being issued - * while reloading the FW. Reset timer to 60 seconds, - * as the FW can take some time to come ready. - * For New EH, cmds on doneQ posted to FW. - */ - did_errcode = 1; - mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60)); dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); - goto did_error; + return SCSI_MLQUEUE_HOST_BUSY; } /* @@ -2165,8 +1715,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) { dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", hd->ioc->name)); - did_errcode = 2; - goto did_error; + return SCSI_MLQUEUE_HOST_BUSY; } pScsiReq = (SCSIIORequest_t *) mf; @@ -2242,137 +1791,73 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Now add the SG list * Always have a SGE even if null length. */ - rc = SUCCESS; if (datalen == 0) { /* Add a NULL SGE */ mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); } else { /* Add a 32 or 64 bit SGE */ - rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx); + if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) + goto fail; } - - if (rc == SUCCESS) { - hd->ScsiLookup[my_idx] = SCpnt; - SCpnt->host_scribble = NULL; - - /* SCSI specific processing */ - issueCmd = 1; - if (hd->is_spi) { - int dvStatus = hd->ioc->spi_data.dvStatus[target]; - - if (dvStatus || hd->ioc->spi_data.forceDv) { + hd->ScsiLookup[my_idx] = SCpnt; + SCpnt->host_scribble = NULL; #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - if ((dvStatus & MPT_SCSICFG_NEED_DV) || - (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { - unsigned long lflags; - /* Schedule DV if necessary */ - spin_lock_irqsave(&dvtaskQ_lock, lflags); - if (!dvtaskQ_active) { - dvtaskQ_active = 1; - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); - - schedule_work(&mptscsih_dvTask); - } else { - spin_unlock_irqrestore(&dvtaskQ_lock, lflags); - } - hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; - } - - /* Trying to do DV to this target, extend timeout. - * Wait to issue intil flag is clear - */ - if (dvStatus & MPT_SCSICFG_DV_PENDING) { - mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); - issueCmd = 0; + if (hd->ioc->bus_type == SCSI) { + int dvStatus = hd->ioc->spi_data.dvStatus[target]; + int issueCmd = 1; + + if (dvStatus || hd->ioc->spi_data.forceDv) { + + if ((dvStatus & MPT_SCSICFG_NEED_DV) || + (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { + unsigned long lflags; + /* Schedule DV if necessary */ + spin_lock_irqsave(&dvtaskQ_lock, lflags); + if (!dvtaskQ_active) { + dvtaskQ_active = 1; + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); + INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); + + schedule_work(&mptscsih_dvTask); + } else { + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } - - /* Set the DV flags. - */ - if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) - mptscsih_set_dvflags(hd, pScsiReq); -#endif + hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; } - } -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) { - foo_to[hd->ioc->timeout_cnt] = SCpnt; - hd->ioc->timeout_cnt++; - //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta); - issueCmd = 0; - printk(MYIOC_s_WARN_FMT - "to pendingQ: (sc=%p, mf=%p, time=%ld)\n", - hd->ioc->name, SCpnt, mf, jiffies); - } -#endif + /* Trying to do DV to this target, extend timeout. + * Wait to issue until flag is clear + */ + if (dvStatus & MPT_SCSICFG_DV_PENDING) { + mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); + issueCmd = 0; + } - if (issueCmd) { - mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); - dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", - hd->ioc->name, SCpnt, mf, my_idx)); - } else { - ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n", - hd->ioc->name, SCpnt, my_idx)); - /* Place this command on the pendingQ if possible */ - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Save the mf pointer - */ - buffer->argp = (void *)mf; + /* Set the DV flags. + */ + if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) + mptscsih_set_dvflags(hd, pScsiReq); - /* Add to the pendingQ - */ - Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->result = (DID_BUS_BUSY << 16); - SCpnt->scsi_done(SCpnt); - } + if (!issueCmd) + goto fail; } - } else { - mptscsih_freeChainBuffers(hd, my_idx); - mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf); - did_errcode = 3; - goto did_error; } +#endif + mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); + dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", + hd->ioc->name, SCpnt, mf, my_idx)); + DBG_DUMP_REQUEST_FRAME(mf) return 0; -did_error: - dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n", - hd->ioc->name, did_errcode, SCpnt)); - /* Just wish OS to issue a retry */ - SCpnt->result = (DID_BUS_BUSY << 16); - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->freeQ)) { - dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n", - (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); - buffer = hd->freeQ.head; - Q_DEL_ITEM(buffer); - - /* Set the scsi_cmnd pointer - */ - buffer->argp = (void *)SCpnt; - - /* Add to the doneQ - */ - Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - } else { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - SCpnt->scsi_done(SCpnt); - } - - return 0; -} + fail: + mptscsih_freeChainBuffers(hd->ioc, my_idx); + mpt_free_msg_frame(hd->ioc, mf); + return SCSI_MLQUEUE_HOST_BUSY; +} /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -2385,7 +1870,7 @@ did_error: * No return. */ static void -mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx) +mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) { MPT_FRAME_HDR *chain; unsigned long flags; @@ -2395,28 +1880,28 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx) /* Get the first chain index and reset * tracker state. */ - chain_idx = hd->ReqToChain[req_idx]; - hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN; + chain_idx = ioc->ReqToChain[req_idx]; + ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN; while (chain_idx != MPT_HOST_NO_CHAIN) { /* Save the next chain buffer index */ - next = hd->ChainToChain[chain_idx]; + next = ioc->ChainToChain[chain_idx]; /* Free this chain buffer and reset * tracker */ - hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN; + ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN; - chain = (MPT_FRAME_HDR *) (hd->ChainBuffer - + (chain_idx * hd->ioc->req_sz)); - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - Q_ADD_TAIL(&hd->FreeChainQ.head, - &chain->u.frame.linkage, MPT_FRAME_HDR); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer + + (chain_idx * ioc->req_sz)); + + spin_lock_irqsave(&ioc->FreeQlock, flags); + list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n", - hd->ioc->name, chain_idx)); + ioc->name, chain_idx)); /* handle next */ chain_idx = next; @@ -2480,12 +1965,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in } spin_unlock_irqrestore(&ioc->diagLock, flags); - /* Do not do a Task Management if there are - * too many failed TMs on this adapter. - */ - if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM) - doTask = 0; - /* Wait a fixed amount of time for the TM pending flag to be cleared. * If we time out and not bus reset, then we return a FAILED status to the caller. * The call to mptscsih_tm_pending_wait() will set the pending flag if we are @@ -2544,11 +2023,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in } } -#ifdef MPTSCSIH_DBG_TIMEOUT - if (hd->ioc->timeout_hard) - rc = 1; -#endif - /* Only fall through to the HRH if this is a bus reset */ if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || @@ -2593,7 +2067,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun /* Return Fail to calling function if no message frames available. */ if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", + dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", hd->ioc->name)); //return FAILED; return -999; @@ -2624,29 +2098,30 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun pScsiTm->Reserved2[ii] = 0; pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n", - hd->ioc->name, ctx2abort, type)); /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf); * Save the MF pointer in case the request times out. */ hd->tmPtr = mf; - hd->numTMrequests++; hd->TMtimer.expires = jiffies + timeout; add_timer(&hd->TMtimer); + dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", + hd->ioc->name, ctx2abort, type)); + + DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); + if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc, sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag)) != 0) { - dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!" + dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - hd->numTMrequests--; hd->tmPtr = NULL; del_timer(&hd->TMtimer); - mpt_free_msg_frame(ScsiTaskCtx, hd->ioc, mf); + mpt_free_msg_frame(hd->ioc, mf); } - + return retval; } @@ -2659,10 +2134,11 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun * * Returns SUCCESS or FAILED. */ -int +static int mptscsih_abort(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; MPT_FRAME_HDR *mf; u32 ctx2abort; int scpnt_idx; @@ -2673,12 +2149,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: " + dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: " "Can't locate host! (sc=%p)\n", SCpnt)); return FAILED; } + ioc = hd->ioc; if (hd->resetPending) return FAILED; @@ -2691,11 +2168,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. If found in - * doneQ, delete from Q. Do OS callback. + /* Cmd not found in ScsiLookup. + * Do OS callback. */ - search_doneQ_for_cmd(hd, SCpnt); - SCpnt->result = DID_RESET << 16; dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", @@ -2703,18 +2178,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) return SUCCESS; } - /* If this command is pended, then timeout/hang occurred - * during DV. Post command and flush pending Q - * and then following up with the reset request. - */ - if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) { - mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); - post_pendingQ_commands(hd); - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Posting pended cmd! (sc=%p)\n", - hd->ioc->name, SCpnt)); - } - /* Most important! Set TaskMsgContext to SCpnt's MsgContext! * (the IO to be ABORT'd) * @@ -2724,7 +2187,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) */ mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; - + hd->abortSCpnt = SCpnt; spin_unlock_irq(host_lock); @@ -2743,12 +2206,26 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) */ hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - + spin_lock_irq(host_lock); + + /* Unmap the DMA buffers, if any. */ + if (SCpnt->use_sg) { + pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, + SCpnt->use_sg, SCpnt->sc_data_direction); + } else if (SCpnt->request_bufflen) { + pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle, + SCpnt->request_bufflen, SCpnt->sc_data_direction); + } + hd->ScsiLookup[scpnt_idx] = NULL; + SCpnt->result = DID_RESET << 16; + SCpnt->scsi_done(SCpnt); /* Issue the command callback */ + mptscsih_freeChainBuffers(ioc, scpnt_idx); + mpt_free_msg_frame(ioc, mf); return FAILED; } spin_lock_irq(host_lock); - return FAILED; + return SUCCESS; } @@ -2761,7 +2238,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -int +static int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; @@ -2782,9 +2259,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); - /* Unsupported for SCSI. Supported for FCP + /* Supported for FC only. */ - if (hd->is_spi) + if (hd->ioc->bus_type == SCSI) return FAILED; spin_unlock_irq(host_lock); @@ -2816,7 +2293,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -int +static int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; @@ -2839,9 +2316,6 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) /* We are now ready to execute the task management request. */ spin_unlock_irq(host_lock); -// printk("testing start : mptscsih_schedule_reset\n"); -// mptscsih_schedule_reset(hd); -// printk("testing end: mptscsih_schedule_reset\n"); if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP) < 0){ @@ -2871,7 +2345,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) * * Returns SUCCESS or FAILED. */ -int +static int mptscsih_host_reset(struct scsi_cmnd *SCpnt) { MPT_SCSI_HOST * hd; @@ -2937,8 +2411,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); + msleep(250); } while (--loop_count); return status; @@ -2965,9 +2438,10 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m SCSITaskMgmt_t *pScsiTmReq; MPT_SCSI_HOST *hd; unsigned long flags; - u8 tmType = 0; + u16 iocstatus; + u8 tmType; - dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n", + dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", ioc->name, mf, mr)); if (ioc->sh) { /* Depending on the thread, a timer is activated for @@ -2978,8 +2452,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m if (hd->tmPtr) { del_timer(&hd->TMtimer); } - dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n", - ioc->name, hd->taskQcnt)); } else { dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); @@ -2997,18 +2469,15 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ tmType = pScsiTmReq->TaskType; - dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n", - tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); + dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", + ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); + DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; + dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", + ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); /* Error? (anything non-zero?) */ - if (*(u32 *)&pScsiTmReply->Reserved2[0]) { - u16 iocstatus; - - iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; - dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType)); - dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus)); - dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n", - le32_to_cpu(pScsiTmReply->IOCLogInfo))); + if (iocstatus) { /* clear flags and continue. */ @@ -3029,11 +2498,9 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m } } } else { - dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n")); + dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); - hd->numTMrequests--; hd->abortSCpnt = NULL; - flush_doneQ(hd); } } @@ -3051,26 +2518,21 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m /* * This is anyones guess quite frankly. */ -int +static int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]) { int heads; int sectors; sector_t cylinders; -#ifdef CONFIG_LBD ulong dummy; -#endif heads = 64; sectors = 32; -#ifdef CONFIG_LBD + dummy = heads * sectors; cylinders = capacity; sector_div(cylinders,dummy); -#else - cylinders = (ulong)capacity / (heads * sectors); -#endif /* * Handle extended translation size for logical drives @@ -3079,13 +2541,9 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, if ((ulong)capacity >= 0x200000) { heads = 255; sectors = 63; -#ifdef CONFIG_LBD dummy = heads * sectors; cylinders = capacity; sector_div(cylinders,dummy); -#else - cylinders = (ulong)capacity / (heads * sectors); -#endif } /* return result */ @@ -3107,38 +2565,60 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, * Return non-zero if allocation fails. * Init memory once per id (not LUN). */ -int +static int mptscsih_slave_alloc(struct scsi_device *device) { struct Scsi_Host *host = device->host; - MPT_SCSI_HOST *hd; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtDevice *vdev; - - hd = (MPT_SCSI_HOST *)host->hostdata; + uint target = device->id; if (hd == NULL) return -ENODEV; - if ((vdev = hd->Targets[device->id]) == NULL) { - if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) { - printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n", - hd->ioc->name, (int)sizeof(VirtDevice)); - return -ENOMEM; - } else { - memset(vdev, 0, sizeof(VirtDevice)); - rwlock_init(&vdev->VdevLock); - Q_INIT(&vdev->WaitQ, void); - Q_INIT(&vdev->SentQ, void); - Q_INIT(&vdev->DoneQ, void); - vdev->tflags = 0; - vdev->ioc_id = hd->ioc->id; - vdev->target_id = device->id; - vdev->bus_id = hd->port; - - hd->Targets[device->id] = vdev; + if ((vdev = hd->Targets[target]) != NULL) + goto out; + + vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + + memset(vdev, 0, sizeof(VirtDevice)); + vdev->tflags = MPT_TARGET_FLAGS_Q_YES; + vdev->ioc_id = hd->ioc->id; + vdev->target_id = device->id; + vdev->bus_id = device->channel; + vdev->raidVolume = 0; + hd->Targets[device->id] = vdev; + if (hd->ioc->bus_type == SCSI) { + if (hd->ioc->spi_data.isRaid & (1 << device->id)) { + vdev->raidVolume = 1; + ddvtprintk((KERN_INFO + "RAID Volume @ id %d\n", device->id)); } + } else { + vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; } + + out: vdev->num_luns++; + return 0; +} + +static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) +{ + int i; + + if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3) + return 0; + + for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) { + if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; + } return 0; } @@ -3147,72 +2627,84 @@ mptscsih_slave_alloc(struct scsi_device *device) * OS entry point to allow for host driver to free allocated memory * Called if no device present or device being unloaded */ -void +static void mptscsih_slave_destroy(struct scsi_device *device) { struct Scsi_Host *host = device->host; - MPT_SCSI_HOST *hd; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtDevice *vdev; - int raid_volume=0; - - hd = (MPT_SCSI_HOST *)host->hostdata; + uint target = device->id; + uint lun = device->lun; if (hd == NULL) return; - mptscsih_search_running_cmds(hd, device->id, device->lun); + mptscsih_search_running_cmds(hd, target, lun); - /* Free memory and reset all flags for this target - */ - if ((vdev = hd->Targets[device->id]) != NULL) { - vdev->num_luns--; - - if (vdev->luns[0] & (1 << device->lun)) - vdev->luns[0] &= ~(1 << device->lun); - - /* Free device structure only if number of luns is 0. - */ - if (vdev->num_luns == 0) { - kfree(hd->Targets[device->id]); - hd->Targets[device->id] = NULL; - - if (!hd->is_spi) - return; - - if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) { - int i; - for(i=0;iioc->spi_data.pIocPg3->NumPhysDisks && - raid_volume==0;i++) - - if(device->id == - hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) { - raid_volume=1; - hd->ioc->spi_data.forceDv |= - MPT_SCSICFG_RELOAD_IOC_PG3; - } - } + vdev = hd->Targets[target]; + vdev->luns[0] &= ~(1 << lun); + if (--vdev->num_luns) + return; - if(!raid_volume){ - hd->ioc->spi_data.dvStatus[device->id] = + kfree(hd->Targets[target]); + hd->Targets[target] = NULL; + + if (hd->ioc->bus_type == SCSI) { + if (mptscsih_is_raid_volume(hd, target)) { + hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; + } else { + hd->ioc->spi_data.dvStatus[target] = MPT_SCSICFG_NEGOTIATE; - if (hd->negoNvram == 0) - hd->ioc->spi_data.dvStatus[device->id] - |= MPT_SCSICFG_DV_NOT_DONE; + if (!hd->negoNvram) { + hd->ioc->spi_data.dvStatus[target] |= + MPT_SCSICFG_DV_NOT_DONE; } } } - - return; } +static void +mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd, + VirtDevice *pTarget, int qdepth) +{ + int max_depth; + int tagged; + + if (hd->ioc->bus_type == SCSI) { + if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { + if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) + max_depth = 1; + else if (((pTarget->inq_data[0] & 0x1f) == 0x00) && + (pTarget->minSyncFactor <= MPT_ULTRA160 )) + max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; + else + max_depth = MPT_SCSI_CMD_PER_DEV_LOW; + } else { + /* error case - No Inq. Data */ + max_depth = 1; + } + } else + max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; + + if (qdepth > max_depth) + qdepth = max_depth; + if (qdepth == 1) + tagged = 0; + else + tagged = MSG_SIMPLE_TAG; + + scsi_adjust_queue_depth(device, tagged, qdepth); +} + + /* * OS entry point to adjust the queue_depths on a per-device basis. * Called once per device the bus scan. Use it to force the queue_depth * member to 1 if a device does not support Q tags. * Return non-zero if fails. */ -int +static int mptscsih_slave_configure(struct scsi_device *device) { struct Scsi_Host *sh = device->host; @@ -3240,31 +2732,22 @@ mptscsih_slave_configure(struct scsi_device *device) pTarget = hd->Targets[device->id]; if (pTarget == NULL) { - /* error case - don't know about this device */ - scsi_adjust_queue_depth(device, 0, 1); + /* Driver doesn't know about this device. + * Kernel may generate a "Dummy Lun 0" which + * may become a real Lun if a + * "scsi add-single-device" command is executed + * while the driver is active (hot-plug a + * device). LSI Raid controllers need + * queue_depth set to DEV_HIGH for this reason. + */ + scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, + MPT_SCSI_CMD_PER_DEV_HIGH); goto slave_configure_exit; } mptscsih_initTarget(hd, device->channel, device->id, device->lun, device->inquiry, device->inquiry_len ); - scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - MPT_SCSI_CMD_PER_DEV_HIGH); - if ( hd->is_spi ) { - if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) - scsi_adjust_queue_depth(device, 0, 1); - else if (((pTarget->inq_data[0] & 0x1f) == 0x00) - && (pTarget->minSyncFactor <= MPT_ULTRA160 )) - scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - MPT_SCSI_CMD_PER_DEV_HIGH); - else - scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - MPT_SCSI_CMD_PER_DEV_LOW); - } else { - /* error case - No Inq. Data */ - scsi_adjust_queue_depth(device, 0, 1); - } - } + mptscsih_set_queue_depth(device, hd, pTarget, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk((MYIOC_s_INFO_FMT "Queue depth=%d, tflags=%x\n", @@ -3284,6 +2767,24 @@ slave_configure_exit: return 0; } +static ssize_t +mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count) +{ + int depth; + struct scsi_device *sdev = to_scsi_device(dev); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) sdev->host->hostdata; + VirtDevice *pTarget; + + depth = simple_strtoul(buf, NULL, 0); + if (depth == 0) + return -EINVAL; + pTarget = hd->Targets[sdev->id]; + if (pTarget == NULL) + return -EINVAL; + mptscsih_set_queue_depth(sdev, (MPT_SCSI_HOST *) sdev->host->hostdata, + pTarget, depth); + return count; +} /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -3302,16 +2803,12 @@ copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSI SCSIIORequest_t *pReq; u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); int index; - char devFoo[96]; - IO_Info_t thisIo; /* Get target structure */ pReq = (SCSIIORequest_t *) mf; index = (int) pReq->TargetID; target = hd->Targets[index]; - if (hd->is_multipath && sc->device->hostdata) - target = (VirtDevice *) sc->device->hostdata; if (sense_count) { u8 *sense_data; @@ -3342,35 +2839,10 @@ copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSI ioc->eventContext++; } } - - /* Print an error report for the user. - */ - thisIo.cdbPtr = sc->cmnd; - thisIo.sensePtr = sc->sense_buffer; - thisIo.SCSIStatus = pScsiReply->SCSIStatus; - thisIo.DoDisplay = 1; - if (hd->is_multipath) - sprintf(devFoo, "%d:%d:%d", - hd->ioc->id, - pReq->TargetID, - pReq->LUN[1]); - else - sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun); - thisIo.DevIDStr = devFoo; -/* fubar */ - thisIo.dataPtr = NULL; - thisIo.inqPtr = NULL; - if (sc->device) { - thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */ - } - (void) mpt_ScsiHost_ErrorReport(&thisIo); - } else { dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n", hd->ioc->name)); } - - return; } static u32 @@ -3390,102 +2862,6 @@ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) return -1; } - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Search the pendingQ for a command with specific index. - * If found, delete and return mf pointer - * If not found, return NULL - */ -static MPT_FRAME_HDR * -mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx) -{ - unsigned long flags; - MPT_DONE_Q *buffer; - MPT_FRAME_HDR *mf = NULL; - MPT_FRAME_HDR *cmdMfPtr; - - ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name)); - cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (!Q_IS_EMPTY(&hd->pendingQ)) { - buffer = hd->pendingQ.head; - do { - mf = (MPT_FRAME_HDR *) buffer->argp; - if (mf == cmdMfPtr) { - Q_DEL_ITEM(buffer); - - /* clear the arg pointer - */ - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - break; - } - mf = NULL; - } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ); - } - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - ddvtprintk((" ...return %p\n", mf)); - return mf; -} - -/* Post all commands on the pendingQ to the FW. - * Lock Q when deleting/adding members - * Lock io_request_lock for OS callback. - */ -static void -post_pendingQ_commands(MPT_SCSI_HOST *hd) -{ - MPT_FRAME_HDR *mf; - MPT_DONE_Q *buffer; - unsigned long flags; - - /* Flush the pendingQ. - */ - ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name)); - while (1) { - spin_lock_irqsave(&hd->freedoneQlock, flags); - if (Q_IS_EMPTY(&hd->pendingQ)) { - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - break; - } - - buffer = hd->pendingQ.head; - /* Delete from Q - */ - Q_DEL_ITEM(buffer); - - mf = (MPT_FRAME_HDR *) buffer->argp; - buffer->argp = NULL; - - /* Add to the freeQ - */ - Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); - spin_unlock_irqrestore(&hd->freedoneQlock, flags); - - if (!mf) { - /* This should never happen */ - printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf); - continue; - } - - mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf); - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - { - u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - struct scsi_cmnd *sc = hd->ScsiLookup[req_idx]; - printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n", - hd->ioc->name, sc, req_idx, mf); - } -#endif - } - - return; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) @@ -3520,14 +2896,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name)); /* 2. Flush running commands - * Clean drop test code - if compiled * Clean ScsiLookup (and associated memory) * AND clean mytaskQ */ - /* 2a. Drop Test Command. - */ - /* 2b. Reply to OS all known outstanding I/O commands. */ mptscsih_flush_running_cmds(hd); @@ -3538,7 +2910,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) */ if (hd->cmdPtr) { del_timer(&hd->timer); - mpt_free_msg_frame(ScsiScanDvCtx, ioc, hd->cmdPtr); + mpt_free_msg_frame(ioc, hd->cmdPtr); } /* 2d. If a task management has not completed, @@ -3546,13 +2918,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) */ if (hd->tmPtr) { del_timer(&hd->TMtimer); - mpt_free_msg_frame(ScsiTaskCtx, ioc, hd->tmPtr); + mpt_free_msg_frame(ioc, hd->tmPtr); } -#ifdef MPTSCSIH_DBG_TIMEOUT - ioc->timeout_hard = 0; -#endif - dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); } else { @@ -3573,7 +2941,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /* 2. Chain Buffer initialization */ - mptscsih_initChainBuffers(hd, 0); /* 3. tmPtr clear */ @@ -3583,8 +2950,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /* 4. Renegotiate to all devices, if SCSI */ - if (hd->is_spi) + if (ioc->bus_type == SCSI) { + dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); + } /* 5. Enable new commands to be posted */ @@ -3592,7 +2961,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->resetPending = 0; - hd->numTMrequests = 0; hd->tmState = TM_STATE_NONE; /* 6. If there was an internal command, @@ -3609,13 +2977,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - /* 7. Flush doneQ - */ - flush_doneQ(hd); - - /* 8. Set flag to force DV and re-read IOC Page 3 + /* 7. Set flag to force DV and re-read IOC Page 3 */ - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; ddvtprintk(("Set reload IOC Pg3 Flag\n")); } @@ -3634,7 +2998,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); switch (event) { @@ -3646,7 +3010,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) hd = NULL; if (ioc->sh) { hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (hd->is_spi) && (hd->soft_resets < -1)) + if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) hd->soft_resets++; } break; @@ -3675,7 +3039,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) if (ioc->sh) hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (hd->is_spi) && (hd->negoNvram == 0)) { + if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) { ScsiCfgData *pSpi; Ioc3PhysDisk_t *pPDisk; int numPDisk; @@ -3701,458 +3065,84 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); break; } - pPDisk++; - numPDisk--; - } - - if (numPDisk == 0) { - /* The physical disk that needs DV was not found - * in the stored IOC Page 3. The driver must reload - * this page. DV routine will set the NEED_DV flag for - * all phys disks that have DV_NOT_DONE set. - */ - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); - } - } - } - } -#endif - -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - printk("Raid Event RF: "); - { - u32 *m = (u32 *)pEvReply; - int ii; - int n = (int)pEvReply->MsgLength; - for (ii=6; ii < n; ii++) - printk(" %08x", le32_to_cpu(m[ii])); - printk("\n"); - } -#endif - break; - - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_EVENT_CHANGE: /* 0A */ - default: - dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event)); - break; - } - - return 1; /* currently means nothing really */ -} - -static struct scsi_host_template driver_template = { - .proc_name = "mptscsih", - .proc_info = mptscsih_proc_info, - .name = "MPT SCSI Host", - .info = mptscsih_info, - .queuecommand = mptscsih_qcmd, - .slave_alloc = mptscsih_slave_alloc, - .slave_configure = mptscsih_slave_configure, - .slave_destroy = mptscsih_slave_destroy, - .eh_abort_handler = mptscsih_abort, - .eh_device_reset_handler = mptscsih_dev_reset, - .eh_bus_reset_handler = mptscsih_bus_reset, - .eh_host_reset_handler = mptscsih_host_reset, - .bios_param = mptscsih_bios_param, - .can_queue = MPT_SCSI_CAN_QUEUE, - .this_id = -1, - .sg_tablesize = MPT_SCSI_SG_DEPTH, - .max_sectors = 8192, - .cmd_per_lun = 7, - .use_clustering = ENABLE_CLUSTERING, -}; - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private data... - */ -static ASCQ_Table_t *mptscsih_ASCQ_TablePtr; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* old symsense.c stuff... */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Private data... - * To protect ourselves against those that would pass us bogus pointers - */ -static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES] - = { 0x1F, 0x00, 0x00, 0x00, - 0x1F, 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 }; -static u8 dummySenseData[SCSI_STD_SENSE_BYTES] - = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 }; -static u8 dummyCDB[16] - = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static u8 dummyScsiData[16] - = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -static char *ScsiStatusString[] = { - "GOOD", /* 00h */ - NULL, /* 01h */ - "CHECK CONDITION", /* 02h */ - NULL, /* 03h */ - "CONDITION MET", /* 04h */ - NULL, /* 05h */ - NULL, /* 06h */ - NULL, /* 07h */ - "BUSY", /* 08h */ - NULL, /* 09h */ - NULL, /* 0Ah */ - NULL, /* 0Bh */ - NULL, /* 0Ch */ - NULL, /* 0Dh */ - NULL, /* 0Eh */ - NULL, /* 0Fh */ - "INTERMEDIATE", /* 10h */ - NULL, /* 11h */ - NULL, /* 12h */ - NULL, /* 13h */ - "INTERMEDIATE-CONDITION MET", /* 14h */ - NULL, /* 15h */ - NULL, /* 16h */ - NULL, /* 17h */ - "RESERVATION CONFLICT", /* 18h */ - NULL, /* 19h */ - NULL, /* 1Ah */ - NULL, /* 1Bh */ - NULL, /* 1Ch */ - NULL, /* 1Dh */ - NULL, /* 1Eh */ - NULL, /* 1Fh */ - NULL, /* 20h */ - NULL, /* 21h */ - "COMMAND TERMINATED", /* 22h */ - NULL, /* 23h */ - NULL, /* 24h */ - NULL, /* 25h */ - NULL, /* 26h */ - NULL, /* 27h */ - "TASK SET FULL", /* 28h */ - NULL, /* 29h */ - NULL, /* 2Ah */ - NULL, /* 2Bh */ - NULL, /* 2Ch */ - NULL, /* 2Dh */ - NULL, /* 2Eh */ - NULL, /* 2Fh */ - "ACA ACTIVE", /* 30h */ - NULL -}; - -static const char *ScsiCommonOpString[] = { - "TEST UNIT READY", /* 00h */ - "REZERO UNIT (REWIND)", /* 01h */ - NULL, /* 02h */ - "REQUEST_SENSE", /* 03h */ - "FORMAT UNIT (MEDIUM)", /* 04h */ - "READ BLOCK LIMITS", /* 05h */ - NULL, /* 06h */ - "REASSIGN BLOCKS", /* 07h */ - "READ(6)", /* 08h */ - NULL, /* 09h */ - "WRITE(6)", /* 0Ah */ - "SEEK(6)", /* 0Bh */ - NULL, /* 0Ch */ - NULL, /* 0Dh */ - NULL, /* 0Eh */ - "READ REVERSE", /* 0Fh */ - "WRITE_FILEMARKS", /* 10h */ - "SPACE(6)", /* 11h */ - "INQUIRY", /* 12h */ - NULL -}; - -static const char *SenseKeyString[] = { - "NO SENSE", /* 0h */ - "RECOVERED ERROR", /* 1h */ - "NOT READY", /* 2h */ - "MEDIUM ERROR", /* 3h */ - "HARDWARE ERROR", /* 4h */ - "ILLEGAL REQUEST", /* 5h */ - "UNIT ATTENTION", /* 6h */ - "DATA PROTECT", /* 7h */ - "BLANK CHECK", /* 8h */ - "VENDOR-SPECIFIC", /* 9h */ - "ABORTED COPY", /* Ah */ - "ABORTED COMMAND", /* Bh */ - "EQUAL (obsolete)", /* Ch */ - "VOLUME OVERFLOW", /* Dh */ - "MISCOMPARE", /* Eh */ - "RESERVED", /* Fh */ - NULL -}; - -#define SPECIAL_ASCQ(c,q) \ - (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70)) - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int dump_cdb(char *foo, unsigned char *cdb) -{ - int i, grpCode, cdbLen; - int l = 0; - - grpCode = cdb[0] >> 5; - if (grpCode < 1) - cdbLen = 6; - else if (grpCode < 3) - cdbLen = 10; - else if (grpCode == 5) - cdbLen = 12; - else - cdbLen = 16; - - for (i=0; i < cdbLen; i++) - l += sprintf(foo+l, " %02X", cdb[i]); - - return l; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Do ASC/ASCQ lookup/grindage to English readable string(s) */ -static const char * ascq_set_strings_4max( - u8 ASC, u8 ASCQ, - const char **s1, const char **s2, const char **s3, const char **s4) -{ - static const char *asc_04_part1_string = "LOGICAL UNIT "; - static const char *asc_04_part2a_string = "NOT READY, "; - static const char *asc_04_part2b_string = "IS "; - static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */ - "CAUSE NOT REPORTABLE", /* 04 00 */ - "IN PROCESS OF BECOMING READY", /* 04 01 */ - "INITIALIZING CMD. REQUIRED", /* 04 02 */ - "MANUAL INTERVENTION REQUIRED", /* 04 03 */ - /* Add " IN PROGRESS" to all the following... */ - "FORMAT", /* 04 04 */ - "REBUILD", /* 04 05 */ - "RECALCULATION", /* 04 06 */ - "OPERATION", /* 04 07 */ - "LONG WRITE", /* 04 08 */ - "SELF-TEST", /* 04 09 */ - NULL - }; - static char *asc_04_part4_string = " IN PROGRESS"; - - static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */ - "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */ - "POWER ON OCCURRED", /* 29 01 */ - "SCSI BUS RESET OCCURRED", /* 29 02 */ - "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */ - "DEVICE INTERNAL RESET", /* 29 04 */ - "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */ - "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */ - NULL - }; - static char *ascq_vendor_uniq = "(Vendor Unique)"; - static char *ascq_noone = "(no matching ASC/ASCQ description found)"; - int idx; - - *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */ - - /* CHECKME! Need lock/sem? - * Update and examine for isense module presense. - */ - mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr; - - if (mptscsih_ASCQ_TablePtr == NULL) { - /* 2nd chances... */ - if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) { - *s1 = asc_04_part1_string; - *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string; - *s3 = asc_04_ascq_NN_part3_strings[ASCQ]; - /* check for " IN PROGRESS" ones */ - if (ASCQ >= 0x04) - *s4 = asc_04_part4_string; - } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1)) - *s1 = asc_29_ascq_NN_strings[ASCQ]; - /* - * Else { leave all *s[1-4] values pointing to the empty "" string } - */ - return *s1; - } - - /* - * Need to check ASC here; if it is "special," then - * the ASCQ is variable, and indicates failed component number. - * We must treat the ASCQ as a "don't care" while searching the - * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later - * on when we actually need to identify the failed component. - */ - if (SPECIAL_ASCQ(ASC,ASCQ)) - ASCQ = 0xFF; - - /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */ - for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++) - if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) { - *s1 = mptscsih_ASCQ_TablePtr[idx].Description; - return *s1; - } - - if ((ASC >= 0x80) || (ASCQ >= 0x80)) - *s1 = ascq_vendor_uniq; - else - *s1 = ascq_noone; - - return *s1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Information Report; desired output format... - *--- -SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION) - Key=6h (UNIT ATTENTION); FRU=03h - ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED" - CDB: 00 00 00 00 00 00 - TestUnitReady - *--- - */ -/* - * SCSI Error Report; desired output format... - *--- -SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0) - SCSI_Status=02h (CHECK CONDITION) - Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady - SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00 - SenseKey=6h (UNIT ATTENTION); FRU=03h - ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED" - *--- - */ - -int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop) -{ - char foo[512]; - char buf2[32]; - char *statstr; - const char *opstr; - int sk = SD_Sense_Key(ioop->sensePtr); - const char *skstr = SenseKeyString[sk]; - unsigned char asc = SD_ASC(ioop->sensePtr); - unsigned char ascq = SD_ASCQ(ioop->sensePtr); - int l; - - /* Change the error logging to only report errors on - * read and write commands. Ignore errors on other commands. - * Should this be configurable via proc? - */ - switch (ioop->cdbPtr[0]) { - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - case READ_16: - case WRITE_16: - break; - default: - return 0; - } - - /* - * More quiet mode. - * Filter out common, repetitive, warning-type errors... like: - * POWER ON (06,29/00 or 06,29/01), - * SPINNING UP (02,04/01), - * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc. - */ - if (sk == SK_NO_SENSE) { - return 0; - } + pPDisk++; + numPDisk--; + } - if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01)) - || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02)) - || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00) - ) - { - /* Do nothing! */ - return 0; - } + if (numPDisk == 0) { + /* The physical disk that needs DV was not found + * in the stored IOC Page 3. The driver must reload + * this page. DV routine will set the NEED_DV flag for + * all phys disks that have DV_NOT_DONE set. + */ + pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; + ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); + } + } + } + } +#endif - /* Prevent the system from continually writing to the log - * if a medium is not found: 02 3A 00 - * Changer issues: TUR, Read Capacity, Table of Contents continually - */ - if (sk==SK_NOT_READY && asc==0x3A) { - if (ioop->cdbPtr == NULL) { - return 0; - } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) || - (ioop->cdbPtr[0] == CMD_ReadCapacity) || - (ioop->cdbPtr[0] == 0x43)) { - return 0; +#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) + printk("Raid Event RF: "); + { + u32 *m = (u32 *)pEvReply; + int ii; + int n = (int)pEvReply->MsgLength; + for (ii=6; ii < n; ii++) + printk(" %08x", le32_to_cpu(m[ii])); + printk("\n"); } - } - if (sk==SK_UNIT_ATTENTION) { - if (ioop->cdbPtr == NULL) - return 0; - else if (ioop->cdbPtr[0] == CMD_TestUnitReady) - return 0; - } +#endif + break; - /* - * Protect ourselves... - */ - if (ioop->cdbPtr == NULL) - ioop->cdbPtr = dummyCDB; - if (ioop->sensePtr == NULL) - ioop->sensePtr = dummySenseData; - if (ioop->inqPtr == NULL) - ioop->inqPtr = dummyInqData; - if (ioop->dataPtr == NULL) - ioop->dataPtr = dummyScsiData; - - statstr = NULL; - if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) || - ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) { - (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus); - statstr = buf2; + case MPI_EVENT_NONE: /* 00 */ + case MPI_EVENT_LOG_DATA: /* 01 */ + case MPI_EVENT_STATE_CHANGE: /* 02 */ + case MPI_EVENT_EVENT_CHANGE: /* 0A */ + default: + dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event)); + break; } - opstr = NULL; - if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*)) - opstr = ScsiCommonOpString[ioop->cdbPtr[0]]; - else if (mpt_ScsiOpcodesPtr) - opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]]; - - l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n", - ioop->DevIDStr, - ioop->SCSIStatus, - statstr); - l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh", - sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq ); - { - const char *x1, *x2, *x3, *x4; - x1 = x2 = x3 = x4 = ""; - x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4); - if (x1 != NULL) { - if (x1[0] != '(') - l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4); - else - l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4); - } - } - l += sprintf(foo+l, "\n CDB:"); - l += dump_cdb(foo+l, ioop->cdbPtr); - if (opstr) - l += sprintf(foo+l, " - \"%s\"", opstr); - l += sprintf(foo+l, "\n"); + return 1; /* currently means nothing really */ +} - PrintF(("%s\n", foo)); +static struct device_attribute mptscsih_queue_depth_attr = { + .attr = { + .name = "queue_depth", + .mode = S_IWUSR, + }, + .store = mptscsih_store_queue_depth, +}; - return l; -} +static struct device_attribute *mptscsih_dev_attrs[] = { + &mptscsih_queue_depth_attr, + NULL, +}; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static struct scsi_host_template driver_template = { + .proc_name = "mptscsih", + .proc_info = mptscsih_proc_info, + .name = "MPT SCSI Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptscsih_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_SCSI_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, + .sdev_attrs = mptscsih_dev_attrs, +}; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -4176,48 +3166,33 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * { int indexed_lun, lun_index; VirtDevice *vdev; + ScsiCfgData *pSpi; char data_56; - dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", + dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", hd->ioc->name, bus_id, target_id, lun, hd)); - /* Is LUN supported? If so, upper 3 bits will be 0 + /* Is LUN supported? If so, upper 2 bits will be 0 * in first byte of inquiry data. */ if (data[0] & 0xe0) return; - vdev = hd->Targets[target_id]; + if ((vdev = hd->Targets[target_id]) == NULL) { + return; + } lun_index = (lun >> 5); /* 32 luns per lun_index */ indexed_lun = (lun % 32); vdev->luns[lun_index] |= (1 << indexed_lun); - vdev->raidVolume = 0; - if (hd->is_spi) { - if (hd->ioc->spi_data.isRaid & (1 << target_id)) { - vdev->raidVolume = 1; - ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id)); - } - } - - if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { - if ( dlen > 8 ) { - memcpy (vdev->inq_data, data, 8); - } else { - memcpy (vdev->inq_data, data, dlen); - } - vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; - - /* If LUN 0, tape and have not done DV, set the DV flag. - */ - if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) { - ScsiCfgData *pSpi = &hd->ioc->spi_data; - if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE) - pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV; - } - - if ( (data[0] == SCSI_TYPE_PROC) && + if (hd->ioc->bus_type == SCSI) { + if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { + /* Treat all Processors as SAF-TE if + * command line option is set */ + vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptscsih_writeIOCPage4(hd, target_id, bus_id); + }else if ((data[0] == TYPE_PROCESSOR) && !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { if ( dlen > 49 ) { vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; @@ -4230,30 +3205,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; mptscsih_writeIOCPage4(hd, target_id, bus_id); } - } else { - /* Treat all Processors as SAF-TE if - * command line option is set */ - if ( hd->ioc->spi_data.Saf_Te ) { - vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, target_id, bus_id); - } } } + if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { + if ( dlen > 8 ) { + memcpy (vdev->inq_data, data, 8); + } else { + memcpy (vdev->inq_data, data, dlen); + } - data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */ - if (dlen > 56) { - if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) { - /* Update the target capabilities + /* If have not done DV, set the DV flag. */ - data_56 = data[56]; - vdev->tflags |= MPT_TARGET_FLAGS_VALID_56; + pSpi = &hd->ioc->spi_data; + if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) { + if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE) + pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV; + } + + vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; + + + data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */ + if (dlen > 56) { + if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) { + /* Update the target capabilities + */ + data_56 = data[56]; + vdev->tflags |= MPT_TARGET_FLAGS_VALID_56; + } + } + mptscsih_setTargetNegoParms(hd, vdev, data_56); + } else { + /* Initial Inquiry may not request enough data bytes to + * obtain byte 57. DV will; if target doesn't return + * at least 57 bytes, data[56] will be zero. */ + if (dlen > 56) { + if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) { + /* Update the target capabilities + */ + data_56 = data[56]; + vdev->tflags |= MPT_TARGET_FLAGS_VALID_56; + mptscsih_setTargetNegoParms(hd, vdev, data_56); + } } } - mptscsih_setTargetNegoParms(hd, vdev, data_56); } - - dprintk((KERN_INFO " target = %p\n", vdev)); - return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -4262,12 +3258,12 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * * the Inquiry data, adapter capabilities, and NVRAM settings. * */ -void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) +static void +mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) { ScsiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->target_id; int nvram; - char canQ = 0; VirtDevice *vdev; int ii; u8 width = MPT_NARROW; @@ -4276,14 +3272,6 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt u8 version, nfactor; u8 noQas = 1; - if (!hd->is_spi) { - if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - if (target->inq_data[7] & 0x02) - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - } - return; - } - target->negoFlags = pspi_data->noQas; /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine @@ -4293,137 +3281,152 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt /* Set flags based on Inquiry data */ - if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { - version = target->inq_data[2] & 0x07; - if (version < 2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - } else { - if (target->inq_data[7] & 0x20) { - width = 1; - } + version = target->inq_data[2] & 0x07; + if (version < 2) { + width = 0; + factor = MPT_ULTRA2; + offset = pspi_data->maxSyncOffset; + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + } else { + if (target->inq_data[7] & 0x20) { + width = 1; + } - if (target->inq_data[7] & 0x10) { - /* bits 2 & 3 show Clocking support - */ + if (target->inq_data[7] & 0x10) { + factor = pspi_data->minSyncFactor; + if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { + /* bits 2 & 3 show Clocking support */ if ((byte56 & 0x0C) == 0) factor = MPT_ULTRA2; else { if ((byte56 & 0x03) == 0) factor = MPT_ULTRA160; - else + else { factor = MPT_ULTRA320; - } - offset = pspi_data->maxSyncOffset; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if ((target->raidVolume == 1) || (byte56 & 0x02)) { - noQas = 0; + if (byte56 & 0x02) + { + ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); + noQas = 0; + } + if (target->inq_data[0] == TYPE_TAPE) { + if (byte56 & 0x01) + target->negoFlags |= MPT_TAPE_NEGO_IDP; + } + } } } else { - factor = MPT_ASYNC; - offset = 0; + ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); + noQas = 0; } - } + + offset = pspi_data->maxSyncOffset; - if (target->inq_data[7] & 0x02) { - canQ = 1; + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support + */ + if (target->raidVolume == 1) { + noQas = 0; + } + } else { + factor = MPT_ASYNC; + offset = 0; } + } - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; + if ( (target->inq_data[7] & 0x02) == 0) { + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + } - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; + /* Update tflags based on NVRAM settings. (SCSI only) + */ + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + nvram = pspi_data->nvram[id]; + nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; + if (width) + width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - factor = max(factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { + if (offset > 0) { + /* Ensure factor is set to the + * maximum of: adapter, nvram, inquiry + */ + if (nfactor) { + if (nfactor < pspi_data->minSyncFactor ) + nfactor = pspi_data->minSyncFactor; + + factor = max(factor, nfactor); + if (factor == MPT_ASYNC) offset = 0; - factor = MPT_ASYNC; - } } else { + offset = 0; factor = MPT_ASYNC; - } } - - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) { - factor = MPT_ULTRA2; + } else { + factor = MPT_ASYNC; } + } - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - if (canQ) { - target->tflags |= MPT_TARGET_FLAGS_Q_YES; - } + /* Make sure data is consistent + */ + if ((!width) && (factor < MPT_ULTRA2)) { + factor = MPT_ULTRA2; + } - target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; + /* Save the data to the target structure. + */ + target->minSyncFactor = factor; + target->maxOffset = offset; + target->maxWidth = width; - /* Disable unused features. - */ - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + /* Disable unused features. + */ + if (!width) + target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - /* GEM, processor WORKAROUND - */ - if (((target->inq_data[0] & 0x1F) == 0x03) - || ((target->inq_data[0] & 0x1F) > 0x08)) { - target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; - } else { - if (noQas && (pspi_data->noQas == 0)) { - pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + if (!offset) + target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - /* Disable QAS in a mixed configuration case - */ + if ( factor > MPT_ULTRA320 ) + noQas = 0; - ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); - for (ii = 0; ii < id; ii++) { - if ( (vdev = hd->Targets[ii]) ) { - vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - } - } + /* GEM, processor WORKAROUND + */ + if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { + target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); + pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; + } else { + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* Disable QAS in a mixed configuration case + */ + + ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + for (ii = 0; ii < id; ii++) { + if ( (vdev = hd->Targets[ii]) ) { + vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags); + } } } - - /* Write SDP1 on this I/O to this target */ - if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { - mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); - pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; - } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { - mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); - pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; - } } - return; + /* Write SDP1 on this I/O to this target */ + if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { + ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); + mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); + pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; + } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { + ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); + mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); + pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; + } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -4437,14 +3440,18 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) { u8 cmd; + ScsiCfgData *pSpi; + ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", + pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); + if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) return; cmd = pReq->CDB[0]; if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { - ScsiCfgData *pSpi = &hd->ioc->spi_data; + pSpi = &hd->ioc->spi_data; if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) { /* Set NEED_DV for all hidden disks */ @@ -4510,6 +3517,8 @@ mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; + if (flags & MPT_TAPE_NEGO_IDP) + *requestedPtr |= 0x08000000; } else if (factor < MPT_ULTRA2) { *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; } @@ -4624,6 +3633,16 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) //negoFlags = MPT_TARGET_NO_NEGO_SYNC; } + /* If id is not a raid volume, get the updated + * transmission settings from the target structure. + */ + if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { + width = pTarget->maxWidth; + factor = pTarget->minSyncFactor; + offset = pTarget->maxOffset; + negoFlags = pTarget->negoFlags; + } + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION /* Force to async and narrow if DV has not been executed * for this ID @@ -4635,21 +3654,13 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) } #endif - /* If id is not a raid volume, get the updated - * transmission settings from the target structure. - */ - if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { - width = pTarget->maxWidth; - factor = pTarget->minSyncFactor; - offset = pTarget->maxOffset; - negoFlags = pTarget->negoFlags; - } - if (flags & MPT_SCSICFG_BLK_NEGO) negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; mptscsih_setDevicePage1Flags(width, factor, offset, &requested, &configuration, negoFlags); + dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", + target_id, width, factor, offset, negoFlags, requested, configuration)); /* Get a MF for this command. */ @@ -4754,9 +3765,6 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) return -EAGAIN; } - ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n", - ioc->name, mf, target_id)); - /* Set the request and the data pointers. * Place data at end of MF. */ @@ -4793,9 +3801,9 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - dsprintk((MYIOC_s_INFO_FMT - "writeIOCPage4: pgaddr 0x%x\n", - ioc->name, (target_id | (bus<<8)))); + dinitprintk((MYIOC_s_INFO_FMT + "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", + ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); mpt_put_msg_frame(ScsiDoneCtx, ioc, mf); @@ -4922,13 +3930,15 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } else { SCSIIOReply_t *pReply; u16 status; + u8 scsi_status; pReply = (SCSIIOReply_t *) mr; status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; + scsi_status = pReply->SCSIStatus; ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n", - status, pReply->SCSIState, pReply->SCSIStatus, + status, pReply->SCSIState, scsi_status, le32_to_cpu(pReply->IOCLogInfo))); switch(status) { @@ -4973,7 +3983,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) /* save sense data in global structure */ completionCode = MPT_SCANDV_SENSE; - hd->pLocal->scsiStatus = pReply->SCSIStatus; + hd->pLocal->scsiStatus = scsi_status; sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_idx * MPT_SENSE_BUFFER_ALLOC)); @@ -4984,7 +3994,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n", sense_data)); } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { - if (pReq->CDB[0] == CMD_Inquiry) + if (pReq->CDB[0] == INQUIRY) completionCode = MPT_SCANDV_ISSUE_SENSE; else completionCode = MPT_SCANDV_DID_RESET; @@ -4994,11 +4004,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) completionCode = MPT_SCANDV_DID_RESET; else { - /* If no error, this will be equivalent - * to MPT_SCANDV_GOOD - */ completionCode = MPT_SCANDV_GOOD; - hd->pLocal->scsiStatus = pReply->SCSIStatus; + hd->pLocal->scsiStatus = scsi_status; } break; @@ -5025,7 +4032,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ wakeup: /* Free Chain buffers (will never chain) in scan or dv */ - //mptscsih_freeChainBuffers(hd, req_idx); + //mptscsih_freeChainBuffers(ioc, req_idx); /* * Wake up the original calling thread @@ -5197,7 +4204,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /* Set command specific information */ switch (cmd) { - case CMD_Inquiry: + case INQUIRY: cmdLen = 6; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; @@ -5205,13 +4212,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) cmdTimeout = 10; break; - case CMD_TestUnitReady: + case TEST_UNIT_READY: cmdLen = 6; dir = MPI_SCSIIO_CONTROL_READ; cmdTimeout = 10; break; - case CMD_StartStopUnit: + case START_STOP: cmdLen = 6; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; @@ -5219,7 +4226,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) cmdTimeout = 15; break; - case CMD_RequestSense: + case REQUEST_SENSE: cmdLen = 6; CDB[0] = cmd; CDB[4] = io->size; @@ -5227,7 +4234,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) cmdTimeout = 10; break; - case CMD_ReadBuffer: + case READ_BUFFER: cmdLen = 10; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; @@ -5246,7 +4253,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) cmdTimeout = 10; break; - case CMD_WriteBuffer: + case WRITE_BUFFER: cmdLen = 10; dir = MPI_SCSIIO_CONTROL_WRITE; CDB[0] = cmd; @@ -5261,21 +4268,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) cmdTimeout = 10; break; - case CMD_Reserve6: + case RESERVE: cmdLen = 6; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; cmdTimeout = 10; break; - case CMD_Release6: + case RELEASE: cmdLen = 6; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; cmdTimeout = 10; break; - case CMD_SynchronizeCache: + case SYNCHRONIZE_CACHE: cmdLen = 10; dir = MPI_SCSIIO_CONTROL_READ; CDB[0] = cmd; @@ -5331,7 +4338,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) else pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); - if (cmd == CMD_RequestSense) { + if (cmd == REQUEST_SENSE) { pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", hd->ioc->name, cmd)); @@ -5439,7 +4446,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) /* Following parameters will not change * in this routine. */ - iocmd.cmd = CMD_SynchronizeCache; + iocmd.cmd = SYNCHRONIZE_CACHE; iocmd.flags = 0; iocmd.physDiskNum = -1; iocmd.data = NULL; @@ -5460,7 +4467,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) /* Write SDP1 for all SCSI devices * Alloc memory and set up config buffer */ - if (hd->is_spi) { + if (ioc->bus_type == SCSI) { if (ioc->spi_data.sdp1length > 0) { pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev, ioc->spi_data.sdp1length * 4, &cfg1_dma_addr); @@ -5509,6 +4516,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) /* Force to async, narrow */ mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, &configuration, flags); + dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " + "offset=0 negoFlags=%x request=%x config=%x\n", + id, flags, requested, configuration)); pcfg1Data->RequestedParameters = le32_to_cpu(requested); pcfg1Data->Reserved = 0; pcfg1Data->Configuration = le32_to_cpu(configuration); @@ -5597,11 +4607,10 @@ mptscsih_domainValidation(void *arg) } spin_unlock_irqrestore(&dvtaskQ_lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); + msleep(250); /* DV only to SCSI adapters */ - if ((int)ioc->chip_type <= (int)FC929) + if (ioc->bus_type != SCSI) continue; /* Make sure everything looks ok */ @@ -5646,8 +4655,7 @@ mptscsih_domainValidation(void *arg) hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); + msleep(250); /* If hidden phys disk, block IO's to all * raid volumes @@ -5681,11 +4689,6 @@ mptscsih_domainValidation(void *arg) } } - /* Post OS IOs that were pended while - * DV running. - */ - post_pendingQ_commands(hd); - if (hd->ioc->spi_data.noQas) mptscsih_qas_check(hd, id); } @@ -5741,11 +4744,14 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) if ((pTarget != NULL) && (!pTarget->raidVolume)) { if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { pTarget->negoFlags |= hd->ioc->spi_data.noQas; + dnegoprintk(("writeSDP1: id=%d flags=0\n", id)); mptscsih_writeSDP1(hd, 0, ii, 0); } } else { - if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) + if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) { + dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id)); mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); + } } } return; @@ -5824,7 +4830,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) lun = 0; bus = (u8) bus_number; ddvtprintk((MYIOC_s_NOTE_FMT - "DV started: bus=%d, id %d dv @ %p\n", + "DV started: bus=%d, id=%d dv @ %p\n", ioc->name, bus, id, &dv)); /* Prep DV structure @@ -5838,8 +4844,6 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) */ dv.cmd = MPT_GET_NVRAM_VALS; mptscsih_dv_parms(hd, &dv, NULL); - if ((!dv.max.width) && (!dv.max.offset)) - return 0; /* Prep SCSI IO structure */ @@ -5851,15 +4855,6 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) iocmd.rsvd = iocmd.rsvd2 = 0; pTarget = hd->Targets[id]; - if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { - /* Another GEM workaround. Check peripheral device type, - * if PROCESSOR, quit DV. - */ - if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) { - pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); - return 0; - } - } /* Use tagged commands if possible. */ @@ -5959,7 +4954,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* Finish iocmd inititialization - hidden or visible disk? */ if (ioc->spi_data.pIocPg3) { - /* Searc IOC page 3 for matching id + /* Search IOC page 3 for matching id */ Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; @@ -6001,7 +4996,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) */ hd->pLocal = NULL; readPage0 = 0; - sz = SCSI_STD_INQUIRY_BYTES; + sz = SCSI_MAX_INQUIRY_BYTES; rc = MPT_SCANDV_GOOD; while (1) { ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); @@ -6026,7 +5021,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { - iocmd.cmd = CMD_RequestSense; + iocmd.cmd = REQUEST_SENSE; iocmd.data_dma = buf1_dma; iocmd.data = pbuf1; iocmd.size = 0x12; @@ -6046,10 +5041,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) goto target_done; } - iocmd.cmd = CMD_Inquiry; + iocmd.cmd = INQUIRY; iocmd.data_dma = buf1_dma; iocmd.data = pbuf1; iocmd.size = sz; + memset(pbuf1, 0x00, sz); if (mptscsih_do_cmd(hd, &iocmd) < 0) goto target_done; else { @@ -6057,7 +5053,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) goto target_done; rc = hd->pLocal->completion; if (rc == MPT_SCANDV_GOOD) { - if (hd->pLocal->scsiStatus == STS_BUSY) { + if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) { if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0) retcode = 1; else @@ -6087,7 +5083,17 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* Another GEM workaround. Check peripheral device type, * if PROCESSOR, quit DV. */ - if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08)) + if (inq0 == TYPE_PROCESSOR) { + mptscsih_initTarget(hd, + bus, + id, + lun, + pbuf1, + sz); + goto target_done; + } + + if (inq0 > 0x08) goto target_done; if (mptscsih_do_cmd(hd, &iocmd) < 0) @@ -6111,6 +5117,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) if ((pbuf1[56] & 0x02) == 0) { pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; + ddvprintk((MYIOC_s_NOTE_FMT + "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", + ioc->name, id, pbuf1[56])); } } } @@ -6127,10 +5136,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) if ((!dv.now.width) && (!dv.now.offset)) goto target_done; - iocmd.cmd = CMD_Inquiry; + iocmd.cmd = INQUIRY; iocmd.data_dma = buf2_dma; iocmd.data = pbuf2; iocmd.size = sz; + memset(pbuf2, 0x00, sz); if (mptscsih_do_cmd(hd, &iocmd) < 0) goto target_done; else if (hd->pLocal == NULL) @@ -6183,14 +5193,26 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) if (memcmp(pbuf1, pbuf2, sz) != 0) { if (!firstPass) doFallback = 1; - } else + } else { + ddvprintk((MYIOC_s_NOTE_FMT + "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); + hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; + mptscsih_initTarget(hd, + bus, + id, + lun, + pbuf1, + sz); break; /* test complete */ + } } } else if (rc == MPT_SCANDV_ISSUE_SENSE) doFallback = 1; /* set fallback flag */ - else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE)) + else if ((rc == MPT_SCANDV_DID_RESET) || + (rc == MPT_SCANDV_SENSE) || + (rc == MPT_SCANDV_FALLBACK)) doFallback = 1; /* set fallback flag */ else goto target_done; @@ -6199,6 +5221,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } } ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); + + if (driver_setup.dv == 0) + goto target_done; + inq0 = (*pbuf1) & 0x1F; /* Continue only for disks @@ -6222,7 +5248,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; - iocmd.cmd = CMD_TestUnitReady; + iocmd.cmd = TEST_UNIT_READY; iocmd.data_dma = -1; iocmd.data = NULL; iocmd.size = 0; @@ -6245,14 +5271,14 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, asc, ascq)); - if (skey == SK_UNIT_ATTENTION) + if (skey == UNIT_ATTENTION) notDone++; /* repeat */ - else if ((skey == SK_NOT_READY) && + else if ((skey == NOT_READY) && (asc == 0x04)&&(ascq == 0x01)) { /* wait then repeat */ mdelay (2000); notDone++; - } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) { + } else if ((skey == NOT_READY) && (asc == 0x3A)) { /* no medium, try read test anyway */ notDone = 0; } else { @@ -6266,7 +5292,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) goto target_done; } - iocmd.cmd = CMD_ReadBuffer; + iocmd.cmd = READ_BUFFER; iocmd.data_dma = buf1_dma; iocmd.data = pbuf1; iocmd.size = 4; @@ -6314,11 +5340,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) ddvprintk((MYIOC_s_INFO_FMT "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, asc, ascq)); - if (skey == SK_ILLEGAL_REQUEST) { + if (skey == ILLEGAL_REQUEST) { notDone = 0; - } else if (skey == SK_UNIT_ATTENTION) { + } else if (skey == UNIT_ATTENTION) { notDone++; /* repeat */ - } else if ((skey == SK_NOT_READY) && + } else if ((skey == NOT_READY) && (asc == 0x04)&&(ascq == 0x01)) { /* wait then repeat */ mdelay (2000); @@ -6373,14 +5399,14 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) for (patt = 0; patt < 4; patt++) { ddvprintk(("Pattern %d\n", patt)); if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) { - iocmd.cmd = CMD_TestUnitReady; + iocmd.cmd = TEST_UNIT_READY; iocmd.data_dma = -1; iocmd.data = NULL; iocmd.size = 0; if (mptscsih_do_cmd(hd, &iocmd) < 0) goto target_done; - iocmd.cmd = CMD_Release6; + iocmd.cmd = RELEASE; iocmd.data_dma = -1; iocmd.data = NULL; iocmd.size = 0; @@ -6402,7 +5428,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) repeat = 5; while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { - iocmd.cmd = CMD_Reserve6; + iocmd.cmd = RESERVE; iocmd.data_dma = -1; iocmd.data = NULL; iocmd.size = 0; @@ -6425,7 +5451,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", skey, asc, ascq)); - if ((skey == SK_NOT_READY) && (asc == 0x04)&& + if ((skey == NOT_READY) && (asc == 0x04)&& (ascq == 0x01)) { /* wait then repeat */ mdelay (2000); @@ -6444,7 +5470,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } mptscsih_fillbuf(pbuf1, sz, patt, 1); - iocmd.cmd = CMD_WriteBuffer; + iocmd.cmd = WRITE_BUFFER; iocmd.data_dma = buf1_dma; iocmd.data = pbuf1; iocmd.size = sz; @@ -6485,10 +5511,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) ddvprintk((MYIOC_s_INFO_FMT "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == SK_UNIT_ATTENTION) { + if (skey == UNIT_ATTENTION) { patt = -1; continue; - } else if (skey == SK_ILLEGAL_REQUEST) { + } else if (skey == ILLEGAL_REQUEST) { if (iocmd.flags & MPT_ICFLAG_ECHO) { if (dataBufSize >= bufsize) { iocmd.flags &= ~MPT_ICFLAG_ECHO; @@ -6506,7 +5532,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } } - iocmd.cmd = CMD_ReadBuffer; + iocmd.cmd = READ_BUFFER; iocmd.data_dma = buf2_dma; iocmd.data = pbuf2; iocmd.size = sz; @@ -6581,7 +5607,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) ddvprintk((MYIOC_s_INFO_FMT "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, hd->pLocal->sense[12], hd->pLocal->sense[13])); - if (skey == SK_UNIT_ATTENTION) { + if (skey == UNIT_ATTENTION) { patt = -1; continue; } @@ -6597,7 +5623,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) target_done: if (iocmd.flags & MPT_ICFLAG_RESERVED) { - iocmd.cmd = CMD_Release6; + iocmd.cmd = RELEASE; iocmd.data_dma = -1; iocmd.data = NULL; iocmd.size = 0; @@ -6619,8 +5645,11 @@ target_done: if ((cfg.hdr != NULL) && (retcode == 0)){ /* If disk, not U320, disable QAS */ - if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) + if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; + ddvprintk((MYIOC_s_NOTE_FMT + "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); + } dv.cmd = MPT_SAVE; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); @@ -6649,8 +5678,8 @@ target_done: if (pDvBuf) pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); - ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n", - ioc->name)); + ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n", + ioc->name, id)); return retcode; } @@ -6730,8 +5759,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) dv->max.offset = offset; dv->max.factor = factor; dv->max.flags = negoFlags; - ddvprintk((" width %d, factor %x, offset %x flags %x\n", - width, factor, offset, negoFlags)); + ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n", + id, width, factor, offset, negoFlags)); break; case MPT_UPDATE_MAX: @@ -6749,8 +5778,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) dv->now.width = dv->max.width; dv->now.offset = dv->max.offset; dv->now.factor = dv->max.factor; - ddvprintk(("width %d, factor %x, offset %x, flags %x\n", - dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); + ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n", + id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); break; case MPT_SET_MAX: @@ -6766,14 +5795,15 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) if (pPage1) { mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, dv->now.offset, &val, &configuration, dv->now.flags); + dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", + id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); pPage1->RequestedParameters = le32_to_cpu(val); pPage1->Reserved = 0; pPage1->Configuration = le32_to_cpu(configuration); - } - ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n", - dv->now.width, dv->now.factor, dv->now.offset, val, configuration)); + ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n", + id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); break; case MPT_SET_MIN: @@ -6790,12 +5820,14 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) if (pPage1) { mptscsih_setDevicePage1Flags (width, factor, offset, &val, &configuration, negoFlags); + dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", + id, width, factor, offset, negoFlags, val, configuration)); pPage1->RequestedParameters = le32_to_cpu(val); pPage1->Reserved = 0; pPage1->Configuration = le32_to_cpu(configuration); } - ddvprintk(("width %d, factor %x, offset %x request %x config %x\n", - width, factor, offset, val, configuration)); + ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", + id, width, factor, offset, val, configuration, negoFlags)); break; case MPT_FALLBACK: @@ -6855,6 +5887,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) factor = MPT_ASYNC; } dv->max.flags |= MPT_TARGET_NO_NEGO_QAS; + dv->max.flags &= ~MPT_TAPE_NEGO_IDP; dv->now.width = width; dv->now.offset = offset; @@ -6865,21 +5898,23 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) if (pPage1) { mptscsih_setDevicePage1Flags (width, factor, offset, &val, &configuration, dv->now.flags); + dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n", + id, width, offset, factor, dv->now.flags, val, configuration)); pPage1->RequestedParameters = le32_to_cpu(val); pPage1->Reserved = 0; pPage1->Configuration = le32_to_cpu(configuration); } - ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n", - dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); + ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", + id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); break; case MPT_SAVE: ddvprintk((MYIOC_s_NOTE_FMT "Saving to Target structure: ", hd->ioc->name)); - ddvprintk(("offset %d, factor %x, width %d \n", - dv->now.offset, dv->now.factor, dv->now.width)); + ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n", + id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); /* Save these values to target structures * or overwrite nvram (phys disks only). @@ -7046,107 +6081,6 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width) #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Commandline Parsing routines and defines. - * - * insmod format: - * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1" - * boot format: - * mptscsih=width:1,dv:n,factor:0x8,saf-te:1 - * - */ -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - -#ifdef MODULE -static char setup_token[] __initdata = - "dv:" - "width:" - "factor:" - "saf-te:" - ; /* DO NOT REMOVE THIS ';' */ -#endif - -#define OPT_DV 1 -#define OPT_MAX_WIDTH 2 -#define OPT_MIN_SYNC_FACTOR 3 -#define OPT_SAF_TE 4 - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#ifdef MODULE -static int -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; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mptscsih_setup(char *str) -{ - char *cur = str; - char *pc, *pv; - unsigned long val; - int c; - - 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); - - printk("Found Token: %s, value %x\n", cur, (int)val); - switch (get_setup_token(cur)) { - case OPT_DV: - driver_setup.dv = val; - break; - - case OPT_MAX_WIDTH: - driver_setup.max_width = val; - break; - - case OPT_MIN_SYNC_FACTOR: - driver_setup.min_sync_fac = val; - break; - - case OPT_SAF_TE: - driver_setup.saf_te = val; - break; - - default: - printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); - break; - } - - if ((cur = strchr(cur, ARG_SEP)) != NULL) - ++cur; - } - return 1; -} -#endif -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - module_init(mptscsih_init); module_exit(mptscsih_exit); diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 2c002b537..893f3c761 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -95,17 +95,8 @@ struct mptscsih_driver_setup { u8 dv; u8 max_width; - u8 min_sync_fac; + u8 min_sync_factor; u8 saf_te; }; - -#define MPTSCSIH_DRIVER_SETUP \ -{ \ - MPTSCSIH_DOMAIN_VALIDATION, \ - MPTSCSIH_MAX_WIDTH, \ - MPTSCSIH_MIN_SYNC, \ - MPTSCSIH_SAF_TE, \ -} - #endif diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile index e3169dbd9..aabc6cdc3 100644 --- a/drivers/message/i2o/Makefile +++ b/drivers/message/i2o/Makefile @@ -5,6 +5,7 @@ # In the future, some of these should be built conditionally. # +i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o obj-$(CONFIG_I2O) += i2o_core.o obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o obj-$(CONFIG_I2O_BLOCK) += i2o_block.o diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 7227a8a1e..2a5d478fc 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -4,40 +4,14 @@ #include #include -static int verbose; extern struct i2o_driver **i2o_drivers; extern unsigned int i2o_max_drivers; static void i2o_report_util_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd); -void i2o_report_fail_status(u8 req_status, u32 * msg); -void i2o_report_common_status(u8 req_status); +static void i2o_report_fail_status(u8 req_status, u32 * msg); +static void i2o_report_common_status(u8 req_status); static void i2o_report_common_dsc(u16 detailed_status); -void i2o_dump_status_block(i2o_status_block * sb) -{ - pr_debug("Organization ID: %d\n", sb->org_id); - pr_debug("IOP ID: %d\n", sb->iop_id); - pr_debug("Host Unit ID: %d\n", sb->host_unit_id); - pr_debug("Segment Number: %d\n", sb->segment_number); - pr_debug("I2O Version: %d\n", sb->i2o_version); - pr_debug("IOP State: %d\n", sb->iop_state); - pr_debug("Messanger Type: %d\n", sb->msg_type); - pr_debug("Inbound Frame Size: %d\n", sb->inbound_frame_size); - pr_debug("Init Code: %d\n", sb->init_code); - pr_debug("Max Inbound MFrames: %d\n", sb->max_inbound_frames); - pr_debug("Current Inbound MFrames: %d\n", sb->cur_inbound_frames); - pr_debug("Max Outbound MFrames: %d\n", sb->max_outbound_frames); - pr_debug("Product ID String: %s\n", sb->product_id); - pr_debug("Expected LCT Size: %d\n", sb->expected_lct_size); - pr_debug("IOP Capabilities: %d\n", sb->iop_capabilities); - pr_debug("Desired Private MemSize: %d\n", sb->desired_mem_size); - pr_debug("Current Private MemSize: %d\n", sb->current_mem_size); - pr_debug("Current Private MemBase: %d\n", sb->current_mem_base); - pr_debug("Desired Private IO Size: %d\n", sb->desired_io_size); - pr_debug("Current Private IO Size: %d\n", sb->current_io_size); - pr_debug("Current Private IO Base: %d\n", sb->current_io_base); -}; - /* * Used for error reporting/debugging purposes. * Report Cmd name, Request status, Detailed Status. @@ -54,7 +28,7 @@ void i2o_report_status(const char *severity, const char *str, if (cmd == I2O_CMD_UTIL_EVT_REGISTER) return; // No status in this reply - printk("%s%s: ", severity, str); + printk(KERN_DEBUG "%s%s: ", severity, str); if (cmd < 0x1F) // Utility cmd i2o_report_util_cmd(cmd); @@ -62,7 +36,7 @@ void i2o_report_status(const char *severity, const char *str, else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd i2o_report_exec_cmd(cmd); else - printk("Cmd = %0#2x, ", cmd); // Other cmds + printk(KERN_DEBUG "Cmd = %0#2x, ", cmd); // Other cmds if (msg[0] & MSG_FAIL) { i2o_report_fail_status(req_status, msg); @@ -74,7 +48,8 @@ void i2o_report_status(const char *severity, const char *str, if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF)) i2o_report_common_dsc(detailed_status); else - printk(" / DetailedStatus = %0#4x.\n", detailed_status); + printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n", + detailed_status); } /* Used to dump a message to syslog during debugging */ @@ -90,71 +65,12 @@ void i2o_dump_message(struct i2o_message *m) #endif } -/** - * i2o_report_controller_unit - print information about a tid - * @c: controller - * @d: device - * - * Dump an information block associated with a given unit (TID). The - * tables are read and a block of text is output to printk that is - * formatted intended for the user. - */ - -void i2o_report_controller_unit(struct i2o_controller *c, struct i2o_device *d) -{ - char buf[64]; - char str[22]; - int ret; - - if (verbose == 0) - return; - - printk(KERN_INFO "Target ID %03x.\n", d->lct_data.tid); - if ((ret = i2o_parm_field_get(d, 0xF100, 3, buf, 16)) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Vendor: %s\n", buf); - } - if ((ret = i2o_parm_field_get(d, 0xF100, 4, buf, 16)) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Device: %s\n", buf); - } - if (i2o_parm_field_get(d, 0xF100, 5, buf, 16) >= 0) { - buf[16] = 0; - printk(KERN_INFO " Description: %s\n", buf); - } - if ((ret = i2o_parm_field_get(d, 0xF100, 6, buf, 8)) >= 0) { - buf[8] = 0; - printk(KERN_INFO " Rev: %s\n", buf); - } - - printk(KERN_INFO " Class: "); - //sprintf(str, "%-21s", i2o_get_class_name(d->lct_data.class_id)); - printk("%s\n", str); - - printk(KERN_INFO " Subclass: 0x%04X\n", d->lct_data.sub_class); - printk(KERN_INFO " Flags: "); - - if (d->lct_data.device_flags & (1 << 0)) - printk("C"); // ConfigDialog requested - if (d->lct_data.device_flags & (1 << 1)) - printk("U"); // Multi-user capable - if (!(d->lct_data.device_flags & (1 << 4))) - printk("P"); // Peer service enabled! - if (!(d->lct_data.device_flags & (1 << 5))) - printk("M"); // Mgmt service enabled! - printk("\n"); -} - -/* -MODULE_PARM(verbose, "i"); -MODULE_PARM_DESC(verbose, "Verbose diagnostics"); -*/ /* * Used for error reporting/debugging purposes. * Following fail status are common to all classes. * The preserved message must be handled in the reply handler. */ -void i2o_report_fail_status(u8 req_status, u32 * msg) +static void i2o_report_fail_status(u8 req_status, u32 * msg) { static char *FAIL_STATUS[] = { "0x80", /* not used */ @@ -177,9 +93,11 @@ void i2o_report_fail_status(u8 req_status, u32 * msg) }; if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) - printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", req_status); + printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", + req_status); else - printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]); + printk(KERN_DEBUG "TRANSPORT_%s.\n", + FAIL_STATUS[req_status & 0x0F]); /* Dump some details */ @@ -192,16 +110,17 @@ void i2o_report_fail_status(u8 req_status, u32 * msg) printk(KERN_ERR " Severity: 0x%02X ", (msg[4] >> 16) & 0xFF); if (msg[4] & (1 << 16)) - printk("(FormatError), " + printk(KERN_DEBUG "(FormatError), " "this msg can never be delivered/processed.\n"); if (msg[4] & (1 << 17)) - printk("(PathError), " + printk(KERN_DEBUG "(PathError), " "this msg can no longer be delivered/processed.\n"); if (msg[4] & (1 << 18)) - printk("(PathState), " + printk(KERN_DEBUG "(PathState), " "the system state does not allow delivery.\n"); if (msg[4] & (1 << 19)) - printk("(Congestion), resources temporarily not available;" + printk(KERN_DEBUG + "(Congestion), resources temporarily not available;" "do not retry immediately.\n"); } @@ -209,7 +128,7 @@ void i2o_report_fail_status(u8 req_status, u32 * msg) * Used for error reporting/debugging purposes. * Following reply status are common to all classes. */ -void i2o_report_common_status(u8 req_status) +static void i2o_report_common_status(u8 req_status) { static char *REPLY_STATUS[] = { "SUCCESS", @@ -227,9 +146,9 @@ void i2o_report_common_status(u8 req_status) }; if (req_status >= ARRAY_SIZE(REPLY_STATUS)) - printk("RequestStatus = %0#2x", req_status); + printk(KERN_DEBUG "RequestStatus = %0#2x", req_status); else - printk("%s", REPLY_STATUS[req_status]); + printk(KERN_DEBUG "%s", REPLY_STATUS[req_status]); } /* @@ -272,9 +191,10 @@ static void i2o_report_common_dsc(u16 detailed_status) }; if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE) - printk(" / DetailedStatus = %0#4x.\n", detailed_status); + printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n", + detailed_status); else - printk(" / %s.\n", COMMON_DSC[detailed_status]); + printk(KERN_DEBUG " / %s.\n", COMMON_DSC[detailed_status]); } /* @@ -284,49 +204,49 @@ static void i2o_report_util_cmd(u8 cmd) { switch (cmd) { case I2O_CMD_UTIL_NOP: - printk("UTIL_NOP, "); + printk(KERN_DEBUG "UTIL_NOP, "); break; case I2O_CMD_UTIL_ABORT: - printk("UTIL_ABORT, "); + printk(KERN_DEBUG "UTIL_ABORT, "); break; case I2O_CMD_UTIL_CLAIM: - printk("UTIL_CLAIM, "); + printk(KERN_DEBUG "UTIL_CLAIM, "); break; case I2O_CMD_UTIL_RELEASE: - printk("UTIL_CLAIM_RELEASE, "); + printk(KERN_DEBUG "UTIL_CLAIM_RELEASE, "); break; case I2O_CMD_UTIL_CONFIG_DIALOG: - printk("UTIL_CONFIG_DIALOG, "); + printk(KERN_DEBUG "UTIL_CONFIG_DIALOG, "); break; case I2O_CMD_UTIL_DEVICE_RESERVE: - printk("UTIL_DEVICE_RESERVE, "); + printk(KERN_DEBUG "UTIL_DEVICE_RESERVE, "); break; case I2O_CMD_UTIL_DEVICE_RELEASE: - printk("UTIL_DEVICE_RELEASE, "); + printk(KERN_DEBUG "UTIL_DEVICE_RELEASE, "); break; case I2O_CMD_UTIL_EVT_ACK: - printk("UTIL_EVENT_ACKNOWLEDGE, "); + printk(KERN_DEBUG "UTIL_EVENT_ACKNOWLEDGE, "); break; case I2O_CMD_UTIL_EVT_REGISTER: - printk("UTIL_EVENT_REGISTER, "); + printk(KERN_DEBUG "UTIL_EVENT_REGISTER, "); break; case I2O_CMD_UTIL_LOCK: - printk("UTIL_LOCK, "); + printk(KERN_DEBUG "UTIL_LOCK, "); break; case I2O_CMD_UTIL_LOCK_RELEASE: - printk("UTIL_LOCK_RELEASE, "); + printk(KERN_DEBUG "UTIL_LOCK_RELEASE, "); break; case I2O_CMD_UTIL_PARAMS_GET: - printk("UTIL_PARAMS_GET, "); + printk(KERN_DEBUG "UTIL_PARAMS_GET, "); break; case I2O_CMD_UTIL_PARAMS_SET: - printk("UTIL_PARAMS_SET, "); + printk(KERN_DEBUG "UTIL_PARAMS_SET, "); break; case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY: - printk("UTIL_REPLY_FAULT_NOTIFY, "); + printk(KERN_DEBUG "UTIL_REPLY_FAULT_NOTIFY, "); break; default: - printk("Cmd = %0#2x, ", cmd); + printk(KERN_DEBUG "Cmd = %0#2x, ", cmd); } } @@ -337,106 +257,106 @@ static void i2o_report_exec_cmd(u8 cmd) { switch (cmd) { case I2O_CMD_ADAPTER_ASSIGN: - printk("EXEC_ADAPTER_ASSIGN, "); + printk(KERN_DEBUG "EXEC_ADAPTER_ASSIGN, "); break; case I2O_CMD_ADAPTER_READ: - printk("EXEC_ADAPTER_READ, "); + printk(KERN_DEBUG "EXEC_ADAPTER_READ, "); break; case I2O_CMD_ADAPTER_RELEASE: - printk("EXEC_ADAPTER_RELEASE, "); + printk(KERN_DEBUG "EXEC_ADAPTER_RELEASE, "); break; case I2O_CMD_BIOS_INFO_SET: - printk("EXEC_BIOS_INFO_SET, "); + printk(KERN_DEBUG "EXEC_BIOS_INFO_SET, "); break; case I2O_CMD_BOOT_DEVICE_SET: - printk("EXEC_BOOT_DEVICE_SET, "); + printk(KERN_DEBUG "EXEC_BOOT_DEVICE_SET, "); break; case I2O_CMD_CONFIG_VALIDATE: - printk("EXEC_CONFIG_VALIDATE, "); + printk(KERN_DEBUG "EXEC_CONFIG_VALIDATE, "); break; case I2O_CMD_CONN_SETUP: - printk("EXEC_CONN_SETUP, "); + printk(KERN_DEBUG "EXEC_CONN_SETUP, "); break; case I2O_CMD_DDM_DESTROY: - printk("EXEC_DDM_DESTROY, "); + printk(KERN_DEBUG "EXEC_DDM_DESTROY, "); break; case I2O_CMD_DDM_ENABLE: - printk("EXEC_DDM_ENABLE, "); + printk(KERN_DEBUG "EXEC_DDM_ENABLE, "); break; case I2O_CMD_DDM_QUIESCE: - printk("EXEC_DDM_QUIESCE, "); + printk(KERN_DEBUG "EXEC_DDM_QUIESCE, "); break; case I2O_CMD_DDM_RESET: - printk("EXEC_DDM_RESET, "); + printk(KERN_DEBUG "EXEC_DDM_RESET, "); break; case I2O_CMD_DDM_SUSPEND: - printk("EXEC_DDM_SUSPEND, "); + printk(KERN_DEBUG "EXEC_DDM_SUSPEND, "); break; case I2O_CMD_DEVICE_ASSIGN: - printk("EXEC_DEVICE_ASSIGN, "); + printk(KERN_DEBUG "EXEC_DEVICE_ASSIGN, "); break; case I2O_CMD_DEVICE_RELEASE: - printk("EXEC_DEVICE_RELEASE, "); + printk(KERN_DEBUG "EXEC_DEVICE_RELEASE, "); break; case I2O_CMD_HRT_GET: - printk("EXEC_HRT_GET, "); + printk(KERN_DEBUG "EXEC_HRT_GET, "); break; case I2O_CMD_ADAPTER_CLEAR: - printk("EXEC_IOP_CLEAR, "); + printk(KERN_DEBUG "EXEC_IOP_CLEAR, "); break; case I2O_CMD_ADAPTER_CONNECT: - printk("EXEC_IOP_CONNECT, "); + printk(KERN_DEBUG "EXEC_IOP_CONNECT, "); break; case I2O_CMD_ADAPTER_RESET: - printk("EXEC_IOP_RESET, "); + printk(KERN_DEBUG "EXEC_IOP_RESET, "); break; case I2O_CMD_LCT_NOTIFY: - printk("EXEC_LCT_NOTIFY, "); + printk(KERN_DEBUG "EXEC_LCT_NOTIFY, "); break; case I2O_CMD_OUTBOUND_INIT: - printk("EXEC_OUTBOUND_INIT, "); + printk(KERN_DEBUG "EXEC_OUTBOUND_INIT, "); break; case I2O_CMD_PATH_ENABLE: - printk("EXEC_PATH_ENABLE, "); + printk(KERN_DEBUG "EXEC_PATH_ENABLE, "); break; case I2O_CMD_PATH_QUIESCE: - printk("EXEC_PATH_QUIESCE, "); + printk(KERN_DEBUG "EXEC_PATH_QUIESCE, "); break; case I2O_CMD_PATH_RESET: - printk("EXEC_PATH_RESET, "); + printk(KERN_DEBUG "EXEC_PATH_RESET, "); break; case I2O_CMD_STATIC_MF_CREATE: - printk("EXEC_STATIC_MF_CREATE, "); + printk(KERN_DEBUG "EXEC_STATIC_MF_CREATE, "); break; case I2O_CMD_STATIC_MF_RELEASE: - printk("EXEC_STATIC_MF_RELEASE, "); + printk(KERN_DEBUG "EXEC_STATIC_MF_RELEASE, "); break; case I2O_CMD_STATUS_GET: - printk("EXEC_STATUS_GET, "); + printk(KERN_DEBUG "EXEC_STATUS_GET, "); break; case I2O_CMD_SW_DOWNLOAD: - printk("EXEC_SW_DOWNLOAD, "); + printk(KERN_DEBUG "EXEC_SW_DOWNLOAD, "); break; case I2O_CMD_SW_UPLOAD: - printk("EXEC_SW_UPLOAD, "); + printk(KERN_DEBUG "EXEC_SW_UPLOAD, "); break; case I2O_CMD_SW_REMOVE: - printk("EXEC_SW_REMOVE, "); + printk(KERN_DEBUG "EXEC_SW_REMOVE, "); break; case I2O_CMD_SYS_ENABLE: - printk("EXEC_SYS_ENABLE, "); + printk(KERN_DEBUG "EXEC_SYS_ENABLE, "); break; case I2O_CMD_SYS_MODIFY: - printk("EXEC_SYS_MODIFY, "); + printk(KERN_DEBUG "EXEC_SYS_MODIFY, "); break; case I2O_CMD_SYS_QUIESCE: - printk("EXEC_SYS_QUIESCE, "); + printk(KERN_DEBUG "EXEC_SYS_QUIESCE, "); break; case I2O_CMD_SYS_TAB_SET: - printk("EXEC_SYS_TAB_SET, "); + printk(KERN_DEBUG "EXEC_SYS_TAB_SET, "); break; default: - printk("Cmd = %#02x, ", cmd); + printk(KERN_DEBUG "Cmd = %#02x, ", cmd); } } @@ -445,46 +365,32 @@ void i2o_debug_state(struct i2o_controller *c) printk(KERN_INFO "%s: State = ", c->name); switch (((i2o_status_block *) c->status_block.virt)->iop_state) { case 0x01: - printk("INIT\n"); + printk(KERN_DEBUG "INIT\n"); break; case 0x02: - printk("RESET\n"); + printk(KERN_DEBUG "RESET\n"); break; case 0x04: - printk("HOLD\n"); + printk(KERN_DEBUG "HOLD\n"); break; case 0x05: - printk("READY\n"); + printk(KERN_DEBUG "READY\n"); break; case 0x08: - printk("OPERATIONAL\n"); + printk(KERN_DEBUG "OPERATIONAL\n"); break; case 0x10: - printk("FAILED\n"); + printk(KERN_DEBUG "FAILED\n"); break; case 0x11: - printk("FAULTED\n"); + printk(KERN_DEBUG "FAULTED\n"); break; default: - printk("%x (unknown !!)\n", + printk(KERN_DEBUG "%x (unknown !!)\n", ((i2o_status_block *) c->status_block.virt)->iop_state); } }; -void i2o_systab_debug(struct i2o_sys_tbl *sys_tbl) -{ - u32 *table; - int count; - u32 size; - - table = (u32 *) sys_tbl; - size = sizeof(struct i2o_sys_tbl) + sys_tbl->num_entries - * sizeof(struct i2o_sys_tbl_entry); - - for (count = 0; count < (size >> 2); count++) - printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]); -} - void i2o_dump_hrt(struct i2o_controller *c) { u32 *rows = (u32 *) c->hrt.virt; @@ -516,56 +422,60 @@ void i2o_dump_hrt(struct i2o_controller *c) d = (u8 *) (rows + 2); state = p[1] << 8 | p[0]; - printk("TID %04X:[", state & 0xFFF); + printk(KERN_DEBUG "TID %04X:[", state & 0xFFF); state >>= 12; if (state & (1 << 0)) - printk("H"); /* Hidden */ + printk(KERN_DEBUG "H"); /* Hidden */ if (state & (1 << 2)) { - printk("P"); /* Present */ + printk(KERN_DEBUG "P"); /* Present */ if (state & (1 << 1)) - printk("C"); /* Controlled */ + printk(KERN_DEBUG "C"); /* Controlled */ } if (state > 9) - printk("*"); /* Hard */ + printk(KERN_DEBUG "*"); /* Hard */ - printk("]:"); + printk(KERN_DEBUG "]:"); switch (p[3] & 0xFFFF) { case 0: /* Adapter private bus - easy */ - printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", - p[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); + printk(KERN_DEBUG + "Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], + d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 1: /* ISA bus */ - printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", - p[2], d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); + printk(KERN_DEBUG + "ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], + d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 2: /* EISA bus */ - printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", + printk(KERN_DEBUG + "EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 3: /* MCA bus */ - printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", - p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); + printk(KERN_DEBUG + "MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], + d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 4: /* PCI bus */ - printk("PCI %d: Bus %d Device %d Function %d", - p[2], d[2], d[1], d[0]); + printk(KERN_DEBUG + "PCI %d: Bus %d Device %d Function %d", p[2], + d[2], d[1], d[0]); break; case 0x80: /* Other */ default: - printk("Unsupported bus type."); + printk(KERN_DEBUG "Unsupported bus type."); break; } - printk("\n"); + printk(KERN_DEBUG "\n"); rows += length; } } -EXPORT_SYMBOL(i2o_dump_status_block); EXPORT_SYMBOL(i2o_dump_message); diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index ff4822ed4..e4f923588 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -15,6 +15,7 @@ #include #include +#include /* Exec OSM functions */ extern struct bus_type i2o_bus_type; @@ -34,7 +35,7 @@ extern struct bus_type i2o_bus_type; static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, u32 type) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -106,8 +107,7 @@ int i2o_device_claim_release(struct i2o_device *dev) if (!rc) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); } if (!rc) @@ -211,8 +211,8 @@ static struct i2o_device *i2o_device_alloc(void) * Returns a pointer to the I2O device on success or negative error code * on failure. */ -struct i2o_device *i2o_device_add(struct i2o_controller *c, - i2o_lct_entry * entry) +static struct i2o_device *i2o_device_add(struct i2o_controller *c, + i2o_lct_entry * entry) { struct i2o_device *dev; @@ -446,7 +446,7 @@ static struct class_interface i2o_device_class_interface = { int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, int oplen, void *reslist, int reslen) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; u32 *res32 = (u32 *) reslist; u32 *restmp = (u32 *) reslist; @@ -546,47 +546,6 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, return size; } -/* - * Set a scalar group value or a whole group. - */ -int i2o_parm_field_set(struct i2o_device *i2o_dev, int group, int field, - void *buf, int buflen) -{ - u16 *opblk; - u8 resblk[8 + buflen]; /* 8 bytes for header */ - int size; - - opblk = kmalloc(buflen + 64, GFP_KERNEL); - if (opblk == NULL) { - printk(KERN_ERR "i2o: no memory for operation buffer.\n"); - return -ENOMEM; - } - - opblk[0] = 1; /* operation count */ - opblk[1] = 0; /* pad */ - opblk[2] = I2O_PARAMS_FIELD_SET; - opblk[3] = group; - - if (field == -1) { /* whole group */ - opblk[4] = -1; - memcpy(opblk + 5, buf, buflen); - } else { /* single field */ - - opblk[4] = 1; - opblk[5] = field; - memcpy(opblk + 6, buf, buflen); - } - - size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_SET, opblk, - 12 + buflen, resblk, sizeof(resblk)); - - kfree(opblk); - if (size > buflen) - return buflen; - - return size; -} - /* * if oper == I2O_PARAMS_TABLE_GET, get from all rows * if fieldcount == -1 return all fields @@ -669,6 +628,5 @@ void i2o_device_exit(void) EXPORT_SYMBOL(i2o_device_claim); EXPORT_SYMBOL(i2o_device_claim_release); EXPORT_SYMBOL(i2o_parm_field_get); -EXPORT_SYMBOL(i2o_parm_field_set); EXPORT_SYMBOL(i2o_parm_table_get); EXPORT_SYMBOL(i2o_parm_issue); diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index bc69d66c2..388a44326 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -18,14 +18,13 @@ #include #include - /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; module_param_named(max_drivers, i2o_max_drivers, uint, 0); MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); /* I2O drivers lock and array */ -static spinlock_t i2o_drivers_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t i2o_drivers_lock; static struct i2o_driver **i2o_drivers; /** @@ -146,7 +145,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) struct i2o_device *i2o_dev; list_for_each_entry(i2o_dev, &c->devices, list) - i2o_driver_notify_device_remove(drv, i2o_dev); + i2o_driver_notify_device_remove(drv, i2o_dev); i2o_driver_notify_controller_remove(drv, c); } @@ -176,7 +175,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) * negative error code on failure (the message will be flushed too). */ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, - struct i2o_message *msg) + struct i2o_message __iomem *msg) { struct i2o_driver *drv; u32 context = readl(&msg->u.s.icntxt); @@ -246,14 +245,15 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, * Send notifications to all registered drivers that a new controller was * added. */ -void i2o_driver_notify_controller_add_all(struct i2o_controller *c) { +void i2o_driver_notify_controller_add_all(struct i2o_controller *c) +{ int i; struct i2o_driver *drv; - for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + for (i = 0; i < I2O_MAX_DRIVERS; i++) { drv = i2o_drivers[i]; - if(drv) + if (drv) i2o_driver_notify_controller_add(drv, c); } } @@ -265,14 +265,15 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c) { * Send notifications to all registered drivers that a controller was * removed. */ -void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) { +void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) +{ int i; struct i2o_driver *drv; - for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + for (i = 0; i < I2O_MAX_DRIVERS; i++) { drv = i2o_drivers[i]; - if(drv) + if (drv) i2o_driver_notify_controller_remove(drv, c); } } @@ -283,14 +284,15 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) { * * Send notifications to all registered drivers that a device was added. */ -void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) { +void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) +{ int i; struct i2o_driver *drv; - for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + for (i = 0; i < I2O_MAX_DRIVERS; i++) { drv = i2o_drivers[i]; - if(drv) + if (drv) i2o_driver_notify_device_add(drv, i2o_dev); } } @@ -301,14 +303,15 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) { * * Send notifications to all registered drivers that a device was removed. */ -void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) { +void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) +{ int i; struct i2o_driver *drv; - for(i = 0; i < I2O_MAX_DRIVERS; i ++) { + for (i = 0; i < I2O_MAX_DRIVERS; i++) { drv = i2o_drivers[i]; - if(drv) + if (drv) i2o_driver_notify_device_remove(drv, i2o_dev); } } @@ -324,6 +327,8 @@ int __init i2o_driver_init(void) { int rc = 0; + spin_lock_init(&i2o_drivers_lock); + if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != (2 * i2o_max_drivers - 1))) { diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 117f26106..b25dc619c 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -29,9 +29,12 @@ #include #include +#include struct i2o_driver i2o_exec_driver; +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); + /* Module internal functions from other sources */ extern int i2o_device_parse_lct(struct i2o_controller *); @@ -45,7 +48,7 @@ struct i2o_exec_wait { u32 tcntxt; /* transaction context from reply */ int complete; /* 1 if reply received otherwise 0 */ u32 m; /* message id */ - struct i2o_message *msg; /* pointer to the reply message */ + struct i2o_message __iomem *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ }; @@ -109,21 +112,20 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long timeout, struct i2o_dma *dma) { DECLARE_WAIT_QUEUE_HEAD(wq); - DEFINE_WAIT(wait); - struct i2o_exec_wait *iwait; + struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; - struct i2o_message *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = c->in_queue.virt + m; int rc = 0; - iwait = i2o_exec_wait_alloc(); - if (!iwait) + wait = i2o_exec_wait_alloc(); + if (!wait) return -ENOMEM; if (tcntxt == 0xffffffff) tcntxt = 0x80000000; if (dma) - iwait->dma = *dma; + wait->dma = *dma; /* * Fill in the message initiator context and transaction context. @@ -131,8 +133,8 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * so we could find a POST WAIT reply easier in the reply handler. */ writel(i2o_exec_driver.context, &msg->u.s.icntxt); - iwait->tcntxt = tcntxt++; - writel(iwait->tcntxt, &msg->u.s.tcntxt); + wait->tcntxt = tcntxt++; + writel(wait->tcntxt, &msg->u.s.tcntxt); /* * Post the message to the controller. At some point later it will @@ -140,31 +142,27 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long */ i2o_msg_post(c, m); - if (!iwait->complete) { - iwait->wq = &wq; + if (!wait->complete) { + wait->wq = &wq; /* * we add elements add the head, because if a entry in the list * will never be removed, we have to iterate over it every time */ - list_add(&iwait->list, &i2o_exec_wait_list); + list_add(&wait->list, &i2o_exec_wait_list); - prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); + wait_event_interruptible_timeout(wq, wait->complete, + timeout * HZ); - if (!iwait->complete) - schedule_timeout(timeout * HZ); - - finish_wait(&wq, &wait); - - iwait->wq = NULL; + wait->wq = NULL; } barrier(); - if (iwait->complete) { - if (readl(&iwait->msg->body[0]) >> 24) - rc = readl(&iwait->msg->body[0]) & 0xff; - i2o_flush_reply(c, iwait->m); - i2o_exec_wait_free(iwait); + if (wait->complete) { + if (readl(&wait->msg->body[0]) >> 24) + rc = readl(&wait->msg->body[0]) & 0xff; + i2o_flush_reply(c, wait->m); + i2o_exec_wait_free(wait); } else { /* * We cannot remove it now. This is important. When it does @@ -201,13 +199,15 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * message must also be given back to the controller. */ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, - struct i2o_message *msg) + struct i2o_message __iomem *msg) { struct i2o_exec_wait *wait, *tmp; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + static spinlock_t lock; int rc = 1; u32 context; + spin_lock_init(&lock); + context = readl(&msg->u.s.tcntxt); /* @@ -322,13 +322,13 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) static int i2o_exec_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { - if (readl(&msg->u.head[0]) & MSG_FAIL) { // Fail bit is set - struct i2o_message *pmsg; /* preserved message */ + if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set + struct i2o_message __iomem *pmsg; /* preserved message */ u32 pm; - pm = readl(&msg->body[3]); + pm = le32_to_cpu(msg->body[3]); - pmsg = c->in_queue.virt + pm; + pmsg = i2o_msg_in_to_virt(c, pm); i2o_report_status(KERN_INFO, "i2o_core", msg); @@ -339,10 +339,10 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, return -1; } - if (readl(&msg->u.s.tcntxt) & 0x80000000) + if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000) return i2o_msg_post_wait_complete(c, m, msg); - if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { struct work_struct *work; pr_debug("%s: LCT notify received\n", c->name); @@ -395,7 +395,7 @@ static void i2o_exec_event(struct i2o_event *evt) */ int i2o_exec_lct_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int i = 0; int rc = -EAGAIN; @@ -435,11 +435,11 @@ int i2o_exec_lct_get(struct i2o_controller *c) * replies immediately after the request. If change_ind > 0 the reply is * send after change indicator of the LCT is > change_ind. */ -int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) { i2o_status_block *sb = c->status_block.virt; struct device *dev; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; dev = &c->pdev->dev; @@ -502,4 +502,3 @@ void __exit i2o_exec_exit(void) EXPORT_SYMBOL(i2o_msg_post_wait_mem); EXPORT_SYMBOL(i2o_exec_lct_get); -EXPORT_SYMBOL(i2o_exec_lct_notify); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 36dc0e9d1..21d87c9f6 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -1,463 +1,425 @@ /* - * I2O Random Block Storage Class OSM + * Block OSM * - * (C) Copyright 1999-2002 Red Hat - * - * Written by Alan Cox, Building Number Three Ltd + * Copyright (C) 1999-2002 Red Hat Software * - * 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. + * Written by Alan Cox, Building Number Three Ltd * - * 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. + * 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. * - * For the purpose of avoiding doubt the preferred form of the work - * for making modifications shall be a standards compliant form such - * gzipped tar and not one requiring a proprietary or patent encumbered - * tool to unpack. + * 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. * - * This is a beta test release. Most of the good code was taken - * from the nbd driver by Pavel Machek, who in turn took some of it - * from loop.c. Isn't free software great for reusability 8) + * For the purpose of avoiding doubt the preferred form of the work + * for making modifications shall be a standards compliant form such + * gzipped tar and not one requiring a proprietary or patent encumbered + * tool to unpack. * - * Fixes/additions: - * Steve Ralston: - * Multiple device handling error fixes, - * Added a queue depth. - * Alan Cox: - * FC920 has an rmw bug. Dont or in the end marker. - * Removed queue walk, fixed for 64bitness. - * Rewrote much of the code over time - * Added indirect block lists - * Handle 64K limits on many controllers - * Don't use indirects on the Promise (breaks) - * Heavily chop down the queue depths - * Deepak Saxena: - * Independent queues per IOP - * Support for dynamic device creation/deletion - * Code cleanup - * Support for larger I/Os through merge* functions - * (taken from DAC960 driver) - * Boji T Kannanthanam: - * Set the I2O Block devices to be detected in increasing - * order of TIDs during boot. - * Search and set the I2O block device that we boot off from as - * the first device to be claimed (as /dev/i2o/hda) - * Properly attach/detach I2O gendisk structure from the system - * gendisk list. The I2O block devices now appear in - * /proc/partitions. - * Markus Lidel : - * Minor bugfixes for 2.6. - * - * To do: - * Serial number scanning to find duplicates for FC multipathing + * Fixes/additions: + * Steve Ralston: + * Multiple device handling error fixes, + * Added a queue depth. + * Alan Cox: + * FC920 has an rmw bug. Dont or in the end marker. + * Removed queue walk, fixed for 64bitness. + * Rewrote much of the code over time + * Added indirect block lists + * Handle 64K limits on many controllers + * Don't use indirects on the Promise (breaks) + * Heavily chop down the queue depths + * Deepak Saxena: + * Independent queues per IOP + * Support for dynamic device creation/deletion + * Code cleanup + * Support for larger I/Os through merge* functions + * (taken from DAC960 driver) + * Boji T Kannanthanam: + * Set the I2O Block devices to be detected in increasing + * order of TIDs during boot. + * Search and set the I2O block device that we boot off + * from as the first device to be claimed (as /dev/i2o/hda) + * Properly attach/detach I2O gendisk structure from the + * system gendisk list. The I2O block devices now appear in + * /proc/partitions. + * Markus Lidel : + * Minor bugfixes for 2.6. */ -#include - #include -#include -#include -#include -#include -#include -#include -#include -#include #include + +#include + +#include #include -#include -#include #include -#include -#include -#include -#include +#include "i2o_block.h" -#include -#include -#include -#include -#include -#include +static struct i2o_driver i2o_block_driver; -#define MAJOR_NR I2O_MAJOR +/* global Block OSM request mempool */ +static struct i2o_block_mempool i2o_blk_req_pool; -#define MAX_I2OB 16 +/* Block OSM class handling definition */ +static struct i2o_class_id i2o_block_class_id[] = { + {I2O_CLASS_RANDOM_BLOCK_STORAGE}, + {I2O_CLASS_END} +}; + +/** + * i2o_block_device_free - free the memory of the I2O Block device + * @dev: I2O Block device, which should be cleaned up + * + * Frees the request queue, gendisk and the i2o_block_device structure. + */ +static void i2o_block_device_free(struct i2o_block_device *dev) +{ + blk_cleanup_queue(dev->gd->queue); -#define MAX_I2OB_DEPTH 8 -#define MAX_I2OB_RETRIES 4 + put_disk(dev->gd); -//#define DRIVERDEBUG -#ifdef DRIVERDEBUG -#define DEBUG( s ) printk( s ) -#else -#define DEBUG( s ) -#endif + kfree(dev); +}; -/* - * Events that this OSM is interested in +/** + * i2o_block_remove - remove the I2O Block device from the system again + * @dev: I2O Block device which should be removed + * + * Remove gendisk from system and free all allocated memory. + * + * Always returns 0. */ -#define I2OB_EVENT_MASK (I2O_EVT_IND_BSA_VOLUME_LOAD | \ - I2O_EVT_IND_BSA_VOLUME_UNLOAD | \ - I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \ - I2O_EVT_IND_BSA_CAPACITY_CHANGE | \ - I2O_EVT_IND_BSA_SCSI_SMART ) +static int i2o_block_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); + printk(KERN_INFO "block-osm: Device removed %s\n", + i2o_blk_dev->gd->disk_name); -/* - * Some of these can be made smaller later - */ + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); -static int i2ob_context; -static struct block_device_operations i2ob_fops; + del_gendisk(i2o_blk_dev->gd); -/* - * I2O Block device descriptor + dev_set_drvdata(dev, NULL); + + i2o_device_claim_release(i2o_dev); + + i2o_block_device_free(i2o_blk_dev); + + return 0; +}; + +/** + * i2o_block_device flush - Flush all dirty data of I2O device dev + * @dev: I2O device which should be flushed + * + * Flushes all dirty data on device dev. + * + * Returns 0 on success or negative error code on failure. */ -struct i2ob_device +static int i2o_block_device_flush(struct i2o_device *dev) { - struct i2o_controller *controller; - struct i2o_device *i2odev; - int unit; - int tid; - int flags; - int refcnt; - struct request *head, *tail; - request_queue_t *req_queue; - int max_segments; - int max_direct; /* Not yet used properly */ - int done_flag; - int depth; - int rcache; - int wcache; - int power; - int index; - int media_change_flag; - u32 max_sectors; - struct gendisk *gd; + struct i2o_message __iomem *msg; + u32 m; + + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(60 << 16, &msg->body[0]); + pr_debug("Flushing...\n"); + + return i2o_msg_post_wait(dev->iop, m, 60); }; -/* - * FIXME: - * We should cache align these to avoid ping-ponging lines on SMP - * boxes under heavy I/O load... +/** + * i2o_block_device_mount - Mount (load) the media of device dev + * @dev: I2O device which should receive the mount request + * @media_id: Media Identifier + * + * Load a media into drive. Identifier should be set to -1, because the + * spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. */ - -struct i2ob_request +static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) { - struct i2ob_request *next; - struct request *req; - int num; - int sg_dma_direction; - int sg_nents; - struct scatterlist sg_table[16]; + struct i2o_message __iomem *msg; + u32 m; + + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(-1, &msg->body[0]); + writel(0, &msg->body[1]); + pr_debug("Mounting...\n"); + + return i2o_msg_post_wait(dev->iop, m, 2); }; -/* - * Per IOP request queue information +/** + * i2o_block_device_lock - Locks the media of device dev + * @dev: I2O device which should receive the lock request + * @media_id: Media Identifier * - * We have a separate request_queue_t per IOP so that a heavilly - * loaded I2O block device on an IOP does not starve block devices - * across all I2O controllers. - * + * Lock media of device dev to prevent removal. The media identifier + * should be set to -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. */ -struct i2ob_iop_queue +static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) { - unsigned int queue_depth; - struct i2ob_request request_queue[MAX_I2OB_DEPTH]; - struct i2ob_request *i2ob_qhead; - request_queue_t *req_queue; - spinlock_t lock; + struct i2o_message __iomem *msg; + u32 m; + + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(-1, &msg->body[0]); + pr_debug("Locking...\n"); + + return i2o_msg_post_wait(dev->iop, m, 2); }; -static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS]; -/* - * Each I2O disk is one of these. +/** + * i2o_block_device_unlock - Unlocks the media of device dev + * @dev: I2O device which should receive the unlocked request + * @media_id: Media Identifier + * + * Unlocks the media in device dev. The media identifier should be set to + * -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. */ +static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message __iomem *msg; + u32 m; -static struct i2ob_device i2ob_dev[MAX_I2OB]; -static int i2ob_dev_count = 0; + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; -/* - * Mutex and spin lock for event handling synchronization - * evt_msg contains the last event. - */ -static DECLARE_MUTEX_LOCKED(i2ob_evt_sem); -static DECLARE_COMPLETION(i2ob_thread_dead); -static spinlock_t i2ob_evt_lock = SPIN_LOCK_UNLOCKED; -static u32 evt_msg[MSG_FRAME_SIZE]; - -static void i2o_block_reply(struct i2o_handler *, struct i2o_controller *, - struct i2o_message *); -static void i2ob_new_device(struct i2o_controller *, struct i2o_device *); -static void i2ob_del_device(struct i2o_controller *, struct i2o_device *); -static void i2ob_reboot_event(void); -static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int); -static void i2ob_end_request(struct request *); -static void i2ob_request(request_queue_t *); -static int i2ob_init_iop(unsigned int); -static int i2ob_query_device(struct i2ob_device *, int, int, void*, int); -static int i2ob_evt(void *); - -static int evt_pid = 0; -static int evt_running = 0; -static int scan_unit = 0; + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(media_id, &msg->body[0]); + pr_debug("Unlocking...\n"); -/* - * I2O OSM registration structure...keeps getting bigger and bigger :) + return i2o_msg_post_wait(dev->iop, m, 2); +}; + +/** + * i2o_block_device_power - Power management for device dev + * @dev: I2O device which should receive the power management request + * @operation: Operation which should be send + * + * Send a power management request to the device dev. + * + * Returns 0 on success or negative error code on failure. */ -static struct i2o_handler i2o_block_handler = +static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) { - i2o_block_reply, - i2ob_new_device, - i2ob_del_device, - i2ob_reboot_event, - "I2O Block OSM", - 0, - I2O_CLASS_RANDOM_BLOCK_STORAGE + struct i2o_device *i2o_dev = dev->i2o_dev; + struct i2o_controller *c = i2o_dev->iop; + struct i2o_message __iomem *msg; + u32 m; + int rc; + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data. + tid, &msg->u.head[1]); + writel(op << 24, &msg->body[0]); + pr_debug("Power...\n"); + + rc = i2o_msg_post_wait(c, m, 60); + if (!rc) + dev->power = op; + + return rc; }; /** - * i2ob_get - Get an I2O message - * @dev: I2O block device + * i2o_block_request_alloc - Allocate an I2O block request struct * - * Get a message from the FIFO used for this block device. The message is returned - * or the I2O 'no message' value of 0xFFFFFFFF if nothing is available. + * Allocates an I2O block request struct and initialize the list. + * + * Returns a i2o_block_request pointer on success or negative error code + * on failure. */ +static inline struct i2o_block_request *i2o_block_request_alloc(void) +{ + struct i2o_block_request *ireq; -static u32 i2ob_get(struct i2ob_device *dev) + ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC); + if (!ireq) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&ireq->queue); + + return ireq; +}; + +/** + * i2o_block_request_free - Frees a I2O block request + * @ireq: I2O block request which should be freed + * + * Fres the allocated memory (give it back to the request mempool). + */ +static inline void i2o_block_request_free(struct i2o_block_request *ireq) { - struct i2o_controller *c=dev->controller; - return I2O_POST_READ32(c); -} + mempool_free(ireq, i2o_blk_req_pool.pool); +}; -static int i2ob_build_sglist(struct i2ob_device *dev, struct i2ob_request *ireq) +/** + * i2o_block_sglist_alloc - Allocate the SG list and map it + * @ireq: I2O block request + * + * Builds the SG list and map it into to be accessable by the controller. + * + * Returns the number of elements in the SG list or 0 on failure. + */ +static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq) { - struct scatterlist *sg = ireq->sg_table; + struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; int nents; - nents = blk_rq_map_sg(dev->req_queue, ireq->req, ireq->sg_table); - + nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); + if (rq_data_dir(ireq->req) == READ) ireq->sg_dma_direction = PCI_DMA_FROMDEVICE; else ireq->sg_dma_direction = PCI_DMA_TODEVICE; - ireq->sg_nents = pci_map_sg(dev->controller->pdev, sg, nents, ireq->sg_dma_direction); + ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents, + ireq->sg_dma_direction); + return ireq->sg_nents; -} +}; -void i2ob_free_sglist(struct i2ob_device *dev, struct i2ob_request *ireq) -{ - struct pci_dev *pdev = dev->controller->pdev; - struct scatterlist *sg = ireq->sg_table; - int nents = ireq->sg_nents; - pci_unmap_sg(pdev, sg, nents, ireq->sg_dma_direction); -} - /** - * i2ob_send - Turn a request into a message and send it - * @m: Message offset - * @dev: I2O device - * @ireq: Request structure - * @unit: Device identity - * - * Generate an I2O BSAREAD request. This interface function is called for devices that - * appear to explode when they are fed indirect chain pointers (notably right now this - * appears to afflict Promise hardwre, so be careful what you feed the hardware + * i2o_block_sglist_free - Frees the SG list + * @ireq: I2O block request from which the SG should be freed * - * No cleanup is done by this interface. It is done on the interrupt side when the - * reply arrives + * Frees the SG list from the I2O block request. */ - -static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit) +static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) { - struct i2o_controller *c = dev->controller; - int tid = dev->tid; - void *msg; - void *mptr; - u64 offset; - struct request *req = ireq->req; - int count = req->nr_sectors<<9; - struct scatterlist *sg; - int sgnum; - int i; + struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev; - // printk(KERN_INFO "i2ob_send called\n"); - /* Map the message to a virtual address */ - msg = c->msg_virt + m; - - sgnum = i2ob_build_sglist(dev, ireq); - - /* FIXME: if we have no resources how should we get out of this */ - if(sgnum == 0) - BUG(); - - /* - * Build the message based on the request. - */ - i2o_raw_writel(i2ob_context|(unit<<8), msg+8); - i2o_raw_writel(ireq->num, msg+12); - i2o_raw_writel(req->nr_sectors << 9, msg+20); + dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents, + ireq->sg_dma_direction); +}; - /* - * Mask out partitions from now on - */ - - /* This can be optimised later - just want to be sure its right for - starters */ - offset = ((u64)req->sector) << 9; - i2o_raw_writel( offset & 0xFFFFFFFF, msg+24); - i2o_raw_writel(offset>>32, msg+28); - mptr=msg+32; - - sg = ireq->sg_table; - if(rq_data_dir(req) == READ) - { - DEBUG("READ\n"); - i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4); - for(i = sgnum; i > 0; i--) - { - if(i != 1) - i2o_raw_writel(0x10000000|sg_dma_len(sg), mptr); - else - i2o_raw_writel(0xD0000000|sg_dma_len(sg), mptr); - i2o_raw_writel(sg_dma_address(sg), mptr+4); - mptr += 8; - count -= sg_dma_len(sg); - sg++; - } - switch(dev->rcache) - { - case CACHE_NULL: - i2o_raw_writel(0, msg+16);break; - case CACHE_PREFETCH: - i2o_raw_writel(0x201F0008, msg+16);break; - case CACHE_SMARTFETCH: - if(req->nr_sectors > 16) - i2o_raw_writel(0x201F0008, msg+16); - else - i2o_raw_writel(0x001F0000, msg+16); - break; - } - -// printk("Reading %d entries %d bytes.\n", -// mptr-msg-8, req->nr_sectors<<9); +/** + * i2o_block_prep_req_fn - Allocates I2O block device specific struct + * @q: request queue for the request + * @req: the request to prepare + * + * Allocate the necessary i2o_block_request struct and connect it to + * the request. This is needed that we not loose the SG list later on. + * + * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. + */ +static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) +{ + struct i2o_block_device *i2o_blk_dev = q->queuedata; + struct i2o_block_request *ireq; + + /* request is already processed by us, so return */ + if (req->flags & REQ_SPECIAL) { + pr_debug("REQ_SPECIAL already set!\n"); + req->flags |= REQ_DONTPREP; + return BLKPREP_OK; } - else if(rq_data_dir(req) == WRITE) - { - DEBUG("WRITE\n"); - i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4); - for(i = sgnum; i > 0; i--) - { - if(i != 1) - i2o_raw_writel(0x14000000|sg_dma_len(sg), mptr); - else - i2o_raw_writel(0xD4000000|sg_dma_len(sg), mptr); - i2o_raw_writel(sg_dma_address(sg), mptr+4); - mptr += 8; - count -= sg_dma_len(sg); - sg++; - } - switch(dev->wcache) - { - case CACHE_NULL: - i2o_raw_writel(0, msg+16);break; - case CACHE_WRITETHROUGH: - i2o_raw_writel(0x001F0008, msg+16);break; - case CACHE_WRITEBACK: - i2o_raw_writel(0x001F0010, msg+16);break; - case CACHE_SMARTBACK: - if(req->nr_sectors > 16) - i2o_raw_writel(0x001F0004, msg+16); - else - i2o_raw_writel(0x001F0010, msg+16); - break; - case CACHE_SMARTTHROUGH: - if(req->nr_sectors > 16) - i2o_raw_writel(0x001F0004, msg+16); - else - i2o_raw_writel(0x001F0010, msg+16); + /* connect the i2o_block_request to the request */ + if (!req->special) { + ireq = i2o_block_request_alloc(); + if (unlikely(IS_ERR(ireq))) { + pr_debug("unable to allocate i2o_block_request!\n"); + return BLKPREP_DEFER; } - -// printk("Writing %d entries %d bytes.\n", -// mptr-msg-8, req->nr_sectors<<9); - } - i2o_raw_writel(I2O_MESSAGE_SIZE(mptr-msg)>>2 | SGL_OFFSET_8, msg); - - if(count != 0) - { - printk(KERN_ERR "Request count botched by %d.\n", count); - } - i2o_post_message(c,m); - i2ob_queues[c->unit]->queue_depth ++; + ireq->i2o_blk_dev = i2o_blk_dev; + req->special = ireq; + ireq->req = req; + } else + ireq = req->special; - return 0; -} + /* do not come back here */ + req->flags |= REQ_DONTPREP | REQ_SPECIAL; -/* - * Remove a request from the _locked_ request list. We update both the - * list chain and if this is the last item the tail pointer. Caller - * must hold the lock. - */ - -static inline void i2ob_unhook_request(struct i2ob_request *ireq, - unsigned int iop) -{ - ireq->next = i2ob_queues[iop]->i2ob_qhead; - i2ob_queues[iop]->i2ob_qhead = ireq; -} + return BLKPREP_OK; +}; -/* - * Request completion handler +/** + * i2o_block_delayed_request_fn - delayed request queue function + * delayed_request: the delayed request with the queue to start + * + * If the request queue is stopped for a disk, and there is no open + * request, a new event is created, which calls this function to start + * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never + * be started again. */ - -static inline void i2ob_end_request(struct request *req) +static void i2o_block_delayed_request_fn(void *delayed_request) { - /* FIXME - pci unmap the request */ - - /* - * Loop until all of the buffers that are linked - * to this request have been marked updated and - * unlocked. - */ - - while (end_that_request_first( req, !req->errors, req->hard_cur_sectors )); + struct i2o_block_delayed_request *dreq = delayed_request; + struct request_queue *q = dreq->queue; + unsigned long flags; - /* - * It is now ok to complete the request. - */ - end_that_request_last( req ); - DEBUG("IO COMPLETED\n"); -} + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + kfree(dreq); +}; -/* - * OSM reply handler. This gets all the message replies +/** + * i2o_block_reply - Block OSM reply handler. + * @c: I2O controller from which the message arrives + * @m: message id of reply + * qmsg: the actuall I2O message reply + * + * This function gets all the message replies. + * */ - -static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg) +static int i2o_block_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) { - unsigned long flags; - struct i2ob_request *ireq = NULL; + struct i2o_block_request *ireq; + struct request *req; + struct i2o_block_device *dev; + struct request_queue *q; u8 st; - u32 *m = (u32 *)msg; - u8 unit = m[2]>>8; - struct i2ob_device *dev = &i2ob_dev[unit]; + unsigned long flags; + + /* FAILed message */ + if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) { + struct i2o_message *pmsg; + u32 pm; - /* - * FAILed message - */ - if(m[0] & (1<<13)) - { - DEBUG("FAIL"); /* * FAILed message from controller * We increment the error count and abort it @@ -468,65 +430,85 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str * better be on the safe side since no one really follows * the spec to the book :) */ - ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; - ireq->req->errors++; - - spin_lock_irqsave(dev->req_queue->queue_lock, flags); - i2ob_unhook_request(ireq, c->unit); - i2ob_end_request(ireq->req); - spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); - + pm = le32_to_cpu(msg->body[3]); + pmsg = i2o_msg_in_to_virt(c, pm); + + req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt)); + if (unlikely(!req)) { + printk(KERN_ERR "block-osm: NULL reply received!\n"); + return -1; + } + + ireq = req->special; + dev = ireq->i2o_blk_dev; + q = dev->gd->queue; + + req->errors++; + + spin_lock_irqsave(q->queue_lock, flags); + + while (end_that_request_chunk(req, !req->errors, + le32_to_cpu(pmsg->body[1]))) ; + end_that_request_last(req); + + dev->open_queue_depth--; + list_del(&ireq->queue); + blk_start_queue(q); + + spin_unlock_irqrestore(q->queue_lock, flags); + /* Now flush the message by making it a NOP */ - m[0]&=0x00FFFFFF; - m[0]|=(I2O_CMD_UTIL_NOP)<<24; - i2o_post_message(c, (unsigned long) m - (unsigned long) c->msg_virt); + i2o_msg_nop(c, pm); - return; + return -1; } - if(msg->function == I2O_CMD_UTIL_EVT_REGISTER) - { - spin_lock(&i2ob_evt_lock); - memcpy(evt_msg, msg, (m[0]>>16)<<2); - spin_unlock(&i2ob_evt_lock); - up(&i2ob_evt_sem); - return; + req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!req)) { + printk(KERN_ERR "block-osm: NULL reply received!\n"); + return -1; } - if(!dev->i2odev) - { + ireq = req->special; + dev = ireq->i2o_blk_dev; + q = dev->gd->queue; + + if (unlikely(!dev->i2o_dev)) { /* * This is HACK, but Intel Integrated RAID allows user - * to delete a volume that is claimed, locked, and in use + * to delete a volume that is claimed, locked, and in use * by the OS. We have to check for a reply from a - * non-existent device and flag it as an error or the system + * non-existent device and flag it as an error or the system * goes kaput... */ - ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; - ireq->req->errors++; - printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n"); - spin_lock_irqsave(dev->req_queue->queue_lock, flags); - i2ob_unhook_request(ireq, c->unit); - i2ob_end_request(ireq->req); - spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); - return; - } + req->errors++; + printk(KERN_WARNING + "I2O Block: Data transfer to deleted device!\n"); + spin_lock_irqsave(q->queue_lock, flags); + while (end_that_request_chunk + (req, !req->errors, le32_to_cpu(msg->body[1]))) ; + end_that_request_last(req); + + dev->open_queue_depth--; + list_del(&ireq->queue); + blk_start_queue(q); + + spin_unlock_irqrestore(q->queue_lock, flags); + return -1; + } /* - * Lets see what is cooking. We stuffed the - * request in the context. + * Lets see what is cooking. We stuffed the + * request in the context. */ - - ireq=&i2ob_queues[c->unit]->request_queue[m[3]]; - st=m[4]>>24; - if(st!=0) - { + st = le32_to_cpu(msg->body[0]) >> 24; + + if (st != 0) { int err; - char *bsa_errors[] = - { - "Success", - "Media Error", + char *bsa_errors[] = { + "Success", + "Media Error", "Failure communicating to device", "Device Failure", "Device is not ready", @@ -540,261 +522,56 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str "Device has reset", "Volume has changed, waiting for acknowledgement" }; - - err = m[4]&0xFFFF; - - /* - * Device not ready means two things. One is that the - * the thing went offline (but not a removal media) - * - * The second is that you have a SuperTrak 100 and the - * firmware got constipated. Unlike standard i2o card - * setups the supertrak returns an error rather than - * blocking for the timeout in these cases. - * - * Don't stick a supertrak100 into cache aggressive modes - */ - - - printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, - bsa_errors[m[4]&0XFFFF]); - if(m[4]&0x00FF0000) - printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF ); - printk(".\n"); - ireq->req->errors++; - } - else - ireq->req->errors = 0; - - /* - * Dequeue the request. We use irqsave locks as one day we - * may be running polled controllers from a BH... - */ - - i2ob_free_sglist(dev, ireq); - spin_lock_irqsave(dev->req_queue->queue_lock, flags); - i2ob_unhook_request(ireq, c->unit); - i2ob_end_request(ireq->req); - i2ob_queues[c->unit]->queue_depth --; - - /* - * We may be able to do more I/O - */ - - i2ob_request(dev->gd->queue); - spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); -} -/* - * Event handler. Needs to be a separate thread b/c we may have - * to do things like scan a partition table, or query parameters - * which cannot be done from an interrupt or from a bottom half. - */ -static int i2ob_evt(void *dummy) -{ - unsigned int evt; - unsigned long flags; - struct i2ob_device *dev; - int unit; - //The only event that has data is the SCSI_SMART event. - struct i2o_reply { - u32 header[4]; - u32 evt_indicator; - u8 ASC; - u8 ASCQ; - u16 pad; - u8 data[16]; - } *evt_local; - - daemonize("i2oblock"); - allow_signal(SIGKILL); - - evt_running = 1; - - while(1) - { - if(down_interruptible(&i2ob_evt_sem)) - { - evt_running = 0; - printk("exiting..."); - break; - } + err = le32_to_cpu(msg->body[0]) & 0xffff; /* - * Keep another CPU/interrupt from overwriting the - * message while we're reading it + * Device not ready means two things. One is that the + * the thing went offline (but not a removal media) * - * We stuffed the unit in the TxContext and grab the event mask - * None of the BSA we care about events have EventData + * The second is that you have a SuperTrak 100 and the + * firmware got constipated. Unlike standard i2o card + * setups the supertrak returns an error rather than + * blocking for the timeout in these cases. + * + * Don't stick a supertrak100 into cache aggressive modes */ - spin_lock_irqsave(&i2ob_evt_lock, flags); - evt_local = (struct i2o_reply *)evt_msg; - spin_unlock_irqrestore(&i2ob_evt_lock, flags); - unit = le32_to_cpu(evt_local->header[3]); - evt = le32_to_cpu(evt_local->evt_indicator); + printk(KERN_ERR "/dev/%s error: %s", dev->gd->disk_name, + bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]); + if (le32_to_cpu(msg->body[0]) & 0x00ff0000) + printk(KERN_ERR " - DDM attempted %d retries", + (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff); + printk(KERN_ERR ".\n"); + req->errors++; + } else + req->errors = 0; - dev = &i2ob_dev[unit]; - switch(evt) - { - /* - * New volume loaded on same TID, so we just re-install. - * The TID/controller don't change as it is the same - * I2O device. It's just new media that we have to - * rescan. - */ - case I2O_EVT_IND_BSA_VOLUME_LOAD: - { - i2ob_install_device(dev->i2odev->controller, - dev->i2odev, unit); - add_disk(dev->gd); - break; - } + if (!end_that_request_chunk + (req, !req->errors, le32_to_cpu(msg->body[1]))) { + add_disk_randomness(req->rq_disk); + spin_lock_irqsave(q->queue_lock, flags); - /* - * No media, so set all parameters to 0 and set the media - * change flag. The I2O device is still valid, just doesn't - * have media, so we don't want to clear the controller or - * device pointer. - */ - case I2O_EVT_IND_BSA_VOLUME_UNLOAD: - { - struct gendisk *p = dev->gd; - blk_queue_max_sectors(dev->gd->queue, 0); - del_gendisk(p); - put_disk(p); - dev->gd = NULL; - dev->media_change_flag = 1; - break; - } + end_that_request_last(req); - case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ: - printk(KERN_WARNING "%s: Attempt to eject locked media\n", - dev->i2odev->dev_name); - break; + dev->open_queue_depth--; + list_del(&ireq->queue); + blk_start_queue(q); - /* - * The capacity has changed and we are going to be - * updating the max_sectors and other information - * about this disk. We try a revalidate first. If - * the block device is in use, we don't want to - * do that as there may be I/Os bound for the disk - * at the moment. In that case we read the size - * from the device and update the information ourselves - * and the user can later force a partition table - * update through an ioctl. - */ - case I2O_EVT_IND_BSA_CAPACITY_CHANGE: - { - u64 size; - - if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 ) - i2ob_query_device(dev, 0x0000, 4, &size, 8); - - spin_lock_irqsave(dev->req_queue->queue_lock, flags); - set_capacity(dev->gd, size>>9); - spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); - break; - } + spin_unlock_irqrestore(q->queue_lock, flags); - /* - * We got a SCSI SMART event, we just log the relevant - * information and let the user decide what they want - * to do with the information. - */ - case I2O_EVT_IND_BSA_SCSI_SMART: - { - char buf[16]; - printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name); - evt_local->data[16]='\0'; - sprintf(buf,"%s",&evt_local->data[0]); - printk(KERN_INFO " Disk Serial#:%s\n",buf); - printk(KERN_INFO " ASC 0x%02x \n",evt_local->ASC); - printk(KERN_INFO " ASCQ 0x%02x \n",evt_local->ASCQ); - break; - } - - /* - * Non event - */ - - case 0: - break; - - /* - * An event we didn't ask for. Call the card manufacturer - * and tell them to fix their firmware :) - */ - - case 0x20: - /* - * If a promise card reports 0x20 event then the brown stuff - * hit the fan big time. The card seems to recover but loses - * the pending writes. Deeply ungood except for testing fsck - */ - if(dev->i2odev->controller->promise) - panic("I2O controller firmware failed. Reboot and force a filesystem check.\n"); - default: - printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n" - KERN_INFO " Blame the I2O card manufacturer 8)\n", - dev->i2odev->dev_name, evt); - break; - } - }; - - complete_and_exit(&i2ob_thread_dead,0); - return 0; -} + i2o_block_sglist_free(ireq); + i2o_block_request_free(ireq); + } else + printk(KERN_ERR "i2o_block: still remaining chunks\n"); -/* - * The I2O block driver is listed as one of those that pulls the - * front entry off the queue before processing it. This is important - * to remember here. If we drop the io lock then CURRENT will change - * on us. We must unlink CURRENT in this routine before we return, if - * we use it. - */ + return 1; +}; -static void i2ob_request(request_queue_t *q) +static void i2o_block_event(struct i2o_event *evt) { - struct request *req; - struct i2ob_request *ireq; - struct i2ob_device *dev; - u32 m; - - while ((req = elv_next_request(q)) != NULL) { - dev = req->rq_disk->private_data; - - /* - * Queue depths probably belong with some kind of - * generic IOP commit control. Certainly it's not right - * its global! - */ - if(i2ob_queues[dev->unit]->queue_depth >= dev->depth) - break; - - /* Get a message */ - m = i2ob_get(dev); - - if(m==0xFFFFFFFF) - { - if(i2ob_queues[dev->unit]->queue_depth == 0) - printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n"); - break; - } - /* - * Everything ok, so pull from kernel queue onto our queue - */ - req->errors = 0; - blkdev_dequeue_request(req); - - ireq = i2ob_queues[dev->unit]->i2ob_qhead; - i2ob_queues[dev->unit]->i2ob_qhead = ireq->next; - ireq->req = req; - - i2ob_send(m, dev, ireq, dev->index); - } -} - + printk(KERN_INFO "block-osm: event received\n"); +}; /* * SCSI-CAM for ioctl geometry mapping @@ -803,8 +580,8 @@ static void i2ob_request(request_queue_t *q) * * LBA -> CHS mapping table taken from: * - * "Incorporating the I2O Architecture into BIOS for Intel Architecture - * Platforms" + * "Incorporating the I2O Architecture into BIOS for Intel Architecture + * Platforms" * * This is an I2O document that is only available to I2O members, * not developers. @@ -825,865 +602,647 @@ static void i2ob_request(request_queue_t *q) #define BLOCK_SIZE_42G 8806400 #define BLOCK_SIZE_84G 17612800 -static void i2o_block_biosparam( - unsigned long capacity, - unsigned short *cyls, - unsigned char *hds, - unsigned char *secs) -{ - unsigned long heads, sectors, cylinders; +static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, + unsigned char *hds, unsigned char *secs) +{ + unsigned long heads, sectors, cylinders; - sectors = 63L; /* Maximize sectors per track */ - if(capacity <= BLOCK_SIZE_528M) + sectors = 63L; /* Maximize sectors per track */ + if (capacity <= BLOCK_SIZE_528M) heads = 16; - else if(capacity <= BLOCK_SIZE_1G) + else if (capacity <= BLOCK_SIZE_1G) heads = 32; - else if(capacity <= BLOCK_SIZE_21G) + else if (capacity <= BLOCK_SIZE_21G) heads = 64; - else if(capacity <= BLOCK_SIZE_42G) + else if (capacity <= BLOCK_SIZE_42G) heads = 128; else heads = 255; cylinders = (unsigned long)capacity / (heads * sectors); - *cyls = (unsigned short) cylinders; /* Stuff return values */ - *secs = (unsigned char) sectors; - *hds = (unsigned char) heads; + *cyls = (unsigned short)cylinders; /* Stuff return values */ + *secs = (unsigned char)sectors; + *hds = (unsigned char)heads; } -/* - * Issue device specific ioctl calls. +/** + * i2o_block_open - Open the block device + * + * Power up the device, mount and lock the media. This function is called, + * if the block device is opened for access. + * + * Returns 0 on success or negative error code on failure. */ - -static int i2ob_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int i2o_block_open(struct inode *inode, struct file *file) { - struct gendisk *disk = inode->i_bdev->bd_disk; - struct i2ob_device *dev = disk->private_data; - void __user *argp = (void __user *)arg; + struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data; - /* Anyone capable of this syscall can do *real bad* things */ + if (!dev->i2o_dev) + return -ENODEV; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - i2o_block_biosparam(get_capacity(disk), - &g.cylinders, &g.heads, &g.sectors); - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(argp, &g, sizeof(g))?-EFAULT:0; - } - - case BLKI2OGRSTRAT: - return put_user(dev->rcache, (int __user *)argp); - case BLKI2OGWSTRAT: - return put_user(dev->wcache, (int __user *)argp); - case BLKI2OSRSTRAT: - if(arg<0||arg>CACHE_SMARTFETCH) - return -EINVAL; - dev->rcache = arg; - break; - case BLKI2OSWSTRAT: - if(arg!=0 && (argCACHE_SMARTBACK)) - return -EINVAL; - dev->wcache = arg; - break; - } - return -ENOTTY; -} + if (dev->power > 0x1f) + i2o_block_device_power(dev, 0x02); -/* - * Close the block device down + i2o_block_device_mount(dev->i2o_dev, -1); + + i2o_block_device_lock(dev->i2o_dev, -1); + + pr_debug("Ready.\n"); + + return 0; +}; + +/** + * i2o_block_release - Release the I2O block device + * + * Unlock and unmount the media, and power down the device. Gets called if + * the block device is closed. + * + * Returns 0 on success or negative error code on failure. */ - -static int i2ob_release(struct inode *inode, struct file *file) +static int i2o_block_release(struct inode *inode, struct file *file) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct i2ob_device *dev = disk->private_data; + struct i2o_block_device *dev = disk->private_data; + u8 operation; /* * This is to deail with the case of an application * opening a device and then the device dissapears while * it's in use, and then the application tries to release - * it. ex: Unmounting a deleted RAID volume at reboot. + * it. ex: Unmounting a deleted RAID volume at reboot. * If we send messages, it will just cause FAILs since * the TID no longer exists. */ - if(!dev->i2odev) + if (!dev->i2o_dev) return 0; - if (dev->refcnt <= 0) - printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt); - dev->refcnt--; - if(dev->refcnt==0) - { - /* - * Flush the onboard cache on unmount - */ - u32 msg[5]; - int *query_done = &dev->done_flag; - msg[0] = (FIVE_WORD_MSG_SIZE|SGL_OFFSET_0); - msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid; - msg[2] = i2ob_context|0x40000000; - msg[3] = (u32)query_done; - msg[4] = 60<<16; - DEBUG("Flushing..."); - i2o_post_wait(dev->controller, msg, 20, 60); + i2o_block_device_flush(dev->i2o_dev); - /* - * Unlock the media - */ - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid; - msg[2] = i2ob_context|0x40000000; - msg[3] = (u32)query_done; - msg[4] = -1; - DEBUG("Unlocking..."); - i2o_post_wait(dev->controller, msg, 20, 2); - DEBUG("Unlocked.\n"); - - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid; - if(dev->flags & (1<<3|1<<4)) /* Removable */ - msg[4] = 0x21 << 24; - else - msg[4] = 0x24 << 24; - - if(i2o_post_wait(dev->controller, msg, 20, 60)==0) - dev->power = 0x24; + i2o_block_device_unlock(dev->i2o_dev, -1); - /* - * Now unclaim the device. - */ + if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ + operation = 0x21; + else + operation = 0x24; + + i2o_block_device_power(dev, operation); - if (i2o_release_device(dev->i2odev, &i2o_block_handler)) - printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n"); - - DEBUG("Unclaim\n"); - } return 0; } -/* - * Open the block device. +/** + * i2o_block_ioctl - Issue device specific ioctl calls. + * @cmd: ioctl command + * @arg: arg + * + * Handles ioctl request for the block device. + * + * Return 0 on success or negative error on failure. */ - -static int i2ob_open(struct inode *inode, struct file *file) +static int i2o_block_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct i2ob_device *dev = disk->private_data; + struct i2o_block_device *dev = disk->private_data; + void __user *argp = (void __user *)arg; - if(!dev->i2odev) - return -ENODEV; - - if(dev->refcnt++==0) - { - u32 msg[6]; - - DEBUG("Claim "); - if(i2o_claim_device(dev->i2odev, &i2o_block_handler)) - { - dev->refcnt--; - printk(KERN_INFO "I2O Block: Could not open device\n"); - return -EBUSY; - } - DEBUG("Claimed "); - /* - * Power up if needed - */ + /* Anyone capable of this syscall can do *real bad* things */ - if(dev->power > 0x1f) + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + switch (cmd) { + case HDIO_GETGEO: { - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid; - msg[4] = 0x02 << 24; - if(i2o_post_wait(dev->controller, msg, 20, 60) == 0) - dev->power = 0x02; + struct hd_geometry g; + i2o_block_biosparam(get_capacity(disk), + &g.cylinders, &g.heads, &g.sectors); + g.start = get_start_sect(inode->i_bdev); + return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; } - /* - * Mount the media if needed. Note that we don't use - * the lock bit. Since we have to issue a lock if it - * refuses a mount (quite possible) then we might as - * well just send two messages out. - */ - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_MMOUNT<<24|HOST_TID<<12|dev->tid; - msg[4] = -1; - msg[5] = 0; - DEBUG("Mount "); - i2o_post_wait(dev->controller, msg, 24, 2); - - /* - * Lock the media - */ - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_MLOCK<<24|HOST_TID<<12|dev->tid; - msg[4] = -1; - DEBUG("Lock "); - i2o_post_wait(dev->controller, msg, 20, 2); - DEBUG("Ready.\n"); - } - return 0; -} + case BLKI2OGRSTRAT: + return put_user(dev->rcache, (int __user *)arg); + case BLKI2OGWSTRAT: + return put_user(dev->wcache, (int __user *)arg); + case BLKI2OSRSTRAT: + if (arg < 0 || arg > CACHE_SMARTFETCH) + return -EINVAL; + dev->rcache = arg; + break; + case BLKI2OSWSTRAT: + if (arg != 0 + && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) + return -EINVAL; + dev->wcache = arg; + break; + } + return -ENOTTY; +}; -/* - * Issue a device query +/** + * i2o_block_media_changed - Have we seen a media change? + * @disk: gendisk which should be verified + * + * Verifies if the media has changed. + * + * Returns 1 if the media was changed or 0 otherwise. */ - -static int i2ob_query_device(struct i2ob_device *dev, int table, - int field, void *buf, int buflen) +static int i2o_block_media_changed(struct gendisk *disk) { - return i2o_query_scalar(dev->controller, dev->tid, - table, field, buf, buflen); -} + struct i2o_block_device *p = disk->private_data; + if (p->media_change_flag) { + p->media_change_flag = 0; + return 1; + } + return 0; +} -/* - * Install the I2O block device we found. +/** + * i2o_block_transfer - Transfer a request to/from the I2O controller + * @req: the request which should be transfered + * + * This function converts the request into a I2O message. The necessary + * DMA buffers are allocated and after everything is setup post the message + * to the I2O controller. No cleanup is done by this function. It is done + * on the interrupt side when the reply arrives. + * + * Return 0 on success or negative error code on failure. */ - -static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, int unit) +static int i2o_block_transfer(struct request *req) { - u64 size; - u32 blocksize; - u8 type; - u16 power; - u32 flags, status; - struct i2ob_device *dev=&i2ob_dev[unit]; - struct gendisk *disk; - request_queue_t *q; - int segments; - + struct i2o_block_device *dev = req->rq_disk->private_data; + struct i2o_controller *c = dev->i2o_dev->iop; + int tid = dev->i2o_dev->lct_data.tid; + struct i2o_message __iomem *msg; + void __iomem *mptr; + struct i2o_block_request *ireq = req->special; + struct scatterlist *sg; + int sgnum; + int i; + u32 m; + u32 tcntxt; + u32 sg_flags; + int rc; + + m = i2o_msg_get(c, &msg); + if (m == I2O_QUEUE_EMPTY) { + rc = -EBUSY; + goto exit; + } - /* - * For logging purposes... - */ - printk(KERN_INFO "i2ob: Installing tid %d device at unit %d\n", - d->lct_data.tid, unit); + tcntxt = i2o_cntxt_list_add(c, req); + if (!tcntxt) { + rc = -ENOMEM; + goto nop_msg; + } - /* - * If this is the first I2O block device found on this IOP, - * we need to initialize all the queue data structures - * before any I/O can be performed. If it fails, this - * device is useless. - */ - if(!i2ob_queues[c->unit]) { - if(i2ob_init_iop(c->unit)) - return 1; + if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) { + rc = -ENOMEM; + goto context_remove; } - q = i2ob_queues[c->unit]->req_queue; + /* Build the message based on the request. */ + writel(i2o_block_driver.context, &msg->u.s.icntxt); + writel(tcntxt, &msg->u.s.tcntxt); + writel(req->nr_sectors << 9, &msg->body[1]); - /* - * This will save one level of lookup/indirection in critical - * code so that we can directly get the queue ptr from the - * device instead of having to go the IOP data structure. - */ - dev->req_queue = q; + writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]); + writel(req->sector >> 23, &msg->body[3]); - /* - * Allocate a gendisk structure and initialize it - */ - disk = alloc_disk(16); - if (!disk) - return 1; + mptr = &msg->body[4]; - dev->gd = disk; - /* initialize gendik structure */ - disk->major = MAJOR_NR; - disk->first_minor = unit<<4; - disk->queue = q; - disk->fops = &i2ob_fops; - sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit); - disk->private_data = dev; + sg = ireq->sg_table; - /* - * Ask for the current media data. If that isn't supported - * then we ask for the device capacity data - */ - if(i2ob_query_device(dev, 0x0004, 1, &blocksize, 4) != 0 - || i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 ) - { - i2ob_query_device(dev, 0x0000, 3, &blocksize, 4); - i2ob_query_device(dev, 0x0000, 4, &size, 8); + if (rq_data_dir(req) == READ) { + writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + sg_flags = 0x10000000; + switch (dev->rcache) { + case CACHE_NULL: + writel(0, &msg->body[0]); + break; + case CACHE_PREFETCH: + writel(0x201F0008, &msg->body[0]); + break; + case CACHE_SMARTFETCH: + if (req->nr_sectors > 16) + writel(0x201F0008, &msg->body[0]); + else + writel(0x001F0000, &msg->body[0]); + break; + } + } else { + writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + sg_flags = 0x14000000; + switch (dev->wcache) { + case CACHE_NULL: + writel(0, &msg->body[0]); + break; + case CACHE_WRITETHROUGH: + writel(0x001F0008, &msg->body[0]); + break; + case CACHE_WRITEBACK: + writel(0x001F0010, &msg->body[0]); + break; + case CACHE_SMARTBACK: + if (req->nr_sectors > 16) + writel(0x001F0004, &msg->body[0]); + else + writel(0x001F0010, &msg->body[0]); + break; + case CACHE_SMARTTHROUGH: + if (req->nr_sectors > 16) + writel(0x001F0004, &msg->body[0]); + else + writel(0x001F0010, &msg->body[0]); + } } - - if(i2ob_query_device(dev, 0x0000, 2, &power, 2)!=0) - power = 0; - i2ob_query_device(dev, 0x0000, 5, &flags, 4); - i2ob_query_device(dev, 0x0000, 6, &status, 4); - set_capacity(disk, size>>9); - /* - * Max number of Scatter-Gather Elements - */ - - dev->power = power; /* Save power state in device proper */ - dev->flags = flags; - - segments = (d->controller->status_block->inbound_frame_size - 7) / 2; - - if(segments > 16) - segments = 16; - - dev->power = power; /* Save power state */ - dev->flags = flags; /* Keep the type info */ - - blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers - explode on 65536 or higher */ - blk_queue_max_phys_segments(q, segments); - blk_queue_max_hw_segments(q, segments); - - dev->rcache = CACHE_SMARTFETCH; - dev->wcache = CACHE_WRITETHROUGH; - - if(d->controller->battery == 0) - dev->wcache = CACHE_WRITETHROUGH; - - if(d->controller->promise) - dev->wcache = CACHE_WRITETHROUGH; - - if(d->controller->short_req) - { - blk_queue_max_sectors(q, 8); - blk_queue_max_phys_segments(q, 8); - blk_queue_max_hw_segments(q, 8); + for (i = sgnum; i > 0; i--) { + if (i == 1) + sg_flags |= 0x80000000; + writel(sg_flags | sg_dma_len(sg), mptr); + writel(sg_dma_address(sg), mptr + 4); + mptr += 8; + sg++; } - strcpy(d->dev_name, disk->disk_name); - strcpy(disk->devfs_name, disk->disk_name); - - printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n", - d->dev_name, dev->max_segments, dev->depth, dev->max_sectors<<9); + writel(I2O_MESSAGE_SIZE + (((unsigned long)mptr - + (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8, + &msg->u.head[0]); - i2ob_query_device(dev, 0x0000, 0, &type, 1); - - printk(KERN_INFO "%s: ", d->dev_name); - switch(type) - { - case 0: printk("Disk Storage");break; - case 4: printk("WORM");break; - case 5: printk("CD-ROM");break; - case 7: printk("Optical device");break; - default: - printk("Type %d", type); - } - if(status&(1<<10)) - printk("(RAID)"); - - if((flags^status)&(1<<4|1<<3)) /* Missing media or device */ - { - printk(KERN_INFO " Not loaded.\n"); - /* Device missing ? */ - if((flags^status)&(1<<4)) - return 1; - } - else - { - printk(": %dMB, %d byte sectors", - (int)(size>>20), blocksize); - } - if(status&(1<<0)) - { - u32 cachesize; - i2ob_query_device(dev, 0x0003, 0, &cachesize, 4); - cachesize>>=10; - if(cachesize>4095) - printk(", %dMb cache", cachesize>>10); - else - printk(", %dKb cache", cachesize); - } - printk(".\n"); - printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", - d->dev_name, dev->max_sectors); + i2o_msg_post(c, m); - /* - * Register for the events we're interested in and that the - * device actually supports. - */ + list_add_tail(&ireq->queue, &dev->open_queue); + dev->open_queue_depth++; - i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, - (I2OB_EVENT_MASK & d->lct_data.event_capabilities)); return 0; -} -/* - * Initialize IOP specific queue structures. This is called - * once for each IOP that has a block device sitting behind it. - */ -static int i2ob_init_iop(unsigned int unit) -{ - int i; - - i2ob_queues[unit] = (struct i2ob_iop_queue *) kmalloc(sizeof(struct i2ob_iop_queue), GFP_ATOMIC); - if(!i2ob_queues[unit]) - { - printk(KERN_WARNING "Could not allocate request queue for I2O block device!\n"); - return -1; - } - - for(i = 0; i< MAX_I2OB_DEPTH; i++) - { - i2ob_queues[unit]->request_queue[i].next = &i2ob_queues[unit]->request_queue[i+1]; - i2ob_queues[unit]->request_queue[i].num = i; - } - - /* Queue is MAX_I2OB + 1... */ - i2ob_queues[unit]->request_queue[i].next = NULL; - i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0]; - i2ob_queues[unit]->queue_depth = 0; - - i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED; - i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock); - if (!i2ob_queues[unit]->req_queue) { - kfree(i2ob_queues[unit]); - return -1; - } + context_remove: + i2o_cntxt_list_remove(c, req); - i2ob_queues[unit]->req_queue->queuedata = &i2ob_queues[unit]; + nop_msg: + i2o_msg_nop(c, m); - return 0; -} + exit: + return rc; +}; -/* - * Probe the I2O subsytem for block class devices +/** + * i2o_block_request_fn - request queue handling function + * q: request queue from which the request could be fetched + * + * Takes the next request from the queue, transfers it and if no error + * occurs dequeue it from the queue. On arrival of the reply the message + * will be processed further. If an error occurs requeue the request. */ -static void i2ob_scan(int bios) +static void i2o_block_request_fn(struct request_queue *q) { - int i; - int warned = 0; - - struct i2o_device *d, *b=NULL; - struct i2o_controller *c; - - for(i=0; i< MAX_I2O_CONTROLLERS; i++) - { - c=i2o_find_controller(i); - - if(c==NULL) - continue; + struct request *req; - /* - * The device list connected to the I2O Controller is doubly linked - * Here we traverse the end of the list , and start claiming devices - * from that end. This assures that within an I2O controller atleast - * the newly created volumes get claimed after the older ones, thus - * mapping to same major/minor (and hence device file name) after - * every reboot. - * The exception being: - * 1. If there was a TID reuse. - * 2. There was more than one I2O controller. - */ + while (!blk_queue_plugged(q)) { + req = elv_next_request(q); + if (!req) + break; - if(!bios) - { - for (d=c->devices;d!=NULL;d=d->next) - if(d->next == NULL) - b = d; - } - else - b = c->devices; + if (blk_fs_request(req)) { + struct i2o_block_delayed_request *dreq; + struct i2o_block_request *ireq = req->special; + unsigned int queue_depth; - while(b != NULL) - { - d=b; - if(bios) - b = b->next; - else - b = b->prev; + queue_depth = ireq->i2o_blk_dev->open_queue_depth; - if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE) - continue; + if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) + if (!i2o_block_transfer(req)) { + blkdev_dequeue_request(req); + continue; + } - if(d->lct_data.user_tid != 0xFFF) - continue; + if (queue_depth) + break; - if(bios) - { - if(d->lct_data.bios_info != 0x80) - continue; - printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid); - } - else - { - if(d->lct_data.bios_info == 0x80) - continue; /*Already claimed on pass 1 */ - } + /* stop the queue and retry later */ + dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC); + if (!dreq) + continue; - if(scan_unitqueue = q; + INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, + dreq); + + printk(KERN_INFO "block-osm: transfer error\n"); + if (!queue_delayed_work(i2o_block_driver.event_queue, + &dreq->work, + I2O_BLOCK_RETRY_TIME)) + kfree(dreq); + else { + blk_stop_queue(q); + break; } - } - i2o_unlock_controller(c); + } else + end_request(req, 0); } -} +}; + +/* I2O Block device operations definition */ +static struct block_device_operations i2o_block_fops = { + .owner = THIS_MODULE, + .open = i2o_block_open, + .release = i2o_block_release, + .ioctl = i2o_block_ioctl, + .media_changed = i2o_block_media_changed +}; -static void i2ob_probe(void) +/** + * i2o_block_device_alloc - Allocate memory for a I2O Block device + * + * Allocate memory for the i2o_block_device struct, gendisk and request + * queue and initialize them as far as no additional information is needed. + * + * Returns a pointer to the allocated I2O Block device on succes or a + * negative error code on failure. + */ +static struct i2o_block_device *i2o_block_device_alloc(void) { - /* - * Some overhead/redundancy involved here, while trying to - * claim the first boot volume encountered as /dev/i2o/hda - * everytime. All the i2o_controllers are searched and the - * first i2o block device marked as bootable is claimed - * If an I2O block device was booted off , the bios sets - * its bios_info field to 0x80, this what we search for. - * Assuming that the bootable volume is /dev/i2o/hda - * everytime will prevent any kernel panic while mounting - * root partition - */ + struct i2o_block_device *dev; + struct gendisk *gd; + struct request_queue *queue; + int rc; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + printk(KERN_ERR "block-osm: Insufficient memory to allocate " + "I2O Block disk.\n"); + rc = -ENOMEM; + goto exit; + } + memset(dev, 0, sizeof(*dev)); + + INIT_LIST_HEAD(&dev->open_queue); + spin_lock_init(&dev->lock); + dev->rcache = CACHE_PREFETCH; + dev->wcache = CACHE_WRITEBACK; + + /* allocate a gendisk with 16 partitions */ + gd = alloc_disk(16); + if (!gd) { + printk(KERN_ERR "block-osm: Insufficient memory to allocate " + "gendisk.\n"); + rc = -ENOMEM; + goto cleanup_dev; + } - printk(KERN_INFO "i2o_block: Checking for Boot device...\n"); - i2ob_scan(1); + /* initialize the request queue */ + queue = blk_init_queue(i2o_block_request_fn, &dev->lock); + if (!queue) { + printk(KERN_ERR "block-osm: Insufficient memory to allocate " + "request queue.\n"); + rc = -ENOMEM; + goto cleanup_queue; + } - /* - * Now the remainder. - */ - printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n"); - i2ob_scan(0); -} + blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + gd->major = I2O_MAJOR; + gd->queue = queue; + gd->fops = &i2o_block_fops; + gd->private_data = dev; -/* - * New device notification handler. Called whenever a new - * I2O block storage device is added to the system. - * - * Should we spin lock around this to keep multiple devs from - * getting updated at the same time? - * + dev->gd = gd; + + return dev; + + cleanup_queue: + put_disk(gd); + + cleanup_dev: + kfree(dev); + + exit: + return ERR_PTR(rc); +}; + +/** + * i2o_block_probe - verify if dev is a I2O Block device and install it + * @dev: device to verify if it is a I2O Block device + * + * We only verify if the user_tid of the device is 0xfff and then install + * the device. Otherwise it is used by some other device (e. g. RAID). + * + * Returns 0 on success or negative error code on failure. */ -void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) +static int i2o_block_probe(struct device *dev) { - struct i2ob_device *dev; - int unit = 0; - - printk(KERN_INFO "i2o_block: New device detected\n"); - printk(KERN_INFO " Controller %d Tid %d\n",c->unit, d->lct_data.tid); + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_block_device *i2o_blk_dev; + struct i2o_controller *c = i2o_dev->iop; + struct gendisk *gd; + struct request_queue *queue; + static int unit = 0; + int rc; + u64 size; + u32 blocksize; + u16 power; + u32 flags, status; + int segments; - /* Check for available space */ - if(i2ob_dev_count>=MAX_I2OB) - { - printk(KERN_ERR "i2o_block: No more devices allowed!\n"); - return; + /* skip devices which are used by IOP */ + if (i2o_dev->lct_data.user_tid != 0xfff) { + pr_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); + return -ENODEV; } - for(unit = 0; unit < MAX_I2OB; unit ++) - { - if(!i2ob_dev[unit].i2odev) - break; + + printk(KERN_INFO "block-osm: New device detected (TID: %03x)\n", + i2o_dev->lct_data.tid); + + if (i2o_device_claim(i2o_dev)) { + printk(KERN_WARNING "block-osm: Unable to claim device. " + "Installation aborted\n"); + rc = -EFAULT; + goto exit; } - if(i2o_claim_device(d, &i2o_block_handler)) - { - printk(KERN_INFO "i2o_block: Unable to claim device. Installation aborted\n"); - return; + i2o_blk_dev = i2o_block_device_alloc(); + if (IS_ERR(i2o_blk_dev)) { + printk(KERN_ERR "block-osm: could not alloc a new I2O block" + "device"); + rc = PTR_ERR(i2o_blk_dev); + goto claim_release; } - dev = &i2ob_dev[unit]; - dev->i2odev = d; - dev->controller = c; - dev->tid = d->lct_data.tid; - dev->unit = c->unit; + i2o_blk_dev->i2o_dev = i2o_dev; + dev_set_drvdata(dev, i2o_blk_dev); - if(i2ob_install_device(c,d,unit)) { - i2o_release_device(d, &i2o_block_handler); - printk(KERN_ERR "i2o_block: Could not install new device\n"); - } - else - { - i2o_release_device(d, &i2o_block_handler); - add_disk(dev->gd); - i2ob_dev_count++; - i2o_device_notify_on(d, &i2o_block_handler); - } + /* setup gendisk */ + gd = i2o_blk_dev->gd; + gd->first_minor = unit << 4; + sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); + sprintf(gd->devfs_name, "i2o/hd%c", 'a' + unit); + gd->driverfs_dev = &i2o_dev->device; - return; -} + /* setup request queue */ + queue = gd->queue; + queue->queuedata = i2o_blk_dev; -/* - * Deleted device notification handler. Called when a device we - * are talking to has been deleted by the user or some other - * mysterious fource outside the kernel. - */ -void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) -{ - int unit = 0; - unsigned long flags; - struct i2ob_device *dev; + blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS); + blk_queue_max_sectors(queue, I2O_MAX_SECTORS); - for(unit = 0; unit < MAX_I2OB; unit ++) - { - dev = &i2ob_dev[unit]; - if(dev->i2odev == d) - { - printk(KERN_INFO " /dev/%s: Controller %d Tid %d\n", - d->dev_name, c->unit, d->lct_data.tid); - break; - } - } + if (c->short_req) + segments = 8; + else { + i2o_status_block *sb; - printk(KERN_INFO "I2O Block Device Deleted\n"); + sb = c->status_block.virt; - if(unit >= MAX_I2OB) - { - printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n"); - return; + segments = (sb->inbound_frame_size - + sizeof(struct i2o_message) / 4 - 4) / 2; } - spin_lock_irqsave(dev->req_queue->queue_lock, flags); + blk_queue_max_hw_segments(queue, segments); - /* - * Need to do this...we somtimes get two events from the IRTOS - * in a row and that causes lots of problems. - */ - i2o_device_notify_off(d, &i2o_block_handler); + pr_debug("max sectors: %d\n", I2O_MAX_SECTORS); + pr_debug("phys segments: %d\n", I2O_MAX_SEGMENTS); + pr_debug("hw segments: %d\n", segments); - /* - * This will force errors when i2ob_get_queue() is called - * by the kenrel. + /* + * Ask for the current media data. If that isn't supported + * then we ask for the device capacity data */ - if(dev->gd) { - struct gendisk *gd = dev->gd; - gd->queue = NULL; - del_gendisk(gd); - put_disk(gd); - dev->gd = NULL; + if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0 + || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) { + i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4); + i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8); } - spin_unlock_irqrestore(dev->req_queue->queue_lock, flags); - dev->req_queue = NULL; - dev->i2odev = NULL; - dev->refcnt = 0; - dev->tid = 0; - - /* - * Do we need this? - * The media didn't really change...the device is just gone - */ - dev->media_change_flag = 1; + pr_debug("blocksize: %d\n", blocksize); - i2ob_dev_count--; -} + if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) + power = 0; + i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); + i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); + + set_capacity(gd, size >> 9); + + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); + + add_disk(gd); + + unit++; -/* - * Have we seen a media change ? - */ -static int i2ob_media_change(struct gendisk *disk) -{ - struct i2ob_device *p = disk->private_data; - if(p->media_change_flag) - { - p->media_change_flag=0; - return 1; - } return 0; -} -static int i2ob_revalidate(struct gendisk *disk) -{ - struct i2ob_device *p = disk->private_data; - return i2ob_install_device(p->controller, p->i2odev, p->index); -} + claim_release: + i2o_device_claim_release(i2o_dev); -/* - * Reboot notifier. This is called by i2o_core when the system - * shuts down. - */ -static void i2ob_reboot_event(void) -{ - int i; - - for(i=0;irefcnt!=0) - { - /* - * Flush the onboard cache - */ - u32 msg[5]; - int *query_done = &dev->done_flag; - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid; - msg[2] = i2ob_context|0x40000000; - msg[3] = (u32)query_done; - msg[4] = 60<<16; - - DEBUG("Flushing..."); - i2o_post_wait(dev->controller, msg, 20, 60); - - DEBUG("Unlocking..."); - /* - * Unlock the media - */ - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid; - msg[2] = i2ob_context|0x40000000; - msg[3] = (u32)query_done; - msg[4] = -1; - i2o_post_wait(dev->controller, msg, 20, 2); - - DEBUG("Unlocked.\n"); - } - } -} + exit: + return rc; +}; -static struct block_device_operations i2ob_fops = -{ - .owner = THIS_MODULE, - .open = i2ob_open, - .release = i2ob_release, - .ioctl = i2ob_ioctl, - .media_changed = i2ob_media_change, - .revalidate_disk= i2ob_revalidate, +/* Block OSM driver struct */ +static struct i2o_driver i2o_block_driver = { + .name = "block-osm", + .event = i2o_block_event, + .reply = i2o_block_reply, + .classes = i2o_block_class_id, + .driver = { + .probe = i2o_block_probe, + .remove = i2o_block_remove, + }, }; -/* - * And here should be modules and kernel interface - * (Just smiley confuses emacs :-) +/** + * i2o_block_init - Block OSM initialization function + * + * Allocate the slab and mempool for request structs, registers i2o_block + * block device and finally register the Block OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. */ - -static int i2o_block_init(void) +static int __init i2o_block_init(void) { - int i; + int rc; + int size; printk(KERN_INFO "I2O Block Storage OSM v0.9\n"); printk(KERN_INFO " (c) Copyright 1999-2001 Red Hat Software.\n"); - - /* - * Register the block device interfaces - */ - if (register_blkdev(MAJOR_NR, "i2o_block")) - return -EIO; - -#ifdef MODULE - printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR); -#endif - - /* - * Set up the queue - */ - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - i2ob_queues[i] = NULL; - /* - * Now fill in the boiler plate - */ - - for (i = 0; i < MAX_I2OB; i++) { - struct i2ob_device *dev = &i2ob_dev[i]; - dev->index = i; - dev->refcnt = 0; - dev->flags = 0; - dev->controller = NULL; - dev->i2odev = NULL; - dev->tid = 0; - dev->head = NULL; - dev->tail = NULL; - dev->depth = MAX_I2OB_DEPTH; - dev->max_sectors = 2; - dev->gd = NULL; + /* Allocate request mempool and slab */ + size = sizeof(struct i2o_block_request); + i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0, + SLAB_HWCACHE_ALIGN, NULL, + NULL); + if (!i2o_blk_req_pool.slab) { + printk(KERN_ERR "block-osm: can't init request slab\n"); + rc = -ENOMEM; + goto exit; } - - /* - * Register the OSM handler as we will need this to probe for - * drives, geometry and other goodies. - */ - if(i2o_install_handler(&i2o_block_handler)<0) - { - unregister_blkdev(MAJOR_NR, "i2o_block"); - printk(KERN_ERR "i2o_block: unable to register OSM.\n"); - return -EINVAL; + i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE, + mempool_alloc_slab, + mempool_free_slab, + i2o_blk_req_pool.slab); + if (!i2o_blk_req_pool.pool) { + printk(KERN_ERR "block-osm: can't init request mempool\n"); + rc = -ENOMEM; + goto free_slab; } - i2ob_context = i2o_block_handler.context; - /* - * Initialize event handling thread - */ - init_MUTEX_LOCKED(&i2ob_evt_sem); - evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND); - if(evt_pid < 0) - { - printk(KERN_ERR "i2o_block: Could not initialize event thread. Aborting\n"); - i2o_remove_handler(&i2o_block_handler); - return 0; + /* Register the block device interfaces */ + rc = register_blkdev(I2O_MAJOR, "i2o_block"); + if (rc) { + printk(KERN_ERR "block-osm: unable to register block device\n"); + goto free_mempool; } +#ifdef MODULE + printk(KERN_INFO "block-osm: registered device at major %d\n", + I2O_MAJOR); +#endif - i2ob_probe(); + /* Register Block OSM into I2O core */ + rc = i2o_driver_register(&i2o_block_driver); + if (rc) { + printk(KERN_ERR "block-osm: Could not register Block driver\n"); + goto unregister_blkdev; + } return 0; - unregister_blkdev(MAJOR_NR, "i2o_block"); - return -ENOMEM; -} + unregister_blkdev: + unregister_blkdev(I2O_MAJOR, "i2o_block"); + free_mempool: + mempool_destroy(i2o_blk_req_pool.pool); -static void i2o_block_exit(void) -{ - int i; - - if(evt_running) { - printk(KERN_INFO "Killing I2O block threads..."); - i = kill_proc(evt_pid, SIGKILL, 1); - if(!i) { - printk("waiting...\n"); - } - /* Be sure it died */ - wait_for_completion(&i2ob_thread_dead); - printk("done.\n"); - } + free_slab: + kmem_cache_destroy(i2o_blk_req_pool.slab); - /* - * Unregister for updates from any devices..otherwise we still - * get them and the core jumps to random memory :O - */ - if(i2ob_dev_count) { - struct i2o_device *d; - for(i = 0; i < MAX_I2OB; i++) - if((d = i2ob_dev[i].i2odev)) - i2ob_del_device(d->controller, d); - } - - /* - * We may get further callbacks for ourself. The i2o_core - * code handles this case reasonably sanely. The problem here - * is we shouldn't get them .. but a couple of cards feel - * obliged to tell us stuff we don't care about. - * - * This isnt ideal at all but will do for now. - */ - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - - /* - * Flush the OSM - */ + exit: + return rc; +}; - i2o_remove_handler(&i2o_block_handler); +/** + * i2o_block_exit - Block OSM exit function + * + * Unregisters Block OSM from I2O core, unregisters i2o_block block device + * and frees the mempool and slab. + */ +static void __exit i2o_block_exit(void) +{ + /* Unregister I2O Block OSM from I2O core */ + i2o_driver_unregister(&i2o_block_driver); - /* - * Return the block device - */ - if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0) - printk("i2o_block: cleanup_module failed\n"); + /* Unregister block device */ + unregister_blkdev(I2O_MAJOR, "i2o_block"); - /* - * release request queue - */ - for (i = 0; i < MAX_I2O_CONTROLLERS; i ++) - if(i2ob_queues[i]) { - blk_cleanup_queue(i2ob_queues[i]->req_queue); - kfree(i2ob_queues[i]); - } -} + /* Free request mempool and slab */ + mempool_destroy(i2o_blk_req_pool.pool); + kmem_cache_destroy(i2o_blk_req_pool.slab); +}; MODULE_AUTHOR("Red Hat"); MODULE_DESCRIPTION("I2O Block Device OSM"); diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index a28c4423b..34451e870 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -2,7 +2,7 @@ * I2O Configuration Interface Driver * * (C) Copyright 1999-2002 Red Hat - * + * * Written by Alan Cox, Building Number Three Ltd * * Fixes/additions: @@ -41,386 +41,172 @@ #include #include #include +#include +#include +#include #include #include -static int i2o_cfg_context = -1; -static void *page_buf; -static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED; -struct wait_queue *i2o_wait_queue; +extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); + +static spinlock_t i2o_config_lock; #define MODINC(x,y) ((x) = ((x) + 1) % (y)) struct sg_simple_element { - u32 flag_count; + u32 flag_count; u32 addr_bus; }; -struct i2o_cfg_info -{ - struct file* fp; +struct i2o_cfg_info { + struct file *fp; struct fasync_struct *fasync; struct i2o_evt_info event_q[I2O_EVT_Q_LEN]; - u16 q_in; // Queue head index - u16 q_out; // Queue tail index - u16 q_len; // Queue length - u16 q_lost; // Number of lost events - u32 q_id; // Event queue ID...used as tx_context - struct i2o_cfg_info *next; + u16 q_in; // Queue head index + u16 q_out; // Queue tail index + u16 q_len; // Queue length + u16 q_lost; // Number of lost events + ulong q_id; // Event queue ID...used as tx_context + struct i2o_cfg_info *next; }; static struct i2o_cfg_info *open_files = NULL; -static int i2o_cfg_info_id = 0; - -static int ioctl_getiops(unsigned long); -static int ioctl_gethrt(unsigned long); -static int ioctl_getlct(unsigned long); -static int ioctl_parms(unsigned long, unsigned int); -static int ioctl_html(unsigned long); -static int ioctl_swdl(unsigned long); -static int ioctl_swul(unsigned long); -static int ioctl_swdel(unsigned long); -static int ioctl_validate(unsigned long); -static int ioctl_evt_reg(unsigned long, struct file *); -static int ioctl_evt_get(unsigned long, struct file *); -static int ioctl_passthru(unsigned long); -static int cfg_fasync(int, struct file*, int); - -/* - * This is the callback for any message we have posted. The message itself - * will be returned to the message pool when we return from the IRQ - * - * This runs in irq context so be short and sweet. - */ -static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m) -{ - u32 *msg = (u32 *)m; - - if (msg[0] & MSG_FAIL) { - u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]); - - printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n"); - - /* Release the preserved msg frame by resubmitting it as a NOP */ - - preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0; - preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0; - preserved_msg[2] = 0; - i2o_post_message(c, msg[7]); - } - - if (msg[4] >> 24) // ReqStatus != SUCCESS - i2o_report_status(KERN_INFO,"i2o_config", msg); - - if(m->function == I2O_CMD_UTIL_EVT_REGISTER) - { - struct i2o_cfg_info *inf; - - for(inf = open_files; inf; inf = inf->next) - if(inf->q_id == msg[3]) - break; - - // - // If this is the case, it means that we're getting - // events for a file descriptor that's been close()'d - // w/o the user unregistering for events first. - // The code currently assumes that the user will - // take care of unregistering for events before closing - // a file. - // - // TODO: - // Should we track event registartion and deregister - // for events when a file is close()'d so this doesn't - // happen? That would get rid of the search through - // the linked list since file->private_data could point - // directly to the i2o_config_info data structure...but - // it would mean having all sorts of tables to track - // what each file is registered for...I think the - // current method is simpler. - DS - // - if(!inf) - return; - - inf->event_q[inf->q_in].id.iop = c->unit; - inf->event_q[inf->q_in].id.tid = m->target_tid; - inf->event_q[inf->q_in].id.evt_mask = msg[4]; - - // - // Data size = msg size - reply header - // - inf->event_q[inf->q_in].data_size = (m->size - 5) * 4; - if(inf->event_q[inf->q_in].data_size) - memcpy(inf->event_q[inf->q_in].evt_data, - (unsigned char *)(msg + 5), - inf->event_q[inf->q_in].data_size); - - spin_lock(&i2o_config_lock); - MODINC(inf->q_in, I2O_EVT_Q_LEN); - if(inf->q_len == I2O_EVT_Q_LEN) - { - MODINC(inf->q_out, I2O_EVT_Q_LEN); - inf->q_lost++; - } - else - { - // Keep I2OEVTGET on another CPU from touching this - inf->q_len++; - } - spin_unlock(&i2o_config_lock); - - -// printk(KERN_INFO "File %p w/id %d has %d events\n", -// inf->fp, inf->q_id, inf->q_len); - - kill_fasync(&inf->fasync, SIGIO, POLL_IN); - } - - return; -} +static ulong i2o_cfg_info_id = 0; /* * Each of these describes an i2o message handler. They are * multiplexed by the i2o_core code */ - -struct i2o_handler cfg_handler= -{ - i2o_cfg_reply, - NULL, - NULL, - NULL, - "Configuration", - 0, - 0xffffffff // All classes -}; - -static ssize_t cfg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) -{ - printk(KERN_INFO "i2o_config write not yet supported\n"); - return 0; -} - - -static ssize_t cfg_read(struct file *file, char __user *buf, size_t count, loff_t *ptr) -{ - return 0; -} +static struct i2o_driver i2o_config_driver = { + .name = "Config-OSM" +}; -/* - * IOCTL Handler - */ -static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, - unsigned long arg) +static int i2o_cfg_getiops(unsigned long arg) { - int ret; - - switch(cmd) - { - case I2OGETIOPS: - ret = ioctl_getiops(arg); - break; - - case I2OHRTGET: - ret = ioctl_gethrt(arg); - break; - - case I2OLCTGET: - ret = ioctl_getlct(arg); - break; - - case I2OPARMSET: - ret = ioctl_parms(arg, I2OPARMSET); - break; - - case I2OPARMGET: - ret = ioctl_parms(arg, I2OPARMGET); - break; - - case I2OSWDL: - ret = ioctl_swdl(arg); - break; - - case I2OSWUL: - ret = ioctl_swul(arg); - break; - - case I2OSWDEL: - ret = ioctl_swdel(arg); - break; - - case I2OVALIDATE: - ret = ioctl_validate(arg); - break; - - case I2OHTML: - ret = ioctl_html(arg); - break; - - case I2OEVTREG: - ret = ioctl_evt_reg(arg, fp); - break; + struct i2o_controller *c; + u8 __user *user_iop_table = (void __user *)arg; + u8 tmp[MAX_I2O_CONTROLLERS]; + int ret = 0; - case I2OEVTGET: - ret = ioctl_evt_get(arg, fp); - break; + memset(tmp, 0, MAX_I2O_CONTROLLERS); - case I2OPASSTHRU: - ret = ioctl_passthru(arg); - break; + list_for_each_entry(c, &i2o_controllers, list) + tmp[c->unit] = 1; - default: - ret = -EINVAL; - } + if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS)) + ret = -EFAULT; return ret; -} - -int ioctl_getiops(unsigned long arg) -{ - u8 __user *user_iop_table = (void __user *)arg; - struct i2o_controller *c = NULL; - int i; - u8 foo[MAX_I2O_CONTROLLERS]; - - if(!access_ok(VERIFY_WRITE, user_iop_table, MAX_I2O_CONTROLLERS)) - return -EFAULT; - - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - { - c = i2o_find_controller(i); - if(c) - { - foo[i] = 1; - if(pci_set_dma_mask(c->pdev, 0xffffffff)) - { - printk(KERN_WARNING "i2o_config : No suitable DMA available on controller %d\n", i); - i2o_unlock_controller(c); - continue; - } - - i2o_unlock_controller(c); - } - else - { - foo[i] = 0; - } - } - - __copy_to_user(user_iop_table, foo, MAX_I2O_CONTROLLERS); - return 0; -} +}; -int ioctl_gethrt(unsigned long arg) +static int i2o_cfg_gethrt(unsigned long arg) { struct i2o_controller *c; - struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; struct i2o_cmd_hrtlct kcmd; i2o_hrt *hrt; int len; u32 reslen; int ret = 0; - if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) return -EFAULT; - if(get_user(reslen, kcmd.reslen) < 0) + if (get_user(reslen, kcmd.reslen) < 0) return -EFAULT; - if(kcmd.resbuf == NULL) + if (kcmd.resbuf == NULL) return -EFAULT; - c = i2o_find_controller(kcmd.iop); - if(!c) + c = i2o_find_iop(kcmd.iop); + if (!c) return -ENXIO; - - hrt = (i2o_hrt *)c->hrt; - i2o_unlock_controller(c); + hrt = (i2o_hrt *) c->hrt.virt; len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); - + /* We did a get user...so assuming mem is ok...is this bad? */ put_user(len, kcmd.reslen); - if(len > reslen) - ret = -ENOBUFS; - if(copy_to_user(kcmd.resbuf, (void*)hrt, len)) + if (len > reslen) + ret = -ENOBUFS; + if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) ret = -EFAULT; return ret; -} +}; -int ioctl_getlct(unsigned long arg) +static int i2o_cfg_getlct(unsigned long arg) { struct i2o_controller *c; - struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; struct i2o_cmd_hrtlct kcmd; i2o_lct *lct; int len; int ret = 0; u32 reslen; - if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) return -EFAULT; - if(get_user(reslen, kcmd.reslen) < 0) + if (get_user(reslen, kcmd.reslen) < 0) return -EFAULT; - if(kcmd.resbuf == NULL) + if (kcmd.resbuf == NULL) return -EFAULT; - c = i2o_find_controller(kcmd.iop); - if(!c) + c = i2o_find_iop(kcmd.iop); + if (!c) return -ENXIO; - lct = (i2o_lct *)c->lct; - i2o_unlock_controller(c); + lct = (i2o_lct *) c->lct; len = (unsigned int)lct->table_size << 2; put_user(len, kcmd.reslen); - if(len > reslen) - ret = -ENOBUFS; - else if(copy_to_user(kcmd.resbuf, (void*)lct, len)) + if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, lct, len)) ret = -EFAULT; return ret; -} +}; -static int ioctl_parms(unsigned long arg, unsigned int type) +static int i2o_cfg_parms(unsigned long arg, unsigned int type) { int ret = 0; struct i2o_controller *c; - struct i2o_cmd_psetget __user *cmd = (void __user *)arg; + struct i2o_device *dev; + struct i2o_cmd_psetget __user *cmd = + (struct i2o_cmd_psetget __user *)arg; struct i2o_cmd_psetget kcmd; u32 reslen; u8 *ops; u8 *res; - int len; + int len = 0; - u32 i2o_cmd = (type == I2OPARMGET ? - I2O_CMD_UTIL_PARAMS_GET : - I2O_CMD_UTIL_PARAMS_SET); + u32 i2o_cmd = (type == I2OPARMGET ? + I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET); - if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget))) + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget))) return -EFAULT; - if(get_user(reslen, kcmd.reslen)) + if (get_user(reslen, kcmd.reslen)) return -EFAULT; - c = i2o_find_controller(kcmd.iop); - if(!c) + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + dev = i2o_iop_find_device(c, kcmd.tid); + if (!dev) return -ENXIO; - ops = (u8*)kmalloc(kcmd.oplen, GFP_KERNEL); - if(!ops) - { - i2o_unlock_controller(c); + ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL); + if (!ops) return -ENOMEM; - } - if(copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) - { - i2o_unlock_controller(c); + if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) { kfree(ops); return -EFAULT; } @@ -429,404 +215,316 @@ static int ioctl_parms(unsigned long arg, unsigned int type) * It's possible to have a _very_ large table * and that the user asks for all of it at once... */ - res = (u8*)kmalloc(65536, GFP_KERNEL); - if(!res) - { - i2o_unlock_controller(c); + res = (u8 *) kmalloc(65536, GFP_KERNEL); + if (!res) { kfree(ops); return -ENOMEM; } - len = i2o_issue_params(i2o_cmd, c, kcmd.tid, - ops, kcmd.oplen, res, 65536); - i2o_unlock_controller(c); + len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536); kfree(ops); - + if (len < 0) { kfree(res); return -EAGAIN; } put_user(len, kcmd.reslen); - if(len > reslen) + if (len > reslen) ret = -ENOBUFS; - else if(copy_to_user(kcmd.resbuf, res, len)) + else if (copy_to_user(kcmd.resbuf, res, len)) ret = -EFAULT; kfree(res); return ret; -} - -int ioctl_html(unsigned long arg) -{ - struct i2o_html __user *cmd = (void __user *)arg; - struct i2o_html kcmd; - struct i2o_controller *c; - u8 *res = NULL; - void *query = NULL; - dma_addr_t query_phys, res_phys; - int ret = 0; - int token; - u32 len; - u32 reslen; - u32 msg[MSG_FRAME_SIZE]; - - if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_html))) - { - printk(KERN_INFO "i2o_config: can't copy html cmd\n"); - return -EFAULT; - } - - if(get_user(reslen, kcmd.reslen) < 0) - { - printk(KERN_INFO "i2o_config: can't copy html reslen\n"); - return -EFAULT; - } - - if(!kcmd.resbuf) - { - printk(KERN_INFO "i2o_config: NULL html buffer\n"); - return -EFAULT; - } - - c = i2o_find_controller(kcmd.iop); - if(!c) - return -ENXIO; - - if(kcmd.qlen) /* Check for post data */ - { - query = pci_alloc_consistent(c->pdev, kcmd.qlen, &query_phys); - if(!query) - { - i2o_unlock_controller(c); - return -ENOMEM; - } - if(copy_from_user(query, kcmd.qbuf, kcmd.qlen)) - { - i2o_unlock_controller(c); - printk(KERN_INFO "i2o_config: could not get query\n"); - pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys); - return -EFAULT; - } - } - - res = pci_alloc_consistent(c->pdev, 65536, &res_phys); - if(!res) - { - i2o_unlock_controller(c); - pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys); - return -ENOMEM; - } - - msg[1] = (I2O_CMD_UTIL_CONFIG_DIALOG << 24)|HOST_TID<<12|kcmd.tid; - msg[2] = i2o_cfg_context; - msg[3] = 0; - msg[4] = kcmd.page; - msg[5] = 0xD0000000|65536; - msg[6] = res_phys; - if(!kcmd.qlen) /* Check for post data */ - msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5; - else - { - msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5; - msg[5] = 0x50000000|65536; - msg[7] = 0xD4000000|(kcmd.qlen); - msg[8] = query_phys; - } - /* - Wait for a considerable time till the Controller - does its job before timing out. The controller might - take more time to process this request if there are - many devices connected to it. - */ - token = i2o_post_wait_mem(c, msg, 9*4, 400, query, res, query_phys, res_phys, kcmd.qlen, 65536); - if(token < 0) - { - printk(KERN_DEBUG "token = %#10x\n", token); - i2o_unlock_controller(c); - - if(token != -ETIMEDOUT) - { - pci_free_consistent(c->pdev, 65536, res, res_phys); - if(kcmd.qlen) - pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys); - } - return token; - } - i2o_unlock_controller(c); - - len = strnlen(res, 65536); - put_user(len, kcmd.reslen); - if(len > reslen) - ret = -ENOMEM; - if(copy_to_user(kcmd.resbuf, res, len)) - ret = -EFAULT; - - pci_free_consistent(c->pdev, 65536, res, res_phys); - if(kcmd.qlen) - pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys); +}; - return ret; -} - -int ioctl_swdl(unsigned long arg) +static int i2o_cfg_swdl(unsigned long arg) { struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (void __user *)arg; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; - unsigned char *buffer; - u32 msg[9]; + struct i2o_dma buffer; + struct i2o_message __iomem *msg; + u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; - dma_addr_t buffer_phys; - if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) return -EFAULT; - if(get_user(swlen, kxfer.swlen) < 0) + if (get_user(swlen, kxfer.swlen) < 0) return -EFAULT; - if(get_user(maxfrag, kxfer.maxfrag) < 0) + if (get_user(maxfrag, kxfer.maxfrag) < 0) return -EFAULT; - if(get_user(curfrag, kxfer.curfrag) < 0) + if (get_user(curfrag, kxfer.curfrag) < 0) return -EFAULT; - if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192; + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; - if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) + if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) return -EFAULT; - - c = i2o_find_controller(kxfer.iop); - if(!c) + + c = i2o_find_iop(kxfer.iop); + if (!c) return -ENXIO; - buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys); - if (buffer==NULL) - { - i2o_unlock_controller(c); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { + i2o_msg_nop(c, m); return -ENOMEM; } - __copy_from_user(buffer, kxfer.buf, fragsize); - - msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7; - msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2]= (u32)cfg_handler.context; - msg[3]= 0; - msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) | - (((u32)maxfrag)<<8) | (((u32)curfrag)); - msg[5]= swlen; - msg[6]= kxfer.sw_id; - msg[7]= (0xD0000000 | fragsize); - msg[8]= buffer_phys; - -// printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0); - - i2o_unlock_controller(c); - if(status != -ETIMEDOUT) - pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys); - - if (status != I2O_POST_WAIT_OK) - { + + __copy_from_user(buffer.virt, kxfer.buf, fragsize); + + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) | + (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); + writel(0xD0000000 | fragsize, &msg->body[3]); + writel(buffer.phys, &msg->body[4]); + +// printk(KERN_INFO "i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + if (status != I2O_POST_WAIT_OK) { // it fails if you try and send frags out of order // and for some yet unknown reasons too - printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status); + printk(KERN_INFO + "i2o_config: swdl failed, DetailedStatus = %d\n", + status); return status; } return 0; -} +}; -int ioctl_swul(unsigned long arg) +static int i2o_cfg_swul(unsigned long arg) { struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (void __user *)arg; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; - unsigned char *buffer; - u32 msg[9]; + struct i2o_dma buffer; + struct i2o_message __iomem *msg; + u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; - dma_addr_t buffer_phys; - - if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - return -EFAULT; - - if(get_user(swlen, kxfer.swlen) < 0) - return -EFAULT; - - if(get_user(maxfrag, kxfer.maxfrag) < 0) - return -EFAULT; - - if(get_user(curfrag, kxfer.curfrag) < 0) - return -EFAULT; - - if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192; - - if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize)) - return -EFAULT; - - c = i2o_find_controller(kxfer.iop); - if(!c) + int ret = 0; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + goto return_fault; + + if (get_user(swlen, kxfer.swlen) < 0) + goto return_fault; + + if (get_user(maxfrag, kxfer.maxfrag) < 0) + goto return_fault; + + if (get_user(curfrag, kxfer.curfrag) < 0) + goto return_fault; + + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; + + if (!kxfer.buf) + goto return_fault; + + c = i2o_find_iop(kxfer.iop); + if (!c) return -ENXIO; - - buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys); - if (buffer==NULL) - { - i2o_unlock_controller(c); + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { + i2o_msg_nop(c, m); return -ENOMEM; } - - msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7; - msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2]= (u32)cfg_handler.context; - msg[3]= 0; - msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag; - msg[5]= swlen; - msg[6]= kxfer.sw_id; - msg[7]= (0xD0000000 | fragsize); - msg[8]= buffer_phys; - -// printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0); - i2o_unlock_controller(c); - - if (status != I2O_POST_WAIT_OK) - { - if(status != -ETIMEDOUT) - pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys); - printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status); + + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((u32) kxfer.flags << 24 | (u32) kxfer. + sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag, + &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); + writel(0xD0000000 | fragsize, &msg->body[3]); + writel(buffer.phys, &msg->body[4]); + +// printk(KERN_INFO "i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + + if (status != I2O_POST_WAIT_OK) { + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + printk(KERN_INFO + "i2o_config: swul failed, DetailedStatus = %d\n", + status); return status; } - - __copy_to_user(kxfer.buf, buffer, fragsize); - pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys); - - return 0; -} -int ioctl_swdel(unsigned long arg) + if (copy_to_user(kxfer.buf, buffer.virt, fragsize)) + ret = -EFAULT; + + i2o_dma_free(&c->pdev->dev, &buffer); + +return_ret: + return ret; +return_fault: + ret = -EFAULT; + goto return_ret; +}; + +static int i2o_cfg_swdel(unsigned long arg) { struct i2o_controller *c; struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (void __user *)arg; - u32 msg[7]; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + struct i2o_message __iomem *msg; + u32 m; unsigned int swlen; int token; - + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) return -EFAULT; - + if (get_user(swlen, kxfer.swlen) < 0) return -EFAULT; - - c = i2o_find_controller(kxfer.iop); + + c = i2o_find_iop(kxfer.iop); if (!c) return -ENXIO; - msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; - msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2] = (u32)i2o_cfg_context; - msg[3] = 0; - msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16; - msg[5] = swlen; - msg[6] = kxfer.sw_id; - - token = i2o_post_wait(c, msg, sizeof(msg), 10); - i2o_unlock_controller(c); - - if (token != I2O_POST_WAIT_OK) - { - printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16, + &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); + + token = i2o_msg_post_wait(c, m, 10); + + if (token != I2O_POST_WAIT_OK) { + printk(KERN_INFO + "i2o_config: swdel failed, DetailedStatus = %d\n", + token); return -ETIMEDOUT; } - + return 0; -} +}; -int ioctl_validate(unsigned long arg) +static int i2o_cfg_validate(unsigned long arg) { - int token; - int iop = (int)arg; - u32 msg[4]; - struct i2o_controller *c; - - c=i2o_find_controller(iop); - if (!c) - return -ENXIO; - - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_CONFIG_VALIDATE<<24 | HOST_TID<<12 | iop; - msg[2] = (u32)i2o_cfg_context; - msg[3] = 0; - - token = i2o_post_wait(c, msg, sizeof(msg), 10); - i2o_unlock_controller(c); - - if (token != I2O_POST_WAIT_OK) - { - printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n", - token); - return -ETIMEDOUT; - } - - return 0; -} - -static int ioctl_evt_reg(unsigned long arg, struct file *fp) + int token; + int iop = (int)arg; + struct i2o_message __iomem *msg; + u32 m; + struct i2o_controller *c; + + c = i2o_find_iop(iop); + if (!c) + return -ENXIO; + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; + + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + + token = i2o_msg_post_wait(c, m, 10); + + if (token != I2O_POST_WAIT_OK) { + printk(KERN_INFO "Can't validate configuration, ErrorStatus = " + "%d\n", token); + return -ETIMEDOUT; + } + + return 0; +}; + +static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) { - u32 msg[5]; - struct i2o_evt_id __user *pdesc = (void __user *)arg; + struct i2o_message __iomem *msg; + u32 m; + struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; struct i2o_evt_id kdesc; - struct i2o_controller *iop; + struct i2o_controller *c; struct i2o_device *d; if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id))) return -EFAULT; /* IOP exists? */ - iop = i2o_find_controller(kdesc.iop); - if(!iop) + c = i2o_find_iop(kdesc.iop); + if (!c) return -ENXIO; - i2o_unlock_controller(iop); /* Device exists? */ - for(d = iop->devices; d; d = d->next) - if(d->lct_data.tid == kdesc.tid) - break; - - if(!d) + d = i2o_iop_find_device(c, kdesc.tid); + if (!d) return -ENODEV; - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid; - msg[2] = (u32)i2o_cfg_context; - msg[3] = (u32)fp->private_data; - msg[4] = kdesc.evt_mask; + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; - i2o_post_this(iop, msg, 20); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]); + writel(kdesc.evt_mask, &msg->body[0]); + + i2o_msg_post(c, m); return 0; -} +} -static int ioctl_evt_get(unsigned long arg, struct file *fp) +static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) { - u32 id = (u32)fp->private_data; struct i2o_cfg_info *p = NULL; - struct i2o_evt_get __user *uget = (void __user *)arg; + struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg; struct i2o_evt_get kget; unsigned long flags; - for(p = open_files; p; p = p->next) - if(p->q_id == id) + for (p = open_files; p; p = p->next) + if (p->q_id == (ulong) fp->private_data) break; - if(!p->q_len) - { + if (!p->q_len) return -ENOENT; - return 0; - } memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info)); MODINC(p->q_out, I2O_EVT_Q_LEN); @@ -836,16 +534,236 @@ static int ioctl_evt_get(unsigned long arg, struct file *fp) kget.lost = p->q_lost; spin_unlock_irqrestore(&i2o_config_lock, flags); - if(copy_to_user(uget, &kget, sizeof(struct i2o_evt_get))) + if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get))) return -EFAULT; return 0; } -static int ioctl_passthru(unsigned long arg) +#ifdef CONFIG_COMPAT +static int i2o_cfg_passthru32(unsigned fd, unsigned cmnd, unsigned long arg, + struct file *file) { - struct i2o_cmd_passthru __user *cmd = (void __user *) arg; + struct i2o_cmd_passthru32 __user *cmd; + struct i2o_controller *c; + u32 __user *user_msg; + u32 *reply = NULL; + u32 __user *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + struct i2o_dma sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + u32 i = 0; + i2o_status_block *sb; + struct i2o_message *msg; + u32 m; + unsigned int iop; + + cmd = (struct i2o_cmd_passthru32 __user *)arg; + + if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg)) + return -EFAULT; + + user_msg = compat_ptr(i); + + c = i2o_find_iop(iop); + if (!c) { + pr_debug("controller %d not found\n", iop); + return -ENXIO; + } + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) { + printk(KERN_WARNING "unable to get size!\n"); + return -EFAULT; + } + size = size >> 16; + + if (size > sb->inbound_frame_size) { + pr_debug("size of message > inbound_frame_size"); + return -EFAULT; + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes + + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) { + printk(KERN_WARNING "unable to copy user message\n"); + return -EFAULT; + } + i2o_dump_message(msg); + + if (get_user(reply_size, &user_reply[0]) < 0) + return -EFAULT; + + reply_size >>= 16; + reply_size <<= 2; + + reply = kmalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); + return -ENOMEM; + } + memset(reply, 0, reply_size); + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; + + writel(i2o_config_driver.context, &msg->u.s.icntxt); + writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { + struct sg_simple_element *sg; + + if (sg_offset * 4 >= size) { + rcode = -EFAULT; + goto cleanup; + } + // TODO 64bit fix + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + kfree(reply); + return -EINVAL; + } + + for (i = 0; i < sg_count; i++) { + int sg_size; + struct i2o_dma *p; + + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); + rcode = -EINVAL; + goto cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[i]); + /* Allocate memory for the transfer */ + if (i2o_dma_alloc + (&c->pdev->dev, p, sg_size, + PCI_DMA_BIDIRECTIONAL)) { + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); + rcode = -ENOMEM; + goto cleanup; + } + /* Copy in the user's SG buffer if necessary */ + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { + // TODO 64bit fix + if (copy_from_user + (p->virt, (void __user *)(unsigned long)sg[i].addr_bus, + sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); + rcode = -EFAULT; + goto cleanup; + } + } + //TODO 64bit fix + sg[i].addr_bus = (u32) p->phys; + } + } + + rcode = i2o_msg_post_wait(c, m, 60); + if (rcode) + goto cleanup; + + if (sg_offset) { + u32 msg[128]; + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element *sg; + int sg_size; + printk(KERN_INFO "sg_offset\n"); + + // re-acquire the original message to handle correctly the sg copy operation + memset(&msg, 0, MSG_FRAME_SIZE * 4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto cleanup; + } + size = size >> 16; + size *= 4; + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) { + rcode = -EFAULT; + goto cleanup; + } + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element *)(msg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user + ((void __user *)(u64) sg[j].addr_bus, + sg_list[j].virt, sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j].virt, + sg[j].addr_bus); + rcode = -EFAULT; + goto cleanup; + } + } + } + } + + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + printk(KERN_INFO "reply_size\n"); + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); + rcode = -EFAULT; + } + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); + rcode = -EFAULT; + } + } + + cleanup: + kfree(reply); + printk(KERN_INFO "rcode: %d\n", rcode); + return rcode; +} + +#else + +static int i2o_cfg_passthru(unsigned long arg) +{ + struct i2o_cmd_passthru __user *cmd = + (struct i2o_cmd_passthru __user *)arg; struct i2o_controller *c; - u32 msg[MSG_FRAME_SIZE]; u32 __user *user_msg; u32 *reply = NULL; u32 __user *user_reply = NULL; @@ -858,64 +776,88 @@ static int ioctl_passthru(unsigned long arg) int sg_index = 0; u32 i = 0; void *p = NULL; + i2o_status_block *sb; + struct i2o_message __iomem *msg; + u32 m; unsigned int iop; if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) return -EFAULT; - c = i2o_find_controller(iop); - if (!c) - return -ENXIO; + c = i2o_find_iop(iop); + if (!c) { + pr_debug("controller %d not found\n", iop); + return -ENXIO; + } + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - memset(&msg, 0, MSG_FRAME_SIZE*4); - if(get_user(size, &user_msg[0])) + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) return -EFAULT; - size = size>>16; + size = size >> 16; - user_reply = &user_msg[size]; - if(size > MSG_FRAME_SIZE) + if (size > sb->inbound_frame_size) { + pr_debug("size of message > inbound_frame_size"); return -EFAULT; - size *= 4; // Convert to bytes + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes /* Copy in the user's I2O command */ - if(copy_from_user(msg, user_msg, size)) + if (copy_from_user(msg, user_msg, size)) return -EFAULT; - if(get_user(reply_size, &user_reply[0]) < 0) + + if (get_user(reply_size, &user_reply[0]) < 0) return -EFAULT; - reply_size = reply_size>>16; - reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); - if(!reply) { - printk(KERN_WARNING"%s: Could not allocate reply buffer\n",c->name); + reply_size >>= 16; + reply_size <<= 2; + + reply = kmalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); return -ENOMEM; } - memset(reply, 0, REPLY_FRAME_SIZE*4); - sg_offset = (msg[0]>>4)&0x0f; - msg[2] = (u32)i2o_cfg_context; - msg[3] = (u32)reply; + memset(reply, 0, reply_size); + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; - memset(sg_list,0, sizeof(sg_list[0])*SG_TABLESIZE); - if(sg_offset) { + writel(i2o_config_driver.context, &msg->u.s.icntxt); + writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { struct sg_simple_element *sg; - if(sg_offset * 4 >= size) { + if (sg_offset * 4 >= size) { rcode = -EFAULT; goto cleanup; } // TODO 64bit fix - sg = (struct sg_simple_element*) (msg+sg_offset); - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); if (sg_count > SG_TABLESIZE) { - printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", c->name,sg_count); - kfree (reply); + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + kfree(reply); return -EINVAL; } - for(i = 0; i < sg_count; i++) { + for (i = 0; i < sg_count; i++) { int sg_size; - if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) { - printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",c->name,i, sg[i].flag_count); + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); rcode = -EINVAL; goto cleanup; } @@ -923,61 +865,78 @@ static int ioctl_passthru(unsigned long arg) /* Allocate memory for the transfer */ p = kmalloc(sg_size, GFP_KERNEL); if (!p) { - printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name,sg_size,i,sg_count); + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); rcode = -ENOMEM; goto cleanup; } - sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. + sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. /* Copy in the user's SG buffer if necessary */ - if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { // TODO 64bit fix - if (copy_from_user(p,(void __user *)sg[i].addr_bus, sg_size)) { - printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",c->name,i); + if (copy_from_user + (p, (void __user *)sg[i].addr_bus, + sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); rcode = -EFAULT; goto cleanup; } } //TODO 64bit fix - sg[i].addr_bus = (u32)virt_to_bus(p); + sg[i].addr_bus = virt_to_bus(p); } } - rcode = i2o_post_wait(c, msg, size, 60); - if(rcode) + rcode = i2o_msg_post_wait(c, m, 60); + if (rcode) goto cleanup; - if(sg_offset) { + if (sg_offset) { + u32 msg[128]; /* Copy back the Scatter Gather buffers back to user space */ u32 j; // TODO 64bit fix - struct sg_simple_element* sg; + struct sg_simple_element *sg; int sg_size; + printk(KERN_INFO "sg_offset\n"); // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MSG_FRAME_SIZE*4); + memset(&msg, 0, MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; goto cleanup; } - size = size>>16; + size = size >> 16; size *= 4; /* Copy in the user's I2O command */ - if (copy_from_user (msg, user_msg, size)) { + if (copy_from_user(msg, user_msg, size)) { rcode = -EFAULT; goto cleanup; } - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); - // TODO 64bit fix - sg = (struct sg_simple_element*)(msg + sg_offset); + // TODO 64bit fix + sg = (struct sg_simple_element *)(msg + sg_offset); for (j = 0; j < sg_count; j++) { /* Copy out the SG list to user's buffer if necessary */ - if (!(sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { sg_size = sg[j].flag_count & 0xffffff; // TODO 64bit fix - if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) { - printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",c->name, sg_list[j], sg[j].addr_bus); + if (copy_to_user + ((void __user *)sg[j].addr_bus, sg_list[j], + sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j], + sg[j].addr_bus); rcode = -EFAULT; goto cleanup; } @@ -986,37 +945,109 @@ static int ioctl_passthru(unsigned long arg) } /* Copy back the reply to user space */ - if (reply_size) { + if (reply_size) { // we wrote our own values for context - now restore the user supplied ones - if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) { - printk(KERN_WARNING"%s: Could not copy message context FROM user\n",c->name); + printk(KERN_INFO "reply_size\n"); + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); rcode = -EFAULT; } - if(copy_to_user(user_reply, reply, reply_size)) { - printk(KERN_WARNING"%s: Could not copy reply TO user\n",c->name); + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); rcode = -EFAULT; } } -cleanup: + cleanup: kfree(reply); - i2o_unlock_controller(c); return rcode; } +#endif + +/* + * IOCTL Handler + */ +static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, + unsigned long arg) +{ + int ret; + + switch (cmd) { + case I2OGETIOPS: + ret = i2o_cfg_getiops(arg); + break; + + case I2OHRTGET: + ret = i2o_cfg_gethrt(arg); + break; + + case I2OLCTGET: + ret = i2o_cfg_getlct(arg); + break; + + case I2OPARMSET: + ret = i2o_cfg_parms(arg, I2OPARMSET); + break; + + case I2OPARMGET: + ret = i2o_cfg_parms(arg, I2OPARMGET); + break; + + case I2OSWDL: + ret = i2o_cfg_swdl(arg); + break; + + case I2OSWUL: + ret = i2o_cfg_swul(arg); + break; + + case I2OSWDEL: + ret = i2o_cfg_swdel(arg); + break; + + case I2OVALIDATE: + ret = i2o_cfg_validate(arg); + break; + + case I2OEVTREG: + ret = i2o_cfg_evt_reg(arg, fp); + break; + + case I2OEVTGET: + ret = i2o_cfg_evt_get(arg, fp); + break; + +#ifndef CONFIG_COMPAT + case I2OPASSTHRU: + ret = i2o_cfg_passthru(arg); + break; +#endif + + default: + pr_debug("i2o_config: unknown ioctl called!\n"); + ret = -EINVAL; + } + + return ret; +} static int cfg_open(struct inode *inode, struct file *file) { - struct i2o_cfg_info *tmp = - (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL); + struct i2o_cfg_info *tmp = + (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), + GFP_KERNEL); unsigned long flags; - if(!tmp) + if (!tmp) return -ENOMEM; - file->private_data = (void*)(i2o_cfg_info_id++); + file->private_data = (void *)(i2o_cfg_info_id++); tmp->fp = file; tmp->fasync = NULL; - tmp->q_id = (u32)file->private_data; + tmp->q_id = (ulong) file->private_data; tmp->q_len = 0; tmp->q_in = 0; tmp->q_out = 0; @@ -1026,13 +1057,28 @@ static int cfg_open(struct inode *inode, struct file *file) spin_lock_irqsave(&i2o_config_lock, flags); open_files = tmp; spin_unlock_irqrestore(&i2o_config_lock, flags); - + return 0; } +static int cfg_fasync(int fd, struct file *fp, int on) +{ + ulong id = (ulong) fp->private_data; + struct i2o_cfg_info *p; + + for (p = open_files; p; p = p->next) + if (p->q_id == id) + break; + + if (!p) + return -EBADF; + + return fasync_helper(fd, fp, on, &p->fasync); +} + static int cfg_release(struct inode *inode, struct file *file) { - u32 id = (u32)file->private_data; + ulong id = (ulong) file->private_data; struct i2o_cfg_info *p1, *p2; unsigned long flags; @@ -1040,14 +1086,12 @@ static int cfg_release(struct inode *inode, struct file *file) p1 = p2 = NULL; spin_lock_irqsave(&i2o_config_lock, flags); - for(p1 = open_files; p1; ) - { - if(p1->q_id == id) - { + for (p1 = open_files; p1;) { + if (p1->q_id == id) { - if(p1->fasync) + if (p1->fasync) cfg_fasync(-1, file, 0); - if(p2) + if (p2) p2->next = p1->next; else open_files = p1->next; @@ -1064,83 +1108,57 @@ static int cfg_release(struct inode *inode, struct file *file) return 0; } -static int cfg_fasync(int fd, struct file *fp, int on) -{ - u32 id = (u32)fp->private_data; - struct i2o_cfg_info *p; - - for(p = open_files; p; p = p->next) - if(p->q_id == id) - break; - - if(!p) - return -EBADF; - - return fasync_helper(fd, fp, on, &p->fasync); -} - -static struct file_operations config_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = cfg_read, - .write = cfg_write, - .ioctl = cfg_ioctl, - .open = cfg_open, - .release = cfg_release, - .fasync = cfg_fasync, +static struct file_operations config_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = i2o_cfg_ioctl, + .open = cfg_open, + .release = cfg_release, + .fasync = cfg_fasync, }; static struct miscdevice i2o_miscdev = { I2O_MINOR, "i2octl", &config_fops -}; +}; static int __init i2o_config_init(void) { printk(KERN_INFO "I2O configuration manager v 0.04.\n"); printk(KERN_INFO " (C) Copyright 1999 Red Hat Software\n"); - - if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL) - { - printk(KERN_ERR "i2o_config: no memory for page buffer.\n"); - return -ENOBUFS; - } - if(misc_register(&i2o_miscdev) < 0) - { + + spin_lock_init(&i2o_config_lock); + + if (misc_register(&i2o_miscdev) < 0) { printk(KERN_ERR "i2o_config: can't register device.\n"); - kfree(page_buf); return -EBUSY; } /* - * Install our handler + * Install our handler */ - if(i2o_install_handler(&cfg_handler)<0) - { - kfree(page_buf); + if (i2o_driver_register(&i2o_config_driver)) { printk(KERN_ERR "i2o_config: handler register failed.\n"); misc_deregister(&i2o_miscdev); return -EBUSY; } - /* - * The low 16bits of the transaction context must match this - * for everything we post. Otherwise someone else gets our mail - */ - i2o_cfg_context = cfg_handler.context; +#ifdef CONFIG_COMPAT + register_ioctl32_conversion(I2OPASSTHRU32, i2o_cfg_passthru32); + register_ioctl32_conversion(I2OGETIOPS, (void *)sys_ioctl); +#endif return 0; } static void i2o_config_exit(void) { +#ifdef CONFIG_COMPAT + unregister_ioctl32_conversion(I2OPASSTHRU32); + unregister_ioctl32_conversion(I2OGETIOPS); +#endif misc_deregister(&i2o_miscdev); - - if(page_buf) - kfree(page_buf); - if(i2o_cfg_context != -1) - i2o_remove_handler(&cfg_handler); + i2o_driver_unregister(&i2o_config_driver); } - + MODULE_AUTHOR("Red Hat Software"); MODULE_DESCRIPTION("I2O Configuration"); MODULE_LICENSE("GPL"); diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index db85e21b9..e02ea8f42 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -1,39 +1,33 @@ /* - * procfs handler for Linux I2O subsystem + * procfs handler for Linux I2O subsystem * - * (c) Copyright 1999 Deepak Saxena - * - * Originally written by Deepak Saxena(deepak@plexity.net) + * (c) Copyright 1999 Deepak Saxena * - * 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. + * Originally written by Deepak Saxena(deepak@plexity.net) * - * This is an initial test release. The code is based on the design - * of the ide procfs system (drivers/block/ide-proc.c). Some code - * taken from i2o-core module by Alan Cox. + * 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. * - * DISCLAIMER: This code is still under development/test and may cause - * your system to behave unpredictably. Use at your own discretion. + * This is an initial test release. The code is based on the design of the + * ide procfs system (drivers/block/ide-proc.c). Some code taken from + * i2o-core module by Alan Cox. * - * LAN entries by Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), - * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) - * University of Helsinki, Department of Computer Science - */ - -/* - * set tabstop=3 - */ - -/* - * TODO List + * DISCLAIMER: This code is still under development/test and may cause + * your system to behave unpredictably. Use at your own discretion. * - * - Add support for any version 2.0 spec changes once 2.0 IRTOS is - * is available to test with - * - Clean up code to use official structure definitions + * + * Fixes/additions: + * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), + * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) + * University of Helsinki, Department of Computer Science + * LAN entries + * Markus Lidel + * Changes for new I2O API */ +#define I2O_MAX_MODULES 4 // FIXME! #define FMT_U64_HEX "0x%08x%08x" #define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) @@ -54,188 +48,198 @@ #include #include -#include "i2o_lan.h" - -/* - * Structure used to define /proc entries - */ -typedef struct _i2o_proc_entry_t -{ - char *name; /* entry name */ - mode_t mode; /* mode */ - read_proc_t *read_proc; /* read func */ - write_proc_t *write_proc; /* write func */ - struct file_operations *fops_proc; /* file operations func */ +/* Structure used to define /proc entries */ +typedef struct _i2o_proc_entry_t { + char *name; /* entry name */ + mode_t mode; /* mode */ + struct file_operations *fops; /* open function */ } i2o_proc_entry; -// #define DRIVERDEBUG - -static int i2o_seq_show_lct(struct seq_file *, void *); -static int i2o_seq_show_hrt(struct seq_file *, void *); -static int i2o_seq_show_status(struct seq_file *, void *); - -static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_driver_store(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_drivers_stored(char *, char **, off_t, int, int *, void *); - -static int i2o_proc_read_groups(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_phys_device(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_claimed(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_users(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_priv_msgs(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_authorized_users(char *, char **, off_t, int, int *, void *); - -static int i2o_proc_read_dev_name(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_dev_identity(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_ddm_identity(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_uinfo(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_sgl_limits(char *, char **, off_t, int, int *, void *); - -static int i2o_proc_read_sensors(char *, char **, off_t, int, int *, void *); - -static int print_serial_number(char *, int, u8 *, int); - -static int i2o_proc_create_entries(void *, i2o_proc_entry *, - struct proc_dir_entry *); -static void i2o_proc_remove_entries(i2o_proc_entry *, struct proc_dir_entry *); -static int i2o_proc_add_controller(struct i2o_controller *, - struct proc_dir_entry * ); -static void i2o_proc_remove_controller(struct i2o_controller *, - struct proc_dir_entry * ); -static void i2o_proc_add_device(struct i2o_device *, struct proc_dir_entry *); -static void i2o_proc_remove_device(struct i2o_device *); -static int create_i2o_procfs(void); -static int destroy_i2o_procfs(void); -static void i2o_proc_new_dev(struct i2o_controller *, struct i2o_device *); -static void i2o_proc_dev_del(struct i2o_controller *, struct i2o_device *); - -static int i2o_proc_read_lan_dev_info(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_mac_addr(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_mcast_addr(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_batch_control(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_operation(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_media_operation(char *, char **, off_t, int, - int *, void *); -static int i2o_proc_read_lan_alt_addr(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_tx_info(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_rx_info(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_hist_stats(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_eth_stats(char *, char **, off_t, int, - int *, void *); -static int i2o_proc_read_lan_tr_stats(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *, - void *); - +/* global I2O /proc/i2o entry */ static struct proc_dir_entry *i2o_proc_dir_root; -/* - * I2O OSM descriptor - */ -static struct i2o_handler i2o_proc_handler = -{ - NULL, - i2o_proc_new_dev, - i2o_proc_dev_del, - NULL, - "I2O procfs Layer", - 0, - 0xffffffff // All classes +/* proc OSM driver struct */ +static struct i2o_driver i2o_proc_driver = { + .name = "proc-osm", }; -static int i2o_seq_open_hrt(struct inode *inode, struct file *file) +static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) { - return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); -}; + int i; -struct file_operations i2o_seq_fops_hrt = { - .open = i2o_seq_open_hrt, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; + /* 19990419 -sralston + * The I2O v1.5 (and v2.0 so far) "official specification" + * got serial numbers WRONG! + * Apparently, and despite what Section 3.4.4 says and + * Figure 3-35 shows (pg 3-39 in the pdf doc), + * the convention / consensus seems to be: + * + First byte is SNFormat + * + Second byte is SNLen (but only if SNFormat==7 (?)) + * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format + */ + switch (serialno[0]) { + case I2O_SNFORMAT_BINARY: /* Binary */ + seq_printf(seq, "0x"); + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%02X", serialno[2 + i]); + } + break; -static int i2o_seq_open_lct(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_lct, PDE(inode)->data); -}; + case I2O_SNFORMAT_ASCII: /* ASCII */ + if (serialno[1] < ' ') { /* printable or SNLen? */ + /* sanity */ + max_len = + (max_len < serialno[1]) ? max_len : serialno[1]; + serialno[1 + max_len] = '\0'; -struct file_operations i2o_seq_fops_lct = { - .open = i2o_seq_open_lct, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; + /* just print it */ + seq_printf(seq, "%s", &serialno[2]); + } else { + /* print chars for specified length */ + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%c", serialno[2 + i]); + } + } + break; -static int i2o_seq_open_status(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_status, PDE(inode)->data); -}; + case I2O_SNFORMAT_UNICODE: /* UNICODE */ + seq_printf(seq, "UNICODE Format. Can't Display\n"); + break; -struct file_operations i2o_seq_fops_status = { - .open = i2o_seq_open_status, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; + case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ + seq_printf(seq, + "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X", + serialno[2], serialno[3], + serialno[4], serialno[5], serialno[6], serialno[7]); + break; -/* - * IOP specific entries...write field just in case someone - * ever wants one. - */ -static i2o_proc_entry generic_iop_entries[] = -{ - {"hrt", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_hrt}, - {"lct", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_lct}, - {"status", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_status}, - {"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL, NULL}, - {"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL, NULL}, - {"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL, NULL}, - {"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; + case I2O_SNFORMAT_WAN: /* WAN MAC Address */ + /* FIXME: Figure out what a WAN access address looks like?? */ + seq_printf(seq, "WAN Access Address"); + break; -/* - * Device specific entries - */ -static i2o_proc_entry generic_dev_entries[] = -{ - {"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL, NULL}, - {"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL, NULL}, - {"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL, NULL}, - {"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL, NULL}, - {"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL, NULL}, - {"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL, NULL}, - {"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL, NULL}, - {"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL, NULL}, - {"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL, NULL}, - {"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL, NULL}, - {"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; +/* plus new in v2.0 */ + case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ + /* FIXME: Figure out what a LAN-64 address really looks like?? */ + seq_printf(seq, + "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X", + serialno[8], serialno[9], + serialno[2], serialno[3], + serialno[4], serialno[5], serialno[6], serialno[7]); + break; + + case I2O_SNFORMAT_DDM: /* I2O DDM */ + seq_printf(seq, + "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", + *(u16 *) & serialno[2], + *(u16 *) & serialno[4], *(u16 *) & serialno[6]); + break; + + case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ + case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ + /* FIXME: Figure if this is even close?? */ + seq_printf(seq, + "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", + *(u32 *) & serialno[2], + *(u32 *) & serialno[6], + *(u32 *) & serialno[10], *(u32 *) & serialno[14]); + break; + + case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ + case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ + default: + seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]); + break; + } -/* - * Storage unit specific entries (SCSI Periph, BS) with device names + return 0; +} + +/** + * i2o_get_class_name - do i2o class name lookup + * @class: class number + * + * Return a descriptive string for an i2o class */ -static i2o_proc_entry rbs_dev_entries[] = +static const char *i2o_get_class_name(int class) { - {"dev_name", S_IFREG|S_IRUGO, i2o_proc_read_dev_name, NULL, NULL}, - {NULL, 0, NULL, NULL} -}; + int idx = 16; + static char *i2o_class_name[] = { + "Executive", + "Device Driver Module", + "Block Device", + "Tape Device", + "LAN Interface", + "WAN Interface", + "Fibre Channel Port", + "Fibre Channel Device", + "SCSI Device", + "ATE Port", + "ATE Device", + "Floppy Controller", + "Floppy Device", + "Secondary Bus Port", + "Peer Transport Agent", + "Peer Transport", + "Unknown" + }; + + switch (class & 0xfff) { + case I2O_CLASS_EXECUTIVE: + idx = 0; + break; + case I2O_CLASS_DDM: + idx = 1; + break; + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + idx = 2; + break; + case I2O_CLASS_SEQUENTIAL_STORAGE: + idx = 3; + break; + case I2O_CLASS_LAN: + idx = 4; + break; + case I2O_CLASS_WAN: + idx = 5; + break; + case I2O_CLASS_FIBRE_CHANNEL_PORT: + idx = 6; + break; + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + idx = 7; + break; + case I2O_CLASS_SCSI_PERIPHERAL: + idx = 8; + break; + case I2O_CLASS_ATE_PORT: + idx = 9; + break; + case I2O_CLASS_ATE_PERIPHERAL: + idx = 10; + break; + case I2O_CLASS_FLOPPY_CONTROLLER: + idx = 11; + break; + case I2O_CLASS_FLOPPY_DEVICE: + idx = 12; + break; + case I2O_CLASS_BUS_ADAPTER_PORT: + idx = 13; + break; + case I2O_CLASS_PEER_TRANSPORT_AGENT: + idx = 14; + break; + case I2O_CLASS_PEER_TRANSPORT: + idx = 15; + break; + } + + return i2o_class_name[idx]; +} #define SCSI_TABLE_SIZE 13 -static char *scsi_devices[] = -{ +static char *scsi_devices[] = { "Direct-Access Read/Write", "Sequential-Access Storage", "Printer", @@ -251,325 +255,285 @@ static char *scsi_devices[] = "Array Controller Device" }; -/* private */ - -/* - * Generic LAN specific entries - * - * Should groups with r/w entries have their own subdirectory? - * - */ -static i2o_proc_entry lan_entries[] = -{ - {"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL, NULL}, - {"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL, NULL}, - {"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR, - i2o_proc_read_lan_mcast_addr, NULL, NULL}, - {"lan_batch_ctrl", S_IFREG|S_IRUGO|S_IWUSR, - i2o_proc_read_lan_batch_control, NULL, NULL}, - {"lan_operation", S_IFREG|S_IRUGO, i2o_proc_read_lan_operation, NULL, NULL}, - {"lan_media_operation", S_IFREG|S_IRUGO, - i2o_proc_read_lan_media_operation, NULL, NULL}, - {"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL, NULL}, - {"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL, NULL}, - {"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL, NULL}, - - {"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - -/* - * Port specific LAN entries - * - */ -static i2o_proc_entry lan_eth_entries[] = -{ - {"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - -static i2o_proc_entry lan_tr_entries[] = -{ - {"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - -static i2o_proc_entry lan_fddi_entries[] = -{ - {"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL, NULL}, - {NULL, 0, NULL, NULL, NULL} -}; - - -static char *chtostr(u8 *chars, int n) +static char *chtostr(u8 * chars, int n) { char tmp[256]; tmp[0] = 0; - return strncat(tmp, (char *)chars, n); + return strncat(tmp, (char *)chars, n); } -static int i2o_report_query_status(char *buf, int block_status, char *group) +static int i2o_report_query_status(struct seq_file *seq, int block_status, + char *group) { - switch (block_status) - { + switch (block_status) { case -ETIMEDOUT: - return sprintf(buf, "Timeout reading group %s.\n",group); + return seq_printf(seq, "Timeout reading group %s.\n", group); case -ENOMEM: - return sprintf(buf, "No free memory to read the table.\n"); + return seq_printf(seq, "No free memory to read the table.\n"); case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: - return sprintf(buf, "Group %s not supported.\n", group); + return seq_printf(seq, "Group %s not supported.\n", group); default: - return sprintf(buf, "Error reading group %s. BlockStatus 0x%02X\n", - group, -block_status); + return seq_printf(seq, + "Error reading group %s. BlockStatus 0x%02X\n", + group, -block_status); } } -static char* bus_strings[] = -{ - "Local Bus", - "ISA", - "EISA", - "MCA", +static char *bus_strings[] = { + "Local Bus", + "ISA", + "EISA", + "MCA", "PCI", - "PCMCIA", - "NUBUS", + "PCMCIA", + "NUBUS", "CARDBUS" }; -static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED; - -int i2o_seq_show_hrt(struct seq_file *seq, void *v) +static int i2o_seq_show_hrt(struct seq_file *seq, void *v) { struct i2o_controller *c = (struct i2o_controller *)seq->private; - i2o_hrt *hrt = (i2o_hrt *)c->hrt; + i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; u32 bus; int i; - if(hrt->hrt_version) - { - seq_printf(seq, "HRT table for controller is too new a version.\n"); + if (hrt->hrt_version) { + seq_printf(seq, + "HRT table for controller is too new a version.\n"); return 0; } seq_printf(seq, "HRT has %d entries of %d bytes each.\n", - hrt->num_entries, hrt->entry_len << 2); + hrt->num_entries, hrt->entry_len << 2); - for(i = 0; i < hrt->num_entries; i++) - { + for (i = 0; i < hrt->num_entries; i++) { seq_printf(seq, "Entry %d:\n", i); seq_printf(seq, " Adapter ID: %0#10x\n", - hrt->hrt_entry[i].adapter_id); + hrt->hrt_entry[i].adapter_id); seq_printf(seq, " Controlling tid: %0#6x\n", - hrt->hrt_entry[i].parent_tid); + hrt->hrt_entry[i].parent_tid); - if(hrt->hrt_entry[i].bus_type != 0x80) - { + if (hrt->hrt_entry[i].bus_type != 0x80) { bus = hrt->hrt_entry[i].bus_type; - seq_printf(seq, " %s Information\n", bus_strings[bus]); - - switch(bus) - { - case I2O_BUS_LOCAL: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.local_bus.LbBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x\n", - hrt->hrt_entry[i].bus.local_bus.LbBaseMemoryAddress); - break; - - case I2O_BUS_ISA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.isa_bus.IsaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.isa_bus.IsaBaseMemoryAddress); - seq_printf(seq, " CSN: %0#4x,", - hrt->hrt_entry[i].bus.isa_bus.CSN); - break; - - case I2O_BUS_EISA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.eisa_bus.EisaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.eisa_bus.EisaBaseMemoryAddress); - seq_printf(seq, " Slot: %0#4x,", - hrt->hrt_entry[i].bus.eisa_bus.EisaSlotNumber); - break; - - case I2O_BUS_MCA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.mca_bus.McaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.mca_bus.McaBaseMemoryAddress); - seq_printf(seq, " Slot: %0#4x,", - hrt->hrt_entry[i].bus.mca_bus.McaSlotNumber); - break; - - case I2O_BUS_PCI: - seq_printf(seq, " Bus: %0#4x", - hrt->hrt_entry[i].bus.pci_bus.PciBusNumber); - seq_printf(seq, " Dev: %0#4x", - hrt->hrt_entry[i].bus.pci_bus.PciDeviceNumber); - seq_printf(seq, " Func: %0#4x", - hrt->hrt_entry[i].bus.pci_bus.PciFunctionNumber); - seq_printf(seq, " Vendor: %0#6x", - hrt->hrt_entry[i].bus.pci_bus.PciVendorID); - seq_printf(seq, " Device: %0#6x\n", - hrt->hrt_entry[i].bus.pci_bus.PciDeviceID); - break; - - default: - seq_printf(seq, " Unsupported Bus Type\n"); + seq_printf(seq, " %s Information\n", + bus_strings[bus]); + + switch (bus) { + case I2O_BUS_LOCAL: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.local_bus. + LbBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x\n", + hrt->hrt_entry[i].bus.local_bus. + LbBaseMemoryAddress); + break; + + case I2O_BUS_ISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseMemoryAddress); + seq_printf(seq, " CSN: %0#4x,", + hrt->hrt_entry[i].bus.isa_bus.CSN); + break; + + case I2O_BUS_EISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseMemoryAddress); + seq_printf(seq, " Slot: %0#4x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaSlotNumber); + break; + + case I2O_BUS_MCA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.mca_bus. + McaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.mca_bus. + McaBaseMemoryAddress); + seq_printf(seq, " Slot: %0#4x,", + hrt->hrt_entry[i].bus.mca_bus. + McaSlotNumber); + break; + + case I2O_BUS_PCI: + seq_printf(seq, " Bus: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciBusNumber); + seq_printf(seq, " Dev: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceNumber); + seq_printf(seq, " Func: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciFunctionNumber); + seq_printf(seq, " Vendor: %0#6x", + hrt->hrt_entry[i].bus.pci_bus. + PciVendorID); + seq_printf(seq, " Device: %0#6x\n", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceID); + break; + + default: + seq_printf(seq, " Unsupported Bus Type\n"); } - } - else + } else seq_printf(seq, " Unknown Bus Type\n"); } - + return 0; } -int i2o_seq_show_lct(struct seq_file *seq, void *v) +static int i2o_seq_show_lct(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)seq->private; - i2o_lct *lct = (i2o_lct *)c->lct; + struct i2o_controller *c = (struct i2o_controller *)seq->private; + i2o_lct *lct = (i2o_lct *) c->lct; int entries; int i; #define BUS_TABLE_SIZE 3 - static char *bus_ports[] = - { + static char *bus_ports[] = { "Generic Bus", "SCSI Bus", "Fibre Channel Bus" }; - entries = (lct->table_size - 3)/9; + entries = (lct->table_size - 3) / 9; seq_printf(seq, "LCT contains %d %s\n", entries, - entries == 1 ? "entry" : "entries"); - if(lct->boot_tid) + entries == 1 ? "entry" : "entries"); + if (lct->boot_tid) seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); - for(i = 0; i < entries; i++) - { + for (i = 0; i < entries; i++) { seq_printf(seq, "Entry %d\n", i); - seq_printf(seq, " Class, SubClass : %s", i2o_get_class_name(lct->lct_entry[i].class_id)); - + seq_printf(seq, " Class, SubClass : %s", + i2o_get_class_name(lct->lct_entry[i].class_id)); + /* - * Classes which we'll print subclass info for + * Classes which we'll print subclass info for */ - switch(lct->lct_entry[i].class_id & 0xFFF) - { - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - switch(lct->lct_entry[i].sub_class) - { - case 0x00: - seq_printf(seq, ", Direct-Access Read/Write"); - break; - - case 0x04: - seq_printf(seq, ", WORM Drive"); - break; - - case 0x05: - seq_printf(seq, ", CD-ROM Drive"); - break; - - case 0x07: - seq_printf(seq, ", Optical Memory Device"); - break; - - default: - seq_printf(seq, ", Unknown (0x%02x)", - lct->lct_entry[i].sub_class); - break; - } + switch (lct->lct_entry[i].class_id & 0xFFF) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + switch (lct->lct_entry[i].sub_class) { + case 0x00: + seq_printf(seq, ", Direct-Access Read/Write"); + break; + + case 0x04: + seq_printf(seq, ", WORM Drive"); break; - case I2O_CLASS_LAN: - switch(lct->lct_entry[i].sub_class & 0xFF) - { - case 0x30: - seq_printf(seq, ", Ethernet"); - break; - - case 0x40: - seq_printf(seq, ", 100base VG"); - break; - - case 0x50: - seq_printf(seq, ", IEEE 802.5/Token-Ring"); - break; - - case 0x60: - seq_printf(seq, ", ANSI X3T9.5 FDDI"); - break; - - case 0x70: - seq_printf(seq, ", Fibre Channel"); - break; - - default: - seq_printf(seq, ", Unknown Sub-Class (0x%02x)", - lct->lct_entry[i].sub_class & 0xFF); - break; - } + case 0x05: + seq_printf(seq, ", CD-ROM Drive"); break; - case I2O_CLASS_SCSI_PERIPHERAL: - if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) - seq_printf(seq, ", %s", - scsi_devices[lct->lct_entry[i].sub_class]); - else - seq_printf(seq, ", Unknown Device Type"); + case 0x07: + seq_printf(seq, ", Optical Memory Device"); break; - case I2O_CLASS_BUS_ADAPTER_PORT: - if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) - seq_printf(seq, ", %s", - bus_ports[lct->lct_entry[i].sub_class]); - else - seq_printf(seq, ", Unknown Bus Type"); + default: + seq_printf(seq, ", Unknown (0x%02x)", + lct->lct_entry[i].sub_class); break; + } + break; + + case I2O_CLASS_LAN: + switch (lct->lct_entry[i].sub_class & 0xFF) { + case 0x30: + seq_printf(seq, ", Ethernet"); + break; + + case 0x40: + seq_printf(seq, ", 100base VG"); + break; + + case 0x50: + seq_printf(seq, ", IEEE 802.5/Token-Ring"); + break; + + case 0x60: + seq_printf(seq, ", ANSI X3T9.5 FDDI"); + break; + + case 0x70: + seq_printf(seq, ", Fibre Channel"); + break; + + default: + seq_printf(seq, ", Unknown Sub-Class (0x%02x)", + lct->lct_entry[i].sub_class & 0xFF); + break; + } + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) + seq_printf(seq, ", %s", + scsi_devices[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Device Type"); + break; + + case I2O_CLASS_BUS_ADAPTER_PORT: + if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) + seq_printf(seq, ", %s", + bus_ports[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Bus Type"); + break; } seq_printf(seq, "\n"); - - seq_printf(seq, " Local TID : 0x%03x\n", lct->lct_entry[i].tid); - seq_printf(seq, " User TID : 0x%03x\n", lct->lct_entry[i].user_tid); + + seq_printf(seq, " Local TID : 0x%03x\n", + lct->lct_entry[i].tid); + seq_printf(seq, " User TID : 0x%03x\n", + lct->lct_entry[i].user_tid); seq_printf(seq, " Parent TID : 0x%03x\n", - lct->lct_entry[i].parent_tid); + lct->lct_entry[i].parent_tid); seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", - lct->lct_entry[i].identity_tag[0], - lct->lct_entry[i].identity_tag[1], - lct->lct_entry[i].identity_tag[2], - lct->lct_entry[i].identity_tag[3], - lct->lct_entry[i].identity_tag[4], - lct->lct_entry[i].identity_tag[5], - lct->lct_entry[i].identity_tag[6], - lct->lct_entry[i].identity_tag[7]); + lct->lct_entry[i].identity_tag[0], + lct->lct_entry[i].identity_tag[1], + lct->lct_entry[i].identity_tag[2], + lct->lct_entry[i].identity_tag[3], + lct->lct_entry[i].identity_tag[4], + lct->lct_entry[i].identity_tag[5], + lct->lct_entry[i].identity_tag[6], + lct->lct_entry[i].identity_tag[7]); seq_printf(seq, " Change Indicator : %0#10x\n", - lct->lct_entry[i].change_ind); + lct->lct_entry[i].change_ind); seq_printf(seq, " Event Capab Mask : %0#10x\n", - lct->lct_entry[i].device_flags); + lct->lct_entry[i].device_flags); } return 0; } -int i2o_seq_show_status(struct seq_file *seq, void *v) +static int i2o_seq_show_status(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)seq->private; + struct i2o_controller *c = (struct i2o_controller *)seq->private; char prodstr[25]; int version; - - i2o_status_get(c); // reread the status block + i2o_status_block *sb = c->status_block.virt; + + i2o_status_get(c); // reread the status block + + seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id); - seq_printf(seq, "Organization ID : %0#6x\n", - c->status_block->org_id); + version = sb->i2o_version; - version = c->status_block->i2o_version; - /* FIXME for Spec 2.0 if (version == 0x02) { seq_printf(seq, "Lowest I2O version supported: "); @@ -599,170 +563,171 @@ int i2o_seq_show_status(struct seq_file *seq, void *v) } } */ - seq_printf(seq, "IOP ID : %0#5x\n", - c->status_block->iop_id); - seq_printf(seq, "Host Unit ID : %0#6x\n", - c->status_block->host_unit_id); - seq_printf(seq, "Segment Number : %0#5x\n", - c->status_block->segment_number); + seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id); + seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id); + seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number); seq_printf(seq, "I2O version : "); switch (version) { - case 0x00: - seq_printf(seq, "1.0\n"); - break; - case 0x01: - seq_printf(seq, "1.5\n"); - break; - case 0x02: - seq_printf(seq, "2.0\n"); - break; - default: - seq_printf(seq, "Unknown version\n"); + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + default: + seq_printf(seq, "Unknown version\n"); } seq_printf(seq, "IOP State : "); - switch (c->status_block->iop_state) { - case 0x01: - seq_printf(seq, "INIT\n"); - break; + switch (sb->iop_state) { + case 0x01: + seq_printf(seq, "INIT\n"); + break; - case 0x02: - seq_printf(seq, "RESET\n"); - break; + case 0x02: + seq_printf(seq, "RESET\n"); + break; - case 0x04: - seq_printf(seq, "HOLD\n"); - break; + case 0x04: + seq_printf(seq, "HOLD\n"); + break; - case 0x05: - seq_printf(seq, "READY\n"); - break; + case 0x05: + seq_printf(seq, "READY\n"); + break; - case 0x08: - seq_printf(seq, "OPERATIONAL\n"); - break; + case 0x08: + seq_printf(seq, "OPERATIONAL\n"); + break; - case 0x10: - seq_printf(seq, "FAILED\n"); - break; + case 0x10: + seq_printf(seq, "FAILED\n"); + break; - case 0x11: - seq_printf(seq, "FAULTED\n"); - break; + case 0x11: + seq_printf(seq, "FAULTED\n"); + break; - default: - seq_printf(seq, "Unknown\n"); - break; + default: + seq_printf(seq, "Unknown\n"); + break; } seq_printf(seq, "Messenger Type : "); - switch (c->status_block->msg_type) { - case 0x00: - seq_printf(seq, "Memory mapped\n"); - break; - case 0x01: - seq_printf(seq, "Memory mapped only\n"); - break; - case 0x02: - seq_printf(seq,"Remote only\n"); - break; - case 0x03: - seq_printf(seq, "Memory mapped and remote\n"); - break; - default: - seq_printf(seq, "Unknown\n"); + switch (sb->msg_type) { + case 0x00: + seq_printf(seq, "Memory mapped\n"); + break; + case 0x01: + seq_printf(seq, "Memory mapped only\n"); + break; + case 0x02: + seq_printf(seq, "Remote only\n"); + break; + case 0x03: + seq_printf(seq, "Memory mapped and remote\n"); + break; + default: + seq_printf(seq, "Unknown\n"); } seq_printf(seq, "Inbound Frame Size : %d bytes\n", - c->status_block->inbound_frame_size<<2); + sb->inbound_frame_size << 2); seq_printf(seq, "Max Inbound Frames : %d\n", - c->status_block->max_inbound_frames); + sb->max_inbound_frames); seq_printf(seq, "Current Inbound Frames : %d\n", - c->status_block->cur_inbound_frames); + sb->cur_inbound_frames); seq_printf(seq, "Max Outbound Frames : %d\n", - c->status_block->max_outbound_frames); + sb->max_outbound_frames); /* Spec doesn't say if NULL terminated or not... */ - memcpy(prodstr, c->status_block->product_id, 24); + memcpy(prodstr, sb->product_id, 24); prodstr[24] = '\0'; seq_printf(seq, "Product ID : %s\n", prodstr); seq_printf(seq, "Expected LCT Size : %d bytes\n", - c->status_block->expected_lct_size); + sb->expected_lct_size); seq_printf(seq, "IOP Capabilities\n"); seq_printf(seq, " Context Field Size Support : "); - switch (c->status_block->iop_capabilities & 0x0000003) { - case 0: - seq_printf(seq, "Supports only 32-bit context fields\n"); - break; - case 1: - seq_printf(seq, "Supports only 64-bit context fields\n"); - break; - case 2: - seq_printf(seq, "Supports 32-bit and 64-bit context fields, " - "but not concurrently\n"); - break; - case 3: - seq_printf(seq, "Supports 32-bit and 64-bit context fields " - "concurrently\n"); - break; - default: - seq_printf(seq, "0x%08x\n",c->status_block->iop_capabilities); + switch (sb->iop_capabilities & 0x0000003) { + case 0: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 1: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 2: + seq_printf(seq, "Supports 32-bit and 64-bit context fields, " + "but not concurrently\n"); + break; + case 3: + seq_printf(seq, "Supports 32-bit and 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "0x%08x\n", sb->iop_capabilities); } seq_printf(seq, " Current Context Field Size : "); - switch (c->status_block->iop_capabilities & 0x0000000C) { - case 0: - seq_printf(seq, "not configured\n"); - break; - case 4: - seq_printf(seq, "Supports only 32-bit context fields\n"); - break; - case 8: - seq_printf(seq, "Supports only 64-bit context fields\n"); - break; - case 12: - seq_printf(seq, "Supports both 32-bit or 64-bit context fields " - "concurrently\n"); - break; - default: - seq_printf(seq, "\n"); + switch (sb->iop_capabilities & 0x0000000C) { + case 0: + seq_printf(seq, "not configured\n"); + break; + case 4: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 8: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 12: + seq_printf(seq, "Supports both 32-bit or 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "\n"); } seq_printf(seq, " Inbound Peer Support : %s\n", - (c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported"); + (sb-> + iop_capabilities & 0x00000010) ? "Supported" : + "Not supported"); seq_printf(seq, " Outbound Peer Support : %s\n", - (c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported"); + (sb-> + iop_capabilities & 0x00000020) ? "Supported" : + "Not supported"); seq_printf(seq, " Peer to Peer Support : %s\n", - (c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported"); + (sb-> + iop_capabilities & 0x00000040) ? "Supported" : + "Not supported"); seq_printf(seq, "Desired private memory size : %d kB\n", - c->status_block->desired_mem_size>>10); + sb->desired_mem_size >> 10); seq_printf(seq, "Allocated private memory size : %d kB\n", - c->status_block->current_mem_size>>10); + sb->current_mem_size >> 10); seq_printf(seq, "Private memory base address : %0#10x\n", - c->status_block->current_mem_base); + sb->current_mem_base); seq_printf(seq, "Desired private I/O size : %d kB\n", - c->status_block->desired_io_size>>10); + sb->desired_io_size >> 10); seq_printf(seq, "Allocated private I/O size : %d kB\n", - c->status_block->current_io_size>>10); + sb->current_io_size >> 10); seq_printf(seq, "Private I/O base address : %0#10x\n", - c->status_block->current_io_base); + sb->current_io_base); return 0; } -int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_hw(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller *)seq->private; static u32 work32[5]; - static u8 *work8 = (u8*)work32; - static u16 *work16 = (u16*)work32; + static u8 *work8 = (u8 *) work32; + static u16 *work16 = (u16 *) work32; int token; u32 hwcap; - static char *cpu_table[] = - { + static char *cpu_table[] = { "Intel 80960 series", "AMD2900 series", "Motorola 68000 series", @@ -773,397 +738,341 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, "Intel x86 series" }; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_scalar(c, ADAPTER_TID, 0x0000, -1, &work32, sizeof(work32)); + token = + i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0000 IOP Hardware"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0x0000 IOP Hardware"); + return 0; } - len += sprintf(buf+len, "I2O Vendor ID : %0#6x\n", work16[0]); - len += sprintf(buf+len, "Product ID : %0#6x\n", work16[1]); - len += sprintf(buf+len, "CPU : "); - if(work8[16] > 8) - len += sprintf(buf+len, "Unknown\n"); + seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]); + seq_printf(seq, "Product ID : %0#6x\n", work16[1]); + seq_printf(seq, "CPU : "); + if (work8[16] > 8) + seq_printf(seq, "Unknown\n"); else - len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]); + seq_printf(seq, "%s\n", cpu_table[work8[16]]); /* Anyone using ProcessorVersion? */ - - len += sprintf(buf+len, "RAM : %dkB\n", work32[1]>>10); - len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10); + + seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10); + seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10); hwcap = work32[3]; - len += sprintf(buf+len, "Capabilities : 0x%08x\n", hwcap); - len += sprintf(buf+len, " [%s] Self booting\n", - (hwcap&0x00000001) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Upgradable IRTOS\n", - (hwcap&0x00000002) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Supports downloading DDMs\n", - (hwcap&0x00000004) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Supports installing DDMs\n", - (hwcap&0x00000008) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Battery-backed RAM\n", - (hwcap&0x00000010) ? "+" : "-"); - - spin_unlock(&i2o_proc_lock); - - return len; -} + seq_printf(seq, "Capabilities : 0x%08x\n", hwcap); + seq_printf(seq, " [%s] Self booting\n", + (hwcap & 0x00000001) ? "+" : "-"); + seq_printf(seq, " [%s] Upgradable IRTOS\n", + (hwcap & 0x00000002) ? "+" : "-"); + seq_printf(seq, " [%s] Supports downloading DDMs\n", + (hwcap & 0x00000004) ? "+" : "-"); + seq_printf(seq, " [%s] Supports installing DDMs\n", + (hwcap & 0x00000008) ? "+" : "-"); + seq_printf(seq, " [%s] Battery-backed RAM\n", + (hwcap & 0x00000010) ? "+" : "-"); + return 0; +} /* Executive group 0003h - Executing DDM List (table) */ -int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller *)seq->private; int token; int i; typedef struct _i2o_exec_execute_ddm_table { u16 ddm_tid; - u8 module_type; - u8 reserved; + u8 module_type; + u8 reserved; u16 i2o_vendor_id; u16 module_id; - u8 module_name_version[28]; + u8 module_name_version[28]; u32 data_size; u32 code_size; } i2o_exec_execute_ddm_table; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; - i2o_exec_execute_ddm_table ddm_table[MAX_I2O_MODULES]; + i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES]; } *result; i2o_exec_execute_ddm_table ddm_table; result = kmalloc(sizeof(*result), GFP_KERNEL); - if(!result) + if (!result) return -ENOMEM; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, - 0x0003, -1, - NULL, 0, - result, sizeof(*result)); + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1, + NULL, 0, result, sizeof(*result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List"); + i2o_report_query_status(seq, token, + "0x0003 Executing DDM List"); goto out; } - len += sprintf(buf+len, "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); - ddm_table=result->ddm_table[0]; + seq_printf(seq, + "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); + ddm_table = result->ddm_table[0]; - for(i=0; i < result->row_count; ddm_table=result->ddm_table[++i]) - { - len += sprintf(buf+len, "0x%03x ", ddm_table.ddm_tid & 0xFFF); + for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) { + seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF); - switch(ddm_table.module_type) - { + switch (ddm_table.module_type) { case 0x01: - len += sprintf(buf+len, "Downloaded DDM "); - break; + seq_printf(seq, "Downloaded DDM "); + break; case 0x22: - len += sprintf(buf+len, "Embedded DDM "); + seq_printf(seq, "Embedded DDM "); break; default: - len += sprintf(buf+len, " "); + seq_printf(seq, " "); } - len += sprintf(buf+len, "%-#7x", ddm_table.i2o_vendor_id); - len += sprintf(buf+len, "%-#8x", ddm_table.module_id); - len += sprintf(buf+len, "%-29s", chtostr(ddm_table.module_name_version, 28)); - len += sprintf(buf+len, "%9d ", ddm_table.data_size); - len += sprintf(buf+len, "%8d", ddm_table.code_size); + seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); + seq_printf(seq, "%-#8x", ddm_table.module_id); + seq_printf(seq, "%-29s", + chtostr(ddm_table.module_name_version, 28)); + seq_printf(seq, "%9d ", ddm_table.data_size); + seq_printf(seq, "%8d", ddm_table.code_size); - len += sprintf(buf+len, "\n"); + seq_printf(seq, "\n"); } -out: - spin_unlock(&i2o_proc_lock); + out: kfree(result); - return len; + return 0; } - /* Executive group 0004h - Driver Store (scalar) */ -int i2o_proc_read_driver_store(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller *)seq->private; u32 work32[8]; int token; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, sizeof(work32)); + token = + i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0004 Driver Store"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0x0004 Driver Store"); + return 0; } - len += sprintf(buf+len, "Module limit : %d\n" - "Module count : %d\n" - "Current space : %d kB\n" - "Free space : %d kB\n", - work32[0], work32[1], work32[2]>>10, work32[3]>>10); - - spin_unlock(&i2o_proc_lock); + seq_printf(seq, "Module limit : %d\n" + "Module count : %d\n" + "Current space : %d kB\n" + "Free space : %d kB\n", + work32[0], work32[1], work32[2] >> 10, work32[3] >> 10); - return len; + return 0; } - /* Executive group 0005h - Driver Store Table (table) */ -int i2o_proc_read_drivers_stored(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) { typedef struct _i2o_driver_store { u16 stored_ddm_index; - u8 module_type; - u8 reserved; + u8 module_type; + u8 reserved; u16 i2o_vendor_id; u16 module_id; - u8 module_name_version[28]; - u8 date[8]; + u8 module_name_version[28]; + u8 date[8]; u32 module_size; u32 mpb_size; u32 module_flags; } i2o_driver_store_table; - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_controller *c = (struct i2o_controller *)seq->private; int token; int i; - typedef struct - { + typedef struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; - i2o_driver_store_table dst[MAX_I2O_MODULES]; + i2o_driver_store_table dst[I2O_MAX_MODULES]; } i2o_driver_result_table; - + i2o_driver_result_table *result; i2o_driver_store_table *dst; - - len = 0; - result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); - if(result == NULL) + if (result == NULL) return -ENOMEM; - spin_lock(&i2o_proc_lock); - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, 0x0005, -1, NULL, 0, - result, sizeof(*result)); + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1, + NULL, 0, result, sizeof(*result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0005 DRIVER STORE TABLE"); - spin_unlock(&i2o_proc_lock); + i2o_report_query_status(seq, token, + "0x0005 DRIVER STORE TABLE"); kfree(result); - return len; + return 0; } - len += sprintf(buf+len, "# Module_type Vendor Mod_id Module_name Vrs" - "Date Mod_size Par_size Flags\n"); - for(i=0, dst=&result->dst[0]; i < result->row_count; dst=&result->dst[++i]) - { - len += sprintf(buf+len, "%-3d", dst->stored_ddm_index); - switch(dst->module_type) - { + seq_printf(seq, + "# Module_type Vendor Mod_id Module_name Vrs" + "Date Mod_size Par_size Flags\n"); + for (i = 0, dst = &result->dst[0]; i < result->row_count; + dst = &result->dst[++i]) { + seq_printf(seq, "%-3d", dst->stored_ddm_index); + switch (dst->module_type) { case 0x01: - len += sprintf(buf+len, "Downloaded DDM "); - break; + seq_printf(seq, "Downloaded DDM "); + break; case 0x22: - len += sprintf(buf+len, "Embedded DDM "); + seq_printf(seq, "Embedded DDM "); break; default: - len += sprintf(buf+len, " "); + seq_printf(seq, " "); } -#if 0 - if(c->i2oversion == 0x02) - len += sprintf(buf+len, "%-d", dst->module_state); -#endif - - len += sprintf(buf+len, "%-#7x", dst->i2o_vendor_id); - len += sprintf(buf+len, "%-#8x", dst->module_id); - len += sprintf(buf+len, "%-29s", chtostr(dst->module_name_version,28)); - len += sprintf(buf+len, "%-9s", chtostr(dst->date,8)); - len += sprintf(buf+len, "%8d ", dst->module_size); - len += sprintf(buf+len, "%8d ", dst->mpb_size); - len += sprintf(buf+len, "0x%04x", dst->module_flags); -#if 0 - if(c->i2oversion == 0x02) - len += sprintf(buf+len, "%d", - dst->notification_level); -#endif - len += sprintf(buf+len, "\n"); + seq_printf(seq, "%-#7x", dst->i2o_vendor_id); + seq_printf(seq, "%-#8x", dst->module_id); + seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28)); + seq_printf(seq, "%-9s", chtostr(dst->date, 8)); + seq_printf(seq, "%8d ", dst->module_size); + seq_printf(seq, "%8d ", dst->mpb_size); + seq_printf(seq, "0x%04x", dst->module_flags); + seq_printf(seq, "\n"); } - spin_unlock(&i2o_proc_lock); kfree(result); - return len; + return 0; } - /* Generic group F000h - Params Descriptor (table) */ -int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_groups(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; u8 properties; - typedef struct _i2o_group_info - { + typedef struct _i2o_group_info { u16 group_number; u16 field_count; u16 row_count; - u8 properties; - u8 reserved; + u8 properties; + u8 reserved; } i2o_group_info; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; i2o_group_info group[256]; } *result; result = kmalloc(sizeof(*result), GFP_KERNEL); - if(!result) + if (!result) return -ENOMEM; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, 0xF000, -1, NULL, 0, - result, sizeof(*result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + result, sizeof(*result)); if (token < 0) { - len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor"); + i2o_report_query_status(seq, token, "0xF000 Params Descriptor"); goto out; } - len += sprintf(buf+len, "# Group FieldCount RowCount Type Add Del Clear\n"); + seq_printf(seq, + "# Group FieldCount RowCount Type Add Del Clear\n"); - for (i=0; i < result->row_count; i++) - { - len += sprintf(buf+len, "%-3d", i); - len += sprintf(buf+len, "0x%04X ", result->group[i].group_number); - len += sprintf(buf+len, "%10d ", result->group[i].field_count); - len += sprintf(buf+len, "%8d ", result->group[i].row_count); + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "0x%04X ", result->group[i].group_number); + seq_printf(seq, "%10d ", result->group[i].field_count); + seq_printf(seq, "%8d ", result->group[i].row_count); properties = result->group[i].properties; - if (properties & 0x1) len += sprintf(buf+len, "Table "); - else len += sprintf(buf+len, "Scalar "); - if (properties & 0x2) len += sprintf(buf+len, " + "); - else len += sprintf(buf+len, " - "); - if (properties & 0x4) len += sprintf(buf+len, " + "); - else len += sprintf(buf+len, " - "); - if (properties & 0x8) len += sprintf(buf+len, " + "); - else len += sprintf(buf+len, " - "); - - len += sprintf(buf+len, "\n"); + if (properties & 0x1) + seq_printf(seq, "Table "); + else + seq_printf(seq, "Scalar "); + if (properties & 0x2) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x4) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x8) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + + seq_printf(seq, "\n"); } if (result->more_flag) - len += sprintf(buf+len, "There is more...\n"); -out: - spin_unlock(&i2o_proc_lock); + seq_printf(seq, "There is more...\n"); + out: kfree(result); - return len; + return 0; } - /* Generic group F001h - Physical Device Table (table) */ -int i2o_proc_read_phys_device(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; u32 adapter_id[64]; } result; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0xF001, -1, NULL, 0, - &result, sizeof(result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0, + &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF001 Physical Device Table"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, + "0xF001 Physical Device Table"); + return 0; } if (result.row_count) - len += sprintf(buf+len, "# AdapterId\n"); + seq_printf(seq, "# AdapterId\n"); - for (i=0; i < result.row_count; i++) - { - len += sprintf(buf+len, "%-2d", i); - len += sprintf(buf+len, "%#7x\n", result.adapter_id[i]); + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.adapter_id[i]); } if (result.more_flag) - len += sprintf(buf+len, "There is more...\n"); + seq_printf(seq, "There is more...\n"); - spin_unlock(&i2o_proc_lock); - return len; + return 0; } /* Generic group F002h - Claimed Table (table) */ -int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_claimed(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; @@ -1171,434 +1080,356 @@ int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len, u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; u16 claimed_tid[64]; } result; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0xF002, -1, NULL, 0, - &result, sizeof(result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0, + &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF002 Claimed Table"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0xF002 Claimed Table"); + return 0; } if (result.row_count) - len += sprintf(buf+len, "# ClaimedTid\n"); + seq_printf(seq, "# ClaimedTid\n"); - for (i=0; i < result.row_count; i++) - { - len += sprintf(buf+len, "%-2d", i); - len += sprintf(buf+len, "%#7x\n", result.claimed_tid[i]); + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.claimed_tid[i]); } if (result.more_flag) - len += sprintf(buf+len, "There is more...\n"); + seq_printf(seq, "There is more...\n"); - spin_unlock(&i2o_proc_lock); - return len; + return 0; } /* Generic group F003h - User Table (table) */ -int i2o_proc_read_users(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_users(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; - typedef struct _i2o_user_table - { + typedef struct _i2o_user_table { u16 instance; u16 user_tid; u8 claim_type; - u8 reserved1; - u16 reserved2; + u8 reserved1; + u16 reserved2; } i2o_user_table; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; i2o_user_table user[64]; } *result; result = kmalloc(sizeof(*result), GFP_KERNEL); - if(!result) + if (!result) return -ENOMEM; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0xF003, -1, NULL, 0, - result, sizeof(*result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0, + result, sizeof(*result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF003 User Table"); + i2o_report_query_status(seq, token, "0xF003 User Table"); goto out; } - len += sprintf(buf+len, "# Instance UserTid ClaimType\n"); + seq_printf(seq, "# Instance UserTid ClaimType\n"); - for(i=0; i < result->row_count; i++) - { - len += sprintf(buf+len, "%-3d", i); - len += sprintf(buf+len, "%#8x ", result->user[i].instance); - len += sprintf(buf+len, "%#7x ", result->user[i].user_tid); - len += sprintf(buf+len, "%#9x\n", result->user[i].claim_type); + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "%#8x ", result->user[i].instance); + seq_printf(seq, "%#7x ", result->user[i].user_tid); + seq_printf(seq, "%#9x\n", result->user[i].claim_type); } if (result->more_flag) - len += sprintf(buf+len, "There is more...\n"); -out: - spin_unlock(&i2o_proc_lock); + seq_printf(seq, "There is more...\n"); + out: kfree(result); - return len; + return 0; } /* Generic group F005h - Private message extensions (table) (optional) */ -int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; - typedef struct _i2o_private - { + typedef struct _i2o_private { u16 ext_instance; u16 organization_id; u16 x_function_code; } i2o_private; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; i2o_private extension[64]; } result; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0xF000, -1, - NULL, 0, - &result, sizeof(result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF005 Private Message Extensions (optional)"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, + "0xF005 Private Message Extensions (optional)"); + return 0; } - - len += sprintf(buf+len, "Instance# OrgId FunctionCode\n"); - for(i=0; i < result.row_count; i++) - { - len += sprintf(buf+len, "%0#9x ", result.extension[i].ext_instance); - len += sprintf(buf+len, "%0#6x ", result.extension[i].organization_id); - len += sprintf(buf+len, "%0#6x", result.extension[i].x_function_code); + seq_printf(seq, "Instance# OrgId FunctionCode\n"); - len += sprintf(buf+len, "\n"); - } + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%0#9x ", result.extension[i].ext_instance); + seq_printf(seq, "%0#6x ", result.extension[i].organization_id); + seq_printf(seq, "%0#6x", result.extension[i].x_function_code); - if(result.more_flag) - len += sprintf(buf+len, "There is more...\n"); + seq_printf(seq, "\n"); + } - spin_unlock(&i2o_proc_lock); + if (result.more_flag) + seq_printf(seq, "There is more...\n"); - return len; + return 0; } - /* Generic group F006h - Authorized User Table (table) */ -int i2o_proc_read_authorized_users(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; int i; - struct - { + struct { u16 result_count; u16 pad; u16 block_size; - u8 block_status; - u8 error_info_size; + u8 block_status; + u8 error_info_size; u16 row_count; u16 more_flag; u32 alternate_tid[64]; } result; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0xF006, -1, - NULL, 0, - &result, sizeof(result)); + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0, + &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF006 Autohorized User Table"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, + "0xF006 Autohorized User Table"); + return 0; } if (result.row_count) - len += sprintf(buf+len, "# AlternateTid\n"); + seq_printf(seq, "# AlternateTid\n"); - for(i=0; i < result.row_count; i++) - { - len += sprintf(buf+len, "%-2d", i); - len += sprintf(buf+len, "%#7x ", result.alternate_tid[i]); + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x ", result.alternate_tid[i]); } if (result.more_flag) - len += sprintf(buf+len, "There is more...\n"); + seq_printf(seq, "There is more...\n"); - spin_unlock(&i2o_proc_lock); - return len; + return 0; } - /* Generic group F100h - Device Identity (scalar) */ -int i2o_proc_read_dev_identity(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number - // == (allow) 512d bytes (max) - static u16 *work16 = (u16*)work32; + struct i2o_device *d = (struct i2o_device *)seq->private; + static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number + // == (allow) 512d bytes (max) + static u16 *work16 = (u16 *) work32; int token; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0xF100, -1, - &work32, sizeof(work32)); + token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); if (token < 0) { - len += i2o_report_query_status(buf+len, token ,"0xF100 Device Identity"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0xF100 Device Identity"); + return 0; } - - len += sprintf(buf, "Device Class : %s\n", i2o_get_class_name(work16[0])); - len += sprintf(buf+len, "Owner TID : %0#5x\n", work16[2]); - len += sprintf(buf+len, "Parent TID : %0#5x\n", work16[3]); - len += sprintf(buf+len, "Vendor info : %s\n", chtostr((u8 *)(work32+2), 16)); - len += sprintf(buf+len, "Product info : %s\n", chtostr((u8 *)(work32+6), 16)); - len += sprintf(buf+len, "Description : %s\n", chtostr((u8 *)(work32+10), 16)); - len += sprintf(buf+len, "Product rev. : %s\n", chtostr((u8 *)(work32+14), 8)); - - len += sprintf(buf+len, "Serial number : "); - len = print_serial_number(buf, len, - (u8*)(work32+16), - /* allow for SNLen plus - * possible trailing '\0' - */ - sizeof(work32)-(16*sizeof(u32))-2 - ); - len += sprintf(buf+len, "\n"); - - spin_unlock(&i2o_proc_lock); - - return len; -} + seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); + seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); + seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); + seq_printf(seq, "Vendor info : %s\n", + chtostr((u8 *) (work32 + 2), 16)); + seq_printf(seq, "Product info : %s\n", + chtostr((u8 *) (work32 + 6), 16)); + seq_printf(seq, "Description : %s\n", + chtostr((u8 *) (work32 + 10), 16)); + seq_printf(seq, "Product rev. : %s\n", + chtostr((u8 *) (work32 + 14), 8)); + + seq_printf(seq, "Serial number : "); + print_serial_number(seq, (u8 *) (work32 + 16), + /* allow for SNLen plus + * possible trailing '\0' + */ + sizeof(work32) - (16 * sizeof(u32)) - 2); + seq_printf(seq, "\n"); -int i2o_proc_read_dev_name(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; + return 0; +} - if ( d->dev_name[0] == '\0' ) - return 0; +static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; - len = sprintf(buf, "%s\n", d->dev_name); + seq_printf(seq, "%s\n", d->device.bus_id); - return len; + return 0; } - /* Generic group F101h - DDM Identity (scalar) */ -int i2o_proc_read_ddm_identity(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; - struct - { + struct { u16 ddm_tid; u8 module_name[24]; u8 module_rev[8]; u8 sn_format; u8 serial_number[12]; - u8 pad[256]; // allow up to 256 byte (max) serial number - } result; - - spin_lock(&i2o_proc_lock); - - len = 0; + u8 pad[256]; // allow up to 256 byte (max) serial number + } result; - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0xF101, -1, - &result, sizeof(result)); + token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF101 DDM Identity"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0xF101 DDM Identity"); + return 0; } - len += sprintf(buf, "Registering DDM TID : 0x%03x\n", result.ddm_tid); - len += sprintf(buf+len, "Module name : %s\n", chtostr(result.module_name, 24)); - len += sprintf(buf+len, "Module revision : %s\n", chtostr(result.module_rev, 8)); + seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); + seq_printf(seq, "Module name : %s\n", + chtostr(result.module_name, 24)); + seq_printf(seq, "Module revision : %s\n", + chtostr(result.module_rev, 8)); - len += sprintf(buf+len, "Serial number : "); - len = print_serial_number(buf, len, result.serial_number, sizeof(result)-36); - /* allow for SNLen plus possible trailing '\0' */ + seq_printf(seq, "Serial number : "); + print_serial_number(seq, result.serial_number, sizeof(result) - 36); + /* allow for SNLen plus possible trailing '\0' */ - len += sprintf(buf+len, "\n"); + seq_printf(seq, "\n"); - spin_unlock(&i2o_proc_lock); - - return len; + return 0; } /* Generic group F102h - User Information (scalar) */ -int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; - struct - { + struct { u8 device_name[64]; u8 service_name[64]; u8 physical_location[64]; u8 instance_number[4]; } result; - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0xF102, -1, - &result, sizeof(result)); + token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF102 User Information"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, "0xF102 User Information"); + return 0; } - len += sprintf(buf, "Device name : %s\n", chtostr(result.device_name, 64)); - len += sprintf(buf+len, "Service name : %s\n", chtostr(result.service_name, 64)); - len += sprintf(buf+len, "Physical name : %s\n", chtostr(result.physical_location, 64)); - len += sprintf(buf+len, "Instance number : %s\n", chtostr(result.instance_number, 4)); + seq_printf(seq, "Device name : %s\n", + chtostr(result.device_name, 64)); + seq_printf(seq, "Service name : %s\n", + chtostr(result.service_name, 64)); + seq_printf(seq, "Physical name : %s\n", + chtostr(result.physical_location, 64)); + seq_printf(seq, "Instance number : %s\n", + chtostr(result.instance_number, 4)); - spin_unlock(&i2o_proc_lock); - return len; + return 0; } /* Generic group F103h - SGL Operating Limits (scalar) */ -int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; static u32 work32[12]; - static u16 *work16 = (u16 *)work32; - static u8 *work8 = (u8 *)work32; + static u16 *work16 = (u16 *) work32; + static u8 *work8 = (u8 *) work32; int token; - spin_lock(&i2o_proc_lock); - - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0xF103, -1, - &work32, sizeof(work32)); + token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF103 SGL Operating Limits"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, + "0xF103 SGL Operating Limits"); + return 0; } - len += sprintf(buf, "SGL chain size : %d\n", work32[0]); - len += sprintf(buf+len, "Max SGL chain size : %d\n", work32[1]); - len += sprintf(buf+len, "SGL chain size target : %d\n", work32[2]); - len += sprintf(buf+len, "SGL frag count : %d\n", work16[6]); - len += sprintf(buf+len, "Max SGL frag count : %d\n", work16[7]); - len += sprintf(buf+len, "SGL frag count target : %d\n", work16[8]); + seq_printf(seq, "SGL chain size : %d\n", work32[0]); + seq_printf(seq, "Max SGL chain size : %d\n", work32[1]); + seq_printf(seq, "SGL chain size target : %d\n", work32[2]); + seq_printf(seq, "SGL frag count : %d\n", work16[6]); + seq_printf(seq, "Max SGL frag count : %d\n", work16[7]); + seq_printf(seq, "SGL frag count target : %d\n", work16[8]); +/* FIXME if (d->i2oversion == 0x02) { - len += sprintf(buf+len, "SGL data alignment : %d\n", work16[8]); - len += sprintf(buf+len, "SGL addr limit : %d\n", work8[20]); - len += sprintf(buf+len, "SGL addr sizes supported : "); - if (work8[21] & 0x01) - len += sprintf(buf+len, "32 bit "); - if (work8[21] & 0x02) - len += sprintf(buf+len, "64 bit "); - if (work8[21] & 0x04) - len += sprintf(buf+len, "96 bit "); - if (work8[21] & 0x08) - len += sprintf(buf+len, "128 bit "); - len += sprintf(buf+len, "\n"); +*/ + seq_printf(seq, "SGL data alignment : %d\n", work16[8]); + seq_printf(seq, "SGL addr limit : %d\n", work8[20]); + seq_printf(seq, "SGL addr sizes supported : "); + if (work8[21] & 0x01) + seq_printf(seq, "32 bit "); + if (work8[21] & 0x02) + seq_printf(seq, "64 bit "); + if (work8[21] & 0x04) + seq_printf(seq, "96 bit "); + if (work8[21] & 0x08) + seq_printf(seq, "128 bit "); + seq_printf(seq, "\n"); +/* } +*/ - spin_unlock(&i2o_proc_lock); - - return len; + return 0; } /* Generic group F200h - Sensors (scalar) */ -int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int i2o_seq_show_sensors(struct seq_file *seq, void *v) { - struct i2o_device *d = (struct i2o_device*)data; + struct i2o_device *d = (struct i2o_device *)seq->private; int token; - struct - { + struct { u16 sensor_instance; - u8 component; + u8 component; u16 component_instance; - u8 sensor_class; - u8 sensor_type; - u8 scaling_exponent; + u8 sensor_class; + u8 sensor_type; + u8 scaling_exponent; u32 actual_reading; u32 minimum_reading; u32 low2lowcat_treshold; @@ -1615,1795 +1446,663 @@ int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len, u32 hicat2high_treshold; u32 hi2hicat_treshold; u32 maximum_reading; - u8 sensor_state; + u8 sensor_state; u16 event_enable; } result; - - spin_lock(&i2o_proc_lock); - len = 0; - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0xF200, -1, - &result, sizeof(result)); + token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result)); if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0xF200 Sensors (optional)"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_report_query_status(seq, token, + "0xF200 Sensors (optional)"); + return 0; } - - len += sprintf(buf+len, "Sensor instance : %d\n", result.sensor_instance); - len += sprintf(buf+len, "Component : %d = ", result.component); - switch (result.component) - { - case 0: len += sprintf(buf+len, "Other"); + seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance); + + seq_printf(seq, "Component : %d = ", result.component); + switch (result.component) { + case 0: + seq_printf(seq, "Other"); break; - case 1: len += sprintf(buf+len, "Planar logic Board"); + case 1: + seq_printf(seq, "Planar logic Board"); break; - case 2: len += sprintf(buf+len, "CPU"); + case 2: + seq_printf(seq, "CPU"); break; - case 3: len += sprintf(buf+len, "Chassis"); + case 3: + seq_printf(seq, "Chassis"); break; - case 4: len += sprintf(buf+len, "Power Supply"); + case 4: + seq_printf(seq, "Power Supply"); break; - case 5: len += sprintf(buf+len, "Storage"); + case 5: + seq_printf(seq, "Storage"); break; - case 6: len += sprintf(buf+len, "External"); + case 6: + seq_printf(seq, "External"); break; - } - len += sprintf(buf+len,"\n"); + } + seq_printf(seq, "\n"); - len += sprintf(buf+len, "Component instance : %d\n", result.component_instance); - len += sprintf(buf+len, "Sensor class : %s\n", - result.sensor_class ? "Analog" : "Digital"); - - len += sprintf(buf+len, "Sensor type : %d = ",result.sensor_type); - switch (result.sensor_type) - { - case 0: len += sprintf(buf+len, "Other\n"); + seq_printf(seq, "Component instance : %d\n", + result.component_instance); + seq_printf(seq, "Sensor class : %s\n", + result.sensor_class ? "Analog" : "Digital"); + + seq_printf(seq, "Sensor type : %d = ", result.sensor_type); + switch (result.sensor_type) { + case 0: + seq_printf(seq, "Other\n"); break; - case 1: len += sprintf(buf+len, "Thermal\n"); + case 1: + seq_printf(seq, "Thermal\n"); break; - case 2: len += sprintf(buf+len, "DC voltage (DC volts)\n"); + case 2: + seq_printf(seq, "DC voltage (DC volts)\n"); break; - case 3: len += sprintf(buf+len, "AC voltage (AC volts)\n"); + case 3: + seq_printf(seq, "AC voltage (AC volts)\n"); break; - case 4: len += sprintf(buf+len, "DC current (DC amps)\n"); + case 4: + seq_printf(seq, "DC current (DC amps)\n"); break; - case 5: len += sprintf(buf+len, "AC current (AC volts)\n"); + case 5: + seq_printf(seq, "AC current (AC volts)\n"); break; - case 6: len += sprintf(buf+len, "Door open\n"); + case 6: + seq_printf(seq, "Door open\n"); break; - case 7: len += sprintf(buf+len, "Fan operational\n"); + case 7: + seq_printf(seq, "Fan operational\n"); break; - } + } - len += sprintf(buf+len, "Scaling exponent : %d\n", result.scaling_exponent); - len += sprintf(buf+len, "Actual reading : %d\n", result.actual_reading); - len += sprintf(buf+len, "Minimum reading : %d\n", result.minimum_reading); - len += sprintf(buf+len, "Low2LowCat treshold : %d\n", result.low2lowcat_treshold); - len += sprintf(buf+len, "LowCat2Low treshold : %d\n", result.lowcat2low_treshold); - len += sprintf(buf+len, "LowWarn2Low treshold : %d\n", result.lowwarn2low_treshold); - len += sprintf(buf+len, "Low2LowWarn treshold : %d\n", result.low2lowwarn_treshold); - len += sprintf(buf+len, "Norm2LowWarn treshold : %d\n", result.norm2lowwarn_treshold); - len += sprintf(buf+len, "LowWarn2Norm treshold : %d\n", result.lowwarn2norm_treshold); - len += sprintf(buf+len, "Nominal reading : %d\n", result.nominal_reading); - len += sprintf(buf+len, "HiWarn2Norm treshold : %d\n", result.hiwarn2norm_treshold); - len += sprintf(buf+len, "Norm2HiWarn treshold : %d\n", result.norm2hiwarn_treshold); - len += sprintf(buf+len, "High2HiWarn treshold : %d\n", result.high2hiwarn_treshold); - len += sprintf(buf+len, "HiWarn2High treshold : %d\n", result.hiwarn2high_treshold); - len += sprintf(buf+len, "HiCat2High treshold : %d\n", result.hicat2high_treshold); - len += sprintf(buf+len, "High2HiCat treshold : %d\n", result.hi2hicat_treshold); - len += sprintf(buf+len, "Maximum reading : %d\n", result.maximum_reading); + seq_printf(seq, "Scaling exponent : %d\n", + result.scaling_exponent); + seq_printf(seq, "Actual reading : %d\n", result.actual_reading); + seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading); + seq_printf(seq, "Low2LowCat treshold : %d\n", + result.low2lowcat_treshold); + seq_printf(seq, "LowCat2Low treshold : %d\n", + result.lowcat2low_treshold); + seq_printf(seq, "LowWarn2Low treshold : %d\n", + result.lowwarn2low_treshold); + seq_printf(seq, "Low2LowWarn treshold : %d\n", + result.low2lowwarn_treshold); + seq_printf(seq, "Norm2LowWarn treshold : %d\n", + result.norm2lowwarn_treshold); + seq_printf(seq, "LowWarn2Norm treshold : %d\n", + result.lowwarn2norm_treshold); + seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading); + seq_printf(seq, "HiWarn2Norm treshold : %d\n", + result.hiwarn2norm_treshold); + seq_printf(seq, "Norm2HiWarn treshold : %d\n", + result.norm2hiwarn_treshold); + seq_printf(seq, "High2HiWarn treshold : %d\n", + result.high2hiwarn_treshold); + seq_printf(seq, "HiWarn2High treshold : %d\n", + result.hiwarn2high_treshold); + seq_printf(seq, "HiCat2High treshold : %d\n", + result.hicat2high_treshold); + seq_printf(seq, "High2HiCat treshold : %d\n", + result.hi2hicat_treshold); + seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading); - len += sprintf(buf+len, "Sensor state : %d = ", result.sensor_state); - switch (result.sensor_state) - { - case 0: len += sprintf(buf+len, "Normal\n"); - break; - case 1: len += sprintf(buf+len, "Abnormal\n"); - break; - case 2: len += sprintf(buf+len, "Unknown\n"); - break; - case 3: len += sprintf(buf+len, "Low Catastrophic (LoCat)\n"); - break; - case 4: len += sprintf(buf+len, "Low (Low)\n"); - break; - case 5: len += sprintf(buf+len, "Low Warning (LoWarn)\n"); - break; - case 6: len += sprintf(buf+len, "High Warning (HiWarn)\n"); - break; - case 7: len += sprintf(buf+len, "High (High)\n"); - break; - case 8: len += sprintf(buf+len, "High Catastrophic (HiCat)\n"); - break; - } - - len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable); - len += sprintf(buf+len, " [%s] Operational state change. \n", - (result.event_enable & 0x01) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] Low catastrophic. \n", - (result.event_enable & 0x02) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] Low reading. \n", - (result.event_enable & 0x04) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] Low warning. \n", - (result.event_enable & 0x08) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] Change back to normal from out of range state. \n", - (result.event_enable & 0x10) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] High warning. \n", - (result.event_enable & 0x20) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] High reading. \n", - (result.event_enable & 0x40) ? "+" : "-" ); - len += sprintf(buf+len, " [%s] High catastrophic. \n", - (result.event_enable & 0x80) ? "+" : "-" ); - - spin_unlock(&i2o_proc_lock); - return len; + seq_printf(seq, "Sensor state : %d = ", result.sensor_state); + switch (result.sensor_state) { + case 0: + seq_printf(seq, "Normal\n"); + break; + case 1: + seq_printf(seq, "Abnormal\n"); + break; + case 2: + seq_printf(seq, "Unknown\n"); + break; + case 3: + seq_printf(seq, "Low Catastrophic (LoCat)\n"); + break; + case 4: + seq_printf(seq, "Low (Low)\n"); + break; + case 5: + seq_printf(seq, "Low Warning (LoWarn)\n"); + break; + case 6: + seq_printf(seq, "High Warning (HiWarn)\n"); + break; + case 7: + seq_printf(seq, "High (High)\n"); + break; + case 8: + seq_printf(seq, "High Catastrophic (HiCat)\n"); + break; + } + + seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable); + seq_printf(seq, " [%s] Operational state change. \n", + (result.event_enable & 0x01) ? "+" : "-"); + seq_printf(seq, " [%s] Low catastrophic. \n", + (result.event_enable & 0x02) ? "+" : "-"); + seq_printf(seq, " [%s] Low reading. \n", + (result.event_enable & 0x04) ? "+" : "-"); + seq_printf(seq, " [%s] Low warning. \n", + (result.event_enable & 0x08) ? "+" : "-"); + seq_printf(seq, + " [%s] Change back to normal from out of range state. \n", + (result.event_enable & 0x10) ? "+" : "-"); + seq_printf(seq, " [%s] High warning. \n", + (result.event_enable & 0x20) ? "+" : "-"); + seq_printf(seq, " [%s] High reading. \n", + (result.event_enable & 0x40) ? "+" : "-"); + seq_printf(seq, " [%s] High catastrophic. \n", + (result.event_enable & 0x80) ? "+" : "-"); + + return 0; } +static int i2o_seq_open_hrt(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); +}; -static int print_serial_number(char *buff, int pos, u8 *serialno, int max_len) +static int i2o_seq_open_lct(struct inode *inode, struct file *file) { - int i; + return single_open(file, i2o_seq_show_lct, PDE(inode)->data); +}; - /* 19990419 -sralston - * The I2O v1.5 (and v2.0 so far) "official specification" - * got serial numbers WRONG! - * Apparently, and despite what Section 3.4.4 says and - * Figure 3-35 shows (pg 3-39 in the pdf doc), - * the convention / consensus seems to be: - * + First byte is SNFormat - * + Second byte is SNLen (but only if SNFormat==7 (?)) - * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format - */ - switch(serialno[0]) - { - case I2O_SNFORMAT_BINARY: /* Binary */ - pos += sprintf(buff+pos, "0x"); - for(i = 0; i < serialno[1]; i++) - { - pos += sprintf(buff+pos, "%02X", serialno[2+i]); - } - break; - - case I2O_SNFORMAT_ASCII: /* ASCII */ - if ( serialno[1] < ' ' ) /* printable or SNLen? */ - { - /* sanity */ - max_len = (max_len < serialno[1]) ? max_len : serialno[1]; - serialno[1+max_len] = '\0'; - - /* just print it */ - pos += sprintf(buff+pos, "%s", &serialno[2]); - } - else - { - /* print chars for specified length */ - for(i = 0; i < serialno[1]; i++) - { - pos += sprintf(buff+pos, "%c", serialno[2+i]); - } - } - break; +static int i2o_seq_open_status(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_status, PDE(inode)->data); +}; - case I2O_SNFORMAT_UNICODE: /* UNICODE */ - pos += sprintf(buff+pos, "UNICODE Format. Can't Display\n"); - break; +static int i2o_seq_open_hw(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hw, PDE(inode)->data); +}; - case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ - pos += sprintf(buff+pos, - "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X", - serialno[2], serialno[3], - serialno[4], serialno[5], - serialno[6], serialno[7]); - break; +static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data); +}; - case I2O_SNFORMAT_WAN: /* WAN MAC Address */ - /* FIXME: Figure out what a WAN access address looks like?? */ - pos += sprintf(buff+pos, "WAN Access Address"); - break; +static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data); +}; -/* plus new in v2.0 */ - case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ - /* FIXME: Figure out what a LAN-64 address really looks like?? */ - pos += sprintf(buff+pos, - "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X", - serialno[8], serialno[9], - serialno[2], serialno[3], - serialno[4], serialno[5], - serialno[6], serialno[7]); - break; +static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data); +}; +static int i2o_seq_open_groups(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_groups, PDE(inode)->data); +}; - case I2O_SNFORMAT_DDM: /* I2O DDM */ - pos += sprintf(buff+pos, - "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", - *(u16*)&serialno[2], - *(u16*)&serialno[4], - *(u16*)&serialno[6]); - break; +static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data); +}; - case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ - case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ - /* FIXME: Figure if this is even close?? */ - pos += sprintf(buff+pos, - "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", - *(u32*)&serialno[2], - *(u32*)&serialno[6], - *(u32*)&serialno[10], - *(u32*)&serialno[14]); - break; +static int i2o_seq_open_claimed(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_claimed, PDE(inode)->data); +}; +static int i2o_seq_open_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_users, PDE(inode)->data); +}; - case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ - case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ - default: - pos += sprintf(buff+pos, "Unknown data format (0x%02x)", - serialno[0]); - break; - } +static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data); +}; - return pos; -} +static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_authorized_users, + PDE(inode)->data); +}; -const char * i2o_get_connector_type(int conn) +static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) { - int idx = 16; - static char *i2o_connector_type[] = { - "OTHER", - "UNKNOWN", - "AUI", - "UTP", - "BNC", - "RJ45", - "STP DB9", - "FIBER MIC", - "APPLE AUI", - "MII", - "DB9", - "HSSDC", - "DUPLEX SC FIBER", - "DUPLEX ST FIBER", - "TNC/BNC", - "HW DEFAULT" - }; + return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data); +}; - switch(conn) - { - case 0x00000000: - idx = 0; - break; - case 0x00000001: - idx = 1; - break; - case 0x00000002: - idx = 2; - break; - case 0x00000003: - idx = 3; - break; - case 0x00000004: - idx = 4; - break; - case 0x00000005: - idx = 5; - break; - case 0x00000006: - idx = 6; - break; - case 0x00000007: - idx = 7; - break; - case 0x00000008: - idx = 8; - break; - case 0x00000009: - idx = 9; - break; - case 0x0000000A: - idx = 10; - break; - case 0x0000000B: - idx = 11; - break; - case 0x0000000C: - idx = 12; - break; - case 0x0000000D: - idx = 13; - break; - case 0x0000000E: - idx = 14; - break; - case 0xFFFFFFFF: - idx = 15; - break; - } +static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data); +}; - return i2o_connector_type[idx]; -} +static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data); +}; +static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data); +}; -const char * i2o_get_connection_type(int conn) +static int i2o_seq_open_sensors(struct inode *inode, struct file *file) { - int idx = 0; - static char *i2o_connection_type[] = { - "Unknown", - "AUI", - "10BASE5", - "FIORL", - "10BASE2", - "10BROAD36", - "10BASE-T", - "10BASE-FP", - "10BASE-FB", - "10BASE-FL", - "100BASE-TX", - "100BASE-FX", - "100BASE-T4", - "1000BASE-SX", - "1000BASE-LX", - "1000BASE-CX", - "1000BASE-T", - "100VG-ETHERNET", - "100VG-TOKEN RING", - "4MBIT TOKEN RING", - "16 Mb Token Ring", - "125 MBAUD FDDI", - "Point-to-point", - "Arbitrated loop", - "Public loop", - "Fabric", - "Emulation", - "Other", - "HW default" - }; + return single_open(file, i2o_seq_show_sensors, PDE(inode)->data); +}; - switch(conn) - { - case I2O_LAN_UNKNOWN: - idx = 0; - break; - case I2O_LAN_AUI: - idx = 1; - break; - case I2O_LAN_10BASE5: - idx = 2; - break; - case I2O_LAN_FIORL: - idx = 3; - break; - case I2O_LAN_10BASE2: - idx = 4; - break; - case I2O_LAN_10BROAD36: - idx = 5; - break; - case I2O_LAN_10BASE_T: - idx = 6; - break; - case I2O_LAN_10BASE_FP: - idx = 7; - break; - case I2O_LAN_10BASE_FB: - idx = 8; - break; - case I2O_LAN_10BASE_FL: - idx = 9; - break; - case I2O_LAN_100BASE_TX: - idx = 10; - break; - case I2O_LAN_100BASE_FX: - idx = 11; - break; - case I2O_LAN_100BASE_T4: - idx = 12; - break; - case I2O_LAN_1000BASE_SX: - idx = 13; - break; - case I2O_LAN_1000BASE_LX: - idx = 14; - break; - case I2O_LAN_1000BASE_CX: - idx = 15; - break; - case I2O_LAN_1000BASE_T: - idx = 16; - break; - case I2O_LAN_100VG_ETHERNET: - idx = 17; - break; - case I2O_LAN_100VG_TR: - idx = 18; - break; - case I2O_LAN_4MBIT: - idx = 19; - break; - case I2O_LAN_16MBIT: - idx = 20; - break; - case I2O_LAN_125MBAUD: - idx = 21; - break; - case I2O_LAN_POINT_POINT: - idx = 22; - break; - case I2O_LAN_ARB_LOOP: - idx = 23; - break; - case I2O_LAN_PUBLIC_LOOP: - idx = 24; - break; - case I2O_LAN_FABRIC: - idx = 25; - break; - case I2O_LAN_EMULATION: - idx = 26; - break; - case I2O_LAN_OTHER: - idx = 27; - break; - case I2O_LAN_DEFAULT: - idx = 28; - break; - } - - return i2o_connection_type[idx]; -} - - -/* LAN group 0000h - Device info (scalar) */ -int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[56]; - static u8 *work8 = (u8*)work32; - static u16 *work16 = (u16*)work32; - static u64 *work64 = (u64*)work32; - int token; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0000, -1, &work32, 56*4); - if (token < 0) { - len += i2o_report_query_status(buf+len, token, "0x0000 LAN Device Info"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "LAN Type : "); - switch (work16[0]) - { - case 0x0030: - len += sprintf(buf+len, "Ethernet, "); - break; - case 0x0040: - len += sprintf(buf+len, "100Base VG, "); - break; - case 0x0050: - len += sprintf(buf+len, "Token Ring, "); - break; - case 0x0060: - len += sprintf(buf+len, "FDDI, "); - break; - case 0x0070: - len += sprintf(buf+len, "Fibre Channel, "); - break; - default: - len += sprintf(buf+len, "Unknown type (0x%04x), ", work16[0]); - break; - } - - if (work16[1]&0x00000001) - len += sprintf(buf+len, "emulated LAN, "); - else - len += sprintf(buf+len, "physical LAN port, "); - - if (work16[1]&0x00000002) - len += sprintf(buf+len, "full duplex\n"); - else - len += sprintf(buf+len, "simplex\n"); - - len += sprintf(buf+len, "Address format : "); - switch(work8[4]) { - case 0x00: - len += sprintf(buf+len, "IEEE 48bit\n"); - break; - case 0x01: - len += sprintf(buf+len, "FC IEEE\n"); - break; - default: - len += sprintf(buf+len, "Unknown (0x%02x)\n", work8[4]); - break; - } - - len += sprintf(buf+len, "State : "); - switch(work8[5]) - { - case 0x00: - len += sprintf(buf+len, "Unknown\n"); - break; - case 0x01: - len += sprintf(buf+len, "Unclaimed\n"); - break; - case 0x02: - len += sprintf(buf+len, "Operational\n"); - break; - case 0x03: - len += sprintf(buf+len, "Suspended\n"); - break; - case 0x04: - len += sprintf(buf+len, "Resetting\n"); - break; - case 0x05: - len += sprintf(buf+len, "ERROR: "); - if(work16[3]&0x0001) - len += sprintf(buf+len, "TxCU inoperative "); - if(work16[3]&0x0002) - len += sprintf(buf+len, "RxCU inoperative "); - if(work16[3]&0x0004) - len += sprintf(buf+len, "Local mem alloc "); - len += sprintf(buf+len, "\n"); - break; - case 0x06: - len += sprintf(buf+len, "Operational no Rx\n"); - break; - case 0x07: - len += sprintf(buf+len, "Suspended no Rx\n"); - break; - default: - len += sprintf(buf+len, "Unspecified\n"); - break; - } - - len += sprintf(buf+len, "Min packet size : %d\n", work32[2]); - len += sprintf(buf+len, "Max packet size : %d\n", work32[3]); - len += sprintf(buf+len, "HW address : " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - work8[16],work8[17],work8[18],work8[19], - work8[20],work8[21],work8[22],work8[23]); - - len += sprintf(buf+len, "Max Tx wire speed : %d bps\n", (int)work64[3]); - len += sprintf(buf+len, "Max Rx wire speed : %d bps\n", (int)work64[4]); - - len += sprintf(buf+len, "Min SDU packet size : 0x%08x\n", work32[10]); - len += sprintf(buf+len, "Max SDU packet size : 0x%08x\n", work32[11]); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0001h - MAC address table (scalar) */ -int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[48]; - static u8 *work8 = (u8*)work32; - int token; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0001, -1, &work32, 48*4); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0001 LAN MAC Address"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "Active address : " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - work8[0],work8[1],work8[2],work8[3], - work8[4],work8[5],work8[6],work8[7]); - len += sprintf(buf+len, "Current address : " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - work8[8],work8[9],work8[10],work8[11], - work8[12],work8[13],work8[14],work8[15]); - len += sprintf(buf+len, "Functional address mask : " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - work8[16],work8[17],work8[18],work8[19], - work8[20],work8[21],work8[22],work8[23]); - - len += sprintf(buf+len,"HW/DDM capabilities : 0x%08x\n", work32[7]); - len += sprintf(buf+len," [%s] Unicast packets supported\n", - (work32[7]&0x00000001)?"+":"-"); - len += sprintf(buf+len," [%s] Promiscuous mode supported\n", - (work32[7]&0x00000002)?"+":"-"); - len += sprintf(buf+len," [%s] Promiscuous multicast mode supported\n", - (work32[7]&0x00000004)?"+":"-"); - len += sprintf(buf+len," [%s] Broadcast reception disabling supported\n", - (work32[7]&0x00000100)?"+":"-"); - len += sprintf(buf+len," [%s] Multicast reception disabling supported\n", - (work32[7]&0x00000200)?"+":"-"); - len += sprintf(buf+len," [%s] Functional address disabling supported\n", - (work32[7]&0x00000400)?"+":"-"); - len += sprintf(buf+len," [%s] MAC reporting supported\n", - (work32[7]&0x00000800)?"+":"-"); - - len += sprintf(buf+len,"Filter mask : 0x%08x\n", work32[6]); - len += sprintf(buf+len," [%s] Unicast packets disable\n", - (work32[6]&0x00000001)?"+":"-"); - len += sprintf(buf+len," [%s] Promiscuous mode enable\n", - (work32[6]&0x00000002)?"+":"-"); - len += sprintf(buf+len," [%s] Promiscuous multicast mode enable\n", - (work32[6]&0x00000004)?"+":"-"); - len += sprintf(buf+len," [%s] Broadcast packets disable\n", - (work32[6]&0x00000100)?"+":"-"); - len += sprintf(buf+len," [%s] Multicast packets disable\n", - (work32[6]&0x00000200)?"+":"-"); - len += sprintf(buf+len," [%s] Functional address disable\n", - (work32[6]&0x00000400)?"+":"-"); - - if (work32[7]&0x00000800) { - len += sprintf(buf+len, " MAC reporting mode : "); - if (work32[6]&0x00000800) - len += sprintf(buf+len, "Pass only priority MAC packets to user\n"); - else if (work32[6]&0x00001000) - len += sprintf(buf+len, "Pass all MAC packets to user\n"); - else if (work32[6]&0x00001800) - len += sprintf(buf+len, "Pass all MAC packets (promiscuous) to user\n"); - else - len += sprintf(buf+len, "Do not pass MAC packets to user\n"); - } - len += sprintf(buf+len, "Number of multicast addresses : %d\n", work32[8]); - len += sprintf(buf+len, "Perfect filtering for max %d multicast addresses\n", - work32[9]); - len += sprintf(buf+len, "Imperfect filtering for max %d multicast addresses\n", - work32[10]); - - spin_unlock(&i2o_proc_lock); - - return len; -} - -/* LAN group 0002h - Multicast MAC address table (table) */ -int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) { - struct i2o_device *d = (struct i2o_device*)data; - int token; - int i; - u8 mc_addr[8]; - - struct - { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - u8 mc_addr[256][8]; - } *result; - - result = kmalloc(sizeof(*result), GFP_KERNEL); - if(!result) - return -ENOMEM; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, 0x0002, -1, - NULL, 0, result, sizeof(*result)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address"); - goto out; - } - - for (i = 0; i < result->row_count; i++) - { - memcpy(mc_addr, result->mc_addr[i], 8); - - len += sprintf(buf+len, "MC MAC address[%d]: " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - i, mc_addr[0], mc_addr[1], mc_addr[2], - mc_addr[3], mc_addr[4], mc_addr[5], - mc_addr[6], mc_addr[7]); - } -out: - spin_unlock(&i2o_proc_lock); - kfree(result); - return len; -} - -/* LAN group 0003h - Batch Control (scalar) */ -int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[9]; - int token; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0003, -1, &work32, 9*4); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0003 LAN Batch Control"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "Batch mode "); - if (work32[0]&0x00000001) - len += sprintf(buf+len, "disabled"); - else - len += sprintf(buf+len, "enabled"); - if (work32[0]&0x00000002) - len += sprintf(buf+len, " (current setting)"); - if (work32[0]&0x00000004) - len += sprintf(buf+len, ", forced"); - else - len += sprintf(buf+len, ", toggle"); - len += sprintf(buf+len, "\n"); - - len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]); - len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]); - len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]); - len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0004h - LAN Operation (scalar) */ -int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[5]; - int token; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0004, -1, &work32, 20); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0004 LAN Operation"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "Packet prepadding (32b words) : %d\n", work32[0]); - len += sprintf(buf+len, "Transmission error reporting : %s\n", - (work32[1]&1)?"on":"off"); - len += sprintf(buf+len, "Bad packet handling : %s\n", - (work32[1]&0x2)?"by host":"by DDM"); - len += sprintf(buf+len, "Packet orphan limit : %d\n", work32[2]); - - len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]); - len += sprintf(buf+len, " [%s] HW CRC suppression\n", - (work32[3]&0x00000004) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW IPv4 checksum\n", - (work32[3]&0x00000100) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW TCP checksum\n", - (work32[3]&0x00000200) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW UDP checksum\n", - (work32[3]&0x00000400) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW RSVP checksum\n", - (work32[3]&0x00000800) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW ICMP checksum\n", - (work32[3]&0x00001000) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Loopback suppression enable\n", - (work32[3]&0x00002000) ? "+" : "-"); - - len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]); - len += sprintf(buf+len, " [%s] FCS in payload\n", - (work32[4]&0x00000004) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW IPv4 checksum validation\n", - (work32[4]&0x00000100) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW TCP checksum validation\n", - (work32[4]&0x00000200) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW UDP checksum validation\n", - (work32[4]&0x00000400) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW RSVP checksum validation\n", - (work32[4]&0x00000800) ? "+" : "-"); - len += sprintf(buf+len, " [%s] HW ICMP checksum validation\n", - (work32[4]&0x00001000) ? "+" : "-"); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0005h - Media operation (scalar) */ -int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - int token; - - struct - { - u32 connector_type; - u32 connection_type; - u64 current_tx_wire_speed; - u64 current_rx_wire_speed; - u8 duplex_mode; - u8 link_status; - u8 reserved; - u8 duplex_mode_target; - u32 connector_type_target; - u32 connection_type_target; - } result; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0005, -1, &result, sizeof(result)); - if (token < 0) { - len += i2o_report_query_status(buf+len, token, "0x0005 LAN Media Operation"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "Connector type : %s\n", - i2o_get_connector_type(result.connector_type)); - len += sprintf(buf+len, "Connection type : %s\n", - i2o_get_connection_type(result.connection_type)); - - len += sprintf(buf+len, "Current Tx wire speed : %d bps\n", (int)result.current_tx_wire_speed); - len += sprintf(buf+len, "Current Rx wire speed : %d bps\n", (int)result.current_rx_wire_speed); - len += sprintf(buf+len, "Duplex mode : %s duplex\n", - (result.duplex_mode)?"Full":"Half"); - - len += sprintf(buf+len, "Link status : "); - switch (result.link_status) - { - case 0x00: - len += sprintf(buf+len, "Unknown\n"); - break; - case 0x01: - len += sprintf(buf+len, "Normal\n"); - break; - case 0x02: - len += sprintf(buf+len, "Failure\n"); - break; - case 0x03: - len += sprintf(buf+len, "Reset\n"); - break; - default: - len += sprintf(buf+len, "Unspecified\n"); - } - - len += sprintf(buf+len, "Duplex mode target : "); - switch (result.duplex_mode_target){ - case 0: - len += sprintf(buf+len, "Half duplex\n"); - break; - case 1: - len += sprintf(buf+len, "Full duplex\n"); - break; - default: - len += sprintf(buf+len, "\n"); - } - - len += sprintf(buf+len, "Connector type target : %s\n", - i2o_get_connector_type(result.connector_type_target)); - len += sprintf(buf+len, "Connection type target : %s\n", - i2o_get_connection_type(result.connection_type_target)); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0006h - Alternate address (table) (optional) */ -int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - int token; - int i; - u8 alt_addr[8]; - struct - { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - u8 alt_addr[256][8]; - } *result; - - result = kmalloc(sizeof(*result), GFP_KERNEL); - if(!result) - return -ENOMEM; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data.tid, - 0x0006, -1, NULL, 0, result, sizeof(*result)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)"); - goto out; - } - - for (i=0; i < result->row_count; i++) - { - memcpy(alt_addr,result->alt_addr[i],8); - len += sprintf(buf+len, "Alternate address[%d]: " - "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - i, alt_addr[0], alt_addr[1], alt_addr[2], - alt_addr[3], alt_addr[4], alt_addr[5], - alt_addr[6], alt_addr[7]); - } -out: - spin_unlock(&i2o_proc_lock); - kfree(result); - return len; -} + return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data); +}; +static struct file_operations i2o_seq_fops_lct = { + .open = i2o_seq_open_lct, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -/* LAN group 0007h - Transmit info (scalar) */ -int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[8]; - int token; +static struct file_operations i2o_seq_fops_hrt = { + .open = i2o_seq_open_hrt, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - spin_lock(&i2o_proc_lock); - len = 0; +static struct file_operations i2o_seq_fops_status = { + .open = i2o_seq_open_status, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0007, -1, &work32, 8*4); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0007 LAN Transmit Info"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_hw = { + .open = i2o_seq_open_hw, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - len += sprintf(buf, "Tx Max SG elements per packet : %d\n", work32[0]); - len += sprintf(buf+len, "Tx Max SG elements per chain : %d\n", work32[1]); - len += sprintf(buf+len, "Tx Max outstanding packets : %d\n", work32[2]); - len += sprintf(buf+len, "Tx Max packets per request : %d\n", work32[3]); - - len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[4]); - len += sprintf(buf+len, " [%s] No DA in SGL\n", - (work32[4]&0x00000002) ? "+" : "-"); - len += sprintf(buf+len, " [%s] CRC suppression\n", - (work32[4]&0x00000004) ? "+" : "-"); - len += sprintf(buf+len, " [%s] MAC insertion\n", - (work32[4]&0x00000010) ? "+" : "-"); - len += sprintf(buf+len, " [%s] RIF insertion\n", - (work32[4]&0x00000020) ? "+" : "-"); - len += sprintf(buf+len, " [%s] IPv4 checksum generation\n", - (work32[4]&0x00000100) ? "+" : "-"); - len += sprintf(buf+len, " [%s] TCP checksum generation\n", - (work32[4]&0x00000200) ? "+" : "-"); - len += sprintf(buf+len, " [%s] UDP checksum generation\n", - (work32[4]&0x00000400) ? "+" : "-"); - len += sprintf(buf+len, " [%s] RSVP checksum generation\n", - (work32[4]&0x00000800) ? "+" : "-"); - len += sprintf(buf+len, " [%s] ICMP checksum generation\n", - (work32[4]&0x00001000) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Loopback enabled\n", - (work32[4]&0x00010000) ? "+" : "-"); - len += sprintf(buf+len, " [%s] Loopback suppression enabled\n", - (work32[4]&0x00020000) ? "+" : "-"); - - spin_unlock(&i2o_proc_lock); - return len; -} +static struct file_operations i2o_seq_fops_ddm_table = { + .open = i2o_seq_open_ddm_table, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -/* LAN group 0008h - Receive info (scalar) */ -int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[8]; - int token; +static struct file_operations i2o_seq_fops_driver_store = { + .open = i2o_seq_open_driver_store, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - spin_lock(&i2o_proc_lock); - len = 0; +static struct file_operations i2o_seq_fops_drivers_stored = { + .open = i2o_seq_open_drivers_stored, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0008, -1, &work32, 8*4); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0008 LAN Receive Info"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_groups = { + .open = i2o_seq_open_groups, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - len += sprintf(buf ,"Rx Max size of chain element : %d\n", work32[0]); - len += sprintf(buf+len, "Rx Max Buckets : %d\n", work32[1]); - len += sprintf(buf+len, "Rx Max Buckets in Reply : %d\n", work32[3]); - len += sprintf(buf+len, "Rx Max Packets in Bucket : %d\n", work32[4]); - len += sprintf(buf+len, "Rx Max Buckets in Post : %d\n", work32[5]); - - len += sprintf(buf+len, "Rx Modes : 0x%08x\n", work32[2]); - len += sprintf(buf+len, " [%s] FCS reception\n", - (work32[2]&0x00000004) ? "+" : "-"); - len += sprintf(buf+len, " [%s] IPv4 checksum validation \n", - (work32[2]&0x00000100) ? "+" : "-"); - len += sprintf(buf+len, " [%s] TCP checksum validation \n", - (work32[2]&0x00000200) ? "+" : "-"); - len += sprintf(buf+len, " [%s] UDP checksum validation \n", - (work32[2]&0x00000400) ? "+" : "-"); - len += sprintf(buf+len, " [%s] RSVP checksum validation \n", - (work32[2]&0x00000800) ? "+" : "-"); - len += sprintf(buf+len, " [%s] ICMP checksum validation \n", - (work32[2]&0x00001000) ? "+" : "-"); - - spin_unlock(&i2o_proc_lock); - return len; -} +static struct file_operations i2o_seq_fops_phys_device = { + .open = i2o_seq_open_phys_device, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -static int i2o_report_opt_field(char *buf, char *field_name, - int field_nbr, int supp_fields, u64 *value) -{ - if (supp_fields & (1 << field_nbr)) - return sprintf(buf, "%-24s : " FMT_U64_HEX "\n", field_name, U64_VAL(value)); - else - return sprintf(buf, "%-24s : Not supported\n", field_name); -} +static struct file_operations i2o_seq_fops_claimed = { + .open = i2o_seq_open_claimed, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -/* LAN group 0100h - LAN Historical statistics (scalar) */ -/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */ -/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics (scalar) */ -/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics (scalar) */ +static struct file_operations i2o_seq_fops_users = { + .open = i2o_seq_open_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len, - int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - int token; +static struct file_operations i2o_seq_fops_priv_msgs = { + .open = i2o_seq_open_priv_msgs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - struct - { - u64 tx_packets; - u64 tx_bytes; - u64 rx_packets; - u64 rx_bytes; - u64 tx_errors; - u64 rx_errors; - u64 rx_dropped; - u64 adapter_resets; - u64 adapter_suspends; - } stats; // 0x0100 - - static u64 supp_groups[4]; // 0x0180 - - struct - { - u64 tx_retries; - u64 tx_directed_bytes; - u64 tx_directed_packets; - u64 tx_multicast_bytes; - u64 tx_multicast_packets; - u64 tx_broadcast_bytes; - u64 tx_broadcast_packets; - u64 tx_group_addr_packets; - u64 tx_short_packets; - } tx_stats; // 0x0182 - - struct - { - u64 rx_crc_errors; - u64 rx_directed_bytes; - u64 rx_directed_packets; - u64 rx_multicast_bytes; - u64 rx_multicast_packets; - u64 rx_broadcast_bytes; - u64 rx_broadcast_packets; - u64 rx_group_addr_packets; - u64 rx_short_packets; - u64 rx_long_packets; - u64 rx_runt_packets; - } rx_stats; // 0x0183 - - struct - { - u64 ipv4_generate; - u64 ipv4_validate_success; - u64 ipv4_validate_errors; - u64 tcp_generate; - u64 tcp_validate_success; - u64 tcp_validate_errors; - u64 udp_generate; - u64 udp_validate_success; - u64 udp_validate_errors; - u64 rsvp_generate; - u64 rsvp_validate_success; - u64 rsvp_validate_errors; - u64 icmp_generate; - u64 icmp_validate_success; - u64 icmp_validate_errors; - } chksum_stats; // 0x0184 - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0100, -1, &stats, sizeof(stats)); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x100 LAN Statistics"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_authorized_users = { + .open = i2o_seq_open_authorized_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - len += sprintf(buf+len, "Tx packets : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_packets)); - len += sprintf(buf+len, "Tx bytes : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_bytes)); - len += sprintf(buf+len, "Rx packets : " FMT_U64_HEX "\n", - U64_VAL(&stats.rx_packets)); - len += sprintf(buf+len, "Rx bytes : " FMT_U64_HEX "\n", - U64_VAL(&stats.rx_bytes)); - len += sprintf(buf+len, "Tx errors : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_errors)); - len += sprintf(buf+len, "Rx errors : " FMT_U64_HEX "\n", - U64_VAL(&stats.rx_errors)); - len += sprintf(buf+len, "Rx dropped : " FMT_U64_HEX "\n", - U64_VAL(&stats.rx_dropped)); - len += sprintf(buf+len, "Adapter resets : " FMT_U64_HEX "\n", - U64_VAL(&stats.adapter_resets)); - len += sprintf(buf+len, "Adapter suspends : " FMT_U64_HEX "\n", - U64_VAL(&stats.adapter_suspends)); - - /* Optional statistics follows */ - /* Get 0x0180 to see which optional groups/fields are supported */ - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0180, -1, &supp_groups, sizeof(supp_groups)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token, "0x180 LAN Supported Optional Statistics"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_dev_name = { + .open = i2o_seq_open_dev_name, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - if (supp_groups[1]) /* 0x0182 */ - { - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0182, -1, &tx_stats, sizeof(tx_stats)); +static struct file_operations i2o_seq_fops_dev_identity = { + .open = i2o_seq_open_dev_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x182 LAN Optional Tx Historical Statistics"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_ddm_identity = { + .open = i2o_seq_open_ddm_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - len += sprintf(buf+len, "==== Optional TX statistics (group 0182h)\n"); - - len += i2o_report_opt_field(buf+len, "Tx RetryCount", - 0, supp_groups[1], &tx_stats.tx_retries); - len += i2o_report_opt_field(buf+len, "Tx DirectedBytes", - 1, supp_groups[1], &tx_stats.tx_directed_bytes); - len += i2o_report_opt_field(buf+len, "Tx DirectedPackets", - 2, supp_groups[1], &tx_stats.tx_directed_packets); - len += i2o_report_opt_field(buf+len, "Tx MulticastBytes", - 3, supp_groups[1], &tx_stats.tx_multicast_bytes); - len += i2o_report_opt_field(buf+len, "Tx MulticastPackets", - 4, supp_groups[1], &tx_stats.tx_multicast_packets); - len += i2o_report_opt_field(buf+len, "Tx BroadcastBytes", - 5, supp_groups[1], &tx_stats.tx_broadcast_bytes); - len += i2o_report_opt_field(buf+len, "Tx BroadcastPackets", - 6, supp_groups[1], &tx_stats.tx_broadcast_packets); - len += i2o_report_opt_field(buf+len, "Tx TotalGroupAddrPackets", - 7, supp_groups[1], &tx_stats.tx_group_addr_packets); - len += i2o_report_opt_field(buf+len, "Tx TotalPacketsTooShort", - 8, supp_groups[1], &tx_stats.tx_short_packets); - } +static struct file_operations i2o_seq_fops_uinfo = { + .open = i2o_seq_open_uinfo, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - if (supp_groups[2]) /* 0x0183 */ - { - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0183, -1, &rx_stats, sizeof(rx_stats)); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x183 LAN Optional Rx Historical Stats"); - spin_unlock(&i2o_proc_lock); - return len; - } +static struct file_operations i2o_seq_fops_sgl_limits = { + .open = i2o_seq_open_sgl_limits, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - len += sprintf(buf+len, "==== Optional RX statistics (group 0183h)\n"); - - len += i2o_report_opt_field(buf+len, "Rx CRCErrorCount", - 0, supp_groups[2], &rx_stats.rx_crc_errors); - len += i2o_report_opt_field(buf+len, "Rx DirectedBytes", - 1, supp_groups[2], &rx_stats.rx_directed_bytes); - len += i2o_report_opt_field(buf+len, "Rx DirectedPackets", - 2, supp_groups[2], &rx_stats.rx_directed_packets); - len += i2o_report_opt_field(buf+len, "Rx MulticastBytes", - 3, supp_groups[2], &rx_stats.rx_multicast_bytes); - len += i2o_report_opt_field(buf+len, "Rx MulticastPackets", - 4, supp_groups[2], &rx_stats.rx_multicast_packets); - len += i2o_report_opt_field(buf+len, "Rx BroadcastBytes", - 5, supp_groups[2], &rx_stats.rx_broadcast_bytes); - len += i2o_report_opt_field(buf+len, "Rx BroadcastPackets", - 6, supp_groups[2], &rx_stats.rx_broadcast_packets); - len += i2o_report_opt_field(buf+len, "Rx TotalGroupAddrPackets", - 7, supp_groups[2], &rx_stats.rx_group_addr_packets); - len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooShort", - 8, supp_groups[2], &rx_stats.rx_short_packets); - len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooLong", - 9, supp_groups[2], &rx_stats.rx_long_packets); - len += i2o_report_opt_field(buf+len, "Rx TotalPacketsRunt", - 10, supp_groups[2], &rx_stats.rx_runt_packets); - } - - if (supp_groups[3]) /* 0x0184 */ - { - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0184, -1, &chksum_stats, sizeof(chksum_stats)); +static struct file_operations i2o_seq_fops_sensors = { + .open = i2o_seq_open_sensors, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x184 LAN Optional Chksum Historical Stats"); - spin_unlock(&i2o_proc_lock); - return len; - } +/* + * IOP specific entries...write field just in case someone + * ever wants one. + */ +static i2o_proc_entry i2o_proc_generic_iop_entries[] = { + {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt}, + {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct}, + {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status}, + {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw}, + {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table}, + {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store}, + {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored}, + {NULL, 0, NULL} +}; - len += sprintf(buf+len, "==== Optional CHKSUM statistics (group 0x0184)\n"); - - len += i2o_report_opt_field(buf+len, "IPv4 Generate", - 0, supp_groups[3], &chksum_stats.ipv4_generate); - len += i2o_report_opt_field(buf+len, "IPv4 ValidateSuccess", - 1, supp_groups[3], &chksum_stats.ipv4_validate_success); - len += i2o_report_opt_field(buf+len, "IPv4 ValidateError", - 2, supp_groups[3], &chksum_stats.ipv4_validate_errors); - len += i2o_report_opt_field(buf+len, "TCP Generate", - 3, supp_groups[3], &chksum_stats.tcp_generate); - len += i2o_report_opt_field(buf+len, "TCP ValidateSuccess", - 4, supp_groups[3], &chksum_stats.tcp_validate_success); - len += i2o_report_opt_field(buf+len, "TCP ValidateError", - 5, supp_groups[3], &chksum_stats.tcp_validate_errors); - len += i2o_report_opt_field(buf+len, "UDP Generate", - 6, supp_groups[3], &chksum_stats.udp_generate); - len += i2o_report_opt_field(buf+len, "UDP ValidateSuccess", - 7, supp_groups[3], &chksum_stats.udp_validate_success); - len += i2o_report_opt_field(buf+len, "UDP ValidateError", - 8, supp_groups[3], &chksum_stats.udp_validate_errors); - len += i2o_report_opt_field(buf+len, "RSVP Generate", - 9, supp_groups[3], &chksum_stats.rsvp_generate); - len += i2o_report_opt_field(buf+len, "RSVP ValidateSuccess", - 10, supp_groups[3], &chksum_stats.rsvp_validate_success); - len += i2o_report_opt_field(buf+len, "RSVP ValidateError", - 11, supp_groups[3], &chksum_stats.rsvp_validate_errors); - len += i2o_report_opt_field(buf+len, "ICMP Generate", - 12, supp_groups[3], &chksum_stats.icmp_generate); - len += i2o_report_opt_field(buf+len, "ICMP ValidateSuccess", - 13, supp_groups[3], &chksum_stats.icmp_validate_success); - len += i2o_report_opt_field(buf+len, "ICMP ValidateError", - 14, supp_groups[3], &chksum_stats.icmp_validate_errors); - } +/* + * Device specific entries + */ +static i2o_proc_entry generic_dev_entries[] = { + {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups}, + {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device}, + {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed}, + {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users}, + {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs}, + {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users}, + {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity}, + {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity}, + {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo}, + {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits}, + {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors}, + {NULL, 0, NULL} +}; - spin_unlock(&i2o_proc_lock); - return len; -} +/* + * Storage unit specific entries (SCSI Periph, BS) with device names + */ +static i2o_proc_entry rbs_dev_entries[] = { + {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name}, + {NULL, 0, NULL} +}; -/* LAN group 0200h - Required Ethernet Statistics (scalar) */ -/* LAN group 0280h - Optional Ethernet Statistics Supported (scalar) */ -/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */ -int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +/** + * i2o_proc_create_entries - Creates proc dir entries + * @dir: proc dir entry under which the entries should be placed + * @i2o_pe: pointer to the entries which should be added + * @data: pointer to I2O controller or device + * + * Create proc dir entries for a I2O controller or I2O device. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_create_entries(struct proc_dir_entry *dir, + i2o_proc_entry * i2o_pe, void *data) { - struct i2o_device *d = (struct i2o_device*)data; - int token; - - struct - { - u64 rx_align_errors; - u64 tx_one_collisions; - u64 tx_multiple_collisions; - u64 tx_deferred; - u64 tx_late_collisions; - u64 tx_max_collisions; - u64 tx_carrier_lost; - u64 tx_excessive_deferrals; - } stats; - - static u64 supp_fields; - struct - { - u64 rx_overrun; - u64 tx_underrun; - u64 tx_heartbeat_failure; - } hist_stats; + struct proc_dir_entry *tmp; - spin_lock(&i2o_proc_lock); - len = 0; + while (i2o_pe->name) { + tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir); + if (!tmp) + return -1; - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0200, -1, &stats, sizeof(stats)); + tmp->data = data; + tmp->proc_fops = i2o_pe->fops; - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0200 LAN Ethernet Statistics"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf+len, "Rx alignment errors : " FMT_U64_HEX "\n", - U64_VAL(&stats.rx_align_errors)); - len += sprintf(buf+len, "Tx one collisions : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_one_collisions)); - len += sprintf(buf+len, "Tx multicollisions : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_multiple_collisions)); - len += sprintf(buf+len, "Tx deferred : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_deferred)); - len += sprintf(buf+len, "Tx late collisions : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_late_collisions)); - len += sprintf(buf+len, "Tx max collisions : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_max_collisions)); - len += sprintf(buf+len, "Tx carrier lost : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_carrier_lost)); - len += sprintf(buf+len, "Tx excessive deferrals : " FMT_U64_HEX "\n", - U64_VAL(&stats.tx_excessive_deferrals)); - - /* Optional Ethernet statistics follows */ - /* Get 0x0280 to see which optional fields are supported */ - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0280, -1, &supp_fields, sizeof(supp_fields)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0280 LAN Supported Optional Ethernet Statistics"); - spin_unlock(&i2o_proc_lock); - return len; + i2o_pe++; } - if (supp_fields) /* 0x0281 */ - { - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0281, -1, &stats, sizeof(stats)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0281 LAN Optional Ethernet Statistics"); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf+len, "==== Optional ETHERNET statistics (group 0x0281)\n"); - - len += i2o_report_opt_field(buf+len, "Rx Overrun", - 0, supp_fields, &hist_stats.rx_overrun); - len += i2o_report_opt_field(buf+len, "Tx Underrun", - 1, supp_fields, &hist_stats.tx_underrun); - len += i2o_report_opt_field(buf+len, "Tx HeartbeatFailure", - 2, supp_fields, &hist_stats.tx_heartbeat_failure); - } - - spin_unlock(&i2o_proc_lock); - return len; + return 0; } -/* LAN group 0300h - Required Token Ring Statistics (scalar) */ -/* LAN group 0380h, 0381h - Optional Statistics not yet defined (TODO) */ -int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +/** + * i2o_proc_subdir_remove - Remove child entries from a proc entry + * @dir: proc dir entry from which the childs should be removed + * + * Iterate over each i2o proc entry under dir and remove it. If the child + * also has entries, remove them too. + */ +static void i2o_proc_subdir_remove(struct proc_dir_entry *dir) { - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[13]; - int token; - - static char *ring_status[] = - { - "", - "", - "", - "", - "", - "Ring Recovery", - "Single Station", - "Counter Overflow", - "Remove Received", - "", - "Auto-Removal Error 1", - "Lobe Wire Fault", - "Transmit Beacon", - "Soft Error", - "Hard Error", - "Signal Loss" - }; - - spin_lock(&i2o_proc_lock); - len = 0; - - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0300, -1, &work64, sizeof(work64)); - - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0300 Token Ring Statistics"); - spin_unlock(&i2o_proc_lock); - return len; + struct proc_dir_entry *pe, *tmp; + pe = dir->subdir; + while (pe) { + tmp = pe->next; + i2o_proc_subdir_remove(pe); + remove_proc_entry(pe->name, dir); + pe = tmp; } +}; - len += sprintf(buf, "LineErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); - len += sprintf(buf+len, "LostFrames : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); - len += sprintf(buf+len, "ACError : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); - len += sprintf(buf+len, "TxAbortDelimiter : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); - len += sprintf(buf+len, "BursErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); - len += sprintf(buf+len, "FrameCopiedErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[5])); - len += sprintf(buf+len, "FrequencyErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); - len += sprintf(buf+len, "InternalErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); - len += sprintf(buf+len, "LastRingStatus : %s\n", ring_status[work64[8]]); - len += sprintf(buf+len, "TokenError : " FMT_U64_HEX "\n", - U64_VAL(&work64[9])); - len += sprintf(buf+len, "UpstreamNodeAddress : " FMT_U64_HEX "\n", - U64_VAL(&work64[10])); - len += sprintf(buf+len, "LastRingID : " FMT_U64_HEX "\n", - U64_VAL(&work64[11])); - len += sprintf(buf+len, "LastBeaconType : " FMT_U64_HEX "\n", - U64_VAL(&work64[12])); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0400h - Required FDDI Statistics (scalar) */ -/* LAN group 0480h, 0481h - Optional Statistics, not yet defined (TODO) */ -int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +/** + * i2o_proc_device_add - Add an I2O device to the proc dir + * @dir: proc dir entry to which the device should be added + * @dev: I2O device which should be added + * + * Add an I2O device to the proc dir entry dir and create the entries for + * the device depending on the class of the I2O device. + */ +static void i2o_proc_device_add(struct proc_dir_entry *dir, + struct i2o_device *dev) { - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[11]; - int token; - - static char *conf_state[] = - { - "Isolated", - "Local a", - "Local b", - "Local ab", - "Local s", - "Wrap a", - "Wrap b", - "Wrap ab", - "Wrap s", - "C-Wrap a", - "C-Wrap b", - "C-Wrap s", - "Through", - }; - - static char *ring_state[] = - { - "Isolated", - "Non-op", - "Rind-op", - "Detect", - "Non-op-Dup", - "Ring-op-Dup", - "Directed", - "Trace" - }; - - static char *link_state[] = - { - "Off", - "Break", - "Trace", - "Connect", - "Next", - "Signal", - "Join", - "Verify", - "Active", - "Maintenance" - }; + char buff[10]; + struct proc_dir_entry *devdir; + i2o_proc_entry *i2o_pe = NULL; - spin_lock(&i2o_proc_lock); - len = 0; + sprintf(buff, "%03x", dev->lct_data.tid); - token = i2o_query_scalar(d->controller, d->lct_data.tid, - 0x0400, -1, &work64, sizeof(work64)); + pr_debug("Adding device /proc/i2o/iop%d/%s\n", dev->iop->unit, buff); - if (token < 0) { - len += i2o_report_query_status(buf+len, token,"0x0400 FDDI Required Statistics"); - spin_unlock(&i2o_proc_lock); - return len; + devdir = proc_mkdir(buff, dir); + if (!devdir) { + printk(KERN_WARNING "i2o: Could not allocate procdir!\n"); + return; } - len += sprintf(buf+len, "ConfigurationState : %s\n", conf_state[work64[0]]); - len += sprintf(buf+len, "UpstreamNode : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); - len += sprintf(buf+len, "DownStreamNode : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); - len += sprintf(buf+len, "FrameErrors : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); - len += sprintf(buf+len, "FramesLost : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); - len += sprintf(buf+len, "RingMgmtState : %s\n", ring_state[work64[5]]); - len += sprintf(buf+len, "LCTFailures : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); - len += sprintf(buf+len, "LEMRejects : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); - len += sprintf(buf+len, "LEMCount : " FMT_U64_HEX "\n", - U64_VAL(&work64[8])); - len += sprintf(buf+len, "LConnectionState : %s\n", - link_state[work64[9]]); - - spin_unlock(&i2o_proc_lock); - return len; -} - -static int i2o_proc_create_entries(void *data, i2o_proc_entry *pentry, - struct proc_dir_entry *parent) -{ - struct proc_dir_entry *ent; - - while(pentry->name != NULL) - { - ent = create_proc_entry(pentry->name, pentry->mode, parent); - if(!ent) return -1; - - ent->data = data; - ent->read_proc = pentry->read_proc; - ent->write_proc = pentry->write_proc; - if(pentry->fops_proc) - ent->proc_fops = pentry->fops_proc; - - ent->nlink = 1; - - pentry++; - } + devdir->data = dev; - return 0; -} + i2o_proc_create_entries(devdir, generic_dev_entries, dev); -static void i2o_proc_remove_entries(i2o_proc_entry *pentry, - struct proc_dir_entry *parent) -{ - while(pentry->name != NULL) - { - remove_proc_entry(pentry->name, parent); - pentry++; + /* Inform core that we want updates about this device's status */ + switch (dev->lct_data.class_id) { + case I2O_CLASS_SCSI_PERIPHERAL: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_pe = rbs_dev_entries; + break; + default: + break; } + if (i2o_pe) + i2o_proc_create_entries(devdir, i2o_pe, dev); } -static int i2o_proc_add_controller(struct i2o_controller *pctrl, - struct proc_dir_entry *root ) +/** + * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree + * @dir: parent proc dir entry + * @c: I2O controller which should be added + * + * Add the entries to the parent proc dir entry. Also each device is added + * to the controllers proc dir entry. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_iop_add(struct proc_dir_entry *dir, + struct i2o_controller *c) { - struct proc_dir_entry *dir, *dir1; + struct proc_dir_entry *iopdir; struct i2o_device *dev; char buff[10]; - sprintf(buff, "iop%d", pctrl->unit); + snprintf(buff, 10, "iop%d", c->unit); - dir = proc_mkdir(buff, root); - if(!dir) - return -1; + pr_debug("Adding IOP /proc/i2o/%s\n", buff); - pctrl->proc_entry = dir; - - i2o_proc_create_entries(pctrl, generic_iop_entries, dir); - - for(dev = pctrl->devices; dev; dev = dev->next) - { - sprintf(buff, "%0#5x", dev->lct_data.tid); + iopdir = proc_mkdir(buff, dir); + if (!iopdir) + return -1; - dir1 = proc_mkdir(buff, dir); - dev->proc_entry = dir1; + iopdir->data = c; - if(!dir1) - printk(KERN_INFO "i2o_proc: Could not allocate proc dir\n"); + i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); - i2o_proc_add_device(dev, dir1); - } + list_for_each_entry(dev, &c->devices, list) + i2o_proc_device_add(iopdir, dev); return 0; } -void i2o_proc_new_dev(struct i2o_controller *c, struct i2o_device *d) -{ - char buff[10]; - -#ifdef DRIVERDEBUG - printk(KERN_INFO "Adding new device to /proc/i2o/iop%d\n", c->unit); -#endif - sprintf(buff, "%0#5x", d->lct_data.tid); - - d->proc_entry = proc_mkdir(buff, c->proc_entry); - - if(!d->proc_entry) - { - printk(KERN_WARNING "i2o: Could not allocate procdir!\n"); - return; - } - - i2o_proc_add_device(d, d->proc_entry); -} - -void i2o_proc_add_device(struct i2o_device *dev, struct proc_dir_entry *dir) -{ - i2o_proc_create_entries(dev, generic_dev_entries, dir); - - /* Inform core that we want updates about this device's status */ - i2o_device_notify_on(dev, &i2o_proc_handler); - switch(dev->lct_data.class_id) - { - case I2O_CLASS_SCSI_PERIPHERAL: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - i2o_proc_create_entries(dev, rbs_dev_entries, dir); - break; - case I2O_CLASS_LAN: - i2o_proc_create_entries(dev, lan_entries, dir); - switch(dev->lct_data.sub_class) - { - case I2O_LAN_ETHERNET: - i2o_proc_create_entries(dev, lan_eth_entries, dir); - break; - case I2O_LAN_FDDI: - i2o_proc_create_entries(dev, lan_fddi_entries, dir); - break; - case I2O_LAN_TR: - i2o_proc_create_entries(dev, lan_tr_entries, dir); - break; - default: - break; - } - break; - default: - break; - } -} - -static void i2o_proc_remove_controller(struct i2o_controller *pctrl, - struct proc_dir_entry *parent) -{ - char buff[10]; - struct i2o_device *dev; - - /* Remove unused device entries */ - for(dev=pctrl->devices; dev; dev=dev->next) - i2o_proc_remove_device(dev); - - if(!atomic_read(&pctrl->proc_entry->count)) - { - sprintf(buff, "iop%d", pctrl->unit); - - i2o_proc_remove_entries(generic_iop_entries, pctrl->proc_entry); - remove_proc_entry(buff, parent); - pctrl->proc_entry = NULL; - } -} - -void i2o_proc_remove_device(struct i2o_device *dev) +/** + * i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree + * @dir: parent proc dir entry + * @c: I2O controller which should be removed + * + * Iterate over each i2o proc entry and search controller c. If it is found + * remove it from the tree. + */ +static void i2o_proc_iop_remove(struct proc_dir_entry *dir, + struct i2o_controller *c) { - struct proc_dir_entry *de=dev->proc_entry; - char dev_id[10]; - - sprintf(dev_id, "%0#5x", dev->lct_data.tid); - - i2o_device_notify_off(dev, &i2o_proc_handler); - /* Would it be safe to remove _files_ even if they are in use? */ - if((de) && (!atomic_read(&de->count))) - { - i2o_proc_remove_entries(generic_dev_entries, de); - switch(dev->lct_data.class_id) - { - case I2O_CLASS_SCSI_PERIPHERAL: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - i2o_proc_remove_entries(rbs_dev_entries, de); - break; - case I2O_CLASS_LAN: - { - i2o_proc_remove_entries(lan_entries, de); - switch(dev->lct_data.sub_class) - { - case I2O_LAN_ETHERNET: - i2o_proc_remove_entries(lan_eth_entries, de); - break; - case I2O_LAN_FDDI: - i2o_proc_remove_entries(lan_fddi_entries, de); - break; - case I2O_LAN_TR: - i2o_proc_remove_entries(lan_tr_entries, de); - break; - } - } + struct proc_dir_entry *pe, *tmp; + + pe = dir->subdir; + while (pe) { + tmp = pe->next; + if (pe->data == c) { + i2o_proc_subdir_remove(pe); + remove_proc_entry(pe->name, dir); } - remove_proc_entry(dev_id, dev->controller->proc_entry); + pr_debug("Removing IOP /proc/i2o/iop%d\n", c->unit); + pe = tmp; } } - -void i2o_proc_dev_del(struct i2o_controller *c, struct i2o_device *d) -{ -#ifdef DRIVERDEBUG - printk(KERN_INFO "Deleting device %d from iop%d\n", - d->lct_data.tid, c->unit); -#endif - - i2o_proc_remove_device(d); -} -static int create_i2o_procfs(void) +/** + * i2o_proc_fs_create - Create the i2o proc fs. + * + * Iterate over each I2O controller and create the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_fs_create(void) { - struct i2o_controller *pctrl = NULL; - int i; + struct i2o_controller *c; i2o_proc_dir_root = proc_mkdir("i2o", NULL); - if(!i2o_proc_dir_root) + if (!i2o_proc_dir_root) return -1; + i2o_proc_dir_root->owner = THIS_MODULE; - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - { - pctrl = i2o_find_controller(i); - if(pctrl) - { - i2o_proc_add_controller(pctrl, i2o_proc_dir_root); - i2o_unlock_controller(pctrl); - } - }; + list_for_each_entry(c, &i2o_controllers, list) + i2o_proc_iop_add(i2o_proc_dir_root, c); return 0; -} +}; -static int __exit destroy_i2o_procfs(void) +/** + * i2o_proc_fs_destroy - Cleanup the all i2o proc entries + * + * Iterate over each I2O controller and remove the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __exit i2o_proc_fs_destroy(void) { - struct i2o_controller *pctrl = NULL; - int i; + struct i2o_controller *c; - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - { - pctrl = i2o_find_controller(i); - if(pctrl) - { - i2o_proc_remove_controller(pctrl, i2o_proc_dir_root); - i2o_unlock_controller(pctrl); - } - } + list_for_each_entry(c, &i2o_controllers, list) + i2o_proc_iop_remove(i2o_proc_dir_root, c); - if(!atomic_read(&i2o_proc_dir_root->count)) - remove_proc_entry("i2o", NULL); - else - return -1; + remove_proc_entry("i2o", NULL); return 0; -} +}; -int __init i2o_proc_init(void) +/** + * i2o_proc_init - Init function for procfs + * + * Registers Proc OSM and creates procfs entries. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_init(void) { - if (i2o_install_handler(&i2o_proc_handler) < 0) - { - printk(KERN_ERR "i2o_proc: Unable to install PROC handler.\n"); - return 0; - } + int rc; - if(create_i2o_procfs()) - return -EBUSY; + rc = i2o_driver_register(&i2o_proc_driver); + if (rc) + return rc; + + rc = i2o_proc_fs_create(); + if (rc) { + i2o_driver_unregister(&i2o_proc_driver); + return rc; + } return 0; -} +}; + +/** + * i2o_proc_exit - Exit function for procfs + * + * Unregisters Proc OSM and removes procfs entries. + */ +static void __exit i2o_proc_exit(void) +{ + i2o_driver_unregister(&i2o_proc_driver); + i2o_proc_fs_destroy(); +}; MODULE_AUTHOR("Deepak Saxena"); MODULE_DESCRIPTION("I2O procfs Handler"); MODULE_LICENSE("GPL"); -static void __exit i2o_proc_exit(void) -{ - destroy_i2o_procfs(); - i2o_remove_handler(&i2o_proc_handler); -} - -#ifdef MODULE module_init(i2o_proc_init); -#endif module_exit(i2o_proc_exit); - diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index ba121fc85..69855ae29 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any @@ -19,13 +19,13 @@ * * o Each (bus,lun) is a logical device in I2O. We keep a map * table. We spoof failed selection for unmapped units - * o Request sense buffers can come back for free. + * o Request sense buffers can come back for free. * o Scatter gather is a bit dynamic. We have to investigate at * setup time. * o Some of our resources are dynamically shared. The i2o core * needs a message reservation protocol to avoid swap v net * deadlocking. We need to back off queue requests. - * + * * In general the firmware wants to help. Where its help isn't performance * useful we just ignore the aid. Its not worth the code in truth. * @@ -40,7 +40,6 @@ * Fix the resource management problems. */ - #include #include #include @@ -53,962 +52,716 @@ #include #include #include +#include +#include + #include #include #include #include -#include -#include #include -#include -#include #include - +#include +#include #define VERSION_STRING "Version 0.1.2" -//#define DRIVERDEBUG +static struct i2o_driver i2o_scsi_driver; -#ifdef DRIVERDEBUG -#define dprintk(s, args...) printk(s, ## args) -#else -#define dprintk(s, args...) -#endif +static int i2o_scsi_max_id = 16; +static int i2o_scsi_max_lun = 8; + +struct i2o_scsi_host { + struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ + struct i2o_controller *iop; /* pointer to the I2O controller */ + struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ +}; + +static struct scsi_host_template i2o_scsi_host_template; #define I2O_SCSI_CAN_QUEUE 4 -#define MAXHOSTS 32 -struct i2o_scsi_host -{ - struct i2o_controller *controller; - s16 task[16][8]; /* Allow 16 devices for now */ - unsigned long tagclock[16][8]; /* Tag clock for queueing */ - s16 bus_task; /* The adapter TID */ +/* SCSI OSM class handling definition */ +static struct i2o_class_id i2o_scsi_class_id[] = { + {I2O_CLASS_SCSI_PERIPHERAL}, + {I2O_CLASS_END} }; -static int scsi_context; -static int lun_done; -static int i2o_scsi_hosts; +static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + struct i2o_device *i2o_dev; + struct Scsi_Host *scsi_host; + int max_channel = 0; + u8 type; + int i; + size_t size; + i2o_status_block *sb; -static u32 *retry[32]; -static struct i2o_controller *retry_ctrl[32]; -static struct timer_list retry_timer; -static spinlock_t retry_lock = SPIN_LOCK_UNLOCKED; -static int retry_ct = 0; + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */ + max_channel++; + } -static atomic_t queue_depth; + if (!max_channel) { + printk(KERN_WARNING "scsi-osm: no channels found on %s\n", + c->name); + return ERR_PTR(-EFAULT); + } -/* - * SG Chain buffer support... - */ + size = max_channel * sizeof(struct i2o_device *) + + sizeof(struct i2o_scsi_host); -#define SG_MAX_FRAGS 64 + scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size); + if (!scsi_host) { + printk(KERN_WARNING "scsi-osm: Could not allocate SCSI host\n"); + return ERR_PTR(-ENOMEM); + } -/* - * FIXME: we should allocate one of these per bus we find as we - * locate them not in a lump at boot. - */ - -typedef struct _chain_buf -{ - u32 sg_flags_cnt[SG_MAX_FRAGS]; - u32 sg_buf[SG_MAX_FRAGS]; -} chain_buf; + scsi_host->max_channel = max_channel - 1; + scsi_host->max_id = i2o_scsi_max_id; + scsi_host->max_lun = i2o_scsi_max_lun; + scsi_host->this_id = c->unit; -#define SG_CHAIN_BUF_SZ sizeof(chain_buf) + sb = c->status_block.virt; -#define SG_MAX_BUFS (i2o_num_controllers * I2O_SCSI_CAN_QUEUE) -#define SG_CHAIN_POOL_SZ (SG_MAX_BUFS * SG_CHAIN_BUF_SZ) + scsi_host->sg_tablesize = (sb->inbound_frame_size - + sizeof(struct i2o_message) / 4 - 6) / 2; -static int max_sg_len = 0; -static chain_buf *sg_chain_pool = NULL; -static int sg_chain_tag = 0; -static int sg_max_frags = SG_MAX_FRAGS; + i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; + i2o_shost->scsi_host = scsi_host; + i2o_shost->iop = c; + + i = 0; + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */ + i2o_shost->channel[i++] = i2o_dev; + + if (i >= max_channel) + break; + } + + return i2o_shost; +}; /** - * i2o_retry_run - retry on timeout - * @f: unused + * i2o_scsi_get_host - Get an I2O SCSI host + * @c: I2O controller to for which to get the SCSI host * - * Retry congested frames. This actually needs pushing down into - * i2o core. We should only bother the OSM with this when we can't - * queue and retry the frame. Or perhaps we should call the OSM - * and its default handler should be this in the core, and this - * call a 2nd "I give up" handler in the OSM ? + * If the I2O controller already exists as SCSI host, the SCSI host + * is returned, otherwise the I2O controller is added to the SCSI + * core. + * + * Returns pointer to the I2O SCSI host on success or NULL on failure. */ - -static void i2o_retry_run(unsigned long f) +static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c) { - int i; - unsigned long flags; - - spin_lock_irqsave(&retry_lock, flags); - for(i=0;idriver_data[i2o_scsi_driver.context]; +}; /** - * flush_pending - empty the retry queue + * i2o_scsi_remove - Remove I2O device from SCSI core + * @dev: device which should be removed + * + * Removes the I2O device from the SCSI core again. * - * Turn each of the pending commands into a NOP and post it back - * to the controller to clear it. + * Returns 0 on success. */ - -static void flush_pending(void) +static int i2o_scsi_remove(struct device *dev) { + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct scsi_device *scsi_dev; + + i2o_shost = i2o_scsi_get_host(c); + + shost_for_each_device(scsi_dev, i2o_shost->scsi_host) + if (scsi_dev->hostdata == i2o_dev) { + scsi_remove_device(scsi_dev); + scsi_device_put(scsi_dev); + break; + } + + return 0; +}; + +/** + * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it + * @dev: device to verify if it is a I2O SCSI device + * + * Retrieve channel, id and lun for I2O device. If everthing goes well + * register the I2O device as SCSI device on the I2O SCSI controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_scsi_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct Scsi_Host *scsi_host; + struct i2o_device *parent; + struct scsi_device *scsi_dev; + u32 id; + u64 lun; + int channel = -1; int i; - unsigned long flags; - - spin_lock_irqsave(&retry_lock, flags); - for(i=0;iscsi_host; + + if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0) + return -EFAULT; + + if (id >= scsi_host->max_id) { + printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_id " + "of I2O host (%d)", id, scsi_host->max_id); + return -EFAULT; } - retry_ct=0; - spin_unlock_irqrestore(&retry_lock, flags); + + if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0) + return -EFAULT; + if (lun >= scsi_host->max_lun) { + printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_lun " + "of I2O host (%d)", (unsigned int)lun, + scsi_host->max_lun); + return -EFAULT; + } + + parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); + if (!parent) { + printk(KERN_WARNING "scsi-osm: can not find parent of device " + "%03x\n", i2o_dev->lct_data.tid); + return -EFAULT; + } + + for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) + if (i2o_shost->channel[i] == parent) + channel = i; + + if (channel == -1) { + printk(KERN_WARNING "scsi-osm: can not find channel of device " + "%03x\n", i2o_dev->lct_data.tid); + return -EFAULT; + } + + scsi_dev = + __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); + + if (!scsi_dev) { + printk(KERN_WARNING "scsi-osm: can not add SCSI device " + "%03x\n", i2o_dev->lct_data.tid); + return -EFAULT; + } + + pr_debug("Added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n", + i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); + + return 0; +}; + +static const char *i2o_scsi_info(struct Scsi_Host *SChost) +{ + struct i2o_scsi_host *hostdata; + hostdata = (struct i2o_scsi_host *)SChost->hostdata; + return hostdata->iop->name; } /** - * i2o_scsi_reply - scsi message reply processor - * @h: our i2o handler + * i2o_scsi_reply - SCSI OSM message reply handler * @c: controller issuing the reply - * @msg: the message from the controller (mapped) + * @m: message id for flushing + * @msg: the message from the controller * * Process reply messages (interrupts in normal scsi controller think). * We can get a variety of messages to process. The normal path is * scsi command completions. We must also deal with IOP failures, * the reply to a bus reset and the reply to a LUN query. * - * Locks: the queue lock is taken to call the completion handler + * Returns 0 on success and if the reply should not be flushed or > 0 + * on success and if the reply should be flushed. Returns negative error + * code on failure and if the reply should be flushed. */ - -static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg) +static int i2o_scsi_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) { - struct scsi_cmnd *current_command; - spinlock_t *lock; - u32 *m = (u32 *)msg; - u8 as,ds,st; - unsigned long flags; - - if(m[0] & (1<<13)) - { - printk("IOP fail.\n"); - printk("From %d To %d Cmd %d.\n", - (m[1]>>12)&0xFFF, - m[1]&0xFFF, - m[1]>>24); - printk("Failure Code %d.\n", m[4]>>24); - if(m[4]&(1<<16)) - printk("Format error.\n"); - if(m[4]&(1<<17)) - printk("Path error.\n"); - if(m[4]&(1<<18)) - printk("Path State.\n"); - if(m[4]&(1<<18)) - printk("Congestion.\n"); - - m=(u32 *)bus_to_virt(m[7]); - printk("Failing message is %p.\n", m); - - /* This isnt a fast path .. */ - spin_lock_irqsave(&retry_lock, flags); - - if((m[4]&(1<<18)) && retry_ct < 32) + struct scsi_cmnd *cmd; + struct device *dev; + u8 as, ds, st; + + cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + + if (msg->u.head[0] & (1 << 13)) { + struct i2o_message __iomem *pmsg; /* preserved message */ + u32 pm; + int err = DID_ERROR; + + pm = le32_to_cpu(msg->body[3]); + + pmsg = i2o_msg_in_to_virt(c, pm); + + printk(KERN_ERR "IOP fail.\n"); + printk(KERN_ERR "From %d To %d Cmd %d.\n", + (msg->u.head[1] >> 12) & 0xFFF, + msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24); + printk(KERN_ERR "Failure Code %d.\n", msg->body[0] >> 24); + if (msg->body[0] & (1 << 16)) + printk(KERN_ERR "Format error.\n"); + if (msg->body[0] & (1 << 17)) + printk(KERN_ERR "Path error.\n"); + if (msg->body[0] & (1 << 18)) + printk(KERN_ERR "Path State.\n"); + if (msg->body[0] & (1 << 18)) { - retry_ctrl[retry_ct]=c; - retry[retry_ct]=m; - if(!retry_ct++) - { - retry_timer.expires=jiffies+1; - add_timer(&retry_timer); - } - spin_unlock_irqrestore(&retry_lock, flags); + printk(KERN_ERR "Congestion.\n"); + err = DID_BUS_BUSY; } - else - { - spin_unlock_irqrestore(&retry_lock, flags); - /* Create a scsi error for this */ - current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c); - if(!current_command) - return; - - lock = current_command->device->host->host_lock; - printk("Aborted %ld\n", current_command->serial_number); - - spin_lock_irqsave(lock, flags); - current_command->result = DID_ERROR << 16; - current_command->scsi_done(current_command); - spin_unlock_irqrestore(lock, flags); - - /* Now flush the message by making it a NOP */ - m[0]&=0x00FFFFFF; - m[0]|=(I2O_CMD_UTIL_NOP)<<24; - i2o_post_message(c,virt_to_bus(m)); - } - return; + + printk(KERN_DEBUG "Failing message is %p.\n", pmsg); + + cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt)); + if (!cmd) + return 1; + + cmd->result = err << 16; + cmd->scsi_done(cmd); + + /* Now flush the message by making it a NOP */ + i2o_msg_nop(c, pm); + + return 1; } - - prefetchw(&queue_depth); - - + /* - * Low byte is device status, next is adapter status, - * (then one byte reserved), then request status. + * Low byte is device status, next is adapter status, + * (then one byte reserved), then request status. */ - ds=(u8)le32_to_cpu(m[4]); - as=(u8)le32_to_cpu(m[4]>>8); - st=(u8)le32_to_cpu(m[4]>>24); - - dprintk(KERN_INFO "i2o got a scsi reply %08X: ", m[0]); - dprintk(KERN_INFO "m[2]=%08X: ", m[2]); - dprintk(KERN_INFO "m[4]=%08X\n", m[4]); - - if(m[2]&0x80000000) - { - if(m[2]&0x40000000) - { - dprintk(KERN_INFO "Event.\n"); - lun_done=1; - return; - } - printk(KERN_INFO "i2o_scsi: bus reset completed.\n"); - return; - } + ds = (u8) le32_to_cpu(msg->body[0]); + as = (u8) (le32_to_cpu(msg->body[0]) >> 8); + st = (u8) (le32_to_cpu(msg->body[0]) >> 24); - current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c); - /* - * Is this a control request coming back - eg an abort ? + * Is this a control request coming back - eg an abort ? */ - - atomic_dec(&queue_depth); - - if(current_command==NULL) - { - if(st) - dprintk(KERN_WARNING "SCSI abort: %08X", m[4]); - dprintk(KERN_INFO "SCSI abort completed.\n"); - return; - } - - dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number); - - if(st == 0x06) - { - if(le32_to_cpu(m[5]) < current_command->underflow) - { - int i; - printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X\n", - le32_to_cpu(m[5]), current_command->underflow); - printk("Cmd: "); - for(i=0;i<15;i++) - printk("%02X ", current_command->cmnd[i]); - printk(".\n"); - } - else st=0; - } - - if(st) - { - /* An error has occurred */ - dprintk(KERN_WARNING "SCSI error %08X", m[4]); - - if (as == 0x0E) - /* SCSI Reset */ - current_command->result = DID_RESET << 16; - else if (as == 0x0F) - current_command->result = DID_PARITY << 16; - else - current_command->result = DID_ERROR << 16; - } - else - /* - * It worked maybe ? - */ - current_command->result = DID_OK << 16 | ds; - - if (current_command->use_sg) { - pci_unmap_sg(c->pdev, - (struct scatterlist *)current_command->buffer, - current_command->use_sg, - current_command->sc_data_direction); - } else if (current_command->request_bufflen) { - pci_unmap_single(c->pdev, - (dma_addr_t)((long)current_command->SCp.ptr), - current_command->request_bufflen, - current_command->sc_data_direction); + if (!cmd) { + if (st) + printk(KERN_WARNING "SCSI abort: %08X", + le32_to_cpu(msg->body[0])); + printk(KERN_INFO "SCSI abort completed.\n"); + return -EFAULT; } - lock = current_command->device->host->host_lock; - spin_lock_irqsave(lock, flags); - current_command->scsi_done(current_command); - spin_unlock_irqrestore(lock, flags); - return; -} + pr_debug("Completed %ld\n", cmd->serial_number); -struct i2o_handler i2o_scsi_handler = { - .reply = i2o_scsi_reply, - .name = "I2O SCSI OSM", - .class = I2O_CLASS_SCSI_PERIPHERAL, -}; + if (st) { + u32 count, error; + /* An error has occurred */ -/** - * i2o_find_lun - report the lun of an i2o device - * @c: i2o controller owning the device - * @d: i2o disk device - * @target: filled in with target id - * @lun: filled in with target lun - * - * Query an I2O device to find out its SCSI lun and target numbering. We - * don't currently handle some of the fancy SCSI-3 stuff although our - * querying is sufficient to do so. - */ - -static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun) -{ - u8 reply[8]; - - if(i2o_query_scalar(c, d->lct_data.tid, 0, 3, reply, 4)<0) - return -1; - - *target=reply[0]; - - if(i2o_query_scalar(c, d->lct_data.tid, 0, 4, reply, 8)<0) - return -1; - - *lun=reply[1]; - - dprintk(KERN_INFO "SCSI (%d,%d)\n", *target, *lun); - return 0; -} + switch (st) { + case 0x06: + count = le32_to_cpu(msg->body[1]); + if (count < cmd->underflow) { + int i; + printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X" + "\n", count, cmd->underflow); + printk(KERN_DEBUG "Cmd: "); + for (i = 0; i < 15; i++) + printk(KERN_DEBUG "%02X ", + cmd->cmnd[i]); + printk(KERN_DEBUG ".\n"); + cmd->result = (DID_ERROR << 16); + } + break; -/** - * i2o_scsi_init - initialize an i2o device for scsi - * @c: i2o controller owning the device - * @d: scsi controller - * @shpnt: scsi device we wish it to become - * - * Enumerate the scsi peripheral/fibre channel peripheral class - * devices that are children of the controller. From that we build - * a translation map for the command queue code. Since I2O works on - * its own tid's we effectively have to think backwards to get what - * the midlayer wants - */ - -static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt) -{ - struct i2o_device *unit; - struct i2o_scsi_host *h =(struct i2o_scsi_host *)shpnt->hostdata; - int lun; - int target; - - h->controller=c; - h->bus_task=d->lct_data.tid; - - for(target=0;target<16;target++) - for(lun=0;lun<8;lun++) - h->task[target][lun] = -1; - - for(unit=c->devices;unit!=NULL;unit=unit->next) - { - dprintk(KERN_INFO "Class %03X, parent %d, want %d.\n", - unit->lct_data.class_id, unit->lct_data.parent_tid, d->lct_data.tid); - - /* Only look at scsi and fc devices */ - if ( (unit->lct_data.class_id != I2O_CLASS_SCSI_PERIPHERAL) - && (unit->lct_data.class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL) - ) - continue; - - /* On our bus ? */ - dprintk(KERN_INFO "Found a disk (%d).\n", unit->lct_data.tid); - if ((unit->lct_data.parent_tid == d->lct_data.tid) - || (unit->lct_data.parent_tid == d->lct_data.parent_tid) - ) - { - u16 limit; - dprintk(KERN_INFO "Its ours.\n"); - if(i2o_find_lun(c, unit, &target, &lun)==-1) - { - printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", unit->lct_data.tid); - continue; + default: + error = le32_to_cpu(msg->body[0]); + + printk(KERN_ERR "scsi-osm: SCSI error %08x\n", error); + + if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) { + int i; + u32 len = sizeof(cmd->sense_buffer); + len = (len > 40) ? 40 : len; + // Copy over the sense data + memcpy(cmd->sense_buffer, (void *)&msg->body[3], + len); + for (i = 0; i <= len; i++) + printk(KERN_INFO "%02x\n", + cmd->sense_buffer[i]); + if (cmd->sense_buffer[0] == 0x70 + && cmd->sense_buffer[2] == DATA_PROTECT) { + /* This is to handle an array failed */ + cmd->result = (DID_TIME_OUT << 16); + printk(KERN_WARNING "%s: SCSI Data " + "Protect-Device (%d,%d,%d) " + "hba_status=0x%x, dev_status=" + "0x%x, cmd=0x%x\n", c->name, + (u32) cmd->device->channel, + (u32) cmd->device->id, + (u32) cmd->device->lun, + (error >> 8) & 0xff, + error & 0xff, cmd->cmnd[0]); + } else + cmd->result = (DID_ERROR << 16); + + break; } - dprintk(KERN_INFO "Found disk %d %d.\n", target, lun); - h->task[target][lun]=unit->lct_data.tid; - h->tagclock[target][lun]=jiffies; - - /* Get the max fragments/request */ - i2o_query_scalar(c, d->lct_data.tid, 0xF103, 3, &limit, 2); - - /* sanity */ - if ( limit == 0 ) - { - printk(KERN_WARNING "i2o_scsi: Ignoring unreasonable SG limit of 0 from IOP!\n"); - limit = 1; + + switch (as) { + case 0x0E: + /* SCSI Reset */ + cmd->result = DID_RESET << 16; + break; + + case 0x0F: + cmd->result = DID_PARITY << 16; + break; + + default: + cmd->result = DID_ERROR << 16; + break; } - - shpnt->sg_tablesize = limit; - dprintk(KERN_INFO "i2o_scsi: set scatter-gather to %d.\n", - shpnt->sg_tablesize); + break; } - } -} + + cmd->scsi_done(cmd); + return 1; + } + + cmd->result = DID_OK << 16 | ds; + + cmd->scsi_done(cmd); + + dev = &c->pdev->dev; + if (cmd->use_sg) + dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer, + cmd->use_sg, cmd->sc_data_direction); + else if (cmd->request_bufflen) + dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr), + cmd->request_bufflen, cmd->sc_data_direction); + + return 1; +}; /** - * i2o_scsi_detect - probe for I2O scsi devices - * @tpnt: scsi layer template + * i2o_scsi_notify_controller_add - Retrieve notifications of added + * controllers + * @c: the controller which was added * - * I2O is a little odd here. The I2O core already knows what the - * devices are. It also knows them by disk and tape as well as - * by controller. We register each I2O scsi class object as a - * scsi controller and then let the enumeration fake up the rest + * If a I2O controller is added, we catch the notification to add a + * corresponding Scsi_Host. */ - -static int i2o_scsi_detect(struct scsi_host_template * tpnt) +static void i2o_scsi_notify_controller_add(struct i2o_controller *c) { - struct Scsi_Host *shpnt = NULL; - int i; - int count; + struct i2o_scsi_host *i2o_shost; + int rc; - printk(KERN_INFO "i2o_scsi.c: %s\n", VERSION_STRING); - - if(i2o_install_handler(&i2o_scsi_handler)<0) - { - printk(KERN_ERR "i2o_scsi: Unable to install OSM handler.\n"); - return 0; - } - scsi_context = i2o_scsi_handler.context; - - if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL) - { - printk(KERN_INFO "i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ); - printk(KERN_INFO "i2o_scsi: SG chaining DISABLED!\n"); - sg_max_frags = 11; - } - else - { - printk(KERN_INFO " chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool); - printk(KERN_INFO " (%d byte buffers X %d can_queue X %d i2o controllers)\n", - SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers); - sg_max_frags = SG_MAX_FRAGS; // 64 - } - - init_timer(&retry_timer); - retry_timer.data = 0UL; - retry_timer.function = i2o_retry_run; - -// printk("SCSI OSM at %d.\n", scsi_context); - - for (count = 0, i = 0; i < MAX_I2O_CONTROLLERS; i++) - { - struct i2o_controller *c=i2o_find_controller(i); - struct i2o_device *d; - /* - * This controller doesn't exist. - */ - - if(c==NULL) - continue; - - /* - * Fixme - we need some altered device locking. This - * is racing with device addition in theory. Easy to fix. - */ - - for(d=c->devices;d!=NULL;d=d->next) - { - /* - * bus_adapter, SCSI (obsolete), or FibreChannel busses only - */ - if( (d->lct_data.class_id!=I2O_CLASS_BUS_ADAPTER_PORT) // bus_adapter -// && (d->lct_data.class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT) // FC_PORT - ) - continue; - - shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host)); - if(shpnt==NULL) - continue; - shpnt->unique_id = (u32)d; - shpnt->io_port = 0; - shpnt->n_io_port = 0; - shpnt->irq = 0; - shpnt->this_id = /* Good question */15; - i2o_scsi_init(c, d, shpnt); - count++; - } - } - i2o_scsi_hosts = count; - - if(count==0) - { - if(sg_chain_pool!=NULL) - { - kfree(sg_chain_pool); - sg_chain_pool = NULL; - } - flush_pending(); - del_timer(&retry_timer); - i2o_remove_handler(&i2o_scsi_handler); + i2o_shost = i2o_scsi_host_alloc(c); + if (IS_ERR(i2o_shost)) { + printk(KERN_ERR "scsi-osm: Could not initialize" + " SCSI host\n"); + return; } - - return count; -} -static int i2o_scsi_release(struct Scsi_Host *host) -{ - if(--i2o_scsi_hosts==0) - { - if(sg_chain_pool!=NULL) - { - kfree(sg_chain_pool); - sg_chain_pool = NULL; - } - flush_pending(); - del_timer(&retry_timer); - i2o_remove_handler(&i2o_scsi_handler); + rc = scsi_add_host(i2o_shost->scsi_host, &c->device); + if (rc) { + printk(KERN_ERR "scsi-osm: Could not add SCSI " "host\n"); + scsi_host_put(i2o_shost->scsi_host); + return; } - scsi_unregister(host); - - return 0; -} + c->driver_data[i2o_scsi_driver.context] = i2o_shost; + pr_debug("new I2O SCSI host added\n"); +}; -static const char *i2o_scsi_info(struct Scsi_Host *SChost) +/** + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed + * controllers + * @c: the controller which was removed + * + * If a I2O controller is removed, we catch the notification to remove the + * corresponding Scsi_Host. + */ +static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) { - struct i2o_scsi_host *hostdata; - hostdata = (struct i2o_scsi_host *)SChost->hostdata; - return(&hostdata->controller->name[0]); -} + struct i2o_scsi_host *i2o_shost; + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return; + + c->driver_data[i2o_scsi_driver.context] = NULL; + + scsi_remove_host(i2o_shost->scsi_host); + scsi_host_put(i2o_shost->scsi_host); + pr_debug("I2O SCSI host removed\n"); +}; + +/* SCSI OSM driver struct */ +static struct i2o_driver i2o_scsi_driver = { + .name = "scsi-osm", + .reply = i2o_scsi_reply, + .classes = i2o_scsi_class_id, + .notify_controller_add = i2o_scsi_notify_controller_add, + .notify_controller_remove = i2o_scsi_notify_controller_remove, + .driver = { + .probe = i2o_scsi_probe, + .remove = i2o_scsi_remove, + }, +}; /** - * i2o_scsi_queuecommand - queue a SCSI command + * i2o_scsi_queuecommand - queue a SCSI command * @SCpnt: scsi command pointer * @done: callback for completion * - * Issue a scsi comamnd asynchronously. Return 0 on success or 1 if - * we hit an error (normally message queue congestion). The only + * Issue a scsi command asynchronously. Return 0 on success or 1 if + * we hit an error (normally message queue congestion). The only * minor complication here is that I2O deals with the device addressing * so we have to map the bus/dev/lun back to an I2O handle as well - * as faking absent devices ourself. + * as faking absent devices ourself. * * Locks: takes the controller lock on error path only */ - + static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, void (*done) (struct scsi_cmnd *)) { - int i; - int tid; struct i2o_controller *c; - struct scsi_cmnd *current_command; struct Scsi_Host *host; - struct i2o_scsi_host *hostdata; - u32 *msg, *mptr; + struct i2o_device *i2o_dev; + struct device *dev; + int tid; + struct i2o_message __iomem *msg; u32 m; - u32 *lenptr; - int direction; - int scsidir; - u32 len; - u32 reqlen; - u32 tag; - unsigned long flags; - - static int max_qd = 1; - + u32 scsi_flags, sg_flags; + u32 __iomem *mptr; + u32 __iomem *lenptr; + u32 len, reqlen; + int i; + /* - * Do the incoming paperwork + * Do the incoming paperwork */ - + + i2o_dev = SCpnt->device->hostdata; host = SCpnt->device->host; - hostdata = (struct i2o_scsi_host *)host->hostdata; - - c = hostdata->controller; - prefetch(c); - prefetchw(&queue_depth); + c = i2o_dev->iop; + dev = &c->pdev->dev; SCpnt->scsi_done = done; - - if(SCpnt->device->id > 15) - { - printk(KERN_ERR "i2o_scsi: Wild target %d.\n", SCpnt->device->id); - return -1; - } - - tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun]; - - dprintk(KERN_INFO "qcmd: Tid = %d\n", tid); - - current_command = SCpnt; /* set current command */ - current_command->scsi_done = done; /* set ptr to done function */ - - /* We don't have such a device. Pretend we did the command - and that selection timed out */ - - if(tid == -1) - { + + if (unlikely(!i2o_dev)) { + printk(KERN_WARNING "scsi-osm: no I2O device in request\n"); SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } - - dprintk(KERN_INFO "Real scsi messages.\n"); + + tid = i2o_dev->lct_data.tid; + + pr_debug("qcmd: Tid = %03x\n", tid); + pr_debug("Real scsi messages.\n"); /* - * Obtain an I2O message. If there are none free then - * throw it back to the scsi layer - */ - - m = le32_to_cpu(I2O_POST_READ32(c)); - if(m==0xFFFFFFFF) - return 1; + * Obtain an I2O message. If there are none free then + * throw it back to the scsi layer + */ + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return SCSI_MLQUEUE_HOST_BUSY; - msg = (u32 *)(c->msg_virt + m); - /* - * Put together a scsi execscb message + * Put together a scsi execscb message */ - + len = SCpnt->request_bufflen; - direction = 0x00000000; // SGL IN (osm<--iop) - - if (SCpnt->sc_data_direction == DMA_NONE) { - scsidir = 0x00000000; // DATA NO XFER - } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { - direction = 0x04000000; // SGL OUT (osm-->iop) - scsidir = 0x80000000; // DATA OUT (iop-->dev) - } else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) { - scsidir = 0x40000000; // DATA IN (iop<--dev) - } else { + + switch (SCpnt->sc_data_direction) { + case PCI_DMA_NONE: + scsi_flags = 0x00000000; // DATA NO XFER + sg_flags = 0x00000000; + break; + + case PCI_DMA_TODEVICE: + scsi_flags = 0x80000000; // DATA OUT (iop-->dev) + sg_flags = 0x14000000; + break; + + case PCI_DMA_FROMDEVICE: + scsi_flags = 0x40000000; // DATA IN (iop<--dev) + sg_flags = 0x10000000; + break; + + default: /* Unknown - kill the command */ SCpnt->result = DID_NO_CONNECT << 16; - - /* We must lock the request queue while completing */ - spin_lock_irqsave(host->host_lock, flags); done(SCpnt); - spin_unlock_irqrestore(host->host_lock, flags); return 0; } - - i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]); - i2o_raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */ - i2o_raw_writel(i2o_context_list_add(SCpnt, c), &msg[3]); /* We want the SCSI control block back */ + writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]); + writel(i2o_scsi_driver.context, &msg->u.s.icntxt); + + /* We want the SCSI control block back */ + writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt); /* LSI_920_PCI_QUIRK * - * Intermittant observations of msg frame word data corruption - * observed on msg[4] after: - * WRITE, READ-MODIFY-WRITE - * operations. 19990606 -sralston + * Intermittant observations of msg frame word data corruption + * observed on msg[4] after: + * WRITE, READ-MODIFY-WRITE + * operations. 19990606 -sralston * - * (Hence we build this word via tag. Its good practice anyway - * we don't want fetches over PCI needlessly) + * (Hence we build this word via tag. Its good practice anyway + * we don't want fetches over PCI needlessly) */ - tag=0; - + /* Attach tags to the devices */ /* - * Attach tags to the devices - */ - if(SCpnt->device->tagged_supported) - { - /* - * Some drives are too stupid to handle fairness issues - * with tagged queueing. We throw in the odd ordered - * tag to stop them starving themselves. - */ - if((jiffies - hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]) > (5*HZ)) - { - tag=0x01800000; /* ORDERED! */ - hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]=jiffies; - } - else - { - /* Hmmm... I always see value of 0 here, - * of which {HEAD_OF, ORDERED, SIMPLE} are NOT! -sralston - */ - if(SCpnt->tag == HEAD_OF_QUEUE_TAG) - tag=0x01000000; - else if(SCpnt->tag == ORDERED_QUEUE_TAG) - tag=0x01800000; - } - } + if(SCpnt->device->tagged_supported) { + if(SCpnt->tag == HEAD_OF_QUEUE_TAG) + scsi_flags |= 0x01000000; + else if(SCpnt->tag == ORDERED_QUEUE_TAG) + scsi_flags |= 0x01800000; + } + */ /* Direction, disconnect ok, tag, CDBLen */ - i2o_raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]); + writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]); - mptr=msg+5; + mptr = &msg->body[1]; - /* - * Write SCSI command into the message - always 16 byte block - */ - + /* Write SCSI command into the message - always 16 byte block */ memcpy_toio(mptr, SCpnt->cmnd, 16); - mptr+=4; - lenptr=mptr++; /* Remember me - fill in when we know */ - + mptr += 4; + lenptr = mptr++; /* Remember me - fill in when we know */ + reqlen = 12; // SINGLE SGE - - /* - * Now fill in the SGList and command - * - * FIXME: we need to set the sglist limits according to the - * message size of the I2O controller. We might only have room - * for 6 or so worst case - */ - - if(SCpnt->use_sg) - { - struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer; + + /* Now fill in the SGList and command */ + if (SCpnt->use_sg) { + struct scatterlist *sg; int sg_count; - int chain = 0; - + + sg = SCpnt->request_buffer; len = 0; - sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg, - SCpnt->sc_data_direction); + sg_count = dma_map_sg(dev, sg, SCpnt->use_sg, + SCpnt->sc_data_direction); - /* FIXME: handle fail */ - if(!sg_count) - BUG(); - - if((sg_max_frags > 11) && (SCpnt->use_sg > 11)) - { - chain = 1; - /* - * Need to chain! - */ - i2o_raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++); - i2o_raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr); - mptr = (u32*)(sg_chain_pool + sg_chain_tag); - if (SCpnt->use_sg > max_sg_len) - { - max_sg_len = SCpnt->use_sg; - printk("i2o_scsi: Chain SG! SCpnt=%p, SG_FragCnt=%d, SG_idx=%d\n", - SCpnt, SCpnt->use_sg, sg_chain_tag); - } - if ( ++sg_chain_tag == SG_MAX_BUFS ) - sg_chain_tag = 0; - for(i = 0 ; i < SCpnt->use_sg; i++) - { - *mptr++=cpu_to_le32(direction|0x10000000|sg_dma_len(sg)); - len+=sg_dma_len(sg); - *mptr++=cpu_to_le32(sg_dma_address(sg)); - sg++; - } - mptr[-2]=cpu_to_le32(direction|0xD0000000|sg_dma_len(sg-1)); - } - else - { - for(i = 0 ; i < SCpnt->use_sg; i++) - { - i2o_raw_writel(direction|0x10000000|sg_dma_len(sg), mptr++); - len+=sg->length; - i2o_raw_writel(sg_dma_address(sg), mptr++); - sg++; - } + if (unlikely(sg_count <= 0)) + return -ENOMEM; - /* Make this an end of list. Again evade the 920 bug and - unwanted PCI read traffic */ - - i2o_raw_writel(direction|0xD0000000|sg_dma_len(sg-1), &mptr[-2]); + for (i = SCpnt->use_sg; i > 0; i--) { + if (i == 1) + sg_flags |= 0xC0000000; + writel(sg_flags | sg_dma_len(sg), mptr++); + writel(sg_dma_address(sg), mptr++); + len += sg_dma_len(sg); + sg++; } - - if(!chain) - reqlen = mptr - msg; - - i2o_raw_writel(len, lenptr); - - if(len != SCpnt->underflow) - printk("Cmd len %08X Cmd underflow %08X\n", - len, SCpnt->underflow); - } - else - { - dprintk(KERN_INFO "non sg for %p, %d\n", SCpnt->request_buffer, - SCpnt->request_bufflen); - i2o_raw_writel(len = SCpnt->request_bufflen, lenptr); - if(len == 0) - { - reqlen = 9; - } - else - { + + reqlen = mptr - &msg->u.head[0]; + writel(len, lenptr); + } else { + len = SCpnt->request_bufflen; + + writel(len, lenptr); + + if (len > 0) { dma_addr_t dma_addr; - dma_addr = pci_map_single(c->pdev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - if(dma_addr == 0) - BUG(); /* How to handle ?? */ - SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr; - i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++); - i2o_raw_writel(dma_addr, mptr++); - } + + dma_addr = dma_map_single(dev, SCpnt->request_buffer, + SCpnt->request_bufflen, + SCpnt->sc_data_direction); + if (!dma_addr) + return -ENOMEM; + + SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr; + sg_flags |= 0xC0000000; + writel(sg_flags | SCpnt->request_bufflen, mptr++); + writel(dma_addr, mptr++); + } else + reqlen = 9; } - - /* - * Stick the headers on - */ - i2o_raw_writel(reqlen<<16 | SGL_OFFSET_10, msg); - + /* Stick the headers on */ + writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]); + /* Queue the message */ - i2o_post_message(c,m); - - atomic_inc(&queue_depth); - - if(atomic_read(&queue_depth)> max_qd) - { - max_qd=atomic_read(&queue_depth); - printk("Queue depth now %d.\n", max_qd); - } - - mb(); - dprintk(KERN_INFO "Issued %ld\n", current_command->serial_number); - + i2o_msg_post(c, m); + + pr_debug("Issued %ld\n", SCpnt->serial_number); + return 0; -} +}; /** - * i2o_scsi_abort - abort a running command + * i2o_scsi_abort - abort a running command * @SCpnt: command to abort * * Ask the I2O controller to abort a command. This is an asynchrnous - * process and our callback handler will see the command complete - * with an aborted message if it succeeds. + * process and our callback handler will see the command complete with an + * aborted message if it succeeds. * - * Locks: no locks are held or needed + * Returns 0 if the command is successfully aborted or negative error code + * on failure. */ - -static int i2o_scsi_abort(struct scsi_cmnd * SCpnt) +static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { + struct i2o_device *i2o_dev; struct i2o_controller *c; - struct Scsi_Host *host; - struct i2o_scsi_host *hostdata; - u32 msg[5]; + struct i2o_message __iomem *msg; + u32 m; int tid; int status = FAILED; - - printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); - - host = SCpnt->device->host; - hostdata = (struct i2o_scsi_host *)host->hostdata; - tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun]; - if(tid==-1) - { - printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n"); - return status; - } - c = hostdata->controller; - - spin_unlock_irq(host->host_lock); - - msg[0] = FIVE_WORD_MSG_SIZE; - msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid; - msg[2] = scsi_context; - msg[3] = 0; - msg[4] = i2o_context_list_remove(SCpnt, c); - if(i2o_post_wait(c, msg, sizeof(msg), 240)) - status = SUCCESS; - - spin_lock_irq(host->host_lock); - return status; -} - -/** - * i2o_scsi_bus_reset - Issue a SCSI reset - * @SCpnt: the command that caused the reset - * - * Perform a SCSI bus reset operation. In I2O this is just a message - * we pass. I2O can do clever multi-initiator and shared reset stuff - * but we don't support this. - * - * Locks: called with no lock held, requires no locks. - */ - -static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt) -{ - int tid; - struct i2o_controller *c; - struct Scsi_Host *host; - struct i2o_scsi_host *hostdata; - u32 m; - void *msg; - unsigned long timeout; - - - /* - * Find the TID for the bus - */ - - host = SCpnt->device->host; + printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); - spin_unlock_irq(host->host_lock); + i2o_dev = SCpnt->device->hostdata; + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; - printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n"); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return SCSI_MLQUEUE_HOST_BUSY; - hostdata = (struct i2o_scsi_host *)host->hostdata; - tid = hostdata->bus_task; - c = hostdata->controller; + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]); - /* - * Now send a SCSI reset request. Any remaining commands - * will be aborted by the IOP. We need to catch the reply - * possibly ? - */ + if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT)) + status = SUCCESS; - timeout = jiffies+2*HZ; - do - { - m = le32_to_cpu(I2O_POST_READ32(c)); - if(m != 0xFFFFFFFF) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - mb(); - } - while(time_before(jiffies, timeout)); - - - msg = c->msg_virt + m; - i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg); - i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4); - i2o_raw_writel(scsi_context|0x80000000, msg+8); - /* We use the top bit to split controller and unit transactions */ - /* Now store unit,tid so we can tie the completion back to a specific device */ - __raw_writel(c->unit << 16 | tid, msg+12); - wmb(); - - /* We want the command to complete after we return */ - spin_lock_irq(host->host_lock); - i2o_post_message(c,m); - - /* Should we wait for the reset to complete ? */ - return SUCCESS; + return status; } /** * i2o_scsi_bios_param - Invent disk geometry - * @sdev: scsi device + * @sdev: scsi device * @dev: block layer device * @capacity: size in sectors * @ip: geometry array * - * This is anyones guess quite frankly. We use the same rules everyone + * This is anyones guess quite frankly. We use the same rules everyone * else appears to and hope. It seems to work. */ - -static int i2o_scsi_bios_param(struct scsi_device * sdev, - struct block_device *dev, sector_t capacity, int *ip) + +static int i2o_scsi_bios_param(struct scsi_device *sdev, + struct block_device *dev, sector_t capacity, + int *ip) { int size; @@ -1023,25 +776,64 @@ static int i2o_scsi_bios_param(struct scsi_device * sdev, return 0; } -MODULE_AUTHOR("Red Hat Software"); -MODULE_LICENSE("GPL"); +static struct scsi_host_template i2o_scsi_host_template = { + .proc_name = "SCSI-OSM", + .name = "I2O SCSI Peripheral OSM", + .info = i2o_scsi_info, + .queuecommand = i2o_scsi_queuecommand, + .eh_abort_handler = i2o_scsi_abort, + .bios_param = i2o_scsi_bios_param, + .can_queue = I2O_SCSI_CAN_QUEUE, + .sg_tablesize = 8, + .cmd_per_lun = 6, + .use_clustering = ENABLE_CLUSTERING, +}; + +/* +int +i2o_scsi_queuecommand(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *)) +{ + printk(KERN_INFO "queuecommand\n"); + return SCSI_MLQUEUE_HOST_BUSY; +}; +*/ + +/** + * i2o_scsi_init - SCSI OSM initialization function + * + * Register SCSI OSM into I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_scsi_init(void) +{ + int rc; + printk(KERN_INFO "I2O SCSI Peripheral OSM\n"); -static struct scsi_host_template driver_template = { - .proc_name = "i2o_scsi", - .name = "I2O SCSI Layer", - .detect = i2o_scsi_detect, - .release = i2o_scsi_release, - .info = i2o_scsi_info, - .queuecommand = i2o_scsi_queuecommand, - .eh_abort_handler = i2o_scsi_abort, - .eh_bus_reset_handler = i2o_scsi_bus_reset, - .bios_param = i2o_scsi_bios_param, - .can_queue = I2O_SCSI_CAN_QUEUE, - .this_id = 15, - .sg_tablesize = 8, - .cmd_per_lun = 6, - .use_clustering = ENABLE_CLUSTERING, + /* Register SCSI OSM into I2O core */ + rc = i2o_driver_register(&i2o_scsi_driver); + if (rc) { + printk(KERN_ERR "scsi-osm: Could not register SCSI driver\n"); + return rc; + } + + return 0; }; -#include "../../scsi/scsi_module.c" +/** + * i2o_scsi_exit - SCSI OSM exit function + * + * Unregisters SCSI OSM from I2O core. + */ +static void __exit i2o_scsi_exit(void) +{ + /* Unregister I2O SCSI OSM from I2O core */ + i2o_driver_unregister(&i2o_scsi_driver); +}; + +MODULE_AUTHOR("Red Hat Software"); +MODULE_LICENSE("GPL"); + +module_init(i2o_scsi_init); +module_exit(i2o_scsi_exit); diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 699723e3a..ea6a8b371 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -27,6 +27,7 @@ #include #include +#include /* global I2O controller list */ LIST_HEAD(i2o_controllers); @@ -37,6 +38,8 @@ LIST_HEAD(i2o_controllers); */ static struct i2o_dma i2o_systab; +static int i2o_hrt_get(struct i2o_controller *c); + /* Module internal functions from other sources */ extern struct i2o_driver i2o_exec_driver; extern int i2o_exec_lct_get(struct i2o_controller *); @@ -62,7 +65,7 @@ extern void i2o_device_exit(void); */ void i2o_msg_nop(struct i2o_controller *c, u32 m) { - struct i2o_message *msg = c->in_queue.virt + m; + struct i2o_message __iomem *msg = c->in_queue.virt + m; writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, @@ -86,7 +89,7 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg, +u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg, int wait) { unsigned long timeout = jiffies + wait * HZ; @@ -117,7 +120,7 @@ u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message **msg, * * Returns context id > 0 on success or 0 on failure. */ -u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) +u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) { struct i2o_context_list_element *entry; unsigned long flags; @@ -162,7 +165,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) * * Returns context id on succes or 0 on failure. */ -u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) +u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) { struct i2o_context_list_element *entry; u32 context = 0; @@ -303,7 +306,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) */ static int i2o_iop_quiesce(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -345,7 +348,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c) */ static int i2o_iop_enable(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -417,7 +420,7 @@ static inline void i2o_iop_enable_all(void) */ static int i2o_iop_clear(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; int rc; @@ -458,7 +461,7 @@ static int i2o_iop_clear(struct i2o_controller *c) static int i2o_iop_reset(struct i2o_controller *c) { u8 *status = c->status.virt; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; @@ -470,7 +473,7 @@ static int i2o_iop_reset(struct i2o_controller *c) if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - memset(status, 0, 4); + memset(status, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); @@ -495,6 +498,13 @@ static int i2o_iop_reset(struct i2o_controller *c) rc = -ETIMEDOUT; goto exit; } + + /* Promise bug */ + if (status[1] || status[4]) { + *status = 0; + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); @@ -556,11 +566,11 @@ static int i2o_iop_reset(struct i2o_controller *c) * * Returns 0 on success or a negative errno code on failure. */ -int i2o_iop_init_outbound_queue(struct i2o_controller *c) +static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { u8 *status = c->status.virt; u32 m; - struct i2o_message *msg; + struct i2o_message __iomem *msg; ulong timeout; int i; @@ -605,12 +615,30 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c) /* Post frames */ for (i = 0; i < NMBR_MSG_FRAMES; i++) { i2o_flush_reply(c, m); + udelay(1); /* Promise */ m += MSG_FRAME_SIZE * 4; } return 0; } +/** + * i2o_iop_send_nop - send a core NOP message + * @c: controller + * + * Send a no-operation message with a reply set to cause no + * action either. Needed for bringing up promise controllers. + */ +static int i2o_iop_send_nop(struct i2o_controller *c) +{ + struct i2o_message __iomem *msg; + u32 m = i2o_msg_get_wait(c, &msg, HZ); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + i2o_msg_nop(c, m); + return 0; +} + /** * i2o_iop_activate - Bring controller up to HOLD * @c: controller @@ -622,8 +650,27 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c) */ static int i2o_iop_activate(struct i2o_controller *c) { + struct pci_dev *i960 = NULL; i2o_status_block *sb = c->status_block.virt; int rc; + + if (c->promise) { + /* Beat up the hardware first of all */ + i960 = + pci_find_slot(c->pdev->bus->number, + PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); + if (i960) + pci_write_config_word(i960, 0x42, 0); + + /* Follow this sequence precisely or the controller + ceases to perform useful functions until reboot */ + if ((rc = i2o_iop_send_nop(c))) + return rc; + + if ((rc = i2o_iop_reset(c))) + return rc; + } + /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ /* In READY state, Get status */ @@ -659,13 +706,22 @@ static int i2o_iop_activate(struct i2o_controller *c) if (rc) return rc; + if (c->promise) { + if ((rc = i2o_iop_send_nop(c))) + return rc; + + if ((rc = i2o_status_get(c))) + return rc; + + if (i960) + pci_write_config_word(i960, 0x42, 0x3FF); + } + /* In HOLD state */ rc = i2o_hrt_get(c); - if (rc) - return rc; - return 0; + return rc; }; /** @@ -678,7 +734,7 @@ static int i2o_iop_activate(struct i2o_controller *c) */ static int i2o_iop_systab_set(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; i2o_status_block *sb = c->status_block.virt; struct device *dev = &c->pdev->dev; @@ -691,10 +747,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c) res->flags = IORESOURCE_MEM; res->start = 0; res->end = 0; - printk("%s: requires private memory resources.\n", c->name); + printk(KERN_INFO "%s: requires private memory resources.\n", + c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) - printk("Can't find parent resource!\n"); + printk(KERN_WARNING "Can't find parent resource!\n"); if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ NULL, NULL) >= 0) { c->mem_alloc = 1; @@ -712,10 +769,11 @@ static int i2o_iop_systab_set(struct i2o_controller *c) res->flags = IORESOURCE_IO; res->start = 0; res->end = 0; - printk("%s: requires private memory resources.\n", c->name); + printk(KERN_INFO "%s: requires private memory resources.\n", + c->name); root = pci_find_parent_resource(c->pdev, res); if (root == NULL) - printk("Can't find parent resource!\n"); + printk(KERN_WARNING "Can't find parent resource!\n"); if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ NULL, NULL) >= 0) { c->io_alloc = 1; @@ -754,7 +812,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c) writel(c->unit + 2, &msg->body[0]); writel(0, &msg->body[1]); - writel(0x54000000 | i2o_systab.phys, &msg->body[2]); + writel(0x54000000 | i2o_systab.len, &msg->body[2]); writel(i2o_systab.phys, &msg->body[3]); writel(0x54000000 | sb->current_mem_size, &msg->body[4]); writel(sb->current_mem_base, &msg->body[5]); @@ -939,7 +997,7 @@ static int i2o_parse_hrt(struct i2o_controller *c) */ int i2o_status_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; u8 *status_block; unsigned long timeout; @@ -994,7 +1052,7 @@ int i2o_status_get(struct i2o_controller *c) * * Returns 0 on success or negativer error code on failure. */ -int i2o_hrt_get(struct i2o_controller *c) +static int i2o_hrt_get(struct i2o_controller *c) { int rc; int i; @@ -1003,7 +1061,7 @@ int i2o_hrt_get(struct i2o_controller *c) struct device *dev = &c->pdev->dev; for (i = 0; i < I2O_HRT_GET_TRIES; i++) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -1063,13 +1121,13 @@ struct i2o_controller *i2o_iop_alloc(void) memset(c, 0, sizeof(*c)); INIT_LIST_HEAD(&c->devices); - c->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&c->lock); init_MUTEX(&c->lct_lock); c->unit = unit++; sprintf(c->name, "iop%d", c->unit); #if BITS_PER_LONG == 64 - c->context_list_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&c->context_list_lock); atomic_set(&c->context_list_counter, 0); INIT_LIST_HEAD(&c->context_list); #endif @@ -1158,7 +1216,7 @@ int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, int tcntxt, u32 evt_mask) { struct i2o_controller *c = dev->iop; - struct i2o_message *msg; + struct i2o_message __iomem *msg; u32 m; m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); @@ -1254,5 +1312,4 @@ EXPORT_SYMBOL(i2o_find_iop); EXPORT_SYMBOL(i2o_iop_find_device); EXPORT_SYMBOL(i2o_event_register); EXPORT_SYMBOL(i2o_status_get); -EXPORT_SYMBOL(i2o_hrt_get); EXPORT_SYMBOL(i2o_controllers); diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 9ee58b6cf..f98849abb 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -138,13 +138,13 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) * If we know what card it is, set the size * correctly. Code is taken from dpt_i2o.c */ - if(pdev->device == 0xa501) { - if(pdev->subsystem_device >= 0xc032 && - pdev->subsystem_device <= 0xc03b) { - if(c->base.len > 0x400000) + if (pdev->device == 0xa501) { + if (pdev->subsystem_device >= 0xc032 && + pdev->subsystem_device <= 0xc03b) { + if (c->base.len > 0x400000) c->base.len = 0x400000; } else { - if(c->base.len > 0x100000) + if (c->base.len > 0x100000) c->base.len = 0x100000; } } @@ -231,7 +231,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) } #endif - if (i2o_dma_alloc(dev, &c->status, 4, GFP_KERNEL)) { + if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { i2o_pci_free(c); return -ENOMEM; } @@ -277,7 +277,6 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) struct device *dev = &c->pdev->dev; struct i2o_message *m; u32 mv; - u32 *msg; /* * Old 960 steppings had a bug in the I2O unit that caused @@ -298,11 +297,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) * Because bus_to_virt is deprecated, we have calculate the * location by ourself! */ - m = (struct i2o_message *)(mv - - (unsigned long)c->out_queue.phys + - (unsigned long)c->out_queue.virt); - - msg = (u32 *) m; + m = i2o_msg_out_to_virt(c, mv); /* * Ensure this message is seen coherently but cachably by diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index 9b3ff1dcf..6fec7fd8c 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -158,7 +158,7 @@ struct remote_queue { struct service_processor { struct list_head node; spinlock_t lock; - void *base_address; + void __iomem *base_address; unsigned int irq; struct command *current_command; struct command *heartbeat; diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index e604925df..02f4f789c 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -173,13 +173,8 @@ static struct dentry *ibmasmfs_create_file (struct super_block *sb, { struct dentry *dentry; struct inode *inode; - struct qstr qname; - qname.name = name; - qname.len = strlen (name); - qname.hash = full_name_hash(name, qname.len); - - dentry = d_alloc(parent, &qname); + dentry = d_alloc_name(parent, name); if (!dentry) return NULL; @@ -202,12 +197,8 @@ static struct dentry *ibmasmfs_create_dir (struct super_block *sb, { struct dentry *dentry; struct inode *inode; - struct qstr qname; - qname.name = name; - qname.len = strlen (name); - qname.hash = full_name_hash(name, qname.len); - dentry = d_alloc(parent, &qname); + dentry = d_alloc_name(parent, name); if (!dentry) return NULL; @@ -520,7 +511,7 @@ static int remote_settings_file_close(struct inode *inode, struct file *file) static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { - unsigned long address = (unsigned long)file->private_data; + void __iomem *address = (void __iomem *)file->private_data; unsigned char *page; int retval; int len = 0; @@ -554,7 +545,7 @@ exit: static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset) { - unsigned long address = (unsigned long)file->private_data; + void __iomem *address = (void __iomem *)file->private_data; char *buff; unsigned int value; diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c index 3b3e6314a..5156de275 100644 --- a/drivers/misc/ibmasm/lowlevel.c +++ b/drivers/misc/ibmasm/lowlevel.c @@ -58,7 +58,7 @@ irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *reg { u32 mfa; struct service_processor *sp = (struct service_processor *)dev_id; - void *base_address = sp->base_address; + void __iomem *base_address = sp->base_address; if (!sp_interrupt_pending(base_address)) return IRQ_NONE; diff --git a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h index 4339504d2..e5ed59c58 100644 --- a/drivers/misc/ibmasm/lowlevel.h +++ b/drivers/misc/ibmasm/lowlevel.h @@ -52,51 +52,51 @@ #define SCOUT_COM_C_BASE 0x0200 #define SCOUT_COM_D_BASE 0x0300 -static inline int sp_interrupt_pending(void *base_address) +static inline int sp_interrupt_pending(void __iomem *base_address) { return SP_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); } -static inline int uart_interrupt_pending(void *base_address) +static inline int uart_interrupt_pending(void __iomem *base_address) { return UART_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); } -static inline void ibmasm_enable_interrupts(void *base_address, int mask) +static inline void ibmasm_enable_interrupts(void __iomem *base_address, int mask) { - void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + void __iomem *ctrl_reg = base_address + INTR_CONTROL_REGISTER; writel( readl(ctrl_reg) & ~mask, ctrl_reg); } -static inline void ibmasm_disable_interrupts(void *base_address, int mask) +static inline void ibmasm_disable_interrupts(void __iomem *base_address, int mask) { - void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + void __iomem *ctrl_reg = base_address + INTR_CONTROL_REGISTER; writel( readl(ctrl_reg) | mask, ctrl_reg); } -static inline void enable_sp_interrupts(void *base_address) +static inline void enable_sp_interrupts(void __iomem *base_address) { ibmasm_enable_interrupts(base_address, SP_INTR_MASK); } -static inline void disable_sp_interrupts(void *base_address) +static inline void disable_sp_interrupts(void __iomem *base_address) { ibmasm_disable_interrupts(base_address, SP_INTR_MASK); } -static inline void enable_uart_interrupts(void *base_address) +static inline void enable_uart_interrupts(void __iomem *base_address) { ibmasm_enable_interrupts(base_address, UART_INTR_MASK); } -static inline void disable_uart_interrupts(void *base_address) +static inline void disable_uart_interrupts(void __iomem *base_address) { ibmasm_disable_interrupts(base_address, UART_INTR_MASK); } #define valid_mfa(mfa) ( (mfa) != NO_MFAS_AVAILABLE ) -static inline u32 get_mfa_outbound(void *base_address) +static inline u32 get_mfa_outbound(void __iomem *base_address) { int retry; u32 mfa; @@ -109,12 +109,12 @@ static inline u32 get_mfa_outbound(void *base_address) return mfa; } -static inline void set_mfa_outbound(void *base_address, u32 mfa) +static inline void set_mfa_outbound(void __iomem *base_address, u32 mfa) { writel(mfa, base_address + OUTBOUND_QUEUE_PORT); } -static inline u32 get_mfa_inbound(void *base_address) +static inline u32 get_mfa_inbound(void __iomem *base_address) { u32 mfa = readl(base_address + INBOUND_QUEUE_PORT); @@ -124,12 +124,12 @@ static inline u32 get_mfa_inbound(void *base_address) return mfa; } -static inline void set_mfa_inbound(void *base_address, u32 mfa) +static inline void set_mfa_inbound(void __iomem *base_address, u32 mfa) { writel(mfa, base_address + INBOUND_QUEUE_PORT); } -static inline struct i2o_message *get_i2o_message(void *base_address, u32 mfa) +static inline struct i2o_message *get_i2o_message(void __iomem *base_address, u32 mfa) { return (struct i2o_message *)(GET_MFA_ADDR(mfa) + base_address); } diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index ee29ced87..eb7f13093 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -59,13 +59,20 @@ static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - int result = -ENOMEM; + int err, result = -ENOMEM; struct service_processor *sp; + if ((err = pci_enable_device(pdev))) { + printk(KERN_ERR "%s: can't enable PCI device at %s\n", + DRIVER_NAME, pci_name(pdev)); + return err; + } + sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); if (sp == NULL) { dev_err(&pdev->dev, "Failed to allocate memory\n"); - return result; + result = -ENOMEM; + goto error_kmalloc; } memset(sp, 0, sizeof(struct service_processor)); @@ -148,6 +155,8 @@ error_heartbeat: ibmasm_event_buffer_exit(sp); error_eventbuffer: kfree(sp); +error_kmalloc: + pci_disable_device(pdev); return result; } @@ -166,6 +175,7 @@ static void __exit ibmasm_remove_one(struct pci_dev *pdev) iounmap(sp->base_address); ibmasm_event_buffer_exit(sp); kfree(sp); + pci_disable_device(pdev); } static struct pci_device_id ibmasm_pci_table[] = @@ -199,10 +209,9 @@ static int __init ibmasm_init(void) return result; } result = pci_register_driver(&ibmasm_driver); - if (result <= 0) { - pci_unregister_driver(&ibmasm_driver); + if (result) { ibmasmfs_unregister(); - return -ENODEV; + return result; } ibmasm_register_panic_notifier(); info(DRIVER_DESC " version " DRIVER_VERSION " loaded"); @@ -215,3 +224,4 @@ module_exit(ibmasm_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + diff --git a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c index 604b87eca..914804512 100644 --- a/drivers/misc/ibmasm/uart.c +++ b/drivers/misc/ibmasm/uart.c @@ -34,7 +34,7 @@ void ibmasm_register_uart(struct service_processor *sp) { struct serial_struct serial; - unsigned char *iomem_base; + void __iomem *iomem_base; iomem_base = sp->base_address + SCOUT_COM_B_BASE; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 6b1b5177d..21becb1e5 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -49,4 +49,15 @@ config MMC_PXA If unsure, say N. +config MMC_WBSD + tristate "Winbond W83L51xD SD/MMC Card Interface support" + depends on MMC + help + This selects the Winbond(R) W83L51xD Secure digital and + Multimedia card Interface. + If you have a machine with a integrated W83L518D or W83L519D + SD/MMC card reader, say Y or M here. + + If unsure, say N. + endmenu diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index def01111d..89510c208 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -17,5 +17,6 @@ obj-$(CONFIG_MMC_BLOCK) += mmc_block.o # obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o +obj-$(CONFIG_MMC_WBSD) += wbsd.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f76673a47..46d884e6e 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -200,6 +200,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) } brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL; + brq.data.sg = mq->sg; + brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg); + mmc_wait_for_req(card->host, &brq.mrq); if (brq.cmd.error) { printk(KERN_ERR "%s: error %d sending read/write command\n", diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index e818b9233..0b9682e9a 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c @@ -80,7 +80,7 @@ static int mmc_queue_thread(void *d) set_current_state(TASK_INTERRUPTIBLE); if (!blk_queue_plugged(q)) mq->req = req = elv_next_request(q); - spin_unlock(q->queue_lock); + spin_unlock_irq(q->queue_lock); if (!req) { if (mq->flags & MMC_QUEUE_EXIT) @@ -147,19 +147,31 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock mq->queue->queuedata = mq; mq->req = NULL; + mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, + GFP_KERNEL); + if (!mq->sg) { + ret = -ENOMEM; + goto cleanup; + } + init_completion(&mq->thread_complete); init_waitqueue_head(&mq->thread_wq); init_MUTEX(&mq->thread_sem); ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL); - if (ret < 0) { - blk_cleanup_queue(mq->queue); - } else { + if (ret >= 0) { wait_for_completion(&mq->thread_complete); init_completion(&mq->thread_complete); ret = 0; + goto out; } + cleanup: + kfree(mq->sg); + mq->sg = NULL; + + blk_cleanup_queue(mq->queue); + out: return ret; } EXPORT_SYMBOL(mmc_init_queue); @@ -169,6 +181,10 @@ void mmc_cleanup_queue(struct mmc_queue *mq) mq->flags |= MMC_QUEUE_EXIT; wake_up(&mq->thread_wq); wait_for_completion(&mq->thread_complete); + + kfree(mq->sg); + mq->sg = NULL; + blk_cleanup_queue(mq->queue); mq->card = NULL; diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h index 6bef90087..7182d2f69 100644 --- a/drivers/mmc/mmc_queue.h +++ b/drivers/mmc/mmc_queue.h @@ -15,6 +15,7 @@ struct mmc_queue { int (*issue_fn)(struct mmc_queue *, struct request *); void *data; struct request_queue *queue; + struct scatterlist *sg; }; struct mmc_io_request { diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 47e1636de..dd592d0d3 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -69,7 +69,7 @@ static void mmci_stop_data(struct mmci_host *host) static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) { unsigned int datactrl, timeout, irqmask; - void *base; + void __iomem *base; DBG(host, "blksz %04x blks %04x flags %08x\n", 1 << data->blksz_bits, data->blocks, data->flags); @@ -108,7 +108,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) static void mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) { - void *base = host->base; + void __iomem *base = host->base; DBG(host, "op %02x arg %08x flags %08x\n", cmd->opcode, cmd->arg, cmd->flags); @@ -169,7 +169,7 @@ static void mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, unsigned int status) { - void *base = host->base; + void __iomem *base = host->base; host->cmd = NULL; @@ -193,7 +193,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain) { - void *base = host->base; + void __iomem *base = host->base; char *ptr = buffer; u32 status; @@ -222,7 +222,7 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) { - void *base = host->base; + void __iomem *base = host->base; char *ptr = buffer; do { @@ -251,7 +251,7 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs) { struct mmci_host *host = dev_id; - void *base = host->base; + void __iomem *base = host->base; u32 status; status = readl(base + MMCISTATUS); @@ -501,7 +501,7 @@ static int mmci_probe(struct amba_device *dev, void *id) * We can do SGIO */ mmc->max_hw_segs = 16; - mmc->max_phys_segs = 16; + mmc->max_phys_segs = NR_SG; /* * Since we only have a 16-bit data length register, we must diff --git a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h index ce3a026d1..4589bbd68 100644 --- a/drivers/mmc/mmci.h +++ b/drivers/mmc/mmci.h @@ -120,7 +120,7 @@ struct clk; struct mmci_host { - void *base; + void __iomem *base; struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; @@ -139,7 +139,6 @@ struct mmci_host { struct timer_list timer; unsigned int oldstat; - struct scatterlist sg[NR_SG]; unsigned int sg_len; /* pio stuff */ @@ -150,14 +149,11 @@ struct mmci_host { static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) { - struct scatterlist *sg = host->sg; - struct request *req = data->req; - /* * Ideally, we want the higher levels to pass us a scatter list. */ - host->sg_len = blk_rq_map_sg(req->q, req, sg); - host->sg_ptr = sg; + host->sg_len = data->sg_len; + host->sg_ptr = data->sg; host->sg_off = 0; } diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 23a509196..97ee26d8a 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -44,6 +44,10 @@ #define DBG(x...) do { } while (0) #endif +#define DRIVER_NAME "pxa2xx-mci" + +#define NR_SG 1 + struct pxamci_host { struct mmc_host *mmc; spinlock_t lock; @@ -63,17 +67,11 @@ struct pxamci_host { dma_addr_t sg_dma; struct pxa_dma_desc *sg_cpu; + unsigned int dma_len; - dma_addr_t dma_buf; - unsigned int dma_size; unsigned int dma_dir; }; -/* - * The base MMC clock rate - */ -#define CLOCKRATE 20000000 - static inline unsigned int ns_to_clocks(unsigned int ns) { return (ns * (CLOCKRATE / 1000000) + 999) / 1000; @@ -122,8 +120,7 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) { unsigned int nob = data->blocks; - unsigned int timeout, size; - dma_addr_t dma; + unsigned int timeout; u32 dcmd; int i; @@ -152,35 +149,22 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) dcmd |= DCMD_BURST32 | DCMD_WIDTH1; - host->dma_size = data->blocks << data->blksz_bits; - host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer, - host->dma_size, host->dma_dir); - - for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) { - u32 len = size; - - if (len > DCMD_LENGTH) - len = 0x1000; + host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + host->dma_dir); + for (i = 0; i < host->dma_len; i++) { if (data->flags & MMC_DATA_READ) { host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; - host->sg_cpu[i].dtadr = dma; + host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); } else { - host->sg_cpu[i].dsadr = dma; + host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]); host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO; } - host->sg_cpu[i].dcmd = dcmd | len; - - dma += len; - size -= len; - - if (size) { - host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) * - sizeof(struct pxa_dma_desc); - } else { - host->sg_cpu[i].ddadr = DDADR_STOP; - } + host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]); + host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) * + sizeof(struct pxa_dma_desc); } + host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP; wmb(); DDADR(host->dma) = host->sg_dma; @@ -255,7 +239,24 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if (stat & STAT_TIME_OUT_RESPONSE) { cmd->error = MMC_ERR_TIMEOUT; } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { +#ifdef CONFIG_PXA27x + /* + * workaround for erratum #42: + * Intel PXA27x Family Processor Specification Update Rev 001 + */ + if (cmd->opcode == MMC_ALL_SEND_CID || + cmd->opcode == MMC_SEND_CSD || + cmd->opcode == MMC_SEND_CID) { + /* a bogus CRC error can appear if the msb of + the 15 byte response is a one */ + if ((cmd->resp[0] & 0x80000000) == 0) + cmd->error = MMC_ERR_BADCRC; + } else { + DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode); + } +#else cmd->error = MMC_ERR_BADCRC; +#endif } pxamci_disable_irq(host, END_CMD_RES); @@ -276,8 +277,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) return 0; DCSR(host->dma) = 0; - dma_unmap_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size, - host->dma_dir); + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, + host->dma_dir); if (stat & STAT_READ_TIME_OUT) data->error = MMC_ERR_TIMEOUT; @@ -374,15 +375,14 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (CLOCKRATE / clk > ios->clock) clk <<= 1; host->clkrt = fls(clk) - 1; + pxa_set_cken(CKEN12_MMC, 1); /* * we write clkrt on the next command */ - } else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { - /* - * Ensure that the clock is off. - */ - writel(STOP_CLOCK, host->base + MMC_STRPCL); + } else { + pxamci_stop_clock(host); + pxa_set_cken(CKEN12_MMC, 0); } if (host->power_mode != ios->power_mode) { @@ -429,7 +429,7 @@ static int pxamci_probe(struct device *dev) if (!r || irq == NO_IRQ) return -ENXIO; - r = request_mem_region(r->start, SZ_4K, "PXAMCI"); + r = request_mem_region(r->start, SZ_4K, DRIVER_NAME); if (!r) return -EBUSY; @@ -440,8 +440,19 @@ static int pxamci_probe(struct device *dev) } mmc->ops = &pxamci_ops; - mmc->f_min = 312500; - mmc->f_max = 20000000; + mmc->f_min = CLOCKRATE_MIN; + mmc->f_max = CLOCKRATE_MAX; + + /* + * We can do SG-DMA, but we don't because we never know how much + * data we successfully wrote to the card. + */ + mmc->max_phys_segs = NR_SG; + + /* + * Our hardware DMA can handle a maximum of one page per SG entry. + */ + mmc->max_seg_size = PAGE_SIZE; host = mmc_priv(mmc); host->mmc = mmc; @@ -460,8 +471,7 @@ static int pxamci_probe(struct device *dev) spin_lock_init(&host->lock); host->res = r; host->irq = irq; - host->imask = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| - END_CMD_RES|PRG_DONE|DATA_TRAN_DONE; + host->imask = MMC_I_MASK_ALL; host->base = ioremap(r->start, SZ_4K); if (!host->base) { @@ -478,17 +488,14 @@ static int pxamci_probe(struct device *dev) writel(64, host->base + MMC_RESTO); writel(host->imask, host->base + MMC_I_MASK); - pxa_gpio_mode(GPIO6_MMCCLK_MD); - pxa_gpio_mode(GPIO8_MMCCS0_MD); - pxa_set_cken(CKEN12_MMC, 1); - - host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host); + host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW, + pxamci_dma_irq, host); if (host->dma < 0) { ret = -EBUSY; goto out; } - ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host); + ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host); if (ret) goto out; @@ -535,15 +542,14 @@ static int pxamci_remove(struct device *dev) END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, host->base + MMC_I_MASK); - pxa_set_cken(CKEN12_MMC, 0); + DRCMRRXMMC = 0; + DRCMRTXMMC = 0; free_irq(host->irq, host); pxa_free_dma(host->dma); iounmap(host->base); dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); - pxa_set_cken(CKEN12_MMC, 0); - release_resource(host->res); mmc_free_host(mmc); @@ -579,7 +585,7 @@ static int pxamci_resume(struct device *dev, u32 level) #endif static struct device_driver pxamci_driver = { - .name = "pxa2xx-mci", + .name = DRIVER_NAME, .bus = &platform_bus_type, .probe = pxamci_probe, .remove = pxamci_remove, diff --git a/drivers/mmc/pxamci.h b/drivers/mmc/pxamci.h index a80b24db9..1b163220d 100644 --- a/drivers/mmc/pxamci.h +++ b/drivers/mmc/pxamci.h @@ -70,6 +70,16 @@ #define BUF_PART_FULL (1 << 0) #define MMC_I_MASK 0x0028 + +/*PXA27x MMC interrupts*/ +#define SDIO_SUSPEND_ACK (1 << 12) +#define SDIO_INT (1 << 11) +#define RD_STALLED (1 << 10) +#define RES_ERR (1 << 9) +#define DAT_ERR (1 << 8) +#define TINT (1 << 7) + +/*PXA2xx MMC interrupts*/ #define TXFIFO_WR_REQ (1 << 6) #define RXFIFO_RD_REQ (1 << 5) #define CLK_IS_OFF (1 << 4) @@ -78,6 +88,12 @@ #define PRG_DONE (1 << 1) #define DATA_TRAN_DONE (1 << 0) +#ifdef CONFIG_PXA27x +#define MMC_I_MASK_ALL 0x00001fff +#else +#define MMC_I_MASK_ALL 0x0000007f +#endif + #define MMC_I_REG 0x002c /* same as MMC_I_MASK */ @@ -92,3 +108,17 @@ #define MMC_RXFIFO 0x0040 /* 8 bit */ #define MMC_TXFIFO 0x0044 /* 8 bit */ + +/* + * The base MMC clock rate + */ +#ifdef CONFIG_PXA27x +#define CLOCKRATE_MIN 304688 +#define CLOCKRATE_MAX 19500000 +#else +#define CLOCKRATE_MIN 312500 +#define CLOCKRATE_MAX 20000000 +#endif + +#define CLOCKRATE CLOCKRATE_MAX + diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index e71624edb..9028caced 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,8 +4,9 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.154 2004/08/09 13:19:43 dwmw2 Exp $ - * + * $Id: cfi_cmdset_0001.c,v 1.160 2004/11/01 06:02:24 nico Exp $ + * (+ suspend fix from v1.162) + * (+ partition detection fix from v1.163) * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -39,6 +40,12 @@ // debugging, turns off buffer write mode if set to 1 #define FORCE_WORD_WRITE 0 +#define MANUFACTURER_INTEL 0x0089 +#define I82802AB 0x00ad +#define I82802AC 0x00ac +#define MANUFACTURER_ST 0x0020 +#define M50LPW080 0x002F + static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); //static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); //static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); @@ -55,14 +62,19 @@ static void cfi_intelext_destroy(struct mtd_info *); struct mtd_info *cfi_cmdset_0001(struct map_info *, int); -static struct mtd_info *cfi_intelext_setup (struct map_info *); -static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **); +static struct mtd_info *cfi_intelext_setup (struct mtd_info *); +static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **); static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len); +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); +#include "fwh_lock.h" + + /* * *********** SETUP AND PROBE BITS *********** @@ -123,8 +135,9 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ -static void fixup_intel_strataflash(struct map_info *map, void* param) +static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_amdstd *extp = cfi->cmdset_priv; @@ -134,16 +147,18 @@ static void fixup_intel_strataflash(struct map_info *map, void* param) } #endif -static void fixup_st_m28w320ct(struct map_info *map, void* param) +static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */ cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ } -static void fixup_st_m28w320cb(struct map_info *map, void* param) +static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; /* Note this is done after the region info is endian swapped */ @@ -151,26 +166,113 @@ static void fixup_st_m28w320cb(struct map_info *map, void* param) (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; }; -static struct cfi_fixup fixup_table[] = { +static void fixup_use_point(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + if (!mtd->point && map_is_linear(map)) { + mtd->point = cfi_intelext_point; + mtd->unpoint = cfi_intelext_unpoint; + } +} + +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { + printk(KERN_INFO "Using buffer write method\n" ); + mtd->write = cfi_intelext_write_buffers; + } +} + +static struct cfi_fixup cfi_fixup_table[] = { #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE - { - CFI_MFR_ANY, CFI_ID_ANY, - fixup_intel_strataflash, NULL - }, + { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, #endif - { - 0x0020, /* STMicroelectronics */ - 0x00ba, /* M28W320CT */ - fixup_st_m28w320ct, NULL - }, { - 0x0020, /* STMicroelectronics */ - 0x00bb, /* M28W320CB */ - fixup_st_m28w320cb, NULL - }, { - 0, 0, NULL, NULL - } +#if !FORCE_WORD_WRITE + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL }, +#endif + { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL }, + { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL }, + { 0, 0, NULL, NULL } +}; + +static struct cfi_fixup jedec_fixup_table[] = { + { MANUFACTURER_INTEL, I82802AB, fixup_use_fwh_lock, NULL, }, + { MANUFACTURER_INTEL, I82802AC, fixup_use_fwh_lock, NULL, }, + { MANUFACTURER_ST, M50LPW080, fixup_use_fwh_lock, NULL, }, + { 0, 0, NULL, NULL } +}; +static struct cfi_fixup fixup_table[] = { + /* The CFI vendor ids and the JEDEC vendor IDs appear + * to be common. It is like the devices id's are as + * well. This table is to pick all cases where + * we know that is the case. + */ + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL }, + { 0, 0, NULL, NULL } }; +static inline struct cfi_pri_intelext * +read_pri_intelext(struct map_info *map, __u16 adr) +{ + struct cfi_pri_intelext *extp; + unsigned int extp_size = sizeof(*extp); + + again: + extp = (struct cfi_pri_intelext *)cfi_read_pri(map, adr, extp_size, "Intel/Sharp"); + if (!extp) + return NULL; + + /* Do some byteswapping if necessary */ + extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); + extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); + extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); + + if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { + unsigned int extra_size = 0; + int nb_parts, i; + + /* Protection Register info */ + extra_size += (extp->NumProtectionFields - 1) * (4 + 6); + + /* Burst Read info */ + extra_size += 6; + + /* Number of hardware-partitions */ + extra_size += 1; + if (extp_size < sizeof(*extp) + extra_size) + goto need_more; + nb_parts = extp->extra[extra_size - 1]; + + for (i = 0; i < nb_parts; i++) { + struct cfi_intelext_regioninfo *rinfo; + rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; + extra_size += sizeof(*rinfo); + if (extp_size < sizeof(*extp) + extra_size) + goto need_more; + rinfo->NumIdentPartitions=le16_to_cpu(rinfo->NumIdentPartitions); + extra_size += (rinfo->NumBlockTypes - 1) + * sizeof(struct cfi_intelext_blockinfo); + } + + if (extp_size < sizeof(*extp) + extra_size) { + need_more: + extp_size = sizeof(*extp) + extra_size; + kfree(extp); + if (extp_size > 4096) { + printk(KERN_ERR + "%s: cfi_pri_intelext is too fat\n", + __FUNCTION__); + return NULL; + } + goto again; + } + } + + return extp; +} + /* This routine is made available to other mtd code via * inter_module_register. It must only be accessed through * inter_module_get which will bump the use count of this module. The @@ -181,8 +283,30 @@ static struct cfi_fixup fixup_table[] = { struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; int i; + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_ERR "Failed to allocate memory for MTD device\n"); + return NULL; + } + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + + /* Fill in the default mtd operations */ + mtd->erase = cfi_intelext_erase_varsize; + mtd->read = cfi_intelext_read; + mtd->write = cfi_intelext_write_words; + mtd->sync = cfi_intelext_sync; + mtd->lock = cfi_intelext_lock; + mtd->unlock = cfi_intelext_unlock; + mtd->suspend = cfi_intelext_suspend; + mtd->resume = cfi_intelext_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + if (cfi->cfi_mode == CFI_MODE_CFI) { /* * It's a real CFI chip, not one for which the probe @@ -192,20 +316,17 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; struct cfi_pri_intelext *extp; - extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp"); - if (!extp) + extp = read_pri_intelext(map, adr); + if (!extp) { + kfree(mtd); return NULL; - - /* Do some byteswapping if necessary */ - extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); - extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); - extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); + } /* Install our own private info structure */ cfi->cmdset_priv = extp; - cfi_fixup(map, fixup_table); - + cfi_fixup(mtd, cfi_fixup_table); + #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ cfi_tell_features(extp); @@ -215,6 +336,12 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n"); } } + else if (cfi->cfi_mode == CFI_MODE_JEDEC) { + /* Apply jedec specific fixups */ + cfi_fixup(mtd, jedec_fixup_table); + } + /* Apply generic fixups */ + cfi_fixup(mtd, fixup_table); for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; @@ -225,28 +352,19 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) map->fldrv = &cfi_intelext_chipdrv; - return cfi_intelext_setup(map); + return cfi_intelext_setup(mtd); } -static struct mtd_info *cfi_intelext_setup(struct map_info *map) +static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; unsigned long offset = 0; int i,j; unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); - if (!mtd) { - printk(KERN_ERR "Failed to allocate memory for MTD device\n"); - goto setup_err; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; @@ -286,38 +404,14 @@ static struct mtd_info *cfi_intelext_setup(struct map_info *map) mtd->eraseregions[i].numblocks); } - /* Also select the correct geometry setup too */ - mtd->erase = cfi_intelext_erase_varsize; - mtd->read = cfi_intelext_read; - - if (map_is_linear(map)) { - mtd->point = cfi_intelext_point; - mtd->unpoint = cfi_intelext_unpoint; - } - - if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { - printk(KERN_INFO "Using buffer write method\n" ); - mtd->write = cfi_intelext_write_buffers; - } else { - printk(KERN_INFO "Using word write method\n" ); - mtd->write = cfi_intelext_write_words; - } #if 0 mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg; mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg; #endif - mtd->sync = cfi_intelext_sync; - mtd->lock = cfi_intelext_lock; - mtd->unlock = cfi_intelext_unlock; - mtd->suspend = cfi_intelext_suspend; - mtd->resume = cfi_intelext_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_intelext_chipdrv; - mtd->name = map->name; /* This function has the potential to distort the reality a bit and therefore should be called last. */ - if (cfi_intelext_partition_fixup(map, &cfi) != 0) + if (cfi_intelext_partition_fixup(mtd, &cfi) != 0) goto setup_err; __module_get(THIS_MODULE); @@ -333,20 +427,16 @@ static struct mtd_info *cfi_intelext_setup(struct map_info *map) return NULL; } -static int cfi_intelext_partition_fixup(struct map_info *map, +static int cfi_intelext_partition_fixup(struct mtd_info *mtd, struct cfi_private **pcfi) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = *pcfi; struct cfi_pri_intelext *extp = cfi->cmdset_priv; /* * Probing of multi-partition flash ships. * - * This is extremely crude at the moment and should probably be - * extracted entirely from the Intel extended query data instead. - * Right now a L18 flash is assumed if multiple operations is - * detected. - * * To support multiple partitions when available, we simply arrange * for each of them to have their own flchip structure even if they * are on the same physical chip. This means completely recreating @@ -355,20 +445,49 @@ static int cfi_intelext_partition_fixup(struct map_info *map, * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */ - if (extp && extp->FeatureSupport & (1 << 9)) { + if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' + && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip; struct flchip_shared *shared; - int numparts, partshift, numvirtchips, i, j; + int offs, numregions, numparts, partshift, numvirtchips, i, j; + + /* Protection Register info */ + offs = (extp->NumProtectionFields - 1) * (4 + 6); + + /* Burst Read info */ + offs += 6; + + /* Number of partition regions */ + numregions = extp->extra[offs]; + offs += 1; + + /* Number of hardware partitions */ + numparts = 0; + for (i = 0; i < numregions; i++) { + struct cfi_intelext_regioninfo *rinfo; + rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[offs]; + numparts += rinfo->NumIdentPartitions; + offs += sizeof(*rinfo) + + (rinfo->NumBlockTypes - 1) * + sizeof(struct cfi_intelext_blockinfo); + } /* - * The L18 flash memory array is divided - * into multiple 8-Mbit partitions. + * All functions below currently rely on all chips having + * the same geometry so we'll just assume that all hardware + * partitions are of the same size too. */ - numparts = 1 << (cfi->cfiq->DevSize - 20); - partshift = 20 + __ffs(cfi->interleave); - numvirtchips = cfi->numchips * numparts; + partshift = cfi->chipshift - __ffs(numparts); + + if ((1 << partshift) < mtd->erasesize) { + printk( KERN_ERR + "%s: bad number of hw partitions (%d)\n", + __FUNCTION__, numparts); + return -EINVAL; + } + numvirtchips = cfi->numchips * numparts; newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL); if (!newcfi) return -ENOMEM; @@ -398,10 +517,10 @@ static int cfi_intelext_partition_fixup(struct map_info *map, } } - printk(KERN_DEBUG "%s: %d sets of %d interleaved chips " - "--> %d partitions of %#x bytes\n", + printk(KERN_DEBUG "%s: %d set(s) of %d interleaved chips " + "--> %d partitions of %d KiB\n", map->name, cfi->numchips, cfi->interleave, - newcfi->numchips, 1<chipshift); + newcfi->numchips, 1<<(newcfi->chipshift-10)); map->fldrv_priv = newcfi; *pcfi = newcfi; @@ -515,7 +634,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr return 0; case FL_ERASING: - if (!(cfip->FeatureSupport & 2) || + if (!cfip || + !(cfip->FeatureSupport & 2) || !(mode == FL_READY || mode == FL_POINT || (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) goto sleep; @@ -603,6 +723,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad } spin_unlock(&shared->lock); } + } else { + spin_unlock(&shared->lock); } } @@ -820,6 +942,7 @@ static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, siz } return ret; } + #if 0 static int cfi_intelext_read_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, int base_offst, int reg_sz) { @@ -882,7 +1005,7 @@ static int cfi_intelext_read_user_prot_reg (struct mtd_info *mtd, loff_t from, s int base_offst,reg_sz; /* Check that we actually have some protection registers */ - if(!(extp->FeatureSupport&64)){ + if(!extp || !(extp->FeatureSupport&64)){ printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name); return 0; } @@ -901,7 +1024,7 @@ static int cfi_intelext_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, s int base_offst,reg_sz; /* Check that we actually have some protection registers */ - if(!(extp->FeatureSupport&64)){ + if(!extp || !(extp->FeatureSupport&64)){ printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name); return 0; } @@ -987,6 +1110,7 @@ static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned /* Done and happy. */ chip->state = FL_STATUS; + /* check for lock bit */ if (map_word_bitsset(map, status, CMD(0x02))) { /* clear status */ @@ -1138,13 +1262,15 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, if (++z > 20) { /* Argh. Not ready for write to buffer */ + map_word Xstatus; map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; - printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx, status = %lx\n", - status.x[0], map_read(map, cmd_adr).x[0]); + Xstatus = map_read(map, cmd_adr); /* Odd. Clear status bits */ map_write(map, CMD(0x50), cmd_adr); map_write(map, CMD(0x70), cmd_adr); + printk(KERN_ERR "Chip not ready for buffer write. status = %lx, Xstatus = %lx\n", + status.x[0], Xstatus.x[0]); ret = -EIO; goto out; } @@ -1306,102 +1432,6 @@ static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, return 0; } -typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk); - -static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, - loff_t ofs, size_t len, void *thunk) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - - if (ofs > mtd->size) - return -EINVAL; - - if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are - * aligned with the erasesize at the appropriate addresses. - */ - - i = 0; - - /* Skip all erase regions which are ended before the start of - the requested erase. Actually, to save on the calculations, - we skip to the first erase region which starts after the - start of the requested erase, and then go back one. - */ - - while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - - /* OK, now i is pointing at the erase region in which this - erase request starts. Check the start of the requested - erase range is aligned with the erase size which is in - effect here. - */ - - if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ - first = i; - - /* Next, check that the end of the requested erase is aligned - * with the erase region at that address. - */ - - while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which - the address actually falls - */ - i--; - - if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - - chipnum = ofs >> cfi->chipshift; - adr = ofs - (chipnum << cfi->chipshift); - - i=first; - - while(len) { - unsigned long chipmask; - int size = regions[i].erasesize; - - ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk); - - if (ret) - return ret; - - adr += size; - len -= size; - - chipmask = (1 << cfi->chipshift) - 1; - if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask)) - i++; - - if (adr >> cfi->chipshift) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - return 0; -} - - static int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { @@ -1437,8 +1467,7 @@ static int do_erase_oneblock(struct map_info *map, struct flchip *chip, spin_unlock(chip->mutex); INVALIDATE_CACHED_RANGE(map, adr, len); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((chip->erase_time*HZ)/(2*1000)); + msleep(chip->erase_time / 2); spin_lock(chip->mutex); /* FIXME. Use a timer to check this, and return immediately. */ @@ -1469,16 +1498,17 @@ static int do_erase_oneblock(struct map_info *map, struct flchip *chip, /* OK Still waiting */ if (time_after(jiffies, timeo)) { + map_word Xstatus; map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; - printk(KERN_ERR "waiting for erase at %08lx to complete timed out. Xstatus = %lx, status = %lx.\n", - adr, status.x[0], map_read(map, adr).x[0]); + Xstatus = map_read(map, adr); /* Clear status bits */ map_write(map, CMD(0x50), adr); map_write(map, CMD(0x70), adr); - DISABLE_VPP(map); - spin_unlock(chip->mutex); - return -EIO; + printk(KERN_ERR "waiting for erase at %08lx to complete timed out. status = %lx, Xstatus = %lx.\n", + adr, status.x[0], Xstatus.x[0]); + ret = -EIO; + goto out; } /* Latency issues. Drop the lock, wait a while and retry */ @@ -1487,9 +1517,6 @@ static int do_erase_oneblock(struct map_info *map, struct flchip *chip, schedule_timeout(1); spin_lock(chip->mutex); } - - DISABLE_VPP(map); - ret = 0; /* We've broken this before. It doesn't hurt to be safe */ map_write(map, CMD(0x70), adr); @@ -1498,7 +1525,13 @@ static int do_erase_oneblock(struct map_info *map, struct flchip *chip, /* check for lock bit */ if (map_word_bitsset(map, status, CMD(0x3a))) { - unsigned char chipstatus = status.x[0]; + unsigned char chipstatus; + + /* Reset the error bits */ + map_write(map, CMD(0x50), adr); + map_write(map, CMD(0x70), adr); + + chipstatus = status.x[0]; if (!map_word_equal(map, status, CMD(chipstatus))) { int i, w; for (w=0; wstate = FL_STATUS; + put_chip(map, chip, adr); spin_unlock(chip->mutex); goto retry; } printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus); ret = -EIO; } + } else { + ret = 0; } - wake_up(&chip->wq); + out: put_chip(map, chip, adr); spin_unlock(chip->mutex); return ret; } @@ -1549,7 +1581,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ofs = instr->addr; len = instr->len; - ret = cfi_intelext_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); if (ret) return ret; @@ -1604,12 +1636,13 @@ static int do_printlockstatus_oneblock(struct map_info *map, struct flchip *chip unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; - int ofs_factor = cfi->interleave * cfi->device_type; + int status, ofs_factor = cfi->interleave * cfi->device_type; cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); - printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", - adr, cfi_read_query(map, adr+(2*ofs_factor))); chip->state = FL_JEDEC_QUERY; + status = cfi_read_query(map, adr+(2*ofs_factor)); + printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", + adr, status); return 0; } #endif @@ -1665,11 +1698,13 @@ static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, /* OK Still waiting */ if (time_after(jiffies, timeo)) { + map_word Xstatus; map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; - printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n", - status.x[0], map_read(map, adr).x[0]); - DISABLE_VPP(map); + Xstatus = map_read(map, adr); + printk(KERN_ERR "waiting for unlock to complete timed out. status = %lx, Xstatus = %lx.\n", + status.x[0], Xstatus.x[0]); + put_chip(map, chip, adr); spin_unlock(chip->mutex); return -EIO; } @@ -1694,18 +1729,18 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", __FUNCTION__, ofs, len); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock, - ofs, len, DO_XXLOCK_ONEBLOCK_LOCK); + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, + ofs, len, DO_XXLOCK_ONEBLOCK_LOCK); #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif return ret; @@ -1718,18 +1753,18 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", __FUNCTION__, ofs, len); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif - ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock, + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK); #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); - cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, - ofs, len, 0); + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + ofs, len, 0); #endif return ret; @@ -1760,9 +1795,18 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) * as the whole point is that nobody can do anything * with the chip now anyway. */ + } else { + /* There seems to be an operation pending. We must wait for it. */ + printk(KERN_NOTICE "Flash device refused suspend due to pending operation (oldstate %d)\n", chip->oldstate); + ret = -EAGAIN; } break; default: + /* Should we actually wait? Once upon a time these routines weren't + allowed to. Or should we return -EAGAIN, because the upper layers + ought to have already shut down anything which was using the device + anyway? The latter for now. */ + printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->oldstate); ret = -EAGAIN; case FL_PM_SUSPENDED: break; @@ -1783,6 +1827,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) because we're returning failure, and it didn't get power cycled */ chip->state = chip->oldstate; + chip->oldstate = FL_READY; wake_up(&chip->wq); } spin_unlock(chip->mutex); @@ -1808,7 +1853,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd) /* Go to known state. Chip may have been power cycled */ if (chip->state == FL_PM_SUSPENDED) { map_write(map, CMD(0xFF), cfi->chips[i].start); - chip->state = FL_READY; + chip->oldstate = chip->state = FL_READY; wake_up(&chip->wq); } diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 5bd15f548..69a612659 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -13,7 +13,7 @@ * * This code is GPL * - * $Id: cfi_cmdset_0002.c,v 1.106 2004/08/09 14:02:32 dwmw2 Exp $ + * $Id: cfi_cmdset_0002.c,v 1.111 2004/11/16 18:29:00 dwmw2 Exp $ * */ @@ -40,13 +40,15 @@ #define MAX_WORD_RETRIES 3 +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_SST 0x00BF +#define SST49LF004B 0x0060 + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); -static int cfi_amdstd_lock_varsize(struct mtd_info *, loff_t, size_t); -static int cfi_amdstd_unlock_varsize(struct mtd_info *, loff_t, size_t); static void cfi_amdstd_sync (struct mtd_info *); static int cfi_amdstd_suspend (struct mtd_info *); static void cfi_amdstd_resume (struct mtd_info *); @@ -55,8 +57,11 @@ static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u static void cfi_amdstd_destroy(struct mtd_info *); struct mtd_info *cfi_cmdset_0002(struct map_info *, int); -static struct mtd_info *cfi_amdstd_setup (struct map_info *); +static struct mtd_info *cfi_amdstd_setup (struct mtd_info *); +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); +static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); +#include "fwh_lock.h" static struct mtd_chip_driver cfi_amdstd_chipdrv = { .probe = NULL, /* Not usable directly */ @@ -66,7 +71,6 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = { }; -/* #define DEBUG_LOCK_BITS */ /* #define DEBUG_CFI_FEATURES */ @@ -122,8 +126,9 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) #ifdef AMD_BOOTLOC_BUG /* Wheee. Bring me the head of someone at AMD. */ -static void fixup_amd_bootblock(struct map_info *map, void* param) +static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_amdstd *extp = cfi->cmdset_priv; __u8 major = extp->MajorVersion; @@ -141,25 +146,92 @@ static void fixup_amd_bootblock(struct map_info *map, void* param) } #endif -static struct cfi_fixup fixup_table[] = { +static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { + DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); + mtd->write = cfi_amdstd_write_buffers; + } +} + +static void fixup_use_secsi(struct mtd_info *mtd, void *param) +{ + /* Setup for chips with a secsi area */ + mtd->read_user_prot_reg = cfi_amdstd_secsi_read; + mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; +} + +static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if ((cfi->cfiq->NumEraseRegions == 1) && + ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) { + mtd->erase = cfi_amdstd_erase_chip; + } + +} + +static struct cfi_fixup cfi_fixup_table[] = { #ifdef AMD_BOOTLOC_BUG - { - 0x0001, /* AMD */ - CFI_ID_ANY, - fixup_amd_bootblock, NULL - }, + { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, +#endif + { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, + { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, +#if !FORCE_WORD_WRITE + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif { 0, 0, NULL, NULL } }; +static struct cfi_fixup jedec_fixup_table[] = { + { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, + { 0, 0, NULL, NULL } +}; + +static struct cfi_fixup fixup_table[] = { + /* The CFI vendor ids and the JEDEC vendor IDs appear + * to be common. It is like the devices id's are as + * well. This table is to pick all cases where + * we know that is the case. + */ + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, + { 0, 0, NULL, NULL } +}; struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; - unsigned char bootloc; + struct mtd_info *mtd; int i; + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); + return NULL; + } + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + + /* Fill in the default mtd operations */ + mtd->erase = cfi_amdstd_erase_varsize; + mtd->write = cfi_amdstd_write_words; + mtd->read = cfi_amdstd_read; + mtd->sync = cfi_amdstd_sync; + mtd->suspend = cfi_amdstd_suspend; + mtd->resume = cfi_amdstd_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + if (cfi->cfi_mode==CFI_MODE_CFI){ + unsigned char bootloc; /* * It's a real CFI chip, not one for which the probe * routine faked a CFI structure. So we read the feature @@ -169,13 +241,16 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) struct cfi_pri_amdstd *extp; extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); - if (!extp) + if (!extp) { + kfree(mtd); return NULL; + } /* Install our own private info structure */ cfi->cmdset_priv = extp; - cfi_fixup(map, fixup_table); + /* Apply cfi device specific fixups */ + cfi_fixup(mtd, cfi_fixup_table); #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ @@ -201,43 +276,28 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) cfi->cfiq->EraseRegionInfo[j] = swap; } } - /* - * These might already be setup (more correctly) by - * jedec_probe.c - still need it for cfi_probe.c path. - */ - if ( ! (cfi->addr_unlock1 && cfi->addr_unlock2) ) { - switch (cfi->device_type) { - case CFI_DEVICETYPE_X8: - cfi->addr_unlock1 = 0x555; - cfi->addr_unlock2 = 0x2aa; - break; - case CFI_DEVICETYPE_X16: - cfi->addr_unlock1 = 0xaaa; - if (map_bankwidth(map) == cfi_interleave(cfi)) { - /* X16 chip(s) in X8 mode */ - cfi->addr_unlock2 = 0x555; - } else { - cfi->addr_unlock2 = 0x554; - } - break; - case CFI_DEVICETYPE_X32: - cfi->addr_unlock1 = 0x1554; - if (map_bankwidth(map) == cfi_interleave(cfi)*2) { - /* X32 chip(s) in X16 mode */ - cfi->addr_unlock1 = 0xaaa; - } else { - cfi->addr_unlock2 = 0xaa8; - } - break; - default: - printk(KERN_WARNING - "MTD %s(): Unsupported device type %d\n", - __func__, cfi->device_type); - return NULL; - } + /* Set the default CFI lock/unlock addresses */ + cfi->addr_unlock1 = 0x555; + cfi->addr_unlock2 = 0x2aa; + /* Modify the unlock address if we are in compatibility mode */ + if ( /* x16 in x8 mode */ + ((cfi->device_type == CFI_DEVICETYPE_X8) && + (cfi->cfiq->InterfaceDesc == 2)) || + /* x32 in x16 mode */ + ((cfi->device_type == CFI_DEVICETYPE_X16) && + (cfi->cfiq->InterfaceDesc == 4))) + { + cfi->addr_unlock1 = 0xaaa; + cfi->addr_unlock2 = 0x555; } } /* CFI mode */ + else if (cfi->cfi_mode == CFI_MODE_JEDEC) { + /* Apply jedec specific fixups */ + cfi_fixup(mtd, jedec_fixup_table); + } + /* Apply generic fixups */ + cfi_fixup(mtd, fixup_table); for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; @@ -246,32 +306,22 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) } map->fldrv = &cfi_amdstd_chipdrv; - - return cfi_amdstd_setup(map); + + return cfi_amdstd_setup(mtd); } -static struct mtd_info *cfi_amdstd_setup(struct map_info *map) +static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - struct mtd_info *mtd; unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; unsigned long offset = 0; int i,j; - mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); printk(KERN_NOTICE "number of %s chips: %d\n", (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips); - - if (!mtd) { - printk(KERN_WARNING "Failed to allocate memory for MTD device\n"); - goto setup_err; - } - - memset(mtd, 0, sizeof(*mtd)); - mtd->priv = map; - mtd->type = MTD_NORFLASH; - /* Also select the correct geometry setup too */ + /* Select the correct geometry setup */ mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; @@ -312,54 +362,10 @@ static struct mtd_info *cfi_amdstd_setup(struct map_info *map) } #endif - if (mtd->numeraseregions == 1 - && ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) { - mtd->erase = cfi_amdstd_erase_chip; - } else { - mtd->erase = cfi_amdstd_erase_varsize; - mtd->lock = cfi_amdstd_lock_varsize; - mtd->unlock = cfi_amdstd_unlock_varsize; - } - - if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) { - DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); - mtd->write = cfi_amdstd_write_buffers; - } else { - DEBUG(MTD_DEBUG_LEVEL1, "Using word write method\n" ); - mtd->write = cfi_amdstd_write_words; - } - - mtd->read = cfi_amdstd_read; - /* FIXME: erase-suspend-program is broken. See http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */ printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); - /* does this chip have a secsi area? */ - if(cfi->mfr==1){ - - switch(cfi->id){ - case 0x50: - case 0x53: - case 0x55: - case 0x56: - case 0x5C: - case 0x5F: - /* Yes */ - mtd->read_user_prot_reg = cfi_amdstd_secsi_read; - mtd->read_fact_prot_reg = cfi_amdstd_secsi_read; - default: - ; - } - } - - - mtd->sync = cfi_amdstd_sync; - mtd->suspend = cfi_amdstd_suspend; - mtd->resume = cfi_amdstd_resume; - mtd->flags = MTD_CAP_NORFLASH; - map->fldrv = &cfi_amdstd_chipdrv; - mtd->name = map->name; __module_get(THIS_MODULE); return mtd; @@ -434,6 +440,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr goto sleep; if (!(mode == FL_READY || mode == FL_POINT + || !cfip || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)) || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)))) goto sleep; @@ -624,14 +631,12 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi chip->state = FL_READY; - /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); map_copy_from(map, buf, adr, len); - /* should these be CFI_DEVICETYPE_X8 instead of cfi->device_type? */ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -732,17 +737,9 @@ static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned ENABLE_VPP(map); retry: - /* - * The CFI_DEVICETYPE_X8 argument is needed even when - * cfi->device_type != CFI_DEVICETYPE_X8. The addresses for - * command sequences don't scale even when the device is - * wider. This is the case for many of the cfi_send_gen_cmd() - * below. I'm not sure, however, why some use - * cfi->device_type. - */ - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); map_write(map, datum, adr); chip->state = FL_WRITING; @@ -958,7 +955,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, struct cfi_private *cfi = map->fldrv_priv; unsigned long timeo = jiffies + HZ; /* see comments in do_write_oneword() regarding uWriteTimeo. */ - static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; + unsigned long uWriteTimeout = ( HZ / 1000 ) + 1; int ret = -EIO; unsigned long cmd_adr; int z, words; @@ -980,9 +977,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, __func__, adr, datum.x[0] ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); /* Write Buffer Load */ map_write(map, CMD(0x25), cmd_adr); @@ -1081,8 +1078,8 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, size_t local_len = (-ofs)&(map_bankwidth(map)-1); if (local_len > len) local_len = len; - ret = cfi_amdstd_write_words(mtd, to, local_len, - retlen, buf); + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), + local_len, retlen, buf); if (ret) return ret; ofs += local_len; @@ -1128,7 +1125,8 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, if (len) { size_t retlen_dregs = 0; - ret = cfi_amdstd_write_words(mtd, to, len, &retlen_dregs, buf); + ret = cfi_amdstd_write_words(mtd, ofs + (chipnum<chipshift), + len, &retlen_dregs, buf); *retlen += retlen_dregs; return ret; @@ -1163,12 +1161,12 @@ static inline int do_erase_chip(struct map_info *map, struct flchip *chip) __func__, chip->start ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x10, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); chip->state = FL_ERASING; chip->erase_suspended = 0; @@ -1229,100 +1227,7 @@ static inline int do_erase_chip(struct map_info *map, struct flchip *chip) } -typedef int (*frob_t)(struct map_info *map, struct flchip *chip, - unsigned long adr, void *thunk); - - -static int cfi_amdstd_varsize_frob(struct mtd_info *mtd, frob_t frob, - loff_t ofs, size_t len, void *thunk) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - unsigned long adr; - int chipnum, ret = 0; - int i, first; - struct mtd_erase_region_info *regions = mtd->eraseregions; - - if (ofs > mtd->size) - return -EINVAL; - - if ((len + ofs) > mtd->size) - return -EINVAL; - - /* Check that both start and end of the requested erase are - * aligned with the erasesize at the appropriate addresses. - */ - - i = 0; - - /* Skip all erase regions which are ended before the start of - the requested erase. Actually, to save on the calculations, - we skip to the first erase region which starts after the - start of the requested erase, and then go back one. - */ - - while (i < mtd->numeraseregions && ofs >= regions[i].offset) - i++; - i--; - - /* OK, now i is pointing at the erase region in which this - erase request starts. Check the start of the requested - erase range is aligned with the erase size which is in - effect here. - */ - - if (ofs & (regions[i].erasesize-1)) - return -EINVAL; - - /* Remember the erase region we start on */ - first = i; - - /* Next, check that the end of the requested erase is aligned - * with the erase region at that address. - */ - - while (inumeraseregions && (ofs + len) >= regions[i].offset) - i++; - - /* As before, drop back one to point at the region in which - the address actually falls - */ - i--; - - if ((ofs + len) & (regions[i].erasesize-1)) - return -EINVAL; - - chipnum = ofs >> cfi->chipshift; - adr = ofs - (chipnum << cfi->chipshift); - - i=first; - - while (len) { - ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk); - - if (ret) - return ret; - - adr += regions[i].erasesize; - len -= regions[i].erasesize; - - if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) - i++; - - if (adr >> cfi->chipshift) { - adr = 0; - chipnum++; - - if (chipnum >= cfi->numchips) - break; - } - } - - return 0; -} - - -static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; unsigned long timeo = jiffies + HZ; @@ -1342,11 +1247,11 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u __func__, adr ); ENABLE_VPP(map); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); map_write(map, CMD(0x30), adr); chip->state = FL_ERASING; @@ -1415,7 +1320,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ofs = instr->addr; len = instr->len; - ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); + ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL); if (ret) return ret; @@ -1588,137 +1493,6 @@ static void cfi_amdstd_resume(struct mtd_info *mtd) } } - -#ifdef DEBUG_LOCK_BITS - -static int do_printlockstatus_oneblock(struct map_info *map, - struct flchip *chip, - unsigned long adr, - void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - int ofs_factor = cfi->interleave * cfi->device_type; - - cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); - printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", - adr, cfi_read_query(map, adr+(2*ofs_factor))); - cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); - - return 0; -} - - -#define debug_dump_locks(mtd, frob, ofs, len, thunk) \ - cfi_amdstd_varsize_frob((mtd), (frob), (ofs), (len), (thunk)) - -#else - -#define debug_dump_locks(...) - -#endif /* DEBUG_LOCK_BITS */ - - -struct xxlock_thunk { - uint8_t val; - flstate_t state; -}; - - -#define DO_XXLOCK_ONEBLOCK_LOCK ((struct xxlock_thunk){0x01, FL_LOCKING}) -#define DO_XXLOCK_ONEBLOCK_UNLOCK ((struct xxlock_thunk){0x00, FL_UNLOCKING}) - - -/* - * FIXME - this is *very* specific to a particular chip. It likely won't - * work for all chips that require unlock. It also hasn't been tested - * with interleaved chips. - */ -static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - struct xxlock_thunk *xxlt = (struct xxlock_thunk *)thunk; - int ret; - - /* - * This is easy because these are writes to registers and not writes - * to flash memory - that means that we don't have to check status - * and timeout. - */ - - adr += chip->start; - /* - * lock block registers: - * - on 64k boundariesand - * - bit 1 set high - * - block lock registers are 4MiB lower - overflow subtract (danger) - */ - adr = ((adr & ~0xffff) | 0x2) + ~0x3fffff; - - cfi_spin_lock(chip->mutex); - ret = get_chip(map, chip, adr, FL_LOCKING); - if (ret) { - cfi_spin_unlock(chip->mutex); - return ret; - } - - chip->state = xxlt->state; - map_write(map, CMD(xxlt->val), adr); - - /* Done and happy. */ - chip->state = FL_READY; - put_chip(map, chip, adr); - cfi_spin_unlock(chip->mutex); - return 0; -} - - -static int cfi_amdstd_lock_varsize(struct mtd_info *mtd, - loff_t ofs, - size_t len) -{ - int ret; - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n", - __func__, ofs, len); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, - (void *)&DO_XXLOCK_ONEBLOCK_LOCK); - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status after, ret=%d\n", - __func__, ret); - - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - return ret; -} - - -static int cfi_amdstd_unlock_varsize(struct mtd_info *mtd, - loff_t ofs, - size_t len) -{ - int ret; - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n", - __func__, ofs, len); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, - (void *)&DO_XXLOCK_ONEBLOCK_UNLOCK); - - DEBUG(MTD_DEBUG_LEVEL3, - "%s: lock status after, ret=%d\n", - __func__, ret); - debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0); - - return ret; -} - - static void cfi_amdstd_destroy(struct mtd_info *mtd) { struct map_info *map = mtd->priv; @@ -1732,7 +1506,7 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) static char im_name[]="cfi_cmdset_0002"; -int __init cfi_amdstd_init(void) +static int __init cfi_amdstd_init(void) { inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); return 0; diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 326eaf7a2..e5957ceaa 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: cfi_cmdset_0020.c,v 1.16 2004/11/16 18:29:00 dwmw2 Exp $ * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -1401,7 +1401,7 @@ static void cfi_staa_destroy(struct mtd_info *mtd) static char im_name[]="cfi_cmdset_0020"; -int __init cfi_staa_init(void) +static int __init cfi_staa_init(void) { inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020); return 0; diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 071be4220..c2a3894d5 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.77 2004/07/14 08:38:44 dwmw2 Exp $ + $Id: cfi_probe.c,v 1.79 2004/10/20 23:04:01 dwmw2 Exp $ */ #include @@ -39,25 +39,24 @@ static int qry_present(struct map_info *map, __u32 base, struct cfi_private *cfi) { int osf = cfi->interleave * cfi->device_type; // scale factor - map_word val; - map_word qry; + map_word val[3]; + map_word qry[3]; - qry = cfi_build_cmd('Q', map, cfi); - val = map_read(map, base + osf*0x10); + qry[0] = cfi_build_cmd('Q', map, cfi); + qry[1] = cfi_build_cmd('R', map, cfi); + qry[2] = cfi_build_cmd('Y', map, cfi); - if (!map_word_equal(map, qry, val)) - return 0; - - qry = cfi_build_cmd('R', map, cfi); - val = map_read(map, base + osf*0x11); + val[0] = map_read(map, base + osf*0x10); + val[1] = map_read(map, base + osf*0x11); + val[2] = map_read(map, base + osf*0x12); - if (!map_word_equal(map, qry, val)) + if (!map_word_equal(map, qry[0], val[0])) return 0; - qry = cfi_build_cmd('Y', map, cfi); - val = map_read(map, base + osf*0x12); + if (!map_word_equal(map, qry[1], val[1])) + return 0; - if (!map_word_equal(map, qry, val)) + if (!map_word_equal(map, qry[2], val[2])) return 0; return 1; // nothing found @@ -243,12 +242,27 @@ static char *vendorname(__u16 vendor) case P_ID_AMD_EXT: return "AMD/Fujitsu Extended"; + + case P_ID_WINBOND: + return "Winbond Standard"; + case P_ID_ST_ADV: + return "ST Advanced"; + case P_ID_MITSUBISHI_STD: return "Mitsubishi Standard"; case P_ID_MITSUBISHI_EXT: return "Mitsubishi Extended"; + + case P_ID_SST_PAGE: + return "SST Page Write"; + + case P_ID_INTEL_PERFORMANCE: + return "Intel Performance Code"; + + case P_ID_INTEL_DATA: + return "Intel Data"; case P_ID_RESERVED: return "Not Allowed / Reserved for Future Use"; @@ -327,6 +341,10 @@ static void print_cfi_ident(struct cfi_ident *cfip) printk(" - x32-only asynchronous interface\n"); break; + case 4: + printk(" - supports x16 and x32 via Word# with asynchronous interface\n"); + break; + case 65535: printk(" - Not Allowed / Reserved\n"); break; diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index d1a785628..49c97bc96 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -7,7 +7,7 @@ * * This code is covered by the GPL. * - * $Id: cfi_util.c,v 1.4 2004/07/14 08:38:44 dwmw2 Exp $ + * $Id: cfi_util.c,v 1.5 2004/08/12 06:40:23 eric Exp $ * */ @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -74,19 +75,114 @@ out: EXPORT_SYMBOL(cfi_read_pri); -void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups) +void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups) { + struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; struct cfi_fixup *f; for (f=fixups; f->fixup; f++) { if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) && ((f->id == CFI_ID_ANY) || (f->id == cfi->id))) { - f->fixup(map, f->param); + f->fixup(mtd, f->param); } } } EXPORT_SYMBOL(cfi_fixup); +int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, + loff_t ofs, size_t len, void *thunk) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr; + int chipnum, ret = 0; + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (ofs > mtd->size) + return -EINVAL; + + if ((len + ofs) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && ofs >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (ofs & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (ofs + len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((ofs + len) & (regions[i].erasesize-1)) + return -EINVAL; + + chipnum = ofs >> cfi->chipshift; + adr = ofs - (chipnum << cfi->chipshift); + + i=first; + + while(len) { + unsigned long chipmask; + int size = regions[i].erasesize; + + ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk); + + if (ret) + return ret; + + adr += size; + len -= size; + + chipmask = (1 << cfi->chipshift) - 1; + if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask)) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + return 0; +} + +EXPORT_SYMBOL(cfi_varsize_frob); + MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index 1e45df074..cd699cb3c 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c @@ -1,5 +1,5 @@ /* - * $Id: chipreg.c,v 1.16 2003/05/29 09:36:15 dwmw2 Exp $ + * $Id: chipreg.c,v 1.17 2004/11/16 18:29:00 dwmw2 Exp $ * * Registration for chip drivers * @@ -15,7 +15,7 @@ #include #include -spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(chip_drvs_list); void register_mtd_chip_driver(struct mtd_chip_driver *drv) diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 3615fd815..fc982c467 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.19 2004/07/13 22:33:32 dwmw2 Exp $ + * $Id: gen_probe.c,v 1.21 2004/08/14 15:14:05 dwmw2 Exp $ */ #include @@ -64,7 +64,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi interleave and device type, etc. */ if (!genprobe_new_chip(map, cp, &cfi)) { /* The probe didn't like it */ - printk(KERN_WARNING "%s: Found no %s device at location zero\n", + printk(KERN_DEBUG "%s: Found no %s device at location zero\n", cp->name, map->name); return NULL; } @@ -169,8 +169,12 @@ static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, cfi->interleave = nr_chips; - for (type = 0; type < 3; type++) { - cfi->device_type = 1<device_type = type; if (cp->probe_chip(map, 0, NULL, cfi)) return 1; diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index daf554c00..3e232fd0f 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: jedec_probe.c,v 1.51 2004/07/14 14:44:30 thayne Exp $ + $Id: jedec_probe.c,v 1.58 2004/11/16 18:29:00 dwmw2 Exp $ See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. @@ -29,6 +29,7 @@ #define MANUFACTURER_AMD 0x0001 #define MANUFACTURER_ATMEL 0x001f #define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_HYUNDAI 0x00AD #define MANUFACTURER_INTEL 0x0089 #define MANUFACTURER_MACRONIX 0x00C2 #define MANUFACTURER_PMC 0x009D @@ -56,6 +57,7 @@ #define AM29F040 0x00A4 #define AM29LV040B 0x004F #define AM29F032B 0x0041 +#define AM29F002T 0x00B0 /* Atmel */ #define AT49BV512 0x0003 @@ -77,6 +79,8 @@ #define MBM29LV400TC 0x22B9 #define MBM29LV400BC 0x22BA +/* Hyundai */ +#define HY29F002T 0x00B0 /* Intel */ #define I28F004B3T 0x00d4 @@ -103,9 +107,11 @@ #define I82802AC 0x00ac /* Macronix */ +#define MX29LV040C 0x004F #define MX29LV160T 0x22C4 #define MX29LV160B 0x2249 #define MX29F016 0x00AD +#define MX29F002T 0x00B0 #define MX29F004T 0x0045 #define MX29F004B 0x0046 @@ -123,6 +129,7 @@ #define M50FW040 0x002C #define M50FW080 0x002D #define M50FW016 0x002E +#define M50LPW080 0x002F /* SST */ #define SST29EE020 0x0010 @@ -176,8 +183,8 @@ enum uaddr { struct unlock_addr { - int addr1; - int addr2; + u32 addr1; + u32 addr2; }; @@ -506,6 +513,17 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO(0x10000,8), } + }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F002T, + name: "AMD AM29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } }, { .mfr_id = MANUFACTURER_ATMEL, .dev_id = AT49BV512, @@ -751,6 +769,17 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x02000,2), ERASEINFO(0x04000,1) } + }, { + mfr_id: MANUFACTURER_HYUNDAI, + dev_id: HY29F002T, + name: "Hyundai HY29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } }, { .mfr_id = MANUFACTURER_INTEL, .dev_id = I28F004B3B, @@ -1055,6 +1084,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO(0x10000,16), } + }, { + .mfr_id = MANUFACTURER_MACRONIX, + .dev_id = MX29LV040C, + .name = "Macronix MX29LV040C", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */ + }, + .DevSize = SIZE_512KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x10000,8), + } }, { .mfr_id = MANUFACTURER_MACRONIX, .dev_id = MX29LV160T, @@ -1134,6 +1176,17 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x08000,1), ERASEINFO(0x10000,7), } + }, { + mfr_id: MANUFACTURER_MACRONIX, + dev_id: MX29F002T, + name: "Macronix MX29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } }, { .mfr_id = MANUFACTURER_PMC, .dev_id = PM49FL002, @@ -1341,6 +1394,22 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x01000,256), } }, { + .mfr_id = MANUFACTURER_SST, /* should be CFI */ + .dev_id = SST39LF160, + .name = "SST 39LF160", + .uaddr = { + [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */ + [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */ + }, + .DevSize = SIZE_2MiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 2, + .regions = { + ERASEINFO(0x1000,256), + ERASEINFO(0x1000,256) + } + + }, { .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ .dev_id = M29W800DT, .name = "ST M29W800DT", @@ -1460,6 +1529,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO(0x10000,32), } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M50LPW080, + .name = "ST M50LPW080", + .uaddr = { + [0] = MTD_UADDR_UNNECESSARY, /* x8 */ + }, + .DevSize = SIZE_1MiB, + .CmdSet = P_ID_INTEL_EXT, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x10000,16), + } }, { .mfr_id = MANUFACTURER_TOSHIBA, .dev_id = TC58FVT160, @@ -1570,7 +1652,7 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x02000, 2), ERASEINFO(0x04000, 1), } - } + } }; @@ -1579,27 +1661,27 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index); static int jedec_probe_chip(struct map_info *map, __u32 base, unsigned long *chip_map, struct cfi_private *cfi); -struct mtd_info *jedec_probe(struct map_info *map); +static struct mtd_info *jedec_probe(struct map_info *map); static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, struct cfi_private *cfi) { map_word result; unsigned long mask; + u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type); mask = (1 << (cfi->device_type * 8)) -1; - result = map_read(map, base); + result = map_read(map, base + ofs); return result.x[0] & mask; } static inline u32 jedec_read_id(struct map_info *map, __u32 base, struct cfi_private *cfi) { - int osf; map_word result; unsigned long mask; - osf = cfi->interleave *cfi->device_type; + u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); mask = (1 << (cfi->device_type * 8)) -1; - result = map_read(map, base + osf); + result = map_read(map, base + ofs); return result.x[0] & mask; } @@ -1615,9 +1697,11 @@ static inline void jedec_reset(u32 base, struct map_info *map, * as they will ignore the writes and dont care what address * the F0 is written to */ if(cfi->addr_unlock1) { - /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/ - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + DEBUG( MTD_DEBUG_LEVEL3, + "reset unlock called %x %x \n", + cfi->addr_unlock1,cfi->addr_unlock2); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); @@ -1662,7 +1746,6 @@ static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_ty static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) { int i,num_erase_regions; - unsigned long mask; __u8 uaddr; printk("Found: %s\n",jedec_table[index].name); @@ -1698,9 +1781,8 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) } /* Mask out address bits which are smaller than the device type */ - mask = ~(p_cfi->device_type-1); - p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask; - p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask; + p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1; + p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2; return 1; /* ok */ } @@ -1721,7 +1803,6 @@ static inline int jedec_match( __u32 base, int rc = 0; /* failure until all tests pass */ u32 mfr, id; __u8 uaddr; - unsigned long mask; /* * The IDs must match. For X16 and X32 devices operating in @@ -1759,7 +1840,7 @@ static inline int jedec_match( __u32 base, DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n", __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) ); - if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) { + if ( base + cfi_interleave(cfi) * ( 1 << finfo->DevSize ) > map->size ) { DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n", __func__, finfo->mfr_id, finfo->dev_id, @@ -1772,18 +1853,16 @@ static inline int jedec_match( __u32 base, goto match_done; } - mask = ~(cfi->device_type-1); - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n", __func__, cfi->addr_unlock1, cfi->addr_unlock2 ); if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr - && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 || - (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) { + && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 || + unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) { DEBUG( MTD_DEBUG_LEVEL3, - "MTD %s(): 0x%.4lx 0x%.4lx did not match\n", - __func__, - unlock_addrs[uaddr].addr1 & mask, - unlock_addrs[uaddr].addr2 & mask); + "MTD %s(): 0x%.4x 0x%.4x did not match\n", + __func__, + unlock_addrs[uaddr].addr1, + unlock_addrs[uaddr].addr2); goto match_done; } @@ -1819,10 +1898,10 @@ static inline int jedec_match( __u32 base, */ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ ); if(cfi->addr_unlock1) { - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have a delay before continuing */ match_done: @@ -1835,19 +1914,18 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, { int i; enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED; + u32 probe_offset1, probe_offset2; retry: if (!cfi->numchips) { - unsigned long mask = ~(cfi->device_type-1); - uaddr_idx++; if (MTD_UADDR_UNNECESSARY == uaddr_idx) return 0; /* Mask out address bits which are smaller than the device type */ - cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask; - cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask; + cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1; + cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2; } /* Make certain we aren't probing past the end of map */ @@ -1858,30 +1936,30 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, return 0; } - if ((base + cfi->addr_unlock1) >= map->size) { - printk(KERN_NOTICE - "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n", - base, cfi->addr_unlock1, map->size -1); - - return 0; + /* Ensure the unlock addresses we try stay inside the map */ + probe_offset1 = cfi_build_cmd_addr( + cfi->addr_unlock1, + cfi_interleave(cfi), + cfi->device_type); + probe_offset2 = cfi_build_cmd_addr( + cfi->addr_unlock1, + cfi_interleave(cfi), + cfi->device_type); + if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || + ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) + { + goto retry; } - if ((base + cfi->addr_unlock2) >= map->size) { - printk(KERN_NOTICE - "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n", - base, cfi->addr_unlock2, map->size -1); - return 0; - } - /* Reset */ jedec_reset(base, map, cfi); /* Autoselect Mode */ if(cfi->addr_unlock1) { - cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL); } - cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL); + cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have a delay before continuing */ if (!cfi->numchips) { @@ -1892,7 +1970,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, cfi->id = jedec_read_id(map, base, cfi); DEBUG(MTD_DEBUG_LEVEL3, "Search for id:(%02x %02x) interleave(%d) type(%d)\n", - cfi->mfr, cfi->id, cfi->interleave, cfi->device_type); + cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); for (i=0; iname, cfi->interleave, cfi->device_type*8, base, + map->name, cfi_interleave(cfi), cfi->device_type*8, base, map->bankwidth*8); return 1; @@ -1977,7 +2055,7 @@ static struct chip_probe jedec_chip_probe = { .probe_chip = jedec_probe_chip }; -struct mtd_info *jedec_probe(struct map_info *map) +static struct mtd_info *jedec_probe(struct map_info *map) { /* * Just use the generic probe stuff to call our CFI-specific @@ -1992,7 +2070,7 @@ static struct mtd_chip_driver jedec_chipdrv = { .module = THIS_MODULE }; -int __init jedec_probe_init(void) +static int __init jedec_probe_init(void) { register_mtd_chip_driver(&jedec_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index f9ff6f02c..c6c83833c 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c @@ -1,7 +1,7 @@ /* * Common code to handle absent "placeholder" devices * Copyright 2001 Resilience Corporation - * $Id: map_absent.c,v 1.4 2003/05/28 12:51:49 dwmw2 Exp $ + * $Id: map_absent.c,v 1.5 2004/11/16 18:29:00 dwmw2 Exp $ * * This map driver is used to allocate "placeholder" MTD * devices on systems that have socketed/removable media. @@ -98,7 +98,7 @@ static void map_absent_destroy(struct mtd_info *mtd) /* nop */ } -int __init map_absent_init(void) +static int __init map_absent_init(void) { register_mtd_chip_driver(&map_absent_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index 283be02dc..c5e8f520c 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple RAM * (C) 2000 Red Hat. GPL'd. - * $Id: map_ram.c,v 1.20 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: map_ram.c,v 1.21 2004/11/16 18:29:00 dwmw2 Exp $ */ #include @@ -124,7 +124,7 @@ static void mapram_nop(struct mtd_info *mtd) /* Nothing to see here */ } -int __init map_ram_init(void) +static int __init map_ram_init(void) { register_mtd_chip_driver(&mapram_chipdrv); return 0; diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index db2e2c6a1..540f90348 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple ROM * (C) 2000 Red Hat. GPL'd. - * $Id: map_rom.c,v 1.21 2004/07/12 14:06:01 dwmw2 Exp $ + * $Id: map_rom.c,v 1.22 2004/11/16 18:29:00 dwmw2 Exp $ */ #include @@ -19,7 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static void maprom_nop (struct mtd_info *); -struct mtd_info *map_rom_probe(struct map_info *map); +static struct mtd_info *map_rom_probe(struct map_info *map); static struct mtd_chip_driver maprom_chipdrv = { .probe = map_rom_probe, @@ -27,7 +27,7 @@ static struct mtd_chip_driver maprom_chipdrv = { .module = THIS_MODULE }; -struct mtd_info *map_rom_probe(struct map_info *map) +static struct mtd_info *map_rom_probe(struct map_info *map) { struct mtd_info *mtd; @@ -75,7 +75,7 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re return -EIO; } -int __init map_rom_init(void) +static int __init map_rom_init(void) { register_mtd_chip_driver(&maprom_chipdrv); return 0; diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 4e0f1a7a0..d5ef1e75b 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -1,5 +1,5 @@ /* - * $Id: cmdlinepart.c,v 1.14 2004/07/12 12:34:23 dwmw2 Exp $ + * $Id: cmdlinepart.c,v 1.16 2004/11/16 18:28:59 dwmw2 Exp $ * * Read flash partition table from command line * @@ -339,7 +339,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, * main.c::checksetup(). Note that we can not yet kmalloc() anything, * so we only save the commandline for later processing. */ -static int __init mtdpart_setup(char *s) +static int mtdpart_setup(char *s) { cmdline = s; return 1; diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index ec8cd5bcb..1613d73dc 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.12 2004/08/10 13:12:18 dwmw2 Exp $ +# $Id: Kconfig,v 1.13 2004/10/01 21:47:13 gleixner Exp $ menu "Self-contained MTD device drivers" depends on MTD!=n @@ -193,8 +193,8 @@ config MTD_DOCPROBE config MTD_DOCECC tristate - default m if MTD_DOCPROBE!=y && MTD_NAND_DISKONCHIP!=y && (MTD_DOCPROBE=m || MTD_NAND_DISKONCHIP=m) - default y if MTD_DOCPROBE=y || MTD_NAND_DISKONCHIP=y + default m if MTD_DOCPROBE=m + default y if MTD_DOCPROBE=y help This isn't a real config option; it's derived. diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index a3eb97a94..80d3393ee 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -1,5 +1,5 @@ /* - * $Id: blkmtd.c,v 1.23 2004/08/09 14:03:19 dwmw2 Exp $ + * $Id: blkmtd.c,v 1.24 2004/11/16 18:29:01 dwmw2 Exp $ * * blkmtd.c - use a block device as a fake MTD * @@ -39,7 +39,7 @@ /* Default erase size in K, always make it a multiple of PAGE_SIZE */ #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -#define VERSION "$Revision: 1.23 $" +#define VERSION "$Revision: 1.24 $" /* Info for the block device */ struct blkmtd_dev { @@ -59,10 +59,10 @@ static void blkmtd_sync(struct mtd_info *mtd); #define MAX_DEVICES 4 /* Module parameters passed by insmod/modprobe */ -char *device[MAX_DEVICES]; /* the block device to use */ -int erasesz[MAX_DEVICES]; /* optional default erase size */ -int ro[MAX_DEVICES]; /* optional read only flag */ -int sync; +static char *device[MAX_DEVICES]; /* the block device to use */ +static int erasesz[MAX_DEVICES]; /* optional default erase size */ +static int ro[MAX_DEVICES]; /* optional read only flag */ +static int sync; MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index fefbf5eaf..bab106033 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2000.c,v 1.62 2004/08/09 14:04:02 dwmw2 Exp $ + * $Id: doc2000.c,v 1.64 2004/11/16 18:29:01 dwmw2 Exp $ */ #include @@ -89,7 +89,7 @@ static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ static int _DoC_WaitReady(struct DiskOnChip *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; unsigned long timeo = jiffies + (HZ * 10); DEBUG(MTD_DEBUG_LEVEL3, @@ -114,7 +114,8 @@ static int _DoC_WaitReady(struct DiskOnChip *doc) static inline int DoC_WaitReady(struct DiskOnChip *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; + /* This is inline, to optimise the common case, where it's ready instantly */ int ret = 0; @@ -140,7 +141,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc) static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, unsigned char xtraflags) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if (DoC_is_2000(doc)) xtraflags |= CDSN_CTRL_FLASH_IO; @@ -172,10 +173,8 @@ static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, unsigned char xtraflags1, unsigned char xtraflags2) { - unsigned long docptr; int i; - - docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if (DoC_is_2000(doc)) xtraflags1 |= CDSN_CTRL_FLASH_IO; @@ -240,11 +239,9 @@ static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) { volatile int dummy; int modulus = 0xffff; - unsigned long docptr; + void __iomem *docptr = doc->virtadr; int i; - docptr = doc->virtadr; - if (len <= 0) return; @@ -271,11 +268,9 @@ static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) /* Write a buffer to DoC, taking care of Millennium odditys */ static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) { - unsigned long docptr; + void __iomem *docptr = doc->virtadr; int i; - docptr = doc->virtadr; - if (len <= 0) return; @@ -292,7 +287,7 @@ static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Software requirement 11.4.4 before writing DeviceSelect */ /* Deassert the CE line to eliminate glitches on the FCE# outputs */ @@ -316,7 +311,7 @@ static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Select the floor (bank) of chips required */ WriteDOC(floor, docptr, FloorSelect); @@ -639,15 +634,13 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) { struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; - unsigned long docptr; + void __iomem *docptr = this->virtadr; struct Nand *mychip; unsigned char syndrome[6]; volatile char dummy; int i, len256 = 0, ret=0; size_t left = len; - docptr = this->virtadr; - /* Don't allow read past end of device */ if (from >= this->totlen) return -EINVAL; @@ -799,15 +792,13 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, { struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ - unsigned long docptr; + void __iomem *docptr = this->virtadr; volatile char dummy; int len256 = 0; struct Nand *mychip; size_t left = len; int status; - docptr = this->virtadr; - /* Don't allow write past end of device */ if (to >= this->totlen) return -EINVAL; @@ -1044,13 +1035,10 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, { struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; int len256 = 0, ret; - unsigned long docptr; struct Nand *mychip; down(&this->lock); - docptr = this->virtadr; - mychip = &this->chips[ofs >> this->chipshift]; if (this->curfloor != mychip->floor) { @@ -1105,7 +1093,7 @@ static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, { struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; int len256 = 0; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; volatile int dummy; int status; @@ -1222,7 +1210,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) __u32 ofs = instr->addr; __u32 len = instr->len; volatile int dummy; - unsigned long docptr; + void __iomem *docptr = this->virtadr; struct Nand *mychip; int status; @@ -1235,8 +1223,6 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASING; - docptr = this->virtadr; - /* FIXME: Do this in the background. Use timers or schedule_task() */ while(len) { mychip = &this->chips[ofs >> this->chipshift]; @@ -1290,7 +1276,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2000(void) +static int __init init_doc2000(void) { inter_module_register(im_name, THIS_MODULE, &DoC2k_init); return 0; diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index df588ac65..8dc060629 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001.c,v 1.44 2004/08/09 14:04:24 dwmw2 Exp $ + * $Id: doc2001.c,v 1.46 2004/11/16 18:29:01 dwmw2 Exp $ */ #include @@ -52,7 +52,7 @@ static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); static struct mtd_info *docmillist = NULL; /* Perform the required delay cycles by reading from the NOP register */ -static void DoC_Delay(unsigned long docptr, unsigned short cycles) +static void DoC_Delay(void __iomem * docptr, unsigned short cycles) { volatile char dummy; int i; @@ -62,7 +62,7 @@ static void DoC_Delay(unsigned long docptr, unsigned short cycles) } /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -static int _DoC_WaitReady(unsigned long docptr) +static int _DoC_WaitReady(void __iomem * docptr) { unsigned short c = 0xffff; @@ -79,7 +79,7 @@ static int _DoC_WaitReady(unsigned long docptr) return (c == 0); } -static inline int DoC_WaitReady(unsigned long docptr) +static inline int DoC_WaitReady(void __iomem * docptr) { /* This is inline, to optimise the common case, where it's ready instantly */ int ret = 0; @@ -103,7 +103,7 @@ static inline int DoC_WaitReady(unsigned long docptr) with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static inline void DoC_Command(unsigned long docptr, unsigned char command, +static inline void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { /* Assert the CLE (Command Latch Enable) line to the flash chip */ @@ -123,7 +123,7 @@ static inline void DoC_Command(unsigned long docptr, unsigned char command, with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs, +static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs, unsigned char xtraflags1, unsigned char xtraflags2) { /* Assert the ALE (Address Latch Enable) line to the flash chip */ @@ -161,7 +161,7 @@ static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long } /* DoC_SelectChip: Select a given flash chip within the current floor */ -static int DoC_SelectChip(unsigned long docptr, int chip) +static int DoC_SelectChip(void __iomem * docptr, int chip) { /* Select the individual flash chip requested */ WriteDOC(chip, docptr, CDSNDeviceSelect); @@ -172,7 +172,7 @@ static int DoC_SelectChip(unsigned long docptr, int chip) } /* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -static int DoC_SelectFloor(unsigned long docptr, int floor) +static int DoC_SelectFloor(void __iomem * docptr, int floor) { /* Select the floor (bank) of chips required */ WriteDOC(floor, docptr, FloorSelect); @@ -417,7 +417,7 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, volatile char dummy; unsigned char syndrome[6]; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; /* Don't allow read past end of device */ @@ -543,7 +543,7 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, int i,ret = 0; volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[to >> (this->chipshift)]; /* Don't allow write past end of device */ @@ -678,7 +678,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, #endif volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; /* Find the chip which is to be used and select it */ @@ -730,7 +730,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, volatile char dummy; int ret = 0; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; /* Find the chip which is to be used and select it */ @@ -799,7 +799,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; __u32 ofs = instr->addr; __u32 len = instr->len; - unsigned long docptr = this->virtadr; + void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; if (len != mtd->erasesize) @@ -856,7 +856,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2001(void) +static int __init init_doc2001(void) { inter_module_register(im_name, THIS_MODULE, &DoCMil_init); return 0; diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index d30ba118f..93087c5e8 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -6,7 +6,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001plus.c,v 1.9 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: doc2001plus.c,v 1.11 2004/11/16 18:29:01 dwmw2 Exp $ * * Released under GPL */ @@ -57,7 +57,7 @@ static struct mtd_info *docmilpluslist = NULL; /* Perform the required delay cycles by writing to the NOP register */ -static void DoC_Delay(unsigned long docptr, int cycles) +static void DoC_Delay(void __iomem * docptr, int cycles) { int i; @@ -68,7 +68,7 @@ static void DoC_Delay(unsigned long docptr, int cycles) #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ -static int _DoC_WaitReady(unsigned long docptr) +static int _DoC_WaitReady(void __iomem * docptr) { unsigned int c = 0xffff; @@ -85,7 +85,7 @@ static int _DoC_WaitReady(unsigned long docptr) return (c == 0); } -static inline int DoC_WaitReady(unsigned long docptr) +static inline int DoC_WaitReady(void __iomem * docptr) { /* This is inline, to optimise the common case, where it's ready instantly */ int ret = 0; @@ -106,7 +106,7 @@ static inline int DoC_WaitReady(unsigned long docptr) * can detect. M-systems suggest always check this on any block level * operation and setting to normal mode if in reset mode. */ -static inline void DoC_CheckASIC(unsigned long docptr) +static inline void DoC_CheckASIC(void __iomem * docptr) { /* Make sure the DoC is in normal mode */ if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) { @@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(unsigned long docptr) /* DoC_Command: Send a flash command to the flash chip through the Flash * command register. Need 2 Write Pipeline Terminates to complete send. */ -static inline void DoC_Command(unsigned long docptr, unsigned char command, +static inline void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { WriteDOC(command, docptr, Mplus_FlashCmd); @@ -133,7 +133,7 @@ static inline void DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, unsigned char xtraflags1, unsigned char xtraflags2) { - unsigned long docptr = doc->virtadr; + void __iomem * docptr = doc->virtadr; /* Allow for possible Mill Plus internal flash interleaving */ ofs >>= doc->interleave; @@ -163,14 +163,14 @@ static inline void DoC_Address(struct DiskOnChip *doc, int numbytes, } /* DoC_SelectChip: Select a given flash chip within the current floor */ -static int DoC_SelectChip(unsigned long docptr, int chip) +static int DoC_SelectChip(void __iomem * docptr, int chip) { /* No choice for flash chip on Millennium Plus */ return 0; } /* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -static int DoC_SelectFloor(unsigned long docptr, int floor) +static int DoC_SelectFloor(void __iomem * docptr, int floor) { WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect); return 0; @@ -253,7 +253,7 @@ static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from) return cmd; } -static inline void MemReadDOC(unsigned long docptr, unsigned char *buf, int len) +static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len) { #ifndef USE_MEMCPY int i; @@ -264,7 +264,7 @@ static inline void MemReadDOC(unsigned long docptr, unsigned char *buf, int len) #endif } -static inline void MemWriteDOC(unsigned long docptr, unsigned char *buf, int len) +static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len) { #ifndef USE_MEMCPY int i; @@ -280,7 +280,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) { int mfr, id, i, j; volatile char dummy; - unsigned long docptr = doc->virtadr; + void __iomem * docptr = doc->virtadr; /* Page in the required floor/chip */ DoC_SelectFloor(docptr, floor); @@ -371,7 +371,7 @@ static void DoC_ScanChips(struct DiskOnChip *this) printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n", this->interleave?"on (16-bit)":"off (8-bit)"); conf ^= 4; - WriteDOC(this->virtadr, conf, Mplus_Configuration); + WriteDOC(conf, this->virtadr, Mplus_Configuration); } /* For each floor, find the number of valid chips it contains */ @@ -531,7 +531,7 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from) int i; loff_t fofs; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; unsigned char *bp, buf[1056]; char c[32]; @@ -616,7 +616,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, loff_t fofs; unsigned char syndrome[6]; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; /* Don't allow read past end of device */ @@ -755,7 +755,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, loff_t fto; volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[to >> (this->chipshift)]; /* Don't allow write past end of device */ @@ -881,7 +881,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, { loff_t fofs, base; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; @@ -959,7 +959,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, volatile char dummy; loff_t fofs, base; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; int ret = 0; @@ -1061,7 +1061,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr) struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; __u32 ofs = instr->addr; __u32 len = instr->len; - unsigned long docptr = this->virtadr; + void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; DoC_CheckASIC(docptr); @@ -1122,7 +1122,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ -int __init init_doc2001plus(void) +static int __init init_doc2001plus(void) { inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); return 0; diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index cb8b8a51e..12e71124f 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -4,7 +4,7 @@ /* (C) 1999 Machine Vision Holdings, Inc. */ /* (C) 1999-2003 David Woodhouse */ -/* $Id: docprobe.c,v 1.41 2003/12/03 10:19:57 dwmw2 Exp $ */ +/* $Id: docprobe.c,v 1.43 2004/11/16 18:29:01 dwmw2 Exp $ */ @@ -270,7 +270,7 @@ static void __init DoC_Probe(unsigned long physadr) memset((char *)this, 0, sizeof(struct DiskOnChip)); mtd->priv = this; - this->virtadr = docptr; + this->virtadr = (void __iomem *)docptr; this->physadr = physadr; this->ChipID = ChipID; sprintf(namebuf, "with ChipID %2.2X", ChipID); @@ -328,7 +328,7 @@ static void __init DoC_Probe(unsigned long physadr) * ****************************************************************************/ -int __init init_doc(void) +static int __init init_doc(void) { int i; diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 5fe0a0865..aafe29b9d 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -1,6 +1,6 @@ /* * mtdram - a test mtd device - * $Id: mtdram.c,v 1.33 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: mtdram.c,v 1.34 2004/11/16 18:29:01 dwmw2 Exp $ * Author: Alexander Larsson * * Copyright (c) 1999 Alexander Larsson @@ -153,7 +153,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, #if CONFIG_MTDRAM_TOTAL_SIZE > 0 #if CONFIG_MTDRAM_ABS_POS > 0 -int __init init_mtdram(void) +static int __init init_mtdram(void) { void *addr; int err; @@ -186,7 +186,7 @@ int __init init_mtdram(void) #else /* CONFIG_MTDRAM_ABS_POS > 0 */ -int __init init_mtdram(void) +static int __init init_mtdram(void) { void *addr; int err; @@ -220,7 +220,7 @@ int __init init_mtdram(void) #else /* CONFIG_MTDRAM_TOTAL_SIZE > 0 */ -int __init init_mtdram(void) +static int __init init_mtdram(void) { return 0; } diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 03a955cdf..8aab73e6f 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -1,6 +1,6 @@ /** * - * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: phram.c,v 1.3 2004/11/16 18:29:01 dwmw2 Exp $ * * Copyright (c) Jochen Schaeuble * 07/2003 rewritten by Joern Engel @@ -39,7 +39,7 @@ static LIST_HEAD(phram_list); -int phram_erase(struct mtd_info *mtd, struct erase_info *instr) +static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) { u_char *start = (u_char *)mtd->priv; @@ -60,7 +60,7 @@ int phram_erase(struct mtd_info *mtd, struct erase_info *instr) return 0; } -int phram_point(struct mtd_info *mtd, loff_t from, size_t len, +static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) { u_char *start = (u_char *)mtd->priv; @@ -73,11 +73,11 @@ int phram_point(struct mtd_info *mtd, loff_t from, size_t len, return 0; } -void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) +static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { } -int phram_read(struct mtd_info *mtd, loff_t from, size_t len, +static int phram_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { u_char *start = (u_char *)mtd->priv; @@ -91,7 +91,7 @@ int phram_read(struct mtd_info *mtd, loff_t from, size_t len, return 0; } -int phram_write(struct mtd_info *mtd, loff_t to, size_t len, +static int phram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { u_char *start = (u_char *)mtd->priv; @@ -340,7 +340,7 @@ module_param_call(slram, slram_setup, NULL, NULL, 000); MODULE_PARM_DESC(slram, "List of memory regions to map. \"map=,\""); -int __init init_phram(void) +static int __init init_phram(void) { printk(KERN_ERR "phram loaded\n"); return 0; diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index c2c2a3c36..01c78f0dc 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -1,5 +1,5 @@ /* - * $Id: pmc551.c,v 1.28 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: pmc551.c,v 1.29 2004/11/16 18:29:01 dwmw2 Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -648,7 +648,7 @@ static int asize=0; /* * PMC551 Card Initialization */ -int __init init_pmc551(void) +static int __init init_pmc551(void) { struct pci_dev *PCI_Device = NULL; struct mypriv *priv; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index fd579ae45..1caf00b84 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -1,6 +1,6 @@ /*====================================================================== - $Id: slram.c,v 1.31 2004/08/09 13:19:44 dwmw2 Exp $ + $Id: slram.c,v 1.32 2004/11/16 18:29:01 dwmw2 Exp $ This driver provides a method to access memory not used by the kernel itself (i.e. if the kernel commandline mem=xxx is used). To actually @@ -75,13 +75,13 @@ MODULE_PARM_DESC(map, "List of memory regions to map. \"map=, , priv; @@ -103,7 +103,7 @@ int slram_erase(struct mtd_info *mtd, struct erase_info *instr) return(0); } -int slram_point(struct mtd_info *mtd, loff_t from, size_t len, +static int slram_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -113,11 +113,11 @@ int slram_point(struct mtd_info *mtd, loff_t from, size_t len, return(0); } -void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) +static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { } -int slram_read(struct mtd_info *mtd, loff_t from, size_t len, +static int slram_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -128,7 +128,7 @@ int slram_read(struct mtd_info *mtd, loff_t from, size_t len, return(0); } -int slram_write(struct mtd_info *mtd, loff_t to, size_t len, +static int slram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { slram_priv_t *priv = (slram_priv_t *)mtd->priv; @@ -141,7 +141,7 @@ int slram_write(struct mtd_info *mtd, loff_t to, size_t len, /*====================================================================*/ -int register_device(char *name, unsigned long start, unsigned long length) +static int register_device(char *name, unsigned long start, unsigned long length) { slram_mtd_list_t **curmtd; @@ -213,7 +213,7 @@ int register_device(char *name, unsigned long start, unsigned long length) return(0); } -void unregister_devices(void) +static void unregister_devices(void) { slram_mtd_list_t *nextitem; @@ -228,7 +228,7 @@ void unregister_devices(void) } } -unsigned long handle_unit(unsigned long value, char *unit) +static unsigned long handle_unit(unsigned long value, char *unit) { if ((*unit == 'M') || (*unit == 'm')) { return(value * 1024 * 1024); @@ -238,7 +238,7 @@ unsigned long handle_unit(unsigned long value, char *unit) return(value); } -int parse_cmdline(char *devname, char *szstart, char *szlength) +static int parse_cmdline(char *devname, char *szstart, char *szlength) { char *buffer; unsigned long devstart; @@ -285,7 +285,7 @@ __setup("slram=", mtd_slram_setup); #endif -int init_slram(void) +static int init_slram(void) { char *devname; int i; diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index f298aee18..5f164955b 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -1,5 +1,5 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org - * $Id: ftl.c,v 1.53 2004/08/09 13:55:43 dwmw2 Exp $ + * $Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $ * * Fixes: Arnaldo Carvalho de Melo * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups @@ -1067,16 +1067,18 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) partition->mbd.blksize = SECTOR_SIZE; partition->mbd.tr = tr; partition->mbd.devnum = -1; - if (add_mtd_blktrans_dev((void *)partition)) - kfree(partition); - - } else - kfree(partition); + if (!add_mtd_blktrans_dev((void *)partition)) + return; + } + + ftl_freepart(partition); + kfree(partition); } static void ftl_remove_dev(struct mtd_blktrans_dev *dev) { del_mtd_blktrans_dev(dev); + ftl_freepart((partition_t *)dev); kfree(dev); } @@ -1094,7 +1096,7 @@ struct mtd_blktrans_ops ftl_tr = { int init_ftl(void) { - DEBUG(0, "$Id: ftl.c,v 1.53 2004/08/09 13:55:43 dwmw2 Exp $\n"); + DEBUG(0, "$Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $\n"); return register_mtd_blktrans(&ftl_tr); } diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index ea32c03e6..39eb53f65 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -7,7 +7,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * Author: David Woodhouse * - * $Id: inftlcore.c,v 1.17 2004/08/09 13:56:48 dwmw2 Exp $ + * $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 Exp $ * * 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 @@ -352,7 +352,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned return targetEUN; } -u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) +static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) { /* * This is the part that needs some cleverness applied. @@ -877,7 +877,7 @@ static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) return 0; } -struct mtd_blktrans_ops inftl_tr = { +static struct mtd_blktrans_ops inftl_tr = { .name = "inftl", .major = INFTL_MAJOR, .part_bits = INFTL_PARTN_BITS, @@ -891,9 +891,9 @@ struct mtd_blktrans_ops inftl_tr = { extern char inftlmountrev[]; -int __init init_inftl(void) +static int __init init_inftl(void) { - printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.17 $, " + printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, " "inftlmount.c %s\n", inftlmountrev); return register_mtd_blktrans(&inftl_tr); diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 64cc97ca7..52816aab7 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -8,7 +8,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: inftlmount.c,v 1.14 2004/08/09 13:57:42 dwmw2 Exp $ + * $Id: inftlmount.c,v 1.15 2004/11/05 21:55:55 kalev Exp $ * * 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 @@ -41,7 +41,7 @@ #include #include -char inftlmountrev[]="$Revision: 1.14 $"; +char inftlmountrev[]="$Revision: 1.15 $"; /* * find_boot_record: Find the INFTL Media Header and its Spare copy which @@ -222,6 +222,8 @@ static int find_boot_record(struct INFTLrecord *inftl) if (ip->Reserved0 != ip->firstUnit) { struct erase_info *instr = &inftl->instr; + instr->mtd = inftl->mbd.mtd; + /* * Most likely this is using the * undocumented qiuck mount feature. @@ -387,6 +389,8 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block) struct erase_info *instr = &inftl->instr; int physblock; + instr->mtd = inftl->mbd.mtd; + DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p," "block=%d)\n", inftl, block); diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index cdc5bbd16..7833587cd 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.30 2004/07/21 00:16:14 jwboyer Exp $ +# $Id: Kconfig,v 1.37 2004/10/20 22:57:18 dwmw2 Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -92,6 +92,25 @@ config MTD_NETSC520 demonstration board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. +config MTD_TS5500 + tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" + depends on X86 && MTD_JEDECPROBE && MTD_PARTITIONS + help + This provides a driver for the on-board flash of the Technologic + System's TS-5500 board. The flash is split into 3 partitions + which are accessed as separate MTD devices. + + mtd0 and mtd2 are the two BIOS drives. Unfortunately the BIOS + uses a proprietary flash translation layer from General Software, + which is not supported (the drives cannot be mounted). You can + create your own file system (jffs for example), but the BIOS + won't be able to boot from it. + + mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL. + + Note that jumper 3 ("Write Enable Drive A") must be set + otherwise detection won't succeeed. + config MTD_SBC_GXX tristate "CFI Flash device mapped on Arcom SBC-GXx boards" depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS @@ -160,7 +179,7 @@ config MTD_AMD76XROM config MTD_ICHXROM tristate "BIOS flash chip on Intel Controller Hub 2/3/4/5" - depends on X86 && MTD_JEDECPROBE && MTD_COMPLEX_MAPPINGS + depends on X86 && MTD_JEDECPROBE help Support for treating the BIOS flash chip on ICHX motherboards as an MTD device - with this you can reprogram your BIOS. @@ -355,13 +374,21 @@ config MTD_ARCTIC use the flash chips on it, say 'Y'. config MTD_EBONY - tristate "CFI Flash device mapped on IBM 440GP Ebony" - depends on MTD_CFI && PPC32 && 440 && EBONY + tristate "Flash devices mapped on IBM 440GP Ebony" + depends on MTD_CFI && PPC32 && 44x && EBONY help This enables access routines for the flash chips on the IBM 440GP Ebony board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. +config MTD_OCOTEA + tristate "Flash devices mapped on IBM 440GX Ocotea" + depends on MTD_CFI && PPC32 && 44x && OCOTEA + help + This enables access routines for the flash chips on the IBM 440GX + Ocotea board. If you have one of these boards and would like to + use the flash chips on it, say 'Y'. + config MTD_REDWOOD tristate "CFI Flash devices mapped on IBM Redwood" depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 ) @@ -448,6 +475,12 @@ config MTD_SA1100 the SA1100 and SA1110, including the Assabet and the Compaq iPAQ. If you have such a board, say 'Y'. +config MTD_IPAQ + tristate "CFI Flash device mapped on Compaq/HP iPAQ" + depends on ARM && IPAQ_HANDHELD && MTD_CFI + help + This provides a driver for the on-board flash of the iPAQ. + config MTD_DC21285 tristate "CFI Flash device mapped on DC21285 Footbridge" depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS @@ -468,11 +501,20 @@ config MTD_IXP4XX tristate "CFI Flash device mapped on Intel IXP4xx based systems" depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX help - This eables MTD access to flash devices on platforms based + This enables MTD access to flash devices on platforms based on Intel's IXP4xx family of network processors such as the IXDP425 and Coyote. If you have an IXP4xx based board and would like to use the flash chips on it, say 'Y'. +config MTD_IXP2000 + tristate "CFI Flash device mapped on Intel IXP2000 based systems" + depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 + help + This enables MTD access to flash devices on platforms based + on Intel's IXP2000 family of network processors such as the + IXDP425 and Coyote. If you have an IXP2000 based board and + would like to use the flash chips on it, say 'Y'. + config MTD_EPXA10DB tristate "CFI Flash device mapped on Epxa10db" depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT @@ -586,5 +628,22 @@ config MTD_DMV182 help Map driver for Dy-4 SVME/DMV-182 board. +config MTD_BAST + tristate "Map driver for Simtec BAST (EB2410ITX)" + depends on ARCH_BAST + select MTD_PARTITIONS + select MTD_MAP_BANK_WIDTH_16 + select MTD_JEDECPROBE + help + Map driver for NOR flash on the Simtec BAST (EB2410ITX). + + Note, this driver *cannot* over-ride the WP link on the + board, or currently detect the state of the link. + +config MTD_BAST_MAXSIZE + int "Maximum size for BAST flash area (MiB)" + depends on MTD_BAST + default "4" + endmenu diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 505178f36..74fa440e0 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/maps/Makefile # -# $Id: Makefile.common,v 1.14 2004/07/12 16:07:31 dwmw2 Exp $ +# $Id: Makefile.common,v 1.19 2004/09/21 14:27:16 bjd Exp $ ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) obj-$(CONFIG_MTD) += map_funcs.o @@ -10,6 +10,7 @@ endif # Chip mappings obj-$(CONFIG_MTD_CDB89712) += cdb89712.o obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o +obj-$(CONFIG_MTD_BAST) += bast-flash.o obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o obj-$(CONFIG_MTD_DC21285) += dc21285.o @@ -31,9 +32,11 @@ obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o +obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o obj-$(CONFIG_MTD_NETSC520) += netsc520.o +obj-$(CONFIG_MTD_TS5500) += ts5500_flash.o obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o obj-$(CONFIG_MTD_VMAX) += vmax301.o obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o @@ -55,6 +58,7 @@ obj-$(CONFIG_MTD_UCLINUX) += uclinux.o obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o obj-$(CONFIG_MTD_EBONY) += ebony.o +obj-$(CONFIG_MTD_OCOTEA) += ocotea.o obj-$(CONFIG_MTD_BEECH) += beech-mtd.o obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o obj-$(CONFIG_MTD_H720X) += h720x-flash.o @@ -62,5 +66,6 @@ obj-$(CONFIG_MTD_SBC8240) += sbc8240.o obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o obj-$(CONFIG_MTD_MPC1211) += mpc1211.o obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o +obj-$(CONFIG_MTD_IXP2000) += ixp2000.o obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o obj-$(CONFIG_MTD_DMV182) += dmv182.o diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 7f3ab3768..baf028c9c 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -2,7 +2,7 @@ * amd76xrom.c * * Normal mappings of chips in physical memory - * $Id: amd76xrom.c,v 1.12 2004/07/14 14:44:31 thayne Exp $ + * $Id: amd76xrom.c,v 1.18 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -12,61 +12,73 @@ #include #include #include +#include +#include #include #include #include +#include #define xstr(s) str(s) #define str(s) #s #define MOD_NAME xstr(KBUILD_BASENAME) -#define MTD_DEV_NAME_LENGTH 16 +#define ADDRESS_NAME_LEN 18 + +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ + +struct amd76xrom_window { + void __iomem *virt; + unsigned long phys; + unsigned long size; + struct list_head maps; + struct resource rsrc; + struct pci_dev *pdev; +}; struct amd76xrom_map_info { + struct list_head list; struct map_info map; struct mtd_info *mtd; - unsigned long window_addr; - u32 window_start, window_size; - struct pci_dev *pdev; - struct resource window_rsrc; - struct resource rom_rsrc; - char mtd_name[MTD_DEV_NAME_LENGTH]; + struct resource rsrc; + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; }; - -static struct amd76xrom_map_info amd76xrom_map = { - .map = { - .name = MOD_NAME, - .size = 0, - .bankwidth = 1, - } - /* remaining fields of structure are initialized to 0 */ +static struct amd76xrom_window amd76xrom_window = { + .maps = LIST_HEAD_INIT(amd76xrom_window.maps), }; - -static void amd76xrom_cleanup(struct amd76xrom_map_info *info) +static void amd76xrom_cleanup(struct amd76xrom_window *window) { + struct amd76xrom_map_info *map, *scratch; u8 byte; - /* Disable writes through the rom window */ - pci_read_config_byte(info->pdev, 0x40, &byte); - pci_write_config_byte(info->pdev, 0x40, byte & ~1); + if (window->pdev) { + /* Disable writes through the rom window */ + pci_read_config_byte(window->pdev, 0x40, &byte); + pci_write_config_byte(window->pdev, 0x40, byte & ~1); + } - if (info->mtd) { - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.virt = 0; + /* Free all of the mtd devices */ + list_for_each_entry_safe(map, scratch, &window->maps, list) { + if (map->rsrc.parent) { + release_resource(&map->rsrc); + } + del_mtd_device(map->mtd); + map_destroy(map->mtd); + list_del(&map->list); + kfree(map); } - if (info->rom_rsrc.parent) - release_resource(&info->rom_rsrc); - if (info->window_rsrc.parent) - release_resource(&info->window_rsrc); - - if (info->window_addr) { - iounmap((void *)(info->window_addr)); - info->window_addr = 0; + if (window->rsrc.parent) + release_resource(&window->rsrc); + + if (window->virt) { + iounmap(window->virt); + window->virt = NULL; + window->phys = 0; + window->size = 0; + window->pdev = NULL; } } @@ -74,168 +86,196 @@ static void amd76xrom_cleanup(struct amd76xrom_map_info *info) static int __devinit amd76xrom_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - struct rom_window { - u32 start; - u32 size; - u8 segen_bits; - }; - static struct rom_window rom_window[] = { - /* - * Need the 5MiB window for chips that have block lock/unlock - * registers located below 4MiB window. - */ - { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), }, - { 0xffc00000, 4*1024*1024, (1<<7), }, - { 0xffff0000, 64*1024, 0 }, - { 0 , 0, 0 }, - }; - static const u32 rom_probe_sizes[] = { - 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024, - 256*1024, 128*1024, 64*1024, 0}; static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; - struct amd76xrom_map_info *info = &amd76xrom_map; - struct rom_window *window; - int i; - u32 rom_size; - - info->pdev = pdev; - window = &rom_window[0]; - - while (window->size) { - /* - * Try to reserve the window mem region. If this fails then - * it is likely due to a fragment of the window being - * "reseved" by the BIOS. In the case that the - * request_mem_region() fails then once the rom size is - * discovered we will try to reserve the unreserved fragment. - */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = window->start; - info->window_rsrc.end = window->start + window->size - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - info->window_rsrc.parent = NULL; - printk(KERN_ERR MOD_NAME - " %s(): Unable to register resource" - " 0x%.08lx-0x%.08lx - kernel bug?\n", - __func__, - info->window_rsrc.start, info->window_rsrc.end); - } + struct amd76xrom_window *window = &amd76xrom_window; + struct amd76xrom_map_info *map = NULL; + unsigned long map_top; + + /* Remember the pci dev I find the window in */ + window->pdev = pdev; - /* Enable the selected rom window */ - pci_read_config_byte(pdev, 0x43, &byte); - pci_write_config_byte(pdev, 0x43, byte | window->segen_bits); + /* Assume the rom window is properly setup, and find it's size */ + pci_read_config_byte(pdev, 0x43, &byte); + if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) { + window->phys = 0xffb00000; /* 5MiB */ + } + else if ((byte & (1<<7)) == (1<<7)) { + window->phys = 0xffc00000; /* 4MiB */ + } + else { + window->phys = 0xffff0000; /* 64KiB */ + } + window->size = 0xffffffffUL - window->phys + 1UL; + + /* + * Try to reserve the window mem region. If this fails then + * it is likely due to a fragment of the window being + * "reseved" by the BIOS. In the case that the + * request_mem_region() fails then once the rom size is + * discovered we will try to reserve the unreserved fragment. + */ + window->rsrc.name = MOD_NAME; + window->rsrc.start = window->phys; + window->rsrc.end = window->phys + window->size - 1; + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, &window->rsrc)) { + window->rsrc.parent = NULL; + printk(KERN_ERR MOD_NAME + " %s(): Unable to register resource" + " 0x%.08lx-0x%.08lx - kernel bug?\n", + __func__, + window->rsrc.start, window->rsrc.end); + } - /* Enable writes through the rom window */ - pci_read_config_byte(pdev, 0x40, &byte); - pci_write_config_byte(pdev, 0x40, byte | 1); +#if 0 - /* FIXME handle registers 0x80 - 0x8C the bios region locks */ + /* Enable the selected rom window */ + pci_read_config_byte(pdev, 0x43, &byte); + pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits); +#endif - printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", - window->size, window->start); - /* For write accesses caches are useless */ - info->window_addr = - (unsigned long)ioremap_nocache(window->start, - window->size); + /* Enable writes through the rom window */ + pci_read_config_byte(pdev, 0x40, &byte); + pci_write_config_byte(pdev, 0x40, byte | 1); + + /* FIXME handle registers 0x80 - 0x8C the bios region locks */ + + /* For write accesses caches are useless */ + window->virt = ioremap_nocache(window->phys, window->size); + if (!window->virt) { + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", + window->phys, window->size); + goto out; + } - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); - continue; + /* Get the first address to look for an rom chip at */ + map_top = window->phys; +#if 1 + /* The probe sequence run over the firmware hub lock + * registers sets them to 0x7 (no access). + * Probe at most the last 4M of the address space. + */ + if (map_top < 0xffc00000) { + map_top = 0xffc00000; + } +#endif + /* Loop through and look for rom chips */ + while((map_top - 1) < 0xffffffffUL) { + struct cfi_private *cfi; + unsigned long offset; + int i; + + if (!map) { + map = kmalloc(sizeof(*map), GFP_KERNEL); + } + if (!map) { + printk(KERN_ERR MOD_NAME ": kmalloc failed"); + goto out; } + memset(map, 0, sizeof(*map)); + INIT_LIST_HEAD(&map->list); + map->map.name = map->map_name; + map->map.phys = map_top; + offset = map_top - window->phys; + map->map.virt = (void __iomem *) + (((unsigned long)(window->virt)) + offset); + map->map.size = 0xffffffffUL - map_top + 1UL; + /* Set the name of the map to the address I am trying */ + sprintf(map->map_name, "%s @%08lx", + MOD_NAME, map->map.phys); + + /* There is no generic VPP support */ + for(map->map.bankwidth = 32; map->map.bankwidth; + map->map.bankwidth >>= 1) + { + char **probe_type; + /* Skip bankwidths that are not supported */ + if (!map_bankwidth_supported(map->map.bankwidth)) + continue; - info->mtd = NULL; + /* Setup the map methods */ + simple_map_init(&map->map); - for(i = 0; (rom_size = rom_probe_sizes[i]); i++) { - char **chip_type; - if (rom_size > window->size) { - continue; - } - info->map.phys = window->start + window->size - rom_size; - info->map.virt = - info->window_addr + window->size - rom_size; - info->map.size = rom_size; - simple_map_init(&info->map); - chip_type = rom_probe_types; - for(; !info->mtd && *chip_type; chip_type++) { - info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map); + /* Try all of the probe methods */ + probe_type = rom_probe_types; + for(; *probe_type; probe_type++) { + map->mtd = do_map_probe(*probe_type, &map->map); + if (map->mtd) + goto found; } - if (info->mtd) goto found_mtd; } - iounmap((void *)(info->window_addr)); - info->window_addr = 0; - - /* Disable writes through the rom window */ - pci_read_config_byte(pdev, 0x40, &byte); - pci_write_config_byte(pdev, 0x40, byte & ~1); - - window++; - } - goto failed; - - found_mtd: - printk(KERN_NOTICE MOD_NAME " chip at offset: 0x%x\n", - window->size - rom_size); - - info->mtd->owner = THIS_MODULE; - - if (!info->window_rsrc.parent) { - /* failed to reserve entire window - try fragments */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = window->start; - info->window_rsrc.end = window->start + window->size - rom_size - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve window resource fragment\n"); -#if 0 + map_top += ROM_PROBE_STEP_SIZE; + continue; + found: + /* Trim the size if we are larger than the map */ + if (map->mtd->size > map->map.size) { + printk(KERN_WARNING MOD_NAME + " rom(%u) larger than window(%lu). fixing...\n", + map->mtd->size, map->map.size); + map->mtd->size = map->map.size; + } + if (window->rsrc.parent) { /* - * The BIOS e820 usually reserves this so it isn't - * usually an error. + * Registering the MTD device in iomem may not be possible + * if there is a BIOS "reserved" and BUSY range. If this + * fails then continue anyway. */ - goto failed; -#endif + map->rsrc.name = map->map_name; + map->rsrc.start = map->map.phys; + map->rsrc.end = map->map.phys + map->mtd->size - 1; + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&window->rsrc, &map->rsrc)) { + printk(KERN_ERR MOD_NAME + ": cannot reserve MTD resource\n"); + map->rsrc.parent = NULL; + } } - } - add_mtd_device(info->mtd); - info->window_start = window->start; - info->window_size = window->size; - - if (info->window_rsrc.parent) { - /* - * Registering the MTD device in iomem may not be possible - * if there is a BIOS "reserved" and BUSY range. If this - * fails then continue anyway. - */ - snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, - "mtd%d", info->mtd->index); - - info->rom_rsrc.name = info->mtd_name; - info->rom_rsrc.start = window->start + window->size - rom_size; - info->rom_rsrc.end = window->start + window->size - 1; - info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve MTD resource\n"); - info->rom_rsrc.parent = NULL; + /* Make the whole region visible in the map */ + map->map.virt = window->virt; + map->map.phys = window->phys; + cfi = map->map.fldrv_priv; + for(i = 0; i < cfi->numchips; i++) { + cfi->chips[i].start += offset; } + + /* Now that the mtd devices is complete claim and export it */ + map->mtd->owner = THIS_MODULE; + if (add_mtd_device(map->mtd)) { + map_destroy(map->mtd); + map->mtd = NULL; + goto out; + } + + + /* Calculate the new value of map_top */ + map_top += map->mtd->size; + + /* File away the map structure */ + list_add(&map->list, &window->maps); + map = NULL; } + out: + /* Free any left over map structures */ + if (map) { + kfree(map); + } + /* See if I have any map structures */ + if (list_empty(&window->maps)) { + amd76xrom_cleanup(window); + return -ENODEV; + } return 0; - - failed: - amd76xrom_cleanup(info); - return -ENODEV; } static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) { - struct amd76xrom_map_info *info = &amd76xrom_map; + struct amd76xrom_window *window = &amd76xrom_window; - amd76xrom_cleanup(info); + amd76xrom_cleanup(window); } static struct pci_device_id amd76xrom_pci_tbl[] = { @@ -258,7 +298,7 @@ static struct pci_driver amd76xrom_driver = { }; #endif -int __init init_amd76xrom(void) +static int __init init_amd76xrom(void) { struct pci_dev *pdev; struct pci_device_id *id; @@ -270,7 +310,6 @@ int __init init_amd76xrom(void) } } if (pdev) { - amd76xrom_map.pdev = pdev; return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]); } return -ENXIO; @@ -281,7 +320,7 @@ int __init init_amd76xrom(void) static void __exit cleanup_amd76xrom(void) { - amd76xrom_remove_one(amd76xrom_map.pdev); + amd76xrom_remove_one(amd76xrom_window.pdev); } module_init(init_amd76xrom); diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c index 2acf5b0b8..777276fd0 100644 --- a/drivers/mtd/maps/arctic-mtd.c +++ b/drivers/mtd/maps/arctic-mtd.c @@ -1,5 +1,5 @@ /* - * $Id: arctic-mtd.c,v 1.11 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: arctic-mtd.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for * IBM 405LP Arctic boards. @@ -98,7 +98,7 @@ init_arctic_mtd(void) { printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); - arctic_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); + arctic_mtd_map.virt = ioremap(PADDR, SIZE); if (!arctic_mtd_map.virt) { printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index 31e9df662..cf362ccc3 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -2,7 +2,7 @@ * NV-RAM memory access on autcpu12 * (C) 2002 Thomas Gleixner (gleixner@autronix.de) * - * $Id: autcpu12-nvram.c,v 1.6 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: autcpu12-nvram.c,v 1.8 2004/11/04 13:24:14 gleixner Exp $ * * 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 @@ -47,7 +47,7 @@ static int __init init_autcpu12_sram (void) { int err, save0, save1; - autcpu12_sram_map.virt = (unsigned long)ioremap(0x12000000, SZ_128K); + autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { printk("Failed to ioremap autcpu12 NV-RAM space\n"); err = -EIO; @@ -76,7 +76,7 @@ static int __init init_autcpu12_sram (void) /* We have a 128K found, restore 0x10000 and set size * to 128K */ - ma[_write32(&autcpu12_sram_map,save1,0x10000); + map_write32(&autcpu12_sram_map,save1,0x10000); autcpu12_sram_map.size = SZ_128K; map: diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c index d8f737aa7..5e79c9d5d 100644 --- a/drivers/mtd/maps/beech-mtd.c +++ b/drivers/mtd/maps/beech-mtd.c @@ -1,5 +1,5 @@ /* - * $Id: beech-mtd.c,v 1.8 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: beech-mtd.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $ * * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for * IBM 405LP Beech boards. @@ -74,7 +74,7 @@ init_beech_mtd(void) { printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); - beech_mtd_map.virt = (unsigned long) ioremap(PADDR, SIZE); + beech_mtd_map.virt = ioremap(PADDR, SIZE); if (!beech_mtd_map.virt) { printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index e8c984ee1..ab15dac2f 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c @@ -1,7 +1,7 @@ /* * Flash on Cirrus CDB89712 * - * $Id: cdb89712.c,v 1.8 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cdb89712.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $ */ #include @@ -44,7 +44,7 @@ static int __init init_cdb89712_flash (void) goto out; } - cdb89712_flash_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); + cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE); if (!cdb89712_flash_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); err = -EIO; @@ -114,7 +114,7 @@ static int __init init_cdb89712_sram (void) goto out; } - cdb89712_sram_map.virt = (unsigned long)ioremap(SRAM_START, SRAM_SIZE); + cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE); if (!cdb89712_sram_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); err = -EIO; @@ -182,7 +182,7 @@ static int __init init_cdb89712_bootrom (void) goto out; } - cdb89712_bootrom_map.virt = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE); + cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE); if (!cdb89712_bootrom_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); err = -EIO; diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index 8475505f0..da8584a66 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -11,7 +11,7 @@ * * (C) 2000 Nicolas Pitre * - * $Id: ceiva.c,v 1.10 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $ */ #include @@ -150,7 +150,7 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info break; } - clps[i].map->virt = (unsigned long)clps[i].vbase; + clps[i].map->virt = (void __iomem *)clps[i].vbase; clps[i].map->bankwidth = clps[i].width; clps[i].map->size = clps[i].size; diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index 28d59ff77..f72e4f894 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -1,7 +1,7 @@ /* * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson * - * $Id: cfi_flagadm.c,v 1.12 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cfi_flagadm.c,v 1.14 2004/11/04 13:24:14 gleixner Exp $ * * 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 @@ -96,7 +96,7 @@ int __init init_flagadm(void) FLASH_SIZE, FLASH_PHYS_ADDR); flagadm_map.phys = FLASH_PHYS_ADDR; - flagadm_map.virt = (unsigned long)ioremap(FLASH_PHYS_ADDR, + flagadm_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); if (!flagadm_map.virt) { diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c index 773b1ba9a..5258c641b 100644 --- a/drivers/mtd/maps/cstm_mips_ixx.c +++ b/drivers/mtd/maps/cstm_mips_ixx.c @@ -1,5 +1,5 @@ /* - * $Id: cstm_mips_ixx.c,v 1.10 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: cstm_mips_ixx.c,v 1.12 2004/11/04 13:24:14 gleixner Exp $ * * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. * Config with both CFI and JEDEC device support. @@ -170,7 +170,7 @@ int __init init_cstm_mips_ixx(void) cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; - cstm_mips_ixx_map[i].virt = (unsigned long)ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); + cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); if (!cstm_mips_ixx_map[i].virt) { printk(KERN_WARNING "Failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/db1550-flash.c b/drivers/mtd/maps/db1550-flash.c index b2504047c..d21388846 100644 --- a/drivers/mtd/maps/db1550-flash.c +++ b/drivers/mtd/maps/db1550-flash.c @@ -1,10 +1,10 @@ /* * Flash memory access on Alchemy Db1550 board * - * $Id: db1550-flash.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: db1550-flash.c,v 1.7 2004/11/04 13:24:14 gleixner Exp $ * * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c: - * (C) 2003 Pete Popov + * (C) 2003, 2004 Pete Popov * */ @@ -19,7 +19,6 @@ #include #include -#include #ifdef DEBUG_RW #define DBG(x...) printk(x) @@ -132,7 +131,7 @@ int setup_flash_params(void) window_addr = 0x1C000000; window_size = 0x4000000; #else /* USER ONLY */ - window_addr = 0x1E000000; + window_addr = 0x18000000; window_size = 0x4000000; #endif return 0; @@ -160,10 +159,9 @@ int __init db1550_mtd_init(void) * Now let's probe for the actual flash. Do it here since * specific machine settings might have been set above. */ - printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n", + printk(KERN_NOTICE "Db1550 flash: probing %d-bit flash bus\n", db1550_map.bankwidth*8); - db1550_map.virt = - (unsigned long)ioremap(window_addr, window_size); + db1550_map.virt = ioremap(window_addr, window_size); mymtd = do_map_probe("cfi_probe", &db1550_map); if (!mymtd) return -ENXIO; mymtd->owner = THIS_MODULE; @@ -177,6 +175,7 @@ static void __exit db1550_mtd_cleanup(void) if (mymtd) { del_mtd_partitions(mymtd); map_destroy(mymtd); + iounmap((void *) db1550_map.virt); } } diff --git a/drivers/mtd/maps/db1x00-flash.c b/drivers/mtd/maps/db1x00-flash.c index 388e14b6b..faa68ec56 100644 --- a/drivers/mtd/maps/db1x00-flash.c +++ b/drivers/mtd/maps/db1x00-flash.c @@ -1,9 +1,9 @@ /* * Flash memory access on Alchemy Db1xxx boards * - * $Id: db1x00-flash.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: db1x00-flash.c,v 1.6 2004/11/04 13:24:14 gleixner Exp $ * - * (C) 2003 Pete Popov + * (C) 2003 Pete Popov * */ @@ -18,8 +18,6 @@ #include #include -#include -#include #ifdef DEBUG_RW #define DBG(x...) printk(x) @@ -27,11 +25,20 @@ #define DBG(x...) #endif +/* MTD CONFIG OPTIONS */ +#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER) +#define DB1X00_BOTH_BANKS +#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER) +#define DB1X00_BOOT_ONLY +#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER) +#define DB1X00_USER_ONLY +#endif + static unsigned long window_addr; static unsigned long window_size; static unsigned long flash_size; -static BCSR * const bcsr = (BCSR *)0xAE000000; +static unsigned short *bcsr = (unsigned short *)0xAE000000; static unsigned char flash_bankwidth = 4; /* @@ -113,7 +120,7 @@ static struct mtd_info *db1xxx_mtd; */ int setup_flash_params(void) { - switch ((bcsr->status >> 14) & 0x3) { + switch ((bcsr[2] >> 14) & 0x3) { case 0: /* 64Mbit devices */ flash_size = 0x800000; /* 8MB per part */ #if defined(DB1X00_BOTH_BANKS) @@ -192,7 +199,7 @@ int __init db1x00_mtd_init(void) */ printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n", db1xxx_mtd_map.bankwidth*8); - db1xxx_mtd_map.virt = (unsigned long)ioremap(window_addr, window_size); + db1xxx_mtd_map.virt = ioremap(window_addr, window_size); db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map); if (!db1xxx_mtd) return -ENXIO; db1xxx_mtd->owner = THIS_MODULE; diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c index 7c4de43c0..d850a27a4 100644 --- a/drivers/mtd/maps/dbox2-flash.c +++ b/drivers/mtd/maps/dbox2-flash.c @@ -1,5 +1,5 @@ /* - * $Id: dbox2-flash.c,v 1.11 2004/07/12 21:59:43 dwmw2 Exp $ + * $Id: dbox2-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * D-Box 2 flash driver */ @@ -75,7 +75,7 @@ struct map_info dbox2_flash_map = { int __init init_dbox2_flash(void) { printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR); - dbox2_flash_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!dbox2_flash_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index fc72bb5c5..938c41f2f 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: dc21285.c,v 1.20 2004/07/12 22:38:29 dwmw2 Exp $ + * $Id: dc21285.c,v 1.22 2004/11/01 13:39:21 rmk Exp $ */ #include #include @@ -32,7 +32,8 @@ static struct mtd_info *dc21285_mtd; * is unpredictible. So we have a 25us penalty per * write access. */ -static void nw_en_write(void) { +static void nw_en_write(void) +{ extern spinlock_t gpio_lock; unsigned long flags; @@ -55,53 +56,60 @@ static void nw_en_write(void) { static map_word dc21285_read8(struct map_info *map, unsigned long ofs) { - return *(uint8_t*)(map->map_priv_1 + ofs); + map_word val; + val.x[0] = *(uint8_t*)(map->virt + ofs); + return val; } static map_word dc21285_read16(struct map_info *map, unsigned long ofs) { - return *(uint16_t*)(map->map_priv_1 + ofs); + map_word val; + val.x[0] = *(uint16_t*)(map->virt + ofs); + return val; } static map_word dc21285_read32(struct map_info *map, unsigned long ofs) { - return *(uint32_t*)(map->map_priv_1 + ofs); + map_word val; + val.x[0] = *(uint32_t*)(map->virt + ofs); + return val; } static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - memcpy(to, (void*)(map->map_priv_1 + from), len); + memcpy(to, (void*)(map->virt + from), len); } -static void dc21285_write(struct map_info *map, map_word d, unsigned long adr) +static void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr) { if (machine_is_netwinder()) nw_en_write(); *CSR_ROMWRITEREG = adr & 3; adr &= ~3; - *(uint8_t*)(map->map_priv_1 + adr) = d.x[0]; + *(uint8_t*)(map->virt + adr) = d.x[0]; } -static void dc21285_write16(struct map_info *map, map_word d, unsigned long adr) +static void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr) { if (machine_is_netwinder()) nw_en_write(); *CSR_ROMWRITEREG = adr & 3; adr &= ~3; - *(uint16_t*)(map->map_priv_1 + adr) = d.x[0]; + *(uint16_t*)(map->virt + adr) = d.x[0]; } -static void dc21285_write32(struct map_info *map, map_word d, unsigned long adr) +static void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr) { if (machine_is_netwinder()) nw_en_write(); - *(uint32_t*)(map->map_priv_1 + adr) = d.x[0]; + *(uint32_t*)(map->virt + adr) = d.x[0]; } static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len) { while (len > 0) { - uint32_t d = *((uint32_t*)from)++; + map_word d; + d.x[0] = *((uint32_t*)from)++; dc21285_write32(map, d, to); to += 4; len -= 4; @@ -111,7 +119,8 @@ static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const voi static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len) { while (len > 0) { - uint16_t d = *((uint16_t*)from)++; + map_word d; + d.x[0] = *((uint16_t*)from)++; dc21285_write16(map, d, to); to += 2; len -= 2; @@ -120,7 +129,8 @@ static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const voi static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len) { - uint8_t d = *((uint8_t*)from)++; + map_word d; + d.x[0] = *((uint8_t*)from)++; dc21285_write8(map, d, to); to++; len--; @@ -135,8 +145,8 @@ static struct map_info dc21285_map = { /* Partition stuff */ -static struct mtd_partition *dc21285_parts; #ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition *dc21285_parts; static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; #endif @@ -163,10 +173,10 @@ static int __init init_dc21285(void) break; case SA110_CNTL_ROMWIDTH_32: dc21285_map.bankwidth = 4; - break; dc21285_map.read = dc21285_read32; dc21285_map.write = dc21285_write32; dc21285_map.copy_to = dc21285_copy_to_32; + break; default: printk (KERN_ERR "DC21285 flash: undefined bankwidth\n"); return -ENXIO; @@ -175,8 +185,8 @@ static int __init init_dc21285(void) dc21285_map.bankwidth*8); /* Let's map the flash area */ - dc21285_map.map_priv_1 = (unsigned long)ioremap(DC21285_FLASH, 16*1024*1024); - if (!dc21285_map.map_priv_1) { + dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024); + if (!dc21285_map.virt) { printk("Failed to ioremap\n"); return -EIO; } @@ -188,14 +198,14 @@ static int __init init_dc21285(void) } if (!dc21285_mtd) { - iounmap((void *)dc21285_map.map_priv_1); + iounmap(dc21285_map.virt); return -ENXIO; } dc21285_mtd->owner = THIS_MODULE; #ifdef CONFIG_MTD_PARTITIONS - nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, (void *)0); + nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0); if (nrparts > 0) add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts); else @@ -231,7 +241,7 @@ static void __exit cleanup_dc21285(void) del_mtd_device(dc21285_mtd); map_destroy(dc21285_mtd); - iounmap((void *)dc21285_map.map_priv_1); + iounmap(dc21285_map.virt); } module_init(init_dc21285); diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index feb38ba14..69d0e7ceb 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -14,7 +14,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dilnetpc.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: dilnetpc.c,v 1.16 2004/11/04 13:24:14 gleixner Exp $ * * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems * featuring the AMD Elan SC410 processor. There are two variants of this @@ -403,7 +403,7 @@ static int __init init_dnpc(void) printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); - dnpc_map.virt = (unsigned long)ioremap_nocache(dnpc_map.phys, dnpc_map.size); + dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size); dnpc_map_flash(dnpc_map.phys, dnpc_map.size); @@ -413,7 +413,7 @@ static int __init init_dnpc(void) } simple_map_init(&dnpc_map); - printk("FLASH virtual address: 0x%lx\n", dnpc_map.virt); + printk("FLASH virtual address: 0x%p\n", dnpc_map.virt); mymtd = do_map_probe("jedec_probe", &dnpc_map); @@ -430,7 +430,7 @@ static int __init init_dnpc(void) mymtd->erasesize = 0x10000; if (!mymtd) { - iounmap((void *)dnpc_map.virt); + iounmap(dnpc_map.virt); return -ENXIO; } @@ -481,9 +481,9 @@ static void __exit cleanup_dnpc(void) map_destroy(mymtd); } if (dnpc_map.virt) { - iounmap((void *)dnpc_map.virt); + iounmap(dnpc_map.virt); dnpc_unmap_flash(); - dnpc_map.virt = 0; + dnpc_map.virt = NULL; } } diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c index cdb9c1bc9..b9bc63503 100644 --- a/drivers/mtd/maps/dmv182.c +++ b/drivers/mtd/maps/dmv182.c @@ -4,7 +4,7 @@ * * Flash map driver for the Dy4 SVME182 board * - * $Id: dmv182.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: dmv182.c,v 1.5 2004/11/04 13:24:14 gleixner Exp $ * * Copyright 2003-2004, TimeSys Corporation * @@ -103,8 +103,7 @@ static int __init init_svme182(void) partitions = svme182_partitions; - svme182_map.virt = - (unsigned long)ioremap(FLASH_BASE_ADDR, svme182_map.size); + svme182_map.virt = ioremap(FLASH_BASE_ADDR, svme182_map.size); if (svme182_map.virt == 0) { printk("Failed to ioremap FLASH memory area.\n"); diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c index 7add7b8f2..b654c316c 100644 --- a/drivers/mtd/maps/ebony.c +++ b/drivers/mtd/maps/ebony.c @@ -1,11 +1,11 @@ /* - * $Id: ebony.c,v 1.10 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: ebony.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * Mapping for Ebony user flash * - * Matt Porter + * Matt Porter * - * Copyright 2002 MontaVista Software Inc. + * Copyright 2002-2004 MontaVista Software 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 @@ -21,9 +21,10 @@ #include #include #include +#include #include #include -#include +#include static struct mtd_info *flash; @@ -63,7 +64,7 @@ static struct mtd_partition ebony_large_partitions[] = { int __init init_ebony(void) { u8 fpga0_reg; - unsigned long fpga0_adr; + u8 __iomem *fpga0_adr; unsigned long long small_flash_base, large_flash_base; fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16); @@ -92,8 +93,7 @@ int __init init_ebony(void) large_flash_base = EBONY_LARGE_FLASH_HIGH; ebony_small_map.phys = small_flash_base; - ebony_small_map.virt = - (unsigned long)ioremap64(small_flash_base, + ebony_small_map.virt = ioremap64(small_flash_base, ebony_small_map.size); if (!ebony_small_map.virt) { @@ -114,8 +114,7 @@ int __init init_ebony(void) } ebony_large_map.phys = large_flash_base; - ebony_large_map.virt = - (unsigned long)ioremap64(large_flash_base, + ebony_large_map.virt = ioremap64(large_flash_base, ebony_large_map.size); if (!ebony_large_map.virt) { @@ -146,13 +145,13 @@ static void __exit cleanup_ebony(void) } if (ebony_small_map.virt) { - iounmap((void *)ebony_small_map.virt); - ebony_small_map.virt = 0; + iounmap(ebony_small_map.virt); + ebony_small_map.virt = NULL; } if (ebony_large_map.virt) { - iounmap((void *)ebony_large_map.virt); - ebony_large_map.virt = 0; + iounmap(ebony_large_map.virt); + ebony_large_map.virt = NULL; } } @@ -160,5 +159,5 @@ module_init(init_ebony); module_exit(cleanup_ebony); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Matt Porter "); +MODULE_AUTHOR("Matt Porter "); MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards"); diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c index 842f1b046..8b0da394f 100644 --- a/drivers/mtd/maps/edb7312.c +++ b/drivers/mtd/maps/edb7312.c @@ -1,5 +1,5 @@ /* - * $Id: edb7312.c,v 1.11 2004/07/14 09:52:55 dwmw2 Exp $ + * $Id: edb7312.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * Handle mapping of the NOR flash on Cogent EDB7312 boards * @@ -82,8 +82,7 @@ int __init init_edb7312nor(void) printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", WINDOW_SIZE, WINDOW_ADDR); - edb7312nor_map.virt = (unsigned long) - ioremap(WINDOW_ADDR, WINDOW_SIZE); + edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!edb7312nor_map.virt) { printk(MSG_PREFIX "failed to ioremap\n"); diff --git a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c index 9410e1fb2..f36bddc65 100644 --- a/drivers/mtd/maps/elan-104nc.c +++ b/drivers/mtd/maps/elan-104nc.c @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: elan-104nc.c,v 1.21 2004/07/12 22:38:29 dwmw2 Exp $ + $Id: elan-104nc.c,v 1.24 2004/11/16 18:29:02 dwmw2 Exp $ The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. @@ -53,7 +53,7 @@ always fail. So we don't do it. I just hope it doesn't break anything. #define PAGE_IO_SIZE 2 static volatile int page_in_window = -1; // Current page in window. -static unsigned long iomapadr; +static void __iomem *iomapadr; static spinlock_t elan_104nc_spin = SPIN_LOCK_UNLOCKED; /* partition_info gives details on the logical partitions that the split the @@ -182,15 +182,15 @@ static void cleanup_elan_104nc(void) map_destroy( all_mtd ); } - iounmap((void *)iomapadr); + iounmap(iomapadr); } -int __init init_elan_104nc(void) +static int __init init_elan_104nc(void) { /* Urg! We use I/O port 0x22 without request_region()ing it, because it's already allocated to the PIC. */ - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { printk( KERN_ERR"%s: failed to ioremap memory region\n", elan_104nc_map.name ); diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c index 545a398c4..ab6dbe2b8 100644 --- a/drivers/mtd/maps/epxa10db-flash.c +++ b/drivers/mtd/maps/epxa10db-flash.c @@ -5,7 +5,7 @@ * Copyright (C) 2001 Altera Corporation * Copyright (C) 2001 Red Hat, Inc. * - * $Id: epxa10db-flash.c,v 1.11 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: epxa10db-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * 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 @@ -62,7 +62,7 @@ static int __init epxa_mtd_init(void) printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); - epxa_map.virt = (unsigned long)ioremap(FLASH_START, FLASH_SIZE); + epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE); if (!epxa_map.virt) { printk("Failed to ioremap %s flash\n",BOARD_NAME); return -EIO; diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c index 50409efda..068bb6a54 100644 --- a/drivers/mtd/maps/fortunet.c +++ b/drivers/mtd/maps/fortunet.c @@ -1,6 +1,6 @@ /* fortunet.c memory map * - * $Id: fortunet.c,v 1.7 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: fortunet.c,v 1.9 2004/11/04 13:24:14 gleixner Exp $ */ #include @@ -209,8 +209,8 @@ int __init init_fortunet(void) map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, - map_regions[ix].map_info.virt = - (int)ioremap_nocache( + map_regions[ix].map_info.virt = + ioremap_nocache( map_regions[ix].window_addr_physical, map_regions[ix].map_info.size); if(!map_regions[ix].map_info.virt) diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index e7cd7b022..c73828171 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c @@ -2,7 +2,7 @@ * Flash memory access on Hynix GMS30C7201/HMS30C7202 based * evaluation boards * - * $Id: h720x-flash.c,v 1.9 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: h720x-flash.c,v 1.11 2004/11/04 13:24:14 gleixner Exp $ * * (C) 2002 Jungjun Kim * 2003 Thomas Gleixner @@ -73,7 +73,7 @@ int __init h720x_mtd_init(void) char *part_type = NULL; - h720x_map.virt = (unsigned long)ioremap(FLASH_PHYS, FLASH_SIZE); + h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE); if (!h720x_map.virt) { printk(KERN_ERR "H720x-MTD: ioremap failed\n"); diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index a26cc3af5..9a8890d7f 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -2,7 +2,7 @@ * ichxrom.c * * Normal mappings of chips in physical memory - * $Id: ichxrom.c,v 1.8 2004/07/16 17:43:11 dwmw2 Exp $ + * $Id: ichxrom.c,v 1.15 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -12,187 +12,87 @@ #include #include #include +#include +#include #include #include #include -#include +#include #define xstr(s) str(s) #define str(s) #s #define MOD_NAME xstr(KBUILD_BASENAME) -#define MTD_DEV_NAME_LENGTH 16 - -#define RESERVE_MEM_REGION 0 - +#define ADDRESS_NAME_LEN 18 -#define MANUFACTURER_INTEL 0x0089 -#define I82802AB 0x00ad -#define I82802AC 0x00ac +#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ -#define ICHX_FWH_REGION_START 0xFF000000UL -#define ICHX_FWH_REGION_SIZE 0x01000000UL #define BIOS_CNTL 0x4e #define FWH_DEC_EN1 0xE3 #define FWH_DEC_EN2 0xF0 #define FWH_SEL1 0xE8 #define FWH_SEL2 0xEE -struct ichxrom_map_info { - struct map_info map; - struct mtd_info *mtd; - unsigned long window_addr; +struct ichxrom_window { + void __iomem* virt; + unsigned long phys; + unsigned long size; + struct list_head maps; + struct resource rsrc; struct pci_dev *pdev; - struct resource window_rsrc; - struct resource rom_rsrc; - char mtd_name[MTD_DEV_NAME_LENGTH]; }; -static inline unsigned long addr(struct map_info *map, unsigned long ofs) -{ - unsigned long offset; - offset = ((8*1024*1024) - map->size) + ofs; - if (offset >= (4*1024*1024)) { - offset += 0x400000; - } - return map->map_priv_1 + 0x400000 + offset; -} - -static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr) -{ - return addr - map->map_priv_1 + ICHX_FWH_REGION_START; -} - -static map_word ichxrom_read(struct map_info *map, unsigned long ofs) -{ - map_word val; - int i; - switch(map->bankwidth) { - case 1: val.x[0] = __raw_readb(addr(map, ofs)); break; - case 2: val.x[0] = __raw_readw(addr(map, ofs)); break; - case 4: val.x[0] = __raw_readl(addr(map, ofs)); break; -#if BITS_PER_LONG >= 64 - case 8: val.x[0] = __raw_readq(addr(map, ofs)); break; -#endif - default: val.x[0] = 0; break; - } - for(i = 1; i < map_words(map); i++) { - val.x[i] = 0; - } - return val; -} - -static void ichxrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - memcpy_fromio(to, addr(map, from), len); -} - -static void ichxrom_write(struct map_info *map, map_word d, unsigned long ofs) -{ - switch(map->bankwidth) { - case 1: __raw_writeb(d.x[0], addr(map,ofs)); break; - case 2: __raw_writew(d.x[0], addr(map,ofs)); break; - case 4: __raw_writel(d.x[0], addr(map,ofs)); break; -#if BITS_PER_LONG >= 64 - case 8: __raw_writeq(d.x[0], addr(map,ofs)); break; -#endif - } - mb(); -} - -static void ichxrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ - memcpy_toio(addr(map, to), from, len); -} - -static struct ichxrom_map_info ichxrom_map = { - .map = { - .name = MOD_NAME, - .phys = NO_XIP, - .size = 0, - .bankwidth = 1, - .read = ichxrom_read, - .copy_from = ichxrom_copy_from, - .write = ichxrom_write, - .copy_to = ichxrom_copy_to, - /* Firmware hubs only use vpp when being programmed - * in a factory setting. So in-place programming - * needs to use a different method. - */ - }, - /* remaining fields of structure are initialized to 0 */ +struct ichxrom_map_info { + struct list_head list; + struct map_info map; + struct mtd_info *mtd; + struct resource rsrc; + char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; }; -enum fwh_lock_state { - FWH_DENY_WRITE = 1, - FWH_IMMUTABLE = 2, - FWH_DENY_READ = 4, +static struct ichxrom_window ichxrom_window = { + .maps = LIST_HEAD_INIT(ichxrom_window.maps), }; -static void ichxrom_cleanup(struct ichxrom_map_info *info) +static void ichxrom_cleanup(struct ichxrom_window *window) { + struct ichxrom_map_info *map, *scratch; u16 word; /* Disable writes through the rom window */ - pci_read_config_word(info->pdev, BIOS_CNTL, &word); - pci_write_config_word(info->pdev, BIOS_CNTL, word & ~1); - - if (info->mtd) { - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.virt = 0; + pci_read_config_word(window->pdev, BIOS_CNTL, &word); + pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1); + + /* Free all of the mtd devices */ + list_for_each_entry_safe(map, scratch, &window->maps, list) { + if (map->rsrc.parent) + release_resource(&map->rsrc); + del_mtd_device(map->mtd); + map_destroy(map->mtd); + list_del(&map->list); + kfree(map); } - if (info->rom_rsrc.parent) - release_resource(&info->rom_rsrc); - if (info->window_rsrc.parent) - release_resource(&info->window_rsrc); - - if (info->window_addr) { - iounmap((void *)(info->window_addr)); - info->window_addr = 0; - } -} - - -static int ichxrom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len, - enum fwh_lock_state state) -{ - struct map_info *map = mtd->priv; - unsigned long start = ofs; - unsigned long end = start + len -1; - - /* FIXME do I need to guard against concurrency here? */ - /* round down to 64K boundaries */ - start = start & ~0xFFFF; - end = end & ~0xFFFF; - while (start <= end) { - unsigned long ctrl_addr; - ctrl_addr = addr(map, start) - 0x400000 + 2; - writeb(state, ctrl_addr); - start = start + 0x10000; + if (window->rsrc.parent) + release_resource(&window->rsrc); + if (window->virt) { + iounmap(window->virt); + window->virt = NULL; + window->phys = 0; + window->size = 0; + window->pdev = NULL; } - return 0; } -static int ichxrom_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return ichxrom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE); -} - -static int ichxrom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return ichxrom_set_lock_state(mtd, ofs, len, 0); -} static int __devinit ichxrom_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { + static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; + struct ichxrom_window *window = &ichxrom_window; + struct ichxrom_map_info *map = NULL; + unsigned long map_top; + u8 byte; u16 word; - struct ichxrom_map_info *info = &ichxrom_map; - unsigned long map_size; - static char *probes[] = { "cfi_probe", "jedec_probe" }; - struct cfi_private *cfi; /* For now I just handle the ichx and I assume there * are not a lot of resources up at the top of the address @@ -204,26 +104,56 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * Also you can page firmware hubs if an 8MB window isn't enough * but don't currently handle that case either. */ + window->pdev = pdev; + + /* Find a region continuous to the end of the ROM window */ + window->phys = 0; + pci_read_config_byte(pdev, FWH_DEC_EN1, &byte); + if (byte == 0xff) { + window->phys = 0xffc00000; + pci_read_config_byte(pdev, FWH_DEC_EN2, &byte); + if ((byte & 0x0f) == 0x0f) { + window->phys = 0xff400000; + } + else if ((byte & 0x0e) == 0x0e) { + window->phys = 0xff500000; + } + else if ((byte & 0x0c) == 0x0c) { + window->phys = 0xff600000; + } + else if ((byte & 0x08) == 0x08) { + window->phys = 0xff700000; + } + } + else if ((byte & 0xfe) == 0xfe) { + window->phys = 0xffc80000; + } + else if ((byte & 0xfc) == 0xfc) { + window->phys = 0xffd00000; + } + else if ((byte & 0xf8) == 0xf8) { + window->phys = 0xffd80000; + } + else if ((byte & 0xf0) == 0xf0) { + window->phys = 0xffe00000; + } + else if ((byte & 0xe0) == 0xe0) { + window->phys = 0xffe80000; + } + else if ((byte & 0xc0) == 0xc0) { + window->phys = 0xfff00000; + } + else if ((byte & 0x80) == 0x80) { + window->phys = 0xfff80000; + } - info->pdev = pdev; - - /* - * Try to reserve the window mem region. If this fails then - * it is likely due to the window being "reseved" by the BIOS. - */ - info->window_rsrc.name = MOD_NAME; - info->window_rsrc.start = ICHX_FWH_REGION_START; - info->window_rsrc.end = ICHX_FWH_REGION_START + ICHX_FWH_REGION_SIZE - 1; - info->window_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, &info->window_rsrc)) { - info->window_rsrc.parent = NULL; - printk(KERN_ERR MOD_NAME - " %s(): Unable to register resource" - " 0x%.08lx-0x%.08lx - kernel bug?\n", - __func__, - info->window_rsrc.start, info->window_rsrc.end); + if (window->phys == 0) { + printk(KERN_ERR MOD_NAME ": Rom window is closed\n"); + goto out; } - + window->phys -= 0x400000UL; + window->size = (0xffffffffUL - window->phys) + 1UL; + /* Enable writes through the rom window */ pci_read_config_word(pdev, BIOS_CNTL, &word); if (!(word & 1) && (word & (1<<1))) { @@ -231,119 +161,167 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * this device, so don't even try. */ printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n"); - goto failed; + goto out; } pci_write_config_word(pdev, BIOS_CNTL, word | 1); + /* + * Try to reserve the window mem region. If this fails then + * it is likely due to the window being "reseved" by the BIOS. + */ + window->rsrc.name = MOD_NAME; + window->rsrc.start = window->phys; + window->rsrc.end = window->phys + window->size - 1; + window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, &window->rsrc)) { + window->rsrc.parent = NULL; + printk(KERN_DEBUG MOD_NAME + ": %s(): Unable to register resource" + " 0x%.08lx-0x%.08lx - kernel bug?\n", + __func__, + window->rsrc.start, window->rsrc.end); + } /* Map the firmware hub into my address space. */ - /* Does this use too much virtual address space? */ - info->window_addr = (unsigned long)ioremap( - ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); - if (!info->window_addr) { - printk(KERN_ERR "Failed to ioremap\n"); - goto failed; + window->virt = ioremap_nocache(window->phys, window->size); + if (!window->virt) { + printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", + window->phys, window->size); + goto out; } - /* For now assume the firmware has setup all relevant firmware - * windows. We don't have enough information to handle this case - * intelligently. + /* Get the first address to look for an rom chip at */ + map_top = window->phys; + if ((window->phys & 0x3fffff) != 0) { + map_top = window->phys + 0x400000; + } +#if 1 + /* The probe sequence run over the firmware hub lock + * registers sets them to 0x7 (no access). + * Probe at most the last 4M of the address space. */ + if (map_top < 0xffc00000) { + map_top = 0xffc00000; + } +#endif + /* Loop through and look for rom chips */ + while((map_top - 1) < 0xffffffffUL) { + struct cfi_private *cfi; + unsigned long offset; + int i; + + if (!map) { + map = kmalloc(sizeof(*map), GFP_KERNEL); + } + if (!map) { + printk(KERN_ERR MOD_NAME ": kmalloc failed"); + goto out; + } + memset(map, 0, sizeof(*map)); + INIT_LIST_HEAD(&map->list); + map->map.name = map->map_name; + map->map.phys = map_top; + offset = map_top - window->phys; + map->map.virt = (void __iomem *) + (((unsigned long)(window->virt)) + offset); + map->map.size = 0xffffffffUL - map_top + 1UL; + /* Set the name of the map to the address I am trying */ + sprintf(map->map_name, "%s @%08lx", + MOD_NAME, map->map.phys); - /* FIXME select the firmware hub and enable a window to it. */ - - info->mtd = NULL; - info->map.map_priv_1 = info->window_addr; - - /* Loop through the possible bankwidths */ - for(ichxrom_map.map.bankwidth = 4; ichxrom_map.map.bankwidth; ichxrom_map.map.bankwidth >>= 1) { - map_size = ICHX_FWH_REGION_SIZE; - while(!info->mtd && (map_size > 0)) { - int i; - info->map.size = map_size; - for(i = 0; i < sizeof(probes)/sizeof(char *); i++) { - info->mtd = do_map_probe(probes[i], &ichxrom_map.map); - if (info->mtd) - break; + /* Firmware hubs only use vpp when being programmed + * in a factory setting. So in-place programming + * needs to use a different method. + */ + for(map->map.bankwidth = 32; map->map.bankwidth; + map->map.bankwidth >>= 1) + { + char **probe_type; + /* Skip bankwidths that are not supported */ + if (!map_bankwidth_supported(map->map.bankwidth)) + continue; + + /* Setup the map methods */ + simple_map_init(&map->map); + + /* Try all of the probe methods */ + probe_type = rom_probe_types; + for(; *probe_type; probe_type++) { + map->mtd = do_map_probe(*probe_type, &map->map); + if (map->mtd) + goto found; } - map_size -= 512*1024; } - if (info->mtd) - break; - } - if (!info->mtd) { - goto failed; - } - cfi = ichxrom_map.map.fldrv_priv; - if ((cfi->mfr == MANUFACTURER_INTEL) && ( - (cfi->id == I82802AB) || - (cfi->id == I82802AC))) - { - /* If it is a firmware hub put in the special lock - * and unlock routines. - */ - info->mtd->lock = ichxrom_lock; - info->mtd->unlock = ichxrom_unlock; - } - if (info->mtd->size > info->map.size) { - printk(KERN_WARNING MOD_NAME " rom(%u) larger than window(%lu). fixing...\n", - info->mtd->size, info->map.size); - info->mtd->size = info->map.size; - } + map_top += ROM_PROBE_STEP_SIZE; + continue; + found: + /* Trim the size if we are larger than the map */ + if (map->mtd->size > map->map.size) { + printk(KERN_WARNING MOD_NAME + " rom(%u) larger than window(%lu). fixing...\n", + map->mtd->size, map->map.size); + map->mtd->size = map->map.size; + } + if (window->rsrc.parent) { + /* + * Registering the MTD device in iomem may not be possible + * if there is a BIOS "reserved" and BUSY range. If this + * fails then continue anyway. + */ + map->rsrc.name = map->map_name; + map->rsrc.start = map->map.phys; + map->rsrc.end = map->map.phys + map->mtd->size - 1; + map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&window->rsrc, &map->rsrc)) { + printk(KERN_ERR MOD_NAME + ": cannot reserve MTD resource\n"); + map->rsrc.parent = NULL; + } + } + + /* Make the whole region visible in the map */ + map->map.virt = window->virt; + map->map.phys = window->phys; + cfi = map->map.fldrv_priv; + for(i = 0; i < cfi->numchips; i++) { + cfi->chips[i].start += offset; + } - info->mtd->owner = THIS_MODULE; - add_mtd_device(info->mtd); - - if (info->window_rsrc.parent) { - /* - * Registering the MTD device in iomem may not be possible - * if there is a BIOS "reserved" and BUSY range. If this - * fails then continue anyway. - */ - snprintf(info->mtd_name, MTD_DEV_NAME_LENGTH, - "mtd%d", info->mtd->index); - - info->rom_rsrc.name = info->mtd_name; - info->rom_rsrc.start = ICHX_FWH_REGION_START - + ICHX_FWH_REGION_SIZE - map_size; - info->rom_rsrc.end = ICHX_FWH_REGION_START - + ICHX_FWH_REGION_SIZE; - info->rom_rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&info->window_rsrc, &info->rom_rsrc)) { - printk(KERN_ERR MOD_NAME - ": cannot reserve MTD resource\n"); - info->rom_rsrc.parent = NULL; + /* Now that the mtd devices is complete claim and export it */ + map->mtd->owner = THIS_MODULE; + if (add_mtd_device(map->mtd)) { + map_destroy(map->mtd); + map->mtd = NULL; + goto out; } + + + /* Calculate the new value of map_top */ + map_top += map->mtd->size; + + /* File away the map structure */ + list_add(&map->list, &window->maps); + map = NULL; } + out: + /* Free any left over map structures */ + if (map) { + kfree(map); + } + /* See if I have any map structures */ + if (list_empty(&window->maps)) { + ichxrom_cleanup(window); + return -ENODEV; + } return 0; - - failed: - ichxrom_cleanup(info); - return -ENODEV; } static void __devexit ichxrom_remove_one (struct pci_dev *pdev) { - struct ichxrom_map_info *info = &ichxrom_map; - u16 word; - - del_mtd_device(info->mtd); - map_destroy(info->mtd); - info->mtd = NULL; - info->map.map_priv_1 = 0; - - iounmap((void *)(info->window_addr)); - info->window_addr = 0; - - /* Disable writes through the rom window */ - pci_read_config_word(pdev, BIOS_CNTL, &word); - pci_write_config_word(pdev, BIOS_CNTL, word & ~1); - -#if RESERVE_MEM_REGION - release_mem_region(ICHX_FWH_REGION_START, ICHX_FWH_REGION_SIZE); -#endif + struct ichxrom_window *window = &ichxrom_window; + ichxrom_cleanup(window); } static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { @@ -371,8 +349,7 @@ static struct pci_driver ichxrom_driver = { }; #endif -static struct pci_dev *mydev; -int __init init_ichxrom(void) +static int __init init_ichxrom(void) { struct pci_dev *pdev; struct pci_device_id *id; @@ -385,7 +362,6 @@ int __init init_ichxrom(void) } } if (pdev) { - mydev = pdev; return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]); } return -ENXIO; @@ -396,7 +372,7 @@ int __init init_ichxrom(void) static void __exit cleanup_ichxrom(void) { - ichxrom_remove_one(mydev); + ichxrom_remove_one(ichxrom_window.pdev); } module_init(init_ichxrom); diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index a05fc01b9..cb39172c8 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c @@ -1,5 +1,5 @@ /* - * $Id: impa7.c,v 1.11 2004/07/14 09:52:55 dwmw2 Exp $ + * $Id: impa7.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ * * Handle mapping of the NOR flash on implementa A7 boards * @@ -91,8 +91,7 @@ int __init init_impa7(void) pt[i].size, pt[i].addr); impa7_map[i].phys = pt[i].addr; - impa7_map[i].virt = (unsigned long) - ioremap(pt[i].addr, pt[i].size); + impa7_map[i].virt = ioremap(pt[i].addr, pt[i].size); if (!impa7_map[i].virt) { printk(MSG_PREFIX "failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index 1f23ab1cd..e39a98a01 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -22,7 +22,7 @@ This is access code for flashes using ARM's flash partitioning standards. - $Id: integrator-flash.c,v 1.16 2004/07/12 21:59:44 dwmw2 Exp $ + $Id: integrator-flash.c,v 1.18 2004/11/01 13:26:15 rmk Exp $ ======================================================================*/ @@ -75,7 +75,7 @@ static int armflash_probe(struct device *_dev) unsigned int size = res->end - res->start + 1; struct armflash_info *info; int err; - void *base; + void __iomem *base; info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); if (!info) { @@ -110,7 +110,7 @@ static int armflash_probe(struct device *_dev) info->map.size = size; info->map.bankwidth = plat->width; info->map.phys = res->start; - info->map.virt = (unsigned long) base; + info->map.virt = base; info->map.name = dev->dev.bus_id; info->map.set_vpp = armflash_set_vpp; @@ -179,7 +179,7 @@ static int armflash_remove(struct device *_dev) if (info->parts) kfree(info->parts); - iounmap((void *)info->map.virt); + iounmap(info->map.virt); release_resource(info->res); kfree(info->res); diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c index 17d7c7759..558d014e7 100644 --- a/drivers/mtd/maps/iq80310.c +++ b/drivers/mtd/maps/iq80310.c @@ -1,5 +1,5 @@ /* - * $Id: iq80310.c,v 1.18 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: iq80310.c,v 1.20 2004/11/04 13:24:15 gleixner Exp $ * * Mapping for the Intel XScale IQ80310 evaluation board * @@ -68,7 +68,7 @@ static int __init init_iq80310(void) int parsed_nr_parts = 0; int ret; - iq80310_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!iq80310_map.virt) { printk("Failed to ioremap\n"); return -EIO; diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 104488c0b..c5b5f447e 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -1,5 +1,5 @@ /* - * $Id: ixp2000.c,v 1.1 2004/09/02 00:13:41 dsaxena Exp $ + * $Id: ixp2000.c,v 1.5 2004/11/16 17:15:48 dsaxena Exp $ * * drivers/mtd/maps/ixp2000.c * @@ -14,7 +14,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * + * */ #include @@ -44,8 +44,8 @@ struct ixp2000_flash_info { }; static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs) -{ - unsigned long (*set_bank)(unsigned long) = +{ + unsigned long (*set_bank)(unsigned long) = (unsigned long(*)(unsigned long))map->map_priv_2; return (set_bank ? set_bank(ofs) : ofs); @@ -53,15 +53,15 @@ static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long #ifdef __ARMEB__ /* - * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which - * causes the lower address bits to be XORed with 0x11 on 8 bit accesses - * and XORed with 0x10 on 16 bit accesses. See the spec update, erratta 44. + * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which + * causes the lower address bits to be XORed with 0x11 on 8 bit accesses + * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44. */ -static int errata44_workaround = 0; +static int erratum44_workaround = 0; static inline unsigned long address_fix8_write(unsigned long addr) { - if (errata44_workaround) { + if (erratum44_workaround) { return (addr ^ 3); } return addr; @@ -88,7 +88,7 @@ static void ixp2000_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { from = flash_bank_setup(map, from); - while(len--) + while(len--) *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++); } @@ -127,8 +127,8 @@ static int ixp2000_flash_remove(struct device *_dev) if (info->map.map_priv_1) iounmap((void *) info->map.map_priv_1); - if (info->partitions) - kfree(info->partitions); + if (info->partitions) { + kfree(info->partitions); } if (info->res) { release_resource(info->res); @@ -147,11 +147,11 @@ static int ixp2000_flash_probe(struct device *_dev) static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; struct platform_device *dev = to_platform_device(_dev); struct ixp2000_flash_data *ixp_data = dev->dev.platform_data; - struct flash_platform_data *plat; + struct flash_platform_data *plat; struct ixp2000_flash_info *info; unsigned long window_size; int err = -1; - + if (!ixp_data) return -ENODEV; @@ -160,7 +160,7 @@ static int ixp2000_flash_probe(struct device *_dev) return -ENODEV; window_size = dev->resource->end - dev->resource->start + 1; - dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dM)\n", + dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n", ixp_data->nr_banks, ((u32)window_size >> 20)); if (plat->width != 1) { @@ -173,7 +173,7 @@ static int ixp2000_flash_probe(struct device *_dev) if(!info) { err = -ENOMEM; goto Error; - } + } memzero(info, sizeof(struct ixp2000_flash_info)); dev_set_drvdata(&dev->dev, info); @@ -183,7 +183,7 @@ static int ixp2000_flash_probe(struct device *_dev) * not attempt to do a direct access on us. */ info->map.phys = NO_XIP; - + info->nr_banks = ixp_data->nr_banks; info->map.size = ixp_data->nr_banks * window_size; info->map.bankwidth = 1; @@ -191,7 +191,7 @@ static int ixp2000_flash_probe(struct device *_dev) /* * map_priv_2 is used to store a ptr to to the bank_setup routine */ - info->map.map_priv_2 = (u32) ixp_data->bank_setup; + info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup; info->map.name = dev->dev.bus_id; info->map.read = ixp2000_flash_read8; @@ -199,8 +199,8 @@ static int ixp2000_flash_probe(struct device *_dev) info->map.copy_from = ixp2000_flash_copy_from; info->map.copy_to = ixp2000_flash_copy_to; - info->res = request_mem_region(dev->resource->start, - dev->resource->end - dev->resource->start + 1, + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, dev->dev.bus_id); if (!info->res) { dev_err(_dev, "Could not reserve memory region\n"); @@ -208,9 +208,8 @@ static int ixp2000_flash_probe(struct device *_dev) goto Error; } - info->map.map_priv_1 = - (unsigned long) ioremap(dev->resource->start, - dev->resource->end - dev->resource->start + 1); + info->map.map_priv_1 = ioremap(dev->resource->start, + dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { dev_err(_dev, "Failed to ioremap flash region\n"); err = -EIO; @@ -224,12 +223,12 @@ static int ixp2000_flash_probe(struct device *_dev) #if defined(__ARMEB__) /* - * Enable errata 44 workaround for NPUs with broken slowport + * Enable erratum 44 workaround for NPUs with broken slowport */ - errata44_workaround = ixp2000_has_broken_slowport(); - dev_info(_dev, "Errata 44 workaround %s\n", - errata44_workaround ? "enabled" : "disabled"); + erratum44_workaround = ixp2000_has_broken_slowport(); + dev_info(_dev, "Erratum 44 workaround %s\n", + erratum44_workaround ? "enabled" : "disabled"); #endif info->mtd = do_map_probe(plat->map_name, &info->map); diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 7ebc8cc5b..5afe660aa 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.3 2004/07/12 22:38:29 dwmw2 Exp $ + * $Id: ixp4xx.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -69,9 +69,22 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, dest[len - 1] = BYTE0(src[i]); } +/* + * Unaligned writes are ignored, causing the 8-bit + * probe to fail and proceed to the 16-bit probe (which succeeds). + */ +static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) +{ + if (!(adr & 1)) + *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; +} + +/* + * Fast write16 function without the probing check above + */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) { - *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; + *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; } struct ixp4xx_flash_info { @@ -88,6 +101,7 @@ static int ixp4xx_flash_remove(struct device *_dev) struct platform_device *dev = to_platform_device(_dev); struct flash_platform_data *plat = dev->dev.platform_data; struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev); + map_word d; dev_set_drvdata(&dev->dev, NULL); @@ -97,7 +111,8 @@ static int ixp4xx_flash_remove(struct device *_dev) /* * This is required for a soft reboot to work. */ - ixp4xx_write16(&info->map, 0xff, 0x55 * 0x2); + d.x[0] = 0xff; + ixp4xx_write16(&info->map, d, 0x55 * 0x2); if (info->mtd) { del_mtd_partitions(info->mtd); @@ -169,7 +184,7 @@ static int ixp4xx_flash_probe(struct device *_dev) info->map.bankwidth = 2; info->map.name = dev->dev.bus_id; info->map.read = ixp4xx_read16, - info->map.write = ixp4xx_write16, + info->map.write = ixp4xx_probe_write16, info->map.copy_from = ixp4xx_copy_from, info->res = request_mem_region(dev->resource->start, @@ -181,9 +196,8 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } - info->map.map_priv_1 = - (unsigned long) ioremap(dev->resource->start, - dev->resource->end - dev->resource->start + 1); + info->map.map_priv_1 = ioremap(dev->resource->start, + dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); err = -EIO; @@ -197,6 +211,9 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } info->mtd->owner = THIS_MODULE; + + /* Use the fast version */ + info->map.write = ixp4xx_write16, err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); if (err > 0) { diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index 046f7efbd..620ef1c38 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c @@ -1,5 +1,5 @@ /* - * $Id: l440gx.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: l440gx.c,v 1.16 2004/11/16 18:29:02 dwmw2 Exp $ * * BIOS Flash chip on Intel 440GX board. * @@ -30,7 +30,7 @@ static struct mtd_info *mymtd; /* Is this really the vpp port? */ -void l440gx_set_vpp(struct map_info *map, int vpp) +static void l440gx_set_vpp(struct map_info *map, int vpp) { unsigned long l; @@ -43,7 +43,7 @@ void l440gx_set_vpp(struct map_info *map, int vpp) outl(l, VPP_PORT); } -struct map_info l440gx_map = { +static struct map_info l440gx_map = { .name = "L440GX BIOS", .size = WINDOW_SIZE, .bankwidth = BUSWIDTH, @@ -73,7 +73,7 @@ static int __init init_l440gx(void) return -ENODEV; } - l440gx_map.virt = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); + l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); if (!l440gx_map.virt) { printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); @@ -103,7 +103,7 @@ static int __init init_l440gx(void) /* Allocate the resource region */ if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) { printk(KERN_WARNING "Could not allocate pm iobase resource\n"); - iounmap((void *)l440gx_map.virt); + iounmap(l440gx_map.virt); return -ENXIO; } } @@ -137,7 +137,7 @@ static int __init init_l440gx(void) return 0; } - iounmap((void *)l440gx_map.virt); + iounmap(l440gx_map.virt); return -ENXIO; } @@ -146,7 +146,7 @@ static void __exit cleanup_l440gx(void) del_mtd_device(mymtd); map_destroy(mymtd); - iounmap((void *)l440gx_map.virt); + iounmap(l440gx_map.virt); } module_init(init_l440gx); diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c index 2a2efaa42..c658d4045 100644 --- a/drivers/mtd/maps/lasat.c +++ b/drivers/mtd/maps/lasat.c @@ -7,7 +7,7 @@ * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * - * $Id: lasat.c,v 1.7 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $ * */ @@ -50,7 +50,7 @@ static int __init init_lasat(void) ENABLE_VPP((&lasat_map)); lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER); - lasat_map.virt = (unsigned long)ioremap_nocache( + lasat_map.virt = ioremap_nocache( lasat_map.phys, lasat_board_info.li_flash_size); lasat_map.size = lasat_board_info.li_flash_size; diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c index 53e708b2e..1298de475 100644 --- a/drivers/mtd/maps/lubbock-flash.c +++ b/drivers/mtd/maps/lubbock-flash.c @@ -1,5 +1,5 @@ /* - * $Id: lubbock-flash.c,v 1.15 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: lubbock-flash.c,v 1.19 2004/11/04 13:24:15 gleixner Exp $ * * Map driver for the Lubbock developer platform. * @@ -15,11 +15,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include @@ -82,16 +84,14 @@ static int __init init_lubbock(void) lubbock_maps[flashboot].name = "Lubbock Boot ROM"; for (i = 0; i < 2; i++) { - lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE); + lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE); if (!lubbock_maps[i].virt) { printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); if (!ret) ret = -ENOMEM; continue; } - lubbock_maps[i].cached = __ioremap(lubbock_maps[i].phys, - WINDOW_SIZE, - L_PTE_CACHEABLE, 1); + lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE); if (!lubbock_maps[i].cached) printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name); simple_map_init(&lubbock_maps[i]); diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c index 4c0f9e967..c5c6901a4 100644 --- a/drivers/mtd/maps/mbx860.c +++ b/drivers/mtd/maps/mbx860.c @@ -1,5 +1,5 @@ /* - * $Id: mbx860.c,v 1.6 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: mbx860.c,v 1.8 2004/11/04 13:24:15 gleixner Exp $ * * Handle mapping of the flash on MBX860 boards * @@ -60,7 +60,7 @@ struct map_info mbx_map = { int __init init_mbx(void) { printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR); - mbx_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); + mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); if (!mbx_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/mpc1211.c b/drivers/mtd/maps/mpc1211.c index cc55200a2..4685e8e13 100644 --- a/drivers/mtd/maps/mpc1211.c +++ b/drivers/mtd/maps/mpc1211.c @@ -1,7 +1,7 @@ /* * Flash on MPC-1211 * - * $Id: mpc1211.c,v 1.3 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $ * * (C) 2002 Interface, Saito.K & Jeanne * @@ -44,7 +44,7 @@ static int __init init_mpc1211_maps(void) int nr_parts; mpc1211_flash_map.phys = 0; - mpc1211_flash_map.virt = P2SEGADDR(0); + mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0); simple_map_init(&mpc1211_flash_map); diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index afdf6589b..0c7799f7f 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c @@ -3,7 +3,7 @@ * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH * - * $Id: netsc520.c,v 1.10 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: netsc520.c,v 1.12 2004/11/04 13:24:15 gleixner Exp $ * * 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 @@ -95,7 +95,7 @@ static struct mtd_info *mymtd; static int __init init_netsc520(void) { printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys); - netsc520_map.virt = (unsigned long)ioremap_nocache(netsc520_map.phys, netsc520_map.size); + netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size); if (!netsc520_map.virt) { printk("Failed to ioremap_nocache\n"); @@ -111,7 +111,7 @@ static int __init init_netsc520(void) mymtd = do_map_probe("map_rom", &netsc520_map); if (!mymtd) { - iounmap((void *)netsc520_map.virt); + iounmap(netsc520_map.virt); return -ENXIO; } @@ -127,8 +127,8 @@ static void __exit cleanup_netsc520(void) map_destroy(mymtd); } if (netsc520_map.virt) { - iounmap((void *)netsc520_map.virt); - netsc520_map.virt = 0; + iounmap(netsc520_map.virt); + netsc520_map.virt = NULL; } } diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index e06b07351..a6014b66b 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -6,7 +6,7 @@ * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) * - * $Id: nettel.c,v 1.5 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: nettel.c,v 1.8 2004/11/04 13:24:15 gleixner Exp $ */ /****************************************************************************/ @@ -180,7 +180,7 @@ int nettel_eraseconfig(void) if (mtd) { nettel_erase.mtd = mtd; nettel_erase.callback = nettel_erasecallback; - nettel_erase.callback = 0; + nettel_erase.callback = NULL; nettel_erase.addr = 0; nettel_erase.len = mtd->size; nettel_erase.priv = (u_long) &wait_q; @@ -273,8 +273,7 @@ int __init nettel_init(void) __asm__ ("wbinvd"); nettel_amd_map.phys = amdaddr; - nettel_amd_map.virt = (unsigned long) - ioremap_nocache(amdaddr, maxsize); + nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); if (!nettel_amd_map.virt) { printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); return(-EIO); @@ -472,8 +471,8 @@ void __exit nettel_cleanup(void) map_destroy(amd_mtd); } if (nettel_amd_map.virt) { - iounmap((void *)nettel_amd_map.virt); - nettel_amd_map.virt = 0; + iounmap(nettel_amd_map.virt); + nettel_amd_map.virt = NULL; } #ifdef CONFIG_MTD_CFI_INTELEXT if (intel_mtd) { diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c index 40c524d62..beb0b7bea 100644 --- a/drivers/mtd/maps/ocelot.c +++ b/drivers/mtd/maps/ocelot.c @@ -1,5 +1,5 @@ /* - * $Id: ocelot.c,v 1.13 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: ocelot.c,v 1.15 2004/11/04 13:24:15 gleixner Exp $ * * Flash on Momenco Ocelot */ @@ -81,7 +81,7 @@ static int __init init_ocelot_maps(void) iounmap(pld); /* Now ioremap the NVRAM space */ - ocelot_nvram_map.virt = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); + ocelot_nvram_map.virt = ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE); if (!ocelot_nvram_map.virt) { printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n"); return -EIO; @@ -101,7 +101,7 @@ static int __init init_ocelot_maps(void) nvram_mtd->write = ocelot_ram_write; /* Now map the flash space */ - ocelot_flash_map.virt = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); + ocelot_flash_map.virt = ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE); if (!ocelot_flash_map.virt) { printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n"); goto fail_2; diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c index 4262f1c03..496109071 100644 --- a/drivers/mtd/maps/omap-toto-flash.c +++ b/drivers/mtd/maps/omap-toto-flash.c @@ -5,7 +5,7 @@ * * (C) 2002 MontVista Software, Inc. * - * $Id: omap-toto-flash.c,v 1.2 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $ */ #include @@ -35,7 +35,7 @@ static struct map_info omap_toto_map_flash = { .name = "OMAP Toto flash", .bankwidth = 2, - .virt = OMAP_TOTO_FLASH_BASE, + .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE, }; diff --git a/drivers/mtd/maps/pb1550-flash.c b/drivers/mtd/maps/pb1550-flash.c index 4747fbc1f..1424726a2 100644 --- a/drivers/mtd/maps/pb1550-flash.c +++ b/drivers/mtd/maps/pb1550-flash.c @@ -1,7 +1,7 @@ /* * Flash memory access on Alchemy Pb1550 board * - * $Id: pb1550-flash.c,v 1.4 2004/07/14 17:45:40 dwmw2 Exp $ + * $Id: pb1550-flash.c,v 1.6 2004/11/04 13:24:15 gleixner Exp $ * * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c: * (C) 2003 Pete Popov @@ -178,8 +178,7 @@ int __init pb1550_mtd_init(void) */ printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n", pb1550_map.bankwidth*8); - pb1550_map.virt = - (unsigned long)ioremap(window_addr, window_size); + pb1550_map.virt = ioremap(window_addr, window_size); mymtd = do_map_probe("cfi_probe", &pb1550_map); if (!mymtd) return -ENXIO; mymtd->owner = THIS_MODULE; diff --git a/drivers/mtd/maps/pb1xxx-flash.c b/drivers/mtd/maps/pb1xxx-flash.c index b6b8ccf48..06e731540 100644 --- a/drivers/mtd/maps/pb1xxx-flash.c +++ b/drivers/mtd/maps/pb1xxx-flash.c @@ -3,7 +3,7 @@ * * (C) 2001 Pete Popov * - * $Id: pb1xxx-flash.c,v 1.11 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: pb1xxx-flash.c,v 1.14 2004/11/04 13:24:15 gleixner Exp $ */ #include @@ -17,7 +17,6 @@ #include #include -#include #ifdef DEBUG_RW #define DBG(x...) printk(x) @@ -150,7 +149,7 @@ int __init pb1xxx_mtd_init(void) */ printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n", BUSWIDTH*8); - pb1xxx_mtd_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + pb1xxx_mtd_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); simple_map_init(&pb1xxx_mtd_map); diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 8b5d1ff45..fa29999fb 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -33,7 +33,7 @@ struct mtd_pci_info { struct map_pci_info { struct map_info map; - void *base; + void __iomem *base; void (*exit)(struct pci_dev *dev, struct map_pci_info *map); unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs); struct pci_dev *dev; @@ -143,7 +143,7 @@ static void intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map) { if (map->base) - iounmap((void *)map->base); + iounmap(map->base); pci_write_config_dword(dev, 0x44, map->map.map_priv_2); } @@ -236,7 +236,7 @@ intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map) u32 val; if (map->base) - iounmap((void *)map->base); + iounmap(map->base); /* * We need to undo the PCI BAR2/PCI ROM BAR address alteration. diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 5822ba99c..0b605af8b 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -1,5 +1,5 @@ /* - * $Id: physmap.c,v 1.34 2004/07/21 00:16:14 jwboyer Exp $ + * $Id: physmap.c,v 1.36 2004/11/04 13:24:15 gleixner Exp $ * * Normal mappings of chips in physical memory * @@ -51,7 +51,7 @@ static int __init init_physmap(void) const char **type; printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); - physmap_map.virt = (unsigned long)ioremap(physmap_map.phys, physmap_map.size); + physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size); if (!physmap_map.virt) { printk("Failed to ioremap\n"); @@ -92,7 +92,7 @@ static int __init init_physmap(void) return 0; } - iounmap((void *)physmap_map.virt); + iounmap(physmap_map.virt); return -ENXIO; } @@ -112,8 +112,8 @@ static void __exit cleanup_physmap(void) #endif map_destroy(mymtd); - iounmap((void *)physmap_map.virt); - physmap_map.virt = 0; + iounmap(physmap_map.virt); + physmap_map.virt = NULL; } module_init(init_physmap); diff --git a/drivers/mtd/maps/pnc2000.c b/drivers/mtd/maps/pnc2000.c index b204786d5..a0f43dad8 100644 --- a/drivers/mtd/maps/pnc2000.c +++ b/drivers/mtd/maps/pnc2000.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: pnc2000.c,v 1.15 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: pnc2000.c,v 1.17 2004/11/16 18:29:02 dwmw2 Exp $ */ #include @@ -26,12 +26,12 @@ */ -struct map_info pnc_map = { +static struct map_info pnc_map = { .name = "PNC-2000", .size = WINDOW_SIZE, .bankwidth = 4, .phys = 0xFFFFFFFF, - .virt = WINDOW_ADDR, + .virt = (void __iomem *)WINDOW_ADDR, }; @@ -62,7 +62,7 @@ static struct mtd_partition pnc_partitions[3] = { */ static struct mtd_info *mymtd; -int __init init_pnc2000(void) +static int __init init_pnc2000(void) { printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index acc3af90a..edd01ee4f 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c @@ -1,5 +1,5 @@ /* - * $Id: redwood.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: redwood.c,v 1.10 2004/11/04 13:24:15 gleixner Exp $ * * drivers/mtd/maps/redwood.c * @@ -131,8 +131,7 @@ int __init init_redwood_flash(void) printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - redwood_flash_map.virt = - (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); + redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!redwood_flash_map.virt) { printk("init_redwood_flash: failed to ioremap\n"); diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c index 837089a8f..809a0c8e7 100644 --- a/drivers/mtd/maps/rpxlite.c +++ b/drivers/mtd/maps/rpxlite.c @@ -1,5 +1,5 @@ /* - * $Id: rpxlite.c,v 1.20 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: rpxlite.c,v 1.22 2004/11/04 13:24:15 gleixner Exp $ * * Handle mapping of the flash on the RPX Lite and CLLF boards */ @@ -28,7 +28,7 @@ static struct map_info rpxlite_map = { int __init init_rpxlite(void) { printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); - rpxlite_map.virt = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); + rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); if (!rpxlite_map.virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index c42ca6f96..0a6f861c4 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -3,9 +3,8 @@ * * (C) 2000 Nicolas Pitre * - * $Id: sa1100-flash.c,v 1.39 2004/07/12 21:59:44 dwmw2 Exp $ + * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $ */ - #include #include #include @@ -14,1339 +13,440 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include +#include -#include - -#ifndef CONFIG_ARCH_SA1100 -#error This is for SA1100 architecture only -#endif - -/* - * This isnt complete yet, so... - */ -#define CONFIG_MTD_SA1100_STATICMAP 1 - -#ifdef CONFIG_MTD_SA1100_STATICMAP -/* - * Here are partition information for all known SA1100-based devices. - * See include/linux/mtd/partitions.h for definition of the mtd_partition - * structure. - * - * Please note: - * 1. We no longer support static flash mappings via the machine io_desc - * structure. - * 2. The flash size given should be the largest flash size that can - * be accommodated. - * - * The MTD layer will detect flash chip aliasing and reduce the size of - * the map accordingly. - * - * Please keep these in alphabetical order, and formatted as per existing - * entries. Thanks. - */ - -#ifdef CONFIG_SA1100_ADSBITSY -static struct mtd_partition adsbitsy_partitions[] = { - { - .name = "bootROM", - .size = 0x80000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "zImage", - .size = 0x100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "ramdisk.gz", - .size = 0x300000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "User FS", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_ASSABET -/* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */ -static struct mtd_partition assabet4_partitions[] = { - { - .name = "bootloader", - .size = 0x00020000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "bootloader params", - .size = 0x00020000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "jffs", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; - -/* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */ -static struct mtd_partition assabet5_partitions[] = { - { - .name = "bootloader", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "bootloader params", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "jffs", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; - -#define assabet_partitions assabet5_partitions -#endif - -#ifdef CONFIG_SA1100_BADGE4 +#if 0 /* - * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit) - * Eight 4 KiW Parameter Bottom Blocks (64 KiB) - * Sixty-three 32 KiW Main Blocks (4032 Ki b) - * - * - * - * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit) - * Eight 4 KiW Parameter Bottom Blocks (64 KiB) - * One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b) - */ -static struct mtd_partition badge4_partitions[] = { - { - .name = "BLOB boot loader", - .offset = 0, - .size = 0x0000A000 - }, { - .name = "params", - .offset = MTDPART_OFS_APPEND, - .size = 0x00006000 - }, { - .name = "root", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL - } -}; -#endif - - -#ifdef CONFIG_SA1100_CERF -#ifdef CONFIG_SA1100_CERF_FLASH_32MB -# define CERF_FLASH_SIZE 0x02000000 -#elif defined CONFIG_SA1100_CERF_FLASH_16MB -# define CERF_FLASH_SIZE 0x01000000 -#elif defined CONFIG_SA1100_CERF_FLASH_8MB -# define CERF_FLASH_SIZE 0x00800000 -#else -# error "Undefined flash size for CERF in sa1100-flash.c" -#endif - -static struct mtd_partition cerf_partitions[] = { - { - .name = "Bootloader", - .size = 0x00020000, - .offset = 0x00000000, - }, { - .name = "Params", - .size = 0x00040000, - .offset = 0x00020000, - }, { - .name = "Kernel", - .size = 0x00100000, - .offset = 0x00060000, - }, { - .name = "Filesystem", - .size = CERF_FLASH_SIZE-0x00160000, - .offset = 0x00160000, - } -}; -#endif - -#ifdef CONFIG_SA1100_CONSUS -static struct mtd_partition consus_partitions[] = { - { - .name = "Consus boot firmware", - .offset = 0, - .size = 0x00040000, - .mask_flags = MTD_WRITABLE, /* force read-only */ - }, { - .name = "Consus kernel", - .offset = 0x00040000, - .size = 0x00100000, - .mask_flags = 0, - }, { - .name = "Consus disk", - .offset = 0x00140000, - /* The rest (up to 16M) for jffs. We could put 0 and - make it find the size automatically, but right now - i have 32 megs. jffs will use all 32 megs if given - the chance, and this leads to horrible problems - when you try to re-flash the image because blob - won't erase the whole partition. */ - .size = 0x01000000 - 0x00140000, - .mask_flags = 0, - }, { - /* this disk is a secondary disk, which can be used as - needed, for simplicity, make it the size of the other - consus partition, although realistically it could be - the remainder of the disk (depending on the file - system used) */ - .name = "Consus disk2", - .offset = 0x01000000, - .size = 0x01000000 - 0x00140000, - .mask_flags = 0, - } -}; -#endif - -#ifdef CONFIG_SA1100_FLEXANET -/* Flexanet has two 28F128J3A flash parts in bank 0: */ -#define FLEXANET_FLASH_SIZE 0x02000000 -static struct mtd_partition flexanet_partitions[] = { - { - .name = "bootloader", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "bootloader params", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "kernel", - .size = 0x000C0000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "altkernel", - .size = 0x000C0000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "root", - .size = 0x00400000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "free1", - .size = 0x00300000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "free2", - .size = 0x00300000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - }, { - .name = "free3", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, - } -}; -#endif - -#ifdef CONFIG_SA1100_FREEBIRD -static struct mtd_partition freebird_partitions[] = { -#ifdef CONFIG_SA1100_FREEBIRD_NEW - { - .name = "firmware", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "kernel", - .size = 0x00080000, - .offset = 0x00040000, - }, { - .name = "params", - .size = 0x00040000, - .offset = 0x000C0000, - }, { - .name = "initrd", - .size = 0x00100000, - .offset = 0x00100000, - }, { - .name = "root cramfs", - .size = 0x00300000, - .offset = 0x00200000, - }, { - .name = "usr cramfs", - .size = 0x00C00000, - .offset = 0x00500000, - }, { - .name = "local", - .size = MTDPART_SIZ_FULL, - .offset = 0x01100000, - } -#else - { - .size = 0x00040000, - .offset = 0, - }, { - .size = 0x000c0000, - .offset = MTDPART_OFS_APPEND, - }, { - .size = 0x00400000, - .offset = MTDPART_OFS_APPEND, - }, { - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -#endif -}; -#endif - -#ifdef CONFIG_SA1100_FRODO -/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ -static struct mtd_partition frodo_partitions[] = -{ - { - .name = "bootloader", - .size = 0x00040000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE - }, { - .name = "bootloader params", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "kernel", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "ramdisk", - .size = 0x00400000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE - }, { - .name = "file system", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND - } -}; -#endif - -#ifdef CONFIG_SA1100_GRAPHICSCLIENT -static struct mtd_partition graphicsclient_partitions[] = { - { - .name = "zImage", - .size = 0x100000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "ramdisk.gz", - .size = 0x300000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "User FS", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_GRAPHICSMASTER -static struct mtd_partition graphicsmaster_partitions[] = { - { - .name = "zImage", - .size = 0x100000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "ramdisk.gz", - .size = 0x300000, - .offset = MTDPART_OFS_APPEND, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "User FS", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_H3XXX -static struct mtd_partition h3xxx_partitions[] = { - { - .name = "H3XXX boot firmware", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { -#ifdef CONFIG_MTD_2PARTS_IPAQ - .name = "H3XXX root jffs2", - .size = MTDPART_SIZ_FULL, - .offset = 0x00040000, -#else - .name = "H3XXX kernel", - .size = 0x00080000, - .offset = 0x00040000, - }, { - .name = "H3XXX params", - .size = 0x00040000, - .offset = 0x000C0000, - }, { -#ifdef CONFIG_JFFS2_FS - .name = "H3XXX root jffs2", - .size = MTDPART_SIZ_FULL, - .offset = 0x00100000, -#else - .name = "H3XXX initrd", - .size = 0x00100000, - .offset = 0x00100000, - }, { - .name = "H3XXX root cramfs", - .size = 0x00300000, - .offset = 0x00200000, - }, { - .name = "H3XXX usr cramfs", - .size = 0x00800000, - .offset = 0x00500000, - }, { - .name = "H3XXX usr local", - .size = MTDPART_SIZ_FULL, - .offset = 0x00d00000, -#endif -#endif - } -}; - -static void h3xxx_set_vpp(struct map_info *map, int vpp) -{ - assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp); -} -#else -#define h3xxx_set_vpp NULL -#endif - -#ifdef CONFIG_SA1100_HACKKIT -static struct mtd_partition hackkit_partitions[] = { - { - .name = "BLOB", - .size = 0x00040000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "config", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "kernel", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "initrd", - .size = 0x00180000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "rootfs", - .size = 0x700000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "data", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_HUW_WEBPANEL -static struct mtd_partition huw_webpanel_partitions[] = { - { - .name = "Loader", - .size = 0x00040000, - .offset = 0, - }, { - .name = "Sector 1", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - }, { - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_JORNADA720 -static struct mtd_partition jornada720_partitions[] = { - { - .name = "JORNADA720 boot firmware", - .size = 0x00040000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "JORNADA720 kernel", - .size = 0x000c0000, - .offset = 0x00040000, - }, { - .name = "JORNADA720 params", - .size = 0x00040000, - .offset = 0x00100000, - }, { - .name = "JORNADA720 initrd", - .size = 0x00100000, - .offset = 0x00140000, - }, { - .name = "JORNADA720 root cramfs", - .size = 0x00300000, - .offset = 0x00240000, - }, { - .name = "JORNADA720 usr cramfs", - .size = 0x00800000, - .offset = 0x00540000, - }, { - .name = "JORNADA720 usr local", - .size = 0, /* will expand to the end of the flash */ - .offset = 0x00d00000, - } -}; - -static void jornada720_set_vpp(struct map_info *map, int vpp) -{ - if (vpp) - PPSR |= 0x80; - else - PPSR &= ~0x80; - PPDR |= 0x80; -} -#else -#define jornada720_set_vpp NULL -#endif - -#ifdef CONFIG_SA1100_PANGOLIN -static struct mtd_partition pangolin_partitions[] = { - { - .name = "boot firmware", - .size = 0x00080000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "kernel", - .size = 0x00100000, - .offset = 0x00080000, - }, { - .name = "initrd", - .size = 0x00280000, - .offset = 0x00180000, - }, { - .name = "initrd-test", - .size = 0x03C00000, - .offset = 0x00400000, - } -}; -#endif - -#ifdef CONFIG_SA1100_PT_SYSTEM3 -/* erase size is 0x40000 == 256k partitions have to have this boundary */ -static struct mtd_partition system3_partitions[] = { - { - .name = "BLOB", - .size = 0x00040000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "config", - .size = 0x00040000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "kernel", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - }, { - .name = "root", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_SHANNON -static struct mtd_partition shannon_partitions[] = { - { - .name = "BLOB boot loader", - .offset = 0, - .size = 0x20000 - }, - { - .name = "kernel", - .offset = MTDPART_OFS_APPEND, - .size = 0xe0000 - }, - { - .name = "initrd", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL - } -}; - -#endif - -#ifdef CONFIG_SA1100_SHERMAN -static struct mtd_partition sherman_partitions[] = { - { - .size = 0x50000, - .offset = 0, - }, { - .size = 0x70000, - .offset = MTDPART_OFS_APPEND, - }, { - .size = 0x600000, - .offset = MTDPART_OFS_APPEND, - }, { - .size = 0xA0000, - .offset = MTDPART_OFS_APPEND, - } -}; -#endif - -#ifdef CONFIG_SA1100_SIMPAD -static struct mtd_partition simpad_partitions[] = { - { - .name = "SIMpad boot firmware", - .size = 0x00080000, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "SIMpad kernel", - .size = 0x00100000, - .offset = MTDPART_OFS_APPEND, - }, { -#ifdef CONFIG_ROOT_CRAMFS - .name = "SIMpad root cramfs", - .size =0x00D80000, - .offset = MTDPART_OFS_APPEND - - }, { - .name = "SIMpad local jffs2", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND -#else - .name = "SIMpad root jffs2", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND -#endif - } -}; -#endif /* CONFIG_SA1100_SIMPAD */ - -#ifdef CONFIG_SA1100_STORK -static struct mtd_partition stork_partitions[] = { + * This is here for documentation purposes only - until these people + * submit their machine types. It will be gone January 2005. + */ +static struct mtd_partition consus_partitions[] = { { - .name = "STORK boot firmware", - .size = 0x00040000, + .name = "Consus boot firmware", .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "STORK params", .size = 0x00040000, - .offset = 0x00040000, - }, { - .name = "STORK kernel", - .size = 0x00100000, - .offset = 0x00080000, + .mask_flags = MTD_WRITABLE, /* force read-only */ }, { -#ifdef CONFIG_JFFS2_FS - .name = "STORK root jffs2", - .offset = 0x00180000, - .size = MTDPART_SIZ_FULL, -#else - .name = "STORK initrd", + .name = "Consus kernel", + .offset = 0x00040000, .size = 0x00100000, - .offset = 0x00180000, - }, { - .name = "STORK root cramfs", - .size = 0x00300000, - .offset = 0x00280000, + .mask_flags = 0, }, { - .name = "STORK usr cramfs", - .size = 0x00800000, - .offset = 0x00580000, + .name = "Consus disk", + .offset = 0x00140000, + /* The rest (up to 16M) for jffs. We could put 0 and + make it find the size automatically, but right now + i have 32 megs. jffs will use all 32 megs if given + the chance, and this leads to horrible problems + when you try to re-flash the image because blob + won't erase the whole partition. */ + .size = 0x01000000 - 0x00140000, + .mask_flags = 0, }, { - .name = "STORK usr local", - .offset = 0x00d80000, - .size = MTDPART_SIZ_FULL, -#endif + /* this disk is a secondary disk, which can be used as + needed, for simplicity, make it the size of the other + consus partition, although realistically it could be + the remainder of the disk (depending on the file + system used) */ + .name = "Consus disk2", + .offset = 0x01000000, + .size = 0x01000000 - 0x00140000, + .mask_flags = 0, } }; -#endif -#ifdef CONFIG_SA1100_TRIZEPS -static struct mtd_partition trizeps_partitions[] = { +/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */ +static struct mtd_partition frodo_partitions[] = +{ { - .name = "Bootloader", - .size = 0x00100000, - .offset = 0, + .name = "bootloader", + .size = 0x00040000, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE + }, { + .name = "bootloader params", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE }, { - .name = "Kernel", + .name = "kernel", .size = 0x00100000, .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE }, { - .name = "root", - .size = MTDPART_SIZ_FULL, + .name = "ramdisk", + .size = 0x00400000, .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE + }, { + .name = "file system", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND } }; -#endif -#ifdef CONFIG_SA1100_YOPY -static struct mtd_partition yopy_partitions[] = { +static struct mtd_partition jornada56x_partitions[] = { { - .name = "boot firmware", + .name = "bootldr", .size = 0x00040000, - .offset = 0x00000000, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { - .name = "kernel", - .size = 0x00080000, - .offset = 0x00080000, - }, { - .name = "initrd", - .size = 0x00300000, - .offset = 0x00100000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, }, { - .name = "root", - .size = 0x01000000, - .offset = 0x00400000, + .name = "rootfs", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, } }; -#endif -static int __init sa1100_static_partitions(struct mtd_partition **parts) +static void jornada56x_set_vpp(int vpp) { - int nb_parts = 0; - -#ifdef CONFIG_SA1100_ADSBITSY - if (machine_is_adsbitsy()) { - *parts = adsbitsy_partitions; - nb_parts = ARRAY_SIZE(adsbitsy_partitions); - } -#endif -#ifdef CONFIG_SA1100_ASSABET - if (machine_is_assabet()) { - *parts = assabet_partitions; - nb_parts = ARRAY_SIZE(assabet_partitions); - } -#endif -#ifdef CONFIG_SA1100_BADGE4 - if (machine_is_badge4()) { - *parts = badge4_partitions; - nb_parts = ARRAY_SIZE(badge4_partitions); - } -#endif -#ifdef CONFIG_SA1100_CERF - if (machine_is_cerf()) { - *parts = cerf_partitions; - nb_parts = ARRAY_SIZE(cerf_partitions); - } -#endif -#ifdef CONFIG_SA1100_CONSUS - if (machine_is_consus()) { - *parts = consus_partitions; - nb_parts = ARRAY_SIZE(consus_partitions); - } -#endif -#ifdef CONFIG_SA1100_FLEXANET - if (machine_is_flexanet()) { - *parts = flexanet_partitions; - nb_parts = ARRAY_SIZE(flexanet_partitions); - } -#endif -#ifdef CONFIG_SA1100_FREEBIRD - if (machine_is_freebird()) { - *parts = freebird_partitions; - nb_parts = ARRAY_SIZE(freebird_partitions); - } -#endif -#ifdef CONFIG_SA1100_FRODO - if (machine_is_frodo()) { - *parts = frodo_partitions; - nb_parts = ARRAY_SIZE(frodo_partitions); - } -#endif -#ifdef CONFIG_SA1100_GRAPHICSCLIENT - if (machine_is_graphicsclient()) { - *parts = graphicsclient_partitions; - nb_parts = ARRAY_SIZE(graphicsclient_partitions); - } -#endif -#ifdef CONFIG_SA1100_GRAPHICSMASTER - if (machine_is_graphicsmaster()) { - *parts = graphicsmaster_partitions; - nb_parts = ARRAY_SIZE(graphicsmaster_partitions); - } -#endif -#ifdef CONFIG_SA1100_H3XXX - if (machine_is_h3xxx()) { - *parts = h3xxx_partitions; - nb_parts = ARRAY_SIZE(h3xxx_partitions); - } -#endif -#ifdef CONFIG_SA1100_HACKKIT - if (machine_is_hackkit()) { - *parts = hackkit_partitions; - nb_parts = ARRAY_SIZE(hackkit_partitions); - } -#endif -#ifdef CONFIG_SA1100_HUW_WEBPANEL - if (machine_is_huw_webpanel()) { - *parts = huw_webpanel_partitions; - nb_parts = ARRAY_SIZE(huw_webpanel_partitions); - } -#endif -#ifdef CONFIG_SA1100_JORNADA720 - if (machine_is_jornada720()) { - *parts = jornada720_partitions; - nb_parts = ARRAY_SIZE(jornada720_partitions); - } -#endif -#ifdef CONFIG_SA1100_PANGOLIN - if (machine_is_pangolin()) { - *parts = pangolin_partitions; - nb_parts = ARRAY_SIZE(pangolin_partitions); - } -#endif -#ifdef CONFIG_SA1100_PT_SYSTEM3 - if (machine_is_pt_system3()) { - *parts = system3_partitions; - nb_parts = ARRAY_SIZE(system3_partitions); - } -#endif -#ifdef CONFIG_SA1100_SHANNON - if (machine_is_shannon()) { - *parts = shannon_partitions; - nb_parts = ARRAY_SIZE(shannon_partitions); - } -#endif -#ifdef CONFIG_SA1100_SHERMAN - if (machine_is_sherman()) { - *parts = sherman_partitions; - nb_parts = ARRAY_SIZE(sherman_partitions); - } -#endif -#ifdef CONFIG_SA1100_SIMPAD - if (machine_is_simpad()) { - *parts = simpad_partitions; - nb_parts = ARRAY_SIZE(simpad_partitions); - } -#endif -#ifdef CONFIG_SA1100_STORK - if (machine_is_stork()) { - *parts = stork_partitions; - nb_parts = ARRAY_SIZE(stork_partitions); - } -#endif -#ifdef CONFIG_SA1100_TRIZEPS - if (machine_is_trizeps()) { - *parts = trizeps_partitions; - nb_parts = ARRAY_SIZE(trizeps_partitions); - } -#endif -#ifdef CONFIG_SA1100_YOPY - if (machine_is_yopy()) { - *parts = yopy_partitions; - nb_parts = ARRAY_SIZE(yopy_partitions); - } -#endif - - return nb_parts; + if (vpp) + GPSR = GPIO_GPIO26; + else + GPCR = GPIO_GPIO26; + GPDR |= GPIO_GPIO26; } + +/* + * Machine Phys Size set_vpp + * Consus : SA1100_CS0_PHYS SZ_32M + * Frodo : SA1100_CS0_PHYS SZ_32M + * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp + */ #endif -struct sa_info { - unsigned long base; - unsigned long size; - int width; - void *vbase; - void (*set_vpp)(struct map_info *, int); - struct map_info *map; +struct sa_subdev_info { + char name[16]; + struct map_info map; struct mtd_info *mtd; - struct resource *res; + struct flash_platform_data *data; }; -#define NR_SUBMTD 4 +struct sa_info { + struct mtd_partition *parts; + struct mtd_info *mtd; + int num_subdev; + struct sa_subdev_info subdev[0]; +}; -static struct sa_info info[NR_SUBMTD]; +static void sa1100_set_vpp(struct map_info *map, int on) +{ + struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map); + subdev->data->set_vpp(on); +} -static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd) +static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) { - struct mtd_info *subdev[nr]; - struct map_info *maps; - int i, found = 0, ret = 0; + if (subdev->mtd) + map_destroy(subdev->mtd); + if (subdev->map.virt) + iounmap(subdev->map.virt); + release_mem_region(subdev->map.phys, subdev->map.size); +} - /* - * Allocate the map_info structs in one go. - */ - maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL); - if (!maps) - return -ENOMEM; +static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res) +{ + unsigned long phys; + unsigned int size; + int ret; - memset(maps, 0, sizeof(struct map_info) * nr); + phys = res->start; + size = res->end - phys + 1; /* - * Claim and then map the memory regions. + * Retrieve the bankwidth from the MSC registers. + * We currently only implement CS0 and CS1 here. */ - for (i = 0; i < nr; i++) { - if (sa[i].base == (unsigned long)-1) - break; - - sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash"); - if (!sa[i].res) { - ret = -EBUSY; - break; - } + switch (phys) { + default: + printk(KERN_WARNING "SA1100 flash: unknown base address " + "0x%08lx, assuming CS0\n", phys); - sa[i].map = maps + i; + case SA1100_CS0_PHYS: + subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4; + break; - sa[i].vbase = ioremap(sa[i].base, sa[i].size); - if (!sa[i].vbase) { - ret = -ENOMEM; - break; - } - - sa[i].map->virt = (unsigned long)sa[i].vbase; - sa[i].map->phys = sa[i].base; - sa[i].map->set_vpp = sa[i].set_vpp; - sa[i].map->bankwidth = sa[i].width; - sa[i].map->size = sa[i].size; + case SA1100_CS1_PHYS: + subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4; + break; + } - simple_map_init(sa[i].map); + if (!request_mem_region(phys, size, subdev->name)) { + ret = -EBUSY; + goto out; + } - /* - * Now let's probe for the actual flash. Do it here since - * specific machine settings might have been set above. - */ - sa[i].mtd = do_map_probe("cfi_probe", sa[i].map); - if (sa[i].mtd == NULL) { - ret = -ENXIO; - break; - } - sa[i].mtd->owner = THIS_MODULE; - subdev[i] = sa[i].mtd; + if (subdev->data->set_vpp) + subdev->map.set_vpp = sa1100_set_vpp; - printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " - "%d-bit\n", sa[i].base, sa[i].mtd->size >> 20, - sa[i].width * 8); - found += 1; + subdev->map.phys = phys; + subdev->map.size = size; + subdev->map.virt = ioremap(phys, size); + if (!subdev->map.virt) { + ret = -ENOMEM; + goto err; } - /* - * ENXIO is special. It means we didn't find a chip when - * we probed. We need to tear down the mapping, free the - * resource and mark it as such. - */ - if (ret == -ENXIO) { - iounmap(sa[i].vbase); - sa[i].vbase = NULL; - release_resource(sa[i].res); - sa[i].res = NULL; - } + simple_map_init(&subdev->map); /* - * If we found one device, don't bother with concat support. - * If we found multiple devices, use concat if we have it - * available, otherwise fail. + * Now let's probe for the actual flash. Do it here since + * specific machine settings might have been set above. */ - if (ret == 0 || ret == -ENXIO) { - if (found == 1) { - *rmtd = subdev[0]; - ret = 0; - } else if (found > 1) { - /* - * We detected multiple devices. Concatenate - * them together. - */ -#ifdef CONFIG_MTD_CONCAT - *rmtd = mtd_concat_create(subdev, found, - "sa1100 flash"); - if (*rmtd == NULL) - ret = -ENXIO; -#else - printk(KERN_ERR "SA1100 flash: multiple devices " - "found but MTD concat support disabled.\n"); - ret = -ENXIO; -#endif - } + subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map); + if (subdev->mtd == NULL) { + ret = -ENXIO; + goto err; } + subdev->mtd->owner = THIS_MODULE; - /* - * If we failed, clean up. - */ - if (ret) { - do { - if (sa[i].mtd) - map_destroy(sa[i].mtd); - if (sa[i].vbase) - iounmap(sa[i].vbase); - if (sa[i].res) - release_resource(sa[i].res); - } while (i--); + printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, " + "%d-bit\n", phys, subdev->mtd->size >> 20, + subdev->map.bankwidth * 8); - kfree(maps); - } + return 0; + err: + sa1100_destroy_subdev(subdev); + out: return ret; } -static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd) +static void sa1100_destroy(struct sa_info *info) { int i; - del_mtd_partitions(mtd); + if (info->mtd) { + del_mtd_partitions(info->mtd); #ifdef CONFIG_MTD_CONCAT - if (mtd != sa[0].mtd) - mtd_concat_destroy(mtd); + if (info->mtd != info->subdev[0].mtd) + mtd_concat_destroy(info->mtd); #endif - - for (i = NR_SUBMTD; i >= 0; i--) { - if (sa[i].mtd) - map_destroy(sa[i].mtd); - if (sa[i].vbase) - iounmap(sa[i].vbase); - if (sa[i].res) - release_resource(sa[i].res); } - kfree(sa[0].map); -} -/* - * A Thought: can we automatically detect the flash? - * - Check to see if the region is busy (yes -> failure) - * - Is the MSC setup for flash (no -> failure) - * - Probe for flash - */ + if (info->parts) + kfree(info->parts); -static struct map_info sa1100_probe_map __initdata = { - .name = "SA1100-flash", -}; + for (i = info->num_subdev - 1; i >= 0; i--) + sa1100_destroy_subdev(&info->subdev[i]); + kfree(info); +} -static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys) +static struct sa_info *__init +sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash) { - struct mtd_info *mtd; - - printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ", - phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32); + struct sa_info *info; + int nr, size, i, ret = 0; - if (check_mem_region(phys, 0x08000000)) { - printk("busy\n"); - return; - } + /* + * Count number of devices. + */ + for (nr = 0; ; nr++) + if (!platform_get_resource(pdev, IORESOURCE_MEM, nr)) + break; - if ((msc & 3) == 1) { - printk("wrong type\n"); - return; + if (nr == 0) { + ret = -ENODEV; + goto out; } - sa1100_probe_map.bankwidth = msc & MSC_RBW ? 2 : 4; - sa1100_probe_map.size = SZ_1M; - sa1100_probe_map.phys = phys; - sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M); - if (sa1100_probe_map.virt == 0) - goto fail; - simple_map_init(&sa1100_probe_map); - - /* Shame cfi_probe blurts out kernel messages... */ - mtd = do_map_probe("cfi_probe", &sa1100_probe_map); - if (mtd) - map_destroy(mtd); - iounmap((void *)sa1100_probe_map.virt); - - if (!mtd) - goto fail; + size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr; - printk("pass\n"); - return; + /* + * Allocate the map_info structs in one go. + */ + info = kmalloc(size, GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto out; + } - fail: - printk("failed\n"); -} + memset(info, 0, size); -static void __init sa1100_probe_flash(void) -{ - printk(KERN_INFO "-- SA11xx Flash probe. Please report results.\n"); - sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS); - sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS); - sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS); - sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS); - sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS); - sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS); - printk(KERN_INFO "-- SA11xx Flash probe complete.\n"); -} + /* + * Claim and then map the memory regions. + */ + for (i = 0; i < nr; i++) { + struct sa_subdev_info *subdev = &info->subdev[i]; + struct resource *res; -static int __init sa1100_locate_flash(void) -{ - int i, nr = -ENODEV; + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + break; - sa1100_probe_flash(); + subdev->map.name = subdev->name; + sprintf(subdev->name, "sa1100-%d", i); + subdev->data = flash; - if (machine_is_adsbitsy()) { - info[0].base = SA1100_CS1_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_assabet()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - info[1].base = SA1100_CS1_PHYS; /* neponset */ - info[1].size = SZ_32M; - nr = 2; - } - if (machine_is_badge4()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_64M; - nr = 1; - } - if (machine_is_cerf()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_consus()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_flexanet()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_freebird()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_frodo()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_graphicsclient()) { - info[0].base = SA1100_CS1_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_graphicsmaster()) { - info[0].base = SA1100_CS1_PHYS; - info[0].size = SZ_16M; - nr = 1; - } - if (machine_is_h3xxx()) { - info[0].set_vpp = h3xxx_set_vpp; - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_huw_webpanel()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_16M; - nr = 1; - } - if (machine_is_itsy()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_jornada720()) { - info[0].set_vpp = jornada720_set_vpp; - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_nanoengine()) { - info[0].base = SA1100_CS0_PHYS; - info[1].size = SZ_32M; - nr = 1; - } - if (machine_is_pangolin()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_64M; - nr = 1; - } - if (machine_is_pfs168()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_pleb()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_4M; - info[1].base = SA1100_CS1_PHYS; - info[1].size = SZ_4M; - nr = 2; - } - if (machine_is_pt_system3()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_16M; - nr = 1; - } - if (machine_is_shannon()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_4M; - nr = 1; - } - if (machine_is_sherman()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_simpad()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_16M; - info[1].base = SA1100_CS1_PHYS; - info[1].size = SZ_16M; - nr = 2; - } - if (machine_is_stork()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; - } - if (machine_is_trizeps()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_16M; - nr = 1; - } - if (machine_is_victor()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_2M; - nr = 1; - } - if (machine_is_yopy()) { - info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_64M; - info[1].base = SA1100_CS1_PHYS; - info[1].size = SZ_64M; - nr = 2; + ret = sa1100_probe_subdev(subdev, res); + if (ret) + break; } - if (nr < 0) - return nr; + info->num_subdev = i; /* - * Retrieve the bankwidth from the MSC registers. - * We currently only implement CS0 and CS1 here. + * ENXIO is special. It means we didn't find a chip when we probed. */ - for (i = 0; i < nr; i++) { - switch (info[i].base) { - default: - printk(KERN_WARNING "SA1100 flash: unknown base address " - "0x%08lx, assuming CS0\n", info[i].base); - case SA1100_CS0_PHYS: - info[i].width = (MSC0 & MSC_RBW) ? 2 : 4; - break; + if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0)) + goto err; - case SA1100_CS1_PHYS: - info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4; - break; - } + /* + * If we found one device, don't bother with concat support. If + * we found multiple devices, use concat if we have it available, + * otherwise fail. Either way, it'll be called "sa1100". + */ + if (info->num_subdev == 1) { + strcpy(info->subdev[0].name, "sa1100"); + info->mtd = info->subdev[0].mtd; + ret = 0; + } else if (info->num_subdev > 1) { +#ifdef CONFIG_MTD_CONCAT + struct mtd_info *cdev[nr]; + /* + * We detected multiple devices. Concatenate them together. + */ + for (i = 0; i < info->num_subdev; i++) + cdev[i] = info->subdev[i].mtd; + + info->mtd = mtd_concat_create(cdev, info->num_subdev, + "sa1100"); + if (info->mtd == NULL) + ret = -ENXIO; +#else + printk(KERN_ERR "SA1100 flash: multiple devices " + "found but MTD concat support disabled.\n"); + ret = -ENXIO; +#endif } - return nr; + if (ret == 0) + return info; + + err: + sa1100_destroy(info); + out: + return ERR_PTR(ret); } -static struct mtd_partition *parsed_parts; -const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; +static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; -static void __init sa1100_locate_partitions(struct mtd_info *mtd) +static int __init sa1100_mtd_probe(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct flash_platform_data *flash = pdev->dev.platform_data; + struct mtd_partition *parts; const char *part_type = NULL; - int nr_parts = 0; + struct sa_info *info; + int err, nr_parts = 0; - do { - /* - * Partition selection stuff. - */ + if (!flash) + return -ENODEV; + + info = sa1100_setup_mtd(pdev, flash); + if (IS_ERR(info)) { + err = PTR_ERR(info); + goto out; + } + + /* + * Partition selection stuff. + */ #ifdef CONFIG_MTD_PARTITIONS - nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0); - if (nr_parts > 0) { - part_type = "dynamic"; - break; - } -#endif -#ifdef CONFIG_MTD_SA1100_STATICMAP - nr_parts = sa1100_static_partitions(&parsed_parts); - if (nr_parts > 0) { - part_type = "static"; - break; - } + nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0); + if (nr_parts > 0) { + info->parts = parts; + part_type = "dynamic"; + } else #endif - } while (0); + { + parts = flash->parts; + nr_parts = flash->nr_parts; + part_type = "static"; + } if (nr_parts == 0) { printk(KERN_NOTICE "SA1100 flash: no partition info " "available, registering whole flash\n"); - add_mtd_device(mtd); + add_mtd_device(info->mtd); } else { printk(KERN_NOTICE "SA1100 flash: using %s partition " "definition\n", part_type); - add_mtd_partitions(mtd, parsed_parts, nr_parts); + add_mtd_partitions(info->mtd, parts, nr_parts); } - /* Always succeeds. */ + dev_set_drvdata(dev, info); + err = 0; + + out: + return err; } -static void __exit sa1100_destroy_partitions(void) +static int __exit sa1100_mtd_remove(struct device *dev) { - if (parsed_parts) - kfree(parsed_parts); + struct sa_info *info = dev_get_drvdata(dev); + dev_set_drvdata(dev, NULL); + sa1100_destroy(info); + return 0; } -static struct mtd_info *mymtd; - -static int __init sa1100_mtd_init(void) +#ifdef CONFIG_PM +static int sa1100_mtd_suspend(struct device *dev, u32 state, u32 level) { - int ret; - int nr; - - nr = sa1100_locate_flash(); - if (nr < 0) - return nr; + struct sa_info *info = dev_get_drvdata(dev); + int ret = 0; - ret = sa1100_setup_mtd(info, nr, &mymtd); - if (ret == 0) - sa1100_locate_partitions(mymtd); + if (info && level == SUSPEND_SAVE_STATE) + ret = info->mtd->suspend(info->mtd); return ret; } -static void __exit sa1100_mtd_cleanup(void) +static int sa1100_mtd_resume(struct device *dev, u32 level) +{ + struct sa_info *info = dev_get_drvdata(dev); + if (info && level == RESUME_RESTORE_STATE) + info->mtd->resume(info->mtd); + return 0; +} +#else +#define sa1100_mtd_suspend NULL +#define sa1100_mtd_resume NULL +#endif + +static struct device_driver sa1100_mtd_driver = { + .name = "flash", + .bus = &platform_bus_type, + .probe = sa1100_mtd_probe, + .remove = __exit_p(sa1100_mtd_remove), + .suspend = sa1100_mtd_suspend, + .resume = sa1100_mtd_resume, +}; + +static int __init sa1100_mtd_init(void) +{ + return driver_register(&sa1100_mtd_driver); +} + +static void __exit sa1100_mtd_exit(void) { - sa1100_destroy_mtd(info, mymtd); - sa1100_destroy_partitions(); + driver_unregister(&sa1100_mtd_driver); } module_init(sa1100_mtd_init); -module_exit(sa1100_mtd_cleanup); +module_exit(sa1100_mtd_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("SA1100 CFI map driver"); diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index 7a9cb1d45..176602839 100644 --- a/drivers/mtd/maps/sbc_gxx.c +++ b/drivers/mtd/maps/sbc_gxx.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: sbc_gxx.c,v 1.29 2004/07/12 22:38:29 dwmw2 Exp $ + $Id: sbc_gxx.c,v 1.32 2004/11/16 18:29:02 dwmw2 Exp $ The SBC-MediaGX / SBC-GXx has up to 16 MiB of Intel StrataFlash (28F320/28F640) in x8 mode. @@ -84,7 +84,7 @@ separate MTD devices. // Globals static volatile int page_in_window = -1; // Current page in window. -static unsigned long iomapadr; +static void __iomem *iomapadr; static spinlock_t sbc_gxx_spin = SPIN_LOCK_UNLOCKED; /* partition_info gives details on the logical partitions that the split the @@ -189,13 +189,13 @@ static void cleanup_sbc_gxx(void) map_destroy( all_mtd ); } - iounmap((void *)iomapadr); + iounmap(iomapadr); release_region(PAGE_IO,PAGE_IO_SIZE); } -int __init init_sbc_gxx(void) +static int __init init_sbc_gxx(void) { - iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); + iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { printk( KERN_ERR"%s: failed to ioremap memory region\n", sbc_gxx_map.name ); @@ -206,7 +206,7 @@ int __init init_sbc_gxx(void) printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", sbc_gxx_map.name, PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); - iounmap((void *)iomapadr); + iounmap(iomapadr); return -EAGAIN; } diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 8269b6029..fc5a5553a 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: sc520cdp.c,v 1.16 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: sc520cdp.c,v 1.18 2004/11/04 13:24:15 gleixner Exp $ * * * The SC520CDP is an evaluation board for the Elan SC520 processor available @@ -186,12 +186,12 @@ static struct sc520_par_table par_table[NUM_FLASH_BANKS] = static void sc520cdp_setup_par(void) { - volatile unsigned long *mmcr; + volatile unsigned long __iomem *mmcr; unsigned long mmcr_val; int i, j; /* map in SC520's MMCR area */ - mmcr = (unsigned long *)ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); + mmcr = ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */ /* force physical address fields to BIOS defaults: */ for(i = 0; i < NUM_FLASH_BANKS; i++) @@ -223,7 +223,7 @@ static void sc520cdp_setup_par(void) sc520cdp_map[i].phys = par_table[i].default_address; } } - iounmap((void *)mmcr); + iounmap(mmcr); } #endif @@ -241,7 +241,7 @@ static int __init init_sc520cdp(void) printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n", sc520cdp_map[i].size, sc520cdp_map[i].phys); - sc520cdp_map[i].virt = (unsigned long)ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); + sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); if (!sc520cdp_map[i].virt) { printk("Failed to ioremap_nocache\n"); @@ -261,7 +261,7 @@ static int __init init_sc520cdp(void) ++devices_found; } else { - iounmap((void *)sc520cdp_map[i].virt); + iounmap(sc520cdp_map[i].virt); } } if(devices_found >= 2) { @@ -290,8 +290,8 @@ static void __exit cleanup_sc520cdp(void) if (mymtd[i]) map_destroy(mymtd[i]); if (sc520cdp_map[i].virt) { - iounmap((void *)sc520cdp_map[i].virt); - sc520cdp_map[i].virt = 0; + iounmap(sc520cdp_map[i].virt); + sc520cdp_map[i].virt = NULL; } } } diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index ff2328dbb..1854cd3a4 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c @@ -1,6 +1,6 @@ /* * MTD map driver for BIOS Flash on Intel SCB2 boards - * $Id: scb2_flash.c,v 1.8 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: scb2_flash.c,v 1.10 2004/11/16 18:29:02 dwmw2 Exp $ * Copyright (C) 2002 Sun Microsystems, Inc. * Tim Hockin * @@ -62,9 +62,9 @@ #define SCB2_WINDOW 0x00100000 -static void *scb2_ioaddr; +static void __iomem *scb2_ioaddr; static struct mtd_info *scb2_mtd; -struct map_info scb2_map = { +static struct map_info scb2_map = { .name = "SCB2 BIOS Flash", .size = 0, .bankwidth = 1, @@ -163,7 +163,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) } scb2_map.phys = SCB2_ADDR; - scb2_map.virt = (unsigned long)scb2_ioaddr; + scb2_map.virt = scb2_ioaddr; scb2_map.size = SCB2_WINDOW; simple_map_init(&scb2_map); diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 58855a15e..d07ddf660 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -2,7 +2,7 @@ Copyright (c) 2001,2002 Christer Weinigel - $Id: scx200_docflash.c,v 1.6 2004/07/12 21:59:45 dwmw2 Exp $ + $Id: scx200_docflash.c,v 1.9 2004/11/16 18:29:02 dwmw2 Exp $ National Semiconductor SCx200 flash mapped with DOCCS */ @@ -81,7 +81,7 @@ static struct map_info scx200_docflash_map = { .name = "NatSemi SCx200 DOCCS Flash", }; -int __init init_scx200_docflash(void) +static int __init init_scx200_docflash(void) { unsigned u; unsigned base; @@ -180,7 +180,7 @@ int __init init_scx200_docflash(void) simple_map_init(&scx200_docflash_map); scx200_docflash_map.phys = docmem.start; - scx200_docflash_map.virt = (unsigned long)ioremap(docmem.start, scx200_docflash_map.size); + scx200_docflash_map.virt = ioremap(docmem.start, scx200_docflash_map.size); if (!scx200_docflash_map.virt) { printk(KERN_ERR NAME ": failed to ioremap the flash\n"); release_resource(&docmem); @@ -190,7 +190,7 @@ int __init init_scx200_docflash(void) mymtd = do_map_probe(flashtype, &scx200_docflash_map); if (!mymtd) { printk(KERN_ERR NAME ": unable to detect flash\n"); - iounmap((void *)scx200_docflash_map.virt); + iounmap(scx200_docflash_map.virt); release_resource(&docmem); return -ENXIO; } @@ -221,7 +221,7 @@ static void __exit cleanup_scx200_docflash(void) map_destroy(mymtd); } if (scx200_docflash_map.virt) { - iounmap((void *)scx200_docflash_map.virt); + iounmap(scx200_docflash_map.virt); release_resource(&docmem); } } diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index 9b2eebe1b..8ce5d8976 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c @@ -1,5 +1,5 @@ /* - * $Id: solutionengine.c,v 1.13 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $ * * Flash and EPROM on Hitachi Solution Engine and similar boards. * @@ -62,9 +62,9 @@ static int __init init_soleng_maps(void) /* First probe at offset 0 */ soleng_flash_map.phys = 0; - soleng_flash_map.virt = P2SEGADDR(0); + soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0); soleng_eprom_map.phys = 0x01000000; - soleng_eprom_map.virt = P1SEGADDR(0x01000000); + soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000); simple_map_init(&soleng_eprom_map); simple_map_init(&soleng_flash_map); diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 2a9932c50..846ddf28a 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -1,4 +1,4 @@ -/* $Id: sun_uflash.c,v 1.9 2004/07/12 21:59:45 dwmw2 Exp $ +/* $Id: sun_uflash.c,v 1.11 2004/11/04 13:24:15 gleixner Exp $ * * sun_uflash - Driver implementation for user-programmable flash * present on many Sun Microsystems SME boardsets. @@ -96,8 +96,7 @@ int uflash_devinit(struct linux_ebus_device* edev) pdev->map.name = pdev->name; } pdev->map.phys = edev->resource[0].start; - pdev->map.virt = - (unsigned long)ioremap_nocache(edev->resource[0].start, pdev->map.size); + pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size); if(0 == pdev->map.virt) { printk("%s: failed to map device\n", __FUNCTION__); kfree(pdev->name); diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 496c9857f..995e9991c 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c @@ -2,7 +2,7 @@ * Handle mapping of the flash memory access routines * on TQM8xxL based devices. * - * $Id: tqm8xxl.c,v 1.11 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: tqm8xxl.c,v 1.13 2004/10/20 22:21:53 dwmw2 Exp $ * * based on rpxlite.c * @@ -50,7 +50,7 @@ static struct mtd_info* mtd_banks[FLASH_BANK_MAX]; static struct map_info* map_banks[FLASH_BANK_MAX]; static struct mtd_part_def part_banks[FLASH_BANK_MAX]; static unsigned long num_banks; -static unsigned long start_scan_addr; +static void __iomem *start_scan_addr; /* * Here are partition information for all known TQM8xxL series devices. @@ -121,7 +121,7 @@ int __init init_tqm_mtd(void) flash_size = bd->bi_flashsize; //request maximum flash size address space - start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); + start_scan_addr = ioremap(flash_addr, flash_size); if (!start_scan_addr) { printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); return -EIO; @@ -231,7 +231,7 @@ error_mem: } } error: - iounmap((void *)start_scan_addr); + iounmap(start_scan_addr); return ret; } @@ -250,7 +250,7 @@ static void __exit cleanup_tqm_mtd(void) } if (start_scan_addr) { - iounmap((void *)start_scan_addr); + iounmap(start_scan_addr); start_scan_addr = 0; } } diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index c5cd70bdb..32ea86024 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -5,7 +5,7 @@ * * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) * - * $Id: uclinux.c,v 1.7 2004/07/12 21:59:45 dwmw2 Exp $ + * $Id: uclinux.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $ */ /****************************************************************************/ @@ -69,8 +69,7 @@ int __init uclinux_mtd_init(void) printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", (int) mapp->map_priv_2, (int) mapp->size); - mapp->virt = (unsigned long) - ioremap_nocache(mapp->phys, mapp->size); + mapp->virt = ioremap_nocache(mapp->phys, mapp->size); if (mapp->virt == 0) { printk("uclinux[mtd]: ioremap_nocache() failed\n"); diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index b7fdece51..82b887b05 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c @@ -1,5 +1,5 @@ /* - * $Id: wr_sbc82xx_flash.c,v 1.5 2004/07/15 14:52:02 dwmw2 Exp $ + * $Id: wr_sbc82xx_flash.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $ * * Map for flash chips on Wind River PowerQUICC II SBC82xx board. * @@ -116,7 +116,7 @@ int __init init_sbc82xx_flash(void) } printk(" at %08lx)\n", sbc82xx_flash_map[i].phys); - sbc82xx_flash_map[i].virt = (unsigned long)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size); + sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size); if (!sbc82xx_flash_map[i].virt) { printk("Failed to ioremap\n"); diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index b134315ab..f8d218581 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.22 2004/07/12 12:35:28 dwmw2 Exp $ + * $Id: mtd_blkdevs.c,v 1.24 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2003 David Woodhouse * @@ -81,7 +81,7 @@ static int mtd_blktrans_thread(void *arg) struct request_queue *rq = tr->blkcore_priv->rq; /* we might get involved when memory gets low, so use PF_MEMALLOC */ - current->flags |= PF_MEMALLOC; + current->flags |= PF_MEMALLOC | PF_NOFREEZE; daemonize("%sd", tr->name); @@ -143,7 +143,7 @@ static void mtd_blktrans_request(struct request_queue *rq) } -int blktrans_open(struct inode *i, struct file *f) +static int blktrans_open(struct inode *i, struct file *f) { struct mtd_blktrans_dev *dev; struct mtd_blktrans_ops *tr; @@ -174,7 +174,7 @@ int blktrans_open(struct inode *i, struct file *f) return ret; } -int blktrans_release(struct inode *i, struct file *f) +static int blktrans_release(struct inode *i, struct file *f) { struct mtd_blktrans_dev *dev; struct mtd_blktrans_ops *tr; @@ -326,7 +326,7 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) return 0; } -void blktrans_notify_remove(struct mtd_info *mtd) +static void blktrans_notify_remove(struct mtd_info *mtd) { struct list_head *this, *this2, *next; @@ -342,7 +342,7 @@ void blktrans_notify_remove(struct mtd_info *mtd) } } -void blktrans_notify_add(struct mtd_info *mtd) +static void blktrans_notify_add(struct mtd_info *mtd) { struct list_head *this; diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index c91d9701e..d6b920786 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -1,7 +1,7 @@ /* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.64 2003/10/04 17:14:14 dwmw2 Exp $ + * $Id: mtdblock.c,v 1.65 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse @@ -361,7 +361,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) kfree(dev); } -struct mtd_blktrans_ops mtdblock_tr = { +static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, @@ -375,7 +375,7 @@ struct mtd_blktrans_ops mtdblock_tr = { .owner = THIS_MODULE, }; -int __init init_mtdblock(void) +static int __init init_mtdblock(void) { return register_mtd_blktrans(&mtdblock_tr); } diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index cdd4ce1df..0c830ba41 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -1,5 +1,5 @@ /* - * $Id: mtdblock_ro.c,v 1.18 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: mtdblock_ro.c,v 1.19 2004/11/16 18:28:59 dwmw2 Exp $ * * (C) 2003 David Woodhouse * @@ -58,7 +58,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) kfree(dev); } -struct mtd_blktrans_ops mtdblock_tr = { +static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 3db73d8c2..fafae6e58 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1,5 +1,5 @@ /* - * $Id: mtdchar.c,v 1.64 2004/08/09 13:59:46 dwmw2 Exp $ + * $Id: mtdchar.c,v 1.65 2004/09/23 23:45:47 gleixner Exp $ * * Character-device access to raw MTD devices. * @@ -179,7 +179,13 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t return -ENOMEM; ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf); - if (!ret) { + /* Nand returns -EBADMSG on ecc errors, but it returns + * the data. For our userspace tools it is important + * to dump areas with ecc errors ! + * Userspace software which accesses NAND this way + * must be aware of the fact that it deals with NAND + */ + if (!ret || (ret == -EBADMSG)) { *ppos += retlen; if (copy_to_user(buf, kbuf, retlen)) { kfree(kbuf); @@ -198,7 +204,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t kfree(kbuf); } - + return total_retlen; } /* mtd_read */ diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 842e7412f..9c0315d1b 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1,5 +1,5 @@ /* - * $Id: mtdcore.c,v 1.43 2004/07/23 15:20:46 dwmw2 Exp $ + * $Id: mtdcore.c,v 1.44 2004/11/16 18:28:59 dwmw2 Exp $ * * Core registration and callback routines for MTD * drivers and users. @@ -382,7 +382,7 @@ done: /*====================================================================*/ /* Init code */ -int __init init_mtd(void) +static int __init init_mtd(void) { #ifdef CONFIG_PROC_FS if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index c3369e0aa..d4547651d 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.50 2004/08/10 16:18:34 dwmw2 Exp $ + * $Id: mtdpart.c,v 1.51 2004/11/16 18:28:59 dwmw2 Exp $ * * 02-21-2002 Thomas Gleixner * added support for read_oob, write_oob @@ -526,7 +526,7 @@ EXPORT_SYMBOL(del_mtd_partitions); static spinlock_t part_parser_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(part_parsers); -struct mtd_part_parser *get_partition_parser(const char *name) +static struct mtd_part_parser *get_partition_parser(const char *name) { struct list_head *this; void *ret = NULL; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index ed085292c..89ab7da16 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/nand/Kconfig -# $Id: Kconfig,v 1.17 2004/08/10 14:24:07 dwmw2 Exp $ +# $Id: Kconfig,v 1.22 2004/10/05 22:11:46 gleixner Exp $ menu "NAND Flash Device Drivers" depends on MTD!=n @@ -36,6 +36,12 @@ config MTD_NAND_EDB7312 This enables the driver for the Cirrus Logic EBD7312 evaluation board to access the onboard NAND Flash. +config MTD_NAND_H1900 + tristate "iPAQ H1900 flash" + depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS + help + This enables the driver for the iPAQ h1900 flash. + config MTD_NAND_SPIA tristate "NAND Flash device on SPIA board" depends on ARM && ARCH_P720T && MTD_NAND @@ -74,15 +80,54 @@ config MTD_NAND_AU1550 This enables the driver for the NAND flash controller on the AMD/Alchemy 1550 SOC. +config MTD_NAND_RTC_FROM4 + tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" + depends on MTD_NAND && SH_SOLUTION_ENGINE + select REED_SOLOMON + select REED_SOLOMON_DEC8 + help + This enables the driver for the Renesas Technology AG-AND + flash interface board (FROM_BOARD4) + config MTD_NAND_PPCHAMELEONEVB tristate "NAND Flash device on PPChameleonEVB board" depends on PPCHAMELEONEVB && MTD_NAND help - This enables the NAND flash driver on the PPChameleon EVB Board. + This enables the NAND flash driver on the PPChameleon EVB Board. + +config MTD_NAND_S3C2410 + tristate "NAND Flash support for S3C2410 SoC" + depends on ARCH_S3C2410 && MTD_NAND + help + This enables the NAND flash controller on the S3C2410. + + No board specfic support is done by this driver, each board + must advertise a platform_device for the driver to attach. + +config MTD_NAND_S3C2410_DEBUG + bool "S3C2410 NAND driver debug" + depends on MTD_NAND_S3C2410 + help + Enable debugging of the S3C2410 NAND driver + +config MTD_NAND_S3C2410_HWECC + bool "S3C2410 NAND Hardware ECC" + depends on MTD_NAND_S3C2410 + help + Enable the use of the S3C2410's internal ECC generator when + using NAND. Early versions of the chip have had problems with + incorrect ECC generation, and if using these, the default of + software ECC is preferable. + + If you lay down a device with the hardware ECC, then you will + currently not be able to switch to software, as there is no + implementation for ECC method used by the S3C2410 config MTD_NAND_DISKONCHIP tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" depends on MTD_NAND && EXPERIMENTAL + select REED_SOLOMON + select REED_SOLOMON_DEC16 help This is a reimplementation of M-Systems DiskOnChip 2000, Millennium and Millennium Plus as a standard NAND device driver, diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index db1939939..a0b6c6052 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/nand/Makefile # -# $Id: Makefile.common,v 1.9 2004/07/12 16:07:31 dwmw2 Exp $ +# $Id: Makefile.common,v 1.13 2004/09/28 22:04:23 bjd Exp $ obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o @@ -14,6 +14,9 @@ obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o +obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o +obj-$(CONFIG_MTD_NAND_H1900) += h1910.o +obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o nand-objs = nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 8e4da6506..4c7719ce3 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Embedded Edge, LLC * - * $Id: au1550nd.c,v 1.5 2004/05/17 07:19:35 ppopov Exp $ + * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,6 +18,17 @@ #include #include #include + +/* fixme: this is ugly */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) +#include +#ifdef CONFIG_MIPS_PB1550 +#include +#endif +#ifdef CONFIG_MIPS_DB1550 +#include +#endif +#else #include #ifdef CONFIG_MIPS_PB1550 #include @@ -25,18 +36,16 @@ #ifdef CONFIG_MIPS_DB1550 #include #endif - +#endif /* * MTD structure for NAND controller */ static struct mtd_info *au1550_mtd = NULL; -static volatile u32 p_nand; -static int nand_width = 1; /* default, only x8 supported for now */ +static void __iomem *p_nand; +static int nand_width = 1; /* default x8*/ -/* Internal buffers. Page buffer and oob buffer for one block*/ -static u_char data_buf[512 + 16]; -static u_char oob_buf[16 * 32]; +#define NAND_CS 1 /* * Define partitions for flash device @@ -70,183 +79,262 @@ const static struct mtd_partition partition_info[] = { #endif }; -static inline void write_cmd_reg(u8 cmd) + +/** + * au_read_byte - read one byte from the chip + * @mtd: MTD device structure + * + * read function for 8bit buswith + */ +static u_char au_read_byte(struct mtd_info *mtd) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_CMD)) = cmd; - else - *((volatile u16 *)(p_nand + MEM_STNAND_CMD)) = cmd; + struct nand_chip *this = mtd->priv; + u_char ret = readb(this->IO_ADDR_R); au_sync(); + return ret; } -static inline void write_addr_reg(u8 addr) +/** + * au_write_byte - write one byte to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * write function for 8it buswith + */ +static void au_write_byte(struct mtd_info *mtd, u_char byte) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_ADDR)) = addr; - else - *((volatile u16 *)(p_nand + MEM_STNAND_ADDR)) = addr; + struct nand_chip *this = mtd->priv; + writeb(byte, this->IO_ADDR_W); au_sync(); } -static inline void write_data_reg(u8 data) +/** + * au_read_byte16 - read one byte endianess aware from the chip + * @mtd: MTD device structure + * + * read function for 16bit buswith with + * endianess conversion + */ +static u_char au_read_byte16(struct mtd_info *mtd) { - if (nand_width) - *((volatile u8 *)(p_nand + MEM_STNAND_DATA)) = data; - else - *((volatile u16 *)(p_nand + MEM_STNAND_DATA)) = data; + struct nand_chip *this = mtd->priv; + u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); au_sync(); + return ret; } -static inline u32 read_data_reg(void) +/** + * au_write_byte16 - write one byte endianess aware to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * write function for 16bit buswith with + * endianess conversion + */ +static void au_write_byte16(struct mtd_info *mtd, u_char byte) { - u32 data; - if (nand_width) { - data = *((volatile u8 *)(p_nand + MEM_STNAND_DATA)); - au_sync(); - } - else { - data = *((volatile u16 *)(p_nand + MEM_STNAND_DATA)); - au_sync(); - } - return data; + struct nand_chip *this = mtd->priv; + writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); + au_sync(); } -void au1550_hwcontrol(struct mtd_info *mtd, int cmd) +/** + * au_read_word - read one word from the chip + * @mtd: MTD device structure + * + * read function for 16bit buswith without + * endianess conversion + */ +static u16 au_read_word(struct mtd_info *mtd) { + struct nand_chip *this = mtd->priv; + u16 ret = readw(this->IO_ADDR_R); + au_sync(); + return ret; } -int au1550_device_ready(struct mtd_info *mtd) +/** + * au_write_word - write one word to the chip + * @mtd: MTD device structure + * @word: data word to write + * + * write function for 16bit buswith without + * endianess conversion + */ +static void au_write_word(struct mtd_info *mtd, u16 word) { - int ready; - ready = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0; - return ready; + struct nand_chip *this = mtd->priv; + writew(word, this->IO_ADDR_W); + au_sync(); } -static u_char au1550_nand_read_byte(struct mtd_info *mtd) +/** + * au_write_buf - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + * + * write function for 8bit buswith + */ +static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { - u_char ret; - ret = read_data_reg(); - return ret; -} + int i; + struct nand_chip *this = mtd->priv; -static void au1550_nand_write_byte(struct mtd_info *mtd, u_char byte) -{ - write_data_reg((u8)byte); + for (i=0; iIO_ADDR_W); + au_sync(); + } } -static void -au1550_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +/** + * au_read_buf - read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + * + * read function for 8bit buswith + */ +static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) { int i; + struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_R); + au_sync(); + } } -static void -au1550_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +/** + * au_verify_buf - Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * verify function for 8bit buswith + */ +static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) { int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_R)) + return -EFAULT; + au_sync(); + } - for (i=0; ipriv; + u16 *p = (u16 *) buf; + len >>= 1; + + for (i=0; iIO_ADDR_W); + au_sync(); + } + +} - for (i=0; ipriv; + u16 *p = (u16 *) buf; + len >>= 1; - return 0; + for (i=0; iIO_ADDR_R); + au_sync(); + } } -static void au1550_nand_select_chip(struct mtd_info *mtd, int chip) +/** + * au_verify_buf16 - Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * verify function for 16bit buswith + */ +static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) { - switch(chip) { - case -1: - /* deassert chip enable */ - au_writel(au_readl(MEM_STNDCTL) & ~0x20 , MEM_STNDCTL); - break; - case 0: - /* assert (force assert) chip enable */ - au_writel(au_readl(MEM_STNDCTL) | 0x20 , MEM_STNDCTL); - break; + int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; - default: - BUG(); + for (i=0; iIO_ADDR_R)) + return -EFAULT; + au_sync(); } + return 0; } -static void au1550_nand_command (struct mtd_info *mtd, unsigned command, - int column, int page_addr) + +static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { register struct nand_chip *this = mtd->priv; - /* - * Write out the command to the device. - */ - if (command == NAND_CMD_SEQIN) { - int readcmd; - - if (column >= mtd->oobblock) { - /* OOB area */ - column -= mtd->oobblock; - readcmd = NAND_CMD_READOOB; - } else if (column < 256) { - /* First 256 bytes --> READ0 */ - readcmd = NAND_CMD_READ0; - } else { - column -= 256; - readcmd = NAND_CMD_READ1; - } - write_cmd_reg(readcmd); - } - write_cmd_reg(command); - - if (column != -1 || page_addr != -1) { - - /* Serially input address */ - if (column != -1) - write_addr_reg(column); - if (page_addr != -1) { - write_addr_reg((unsigned char) (page_addr & 0xff)); - write_addr_reg(((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (mtd->size & 0x0c000000) - write_addr_reg((unsigned char) ((page_addr >> 16) & 0x0f)); - } - } - - switch (command) { - - case NAND_CMD_PAGEPROG: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - case NAND_CMD_SEQIN: - case NAND_CMD_STATUS: + switch(cmd){ + + case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break; + case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; + + case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + /* FIXME: Nobody knows why this is neccecary, + * but it works only that way */ + udelay(1); break; - case NAND_CMD_RESET: - if (this->dev_ready) - break; - udelay(this->chip_delay); - write_cmd_reg(NAND_CMD_STATUS); - while ( !(read_data_reg() & 0x40)); - return; - - /* This applies to read commands */ - default: - udelay (this->chip_delay); + case NAND_CTL_SETNCE: + /* assert (force assert) chip enable */ + au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; + break; + + case NAND_CTL_CLRNCE: + /* deassert chip enable */ + au_writel(0, MEM_STNDCTL); break; + break; } + + this->IO_ADDR_R = this->IO_ADDR_W; - /* wait until command is processed */ - while (!this->dev_ready(mtd)); + /* Drain the writebuffer */ + au_sync(); } +int au1550_device_ready(struct mtd_info *mtd) +{ + int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0; + au_sync(); + return ret; +} /* * Main initialization routine @@ -255,7 +343,7 @@ int __init au1550_init (void) { struct nand_chip *this; u16 boot_swapboot = 0; /* default value */ - u32 mem_time; + int retval; /* Allocate memory for MTD device structure and private data */ au1550_mtd = kmalloc (sizeof(struct mtd_info) + @@ -275,11 +363,9 @@ int __init au1550_init (void) /* Link the private data with the MTD structure */ au1550_mtd->priv = this; - /* disable interrupts */ - au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); - /* disable NAND boot */ - au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); + /* MEM_STNDCTL: disable ints, disable nand boot */ + au_writel(0, MEM_STNDCTL); #ifdef CONFIG_MIPS_PB1550 /* set gpio206 high */ @@ -295,7 +381,6 @@ int __init au1550_init (void) case 0xD: /* x16 NAND Flash */ nand_width = 0; - printk("Pb1550 NAND: 16-bit NAND not supported by MTD\n"); break; case 1: case 9: @@ -307,62 +392,62 @@ int __init au1550_init (void) break; default: printk("Pb1550 NAND: bad boot:swap\n"); - kfree(au1550_mtd); - return 1; + retval = -EINVAL; + goto outmem; } +#endif /* Configure RCE1 - should be done by YAMON */ - au_writel(0x5 | (nand_width << 22), MEM_STCFG1); - au_writel(NAND_TIMING, MEM_STTIME1); - mem_time = au_readl(MEM_STTIME1); + au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */ + au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */ au_sync(); - /* setup and enable chip select */ + /* setup and enable chip select, MEM_STADDR1 */ /* we really need to decode offsets only up till 0x20 */ au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), MEM_STADDR1); au_sync(); -#endif -#ifdef CONFIG_MIPS_DB1550 - /* Configure RCE1 - should be done by YAMON */ - au_writel(0x00400005, MEM_STCFG1); - au_writel(0x00007774, MEM_STTIME1); - au_writel(0x12000FFF, MEM_STADDR1); -#endif - - p_nand = (volatile struct nand_regs *)ioremap(NAND_PHYS_ADDR, 0x1000); + p_nand = ioremap(NAND_PHYS_ADDR, 0x1000); /* Set address of hardware control function */ this->hwcontrol = au1550_hwcontrol; this->dev_ready = au1550_device_ready; /* 30 us command delay time */ this->chip_delay = 30; - - this->cmdfunc = au1550_nand_command; - this->select_chip = au1550_nand_select_chip; - this->write_byte = au1550_nand_write_byte; - this->read_byte = au1550_nand_read_byte; - this->write_buf = au1550_nand_write_buf; - this->read_buf = au1550_nand_read_buf; - this->verify_buf = au1550_nand_verify_buf; this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf; - this->oob_buf = oob_buf; + this->options = NAND_NO_AUTOINCR; + + if (!nand_width) + this->options |= NAND_BUSWIDTH_16; + + this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte; + this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; + this->write_word = au_write_word; + this->read_word = au_read_word; + this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf; + this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf; + this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; /* Scan to find existence of the device */ if (nand_scan (au1550_mtd, 1)) { - kfree (au1550_mtd); - return -ENXIO; + retval = -ENXIO; + goto outio; } /* Register the partitions */ add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS); return 0; + + outio: + iounmap ((void *)p_nand); + + outmem: + kfree (au1550_mtd); + return retval; } module_init(au1550_init); @@ -375,16 +460,14 @@ static void __exit au1550_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1]; - iounmap ((void *)p_nand); - - /* Unregister partitions */ - del_mtd_partitions(au1550_mtd); - - /* Unregister the device */ - del_mtd_device (au1550_mtd); + /* Release resources, unregister device */ + nand_release (au1550_mtd); /* Free the MTD device structure */ kfree (au1550_mtd); + + /* Unmap */ + iounmap ((void *)p_nand); } module_exit(au1550_cleanup); #endif diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 33779a8da..4afa8ced0 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * - * $Id: autcpu12.c,v 1.20 2004/07/20 02:44:26 dwmw2 Exp $ + * $Id: autcpu12.c,v 1.22 2004/11/04 12:53:10 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -48,17 +48,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE; static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET; -static int autcpu12_fio_base; - -#ifdef MODULE -MODULE_PARM(autcpu12_fio_pbase, "i"); -MODULE_PARM(autcpu12_fio_ctrl, "i"); -MODULE_PARM(autcpu12_pedr, "i"); - -__setup("autcpu12_fio_pbase=",autcpu12_fio_pbase); -__setup("autcpu12_fio_ctrl=",autcpu12_fio_ctrl); -__setup("autcpu12_pedr=",autcpu12_pedr); -#endif +static void __iomem * autcpu12_fio_base; /* * Define partitions for flash devices @@ -150,7 +140,7 @@ int __init autcpu12_init (void) } /* map physical adress */ - autcpu12_fio_base=(unsigned long)ioremap(autcpu12_fio_pbase,SZ_1K); + autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K); if(!autcpu12_fio_base){ printk("Ioremap autcpu12 SmartMedia Card failed\n"); err = -EIO; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 0f7dedd6b..f2116fa8e 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -8,16 +8,22 @@ * Author: David Woodhouse * Additional Diskonchip 2000 and Millennium support by Dan Brown * Diskonchip Millennium Plus support by Kalev Lember - * + * + * Error correction code lifted from the old docecc code + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * converted to the generic Reed-Solomon library by Thomas Gleixner + * * Interface to generic NAND code for M-Systems DiskOnChip devices * - * $Id: diskonchip.c,v 1.34 2004/08/09 19:41:12 dbrown Exp $ + * $Id: diskonchip.c,v 1.42 2004/11/16 18:29:03 dwmw2 Exp $ */ #include #include #include #include +#include #include #include @@ -62,7 +68,7 @@ static unsigned long __initdata doc_locations[] = { static struct mtd_info *doclist = NULL; struct doc_priv { - unsigned long virtadr; + void __iomem *virtadr; unsigned long physadr; u_char ChipID; u_char CDSNControl; @@ -96,28 +102,136 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); static void doc200x_select_chip(struct mtd_info *mtd, int chip); static int debug=0; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); static int try_dword=1; -MODULE_PARM(try_dword, "i"); +module_param(try_dword, int, 0); static int no_ecc_failures=0; -MODULE_PARM(no_ecc_failures, "i"); +module_param(no_ecc_failures, int, 0); +#ifdef CONFIG_MTD_PARTITIONS static int no_autopart=0; -MODULE_PARM(no_autopart, "i"); +module_param(no_autopart, int, 0); +#endif #ifdef MTD_NAND_DISKONCHIP_BBTWRITE static int inftl_bbt_write=1; #else static int inftl_bbt_write=0; #endif -MODULE_PARM(inftl_bbt_write, "i"); +module_param(inftl_bbt_write, int, 0); static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; -MODULE_PARM(doc_config_location, "l"); +module_param(doc_config_location, ulong, 0); MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); + +/* Sector size for HW ECC */ +#define SECTOR_SIZE 512 +/* The sector bytes are packed into NB_DATA 10 bit words */ +#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10) +/* Number of roots */ +#define NROOTS 4 +/* First consective root */ +#define FCR 510 +/* Number of symbols */ +#define NN 1023 + +/* the Reed Solomon control structure */ +static struct rs_control *rs_decoder; + +/* + * The HW decoder in the DoC ASIC's provides us a error syndrome, + * which we must convert to a standard syndrom usable by the generic + * Reed-Solomon library code. + * + * Fabrice Bellard figured this out in the old docecc code. I added + * some comments, improved a minor bit and converted it to make use + * of the generic Reed-Solomon libary. tglx + */ +static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) +{ + int i, j, nerr, errpos[8]; + uint8_t parity; + uint16_t ds[4], s[5], tmp, errval[8], syn[4]; + + /* Convert the ecc bytes into words */ + ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); + ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); + ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4); + ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); + parity = ecc[1]; + + /* Initialize the syndrom buffer */ + for (i = 0; i < NROOTS; i++) + s[i] = ds[0]; + /* + * Evaluate + * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] + * where x = alpha^(FCR + i) + */ + for(j = 1; j < NROOTS; j++) { + if(ds[j] == 0) + continue; + tmp = rs->index_of[ds[j]]; + for(i = 0; i < NROOTS; i++) + s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; + } + + /* Calc s[i] = s[i] / alpha^(v + i) */ + for (i = 0; i < NROOTS; i++) { + if (syn[i]) + syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); + } + /* Call the decoder library */ + nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); + + /* Incorrectable errors ? */ + if (nerr < 0) + return nerr; + + /* + * Correct the errors. The bitpositions are a bit of magic, + * but they are given by the design of the de/encoder circuit + * in the DoC ASIC's. + */ + for(i = 0;i < nerr; i++) { + int index, bitpos, pos = 1015 - errpos[i]; + uint8_t val; + if (pos >= NB_DATA && pos < 1019) + continue; + if (pos < NB_DATA) { + /* extract bit position (MSB first) */ + pos = 10 * (NB_DATA - 1 - pos) - 6; + /* now correct the following 10 bits. At most two bytes + can be modified since pos is even */ + index = (pos >> 3) ^ 1; + bitpos = pos & 7; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t) (errval[i] >> (2 + bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + index = ((pos >> 3) + 1) ^ 1; + bitpos = (bitpos + 10) & 7; + if (bitpos == 0) + bitpos = 8; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t)(errval[i] << (8 - bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + } + } + /* If the parity is wrong, no rescue possible */ + return parity ? -1 : nerr; +} + static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) { volatile char dummy; @@ -139,7 +253,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ static int _DoC_WaitReady(struct doc_priv *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; unsigned long timeo = jiffies + (HZ * 10); if(debug) printk("_DoC_WaitReady...\n"); @@ -169,7 +283,7 @@ static int _DoC_WaitReady(struct doc_priv *doc) static inline int DoC_WaitReady(struct doc_priv *doc) { - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int ret = 0; if (DoC_is_MillenniumPlus(doc)) { @@ -195,7 +309,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if(debug)printk("write_byte %02x\n", datum); WriteDOC(datum, docptr, CDSNSlowIO); @@ -206,7 +320,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, CDSNSlowIO); @@ -221,7 +335,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("writebuf of %d bytes: ", len); for (i=0; i < len; i++) { @@ -237,7 +351,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("readbuf of %d bytes: ", len); @@ -252,7 +366,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug) printk("readbuf_dword of %d bytes: ", len); @@ -273,7 +387,7 @@ static int doc2000_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; for (i=0; i < len; i++) @@ -305,7 +419,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) uint32_t dword; uint8_t byte[4]; } ident; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); doc2000_write_byte(mtd, NAND_CMD_READID); @@ -364,7 +478,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, Mil_CDSN_IO); @@ -375,7 +489,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; //ReadDOC(docptr, CDSNSlowIO); /* 11.4.5 -- delay twice to allow extended length cycle */ @@ -390,7 +504,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; for (i=0; i < len; i++) @@ -404,7 +518,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ @@ -422,7 +536,7 @@ static int doc2001_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ @@ -442,7 +556,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, Mplus_ReadPipeInit); @@ -457,7 +571,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("writebuf of %d bytes: ", len); @@ -474,7 +588,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("readbuf of %d bytes: ", len); @@ -504,7 +618,7 @@ static int doc2001plus_verifybuf(struct mtd_info *mtd, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; if (debug)printk("verifybuf of %d bytes: ", len); @@ -530,7 +644,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); @@ -556,7 +670,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; if(debug)printk("select chip (%d)\n", chip); @@ -583,7 +697,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; switch(cmd) { case NAND_CTL_SETNCE: @@ -621,7 +735,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* * Must terminate write pipeline before sending any commands @@ -725,7 +839,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if (DoC_is_MillenniumPlus(doc)) { /* 11.4.2 -- must NOP four times before checking FR/B# */ @@ -763,7 +877,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ switch(mode) { @@ -782,7 +896,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ switch(mode) { @@ -803,7 +917,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, { struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; int emptymatch = 1; @@ -861,7 +975,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ int i, ret = 0; struct nand_chip *this = mtd->priv; struct doc_priv *doc = (void *)this->priv; - unsigned long docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; volatile u_char dummy; int emptymatch = 1; @@ -914,7 +1028,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ erased block, in which case the ECC will not come out right. We'll suppress the error and tell the caller everything's OK. Because it is. */ - if (!emptymatch) ret = doc_decode_ecc (dat, calc_ecc); + if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); } @@ -1385,13 +1499,13 @@ static inline int __init doc_probe(unsigned long physadr) struct mtd_info *mtd; struct nand_chip *nand; struct doc_priv *doc; - unsigned long virtadr; + void __iomem *virtadr; unsigned char save_control; unsigned char tmp, tmpb, tmpc; int reg, len, numchips; int ret = 0; - virtadr = (unsigned long)ioremap(physadr, DOC_IOREMAP_LEN); + virtadr = ioremap(physadr, DOC_IOREMAP_LEN); if (!virtadr) { printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); return -EIO; @@ -1518,7 +1632,7 @@ static inline int __init doc_probe(unsigned long physadr) sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); - mtd = kmalloc(len, GFP_KERNEL); + mtd = kmalloc(len, GFP_KERNEL); if (!mtd) { printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; @@ -1543,7 +1657,7 @@ static inline int __init doc_probe(unsigned long physadr) nand->enable_hwecc = doc200x_enable_hwecc; nand->calculate_ecc = doc200x_calculate_ecc; nand->correct_data = doc200x_correct_data; - //nand->data_buf + nand->autooob = &doc200x_oobinfo; nand->eccmode = NAND_ECC_HW6_512; nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; @@ -1589,13 +1703,47 @@ fail: return ret; } -int __init init_nanddoc(void) +static void release_nanddoc(void) { - int i; + struct mtd_info *mtd, *nextmtd; + struct nand_chip *nand; + struct doc_priv *doc; + + for (mtd = doclist; mtd; mtd = nextmtd) { + nand = mtd->priv; + doc = (void *)nand->priv; + + nextmtd = doc->nextdoc; + nand_release(mtd); + iounmap((void *)doc->virtadr); + kfree(mtd); + } +} + +static int __init init_nanddoc(void) +{ + int i, ret = 0; + + /* We could create the decoder on demand, if memory is a concern. + * This way we have it handy, if an error happens + * + * Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * first consecutive root is 510 + * primitve element to generate roots = 1 + * generator polinomial degree = 4 + */ + rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); + if (!rs_decoder) { + printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); + return -ENOMEM; + } if (doc_config_location) { printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); - return doc_probe(doc_config_location); + ret = doc_probe(doc_config_location); + if (ret < 0) + goto outerr; } else { for (i=0; (doc_locations[i] != 0xffffffff); i++) { doc_probe(doc_locations[i]); @@ -1605,25 +1753,23 @@ int __init init_nanddoc(void) found, so the user knows we at least tried. */ if (!doclist) { printk(KERN_INFO "No valid DiskOnChip devices found\n"); - return -ENODEV; + ret = -ENODEV; + goto outerr; } return 0; +outerr: + free_rs(rs_decoder); + return ret; } -void __exit cleanup_nanddoc(void) +static void __exit cleanup_nanddoc(void) { - struct mtd_info *mtd, *nextmtd; - struct nand_chip *nand; - struct doc_priv *doc; + /* Cleanup the nand/DoC resources */ + release_nanddoc(); - for (mtd = doclist; mtd; mtd = nextmtd) { - nand = mtd->priv; - doc = (void *)nand->priv; - - nextmtd = doc->nextdoc; - nand_release(mtd); - iounmap((void *)doc->virtadr); - kfree(mtd); + /* Free the reed solomon resources */ + if (rs_decoder) { + free_rs(rs_decoder); } } diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 797794069..5549681cc 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: edb7312.c,v 1.8 2004/07/12 15:03:26 dwmw2 Exp $ + * $Id: edb7312.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -53,19 +53,9 @@ static struct mtd_info *ep7312_mtd = NULL; * Module stuff */ -static int ep7312_fio_pbase = EP7312_FIO_PBASE; -static int ep7312_pxdr = EP7312_PXDR; -static int ep7312_pxddr = EP7312_PXDDR; - -#ifdef MODULE -MODULE_PARM(ep7312_fio_pbase, "i"); -MODULE_PARM(ep7312_pxdr, "i"); -MODULE_PARM(ep7312_pxddr, "i"); - -__setup("ep7312_fio_pbase=",ep7312_fio_pbase); -__setup("ep7312_pxdr=",ep7312_pxdr); -__setup("ep7312_pxddr=",ep7312_pxddr); -#endif +static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; +static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR; +static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR; #ifdef CONFIG_MTD_PARTITIONS /* @@ -131,7 +121,7 @@ static int __init ep7312_init (void) const char *part_type = 0; int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; - int ep7312_fio_base; + void __iomem * ep7312_fio_base; /* Allocate memory for MTD device structure and private data */ ep7312_mtd = kmalloc(sizeof(struct mtd_info) + @@ -143,7 +133,7 @@ static int __init ep7312_init (void) } /* map physical adress */ - ep7312_fio_base = (unsigned long)ioremap(ep7312_fio_pbase, SZ_1K); + ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); if(!ep7312_fio_base) { printk("ioremap EDB7312 NAND flash failed\n"); kfree(ep7312_mtd); @@ -181,16 +171,7 @@ static int __init ep7312_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (ep7312_mtd->oobblock + ep7312_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk("Unable to allocate NAND data buffer for EDB7312.\n"); - iounmap((void *)ep7312_fio_base); - kfree (ep7312_mtd); - return -ENOMEM; - } - -#ifdef CONFIG_PARTITIONS +#ifdef CONFIG_MTD_PARTITIONS ep7312_mtd->name = "edb7312-nand"; mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); @@ -221,8 +202,8 @@ static void __exit ep7312_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; - /* Unregister the device */ - del_mtd_device (ep7312_mtd); + /* Release resources, unregister device */ + nand_release (ap7312_mtd); /* Free internal data buffer */ kfree (this->data_buf); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ff6adf43f..181b95275 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -24,6 +24,10 @@ * * 05-19-2004 tglx: Basic support for Renesas AG-AND chips * + * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared + * among multiple independend devices. Suggestions and initial patch + * from Ben Dooks + * * Credits: * David Woodhouse for adding multichip support * @@ -37,7 +41,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.115 2004/08/09 13:19:45 dwmw2 Exp $ + * $Id: nand_base.c,v 1.121 2004/10/06 19:53:11 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -131,25 +135,31 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int #define nand_verify_pages(...) (0) #endif -static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state); +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** - * nand_release_chip - [GENERIC] release chip + * nand_release_device - [GENERIC] release chip * @mtd: MTD device structure * * Deselect, release chip lock and wake up anyone waiting on the device */ -static void nand_release_chip (struct mtd_info *mtd) +static void nand_release_device (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; /* De-select the NAND device */ this->select_chip(mtd, -1); + /* Do we have a hardware controller ? */ + if (this->controller) { + spin_lock(&this->controller->lock); + this->controller->active = NULL; + spin_unlock(&this->controller->lock); + } /* Release the chip */ - spin_lock_bh (&this->chip_lock); + spin_lock (&this->chip_lock); this->state = FL_READY; wake_up (&this->wq); - spin_unlock_bh (&this->chip_lock); + spin_unlock (&this->chip_lock); } /** @@ -388,7 +398,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) chipnr = (int)(ofs >> this->chip_shift); /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_READING); + nand_get_device (this, mtd, FL_READING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -410,7 +420,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) if (getchip) { /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); } return res; @@ -533,8 +543,8 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in if (page_addr != -1) { this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); - /* One more address cycle for higher density devices */ - if (this->chipsize & 0x0c000000) + /* One more address cycle for devices > 32MiB */ + if (this->chipsize > (32 << 20)) this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); } /* Latch in address */ @@ -689,15 +699,16 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, } /** - * nand_get_chip - [GENERIC] Get chip for selected access + * nand_get_device - [GENERIC] Get chip for selected access * @this: the nand chip descriptor * @mtd: MTD device structure * @new_state: the state which is requested * * Get the device and lock it for exclusive access */ -static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) { + struct nand_chip *active = this; DECLARE_WAITQUEUE (wait, current); @@ -705,19 +716,29 @@ static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new * Grab the lock and see if the device is available */ retry: - spin_lock_bh (&this->chip_lock); - - if (this->state == FL_READY) { - this->state = new_state; - spin_unlock_bh (&this->chip_lock); - return; + /* Hardware controller shared among independend devices */ + if (this->controller) { + spin_lock (&this->controller->lock); + if (this->controller->active) + active = this->controller->active; + else + this->controller->active = this; + spin_unlock (&this->controller->lock); } - + + if (active == this) { + spin_lock (&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock (&this->chip_lock); + return; + } + } set_current_state (TASK_UNINTERRUPTIBLE); - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); + add_wait_queue (&active->wq, &wait); + spin_unlock (&active->chip_lock); schedule (); - remove_wait_queue (&this->wq, &wait); + remove_wait_queue (&active->wq, &wait); goto retry; } @@ -747,7 +768,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) * any case on any machine. */ ndelay (100); - spin_lock_bh (&this->chip_lock); if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); else @@ -755,24 +775,19 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) while (time_before(jiffies, timeo)) { /* Check, if we were interrupted */ - if (this->state != state) { - spin_unlock_bh (&this->chip_lock); + if (this->state != state) return 0; - } + if (this->dev_ready) { if (this->dev_ready(mtd)) + break; + } else { + if (this->read_byte(mtd) & NAND_STATUS_READY) break; } - if (this->read_byte(mtd) & NAND_STATUS_READY) - break; - - spin_unlock_bh (&this->chip_lock); yield (); - spin_lock_bh (&this->chip_lock); } status = (int) this->read_byte(mtd); - spin_unlock_bh (&this->chip_lock); - return status; } @@ -1051,7 +1066,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd ,FL_READING); + nand_get_device (this, mtd ,FL_READING); /* use userspace supplied oobinfo, if zero */ if (oobsel == NULL) @@ -1281,7 +1296,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* * Return success, if no ECC failures, else -EBADMSG @@ -1328,7 +1343,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd , FL_READING); + nand_get_device (this, mtd , FL_READING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -1379,7 +1394,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* Return happy */ *retlen = len; @@ -1413,7 +1428,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd , FL_READING); + nand_get_device (this, mtd , FL_READING); this->select_chip (mtd, chip); @@ -1442,7 +1457,7 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, } /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return 0; } @@ -1564,7 +1579,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Calculate chipnr */ chipnr = (int)(to >> this->chip_shift); @@ -1669,7 +1684,7 @@ cmp: out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return ret; } @@ -1709,7 +1724,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Select the NAND device */ this->select_chip(mtd, chipnr); @@ -1771,7 +1786,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret = 0; out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); return ret; } @@ -1838,7 +1853,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig } /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_WRITING); + nand_get_device (this, mtd, FL_WRITING); /* Get the current chip-nr */ chipnr = (int) (to >> this->chip_shift); @@ -1952,7 +1967,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig ret = 0; out: /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); *retlen = written; return ret; @@ -2041,7 +2056,7 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb instr->fail_addr = 0xffffffff; /* Grab the lock and see if the device is available */ - nand_get_chip (this, mtd, FL_ERASING); + nand_get_device (this, mtd, FL_ERASING); /* Shift to get first page */ page = (int) (instr->addr >> this->page_shift); @@ -2112,7 +2127,7 @@ erase_exit: mtd_erase_callback(instr); /* Deselect and wake up anyone waiting on the device */ - nand_release_chip(mtd); + nand_release_device(mtd); /* Return more or less happy */ return ret; @@ -2127,43 +2142,13 @@ erase_exit: static void nand_sync (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; - DECLARE_WAITQUEUE (wait, current); DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); -retry: - /* Grab the spinlock */ - spin_lock_bh (&this->chip_lock); - - /* See what's going on */ - switch (this->state) { - case FL_READY: - case FL_SYNCING: - this->state = FL_SYNCING; - spin_unlock_bh (&this->chip_lock); - break; - - default: - /* Not an idle state */ - add_wait_queue (&this->wq, &wait); - spin_unlock_bh (&this->chip_lock); - schedule (); - - remove_wait_queue (&this->wq, &wait); - goto retry; - } - - /* Lock the device */ - spin_lock_bh (&this->chip_lock); - - /* Set the device to be ready again */ - if (this->state == FL_SYNCING) { - this->state = FL_READY; - wake_up (&this->wq); - } - - /* Unlock the device */ - spin_unlock_bh (&this->chip_lock); + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_SYNCING); + /* Release it and go back */ + nand_release_device (mtd); } diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 2642e1151..77f08d1ee 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -6,7 +6,7 @@ * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * - * $Id: nand_bbt.c,v 1.24 2004/06/28 08:25:35 gleixner Exp $ + * $Id: nand_bbt.c,v 1.26 2004/10/05 13:50:20 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -114,6 +114,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des * @num: the number of bbt descriptors to read * @bits: number of bits per block * @offs: offset in the memory table + * @reserved_block_code: Pattern to identify reserved blocks * * Read the bad block table starting from page. * @@ -796,7 +797,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) len = mtd->size >> (this->bbt_erase_shift + 2); /* Allocate memory (2bit per block) */ - this->bbt = (uint8_t *) kmalloc (len, GFP_KERNEL); + this->bbt = kmalloc (len, GFP_KERNEL); if (!this->bbt) { printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); return -ENOMEM; diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index 9c356a0a7..e510a83d7 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/edb7312.c * * - * $Id: ppchameleonevb.c,v 1.2 2004/05/05 22:09:54 gleixner Exp $ + * $Id: ppchameleonevb.c,v 1.6 2004/11/05 16:07:16 kalev Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -64,22 +64,17 @@ static struct mtd_info *ppchameleonevb_mtd = NULL; /* * Module stuff */ -static int ppchameleon_fio_pbase = CFG_NAND0_PADDR; -static int ppchameleonevb_fio_pbase = CFG_NAND1_PADDR; +static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR; +static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR; #ifdef MODULE -MODULE_PARM(ppchameleon_fio_pbase, "i"); +module_param(ppchameleon_fio_pbase, ulong, 0); +module_param(ppchameleonevb_fio_pbase, ulong, 0); +#else __setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase); -MODULE_PARM(ppchameleonevb_fio_pbase, "i"); __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); #endif -/* Internal buffers. Page buffer and oob buffer for one block */ -static u_char data_buf[2048 + 64]; -static u_char oob_buf[64 * 64]; -static u_char data_buf_evb[512 + 16]; -static u_char oob_buf_evb[16 * 32]; - #ifdef CONFIG_MTD_PARTITIONS /* * Define static partitions for flash devices @@ -196,8 +191,8 @@ static int __init ppchameleonevb_init (void) const char *part_type = 0; int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; - int ppchameleon_fio_base; - int ppchameleonevb_fio_base; + void __iomem *ppchameleon_fio_base; + void __iomem *ppchameleonevb_fio_base; /********************************* @@ -205,15 +200,14 @@ static int __init ppchameleonevb_init (void) *********************************/ /* Allocate memory for MTD device structure and private data */ ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleon_mtd) { printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); return -ENOMEM; } /* map physical address */ - ppchameleon_fio_base = (unsigned long)ioremap(ppchameleon_fio_pbase, SZ_4M); + ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M); if(!ppchameleon_fio_base) { printk("ioremap PPChameleon NAND flash failed\n"); kfree(ppchameleon_mtd); @@ -264,10 +258,6 @@ static int __init ppchameleonevb_init (void) /* ECC mode */ this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf; - this->oob_buf = oob_buf; - /* Scan to find existence of the device (it could not be mounted) */ if (nand_scan (ppchameleon_mtd, 1)) { iounmap((void *)ppchameleon_fio_base); @@ -309,15 +299,14 @@ nand_evb_init: ****************************/ /* Allocate memory for MTD device structure and private data */ ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleonevb_mtd) { printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); return -ENOMEM; } /* map physical address */ - ppchameleonevb_fio_base = (unsigned long)ioremap(ppchameleonevb_fio_pbase, SZ_4M); + ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M); if(!ppchameleonevb_fio_base) { printk("ioremap PPChameleonEVB NAND flash failed\n"); kfree(ppchameleonevb_mtd); @@ -349,7 +338,8 @@ nand_evb_init: out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); /* enable output driver */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | + NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); #ifdef USE_READY_BUSY_PIN /* three-state select */ out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC); @@ -359,7 +349,6 @@ nand_evb_init: out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); #endif - /* insert callbacks */ this->IO_ADDR_R = ppchameleonevb_fio_base; this->IO_ADDR_W = ppchameleonevb_fio_base; @@ -372,10 +361,6 @@ nand_evb_init: /* ECC mode */ this->eccmode = NAND_ECC_SOFT; - /* Set internal data buffer */ - this->data_buf = data_buf_evb; - this->oob_buf = oob_buf_evb; - /* Scan to find existence of the device */ if (nand_scan (ppchameleonevb_mtd, 1)) { iounmap((void *)ppchameleonevb_fio_base); @@ -412,15 +397,20 @@ module_init(ppchameleonevb_init); */ static void __exit ppchameleonevb_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &ppchameleonevb_mtd[1]; - - /* Unregister the device */ - del_mtd_device (ppchameleonevb_mtd); + struct nand_chip *this; - /* Free internal data buffer */ - kfree (this->data_buf); + /* Release resources, unregister device(s) */ + nand_release (ppchameleon_mtd); + nand_release (ppchameleonevb_mtd); + + /* Release iomaps */ + this = (struct nand_chip *) &ppchameleon_mtd[1]; + iounmap((void *) this->IO_ADDR_R; + this = (struct nand_chip *) &ppchameleonevb_mtd[1]; + iounmap((void *) this->IO_ADDR_R; /* Free the MTD device structure */ + kfree (ppchameleon_mtd); kfree (ppchameleonevb_mtd); } module_exit(ppchameleonevb_cleanup); diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index acf6fc808..b777c412b 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c @@ -8,7 +8,7 @@ * to controllines (due to change in nand.c) * page_cache added * - * $Id: spia.c,v 1.21 2003/07/11 15:12:29 dwmw2 Exp $ + * $Id: spia.c,v 1.24 2004/11/04 12:53:10 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -59,10 +59,10 @@ static int spia_fio_base = SPIA_FIO_BASE; static int spia_pedr = SPIA_PEDR; static int spia_peddr = SPIA_PEDDR; -MODULE_PARM(spia_io_base, "i"); -MODULE_PARM(spia_fio_base, "i"); -MODULE_PARM(spia_pedr, "i"); -MODULE_PARM(spia_peddr, "i"); +module_param(spia_io_base, int, 0); +module_param(spia_fio_base, int, 0); +module_param(spia_pedr, int, 0); +module_param(spia_peddr, int, 0); /* * Define partitions for flash device @@ -132,8 +132,8 @@ int __init spia_init (void) (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; /* Set address of NAND IO lines */ - this->IO_ADDR_R = spia_fio_base; - this->IO_ADDR_W = spia_fio_base; + this->IO_ADDR_R = (void __iomem *) spia_fio_base; + this->IO_ADDR_W = (void __iomem *) spia_fio_base; /* Set address of hardware control function */ this->hwcontrol = spia_hwcontrol; /* 15 us command delay time */ @@ -145,14 +145,6 @@ int __init spia_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (spia_mtd->oobblock + spia_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for SPIA.\n"); - kfree (spia_mtd); - return -ENOMEM; - } - /* Register the partitions */ add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); @@ -167,13 +159,8 @@ module_init(spia_init); #ifdef MODULE static void __exit spia_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &spia_mtd[1]; - - /* Unregister the device */ - del_mtd_device (spia_mtd); - - /* Free internal data buffer */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (spia_mtd); /* Free the MTD device structure */ kfree (spia_mtd); diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index ecb9f3dc8..52c808fb5 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c @@ -15,7 +15,7 @@ * This is a device driver for the NAND flash device found on the * TI fido board. It supports 32MiB and 64MiB cards * - * $Id: toto.c,v 1.2 2003/10/21 10:04:58 dwmw2 Exp $ + * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ */ #include @@ -37,7 +37,7 @@ */ static struct mtd_info *toto_mtd = NULL; -static int toto_io_base = OMAP_FLASH_1_BASE; +static unsigned long toto_io_base = OMAP_FLASH_1_BASE; #define CONFIG_NAND_WORKAROUND 1 @@ -155,14 +155,6 @@ int __init toto_init (void) goto out_mtd; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (toto_mtd->oobblock + toto_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk (KERN_WARNING "Unable to allocate NAND data buffer for toto.\n"); - err = -ENOMEM; - goto out_mtd; - } - /* Register the partitions */ switch(toto_mtd->size){ case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; @@ -194,16 +186,8 @@ module_init(toto_init); */ static void __exit toto_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &toto_mtd[1]; - - /* Unregister partitions */ - del_mtd_partitions(toto_mtd); - - /* Unregister the device */ - del_mtd_device (toto_mtd); - - /* Free internal data buffers */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (toto_mtd); /* Free the MTD device structure */ kfree (toto_mtd); diff --git a/drivers/mtd/nand/tx4925ndfmc.c b/drivers/mtd/nand/tx4925ndfmc.c index 5f6a2f5ed..bba688830 100644 --- a/drivers/mtd/nand/tx4925ndfmc.c +++ b/drivers/mtd/nand/tx4925ndfmc.c @@ -11,7 +11,7 @@ * Derived from drivers/mtd/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: tx4925ndfmc.c,v 1.3 2004/07/20 02:44:26 dwmw2 Exp $ + * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $ * * Copyright (C) 2001 Toshiba Corporation * @@ -340,8 +340,8 @@ int __init tx4925ndfmc_init (void) tx4925ndfmc_mtd->priv = this; /* Set address of NAND IO lines */ - this->IO_ADDR_R = (unsigned long)&(tx4925_ndfmcptr->dtr); - this->IO_ADDR_W = (unsigned long)&(tx4925_ndfmcptr->dtr); + this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr); + this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr); this->hwcontrol = tx4925ndfmc_hwcontrol; this->enable_hwecc = tx4925ndfmc_enable_hwecc; this->calculate_ecc = tx4925ndfmc_readecc; @@ -363,14 +363,6 @@ int __init tx4925ndfmc_init (void) goto out_ior; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (tx4925ndfmc_mtd->oobblock + tx4925ndfmc_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for RBTX4925.\n"); - err = -ENOMEM; - goto out_ior; - } - /* Register the partitions */ #ifdef CONFIG_MTD_CMDLINE_PARTS { @@ -391,14 +383,12 @@ int __init tx4925ndfmc_init (void) default: { printk ("Unsupported SmartMedia device\n"); err = -ENXIO; - goto out_buf; + goto out_ior; } } #endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ goto out; -out_buf: - kfree (this->data_buf); out_ior: out: return err; @@ -412,16 +402,8 @@ module_init(tx4925ndfmc_init); #ifdef MODULE static void __exit tx4925ndfmc_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) &tx4925ndfmc_mtd[1]; - - /* Unregister partitions */ - del_mtd_partitions(tx4925ndfmc_mtd); - - /* Unregister the device */ - del_mtd_device (tx4925ndfmc_mtd); - - /* Free internal data buffers */ - kfree (this->data_buf); + /* Release resources, unregister device */ + nand_release (tx4925ndfmc_mtd); /* Free the MTD device structure */ kfree (tx4925ndfmc_mtd); diff --git a/drivers/mtd/nand/tx4938ndfmc.c b/drivers/mtd/nand/tx4938ndfmc.c index f2375b241..df26e5882 100644 --- a/drivers/mtd/nand/tx4938ndfmc.c +++ b/drivers/mtd/nand/tx4938ndfmc.c @@ -10,7 +10,7 @@ * * Based on spia.c by Steven J. Hill * - * $Id: tx4938ndfmc.c,v 1.2 2004/03/27 19:55:53 gleixner Exp $ + * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ * * Copyright (C) 2000-2001 Toshiba Corporation * @@ -365,14 +365,6 @@ int __init tx4938ndfmc_init (void) return -ENXIO; } - /* Allocate memory for internal data buffer */ - this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL); - if (!this->data_buf) { - printk ("Unable to allocate NAND data buffer for TX4938.\n"); - kfree (tx4938ndfmc_mtd); - return -ENOMEM; - } - if (protected) { printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); @@ -401,19 +393,11 @@ module_init(tx4938ndfmc_init); */ static void __exit tx4938ndfmc_cleanup (void) { - struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv; - - /* Unregister the device */ -#ifdef CONFIG_MTD_CMDLINE_PARTS - del_mtd_partitions(tx4938ndfmc_mtd); -#endif - del_mtd_device (tx4938ndfmc_mtd); + /* Release resources, unregister device */ + nand_release (tx4938ndfmc_mtd); /* Free the MTD device structure */ kfree (tx4938ndfmc_mtd); - - /* Free internal data buffer */ - kfree (this->data_buf); } module_exit(tx4938ndfmc_cleanup); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index 4102a6797..b20140436 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -1,7 +1,7 @@ /* Linux driver for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftlcore.c,v 1.96 2004/06/28 13:52:55 dbrown Exp $ */ +/* $Id: nftlcore.c,v 1.97 2004/11/16 18:28:59 dwmw2 Exp $ */ /* The contents of this file are distributed under the GNU General @@ -421,7 +421,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p return targetEUN; } -u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) +static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) { /* This is the part that needs some cleverness applied. For now, I'm doing the minimum applicable to actually @@ -731,7 +731,7 @@ static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) ****************************************************************************/ -struct mtd_blktrans_ops nftl_tr = { +static struct mtd_blktrans_ops nftl_tr = { .name = "nftl", .major = NFTL_MAJOR, .part_bits = NFTL_PARTN_BITS, @@ -747,9 +747,9 @@ struct mtd_blktrans_ops nftl_tr = { extern char nftlmountrev[]; -int __init init_nftl(void) +static int __init init_nftl(void) { - printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.96 $, nftlmount.c %s\n", nftlmountrev); + printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.97 $, nftlmount.c %s\n", nftlmountrev); return register_mtd_blktrans(&nftl_tr); } diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index a8a4e1ac8..19d6192f6 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -4,7 +4,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: nftlmount.c,v 1.36 2004/06/28 13:52:55 dbrown Exp $ + * $Id: nftlmount.c,v 1.39 2004/11/05 22:51:41 kalev Exp $ * * 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 @@ -31,7 +31,7 @@ #define SECTORSIZE 512 -char nftlmountrev[]="$Revision: 1.36 $"; +char nftlmountrev[]="$Revision: 1.39 $"; /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the * various device information of the NFTL partition and Bad Unit Table. Update @@ -41,7 +41,6 @@ char nftlmountrev[]="$Revision: 1.36 $"; static int find_boot_record(struct NFTLrecord *nftl) { struct nftl_uci1 h1; - struct nftl_oob oob; unsigned int block, boot_record_count = 0; size_t retlen; u8 buf[SECTORSIZE]; @@ -269,7 +268,8 @@ static int memcmpb(void *a, int c, int n) static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, int check_oob) { - int i, retlen; + int i; + size_t retlen; u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize]; for (i = 0; i < len; i += SECTORSIZE) { @@ -302,6 +302,8 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) struct nftl_uci1 uci; struct erase_info *instr = &nftl->instr; + instr->mtd = nftl->mbd.mtd; + /* Read the Unit Control Information #1 for Wear-Leveling */ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, &retlen, (char *)&uci) < 0) @@ -366,7 +368,8 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b { unsigned int block, i, status; struct nftl_bci bci; - int sectors_per_block, retlen; + int sectors_per_block; + size_t retlen; sectors_per_block = nftl->EraseSize / SECTORSIZE; block = first_block; diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 0c9911563..7628bda82 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -124,9 +124,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 3aa8409fe..6bff013a9 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -107,9 +107,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index ca0d71d63..8c2a06bfe 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -59,8 +59,8 @@ static const char version[] = #include #include #include +#include -#include #include #include #include @@ -294,6 +294,7 @@ static void el16_tx_timeout (struct net_device *dev); static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad); static void init_82586_mem(struct net_device *dev); static struct ethtool_ops netdev_ethtool_ops; +static void init_rx_bufs(struct net_device *); static int io = 0x300; static int irq; @@ -612,7 +613,6 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id, struct pt_regs *regs) } if ((status & 0x0070) != 0x0040 && netif_running(dev)) { - static void init_rx_bufs(struct net_device *); /* The Rx unit is not ready, it must be hung. Restart the receiver by initializing the rx buffers, and issuing an Rx start command. */ if (net_debug) diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 388929551..7d25f2e36 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -90,9 +90,9 @@ static int max_interrupt_work = 10; #include #include #include +#include #include -#include #include #include @@ -197,9 +197,9 @@ static int el3_rx(struct net_device *dev); static int el3_close(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void el3_tx_timeout (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static void el3_down(struct net_device *dev); static void el3_up(struct net_device *dev); +static struct ethtool_ops ethtool_ops; #ifdef CONFIG_PM static int el3_suspend(struct pm_dev *pdev); static int el3_resume(struct pm_dev *pdev); @@ -321,7 +321,7 @@ static int __init el3_common_init(struct net_device *dev) dev->set_multicast_list = &set_multicast_list; dev->tx_timeout = el3_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->do_ioctl = netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); err = register_netdev(dev); if (err) { @@ -1285,123 +1285,64 @@ el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) return 0; } -/** - * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls - * @dev: network interface on which out-of-band action is to be performed - * @useraddr: userspace address to which data is to be read and returned - * - * Process the various commands of the SIOCETHTOOL interface. - */ +static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); +} -static int -netdev_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - u32 ethcmd; struct el3_private *lp = netdev_priv(dev); + int ret; - /* dev_ioctl() in ../../net/core/dev.c has already checked - capable(CAP_NET_ADMIN), so don't bother with that here. */ - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - int ret; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - ret = el3_netdev_get_ecmd(dev, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return ret; - } - - /* set settings */ - case ETHTOOL_SSET: { - int ret; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&lp->lock); - ret = el3_netdev_set_ecmd(dev, &ecmd); - spin_unlock_irq(&lp->lock); - return ret; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - spin_lock_irq(&lp->lock); - edata.data = el3_link_ok(dev); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = el3_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; - el3_debug = edata.data; - return 0; - } + spin_lock_irq(&lp->lock); + ret = el3_netdev_get_ecmd(dev, ecmd); + spin_unlock_irq(&lp->lock); + return ret; +} - default: - break; - } +static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct el3_private *lp = netdev_priv(dev); + int ret; - return -EOPNOTSUPP; + spin_lock_irq(&lp->lock); + ret = el3_netdev_set_ecmd(dev, ecmd); + spin_unlock_irq(&lp->lock); + return ret; } -/** - * netdev_ioctl: Handle network interface ioctls - * @dev: network interface on which out-of-band action is to be performed - * @rq: user request data - * @cmd: command issued by user - * - * Process the various out-of-band ioctls passed to this driver. - */ - -static int -netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +static u32 el3_get_link(struct net_device *dev) { - int rc = 0; + struct el3_private *lp = netdev_priv(dev); + u32 ret; - switch (cmd) { - case SIOCETHTOOL: - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - break; + spin_lock_irq(&lp->lock); + ret = el3_link_ok(dev); + spin_unlock_irq(&lp->lock); + return ret; +} - default: - rc = -EOPNOTSUPP; - break; - } +static u32 el3_get_msglevel(struct net_device *dev) +{ + return el3_debug; +} - return rc; +static void el3_set_msglevel(struct net_device *dev, u32 v) +{ + el3_debug = v; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = el3_get_drvinfo, + .get_settings = el3_get_settings, + .set_settings = el3_set_settings, + .get_link = el3_get_link, + .get_msglevel = el3_get_msglevel, + .set_msglevel = el3_set_msglevel, +}; + static void el3_down(struct net_device *dev) { diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index bcdc0d608..7dca6e585 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -72,9 +72,9 @@ static int max_interrupt_work = 20; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 1902f7921..0a5df59d4 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -104,10 +104,10 @@ #include #include #include +#include #include #include -#include #include #include "3c523.h" diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index c6f1995e0..15550b144 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -102,11 +102,11 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter #include #include +#include #include #include #include -#include #include #include @@ -751,18 +751,15 @@ static int mc32_load_rx_ring(struct net_device *dev) rx_base=lp->rx_chain; - for(i=0; irx_ring[i].skb=alloc_skb(1532, GFP_KERNEL); - skb_reserve(lp->rx_ring[i].skb, 18); - - if(lp->rx_ring[i].skb==NULL) - { - for(;i>=0;i--) + if (lp->rx_ring[i].skb==NULL) { + for (;i>=0;i--) kfree_skb(lp->rx_ring[i].skb); return -ENOBUFS; } - + skb_reserve(lp->rx_ring[i].skb, 18); + p=isa_bus_to_virt(lp->base+rx_base); p->control=0; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index ab2e61a9d..f1075f733 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -257,8 +257,8 @@ static int vortex_debug = 1; #include #include #include +#include #include /* For NR_IRQS only. */ -#include #include #include @@ -695,7 +695,7 @@ enum Window2 { /* Window 2. */ Wn2_ResetOptions=12, }; enum Window3 { /* Window 3: MAC/config bits. */ - Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, + Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8, }; #define BFEXT(value, offset, bitcount) \ @@ -723,7 +723,8 @@ enum Win4_Media_bits { Media_LnkBeat = 0x0800, }; enum Window7 { /* Window 7: Bus Master control. */ - Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, + Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6, + Wn7_MasterStatus = 12, }; /* Boomerang bus master control registers. */ enum MasterCtrl { @@ -797,7 +798,7 @@ struct vortex_private { /* PCI configuration space information. */ struct device *gendev; - char *cb_fn_base; /* CardBus function status addr space. */ + char __iomem *cb_fn_base; /* CardBus function status addr space. */ /* Some values here only for performance evaluation and path-coverage */ int rx_nocopy, rx_copy, queued_packet, rx_csumhits; @@ -816,10 +817,11 @@ struct vortex_private { partner_flow_ctrl:1, /* Partner supports flow control */ has_nway:1, enable_wol:1, /* Wake-on-LAN is enabled */ - pm_state_valid:1, /* power_state[] has sane contents */ + pm_state_valid:1, /* pci_dev->saved_config_space has sane contents */ open:1, medialock:1, - must_free_region:1; /* Flag: if zero, Cardbus owns the I/O region */ + must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ + large_frames:1; /* accept large frames */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -832,7 +834,6 @@ struct vortex_private { u16 io_size; /* Size of PCI region (for release_region) */ spinlock_t lock; /* Serialise access to device & its vortex_private */ spinlock_t mdio_lock; /* Serialise access to mdio hardware */ - u32 power_state[16]; }; #ifdef CONFIG_PCI @@ -900,10 +901,14 @@ static void dump_tx_ring(struct net_device *dev); static void update_stats(long ioaddr, struct net_device *dev); static struct net_device_stats *vortex_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +#ifdef CONFIG_PCI static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +#endif static void vortex_tx_timeout(struct net_device *dev); static void acpi_set_WOL(struct net_device *dev); static struct ethtool_ops vortex_ethtool_ops; +static void set_8021q_mode(struct net_device *dev, int enable); + /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ /* Option count limit only -- unlimited interfaces are supported. */ @@ -1164,6 +1169,7 @@ static int __devinit vortex_probe1(struct device *gendev, dev->base_addr = ioaddr; dev->irq = irq; dev->mtu = mtu; + vp->large_frames = mtu > 1500; vp->drv_flags = vci->drv_flags; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; vp->io_size = vci->io_size; @@ -1290,6 +1296,13 @@ static int __devinit vortex_probe1(struct device *gendev, for (i = 0; i < 6; i++) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); } + /* Unfortunately an all zero eeprom passes the checksum and this + gets found in the wild in failure cases. Crypto is hard 8) */ + if (!is_valid_ether_addr(dev->dev_addr)) { + retval = -EINVAL; + printk(KERN_ERR "*** EEPROM MAC address is invalid.\n"); + goto free_ring; /* With every pack */ + } EL3WINDOW(2); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + i); @@ -1468,7 +1481,9 @@ static int __devinit vortex_probe1(struct device *gendev, dev->stop = vortex_close; dev->get_stats = vortex_get_stats; +#ifdef CONFIG_PCI dev->do_ioctl = vortex_ioctl; +#endif dev->ethtool_ops = &vortex_ethtool_ops; dev->set_multicast_list = set_rx_mode; dev->tx_timeout = vortex_tx_timeout; @@ -1478,7 +1493,7 @@ static int __devinit vortex_probe1(struct device *gendev, #endif if (pdev && vp->enable_wol) { vp->pm_state_valid = 1; - pci_save_state(VORTEX_PCI(vp), vp->power_state); + pci_save_state(VORTEX_PCI(vp)); acpi_set_WOL(dev); } retval = register_netdev(dev); @@ -1535,7 +1550,7 @@ vortex_up(struct net_device *dev) if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ - pci_restore_state(VORTEX_PCI(vp), vp->power_state); + pci_restore_state(VORTEX_PCI(vp)); } /* Before initializing select the active media port. */ @@ -1616,7 +1631,7 @@ vortex_up(struct net_device *dev) /* Set the full-duplex bit. */ outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | + (vp->large_frames ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); @@ -1700,6 +1715,8 @@ vortex_up(struct net_device *dev) } /* Set receiver mode: presumably accept b-case and phys addr only. */ set_rx_mode(dev); + /* enable 802.1q tagged frames */ + set_8021q_mode(dev, 1); outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ // issue_and_wait(dev, SetTxStart|0x07ff); @@ -1842,7 +1859,7 @@ vortex_timer(unsigned long data) /* Set the full-duplex bit. */ EL3WINDOW(3); outw( (vp->full_duplex ? 0x20 : 0) | - (dev->mtu > 1500 ? 0x40 : 0) | + (vp->large_frames ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); if (vortex_debug > 1) @@ -2068,6 +2085,8 @@ vortex_error(struct net_device *dev, int status) issue_and_wait(dev, RxReset|0x07); /* Set the Rx filter to the current state. */ set_rx_mode(dev); + /* enable 802.1q VLAN tagged frames */ + set_8021q_mode(dev, 1); outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ outw(AckIntr | HostError, ioaddr + EL3_CMD); } @@ -2672,6 +2691,9 @@ vortex_down(struct net_device *dev, int final_down) outw(RxDisable, ioaddr + EL3_CMD); outw(TxDisable, ioaddr + EL3_CMD); + /* Disable receiving 802.1q tagged frames */ + set_8021q_mode(dev, 0); + if (dev->if_port == XCVR_10base2) /* Turn off thinnet power. Green! */ outw(StopCoax, ioaddr + EL3_CMD); @@ -2685,7 +2707,7 @@ vortex_down(struct net_device *dev, int final_down) outl(0, ioaddr + DownListPtr); if (final_down && VORTEX_PCI(vp) && vp->enable_wol) { - pci_save_state(VORTEX_PCI(vp), vp->power_state); + pci_save_state(VORTEX_PCI(vp)); acpi_set_WOL(dev); } } @@ -2865,9 +2887,10 @@ static void vortex_get_drvinfo(struct net_device *dev, } static struct ethtool_ops vortex_ethtool_ops = { - .get_drvinfo = vortex_get_drvinfo, + .get_drvinfo = vortex_get_drvinfo, }; +#ifdef CONFIG_PCI static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct vortex_private *vp = netdev_priv(dev); @@ -2925,6 +2948,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return err; } +#endif /* Pre-Cyclone chips have no documented multicast filter, so the only @@ -2947,6 +2971,61 @@ static void set_rx_mode(struct net_device *dev) outw(new_mode, ioaddr + EL3_CMD); } +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +/* Setup the card so that it can receive frames with an 802.1q VLAN tag. + Note that this must be done after each RxReset due to some backwards + compatibility logic in the Cyclone and Tornado ASICs */ + +/* The Ethernet Type used for 802.1q tagged frames */ +#define VLAN_ETHER_TYPE 0x8100 + +static void set_8021q_mode(struct net_device *dev, int enable) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + int old_window = inw(ioaddr + EL3_CMD); + int mac_ctrl; + + if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) { + /* cyclone and tornado chipsets can recognize 802.1q + * tagged frames and treat them correctly */ + + int max_pkt_size = dev->mtu+14; /* MTU+Ethernet header */ + if (enable) + max_pkt_size += 4; /* 802.1Q VLAN tag */ + + EL3WINDOW(3); + outw(max_pkt_size, ioaddr+Wn3_MaxPktSize); + + /* set VlanEtherType to let the hardware checksumming + treat tagged frames correctly */ + EL3WINDOW(7); + outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType); + } else { + /* on older cards we have to enable large frames */ + + vp->large_frames = dev->mtu > 1500 || enable; + + EL3WINDOW(3); + mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl); + if (vp->large_frames) + mac_ctrl |= 0x40; + else + mac_ctrl &= ~0x40; + outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl); + } + + EL3WINDOW(old_window); +} +#else + +static void set_8021q_mode(struct net_device *dev, int enable) +{ +} + + +#endif + /* MII transceiver control section. Read and write the MII registers using software-generated serial MDIO protocol. See the MII specifications or DP83840A data sheet @@ -3086,7 +3165,7 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev) if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ if (vp->pm_state_valid) - pci_restore_state(VORTEX_PCI(vp), vp->power_state); + pci_restore_state(VORTEX_PCI(vp)); } /* Should really use issue_and_wait() here */ outw(TotalReset|0x14, dev->base_addr + EL3_CMD); diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 0e5aec0d5..18b027e73 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -14,7 +14,6 @@ */ #include #include -#include #include #include #include @@ -30,26 +29,67 @@ #include #include #include +#include /* Used for the temporal inet entries and routing */ #include +#include #include -#include #include #include #include +#ifdef CONFIG_HP300 +#include +#endif #include "7990.h" +#define WRITERAP(lp,x) out_be16(lp->base + LANCE_RAP, (x)) +#define WRITERDP(lp,x) out_be16(lp->base + LANCE_RDP, (x)) +#define READRDP(lp) in_be16(lp->base + LANCE_RDP) + +#if defined(CONFIG_HPLANCE) || defined(CONFIG_HPLANCE_MODULE) +#include "hplance.h" + +#undef WRITERAP +#undef WRITERDP +#undef READRDP + +#if defined(CONFIG_MVME147_NET) || defined(CONFIG_MVME147_NET_MODULE) + /* Lossage Factor Nine, Mr Sulu. */ -#define WRITERAP(x) (lp->writerap(lp,x)) -#define WRITERDP(x) (lp->writerdp(lp,x)) -#define READRDP() (lp->readrdp(lp)) -/* These used to be ll->rap = x, ll->rdp = x, and (ll->rdp). Sigh. - * If you want to switch them back then - * #define DECLARE_LL volatile struct lance_regs *ll = lp->ll - */ -#define DECLARE_LL /* nothing to declare */ +#define WRITERAP(lp,x) (lp->writerap(lp,x)) +#define WRITERDP(lp,x) (lp->writerdp(lp,x)) +#define READRDP(lp) (lp->readrdp(lp)) + +#else + +/* These inlines can be used if only CONFIG_HPLANCE is defined */ +static inline void WRITERAP(struct lance_private *lp, __u16 value) +{ + do { + out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); +} + +static inline void WRITERDP(struct lance_private *lp, __u16 value) +{ + do { + out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); +} + +static inline __u16 READRDP(struct lance_private *lp) +{ + __u16 value; + do { + value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); + return value; +} + +#endif +#endif /* CONFIG_HPLANCE || CONFIG_HPLANCE_MODULE */ /* debugging output macros, various flavours */ /* #define TEST_HITS */ @@ -79,19 +119,18 @@ static void load_csrs (struct lance_private *lp) { volatile struct lance_init_block *aib = lp->lance_init_block; int leptr; - DECLARE_LL; leptr = LANCE_ADDR (aib); - WRITERAP(LE_CSR1); /* load address of init block */ - WRITERDP(leptr & 0xFFFF); - WRITERAP(LE_CSR2); - WRITERDP(leptr >> 16); - WRITERAP(LE_CSR3); - WRITERDP(lp->busmaster_regval); /* set byteswap/ALEctrl/byte ctrl */ + WRITERAP(lp, LE_CSR1); /* load address of init block */ + WRITERDP(lp, leptr & 0xFFFF); + WRITERAP(lp, LE_CSR2); + WRITERDP(lp, leptr >> 16); + WRITERAP(lp, LE_CSR3); + WRITERDP(lp, lp->busmaster_regval); /* set byteswap/ALEctrl/byte ctrl */ /* Point back to csr0 */ - WRITERAP(LE_CSR0); + WRITERAP(lp, LE_CSR0); } /* #define to 0 or 1 appropriately */ @@ -192,24 +231,23 @@ static void lance_init_ring (struct net_device *dev) static int init_restart_lance (struct lance_private *lp) { int i; - DECLARE_LL; - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_INIT); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_INIT); /* Need a hook here for sunlance ledma stuff */ /* Wait for the lance to complete initialization */ - for (i = 0; (i < 100) && !(READRDP() & (LE_C0_ERR | LE_C0_IDON)); i++) + for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++) barrier(); - if ((i == 100) || (READRDP() & LE_C0_ERR)) { - printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP()); + if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) { + printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp)); return -1; } /* Clear IDON by writing a "1", enable interrupts and start lance */ - WRITERDP(LE_C0_IDON); - WRITERDP(LE_C0_INEA | LE_C0_STRT); + WRITERDP(lp, LE_C0_IDON); + WRITERDP(lp, LE_C0_INEA | LE_C0_STRT); return 0; } @@ -218,11 +256,10 @@ static int lance_reset (struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); int status; - DECLARE_LL; /* Stop the lance */ - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_STOP); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STOP); load_csrs (lp); lance_init_ring (dev); @@ -245,7 +282,6 @@ static int lance_rx (struct net_device *dev) #ifdef TEST_HITS int i; #endif - DECLARE_LL; #ifdef TEST_HITS printk ("["); @@ -259,8 +295,10 @@ static int lance_rx (struct net_device *dev) } printk ("]"); #endif - - WRITERDP(LE_C0_RINT | LE_C0_INEA); /* ack Rx int, reenable ints */ +#ifdef CONFIG_HP300 + blinken_leds(0x40, 0); +#endif + WRITERDP(lp, LE_C0_RINT | LE_C0_INEA); /* ack Rx int, reenable ints */ for (rd = &ib->brx_ring [lp->rx_new]; /* For each Rx ring we own... */ !((bits = rd->rmd1_bits) & LE_R1_OWN); rd = &ib->brx_ring [lp->rx_new]) { @@ -321,10 +359,12 @@ static int lance_tx (struct net_device *dev) volatile struct lance_tx_desc *td; int i, j; int status; - DECLARE_LL; +#ifdef CONFIG_HP300 + blinken_leds(0x80, 0); +#endif /* csr0 is 2f3 */ - WRITERDP(LE_C0_TINT | LE_C0_INEA); + WRITERDP(lp, LE_C0_TINT | LE_C0_INEA); /* csr0 is 73 */ j = lp->tx_old; @@ -349,8 +389,8 @@ static int lance_tx (struct net_device *dev) printk("%s: Carrier Lost, trying %s\n", dev->name, lp->tpe?"TPE":"AUI"); /* Stop the lance */ - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_STOP); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STOP); lance_init_ring (dev); load_csrs (lp); init_restart_lance (lp); @@ -366,8 +406,8 @@ static int lance_tx (struct net_device *dev) printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", dev->name); /* Stop the lance */ - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_STOP); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STOP); lance_init_ring (dev); load_csrs (lp); init_restart_lance (lp); @@ -393,7 +433,7 @@ static int lance_tx (struct net_device *dev) j = (j + 1) & lp->tx_ring_mod_mask; } lp->tx_old = j; - WRITERDP(LE_C0_TINT | LE_C0_INEA); + WRITERDP(lp, LE_C0_TINT | LE_C0_INEA); return 0; } @@ -403,26 +443,25 @@ lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) struct net_device *dev = (struct net_device *)dev_id; struct lance_private *lp = netdev_priv(dev); int csr0; - DECLARE_LL; spin_lock (&lp->devlock); - WRITERAP(LE_CSR0); /* LANCE Controller Status */ - csr0 = READRDP(); + WRITERAP(lp, LE_CSR0); /* LANCE Controller Status */ + csr0 = READRDP(lp); PRINT_RINGS(); if (!(csr0 & LE_C0_INTR)) { /* Check if any interrupt has */ - spin_lock (&lp->devlock); + spin_unlock (&lp->devlock); return IRQ_NONE; /* been generated by the Lance. */ } /* Acknowledge all the interrupt sources ASAP */ - WRITERDP(csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT)); + WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT)); if ((csr0 & LE_C0_ERR)) { /* Clear the error condition */ - WRITERDP(LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA); + WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA); } if (csr0 & LE_C0_RINT) @@ -440,7 +479,7 @@ lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) printk("%s: Bus master arbitration failure, status %4.4x.\n", dev->name, csr0); /* Restart the chip. */ - WRITERDP(LE_C0_STRT); + WRITERDP(lp, LE_C0_STRT); } if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) { @@ -448,8 +487,8 @@ lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) netif_wake_queue (dev); } - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA); spin_unlock (&lp->devlock); return IRQ_HANDLED; @@ -459,14 +498,13 @@ int lance_open (struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); int res; - DECLARE_LL; /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */ if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev)) return -EAGAIN; res = lance_reset(dev); - lp->devlock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->devlock); netif_start_queue (dev); return res; @@ -475,13 +513,12 @@ int lance_open (struct net_device *dev) int lance_close (struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - DECLARE_LL; netif_stop_queue (dev); /* Stop the LANCE */ - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_STOP); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STOP); free_irq(lp->irq, dev); @@ -504,7 +541,6 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) int entry, skblen, len; static int outs; unsigned long flags; - DECLARE_LL; if (!TX_BUFFS_AVAIL) return -1; @@ -540,7 +576,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) outs++; /* Kick the lance: transmit now */ - WRITERDP(LE_C0_INEA | LE_C0_TDMD); + WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD); dev->trans_start = jiffies; dev_kfree_skb (skb); @@ -604,7 +640,6 @@ void lance_set_multicast (struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; int stopped; - DECLARE_LL; stopped = netif_queue_stopped(dev); if (!stopped) @@ -613,8 +648,8 @@ void lance_set_multicast (struct net_device *dev) while (lp->tx_old != lp->tx_new) schedule(); - WRITERAP(LE_CSR0); - WRITERDP(LE_C0_STOP); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STOP); lance_init_ring (dev); if (dev->flags & IFF_PROMISC) { @@ -630,4 +665,17 @@ void lance_set_multicast (struct net_device *dev) netif_start_queue (dev); } +#ifdef CONFIG_NET_POLL_CONTROLLER +void lance_poll(struct net_device *dev) +{ + struct lance_private *lp = netdev_priv(dev); + + spin_lock (&lp->devlock); + WRITERAP(lp, LE_CSR0); + WRITERDP(lp, LE_C0_STRT); + spin_unlock (&lp->devlock); + lance_interrupt(dev->irq, dev, NULL); +} +#endif + MODULE_LICENSE("GPL"); diff --git a/drivers/net/7990.h b/drivers/net/7990.h index 6875780ae..31ae50997 100644 --- a/drivers/net/7990.h +++ b/drivers/net/7990.h @@ -14,11 +14,8 @@ #define _7990_H /* The lance only has two register locations. We communicate mostly via memory. */ -struct lance_regs -{ - unsigned short rdp; /* Register Data Port */ - unsigned short rap; /* Register Address Port */ -}; +#define LANCE_RDP 0 /* Register Data Port */ +#define LANCE_RAP 2 /* Register Address Port */ /* Transmit/receive ring definitions. * We allow the specific drivers to override these defaults if they want to. @@ -104,7 +101,7 @@ struct lance_init_block { struct lance_private { char *name; - volatile struct lance_regs *ll; + unsigned long base; volatile struct lance_init_block *init_block; /* CPU address of RAM */ volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */ @@ -252,5 +249,8 @@ extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev); extern struct net_device_stats *lance_get_stats (struct net_device *dev); extern void lance_set_multicast (struct net_device *dev); extern void lance_tx_timeout(struct net_device *dev); +#ifdef CONFIG_NET_POLL_CONTROLLER +extern void lance_poll(struct net_device *dev); +#endif #endif /* ndef _7990_H */ diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 62dd13951..a71423c75 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -71,6 +71,7 @@ #include #include #include +#include #include /* VLAN tagging feature enable/disable */ @@ -335,7 +336,7 @@ struct cp_extra_stats { }; struct cp_private { - void *regs; + void __iomem *regs; struct net_device *dev; spinlock_t lock; u32 msg_enable; @@ -366,7 +367,6 @@ struct cp_private { #endif unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */ - u32 power_state[16]; struct mii_if_info mii_if; }; @@ -1580,11 +1580,11 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) #define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int read_eeprom (void *ioaddr, int location, int addr_len) +static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) { int i; unsigned retval = 0; - void *ee_addr = ioaddr + Cfg9346; + void __iomem *ee_addr = ioaddr + Cfg9346; int read_cmd = location | (EE_READ_CMD << addr_len); writeb (EE_ENB & ~EE_CS, ee_addr); @@ -1631,7 +1631,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *dev; struct cp_private *cp; int rc; - void *regs; + void __iomem *regs; long pciaddr; unsigned int addr_len, i, pci_using_dac; u8 pci_rev; @@ -1698,7 +1698,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } /* Configure DMA attributes. */ - if ((sizeof(dma_addr_t) > 32) && + if ((sizeof(dma_addr_t) > 4) && !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) && !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { pci_using_dac = 1; @@ -1845,7 +1845,7 @@ static int cp_suspend (struct pci_dev *pdev, u32 state) spin_unlock_irqrestore (&cp->lock, flags); if (cp->pdev && cp->wol_enabled) { - pci_save_state (cp->pdev, cp->power_state); + pci_save_state (cp->pdev); cp_set_d3_state (cp); } @@ -1864,7 +1864,7 @@ static int cp_resume (struct pci_dev *pdev) if (cp->pdev && cp->wol_enabled) { pci_set_power_state (cp->pdev, 0); - pci_restore_state (cp->pdev, cp->power_state); + pci_restore_state (cp->pdev); } cp_init_hw (cp); diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 58290c5bb..51e56c4a2 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -567,7 +567,6 @@ struct rtl8139_private { void *mmio_addr; int drv_flags; struct pci_dev *pci_dev; - u32 pci_state[16]; u32 msg_enable; struct net_device_stats stats; unsigned char *rx_ring; @@ -593,16 +592,17 @@ struct rtl8139_private { int time_to_die; struct mii_if_info mii; unsigned int regs_len; + unsigned long fifo_copy_timeout; }; MODULE_AUTHOR ("Jeff Garzik "); MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM (multicast_filter_limit, "i"); -MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM (debug, "i"); +module_param(multicast_filter_limit, int, 0); +module_param_array(media, int, NULL, 0); +module_param_array(full_duplex, int, NULL, 0); +module_param(debug, int, 0); MODULE_PARM_DESC (debug, "8139too bitmapped message enable number"); MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); @@ -613,7 +613,7 @@ static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, int val); -static inline void rtl8139_start_thread(struct net_device *dev); +static void rtl8139_start_thread(struct net_device *dev); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, @@ -1643,7 +1643,7 @@ static int rtl8139_thread (void *data) complete_and_exit (&tp->thr_exited, 0); } -static inline void rtl8139_start_thread(struct net_device *dev) +static void rtl8139_start_thread(struct net_device *dev) { struct rtl8139_private *tp = dev->priv; @@ -1927,6 +1927,24 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring, } #endif +static void rtl8139_isr_ack(struct rtl8139_private *tp) +{ + void *ioaddr = tp->mmio_addr; + u16 status; + + status = RTL_R16 (IntrStatus) & RxAckBits; + + /* Clear out errors and receive interrupts */ + if (likely(status != 0)) { + if (unlikely(status & (RxFIFOOver | RxOverflow))) { + tp->stats.rx_errors++; + if (status & RxFIFOOver) + tp->stats.rx_fifo_errors++; + } + RTL_W16_F (IntrStatus, RxAckBits); + } +} + static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int budget) { @@ -1934,9 +1952,10 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int received = 0; unsigned char *rx_ring = tp->rx_ring; unsigned int cur_rx = tp->cur_rx; + unsigned int rx_size = 0; DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, + " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); @@ -1944,10 +1963,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { u32 ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; - unsigned int rx_size; unsigned int pkt_size; struct sk_buff *skb; - u16 status; rmb(); @@ -1976,10 +1993,24 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, * since EarlyRx is disabled. */ if (unlikely(rx_size == 0xfff0)) { + if (!tp->fifo_copy_timeout) + tp->fifo_copy_timeout = jiffies + 2; + else if (time_after(jiffies, tp->fifo_copy_timeout)) { + DPRINTK ("%s: hung FIFO. Reset.", dev->name); + rx_size = 0; + goto no_early_rx; + } + if (netif_msg_intr(tp)) { + printk(KERN_DEBUG "%s: fifo copy in progress.", + dev->name); + } tp->xstats.early_rx++; - goto done; + break; } +no_early_rx: + tp->fifo_copy_timeout = 0; + /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further @@ -1989,7 +2020,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, (rx_size < 8) || (!(rx_status & RxStatusOK)))) { rtl8139_rx_err (rx_status, dev, tp, ioaddr); - return -1; + received = -1; + goto out; } /* Malloc up new buffer, compatible with net-2e. */ @@ -2025,19 +2057,11 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - /* Clear out errors and receive interrupts */ - status = RTL_R16 (IntrStatus) & RxAckBits; - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } + rtl8139_isr_ack(tp); } - done: + if (unlikely(!received || rx_size == 0xfff0)) + rtl8139_isr_ack(tp); #if RTL8139_DEBUG > 1 DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," @@ -2047,6 +2071,15 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, #endif tp->cur_rx = cur_rx; + + /* + * The receive buffer should be mostly empty. + * Tell NAPI to reenable the Rx irq. + */ + if (tp->fifo_copy_timeout) + received = budget; + +out: return received; } @@ -2555,7 +2588,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) void *ioaddr = tp->mmio_addr; unsigned long flags; - pci_save_state (pdev, tp->pci_state); + pci_save_state (pdev); if (!netif_running (dev)) return 0; @@ -2583,9 +2616,8 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state) static int rtl8139_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); - struct rtl8139_private *tp = dev->priv; - pci_restore_state (pdev, tp->pci_state); + pci_restore_state (pdev); if (!netif_running (dev)) return 0; pci_set_power_state (pdev, 0); diff --git a/drivers/net/82596.c b/drivers/net/82596.c index c835712ed..ff9bf1cbe 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -53,8 +53,8 @@ #include #include #include +#include -#include #include #include #include @@ -1260,7 +1260,7 @@ struct net_device * __init i82596_probe(int unit) lp->scb.command = 0; lp->scb.cmd = I596_NULL; lp->scb.rfd = I596_NULL; - lp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->lock); err = register_netdev(dev); if (err) diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 22e7dfb47..e3053a877 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -41,6 +41,8 @@ module by all drivers that require it. Alan Cox : Spinlocking work, added 'BUG_83C690' Paul Gortmaker : Separate out Tx timeout code from Tx path. + Paul Gortmaker : Remove old unused single Tx buffer code. + Hayato Fujiwara : Add m32r support. Sources: The National Semiconductor LAN Databook, and the 3Com 3c503 databook. @@ -56,9 +58,9 @@ static const char version[] = #include #include #include +#include #include #include -#include #include #include #include @@ -218,6 +220,15 @@ void ei_tx_timeout(struct net_device *dev) int txsr, isr, tickssofar = jiffies - dev->trans_start; unsigned long flags; +#if defined(CONFIG_M32R) && defined(CONFIG_SMP) + unsigned long icucr; + + local_irq_save(flags); + icucr = inl(ICUCR1); + icucr |= M32R_ICUCR_ISMOD11; + outl(icucr, ICUCR1); + local_irq_restore(flags); +#endif ei_local->stat.tx_errors++; spin_lock_irqsave(&ei_local->page_lock, flags); @@ -289,8 +300,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) 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, @@ -309,7 +318,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (ei_local->tx2 == 0) { - output_page = ei_local->tx_start_page + TX_1X_PAGES; + output_page = ei_local->tx_start_page + TX_PAGES/2; 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", @@ -366,28 +375,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *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. - */ - - if (length == send_length) - ei_block_output(dev, length, skb->data, ei_local->tx_start_page); - else { - memset(scratch, 0, ETH_ZLEN); - memcpy(scratch, skb->data, skb->len); - ei_block_output(dev, ETH_ZLEN, scratch, 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); @@ -590,8 +577,6 @@ static void ei_tx_intr(struct net_device *dev) outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ -#ifdef EI_PINGPONG - /* * There are two Tx buffers, see which one finished, and trigger * the send of another one if it exists. @@ -634,13 +619,6 @@ static void ei_tx_intr(struct net_device *dev) // 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++; @@ -835,7 +813,7 @@ static void ei_rx_overrun(struct net_device *dev) * We wait at least 10ms. */ - udelay(10*1000); + mdelay(10); /* * Reset RBCR[01] back to zero as per magic incantation. diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 58fd65e03..948723b72 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -12,17 +12,7 @@ #include #include -#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 TX_PAGES 12 /* Two Tx slots */ #define ETHER_ADDR_LEN 6 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 882837793..82c10bbd6 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -200,7 +200,7 @@ source "drivers/net/arm/Kconfig" config MACE tristate "MACE (Power Mac ethernet) support" - depends on NET_ETHERNET && PPC_PMAC + depends on NET_ETHERNET && PPC_PMAC && PPC32 select CRC32 help Power Macintoshes and clones with Ethernet built-in on the @@ -223,7 +223,7 @@ config MACE_AAUI_PORT config BMAC tristate "BMAC (G3 ethernet) support" - depends on NET_ETHERNET && PPC_PMAC + depends on NET_ETHERNET && PPC_PMAC && PPC32 select CRC32 help Say Y for support of BMAC Ethernet interfaces. These are used on G3 @@ -288,7 +288,7 @@ config ZORRO8390 config APNE tristate "PCMCIA NE2000 support" - depends on NETDEVICES && AMIGA_PCMCIA + depends on NET_ETHERNET && AMIGA_PCMCIA select CRC32 help If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, @@ -299,7 +299,7 @@ config APNE config APOLLO_ELPLUS tristate "Apollo 3c505 support" - depends on NETDEVICES && APOLLO + depends on NET_ETHERNET && APOLLO help Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. If you don't have one made for Apollos, you can use one from a PC, @@ -308,7 +308,7 @@ config APOLLO_ELPLUS config MAC8390 bool "Macintosh NS 8390 based ethernet cards" - depends on NETDEVICES && MAC + depends on NET_ETHERNET && MAC select CRC32 help If you want to include a driver to support Nubus or LC-PDS @@ -318,7 +318,7 @@ config MAC8390 config MAC89x0 tristate "Macintosh CS89x0 based ethernet cards" - depends on NETDEVICES && MAC && BROKEN + depends on NET_ETHERNET && MAC && BROKEN ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a Nubus or LC-PDS network (Ethernet) card of this type, say Y and @@ -331,7 +331,7 @@ config MAC89x0 config MACSONIC tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)" - depends on NETDEVICES && MAC + depends on NET_ETHERNET && MAC ---help--- Support for NatSemi SONIC based Ethernet devices. This includes the onboard Ethernet in many Quadras as well as some LC-PDS, @@ -345,7 +345,7 @@ config MACSONIC config MACMACE bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)" - depends on NETDEVICES && MAC && EXPERIMENTAL + depends on NET_ETHERNET && MAC && EXPERIMENTAL select CRC32 help Support for the onboard AMD 79C940 MACE Ethernet controller used in @@ -355,7 +355,7 @@ config MACMACE config MVME147_NET tristate "MVME147 (Lance) Ethernet support" - depends on NETDEVICES && MVME147 + depends on NET_ETHERNET && MVME147 select CRC32 help Support for the on-board Ethernet interface on the Motorola MVME147 @@ -365,7 +365,7 @@ config MVME147_NET config MVME16x_NET tristate "MVME16x Ethernet support" - depends on NETDEVICES && MVME16x + depends on NET_ETHERNET && MVME16x help This is the driver for the Ethernet interface on the Motorola MVME162, 166, 167, 172 and 177 boards. Say Y here to include the @@ -374,7 +374,7 @@ config MVME16x_NET config BVME6000_NET tristate "BVME6000 Ethernet support" - depends on NETDEVICES && BVME6000 + depends on NET_ETHERNET && BVME6000 help This is the driver for the Ethernet interface on BVME4000 and BVME6000 VME boards. Say Y here to include the driver for this chip @@ -383,7 +383,7 @@ config BVME6000_NET config ATARILANCE tristate "Atari Lance support" - depends on NETDEVICES && ATARI + depends on NET_ETHERNET && ATARI help Say Y to include support for several Atari Ethernet adapters based on the AMD Lance chipset: RieblCard (with or without battery), or @@ -391,7 +391,7 @@ config ATARILANCE config ATARI_BIONET tristate "BioNet-100 support" - depends on NETDEVICES && ATARI && ATARI_ACSI!=n && BROKEN + depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN help Say Y to include support for BioData's BioNet-100 Ethernet adapter for the ACSI port. The driver works (has to work...) with a polled @@ -399,7 +399,7 @@ config ATARI_BIONET config ATARI_PAMSNET tristate "PAMsNet support" - depends on NETDEVICES && ATARI && ATARI_ACSI!=n && BROKEN + depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN help Say Y to include support for the PAMsNet Ethernet adapter for the ACSI port ("ACSI node"). The driver works (has to work...) with a @@ -407,7 +407,7 @@ config ATARI_PAMSNET config SUN3LANCE tristate "Sun3/Sun3x on-board LANCE support" - depends on NETDEVICES && (SUN3 || SUN3X) + depends on NET_ETHERNET && (SUN3 || SUN3X) help Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80) featured an AMD Lance 10Mbit Ethernet controller on board; say Y @@ -420,7 +420,7 @@ config SUN3LANCE config SUN3_82586 tristate "Sun3 on-board Intel 82586 support" - depends on NETDEVICES && SUN3 + depends on NET_ETHERNET && SUN3 help This driver enables support for the on-board Intel 82586 based Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note @@ -429,7 +429,7 @@ config SUN3_82586 config HPLANCE bool "HP on-board LANCE support" - depends on NETDEVICES && HP300 + depends on NET_ETHERNET && DIO select CRC32 help If you want to use the builtin "LANCE" Ethernet controller on an @@ -817,7 +817,7 @@ config SMC91X tristate "SMC 91C9x/91C1xxx support" select CRC32 select MII - depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6) + depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R) help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it @@ -1075,7 +1075,7 @@ config ETH16I config NE2000 tristate "NE2000/NE1000 support" - depends on NET_ISA || (Q40 && m) + depends on NET_ISA || (Q40 && m) || M32R select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -1353,7 +1353,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on NET_PCI && ISA + depends on NET_PCI && (ISA || ARCH_IXDP2X01) ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the @@ -1413,66 +1413,17 @@ config E100 depends on NET_PCI && PCI select MII ---help--- - This driver supports Intel(R) PRO/100 family of adapters, which - includes: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - - 82558 PRO/100+ PCI Adapter 668081-xxx, - 689661-xxx - 82558 PRO/100+ Management Adapter 691334-xxx, - 701738-xxx, - 721383-xxx - 82558 PRO/100+ Dual Port Server Adapter 714303-xxx, - 711269-xxx, - A28276-xxx - 82558 PRO/100+ PCI Server Adapter 710550-xxx - 82550 PRO/100 S Server Adapter 752438-xxx - 82559 A56831-xxx, - A10563-xxx, - A12171-xxx, - A12321-xxx, - A12320-xxx, - A12170-xxx - 748568-xxx - 748565-xxx - 82550 PRO/100 S Desktop Adapter 751767-xxx - 82559 748592-xxx, - A12167-xxx, - A12318-xxx, - A12317-xxx, - A12165-xxx, - 748569-xxx - 82559 PRO/100+ Server Adapter 729757-xxx - 82559 PRO/100 S Management Adapter 748566-xxx, - 748564-xxx - 82550 PRO/100 S Dual Port Server Adapter A56831-xxx - 82551 PRO/100 M Desktop Adapter A80897-xxx - PRO/100 S Advanced Management Adapter - 747842-xxx, - 745171-xxx - CNR PRO/100 VE Desktop Adapter A10386-xxx, - A10725-xxx, - A23801-xxx, - A19716-xxx - PRO/100 VM Desktop Adapter A14323-xxx, - A19725-xxx, - A23801-xxx, - A22220-xxx, - A23796-xxx - - + This driver supports Intel(R) PRO/100 family of adapters. To verify that your adapter is supported, find the board ID number on the adapter. Look for a label that has a barcode and a number - in the format 123456-001 (six digits hyphen three digits). Match - this to the list of numbers above. + in the format 123456-001 (six digits hyphen three digits). - For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: + Use the above information and the Adapter & Driver ID Guide at: http://support.intel.com/support/network/adapter/pro100/21397.htm + to identify the adapter. + For the latest Intel PRO/100 network driver for Linux, see: http://appsr.intel.com/scripts-df/support_intel.asp @@ -1742,17 +1693,6 @@ config VIA_RHINE_MMIO If unsure, say Y. -config VIA_VELOCITY - tristate "VIA Velocity support" - depends on NET_PCI && PCI - select CRC32 - select MII - help - If you have a VIA "Velocity" based network card say Y here. - - To compile this driver as a module, choose M here. The module - will be called via-rhine. - config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" depends on NET_PCI && EXPERIMENTAL && MIPS @@ -1932,29 +1872,8 @@ config E1000 depends on PCI ---help--- This driver supports Intel(R) PRO/1000 gigabit ethernet family of - adapters, which includes: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - 82542 PRO/1000 Gigabit Server Adapter 700262-xxx, - 717037-xxx - 82543 PRO/1000 F Server Adapter 738640-xxx, - A38888-xxx - 82543 PRO/1000 T Server Adapter A19845-xxx, - A33948-xxx - 82544 PRO/1000 XT Server Adapter A51580-xxx - 82544 PRO/1000 XF Server Adapter A50484-xxx - 82544 PRO/1000 T Desktop Adapter A62947-xxx - 82540 PRO/1000 MT Desktop Adapter A78408-xxx - 82541 PRO/1000 MT Desktop Adapter C91016-xxx - 82545 PRO/1000 MT Server Adapter A92165-xxx - 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx - 82545 PRO/1000 MF Server Adapter A91622-xxx - 82545 PRO/1000 MF Server Adapter(LX) A91624-xxx - 82546 PRO/1000 MF Dual Port Server Adapter A91620-xxx - - For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: + adapters. For more information on how to identify your adapter, go + to the Adapter & Driver ID Guide at: @@ -2043,6 +1962,23 @@ config R8169 To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI @@ -2122,6 +2058,18 @@ config SK98LIN say M here and read Documentation/kbuild/modules.txt. The module will be called sk98lin. This is recommended. +config VIA_VELOCITY + tristate "VIA Velocity support" + depends on NET_PCI && PCI + select CRC32 + select CRC_CCITT + select MII + help + If you have a VIA "Velocity" based network card say Y here. + + To compile this driver as a module, choose M here. The module + will be called via-velocity. + config TIGON3 tristate "Broadcom Tigon3 support" depends on PCI @@ -2131,6 +2079,45 @@ config TIGON3 To compile this driver as a module, choose M here: the module will be called tg3. This is recommended. +config GIANFAR + tristate "Gianfar Ethernet" + depends on 85xx + help + This driver supports the Gigabit TSEC on the MPC85xx + family of chips, and the FEC on the 8540 + +config GFAR_NAPI + bool "NAPI Support" + depends on GIANFAR + +config MV643XX_ETH + tristate "MV-643XX Ethernet support" + depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX + help + This driver supports the gigabit Ethernet on the Marvell MV643XX + chipset which is used in the Momenco Ocelot C and Jaguar ATX. + +config MV643XX_ETH_0 + bool "MV-643XX Port 0" + depends on MV643XX_ETH + help + This enables support for Port 0 of the Marvell MV643XX Gigabit + Ethernet. + +config MV643XX_ETH_1 + bool "MV-643XX Port 1" + depends on MV643XX_ETH + help + This enables support for Port 1 of the Marvell MV643XX Gigabit + Ethernet. + +config MV643XX_ETH_2 + bool "MV-643XX Port 2" + depends on MV643XX_ETH + help + This enables support for Port 2 of the Marvell MV643XX Gigabit + Ethernet. + endmenu # @@ -2145,14 +2132,8 @@ config IXGB depends on PCI ---help--- This driver supports Intel(R) PRO/10GbE family of - adapters, which includes: - - Controller Adapter Name Board IDs - ---------- ------------ --------- - 82597EX Intel(R) PRO/10GbE LR Server Adapter A82505-xxx - - For more information on how to identify your adapter, go to the - Adapter & Driver ID Guide at: + adapters. For more information on how to identify your adapter, go + to the Adapter & Driver ID Guide at: diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 2ae71cf8b..1b6d01932 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -10,6 +10,9 @@ obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_IBM_EMAC) += ibm_emac/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_BONDING) += bonding/ +obj-$(CONFIG_GIANFAR) += gianfar_driver.o + +gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o # # link order important here @@ -95,6 +98,8 @@ obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o +obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o + obj-$(CONFIG_PPP) += ppp_generic.o slhc.o obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o @@ -189,5 +194,6 @@ obj-$(CONFIG_NET_WIRELESS) += wireless/ obj-$(CONFIG_NET_TULIP) += tulip/ obj-$(CONFIG_HAMRADIO) += hamradio/ obj-$(CONFIG_IRDA) += irda/ +obj-$(CONFIG_ETRAX_ETHERNET) += cris/ obj-$(CONFIG_NETCONSOLE) += netconsole.o diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 797e93da6..dbc3ec754 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -284,9 +284,6 @@ static struct devprobe2 m68k_probes[] __initdata = { #ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ {pamsnet_probe, 0}, #endif -#ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ - {hplance_probe, 0}, -#endif #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ {mvme147lance_probe, 0}, #endif diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 0d95f0bf9..8e538a6d7 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -52,8 +52,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 90ed3329a..6eea3a8ac 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -425,13 +426,14 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; MODULE_AUTHOR("Jes Sorensen "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); -MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i"); + +module_param_array(link, int, NULL, 0); +module_param_array(trace, int, NULL, 0); +module_param_array(tx_coal_tick, int, NULL, 0); +module_param_array(max_tx_desc, int, NULL, 0); +module_param_array(rx_coal_tick, int, NULL, 0); +module_param_array(max_rx_desc, int, NULL, 0); +module_param_array(tx_ratio, int, NULL, 0); MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); @@ -441,7 +443,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); -static char version[] __initdata = +static char version[] __devinitdata = "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; @@ -455,6 +457,8 @@ static struct ethtool_ops ace_ethtool_ops = { .get_drvinfo = ace_get_drvinfo, }; +static void ace_watchdog(struct net_device *dev); + static int __devinit acenic_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -474,6 +478,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, ap = dev->priv; ap->pdev = pdev; + ap->name = pci_name(pdev); dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; #if ACENIC_DO_VLAN @@ -482,7 +487,6 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; #endif if (1) { - static void ace_watchdog(struct net_device *dev); dev->tx_timeout = &ace_watchdog; dev->watchdog_timeo = 5*HZ; } @@ -516,7 +520,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { printk(KERN_INFO "%s: Enabling PCI Memory Mapped " "access - was not enabled by BIOS/Firmware\n", - dev->name); + ap->name); ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); @@ -535,59 +539,44 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, * addresses but who gives a damn. */ dev->base_addr = pci_resource_start(pdev, 0); - ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); + ap->regs = ioremap(dev->base_addr, 0x4000); if (!ap->regs) { printk(KERN_ERR "%s: Unable to map I/O register, " "AceNIC %i will be disabled.\n", - dev->name, boards_found); + ap->name, boards_found); goto fail_free_netdev; } switch(pdev->vendor) { case PCI_VENDOR_ID_ALTEON: if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { - strncpy(ap->name, "Farallon PN9100-T " - "Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: Farallon PN9100-T ", - dev->name); + ap->name); } else { - strncpy(ap->name, "AceNIC Gigabit Ethernet", - sizeof (ap->name)); printk(KERN_INFO "%s: Alteon AceNIC ", - dev->name); + ap->name); } break; case PCI_VENDOR_ID_3COM: - strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); + printk(KERN_INFO "%s: 3Com 3C985 ", ap->name); break; case PCI_VENDOR_ID_NETGEAR: - strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: NetGear GA620 ", dev->name); + printk(KERN_INFO "%s: NetGear GA620 ", ap->name); break; case PCI_VENDOR_ID_DEC: if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { - strncpy(ap->name, "Farallon PN9000-SX " - "Gigabit Ethernet", sizeof (ap->name)); printk(KERN_INFO "%s: Farallon PN9000-SX ", - dev->name); + ap->name); break; } case PCI_VENDOR_ID_SGI: - strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: SGI AceNIC ", dev->name); + printk(KERN_INFO "%s: SGI AceNIC ", ap->name); break; default: - strncpy(ap->name, "Unknown AceNIC based Gigabit " - "Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); + printk(KERN_INFO "%s: Unknown AceNIC ", ap->name); break; } - ap->name [sizeof (ap->name) - 1] = '\0'; printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); #ifdef __sparc__ printk("irq %s\n", __irq_itoa(pdev->irq)); @@ -622,6 +611,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, printk(KERN_ERR "acenic: device registration failed\n"); goto fail_uninit; } + ap->name = dev->name; if (ap->pci_using_dac) dev->features |= NETIF_F_HIGHDMA; @@ -641,8 +631,8 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev, static void __devexit acenic_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; short i; unregister_netdev(dev); @@ -752,7 +742,7 @@ module_exit(acenic_exit); static void ace_free_descriptors(struct net_device *dev) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); int size; if (ap->rx_std_ring != NULL) { @@ -802,7 +792,7 @@ static void ace_free_descriptors(struct net_device *dev) static int ace_allocate_descriptors(struct net_device *dev) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); int size; size = (sizeof(struct rx_desc) * @@ -873,7 +863,7 @@ static void ace_init_cleanup(struct net_device *dev) { struct ace_private *ap; - ap = dev->priv; + ap = netdev_priv(dev); ace_free_descriptors(dev); @@ -895,7 +885,7 @@ static void ace_init_cleanup(struct net_device *dev) /* * Commands are considered to be slow. */ -static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd) +static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd) { u32 idx; @@ -908,10 +898,10 @@ static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd) } -static int __init ace_init(struct net_device *dev) +static int __devinit ace_init(struct net_device *dev) { struct ace_private *ap; - struct ace_regs *regs; + struct ace_regs __iomem *regs; struct ace_info *info = NULL; struct pci_dev *pdev; unsigned long myjif; @@ -921,7 +911,7 @@ static int __init ace_init(struct net_device *dev) short i; unsigned char cache_size; - ap = dev->priv; + ap = netdev_priv(dev); regs = ap->regs; board_idx = ap->board_idx; @@ -1329,11 +1319,10 @@ static int __init ace_init(struct net_device *dev) writel(TX_RING_BASE, ®s->WinBase); if (ACE_IS_TIGON_I(ap)) { - ap->tx_ring = (struct tx_desc *)regs->Window; - for (i = 0; i < (TIGON_I_TX_RING_ENTRIES * - sizeof(struct tx_desc) / 4); i++) { - writel(0, (unsigned long)ap->tx_ring + i * 4); - } + ap->tx_ring = (struct tx_desc *) regs->Window; + for (i = 0; i < (TIGON_I_TX_RING_ENTRIES + * sizeof(struct tx_desc)) / sizeof(u32); i++) + writel(0, (void __iomem *)ap->tx_ring + i * 4); set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE); } else { @@ -1387,7 +1376,7 @@ static int __init ace_init(struct net_device *dev) if (board_idx == BOARD_IDX_OVERFLOW) { printk(KERN_WARNING "%s: more than %i NICs detected, " "ignoring module parameters!\n", - dev->name, ACE_MAX_MOD_PARMS); + ap->name, ACE_MAX_MOD_PARMS); } else if (board_idx >= 0) { if (tx_coal_tick[board_idx]) writel(tx_coal_tick[board_idx], @@ -1426,7 +1415,7 @@ static int __init ace_init(struct net_device *dev) if (option & 0x01) { printk(KERN_INFO "%s: Setting half duplex link\n", - dev->name); + ap->name); tmp &= ~LNK_FULL_DUPLEX; } if (option & 0x02) @@ -1439,7 +1428,7 @@ static int __init ace_init(struct net_device *dev) tmp |= LNK_1000MB; if ((option & 0x70) == 0) { printk(KERN_WARNING "%s: No media speed specified, " - "forcing auto negotiation\n", dev->name); + "forcing auto negotiation\n", ap->name); tmp |= LNK_NEGOTIATE | LNK_1000MB | LNK_100MB | LNK_10MB; } @@ -1447,12 +1436,12 @@ static int __init ace_init(struct net_device *dev) tmp |= LNK_NEG_FCTL; else printk(KERN_INFO "%s: Disabling flow control " - "negotiation\n", dev->name); + "negotiation\n", ap->name); if (option & 0x200) tmp |= LNK_RX_FLOW_CTL_Y; if ((option & 0x400) && (ap->version >= 2)) { printk(KERN_INFO "%s: Enabling TX flow control\n", - dev->name); + ap->name); tmp |= LNK_TX_FLOW_CTL_Y; } } @@ -1509,7 +1498,7 @@ static int __init ace_init(struct net_device *dev) cpu_relax(); if (!ap->fw_running) { - printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name); + printk(KERN_ERR "%s: Firmware NOT running!\n", ap->name); ace_dump_trace(ap); writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); @@ -1542,13 +1531,13 @@ static int __init ace_init(struct net_device *dev) ace_load_std_rx_ring(ap, RX_RING_SIZE); else printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n", - dev->name); + ap->name); if (ap->version >= 2) { if (!test_and_set_bit(0, &ap->mini_refill_busy)) ace_load_mini_rx_ring(ap, RX_MINI_SIZE); else printk(KERN_ERR "%s: Someone is busy refilling " - "the RX mini ring\n", dev->name); + "the RX mini ring\n", ap->name); } return 0; @@ -1560,14 +1549,9 @@ static int __init ace_init(struct net_device *dev) static void ace_set_rxtx_parms(struct net_device *dev, int jumbo) { - struct ace_private *ap; - struct ace_regs *regs; - int board_idx; - - ap = dev->priv; - regs = ap->regs; - - board_idx = ap->board_idx; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; + int board_idx = ap->board_idx; if (board_idx >= 0) { if (!jumbo) { @@ -1604,8 +1588,8 @@ static void ace_set_rxtx_parms(struct net_device *dev, int jumbo) static void ace_watchdog(struct net_device *data) { struct net_device *dev = data; - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; /* * We haven't received a stats update event for more than 2.5 @@ -1628,7 +1612,7 @@ static void ace_watchdog(struct net_device *data) static void ace_tasklet(unsigned long dev) { - struct ace_private *ap = ((struct net_device *)dev)->priv; + struct ace_private *ap = netdev_priv((struct net_device *)dev); int cur_size; cur_size = atomic_read(&ap->cur_rx_bufs); @@ -1686,10 +1670,9 @@ static void ace_dump_trace(struct ace_private *ap) */ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs) { - struct ace_regs *regs; + struct ace_regs __iomem *regs = ap->regs; short i, idx; - - regs = ap->regs; + prefetchw(&ap->cur_rx_bufs); @@ -1750,11 +1733,9 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs) static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs) { - struct ace_regs *regs; + struct ace_regs __iomem *regs = ap->regs; short i, idx; - regs = ap->regs; - prefetchw(&ap->cur_mini_bufs); idx = ap->rx_mini_skbprd; @@ -1809,11 +1790,9 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs) */ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs) { - struct ace_regs *regs; + struct ace_regs __iomem *regs = ap->regs; short i, idx; - regs = ap->regs; - idx = ap->rx_jumbo_skbprd; for (i = 0; i < nr_bufs; i++) { @@ -1878,13 +1857,13 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) { struct ace_private *ap; - ap = dev->priv; + ap = netdev_priv(dev); while (evtcsm != evtprd) { switch (ap->evt_ring[evtcsm].evt) { case E_FW_RUNNING: printk(KERN_INFO "%s: Firmware up and running\n", - dev->name); + ap->name); ap->fw_running = 1; wmb(); break; @@ -1899,7 +1878,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) u32 state = readl(&ap->regs->GigLnkState); printk(KERN_WARNING "%s: Optical link UP " "(%s Duplex, Flow Control: %s%s)\n", - dev->name, + ap->name, state & LNK_FULL_DUPLEX ? "Full":"Half", state & LNK_TX_FLOW_CTL_Y ? "TX " : "", state & LNK_RX_FLOW_CTL_Y ? "RX" : ""); @@ -1907,15 +1886,15 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) } case E_C_LINK_DOWN: printk(KERN_WARNING "%s: Optical link DOWN\n", - dev->name); + ap->name); break; case E_C_LINK_10_100: printk(KERN_WARNING "%s: 10/100BaseT link " - "UP\n", dev->name); + "UP\n", ap->name); break; default: printk(KERN_ERR "%s: Unknown optical link " - "state %02x\n", dev->name, code); + "state %02x\n", ap->name, code); } break; } @@ -1923,19 +1902,19 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) switch(ap->evt_ring[evtcsm].code) { case E_C_ERR_INVAL_CMD: printk(KERN_ERR "%s: invalid command error\n", - dev->name); + ap->name); break; case E_C_ERR_UNIMP_CMD: printk(KERN_ERR "%s: unimplemented command " - "error\n", dev->name); + "error\n", ap->name); break; case E_C_ERR_BAD_CFG: printk(KERN_ERR "%s: bad config error\n", - dev->name); + ap->name); break; default: printk(KERN_ERR "%s: unknown error %02x\n", - dev->name, ap->evt_ring[evtcsm].code); + ap->name, ap->evt_ring[evtcsm].code); } break; case E_RESET_JUMBO_RNG: @@ -1964,13 +1943,13 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) ap->jumbo = 0; ap->rx_jumbo_skbprd = 0; printk(KERN_INFO "%s: Jumbo ring flushed\n", - dev->name); + ap->name); clear_bit(0, &ap->jumbo_refill_busy); break; } default: printk(KERN_ERR "%s: Unhandled event 0x%02x\n", - dev->name, ap->evt_ring[evtcsm].evt); + ap->name, ap->evt_ring[evtcsm].evt); } evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES; } @@ -1981,7 +1960,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); u32 idx; int mini_count = 0, std_count = 0; @@ -2093,8 +2072,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) * the 12.3.x Firmware - my Tigon I NICs seem to disagree! */ if (ACE_IS_TIGON_I(ap)) { - struct ace_regs *regs = ap->regs; - writel(idx, ®s->RxRetCsm); + writel(idx, &ap->regs->RxRetCsm); } ap->cur_rx = idx; @@ -2108,7 +2086,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) static inline void ace_tx_int(struct net_device *dev, u32 txcsm, u32 idx) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); do { struct sk_buff *skb; @@ -2174,16 +2152,13 @@ static inline void ace_tx_int(struct net_device *dev, static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { - struct ace_private *ap; - struct ace_regs *regs; struct net_device *dev = (struct net_device *)dev_id; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; u32 idx; u32 txcsm, rxretcsm, rxretprd; u32 evtcsm, evtprd; - ap = dev->priv; - regs = ap->regs; - /* * In case of PCI shared interrupts or spurious interrupts, * we want to make sure it is actually our interrupt before @@ -2304,7 +2279,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) #if ACENIC_DO_VLAN static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); unsigned long flags; local_irq_save(flags); @@ -2319,7 +2294,7 @@ static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); unsigned long flags; local_irq_save(flags); @@ -2336,13 +2311,10 @@ static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) static int ace_open(struct net_device *dev) { - struct ace_private *ap; - struct ace_regs *regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; struct cmd cmd; - ap = dev->priv; - regs = ap->regs; - if (!(ap->fw_running)) { printk(KERN_WARNING "%s: Firmware not running!\n", dev->name); return -EBUSY; @@ -2394,8 +2366,8 @@ static int ace_open(struct net_device *dev) static int ace_close(struct net_device *dev) { - struct ace_private *ap; - struct ace_regs *regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; struct cmd cmd; unsigned long flags; short i; @@ -2407,9 +2379,7 @@ static int ace_close(struct net_device *dev) */ netif_stop_queue(dev); - ap = dev->priv; - regs = ap->regs; - + if (ap->promisc) { cmd.evt = C_SET_PROMISC_MODE; cmd.code = C_C_PROMISC_DISABLE; @@ -2444,9 +2414,11 @@ static int ace_close(struct net_device *dev) if (mapping) { if (ACE_IS_TIGON_I(ap)) { - writel(0, &ap->tx_ring[i].addr.addrhi); - writel(0, &ap->tx_ring[i].addr.addrlo); - writel(0, &ap->tx_ring[i].flagsize); + struct tx_desc __iomem *tx + = (struct tx_desc __iomem *) &ap->tx_ring[i]; + writel(0, &tx->addr.addrhi); + writel(0, &tx->addr.addrlo); + writel(0, &tx->flagsize); } else memset(ap->tx_ring + i, 0, sizeof(struct tx_desc)); @@ -2503,11 +2475,12 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr, #endif if (ACE_IS_TIGON_I(ap)) { - writel(addr >> 32, &desc->addr.addrhi); - writel(addr & 0xffffffff, &desc->addr.addrlo); - writel(flagsize, &desc->flagsize); + struct tx_desc __iomem *io = (struct tx_desc __iomem *) desc; + writel(addr >> 32, &io->addr.addrhi); + writel(addr & 0xffffffff, &io->addr.addrlo); + writel(flagsize, &io->flagsize); #if ACENIC_DO_VLAN - writel(vlan_tag, &desc->vlanres); + writel(vlan_tag, &io->vlanres); #endif } else { desc->addr.addrhi = addr >> 32; @@ -2522,10 +2495,11 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr, static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; struct tx_desc *desc; u32 idx, flagsize; + unsigned long maxjiff = jiffies + 3*HZ; restart: idx = ap->tx_prd; @@ -2533,10 +2507,7 @@ restart: if (tx_ring_full(ap, ap->tx_ret_csm, idx)) goto overflow; -#if MAX_SKB_FRAGS - if (!skb_shinfo(skb)->nr_frags) -#endif - { + if (!skb_shinfo(skb)->nr_frags) { dma_addr_t mapping; u32 vlan_tag = 0; @@ -2558,9 +2529,7 @@ restart: flagsize |= BD_FLG_COAL_NOW; ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag); - } -#if MAX_SKB_FRAGS - else { + } else { dma_addr_t mapping; u32 vlan_tag = 0; int i, len = 0; @@ -2615,7 +2584,6 @@ restart: ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag); } } -#endif wmb(); ap->tx_prd = idx; @@ -2635,7 +2603,7 @@ restart: } dev->trans_start = jiffies; - return 0; + return NETDEV_TX_OK; overflow: /* @@ -2654,15 +2622,22 @@ overflow: * Alternative is to return with 1 not throttling queue. In this * case loop becomes longer, no more useful effects. */ - barrier(); - goto restart; + if (time_before(jiffies, maxjiff)) { + barrier(); + cpu_relax(); + goto restart; + } + + /* The ring is stuck full. */ + printk(KERN_WARNING "%s: Transmit ring stuck full\n", dev->name); + return NETDEV_TX_BUSY; } static int ace_change_mtu(struct net_device *dev, int new_mtu) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; if (new_mtu > ACE_JUMBO_MTU) return -EINVAL; @@ -2698,8 +2673,8 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu) static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; u32 link; memset(ecmd, 0, sizeof(struct ethtool_cmd)); @@ -2751,8 +2726,8 @@ static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; u32 link, speed; link = readl(®s->GigLnkState); @@ -2814,7 +2789,7 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) static void ace_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct ace_private *ap = dev->priv; + struct ace_private *ap = netdev_priv(dev); strlcpy(info->driver, "acenic", sizeof(info->driver)); snprintf(info->version, sizeof(info->version), "%i.%i.%i", @@ -2832,8 +2807,9 @@ static void ace_get_drvinfo(struct net_device *dev, */ static int ace_set_mac_addr(struct net_device *dev, void *p) { + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; struct sockaddr *addr=p; - struct ace_regs *regs; u8 *da; struct cmd cmd; @@ -2844,7 +2820,6 @@ static int ace_set_mac_addr(struct net_device *dev, void *p) da = (u8 *)dev->dev_addr; - regs = ((struct ace_private *)dev->priv)->regs; writel(da[0] << 8 | da[1], ®s->MacAddrHi); writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5], ®s->MacAddrLo); @@ -2860,8 +2835,8 @@ static int ace_set_mac_addr(struct net_device *dev, void *p) static void ace_set_multicast_list(struct net_device *dev) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; struct cmd cmd; if ((dev->flags & IFF_ALLMULTI) && !(ap->mcast_all)) { @@ -2914,9 +2889,9 @@ static void ace_set_multicast_list(struct net_device *dev) static struct net_device_stats *ace_get_stats(struct net_device *dev) { - struct ace_private *ap = dev->priv; - struct ace_mac_stats *mac_stats = - (struct ace_mac_stats *)ap->regs->Stats; + struct ace_private *ap = netdev_priv(dev); + struct ace_mac_stats __iomem *mac_stats = + (struct ace_mac_stats __iomem *)ap->regs->Stats; ap->stats.rx_missed_errors = readl(&mac_stats->drop_space); ap->stats.multicast = readl(&mac_stats->kept_mc); @@ -2926,10 +2901,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) } -static void __init ace_copy(struct ace_regs *regs, void *src, +static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, u32 dest, int size) { - unsigned long tdest; + void __iomem *tdest; u32 *wsrc; short tsize, i; @@ -2939,7 +2914,7 @@ static void __init ace_copy(struct ace_regs *regs, void *src, while (size > 0) { tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), min_t(u32, size, ACE_WINDOW_SIZE)); - tdest = (unsigned long)®s->Window + + tdest = (void __iomem *) ®s->Window + (dest & (ACE_WINDOW_SIZE - 1)); writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); /* @@ -2959,9 +2934,9 @@ static void __init ace_copy(struct ace_regs *regs, void *src, } -static void __init ace_clear(struct ace_regs *regs, u32 dest, int size) +static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size) { - unsigned long tdest; + void __iomem *tdest; short tsize = 0, i; if (size <= 0) @@ -2970,7 +2945,7 @@ static void __init ace_clear(struct ace_regs *regs, u32 dest, int size) while (size > 0) { tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1), min_t(u32, size, ACE_WINDOW_SIZE)); - tdest = (unsigned long)®s->Window + + tdest = (void __iomem *) ®s->Window + (dest & (ACE_WINDOW_SIZE - 1)); writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); @@ -2992,17 +2967,14 @@ static void __init ace_clear(struct ace_regs *regs, u32 dest, int size) * This operation requires the NIC to be halted and is performed with * interrupts disabled and with the spinlock hold. */ -int __init ace_load_firmware(struct net_device *dev) +int __devinit ace_load_firmware(struct net_device *dev) { - struct ace_private *ap; - struct ace_regs *regs; - - ap = dev->priv; - regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { printk(KERN_ERR "%s: trying to download firmware while the " - "CPU is running!\n", dev->name); + "CPU is running!\n", ap->name); return -EFAULT; } @@ -3046,7 +3018,7 @@ int __init ace_load_firmware(struct net_device *dev) * Thanks to Stevarino Webinski for helping tracking down the bugs in the * code i2c readout code by beta testing all my hacks. */ -static void __init eeprom_start(struct ace_regs *regs) +static void __devinit eeprom_start(struct ace_regs __iomem *regs) { u32 local; @@ -3075,7 +3047,7 @@ static void __init eeprom_start(struct ace_regs *regs) } -static void __init eeprom_prep(struct ace_regs *regs, u8 magic) +static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic) { short i; u32 local; @@ -3112,7 +3084,7 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic) } -static int __init eeprom_check_ack(struct ace_regs *regs) +static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs) { int state; u32 local; @@ -3140,7 +3112,7 @@ static int __init eeprom_check_ack(struct ace_regs *regs) } -static void __init eeprom_stop(struct ace_regs *regs) +static void __devinit eeprom_stop(struct ace_regs __iomem *regs) { u32 local; @@ -3175,10 +3147,11 @@ static void __init eeprom_stop(struct ace_regs *regs) /* * Read a whole byte from the EEPROM. */ -static int __init read_eeprom_byte(struct net_device *dev, +static int __devinit read_eeprom_byte(struct net_device *dev, unsigned long offset) { - struct ace_regs *regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; unsigned long flags; u32 local; int result = 0; @@ -3187,11 +3160,9 @@ static int __init read_eeprom_byte(struct net_device *dev, if (!dev) { printk(KERN_ERR "No device!\n"); result = -ENODEV; - goto eeprom_read_error; + goto out; } - regs = ((struct ace_private *)dev->priv)->regs; - /* * Don't take interrupts on this CPU will bit banging * the %#%#@$ I2C device @@ -3203,7 +3174,7 @@ static int __init read_eeprom_byte(struct net_device *dev, eeprom_prep(regs, EEPROM_WRITE_SELECT); if (eeprom_check_ack(regs)) { local_irq_restore(flags); - printk(KERN_ERR "%s: Unable to sync eeprom\n", dev->name); + printk(KERN_ERR "%s: Unable to sync eeprom\n", ap->name); result = -EIO; goto eeprom_read_error; } @@ -3212,7 +3183,7 @@ static int __init read_eeprom_byte(struct net_device *dev, if (eeprom_check_ack(regs)) { local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set address byte 0\n", - dev->name); + ap->name); result = -EIO; goto eeprom_read_error; } @@ -3221,7 +3192,7 @@ static int __init read_eeprom_byte(struct net_device *dev, if (eeprom_check_ack(regs)) { local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set address byte 1\n", - dev->name); + ap->name); result = -EIO; goto eeprom_read_error; } @@ -3231,7 +3202,7 @@ static int __init read_eeprom_byte(struct net_device *dev, if (eeprom_check_ack(regs)) { local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set READ_SELECT\n", - dev->name); + ap->name); result = -EIO; goto eeprom_read_error; } @@ -3288,7 +3259,7 @@ static int __init read_eeprom_byte(struct net_device *dev, eeprom_read_error: printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n", - dev->name, offset); + ap->name, offset); goto out; } diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index c4624b85d..a97107023 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -10,11 +10,6 @@ */ #define USE_TX_COAL_NOW 0 -#ifndef MAX_SKB_FRAGS -#define MAX_SKB_FRAGS 0 -#endif - - /* * Addressing: * @@ -638,7 +633,7 @@ struct ace_skb struct ace_private { struct ace_info *info; - struct ace_regs *regs; /* register base */ + struct ace_regs __iomem *regs; /* register base */ struct ace_skb *skb; dma_addr_t info_dma; /* 32/64 bit */ @@ -693,7 +688,7 @@ struct ace_private int board_idx; u16 pci_command; u8 pci_latency; - char name[48]; + const char *name; #ifdef INDEX_DEBUG spinlock_t debug_lock __attribute__ ((aligned (SMP_CACHE_BYTES))); @@ -712,13 +707,7 @@ static inline int tx_space (struct ace_private *ap, u32 csm, u32 prd) } #define tx_free(ap) tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap) - -#if MAX_SKB_FRAGS #define tx_ring_full(ap, csm, prd) (tx_space(ap, csm, prd) <= TX_RESERVED) -#else -#define tx_ring_full 0 -#endif - static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr) { @@ -729,7 +718,7 @@ static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr) } -static inline void ace_set_txprd(struct ace_regs *regs, +static inline void ace_set_txprd(struct ace_regs __iomem *regs, struct ace_private *ap, u32 value) { #ifdef INDEX_DEBUG @@ -750,8 +739,8 @@ static inline void ace_set_txprd(struct ace_regs *regs, static inline void ace_mask_irq(struct net_device *dev) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; if (ACE_IS_TIGON_I(ap)) writel(1, ®s->MaskInt); @@ -764,8 +753,8 @@ static inline void ace_mask_irq(struct net_device *dev) static inline void ace_unmask_irq(struct net_device *dev) { - struct ace_private *ap = dev->priv; - struct ace_regs *regs = ap->regs; + struct ace_private *ap = netdev_priv(dev); + struct ace_regs __iomem *regs = ap->regs; if (ACE_IS_TIGON_I(ap)) writel(0, ®s->MaskInt); diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h index 3fbfb7ad1..6d625d595 100644 --- a/drivers/net/acenic_firmware.h +++ b/drivers/net/acenic_firmware.h @@ -23,7 +23,7 @@ #define tigonFwRodata NULL #else /* Generated by genfw.c */ -static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { +static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = { 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000, diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index ca57a7a53..89183239b 100755 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -124,7 +124,7 @@ This function will read the PHY registers. */ static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val) { - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; unsigned int reg_val; unsigned int repeat= REPEAT_CNT; @@ -155,7 +155,7 @@ This function will write into PHY registers. static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val) { unsigned int repeat = REPEAT_CNT - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; unsigned int reg_val; reg_val = readl(mmio + PHY_ACCESS); @@ -211,7 +211,7 @@ static void amd8111e_set_ext_phy(struct net_device *dev) u32 bmcr,advert,tmp; /* Determine mii register values to set the speed */ - advert = amd8111e_mdio_read(dev, PHY_ID, MII_ADVERTISE); + advert = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_ADVERTISE); tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); switch (lp->ext_phy_option){ @@ -235,11 +235,11 @@ static void amd8111e_set_ext_phy(struct net_device *dev) } if(advert != tmp) - amd8111e_mdio_write(dev, PHY_ID, MII_ADVERTISE, tmp); + amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_ADVERTISE, tmp); /* Restart auto negotiation */ - bmcr = amd8111e_mdio_read(dev, PHY_ID, MII_BMCR); + bmcr = amd8111e_mdio_read(dev, lp->ext_phy_addr, MII_BMCR); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); - amd8111e_mdio_write(dev, PHY_ID, MII_BMCR, bmcr); + amd8111e_mdio_write(dev, lp->ext_phy_addr, MII_BMCR, bmcr); } @@ -350,6 +350,7 @@ static int amd8111e_init_ring(struct net_device *dev) lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]); lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2); + wmb(); lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT); } @@ -384,7 +385,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod) unsigned int event_count; struct amd8111e_priv *lp = netdev_priv(dev); - void* mmio = lp->mmio; + void __iomem *mmio = lp->mmio; struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf; @@ -442,7 +443,7 @@ This function initializes the device registers and starts the device. static int amd8111e_restart(struct net_device *dev) { struct amd8111e_priv *lp = netdev_priv(dev); - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; int i,reg_val; /* stop the chip */ @@ -522,14 +523,14 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp) { unsigned int reg_val; unsigned int logic_filter[2] ={0,}; - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; /* stop the chip */ writel(RUN, mmio + CMD0); /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */ - writew( 0x8101, mmio + AUTOPOLL0); + writew( 0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0); /* Clear RCV_RING_BASE_ADDR */ writel(0, mmio + RCV_RING_BASE_ADDR0); @@ -719,13 +720,13 @@ static int amd8111e_tx(struct net_device *dev) return 0; } -#if CONFIG_AMD8111E_NAPI +#ifdef CONFIG_AMD8111E_NAPI /* This function handles the driver receive operation in polling mode */ static int amd8111e_rx_poll(struct net_device *dev, int * budget) { - struct amd8111e_priv *lp = dev->priv; + struct amd8111e_priv *lp = netdev_priv(dev); int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK; - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; struct sk_buff *skb,*new_skb; int min_pkt_len, status; unsigned int intr0; @@ -740,11 +741,11 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) do{ /* process receive packets until we use the quota*/ /* If we own the next entry, it's a new packet. Send it up. */ - while(!(lp->rx_ring[rx_index].rx_flags & OWN_BIT)){ - - /* check if err summary bit is set */ - if(le16_to_cpu(lp->rx_ring[rx_index].rx_flags) - & ERR_BIT){ + while(1) { + status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); + if (status & OWN_BIT) + break; + /* * There is a tricky error noted by John Murphy, * to Russ Nelson: Even with @@ -753,89 +754,88 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget) * the last correctly noting the error. */ - /* reseting flags */ - lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS; - goto err_next_pkt; - + if(status & ERR_BIT) { + /* reseting flags */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + goto err_next_pkt; } /* check for STP and ENP */ - status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); - if(!((status & STP_BIT) && (status & ENP_BIT))){ - /* reseting flags */ - lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS; - goto err_next_pkt; - } - pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; + if(!((status & STP_BIT) && (status & ENP_BIT))){ + /* reseting flags */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + goto err_next_pkt; + } + pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; #if AMD8111E_VLAN_TAG_USED - vtag = le16_to_cpu(lp->rx_ring[rx_index].rx_flags) & TT_MASK; - /*MAC will strip vlan tag*/ - if(lp->vlgrp != NULL && vtag !=0) - min_pkt_len =MIN_PKT_LEN - 4; - else + vtag = status & TT_MASK; + /*MAC will strip vlan tag*/ + if(lp->vlgrp != NULL && vtag !=0) + min_pkt_len =MIN_PKT_LEN - 4; + else #endif - min_pkt_len =MIN_PKT_LEN; + min_pkt_len =MIN_PKT_LEN; - if (pkt_len < min_pkt_len) { - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - lp->drv_rx_errors++; - goto err_next_pkt; - } - if(--rx_pkt_limit < 0) - goto rx_not_empty; - if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){ - /* if allocation fail, - ignore that pkt and go to next one */ - lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; - lp->drv_rx_errors++; - goto err_next_pkt; - } + if (pkt_len < min_pkt_len) { + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + lp->drv_rx_errors++; + goto err_next_pkt; + } + if(--rx_pkt_limit < 0) + goto rx_not_empty; + if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){ + /* if allocation fail, + ignore that pkt and go to next one */ + lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; + lp->drv_rx_errors++; + goto err_next_pkt; + } - skb_reserve(new_skb, 2); - skb = lp->rx_skbuff[rx_index]; - pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index], - lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_len); - skb->dev = dev; - lp->rx_skbuff[rx_index] = new_skb; - new_skb->dev = dev; - lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev, - new_skb->data, lp->rx_buff_len-2,PCI_DMA_FROMDEVICE); - - skb->protocol = eth_type_trans(skb, dev); + skb_reserve(new_skb, 2); + skb = lp->rx_skbuff[rx_index]; + pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index], + lp->rx_buff_len-2, PCI_DMA_FROMDEVICE); + skb_put(skb, pkt_len); + skb->dev = dev; + lp->rx_skbuff[rx_index] = new_skb; + new_skb->dev = dev; + lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev, + new_skb->data, + lp->rx_buff_len-2, + PCI_DMA_FROMDEVICE); + + skb->protocol = eth_type_trans(skb, dev); #if AMD8111E_VLAN_TAG_USED - - vtag = lp->rx_ring[rx_index].rx_flags & TT_MASK; - if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){ - amd8111e_vlan_rx(lp, skb, - lp->rx_ring[rx_index].tag_ctrl_info); - } else + if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){ + amd8111e_vlan_rx(lp, skb, + le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info)); + } else #endif - - netif_receive_skb(skb); - /*COAL update rx coalescing parameters*/ - lp->coal_conf.rx_packets++; - lp->coal_conf.rx_bytes += pkt_len; - num_rx_pkt++; - dev->last_rx = jiffies; + netif_receive_skb(skb); + /*COAL update rx coalescing parameters*/ + lp->coal_conf.rx_packets++; + lp->coal_conf.rx_bytes += pkt_len; + num_rx_pkt++; + dev->last_rx = jiffies; -err_next_pkt: - lp->rx_ring[rx_index].buff_phy_addr - = cpu_to_le32(lp->rx_dma_addr[rx_index]); - lp->rx_ring[rx_index].buff_count = + err_next_pkt: + lp->rx_ring[rx_index].buff_phy_addr + = cpu_to_le32(lp->rx_dma_addr[rx_index]); + lp->rx_ring[rx_index].buff_count = cpu_to_le16(lp->rx_buff_len-2); - lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); - rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; - } - /* Check the interrupt status register for more packets in the - mean time. Process them since we have not used up our quota.*/ + wmb(); + lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); + rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; + } + /* Check the interrupt status register for more packets in the + mean time. Process them since we have not used up our quota.*/ - intr0 = readl(mmio + INT0); - /*Ack receive packets */ - writel(intr0 & RINT0,mmio + INT0); + intr0 = readl(mmio + INT0); + /*Ack receive packets */ + writel(intr0 & RINT0,mmio + INT0); - }while(intr0 & RINT0); + } while(intr0 & RINT0); /* Receive descriptor is empty now */ dev->quota -= num_rx_pkt; @@ -873,11 +873,12 @@ static int amd8111e_rx(struct net_device *dev) /* If we own the next entry, it's a new packet. Send it up. */ while(++num_rx_pkt <= max_rx_pkt){ - if(lp->rx_ring[rx_index].rx_flags & OWN_BIT) + status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); + if(status & OWN_BIT) return 0; /* check if err summary bit is set */ - if(le16_to_cpu(lp->rx_ring[rx_index].rx_flags) & ERR_BIT){ + if(status & ERR_BIT){ /* * There is a tricky error noted by John Murphy, * to Russ Nelson: Even with full-sized @@ -888,7 +889,6 @@ static int amd8111e_rx(struct net_device *dev) goto err_next_pkt; } /* check for STP and ENP */ - status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags); if(!((status & STP_BIT) && (status & ENP_BIT))){ /* reseting flags */ lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS; @@ -897,7 +897,7 @@ static int amd8111e_rx(struct net_device *dev) pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4; #if AMD8111E_VLAN_TAG_USED - vtag = le16_to_cpu(lp->rx_ring[rx_index].rx_flags) & TT_MASK; + vtag = status & TT_MASK; /*MAC will strip vlan tag*/ if(lp->vlgrp != NULL && vtag !=0) min_pkt_len =MIN_PKT_LEN - 4; @@ -931,12 +931,10 @@ static int amd8111e_rx(struct net_device *dev) skb->protocol = eth_type_trans(skb, dev); -#if AMD8111E_VLAN_TAG_USED - - vtag = lp->rx_ring[rx_index].rx_flags & TT_MASK; +#if AMD8111E_VLAN_TAG_USED if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){ amd8111e_vlan_rx(lp, skb, - lp->rx_ring[rx_index].tag_ctrl_info); + le16_to_cpu(lp->rx_ring[rx_index].tag_ctrl_info)); } else #endif @@ -952,6 +950,7 @@ err_next_pkt: = cpu_to_le32(lp->rx_dma_addr[rx_index]); lp->rx_ring[rx_index].buff_count = cpu_to_le16(lp->rx_buff_len-2); + wmb(); lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT); rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK; } @@ -1004,7 +1003,7 @@ static int amd8111e_link_change(struct net_device* dev) /* This function reads the mib counters. */ -static int amd8111e_read_mib(void* mmio, u8 MIB_COUNTER) +static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER) { unsigned int status; unsigned int data; @@ -1027,7 +1026,7 @@ This function reads the mib registers and returns the hardware statistics. It u static struct net_device_stats *amd8111e_get_stats(struct net_device * dev) { struct amd8111e_priv *lp = netdev_priv(dev); - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; unsigned long flags; /* struct net_device_stats *prev_stats = &lp->prev_stats; */ struct net_device_stats* new_stats = &lp->stats; @@ -1260,7 +1259,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg struct net_device * dev = (struct net_device *) dev_id; struct amd8111e_priv *lp = netdev_priv(dev); - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; unsigned int intr0; unsigned int handled = 1; @@ -1432,7 +1431,7 @@ static int amd8111e_start_xmit(struct sk_buff *skb, struct net_device * dev) #if AMD8111E_VLAN_TAG_USED if((lp->vlgrp != NULL) && vlan_tx_tag_present(skb)){ lp->tx_ring[tx_index].tag_ctrl_cmd |= - cpu_to_le32(TCC_VLAN_INSERT); + cpu_to_le16(TCC_VLAN_INSERT); lp->tx_ring[tx_index].tag_ctrl_info = cpu_to_le16(vlan_tx_tag_get(skb)); @@ -1444,6 +1443,7 @@ static int amd8111e_start_xmit(struct sk_buff *skb, struct net_device * dev) (u32) cpu_to_le32(lp->tx_dma_addr[tx_index]); /* Set FCS and LTINT bits */ + wmb(); lp->tx_ring[tx_index].tx_flags |= cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT|ADD_FCS_BIT|LTINT_BIT); @@ -1464,32 +1464,25 @@ static int amd8111e_start_xmit(struct sk_buff *skb, struct net_device * dev) /* This function returns all the memory mapped registers of the device. */ -static char* amd8111e_read_regs(struct amd8111e_priv* lp) -{ - void * mmio = lp->mmio; - u32 * reg_buff; - - reg_buff = kmalloc( AMD8111E_REG_DUMP_LEN,GFP_KERNEL); - if(NULL == reg_buff) - return NULL; - +static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf) +{ + void __iomem *mmio = lp->mmio; /* Read only necessary registers */ - reg_buff[0] = readl(mmio + XMT_RING_BASE_ADDR0); - reg_buff[1] = readl(mmio + XMT_RING_LEN0); - reg_buff[2] = readl(mmio + RCV_RING_BASE_ADDR0); - reg_buff[3] = readl(mmio + RCV_RING_LEN0); - reg_buff[4] = readl(mmio + CMD0); - reg_buff[5] = readl(mmio + CMD2); - reg_buff[6] = readl(mmio + CMD3); - reg_buff[7] = readl(mmio + CMD7); - reg_buff[8] = readl(mmio + INT0); - reg_buff[9] = readl(mmio + INTEN0); - reg_buff[10] = readl(mmio + LADRF); - reg_buff[11] = readl(mmio + LADRF+4); - reg_buff[12] = readl(mmio + STAT0); - - return (char *)reg_buff; + buf[0] = readl(mmio + XMT_RING_BASE_ADDR0); + buf[1] = readl(mmio + XMT_RING_LEN0); + buf[2] = readl(mmio + RCV_RING_BASE_ADDR0); + buf[3] = readl(mmio + RCV_RING_LEN0); + buf[4] = readl(mmio + CMD0); + buf[5] = readl(mmio + CMD2); + buf[6] = readl(mmio + CMD3); + buf[7] = readl(mmio + CMD7); + buf[8] = readl(mmio + INT0); + buf[9] = readl(mmio + INTEN0); + buf[10] = readl(mmio + LADRF); + buf[11] = readl(mmio + LADRF+4); + buf[12] = readl(mmio + STAT0); } + /* amd8111e crc generator implementation is different from the kernel ether_crc() function. @@ -1567,131 +1560,101 @@ static void amd8111e_set_multicast_list(struct net_device *dev) } -/* -This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. -*/ - -static int amd8111e_ethtool_ioctl(struct net_device* dev, void __user *useraddr) +static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info) { struct amd8111e_priv *lp = netdev_priv(dev); struct pci_dev *pci_dev = lp->pci_dev; - u32 ethcmd; - - if( useraddr == NULL) + strcpy (info->driver, MODULE_NAME); + strcpy (info->version, MODULE_VERS); + sprintf(info->fw_version,"%u",chip_version); + strcpy (info->bus_info, pci_name(pci_dev)); +} + +static int amd8111e_get_regs_len(struct net_device *dev) +{ + return AMD8111E_REG_DUMP_LEN; +} + +static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + regs->version = 0; + amd8111e_read_regs(lp, buf); +} + +static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + spin_lock_irq(&lp->lock); + mii_ethtool_gset(&lp->mii_if, ecmd); + spin_unlock_irq(&lp->lock); + return 0; +} + +static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + int res; + spin_lock_irq(&lp->lock); + res = mii_ethtool_sset(&lp->mii_if, ecmd); + spin_unlock_irq(&lp->lock); + return res; +} + +static int amd8111e_nway_reset(struct net_device *dev) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + return mii_nway_restart(&lp->mii_if); +} + +static u32 amd8111e_get_link(struct net_device *dev) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + return mii_link_ok(&lp->mii_if); +} + +static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + wol_info->supported = WAKE_MAGIC|WAKE_PHY; + if (lp->options & OPTION_WOL_ENABLE) + wol_info->wolopts = WAKE_MAGIC; +} + +static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY)) return -EINVAL; - if(copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch(ethcmd){ - - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, MODULE_NAME); - strcpy (info.version, MODULE_VERS); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - sprintf(info.fw_version,"%u",chip_version); - strcpy (info.bus_info, pci_name(pci_dev)); - info.eedump_len = 0; - info.regdump_len = AMD8111E_REG_DUMP_LEN; - if (copy_to_user (useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - mii_ethtool_gset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; + spin_lock_irq(&lp->lock); + if (wol_info->wolopts & WAKE_MAGIC) + lp->options |= + (OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE); + else if(wol_info->wolopts & WAKE_PHY) + lp->options |= + (OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE); + else + lp->options &= ~OPTION_WOL_ENABLE; + spin_unlock_irq(&lp->lock); + return 0; +} - spin_lock_irq(&lp->lock); - r = mii_ethtool_sset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - return r; - } - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - u8 *regbuf; - int ret; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - if (regs.len > AMD8111E_REG_DUMP_LEN) - regs.len = AMD8111E_REG_DUMP_LEN; - regs.version = 0; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - return -EFAULT; - - regbuf = amd8111e_read_regs(lp); - if (!regbuf) - return -ENOMEM; - - useraddr += offsetof(struct ethtool_regs, data); - ret = 0; - if (copy_to_user(useraddr, regbuf, regs.len)) - ret = -EFAULT; - kfree(regbuf); - return ret; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&lp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value val = {ETHTOOL_GLINK}; - val.data = mii_link_ok(&lp->mii_if); - if (copy_to_user(useraddr, &val, sizeof(val))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol_info = { ETHTOOL_GWOL }; - - wol_info.supported = WAKE_MAGIC|WAKE_PHY; - wol_info.wolopts = 0; - if (lp->options & OPTION_WOL_ENABLE) - wol_info.wolopts = WAKE_MAGIC; - memset(&wol_info.sopass, 0, sizeof(wol_info.sopass)); - if (copy_to_user(useraddr, &wol_info, sizeof(wol_info))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol_info; +static struct ethtool_ops ops = { + .get_drvinfo = amd8111e_get_drvinfo, + .get_regs_len = amd8111e_get_regs_len, + .get_regs = amd8111e_get_regs, + .get_settings = amd8111e_get_settings, + .set_settings = amd8111e_set_settings, + .nway_reset = amd8111e_nway_reset, + .get_link = amd8111e_get_link, + .get_wol = amd8111e_get_wol, + .set_wol = amd8111e_set_wol, +}; - if (copy_from_user(&wol_info, useraddr, sizeof(wol_info))) - return -EFAULT; - if (wol_info.wolopts & ~(WAKE_MAGIC |WAKE_PHY)) - return -EINVAL; - spin_lock_irq(&lp->lock); - if(wol_info.wolopts & WAKE_MAGIC) - lp->options |= - (OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE); - else if(wol_info.wolopts & WAKE_PHY) - lp->options |= - (OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE); - else - lp->options &= ~OPTION_WOL_ENABLE; - spin_unlock_irq(&lp->lock); - return 0; - } +/* +This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. +*/ - default: - break; - } - return -EOPNOTSUPP; -} static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -1703,10 +1666,8 @@ static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd) return -EPERM; switch(cmd) { - case SIOCETHTOOL: - return amd8111e_ethtool_ioctl(dev, ifr->ifr_data); case SIOCGMIIPHY: - data->phy_id = PHY_ID; + data->phy_id = lp->ext_phy_addr; /* fallthru */ case SIOCGMIIREG: @@ -1736,7 +1697,7 @@ static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd) } static int amd8111e_set_mac_address(struct net_device *dev, void *p) { - struct amd8111e_priv *lp = dev->priv; + struct amd8111e_priv *lp = netdev_priv(dev); int i; struct sockaddr *addr = p; @@ -1874,7 +1835,7 @@ static int amd8111e_suspend(struct pci_dev *pci_dev, u32 state) pci_enable_wake(pci_dev, 4, 0); /* 4 == D3 cold */ } - pci_save_state(pci_dev, lp->pm_state); + pci_save_state(pci_dev); pci_set_power_state(pci_dev, 3); return 0; @@ -1888,7 +1849,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev) return 0; pci_set_power_state(pci_dev, 0); - pci_restore_state(pci_dev, lp->pm_state); + pci_restore_state(pci_dev); pci_enable_wake(pci_dev, 3, 0); pci_enable_wake(pci_dev, 4, 0); /* D3 cold */ @@ -1912,7 +1873,7 @@ static void __devexit amd8111e_remove_one(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { unregister_netdev(dev); - iounmap((void *) ((struct amd8111e_priv *)(dev->priv))->mmio); + iounmap(((struct amd8111e_priv *)netdev_priv(dev))->mmio); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -1923,7 +1884,7 @@ static void amd8111e_config_ipg(struct net_device* dev) { struct amd8111e_priv *lp = netdev_priv(dev); struct ipg_info* ipg_data = &lp->ipg_data; - void * mmio = lp->mmio; + void __iomem *mmio = lp->mmio; unsigned int prev_col_cnt = ipg_data->col_cnt; unsigned int total_col_cnt; unsigned int tmp_ipg; @@ -1979,6 +1940,26 @@ static void amd8111e_config_ipg(struct net_device* dev) } +static void __devinit amd8111e_probe_ext_phy(struct net_device* dev) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + int i; + + for (i = 0x1e; i >= 0; i--) { + u32 id1, id2; + + if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1)) + continue; + if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2)) + continue; + lp->ext_phy_id = (id1 << 16) | id2; + lp->ext_phy_addr = i; + return; + } + lp->ext_phy_id = 0; + lp->ext_phy_addr = 1; +} + static int __devinit amd8111e_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2049,12 +2030,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, lp->amd8111e_net_dev = dev; lp->pm_cap = pm_cap; - /* setting mii default values */ - lp->mii_if.dev = dev; - lp->mii_if.mdio_read = amd8111e_mdio_read; - lp->mii_if.mdio_write = amd8111e_mdio_write; - lp->mii_if.phy_id = PHY_ID; - spin_lock_init(&lp->lock); lp->mmio = ioremap(reg_addr, reg_len); @@ -2085,6 +2060,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, dev->set_mac_address = amd8111e_set_mac_address; dev->do_ioctl = amd8111e_ioctl; dev->change_mtu = amd8111e_change_mtu; + SET_ETHTOOL_OPS(dev, &ops); dev->irq =pdev->irq; dev->tx_timeout = amd8111e_tx_timeout; dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; @@ -2101,7 +2077,15 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, dev->vlan_rx_register =amd8111e_vlan_rx_register; dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid; #endif - + /* Probe the external PHY */ + amd8111e_probe_ext_phy(dev); + + /* setting mii default values */ + lp->mii_if.dev = dev; + lp->mii_if.mdio_read = amd8111e_mdio_read; + lp->mii_if.mdio_write = amd8111e_mdio_write; + lp->mii_if.phy_id = lp->ext_phy_addr; + /* Set receive buffer length and set jumbo option*/ amd8111e_set_rx_buff_len(dev); @@ -2134,9 +2118,15 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, for (i = 0; i < 6; i++) printk("%2.2x%c",dev->dev_addr[i],i == 5 ? ' ' : ':'); printk( "\n"); + if (lp->ext_phy_id) + printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n", + dev->name, lp->ext_phy_id, lp->ext_phy_addr); + else + printk(KERN_INFO "%s: Couldn't detect MII PHY, assuming address 0x01\n", + dev->name); return 0; err_iounmap: - iounmap((void *) lp->mmio); + iounmap(lp->mmio); err_free_dev: free_netdev(dev); diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index f95425d5f..cfe3a4298 100755 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -649,7 +649,6 @@ typedef enum { #define TCC_MASK 0x0003 /* driver ioctl parameters */ -#define PHY_ID 0x01 /* currently it is fixed */ #define AMD8111E_REG_DUMP_LEN 13*sizeof(u32) /* crc generator constants */ @@ -766,7 +765,7 @@ struct amd8111e_priv{ dma_addr_t tx_dma_addr[NUM_TX_BUFFERS]; dma_addr_t rx_dma_addr[NUM_RX_BUFFERS]; /* Reg memory mapped address */ - void * mmio; + void __iomem *mmio; spinlock_t lock; /* Guard lock */ unsigned long rx_idx, tx_idx; /* The next free ring entry */ @@ -777,10 +776,11 @@ struct amd8111e_priv{ int options; /* Options enabled/disabled for the device */ unsigned long ext_phy_option; + int ext_phy_addr; + u32 ext_phy_id; struct amd8111e_link_config link_config; int pm_cap; - u32 pm_state[12]; struct net_device *next; int mii; diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 925dd0477..00bb1b2ae 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -69,9 +69,9 @@ static const char *version = #include /* For udelay() */ #include #include +#include #include -#include #include #include diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 70a7a181b..118503bc3 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -227,9 +227,9 @@ static int dma; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 77ff7df32..edcc38761 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -231,7 +231,7 @@ err_free_irq: static int arcrimi_reset(struct net_device *dev, int really_reset) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *ioaddr = lp->mem_start + 0x800; + void __iomem *ioaddr = lp->mem_start + 0x800; BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); @@ -252,7 +252,7 @@ static int arcrimi_reset(struct net_device *dev, int really_reset) static void arcrimi_setmask(struct net_device *dev, int mask) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *ioaddr = lp->mem_start + 0x800; + void __iomem *ioaddr = lp->mem_start + 0x800; AINTMASK(mask); } @@ -260,7 +260,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask) static int arcrimi_status(struct net_device *dev) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *ioaddr = lp->mem_start + 0x800; + void __iomem *ioaddr = lp->mem_start + 0x800; return ASTATUS(); } @@ -268,7 +268,7 @@ static int arcrimi_status(struct net_device *dev) static void arcrimi_command(struct net_device *dev, int cmd) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *ioaddr = lp->mem_start + 0x800; + void __iomem *ioaddr = lp->mem_start + 0x800; ACOMMAND(cmd); } @@ -277,7 +277,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } @@ -286,7 +286,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse void *buf, int count) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 5912a24a3..5d304676f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -401,7 +401,8 @@ static int arcnet_open(struct net_device *dev) lp->rfc1201.sequence = 1; /* bring up the hardware driver */ - lp->hw.open(dev); + if (lp->hw.open) + lp->hw.open(dev); if (dev->dev_addr[0] == 0) BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 05a832a2f..ba0f8a2eb 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -566,7 +566,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *memaddr = lp->mem_start + bufnum * 512 + offset; + void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } @@ -575,7 +575,7 @@ static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offse void *buf, int count) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - void *memaddr = lp->mem_start + bufnum * 512 + offset; + void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 10a94c544..9fe93acfc 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -47,8 +47,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 6b28a3d9b..9b659e3c8 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -630,6 +630,16 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_RETVAL(handled); } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void am79c961_poll_controller(struct net_device *dev) +{ + unsigned long flags; + local_irq_save(flags); + am79c961_interrupt(dev->irq, dev, NULL); + local_irq_restore(flags); +} +#endif + /* * Initialise the chip. Note that we always expect * to be entered with interrupts enabled. @@ -721,6 +731,9 @@ static int __init am79c961_init(void) dev->get_stats = am79c961_getstats; dev->set_multicast_list = am79c961_setmulticastlist; dev->tx_timeout = am79c961_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = am79c961_poll_controller; +#endif ret = register_netdev(dev); if (ret == 0) diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index fb401b27c..6118f09c6 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -48,9 +48,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index d054876b9..e0d22a31e 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -64,9 +64,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index d861c54a7..942a28195 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -40,13 +40,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include #include @@ -56,14 +57,19 @@ #define NET_DEBUG 0 #define DEBUG_INIT 2 +#define DRV_NAME "etherh" +#define DRV_VERSION "1.11" + static unsigned int net_debug = NET_DEBUG; struct etherh_priv { - void *ioc_fast; - void *memc; + void __iomem *ioc_fast; + void __iomem *memc; + void __iomem *dma_base; unsigned int id; - void *ctrl_port; + void __iomem *ctrl_port; unsigned char ctrl; + u32 supported; }; struct etherh_data { @@ -72,11 +78,7 @@ struct etherh_data { unsigned long ctrlport_offset; int ctrl_ioc; const char name[16]; - /* - * netdev flags and port - */ - unsigned short flags; - unsigned char if_port; + u32 supported; unsigned char tx_start_page; unsigned char stop_page; }; @@ -86,7 +88,7 @@ MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_LICENSE("GPL"); static char version[] __initdata = - "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n"; + "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; #define ETHERH500_DATAPORT 0x800 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */ @@ -166,7 +168,8 @@ static void etherh_setif(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); - unsigned long addr, flags; + unsigned long flags; + void __iomem *addr; local_irq_save(flags); @@ -174,7 +177,7 @@ etherh_setif(struct net_device *dev) switch (etherh_priv(dev)->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - addr = dev->base_addr + EN0_RCNTHI; + addr = (void *)dev->base_addr + EN0_RCNTHI; switch (dev->if_port) { case IF_PORT_10BASE2: @@ -209,17 +212,19 @@ static int etherh_getifstat(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); + void __iomem *addr; int stat = 0; switch (etherh_priv(dev)->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: + addr = (void *)dev->base_addr + EN0_RCNTHI; switch (dev->if_port) { case IF_PORT_10BASE2: stat = 1; break; case IF_PORT_10BASET: - stat = readb(dev->base_addr+EN0_RCNTHI) & 4; + stat = readb(addr) & 4; break; } break; @@ -276,8 +281,9 @@ static void etherh_reset(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); + void __iomem *addr = (void *)dev->base_addr; - writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr); + writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr); /* * See if we need to change the interface type. @@ -303,8 +309,8 @@ static void etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page) { struct ei_device *ei_local = netdev_priv(dev); - unsigned int addr, dma_addr; unsigned long dma_start; + void __iomem *dma_base, *addr; if (ei_local->dmaing) { printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " @@ -321,8 +327,8 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ei_local->dmaing = 1; - addr = dev->base_addr; - dma_addr = dev->mem_start; + addr = (void *)dev->base_addr; + dma_base = etherh_priv(dev)->dma_base; count = (count + 1) & ~1; writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); @@ -343,9 +349,9 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD); if (ei_local->word16) - writesw (dma_addr, buf, count >> 1); + writesw (dma_base, buf, count >> 1); else - writesb (dma_addr, buf, count); + writesb (dma_base, buf, count); dma_start = jiffies; @@ -369,8 +375,8 @@ static void etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) { struct ei_device *ei_local = netdev_priv(dev); - unsigned int addr, dma_addr; unsigned char *buf; + void __iomem *dma_base, *addr; if (ei_local->dmaing) { printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " @@ -381,8 +387,8 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ei_local->dmaing = 1; - addr = dev->base_addr; - dma_addr = dev->mem_start; + addr = (void *)dev->base_addr; + dma_base = etherh_priv(dev)->dma_base; buf = skb->data; writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); @@ -393,11 +399,11 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); if (ei_local->word16) { - readsw (dma_addr, buf, count >> 1); + readsw (dma_base, buf, count >> 1); if (count & 1) - buf[count - 1] = readb (dma_addr); + buf[count - 1] = readb (dma_base); } else - readsb (dma_addr, buf, count); + readsb (dma_base, buf, count); writeb (ENISR_RDC, addr + EN0_ISR); ei_local->dmaing = 0; @@ -410,7 +416,7 @@ static void etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { struct ei_device *ei_local = netdev_priv(dev); - unsigned int addr, dma_addr; + void __iomem *dma_base, *addr; if (ei_local->dmaing) { printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " @@ -421,8 +427,8 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ei_local->dmaing = 1; - addr = dev->base_addr; - dma_addr = dev->mem_start; + addr = (void *)dev->base_addr; + dma_base = etherh_priv(dev)->dma_base; writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); writeb (sizeof (*hdr), addr + EN0_RCNTLO); @@ -432,9 +438,9 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); if (ei_local->word16) - readsw (dma_addr, hdr, sizeof (*hdr) >> 1); + readsw (dma_base, hdr, sizeof (*hdr) >> 1); else - readsb (dma_addr, hdr, sizeof (*hdr)); + readsb (dma_base, hdr, sizeof (*hdr)); writeb (ENISR_RDC, addr + EN0_ISR); ei_local->dmaing = 0; @@ -522,16 +528,30 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec) struct in_chunk_dir cd; char *s; - if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { + if (!ecard_readchunk(&cd, ec, 0xf5, 0)) { + printk(KERN_ERR "%s: unable to read podule description string\n", + ec->dev.bus_id); + goto no_addr; + } + + s = strchr(cd.d.string, '('); + if (s) { int i; + for (i = 0; i < 6; i++) { addr[i] = simple_strtoul(s + 1, &s, 0x10); if (*s != (i == 5? ')' : ':')) break; } + if (i == 6) return 0; } + + printk(KERN_ERR "%s: unable to parse MAC address: %s\n", + ec->dev.bus_id, cd.d.string); + + no_addr: return -ENODEV; } @@ -556,6 +576,62 @@ static int __init etherm_addr(char *addr) return 0; } +static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev->class_dev.dev->bus_id, + sizeof(info->bus_info)); +} + +static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = etherh_priv(dev)->supported; + cmd->speed = SPEED_10; + cmd->duplex = DUPLEX_HALF; + cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC; + cmd->autoneg = dev->flags & IFF_AUTOMEDIA ? AUTONEG_ENABLE : AUTONEG_DISABLE; + return 0; +} + +static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + switch (cmd->autoneg) { + case AUTONEG_ENABLE: + dev->flags |= IFF_AUTOMEDIA; + break; + + case AUTONEG_DISABLE: + switch (cmd->port) { + case PORT_TP: + dev->if_port = IF_PORT_10BASET; + break; + + case PORT_BNC: + dev->if_port = IF_PORT_10BASE2; + break; + + default: + return -EINVAL; + } + dev->flags &= ~IFF_AUTOMEDIA; + break; + + default: + return -EINVAL; + } + + etherh_setif(dev); + + return 0; +} + +static struct ethtool_ops etherh_ethtool_ops = { + .get_settings = etherh_get_settings, + .set_settings = etherh_set_settings, + .get_drvinfo = etherh_get_drvinfo, +}; + static u32 etherh_regoffsets[16]; static u32 etherm_regoffsets[16]; @@ -587,10 +663,21 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) dev->stop = etherh_close; dev->set_config = etherh_set_config; dev->irq = ec->irq; - dev->if_port = data->if_port; - dev->flags |= data->flags; + dev->ethtool_ops = ðerh_ethtool_ops; + + if (data->supported & SUPPORTED_Autoneg) + dev->flags |= IFF_AUTOMEDIA; + if (data->supported & SUPPORTED_TP) { + dev->flags |= IFF_PORTSEL; + dev->if_port = IF_PORT_10BASET; + } else if (data->supported & SUPPORTED_BNC) { + dev->flags |= IFF_PORTSEL; + dev->if_port = IF_PORT_10BASE2; + } else + dev->if_port = IF_PORT_UNKNOWN; eh = etherh_priv(dev); + eh->supported = data->supported; eh->ctrl = 0; eh->id = ec->cid.product; eh->memc = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), PAGE_SIZE); @@ -610,7 +697,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) } dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset; - dev->mem_start = (unsigned long)eh->memc + data->dataport_offset; + eh->dma_base = eh->memc + data->dataport_offset; eh->ctrl_port += data->ctrlport_offset; /* @@ -701,7 +788,7 @@ static struct etherh_data etherm_data = { .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT, .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT, .name = "ANT EtherM", - .if_port = IF_PORT_UNKNOWN, + .supported = SUPPORTED_10baseT_Half, .tx_start_page = ETHERM_TX_START_PAGE, .stop_page = ETHERM_STOP_PAGE, }; @@ -712,7 +799,7 @@ static struct etherh_data etherlan500_data = { .ctrlport_offset = ETHERH500_CTRLPORT, .ctrl_ioc = 1, .name = "i3 EtherH 500", - .if_port = IF_PORT_UNKNOWN, + .supported = SUPPORTED_10baseT_Half, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE, }; @@ -722,8 +809,7 @@ static struct etherh_data etherlan600_data = { .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, .name = "i3 EtherH 600", - .flags = IFF_PORTSEL | IFF_AUTOMEDIA, - .if_port = IF_PORT_10BASET, + .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE, }; @@ -733,8 +819,7 @@ static struct etherh_data etherlan600a_data = { .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, .name = "i3 EtherH 600A", - .flags = IFF_PORTSEL | IFF_AUTOMEDIA, - .if_port = IF_PORT_10BASET, + .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, .tx_start_page = ETHERH_TX_START_PAGE, .stop_page = ETHERH_STOP_PAGE, }; @@ -752,7 +837,7 @@ static struct ecard_driver etherh_driver = { .remove = __devexit_p(etherh_remove), .id_table = etherh_ids, .drv = { - .name = "etherh", + .name = DRV_NAME, }, }; diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index a3e7e63c3..0dcf27a51 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -56,9 +56,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c index 92a2ec2e5..1798ce726 100644 --- a/drivers/net/atari_bionet.c +++ b/drivers/net/atari_bionet.c @@ -97,6 +97,7 @@ static char version[] = #include #include #include +#include #include #include @@ -105,7 +106,6 @@ static char version[] = #include #include #include -#include #include #include #include diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c index c74e58662..81c362c8c 100644 --- a/drivers/net/atari_pamsnet.c +++ b/drivers/net/atari_pamsnet.c @@ -88,9 +88,9 @@ static char *version = #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index e462e2fca..ad011214c 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -56,12 +56,12 @@ static char version[] = "atarilance.c: v1.3 04/04/96 " #include #include #include +#include #include #include #include #include -#include #include /* Debug level: @@ -606,7 +606,7 @@ static unsigned long __init lance_probe1( struct net_device *dev, printk( " Use \"ifconfig hw ether ...\" to set the address.\n" ); } - lp->devlock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->devlock); MEM->init.mode = 0x0000; /* Disable Rx and Tx. */ for( i = 0; i < 6; i++ ) diff --git a/drivers/net/atp.c b/drivers/net/atp.c index fd2e033fe..662e40f30 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -141,9 +141,9 @@ static int xcvr[NUM_UNITS]; /* The data transfer mode. */ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index afcdcffc7..3328ed511 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -36,10 +36,10 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/drivers/net/b44.c b/drivers/net/b44.c index ba1d4fc9a..f6fd4090a 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -27,8 +28,8 @@ #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.94" -#define DRV_MODULE_RELDATE "May 4, 2004" +#define DRV_MODULE_VERSION "0.95" +#define DRV_MODULE_RELDATE "Aug 3, 2004" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -57,6 +58,7 @@ #define B44_DEF_TX_RING_PENDING (B44_TX_RING_SIZE - 1) #define B44_TX_RING_BYTES (sizeof(struct dma_desc) * \ B44_TX_RING_SIZE) +#define B44_DMA_MASK 0x3fffffff #define TX_RING_GAP(BP) \ (B44_TX_RING_SIZE - (BP)->tx_pending) @@ -67,6 +69,7 @@ #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64) +#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8) /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) @@ -74,13 +77,14 @@ static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; -MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); +MODULE_AUTHOR("Florian Schirmer, Pekka Pietikainen, David S. Miller"); MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(b44_debug, "i"); -MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value"); +MODULE_VERSION(DRV_MODULE_VERSION); static int b44_debug = -1; /* -1 == use B44_DEF_MSG_ENABLE as value */ +module_param(b44_debug, int, 0); +MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value"); static struct pci_device_id b44_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401, @@ -97,6 +101,21 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); static void b44_halt(struct b44 *); static void b44_init_rings(struct b44 *); static void b44_init_hw(struct b44 *); +static int b44_poll(struct net_device *dev, int *budget); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void b44_poll_controller(struct net_device *dev); +#endif + +static inline unsigned long br32(const struct b44 *bp, unsigned long reg) +{ + return readl(bp->regs + reg); +} + +static inline void bw32(const struct b44 *bp, + unsigned long reg, unsigned long val) +{ + writel(val, bp->regs + reg); +} static int b44_wait_bit(struct b44 *bp, unsigned long reg, u32 bit, unsigned long timeout, const int clear) @@ -104,7 +123,7 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg, unsigned long i; for (i = 0; i < timeout; i++) { - u32 val = br32(reg); + u32 val = br32(bp, reg); if (clear && !(val & bit)) break; @@ -130,45 +149,12 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg, * interrupts disabled. */ -#define SBID_SDRAM 0 -#define SBID_PCI_MEM 1 -#define SBID_PCI_CFG 2 -#define SBID_PCI_DMA 3 -#define SBID_SDRAM_SWAPPED 4 -#define SBID_ENUM 5 -#define SBID_REG_SDRAM 6 -#define SBID_REG_ILINE20 7 -#define SBID_REG_EMAC 8 -#define SBID_REG_CODEC 9 -#define SBID_REG_USB 10 -#define SBID_REG_PCI 11 -#define SBID_REG_MIPS 12 -#define SBID_REG_EXTIF 13 -#define SBID_EXTIF 14 -#define SBID_EJTAG 15 -#define SBID_MAX 16 - -static u32 ssb_get_addr(struct b44 *bp, u32 id, u32 instance) -{ - switch (id) { - case SBID_PCI_DMA: - return 0x40000000; - case SBID_ENUM: - return 0x18000000; - case SBID_REG_EMAC: - return 0x18000000; - case SBID_REG_CODEC: - return 0x18001000; - case SBID_REG_PCI: - return 0x18002000; - default: - return 0; - }; -} +#define SB_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */ +#define BCM4400_PCI_CORE_ADDR 0x18002000 /* Address of PCI core on BCM4400 cards */ static u32 ssb_get_core_rev(struct b44 *bp) { - return (br32(B44_SBIDHIGH) & SBIDHIGH_RC_MASK); + return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK); } static u32 ssb_pci_setup(struct b44 *bp, u32 cores) @@ -176,17 +162,16 @@ static u32 ssb_pci_setup(struct b44 *bp, u32 cores) u32 bar_orig, pci_rev, val; pci_read_config_dword(bp->pdev, SSB_BAR0_WIN, &bar_orig); - pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, - ssb_get_addr(bp, SBID_REG_PCI, 0)); + pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, BCM4400_PCI_CORE_ADDR); pci_rev = ssb_get_core_rev(bp); - val = br32(B44_SBINTVEC); + val = br32(bp, B44_SBINTVEC); val |= cores; - bw32(B44_SBINTVEC, val); + bw32(bp, B44_SBINTVEC, val); - val = br32(SSB_PCI_TRANS_2); + val = br32(bp, SSB_PCI_TRANS_2); val |= SSB_PCI_PREF | SSB_PCI_BURST; - bw32(SSB_PCI_TRANS_2, val); + bw32(bp, SSB_PCI_TRANS_2, val); pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, bar_orig); @@ -195,18 +180,18 @@ static u32 ssb_pci_setup(struct b44 *bp, u32 cores) static void ssb_core_disable(struct b44 *bp) { - if (br32(B44_SBTMSLOW) & SBTMSLOW_RESET) + if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET) return; - bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK)); + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK)); b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0); b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1); - bw32(B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK | + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK | SBTMSLOW_REJECT | SBTMSLOW_RESET)); - br32(B44_SBTMSLOW); + br32(bp, B44_SBTMSLOW); udelay(1); - bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET)); - br32(B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET)); + br32(bp, B44_SBTMSLOW); udelay(1); } @@ -215,31 +200,31 @@ static void ssb_core_reset(struct b44 *bp) u32 val; ssb_core_disable(bp); - bw32(B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC)); - br32(B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC)); + br32(bp, B44_SBTMSLOW); udelay(1); /* Clear SERR if set, this is a hw bug workaround. */ - if (br32(B44_SBTMSHIGH) & SBTMSHIGH_SERR) - bw32(B44_SBTMSHIGH, 0); + if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR) + bw32(bp, B44_SBTMSHIGH, 0); - val = br32(B44_SBIMSTATE); + val = br32(bp, B44_SBIMSTATE); if (val & (SBIMSTATE_IBE | SBIMSTATE_TO)) - bw32(B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO)); + bw32(bp, B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO)); - bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC)); - br32(B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC)); + br32(bp, B44_SBTMSLOW); udelay(1); - bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK)); - br32(B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK)); + br32(bp, B44_SBTMSLOW); udelay(1); } static int ssb_core_unit(struct b44 *bp) { #if 0 - u32 val = br32(B44_SBADMATCH0); + u32 val = br32(bp, B44_SBADMATCH0); u32 base; type = val & SBADMATCH0_TYPE_MASK; @@ -263,7 +248,7 @@ static int ssb_core_unit(struct b44 *bp) static int ssb_is_core_up(struct b44 *bp) { - return ((br32(B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK)) + return ((br32(bp, B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK)) == SBTMSLOW_CLOCK); } @@ -275,19 +260,19 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index) val |= ((u32) data[3]) << 16; val |= ((u32) data[4]) << 8; val |= ((u32) data[5]) << 0; - bw32(B44_CAM_DATA_LO, val); + bw32(bp, B44_CAM_DATA_LO, val); val = (CAM_DATA_HI_VALID | (((u32) data[0]) << 8) | (((u32) data[1]) << 0)); - bw32(B44_CAM_DATA_HI, val); - bw32(B44_CAM_CTRL, (CAM_CTRL_WRITE | + bw32(bp, B44_CAM_DATA_HI, val); + bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE | (index << CAM_CTRL_INDEX_SHIFT))); b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1); } static inline void __b44_disable_ints(struct b44 *bp) { - bw32(B44_IMASK, 0); + bw32(bp, B44_IMASK, 0); } static void b44_disable_ints(struct b44 *bp) @@ -295,34 +280,34 @@ static void b44_disable_ints(struct b44 *bp) __b44_disable_ints(bp); /* Flush posted writes. */ - br32(B44_IMASK); + br32(bp, B44_IMASK); } static void b44_enable_ints(struct b44 *bp) { - bw32(B44_IMASK, bp->imask); + bw32(bp, B44_IMASK, bp->imask); } static int b44_readphy(struct b44 *bp, int reg, u32 *val) { int err; - bw32(B44_EMAC_ISTAT, EMAC_INT_MII); - bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START | + bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII); + bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) | (bp->phy_addr << MDIO_DATA_PMD_SHIFT) | (reg << MDIO_DATA_RA_SHIFT) | (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT))); err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0); - *val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA; + *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA; return err; } static int b44_writephy(struct b44 *bp, int reg, u32 val) { - bw32(B44_EMAC_ISTAT, EMAC_INT_MII); - bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START | + bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII); + bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START | (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) | (bp->phy_addr << MDIO_DATA_PMD_SHIFT) | (reg << MDIO_DATA_RA_SHIFT) | @@ -382,20 +367,20 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags) bp->flags &= ~(B44_FLAG_TX_PAUSE | B44_FLAG_RX_PAUSE); bp->flags |= pause_flags; - val = br32(B44_RXCONFIG); + val = br32(bp, B44_RXCONFIG); if (pause_flags & B44_FLAG_RX_PAUSE) val |= RXCONFIG_FLOW; else val &= ~RXCONFIG_FLOW; - bw32(B44_RXCONFIG, val); + bw32(bp, B44_RXCONFIG, val); - val = br32(B44_MAC_FLOW); + val = br32(bp, B44_MAC_FLOW); if (pause_flags & B44_FLAG_TX_PAUSE) val |= (MAC_FLOW_PAUSE_ENAB | (0xc0 & MAC_FLOW_RX_HI_WATER)); else val &= ~MAC_FLOW_PAUSE_ENAB; - bw32(B44_MAC_FLOW, val); + bw32(bp, B44_MAC_FLOW, val); } static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) @@ -491,11 +476,11 @@ static void b44_stats_update(struct b44 *bp) val = &bp->hw_stats.tx_good_octets; for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) { - *val++ += br32(reg); + *val++ += br32(bp, reg); } val = &bp->hw_stats.rx_good_octets; for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) { - *val++ += br32(reg); + *val++ += br32(bp, reg); } } @@ -535,14 +520,14 @@ static void b44_check_phy(struct b44 *bp) if (!netif_carrier_ok(bp->dev) && (bmsr & BMSR_LSTATUS)) { - u32 val = br32(B44_TX_CTRL); + u32 val = br32(bp, B44_TX_CTRL); u32 local_adv, remote_adv; if (bp->flags & B44_FLAG_FULL_DUPLEX) val |= TX_CTRL_DUPLEX; else val &= ~TX_CTRL_DUPLEX; - bw32(B44_TX_CTRL, val); + bw32(bp, B44_TX_CTRL, val); if (!(bp->flags & B44_FLAG_FORCE_LINK) && !b44_readphy(bp, MII_ADVERTISE, &local_adv) && @@ -587,7 +572,7 @@ static void b44_tx(struct b44 *bp) { u32 cur, cons; - cur = br32(B44_DMATX_STAT) & DMATX_STAT_CDMASK; + cur = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK; cur /= sizeof(struct dma_desc); /* XXX needs updating when NETIF_F_SG is supported */ @@ -611,7 +596,7 @@ static void b44_tx(struct b44 *bp) TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH) netif_wake_queue(bp->dev); - bw32(B44_GPTIMER, 0); + bw32(bp, B44_GPTIMER, 0); } /* Works like this. This chip writes a 'struct rx_header" 30 bytes @@ -638,10 +623,30 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (skb == NULL) return -ENOMEM; - skb->dev = bp->dev; mapping = pci_map_single(bp->pdev, skb->data, RX_PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + + /* Hardware bug work-around, the chip is unable to do PCI DMA + to/from anything above 1GB :-( */ + if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) { + /* Sigh... */ + pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA); + if (skb == NULL) + return -ENOMEM; + mapping = pci_map_single(bp->pdev, skb->data, + RX_PKT_BUF_SZ, + PCI_DMA_FROMDEVICE); + if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) { + pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + return -ENOMEM; + } + } + + skb->dev = bp->dev; skb_reserve(skb, bp->rx_offset); rh = (struct rx_header *) @@ -708,7 +713,7 @@ static int b44_rx(struct b44 *bp, int budget) u32 cons, prod; received = 0; - prod = br32(B44_DMARX_STAT) & DMARX_STAT_CDMASK; + prod = br32(bp, B44_DMARX_STAT) & DMARX_STAT_CDMASK; prod /= sizeof(struct dma_desc); cons = bp->rx_cons; @@ -787,7 +792,7 @@ static int b44_rx(struct b44 *bp, int budget) } bp->rx_cons = cons; - bw32(B44_DMARX_PTR, cons * sizeof(struct dma_desc)); + bw32(bp, B44_DMARX_PTR, cons * sizeof(struct dma_desc)); return received; } @@ -851,8 +856,8 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_lock_irqsave(&bp->lock, flags); - istat = br32(B44_ISTAT); - imask = br32(B44_IMASK); + istat = br32(bp, B44_ISTAT); + imask = br32(bp, B44_IMASK); /* ??? What the fuck is the purpose of the interrupt mask * ??? register if we have to mask it out by hand anyways? @@ -872,8 +877,8 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev->name); } - bw32(B44_ISTAT, istat); - br32(B44_ISTAT); + bw32(bp, B44_ISTAT, istat); + br32(bp, B44_ISTAT); } spin_unlock_irqrestore(&bp->lock, flags); return IRQ_RETVAL(handled); @@ -919,6 +924,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = bp->tx_prod; mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); + if(mapping+len > B44_DMA_MASK) { + /* Chip can't handle DMA to/from >1GB, use bounce buffer */ + pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE); + memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len); + mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE); + } bp->tx_buffers[entry].skb = skb; pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping); @@ -937,11 +948,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); - bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc)); + bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc)); if (bp->flags & B44_FLAG_BUGGY_TXPTR) - bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc)); + bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc)); if (bp->flags & B44_FLAG_REORDER_BUG) - br32(B44_DMATX_PTR); + br32(bp, B44_DMATX_PTR); if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); @@ -1066,6 +1077,11 @@ static void b44_free_consistent(struct b44 *bp) bp->tx_ring, bp->tx_ring_dma); bp->tx_ring = NULL; } + if (bp->tx_bufs) { + pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ, + bp->tx_bufs, bp->tx_bufs_dma); + bp->tx_bufs = NULL; + } } /* @@ -1088,6 +1104,12 @@ static int b44_alloc_consistent(struct b44 *bp) goto out_err; memset(bp->tx_buffers, 0, size); + size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ; + bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma); + if (!bp->tx_bufs) + goto out_err; + memset(bp->tx_bufs, 0, size); + size = DMA_TABLE_BYTES; bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma); if (!bp->rx_ring) @@ -1109,27 +1131,27 @@ static void b44_clear_stats(struct b44 *bp) { unsigned long reg; - bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) - br32(reg); + br32(bp, reg); for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) - br32(reg); + br32(bp, reg); } /* bp->lock is held. */ static void b44_chip_reset(struct b44 *bp) { if (ssb_is_core_up(bp)) { - bw32(B44_RCV_LAZY, 0); - bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE); + bw32(bp, B44_RCV_LAZY, 0); + bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1); - bw32(B44_DMATX_CTRL, 0); + bw32(bp, B44_DMATX_CTRL, 0); bp->tx_prod = bp->tx_cons = 0; - if (br32(B44_DMARX_STAT) & DMARX_STAT_EMASK) { + if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) { b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE, 100, 0); } - bw32(B44_DMARX_CTRL, 0); + bw32(bp, B44_DMARX_CTRL, 0); bp->rx_prod = bp->rx_cons = 0; } else { ssb_pci_setup(bp, (bp->core_unit == 0 ? @@ -1142,20 +1164,20 @@ static void b44_chip_reset(struct b44 *bp) b44_clear_stats(bp); /* Make PHY accessible. */ - bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE | + bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE | (0x0d & MDIO_CTRL_MAXF_MASK))); - br32(B44_MDIO_CTRL); + br32(bp, B44_MDIO_CTRL); - if (!(br32(B44_DEVCTRL) & DEVCTRL_IPP)) { - bw32(B44_ENET_CTRL, ENET_CTRL_EPSEL); - br32(B44_ENET_CTRL); + if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) { + bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL); + br32(bp, B44_ENET_CTRL); bp->flags &= ~B44_FLAG_INTERNAL_PHY; } else { - u32 val = br32(B44_DEVCTRL); + u32 val = br32(bp, B44_DEVCTRL); if (val & DEVCTRL_EPR) { - bw32(B44_DEVCTRL, (val & ~DEVCTRL_EPR)); - br32(B44_DEVCTRL); + bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR)); + br32(bp, B44_DEVCTRL); udelay(100); } bp->flags |= B44_FLAG_INTERNAL_PHY; @@ -1172,13 +1194,13 @@ static void b44_halt(struct b44 *bp) /* bp->lock is held. */ static void __b44_set_mac_addr(struct b44 *bp) { - bw32(B44_CAM_CTRL, 0); + bw32(bp, B44_CAM_CTRL, 0); if (!(bp->dev->flags & IFF_PROMISC)) { u32 val; __b44_cam_write(bp, bp->dev->dev_addr, 0); - val = br32(B44_CAM_CTRL); - bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE); + val = br32(bp, B44_CAM_CTRL); + bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE); } } @@ -1212,30 +1234,30 @@ static void b44_init_hw(struct b44 *bp) b44_setup_phy(bp); /* Enable CRC32, set proper LED modes and power on PHY */ - bw32(B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); - bw32(B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT)); + bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); + bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT)); /* This sets the MAC address too. */ __b44_set_rx_mode(bp->dev); /* MTU + eth header + possible VLAN tag + struct rx_header */ - bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); - bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); + bw32(bp, B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); + bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); - bw32(B44_TX_WMARK, 56); /* XXX magic */ - bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE); - bw32(B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); - bw32(B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | + bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ + bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); + bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); + bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | (bp->rx_offset << DMARX_CTRL_ROSHIFT))); - bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); + bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); - bw32(B44_DMARX_PTR, bp->rx_pending); + bw32(bp, B44_DMARX_PTR, bp->rx_pending); bp->rx_prod = bp->rx_pending; - bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); - val = br32(B44_ENET_CTRL); - bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); + val = br32(bp, B44_ENET_CTRL); + bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); } static int b44_open(struct net_device *dev) @@ -1286,6 +1308,19 @@ err_out_free: } #endif +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void b44_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + b44_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + static int b44_close(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); @@ -1347,7 +1382,10 @@ static struct net_device_stats *b44_get_stats(struct net_device *dev) hwstat->rx_symbol_errs); nstat->tx_aborted_errors = hwstat->tx_underruns; +#if 0 + /* Carrier lost counter seems to be broken for some devices */ nstat->tx_carrier_errors = hwstat->tx_carrier_lost; +#endif return nstat; } @@ -1372,11 +1410,11 @@ static void __b44_set_rx_mode(struct net_device *dev) int i=0; unsigned char zero[6] = {0,0,0,0,0,0}; - val = br32(B44_RXCONFIG); + val = br32(bp, B44_RXCONFIG); val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI); if (dev->flags & IFF_PROMISC) { val |= RXCONFIG_PROMISC; - bw32(B44_RXCONFIG, val); + bw32(bp, B44_RXCONFIG, val); } else { __b44_set_mac_addr(bp); @@ -1388,9 +1426,9 @@ static void __b44_set_rx_mode(struct net_device *dev) for(;i<64;i++) { __b44_cam_write(bp, zero, i); } - bw32(B44_RXCONFIG, val); - val = br32(B44_CAM_CTRL); - bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE); + bw32(bp, B44_RXCONFIG, val); + val = br32(bp, B44_CAM_CTRL); + bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE); } } @@ -1673,7 +1711,6 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->dev->dev_addr[5] = eeprom[82]; bp->phy_addr = eeprom[90] & 0x1f; - bp->mdc_port = (eeprom[90] >> 14) & 0x1; /* With this, plus the rx_header prepended to the data by the * hardware, we'll land the ethernet header on a 2-byte boundary. @@ -1683,7 +1720,7 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->imask = IMASK_DEF; bp->core_unit = ssb_core_unit(bp); - bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0); + bp->dma_offset = SB_PCI_DMA; /* XXX - really required? bp->flags |= B44_FLAG_BUGGY_TXPTR; @@ -1727,12 +1764,19 @@ static int __devinit b44_init_one(struct pci_dev *pdev, pci_set_master(pdev); - err = pci_set_dma_mask(pdev, (u64) 0xffffffff); + err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK); if (err) { printk(KERN_ERR PFX "No usable DMA configuration, " "aborting.\n"); goto err_out_free_res; } + + err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); + if (err) { + printk(KERN_ERR PFX "No usable DMA configuration, " + "aborting.\n"); + goto err_out_free_res; + } b44reg_base = pci_resource_start(pdev, 0); b44reg_len = pci_resource_len(pdev, 0); @@ -1760,7 +1804,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, spin_lock_init(&bp->lock); - bp->regs = (unsigned long) ioremap(b44reg_base, b44reg_len); + bp->regs = ioremap(b44reg_base, b44reg_len); if (bp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -1782,6 +1826,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev, dev->poll = b44_poll; dev->weight = 64; dev->watchdog_timeo = B44_TX_TIMEOUT; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = b44_poll_controller; +#endif dev->change_mtu = b44_change_mtu; dev->irq = pdev->irq; SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); @@ -1816,7 +1863,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - pci_save_state(bp->pdev, bp->pci_cfg_state); + pci_save_state(bp->pdev); printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); for (i = 0; i < 6; i++) @@ -1826,7 +1873,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, return 0; err_out_iounmap: - iounmap((void *) bp->regs); + iounmap(bp->regs); err_out_free_dev: free_netdev(dev); @@ -1848,7 +1895,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev) struct b44 *bp = netdev_priv(dev); unregister_netdev(dev); - iounmap((void *) bp->regs); + iounmap(bp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -1859,7 +1906,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev) static int b44_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); if (!netif_running(dev)) return 0; @@ -1880,9 +1927,9 @@ static int b44_suspend(struct pci_dev *pdev, u32 state) static int b44_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct b44 *bp = dev->priv; + struct b44 *bp = netdev_priv(dev); - pci_restore_state(pdev, bp->pci_cfg_state); + pci_restore_state(pdev); if (!netif_running(dev)) return 0; diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 23bee93fe..f886692f2 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -223,21 +223,8 @@ #define B44_RX_SYM 0x05D0UL /* MIB RX Symbol Errors */ #define B44_RX_PAUSE 0x05D4UL /* MIB RX Pause Packets */ #define B44_RX_NPAUSE 0x05D8UL /* MIB RX Non-Pause Packets */ -#define B44_SBIPSFLAG 0x0F08UL /* SB Initiator Port OCP Slave Flag */ -#define SBIPSFLAG_IMASK1 0x0000003f /* Which sbflags --> mips interrupt 1 */ -#define SBIPSFLAG_ISHIFT1 0 -#define SBIPSFLAG_IMASK2 0x00003f00 /* Which sbflags --> mips interrupt 2 */ -#define SBIPSFLAG_ISHIFT2 8 -#define SBIPSFLAG_IMASK3 0x003f0000 /* Which sbflags --> mips interrupt 3 */ -#define SBIPSFLAG_ISHIFT3 16 -#define SBIPSFLAG_IMASK4 0x3f000000 /* Which sbflags --> mips interrupt 4 */ -#define SBIPSFLAG_ISHIFT4 24 -#define B44_SBTPSFLAG 0x0F18UL /* SB Target Port OCP Slave Flag */ -#define SBTPS_NUM0_MASK 0x0000003f -#define SBTPS_F0EN0 0x00000040 -#define B44_SBADMATCH3 0x0F60UL /* SB Address Match 3 */ -#define B44_SBADMATCH2 0x0F68UL /* SB Address Match 2 */ -#define B44_SBADMATCH1 0x0F70UL /* SB Address Match 1 */ + +/* Silicon backplane register definitions */ #define B44_SBIMSTATE 0x0F90UL /* SB Initiator Agent State */ #define SBIMSTATE_PC 0x0000000f /* Pipe Count */ #define SBIMSTATE_AP_MASK 0x00000030 /* Arbitration Priority */ @@ -269,86 +256,6 @@ #define SBTMSHIGH_GCR 0x20000000 /* Gated Clock Request */ #define SBTMSHIGH_BISTF 0x40000000 /* BIST Failed */ #define SBTMSHIGH_BISTD 0x80000000 /* BIST Done */ -#define B44_SBBWA0 0x0FA0UL /* SB Bandwidth Allocation Table 0 */ -#define SBBWA0_TAB0_MASK 0x0000ffff /* Lookup Table 0 */ -#define SBBWA0_TAB0_SHIFT 0 -#define SBBWA0_TAB1_MASK 0xffff0000 /* Lookup Table 0 */ -#define SBBWA0_TAB1_SHIFT 16 -#define B44_SBIMCFGLOW 0x0FA8UL /* SB Initiator Configuration Low */ -#define SBIMCFGLOW_STO_MASK 0x00000003 /* Service Timeout */ -#define SBIMCFGLOW_RTO_MASK 0x00000030 /* Request Timeout */ -#define SBIMCFGLOW_RTO_SHIFT 4 -#define SBIMCFGLOW_CID_MASK 0x00ff0000 /* Connection ID */ -#define SBIMCFGLOW_CID_SHIFT 16 -#define B44_SBIMCFGHIGH 0x0FACUL /* SB Initiator Configuration High */ -#define SBIMCFGHIGH_IEM_MASK 0x0000000c /* Inband Error Mode */ -#define SBIMCFGHIGH_TEM_MASK 0x00000030 /* Timeout Error Mode */ -#define SBIMCFGHIGH_TEM_SHIFT 4 -#define SBIMCFGHIGH_BEM_MASK 0x000000c0 /* Bus Error Mode */ -#define SBIMCFGHIGH_BEM_SHIFT 6 -#define B44_SBADMATCH0 0x0FB0UL /* SB Address Match 0 */ -#define SBADMATCH0_TYPE_MASK 0x00000003 /* Address Type */ -#define SBADMATCH0_AD64 0x00000004 /* Reserved */ -#define SBADMATCH0_AI0_MASK 0x000000f8 /* Type0 Size */ -#define SBADMATCH0_AI0_SHIFT 3 -#define SBADMATCH0_AI1_MASK 0x000001f8 /* Type1 Size */ -#define SBADMATCH0_AI1_SHIFT 3 -#define SBADMATCH0_AI2_MASK 0x000001f8 /* Type2 Size */ -#define SBADMATCH0_AI2_SHIFT 3 -#define SBADMATCH0_ADEN 0x00000400 /* Enable */ -#define SBADMATCH0_ADNEG 0x00000800 /* Negative Decode */ -#define SBADMATCH0_BS0_MASK 0xffffff00 /* Type0 Base Address */ -#define SBADMATCH0_BS0_SHIFT 8 -#define SBADMATCH0_BS1_MASK 0xfffff000 /* Type1 Base Address */ -#define SBADMATCH0_BS1_SHIFT 12 -#define SBADMATCH0_BS2_MASK 0xffff0000 /* Type2 Base Address */ -#define SBADMATCH0_BS2_SHIFT 16 -#define B44_SBTMCFGLOW 0x0FB8UL /* SB Target Configuration Low */ -#define SBTMCFGLOW_CD_MASK 0x000000ff /* Clock Divide Mask */ -#define SBTMCFGLOW_CO_MASK 0x0000f800 /* Clock Offset Mask */ -#define SBTMCFGLOW_CO_SHIFT 11 -#define SBTMCFGLOW_IF_MASK 0x00fc0000 /* Interrupt Flags Mask */ -#define SBTMCFGLOW_IF_SHIFT 18 -#define SBTMCFGLOW_IM_MASK 0x03000000 /* Interrupt Mode Mask */ -#define SBTMCFGLOW_IM_SHIFT 24 -#define B44_SBTMCFGHIGH 0x0FBCUL /* SB Target Configuration High */ -#define SBTMCFGHIGH_BM_MASK 0x00000003 /* Busy Mode */ -#define SBTMCFGHIGH_RM_MASK 0x0000000C /* Retry Mode */ -#define SBTMCFGHIGH_RM_SHIFT 2 -#define SBTMCFGHIGH_SM_MASK 0x00000030 /* Stop Mode */ -#define SBTMCFGHIGH_SM_SHIFT 4 -#define SBTMCFGHIGH_EM_MASK 0x00000300 /* Error Mode */ -#define SBTMCFGHIGH_EM_SHIFT 8 -#define SBTMCFGHIGH_IM_MASK 0x00000c00 /* Interrupt Mode */ -#define SBTMCFGHIGH_IM_SHIFT 10 -#define B44_SBBCFG 0x0FC0UL /* SB Broadcast Configuration */ -#define SBBCFG_LAT_MASK 0x00000003 /* SB Latency */ -#define SBBCFG_MAX0_MASK 0x000f0000 /* MAX Counter 0 */ -#define SBBCFG_MAX0_SHIFT 16 -#define SBBCFG_MAX1_MASK 0x00f00000 /* MAX Counter 1 */ -#define SBBCFG_MAX1_SHIFT 20 -#define B44_SBBSTATE 0x0FC8UL /* SB Broadcast State */ -#define SBBSTATE_SRD 0x00000001 /* ST Reg Disable */ -#define SBBSTATE_HRD 0x00000002 /* Hold Reg Disable */ -#define B44_SBACTCNFG 0x0FD8UL /* SB Activate Configuration */ -#define B44_SBFLAGST 0x0FE8UL /* SB Current SBFLAGS */ -#define B44_SBIDLOW 0x0FF8UL /* SB Identification Low */ -#define SBIDLOW_CS_MASK 0x00000003 /* Config Space Mask */ -#define SBIDLOW_AR_MASK 0x00000038 /* Num Address Ranges Supported */ -#define SBIDLOW_AR_SHIFT 3 -#define SBIDLOW_SYNCH 0x00000040 /* Sync */ -#define SBIDLOW_INIT 0x00000080 /* Initiator */ -#define SBIDLOW_MINLAT_MASK 0x00000f00 /* Minimum Backplane Latency */ -#define SBIDLOW_MINLAT_SHIFT 8 -#define SBIDLOW_MAXLAT_MASK 0x0000f000 /* Maximum Backplane Latency */ -#define SBIDLOW_MAXLAT_SHIFT 12 -#define SBIDLOW_FIRST 0x00010000 /* This Initiator is First */ -#define SBIDLOW_CW_MASK 0x000c0000 /* Cycle Counter Width */ -#define SBIDLOW_CW_SHIFT 18 -#define SBIDLOW_TP_MASK 0x00f00000 /* Target Ports */ -#define SBIDLOW_TP_SHIFT 20 -#define SBIDLOW_IP_MASK 0x0f000000 /* Initiator Ports */ -#define SBIDLOW_IP_SHIFT 24 #define B44_SBIDHIGH 0x0FFCUL /* SB Identification High */ #define SBIDHIGH_RC_MASK 0x0000000f /* Revision Code */ #define SBIDHIGH_CC_MASK 0x0000fff0 /* Core Code */ @@ -356,23 +263,13 @@ #define SBIDHIGH_VC_MASK 0xffff0000 /* Vendor Code */ #define SBIDHIGH_VC_SHIFT 16 -#define CORE_CODE_ILINE20 0x801 -#define CORE_CODE_SDRAM 0x803 -#define CORE_CODE_PCI 0x804 -#define CORE_CODE_MIPS 0x805 -#define CORE_CODE_ENET 0x806 -#define CORE_CODE_CODEC 0x807 -#define CORE_CODE_USB 0x808 -#define CORE_CODE_ILINE100 0x80a -#define CORE_CODE_EXTIF 0x811 - /* SSB PCI config space registers. */ #define SSB_BAR0_WIN 0x80 #define SSB_BAR1_WIN 0x84 #define SSB_SPROM_CONTROL 0x88 #define SSB_BAR1_CONTROL 0x8c -/* SSB core and hsot control registers. */ +/* SSB core and host control registers. */ #define SSB_CONTROL 0x0000UL #define SSB_ARBCONTROL 0x0010UL #define SSB_ISTAT 0x0020UL @@ -395,9 +292,6 @@ #define SSB_PCI_MASK1 0xfc000000 #define SSB_PCI_MASK2 0xc0000000 -#define br32(REG) readl(bp->regs + (REG)) -#define bw32(REG,VAL) writel((VAL), bp->regs + (REG)) - /* 4400 PHY registers */ #define B44_MII_AUXCTRL 24 /* Auxiliary Control */ #define MII_AUXCTRL_DUPLEX 0x0001 /* Full Duplex */ @@ -503,6 +397,7 @@ struct b44 { struct ring_info *rx_buffers; struct ring_info *tx_buffers; + unsigned char *tx_bufs; u32 dma_offset; u32 flags; @@ -530,17 +425,15 @@ struct b44 { struct net_device_stats stats; struct b44_hw_stats hw_stats; - unsigned long regs; + void __iomem *regs; struct pci_dev *pdev; struct net_device *dev; - dma_addr_t rx_ring_dma, tx_ring_dma; + dma_addr_t rx_ring_dma, tx_ring_dma,tx_bufs_dma; u32 rx_pending; u32 tx_pending; - u32 pci_cfg_state[64 / sizeof(u32)]; u8 phy_addr; - u8 mdc_port; u8 core_unit; struct mii_if_info mii_if; diff --git a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c index e62ad3ad6..55a0f66f6 100644 --- a/drivers/net/bagetlance.c +++ b/drivers/net/bagetlance.c @@ -25,9 +25,9 @@ static char *version = "bagetlance.c: v1.1 11/10/98\n"; #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 49f5ceee5..a76519afa 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1285,7 +1285,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) int res = 1; skb->mac.raw = (unsigned char *)skb->data; - eth_data = (struct ethhdr *)skb->data; + eth_data = eth_hdr(skb); /* make sure that the curr_active_slave and the slaves list do * not change during tx diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6917b665b..654a79fb6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -469,6 +469,13 @@ * * Add support for VLAN hardware acceleration capable slaves. * * Add capability to tag self generated packets in ALB/TLB modes. * Set version to 2.6.0. + * 2004/10/29 - Mitch Williams + * - Fixed bug when unloading module while using 802.3ad. If + * spinlock debugging is turned on, this causes a stack dump. + * Solution is to move call to dev_remove_pack outside of the + * spinlock. + * Set version to 2.6.1. + * */ //#define BONDING_DEBUG 1 @@ -491,8 +498,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -3566,15 +3573,15 @@ static int bond_close(struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; - write_lock_bh(&bond->lock); - - bond_mc_list_destroy(bond); - if (bond->params.mode == BOND_MODE_8023AD) { /* Unregister the receive of LACPDUs */ bond_unregister_lacpdu(bond); } + write_lock_bh(&bond->lock); + + bond_mc_list_destroy(bond); + /* signal timers not to re-arm */ bond->kill_timers = 1; @@ -4700,6 +4707,7 @@ static void __exit bonding_exit(void) module_init(bonding_init); module_exit(bonding_exit); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION); MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others"); MODULE_SUPPORTED_DEVICE("most ethernet devices"); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c07cf2cc1..8c3253084 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -36,8 +36,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.6.0" -#define DRV_RELDATE "January 14, 2004" +#define DRV_VERSION "2.6.1" +#define DRV_RELDATE "October 29, 2004" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c index 409b75442..3d88ad622 100644 --- a/drivers/net/bsd_comp.c +++ b/drivers/net/bsd_comp.c @@ -1160,7 +1160,7 @@ static struct compressor ppp_bsd_compress = { * Module support routines *************************************************************/ -int __init bsdcomp_init(void) +static int __init bsdcomp_init(void) { int answer = ppp_register_compressor(&ppp_bsd_compress); if (answer == 0) @@ -1168,7 +1168,7 @@ int __init bsdcomp_init(void) return answer; } -void __exit bsdcomp_cleanup(void) +static void __exit bsdcomp_cleanup(void) { ppp_unregister_compressor(&ppp_bsd_compress); } diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index b04bf5e72..e8c74071f 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -84,6 +84,9 @@ Oskar Schirmer : oskar@scara.com : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=) + Deepak Saxena : dsaxena@plexity.net + : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support + */ /* Always include 'config.h' first in case the user wants to turn on @@ -97,7 +100,11 @@ * Note that even if DMA is turned off we still support the 'dma' and 'use_dma' * module options so we don't break any startup scripts. */ +#ifndef CONFIG_ARCH_IXDP2X01 +#define ALLOW_DMA 0 +#else #define ALLOW_DMA 1 +#endif /* * Set this to zero to remove all the debug statements via @@ -128,9 +135,9 @@ #include #include #include +#include #include -#include #include #if ALLOW_DMA #include @@ -162,6 +169,10 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0}; static unsigned int netcard_portlist[] __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; +#elif defined(CONFIG_ARCH_IXDP2X01) +#include +static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; +static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; #else static unsigned int netcard_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; @@ -454,11 +465,12 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) retval = -ENODEV; goto out2; } - ioaddr &= ~3; - outw(PP_ChipID, ioaddr + ADD_PORT); } printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + ioaddr &= ~3; + outw(PP_ChipID, ioaddr + ADD_PORT); + if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { printk(KERN_ERR "%s: incorrect signature 0x%x\n", dev->name, inw(ioaddr + DATA_PORT)); @@ -665,6 +677,9 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { +#ifdef CONFIG_ARCH_IXDP2X01 + i = cs8900_irq_map[0]; +#else /* Translate the IRQ using the IRQ mapping table. */ if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0])) printk("\ncs89x0: invalid ISA interrupt number %d\n", i); @@ -681,6 +696,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT) lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8); } +#endif } if (!dev->irq) dev->irq = i; @@ -884,8 +900,10 @@ skip_this_frame: void __init reset_chip(struct net_device *dev) { +#ifndef CONFIG_ARCH_IXDP2X01 struct net_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; +#endif int reset_start_time; writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET); @@ -894,6 +912,7 @@ void __init reset_chip(struct net_device *dev) current->state = TASK_INTERRUPTIBLE; schedule_timeout(30*HZ/1000); +#ifndef CONFIG_ARCH_IXDP2X01 if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT); @@ -904,6 +923,8 @@ void __init reset_chip(struct net_device *dev) outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); } +#endif /* IXDP2x01 */ + /* Wait until the chip is reset */ reset_start_time = jiffies; while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2) @@ -1155,12 +1176,14 @@ net_open(struct net_device *dev) else #endif { +#ifndef CONFIG_ARCH_IXDP2X01 if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); ret = -EAGAIN; goto bad_out; } +#endif /* FIXME: Cirrus' release had this: */ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ ); /* And 2.3.47 had this: */ @@ -1575,7 +1598,9 @@ static void release_dma_buff(struct net_local *lp) static int net_close(struct net_device *dev) { +#if ALLOW_DMA struct net_local *lp = netdev_priv(dev); +#endif netif_stop_queue(dev); diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index f1507b549..b0ef7ad2b 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h @@ -16,6 +16,13 @@ #include +#ifdef CONFIG_ARCH_IXDP2X01 +/* IXDP2401/IXDP2801 uses dword-aligned register addressing */ +#define CS89x0_PORT(reg) ((reg) * 2) +#else +#define CS89x0_PORT(reg) (reg) +#endif + #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ /* offset 2h -> Model/Product Number */ /* offset 3h -> Chip Revision Number */ @@ -324,16 +331,16 @@ #define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */ #define PKT_START PP_TxFrame /* Start of packet RAM */ -#define RX_FRAME_PORT 0x0000 +#define RX_FRAME_PORT CS89x0_PORT(0x0000) #define TX_FRAME_PORT RX_FRAME_PORT -#define TX_CMD_PORT 0x0004 +#define TX_CMD_PORT CS89x0_PORT(0x0004) #define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */ #define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */ #define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */ -#define TX_LEN_PORT 0x0006 -#define ISQ_PORT 0x0008 -#define ADD_PORT 0x000A -#define DATA_PORT 0x000C +#define TX_LEN_PORT CS89x0_PORT(0x0006) +#define ISQ_PORT CS89x0_PORT(0x0008) +#define ADD_PORT CS89x0_PORT(0x000A) +#define DATA_PORT CS89x0_PORT(0x000C) #define EEPROM_WRITE_EN 0x00F0 #define EEPROM_WRITE_DIS 0x0000 diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 7f62a4352..521c83137 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -812,12 +812,6 @@ static int lance_open(struct net_device *dev) } status = init_restart_lance(lp); - - /* - * if (!status) - * MOD_INC_USE_COUNT; - */ - return status; } @@ -849,9 +843,6 @@ static int lance_close(struct net_device *dev) free_irq(lp->dma_irq, dev); } free_irq(dev->irq, dev); - /* - MOD_DEC_USE_COUNT; - */ return 0; } diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 9ef9f3944..4dce49305 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -19,7 +19,7 @@ * LVS Lawrence V. Stefani * * Maintainers: - * macro Maciej W. Rozycki + * macro Maciej W. Rozycki * * Credits: * I'd like to thank Patricia Cross for helping me get started with @@ -190,6 +190,7 @@ * Feb 2001 Skb allocation fixes * Feb 2001 davej PCI enable cleanups. * 04 Aug 2003 macro Converted to the DMA API. + * 14 Aug 2004 macro Fix device names reported. */ /* Include files */ @@ -207,19 +208,21 @@ #include #include #include +#include #include -#include #include #include "defxx.h" -/* Version information string - should be updated prior to each new release!!! */ +/* Version information string should be updated prior to each new release! */ +#define DRV_NAME "defxx" +#define DRV_VERSION "v1.07" +#define DRV_RELDATE "2004/08/14" static char version[] __devinitdata = - "defxx.c:v1.06 2003/08/04 Lawrence V. Stefani and others\n"; - -#define DRV_NAME "defxx" + DRV_NAME ": " DRV_VERSION " " DRV_RELDATE + " Lawrence V. Stefani and others\n"; #define DYNAMIC_BUFFERS 1 @@ -235,7 +238,7 @@ static char version[] __devinitdata = static void dfx_bus_init(struct net_device *dev); static void dfx_bus_config_check(DFX_board_t *bp); -static int dfx_driver_init(struct net_device *dev); +static int dfx_driver_init(struct net_device *dev, const char *print_name); static int dfx_adap_init(DFX_board_t *bp, int get_buffers); static int dfx_open(struct net_device *dev); @@ -404,24 +407,25 @@ static inline void dfx_port_read_long( */ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) { + static int version_disp; + char *print_name = DRV_NAME; struct net_device *dev; DFX_board_t *bp; /* board pointer */ int alloc_size; /* total buffer size used */ int err; -#ifndef MODULE - static int version_disp; - - if (!version_disp) /* display version info if adapter is found */ - { + if (!version_disp) { /* display version info if adapter is found */ version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ } -#endif + + if (pdev != NULL) + print_name = pdev->slot_name; dev = alloc_fddidev(sizeof(*bp)); if (!dev) { - printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n"); + printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n", + print_name); return -ENOMEM; } @@ -437,9 +441,12 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) bp = dev->priv; - if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) { - printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", - DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr); + if (!request_region(ioaddr, + pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, + print_name)) { + printk(KERN_ERR "%s: Cannot reserve I/O resource " + "0x%x @ 0x%lx, aborting\n", print_name, + pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr); err = -EBUSY; goto err_out; } @@ -468,7 +475,7 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) pci_set_master (pdev); } - if (dfx_driver_init(dev) != DFX_K_SUCCESS) { + if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) { err = -ENODEV; goto err_out_region; } @@ -477,6 +484,7 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) if (err) goto err_out_kfree; + printk("%s: registered as %s\n", print_name, dev->name); return 0; err_out_kfree: @@ -770,6 +778,7 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp) * * Arguments: * dev - pointer to device information + * print_name - printable device name * * Functional Description: * This function allocates additional resources such as the host memory @@ -792,7 +801,8 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp) * returning from this routine. */ -static int __devinit dfx_driver_init(struct net_device *dev) +static int __devinit dfx_driver_init(struct net_device *dev, + const char *print_name) { DFX_board_t *bp = dev->priv; int alloc_size; /* total buffer size needed */ @@ -841,26 +851,20 @@ static int __devinit dfx_driver_init(struct net_device *dev) /* Read the factory MAC address from the adapter then save it */ - if (dfx_hw_port_ctrl_req(bp, - PI_PCTRL_M_MLA, - PI_PDATA_A_MLA_K_LO, - 0, - &data) != DFX_K_SUCCESS) - { - printk("%s: Could not read adapter factory MAC address!\n", dev->name); + if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0, + &data) != DFX_K_SUCCESS) { + printk("%s: Could not read adapter factory MAC address!\n", + print_name); return(DFX_K_FAILURE); - } + } memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32)); - if (dfx_hw_port_ctrl_req(bp, - PI_PCTRL_M_MLA, - PI_PDATA_A_MLA_K_HI, - 0, - &data) != DFX_K_SUCCESS) - { - printk("%s: Could not read adapter factory MAC address!\n", dev->name); + if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0, + &data) != DFX_K_SUCCESS) { + printk("%s: Could not read adapter factory MAC address!\n", + print_name); return(DFX_K_FAILURE); - } + } memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16)); /* @@ -872,27 +876,19 @@ static int __devinit dfx_driver_init(struct net_device *dev) memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN); if (bp->bus_type == DFX_BUS_TYPE_EISA) - printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - dev->name, - dev->base_addr, - dev->irq, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); + printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, " + "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + print_name, dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); else - printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - dev->name, - dev->base_addr, - dev->irq, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); + printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, " + "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + print_name, dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); /* * Get memory for descriptor block, consumer block, and other buffers @@ -909,11 +905,11 @@ static int __devinit dfx_driver_init(struct net_device *dev) (PI_ALIGN_K_DESC_BLK - 1); bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size, &bp->kmalloced_dma); - if (top_v == NULL) - { - printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name); + if (top_v == NULL) { + printk("%s: Could not allocate memory for host buffers " + "and structures!\n", print_name); return(DFX_K_FAILURE); - } + } memset(top_v, 0, alloc_size); /* zero out memory before continuing */ top_p = bp->kmalloced_dma; /* get physical address of buffer */ @@ -970,14 +966,20 @@ static int __devinit dfx_driver_init(struct net_device *dev) /* Display virtual and physical addresses if debug driver */ - DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", dev->name, (long)bp->descr_block_virt, bp->descr_block_phys); - DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_req_virt, bp->cmd_req_phys); - DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); - DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->rcv_block_virt, bp->rcv_block_phys); - DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->cons_block_virt, bp->cons_block_phys); + DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", + print_name, + (long)bp->descr_block_virt, bp->descr_block_phys); + DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", + print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys); + DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", + print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); + DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", + print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys); + DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", + print_name, (long)bp->cons_block_virt, bp->cons_block_phys); return(DFX_K_SUCCESS); - } +} /* @@ -1814,16 +1816,18 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev) /* Fill the bp->stats structure with driver-maintained counters */ - bp->stats.rx_packets = bp->rcv_total_frames; - bp->stats.tx_packets = bp->xmt_total_frames; - bp->stats.rx_bytes = bp->rcv_total_bytes; - bp->stats.tx_bytes = bp->xmt_total_bytes; - bp->stats.rx_errors = (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors); - bp->stats.tx_errors = bp->xmt_length_errors; - bp->stats.rx_dropped = bp->rcv_discards; - bp->stats.tx_dropped = bp->xmt_discards; - bp->stats.multicast = bp->rcv_multicast_frames; - bp->stats.transmit_collision = 0; /* always zero (0) for FDDI */ + bp->stats.gen.rx_packets = bp->rcv_total_frames; + bp->stats.gen.tx_packets = bp->xmt_total_frames; + bp->stats.gen.rx_bytes = bp->rcv_total_bytes; + bp->stats.gen.tx_bytes = bp->xmt_total_bytes; + bp->stats.gen.rx_errors = bp->rcv_crc_errors + + bp->rcv_frame_status_errors + + bp->rcv_length_errors; + bp->stats.gen.tx_errors = bp->xmt_length_errors; + bp->stats.gen.rx_dropped = bp->rcv_discards; + bp->stats.gen.tx_dropped = bp->xmt_discards; + bp->stats.gen.multicast = bp->rcv_multicast_frames; + bp->stats.gen.collisions = 0; /* always zero (0) for FDDI */ /* Get FDDI SMT MIB objects */ @@ -2666,12 +2670,12 @@ static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type) static void my_skb_align(struct sk_buff *skb, int n) { - unsigned long x=(unsigned long)skb->data; + unsigned long x = (unsigned long)skb->data; unsigned long v; - v=(x+n-1)&~(n-1); /* Where we want to be */ + v = ALIGN(x, n); /* Where we want to be */ - skb_reserve(skb, v-x); + skb_reserve(skb, v - x); } @@ -3426,11 +3430,6 @@ static int __init dfx_init(void) { int rc_pci, rc_eisa; -/* when a module, this is printed whether or not devices are found in probe */ -#ifdef MODULE - printk(version); -#endif - rc_pci = pci_module_init(&dfx_driver); if (rc_pci >= 0) dfx_have_pci = 1; @@ -3451,6 +3450,9 @@ static void __exit dfx_cleanup(void) module_init(dfx_init); module_exit(dfx_cleanup); +MODULE_AUTHOR("Lawrence V. Stefani"); +MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver " + DRV_VERSION " " DRV_RELDATE); MODULE_LICENSE("GPL"); diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h index 6a04896cb..a480b80d2 100644 --- a/drivers/net/defxx.h +++ b/drivers/net/defxx.h @@ -16,7 +16,7 @@ * LVS Lawrence V. Stefani * * Maintainers: - * macro Maciej W. Rozycki + * macro Maciej W. Rozycki * * Modification History: * Date Name Description diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 5d62a032b..28109cb70 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -255,9 +255,9 @@ #include #include #include +#include #include -#include #include #include @@ -666,7 +666,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) outb(nicsr, DEPCA_NICSR); } - lp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->lock); sprintf(lp->adapter_name, "%s (%s)", depca_signature[lp->adapter], device->bus_id); status = -EBUSY; @@ -1222,10 +1222,10 @@ static int InitRestartDepca(struct net_device *dev) /* clear IDON by writing a "1", enable interrupts and start lance */ outw(IDON | INEA | STRT, DEPCA_DATA); if (depca_debug > 2) { - printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); + printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA)); } } else { - printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); + printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->mem_start, inw(DEPCA_DATA)); status = -1; } @@ -1901,7 +1901,7 @@ static void depca_dbg_open(struct net_device *dev) } } printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); - printk("Initialisation block at 0x%8.8lx(Phys)\n", virt_to_phys(lp->sh_mem)); + printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start); printk(" mode: 0x%4.4x\n", p->mode); printk(" physical address: "); for (i = 0; i < ETH_ALEN - 1; i++) { @@ -1915,7 +1915,7 @@ static void depca_dbg_open(struct net_device *dev) printk("%2.2x\n", p->mcast_table[i]); printk(" rx_ring at: 0x%8.8x\n", p->rx_ring); printk(" tx_ring at: 0x%8.8x\n", p->tx_ring); - printk("buffers (Phys): 0x%8.8lx\n", virt_to_phys(lp->sh_mem) + lp->buffs_offset); + printk("buffers (Phys): 0x%8.8lx\n", lp->mem_start + lp->buffs_offset); printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen); printk("TX: %d Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen); outw(CSR2, DEPCA_ADDR); diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index c496ebfc8..779af1727 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -97,8 +97,8 @@ #include #include #include +#include -#include #include #include #include @@ -1597,10 +1597,10 @@ static int __init dgrs_init_module (void) #endif #ifdef CONFIG_PCI pcicount = pci_register_driver(&dgrs_pci_driver); - if (pcicount < 0) + if (pcicount) return pcicount; #endif - return (eisacount + pcicount) == 0 ? -ENODEV : 0; + return 0; } static void __exit dgrs_cleanup_module (void) diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 53f01d51c..575896cb9 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -107,7 +107,6 @@ static int change_mtu (struct net_device *dev, int new_mtu); static void set_multicast (struct net_device *dev); static struct net_device_stats *get_stats (struct net_device *dev); static int clear_stats (struct net_device *dev); -static int rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr); static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int rio_close (struct net_device *dev); static int find_miiphy (struct net_device *dev); @@ -122,6 +121,8 @@ static int mii_read (struct net_device *dev, int phy_addr, int reg_num); static int mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data); +static struct ethtool_ops ethtool_ops; + static int __devinit rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -168,7 +169,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) #endif dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->chip_id = chip_idx; np->pdev = pdev; spin_lock_init (&np->tx_lock); @@ -244,6 +245,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) dev->tx_timeout = &rio_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; + SET_ETHTOOL_OPS(dev, ðtool_ops); #if 0 dev->features = NETIF_F_IP_CSUM; #endif @@ -335,7 +337,7 @@ find_miiphy (struct net_device *dev) int i, phy_found = 0; struct netdev_private *np; long ioaddr; - np = dev->priv; + np = netdev_priv(dev); ioaddr = dev->base_addr; np->phy_addr = 1; @@ -362,7 +364,7 @@ parse_eeprom (struct net_device *dev) u8 *psib; u32 crc; PSROM_t psrom = (PSROM_t) sromdata; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int cid, next; @@ -432,7 +434,7 @@ parse_eeprom (struct net_device *dev) static int rio_open (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; u16 macctrl; @@ -516,7 +518,7 @@ static void rio_timer (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned int entry; int next_tick = 1*HZ; unsigned long flags; @@ -574,7 +576,7 @@ rio_tx_timeout (struct net_device *dev) static void alloc_list (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -631,7 +633,7 @@ alloc_list (struct net_device *dev) static int start_xmit (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; u32 ioaddr; @@ -711,7 +713,7 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); while (1) { int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); @@ -745,7 +747,7 @@ rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs) static void rio_free_tx (struct net_device *dev, int irq) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->old_tx % TX_RING_SIZE; int tx_use = 0; unsigned long flag = 0; @@ -798,7 +800,7 @@ tx_error (struct net_device *dev, int tx_status) int frame_id; int i; - np = dev->priv; + np = netdev_priv(dev); frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", @@ -855,7 +857,7 @@ tx_error (struct net_device *dev, int tx_status) static int receive_packet (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int cnt = 30; @@ -965,7 +967,7 @@ static void rio_error (struct net_device *dev, int int_status) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 macctrl; /* Link change event */ @@ -1016,7 +1018,7 @@ static struct net_device_stats * get_stats (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); #ifdef MEM_MAPPING int i; #endif @@ -1132,7 +1134,7 @@ clear_stats (struct net_device *dev) int change_mtu (struct net_device *dev, int new_mtu) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int max = (np->jumbo) ? MAX_JUMBO : 1536; if ((new_mtu < 68) || (new_mtu > max)) { @@ -1150,7 +1152,7 @@ set_multicast (struct net_device *dev) long ioaddr = dev->base_addr; u32 hash_table[2]; u16 rx_mode = 0; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); hash_table[0] = hash_table[1] = 0; /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ @@ -1194,137 +1196,118 @@ set_multicast (struct net_device *dev) writew (rx_mode, ioaddr + ReceiveMode); } -static int -rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, "DL2K"); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); +} + +static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; - u32 ethcmd; + struct netdev_private *np = netdev_priv(dev); + if (np->phy_media) { + /* fiber device */ + cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE; + cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + } else { + /* copper device */ + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_MII; + cmd->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| + ADVERTISED_Autoneg | ADVERTISED_MII; + cmd->port = PORT_MII; + cmd->transceiver = XCVR_INTERNAL; + } + if ( np->link_status ) { + cmd->speed = np->speed; + cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + } else { + cmd->speed = -1; + cmd->duplex = -1; + } + if ( np->an_enable) + cmd->autoneg = AUTONEG_ENABLE; + else + cmd->autoneg = AUTONEG_DISABLE; - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "DL2K"); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pdev)); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; + cmd->phy_address = np->phy_addr; + return 0; +} + +static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct netdev_private *np = netdev_priv(dev); + netif_carrier_off(dev); + if (cmd->autoneg == AUTONEG_ENABLE) { + if (np->an_enable) return 0; + else { + np->an_enable = 1; + mii_set_media(dev); + return 0; } - - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - if (np->phy_media) { - /* fiber device */ - cmd.supported = SUPPORTED_Autoneg | - SUPPORTED_FIBRE; - cmd.advertising= ADVERTISED_Autoneg | - ADVERTISED_FIBRE; - cmd.port = PORT_FIBRE; - cmd.transceiver = XCVR_INTERNAL; - } else { - /* copper device */ - cmd.supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_MII; - cmd.advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| - ADVERTISED_Autoneg | ADVERTISED_MII; - cmd.port = PORT_MII; - cmd.transceiver = XCVR_INTERNAL; - } - if ( np->link_status ) { - cmd.speed = np->speed; - cmd.duplex = np->full_duplex ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - cmd.speed = -1; - cmd.duplex = -1; - } - if ( np->an_enable) - cmd.autoneg = AUTONEG_ENABLE; - else - cmd.autoneg = AUTONEG_DISABLE; - - cmd.phy_address = np->phy_addr; - - if (copy_to_user(useraddr, &cmd, - sizeof(cmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - netif_carrier_off(dev); - if (cmd.autoneg == AUTONEG_ENABLE) { - if (np->an_enable) - return 0; - else { - np->an_enable = 1; - mii_set_media(dev); - return 0; - } - } else { - np->an_enable = 0; - if (np->speed == 1000){ - cmd.speed = SPEED_100; - cmd.duplex = DUPLEX_FULL; - printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manul 100Mbps, Full duplex.\n"); - } - switch(cmd.speed + cmd.duplex){ - - case SPEED_10 + DUPLEX_HALF: - np->speed = 10; - np->full_duplex = 0; - break; - - case SPEED_10 + DUPLEX_FULL: - np->speed = 10; - np->full_duplex = 1; - break; - case SPEED_100 + DUPLEX_HALF: - np->speed = 100; - np->full_duplex = 0; - break; - case SPEED_100 + DUPLEX_FULL: - np->speed = 100; - np->full_duplex = 1; - break; - case SPEED_1000 + DUPLEX_HALF:/* not supported */ - case SPEED_1000 + DUPLEX_FULL:/* not supported */ - default: - return -EINVAL; - } - mii_set_media(dev); - } - return 0; + } else { + np->an_enable = 0; + if (np->speed == 1000) { + cmd->speed = SPEED_100; + cmd->duplex = DUPLEX_FULL; + printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n"); } -#ifdef ETHTOOL_GLINK - case ETHTOOL_GLINK:{ - struct ethtool_value link = { ETHTOOL_GLINK }; - link.data = np->link_status; - if (copy_to_user(useraddr, &link, sizeof(link))) - return -EFAULT; - return 0; - } -#endif + switch(cmd->speed + cmd->duplex) { + + case SPEED_10 + DUPLEX_HALF: + np->speed = 10; + np->full_duplex = 0; + break; + + case SPEED_10 + DUPLEX_FULL: + np->speed = 10; + np->full_duplex = 1; + break; + case SPEED_100 + DUPLEX_HALF: + np->speed = 100; + np->full_duplex = 0; + break; + case SPEED_100 + DUPLEX_FULL: + np->speed = 100; + np->full_duplex = 1; + break; + case SPEED_1000 + DUPLEX_HALF:/* not supported */ + case SPEED_1000 + DUPLEX_FULL:/* not supported */ default: - return -EOPNOTSUPP; - } + return -EINVAL; + } + mii_set_media(dev); + } + return 0; +} + +static u32 rio_get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->link_status; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = rio_get_drvinfo, + .get_settings = rio_get_settings, + .set_settings = rio_set_settings, + .get_link = rio_get_link, +}; static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { int phy_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; struct netdev_desc *desc; @@ -1332,8 +1315,6 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) phy_addr = np->phy_addr; switch (cmd) { - case SIOCETHTOOL: - return rio_ethtool_ioctl(dev, rq->ifr_data); case SIOCDEVPRIVATE: break; @@ -1490,7 +1471,7 @@ mii_wait_link (struct net_device *dev, int wait) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; do { @@ -1512,7 +1493,7 @@ mii_get_media (struct net_device *dev) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, MII_BMSR); @@ -1594,7 +1575,7 @@ mii_set_media (struct net_device *dev) ANAR_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Does user set speed? */ @@ -1684,7 +1665,7 @@ mii_get_media_pcs (struct net_device *dev) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, PCS_BMSR); @@ -1740,7 +1721,7 @@ mii_set_media_pcs (struct net_device *dev) ANAR_PCS_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Auto-Negotiation? */ @@ -1794,7 +1775,7 @@ static int rio_close (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1840,7 +1821,7 @@ rio_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev (dev); pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index 86302faf9..6e75482d7 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -28,8 +28,8 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -92,7 +92,7 @@ enum dl2x_offsets { EepromCtrl = 0x4a, ExpromAddr = 0x4c, Exprodata = 0x50, - WakeEvent0x51, + WakeEvent = 0x51, CountDown = 0x54, IntStatusAck = 0x5a, IntEnable = 0x5c, diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 7e15c51af..dd8c15ac5 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -77,7 +77,7 @@ static void __init dummy_setup(struct net_device *dev) static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *stats = dev->priv; + struct net_device_stats *stats = netdev_priv(dev); stats->tx_packets++; stats->tx_bytes+=skb->len; @@ -88,7 +88,7 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *dummy_get_stats(struct net_device *dev) { - return dev->priv; + return netdev_priv(dev); } static struct net_device **dummies; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 8855b20e3..c075355aa 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -87,9 +87,8 @@ * cb_to_use is the next CB to use for queuing a command; cb_to_clean * is the next CB to check for completion; cb_to_send is the first * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt, or - * in dev->poll in the case where NAPI is enabled. cbs_avail keeps - * track of number of free CB resources available. + * up happens in interrupt context in response to a CU interrupt. + * cbs_avail keeps track of number of free CB resources available. * * Hardware padding of short packets to minimum packet size is * enabled. 82557 pads with 7Eh, while the later controllers pad @@ -112,9 +111,8 @@ * replacement RFDs cannot be allocated, or the RU goes non-active, * the RU must be restarted. Frame arrival generates an interrupt, * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. If NAPI is enabled, this work - * happens in dev->poll. A software-generated interrupt is gen- - * erated from the watchdog to recover from a failed allocation + * therefore no locking is required. A software-generated interrupt + * is generated from the watchdog to recover from a failed allocation * senario where all Rx resources have been indicated and none re- * placed. * @@ -126,8 +124,6 @@ * supported. Tx Scatter/Gather is not supported. Jumbo Frames is * not supported (hardware limitation). * - * NAPI support is enabled with CONFIG_E100_NAPI. - * * MagicPacket(tm) WoL support is enabled/disabled via ethtool. * * Thanks to JC (jchapman@katalix.com) for helping with @@ -158,7 +154,8 @@ #define DRV_NAME "e100" -#define DRV_VERSION "3.0.18" +#define DRV_EXT "-NAPI" +#define DRV_VERSION "3.2.3-k2"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation" #define PFX DRV_NAME ": " @@ -201,6 +198,8 @@ static struct pci_device_id e100_id_table[] = { INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1056, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1057, 5), INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), @@ -242,6 +241,7 @@ enum phy { phy_nsc_tx = 0x5C002000, phy_82562_et = 0x033002A8, phy_82562_em = 0x032002A8, + phy_82562_ek = 0x031002A8, phy_82562_eh = 0x017002A8, phy_unknown = 0xFFFFFFFF, }; @@ -330,11 +330,16 @@ enum eeprom_op { }; enum eeprom_offsets { + eeprom_cnfg_mdix = 0x03, eeprom_id = 0x0A, eeprom_config_asf = 0x0D, eeprom_smbus_addr = 0x90, }; +enum eeprom_cnfg_mdix { + eeprom_mdix_enabled = 0x0080, +}; + enum eeprom_id { eeprom_id_wol = 0x0020, }; @@ -350,10 +355,12 @@ enum cb_status { }; enum cb_command { + cb_nop = 0x0000, cb_iaaddr = 0x0001, cb_config = 0x0002, cb_multi = 0x0003, cb_tx = 0x0004, + cb_ucode = 0x0005, cb_dump = 0x0006, cb_tx_sf = 0x0008, cb_cid = 0x1f00, @@ -428,12 +435,14 @@ struct multi { }; /* Important: keep total struct u32-aligned */ +#define UCODE_SIZE 134 struct cb { u16 status; u16 command; u32 link; union { u8 iaaddr[ETH_ALEN]; + u32 ucode[UCODE_SIZE]; struct config config; struct multi multi; struct { @@ -504,7 +513,7 @@ struct nic { spinlock_t cb_lock ____cacheline_aligned; spinlock_t cmd_lock; - struct csr *csr; + struct csr __iomem *csr; enum scb_cmd_lo cuc_cmd; unsigned int cbs_avail; struct cb *cbs; @@ -548,12 +557,12 @@ struct nic { u32 rx_fc_pause; u32 rx_fc_unsupported; u32 rx_tco_frames; + u32 rx_over_length_errors; u8 rev_id; u16 leds; u16 eeprom_wc; u16 eeprom[256]; - u32 pm_state[16]; }; static inline void e100_write_flush(struct nic *nic) @@ -565,13 +574,21 @@ static inline void e100_write_flush(struct nic *nic) static inline void e100_enable_irq(struct nic *nic) { + unsigned long flags; + + spin_lock_irqsave(&nic->cmd_lock, flags); writeb(irq_mask_none, &nic->csr->scb.cmd_hi); + spin_unlock_irqrestore(&nic->cmd_lock, flags); e100_write_flush(nic); } static inline void e100_disable_irq(struct nic *nic) { + unsigned long flags; + + spin_lock_irqsave(&nic->cmd_lock, flags); writeb(irq_mask_all, &nic->csr->scb.cmd_hi); + spin_unlock_irqrestore(&nic->cmd_lock, flags); e100_write_flush(nic); } @@ -586,16 +603,6 @@ static void e100_hw_reset(struct nic *nic) writel(software_reset, &nic->csr->port); e100_write_flush(nic); udelay(20); - /* TCO workaround - 82559 and greater */ - if(nic->mac >= mac_82559_D101M) { - /* Issue a redundant CU load base without setting - * general pointer, and without waiting for scb to - * clear. This gets us into post-driver. Finally, - * wait 20 msec for reset to take effect. */ - writeb(cuc_load_base, &nic->csr->scb.cmd_lo); - mdelay(20); - } - /* Mask off our interrupt line - it's unmasked after reset */ e100_disable_irq(nic); } @@ -980,6 +987,27 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); } +static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) +{ + int i; + static const u32 ucode[UCODE_SIZE] = { + /* NFS packets are misinterpreted as TCO packets and + * incorrectly routed to the BMC over SMBus. This + * microcode patch checks the fragmented IP bit in the + * NFS/UDP header to distinguish between NFS and TCO. */ + 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, + 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, + 0x00906EFD, 0x00900EFD, 0x00E00EF8, + }; + + if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) { + for(i = 0; i < UCODE_SIZE; i++) + cb->u.ucode[i] = cpu_to_le32(ucode[i]); + cb->command = cpu_to_le16(cb_ucode); + } else + cb->command = cpu_to_le16(cb_nop); +} + static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, struct sk_buff *skb) { @@ -1045,7 +1073,9 @@ static int e100_phy_init(struct nic *nic) mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); } - if(nic->mac >= mac_82550_D102) + if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && + (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && + (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) /* enable/disable MDI/MDI-X auto-switching */ mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); @@ -1069,6 +1099,8 @@ static int e100_hw_init(struct nic *nic) return err; if((err = e100_exec_cmd(nic, ruc_load_base, 0))) return err; + if((err = e100_exec_cb(nic, NULL, e100_load_ucode))) + return err; if((err = e100_exec_cb(nic, NULL, e100_configure))) return err; if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) @@ -1143,9 +1175,11 @@ static void e100_update_stats(struct nic *nic) ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + le32_to_cpu(s->tx_lost_crs); ns->rx_dropped += le32_to_cpu(s->rx_resource_errors); - ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors); + ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + + nic->rx_over_length_errors; ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); + ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + le32_to_cpu(s->rx_alignment_errors) + @@ -1217,8 +1251,13 @@ static void e100_watchdog(unsigned long data) mii_check_link(&nic->mii); /* Software generated interrupt to recover from (rare) Rx - * allocation failure */ - writeb(irq_sw_gen, &nic->csr->scb.cmd_hi); + * allocation failure. + * Unfortunately have to use a spinlock to not re-enable interrupts + * accidentally, due to hardware that shares a register between the + * interrupt mask bit and the SW Interrupt generation bit */ + spin_lock_irq(&nic->cmd_lock); + writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi); + spin_unlock_irq(&nic->cmd_lock); e100_write_flush(nic); e100_update_stats(nic); @@ -1268,6 +1307,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) switch(err) { case -ENOSPC: /* We queued the skb, but now we're out of space. */ + DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); netif_stop_queue(netdev); break; case -ENOMEM: @@ -1388,14 +1428,12 @@ static inline void e100_start_receiver(struct nic *nic) #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) { - unsigned int rx_offset = 2; /* u32 align protocol headers */ - - if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset))) + if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) return -ENOMEM; /* Align, init, and map the RFD. */ rx->skb->dev = nic->netdev; - skb_reserve(rx->skb, rx_offset); + skb_reserve(rx->skb, NET_IP_ALIGN); memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd)); rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); @@ -1434,7 +1472,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, /* If data isn't ready, nothing to indicate */ if(unlikely(!(rfd_status & cb_complete))) - return -EAGAIN; + return -EAGAIN; /* Get actual data size */ actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; @@ -1456,18 +1494,14 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, dev_kfree_skb_any(skb); } else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) { /* Don't indicate oversized frames */ - nic->net_stats.rx_over_errors++; + nic->rx_over_length_errors++; nic->net_stats.rx_dropped++; dev_kfree_skb_any(skb); } else { nic->net_stats.rx_packets++; nic->net_stats.rx_bytes += actual_size; nic->netdev->last_rx = jiffies; -#ifdef CONFIG_E100_NAPI netif_receive_skb(skb); -#else - netif_rx(skb); -#endif if(work_done) (*work_done)++; } @@ -1562,20 +1596,12 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) if(stat_ack & stat_ack_rnr) nic->ru_running = 0; -#ifdef CONFIG_E100_NAPI e100_disable_irq(nic); netif_rx_schedule(netdev); -#else - if(stat_ack & stat_ack_rx) - e100_rx_clean(nic, NULL, 0); - if(stat_ack & stat_ack_tx) - e100_tx_clean(nic); -#endif return IRQ_HANDLED; } -#ifdef CONFIG_E100_NAPI static int e100_poll(struct net_device *netdev, int *budget) { struct nic *nic = netdev_priv(netdev); @@ -1598,7 +1624,6 @@ static int e100_poll(struct net_device *netdev, int *budget) return 1; } -#endif #ifdef CONFIG_NET_POLL_CONTROLLER static void e100_netpoll(struct net_device *netdev) @@ -1641,7 +1666,7 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu) static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ - return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) && + return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && (nic->eeprom[eeprom_config_asf] & eeprom_asf) && !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); @@ -1739,7 +1764,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), skb->data, ETH_DATA_LEN)) - err = -EAGAIN; + err = -EAGAIN; err_loopback_none: mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); @@ -1932,12 +1957,17 @@ static int e100_set_ringparam(struct net_device *netdev, struct param_range *rfds = &nic->params.rfds; struct param_range *cbs = &nic->params.cbs; + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + if(netif_running(netdev)) e100_down(nic); rfds->count = max(ring->rx_pending, rfds->min); rfds->count = min(rfds->count, rfds->max); cbs->count = max(ring->tx_pending, cbs->min); cbs->count = min(cbs->count, cbs->max); + DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", + rfds->count, cbs->count); if(netif_running(netdev)) e100_up(nic); @@ -1961,18 +1991,27 @@ static int e100_diag_test_count(struct net_device *netdev) static void e100_diag_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) { + struct ethtool_cmd cmd; struct nic *nic = netdev_priv(netdev); - int i; + int i, err; memset(data, 0, E100_TEST_LEN * sizeof(u64)); data[0] = !mii_link_ok(&nic->mii); data[1] = e100_eeprom_load(nic); if(test->flags & ETH_TEST_FL_OFFLINE) { + + /* save speed, duplex & autoneg settings */ + err = mii_ethtool_gset(&nic->mii, &cmd); + if(netif_running(netdev)) e100_down(nic); data[2] = e100_self_test(nic); data[3] = e100_loopback_test(nic, lb_mac); data[4] = e100_loopback_test(nic, lb_phy); + + /* restore speed, duplex & autoneg settings */ + err = mii_ethtool_sset(&nic->mii, &cmd); + if(netif_running(netdev)) e100_up(nic); } @@ -2135,13 +2174,12 @@ static int __devinit e100_probe(struct pci_dev *pdev, SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); netdev->tx_timeout = e100_tx_timeout; netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_E100_NAPI netdev->poll = e100_poll; netdev->weight = E100_NAPI_WEIGHT; -#endif #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = e100_netpoll; #endif + strcpy(netdev->name, pci_name(pdev)); nic = netdev_priv(netdev); nic->netdev = netdev; @@ -2166,8 +2204,6 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_disable_pdev; } - pci_set_master(pdev); - if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) { DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); goto err_out_free_res; @@ -2188,9 +2224,18 @@ static int __devinit e100_probe(struct pci_dev *pdev, else nic->flags &= ~ich; + e100_get_defaults(nic); + spin_lock_init(&nic->cb_lock); spin_lock_init(&nic->cmd_lock); + /* Reset the device before pci_set_master() in case device is in some + * funky state and has an interrupt pending - hint: we don't have the + * interrupt handler registered yet. */ + e100_hw_reset(nic); + + pci_set_master(pdev); + init_timer(&nic->watchdog); nic->watchdog.function = e100_watchdog; nic->watchdog.data = (unsigned long)nic; @@ -2203,8 +2248,6 @@ static int __devinit e100_probe(struct pci_dev *pdev, goto err_out_iounmap; } - e100_get_defaults(nic); - e100_hw_reset(nic); e100_phy_init(nic); if((err = e100_eeprom_load(nic))) @@ -2225,6 +2268,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); + strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) { DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); goto err_out_free; @@ -2279,7 +2323,7 @@ static int e100_suspend(struct pci_dev *pdev, u32 state) e100_hw_reset(nic); netif_device_detach(netdev); - pci_save_state(pdev, nic->pm_state); + pci_save_state(pdev); pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic))); pci_disable_device(pdev); pci_set_power_state(pdev, state); @@ -2293,7 +2337,7 @@ static int e100_resume(struct pci_dev *pdev) struct nic *nic = netdev_priv(netdev); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, nic->pm_state); + pci_restore_state(pdev); e100_hw_init(nic); netif_device_attach(netdev); @@ -2321,7 +2365,7 @@ static int __init e100_init_module(void) printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); } - return pci_module_init(&e100_driver); + return pci_module_init(&e100_driver); } static void __exit e100_cleanup_module(void) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 067bb099e..77db78960 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -49,11 +49,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include #include @@ -71,12 +72,13 @@ #include #include #include -#include #define BAR_0 0 #define BAR_1 1 #define BAR_5 5 +#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} struct e1000_adapter; @@ -98,11 +100,12 @@ struct e1000_adapter; #define E1000_MAX_INTR 10 -/* How many descriptors for TX and RX ? */ +/* TX/RX descriptor defines */ #define E1000_DEFAULT_TXD 256 #define E1000_MAX_TXD 256 #define E1000_MIN_TXD 80 #define E1000_MAX_82544_TXD 4096 + #define E1000_DEFAULT_RXD 256 #define E1000_MAX_RXD 256 #define E1000_MIN_RXD 80 @@ -123,14 +126,11 @@ struct e1000_adapter; #define E1000_TX_HEAD_ADDR_SHIFT 7 #define E1000_PBA_TX_MASK 0xFFFF0000 -/* Flow Control High-Watermark: 5688 bytes below Rx FIFO size */ -#define E1000_FC_HIGH_DIFF 0x1638 - -/* Flow Control Low-Watermark: 5696 bytes below Rx FIFO size */ -#define E1000_FC_LOW_DIFF 0x1640 +/* Flow Control Watermarks */ +#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */ +#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */ -/* Flow Control Pause Time: 858 usec */ -#define E1000_FC_PAUSE_TIME 0x0680 +#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ /* How many Tx Descriptors do we need to call netif_wake_queue ? */ #define E1000_TX_QUEUE_WAKE 16 @@ -153,9 +153,9 @@ struct e1000_adapter; struct e1000_buffer { struct sk_buff *skb; uint64_t dma; - unsigned long length; unsigned long time_stamp; - unsigned int next_to_watch; + uint16_t length; + uint16_t next_to_watch; }; struct e1000_desc_ring { @@ -202,7 +202,7 @@ struct e1000_adapter { spinlock_t stats_lock; atomic_t irq_sem; struct work_struct tx_timeout_task; - uint8_t fc_autoneg; + uint8_t fc_autoneg; struct timer_list blink_timer; unsigned long led_status; @@ -252,7 +252,6 @@ struct e1000_adapter { struct e1000_desc_ring test_rx_ring; - uint32_t pci_state[16]; int msg_enable; }; #endif /* _E1000_H_ */ diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 9ca716eab..cc50e4d5d 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -88,9 +88,9 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, + { "rx_long_byte_count", E1000_STAT(stats.gorcl) }, { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, - { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, - { "rx_long_byte_count", E1000_STAT(stats.gorcl) } + { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) } }; #define E1000_STATS_LEN \ sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats) @@ -170,7 +170,8 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->duplex = -1; } - ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || + hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0; } @@ -192,6 +193,7 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if(netif_running(adapter->netdev)) { e1000_down(adapter); + e1000_reset(adapter); e1000_up(adapter); } else e1000_reset(adapter); @@ -199,12 +201,13 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return 0; } -static void +static void e1000_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; + pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); @@ -218,9 +221,9 @@ e1000_get_pauseparam(struct net_device *netdev, } } -static int +static int e1000_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; @@ -246,7 +249,8 @@ e1000_set_pauseparam(struct net_device *netdev, e1000_reset(adapter); } else - return e1000_force_mac_fc(hw); + return ((hw->media_type == e1000_media_type_fiber) ? + e1000_setup_link(hw) : e1000_force_mac_fc(hw)); return 0; } @@ -271,7 +275,7 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data) e1000_reset(adapter); return 0; } - + static uint32_t e1000_get_tx_csum(struct net_device *netdev) { @@ -337,7 +341,7 @@ e1000_get_regs_len(struct net_device *netdev) static void e1000_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) + struct ethtool_regs *regs, void *p) { struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; @@ -418,6 +422,10 @@ e1000_get_regs(struct net_device *netdev, e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ + if(hw->mac_type >= e1000_82540 && + hw->media_type == e1000_media_type_copper) { + regs_buff[26] = E1000_READ_REG(hw, MANC); + } } static int @@ -438,7 +446,7 @@ e1000_get_eeprom(struct net_device *netdev, int ret_val = 0; uint16_t i; - if(eeprom->len == 0) + if(eeprom->len == 0) return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); @@ -446,9 +454,9 @@ e1000_get_eeprom(struct net_device *netdev, first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(sizeof(uint16_t) * + eeprom_buff = kmalloc(sizeof(uint16_t) * (last_word - first_word + 1), GFP_KERNEL); - if (!eeprom_buff) + if(!eeprom_buff) return -ENOMEM; if(hw->eeprom.type == e1000_eeprom_spi) @@ -466,9 +474,8 @@ e1000_get_eeprom(struct net_device *netdev, for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); - - memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset%2), - eeprom->len); + memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1), + eeprom->len); kfree(eeprom_buff); return ret_val; @@ -520,6 +527,7 @@ e1000_set_eeprom(struct net_device *netdev, le16_to_cpus(&eeprom_buff[i]); memcpy(ptr, bytes, eeprom->len); + for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); @@ -575,17 +583,19 @@ static int e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { - int err; struct e1000_adapter *adapter = netdev->priv; e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; - struct e1000_desc_ring tx_old, tx_new; - struct e1000_desc_ring rx_old, rx_new; + struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new; + int err; tx_old = adapter->tx_ring; rx_old = adapter->rx_ring; - + + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + if(netif_running(adapter->netdev)) e1000_down(adapter); @@ -600,15 +610,15 @@ e1000_set_ringparam(struct net_device *netdev, E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); if(netif_running(adapter->netdev)) { - /* try to get new resources before deleting old */ + /* Try to get new resources before deleting old */ if((err = e1000_setup_rx_resources(adapter))) goto err_setup_rx; if((err = e1000_setup_tx_resources(adapter))) goto err_setup_tx; /* save the new, restore the old in order to free it, - * then restore the new back again */ - + * then restore the new back again */ + rx_new = adapter->rx_ring; tx_new = adapter->tx_ring; adapter->rx_ring = rx_old; @@ -620,6 +630,7 @@ e1000_set_ringparam(struct net_device *netdev, if((err = e1000_up(adapter))) return err; } + return 0; err_setup_tx: e1000_free_rx_resources(adapter); @@ -630,7 +641,6 @@ err_setup_rx: return err; } - #define REG_PATTERN_TEST(R, M, W) \ { \ uint32_t pat, value; \ @@ -766,13 +776,15 @@ static int e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) { struct net_device *netdev = adapter->netdev; - uint32_t icr, mask, i=0; + uint32_t icr, mask, i=0, shared_int = TRUE; + uint32_t irq = adapter->pdev->irq; *data = 0; /* Hook up test interrupt handler just for this test */ - if(request_irq(adapter->pdev->irq, &e1000_test_intr, SA_SHIRQ, - netdev->name, netdev)) { + if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) { + shared_int = FALSE; + } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){ *data = 1; return -1; } @@ -802,20 +814,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) /* Interrupt to test */ mask = 1 << i; - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, mask); - E1000_WRITE_REG(&adapter->hw, ICS, mask); - msec_delay(10); - - if(adapter->test_icr & mask) { - *data = 3; - break; + if(!shared_int) { + /* Disable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMC, mask); + E1000_WRITE_REG(&adapter->hw, ICS, mask); + msec_delay(10); + + if(adapter->test_icr & mask) { + *data = 3; + break; + } } /* Enable the interrupt to be reported in @@ -834,20 +848,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) break; } - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, ~mask); - E1000_WRITE_REG(&adapter->hw, ICS, ~mask); - msec_delay(10); + if(!shared_int) { + /* Disable the other interrupts to be reported in + * the cause register and then force the other + * interrupts and see if any get posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMC, ~mask); + E1000_WRITE_REG(&adapter->hw, ICS, ~mask); + msec_delay(10); - if(adapter->test_icr) { - *data = 5; - break; + if(adapter->test_icr) { + *data = 5; + break; + } } } @@ -856,7 +872,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) msec_delay(10); /* Unhook test interrupt handler */ - free_irq(adapter->pdev->irq, netdev); + free_irq(irq, netdev); return *data; } @@ -1004,8 +1020,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); struct sk_buff *skb; - if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, - GFP_KERNEL))) { + if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, + GFP_KERNEL))) { ret_val = 6; goto err_nomem; } @@ -1021,7 +1037,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter) return 0; - err_nomem: +err_nomem: e1000_free_desc_rings(adapter); return ret_val; } @@ -1312,15 +1328,15 @@ e1000_run_loopback_test(struct e1000_adapter *adapter) for(i = 0; i < 64; i++) { e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024); - pci_dma_sync_single(pdev, txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - PCI_DMA_TODEVICE); + pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma, + txdr->buffer_info[i].length, + PCI_DMA_TODEVICE); } E1000_WRITE_REG(&adapter->hw, TDT, i); msec_delay(200); - pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma, + pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[0].dma, rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE); return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024); @@ -1357,7 +1373,7 @@ e1000_diag_test_count(struct net_device *netdev) } static void -e1000_diag_test(struct net_device *netdev, +e1000_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, uint64_t *data) { struct e1000_adapter *adapter = netdev->priv; @@ -1368,7 +1384,7 @@ e1000_diag_test(struct net_device *netdev, /* save speed, duplex, autoneg settings */ uint16_t autoneg_advertised = adapter->hw.autoneg_advertised; - uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex; + uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex; uint8_t autoneg = adapter->hw.autoneg; /* Link test performed before hardware reset so autoneg doesn't @@ -1396,10 +1412,11 @@ e1000_diag_test(struct net_device *netdev, if(e1000_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; - /* restore Autoneg/speed/duplex settings */ + /* restore speed, duplex, autoneg settings */ adapter->hw.autoneg_advertised = autoneg_advertised; - adapter->hw.forced_speed_duplex = forced_speed_duplex; - adapter->hw.autoneg = autoneg; + adapter->hw.forced_speed_duplex = forced_speed_duplex; + adapter->hw.autoneg = autoneg; + e1000_reset(adapter); if(if_running) e1000_up(adapter); @@ -1427,6 +1444,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: case E1000_DEV_ID_82544EI_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: + case E1000_DEV_ID_82545EM_FIBER: + case E1000_DEV_ID_82545EM_COPPER: wol->supported = 0; wol->wolopts = 0; return; @@ -1469,6 +1489,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: case E1000_DEV_ID_82544EI_FIBER: + case E1000_DEV_ID_82546EB_QUAD_COPPER: return wol->wolopts ? -EOPNOTSUPP : 0; case E1000_DEV_ID_82546EB_FIBER: @@ -1571,8 +1592,8 @@ e1000_get_ethtool_stats(struct net_device *netdev, e1000_update_stats(adapter); for(i = 0; i < E1000_STATS_LEN; i++) { char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; - data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) - ? *(uint64_t *)p : *(uint32_t *)p; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == + sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; } } diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 41c05e5c3..0c7d458fd 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -65,6 +65,7 @@ static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); static int32_t e1000_set_vco_speed(struct e1000_hw *hw); +static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw); static int32_t e1000_set_phy_mode(struct e1000_hw *hw); /* IGP cable length table */ @@ -251,6 +252,7 @@ e1000_set_mac_type(struct e1000_hw *hw) break; case E1000_DEV_ID_82541ER: case E1000_DEV_ID_82541GI: + case E1000_DEV_ID_82541GI_LF: case E1000_DEV_ID_82541GI_MOBILE: hw->mac_type = e1000_82541_rev_2; break; @@ -920,7 +922,8 @@ e1000_setup_copper_link(struct e1000_hw *hw) if(ret_val) return ret_val; - if(hw->mac_type == e1000_82545_rev_3) { + if((hw->mac_type == e1000_82545_rev_3) || + (hw->mac_type == e1000_82546_rev_3)) { ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); phy_data |= 0x00000008; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); @@ -1592,6 +1595,15 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if(ret_val) return ret_val; + + if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) && + (!hw->autoneg) && + (hw->forced_speed_duplex == e1000_10_full || + hw->forced_speed_duplex == e1000_10_half)) { + ret_val = e1000_polarity_reversal_workaround(hw); + if(ret_val) + return ret_val; + } } return E1000_SUCCESS; } @@ -1981,6 +1993,7 @@ e1000_check_for_link(struct e1000_hw *hw) uint32_t ctrl; uint32_t status; uint32_t rctl; + uint32_t icr; uint32_t signal = 0; int32_t ret_val; uint16_t phy_data; @@ -2030,6 +2043,25 @@ e1000_check_for_link(struct e1000_hw *hw) * link-up */ e1000_check_downshift(hw); + /* If we are on 82544 or 82543 silicon and speed/duplex + * are forced to 10H or 10F, then we will implement the polarity + * reversal workaround. We disable interrupts first, and upon + * returning, place the devices interrupt state to its previous + * value except for the link status change interrupt which will + * happen due to the execution of this workaround. + */ + + if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) && + (!hw->autoneg) && + (hw->forced_speed_duplex == e1000_10_full || + hw->forced_speed_duplex == e1000_10_half)) { + E1000_WRITE_REG(hw, IMC, 0xffffffff); + ret_val = e1000_polarity_reversal_workaround(hw); + icr = E1000_READ_REG(hw, ICR); + E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC)); + E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK); + } + } else { /* No link detected */ e1000_config_dsp_after_link_change(hw, FALSE); @@ -3057,16 +3089,6 @@ e1000_init_eeprom_params(struct e1000_hw *hw) } break; default: - eeprom->type = e1000_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } break; } @@ -3453,7 +3475,6 @@ e1000_read_eeprom(struct e1000_hw *hw, uint32_t i = 0; DEBUGFUNC("e1000_read_eeprom"); - /* A check for invalid values: offset too large, too many words, and not * enough words. */ @@ -5200,27 +5221,88 @@ e1000_set_vco_speed(struct e1000_hw *hw) return E1000_SUCCESS; } -/****************************************************************************** - * Verifies the hardware needs to allow ARPs to be processed by the host - * - * hw - Struct containing variables accessed by shared code - * - * returns: - TRUE/FALSE - * - *****************************************************************************/ -uint32_t -e1000_enable_mng_pass_thru(struct e1000_hw *hw) +static int32_t +e1000_polarity_reversal_workaround(struct e1000_hw *hw) { - uint32_t manc; + int32_t ret_val; + uint16_t mii_status_reg; + uint16_t i; - if (hw->asf_firmware_present) { - manc = E1000_READ_REG(hw, MANC); + /* Polarity reversal workaround for forced 10F/10H links. */ + + /* Disable the transmitter on the PHY */ + + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); + if(ret_val) + return ret_val; + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); + if(ret_val) + return ret_val; + + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); + if(ret_val) + return ret_val; + + /* This loop will early-out if the NO link condition has been met. */ + for(i = PHY_FORCE_TIME; i > 0; i--) { + /* Read the MII Status Register and wait for Link Status bit + * to be clear. + */ - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - return FALSE; - if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) - return TRUE; + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); + if(ret_val) + return ret_val; + + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); + if(ret_val) + return ret_val; + + if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break; + msec_delay_irq(100); + } + + /* Recommended delay time after link has been lost */ + msec_delay_irq(1000); + + /* Now we will re-enable th transmitter on the PHY */ + + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); + if(ret_val) + return ret_val; + msec_delay_irq(50); + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); + if(ret_val) + return ret_val; + msec_delay_irq(50); + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); + if(ret_val) + return ret_val; + msec_delay_irq(50); + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); + if(ret_val) + return ret_val; + + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); + if(ret_val) + return ret_val; + + /* This loop will early-out if the link condition has been met. */ + for(i = PHY_FORCE_TIME; i > 0; i--) { + /* Read the MII Status Register and wait for Link Status bit + * to be set. + */ + + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); + if(ret_val) + return ret_val; + + ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); + if(ret_val) + return ret_val; + + if(mii_status_reg & MII_SR_LINK_STATUS) break; + msec_delay_irq(100); } - return FALSE; + return E1000_SUCCESS; } + diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index c9ee93a0d..b1054cf14 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -357,11 +357,11 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); #define E1000_DEV_ID_82547GI 0x1075 #define E1000_DEV_ID_82541GI 0x1076 #define E1000_DEV_ID_82541GI_MOBILE 0x1077 +#define E1000_DEV_ID_82541GI_LF 0x107C #define E1000_DEV_ID_82546GB_COPPER 0x1079 #define E1000_DEV_ID_82546GB_FIBER 0x107A #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82547EI 0x1019 - #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -970,7 +970,7 @@ struct e1000_hw_stats { /* Structure containing variables used by the shared code (e1000_hw.c) */ struct e1000_hw { - uint8_t *hw_addr; + uint8_t __iomem *hw_addr; e1000_mac_type mac_type; e1000_phy_type phy_type; uint32_t phy_init_script; @@ -1043,7 +1043,6 @@ struct e1000_hw { #define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ #define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ - /* Register Bit Masks */ /* Device Control */ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4b9b77567..92ecad311 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -27,73 +27,69 @@ *******************************************************************************/ #include "e1000.h" -#include /* Change Log + * 5.3.12 6/7/04 + * - kcompat NETIF_MSG for older kernels (2.4.9) + * - if_mii support and associated kcompat for older kernels + * - More errlogging support from Jon Mason + * - Fix TSO issues on PPC64 machines -- Jon Mason * - * 5.2.51 5/14/04 - * o set default configuration to 'NAPI disabled'. NAPI enabled driver - * causes kernel panic when the interface is shutdown while data is being - * transferred. - * 5.2.47 5/04/04 - * o fixed ethtool -t implementation - * 5.2.45 4/29/04 - * o fixed ethtool -e implementation - * o Support for ethtool ops [Stephen Hemminger (shemminger@osdl.org)] - * 5.2.42 4/26/04 - * o Added support for the DPRINTK macro for enhanced error logging. Some - * parts of the patch were supplied by Jon Mason. - * o Move the register_netdevice() donw in the probe routine due to a - * loading/unloading test issue. - * o Added a long RX byte count the the extra ethtool data members for BER - * testing purposes. - * 5.2.39 3/12/04 + * 5.3.11 6/4/04 + * - ethtool register dump reads MANC register conditionally. + * + * 5.3.10 6/1/04 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.2.52-k4"; +#ifndef CONFIG_E1000_NAPI +#define DRIVERNAPI +#else +#define DRIVERNAPI "-NAPI" +#endif +char e1000_driver_version[] = "5.5.4-k2"DRIVERNAPI; char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * - * Wildcard entries (PCI_ANY_ID) should come last * Last entry must be all 0s * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } + * Macro expands to... + * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} */ static struct pci_device_id e1000_pci_tbl[] = { - {0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + INTEL_E1000_ETHERNET_DEVICE(0x1000), + INTEL_E1000_ETHERNET_DEVICE(0x1001), + INTEL_E1000_ETHERNET_DEVICE(0x1004), + INTEL_E1000_ETHERNET_DEVICE(0x1008), + INTEL_E1000_ETHERNET_DEVICE(0x1009), + INTEL_E1000_ETHERNET_DEVICE(0x100C), + INTEL_E1000_ETHERNET_DEVICE(0x100D), + INTEL_E1000_ETHERNET_DEVICE(0x100E), + INTEL_E1000_ETHERNET_DEVICE(0x100F), + INTEL_E1000_ETHERNET_DEVICE(0x1010), + INTEL_E1000_ETHERNET_DEVICE(0x1011), + INTEL_E1000_ETHERNET_DEVICE(0x1012), + INTEL_E1000_ETHERNET_DEVICE(0x1013), + INTEL_E1000_ETHERNET_DEVICE(0x1015), + INTEL_E1000_ETHERNET_DEVICE(0x1016), + INTEL_E1000_ETHERNET_DEVICE(0x1017), + INTEL_E1000_ETHERNET_DEVICE(0x1018), + INTEL_E1000_ETHERNET_DEVICE(0x1019), + INTEL_E1000_ETHERNET_DEVICE(0x101D), + INTEL_E1000_ETHERNET_DEVICE(0x101E), + INTEL_E1000_ETHERNET_DEVICE(0x1026), + INTEL_E1000_ETHERNET_DEVICE(0x1027), + INTEL_E1000_ETHERNET_DEVICE(0x1028), + INTEL_E1000_ETHERNET_DEVICE(0x1075), + INTEL_E1000_ETHERNET_DEVICE(0x1076), + INTEL_E1000_ETHERNET_DEVICE(0x1077), + INTEL_E1000_ETHERNET_DEVICE(0x1078), + INTEL_E1000_ETHERNET_DEVICE(0x1079), + INTEL_E1000_ETHERNET_DEVICE(0x107A), + INTEL_E1000_ETHERNET_DEVICE(0x107B), + INTEL_E1000_ETHERNET_DEVICE(0x107C), /* required last entry */ {0,} }; @@ -132,8 +128,8 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static int e1000_change_mtu(struct net_device *netdev, int new_mtu); static int e1000_set_mac(struct net_device *netdev, void *p); -static inline void e1000_irq_disable(struct e1000_adapter *adapter); -static inline void e1000_irq_enable(struct e1000_adapter *adapter); +static void e1000_irq_disable(struct e1000_adapter *adapter); +static void e1000_irq_enable(struct e1000_adapter *adapter); static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs); static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); #ifdef CONFIG_E1000_NAPI @@ -150,9 +146,9 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, void set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); -static inline void e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb); +static void e1000_rx_checksum(struct e1000_adapter *adapter, + struct e1000_rx_desc *rx_desc, + struct sk_buff *skb); static void e1000_tx_timeout(struct net_device *dev); static void e1000_tx_timeout_task(struct net_device *dev); static void e1000_smartspeed(struct e1000_adapter *adapter); @@ -172,7 +168,7 @@ static int e1000_resume(struct pci_dev *pdev); #ifdef CONFIG_NET_POLL_CONTROLLER /* for netdump / net console */ -static void e1000_netpoll (struct net_device *dev); +static void e1000_netpoll (struct net_device *netdev); #endif struct notifier_block e1000_notifier_reboot = { @@ -185,7 +181,6 @@ struct notifier_block e1000_notifier_reboot = { extern void e1000_check_options(struct e1000_adapter *adapter); - static struct pci_driver e1000_driver = { .name = e1000_driver_name, .id_table = e1000_pci_tbl, @@ -202,7 +197,7 @@ MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); MODULE_LICENSE("GPL"); -static int debug = 3; +static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); @@ -256,6 +251,14 @@ e1000_up(struct e1000_adapter *adapter) /* hardware has been reset, we need to reload some things */ + /* Reset the PHY if it was previously powered down */ + if(adapter->hw.media_type == e1000_media_type_copper) { + uint16_t mii_reg; + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); + if(mii_reg & MII_CR_POWER_DOWN) + e1000_phy_reset(&adapter->hw); + } + e1000_set_multi(netdev); e1000_restore_vlan(adapter); @@ -294,12 +297,22 @@ e1000_down(struct e1000_adapter *adapter) e1000_reset(adapter); e1000_clean_tx_ring(adapter); e1000_clean_rx_ring(adapter); + + /* If WoL is not enabled + * Power down the PHY so no link is implied when interface is down */ + if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) { + uint16_t mii_reg; + e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg); + } } void e1000_reset(struct e1000_adapter *adapter) { - uint32_t pba, manc; + uint32_t pba; + /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ @@ -323,10 +336,10 @@ e1000_reset(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, PBA, pba); /* flow control settings */ - adapter->hw.fc_high_water = - (pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_HIGH_DIFF; - adapter->hw.fc_low_water = - (pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_LOW_DIFF; + adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) - + E1000_FC_HIGH_DIFF; + adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) - + E1000_FC_LOW_DIFF; adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; @@ -334,19 +347,14 @@ e1000_reset(struct e1000_adapter *adapter) e1000_reset_hw(&adapter->hw); if(adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); - e1000_init_hw(&adapter->hw); + if(e1000_init_hw(&adapter->hw)) + DPRINTK(PROBE, ERR, "Hardware Error\n"); /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); e1000_reset_adaptive(&adapter->hw); e1000_phy_get_info(&adapter->hw, &adapter->phy_info); - - if(adapter->en_mng_pt) { - manc = E1000_READ_REG(&adapter->hw, MANC); - manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); - E1000_WRITE_REG(&adapter->hw, MANC, manc); - } } /** @@ -409,11 +417,6 @@ e1000_probe(struct pci_dev *pdev, adapter->hw.back = adapter; adapter->msg_enable = (1 << debug) - 1; - rtnl_lock(); - /* we need to set the name early since the DPRINTK macro needs it set */ - if (dev_alloc_name(netdev, netdev->name) < 0) - goto err_free_unlock; - mmio_start = pci_resource_start(pdev, BAR_0); mmio_len = pci_resource_len(pdev, BAR_0); @@ -453,6 +456,7 @@ e1000_probe(struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = e1000_netpoll; #endif + strcpy(netdev->name, pci_name(pdev)); netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len; @@ -476,7 +480,6 @@ e1000_probe(struct pci_dev *pdev, } #ifdef NETIF_F_TSO -#ifdef BROKEN_ON_NON_IA_ARCHS /* Disbaled for now until root-cause is found for * hangs reported against non-IA archs. TSO can be * enabled using ethtool -K eth tso on */ @@ -484,13 +487,12 @@ e1000_probe(struct pci_dev *pdev, (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; #endif -#endif - if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); - + /* hard_start_xmit is safe against parallel locking */ + netdev->features |= NETIF_F_LLTX; + /* before reading the EEPROM, reset the controller to * put the device in a known good starting state */ @@ -506,10 +508,12 @@ e1000_probe(struct pci_dev *pdev, /* copy the MAC address out of the EEPROM */ - e1000_read_mac_addr(&adapter->hw); + if (e1000_read_mac_addr(&adapter->hw)) + DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); if(!is_valid_ether_addr(netdev->dev_addr)) { + DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; } @@ -538,7 +542,6 @@ e1000_probe(struct pci_dev *pdev, netif_carrier_off(netdev); netif_stop_queue(netdev); - DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); e1000_check_options(adapter); /* Initial Wake on LAN setting @@ -569,15 +572,15 @@ e1000_probe(struct pci_dev *pdev, adapter->wol |= E1000_WUFC_MAG; /* reset the hardware with the new settings */ - e1000_reset(adapter); - /* since we are holding the rtnl lock already, call the no-lock version */ - if((err = register_netdevice(netdev))) + strcpy(netdev->name, "eth%d"); + if((err = register_netdev(netdev))) goto err_register; + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); + cards_found++; - rtnl_unlock(); return 0; err_register: @@ -585,8 +588,6 @@ err_sw_init: err_eeprom: iounmap(adapter->hw.hw_addr); err_ioremap: -err_free_unlock: - rtnl_unlock(); free_netdev(netdev); err_alloc_etherdev: pci_release_regions(pdev); @@ -627,6 +628,8 @@ e1000_remove(struct pci_dev *pdev) pci_release_regions(pdev); free_netdev(netdev); + + pci_disable_device(pdev); } /** @@ -663,7 +666,7 @@ e1000_sw_init(struct e1000_adapter *adapter) /* identify the MAC */ - if (e1000_set_mac_type(hw)) { + if(e1000_set_mac_type(hw)) { DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); return -EIO; } @@ -672,19 +675,19 @@ e1000_sw_init(struct e1000_adapter *adapter) e1000_init_eeprom_params(hw); - if((hw->mac_type == e1000_82541) || - (hw->mac_type == e1000_82547) || - (hw->mac_type == e1000_82541_rev_2) || - (hw->mac_type == e1000_82547_rev_2)) + switch(hw->mac_type) { + default: + break; + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: hw->phy_init_script = 1; + break; + } e1000_set_media_type(hw); - if(hw->mac_type < e1000_82543) - hw->report_tx_early = 0; - else - hw->report_tx_early = 1; - hw->wait_autoneg_complete = FALSE; hw->tbi_compatibility_en = TRUE; hw->adaptive_ifs = TRUE; @@ -736,7 +739,7 @@ e1000_open(struct net_device *netdev) if((err = e1000_up(adapter))) goto err_up; - return 0; + return E1000_SUCCESS; err_up: e1000_free_rx_resources(adapter); @@ -788,8 +791,10 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter) int size; size = sizeof(struct e1000_buffer) * txdr->count; - txdr->buffer_info = kmalloc(size, GFP_KERNEL); + txdr->buffer_info = vmalloc(size); if(!txdr->buffer_info) { + DPRINTK(PROBE, ERR, + "Unble to Allocate Memory for the Transmit descriptor ring\n"); return -ENOMEM; } memset(txdr->buffer_info, 0, size); @@ -801,7 +806,9 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter) txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if(!txdr->desc) { - kfree(txdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unble to Allocate Memory for the Transmit descriptor ring\n"); + vfree(txdr->buffer_info); return -ENOMEM; } memset(txdr->desc, 0, txdr->size); @@ -878,10 +885,10 @@ e1000_configure_tx(struct e1000_adapter *adapter) adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - if(adapter->hw.report_tx_early == 1) - adapter->txd_cmd |= E1000_TXD_CMD_RS; - else + if(adapter->hw.mac_type < e1000_82543) adapter->txd_cmd |= E1000_TXD_CMD_RPS; + else + adapter->txd_cmd |= E1000_TXD_CMD_RS; /* Cache if we're 82544 running in PCI-X because we'll * need this to apply a workaround later in the send path. */ @@ -905,8 +912,10 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) int size; size = sizeof(struct e1000_buffer) * rxdr->count; - rxdr->buffer_info = kmalloc(size, GFP_KERNEL); + rxdr->buffer_info = vmalloc(size); if(!rxdr->buffer_info) { + DPRINTK(PROBE, ERR, + "Unble to Allocate Memory for the Recieve descriptor ring\n"); return -ENOMEM; } memset(rxdr->buffer_info, 0, size); @@ -919,7 +928,9 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter) rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); if(!rxdr->desc) { - kfree(rxdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unble to Allocate Memory for the Recieve descriptor ring\n"); + vfree(rxdr->buffer_info); return -ENOMEM; } memset(rxdr->desc, 0, rxdr->size); @@ -953,7 +964,9 @@ e1000_setup_rctl(struct e1000_adapter *adapter) else rctl &= ~E1000_RCTL_SBP; + /* Setup buffer sizes */ rctl &= ~(E1000_RCTL_SZ_4096); + rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE); switch (adapter->rx_buffer_len) { case E1000_RXBUFFER_2048: default: @@ -961,13 +974,13 @@ e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); break; case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + rctl |= E1000_RCTL_SZ_4096; break; case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + rctl |= E1000_RCTL_SZ_8192; break; case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; + rctl |= E1000_RCTL_SZ_16384; break; } @@ -989,13 +1002,11 @@ e1000_configure_rx(struct e1000_adapter *adapter) uint32_t rctl; uint32_t rxcsum; - /* make sure receives are disabled while setting up the descriptors */ - + /* disable receives while setting up the descriptors */ rctl = E1000_READ_REG(&adapter->hw, RCTL); E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); /* set the Receive Delay Timer Register */ - E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay); if(adapter->hw.mac_type >= e1000_82540) { @@ -1006,7 +1017,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) } /* Setup the Base and Length of the Rx Descriptor Ring */ - E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL)); E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32)); @@ -1025,7 +1035,6 @@ e1000_configure_rx(struct e1000_adapter *adapter) } /* Enable Receives */ - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } @@ -1043,7 +1052,7 @@ e1000_free_tx_resources(struct e1000_adapter *adapter) e1000_clean_tx_ring(adapter); - kfree(adapter->tx_ring.buffer_info); + vfree(adapter->tx_ring.buffer_info); adapter->tx_ring.buffer_info = NULL; pci_free_consistent(pdev, adapter->tx_ring.size, @@ -1073,9 +1082,9 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter) if(buffer_info->skb) { pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); dev_kfree_skb(buffer_info->skb); @@ -1112,7 +1121,7 @@ e1000_free_rx_resources(struct e1000_adapter *adapter) e1000_clean_rx_ring(adapter); - kfree(rx_ring->buffer_info); + vfree(rx_ring->buffer_info); rx_ring->buffer_info = NULL; pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); @@ -1141,12 +1150,11 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter) if(buffer_info->skb) { pci_unmap_single(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_FROMDEVICE); + buffer_info->dma, + buffer_info->length, + PCI_DMA_FROMDEVICE); dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; } } @@ -1259,9 +1267,12 @@ e1000_set_multi(struct net_device *netdev) uint32_t rctl; uint32_t hash_value; int i; + unsigned long flags; /* Check for Promiscuous and All Multicast modes */ + spin_lock_irqsave(&adapter->tx_lock, flags); + rctl = E1000_READ_REG(hw, RCTL); if(netdev->flags & IFF_PROMISC) { @@ -1310,9 +1321,12 @@ e1000_set_multi(struct net_device *netdev) if(hw->mac_type == e1000_82542_rev2_0) e1000_leave_82542_rst(adapter); + + spin_unlock_irqrestore(&adapter->tx_lock, flags); } -/* need to wait a few seconds after link up to get diagnostic information from the phy */ +/* Need to wait a few seconds after link up to get diagnostic information from + * the phy */ static void e1000_update_phy_info(unsigned long data) @@ -1420,7 +1434,7 @@ e1000_watchdog(unsigned long data) adapter->tpt_old = adapter->stats.tpt; adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old; adapter->colc_old = adapter->stats.colc; - + adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; adapter->gorcl_old = adapter->stats.gorcl; adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; @@ -1477,8 +1491,9 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) #ifdef NETIF_F_TSO struct e1000_context_desc *context_desc; unsigned int i; - uint8_t ipcss, ipcso, tucss, tucso, hdr_len; + uint32_t cmd_length = 0; uint16_t ipcse, tucse, mss; + uint8_t ipcss, ipcso, tucss, tucso, hdr_len; if(skb_shinfo(skb)->tso_size) { hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); @@ -1497,6 +1512,10 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) tucso = (void *)&(skb->h.th->check) - (void *)skb->data; tucse = 0; + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | + E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | + (skb->len - (hdr_len))); + i = adapter->tx_ring.next_to_use; context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); @@ -1508,10 +1527,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb) context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32( - E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | - (skb->len - (hdr_len))); + context_desc->cmd_and_length = cpu_to_le32(cmd_length); if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; @@ -1528,22 +1544,21 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) { struct e1000_context_desc *context_desc; unsigned int i; - uint8_t css, cso; + uint8_t css; - if(skb->ip_summed == CHECKSUM_HW) { + if(likely(skb->ip_summed == CHECKSUM_HW)) { css = skb->h.raw - skb->data; - cso = (skb->h.raw + skb->csum) - skb->data; i = adapter->tx_ring.next_to_use; context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = cso; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); - if(++i == adapter->tx_ring.count) i = 0; + if(unlikely(++i == adapter->tx_ring.count)) i = 0; adapter->tx_ring.next_to_use = i; return TRUE; @@ -1567,7 +1582,6 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, unsigned int f; len -= skb->data_len; - i = tx_ring->next_to_use; while(len) { @@ -1576,14 +1590,14 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(mss && !nr_frags && size == len && size > 8) + if(unlikely(mss && !nr_frags && size == len && size > 8)) size -= 4; #endif /* Workaround for potential 82544 hang in PCI-X. Avoid * terminating buffers within evenly-aligned dwords. */ - if(adapter->pcix_82544 && + if(unlikely(adapter->pcix_82544 && !((unsigned long)(skb->data + offset + size - 1) & 4) && - size > 4) + size > 4)) size -= 4; buffer_info->length = size; @@ -1597,7 +1611,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, len -= size; offset += size; count++; - if(++i == tx_ring->count) i = 0; + if(unlikely(++i == tx_ring->count)) i = 0; } for(f = 0; f < nr_frags; f++) { @@ -1613,15 +1627,15 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(mss && f == (nr_frags-1) && size == len && size > 8) + if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) size -= 4; #endif /* Workaround for potential 82544 hang in PCI-X. * Avoid terminating buffers within evenly-aligned * dwords. */ - if(adapter->pcix_82544 && + if(unlikely(adapter->pcix_82544 && !((unsigned long)(frag->page+offset+size-1) & 4) && - size > 4) + size > 4)) size -= 4; buffer_info->length = size; @@ -1636,13 +1650,14 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb, len -= size; offset += size; count++; - if(++i == tx_ring->count) i = 0; + if(unlikely(++i == tx_ring->count)) i = 0; } } + i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - + return count; } @@ -1655,18 +1670,18 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; unsigned int i; - if(tx_flags & E1000_TX_FLAGS_TSO) { + if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | E1000_TXD_CMD_TSE; txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8; } - if(tx_flags & E1000_TX_FLAGS_CSUM) { + if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; txd_upper |= E1000_TXD_POPTS_TXSM << 8; } - if(tx_flags & E1000_TX_FLAGS_VLAN) { + if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { txd_lower |= E1000_TXD_CMD_VLE; txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); } @@ -1680,7 +1695,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) tx_desc->lower.data = cpu_to_le32(txd_lower | buffer_info->length); tx_desc->upper.data = cpu_to_le32(txd_upper); - if(++i == tx_ring->count) i = 0; + if(unlikely(++i == tx_ring->count)) i = 0; } tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); @@ -1733,7 +1748,7 @@ no_fifo_stall_required: return 0; } -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { @@ -1741,22 +1756,23 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; - unsigned long flags; unsigned int len = skb->len; - int count = 0; - unsigned int mss = 0; + unsigned long flags; unsigned int nr_frags = 0; + unsigned int mss = 0; + int count = 0; unsigned int f; nr_frags = skb_shinfo(skb)->nr_frags; len -= skb->data_len; - if(skb->len <= 0) { + + if(unlikely(skb->len <= 0)) { dev_kfree_skb_any(skb); - return 0; + return NETDEV_TX_OK; } #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->tso_size; - /* The controller does a simple calculation to + /* The controller does a simple calculation to * make sure there is enough room in the FIFO before * initiating the DMA for each buffer. The calc is: * 4 = ceil(buffer len/mss). To make sure we don't @@ -1766,62 +1782,70 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) max_per_txd = min(mss << 2, max_per_txd); max_txd_pwr = fls(max_per_txd) - 1; } + if((mss) || (skb->ip_summed == CHECKSUM_HW)) count++; - count++; /*for sentinel desc*/ + count++; /* for sentinel desc */ #else if(skb->ip_summed == CHECKSUM_HW) count++; #endif - count += TXD_USE_COUNT(len, max_txd_pwr); + if(adapter->pcix_82544) count++; nr_frags = skb_shinfo(skb)->nr_frags; for(f = 0; f < nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, - max_txd_pwr); + max_txd_pwr); if(adapter->pcix_82544) count += nr_frags; - - spin_lock_irqsave(&adapter->tx_lock, flags); - /* need: count + 2 desc gap to keep tail from touching + + local_irq_save(flags); + if (!spin_trylock(&adapter->tx_lock)) { + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } + + /* need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ - if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2 ) { + if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) { netif_stop_queue(netdev); spin_unlock_irqrestore(&adapter->tx_lock, flags); - return 1; + return NETDEV_TX_BUSY; } - spin_unlock_irqrestore(&adapter->tx_lock, flags); - if(adapter->hw.mac_type == e1000_82547) { - if(e1000_82547_fifo_workaround(adapter, skb)) { + if(unlikely(adapter->hw.mac_type == e1000_82547)) { + if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) { netif_stop_queue(netdev); mod_timer(&adapter->tx_fifo_stall_timer, jiffies); - return 1; + spin_unlock_irqrestore(&adapter->tx_lock, flags); + return NETDEV_TX_BUSY; } } - if(adapter->vlgrp && vlan_tx_tag_present(skb)) { + if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); } first = adapter->tx_ring.next_to_use; - if(e1000_tso(adapter, skb)) + if(likely(e1000_tso(adapter, skb))) tx_flags |= E1000_TX_FLAGS_TSO; - else if(e1000_tx_csum(adapter, skb)) + else if(likely(e1000_tx_csum(adapter, skb))) tx_flags |= E1000_TX_FLAGS_CSUM; - e1000_tx_queue(adapter, - e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), + e1000_tx_queue(adapter, + e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), tx_flags); netdev->trans_start = jiffies; - return 0; + spin_unlock_irqrestore(&adapter->tx_lock, flags); + return NETDEV_TX_OK; } /** @@ -1843,10 +1867,8 @@ e1000_tx_timeout_task(struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; - netif_device_detach(netdev); e1000_down(adapter); e1000_up(adapter); - netif_device_attach(netdev); } /** @@ -1905,7 +1927,6 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) } if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) { - e1000_down(adapter); e1000_up(adapter); } @@ -1951,8 +1972,6 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); - /* the rest of the counters are only modified here */ - adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); adapter->stats.mpc += E1000_READ_REG(hw, MPC); adapter->stats.scc += E1000_READ_REG(hw, SCC); @@ -2059,7 +2078,7 @@ e1000_update_stats(struct e1000_adapter *adapter) * @adapter: board private structure **/ -static inline void +static void e1000_irq_disable(struct e1000_adapter *adapter) { atomic_inc(&adapter->irq_sem); @@ -2073,10 +2092,10 @@ e1000_irq_disable(struct e1000_adapter *adapter) * @adapter: board private structure **/ -static inline void +static void e1000_irq_enable(struct e1000_adapter *adapter) { - if(atomic_dec_and_test(&adapter->irq_sem)) { + if(likely(atomic_dec_and_test(&adapter->irq_sem))) { E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); E1000_WRITE_FLUSH(&adapter->hw); } @@ -2095,21 +2114,21 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; - uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); + uint32_t icr = E1000_READ_REG(hw, ICR); #ifndef CONFIG_E1000_NAPI unsigned int i; #endif - if(!icr) + if(unlikely(!icr)) return IRQ_NONE; /* Not our interrupt */ - if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; mod_timer(&adapter->watchdog_timer, jiffies); } #ifdef CONFIG_E1000_NAPI - if(netif_rx_schedule_prep(netdev)) { + if(likely(netif_rx_schedule_prep(netdev))) { /* Disable interrupts and register for poll. The flush of the posted write is intentionally left out. @@ -2121,8 +2140,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) } #else for(i = 0; i < E1000_MAX_INTR; i++) - if(!e1000_clean_rx_irq(adapter) & - !e1000_clean_tx_irq(adapter)) + if(unlikely(!e1000_clean_rx_irq(adapter) & + !e1000_clean_tx_irq(adapter))) break; #endif @@ -2140,15 +2159,18 @@ e1000_clean(struct net_device *netdev, int *budget) { struct e1000_adapter *adapter = netdev->priv; int work_to_do = min(*budget, netdev->quota); + int tx_cleaned; int work_done = 0; - e1000_clean_tx_irq(adapter); + tx_cleaned = e1000_clean_tx_irq(adapter); e1000_clean_rx_irq(adapter, &work_done, work_to_do); *budget -= work_done; netdev->quota -= work_done; - if(work_done < work_to_do || !netif_running(netdev)) { + /* if no Rx and Tx cleanup work was done, exit the polling mode */ + if(!tx_cleaned || (work_done < work_to_do) || + !netif_running(netdev)) { netif_rx_complete(netdev); e1000_irq_enable(adapter); return 0; @@ -2156,8 +2178,8 @@ e1000_clean(struct net_device *netdev, int *budget) return (work_done >= work_to_do); } -#endif +#endif /** * e1000_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure @@ -2174,31 +2196,25 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) unsigned int i, eop; boolean_t cleaned = FALSE; - i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - for(cleaned = FALSE; !cleaned; ) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; - if(buffer_info->dma) { - + if(likely(buffer_info->dma)) { pci_unmap_page(pdev, buffer_info->dma, buffer_info->length, PCI_DMA_TODEVICE); - buffer_info->dma = 0; } if(buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; } @@ -2207,7 +2223,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_desc->upper.data = 0; cleaned = (i == eop); - if(++i == tx_ring->count) i = 0; + if(unlikely(++i == tx_ring->count)) i = 0; } eop = tx_ring->buffer_info[i].next_to_watch; @@ -2218,7 +2234,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) spin_lock(&adapter->tx_lock); - if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) + if(unlikely(cleaned && netif_queue_stopped(netdev) && + netif_carrier_ok(netdev))) netif_wake_queue(netdev); spin_unlock(&adapter->tx_lock); @@ -2227,7 +2244,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) } /** - * e1000_clean_rx_irq - Send received data up the network stack, + * e1000_clean_rx_irq - Send received data up the network stack * @adapter: board private structure **/ @@ -2256,14 +2273,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) while(rx_desc->status & E1000_RXD_STAT_DD) { buffer_info = &rx_ring->buffer_info[i]; - #ifdef CONFIG_E1000_NAPI if(*work_done >= work_to_do) break; - (*work_done)++; #endif - cleaned = TRUE; pci_unmap_single(pdev, @@ -2274,49 +2288,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) skb = buffer_info->skb; length = le16_to_cpu(rx_desc->length); - if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { - + if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { /* All receives must fit into a single buffer */ - - E1000_DBG("%s: Receive packet consumed multiple buffers\n", - netdev->name); - + E1000_DBG("%s: Receive packet consumed multiple" + " buffers\n", netdev->name); dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; + goto next_desc; } - if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { - + if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { last_byte = *(skb->data + length - 1); - if(TBI_ACCEPT(&adapter->hw, rx_desc->status, rx_desc->errors, length, last_byte)) { - spin_lock_irqsave(&adapter->stats_lock, flags); - e1000_tbi_adjust_stats(&adapter->hw, &adapter->stats, length, skb->data); - spin_unlock_irqrestore(&adapter->stats_lock, flags); length--; } else { - dev_kfree_skb_irq(skb); - rx_desc->status = 0; - buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; + goto next_desc; } } @@ -2328,28 +2321,30 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) skb->protocol = eth_type_trans(skb, netdev); #ifdef CONFIG_E1000_NAPI - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { + if(unlikely(adapter->vlgrp && + (rx_desc->status & E1000_RXD_STAT_VP))) { vlan_hwaccel_receive_skb(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); + le16_to_cpu(rx_desc->special) & + E1000_RXD_SPC_VLAN_MASK); } else { netif_receive_skb(skb); } #else /* CONFIG_E1000_NAPI */ - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { + if(unlikely(adapter->vlgrp && + (rx_desc->status & E1000_RXD_STAT_VP))) { vlan_hwaccel_rx(skb, adapter->vlgrp, - le16_to_cpu(rx_desc->special & - E1000_RXD_SPC_VLAN_MASK)); + le16_to_cpu(rx_desc->special) & + E1000_RXD_SPC_VLAN_MASK); } else { netif_rx(skb); } #endif /* CONFIG_E1000_NAPI */ netdev->last_rx = jiffies; +next_desc: rx_desc->status = 0; buffer_info->skb = NULL; - - if(++i == rx_ring->count) i = 0; + if(unlikely(++i == rx_ring->count)) i = 0; rx_desc = E1000_RX_DESC(*rx_ring, i); } @@ -2381,11 +2376,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) buffer_info = &rx_ring->buffer_info[i]; while(!buffer_info->skb) { - rx_desc = E1000_RX_DESC(*rx_ring, i); skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); - - if(!skb) { + if(unlikely(!skb)) { /* Better luck next round */ break; } @@ -2400,15 +2393,15 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) buffer_info->skb = skb; buffer_info->length = adapter->rx_buffer_len; - buffer_info->dma = - pci_map_single(pdev, - skb->data, - adapter->rx_buffer_len, - PCI_DMA_FROMDEVICE); + buffer_info->dma = pci_map_single(pdev, + skb->data, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) { + if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) { /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, @@ -2418,7 +2411,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, RDT, i); } - if(++i == rx_ring->count) i = 0; + if(unlikely(++i == rx_ring->count)) i = 0; buffer_info = &rx_ring->buffer_info[i]; } @@ -2537,22 +2530,24 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return -EFAULT; mii_reg = data->val_in; if (e1000_write_phy_reg(&adapter->hw, data->reg_num, - data->val_in)) + mii_reg)) return -EIO; if (adapter->hw.phy_type == e1000_phy_m88) { switch (data->reg_num) { case PHY_CTRL: - if(data->val_in & MII_CR_AUTO_NEG_EN) { + if(mii_reg & MII_CR_POWER_DOWN) + break; + if(mii_reg & MII_CR_AUTO_NEG_EN) { adapter->hw.autoneg = 1; adapter->hw.autoneg_advertised = 0x2F; } else { - if (data->val_in & 0x40) + if (mii_reg & 0x40) spddplx = SPEED_1000; - else if (data->val_in & 0x2000) + else if (mii_reg & 0x2000) spddplx = SPEED_100; else spddplx = SPEED_10; - spddplx += (data->val_in & 0x100) + spddplx += (mii_reg & 0x100) ? FULL_DUPLEX : HALF_DUPLEX; retval = e1000_set_spd_dplx(adapter, @@ -2572,6 +2567,18 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return -EIO; break; } + } else { + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) + break; + if(netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + break; + } } break; default: @@ -2587,17 +2594,17 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) * @sk_buff: socket buffer with received data **/ -static inline void +static void e1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb) { /* 82543 or newer only */ - if((adapter->hw.mac_type < e1000_82543) || + if(unlikely((adapter->hw.mac_type < e1000_82543) || /* Ignore Checksum bit is set */ (rx_desc->status & E1000_RXD_STAT_IXSM) || /* TCP Checksum has not been calculated */ - (!(rx_desc->status & E1000_RXD_STAT_TCPCS))) { + (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) { skb->ip_summed = CHECKSUM_NONE; return; } @@ -2609,7 +2616,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter, skb->ip_summed = CHECKSUM_NONE; adapter->hw_csum_err++; } else { - /* TCP checksum is good */ + /* TCP checksum is good */ skb->ip_summed = CHECKSUM_UNNECESSARY; adapter->hw_csum_good++; } @@ -2620,7 +2627,8 @@ e1000_pci_set_mwi(struct e1000_hw *hw) { struct e1000_adapter *adapter = hw->back; - pci_set_mwi(adapter->pdev); + int ret; + ret = pci_set_mwi(adapter->pdev); } void @@ -2670,26 +2678,22 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) if(grp) { /* enable VLAN tag insert/strip */ - ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl |= E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); /* enable VLAN receive filtering */ - rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl |= E1000_RCTL_VFE; rctl &= ~E1000_RCTL_CFIEN; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); } else { /* disable VLAN tag insert/strip */ - ctrl = E1000_READ_REG(&adapter->hw, CTRL); ctrl &= ~E1000_CTRL_VME; E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); /* disable VLAN filtering */ - rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl &= ~E1000_RCTL_VFE; E1000_WRITE_REG(&adapter->hw, RCTL, rctl); @@ -2705,7 +2709,6 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) uint32_t vfta, index; /* add VID to filter table */ - index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta |= (1 << (vid & 0x1F)); @@ -2725,8 +2728,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) e1000_irq_enable(adapter); - /* remove VID from filter table*/ - + /* remove VID from filter table */ index = (vid >> 5) & 0x7F; vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); vfta &= ~(1 << (vid & 0x1F)); @@ -2772,6 +2774,8 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: + DPRINTK(PROBE, ERR, + "Unsupported Speed/Duplexity configuration\n"); return -EINVAL; } return 0; @@ -2852,7 +2856,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ } - pci_save_state(pdev, adapter->pci_state); + pci_save_state(pdev); if(adapter->hw.mac_type >= e1000_82540 && adapter->hw.media_type == e1000_media_type_copper) { @@ -2865,6 +2869,8 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) } } + pci_disable_device(pdev); + state = (state > 0) ? 3 : 0; pci_set_power_state(pdev, state); @@ -2877,10 +2883,13 @@ e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev->priv; - uint32_t manc; + uint32_t manc, ret; pci_set_power_state(pdev, 0); - pci_restore_state(pdev, adapter->pci_state); + pci_restore_state(pdev); + ret = pci_enable_device(pdev); + if (pdev->is_busmaster) + pci_set_master(pdev); pci_enable_wake(pdev, 3, 0); pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ @@ -2910,12 +2919,12 @@ e1000_resume(struct pci_dev *pdev) * without having to re-enable interrupts. It's not called while * the interrupt routine is executing. */ - -static void e1000_netpoll (struct net_device *dev) +static void +e1000_netpoll (struct net_device *netdev) { - struct e1000_adapter *adapter = dev->priv; + struct e1000_adapter *adapter = netdev->priv; disable_irq(adapter->pdev->irq); - e1000_intr (adapter->pdev->irq, dev, NULL); + e1000_intr(adapter->pdev->irq, netdev, NULL); enable_irq(adapter->pdev->irq); } #endif diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 9e2086896..630beaf27 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -49,6 +49,12 @@ set_current_state(TASK_UNINTERRUPTIBLE); \ schedule_timeout((x * HZ)/1000 + 2); \ } } while(0) +/* Some workarounds require millisecond delays and are run during interrupt + * context. Most notably, when establishing link, the phy may need tweaking + * but cannot process phy register reads/writes faster than millisecond + * intervals...and we establish link due to a "link status change" interrupt. + */ +#define msec_delay_irq(x) mdelay(x) #endif #define PCI_COMMAND_REGISTER PCI_COMMAND diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 3e79a45de..038d55958 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -34,31 +34,21 @@ #define E1000_MAX_NIC 32 -#define OPTION_UNSET -1 +#define OPTION_UNSET -1 #define OPTION_DISABLED 0 #define OPTION_ENABLED 1 -/* Module Parameters are always initialized to -1, so that the driver - * can tell the difference between no user specified value or the - * user asking for the default value. - * The true default values are loaded in when e1000_check_options is called. - * - * This is a GCC extension to ANSI C. - * See the item "Labeled Elements in Initializers" in the section - * "Extensions to the C Language Family" of the GCC documentation. - */ - -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } - /* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */ -#define E1000_PARAM(X, S) \ -static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \ -MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \ -MODULE_PARM_DESC(X, S); +#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } +#define E1000_PARAM(X, desc) \ + static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ + static int num_##X = 0; \ + module_param_array(X, int, &num_##X, 0); \ + MODULE_PARM_DESC(X, desc); /* Transmit Descriptor Count * @@ -212,7 +202,7 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 -#define DEFAULT_ITR 1 +#define DEFAULT_ITR 8000 #define MAX_ITR 100000 #define MIN_ITR 100 @@ -235,7 +225,7 @@ struct e1000_option { static int __devinit e1000_validate_option(int *value, struct e1000_option *opt, - struct e1000_adapter *adapter) + struct e1000_adapter *adapter) { if(*value == OPTION_UNSET) { *value = opt->def; @@ -256,7 +246,7 @@ e1000_validate_option(int *value, struct e1000_option *opt, case range_option: if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { DPRINTK(PROBE, INFO, - "%s set to %i\n", opt->name, *value); + "%s set to %i\n", opt->name, *value); return 0; } break; @@ -305,7 +295,6 @@ e1000_check_options(struct e1000_adapter *adapter) DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%i\n", bd); DPRINTK(PROBE, NOTICE, "Using defaults for all values\n"); - bd = E1000_MAX_NIC; } { /* Transmit Descriptor Count */ @@ -322,9 +311,14 @@ e1000_check_options(struct e1000_adapter *adapter) opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD; - tx_ring->count = TxDescriptors[bd]; - e1000_validate_option(&tx_ring->count, &opt, adapter); - E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); + if (num_TxDescriptors > bd) { + tx_ring->count = TxDescriptors[bd]; + e1000_validate_option(&tx_ring->count, &opt, adapter); + E1000_ROUNDUP(tx_ring->count, + REQ_TX_DESCRIPTOR_MULTIPLE); + } else { + tx_ring->count = opt.def; + } } { /* Receive Descriptor Count */ struct e1000_option opt = { @@ -340,9 +334,14 @@ e1000_check_options(struct e1000_adapter *adapter) opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD; - rx_ring->count = RxDescriptors[bd]; - e1000_validate_option(&rx_ring->count, &opt, adapter); - E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); + if (num_RxDescriptors > bd) { + rx_ring->count = RxDescriptors[bd]; + e1000_validate_option(&rx_ring->count, &opt, adapter); + E1000_ROUNDUP(rx_ring->count, + REQ_RX_DESCRIPTOR_MULTIPLE); + } else { + rx_ring->count = opt.def; + } } { /* Checksum Offload Enable/Disable */ struct e1000_option opt = { @@ -352,9 +351,13 @@ e1000_check_options(struct e1000_adapter *adapter) .def = OPTION_ENABLED }; - int rx_csum = XsumRX[bd]; - e1000_validate_option(&rx_csum, &opt, adapter); - adapter->rx_csum = rx_csum; + if (num_XsumRX > bd) { + int rx_csum = XsumRX[bd]; + e1000_validate_option(&rx_csum, &opt, adapter); + adapter->rx_csum = rx_csum; + } else { + adapter->rx_csum = opt.def; + } } { /* Flow Control */ @@ -374,9 +377,13 @@ e1000_check_options(struct e1000_adapter *adapter) .p = fc_list }} }; - int fc = FlowControl[bd]; - e1000_validate_option(&fc, &opt, adapter); - adapter->hw.fc = adapter->hw.original_fc = fc; + if (num_FlowControl > bd) { + int fc = FlowControl[bd]; + e1000_validate_option(&fc, &opt, adapter); + adapter->hw.fc = adapter->hw.original_fc = fc; + } else { + adapter->hw.fc = opt.def; + } } { /* Transmit Interrupt Delay */ struct e1000_option opt = { @@ -388,8 +395,13 @@ e1000_check_options(struct e1000_adapter *adapter) .max = MAX_TXDELAY }} }; - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, adapter); + if (num_TxIntDelay > bd) { + adapter->tx_int_delay = TxIntDelay[bd]; + e1000_validate_option(&adapter->tx_int_delay, &opt, + adapter); + } else { + adapter->tx_int_delay = opt.def; + } } { /* Transmit Absolute Interrupt Delay */ struct e1000_option opt = { @@ -401,8 +413,13 @@ e1000_check_options(struct e1000_adapter *adapter) .max = MAX_TXABSDELAY }} }; - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, adapter); + if (num_TxAbsIntDelay > bd) { + adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; + e1000_validate_option(&adapter->tx_abs_int_delay, &opt, + adapter); + } else { + adapter->tx_abs_int_delay = opt.def; + } } { /* Receive Interrupt Delay */ struct e1000_option opt = { @@ -414,8 +431,13 @@ e1000_check_options(struct e1000_adapter *adapter) .max = MAX_RXDELAY }} }; - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, adapter); + if (num_RxIntDelay > bd) { + adapter->rx_int_delay = RxIntDelay[bd]; + e1000_validate_option(&adapter->rx_int_delay, &opt, + adapter); + } else { + adapter->rx_int_delay = opt.def; + } } { /* Receive Absolute Interrupt Delay */ struct e1000_option opt = { @@ -427,8 +449,13 @@ e1000_check_options(struct e1000_adapter *adapter) .max = MAX_RXABSDELAY }} }; - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, adapter); + if (num_RxAbsIntDelay > bd) { + adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; + e1000_validate_option(&adapter->rx_abs_int_delay, &opt, + adapter); + } else { + adapter->rx_abs_int_delay = opt.def; + } } { /* Interrupt Throttling Rate */ struct e1000_option opt = { @@ -440,21 +467,27 @@ e1000_check_options(struct e1000_adapter *adapter) .max = MAX_ITR }} }; - adapter->itr = InterruptThrottleRate[bd]; - switch(adapter->itr) { - case -1: + if (num_InterruptThrottleRate > bd) { + adapter->itr = InterruptThrottleRate[bd]; + switch(adapter->itr) { + case -1: + adapter->itr = 1; + break; + case 0: + DPRINTK(PROBE, INFO, "%s turned off\n", + opt.name); + break; + case 1: + DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", + opt.name); + break; + default: + e1000_validate_option(&adapter->itr, &opt, + adapter); + break; + } + } else { adapter->itr = 1; - break; - case 0: - DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); - break; - case 1: - DPRINTK(PROBE, INFO, - "%s set to dynamic mode\n", opt.name); - break; - default: - e1000_validate_option(&adapter->itr, &opt, adapter); - break; } } @@ -482,19 +515,20 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) { int bd = adapter->bd_number; - bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd; - - if((Speed[bd] != OPTION_UNSET)) { + if(num_Speed > bd) { DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, " "parameter ignored\n"); } - if((Duplex[bd] != OPTION_UNSET)) { + + if(num_Duplex > bd) { DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, " "parameter ignored\n"); } - if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) { - DPRINTK(PROBE, INFO, "AutoNeg other than Full/1000 is " - "not valid for fiber adapters, parameter ignored\n"); + + if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) { + DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is " + "not valid for fiber adapters, " + "parameter ignored\n"); } } @@ -510,7 +544,6 @@ e1000_check_copper_options(struct e1000_adapter *adapter) { int speed, dplx; int bd = adapter->bd_number; - bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd; { /* Speed */ struct e1000_opt_list speed_list[] = {{ 0, "" }, @@ -527,8 +560,12 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .p = speed_list }} }; - speed = Speed[bd]; - e1000_validate_option(&speed, &opt, adapter); + if (num_Speed > bd) { + speed = Speed[bd]; + e1000_validate_option(&speed, &opt, adapter); + } else { + speed = opt.def; + } } { /* Duplex */ struct e1000_opt_list dplx_list[] = {{ 0, "" }, @@ -544,11 +581,15 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .p = dplx_list }} }; - dplx = Duplex[bd]; - e1000_validate_option(&dplx, &opt, adapter); + if (num_Duplex > bd) { + dplx = Duplex[bd]; + e1000_validate_option(&dplx, &opt, adapter); + } else { + dplx = opt.def; + } } - if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) { + if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) { DPRINTK(PROBE, INFO, "AutoNeg specified along with Speed or Duplex, " "parameter ignored\n"); @@ -605,30 +646,30 @@ e1000_check_copper_options(struct e1000_adapter *adapter) switch (speed + dplx) { case 0: adapter->hw.autoneg = adapter->fc_autoneg = 1; - if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET) + if((num_Speed > bd) && (speed != 0 || dplx != 0)) DPRINTK(PROBE, INFO, "Speed and duplex autonegotiation enabled\n"); break; case HALF_DUPLEX: DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at Half Duplex only\n"); + DPRINTK(PROBE, INFO, "Using Autonegotiation at " + "Half Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_100_HALF; break; case FULL_DUPLEX: DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at Full Duplex only\n"); + DPRINTK(PROBE, INFO, "Using Autonegotiation at " + "Full Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL; break; case SPEED_10: - DPRINTK(PROBE, INFO, - "10 Mbps Speed specified without Duplex\n"); + DPRINTK(PROBE, INFO, "10 Mbps Speed specified " + "without Duplex\n"); DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | @@ -647,10 +688,10 @@ e1000_check_copper_options(struct e1000_adapter *adapter) adapter->hw.autoneg_advertised = 0; break; case SPEED_100: - DPRINTK(PROBE, INFO, - "100 Mbps Speed specified without Duplex\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at 100 Mbps only\n"); + DPRINTK(PROBE, INFO, "100 Mbps Speed specified " + "without Duplex\n"); + DPRINTK(PROBE, INFO, "Using Autonegotiation at " + "100 Mbps only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | ADVERTISE_100_FULL; @@ -668,10 +709,11 @@ e1000_check_copper_options(struct e1000_adapter *adapter) adapter->hw.autoneg_advertised = 0; break; case SPEED_1000: + DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without " + "Duplex\n"); DPRINTK(PROBE, INFO, - "1000 Mbps Speed specified without Duplex\n"); - DPRINTK(PROBE, INFO, - "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); + "Using Autonegotiation at 1000 Mbps " + "Full Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; @@ -679,7 +721,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) DPRINTK(PROBE, INFO, "Half Duplex is not supported at 1000 Mbps\n"); DPRINTK(PROBE, INFO, - "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); + "Using Autonegotiation at 1000 Mbps " + "Full Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; @@ -696,8 +739,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) /* Speed, AutoNeg and MDI/MDI-X must all play nice */ if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) { DPRINTK(PROBE, INFO, - "Speed, AutoNeg and MDI-X specifications are " - "incompatible. Setting MDI-X to a compatible value.\n"); + "Speed, AutoNeg and MDI-X specifications are " + "incompatible. Setting MDI-X to a compatible value.\n"); } } diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 9f5ea6075..3f05a33e7 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -145,9 +145,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c index 36b5508f4..0199073aa 100644 --- a/drivers/net/eepro100.c +++ b/drivers/net/eepro100.c @@ -88,7 +88,6 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; #define PKT_BUF_SZ 1536 #include -#include #include #include @@ -103,8 +102,8 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include -#include #include #include #include @@ -491,9 +490,6 @@ struct speedo_private { unsigned short partner; /* Link partner caps. */ struct mii_if_info mii_if; /* MII API hooks, info */ u32 msg_enable; /* debug message level */ -#ifdef CONFIG_PM - u32 pm_state[16]; -#endif }; /* The parameters for a CmdConfigure operation. @@ -542,6 +538,7 @@ static struct net_device_stats *speedo_get_stats(struct net_device *dev); static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); static void speedo_show_state(struct net_device *dev); +static struct ethtool_ops ethtool_ops; @@ -896,6 +893,7 @@ static int __devinit speedo_found1(struct pci_dev *pdev, dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_speedo; #endif @@ -2011,82 +2009,68 @@ speedo_get_stats(struct net_device *dev) return &sp->stats; } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; struct speedo_private *sp = netdev_priv(dev); - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - /* get driver-specific version/etc. info */ - 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, pci_name(sp->pdev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&sp->lock); - mii_ethtool_gset(&sp->mii_if, &ecmd); - spin_unlock_irq(&sp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&sp->lock); - r = mii_ethtool_sset(&sp->mii_if, &ecmd); - spin_unlock_irq(&sp->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&sp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&sp->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = sp->msg_enable; - 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; - sp->msg_enable = edata.data; - return 0; - } + strncpy(info->driver, "eepro100", sizeof(info->driver)-1); + strncpy(info->version, version, sizeof(info->version)-1); + if (sp->pdev) + strcpy(info->bus_info, pci_name(sp->pdev)); +} - } - - return -EOPNOTSUPP; +static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct speedo_private *sp = netdev_priv(dev); + spin_lock_irq(&sp->lock); + mii_ethtool_gset(&sp->mii_if, ecmd); + spin_unlock_irq(&sp->lock); + return 0; +} + +static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct speedo_private *sp = netdev_priv(dev); + int res; + spin_lock_irq(&sp->lock); + res = mii_ethtool_sset(&sp->mii_if, ecmd); + spin_unlock_irq(&sp->lock); + return res; } +static int speedo_nway_reset(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return mii_nway_restart(&sp->mii_if); +} + +static u32 speedo_get_link(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return mii_link_ok(&sp->mii_if); +} + +static u32 speedo_get_msglevel(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return sp->msg_enable; +} + +static void speedo_set_msglevel(struct net_device *dev, u32 v) +{ + struct speedo_private *sp = netdev_priv(dev); + sp->msg_enable = v; +} + +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = speedo_get_drvinfo, + .get_settings = speedo_get_settings, + .set_settings = speedo_set_settings, + .nway_reset = speedo_nway_reset, + .get_link = speedo_get_link, + .get_msglevel = speedo_get_msglevel, + .set_msglevel = speedo_set_msglevel, +}; + static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct speedo_private *sp = netdev_priv(dev); @@ -2122,8 +2106,6 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); return 0; - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); default: return -EOPNOTSUPP; } @@ -2335,7 +2317,7 @@ static int eepro100_suspend(struct pci_dev *pdev, u32 state) struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; - pci_save_state(pdev, sp->pm_state); + pci_save_state(pdev); if (!netif_running(dev)) return 0; @@ -2346,6 +2328,8 @@ static int eepro100_suspend(struct pci_dev *pdev, u32 state) outl(PortPartialReset, ioaddr + SCBPort); /* XXX call pci_set_power_state ()? */ + pci_disable_device(pdev); + pci_set_power_state (pdev, 3); return 0; } @@ -2355,7 +2339,10 @@ static int eepro100_resume(struct pci_dev *pdev) struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; - pci_restore_state(pdev, sp->pm_state); + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); if (!netif_running(dev)) return 0; @@ -2447,22 +2434,6 @@ static struct pci_driver eepro100_driver = { #endif /* CONFIG_PM */ }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48) -static int pci_module_init(struct pci_driver *pdev) -{ - int rc; - - rc = pci_register_driver(pdev); - if (rc <= 0) { - printk(KERN_INFO "%s: No cards found, driver not installed.\n", - pdev->name); - pci_unregister_driver(pdev); - return -ENODEV; - } - return 0; -} -#endif - static int __init eepro100_init_module(void) { #ifdef MODULE diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 1880fc0ba..8d0585f78 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -115,9 +115,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 771bfc672..459013762 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -80,8 +80,6 @@ These may be modified when a driver module is loaded.*/ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; /* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ @@ -99,9 +97,9 @@ static int rx_copybreak; Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 32 +#define TX_RING_SIZE 256 +#define TX_QUEUE_LEN 240 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc) @@ -135,7 +133,7 @@ static int rx_copybreak; #include #include #include -#include +#include #include #include @@ -152,12 +150,10 @@ MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver"); MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); -MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); @@ -289,6 +285,12 @@ enum CommandBits { StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80, }; +#define EpicRemoved 0xffffffff /* Chip failed or removed (CardBus) */ + +#define EpicNapiEvent (TxEmpty | TxDone | \ + RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) +#define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) + static u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -327,9 +329,12 @@ struct epic_private { /* Ring pointers. */ spinlock_t lock; /* Group with Tx control cache line. */ + spinlock_t napi_lock; + unsigned int reschedule_in_poll; unsigned int cur_tx, dirty_tx; unsigned int cur_rx, dirty_rx; + u32 irq_mask; unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct pci_dev *pci_dev; /* PCI bus location. */ @@ -356,7 +361,8 @@ static void epic_timer(unsigned long data); static void epic_tx_timeout(struct net_device *dev); static void epic_init_ring(struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int epic_rx(struct net_device *dev); +static int epic_rx(struct net_device *dev, int budget); +static int epic_poll(struct net_device *dev, int *budget); static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; @@ -375,7 +381,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, int irq; struct net_device *dev; struct epic_private *ep; - int i, option = 0, duplex = 0; + int i, ret, option = 0, duplex = 0; void *ring_space; dma_addr_t ring_dma; @@ -389,29 +395,33 @@ static int __devinit epic_init_one (struct pci_dev *pdev, card_idx++; - i = pci_enable_device(pdev); - if (i) - return i; + ret = pci_enable_device(pdev); + if (ret) + goto out; irq = pdev->irq; if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { printk (KERN_ERR "card %d: no PCI region space\n", card_idx); - return -ENODEV; + ret = -ENODEV; + goto err_out_disable; } pci_set_master(pdev); + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) + goto err_out_disable; + + ret = -ENOMEM; + dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); - return -ENOMEM; + goto err_out_free_res; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_free_netdev; - #ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0); #else @@ -419,7 +429,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev, ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); - goto err_out_free_res; + goto err_out_free_netdev; } #endif @@ -456,7 +466,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev, dev->base_addr = ioaddr; dev->irq = irq; - spin_lock_init (&ep->lock); + spin_lock_init(&ep->lock); + spin_lock_init(&ep->napi_lock); + ep->reschedule_in_poll = 0; /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); @@ -486,6 +498,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev, ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + ep->irq_mask = + (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | EpicNapiEvent; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -540,10 +555,12 @@ static int __devinit epic_init_one (struct pci_dev *pdev, dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; + dev->poll = epic_poll; + dev->weight = 64; - i = register_netdev(dev); - if (i) - goto err_out_unmap_tx; + ret = register_netdev(dev); + if (ret < 0) + goto err_out_unmap_rx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); @@ -551,19 +568,24 @@ static int __devinit epic_init_one (struct pci_dev *pdev, printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - return 0; +out: + return ret; +err_out_unmap_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); err_out_iounmap: #ifndef USE_IO_OPS iounmap(ioaddr); -err_out_free_res: -#endif - pci_release_regions(pdev); err_out_free_netdev: +#endif free_netdev(dev); - return -ENODEV; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; } /* Serial EEPROM section. */ @@ -589,6 +611,38 @@ err_out_free_netdev: #define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) +static void epic_disable_int(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(0x00000000, ioaddr + INTMASK); +} + +static inline void __epic_pci_commit(long ioaddr) +{ +#ifndef USE_IO_OPS + inl(ioaddr + INTMASK); +#endif +} + +static inline void epic_napi_irq_off(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK); + __epic_pci_commit(ioaddr); +} + +static inline void epic_napi_irq_on(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + /* No need to commit possible posted write */ + outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK); +} + static int __devinit read_eeprom(long ioaddr, int location) { int i; @@ -749,9 +803,8 @@ static int epic_open(struct net_device *dev) /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " @@ -792,7 +845,7 @@ static void epic_pause(struct net_device *dev) } /* Remove the packets on the Rx queue. */ - epic_rx(dev); + epic_rx(dev, RX_RING_SIZE); } static void epic_restart(struct net_device *dev) @@ -838,9 +891,9 @@ static void epic_restart(struct net_device *dev) /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL), @@ -926,7 +979,6 @@ static void epic_init_ring(struct net_device *dev) int i; ep->tx_full = 0; - ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; ep->dirty_tx = ep->cur_tx = 0; ep->cur_rx = ep->dirty_rx = 0; ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1026,6 +1078,76 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } +static void epic_tx_error(struct net_device *dev, struct epic_private *ep, + int status) +{ + struct net_device_stats *stats = &ep->stats; + +#ifndef final_version + /* There was an major error, log it. */ + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + stats->tx_errors++; + if (status & 0x1050) + stats->tx_aborted_errors++; + if (status & 0x0008) + stats->tx_carrier_errors++; + if (status & 0x0040) + stats->tx_window_errors++; + if (status & 0x0010) + stats->tx_fifo_errors++; +} + +static void epic_tx(struct net_device *dev, struct epic_private *ep) +{ + unsigned int dirty_tx, cur_tx; + + /* + * Note: if this lock becomes a problem we can narrow the locked + * region at the cost of occasionally grabbing the lock more times. + */ + cur_tx = ep->cur_tx; + for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) { + struct sk_buff *skb; + int entry = dirty_tx % TX_RING_SIZE; + int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + + if (txstatus & DescOwn) + break; /* It still hasn't been Txed */ + + if (likely(txstatus & 0x0001)) { + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; + ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; + } else + epic_tx_error(dev, ep, txstatus); + + /* Free the original skb. */ + skb = ep->tx_skbuff[entry]; + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + ep->tx_skbuff[entry] = NULL; + } + +#ifndef final_version + if (cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_WARNING + "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, cur_tx, ep->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + ep->dirty_tx = dirty_tx; + if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, allow new TX entries. */ + ep->tx_full = 0; + netif_wake_queue(dev); + } +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1033,135 +1155,71 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *r struct net_device *dev = dev_instance; struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int status, boguscnt = max_interrupt_work; unsigned int handled = 0; + int status; - do { - status = inl(ioaddr + INTSTAT); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(status & 0x00007fff, ioaddr + INTSTAT); + status = inl(ioaddr + INTSTAT); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(status & EpicNormalEvent, ioaddr + INTSTAT); - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " - "intstat=%#8.8x.\n", - dev->name, status, (int)inl(ioaddr + INTSTAT)); + if (debug > 4) { + printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " + "intstat=%#8.8x.\n", dev->name, status, + (int)inl(ioaddr + INTSTAT)); + } - if ((status & IntrSummary) == 0) - break; - handled = 1; - - if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow)) - epic_rx(dev); - - if (status & (TxEmpty | TxDone)) { - unsigned int dirty_tx, cur_tx; - - /* Note: if this lock becomes a problem we can narrow the locked - region at the cost of occasionally grabbing the lock more - times. */ - spin_lock(&ep->lock); - cur_tx = ep->cur_tx; - dirty_tx = ep->dirty_tx; - for (; cur_tx - dirty_tx > 0; dirty_tx++) { - struct sk_buff *skb; - int entry = dirty_tx % TX_RING_SIZE; - int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); - - if (txstatus & DescOwn) - break; /* It still hasn't been Txed */ - - if ( ! (txstatus & 0x0001)) { - /* There was an major error, log it. */ -#ifndef final_version - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); -#endif - ep->stats.tx_errors++; - if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; - if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; - if (txstatus & 0x0040) ep->stats.tx_window_errors++; - if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; - } else { - ep->stats.collisions += (txstatus >> 8) & 15; - ep->stats.tx_packets++; - ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; - } - - /* Free the original skb. */ - skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - ep->tx_skbuff[entry] = NULL; - } + if ((status & IntrSummary) == 0) + goto out; -#ifndef final_version - if (cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, cur_tx, ep->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - ep->dirty_tx = dirty_tx; - if (ep->tx_full - && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, allow new TX entries. */ - ep->tx_full = 0; - spin_unlock(&ep->lock); - netif_wake_queue(dev); - } else - spin_unlock(&ep->lock); - } + handled = 1; - /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow | RxFull | - PCIBusErr170 | PCIBusErr175)) { - if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ - break; - /* Always update the error counts to avoid overhead later. */ - ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); - ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); - ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - - if (status & TxUnderrun) { /* Tx FIFO underflow. */ - ep->stats.tx_fifo_errors++; - outl(ep->tx_threshold += 128, ioaddr + TxThresh); - /* Restart the transmit process. */ - outl(RestartTx, ioaddr + COMMAND); - } - if (status & RxOverflow) { /* Missed a Rx frame. */ - ep->stats.rx_errors++; - } - if (status & (RxOverflow | RxFull)) - outw(RxQueued, ioaddr + COMMAND); - if (status & PCIBusErr170) { - printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", - dev->name, status); - epic_pause(dev); - epic_restart(dev); - } - /* Clear all error sources. */ - outl(status & 0x7f18, ioaddr + INTSTAT); + if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { + spin_lock(&ep->napi_lock); + if (netif_rx_schedule_prep(dev)) { + epic_napi_irq_off(dev, ep); + __netif_rx_schedule(dev); + } else + ep->reschedule_in_poll++; + spin_unlock(&ep->napi_lock); + } + status &= ~EpicNapiEvent; + + /* Check uncommon events all at once. */ + if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { + if (status == EpicRemoved) + goto out; + + /* Always update the error counts to avoid overhead later. */ + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); + + if (status & TxUnderrun) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + outl(ep->tx_threshold += 128, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(RestartTx, ioaddr + COMMAND); } - if (--boguscnt < 0) { - printk(KERN_ERR "%s: Too much work at interrupt, " - "IntrStatus=0x%8.8x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + INTSTAT); - break; + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } - } while (1); + /* Clear all error sources. */ + outl(status & 0x7f18, ioaddr + INTSTAT); + } - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, status); +out: + if (debug > 3) { + printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n", + dev->name, status); + } return IRQ_RETVAL(handled); } -static int epic_rx(struct net_device *dev) +static int epic_rx(struct net_device *dev, int budget) { struct epic_private *ep = dev->priv; int entry = ep->cur_rx % RX_RING_SIZE; @@ -1171,6 +1229,10 @@ static int epic_rx(struct net_device *dev) if (debug > 4) printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); + + if (rx_work_limit > budget) + rx_work_limit = budget; + /* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); @@ -1226,7 +1288,7 @@ static int epic_rx(struct net_device *dev) ep->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; ep->stats.rx_packets++; ep->stats.rx_bytes += pkt_len; @@ -1254,6 +1316,65 @@ static int epic_rx(struct net_device *dev) return work_done; } +static void epic_rx_err(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + int status; + + status = inl(ioaddr + INTSTAT); + + if (status == EpicRemoved) + return; + if (status & RxOverflow) /* Missed a Rx frame. */ + ep->stats.rx_errors++; + if (status & (RxOverflow | RxFull)) + outw(RxQueued, ioaddr + COMMAND); +} + +static int epic_poll(struct net_device *dev, int *budget) +{ + struct epic_private *ep = dev->priv; + int work_done, orig_budget; + long ioaddr = dev->base_addr; + + orig_budget = (*budget > dev->quota) ? dev->quota : *budget; + +rx_action: + + epic_tx(dev, ep); + + work_done = epic_rx(dev, *budget); + + epic_rx_err(dev, ep); + + *budget -= work_done; + dev->quota -= work_done; + + if (netif_running(dev) && (work_done < orig_budget)) { + unsigned long flags; + int more; + + /* A bit baroque but it avoids a (space hungry) spin_unlock */ + + spin_lock_irqsave(&ep->napi_lock, flags); + + more = ep->reschedule_in_poll; + if (!more) { + __netif_rx_complete(dev); + outl(EpicNapiEvent, ioaddr + INTSTAT); + epic_napi_irq_on(dev, ep); + } else + ep->reschedule_in_poll--; + + spin_unlock_irqrestore(&ep->napi_lock, flags); + + if (more) + goto rx_action; + } + + return (work_done >= orig_budget); +} + static int epic_close(struct net_device *dev) { long ioaddr = dev->base_addr; @@ -1268,9 +1389,13 @@ static int epic_close(struct net_device *dev) dev->name, (int)inl(ioaddr + INTSTAT)); del_timer_sync(&ep->timer); - epic_pause(dev); + + epic_disable_int(dev, ep); + free_irq(dev->irq, dev); + epic_pause(dev); + /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { skb = ep->rx_skbuff[i]; @@ -1491,6 +1616,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev) #endif pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } diff --git a/drivers/net/eql.c b/drivers/net/eql.c index a53574b0e..fd66d2722 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -164,12 +164,12 @@ static char version[] __initdata = static void __init eql_setup(struct net_device *dev) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); SET_MODULE_OWNER(dev); init_timer(&eql->timer); - eql->timer.data = (unsigned long) dev->priv; + eql->timer.data = (unsigned long) eql; eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL; eql->timer.function = eql_timer; @@ -197,7 +197,7 @@ static void __init eql_setup(struct net_device *dev) static int eql_open(struct net_device *dev) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); /* XXX We should force this off automatically for the user. */ printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on " @@ -241,7 +241,7 @@ static void eql_kill_slave_queue(slave_queue_t *queue) static int eql_close(struct net_device *dev) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); /* * The timer has to be stopped first before we start hacking away @@ -326,7 +326,7 @@ static slave_t *__eql_schedule_slaves(slave_queue_t *queue) static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); slave_t *slave; spin_lock(&eql->queue.lock); @@ -352,7 +352,7 @@ static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats * eql_get_stats(struct net_device *dev) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); return &eql->stats; } @@ -378,7 +378,7 @@ static slave_t *__eql_find_slave_dev(slave_queue_t *queue, struct net_device *de static inline int eql_is_full(slave_queue_t *queue) { - equalizer_t *eql = queue->master_dev->priv; + equalizer_t *eql = netdev_priv(queue->master_dev); if (queue->num_slaves >= eql->max_slaves) return 1; @@ -420,7 +420,7 @@ static int eql_enslave(struct net_device *master_dev, slaving_request_t __user * if (!eql_is_master(slave_dev) && !eql_is_slave(slave_dev)) { slave_t *s = kmalloc(sizeof(*s), GFP_KERNEL); - equalizer_t *eql = master_dev->priv; + equalizer_t *eql = netdev_priv(master_dev); int ret; if (!s) { @@ -453,7 +453,7 @@ static int eql_enslave(struct net_device *master_dev, slaving_request_t __user * static int eql_emancipate(struct net_device *master_dev, slaving_request_t __user *srqp) { - equalizer_t *eql = master_dev->priv; + equalizer_t *eql = netdev_priv(master_dev); struct net_device *slave_dev; slaving_request_t srq; int ret; @@ -485,7 +485,7 @@ static int eql_emancipate(struct net_device *master_dev, slaving_request_t __use static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *scp) { - equalizer_t *eql = dev->priv; + equalizer_t *eql = netdev_priv(dev); slave_t *slave; struct net_device *slave_dev; slave_config_t sc; @@ -539,7 +539,7 @@ static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp) if (!slave_dev) return ret; - eql = dev->priv; + eql = netdev_priv(dev); spin_lock_bh(&eql->queue.lock); if (eql_is_slave(slave_dev)) { slave = __eql_find_slave_dev(&eql->queue, slave_dev); @@ -561,7 +561,7 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp) master_config_t mc; if (eql_is_master(dev)) { - eql = dev->priv; + eql = netdev_priv(dev); mc.max_slaves = eql->max_slaves; mc.min_slaves = eql->min_slaves; if (copy_to_user(mcp, &mc, sizeof (master_config_t))) @@ -580,7 +580,7 @@ static int eql_s_master_cfg(struct net_device *dev, master_config_t __user *mcp) return -EFAULT; if (eql_is_master(dev)) { - eql = dev->priv; + eql = netdev_priv(dev); eql->max_slaves = mc.max_slaves; eql->min_slaves = mc.min_slaves; return 0; diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index 5a9ae260f..39f678270 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -160,9 +160,9 @@ static char *version = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c index ef47c5c9a..24f237b22 100644 --- a/drivers/net/ethertap.c +++ b/drivers/net/ethertap.c @@ -124,7 +124,7 @@ static int ethertap_open(struct net_device *dev) struct net_local *lp = netdev_priv(dev); if (ethertap_debug > 2) - printk(KERN_DEBUG "%s: Doing ethertap_open()...", dev->name); + printk(KERN_DEBUG "%s: Doing ethertap_open()...\n", dev->name); lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx); if (lp->nl == NULL) diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index d896baa2e..8f995141b 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -161,8 +161,8 @@ #include #include #include +#include -#include #include #include #include @@ -305,6 +305,8 @@ static int ewrk3_close(struct net_device *dev); static struct net_device_stats *ewrk3_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static struct ethtool_ops ethtool_ops_203; +static struct ethtool_ops ethtool_ops; /* ** Private functions @@ -532,7 +534,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) printk(" is in I/O only mode"); } - lp = (struct ewrk3_private *) dev->priv; + lp = netdev_priv(dev); lp->shmem_base = mem_start; lp->shmem_length = shmem_length; lp->lemac = lemac; @@ -610,6 +612,10 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) dev->get_stats = ewrk3_get_stats; dev->set_multicast_list = set_multicast_list; dev->do_ioctl = ewrk3_ioctl; + if (lp->adapter_name[4] == '3') + SET_ETHTOOL_OPS(dev, ðtool_ops_203); + else + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = ewrk3_timeout; dev->watchdog_timeo = QUEUE_PKT_TIMEOUT; @@ -621,7 +627,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) static int ewrk3_open(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int i, status = 0; u_char icr, csr; @@ -684,7 +690,7 @@ static int ewrk3_open(struct net_device *dev) */ static void ewrk3_init(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_char csr, page; u_long iobase = dev->base_addr; int i; @@ -725,7 +731,7 @@ static void ewrk3_init(struct net_device *dev) static void ewrk3_timeout(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_char icr, csr; u_long iobase = dev->base_addr; @@ -761,7 +767,7 @@ static void ewrk3_timeout(struct net_device *dev) */ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_long buf = 0; u_char icr; @@ -883,7 +889,7 @@ static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs) u_long iobase; u_char icr, cr, csr; - lp = (struct ewrk3_private *) dev->priv; + lp = netdev_priv(dev); iobase = dev->base_addr; /* get the interrupt information */ @@ -931,7 +937,7 @@ static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Called with lp->hw_lock held */ static int ewrk3_rx(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int i, status = 0; u_char page; @@ -1059,7 +1065,7 @@ static int ewrk3_rx(struct net_device *dev) */ static int ewrk3_tx(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char tx_status; @@ -1095,7 +1101,7 @@ static int ewrk3_tx(struct net_device *dev) static int ewrk3_close(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char icr, csr; @@ -1130,7 +1136,7 @@ static int ewrk3_close(struct net_device *dev) static struct net_device_stats *ewrk3_get_stats(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); /* Null body since there is no framing error counter */ return &lp->stats; @@ -1141,7 +1147,7 @@ static struct net_device_stats *ewrk3_get_stats(struct net_device *dev) */ static void set_multicast_list(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char csr; @@ -1174,7 +1180,7 @@ static void set_multicast_list(struct net_device *dev) */ static void SetMulticastFilter(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); struct dev_mc_list *dmi = dev->mc_list; u_long iobase = dev->base_addr; int i; @@ -1520,195 +1526,173 @@ static int __init EISA_signature(char *name, s32 eisa_id) return status; /* return the device name string */ } -static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; - u_long iobase = dev->base_addr; - u32 ethcmd; - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - /* Get driver info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL); - - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - sprintf(info.fw_version, "%d", fwrev); - strcpy(info.bus_info, "N/A"); - info.eedump_len = EEPROM_MAX; - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - /* Get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - u_char cr = inb(EWRK3_CR); - - switch (lp->adapter_name[4]) { - case '3': /* DE203 */ - ecmd.supported = SUPPORTED_BNC; - ecmd.port = PORT_BNC; - break; + int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL); - case '4': /* DE204 */ - ecmd.supported = SUPPORTED_TP; - ecmd.port = PORT_TP; - break; + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + sprintf(info->fw_version, "%d", fwrev); + strcpy(info->bus_info, "N/A"); + info->eedump_len = EEPROM_MAX; +} - case '5': /* DE205 */ - ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI; - ecmd.autoneg = !(cr & CR_APD); - /* - ** Port is only valid if autoneg is disabled - ** and even then we don't know if AUI is jumpered. - */ - if (!ecmd.autoneg) - ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP; - break; - } +static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + u8 cr = inb(EWRK3_CR); + + switch (lp->adapter_name[4]) { + case '3': /* DE203 */ + ecmd->supported = SUPPORTED_BNC; + ecmd->port = PORT_BNC; + break; - ecmd.supported |= SUPPORTED_10baseT_Half; - ecmd.speed = SPEED_10; - ecmd.duplex = DUPLEX_HALF; + case '4': /* DE204 */ + ecmd->supported = SUPPORTED_TP; + ecmd->port = PORT_TP; + break; - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; + case '5': /* DE205 */ + ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI; + ecmd->autoneg = !(cr & CR_APD); + /* + ** Port is only valid if autoneg is disabled + ** and even then we don't know if AUI is jumpered. + */ + if (!ecmd->autoneg) + ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP; + break; } - /* Set settings */ - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - u_char cr; - u_long flags; - - /* DE205 is the only card with anything to set */ - if (lp->adapter_name[4] != '5') - return -EOPNOTSUPP; - - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - - /* Sanity-check parameters */ - if (ecmd.speed != SPEED_10) - return -EINVAL; - if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC) - return -EINVAL; /* AUI is not software-selectable */ - if (ecmd.transceiver != XCVR_INTERNAL) - return -EINVAL; - if (ecmd.duplex != DUPLEX_HALF) - return -EINVAL; - if (ecmd.phy_address != 0) - return -EINVAL; - - spin_lock_irqsave(&lp->hw_lock, flags); - cr = inb(EWRK3_CR); - - /* If Autoneg is set, change to Auto Port mode */ - /* Otherwise, disable Auto Port and set port explicitly */ - if (ecmd.autoneg) { - cr &= ~CR_APD; - } else { - cr |= CR_APD; - if (ecmd.port == PORT_TP) - cr &= ~CR_PSEL; /* Force TP */ - else - cr |= CR_PSEL; /* Force BNC */ - } - - /* Commit the changes */ - outb(cr, EWRK3_CR); + ecmd->supported |= SUPPORTED_10baseT_Half; + ecmd->speed = SPEED_10; + ecmd->duplex = DUPLEX_HALF; + return 0; +} - spin_unlock_irqrestore(&lp->hw_lock, flags); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } +static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + unsigned long flags; + u8 cr; - /* Get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - u_char cmr = inb(EWRK3_CMR); + /* DE205 is the only card with anything to set */ + if (lp->adapter_name[4] != '5') + return -EOPNOTSUPP; - /* DE203 has BNC only and link status does not apply */ - if (lp->adapter_name[4] == '3') - return -EOPNOTSUPP; + /* Sanity-check parameters */ + if (ecmd->speed != SPEED_10) + return -EINVAL; + if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC) + return -EINVAL; /* AUI is not software-selectable */ + if (ecmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if (ecmd->duplex != DUPLEX_HALF) + return -EINVAL; + if (ecmd->phy_address != 0) + return -EINVAL; - /* On DE204 this is always valid since TP is the only port. */ - /* On DE205 this reflects TP status even if BNC or AUI is selected. */ - edata.data = !(cmr & CMR_LINK); + spin_lock_irqsave(&lp->hw_lock, flags); + cr = inb(EWRK3_CR); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + /* If Autoneg is set, change to Auto Port mode */ + /* Otherwise, disable Auto Port and set port explicitly */ + if (ecmd->autoneg) { + cr &= ~CR_APD; + } else { + cr |= CR_APD; + if (ecmd->port == PORT_TP) + cr &= ~CR_PSEL; /* Force TP */ + else + cr |= CR_PSEL; /* Force BNC */ } - /* Blink LED for identification */ - case ETHTOOL_PHYS_ID: { - struct ethtool_value edata; - u_long flags; - u_char cr; - int count; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - /* Toggle LED 4x per second */ - count = edata.data << 2; + /* Commit the changes */ + outb(cr, EWRK3_CR); + spin_unlock_irqrestore(&lp->hw_lock, flags); + return 0; +} - spin_lock_irqsave(&lp->hw_lock, flags); +static u32 ewrk3_get_link(struct net_device *dev) +{ + unsigned long iobase = dev->base_addr; + u8 cmr = inb(EWRK3_CMR); + /* DE203 has BNC only and link status does not apply */ + /* On DE204 this is always valid since TP is the only port. */ + /* On DE205 this reflects TP status even if BNC or AUI is selected. */ + return !(cmr & CMR_LINK); +} - /* Bail if a PHYS_ID is already in progress */ - if (lp->led_mask == 0) { - spin_unlock_irqrestore(&lp->hw_lock, flags); - return -EBUSY; - } +static int ewrk3_phys_id(struct net_device *dev, u32 data) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + unsigned long flags; + u8 cr; + int count; - /* Prevent ISR from twiddling the LED */ - lp->led_mask = 0; + /* Toggle LED 4x per second */ + count = data << 2; - while (count--) { - /* Toggle the LED */ - cr = inb(EWRK3_CR); - outb(cr ^ CR_LED, EWRK3_CR); + spin_lock_irqsave(&lp->hw_lock, flags); - /* Wait a little while */ - spin_unlock_irqrestore(&lp->hw_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ>>2); - spin_lock_irqsave(&lp->hw_lock, flags); + /* Bail if a PHYS_ID is already in progress */ + if (lp->led_mask == 0) { + spin_unlock_irqrestore(&lp->hw_lock, flags); + return -EBUSY; + } - /* Exit if we got a signal */ - if (signal_pending(current)) - break; - } + /* Prevent ISR from twiddling the LED */ + lp->led_mask = 0; - lp->led_mask = CR_LED; + while (count--) { + /* Toggle the LED */ cr = inb(EWRK3_CR); - outb(cr & ~CR_LED, EWRK3_CR); + outb(cr ^ CR_LED, EWRK3_CR); + + /* Wait a little while */ spin_unlock_irqrestore(&lp->hw_lock, flags); - return signal_pending(current) ? -ERESTARTSYS : 0; - } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ>>2); + spin_lock_irqsave(&lp->hw_lock, flags); + /* Exit if we got a signal */ + if (signal_pending(current)) + break; } - return -EOPNOTSUPP; + lp->led_mask = CR_LED; + cr = inb(EWRK3_CR); + outb(cr & ~CR_LED, EWRK3_CR); + spin_unlock_irqrestore(&lp->hw_lock, flags); + return signal_pending(current) ? -ERESTARTSYS : 0; } +static struct ethtool_ops ethtool_ops_203 = { + .get_drvinfo = ewrk3_get_drvinfo, + .get_settings = ewrk3_get_settings, + .set_settings = ewrk3_set_settings, + .phys_id = ewrk3_phys_id, +}; + +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = ewrk3_get_drvinfo, + .get_settings = ewrk3_get_settings, + .set_settings = ewrk3_set_settings, + .get_link = ewrk3_get_link, + .phys_id = ewrk3_phys_id, +}; + /* ** Perform IOCTL call functions here. Some are privileged operations and the ** effective uid is checked in those cases. */ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru; u_long iobase = dev->base_addr; int i, j, status = 0; @@ -1721,11 +1705,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) union ewrk3_addr *tmp; - /* ethtool IOCTLs are handled elsewhere */ - if (cmd == SIOCETHTOOL) - return ewrk3_ethtool_ioctl(dev, rq->ifr_data); - - /* Other than ethtool, all we handle are private IOCTLs */ + /* All we handle are private IOCTLs */ if (cmd != EWRK3IOCTL) return -EOPNOTSUPP; diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index 9112ca037..fddc5360f 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -85,9 +85,9 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/fec.c b/drivers/net/fec.c index b9e59da66..2c7008491 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -18,8 +18,8 @@ * Much better multiple PHY support by Magnus Damm. * Copyright (c) 2000 Ericsson Radio Systems AB. * - * Support for FEC controller of ColdFire/5272. - * Copyrught (c) 2001-2002 Greg Ungerer (gerg@snapgear.com) + * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282. + * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com) */ #include @@ -39,14 +39,14 @@ #include #include #include +#include #include -#include #include #include #include -#ifdef CONFIG_M5272 +#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x) #include #include #include "fec.h" @@ -56,19 +56,31 @@ #include "commproc.h" #endif -static int opened = 0; -static int found = 0; +#if defined(CONFIG_FEC2) +#define FEC_MAX_PORTS 2 +#else +#define FEC_MAX_PORTS 1 +#endif /* * Define the fixed address of the FEC hardware. */ -#ifdef CONFIG_M5272 -static volatile fec_t *fec_hwp = (volatile fec_t *) (MCF_MBAR + 0x840); -static ushort my_enet_addr[] = { 0x00d0, 0xcf00, 0x0072 }; +static unsigned int fec_hw[] = { +#if defined(CONFIG_M5272) + (MCF_MBAR + 0x840), +#elif defined(CONFIG_M527x) + (MCF_MBAR + 0x1000), + (MCF_MBAR + 0x1800), +#elif defined(CONFIG_M528x) + (MCF_MBAR + 0x1000), #else -static volatile fec_t *fec_hwp = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec) -static ushort my_enet_addr[3]; -#endif /* CONFIG_M5272 */ + &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), +#endif +}; + +static unsigned char fec_mac_default[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; /* * Some hardware gets it MAC address out of local flash memory. @@ -76,10 +88,12 @@ static ushort my_enet_addr[3]; */ #if defined(CONFIG_NETtel) #define FEC_FLASHMAC 0xf0006006 -#elif defined(CONFIG_GILBARCONAP) +#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES) #define FEC_FLASHMAC 0xf0006000 #elif defined (CONFIG_MTD_KeyTechnology) #define FEC_FLASHMAC 0xffe04000 +#elif defined(CONFIG_CANCam) +#define FEC_FLASHMAC 0xf0020000 #else #define FEC_FLASHMAC 0 #endif @@ -110,21 +124,14 @@ typedef struct { * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. */ -#if 1 -#define FEC_ENET_RX_PAGES 4 -#define FEC_ENET_RX_FRSIZE 2048 -#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) -#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) -#define TX_RING_SIZE 8 /* Must be power of two */ -#define TX_RING_MOD_MASK 7 /* for this to work */ -#else -#define FEC_ENET_RX_PAGES 16 +#define FEC_ENET_RX_PAGES 8 #define FEC_ENET_RX_FRSIZE 2048 #define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) #define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define FEC_ENET_TX_FRSIZE 2048 +#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE) #define TX_RING_SIZE 16 /* Must be power of two */ #define TX_RING_MOD_MASK 15 /* for this to work */ -#endif /* Interrupt events/masks. */ @@ -145,6 +152,18 @@ typedef struct { #define PKT_MINBUF_SIZE 64 #define PKT_MAXBLR_SIZE 1520 + +/* + * The 5270/5271/5280/5282 RX control register also contains maximum frame + * size bits. Other FEC hardware does not, so we need to take that into + * account when setting it. + */ +#if defined(CONFIG_M527x) || defined(CONFIG_M528x) +#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) +#else +#define OPT_FRAME_SIZE 0 +#endif + /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and * tx_bd_base always point to the base of the buffer descriptors. The * cur_rx and cur_tx point to the currently available buffer. @@ -154,7 +173,11 @@ typedef struct { * the buffer descriptor determines the actual condition. */ struct fec_enet_private { + /* Hardware registers of the FEC device */ + volatile fec_t *hwp; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; ushort skb_cur; ushort skb_dirty; @@ -177,12 +200,16 @@ struct fec_enet_private { struct work_struct phy_task; uint sequence_done; + uint mii_phy_task_queued; uint phy_addr; + int index; + int opened; int link; int old_link; int full_duplex; + unsigned char mac_addr[ETH_ALEN]; }; static int fec_enet_open(struct net_device *dev); @@ -299,6 +326,18 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) bdp->cbd_bufaddr = __pa(skb->data); bdp->cbd_datlen = skb->len; + /* + * On some FEC implementations data must be aligned on + * 4-byte boundaries. Use bounce buffers to copy data + * and get it aligned. Ugh. + */ + if (bdp->cbd_bufaddr & 0x3) { + unsigned int index; + index = bdp - fep->tx_bd_base; + memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen); + bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); + } + /* Save skb pointer. */ fep->tx_skbuff[fep->skb_cur] = skb; @@ -407,10 +446,6 @@ fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) */ while ((int_events = fecp->fec_ievent) != 0) { fecp->fec_ievent = int_events; - if ((int_events & (FEC_ENET_HBERR | FEC_ENET_BABR | - FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) { - printk("FEC ERROR %x\n", int_events); - } /* Handle receive event in its own function. */ @@ -542,7 +577,7 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { printk("FEC ENET: rcv is not +last\n"); #endif - if (!opened) + if (!fep->opened) goto rx_processing_done; /* Check for errors. */ @@ -646,7 +681,7 @@ fec_enet_mii(struct net_device *dev) uint mii_reg; fep = netdev_priv(dev); - ep = fec_hwp; + ep = fep->hwp; mii_reg = ep->fec_mii_data; if ((mip = mii_head) == NULL) { @@ -694,7 +729,7 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi } else { mii_head = mii_tail = mip; - fec_hwp->fec_mii_data = regval; + fep->hwp->fec_mii_data = regval; } } else { @@ -1028,6 +1063,43 @@ static phy_info_t phy_info_am79c874 = { }, }; +/* ------------------------------------------------------------------------- */ +/* Kendin KS8721BL phy */ + +/* register definitions for the 8721 */ + +#define MII_KS8721BL_RXERCR 21 +#define MII_KS8721BL_ICSR 22 +#define MII_KS8721BL_PHYCR 31 + +static phy_info_t phy_info_ks8721bl = { + 0x00022161, + "KS8721BL", + + (const phy_cmd_t []) { /* config */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup */ + { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* find out the current status */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + /* we only need to read ISR to acknowledge */ + { mk_mii_read(MII_KS8721BL_ICSR), NULL }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown */ + { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + /* ------------------------------------------------------------------------- */ static phy_info_t *phy_info[] = { @@ -1035,24 +1107,26 @@ static phy_info_t *phy_info[] = { &phy_info_lxt971, &phy_info_qs6612, &phy_info_am79c874, + &phy_info_ks8721bl, NULL }; /* ------------------------------------------------------------------------- */ -static void #ifdef CONFIG_RPXCLASSIC +static void mii_link_interrupt(void *dev_id); #else +static irqreturn_t mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); #endif -#ifdef CONFIG_M5272 +#if defined(CONFIG_M5272) /* * Code specific to Coldfire 5272 setup. */ -static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t *fecp) +static void __inline__ fec_request_intrs(struct net_device *dev) { volatile unsigned long *icrp; @@ -1076,26 +1150,29 @@ static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) { volatile fec_t *fecp; - fecp = fec_hwp; - fecp->fec_r_cntrl = 0x04; + fecp = fep->hwp; + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; fecp->fec_x_cntrl = 0x00; - /* Set MII speed to 2.5 MHz - */ - fecp->fec_mii_speed = fep->phy_speed = 0x0e; + /* + * Set MII speed to 2.5 MHz + * See 5272 manual section 11.5.8: MSCR + */ + fep->phy_speed = ((((MCF_CLK / 4) / (2500000 / 10)) + 5) / 10) * 2; + fecp->fec_mii_speed = fep->phy_speed; fec_restart(dev, 0); } -static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_private *fep) +static void __inline__ fec_get_mac(struct net_device *dev) { + struct fec_enet_private *fep = netdev_priv(dev); volatile fec_t *fecp; - unsigned char *eap, *iap, tmpaddr[6]; + unsigned char *iap, tmpaddr[6]; int i; - fecp = fec_hwp; - eap = (unsigned char *) my_enet_addr; + fecp = fep->hwp; if (fec_flashmac) { /* @@ -1105,18 +1182,24 @@ static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_priva iap = fec_flashmac; if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) - iap = eap; + iap = fec_mac_default; if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) - iap = eap; + iap = fec_mac_default; } else { *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); iap = &tmpaddr[0]; } - for (i=0; i<6; i++) - dev->dev_addr[i] = *eap++ = *iap++; + for (i=0; idev_addr[i] = fep->mac_addr[i] = *iap++; + + /* Adjust MAC if using default MAC address */ + if (iap == fec_mac_default) { + dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = + iap[ETH_ALEN-1] + fep->index; + } } static void __inline__ fec_enable_phy_intr(void) @@ -1151,12 +1234,167 @@ static void __inline__ fec_uncache(unsigned long addr) /* ------------------------------------------------------------------------- */ +#elif defined(CONFIG_M527x) || defined(CONFIG_M528x) + +/* + * Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups. + */ +static void __inline__ fec_request_intrs(struct net_device *dev) +{ + struct fec_enet_private *fep; + int b; + + fep = netdev_priv(dev); + b = (fep->index) ? 128 : 64; + + /* Setup interrupt handlers. */ + if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0) + printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b); + if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0) + printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b); + if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0) + printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b); + if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0) + printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b); + + if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0) + printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b); + if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0) + printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b); + + if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0) + printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b); + if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0) + printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b); + if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0) + printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b); + if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0) + printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b); + if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0) + printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b); + if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0) + printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b); + if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0) + printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b); + + /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */ + { + volatile unsigned char *icrp; + volatile unsigned long *imrp; + int i; + + b = (fep->index) ? MCFICM_INTC1 : MCFICM_INTC0; + icrp = (volatile unsigned char *) (MCF_IPSBAR + b + + MCFINTC_ICR0); + for (i = 23; (i < 36); i++) + icrp[i] = 0x23; + + imrp = (volatile unsigned long *) (MCF_IPSBAR + b + + MCFINTC_IMRH); + *imrp &= ~0x0000000f; + imrp = (volatile unsigned long *) (MCF_IPSBAR + b + + MCFINTC_IMRL); + *imrp &= ~0xff800001; + } + +#if defined(CONFIG_M528x) + /* Set up gpio outputs for MII lines */ + { + volatile unsigned short *gpio_paspar; + + gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR + + 0x100056); + *gpio_paspar = 0x0f00; + } +#endif +} + +static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) +{ + volatile fec_t *fecp; + + fecp = fep->hwp; + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + * See 5282 manual section 17.5.4.7: MSCR + */ + fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; + fecp->fec_mii_speed = fep->phy_speed; + + fec_restart(dev, 0); +} + +static void __inline__ fec_get_mac(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + volatile fec_t *fecp; + unsigned char *iap, tmpaddr[6]; + int i; + + fecp = fep->hwp; + + if (fec_flashmac) { + /* + * Get MAC address from FLASH. + * If it is all 1's or 0's, use the default. + */ + iap = fec_flashmac; + if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && + (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) + iap = fec_mac_default; + if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && + (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) + iap = fec_mac_default; + } else { + *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; + *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); + iap = &tmpaddr[0]; + } + + for (i=0; idev_addr[i] = fep->mac_addr[i] = *iap++; + + /* Adjust MAC if using default MAC address */ + if (iap == fec_mac_default) { + dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] = + iap[ETH_ALEN-1] + fep->index; + } +} + +static void __inline__ fec_enable_phy_intr(void) +{ +} + +static void __inline__ fec_disable_phy_intr(void) +{ +} + +static void __inline__ fec_phy_ack_intr(void) +{ +} + +static void __inline__ fec_localhw_setup(void) +{ +} + +/* + * Do not need to make region uncached on 5272. + */ +static void __inline__ fec_uncache(unsigned long addr) +{ +} + +/* ------------------------------------------------------------------------- */ + #else /* * Code sepcific to the MPC860T setup. */ -static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t *fecp) +static void __inline__ fec_request_intrs(struct net_device *dev) { volatile immap_t *immap; @@ -1184,13 +1422,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t #endif } -static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_private *fep) +static void __inline__ fec_get_mac(struct net_device *dev) { - unsigned char *eap, *iap, tmpaddr[6]; + struct fec_enet_private *fep = netdev_priv(dev); + unsigned char *iap, tmpaddr[6]; bd_t *bd; int i; - eap = (unsigned char *)my_enet_addr; iap = bd->bi_enetaddr; bd = (bd_t *)__res; @@ -1208,7 +1446,7 @@ static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_priva #endif for (i=0; i<6; i++) - dev->dev_addr[i] = *eap++ = *iap++; + dev->dev_addr[i] = fep->mac_addr[i] = *iap++; } static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) @@ -1217,7 +1455,7 @@ static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_priva volatile immap_t *immap; volatile fec_t *fecp; - fecp = fec_hwp; + fecp = fep->hwp; immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ /* Configure all of port D for MII. @@ -1240,7 +1478,8 @@ static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_priva static void __inline__ fec_enable_phy_intr(void) { volatile fec_t *fecp; - fecp = fec_hwp; + + fecp = fep->hwp; /* Enable MII command finished interrupt */ @@ -1258,8 +1497,8 @@ static void __inline__ fec_phy_ack_intr(void) static void __inline__ fec_localhw_setup(void) { volatile fec_t *fecp; - fecp = fec_hwp; + fecp = fep->hwp; fecp->fec_r_hash = PKT_MAXBUF_SIZE; /* Enable big endian and don't care about SDMA FC. */ @@ -1319,6 +1558,11 @@ static void mii_display_config(struct net_device *dev) struct fec_enet_private *fep = netdev_priv(dev); volatile uint *s = &(fep->phy_status); + /* + ** When we get here, phy_task is already removed from + ** the workqueue. It is thus safe to allow to reuse it. + */ + fep->mii_phy_task_queued = 0; printk("%s: config: auto-negotiation ", dev->name); if (*s & PHY_CONF_ANE) @@ -1350,6 +1594,11 @@ static void mii_relink(struct net_device *dev) struct fec_enet_private *fep = netdev_priv(dev); int duplex; + /* + ** When we get here, phy_task is already removed from + ** the workqueue. It is thus safe to allow to reuse it. + */ + fep->mii_phy_task_queued = 0; fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; mii_display_status(dev); fep->old_link = fep->link; @@ -1370,18 +1619,35 @@ static void mii_relink(struct net_device *dev) } +/* mii_queue_relink is called in interrupt context from mii_link_interrupt */ static void mii_queue_relink(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); + /* + ** We cannot queue phy_task twice in the workqueue. It + ** would cause an endless loop in the workqueue. + ** Fortunately, if the last mii_relink entry has not yet been + ** executed now, it will do the job for the current interrupt, + ** which is just what we want. + */ + if (fep->mii_phy_task_queued) + return; + + fep->mii_phy_task_queued = 1; INIT_WORK(&fep->phy_task, (void*)mii_relink, dev); schedule_work(&fep->phy_task); } +/* mii_queue_config is called in user context from fec_enet_open */ static void mii_queue_config(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); + if (fep->mii_phy_task_queued) + return; + + fep->mii_phy_task_queued = 1; INIT_WORK(&fep->phy_task, (void*)mii_display_config, dev); schedule_work(&fep->phy_task); } @@ -1401,7 +1667,7 @@ static void mii_discover_phy3(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep; - int i; + int i; fep = netdev_priv(dev); fep->phy_id |= (mii_reg & 0xffff); @@ -1432,7 +1698,7 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) uint phytype; fep = netdev_priv(dev); - fecp = fec_hwp; + fecp = fep->hwp; if (fep->phy_addr < 32) { if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { @@ -1458,10 +1724,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) /* This interrupt occurs when the PHY detects a link change. */ -static void #ifdef CONFIG_RPXCLASSIC +static void mii_link_interrupt(void *dev_id) #else +static irqreturn_t mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) #endif { @@ -1477,6 +1744,7 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) mii_do_cmd(dev, fep->phy->ack_int); mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ + return IRQ_HANDLED; } static int @@ -1487,7 +1755,6 @@ fec_enet_open(struct net_device *dev) /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. */ - fec_set_mac_address(dev); fep->sequence_done = 0; @@ -1506,6 +1773,12 @@ fec_enet_open(struct net_device *dev) schedule(); mii_do_cmd(dev, fep->phy->startup); + + /* Set the initial link state to true. A lot of hardware + * based on this device does not implement a PHY interrupt, + * so we are never notified of link change. + */ + fep->link = 1; } else { fep->link = 1; /* lets just try it and see */ /* no phy, go full duplex, it's most likely a hub chip */ @@ -1513,16 +1786,18 @@ fec_enet_open(struct net_device *dev) } netif_start_queue(dev); - opened = 1; + fep->opened = 1; return 0; /* Success */ } static int fec_enet_close(struct net_device *dev) { + struct fec_enet_private *fep = netdev_priv(dev); + /* Don't know what to do yet. */ - opened = 0; + fep->opened = 0; netif_stop_queue(dev); fec_stop(dev); @@ -1558,7 +1833,7 @@ static void set_multicast_list(struct net_device *dev) unsigned char hash; fep = netdev_priv(dev); - ep = fec_hwp; + ep = fep->hwp; if (dev->flags&IFF_PROMISC) { /* Log any net taps. */ @@ -1622,18 +1897,18 @@ static void set_multicast_list(struct net_device *dev) static void fec_set_mac_address(struct net_device *dev) { - int i; + struct fec_enet_private *fep; volatile fec_t *fecp; - fecp = fec_hwp; - - /* Set our copy of the Ethernet address */ - for (i = 0; i < (ETH_ALEN / 2); i++) - my_enet_addr[i] = (dev->dev_addr[i*2] << 8) | dev->dev_addr[i*2 + 1]; + fep = netdev_priv(dev); + fecp = fep->hwp; /* Set station address. */ - fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; - fecp->fec_addr_high = my_enet_addr[2] << 16; + fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | + (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24); + fecp->fec_addr_high = (fep->mac_addr[5] << 16) | + (fep->mac_addr[4] << 24); + } /* Initialize the FEC Ethernet on 860T (or ColdFire 5272). @@ -1649,14 +1924,18 @@ int __init fec_enet_init(struct net_device *dev) cbd_t *cbd_base; volatile fec_t *fecp; int i, j; + static int index = 0; /* Only allow us to be probed once. */ - if (found) - return(-ENXIO); + if (index >= FEC_MAX_PORTS) + return -ENXIO; /* Create an Ethernet device instance. */ - fecp = fec_hwp; + fecp = (volatile fec_t *) fec_hw[index]; + + fep->index = index; + fep->hwp = fecp; /* Whack a reset. We should wait for this. */ @@ -1679,7 +1958,7 @@ int __init fec_enet_init(struct net_device *dev) * This is our default MAC address unless the user changes * it via eth_mac_addr (our dev->set_mac_addr handler). */ - fec_get_mac(dev, fep); + fec_get_mac(dev); /* Allocate memory for buffer descriptors. */ @@ -1734,7 +2013,15 @@ int __init fec_enet_init(struct net_device *dev) /* ...and the same for transmmit. */ bdp = fep->tx_bd_base; - for (i=0; i= FEC_ENET_TX_FRPPG) { + mem_addr = __get_free_page(GFP_KERNEL); + j = 1; + } else { + mem_addr += FEC_ENET_TX_FRSIZE; + j++; + } + fep->tx_bounce[i] = (unsigned char *) mem_addr; /* Initialize the BD for every fragment in the page. */ @@ -1756,7 +2043,7 @@ int __init fec_enet_init(struct net_device *dev) /* Install our interrupt handlers. This varies depending on * the architecture. */ - fec_request_intrs(dev, fecp); + fec_request_intrs(dev); dev->base_addr = (unsigned long)fecp; @@ -1788,7 +2075,7 @@ int __init fec_enet_init(struct net_device *dev) fep->phy_addr = 0; mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); - found++; + index++; return 0; } @@ -1800,14 +2087,12 @@ static void fec_restart(struct net_device *dev, int duplex) { struct fec_enet_private *fep; - int i; - unsigned char *eap; volatile cbd_t *bdp; volatile fec_t *fecp; - - fecp = fec_hwp; + int i; fep = netdev_priv(dev); + fecp = fep->hwp; /* Whack a reset. We should wait for this. */ @@ -1826,12 +2111,13 @@ fec_restart(struct net_device *dev, int duplex) /* Set station address. */ - fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; - fecp->fec_addr_high = (my_enet_addr[2] << 16); + fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) | + (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24); + fecp->fec_addr_high = (fep->mac_addr[5] << 16) | + (fep->mac_addr[4] << 24); - eap = (unsigned char *)&my_enet_addr[0]; - for (i=0; i<6; i++) - dev->dev_addr[i] = *eap++; + for (i=0; idev_addr[i] = fep->mac_addr[i]; /* Reset all multicast. */ @@ -1898,11 +2184,12 @@ fec_restart(struct net_device *dev, int duplex) /* Enable MII mode. */ if (duplex) { - fecp->fec_r_cntrl = 0x04; /* MII enable */ - fecp->fec_x_cntrl = 0x04; /* FD enable */ + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */ + fecp->fec_x_cntrl = 0x04; /* FD enable */ } else { - fecp->fec_r_cntrl = 0x06; /* MII enable|No Rcv on Xmit */ + /* MII enable|No Rcv on Xmit */ + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06; fecp->fec_x_cntrl = 0x00; } fep->full_duplex = duplex; @@ -1923,8 +2210,8 @@ fec_stop(struct net_device *dev) volatile fec_t *fecp; struct fec_enet_private *fep; - fecp = fec_hwp; fep = netdev_priv(dev); + fecp = fep->hwp; fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ @@ -1944,29 +2231,27 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } -static struct net_device *fec_dev; - static int __init fec_enet_module_init(void) { struct net_device *dev; - int err; - - dev = alloc_etherdev(sizeof(struct fec_enet_private)); - if (!dev) - return -ENOMEM; - err = fec_enet_init(dev); - if (err) { - free_netdev(dev); - return err; - } - - if (register_netdev(dev) != 0) { - /* XXX: missing cleanup here */ - free_netdev(dev); - return -EIO; + int i, err; + + for (i = 0; (i < FEC_MAX_PORTS); i++) { + dev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!dev) + return -ENOMEM; + err = fec_enet_init(dev); + if (err) { + free_netdev(dev); + continue; + } + if (register_netdev(dev) != 0) { + /* XXX: missing cleanup here */ + free_netdev(dev); + return -EIO; + } } - fec_dev = dev; - return(0); + return 0; } module_init(fec_enet_module_init); diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 3bdb0d78b..c6e4f979f 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -1,8 +1,8 @@ /****************************************************************************/ /* - * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5272 - * and 5282.. + * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5270, + 5271, 5272, 5274, 5275, 5280 and 5282. * * (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2000-2001, Lineo (www.lineo.com) @@ -13,7 +13,7 @@ #define FEC_H /****************************************************************************/ -#ifdef CONFIG_M5282 +#if defined(CONFIG_M527x) || defined(CONFIG_M528x) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models diff --git a/drivers/net/fec_8xx/fec_8xx-netta.c b/drivers/net/fec_8xx/fec_8xx-netta.c index 7d73661aa..29c275e1d 100644 --- a/drivers/net/fec_8xx/fec_8xx-netta.c +++ b/drivers/net/fec_8xx/fec_8xx-netta.c @@ -21,12 +21,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index 1bf15eed6..b4f3a9f8a 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c @@ -30,12 +30,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c index 700233655..8fd1495fa 100644 --- a/drivers/net/fec_8xx/fec_mii.c +++ b/drivers/net/fec_8xx/fec_mii.c @@ -30,12 +30,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c index f0b6f9c9d..04c748523 100644 --- a/drivers/net/fmv18x.c +++ b/drivers/net/fmv18x.c @@ -51,9 +51,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 0ead66f20..cb40c184f 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -75,6 +75,10 @@ * added CK804/MCP04 device IDs, code fixes * for registers, link status and other minor fixes. * 0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe + * 0.29: 31 Aug 2004: Add backup timer for link change notification. + * 0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset + * into nv_close, otherwise reenabling for wol can + * cause DMA to kfree'd memory. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -86,7 +90,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.28" +#define FORCEDETH_VERSION "0.30" #define DRV_NAME "forcedeth" #include @@ -120,10 +124,11 @@ * Hardware access: */ -#define DEV_NEED_LASTPACKET1 0x0001 -#define DEV_IRQMASK_1 0x0002 -#define DEV_IRQMASK_2 0x0004 -#define DEV_NEED_TIMERIRQ 0x0008 +#define DEV_NEED_LASTPACKET1 0x0001 /* set LASTPACKET1 in tx flags */ +#define DEV_IRQMASK_1 0x0002 /* use NVREG_IRQMASK_WANTED_1 for irq mask */ +#define DEV_IRQMASK_2 0x0004 /* use NVREG_IRQMASK_WANTED_2 for irq mask */ +#define DEV_NEED_TIMERIRQ 0x0008 /* set the timer irq flag in the irq mask */ +#define DEV_NEED_LINKTIMER 0x0010 /* poll link settings. Relies on the timer irq */ enum { NvRegIrqStatus = 0x000, @@ -215,6 +220,7 @@ enum { #define NVREG_TXRXCTL_BIT2 0x0004 #define NVREG_TXRXCTL_IDLE 0x0008 #define NVREG_TXRXCTL_RESET 0x0010 +#define NVREG_TXRXCTL_RXCHECK 0x0400 NvRegMIIStatus = 0x180, #define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_LINKCHANGE 0x0008 @@ -311,6 +317,10 @@ struct ring_desc { #define NV_RX_ERROR (1<<30) #define NV_RX_AVAIL (1<<31) +#define NV_RX2_CHECKSUMMASK (0x1C000000) +#define NV_RX2_CHECKSUMOK1 (0x10000000) +#define NV_RX2_CHECKSUMOK2 (0x14000000) +#define NV_RX2_CHECKSUMOK3 (0x18000000) #define NV_RX2_DESCRIPTORVALID (1<<29) #define NV_RX2_SUBSTRACT1 (1<<25) #define NV_RX2_ERROR1 (1<<18) @@ -367,9 +377,17 @@ struct ring_desc { #define OOM_REFILL (1+HZ/20) #define POLL_WAIT (1+HZ/100) +#define LINK_TIMEOUT (3*HZ) +/* + * desc_ver values: + * This field has two purposes: + * - Newer nics uses a different ring layout. The layout is selected by + * comparing np->desc_ver with DESC_VER_xy. + * - It contains bits that are forced on when writing to NvRegTxRxControl. + */ #define DESC_VER_1 0x0 -#define DESC_VER_2 0x02100 +#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK) /* PHY defines */ #define PHY_OUI_MARVELL 0x5043 @@ -435,6 +453,8 @@ struct fe_priv { u32 irqmask; u32 desc_ver; + void __iomem *base; + /* rx specific fields. * Locking: Within irq hander or disable_irq+spin_lock(&np->lock); */ @@ -446,6 +466,11 @@ struct fe_priv { struct timer_list oom_kick; struct timer_list nic_poll; + /* media detection workaround. + * Locking: Within irq hander or disable_irq+spin_lock(&np->lock); + */ + int need_linktimer; + unsigned long link_timeout; /* * tx specific fields. */ @@ -464,15 +489,15 @@ static int max_interrupt_work = 5; static inline struct fe_priv *get_nvpriv(struct net_device *dev) { - return (struct fe_priv *) dev->priv; + return netdev_priv(dev); } -static inline u8 *get_hwbase(struct net_device *dev) +static inline u8 __iomem *get_hwbase(struct net_device *dev) { - return (u8 *) dev->base_addr; + return get_nvpriv(dev)->base; } -static inline void pci_push(u8 * base) +static inline void pci_push(u8 __iomem *base) { /* force out pending posted writes */ readl(base); @@ -487,7 +512,7 @@ static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v) static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target, int delay, int delaymax, const char *msg) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); pci_push(base); do { @@ -509,7 +534,7 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target, */ static int mii_rw(struct net_device *dev, int addr, int miireg, int value) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); u32 reg; int retval; @@ -580,7 +605,7 @@ static int phy_reset(struct net_device *dev) static int phy_init(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg; /* set advertise register */ @@ -657,7 +682,7 @@ static int phy_init(struct net_device *dev) static void nv_start_rx(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name); /* Already running? Stop it. */ @@ -675,7 +700,7 @@ static void nv_start_rx(struct net_device *dev) static void nv_stop_rx(struct net_device *dev) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: nv_stop_rx\n", dev->name); writel(0, base + NvRegReceiverControl); @@ -689,7 +714,7 @@ static void nv_stop_rx(struct net_device *dev) static void nv_start_tx(struct net_device *dev) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: nv_start_tx\n", dev->name); writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl); @@ -698,7 +723,7 @@ static void nv_start_tx(struct net_device *dev) static void nv_stop_tx(struct net_device *dev) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: nv_stop_tx\n", dev->name); writel(0, base + NvRegTransmitterControl); @@ -713,7 +738,7 @@ static void nv_stop_tx(struct net_device *dev) static void nv_txrx_reset(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name); writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl); @@ -740,90 +765,49 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) return &np->stats; } -static int nv_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "forcedeth"); - strcpy(info.version, FORCEDETH_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GLINK: - { - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = !!netif_carrier_ok(dev); + strcpy(info->driver, "forcedeth"); + strcpy(info->version, FORCEDETH_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: - { - struct ethtool_wolinfo wolinfo; - memset(&wolinfo, 0, sizeof(wolinfo)); - wolinfo.supported = WAKE_MAGIC; +static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) +{ + struct fe_priv *np = get_nvpriv(dev); + wolinfo->supported = WAKE_MAGIC; - spin_lock_irq(&np->lock); - if (np->wolenabled) - wolinfo.wolopts = WAKE_MAGIC; - spin_unlock_irq(&np->lock); + spin_lock_irq(&np->lock); + if (np->wolenabled) + wolinfo->wolopts = WAKE_MAGIC; + spin_unlock_irq(&np->lock); +} - if (copy_to_user(useraddr, &wolinfo, sizeof(wolinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: - { - struct ethtool_wolinfo wolinfo; - if (copy_from_user(&wolinfo, useraddr, sizeof(wolinfo))) - return -EFAULT; +static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); - spin_lock_irq(&np->lock); - if (wolinfo.wolopts == 0) { - writel(0, base + NvRegWakeUpFlags); - np->wolenabled = 0; - } - if (wolinfo.wolopts & WAKE_MAGIC) { - writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); - np->wolenabled = 1; - } - spin_unlock_irq(&np->lock); - return 0; + spin_lock_irq(&np->lock); + if (wolinfo->wolopts == 0) { + writel(0, base + NvRegWakeUpFlags); + np->wolenabled = 0; } - - default: - break; + if (wolinfo->wolopts & WAKE_MAGIC) { + writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); + np->wolenabled = 1; } - - return -EOPNOTSUPP; + spin_unlock_irq(&np->lock); + return 0; } -/* - * nv_ioctl: dev->do_ioctl function - * Called with rtnl_lock held. - */ -static int nv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - switch(cmd) { - case SIOCETHTOOL: - return nv_ethtool_ioctl(dev, rq->ifr_data); - default: - return -EOPNOTSUPP; - } -} +static struct ethtool_ops ops = { + .get_drvinfo = nv_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_wol = nv_get_wol, + .set_wol = nv_set_wol, +}; /* * nv_alloc_rx: fill rx ring entries. @@ -1041,7 +1025,7 @@ static void nv_tx_done(struct net_device *dev) static void nv_tx_timeout(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name, readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK); @@ -1173,6 +1157,15 @@ static void nv_rx_process(struct net_device *dev) goto next_pkt; } } + Flags &= NV_RX2_CHECKSUMMASK; + if (Flags == NV_RX2_CHECKSUMOK1 || + Flags == NV_RX2_CHECKSUMOK2 || + Flags == NV_RX2_CHECKSUMOK3) { + dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name); + np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY; + } else { + dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name); + } } /* got a valid packet - forward it to the network core */ skb = np->rx_skbuff[i]; @@ -1210,7 +1203,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) static void nv_set_multicast(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); u32 addr[2]; u32 mask[2]; u32 pff; @@ -1270,7 +1263,7 @@ static void nv_set_multicast(struct net_device *dev) static int nv_update_linkspeed(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); int adv, lpa; int newls = np->linkspeed; int newdup = np->duplex; @@ -1384,32 +1377,36 @@ set_speed: return retval; } +static void nv_linkchange(struct net_device *dev) +{ + if (nv_update_linkspeed(dev)) { + if (netif_carrier_ok(dev)) { + nv_stop_rx(dev); + } else { + netif_carrier_on(dev); + printk(KERN_INFO "%s: link up.\n", dev->name); + } + nv_start_rx(dev); + } else { + if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); + printk(KERN_INFO "%s: link down.\n", dev->name); + nv_stop_rx(dev); + } + } +} + static void nv_link_irq(struct net_device *dev) { - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); u32 miistat; miistat = readl(base + NvRegMIIStatus); writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); - dprintk(KERN_DEBUG "%s: link change notification, status 0x%x.\n", dev->name, miistat); + dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); - if (miistat & (NVREG_MIISTAT_LINKCHANGE)) { - if (nv_update_linkspeed(dev)) { - if (netif_carrier_ok(dev)) { - nv_stop_rx(dev); - } else { - netif_carrier_on(dev); - printk(KERN_INFO "%s: link up.\n", dev->name); - } - nv_start_rx(dev); - } else { - if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - printk(KERN_INFO "%s: link down.\n", dev->name); - nv_stop_rx(dev); - } - } - } + if (miistat & (NVREG_MIISTAT_LINKCHANGE)) + nv_linkchange(dev); dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); } @@ -1417,7 +1414,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); u32 events; int i; @@ -1452,6 +1449,12 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) nv_link_irq(dev); spin_unlock(&np->lock); } + if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { + spin_lock(&np->lock); + nv_linkchange(dev); + spin_unlock(&np->lock); + np->link_timeout = jiffies + LINK_TIMEOUT; + } if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); @@ -1483,7 +1486,7 @@ static void nv_do_nic_poll(unsigned long data) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); disable_irq(dev->irq); /* FIXME: Do we need synchronize_irq(dev->irq) here? */ @@ -1500,7 +1503,7 @@ static void nv_do_nic_poll(unsigned long data) static int nv_open(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); int ret, oom, i; dprintk(KERN_DEBUG "nv_open: begin\n"); @@ -1641,7 +1644,7 @@ out_drain: static int nv_close(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); - u8 *base; + u8 __iomem *base; spin_lock_irq(&np->lock); np->in_shutdown = 1; @@ -1655,9 +1658,10 @@ static int nv_close(struct net_device *dev) spin_lock_irq(&np->lock); nv_stop_tx(dev); nv_stop_rx(dev); - base = get_hwbase(dev); + nv_txrx_reset(dev); /* disable interrupts on the nic or we will lock up */ + base = get_hwbase(dev); writel(0, base + NvRegIrqMask); pci_push(base); dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); @@ -1681,7 +1685,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i struct net_device *dev; struct fe_priv *np; unsigned long addr; - u8 *base; + u8 __iomem *base; int err, i; dev = alloc_etherdev(sizeof(struct fe_priv)); @@ -1743,9 +1747,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->desc_ver = DESC_VER_2; err = -ENOMEM; - dev->base_addr = (unsigned long) ioremap(addr, NV_PCI_REGSZ); - if (!dev->base_addr) + np->base = ioremap(addr, NV_PCI_REGSZ); + if (!np->base) goto out_relreg; + dev->base_addr = (unsigned long)np->base; dev->irq = pci_dev->irq; np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), &np->ring_addr); @@ -1759,7 +1764,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->get_stats = nv_get_stats; dev->change_mtu = nv_change_mtu; dev->set_multicast_list = nv_set_multicast; - dev->do_ioctl = nv_ioctl; + SET_ETHTOOL_OPS(dev, &ops); dev->tx_timeout = nv_tx_timeout; dev->watchdog_timeo = NV_WATCHDOG_TIMEO; @@ -1816,6 +1821,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->irqmask = NVREG_IRQMASK_WANTED_2; if (id->driver_data & DEV_NEED_TIMERIRQ) np->irqmask |= NVREG_IRQ_TIMER; + if (id->driver_data & DEV_NEED_LINKTIMER) { + dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev)); + np->need_linktimer = 1; + np->link_timeout = jiffies + LINK_TIMEOUT; + } else { + dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev)); + np->need_linktimer = 0; + } /* find a suitable phy */ for (i = 1; i < 32; i++) { @@ -1884,7 +1897,7 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) { struct net_device *dev = pci_get_drvdata(pci_dev); struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); + u8 __iomem *base = get_hwbase(dev); unregister_netdev(dev); @@ -1909,21 +1922,21 @@ static struct pci_device_id pci_tbl[] = { .device = PCI_DEVICE_ID_NVIDIA_NVENET_1, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ, + .driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce2 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_2, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, .device = PCI_DEVICE_ID_NVIDIA_NVENET_3, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ, + .driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, }, { /* nForce3 Ethernet Controller */ .vendor = PCI_VENDOR_ID_NVIDIA, diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 5005c1c94..a8ceee273 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -8,7 +8,7 @@ * Author: Andy Fleming * Maintainer: Kumar Gala (kumar.gala@freescale.com) * - * Copyright 2004 Freescale Semiconductor, Inc + * Copyright (c) 2002-2004 Freescale Semiconductor, 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 @@ -96,20 +96,11 @@ #include "gianfar.h" #include "gianfar_phy.h" -#ifdef CONFIG_NET_FASTROUTE -#include -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41) -#define irqreturn_t void -#define IRQ_HANDLED -#endif #define TX_TIMEOUT (1*HZ) #define SKB_ALLOC_TIMEOUT 1000000 #undef BRIEF_GFAR_ERRORS -#define VERBOSE_GFAR_ERRORS +#undef VERBOSE_GFAR_ERRORS #ifdef CONFIG_GFAR_NAPI #define RECEIVE(x) netif_receive_skb(x) @@ -117,9 +108,8 @@ #define RECEIVE(x) netif_rx(x) #endif -#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.0, " -char gfar_driver_name[] = "Gianfar Ethernet"; -char gfar_driver_version[] = "1.0"; +const char gfar_driver_name[] = "Gianfar Ethernet"; +const char gfar_driver_version[] = "1.1"; int startup_gfar(struct net_device *dev); static int gfar_enet_open(struct net_device *dev); @@ -148,24 +138,11 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif -#ifdef CONFIG_NET_FASTROUTE -static int gfar_accept_fastpath(struct net_device *dev, struct dst_entry *dst); -#endif -static inline int try_fastroute(struct sk_buff *skb, struct net_device *dev, int length); -#ifdef CONFIG_GFAR_NAPI static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); -#else -static int gfar_clean_rx_ring(struct net_device *dev); -#endif static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); +static void gfar_phy_startup_timer(unsigned long data); extern struct ethtool_ops gfar_ethtool_ops; -extern void gfar_gstrings_normon(struct net_device *dev, u32 stringset, - u8 * buf); -extern void gfar_fill_stats_normon(struct net_device *dev, - struct ethtool_stats *dummy, u64 * buf); -extern int gfar_stats_count_normon(struct net_device *dev); - MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); @@ -183,7 +160,7 @@ static int gfar_probe(struct ocp_device *ocpdev) struct ocp_gfar_data *einfo; int idx; int err = 0; - struct ethtool_ops *dev_ethtool_ops; + int dev_ethtool_ops = 0; einfo = (struct ocp_gfar_data *) ocpdev->def->additions; @@ -197,7 +174,8 @@ static int gfar_probe(struct ocp_device *ocpdev) /* get a pointer to the register memory which can * configure the PHYs. If it's different from this set, * get the device which has those regs */ - if ((einfo->phyregidx >= 0) && (einfo->phyregidx != ocpdev->def->index)) { + if ((einfo->phyregidx >= 0) && + (einfo->phyregidx != ocpdev->def->index)) { mdiodev = ocp_find_device(OCP_ANY_ID, OCP_FUNC_GFAR, einfo->phyregidx); @@ -222,7 +200,7 @@ static int gfar_probe(struct ocp_device *ocpdev) /* get a pointer to the register memory */ priv->regs = (struct gfar *) - ioremap(ocpdev->def->paddr, sizeof (struct gfar)); + ioremap(ocpdev->def->paddr, sizeof (struct gfar)); if (priv->regs == NULL) { err = -ENOMEM; @@ -238,6 +216,8 @@ static int gfar_probe(struct ocp_device *ocpdev) goto phy_regs_fail; } + spin_lock_init(&priv->lock); + ocp_set_drvdata(ocpdev, dev); /* Stop the DMA engine now, in case it was running before */ @@ -269,15 +249,13 @@ static int gfar_probe(struct ocp_device *ocpdev) gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS); /* Copy the station address into the dev structure, */ - /* and into the address registers MAC_STNADDR1,2. */ - /* Backwards, because little endian MACs are dumb. */ - /* Don't set the regs if the firmware already did */ memcpy(dev->dev_addr, einfo->mac_addr, MAC_ADDR_LEN); /* Set the dev->base_addr to the gfar reg region */ dev->base_addr = (unsigned long) (priv->regs); SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &ocpdev->dev); /* Fill in the dev structure */ dev->open = gfar_enet_open; @@ -293,37 +271,16 @@ static int gfar_probe(struct ocp_device *ocpdev) dev->change_mtu = gfar_change_mtu; dev->mtu = 1500; dev->set_multicast_list = gfar_set_multi; - dev->flags |= IFF_MULTICAST; - - dev_ethtool_ops = - (struct ethtool_ops *)kmalloc(sizeof(struct ethtool_ops), - GFP_KERNEL); - - if(dev_ethtool_ops == NULL) { - err = -ENOMEM; - goto ethtool_fail; - } - - memcpy(dev_ethtool_ops, &gfar_ethtool_ops, sizeof(gfar_ethtool_ops)); - - /* If there is no RMON support in this device, we don't - * want to expose non-existant statistics */ - if((priv->einfo->flags & GFAR_HAS_RMON) == 0) { - dev_ethtool_ops->get_strings = gfar_gstrings_normon; - dev_ethtool_ops->get_stats_count = gfar_stats_count_normon; - dev_ethtool_ops->get_ethtool_stats = gfar_fill_stats_normon; - } - if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0) { - dev_ethtool_ops->set_coalesce = NULL; - dev_ethtool_ops->get_coalesce = NULL; - } + /* Index into the array of possible ethtool + * ops to catch all 4 possibilities */ + if((priv->einfo->flags & GFAR_HAS_RMON) == 0) + dev_ethtool_ops += 1; - dev->ethtool_ops = dev_ethtool_ops; + if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0) + dev_ethtool_ops += 2; -#ifdef CONFIG_NET_FASTROUTE - dev->accept_fastpath = gfar_accept_fastpath; -#endif + dev->ethtool_ops = gfar_op_array[dev_ethtool_ops]; priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; #ifdef CONFIG_GFAR_BUFSTASH @@ -332,24 +289,23 @@ static int gfar_probe(struct ocp_device *ocpdev) priv->tx_ring_size = DEFAULT_TX_RING_SIZE; priv->rx_ring_size = DEFAULT_RX_RING_SIZE; - /* Initially, coalescing is disabled */ - priv->txcoalescing = 0; - priv->txcount = 0; - priv->txtime = 0; - priv->rxcoalescing = 0; - priv->rxcount = 0; - priv->rxtime = 0; + priv->txcoalescing = DEFAULT_TX_COALESCE; + priv->txcount = DEFAULT_TXCOUNT; + priv->txtime = DEFAULT_TXTIME; + priv->rxcoalescing = DEFAULT_RX_COALESCE; + priv->rxcount = DEFAULT_RXCOUNT; + priv->rxtime = DEFAULT_RXTIME; err = register_netdev(dev); if (err) { printk(KERN_ERR "%s: Cannot register net device, aborting.\n", - dev->name); + dev->name); goto register_fail; } /* Print out the device info */ - printk(DEVICE_NAME, dev->name); + printk(KERN_INFO DEVICE_NAME, dev->name); for (idx = 0; idx < 6; idx++) printk("%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':'); printk("\n"); @@ -367,10 +323,7 @@ static int gfar_probe(struct ocp_device *ocpdev) return 0; - register_fail: - kfree(dev_ethtool_ops); -ethtool_fail: iounmap((void *) priv->phyregs); phy_regs_fail: iounmap((void *) priv->regs); @@ -386,7 +339,6 @@ static void gfar_remove(struct ocp_device *ocpdev) ocp_set_drvdata(ocpdev, NULL); - kfree(dev->ethtool_ops); iounmap((void *) priv->regs); iounmap((void *) priv->phyregs); free_netdev(dev); @@ -399,26 +351,90 @@ static int init_phy(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); struct phy_info *curphy; + unsigned int timeout = PHY_INIT_TIMEOUT; + struct gfar *phyregs = priv->phyregs; + struct gfar_mii_info *mii_info; + int err; - priv->link = 1; priv->oldlink = 0; priv->oldspeed = 0; - priv->olddplx = -1; + priv->oldduplex = -1; + + mii_info = kmalloc(sizeof(struct gfar_mii_info), + GFP_KERNEL); + + if(NULL == mii_info) { + printk(KERN_ERR "%s: Could not allocate mii_info\n", + dev->name); + return -ENOMEM; + } + + mii_info->speed = SPEED_1000; + mii_info->duplex = DUPLEX_FULL; + mii_info->pause = 0; + mii_info->link = 1; + + mii_info->advertising = (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full); + mii_info->autoneg = 1; + + mii_info->mii_id = priv->einfo->phyid; + + mii_info->dev = dev; + + mii_info->mdio_read = &read_phy_reg; + mii_info->mdio_write = &write_phy_reg; + + priv->mii_info = mii_info; + + /* Reset the management interface */ + gfar_write(&phyregs->miimcfg, MIIMCFG_RESET); + + /* Setup the MII Mgmt clock speed */ + gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE); + + /* Wait until the bus is free */ + while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) && + timeout--) + cpu_relax(); + + if(timeout <= 0) { + printk(KERN_ERR "%s: The MII Bus is stuck!\n", + dev->name); + err = -1; + goto bus_fail; + } /* get info for this PHY */ - curphy = get_phy_info(dev); + curphy = get_phy_info(priv->mii_info); if (curphy == NULL) { printk(KERN_ERR "%s: No PHY found\n", dev->name); - return -1; + err = -1; + goto no_phy; } - priv->phyinfo = curphy; + mii_info->phyinfo = curphy; - /* Run the commands which configure the PHY */ - phy_run_commands(dev, curphy->config); + /* Run the commands which initialize the PHY */ + if(curphy->init) { + err = curphy->init(priv->mii_info); + + if (err) + goto phy_init_fail; + } return 0; + +phy_init_fail: +no_phy: +bus_fail: + kfree(mii_info); + + return err; } static void init_registers(struct net_device *dev) @@ -494,7 +510,7 @@ void stop_gfar(struct net_device *dev) spin_lock_irqsave(&priv->lock, flags); /* Tell the kernel the link is down */ - priv->link = 0; + priv->mii_info->link = 0; adjust_link(dev); /* Mask all interrupts */ @@ -521,7 +537,12 @@ void stop_gfar(struct net_device *dev) gfar_write(®s->maccfg1, tempval); if (priv->einfo->flags & GFAR_HAS_PHY_INTR) { - phy_run_commands(dev, priv->phyinfo->shutdown); + /* Clear any pending interrupts */ + mii_clear_phy_interrupt(priv->mii_info); + + /* Disable PHY Interrupts */ + mii_configure_phy_interrupt(priv->mii_info, + MII_INTERRUPT_DISABLED); } spin_unlock_irqrestore(&priv->lock, flags); @@ -543,15 +564,11 @@ void stop_gfar(struct net_device *dev) free_skb_resources(priv); - dma_unmap_single(NULL, gfar_read(®s->tbase), - sizeof(struct txbd)*priv->tx_ring_size, - DMA_BIDIRECTIONAL); - dma_unmap_single(NULL, gfar_read(®s->rbase), - sizeof(struct rxbd)*priv->rx_ring_size, - DMA_BIDIRECTIONAL); - - /* Free the buffer descriptors */ - kfree(priv->tx_bd_base); + dma_free_coherent(NULL, + sizeof(struct txbd8)*priv->tx_ring_size + + sizeof(struct rxbd8)*priv->rx_ring_size, + priv->tx_bd_base, + gfar_read(®s->tbase)); } /* If there are any tx skbs or rx skbs still around, free them. @@ -610,7 +627,8 @@ int startup_gfar(struct net_device *dev) { struct txbd8 *txbdp; struct rxbd8 *rxbdp; - unsigned long addr; + dma_addr_t addr; + unsigned long vaddr; int i; struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; @@ -620,32 +638,27 @@ int startup_gfar(struct net_device *dev) gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - addr = - (unsigned int) kmalloc(sizeof (struct txbd8) * priv->tx_ring_size + - sizeof (struct rxbd8) * priv->rx_ring_size, - GFP_KERNEL); + vaddr = (unsigned long) dma_alloc_coherent(NULL, + sizeof (struct txbd8) * priv->tx_ring_size + + sizeof (struct rxbd8) * priv->rx_ring_size, + &addr, GFP_KERNEL); - if (addr == 0) { + if (vaddr == 0) { printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", dev->name); return -ENOMEM; } - priv->tx_bd_base = (struct txbd8 *) addr; + priv->tx_bd_base = (struct txbd8 *) vaddr; /* enet DMA only understands physical addresses */ - gfar_write(®s->tbase, - dma_map_single(NULL, (void *)addr, - sizeof(struct txbd8) * priv->tx_ring_size, - DMA_BIDIRECTIONAL)); + gfar_write(®s->tbase, addr); /* Start the rx descriptor ring where the tx ring leaves off */ addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; - priv->rx_bd_base = (struct rxbd8 *) addr; - gfar_write(®s->rbase, - dma_map_single(NULL, (void *)addr, - sizeof(struct rxbd8) * priv->rx_ring_size, - DMA_BIDIRECTIONAL)); + vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; + priv->rx_bd_base = (struct rxbd8 *) vaddr; + gfar_write(®s->rbase, addr); /* Setup the skbuff rings */ priv->tx_skbuff = @@ -718,7 +731,7 @@ int startup_gfar(struct net_device *dev) /* Install our interrupt handlers for Error, * Transmit, and Receive */ if (request_irq(priv->einfo->interruptError, gfar_error, - SA_SHIRQ, "enet_error", dev) < 0) { + 0, "enet_error", dev) < 0) { printk(KERN_ERR "%s: Can't get IRQ %d\n", dev->name, priv->einfo->interruptError); @@ -727,7 +740,7 @@ int startup_gfar(struct net_device *dev) } if (request_irq(priv->einfo->interruptTransmit, gfar_transmit, - SA_SHIRQ, "enet_tx", dev) < 0) { + 0, "enet_tx", dev) < 0) { printk(KERN_ERR "%s: Can't get IRQ %d\n", dev->name, priv->einfo->interruptTransmit); @@ -737,7 +750,7 @@ int startup_gfar(struct net_device *dev) } if (request_irq(priv->einfo->interruptReceive, gfar_receive, - SA_SHIRQ, "enet_rx", dev) < 0) { + 0, "enet_rx", dev) < 0) { printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n", dev->name, priv->einfo->interruptReceive); @@ -746,7 +759,7 @@ int startup_gfar(struct net_device *dev) } } else { if (request_irq(priv->einfo->interruptTransmit, gfar_interrupt, - SA_SHIRQ, "gfar_interrupt", dev) < 0) { + 0, "gfar_interrupt", dev) < 0) { printk(KERN_ERR "%s: Can't get IRQ %d\n", dev->name, priv->einfo->interruptError); @@ -755,39 +768,13 @@ int startup_gfar(struct net_device *dev) } } - /* Grab the PHY interrupt */ - if (priv->einfo->flags & GFAR_HAS_PHY_INTR) { - if (request_irq(priv->einfo->interruptPHY, phy_interrupt, - SA_SHIRQ, "phy_interrupt", dev) < 0) { - printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", - dev->name, priv->einfo->interruptPHY); - - err = -1; - - if (priv->einfo->flags & GFAR_HAS_MULTI_INTR) - goto phy_irq_fail; - else - goto tx_irq_fail; - } - } else { - init_timer(&priv->phy_info_timer); - priv->phy_info_timer.function = &gfar_phy_timer; - priv->phy_info_timer.data = (unsigned long) dev; - mod_timer(&priv->phy_info_timer, jiffies + 2 * HZ); - } - - /* Set up the bottom half queue */ - INIT_WORK(&priv->tq, (void (*)(void *))gfar_phy_change, dev); - - /* Configure the PHY interrupt */ - phy_run_commands(dev, priv->phyinfo->startup); - - /* Tell the kernel the link is up, and determine the - * negotiated features (speed, duplex) */ - adjust_link(dev); + /* Set up the PHY change work queue */ + INIT_WORK(&priv->tq, gfar_phy_change, dev); - if (priv->link == 0) - printk(KERN_INFO "%s: No link detected\n", dev->name); + init_timer(&priv->phy_info_timer); + priv->phy_info_timer.function = &gfar_phy_startup_timer; + priv->phy_info_timer.data = (unsigned long) priv->mii_info; + mod_timer(&priv->phy_info_timer, jiffies + HZ); /* Configure the coalescing support */ if (priv->txcoalescing) @@ -827,8 +814,6 @@ int startup_gfar(struct net_device *dev) return 0; -phy_irq_fail: - free_irq(priv->einfo->interruptReceive, dev); rx_irq_fail: free_irq(priv->einfo->interruptTransmit, dev); tx_irq_fail: @@ -837,7 +822,17 @@ err_irq_fail: rx_skb_fail: free_skb_resources(priv); tx_skb_fail: - kfree(priv->tx_bd_base); + dma_free_coherent(NULL, + sizeof(struct txbd8)*priv->tx_ring_size + + sizeof(struct rxbd8)*priv->rx_ring_size, + priv->tx_bd_base, + gfar_read(®s->tbase)); + + if (priv->mii_info->phyinfo->close) + priv->mii_info->phyinfo->close(priv->mii_info); + + kfree(priv->mii_info); + return err; } @@ -854,7 +849,7 @@ static int gfar_enet_open(struct net_device *dev) err = init_phy(dev); - if (err) + if(err) return err; err = startup_gfar(dev); @@ -934,8 +929,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Stops the kernel queue, and halts the controller */ static int gfar_close(struct net_device *dev) { + struct gfar_private *priv = netdev_priv(dev); stop_gfar(dev); + /* Shutdown the PHY */ + if (priv->mii_info->phyinfo->close) + priv->mii_info->phyinfo->close(priv->mii_info); + + kfree(priv->mii_info); + netif_stop_queue(dev); return 0; @@ -971,121 +973,6 @@ int gfar_set_mac_address(struct net_device *dev) return 0; } -/********************************************************************** - * gfar_accept_fastpath - * - * Used to authenticate to the kernel that a fast path entry can be - * added to device's routing table cache - * - * Input : pointer to ethernet interface network device structure and - * a pointer to the designated entry to be added to the cache. - * Output : zero upon success, negative upon failure - **********************************************************************/ -#ifdef CONFIG_NET_FASTROUTE -static int gfar_accept_fastpath(struct net_device *dev, struct dst_entry *dst) -{ - struct net_device *odev = dst->dev; - - if ((dst->ops->protocol != __constant_htons(ETH_P_IP)) - || (odev->type != ARPHRD_ETHER) - || (odev->accept_fastpath == NULL)) { - return -1; - } - - return 0; -} -#endif - -/* try_fastroute() -- Checks the fastroute cache to see if a given packet - * can be routed immediately to another device. If it can, we send it. - * If we used a fastroute, we return 1. Otherwise, we return 0. - * Returns 0 if CONFIG_NET_FASTROUTE is not on - */ -static inline int try_fastroute(struct sk_buff *skb, struct net_device *dev, int length) -{ -#ifdef CONFIG_NET_FASTROUTE - struct ethhdr *eth; - struct iphdr *iph; - unsigned int hash; - struct rtable *rt; - struct net_device *odev; - struct gfar_private *priv = netdev_priv(dev); - unsigned int CPU_ID = smp_processor_id(); - - eth = (struct ethhdr *) (skb->data); - - /* Only route ethernet IP packets */ - if (eth->h_proto == __constant_htons(ETH_P_IP)) { - iph = (struct iphdr *) (skb->data + ETH_HLEN); - - /* Generate the hash value */ - hash = ((*(u8 *) &iph->daddr) ^ (*(u8 *) & iph->saddr)) & NETDEV_FASTROUTE_HMASK; - - rt = (struct rtable *) (dev->fastpath[hash]); - if (rt != NULL - && ((*(u32 *) &iph->daddr) == (*(u32 *) &rt->key.dst)) - && ((*(u32 *) &iph->saddr) == (*(u32 *) &rt->key.src)) - && !(rt->u.dst.obsolete)) { - odev = rt->u.dst.dev; - netdev_rx_stat[CPU_ID].fastroute_hit++; - - /* Make sure the packet is: - * 1) IPv4 - * 2) without any options (header length of 5) - * 3) Not a multicast packet - * 4) going to a valid destination - * 5) Not out of time-to-live - */ - if (iph->version == 4 - && iph->ihl == 5 - && (!(eth->h_dest[0] & 0x01)) - && neigh_is_valid(rt->u.dst.neighbour) - && iph->ttl > 1) { - - /* Fast Route Path: Taken if the outgoing device is ready to transmit the packet now */ - if ((!netif_queue_stopped(odev)) - && (!spin_is_locked(odev->xmit_lock)) - && (skb->len <= (odev->mtu + ETH_HLEN + 2 + 4))) { - - skb->pkt_type = PACKET_FASTROUTE; - skb->protocol = __constant_htons(ETH_P_IP); - ip_decrease_ttl(iph); - memcpy(eth->h_source, odev->dev_addr, MAC_ADDR_LEN); - memcpy(eth->h_dest, rt->u.dst.neighbour->ha, MAC_ADDR_LEN); - skb->dev = odev; - - /* Prep the skb for the packet */ - skb_put(skb, length); - - if (odev->hard_start_xmit(skb, odev) != 0) { - panic("%s: FastRoute path corrupted", dev->name); - } - netdev_rx_stat[CPU_ID].fastroute_success++; - } - - /* Semi Fast Route Path: Mark the packet as needing fast routing, but let the - * stack handle getting it to the device */ - else { - skb->pkt_type = PACKET_FASTROUTE; - skb->nh.raw = skb->data + ETH_HLEN; - skb->protocol = __constant_htons(ETH_P_IP); - netdev_rx_stat[CPU_ID].fastroute_defer++; - - /* Prep the skb for the packet */ - skb_put(skb, length); - - if(RECEIVE(skb) == NET_RX_DROP) { - priv->extra_stats.kernel_dropped++; - } - } - - return 1; - } - } - } -#endif /* CONFIG_NET_FASTROUTE */ - return 0; -} static int gfar_change_mtu(struct net_device *dev, int new_mtu) { @@ -1148,8 +1035,7 @@ static void gfar_timeout(struct net_device *dev) startup_gfar(dev); } - if (!netif_queue_stopped(dev)) - netif_schedule(dev); + netif_schedule(dev); } /* Interrupt Handler for Transmit complete */ @@ -1315,7 +1201,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) #else spin_lock(&priv->lock); - gfar_clean_rx_ring(dev); + gfar_clean_rx_ring(dev, priv->rx_ring_size); /* If we are coalescing interrupts, update the timer */ /* Otherwise, clear it */ @@ -1336,7 +1222,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) /* gfar_process_frame() -- handle one incoming packet if skb - * isn't NULL. Try the fastroute before using the stack */ + * isn't NULL. */ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length) { @@ -1350,17 +1236,15 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, priv->stats.rx_dropped++; priv->extra_stats.rx_skbmissing++; } else { - if(try_fastroute(skb, dev, length) == 0) { - /* Prep the skb for the packet */ - skb_put(skb, length); + /* Prep the skb for the packet */ + skb_put(skb, length); - /* Tell the skb what kind of packet this is */ - skb->protocol = eth_type_trans(skb, dev); + /* Tell the skb what kind of packet this is */ + skb->protocol = eth_type_trans(skb, dev); - /* Send the packet up the stack */ - if (RECEIVE(skb) == NET_RX_DROP) { - priv->extra_stats.kernel_dropped++; - } + /* Send the packet up the stack */ + if (RECEIVE(skb) == NET_RX_DROP) { + priv->extra_stats.kernel_dropped++; } } @@ -1368,14 +1252,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, } /* gfar_clean_rx_ring() -- Processes each frame in the rx ring - * until all are gone (or, in the case of NAPI, the budget/quota - * has been reached). Returns the number of frames handled + * until the budget/quota has been reached. Returns the number + * of frames handled */ -#ifdef CONFIG_GFAR_NAPI static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) -#else -static int gfar_clean_rx_ring(struct net_device *dev) -#endif { struct rxbd8 *bdp; struct sk_buff *skb; @@ -1386,12 +1266,7 @@ static int gfar_clean_rx_ring(struct net_device *dev) /* Get the first full descriptor */ bdp = priv->cur_rx; -#ifdef CONFIG_GFAR_NAPI -#define GFAR_RXDONE() ((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0)) -#else -#define GFAR_RXDONE() (bdp->status & RXBD_EMPTY) -#endif - while (!GFAR_RXDONE()) { + while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) { skb = priv->rx_skbuff[priv->skb_currx]; if (!(bdp->status & @@ -1407,7 +1282,6 @@ static int gfar_clean_rx_ring(struct net_device *dev) gfar_process_frame(dev, skb, pkt_len); priv->stats.rx_bytes += pkt_len; - } else { count_errors(bdp->status, priv); @@ -1462,7 +1336,6 @@ static int gfar_poll(struct net_device *dev, int *budget) if (rx_work_limit > dev->quota) rx_work_limit = dev->quota; - spin_lock(&priv->lock); howmany = gfar_clean_rx_ring(dev, rx_work_limit); dev->quota -= howmany; @@ -1489,8 +1362,6 @@ static int gfar_poll(struct net_device *dev, int *budget) priv->rxclean = 1; } - spin_unlock(priv->lock); - return (rx_work_limit < 0) ? 1 : 0; } #endif @@ -1586,10 +1457,14 @@ static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct net_device *dev = (struct net_device *) dev_id; struct gfar_private *priv = netdev_priv(dev); - /* Run the commands which acknowledge the interrupt */ - phy_run_commands(dev, priv->phyinfo->ack_int); + /* Clear the interrupt */ + mii_clear_phy_interrupt(priv->mii_info); + + /* Disable PHY interrupts */ + mii_configure_phy_interrupt(priv->mii_info, + MII_INTERRUPT_DISABLED); - /* Schedule the bottom half */ + /* Schedule the phy change */ schedule_work(&priv->tq); return IRQ_HANDLED; @@ -1600,18 +1475,24 @@ static void gfar_phy_change(void *data) { struct net_device *dev = (struct net_device *) data; struct gfar_private *priv = netdev_priv(dev); - int timeout = HZ / 1000 + 1; + int result = 0; /* Delay to give the PHY a chance to change the * register state */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); + msleep(1); - /* Run the commands which check the link state */ - phy_run_commands(dev, priv->phyinfo->handle_int); + /* Update the link, speed, duplex */ + result = priv->mii_info->phyinfo->read_status(priv->mii_info); - /* React to the change in state */ - adjust_link(dev); + /* Adjust the known status as long as the link + * isn't still coming up */ + if((0 == result) || (priv->mii_info->link == 0)) + adjust_link(dev); + + /* Reenable interrupts, if needed */ + if (priv->einfo->flags & GFAR_HAS_PHY_INTR) + mii_configure_phy_interrupt(priv->mii_info, + MII_INTERRUPT_ENABLED); } /* Called every so often on systems that don't interrupt @@ -1623,7 +1504,72 @@ static void gfar_phy_timer(unsigned long data) schedule_work(&priv->tq); - mod_timer(&priv->phy_info_timer, jiffies + 2 * HZ); + mod_timer(&priv->phy_info_timer, jiffies + + GFAR_PHY_CHANGE_TIME * HZ); +} + +/* Keep trying aneg for some time + * If, after GFAR_AN_TIMEOUT seconds, it has not + * finished, we switch to forced. + * Either way, once the process has completed, we either + * request the interrupt, or switch the timer over to + * using gfar_phy_timer to check status */ +static void gfar_phy_startup_timer(unsigned long data) +{ + int result; + static int secondary = GFAR_AN_TIMEOUT; + struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data; + struct gfar_private *priv = netdev_priv(mii_info->dev); + + /* Configure the Auto-negotiation */ + result = mii_info->phyinfo->config_aneg(mii_info); + + /* If autonegotiation failed to start, and + * we haven't timed out, reset the timer, and return */ + if (result && secondary--) { + mod_timer(&priv->phy_info_timer, jiffies + HZ); + return; + } else if (result) { + /* Couldn't start autonegotiation. + * Try switching to forced */ + mii_info->autoneg = 0; + result = mii_info->phyinfo->config_aneg(mii_info); + + /* Forcing failed! Give up */ + if(result) { + printk(KERN_ERR "%s: Forcing failed!\n", + mii_info->dev->name); + return; + } + } + + /* Kill the timer so it can be restarted */ + del_timer_sync(&priv->phy_info_timer); + + /* Grab the PHY interrupt, if necessary/possible */ + if (priv->einfo->flags & GFAR_HAS_PHY_INTR) { + if (request_irq(priv->einfo->interruptPHY, + phy_interrupt, + SA_SHIRQ, + "phy_interrupt", + mii_info->dev) < 0) { + printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n", + mii_info->dev->name, + priv->einfo->interruptPHY); + } else { + mii_configure_phy_interrupt(priv->mii_info, + MII_INTERRUPT_ENABLED); + return; + } + } + + /* Start the timer again, this time in order to + * handle a change in status */ + init_timer(&priv->phy_info_timer); + priv->phy_info_timer.function = &gfar_phy_timer; + priv->phy_info_timer.data = (unsigned long) mii_info->dev; + mod_timer(&priv->phy_info_timer, jiffies + + GFAR_PHY_CHANGE_TIME * HZ); } /* Called every time the controller might need to be made @@ -1637,12 +1583,13 @@ static void adjust_link(struct net_device *dev) struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->regs; u32 tempval; + struct gfar_mii_info *mii_info = priv->mii_info; - if (priv->link) { + if (mii_info->link) { /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ - if (priv->duplexity != priv->olddplx) { - if (!(priv->duplexity)) { + if (mii_info->duplex != priv->oldduplex) { + if (!(mii_info->duplex)) { tempval = gfar_read(®s->maccfg2); tempval &= ~(MACCFG2_FULL_DUPLEX); gfar_write(®s->maccfg2, tempval); @@ -1658,11 +1605,11 @@ static void adjust_link(struct net_device *dev) dev->name); } - priv->olddplx = priv->duplexity; + priv->oldduplex = mii_info->duplex; } - if (priv->speed != priv->oldspeed) { - switch (priv->speed) { + if (mii_info->speed != priv->oldspeed) { + switch (mii_info->speed) { case 1000: tempval = gfar_read(®s->maccfg2); tempval = @@ -1679,14 +1626,14 @@ static void adjust_link(struct net_device *dev) default: printk(KERN_WARNING "%s: Ack! Speed (%d) is not 10/100/1000!\n", - dev->name, priv->speed); + dev->name, mii_info->speed); break; } printk(KERN_INFO "%s: Speed %dBT\n", dev->name, - priv->speed); + mii_info->speed); - priv->oldspeed = priv->speed; + priv->oldspeed = mii_info->speed; } if (!priv->oldlink) { @@ -1700,15 +1647,10 @@ static void adjust_link(struct net_device *dev) printk(KERN_INFO "%s: Link is down\n", dev->name); priv->oldlink = 0; priv->oldspeed = 0; - priv->olddplx = -1; + priv->oldduplex = -1; netif_carrier_off(dev); } } - -#ifdef VERBOSE_GFAR_ERRORS - printk(KERN_INFO "%s: Link now %s; %dBT %s-duplex\n", - dev->name, priv->link ? "up" : "down", priv->speed, priv->duplexity ? "full" : "half"); -#endif } @@ -1905,11 +1847,7 @@ static int __init gfar_init(void) int rc; rc = ocp_register_driver(&gfar_driver); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) if (rc != 0) { -#else - if (rc == 0) { -#endif ocp_unregister_driver(&gfar_driver); return -ENODEV; } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index f7af3465c..91eaab35d 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -8,7 +8,7 @@ * Author: Andy Fleming * Maintainer: Kumar Gala (kumar.gala@freescale.com) * - * Copyright 2004 Freescale Semiconductor, Inc + * Copyright (c) 2002-2004 Freescale Semiconductor, 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 @@ -17,6 +17,8 @@ * * Still left to do: * -Add support for module parameters + * -Add support for ethtool -s + * -Add patch for ethtool phys id */ #ifndef __GIANFAR_H #define __GIANFAR_H @@ -42,15 +44,7 @@ #include #include #include - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) #include -#else -#include -#define work_struct tq_struct -#define schedule_work schedule_task -#endif - #include #include #include @@ -70,8 +64,13 @@ #define MAC_ADDR_LEN 6 -extern char gfar_driver_name[]; -extern char gfar_driver_version[]; +#define PHY_INIT_TIMEOUT 100000 +#define GFAR_PHY_CHANGE_TIME 2 + +#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, " +#define DRV_NAME "gfar-enet" +extern const char gfar_driver_name[]; +extern const char gfar_driver_version[]; /* These need to be powers of 2 for this driver */ #ifdef CONFIG_GFAR_NAPI @@ -105,11 +104,13 @@ extern char gfar_driver_version[]; #define GFAR_100_TIME 2560 #define GFAR_10_TIME 25600 +#define DEFAULT_TX_COALESCE 1 #define DEFAULT_TXCOUNT 16 -#define DEFAULT_TXTIME 32768 +#define DEFAULT_TXTIME 400 +#define DEFAULT_RX_COALESCE 1 #define DEFAULT_RXCOUNT 16 -#define DEFAULT_RXTIME 32768 +#define DEFAULT_RXTIME 400 #define TBIPA_VALUE 0x1f #define MIIMCFG_INIT_VALUE 0x00000007 @@ -467,8 +468,7 @@ struct gfar { * empty and completely full conditions. The empty/ready indicator in * the buffer descriptor determines the actual condition. */ -struct gfar_private -{ +struct gfar_private { /* pointers to arrays of skbuffs for tx and rx */ struct sk_buff ** tx_skbuff; struct sk_buff ** rx_skbuff; @@ -496,7 +496,6 @@ struct gfar_private struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ struct gfar *regs; /* Pointer to the GFAR memory mapped Registers */ - struct phy_info *phyinfo; struct gfar *phyregs; struct work_struct tq; struct timer_list phy_info_timer; @@ -509,15 +508,14 @@ struct gfar_private unsigned int rx_ring_size; wait_queue_head_t rxcleanupq; unsigned int rxclean; - int link; /* current link state */ - int oldlink; - int duplexity; /* Indicates negotiated duplex state */ - int olddplx; - int speed; /* Indicates negotiated speed */ - int oldspeed; - + /* Info structure initialized by board setup code */ struct ocp_gfar_data *einfo; + + struct gfar_mii_info *mii_info; + int oldspeed; + int oldduplex; + int oldlink; }; extern inline u32 gfar_read(volatile unsigned *addr) @@ -532,6 +530,6 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val) out_be32(addr, val); } - +extern struct ethtool_ops *gfar_op_array[]; #endif /* __GIANFAR_H */ diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 4ccb5afd6..14ab0b217 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -1,18 +1,18 @@ /* - * drivers/net/gianfar_ethtool.c + * drivers/net/gianfar_ethtool.c * - * Gianfar Ethernet Driver - * Ethtool support for Gianfar Enet - * Based on e1000 ethtool support + * Gianfar Ethernet Driver + * Ethtool support for Gianfar Enet + * Based on e1000 ethtool support * - * Author: Andy Fleming - * Maintainer: Kumar Gala (kumar.gala@freescale.com) + * Author: Andy Fleming + * Maintainer: Kumar Gala (kumar.gala@freescale.com) * - * Copyright 2004 Freescale Semiconductor, Inc + * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. * - * This software may be used and distributed according to - * the terms of the GNU Public License, Version 2, incorporated herein - * by reference. + * This software may be used and distributed according to + * the terms of the GNU Public License, Version 2, incorporated herein + * by reference. */ #include @@ -58,64 +58,64 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); static char stat_gstrings[][ETH_GSTRING_LEN] = { - "RX Dropped by Kernel", - "RX Large Frame Errors", - "RX Short Frame Errors", - "RX Non-Octet Errors", - "RX CRC Errors", - "RX Overrun Errors", - "RX Busy Errors", - "RX Babbling Errors", - "RX Truncated Frames", - "Ethernet Bus Error", - "TX Babbling Errors", - "TX Underrun Errors", - "RX SKB Missing Errors", - "TX Timeout Errors", - "tx&rx 64B frames", - "tx&rx 65-127B frames", - "tx&rx 128-255B frames", - "tx&rx 256-511B frames", - "tx&rx 512-1023B frames", - "tx&rx 1024-1518B frames", - "tx&rx 1519-1522B Good VLAN", - "RX bytes", - "RX Packets", - "RX FCS Errors", - "Receive Multicast Packet", - "Receive Broadcast Packet", - "RX Control Frame Packets", - "RX Pause Frame Packets", - "RX Unknown OP Code", - "RX Alignment Error", - "RX Frame Length Error", - "RX Code Error", - "RX Carrier Sense Error", - "RX Undersize Packets", - "RX Oversize Packets", - "RX Fragmented Frames", - "RX Jabber Frames", - "RX Dropped Frames", - "TX Byte Counter", - "TX Packets", - "TX Multicast Packets", - "TX Broadcast Packets", - "TX Pause Control Frames", - "TX Deferral Packets", - "TX Excessive Deferral Packets", - "TX Single Collision Packets", - "TX Multiple Collision Packets", - "TX Late Collision Packets", - "TX Excessive Collision Packets", - "TX Total Collision", - "RESERVED", - "TX Dropped Frames", - "TX Jabber Frames", - "TX FCS Errors", - "TX Control Frames", - "TX Oversize Frames", - "TX Undersize Frames", - "TX Fragmented Frames", + "rx-dropped-by-kernel", + "rx-large-frame-errors", + "rx-short-frame-errors", + "rx-non-octet-errors", + "rx-crc-errors", + "rx-overrun-errors", + "rx-busy-errors", + "rx-babbling-errors", + "rx-truncated-frames", + "ethernet-bus-error", + "tx-babbling-errors", + "tx-underrun-errors", + "rx-skb-missing-errors", + "tx-timeout-errors", + "tx-rx-64-frames", + "tx-rx-65-127-frames", + "tx-rx-128-255-frames", + "tx-rx-256-511-frames", + "tx-rx-512-1023-frames", + "tx-rx-1024-1518-frames", + "tx-rx-1519-1522-good-vlan", + "rx-bytes", + "rx-packets", + "rx-fcs-errors", + "receive-multicast-packet", + "receive-broadcast-packet", + "rx-control-frame-packets", + "rx-pause-frame-packets", + "rx-unknown-op-code", + "rx-alignment-error", + "rx-frame-length-error", + "rx-code-error", + "rx-carrier-sense-error", + "rx-undersize-packets", + "rx-oversize-packets", + "rx-fragmented-frames", + "rx-jabber-frames", + "rx-dropped-frames", + "tx-byte-counter", + "tx-packets", + "tx-multicast-packets", + "tx-broadcast-packets", + "tx-pause-control-frames", + "tx-deferral-packets", + "tx-excessive-deferral-packets", + "tx-single-collision-packets", + "tx-multiple-collision-packets", + "tx-late-collision-packets", + "tx-excessive-collision-packets", + "tx-total-collision", + "reserved", + "tx-dropped-frames", + "tx-jabber-frames", + "tx-fcs-errors", + "tx-control-frames", + "tx-oversize-frames", + "tx-undersize-frames", + "tx-fragmented-frames", }; /* Fill in an array of 64-bit statistics from various sources. @@ -125,7 +125,7 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) { int i; - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); u32 *rmon = (u32 *) & priv->regs->rmon; u64 *extra = (u64 *) & priv->extra_stats; struct gfar_stats *stats = (struct gfar_stats *) buf; @@ -154,7 +154,7 @@ void gfar_fill_stats_normon(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) { int i; - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); u64 *extra = (u64 *) & priv->extra_stats; for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) { @@ -171,7 +171,7 @@ int gfar_stats_count_normon(struct net_device *dev) void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { - strncpy(drvinfo->driver, gfar_driver_name, GFAR_INFOSTR_LEN); + strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); strncpy(drvinfo->version, gfar_driver_version, GFAR_INFOSTR_LEN); strncpy(drvinfo->fw_version, "N/A", GFAR_INFOSTR_LEN); strncpy(drvinfo->bus_info, "N/A", GFAR_INFOSTR_LEN); @@ -184,7 +184,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct /* Return the current settings in the ethtool_cmd structure */ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); uint gigabit_support = priv->einfo->flags & GFAR_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0; uint gigabit_advert = @@ -201,10 +201,10 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) | ADVERTISED_100baseT_Full | gigabit_advert | ADVERTISED_Autoneg); - cmd->speed = priv->speed; - cmd->duplex = priv->duplexity; + cmd->speed = priv->mii_info->speed; + cmd->duplex = priv->mii_info->duplex; cmd->port = PORT_MII; - cmd->phy_address = priv->einfo->phyid; + cmd->phy_address = priv->mii_info->mii_id; cmd->transceiver = XCVR_EXTERNAL; cmd->autoneg = AUTONEG_ENABLE; cmd->maxtxpkt = priv->txcount; @@ -223,7 +223,7 @@ int gfar_reglen(struct net_device *dev) void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { int i; - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); u32 *theregs = (u32 *) priv->regs; u32 *buf = (u32 *) regbuf; @@ -231,13 +231,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb buf[i] = theregs[i]; } -/* Return the link state 1 is up, 0 is down */ -u32 gfar_get_link(struct net_device *dev) -{ - struct gfar_private *priv = (struct gfar_private *) dev->priv; - return (u32) priv->link; -} - /* Fill in a buffer with the strings which correspond to the * stats */ void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) @@ -252,7 +245,7 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use unsigned int count; /* The timer is different, depending on the interface speed */ - switch (priv->speed) { + switch (priv->mii_info->speed) { case 1000: count = GFAR_GBIT_TIME; break; @@ -276,7 +269,7 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic unsigned int count; /* The timer is different, depending on the interface speed */ - switch (priv->speed) { + switch (priv->mii_info->speed) { case 1000: count = GFAR_GBIT_TIME; break; @@ -298,7 +291,7 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic * structure. */ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); cvals->rx_max_coalesced_frames = priv->rxcount; @@ -344,7 +337,7 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) */ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); /* Set up rx coalescing */ if ((cvals->rx_coalesce_usecs == 0) || @@ -386,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) * jumbo are ignored by the driver */ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; @@ -409,7 +402,7 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) { u32 tempval; - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); int err = 0; if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) @@ -473,7 +466,7 @@ struct ethtool_ops gfar_ethtool_ops = { .get_drvinfo = gfar_gdrvinfo, .get_regs_len = gfar_reglen, .get_regs = gfar_get_regs, - .get_link = gfar_get_link, + .get_link = ethtool_op_get_link, .get_coalesce = gfar_gcoalesce, .set_coalesce = gfar_scoalesce, .get_ringparam = gfar_gringparam, @@ -482,3 +475,51 @@ struct ethtool_ops gfar_ethtool_ops = { .get_stats_count = gfar_stats_count, .get_ethtool_stats = gfar_fill_stats, }; + +struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings_normon, + .get_stats_count = gfar_stats_count_normon, + .get_ethtool_stats = gfar_fill_stats_normon, +}; + +struct ethtool_ops gfar_nocoalesce_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings, + .get_stats_count = gfar_stats_count, + .get_ethtool_stats = gfar_fill_stats, +}; + +struct ethtool_ops gfar_normon_ethtool_ops = { + .get_settings = gfar_gsettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, + .get_link = ethtool_op_get_link, + .get_coalesce = gfar_gcoalesce, + .set_coalesce = gfar_scoalesce, + .get_ringparam = gfar_gringparam, + .set_ringparam = gfar_sringparam, + .get_strings = gfar_gstrings_normon, + .get_stats_count = gfar_stats_count_normon, + .get_ethtool_stats = gfar_fill_stats_normon, +}; + +struct ethtool_ops *gfar_op_array[] = { + &gfar_ethtool_ops, + &gfar_normon_ethtool_ops, + &gfar_nocoalesce_ethtool_ops, + &gfar_normon_nocoalesce_ethtool_ops +}; diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c index ea02e5da9..02b16abc8 100644 --- a/drivers/net/gianfar_phy.c +++ b/drivers/net/gianfar_phy.c @@ -8,7 +8,7 @@ * Author: Andy Fleming * Maintainer: Kumar Gala (kumar.gala@freescale.com) * - * Copyright 2004 Freescale Semiconductor, Inc + * Copyright (c) 2002-2004 Freescale Semiconductor, 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 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -39,21 +38,31 @@ #include #include #include +#include #include "gianfar.h" #include "gianfar_phy.h" +static void config_genmii_advert(struct gfar_mii_info *mii_info); +static void genmii_setup_forced(struct gfar_mii_info *mii_info); +static void genmii_restart_aneg(struct gfar_mii_info *mii_info); +static int gbit_config_aneg(struct gfar_mii_info *mii_info); +static int genmii_config_aneg(struct gfar_mii_info *mii_info); +static int genmii_update_link(struct gfar_mii_info *mii_info); +static int genmii_read_status(struct gfar_mii_info *mii_info); +u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum); +void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val); + /* Write value to the PHY for this device to the register at regnum, */ /* waiting until the write is done before it returns. All PHY */ /* configuration has to be done through the TSEC1 MIIM regs */ -void write_phy_reg(struct net_device *dev, u16 regnum, u16 value) +void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); struct gfar *regbase = priv->phyregs; - struct ocp_gfar_data *einfo = priv->einfo; /* Set the PHY address and the register address we want to write */ - gfar_write(®base->miimadd, ((einfo->phyid) << 8) | regnum); + gfar_write(®base->miimadd, (mii_id << 8) | regnum); /* Write out the value we want */ gfar_write(®base->miimcon, value); @@ -66,19 +75,18 @@ void write_phy_reg(struct net_device *dev, u16 regnum, u16 value) /* Reads from register regnum in the PHY for device dev, */ /* returning the value. Clears miimcom first. All PHY */ /* configuration has to be done through the TSEC1 MIIM regs */ -u16 read_phy_reg(struct net_device *dev, u16 regnum) +int read_phy_reg(struct net_device *dev, int mii_id, int regnum) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_private *priv = netdev_priv(dev); struct gfar *regbase = priv->phyregs; - struct ocp_gfar_data *einfo = priv->einfo; u16 value; /* Set the PHY address and the register address we want to read */ - gfar_write(®base->miimadd, ((einfo->phyid) << 8) | regnum); + gfar_write(®base->miimadd, (mii_id << 8) | regnum); /* Clear miimcom, and then initiate a read */ gfar_write(®base->miimcom, 0); - gfar_write(®base->miimcom, MIIM_READ_COMMAND); + gfar_write(®base->miimcom, MII_READ_COMMAND); /* Wait for the transaction to finish */ while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) @@ -90,444 +98,557 @@ u16 read_phy_reg(struct net_device *dev, u16 regnum) return value; } -/* returns which value to write to the control register. */ -/* For 10/100 the value is slightly different. */ -u16 mii_cr_init(u16 mii_reg, struct net_device * dev) +void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; - struct ocp_gfar_data *einfo = priv->einfo; + if(mii_info->phyinfo->ack_interrupt) + mii_info->phyinfo->ack_interrupt(mii_info); +} - if (einfo->flags & GFAR_HAS_GIGABIT) - return MIIM_CONTROL_INIT; - else - return MIIM_CR_INIT; + +void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts) +{ + mii_info->interrupts = interrupts; + if(mii_info->phyinfo->config_intr) + mii_info->phyinfo->config_intr(mii_info); } -#define BRIEF_GFAR_ERRORS -/* Wait for auto-negotiation to complete */ -u16 mii_parse_sr(u16 mii_reg, struct net_device * dev) + +/* Writes MII_ADVERTISE with the appropriate values, after + * sanitizing advertise to make sure only supported features + * are advertised + */ +static void config_genmii_advert(struct gfar_mii_info *mii_info) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + u32 advertise; + u16 adv; + + /* Only allow advertising what this PHY supports */ + mii_info->advertising &= mii_info->phyinfo->features; + advertise = mii_info->advertising; + + /* Setup standard advertisement */ + adv = phy_read(mii_info, MII_ADVERTISE); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (advertise & ADVERTISED_10baseT_Half) + adv |= ADVERTISE_10HALF; + if (advertise & ADVERTISED_10baseT_Full) + adv |= ADVERTISE_10FULL; + if (advertise & ADVERTISED_100baseT_Half) + adv |= ADVERTISE_100HALF; + if (advertise & ADVERTISED_100baseT_Full) + adv |= ADVERTISE_100FULL; + phy_write(mii_info, MII_ADVERTISE, adv); +} - unsigned int timeout = GFAR_AN_TIMEOUT; +static void genmii_setup_forced(struct gfar_mii_info *mii_info) +{ + u16 ctrl; + u32 features = mii_info->phyinfo->features; + + ctrl = phy_read(mii_info, MII_BMCR); + + ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE); + ctrl |= BMCR_RESET; + + switch(mii_info->speed) { + case SPEED_1000: + if(features & (SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full)) { + ctrl |= BMCR_SPEED1000; + break; + } + mii_info->speed = SPEED_100; + case SPEED_100: + if (features & (SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full)) { + ctrl |= BMCR_SPEED100; + break; + } + mii_info->speed = SPEED_10; + case SPEED_10: + if (features & (SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full)) + break; + default: /* Unsupported speed! */ + printk(KERN_ERR "%s: Bad speed!\n", + mii_info->dev->name); + break; + } - if (mii_reg & MIIM_STATUS_LINK) - priv->link = 1; - else - priv->link = 0; + phy_write(mii_info, MII_BMCR, ctrl); +} - /* Only auto-negotiate if the link has just gone up */ - if (priv->link && !priv->oldlink) { - while ((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--) - mii_reg = read_phy_reg(dev, MIIM_STATUS); -#if defined(BRIEF_GFAR_ERRORS) - if (mii_reg & MIIM_STATUS_AN_DONE) - printk(KERN_INFO "%s: Auto-negotiation done\n", - dev->name); - else - printk(KERN_INFO "%s: Auto-negotiation timed out\n", - dev->name); -#endif - } +/* Enable and Restart Autonegotiation */ +static void genmii_restart_aneg(struct gfar_mii_info *mii_info) +{ + u16 ctl; + + ctl = phy_read(mii_info, MII_BMCR); + ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(mii_info, MII_BMCR, ctl); +} + + +static int gbit_config_aneg(struct gfar_mii_info *mii_info) +{ + u16 adv; + u32 advertise; + + if(mii_info->autoneg) { + /* Configure the ADVERTISE register */ + config_genmii_advert(mii_info); + advertise = mii_info->advertising; + + adv = phy_read(mii_info, MII_1000BASETCONTROL); + adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP | + MII_1000BASETCONTROL_HALFDUPLEXCAP); + if (advertise & SUPPORTED_1000baseT_Half) + adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; + if (advertise & SUPPORTED_1000baseT_Full) + adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; + phy_write(mii_info, MII_1000BASETCONTROL, adv); + + /* Start/Restart aneg */ + genmii_restart_aneg(mii_info); + } else + genmii_setup_forced(mii_info); return 0; } -/* Determine the speed and duplex which was negotiated */ -u16 mii_parse_88E1011_psr(u16 mii_reg, struct net_device * dev) +static int marvell_config_aneg(struct gfar_mii_info *mii_info) +{ + /* The Marvell PHY has an errata which requires + * that certain registers get written in order + * to restart autonegotiation */ + phy_write(mii_info, MII_BMCR, BMCR_RESET); + + phy_write(mii_info, 0x1d, 0x1f); + phy_write(mii_info, 0x1e, 0x200c); + phy_write(mii_info, 0x1d, 0x5); + phy_write(mii_info, 0x1e, 0); + phy_write(mii_info, 0x1e, 0x100); + + gbit_config_aneg(mii_info); + + return 0; +} +static int genmii_config_aneg(struct gfar_mii_info *mii_info) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; - unsigned int speed; + if (mii_info->autoneg) { + config_genmii_advert(mii_info); + genmii_restart_aneg(mii_info); + } else + genmii_setup_forced(mii_info); + + return 0; +} + + +static int genmii_update_link(struct gfar_mii_info *mii_info) +{ + u16 status; + + /* Do a fake read */ + phy_read(mii_info, MII_BMSR); + + /* Read link and autonegotiation status */ + status = phy_read(mii_info, MII_BMSR); + if ((status & BMSR_LSTATUS) == 0) + mii_info->link = 0; + else + mii_info->link = 1; - if (priv->link) { - if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) - priv->duplexity = 1; + /* If we are autonegotiating, and not done, + * return an error */ + if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE)) + return -EAGAIN; + + return 0; +} + +static int genmii_read_status(struct gfar_mii_info *mii_info) +{ + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + if (mii_info->autoneg) { + status = phy_read(mii_info, MII_LPA); + + if (status & (LPA_10FULL | LPA_100FULL)) + mii_info->duplex = DUPLEX_FULL; else - priv->duplexity = 0; + mii_info->duplex = DUPLEX_HALF; + if (status & (LPA_100FULL | LPA_100HALF)) + mii_info->speed = SPEED_100; + else + mii_info->speed = SPEED_10; + mii_info->pause = 0; + } + /* On non-aneg, we assume what we put in BMCR is the speed, + * though magic-aneg shouldn't prevent this case from occurring + */ - speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); + return 0; +} +static int marvell_read_status(struct gfar_mii_info *mii_info) +{ + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + int speed; + status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS); - switch (speed) { - case MIIM_88E1011_PHYSTAT_GBIT: - priv->speed = 1000; - break; - case MIIM_88E1011_PHYSTAT_100: - priv->speed = 100; - break; - default: - priv->speed = 10; - break; +#if 0 + /* If speed and duplex aren't resolved, + * return an error. Isn't this handled + * by checking aneg? + */ + if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0) + return -EAGAIN; +#endif + + /* Get the duplexity */ + if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + + /* Get the speed */ + speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK; + switch(speed) { + case MII_M1011_PHY_SPEC_STATUS_1000: + mii_info->speed = SPEED_1000; + break; + case MII_M1011_PHY_SPEC_STATUS_100: + mii_info->speed = SPEED_100; + break; + default: + mii_info->speed = SPEED_10; + break; } - } else { - priv->speed = 0; - priv->duplexity = 0; + mii_info->pause = 0; } return 0; } -u16 mii_parse_cis8201(u16 mii_reg, struct net_device * dev) -{ - struct gfar_private *priv = (struct gfar_private *) dev->priv; - unsigned int speed; - if (priv->link) { - if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX) - priv->duplexity = 1; +static int cis820x_read_status(struct gfar_mii_info *mii_info) +{ + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + int speed; + + status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT); + if (status & MII_CIS8201_AUXCONSTAT_DUPLEX) + mii_info->duplex = DUPLEX_FULL; else - priv->duplexity = 0; + mii_info->duplex = DUPLEX_HALF; - speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED; + speed = status & MII_CIS8201_AUXCONSTAT_SPEED; switch (speed) { - case MIIM_CIS8201_AUXCONSTAT_GBIT: - priv->speed = 1000; + case MII_CIS8201_AUXCONSTAT_GBIT: + mii_info->speed = SPEED_1000; break; - case MIIM_CIS8201_AUXCONSTAT_100: - priv->speed = 100; + case MII_CIS8201_AUXCONSTAT_100: + mii_info->speed = SPEED_100; break; default: - priv->speed = 10; + mii_info->speed = SPEED_10; break; } - } else { - priv->speed = 0; - priv->duplexity = 0; } return 0; } -u16 mii_parse_dm9161_scsr(u16 mii_reg, struct net_device * dev) +static int marvell_ack_interrupt(struct gfar_mii_info *mii_info) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + /* Clear the interrupts by reading the reg */ + phy_read(mii_info, MII_M1011_IEVENT); + + return 0; +} - if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) - priv->speed = 100; +static int marvell_config_intr(struct gfar_mii_info *mii_info) +{ + if(mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT); else - priv->speed = 10; + phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); + + return 0; +} + +static int cis820x_init(struct gfar_mii_info *mii_info) +{ + phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, + MII_CIS8201_AUXCONSTAT_INIT); + phy_write(mii_info, MII_CIS8201_EXT_CON1, + MII_CIS8201_EXTCON1_INIT); + + return 0; +} - if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) - priv->duplexity = 1; +static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info) +{ + phy_read(mii_info, MII_CIS8201_ISTAT); + + return 0; +} + +static int cis820x_config_intr(struct gfar_mii_info *mii_info) +{ + if(mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK); else - priv->duplexity = 0; + phy_write(mii_info, MII_CIS8201_IMASK, 0); return 0; } -u16 dm9161_wait(u16 mii_reg, struct net_device *dev) +#define DM9161_DELAY 10 + +static int dm9161_read_status(struct gfar_mii_info *mii_info) { - int timeout = HZ; - int secondary = 10; - u16 temp; + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + status = phy_read(mii_info, MII_DM9161_SCSR); + if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H)) + mii_info->speed = SPEED_100; + else + mii_info->speed = SPEED_10; + + if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F)) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + } - do { + return 0; +} - /* Davicom takes a bit to come up after a reset, - * so wait here for a bit */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); - temp = read_phy_reg(dev, MIIM_STATUS); +static int dm9161_config_aneg(struct gfar_mii_info *mii_info) +{ + struct dm9161_private *priv = mii_info->priv; - secondary--; - } while ((!(temp & MIIM_STATUS_AN_DONE)) && secondary); + if(0 == priv->resetdone) + return -EAGAIN; return 0; } -/* - * consult the BCM54xx auxilliary status register to find the link settings - */ -u16 mii_parse_bcm54xx_sr(u16 mii_reg, struct net_device * dev) +static void dm9161_timer(unsigned long data) { - struct gfar_private *priv = (struct gfar_private *) dev->priv; + struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data; + struct dm9161_private *priv = mii_info->priv; + u16 status = phy_read(mii_info, MII_BMSR); + + if (status & BMSR_ANEGCOMPLETE) { + priv->resetdone = 1; + } else + mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); +} + +static int dm9161_init(struct gfar_mii_info *mii_info) +{ + struct dm9161_private *priv; + + /* Allocate the private data structure */ + priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL); + + if (NULL == priv) + return -ENOMEM; - /* Link modes of the BCM5400 PHY */ - static const uint16_t link_table[8][3] = { - { 0, 0 }, /* No link */ - { 0, 10 }, /* 10BT Half Duplex */ - { 1, 10 }, /* 10BT Full Duplex */ - { 0, 100 }, /* 100BT Half Duplex */ - { 0, 100 }, /* 100BT Half Duplex */ - { 1, 100 }, /* 100BT Full Duplex*/ - { 1, 1000 }, /* 1000BT */ - { 1, 1000 }, /* 1000BT */ - }; + mii_info->priv = priv; - uint16_t link_mode; + /* Reset is not done yet */ + priv->resetdone = 0; - link_mode = mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK; - link_mode >>= MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT; + /* Isolate the PHY */ + phy_write(mii_info, MII_BMCR, BMCR_ISOLATE); - priv->duplexity = link_table[link_mode][0]; - priv->speed = link_table[link_mode][1]; + /* Do not bypass the scrambler/descrambler */ + phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT); + + /* Clear 10BTCSR to default */ + phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT); + + /* Reconnect the PHY, and enable Autonegotiation */ + phy_write(mii_info, MII_BMCR, BMCR_ANENABLE); + + /* Start a timer for DM9161_DELAY seconds to wait + * for the PHY to be ready */ + init_timer(&priv->timer); + priv->timer.function = &dm9161_timer; + priv->timer.data = (unsigned long) mii_info; + mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); return 0; } -static struct phy_info phy_info_M88E1011S = { - 0x01410c6, - "Marvell 88E1011S", - 4, - (const struct phy_cmd[]) { /* config */ - /* Reset and configure the PHY */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* startup */ - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - /* Read the status */ - {MIIM_88E1011_PHY_STATUS, miim_read, mii_parse_88E1011_psr}, - /* Clear the IEVENT register */ - {MIIM_88E1011_IEVENT, miim_read, NULL}, - /* Set up the mask */ - {MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_INIT, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* ack_int */ - /* Clear the interrupt */ - {MIIM_88E1011_IEVENT, miim_read, NULL}, - /* Disable interrupts */ - {MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_CLEAR, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* handle_int */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Check the status */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - {MIIM_88E1011_PHY_STATUS, miim_read, mii_parse_88E1011_psr}, - /* Enable Interrupts */ - {MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_INIT, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* shutdown */ - {MIIM_88E1011_IEVENT, miim_read, NULL}, - {MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_CLEAR, NULL}, - {miim_end,} - }, -}; +static void dm9161_close(struct gfar_mii_info *mii_info) +{ + struct dm9161_private *priv = mii_info->priv; + + del_timer_sync(&priv->timer); + kfree(priv); +} + +#if 0 +static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info) +{ + phy_read(mii_info, MII_DM9161_INTR); -/* Cicada 8204 */ -static struct phy_info phy_info_cis8204 = { - 0x3f11, + return 0; +} +#endif + +/* Cicada 820x */ +static struct phy_info phy_info_cis820x = { + 0x000fc440, "Cicada Cis8204", - 6, - (const struct phy_cmd[]) { /* config */ - /* Override PHY config settings */ - {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, - /* Set up the interface mode */ - {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* startup */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - /* Read the status */ - {MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201}, - /* Clear the status register */ - {MIIM_CIS8204_ISTAT, miim_read, NULL}, - /* Enable interrupts */ - {MIIM_CIS8204_IMASK, MIIM_CIS8204_IMASK_MASK, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* ack_int */ - /* Clear the status register */ - {MIIM_CIS8204_ISTAT, miim_read, NULL}, - /* Disable interrupts */ - {MIIM_CIS8204_IMASK, 0x0, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* handle_int */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - /* Read the status */ - {MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201}, - /* Enable interrupts */ - {MIIM_CIS8204_IMASK, MIIM_CIS8204_IMASK_MASK, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* shutdown */ - /* Clear the status register */ - {MIIM_CIS8204_ISTAT, miim_read, NULL}, - /* Disable interrupts */ - {MIIM_CIS8204_IMASK, 0x0, NULL}, - {miim_end,} - }, + 0x000fffc0, + .features = MII_GBIT_FEATURES, + .init = &cis820x_init, + .config_aneg = &gbit_config_aneg, + .read_status = &cis820x_read_status, + .ack_interrupt = &cis820x_ack_interrupt, + .config_intr = &cis820x_config_intr, }; -/* Cicada 8201 */ -static struct phy_info phy_info_cis8201 = { - 0xfc41, - "CIS8201", - 4, - (const struct phy_cmd[]) { /* config */ - /* Override PHY config settings */ - {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, - /* Set up the interface mode */ - {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* startup */ - /* Read the Status (2x to make sure link is right) */ - {MIIM_STATUS, miim_read, NULL}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - /* Read the status */ - {MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* ack_int */ - {miim_end,} - }, - (const struct phy_cmd[]) { /* handle_int */ - {miim_end,} - }, - (const struct phy_cmd[]) { /* shutdown */ - {miim_end,} - }, +static struct phy_info phy_info_dm9161 = { + .phy_id = 0x0181b880, + .name = "Davicom DM9161E", + .phy_id_mask = 0x0ffffff0, + .init = dm9161_init, + .config_aneg = dm9161_config_aneg, + .read_status = dm9161_read_status, + .close = dm9161_close, }; -static struct phy_info phy_info_dm9161 = { - 0x0181b88, - "Davicom DM9161E", - 4, - (const struct phy_cmd[]) { /* config */ - {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL}, - /* Do not bypass the scrambler/descrambler */ - {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL}, - /* Clear 10BTCSR to default */ - {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL}, - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CR_INIT, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* startup */ - /* Restart Auto Negotiation */ - {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL}, - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, dm9161_wait}, - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - /* Read the status */ - {MIIM_DM9161_SCSR, miim_read, mii_parse_dm9161_scsr}, - /* Clear any pending interrupts */ - {MIIM_DM9161_INTR, miim_read, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* ack_int */ - {MIIM_DM9161_INTR, miim_read, NULL}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* handle_int */ - {MIIM_STATUS, miim_read, NULL}, - {MIIM_STATUS, miim_read, mii_parse_sr}, - {MIIM_DM9161_SCSR, miim_read, mii_parse_dm9161_scsr}, - {miim_end,} - }, - (const struct phy_cmd[]) { /* shutdown */ - {MIIM_DM9161_INTR, miim_read, NULL}, - {miim_end,} - }, +static struct phy_info phy_info_marvell = { + .phy_id = 0x01410c00, + .phy_id_mask = 0xffffff00, + .name = "Marvell 88E1101", + .features = MII_GBIT_FEATURES, + .config_aneg = &marvell_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, }; -/* Broadcom BCM5421S PHY */ -static struct phy_info phy_info_bcm5421s = { - .id = 0x2060E1, - .name = "Broadcom BCM5421S", - .shift = 0, - .config = (const struct phy_cmd[]) { - /* Configure some basic stuff */ - {MIIM_CONTROL, MIIM_CR_INIT, NULL}, -#if 0 /* 5421 only */ - miim_write(MII_BCM5400_AUXCONTROL, 0x1007), - miim_set_bits(MII_BCM5400_AUXCONTROL, 0x0400), - miim_write(MII_BCM5400_AUXCONTROL, 0x0007), - miim_set_bits(MII_BCM5400_AUXCONTROL, 0x0800), - miim_write(0x17, 0x000a), - miim_set_bits(MII_RERRCOUNTER, 0x0200), -#endif -#if 0 /* enable automatic low power */ - miim_write(MII_NCONFIG, 0x9002), - miim_write(MII_NCONFIG, 0xa821), - miim_write(MII_NCONFIG, 0x941d), -#endif - {miim_end,} - }, - .startup = (const struct phy_cmd[]) { - /* Restart Auto Negotiation */ - miim_set_bits(MIIM_CONTROL, BMCR_ANENABLE | BMCR_ANRESTART), -#if 0 - /* Status is read once to clear old link state */ - {MIIM_STATUS, miim_read, dm9161_wait}, -#endif - /* Auto-negotiate */ - {MIIM_STATUS, miim_read, mii_parse_sr}, - - /* Read the link status */ - {MIIM_BCM54xx_AUXSTATUS, miim_read, mii_parse_bcm54xx_sr}, - - {miim_end,} - }, - .ack_int = (const struct phy_cmd[]) { - {miim_end,} - }, - .handle_int = (const struct phy_cmd[]) { - {MIIM_STATUS, miim_read, NULL}, - {MIIM_STATUS, miim_read, mii_parse_sr}, - {miim_end,} - }, - .shutdown = (const struct phy_cmd[]) { - {miim_end,} - }, +static struct phy_info phy_info_genmii= { + .phy_id = 0x00000000, + .phy_id_mask = 0x00000000, + .name = "Generic MII", + .features = MII_BASIC_FEATURES, + .config_aneg = genmii_config_aneg, + .read_status = genmii_read_status, }; static struct phy_info *phy_info[] = { - &phy_info_cis8201, - &phy_info_cis8204, - &phy_info_M88E1011S, + &phy_info_cis820x, + &phy_info_marvell, &phy_info_dm9161, - &phy_info_bcm5421s, + &phy_info_genmii, NULL }; +u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum) +{ + u16 retval; + unsigned long flags; + + spin_lock_irqsave(&mii_info->mdio_lock, flags); + retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum); + spin_unlock_irqrestore(&mii_info->mdio_lock, flags); + + return retval; +} + +void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val) +{ + unsigned long flags; + + spin_lock_irqsave(&mii_info->mdio_lock, flags); + mii_info->mdio_write(mii_info->dev, + mii_info->mii_id, + regnum, val); + spin_unlock_irqrestore(&mii_info->mdio_lock, flags); +} + /* Use the PHY ID registers to determine what type of PHY is attached * to device dev. return a struct phy_info structure describing that PHY */ -struct phy_info * get_phy_info(struct net_device *dev) +struct phy_info * get_phy_info(struct gfar_mii_info *mii_info) { u16 phy_reg; u32 phy_ID; int i; struct phy_info *theInfo = NULL; + struct net_device *dev = mii_info->dev; /* Grab the bits from PHYIR1, and put them in the upper half */ - phy_reg = read_phy_reg(dev, MIIM_PHYIR1); + phy_reg = phy_read(mii_info, MII_PHYSID1); phy_ID = (phy_reg & 0xffff) << 16; /* Grab the bits from PHYIR2, and put them in the lower half */ - phy_reg = read_phy_reg(dev, MIIM_PHYIR2); + phy_reg = phy_read(mii_info, MII_PHYSID2); phy_ID |= (phy_reg & 0xffff); /* loop through all the known PHY types, and find one that */ /* matches the ID we read from the PHY. */ for (i = 0; phy_info[i]; i++) - if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) + if (phy_info[i]->phy_id == + (phy_ID & phy_info[i]->phy_id_mask)) { theInfo = phy_info[i]; + break; + } + /* This shouldn't happen, as we have generic PHY support */ if (theInfo == NULL) { printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID); return NULL; @@ -538,85 +659,3 @@ struct phy_info * get_phy_info(struct net_device *dev) return theInfo; } - -/* Take a list of struct phy_cmd, and, depending on the values, either */ -/* read or write, using a helper function if provided */ -/* It is assumed that all lists of struct phy_cmd will be terminated by */ -/* mii_end. */ -void phy_run_commands(struct net_device *dev, const struct phy_cmd *cmd) -{ - int i; - u16 result; - struct gfar_private *priv = (struct gfar_private *) dev->priv; - struct gfar *phyregs = priv->phyregs; - - /* Reset the management interface */ - gfar_write(&phyregs->miimcfg, MIIMCFG_RESET); - - /* Setup the MII Mgmt clock speed */ - gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE); - - /* Wait until the bus is free */ - while (gfar_read(&phyregs->miimind) & MIIMIND_BUSY) - cpu_relax(); - - for (i = 0; cmd->mii_reg != miim_end; i++) { - switch (cmd->mii_data >> 16) { - case 0x0000: - /* Otherwise, it's a write */ - /* If a function was supplied, it will provide - * the value to write */ - /* Otherwise, the value was supplied in cmd->mii_data */ - if (cmd->funct != NULL) - result = (*(cmd->funct)) (0, dev); - else - result = cmd->mii_data; - - write_phy_reg(dev, cmd->mii_reg, result); - break; - - case 0x0001: - /* Read the value of the PHY reg */ - result = read_phy_reg(dev, cmd->mii_reg); - - /* If a function was supplied, we need to let it process */ - /* the result. */ - if (cmd->funct != NULL) - (*(cmd->funct)) (result, dev); - break; - - case 0x0002: - /* read the value, clear some bits and write it back */ - BUG_ON(cmd->funct); - - result = read_phy_reg(dev, cmd->mii_reg); - result &= cmd->mii_data; - write_phy_reg(dev, cmd->mii_reg, result); - break; - - case 0x0003: - /* read the value, set some bits and write it back */ - BUG_ON(cmd->funct); - - result = read_phy_reg(dev, cmd->mii_reg); - result &= cmd->mii_data; - write_phy_reg(dev, cmd->mii_reg, result); - break; - - case 0x0004: - /* read the value, flip some bits and write it back */ - BUG_ON(cmd->funct); - - result = read_phy_reg(dev, cmd->mii_reg); - result &= cmd->mii_data; - write_phy_reg(dev, cmd->mii_reg, result); - break; - - default: - printk("GIANFAR: Unknown MII command %08x\n", - cmd->mii_data); - BUG(); - } - cmd++; - } -} diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h index df4c0ec9d..1e9b3abf1 100644 --- a/drivers/net/gianfar_phy.h +++ b/drivers/net/gianfar_phy.h @@ -8,7 +8,7 @@ * Author: Andy Fleming * Maintainer: Kumar Gala (kumar.gala@freescale.com) * - * Copyright 2004 Freescale Semiconductor, Inc + * Copyright (c) 2002-2004 Freescale Semiconductor, 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 @@ -19,145 +19,144 @@ #ifndef __GIANFAR_PHY_H #define __GIANFAR_PHY_H -/* simple datum processing commands */ -#define miim_end (0xffff0000U) -#define miim_read (0x00010000U) -#define miim_clear_bits(reg,x) { reg, (0x00020000U | ~(u32)(x)), NULL } -#define miim_set_bits(reg,x) { reg, (0x00030000U | (u32)(x)), NULL } -#define miim_flip_bits(reg,x) { reg, (0x00040000U | (u32)(x)), NULL } -#define miim_write(reg, x) { reg, (0x0000ffffU & (u32)(x)), NULL } +#define MII_end ((u32)-2) +#define MII_read ((u32)-1) #define MIIMIND_BUSY 0x00000001 #define MIIMIND_NOTVALID 0x00000004 -#define MIIM_CONTROL 0x00 -#define MIIM_CONTROL_RESET 0x00008000 -#define MIIM_CONTROL_INIT 0x00001140 -#define MIIM_ANEN 0x00001000 - -#define MIIM_CR 0x00 -#define MIIM_CR_RST 0x00008000 -#define MIIM_CR_INIT 0x00001000 - -#define MIIM_STATUS 0x1 -#define MIIM_STATUS_AN_DONE 0x00000020 -#define MIIM_STATUS_LINK 0x0004 - -#define MIIM_PHYIR1 0x2 -#define MIIM_PHYIR2 0x3 - -#define GFAR_AN_TIMEOUT 0x000fffff - -#define MIIM_ANLPBPA 0x5 -#define MIIM_ANLPBPA_HALF 0x00000040 -#define MIIM_ANLPBPA_FULL 0x00000020 - -#define MIIM_ANEX 0x6 -#define MIIM_ANEX_NP 0x00000004 -#define MIIM_ANEX_PRX 0x00000002 +#define GFAR_AN_TIMEOUT 2000 +/* 1000BT control (Marvell & BCM54xx at least) */ +#define MII_1000BASETCONTROL 0x09 +#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 +#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100 /* Cicada Extended Control Register 1 */ -#define MIIM_CIS8201_EXT_CON1 0x17 -#define MIIM_CIS8201_EXTCON1_INIT 0x0000 +#define MII_CIS8201_EXT_CON1 0x17 +#define MII_CIS8201_EXTCON1_INIT 0x0000 /* Cicada Interrupt Mask Register */ -#define MIIM_CIS8204_IMASK 0x19 -#define MIIM_CIS8204_IMASK_IEN 0x8000 -#define MIIM_CIS8204_IMASK_SPEED 0x4000 -#define MIIM_CIS8204_IMASK_LINK 0x2000 -#define MIIM_CIS8204_IMASK_DUPLEX 0x1000 -#define MIIM_CIS8204_IMASK_MASK 0xf000 +#define MII_CIS8201_IMASK 0x19 +#define MII_CIS8201_IMASK_IEN 0x8000 +#define MII_CIS8201_IMASK_SPEED 0x4000 +#define MII_CIS8201_IMASK_LINK 0x2000 +#define MII_CIS8201_IMASK_DUPLEX 0x1000 +#define MII_CIS8201_IMASK_MASK 0xf000 /* Cicada Interrupt Status Register */ -#define MIIM_CIS8204_ISTAT 0x1a -#define MIIM_CIS8204_ISTAT_STATUS 0x8000 -#define MIIM_CIS8204_ISTAT_SPEED 0x4000 -#define MIIM_CIS8204_ISTAT_LINK 0x2000 -#define MIIM_CIS8204_ISTAT_DUPLEX 0x1000 +#define MII_CIS8201_ISTAT 0x1a +#define MII_CIS8201_ISTAT_STATUS 0x8000 +#define MII_CIS8201_ISTAT_SPEED 0x4000 +#define MII_CIS8201_ISTAT_LINK 0x2000 +#define MII_CIS8201_ISTAT_DUPLEX 0x1000 /* Cicada Auxiliary Control/Status Register */ -#define MIIM_CIS8201_AUX_CONSTAT 0x1c -#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004 -#define MIIM_CIS8201_AUXCONSTAT_DUPLEX 0x0020 -#define MIIM_CIS8201_AUXCONSTAT_SPEED 0x0018 -#define MIIM_CIS8201_AUXCONSTAT_GBIT 0x0010 -#define MIIM_CIS8201_AUXCONSTAT_100 0x0008 +#define MII_CIS8201_AUX_CONSTAT 0x1c +#define MII_CIS8201_AUXCONSTAT_INIT 0x0004 +#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020 +#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018 +#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010 +#define MII_CIS8201_AUXCONSTAT_100 0x0008 /* 88E1011 PHY Status Register */ -#define MIIM_88E1011_PHY_STATUS 0x11 -#define MIIM_88E1011_PHYSTAT_SPEED 0xc000 -#define MIIM_88E1011_PHYSTAT_GBIT 0x8000 -#define MIIM_88E1011_PHYSTAT_100 0x4000 -#define MIIM_88E1011_PHYSTAT_DUPLEX 0x2000 -#define MIIM_88E1011_PHYSTAT_LINK 0x0400 +#define MII_M1011_PHY_SPEC_STATUS 0x11 +#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000 +#define MII_M1011_PHY_SPEC_STATUS_100 0x4000 +#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000 +#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000 +#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800 +#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400 -#define MIIM_88E1011_IEVENT 0x13 -#define MIIM_88E1011_IEVENT_CLEAR 0x0000 +#define MII_M1011_IEVENT 0x13 +#define MII_M1011_IEVENT_CLEAR 0x0000 -#define MIIM_88E1011_IMASK 0x12 -#define MIIM_88E1011_IMASK_INIT 0x6400 -#define MIIM_88E1011_IMASK_CLEAR 0x0000 +#define MII_M1011_IMASK 0x12 +#define MII_M1011_IMASK_INIT 0x6400 +#define MII_M1011_IMASK_CLEAR 0x0000 -/* DM9161 Control register values */ -#define MIIM_DM9161_CR_STOP 0x0400 -#define MIIM_DM9161_CR_RSTAN 0x1200 - -#define MIIM_DM9161_SCR 0x10 -#define MIIM_DM9161_SCR_INIT 0x0610 +#define MII_DM9161_SCR 0x10 +#define MII_DM9161_SCR_INIT 0x0610 /* DM9161 Specified Configuration and Status Register */ -#define MIIM_DM9161_SCSR 0x11 -#define MIIM_DM9161_SCSR_100F 0x8000 -#define MIIM_DM9161_SCSR_100H 0x4000 -#define MIIM_DM9161_SCSR_10F 0x2000 -#define MIIM_DM9161_SCSR_10H 0x1000 +#define MII_DM9161_SCSR 0x11 +#define MII_DM9161_SCSR_100F 0x8000 +#define MII_DM9161_SCSR_100H 0x4000 +#define MII_DM9161_SCSR_10F 0x2000 +#define MII_DM9161_SCSR_10H 0x1000 /* DM9161 Interrupt Register */ -#define MIIM_DM9161_INTR 0x15 -#define MIIM_DM9161_INTR_PEND 0x8000 -#define MIIM_DM9161_INTR_DPLX_MASK 0x0800 -#define MIIM_DM9161_INTR_SPD_MASK 0x0400 -#define MIIM_DM9161_INTR_LINK_MASK 0x0200 -#define MIIM_DM9161_INTR_MASK 0x0100 -#define MIIM_DM9161_INTR_DPLX_CHANGE 0x0010 -#define MIIM_DM9161_INTR_SPD_CHANGE 0x0008 -#define MIIM_DM9161_INTR_LINK_CHANGE 0x0004 -#define MIIM_DM9161_INTR_INIT 0x0000 -#define MIIM_DM9161_INTR_STOP \ -(MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \ - | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK) +#define MII_DM9161_INTR 0x15 +#define MII_DM9161_INTR_PEND 0x8000 +#define MII_DM9161_INTR_DPLX_MASK 0x0800 +#define MII_DM9161_INTR_SPD_MASK 0x0400 +#define MII_DM9161_INTR_LINK_MASK 0x0200 +#define MII_DM9161_INTR_MASK 0x0100 +#define MII_DM9161_INTR_DPLX_CHANGE 0x0010 +#define MII_DM9161_INTR_SPD_CHANGE 0x0008 +#define MII_DM9161_INTR_LINK_CHANGE 0x0004 +#define MII_DM9161_INTR_INIT 0x0000 +#define MII_DM9161_INTR_STOP \ +(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \ + | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK) /* DM9161 10BT Configuration/Status */ -#define MIIM_DM9161_10BTCSR 0x12 -#define MIIM_DM9161_10BTCSR_INIT 0x7800 - -/* BCM54xx regs */ -#define MIIM_BCM54xx_AUXCONTROL 0x18 -#define MIIM_BCM54xx_AUXSTATUS 0x19 -#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700 -#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8 - -#define MIIM_READ_COMMAND 0x00000001 - -/* - * struct phy_cmd: A command for reading or writing a PHY register - * - * mii_reg: The register to read or write - * - * mii_data: For writes, the value to put in the register. - * A value of -1 indicates this is a read. - * - * funct: A function pointer which is invoked for each command. - * For reads, this function will be passed the value read - * from the PHY, and process it. - * For writes, the result of this function will be written - * to the PHY register - */ -struct phy_cmd { - u32 mii_reg; - u32 mii_data; - u16 (*funct) (u16 mii_reg, struct net_device * dev); +#define MII_DM9161_10BTCSR 0x12 +#define MII_DM9161_10BTCSR_INIT 0x7800 + +#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ + SUPPORTED_10baseT_Full | \ + SUPPORTED_100baseT_Half | \ + SUPPORTED_100baseT_Full | \ + SUPPORTED_Autoneg | \ + SUPPORTED_TP | \ + SUPPORTED_MII) + +#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \ + SUPPORTED_1000baseT_Half | \ + SUPPORTED_1000baseT_Full) + +#define MII_READ_COMMAND 0x00000001 + +#define MII_INTERRUPT_DISABLED 0x0 +#define MII_INTERRUPT_ENABLED 0x1 +/* Taken from mii_if_info and sungem_phy.h */ +struct gfar_mii_info { + /* Information about the PHY type */ + /* And management functions */ + struct phy_info *phyinfo; + + /* forced speed & duplex (no autoneg) + * partner speed & duplex & pause (autoneg) + */ + int speed; + int duplex; + int pause; + + /* The most recently read link state */ + int link; + + /* Enabled Interrupts */ + u32 interrupts; + + u32 advertising; + int autoneg; + int mii_id; + + /* private data pointer */ + /* For use by PHYs to maintain extra state */ + void *priv; + + /* Provided by host chip */ + struct net_device *dev; + + /* A lock to ensure that only one thing can read/write + * the MDIO bus at a time */ + spinlock_t mdio_lock; + + /* Provided by ethernet driver */ + int (*mdio_read) (struct net_device *dev, int mii_id, int reg); + void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val); }; /* struct phy_info: a structure which defines attributes for a PHY @@ -165,38 +164,50 @@ struct phy_cmd { * id will contain a number which represents the PHY. During * startup, the driver will poll the PHY to find out what its * UID--as defined by registers 2 and 3--is. The 32-bit result - * gotten from the PHY will be shifted right by "shift" bits to + * gotten from the PHY will be ANDed with phy_id_mask to * discard any bits which may change based on revision numbers * unimportant to functionality * - * The struct phy_cmd entries represent pointers to an arrays of - * commands which tell the driver what to do to the PHY. + * There are 6 commands which take a gfar_mii_info structure. + * Each PHY must declare config_aneg, and read_status. */ struct phy_info { - u32 id; - char *name; - unsigned int shift; - /* Called to configure the PHY, and modify the controller - * based on the results */ - const struct phy_cmd *config; - - /* Called when starting up the controller. Usually sets - * up the interrupt for state changes */ - const struct phy_cmd *startup; - - /* Called inside the interrupt handler to acknowledge - * the interrupt */ - const struct phy_cmd *ack_int; - - /* Called in the bottom half to handle the interrupt */ - const struct phy_cmd *handle_int; - - /* Called when bringing down the controller. Usually stops - * the interrupts from being generated */ - const struct phy_cmd *shutdown; + u32 phy_id; + char *name; + unsigned int phy_id_mask; + u32 features; + + /* Called to initialize the PHY */ + int (*init)(struct gfar_mii_info *mii_info); + + /* Called to suspend the PHY for power */ + int (*suspend)(struct gfar_mii_info *mii_info); + + /* Reconfigures autonegotiation (or disables it) */ + int (*config_aneg)(struct gfar_mii_info *mii_info); + + /* Determines the negotiated speed and duplex */ + int (*read_status)(struct gfar_mii_info *mii_info); + + /* Clears any pending interrupts */ + int (*ack_interrupt)(struct gfar_mii_info *mii_info); + + /* Enables or disables interrupts */ + int (*config_intr)(struct gfar_mii_info *mii_info); + + /* Clears up any memory if needed */ + void (*close)(struct gfar_mii_info *mii_info); }; -struct phy_info *get_phy_info(struct net_device *dev); -void phy_run_commands(struct net_device *dev, const struct phy_cmd *cmd); +struct phy_info *get_phy_info(struct gfar_mii_info *mii_info); +int read_phy_reg(struct net_device *dev, int mii_id, int regnum); +void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value); +void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info); +void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts); + +struct dm9161_private { + struct timer_list timer; + int resetdone; +}; #endif /* GIANFAR_PHY_H */ diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c index 0cbf1d143..b6f1e8be4 100644 --- a/drivers/net/gt96100eth.c +++ b/drivers/net/gt96100eth.c @@ -28,7 +28,6 @@ * gt96100_cleanup_module(), and other general code cleanups * . */ -#include #include #include #include @@ -45,9 +44,9 @@ #include #include #include +#include #include -#include #include #define DESC_BE 1 @@ -66,10 +65,6 @@ static int gt96100_add_hash_entry(struct net_device *dev, static void read_mib_counters(struct gt96100_private *gp); static int read_MII(int phy_addr, u32 reg); static int write_MII(int phy_addr, u32 reg, u16 data); -#if 0 -static void dump_tx_ring(struct net_device *dev); -static void dump_rx_ring(struct net_device *dev); -#endif static int gt96100_init_module(void); static void gt96100_cleanup_module(void); static void dump_MII(int dbg_lvl, struct net_device *dev); @@ -84,7 +79,7 @@ static void abort(struct net_device *dev, u32 abort_bits); static void hard_stop(struct net_device *dev); static void enable_ether_irq(struct net_device *dev); static void disable_ether_irq(struct net_device *dev); -static int gt96100_probe1(int port_num); +static int gt96100_probe1(struct pci_dev *pci, int port_num); static void reset_tx(struct net_device *dev); static void reset_rx(struct net_device *dev); static int gt96100_check_tx_consistent(struct gt96100_private *gp); @@ -164,13 +159,11 @@ chip_name(int chip_rev) /* DMA memory allocation, derived from pci_alloc_consistent. */ -static void * -dmaalloc(size_t size, dma_addr_t *dma_handle) +static void * dmaalloc(size_t size, dma_addr_t *dma_handle) { void *ret; - ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA, - get_order(size)); + ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(size)); if (ret != NULL) { dma_cache_inv((unsigned long)ret, size); @@ -184,17 +177,13 @@ dmaalloc(size_t size, dma_addr_t *dma_handle) return ret; } -static void -dmafree(size_t size, void *vaddr) +static void dmafree(size_t size, void *vaddr) { vaddr = (void*)KSEG0ADDR(vaddr); free_pages((unsigned long)vaddr, get_order(size)); } - - -static void -gt96100_delay(int ms) +static void gt96100_delay(int ms) { if (in_interrupt()) return; @@ -327,34 +316,6 @@ write_MII(int phy_addr, u32 reg, u16 data) return 0; } -#if 0 -// These routines work, just disabled to avoid compile warnings -static void -dump_tx_ring(struct net_device *dev) -{ - struct gt96100_private *gp = netdev_priv(dev); - int i; - - dbg(0, "%s: txno/txni/cnt=%d/%d/%d\n", __FUNCTION__, - gp->tx_next_out, gp->tx_next_in, gp->tx_count); - - for (i=0; irx_next_out); - - for (i=0; iirq < 0) { - printk(KERN_ERR "%s: irq unknown - probing not supported\n", __FUNCTION_); + printk(KERN_ERR "%s: irq unknown - probing not supported\n", + __FUNCTION__); return -ENODEV; } - pcibios_read_config_byte(0, 0, PCI_REVISION_ID, &chip_rev); + pci_read_config_byte(pci, PCI_REVISION_ID, &chip_rev); if (chip_rev >= REV_GT96100A_1) { phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG); phy_addr = (phyAD >> (5*port_num)) & 0x1f; } else { /* - * not sure what's this about -- probably - * a gt bug + * not sure what's this about -- probably a gt bug */ phy_addr = port_num; phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG); @@ -831,6 +784,7 @@ out1: free_netdev (dev); out: release_region(gtif->iobase, GT96100_ETH_IO_SIZE); + err("%s failed. Returns %d\n", __FUNCTION__, retval); return retval; } @@ -1102,6 +1056,7 @@ gt96100_close(struct net_device *dev) } free_irq(dev->irq, dev); + return 0; } @@ -1312,10 +1267,11 @@ gt96100_tx_complete(struct net_device *dev, u32 status) cmdstat, nextOut); if (cmdstat & (u32)txOwn) { - //dump_tx_ring(dev); - // DMA is not finished writing descriptor??? - // Leave and come back later to pick-up where - // we left off. + /* + * DMA is not finished writing descriptor??? + * Leave and come back later to pick-up where + * we left off. + */ break; } @@ -1342,7 +1298,8 @@ gt96100_tx_complete(struct net_device *dev, u32 status) gp->tx_full = 0; if (gp->last_psr & psrLink) { netif_wake_queue(dev); - dbg(2, "%s: Tx Ring was full, queue waked\n", __FUNCTION_); + dbg(2, "%s: Tx Ring was full, queue waked\n", + __FUNCTION__); } } @@ -1425,12 +1382,12 @@ gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs) if ((psr & psrLink) && !gp->tx_full && netif_queue_stopped(dev)) { - dbg(0, ": Link up, waking queue.\n", - __FUNCTION_); + dbg(0, "%s: Link up, waking queue.\n", + __FUNCTION__); netif_wake_queue(dev); } else if (!(psr & psrLink) && !netif_queue_stopped(dev)) { - dbg(0, "Link down, stopping queue.\n", + dbg(0, "%s: Link down, stopping queue.\n", __FUNCTION__); netif_stop_queue(dev); } @@ -1569,8 +1526,8 @@ static void gt96100_cleanup_module(void) for (i=0; idev != NULL) { - struct gt96100_private *gp = - (struct gt96100_private *)gtif->dev->priv; + struct gt96100_private *gp = (struct gt96100_private *) + netdev_priv(gtif->dev); unregister_netdev(gtif->dev); dmafree(RX_HASH_TABLE_SIZE, gp->hash_table_dma); dmafree(PKT_BUF_SZ*RX_RING_SIZE, gp->rx_buff); @@ -1583,9 +1540,6 @@ static void gt96100_cleanup_module(void) } } - -#ifndef MODULE - static int __init gt96100_setup(char *options) { char *this_opt; @@ -1610,9 +1564,6 @@ static int __init gt96100_setup(char *options) __setup("gt96100eth=", gt96100_setup); -#endif /* !MODULE */ - - module_init(gt96100_init_module); module_exit(gt96100_cleanup_module); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index b5169e849..9b885efad 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -170,10 +170,10 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -559,13 +559,14 @@ static void hamachi_tx_timeout(struct net_device *dev); static void hamachi_init_ring(struct net_device *dev); static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static inline int hamachi_rx(struct net_device *dev); +static int hamachi_rx(struct net_device *dev); static inline int hamachi_tx(struct net_device *dev); static void hamachi_error(struct net_device *dev, int intr_status); static int hamachi_close(struct net_device *dev); static struct net_device_stats *hamachi_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); - +static struct ethtool_ops ethtool_ops; +static struct ethtool_ops ethtool_ops_no_mii; static int __devinit hamachi_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -631,7 +632,7 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev, read_eeprom(ioaddr, i), i % 16 != 15 ? " " : "\n"); #endif - hmp = dev->priv; + hmp = netdev_priv(dev); spin_lock_init(&hmp->lock); hmp->mii_if.dev = dev; @@ -725,6 +726,10 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev, dev->get_stats = &hamachi_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + if (chip_tbl[hmp->chip_id].flags & CanHaveMII) + SET_ETHTOOL_OPS(dev, ðtool_ops); + else + SET_ETHTOOL_OPS(dev, ðtool_ops_no_mii); dev->tx_timeout = &hamachi_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; if (mtu) @@ -851,7 +856,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int hamachi_open(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; u32 rx_int_var, tx_int_var; @@ -1000,7 +1005,7 @@ static int hamachi_open(struct net_device *dev) static inline int hamachi_tx(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); /* Update the dirty pointer until we find an entry that is still owned by the card */ @@ -1032,7 +1037,7 @@ static inline int hamachi_tx(struct net_device *dev) static void hamachi_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 10*HZ; @@ -1057,7 +1062,7 @@ static void hamachi_timer(unsigned long data) static void hamachi_tx_timeout(struct net_device *dev) { int i; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Hamachi transmit timed out, status %8.8x," @@ -1163,7 +1168,7 @@ static void hamachi_tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void hamachi_init_ring(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); int i; hmp->tx_full = 0; @@ -1255,7 +1260,7 @@ do { \ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); unsigned entry; u16 status; @@ -1383,7 +1388,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs #endif ioaddr = dev->base_addr; - hmp = dev->priv; + hmp = netdev_priv(dev); spin_lock(&hmp->lock); do { @@ -1477,7 +1482,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs for clarity and better register allocation. */ static int hamachi_rx(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); int entry = hmp->cur_rx % RX_RING_SIZE; int boguscnt = (hmp->dirty_rx + RX_RING_SIZE) - hmp->cur_rx; @@ -1693,7 +1698,7 @@ static int hamachi_rx(struct net_device *dev) static void hamachi_error(struct net_device *dev, int intr_status) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); if (intr_status & (LinkChange|NegotiationChange)) { if (hamachi_debug > 1) @@ -1727,7 +1732,7 @@ static void hamachi_error(struct net_device *dev, int intr_status) static int hamachi_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1813,7 +1818,7 @@ static int hamachi_close(struct net_device *dev) static struct net_device_stats *hamachi_get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); /* We should lock this segment of code for SMP eventually, although the vulnerability window is very small and statistics are @@ -1867,84 +1872,76 @@ static void set_rx_mode(struct net_device *dev) } } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - struct hamachi_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } + if (!netif_running(dev)) + return -EINVAL; + return 0; +} - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - return mii_nway_restart(&np->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; +static void hamachi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct hamachi_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); } +static int hamachi_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct hamachi_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} + +static int hamachi_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct hamachi_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return res; +} + +static int hamachi_nway_reset(struct net_device *dev) +{ + struct hamachi_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} + +static u32 hamachi_get_link(struct net_device *dev) +{ + struct hamachi_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = hamachi_get_drvinfo, + .get_settings = hamachi_get_settings, + .set_settings = hamachi_set_settings, + .nway_reset = hamachi_nway_reset, + .get_link = hamachi_get_link, +}; + +static struct ethtool_ops ethtool_ops_no_mii = { + .begin = check_if_running, + .get_drvinfo = hamachi_get_drvinfo, +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct hamachi_private *np = dev->priv; + struct hamachi_private *np = netdev_priv(dev); struct mii_ioctl_data *data = if_mii(rq); int rc; if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */ + if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */ u32 *d = (u32 *)&rq->ifr_ifru; /* Should add this check here or an ordinary user can do nasty * things. -KDU @@ -1976,7 +1973,7 @@ static void __devexit hamachi_remove_one (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, hmp->rx_ring_dma); @@ -2009,10 +2006,7 @@ static int __init hamachi_init (void) #ifdef MODULE printk(version); #endif - if (pci_register_driver(&hamachi_driver) > 0) - return 0; - pci_unregister_driver(&hamachi_driver); - return -ENODEV; + return pci_register_driver(&hamachi_driver); } static void __exit hamachi_exit (void) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e6dba5623..85a875239 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -152,13 +152,13 @@ static void sp_xmit_on_air(unsigned long channel) if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->status2 = 0; } else sp_start_tx_timer(sp); @@ -229,13 +229,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) */ if (sp->duplex == 1) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, count); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, count); sp->xleft = count - actual; sp->xhead = sp->xbuff + actual; sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); } else { sp->xleft = count; sp->xhead = sp->xbuff; @@ -493,7 +493,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty) } if (sp->tx_enable == 1) { - actual = tty->driver->write(tty, 0, sp->xhead, sp->xleft); + actual = tty->driver->write(tty, sp->xhead, sp->xleft); sp->xleft -= actual; sp->xhead += actual; } @@ -652,8 +652,8 @@ static void resync_tnc(unsigned long channel) /* resync the TNC */ sp->led_state = 0x60; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); - sp->tty->driver->write(sp->tty, 0, &resync_cmd, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &resync_cmd, 1); /* Start resync timer again -- the TNC might be still absent */ @@ -669,7 +669,7 @@ static inline int tnc_init(struct sixpack *sp) { unsigned char inbyte = 0xe8; - sp->tty->driver->write(sp->tty, 0, &inbyte, 1); + sp->tty->driver->write(sp->tty, &inbyte, 1); del_timer(&sp->resync_t); sp->resync_t.data = (unsigned long) sp; @@ -954,9 +954,9 @@ static void decode_prio_command(unsigned char cmd, struct sixpack *sp) } else { /* output watchdog char if idle */ if ((sp->status2 != 0) && (sp->duplex == 1)) { sp->led_state = 0x70; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->tx_enable = 1; - actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2); + actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2); sp->xleft -= actual; sp->xhead += actual; sp->led_state = 0x60; @@ -966,7 +966,7 @@ static void decode_prio_command(unsigned char cmd, struct sixpack *sp) } /* needed to trigger the TNC watchdog */ - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); /* if the state byte has been received, the TNC is present, so the resync timer can be reset. */ @@ -996,12 +996,12 @@ static void decode_std_command(unsigned char cmd, struct sixpack *sp) if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) { sp->led_state = 0x68; - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); } } else { sp->led_state = 0x60; /* fill trailing bytes with zeroes */ - sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1); + sp->tty->driver->write(sp->tty, &sp->led_state, 1); rest = sp->rx_count; if (rest != 0) for (i = rest; i <= 3; i++) diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 4bd7c0965..77f29fdde 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -83,9 +83,9 @@ #include #include #include +#include #include -#include #include /* --------------------------------------------------------------------- */ diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 6b85ab3c9..803d5a137 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -193,7 +193,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty bpq = (struct bpqdev *)dev->priv; - eth = (struct ethhdr *)skb->mac.raw; + eth = eth_hdr(skb); if (!(bpq->acpt_addr[0] & 0x01) && memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN)) diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 9f3dac7d2..94191fdb8 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -246,8 +245,14 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev); static struct net_device_stats *scc_get_stats(struct net_device *dev); static int scc_set_mac_address(struct net_device *dev, void *sa); -static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs); +static inline void tx_on(struct scc_priv *priv); +static inline void rx_on(struct scc_priv *priv); +static inline void rx_off(struct scc_priv *priv); +static void start_timer(struct scc_priv *priv, int t, int r15); +static inline unsigned char random(void); + static inline void z8530_isr(struct scc_info *info); +static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs); static void rx_isr(struct scc_priv *priv); static void special_condition(struct scc_priv *priv, int rc); static void rx_bh(void *arg); @@ -255,12 +260,6 @@ static void tx_isr(struct scc_priv *priv); static void es_isr(struct scc_priv *priv); static void tm_isr(struct scc_priv *priv); -static inline void tx_on(struct scc_priv *priv); -static inline void rx_on(struct scc_priv *priv); -static inline void rx_off(struct scc_priv *priv); -static void start_timer(struct scc_priv *priv, int t, int r15); -static inline unsigned char random(void); - /* Initialization variables */ @@ -945,42 +944,115 @@ static int scc_set_mac_address(struct net_device *dev, void *sa) { } -static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) { - struct scc_info *info = dev_id; +static inline void tx_on(struct scc_priv *priv) { + int i, n; + unsigned long flags; - spin_lock(info->priv[0].register_lock); - /* At this point interrupts are enabled, and the interrupt under service - is already acknowledged, but masked off. + if (priv->param.dma >= 0) { + n = (priv->chip == Z85230) ? 3 : 1; + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_WRITE); + set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); + set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); + release_dma_lock(flags); + /* Enable TX underrun interrupt */ + write_scc(priv, R15, TxUIE); + /* Configure DREQ */ + if (priv->type == TYPE_TWIN) + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, + priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); + /* Write first byte(s) */ + spin_lock_irqsave(priv->register_lock, flags); + for (i = 0; i < n; i++) + write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); + enable_dma(priv->param.dma); + spin_unlock_irqrestore(priv->register_lock, flags); + } else { + write_scc(priv, R15, TxUIE); + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); + tx_isr(priv); + } + /* Reset EOM latch if we do not have the AUTOEOM feature */ + if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); +} - Interrupt processing: We loop until we know that the IRQ line is - low. If another positive edge occurs afterwards during the ISR, - another interrupt will be triggered by the interrupt controller - as soon as the IRQ level is enabled again (see asm/irq.h). - Bottom-half handlers will be processed after scc_isr(). This is - important, since we only have small ringbuffers and want new data - to be fetched/delivered immediately. */ +static inline void rx_on(struct scc_priv *priv) { + unsigned long flags; - if (info->priv[0].type == TYPE_TWIN) { - int is, card_base = info->priv[0].card_base; - while ((is = ~inb(card_base + TWIN_INT_REG)) & - TWIN_INT_MSK) { - if (is & TWIN_SCC_MSK) { - z8530_isr(info); - } else if (is & TWIN_TMR1_MSK) { - inb(card_base + TWIN_CLR_TMR1); - tm_isr(&info->priv[0]); - } else { - inb(card_base + TWIN_CLR_TMR2); - tm_isr(&info->priv[1]); - } + /* Clear RX FIFO */ + while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); + priv->rx_over = 0; + if (priv->param.dma >= 0) { + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_READ); + set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(priv->param.dma, BUF_SIZE); + release_dma_lock(flags); + enable_dma(priv->param.dma); + /* Configure PackeTwin DMA */ + if (priv->type == TYPE_TWIN) { + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, + priv->card_base + TWIN_DMA_CFG); } - } else z8530_isr(info); - spin_unlock(info->priv[0].register_lock); - return IRQ_HANDLED; + /* Sp. cond. intr. only, ext int enable, RX DMA enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | + WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + /* Reset current frame */ + priv->rx_ptr = 0; + /* Intr. on all Rx characters and Sp. cond., ext int enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | + WT_FN_RDYFN); + } + write_scc(priv, R0, ERR_RES); + write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); +} + + +static inline void rx_off(struct scc_priv *priv) { + /* Disable receiver */ + write_scc(priv, R3, Rx8); + /* Disable DREQ / RX interrupt */ + if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) + outb(0, priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); + /* Disable DMA */ + if (priv->param.dma >= 0) disable_dma(priv->param.dma); +} + + +static void start_timer(struct scc_priv *priv, int t, int r15) { + unsigned long flags; + + outb(priv->tmr_mode, priv->tmr_ctrl); + if (t == 0) { + tm_isr(priv); + } else if (t > 0) { + save_flags(flags); + cli(); + outb(t & 0xFF, priv->tmr_cnt); + outb((t >> 8) & 0xFF, priv->tmr_cnt); + if (priv->type != TYPE_TWIN) { + write_scc(priv, R15, r15 | CTSIE); + priv->rr0 |= CTS; + } + restore_flags(flags); + } } +static inline unsigned char random(void) { + /* See "Numerical Recipes in C", second edition, p. 284 */ + rand = rand * 1664525L + 1013904223L; + return (unsigned char) (rand >> 24); +} + static inline void z8530_isr(struct scc_info *info) { int is, i = 100; @@ -1009,6 +1081,42 @@ static inline void z8530_isr(struct scc_info *info) { } +static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) { + struct scc_info *info = dev_id; + + spin_lock(info->priv[0].register_lock); + /* At this point interrupts are enabled, and the interrupt under service + is already acknowledged, but masked off. + + Interrupt processing: We loop until we know that the IRQ line is + low. If another positive edge occurs afterwards during the ISR, + another interrupt will be triggered by the interrupt controller + as soon as the IRQ level is enabled again (see asm/irq.h). + + Bottom-half handlers will be processed after scc_isr(). This is + important, since we only have small ringbuffers and want new data + to be fetched/delivered immediately. */ + + if (info->priv[0].type == TYPE_TWIN) { + int is, card_base = info->priv[0].card_base; + while ((is = ~inb(card_base + TWIN_INT_REG)) & + TWIN_INT_MSK) { + if (is & TWIN_SCC_MSK) { + z8530_isr(info); + } else if (is & TWIN_TMR1_MSK) { + inb(card_base + TWIN_CLR_TMR1); + tm_isr(&info->priv[0]); + } else { + inb(card_base + TWIN_CLR_TMR2); + tm_isr(&info->priv[1]); + } + } + } else z8530_isr(info); + spin_unlock(info->priv[0].register_lock); + return IRQ_HANDLED; +} + + static void rx_isr(struct scc_priv *priv) { if (priv->param.dma >= 0) { /* Check special condition and perform error reset. See 2.4.7.5. */ @@ -1292,114 +1400,3 @@ static void tm_isr(struct scc_priv *priv) { break; } } - - -static inline void tx_on(struct scc_priv *priv) { - int i, n; - unsigned long flags; - - if (priv->param.dma >= 0) { - n = (priv->chip == Z85230) ? 3 : 1; - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_WRITE); - set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); - set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); - release_dma_lock(flags); - /* Enable TX underrun interrupt */ - write_scc(priv, R15, TxUIE); - /* Configure DREQ */ - if (priv->type == TYPE_TWIN) - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, - priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); - /* Write first byte(s) */ - spin_lock_irqsave(priv->register_lock, flags); - for (i = 0; i < n; i++) - write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); - enable_dma(priv->param.dma); - spin_unlock_irqrestore(priv->register_lock, flags); - } else { - write_scc(priv, R15, TxUIE); - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); - tx_isr(priv); - } - /* Reset EOM latch if we do not have the AUTOEOM feature */ - if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); -} - - -static inline void rx_on(struct scc_priv *priv) { - unsigned long flags; - - /* Clear RX FIFO */ - while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); - priv->rx_over = 0; - if (priv->param.dma >= 0) { - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_READ); - set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(priv->param.dma, BUF_SIZE); - release_dma_lock(flags); - enable_dma(priv->param.dma); - /* Configure PackeTwin DMA */ - if (priv->type == TYPE_TWIN) { - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, - priv->card_base + TWIN_DMA_CFG); - } - /* Sp. cond. intr. only, ext int enable, RX DMA enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | - WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); - } else { - /* Reset current frame */ - priv->rx_ptr = 0; - /* Intr. on all Rx characters and Sp. cond., ext int enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | - WT_FN_RDYFN); - } - write_scc(priv, R0, ERR_RES); - write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); -} - - -static inline void rx_off(struct scc_priv *priv) { - /* Disable receiver */ - write_scc(priv, R3, Rx8); - /* Disable DREQ / RX interrupt */ - if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) - outb(0, priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); - /* Disable DMA */ - if (priv->param.dma >= 0) disable_dma(priv->param.dma); -} - - -static void start_timer(struct scc_priv *priv, int t, int r15) { - unsigned long flags; - - outb(priv->tmr_mode, priv->tmr_ctrl); - if (t == 0) { - tm_isr(priv); - } else if (t > 0) { - save_flags(flags); - cli(); - outb(t & 0xFF, priv->tmr_cnt); - outb((t >> 8) & 0xFF, priv->tmr_cnt); - if (priv->type != TYPE_TWIN) { - write_scc(priv, R15, r15 | CTSIE); - priv->rr0 |= CTS; - } - restore_flags(flags); - } -} - - -static inline unsigned char random(void) { - /* See "Numerical Recipes in C", second edition, p. 284 */ - rand = rand * 1664525L + 1013904223L; - return (unsigned char) (rand >> 24); -} - diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 86deb5210..8e115b5a6 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index c7076aa0b..1b8663f5f 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -379,7 +379,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) } ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); + actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); ax->tx_packets++; ax->tx_bytes+=actual; ax->dev->trans_start = jiffies; @@ -411,7 +411,7 @@ static void ax25_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, ax->xhead, ax->xleft); + actual = tty->driver->write(tty, ax->xhead, ax->xleft); ax->xleft -= actual; ax->xhead += actual; } @@ -518,7 +518,7 @@ static int ax_open(struct net_device *dev) ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */ - ax->buflock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&ax->buflock); netif_start_queue(dev); return 0; @@ -602,8 +602,6 @@ static int ax25_open(struct tty_struct *tty) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); /* Restore default settings */ ax->dev->type = ARPHRD_AX25; diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 2049556d1..8da194802 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -173,6 +173,7 @@ #include #include #include +#include #include @@ -180,7 +181,6 @@ #include #include #include -#include #include "z8530.h" diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index c516e7156..acae5949a 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 78ae4b2ac..2392d4523 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -114,8 +114,8 @@ #include /* for CONFIG_PCI */ #include #include +#include -#include #include #include "hp100.h" @@ -161,7 +161,7 @@ struct hp100_private { u_char bus; struct pci_dev *pci_dev; short mem_mapped; /* memory mapped access */ - void *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ + void __iomem *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ unsigned long mem_ptr_phys; /* physical memory mapped area */ short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */ int hub_status; /* was login to hub successful? */ @@ -435,7 +435,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, u_short local_mode, lsw; short mem_mapped; unsigned long mem_ptr_phys; - void **mem_ptr_virt; + void __iomem *mem_ptr_virt; struct hp100_private *lp; #ifdef HP100_DEBUG_B @@ -2906,13 +2906,19 @@ static struct eisa_driver hp100_eisa_driver = { static int __devinit hp100_pci_probe (struct pci_dev *pdev, const struct pci_device_id *ent) { - struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); - int ioaddr = pci_resource_start(pdev, 0); + struct net_device *dev; + int ioaddr; u_short pci_command; int err; - - if (!dev) - return -ENOMEM; + + if (pci_enable_device(pdev)) + return -ENODEV; + + dev = alloc_etherdev(sizeof(struct hp100_private)); + if (!dev) { + err = -ENOMEM; + goto out0; + } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -2934,7 +2940,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev, pci_write_config_word(pdev, PCI_COMMAND, pci_command); } - + ioaddr = pci_resource_start(pdev, 0); err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev); if (err) goto out1; @@ -2951,6 +2957,8 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev, release_region(dev->base_addr, HP100_REGION_SIZE); out1: free_netdev(dev); + out0: + pci_disable_device(pdev); return err; } @@ -2959,6 +2967,7 @@ static void __devexit hp100_pci_remove (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); cleanup_dev(dev); + pci_disable_device(pdev); } diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 965f94958..08703d6f9 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c @@ -40,9 +40,7 @@ /* Our private data structure */ struct hplance_private { - struct lance_private lance; - unsigned int scode; - void *base; + struct lance_private lance; }; /* function prototypes... This is easy because all the grot is in the @@ -50,89 +48,96 @@ struct hplance_private { * plus board-specific init, open and close actions. * Oh, and we need to tell the generic code how to read and write LANCE registers... */ -static void hplance_init(struct net_device *dev, int scode); -static int hplance_open(struct net_device *dev); -static int hplance_close(struct net_device *dev); +static int __devinit hplance_init_one(struct dio_dev *d, + const struct dio_device_id *ent); +static void __devinit hplance_init(struct net_device *dev, + struct dio_dev *d); +static void __devexit hplance_remove_one(struct dio_dev *d); static void hplance_writerap(void *priv, unsigned short value); static void hplance_writerdp(void *priv, unsigned short value); static unsigned short hplance_readrdp(void *priv); +static int hplance_open(struct net_device *dev); +static int hplance_close(struct net_device *dev); -#ifdef MODULE -static struct hplance_private *root_hplance_dev; -#endif +static struct dio_device_id hplance_dio_tbl[] = { + { DIO_ID_LAN }, + { 0 } +}; -static void cleanup_card(struct net_device *dev) -{ - struct hplance_private *lp = netdev_priv(dev); - dio_unconfig_board(lp->scode); -} +static struct dio_driver hplance_driver = { + .name = "hplance", + .id_table = hplance_dio_tbl, + .probe = hplance_init_one, + .remove = __devexit_p(hplance_remove_one), +}; /* Find all the HP Lance boards and initialise them... */ -struct net_device * __init hplance_probe(int unit) +static int __devinit hplance_init_one(struct dio_dev *d, + const struct dio_device_id *ent) { struct net_device *dev; - - if (!MACH_IS_HP300) - return ERR_PTR(-ENODEV); + int err = -ENOMEM; dev = alloc_etherdev(sizeof(struct hplance_private)); if (!dev) - return ERR_PTR(-ENOMEM); + goto out; - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - } + err = -EBUSY; + if (!request_mem_region(dio_resource_start(d), + dio_resource_len(d), d->name)) + goto out_free_netdev; - SET_MODULE_OWNER(dev); - - /* Isn't DIO nice? */ - for(;;) - { - int scode = dio_find(DIO_ID_LAN); - - if (!scode) - break; - - dio_config_board(scode); - hplance_init(dev, scode); - if (!register_netdev(dev)) { - struct hplance_private *lp = netdev_priv(dev); - lp->next_module = root_hplance_dev; - root_hplance_dev = lp; - return dev; - } - cleanup_card(dev); - } + hplance_init(dev, d); + err = register_netdev(dev); + if (err) + goto out_release_mem_region; + + dio_set_drvdata(d, dev); + return 0; + + out_release_mem_region: + release_mem_region(dio_resource_start(d), dio_resource_len(d)); + out_free_netdev: free_netdev(dev); - return ERR_PTR(-ENODEV); + out: + return err; } -/* Initialise a single lance board at the given select code */ -static void __init hplance_init(struct net_device *dev, int scode) +static void __devexit hplance_remove_one(struct dio_dev *d) { - const char *name = dio_scodetoname(scode); - void *va = dio_scodetoviraddr(scode); + struct net_device *dev = dio_get_drvdata(d); + + unregister_netdev(dev); + release_mem_region(dio_resource_start(d), dio_resource_len(d)); + free_netdev(dev); +} + +/* Initialise a single lance board at the given DIO device */ +static void __init hplance_init(struct net_device *dev, struct dio_dev *d) +{ + unsigned long va = (d->resource.start + DIO_VIRADDRBASE); struct hplance_private *lp; int i; - printk("%s: %s; select code %d, addr", dev->name, name, scode); + printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, d->name, d->scode); /* reset the board */ out_8(va+DIO_IDOFF, 0xff); udelay(100); /* ariba! ariba! udelay! udelay! */ /* Fill the dev fields */ - dev->base_addr = (unsigned long)va; + dev->base_addr = va; dev->open = &hplance_open; dev->stop = &hplance_close; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = lance_poll; +#endif dev->hard_start_xmit = &lance_start_xmit; dev->get_stats = &lance_get_stats; dev->set_multicast_list = &lance_set_multicast; dev->dma = 0; - for (i=0; i<6; i++) - { + for (i=0; i<6; i++) { /* The NVRAM holds our ethernet address, one nibble per byte, * at bytes NVRAMOFF+1,3,5,7,9... */ @@ -142,12 +147,12 @@ static void __init hplance_init(struct net_device *dev, int scode) } lp = netdev_priv(dev); - lp->lance.name = (char*)name; /* discards const, shut up gcc */ - lp->lance.ll = (struct lance_regs *)(va + HPLANCE_REGOFF); + lp->lance.name = (char*)d->name; /* discards const, shut up gcc */ + lp->lance.base = va; lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */ lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */ lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ - lp->lance.irq = dio_scodetoipl(scode); + lp->lance.irq = d->ipl; lp->lance.writerap = hplance_writerap; lp->lance.writerdp = hplance_writerdp; lp->lance.readrdp = hplance_readrdp; @@ -155,8 +160,6 @@ static void __init hplance_init(struct net_device *dev, int scode) lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS; lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK; lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK; - lp->scode = scode; - lp->base = va; printk(", irq %d\n", lp->lance.irq); } @@ -165,78 +168,64 @@ static void __init hplance_init(struct net_device *dev, int scode) */ static void hplance_writerap(void *priv, unsigned short value) { - struct hplance_private *lp = (struct hplance_private *)priv; - struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; - do { - lp->lance.ll->rap = value; - } while ((hpregs->status & LE_ACK) == 0); + struct lance_private *lp = (struct lance_private *)priv; + do { + out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); } static void hplance_writerdp(void *priv, unsigned short value) { - struct hplance_private *lp = (struct hplance_private *)priv; - struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; - do { - lp->lance.ll->rdp = value; - } while ((hpregs->status & LE_ACK) == 0); + struct lance_private *lp = (struct lance_private *)priv; + do { + out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); } static unsigned short hplance_readrdp(void *priv) { - unsigned short val; - struct hplance_private *lp = (struct hplance_private *)priv; - struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; - do { - val = lp->lance.ll->rdp; - } while ((hpregs->status & LE_ACK) == 0); - return val; + struct lance_private *lp = (struct lance_private *)priv; + __u16 value; + do { + value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP); + } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0); + return value; } static int hplance_open(struct net_device *dev) { int status; - struct hplance_private *lp = netdev_priv(dev); - struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; + struct lance_private *lp = netdev_priv(dev); status = lance_open(dev); /* call generic lance open code */ if (status) return status; /* enable interrupts at board level. */ - out_8(&(hpregs->status), LE_IE); + out_8(lp->base + HPLANCE_STATUS, LE_IE); return 0; } static int hplance_close(struct net_device *dev) { - struct hplance_private *lp = netdev_priv(dev); - struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; - out_8(&(hpregs->status), 8); /* disable interrupts at boardlevel */ + struct lance_private *lp = netdev_priv(dev); + + out_8(lp->base + HPLANCE_STATUS, 0); /* disable interrupts at boardlevel */ lance_close(dev); return 0; } -#ifdef MODULE -MODULE_LICENSE("GPL"); -int init_module(void) +int __init hplance_init_module(void) { - int found = 0; - while (!IS_ERR(hplance_probe(-1))) - found++; - return found ? 0 : -ENODEV; + return dio_module_init(&hplance_driver); } -void cleanup_module(void) +void __exit hplance_cleanup_module(void) { - /* Walk the chain of devices, unregistering them */ - struct hplance_private *lp; - while (root_hplance_dev) { - lp = root_hplance_dev->next_module; - unregister_netdev(root_lance_dev->dev); - cleanup_card(root_lance_dev->dev); - free_netdev(root_lance_dev->dev); - root_lance_dev = lp; - } + dio_unregister_driver(&hplance_driver); } -#endif /* MODULE */ +module_init(hplance_init_module); +module_exit(hplance_cleanup_module); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/hplance.h b/drivers/net/hplance.h index 3af4c4d1f..04aee9e03 100644 --- a/drivers/net/hplance.h +++ b/drivers/net/hplance.h @@ -4,15 +4,10 @@ */ /* Registers */ -struct hplance_reg -{ - u_char pad0; - volatile u_char id; /* DIO register: ID byte */ - u_char pad1; - volatile u_char status; /* DIO register: interrupt enable */ -}; +#define HPLANCE_ID 0x01 /* DIO register: ID byte */ +#define HPLANCE_STATUS 0x03 /* DIO register: interrupt enable/status */ -/* Control and status bits for the hplance->status register */ +/* Control and status bits for the status register */ #define LE_IE 0x80 /* interrupt enable */ #define LE_IR 0x40 /* interrupt requested */ #define LE_LOCK 0x08 /* lock status register */ @@ -25,7 +20,7 @@ struct hplance_reg /* These are the offsets for the DIO regs (hplance_reg), lance_ioreg, * memory and NVRAM: */ -#define HPLANCE_IDOFF 0 /* board baseaddr, struct hplance_reg */ -#define HPLANCE_REGOFF 0x4000 /* struct lance_regs */ +#define HPLANCE_IDOFF 0 /* board baseaddr */ +#define HPLANCE_REGOFF 0x4000 /* lance registers */ #define HPLANCE_MEMOFF 0x8000 /* struct lance_init_block */ #define HPLANCE_NVRAMOFF 0xC008 /* etheraddress as one *nibble* per byte */ diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index fecaec102..6e0ca7340 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -23,8 +23,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h index 5310033ad..7436af605 100644 --- a/drivers/net/ibm_emac/ibm_emac.h +++ b/drivers/net/ibm_emac/ibm_emac.h @@ -228,6 +228,21 @@ typedef struct emac_regs { (desc & EMAC_BAD_RX_PACKET) #endif +/* SoC implementation specific EMAC register defaults */ +#if defined(CONFIG_440GP) +#define EMAC_RWMR_DEFAULT 0x80009000 +#define EMAC_TMR0_DEFAULT 0x00000000 +#define EMAC_TMR1_DEFAULT 0xf8640000 +#elif defined(CONFIG_440GX) +#define EMAC_RWMR_DEFAULT 0x1000a200 +#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32 +#define EMAC_TMR1_DEFAULT 0xa00f0000 +#else +#define EMAC_RWMR_DEFAULT 0x0f002000 +#define EMAC_TMR0_DEFAULT 0x00000000 +#define EMAC_TMR1_DEFAULT 0x380f0000 +#endif /* CONFIG_440GP */ + /* Revision specific EMAC register defaults */ #ifdef CONFIG_IBM_EMAC4 #define EMAC_M1_DEFAULT (EMAC_M1_BASE | \ @@ -236,7 +251,7 @@ typedef struct emac_regs { #define EMAC_RMR_DEFAULT (EMAC_RMR_BASE | \ EMAC_RMR_RFAF_128_2048) #define EMAC_TMR0_XMIT (EMAC_TMR0_GNP0 | \ - EMAC_TMR0_TFAE_128_2048) + EMAC_TMR0_DEFAULT) #define EMAC_TRTR_DEFAULT EMAC_TRTR_1024 #else /* !CONFIG_IBM_EMAC4 */ #define EMAC_M1_DEFAULT EMAC_M1_BASE @@ -245,19 +260,4 @@ typedef struct emac_regs { #define EMAC_TRTR_DEFAULT EMAC_TRTR_1600 #endif /* CONFIG_IBM_EMAC4 */ -/* SoC implementation specific EMAC register defaults */ -#if defined(CONFIG_440GP) -#define EMAC_RWMR_DEFAULT 0x80009000 -#define EMAC_TMR0_DEFAULT 0x00000000 -#define EMAC_TMR1_DEFAULT 0xf8640000 -#elif defined(CONFIG_440GX) -#define EMAC_RWMR_DEFAULT 0x1000a200 -#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_128_2048 -#define EMAC_TMR1_DEFAULT 0x88810000 -#else -#define EMAC_RWMR_DEFAULT 0x0f002000 -#define EMAC_TMR0_DEFAULT 0x00000000 -#define EMAC_TMR1_DEFAULT 0x380f0000 -#endif /* CONFIG_440GP */ - #endif diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 2ca3de076..39c65064c 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -40,9 +40,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -90,23 +90,24 @@ MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n" #define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev)) -static unsigned int rgmii_enable[] = - { RGMII_RTBI, RGMII_RGMII, RGMII_TBI, RGMII_GMII }; +static unsigned int rgmii_enable[] = { + RGMII_RTBI, + RGMII_RGMII, + RGMII_TBI, + RGMII_GMII +}; -static unsigned int rgmii_speed_mask[] = { 0, - 0, +static unsigned int rgmii_speed_mask[] = { RGMII_MII2_SPDMASK, RGMII_MII3_SPDMASK }; -static unsigned int rgmii_speed100[] = { 0, - 0, +static unsigned int rgmii_speed100[] = { RGMII_MII2_100MB, RGMII_MII3_100MB }; -static unsigned int rgmii_speed1000[] = { 0, - 0, +static unsigned int rgmii_speed1000[] = { RGMII_MII2_1000MB, RGMII_MII3_1000MB }; @@ -122,11 +123,21 @@ static unsigned int zmii_enable[][4] = { ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)}, {ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)} }; -static unsigned int mdi_enable[] = - { ZMII_MDI0, ZMII_MDI1, ZMII_MDI2, ZMII_MDI3 }; + +static unsigned int mdi_enable[] = { + ZMII_MDI0, + ZMII_MDI1, + ZMII_MDI2, + ZMII_MDI3 +}; static unsigned int zmii_speed = 0x0; -static unsigned int zmii_speed100[] = { ZMII_MII0_100MB, ZMII_MII1_100MB }; +static unsigned int zmii_speed100[] = { + ZMII_MII0_100MB, + ZMII_MII1_100MB, + ZMII_MII2_100MB, + ZMII_MII3_100MB +}; /* Since multiple EMACs share MDIO lines in various ways, we need * to avoid re-using the same PHY ID in cases where the arch didn't @@ -367,6 +378,7 @@ static void emac_close_zmii(struct ocp_device *ocpdev) int emac_phy_read(struct net_device *dev, int mii_id, int reg) { + int count; uint32_t stacr; struct ocp_enet_private *fep = dev->priv; emac_t *emacp = fep->emacp; @@ -385,9 +397,13 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg) emacp = fep->emacp; } - udelay(MDIO_DELAY); + count = 0; + while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0) + && (count++ < MDIO_DELAY)) + udelay(1); + MDIO_DEBUG((" (count was %d)\n", count)); - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) { + if ((stacr & EMAC_STACR_OC) == 0) { printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name); return -1; } @@ -398,8 +414,11 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg) out_be32(&emacp->em0stacr, stacr); - udelay(MDIO_DELAY); - stacr = in_be32(&emacp->em0stacr); + count = 0; + while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0) + && (count++ < MDIO_DELAY)) + udelay(1); + MDIO_DEBUG((" (count was %d)\n", count)); if ((stacr & EMAC_STACR_OC) == 0) { printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name); @@ -419,6 +438,7 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg) void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data) { + int count; uint32_t stacr; struct ocp_enet_private *fep = dev->priv; emac_t *emacp = fep->emacp; @@ -437,9 +457,13 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data) emacp = fep->emacp; } - udelay(MDIO_DELAY); + count = 0; + while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0) + && (count++ < MDIO_DELAY)) + udelay(1); + MDIO_DEBUG((" (count was %d)\n", count)); - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) { + if ((stacr & EMAC_STACR_OC) == 0) { printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name); return; } @@ -451,9 +475,12 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data) out_be32(&emacp->em0stacr, stacr); - udelay(MDIO_DELAY); + while (((stacr = in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) + && (count++ < 5000)) + udelay(1); + MDIO_DEBUG((" (count was %d)\n", count)); - if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) + if ((stacr & EMAC_STACR_OC) == 0) printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name); /* Check for a write error */ @@ -593,7 +620,7 @@ emac_rx_csum(struct net_device *dev, unsigned short ctrl, struct sk_buff *skb) static int emac_rx_clean(struct net_device *dev) { - int i, b, bnum, buf[6]; + int i, b, bnum = 0, buf[6]; int error, frame_length; struct ocp_enet_private *fep = dev->priv; unsigned short ctrl; @@ -994,7 +1021,6 @@ static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev) static int emac_adjust_to_link(struct ocp_enet_private *fep) { emac_t *emacp = fep->emacp; - struct ibm_ocp_rgmii *rgmii; unsigned long mode_reg; int full_duplex, speed; @@ -1011,21 +1037,23 @@ static int emac_adjust_to_link(struct ocp_enet_private *fep) speed = fep->phy_mii.speed; } - if (fep->rgmii_dev) - rgmii = RGMII_PRIV(fep->rgmii_dev); /* set speed (default is 10Mb) */ switch (speed) { case SPEED_1000: mode_reg |= EMAC_M1_JUMBO_ENABLE | EMAC_M1_RFS_16K; - if ((rgmii->mode[fep->rgmii_input] == RTBI) - || (rgmii->mode[fep->rgmii_input] == TBI)) - mode_reg |= EMAC_M1_MF_1000GPCS; - else - mode_reg |= EMAC_M1_MF_1000MBPS; - if (fep->rgmii_dev) + if (fep->rgmii_dev) { + struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(fep->rgmii_dev); + + if ((rgmii->mode[fep->rgmii_input] == RTBI) + || (rgmii->mode[fep->rgmii_input] == TBI)) + mode_reg |= EMAC_M1_MF_1000GPCS; + else + mode_reg |= EMAC_M1_MF_1000MBPS; + emac_rgmii_port_speed(fep->rgmii_dev, fep->rgmii_input, 1000); + } break; case SPEED_100: mode_reg |= EMAC_M1_MF_100MBPS | EMAC_M1_RFS_4K; @@ -1940,8 +1968,6 @@ static struct ocp_driver emac_driver = { static int __init emac_init(void) { - int rc; - printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n"); printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n"); @@ -1950,13 +1976,8 @@ static int __init emac_init(void) skb_res); skb_res = 2; } - rc = ocp_register_driver(&emac_driver); - if (rc < 0) { - ocp_unregister_driver(&emac_driver); - return -ENODEV; - } - return 0; + return ocp_register_driver(&emac_driver); } static void __exit emac_exit(void) diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h index 691ce4e5c..97e6e1ea8 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.h +++ b/drivers/net/ibm_emac/ibm_emac_core.h @@ -67,7 +67,7 @@ #define TX_TIMEOUT (2*HZ) /* MDIO latency delay */ -#define MDIO_DELAY 50 +#define MDIO_DELAY 250 /* Power managment shift registers */ #define IBM_CPM_EMMII 0 /* Shift value for MII */ diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c index 02d847cfa..6597791a7 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.c +++ b/drivers/net/ibm_emac/ibm_emac_mal.c @@ -55,8 +55,6 @@ int mal_register_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac) write_unlock_irqrestore(&mal_list_lock, flags); - MOD_INC_USE_COUNT; - return 0; } @@ -73,8 +71,6 @@ int mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac) write_unlock_irqrestore(&mal_list_lock, flags); - MOD_DEC_USE_COUNT; - return 0; } diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h index 8e456ce5a..dd9f0dabc 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.h +++ b/drivers/net/ibm_emac/ibm_emac_mal.h @@ -83,6 +83,7 @@ struct ibm_ocp_mal { GET_MAL0_STANZA(dcrn) \ GET_MAL1_STANZA(dcrn) \ default: \ + x = 0; \ BUG(); \ } \ x; }) diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 0aa0a8261..2f7a9e769 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -88,9 +88,9 @@ History: #include #include #include +#include #include -#include #include #define _IBM_LANA_DRIVER_ @@ -885,14 +885,6 @@ static struct net_device_stats *ibmlana_stats(struct net_device *dev) return &priv->stat; } -/* we don't support runtime reconfiguration, since am MCA card can - be unambigously identified by its POS registers. */ - -static int ibmlana_config(struct net_device *dev, struct ifmap *map) -{ - return 0; -} - /* switch receiver mode. */ static void ibmlana_set_multicast_list(struct net_device *dev) @@ -984,7 +976,6 @@ static int ibmlana_probe(struct net_device *dev) dev->open = ibmlana_open; dev->stop = ibmlana_close; - dev->set_config = ibmlana_config; dev->hard_start_xmit = ibmlana_tx; dev->do_ioctl = NULL; dev->get_stats = ibmlana_stats; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 5fa162f6c..03a7295a3 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -2,8 +2,8 @@ /* */ /* IBM eServer i/pSeries Virtual Ethernet Device Driver */ /* Copyright (C) 2003 IBM Corp. */ -/* Dave Larson (larson1@us.ibm.com) */ -/* Santiago Leon (santil@us.ibm.com) */ +/* Originally written by Dave Larson (larson1@us.ibm.com) */ +/* Maintained by Santiago Leon (santil@us.ibm.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 */ @@ -96,6 +96,7 @@ static void ibmveth_proc_unregister_driver(void); static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*); #ifdef CONFIG_PROC_FS #define IBMVETH_PROC_DIR "ibmveth" @@ -104,11 +105,12 @@ static struct proc_dir_entry *ibmveth_proc_dir; static const char ibmveth_driver_name[] = "ibmveth"; static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; -static const char ibmveth_driver_version[] = "1.0"; +#define ibmveth_driver_version "1.03" -MODULE_AUTHOR("Dave Larson "); +MODULE_AUTHOR("Santiago Leon "); MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(ibmveth_driver_version); /* simple methods of getting data from the current rxq entry */ static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter) @@ -213,11 +215,12 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc free_index = pool->consumer_index++ % pool->size; index = pool->free_map[free_index]; - ibmveth_assert(index != 0xffff); + ibmveth_assert(index != IBM_VETH_INVALID_MAP); ibmveth_assert(pool->skbuff[index] == NULL); dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, DMA_FROM_DEVICE); + pool->free_map[free_index] = IBM_VETH_INVALID_MAP; pool->dma_addr[index] = dma_addr; pool->skbuff[index] = skb; @@ -232,6 +235,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); if(lpar_rc != H_Success) { + pool->free_map[free_index] = IBM_VETH_INVALID_MAP; pool->skbuff[index] = NULL; pool->consumer_index--; vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, DMA_FROM_DEVICE); @@ -239,7 +243,6 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc adapter->replenish_add_buff_failure++; break; } else { - pool->free_map[free_index] = 0xffff; buffers_added++; adapter->replenish_add_buff_success++; } @@ -269,7 +272,8 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); atomic_inc(&adapter->not_replenishing); - ibmveth_assert(atomic_read(&adapter->not_replenishing) == 1); + + ibmveth_schedule_replenishing(adapter); } /* kick the replenish tasklet if we need replenishing and it isn't already running */ @@ -528,7 +532,7 @@ static int ibmveth_open(struct net_device *netdev) ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); do { rc = h_free_logical_lan(adapter->vdev->unit_address); - } while H_isLongBusy(rc); + } while (H_isLongBusy(rc) || (rc == H_Busy)); ibmveth_cleanup(adapter); return rc; @@ -560,7 +564,7 @@ static int ibmveth_close(struct net_device *netdev) do { lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); - } while H_isLongBusy(lpar_rc); + } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy)); if(lpar_rc != H_Success) { @@ -597,7 +601,7 @@ static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo * } static u32 netdev_get_link(struct net_device *dev) { - return 0; + return 1; } static struct ethtool_ops netdev_ethtool_ops = { @@ -732,6 +736,8 @@ static int ibmveth_poll(struct net_device *netdev, int *budget) if(ibmveth_rxq_pending_buffer(adapter)) { struct sk_buff *skb; + rmb(); + if(!ibmveth_rxq_buffer_valid(adapter)) { wmb(); /* suggested by larson1 */ adapter->rx_invalid_buffer++; @@ -882,13 +888,16 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); if(!mac_addr_p) { - ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n"); + printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR " + "attribute\n", __FILE__, __LINE__); return 0; } mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0); if(!mcastFilterSize_p) { - ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n"); + printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find " + "VETH_MCAST_FILTER_SIZE attribute\n", + __FILE__, __LINE__); return 0; } diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h index 599d15b2f..51a470da9 100644 --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h @@ -77,6 +77,8 @@ #define IbmVethPool1DftCnt 256 #define IbmVethPool2DftCnt 256 +#define IBM_VETH_INVALID_MAP ((u16)0xffff) + struct ibmveth_buff_pool { u32 size; u32 index; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index a93cda669..e16f8b20a 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -506,7 +506,7 @@ static struct net_device_stats *ioc3_get_stats(struct net_device *dev) static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len) { - struct ethhdr *eh = skb->mac.ethernet; + struct ethhdr *eh = eth_hdr(skb); uint32_t csum, ehsum; unsigned int proto; struct iphdr *ih; @@ -1333,7 +1333,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) uint32_t csum, ehsum; uint16_t *eh; - /* The MAC header. skb->mac.ethernet seem the logic approach + /* The MAC header. skb->mac seem the logic approach to find the MAC header - except it's a NULL pointer ... */ eh = (uint16_t *) skb->data; diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index c5af0cb78..a02a2a25a 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #include #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 6ae10e514..84292c0e0 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -52,7 +52,7 @@ /*------------------------------------------------------------------*/ #include - +#include #include #include #include @@ -88,10 +88,10 @@ static struct usb_device_id dongles[] = { /* * Important note : - * Devices based on the SigmaTel chipset (0x66f, 0x4200) are not compliant - * with the USB-IrDA specification (and actually very very different), and - * there is no way this driver can support those devices, apart from - * a complete rewrite... + * Devices based on the SigmaTel chipset (0x66f, 0x4200) are not designed + * using the "USB-IrDA specification" (yes, there exist such a thing), and + * therefore not supported by this driver (don't add them above). + * There is a Linux driver, stir4200, that support those USB devices. * Jean II */ @@ -268,7 +268,6 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) speed_bulk_callback, self); urb->transfer_buffer_length = USB_IRDA_HEADER; urb->transfer_flags = URB_ASYNC_UNLINK; - urb->timeout = msecs_to_jiffies(100); /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { @@ -411,8 +410,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) * after each of our packets that is exact multiple of the frame size. * This is how the dongle will detect the end of packet - Jean II */ urb->transfer_flags |= URB_ZERO_PACKET; - /* Timeout need to be shorter than NET watchdog timer */ - urb->timeout = msecs_to_jiffies(200); /* Generate min turn time. FIXME: can we do better than this? */ /* Trying to a turnaround time at this level is trying to measure @@ -1010,9 +1007,9 @@ static int irda_usb_net_close(struct net_device *netdev) } /* Cancel Tx and speed URB - need to be synchronous to avoid races */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->tx_urb); + usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->speed_urb); + usb_kill_urb(self->speed_urb); /* Stop and remove instance of IrLAP */ if (self->irlap) @@ -1523,9 +1520,9 @@ static void irda_usb_disconnect(struct usb_interface *intf) /* Cancel Tx and speed URB. * Toggle flags to make sure it's synchronous. */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->tx_urb); + usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(self->speed_urb); + usb_kill_urb(self->speed_urb); } /* Cleanup the device stuff */ @@ -1596,7 +1593,7 @@ module_exit(usb_irda_cleanup); /* * Module parameters */ -MODULE_PARM(qos_mtt_bits, "i"); +module_param(qos_mtt_bits, int, 0); MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); MODULE_AUTHOR("Roman Weissgaerber , Dag Brattli and Jean Tourrilhes "); MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 6ad80edb2..c2c26b605 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -51,9 +51,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index b67441d0a..1a7dff948 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -234,7 +234,7 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t } else writelen = len; - return tty->driver->write(tty, 0, ptr, writelen); + return tty->driver->write(tty, ptr, writelen); } /* ------------------------------------------------------- */ @@ -509,13 +509,6 @@ static int irtty_open(struct tty_struct *tty) if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); -/* from old irtty - but what is it good for? - * we _are_ the ldisc and we _don't_ implement flush_buffer! - * - * if (tty->ldisc.flush_buffer) - * tty->ldisc.flush_buffer(tty); - */ - /* apply mtt override */ sir_tty_drv.qos_mtt_bits = qos_mtt_bits; diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index c1e79f516..480454f65 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -351,8 +351,9 @@ static int __init nsc_ircc_open(int i, chipio_t *info) } MESSAGE("IrDA: Registered device %s\n", dev->name); - /* Check if user has supplied the dongle id or not */ - if (!dongle_id) { + /* Check if user has supplied a valid dongle id or not */ + if ((dongle_id <= 0) || + (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); MESSAGE("%s, Found dongle: %s\n", driver_name, diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index c4b7b2a27..89f5096ca 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c @@ -39,19 +39,7 @@ #include #include #include -#include - -#include -#include -#include - -#ifndef GPIO_IRDA_FIR -#define GPIO_IRDA_FIR (0) -#endif - -#ifndef GPIO_IRDA_POWER -#define GPIO_IRDA_POWER (0) -#endif +#include static int power_level = 3; static int tx_lpm; @@ -75,6 +63,7 @@ struct sa1100_irda { struct net_device_stats stats; struct device *dev; + struct irda_platform_data *pdata; struct irlap_cb *irlap; struct qos_info qos; @@ -170,12 +159,8 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed) Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE; - if (machine_is_assabet()) - ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL); - if (machine_is_h3xxx()) - clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - if (machine_is_yopy()) - PPSR &= ~GPIO_IRDA_FIR; + if (si->pdata->set_speed) + si->pdata->set_speed(si->dev, speed); si->speed = speed; @@ -194,12 +179,8 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed) si->speed = speed; - if (machine_is_assabet()) - ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL); - if (machine_is_h3xxx()) - set_h3600_egpio(IPAQ_EGPIO_IR_FSEL); - if (machine_is_yopy()) - PPSR |= GPIO_IRDA_FIR; + if (si->pdata->set_speed) + si->pdata->set_speed(si->dev, speed); sa1100_irda_rx_alloc(si); sa1100_irda_rx_dma_start(si); @@ -215,51 +196,6 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed) return ret; } -/* - * This sets the IRDA power level on the Assabet. - */ -static inline int -sa1100_irda_set_power_assabet(struct sa1100_irda *si, unsigned int state) -{ - static unsigned int bcr_state[4] = { - ASSABET_BCR_IRDA_MD0, - ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0, - ASSABET_BCR_IRDA_MD1, - 0 - }; - - if (state < 4) { - state = bcr_state[state]; - ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1| - ASSABET_BCR_IRDA_MD0)); - ASSABET_BCR_set(state); - } - return 0; -} - -/* - * This turns the IRDA power on or off on the Compaq H3600 - */ -static inline int -sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state) -{ - assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state ); - return 0; -} - -/* - * This turns the IRDA power on or off on the Yopy - */ -static inline int -sa1100_irda_set_power_yopy(struct sa1100_irda *si, unsigned int state) -{ - if (state) - PPSR &= ~GPIO_IRDA_POWER; - else - PPSR |= GPIO_IRDA_POWER; - return 0; -} - /* * Control the power state of the IrDA transmitter. * State: @@ -274,14 +210,8 @@ static int __sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state) { int ret = 0; - - if (machine_is_assabet()) - ret = sa1100_irda_set_power_assabet(si, state); - if (machine_is_h3xxx()) - ret = sa1100_irda_set_power_h3600(si, state); - if (machine_is_yopy()) - ret = sa1100_irda_set_power_yopy(si, state); - + if (si->pdata->set_power) + ret = si->pdata->set_power(si->dev, state); return ret; } @@ -304,11 +234,8 @@ static int sa1100_irda_startup(struct sa1100_irda *si) /* * Ensure that the ports for this device are setup correctly. */ - if (machine_is_yopy()) { - PPDR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - PPSR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - PSDR |= GPIO_IRDA_POWER | GPIO_IRDA_FIR; - } + if (si->pdata->startup) + si->pdata->startup(si->dev); /* * Configure PPC for IRDA - we want to drive TXD2 low. @@ -333,10 +260,15 @@ static int sa1100_irda_startup(struct sa1100_irda *si) Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; ret = sa1100_irda_set_speed(si, si->speed = 9600); - if (ret) - return ret; + if (ret) { + Ser2UTCR3 = 0; + Ser2HSCR0 = 0; - return 0; + if (si->pdata->shutdown) + si->pdata->shutdown(si->dev); + } + + return ret; } static void sa1100_irda_shutdown(struct sa1100_irda *si) @@ -350,6 +282,9 @@ static void sa1100_irda_shutdown(struct sa1100_irda *si) /* Disable the port. */ Ser2UTCR3 = 0; Ser2HSCR0 = 0; + + if (si->pdata->shutdown) + si->pdata->shutdown(si->dev); } #ifdef CONFIG_PM @@ -959,6 +894,9 @@ static int sa1100_irda_probe(struct device *_dev) unsigned int baudrate_mask; int err; + if (!pdev->dev.platform_data) + return -EINVAL; + err = request_mem_region(__PREG(Ser2UTCR0), 0x24, "IrDA") ? 0 : -EBUSY; if (err) goto err_mem_1; @@ -975,6 +913,7 @@ static int sa1100_irda_probe(struct device *_dev) si = dev->priv; si->dev = &pdev->dev; + si->pdata = pdev->dev.platform_data; /* * Initialise the HP-SIR buffers @@ -1028,7 +967,7 @@ static int sa1100_irda_probe(struct device *_dev) err = register_netdev(dev); if (err == 0) - dev_set_drvdata(&pdev->dev, si); + dev_set_drvdata(&pdev->dev, dev); if (err) { err_mem_5: @@ -1074,15 +1013,8 @@ static struct device_driver sa1100ir_driver = { .resume = sa1100_irda_resume, }; -static struct platform_device sa1100ir_device = { - .name = "sa11x0-ir", - .id = 0, -}; - static int __init sa1100_irda_init(void) { - int ret; - /* * Limit power level a sensible range. */ @@ -1091,19 +1023,12 @@ static int __init sa1100_irda_init(void) if (power_level > 3) power_level = 3; - ret = driver_register(&sa1100ir_driver); - if (ret == 0) { - ret = platform_device_register(&sa1100ir_device); - if (ret) - driver_unregister(&sa1100ir_driver); - } - return ret; + return driver_register(&sa1100ir_driver); } static void __exit sa1100_irda_exit(void) { driver_unregister(&sa1100ir_driver); - platform_device_unregister(&sa1100ir_device); } module_init(sa1100_irda_init); diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 81282d94f..f80a19e83 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -520,11 +520,6 @@ static int change_speed(struct stir_cb *stir, unsigned speed) found: pr_debug("speed change from %d to %d\n", stir->speed, speed); - /* sometimes needed to get chip out of stuck state */ - err = usb_reset_device(stir->usbdev); - if (err) - goto out; - /* Reset modulator */ err = write_reg(stir, REG_CTRL1, CTRL1_SRESET); if (err) @@ -575,7 +570,7 @@ static int change_speed(struct stir_cb *stir, unsigned speed) */ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct stir_cb *stir = netdev->priv; + struct stir_cb *stir = netdev_priv(netdev); netif_stop_queue(netdev); @@ -710,7 +705,7 @@ static int receive_start(struct stir_cb *stir) static void receive_stop(struct stir_cb *stir) { stir->receiving = 0; - usb_unlink_urb(stir->rx_urb); + usb_kill_urb(stir->rx_urb); if (stir->rx_buff.in_frame) stir->stats.collisions++; @@ -766,8 +761,9 @@ static int stir_transmit_thread(void *arg) && netif_device_present(dev) && !signal_pending(current)) { +#ifdef CONFIG_PM /* if suspending, then power off and wait */ - if (current->flags & PF_FREEZE) { + if (unlikely(current->flags & PF_FREEZE)) { if (stir->receiving) receive_stop(stir); else @@ -780,6 +776,7 @@ static int stir_transmit_thread(void *arg) if (change_speed(stir, stir->speed)) break; } +#endif /* if something to send? */ skb = xchg(&stir->tx_pending, NULL); @@ -874,7 +871,7 @@ static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs) */ static int stir_net_open(struct net_device *netdev) { - struct stir_cb *stir = netdev->priv; + struct stir_cb *stir = netdev_priv(netdev); int err; char hwname[16]; @@ -927,7 +924,7 @@ static int stir_net_open(struct net_device *netdev) sprintf(hwname, "usb#%d", stir->usbdev->devnum); stir->irlap = irlap_open(netdev, &stir->qos, hwname); if (!stir->irlap) { - err("irlap_open failed"); + err("stir4200: irlap_open failed"); goto err_out5; } @@ -936,7 +933,7 @@ static int stir_net_open(struct net_device *netdev) CLONE_FS|CLONE_FILES); if (stir->thr_pid < 0) { err = stir->thr_pid; - err("unable to start kernel thread"); + err("stir4200: unable to start kernel thread"); goto err_out6; } @@ -966,7 +963,7 @@ static int stir_net_open(struct net_device *netdev) */ static int stir_net_close(struct net_device *netdev) { - struct stir_cb *stir = netdev->priv; + struct stir_cb *stir = netdev_priv(netdev); /* Stop transmit processing */ netif_stop_queue(netdev); @@ -977,7 +974,7 @@ static int stir_net_close(struct net_device *netdev) kfree(stir->fifo_status); /* Mop up receive urb's */ - usb_unlink_urb(stir->rx_urb); + usb_kill_urb(stir->rx_urb); kfree(stir->io_buf); usb_free_urb(stir->rx_urb); @@ -995,10 +992,10 @@ static int stir_net_close(struct net_device *netdev) /* * IOCTLs : Extra out-of-band network commands... */ -static int stir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int stir_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) { struct if_irda_req *irq = (struct if_irda_req *) rq; - struct stir_cb *stir = dev->priv; + struct stir_cb *stir = netdev_priv(netdev); int ret = 0; switch (cmd) { @@ -1035,9 +1032,9 @@ static int stir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) /* * Get device stats (for /proc/net/dev and ifconfig) */ -static struct net_device_stats *stir_net_get_stats(struct net_device *dev) +static struct net_device_stats *stir_net_get_stats(struct net_device *netdev) { - struct stir_cb *stir = dev->priv; + struct stir_cb *stir = netdev_priv(netdev); return &stir->stats; } @@ -1063,13 +1060,13 @@ static int stir_probe(struct usb_interface *intf, SET_MODULE_OWNER(net); SET_NETDEV_DEV(net, &intf->dev); - stir = net->priv; + stir = netdev_priv(net); stir->netdev = net; stir->usbdev = dev; ret = usb_reset_configuration(dev); if (ret != 0) { - err("usb reset configuration failed"); + err("stir4200: usb reset configuration failed"); goto err_out2; } @@ -1102,7 +1099,7 @@ static int stir_probe(struct usb_interface *intf, if (ret != 0) goto err_out2; - MESSAGE("IrDA: Registered SigmaTel device %s\n", net->name); + info("IrDA: Registered SigmaTel device %s", net->name); usb_set_intfdata(intf, stir); @@ -1130,7 +1127,7 @@ static void stir_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); } - +#ifdef CONFIG_PM /* Power management suspend, so power off the transmitter/receiver */ static int stir_suspend(struct usb_interface *intf, u32 state) { @@ -1150,6 +1147,7 @@ static int stir_resume(struct usb_interface *intf) /* receiver restarted when send thread wakes up */ return 0; } +#endif /* * USB device callbacks @@ -1160,8 +1158,10 @@ static struct usb_driver irda_driver = { .probe = stir_probe, .disconnect = stir_disconnect, .id_table = dongles, +#ifdef CONFIG_PM .suspend = stir_suspend, .resume = stir_resume, +#endif }; /* @@ -1169,11 +1169,7 @@ static struct usb_driver irda_driver = { */ static int __init stir_init(void) { - if (usb_register(&irda_driver) < 0) - return -1; - - MESSAGE("SigmaTel support registered\n"); - return 0; + return usb_register(&irda_driver); } module_init(stir_init); diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 4d1000efe..feaaf3f9d 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -26,6 +26,16 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177. jul/09/2002 : only implement two kind of dongle currently. Oct/02/2002 : work on VT8231 and VT8233 . Aug/06/2003 : change driver format to pci driver . + +2004-02-16: +- Removed unneeded 'legacy' pci stuff. +- Make sure SIR mode is set (hw_init()) before calling mode-dependant stuff. +- On speed change from core, don't send SIR frame with new speed. + Use current speed and change speeds later. +- Make module-param dongle_id actually work. +- New dongle_id 17 (0x11): TDFS4500. Single-ended SIR only. + Tested with home-grown PCB on EPIA boards. +- Code cleanup. ********************************************************************/ #include @@ -53,35 +63,27 @@ F02 Oct/28/02: Add SB device ID for 3147 and 3177. #include "via-ircc.h" -//#define DBG_IO 1 -//#define DBGMSG 1 -//#define DBGMSG_96 1 -//#define DBGMSG_76 1 -//static int debug=0; - - -#define DBG(x) {if (debug) x;} +#define VIA_MODULE_NAME "via-ircc" +#define CHIP_IO_EXTENT 0x40 -#define VIA_MODULE_NAME "via-ircc" -#define CHIP_IO_EXTENT 8 -#define BROKEN_DONGLE_ID - -static char *driver_name = "via-ircc"; +static char *driver_name = VIA_MODULE_NAME; /* Module parameters */ static int qos_mtt_bits = 0x07; /* 1 ms or more */ -static int dongle_id = 9; //defalut IBM type +static int dongle_id = 0; /* default: probe */ -/* Resource is allocate by BIOS user only need to supply dongle_id*/ +/* We can't guess the type of connected dongle, user *must* supply it. */ MODULE_PARM(dongle_id, "i"); +/* FIXME : we should not need this, because instances should be automatically + * managed by the PCI layer. Especially that we seem to only be using the + * first entry. Jean II */ /* Max 4 instances for now */ static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; /* Some prototypes */ static int via_ircc_open(int i, chipio_t * info, unsigned int id); static int __exit via_ircc_close(struct via_ircc_cb *self); -static int via_ircc_setup(chipio_t * info, unsigned int id); static int via_ircc_dma_receive(struct via_ircc_cb *self); static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, int iobase); @@ -89,6 +91,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev); static int via_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev); +static void via_hw_init(struct via_ircc_cb *self); static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 baud); static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); @@ -110,7 +113,7 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase); static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id); static void __exit via_remove_one (struct pci_dev *pdev); -/* Should use udelay() instead, even if we are x86 only - Jean II */ +/* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */ static void iodelay(int udelay) { u8 data; @@ -122,11 +125,11 @@ static void iodelay(int udelay) } static struct pci_device_id via_pci_tbl[] = { - { PCI_VENDOR_ID_VIA, DeviceID1, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, - { PCI_VENDOR_ID_VIA, DeviceID2, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, - { PCI_VENDOR_ID_VIA, DeviceID3, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, - { PCI_VENDOR_ID_VIA, DeviceID4, PCI_ANY_ID, PCI_ANY_ID,0,0,3 }, - { PCI_VENDOR_ID_VIA, DeviceID5, PCI_ANY_ID, PCI_ANY_ID,0,0,4 }, + { PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, + { PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, + { PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, + { PCI_VENDOR_ID_VIA, 0x3147, PCI_ANY_ID, PCI_ANY_ID,0,0,3 }, + { PCI_VENDOR_ID_VIA, 0x3177, PCI_ANY_ID, PCI_ANY_ID,0,0,4 }, { 0, } }; @@ -150,22 +153,15 @@ static int __init via_ircc_init(void) { int rc; -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_ircc_init ......\n")); -#endif - rc = pci_register_driver (&via_driver); -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_ircc_init :rc = %d......\n",rc)); -#endif - if (rc < 1) { -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_ircc_init return -ENODEV......\n")); -#endif - if (rc == 0) pci_unregister_driver (&via_driver); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + + rc = pci_register_driver(&via_driver); + if (rc < 0) { + IRDA_DEBUG(0, "%s(): error rc = %d, returning -ENODEV...\n", + __FUNCTION__, rc); return -ENODEV; } return 0; - } static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id) @@ -174,33 +170,24 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1; u16 Chipset,FirDRQ1,FirDRQ0,FirIRQ,FirIOBase; chipio_t info; - -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one : Device ID=(0X%X)\n",id->device)); -#endif - if(id->device != DeviceID1 && id->device != DeviceID2 && - id->device != DeviceID3 && id->device != DeviceID4 && - id->device != DeviceID5 ){ -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one : Device ID(0X%X) not Supported\n",id->device)); -#endif - return -ENODEV; //South not exist !!!!! - } + + IRDA_DEBUG(2, "%s(): Device ID=(0X%X)\n", __FUNCTION__, id->device); + rc = pci_enable_device (pcidev); -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one : rc=%d\n",rc)); -#endif - if (rc) - return -ENODEV; - //South Bridge exist + if (rc) { + IRDA_DEBUG(0, "%s(): error rc = %d\n", __FUNCTION__, rc); + return -ENODEV; + } + + // South Bridge exist if ( ReadLPCReg(0x20) != 0x3C ) Chipset=0x3096; else Chipset=0x3076; + if (Chipset==0x3076) { -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one : 3076 ......\n")); -#endif + IRDA_DEBUG(2, "%s(): Chipset = 3076\n", __FUNCTION__); + WriteLPCReg(7,0x0c ); temp=ReadLPCReg(0x30);//check if BIOS Enable Fir if((temp&0x01)==1) { // BIOS close or no FIR @@ -236,9 +223,8 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi } else rc = -ENODEV; //IR not turn on } else { //Not VT1211 -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one : 3096 ......\n")); -#endif + IRDA_DEBUG(2, "%s(): Chipset = 3096\n", __FUNCTION__); + pci_read_config_byte(pcidev,0x67,&bTmp);//check if BIOS Enable Fir if((bTmp&0x01)==1) { // BIOS enable FIR //Enable Double DMA clock @@ -276,9 +262,8 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi } else rc = -ENODEV; //IR not turn on !!!!! }//Not VT1211 -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_init_one End : rc=%d\n",rc)); -#endif + + IRDA_DEBUG(2, "%s(): End - rc = %d\n", __FUNCTION__, rc); return rc; } @@ -292,9 +277,8 @@ static void __exit via_ircc_clean(void) { int i; -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_ircc_clean\n")); -#endif + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + for (i=0; i < 4; i++) { if (dev_self[i]) via_ircc_close(dev_self[i]); @@ -303,20 +287,29 @@ static void __exit via_ircc_clean(void) static void __exit via_remove_one (struct pci_dev *pdev) { -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_remove_one : ......\n")); -#endif + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + + /* FIXME : This is ugly. We should use pci_get_drvdata(pdev); + * to get our driver instance and call directly via_ircc_close(). + * See vlsi_ir for details... + * Jean II */ via_ircc_clean(); + /* FIXME : This should be in via_ircc_close(), because here we may + * theoritically disable still configured devices :-( - Jean II */ + pci_disable_device(pdev); } static void __exit via_ircc_cleanup(void) { + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); -#ifdef HEADMSG - DBG(printk(KERN_INFO "via_ircc_cleanup ......\n")); -#endif + /* FIXME : This should be redundant, as pci_unregister_driver() + * should call via_remove_one() on each device. + * Jean II */ via_ircc_clean(); + + /* Cleanup all instances of the driver */ pci_unregister_driver (&via_driver); } @@ -332,8 +325,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) struct via_ircc_cb *self; int err; - if ((via_ircc_setup(info, id)) == -1) - return -1; + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); /* Allocate new instance of the driver */ dev = alloc_irdadev(sizeof(struct via_ircc_cb)); @@ -344,6 +336,10 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) self->netdev = dev; spin_lock_init(&self->lock); + /* FIXME : We should store our driver instance in the PCI layer, + * using pci_set_drvdata(), not in this array. + * See vlsi_ir for details... - Jean II */ + /* FIXME : 'i' is always 0 (see via_init_one()) :-( - Jean II */ /* Need to store self somewhere */ dev_self[i] = self; self->index = i; @@ -361,19 +357,40 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) /* Reserve the ioports that we need */ if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) { -// WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__, self->io.fir_base); + IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n", + __FUNCTION__, self->io.fir_base); err = -ENODEV; goto err_out1; } /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&self->qos); + + /* Check if user has supplied the dongle id or not */ + if (!dongle_id) + dongle_id = via_ircc_read_dongle_id(self->io.fir_base); + self->io.dongle_id = dongle_id; + /* The only value we must override it the baudrate */ -// self->qos.baud_rate.bits = IR_9600;// May use this for testing + /* Maximum speeds and capabilities are dongle-dependant. */ + switch( self->io.dongle_id ){ + case 0x0d: + self->qos.baud_rate.bits = + IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | + IR_576000 | IR_1152000 | (IR_4000000 << 8); + break; + default: + self->qos.baud_rate.bits = + IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; + break; + } - self->qos.baud_rate.bits = - IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | - IR_576000 | IR_1152000 | (IR_4000000 << 8); + /* Following was used for testing: + * + * self->qos.baud_rate.bits = IR_9600; + * + * Is is no good, as it prohibits (error-prone) speed-changes. + */ self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); @@ -424,15 +441,12 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) if (err) goto err_out4; - MESSAGE("IrDA: Registered device %s\n", dev->name); - - /* Check if user has supplied the dongle id or not */ - if (!dongle_id) - dongle_id = via_ircc_read_dongle_id(self->io.fir_base); - self->io.dongle_id = dongle_id; - via_ircc_change_dongle_speed(self->io.fir_base, 9600, - self->io.dongle_id); + MESSAGE("IrDA: Registered device %s (via-ircc)\n", dev->name); + /* Initialise the hardware.. + */ + self->io.speed = 9600; + via_hw_init(self); return 0; err_out4: dma_free_coherent(NULL, self->tx_buff.truesize, @@ -458,7 +472,7 @@ static int __exit via_ircc_close(struct via_ircc_cb *self) { int iobase; - IRDA_DEBUG(4, "%s()\n", __FUNCTION__); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); ASSERT(self != NULL, return -1;); @@ -469,7 +483,7 @@ static int __exit via_ircc_close(struct via_ircc_cb *self) unregister_netdev(self->netdev); /* Release the PORT that this driver is using */ - IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", + IRDA_DEBUG(2, "%s(), Releasing Region %03x\n", __FUNCTION__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) @@ -486,14 +500,17 @@ static int __exit via_ircc_close(struct via_ircc_cb *self) } /* - * Function via_ircc_setup (info) + * Function via_hw_init(self) * * Returns non-negative on success. * + * Formerly via_ircc_setup */ -static int via_ircc_setup(chipio_t * info, unsigned int chip_id) +static void via_hw_init(struct via_ircc_cb *self) { - int iobase = info->fir_base; + int iobase = self->io.fir_base; + + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); SetMaxRxPacketSize(iobase, 0x0fff); //set to max:4095 // FIFO Init @@ -504,22 +521,40 @@ static int via_ircc_setup(chipio_t * info, unsigned int chip_id) EnTXFIFOReadyInt(iobase, OFF); InvertTX(iobase, OFF); InvertRX(iobase, OFF); + if (ReadLPCReg(0x20) == 0x3c) WriteLPCReg(0xF0, 0); // for VT1211 - if (IsSIROn(iobase)) { - SIRFilter(iobase, ON); - SIRRecvAny(iobase, ON); - } else { - SIRFilter(iobase, OFF); - SIRRecvAny(iobase, OFF); - } - //Int Init + /* Int Init */ EnRXSpecInt(iobase, ON); - //DMA Init Later.... - WriteReg(iobase, I_ST_CT_0, 0x80); - EnableDMA(iobase, ON); - return 0; + /* The following is basically hwreset */ + /* If this is the case, why not just call hwreset() ? Jean II */ + ResetChip(iobase, 5); + EnableDMA(iobase, OFF); + EnableTX(iobase, OFF); + EnableRX(iobase, OFF); + EnRXDMA(iobase, OFF); + EnTXDMA(iobase, OFF); + RXStart(iobase, OFF); + TXStart(iobase, OFF); + InitCard(iobase); + CommonInit(iobase); + SIRFilter(iobase, ON); + SetSIR(iobase, ON); + CRC16(iobase, ON); + EnTXCRC(iobase, 0); + WriteReg(iobase, I_ST_CT_0, 0x00); + SetBaudRate(iobase, 9600); + SetPulseWidth(iobase, 12); + SetSendPreambleCount(iobase, 0); + + self->io.speed = 9600; + self->st_fifo.len = 0; + + via_ircc_change_dongle_speed(iobase, self->io.speed, + self->io.dongle_id); + + WriteReg(iobase, I_ST_CT_0, 0x80); } /* @@ -528,8 +563,9 @@ static int via_ircc_setup(chipio_t * info, unsigned int chip_id) */ static int via_ircc_read_dongle_id(int iobase) { - int dongle_id = 9; + int dongle_id = 9; /* Default to IBM */ + ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n"); return dongle_id; } @@ -543,22 +579,16 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, { u8 mode = 0; - WriteReg(iobase, I_ST_CT_0, 0x0); - switch (dongle_id) { //HP1100 - case 0x00: /* same as */ - case 0x01: /* Differential serial interface */ - break; - case 0x02: /* same as */ - case 0x03: /* Reserved */ - break; - case 0x04: /* Sharp RY5HD01 */ - break; - case 0x05: /* Reserved, but this is what the Thinkpad reports */ - break; - case 0x06: /* Single-ended serial interface */ - break; - case 0x07: /* Consumer-IR only */ - break; + /* speed is unused, as we use IsSIROn()/IsMIROn() */ + speed = speed; + + IRDA_DEBUG(1, "%s(): change_dongle_speed to %d for 0x%x, %d\n", + __FUNCTION__, speed, iobase, dongle_id); + + switch (dongle_id) { + + /* Note: The dongle_id's listed here are derived from + * nsc-ircc.c */ case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ UseOneRX(iobase, ON); // use one RX pin RX1,RX2 @@ -587,10 +617,12 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, } } break; + case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ UseOneRX(iobase, ON); //use ONE RX....RX1 InvertTX(iobase, OFF); InvertRX(iobase, OFF); // invert RX pin + EnRX2(iobase, ON); EnGPIOtoRX2(iobase, OFF); if (IsSIROn(iobase)) { //sir @@ -621,6 +653,7 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, } } break; + case 0x0d: UseOneRX(iobase, OFF); // use two RX pin RX1,RX2 InvertTX(iobase, OFF); @@ -636,6 +669,31 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, EnRX2(iobase, OFF); //fir to rx } break; + + case 0x11: /* Temic TFDS4500 */ + + IRDA_DEBUG(2, "%s: Temic TFDS4500: One RX pin, TX normal, RX inverted.\n", __FUNCTION__); + + UseOneRX(iobase, ON); //use ONE RX....RX1 + InvertTX(iobase, OFF); + InvertRX(iobase, ON); // invert RX pin + + EnRX2(iobase, ON); //sir to rx2 + EnGPIOtoRX2(iobase, OFF); + + if( IsSIROn(iobase) ){ //sir + + // Mode select On + SlowIRRXLowActive(iobase, ON); + udelay(20); + // Mode select Off + SlowIRRXLowActive(iobase, OFF); + + } else{ + IRDA_DEBUG(0, "%s: Warning: TFDS4500 not running in SIR mode !\n", __FUNCTION__); + } + break; + case 0x0ff: /* Vishay */ if (IsSIROn(iobase)) mode = 0; @@ -646,9 +704,12 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, else if (IsVFIROn(iobase)) mode = 5; //VFIR-16 SI_SetMode(iobase, mode); - } - WriteReg(iobase, I_ST_CT_0, 0x80); + break; + default: + ERROR("%s: Error: dongle_id %d unsupported !\n", + __FUNCTION__, dongle_id); + } } /* @@ -666,46 +727,25 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) iobase = self->io.fir_base; /* Update accounting for new speed */ self->io.speed = speed; -#ifdef DBGMSG - DBG(printk(KERN_INFO "change_speed =%x......\n", speed)); -#endif - -#ifdef DBG_IO - if (self->io.speed > 0x2580) - outb(0xaa, 0x90); - else - outb(0xbb, 0x90); -#endif + IRDA_DEBUG(1, "%s: change_speed to %d bps.\n", __FUNCTION__, speed); + WriteReg(iobase, I_ST_CT_0, 0x0); /* Controller mode sellection */ switch (speed) { + case 2400: case 9600: - value = 11; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; case 19200: - value = 5; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; case 38400: - value = 2; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; case 57600: - value = 1; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; case 115200: - value = 0; + value = (115200/speed)-1; SetSIR(iobase, ON); CRC16(iobase, ON); break; case 576000: + /* FIXME: this can't be right, as it's the same as 115200, + * and 576000 is MIR, not SIR. */ value = 0; SetSIR(iobase, ON); CRC16(iobase, ON); @@ -713,6 +753,7 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) case 1152000: value = 0; SetMIR(iobase, ON); + /* FIXME: CRC ??? */ break; case 4000000: value = 0; @@ -725,19 +766,29 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) case 16000000: value = 0; SetVFIR(iobase, ON); + /* FIXME: CRC ??? */ break; default: value = 0; break; } + /* Set baudrate to 0x19[2..7] */ bTmp = (ReadReg(iobase, I_CF_H_1) & 0x03); - bTmp = bTmp | (value << 2); + bTmp |= value << 2; WriteReg(iobase, I_CF_H_1, bTmp); + + /* Some dongles may need to be informed about speed changes. */ via_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id); -// EnTXFIFOHalfLevelInt(iobase,ON); + /* Set FIFO size to 64 */ SetFIFO(iobase, 64); + + /* Enable IR */ + WriteReg(iobase, I_ST_CT_0, 0x80); + + // EnTXFIFOHalfLevelInt(iobase,ON); + /* Enable some interrupts so we can receive frames */ //EnAllInt(iobase,ON); @@ -748,6 +799,7 @@ static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) SIRFilter(iobase, OFF); SIRRecvAny(iobase, OFF); } + if (speed > 115200) { /* Install FIR xmit handler */ dev->hard_start_xmit = via_ircc_hard_xmit_fir; @@ -805,7 +857,8 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb, self->tx_buff.truesize); self->stats.tx_bytes += self->tx_buff.len; - SetBaudRate(iobase, speed); + /* Send this frame with old speed */ + SetBaudRate(iobase, self->io.speed); SetPulseWidth(iobase, 12); SetSendPreambleCount(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x80); @@ -887,9 +940,6 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb, static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase) { -// int i; -// u8 *ch; - EnTXDMA(iobase, OFF); self->io.direction = IO_XMIT; EnPhys(iobase, ON); @@ -907,18 +957,10 @@ static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase) ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - self->tx_buff.head) + self->tx_buff_dma, self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); -#ifdef DBGMSG - DBG(printk - (KERN_INFO "dma_xmit:tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", - self->tx_fifo.ptr, self->tx_fifo.queue[self->tx_fifo.ptr].len, - self->tx_fifo.len)); -/* - ch = self->tx_fifo.queue[self->tx_fifo.ptr].start; - for(i=0 ; i < self->tx_fifo.queue[self->tx_fifo.ptr].len ; i++) { - DBG(printk(KERN_INFO "%x..\n",ch[i])); - } -*/ -#endif + IRDA_DEBUG(1, "%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", + __FUNCTION__, self->tx_fifo.ptr, + self->tx_fifo.queue[self->tx_fifo.ptr].len, + self->tx_fifo.len); SetSendByte(iobase, self->tx_fifo.queue[self->tx_fifo.ptr].len); RXStart(iobase, OFF); @@ -940,7 +982,8 @@ static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self) int ret = TRUE; u8 Tx_status; - IRDA_DEBUG(2, "%s()\n", __FUNCTION__); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + iobase = self->io.fir_base; /* Disable DMA */ // DisableDmaChannel(self->io.dma); @@ -970,12 +1013,10 @@ static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self) self->tx_fifo.ptr++; } } -#ifdef DBGMSG - DBG(printk - (KERN_INFO - "via_ircc_dma_xmit_complete:tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", - self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free)); -#endif + IRDA_DEBUG(1, + "%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", + __FUNCTION__, + self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free); /* F01_S // Any frames to be sent back-to-back? if (self->tx_fifo.len) { @@ -1010,6 +1051,8 @@ static int via_ircc_dma_receive(struct via_ircc_cb *self) iobase = self->io.fir_base; + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; self->tx_fifo.tail = self->tx_buff.head; self->RxDataReady = 0; @@ -1017,6 +1060,7 @@ static int via_ircc_dma_receive(struct via_ircc_cb *self) self->rx_buff.data = self->rx_buff.head; self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; + EnPhys(iobase, ON); EnableTX(iobase, OFF); EnableRX(iobase, ON); @@ -1090,22 +1134,16 @@ static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, if (len == 0) return TRUE; //interrupt only, data maybe move by RxT if (((len - 4) < 2) || ((len - 4) > 2048)) { -#ifdef DBGMSG - DBG(printk - (KERN_INFO - "receive_comple:Trouble:len=%x,CurCount=%x,LastCount=%x..\n", - len, RxCurCount(iobase, self), - self->RxLastCount)); -#endif + IRDA_DEBUG(1, "%s(): Trouble:len=%x,CurCount=%x,LastCount=%x..\n", + __FUNCTION__, len, RxCurCount(iobase, self), + self->RxLastCount); hwreset(self); return FALSE; } -#ifdef DBGMSG - DBG(printk - (KERN_INFO - "recv_comple:fifo.len=%x,len=%x,CurCount=%x..\n", - st_fifo->len, len - 4, RxCurCount(iobase, self))); -#endif + IRDA_DEBUG(2, "%s(): fifo.len=%x,len=%x,CurCount=%x..\n", + __FUNCTION__, + st_fifo->len, len - 4, RxCurCount(iobase, self)); + st_fifo->entries[st_fifo->tail].status = status; st_fifo->entries[st_fifo->tail].len = len; st_fifo->pending_bytes += len; @@ -1148,16 +1186,11 @@ F01_E */ } skb_reserve(skb, 1); skb_put(skb, len - 4); + memcpy(skb->data, self->rx_buff.data, len - 4); -#ifdef DBGMSG - DBG(printk - (KERN_INFO "RxT:len=%x.rx_buff=%x\n", len - 4, - self->rx_buff.data)); -/* for(i=0 ; i < (len-4) ; i++) { - DBG(printk(KERN_INFO "%x..\n",self->rx_buff.data[i])); - } -*/ -#endif + IRDA_DEBUG(2, "%s(): len=%x.rx_buff=%p\n", __FUNCTION__, + len - 4, self->rx_buff.data); + // Move to next frame self->rx_buff.data += len; self->stats.rx_bytes += len; @@ -1185,9 +1218,8 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase) len = GetRecvByte(iobase, self); -#ifdef DBGMSG - DBG(printk(KERN_INFO "upload_rxdata: len=%x\n", len)); -#endif + IRDA_DEBUG(2, "%s(): len=%x\n", __FUNCTION__, len); + skb = dev_alloc_skb(len + 1); if ((skb == NULL) || ((len - 4) < 2)) { self->stats.rx_dropped++; @@ -1265,11 +1297,10 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase) skb_reserve(skb, 1); skb_put(skb, len - 4); memcpy(skb->data, self->rx_buff.data, len - 4); -#ifdef DBGMSG - DBG(printk - (KERN_INFO "RxT:len=%x.head=%x\n", len - 4, - st_fifo->head)); -#endif + + IRDA_DEBUG(2, "%s(): len=%x.head=%x\n", __FUNCTION__, + len - 4, st_fifo->head); + // Move to next frame self->rx_buff.data += len; self->stats.rx_bytes += len; @@ -1280,12 +1311,12 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase) netif_rx(skb); } //while self->RetryCount = 0; -#ifdef DBGMSG - DBG(printk - (KERN_INFO - "RxT:End of upload HostStatus=%x,RxStatus=%x\n", - GetHostStatus(iobase), GetRXStatus(iobase))); -#endif + + IRDA_DEBUG(2, + "%s(): End of upload HostStatus=%x,RxStatus=%x\n", + __FUNCTION__, + GetHostStatus(iobase), GetRXStatus(iobase)); + /* * if frame is receive complete at this routine ,then upload * frame. @@ -1328,6 +1359,14 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, iobase = self->io.fir_base; spin_lock(&self->lock); iHostIntType = GetHostStatus(iobase); + + IRDA_DEBUG(4, "%s(): iHostIntType %02x: %s %s %s %02x\n", + __FUNCTION__, iHostIntType, + (iHostIntType & 0x40) ? "Timer" : "", + (iHostIntType & 0x20) ? "Tx" : "", + (iHostIntType & 0x10) ? "Rx" : "", + (iHostIntType & 0x0e) >> 1); + if ((iHostIntType & 0x40) != 0) { //Timer Event self->EventFlag.TimeOut++; ClearTimerInt(iobase, 1); @@ -1340,8 +1379,7 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, */ if (self->RxDataReady > 30) { hwreset(self); - if (irda_device_txqueue_empty - (self->netdev)) { + if (irda_device_txqueue_empty(self->netdev)) { via_ircc_dma_receive(self); } } else { // call this to upload frame. @@ -1351,6 +1389,14 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, } //Timer Event if ((iHostIntType & 0x20) != 0) { //Tx Event iTxIntType = GetTXStatus(iobase); + + IRDA_DEBUG(4, "%s(): iTxIntType %02x: %s %s %s %s\n", + __FUNCTION__, iTxIntType, + (iTxIntType & 0x08) ? "FIFO underr." : "", + (iTxIntType & 0x04) ? "EOM" : "", + (iTxIntType & 0x02) ? "FIFO ready" : "", + (iTxIntType & 0x01) ? "Early EOM" : ""); + if (iTxIntType & 0x4) { self->EventFlag.EOMessage++; // read and will auto clean if (via_ircc_dma_xmit_complete(self)) { @@ -1367,10 +1413,19 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, if ((iHostIntType & 0x10) != 0) { //Rx Event /* Check if DMA has finished */ iRxIntType = GetRXStatus(iobase); -#ifdef DBGMSG + + IRDA_DEBUG(4, "%s(): iRxIntType %02x: %s %s %s %s %s %s %s\n", + __FUNCTION__, iRxIntType, + (iRxIntType & 0x80) ? "PHY err." : "", + (iRxIntType & 0x40) ? "CRC err" : "", + (iRxIntType & 0x20) ? "FIFO overr." : "", + (iRxIntType & 0x10) ? "EOF" : "", + (iRxIntType & 0x08) ? "RxData" : "", + (iRxIntType & 0x02) ? "RxMaxLen" : "", + (iRxIntType & 0x01) ? "SIR bad" : ""); if (!iRxIntType) - DBG(printk(KERN_INFO " RxIRQ =0\n")); -#endif + IRDA_DEBUG(3, "%s(): RxIRQ =0\n", __FUNCTION__); + if (iRxIntType & 0x10) { if (via_ircc_dma_receive_complete(self, iobase)) { //F01 if(!(IsFIROn(iobase))) via_ircc_dma_receive(self); @@ -1378,14 +1433,11 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id, } } // No ERR else { //ERR -#ifdef DBGMSG - DBG(printk - (KERN_INFO - " RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", - iRxIntType, iHostIntType, RxCurCount(iobase, - self), - self->RxLastCount)); -#endif + IRDA_DEBUG(4, "%s(): RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", + __FUNCTION__, iRxIntType, iHostIntType, + RxCurCount(iobase, self), + self->RxLastCount); + if (iRxIntType & 0x20) { //FIFO OverRun ERR ResetChip(iobase, 0); ResetChip(iobase, 1); @@ -1406,9 +1458,9 @@ static void hwreset(struct via_ircc_cb *self) { int iobase; iobase = self->io.fir_base; -#ifdef DBGMSG - DBG(printk(KERN_INFO "hwreset ....\n")); -#endif + + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); + ResetChip(iobase, 5); EnableDMA(iobase, OFF); EnableTX(iobase, OFF); @@ -1428,7 +1480,10 @@ static void hwreset(struct via_ircc_cb *self) SetPulseWidth(iobase, 12); SetSendPreambleCount(iobase, 0); WriteReg(iobase, I_ST_CT_0, 0x80); + + /* Restore speed. */ via_ircc_change_speed(self, self->io.speed); + self->st_fifo.len = 0; } @@ -1448,9 +1503,9 @@ static int via_ircc_is_receiving(struct via_ircc_cb *self) iobase = self->io.fir_base; if (CkRxRecv(iobase, self)) status = TRUE; -#ifdef DBGMSG - DBG(printk(KERN_INFO "is_receiving status=%x....\n", status)); -#endif + + IRDA_DEBUG(2, "%s(): status=%x....\n", __FUNCTION__, status); + return status; } @@ -1467,15 +1522,14 @@ static int via_ircc_net_open(struct net_device *dev) int iobase; char hwname[32]; - IRDA_DEBUG(4, "%s()\n", __FUNCTION__); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = (struct via_ircc_cb *) dev->priv; self->stats.rx_packets = 0; ASSERT(self != NULL, return 0;); iobase = self->io.fir_base; - if (request_irq - (self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) { + if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) { WARNING("%s, unable to allocate irq=%d\n", driver_name, self->io.irq); return -EAGAIN; @@ -1504,6 +1558,10 @@ static int via_ircc_net_open(struct net_device *dev) EnAllInt(iobase, ON); EnInternalLoop(iobase, OFF); EnExternalLoop(iobase, OFF); + + /* */ + via_ircc_dma_receive(self); + /* Ready to play! */ netif_start_queue(dev); @@ -1511,12 +1569,8 @@ static int via_ircc_net_open(struct net_device *dev) * Open new IrLAP layer instance, now that everything should be * initialized properly */ - sprintf(hwname, "VIA"); - /* - * for different kernel ,irlap_open have different parameter. - */ + sprintf(hwname, "VIA @ 0x%x", iobase); self->irlap = irlap_open(dev, &self->qos, hwname); -// self->irlap = irlap_open(dev, &self->qos); self->RxLastCount = 0; @@ -1534,16 +1588,12 @@ static int via_ircc_net_close(struct net_device *dev) struct via_ircc_cb *self; int iobase; - IRDA_DEBUG(4, "%s()\n", __FUNCTION__); + IRDA_DEBUG(3, "%s()\n", __FUNCTION__); ASSERT(dev != NULL, return -1;); self = (struct via_ircc_cb *) dev->priv; ASSERT(self != NULL, return 0;); -#ifdef DBG_IO - outb(0xff, 0x90); - outb(0xff, 0x94); -#endif /* Stop device */ netif_stop_queue(dev); /* Stop and remove instance of IrLAP */ @@ -1580,7 +1630,7 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, ASSERT(dev != NULL, return -1;); self = dev->priv; ASSERT(self != NULL, return -1;); - IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, + IRDA_DEBUG(1, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); /* Disable interrupts & save flags */ spin_lock_irqsave(&self->lock, flags); diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h index dcb5c3d33..204b1b34f 100644 --- a/drivers/net/irda/via-ircc.h +++ b/drivers/net/irda/via-ircc.h @@ -170,17 +170,6 @@ struct via_ircc_cb { // Sets bit to 1 #define ResetBit(val,bit) val= (unsigned char ) (val & ~(0x1 << bit)) // Sets bit to 0 -#define PCI_CONFIG_ADDRESS 0xcf8 -#define PCI_CONFIG_DATA 0xcfc - -#define VenderID 0x1106 -#define DeviceID1 0x8231 -#define DeviceID2 0x3109 -#define DeviceID3 0x3074 -//F01_S -#define DeviceID4 0x3147 -#define DeviceID5 0x3177 -//F01_E #define OFF 0 #define ON 1 @@ -794,7 +783,7 @@ static void SetBaudRate(__u16 iobase, __u32 rate) value = 0; // will automatically be fixed in 4M } temp = (ReadReg(iobase, I_CF_H_1) & 0x03); - temp = temp | (value << 2); + temp |= value << 2; WriteReg(iobase, I_CF_H_1, temp); } @@ -805,9 +794,9 @@ static void SetPulseWidth(__u16 iobase, __u8 width) temp = (ReadReg(iobase, I_CF_L_1) & 0x1f); temp1 = (ReadReg(iobase, I_CF_H_1) & 0xfc); temp2 = (width & 0x07) << 5; - temp = temp | temp2; + temp |= temp2; temp2 = (width & 0x18) >> 3; - temp1 = temp1 | temp2; + temp1 |= temp2; WriteReg(iobase, I_CF_L_1, temp); WriteReg(iobase, I_CF_H_1, temp1); } @@ -817,7 +806,7 @@ static void SetSendPreambleCount(__u16 iobase, __u8 count) __u8 temp; temp = ReadReg(iobase, I_CF_L_1) & 0xe0; - temp = temp | count; + temp |= count; WriteReg(iobase, I_CF_L_1, temp); } diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index eda2d01a5..5ee2550ff 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1768,7 +1768,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state) if (netif_running(ndev)) { netif_device_detach(ndev); vlsi_stop_hw(idev); - pci_save_state(pdev, idev->cfg_space); + pci_save_state(pdev); if (!idev->new_baud) /* remember speed settings to restore on resume */ idev->new_baud = idev->baud; @@ -1819,7 +1819,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev) } if (netif_running(ndev)) { - pci_restore_state(pdev, idev->cfg_space); + pci_restore_state(pdev); vlsi_start_hw(idev); netif_device_attach(ndev); } diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 55e4a7f34..1e947e6ad 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h @@ -769,7 +769,6 @@ typedef struct vlsi_irda_dev { spinlock_t lock; struct semaphore sem; - u32 cfg_space[64/sizeof(u32)]; u8 resume_ok; struct proc_dir_entry *proc_entry; diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index 650943395..50bebb55e 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -55,9 +55,9 @@ static const char *version = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index e62ca7b1b..43ef7951e 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -248,7 +248,7 @@ static int veth_allocate_events(HvLpIndex rlp, int number) { struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 }; - mf_allocateLpEvents(rlp, HvLpEvent_Type_VirtualLan, + mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, sizeof(struct VethLpEvent), number, &veth_complete_allocation, &vc); wait_for_completion(&vc.c); @@ -662,12 +662,12 @@ static void veth_destroy_connection(u8 rlp) del_timer_sync(&cnx->ack_timer); if (cnx->num_events > 0) - mf_deallocateLpEvents(cnx->remote_lp, + mf_deallocate_lp_events(cnx->remote_lp, HvLpEvent_Type_VirtualLan, cnx->num_events, NULL, NULL); if (cnx->num_ack_events > 0) - mf_deallocateLpEvents(cnx->remote_lp, + mf_deallocate_lp_events(cnx->remote_lp, HvLpEvent_Type_VirtualLan, cnx->num_ack_events, NULL, NULL); @@ -747,60 +747,41 @@ static void veth_set_multicast_list(struct net_device *dev) write_unlock_irqrestore(&port->mcast_gate, flags); } -static int veth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { -#ifdef SIOCETHTOOL - struct ethtool_cmd ecmd; - - if (cmd != SIOCETHTOOL) - return -EOPNOTSUPP; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = (SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - ecmd.advertising = (SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - ecmd.port = PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = 0; - ecmd.speed = SPEED_1000; - ecmd.duplex = DUPLEX_FULL; - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.maxtxpkt = 120; - ecmd.maxrxpkt = 120; - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strncpy(info.driver, "veth", sizeof(info.driver) - 1); - info.driver[sizeof(info.driver) - 1] = '\0'; - strncpy(info.version, "1.0", sizeof(info.version) - 1); - if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - return 0; - } - /* get link status */ - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = 1; - if (copy_to_user(ifr->ifr_data, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + strncpy(info->driver, "veth", sizeof(info->driver) - 1); + info->driver[sizeof(info->driver) - 1] = '\0'; + strncpy(info->version, "1.0", sizeof(info->version) - 1); +} - default: - break; - } +static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + ecmd->supported = (SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + ecmd->advertising = (SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = 0; + ecmd->speed = SPEED_1000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->maxtxpkt = 120; + ecmd->maxrxpkt = 120; + return 0; +} -#endif - return -EOPNOTSUPP; +static u32 veth_get_link(struct net_device *dev) +{ + return 1; } +static struct ethtool_ops ops = { + .get_drvinfo = veth_get_drvinfo, + .get_settings = veth_get_settings, + .get_link = veth_get_link, +}; + static void veth_tx_timeout(struct net_device *dev) { struct veth_port *port = (struct veth_port *)dev->priv; @@ -889,7 +870,7 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) dev->change_mtu = veth_change_mtu; dev->set_mac_address = NULL; dev->set_multicast_list = veth_set_multicast_list; - dev->do_ioctl = veth_ioctl; + SET_ETHTOOL_OPS(dev, &ops); dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000); dev->tx_timeout = veth_tx_timeout; diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 5111c8e6b..d5c6f477f 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -178,6 +178,5 @@ struct ixgb_adapter { /* structs defined in ixgb_hw.h */ struct ixgb_hw hw; struct ixgb_hw_stats stats; - uint32_t pci_state[16]; }; #endif /* _IXGB_H_ */ diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index 605a6873e..e455a5f32 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -38,12 +38,6 @@ extern char ixgb_driver_version[]; extern int ixgb_up(struct ixgb_adapter *adapter); extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); -static inline int ixgb_eeprom_size(struct ixgb_hw *hw) -{ - /* return size in bytes */ - return (IXGB_EEPROM_SIZE << 1); -} - struct ixgb_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -94,9 +88,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = { #define IXGB_STATS_LEN \ sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats) -static void -ixgb_ethtool_gset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) +static int +ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd) { + struct ixgb_adapter *adapter = netdev->priv; ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->port = PORT_FIBRE; @@ -111,11 +106,13 @@ ixgb_ethtool_gset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) } ecmd->autoneg = AUTONEG_DISABLE; + return 0; } static int -ixgb_ethtool_sset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) +ixgb_ethtool_sset(struct net_device *netdev, struct ethtool_cmd *ecmd) { + struct ixgb_adapter *adapter = netdev->priv; if (ecmd->autoneg == AUTONEG_ENABLE || ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) return -EINVAL; @@ -123,14 +120,14 @@ ixgb_ethtool_sset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) ixgb_down(adapter, TRUE); ixgb_up(adapter); } - return 0; } -static int -ixgb_ethtool_gpause(struct ixgb_adapter *adapter, +static void +ixgb_ethtool_gpause(struct net_device *dev, struct ethtool_pauseparam *epause) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; epause->autoneg = AUTONEG_DISABLE; @@ -143,14 +140,13 @@ ixgb_ethtool_gpause(struct ixgb_adapter *adapter, epause->rx_pause = 1; epause->tx_pause = 1; } - - return 0; } static int -ixgb_ethtool_spause(struct ixgb_adapter *adapter, +ixgb_ethtool_spause(struct net_device *dev, struct ethtool_pauseparam *epause) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; if (epause->autoneg == AUTONEG_ENABLE) @@ -172,26 +168,23 @@ ixgb_ethtool_spause(struct ixgb_adapter *adapter, } static void -ixgb_ethtool_gdrvinfo(struct ixgb_adapter *adapter, +ixgb_ethtool_gdrvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { + struct ixgb_adapter *adapter = netdev->priv; strncpy(drvinfo->driver, ixgb_driver_name, 32); strncpy(drvinfo->version, ixgb_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); - drvinfo->n_stats = IXGB_STATS_LEN; -#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t) - drvinfo->regdump_len = IXGB_REG_DUMP_LEN; - drvinfo->eedump_len = ixgb_eeprom_size(&adapter->hw); } #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_ static void -ixgb_ethtool_gregs(struct ixgb_adapter *adapter, - struct ethtool_regs *regs, uint32_t * regs_buff) +ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - uint32_t *reg = regs_buff; + uint32_t *reg = buf; uint32_t *reg_start = reg; uint8_t i; @@ -323,69 +316,37 @@ ixgb_ethtool_gregs(struct ixgb_adapter *adapter, } static int -ixgb_ethtool_geeprom(struct ixgb_adapter *adapter, - struct ethtool_eeprom *eeprom, uint16_t * eeprom_buff) +ixgb_ethtool_geeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - int i, max_len, first_word, last_word; - int ret_val = 0; - - if (eeprom->len == 0) { - ret_val = -EINVAL; - goto geeprom_error; - } eeprom->magic = hw->vendor_id | (hw->device_id << 16); - max_len = ixgb_eeprom_size(hw); - /* use our function to read the eeprom and update our cache */ ixgb_get_eeprom_data(hw); - - if (eeprom->offset > eeprom->offset + eeprom->len) { - ret_val = -EINVAL; - goto geeprom_error; - } - - if ((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - for (i = 0; i <= (last_word - first_word); i++) { - eeprom_buff[i] = hw->eeprom[first_word + i]; - } - geeprom_error: - return ret_val; + memcpy(data, (char *)hw->eeprom + eeprom->offset, eeprom->len); + return 0; } static int -ixgb_ethtool_seeprom(struct ixgb_adapter *adapter, - struct ethtool_eeprom *eeprom, void __user *user_data) +ixgb_ethtool_seeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - uint16_t eeprom_buff[256]; - int i, max_len, first_word, last_word; - void *ptr; + /* We are under rtnl, so static is OK */ + static uint16_t eeprom_buff[IXGB_EEPROM_SIZE]; + int i, first_word, last_word; + char *ptr; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; - if (eeprom->len == 0) - return -EINVAL; - - max_len = ixgb_eeprom_size(hw); - - if (eeprom->offset > eeprom->offset + eeprom->len) - return -EINVAL; - - if ((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); - first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - ptr = (void *)eeprom_buff; + ptr = (char *)eeprom_buff; if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ @@ -399,8 +360,7 @@ ixgb_ethtool_seeprom(struct ixgb_adapter *adapter, eeprom_buff[last_word - first_word] = ixgb_read_eeprom(hw, last_word); } - if (copy_from_user(ptr, user_data, eeprom->len)) - return -EFAULT; + memcpy(ptr, data, eeprom->len); for (i = 0; i <= (last_word - first_word); i++) ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]); @@ -431,8 +391,9 @@ static void ixgb_led_blink_callback(unsigned long data) } static int -ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id) +ixgb_ethtool_led_blink(struct net_device *netdev, u32 data) { + struct ixgb_adapter *adapter = netdev->priv; if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = ixgb_led_blink_callback; @@ -442,8 +403,8 @@ ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id) mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); - if (id->data) - schedule_timeout(id->data * HZ); + if (data) + schedule_timeout(data * HZ); else schedule_timeout(MAX_SCHEDULE_TIMEOUT); @@ -454,268 +415,141 @@ ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id) return 0; } -int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) +static int ixgb_nway_reset(struct net_device *netdev) { - struct ixgb_adapter *adapter = netdev->priv; - void __user *addr = ifr->ifr_data; - uint32_t cmd; + if (netif_running(netdev)) { + struct ixgb_adapter *adapter = netdev->priv; + ixgb_down(adapter, TRUE); + ixgb_up(adapter); + } + return 0; +} - if (get_user(cmd, (uint32_t __user *) addr)) - return -EFAULT; +static int ixgb_get_stats_count(struct net_device *dev) +{ + return IXGB_STATS_LEN; +} - switch (cmd) { - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - ixgb_ethtool_gset(adapter, &ecmd); - if (copy_to_user(addr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET:{ - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, addr, sizeof(ecmd))) - return -EFAULT; - return ixgb_ethtool_sset(adapter, &ecmd); - } - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO }; - ixgb_ethtool_gdrvinfo(adapter, &drvinfo); - if (copy_to_user(addr, &drvinfo, sizeof(drvinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSTRINGS:{ - struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; - char *strings = NULL; - int err = 0; - - if (copy_from_user(&gstrings, addr, sizeof(gstrings))) - return -EFAULT; - switch (gstrings.string_set) { - case ETH_SS_STATS:{ - int i; - gstrings.len = IXGB_STATS_LEN; - strings = - kmalloc(IXGB_STATS_LEN * - ETH_GSTRING_LEN, - GFP_KERNEL); - if (!strings) - return -ENOMEM; - for (i = 0; i < IXGB_STATS_LEN; i++) { - memcpy(&strings - [i * ETH_GSTRING_LEN], - ixgb_gstrings_stats[i]. - stat_string, - ETH_GSTRING_LEN); - } - break; - } - default: - return -EOPNOTSUPP; - } - if (copy_to_user(addr, &gstrings, sizeof(gstrings))) - err = -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if (!err && copy_to_user(addr, strings, - gstrings.len * - ETH_GSTRING_LEN)) - err = -EFAULT; - - kfree(strings); - return err; - } - case ETHTOOL_GREGS:{ - struct ethtool_regs regs = { ETHTOOL_GREGS }; - uint32_t regs_buff[IXGB_REG_DUMP_LEN]; - - if (copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - ixgb_ethtool_gregs(adapter, ®s, regs_buff); - if (copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if (copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; - } - case ETHTOOL_NWAY_RST:{ - if (netif_running(netdev)) { - ixgb_down(adapter, TRUE); - ixgb_up(adapter); - } - return 0; - } - case ETHTOOL_PHYS_ID:{ - struct ethtool_value id; - if (copy_from_user(&id, addr, sizeof(id))) - return -EFAULT; - return ixgb_ethtool_led_blink(adapter, &id); - } - case ETHTOOL_GLINK:{ - struct ethtool_value link = { ETHTOOL_GLINK }; - link.data = netif_carrier_ok(netdev); - if (copy_to_user(addr, &link, sizeof(link))) - return -EFAULT; - return 0; - } - - case ETHTOOL_GEEPROM:{ - struct ethtool_eeprom eeprom = { ETHTOOL_GEEPROM }; - uint16_t eeprom_buff[IXGB_EEPROM_SIZE]; - void *ptr; - int err = 0; - - if (copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - if ((err = - ixgb_ethtool_geeprom(adapter, &eeprom, - eeprom_buff)) < 0) - return err; - - if (copy_to_user(addr, &eeprom, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - - if (copy_to_user(addr, ptr, eeprom.len)) - return -EFAULT; - return 0; - } - case ETHTOOL_SEEPROM:{ - struct ethtool_eeprom eeprom; - - if (copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - return ixgb_ethtool_seeprom(adapter, &eeprom, addr); - } - case ETHTOOL_GPAUSEPARAM:{ - struct ethtool_pauseparam epause = - { ETHTOOL_GPAUSEPARAM }; - ixgb_ethtool_gpause(adapter, &epause); - if (copy_to_user(addr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM:{ - struct ethtool_pauseparam epause; - if (copy_from_user(&epause, addr, sizeof(epause))) - return -EFAULT; - return ixgb_ethtool_spause(adapter, &epause); - } - case ETHTOOL_GSTATS:{ - struct { - struct ethtool_stats eth_stats; - uint64_t data[IXGB_STATS_LEN]; - } stats = { { - ETHTOOL_GSTATS, IXGB_STATS_LEN}}; - int i; - - for (i = 0; i < IXGB_STATS_LEN; i++) - stats.data[i] = - (ixgb_gstrings_stats[i].sizeof_stat == - sizeof(uint64_t)) ? *(uint64_t *) ((char *) - adapter - + - ixgb_gstrings_stats - [i]. - stat_offset) - : *(uint32_t *) ((char *)adapter + - ixgb_gstrings_stats[i]. - stat_offset); - if (copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_GRXCSUM:{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = adapter->rx_csum; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRXCSUM:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - adapter->rx_csum = edata.data; - ixgb_down(adapter, TRUE); - ixgb_up(adapter); - return 0; - } - case ETHTOOL_GTXCSUM:{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - edata.data = (netdev->features & NETIF_F_HW_CSUM) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STXCSUM:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; - - return 0; - } - case ETHTOOL_GSG:{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - edata.data = (netdev->features & NETIF_F_SG) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSG:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_SG; - else - netdev->features &= ~NETIF_F_SG; - - return 0; - } -#ifdef NETIF_F_TSO - case ETHTOOL_GTSO:{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - edata.data = (netdev->features & NETIF_F_TSO) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STSO:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - return 0; - } -#endif - default: - return -EOPNOTSUPP; +static void ixgb_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + int i; + for (i = 0; i < IXGB_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + ixgb_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); } } + +static int ixgb_get_regs_len(struct net_device *dev) +{ + return 136*sizeof(uint32_t); +} + +static int ixgb_get_eeprom_len(struct net_device *dev) +{ + /* return size in bytes */ + return (IXGB_EEPROM_SIZE << 1); +} + +static void get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct ixgb_adapter *adapter = dev->priv; + int i; + + for (i = 0; i < IXGB_STATS_LEN; i++) { + void *p = (char *)adapter + ixgb_gstrings_stats[i].stat_offset; + stats->data[i] = + (ixgb_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) + ? *(uint64_t *) p + : *(uint32_t *) p; + } +} + +static u32 ixgb_get_rx_csum(struct net_device *dev) +{ + struct ixgb_adapter *adapter = dev->priv; + return adapter->rx_csum; +} + +static int ixgb_set_rx_csum(struct net_device *dev, u32 sum) +{ + struct ixgb_adapter *adapter = dev->priv; + adapter->rx_csum = sum; + ixgb_down(adapter, TRUE); + ixgb_up(adapter); + return 0; +} + +static u32 ixgb_get_tx_csum(struct net_device *dev) +{ + return (dev->features & NETIF_F_HW_CSUM) != 0; +} + +static int ixgb_set_tx_csum(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_HW_CSUM; + else + dev->features &= ~NETIF_F_HW_CSUM; + return 0; +} + +static u32 ixgb_get_sg(struct net_device *dev) +{ + return (dev->features & NETIF_F_SG) != 0; +} + +static int ixgb_set_sg(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_SG; + else + dev->features &= ~NETIF_F_SG; + return 0; +} + +#ifdef NETIF_F_TSO +static u32 ixgb_get_tso(struct net_device *dev) +{ + return (dev->features & NETIF_F_TSO) != 0; +} + +static int ixgb_set_tso(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_TSO; + else + dev->features &= ~NETIF_F_TSO; + return 0; +} +#endif + +struct ethtool_ops ixgb_ethtool_ops = { + .get_settings = ixgb_ethtool_gset, + .set_settings = ixgb_ethtool_sset, + .get_drvinfo = ixgb_ethtool_gdrvinfo, + .nway_reset = ixgb_nway_reset, + .get_link = ethtool_op_get_link, + .phys_id = ixgb_ethtool_led_blink, + .get_strings = ixgb_get_strings, + .get_stats_count = ixgb_get_stats_count, + .get_regs = ixgb_ethtool_gregs, + .get_regs_len = ixgb_get_regs_len, + .get_eeprom_len = ixgb_get_eeprom_len, + .get_eeprom = ixgb_ethtool_geeprom, + .set_eeprom = ixgb_ethtool_seeprom, + .get_pauseparam = ixgb_ethtool_gpause, + .set_pauseparam = ixgb_ethtool_spause, + .get_ethtool_stats = get_ethtool_stats, + .get_rx_csum = ixgb_get_rx_csum, + .set_rx_csum = ixgb_set_rx_csum, + .get_tx_csum = ixgb_get_tx_csum, + .set_tx_csum = ixgb_set_tx_csum, + .get_sg = ixgb_get_sg, + .set_sg = ixgb_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ixgb_get_tso, + .set_tso = ixgb_set_tso, +#endif +}; diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h index c6898ca61..fad5032d2 100644 --- a/drivers/net/ixgb/ixgb_hw.h +++ b/drivers/net/ixgb/ixgb_hw.h @@ -683,7 +683,7 @@ struct ixgb_bus { }; struct ixgb_hw { - uint8_t *hw_addr; /* Base Address of the hardware */ + uint8_t __iomem *hw_addr;/* Base Address of the hardware */ void *back; /* Pointer to OS-dependent struct */ struct ixgb_fc fc; /* Flow control parameters */ struct ixgb_bus bus; /* Bus parameters */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index f28ab3346..bcc106868 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -30,7 +30,7 @@ char ixgb_driver_name[] = "ixgb"; char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; -char ixgb_driver_version[] = "1.0.66"; +char ixgb_driver_version[] = "1.0.66-k2"; char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table @@ -55,6 +55,8 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl); /* Local Function Prototypes */ +static inline void ixgb_irq_disable(struct ixgb_adapter *adapter); +static inline void ixgb_irq_enable(struct ixgb_adapter *adapter); int ixgb_up(struct ixgb_adapter *adapter); void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); void ixgb_reset(struct ixgb_adapter *adapter); @@ -82,10 +84,11 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev); static int ixgb_change_mtu(struct net_device *netdev, int new_mtu); static int ixgb_set_mac(struct net_device *netdev, void *p); static void ixgb_update_stats(struct ixgb_adapter *adapter); -static inline void ixgb_irq_disable(struct ixgb_adapter *adapter); -static inline void ixgb_irq_enable(struct ixgb_adapter *adapter); static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs); static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter); +static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter, + struct ixgb_rx_desc *rx_desc, + struct sk_buff *skb); #ifdef CONFIG_IXGB_NAPI static int ixgb_clean(struct net_device *netdev, int *budget); static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, @@ -94,10 +97,6 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); #endif static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); -static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter, - struct ixgb_rx_desc *rx_desc, - struct sk_buff *skb); static void ixgb_tx_timeout(struct net_device *dev); static void ixgb_tx_timeout_task(struct net_device *dev); static void ixgb_vlan_rx_register(struct net_device *netdev, @@ -124,7 +123,7 @@ struct notifier_block ixgb_notifier_reboot = { /* Exported from other modules */ extern void ixgb_check_options(struct ixgb_adapter *adapter); -extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); +extern struct ethtool_ops ixgb_ethtool_ops; static struct pci_driver ixgb_driver = { .name = ixgb_driver_name, @@ -185,6 +184,34 @@ static void __exit ixgb_exit_module(void) module_exit(ixgb_exit_module); +/** + * ixgb_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +static inline void ixgb_irq_disable(struct ixgb_adapter *adapter) +{ + atomic_inc(&adapter->irq_sem); + IXGB_WRITE_REG(&adapter->hw, IMC, ~0); + IXGB_WRITE_FLUSH(&adapter->hw); + synchronize_irq(adapter->pdev->irq); +} + +/** + * ixgb_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ + +static inline void ixgb_irq_enable(struct ixgb_adapter *adapter) +{ + if (atomic_dec_and_test(&adapter->irq_sem)) { + IXGB_WRITE_REG(&adapter->hw, IMS, + IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | + IXGB_INT_RXO | IXGB_INT_LSC); + IXGB_WRITE_FLUSH(&adapter->hw); + } +} + int ixgb_up(struct ixgb_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -344,9 +371,9 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->set_multicast_list = &ixgb_set_multi; netdev->set_mac_address = &ixgb_set_mac; netdev->change_mtu = &ixgb_change_mtu; - netdev->do_ioctl = &ixgb_ioctl; netdev->tx_timeout = &ixgb_tx_timeout; netdev->watchdog_timeo = HZ; + SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops); #ifdef CONFIG_IXGB_NAPI netdev->poll = &ixgb_clean; netdev->weight = 64; @@ -1550,34 +1577,6 @@ static void ixgb_update_stats(struct ixgb_adapter *adapter) adapter->net_stats.tx_window_errors = 0; } -/** - * ixgb_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ - -static inline void ixgb_irq_disable(struct ixgb_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - IXGB_WRITE_REG(&adapter->hw, IMC, ~0); - IXGB_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * ixgb_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ - -static inline void ixgb_irq_enable(struct ixgb_adapter *adapter) -{ - if (atomic_dec_and_test(&adapter->irq_sem)) { - IXGB_WRITE_REG(&adapter->hw, IMS, - IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | - IXGB_INT_RXO | IXGB_INT_LSC); - IXGB_WRITE_FLUSH(&adapter->hw); - } -} - #define IXGB_MAX_INTR 10 /** * ixgb_intr - Interrupt Handler @@ -1614,8 +1613,13 @@ static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs) __netif_rx_schedule(netdev); } #else - for (i = 0; i < IXGB_MAX_INTR; i++) - if (!ixgb_clean_rx_irq(adapter) & !ixgb_clean_tx_irq(adapter)) + /* yes, that is actually a & and it is meant to make sure that + * every pass through this for loop checks both receive and + * transmit queues for completed descriptors, intended to + * avoid starvation issues and assist tx/rx fairness. */ + for(i = 0; i < IXGB_MAX_INTR; i++) + if(!ixgb_clean_rx_irq(adapter) & + !ixgb_clean_tx_irq(adapter)) break; /* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL) @@ -1677,7 +1681,7 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter) eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = IXGB_TX_DESC(*tx_ring, eop); - while (eop_desc->status & cpu_to_le32(IXGB_TX_DESC_STATUS_DD)) { + while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) { for (cleaned = FALSE; !cleaned;) { tx_desc = IXGB_TX_DESC(*tx_ring, i); @@ -1729,6 +1733,39 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter) return cleaned; } +/** + * ixgb_rx_checksum - Receive Checksum Offload for 82597. + * @adapter: board private structure + * @rx_desc: receive descriptor + * @sk_buff: socket buffer with received data + **/ + +static inline void +ixgb_rx_checksum(struct ixgb_adapter *adapter, + struct ixgb_rx_desc *rx_desc, struct sk_buff *skb) +{ + /* Ignore Checksum bit is set OR + * TCP Checksum has not been calculated + */ + if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) || + (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) { + skb->ip_summed = CHECKSUM_NONE; + return; + } + + /* At this point we know the hardware did the TCP checksum */ + /* now look at the TCP checksum error bit */ + if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) { + /* let the stack verify checksum errors */ + skb->ip_summed = CHECKSUM_NONE; + adapter->hw_csum_rx_error++; + } else { + /* TCP checksum is good */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_rx_good++; + } +} + /** * ixgb_clean_rx_irq - Send received data up the network stack, * @adapter: board private structure @@ -1936,58 +1973,6 @@ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter) rx_ring->next_to_use = i; } -/** - * ixgb_ioctl - perform a command - e.g: ethtool:get_driver_info. - * @param netdev network interface device structure - * @param ifr data to be used/filled in by the ioctl command - * @param cmd ioctl command to execute - **/ - -static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCETHTOOL: - return ixgb_ethtool_ioctl(netdev, ifr); - default: - return -EOPNOTSUPP; - } - - return 0; -} - -/** - * ixgb_rx_checksum - Receive Checksum Offload for 82597. - * @adapter: board private structure - * @rx_desc: receive descriptor - * @sk_buff: socket buffer with received data - **/ - -static inline void -ixgb_rx_checksum(struct ixgb_adapter *adapter, - struct ixgb_rx_desc *rx_desc, struct sk_buff *skb) -{ - /* Ignore Checksum bit is set OR - * TCP Checksum has not been calculated - */ - if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) || - (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* At this point we know the hardware did the TCP checksum */ - /* now look at the TCP checksum error bit */ - if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) { - /* let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; - adapter->hw_csum_rx_error++; - } else { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_rx_good++; - } -} - /** * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping. * @@ -2117,7 +2102,7 @@ static int ixgb_suspend(struct pci_dev *pdev, uint32_t state) if (netif_running(netdev)) ixgb_down(adapter, TRUE); - pci_save_state(pdev, adapter->pci_state); + pci_save_state(pdev); state = (state > 0) ? 3 : 0; pci_set_power_state(pdev, state); diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 8624bfc49..7046c4395 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -27,10 +27,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/lance.c b/drivers/net/lance.c index f04d0a82c..87acad342 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -56,8 +56,8 @@ static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker #include #include #include +#include -#include #include #include diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 4957de6d8..5e263fcba 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -83,8 +83,8 @@ #include #include #include +#include -#include #include #include #include @@ -1218,7 +1218,7 @@ static int __devinit i82596_probe(struct net_device *dev, lp->scb.command = 0; lp->scb.cmd = I596_NULL; lp->scb.rfd = I596_NULL; - lp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->lock); lp->dma_addr = dma_addr; lp->dev = gen_dev; @@ -1426,8 +1426,6 @@ static int i596_close(struct net_device *dev) free_irq(dev->irq, dev); remove_rx_bufs(dev); - MOD_DEC_USE_COUNT; - return 0; } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 8ffa894c3..4bca692d6 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include /* For the statistics structure. */ @@ -183,6 +184,17 @@ static struct net_device_stats *get_stats(struct net_device *dev) return stats; } +u32 loopback_get_link(struct net_device *dev) +{ + return 1; +} + +static struct ethtool_ops loopback_ethtool_ops = { + .get_link = loopback_get_link, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +}; + struct net_device loopback_dev = { .name = "lo", .mtu = (16 * 1024) + 20 + 20 + 12, @@ -199,6 +211,7 @@ struct net_device loopback_dev = { .features = NETIF_F_SG|NETIF_F_FRAGLIST |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA |NETIF_F_LLTX, + .ethtool_ops = &loopback_ethtool_ops, }; /* Setup and register the of the LOOPBACK device. */ diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index c87d90a83..70be2a9e3 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -70,8 +70,8 @@ All other communication is through memory! #include #include #include +#include -#include #include #include diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 0a8094eb3..ce5761816 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -32,9 +32,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -42,10 +42,6 @@ #include "8390.h" -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - #define WD_START_PG 0x00 /* First page of TX buffer */ #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ #define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 8c0825589..f65b0db11 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -98,6 +98,7 @@ static char *version = #include #include #include +#include #include #include @@ -308,8 +309,7 @@ void __init reset_chip(struct net_device *dev) writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET); /* wait 30 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(30*HZ/1000); + msleep_interruptible(30); /* Wait until the chip is reset */ reset_start_time = jiffies; diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index e67bf67f1..a4dde8181 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -42,10 +42,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/meth.c b/drivers/net/meth.c index 619a67a8c..2c0f2aaad 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -367,31 +367,6 @@ static int meth_release(struct net_device *dev) return 0; } -/* - * Configuration changes (passed on by ifconfig) - */ -static int meth_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; - - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) { - printk(KERN_WARNING "meth: Can't change I/O address\n"); - return -EOPNOTSUPP; - } - - /* Don't allow changing the IRQ */ - if (map->irq != dev->irq) { - printk(KERN_WARNING "meth: Can't change IRQ\n"); - return -EOPNOTSUPP; - } - DPRINTK("Configured\n"); - - /* ignore other fields */ - return 0; -} - /* * Receive a packet: retrieve, encapsulate and pass over to upper levels */ @@ -813,7 +788,6 @@ static struct net_device *meth_init(void) dev->open = meth_open; dev->stop = meth_release; - dev->set_config = meth_config; dev->hard_start_xmit = meth_tx; dev->do_ioctl = meth_ioctl; dev->get_stats = meth_stats; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 41d38b3b3..362fee325 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c index 5995658b1..56a82d8ee 100644 --- a/drivers/net/mvme147.c +++ b/drivers/net/mvme147.c @@ -18,7 +18,6 @@ /* Used for the temporal inet entries and routing */ #include #include -#include #include #include #include @@ -40,7 +39,6 @@ /* Our private data structure */ struct m147lance_private { struct lance_private lance; - void *base; unsigned long ram; }; @@ -51,9 +49,9 @@ struct m147lance_private { */ static int m147lance_open(struct net_device *dev); static int m147lance_close(struct net_device *dev); -static void m147lance_writerap(struct m147lance_private *lp, unsigned short value); -static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value); -static unsigned short m147lance_readrdp(struct m147lance_private *lp); +static void m147lance_writerap(struct lance_private *lp, unsigned short value); +static void m147lance_writerdp(struct lance_private *lp, unsigned short value); +static unsigned short m147lance_readrdp(struct lance_private *lp); typedef void (*writerap_t)(void *, unsigned short); typedef void (*writerdp_t)(void *, unsigned short); @@ -122,7 +120,7 @@ struct net_device * __init mvme147lance_probe(int unit) } lp->lance.name = (char*)name; /* discards const, shut up gcc */ - lp->lance.ll = (struct lance_regs *)(dev->base_addr); + lp->lance.base = dev->base_addr; lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */ lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram); /* LANCE addr of same RAM */ lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ @@ -145,19 +143,19 @@ struct net_device * __init mvme147lance_probe(int unit) return dev; } -static void m147lance_writerap(struct m147lance_private *lp, unsigned short value) +static void m147lance_writerap(struct lance_private *lp, unsigned short value) { - lp->lance.ll->rap = value; + out_be16(lp->base + LANCE_RAP, value); } -static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value) +static void m147lance_writerdp(struct lance_private *lp, unsigned short value) { - lp->lance.ll->rdp = value; + out_be16(lp->base + LANCE_RDP, value); } -static unsigned short m147lance_readrdp(struct m147lance_private *lp) +static unsigned short m147lance_readrdp(struct lance_private *lp) { - return lp->lance.ll->rdp; + return in_be16(lp->base + LANCE_RDP); } static int m147lance_open(struct net_device *dev) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index c4c9cb22a..d85e04bd7 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -22,6 +22,7 @@ static char version[] = #include #include #include +#include #include #include @@ -29,7 +30,6 @@ static char version[] = #include #include -#include #include #include #include @@ -85,7 +85,7 @@ static char version[] = static struct myri_eth *root_myri_dev; #endif -static void myri_reset_off(unsigned long lp, unsigned long cregs) +static void myri_reset_off(void __iomem *lp, void __iomem *cregs) { /* Clear IRQ mask. */ sbus_writel(0, lp + LANAI_EIMASK); @@ -94,7 +94,7 @@ static void myri_reset_off(unsigned long lp, unsigned long cregs) sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL); } -static void myri_reset_on(unsigned long cregs) +static void myri_reset_on(void __iomem *cregs) { /* Enable RESET function. */ sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL); @@ -103,14 +103,14 @@ static void myri_reset_on(unsigned long cregs) sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL); } -static void myri_disable_irq(unsigned long lp, unsigned long cregs) +static void myri_disable_irq(void __iomem *lp, void __iomem *cregs) { sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL); sbus_writel(0, lp + LANAI_EIMASK); sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT); } -static void myri_enable_irq(unsigned long lp, unsigned long cregs) +static void myri_enable_irq(void __iomem *lp, void __iomem *cregs) { sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL); sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK); @@ -119,7 +119,7 @@ static void myri_enable_irq(unsigned long lp, unsigned long cregs) static inline void bang_the_chip(struct myri_eth *mp) { struct myri_shmem *shmem = mp->shmem; - unsigned long cregs = mp->cregs; + void __iomem *cregs = mp->cregs; sbus_writel(1, &shmem->send); sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL); @@ -128,7 +128,7 @@ static inline void bang_the_chip(struct myri_eth *mp) static int myri_do_handshake(struct myri_eth *mp) { struct myri_shmem *shmem = mp->shmem; - unsigned long cregs = mp->cregs; + void __iomem *cregs = mp->cregs; struct myri_channel *chan = &shmem->channel; int tick = 0; @@ -176,27 +176,27 @@ static int myri_do_handshake(struct myri_eth *mp) static int myri_load_lanai(struct myri_eth *mp) { struct net_device *dev = mp->dev; - struct myri_shmem *shmem = mp->shmem; - unsigned char *rptr; + struct myri_shmem __iomem *shmem = mp->shmem; + void __iomem *rptr; int i; myri_disable_irq(mp->lregs, mp->cregs); myri_reset_on(mp->cregs); - rptr = (unsigned char *) mp->lanai; + rptr = mp->lanai; for (i = 0; i < mp->eeprom.ramsz; i++) - sbus_writeb(0, &rptr[i]); + sbus_writeb(0, rptr + i); if (mp->eeprom.cpuvers >= CPUVERS_3_0) sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL); /* Load executable code. */ for (i = 0; i < sizeof(lanai4_code); i++) - sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]); + sbus_writeb(lanai4_code[i], rptr + (lanai4_code_off * 2) + i); /* Load data segment. */ for (i = 0; i < sizeof(lanai4_data); i++) - sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]); + sbus_writeb(lanai4_data[i], rptr + (lanai4_data_off * 2) + i); /* Set device address. */ sbus_writeb(0, &shmem->addr[0]); @@ -237,15 +237,15 @@ static int myri_load_lanai(struct myri_eth *mp) static void myri_clean_rings(struct myri_eth *mp) { - struct sendq *sq = mp->sq; - struct recvq *rq = mp->rq; + struct sendq __iomem *sq = mp->sq; + struct recvq __iomem *rq = mp->rq; int i; sbus_writel(0, &rq->tail); sbus_writel(0, &rq->head); for (i = 0; i < (RX_RING_SIZE+1); i++) { if (mp->rx_skbs[i] != NULL) { - struct myri_rxd *rxd = &rq->myri_rxd[i]; + struct myri_rxd __iomem *rxd = &rq->myri_rxd[i]; u32 dma_addr; dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); @@ -261,7 +261,7 @@ static void myri_clean_rings(struct myri_eth *mp) for (i = 0; i < TX_RING_SIZE; i++) { if (mp->tx_skbs[i] != NULL) { struct sk_buff *skb = mp->tx_skbs[i]; - struct myri_txd *txd = &sq->myri_txd[i]; + struct myri_txd __iomem *txd = &sq->myri_txd[i]; u32 dma_addr; dma_addr = sbus_readl(&txd->myri_gathers[0].addr); @@ -274,8 +274,8 @@ static void myri_clean_rings(struct myri_eth *mp) static void myri_init_rings(struct myri_eth *mp, int from_irq) { - struct recvq *rq = mp->rq; - struct myri_rxd *rxd = &rq->myri_rxd[0]; + struct recvq __iomem *rq = mp->rq; + struct myri_rxd __iomem *rxd = &rq->myri_rxd[0]; struct net_device *dev = mp->dev; int gfp_flags = GFP_KERNEL; int i; @@ -343,7 +343,7 @@ static void dump_ehdr_and_myripad(unsigned char *stuff) static void myri_tx(struct myri_eth *mp, struct net_device *dev) { - struct sendq *sq = mp->sq; + struct sendq __iomem *sq= mp->sq; int entry = mp->tx_old; int limit = sbus_readl(&sq->head); @@ -376,7 +376,7 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN); skb_pull(skb, dev->hard_header_len); - eth = skb->mac.ethernet; + eth = eth_hdr(skb); #ifdef DEBUG_HEADER DHDR(("myri_type_trans: ")); @@ -411,8 +411,8 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de static void myri_rx(struct myri_eth *mp, struct net_device *dev) { - struct recvq *rq = mp->rq; - struct recvq *rqa = mp->rqack; + struct recvq __iomem *rq = mp->rq; + struct recvq __iomem *rqa = mp->rqack; int entry = sbus_readl(&rqa->head); int limit = sbus_readl(&rqa->tail); int drops; @@ -423,11 +423,11 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) drops = 0; DRX(("\n")); while (entry != limit) { - struct myri_rxd *rxdack = &rqa->myri_rxd[entry]; + struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry]; u32 csum = sbus_readl(&rxdack->csum); int len = sbus_readl(&rxdack->myri_scatters[0].len); int index = sbus_readl(&rxdack->ctx); - struct myri_rxd *rxd = &rq->myri_rxd[rq->tail]; + struct myri_rxd __iomem *rxd = &rq->myri_rxd[rq->tail]; struct sk_buff *skb = mp->rx_skbs[index]; /* Ack it. */ @@ -545,7 +545,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct myri_eth *mp = (struct myri_eth *) dev->priv; - unsigned long lregs = mp->lregs; + void __iomem *lregs = mp->lregs; struct myri_channel *chan = &mp->shmem->channel; unsigned long flags; u32 status; @@ -610,8 +610,8 @@ static void myri_tx_timeout(struct net_device *dev) static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct myri_eth *mp = (struct myri_eth *) dev->priv; - struct sendq *sq = mp->sq; - struct myri_txd *txd; + struct sendq __iomem *sq = mp->sq; + struct myri_txd __iomem *txd; unsigned long flags; unsigned int head, tail; int len, entry; @@ -998,22 +998,20 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num) printk("MyriCOM: Cannot map MyriCOM registers.\n"); goto err; } - mp->lanai = (unsigned short *) (mp->regs + (256 * 1024)); - mp->lanai3 = (unsigned int *) mp->lanai; - mp->lregs = (unsigned long) &mp->lanai[0x10000]; + mp->lanai = mp->regs + (256 * 1024); + mp->lregs = mp->lanai + (0x10000 * 2); } else { DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); mp->cregs = sbus_ioremap(&sdev->resource[0], 0, PAGE_SIZE, "MyriCOM Control Regs"); mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024), PAGE_SIZE, "MyriCOM LANAI Regs"); - mp->lanai = (unsigned short *) + mp->lanai = sbus_ioremap(&sdev->resource[0], (512 * 1024), mp->eeprom.ramsz, "MyriCOM SRAM"); - mp->lanai3 = (unsigned int *) mp->lanai; } - DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n", - mp->cregs, mp->lregs, mp->lanai, mp->lanai3)); + DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n", + mp->cregs, mp->lregs, mp->lanai)); if (mp->eeprom.cpuvers >= CPUVERS_4_0) mp->shmem_base = 0xf000; @@ -1022,7 +1020,8 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num) DET(("Shared memory base is %04x, ", mp->shmem_base)); - mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base]; + mp->shmem = (struct myri_shmem __iomem *) + (mp->lanai + (mp->shmem_base * 2)); DET(("shmem mapped at %p\n", mp->shmem)); mp->rqack = &mp->shmem->channel.recvqa; diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index 944ddfa65..9391e55a5 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h @@ -270,22 +270,21 @@ struct myri_eth { * to obtain good cache hit rates. */ spinlock_t irq_lock; - struct myri_shmem *shmem; /* Shared data structures. */ - unsigned long cregs; /* Control register space. */ - struct recvq *rqack; /* Where we ack rx's. */ - struct recvq *rq; /* Where we put buffers. */ - struct sendq *sq; /* Where we stuff tx's. */ + struct myri_shmem __iomem *shmem; /* Shared data structures. */ + void __iomem *cregs; /* Control register space. */ + struct recvq __iomem *rqack; /* Where we ack rx's. */ + struct recvq __iomem *rq; /* Where we put buffers. */ + struct sendq __iomem *sq; /* Where we stuff tx's. */ struct net_device *dev; /* Linux/NET dev struct. */ int tx_old; /* To speed up tx cleaning. */ - unsigned long lregs; /* Quick ptr to LANAI regs. */ + void __iomem *lregs; /* Quick ptr to LANAI regs. */ struct sk_buff *rx_skbs[RX_RING_SIZE+1];/* RX skb's */ struct sk_buff *tx_skbs[TX_RING_SIZE]; /* TX skb's */ struct net_device_stats enet_stats; /* Interface stats. */ /* These are less frequently accessed. */ - unsigned long regs; /* MyriCOM register space. */ - unsigned short *lanai; /* View 2 of register space. */ - unsigned int *lanai3; /* View 3 of register space. */ + void __iomem *regs; /* MyriCOM register space. */ + void __iomem *lanai; /* View 2 of register space. */ unsigned int myri_bursts; /* SBUS bursts. */ struct myri_eeprom eeprom; /* Local copy of EEPROM. */ unsigned int reg_size; /* Size of register space. */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 88c626afe..5bb12dc93 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -159,8 +159,8 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -719,7 +719,7 @@ struct netdev_private { }; static void move_int_phy(struct net_device *dev, int addr); -static int eeprom_read(long ioaddr, int location); +static int eeprom_read(void __iomem *ioaddr, int location); static int mdio_read(struct net_device *dev, int reg); static void mdio_write(struct net_device *dev, int reg, u16 data); static void init_phy_fixup(struct net_device *dev); @@ -750,6 +750,9 @@ static void netdev_error(struct net_device *dev, int intr_status); static void netdev_rx(struct net_device *dev); static void netdev_tx_done(struct net_device *dev); static int natsemi_change_mtu(struct net_device *dev, int new_mtu); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void natsemi_poll_controller(struct net_device *dev); +#endif static void __set_rx_mode(struct net_device *dev); static void set_rx_mode(struct net_device *dev); static void __get_stats(struct net_device *dev); @@ -765,10 +768,17 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr); 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); +static struct ethtool_ops ethtool_ops; + +static inline void __iomem *ns_ioaddr(struct net_device *dev) +{ + return (void __iomem *) dev->base_addr; +} static void move_int_phy(struct net_device *dev, int addr) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); int target = 31; /* @@ -785,8 +795,8 @@ static void move_int_phy(struct net_device *dev, int addr) target--; if (target == np->phy_addr_external) target--; - writew(target, dev->base_addr + PhyCtrl); - readw(dev->base_addr + PhyCtrl); + writew(target, ioaddr + PhyCtrl); + readw(ioaddr + PhyCtrl); udelay(1); } @@ -797,7 +807,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, struct netdev_private *np; int i, option, irq, chip_idx = ent->driver_data; static int find_cnt = -1; - unsigned long ioaddr, iosize; + unsigned long iostart, iosize; + void __iomem *ioaddr; const int pcibar = 1; /* PCI base address register */ int prev_eedata; u32 tmp; @@ -824,7 +835,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, } find_cnt++; - ioaddr = pci_resource_start(pdev, pcibar); + iostart = pci_resource_start(pdev, pcibar); iosize = pci_resource_len(pdev, pcibar); irq = pdev->irq; @@ -841,7 +852,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, if (i) goto err_pci_request_regions; - ioaddr = (unsigned long) ioremap (ioaddr, iosize); + ioaddr = ioremap(iostart, iosize); if (!ioaddr) { i = -ENOMEM; goto err_ioremap; @@ -856,7 +867,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, prev_eedata = eedata; } - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long __force) ioaddr; dev->irq = irq; np = netdev_priv(dev); @@ -876,7 +887,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, * The address would be used to access a phy over the mii bus, but * the internal phy is accessed through mapped registers. */ - if (readl(dev->base_addr + ChipConfig) & CfgExtPhy) + if (readl(ioaddr + ChipConfig) & CfgExtPhy) dev->if_port = PORT_MII; else dev->if_port = PORT_TP; @@ -920,6 +931,10 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, dev->do_ioctl = &netdev_ioctl; dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = &natsemi_poll_controller; +#endif + SET_ETHTOOL_OPS(dev, ðtool_ops); if (mtu) dev->mtu = mtu; @@ -965,7 +980,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, if (netif_msg_drv(np)) { printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ", - dev->name, natsemi_pci_info[chip_idx].name, ioaddr, + dev->name, natsemi_pci_info[chip_idx].name, iostart, pci_name(np->pci_dev)); for (i = 0; i < ETH_ALEN-1; i++) printk("%02x:", dev->dev_addr[i]); @@ -978,7 +993,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, return 0; err_register_netdev: - iounmap ((void *) dev->base_addr); + iounmap(ioaddr); err_ioremap: pci_release_regions(pdev); @@ -1010,12 +1025,13 @@ enum EEPROM_Cmds { EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), }; -static int eeprom_read(long addr, int location) +static int eeprom_read(void __iomem *addr, int location) { int i; int retval = 0; - long ee_addr = addr + EECtrl; + void __iomem *ee_addr = addr + EECtrl; int read_cmd = location | EE_ReadCmd; + writel(EE_Write0, ee_addr); /* Shift the read command bits out. */ @@ -1052,33 +1068,35 @@ static int eeprom_read(long addr, int location) /* clock transitions >= 20ns (25MHz) * One readl should be good to PCI @ 100MHz */ -#define mii_delay(dev) readl(dev->base_addr + EECtrl) +#define mii_delay(ioaddr) readl(ioaddr + EECtrl) static int mii_getbit (struct net_device *dev) { int data; + void __iomem *ioaddr = ns_ioaddr(dev); - writel(MII_ShiftClk, dev->base_addr + EECtrl); - data = readl(dev->base_addr + EECtrl); - writel(0, dev->base_addr + EECtrl); - mii_delay(dev); + writel(MII_ShiftClk, ioaddr + EECtrl); + data = readl(ioaddr + EECtrl); + writel(0, ioaddr + EECtrl); + mii_delay(ioaddr); return (data & MII_Data)? 1 : 0; } static void mii_send_bits (struct net_device *dev, u32 data, int len) { u32 i; + void __iomem *ioaddr = ns_ioaddr(dev); for (i = (1 << (len-1)); i; i >>= 1) { u32 mdio_val = MII_Write | ((data & i)? MII_Data : 0); - writel(mdio_val, dev->base_addr + EECtrl); - mii_delay(dev); - writel(mdio_val | MII_ShiftClk, dev->base_addr + EECtrl); - mii_delay(dev); + writel(mdio_val, ioaddr + EECtrl); + mii_delay(ioaddr); + writel(mdio_val | MII_ShiftClk, ioaddr + EECtrl); + mii_delay(ioaddr); } - writel(0, dev->base_addr + EECtrl); - mii_delay(dev); + writel(0, ioaddr + EECtrl); + mii_delay(ioaddr); } static int miiport_read(struct net_device *dev, int phy_id, int reg) @@ -1123,13 +1141,14 @@ static void miiport_write(struct net_device *dev, int phy_id, int reg, u16 data) static int mdio_read(struct net_device *dev, int reg) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); /* The 83815 series has two ports: * - an internal transceiver * - an external mii bus */ if (dev->if_port == PORT_TP) - return readw(dev->base_addr+BasicControl+(reg<<2)); + return readw(ioaddr+BasicControl+(reg<<2)); else return miiport_read(dev, np->phy_addr_external, reg); } @@ -1137,10 +1156,11 @@ static int mdio_read(struct net_device *dev, int reg) static void mdio_write(struct net_device *dev, int reg, u16 data) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); /* The 83815 series has an internal transceiver; handle separately */ if (dev->if_port == PORT_TP) - writew(data, dev->base_addr+BasicControl+(reg<<2)); + writew(data, ioaddr+BasicControl+(reg<<2)); else miiport_write(dev, np->phy_addr_external, reg, data); } @@ -1148,7 +1168,7 @@ static void mdio_write(struct net_device *dev, int reg, u16 data) static void init_phy_fixup(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = ns_ioaddr(dev); int i; u32 cfg; u16 tmp; @@ -1180,7 +1200,7 @@ static void init_phy_fixup(struct net_device *dev) */ } mdio_write(dev, MII_BMCR, tmp); - readl(dev->base_addr + ChipConfig); + readl(ioaddr + ChipConfig); udelay(1); /* find out what phy this is */ @@ -1202,7 +1222,7 @@ static void init_phy_fixup(struct net_device *dev) default: break; } - cfg = readl(dev->base_addr + ChipConfig); + cfg = readl(ioaddr + ChipConfig); if (cfg & CfgExtPhy) return; @@ -1260,9 +1280,10 @@ static void init_phy_fixup(struct net_device *dev) static int switch_port_external(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); u32 cfg; - cfg = readl(dev->base_addr + ChipConfig); + cfg = readl(ioaddr + ChipConfig); if (cfg & CfgExtPhy) return 0; @@ -1272,8 +1293,8 @@ static int switch_port_external(struct net_device *dev) } /* 1) switch back to external phy */ - writel(cfg | (CfgExtPhy | CfgPhyDis), dev->base_addr + ChipConfig); - readl(dev->base_addr + ChipConfig); + writel(cfg | (CfgExtPhy | CfgPhyDis), ioaddr + ChipConfig); + readl(ioaddr + ChipConfig); udelay(1); /* 2) reset the external phy: */ @@ -1292,11 +1313,12 @@ static int switch_port_external(struct net_device *dev) static int switch_port_internal(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); int i; u32 cfg; u16 bmcr; - cfg = readl(dev->base_addr + ChipConfig); + cfg = readl(ioaddr + ChipConfig); if (!(cfg &CfgExtPhy)) return 0; @@ -1306,17 +1328,17 @@ static int switch_port_internal(struct net_device *dev) } /* 1) switch back to internal phy: */ cfg = cfg & ~(CfgExtPhy | CfgPhyDis); - writel(cfg, dev->base_addr + ChipConfig); - readl(dev->base_addr + ChipConfig); + writel(cfg, ioaddr + ChipConfig); + readl(ioaddr + ChipConfig); udelay(1); /* 2) reset the internal phy: */ - bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2)); - writel(bmcr | BMCR_RESET, dev->base_addr+BasicControl+(MII_BMCR<<2)); - readl(dev->base_addr + ChipConfig); + bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2)); + writel(bmcr | BMCR_RESET, ioaddr+BasicControl+(MII_BMCR<<2)); + readl(ioaddr + ChipConfig); udelay(10); for (i=0;ibase_addr+BasicControl+(MII_BMCR<<2)); + bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2)); if (!(bmcr & BMCR_RESET)) break; udelay(10); @@ -1392,6 +1414,7 @@ static void natsemi_reset(struct net_device *dev) u16 pmatch[3]; u16 sopass[3]; struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); /* * Resetting the chip causes some registers to be lost. @@ -1402,26 +1425,26 @@ static void natsemi_reset(struct net_device *dev) */ /* CFG */ - cfg = readl(dev->base_addr + ChipConfig) & CFG_RESET_SAVE; + cfg = readl(ioaddr + ChipConfig) & CFG_RESET_SAVE; /* WCSR */ - wcsr = readl(dev->base_addr + WOLCmd) & WCSR_RESET_SAVE; + wcsr = readl(ioaddr + WOLCmd) & WCSR_RESET_SAVE; /* RFCR */ - rfcr = readl(dev->base_addr + RxFilterAddr) & RFCR_RESET_SAVE; + rfcr = readl(ioaddr + RxFilterAddr) & RFCR_RESET_SAVE; /* PMATCH */ for (i = 0; i < 3; i++) { - writel(i*2, dev->base_addr + RxFilterAddr); - pmatch[i] = readw(dev->base_addr + RxFilterData); + writel(i*2, ioaddr + RxFilterAddr); + pmatch[i] = readw(ioaddr + RxFilterData); } /* SOPAS */ for (i = 0; i < 3; i++) { - writel(0xa+(i*2), dev->base_addr + RxFilterAddr); - sopass[i] = readw(dev->base_addr + RxFilterData); + writel(0xa+(i*2), ioaddr + RxFilterAddr); + sopass[i] = readw(ioaddr + RxFilterData); } /* now whack the chip */ - writel(ChipReset, dev->base_addr + ChipCmd); + writel(ChipReset, ioaddr + ChipCmd); for (i=0;ibase_addr + ChipCmd) & ChipReset)) + if (!(readl(ioaddr + ChipCmd) & ChipReset)) break; udelay(5); } @@ -1434,40 +1457,41 @@ static void natsemi_reset(struct net_device *dev) } /* restore CFG */ - cfg |= readl(dev->base_addr + ChipConfig) & ~CFG_RESET_SAVE; + cfg |= readl(ioaddr + ChipConfig) & ~CFG_RESET_SAVE; /* turn on external phy if it was selected */ if (dev->if_port == PORT_TP) cfg &= ~(CfgExtPhy | CfgPhyDis); else cfg |= (CfgExtPhy | CfgPhyDis); - writel(cfg, dev->base_addr + ChipConfig); + writel(cfg, ioaddr + ChipConfig); /* restore WCSR */ - wcsr |= readl(dev->base_addr + WOLCmd) & ~WCSR_RESET_SAVE; - writel(wcsr, dev->base_addr + WOLCmd); + wcsr |= readl(ioaddr + WOLCmd) & ~WCSR_RESET_SAVE; + writel(wcsr, ioaddr + WOLCmd); /* read RFCR */ - rfcr |= readl(dev->base_addr + RxFilterAddr) & ~RFCR_RESET_SAVE; + rfcr |= readl(ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE; /* restore PMATCH */ for (i = 0; i < 3; i++) { - writel(i*2, dev->base_addr + RxFilterAddr); - writew(pmatch[i], dev->base_addr + RxFilterData); + writel(i*2, ioaddr + RxFilterAddr); + writew(pmatch[i], ioaddr + RxFilterData); } for (i = 0; i < 3; i++) { - writel(0xa+(i*2), dev->base_addr + RxFilterAddr); - writew(sopass[i], dev->base_addr + RxFilterData); + writel(0xa+(i*2), ioaddr + RxFilterAddr); + writew(sopass[i], ioaddr + RxFilterData); } /* restore RFCR */ - writel(rfcr, dev->base_addr + RxFilterAddr); + writel(rfcr, ioaddr + RxFilterAddr); } static void natsemi_reload_eeprom(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); int i; - writel(EepromReload, dev->base_addr + PCIBusCfg); + writel(EepromReload, ioaddr + PCIBusCfg); for (i=0;ibase_addr + PCIBusCfg) & EepromReload)) + if (!(readl(ioaddr + PCIBusCfg) & EepromReload)) break; } if (i==NATSEMI_HW_TIMEOUT) { @@ -1481,7 +1505,7 @@ static void natsemi_reload_eeprom(struct net_device *dev) static void natsemi_stop_rxtx(struct net_device *dev) { - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); struct netdev_private *np = netdev_priv(dev); int i; @@ -1503,7 +1527,7 @@ static void natsemi_stop_rxtx(struct net_device *dev) static int netdev_open(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); int i; /* Reset the chip, just in case. */ @@ -1552,6 +1576,7 @@ static int netdev_open(struct net_device *dev) static void do_cable_magic(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = ns_ioaddr(dev); if (dev->if_port != PORT_TP) return; @@ -1565,15 +1590,15 @@ static void do_cable_magic(struct net_device *dev) * activity LED while idle. This process is based on instructions * from engineers at National. */ - if (readl(dev->base_addr + ChipConfig) & CfgSpeed100) { + if (readl(ioaddr + ChipConfig) & CfgSpeed100) { u16 data; - writew(1, dev->base_addr + PGSEL); + writew(1, ioaddr + PGSEL); /* * coefficient visibility should already be enabled via * DSPCFG | 0x1000 */ - data = readw(dev->base_addr + TSTDAT) & 0xff; + data = readw(ioaddr + TSTDAT) & 0xff; /* * the value must be negative, and within certain values * (these values all come from National) @@ -1582,13 +1607,13 @@ static void do_cable_magic(struct net_device *dev) struct netdev_private *np = netdev_priv(dev); /* the bug has been triggered - fix the coefficient */ - writew(TSTDAT_FIXED, dev->base_addr + TSTDAT); + writew(TSTDAT_FIXED, ioaddr + TSTDAT); /* lock the value */ - data = readw(dev->base_addr + DSPCFG); + data = readw(ioaddr + DSPCFG); np->dspcfg = data | DSPCFG_LOCK; - writew(np->dspcfg, dev->base_addr + DSPCFG); + writew(np->dspcfg, ioaddr + DSPCFG); } - writew(0, dev->base_addr + PGSEL); + writew(0, ioaddr + PGSEL); } } @@ -1596,6 +1621,7 @@ static void undo_cable_magic(struct net_device *dev) { u16 data; struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); if (dev->if_port != PORT_TP) return; @@ -1603,18 +1629,18 @@ static void undo_cable_magic(struct net_device *dev) if (np->srr >= SRR_DP83816_A5) return; - writew(1, dev->base_addr + PGSEL); + writew(1, ioaddr + PGSEL); /* make sure the lock bit is clear */ - data = readw(dev->base_addr + DSPCFG); + data = readw(ioaddr + DSPCFG); np->dspcfg = data & ~DSPCFG_LOCK; - writew(np->dspcfg, dev->base_addr + DSPCFG); - writew(0, dev->base_addr + PGSEL); + writew(np->dspcfg, ioaddr + DSPCFG); + writew(0, ioaddr + PGSEL); } static void check_link(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); int duplex; u16 bmsr; @@ -1675,7 +1701,7 @@ static void check_link(struct net_device *dev) static void init_registers(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); init_phy_fixup(dev); @@ -1754,6 +1780,7 @@ static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); int next_tick = 5*HZ; if (netif_msg_timer(np)) { @@ -1765,7 +1792,6 @@ static void netdev_timer(unsigned long data) } if (dev->if_port == PORT_TP) { - long ioaddr = dev->base_addr; u16 dspcfg; spin_lock_irq(&np->lock); @@ -1808,7 +1834,7 @@ static void netdev_timer(unsigned long data) refill_rx(dev); enable_irq(dev->irq); if (!np->oom) { - writel(RxOn, dev->base_addr + ChipCmd); + writel(RxOn, ioaddr + ChipCmd); } else { next_tick = 1; } @@ -1842,7 +1868,7 @@ static void dump_ring(struct net_device *dev) static void tx_timeout(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); disable_irq(dev->irq); spin_lock_irq(&np->lock); @@ -2042,6 +2068,7 @@ static void reinit_ring(struct net_device *dev) static int start_tx(struct sk_buff *skb, struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); unsigned entry; /* Note: Ordering is important here, set the field with the @@ -2070,7 +2097,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); } /* Wake the potentially-idle transmit channel. */ - writel(TxOn, dev->base_addr + ChipCmd); + writel(TxOn, ioaddr + ChipCmd); } else { dev_kfree_skb_irq(skb); np->stats.tx_dropped++; @@ -2135,7 +2162,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs { struct net_device *dev = dev_instance; struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); int boguscnt = max_interrupt_work; unsigned int handled = 0; @@ -2197,6 +2224,7 @@ static void netdev_rx(struct net_device *dev) int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; s32 desc_status = le32_to_cpu(np->rx_head_desc->cmd_status); unsigned int buflen = np->rx_buf_sz; + void __iomem * ioaddr = ns_ioaddr(dev); /* If the driver owns the next entry it's a new packet. Send it up. */ while (desc_status < 0) { /* e.g. & DescOwn */ @@ -2278,13 +2306,13 @@ static void netdev_rx(struct net_device *dev) if (np->oom) mod_timer(&np->timer, jiffies + 1); else - writel(RxOn, dev->base_addr + ChipCmd); + writel(RxOn, ioaddr + ChipCmd); } static void netdev_error(struct net_device *dev, int intr_status) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); spin_lock(&np->lock); if (intr_status & LinkChange) { @@ -2343,7 +2371,7 @@ static void netdev_error(struct net_device *dev, int intr_status) static void __get_stats(struct net_device *dev) { - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); struct netdev_private *np = netdev_priv(dev); /* The chip only need report frame silently dropped. */ @@ -2364,10 +2392,19 @@ static struct net_device_stats *get_stats(struct net_device *dev) return &np->stats; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void natsemi_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + intr_handler(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + #define HASH_TABLE 0x200 static void __set_rx_mode(struct net_device *dev) { - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); struct netdev_private *np = netdev_priv(dev); u8 mc_filter[64]; /* Multicast hash filter */ u32 rx_mode; @@ -2413,7 +2450,7 @@ static int natsemi_change_mtu(struct net_device *dev, int new_mtu) /* synchronized against open : rtnl_lock() held by caller */ if (netif_running(dev)) { struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); disable_irq(dev->irq); spin_lock(&np->lock); @@ -2442,181 +2479,141 @@ static void set_rx_mode(struct net_device *dev) spin_unlock_irq(&np->lock); } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct netdev_private *np = netdev_priv(dev); - u32 cmd; - - if (get_user(cmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (cmd) { - /* get driver info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - 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, pci_name(np->pci_dev), - ETHTOOL_BUSINFO_LEN); - info.eedump_len = NATSEMI_EEPROM_SIZE; - info.regdump_len = NATSEMI_REGS_SIZE; - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - netdev_get_ecmd(dev, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - int r; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = netdev_set_ecmd(dev, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* get wake-on-lan */ - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - spin_lock_irq(&np->lock); - netdev_get_wol(dev, &wol.supported, &wol.wolopts); - netdev_get_sopass(dev, wol.sopass); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - /* set wake-on-lan */ - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - int r; - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - spin_lock_irq(&np->lock); - netdev_set_wol(dev, wol.wolopts); - r = netdev_set_sopass(dev, wol.sopass); - spin_unlock_irq(&np->lock); - return r; - } - /* get registers */ - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - u8 regbuf[NATSEMI_REGS_SIZE]; - int r; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; + strncpy(info->driver, DRV_NAME, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRV_VERSION, ETHTOOL_BUSINFO_LEN); + strncpy(info->bus_info, pci_name(np->pci_dev), ETHTOOL_BUSINFO_LEN); +} - if (regs.len > NATSEMI_REGS_SIZE) { - regs.len = NATSEMI_REGS_SIZE; - } - regs.version = NATSEMI_REGS_VER; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - return -EFAULT; +static int get_regs_len(struct net_device *dev) +{ + return NATSEMI_REGS_SIZE; +} - useraddr += offsetof(struct ethtool_regs, data); +static int get_eeprom_len(struct net_device *dev) +{ + return NATSEMI_EEPROM_SIZE; +} - spin_lock_irq(&np->lock); - r = netdev_get_regs(dev, regbuf); - spin_unlock_irq(&np->lock); +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + netdev_get_ecmd(dev, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - 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 = np->msg_enable; - 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; - np->msg_enable = 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, MII_BMCR); - if (tmp & BMCR_ANENABLE) { - tmp |= (BMCR_ANRESTART); - mdio_write(dev, MII_BMCR, tmp); - r = 0; - } - return r; - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - /* LSTATUS is latched low until a read - so read twice */ - mdio_read(dev, MII_BMSR); - edata.data = (mdio_read(dev, 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; +static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = netdev_set_ecmd(dev, ecmd); + spin_unlock_irq(&np->lock); + return res; +} - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; +static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + netdev_get_wol(dev, &wol->supported, &wol->wolopts); + netdev_get_sopass(dev, wol->sopass); + spin_unlock_irq(&np->lock); +} - if (eeprom.offset > eeprom.offset+eeprom.len) - return -EINVAL; +static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + netdev_set_wol(dev, wol->wolopts); + res = netdev_set_sopass(dev, wol->sopass); + spin_unlock_irq(&np->lock); + return res; +} - 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; +static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) +{ + struct netdev_private *np = netdev_priv(dev); + regs->version = NATSEMI_REGS_VER; + spin_lock_irq(&np->lock); + netdev_get_regs(dev, buf); + spin_unlock_irq(&np->lock); +} - useraddr += offsetof(struct ethtool_eeprom, data); +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; +} - spin_lock_irq(&np->lock); - r = netdev_get_eeprom(dev, eebuf); - spin_unlock_irq(&np->lock); +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; +} - if (r) - return r; - if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len)) - return -EFAULT; - return 0; +static int nway_reset(struct net_device *dev) +{ + int tmp; + int r = -EINVAL; + /* if autoneg is off, it's an error */ + tmp = mdio_read(dev, MII_BMCR); + if (tmp & BMCR_ANENABLE) { + tmp |= (BMCR_ANRESTART); + mdio_write(dev, MII_BMCR, tmp); + r = 0; } + return r; +} - } +static u32 get_link(struct net_device *dev) +{ + /* LSTATUS is latched low until a read - so read twice */ + mdio_read(dev, MII_BMSR); + return (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0; +} - return -EOPNOTSUPP; +static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) +{ + struct netdev_private *np = netdev_priv(dev); + u8 eebuf[NATSEMI_EEPROM_SIZE]; + int res; + + eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); + spin_lock_irq(&np->lock); + res = netdev_get_eeprom(dev, eebuf); + spin_unlock_irq(&np->lock); + if (!res) + memcpy(data, eebuf+eeprom->offset, eeprom->len); + return res; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = get_drvinfo, + .get_regs_len = get_regs_len, + .get_eeprom_len = get_eeprom_len, + .get_settings = get_settings, + .set_settings = set_settings, + .get_wol = get_wol, + .set_wol = set_wol, + .get_regs = get_regs, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, + .nway_reset = nway_reset, + .get_link = get_link, + .get_eeprom = get_eeprom, +}; + static int netdev_set_wol(struct net_device *dev, u32 newval) { struct netdev_private *np = netdev_priv(dev); - u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary; + void __iomem * ioaddr = ns_ioaddr(dev); + u32 data = readl(ioaddr + WOLCmd) & ~WakeOptsSummary; /* translate to bitmasks this chip understands */ if (newval & WAKE_PHY) @@ -2637,7 +2634,7 @@ static int netdev_set_wol(struct net_device *dev, u32 newval) } } - writel(data, dev->base_addr + WOLCmd); + writel(data, ioaddr + WOLCmd); return 0; } @@ -2645,7 +2642,8 @@ static int netdev_set_wol(struct net_device *dev, u32 newval) static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur) { struct netdev_private *np = netdev_priv(dev); - u32 regval = readl(dev->base_addr + WOLCmd); + void __iomem * ioaddr = ns_ioaddr(dev); + u32 regval = readl(ioaddr + WOLCmd); *supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_ARP | WAKE_MAGIC); @@ -2680,6 +2678,7 @@ static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur) static int netdev_set_sopass(struct net_device *dev, u8 *newval) { struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); u16 *sval = (u16 *)newval; u32 addr; @@ -2688,22 +2687,22 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval) } /* enable writing to these registers by disabling the RX filter */ - addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask; + addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask; addr &= ~RxFilterEnable; - writel(addr, dev->base_addr + RxFilterAddr); + writel(addr, ioaddr + RxFilterAddr); /* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */ - writel(addr | 0xa, dev->base_addr + RxFilterAddr); - writew(sval[0], dev->base_addr + RxFilterData); + writel(addr | 0xa, ioaddr + RxFilterAddr); + writew(sval[0], ioaddr + RxFilterData); - writel(addr | 0xc, dev->base_addr + RxFilterAddr); - writew(sval[1], dev->base_addr + RxFilterData); + writel(addr | 0xc, ioaddr + RxFilterAddr); + writew(sval[1], ioaddr + RxFilterData); - writel(addr | 0xe, dev->base_addr + RxFilterAddr); - writew(sval[2], dev->base_addr + RxFilterData); + writel(addr | 0xe, ioaddr + RxFilterAddr); + writew(sval[2], ioaddr + RxFilterData); /* re-enable the RX filter */ - writel(addr | RxFilterEnable, dev->base_addr + RxFilterAddr); + writel(addr | RxFilterEnable, ioaddr + RxFilterAddr); return 0; } @@ -2711,6 +2710,7 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval) static int netdev_get_sopass(struct net_device *dev, u8 *data) { struct netdev_private *np = netdev_priv(dev); + void __iomem * ioaddr = ns_ioaddr(dev); u16 *sval = (u16 *)data; u32 addr; @@ -2720,18 +2720,18 @@ static int netdev_get_sopass(struct net_device *dev, u8 *data) } /* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */ - addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask; + addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask; - writel(addr | 0xa, dev->base_addr + RxFilterAddr); - sval[0] = readw(dev->base_addr + RxFilterData); + writel(addr | 0xa, ioaddr + RxFilterAddr); + sval[0] = readw(ioaddr + RxFilterData); - writel(addr | 0xc, dev->base_addr + RxFilterAddr); - sval[1] = readw(dev->base_addr + RxFilterData); + writel(addr | 0xc, ioaddr + RxFilterAddr); + sval[1] = readw(ioaddr + RxFilterData); - writel(addr | 0xe, dev->base_addr + RxFilterAddr); - sval[2] = readw(dev->base_addr + RxFilterData); + writel(addr | 0xe, ioaddr + RxFilterAddr); + sval[2] = readw(ioaddr + RxFilterData); - writel(addr, dev->base_addr + RxFilterAddr); + writel(addr, ioaddr + RxFilterAddr); return 0; } @@ -2894,10 +2894,11 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf) int j; u32 rfcr; u32 *rbuf = (u32 *)buf; + void __iomem * ioaddr = ns_ioaddr(dev); /* read non-mii page 0 of registers */ for (i = 0; i < NATSEMI_PG0_NREGS/2; i++) { - rbuf[i] = readl(dev->base_addr + i*4); + rbuf[i] = readl(ioaddr + i*4); } /* read current mii registers */ @@ -2905,20 +2906,20 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf) rbuf[i] = mdio_read(dev, i & 0x1f); /* 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); + writew(1, ioaddr + PGSEL); + rbuf[i++] = readw(ioaddr + PMDCSR); + rbuf[i++] = readw(ioaddr + TSTDAT); + rbuf[i++] = readw(ioaddr + DSPCFG); + rbuf[i++] = readw(ioaddr + SDCFG); + writew(0, ioaddr + PGSEL); /* read RFCR indexed registers */ - rfcr = readl(dev->base_addr + RxFilterAddr); + rfcr = readl(ioaddr + RxFilterAddr); for (j = 0; j < NATSEMI_RFDR_NREGS; j++) { - writel(j*2, dev->base_addr + RxFilterAddr); - rbuf[i++] = readw(dev->base_addr + RxFilterData); + writel(j*2, ioaddr + RxFilterAddr); + rbuf[i++] = readw(ioaddr + RxFilterData); } - writel(rfcr, dev->base_addr + RxFilterAddr); + writel(rfcr, ioaddr + RxFilterAddr); /* the interrupt status is clear-on-read - see if we missed any */ if (rbuf[4] & rbuf[5]) { @@ -2943,10 +2944,11 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf) { int i; u16 *ebuf = (u16 *)buf; + void __iomem * ioaddr = ns_ioaddr(dev); /* 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); + ebuf[i] = eeprom_read(ioaddr, 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. */ @@ -2961,8 +2963,6 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) struct netdev_private *np = netdev_priv(dev); switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); case SIOCGMIIPHY: /* Get address of MII PHY in use. */ case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ data->phy_id = np->phy_addr_external; @@ -3016,7 +3016,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static void enable_wol_mode(struct net_device *dev, int enable_intr) { - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); struct netdev_private *np = netdev_priv(dev); if (netif_msg_wol(np)) @@ -3049,7 +3049,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr) static int netdev_close(struct net_device *dev) { - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); struct netdev_private *np = netdev_priv(dev); if (netif_msg_ifdown(np)) @@ -3126,10 +3126,11 @@ static int netdev_close(struct net_device *dev) static void __devexit natsemi_remove1 (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + void __iomem * ioaddr = ns_ioaddr(dev); unregister_netdev (dev); pci_release_regions (pdev); - iounmap ((char *) dev->base_addr); + iounmap(ioaddr); free_netdev (dev); pci_set_drvdata(pdev, NULL); } @@ -3163,7 +3164,7 @@ static int natsemi_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata (pdev); struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem * ioaddr = ns_ioaddr(dev); rtnl_lock(); if (netif_running (dev)) { diff --git a/drivers/net/ne.c b/drivers/net/ne.c index a4116f136..d9a9a0bb7 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -29,6 +29,7 @@ last in cleanup_modue() Richard Guenther : Added support for ISAPnP cards Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead. + Hayato Fujiwara : Add m32r support. */ @@ -128,6 +129,14 @@ bad_clone_list[] __initdata = { #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ +#ifdef CONFIG_PLAT_MAPPI +# define DCR_VAL 0x4b +#elif CONFIG_PLAT_OAKS32R +# define DCR_VAL 0x48 +#else +# define DCR_VAL 0x49 +#endif + static int ne_probe1(struct net_device *dev, int ioaddr); static int ne_probe_isapnp(struct net_device *dev); @@ -387,7 +396,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) for (i = 0; i < 16; i++) SA_prom[i] = SA_prom[i+i]; /* We must set the 8390 for word mode. */ - outb_p(0x49, ioaddr + EN0_DCFG); + outb_p(DCR_VAL, ioaddr + EN0_DCFG); start_page = NESM_START_PG; stop_page = NESM_STOP_PG; } else { @@ -395,7 +404,12 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) stop_page = NE1SM_STOP_PG; } +#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R) + neX000 = ((SA_prom[14] == 0x57 && SA_prom[15] == 0x57) + || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42)); +#else neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); +#endif ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00); @@ -476,10 +490,20 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) dev->base_addr = ioaddr; +#ifdef CONFIG_PLAT_MAPPI + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, + ioaddr + E8390_CMD); /* 0x61 */ + for (i = 0 ; i < ETHER_ADDR_LEN ; i++) { + dev->dev_addr[i] = SA_prom[i] + = inb_p(ioaddr + EN1_PHYS_SHIFT(i)); + printk(" %2.2x", SA_prom[i]); + } +#else for(i = 0; i < ETHER_ADDR_LEN; i++) { printk(" %2.2x", SA_prom[i]); dev->dev_addr[i] = SA_prom[i]; } +#endif printk("\n%s: %s found at %#x, using IRQ %d.\n", dev->name, name, ioaddr, dev->irq); @@ -487,7 +511,11 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) ei_status.name = name; ei_status.tx_start_page = start_page; ei_status.stop_page = stop_page; +#ifdef CONFIG_PLAT_OAKS32R + ei_status.word16 = 0; +#else ei_status.word16 = (wordlength == 2); +#endif ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c index 5d690c9f1..4fe6e7574 100644 --- a/drivers/net/ne2.c +++ b/drivers/net/ne2.c @@ -74,9 +74,9 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon #include #include +#include #include -#include #include #include diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index ed15b19eb..ae0698bd7 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -653,12 +653,43 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +#ifdef CONFIG_PM +static int ne2k_pci_suspend (struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata (pdev); + + netif_device_detach(dev); + pci_save_state(pdev); + pci_set_power_state(pdev, state); + + return 0; +} + +static int ne2k_pci_resume (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata (pdev); + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + NS8390_init(dev, 1); + netif_device_attach(dev); + + return 0; +} + +#endif /* CONFIG_PM */ + static struct pci_driver ne2k_driver = { .name = DRV_NAME, .probe = ne2k_pci_init_one, .remove = __devexit_p(ne2k_pci_remove_one), .id_table = ne2k_pci_tbl, +#ifdef CONFIG_PM + .suspend = ne2k_pci_suspend, + .resume = ne2k_pci_resume, +#endif /* CONFIG_PM */ + }; diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index 854bc2b70..1f9e0ddf9 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -105,260 +105,6 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *mask, } EXPORT_SYMBOL(alloc_netdev); -/** - * alloc_etherdev - Allocates and sets up an ethernet device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with ethernet-generic - * values. Basically does everything except registering the device. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_etherdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "eth%d", ether_setup); -} - -EXPORT_SYMBOL(alloc_etherdev); - -static int eth_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr=p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - return 0; -} - -static int eth_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -#ifdef CONFIG_FDDI - -/** - * alloc_fddidev - Register FDDI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this FDDI device - * - * Fill in the fields of the device structure with FDDI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fddidev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fddi%d", fddi_setup); -} - -EXPORT_SYMBOL(alloc_fddidev); - -static int fddi_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN)) - return(-EINVAL); - dev->mtu = new_mtu; - return(0); -} - -#endif /* CONFIG_FDDI */ - -#ifdef CONFIG_HIPPI - -static int hippi_change_mtu(struct net_device *dev, int new_mtu) -{ - /* - * HIPPI's got these nice large MTUs. - */ - if ((new_mtu < 68) || (new_mtu > 65280)) - return -EINVAL; - dev->mtu = new_mtu; - return(0); -} - - -/* - * For HIPPI we will actually use the lower 4 bytes of the hardware - * address as the I-FIELD rather than the actual hardware address. - */ -static int hippi_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -static int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p) -{ - /* Never send broadcast/multicast ARP messages */ - p->mcast_probes = 0; - - /* In IPv6 unicast probes are valid even on NBMA, - * because they are encapsulated in normal IPv6 protocol. - * Should be a generic flag. - */ - if (p->tbl->family != AF_INET6) - p->ucast_probes = 0; - return 0; -} - -static void hippi_setup(struct net_device *dev) -{ - dev->set_multicast_list = NULL; - dev->change_mtu = hippi_change_mtu; - dev->hard_header = hippi_header; - dev->rebuild_header = hippi_rebuild_header; - dev->set_mac_address = hippi_mac_addr; - dev->hard_header_parse = NULL; - dev->hard_header_cache = NULL; - dev->header_cache_update = NULL; - dev->neigh_setup = hippi_neigh_setup_dev; - - /* - * We don't support HIPPI `ARP' for the time being, and probably - * never will unless someone else implements it. However we - * still need a fake ARPHRD to make ifconfig and friends play ball. - */ - dev->type = ARPHRD_HIPPI; - dev->hard_header_len = HIPPI_HLEN; - dev->mtu = 65280; - dev->addr_len = HIPPI_ALEN; - dev->tx_queue_len = 25 /* 5 */; - memset(dev->broadcast, 0xFF, HIPPI_ALEN); - - - /* - * HIPPI doesn't support broadcast+multicast and we only use - * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. - */ - dev->flags = 0; -} - -/** - * alloc_hippi_dev - Register HIPPI device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this HIPPI device - * - * Fill in the fields of the device structure with HIPPI-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_hippi_dev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "hip%d", hippi_setup); -} - -EXPORT_SYMBOL(alloc_hippi_dev); - -#endif /* CONFIG_HIPPI */ - -void ether_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with ethernet-generic values. - This should be in a common file instead of per-driver. */ - - dev->change_mtu = eth_change_mtu; - dev->hard_header = eth_header; - dev->rebuild_header = eth_rebuild_header; - dev->set_mac_address = eth_mac_addr; - dev->hard_header_cache = eth_header_cache; - dev->header_cache_update= eth_header_cache_update; - dev->hard_header_parse = eth_header_parse; - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = ETH_HLEN; - dev->mtu = 1500; /* eth_mtu */ - dev->addr_len = ETH_ALEN; - dev->tx_queue_len = 1000; /* Ethernet wants good queues */ - - memset(dev->broadcast,0xFF, ETH_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST|IFF_MULTICAST; -} -EXPORT_SYMBOL(ether_setup); - -#ifdef CONFIG_FDDI - -void fddi_setup(struct net_device *dev) -{ - /* - * Fill in the fields of the device structure with FDDI-generic values. - * This should be in a common file instead of per-driver. - */ - - dev->change_mtu = fddi_change_mtu; - dev->hard_header = fddi_header; - dev->rebuild_header = fddi_rebuild_header; - - dev->type = ARPHRD_FDDI; - dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ - dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ - dev->addr_len = FDDI_K_ALEN; - dev->tx_queue_len = 100; /* Long queues on FDDI */ - - memset(dev->broadcast, 0xFF, FDDI_K_ALEN); - - /* New-style flags */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST; -} -EXPORT_SYMBOL(fddi_setup); - -#endif /* CONFIG_FDDI */ - -#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) - -static int ltalk_change_mtu(struct net_device *dev, int mtu) -{ - return -EINVAL; -} - -static int ltalk_mac_addr(struct net_device *dev, void *addr) -{ - return -EINVAL; -} - - -void ltalk_setup(struct net_device *dev) -{ - /* Fill in the fields of the device structure with localtalk-generic values. */ - - dev->change_mtu = ltalk_change_mtu; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = ltalk_mac_addr; - dev->hard_header_cache = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_LOCALTLK; - dev->hard_header_len = LTALK_HLEN; - dev->mtu = LTALK_MTU; - dev->addr_len = LTALK_ALEN; - dev->tx_queue_len = 10; - - dev->broadcast[0] = 0xFF; - - dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; -} -EXPORT_SYMBOL(ltalk_setup); - -#endif /* CONFIG_ATALK || CONFIG_ATALK_MODULE */ - int register_netdev(struct net_device *dev) { int err; @@ -404,90 +150,3 @@ void unregister_netdev(struct net_device *dev) EXPORT_SYMBOL(register_netdev); EXPORT_SYMBOL(unregister_netdev); - -#ifdef CONFIG_TR - -void tr_setup(struct net_device *dev) -{ - /* - * Configure and register - */ - - dev->hard_header = tr_header; - dev->rebuild_header = tr_rebuild_header; - - dev->type = ARPHRD_IEEE802_TR; - dev->hard_header_len = TR_HLEN; - dev->mtu = 2000; - dev->addr_len = TR_ALEN; - dev->tx_queue_len = 100; /* Long queues on tr */ - - memset(dev->broadcast,0xFF, TR_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST | IFF_MULTICAST ; -} - -/** - * alloc_trdev - Register token ring device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this token ring device - * - * Fill in the fields of the device structure with token ring-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_trdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "tr%d", tr_setup); -} - -EXPORT_SYMBOL(tr_setup); -EXPORT_SYMBOL(alloc_trdev); - -#endif /* CONFIG_TR */ - -#ifdef CONFIG_NET_FC - -void fc_setup(struct net_device *dev) -{ - dev->hard_header = fc_header; - dev->rebuild_header = fc_rebuild_header; - - dev->type = ARPHRD_IEEE802; - dev->hard_header_len = FC_HLEN; - dev->mtu = 2024; - dev->addr_len = FC_ALEN; - dev->tx_queue_len = 100; /* Long queues on fc */ - - memset(dev->broadcast,0xFF, FC_ALEN); - - /* New-style flags. */ - dev->flags = IFF_BROADCAST; -} - -/** - * alloc_fcdev - Register fibre channel device - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this fibre channel device - * - * Fill in the fields of the device structure with fibre channel-generic values. - * - * Constructs a new net device, complete with a private data area of - * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for - * this private data area. - */ - -struct net_device *alloc_fcdev(int sizeof_priv) -{ - return alloc_netdev(sizeof_priv, "fc%d", fc_setup); -} - -EXPORT_SYMBOL(fc_setup); -EXPORT_SYMBOL(alloc_fcdev); - -#endif /* CONFIG_NET_FC */ - diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 8124ad671..2ab01a5d1 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -59,7 +59,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 234709ded..a76c8575c 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -115,7 +115,7 @@ static int fifo=0x8; /* don't change */ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index c43c4cf9e..fd58f0d9e 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -73,8 +73,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index c2551c5fb..7b9d83b07 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -64,6 +64,8 @@ * tuning * 0.20 - fix stupid RFEN thinko. i am such a smurf. * + * 20040828 0.21 - add hardware vlan accleration + * by Neil Horman * Driver Overview * =============== * @@ -92,7 +94,9 @@ //#define dprintk printk #define dprintk(x...) do { } while (0) +#include #include +#include #include #include #include @@ -108,6 +112,7 @@ #include #include #include +#include #include #include @@ -115,7 +120,7 @@ #define DRV_NAME "ns83820" -/* Global parameters. See MODULE_PARM near the bottom. */ +/* Global parameters. See module_param near the bottom. */ static int ihr = 2; static int reset_phy = 0; static int lnksts = 0; /* CFG_LNKSTS bit polarity */ @@ -138,6 +143,9 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ /* tunables */ #define RX_BUF_SIZE 1500 /* 8192 */ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#define NS83820_VLAN_ACCEL_SUPPORT +#endif /* Must not exceed ~65000. */ #define NR_RX_DESC 64 @@ -262,6 +270,8 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define EXTSTS_UDPPKT 0x00200000 #define EXTSTS_TCPPKT 0x00080000 #define EXTSTS_IPPKT 0x00020000 +#define EXTSTS_VPKT 0x00010000 +#define EXTSTS_VTG_MASK 0x0000ffff #define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0)) @@ -403,6 +413,7 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define CMDSTS_INTR 0x20000000 #define CMDSTS_ERR 0x10000000 #define CMDSTS_OK 0x08000000 +#define CMDSTS_RUNT 0x00200000 #define CMDSTS_LEN_MASK 0x0000ffff #define CMDSTS_DEST_MASK 0x01800000 @@ -428,10 +439,14 @@ struct rx_info { struct ns83820 { struct net_device_stats stats; - u8 *base; + u8 __iomem *base; struct pci_dev *pci_dev; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + struct vlan_group *vlgrp; +#endif + struct rx_info rx_info; struct tasklet_struct rx_tasklet; @@ -494,6 +509,33 @@ static inline void kick_rx(struct net_device *ndev) (((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE) +#ifdef NS83820_VLAN_ACCEL_SUPPORT +static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp) +{ + struct ns83820 *dev = PRIV(ndev); + + spin_lock_irq(&dev->misc_lock); + spin_lock(&dev->tx_lock); + + dev->vlgrp = grp; + + spin_unlock(&dev->tx_lock); + spin_unlock_irq(&dev->misc_lock); +} + +static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) +{ + struct ns83820 *dev = PRIV(ndev); + + spin_lock_irq(&dev->misc_lock); + spin_lock(&dev->tx_lock); + if (dev->vlgrp) + dev->vlgrp->vlan_devices[vid] = NULL; + spin_unlock(&dev->tx_lock); + spin_unlock_irq(&dev->misc_lock); +} +#endif + /* Packet Receiver * * The hardware supports linked lists of receive descriptors for @@ -836,6 +878,7 @@ static void fastcall rx_irq(struct net_device *ndev) struct ns83820 *dev = PRIV(ndev); struct rx_info *info = &dev->rx_info; unsigned next_rx; + int rx_rc, len; u32 cmdsts, *desc; unsigned long flags; int nr = 0; @@ -876,8 +919,24 @@ static void fastcall rx_irq(struct net_device *ndev) pci_unmap_single(dev->pci_dev, bufptr, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + len = cmdsts & CMDSTS_LEN_MASK; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + /* NH: As was mentioned below, this chip is kinda + * brain dead about vlan tag stripping. Frames + * that are 64 bytes with a vlan header appended + * like arp frames, or pings, are flagged as Runts + * when the tag is stripped and hardware. This + * also means that the OK bit in the descriptor + * is cleared when the frame comes in so we have + * to do a specific length check here to make sure + * the frame would have been ok, had we not stripped + * the tag. + */ + if (likely((CMDSTS_OK & cmdsts) || + ((cmdsts & CMDSTS_RUNT) && len >= 56))) { +#else if (likely(CMDSTS_OK & cmdsts)) { - int len = cmdsts & 0xffff; +#endif skb_put(skb, len); if (unlikely(!skb)) goto netdev_mangle_me_harder_failed; @@ -891,7 +950,18 @@ static void fastcall rx_irq(struct net_device *ndev) skb->ip_summed = CHECKSUM_NONE; } skb->protocol = eth_type_trans(skb, ndev); - if (NET_RX_DROP == netif_rx(skb)) { +#ifdef NS83820_VLAN_ACCEL_SUPPORT + if(extsts & EXTSTS_VPKT) { + unsigned short tag; + tag = ntohs(extsts & EXTSTS_VTG_MASK); + rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag); + } else { + rx_rc = netif_rx(skb); + } +#else + rx_rc = netif_rx(skb); +#endif + if (NET_RX_DROP == rx_rc) { netdev_mangle_me_harder_failed: dev->stats.rx_dropped ++; } @@ -1099,6 +1169,17 @@ again: extsts |= EXTSTS_UDPPKT; } +#ifdef NS83820_VLAN_ACCEL_SUPPORT + if(vlan_tx_tag_present(skb)) { + /* fetch the vlan tag info out of the + * ancilliary data if the vlan code + * is using hw vlan acceleration + */ + short tag = vlan_tx_tag_get(skb); + extsts |= (EXTSTS_VPKT | htons(tag)); + } +#endif + len = skb->len; if (nr_frags) len -= skb->data_len; @@ -1164,7 +1245,7 @@ again: static void ns83820_update_stats(struct ns83820 *dev) { - u8 *base = dev->base; + u8 __iomem *base = dev->base; /* the DP83820 will freeze counters, so we need to read all of them */ dev->stats.rx_errors += readl(base + 0x60) & 0xffff; @@ -1192,59 +1273,26 @@ static struct net_device_stats *ns83820_get_stats(struct net_device *ndev) return &dev->stats; } -static int ns83820_ethtool_ioctl (struct ns83820 *dev, void __user *useraddr) +static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "ns83820"); - strcpy(info.version, VERSION); - strcpy(info.bus_info, pci_name(dev->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; - - if (cfg & CFG_LNKSTS) - edata.data = 1; - else - edata.data = 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - default: - break; - } - - return -EOPNOTSUPP; + struct ns83820 *dev = PRIV(ndev); + strcpy(info->driver, "ns83820"); + strcpy(info->version, VERSION); + strcpy(info->bus_info, pci_name(dev->pci_dev)); } -static int ns83820_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +static u32 ns83820_get_link(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - - switch(cmd) { - case SIOCETHTOOL: - return ns83820_ethtool_ioctl(dev, rq->ifr_data); - - default: - return -EOPNOTSUPP; - } + u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; + return cfg & CFG_LNKSTS ? 1 : 0; } +static struct ethtool_ops ops = { + .get_drvinfo = ns83820_get_drvinfo, + .get_link = ns83820_get_link +}; + static void ns83820_mib_isr(struct ns83820 *dev) { spin_lock(&dev->misc_lock); @@ -1545,7 +1593,7 @@ static int ns83820_change_mtu(struct net_device *ndev, int new_mtu) static void ns83820_set_multicast(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - u8 *rfcr = dev->base + RFCR; + u8 __iomem *rfcr = dev->base + RFCR; u32 and_mask = 0xffffffff; u32 or_mask = 0; u32 val; @@ -1849,7 +1897,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ dev->IMR_cache = 0; - setup_ee_mem_bitbanger(&dev->ee, (long)dev->base + MEAR, 3, 2, 1, 0, + setup_ee_mem_bitbanger(&dev->ee, dev->base + MEAR, 3, 2, 1, 0, 0); err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, @@ -1884,10 +1932,9 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev->get_stats = ns83820_get_stats; ndev->change_mtu = ns83820_change_mtu; ndev->set_multicast_list = ns83820_set_multicast; - ndev->do_ioctl = ns83820_ioctl; + SET_ETHTOOL_OPS(ndev, &ops); ndev->tx_timeout = ns83820_tx_timeout; ndev->watchdog_timeo = 5 * HZ; - pci_set_drvdata(pci_dev, ndev); ns83820_do_reset(dev, CR_RST); @@ -2013,11 +2060,25 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ * a ping with a VLAN header) then the card, strips the 4 byte VLAN * tag and then checks the packet size, so if RXCFG_ARP is not enabled, * it discrards it!. These guys...... + * also turn on tag stripping if hardware acceleration is enabled */ - writel(VRCR_IPEN | VRCR_VTDEN, dev->base + VRCR); +#ifdef NS83820_VLAN_ACCEL_SUPPORT +#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN|VRCR_VTREN) +#else +#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN) +#endif + writel(VRCR_INIT_VALUE, dev->base + VRCR); - /* Enable per-packet TCP/UDP/IP checksumming */ - writel(VTCR_PPCHK, dev->base + VTCR); + /* Enable per-packet TCP/UDP/IP checksumming + * and per packet vlan tag insertion if + * vlan hardware acceleration is enabled + */ +#ifdef NS83820_VLAN_ACCEL_SUPPORT +#define VTCR_INIT_VALUE (VTCR_PPCHK|VTCR_VPPTI) +#else +#define VTCR_INIT_VALUE VTCR_PPCHK +#endif + writel(VTCR_INIT_VALUE, dev->base + VTCR); /* Ramit : Enable async and sync pause frames */ /* writel(0, dev->base + PCR); */ @@ -2034,6 +2095,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev->features |= NETIF_F_SG; ndev->features |= NETIF_F_IP_CSUM; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + /* We also support hardware vlan acceleration */ + ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + ndev->vlan_rx_register = ns83820_vlan_rx_register; + ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid; +#endif + if (using_dac) { printk(KERN_INFO "%s: using 64 bit addressing.\n", ndev->name); @@ -2142,13 +2210,13 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, ns83820_pci_tbl); -MODULE_PARM(lnksts, "i"); +module_param(lnksts, int, 0); MODULE_PARM_DESC(lnksts, "Polarity of LNKSTS bit"); -MODULE_PARM(ihr, "i"); +module_param(ihr, int, 0); MODULE_PARM_DESC(ihr, "Time in 100 us increments to delay interrupts (range 0-127)"); -MODULE_PARM(reset_phy, "i"); +module_param(reset_phy, int, 0); MODULE_PARM_DESC(reset_phy, "Set to 1 to reset the PHY on startup"); module_init(ns83820_init); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index f93124898..81dee74b4 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -481,7 +481,6 @@ struct netdrv_private { unsigned int mediasense:1; /* Media sensing in progress. */ spinlock_t lock; chip_t chipset; - u32 pci_state[16]; /* Data saved during suspend */ }; MODULE_AUTHOR ("Jeff Garzik "); @@ -796,7 +795,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, tp->pci_dev = pdev; tp->board = ent->driver_data; tp->mmio_addr = ioaddr; - tp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&tp->lock); pci_set_drvdata(pdev, dev); @@ -1921,7 +1920,7 @@ static int netdrv_suspend (struct pci_dev *pdev, u32 state) spin_unlock_irqrestore (&tp->lock, flags); - pci_save_state (pdev, tp->pci_state); + pci_save_state (pdev); pci_set_power_state (pdev, 3); return 0; @@ -1936,7 +1935,7 @@ static int netdrv_resume (struct pci_dev *pdev) if (!netif_running(dev)) return 0; pci_set_power_state (pdev, 0); - pci_restore_state (pdev, tp->pci_state); + pci_restore_state (pdev); netif_device_attach (dev); netdrv_hw_start (dev); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 7c4ed0ddd..b5c99d2f3 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -84,6 +84,7 @@ earlier 3Com products. #include #include #include +#include #include #include @@ -97,7 +98,6 @@ earlier 3Com products. #include #include #include -#include /*====================================================================*/ diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 2e0135dad..970ed7bb5 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,6 @@ #include #include #include -#include /* To minimize the size of the driver source I only define operating constants if they are used several times. You'll need the manual diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 0d9a06f8c..3029129ae 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -936,7 +936,7 @@ module_exit(exit_axnet_cs); static const char *version_8390 = "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@scyld.com)\n"; -#include +#include #include #include #include diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 947dad4ca..0ec78c327 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -144,6 +144,7 @@ Include Files #include #include #include +#include #include #include @@ -155,7 +156,6 @@ Include Files #include #include #include -#include /* ---------------------------------------------------------------------------- Defines diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 49d60d9ca..dc560feaa 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -304,6 +304,7 @@ static void mdio_sync(ioaddr_t addr); static int mdio_read(struct net_device *dev, int phy_id, int loc); static void mdio_write(struct net_device *dev, int phy_id, int loc, int value); static int smc_link_ok(struct net_device *dev); +static struct ethtool_ops ethtool_ops; /*====================================================================== @@ -357,6 +358,7 @@ static dev_link_t *smc91c92_attach(void) dev->open = &smc_open; dev->stop = &smc_close; dev->do_ioctl = &smc_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = smc_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -2113,136 +2115,135 @@ static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) tmp |= TCR_FDUPLX; else tmp &= ~TCR_FDUPLX; - outw(ioaddr + TCR, tmp); + outw(tmp, ioaddr + TCR); return 0; } -static int smc_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - u32 ethcmd; - struct smc_private *smc = netdev_priv(dev); - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; + if (!netif_running(dev)) + return -EINVAL; return 0; - } +} + +static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); +} - /* get settings */ - case ETHTOOL_GSET: { +static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); if (smc->cfg & CFG_MII_SELECT) - ret = mii_ethtool_gset(&smc->mii_if, &ecmd); + ret = mii_ethtool_gset(&smc->mii_if, ecmd); else - ret = smc_netdev_get_ecmd(dev, &ecmd); + ret = smc_netdev_get_ecmd(dev, ecmd); spin_unlock_irq(&smc->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; + SMC_SELECT_BANK(saved_bank); return ret; - } +} - /* set settings */ - case ETHTOOL_SSET: { +static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; + + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); if (smc->cfg & CFG_MII_SELECT) - ret = mii_ethtool_sset(&smc->mii_if, &ecmd); + ret = mii_ethtool_sset(&smc->mii_if, ecmd); else - ret = smc_netdev_set_ecmd(dev, &ecmd); + ret = smc_netdev_set_ecmd(dev, ecmd); spin_unlock_irq(&smc->lock); + SMC_SELECT_BANK(saved_bank); return ret; - } +} + +static u32 smc_get_link(struct net_device *dev) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); + u32 ret; - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); - edata.data = smc_link_ok(dev); + ret = smc_link_ok(dev); spin_unlock_irq(&smc->lock); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + SMC_SELECT_BANK(saved_bank); + return ret; +} #ifdef PCMCIA_DEBUG - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - edata.data = pc_debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static u32 smc_get_msglevel(struct net_device *dev) +{ + return pc_debug; +} - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - pc_debug = edata.data; - return 0; - } +static void smc_set_msglevel(struct net_device *dev, u32 val) +{ + pc_debug = val; +} #endif - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - if (smc->cfg & CFG_MII_SELECT) - return mii_nway_restart(&smc->mii_if); - else - return -EOPNOTSUPP; - } - - default: - break; - } - return -EOPNOTSUPP; +static int smc_nway_reset(struct net_device *dev) +{ + struct smc_private *smc = netdev_priv(dev); + if (smc->cfg & CFG_MII_SELECT) { + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); + int res; + + SMC_SELECT_BANK(3); + res = mii_nway_restart(&smc->mii_if); + SMC_SELECT_BANK(saved_bank); + + return res; + } else + return -EOPNOTSUPP; } +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = smc_get_drvinfo, + .get_settings = smc_get_settings, + .set_settings = smc_set_settings, + .get_link = smc_get_link, +#ifdef PCMCIA_DEBUG + .get_msglevel = smc_get_msglevel, + .set_msglevel = smc_set_msglevel, +#endif + .nway_reset = smc_nway_reset, +}; + static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { - struct smc_private *smc = netdev_priv(dev); - struct mii_ioctl_data *mii; - int rc = 0; - u_short saved_bank; - ioaddr_t ioaddr = dev->base_addr; - - mii = if_mii(rq); - if (!netif_running(dev)) - return -EINVAL; + struct smc_private *smc = netdev_priv(dev); + struct mii_ioctl_data *mii = if_mii(rq); + int rc = 0; + u16 saved_bank; + ioaddr_t ioaddr = dev->base_addr; - switch (cmd) { - case SIOCETHTOOL: - saved_bank = inw(ioaddr + BANK_SELECT); - SMC_SELECT_BANK(3); - rc = smc_ethtool_ioctl(dev, rq->ifr_data); - SMC_SELECT_BANK(saved_bank); - break; + if (!netif_running(dev)) + return -EINVAL; - default: spin_lock_irq(&smc->lock); saved_bank = inw(ioaddr + BANK_SELECT); SMC_SELECT_BANK(3); rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); SMC_SELECT_BANK(saved_bank); spin_unlock_irq(&smc->lock); - break; - } - - return rc; + return rc; } static struct pcmcia_driver smc91c92_cs_driver = { diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 5be2ba3b0..25c2fc991 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -89,7 +90,6 @@ #include #include -#include #include #ifndef MANFID_COMPAQ diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index effbad31d..381b78590 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -47,8 +47,8 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n"; #include #include #include +#include -#include #include #include #include @@ -359,9 +359,9 @@ struct pcnet32_private { struct net_device_stats stats; char tx_full; int options; - int shared_irq:1, /* shared irq possible */ - dxsuflo:1, /* disable transmit stop on uflo */ - mii:1; /* mii port available */ + unsigned int shared_irq:1, /* shared irq possible */ + dxsuflo:1, /* disable transmit stop on uflo */ + mii:1; /* mii port available */ struct net_device *next; struct mii_if_info mii_if; struct timer_list watchdog_timer; @@ -1010,7 +1010,11 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) return -EBUSY; } - return pcnet32_probe1(ioaddr, 1, pdev); + err = pcnet32_probe1(ioaddr, 1, pdev); + if (err < 0) { + pci_disable_device(pdev); + } + return err; } @@ -2249,6 +2253,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev) release_region(dev->base_addr, PCNET32_TOTAL_SIZE); pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } } @@ -2264,7 +2269,6 @@ static struct pci_driver pcnet32_driver = { static int debug = -1; static int tx_start_pt = -1; static int pcnet32_have_pci; -static int num_params; module_param(debug, int, 0); MODULE_PARM_DESC(debug, DRV_NAME " debug level"); @@ -2276,12 +2280,12 @@ module_param(tx_start_pt, int, 0); MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); module_param(pcnet32vlb, int, 0); MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); -module_param_array(options, int, num_params, 0); +module_param_array(options, int, NULL, 0); MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); -module_param_array(full_duplex, int, num_params, 0); +module_param_array(full_duplex, int, NULL, 0); MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)"); /* Module Parameter for HomePNA cards added by Patrick Simmons, 2004 */ -module_param_array(homepna, int, num_params, 0); +module_param_array(homepna, int, NULL, 0); MODULE_PARM_DESC(homepna, DRV_NAME " mode for 79C978 cards (1 for HomePNA, 0 for Ethernet, default Ethernet"); MODULE_AUTHOR("Thomas Bogendoerfer"); diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 43f923c96..3dd010328 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -109,11 +109,11 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n" #include #include #include +#include #include #include -#include #include #include #include @@ -547,7 +547,7 @@ static unsigned short plip_type_trans(struct sk_buff *skb, struct net_device *de skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); - eth= skb->mac.ethernet; + eth = eth_hdr(skb); if(*eth->h_dest&1) { diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index e44b189c6..e8be5a26d 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -122,6 +122,9 @@ static struct ppp_channel_ops async_ops = { * frees the memory that ppp_asynctty_receive is using. The best * way to fix this is to use a rwlock in the tty struct, but for now * we use a single global rwlock for all ttys in ppp line discipline. + * + * FIXME: this is no longer true. The _close path for the ldisc is + * now guaranteed to be sane. */ static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED; @@ -144,7 +147,8 @@ static void ap_put(struct asyncppp *ap) } /* - * Called when a tty is put into PPP line discipline. + * Called when a tty is put into PPP line discipline. Called in process + * context. */ static int ppp_asynctty_open(struct tty_struct *tty) @@ -233,6 +237,18 @@ ppp_asynctty_close(struct tty_struct *tty) kfree(ap); } +/* + * Called on tty hangup in process context. + * + * Wait for I/O to driver to complete and unregister PPP channel. + * This is already done by the close routine, so just call that. + */ +static int ppp_asynctty_hangup(struct tty_struct *tty) +{ + ppp_asynctty_close(tty); + return 0; +} + /* * Read does nothing - no data is ever available this way. * Pppd reads and writes packets via /dev/ppp instead. @@ -250,11 +266,16 @@ ppp_asynctty_read(struct tty_struct *tty, struct file *file, */ static ssize_t ppp_asynctty_write(struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, size_t count) + const unsigned char *buf, size_t count) { return -EAGAIN; } +/* + * Called in process context only. May be re-entered by multiple + * ioctl calling threads. + */ + static int ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) @@ -371,6 +392,7 @@ static struct tty_ldisc ppp_ldisc = { .name = "ppp", .open = ppp_asynctty_open, .close = ppp_asynctty_close, + .hangup = ppp_asynctty_hangup, .read = ppp_asynctty_read, .write = ppp_asynctty_write, .ioctl = ppp_asynctty_ioctl, @@ -664,7 +686,7 @@ ppp_async_push(struct asyncppp *ap) if (!tty_stuffed && ap->optr < ap->olim) { avail = ap->olim - ap->optr; set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->driver->write(tty, 0, ap->optr, avail); + sent = tty->driver->write(tty, ap->optr, avail); if (sent < 0) goto flush; /* error, e.g. loss of CD */ ap->optr += sent; @@ -716,7 +738,8 @@ flush: /* * Flush output from our internal buffers. - * Called for the TCFLSH ioctl. + * Called for the TCFLSH ioctl. Can be entered in parallel + * but this is covered by the xmit_lock. */ static void ppp_async_flush_output(struct asyncppp *ap) @@ -816,7 +839,9 @@ process_input_packet(struct asyncppp *ap) skb_trim(skb, 0); } -/* called when the tty driver has data for us. */ +/* Called when the tty driver has data for us. Runs parallel with the + other ldisc functions but will not be re-entered */ + static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf, char *flags, int count) @@ -886,7 +911,9 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, break; c = buf[n]; - if (c == PPP_FLAG) { + if (flags != NULL && flags[n] != 0) { + ap->state |= SC_TOSS; + } else if (c == PPP_FLAG) { process_input_packet(ap); } else if (c == PPP_ESCAPE) { ap->state |= SC_ESCAPE; diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c index c51291a3c..df75c94e1 100644 --- a/drivers/net/ppp_deflate.c +++ b/drivers/net/ppp_deflate.c @@ -636,7 +636,7 @@ struct compressor ppp_deflate_draft = { .owner = THIS_MODULE }; -int __init deflate_init(void) +static int __init deflate_init(void) { int answer = ppp_register_compressor(&ppp_deflate); if (answer == 0) @@ -646,7 +646,7 @@ int __init deflate_init(void) return answer; } -void __exit deflate_cleanup(void) +static void __exit deflate_cleanup(void) { ppp_unregister_compressor(&ppp_deflate); ppp_unregister_compressor(&ppp_deflate_draft); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 651601105..c50980e8a 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -19,7 +19,7 @@ * PPP driver, written by Michael Callahan and Al Longyear, and * subsequently hacked by Paul Mackerras. * - * ==FILEVERSION 20020217== + * ==FILEVERSION 20041108== */ #include @@ -412,6 +412,17 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ret = 0; if (pf->dead) break; + if (pf->kind == INTERFACE) { + /* + * Return 0 (EOF) on an interface that has no + * channels connected, unless it is looping + * network traffic (demand mode). + */ + struct ppp *ppp = PF_TO_PPP(pf); + if (ppp->n_channels == 0 + && (ppp->flags & SC_LOOP_TRAFFIC) == 0) + break; + } ret = -EAGAIN; if (file->f_flags & O_NONBLOCK) break; @@ -491,6 +502,14 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) mask |= POLLIN | POLLRDNORM; if (pf->dead) mask |= POLLHUP; + else if (pf->kind == INTERFACE) { + /* see comment in ppp_read */ + struct ppp *ppp = PF_TO_PPP(pf); + if (ppp->n_channels == 0 + && (ppp->flags & SC_LOOP_TRAFFIC) == 0) + mask |= POLLIN | POLLRDNORM; + } + return mask; } @@ -1595,6 +1614,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) skb->dev = ppp->dev; skb->protocol = htons(npindex_to_ethertype[npi]); skb->mac.raw = skb->data; + skb->input_dev = ppp->dev; netif_rx(skb); ppp->dev->last_rx = jiffies; } @@ -1919,7 +1939,7 @@ ppp_register_channel(struct ppp_channel *chan) #endif /* CONFIG_PPP_MULTILINK */ init_rwsem(&pch->chan_sem); spin_lock_init(&pch->downl); - pch->upl = RW_LOCK_UNLOCKED; + rwlock_init(&pch->upl); spin_lock_bh(&all_channels_lock); pch->file.index = ++last_channel_index; list_add(&pch->list, &new_channels); @@ -2558,7 +2578,8 @@ ppp_disconnect_channel(struct channel *pch) /* remove it from the ppp unit's list */ ppp_lock(ppp); list_del(&pch->clist); - --ppp->n_channels; + if (--ppp->n_channels == 0) + wake_up_interruptible(&ppp->file.rwait); ppp_unlock(ppp); if (atomic_dec_and_test(&ppp->file.refcnt)) ppp_destroy_interface(ppp); diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index a8f890858..37bbfad7e 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -175,6 +175,8 @@ ppp_print_buffer (const char *name, const __u8 *buf, int count) * frees the memory that ppp_synctty_receive is using. The best * way to fix this is to use a rwlock in the tty struct, but for now * we use a single global rwlock for all ttys in ppp line discipline. + * + * FIXME: Fixed in tty_io nowdays. */ static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED; @@ -282,6 +284,18 @@ ppp_sync_close(struct tty_struct *tty) kfree(ap); } +/* + * Called on tty hangup in process context. + * + * Wait for I/O to driver to complete and unregister PPP channel. + * This is already done by the close routine, so just call that. + */ +static int ppp_sync_hangup(struct tty_struct *tty) +{ + ppp_sync_close(tty); + return 0; +} + /* * Read does nothing - no data is ever available this way. * Pppd reads and writes packets via /dev/ppp instead. @@ -299,7 +313,7 @@ ppp_sync_read(struct tty_struct *tty, struct file *file, */ static ssize_t ppp_sync_write(struct tty_struct *tty, struct file *file, - const unsigned char __user *buf, size_t count) + const unsigned char *buf, size_t count) { return -EAGAIN; } @@ -420,6 +434,7 @@ static struct tty_ldisc ppp_sync_ldisc = { .name = "pppsync", .open = ppp_sync_open, .close = ppp_sync_close, + .hangup = ppp_sync_hangup, .read = ppp_sync_read, .write = ppp_sync_write, .ioctl = ppp_synctty_ioctl, @@ -649,7 +664,7 @@ ppp_sync_push(struct syncppp *ap) tty_stuffed = 0; if (!tty_stuffed && ap->tpkt != 0) { set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->driver->write(tty, 0, ap->tpkt->data, ap->tpkt->len); + sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len); if (sent < 0) goto flush; /* error, e.g. loss of CD */ if (sent < ap->tpkt->len) { diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 64b35cc25..672e3cd2d 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -391,7 +391,7 @@ static int pppoe_rcv(struct sk_buff *skb, ph = (struct pppoe_hdr *) skb->nh.raw; - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); if (!po) goto drop; @@ -440,7 +440,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (ph->code != PADT_CODE) goto abort; - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); if (po) { struct sock *sk = po->sk; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index e686cb440..bfcb612af 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -7,7 +7,7 @@ Feb 4 2002 - created initially by ShuChen . May 20 2002 - Add link status force-mode and TBI mode support. ========================================================================= - 1. The media can be forced in 5 modes. + 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. @@ -41,6 +41,7 @@ VERSION 1.2 <2002/11/30> #include #include #include +#include #include #include #include @@ -64,6 +65,14 @@ VERSION 1.2 <2002/11/30> #define dprintk(fmt, args...) do {} while (0) #endif /* RTL8169_DEBUG */ +#ifdef CONFIG_R8169_NAPI +#define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_quota(count, quota) min(count, quota) +#else +#define rtl8169_rx_skb netif_rx +#define rtl8169_rx_quota(count, quota) count +#endif + /* media options */ #define MAX_UNITS 8 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -90,15 +99,16 @@ static int multicast_filter_limit = 32; #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ +#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ #define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (HZ) +#define RTL8169_PHY_TIMEOUT (10*HZ) /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -140,12 +150,14 @@ const static struct { static struct pci_device_id rtl8169_pci_tbl[] = { {0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,}, }; MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); static int rx_copybreak = 200; +static int use_dac; enum RTL8169_registers { MAC0 = 0, /* Ethernet hardware address. */ @@ -194,7 +206,7 @@ enum RTL8169_register_content { SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -233,6 +245,14 @@ enum RTL8169_register_content { TxInterFrameGapShift = 24, TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + /* TBICSR p.28 */ + TBIReset = 0x80000000, + TBILoopback = 0x40000000, + TBINwEnable = 0x20000000, + TBINwRestart = 0x10000000, + TBILinkOk = 0x02000000, + TBINwComplete = 0x01000000, + /* CPlusCmd p.31 */ RxVlan = (1 << 6), RxChkSum = (1 << 5), @@ -306,10 +326,10 @@ struct RxDesc { }; struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ + void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; /* spin lock flag */ int chipset; int mac_version; int phy_version; @@ -317,21 +337,31 @@ struct rtl8169_private { u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; - unsigned long phy_link_down_cnt; u16 cp_cmd; + u16 intr_mask; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; + + int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); + void (*get_settings)(struct net_device *, struct ethtool_cmd *); + void (*phy_reset_enable)(void *); + unsigned int (*phy_reset_pending)(void *); + unsigned int (*link_ok)(void *); }; MODULE_AUTHOR("Realtek"); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(use_dac, "i"); +MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); MODULE_LICENSE("GPL"); static int rtl8169_open(struct net_device *dev); @@ -344,9 +374,14 @@ static int rtl8169_close(struct net_device *dev); static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget); +#endif static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; + SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; +static const u16 rtl8169_napi_event = + RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -364,11 +399,9 @@ static void mdio_write(void *ioaddr, int RegAddr, int value) for (i = 2000; i > 0; i--) { // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if (!(RTL_R32(PHYAR) & 0x80000000)) break; - } else { - udelay(100); - } + udelay(100); } } @@ -390,18 +423,264 @@ static int mdio_read(void *ioaddr, int RegAddr) return value; } +static unsigned int rtl8169_tbi_reset_pending(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBIReset; +} + +static unsigned int rtl8169_xmii_reset_pending(void *ioaddr) +{ + return mdio_read(ioaddr, 0) & 0x8000; +} + +static unsigned int rtl8169_tbi_link_ok(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBILinkOk; +} + +static unsigned int rtl8169_xmii_link_ok(void *ioaddr) +{ + return RTL_R8(PHYstatus) & LinkStatus; +} + +static void rtl8169_tbi_reset_enable(void *ioaddr) +{ + RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); +} + +static void rtl8169_xmii_reset_enable(void *ioaddr) +{ + unsigned int val; + + val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff; + mdio_write(ioaddr, PHY_CTRL_REG, val); +} + +static void rtl8169_check_link_status(struct net_device *dev, + struct rtl8169_private *tp, void *ioaddr) +{ + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + if (tp->link_ok(ioaddr)) { + netif_carrier_on(dev); + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else + netif_carrier_off(dev); + spin_unlock_irqrestore(&tp->lock, flags); +} + +static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) +{ + struct { + u16 speed; + u8 duplex; + u8 autoneg; + u8 media; + } link_settings[] = { + { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, + { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, + { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, + { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, + { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, + /* Make TBI happy */ + { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } + }, *p; + unsigned char option; + + option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; + + if ((option != 0xff) && !idx) + printk(KERN_WARNING PFX "media option is deprecated.\n"); + + for (p = link_settings; p->media != 0xff; p++) { + if (p->media == option) + break; + } + *autoneg = p->autoneg; + *speed = p->speed; + *duplex = p->duplex; +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); strcpy(info->driver, RTL8169_DRIVER_NAME); strcpy(info->version, RTL8169_VERSION ); strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static int rtl8169_set_speed_tbi(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int ret = 0; + u32 reg; + + reg = RTL_R32(TBICSR); + if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && + (duplex == DUPLEX_FULL)) { + RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); + } else if (autoneg == AUTONEG_ENABLE) + RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); + else { + printk(KERN_WARNING PFX + "%s: incorrect speed setting refused in TBI mode\n", + dev->name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int rtl8169_set_speed_xmii(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int auto_nego, giga_ctrl; + + auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); + auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG); + giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null); + + if (autoneg == AUTONEG_ENABLE) { + auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl |= PHY_Cap_1000_Full; + } else { + if (speed == SPEED_10) + auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full; + else if (speed == SPEED_100) + auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full; + else if (speed == SPEED_1000) + giga_ctrl |= PHY_Cap_1000_Full; + + if (duplex == DUPLEX_HALF) + auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); + } + + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); + mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); + mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | + PHY_Restart_Auto_Nego); + return 0; +} + +static int rtl8169_set_speed(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + int ret; + + ret = tp->set_speed(dev, autoneg, speed, duplex); + + if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); + + return ret; +} + +static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u32 status; + + cmd->supported = + SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + + status = RTL_R32(TBICSR); + cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; + cmd->autoneg = !!(status & TBINwEnable); + + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; /* Always set */ +} + +static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u8 status; + + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP; + + cmd->autoneg = 1; + cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; + + if (tp->phy_auto_nego_reg & PHY_Cap_10_Half) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_10_Full) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Half) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Full) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full) + cmd->advertising |= ADVERTISED_1000baseT_Full; + + status = RTL_R8(PHYstatus); + + if (status & _1000bpsF) + cmd->speed = SPEED_1000; + else if (status & _100bps) + cmd->speed = SPEED_100; + else if (status & _10bps) + cmd->speed = SPEED_10; + + cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; +} + +static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + tp->get_settings(dev, cmd); + + spin_unlock_irqrestore(&tp->lock, flags); + return 0; +} + + static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_settings = rtl8169_get_settings, + .set_settings = rtl8169_set_settings, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, @@ -500,7 +779,7 @@ static void rtl8169_print_phy_version(struct rtl8169_private *tp) static void rtl8169_hw_phy_config(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; struct { u16 regs[5]; /* Beware of bit-sign propagation */ @@ -566,61 +845,47 @@ static void rtl8169_hw_phy_config(struct net_device *dev) mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0 } -static void rtl8169_hw_phy_reset(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int i, val; - - printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name); - - val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; - mdio_write(ioaddr, 0, val); - - for (i = 50; i >= 0; i--) { - if (!(mdio_read(ioaddr, 0) & 0x8000)) - break; - udelay(100); /* Gross */ - } - - if (i < 0) { - printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n", - dev->name); - } -} - static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; + unsigned long timeout = RTL8169_PHY_TIMEOUT; assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->phy_version < RTL_GIGA_PHY_VER_G); - if (RTL_R8(PHYstatus) & LinkStatus) - tp->phy_link_down_cnt = 0; - else { - tp->phy_link_down_cnt++; - if (tp->phy_link_down_cnt >= 12) { - int reg; + if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + return; - // If link on 1000, perform phy reset. - reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); - if (reg & PHY_Cap_1000_Full) - rtl8169_hw_phy_reset(dev); + spin_lock_irq(&tp->lock); - tp->phy_link_down_cnt = 0; - } + if (tp->phy_reset_pending(ioaddr)) { + /* + * A busy loop could burn quite a few cycles on nowadays CPU. + * Let's delay the execution of the timer for a few ticks. + */ + timeout = HZ/10; + goto out_mod_timer; } - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); + if (tp->link_ok(ioaddr)) + goto out_unlock; + + printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name); + + tp->phy_reset_enable(ioaddr); + +out_mod_timer: + mod_timer(timer, jiffies + timeout); +out_unlock: + spin_unlock_irq(&tp->lock); } static inline void rtl8169_delete_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -628,21 +893,17 @@ static inline void rtl8169_delete_timer(struct net_device *dev) return; del_timer_sync(timer); - - tp->phy_link_down_cnt = 0; } static inline void rtl8169_request_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || (tp->phy_version >= RTL_GIGA_PHY_VER_G)) return; - tp->phy_link_down_cnt = 0; - init_timer(timer); timer->expires = jiffies + RTL8169_PHY_TIMEOUT; timer->data = (unsigned long)(dev); @@ -681,7 +942,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); goto err_out; } @@ -693,7 +954,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); + printk(KERN_ERR PFX + "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } @@ -718,14 +980,15 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, rc = pci_request_regions(pdev, MODULENAME); if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: could not request regions.\n", + pdev->slot_name); goto err_out_disable; } tp->cp_cmd = PCIMulRW | RxChkSum; - if ((sizeof(dma_addr_t) > 32) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + if ((sizeof(dma_addr_t) > 4) && + !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac) tp->cp_cmd |= PCIDAC; else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); @@ -800,8 +1063,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; + u8 autoneg, duplex; + u16 speed; int i, rc; - int option = -1, Cap10_100 = 0, Cap1000 = 0; assert(pdev != NULL); assert(ent != NULL); @@ -822,6 +1086,22 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) assert(dev != NULL); assert(tp != NULL); + if (RTL_R8(PHYstatus) & TBI_Enable) { + tp->set_speed = rtl8169_set_speed_tbi; + tp->get_settings = rtl8169_gset_tbi; + tp->phy_reset_enable = rtl8169_tbi_reset_enable; + tp->phy_reset_pending = rtl8169_tbi_reset_pending; + tp->link_ok = rtl8169_tbi_link_ok; + + tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */ + } else { + tp->set_speed = rtl8169_set_speed_xmii; + tp->get_settings = rtl8169_gset_xmii; + tp->phy_reset_enable = rtl8169_xmii_reset_enable; + tp->phy_reset_pending = rtl8169_xmii_reset_pending; + tp->link_ok = rtl8169_xmii_link_ok; + } + // Get MAC address. FIXME: read EEPROM for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); @@ -836,9 +1116,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // +#ifdef CONFIG_R8169_NAPI + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; + printk(KERN_INFO PFX "NAPI enabled\n"); +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -885,95 +1168,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - // if TBI is not endbled - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); - - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - // Force RTL8169 in 10/100/1000 Full/Half mode. - if (option > 0) { - printk(KERN_INFO "%s: Force-mode Enabled.\n", - dev->name); - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; - } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); - } else { - printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", - dev->name); - - // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - PHY_Cap_100_Full_Or_Less | (val & 0x1f)); + rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - // enable 1000 Full Mode - mdio_write(ioaddr, PHY_1000_CTRL_REG, - PHY_Cap_1000_Full); - - } - - // Enable auto-negotiation and restart auto-nigotiation - mdio_write(ioaddr, PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - udelay(100); - - // wait for auto-negotiation process - for (i = 10000; i > 0; i--) { - //check if auto-negotiation complete - if (mdio_read(ioaddr, PHY_STAT_REG) & - PHY_Auto_Neco_Comp) { - udelay(100); - option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation.\n", - dev->name); - } else { - printk(KERN_INFO - "%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); - } - break; - } else { - udelay(100); - } - } // end for-loop to wait for auto-negotiation process - - } else { - udelay(100); - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", - dev->name, - (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); - - } + rtl8169_set_speed(dev, autoneg, speed, duplex); + + if (RTL_R8(PHYstatus) & TBI_Enable) + printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); return 0; } @@ -982,7 +1182,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); assert(dev != NULL); assert(tp != NULL); @@ -1001,7 +1201,7 @@ rtl8169_remove_one(struct pci_dev *pdev) static int rtl8169_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -1042,7 +1242,7 @@ static int rtl8169_resume(struct pci_dev *pdev) static int rtl8169_open(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; int retval; @@ -1074,6 +1274,8 @@ rtl8169_open(struct net_device *dev) rtl8169_hw_start(dev); rtl8169_request_timer(dev); + + rtl8169_check_link_status(dev, tp, tp->mmio_addr); out: return retval; @@ -1091,7 +1293,7 @@ err_free_irq: static void rtl8169_hw_start(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; @@ -1102,8 +1304,7 @@ rtl8169_hw_start(struct net_device *dev) for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; - else - udelay(10); + udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1114,8 +1315,8 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); + i = rtl8169_rx_config | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ @@ -1126,7 +1327,8 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); + dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " + "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } @@ -1151,7 +1353,6 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); - } static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) @@ -1248,7 +1449,7 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) static int rtl8169_init_ring(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; @@ -1302,10 +1503,11 @@ rtl8169_tx_clear(struct rtl8169_private *tp) static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u8 tmp8; + printk(KERN_INFO "%s: TX Timeout\n", dev->name); /* disable Tx, if not already */ tmp8 = RTL_R8(ChipCmd); if (tmp8 & CmdTxEnb) @@ -1328,9 +1530,9 @@ rtl8169_tx_timeout(struct net_device *dev) static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned int entry = tp->cur_tx % NUM_TX_DESC; u32 len = skb->len; if (unlikely(skb->len < ETH_ZLEN)) { @@ -1340,10 +1542,9 @@ rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) len = ETH_ZLEN; } - spin_lock_irq(&tp->lock); - if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) { dma_addr_t mapping; + u32 status; mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); @@ -1351,24 +1552,30 @@ rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->Tx_skbuff[entry] = skb; tp->TxDescArray[entry].addr = cpu_to_le64(mapping); - tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit | - LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC))); + /* anti gcc 2.95.3 bugware */ + status = OWNbit | FSbit | LSbit | len | + (EORbit * !((entry + 1) % NUM_TX_DESC)); + tp->TxDescArray[entry].status = cpu_to_le32(status); RTL_W8(TxPoll, 0x40); //set polling bit dev->trans_start = jiffies; tp->cur_tx++; + smp_wmb(); } else goto err_drop; - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) { + u32 dirty = tp->dirty_tx; + netif_stop_queue(dev); + smp_rmb(); + if (dirty != tp->dirty_tx) + netif_wake_queue(dev); } -out: - spin_unlock_irq(&tp->lock); +out: return 0; err_drop: @@ -1382,17 +1589,18 @@ static void rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); assert(ioaddr != NULL); dirty_tx = tp->dirty_tx; + smp_rmb(); tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; + unsigned int entry = dirty_tx % NUM_TX_DESC; struct sk_buff *skb = tp->Tx_skbuff[entry]; u32 status; @@ -1415,6 +1623,7 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; + smp_wmb(); if (netif_queue_stopped(dev)) netif_wake_queue(dev); } @@ -1442,11 +1651,11 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, return ret; } -static void +static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long cur_rx, rx_left; + unsigned int cur_rx, rx_left, count; int delta; assert(dev != NULL); @@ -1455,9 +1664,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; + rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; + unsigned int entry = cur_rx % NUM_RX_DESC; u32 status; rmb(); @@ -1494,7 +1704,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; @@ -1505,13 +1715,15 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rx_left--; } + count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) + if (delta < 0) { printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + delta = 0; + } + tp->dirty_rx += delta; /* * FIXME: until there is periodic timer to try and refill the ring, @@ -1522,6 +1734,8 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, */ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + + return count; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -1529,7 +1743,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0; @@ -1543,26 +1757,46 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) break; handled = 1; -/* - if (status & RxUnderrun) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; -*/ + + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); if (!(status & rtl8169_intr_mask)) break; + if (unlikely(status & SYSErr)) { + printk(KERN_ERR PFX "%s: PCI error (status: 0x%04x)." + " Device disabled.\n", dev->name, status); + RTL_W8(ChipCmd, 0x00); + RTL_W16(IntrMask, 0x0000); + RTL_R16(IntrMask); + break; + } + + if (status & LinkChg) + rtl8169_check_link_status(dev, tp, ioaddr); + +#ifdef CONFIG_R8169_NAPI + RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); + tp->intr_mask = ~rtl8169_napi_event; + + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); + else { + printk(KERN_INFO "%s: interrupt %x taken in poll\n", + dev->name, status); + } + break; +#else // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt - if (status & (TxOK | TxErr)) { - spin_lock(&tp->lock); + if (status & (TxOK | TxErr)) rtl8169_tx_interrupt(dev, tp, ioaddr); - spin_unlock(&tp->lock); - } +#endif boguscnt--; } while (boguscnt > 0); @@ -1576,10 +1810,40 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget) +{ + unsigned int work_done, work_to_do = min(*budget, dev->quota); + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + + work_done = rtl8169_rx_interrupt(dev, tp, ioaddr); + rtl8169_tx_interrupt(dev, tp, ioaddr); + + *budget -= work_done; + dev->quota -= work_done; + + if ((work_done < work_to_do) || !netif_running(dev)) { + netif_rx_complete(dev); + tp->intr_mask = 0xffff; + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + RTL_W16(IntrMask, rtl8169_intr_mask); + } + + return (work_done >= work_to_do); +} +#endif + static int rtl8169_close(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; void *ioaddr = tp->mmio_addr; @@ -1621,7 +1885,7 @@ rtl8169_close(struct net_device *dev) static void rtl8169_set_rx_mode(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1655,10 +1919,8 @@ rtl8169_set_rx_mode(struct net_device *dev) spin_lock_irqsave(&tp->lock, flags); - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); + tmp = rtl8169_rx_config | rx_mode | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -1675,7 +1937,7 @@ rtl8169_set_rx_mode(struct net_device *dev) */ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 059f1a68a..4108b287b 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -157,7 +157,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev, * Remap the regs into kernel space. */ - rrpriv->regs = (struct rr_regs *)ioremap(dev->base_addr, 0x1000); + rrpriv->regs = ioremap(dev->base_addr, 0x1000); if (!rrpriv->regs){ printk(KERN_ERR "%s: Unable to map I/O register, " @@ -267,7 +267,7 @@ static void __devexit rr_remove_one (struct pci_dev *pdev) */ static void rr_issue_cmd(struct rr_private *rrpriv, struct cmd *cmd) { - struct rr_regs *regs; + struct rr_regs __iomem *regs; u32 idx; regs = rrpriv->regs; @@ -304,7 +304,7 @@ static void rr_issue_cmd(struct rr_private *rrpriv, struct cmd *cmd) static int rr_reset(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; struct eeprom *hw = NULL; u32 start_pc; int i; @@ -418,7 +418,7 @@ static unsigned int rr_read_eeprom(struct rr_private *rrpriv, unsigned char *buf, unsigned long length) { - struct rr_regs *regs = rrpriv->regs; + struct rr_regs __iomem *regs = rrpriv->regs; u32 misc, io, host, i; io = readl(®s->ExtIo); @@ -470,7 +470,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv, unsigned char *buf, unsigned long length) { - struct rr_regs *regs = rrpriv->regs; + struct rr_regs __iomem *regs = rrpriv->regs; u32 misc, io, data, i, j, ready, error = 0; io = readl(®s->ExtIo); @@ -520,7 +520,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv, static int __init rr_init(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; struct eeprom *hw = NULL; u32 sram_size, rev; int i; @@ -589,7 +589,7 @@ static int __init rr_init(struct net_device *dev) static int rr_init1(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; unsigned long myjif, flags; struct cmd cmd; u32 hostctrl; @@ -759,7 +759,7 @@ static int rr_init1(struct net_device *dev) static u32 rr_handle_event(struct net_device *dev, u32 prodidx, u32 eidx) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; u32 tmp; rrpriv = netdev_priv(dev); @@ -962,7 +962,7 @@ static u32 rr_handle_event(struct net_device *dev, u32 prodidx, u32 eidx) static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) { struct rr_private *rrpriv = netdev_priv(dev); - struct rr_regs *regs = rrpriv->regs; + struct rr_regs __iomem *regs = rrpriv->regs; do { struct rx_desc *desc; @@ -1057,7 +1057,7 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; struct net_device *dev = (struct net_device *)dev_id; u32 prodidx, rxindex, eidx, txcsmr, rxlimit, txcon; @@ -1139,11 +1139,54 @@ static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) return IRQ_HANDLED; } +static inline void rr_raz_tx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < TX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->tx_skbuff[i]; + + if (skb) { + struct tx_desc *desc = &(rrpriv->tx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + skb->len, PCI_DMA_TODEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->tx_skbuff[i] = NULL; + } + } +} + + +static inline void rr_raz_rx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < RX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->rx_skbuff[i]; + + if (skb) { + struct rx_desc *desc = &(rrpriv->rx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->rx_skbuff[i] = NULL; + } + } +} + static void rr_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct rr_private *rrpriv = netdev_priv(dev); - struct rr_regs *regs = rrpriv->regs; + struct rr_regs __iomem *regs = rrpriv->regs; unsigned long flags; if (readl(®s->HostCtrl) & NIC_HALTED){ @@ -1171,7 +1214,7 @@ static int rr_open(struct net_device *dev) { struct rr_private *rrpriv = netdev_priv(dev); struct pci_dev *pdev = rrpriv->pci_dev; - struct rr_regs *regs; + struct rr_regs __iomem *regs; int ecode = 0; unsigned long flags; dma_addr_t dma_addr; @@ -1254,53 +1297,10 @@ static int rr_open(struct net_device *dev) } -static inline void rr_raz_tx(struct rr_private *rrpriv, - struct net_device *dev) -{ - int i; - - for (i = 0; i < TX_RING_ENTRIES; i++) { - struct sk_buff *skb = rrpriv->tx_skbuff[i]; - - if (skb) { - struct tx_desc *desc = &(rrpriv->tx_ring[i]); - - pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, - skb->len, PCI_DMA_TODEVICE); - desc->size = 0; - set_rraddr(&desc->addr, 0); - dev_kfree_skb(skb); - rrpriv->tx_skbuff[i] = NULL; - } - } -} - - -static inline void rr_raz_rx(struct rr_private *rrpriv, - struct net_device *dev) -{ - int i; - - for (i = 0; i < RX_RING_ENTRIES; i++) { - struct sk_buff *skb = rrpriv->rx_skbuff[i]; - - if (skb) { - struct rx_desc *desc = &(rrpriv->rx_ring[i]); - - pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, - dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); - desc->size = 0; - set_rraddr(&desc->addr, 0); - dev_kfree_skb(skb); - rrpriv->rx_skbuff[i] = NULL; - } - } -} - static void rr_dump(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; u32 index, cons; short i; int len; @@ -1363,7 +1363,7 @@ static void rr_dump(struct net_device *dev) static int rr_close(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; unsigned long flags; u32 tmp; short i; @@ -1428,7 +1428,7 @@ static int rr_close(struct net_device *dev) static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct rr_private *rrpriv = netdev_priv(dev); - struct rr_regs *regs = rrpriv->regs; + struct rr_regs __iomem *regs = rrpriv->regs; struct ring_ctrl *txctrl; unsigned long flags; u32 index, len = skb->len; @@ -1513,7 +1513,7 @@ static struct net_device_stats *rr_get_stats(struct net_device *dev) static int rr_load_firmware(struct net_device *dev) { struct rr_private *rrpriv; - struct rr_regs *regs; + struct rr_regs __iomem *regs; unsigned long eptr, segptr; int i, j; u32 localctrl, sptr, len, tmp; diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h index 1049131ed..10baae559 100644 --- a/drivers/net/rrunner.h +++ b/drivers/net/rrunner.h @@ -510,7 +510,7 @@ static inline void set_rraddr(rraddr *ra, dma_addr_t addr) } -static inline void set_rxaddr(struct rr_regs *regs, volatile dma_addr_t addr) +static inline void set_rxaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr) { unsigned long baddr = addr; #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) @@ -527,7 +527,7 @@ static inline void set_rxaddr(struct rr_regs *regs, volatile dma_addr_t addr) } -static inline void set_infoaddr(struct rr_regs *regs, volatile dma_addr_t addr) +static inline void set_infoaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr) { unsigned long baddr = addr; #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) @@ -808,7 +808,7 @@ struct rr_private /* Alignment ok ? */ struct sk_buff *rx_skbuff[RX_RING_ENTRIES]; struct sk_buff *tx_skbuff[TX_RING_ENTRIES]; - struct rr_regs *regs; /* Register base */ + struct rr_regs __iomem *regs; /* Register base */ struct ring_ctrl *rx_ctrl; /* Receive ring control */ struct rr_info *info; /* Shared info page */ dma_addr_t rx_ctrl_dma; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c4bd1793f..5ecc3b6c3 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -235,10 +235,10 @@ static struct pci_device_id s2io_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, s2io_tbl); static struct pci_driver s2io_driver = { - name:"S2IO", - id_table:s2io_tbl, - probe:s2io_init_nic, - remove:__devexit_p(s2io_rem_nic), + .name = "S2IO", + .id_table = s2io_tbl, + .probe = s2io_init_nic, + .remove = __devexit_p(s2io_rem_nic), }; /* @@ -1935,7 +1935,7 @@ void s2io_reset(nic_t * sp) schedule_timeout(HZ / 4); /* Restore the PCI state saved during initializarion. */ - pci_restore_state(sp->pdev, sp->config_space); + pci_restore_state(sp->pdev); s2io_init_pci(sp); set_current_state(TASK_UNINTERRUPTIBLE); @@ -3983,14 +3983,14 @@ static void s2io_init_pci(nic_t * sp) MODULE_AUTHOR("Raghavendra Koushik "); MODULE_LICENSE("GPL"); -MODULE_PARM(ring_num, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(frame_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(ring_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(fifo_num, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(fifo_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_prio, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(tx_prio, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(latency_timer, "1-" __MODULE_STRING(1) "i"); +module_param(ring_num, uint, 0); +module_param_array(frame_len, uint, NULL, 0); +module_param_array(ring_len, uint, NULL, 0); +module_param(fifo_num, uint, 0); +module_param_array(fifo_len, uint, NULL, 0); +module_param(rx_prio, uint, 0); +module_param(tx_prio, uint, 0); +module_param(latency_timer, byte, 0); /* * Input Argument/s: @@ -4238,7 +4238,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } - pci_save_state(sp->pdev, sp->config_space); + pci_save_state(sp->pdev); /* Setting swapper control on the NIC, for proper reset operation */ if (s2io_set_swapper(sp)) { diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index e9a166450..94754485a 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -667,7 +667,6 @@ typedef struct s2io_nic { u8 cache_line; u32 rom_expansion; u16 pcix_cmd; - u32 config_space[256 / sizeof(u32)]; u32 irq; atomic_t rx_bufs_left[MAX_RX_RINGS]; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 03f28fdc0..dcc64eb8d 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -50,8 +50,8 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n"; #include #include #include +#include -#include #include #include #include diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index e0f88fbd3..153467952 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -68,8 +68,8 @@ static int int_timeout = 0; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 0f237b54d..d9fd93004 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -45,9 +45,9 @@ static const char version[] = #include #include #include +#include #include -#include #include #include diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index b71f45f5c..4385cd167 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -19,11 +19,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 425e89fe2..ed02d0cb5 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -64,9 +64,9 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include /* User space memory access functions */ @@ -124,6 +124,7 @@ static struct mii_chip_info { { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME}, { "ICS LAN PHY", 0x0015, 0xF440, LAN }, { "NS 83851 PHY", 0x2000, 0x5C20, MIX }, + { "NS 83847 PHY", 0x2000, 0x5C30, MIX }, { "Realtek RTL8201 PHY", 0x0000, 0x8200, LAN }, { "VIA 6103 PHY", 0x0101, 0x8f20, LAN }, {NULL,}, @@ -139,9 +140,9 @@ struct mii_phy { }; typedef struct _BufferDesc { - u32 link; - u32 cmdsts; - u32 bufptr; + u32 link; + u32 cmdsts; + u32 bufptr; } BufferDesc; struct sis900_private { @@ -155,7 +156,7 @@ struct sis900_private { unsigned int cur_phy; struct timer_list timer; /* Link status detection timer. */ - u8 autong_complete; /* 1: auto-negotiate complete */ + u8 autong_complete; /* 1: auto-negotiate complete */ unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */ unsigned int cur_tx, dirty_tx; @@ -169,9 +170,8 @@ struct sis900_private { dma_addr_t tx_ring_dma; dma_addr_t rx_ring_dma; - unsigned int tx_full; /* The Tx queue is full. */ + unsigned int tx_full; /* The Tx queue is full. */ u8 host_bridge_rev; - u32 pci_state[16]; }; MODULE_AUTHOR("Jim Huang , Ollie Lho "); @@ -255,19 +255,19 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de * MAC address is read into @net_dev->dev_addr. */ -static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, + struct net_device *net_dev) { struct pci_dev *isa_bridge = NULL; u8 reg; int i; - isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge); + isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge); + if (!isa_bridge) + isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge); if (!isa_bridge) { - isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge); - if (!isa_bridge) { - printk("%s: Can not find ISA bridge\n", net_dev->name); - return 0; - } + printk("%s: Can not find ISA bridge\n", net_dev->name); + return 0; } pci_read_config_byte(isa_bridge, 0x48, ®); pci_write_config_byte(isa_bridge, 0x48, reg | 0x40); @@ -277,6 +277,7 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_d ((u8 *)(net_dev->dev_addr))[i] = inb(0x71); } pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40); + pci_dev_put(isa_bridge); return 1; } @@ -292,7 +293,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_d * @net_dev->dev_addr. */ -static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, + struct net_device *net_dev) { long ioaddr = net_dev->base_addr; u32 rfcrSave; @@ -334,7 +336,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de * MAC address is read into @net_dev->dev_addr. */ -static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, + struct net_device *net_dev) { long ioaddr = net_dev->base_addr; long ee_addr = ioaddr + mear; @@ -371,7 +374,8 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_de * ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc. */ -static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) +static int __devinit sis900_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) { struct sis900_private *sis_priv; struct net_device *net_dev; @@ -484,9 +488,11 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev } /* save our host bridge revision */ - dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL); - if (dev) + dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL); + if (dev) { pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev); + pci_dev_put(dev); + } /* print some information about our NIC */ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name, @@ -522,7 +528,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev * return error if it failed to found. */ -static int __init sis900_mii_probe (struct net_device * net_dev) +static int __init sis900_mii_probe(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; u16 poll_bit = MII_STAT_LINK, status = 0; @@ -572,9 +578,10 @@ static int __init sis900_mii_probe (struct net_device * net_dev) mii_phy->phy_types = mii_chip_table[i].phy_types; if (mii_chip_table[i].phy_types == MIX) mii_phy->phy_types = - (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME; + (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME; printk(KERN_INFO "%s: %s transceiver found at address %d.\n", - net_dev->name, mii_chip_table[i].name, phy_addr); + net_dev->name, mii_chip_table[i].name, + phy_addr); break; } @@ -587,7 +594,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev) if (sis_priv->mii == NULL) { printk(KERN_INFO "%s: No MII transceivers found!\n", - net_dev->name); + net_dev->name); return 0; } @@ -611,7 +618,8 @@ static int __init sis900_mii_probe (struct net_device * net_dev) poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit); if (time_after_eq(jiffies, timeout)) { - printk(KERN_WARNING "%s: reset phy and link down now\n", net_dev->name); + printk(KERN_WARNING "%s: reset phy and link down now\n", + net_dev->name); return -ETIME; } } @@ -647,38 +655,41 @@ static int __init sis900_mii_probe (struct net_device * net_dev) static u16 sis900_default_phy(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; - struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL, *phy_lan = NULL; + struct mii_phy *phy = NULL, *phy_home = NULL, + *default_phy = NULL, *phy_lan = NULL; u16 status; - for( phy=sis_priv->first_mii; phy; phy=phy->next ){ + for (phy=sis_priv->first_mii; phy; phy=phy->next) { status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); /* Link ON & Not select default PHY & not ghost PHY */ - if ( (status & MII_STAT_LINK) && !default_phy && (phy->phy_types != UNKNOWN) ) + if ((status & MII_STAT_LINK) && !default_phy && + (phy->phy_types != UNKNOWN)) default_phy = phy; - else{ + else { status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL); mdio_write(net_dev, phy->phy_addr, MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_ISOLATE); - if( phy->phy_types == HOME ) + if (phy->phy_types == HOME) phy_home = phy; - else if (phy->phy_types == LAN) + else if(phy->phy_types == LAN) phy_lan = phy; } } - if( !default_phy && phy_home ) + if (!default_phy && phy_home) default_phy = phy_home; - else if( !default_phy && phy_lan ) + else if (!default_phy && phy_lan) default_phy = phy_lan; - else if ( !default_phy ) + else if (!default_phy) default_phy = sis_priv->first_mii; - if( sis_priv->mii != default_phy ){ + if (sis_priv->mii != default_phy) { sis_priv->mii = default_phy; sis_priv->cur_phy = default_phy->phy_addr; - printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", net_dev->name,sis_priv->cur_phy); + printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", + net_dev->name,sis_priv->cur_phy); } status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); @@ -701,7 +712,7 @@ static u16 sis900_default_phy(struct net_device * net_dev) * mii status register. It's necessary before auto-negotiate. */ -static void sis900_set_capability( struct net_device *net_dev , struct mii_phy *phy ) +static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *phy) { u16 cap; u16 status; @@ -851,7 +862,8 @@ static u16 mdio_read(struct net_device *net_dev, int phy_id, int location) * please see SiS7014 or ICS spec */ -static void mdio_write(struct net_device *net_dev, int phy_id, int location, int value) +static void mdio_write(struct net_device *net_dev, int phy_id, int location, + int value) { long mdio_addr = net_dev->base_addr + mear; int mii_cmd = MIIwrite|(phy_id<pci_dev, PCI_CLASS_REVISION, &revision); sis630_set_eq(net_dev, revision); - ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev); + ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, + net_dev->name, net_dev); if (ret) return ret; @@ -1136,48 +1149,55 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision) return; if (netif_carrier_ok(net_dev)) { - reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); - mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (0x2200 | reg14h) & 0xBFFF); + reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); + mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, + (0x2200 | reg14h) & 0xBFFF); for (i=0; i < maxcount; i++) { - eq_value=(0x00F8 & mdio_read(net_dev, sis_priv->cur_phy, MII_RESV)) >> 3; + eq_value = (0x00F8 & mdio_read(net_dev, + sis_priv->cur_phy, MII_RESV)) >> 3; if (i == 0) max_value=min_value=eq_value; - max_value=(eq_value > max_value) ? eq_value : max_value; - min_value=(eq_value < min_value) ? eq_value : min_value; + max_value = (eq_value > max_value) ? + eq_value : max_value; + min_value = (eq_value < min_value) ? + eq_value : min_value; } /* 630E rule to determine the equalizer value */ if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV || revision == SIS630ET_900_REV) { if (max_value < 5) - eq_value=max_value; + eq_value = max_value; else if (max_value >= 5 && max_value < 15) - eq_value=(max_value == min_value) ? max_value+2 : max_value+1; + eq_value = (max_value == min_value) ? + max_value+2 : max_value+1; else if (max_value >= 15) - eq_value=(max_value == min_value) ? max_value+6 : max_value+5; + eq_value=(max_value == min_value) ? + max_value+6 : max_value+5; } /* 630B0&B1 rule to determine the equalizer value */ if (revision == SIS630A_900_REV && (sis_priv->host_bridge_rev == SIS630B0 || sis_priv->host_bridge_rev == SIS630B1)) { if (max_value == 0) - eq_value=3; + eq_value = 3; else - eq_value=(max_value+min_value+1)/2; + eq_value = (max_value + min_value + 1)/2; } /* write equalizer value and setting */ - reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); - reg14h=(reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8); - reg14h=(reg14h | 0x6000) & 0xFDFF; + reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); + reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8); + reg14h = (reg14h | 0x6000) & 0xFDFF; mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h); - } - else { - reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); + } else { + reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); if (revision == SIS630A_900_REV && (sis_priv->host_bridge_rev == SIS630B0 || sis_priv->host_bridge_rev == SIS630B1)) - mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2200) & 0xBFFF); + mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, + (reg14h | 0x2200) & 0xBFFF); else - mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2000) & 0xBFFF); + mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, + (reg14h | 0x2000) & 0xBFFF); } return; } @@ -1205,7 +1225,8 @@ static void sis900_timer(unsigned long data) sis900_read_mode(net_dev, &speed, &duplex); if (duplex){ sis900_set_mode(net_dev->base_addr, speed, duplex); - pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); + pci_read_config_byte(sis_priv->pci_dev, + PCI_CLASS_REVISION, &revision); sis630_set_eq(net_dev, revision); netif_start_queue(net_dev); } @@ -1229,9 +1250,8 @@ static void sis900_timer(unsigned long data) sis900_check_mode(net_dev, mii_phy); netif_carrier_on(net_dev); } - } + } else { /* Link ON -> OFF */ - else { if (!(status & MII_STAT_LINK)){ netif_carrier_off(net_dev); printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); @@ -1241,7 +1261,8 @@ static void sis900_timer(unsigned long data) ((mii_phy->phy_id1 & 0xFFF0) == 0x8000)) sis900_reset_phy(net_dev, sis_priv->cur_phy); - pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); + pci_read_config_byte(sis_priv->pci_dev, + PCI_CLASS_REVISION, &revision); sis630_set_eq(net_dev, revision); goto LookForLink; @@ -1264,18 +1285,18 @@ static void sis900_timer(unsigned long data) * and autong_complete should be set to 1. */ -static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy) +static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_phy) { struct sis900_private *sis_priv = net_dev->priv; long ioaddr = net_dev->base_addr; int speed, duplex; - if( mii_phy->phy_types == LAN ){ - outl( ~EXD & inl( ioaddr + cfg ), ioaddr + cfg); + if (mii_phy->phy_types == LAN) { + outl(~EXD & inl(ioaddr + cfg), ioaddr + cfg); sis900_set_capability(net_dev , mii_phy); sis900_auto_negotiate(net_dev, sis_priv->cur_phy); - }else{ - outl(EXD | inl( ioaddr + cfg ), ioaddr + cfg); + } else { + outl(EXD | inl(ioaddr + cfg), ioaddr + cfg); speed = HW_SPEED_HOME; duplex = FDX_CAPABLE_HALF_SELECTED; sis900_set_mode(ioaddr, speed, duplex); @@ -1300,20 +1321,20 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex) { u32 tx_flags = 0, rx_flags = 0; - if( inl(ioaddr + cfg) & EDB_MASTER_EN ){ - tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); + if (inl(ioaddr + cfg) & EDB_MASTER_EN) { + tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | + (TX_FILL_THRESH << TxFILLT_shift); rx_flags = DMA_BURST_64 << RxMXDMA_shift; - } - else{ - tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); + } else { + tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | + (TX_FILL_THRESH << TxFILLT_shift); rx_flags = DMA_BURST_512 << RxMXDMA_shift; } - if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS ) { + if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) { rx_flags |= (RxDRNT_10 << RxDRNT_shift); tx_flags |= (TxDRNT_10 << TxDRNT_shift); - } - else { + } else { rx_flags |= (RxDRNT_100 << RxDRNT_shift); tx_flags |= (TxDRNT_100 << TxDRNT_shift); } @@ -1403,19 +1424,19 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex sis_priv->autong_complete = 1; /* Workaround for Realtek RTL8201 PHY issue */ - if((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)){ - if(mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX) + if ((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)) { + if (mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX) *duplex = FDX_CAPABLE_FULL_SELECTED; - if(mdio_read(net_dev, phy_addr, 0x0019) & 0x01) + if (mdio_read(net_dev, phy_addr, 0x0019) & 0x01) *speed = HW_SPEED_100_MBPS; } printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", - net_dev->name, - *speed == HW_SPEED_100_MBPS ? - "100mbps" : "10mbps", - *duplex == FDX_CAPABLE_FULL_SELECTED ? - "full" : "half"); + net_dev->name, + *speed == HW_SPEED_100_MBPS ? + "100mbps" : "10mbps", + *duplex == FDX_CAPABLE_FULL_SELECTED ? + "full" : "half"); } /** @@ -1677,13 +1698,13 @@ static int sis900_rx(struct net_device *net_dev) sis_priv->stats.rx_bytes += rx_size; sis_priv->stats.rx_packets++; - /* refill the Rx buffer, what if there is not enought memory for - new socket buffer ?? */ + /* refill the Rx buffer, what if there is not enought + * memory for new socket buffer ?? */ if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { - /* not enough memory for skbuff, this makes a "hole" - on the buffer ring, it is not clear how the - hardware will react to this kind of degenerated - buffer */ + /* not enough memory for skbuff, this makes a + * "hole" on the buffer ring, it is not clear + * how the hardware will react to this kind + * of degenerated buffer */ printk(KERN_INFO "%s: Memory squeeze," "deferring packet.\n", net_dev->name); @@ -1707,8 +1728,8 @@ static int sis900_rx(struct net_device *net_dev) rx_status = sis_priv->rx_ring[entry].cmdsts; } // while - /* refill the Rx buffer, what if the rate of refilling is slower than - consuming ?? */ + /* refill the Rx buffer, what if the rate of refilling is slower + * than consuming ?? */ for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) { struct sk_buff *skb; @@ -1716,10 +1737,10 @@ static int sis900_rx(struct net_device *net_dev) if (sis_priv->rx_skbuff[entry] == NULL) { if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { - /* not enough memory for skbuff, this makes a "hole" - on the buffer ring, it is not clear how the - hardware will react to this kind of degenerated - buffer */ + /* not enough memory for skbuff, this makes a + * "hole" on the buffer ring, it is not clear + * how the hardware will react to this kind + * of degenerated buffer */ printk(KERN_INFO "%s: Memory squeeze," "deferring packet.\n", net_dev->name); @@ -1764,8 +1785,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) if (tx_status & OWN) { /* The packet is not transmitted yet (owned by hardware) ! - Note: the interrupt is generated only when Tx Machine - is idle, so this is an almost impossible case */ + * Note: the interrupt is generated only when Tx Machine + * is idle, so this is an almost impossible case */ break; } @@ -1803,8 +1824,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) if (sis_priv->tx_full && netif_queue_stopped(net_dev) && sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) { - /* The ring is no longer full, clear tx_full and schedule more transmission - by netif_wake_queue(net_dev) */ + /* The ring is no longer full, clear tx_full and schedule + * more transmission by netif_wake_queue(net_dev) */ sis_priv->tx_full = 0; netif_wake_queue (net_dev); } @@ -1818,8 +1839,7 @@ static void sis900_finish_xmit (struct net_device *net_dev) * free Tx and RX socket buffer */ -static int -sis900_close(struct net_device *net_dev) +static int sis900_close(struct net_device *net_dev) { long ioaddr = net_dev->base_addr; struct sis900_private *sis_priv = net_dev->priv; @@ -1955,27 +1975,28 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { /* we switch on the ifmap->port field. I couldn't find anything - like a definition or standard for the values of that field. - I think the meaning of those values is device specific. But - since I would like to change the media type via the ifconfig - command I use the definition from linux/netdevice.h - (which seems to be different from the ifport(pcmcia) definition) - */ + * like a definition or standard for the values of that field. + * I think the meaning of those values is device specific. But + * since I would like to change the media type via the ifconfig + * command I use the definition from linux/netdevice.h + * (which seems to be different from the ifport(pcmcia) definition) */ switch(map->port){ case IF_PORT_UNKNOWN: /* use auto here */ dev->if_port = map->port; - /* we are going to change the media type, so the Link will - be temporary down and we need to reflect that here. When - the Link comes up again, it will be sensed by the sis_timer - procedure, which also does all the rest for us */ + /* we are going to change the media type, so the Link + * will be temporary down and we need to reflect that + * here. When the Link comes up again, it will be + * sensed by the sis_timer procedure, which also does + * all the rest for us */ netif_carrier_off(dev); /* read current state */ status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); /* enable auto negotiation and reset the negotioation - (I don't really know what the auto negatiotiation reset - really means, but it sounds for me right to do one here)*/ + * (I don't really know what the auto negatiotiation + * reset really means, but it sounds for me right to + * do one here) */ mdio_write(dev, mii_phy->phy_addr, MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); @@ -1984,10 +2005,11 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) case IF_PORT_10BASET: /* 10BaseT */ dev->if_port = map->port; - /* we are going to change the media type, so the Link will - be temporary down and we need to reflect that here. When - the Link comes up again, it will be sensed by the sis_timer - procedure, which also does all the rest for us */ + /* we are going to change the media type, so the Link + * will be temporary down and we need to reflect that + * here. When the Link comes up again, it will be + * sensed by the sis_timer procedure, which also does + * all the rest for us */ netif_carrier_off(dev); /* set Speed to 10Mbps */ @@ -1996,24 +2018,27 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) /* disable auto negotiation and force 10MBit mode*/ mdio_write(dev, mii_phy->phy_addr, - MII_CONTROL, status & ~(MII_CNTL_SPEED | MII_CNTL_AUTO)); + MII_CONTROL, status & ~(MII_CNTL_SPEED | + MII_CNTL_AUTO)); break; case IF_PORT_100BASET: /* 100BaseT */ case IF_PORT_100BASETX: /* 100BaseTx */ dev->if_port = map->port; - /* we are going to change the media type, so the Link will - be temporary down and we need to reflect that here. When - the Link comes up again, it will be sensed by the sis_timer - procedure, which also does all the rest for us */ + /* we are going to change the media type, so the Link + * will be temporary down and we need to reflect that + * here. When the Link comes up again, it will be + * sensed by the sis_timer procedure, which also does + * all the rest for us */ netif_carrier_off(dev); /* set Speed to 100Mbps */ /* disable auto negotiation and enable 100MBit Mode */ status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); mdio_write(dev, mii_phy->phy_addr, - MII_CONTROL, (status & ~MII_CNTL_SPEED) | MII_CNTL_SPEED); + MII_CONTROL, (status & ~MII_CNTL_SPEED) | + MII_CNTL_SPEED); break; @@ -2093,12 +2118,14 @@ static void set_rx_mode(struct net_device *net_dev) for (i = 0; i < table_entries; i++) mc_filter[i] = 0xffff; } else { - /* Accept Broadcast packet, destination address matchs our MAC address, - use Receive Filter to reject unwanted MCAST packet */ + /* Accept Broadcast packet, destination address matchs our + * MAC address, use Receive Filter to reject unwanted MCAST + * packets */ struct dev_mc_list *mclist; rx_mode = RFAAB; - for (i = 0, mclist = net_dev->mc_list; mclist && i < net_dev->mc_count; - i++, mclist = mclist->next) { + for (i = 0, mclist = net_dev->mc_list; + mclist && i < net_dev->mc_count; + i++, mclist = mclist->next) { unsigned int bit_nr = sis900_mcast_bitnr(mclist->dmi_addr, revision); mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf)); @@ -2114,7 +2141,8 @@ static void set_rx_mode(struct net_device *net_dev) outl(RFEN | rx_mode, ioaddr + rfcr); - /* sis900 is capatable of looping back packet at MAC level for debugging purpose */ + /* sis900 is capable of looping back packets at MAC level for + * debugging purpose */ if (net_dev->flags & IFF_LOOPBACK) { u32 cr_saved; /* We must disable Tx/Rx before setting loopback mode */ @@ -2199,7 +2227,6 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev) static int sis900_suspend(struct pci_dev *pci_dev, u32 state) { struct net_device *net_dev = pci_get_drvdata(pci_dev); - struct sis900_private *sis_priv = net_dev->priv; long ioaddr = net_dev->base_addr; if(!netif_running(net_dev)) @@ -2212,7 +2239,7 @@ static int sis900_suspend(struct pci_dev *pci_dev, u32 state) outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr); pci_set_power_state(pci_dev, 3); - pci_save_state(pci_dev, sis_priv->pci_state); + pci_save_state(pci_dev); return 0; } @@ -2225,7 +2252,7 @@ static int sis900_resume(struct pci_dev *pci_dev) if(!netif_running(net_dev)) return 0; - pci_restore_state(pci_dev, sis_priv->pci_state); + pci_restore_state(pci_dev); pci_set_power_state(pci_dev, 0); sis900_init_rxfilter(net_dev); diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h index a4ed1a7e6..e65a19f87 100644 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -66,8 +66,8 @@ typedef struct s_AC SK_AC; #include #include #include +#include #include -#include #include #include #include @@ -109,7 +109,7 @@ typedef struct s_AC SK_AC; #define SK_MAX_MACS 2 #define SK_MAX_NETS 2 -#define SK_IOC char* +#define SK_IOC char __iomem * typedef struct s_DrvRlmtMbuf SK_MBUF; diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h index 0790e7b7a..3b4c11036 100644 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ b/drivers/net/sk98lin/h/skdrv2nd.h @@ -53,60 +53,6 @@ #include "h/skrlmt.h" #include "h/skgedrv.h" -#define SK_PCI_ISCOMPLIANT(result, pdev) { \ - result = SK_FALSE; /* default */ \ - /* 3Com (0x10b7) */ \ - if (pdev->vendor == 0x10b7) { \ - /* Gigabit Ethernet Adapter (0x1700) */ \ - if ((pdev->device == 0x1700) || \ - (pdev->device == 0x80eb)) { \ - result = SK_TRUE; \ - } \ - /* SysKonnect (0x1148) */ \ - } else if (pdev->vendor == 0x1148) { \ - /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */ \ - /* SK-98xx V2.0 Gigabit Ethernet Adapter (0x4320) */ \ - if ((pdev->device == 0x4300) || \ - (pdev->device == 0x4320)) { \ - result = SK_TRUE; \ - } \ - /* D-Link (0x1186) */ \ - } else if (pdev->vendor == 0x1186) { \ - /* Gigabit Ethernet Adapter (0x4c00) */ \ - if ((pdev->device == 0x4c00)) { \ - result = SK_TRUE; \ - } \ - /* Marvell (0x11ab) */ \ - } else if (pdev->vendor == 0x11ab) { \ - /* Gigabit Ethernet Adapter (0x4320) */ \ - /* Gigabit Ethernet Adapter (0x4360) */ \ - /* Gigabit Ethernet Adapter (0x4361) */ \ - /* Belkin (0x5005) */ \ - if ((pdev->device == 0x4320) || \ - (pdev->device == 0x4360) || \ - (pdev->device == 0x4361) || \ - (pdev->device == 0x5005)) { \ - result = SK_TRUE; \ - } \ - /* CNet (0x1371) */ \ - } else if (pdev->vendor == 0x1371) { \ - /* GigaCard Network Adapter (0x434e) */ \ - if ((pdev->device == 0x434e)) { \ - result = SK_TRUE; \ - } \ - /* Linksys (0x1737) */ \ - } else if (pdev->vendor == 0x1737) { \ - /* Gigabit Network Adapter (0x1032) */ \ - /* Gigabit Network Adapter (0x1064) */ \ - if ((pdev->device == 0x1032) || \ - (pdev->device == 0x1064)) { \ - result = SK_TRUE; \ - } \ - } else { \ - result = SK_FALSE; \ - } \ -} - extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); @@ -339,7 +285,7 @@ struct s_TxPort { TXD *pTxdRingPrev; /* descriptor sent previously */ int TxdRingFree; /* # of free entrys */ spinlock_t TxDesRingLock; /* serialize descriptor accesses */ - caddr_t HwAddr; /* bmu registers address */ + SK_IOC HwAddr; /* bmu registers address */ int PortIndex; /* index number of port (0 or 1) */ }; @@ -355,7 +301,7 @@ struct s_RxPort { int RxdRingFree; /* # of free entrys */ spinlock_t RxDesRingLock; /* serialize descriptor accesses */ int RxFillLimit; /* limit for buffers in ring */ - caddr_t HwAddr; /* bmu registers address */ + SK_IOC HwAddr; /* bmu registers address */ int PortIndex; /* index number of port (0 or 1) */ }; diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c index 5a7ce8ef8..abf857603 100644 --- a/drivers/net/sk98lin/skaddr.c +++ b/drivers/net/sk98lin/skaddr.c @@ -892,7 +892,7 @@ SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber) /* Port Number */ { - int ReturnCode; + int ReturnCode = 0; #if (!defined(SK_SLIM) || defined(DEBUG)) if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { return (SK_ADDR_ILLEGAL_PORT); @@ -1424,7 +1424,7 @@ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* port whose promiscuous mode changes */ int NewPromMode) /* new promiscuous mode */ { - int ReturnCode; + int ReturnCode = 0; #if (!defined(SK_SLIM) || defined(DEBUG)) if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { return (SK_ADDR_ILLEGAL_PORT); diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 503fdff54..5db59c43f 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -72,8 +72,8 @@ * * * + * * - * * * * @@ -110,10 +110,7 @@ #include #include - -#ifdef CONFIG_PROC_FS #include -#endif #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -239,7 +236,7 @@ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); #ifdef CONFIG_PROC_FS static const char SK_Root_Dir_entry[] = "sk98lin"; -static struct proc_dir_entry *pSkRootDir = NULL; +static struct proc_dir_entry *pSkRootDir; extern struct file_operations sk_proc_fops; #endif @@ -255,303 +252,13 @@ static void DumpLong(char*, int); #endif /* global variables *********************************************************/ -static const char *BootString = BOOT_STRING; struct SK_NET_DEVICE *SkGeRootDev = NULL; -static int probed __initdata = 0; static SK_BOOL DoPrintInterfaceChange = SK_TRUE; /* local variables **********************************************************/ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *pSkRootDir; -#endif - - - -/***************************************************************************** - * - * skge_probe - find all SK-98xx adapters - * - * Description: - * This function scans the PCI bus for SK-98xx adapters. Resources for - * each adapter are allocated and the adapter is brought into Init 1 - * state. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_probe (void) -{ - int boards_found = 0; - int vendor_flag = SK_FALSE; - SK_AC *pAC; - DEV_NET *pNet = NULL; - struct pci_dev *pdev = NULL; - struct SK_NET_DEVICE *dev = NULL; - SK_BOOL DeviceFound = SK_FALSE; - SK_BOOL BootStringCount = SK_FALSE; - int retval; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *pProcFile; -#endif - - if (probed) - return -ENODEV; - probed++; - - - while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) { - - if (pci_enable_device(pdev)) { - continue; - } - dev = NULL; - pNet = NULL; - - /* Don't handle Yukon2 cards at the moment */ - /* 12-feb-2004 ---- mlindner@syskonnect.de */ - if (pdev->vendor == 0x11ab) { - if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) ) - continue; - } - - SK_PCI_ISCOMPLIANT(vendor_flag, pdev); - if (!vendor_flag) - continue; - - /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - continue; - - - if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } - - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (pNet->pAC == NULL){ - free_netdev(dev); - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - /* Print message */ - if (!BootStringCount) { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - BootStringCount = SK_TRUE; - printk("%s\n", BootString); - } - - memset(pNet->pAC, 0, sizeof(SK_AC)); - pAC = pNet->pAC; - pAC->PciDev = pdev; - pAC->PciDevId = pdev->device; - pAC->dev[0] = dev; - pAC->dev[1] = dev; - sprintf(pAC->Name, "SysKonnect SK-98xx"); - pAC->CheckQueue = SK_FALSE; - - pNet->Mtu = 1500; - pNet->Up = 0; - dev->irq = pdev->irq; - retval = SkGeInitPCI(pAC); - if (retval) { - printk("SKGE: PCI setup failed: %i\n", retval); - free_netdev(dev); - continue; - } - - SET_MODULE_OWNER(dev); - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->last_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; - SET_NETDEV_DEV(dev, &pdev->dev); - -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM - - if (pAC->ChipsetType) { - /* Use only if yukon hardware */ - /* SK and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif -#endif - - pAC->Index = boards_found; - - if (SkGeBoardInit(dev, pAC)) { - free_netdev(dev); - continue; - } - - /* Register net device */ - if (register_netdev(dev)) { - printk(KERN_ERR "SKGE: Could not register device.\n"); - FreeResources(dev); - free_netdev(dev); - continue; - } - - /* Print adapter specific string from vpd */ - ProductStr(pAC); - printk("%s: %s\n", dev->name, pAC->DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); - - SkGeYellowLED(pAC, pAC->IoBase, 1); - - - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); - - /* First adapter... Create proc and print message */ -#ifdef CONFIG_PROC_FS - if (!DeviceFound) { - DeviceFound = SK_TRUE; - SK_MEMCPY(&SK_Root_Dir_entry, BootString, - sizeof(SK_Root_Dir_entry) - 1); - - /*Create proc (directory)*/ - if(!pSkRootDir) { - pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); - if (!pSkRootDir) { - printk(KERN_WARNING "%s: Unable to create /proc/net/%s", - dev->name, SK_Root_Dir_entry); - } else { - pSkRootDir->owner = THIS_MODULE; - } - } - } - - /* Create proc file */ - if (pSkRootDir && - (pProcFile = create_proc_entry(dev->name, S_IRUGO, - pSkRootDir))) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - } - -#endif - - pNet->PortNr = 0; - pNet->NetNr = 0; - - boards_found++; - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } - - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->last_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; - -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM - if (pAC->ChipsetType) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif -#endif - - if (register_netdev(dev)) { - printk(KERN_ERR "SKGE: Could not register device.\n"); - free_netdev(dev); - pAC->dev[1] = pAC->dev[0]; - } else { -#ifdef CONFIG_PROC_FS - if (pSkRootDir - && (pProcFile = create_proc_entry(dev->name, - S_IRUGO, pSkRootDir))) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - } -#endif - - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); - - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - } - } - - /* Save the hardware revision */ - pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + - (pAC->GIni.GIPciHwRev & 0x0F); - - /* Set driver globals */ - pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; - pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; - - SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); - SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ -#ifndef MODULE - dev->base_addr = 0; -#endif - } - - /* - * If we're at this point we're going through skge_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - return boards_found; -} /* skge_probe */ - - /***************************************************************************** * * SkGeInitPCI - Init the PCI resources @@ -596,7 +303,7 @@ int SkGeInitPCI(SK_AC *pAC) /* * Remap the regs into kernel space. */ - pAC->IoBase = (char*)ioremap_nocache(dev->mem_start, 0x4000); + pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); if (!pAC->IoBase){ retval = 3; @@ -666,9 +373,6 @@ MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); MODULE_PARM(ConType, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -/* not used, just there because every driver should have them: */ -MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); -MODULE_PARM(debug, "i"); /* used for interrupt moderation */ MODULE_PARM(IntsPerSec, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); MODULE_PARM(Moderation, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); @@ -755,123 +459,12 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; #endif -static int debug = 0; /* not used */ -static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ - static int IntsPerSec[SK_MAX_CARD_PARAM]; static char *Moderation[SK_MAX_CARD_PARAM]; static char *ModerationMask[SK_MAX_CARD_PARAM]; static char *AutoSizing[SK_MAX_CARD_PARAM]; static char *Stats[SK_MAX_CARD_PARAM]; - -/***************************************************************************** - * - * skge_init_module - module initialization function - * - * Description: - * Very simple, only call skge_probe and return approriate result. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_init_module(void) -{ - int cards; - SkGeRootDev = NULL; - - /* just to avoid warnings ... */ - debug = 0; - options[0] = 0; - - cards = skge_probe(); - if (cards == 0) { - printk("sk98lin: No adapter found.\n"); - } - return cards ? 0 : -ENODEV; -} /* skge_init_module */ - - -/***************************************************************************** - * - * skge_cleanup_module - module unload function - * - * Description: - * Disable adapter if it is still running, free resources, - * free device struct. - * - * Returns: N/A - */ -static void __exit skge_cleanup_module(void) -{ -DEV_NET *pNet; -SK_AC *pAC; -struct SK_NET_DEVICE *next; -unsigned long Flags; -SK_EVPARA EvPara; - - while (SkGeRootDev) { - pNet = (DEV_NET*) SkGeRootDev->priv; - pAC = pNet->pAC; - next = pAC->Next; - - netif_stop_queue(SkGeRootDev); - SkGeYellowLED(pAC, pAC->IoBase, 0); - - if(pAC->BoardLevel == SK_INIT_RUN) { - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = SK_INIT_DATA; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if(pAC->BoardLevel == SK_INIT_IO) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - } - - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ - unregister_netdev(pAC->dev[1]); - free_netdev(pAC->dev[1]); - } - - FreeResources(SkGeRootDev); - - SkGeRootDev->get_stats = NULL; - /* - * otherwise unregister_netdev calls get_stats with - * invalid IO ... :-( - */ - unregister_netdev(SkGeRootDev); - free_netdev(SkGeRootDev); - kfree(pAC); - SkGeRootDev = next; - } - -#ifdef CONFIG_PROC_FS - /* clear proc-dir */ - remove_proc_entry(pSkRootDir->name, proc_net); -#endif - -} /* skge_cleanup_module */ - -module_init(skge_init_module); -module_exit(skge_cleanup_module); - - /***************************************************************************** * * SkGeBoardInit - do level 0 and 1 initialization @@ -3094,8 +2687,7 @@ SK_EVPARA EvPara; SkEventDispatcher(pAC, pAC->IoBase); for (i=0; iGIni.GIMacsFound; i++) { - spin_lock_irqsave( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); netif_stop_queue(pAC->dev[i]); } @@ -4774,12 +4366,10 @@ SK_BOOL DualNet; spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4792,8 +4382,7 @@ SK_BOOL DualNet; spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); pAC->ActivePort = ToPort; #if 0 SetQueueSizes(pAC); @@ -4808,8 +4397,7 @@ SK_BOOL DualNet; pAC, pAC->ActivePort, DualNet)) { - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4835,8 +4423,7 @@ SK_BOOL DualNet; SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); ClearAndStartRx(pAC, FromPort); ClearAndStartRx(pAC, ToPort); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -5311,8 +4898,317 @@ int l; #endif -/******************************************************************************* - * - * End of file - * - ******************************************************************************/ +static int __devinit skge_probe_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + SK_AC *pAC; + DEV_NET *pNet = NULL; + struct net_device *dev = NULL; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *pProcFile; +#endif + static int boards_found = 0; + int error = -ENODEV; + + if (pci_enable_device(pdev)) + goto out; + + /* Configure DMA attributes. */ + if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && + pci_set_dma_mask(pdev, (u64) 0xffffffff)) + goto out_disable_device; + + + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); + goto out_disable_device; + } + + pNet = dev->priv; + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); + if (!pNet->pAC) { + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); + goto out_free_netdev; + } + + memset(pNet->pAC, 0, sizeof(SK_AC)); + pAC = pNet->pAC; + pAC->PciDev = pdev; + pAC->PciDevId = pdev->device; + pAC->dev[0] = dev; + pAC->dev[1] = dev; + sprintf(pAC->Name, "SysKonnect SK-98xx"); + pAC->CheckQueue = SK_FALSE; + + pNet->Mtu = 1500; + pNet->Up = 0; + dev->irq = pdev->irq; + error = SkGeInitPCI(pAC); + if (error) { + printk("SKGE: PCI setup failed: %i\n", error); + goto out_free_netdev; + } + + SET_MODULE_OWNER(dev); + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; + SET_NETDEV_DEV(dev, &pdev->dev); + +#ifdef SK_ZEROCOPY +#ifdef USE_SK_TX_CHECKSUM + if (pAC->ChipsetType) { + /* Use only if yukon hardware */ + /* SK and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif +#endif + + pAC->Index = boards_found++; + + if (SkGeBoardInit(dev, pAC)) + goto out_free_netdev; + + /* Register net device */ + if (register_netdev(dev)) { + printk(KERN_ERR "SKGE: Could not register device.\n"); + goto out_free_resources; + } + + /* Print adapter specific string from vpd */ + ProductStr(pAC); + printk("%s: %s\n", dev->name, pAC->DeviceStr); + + /* Print configuration settings */ + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); + + SkGeYellowLED(pAC, pAC->IoBase, 1); + + + memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); + +#ifdef CONFIG_PROC_FS + pProcFile = create_proc_entry(dev->name, S_IRUGO, pSkRootDir); + if (pProcFile) { + pProcFile->proc_fops = &sk_proc_fops; + pProcFile->data = dev; + pProcFile->owner = THIS_MODULE; + } +#endif + + pNet->PortNr = 0; + pNet->NetNr = 0; + + boards_found++; + + /* More then one port found */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); + goto out; + } + + pAC->dev[1] = dev; + pNet = dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + pNet->Mtu = 1500; + pNet->Up = 0; + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; + +#ifdef SK_ZEROCOPY +#ifdef USE_SK_TX_CHECKSUM + if (pAC->ChipsetType) { + /* SG and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif +#endif + + if (register_netdev(dev)) { + printk(KERN_ERR "SKGE: Could not register device.\n"); + free_netdev(dev); + pAC->dev[1] = pAC->dev[0]; + } else { +#ifdef CONFIG_PROC_FS + pProcFile = create_proc_entry(dev->name, S_IRUGO, + pSkRootDir); + if (pProcFile) { + pProcFile->proc_fops = &sk_proc_fops; + pProcFile->data = dev; + pProcFile->owner = THIS_MODULE; + } +#endif + + memcpy(&dev->dev_addr, + &pAC->Addr.Net[1].CurrentMacAddress, 6); + + printk("%s: %s\n", dev->name, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + } + } + + /* Save the hardware revision */ + pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + + (pAC->GIni.GIPciHwRev & 0x0F); + + /* Set driver globals */ + pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; + pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; + + memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); + memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); + + pci_set_drvdata(pdev, dev); + return 0; + + out_free_resources: + FreeResources(dev); + out_free_netdev: + free_netdev(dev); + out_disable_device: + pci_disable_device(pdev); + out: + return error; +} + +static void __devexit skge_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = (DEV_NET *) dev->priv; + SK_AC *pAC = pNet->pAC; + int have_second_mac = 0; + + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) + have_second_mac = 1; + + remove_proc_entry(dev->name, pSkRootDir); + unregister_netdev(dev); + if (have_second_mac) { + remove_proc_entry(pAC->dev[1]->name, pSkRootDir); + unregister_netdev(pAC->dev[1]); + } + + SkGeYellowLED(pAC, pAC->IoBase, 0); + + if (pAC->BoardLevel == SK_INIT_RUN) { + SK_EVPARA EvPara; + unsigned long Flags; + + /* board is still alive */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + EvPara.Para32[0] = 0; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + EvPara.Para32[0] = 1; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SkGeDeInit(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pAC->BoardLevel = SK_INIT_DATA; + /* We do NOT check here, if IRQ was pending, of course*/ + } + + if (pAC->BoardLevel == SK_INIT_IO) { + /* board is still alive */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = SK_INIT_DATA; + } + + FreeResources(dev); + free_netdev(dev); + if (have_second_mac) + free_netdev(pAC->dev[1]); + kfree(pAC); +} + +static struct pci_device_id skge_pci_tbl[] = { + { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */ + { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; + +static struct pci_driver skge_driver = { + .name = "skge", + .id_table = skge_pci_tbl, + .probe = skge_probe_one, + .remove = __devexit_p(skge_remove_one), +}; + +static int __init skge_init(void) +{ + int error; + +#ifdef CONFIG_PROC_FS + memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1); + + pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); + if (!pSkRootDir) { + printk(KERN_WARNING "Unable to create /proc/net/%s", + SK_Root_Dir_entry); + return -ENOMEM; + } + pSkRootDir->owner = THIS_MODULE; +#endif + + error = pci_module_init(&skge_driver); + if (error) { +#ifdef CONFIG_PROC_FS + remove_proc_entry(pSkRootDir->name, proc_net); +#endif + } + + return error; +} + +static void __exit skge_exit(void) +{ + pci_unregister_driver(&skge_driver); +#ifdef CONFIG_PROC_FS + remove_proc_entry(pSkRootDir->name, proc_net); +#endif +} + +module_init(skge_init); +module_exit(skge_exit); diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index bc71b55a9..425012d48 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -72,10 +72,10 @@ static const char rcsid[] = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $" #include #include #include +#include #include #include -#include #include "sk_g16.h" diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 2039f2233..ef640f908 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -97,9 +97,9 @@ History: #include #include #include +#include #include -#include #include #define _SK_MCA_DRIVER_ @@ -972,14 +972,6 @@ static struct net_device_stats *skmca_stats(struct net_device *dev) return &(priv->stat); } -/* we don't support runtime reconfiguration, since an MCA card can - be unambigously identified by its POS registers. */ - -static int skmca_config(struct net_device *dev, struct ifmap *map) -{ - return 0; -} - /* switch receiver mode. We use the LANCE's multicast filter to prefilter multicast addresses. */ @@ -1147,7 +1139,6 @@ struct net_device * __init skmca_probe(int unit) /* set methods */ dev->open = skmca_open; dev->stop = skmca_close; - dev->set_config = skmca_config; dev->hard_start_xmit = skmca_tx; dev->do_ioctl = NULL; dev->get_stats = skmca_stats; diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index 6a74332f0..18d429021 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c @@ -1901,7 +1901,8 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc) } if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) { - if (frame_status &= ~LAN_TX) { + frame_status &= ~LAN_TX; + if (frame_status) { DB_TX("Ring is down: terminate LAN_TX",0,0,2) ; } else { diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 1eee9d37f..e9ef28cbb 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -83,9 +83,9 @@ static const char *boot_msg = #include #include #include +#include #include -#include #include #include @@ -1095,7 +1095,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev) */ if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) { - bp->MacStat.tx_errors++; /* bump error counter */ + bp->MacStat.gen.tx_errors++; /* bump error counter */ // dequeue packets from xmt queue and send them netif_start_queue(dev); dev_kfree_skb(skb); @@ -1546,8 +1546,8 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd) skb->len, PCI_DMA_TODEVICE); txd->txd_os.dma_addr = 0; - smc->os.MacStat.tx_packets++; // Count transmitted packets. - smc->os.MacStat.tx_bytes+=skb->len; // Count bytes + smc->os.MacStat.gen.tx_packets++; // Count transmitted packets. + smc->os.MacStat.gen.tx_bytes+=skb->len; // Count bytes // free the skb dev_kfree_skb_irq(skb); @@ -1629,7 +1629,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, skb = rxd->rxd_os.skb; if (!skb) { PRINTK(KERN_INFO "No skb in rxd\n"); - smc->os.MacStat.rx_errors++; + smc->os.MacStat.gen.rx_errors++; goto RequeueRxd; } virt = skb->data; @@ -1682,13 +1682,14 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, } // Count statistics. - smc->os.MacStat.rx_packets++; // Count indicated receive packets. - smc->os.MacStat.rx_bytes+=len; // Count bytes + smc->os.MacStat.gen.rx_packets++; // Count indicated receive + // packets. + smc->os.MacStat.gen.rx_bytes+=len; // Count bytes. // virt points to header again if (virt[1] & 0x01) { // Check group (multicast) bit. - smc->os.MacStat.multicast++; + smc->os.MacStat.gen.multicast++; } // deliver frame to system @@ -1706,7 +1707,8 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, RequeueRxd: PRINTK(KERN_INFO "Rx: re-queue RXD.\n"); mac_drv_requeue_rxd(smc, rxd, frag_count); - smc->os.MacStat.rx_errors++; // Count receive packets not indicated. + smc->os.MacStat.gen.rx_errors++; // Count receive packets + // not indicated. } // mac_drv_rx_complete @@ -2081,7 +2083,7 @@ void smt_stat_counter(struct s_smc *smc, int stat) break; case 1: PRINTK(KERN_INFO "Receive fifo overflow.\n"); - smc->os.MacStat.rx_errors++; + smc->os.MacStat.gen.rx_errors++; break; default: PRINTK(KERN_INFO "Unknown status (%d).\n", stat); diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 6209a35aa..4ce52f5f2 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -57,10 +57,11 @@ #define SL_CHECK_TRANSMIT #include #include +#include #include #include -#include +#include #include #include #include @@ -85,8 +86,8 @@ static struct net_device **slip_devs; -int slip_maxdev = SL_NRUNIT; /* Can be overridden with insmod! */ -MODULE_PARM(slip_maxdev, "i"); +static int slip_maxdev = SL_NRUNIT; +module_param(slip_maxdev, int, 0); MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices"); static int slip_esc(unsigned char *p, unsigned char *d, int len); @@ -417,7 +418,7 @@ sl_encaps(struct slip *sl, unsigned char *icp, int len) * 14 Oct 1994 Dmitry Gorodchanin. */ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = sl->tty->driver->write(sl->tty, 0, sl->xbuff, count); + actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); #ifdef SL_CHECK_TRANSMIT sl->dev->trans_start = jiffies; #endif @@ -451,20 +452,18 @@ static void slip_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, sl->xhead, sl->xleft); + actual = tty->driver->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; } static void sl_tx_timeout(struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); spin_lock(&sl->lock); if (netif_queue_stopped(dev)) { - struct slip *sl = (struct slip*)(dev->priv); - if (!netif_running(dev)) goto out; @@ -494,7 +493,7 @@ out: static int sl_xmit(struct sk_buff *skb, struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); spin_lock(&sl->lock); if (!netif_running(dev)) { @@ -528,7 +527,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev) static int sl_close(struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); spin_lock_bh(&sl->lock); if (sl->tty) { @@ -547,7 +546,7 @@ sl_close(struct net_device *dev) static int sl_open(struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); if (sl->tty==NULL) return -ENODEV; @@ -561,7 +560,7 @@ static int sl_open(struct net_device *dev) static int sl_change_mtu(struct net_device *dev, int new_mtu) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); if (new_mtu < 68 || new_mtu > 65534) return -EINVAL; @@ -577,7 +576,7 @@ static struct net_device_stats * sl_get_stats(struct net_device *dev) { static struct net_device_stats stats; - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); #ifdef SL_INCLUDE_CSLIP struct slcompress *comp; #endif @@ -612,7 +611,7 @@ sl_get_stats(struct net_device *dev) static int sl_init(struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); /* * Finish setting up the DEVICE info. @@ -630,7 +629,7 @@ static int sl_init(struct net_device *dev) static void sl_uninit(struct net_device *dev) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); sl_free_bufs(sl); } @@ -672,7 +671,9 @@ static int slip_receive_room(struct tty_struct *tty) * Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when * a block of SLIP data has been received, which can now be decapsulated - * and sent on to some IP layer for further processing. + * and sent on to some IP layer for further processing. This will not + * be re-entered while running but other ldisc functions may be called + * in parallel */ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) @@ -717,7 +718,7 @@ static void sl_sync(void) if ((dev = slip_devs[i]) == NULL) break; - sl = dev->priv; + sl = netdev_priv(dev); if (sl->tty || sl->leased) continue; if (dev->flags&IFF_UP) @@ -744,7 +745,7 @@ sl_alloc(dev_t line) if (dev == NULL) break; - sl = dev->priv; + sl = netdev_priv(dev); if (sl->leased) { if (sl->line != line) continue; @@ -786,7 +787,7 @@ sl_alloc(dev_t line) i = sel; dev = slip_devs[i]; if (score > 1) { - sl = dev->priv; + sl = netdev_priv(dev); sl->flags &= (1 << SLF_INUSE); return sl; } @@ -797,7 +798,7 @@ sl_alloc(dev_t line) return NULL; if (dev) { - sl = dev->priv; + sl = netdev_priv(dev); if (test_bit(SLF_INUSE, &sl->flags)) { unregister_netdevice(dev); dev = NULL; @@ -815,7 +816,7 @@ sl_alloc(dev_t line) dev->base_addr = i; } - sl = dev->priv; + sl = netdev_priv(dev); /* Initialize channel control data */ sl->magic = SLIP_MAGIC; @@ -841,9 +842,11 @@ sl_alloc(dev_t line) * SLIP line discipline is called for. Because we are * sure the tty line exists, we only have to link it to * a free SLIP channel... + * + * Called in process context serialized from other ldisc calls. */ -static int -slip_open(struct tty_struct *tty) + +static int slip_open(struct tty_struct *tty) { struct slip *sl; int err; @@ -876,11 +879,11 @@ slip_open(struct tty_struct *tty) tty->disc_data = sl; sl->line = tty_devnum(tty); sl->pid = current->pid; + + /* FIXME: already done before we were called - seems this can go */ if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - + if (!test_bit(SLF_INUSE, &sl->flags)) { /* Perform the low-level SLIP initialization. */ if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0) @@ -923,6 +926,9 @@ err_exit: } /* + + FIXME: 1,2 are fixed 3 was never true anyway. + Let me to blame a bit. 1. TTY module calls this funstion on soft interrupt. 2. TTY module calls this function WITH MASKED INTERRUPTS! @@ -941,9 +947,8 @@ err_exit: /* * Close down a SLIP channel. - * This means flushing out any pending queues, and then restoring the - * TTY line discipline to what it was before it got hooked to SLIP - * (which usually is TTY again). + * This means flushing out any pending queues, and then returning. This + * call is serialized against other ldisc functions. */ static void slip_close(struct tty_struct *tty) @@ -1254,7 +1259,7 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd) { - struct slip *sl = (struct slip*)(dev->priv); + struct slip *sl = netdev_priv(dev); unsigned long *p = (unsigned long *)&rq->ifr_ifru; if (sl == NULL) /* Allocation failed ?? */ @@ -1400,7 +1405,7 @@ static void __exit slip_exit(void) dev = slip_devs[i]; if (!dev) continue; - sl = dev->priv; + sl = netdev_priv(dev); spin_lock_bh(&sl->lock); if (sl->tty) { busy++; @@ -1417,7 +1422,7 @@ static void __exit slip_exit(void) continue; slip_devs[i] = NULL; - sl = dev->priv; + sl = netdev_priv(dev); if (sl->tty) { printk(KERN_ERR "%s: tty discipline still running\n", dev->name); @@ -1469,7 +1474,7 @@ static void sl_outfill(unsigned long sls) if (!netif_queue_stopped(sl->dev)) { /* if device busy no outfill */ - sl->tty->driver->write(sl->tty, 0, &s, 1); + sl->tty->driver->write(sl->tty, &s, 1); } } else diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 8ee249a38..de31ab713 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -72,8 +72,8 @@ static const char version[] = #include #include #include +#include -#include #include #include "smc9194.h" @@ -1191,133 +1191,6 @@ static void smc_timeout(struct net_device *dev) netif_wake_queue(dev); } -/*-------------------------------------------------------------------- - . - . This is the main routine of the driver, to handle the device when - . it needs some attention. - . - . So: - . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge - . each to the interrupt register - . and finally restore state. - . - ---------------------------------------------------------------------*/ - -static irqreturn_t smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - int ioaddr = dev->base_addr; - struct smc_local *lp = netdev_priv(dev); - - byte status; - word card_stats; - byte mask; - int timeout; - /* state registers */ - word saved_bank; - word saved_pointer; - int handled = 0; - - - PRINTK3((CARDNAME": SMC interrupt started \n")); - - saved_bank = inw( ioaddr + BANK_SELECT ); - - SMC_SELECT_BANK(2); - saved_pointer = inw( ioaddr + POINTER ); - - mask = inb( ioaddr + INT_MASK ); - /* clear all interrupts */ - outb( 0, ioaddr + INT_MASK ); - - - /* set a timeout value, so I don't stay here forever */ - timeout = 4; - - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); - do { - /* read the status flag, and mask it */ - status = inb( ioaddr + INTERRUPT ) & mask; - if (!status ) - break; - - handled = 1; - - PRINTK3((KERN_WARNING CARDNAME - ": Handling interrupt status %x \n", status )); - - if (status & IM_RCV_INT) { - /* Got a packet(s). */ - PRINTK2((KERN_WARNING CARDNAME - ": Receive Interrupt\n")); - smc_rcv(dev); - } else if (status & IM_TX_INT ) { - PRINTK2((KERN_WARNING CARDNAME - ": TX ERROR handled\n")); - smc_tx(dev); - outb(IM_TX_INT, ioaddr + INTERRUPT ); - } else if (status & IM_TX_EMPTY_INT ) { - /* update stats */ - SMC_SELECT_BANK( 0 ); - card_stats = inw( ioaddr + COUNTER ); - /* single collisions */ - lp->stats.collisions += card_stats & 0xF; - card_stats >>= 4; - /* multiple collisions */ - lp->stats.collisions += card_stats & 0xF; - - /* these are for when linux supports these statistics */ - - SMC_SELECT_BANK( 2 ); - PRINTK2((KERN_WARNING CARDNAME - ": TX_BUFFER_EMPTY handled\n")); - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); - mask &= ~IM_TX_EMPTY_INT; - lp->stats.tx_packets += lp->packets_waiting; - lp->packets_waiting = 0; - - } else if (status & IM_ALLOC_INT ) { - PRINTK2((KERN_DEBUG CARDNAME - ": Allocation interrupt \n")); - /* clear this interrupt so it doesn't happen again */ - mask &= ~IM_ALLOC_INT; - - smc_hardware_send_packet( dev ); - - /* enable xmit interrupts based on this */ - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); - - /* and let the card send more packets to me */ - netif_wake_queue(dev); - - PRINTK2((CARDNAME": Handoff done successfully.\n")); - } else if (status & IM_RX_OVRN_INT ) { - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); - } else if (status & IM_EPH_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); - } else if (status & IM_ERCV_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); - outb( IM_ERCV_INT, ioaddr + INTERRUPT ); - } - } while ( timeout -- ); - - - /* restore state register */ - SMC_SELECT_BANK( 2 ); - outb( mask, ioaddr + INT_MASK ); - - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); - outw( saved_pointer, ioaddr + POINTER ); - - SMC_SELECT_BANK( saved_bank ); - - PRINTK3((CARDNAME ": Interrupt done\n")); - return IRQ_RETVAL(handled); -} - /*------------------------------------------------------------- . . smc_rcv - receive a packet from the card @@ -1509,6 +1382,134 @@ static void smc_tx( struct net_device * dev ) return; } +/*-------------------------------------------------------------------- + . + . This is the main routine of the driver, to handle the device when + . it needs some attention. + . + . So: + . first, save state of the chipset + . branch off into routines to handle each case, and acknowledge + . each to the interrupt register + . and finally restore state. + . + ---------------------------------------------------------------------*/ + +static irqreturn_t smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + int ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + + byte status; + word card_stats; + byte mask; + int timeout; + /* state registers */ + word saved_bank; + word saved_pointer; + int handled = 0; + + + PRINTK3((CARDNAME": SMC interrupt started \n")); + + saved_bank = inw( ioaddr + BANK_SELECT ); + + SMC_SELECT_BANK(2); + saved_pointer = inw( ioaddr + POINTER ); + + mask = inb( ioaddr + INT_MASK ); + /* clear all interrupts */ + outb( 0, ioaddr + INT_MASK ); + + + /* set a timeout value, so I don't stay here forever */ + timeout = 4; + + PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); + do { + /* read the status flag, and mask it */ + status = inb( ioaddr + INTERRUPT ) & mask; + if (!status ) + break; + + handled = 1; + + PRINTK3((KERN_WARNING CARDNAME + ": Handling interrupt status %x \n", status )); + + if (status & IM_RCV_INT) { + /* Got a packet(s). */ + PRINTK2((KERN_WARNING CARDNAME + ": Receive Interrupt\n")); + smc_rcv(dev); + } else if (status & IM_TX_INT ) { + PRINTK2((KERN_WARNING CARDNAME + ": TX ERROR handled\n")); + smc_tx(dev); + outb(IM_TX_INT, ioaddr + INTERRUPT ); + } else if (status & IM_TX_EMPTY_INT ) { + /* update stats */ + SMC_SELECT_BANK( 0 ); + card_stats = inw( ioaddr + COUNTER ); + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + + /* these are for when linux supports these statistics */ + + SMC_SELECT_BANK( 2 ); + PRINTK2((KERN_WARNING CARDNAME + ": TX_BUFFER_EMPTY handled\n")); + outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); + mask &= ~IM_TX_EMPTY_INT; + lp->stats.tx_packets += lp->packets_waiting; + lp->packets_waiting = 0; + + } else if (status & IM_ALLOC_INT ) { + PRINTK2((KERN_DEBUG CARDNAME + ": Allocation interrupt \n")); + /* clear this interrupt so it doesn't happen again */ + mask &= ~IM_ALLOC_INT; + + smc_hardware_send_packet( dev ); + + /* enable xmit interrupts based on this */ + mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); + + /* and let the card send more packets to me */ + netif_wake_queue(dev); + + PRINTK2((CARDNAME": Handoff done successfully.\n")); + } else if (status & IM_RX_OVRN_INT ) { + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); + } else if (status & IM_EPH_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); + } else if (status & IM_ERCV_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); + outb( IM_ERCV_INT, ioaddr + INTERRUPT ); + } + } while ( timeout -- ); + + + /* restore state register */ + SMC_SELECT_BANK( 2 ); + outb( mask, ioaddr + INT_MASK ); + + PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); + outw( saved_pointer, ioaddr + POINTER ); + + SMC_SELECT_BANK( saved_bank ); + + PRINTK3((CARDNAME ": Interrupt done\n")); + return IRQ_RETVAL(handled); +} + + /*---------------------------------------------------- . smc_close . diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 85fae0965..9b75be8b9 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -55,9 +55,10 @@ * smc_phy_configure * - clean up (and fix stack overrun) in PHY * MII read/write functions + * 22/09/04 Nicolas Pitre big update (see commit log for details) */ static const char version[] = - "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre \n"; + "smc91x.c: v1.1, sep 22 2004 by Nicolas Pitre \n"; /* Debugging level */ #ifndef SMC_DEBUG @@ -72,7 +73,7 @@ static const char version[] = #include #include #include -#include +#include #include #include #include @@ -80,6 +81,7 @@ static const char version[] = #include #include #include +#include #include #include @@ -174,7 +176,8 @@ struct smc_local { * packet, I will store the skbuff here, until I get the * desired memory. Then, I'll send it out and free it. */ - struct sk_buff *saved_skb; + struct sk_buff *pending_tx_skb; + struct tasklet_struct tx_task; /* * these are things that the kernel wants me to keep, so users @@ -200,6 +203,11 @@ struct smc_local { u32 msg_enable; u32 phy_type; struct mii_if_info mii; + + /* work queue */ + struct work_struct phy_configure; + int work_pending; + spinlock_t lock; #ifdef SMC_USE_PXA_DMA @@ -212,7 +220,7 @@ struct smc_local { #define DBG(n, args...) \ do { \ if (SMC_DEBUG >= (n)) \ - printk(KERN_DEBUG args); \ + printk(args); \ } while (0) #define PRINTK(args...) printk(args) @@ -256,24 +264,22 @@ static void PRINT_PKT(u_char *buf, int length) /* this enables an interrupt in the interrupt mask register */ #define SMC_ENABLE_INT(x) do { \ - unsigned long flags; \ unsigned char mask; \ - spin_lock_irqsave(&lp->lock, flags); \ + spin_lock_irq(&lp->lock); \ mask = SMC_GET_INT_MASK(); \ mask |= (x); \ SMC_SET_INT_MASK(mask); \ - spin_unlock_irqrestore(&lp->lock, flags); \ + spin_unlock_irq(&lp->lock); \ } while (0) /* this disables an interrupt from the interrupt mask register */ #define SMC_DISABLE_INT(x) do { \ - unsigned long flags; \ unsigned char mask; \ - spin_lock_irqsave(&lp->lock, flags); \ + spin_lock_irq(&lp->lock); \ mask = SMC_GET_INT_MASK(); \ mask &= ~(x); \ SMC_SET_INT_MASK(mask); \ - spin_unlock_irqrestore(&lp->lock, flags); \ + spin_unlock_irq(&lp->lock); \ } while (0) /* @@ -302,10 +308,17 @@ static void PRINT_PKT(u_char *buf, int length) static void smc_reset(struct net_device *dev) { unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); unsigned int ctl, cfg; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + /* Disable all interrupts */ + spin_lock(&lp->lock); + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(0); + spin_unlock(&lp->lock); + /* * This resets the registers mostly to defaults, but doesn't * affect EEPROM. That seems unnecessary @@ -361,20 +374,24 @@ static void smc_reset(struct net_device *dev) * transmitted packets, to make the best use out of our limited * memory */ -#if ! THROTTLE_TX_PKTS - ctl |= CTL_AUTO_RELEASE; -#else - ctl &= ~CTL_AUTO_RELEASE; -#endif + if(!THROTTLE_TX_PKTS) + ctl |= CTL_AUTO_RELEASE; + else + ctl &= ~CTL_AUTO_RELEASE; SMC_SET_CTL(ctl); - /* Disable all interrupts */ - SMC_SELECT_BANK(2); - SMC_SET_INT_MASK(0); - /* Reset the MMU */ + SMC_SELECT_BANK(2); SMC_SET_MMU_CMD(MC_RESET); SMC_WAIT_MMU_BUSY(); + + /* clear anything saved */ + if (lp->pending_tx_skb != NULL) { + dev_kfree_skb (lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } } /* @@ -393,24 +410,39 @@ static void smc_enable(struct net_device *dev) SMC_SET_TCR(lp->tcr_cur_mode); SMC_SET_RCR(lp->rcr_cur_mode); + SMC_SELECT_BANK(1); + SMC_SET_MAC_ADDR(dev->dev_addr); + /* now, enable interrupts */ mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT; if (lp->version >= (CHIP_91100 << 4)) mask |= IM_MDINT; SMC_SELECT_BANK(2); SMC_SET_INT_MASK(mask); + + /* + * From this point the register bank must _NOT_ be switched away + * to something else than bank 2 without proper locking against + * races with any tasklet or interrupt handlers until smc_shutdown() + * or smc_reset() is called. + */ } /* * this puts the device in an inactive state */ -static void smc_shutdown(unsigned long ioaddr) +static void smc_shutdown(struct net_device *dev) { + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); /* no more interrupts for me */ + spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); + spin_unlock(&lp->lock); /* and tell the card to stay away from that nasty outside world */ SMC_SELECT_BANK(0); @@ -452,6 +484,8 @@ static inline void smc_rcv(struct net_device *dev) packet_len, packet_len); if (unlikely(status & RS_ERRORS)) { + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD(MC_RELEASE); lp->stats.rx_errors++; if (status & RS_ALGNERR) lp->stats.rx_frame_errors++; @@ -469,17 +503,21 @@ static inline void smc_rcv(struct net_device *dev) lp->stats.multicast++; /* - * Actual payload is packet_len - 4 (or 3 if odd byte). + * Actual payload is packet_len - 6 (or 5 if odd byte). * We want skb_reserve(2) and the final ctrl word * (2 bytes, possibly containing the payload odd byte). - * Ence packet_len - 4 + 2 + 2. + * Furthermore, we add 2 bytes to allow rounding up to + * multiple of 4 bytes on 32 bit buses. + * Ence packet_len - 6 + 2 + 2 + 2. */ skb = dev_alloc_skb(packet_len); if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", dev->name); + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD(MC_RELEASE); lp->stats.rx_dropped++; - goto done; + return; } /* Align IP header to 32 bits */ @@ -490,14 +528,18 @@ static inline void smc_rcv(struct net_device *dev) status |= RS_ODDFRAME; /* - * If odd length: packet_len - 3, - * otherwise packet_len - 4. + * If odd length: packet_len - 5, + * otherwise packet_len - 6. + * With the trailing ctrl byte it's packet_len - 4. */ - data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4); + data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6); data = skb_put(skb, data_len); - SMC_PULL_DATA(data, packet_len - 2); + SMC_PULL_DATA(data, packet_len - 4); + + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD(MC_RELEASE); - PRINT_PKT(data, packet_len - 2); + PRINT_PKT(data, packet_len - 4); dev->last_rx = jiffies; skb->dev = dev; @@ -506,34 +548,76 @@ static inline void smc_rcv(struct net_device *dev) lp->stats.rx_packets++; lp->stats.rx_bytes += data_len; } - -done: - SMC_WAIT_MMU_BUSY(); - SMC_SET_MMU_CMD(MC_RELEASE); } +#ifdef CONFIG_SMP +/* + * On SMP we have the following problem: + * + * A = smc_hardware_send_pkt() + * B = smc_hard_start_xmit() + * C = smc_interrupt() + * + * A and B can never be executed simultaneously. However, at least on UP, + * it is possible (and even desirable) for C to interrupt execution of + * A or B in order to have better RX reliability and avoid overruns. + * C, just like A and B, must have exclusive access to the chip and + * each of them must lock against any other concurrent access. + * Unfortunately this is not possible to have C suspend execution of A or + * B taking place on another CPU. On UP this is no an issue since A and B + * are run from softirq context and C from hard IRQ context, and there is + * no other CPU where concurrent access can happen. + * If ever there is a way to force at least B and C to always be executed + * on the same CPU then we could use read/write locks to protect against + * any other concurrent access and C would always interrupt B. But life + * isn't that easy in a SMP world... + */ +#define smc_special_trylock(lock) \ +({ \ + int __ret; \ + local_irq_disable(); \ + __ret = spin_trylock(lock); \ + if (!__ret) \ + local_irq_enable(); \ + __ret; \ +}) +#define smc_special_lock(lock) spin_lock_irq(lock) +#define smc_special_unlock(lock) spin_unlock_irq(lock) +#else +#define smc_special_trylock(lock) (1) +#define smc_special_lock(lock) do { } while (0) +#define smc_special_unlock(lock) do { } while (0) +#endif + /* * This is called to actually send a packet to the chip. - * Returns non-zero when successful. */ -static void smc_hardware_send_packet(struct net_device *dev) +static void smc_hardware_send_pkt(unsigned long data) { + struct net_device *dev = (struct net_device *)data; struct smc_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; - struct sk_buff *skb = lp->saved_skb; + struct sk_buff *skb; unsigned int packet_no, len; unsigned char *buf; DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + if (!smc_special_trylock(&lp->lock)) { + netif_stop_queue(dev); + tasklet_schedule(&lp->tx_task); + return; + } + + skb = lp->pending_tx_skb; + lp->pending_tx_skb = NULL; packet_no = SMC_GET_AR(); if (unlikely(packet_no & AR_FAILED)) { printk("%s: Memory allocation failed.\n", dev->name); - lp->saved_skb = NULL; lp->stats.tx_errors++; lp->stats.tx_fifo_errors++; - dev_kfree_skb_any(skb); - return; + smc_special_unlock(&lp->lock); + goto done; } /* point to the beginning of the packet */ @@ -558,15 +642,33 @@ static void smc_hardware_send_packet(struct net_device *dev) /* Send final ctl word with the last byte if there is one */ SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG); - /* and let the chipset deal with it */ + /* + * If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag + * before queueing this packet for TX, and if it's clear then + * we stop the queue here. This will have the effect of + * having at most 2 packets queued for TX in the chip's memory + * at all time. If THROTTLE_TX_PKTS is not set then the queue + * is stopped only when memory allocation (MC_ALLOC) does not + * succeed right away. + */ + if (THROTTLE_TX_PKTS && !(SMC_GET_INT() & IM_TX_EMPTY_INT)) + netif_stop_queue(dev); + + /* queue the packet for TX */ SMC_SET_MMU_CMD(MC_ENQUEUE); SMC_ACK_INT(IM_TX_EMPTY_INT); + smc_special_unlock(&lp->lock); dev->trans_start = jiffies; - dev_kfree_skb_any(skb); - lp->saved_skb = NULL; lp->stats.tx_packets++; lp->stats.tx_bytes += len; + + SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT); + +done: if (!THROTTLE_TX_PKTS) + netif_wake_queue(dev); + + dev_kfree_skb(skb); } /* @@ -579,12 +681,12 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; - unsigned int numPages, poll_count, status, saved_bank; + unsigned int numPages, poll_count, status; DBG(3, "%s: %s\n", dev->name, __FUNCTION__); - BUG_ON(lp->saved_skb != NULL); - lp->saved_skb = skb; + BUG_ON(lp->pending_tx_skb != NULL); + lp->pending_tx_skb = skb; /* * The MMU wants the number of pages to be the number of 256 bytes @@ -600,16 +702,16 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) numPages = ((skb->len & ~1) + (6 - 1)) >> 8; if (unlikely(numPages > 7)) { printk("%s: Far too big packet error.\n", dev->name); - lp->saved_skb = NULL; + lp->pending_tx_skb = NULL; lp->stats.tx_errors++; lp->stats.tx_dropped++; dev_kfree_skb(skb); return 0; } + smc_special_lock(&lp->lock); + /* now, try to allocate the memory */ - saved_bank = SMC_CURRENT_BANK(); - SMC_SELECT_BANK(2); SMC_SET_MMU_CMD(MC_ALLOC | numPages); /* @@ -625,6 +727,8 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } while (--poll_count); + smc_special_unlock(&lp->lock); + if (!poll_count) { /* oh well, wait until the chip finds memory later */ netif_stop_queue(dev); @@ -634,24 +738,10 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* * Allocation succeeded: push packet to the chip's own memory * immediately. - * - * If THROTTLE_TX_PKTS is selected that means we don't want - * more than a single TX packet taking up space in the chip's - * internal memory at all time, in which case we stop the - * queue right here until we're notified of TX completion. - * - * Otherwise we're quite happy to feed more TX packets right - * away for better TX throughput, in which case the queue is - * left active. */ -#if THROTTLE_TX_PKTS - netif_stop_queue(dev); -#endif - smc_hardware_send_packet(dev); - SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT); + smc_hardware_send_pkt((unsigned long)dev); } - SMC_SELECT_BANK(saved_bank); return 0; } @@ -765,10 +855,8 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits) static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) { unsigned long ioaddr = dev->base_addr; - unsigned int phydata, old_bank; + unsigned int phydata; - /* Save the current bank, and select bank 3 */ - old_bank = SMC_CURRENT_BANK(); SMC_SELECT_BANK(3); /* Idle - 32 ones */ @@ -783,12 +871,10 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) /* Return to idle state */ SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); - /* And select original bank */ - SMC_SELECT_BANK(old_bank); - DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __FUNCTION__, phyaddr, phyreg, phydata); + SMC_SELECT_BANK(2); return phydata; } @@ -799,10 +885,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, int phydata) { unsigned long ioaddr = dev->base_addr; - unsigned int old_bank; - /* Save the current bank, and select bank 3 */ - old_bank = SMC_CURRENT_BANK(); SMC_SELECT_BANK(3); /* Idle - 32 ones */ @@ -814,17 +897,16 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, /* Return to idle state */ SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); - /* And select original bank */ - SMC_SELECT_BANK(old_bank); - DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", __FUNCTION__, phyaddr, phyreg, phydata); + + SMC_SELECT_BANK(2); } /* * Finds and reports the PHY address */ -static void smc_detect_phy(struct net_device *dev) +static void smc_phy_detect(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); int phyaddr; @@ -891,7 +973,9 @@ static int smc_phy_fixed(struct net_device *dev) smc_phy_write(dev, phyaddr, MII_BMCR, bmcr); /* Re-Configure the Receive/Phy Control register */ + SMC_SELECT_BANK(0); SMC_SET_RPC(lp->rpc_cur_mode); + SMC_SELECT_BANK(2); return 1; } @@ -939,13 +1023,10 @@ static int smc_phy_reset(struct net_device *dev, int phy) */ static void smc_phy_powerdown(struct net_device *dev, int phy) { - struct smc_local *lp = netdev_priv(dev); unsigned int bmcr; - spin_lock_irq(&lp->lock); bmcr = smc_phy_read(dev, phy, MII_BMCR); smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); - spin_unlock_irq(&lp->lock); } /* @@ -962,8 +1043,6 @@ static void smc_phy_check_media(struct net_device *dev, int init) unsigned long ioaddr = dev->base_addr; if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { - unsigned int old_bank; - /* duplex state has changed */ if (lp->mii.full_duplex) { lp->tcr_cur_mode |= TCR_SWFDUP; @@ -971,10 +1050,8 @@ static void smc_phy_check_media(struct net_device *dev, int init) lp->tcr_cur_mode &= ~TCR_SWFDUP; } - old_bank = SMC_CURRENT_BANK(); SMC_SELECT_BANK(0); SMC_SET_TCR(lp->tcr_cur_mode); - SMC_SELECT_BANK(old_bank); } } @@ -987,8 +1064,9 @@ static void smc_phy_check_media(struct net_device *dev, int init) * of autonegotiation.) If the RPC ANEG bit is cleared, the selection * is controlled by the RPC SPEED and RPC DPLX bits. */ -static void smc_phy_configure(struct net_device *dev) +static void smc_phy_configure(void *data) { + struct net_device *dev = data; struct smc_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; int phyaddr = lp->mii.phy_id; @@ -1080,6 +1158,7 @@ static void smc_phy_configure(struct net_device *dev) smc_phy_configure_exit: spin_unlock_irq(&lp->lock); + lp->work_pending = 0; } /* @@ -1115,12 +1194,13 @@ static void smc_10bt_check_media(struct net_device *dev, int init) { struct smc_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; - unsigned int old_carrier, new_carrier, old_bank; + unsigned int old_carrier, new_carrier; - old_bank = SMC_CURRENT_BANK(); - SMC_SELECT_BANK(0); old_carrier = netif_carrier_ok(dev) ? 1 : 0; + + SMC_SELECT_BANK(0); new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0; + SMC_SELECT_BANK(2); if (init || (old_carrier != new_carrier)) { if (!new_carrier) { @@ -1132,24 +1212,20 @@ static void smc_10bt_check_media(struct net_device *dev, int init) printk(KERN_INFO "%s: link %s\n", dev->name, new_carrier ? "up" : "down"); } - SMC_SELECT_BANK(old_bank); } static void smc_eph_interrupt(struct net_device *dev) { unsigned long ioaddr = dev->base_addr; - unsigned int old_bank, ctl; + unsigned int ctl; smc_10bt_check_media(dev, 0); - old_bank = SMC_CURRENT_BANK(); SMC_SELECT_BANK(1); - ctl = SMC_GET_CTL(); SMC_SET_CTL(ctl & ~CTL_LE_ENABLE); SMC_SET_CTL(ctl); - - SMC_SELECT_BANK(old_bank); + SMC_SELECT_BANK(2); } /* @@ -1162,12 +1238,17 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) unsigned long ioaddr = dev->base_addr; struct smc_local *lp = netdev_priv(dev); int status, mask, timeout, card_stats; - int saved_bank, saved_pointer; + int saved_pointer; DBG(3, "%s: %s\n", dev->name, __FUNCTION__); - saved_bank = SMC_CURRENT_BANK(); - SMC_SELECT_BANK(2); + spin_lock(&lp->lock); + + /* A preamble may be used when there is a potential race + * between the interruptible transmit functions and this + * ISR. */ + SMC_INTERRUPT_PREAMBLE; + saved_pointer = SMC_GET_PTR(); mask = SMC_GET_INT_MASK(); SMC_SET_INT_MASK(0); @@ -1178,7 +1259,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) do { status = SMC_GET_INT(); - DBG(2, "%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", + DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", dev->name, status, mask, ({ int meminfo; SMC_SELECT_BANK(0); meminfo = SMC_GET_MIR(); @@ -1189,8 +1270,6 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!status) break; - spin_lock(&lp->lock); - if (status & IM_RCV_INT) { DBG(3, "%s: RX irq\n", dev->name); smc_rcv(dev); @@ -1198,17 +1277,12 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) DBG(3, "%s: TX int\n", dev->name); smc_tx(dev); SMC_ACK_INT(IM_TX_INT); -#if THROTTLE_TX_PKTS - netif_wake_queue(dev); -#endif + if (THROTTLE_TX_PKTS) + netif_wake_queue(dev); } else if (status & IM_ALLOC_INT) { DBG(3, "%s: Allocation irq\n", dev->name); - smc_hardware_send_packet(dev); - mask |= (IM_TX_INT | IM_TX_EMPTY_INT); + tasklet_hi_schedule(&lp->tx_task); mask &= ~IM_ALLOC_INT; -#if ! THROTTLE_TX_PKTS - netif_wake_queue(dev); -#endif } else if (status & IM_TX_EMPTY_INT) { DBG(3, "%s: TX empty\n", dev->name); mask &= ~IM_TX_EMPTY_INT; @@ -1238,14 +1312,13 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) SMC_ACK_INT(IM_ERCV_INT); PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name); } - - spin_unlock(&lp->lock); } while (--timeout); /* restore register states */ - SMC_SET_INT_MASK(mask); SMC_SET_PTR(saved_pointer); - SMC_SELECT_BANK(saved_bank); + SMC_SET_INT_MASK(mask); + + spin_unlock(&lp->lock); DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); @@ -1264,95 +1337,41 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void smc_timeout(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int status, mask, meminfo, fifo; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + spin_lock_irq(&lp->lock); + status = SMC_GET_INT(); + mask = SMC_GET_INT_MASK(); + fifo = SMC_GET_FIFO(); + SMC_SELECT_BANK(0); + meminfo = SMC_GET_MIR(); + SMC_SELECT_BANK(2); + spin_unlock_irq(&lp->lock); + PRINTK( "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", + dev->name, status, mask, meminfo, fifo ); + smc_reset(dev); smc_enable(dev); -#if 0 /* * Reconfiguring the PHY doesn't seem like a bad idea here, but - * it introduced a problem. Now that this is a timeout routine, - * we are getting called from within an interrupt context. - * smc_phy_configure() calls msleep() which calls - * schedule_timeout() which calls schedule(). When schedule() - * is called from an interrupt context, it prints out - * "Scheduling in interrupt" and then calls BUG(). This is - * obviously not desirable. This was worked around by removing - * the call to smc_phy_configure() here because it didn't seem - * absolutely necessary. Ultimately, if msleep() is - * supposed to be usable from an interrupt context (which it - * looks like it thinks it should handle), it should be fixed. + * smc_phy_configure() calls msleep() which calls schedule_timeout() + * which calls schedule(). Hence we use a work queue. */ - if (lp->phy_type != 0) - smc_phy_configure(dev); -#endif - - /* clear anything saved */ - if (lp->saved_skb != NULL) { - dev_kfree_skb (lp->saved_skb); - lp->saved_skb = NULL; - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; + if (lp->phy_type != 0) { + if (schedule_work(&lp->phy_configure)) { + lp->work_pending = 1; + } } + /* We can accept TX packets again */ dev->trans_start = jiffies; netif_wake_queue(dev); } -/* - * This sets the internal hardware table to filter out unwanted multicast - * packets before they take up memory. - * - * The SMC chip uses a hash table where the high 6 bits of the CRC of - * address are the offset into the table. If that bit is 1, then the - * multicast packet is accepted. Otherwise, it's dropped silently. - * - * To use the 6 bits as an offset into the table, the high 3 bits are the - * number of the 8 bit register, while the low 3 bits are the bit within - * that register. - * - * This routine is based very heavily on the one provided by Peter Cammaert. - */ -static void -smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs) -{ - int i; - unsigned char multicast_table[8]; - struct dev_mc_list *cur_addr; - - /* table for flipping the order of 3 bits */ - static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - - /* start with a table of all zeros: reject all */ - memset(multicast_table, 0, sizeof(multicast_table)); - - cur_addr = addrs; - for (i = 0; i < count; i++, cur_addr = cur_addr->next) { - int position; - - /* do we have a pointer here? */ - if (!cur_addr) - break; - /* make sure this is a multicast address - shouldn't this - be a given if we have it here ? */ - if (!(*cur_addr->dmi_addr & 1)) - continue; - - /* only use the low order bits */ - position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; - - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert3[position&7]] |= - (1<>3)&7]); - - } - /* now, the table can be loaded into the chipset */ - SMC_SELECT_BANK(3); - SMC_SET_MCAST(multicast_table); -} - /* * This routine will, depending on the values passed to it, * either make it accept multicast packets, go into @@ -1363,14 +1382,14 @@ static void smc_set_multicast_list(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; + unsigned char multicast_table[8]; + int update_multicast = 0; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); - SMC_SELECT_BANK(0); if (dev->flags & IFF_PROMISC) { DBG(2, "%s: RCR_PRMS\n", dev->name); lp->rcr_cur_mode |= RCR_PRMS; - SMC_SET_RCR(lp->rcr_cur_mode); } /* BUG? I never disable promiscuous mode if multicasting was turned on. @@ -1384,38 +1403,78 @@ static void smc_set_multicast_list(struct net_device *dev) * checked before the table is */ else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { - lp->rcr_cur_mode |= RCR_ALMUL; - SMC_SET_RCR(lp->rcr_cur_mode); DBG(2, "%s: RCR_ALMUL\n", dev->name); + lp->rcr_cur_mode |= RCR_ALMUL; } /* - * We just get all multicast packets even if we only want them - * from one source. This will be changed at some future point. + * This sets the internal hardware table to filter out unwanted + * multicast packets before they take up memory. + * + * The SMC chip uses a hash table where the high 6 bits of the CRC of + * address are the offset into the table. If that bit is 1, then the + * multicast packet is accepted. Otherwise, it's dropped silently. + * + * To use the 6 bits as an offset into the table, the high 3 bits are + * the number of the 8 bit register, while the low 3 bits are the bit + * within that register. */ else if (dev->mc_count) { - /* support hardware multicasting */ + int i; + struct dev_mc_list *cur_addr; + + /* table for flipping the order of 3 bits */ + static const unsigned char invert3[] = {0, 4, 2, 6, 1, 5, 3, 7}; + + /* start with a table of all zeros: reject all */ + memset(multicast_table, 0, sizeof(multicast_table)); + + cur_addr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + int position; + + /* do we have a pointer here? */ + if (!cur_addr) + break; + /* make sure this is a multicast address - + shouldn't this be a given if we have it here ? */ + if (!(*cur_addr->dmi_addr & 1)) + continue; + + /* only use the low order bits */ + position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert3[position&7]] |= + (1<>3)&7]); + } /* be sure I get rid of flags I might have set */ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); - SMC_SET_RCR(lp->rcr_cur_mode); - /* - * NOTE: this has to set the bank, so make sure it is the - * last thing called. The bank is set to zero at the top - */ - smc_setmulticast(ioaddr, dev->mc_count, dev->mc_list); + + /* now, the table can be loaded into the chipset */ + update_multicast = 1; } else { DBG(2, "%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name); lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); - SMC_SET_RCR(lp->rcr_cur_mode); /* * since I'm disabling all multicast entirely, I need to * clear the multicast list */ + memset(multicast_table, 0, sizeof(multicast_table)); + update_multicast = 1; + } + + spin_lock_irq(&lp->lock); + SMC_SELECT_BANK(0); + SMC_SET_RCR(lp->rcr_cur_mode); + if (update_multicast) { SMC_SELECT_BANK(3); - SMC_CLEAR_MCAST(); + SMC_SET_MCAST(multicast_table); } + SMC_SELECT_BANK(2); + spin_unlock_irq(&lp->lock); } @@ -1428,7 +1487,6 @@ static int smc_open(struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; DBG(2, "%s: %s\n", dev->name, __FUNCTION__); @@ -1438,13 +1496,10 @@ smc_open(struct net_device *dev) * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */ if (!is_valid_ether_addr(dev->dev_addr)) { - DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n")); + PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); return -EINVAL; } - /* clear out all the junk that was put here before... */ - lp->saved_skb = NULL; - /* Setup the default Register Modes */ lp->tcr_cur_mode = TCR_DEFAULT; lp->rcr_cur_mode = RCR_DEFAULT; @@ -1461,10 +1516,7 @@ smc_open(struct net_device *dev) smc_reset(dev); smc_enable(dev); - SMC_SELECT_BANK(1); - SMC_SET_MAC_ADDR(dev->dev_addr); - - /* Configure the PHY */ + /* Configure the PHY, initialize the link state */ if (lp->phy_type != 0) smc_phy_configure(dev); else { @@ -1473,12 +1525,6 @@ smc_open(struct net_device *dev) spin_unlock_irq(&lp->lock); } - /* - * make sure to initialize the link state with netif_carrier_off() - * somewhere, too --jgarzik - * - * smc_phy_configure() and smc_10bt_check_media() does that. --rmk - */ netif_start_queue(dev); return 0; } @@ -1500,10 +1546,28 @@ static int smc_close(struct net_device *dev) netif_carrier_off(dev); /* clear everything */ - smc_shutdown(dev->base_addr); + smc_shutdown(dev); - if (lp->phy_type != 0) + if (lp->phy_type != 0) { + /* We need to ensure that no calls to + smc_phy_configure are pending. + + flush_scheduled_work() cannot be called because we + are running with the netlink semaphore held (from + devinet_ioctl()) and the pending work queue + contains linkwatch_event() (scheduled by + netif_carrier_off() above). linkwatch_event() also + wants the netlink semaphore. + */ + while(lp->work_pending) + schedule(); smc_phy_powerdown(dev, lp->mii.phy_id); + } + + if (lp->pending_tx_skb) { + dev_kfree_skb(lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + } return 0; } @@ -1793,6 +1857,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) /* fill in some of the fields */ dev->base_addr = ioaddr; lp->version = revision_register & 0xff; + spin_lock_init(&lp->lock); /* Get the MAC address */ SMC_SELECT_BANK(1); @@ -1848,7 +1913,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) dev->set_multicast_list = smc_set_multicast_list; dev->ethtool_ops = &smc_ethtool_ops; - spin_lock_init(&lp->lock); + tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev); + INIT_WORK(&lp->phy_configure, smc_phy_configure, dev); lp->mii.phy_id_mask = 0x1f; lp->mii.reg_num_mask = 0x1f; lp->mii.force_media = 0; @@ -1861,7 +1927,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) * Locate the phy, if any. */ if (lp->version >= (CHIP_91100 << 4)) - smc_detect_phy(dev); + smc_phy_detect(dev); /* Set default parameters */ lp->msg_enable = NETIF_MSG_LINK; @@ -1879,6 +1945,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) goto err_out; set_irq_type(dev->irq, IRQT_RISING); + #ifdef SMC_USE_PXA_DMA { int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, @@ -2112,7 +2179,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level) if (ndev && level == SUSPEND_DISABLE) { if (netif_running(ndev)) { netif_device_detach(ndev); - smc_shutdown(ndev->base_addr); + smc_shutdown(ndev); } } return 0; @@ -2125,15 +2192,12 @@ static int smc_drv_resume(struct device *dev, u32 level) if (ndev && level == RESUME_ENABLE) { struct smc_local *lp = netdev_priv(ndev); - unsigned long ioaddr = ndev->base_addr; if (pdev->num_resources == 3) smc_enable_device(pdev->resource[2].start); if (netif_running(ndev)) { smc_reset(ndev); smc_enable(ndev); - SMC_SELECT_BANK(1); - SMC_SET_MAC_ADDR(ndev->dev_addr); if (lp->phy_type != 0) smc_phy_configure(ndev); netif_device_attach(ndev); @@ -2154,10 +2218,12 @@ static struct device_driver smc_driver = { static int __init smc_init(void) { #ifdef MODULE +#ifdef CONFIG_ISA if (io == -1) printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", CARDNAME); +#endif #endif return driver_register(&smc_driver); diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 7679022c0..fad8c0437 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -39,11 +39,7 @@ * Define your architecture specific bus configuration parameters here. */ -#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \ - defined(CONFIG_SA1100_PFS168) || \ - defined(CONFIG_SA1100_FLEXANET) || \ - defined(CONFIG_SA1100_GRAPHICSMASTER) || \ - defined(CONFIG_ARCH_LUBBOCK) +#if defined(CONFIG_ARCH_LUBBOCK) /* We can only do 16-bit reads and writes in the static memory space. */ #define SMC_CAN_USE_8BIT 0 @@ -96,6 +92,25 @@ } while (0) #define set_irq_type(irq, type) +#elif defined(CONFIG_SA1100_PLEB) +/* We can only do 16-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) inb((a) + (r)) +#define SMC_insb(a, r, p, l) insb((a) + (r), p, (l)) +#define SMC_inw(a, r) inw((a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outb(v, a, r) outb(v, (a) + (r)) +#define SMC_outsb(a, r, p, l) outsb((a) + (r), p, (l)) +#define SMC_outw(v, a, r) outw(v, (a) + (r)) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) + +#define set_irq_type(irq, type) do {} while (0) + #elif defined(CONFIG_SA1100_ASSABET) #include @@ -160,6 +175,71 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg) #define SMC_insw(a, r, p, l) insw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) +#elif defined(CONFIG_M32R) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 + +#define SMC_inb(a, r) inb((a) + (r) - 0xa0000000) +#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000) +#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000) +#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000) +#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) + +#define set_irq_type(irq, type) do {} while(0) + +#define RPC_LSA_DEFAULT RPC_LED_TX_RX +#define RPC_LSB_DEFAULT RPC_LED_100_10 + +#elif defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404) + +/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between + * the way that the CPU handles chip selects and the way that the SMC + * chip expects the chip select to operate. Refer to + * Documentation/arm/Sharp-LH/IOBarrier for details. The read from + * IOBARRIER is a byte as a least-common denominator of possible + * regions to use as the barrier. It would be wasteful to read 32 + * bits from a byte oriented region. + * + * There is no explicit protection against interrupts intervening + * between the writew and the IOBARRIER. In SMC ISR there is a + * preamble that performs an IOBARRIER in the extremely unlikely event + * that the driver interrupts itself between a writew to the chip an + * the IOBARRIER that follows *and* the cache is large enough that the + * first off-chip access while handing the interrupt is to the SMC + * chip. Other devices in the same address space as the SMC chip must + * be aware of the potential for trouble and perform a similar + * IOBARRIER on entry to their ISR. + */ + +#include /* IOBARRIER_VIRT */ + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 0 +#define LPD7A40X_IOBARRIER readb (IOBARRIER_VIRT) + +#define SMC_inw(a,r) readw ((void*) ((a) + (r))) +#define SMC_insw(a,r,p,l) readsw ((void*) ((a) + (r)), p, l) +#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; }) + +static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) +{ + unsigned short* ps = (unsigned short*) p; + while (l-- > 0) { + writew (*ps++, a + r); + LPD7A40X_IOBARRIER; + } +} + +#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER + +#define RPC_LSA_DEFAULT RPC_LED_TX_RX +#define RPC_LSB_DEFAULT RPC_LED_100_10 + #else #define SMC_CAN_USE_8BIT 1 @@ -189,8 +269,9 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg) * different and probably not worth it for that reason, and not as critical * as RX which can overrun memory and lose packets. */ -#include +#include #include +#include #ifdef SMC_insl #undef SMC_insl @@ -210,21 +291,23 @@ smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma, /* 64 bit alignment is required for memory to memory DMA */ if ((long)buf & 4) { - *((u32 *)buf)++ = SMC_inl(ioaddr, reg); + *((u32 *)buf) = SMC_inl(ioaddr, reg); + buf += 4; len--; } len *= 4; - dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE); DCSR(dma) = DCSR_NODESC; DTADR(dma) = dmabuf; DSADR(dma) = physaddr + reg; DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | DCMD_WIDTH4 | (DCMD_LENGTH & len)); DCSR(dma) = DCSR_NODESC | DCSR_RUN; - while (!(DCSR(dma) & DCSR_STOPSTATE)); + while (!(DCSR(dma) & DCSR_STOPSTATE)) + cpu_relax(); DCSR(dma) = 0; - dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); + dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE); } #endif @@ -246,21 +329,23 @@ smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma, /* 64 bit alignment is required for memory to memory DMA */ while ((long)buf & 6) { - *((u16 *)buf)++ = SMC_inw(ioaddr, reg); + *((u16 *)buf) = SMC_inw(ioaddr, reg); + buf += 2; len--; } len *= 2; - dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE); DCSR(dma) = DCSR_NODESC; DTADR(dma) = dmabuf; DSADR(dma) = physaddr + reg; DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | DCMD_WIDTH2 | (DCMD_LENGTH & len)); DCSR(dma) = DCSR_NODESC | DCSR_RUN; - while (!(DCSR(dma) & DCSR_STOPSTATE)); + while (!(DCSR(dma) & DCSR_STOPSTATE)) + cpu_relax(); DCSR(dma) = 0; - dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); + dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE); } #endif @@ -749,16 +834,9 @@ static const char * chip_ids[ 16 ] = { SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \ } while (0) -#define SMC_CLEAR_MCAST() \ - do { \ - SMC_outw( 0, ioaddr, MCAST_REG1 ); \ - SMC_outw( 0, ioaddr, MCAST_REG2 ); \ - SMC_outw( 0, ioaddr, MCAST_REG3 ); \ - SMC_outw( 0, ioaddr, MCAST_REG4 ); \ - } while (0) #define SMC_SET_MCAST(x) \ do { \ - unsigned char *mt = (x); \ + const unsigned char *mt = (x); \ SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \ SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \ SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \ @@ -809,9 +887,10 @@ static const char * chip_ids[ 16 ] = { do { \ char *__ptr = (p); \ int __len = (l); \ - if (__len >= 2 && (long)__ptr & 2) { \ + if (__len >= 2 && (unsigned long)__ptr & 2) { \ __len -= 2; \ - SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\ + SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG ); \ + __ptr += 2; \ } \ SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \ if (__len & 2) { \ @@ -823,7 +902,7 @@ static const char * chip_ids[ 16 ] = { do { \ char *__ptr = (p); \ int __len = (l); \ - if ((long)__ptr & 2) { \ + if ((unsigned long)__ptr & 2) { \ /* \ * We want 32bit alignment here. \ * Since some buses perform a full 32bit \ @@ -831,7 +910,7 @@ static const char * chip_ids[ 16 ] = { * SMC_inw() here. Back both source (on chip \ * and destination) pointers of 2 bytes. \ */ \ - (long)__ptr &= ~2; \ + __ptr -= 2; \ __len += 2; \ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ } \ @@ -862,5 +941,8 @@ static const char * chip_ids[ 16 ] = { }) #endif +#if !defined (SMC_INTERRUPT_PREAMBLE) +# define SMC_INTERRUPT_PREAMBLE +#endif #endif /* _SMC91X_H_ */ diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 793201d3f..f87ff13f6 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -312,9 +312,6 @@ static int full_duplex[MAX_UNITS] = {0, }; #include -#define COMPAT_MOD_INC_USE_COUNT -#define COMPAT_MOD_DEC_USE_COUNT - #define init_tx_timer(dev, func, timeout) \ dev->tx_timeout = func; \ dev->watchdog_timeo = timeout; @@ -799,12 +796,13 @@ static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); static void netdev_media_change(struct net_device *dev); +static struct ethtool_ops ethtool_ops; #ifdef VLAN_SUPPORT static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 2) @@ -816,7 +814,7 @@ static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *g static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) @@ -827,7 +825,7 @@ static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) @@ -951,7 +949,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); spin_lock_init(&np->lock); pci_set_drvdata(pdev, dev); @@ -1015,6 +1013,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev, dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); if (mtu) dev->mtu = mtu; @@ -1102,20 +1101,15 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i, retval; size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; /* Do we ever need to reset the chip??? */ - - COMPAT_MOD_INC_USE_COUNT; - retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); - if (retval) { - COMPAT_MOD_DEC_USE_COUNT; + if (retval) return retval; - } /* Disable the Rx and Tx, and reset the chip. */ writel(0, ioaddr + GenCtrl); @@ -1132,10 +1126,8 @@ static int netdev_open(struct net_device *dev) rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE; np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size; np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma); - if (np->queue_mem == 0) { - COMPAT_MOD_DEC_USE_COUNT; + if (np->queue_mem == 0) return -ENOMEM; - } np->tx_done_q = np->queue_mem; np->tx_done_q_dma = np->queue_mem_dma; @@ -1267,7 +1259,7 @@ static int netdev_open(struct net_device *dev) static void check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 reg0; int silly_count = 1000; @@ -1302,7 +1294,7 @@ static void check_duplex(struct net_device *dev) static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int old_debug; @@ -1332,7 +1324,7 @@ static void tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = np->reap_tx = 0; @@ -1378,7 +1370,7 @@ static void init_ring(struct net_device *dev) static int start_tx(struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned int entry; u32 status; int i; @@ -1497,7 +1489,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); do { u32 intr_status = readl(ioaddr + IntrClear); @@ -1597,7 +1589,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */ static int __netdev_rx(struct net_device *dev, int *quota) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u32 desc_status; int retcode = 0; @@ -1752,7 +1744,7 @@ static int netdev_poll(struct net_device *dev, int *budget) static void refill_rx_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int entry = -1; @@ -1780,7 +1772,7 @@ static void refill_rx_ring(struct net_device *dev) static void netdev_media_change(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; u16 reg0, reg1, reg4, reg5; u32 new_tx_mode; @@ -1855,7 +1847,7 @@ static void netdev_media_change(struct net_device *dev) static void netdev_error(struct net_device *dev, int intr_status) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); /* Came close to underrunning the Tx FIFO, increase threshold. */ if (intr_status & IntrTxDataLow) { @@ -1883,7 +1875,7 @@ static void netdev_error(struct net_device *dev, int intr_status) static struct net_device_stats *get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); /* This adapter architecture needs no SMP locks. */ np->stats.tx_bytes = readl(ioaddr + 0x57010); @@ -1917,7 +1909,7 @@ static void set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; int i; #ifdef VLAN_SUPPORT - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); rx_mode |= VlanMode; if (np->vlgrp) { @@ -1996,106 +1988,89 @@ static void set_rx_mode(struct net_device *dev) writel(rx_mode, ioaddr + RxFilterMode); } +static int check_if_running(struct net_device *dev) +{ + if (!netif_running(dev)) + return -EINVAL; + return 0; +} -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct ethtool_cmd ecmd; - struct netdev_private *np = dev->priv; - - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info; - memset(&info, 0, sizeof(info)); - info.cmd = ecmd.cmd; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - *info.fw_version = 0; - strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev)); +} - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - check_duplex(dev); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + 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; - } - default: - return -EOPNOTSUPP; - } +static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + check_duplex(dev); + return res; } +static int nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} + +static u32 get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} + +static u32 get_msglevel(struct net_device *dev) +{ + return debug; +} + +static void set_msglevel(struct net_device *dev, u32 val) +{ + debug = val; +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = get_drvinfo, + .get_settings = get_settings, + .set_settings = set_settings, + .nway_reset = nway_reset, + .get_link = get_link, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, +}; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + struct mii_ioctl_data *data = if_mii(rq); int rc; if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else { - struct mii_ioctl_data *data = if_mii(rq); - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL); - spin_unlock_irq(&np->lock); + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL); + spin_unlock_irq(&np->lock); - if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0])) - check_duplex(dev); - } + if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0])) + check_duplex(dev); return rc; } @@ -2103,7 +2078,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int netdev_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; netif_stop_queue(dev); @@ -2165,8 +2140,6 @@ static int netdev_close(struct net_device *dev) np->tx_info[i].skb = NULL; } - COMPAT_MOD_DEC_USE_COUNT; - return 0; } @@ -2174,16 +2147,16 @@ static int netdev_close(struct net_device *dev) static void __devexit starfire_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct netdev_private *np; + struct netdev_private *np = netdev_priv(dev); if (!dev) BUG(); - np = dev->priv; + unregister_netdev(dev); + if (np->queue_mem) pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma); - unregister_netdev(dev); /* XXX: add wakeup code -- requires firmware for MagicPacket */ pci_set_power_state(pdev, 3); /* go to sleep in D3 mode */ diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index 053fcaf1c..d5a58fb30 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -39,7 +39,7 @@ static int fifo=0x8; /* don't change */ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 6faef842d..1f43bbfbc 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -36,10 +36,10 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index ec05d1bd1..025dcd867 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -68,7 +68,7 @@ static struct bigmac *root_bigmac_dev; #define QEC_RESET_TRIES 200 -static int qec_global_reset(unsigned long gregs) +static int qec_global_reset(void __iomem *gregs) { int tries = QEC_RESET_TRIES; @@ -88,7 +88,7 @@ static int qec_global_reset(unsigned long gregs) static void qec_init(struct bigmac *bp) { - unsigned long gregs = bp->gregs; + void __iomem *gregs = bp->gregs; struct sbus_dev *qec_sdev = bp->qec_sdev; u8 bsizes = bp->bigmac_bursts; u32 regval; @@ -117,7 +117,7 @@ static void qec_init(struct bigmac *bp) #define TX_RESET_TRIES 32 #define RX_RESET_TRIES 32 -static void bigmac_tx_reset(unsigned long bregs) +static void bigmac_tx_reset(void __iomem *bregs) { int tries = TX_RESET_TRIES; @@ -137,7 +137,7 @@ static void bigmac_tx_reset(unsigned long bregs) } } -static void bigmac_rx_reset(unsigned long bregs) +static void bigmac_rx_reset(void __iomem *bregs) { int tries = RX_RESET_TRIES; @@ -159,7 +159,7 @@ static void bigmac_stop(struct bigmac *bp) bigmac_rx_reset(bp->bregs); } -static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs) +static void bigmac_get_counters(struct bigmac *bp, void __iomem *bregs) { struct net_device_stats *stats = &bp->enet_stats; @@ -244,7 +244,7 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq) #define MGMT_CLKON (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK) #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB) -static void idle_transceiver(unsigned long tregs) +static void idle_transceiver(void __iomem *tregs) { int i = 20; @@ -256,7 +256,7 @@ static void idle_transceiver(unsigned long tregs) } } -static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit) +static void write_tcvr_bit(struct bigmac *bp, void __iomem *tregs, int bit) { if (bp->tcvr_type == internal) { bit = (bit & 1) << 3; @@ -279,7 +279,7 @@ static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit) } } -static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs) +static int read_tcvr_bit(struct bigmac *bp, void __iomem *tregs) { int retval = 0; @@ -302,7 +302,7 @@ static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs) return retval; } -static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs) +static int read_tcvr_bit2(struct bigmac *bp, void __iomem *tregs) { int retval = 0; @@ -325,7 +325,7 @@ static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs) } static void put_tcvr_byte(struct bigmac *bp, - unsigned long tregs, + void __iomem *tregs, unsigned int byte) { int shift = 4; @@ -336,7 +336,7 @@ static void put_tcvr_byte(struct bigmac *bp, } while (shift >= 0); } -static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs, +static void bigmac_tcvr_write(struct bigmac *bp, void __iomem *tregs, int reg, unsigned short val) { int shift; @@ -376,7 +376,7 @@ static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs, } static unsigned short bigmac_tcvr_read(struct bigmac *bp, - unsigned long tregs, + void __iomem *tregs, int reg) { unsigned short retval = 0; @@ -444,7 +444,7 @@ static unsigned short bigmac_tcvr_read(struct bigmac *bp, static void bigmac_tcvr_init(struct bigmac *bp) { - unsigned long tregs = bp->tregs; + void __iomem *tregs = bp->tregs; u32 mpal; idle_transceiver(tregs); @@ -482,7 +482,7 @@ static void bigmac_tcvr_init(struct bigmac *bp) static int bigmac_init(struct bigmac *, int); -static int try_next_permutation(struct bigmac *bp, unsigned long tregs) +static int try_next_permutation(struct bigmac *bp, void __iomem *tregs) { if (bp->sw_bmcr & BMCR_SPEED100) { int timeout; @@ -518,7 +518,7 @@ static int try_next_permutation(struct bigmac *bp, unsigned long tregs) static void bigmac_timer(unsigned long data) { struct bigmac *bp = (struct bigmac *) data; - unsigned long tregs = bp->tregs; + void __iomem *tregs = bp->tregs; int restart_timer = 0; bp->timer_ticks++; @@ -573,7 +573,7 @@ static void bigmac_timer(unsigned long data) */ static void bigmac_begin_auto_negotiation(struct bigmac *bp) { - unsigned long tregs = bp->tregs; + void __iomem *tregs = bp->tregs; int timeout; /* Grab new software copies of PHY registers. */ @@ -612,9 +612,9 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp) static int bigmac_init(struct bigmac *bp, int from_irq) { - unsigned long gregs = bp->gregs; - unsigned long cregs = bp->creg; - unsigned long bregs = bp->bregs; + void __iomem *gregs = bp->gregs; + void __iomem *cregs = bp->creg; + void __iomem *bregs = bp->bregs; unsigned char *e = &bp->dev->dev_addr[0]; /* Latch current counters into statistics. */ @@ -987,7 +987,7 @@ static struct net_device_stats *bigmac_get_stats(struct net_device *dev) static void bigmac_set_multicast(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; - unsigned long bregs = bp->bregs; + void __iomem *bregs = bp->bregs; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i; diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index b4c5309b3..5674003fc 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h @@ -303,10 +303,10 @@ enum bigmac_timer_state { }; struct bigmac { - unsigned long gregs; /* QEC Global Registers */ - unsigned long creg; /* QEC BigMAC Channel Registers */ - unsigned long bregs; /* BigMAC Registers */ - unsigned long tregs; /* BigMAC Transceiver */ + void __iomem *gregs; /* QEC Global Registers */ + void __iomem *creg; /* QEC BigMAC Channel Registers */ + void __iomem *bregs; /* BigMAC Registers */ + void __iomem *tregs; /* BigMAC Transceiver */ struct bmac_init_block *bmac_block; /* RX and TX descriptors */ __u32 bblock_dvma; /* RX and TX descriptors */ diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 849b57634..5ade45535 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -162,9 +162,9 @@ static char *media[MAX_UNITS]; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -511,8 +511,7 @@ static int __set_mac_addr(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); - - +static struct ethtool_ops ethtool_ops; static int __devinit sundance_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -567,7 +566,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->pci_dev = pdev; np->chip_id = chip_idx; np->msg_enable = (1 << debug) - 1; @@ -600,6 +599,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; @@ -787,7 +787,7 @@ static void mdio_sync(long mdio_addr) static int mdio_read(struct net_device *dev, int phy_id, int location) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long mdio_addr = dev->base_addr + MIICtrl; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i, retval = 0; @@ -817,7 +817,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) static void mdio_write(struct net_device *dev, int phy_id, int location, int value) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long mdio_addr = dev->base_addr + MIICtrl; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; int i; @@ -846,7 +846,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -879,7 +879,7 @@ static int netdev_open(struct net_device *dev) if (dev->if_port == 0) dev->if_port = np->default_port; - np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED; + spin_lock_init(&np->mcastlock); set_rx_mode(dev); writew(0, ioaddr + IntrEnable); @@ -916,7 +916,7 @@ static int netdev_open(struct net_device *dev) static void check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); int negotiated = mii_lpa & np->mii_if.advertising; @@ -945,7 +945,7 @@ static void check_duplex(struct net_device *dev) static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 10*HZ; @@ -962,7 +962,7 @@ static void netdev_timer(unsigned long data) static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; unsigned long flag; @@ -1015,7 +1015,7 @@ static void tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -1058,7 +1058,7 @@ static void init_ring(struct net_device *dev) static void tx_poll (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned head = np->cur_task % TX_RING_SIZE; struct netdev_desc *txdesc = &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE]; @@ -1085,7 +1085,7 @@ static void tx_poll (unsigned long data) static int start_tx (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; @@ -1127,7 +1127,7 @@ start_tx (struct sk_buff *skb, struct net_device *dev) static int reset_tx (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; struct sk_buff *skb; int i; @@ -1176,7 +1176,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); do { int intr_status = readw(ioaddr + IntrStatus); @@ -1301,7 +1301,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs static void rx_poll(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int boguscnt = np->budget; long ioaddr = dev->base_addr; @@ -1398,7 +1398,7 @@ not_done: static void refill_rx (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry; int cnt = 0; @@ -1429,7 +1429,7 @@ static void refill_rx (struct net_device *dev) static void netdev_error(struct net_device *dev, int intr_status) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 mii_ctl, mii_advertise, mii_lpa; int speed; @@ -1483,7 +1483,7 @@ static void netdev_error(struct net_device *dev, int intr_status) static struct net_device_stats *get_stats(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -1512,7 +1512,7 @@ static struct net_device_stats *get_stats(struct net_device *dev) static void set_rx_mode(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 mc_filter[4]; /* Multicast hash filter */ u32 rx_mode; int i; @@ -1565,91 +1565,79 @@ static int __set_mac_addr(struct net_device *dev) writew(addr16, dev->base_addr + StationAddr+4); return 0; } - -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - struct netdev_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - /* get constant driver settings/info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } + if (!netif_running(dev)) + return -EINVAL; + return 0; +} - /* get media settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set media settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii_if); - } +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return res; +} - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = np->msg_enable; - 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; - np->msg_enable = edata.data; - return 0; - } +static int nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} - default: - return -EOPNOTSUPP; +static u32 get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} - } +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; +} + +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; } +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = get_drvinfo, + .get_settings = get_settings, + .set_settings = set_settings, + .nway_reset = nway_reset, + .get_link = get_link, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int rc; int i; long ioaddr = dev->base_addr; @@ -1657,14 +1645,9 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else { - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - } + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); + spin_unlock_irq(&np->lock); switch (cmd) { case SIOCDEVPRIVATE: for (i=0; ibase_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1775,7 +1758,7 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev(dev); pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index e48ec3421..38e94961e 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -5,6 +5,9 @@ * * Support for Apple GMAC and assorted PHYs by * Benjamin Herrenscmidt (benh@kernel.crashing.org) + * + * NAPI and NETPOLL support + * (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com) * * TODO: * - Get rid of all those nasty mdelay's and replace them @@ -34,9 +37,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -181,6 +184,18 @@ static inline void phy_write(struct gem *gp, int reg, u16 val) __phy_write(gp, gp->mii_phy_addr, reg, val); } +static inline void gem_enable_ints(struct gem *gp) +{ + /* Enable all interrupts but TXDONE */ + writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK); +} + +static inline void gem_disable_ints(struct gem *gp) +{ + /* Disable all interrupts, including TXDONE */ + writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK); +} + static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits) { if (netif_msg_intr(gp)) @@ -678,12 +693,12 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit) } } -static void gem_rx(struct gem *gp) +static int gem_rx(struct gem *gp, int work_to_do) { - int entry, drops; + int entry, drops, work_done = 0; u32 done; - if (netif_msg_intr(gp)) + if (netif_msg_rx_status(gp)) printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", gp->dev->name, readl(gp->regs + RXDMA_DONE), gp->rx_new); @@ -700,6 +715,9 @@ static void gem_rx(struct gem *gp) if ((status & RXDCTRL_OWN) != 0) break; + if (work_done >= RX_RING_SIZE || work_done >= work_to_do) + break; + /* When writing back RX descriptor, GEM writes status * then buffer address, possibly in seperate transactions. * If we don't wait for the chip to write both, we could @@ -713,6 +731,9 @@ static void gem_rx(struct gem *gp) break; } + /* We can now account for the work we're about to do */ + work_done++; + skb = gp->rx_skbs[entry]; len = (status & RXDCTRL_BUFSZ) >> 16; @@ -775,7 +796,8 @@ static void gem_rx(struct gem *gp) skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff); skb->ip_summed = CHECKSUM_HW; skb->protocol = eth_type_trans(skb, gp->dev); - netif_rx(skb); + + netif_receive_skb(skb); gp->net_stats.rx_packets++; gp->net_stats.rx_bytes += len; @@ -792,35 +814,103 @@ static void gem_rx(struct gem *gp) if (drops) printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", gp->dev->name); + + return work_done; +} + +static int gem_poll(struct net_device *dev, int *budget) +{ + struct gem *gp = dev->priv; + unsigned long flags; + + spin_lock_irqsave(&gp->lock, flags); + + do { + int work_to_do, work_done; + + /* Handle anomalies */ + if (gp->status & GREG_STAT_ABNORMAL) { + if (gem_abnormal_irq(dev, gp, gp->status)) + break; + } + + /* Run TX completion thread */ + spin_lock(&gp->tx_lock); + gem_tx(dev, gp, gp->status); + spin_unlock(&gp->tx_lock); + + spin_unlock_irqrestore(&gp->lock, flags); + + /* Run RX thread. We don't use any locking here, + * code willing to do bad things - like cleaning the + * rx ring - must call netif_poll_disable(), which + * schedule_timeout()'s if polling is already disabled. + */ + work_to_do = min(*budget, dev->quota); + + work_done = gem_rx(gp, work_to_do); + + *budget -= work_done; + dev->quota -= work_done; + + if (work_done >= work_to_do) + return 1; + + spin_lock_irqsave(&gp->lock, flags); + + gp->status = readl(gp->regs + GREG_STAT); + } while (gp->status & GREG_STAT_NAPI); + + __netif_rx_complete(dev); + gem_enable_ints(gp); + + spin_unlock_irqrestore(&gp->lock, flags); + return 0; } static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct gem *gp = dev->priv; - u32 gem_status = readl(gp->regs + GREG_STAT); + unsigned long flags; /* Swallow interrupts when shutting the chip down */ - if (gp->hw_running == 0) - goto out; + if (!gp->hw_running) + return IRQ_HANDLED; - spin_lock(&gp->lock); + spin_lock_irqsave(&gp->lock, flags); + + if (netif_rx_schedule_prep(dev)) { + u32 gem_status = readl(gp->regs + GREG_STAT); - if (gem_status & GREG_STAT_ABNORMAL) { - if (gem_abnormal_irq(dev, gp, gem_status)) - goto out; + if (gem_status == 0) { + spin_unlock_irqrestore(&gp->lock, flags); + return IRQ_NONE; + } + gp->status = gem_status; + gem_disable_ints(gp); + __netif_rx_schedule(dev); } - if (gem_status & (GREG_STAT_TXALL | GREG_STAT_TXINTME)) - gem_tx(dev, gp, gem_status); - if (gem_status & GREG_STAT_RXDONE) - gem_rx(gp); - -out: - spin_unlock(&gp->lock); + spin_unlock_irqrestore(&gp->lock, flags); + + /* If polling was disabled at the time we received that + * interrupt, we may return IRQ_HANDLED here while we + * should return IRQ_NONE. No big deal... + */ return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void gem_poll_controller(struct net_device *dev) +{ + /* gem_interrupt is safe to reentrance so no need + * to disable_irq here. + */ + gem_interrupt(dev->irq, dev, NULL); +} +#endif + static void gem_tx_timeout(struct net_device *dev) { struct gem *gp = dev->priv; @@ -842,10 +932,12 @@ static void gem_tx_timeout(struct net_device *dev) readl(gp->regs + MAC_RXCFG)); spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gp->reset_task_pending = 2; schedule_work(&gp->reset_task); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); } @@ -863,6 +955,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) struct gem *gp = dev->priv; int entry; u64 ctrl; + unsigned long flags; ctrl = 0; if (skb->ip_summed == CHECKSUM_HW) { @@ -876,15 +969,20 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) (csum_stuff_off << 21)); } - spin_lock_irq(&gp->lock); + local_irq_save(flags); + if (!spin_trylock(&gp->tx_lock)) { + /* Tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } /* This is a hard error, log it. */ if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); - spin_unlock_irq(&gp->lock); + spin_unlock_irqrestore(&gp->tx_lock, flags); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } entry = gp->tx_new; @@ -968,11 +1066,11 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->name, entry, skb->len); mb(); writel(gp->tx_new, gp->regs + TXDMA_KICK); - spin_unlock_irq(&gp->lock); + spin_unlock_irqrestore(&gp->tx_lock, flags); dev->trans_start = jiffies; - return 0; + return NETDEV_TX_OK; } /* Jumbo-grams don't seem to work :-( */ @@ -999,9 +1097,11 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu) } spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); dev->mtu = new_mtu; gp->reset_task_pending = 1; schedule_work(&gp->reset_task); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); flush_scheduled_work(); @@ -1011,7 +1111,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu) #define STOP_TRIES 32 -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_stop(struct gem *gp) { int limit; @@ -1037,7 +1137,7 @@ static void gem_stop(struct gem *gp) printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_start_dma(struct gem *gp) { unsigned long val; @@ -1062,7 +1162,7 @@ static void gem_start_dma(struct gem *gp) } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ // XXX dbl check what that function should do when called on PCS PHY static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep) { @@ -1149,7 +1249,7 @@ non_mii: /* A link-up condition has occurred, initialize and enable the * rest of the chip. * - * Must be invoked under gp->lock. + * Must be invoked under gp->lock and gp->tx_lock. */ static int gem_set_link_modes(struct gem *gp) { @@ -1256,7 +1356,7 @@ static int gem_set_link_modes(struct gem *gp) return 0; } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static int gem_mdio_link_not_up(struct gem *gp) { switch (gp->lstate) { @@ -1312,19 +1412,13 @@ static void gem_reset_task(void *data) { struct gem *gp = (struct gem *) data; - /* The link went down, we reset the ring, but keep - * DMA stopped. Todo: Use this function for reset - * on error as well. - */ - + netif_poll_disable(gp->dev); spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); if (gp->hw_running && gp->opened) { - /* Make sure we don't get interrupts or tx packets */ netif_stop_queue(gp->dev); - writel(0xffffffff, gp->regs + GREG_IMASK); - /* Reset the chip & rings */ gem_stop(gp); gem_init_rings(gp); @@ -1336,7 +1430,9 @@ static void gem_reset_task(void *data) } gp->reset_task_pending = 0; + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); + netif_poll_enable(gp->dev); } static void gem_link_timer(unsigned long data) @@ -1348,6 +1444,7 @@ static void gem_link_timer(unsigned long data) return; spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); /* If the link of task is still pending, we just * reschedule the link timer @@ -1417,10 +1514,11 @@ static void gem_link_timer(unsigned long data) restart: mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10)); out_unlock: + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_clean_rings(struct gem *gp) { struct gem_init_block *gb = gp->init_block; @@ -1471,7 +1569,7 @@ static void gem_clean_rings(struct gem *gp) } } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_rings(struct gem *gp) { struct gem_init_block *gb = gp->init_block; @@ -1521,7 +1619,7 @@ static void gem_init_rings(struct gem *gp) wmb(); } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_phy(struct gem *gp) { u32 mifcfg; @@ -1659,7 +1757,7 @@ static void gem_init_phy(struct gem *gp) } } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_dma(struct gem *gp) { u64 desc_dma = (u64) gp->gblock_dvma; @@ -1697,7 +1795,7 @@ static void gem_init_dma(struct gem *gp) gp->regs + RXDMA_BLANK); } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static u32 gem_setup_multicast(struct gem *gp) { @@ -1740,7 +1838,7 @@ gem_setup_multicast(struct gem *gp) return rxcfg; } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_mac(struct gem *gp) { unsigned char *e = &gp->dev->dev_addr[0]; @@ -1818,7 +1916,7 @@ static void gem_init_mac(struct gem *gp) writel(0xffffffff, gp->regs + MAC_MCMASK); } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_pause_thresholds(struct gem *gp) { u32 cfg; @@ -1954,7 +2052,7 @@ static int gem_check_invariants(struct gem *gp) return 0; } -/* Must be invoked under gp->lock. */ +/* Must be invoked under gp->lock and gp->tx_lock. */ static void gem_init_hw(struct gem *gp, int restart_link) { /* On Apple's gmac, I initialize the PHY only after @@ -2052,9 +2150,11 @@ static void gem_stop_phy(struct gem *gp) if (!gp->wake_on_lan) { spin_lock_irqsave(&gp->lock, flags); + spin_lock(&gp->tx_lock); gem_stop(gp); writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST); writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST); + spin_unlock(&gp->tx_lock); spin_unlock_irqrestore(&gp->lock, flags); } @@ -2102,8 +2202,10 @@ static void gem_shutdown(struct gem *gp) unsigned long flags; spin_lock_irqsave(&gp->lock, flags); + spin_lock(&gp->tx_lock); gem_stop(gp); - spin_unlock_irqrestore(&gp->lock, flags); + spin_unlock(&gp->tx_lock); + spin_unlock_irqrestore(&gp->lock, flags); } } @@ -2163,7 +2265,9 @@ static int gem_open(struct net_device *dev) /* Reset the chip */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gem_stop(gp); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); gp->hw_running = 1; @@ -2177,6 +2281,7 @@ static int gem_open(struct net_device *dev) printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name); spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); #ifdef CONFIG_PPC_PMAC if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE) gem_apple_powerdown(gp); @@ -2185,12 +2290,14 @@ static int gem_open(struct net_device *dev) gp->pm_timer.expires = jiffies + 10*HZ; add_timer(&gp->pm_timer); up(&gp->pm_sem); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); return -EAGAIN; } spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); /* Allocate & setup ring buffers */ gem_init_rings(gp); @@ -2200,6 +2307,7 @@ static int gem_open(struct net_device *dev) gp->opened = 1; + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); up(&gp->pm_sem); @@ -2214,11 +2322,16 @@ static int gem_close(struct net_device *dev) /* Make sure we don't get distracted by suspend/resume */ down(&gp->pm_sem); + /* Note: we don't need to call netif_poll_disable() here because + * our caller (dev_close) already did it for us + */ + /* Stop traffic, mark us closed */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gp->opened = 0; - writel(0xffffffff, gp->regs + GREG_IMASK); + netif_stop_queue(dev); /* Stop chip */ @@ -2230,6 +2343,7 @@ static int gem_close(struct net_device *dev) /* Bye, the pm timer will finish the job */ free_irq(gp->pdev->irq, (void *) dev); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); /* Fire the PM timer that will shut us down in about 10 seconds */ @@ -2247,6 +2361,8 @@ static int gem_suspend(struct pci_dev *pdev, u32 state) struct net_device *dev = pci_get_drvdata(pdev); struct gem *gp = dev->priv; + netif_poll_disable(dev); + /* We hold the PM semaphore during entire driver * sleep time */ @@ -2258,18 +2374,18 @@ static int gem_suspend(struct pci_dev *pdev, u32 state) /* If the driver is opened, we stop the DMA */ if (gp->opened) { spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); /* Stop traffic, mark us closed */ netif_device_detach(dev); - writel(0xffffffff, gp->regs + GREG_IMASK); - /* Stop chip */ gem_stop(gp); /* Get rid of ring buffers */ gem_clean_rings(gp); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) @@ -2303,12 +2419,14 @@ static int gem_resume(struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gem_stop(gp); gp->hw_running = 1; gem_init_rings(gp); gem_init_hw(gp, 1); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); netif_device_attach(dev); @@ -2317,6 +2435,8 @@ static int gem_resume(struct pci_dev *pdev) } up(&gp->pm_sem); + netif_poll_enable(dev); + return 0; } #endif /* CONFIG_PM */ @@ -2327,6 +2447,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev) struct net_device_stats *stats = &gp->net_stats; spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); if (gp->hw_running) { stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR); @@ -2346,6 +2467,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev) writel(0, gp->regs + MAC_LCOLL); } + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); return &gp->net_stats; @@ -2361,6 +2483,7 @@ static void gem_set_multicast(struct net_device *dev) return; spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); netif_stop_queue(dev); @@ -2385,6 +2508,7 @@ static void gem_set_multicast(struct net_device *dev) netif_wake_queue(dev); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); } @@ -2416,6 +2540,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) /* Return current PHY settings */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); cmd->autoneg = gp->want_autoneg; cmd->speed = gp->phy_mii.speed; cmd->duplex = gp->phy_mii.duplex; @@ -2427,6 +2552,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) */ if (cmd->advertising == 0) cmd->advertising = cmd->supported; + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); } else { // XXX PCS ? cmd->supported = @@ -2466,7 +2592,9 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) /* Apply settings and restart link process. */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gem_begin_auto_negotiation(gp, cmd); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); return 0; @@ -2481,7 +2609,9 @@ static int gem_nway_reset(struct net_device *dev) /* Restart link process. */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gem_begin_auto_negotiation(gp, NULL); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); return 0; @@ -2551,14 +2681,14 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return rc; } -#if (!defined(__sparc__) && !defined(CONFIG_PPC)) +#if (!defined(__sparc__) && !defined(CONFIG_PPC_PMAC)) /* Fetch MAC address from vital product data of PCI ROM. */ -static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_addr) +static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr) { int this_offset; for (this_offset = 0x20; this_offset < len; this_offset++) { - void *p = rom_base + this_offset; + void __iomem *p = rom_base + this_offset; int i; if (readb(p + 0) != 0x90 || @@ -2581,7 +2711,7 @@ static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_add static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr) { u32 rom_reg_orig; - void *p; + void __iomem *p; if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) { if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0) @@ -2733,6 +2863,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->msg_enable = DEFAULT_MSG; spin_lock_init(&gp->lock); + spin_lock_init(&gp->tx_lock); init_MUTEX(&gp->pm_sem); init_timer(&gp->link_timer); @@ -2750,7 +2881,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->timer_ticks = 0; netif_carrier_off(dev); - gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len); + gp->regs = ioremap(gemreg_base, gemreg_len); if (gp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -2768,7 +2899,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gem_apple_powerup(gp); #endif spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gem_stop(gp); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); /* Fill up the mii_phy structure (even if we won't use it) */ @@ -2806,12 +2939,17 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->get_stats = gem_get_stats; dev->set_multicast_list = gem_set_multicast; dev->do_ioctl = gem_ioctl; + dev->poll = gem_poll; + dev->weight = 64; dev->ethtool_ops = &gem_ethtool_ops; dev->tx_timeout = gem_tx_timeout; dev->watchdog_timeo = 5 * HZ; dev->change_mtu = gem_change_mtu; dev->irq = pdev->irq; dev->dma = 0; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = gem_poll_controller; +#endif if (register_netdev(dev)) { printk(KERN_ERR PFX "Cannot register net device, " @@ -2829,9 +2967,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev, /* Detect & init PHY, start autoneg */ spin_lock_irq(&gp->lock); + spin_lock(&gp->tx_lock); gp->hw_running = 1; gem_init_phy(gp); gem_begin_auto_negotiation(gp, NULL); + spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); if (gp->phy_type == phy_mii_mdio0 || @@ -2842,7 +2982,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); /* GEM can do it all... */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX; if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; @@ -2867,7 +3007,7 @@ err_out_iounmap: gem_shutdown(gp); up(&gp->pm_sem); - iounmap((void *) gp->regs); + iounmap(gp->regs); err_out_free_res: pci_release_regions(pdev); @@ -2901,7 +3041,7 @@ static void __devexit gem_remove_one(struct pci_dev *pdev) sizeof(struct gem_init_block), gp->init_block, gp->gblock_dvma); - iounmap((void *) gp->regs); + iounmap(gp->regs); pci_release_regions(pdev); free_netdev(dev); diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index eed77bfe1..00343226f 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -60,6 +60,9 @@ GREG_STAT_PCS | GREG_STAT_TXMAC | GREG_STAT_RXMAC | \ GREG_STAT_MAC | GREG_STAT_MIF | GREG_STAT_PCIERR) +#define GREG_STAT_NAPI (GREG_STAT_TXALL | GREG_STAT_TXINTME | \ + GREG_STAT_RXDONE | GREG_STAT_ABNORMAL) + /* The layout of GREG_IMASK and GREG_IACK is identical to GREG_STAT. * Bits set in GREG_IMASK will prevent that interrupt type from being * signalled to the cpu. GREG_IACK can be used to clear specific top-level @@ -950,7 +953,8 @@ enum link_state { struct gem { spinlock_t lock; - unsigned long regs; + spinlock_t tx_lock; + void __iomem *regs; int rx_new, rx_old; int tx_new, tx_old; @@ -969,6 +973,7 @@ struct gem { struct sk_buff *tx_skbs[RX_RING_SIZE]; u32 msg_enable; + u32 status; struct net_device_stats net_stats; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 13fdcca49..525b9ca61 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -36,9 +36,9 @@ static char version[] = #include #include #include +#include #include -#include #include #include #include @@ -203,12 +203,12 @@ MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); */ #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) -static void sbus_hme_write32(unsigned long reg, u32 val) +static void sbus_hme_write32(void __iomem *reg, u32 val) { sbus_writel(val, reg); } -static u32 sbus_hme_read32(unsigned long reg) +static u32 sbus_hme_read32(void __iomem *reg) { return sbus_readl(reg); } @@ -232,12 +232,12 @@ static u32 sbus_hme_read_desc32(u32 *p) return *p; } -static void pci_hme_write32(unsigned long reg, u32 val) +static void pci_hme_write32(void __iomem *reg, u32 val) { writel(val, reg); } -static u32 pci_hme_read32(unsigned long reg) +static u32 pci_hme_read32(void __iomem *reg) { return readl(reg); } @@ -354,7 +354,7 @@ do { (__txd)->tx_addr = cpu_to_le32(__addr); \ /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ -static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit) +static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit) { hme_write32(hp, tregs + TCVR_BBDATA, bit); hme_write32(hp, tregs + TCVR_BBCLOCK, 0); @@ -362,7 +362,7 @@ static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit) } #if 0 -static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal) +static u32 BB_GET_BIT(struct happy_meal *hp, void __iomem *tregs, int internal) { u32 ret; @@ -378,7 +378,7 @@ static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal) } #endif -static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal) +static u32 BB_GET_BIT2(struct happy_meal *hp, void __iomem *tregs, int internal) { u32 retval; @@ -397,7 +397,7 @@ static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal) #define TCVR_FAILURE 0x80000000 /* Impossible MIF read value */ static int happy_meal_bb_read(struct happy_meal *hp, - unsigned long tregs, int reg) + void __iomem *tregs, int reg) { u32 tmp; int retval = 0; @@ -443,7 +443,7 @@ static int happy_meal_bb_read(struct happy_meal *hp, } static void happy_meal_bb_write(struct happy_meal *hp, - unsigned long tregs, int reg, + void __iomem *tregs, int reg, unsigned short value) { u32 tmp; @@ -488,7 +488,7 @@ static void happy_meal_bb_write(struct happy_meal *hp, #define TCVR_READ_TRIES 16 static int happy_meal_tcvr_read(struct happy_meal *hp, - unsigned long tregs, int reg) + void __iomem *tregs, int reg) { int tries = TCVR_READ_TRIES; int retval; @@ -520,7 +520,7 @@ static int happy_meal_tcvr_read(struct happy_meal *hp, #define TCVR_WRITE_TRIES 16 static void happy_meal_tcvr_write(struct happy_meal *hp, - unsigned long tregs, int reg, + void __iomem *tregs, int reg, unsigned short value) { int tries = TCVR_WRITE_TRIES; @@ -579,7 +579,7 @@ static void happy_meal_tcvr_write(struct happy_meal *hp, * service routine, and the chip is reset, or the link is ifconfig'd down * and then back up, this entire process repeats itself all over again. */ -static int try_next_permutation(struct happy_meal *hp, unsigned long tregs) +static int try_next_permutation(struct happy_meal *hp, void __iomem *tregs) { hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR); @@ -603,7 +603,7 @@ static int try_next_permutation(struct happy_meal *hp, unsigned long tregs) return -1; } -static void display_link_mode(struct happy_meal *hp, unsigned long tregs) +static void display_link_mode(struct happy_meal *hp, void __iomem *tregs) { printk(KERN_INFO "%s: Link is up using ", hp->dev->name); if (hp->tcvr_type == external) @@ -625,7 +625,7 @@ static void display_link_mode(struct happy_meal *hp, unsigned long tregs) } } -static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs) +static void display_forced_link_mode(struct happy_meal *hp, void __iomem *tregs) { printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name); if (hp->tcvr_type == external) @@ -644,7 +644,7 @@ static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs) printk("Half Duplex.\n"); } -static int set_happy_link_modes(struct happy_meal *hp, unsigned long tregs) +static int set_happy_link_modes(struct happy_meal *hp, void __iomem *tregs) { int full; @@ -708,7 +708,7 @@ static int happy_meal_init(struct happy_meal *hp); static int is_lucent_phy(struct happy_meal *hp) { - unsigned long tregs = hp->tcvregs; + void __iomem *tregs = hp->tcvregs; unsigned short mr2, mr3; int ret = 0; @@ -724,7 +724,7 @@ static int is_lucent_phy(struct happy_meal *hp) static void happy_meal_timer(unsigned long data) { struct happy_meal *hp = (struct happy_meal *) data; - unsigned long tregs = hp->tcvregs; + void __iomem *tregs = hp->tcvregs; int restart_timer = 0; spin_lock_irq(&hp->happy_lock); @@ -905,7 +905,7 @@ out: #define RX_RESET_TRIES 32 /* hp->happy_lock must be held */ -static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs) +static void happy_meal_tx_reset(struct happy_meal *hp, void __iomem *bregs) { int tries = TX_RESET_TRIES; @@ -925,7 +925,7 @@ static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs) } /* hp->happy_lock must be held */ -static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs) +static void happy_meal_rx_reset(struct happy_meal *hp, void __iomem *bregs) { int tries = RX_RESET_TRIES; @@ -947,7 +947,7 @@ static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs) #define STOP_TRIES 16 /* hp->happy_lock must be held */ -static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs) +static void happy_meal_stop(struct happy_meal *hp, void __iomem *gregs) { int tries = STOP_TRIES; @@ -967,7 +967,7 @@ static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs) } /* hp->happy_lock must be held */ -static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs) +static void happy_meal_get_counters(struct happy_meal *hp, void __iomem *bregs) { struct net_device_stats *stats = &hp->net_stats; @@ -990,7 +990,7 @@ static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs) } /* hp->happy_lock must be held */ -static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs) +static void happy_meal_poll_stop(struct happy_meal *hp, void __iomem *tregs) { ASD(("happy_meal_poll_stop: ")); @@ -1025,7 +1025,7 @@ static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs) #define TCVR_UNISOLATE_TRIES 32 /* Dis-isolation can take longer. */ /* hp->happy_lock must be held */ -static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs) +static int happy_meal_tcvr_reset(struct happy_meal *hp, void __iomem *tregs) { u32 tconfig; int result, tries = TCVR_RESET_TRIES; @@ -1123,7 +1123,7 @@ static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs) * * hp->happy_lock must be held */ -static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs) +static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tregs) { unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG); @@ -1318,7 +1318,7 @@ static void happy_meal_init_rings(struct happy_meal *hp) /* hp->happy_lock must be held */ static void happy_meal_begin_auto_negotiation(struct happy_meal *hp, - unsigned long tregs, + void __iomem *tregs, struct ethtool_cmd *ep) { int timeout; @@ -1443,11 +1443,11 @@ force_link: /* hp->happy_lock must be held */ static int happy_meal_init(struct happy_meal *hp) { - unsigned long gregs = hp->gregs; - unsigned long etxregs = hp->etxregs; - unsigned long erxregs = hp->erxregs; - unsigned long bregs = hp->bigmacregs; - unsigned long tregs = hp->tcvregs; + void __iomem *gregs = hp->gregs; + void __iomem *etxregs = hp->etxregs; + void __iomem *erxregs = hp->erxregs; + void __iomem *bregs = hp->bigmacregs; + void __iomem *tregs = hp->tcvregs; u32 regtmp, rxcfg; unsigned char *e = &hp->dev->dev_addr[0]; @@ -1736,9 +1736,9 @@ static int happy_meal_init(struct happy_meal *hp) /* hp->happy_lock must be held */ static void happy_meal_set_initial_advertisement(struct happy_meal *hp) { - unsigned long tregs = hp->tcvregs; - unsigned long bregs = hp->bigmacregs; - unsigned long gregs = hp->gregs; + void __iomem *tregs = hp->tcvregs; + void __iomem *bregs = hp->bigmacregs; + void __iomem *gregs = hp->gregs; happy_meal_stop(hp, gregs); hme_write32(hp, tregs + TCVR_IMASK, 0xffff); @@ -1910,7 +1910,7 @@ static int happy_meal_is_not_so_happy(struct happy_meal *hp, u32 status) /* hp->happy_lock must be held */ static void happy_meal_mif_interrupt(struct happy_meal *hp) { - unsigned long tregs = hp->tcvregs; + void __iomem *tregs = hp->tcvregs; printk(KERN_INFO "%s: Link status change.\n", hp->dev->name); hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR); @@ -2390,7 +2390,7 @@ static struct net_device_stats *happy_meal_get_stats(struct net_device *dev) static void happy_meal_set_multicast(struct net_device *dev) { struct happy_meal *hp = dev->priv; - unsigned long bregs = hp->bigmacregs; + void __iomem *bregs = hp->bigmacregs; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i; @@ -2948,12 +2948,12 @@ static int is_quattro_p(struct pci_dev *pdev) } /* Fetch MAC address from vital product data of PCI ROM. */ -static void find_eth_addr_in_vpd(void *rom_base, int len, int index, unsigned char *dev_addr) +static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr) { int this_offset; for (this_offset = 0x20; this_offset < len; this_offset++) { - void *p = rom_base + this_offset; + void __iomem *p = rom_base + this_offset; if (readb(p + 0) != 0x90 || readb(p + 1) != 0x00 || @@ -2980,7 +2980,7 @@ static void find_eth_addr_in_vpd(void *rom_base, int len, int index, unsigned ch static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) { u32 rom_reg_orig; - void *p; + void __iomem *p; int index; index = 0; @@ -3025,7 +3025,8 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) #endif struct happy_meal *hp; struct net_device *dev; - unsigned long hpreg_base; + void __iomem *hpreg_base; + unsigned long hpreg_res; int i, qfe_slot = -1; char prom_name[64]; int err; @@ -3084,7 +3085,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) qp->happy_meals[qfe_slot] = dev; } - hpreg_base = pci_resource_start(pdev, 0); + hpreg_res = pci_resource_start(pdev, 0); err = -ENODEV; if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) { printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n"); @@ -3096,7 +3097,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) goto err_out_clear_quattro; } - if ((hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000)) == 0) { + if ((hpreg_base = ioremap(hpreg_res, 0x8000)) == 0) { printk(KERN_ERR "happymeal(PCI): Unable to remap card memory.\n"); goto err_out_free_res; } @@ -3256,7 +3257,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) return 0; err_out_iounmap: - iounmap((void *)hp->gregs); + iounmap(hp->gregs); err_out_free_res: pci_release_regions(pdev); @@ -3389,7 +3390,7 @@ static void __exit happy_meal_cleanup_module(void) PAGE_SIZE, hp->happy_block, hp->hblock_dvma); - iounmap((void *)hp->gregs); + iounmap(hp->gregs); pci_release_regions(hp->happy_dev); } #endif diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index f2784d217..34e9f953c 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h @@ -397,7 +397,7 @@ struct quattro; /* Happy happy, joy joy! */ struct happy_meal { - unsigned long gregs; /* Happy meal global registers */ + void __iomem *gregs; /* Happy meal global registers */ struct hmeal_init_block *happy_block; /* RX and TX descriptors (CPU addr) */ #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) @@ -423,14 +423,14 @@ struct happy_meal { struct net_device_stats net_stats; /* Statistical counters */ #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) - u32 (*read32)(unsigned long); - void (*write32)(unsigned long, u32); + u32 (*read32)(void __iomem *); + void (*write32)(void __iomem *, u32); #endif - unsigned long etxregs; /* External transmitter regs */ - unsigned long erxregs; /* External receiver regs */ - unsigned long bigmacregs; /* BIGMAC core regs */ - unsigned long tcvregs; /* MIF transceiver regs */ + void __iomem *etxregs; /* External transmitter regs */ + void __iomem *erxregs; /* External receiver regs */ + void __iomem *bigmacregs; /* BIGMAC core regs */ + void __iomem *tcvregs; /* MIF transceiver regs */ dma_addr_t hblock_dvma; /* DVMA visible address happy block */ unsigned int happy_flags; /* Driver state flags */ diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index e80311524..d2d34594b 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -94,9 +94,9 @@ static char lancestr[] = "LANCE"; #include #include #include +#include #include -#include #include #include #include @@ -230,9 +230,9 @@ struct lance_init_block { ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0]))))) struct lance_private { - unsigned long lregs; /* Lance RAP/RDP regs. */ - unsigned long dregs; /* DMA controller regs. */ - volatile struct lance_init_block *init_block; + void __iomem *lregs; /* Lance RAP/RDP regs. */ + void __iomem *dregs; /* DMA controller regs. */ + struct lance_init_block *init_block; spinlock_t lock; @@ -270,7 +270,7 @@ struct lance_private { #define LANCE_REG_SIZE 0x04UL #define STOP_LANCE(__lp) \ -do { unsigned long __base = (__lp)->lregs; \ +do { void __iomem *__base = (__lp)->lregs; \ sbus_writew(LE_CSR0, __base + RAP); \ sbus_writew(LE_C0_STOP, __base + RDP); \ } while (0) @@ -314,7 +314,7 @@ static void load_csrs(struct lance_private *lp) static void lance_init_ring_dvma(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; dma_addr_t aib = lp->init_block_dvma; __u32 leptr; int i; @@ -371,7 +371,7 @@ static void lance_init_ring_dvma(struct net_device *dev) static void lance_init_ring_pio(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; u32 leptr; int i; @@ -501,8 +501,8 @@ static int init_restart_lance(struct lance_private *lp) static void lance_rx_dvma(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; - volatile struct lance_rx_desc *rd; + struct lance_init_block *ib = lp->init_block; + struct lance_rx_desc *rd; u8 bits; int len, entry = lp->rx_new; struct sk_buff *skb; @@ -564,14 +564,14 @@ static void lance_rx_dvma(struct net_device *dev) static void lance_tx_dvma(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; int i, j; spin_lock(&lp->lock); j = lp->tx_old; for (i = j; i != lp->tx_new; i = j) { - volatile struct lance_tx_desc *td = &ib->btx_ring [i]; + struct lance_tx_desc *td = &ib->btx_ring [i]; u8 bits = td->tmd1_bits; /* If we hit a packet not owned by us, stop */ @@ -641,12 +641,12 @@ out: spin_unlock(&lp->lock); } -static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len) +static void lance_piocopy_to_skb(struct sk_buff *skb, void __iomem *piobuf, int len) { u16 *p16 = (u16 *) skb->data; u32 *p32; u8 *p8; - unsigned long pbuf = (unsigned long) piobuf; + void __iomem *pbuf = piobuf; /* We know here that both src and dest are on a 16bit boundary. */ *p16++ = sbus_readw(pbuf); @@ -674,8 +674,8 @@ static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int static void lance_rx_pio(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; - volatile struct lance_rx_desc *rd; + struct lance_init_block *ib = lp->init_block; + struct lance_rx_desc *rd; unsigned char bits; int len, entry; struct sk_buff *skb; @@ -736,14 +736,14 @@ static void lance_rx_pio(struct net_device *dev) static void lance_tx_pio(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; int i, j; spin_lock(&lp->lock); j = lp->tx_old; for (i = j; i != lp->tx_new; i = j) { - volatile struct lance_tx_desc *td = &ib->btx_ring [i]; + struct lance_tx_desc *td = &ib->btx_ring [i]; u8 bits = sbus_readb(&td->tmd1_bits); /* If we hit a packet not owned by us, stop */ @@ -880,7 +880,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void build_fake_packet(struct lance_private *lp) { struct net_device *dev = lp->dev; - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; u16 *packet; struct ethhdr *eth; int i, entry; @@ -916,7 +916,7 @@ struct net_device *last_dev; static int lance_open(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; int status = 0; last_dev = dev; @@ -1006,9 +1006,9 @@ static int lance_reset(struct net_device *dev) return status; } -static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int len) +static void lance_piocopy_from_skb(void __iomem *dest, unsigned char *src, int len) { - unsigned long piobuf = (unsigned long) dest; + void __iomem *piobuf = dest; u32 *p32; u16 *p16; u8 *p8; @@ -1064,11 +1064,11 @@ static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int sbus_writeb(src[0], piobuf); } -static void lance_piozero(volatile void *dest, int len) +static void lance_piozero(void __iomem *dest, int len) { - unsigned long piobuf = (unsigned long) dest; + void __iomem *piobuf = dest; - if (piobuf & 1) { + if ((unsigned long)piobuf & 1) { sbus_writeb(0, piobuf); piobuf += 1; len -= 1; @@ -1079,7 +1079,7 @@ static void lance_piozero(volatile void *dest, int len) sbus_writeb(0, piobuf); return; } - if (piobuf & 2) { + if ((unsigned long)piobuf & 2) { sbus_writew(0, piobuf); piobuf += 2; len -= 2; @@ -1113,7 +1113,7 @@ static void lance_tx_timeout(struct net_device *dev) static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; int entry, skblen, len; skblen = skb->len; @@ -1174,8 +1174,8 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev) static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; - volatile u16 *mcast_table = (u16 *) &ib->filter; + struct lance_init_block *ib = lp->init_block; + u16 *mcast_table = (u16 *) &ib->filter; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i; @@ -1224,7 +1224,7 @@ static void lance_load_multicast(struct net_device *dev) static void lance_set_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib = lp->init_block; + struct lance_init_block *ib = lp->init_block; u16 mode; if (!netif_running(dev)) @@ -1277,12 +1277,12 @@ static void lance_free_hwresources(struct lance_private *lp) sbus_iounmap(lp->lregs, LANCE_REG_SIZE); if (lp->init_block != NULL) { if (lp->pio_buffer) { - sbus_iounmap((unsigned long)lp->init_block, + sbus_iounmap(lp->init_block, sizeof(struct lance_init_block)); } else { sbus_free_consistent(lp->sdev, sizeof(struct lance_init_block), - (void *)lp->init_block, + lp->init_block, lp->init_block_dvma); } } @@ -1349,7 +1349,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev, lp->sdev = sdev; if (lebuffer) { - lp->init_block = (volatile struct lance_init_block *) + lp->init_block = sbus_ioremap(&lebuffer->resource[0], 0, sizeof(struct lance_init_block), "lebuffer"); if (lp->init_block == NULL) { @@ -1362,7 +1362,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev, lp->rx = lance_rx_pio; lp->tx = lance_tx_pio; } else { - lp->init_block = (volatile struct lance_init_block *) + lp->init_block = sbus_alloc_consistent(sdev, sizeof(struct lance_init_block), &lp->init_block_dvma); if (lp->init_block == NULL || diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 39a4b40b4..37ef1b82a 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -27,9 +27,9 @@ static char version[] = #include #include #include +#include #include -#include #include #include #include @@ -49,7 +49,7 @@ static void qe_set_multicast(struct net_device *dev); #define QEC_RESET_TRIES 200 -static inline int qec_global_reset(unsigned long gregs) +static inline int qec_global_reset(void __iomem *gregs) { int tries = QEC_RESET_TRIES; @@ -73,8 +73,8 @@ static inline int qec_global_reset(unsigned long gregs) static inline int qe_stop(struct sunqe *qep) { - unsigned long cregs = qep->qcregs; - unsigned long mregs = qep->mregs; + void __iomem *cregs = qep->qcregs; + void __iomem *mregs = qep->mregs; int tries; /* Reset the MACE, then the QEC channel. */ @@ -130,9 +130,9 @@ static void qe_init_rings(struct sunqe *qep) static int qe_init(struct sunqe *qep, int from_irq) { struct sunqec *qecp = qep->parent; - unsigned long cregs = qep->qcregs; - unsigned long mregs = qep->mregs; - unsigned long gregs = qecp->gregs; + void __iomem *cregs = qep->qcregs; + void __iomem *mregs = qep->mregs; + void __iomem *gregs = qecp->gregs; unsigned char *e = &qep->dev->dev_addr[0]; u32 tmp; int i; @@ -699,7 +699,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) static u32 qe_get_link(struct net_device *dev) { struct sunqe *qep = dev->priv; - unsigned long mregs = qep->mregs; + void __iomem *mregs = qep->mregs; u8 phyconfig; spin_lock_irq(&qep->lock); diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index b90ed5db4..af34f3611 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h @@ -311,7 +311,7 @@ struct qe_init_block { struct sunqe; struct sunqec { - unsigned long gregs; /* QEC Global Registers */ + void __iomem *gregs; /* QEC Global Registers */ struct sunqe *qes[4]; /* Each child MACE */ unsigned int qec_bursts; /* Support burst sizes */ struct sbus_dev *qec_sdev; /* QEC's SBUS device */ @@ -331,8 +331,8 @@ struct sunqe_buffers { ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0])))) struct sunqe { - unsigned long qcregs; /* QEC per-channel Registers */ - unsigned long mregs; /* Per-channel MACE Registers */ + void __iomem *qcregs; /* QEC per-channel Registers */ + void __iomem *mregs; /* Per-channel MACE Registers */ struct qe_init_block *qe_block; /* RX and TX descriptors */ __u32 qblock_dvma; /* RX and TX descriptors */ spinlock_t lock; /* Protects txfull state */ diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 952ef8177..c2ec9fd8c 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -49,9 +49,9 @@ static const char *version = #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0e4615472..b39435b32 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4,12 +4,15 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. + * + * Firmware is: + * Copyright (C) 2000-2003 Broadcom Corporation. */ #include #include - +#include #include #include #include @@ -57,8 +60,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.8" -#define DRV_MODULE_RELDATE "July 14, 2004" +#define DRV_MODULE_VERSION "3.14" +#define DRV_MODULE_RELDATE "November 15, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -138,10 +141,11 @@ static char version[] __devinitdata = MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(tg3_debug, "i"); -MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); +MODULE_VERSION(DRV_MODULE_VERSION); static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ +module_param(tg3_debug, int, 0); +MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); static struct pci_device_id tg3_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, @@ -202,6 +206,14 @@ static struct pci_device_id tg3_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, @@ -221,8 +233,8 @@ static struct pci_device_id tg3_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); -struct { - char string[ETH_GSTRING_LEN]; +static struct { + const char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { { "rx_octets" }, { "rx_fragments" }, @@ -328,7 +340,7 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); spin_unlock_irqrestore(&tp->indirect_lock, flags); } else { - unsigned long dest = tp->regs + off; + void __iomem *dest = tp->regs + off; writel(val, dest); readl(dest); /* always flush PCI write */ } @@ -336,7 +348,7 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val) { - unsigned long mbox = tp->regs + off; + void __iomem *mbox = tp->regs + off; writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) readl(mbox); @@ -344,7 +356,7 @@ static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val) static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val) { - unsigned long mbox = tp->regs + off; + void __iomem *mbox = tp->regs + off; writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) writel(val, mbox); @@ -414,6 +426,20 @@ static void tg3_enable_ints(struct tg3 *tp) tg3_cond_int(tp); } +/* tg3_restart_ints + * similar to tg3_enable_ints, but it can return without flushing the + * PIO write which reenables interrupts + */ +static void tg3_restart_ints(struct tg3 *tp) +{ + tw32(TG3PCI_MISC_HOST_CTRL, + (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); + tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000); + mmiowb(); + + tg3_cond_int(tp); +} + static inline void tg3_netif_stop(struct tg3 *tp) { netif_poll_disable(tp->dev); @@ -442,9 +468,14 @@ static void tg3_switch_clocks(struct tg3 *tp) 0x1f); tp->pci_clock_ctrl = clock_ctrl; - if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 && - (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { + if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { + tw32_f(TG3PCI_CLOCK_CTRL, + clock_ctrl | CLOCK_CTRL_625_CORE); + udelay(40); + } + } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); @@ -858,34 +889,54 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT1)); udelay(100); } else { + int no_gpio2; + u32 grc_local_ctrl; + if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; + /* On 5753 and variants, GPIO2 cannot be used. */ + no_gpio2 = (tp->nic_sram_data_cfg & + NIC_SRAM_DATA_CFG_NO_GPIO2) != 0; + + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2; + if (no_gpio2) { + grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT2); + } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); + grc_local_ctrl); udelay(100); + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + GRC_LCLCTRL_GPIO_OUTPUT2; + if (no_gpio2) { + grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT2); + } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1 | - GRC_LCLCTRL_GPIO_OUTPUT2)); + grc_local_ctrl); udelay(100); - tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | - (GRC_LCLCTRL_GPIO_OE0 | - GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | - GRC_LCLCTRL_GPIO_OUTPUT1)); - udelay(100); + grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1; + if (!no_gpio2) { + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + grc_local_ctrl); + udelay(100); + } } } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && @@ -980,7 +1031,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) tp->link_config.orig_autoneg = tp->link_config.autoneg; } - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; @@ -992,7 +1043,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state) if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) { u32 mac_mode; - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a); udelay(40); @@ -1114,29 +1165,33 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv u32 old_rx_mode = tp->rx_mode; u32 old_tx_mode = tp->tx_mode; - if (local_adv & ADVERTISE_PAUSE_CAP) { - if (local_adv & ADVERTISE_PAUSE_ASYM) { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); - else if (remote_adv & LPA_PAUSE_ASYM) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE); - } else { - if (remote_adv & LPA_PAUSE_CAP) - new_tg3_flags |= - (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE); + if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) { + if (local_adv & ADVERTISE_PAUSE_CAP) { + if (local_adv & ADVERTISE_PAUSE_ASYM) { + if (remote_adv & LPA_PAUSE_CAP) + new_tg3_flags |= + (TG3_FLAG_RX_PAUSE | + TG3_FLAG_TX_PAUSE); + else if (remote_adv & LPA_PAUSE_ASYM) + new_tg3_flags |= + (TG3_FLAG_RX_PAUSE); + } else { + if (remote_adv & LPA_PAUSE_CAP) + new_tg3_flags |= + (TG3_FLAG_RX_PAUSE | + TG3_FLAG_TX_PAUSE); + } + } else if (local_adv & ADVERTISE_PAUSE_ASYM) { + if ((remote_adv & LPA_PAUSE_CAP) && + (remote_adv & LPA_PAUSE_ASYM)) + new_tg3_flags |= TG3_FLAG_TX_PAUSE; } - } else if (local_adv & ADVERTISE_PAUSE_ASYM) { - if ((remote_adv & LPA_PAUSE_CAP) && - (remote_adv & LPA_PAUSE_ASYM)) - new_tg3_flags |= TG3_FLAG_TX_PAUSE; - } - tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); - tp->tg3_flags |= new_tg3_flags; + tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE); + tp->tg3_flags |= new_tg3_flags; + } else { + new_tg3_flags = tp->tg3_flags; + } if (new_tg3_flags & TG3_FLAG_RX_PAUSE) tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; @@ -1487,6 +1542,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) current_speed = SPEED_INVALID; current_duplex = DUPLEX_INVALID; + if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) { + u32 val; + + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007); + tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); + if (!(val & (1 << 10))) { + val |= (1 << 10); + tg3_writephy(tp, MII_TG3_AUX_CTRL, val); + goto relink; + } + } + bmsr = 0; for (i = 0; i < 100; i++) { tg3_readphy(tp, MII_BMSR, &bmsr); @@ -1566,7 +1633,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tg3_setup_flow_control(tp, local_adv, remote_adv); } } - +relink: if (current_link_up == 0) { u32 tmp; @@ -1616,7 +1683,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) { + if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) { /* Polled via timer. */ tw32_f(MAC_EVENT, 0); } else { @@ -1965,190 +2032,327 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, static int fiber_autoneg(struct tg3 *tp, u32 *flags) { int res = 0; + struct tg3_fiber_aneginfo aninfo; + int status = ANEG_FAILED; + unsigned int tick; + u32 tmp; - if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { - u32 dig_status; + tw32_f(MAC_TX_AUTO_NEG, 0); - dig_status = tr32(SG_DIG_STATUS); - *flags = 0; - if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE) - *flags |= MR_LP_ADV_ASYM_PAUSE; - if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE) - *flags |= MR_LP_ADV_SYM_PAUSE; + tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; + tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); + udelay(40); - if ((dig_status & SG_DIG_AUTONEG_COMPLETE) && - !(dig_status & (SG_DIG_AUTONEG_ERROR | - SG_DIG_PARTNER_FAULT_MASK))) - res = 1; - } else { - struct tg3_fiber_aneginfo aninfo; - int status = ANEG_FAILED; - unsigned int tick; - u32 tmp; + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); + udelay(40); - tw32_f(MAC_TX_AUTO_NEG, 0); + memset(&aninfo, 0, sizeof(aninfo)); + aninfo.flags |= MR_AN_ENABLE; + aninfo.state = ANEG_STATE_UNKNOWN; + aninfo.cur_time = 0; + tick = 0; + while (++tick < 195000) { + status = tg3_fiber_aneg_smachine(tp, &aninfo); + if (status == ANEG_DONE || status == ANEG_FAILED) + break; - tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); - udelay(40); + udelay(1); + } - tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); - udelay(40); + tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); - memset(&aninfo, 0, sizeof(aninfo)); - aninfo.flags |= MR_AN_ENABLE; - aninfo.state = ANEG_STATE_UNKNOWN; - aninfo.cur_time = 0; - tick = 0; - while (++tick < 195000) { - status = tg3_fiber_aneg_smachine(tp, &aninfo); - if (status == ANEG_DONE || status == ANEG_FAILED) - break; + *flags = aninfo.flags; - udelay(1); - } + if (status == ANEG_DONE && + (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | + MR_LP_ADV_FULL_DUPLEX))) + res = 1; - tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); + return res; +} - *flags = aninfo.flags; +static void tg3_init_bcm8002(struct tg3 *tp) +{ + u32 mac_status = tr32(MAC_STATUS); + int i; - if (status == ANEG_DONE && - (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK | - MR_LP_ADV_FULL_DUPLEX))) - res = 1; - } + /* Reset when initting first time or we have a link. */ + if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) && + !(mac_status & MAC_STATUS_PCS_SYNCED)) + return; - return res; + /* Set PLL lock range. */ + tg3_writephy(tp, 0x16, 0x8007); + + /* SW reset */ + tg3_writephy(tp, MII_BMCR, BMCR_RESET); + + /* Wait for reset to complete. */ + /* XXX schedule_timeout() ... */ + for (i = 0; i < 500; i++) + udelay(10); + + /* Config mode; select PMA/Ch 1 regs. */ + tg3_writephy(tp, 0x10, 0x8411); + + /* Enable auto-lock and comdet, select txclk for tx. */ + tg3_writephy(tp, 0x11, 0x0a10); + + tg3_writephy(tp, 0x18, 0x00a0); + tg3_writephy(tp, 0x16, 0x41ff); + + /* Assert and deassert POR. */ + tg3_writephy(tp, 0x13, 0x0400); + udelay(40); + tg3_writephy(tp, 0x13, 0x0000); + + tg3_writephy(tp, 0x11, 0x0a50); + udelay(40); + tg3_writephy(tp, 0x11, 0x0a10); + + /* Wait for signal to stabilize */ + /* XXX schedule_timeout() ... */ + for (i = 0; i < 15000; i++) + udelay(10); + + /* Deselect the channel register so we can read the PHYID + * later. + */ + tg3_writephy(tp, 0x10, 0x8011); } -static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) +static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) { - u32 orig_pause_cfg; - u16 orig_active_speed; - u8 orig_active_duplex; + u32 sg_dig_ctrl, sg_dig_status; + u32 serdes_cfg, expected_sg_dig_ctrl; + int workaround, port_a; int current_link_up; - int i; - orig_pause_cfg = - (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | - TG3_FLAG_TX_PAUSE)); - orig_active_speed = tp->link_config.active_speed; - orig_active_duplex = tp->link_config.active_duplex; + serdes_cfg = 0; + expected_sg_dig_ctrl = 0; + workaround = 0; + port_a = 1; + current_link_up = 0; - tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); - tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); + if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 && + tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) { + workaround = 1; + if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) + port_a = 0; - if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) { - /* Allow time for the hardware to auto-negotiate (195ms) */ - unsigned int tick = 0; + serdes_cfg = tr32(MAC_SERDES_CFG) & + ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20)); + } - while (++tick < 195000) { - if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE) - break; - udelay(1); + sg_dig_ctrl = tr32(SG_DIG_CTRL); + + if (tp->link_config.autoneg != AUTONEG_ENABLE) { + if (sg_dig_ctrl & (1 << 31)) { + if (workaround) { + u32 val = serdes_cfg; + + if (port_a) + val |= 0xc010880; + else + val |= 0x4010880; + tw32_f(MAC_SERDES_CFG, val); + } + tw32_f(SG_DIG_CTRL, 0x01388400); } - if (tick >= 195000) - printk(KERN_INFO PFX "%s: HW autoneg failed !\n", - tp->dev->name); + if (mac_status & MAC_STATUS_PCS_SYNCED) { + tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; + } + goto out; } - /* Reset when initting first time or we have a link. */ - if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - /* Set PLL lock range. */ - tg3_writephy(tp, 0x16, 0x8007); + /* Want auto-negotiation. */ + expected_sg_dig_ctrl = 0x81388400; - /* SW reset */ - tg3_writephy(tp, MII_BMCR, BMCR_RESET); + /* Pause capability */ + expected_sg_dig_ctrl |= (1 << 11); - /* Wait for reset to complete. */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 500; i++) - udelay(10); + /* Asymettric pause */ + expected_sg_dig_ctrl |= (1 << 12); - /* Config mode; select PMA/Ch 1 regs. */ - tg3_writephy(tp, 0x10, 0x8411); + if (sg_dig_ctrl != expected_sg_dig_ctrl) { + if (workaround) + tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30)); + udelay(5); + tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl); - /* Enable auto-lock and comdet, select txclk for tx. */ - tg3_writephy(tp, 0x11, 0x0a10); + tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED; + } else if (mac_status & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET)) { + int i; - tg3_writephy(tp, 0x18, 0x00a0); - tg3_writephy(tp, 0x16, 0x41ff); + /* Giver time to negotiate (~200ms) */ + for (i = 0; i < 40000; i++) { + sg_dig_status = tr32(SG_DIG_STATUS); + if (sg_dig_status & (0x3)) + break; + udelay(5); + } + mac_status = tr32(MAC_STATUS); - /* Assert and deassert POR. */ - tg3_writephy(tp, 0x13, 0x0400); - udelay(40); - tg3_writephy(tp, 0x13, 0x0000); + if ((sg_dig_status & (1 << 1)) && + (mac_status & MAC_STATUS_PCS_SYNCED)) { + u32 local_adv, remote_adv; - tg3_writephy(tp, 0x11, 0x0a50); - udelay(40); - tg3_writephy(tp, 0x11, 0x0a10); + local_adv = ADVERTISE_PAUSE_CAP; + remote_adv = 0; + if (sg_dig_status & (1 << 19)) + remote_adv |= LPA_PAUSE_CAP; + if (sg_dig_status & (1 << 20)) + remote_adv |= LPA_PAUSE_ASYM; - /* Wait for signal to stabilize */ - /* XXX schedule_timeout() ... */ - for (i = 0; i < 15000; i++) - udelay(10); + tg3_setup_flow_control(tp, local_adv, remote_adv); + current_link_up = 1; + tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + } else if (!(sg_dig_status & (1 << 1))) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED) + tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED; + else { + if (workaround) { + u32 val = serdes_cfg; + + if (port_a) + val |= 0xc010880; + else + val |= 0x4010880; + + tw32_f(MAC_SERDES_CFG, val); + } - /* Deselect the channel register so we can read the PHYID - * later. - */ - tg3_writephy(tp, 0x10, 0x8011); + tw32_f(SG_DIG_CTRL, 0x01388400); + udelay(40); + + mac_status = tr32(MAC_STATUS); + if (mac_status & MAC_STATUS_PCS_SYNCED) { + tg3_setup_flow_control(tp, 0, 0); + current_link_up = 1; + } + } + } } - /* Enable link change interrupt unless serdes polling. */ - if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) - tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); - else - tw32_f(MAC_EVENT, 0); - udelay(40); +out: + return current_link_up; +} - current_link_up = 0; - if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) { - if (tp->link_config.autoneg == AUTONEG_ENABLE) { - u32 flags; +static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) +{ + int current_link_up = 0; + + if (!(mac_status & MAC_STATUS_PCS_SYNCED)) { + tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; + goto out; + } + + if (tp->link_config.autoneg == AUTONEG_ENABLE) { + u32 flags; + int i; - if (fiber_autoneg(tp, &flags)) { - u32 local_adv, remote_adv; + if (fiber_autoneg(tp, &flags)) { + u32 local_adv, remote_adv; - local_adv = ADVERTISE_PAUSE_CAP; - remote_adv = 0; - if (flags & MR_LP_ADV_SYM_PAUSE) - remote_adv |= LPA_PAUSE_CAP; - if (flags & MR_LP_ADV_ASYM_PAUSE) - remote_adv |= LPA_PAUSE_ASYM; + local_adv = ADVERTISE_PAUSE_CAP; + remote_adv = 0; + if (flags & MR_LP_ADV_SYM_PAUSE) + remote_adv |= LPA_PAUSE_CAP; + if (flags & MR_LP_ADV_ASYM_PAUSE) + remote_adv |= LPA_PAUSE_ASYM; - tg3_setup_flow_control(tp, local_adv, remote_adv); + tg3_setup_flow_control(tp, local_adv, remote_adv); - tp->tg3_flags |= - TG3_FLAG_GOT_SERDES_FLOWCTL; - current_link_up = 1; - } - for (i = 0; i < 60; i++) { - udelay(20); - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) - break; - } - if (current_link_up == 0 && - (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) { - current_link_up = 1; - } - } else { - /* Forcing 1000FD link up. */ - current_link_up = 1; tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; + current_link_up = 1; } - } else - tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL; + for (i = 0; i < 30; i++) { + udelay(20); + tw32_f(MAC_STATUS, + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + udelay(40); + if ((tr32(MAC_STATUS) & + (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + + mac_status = tr32(MAC_STATUS); + if (current_link_up == 0 && + (mac_status & MAC_STATUS_PCS_SYNCED) && + !(mac_status & MAC_STATUS_RCVD_CFG)) + current_link_up = 1; + } else { + /* Forcing 1000FD link up. */ + current_link_up = 1; + tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL; + + tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS)); + udelay(40); + } + +out: + return current_link_up; +} + +static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) +{ + u32 orig_pause_cfg; + u16 orig_active_speed; + u8 orig_active_duplex; + u32 mac_status; + int current_link_up; + int i; + + orig_pause_cfg = + (tp->tg3_flags & (TG3_FLAG_RX_PAUSE | + TG3_FLAG_TX_PAUSE)); + orig_active_speed = tp->link_config.active_speed; + orig_active_duplex = tp->link_config.active_duplex; + + if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) && + netif_carrier_ok(tp->dev) && + (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) { + mac_status = tr32(MAC_STATUS); + mac_status &= (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET | + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_RCVD_CFG); + if (mac_status == (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET)) { + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + return 0; + } + } + + tw32_f(MAC_TX_AUTO_NEG, 0); + + tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); + tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; + tw32_f(MAC_MODE, tp->mac_mode); + udelay(40); + + if (tp->phy_id == PHY_ID_BCM8002) + tg3_init_bcm8002(tp); + + /* Enable link change event even when serdes polling. */ + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + udelay(40); + + current_link_up = 0; + mac_status = tr32(MAC_STATUS); + + if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) + current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status); + else + current_link_up = tg3_setup_fiber_by_hand(tp, mac_status); tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; tw32_f(MAC_MODE, tp->mac_mode); @@ -2159,19 +2363,24 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) (tp->hw_status->status & ~SD_STATUS_LINK_CHG)); for (i = 0; i < 100; i++) { - udelay(20); - tw32_f(MAC_STATUS, - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - udelay(40); - if ((tr32(MAC_STATUS) & - (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)) == 0) + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)); + udelay(5); + if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED)) == 0) break; } - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) + mac_status = tr32(MAC_STATUS); + if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) { current_link_up = 0; + if (tp->link_config.autoneg == AUTONEG_ENABLE) { + tw32_f(MAC_MODE, (tp->mac_mode | + MAC_MODE_SEND_CONFIGS)); + udelay(1); + tw32_f(MAC_MODE, tp->mac_mode); + } + } if (current_link_up == 1) { tp->link_config.active_speed = SPEED_1000; @@ -2203,15 +2412,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) tg3_link_report(tp); } - if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { - tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); - udelay(40); - if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - tw32_f(MAC_MODE, tp->mac_mode); - udelay(40); - } - } - return 0; } @@ -2219,7 +2419,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) { int err; - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { err = tg3_setup_fiber_phy(tp, force_reset); } else { err = tg3_setup_copper_phy(tp, force_reset); @@ -2581,6 +2781,7 @@ next_pkt_nopost: tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, sw_idx); } + mmiowb(); return received; } @@ -2639,7 +2840,7 @@ static int tg3_poll(struct net_device *netdev, int *budget) if (done) { spin_lock_irqsave(&tp->lock, flags); __netif_rx_complete(netdev); - tg3_enable_ints(tp); + tg3_restart_ints(tp); spin_unlock_irqrestore(&tp->lock, flags); } @@ -2738,11 +2939,11 @@ static void tg3_reset_task(void *_data) tg3_halt(tp); tg3_init_hw(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - if (restart_timer) mod_timer(&tp->timer, jiffies + 1); } @@ -2812,6 +3013,7 @@ static void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags, u32 mss_and_is_end) { + struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; int is_end = (mss_and_is_end & 0x1); u32 mss = (mss_and_is_end >> 1); u32 vlan_tag = 0; @@ -2823,35 +3025,11 @@ static void tg3_set_txd(struct tg3 *tp, int entry, flags &= 0xffff; } vlan_tag |= (mss << TXD_MSS_SHIFT); - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; - - txd->addr_hi = ((u64) mapping >> 32); - txd->addr_lo = ((u64) mapping & 0xffffffff); - txd->len_flags = (len << TXD_LEN_SHIFT) | flags; - txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; - } else { - struct tx_ring_info *txr = &tp->tx_buffers[entry]; - unsigned long txd; - txd = (tp->regs + - NIC_SRAM_WIN_BASE + - NIC_SRAM_TX_BUFFER_DESC); - txd += (entry * TXD_SIZE); - - /* Save some PIOs */ - if (sizeof(dma_addr_t) != sizeof(u32)) - writel(((u64) mapping >> 32), - txd + TXD_ADDR + TG3_64BIT_REG_HIGH); - - writel(((u64) mapping & 0xffffffff), - txd + TXD_ADDR + TG3_64BIT_REG_LOW); - writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS); - if (txr->prev_vlan_tag != vlan_tag) { - writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG); - txr->prev_vlan_tag = vlan_tag; - } - } + txd->addr_hi = ((u64) mapping >> 32); + txd->addr_lo = ((u64) mapping & 0xffffffff); + txd->len_flags = (len << TXD_LEN_SHIFT) | flags; + txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; } static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) @@ -2892,7 +3070,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) * So we really do need to disable interrupts when taking * tx_lock here. */ - spin_lock_irqsave(&tp->tx_lock, flags); + local_irq_save(flags); + if (!spin_trylock(&tp->tx_lock)) { + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { @@ -2900,7 +3082,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&tp->tx_lock, flags); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + return NETDEV_TX_BUSY; } entry = tp->tx_prod; @@ -3040,30 +3222,19 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Packets are ready, update Tx producer idx local and on card. */ - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - } else { - /* First, make sure tg3 sees last descriptor fully - * in SRAM. - */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); - - tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - } + tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); out_unlock: + mmiowb(); spin_unlock_irqrestore(&tp->tx_lock, flags); dev->trans_start = jiffies; - return 0; + return NETDEV_TX_OK; } static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp, @@ -3102,9 +3273,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) tg3_init_hw(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -3190,7 +3362,6 @@ static void tg3_free_rings(struct tg3 *tp) */ static void tg3_init_rings(struct tg3 *tp) { - unsigned long start, end; u32 i; /* Free up all the SKBs. */ @@ -3200,21 +3371,7 @@ static void tg3_init_rings(struct tg3 *tp) memset(tp->rx_std, 0, TG3_RX_RING_BYTES); memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES); memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); - } else { - start = (tp->regs + - NIC_SRAM_WIN_BASE + - NIC_SRAM_TX_BUFFER_DESC); - end = start + TG3_TX_RING_BYTES; - while (start < end) { - writel(0, start); - start += 4; - } - for (i = 0; i < TG3_TX_RING_SIZE; i++) - tp->tx_buffers[i].prev_vlan_tag = 0; - } + memset(tp->tx_ring, 0, TG3_TX_RING_BYTES); /* Initialize invariants of the rings, we only set this * stuff once. This works because the card does not @@ -3345,15 +3502,10 @@ static int tg3_alloc_consistent(struct tg3 *tp) if (!tp->rx_rcb) goto err_out; - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, - &tp->tx_desc_mapping); - if (!tp->tx_ring) - goto err_out; - } else { - tp->tx_ring = NULL; - tp->tx_desc_mapping = 0; - } + tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES, + &tp->tx_desc_mapping); + if (!tp->tx_ring) + goto err_out; tp->hw_status = pci_alloc_consistent(tp->pdev, TG3_HW_STATUS_SIZE, @@ -3595,6 +3747,8 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) } } +static void tg3_stop_fw(struct tg3 *); + /* tp->lock is held. */ static int tg3_chip_reset(struct tg3 *tp) { @@ -3602,7 +3756,7 @@ static int tg3_chip_reset(struct tg3 *tp) u32 flags_save; int i; - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) + if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) tg3_nvram_lock(tp); /* @@ -3688,7 +3842,7 @@ static int tg3_chip_reset(struct tg3 *tp) val |= PCISTATE_RETRY_SAME_DMA; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); @@ -3697,6 +3851,11 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { + tg3_stop_fw(tp); + tw32(0x5000, 0x400); + } + tw32(GRC_MODE, tp->grc_mode); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { @@ -3713,7 +3872,7 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tw32_f(MAC_MODE, tp->mac_mode); } else @@ -3728,7 +3887,7 @@ static int tg3_chip_reset(struct tg3 *tp) udelay(10); } if (i >= 100000 && - !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { + !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, " "firmware will not restart magic=%08x\n", tp->dev->name, val); @@ -4399,7 +4558,7 @@ static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, }; -u32 tg3TsoFwRodata[] = { +static u32 tg3TsoFwRodata[] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, @@ -4407,7 +4566,7 @@ u32 tg3TsoFwRodata[] = { 0x00000000, }; -u32 tg3TsoFwData[] = { +static u32 tg3TsoFwData[] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -4588,14 +4747,14 @@ static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x00000000, 0x00000000, 0x00000000, }; -u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, 0x00000000, }; -u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; @@ -4810,10 +4969,7 @@ static int tg3_reset_hw(struct tg3 *tp) GRC_MODE_4X_NIC_SEND_RINGS | GRC_MODE_NO_TX_PHDR_CSUM | GRC_MODE_NO_RX_PHDR_CSUM); - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) - tp->grc_mode |= GRC_MODE_HOST_SENDBDS; - else - tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS; + tp->grc_mode |= GRC_MODE_HOST_SENDBDS; if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) @@ -4966,18 +5122,11 @@ static int tg3_reset_hw(struct tg3 *tp) tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, - tp->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - } else { - tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, - 0, - BDINFO_FLAGS_DISABLED, - NIC_SRAM_TX_BUFFER_DESC); - } + tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, + tp->tx_desc_mapping, + (TG3_TX_RING_SIZE << + BDINFO_FLAGS_MAXLEN_SHIFT), + NIC_SRAM_TX_BUFFER_DESC); /* There is only one receive return ring on 5705/5750, no need * to explicitly disable the others. @@ -5243,14 +5392,14 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { /* Set drive transmission level to 1.2V */ val = tr32(MAC_SERDES_CFG); @@ -5268,22 +5417,8 @@ static int tg3_reset_hw(struct tg3 *tp) tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - tp->phy_id == PHY_ID_SERDES) { - /* Enable hardware link auto-negotiation */ - u32 digctrl, txctrl; - - digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N | - SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS | - (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE | - SG_DIG_GBIC_ENABLE; - - txctrl = tr32(MAC_SERDES_CFG); - tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT); - tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET); - tr32(SG_DIG_CTRL); - udelay(5); - tw32_f(SG_DIG_CTRL, digctrl); - + (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { + /* Use hardware link auto-negotiation */ tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG; } @@ -5291,7 +5426,7 @@ static int tg3_reset_hw(struct tg3 *tp) if (err) return err; - if (tp->phy_id != PHY_ID_SERDES) { + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { u32 tmp; /* Clear CRC stats. */ @@ -5483,7 +5618,8 @@ static void tg3_timer(unsigned long __opaque) need_setup = 1; } if (! netif_carrier_ok(tp->dev) && - (mac_stat & MAC_STATUS_PCS_SYNCED)) { + (mac_stat & (MAC_STATUS_PCS_SYNCED | + MAC_STATUS_SIGNAL_DET))) { need_setup = 1; } if (need_setup) { @@ -5536,8 +5672,8 @@ static int tg3_open(struct net_device *dev) spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - /* If you move this call, make sure TG3_FLAG_HOST_TXDS in - * tp->tg3_flags is accurate at that new place. + /* The placement of this call is tied + * to the setup and use of Host TX descriptors. */ err = tg3_alloc_consistent(tp); if (err) @@ -5879,7 +6015,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp) { struct tg3_hw_stats *hw_stats = tp->hw_stats; - if (tp->phy_id != PHY_ID_SERDES && + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) { unsigned long flags; @@ -6152,7 +6288,9 @@ static void tg3_set_rx_mode(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); spin_lock_irq(&tp->lock); + spin_lock(&tp->tx_lock); __tg3_set_rx_mode(dev); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); } @@ -6235,11 +6373,11 @@ static int tg3_get_eeprom_len(struct net_device *dev) return EEPROM_CHIP_SIZE; } -static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, - u32 offset, u32 *val); +static int tg3_nvram_read_using_eeprom(struct tg3 *tp, + u32 offset, u32 *val); static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int ret; u8 *pd; u32 i, offset, len, val, b_offset, b_count; @@ -6310,7 +6448,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->supported |= (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); - if (tp->phy_id != PHY_ID_SERDES) + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | @@ -6339,7 +6477,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->link_config.phy_is_low_power) return -EAGAIN; - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { /* These are the only valid advertisement bits allowed. */ if (cmd->autoneg == AUTONEG_ENABLE && (cmd->advertising & ~(ADVERTISED_1000baseT_Half | @@ -6397,7 +6535,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; if ((wol->wolopts & WAKE_MAGIC) && - tp->phy_id == PHY_ID_SERDES && + tp->tg3_flags2 & TG3_FLG2_PHY_SERDES && !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP)) return -EINVAL; @@ -6493,10 +6631,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e tg3_halt(tp); tg3_init_hw(tp); - netif_wake_queue(tp->dev); + tg3_netif_start(tp); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -6506,8 +6643,8 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam struct tg3 *tp = netdev_priv(dev); epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; - epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; - epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0; + epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0; + epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0; } static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) @@ -6522,18 +6659,18 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam else tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; if (epause->rx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_RX; + tp->tg3_flags |= TG3_FLAG_RX_PAUSE; else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX; + tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE; if (epause->tx_pause) - tp->tg3_flags |= TG3_FLAG_PAUSE_TX; + tp->tg3_flags |= TG3_FLAG_TX_PAUSE; else - tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX; + tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; tg3_halt(tp); tg3_init_hw(tp); + tg3_netif_start(tp); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); return 0; } @@ -6602,7 +6739,7 @@ static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) static void tg3_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } @@ -6620,7 +6757,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: { u32 mii_regval; - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ spin_lock_irq(&tp->lock); @@ -6633,7 +6770,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } case SIOCSMIIREG: - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) break; /* We have no PHY */ if (!capable(CAP_NET_ADMIN)) @@ -6720,7 +6857,7 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) { int j; - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) return; tw32_f(GRC_EEPROM_ADDR, @@ -6768,8 +6905,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) } } -static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp, - u32 offset, u32 *val) +static int tg3_nvram_read_using_eeprom(struct tg3 *tp, + u32 offset, u32 *val) { u32 tmp; int i; @@ -6807,8 +6944,8 @@ static int __devinit tg3_nvram_read(struct tg3 *tp, { int i; - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { - printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n"); + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { + printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n"); return -EINVAL; } @@ -6870,10 +7007,10 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES }, /* BCM95700A9 */ + { PCI_VENDOR_ID_BROADCOM, 0x0003, 0 }, /* BCM95700A9 */ { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES }, /* BCM95701A7 */ + { PCI_VENDOR_ID_BROADCOM, 0x0007, 0 }, /* BCM95701A7 */ { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */ @@ -6882,7 +7019,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { /* 3com boards. */ { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - { PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES }, /* 3C996SX */ + { PCI_VENDOR_ID_3COM, 0x1004, 0 }, /* 3C996SX */ { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ @@ -6895,37 +7032,43 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = { /* Compaq boards. */ { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ - { PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES }, /* CHANGELING */ + { PCI_VENDOR_ID_COMPAQ, 0x007d, 0 }, /* CHANGELING */ { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ /* IBM boards. */ - { PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */ + { PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */ }; -static int __devinit tg3_phy_probe(struct tg3 *tp) +static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) { - u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; - u32 hw_phy_id, hw_phy_id_masked; - u32 val; - int i, eeprom_signature_found, err; + int i; - tp->phy_id = PHY_ID_INVALID; for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) { if ((subsys_id_to_phy_id[i].subsys_vendor == tp->pdev->subsystem_vendor) && (subsys_id_to_phy_id[i].subsys_devid == - tp->pdev->subsystem_device)) { - tp->phy_id = subsys_id_to_phy_id[i].phy_id; - break; - } + tp->pdev->subsystem_device)) + return &subsys_id_to_phy_id[i]; } + return NULL; +} + +static int __devinit tg3_phy_probe(struct tg3 *tp) +{ + u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2; + u32 hw_phy_id, hw_phy_id_masked; + u32 val; + int eeprom_signature_found, eeprom_phy_serdes, err; + tp->phy_id = PHY_ID_INVALID; eeprom_phy_id = PHY_ID_INVALID; + eeprom_phy_serdes = 0; eeprom_signature_found = 0; tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg, led_cfg; + u32 nic_phy_id, cfg2; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); tp->nic_sram_data_cfg = nic_cfg; @@ -6933,21 +7076,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) eeprom_signature_found = 1; if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) == - NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) { - eeprom_phy_id = PHY_ID_SERDES; - } else { - u32 nic_phy_id; + NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) + eeprom_phy_serdes = 1; - tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); - if (nic_phy_id != 0) { - u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; - u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; + tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id); + if (nic_phy_id != 0) { + u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK; + u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK; - eeprom_phy_id = (id1 >> 16) << 10; - eeprom_phy_id |= (id2 & 0xfc00) << 16; - eeprom_phy_id |= (id2 & 0x03ff) << 0; - } - } + eeprom_phy_id = (id1 >> 16) << 10; + eeprom_phy_id |= (id2 & 0xfc00) << 16; + eeprom_phy_id |= (id2 & 0x03ff) << 0; + } else + eeprom_phy_id = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) { tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg); @@ -7009,6 +7150,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL) tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP; + + tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2); + if (cfg2 & (1 << 17)) + tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING; } /* Reading the PHY ID register can conflict with ASF @@ -7035,20 +7180,31 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { tp->phy_id = hw_phy_id; + if (hw_phy_id_masked == PHY_ID_BCM8002) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; } else { - /* phy_id currently holds the value found in the - * subsys_id_to_phy_id[] table or PHY_ID_INVALID - * if a match was not found there. - */ - if (tp->phy_id == PHY_ID_INVALID) { - if (!eeprom_signature_found || - !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK)) - return -ENODEV; + if (eeprom_signature_found) { tp->phy_id = eeprom_phy_id; + if (eeprom_phy_serdes) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; + } else { + struct subsys_tbl_ent *p; + + /* No eeprom signature? Try the hardcoded + * subsys device table. + */ + p = lookup_by_subsys(tp); + if (!p) + return -ENODEV; + + tp->phy_id = p->phy_id; + if (!tp->phy_id || + tp->phy_id == PHY_ID_BCM8002) + tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; } } - if (tp->phy_id != PHY_ID_SERDES && + if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { u32 bmsr, adv_reg, tg3_ctrl; @@ -7105,7 +7261,7 @@ skip_phy_reset: if (!eeprom_signature_found) tp->led_ctrl = LED_CTRL_MODE_PHY_1; - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) tp->link_config.advertising = (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | @@ -7124,11 +7280,11 @@ static void __devinit tg3_read_partno(struct tg3 *tp) unsigned char vpd_data[256]; int i; - if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) { + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { /* Sun decided not to put the necessary bits in the * NVRAM of their onboard tg3 parts :( */ - strcpy(tp->board_part_number, "Sun 5704"); + strcpy(tp->board_part_number, "Sun 570X"); return; } @@ -7189,27 +7345,21 @@ out_not_found: } #ifdef CONFIG_SPARC64 -static int __devinit tg3_is_sun_5704(struct tg3 *tp) +static int __devinit tg3_is_sun_570X(struct tg3 *tp) { struct pci_dev *pdev = tp->pdev; struct pcidev_cookie *pcp = pdev->sysdata; if (pcp != NULL) { int node = pcp->prom_node; - u32 venid, devid; + u32 venid; int err; err = prom_getproperty(node, "subsystem-vendor-id", (char *) &venid, sizeof(venid)); if (err == 0 || err == -1) return 0; - err = prom_getproperty(node, "subsystem-id", - (char *) &devid, sizeof(devid)); - if (err == 0 || err == -1) - return 0; - - if (venid == PCI_VENDOR_ID_SUN && - devid == PCI_DEVICE_ID_TIGON3_5704) + if (venid == PCI_VENDOR_ID_SUN) return 1; } return 0; @@ -7226,8 +7376,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) int err; #ifdef CONFIG_SPARC64 - if (tg3_is_sun_5704(tp)) - tp->tg3_flags2 |= TG3_FLG2_SUN_5704; + if (tg3_is_sun_570X(tp)) + tp->tg3_flags2 |= TG3_FLG2_SUN_570X; #endif /* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write @@ -7453,7 +7603,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) chiprevid == CHIPREV_ID_5701_B0 || chiprevid == CHIPREV_ID_5701_B2 || chiprevid == CHIPREV_ID_5701_B5) { - unsigned long sram_base; + void __iomem *sram_base; /* Write some dummy words into the SRAM status block * area, see if it reads back correctly. If the return @@ -7472,32 +7622,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) udelay(50); tg3_nvram_init(tp); - /* Always use host TXDs, it performs better in particular - * with multi-frag packets. The tests below are kept here - * as documentation should we change this decision again - * in the future. - */ - tp->tg3_flags |= TG3_FLAG_HOST_TXDS; - -#if 0 - /* Determine if TX descriptors will reside in - * main memory or in the chip SRAM. - */ - if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) - tp->tg3_flags |= TG3_FLAG_HOST_TXDS; -#endif - grc_misc_cfg = tr32(GRC_MISC_CFG); grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK; + /* Broadcom's driver says that CIOBE multisplit has a bug */ +#if 0 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) { tp->tg3_flags |= TG3_FLAG_SPLIT_MODE; tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ; } - +#endif if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 && (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 || grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M)) @@ -7512,7 +7647,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F)) + (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F))) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; err = tg3_phy_probe(tp); @@ -7524,7 +7660,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_read_partno(tp); - if (tp->phy_id == PHY_ID_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT; } else { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) @@ -7547,13 +7683,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * upon subsystem IDs. */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && - tp->phy_id != PHY_ID_SERDES) { + !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | TG3_FLAG_USE_LINKCHG_REG); } /* For all SERDES we poll the MAC status register. */ - if (tp->phy_id == PHY_ID_SERDES) + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) tp->tg3_flags |= TG3_FLAG_POLL_SERDES; else tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; @@ -7624,7 +7760,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) mac_offset = 0x7c; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && - !(tp->tg3_flags & TG3_FLG2_SUN_5704)) { + !(tp->tg3_flags & TG3_FLG2_SUN_570X)) { if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID) mac_offset = 0xcc; if (tg3_nvram_lock(tp)) @@ -7646,7 +7782,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) dev->dev_addr[5] = (lo >> 0) & 0xff; } /* Next, try NVRAM. */ - else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) && + else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && !tg3_nvram_read(tp, mac_offset + 0, &hi) && !tg3_nvram_read(tp, mac_offset + 4, &lo)) { dev->dev_addr[0] = ((hi >> 16) & 0xff); @@ -7819,7 +7955,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) #endif if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { - tp->dma_rwctrl |= 0x001f0000; + /* DMA read watermark not used on PCIE */ + tp->dma_rwctrl |= 0x00180000; } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) @@ -7988,8 +8125,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5704: return "5704"; case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5750: return "5750"; - case PHY_ID_BCM8002: return "8002"; - case PHY_ID_SERDES: return "serdes"; + case PHY_ID_BCM8002: return "8002/serdes"; + case 0: return "serdes"; default: return "unknown"; }; } @@ -8096,6 +8233,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; + dev->features |= NETIF_F_LLTX; #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = tg3_vlan_rx_register; @@ -8141,7 +8279,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); - tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len); + tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -8234,7 +8372,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp); } @@ -8257,6 +8395,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (tp->tg3_flags2 & TG3_FLG2_IS_5788) dev->features &= ~NETIF_F_HIGHDMA; + /* flow control autonegotiation is default behavior */ + tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " @@ -8270,7 +8411,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, * of the PCI config space. We need to restore this after * GRC_MISC_CFG core clock resets and some resume events. */ - pci_save_state(tp->pdev, tp->pci_cfg_state); + pci_save_state(tp->pdev); printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", dev->name, @@ -8288,11 +8429,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] " + printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] " "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] " "TSOcap[%d] \n", dev->name, - (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0, (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, @@ -8304,7 +8444,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, return 0; err_out_iounmap: - iounmap((void *) tp->regs); + iounmap(tp->regs); err_out_free_dev: free_netdev(dev); @@ -8326,7 +8466,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) struct tg3 *tp = netdev_priv(dev); unregister_netdev(dev); - iounmap((void *)tp->regs); + iounmap(tp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -8371,11 +8511,11 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state) tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); - spin_unlock(&tp->tx_lock); - spin_unlock_irq(&tp->lock); - netif_device_attach(dev); tg3_netif_start(tp); + + spin_unlock(&tp->tx_lock); + spin_unlock_irq(&tp->lock); } return err; @@ -8390,7 +8530,7 @@ static int tg3_resume(struct pci_dev *pdev) if (!netif_running(dev)) return 0; - pci_restore_state(tp->pdev, tp->pci_cfg_state); + pci_restore_state(tp->pdev); err = tg3_set_power_state(tp, 0); if (err) @@ -8408,11 +8548,11 @@ static int tg3_resume(struct pci_dev *pdev) tg3_enable_ints(tp); + tg3_netif_start(tp); + spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); - tg3_netif_start(tp); - return 0; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 5c0c104f4..3b22f53d2 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -124,6 +124,7 @@ #define CHIPREV_ID_5705_A3 0x3003 #define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A1 0x4001 +#define CHIPREV_ID_5750_A3 0x4003 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -1435,6 +1436,7 @@ #define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100 #define NIC_SRAM_DATA_CFG_MINI_PCI 0x00001000 #define NIC_SRAM_DATA_CFG_FIBER_WOL 0x00004000 +#define NIC_SRAM_DATA_CFG_NO_GPIO2 0x00100000 #define NIC_SRAM_DATA_PHY_ID 0x00000b74 #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 @@ -1548,7 +1550,7 @@ * exist only in the cards on-chip SRAM. All 16 send bds are under * the same mode, they may not be configured individually. * - * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags. + * This driver always uses host memory TX descriptors. * * To use host memory TX descriptors: * 1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register. @@ -1988,7 +1990,7 @@ struct tg3 { spinlock_t lock; spinlock_t indirect_lock; - unsigned long regs; + void __iomem *regs; struct net_device *dev; struct pci_dev *pdev; @@ -2004,7 +2006,6 @@ struct tg3 { spinlock_t tx_lock; - /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */ struct tg3_tx_buffer_desc *tx_ring; struct tx_ring_info *tx_buffers; dma_addr_t tx_desc_mapping; @@ -2040,7 +2041,6 @@ struct tg3 { u32 rx_offset; u32 tg3_flags; -#define TG3_FLAG_HOST_TXDS 0x00000001 #define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002 #define TG3_FLAG_RX_CHECKSUMS 0x00000004 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008 @@ -2070,15 +2070,13 @@ struct tg3 { #define TG3_FLAG_JUMBO_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 -#define TG3_FLAG_PAUSE_RX 0x04000000 -#define TG3_FLAG_PAUSE_TX 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_SPLIT_MODE 0x40000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000 u32 tg3_flags2; #define TG3_FLG2_RESTART_TIMER 0x00000001 -#define TG3_FLG2_SUN_5704 0x00000002 +#define TG3_FLG2_SUN_570X 0x00000002 #define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004 #define TG3_FLG2_IS_5788 0x00000008 #define TG3_FLG2_MAX_RXPEND_64 0x00000010 @@ -2089,6 +2087,9 @@ struct tg3 { #define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_HW_AUTONEG 0x00000800 +#define TG3_FLG2_PHY_JUST_INITTED 0x00001000 +#define TG3_FLG2_PHY_SERDES 0x00002000 +#define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 @@ -2120,7 +2121,6 @@ struct tg3 { u8 pci_lat_timer; u8 pci_hdr_type; u8 pci_bist; - u32 pci_cfg_state[64 / sizeof(u32)]; int pm_cap; @@ -2136,7 +2136,6 @@ struct tg3 { #define PHY_ID_BCM5705 0x600081a0 #define PHY_ID_BCM5750 0x60008180 #define PHY_ID_BCM8002 0x60010140 -#define PHY_ID_SERDES 0xfeedbee0 #define PHY_ID_INVALID 0xffffffff #define PHY_ID_REV_MASK 0x0000000f #define PHY_REV_BCM5401_B0 0x1 @@ -2159,7 +2158,7 @@ struct tg3 { (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ - (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index a50df64b2..47d7d6d4c 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -61,12 +61,12 @@ #include #include #include +#include #include #include #include -#include #include "3c359.h" diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig index f34e40e8f..9e91287c1 100644 --- a/drivers/net/tokenring/Kconfig +++ b/drivers/net/tokenring/Kconfig @@ -84,7 +84,8 @@ config 3C359 config TMS380TR tristate "Generic TMS380 Token Ring ISA/PCI adapter support" - depends on TR && (PCI || ISA) + depends on TR && (PCI || ISA) && HOTPLUG + select FW_LOADER ---help--- This driver provides generic support for token ring adapters based on the Texas Instruments TMS380 series chipsets. This diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index 471c6a823..bd4a2bccf 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c @@ -457,14 +457,7 @@ static struct pci_driver abyss_driver = { static int __init abyss_init (void) { - int rc = pci_register_driver (&abyss_driver); - if (rc < 0) - return rc; - if (rc == 0) { - pci_unregister_driver (&abyss_driver); - return -ENODEV; - } - return 0; + return pci_register_driver(&abyss_driver); } static void __exit abyss_rmmod (void) diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 69e9246d8..8458e2135 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -895,7 +895,7 @@ static int tok_open(struct net_device *dev) ti->sram_virt &= ~1; /* to reverse what we do in tok_close */ /* init the spinlock */ - ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + spin_lock_init(&ti->lock); init_timer(&ti->tr_timer); i = tok_init_card(dev); diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index dcf7f3e8c..d90a283f3 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -120,12 +120,12 @@ #include #include #include +#include #include #include #include -#include #include "lanstreamer.h" @@ -1606,7 +1606,7 @@ static void streamer_arb_cmd(struct net_device *dev) i += 2; } - memcpy_fromio(skb_put(mac_frame, buffer_len), + memcpy(skb_put(mac_frame, buffer_len), frame_data, buffer_len); } while (next_ptr && (buff_off = next_ptr)); diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index ea82d131a..654b931ae 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -99,12 +99,12 @@ #include #include #include +#include #include #include #include -#include #include "olympic.h" @@ -221,6 +221,8 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device olympic_priv = dev->priv ; + spin_lock_init(&olympic_priv->olympic_lock) ; + init_waitqueue_head(&olympic_priv->srb_wait); init_waitqueue_head(&olympic_priv->trb_wait); #if OLYMPIC_DEBUG @@ -291,7 +293,7 @@ op_disable_dev: static int __devinit olympic_init(struct net_device *dev) { struct olympic_private *olympic_priv; - u8 *olympic_mmio, *init_srb,*adapter_addr; + u8 __iomem *olympic_mmio, *init_srb,*adapter_addr; unsigned long t; unsigned int uaa_addr; @@ -311,7 +313,6 @@ static int __devinit olympic_init(struct net_device *dev) } } - spin_lock_init(&olympic_priv->olympic_lock) ; /* Needed for cardbus */ if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) { @@ -435,13 +436,15 @@ static int __devinit olympic_init(struct net_device *dev) static int olympic_open(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; unsigned long flags, t; char open_error[255] ; int i, open_finished = 1 ; DECLARE_WAITQUEUE(wait,current) ; + olympic_init(dev); + if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) { return -EAGAIN; } @@ -706,10 +709,10 @@ static int olympic_open(struct net_device *dev) #endif if (olympic_priv->olympic_network_monitor) { - u8 *oat ; - u8 *opt ; - oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; - opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + u8 __iomem *oat ; + u8 __iomem *opt ; + oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), @@ -755,7 +758,7 @@ static int olympic_open(struct net_device *dev) static void olympic_rx(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; struct olympic_rx_status *rx_status; struct olympic_rx_desc *rx_desc ; int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len; @@ -898,7 +901,10 @@ static void olympic_freemem(struct net_device *dev) int i; for(i=0;irx_ring_skb[olympic_priv->rx_status_last_received]); + if (olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] != NULL) { + dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]); + olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] = NULL; + } if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) { pci_unmap_single(olympic_priv->pdev, le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer), @@ -925,9 +931,9 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs { struct net_device *dev= (struct net_device *)dev_id; struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; u32 sisr; - u8 *adapter_check_area ; + u8 __iomem *adapter_check_area ; /* * Read sisr but don't reset it yet. @@ -944,9 +950,6 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs /* Hotswap gives us this on removal */ if (sisr == 0xffffffff) { printk(KERN_WARNING "%s: Hotswap adapter removal.\n",dev->name) ; - olympic_freemem(dev) ; - free_irq(dev->irq, dev) ; - dev->stop = NULL ; spin_unlock(&olympic_priv->olympic_lock) ; return IRQ_NONE; } @@ -961,9 +964,7 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs printk(KERN_ERR "The adapter must be reset to clear this condition.\n") ; printk(KERN_ERR "Please report this error to the driver maintainer and/\n") ; printk(KERN_ERR "or the linux-tr mailing list.\n") ; - olympic_freemem(dev) ; - free_irq(dev->irq, dev) ; - dev->stop = NULL ; + wake_up_interruptible(&olympic_priv->srb_wait); spin_unlock(&olympic_priv->olympic_lock) ; return IRQ_HANDLED; } /* SISR_ERR */ @@ -1006,9 +1007,6 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs writel(readl(olympic_mmio+LAPWWC),olympic_mmio+LAPA); adapter_check_area = olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWC)) & (~0xf800)) ; printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; - olympic_freemem(dev) ; - free_irq(dev->irq, dev) ; - dev->stop = NULL ; spin_unlock(&olympic_priv->olympic_lock) ; return IRQ_HANDLED; } /* SISR_ADAPTER_CHECK */ @@ -1049,7 +1047,7 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; unsigned long flags ; spin_lock_irqsave(&olympic_priv->olympic_lock, flags); @@ -1080,7 +1078,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) static int olympic_close(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb; unsigned long t,flags; DECLARE_WAITQUEUE(wait,current) ; @@ -1094,34 +1092,32 @@ static int olympic_close(struct net_device *dev) writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + add_wait_queue(&olympic_priv->srb_wait,&wait) ; + set_current_state(TASK_INTERRUPTIBLE) ; + spin_lock_irqsave(&olympic_priv->olympic_lock,flags); olympic_priv->srb_queued=1; writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); - - t = jiffies ; - - add_wait_queue(&olympic_priv->srb_wait,&wait) ; - set_current_state(TASK_INTERRUPTIBLE) ; while(olympic_priv->srb_queued) { - schedule() ; + + t = schedule_timeout(60*HZ); + if(signal_pending(current)) { printk(KERN_WARNING "%s: SRB timed out.\n",dev->name); printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR)); olympic_priv->srb_queued=0; break; } - if ((jiffies-t) > 60*HZ) { + + if (t == 0) { printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ; - olympic_priv->srb_queued=0; - break ; } - set_current_state(TASK_INTERRUPTIBLE) ; + olympic_priv->srb_queued=0; } remove_wait_queue(&olympic_priv->srb_wait,&wait) ; - set_current_state(TASK_RUNNING) ; olympic_priv->rx_status_last_received++; olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; @@ -1152,9 +1148,9 @@ static int olympic_close(struct net_device *dev) static void olympic_set_rx_mode(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - u8 *olympic_mmio = olympic_priv->olympic_mmio ; + u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; u8 options = 0; - u8 *srb; + u8 __iomem *srb; struct dev_mc_list *dmi ; unsigned char dev_mc_address[4] ; int i ; @@ -1220,8 +1216,8 @@ static void olympic_set_rx_mode(struct net_device *dev) static void olympic_srb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - u8 *olympic_mmio = olympic_priv->olympic_mmio ; - u8 *srb; + u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; + u8 __iomem *srb; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); @@ -1394,22 +1390,21 @@ static int olympic_set_mac_address (struct net_device *dev, void *addr) static void olympic_arb_cmd(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; - u8 *olympic_mmio=olympic_priv->olympic_mmio; - u8 *arb_block, *asb_block, *srb ; + u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; + u8 __iomem *arb_block, *asb_block, *srb ; u8 header_len ; u16 frame_len, buffer_len ; struct sk_buff *mac_frame ; - u8 *buf_ptr ; - u8 *frame_data ; + u8 __iomem *buf_ptr ; + u8 __iomem *frame_data ; u16 buff_off ; u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ u8 fdx_prot_error ; u16 next_ptr; - int i ; - arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; - asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; - srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; + arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; + srb = (olympic_priv->olympic_lap + olympic_priv->srb) ; if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ @@ -1513,29 +1508,6 @@ drop_frame: writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL); netif_stop_queue(dev); olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; - for(i=0;irx_ring_skb[olympic_priv->rx_status_last_received]); - if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) { - pci_unmap_single(olympic_priv->pdev, - le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer), - olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE); - } - olympic_priv->rx_status_last_received++; - olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; - } - /* unmap rings */ - pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_status_ring_dma_addr, - sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE); - pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_ring_dma_addr, - sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE); - - pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_status_ring_dma_addr, - sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE); - pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr, - sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE); - - free_irq(dev->irq,dev); - dev->stop=NULL; printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; } /* If serious error */ @@ -1604,10 +1576,10 @@ drop_frame: static void olympic_asb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; - u8 *arb_block, *asb_block ; + u8 __iomem *arb_block, *asb_block ; - arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; - asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; + arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */ @@ -1666,8 +1638,8 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt { struct net_device *dev = (struct net_device *)data ; struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; - u8 *oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; - u8 *opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; int size = 0 ; int len=0; off_t begin=0; diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h index e209b79d6..2fc59c997 100644 --- a/drivers/net/tokenring/olympic.h +++ b/drivers/net/tokenring/olympic.h @@ -251,8 +251,8 @@ struct olympic_private { u16 arb; /* be16 */ u16 asb; /* be16 */ - u8 *olympic_mmio; - u8 *olympic_lap; + u8 __iomem *olympic_mmio; + u8 __iomem *olympic_lap; struct pci_dev *pdev ; char *olympic_card_name ; diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 599057ac3..1331fd1d8 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c @@ -49,9 +49,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 9d121890b..df43b449e 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -96,9 +96,9 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index b68f1957c..37ddb5c2b 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -243,14 +243,7 @@ static struct pci_driver tms_pci_driver = { static int __init tms_pci_init (void) { - int rc = pci_register_driver (&tms_pci_driver); - if (rc < 0) - return rc; - if (rc == 0) { - pci_unregister_driver (&tms_pci_driver); - return -ENODEV; - } - return 0; + return pci_register_driver(&tms_pci_driver); } static void __exit tms_pci_rmmod (void) diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 52addd8f7..5db694c4e 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -14,9 +14,9 @@ */ -#include "tulip.h" #include #include +#include "tulip.h" static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; @@ -30,8 +30,8 @@ void t21142_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); + void __iomem *ioaddr = tp->base_addr; + int csr12 = ioread32(ioaddr + CSR12); int next_tick = 60*HZ; int new_csr6 = 0; @@ -69,18 +69,18 @@ void t21142_timer(unsigned long data) if (!(csr12 & 4)) { /* 10mbps link beat good. */ new_csr6 = 0x82420000; dev->if_port = 0; - outl(0, ioaddr + CSR13); - outl(0x0003FFFF, ioaddr + CSR14); - outw(t21142_csr15[dev->if_port], ioaddr + CSR15); - outl(t21142_csr13[dev->if_port], ioaddr + CSR13); + iowrite32(0, ioaddr + CSR13); + iowrite32(0x0003FFFF, ioaddr + CSR14); + iowrite16(t21142_csr15[dev->if_port], ioaddr + CSR15); + iowrite32(t21142_csr13[dev->if_port], ioaddr + CSR13); } else { /* Select 100mbps port to check for link beat. */ new_csr6 = 0x83860000; dev->if_port = 3; - outl(0, ioaddr + CSR13); - outl(0x0003FF7F, ioaddr + CSR14); - outw(8, ioaddr + CSR15); - outl(1, ioaddr + CSR13); + iowrite32(0, ioaddr + CSR13); + iowrite32(0x0003FF7F, ioaddr + CSR14); + iowrite16(8, ioaddr + CSR15); + iowrite32(1, ioaddr + CSR13); } if (tulip_debug > 1) printk(KERN_INFO"%s: Testing new 21143 media %s.\n", @@ -88,7 +88,7 @@ void t21142_timer(unsigned long data) if (new_csr6 != (tp->csr6 & ~0x00D5)) { tp->csr6 &= 0x00D5; tp->csr6 |= new_csr6; - outl(0x0301, ioaddr + CSR12); + iowrite32(0x0301, ioaddr + CSR12); tulip_restart_rxtx(tp); } next_tick = 3*HZ; @@ -104,7 +104,7 @@ void t21142_timer(unsigned long data) void t21142_start_nway(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int csr14 = ((tp->sym_advertise & 0x0780) << 9) | ((tp->sym_advertise & 0x0020) << 1) | 0xffbf; @@ -114,17 +114,17 @@ void t21142_start_nway(struct net_device *dev) if (tulip_debug > 1) printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%8.8x.\n", dev->name, csr14); - outl(0x0001, ioaddr + CSR13); + iowrite32(0x0001, ioaddr + CSR13); udelay(100); - outl(csr14, ioaddr + CSR14); + iowrite32(csr14, ioaddr + CSR14); tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0); - outl(tp->csr6, ioaddr + CSR6); + iowrite32(tp->csr6, ioaddr + CSR6); if (tp->mtable && tp->mtable->csr15dir) { - outl(tp->mtable->csr15dir, ioaddr + CSR15); - outl(tp->mtable->csr15val, ioaddr + CSR15); + iowrite32(tp->mtable->csr15dir, ioaddr + CSR15); + iowrite32(tp->mtable->csr15val, ioaddr + CSR15); } else - outw(0x0008, ioaddr + CSR15); - outl(0x1301, ioaddr + CSR12); /* Trigger NWAY. */ + iowrite16(0x0008, ioaddr + CSR15); + iowrite32(0x1301, ioaddr + CSR12); /* Trigger NWAY. */ } @@ -132,12 +132,12 @@ void t21142_start_nway(struct net_device *dev) void t21142_lnk_change(struct net_device *dev, int csr5) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int csr12 = inl(ioaddr + CSR12); + void __iomem *ioaddr = tp->base_addr; + int csr12 = ioread32(ioaddr + CSR12); if (tulip_debug > 1) printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, " - "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14)); + "%8.8x.\n", dev->name, csr12, csr5, ioread32(ioaddr + CSR14)); /* If NWay finished and we have a negotiated partner capability. */ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { @@ -183,19 +183,19 @@ void t21142_lnk_change(struct net_device *dev, int csr5) tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff); if (tp->full_duplex) tp->csr6 |= 0x0200; - outl(1, ioaddr + CSR13); + iowrite32(1, ioaddr + CSR13); } #if 0 /* Restart shouldn't be needed. */ - outl(tp->csr6 | RxOn, ioaddr + CSR6); + iowrite32(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", - dev->name, inl(ioaddr + CSR5)); + dev->name, ioread32(ioaddr + CSR5)); #endif tulip_start_rxtx(tp); 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)); + dev->name, tp->csr6, ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); } else if ((tp->nwayset && (csr5 & 0x08000000) && (dev->if_port == 3 || dev->if_port == 5) && (csr12 & 2) == 2) || @@ -216,7 +216,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5) tp->timer.expires = RUN_AT(3*HZ); add_timer(&tp->timer); } else if (dev->if_port == 5) - outl(inl(ioaddr + CSR14) & ~0x080, ioaddr + CSR14); + iowrite32(ioread32(ioaddr + CSR14) & ~0x080, ioaddr + CSR14); } else if (dev->if_port == 0 || dev->if_port == 4) { if ((csr12 & 4) == 0) printk(KERN_INFO"%s: 21143 10baseT link beat good.\n", @@ -236,8 +236,8 @@ void t21142_lnk_change(struct net_device *dev, int csr5) dev->name); dev->if_port = 3; tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff); - outl(0x0003FF7F, ioaddr + CSR14); - outl(0x0301, ioaddr + CSR12); + iowrite32(0x0003FF7F, ioaddr + CSR14); + iowrite32(0x0301, ioaddr + CSR12); tulip_restart_rxtx(tp); } } diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 6182cf4e3..e2cdaf876 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -40,9 +40,7 @@ config TULIP (smc9332dst), you can also try the driver for "Generic DECchip" cards, above. However, most people with a network card of this type will say Y here.) Do read the Ethernet-HOWTO, available from - . More specific - information is contained in - . + . To compile this driver as a module, choose M here and read . The module will diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 71fc3d084..bd46f7d4c 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -287,7 +287,7 @@ struct de_private { unsigned tx_tail; unsigned rx_tail; - void *regs; + void __iomem *regs; struct net_device *dev; spinlock_t lock; @@ -1208,8 +1208,7 @@ static void de_adapter_wake (struct de_private *de) pci_write_config_dword(de->pdev, PCIPM, pmctl); /* de4x5.c delays, so we do too */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(msecs_to_jiffies(10)); + msleep(10); } } @@ -1735,11 +1734,11 @@ static void __init de21040_get_media_info(struct de_private *de) } /* Note: this routine returns extra data bits for size detection. */ -static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len) +static unsigned __init tulip_read_eeprom(void __iomem *regs, int location, int addr_len) { int i; unsigned retval = 0; - void *ee_addr = regs + ROMCmd; + void __iomem *ee_addr = regs + ROMCmd; int read_cmd = location | (EE_READ_CMD << addr_len); writel(EE_ENB & ~EE_CS, ee_addr); @@ -1932,7 +1931,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, struct net_device *dev; struct de_private *de; int rc; - void *regs; + void __iomem *regs; long pciaddr; static int board_idx = -1; diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 962138008..5160ef2da 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -467,8 +467,8 @@ #include #include #include +#include -#include #include #include #include @@ -1141,7 +1141,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) lp->asBitValid = TRUE; lp->timeout = -1; lp->gendev = gendev; - lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->lock); init_timer(&lp->timer); de4x5_parse_params(dev); @@ -1316,7 +1316,7 @@ de4x5_open(struct net_device *dev) ** Re-initialize the DE4X5... */ status = de4x5_init(dev); - lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + spin_lock_init(&lp->lock); lp->state = OPEN; de4x5_dbg_open(dev); @@ -2242,8 +2242,13 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, return -ENODEV; /* Ok, the device seems to be for us. */ - if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) - return -ENOMEM; + if ((error = pci_enable_device (pdev))) + return error; + + if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) { + error = -ENOMEM; + goto disable_dev; + } lp = netdev_priv(dev); lp->bus = PCI; @@ -2327,6 +2332,8 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, release_region (iobase, DE4X5_PCI_TOTAL_SIZE); free_dev: free_netdev (dev); + disable_dev: + pci_disable_device (pdev); return error; } @@ -2341,6 +2348,7 @@ static void __devexit de4x5_pci_remove (struct pci_dev *pdev) unregister_netdev (dev); free_netdev (dev); release_region (iobase, DE4X5_PCI_TOTAL_SIZE); + pci_disable_device (pdev); } static struct pci_device_id de4x5_pci_tbl[] = { @@ -5081,7 +5089,7 @@ mii_get_phy(struct net_device *dev) lp->useMII = TRUE; /* Search the MII address space for possible PHY devices */ - for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) { + for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) { lp->phy[lp->active].addr = i; if (i==0) n++; /* Count cycles */ while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */ diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index f3298d161..e64938e61 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -86,12 +86,13 @@ #include #include #include +#include #include -#include #include #include #include +#include /* Board/System/Debug information/definition ---------------- */ @@ -314,13 +315,13 @@ static u16 phy_read_1bit(unsigned long); static u8 dmfe_sense_speed(struct dmfe_board_info *); static void dmfe_process_mode(struct dmfe_board_info *); static void dmfe_timer(unsigned long); +static inline u32 cal_CRC(unsigned char *, unsigned int, u8); static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *); static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *); static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *); static void dmfe_dynamic_reset(struct DEVICE *); static void dmfe_free_rxbuffer(struct dmfe_board_info *); static void dmfe_init_dm910x(struct DEVICE *); -static inline u32 cal_CRC(unsigned char *, unsigned int, u8); static void dmfe_parse_srom(struct dmfe_board_info *); static void dmfe_program_DM9801(struct dmfe_board_info *, int); static void dmfe_program_DM9802(struct dmfe_board_info *); @@ -884,6 +885,20 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db) } +/* + * Calculate the CRC valude of the Rx packet + * flag = 1 : return the reverse CRC (for the received packet CRC) + * 0 : return the normal CRC (for Hash Table index) + */ + +static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) +{ + u32 crc = crc32(~0, Data, Len); + if (flag) crc = ~crc; + return crc; +} + + /* * Receive the come packet and pass to upper layer */ @@ -1773,20 +1788,6 @@ static u16 phy_read_1bit(unsigned long ioaddr) } -/* - * Calculate the CRC valude of the Rx packet - * flag = 1 : return the reverse CRC (for the received packet CRC) - * 0 : return the normal CRC (for Hash Table index) - */ - -static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) -{ - u32 crc = crc32(~0, Data, Len); - if (flag) crc = ~crc; - return crc; -} - - /* * Parser SROM and media mode */ diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 512debab8..ac5bf49ff 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -14,6 +14,7 @@ */ +#include #include "tulip.h" #include #include @@ -312,7 +313,7 @@ subsequent_board: /* Delay between EEPROM clock transitions. Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. We add a bus turn-around to insure that this remains true. */ -#define eeprom_delay() inl(ee_addr) +#define eeprom_delay() ioread32(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ #define EE_READ_CMD (6) @@ -323,34 +324,34 @@ int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_l int i; unsigned retval = 0; struct tulip_private *tp = dev->priv; - long ee_addr = tp->base_addr + CSR9; + void __iomem *ee_addr = tp->base_addr + CSR9; int read_cmd = location | (EE_READ_CMD << addr_len); - outl(EE_ENB & ~EE_CS, ee_addr); - outl(EE_ENB, ee_addr); + iowrite32(EE_ENB & ~EE_CS, ee_addr); + iowrite32(EE_ENB, ee_addr); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outl(EE_ENB | dataval, ee_addr); + iowrite32(EE_ENB | dataval, ee_addr); eeprom_delay(); - outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(); - retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); + retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0); } - outl(EE_ENB, ee_addr); + iowrite32(EE_ENB, ee_addr); eeprom_delay(); for (i = 16; i > 0; i--) { - outl(EE_ENB | EE_SHIFT_CLK, ee_addr); + iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr); eeprom_delay(); - retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); - outl(EE_ENB, ee_addr); + retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0); + iowrite32(EE_ENB, ee_addr); eeprom_delay(); } /* Terminate the EEPROM access. */ - outl(EE_ENB & ~EE_CS, ee_addr); + iowrite32(EE_ENB & ~EE_CS, ee_addr); return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval; } diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index f86170e9b..7650fd97c 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -14,10 +14,10 @@ */ +#include #include "tulip.h" #include #include -#include int tulip_rx_copybreak; unsigned int tulip_max_interrupt_work; @@ -89,11 +89,11 @@ int tulip_refill_rx(struct net_device *dev) tp->rx_ring[entry].status = cpu_to_le32(DescOwned); } if(tp->chip_id == LC82C168) { - if(((inl(dev->base_addr + CSR5)>>17)&0x07) == 4) { + if(((ioread32(tp->base_addr + CSR5)>>17)&0x07) == 4) { /* Rx stopped due to out of buffers, * restart it */ - outl(0x01, dev->base_addr + CSR2); + iowrite32(0x01, tp->base_addr + CSR2); } } return refilled; @@ -133,12 +133,12 @@ int tulip_poll(struct net_device *dev, int *budget) tp->rx_ring[entry].status); do { - if (inl(dev->base_addr + CSR5) == 0xffffffff) { + if (ioread32(tp->base_addr + CSR5) == 0xffffffff) { printk(KERN_DEBUG " In tulip_poll(), hardware disappeared.\n"); break; } /* Acknowledge current RX interrupt sources. */ - outl((RxIntr | RxNoBuf), dev->base_addr + CSR5); + iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5); /* If we own the next entry, it is a new packet. Send it up. */ @@ -258,7 +258,7 @@ int tulip_poll(struct net_device *dev, int *budget) * No idea how to fix this if "playing with fire" will fail * tomorrow (night 011029). If it will not fail, we won * finally: amount of IO did not increase at all. */ - } while ((inl(dev->base_addr + CSR5) & RxIntr)); + } while ((ioread32(tp->base_addr + CSR5) & RxIntr)); done: @@ -285,13 +285,13 @@ done: if( received > 1 ) { if( ! tp->mit_on ) { tp->mit_on = 1; - outl(mit_table[MIT_TABLE], dev->base_addr + CSR11); + iowrite32(mit_table[MIT_TABLE], tp->base_addr + CSR11); } } else { if( tp->mit_on ) { tp->mit_on = 0; - outl(0, dev->base_addr + CSR11); + iowrite32(0, tp->base_addr + CSR11); } } } @@ -309,7 +309,7 @@ done: /* Remove us from polling list and enable RX intr. */ netif_rx_complete(dev); - outl(tulip_tbl[tp->chip_id].valid_intrs, dev->base_addr+CSR7); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); /* The last op happens after poll completion. Which means the following: * 1. it can race with disabling irqs in irq handler @@ -474,19 +474,19 @@ static int tulip_rx(struct net_device *dev) static inline unsigned int phy_interrupt (struct net_device *dev) { #ifdef __hppa__ - int csr12 = inl(dev->base_addr + CSR12) & 0xff; struct tulip_private *tp = netdev_priv(dev); + int csr12 = ioread32(tp->base_addr + CSR12) & 0xff; if (csr12 != tp->csr12_shadow) { /* ack interrupt */ - outl(csr12 | 0x02, dev->base_addr + CSR12); + iowrite32(csr12 | 0x02, tp->base_addr + CSR12); tp->csr12_shadow = csr12; /* do link change stuff */ spin_lock(&tp->lock); tulip_check_duplex(dev); spin_unlock(&tp->lock); /* clear irq ack bit */ - outl(csr12 & ~0x02, dev->base_addr + CSR12); + iowrite32(csr12 & ~0x02, tp->base_addr + CSR12); return 1; } @@ -501,7 +501,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_instance; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int csr5; int missed; int rx = 0; @@ -519,7 +519,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) unsigned int handled = 0; /* Let's see whether the interrupt really is for us */ - csr5 = inl(ioaddr + CSR5); + csr5 = ioread32(ioaddr + CSR5); if (tp->flags & HAS_PHY_IRQ) handled = phy_interrupt (dev); @@ -536,7 +536,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (!rxd && (csr5 & (RxIntr | RxNoBuf))) { rxd++; /* Mask RX intrs and add the device to poll list. */ - outl(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); netif_rx_schedule(dev); if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) @@ -546,11 +546,11 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) /* Acknowledge the interrupt sources we handle here ASAP the poll function does Rx and RxNoBuf acking */ - outl(csr5 & 0x0001ff3f, ioaddr + CSR5); + iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5); #else /* Acknowledge all of the current interrupt sources ASAP. */ - outl(csr5 & 0x0001ffff, ioaddr + CSR5); + iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5); if (csr5 & (RxIntr | RxNoBuf)) { @@ -562,7 +562,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (tulip_debug > 4) printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", - dev->name, csr5, inl(dev->base_addr + CSR5)); + dev->name, csr5, ioread32(ioaddr + CSR5)); if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { @@ -637,7 +637,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (tulip_debug > 2) printk(KERN_WARNING "%s: The transmitter stopped." " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", - dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); + dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6); tulip_restart_rxtx(tp); } spin_unlock(&tp->lock); @@ -655,16 +655,16 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) tp->csr6 |= 0x00200000; /* Store-n-forward. */ /* Restart the transmit process. */ tulip_restart_rxtx(tp); - outl(0, ioaddr + CSR1); + iowrite32(0, ioaddr + CSR1); } if (csr5 & (RxDied | RxNoBuf)) { if (tp->flags & COMET_MAC_ADDR) { - outl(tp->mc_filter[0], ioaddr + 0xAC); - outl(tp->mc_filter[1], ioaddr + 0xB0); + iowrite32(tp->mc_filter[0], ioaddr + 0xAC); + iowrite32(tp->mc_filter[1], ioaddr + 0xB0); } } if (csr5 & RxDied) { /* Missed a Rx frame. */ - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; + tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; tp->stats.rx_errors++; tulip_start_rxtx(tp); } @@ -692,7 +692,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) dev->name, tp->nir, error); } /* Clear all error sources, included undocumented ones! */ - outl(0x0800f7ba, ioaddr + CSR5); + iowrite32(0x0800f7ba, ioaddr + CSR5); oi++; } if (csr5 & TimerInt) { @@ -700,7 +700,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (tulip_debug > 2) printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n", dev->name, csr5); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); tp->ttimer = 0; oi++; } @@ -710,20 +710,20 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi); /* Acknowledge all interrupt sources. */ - outl(0x8001ffff, ioaddr + CSR5); + iowrite32(0x8001ffff, ioaddr + CSR5); if (tp->flags & HAS_INTR_MITIGATION) { /* Josip Loncaric at ICASE did extensive experimentation to develop a good interrupt mitigation setting.*/ - outl(0x8b240000, ioaddr + CSR11); + iowrite32(0x8b240000, ioaddr + CSR11); } else if (tp->chip_id == LC82C168) { /* the LC82C168 doesn't have a hw timer.*/ - outl(0x00, ioaddr + CSR7); + iowrite32(0x00, ioaddr + CSR7); mod_timer(&tp->timer, RUN_AT(HZ/50)); } else { /* Mask all interrupting sources, set timer to re-enable. */ - outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); - outl(0x0012, ioaddr + CSR11); + iowrite32(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); + iowrite32(0x0012, ioaddr + CSR11); } break; } @@ -732,7 +732,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (work_count == 0) break; - csr5 = inl(ioaddr + CSR5); + csr5 = ioread32(ioaddr + CSR5); #ifdef CONFIG_TULIP_NAPI if (rxd) @@ -758,29 +758,29 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (tulip_debug > 1) printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx); if (tp->chip_id == LC82C168) { - outl(0x00, ioaddr + CSR7); + iowrite32(0x00, ioaddr + CSR7); mod_timer(&tp->timer, RUN_AT(HZ/50)); } else { - if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) { + if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) { if (tulip_debug > 1) printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir); - outl(tulip_tbl[tp->chip_id].valid_intrs | TimerInt, + iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt, ioaddr + CSR7); - outl(TimerInt, ioaddr + CSR5); - outl(12, ioaddr + CSR11); + iowrite32(TimerInt, ioaddr + CSR5); + iowrite32(12, ioaddr + CSR11); tp->ttimer = 1; } } } #endif /* CONFIG_TULIP_NAPI */ - if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) { + if ((missed = ioread32(ioaddr + CSR8) & 0x1ffff)) { tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed; } if (tulip_debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, inl(ioaddr + CSR5)); + dev->name, ioread32(ioaddr + CSR5)); return IRQ_HANDLED; } diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index 35f2989fa..0b914b46b 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -18,13 +18,14 @@ #include #include #include +#include #include "tulip.h" /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back PCI I/O cycles, but we insert a delay to avoid "overclocking" issues or future 66Mhz PCI. */ -#define mdio_delay() inl(mdio_addr) +#define mdio_delay() ioread32(mdio_addr) /* Read and write the MII registers using software-generated serial MDIO protocol. It is just different enough from the EEPROM protocol @@ -52,8 +53,8 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location) int i; int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location; int retval = 0; - long ioaddr = dev->base_addr; - long mdio_addr = ioaddr + CSR9; + void __iomem *ioaddr = tp->base_addr; + void __iomem *mdio_addr = ioaddr + CSR9; unsigned long flags; if (location & ~0x1f) @@ -61,19 +62,19 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location) if (tp->chip_id == COMET && phy_id == 30) { if (comet_miireg2offset[location]) - return inl(ioaddr + comet_miireg2offset[location]); + return ioread32(ioaddr + comet_miireg2offset[location]); return 0xffff; } spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) { int i = 1000; - outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); - inl(ioaddr + 0xA0); - inl(ioaddr + 0xA0); + iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); + ioread32(ioaddr + 0xA0); + ioread32(ioaddr + 0xA0); while (--i > 0) { barrier(); - if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000)) + if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000)) break; } spin_unlock_irqrestore(&tp->mii_lock, flags); @@ -82,26 +83,26 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location) /* Establish sync by sending at least 32 logic ones. */ for (i = 32; i >= 0; i--) { - outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); mdio_delay(); - outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - outl(MDIO_ENB | dataval, mdio_addr); + iowrite32(MDIO_ENB | dataval, mdio_addr); mdio_delay(); - outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { - outl(MDIO_ENB_IN, mdio_addr); + iowrite32(MDIO_ENB_IN, mdio_addr); mdio_delay(); - retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } @@ -114,8 +115,8 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) struct tulip_private *tp = netdev_priv(dev); int i; int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff); - long ioaddr = dev->base_addr; - long mdio_addr = ioaddr + CSR9; + void __iomem *ioaddr = tp->base_addr; + void __iomem *mdio_addr = ioaddr + CSR9; unsigned long flags; if (location & ~0x1f) @@ -123,17 +124,17 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) if (tp->chip_id == COMET && phy_id == 30) { if (comet_miireg2offset[location]) - outl(val, ioaddr + comet_miireg2offset[location]); + iowrite32(val, ioaddr + comet_miireg2offset[location]); return; } spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) { int i = 1000; - outl(cmd, ioaddr + 0xA0); + iowrite32(cmd, ioaddr + 0xA0); do { barrier(); - if ( ! (inl(ioaddr + 0xA0) & 0x80000000)) + if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000)) break; } while (--i > 0); spin_unlock_irqrestore(&tp->mii_lock, flags); @@ -142,24 +143,24 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) /* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) { - outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); mdio_delay(); - outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - outl(MDIO_ENB | dataval, mdio_addr); + iowrite32(MDIO_ENB | dataval, mdio_addr); mdio_delay(); - outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - outl(MDIO_ENB_IN, mdio_addr); + iowrite32(MDIO_ENB_IN, mdio_addr); mdio_delay(); - outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } @@ -170,8 +171,8 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val) /* Set up the transceiver control registers for the selected media type. */ void tulip_select_media(struct net_device *dev, int startup) { - long ioaddr = dev->base_addr; struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; struct mediatable *mtable = tp->mtable; u32 new_csr6; int i; @@ -187,8 +188,8 @@ void tulip_select_media(struct net_device *dev, int startup) dev->name, p[1]); dev->if_port = p[0]; if (startup) - outl(mtable->csr12dir | 0x100, ioaddr + CSR12); - outl(p[1], ioaddr + CSR12); + iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); + iowrite32(p[1], ioaddr + CSR12); new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); break; case 2: case 4: { @@ -208,7 +209,7 @@ void tulip_select_media(struct net_device *dev, int startup) printk(KERN_DEBUG "%s: Resetting the transceiver.\n", dev->name); for (i = 0; i < rst[0]; i++) - outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); + iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } if (tulip_debug > 1) printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control " @@ -219,11 +220,11 @@ void tulip_select_media(struct net_device *dev, int startup) csr14val = setup[1]; csr15dir = (setup[3]<<16) | setup[2]; csr15val = (setup[4]<<16) | setup[2]; - outl(0, ioaddr + CSR13); - outl(csr14val, ioaddr + CSR14); - outl(csr15dir, ioaddr + CSR15); /* Direction */ - outl(csr15val, ioaddr + CSR15); /* Data */ - outl(csr13val, ioaddr + CSR13); + iowrite32(0, ioaddr + CSR13); + iowrite32(csr14val, ioaddr + CSR14); + iowrite32(csr15dir, ioaddr + CSR15); /* Direction */ + iowrite32(csr15val, ioaddr + CSR15); /* Data */ + iowrite32(csr13val, ioaddr + CSR13); } else { csr13val = 1; csr14val = 0; @@ -232,12 +233,12 @@ void tulip_select_media(struct net_device *dev, int startup) if (dev->if_port <= 4) csr14val = t21142_csr14[dev->if_port]; if (startup) { - outl(0, ioaddr + CSR13); - outl(csr14val, ioaddr + CSR14); + iowrite32(0, ioaddr + CSR13); + iowrite32(csr14val, ioaddr + CSR14); } - outl(csr15dir, ioaddr + CSR15); /* Direction */ - outl(csr15val, ioaddr + CSR15); /* Data */ - if (startup) outl(csr13val, ioaddr + CSR13); + iowrite32(csr15dir, ioaddr + CSR15); /* Direction */ + iowrite32(csr15val, ioaddr + CSR15); /* Data */ + if (startup) iowrite32(csr13val, ioaddr + CSR13); } if (tulip_debug > 1) printk(KERN_DEBUG "%s: Setting CSR15 to %8.8x/%8.8x.\n", @@ -262,21 +263,21 @@ void tulip_select_media(struct net_device *dev, int startup) misc_info = reset_sequence + reset_length; if (startup) for (i = 0; i < reset_length; i++) - outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); + iowrite32(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); for (i = 0; i < init_length; i++) - outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); + iowrite32(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); } else { u8 *init_sequence = p + 2; u8 *reset_sequence = p + 3 + init_length; int reset_length = p[2 + init_length]; misc_info = (u16*)(reset_sequence + reset_length); if (startup) { - outl(mtable->csr12dir | 0x100, ioaddr + CSR12); + iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); for (i = 0; i < reset_length; i++) - outl(reset_sequence[i], ioaddr + CSR12); + iowrite32(reset_sequence[i], ioaddr + CSR12); } for (i = 0; i < init_length; i++) - outl(init_sequence[i], ioaddr + CSR12); + iowrite32(init_sequence[i], ioaddr + CSR12); } tmp_info = get_u16(&misc_info[1]); if (tmp_info) @@ -306,7 +307,7 @@ void tulip_select_media(struct net_device *dev, int startup) printk(KERN_DEBUG "%s: Resetting the transceiver.\n", dev->name); for (i = 0; i < rst[0]; i++) - outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); + iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } break; @@ -319,32 +320,32 @@ void tulip_select_media(struct net_device *dev, int startup) if (tulip_debug > 1) printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n", dev->name, medianame[dev->if_port], - inl(ioaddr + CSR12) & 0xff); + ioread32(ioaddr + CSR12) & 0xff); } else if (tp->chip_id == LC82C168) { if (startup && ! tp->medialock) dev->if_port = tp->mii_cnt ? 11 : 0; if (tulip_debug > 1) printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s.\n", - dev->name, inl(ioaddr + 0xB8), medianame[dev->if_port]); + dev->name, ioread32(ioaddr + 0xB8), medianame[dev->if_port]); if (tp->mii_cnt) { new_csr6 = 0x810C0000; - outl(0x0001, ioaddr + CSR15); - outl(0x0201B07A, ioaddr + 0xB8); + iowrite32(0x0001, ioaddr + CSR15); + iowrite32(0x0201B07A, ioaddr + 0xB8); } else if (startup) { /* Start with 10mbps to do autonegotiation. */ - outl(0x32, ioaddr + CSR12); + iowrite32(0x32, ioaddr + CSR12); new_csr6 = 0x00420000; - outl(0x0001B078, ioaddr + 0xB8); - outl(0x0201B078, ioaddr + 0xB8); + iowrite32(0x0001B078, ioaddr + 0xB8); + iowrite32(0x0201B078, ioaddr + 0xB8); } else if (dev->if_port == 3 || dev->if_port == 5) { - outl(0x33, ioaddr + CSR12); + iowrite32(0x33, ioaddr + CSR12); new_csr6 = 0x01860000; /* Trigger autonegotiation. */ - outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8); + iowrite32(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8); } else { - outl(0x32, ioaddr + CSR12); + iowrite32(0x32, ioaddr + CSR12); new_csr6 = 0x00420000; - outl(0x1F078, ioaddr + 0xB8); + iowrite32(0x1F078, ioaddr + 0xB8); } } else { /* Unknown chip type with no media table. */ if (tp->default_port == 0) @@ -359,7 +360,7 @@ void tulip_select_media(struct net_device *dev, int startup) printk(KERN_DEBUG "%s: No media description table, assuming " "%s transceiver, CSR12 %2.2x.\n", dev->name, medianame[dev->if_port], - inl(ioaddr + CSR12)); + ioread32(ioaddr + CSR12)); } tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index 1a0943c68..d9980bde7 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -15,14 +15,15 @@ */ #include +#include #include "tulip.h" void pnic_do_nway(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; - u32 phy_reg = inl(ioaddr + 0xB8); + void __iomem *ioaddr = tp->base_addr; + u32 phy_reg = ioread32(ioaddr + 0xB8); u32 new_csr6 = tp->csr6 & ~0x40C40200; if (phy_reg & 0x78000000) { /* Ignore baseT4 */ @@ -32,9 +33,9 @@ void pnic_do_nway(struct net_device *dev) else if (phy_reg & 0x08000000) dev->if_port = 0; tp->nwayset = 1; new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000; - outl(0x32 | (dev->if_port & 1), ioaddr + CSR12); + iowrite32(0x32 | (dev->if_port & 1), ioaddr + CSR12); if (dev->if_port & 1) - outl(0x1F868, ioaddr + 0xB8); + iowrite32(0x1F868, ioaddr + 0xB8); if (phy_reg & 0x30000000) { tp->full_duplex = 1; new_csr6 |= 0x00000200; @@ -54,14 +55,14 @@ void pnic_do_nway(struct net_device *dev) void pnic_lnk_change(struct net_device *dev, int csr5) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int phy_reg = inl(ioaddr + 0xB8); + void __iomem *ioaddr = tp->base_addr; + int phy_reg = ioread32(ioaddr + 0xB8); if (tulip_debug > 1) printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n", dev->name, phy_reg, csr5); - if (inl(ioaddr + CSR5) & TPLnkFail) { - outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); + if (ioread32(ioaddr + CSR5) & TPLnkFail) { + iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); /* If we use an external MII, then we mustn't use the * internal negotiation. */ @@ -69,12 +70,12 @@ void pnic_lnk_change(struct net_device *dev, int csr5) return; if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); - outl(tp->csr6, ioaddr + CSR6); - outl(0x30, ioaddr + CSR12); - outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ + iowrite32(tp->csr6, ioaddr + CSR6); + iowrite32(0x30, ioaddr + CSR12); + iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ dev->trans_start = jiffies; } - } else if (inl(ioaddr + CSR5) & TPLnkPass) { + } else if (ioread32(ioaddr + CSR5) & TPLnkPass) { if (tulip_media_cap[dev->if_port] & MediaIsMII) { spin_lock(&tp->lock); tulip_check_duplex(dev); @@ -82,7 +83,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5) } else { pnic_do_nway(dev); } - outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); + iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); } } @@ -90,10 +91,10 @@ void pnic_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int next_tick = 60*HZ; - if(!inl(ioaddr + CSR7)) { + if(!ioread32(ioaddr + CSR7)) { /* the timer was called due to a work overflow * in the interrupt handler. Skip the connection * checks, the nic is definitively speaking with @@ -108,17 +109,17 @@ void pnic_timer(unsigned long data) next_tick = 3*HZ; spin_unlock_irq(&tp->lock); } else { - int csr12 = inl(ioaddr + CSR12); + int csr12 = ioread32(ioaddr + CSR12); int new_csr6 = tp->csr6 & ~0x40C40200; - int phy_reg = inl(ioaddr + 0xB8); - int csr5 = inl(ioaddr + CSR5); + int phy_reg = ioread32(ioaddr + 0xB8); + int csr5 = ioread32(ioaddr + CSR5); if (tulip_debug > 1) printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s " "CSR5 %8.8x.\n", dev->name, phy_reg, medianame[dev->if_port], csr5); if (phy_reg & 0x04000000) { /* Remote link fault */ - outl(0x0201F078, ioaddr + 0xB8); + iowrite32(0x0201F078, ioaddr + 0xB8); next_tick = 1*HZ; tp->nwayset = 0; } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */ @@ -129,21 +130,21 @@ void pnic_timer(unsigned long data) printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " "CSR5 %8.8x, PHY %3.3x.\n", dev->name, medianame[dev->if_port], csr12, - inl(ioaddr + CSR5), inl(ioaddr + 0xB8)); + ioread32(ioaddr + CSR5), ioread32(ioaddr + 0xB8)); next_tick = 3*HZ; if (tp->medialock) { } else if (tp->nwayset && (dev->if_port & 1)) { next_tick = 1*HZ; } else if (dev->if_port == 0) { dev->if_port = 3; - outl(0x33, ioaddr + CSR12); + iowrite32(0x33, ioaddr + CSR12); new_csr6 = 0x01860000; - outl(0x1F868, ioaddr + 0xB8); + iowrite32(0x1F868, ioaddr + 0xB8); } else { dev->if_port = 0; - outl(0x32, ioaddr + CSR12); + iowrite32(0x32, ioaddr + CSR12); new_csr6 = 0x00420000; - outl(0x1F078, ioaddr + 0xB8); + iowrite32(0x1F078, ioaddr + 0xB8); } if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; @@ -160,12 +161,12 @@ void pnic_timer(unsigned long data) } too_good_connection: mod_timer(&tp->timer, RUN_AT(next_tick)); - if(!inl(ioaddr + CSR7)) { + if(!ioread32(ioaddr + CSR7)) { if (tulip_debug > 1) printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name); disable_irq(dev->irq); tulip_refill_rx(dev); enable_irq(dev->irq); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); } } diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index f28a99df7..55f4a9a63 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -76,8 +76,8 @@ -#include "tulip.h" #include +#include "tulip.h" #include @@ -85,12 +85,12 @@ void pnic2_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->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)); + dev->name,ioread32(ioaddr + CSR12)); if (next_tick) { mod_timer(&tp->timer, RUN_AT(next_tick)); @@ -101,7 +101,7 @@ void pnic2_timer(unsigned long data) void pnic2_start_nway(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int csr14; int csr12; @@ -110,7 +110,7 @@ void pnic2_start_nway(struct net_device *dev) /* load in csr14 and mask off bits not to touch * comment at top of file explains mask value */ - csr14 = (inl(ioaddr + CSR14) & 0xfff0ee39); + csr14 = (ioread32(ioaddr + CSR14) & 0xfff0ee39); /* bit 17 - advetise 100baseTx-FD */ if (tp->sym_advertise & 0x0100) csr14 |= 0x00020000; @@ -137,7 +137,7 @@ void pnic2_start_nway(struct net_device *dev) /* now we have to set up csr6 for NWAY state */ - tp->csr6 = inl(ioaddr + CSR6); + tp->csr6 = ioread32(ioaddr + CSR6); if (tulip_debug > 1) printk(KERN_DEBUG "%s: On Entry to Nway, " "csr6=%8.8x.\n", dev->name, tp->csr6); @@ -156,8 +156,8 @@ void pnic2_start_nway(struct net_device *dev) * and "Stop" - reset both Transmit (bit 13) and Receive (bit 1) */ tp->csr6 |= 0x01000000; - outl(csr14, ioaddr + CSR14); - outl(tp->csr6, ioaddr + CSR6); + iowrite32(csr14, ioaddr + CSR14); + iowrite32(tp->csr6, ioaddr + CSR6); udelay(100); /* all set up so now force the negotiation to begin */ @@ -166,9 +166,9 @@ void pnic2_start_nway(struct net_device *dev) * Autonegotiation bits 14:12. Writing a 001 to those bits * should start the autonegotiation */ - csr12 = (inl(ioaddr + CSR12) & 0xffff8fff); + csr12 = (ioread32(ioaddr + CSR12) & 0xffff8fff); csr12 |= 0x1000; - outl(csr12, ioaddr + CSR12); + iowrite32(csr12, ioaddr + CSR12); } @@ -176,16 +176,16 @@ void pnic2_start_nway(struct net_device *dev) void pnic2_lnk_change(struct net_device *dev, int csr5) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int csr14; /* read the staus register to find out what is up */ - int csr12 = inl(ioaddr + CSR12); + int csr12 = ioread32(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)); + csr5, ioread32(ioaddr + CSR14)); /* If NWay finished and we have a negotiated partner capability. * check bits 14:12 for bit pattern 101 - all is good @@ -243,8 +243,8 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) * 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); + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(csr14,ioaddr + CSR14); /* now set the data port and operating mode @@ -255,7 +255,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* get current csr6 and mask off bits not to touch */ /* see comment at top of file */ - tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); + tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); /* so if using if_port 3 or 5 then select the 100baseT * port else select the 10baseT port. @@ -269,12 +269,12 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* now set the full duplex bit appropriately */ if (tp->full_duplex) tp->csr6 |= 0x00000200; - outl(1, ioaddr + CSR13); + iowrite32(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)); + ioread32(ioaddr + CSR6), ioread32(ioaddr + CSR12)); /* now the following actually writes out the * new csr6 values @@ -291,8 +291,8 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* remember to turn off bit 7 - autonegotiate * enable so we don't forget */ - csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); - outl(csr14,ioaddr + CSR14); + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(csr14,ioaddr + CSR14); /* what should we do when autonegotiate fails? * should we try again or default to baseline @@ -308,7 +308,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* set to 10baseTx-HD - see Data Port Selection * comment given at the top of the file */ - tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); + tp->csr6 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); tp->csr6 |= 0x00400000; tulip_restart_rxtx(tp); @@ -393,13 +393,13 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) dev->if_port = 0; /* make sure autonegotiate enable is off */ - csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); - outl(csr14,ioaddr + CSR14); + csr14 = (ioread32(ioaddr + CSR14) & 0xffffff7f); + iowrite32(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 = (ioread32(ioaddr + CSR6) & 0xfe3bd1fd); tp->csr6 |= 0x00400000; tulip_restart_rxtx(tp); diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index 69f06dc0c..e058a9fbf 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -14,6 +14,7 @@ */ +#include #include "tulip.h" @@ -21,16 +22,16 @@ void tulip_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; - u32 csr12 = inl(ioaddr + CSR12); + void __iomem *ioaddr = tp->base_addr; + u32 csr12 = ioread32(ioaddr + CSR12); int next_tick = 2*HZ; if (tulip_debug > 2) { printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode" " %8.8x SIA %8.8x %8.8x %8.8x %8.8x.\n", - dev->name, medianame[dev->if_port], inl(ioaddr + CSR5), - inl(ioaddr + CSR6), csr12, inl(ioaddr + CSR13), - inl(ioaddr + CSR14), inl(ioaddr + CSR15)); + dev->name, medianame[dev->if_port], ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6), csr12, ioread32(ioaddr + CSR13), + ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); } switch (tp->chip_id) { case DC21140: @@ -48,7 +49,7 @@ void tulip_timer(unsigned long data) if (tulip_debug > 2) printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x " "CSR12 0x%2.2x.\n", - dev->name, inl(ioaddr + CSR6), csr12 & 0xff); + dev->name, ioread32(ioaddr + CSR6), csr12 & 0xff); break; } mleaf = &tp->mtable->mleaf[tp->cur_index]; @@ -136,12 +137,12 @@ void mxic_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int next_tick = 60*HZ; if (tulip_debug > 3) { printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, - inl(ioaddr + CSR12)); + ioread32(ioaddr + CSR12)); } if (next_tick) { mod_timer(&tp->timer, RUN_AT(next_tick)); diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 56d18cc18..6cce2834d 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -149,6 +149,9 @@ enum status_bits { TxIntr = 0x01, }; +/* bit mask for CSR5 TX/RX process state */ +#define CSR5_TS 0x00700000 +#define CSR5_RS 0x000e0000 enum tulip_mode_bits { TxThreshold = (1 << 22), @@ -379,7 +382,7 @@ struct tulip_private { int ttimer; int susp_rx; unsigned long nir; - unsigned long base_addr; + void __iomem *base_addr; int csr12_shadow; int pad0; /* Used for 8-byte alignment */ }; @@ -446,40 +449,33 @@ extern struct tulip_chip_table tulip_tbl[]; void oom_timer(unsigned long data); extern u8 t21040_csr13[]; -#ifndef USE_IO_OPS -#undef inb -#undef inw -#undef inl -#undef outb -#undef outw -#undef outl -#define inb(addr) readb((void*)(addr)) -#define inw(addr) readw((void*)(addr)) -#define inl(addr) readl((void*)(addr)) -#define outb(val,addr) writeb((val), (void*)(addr)) -#define outw(val,addr) writew((val), (void*)(addr)) -#define outl(val,addr) writel((val), (void*)(addr)) -#endif /* !USE_IO_OPS */ - - - static inline void tulip_start_rxtx(struct tulip_private *tp) { - long ioaddr = tp->base_addr; - outl(tp->csr6 | RxTx, ioaddr + CSR6); + void __iomem *ioaddr = tp->base_addr; + iowrite32(tp->csr6 | RxTx, ioaddr + CSR6); barrier(); - (void) inl(ioaddr + CSR6); /* mmio sync */ + (void) ioread32(ioaddr + CSR6); /* mmio sync */ } static inline void tulip_stop_rxtx(struct tulip_private *tp) { - long ioaddr = tp->base_addr; - u32 csr6 = inl(ioaddr + CSR6); + void __iomem *ioaddr = tp->base_addr; + u32 csr6 = ioread32(ioaddr + CSR6); if (csr6 & RxTx) { - outl(csr6 & ~RxTx, ioaddr + CSR6); + unsigned i=1300/10; + iowrite32(csr6 & ~RxTx, ioaddr + CSR6); barrier(); - (void) inl(ioaddr + CSR6); /* mmio sync */ + /* wait until in-flight frame completes. + * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) + * Typically expect this loop to end in < 50 us on 100BT. + */ + while (--i && (ioread32(ioaddr + CSR5) & (CSR5_TS|CSR5_RS))) + udelay(10); + + if (!i) + printk(KERN_DEBUG "%s: tulip_stop_rxtx() failed\n", + tp->pdev->slot_name); } } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index cff6f977c..94195e94a 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -26,8 +26,8 @@ #include -#include "tulip.h" #include +#include "tulip.h" #include #include #include @@ -279,7 +279,7 @@ static void tulip_set_power_state (struct tulip_private *tp, static void tulip_up(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int next_tick = 3*HZ; int i; @@ -288,23 +288,23 @@ static void tulip_up(struct net_device *dev) /* On some chip revs we must set the MII/SYM port before the reset!? */ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) - outl(0x00040000, ioaddr + CSR6); + iowrite32(0x00040000, ioaddr + CSR6); /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ - outl(0x00000001, ioaddr + CSR0); + iowrite32(0x00000001, ioaddr + CSR0); udelay(100); /* Deassert reset. Wait the specified 50 PCI cycles after a reset by initializing Tx and Rx queues and the address filter list. */ - outl(tp->csr0, ioaddr + CSR0); + iowrite32(tp->csr0, ioaddr + CSR0); udelay(100); if (tulip_debug > 1) printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", dev->name, dev->irq); - outl(tp->rx_ring_dma, ioaddr + CSR3); - outl(tp->tx_ring_dma, ioaddr + CSR4); + iowrite32(tp->rx_ring_dma, ioaddr + CSR3); + iowrite32(tp->tx_ring_dma, ioaddr + CSR4); tp->cur_rx = tp->cur_tx = 0; tp->dirty_rx = tp->dirty_tx = 0; @@ -312,15 +312,15 @@ static void tulip_up(struct net_device *dev) u32 addr_low = le32_to_cpu(get_unaligned((u32 *)dev->dev_addr)); u32 addr_high = le16_to_cpu(get_unaligned((u16 *)(dev->dev_addr+4))); if (tp->chip_id == AX88140) { - outl(0, ioaddr + CSR13); - outl(addr_low, ioaddr + CSR14); - outl(1, ioaddr + CSR13); - outl(addr_high, ioaddr + CSR14); + iowrite32(0, ioaddr + CSR13); + iowrite32(addr_low, ioaddr + CSR14); + iowrite32(1, ioaddr + CSR13); + iowrite32(addr_high, ioaddr + CSR14); } else if (tp->flags & COMET_MAC_ADDR) { - outl(addr_low, ioaddr + 0xA4); - outl(addr_high, ioaddr + 0xA8); - outl(0, ioaddr + 0xAC); - outl(0, ioaddr + 0xB0); + iowrite32(addr_low, ioaddr + 0xA4); + iowrite32(addr_high, ioaddr + 0xA8); + iowrite32(0, ioaddr + 0xAC); + iowrite32(0, ioaddr + 0xB0); } } else { /* This is set_rx_mode(), but without starting the transmitter. */ @@ -390,9 +390,9 @@ media_picked: if (tp->chip_id == DC21143 && (tulip_media_cap[dev->if_port] & MediaIsMII)) { /* We must reset the media CSRs when we force-select MII mode. */ - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - outl(0x0008, ioaddr + CSR15); + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + iowrite32(0x0008, ioaddr + CSR15); } tulip_select_media(dev, 1); } else if (tp->chip_id == DC21142) { @@ -402,49 +402,49 @@ media_picked: printk(KERN_INFO "%s: Using MII transceiver %d, status " "%4.4x.\n", dev->name, tp->phys[0], tulip_mdio_read(dev, tp->phys[0], 1)); - outl(csr6_mask_defstate, ioaddr + CSR6); + iowrite32(csr6_mask_defstate, ioaddr + CSR6); tp->csr6 = csr6_mask_hdcap; dev->if_port = 11; - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); } else t21142_start_nway(dev); } else if (tp->chip_id == PNIC2) { /* 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); + iowrite32(ioread32(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5); + iowrite32(ioread32(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7); pnic2_start_nway(dev); } else if (tp->chip_id == LC82C168 && ! tp->medialock) { if (tp->mii_cnt) { dev->if_port = 11; tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); - outl(0x0001, ioaddr + CSR15); - } else if (inl(ioaddr + CSR5) & TPLnkPass) + iowrite32(0x0001, ioaddr + CSR15); + } else if (ioread32(ioaddr + CSR5) & TPLnkPass) pnic_do_nway(dev); else { /* Start with 10mbps to do autonegotiation. */ - outl(0x32, ioaddr + CSR12); + iowrite32(0x32, ioaddr + CSR12); tp->csr6 = 0x00420000; - outl(0x0001B078, ioaddr + 0xB8); - outl(0x0201B078, ioaddr + 0xB8); + iowrite32(0x0001B078, ioaddr + 0xB8); + iowrite32(0x0201B078, ioaddr + 0xB8); next_tick = 1*HZ; } } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) && ! tp->medialock) { dev->if_port = 0; tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); - outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); + iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { /* Provided by BOLO, Macronix - 12/10/1998. */ dev->if_port = 0; tp->csr6 = 0x01a80200; - outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); - outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0); + iowrite32(0x0f370000 | ioread16(ioaddr + 0x80), ioaddr + 0x80); + iowrite32(0x11000 | ioread16(ioaddr + 0xa0), ioaddr + 0xa0); } else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) { /* Enable automatic Tx underrun recovery. */ - outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88); + iowrite32(ioread32(ioaddr + 0x88) | 1, ioaddr + 0x88); dev->if_port = tp->mii_cnt ? 11 : 0; tp->csr6 = 0x00040000; } else if (tp->chip_id == AX88140) { @@ -456,18 +456,18 @@ media_picked: tulip_stop_rxtx(tp); barrier(); udelay(5); - outl(tp->csr6 | TxOn, ioaddr + CSR6); + iowrite32(tp->csr6 | TxOn, ioaddr + CSR6); /* Enable interrupts by setting the interrupt mask. */ - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); + iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); tulip_start_rxtx(tp); - outl(0, ioaddr + CSR2); /* Rx poll demand */ + iowrite32(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", - dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), - inl(ioaddr + CSR6)); + dev->name, ioread32(ioaddr + CSR0), ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); } /* Set the timer to switch to check for link beat and perhaps switch @@ -502,7 +502,7 @@ tulip_open(struct net_device *dev) static void tulip_tx_timeout(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; unsigned long flags; spin_lock_irqsave (&tp->lock, flags); @@ -517,8 +517,8 @@ static void tulip_tx_timeout(struct net_device *dev) || tp->chip_id == DM910X) { printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, " "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12), - inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15)); + dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), + ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); if ( ! tp->medialock && tp->mtable) { do --tp->cur_index; @@ -536,12 +536,12 @@ static void tulip_tx_timeout(struct net_device *dev) } else if (tp->chip_id == PNIC2) { printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, " "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n", - dev->name, (int)inl(ioaddr + CSR5), (int)inl(ioaddr + CSR6), - (int)inl(ioaddr + CSR7), (int)inl(ioaddr + CSR12)); + dev->name, (int)ioread32(ioaddr + CSR5), (int)ioread32(ioaddr + CSR6), + (int)ioread32(ioaddr + CSR7), (int)ioread32(ioaddr + CSR12)); } else { printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 " "%8.8x, resetting...\n", - dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12)); + dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12)); dev->if_port = 0; } @@ -576,7 +576,7 @@ static void tulip_tx_timeout(struct net_device *dev) tulip_restart_rxtx(tp); /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); + iowrite32(0, ioaddr + CSR1); tp->stats.tx_errors++; @@ -678,7 +678,7 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->cur_tx++; /* Trigger an immediate transmit demand. */ - outl(0, dev->base_addr + CSR1); + iowrite32(0, tp->base_addr + CSR1); spin_unlock_irq(&tp->lock); @@ -725,8 +725,8 @@ static void tulip_clean_tx_ring(struct tulip_private *tp) static void tulip_down (struct net_device *dev) { - long ioaddr = dev->base_addr; struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; unsigned long flags; del_timer_sync (&tp->timer); @@ -736,7 +736,7 @@ static void tulip_down (struct net_device *dev) spin_lock_irqsave (&tp->lock, flags); /* Disable interrupts by clearing the interrupt mask. */ - outl (0x00000000, ioaddr + CSR7); + iowrite32 (0x00000000, ioaddr + CSR7); /* Stop the Tx and Rx processes. */ tulip_stop_rxtx(tp); @@ -747,8 +747,8 @@ static void tulip_down (struct net_device *dev) /* release any unconsumed transmit buffers */ tulip_clean_tx_ring(tp); - if (inl (ioaddr + CSR6) != 0xffffffff) - tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff; + if (ioread32 (ioaddr + CSR6) != 0xffffffff) + tp->stats.rx_missed_errors += ioread32 (ioaddr + CSR8) & 0xffff; spin_unlock_irqrestore (&tp->lock, flags); @@ -765,8 +765,8 @@ static void tulip_down (struct net_device *dev) static int tulip_close (struct net_device *dev) { - long ioaddr = dev->base_addr; struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; int i; netif_stop_queue (dev); @@ -775,7 +775,7 @@ static int tulip_close (struct net_device *dev) if (tulip_debug > 1) printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, inl (ioaddr + CSR5)); + dev->name, ioread32 (ioaddr + CSR5)); free_irq (dev->irq, dev); @@ -814,14 +814,14 @@ static int tulip_close (struct net_device *dev) static struct net_device_stats *tulip_get_stats(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; if (netif_running(dev)) { unsigned long flags; spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; + tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; spin_unlock_irqrestore(&tp->lock, flags); } @@ -830,44 +830,29 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev) } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct tulip_private *np = netdev_priv(dev); - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pdev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); } +static struct ethtool_ops ops = { + .get_drvinfo = tulip_get_drvinfo +}; + /* Provide ioctl() calls to examine the MII xcvr state. */ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; struct mii_ioctl_data *data = if_mii(rq); const unsigned int phy_idx = 0; int phy = tp->phys[phy_idx] & 0x1f; unsigned int regnum = data->reg_num; switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ if (tp->mii_cnt) data->phy_id = phy; @@ -880,8 +865,8 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) case SIOCGMIIREG: /* Read MII PHY register. */ if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { - int csr12 = inl (ioaddr + CSR12); - int csr14 = inl (ioaddr + CSR14); + int csr12 = ioread32 (ioaddr + CSR12); + int csr14 = ioread32 (ioaddr + CSR14); switch (regnum) { case 0: if (((csr14<<5) & 0x1000) || @@ -901,7 +886,7 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) case 4: /* Advertised value, bogus 10baseTx-FD value from CSR6. */ data->val_out = - ((inl(ioaddr + CSR6) >> 3) & 0x0040) + + ((ioread32(ioaddr + CSR6) >> 3) & 0x0040) + ((csr14 >> 1) & 0x20) + 1; data->val_out |= ((csr14 >> 9) & 0x03C0); break; @@ -1026,10 +1011,10 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) static void set_rx_mode(struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = tp->base_addr; int csr6; - csr6 = inl(ioaddr + CSR6) & ~0x00D5; + csr6 = ioread32(ioaddr + CSR6) & ~0x00D5; tp->csr6 &= ~0x00D5; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ @@ -1073,13 +1058,13 @@ static void set_rx_mode(struct net_device *dev) mc_filter[1] == tp->mc_filter[1]) ; /* No change. */ else if (tp->flags & IS_ASIX) { - outl(2, ioaddr + CSR13); - outl(mc_filter[0], ioaddr + CSR14); - outl(3, ioaddr + CSR13); - outl(mc_filter[1], ioaddr + CSR14); + iowrite32(2, ioaddr + CSR13); + iowrite32(mc_filter[0], ioaddr + CSR14); + iowrite32(3, ioaddr + CSR13); + iowrite32(mc_filter[1], ioaddr + CSR14); } else if (tp->flags & COMET_MAC_ADDR) { - outl(mc_filter[0], ioaddr + 0xAC); - outl(mc_filter[1], ioaddr + 0xB0); + iowrite32(mc_filter[0], ioaddr + 0xAC); + iowrite32(mc_filter[1], ioaddr + 0xB0); } tp->mc_filter[0] = mc_filter[0]; tp->mc_filter[1] = mc_filter[1]; @@ -1139,13 +1124,13 @@ static void set_rx_mode(struct net_device *dev) netif_stop_queue(dev); /* Trigger an immediate transmit demand. */ - outl(0, ioaddr + CSR1); + iowrite32(0, ioaddr + CSR1); } spin_unlock_irqrestore(&tp->lock, flags); } - outl(csr6, ioaddr + CSR6); + iowrite32(csr6, ioaddr + CSR6); } #ifdef CONFIG_TULIP_MWI @@ -1236,6 +1221,11 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, struct tulip_private *tp; /* See note below on the multiport cards. */ static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'}; + static struct pci_device_id early_486_chipsets[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) }, + { }, + }; static int last_irq; static int multiport_cnt; /* For four-port boards w/one EEPROM */ u8 chip_rev; @@ -1243,7 +1233,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, unsigned short sum; unsigned char *ee_data; struct net_device *dev; - long ioaddr; + void __iomem *ioaddr; static int board_idx = -1; int chip_idx = ent->driver_data; const char *chip_name = tulip_tbl[chip_idx].chip_name; @@ -1289,17 +1279,15 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, * without the workarounds being on. */ - /* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned - Aries might need this too. The Saturn errata are not pretty reading but - thankfully it's an old 486 chipset. + /* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache + aligned. Aries might need this too. The Saturn errata are not + pretty reading but thankfully it's an old 486 chipset. + + 2. The dreaded SiS496 486 chipset. Same workaround as Intel + Saturn. */ - if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) { - csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift); - force_csr0 = 1; - } - /* The dreaded SiS496 486 chipset. Same workaround as above. */ - if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) { + if (pci_dev_present(early_486_chipsets)) { csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift); force_csr0 = 1; } @@ -1338,7 +1326,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, return i; } - ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; /* alloc_etherdev ensures aligned and zeroed private structures */ @@ -1364,11 +1351,12 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, goto err_out_free_netdev; #ifndef USE_IO_OPS - ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 1), - tulip_tbl[chip_idx].io_size); + ioaddr = pci_iomap(pdev, 1, tulip_tbl[chip_idx].io_size); +#else + ioaddr = pci_iomap(pdev, 0, tulip_tbl[chip_idx].io_size); +#endif if (!ioaddr) goto err_out_free_res; -#endif pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); @@ -1399,7 +1387,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->timer.data = (unsigned long)dev; tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; #ifdef CONFIG_TULIP_MWI if (!force_csr0 && (tp->flags & HAS_PCI_MWI)) @@ -1433,7 +1421,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, #endif /* Clear the missed-packet counter. */ - inl(ioaddr + CSR8); + ioread32(ioaddr + CSR8); /* The station address ROM is read byte serially. The register must be polled, waiting for the value to be read bit serially from the @@ -1444,17 +1432,17 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (chip_idx == LC82C168) { for (i = 0; i < 3; i++) { int value, boguscnt = 100000; - outl(0x600 | i, ioaddr + 0x98); + iowrite32(0x600 | i, ioaddr + 0x98); do - value = inl(ioaddr + CSR9); + value = ioread32(ioaddr + CSR9); while (value < 0 && --boguscnt > 0); put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i); sum += value & 0xffff; } } else if (chip_idx == COMET) { /* No need to read the EEPROM. */ - put_unaligned(cpu_to_le32(inl(ioaddr + 0xA4)), (u32 *)dev->dev_addr); - put_unaligned(cpu_to_le16(inl(ioaddr + 0xA8)), (u16 *)(dev->dev_addr + 4)); + put_unaligned(cpu_to_le32(ioread32(ioaddr + 0xA4)), (u32 *)dev->dev_addr); + put_unaligned(cpu_to_le16(ioread32(ioaddr + 0xA8)), (u16 *)(dev->dev_addr + 4)); for (i = 0; i < 6; i ++) sum += dev->dev_addr[i]; } else { @@ -1644,11 +1632,12 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_tulip; #endif + SET_ETHTOOL_OPS(dev, &ops); if (register_netdev(dev)) goto err_out_free_ring; - printk(KERN_INFO "%s: %s rev %d at %#3lx,", + printk(KERN_INFO "%s: %s rev %d at %p,", dev->name, chip_name, chip_rev, ioaddr); pci_set_drvdata(pdev, dev); @@ -1671,43 +1660,43 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, case DM910X: default: if (tp->mtable) - outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); + iowrite32(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); break; case DC21142: if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) { - outl(csr6_mask_defstate, ioaddr + CSR6); - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); - outl(csr6_mask_hdcap, ioaddr + CSR6); + iowrite32(csr6_mask_defstate, ioaddr + CSR6); + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); + iowrite32(csr6_mask_hdcap, ioaddr + CSR6); } else t21142_start_nway(dev); break; case PNIC2: /* just do a reset for sanity sake */ - outl(0x0000, ioaddr + CSR13); - outl(0x0000, ioaddr + CSR14); + iowrite32(0x0000, ioaddr + CSR13); + iowrite32(0x0000, ioaddr + CSR14); break; case LC82C168: if ( ! tp->mii_cnt) { tp->nway = 1; tp->nwayset = 0; - outl(csr6_ttm | csr6_ca, ioaddr + CSR6); - outl(0x30, ioaddr + CSR12); - outl(0x0001F078, ioaddr + CSR6); - outl(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */ + iowrite32(csr6_ttm | csr6_ca, ioaddr + CSR6); + iowrite32(0x30, ioaddr + CSR12); + iowrite32(0x0001F078, ioaddr + CSR6); + iowrite32(0x0201F078, ioaddr + CSR6); /* Turn on autonegotiation. */ } break; case MX98713: case COMPEX9881: - outl(0x00000000, ioaddr + CSR6); - outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ - outl(0x00000001, ioaddr + CSR13); + iowrite32(0x00000000, ioaddr + CSR6); + iowrite32(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ + iowrite32(0x00000001, ioaddr + CSR13); break; case MX98715: case MX98725: - outl(0x01a80000, ioaddr + CSR6); - outl(0xFFFFFFFF, ioaddr + CSR14); - outl(0x00001000, ioaddr + CSR12); + iowrite32(0x01a80000, ioaddr + CSR6); + iowrite32(0xFFFFFFFF, ioaddr + CSR14); + iowrite32(0x00001000, ioaddr + CSR12); break; case COMET: /* No initialization necessary. */ @@ -1728,11 +1717,9 @@ err_out_free_ring: err_out_mtable: if (tp->mtable) kfree (tp->mtable); -#ifndef USE_IO_OPS - iounmap((void *)ioaddr); + pci_iounmap(pdev, ioaddr); err_out_free_res: -#endif pci_release_regions (pdev); err_out_free_netdev: @@ -1790,9 +1777,7 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev) tp->rx_ring, tp->rx_ring_dma); if (tp->mtable) kfree (tp->mtable); -#ifndef USE_IO_OPS - iounmap((void *)dev->base_addr); -#endif + pci_iounmap(pdev, tp->base_addr); free_netdev (dev); pci_release_regions (pdev); pci_set_drvdata (pdev, NULL); diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index d3efcadca..5bf05492a 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -130,9 +130,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include @@ -258,21 +258,6 @@ static struct pci_id_info pci_id_tbl[] = { work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space accesses instead of memory space. */ -#ifdef USE_IO_OPS -#undef readb -#undef readw -#undef readl -#undef writeb -#undef writew -#undef writel -#define readb inb -#define readw inw -#define readl inl -#define writeb outb -#define writew outw -#define writel outl -#endif - /* Offsets to the Command and Status Registers, "CSRs". While similar to the Tulip, these registers are longword aligned. Note: It's not useful to define symbolic names for every register bit in @@ -361,9 +346,10 @@ struct netdev_private { unsigned char phys[MII_CNT]; /* MII device addresses, but only the first is used */ u32 mii; struct mii_if_info mii_if; + void __iomem *base_addr; }; -static int eeprom_read(long ioaddr, int location); +static int eeprom_read(void __iomem *ioaddr, int location); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int netdev_open(struct net_device *dev); @@ -397,7 +383,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, int chip_idx = ent->driver_data; int irq; int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0; - long ioaddr; + void __iomem *ioaddr; + int bar = 1; i = pci_enable_device(pdev); if (i) return i; @@ -419,27 +406,24 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, if (pci_request_regions(pdev, DRV_NAME)) goto err_out_netdev; - #ifdef USE_IO_OPS - ioaddr = pci_resource_start(pdev, 0); -#else - ioaddr = pci_resource_start(pdev, 1); - ioaddr = (long) ioremap (ioaddr, pci_id_tbl[chip_idx].io_size); + bar = 0; +#endif + ioaddr = pci_iomap(pdev, bar, pci_id_tbl[chip_idx].io_size); if (!ioaddr) goto err_out_free_res; -#endif for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = le16_to_cpu(eeprom_read(ioaddr, i)); /* Reset the chip to erase previous misconfiguration. No hold time required! */ - writel(0x00000001, ioaddr + PCIBusCfg); + iowrite32(0x00000001, ioaddr + PCIBusCfg); - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->pci_dev = pdev; np->chip_id = chip_idx; np->drv_flags = pci_id_tbl[chip_idx].drv_flags; @@ -447,6 +431,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, np->mii_if.dev = dev; np->mii_if.mdio_read = mdio_read; np->mii_if.mdio_write = mdio_write; + np->base_addr = ioaddr; pci_set_drvdata(pdev, dev); @@ -482,7 +467,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, if (i) goto err_out_cleardev; - printk(KERN_INFO "%s: %s at 0x%lx, ", + printk(KERN_INFO "%s: %s at %p, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); @@ -515,10 +500,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, err_out_cleardev: pci_set_drvdata(pdev, NULL); -#ifndef USE_IO_OPS - iounmap((void *)ioaddr); + pci_iounmap(pdev, ioaddr); err_out_free_res: -#endif pci_release_regions(pdev); err_out_netdev: free_netdev (dev); @@ -537,7 +520,7 @@ err_out_netdev: The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is depricated. */ -#define eeprom_delay(ee_addr) readl(ee_addr) +#define eeprom_delay(ee_addr) ioread32(ee_addr) enum EEPROM_Ctrl_Bits { EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805, @@ -549,35 +532,35 @@ enum EEPROM_Cmds { EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), }; -static int eeprom_read(long addr, int location) +static int eeprom_read(void __iomem *addr, int location) { int i; int retval = 0; - long ee_addr = addr + EECtrl; + void __iomem *ee_addr = addr + EECtrl; int read_cmd = location | EE_ReadCmd; - writel(EE_ChipSelect, ee_addr); + iowrite32(EE_ChipSelect, ee_addr); /* Shift the read command bits out. */ for (i = 10; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; - writel(dataval, ee_addr); + iowrite32(dataval, ee_addr); eeprom_delay(ee_addr); - writel(dataval | EE_ShiftClk, ee_addr); + iowrite32(dataval | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); } - writel(EE_ChipSelect, ee_addr); + iowrite32(EE_ChipSelect, ee_addr); eeprom_delay(ee_addr); for (i = 16; i > 0; i--) { - writel(EE_ChipSelect | EE_ShiftClk, ee_addr); + iowrite32(EE_ChipSelect | EE_ShiftClk, ee_addr); eeprom_delay(ee_addr); - retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0); - writel(EE_ChipSelect, ee_addr); + retval = (retval << 1) | ((ioread32(ee_addr) & EE_DataIn) ? 1 : 0); + iowrite32(EE_ChipSelect, ee_addr); eeprom_delay(ee_addr); } /* Terminate the EEPROM access. */ - writel(0, ee_addr); + iowrite32(0, ee_addr); return retval; } @@ -588,7 +571,7 @@ static int eeprom_read(long addr, int location) The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back 33Mhz PCI cycles. */ -#define mdio_delay(mdio_addr) readl(mdio_addr) +#define mdio_delay(mdio_addr) ioread32(mdio_addr) /* Set iff a MII transceiver on any interface requires mdio preamble. This only set with older transceivers, so the extra @@ -600,22 +583,23 @@ static char mii_preamble_required = 1; /* Generate the preamble required for initial synchronization and a few older transceivers. */ -static void mdio_sync(long mdio_addr) +static void mdio_sync(void __iomem *mdio_addr) { int bits = 32; /* Establish sync by sending at least 32 logic ones. */ while (--bits >= 0) { - writel(MDIO_WRITE1, mdio_addr); + iowrite32(MDIO_WRITE1, mdio_addr); mdio_delay(mdio_addr); - writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); + iowrite32(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); mdio_delay(mdio_addr); } } static int mdio_read(struct net_device *dev, int phy_id, int location) { - long mdio_addr = dev->base_addr + MIICtrl; + struct netdev_private *np = netdev_priv(dev); + void __iomem *mdio_addr = np->base_addr + MIICtrl; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i, retval = 0; @@ -626,17 +610,17 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writel(dataval, mdio_addr); + iowrite32(dataval, mdio_addr); mdio_delay(mdio_addr); - writel(dataval | MDIO_ShiftClk, mdio_addr); + iowrite32(dataval | MDIO_ShiftClk, mdio_addr); mdio_delay(mdio_addr); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 20; i > 0; i--) { - writel(MDIO_EnbIn, mdio_addr); + iowrite32(MDIO_EnbIn, mdio_addr); mdio_delay(mdio_addr); - retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0); - writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); + retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DataIn) ? 1 : 0); + iowrite32(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); mdio_delay(mdio_addr); } return (retval>>1) & 0xffff; @@ -644,8 +628,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) static void mdio_write(struct net_device *dev, int phy_id, int location, int value) { - struct netdev_private *np = dev->priv; - long mdio_addr = dev->base_addr + MIICtrl; + struct netdev_private *np = netdev_priv(dev); + void __iomem *mdio_addr = np->base_addr + MIICtrl; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; int i; @@ -659,16 +643,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val for (i = 31; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writel(dataval, mdio_addr); + iowrite32(dataval, mdio_addr); mdio_delay(mdio_addr); - writel(dataval | MDIO_ShiftClk, mdio_addr); + iowrite32(dataval | MDIO_ShiftClk, mdio_addr); mdio_delay(mdio_addr); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - writel(MDIO_EnbIn, mdio_addr); + iowrite32(MDIO_EnbIn, mdio_addr); mdio_delay(mdio_addr); - writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); + iowrite32(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); mdio_delay(mdio_addr); } return; @@ -677,11 +661,11 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; int i; - writel(0x00000001, ioaddr + PCIBusCfg); /* Reset */ + iowrite32(0x00000001, ioaddr + PCIBusCfg); /* Reset */ netif_device_detach(dev); i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); @@ -720,7 +704,7 @@ out_err: static int update_link(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int duplex, fasteth, result, mii_reg; /* BSMR */ @@ -783,8 +767,8 @@ static int update_link(struct net_device *dev) #define RXTX_TIMEOUT 2000 static inline void update_csr6(struct net_device *dev, int new) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; int limit = RXTX_TIMEOUT; if (!netif_device_present(dev)) @@ -792,10 +776,10 @@ static inline void update_csr6(struct net_device *dev, int new) if (new==np->csr6) return; /* stop both Tx and Rx processes */ - writel(np->csr6 & ~0x2002, ioaddr + NetworkConfig); + iowrite32(np->csr6 & ~0x2002, ioaddr + NetworkConfig); /* wait until they have really stopped */ for (;;) { - int csr5 = readl(ioaddr + IntrStatus); + int csr5 = ioread32(ioaddr + IntrStatus); int t; t = (csr5 >> 17) & 0x07; @@ -816,7 +800,7 @@ static inline void update_csr6(struct net_device *dev, int new) } np->csr6 = new; /* and restart them with the new configuration */ - writel(np->csr6, ioaddr + NetworkConfig); + iowrite32(np->csr6, ioaddr + NetworkConfig); if (new & 0x200) np->mii_if.full_duplex = 1; } @@ -824,14 +808,14 @@ static inline void update_csr6(struct net_device *dev, int new) static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; if (debug > 2) printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x " "config %8.8x.\n", - dev->name, (int)readl(ioaddr + IntrStatus), - (int)readl(ioaddr + NetworkConfig)); + dev->name, ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); spin_lock_irq(&np->lock); update_csr6(dev, update_link(dev)); spin_unlock_irq(&np->lock); @@ -841,7 +825,7 @@ static void netdev_timer(unsigned long data) static void init_rxtx_rings(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->rx_head_desc = &np->rx_ring[0]; @@ -881,9 +865,9 @@ static void init_rxtx_rings(struct net_device *dev) np->tx_full = 0; np->tx_q_bytes = np->dirty_tx = np->cur_tx = 0; - writel(np->ring_dma_addr, dev->base_addr + RxRingPtr); - writel(np->ring_dma_addr+sizeof(struct w840_rx_desc)*RX_RING_SIZE, - dev->base_addr + TxRingPtr); + iowrite32(np->ring_dma_addr, np->base_addr + RxRingPtr); + iowrite32(np->ring_dma_addr+sizeof(struct w840_rx_desc)*RX_RING_SIZE, + np->base_addr + TxRingPtr); } @@ -916,12 +900,12 @@ static void free_rxtx_rings(struct netdev_private* np) static void init_registers(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; int i; for (i = 0; i < 6; i++) - writeb(dev->dev_addr[i], ioaddr + StationAddr + i); + iowrite8(dev->dev_addr[i], ioaddr + StationAddr + i); /* Initialize other registers. */ #ifdef __BIG_ENDIAN @@ -958,7 +942,7 @@ static void init_registers(struct net_device *dev) #warning Processor architecture undefined i |= 0x4800; #endif - writel(i, ioaddr + PCIBusCfg); + iowrite32(i, ioaddr + PCIBusCfg); np->csr6 = 0; /* 128 byte Tx threshold; @@ -966,19 +950,19 @@ static void init_registers(struct net_device *dev) update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev)); /* Clear and Enable interrupts by setting the interrupt mask. */ - writel(0x1A0F5, ioaddr + IntrStatus); - writel(0x1A0F5, ioaddr + IntrEnable); + iowrite32(0x1A0F5, ioaddr + IntrStatus); + iowrite32(0x1A0F5, ioaddr + IntrEnable); - writel(0, ioaddr + RxStartDemand); + iowrite32(0, ioaddr + RxStartDemand); } static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus)); + " resetting...\n", dev->name, ioread32(ioaddr + IntrStatus)); { int i; @@ -992,7 +976,7 @@ static void tx_timeout(struct net_device *dev) } printk(KERN_DEBUG "Tx cur %d Tx dirty %d Tx Full %d, q bytes %d.\n", np->cur_tx, np->dirty_tx, np->tx_full, np->tx_q_bytes); - printk(KERN_DEBUG "Tx Descriptor addr %xh.\n",readl(ioaddr+0x4C)); + printk(KERN_DEBUG "Tx Descriptor addr %xh.\n",ioread32(ioaddr+0x4C)); disable_irq(dev->irq); spin_lock_irq(&np->lock); @@ -1002,7 +986,7 @@ static void tx_timeout(struct net_device *dev) * everything. */ - writel(1, dev->base_addr+PCIBusCfg); + iowrite32(1, np->base_addr+PCIBusCfg); udelay(1); free_rxtx_rings(np); @@ -1020,7 +1004,7 @@ static void tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static int alloc_ringdesc(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1045,7 +1029,7 @@ static void free_ringdesc(struct netdev_private *np) static int start_tx(struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned entry; /* Caution: the write order is important here, set the field @@ -1086,7 +1070,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) wmb(); /* flush length, buffer1, buffer2 */ np->tx_ring[entry].status = DescOwn; wmb(); /* flush status and kick the hardware */ - writel(0, dev->base_addr + TxStartDemand); + iowrite32(0, np->base_addr + TxStartDemand); np->tx_q_bytes += skb->len; /* Work around horrible bug in the chip by marking the queue as full when we do not have FIFO room for a maximum sized packet. */ @@ -1109,7 +1093,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) static void netdev_tx_done(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { int entry = np->dirty_tx % TX_RING_SIZE; int tx_status = np->tx_ring[entry].status; @@ -1162,18 +1146,18 @@ static void netdev_tx_done(struct net_device *dev) static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = (struct net_device *)dev_instance; - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; int work_limit = max_interrupt_work; int handled = 0; if (!netif_device_present(dev)) return IRQ_NONE; do { - u32 intr_status = readl(ioaddr + IntrStatus); + u32 intr_status = ioread32(ioaddr + IntrStatus); /* Acknowledge all of the current interrupt sources ASAP. */ - writel(intr_status & 0x001ffff, ioaddr + IntrStatus); + iowrite32(intr_status & 0x001ffff, ioaddr + IntrStatus); if (debug > 4) printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", @@ -1187,7 +1171,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs if (intr_status & (IntrRxDone | RxNoBuf)) netdev_rx(dev); if (intr_status & RxNoBuf) - writel(0, ioaddr + RxStartDemand); + iowrite32(0, ioaddr + RxStartDemand); if (intr_status & (TxIdle | IntrTxDone) && np->cur_tx != np->dirty_tx) { @@ -1208,8 +1192,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs 10*82usec ticks. */ spin_lock(&np->lock); if (netif_device_present(dev)) { - writel(AbnormalIntr | TimerInt, ioaddr + IntrEnable); - writel(10, ioaddr + GPTimer); + iowrite32(AbnormalIntr | TimerInt, ioaddr + IntrEnable); + iowrite32(10, ioaddr + GPTimer); } spin_unlock(&np->lock); break; @@ -1218,7 +1202,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs if (debug > 3) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, (int)readl(ioaddr + IntrStatus)); + dev->name, ioread32(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } @@ -1226,7 +1210,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs for clarity and better register allocation. */ static int netdev_rx(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int work_limit = np->dirty_rx + RX_RING_SIZE - np->cur_rx; @@ -1342,8 +1326,8 @@ static int netdev_rx(struct net_device *dev) static void netdev_error(struct net_device *dev, int intr_status) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; if (debug > 2) printk(KERN_DEBUG "%s: Abnormal event, %8.8x.\n", @@ -1377,22 +1361,22 @@ static void netdev_error(struct net_device *dev, int intr_status) if (intr_status & TimerInt) { /* Re-enable other interrupts. */ if (netif_device_present(dev)) - writel(0x1A0F5, ioaddr + IntrEnable); + iowrite32(0x1A0F5, ioaddr + IntrEnable); } - np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff; - writel(0, ioaddr + RxStartDemand); + np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; + iowrite32(0, ioaddr + RxStartDemand); spin_unlock(&np->lock); } static struct net_device_stats *get_stats(struct net_device *dev) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; /* The chip only need report frame silently dropped. */ spin_lock_irq(&np->lock); if (netif_running(dev) && netif_device_present(dev)) - np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff; + np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; spin_unlock_irq(&np->lock); return &np->stats; @@ -1401,7 +1385,8 @@ static struct net_device_stats *get_stats(struct net_device *dev) static u32 __set_rx_mode(struct net_device *dev) { - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; u32 mc_filter[2]; /* Multicast hash filter */ u32 rx_mode; @@ -1428,14 +1413,14 @@ static u32 __set_rx_mode(struct net_device *dev) } rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; } - writel(mc_filter[0], ioaddr + MulticastFilter0); - writel(mc_filter[1], ioaddr + MulticastFilter1); + iowrite32(mc_filter[0], ioaddr + MulticastFilter0); + iowrite32(mc_filter[1], ioaddr + MulticastFilter1); return rx_mode; } static void set_rx_mode(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u32 rx_mode = __set_rx_mode(dev); spin_lock_irq(&np->lock); update_csr6(dev, (np->csr6 & ~0x00F8) | rx_mode); @@ -1444,7 +1429,7 @@ static void set_rx_mode(struct net_device *dev) static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); strcpy (info->driver, DRV_NAME); strcpy (info->version, DRV_VERSION); @@ -1453,7 +1438,7 @@ static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo * static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int rc; spin_lock_irq(&np->lock); @@ -1465,7 +1450,7 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int rc; spin_lock_irq(&np->lock); @@ -1477,13 +1462,13 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int netdev_nway_reset(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); return mii_nway_restart(&np->mii_if); } static u32 netdev_get_link(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); return mii_link_ok(&np->mii_if); } @@ -1516,7 +1501,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f; + data->phy_id = ((struct netdev_private *)netdev_priv(dev))->phys[0] & 0x1f; /* Fall Through */ case SIOCGMIIREG: /* Read MII PHY register. */ @@ -1539,15 +1524,15 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int netdev_close(struct net_device *dev) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; netif_stop_queue(dev); if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was %8.8x " - "Config %8.8x.\n", dev->name, (int)readl(ioaddr + IntrStatus), - (int)readl(ioaddr + NetworkConfig)); + "Config %8.8x.\n", dev->name, ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); } @@ -1556,15 +1541,15 @@ static int netdev_close(struct net_device *dev) spin_lock_irq(&np->lock); netif_device_detach(dev); update_csr6(dev, 0); - writel(0x0000, ioaddr + IntrEnable); + iowrite32(0x0000, ioaddr + IntrEnable); spin_unlock_irq(&np->lock); free_irq(dev->irq, dev); wmb(); netif_device_attach(dev); - if (readl(ioaddr + NetworkConfig) != 0xffffffff) - np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff; + if (ioread32(ioaddr + NetworkConfig) != 0xffffffff) + np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; #ifdef __i386__ if (debug > 2) { @@ -1599,11 +1584,10 @@ static void __devexit w840_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { + struct netdev_private *np = netdev_priv(dev); unregister_netdev(dev); pci_release_regions(pdev); -#ifndef USE_IO_OPS - iounmap((char *)(dev->base_addr)); -#endif + pci_iounmap(pdev, np->base_addr); free_netdev(dev); } @@ -1638,8 +1622,8 @@ static void __devexit w840_remove1 (struct pci_dev *pdev) static int w840_suspend (struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata (pdev); - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base_addr; rtnl_lock(); if (netif_running (dev)) { @@ -1648,19 +1632,19 @@ static int w840_suspend (struct pci_dev *pdev, u32 state) spin_lock_irq(&np->lock); netif_device_detach(dev); update_csr6(dev, 0); - writel(0, ioaddr + IntrEnable); + iowrite32(0, ioaddr + IntrEnable); netif_stop_queue(dev); spin_unlock_irq(&np->lock); spin_unlock_wait(&dev->xmit_lock); synchronize_irq(dev->irq); - np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff; + np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; /* no more hardware accesses behind this line. */ if (np->csr6) BUG(); - if (readl(ioaddr + IntrEnable)) BUG(); + if (ioread32(ioaddr + IntrEnable)) BUG(); /* pci_power_off(pdev, -1); */ @@ -1675,7 +1659,7 @@ static int w840_suspend (struct pci_dev *pdev, u32 state) static int w840_resume (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata (pdev); - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); rtnl_lock(); if (netif_device_present(dev)) @@ -1685,8 +1669,8 @@ static int w840_resume (struct pci_dev *pdev) /* pci_power_on(pdev); */ spin_lock_irq(&np->lock); - writel(1, dev->base_addr+PCIBusCfg); - readl(dev->base_addr+PCIBusCfg); + iowrite32(1, np->base_addr+PCIBusCfg); + ioread32(np->base_addr+PCIBusCfg); udelay(1); netif_device_attach(dev); init_rxtx_rings(dev); diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 6e6589039..26cc4f637 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -28,9 +28,9 @@ #include #include #include +#include #include -#include #include #ifdef DEBUG @@ -117,6 +117,9 @@ static int xircom_open(struct net_device *dev); static int xircom_close(struct net_device *dev); static void xircom_up(struct xircom_private *card); static struct net_device_stats *xircom_get_stats(struct net_device *dev); +#if CONFIG_NET_POLL_CONTROLLER +static void xircom_poll_controller(struct net_device *dev); +#endif static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset); static void investigate_write_descriptor(struct net_device *dev, struct xircom_private *card, int descnr, unsigned int bufferoffset); @@ -256,7 +259,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ private->dev = dev; private->pdev = pdev; private->io_port = pci_resource_start(pdev, 0); - private->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&private->lock); dev->irq = pdev->irq; dev->base_addr = private->io_port; @@ -269,6 +272,9 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ dev->stop = &xircom_close; dev->get_stats = &xircom_get_stats; dev->priv = private; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = &xircom_poll_controller; +#endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); pci_set_drvdata(pdev, dev); @@ -500,6 +506,14 @@ static struct net_device_stats *xircom_get_stats(struct net_device *dev) } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void xircom_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + xircom_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif static void initialize_card(struct xircom_private *card) diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c index 62417cc98..3db61f732 100644 --- a/drivers/net/tulip/xircom_tulip_cb.c +++ b/drivers/net/tulip/xircom_tulip_cb.c @@ -329,9 +329,6 @@ struct xircom_private { int saved_if_port; struct pci_dev *pdev; spinlock_t lock; -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif }; static int mdio_read(struct net_device *dev, int phy_id, int location); @@ -350,6 +347,7 @@ static struct net_device_stats *xircom_get_stats(struct net_device *dev); static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); static void check_duplex(struct net_device *dev); +static struct ethtool_ops ops; /* The Xircom cards are picky about when certain bits in CSR6 can be @@ -450,7 +448,7 @@ static void __devinit read_mac_address(struct net_device *dev) */ static void find_mii_transceivers(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int phy, phy_idx; if (media_cap[tp->default_port] & MediaIsMII) { @@ -505,7 +503,7 @@ static void find_mii_transceivers(struct net_device *dev) */ static void transceiver_voodoo(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ @@ -584,9 +582,9 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi /* Clear the missed-packet counter. */ (volatile int)inl(ioaddr + CSR8); - tp = dev->priv; + tp = netdev_priv(dev); - tp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&tp->lock); tp->pdev = pdev; tp->chip_id = chip_idx; /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */ @@ -626,6 +624,7 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi #endif dev->tx_timeout = xircom_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + SET_ETHTOOL_OPS(dev, &ops); transceiver_voodoo(dev); @@ -749,7 +748,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static void xircom_up(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -804,7 +803,7 @@ xircom_up(struct net_device *dev) static int xircom_open(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; @@ -818,7 +817,7 @@ xircom_open(struct net_device *dev) static void xircom_tx_timeout(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; if (media_cap[dev->if_port] & MediaIsMII) { @@ -870,7 +869,7 @@ static void xircom_tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void xircom_init_ring(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int i; tp->tx_full = 0; @@ -919,7 +918,7 @@ static void xircom_init_ring(struct net_device *dev) static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int entry; u32 flag; @@ -971,7 +970,7 @@ xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) static void xircom_media_change(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; u16 reg0, reg1, reg4, reg5; u32 csr6 = inl(ioaddr + CSR6), newcsr6; @@ -1032,7 +1031,7 @@ static void xircom_media_change(struct net_device *dev) static void check_duplex(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); u16 reg0; mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET); @@ -1065,7 +1064,7 @@ static void check_duplex(struct net_device *dev) static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = dev_instance; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; int csr5, work_budget = max_interrupt_work; int handled = 0; @@ -1203,7 +1202,7 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs static int xircom_rx(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; int work_done = 0; @@ -1303,7 +1302,7 @@ static void xircom_down(struct net_device *dev) { long ioaddr = dev->base_addr; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); /* Disable interrupts by clearing the interrupt mask. */ outl(0, ioaddr + CSR7); @@ -1321,7 +1320,7 @@ static int xircom_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int i; if (xircom_debug > 1) @@ -1359,7 +1358,7 @@ xircom_close(struct net_device *dev) static struct net_device_stats *xircom_get_stats(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; if (netif_device_present(dev)) @@ -1368,18 +1367,10 @@ static struct net_device_stats *xircom_get_stats(struct net_device *dev) return &tp->stats; } - -static int xircom_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - struct ethtool_cmd ecmd; - struct xircom_private *tp = dev->priv; - - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = + struct xircom_private *tp = netdev_priv(dev); + ecmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -1387,98 +1378,90 @@ static int xircom_ethtool_ioctl(struct net_device *dev, void __user *useraddr) SUPPORTED_Autoneg | SUPPORTED_MII; - ecmd.advertising = ADVERTISED_MII; - if (tp->advertising[0] & ADVERTISE_10HALF) - ecmd.advertising |= ADVERTISED_10baseT_Half; - if (tp->advertising[0] & ADVERTISE_10FULL) - ecmd.advertising |= ADVERTISED_10baseT_Full; - if (tp->advertising[0] & ADVERTISE_100HALF) - ecmd.advertising |= ADVERTISED_100baseT_Half; - if (tp->advertising[0] & ADVERTISE_100FULL) - ecmd.advertising |= ADVERTISED_100baseT_Full; - if (tp->autoneg) { - ecmd.advertising |= ADVERTISED_Autoneg; - ecmd.autoneg = AUTONEG_ENABLE; - } else - ecmd.autoneg = AUTONEG_DISABLE; - - ecmd.port = PORT_MII; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = tp->phys[0]; - ecmd.speed = tp->speed100 ? SPEED_100 : SPEED_10; - ecmd.duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd.maxtxpkt = TX_RING_SIZE / 2; - ecmd.maxrxpkt = 0; - - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; + ecmd->advertising = ADVERTISED_MII; + if (tp->advertising[0] & ADVERTISE_10HALF) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->advertising[0] & ADVERTISE_10FULL) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->advertising[0] & ADVERTISE_100HALF) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->advertising[0] & ADVERTISE_100FULL) + ecmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->autoneg) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + } else + ecmd->autoneg = AUTONEG_DISABLE; + + ecmd->port = PORT_MII; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = tp->phys[0]; + ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10; + ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + ecmd->maxtxpkt = TX_RING_SIZE / 2; + ecmd->maxrxpkt = 0; + return 0; +} - case ETHTOOL_SSET: { - u16 autoneg, speed100, full_duplex; - - autoneg = (ecmd.autoneg == AUTONEG_ENABLE); - speed100 = (ecmd.speed == SPEED_100); - full_duplex = (ecmd.duplex == DUPLEX_FULL); - - tp->autoneg = autoneg; - if (speed100 != tp->speed100 || - full_duplex != tp->full_duplex) { - tp->speed100 = speed100; - tp->full_duplex = full_duplex; - /* change advertising bits */ - tp->advertising[0] &= ~(ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL | - ADVERTISE_100BASE4); - if (speed100) { - if (full_duplex) - tp->advertising[0] |= ADVERTISE_100FULL; - else - tp->advertising[0] |= ADVERTISE_100HALF; - } else { - if (full_duplex) - tp->advertising[0] |= ADVERTISE_10FULL; - else - tp->advertising[0] |= ADVERTISE_10HALF; - } +static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct xircom_private *tp = netdev_priv(dev); + u16 autoneg, speed100, full_duplex; + + autoneg = (ecmd->autoneg == AUTONEG_ENABLE); + speed100 = (ecmd->speed == SPEED_100); + full_duplex = (ecmd->duplex == DUPLEX_FULL); + + tp->autoneg = autoneg; + if (speed100 != tp->speed100 || + full_duplex != tp->full_duplex) { + tp->speed100 = speed100; + tp->full_duplex = full_duplex; + /* change advertising bits */ + tp->advertising[0] &= ~(ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL | + ADVERTISE_100BASE4); + if (speed100) { + if (full_duplex) + tp->advertising[0] |= ADVERTISE_100FULL; + else + tp->advertising[0] |= ADVERTISE_100HALF; + } else { + if (full_duplex) + tp->advertising[0] |= ADVERTISE_10FULL; + else + tp->advertising[0] |= ADVERTISE_10HALF; } - check_duplex(dev); - return 0; - } - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info; - memset(&info, 0, sizeof(info)); - info.cmd = ecmd.cmd; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - *info.fw_version = 0; - strcpy(info.bus_info, pci_name(tp->pdev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; } + check_duplex(dev); + return 0; +} - default: - return -EOPNOTSUPP; - } +static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct xircom_private *tp = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(tp->pdev)); } +static struct ethtool_ops ops = { + .get_settings = xircom_get_settings, + .set_settings = xircom_set_settings, + .get_drvinfo = xircom_get_drvinfo, +}; /* Provide ioctl() calls to examine the MII xcvr state. */ static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); u16 *data = (u16 *)&rq->ifr_ifru; int phy = tp->phys[0] & 0x1f; unsigned long flags; switch(cmd) { - case SIOCETHTOOL: - return xircom_ethtool_ioctl(dev, rq->ifr_data); - /* Legacy mii-diag interface */ case SIOCGMIIPHY: /* Get address of MII PHY in use. */ if (tp->mii_cnt) @@ -1531,7 +1514,7 @@ static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) when re-entered but still correct. */ static void set_rx_mode(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); struct dev_mc_list *mclist; long ioaddr = dev->base_addr; int csr6 = inl(ioaddr + CSR6); @@ -1672,12 +1655,12 @@ MODULE_DEVICE_TABLE(pci, xircom_pci_table); static int xircom_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); printk(KERN_INFO "xircom_suspend(%s)\n", dev->name); if (tp->open) xircom_down(dev); - pci_save_state(pdev, tp->pci_state); + pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, 3); @@ -1688,12 +1671,12 @@ static int xircom_suspend(struct pci_dev *pdev, u32 state) static int xircom_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); printk(KERN_INFO "xircom_resume(%s)\n", dev->name); pci_set_power_state(pdev,0); pci_enable_device(pdev); - pci_restore_state(pdev, tp->pci_state); + pci_restore_state(pdev); /* Bring the chip out of sleep mode. Caution: Snooze mode does not work with some boards! */ diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 142f5f52f..b7d706fb0 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -1,6 +1,6 @@ /* typhoon.c: A Linux Ethernet device driver for 3Com 3CR990 family of NICs */ /* - Written 2002-2003 by David Dillow + Written 2002-2004 by David Dillow Based on code written 1998-2000 by Donald Becker and Linux 2.2.x driver by David P. McLean . @@ -33,8 +33,16 @@ *) Waiting for a command response takes 8ms due to non-preemptable polling. Only significant for getting stats and creating SAs, but an ugly wart never the less. - *) I've not tested multicast. I think it works, but reports welcome. + + TODO: *) Doesn't do IPSEC offloading. Yet. Keep yer pants on, it's coming. + *) Add more support for ethtool (especially for NIC stats) + *) Allow disabling of RX checksum offloading + *) Fix MAC changing to work while the interface is up + (Need to put commands on the TX ring, which changes + the locking) + *) Add in FCS to {rx,tx}_bytes, since the hardware doesn't. See + http://oss.sgi.com/cgi-bin/mesg.cgi?a=netdev&i=20031215152211.7003fe8e.rddunlap%40osdl.org */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. @@ -85,8 +93,8 @@ static const int multicast_filter_limit = 32; #define PKT_BUF_SZ 1536 #define DRV_MODULE_NAME "typhoon" -#define DRV_MODULE_VERSION "1.5.3" -#define DRV_MODULE_RELDATE "03/12/15" +#define DRV_MODULE_VERSION "1.5.4" +#define DRV_MODULE_RELDATE "04/09/09" #define PFX DRV_MODULE_NAME ": " #define ERR_PFX KERN_ERR PFX @@ -107,13 +115,14 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include -#include #include #include #include #include #include +#include #include "typhoon.h" #include "typhoon-firmware.h" @@ -248,11 +257,11 @@ struct typhoon { /* Tx cache line section */ struct transmit_ring txLoRing ____cacheline_aligned; struct pci_dev * tx_pdev; - unsigned long tx_ioaddr; + void __iomem *tx_ioaddr; u32 txlo_dma_addr; /* Irq/Rx cache line section */ - unsigned long ioaddr ____cacheline_aligned; + void __iomem *ioaddr ____cacheline_aligned; struct typhoon_indexes *indexes; u8 awaiting_resp; u8 duplex; @@ -279,7 +288,6 @@ struct typhoon { u16 xcvr_select; u16 wol_events; u32 offload; - u32 pci_state[16]; /* unused stuff (future use) */ int capabilities; @@ -373,7 +381,7 @@ typhoon_inc_rx_index(u32 *index, const int count) } static int -typhoon_reset(unsigned long ioaddr, int wait_type) +typhoon_reset(void __iomem *ioaddr, int wait_type) { int i, err = 0; int timeout; @@ -410,25 +418,26 @@ typhoon_reset(unsigned long ioaddr, int wait_type) out: writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS); - udelay(100); - return err; /* The 3XP seems to need a little extra time to complete the load * of the sleep image before we can reliably boot it. Failure to * do this occasionally results in a hung adapter after boot in * typhoon_init_one() while trying to read the MAC address or * putting the card to sleep. 3Com's driver waits 5ms, but - * that seems to be overkill -- with a 50usec delay, it survives - * 35000 typhoon_init_one() calls, where it only make it 25-100 - * without it. - * - * As it turns out, still occasionally getting a hung adapter, - * so I'm bumping it to 100us. + * that seems to be overkill. However, if we can sleep, we might + * as well give it that much time. Otherwise, we'll give it 500us, + * which should be enough (I've see it work well at 100us, but still + * saw occasional problems.) */ + if(wait_type == WaitSleep) + msleep(5); + else + udelay(500); + return err; } static int -typhoon_wait_status(unsigned long ioaddr, u32 wait_value) +typhoon_wait_status(void __iomem *ioaddr, u32 wait_value) { int i, err = 0; @@ -688,7 +697,7 @@ out: static void typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; int err; @@ -726,7 +735,7 @@ typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) static void typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); spin_lock_bh(&tp->state_lock); if(tp->vlgrp) tp->vlgrp->vlan_devices[vid] = NULL; @@ -757,7 +766,7 @@ typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing, static int typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct transmit_ring *txRing; struct tx_desc *txd, *first_txd; dma_addr_t skb_dma; @@ -908,7 +917,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) static void typhoon_set_rx_mode(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; u32 mc_filter[2]; u16 filter; @@ -965,6 +974,9 @@ typhoon_do_get_stats(struct typhoon *tp) /* 3Com's Linux driver uses txMultipleCollisions as it's * collisions value, but there is some other collision info as well... + * + * The extra status reported would be a good candidate for + * ethtool_ops->get_{strings,stats}() */ stats->tx_packets = le32_to_cpu(s->txPackets); stats->tx_bytes = le32_to_cpu(s->txBytes); @@ -1002,7 +1014,7 @@ typhoon_do_get_stats(struct typhoon *tp) static struct net_device_stats * typhoon_get_stats(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct net_device_stats *stats = &tp->stats; struct net_device_stats *saved = &tp->stats_saved; @@ -1030,9 +1042,10 @@ typhoon_set_mac_address(struct net_device *dev, void *addr) return 0; } -static inline void -typhoon_ethtool_gdrvinfo(struct typhoon *tp, struct ethtool_drvinfo *info) +static void +typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { + struct typhoon *tp = netdev_priv(dev); struct pci_dev *pci_dev = tp->pdev; struct cmd_desc xp_cmd; struct resp_desc xp_resp[3]; @@ -1055,9 +1068,11 @@ typhoon_ethtool_gdrvinfo(struct typhoon *tp, struct ethtool_drvinfo *info) strcpy(info->bus_info, pci_name(pci_dev)); } -static inline void -typhoon_ethtool_gset(struct typhoon *tp, struct ethtool_cmd *cmd) +static int +typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { + struct typhoon *tp = netdev_priv(dev); + cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg; @@ -1107,15 +1122,19 @@ typhoon_ethtool_gset(struct typhoon *tp, struct ethtool_cmd *cmd) cmd->autoneg = AUTONEG_DISABLE; cmd->maxtxpkt = 1; cmd->maxrxpkt = 1; + + return 0; } -static inline int -typhoon_ethtool_sset(struct typhoon *tp, struct ethtool_cmd *cmd) +static int +typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; int xcvr; int err; + err = -EINVAL; if(cmd->autoneg == AUTONEG_ENABLE) { xcvr = TYPHOON_XCVR_AUTONEG; } else { @@ -1125,23 +1144,23 @@ typhoon_ethtool_sset(struct typhoon *tp, struct ethtool_cmd *cmd) else if(cmd->speed == SPEED_100) xcvr = TYPHOON_XCVR_100HALF; else - return -EINVAL; + goto out; } else if(cmd->duplex == DUPLEX_FULL) { if(cmd->speed == SPEED_10) xcvr = TYPHOON_XCVR_10FULL; else if(cmd->speed == SPEED_100) xcvr = TYPHOON_XCVR_100FULL; else - return -EINVAL; + goto out; } else - return -EINVAL; + goto out; } INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT); xp_cmd.parm1 = cpu_to_le16(xcvr); err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) - return err; + goto out; tp->xcvr_select = xcvr; if(cmd->autoneg == AUTONEG_ENABLE) { @@ -1152,95 +1171,82 @@ typhoon_ethtool_sset(struct typhoon *tp, struct ethtool_cmd *cmd) tp->duplex = cmd->duplex; } - return 0; +out: + return err; } -static inline int -typhoon_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void +typhoon_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct typhoon *tp = (struct typhoon *) dev->priv; - u32 ethcmd; - - if(copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - - typhoon_ethtool_gdrvinfo(tp, &info); - if(copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; + struct typhoon *tp = netdev_priv(dev); + + wol->supported = WAKE_PHY | WAKE_MAGIC; + wol->wolopts = 0; + if(tp->wol_events & TYPHOON_WAKE_LINK_EVENT) + wol->wolopts |= WAKE_PHY; + if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) + wol->wolopts |= WAKE_MAGIC; + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} - typhoon_ethtool_gset(tp, &cmd); - if(copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; - if(copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; +static int +typhoon_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct typhoon *tp = netdev_priv(dev); - return typhoon_ethtool_sset(tp, &cmd); - } - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; + if(wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC)) + return -EINVAL; - edata.data = netif_carrier_ok(dev) ? 1 : 0; - if(copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if(tp->wol_events & TYPHOON_WAKE_LINK_EVENT) - wol.wolopts |= WAKE_PHY; - if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) - wol.wolopts |= WAKE_MAGIC; - if(copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - - if(copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - tp->wol_events = 0; - if(wol.wolopts & WAKE_PHY) - tp->wol_events |= TYPHOON_WAKE_LINK_EVENT; - if(wol.wolopts & WAKE_MAGIC) - tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT; - return 0; - } - default: - break; - } + tp->wol_events = 0; + if(wol->wolopts & WAKE_PHY) + tp->wol_events |= TYPHOON_WAKE_LINK_EVENT; + if(wol->wolopts & WAKE_MAGIC) + tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT; - return -EOPNOTSUPP; + return 0; } -static int -typhoon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static u32 +typhoon_get_rx_csum(struct net_device *dev) { - switch (cmd) { - case SIOCETHTOOL: - return typhoon_ethtool_ioctl(dev, ifr->ifr_data); - default: - break; - } + /* For now, we don't allow turning off RX checksums. + */ + return 1; +} - return -EOPNOTSUPP; +static void +typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + ering->rx_max_pending = RXENT_ENTRIES; + ering->rx_mini_max_pending = 0; + ering->rx_jumbo_max_pending = 0; + ering->tx_max_pending = TXLO_ENTRIES - 1; + + ering->rx_pending = RXENT_ENTRIES; + ering->rx_mini_pending = 0; + ering->rx_jumbo_pending = 0; + ering->tx_pending = TXLO_ENTRIES - 1; } +static struct ethtool_ops typhoon_ethtool_ops = { + .get_settings = typhoon_get_settings, + .set_settings = typhoon_set_settings, + .get_drvinfo = typhoon_get_drvinfo, + .get_wol = typhoon_get_wol, + .set_wol = typhoon_set_wol, + .get_link = ethtool_op_get_link, + .get_rx_csum = typhoon_get_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, + .get_ringparam = typhoon_get_ringparam, +}; + static int -typhoon_wait_interrupt(unsigned long ioaddr) +typhoon_wait_interrupt(void __iomem *ioaddr) { int i, err = 0; @@ -1348,7 +1354,7 @@ typhoon_init_rings(struct typhoon *tp) static int typhoon_download_firmware(struct typhoon *tp) { - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; struct pci_dev *pdev = tp->pdev; struct typhoon_file_header *fHdr; struct typhoon_section_header *sHdr; @@ -1497,7 +1503,7 @@ err_out: static int typhoon_boot_3XP(struct typhoon *tp, u32 initial_status) { - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; if(typhoon_wait_status(ioaddr, initial_status) < 0) { printk(KERN_ERR "%s: boot ready timeout\n", tp->name); @@ -1756,7 +1762,7 @@ typhoon_fill_free_ring(struct typhoon *tp) static int typhoon_poll(struct net_device *dev, int *total_budget) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct typhoon_indexes *indexes = tp->indexes; int orig_budget = *total_budget; int budget, work_done, done; @@ -1812,7 +1818,8 @@ static irqreturn_t typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = (struct net_device *) dev_instance; - unsigned long ioaddr = dev->base_addr; + struct typhoon *tp = dev->priv; + void __iomem *ioaddr = tp->ioaddr; u32 intr_status; intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS); @@ -1852,7 +1859,7 @@ static int typhoon_sleep(struct typhoon *tp, int state, u16 events) { struct pci_dev *pdev = tp->pdev; - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; struct cmd_desc xp_cmd; int err; @@ -1890,10 +1897,10 @@ static int typhoon_wakeup(struct typhoon *tp, int wait_type) { struct pci_dev *pdev = tp->pdev; - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; pci_set_power_state(pdev, 0); - pci_restore_state(pdev, tp->pci_state); + pci_restore_state(pdev); /* Post 2.x.x versions of the Sleep Image require a reset before * we can download the Runtime Image. But let's not make users of @@ -1911,7 +1918,7 @@ static int typhoon_start_runtime(struct typhoon *tp) { struct net_device *dev = tp->dev; - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; struct cmd_desc xp_cmd; int err; @@ -2006,7 +2013,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type) { struct typhoon_indexes *indexes = tp->indexes; struct transmit_ring *txLo = &tp->txLoRing; - unsigned long ioaddr = tp->ioaddr; + void __iomem *ioaddr = tp->ioaddr; struct cmd_desc xp_cmd; int i; @@ -2068,9 +2075,9 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type) static void typhoon_tx_timeout(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); - if(typhoon_reset(dev->base_addr, WaitNoSleep) < 0) { + if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) { printk(KERN_WARNING "%s: could not reset in tx timeout\n", dev->name); goto truely_dead; @@ -2091,14 +2098,14 @@ typhoon_tx_timeout(struct net_device *dev) truely_dead: /* Reset the hardware, and turn off carrier to avoid more timeouts */ - typhoon_reset(dev->base_addr, NoWait); + typhoon_reset(tp->ioaddr, NoWait); netif_carrier_off(dev); } static int typhoon_open(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); int err; err = typhoon_wakeup(tp, WaitSleep); @@ -2126,7 +2133,7 @@ out_sleep: if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { printk(KERN_ERR "%s: unable to reboot into sleep img\n", dev->name); - typhoon_reset(dev->base_addr, NoWait); + typhoon_reset(tp->ioaddr, NoWait); goto out; } @@ -2140,7 +2147,7 @@ out: static int typhoon_close(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); netif_stop_queue(dev); @@ -2168,7 +2175,7 @@ static int typhoon_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); /* If we're down, resume when we are upped. */ @@ -2192,7 +2199,7 @@ typhoon_resume(struct pci_dev *pdev) return 0; reset: - typhoon_reset(dev->base_addr, NoWait); + typhoon_reset(tp->ioaddr, NoWait); return -EBUSY; } @@ -2200,7 +2207,7 @@ static int typhoon_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; /* If we're down, we're already suspended. @@ -2276,6 +2283,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct typhoon *tp; int card_id = (int) ent->driver_data; unsigned long ioaddr; + void __iomem *ioaddr_mapped; void *shared; dma_addr_t shared_dma; struct cmd_desc xp_cmd; @@ -2303,17 +2311,17 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto error_out_dev; } - /* If we transitioned from D3->D0 in pci_enable_device(), - * we lost our configuration and need to restore it to the - * conditions at boot. - */ - pci_restore_state(pdev, NULL); + err = pci_set_mwi(pdev); + if(err < 0) { + printk(ERR_PFX "%s: unable to set MWI\n", pci_name(pdev)); + goto error_out_disable; + } - err = pci_set_dma_mask(pdev, 0xffffffffULL); + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if(err < 0) { printk(ERR_PFX "%s: No usable DMA configuration\n", pci_name(pdev)); - goto error_out_dev; + goto error_out_mwi; } /* sanity checks, resource #1 is our mmio area @@ -2323,36 +2331,32 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "%s: region #1 not a PCI MMIO resource, aborting\n", pci_name(pdev)); err = -ENODEV; - goto error_out_dev; + goto error_out_mwi; } if(pci_resource_len(pdev, 1) < 128) { printk(ERR_PFX "%s: Invalid PCI MMIO region size, aborting\n", pci_name(pdev)); err = -ENODEV; - goto error_out_dev; + goto error_out_mwi; } err = pci_request_regions(pdev, "typhoon"); if(err < 0) { printk(ERR_PFX "%s: could not request regions\n", pci_name(pdev)); - goto error_out_dev; + goto error_out_mwi; } - pci_set_master(pdev); - pci_set_mwi(pdev); - /* map our MMIO region */ ioaddr = pci_resource_start(pdev, 1); - ioaddr = (unsigned long) ioremap(ioaddr, 128); - if(!ioaddr) { + ioaddr_mapped = ioremap(ioaddr, 128); + if (!ioaddr_mapped) { printk(ERR_PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev)); err = -EIO; goto error_out_regions; } - dev->base_addr = ioaddr; /* allocate pci dma space for rx and tx descriptor rings */ @@ -2366,17 +2370,17 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } dev->irq = pdev->irq; - tp = dev->priv; + tp = netdev_priv(dev); tp->shared = (struct typhoon_shared *) shared; tp->shared_dma = shared_dma; tp->pdev = pdev; tp->tx_pdev = pdev; - tp->ioaddr = dev->base_addr; - tp->tx_ioaddr = dev->base_addr; + tp->ioaddr = ioaddr_mapped; + tp->tx_ioaddr = ioaddr_mapped; tp->dev = dev; /* need to be able to restore PCI state after a suspend */ - pci_save_state(pdev, tp->pci_state); + pci_save_state(pdev); /* Init sequence: * 1) Reset the adapter to clear any bad juju @@ -2385,12 +2389,17 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * 4) Get the hardware address. * 5) Put the card to sleep. */ - if(typhoon_reset(ioaddr, WaitSleep) < 0) { + if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) { printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev)); err = -EIO; goto error_out_dma; } + /* Now that we've reset the 3XP and are sure it's not going to + * write all over memory, enable bus mastering. + */ + pci_set_master(pdev); + /* dev->name is not valid until we register, but we need to * use some common routines to initialize the card. So that those * routines print the right name, we keep our oun pointer to the name @@ -2464,9 +2473,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->watchdog_timeo = TX_TIMEOUT; dev->get_stats = typhoon_get_stats; dev->set_mac_address = typhoon_set_mac_address; - dev->do_ioctl = typhoon_ioctl; dev->vlan_rx_register = typhoon_vlan_rx_register; dev->vlan_rx_kill_vid = typhoon_vlan_rx_kill_vid; + SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops); /* We can handle scatter gather, up to 16 entries, and * we can do IP checksumming (only version 4, doh...) @@ -2518,15 +2527,19 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; error_out_reset: - typhoon_reset(ioaddr, NoWait); + typhoon_reset(ioaddr_mapped, NoWait); error_out_dma: pci_free_consistent(pdev, sizeof(struct typhoon_shared), shared, shared_dma); error_out_remap: - iounmap((void *) ioaddr); + iounmap(ioaddr_mapped); error_out_regions: pci_release_regions(pdev); +error_out_mwi: + pci_clear_mwi(pdev); +error_out_disable: + pci_disable_device(pdev); error_out_dev: free_netdev(dev); error_out: @@ -2537,16 +2550,17 @@ static void __devexit typhoon_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) (dev->priv); + struct typhoon *tp = netdev_priv(dev); unregister_netdev(dev); pci_set_power_state(pdev, 0); - pci_restore_state(pdev, tp->pci_state); - typhoon_reset(dev->base_addr, NoWait); - iounmap((char *) (dev->base_addr)); + pci_restore_state(pdev); + typhoon_reset(tp->ioaddr, NoWait); + iounmap(tp->ioaddr); pci_free_consistent(pdev, sizeof(struct typhoon_shared), tp->shared, tp->shared_dma); pci_release_regions(pdev); + pci_clear_mwi(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 6c9206301..55a5c09a0 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -125,11 +125,16 @@ LK1.1.19 (Roger Luethi) - Increase Tx threshold for unspecified errors + LK1.2.0-2.6 (Roger Luethi) + - Massive clean-up + - Rewrite PHY, media handling (remove options, full_duplex, backoff) + - Fix Tx engine race for good + */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.1.20-2.6" -#define DRV_RELDATE "May-23-2004" +#define DRV_VERSION "1.2.0-2.6" +#define DRV_RELDATE "June-10-2004" /* A few user-configurable values. @@ -142,22 +147,10 @@ static int max_interrupt_work = 20; Setting to > 1518 effectively disables this feature. */ static int rx_copybreak; -/* Select a backoff algorithm (Ethernet capture effect) */ -static int backoff; - -/* Used to pass the media type, etc. - Both 'options[]' and 'full_duplex[]' should exist for driver - interoperability. - The media type is usually passed in 'options[]'. - The default is autonegotiation for speed and duplex. - This should rarely be overridden. - Use option values 0x10/0x20 for 10Mbps, 0x100,0x200 for 100Mbps. - Use option values 0x10 and 0x100 for forcing half duplex fixed speed. - Use option values 0x20 and 0x200 for forcing full duplex operation. -*/ -#define MAX_UNITS 8 /* More are supported, limit only on options */ -static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +/* + * In case you are looking for 'options[]' or 'full_duplex[]', they + * are gone. Use ethtool(8) instead. + */ /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). The Rhine has a 64 element 8390-like hash table. */ @@ -200,8 +193,8 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -210,9 +203,6 @@ static const int multicast_filter_limit = 32; static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"; -static char shortname[] = DRV_NAME; - - /* This driver was written to use PCI memory space. Some early versions of the Rhine may only work correctly with I/O space accesses. */ #ifdef CONFIG_VIA_RHINE_MMIO @@ -239,15 +229,9 @@ MODULE_LICENSE("GPL"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(backoff, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); -MODULE_PARM_DESC(backoff, "VIA Rhine: Bits 0-3: backoff algorithm"); -MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex"); -MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)"); /* Theory of Operation @@ -350,24 +334,24 @@ The chip does not pad to minimum transmit length. enum rhine_revs { VT86C100A = 0x00, + VTunknown0 = 0x20, VT6102 = 0x40, VT8231 = 0x50, /* Integrated MAC */ VT8233 = 0x60, /* Integrated MAC */ VT8235 = 0x74, /* Integrated MAC */ VT8237 = 0x78, /* Integrated MAC */ - VTunknown0 = 0x7C, + VTunknown1 = 0x7C, VT6105 = 0x80, VT6105_B0 = 0x83, VT6105L = 0x8A, VT6107 = 0x8C, - VTunknown1 = 0x8E, - VT6105M = 0x90, + VTunknown2 = 0x8E, + VT6105M = 0x90, /* Management adapter */ }; enum rhine_quirks { rqWOL = 0x0001, /* Wake-On-LAN support */ rqForceReset = 0x0002, - rqDavicomPhy = 0x0020, rq6patterns = 0x0040, /* 6 instead of 4 patterns for WOL */ rqStatusWBRace = 0x0080, /* Tx Status Writeback Error possible */ rqRhineI = 0x0100, /* See comment below */ @@ -395,6 +379,7 @@ MODULE_DEVICE_TABLE(pci, rhine_pci_tbl); /* Offsets to the device registers. */ enum register_offsets { StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08, + ChipCmd1=0x09, IntrStatus=0x0C, IntrEnable=0x0E, MulticastFilter0=0x10, MulticastFilter1=0x14, RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54, @@ -403,8 +388,8 @@ enum register_offsets { ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, StickyHW=0x83, IntrStatus2=0x84, - WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6, - WOLcgClr=0xA7, + WOLcrSet=0xA0, PwcfgSet=0xA1, WOLcgSet=0xA3, WOLcrClr=0xA4, + WOLcrClr1=0xA6, WOLcgClr=0xA7, PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD, }; @@ -436,6 +421,15 @@ enum intr_status_bits { IntrTxErrSummary=0x082218, }; +/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */ +enum wol_bits { + WOLucast = 0x10, + WOLmagic = 0x20, + WOLbmcast = 0x30, + WOLlnkon = 0x40, + WOLlnkoff = 0x80, +}; + /* The Rx and Tx buffer descriptors. */ struct rx_desc { s32 rx_status; @@ -464,13 +458,12 @@ enum desc_status_bits { /* Bits in ChipCmd. */ enum chip_cmd_bits { - CmdInit=0x0001, CmdStart=0x0002, CmdStop=0x0004, CmdRxOn=0x0008, - CmdTxOn=0x0010, CmdTxDemand=0x0020, CmdRxDemand=0x0040, - CmdEarlyRx=0x0100, CmdEarlyTx=0x0200, CmdFDuplex=0x0400, - CmdNoTxPoll=0x0800, CmdReset=0x8000, + CmdInit=0x01, CmdStart=0x02, CmdStop=0x04, CmdRxOn=0x08, + CmdTxOn=0x10, Cmd1TxDemand=0x20, CmdRxDemand=0x40, + Cmd1EarlyRx=0x01, Cmd1EarlyTx=0x02, Cmd1FDuplex=0x04, + Cmd1NoTxPoll=0x08, Cmd1Reset=0x80, }; -#define MAX_MII_CNT 4 struct rhine_private { /* Descriptor rings */ struct rx_desc *rx_ring; @@ -492,8 +485,8 @@ struct rhine_private { dma_addr_t tx_bufs_dma; struct pci_dev *pdev; + long pioaddr; struct net_device_stats stats; - struct timer_list timer; /* Media monitoring timer. */ spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ @@ -502,23 +495,16 @@ struct rhine_private { unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; unsigned int rx_buf_sz; /* Based on MTU+slack. */ - u16 chip_cmd; /* Current setting for ChipCmd */ + u8 wolopts; - /* These values are keep track of the transceiver/media in use. */ u8 tx_thresh, rx_thresh; - /* MII transceiver section. */ - unsigned char phys[MAX_MII_CNT]; /* MII device addresses. */ - unsigned int mii_cnt; /* number of MIIs found, but only the first one is used */ - u16 mii_status; /* last read MII status */ struct mii_if_info mii_if; }; static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); -static void rhine_check_duplex(struct net_device *dev); -static void rhine_timer(unsigned long data); static void rhine_tx_timeout(struct net_device *dev); static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -530,6 +516,16 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; static int rhine_close(struct net_device *dev); +static void rhine_shutdown (struct device *gdev); + +#define RHINE_WAIT_FOR(condition) do { \ + int i=1024; \ + while (!(condition) && --i) \ + ; \ + if (debug > 1 && i < 512) \ + printk(KERN_INFO "%s: %4d cycles used @ %s:%d\n", \ + DRV_NAME, 1024-i, __func__, __LINE__); \ +} while(0) static inline u32 get_intr_status(struct net_device *dev) { @@ -546,12 +542,13 @@ static inline u32 get_intr_status(struct net_device *dev) /* * Get power related registers into sane state. - * Returns content of power-event (WOL) registers. + * Notify user about past WOL event. */ static void rhine_power_init(struct net_device *dev) { long ioaddr = dev->base_addr; struct rhine_private *rp = netdev_priv(dev); + u16 wolstat; if (rp->quirks & rqWOL) { /* Make sure chip is in power state D0 */ @@ -566,63 +563,109 @@ static void rhine_power_init(struct net_device *dev) if (rp->quirks & rq6patterns) writeb(0x03, ioaddr + WOLcrClr1); + /* Save power-event status bits */ + wolstat = readb(ioaddr + PwrcsrSet); + if (rp->quirks & rq6patterns) + wolstat |= (readb(ioaddr + PwrcsrSet1) & 0x03) << 8; + /* Clear power-event status bits */ writeb(0xFF, ioaddr + PwrcsrClr); if (rp->quirks & rq6patterns) writeb(0x03, ioaddr + PwrcsrClr1); + + if (wolstat) { + char *reason; + switch (wolstat) { + case WOLmagic: + reason = "Magic packet"; + break; + case WOLlnkon: + reason = "Link went up"; + break; + case WOLlnkoff: + reason = "Link went down"; + break; + case WOLucast: + reason = "Unicast packet"; + break; + case WOLbmcast: + reason = "Multicast/broadcast packet"; + break; + default: + reason = "Unknown"; + } + printk(KERN_INFO "%s: Woke system up. Reason: %s.\n", + DRV_NAME, reason); + } } } -static void wait_for_reset(struct net_device *dev, u32 quirks, char *name) +static void rhine_chip_reset(struct net_device *dev) { long ioaddr = dev->base_addr; - int boguscnt = 20; + struct rhine_private *rp = netdev_priv(dev); + writeb(Cmd1Reset, ioaddr + ChipCmd1); IOSYNC; - if (readw(ioaddr + ChipCmd) & CmdReset) { + if (readb(ioaddr + ChipCmd1) & Cmd1Reset) { printk(KERN_INFO "%s: Reset not complete yet. " - "Trying harder.\n", name); + "Trying harder.\n", DRV_NAME); - /* Rhine-II needs to be forced sometimes */ - if (quirks & rqForceReset) + /* Force reset */ + if (rp->quirks & rqForceReset) writeb(0x40, ioaddr + MiscCmd); - /* VT86C100A may need long delay after reset (dlink) */ - /* Seen on Rhine-II as well (rl) */ - while ((readw(ioaddr + ChipCmd) & CmdReset) && --boguscnt) - udelay(5); - + /* Reset can take somewhat longer (rare) */ + RHINE_WAIT_FOR(!(readb(ioaddr + ChipCmd1) & Cmd1Reset)); } if (debug > 1) - printk(KERN_INFO "%s: Reset %s.\n", name, - boguscnt ? "succeeded" : "failed"); + printk(KERN_INFO "%s: Reset %s.\n", dev->name, + (readb(ioaddr + ChipCmd1) & Cmd1Reset) ? + "failed" : "succeeded"); } #ifdef USE_MMIO -static void __devinit enable_mmio(long ioaddr, u32 quirks) +static void enable_mmio(long pioaddr, u32 quirks) { int n; if (quirks & rqRhineI) { /* More recent docs say that this bit is reserved ... */ - n = inb(ioaddr + ConfigA) | 0x20; - outb(n, ioaddr + ConfigA); + n = inb(pioaddr + ConfigA) | 0x20; + outb(n, pioaddr + ConfigA); } else { - n = inb(ioaddr + ConfigD) | 0x80; - outb(n, ioaddr + ConfigD); + n = inb(pioaddr + ConfigD) | 0x80; + outb(n, pioaddr + ConfigD); } } #endif -static void __devinit reload_eeprom(long ioaddr) +/* + * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM + * (plus 0x6C for Rhine-I/II) + */ +static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev) { - int i; - outb(0x20, ioaddr + MACRegEEcsr); - /* Typically 2 cycles to reload. */ - for (i = 0; i < 150; i++) - if (! (inb(ioaddr + MACRegEEcsr) & 0x20)) - break; + long ioaddr = dev->base_addr; + struct rhine_private *rp = netdev_priv(dev); + + outb(0x20, pioaddr + MACRegEEcsr); + RHINE_WAIT_FOR(!(inb(pioaddr + MACRegEEcsr) & 0x20)); + +#ifdef USE_MMIO + /* + * Reloading from EEPROM overwrites ConfigA-D, so we must re-enable + * MMIO. If reloading EEPROM was done first this could be avoided, but + * it is not known if that still works with the "win98-reboot" problem. + */ + enable_mmio(pioaddr, rp->quirks); +#endif + + /* Turn off EEPROM-controlled wake-up (magic packet) */ + if (rp->quirks & rqWOL) + writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); + } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -634,22 +677,33 @@ static void rhine_poll(struct net_device *dev) } #endif +static void rhine_hw_init(struct net_device *dev, long pioaddr) +{ + struct rhine_private *rp = netdev_priv(dev); + + /* Reset the chip to erase previous misconfiguration. */ + rhine_chip_reset(dev); + + /* Rhine-I needs extra time to recuperate before EEPROM reload */ + if (rp->quirks & rqRhineI) + msleep(5); + + /* Reload EEPROM controlled bytes cleared by soft reset */ + rhine_reload_eeprom(pioaddr, dev); +} + static int __devinit rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; struct rhine_private *rp; - int i, option, rc; + int i, rc; u8 pci_rev; u32 quirks; - static int card_idx = -1; - long ioaddr; + long pioaddr; long memaddr; - int io_size; - int phy, phy_idx = 0; -#ifdef USE_MMIO - long ioaddr0; -#endif + long ioaddr; + int io_size, phy_id; const char *name; /* when built into the kernel, we only print version if device is found */ @@ -659,26 +713,30 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, printk(version); #endif - card_idx++; - option = card_idx < MAX_UNITS ? options[card_idx] : 0; pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); io_size = 256; - if (pci_rev < VT6102) { - quirks = rqRhineI | rqDavicomPhy; + phy_id = 0; + quirks = 0; + name = "Rhine"; + if (pci_rev < VTunknown0) { + quirks = rqRhineI; io_size = 128; - name = "VT86C100A Rhine"; } - else { + else if (pci_rev >= VT6102) { quirks = rqWOL | rqForceReset; if (pci_rev < VT6105) { name = "Rhine II"; quirks |= rqStatusWBRace; /* Rhine-II exclusive */ } else { - name = "Rhine III"; + phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */ if (pci_rev >= VT6105_B0) quirks |= rq6patterns; + if (pci_rev < VT6105M) + name = "Rhine III"; + else + name = "Rhine III (Management Adapter)"; } } @@ -702,28 +760,31 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, goto err_out; } - ioaddr = pci_resource_start(pdev, 0); + pioaddr = pci_resource_start(pdev, 0); memaddr = pci_resource_start(pdev, 1); pci_set_master(pdev); - dev = alloc_etherdev(sizeof(*rp)); - if (dev == NULL) { + dev = alloc_etherdev(sizeof(struct rhine_private)); + if (!dev) { rc = -ENOMEM; - printk(KERN_ERR "init_ethernet failed for card #%d\n", - card_idx); + printk(KERN_ERR "alloc_etherdev failed\n"); goto err_out; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - rc = pci_request_regions(pdev, shortname); + rp = netdev_priv(dev); + rp->quirks = quirks; + rp->pioaddr = pioaddr; + rp->pdev = pdev; + + rc = pci_request_regions(pdev, DRV_NAME); if (rc) goto err_out_free_netdev; #ifdef USE_MMIO - ioaddr0 = ioaddr; - enable_mmio(ioaddr0, quirks); + enable_mmio(pioaddr, quirks); ioaddr = (long) ioremap(memaddr, io_size); if (!ioaddr) { @@ -737,7 +798,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, i = 0; while (mmio_verify_registers[i]) { int reg = mmio_verify_registers[i++]; - unsigned char a = inb(ioaddr0+reg); + unsigned char a = inb(pioaddr+reg); unsigned char b = readb(ioaddr+reg); if (a != b) { rc = -EIO; @@ -746,65 +807,38 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, goto err_out_unmap; } } +#else + ioaddr = pioaddr; #endif /* USE_MMIO */ + dev->base_addr = ioaddr; - rp = netdev_priv(dev); - rp->quirks = quirks; + /* Get chip registers into a sane state */ rhine_power_init(dev); - - /* Reset the chip to erase previous misconfiguration. */ - writew(CmdReset, ioaddr + ChipCmd); - - wait_for_reset(dev, quirks, shortname); - - /* Reload the station address from the EEPROM. */ -#ifdef USE_MMIO - 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, quirks); -#else - reload_eeprom(ioaddr); -#endif + rhine_hw_init(dev, pioaddr); for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ioaddr + StationAddr + i); if (!is_valid_ether_addr(dev->dev_addr)) { rc = -EIO; - printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx); + printk(KERN_ERR "Invalid MAC address\n"); goto err_out_unmap; } - if (quirks & rqWOL) { - /* - * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA - * turned on. it makes MAC receive magic packet - * automatically. So, we turn it off. (D-Link) - */ - writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); - } - - /* Select backoff algorithm */ - if (backoff) - writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff), - ioaddr + ConfigD); + /* For Rhine-I/II, phy_id is loaded from EEPROM */ + if (!phy_id) + phy_id = readb(ioaddr + 0x6C); dev->irq = pdev->irq; spin_lock_init(&rp->lock); - rp->pdev = pdev; rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; rp->mii_if.mdio_write = mdio_write; rp->mii_if.phy_id_mask = 0x1f; rp->mii_if.reg_num_mask = 0x1f; - if (dev->mem_start) - option = dev->mem_start; - /* The chip-specific entries in the device structure. */ dev->open = rhine_open; dev->hard_start_xmit = rhine_start_tx; @@ -826,20 +860,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if (rc) goto err_out_unmap; - /* The lower four bits are the media type. */ - if (option > 0) { - if (option & 0x220) - rp->mii_if.full_duplex = 1; - } - if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) - rp->mii_if.full_duplex = 1; - - if (rp->mii_if.full_duplex) { - printk(KERN_INFO "%s: Set to forced full duplex, " - "autonegotiation disabled.\n", dev->name); - rp->mii_if.force_media = 1; - } - printk(KERN_INFO "%s: VIA %s at 0x%lx, ", dev->name, name, #ifdef USE_MMIO @@ -855,17 +875,18 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - rp->phys[0] = 1; /* Standard for this chip. */ - for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, 1); + { + u16 mii_cmd; + int mii_status = mdio_read(dev, phy_id, 1); + mii_cmd = mdio_read(dev, phy_id, MII_BMCR) & ~BMCR_ISOLATE; + mdio_write(dev, phy_id, MII_BMCR, mii_cmd); if (mii_status != 0xffff && mii_status != 0x0000) { - rp->phys[phy_idx++] = phy; - rp->mii_if.advertising = mdio_read(dev, phy, 4); + rp->mii_if.advertising = mdio_read(dev, phy_id, 4); printk(KERN_INFO "%s: MII PHY found at address " "%d, status 0x%4.4x advertising %4.4x " - "Link %4.4x.\n", dev->name, phy, + "Link %4.4x.\n", dev->name, phy_id, mii_status, rp->mii_if.advertising, - mdio_read(dev, phy, 5)); + mdio_read(dev, phy_id, 5)); /* set IFF_RUNNING */ if (mii_status & BMSR_LSTATUS) @@ -873,27 +894,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, else netif_carrier_off(dev); - break; - } - } - rp->mii_cnt = phy_idx; - rp->mii_if.phy_id = rp->phys[0]; - - /* Allow forcing the media type. */ - if (option > 0) { - if (option & 0x220) - rp->mii_if.full_duplex = 1; - if (option & 0x330) { - printk(KERN_INFO " Forcing %dMbs %s-duplex " - "operation.\n", - (option & 0x300 ? 100 : 10), - (option & 0x220 ? "full" : "half")); - if (rp->mii_cnt) - mdio_write(dev, rp->phys[0], MII_BMCR, - ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */ - ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */ } } + rp->mii_if.phy_id = phy_id; return 0; @@ -1065,6 +1068,21 @@ static void free_tbufs(struct net_device* dev) } } +static void rhine_check_media(struct net_device *dev, unsigned int init_media) +{ + struct rhine_private *rp = netdev_priv(dev); + long ioaddr = dev->base_addr; + + mii_check_media(&rp->mii_if, debug, init_media); + + if (rp->mii_if.full_duplex) + writeb(readb(ioaddr + ChipCmd1) | Cmd1FDuplex, + ioaddr + ChipCmd1); + else + writeb(readb(ioaddr + ChipCmd1) & ~Cmd1FDuplex, + ioaddr + ChipCmd1); +} + static void init_registers(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); @@ -1080,7 +1098,6 @@ static void init_registers(struct net_device *dev) writeb(0x20, ioaddr + TxConfig); rp->tx_thresh = 0x20; rp->rx_thresh = 0x60; /* Written in rhine_set_rx_mode(). */ - rp->mii_if.full_duplex = 0; writel(rp->rx_ring_dma, ioaddr + RxRingPtr); writel(rp->tx_ring_dma, ioaddr + TxRingPtr); @@ -1094,17 +1111,44 @@ static void init_registers(struct net_device *dev) IntrPCIErr | IntrStatsMax | IntrLinkChange, ioaddr + IntrEnable); - rp->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll; - if (rp->mii_if.force_media) - rp->chip_cmd |= CmdFDuplex; - writew(rp->chip_cmd, ioaddr + ChipCmd); + writew(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8), + ioaddr + ChipCmd); + rhine_check_media(dev, 1); +} + +/* Enable MII link status auto-polling (required for IntrLinkChange) */ +static void rhine_enable_linkmon(long ioaddr) +{ + writeb(0, ioaddr + MIICmd); + writeb(MII_BMSR, ioaddr + MIIRegAddr); + writeb(0x80, ioaddr + MIICmd); + + RHINE_WAIT_FOR((readb(ioaddr + MIIRegAddr) & 0x20)); + + writeb(MII_BMSR | 0x40, ioaddr + MIIRegAddr); +} + +/* Disable MII link status auto-polling (required for MDIO access) */ +static void rhine_disable_linkmon(long ioaddr, u32 quirks) +{ + writeb(0, ioaddr + MIICmd); + + if (quirks & rqRhineI) { + writeb(0x01, ioaddr + MIIRegAddr); // MII_BMSR + + /* Can be called from ISR. Evil. */ + mdelay(1); + + /* 0x80 must be set immediately before turning it off */ + writeb(0x80, ioaddr + MIICmd); - rhine_check_duplex(dev); + RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x20); - /* The LED outputs of various MII xcvrs should be configured. */ - /* For NS or Mison phys, turn on bit 1 in register 0x17 */ - mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) | - 0x0001); + /* Heh. Now clear 0x80 again. */ + writeb(0, ioaddr + MIICmd); + } + else + RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x80); } /* Read and write over the MII Management Data I/O (MDIO) interface. */ @@ -1112,156 +1156,72 @@ static void init_registers(struct net_device *dev) static int mdio_read(struct net_device *dev, int phy_id, int regnum) { long ioaddr = dev->base_addr; - int boguscnt = 1024; + struct rhine_private *rp = netdev_priv(dev); + int result; - /* Wait for a previous command to complete. */ - while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0) - ; - writeb(0x00, ioaddr + MIICmd); + rhine_disable_linkmon(ioaddr, rp->quirks); + + /* rhine_disable_linkmon already cleared MIICmd */ writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); writeb(0x40, ioaddr + MIICmd); /* Trigger read */ - boguscnt = 1024; - while ((readb(ioaddr + MIICmd) & 0x40) && --boguscnt > 0) - ; - return readw(ioaddr + MIIData); + RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x40)); + result = readw(ioaddr + MIIData); + + rhine_enable_linkmon(ioaddr); + return result; } static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value) { struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - int boguscnt = 1024; - if (phy_id == rp->phys[0]) { - switch (regnum) { - case MII_BMCR: /* Is user forcing speed/duplex? */ - if (value & 0x9000) /* Autonegotiation. */ - rp->mii_if.force_media = 0; - else - rp->mii_if.full_duplex = (value & 0x0100) ? 1 : 0; - break; - case MII_ADVERTISE: - rp->mii_if.advertising = value; - break; - } - } + rhine_disable_linkmon(ioaddr, rp->quirks); - /* Wait for a previous command to complete. */ - while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0) - ; - writeb(0x00, ioaddr + MIICmd); + /* rhine_disable_linkmon already cleared MIICmd */ writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); writew(value, ioaddr + MIIData); - writeb(0x20, ioaddr + MIICmd); /* Trigger write. */ -} + writeb(0x20, ioaddr + MIICmd); /* Trigger write */ + RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x20)); + rhine_enable_linkmon(ioaddr); +} static int rhine_open(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - int i; - - /* Reset the chip. */ - writew(CmdReset, ioaddr + ChipCmd); + int rc; - i = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name, + rc = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name, dev); - if (i) - return i; + if (rc) + return rc; if (debug > 1) printk(KERN_DEBUG "%s: rhine_open() irq %d.\n", dev->name, rp->pdev->irq); - i = alloc_ring(dev); - if (i) - return i; + rc = alloc_ring(dev); + if (rc) + return rc; alloc_rbufs(dev); alloc_tbufs(dev); - wait_for_reset(dev, rp->quirks, dev->name); + rhine_chip_reset(dev); init_registers(dev); if (debug > 2) printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x " "MII status: %4.4x.\n", dev->name, readw(ioaddr + ChipCmd), - mdio_read(dev, rp->phys[0], MII_BMSR)); + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); netif_start_queue(dev); - /* Set the timer to check for link beat. */ - init_timer(&rp->timer); - rp->timer.expires = jiffies + 2 * HZ/100; - rp->timer.data = (unsigned long)dev; - rp->timer.function = &rhine_timer; /* timer handler */ - add_timer(&rp->timer); - return 0; } -static void rhine_check_duplex(struct net_device *dev) -{ - struct rhine_private *rp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int mii_lpa = mdio_read(dev, rp->phys[0], MII_LPA); - int negotiated = mii_lpa & rp->mii_if.advertising; - int duplex; - - if (rp->mii_if.force_media || mii_lpa == 0xffff) - return; - duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; - if (rp->mii_if.full_duplex != duplex) { - rp->mii_if.full_duplex = duplex; - if (debug) - printk(KERN_INFO "%s: Setting %s-duplex based on " - "MII #%d link partner capability of %4.4x.\n", - dev->name, duplex ? "full" : "half", - rp->phys[0], mii_lpa); - if (duplex) - rp->chip_cmd |= CmdFDuplex; - else - rp->chip_cmd &= ~CmdFDuplex; - writew(rp->chip_cmd, ioaddr + ChipCmd); - } -} - - -static void rhine_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct rhine_private *rp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int next_tick = 10*HZ; - int mii_status; - - if (debug > 3) { - printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n", - dev->name, readw(ioaddr + IntrStatus)); - } - - spin_lock_irq (&rp->lock); - - rhine_check_duplex(dev); - - /* make IFF_RUNNING follow the MII status bit "Link established" */ - mii_status = mdio_read(dev, rp->phys[0], MII_BMSR); - if ((mii_status & BMSR_LSTATUS) != (rp->mii_status & BMSR_LSTATUS)) { - if (mii_status & BMSR_LSTATUS) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - } - rp->mii_status = mii_status; - - spin_unlock_irq(&rp->lock); - - rp->timer.expires = jiffies + next_tick; - add_timer(&rp->timer); -} - - static void rhine_tx_timeout(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); @@ -1270,16 +1230,13 @@ static void rhine_tx_timeout(struct net_device *dev) printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " "%4.4x, resetting...\n", dev->name, readw(ioaddr + IntrStatus), - mdio_read(dev, rp->phys[0], MII_BMSR)); + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); /* protect against concurrent rx interrupts */ disable_irq(rp->pdev->irq); spin_lock(&rp->lock); - /* Reset the chip. */ - writew(CmdReset, ioaddr + ChipCmd); - /* clear all descriptors */ free_tbufs(dev); free_rbufs(dev); @@ -1287,7 +1244,7 @@ static void rhine_tx_timeout(struct net_device *dev) alloc_rbufs(dev); /* Reinitialize the hardware. */ - wait_for_reset(dev, rp->quirks, dev->name); + rhine_chip_reset(dev); init_registers(dev); spin_unlock(&rp->lock); @@ -1301,8 +1258,8 @@ static void rhine_tx_timeout(struct net_device *dev) static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); + long ioaddr = dev->base_addr; unsigned entry; - u32 intr_status; /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -1353,14 +1310,9 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) /* Non-x86 Todo: explicitly flush cache lines here. */ - /* - * Wake the potentially-idle transmit channel unless errors are - * pending (the ISR must sort them out first). - */ - intr_status = get_intr_status(dev); - if ((intr_status & IntrTxErrSummary) == 0) { - writew(CmdTxDemand | rp->chip_cmd, dev->base_addr + ChipCmd); - } + /* Wake the potentially-idle transmit channel */ + writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand, + ioaddr + ChipCmd1); IOSYNC; if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN) @@ -1408,11 +1360,10 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs * if (intr_status & (IntrTxErrSummary | IntrTxDone)) { if (intr_status & IntrTxErrSummary) { - int cnt = 20; /* Avoid scavenging before Tx engine turned off */ - while ((readw(ioaddr+ChipCmd) & CmdTxOn) && --cnt) - udelay(5); - if (debug > 2 && !cnt) + RHINE_WAIT_FOR(!(readb(ioaddr+ChipCmd) & CmdTxOn)); + if (debug > 2 && + readb(ioaddr+ChipCmd) & CmdTxOn) printk(KERN_WARNING "%s: " "rhine_interrupt() Tx engine" "still on.\n", dev->name); @@ -1572,10 +1523,6 @@ static void rhine_rx(struct net_device *dev) rp->rx_buf_sz, PCI_DMA_FROMDEVICE); - /* *_IP_COPYSUM isn't defined anywhere and - eth_copy_and_sum is memcpy for all archs so - this is kind of pointless right now - ... or? */ eth_copy_and_sum(skb, rp->rx_skbuff[entry]->tail, pkt_len, 0); @@ -1627,10 +1574,6 @@ static void rhine_rx(struct net_device *dev) } rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); } - - /* Pre-emptively restart Rx engine. */ - writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand, - dev->base_addr + ChipCmd); } /* @@ -1664,7 +1607,10 @@ static void rhine_restart_tx(struct net_device *dev) { writel(rp->tx_ring_dma + entry * sizeof(struct tx_desc), ioaddr + TxRingPtr); - writew(CmdTxDemand | rp->chip_cmd, ioaddr + ChipCmd); + writeb(readb(ioaddr + ChipCmd) | CmdTxOn, + ioaddr + ChipCmd); + writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand, + ioaddr + ChipCmd1); IOSYNC; } else { @@ -1684,20 +1630,8 @@ static void rhine_error(struct net_device *dev, int intr_status) spin_lock(&rp->lock); - if (intr_status & (IntrLinkChange)) { - if (readb(ioaddr + MIIStatus) & 0x02) { - /* Link failed, restart autonegotiation. */ - if (rp->quirks & rqRhineI) - mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300); - } else - rhine_check_duplex(dev); - if (debug) - printk(KERN_ERR "%s: MII status changed: " - "Autonegotiation advertising %4.4x partner " - "%4.4x.\n", dev->name, - mdio_read(dev, rp->phys[0], MII_ADVERTISE), - mdio_read(dev, rp->phys[0], MII_LPA)); - } + if (intr_status & IntrLinkChange) + rhine_check_media(dev, 0); if (intr_status & IntrStatsMax) { rp->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); rp->stats.rx_missed_errors += readw(ioaddr + RxMissed); @@ -1790,7 +1724,7 @@ static void rhine_set_rx_mode(struct net_device *dev) i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); } writel(mc_filter[0], ioaddr + MulticastFilter0); writel(mc_filter[1], ioaddr + MulticastFilter1); @@ -1856,6 +1790,39 @@ static void netdev_set_msglevel(struct net_device *dev, u32 value) debug = value; } +static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct rhine_private *rp = netdev_priv(dev); + + if (!(rp->quirks & rqWOL)) + return; + + spin_lock_irq(&rp->lock); + wol->supported = WAKE_PHY | WAKE_MAGIC | + WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; /* Untested */ + wol->wolopts = rp->wolopts; + spin_unlock_irq(&rp->lock); +} + +static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct rhine_private *rp = netdev_priv(dev); + u32 support = WAKE_PHY | WAKE_MAGIC | + WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; /* Untested */ + + if (!(rp->quirks & rqWOL)) + return -EINVAL; + + if (wol->wolopts & ~support) + return -EINVAL; + + spin_lock_irq(&rp->lock); + rp->wolopts = wol->wolopts; + spin_unlock_irq(&rp->lock); + + return 0; +} + static struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, .get_settings = netdev_get_settings, @@ -1864,6 +1831,8 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_link = netdev_get_link, .get_msglevel = netdev_get_msglevel, .set_msglevel = netdev_set_msglevel, + .get_wol = rhine_get_wol, + .set_wol = rhine_set_wol, .get_sg = ethtool_op_get_sg, .get_tx_csum = ethtool_op_get_tx_csum, }; @@ -1888,8 +1857,6 @@ static int rhine_close(struct net_device *dev) long ioaddr = dev->base_addr; struct rhine_private *rp = netdev_priv(dev); - del_timer_sync(&rp->timer); - spin_lock_irq(&rp->lock); netif_stop_queue(dev); @@ -1936,12 +1903,114 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +static void rhine_shutdown (struct device *gendev) +{ + struct pci_dev *pdev = to_pci_dev(gendev); + struct net_device *dev = pci_get_drvdata(pdev); + struct rhine_private *rp = netdev_priv(dev); + + long ioaddr = dev->base_addr; + + rhine_power_init(dev); + + /* Make sure we use pattern 0, 1 and not 4, 5 */ + if (rp->quirks & rq6patterns) + writeb(0x04, ioaddr + 0xA7); + + if (rp->wolopts & WAKE_MAGIC) + writeb(WOLmagic, ioaddr + WOLcrSet); + + if (rp->wolopts & (WAKE_BCAST|WAKE_MCAST)) + writeb(WOLbmcast, ioaddr + WOLcgSet); + + if (rp->wolopts & WAKE_PHY) + writeb(WOLlnkon | WOLlnkoff, ioaddr + WOLcrSet); + + if (rp->wolopts & WAKE_UCAST) + writeb(WOLucast, ioaddr + WOLcrSet); + + /* Enable legacy WOL (for old motherboards) */ + writeb(0x01, ioaddr + PwcfgSet); + writeb(readb(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW); + + /* Hit power state D3 (sleep) */ + writeb(readb(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW); + + /* TODO: Check use of pci_enable_wake() */ + +} + +#ifdef CONFIG_PM +static int rhine_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rhine_private *rp = netdev_priv(dev); + unsigned long flags; + + if (!netif_running(dev)) + return 0; + + netif_device_detach(dev); + pci_save_state(pdev); + + spin_lock_irqsave(&rp->lock, flags); + rhine_shutdown(&pdev->dev); + spin_unlock_irqrestore(&rp->lock, flags); + + free_irq(dev->irq, dev); + return 0; +} + +static int rhine_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rhine_private *rp = netdev_priv(dev); + unsigned long flags; + int ret; + + if (!netif_running(dev)) + return 0; + + if (request_irq(dev->irq, rhine_interrupt, SA_SHIRQ, dev->name, dev)) + printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name); + + ret = pci_set_power_state(pdev, 0); + if (debug > 1) + printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n", + dev->name, ret ? "failed" : "succeeded", ret); + + pci_restore_state(pdev); + + spin_lock_irqsave(&rp->lock, flags); +#ifdef USE_MMIO + enable_mmio(rp->pioaddr, rp->quirks); +#endif + rhine_power_init(dev); + free_tbufs(dev); + free_rbufs(dev); + alloc_tbufs(dev); + alloc_rbufs(dev); + init_registers(dev); + spin_unlock_irqrestore(&rp->lock, flags); + + netif_device_attach(dev); + + return 0; +} +#endif /* CONFIG_PM */ static struct pci_driver rhine_driver = { - .name = "via-rhine", + .name = DRV_NAME, .id_table = rhine_pci_tbl, .probe = rhine_init_one, .remove = __devexit_p(rhine_remove_one), +#ifdef CONFIG_PM + .suspend = rhine_suspend, + .resume = rhine_resume, +#endif /* CONFIG_PM */ + .driver = { + .shutdown = rhine_shutdown, + } }; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index f053d2a9e..1886fe6b9 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -78,6 +78,8 @@ #include #include #include +#include +#include #include "via-velocity.h" @@ -226,7 +228,10 @@ VELOCITY_PARAM(wol_opts, "Wake On Lan options"); VELOCITY_PARAM(int_works, "Number of packets per interrupt services"); -static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent); +static int rx_copybreak = 200; +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); + static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info); static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev); static void velocity_print_info(struct velocity_info *vptr); @@ -238,41 +243,54 @@ static void velocity_set_multi(struct net_device *dev); static struct net_device_stats *velocity_get_stats(struct net_device *dev); static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int velocity_close(struct net_device *dev); -static int velocity_rx_srv(struct velocity_info *vptr, int status); static int velocity_receive_frame(struct velocity_info *, int idx); static int velocity_alloc_rx_buf(struct velocity_info *, int idx); -static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type); static void velocity_free_rd_ring(struct velocity_info *vptr); static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *); static int velocity_soft_reset(struct velocity_info *vptr); static void mii_init(struct velocity_info *vptr, u32 mii_status); static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); static void velocity_print_link_status(struct velocity_info *vptr); -static void safe_disable_mii_autopoll(struct mac_regs * regs); +static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs); static void velocity_shutdown(struct velocity_info *vptr); static void enable_flow_control_ability(struct velocity_info *vptr); -static void enable_mii_autopoll(struct mac_regs * regs); -static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata); -static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data); -static int velocity_set_wol(struct velocity_info *vptr); -static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context); -static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context); -static u32 mii_check_media_mode(struct mac_regs * regs); -static u32 check_connection_type(struct mac_regs * regs); -static void velocity_init_cam_filter(struct velocity_info *vptr); +static void enable_mii_autopoll(struct mac_regs __iomem * regs); +static int velocity_mii_read(struct mac_regs __iomem *, u8 byIdx, u16 * pdata); +static int velocity_mii_write(struct mac_regs __iomem *, u8 byMiiAddr, u16 data); +static u32 mii_check_media_mode(struct mac_regs __iomem * regs); +static u32 check_connection_type(struct mac_regs __iomem * regs); static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status); #ifdef CONFIG_PM + static int velocity_suspend(struct pci_dev *pdev, u32 state); static int velocity_resume(struct pci_dev *pdev); static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr); static struct notifier_block velocity_inetaddr_notifier = { - notifier_call:velocity_netdev_event, + .notifier_call = velocity_netdev_event, }; -#endif /* CONFIG_PM */ +static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(velocity_dev_list); + +static void velocity_register_notifier(void) +{ + register_inetaddr_notifier(&velocity_inetaddr_notifier); +} + +static void velocity_unregister_notifier(void) +{ + unregister_inetaddr_notifier(&velocity_inetaddr_notifier); +} + +#else /* CONFIG_PM */ + +#define velocity_register_notifier() do {} while (0) +#define velocity_unregister_notifier() do {} while (0) + +#endif /* !CONFIG_PM */ /* * Internal board variants. At the moment we have only one @@ -289,8 +307,9 @@ static struct velocity_info_tbl chip_info_table[] = { */ static struct pci_device_id velocity_id_table[] __devinitdata = { - {0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]}, - {0,} + {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table}, + {0, } }; MODULE_DEVICE_TABLE(pci, velocity_id_table); @@ -326,12 +345,22 @@ static void __devexit velocity_remove1(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct velocity_info *vptr = dev->priv; +#ifdef CONFIG_PM + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + if (!list_empty(&velocity_dev_list)) + list_del(&vptr->list); + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); +#endif unregister_netdev(dev); iounmap(vptr->mac_regs); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); + + velocity_nics--; } /** @@ -433,9 +462,9 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index, static void velocity_init_cam_filter(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; - /* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */ + /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); WORD_REG_BITS_ON(MCFG_VIDFR, ®s->MCFG); @@ -474,16 +503,16 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) static void velocity_rx_reset(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; int i; - vptr->rd_used = vptr->rd_curr = 0; + vptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0; /* * Init state, all RD entries belong to the NIC */ for (i = 0; i < vptr->options.numrx; ++i) - vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC); + vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC; writew(vptr->options.numrx, ®s->RBRDU); writel(vptr->rd_pool_dma, ®s->RDBaseLo); @@ -503,7 +532,7 @@ static void velocity_rx_reset(struct velocity_info *vptr) static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; int i, mii_status; mac_wol_reset(regs); @@ -558,10 +587,15 @@ static void velocity_init_registers(struct velocity_info *vptr, writeb(WOLCFG_SAM | WOLCFG_SAB, ®s->WOLCFGSet); /* - * Bback off algorithm use original IEEE standard + * Back off algorithm use original IEEE standard */ BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), ®s->CFGB); + /* + * Init CAM filter + */ + velocity_init_cam_filter(vptr); + /* * Set packet filter: Receive directed and broadcast address */ @@ -586,8 +620,6 @@ static void velocity_init_registers(struct velocity_info *vptr, mac_tx_queue_run(regs, i); } - velocity_init_cam_filter(vptr); - init_flow_control_register(vptr); writel(CR0_STOP, ®s->CR0Clr); @@ -595,7 +627,6 @@ static void velocity_init_registers(struct velocity_info *vptr, mii_status = velocity_get_opt_media_mode(vptr); netif_stop_queue(vptr->dev); - mac_clear_isr(regs); mii_init(vptr, mii_status); @@ -623,7 +654,7 @@ static void velocity_init_registers(struct velocity_info *vptr, static int velocity_soft_reset(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; int i = 0; writel(CR0_SFRST, ®s->CR0Set); @@ -659,10 +690,10 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi int i; struct velocity_info_tbl *info = (struct velocity_info_tbl *) ent->driver_data; struct velocity_info *vptr; - struct mac_regs * regs; + struct mac_regs __iomem * regs; int ret = -ENOMEM; - if (velocity_nics++ >= MAX_UNITS) { + if (velocity_nics >= MAX_UNITS) { printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", velocity_nics); return -ENODEV; @@ -694,7 +725,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi vptr->dev = dev; - dev->priv = vptr; dev->irq = pdev->irq; ret = pci_enable_device(pdev); @@ -729,7 +759,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi dev->dev_addr[i] = readb(®s->PAR[i]); - velocity_get_options(&vptr->options, velocity_nics - 1, dev->name); + velocity_get_options(&vptr->options, velocity_nics, dev->name); /* * Mask out the options cannot be set to the chip @@ -775,6 +805,16 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi /* and leave the chip powered down */ pci_set_power_state(pdev, 3); +#ifdef CONFIG_PM + { + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + list_add(&vptr->list, &velocity_dev_list); + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); + } +#endif + velocity_nics++; out: return ret; @@ -827,9 +867,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_i vptr->io_size = info->io_size; vptr->num_txq = info->txqueue; vptr->multicast_limit = MCAM_SIZE; - spin_lock_init(&vptr->lock); - spin_lock_init(&vptr->xmit_lock); + INIT_LIST_HEAD(&vptr->list); } /** @@ -966,6 +1005,60 @@ static void velocity_free_rings(struct velocity_info *vptr) pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma); } +static inline void velocity_give_many_rx_descs(struct velocity_info *vptr) +{ + struct mac_regs __iomem *regs = vptr->mac_regs; + int avail, dirty, unusable; + + /* + * RD number must be equal to 4X per hardware spec + * (programming guide rev 1.20, p.13) + */ + if (vptr->rd_filled < 4) + return; + + wmb(); + + unusable = vptr->rd_filled & 0x0003; + dirty = vptr->rd_dirty - unusable; + for (avail = vptr->rd_filled & 0xfffc; avail; avail--) { + dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1; + vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC; + } + + writew(vptr->rd_filled & 0xfffc, ®s->RBRDU); + vptr->rd_filled = unusable; +} + +static int velocity_rx_refill(struct velocity_info *vptr) +{ + int dirty = vptr->rd_dirty, done = 0, ret = 0; + + do { + struct rx_desc *rd = vptr->rd_ring + dirty; + + /* Fine for an all zero Rx desc at init time as well */ + if (rd->rdesc0.owner == OWNED_BY_NIC) + break; + + if (!vptr->rd_info[dirty].skb) { + ret = velocity_alloc_rx_buf(vptr, dirty); + if (ret < 0) + break; + } + done++; + dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0; + } while (dirty != vptr->rd_curr); + + if (done) { + vptr->rd_dirty = dirty; + vptr->rd_filled += done; + velocity_give_many_rx_descs(vptr); + } + + return ret; +} + /** * velocity_init_rd_ring - set up receive ring * @vptr: velocity to configure @@ -976,9 +1069,7 @@ static void velocity_free_rings(struct velocity_info *vptr) static int velocity_init_rd_ring(struct velocity_info *vptr) { - int i, ret = -ENOMEM; - struct rx_desc *rd; - struct velocity_rd_info *rd_info; + int ret = -ENOMEM; unsigned int rsize = sizeof(struct velocity_rd_info) * vptr->options.numrx; @@ -987,28 +1078,20 @@ static int velocity_init_rd_ring(struct velocity_info *vptr) goto out; memset(vptr->rd_info, 0, rsize); - /* Init the RD ring entries */ - for (i = 0; i < vptr->options.numrx; i++) { - rd = &(vptr->rd_ring[i]); - rd_info = &(vptr->rd_info[i]); + vptr->rd_filled = vptr->rd_dirty = vptr->rd_curr = 0; - ret = velocity_alloc_rx_buf(vptr, i); - if (ret < 0) { - VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR - "%s: failed to allocate RX buffer.\n", - vptr->dev->name); - velocity_free_rd_ring(vptr); - goto out; - } - rd->rdesc0.owner = OWNED_BY_NIC; + ret = velocity_rx_refill(vptr); + if (ret < 0) { + VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: failed to allocate RX buffer.\n", vptr->dev->name); + velocity_free_rd_ring(vptr); } - vptr->rd_used = vptr->rd_curr = 0; out: return ret; } /** - * velocity_free_rd_ring - set up receive ring + * velocity_free_rd_ring - free receive ring * @vptr: velocity to clean up * * Free the receive buffers for each ring slot and any @@ -1025,7 +1108,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr) for (i = 0; i < vptr->options.numrx; i++) { struct velocity_rd_info *rd_info = &(vptr->rd_info[i]); - if (!rd_info->skb_dma) + if (!rd_info->skb) continue; pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, PCI_DMA_FROMDEVICE); @@ -1073,8 +1156,10 @@ static int velocity_init_td_ring(struct velocity_info *vptr) for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) { td = &(vptr->td_rings[j][i]); td_info = &(vptr->td_infos[j][i]); - td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ; - td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ; + td_info->buf = vptr->tx_bufs + + (j * vptr->options.numtx + i) * PKT_BUF_SZ; + td_info->buf_dma = vptr->tx_bufs_dma + + (j * vptr->options.numtx + i) * PKT_BUF_SZ; } vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0; } @@ -1146,40 +1231,27 @@ static void velocity_free_td_ring(struct velocity_info *vptr) static int velocity_rx_srv(struct velocity_info *vptr, int status) { - struct rx_desc *rd; struct net_device_stats *stats = &vptr->stats; - struct mac_regs * regs = vptr->mac_regs; int rd_curr = vptr->rd_curr; int works = 0; - while (1) { - - rd = &(vptr->rd_ring[rd_curr]); + do { + struct rx_desc *rd = vptr->rd_ring + rd_curr; - if ((vptr->rd_info[rd_curr]).skb == NULL) { - if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) - break; - } - - if (works++ > 15) + if (!vptr->rd_info[rd_curr].skb) break; if (rd->rdesc0.owner == OWNED_BY_NIC) break; + rmb(); + /* * Don't drop CE or RL error frame although RXOK is off - * FIXME: need to handle copybreak */ if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) { - if (velocity_receive_frame(vptr, rd_curr) == 0) { - if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) { - VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name); - break; - } - } else { + if (velocity_receive_frame(vptr, rd_curr) < 0) stats->rx_dropped++; - } } else { if (rd->rdesc0.RSR & RSR_CRC) stats->rx_crc_errors++; @@ -1191,26 +1263,20 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status) rd->inten = 1; - if (++vptr->rd_used >= 4) { - int i, rd_prev = rd_curr; - for (i = 0; i < 4; i++) { - if (--rd_prev < 0) - rd_prev = vptr->options.numrx - 1; - - rd = &(vptr->rd_ring[rd_prev]); - rd->rdesc0.owner = OWNED_BY_NIC; - } - writew(4, &(regs->RBRDU)); - vptr->rd_used -= 4; - } - vptr->dev->last_rx = jiffies; rd_curr++; if (rd_curr >= vptr->options.numrx) rd_curr = 0; - } + } while (++works <= 15); + vptr->rd_curr = rd_curr; + + if (works > 0 && velocity_rx_refill(vptr) < 0) { + VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: rx buf allocation failure\n", vptr->dev->name); + } + VAR_USED(stats); return works; } @@ -1241,6 +1307,65 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb) } } +/** + * velocity_rx_copy - in place Rx copy for small packets + * @rx_skb: network layer packet buffer candidate + * @pkt_size: received data size + * @rd: receive packet descriptor + * @dev: network device + * + * Replace the current skb that is scheduled for Rx processing by a + * shorter, immediatly allocated skb, if the received packet is small + * enough. This function returns a negative value if the received + * packet is too big or if memory is exhausted. + */ +static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size, + struct velocity_info *vptr) +{ + int ret = -1; + + if (pkt_size < rx_copybreak) { + struct sk_buff *new_skb; + + new_skb = dev_alloc_skb(pkt_size + 2); + if (new_skb) { + new_skb->dev = vptr->dev; + new_skb->ip_summed = rx_skb[0]->ip_summed; + + if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) + skb_reserve(new_skb, 2); + + memcpy(new_skb->data, rx_skb[0]->tail, pkt_size); + *rx_skb = new_skb; + ret = 0; + } + + } + return ret; +} + +/** + * velocity_iph_realign - IP header alignment + * @vptr: velocity we are handling + * @skb: network layer packet buffer + * @pkt_size: received data size + * + * Align IP header on a 2 bytes boundary. This behavior can be + * configured by the user. + */ +static inline void velocity_iph_realign(struct velocity_info *vptr, + struct sk_buff *skb, int pkt_size) +{ + /* FIXME - memmove ? */ + if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) { + int i; + + for (i = pkt_size; i >= 0; i--) + *(skb->data + i + 2) = *(skb->data + i); + skb_reserve(skb, 2); + } +} + /** * velocity_receive_frame - received packet processor * @vptr: velocity we are handling @@ -1252,9 +1377,11 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb) static int velocity_receive_frame(struct velocity_info *vptr, int idx) { + void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int); struct net_device_stats *stats = &vptr->stats; struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]); struct rx_desc *rd = &(vptr->rd_ring[idx]); + int pkt_len = rd->rdesc0.len; struct sk_buff *skb; if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) { @@ -1269,22 +1396,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) skb = rd_info->skb; skb->dev = vptr->dev; - pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, - PCI_DMA_FROMDEVICE); - rd_info->skb_dma = (dma_addr_t) NULL; - rd_info->skb = NULL; - - /* FIXME - memmove ? */ - if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) { - int i; - for (i = rd->rdesc0.len + 4; i >= 0; i--) - *(skb->data + i + 2) = *(skb->data + i); - skb->data += 2; - skb->tail += 2; - } - - skb_put(skb, (rd->rdesc0.len - 4)); - skb->protocol = eth_type_trans(skb, skb->dev); + pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma, + vptr->rx_buf_sz, PCI_DMA_FROMDEVICE); /* * Drop frame not meeting IEEE 802.3 @@ -1297,13 +1410,23 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) } } + pci_action = pci_dma_sync_single_for_device; + velocity_rx_csum(rd, skb); - - /* - * FIXME: need rx_copybreak handling - */ - stats->rx_bytes += skb->len; + if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) { + velocity_iph_realign(vptr, skb, pkt_len); + pci_action = pci_unmap_single; + rd_info->skb = NULL; + } + + pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, + PCI_DMA_FROMDEVICE); + + skb_put(skb, pkt_len - 4); + skb->protocol = eth_type_trans(skb, skb->dev); + + stats->rx_bytes += pkt_len; netif_rx(skb); return 0; @@ -1485,7 +1608,7 @@ static void velocity_error(struct velocity_info *vptr, int status) { if (status & ISR_TXSTLI) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; printk(KERN_ERR "TD structure errror TDindex=%hx\n", readw(®s->TDIdx[0])); BYTE_REG_BITS_ON(TXESR_TDSTR, ®s->TXESR); @@ -1497,7 +1620,7 @@ static void velocity_error(struct velocity_info *vptr, int status) } if (status & ISR_SRCI) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; int linked; if (vptr->options.spd_dpx == SPD_DPX_AUTO) { @@ -1715,7 +1838,7 @@ out_unlock: static void velocity_shutdown(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; mac_disable_int(regs); writel(CR0_STOP, ®s->CR0Set); writew(0xFFFF, ®s->TDCSRClr); @@ -1962,32 +2085,6 @@ static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs) } -/** - * ether_crc - ethernet CRC function - * - * Compute an ethernet CRC hash of the data block provided. This - * is not performance optimised but is not needed in performance - * critical code paths. - * - * FIXME: could we use shared code here ? - */ - -static inline u32 ether_crc(int length, unsigned char *data) -{ - static unsigned const ethernet_polynomial = 0x04c11db7U; - - int crc = -1; - - while (--length >= 0) { - unsigned char current_octet = *data++; - int bit; - for (bit = 0; bit < 8; bit++, current_octet >>= 1) { - crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); - } - } - return crc; -} - /** * velocity_set_multi - filter list change callback * @dev: network device @@ -2000,7 +2097,7 @@ static inline u32 ether_crc(int length, unsigned char *data) static void velocity_set_multi(struct net_device *dev) { struct velocity_info *vptr = dev->priv; - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; u8 rx_mode; int i; struct dev_mc_list *mclist; @@ -2123,13 +2220,13 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) */ static struct pci_driver velocity_driver = { - name:VELOCITY_NAME, - id_table:velocity_id_table, - probe:velocity_found1, - remove:velocity_remove1, + .name = VELOCITY_NAME, + .id_table = velocity_id_table, + .probe = velocity_found1, + .remove = __devexit_p(velocity_remove1), #ifdef CONFIG_PM - suspend:velocity_suspend, - resume:velocity_resume, + .suspend = velocity_suspend, + .resume = velocity_resume, #endif }; @@ -2145,11 +2242,11 @@ static struct pci_driver velocity_driver = { static int __init velocity_init_module(void) { int ret; - ret = pci_module_init(&velocity_driver); -#ifdef CONFIG_PM - register_inetaddr_notifier(&velocity_inetaddr_notifier); -#endif + velocity_register_notifier(); + ret = pci_module_init(&velocity_driver); + if (ret < 0) + velocity_unregister_notifier(); return ret; } @@ -2164,9 +2261,7 @@ static int __init velocity_init_module(void) static void __exit velocity_cleanup_module(void) { -#ifdef CONFIG_PM - unregister_inetaddr_notifier(&velocity_inetaddr_notifier); -#endif + velocity_unregister_notifier(); pci_unregister_driver(&velocity_driver); } @@ -2256,7 +2351,7 @@ static void mii_init(struct velocity_info *vptr, u32 mii_status) * Turn off the autopoll and wait for it to disable on the chip */ -static void safe_disable_mii_autopoll(struct mac_regs * regs) +static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs) { u16 ww; @@ -2277,7 +2372,7 @@ static void safe_disable_mii_autopoll(struct mac_regs * regs) * hardware. Wait for it to enable. */ -static void enable_mii_autopoll(struct mac_regs * regs) +static void enable_mii_autopoll(struct mac_regs __iomem * regs) { int ii; @@ -2310,7 +2405,7 @@ static void enable_mii_autopoll(struct mac_regs * regs) * on success or -ETIMEDOUT if the PHY did not respond. */ -static int velocity_mii_read(struct mac_regs * regs, u8 index, u16 *data) +static int velocity_mii_read(struct mac_regs __iomem *regs, u8 index, u16 *data) { u16 ww; @@ -2346,7 +2441,7 @@ static int velocity_mii_read(struct mac_regs * regs, u8 index, u16 *data) * on success or -ETIMEDOUT if the PHY did not respond. */ -static int velocity_mii_write(struct mac_regs * regs, u8 mii_addr, u16 data) +static int velocity_mii_write(struct mac_regs __iomem *regs, u8 mii_addr, u16 data) { u16 ww; @@ -2481,7 +2576,7 @@ static void set_mii_flow_control(struct velocity_info *vptr) static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) { u32 curr_status; - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; vptr->mii_status = mii_check_media_mode(vptr->mac_regs); curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL); @@ -2588,7 +2683,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) * accordingly */ -static u32 mii_check_media_mode(struct mac_regs * regs) +static u32 mii_check_media_mode(struct mac_regs __iomem * regs) { u32 status = 0; u16 ANAR; @@ -2624,7 +2719,7 @@ static u32 mii_check_media_mode(struct mac_regs * regs) return status; } -static u32 check_connection_type(struct mac_regs * regs) +static u32 check_connection_type(struct mac_regs __iomem * regs) { u32 status = 0; u8 PHYSR0; @@ -2669,7 +2764,7 @@ static u32 check_connection_type(struct mac_regs * regs) static void enable_flow_control_ability(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; switch (vptr->options.flow_cntl) { @@ -2746,7 +2841,7 @@ static void velocity_ethtool_down(struct net_device *dev) static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct velocity_info *vptr = dev->priv; - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; u32 status; status = check_connection_type(vptr->mac_regs); @@ -2794,7 +2889,7 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd static u32 velocity_get_link(struct net_device *dev) { struct velocity_info *vptr = dev->priv; - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 0 : 1; } @@ -2890,7 +2985,7 @@ static struct ethtool_ops velocity_ethtool_ops = { static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct velocity_info *vptr = dev->priv; - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; unsigned long flags; struct mii_ioctl_data *miidata = if_mii(ifr); int err; @@ -2936,9 +3031,9 @@ static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd static void velocity_save_context(struct velocity_info *vptr, struct velocity_context * context) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; u16 i; - u8 *ptr = (u8 *)regs; + u8 __iomem *ptr = (u8 __iomem *)regs; for (i = MAC_REG_PAR; i < MAC_REG_CR0_CLR; i += 4) *((u32 *) (context->mac_reg + i)) = readl(ptr + i); @@ -2962,9 +3057,9 @@ static void velocity_save_context(struct velocity_info *vptr, struct velocity_co static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; int i; - u8 *ptr = (u8 *)regs; + u8 __iomem *ptr = (u8 __iomem *)regs; for (i = MAC_REG_PAR; i < MAC_REG_CR0_SET; i += 4) { writel(*((u32 *) (context->mac_reg + i)), ptr + i); @@ -2992,172 +3087,6 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity } -static int velocity_suspend(struct pci_dev *pdev, u32 state) -{ - struct velocity_info *vptr = pci_get_drvdata(pdev); - unsigned long flags; - - if(!netif_running(vptr->dev)) - return 0; - - netif_device_detach(vptr->dev); - - spin_lock_irqsave(&vptr->lock, flags); - pci_save_state(pdev, vptr->pci_state); -#ifdef ETHTOOL_GWOL - if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) { - velocity_get_ip(vptr); - velocity_save_context(vptr, &vptr->context); - velocity_shutdown(vptr); - velocity_set_wol(vptr); - pci_enable_wake(pdev, 3, 1); - pci_set_power_state(pdev, 3); - } else { - velocity_save_context(vptr, &vptr->context); - velocity_shutdown(vptr); - pci_disable_device(pdev); - pci_set_power_state(pdev, state); - } -#else - pci_set_power_state(pdev, state); -#endif - spin_unlock_irqrestore(&vptr->lock, flags); - return 0; -} - -static int velocity_resume(struct pci_dev *pdev) -{ - struct velocity_info *vptr = pci_get_drvdata(pdev); - unsigned long flags; - int i; - - if(!netif_running(vptr->dev)) - return 0; - - pci_set_power_state(pdev, 0); - pci_enable_wake(pdev, 0, 0); - pci_restore_state(pdev, vptr->pci_state); - - mac_wol_reset(vptr->mac_regs); - - spin_lock_irqsave(&vptr->lock, flags); - velocity_restore_context(vptr, &vptr->context); - velocity_init_registers(vptr, VELOCITY_INIT_WOL); - mac_disable_int(vptr->mac_regs); - - velocity_tx_srv(vptr, 0); - - for (i = 0; i < vptr->num_txq; i++) { - if (vptr->td_used[i]) { - mac_tx_queue_wake(vptr->mac_regs, i); - } - } - - mac_enable_int(vptr->mac_regs); - spin_unlock_irqrestore(&vptr->lock, flags); - netif_device_attach(vptr->dev); - - return 0; -} - -static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) -{ - struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; - struct net_device *dev; - struct velocity_info *vptr; - - if (ifa) { - dev = ifa->ifa_dev->dev; - vptr = dev->priv; - velocity_get_ip(vptr); - } - return NOTIFY_DONE; -} -#endif - -/* - * Purpose: Functions to set WOL. - */ - -const static unsigned short crc16_tab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - - -static u32 mask_pattern[2][4] = { - {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */ - {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */ -}; - -/** - * ether_crc16 - compute ethernet CRC - * @len: buffer length - * @cp: buffer - * @crc16: initial CRC - * - * Compute a CRC value for a block of data. - * FIXME: can we use generic functions ? - */ - -static u16 ether_crc16(int len, u8 * cp, u16 crc16) -{ - while (len--) - crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff]; - return (crc16); -} - -/** - * bit_reverse - 16bit reverse - * @data: 16bit data t reverse - * - * Reverse the order of a 16bit value and return the reversed bits - */ - -static u16 bit_reverse(u16 data) -{ - u32 new = 0x00000000; - int ii; - - - for (ii = 0; ii < 16; ii++) { - new |= ((u32) (data & 1) << (31 - ii)); - data >>= 1; - } - - return (u16) (new >> 16); -} - /** * wol_calc_crc - WOL CRC * @pattern: data pattern @@ -3166,7 +3095,7 @@ static u16 bit_reverse(u16 data) * Compute the wake on lan crc hashes for the packet header * we are interested in. */ - + u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) { u16 crc = 0xFFFF; @@ -3186,12 +3115,12 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) continue; } mask >>= 1; - crc = ether_crc16(1, &(pattern[i * 8 + j]), crc); + crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1); } } /* Finally, invert the result once to get the correct data */ crc = ~crc; - return bit_reverse(crc); + return bitreverse(crc) >> 16; } /** @@ -3203,13 +3132,18 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) * * FIXME: check static buffer is safe here */ - + static int velocity_set_wol(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; static u8 buf[256]; int i; + static u32 mask_pattern[2][4] = { + {0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */ + {0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff} /* Magic Packet */ + }; + writew(0xFFFF, ®s->WOLCRClr); writeb(WOLCFG_SAB | WOLCFG_SAM, ®s->WOLCFGSet); writew(WOLCR_MAGIC_EN, ®s->WOLCRSet); @@ -3236,7 +3170,8 @@ static int velocity_set_wol(struct velocity_info *vptr) memcpy(arp->ar_tip, vptr->ip_addr, 4); - crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]); + crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, + (u8 *) & mask_pattern[0][0]); writew(crc, ®s->PatternCRC[0]); writew(WOLCR_ARP_EN, ®s->WOLCRSet); @@ -3275,3 +3210,92 @@ static int velocity_set_wol(struct velocity_info *vptr) return 0; } +static int velocity_suspend(struct pci_dev *pdev, u32 state) +{ + struct velocity_info *vptr = pci_get_drvdata(pdev); + unsigned long flags; + + if(!netif_running(vptr->dev)) + return 0; + + netif_device_detach(vptr->dev); + + spin_lock_irqsave(&vptr->lock, flags); + pci_save_state(pdev); +#ifdef ETHTOOL_GWOL + if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) { + velocity_get_ip(vptr); + velocity_save_context(vptr, &vptr->context); + velocity_shutdown(vptr); + velocity_set_wol(vptr); + pci_enable_wake(pdev, 3, 1); + pci_set_power_state(pdev, 3); + } else { + velocity_save_context(vptr, &vptr->context); + velocity_shutdown(vptr); + pci_disable_device(pdev); + pci_set_power_state(pdev, state); + } +#else + pci_set_power_state(pdev, state); +#endif + spin_unlock_irqrestore(&vptr->lock, flags); + return 0; +} + +static int velocity_resume(struct pci_dev *pdev) +{ + struct velocity_info *vptr = pci_get_drvdata(pdev); + unsigned long flags; + int i; + + if(!netif_running(vptr->dev)) + return 0; + + pci_set_power_state(pdev, 0); + pci_enable_wake(pdev, 0, 0); + pci_restore_state(pdev); + + mac_wol_reset(vptr->mac_regs); + + spin_lock_irqsave(&vptr->lock, flags); + velocity_restore_context(vptr, &vptr->context); + velocity_init_registers(vptr, VELOCITY_INIT_WOL); + mac_disable_int(vptr->mac_regs); + + velocity_tx_srv(vptr, 0); + + for (i = 0; i < vptr->num_txq; i++) { + if (vptr->td_used[i]) { + mac_tx_queue_wake(vptr->mac_regs, i); + } + } + + mac_enable_int(vptr->mac_regs); + spin_unlock_irqrestore(&vptr->lock, flags); + netif_device_attach(vptr->dev); + + return 0; +} + +static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; + + if (ifa) { + struct net_device *dev = ifa->ifa_dev->dev; + struct velocity_info *vptr; + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + list_for_each_entry(vptr, &velocity_dev_list, list) { + if (vptr->dev == dev) { + velocity_get_ip(vptr); + break; + } + } + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); + } + return NOTIFY_DONE; +} +#endif diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index 2175b8696..626e84f96 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -37,7 +37,6 @@ #define OPTION_DEFAULT { [0 ... MAX_UNITS-1] = -1} #define REV_ID_VT6110 (0) -#define DEVICE_ID (0x3119) #define BYTE_REG_BITS_ON(x,p) do { writeb(readb((p))|(x),(p));} while (0) #define WORD_REG_BITS_ON(x,p) do { writew(readw((p))|(x),(p));} while (0) @@ -1271,7 +1270,7 @@ enum velocity_cam_type { * provided mask buffer. */ -static inline void mac_get_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type) +static inline void mac_get_cam_mask(struct mac_regs __iomem * regs, u8 * mask, enum velocity_cam_type cam_type) { int i; /* Select CAM mask */ @@ -1303,7 +1302,7 @@ static inline void mac_get_cam_mask(struct mac_regs * regs, u8 * mask, enum velo * Store a new mask into a CAM */ -static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velocity_cam_type cam_type) +static inline void mac_set_cam_mask(struct mac_regs __iomem * regs, u8 * mask, enum velocity_cam_type cam_type) { int i; /* Select CAM mask */ @@ -1320,7 +1319,7 @@ static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velo /* disable CAMEN */ writeb(0, ®s->CAMADDR); - /* Select CAM mask */ + /* Select mar */ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); } @@ -1334,7 +1333,7 @@ static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velo * Load an address or vlan tag into a CAM */ -static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) +static inline void mac_set_cam(struct mac_regs __iomem * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) { int i; @@ -1361,7 +1360,7 @@ static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum v writeb(0, ®s->CAMADDR); - /* Select CAM mask */ + /* Select mar */ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); } @@ -1376,7 +1375,7 @@ static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum v * the caller. VLAN tags are 2 bytes the address cam entries are 6. */ -static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) +static inline void mac_get_cam(struct mac_regs __iomem * regs, int idx, u8 *addr, enum velocity_cam_type cam_type) { int i; @@ -1402,7 +1401,7 @@ static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum v writeb(0, ®s->CAMADDR); - /* Select CAM mask */ + /* Select mar */ BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, ®s->CAMCR); } @@ -1415,7 +1414,7 @@ static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum v * the rest of the logic from the result of sleep/wakeup */ -inline static void mac_wol_reset(struct mac_regs * regs) +inline static void mac_wol_reset(struct mac_regs __iomem * regs) { /* Turn off SWPTAG right after leaving power mode */ @@ -1734,17 +1733,12 @@ struct velocity_opt { }; struct velocity_info { - struct velocity_info *next; - struct velocity_info *prev; + struct list_head list; struct pci_dev *pdev; struct net_device *dev; struct net_device_stats stats; -#if CONFIG_PM - u32 pci_state[16]; -#endif - dma_addr_t rd_pool_dma; dma_addr_t td_pool_dma[TX_QUEUE_NO]; @@ -1754,7 +1748,7 @@ struct velocity_info { u8 ip_addr[4]; enum chip_type chip_id; - struct mac_regs * mac_regs; + struct mac_regs __iomem * mac_regs; unsigned long memaddr; unsigned long ioaddr; u32 io_size; @@ -1772,7 +1766,8 @@ struct velocity_info { struct velocity_td_info *td_infos[TX_QUEUE_NO]; int rd_curr; - int rd_used; + int rd_dirty; + u32 rd_filled; struct rx_desc *rd_ring; struct velocity_rd_info *rd_info; /* It's an array */ @@ -1793,7 +1788,6 @@ struct velocity_info { u8 mCAMmask[(MCAM_SIZE / 8)]; spinlock_t lock; - spinlock_t xmit_lock; int wol_opts; u8 wol_passwd[6]; @@ -1867,7 +1861,7 @@ static inline void velocity_update_hw_mibs(struct velocity_info *vptr) static inline void init_flow_control_register(struct velocity_info *vptr) { - struct mac_regs * regs = vptr->mac_regs; + struct mac_regs __iomem * regs = vptr->mac_regs; /* Set {XHITH1, XHITH0, XLTH1, XLTH0} in FlowCR1 to {1, 0, 1, 1} depend on RD=64, and Turn on XNOEN in FlowCR1 */ diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index e8cfa4fc9..625456ef9 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -56,7 +56,7 @@ static char *hw; /* pointer to hw=xxx command line string */ typedef struct card_s { struct net_device *dev; spinlock_t lock; /* TX lock */ - u8 *win0base; /* ISA window base address */ + u8 __iomem *win0base; /* ISA window base address */ u32 phy_winbase; /* ISA physical base address */ sync_serial_settings settings; int rxpart; /* partial frame received, next frame invalid*/ diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index dbd790168..67cf7377e 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -156,7 +156,7 @@ struct cosa_data { unsigned short startaddr; /* Firmware start address */ unsigned short busmaster; /* Use busmastering? */ int nchannels; /* # of channels on this card */ - int driver_status; /* For communicating with firware */ + int driver_status; /* For communicating with firmware */ int firmware_status; /* Downloaded, reseted, etc. */ long int rxbitmap, txbitmap; /* Bitmap of channels who are willing to send/receive data */ long int rxtx; /* RX or TX in progress? */ diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c index e59ad5f0f..6e74af62c 100644 --- a/drivers/net/wan/cycx_drv.c +++ b/drivers/net/wan/cycx_drv.c @@ -70,8 +70,8 @@ MODULE_LICENSE("GPL"); static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len); static void cycx_bootcfg(struct cycx_hw *hw); -static int reset_cyc2x(void *addr); -static int detect_cyc2x(void *addr); +static int reset_cyc2x(void __iomem *addr); +static int detect_cyc2x(void __iomem *addr); /* Miscellaneous functions */ static void delay_cycx(int sec); @@ -135,9 +135,8 @@ void cycx_drv_cleanup(void) * Return: 0 ok. * < 0 error */ EXPORT_SYMBOL(cycx_setup); -int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len) +int cycx_setup(struct cycx_hw *hw, void *cfm, u32 len, unsigned long dpmbase) { - long dpmbase = (long)hw->dpmbase; int err; /* Verify IRQ configuration options */ @@ -203,7 +202,7 @@ void cycx_intr(struct cycx_hw *hw) * o Set exec flag. * o Busy-wait until flag is reset. */ EXPORT_SYMBOL(cycx_exec); -int cycx_exec(void *addr) +int cycx_exec(void __iomem *addr) { u16 i = 0; /* wait till addr content is zeroed */ @@ -249,7 +248,7 @@ int cycx_poke(struct cycx_hw *hw, u32 addr, void *buf, u32 len) /* Load Aux Routines */ /* Reset board hardware. return 1 if memory exists at addr and 0 if not. */ -static int memory_exists(void *addr) +static int memory_exists(void __iomem *addr) { int tries = 0; @@ -267,9 +266,9 @@ static int memory_exists(void *addr) } /* Load reset code. */ -static void reset_load(void *addr, u8 *buffer, u32 cnt) +static void reset_load(void __iomem *addr, u8 *buffer, u32 cnt) { - void *pt_code = addr + RESET_OFFSET; + void __iomem *pt_code = addr + RESET_OFFSET; u16 i; /*, j; */ for (i = 0 ; i < cnt ; i++) { @@ -281,7 +280,7 @@ static void reset_load(void *addr, u8 *buffer, u32 cnt) /* Load buffer using boot interface. * o copy data from buffer to Cyclom-X memory * o wait for reset code to copy it to right portion of memory */ -static int buffer_load(void *addr, u8 *buffer, u32 cnt) +static int buffer_load(void __iomem *addr, u8 *buffer, u32 cnt) { memcpy_toio(addr + DATA_OFFSET, buffer, cnt); writew(GEN_BOOT_DAT, addr + CMD_OFFSET); @@ -290,7 +289,7 @@ static int buffer_load(void *addr, u8 *buffer, u32 cnt) } /* Set up entry point and kick start Cyclom-X CPU. */ -static void cycx_start(void *addr) +static void cycx_start(void __iomem *addr) { /* put in 0x30 offset the jump instruction to the code entry point */ writeb(0xea, addr + 0x30); @@ -304,9 +303,9 @@ static void cycx_start(void *addr) } /* Load and boot reset code. */ -static void cycx_reset_boot(void *addr, u8 *code, u32 len) +static void cycx_reset_boot(void __iomem *addr, u8 *code, u32 len) { - void *pt_start = addr + START_OFFSET; + void __iomem *pt_start = addr + START_OFFSET; writeb(0xea, pt_start++); /* jmp to f000:3f00 */ writeb(0x00, pt_start++); @@ -321,9 +320,9 @@ static void cycx_reset_boot(void *addr, u8 *code, u32 len) } /* Load data.bin file through boot (reset) interface. */ -static int cycx_data_boot(void *addr, u8 *code, u32 len) +static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len) { - void *pt_boot_cmd = addr + CMD_OFFSET; + void __iomem *pt_boot_cmd = addr + CMD_OFFSET; u32 i; /* boot buffer lenght */ @@ -352,9 +351,9 @@ static int cycx_data_boot(void *addr, u8 *code, u32 len) /* Load code.bin file through boot (reset) interface. */ -static int cycx_code_boot(void *addr, u8 *code, u32 len) +static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len) { - void *pt_boot_cmd = addr + CMD_OFFSET; + void __iomem *pt_boot_cmd = addr + CMD_OFFSET; u32 i; /* boot buffer lenght */ @@ -391,7 +390,7 @@ static int load_cyc2x(struct cycx_hw *hw, struct cycx_firmware *cfm, u32 len) u8 *reset_image, *data_image, *code_image; - void *pt_cycld = hw->dpmbase + 0x400; + void __iomem *pt_cycld = hw->dpmbase + 0x400; u16 cksum; /* Announce */ @@ -523,7 +522,7 @@ static void cycx_bootcfg(struct cycx_hw *hw) * Return 1 if detected o.k. or 0 if failed. * Note: This test is destructive! Adapter will be left in shutdown * state after the test. */ -static int detect_cyc2x(void *addr) +static int detect_cyc2x(void __iomem *addr) { reset_cyc2x(addr); @@ -545,7 +544,7 @@ static int get_option_index(long *optlist, long optval) } /* Reset adapter's CPU. */ -static int reset_cyc2x(void *addr) +static int reset_cyc2x(void __iomem *addr) { writeb(0, addr + RST_ENABLE); delay_cycx(2); diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c index 20b6a29a1..3dadcb42a 100644 --- a/drivers/net/wan/cycx_main.c +++ b/drivers/net/wan/cycx_main.c @@ -223,13 +223,12 @@ static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf) /* Configure hardware, load firmware, etc. */ memset(&card->hw, 0, sizeof(card->hw)); card->hw.irq = irq; - card->hw.dpmbase = (void *)conf->maddr; card->hw.dpmsize = CYCX_WINDOWSIZE; card->hw.fwid = CFID_X25_2X; - card->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&card->lock); init_waitqueue_head(&card->wait_stats); - rc = cycx_setup(&card->hw, conf->data, conf->data_size); + rc = cycx_setup(&card->hw, conf->data, conf->data_size, conf->maddr); if (rc) goto out_irq; diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c index cd1cd8569..5b48cd856 100644 --- a/drivers/net/wan/cycx_x25.c +++ b/drivers/net/wan/cycx_x25.c @@ -92,6 +92,8 @@ #include /* Cyclom 2X common user API definitions */ #include /* X.25 firmware API definitions */ +#include + /* Defines & Macros */ #define CYCX_X25_MAX_CMD_RETRY 5 #define CYCX_X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */ @@ -186,7 +188,7 @@ static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble), reset_timer(struct net_device *dev); static u8 bps_to_speed_code(u32 bps); -static u8 log2(u32 n); +static u8 cycx_log2(u32 n); static unsigned dec_to_uint(u8 *str, int len); @@ -231,7 +233,7 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf) /* Initialize protocol-specific fields */ card->mbox = card->hw.dpmbase + X25_MBOX_OFFS; card->u.x.connection_keys = 0; - card->u.x.lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&card->u.x.lock); /* Configure adapter. Here we set reasonable defaults, then parse * device configuration structure and set configuration options. @@ -263,7 +265,7 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf) else card->wandev.mtu = 64; - cfg.pktlen = log2(card->wandev.mtu); + cfg.pktlen = cycx_log2(card->wandev.mtu); if (conf->station == WANOPT_DTE) { cfg.locaddr = 3; /* DTE */ @@ -1195,7 +1197,7 @@ static int x25_place_call(struct cycx_device *card, remotelen = strlen(chan->addr); u8 key; - if (card->u.x.connection_keys == ~0UL) { + if (card->u.x.connection_keys == ~0U) { printk(KERN_INFO "%s: too many simultaneous connection " "requests!\n", card->devname); return -EAGAIN; @@ -1486,11 +1488,7 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event) ptr = skb_put(skb, 1); *ptr = event; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; /* timestamp */ } @@ -1513,7 +1511,7 @@ static u8 bps_to_speed_code(u32 bps) } /* log base 2 */ -static u8 log2(u32 n) +static u8 cycx_log2(u32 n) { u8 log = 0; diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index bad0d4185..6e1ec5bf2 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -45,11 +45,11 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 4cbda752b..e998cfff9 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -230,6 +230,7 @@ struct dscc4_dev_priv { unsigned short parity; struct net_device *dev; sync_serial_settings settings; + void __iomem *base_addr; u32 __pad __attribute__ ((aligned (4))); }; @@ -351,9 +352,9 @@ struct dscc4_dev_priv { #endif /* Functions prototypes */ -static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); -static inline void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); -static int dscc4_found1(struct pci_dev *, unsigned long ioaddr); +static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); +static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *); +static int dscc4_found1(struct pci_dev *, void __iomem *ioaddr); static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent); static int dscc4_open(struct net_device *); static int dscc4_start_xmit(struct sk_buff *, struct net_device *); @@ -366,7 +367,6 @@ static void dscc4_tx_timeout(struct net_device *); static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs); static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short); static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *); -static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int); #ifdef DSCC4_POLLING static int dscc4_tx_poll(struct dscc4_dev_priv *, struct net_device *); #endif @@ -391,7 +391,7 @@ static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv, state &= ~mask; state |= value; dpriv->scc_regs[offset >> 2] = state; - writel(state, dev->base_addr + SCC_REG_START(dpriv) + offset); + writel(state, dpriv->base_addr + SCC_REG_START(dpriv) + offset); } static void scc_writel(u32 bits, struct dscc4_dev_priv *dpriv, @@ -402,7 +402,7 @@ static void scc_writel(u32 bits, struct dscc4_dev_priv *dpriv, * As of 2002/02/16, there are no thread racing for access. */ dpriv->scc_regs[offset >> 2] = bits; - writel(bits, dev->base_addr + SCC_REG_START(dpriv) + offset); + writel(bits, dpriv->base_addr + SCC_REG_START(dpriv) + offset); } static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset) @@ -413,8 +413,8 @@ static inline u32 scc_readl(struct dscc4_dev_priv *dpriv, int offset) static u32 scc_readl_star(struct dscc4_dev_priv *dpriv, struct net_device *dev) { /* Cf errata DS5 p.4 */ - readl(dev->base_addr + SCC_REG_START(dpriv) + STAR); - return readl(dev->base_addr + SCC_REG_START(dpriv) + STAR); + readl(dpriv->base_addr + SCC_REG_START(dpriv) + STAR); + return readl(dpriv->base_addr + SCC_REG_START(dpriv) + STAR); } static inline void dscc4_do_tx(struct dscc4_dev_priv *dpriv, @@ -422,9 +422,9 @@ static inline void dscc4_do_tx(struct dscc4_dev_priv *dpriv, { dpriv->ltda = dpriv->tx_fd_dma + ((dpriv->tx_current-1)%TX_RING_SIZE)*sizeof(struct TxFD); - writel(dpriv->ltda, dev->base_addr + CH0LTDA + dpriv->dev_id*4); + writel(dpriv->ltda, dpriv->base_addr + CH0LTDA + dpriv->dev_id*4); /* Flush posted writes *NOW* */ - readl(dev->base_addr + CH0LTDA + dpriv->dev_id*4); + readl(dpriv->base_addr + CH0LTDA + dpriv->dev_id*4); } static inline void dscc4_rx_update(struct dscc4_dev_priv *dpriv, @@ -432,7 +432,7 @@ static inline void dscc4_rx_update(struct dscc4_dev_priv *dpriv, { dpriv->lrda = dpriv->rx_fd_dma + ((dpriv->rx_dirty - 1)%RX_RING_SIZE)*sizeof(struct RxFD); - writel(dpriv->lrda, dev->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(dpriv->lrda, dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); } static inline unsigned int dscc4_tx_done(struct dscc4_dev_priv *dpriv) @@ -443,7 +443,7 @@ static inline unsigned int dscc4_tx_done(struct dscc4_dev_priv *dpriv) static inline unsigned int dscc4_tx_quiescent(struct dscc4_dev_priv *dpriv, struct net_device *dev) { - return readl(dev->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda; + return readl(dpriv->base_addr + CH0FTDA + dpriv->dev_id*4) == dpriv->ltda; } int state_check(u32 state, struct dscc4_dev_priv *dpriv, struct net_device *dev, @@ -518,9 +518,7 @@ inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) skb = dev_alloc_skb(len); dpriv->rx_skbuff[dirty] = skb; if (skb) { - skb->dev = dev; skb->protocol = hdlc_type_trans(skb, dev); - skb->mac.raw = skb->data; rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data, len, PCI_DMA_FROMDEVICE); } else { @@ -555,7 +553,7 @@ done: static int dscc4_do_action(struct net_device *dev, char *msg) { - unsigned long ioaddr = dev->base_addr; + void __iomem *ioaddr = dscc4_priv(dev)->base_addr; s16 i = 0; writel(Action, ioaddr + GCMDR); @@ -604,11 +602,11 @@ static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) spin_lock_irqsave(&dpriv->pci_priv->lock, flags); /* Cf errata DS5 p.6 */ - writel(0x00000000, dev->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(0x00000000, dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); scc_patchl(PowerUp, 0, dpriv, dev, CCR0); - readl(dev->base_addr + CH0LRDA + dpriv->dev_id*4); - writel(MTFi|Rdr, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG); - writel(Action, dev->base_addr + GCMDR); + readl(dpriv->base_addr + CH0LRDA + dpriv->dev_id*4); + writel(MTFi|Rdr, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG); + writel(Action, dpriv->base_addr + GCMDR); spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags); } @@ -630,7 +628,7 @@ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev) wmb(); } - writel(MTFi|Rdt, dev->base_addr + dpriv->dev_id*0x0c + CH0CFG); + writel(MTFi|Rdt, dpriv->base_addr + dpriv->dev_id*0x0c + CH0CFG); if (dscc4_do_action(dev, "Rdt") < 0) printk(KERN_ERR "%s: Tx reset failed\n", dev->name); } @@ -709,7 +707,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, struct dscc4_pci_priv *priv; struct dscc4_dev_priv *dpriv; static int cards_found = 0; - unsigned long ioaddr; + void __iomem *ioaddr; int i; printk(KERN_DEBUG "%s", version); @@ -728,7 +726,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev, DRV_NAME); goto err_out_free_mmio_region0; } - ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0), + ioaddr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!ioaddr) { printk(KERN_ERR "%s: cannot remap MMIO region %lx @ %lx\n", @@ -829,7 +827,7 @@ err_out_free_irq: err_out_free1: dscc4_free1(pdev); err_out_iounmap: - iounmap ((void *)ioaddr); + iounmap (ioaddr); err_out_free_mmio_region: release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); @@ -866,7 +864,19 @@ static void dscc4_init_registers(struct dscc4_dev_priv *dpriv, //scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2); } -static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) +static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) +{ + int ret = 0; + + if ((hz < 0) || (hz > DSCC4_HZ_MAX)) + ret = -EOPNOTSUPP; + else + dpriv->pci_priv->xtal_hz = hz; + + return ret; +} + +static int dscc4_found1(struct pci_dev *pdev, void __iomem *ioaddr) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; @@ -906,7 +916,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) struct net_device *d = dscc4_to_dev(dpriv); hdlc_device *hdlc = dev_to_hdlc(d); - d->base_addr = ioaddr; + d->base_addr = (unsigned long)ioaddr; d->init = NULL; d->irq = pdev->irq; d->open = dscc4_open; @@ -920,6 +930,7 @@ static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr) dpriv->dev_id = i; dpriv->pci_priv = ppriv; + dpriv->base_addr = ioaddr; spin_lock_init(&dpriv->lock); hdlc->xmit = dscc4_start_xmit; @@ -998,7 +1009,7 @@ static int dscc4_loopback_check(struct dscc4_dev_priv *dpriv) * * This code doesn't need to be efficient. Keep It Simple */ -static void dscc4_pci_reset(struct pci_dev *pdev, unsigned long ioaddr) +static void dscc4_pci_reset(struct pci_dev *pdev, void __iomem *ioaddr) { int i; @@ -1340,18 +1351,6 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return ret; } -static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz) -{ - int ret = 0; - - if ((hz < 0) || (hz > DSCC4_HZ_MAX)) - ret = -EOPNOTSUPP; - else - dpriv->pci_priv->xtal_hz = hz; - - return ret; -} - static int dscc4_match(struct thingie *p, int value) { int i; @@ -1477,7 +1476,7 @@ static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs) struct dscc4_dev_priv *root = token; struct dscc4_pci_priv *priv; struct net_device *dev; - unsigned long ioaddr; + void __iomem *ioaddr; u32 state; unsigned long flags; int i, handled = 1; @@ -1487,7 +1486,7 @@ static irqreturn_t dscc4_irq(int irq, void *token, struct pt_regs *ptregs) spin_lock_irqsave(&priv->lock, flags); - ioaddr = dev->base_addr; + ioaddr = root->base_addr; state = readl(ioaddr + GSTAR); if (!state) { @@ -1531,7 +1530,7 @@ out: return IRQ_RETVAL(handled); } -static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, +static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, struct dscc4_dev_priv *dpriv) { struct net_device *dev = dscc4_to_dev(dpriv); @@ -1614,8 +1613,8 @@ try: dpriv->flags = NeedIDT; /* Tx reset */ writel(MTFi | Rdt, - dev->base_addr + 0x0c*dpriv->dev_id + CH0CFG); - writel(Action, dev->base_addr + GCMDR); + dpriv->base_addr + 0x0c*dpriv->dev_id + CH0CFG); + writel(Action, dpriv->base_addr + GCMDR); return; } if (state & Cts) { @@ -1630,7 +1629,8 @@ try: goto try; } if (state & Xpr) { - unsigned long scc_addr, ring; + void __iomem *scc_addr; + unsigned long ring; int i; /* @@ -1644,7 +1644,7 @@ try: if (!i) printk(KERN_INFO "%s busy in irq\n", dev->name); - scc_addr = dev->base_addr + 0x0c*dpriv->dev_id; + scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id; /* Keep this order: IDT before IDR */ if (dpriv->flags & NeedIDT) { if (debug > 2) @@ -1700,7 +1700,7 @@ try: goto try; } -static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv, +static void dscc4_rx_irq(struct dscc4_pci_priv *priv, struct dscc4_dev_priv *dpriv) { struct net_device *dev = dscc4_to_dev(dpriv); @@ -1802,12 +1802,12 @@ try: */ if (state & Rdo) { struct RxFD *rx_fd; - u32 scc_addr; + void __iomem *scc_addr; int cur; //if (debug) // dscc4_rx_dump(dpriv); - scc_addr = dev->base_addr + 0x0c*dpriv->dev_id; + scc_addr = dpriv->base_addr + 0x0c*dpriv->dev_id; scc_patchl(RxActivate, 0, dpriv, dev, CCR2); /* @@ -1971,13 +1971,13 @@ static void __devexit dscc4_remove_one(struct pci_dev *pdev) { struct dscc4_pci_priv *ppriv; struct dscc4_dev_priv *root; - unsigned long ioaddr; + void __iomem *ioaddr; int i; ppriv = pci_get_drvdata(pdev); root = ppriv->root; - ioaddr = dscc4_to_dev(root)->base_addr; + ioaddr = root->base_addr; dscc4_pci_reset(pdev, ioaddr); @@ -1996,7 +1996,7 @@ static void __devexit dscc4_remove_one(struct pci_dev *pdev) dscc4_free1(pdev); - iounmap((void *)ioaddr); + iounmap(ioaddr); release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 543ac7900..3955bf1ad 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -411,7 +411,7 @@ struct buf_window { }; /* Calculate offset of a buffer object within the shared memory window */ -#define BUF_OFFSET(X) ((unsigned int)&(((struct buf_window *)BFM_BASE)->X)) +#define BUF_OFFSET(X) (BFM_BASE + offsetof(struct buf_window, X)) #pragma pack() @@ -443,8 +443,8 @@ struct fst_port_info { /* Per card information */ struct fst_card_info { - char *mem; /* Card memory mapped to kernel space */ - char *ctlmem; /* Control memory for PCI cards */ + char __iomem *mem; /* Card memory mapped to kernel space */ + char __iomem *ctlmem; /* Control memory for PCI cards */ unsigned int phys_mem; /* Physical memory window address */ unsigned int phys_ctlmem; /* Physical control memory address */ unsigned int irq; /* Interrupt request line number */ @@ -781,7 +781,7 @@ fst_disable_intr(struct fst_card_info *card) } } -/* Process the result of trying to pass a recieved frame up the stack +/* Process the result of trying to pass a received frame up the stack */ static void fst_process_rx_status(int rx_status, char *name) @@ -857,6 +857,18 @@ fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, dev->trans_start = jiffies; } +/* + * Mark it for our own raw sockets interface + */ +static unsigned short farsync_type_trans(struct sk_buff *skb, + struct net_device *dev) +{ + skb->dev = dev; + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + return htons(ETH_P_CUST); +} + /* Rx dma complete interrupt */ static void @@ -881,17 +893,10 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port, /* Push upstream */ dbg(DBG_RX, "Pushing the frame up the stack\n"); - skb->mac.raw = skb->data; - skb->dev = dev; - if (port->mode == FST_RAW) { - /* - * Mark it for our own raw sockets interface - */ - skb->protocol = htons(ETH_P_CUST); - skb->pkt_type = PACKET_HOST; - } else { - skb->protocol = hdlc_type_trans(skb, skb->dev); - } + if (port->mode == FST_RAW) + skb->protocol = farsync_type_trans(skb, dev); + else + skb->protocol = hdlc_type_trans(skb, dev); rx_status = netif_rx(skb); fst_process_rx_status(rx_status, port_to_dev(port)->name); if (rx_status == NET_RX_DROP) @@ -1316,17 +1321,10 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port) /* Push upstream */ dbg(DBG_RX, "Pushing frame up the stack\n"); - skb->mac.raw = skb->data; - skb->dev = dev; - if (port->mode == FST_RAW) { - /* - * Mark it for our own raw sockets interface - */ - skb->protocol = htons(ETH_P_CUST); - skb->pkt_type = PACKET_HOST; - } else { - skb->protocol = hdlc_type_trans(skb, skb->dev); - } + if (port->mode == FST_RAW) + skb->protocol = farsync_type_trans(skb, dev); + else + skb->protocol = hdlc_type_trans(skb, dev); rx_status = netif_rx(skb); fst_process_rx_status(rx_status, port_to_dev(port)->name); if (rx_status == NET_RX_DROP) { diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c index b7f6504a5..05107bc0f 100644 --- a/drivers/net/wan/hd6457x.c +++ b/drivers/net/wan/hd6457x.c @@ -38,9 +38,9 @@ #include #include #include +#include #include -#include #include #include @@ -148,13 +148,13 @@ static inline u16 desc_offset(port_t *port, u16 desc, int transmit) -static inline pkt_desc* desc_address(port_t *port, u16 desc, int transmit) +static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc, int transmit) { #ifdef PAGE0_ALWAYS_MAPPED - return (pkt_desc*)(win0base(port_to_card(port)) + return (pkt_desc __iomem *)(win0base(port_to_card(port)) + desc_offset(port, desc, transmit)); #else - return (pkt_desc*)(winbase(port_to_card(port)) + return (pkt_desc __iomem *)(winbase(port_to_card(port)) + desc_offset(port, desc, transmit)); #endif } @@ -188,7 +188,7 @@ static void sca_init_sync_port(port_t *port) : card->rx_ring_buffers; for (i = 0; i < buffs; i++) { - pkt_desc* desc = desc_address(port, i, transmit); + pkt_desc __iomem *desc = desc_address(port, i, transmit); u16 chain_off = desc_offset(port, i + 1, transmit); u32 buff_off = buffer_offset(port, i, transmit); @@ -269,7 +269,7 @@ static inline void sca_msci_intr(port_t *port) -static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin) +static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u16 rxin) { struct net_device *dev = port_to_dev(port); struct net_device_stats *stats = hdlc_stats(dev); @@ -315,8 +315,6 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin) #endif stats->rx_packets++; stats->rx_bytes += skb->len; - skb->mac.raw = skb->data; - skb->dev = dev; skb->dev->last_rx = jiffies; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); @@ -341,7 +339,7 @@ static inline void sca_rx_intr(port_t *port) while (1) { u32 desc_off = desc_offset(port, port->rxin, 0); - pkt_desc *desc; + pkt_desc __iomem *desc; u32 cda = sca_ina(dmac + CDAL, card); if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) @@ -392,7 +390,7 @@ static inline void sca_tx_intr(port_t *port) DSR_TX(phy_node(port)), card); while (1) { - pkt_desc *desc; + pkt_desc __iomem *desc; u32 desc_off = desc_offset(port, port->txlast, 1); u32 cda = sca_ina(dmac + CDAL, card); @@ -463,8 +461,8 @@ static void sca_set_port(port_t *port) brv >>= 1; /* brv = 2^9 = 512 max in specs */ /* Baud Rate = CLOCK_BASE / TMC / 2^BR */ - tmc = CLOCK_BASE / (brv * port->settings.clock_rate); - }while(br > 1 && tmc <= 128); + tmc = CLOCK_BASE / brv / port->settings.clock_rate; + }while (br > 1 && tmc <= 128); if (tmc < 1) { tmc = 1; @@ -473,7 +471,7 @@ static void sca_set_port(port_t *port) } else if (tmc > 255) tmc = 256; /* tmc=0 means 256 - low baud rates */ - port->settings.clock_rate = CLOCK_BASE / (brv * tmc); + port->settings.clock_rate = CLOCK_BASE / brv / tmc; } else { br = 9; /* Minimum clock rate */ tmc = 256; /* 8bit = 0 */ @@ -730,7 +728,7 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) { port_t *port = dev_to_port(dev); card_t *card = port_to_card(port); - pkt_desc *desc; + pkt_desc __iomem *desc; u32 buff, len; #ifndef ALL_PAGES_ALWAYS_MAPPED u8 page; @@ -799,7 +797,7 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) #ifdef NEED_DETECT_RAM -static u32 __devinit sca_detect_ram(card_t *card, u8 *rambase, u32 ramsize) +static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize) { /* Round RAM size to 32 bits, fill from end to start */ u32 i = ramsize &= ~3; diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index 5231063c9..07e5eef1f 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -23,6 +23,8 @@ #include #include +#include + /* These functions are callbacks called by LAPB layer */ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) @@ -38,11 +40,7 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code) ptr = skb_put(skb, 1); *ptr = code; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); netif_rx(skb); } @@ -74,11 +72,7 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) ptr = skb->data; *ptr = 0; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); return netif_rx(skb); } diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index c8f3187e1..7f2e3653c 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -43,6 +43,8 @@ #include #include +#include + static char bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* If this number is made larger, check that the temporary string buffer @@ -137,11 +139,7 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) ptr = skb->data; *ptr = 0x00; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; return netif_rx(skb); } @@ -233,11 +231,7 @@ static void lapbeth_connected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x01; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; netif_rx(skb); } @@ -255,11 +249,7 @@ static void lapbeth_disconnected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x02; - skb->dev = dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, dev); skb->dev->last_rx = jiffies; netif_rx(skb); } diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c index 058ff8048..9dccd9546 100644 --- a/drivers/net/wan/lmc/lmc_debug.c +++ b/drivers/net/wan/lmc/lmc_debug.c @@ -64,7 +64,7 @@ void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3) #endif } -inline void lmc_trace(struct net_device *dev, char *msg){ +void lmc_trace(struct net_device *dev, char *msg){ #ifdef LMC_TRACE unsigned long j = jiffies + 3; /* Wait for 50 ms */ diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index b9800715d..15e545f66 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -56,11 +56,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -101,7 +101,6 @@ static int lmc_open(struct net_device *dev); static int lmc_close(struct net_device *dev); static struct net_device_stats *lmc_get_stats(struct net_device *dev); static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static int lmc_set_config(struct net_device *dev, struct ifmap *map); static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size); static void lmc_softreset(lmc_softc_t * const); static void lmc_running_reset(struct net_device *dev); @@ -814,7 +813,6 @@ static void lmc_setup(struct net_device * const dev) /*fold00*/ dev->stop = lmc_close; dev->get_stats = lmc_get_stats; dev->do_ioctl = lmc_ioctl; - dev->set_config = lmc_set_config; dev->tx_timeout = lmc_driver_timeout; dev->watchdog_timeo = (HZ); /* 1 second */ @@ -1975,13 +1973,6 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_softreset out"); } -static int lmc_set_config(struct net_device *dev, struct ifmap *map) /*fold00*/ -{ - lmc_trace(dev, "lmc_set_config in"); - lmc_trace(dev, "lmc_set_config out"); - return -EOPNOTSUPP; -} - void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in"); diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index 2aca8dc98..f55ce76b0 100644 --- a/drivers/net/wan/lmc/lmc_media.c +++ b/drivers/net/wan/lmc/lmc_media.c @@ -16,11 +16,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index bb9f1eab7..74876c007 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c @@ -36,11 +36,11 @@ #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index 9dc4a8db2..dfe3bfeef 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -111,7 +111,7 @@ typedef struct port_s { typedef struct card_s { - u8 *winbase; /* ISA window base address */ + u8 __iomem *winbase; /* ISA window base address */ u32 phy_winbase; /* ISA physical base address */ u32 ram_size; /* number of bytes */ u16 io; /* IO Base address */ diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h index e6af4921e..73401b0f0 100644 --- a/drivers/net/wan/pc300.h +++ b/drivers/net/wan/pc300.h @@ -105,14 +105,10 @@ #ifndef CY_TYPES #define CY_TYPES -#if defined(__alpha__) -typedef unsigned long ucdouble; /* 64 bits, unsigned */ -typedef unsigned int uclong; /* 32 bits, unsigned */ -#else -typedef unsigned long uclong; /* 32 bits, unsigned */ -#endif -typedef unsigned short ucshort; /* 16 bits, unsigned */ -typedef unsigned char ucchar; /* 8 bits, unsigned */ +typedef __u64 ucdouble; /* 64 bits, unsigned */ +typedef __u32 uclong; /* 32 bits, unsigned */ +typedef __u16 ucshort; /* 16 bits, unsigned */ +typedef __u8 ucchar; /* 8 bits, unsigned */ #endif /* CY_TYPES */ #define PC300_PROTO_MLPPP 1 @@ -164,9 +160,9 @@ typedef unsigned char ucchar; /* 8 bits, unsigned */ * (required to support Alpha systems) * ***************************************/ #ifdef __KERNEL__ -#define cpc_writeb(port,val) {writeb((ucchar)(val),(ulong)(port)); mb();} -#define cpc_writew(port,val) {writew((ushort)(val),(ulong)(port)); mb();} -#define cpc_writel(port,val) {writel((uclong)(val),(ulong)(port)); mb();} +#define cpc_writeb(port,val) {writeb((ucchar)(val),(port)); mb();} +#define cpc_writew(port,val) {writew((ushort)(val),(port)); mb();} +#define cpc_writel(port,val) {writel((uclong)(val),(port)); mb();} #define cpc_readb(port) readb(port) #define cpc_readw(port) readw(port) @@ -358,17 +354,17 @@ typedef struct pc300hw { uclong iophys; /* PLX registers I/O base */ uclong iosize; /* PLX registers I/O size */ uclong plxphys; /* PLX registers MMIO base (physical) */ - uclong plxbase; /* PLX registers MMIO base (virtual) */ + void __iomem * plxbase; /* PLX registers MMIO base (virtual) */ uclong plxsize; /* PLX registers MMIO size */ uclong scaphys; /* SCA registers MMIO base (physical) */ - uclong scabase; /* SCA registers MMIO base (virtual) */ + void __iomem * scabase; /* SCA registers MMIO base (virtual) */ uclong scasize; /* SCA registers MMIO size */ uclong ramphys; /* On-board RAM MMIO base (physical) */ - uclong rambase; /* On-board RAM MMIO base (virtual) */ + void __iomem * rambase; /* On-board RAM MMIO base (virtual) */ uclong alloc_ramsize; /* RAM MMIO size allocated by the PCI bridge */ uclong ramsize; /* On-board RAM MMIO size */ uclong falcphys; /* FALC registers MMIO base (physical) */ - uclong falcbase; /* FALC registers MMIO base (virtual) */ + void __iomem * falcbase;/* FALC registers MMIO base (virtual) */ uclong falcsize; /* FALC registers MMIO size */ } pc300hw_t; diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 29b82687b..59b7d5727 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -307,7 +307,7 @@ static void tx_dma_buf_pt_init(pc300_t * card, int ch) { int i; int ch_factor = ch * N_DMA_TX_BUF; - volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase + volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) { @@ -322,7 +322,7 @@ static void tx_dma_buf_init(pc300_t * card, int ch) { int i; int ch_factor = ch * N_DMA_TX_BUF; - volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase + volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) { @@ -337,7 +337,7 @@ static void rx_dma_buf_pt_init(pc300_t * card, int ch) { int i; int ch_factor = ch * N_DMA_RX_BUF; - volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase + volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) { @@ -352,7 +352,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch) { int i; int ch_factor = ch * N_DMA_RX_BUF; - volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase + volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) { @@ -365,7 +365,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch) static void tx_dma_buf_check(pc300_t * card, int ch) { - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int i; ucshort first_bd = card->chan[ch].tx_first_bd; ucshort next_bd = card->chan[ch].tx_next_bd; @@ -374,13 +374,13 @@ static void tx_dma_buf_check(pc300_t * card, int ch) first_bd, TX_BD_ADDR(ch, first_bd), next_bd, TX_BD_ADDR(ch, next_bd)); for (i = first_bd, - ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, first_bd)); + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd)); i != ((next_bd + 1) & (N_DMA_TX_BUF - 1)); i = (i + 1) & (N_DMA_TX_BUF - 1), - ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i))) { - printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", - ch, i, (uclong) cpc_readl(&ptdescr->next), - (uclong) cpc_readl(&ptdescr->ptbuf), + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) { + printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", + ch, i, cpc_readl(&ptdescr->next), + cpc_readl(&ptdescr->ptbuf), cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } printk("\n"); @@ -390,7 +390,7 @@ static void tx_dma_buf_check(pc300_t * card, int ch) /* Show all TX buffer descriptors */ static void tx1_dma_buf_check(pc300_t * card, int ch) { - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int i; ucshort first_bd = card->chan[ch].tx_first_bd; ucshort next_bd = card->chan[ch].tx_next_bd; @@ -400,14 +400,14 @@ static void tx1_dma_buf_check(pc300_t * card, int ch) printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, first_bd, TX_BD_ADDR(ch, first_bd), next_bd, TX_BD_ADDR(ch, next_bd)); - printk("TX_CDA=0x%08lx, TX_EDA=0x%08lx\n", - (uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)), - (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch))); + printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n", + cpc_readl(scabase + DTX_REG(CDAL, ch)), + cpc_readl(scabase + DTX_REG(EDAL, ch))); for (i = 0; i < N_DMA_TX_BUF; i++) { - ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i)); - printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", - ch, i, (uclong) cpc_readl(&ptdescr->next), - (uclong) cpc_readl(&ptdescr->ptbuf), + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i)); + printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", + ch, i, cpc_readl(&ptdescr->next), + cpc_readl(&ptdescr->ptbuf), cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } printk("\n"); @@ -416,7 +416,7 @@ static void tx1_dma_buf_check(pc300_t * card, int ch) static void rx_dma_buf_check(pc300_t * card, int ch) { - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int i; ucshort first_bd = card->chan[ch].rx_first_bd; ucshort last_bd = card->chan[ch].rx_last_bd; @@ -424,13 +424,13 @@ static void rx_dma_buf_check(pc300_t * card, int ch) ch_factor = ch * N_DMA_RX_BUF; printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd); - for (i = 0, ptdescr = (pcsca_bd_t *) (card->hw.rambase + + for (i = 0, ptdescr = (card->hw.rambase + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t)); i < N_DMA_RX_BUF; i++, ptdescr++) { if (cpc_readb(&ptdescr->status) & DST_OSB) - printk ("\n CH%d RX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d", - ch, i, (uclong) cpc_readl(&ptdescr->next), - (uclong) cpc_readl(&ptdescr->ptbuf), + printk ("\n CH%d RX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", + ch, i, cpc_readl(&ptdescr->next), + cpc_readl(&ptdescr->ptbuf), cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } @@ -439,12 +439,12 @@ static void rx_dma_buf_check(pc300_t * card, int ch) int dma_get_rx_frame_size(pc300_t * card, int ch) { - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; ucshort first_bd = card->chan[ch].rx_first_bd; int rcvd = 0; volatile ucchar status; - ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); + ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd)); while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { rcvd += cpc_readw(&ptdescr->len); first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); @@ -453,7 +453,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch) * (dma_buf_read will clean the buffer descriptors in this case). */ return (rcvd); } - ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next)); + ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); } return (-1); } @@ -465,7 +465,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch) int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len) { int i, nchar; - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int tosend = len; ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1; @@ -474,11 +474,11 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len) } for (i = 0; i < nbuf; i++) { - ptdescr = (pcsca_bd_t *) (card->hw.rambase + + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); nchar = cpc_min(BD_DEF_LEN, tosend); if (cpc_readb(&ptdescr->status) & DST_OSB) { - memcpy_toio((void *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), + memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), &ptdata[len - tosend], nchar); cpc_writew(&ptdescr->len, nchar); card->chan[ch].nfree_tx_bd--; @@ -507,11 +507,11 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) { int nchar; pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; - volatile pcsca_bd_t *ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int rcvd = 0; volatile ucchar status; - ptdescr = (pcsca_bd_t *) (card->hw.rambase + + ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, chan->rx_first_bd)); while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { nchar = cpc_readw(&ptdescr->len); @@ -527,7 +527,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1); if (status & DST_EOM) break; - ptdescr = (pcsca_bd_t *) (card->hw.rambase + + ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); status = cpc_readb(&ptdescr->status); } @@ -536,7 +536,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) if (nchar != 0) { if (skb) { memcpy_fromio(skb_put(skb, nchar), - (void *)(card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar); + (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar); } rcvd += nchar; } @@ -547,7 +547,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) if (status & DST_EOM) break; - ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next)); + ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); } if (rcvd != 0) { @@ -562,7 +562,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) void tx_dma_stop(pc300_t * card, int ch) { - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; ucchar drr_ena_bit = 1 << (5 + 2 * ch); ucchar drr_rst_bit = 1 << (1 + 2 * ch); @@ -573,7 +573,7 @@ void tx_dma_stop(pc300_t * card, int ch) void rx_dma_stop(pc300_t * card, int ch) { - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; ucchar drr_ena_bit = 1 << (4 + 2 * ch); ucchar drr_rst_bit = 1 << (2 * ch); @@ -584,7 +584,7 @@ void rx_dma_stop(pc300_t * card, int ch) void rx_dma_start(pc300_t * card, int ch) { - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; /* Start DMA */ @@ -609,7 +609,7 @@ void rx_dma_start(pc300_t * card, int ch) /*************************/ void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd) { - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; unsigned long i = 0; while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) { @@ -627,7 +627,7 @@ void falc_intr_enable(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; /* Interrupt pins are open-drain */ cpc_writeb(falcbase + F_REG(IPC, ch), @@ -674,7 +674,7 @@ void falc_intr_enable(pc300_t * card, int ch) void falc_open_timeslot(pc300_t * card, int ch, int timeslot) { - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), @@ -690,7 +690,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot) void falc_close_timeslot(pc300_t * card, int ch, int timeslot) { - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), @@ -708,7 +708,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR1, ch), 0); @@ -730,7 +730,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; cpc_writeb(falcbase + F_REG(ICB1, ch), 0); if (conf->fr_mode == PC300_FR_UNFRAMED) { @@ -811,7 +811,7 @@ void falc_init_t1(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); /* Switch to T1 mode (PCM 24) */ @@ -980,7 +980,7 @@ void falc_init_e1(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); /* Switch to E1 mode (PCM 30) */ @@ -1157,7 +1157,7 @@ void falc_init_e1(pc300_t * card, int ch) void falc_init_hdlc(pc300_t * card, int ch) { - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; @@ -1186,7 +1186,7 @@ void te_config(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar dummy; unsigned long flags; @@ -1246,7 +1246,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; /* Verify LOS */ if (frs0 & FRS0_LOS) { @@ -1402,7 +1402,7 @@ void falc_update_stats(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucshort counter; counter = cpc_readb(falcbase + F_REG(FECL, ch)); @@ -1455,7 +1455,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (loop_on) { // EVENT_FALC_ABNORMAL @@ -1499,7 +1499,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (loop_on) { cpc_writeb(falcbase + F_REG(LIM0, ch), @@ -1527,7 +1527,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (loop_on) { // EVENT_FALC_ABNORMAL @@ -1580,7 +1580,7 @@ void turn_off_xlu(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1601,7 +1601,7 @@ void turn_off_xld(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1624,7 +1624,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1657,7 +1657,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1687,7 +1687,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate) pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (activate) { pfalc->prbs = 1; @@ -1959,7 +1959,6 @@ void cpc_net_rx(struct net_device *dev) cpc_trace(dev, skb, 'R'); } stats->rx_packets++; - skb->mac.raw = skb->data; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } @@ -1973,11 +1972,11 @@ static void sca_tx_intr(pc300dev_t *dev) pc300ch_t *chan = (pc300ch_t *)dev->chan; pc300_t *card = (pc300_t *)chan->card; int ch = chan->channel; - volatile pcsca_bd_t * ptdescr; + volatile pcsca_bd_t __iomem * ptdescr; struct net_device_stats *stats = hdlc_stats(dev->dev); /* Clean up descriptors from previous transmission */ - ptdescr = (pcsca_bd_t *)(card->hw.rambase + + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd)); while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != TX_BD_ADDR(ch,chan->tx_first_bd)) && @@ -1988,8 +1987,7 @@ static void sca_tx_intr(pc300dev_t *dev) cpc_writew(&ptdescr->len, 0); chan->nfree_tx_bd++; chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1); - ptdescr = (pcsca_bd_t *)(card->hw.rambase + - TX_BD_ADDR(ch,chan->tx_first_bd)); + ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd)); } #ifdef CONFIG_PC300_MLPPP @@ -2006,7 +2004,7 @@ static void sca_tx_intr(pc300dev_t *dev) static void sca_intr(pc300_t * card) { - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; volatile uclong status; int ch; int intr_count = 0; @@ -2187,7 +2185,7 @@ static void falc_t1_loop_detection(pc300_t * card, int ch, ucchar frs1) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && !pfalc->loop_gen) { @@ -2212,7 +2210,7 @@ static void falc_e1_loop_detection(pc300_t * card, int ch, ucchar rsp) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && !pfalc->loop_gen) { @@ -2237,7 +2235,7 @@ static void falc_t1_intr(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar isr0, isr3, gis; ucchar dummy; @@ -2284,7 +2282,7 @@ static void falc_e1_intr(pc300_t * card, int ch) { pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; falc_t *pfalc = (falc_t *) & chan->falc; - uclong falcbase = card->hw.falcbase; + void __iomem *falcbase = card->hw.falcbase; ucchar isr1, isr2, isr3, gis, rsp; ucchar dummy; @@ -2408,7 +2406,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs) void cpc_sca_status(pc300_t * card, int ch) { ucchar ilar; - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; uclong flags; tx_dma_buf_check(card, ch); @@ -2417,12 +2415,12 @@ void cpc_sca_status(pc300_t * card, int ch) printk ("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n", ilar, cpc_readb(scabase + WCRL), cpc_readb(scabase + PCR), cpc_readb(scabase + BTCR), cpc_readb(scabase + BOLR)); - printk("TX_CDA=0x%08lx, TX_EDA=0x%08lx\n", - (uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)), - (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch))); - printk("RX_CDA=0x%08lx, RX_EDA=0x%08lx, BFL=0x%04x\n", - (uclong) cpc_readl(scabase + DRX_REG(CDAL, ch)), - (uclong) cpc_readl(scabase + DRX_REG(EDAL, ch)), + printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n", + cpc_readl(scabase + DTX_REG(CDAL, ch)), + cpc_readl(scabase + DTX_REG(EDAL, ch))); + printk("RX_CDA=0x%08x, RX_EDA=0x%08x, BFL=0x%04x\n", + cpc_readl(scabase + DRX_REG(CDAL, ch)), + cpc_readl(scabase + DRX_REG(EDAL, ch)), cpc_readw(scabase + DRX_REG(BFLL, ch))); printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n", cpc_readb(scabase + DMER), cpc_readb(scabase + DSR_TX(ch)), @@ -2487,7 +2485,7 @@ void cpc_sca_status(pc300_t * card, int ch) cpc_readb(scabase + M_REG(IE2, ch)), cpc_readb(scabase + M_REG(IE4, ch)), cpc_readb(scabase + M_REG(FIE, ch))); - printk("IER0=0x%08lx\n", (uclong) cpc_readl(scabase + IER0)); + printk("IER0=0x%08x\n", cpc_readl(scabase + IER0)); if (ilar != 0) { CPC_LOCK(card, flags); @@ -2544,7 +2542,7 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int ch = chan->channel; void __user *arg = ifr->ifr_data; struct if_settings *settings = &ifr->ifr_settings; - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -2863,8 +2861,8 @@ int ch_config(pc300dev_t * d) pc300ch_t *chan = (pc300ch_t *) d->chan; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; pc300_t *card = (pc300_t *) chan->card; - uclong scabase = card->hw.scabase; - uclong plxbase = card->hw.plxbase; + void __iomem *scabase = card->hw.scabase; + void __iomem *plxbase = card->hw.plxbase; int ch = chan->channel; uclong clkrate = chan->conf.phys_settings.clock_rate; uclong clktype = chan->conf.phys_settings.clock_type; @@ -3010,7 +3008,7 @@ int rx_config(pc300dev_t * d) { pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; int ch = chan->channel; cpc_writeb(scabase + DSR_RX(ch), 0); @@ -3041,7 +3039,7 @@ int tx_config(pc300dev_t * d) { pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; int ch = chan->channel; cpc_writeb(scabase + DSR_TX(ch), 0); @@ -3105,7 +3103,7 @@ void cpc_opench(pc300dev_t * d) pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; int ch = chan->channel; - uclong scabase = card->hw.scabase; + void __iomem *scabase = card->hw.scabase; ch_config(d); @@ -3211,7 +3209,7 @@ static uclong detect_ram(pc300_t * card) { uclong i; ucchar data; - uclong rambase = card->hw.rambase; + void __iomem *rambase = card->hw.rambase; card->hw.ramsize = PC300_RAMSIZE; /* Let's find out how much RAM is present on this board */ @@ -3227,7 +3225,7 @@ static uclong detect_ram(pc300_t * card) static void plx_init(pc300_t * card) { - struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *) card->hw.plxbase; + struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase; /* Reset PLX */ cpc_writel(&plx_ctl->init_ctrl, @@ -3408,12 +3406,12 @@ static void cpc_init_card(pc300_t * card) printk("RSV "); break; } - printk (" #%d, %ldKB of RAM at 0x%08lx, IRQ%d, channel %d.\n", + printk (" #%d, %dKB of RAM at 0x%08x, IRQ%d, channel %d.\n", board_nbr, card->hw.ramsize / 1024, card->hw.ramphys, card->hw.irq, i + 1); devcount++; } else { - printk ("Dev%d on card(0x%08lx): unable to allocate i/f name.\n", + printk ("Dev%d on card(0x%08x): unable to allocate i/f name.\n", i + 1, card->hw.ramphys); free_netdev(dev); continue; @@ -3493,7 +3491,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!request_region(card->hw.iophys, card->hw.iosize, "PLX Registers")) { /* In case we can't allocate it, warn user */ printk("WARNING: couldn't allocate I/O region for PC300 board " - "at 0x%08lx!\n", card->hw.ramphys); + "at 0x%08x!\n", card->hw.ramphys); } if (card->hw.plxphys) { @@ -3506,7 +3504,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!request_mem_region(card->hw.plxphys, card->hw.plxsize, "PLX Registers")) { - printk("PC300 found at RAM 0x%08lx, " + printk("PC300 found at RAM 0x%08x, " "but could not allocate PLX mem region.\n", card->hw.ramphys); err = -ENODEV; @@ -3514,7 +3512,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } if (!request_mem_region(card->hw.ramphys, card->hw.alloc_ramsize, "On-board RAM")) { - printk("PC300 found at RAM 0x%08lx, " + printk("PC300 found at RAM 0x%08x, " "but could not allocate RAM mem region.\n", card->hw.ramphys); err = -ENODEV; @@ -3522,7 +3520,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } if (!request_mem_region(card->hw.scaphys, card->hw.scasize, "SCA-II Registers")) { - printk("PC300 found at RAM 0x%08lx, " + printk("PC300 found at RAM 0x%08x, " "but could not allocate SCA mem region.\n", card->hw.ramphys); err = -ENODEV; @@ -3532,10 +3530,9 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if ((err = pci_enable_device(pdev)) != 0) goto err_release_sca; - card->hw.plxbase = (uclong) ioremap(card->hw.plxphys, card->hw.plxsize); - card->hw.rambase = (uclong) ioremap(card->hw.ramphys, - card->hw.alloc_ramsize); - card->hw.scabase = (uclong) ioremap(card->hw.scaphys, card->hw.scasize); + card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize); + card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize); + card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize); switch (device_id) { case PCI_DEVICE_ID_PC300_TE_1: case PCI_DEVICE_ID_PC300_TE_2: @@ -3543,14 +3540,13 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) case PCI_DEVICE_ID_PC300_TE_M_2: request_mem_region(card->hw.falcphys, card->hw.falcsize, "FALC Registers"); - card->hw.falcbase = (uclong) ioremap(card->hw.falcphys, - card->hw.falcsize); + card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize); break; case PCI_DEVICE_ID_PC300_RX_1: case PCI_DEVICE_ID_PC300_RX_2: default: - card->hw.falcbase = 0; + card->hw.falcbase = NULL; break; } @@ -3604,7 +3600,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Allocate IRQ */ if (request_irq(card->hw.irq, cpc_intr, SA_SHIRQ, "Cyclades-PC300", card)) { - printk ("PC300 found at RAM 0x%08lx, but could not allocate IRQ%d.\n", + printk ("PC300 found at RAM 0x%08x, but could not allocate IRQ%d.\n", card->hw.ramphys, card->hw.irq); goto err_io_unmap; } @@ -3616,11 +3612,11 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err_io_unmap: - iounmap((void *) card->hw.plxbase); - iounmap((void *) card->hw.scabase); - iounmap((void *) card->hw.rambase); + iounmap(card->hw.plxbase); + iounmap(card->hw.scabase); + iounmap(card->hw.rambase); if (card->hw.type == PC300_TE) { - iounmap((void *) card->hw.falcbase); + iounmap(card->hw.falcbase); release_mem_region(card->hw.falcphys, card->hw.falcsize); } err_release_sca: @@ -3649,15 +3645,15 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev) for (i = 0; i < card->hw.nchan; i++) { unregister_hdlc_device(card->chan[i].d.dev); } - iounmap((void *) card->hw.plxbase); - iounmap((void *) card->hw.scabase); - iounmap((void *) card->hw.rambase); + iounmap(card->hw.plxbase); + iounmap(card->hw.scabase); + iounmap(card->hw.rambase); release_mem_region(card->hw.plxphys, card->hw.plxsize); release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize); release_mem_region(card->hw.scaphys, card->hw.scasize); release_region(card->hw.iophys, card->hw.iosize); if (card->hw.type == PC300_TE) { - iounmap((void *) card->hw.falcbase); + iounmap(card->hw.falcbase); release_mem_region(card->hw.falcphys, card->hw.falcsize); } for (i = 0; i < card->hw.nchan; i++) diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 79d6894ac..29f84ad08 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -120,8 +120,7 @@ int cpc_tty_unreg_flag = 0; /* TTY functions prototype */ static int cpc_tty_open(struct tty_struct *tty, struct file *flip); static void cpc_tty_close(struct tty_struct *tty, struct file *flip); -static int cpc_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count); +static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count); static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); @@ -192,13 +191,14 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal) */ void cpc_tty_init(pc300dev_t *pc300dev) { - int port, aux; + unsigned long port; + int aux; st_cpc_tty_area * cpc_tty; /* hdlcX - X=interface number */ port = pc300dev->dev->name[4] - '0'; if (port >= CPC_TTY_NPORTS) { - printk("%s-tty: invalid interface selected (0-%i): %i", + printk("%s-tty: invalid interface selected (0-%i): %li", pc300dev->dev->name, CPC_TTY_NPORTS-1,port); return; @@ -426,8 +426,7 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip) * o verify the DCD signal * o send characters to board and start the transmission */ -static int cpc_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { st_cpc_tty_area *cpc_tty; pc300ch_t *pc300chan; @@ -453,8 +452,7 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user, return -EINVAL; /* frame too big */ } - CPC_TTY_DBG("%s: cpc_tty_write %s data len=%i\n",cpc_tty->name, - (from_user)?"from user" : "from kernel",count); + CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count); pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev); @@ -481,27 +479,10 @@ static int cpc_tty_write(struct tty_struct *tty, int from_user, return -EINVAL; } - if (from_user) { - unsigned char *buf_tmp; - - buf_tmp = cpc_tty->buf_tx; - if (copy_from_user(buf_tmp, buf, count)) { - /* failed to copy from user */ - CPC_TTY_DBG("%s: error in copy from user\n",cpc_tty->name); - return -EINVAL; - } - - if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*) buf_tmp,count)) { - /* failed to send */ - CPC_TTY_DBG("%s: transmission error\n",cpc_tty->name); - return 0; - } - } else { - if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { - /* failed to send */ - CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name); - return 0; - } + if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { + /* failed to send */ + CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name); + return 0; } return count; } @@ -634,14 +615,8 @@ static void cpc_tty_flush_buffer(struct tty_struct *tty) } CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name); - - wake_up_interruptible(&tty->write_wait); - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){ - CPC_TTY_DBG("%s: call line disc. wake up\n",cpc_tty->name); - tty->ldisc.write_wakeup(tty); - } + tty_wakeup(tty); return; } @@ -688,25 +663,32 @@ static void cpc_tty_hangup(struct tty_struct *tty) */ static void cpc_tty_rx_work(void * data) { - int port, i, j; + unsigned long port; + int i, j; st_cpc_tty_area *cpc_tty; volatile st_cpc_rx_buf * buf; char flags=0,flg_rx=1; + struct tty_ldisc *ld; if (cpc_tty_cnt == 0) return; + for (i=0; (i < 4) && flg_rx ; i++) { flg_rx = 0; - port = (int) data; + port = (unsigned long)data; for (j=0; j < CPC_TTY_NPORTS; j++) { cpc_tty = &cpc_tty_area[port]; if ((buf=cpc_tty->buf_rx.first) != 0) { - - if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { - CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name); - cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (char *)(buf->data), - &flags, buf->size); + if(cpc_tty->tty) { + ld = tty_ldisc_ref(cpc_tty->tty); + if(ld) { + if (ld->receive_buf) { + CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name); + ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size); + } + tty_ldisc_deref(ld); + } } cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; kfree((unsigned char *)buf); @@ -728,13 +710,13 @@ static void cpc_tty_rx_work(void * data) */ static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan) { - volatile pcsca_bd_t * ptdescr; + volatile pcsca_bd_t __iomem * ptdescr; volatile unsigned char status; pc300_t *card = (pc300_t *)pc300chan->card; int ch = pc300chan->channel; /* dma buf read */ - ptdescr = (pcsca_bd_t *)(card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, pc300chan->rx_first_bd)); while (pc300chan->rx_first_bd != pc300chan->rx_last_bd) { status = cpc_readb(&ptdescr->status); @@ -745,7 +727,7 @@ static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan) if (status & DST_EOM) { break; /* end of message */ } - ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next)); + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->next)); } } @@ -755,12 +737,12 @@ void cpc_tty_receive(pc300dev_t *pc300dev) pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; pc300_t *card = (pc300_t *)pc300chan->card; int ch = pc300chan->channel; - volatile pcsca_bd_t * ptdescr; + volatile pcsca_bd_t __iomem * ptdescr; struct net_device_stats *stats = hdlc_stats(pc300dev->dev); int rx_len, rx_aux; volatile unsigned char status; unsigned short first_bd = pc300chan->rx_first_bd; - st_cpc_rx_buf *new; + st_cpc_rx_buf *new=NULL; unsigned char dsr_rx; if (pc300dev->cpc_tty == NULL) { @@ -773,14 +755,14 @@ void cpc_tty_receive(pc300dev_t *pc300dev) while (1) { rx_len = 0; - ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) { rx_len += cpc_readw(&ptdescr->len); first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1); if (status & DST_EOM) { break; } - ptdescr=(pcsca_bd_t*)(card->hw.rambase+cpc_readl(&ptdescr->next)); + ptdescr=(pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next)); } if (!rx_len) { @@ -789,6 +771,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, pc300chan->rx_last_bd)); } + if (new) { + kfree(new); + new = NULL; + } return; } @@ -808,7 +794,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev) } /* dma buf read */ - ptdescr = (pcsca_bd_t *)(card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, pc300chan->rx_first_bd)); rx_len = 0; /* counter frame size */ @@ -834,7 +820,8 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_tty->name); cpc_tty_rx_disc_frame(pc300chan); rx_len = 0; - kfree((unsigned char *)new); + kfree(new); + new = NULL; break; /* read next frame - while(1) */ } @@ -843,14 +830,15 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_tty_rx_disc_frame(pc300chan); stats->rx_dropped++; rx_len = 0; - kfree((unsigned char *)new); + kfree(new); + new = NULL; break; /* read next frame - while(1) */ } /* read the segment of the frame */ if (rx_aux != 0) { memcpy_fromio((new->data + rx_len), - (void *)(card->hw.rambase + + (void __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), rx_aux); rx_len += rx_aux; } @@ -860,7 +848,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev) (N_DMA_RX_BUF -1); if (status & DST_EOM)break; - ptdescr = (pcsca_bd_t *) (card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + cpc_readl(&ptdescr->next)); } /* update pointer */ @@ -910,13 +898,7 @@ static void cpc_tty_tx_work(void *data) CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name); return; } - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){ - CPC_TTY_DBG("%s:call line disc. wakeup\n",cpc_tty->name); - tty->ldisc.write_wakeup (tty); - } - - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } /* @@ -934,7 +916,7 @@ static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) int ch = chan->channel; struct net_device_stats *stats = hdlc_stats(dev->dev); unsigned long flags; - volatile pcsca_bd_t * ptdescr; + volatile pcsca_bd_t __iomem *ptdescr; int i, nchar; int tosend = len; int nbuf = ((len - 1)/BD_DEF_LEN) + 1; @@ -951,11 +933,11 @@ static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) CPC_TTY_DBG("%s: call dma_buf_write\n", (st_cpc_tty_area *)dev->cpc_tty->name); for (i = 0 ; i < nbuf ; i++) { - ptdescr = (pcsca_bd_t *)(card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + TX_BD_ADDR(ch, card->chan[ch].tx_next_bd)); nchar = (BD_DEF_LEN > tosend) ? tosend : BD_DEF_LEN; if (cpc_readb(&ptdescr->status) & DST_OSB) { - memcpy_toio((void *)(card->hw.rambase + + memcpy_toio((void __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), &pdata[len - tosend], nchar); diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index 0ea4b239e..8dea07b47 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -90,9 +90,9 @@ typedef struct port_s { typedef struct card_s { - u8* rambase; /* buffer memory base (virtual) */ - u8* scabase; /* SCA memory base (virtual) */ - plx9052* plxbase; /* PLX registers memory base (virtual) */ + u8 __iomem *rambase; /* buffer memory base (virtual) */ + u8 __iomem *scabase; /* SCA memory base (virtual) */ + plx9052 __iomem *plxbase;/* PLX registers memory base (virtual) */ u16 rx_ring_buffers; /* number of buffers in a ring */ u16 tx_ring_buffers; u16 buff_offset; /* offset of first buffer of first channel */ @@ -116,7 +116,7 @@ typedef struct card_s { #define get_port(card, port) (&card->ports[port]) #define sca_flush(card) (sca_in(IER0, card)); -static inline void new_memcpy_toio(char *dest, char *src, int length) +static inline void new_memcpy_toio(char __iomem *dest, char *src, int length) { int len; do { @@ -295,7 +295,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, { card_t *card; u8 rev_id; - u32 *p; + u32 __iomem *p; int i; u32 ramsize; u32 ramphys; /* buffer memory base */ diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 8b1ef3e69..34578429d 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -294,7 +294,7 @@ sbni_pci_probe( struct net_device *dev ) { struct pci_dev *pdev = NULL; - while( (pdev = pci_find_class( PCI_CLASS_NETWORK_OTHER << 8, pdev )) + while( (pdev = pci_get_class( PCI_CLASS_NETWORK_OTHER << 8, pdev )) != NULL ) { int pci_irq_line; unsigned long pci_ioaddr; @@ -331,10 +331,14 @@ sbni_pci_probe( struct net_device *dev ) /* avoiding re-enable dual adapters */ if( (pci_ioaddr & 7) == 0 && pci_enable_device( pdev ) ) { release_region( pci_ioaddr, SBNI_IO_EXTENT ); + pci_dev_put( pdev ); return -EIO; } if( sbni_probe1( dev, pci_ioaddr, pci_irq_line ) ) { SET_NETDEV_DEV(dev, &pdev->dev); + /* not the best thing to do, but this is all messed up + for hotplug systems anyway... */ + pci_dev_put( pdev ); return 0; } } diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 12598181a..f0ed00ef0 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -51,9 +51,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c index b00fb7837..afbe0024e 100644 --- a/drivers/net/wan/sdla_chdlc.c +++ b/drivers/net/wan/sdla_chdlc.c @@ -3628,11 +3628,7 @@ static void tty_poll_work (void* data) if ((tty=card->tty)==NULL) return; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup){ - (tty->ldisc.write_wakeup)(tty); - } - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); #if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif @@ -3743,8 +3739,7 @@ static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp) return 0; } -static int wanpipe_tty_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) +static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { unsigned long smp_flags=0; sdla_t *card=NULL; @@ -3788,58 +3783,16 @@ static int wanpipe_tty_write(struct tty_struct * tty, int from_user, return -EINVAL; } - if (from_user) { - - unsigned char *tmp_buf; - - if ((tmp_buf=card->tty_buf)==NULL){ - dbg_printk(KERN_INFO "No TTY BUF in Write\n"); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return -ENOMEM; - } - - if (copy_from_user(tmp_buf,buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to copy from user!\n", - card->devname); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return -EINVAL; - } - - if (chdlc_send(card,(void*)tmp_buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to send, retry later: user!\n", - card->devname); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return 0; - } + if (chdlc_send(card,(void*)buf,count)){ + dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", + card->devname); + clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - }else{ - if (chdlc_send(card,(void*)buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", - card->devname); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return 0; - } + wanpipe_tty_trigger_tx_irq(card); + + if(card->hw.type != SDLA_S514) + s508_unlock(card,&smp_flags); + return 0; } dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); @@ -3857,6 +3810,7 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len) char fp=0; struct tty_struct *tty; int i; + struct tty_ldisc *ld; if (!card->tty_open){ dbg_printk(KERN_INFO "%s: TTY not open during receive\n", @@ -3944,8 +3898,11 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len) len -= offset; } sdla_peek(&card->hw, addr, card->tty_rx+offset, len); - if (tty->ldisc.receive_buf){ - tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen); + ld = tty_ldisc_ref(tty); + if (ld) { + if (ld->receive_buf) + ld->receive_buf(tty,card->tty_rx,&fp,olen); + tty_ldisc_deref(ld); }else{ if (net_ratelimit()){ printk(KERN_INFO @@ -4252,14 +4209,10 @@ static void wanpipe_tty_flush_buffer(struct tty_struct *tty) if (!tty) return; - wake_up_interruptible(&tty->write_wait); #if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - + tty_wakeup(tty); return; } diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c index 52f40883d..2efccb055 100644 --- a/drivers/net/wan/sdla_fr.c +++ b/drivers/net/wan/sdla_fr.c @@ -3678,7 +3678,7 @@ static int process_udp_mgmt_pkt(sdla_t* card) break; } - (void *)ptr_trc_el = card->u.f.curr_trc_el; + ptr_trc_el = (void *)card->u.f.curr_trc_el; buffer_length = 0; fr_udp_pkt->data[0x00] = 0x00; @@ -3729,7 +3729,7 @@ static int process_udp_mgmt_pkt(sdla_t* card) ptr_trc_el ++; if((void *)ptr_trc_el > card->u.f.trc_el_last) - (void*)ptr_trc_el = card->u.f.trc_el_base; + ptr_trc_el = (void*)card->u.f.trc_el_base; buffer_length += sizeof(fpipemon_trc_hdr_t); if(fpipemon_trc->fpipemon_trc_hdr.data_passed) { diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c index 501e9a752..c8bc6da57 100644 --- a/drivers/net/wan/sdladrv.c +++ b/drivers/net/wan/sdladrv.c @@ -937,7 +937,7 @@ int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf, curlen); addr += curlen; - (char*)buf += curlen; + buf = (char*)buf + curlen; len -= curlen; } @@ -1019,7 +1019,7 @@ int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf, curlen); addr += curlen; - (char*)buf += curlen; + buf = (char*)buf + curlen; len -= curlen; } @@ -2001,7 +2001,7 @@ static int detect_s514 (sdlahw_t* hw) (void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, (unsigned long)MAX_SIZEOF_S514_MEMORY); /* map the physical control register memory to virtual memory */ - (void *)hw->vector = ioremap( + hw->vector = (unsigned long)ioremap( (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE), (unsigned long)16); diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c index be10f8c41..74e151ace 100644 --- a/drivers/net/wan/sdlamain.c +++ b/drivers/net/wan/sdlamain.c @@ -976,7 +976,7 @@ static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump) dump.length -= len; dump.offset += len; - (char*)dump.ptr += len; + dump.ptr = (char*)dump.ptr + len; } sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */ diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index f7442d52d..2329c23af 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -50,6 +50,7 @@ #include #include #include +#include #include @@ -767,9 +768,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) struct in_ifaddr *ifa; u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ #ifdef CONFIG_INET - if ((in_dev=in_dev_get(dev)) != NULL) + rcu_read_lock(); + if ((in_dev = __in_dev_get(dev)) != NULL) { - read_lock(&in_dev->lock); for (ifa=in_dev->ifa_list; ifa != NULL; ifa=ifa->ifa_next) { if (strcmp(dev->name, ifa->ifa_label) == 0) @@ -779,9 +780,8 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) break; } } - read_unlock(&in_dev->lock); - in_dev_put(in_dev); } + rcu_read_unlock(); #endif /* I hope both addr and mask are in the net order */ sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 6370aa7c2..e71b1800e 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -71,7 +71,7 @@ typedef struct card_t { int n_ports; /* 1, 2 or 4 ports */ u8 irq; - u8 *plx; /* PLX PCI9060 virtual base address */ + u8 __iomem *plx; /* PLX PCI9060 virtual base address */ struct pci_dev *pdev; /* for pdev->slot_name */ int rx_in; struct sk_buff *rx_skbs[RX_QUEUE_LENGTH]; @@ -224,8 +224,6 @@ static inline void wanxl_rx_intr(card_t *card) #endif stats->rx_packets++; stats->rx_bytes += skb->len; - skb->mac.raw = skb->data; - skb->dev = dev; dev->last_rx = jiffies; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); @@ -399,7 +397,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int wanxl_open(struct net_device *dev) { port_t *port = dev_to_port(dev); - u8 *dbr = port->card->plx + PLX_DOORBELL_TO_CARD; + u8 __iomem *dbr = port->card->plx + PLX_DOORBELL_TO_CARD; unsigned long timeout; int i; @@ -562,7 +560,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, unsigned long timeout; u32 plx_phy; /* PLX PCI base address */ u32 mem_phy; /* memory PCI base addr */ - u8 *mem; /* memory virtual base addr */ + u8 __iomem *mem; /* memory virtual base addr */ int i, ports, alloc_size; #ifndef MODULE diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 467ad7b8c..03f4331b4 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -34,6 +34,8 @@ #include #include "x25_asy.h" +#include + static struct net_device **x25_asy_devs; static int x25_asy_maxdev = SL_NRUNIT; @@ -209,10 +211,8 @@ static void x25_asy_bump(struct x25_asy *sl) return; } skb_push(skb,1); /* LAPB internal control */ - skb->dev = sl->dev; memcpy(skb_put(skb,count), sl->rbuff, count); - skb->mac.raw=skb->data; - skb->protocol=htons(ETH_P_X25); + skb->protocol = x25_type_trans(skb, sl->dev); if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK) { kfree_skb(skb); @@ -253,7 +253,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len) * 14 Oct 1994 Dmitry Gorodchanin. */ sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - actual = sl->tty->driver->write(sl->tty, 0, sl->xbuff, count); + actual = sl->tty->driver->write(sl->tty, sl->xbuff, count); sl->xleft = count - actual; sl->xhead = sl->xbuff + actual; /* VSV */ @@ -283,7 +283,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty) return; } - actual = tty->driver->write(tty, 0, sl->xhead, sl->xleft); + actual = tty->driver->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; } @@ -419,11 +419,7 @@ static void x25_asy_connected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x01; - skb->dev = sl->dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); sl->dev->last_rx = jiffies; } @@ -442,11 +438,7 @@ static void x25_asy_disconnected(struct net_device *dev, int reason) ptr = skb_put(skb, 1); *ptr = 0x02; - skb->dev = sl->dev; - skb->protocol = htons(ETH_P_X25); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_HOST; - + skb->protocol = x25_type_trans(skb, sl->dev); netif_rx(skb); sl->dev->last_rx = jiffies; } diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 8d38c1803..41838bca6 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -34,9 +35,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -1188,6 +1189,7 @@ struct airo_info { struct iw_statistics wstats; // wireless stats unsigned long scan_timestamp; /* Time started to scan */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif /* WIRELESS_EXT */ #ifdef MICSUPPORT /* MIC stuff */ @@ -1209,7 +1211,6 @@ struct airo_info { SsidRid *SSID; APListRid *APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE - u32 pci_state[16]; char proc_name[IFNAMSIZ]; }; @@ -1815,7 +1816,8 @@ static int writeConfigRid(struct airo_info*ai, int lock) { if (!test_bit (FLAG_COMMIT, &ai->flags)) return SUCCESS; - clear_bit (FLAG_COMMIT | FLAG_RESET, &ai->flags); + clear_bit (FLAG_COMMIT, &ai->flags); + clear_bit (FLAG_RESET, &ai->flags); checkThrottle(ai); cfgr = ai->config; @@ -1979,9 +1981,6 @@ static int mpi_send_packet (struct net_device *dev) ai->txfids[0].tx_desc.eoc = 1; ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr); - memcpy((char *)ai->txfids[0].card_ram_off, - (char *)&ai->txfids[0].tx_desc, sizeof(TxFid)); - /* * Magic, the cards firmware needs a length count (2 bytes) in the host buffer * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen @@ -2011,6 +2010,7 @@ static int mpi_send_packet (struct net_device *dev) return ERROR; *payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic)); + ai->txfids[0].tx_desc.len += sizeof(pMic); /* copy data into airo dma buffer */ memcpy (sendbuf, buffer, sizeof(etherHead)); buffer += sizeof(etherHead); @@ -2029,6 +2029,9 @@ static int mpi_send_packet (struct net_device *dev) memcpy(sendbuf, buffer, len); } + memcpy((char *)ai->txfids[0].card_ram_off, + (char *)&ai->txfids[0].tx_desc, sizeof(TxFid)); + OUT4500(ai, EVACK, 8); dev_kfree_skb_any(skb); @@ -2183,6 +2186,12 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { struct airo_info *priv = dev->priv; u32 *fids = priv->fids; + if (test_bit(FLAG_MPI, &priv->flags)) { + /* Not implemented yet for MPI350 */ + netif_stop_queue(dev); + return -ENETDOWN; + } + if ( skb == NULL ) { printk( KERN_ERR "airo: skb == NULL!!!\n" ); return 0; @@ -2248,12 +2257,14 @@ struct net_device_stats *airo_get_stats(struct net_device *dev) { struct airo_info *local = dev->priv; - /* Get stats out of the card if available */ - if (down_trylock(&local->sem) != 0) { - set_bit(JOB_STATS, &local->flags); - wake_up_interruptible(&local->thr_wait); - } else - airo_read_stats(local); + if (!test_bit(JOB_STATS, &local->flags)) { + /* Get stats out of the card if available */ + if (down_trylock(&local->sem) != 0) { + set_bit(JOB_STATS, &local->flags); + wake_up_interruptible(&local->thr_wait); + } else + airo_read_stats(local); + } return &local->stats; } @@ -2339,6 +2350,9 @@ static void del_airo_dev( struct net_device *dev ); void stop_airo_card( struct net_device *dev, int freeres ) { struct airo_info *ai = dev->priv; + + set_bit(FLAG_RADIO_DOWN, &ai->flags); + disable_MAC(ai, 1); disable_interrupts(ai); free_irq( dev->irq, dev ); takedown_proc_entry( dev, ai ); @@ -2626,8 +2640,7 @@ static void wifi_setup(struct net_device *dev) dev->set_mac_address = &airo_set_mac_address; dev->do_ioctl = &airo_ioctl; #ifdef WIRELESS_EXT - dev->get_wireless_stats = airo_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; + dev->wireless_handlers = &airo_handler_def; #endif /* WIRELESS_EXT */ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; @@ -2654,6 +2667,9 @@ static struct net_device *init_wifidev(struct airo_info *ai, dev->priv = ethdev->priv; dev->irq = ethdev->irq; dev->base_addr = ethdev->base_addr; +#ifdef WIRELESS_EXT + dev->wireless_data = ethdev->wireless_data; +#endif /* WIRELESS_EXT */ memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); err = register_netdev(dev); if (err<0) { @@ -2706,7 +2722,7 @@ struct net_device *_init_airo_card( unsigned short irq, int port, set_bit(FLAG_MPI, &ai->flags); } ai->dev = dev; - ai->aux_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&ai->aux_lock); sema_init(&ai->sem, 1); ai->config.len = 0; ai->pci = pci; @@ -2733,8 +2749,9 @@ struct net_device *_init_airo_card( unsigned short irq, int port, dev->set_mac_address = &airo_set_mac_address; dev->do_ioctl = &airo_ioctl; #ifdef WIRELESS_EXT - dev->get_wireless_stats = airo_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; + dev->wireless_handlers = &airo_handler_def; + ai->wireless_data.spy_data = &ai->spy_data; + dev->wireless_data = &ai->wireless_data; #endif /* WIRELESS_EXT */ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; @@ -3217,7 +3234,7 @@ badrx: goto exitrx; } } -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ +#ifdef WIRELESS_SPY if (apriv->spy_data.spy_number > 0) { char *sa; struct iw_quality wstats; @@ -3237,7 +3254,7 @@ badrx: /* Update spy records */ wireless_spy_update(dev, sa, &wstats); } -#endif /* IW_WIRELESS_SPY */ +#endif /* WIRELESS_SPY */ OUT4500( apriv, EVACK, EV_RX); if (test_bit(FLAG_802_11, &apriv->flags)) { @@ -3405,13 +3422,8 @@ static void disable_MAC( struct airo_info *ai, int lock ) { } static void enable_interrupts( struct airo_info *ai ) { - /* Reset the status register */ - u16 status = IN4500( ai, EVSTAT ); - OUT4500( ai, EVACK, status ); /* Enable the interrupts */ OUT4500( ai, EVINTEN, STATUS_INTS ); - /* Note there is a race condition between the last two lines that - I don't know how to get rid of right now... */ } static void disable_interrupts( struct airo_info *ai ) { @@ -3459,7 +3471,7 @@ static void mpi_receive_802_3(struct airo_info *ai) memcpy(buffer + ETH_ALEN * 2, ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off, len - ETH_ALEN * 2 - off); - if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off)) { + if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) { badmic: dev_kfree_skb_irq (skb); goto badrx; @@ -3467,7 +3479,7 @@ badmic: #else memcpy(buffer, ai->rxfids[0].virtual_host_addr, len); #endif -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ +#ifdef WIRELESS_SPY if (ai->spy_data.spy_number > 0) { char *sa; struct iw_quality wstats; @@ -3479,7 +3491,7 @@ badmic: /* Update spy records */ wireless_spy_update(ai->dev, sa, &wstats); } -#endif /* IW_WIRELESS_SPY */ +#endif /* WIRELESS_SPY */ skb->dev = ai->dev; skb->ip_summed = CHECKSUM_NONE; @@ -3669,18 +3681,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = readCapabilityRid(ai, &cap_rid, lock); if ( status != SUCCESS ) return ERROR; - /* - * This driver supports MPI350 firmwares up to, and - * including 5.30.17 - */ - if (test_bit(FLAG_MPI, &ai->flags) && - strncmp (cap_rid.prodVer, "5.00.", 5) && - strncmp (cap_rid.prodVer, "5b00.", 5) && - strncmp (cap_rid.prodVer, "5.02.", 5) && - strncmp (cap_rid.prodVer, "5.20.", 5) && - strncmp (cap_rid.prodVer, "5.30.", 5)) - printk(KERN_ERR "airo: Firmware version %s is not supported. Use it at your own risk!\n", cap_rid.prodVer); - status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock); if ( status == SUCCESS ) { if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) @@ -3715,9 +3715,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) /* Check to see if there are any insmod configured rates to add */ - if ( rates ) { + if ( rates[0] ) { int i = 0; - if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates)); + memset(ai->config.rates,0,sizeof(ai->config.rates)); for( i = 0; i < 8 && rates[i]; i++ ) { ai->config.rates[i] = rates[i]; } @@ -3784,7 +3784,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { // Im really paranoid about letting it run forever! int max_tries = 600000; - u16 cmd; if (IN4500(ai, EVSTAT) & EV_CMD) OUT4500(ai, EVACK, EV_CMD); @@ -3793,26 +3792,23 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { OUT4500(ai, PARAM1, pCmd->parm1); OUT4500(ai, PARAM2, pCmd->parm2); OUT4500(ai, COMMAND, pCmd->cmd); - while ( max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0 && - (cmd = IN4500(ai, COMMAND)) != 0 ) - if (cmd == pCmd->cmd) - // PC4500 didn't notice command, try again - OUT4500(ai, COMMAND, pCmd->cmd); - if ( max_tries == -1 ) { - printk( KERN_ERR - "airo: Max tries exceeded when issueing command\n" ); - return ERROR; - } while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) { + if ((IN4500(ai, COMMAND)) == pCmd->cmd) + // PC4500 didn't notice command, try again + OUT4500(ai, COMMAND, pCmd->cmd); if (!in_atomic() && (max_tries & 255) == 0) schedule(); } + if ( max_tries == -1 ) { printk( KERN_ERR - "airo: Max tries exceeded waiting for command\n" ); - return ERROR; + "airo: Max tries exceeded when issueing command\n" ); + if (IN4500(ai, COMMAND) & COMMAND_BUSY) + OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); + return ERROR; } + // command completed pRsp->status = IN4500(ai, STATUS); pRsp->rsp0 = IN4500(ai, RESP0); @@ -4508,8 +4504,6 @@ static ssize_t proc_read( struct file *file, len = priv->readlen - pos; if (copy_to_user(buffer, priv->rbuffer + pos, len)) return -EFAULT; - if (pos + len > priv->writelen) - priv->writelen = pos + len; *offset = pos + len; return len; } @@ -5501,7 +5495,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, u32 state) issuecommand(ai, &cmd, &rsp); pci_enable_wake(pdev, state, 1); - pci_save_state(pdev, ai->pci_state); + pci_save_state(pdev); return pci_set_power_state(pdev, state); } @@ -5512,7 +5506,7 @@ static int airo_pci_resume(struct pci_dev *pdev) Resp rsp; pci_set_power_state(pdev, 0); - pci_restore_state(pdev, ai->pci_state); + pci_restore_state(pdev); pci_enable_wake(pdev, ai->power, 0); if (ai->power > 1) { @@ -5520,7 +5514,6 @@ static int airo_pci_resume(struct pci_dev *pdev) mpi_init_descriptors(ai); setup_card(ai, dev->dev_addr, 0); clear_bit(FLAG_RADIO_OFF, &ai->flags); - clear_bit(FLAG_RADIO_DOWN, &ai->flags); clear_bit(FLAG_PENDING_XMIT, &ai->flags); } else { OUT4500(ai, EVACK, EV_AWAKEN); @@ -5605,6 +5598,30 @@ static void __exit airo_cleanup_module( void ) * would not work at all... - Jean II */ +static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) +{ + int quality = 0; + + if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) { + if (memcmp(cap_rid->prodName, "350", 3)) + if (status_rid->signalQuality > 0x20) + quality = 0; + else + quality = 0x20 - status_rid->signalQuality; + else + if (status_rid->signalQuality > 0xb0) + quality = 0; + else if (status_rid->signalQuality < 0x10) + quality = 0xa0; + else + quality = 0xb0 - status_rid->signalQuality; + } + return quality; +} + +#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0) +#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50); + /*------------------------------------------------------------------*/ /* * Wireless Handler : get protocol name @@ -6292,7 +6309,8 @@ static int airo_set_txpow(struct net_device *dev, readCapabilityRid(local, &cap_rid, 1); if (vwrq->disabled) { - set_bit (FLAG_RADIO_OFF | FLAG_COMMIT, &local->flags); + set_bit (FLAG_RADIO_OFF, &local->flags); + set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; /* Call commit handler */ } if (vwrq->flags != IW_TXPOW_MWATT) { @@ -6431,7 +6449,7 @@ static int airo_get_range(struct net_device *dev, range->num_frequency = k; /* Hum... Should put the right values there */ - range->max_qual.qual = 10; + range->max_qual.qual = airo_get_max_quality(&cap_rid); range->max_qual.level = 0x100 - 120; /* -120 dBm */ range->max_qual.noise = 0; range->sensitivity = 65535; @@ -6498,13 +6516,20 @@ static int airo_get_range(struct net_device *dev, /* Experimental measurements - boundary 11/5.5 Mb/s */ /* Note : with or without the (local->rssi), results * are somewhat different. - Jean II */ - range->avg_qual.qual = 6; + range->avg_qual.qual = airo_get_avg_quality(&cap_rid); if (local->rssi) range->avg_qual.level = 186; /* -70 dBm */ else range->avg_qual.level = 176; /* -80 dBm */ range->avg_qual.noise = 0; + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP); return 0; } @@ -6872,9 +6897,15 @@ static int airo_get_scan(struct net_device *dev, while((!rc) && (BSSList.index != 0xffff)) { /* Translate to WE format this entry */ current_ev = airo_translate_scan(dev, current_ev, - extra + IW_SCAN_MAX_DATA, + extra + dwrq->length, &BSSList); + /* Check if there is space for one more entry */ + if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { + /* Ask user space to try again with a bigger buffer */ + return -E2BIG; + } + /* Read next entry */ rc = PC4500_readrid(ai, RID_BSSLISTNEXT, &BSSList, sizeof(BSSList), 1); @@ -7010,12 +7041,10 @@ static const struct iw_handler_def airo_handler_def = .num_standard = sizeof(airo_handler)/sizeof(iw_handler), .num_private = sizeof(airo_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(airo_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) airo_handler, - .private = (iw_handler *) airo_private_handler, - .private_args = (struct iw_priv_args *) airo_private_args, - .spy_offset = ((void *) (&((struct airo_info *) NULL)->spy_data) - - (void *) NULL), - + .standard = airo_handler, + .private = airo_private_handler, + .private_args = airo_private_args, + .get_wireless_stats = airo_get_wireless_stats, }; #endif /* WIRELESS_EXT */ @@ -7112,6 +7141,7 @@ static void airo_read_wireless_stats(struct airo_info *local) { StatusRid status_rid; StatsRid stats_rid; + CapabilityRid cap_rid; u32 *vals = stats_rid.vals; /* Get stats out of the card */ @@ -7120,6 +7150,7 @@ static void airo_read_wireless_stats(struct airo_info *local) up(&local->sem); return; } + readCapabilityRid(local, &cap_rid, 0); readStatusRid(local, &status_rid, 0); readStatsRid(local, &stats_rid, RID_STATS, 0); up(&local->sem); @@ -7128,7 +7159,7 @@ static void airo_read_wireless_stats(struct airo_info *local) local->wstats.status = status_rid.mode; /* Signal quality and co. But where is the noise level ??? */ - local->wstats.qual.qual = status_rid.signalQuality; + local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); if (local->rssi) local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; else @@ -7155,12 +7186,14 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) { struct airo_info *local = dev->priv; - /* Get stats out of the card if available */ - if (down_trylock(&local->sem) != 0) { - set_bit(JOB_WSTATS, &local->flags); - wake_up_interruptible(&local->thr_wait); - } else - airo_read_wireless_stats(local); + if (!test_bit(JOB_WSTATS, &local->flags)) { + /* Get stats out of the card if available */ + if (down_trylock(&local->sem) != 0) { + set_bit(JOB_WSTATS, &local->flags); + wake_up_interruptible(&local->thr_wait); + } else + airo_read_wireless_stats(local); + } return &local->wstats; } @@ -7187,9 +7220,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { { case AIROGCAP: ridcode = RID_CAPABILITIES; break; case AIROGCFG: ridcode = RID_CONFIG; - disable_MAC (ai, 1); - writeConfigRid (ai, 1); - enable_MAC (ai, &rsp, 1); + if (test_bit(FLAG_COMMIT, &ai->flags)) { + disable_MAC (ai, 1); + writeConfigRid (ai, 1); + enable_MAC (ai, &rsp, 1); + } break; case AIROGSLIST: ridcode = RID_SSID; break; case AIROGVLIST: ridcode = RID_APLIST; break; @@ -7269,6 +7304,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { case AIROPCAP: ridcode = RID_CAPABILITIES; break; case AIROPAPLIST: ridcode = RID_APLIST; break; case AIROPCFG: ai->config.len = 0; + clear_bit(FLAG_COMMIT, &ai->flags); ridcode = RID_CONFIG; break; case AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break; case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break; diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c index 20bd0dfef..51c54132c 100644 --- a/drivers/net/wireless/airport.c +++ b/drivers/net/wireless/airport.c @@ -1,4 +1,4 @@ -/* airport.c 0.13e +/* airport.c * * A driver for "Hermes" chipset based Apple Airport wireless * card. @@ -11,6 +11,9 @@ * 0.06 : fix possible hang on powerup, add sleep support */ +#define DRIVER_NAME "airport" +#define PFX DRIVER_NAME ": " + #include #include @@ -25,6 +28,7 @@ #include #include #include +#include #include #include @@ -50,7 +54,7 @@ static int airport_suspend(struct macio_dev *mdev, u32 state) { struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; int err; @@ -84,15 +88,14 @@ static int airport_resume(struct macio_dev *mdev) { struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; int err; printk(KERN_DEBUG "%s: Airport waking up\n", dev->name); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/5); + msleep(200); enable_irq(dev->irq); @@ -126,7 +129,7 @@ static int airport_detach(struct macio_dev *mdev) { struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); struct airport *card = priv->card; if (card->ndev_registered) @@ -144,8 +147,7 @@ airport_detach(struct macio_dev *mdev) macio_release_resource(mdev, 0); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); macio_set_drvdata(mdev, NULL); free_netdev(dev); @@ -171,14 +173,12 @@ static int airport_hard_reset(struct orinoco_private *priv) disable_irq(dev->irq); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); enable_irq(dev->irq); - schedule_timeout(HZ); + ssleep(1); #endif return 0; @@ -194,24 +194,24 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match) hermes_t *hw; if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) { - printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n"); + printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n"); return -ENODEV; } /* Allocate space for private device-specific data */ dev = alloc_orinocodev(sizeof(*card), airport_hard_reset); if (! dev) { - printk(KERN_ERR "airport: can't allocate device datas\n"); + printk(KERN_ERR PFX "can't allocate device datas\n"); return -ENODEV; } - priv = dev->priv; + priv = netdev_priv(dev); card = priv->card; hw = &priv->hw; card->mdev = mdev; if (macio_request_resource(mdev, 0, "airport")) { - printk(KERN_ERR "airport: can't request IO resource !\n"); + printk(KERN_ERR PFX "can't request IO resource !\n"); free_netdev(dev); return -EBUSY; } @@ -224,11 +224,11 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match) /* Setup interrupts & base address */ dev->irq = macio_irq(mdev, 0); phys_addr = macio_resource_start(mdev, 0); /* Physical address */ - printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr); + printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr); dev->base_addr = phys_addr; card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN); if (!card->vaddr) { - printk("airport: ioremap() failed\n"); + printk(PFX "ioremap() failed\n"); goto failed; } @@ -237,24 +237,23 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match) /* Power up card */ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ssleep(1); /* Reset it before we get the interrupt */ hermes_init(hw); if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) { - printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq); + printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq); goto failed; } card->irq_requested = 1; /* Tell the stack we exist */ if (register_netdev(dev) != 0) { - printk(KERN_ERR "airport: register_netdev() failed\n"); + printk(KERN_ERR PFX "register_netdev() failed\n"); goto failed; } - printk(KERN_DEBUG "airport: card registered for interface %s\n", dev->name); + printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name); card->ndev_registered = 1; return 0; failed: @@ -263,7 +262,8 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match) } /* airport_attach */ -static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt )"; +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (Benjamin Herrenschmidt )"; MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); @@ -280,7 +280,7 @@ static struct of_match airport_match[] = static struct macio_driver airport_driver = { - .name = "airport", + .name = DRIVER_NAME, .match_table = airport_match, .probe = airport_attach, .remove = airport_detach, diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h index a48af699c..e499f4b52 100644 --- a/drivers/net/wireless/arlan.h +++ b/drivers/net/wireless/arlan.h @@ -19,8 +19,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index cde68a443..646011351 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1267,7 +1267,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs build_wpa_mib(priv); break; case ISR_GENERIC_IRQ: - printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name); + printk(KERN_INFO "%s: Generic_irq received.\n", dev->name); break; } } @@ -2430,12 +2430,13 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) rc = -ENOMEM; break; } - + if (copy_from_user(new_firmware, com.data, com.len)) { + kfree(new_firmware); rc = -EFAULT; break; } - + if (priv->firmware) kfree(priv->firmware); @@ -2566,7 +2567,7 @@ static void join(struct atmel_private *priv, int type) struct { u8 BSSID[6]; u8 SSID[MAX_SSID_LENGTH]; - u8 BSS_type; /* this is a short in a scan command - wierd */ + u8 BSS_type; /* this is a short in a scan command - weird */ u8 channel; u16 timeout; u8 SSID_size; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index c3c561fd9..b99c439ac 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -350,13 +350,10 @@ static struct { /* This is strictly temporary, until PCMCIA devices get integrated into the device model. */ static struct device *atmel_device(void) { - static char *kobj_name = "atmel_cs"; - static struct device dev = { .bus_id = "pcmcia", }; - dev.kobj.k_name = kmalloc(strlen(kobj_name)+1, GFP_KERNEL); - strcpy(dev.kobj.k_name, kobj_name); + kobject_set_name(&dev.kobj, "atmel_cs"); kobject_init(&dev.kobj); return &dev; diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index d5ec3dedb..730090118 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c @@ -13,8 +13,8 @@ * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no * particular order). * - * Copyright (C) 2000, David Gibson, Linuxcare Australia - * Copyright (C) 2001, David Gibson, IBM + * Copyright (C) 2000, David Gibson, Linuxcare Australia. + * (C) Copyright David Gibson, IBM Corp. 2001-2003. * * 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 @@ -53,10 +53,9 @@ #include "hermes.h" MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller"); -MODULE_AUTHOR("David Gibson "); -#ifdef MODULE_LICENSE +MODULE_AUTHOR("Pavel Roskin " + " & David Gibson "); MODULE_LICENSE("Dual MPL/GPL"); -#endif /* These are maximum timeouts. Most often, card wil react much faster */ #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */ @@ -226,7 +225,7 @@ int hermes_init(hermes_t *hw) * * Callable from any context, but locking is your problem. */ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, - hermes_response_t *resp) + struct hermes_response *resp) { int err; int k; @@ -392,7 +391,6 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) return -EIO; } - return 0; } diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index 126923ffd..429d57240 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h @@ -12,7 +12,8 @@ * project, the Linux wvlan_cs driver, Lucent's HCF-Light * (wvlan_hcf.c) library, and the NetBSD wireless driver. * - * Copyright (C) 2000, David Gibson, Linuxcare Australia + * Copyright (C) 2000, David Gibson, Linuxcare Australia. + * (C) Copyright David Gibson, IBM Corp. 2001-2003. * * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. * @@ -124,29 +125,52 @@ /* * Command codes */ -/*--- Controller Commands --------------------------*/ +/*--- Controller Commands ----------------------------*/ #define HERMES_CMD_INIT (0x0000) #define HERMES_CMD_ENABLE (0x0001) #define HERMES_CMD_DISABLE (0x0002) #define HERMES_CMD_DIAG (0x0003) -/*--- Buffer Mgmt Commands --------------------------*/ +/*--- Buffer Mgmt Commands ---------------------------*/ #define HERMES_CMD_ALLOC (0x000A) #define HERMES_CMD_TX (0x000B) -#define HERMES_CMD_CLRPRST (0x0012) -/*--- Regulate Commands --------------------------*/ +/*--- Regulate Commands ------------------------------*/ #define HERMES_CMD_NOTIFY (0x0010) #define HERMES_CMD_INQUIRE (0x0011) -/*--- Configure Commands --------------------------*/ +/*--- Configure Commands -----------------------------*/ #define HERMES_CMD_ACCESS (0x0021) #define HERMES_CMD_DOWNLD (0x0022) +/*--- Serial I/O Commands ----------------------------*/ +#define HERMES_CMD_READMIF (0x0030) +#define HERMES_CMD_WRITEMIF (0x0031) + /*--- Debugging Commands -----------------------------*/ -#define HERMES_CMD_MONITOR (0x0038) -#define HERMES_MONITOR_ENABLE (0x000b) -#define HERMES_MONITOR_DISABLE (0x000f) +#define HERMES_CMD_TEST (0x0038) + + +/* Test command arguments */ +#define HERMES_TEST_SET_CHANNEL 0x0800 +#define HERMES_TEST_MONITOR 0x0b00 +#define HERMES_TEST_STOP 0x0f00 + +/* Authentication algorithms */ +#define HERMES_AUTH_OPEN 1 +#define HERMES_AUTH_SHARED_KEY 2 + +/* WEP settings */ +#define HERMES_WEP_PRIVACY_INVOKED 0x0001 +#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002 +#define HERMES_WEP_HOST_ENCRYPT 0x0010 +#define HERMES_WEP_HOST_DECRYPT 0x0080 + +/* Symbol hostscan options */ +#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001 +#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002 +#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040 +#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080 /* * Frame structures and constants @@ -157,16 +181,6 @@ #define HERMES_802_3_OFFSET (14+32) #define HERMES_802_2_OFFSET (14+32+14) -struct hermes_rx_descriptor { - u16 status; - u32 time; - u8 silence; - u8 signal; - u8 rate; - u8 rxflow; - u32 reserved; -} __attribute__ ((packed)); - #define HERMES_RXSTAT_ERR (0x0003) #define HERMES_RXSTAT_BADCRC (0x0001) #define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) @@ -201,7 +215,11 @@ struct hermes_tx_descriptor { #define HERMES_INQ_TALLIES (0xF100) #define HERMES_INQ_SCAN (0xF101) +#define HERMES_INQ_CHANNELINFO (0xF102) +#define HERMES_INQ_HOSTSCAN (0xF103) +#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104) #define HERMES_INQ_LINKSTATUS (0xF200) +#define HERMES_INQ_SEC_STAT_AGERE (0xF202) struct hermes_tallies_frame { u16 TxUnicastFrames; @@ -233,23 +251,58 @@ struct hermes_tallies_frame { /* Grabbed from wlan-ng - Thanks Mark... - Jean II * This is the result of a scan inquiry command */ /* Structure describing info about an Access Point */ -struct hermes_scan_apinfo { +struct prism2_scan_apinfo { u16 channel; /* Channel where the AP sits */ u16 noise; /* Noise level */ u16 level; /* Signal level */ u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ - u16 beacon_interv; /* Beacon interval ? */ - u16 capabilities; /* Capabilities ? */ + u16 beacon_interv; /* Beacon interval */ + u16 capabilities; /* Capabilities */ + u16 essid_len; /* ESSID length */ u8 essid[32]; /* ESSID of the network */ u8 rates[10]; /* Bit rate supported */ - u16 proberesp_rate; /* ???? */ + u16 proberesp_rate; /* Data rate of the response frame */ + u16 atim; /* ATIM window time, Kus (hostscan only) */ } __attribute__ ((packed)); -/* Container */ -struct hermes_scan_frame { - u16 rsvd; /* ??? */ - u16 scanreason; /* ??? */ - struct hermes_scan_apinfo aps[35]; /* Scan result */ + +/* Same stuff for the Lucent/Agere card. + * Thanks to h1kari - Jean II */ +struct agere_scan_apinfo { + u16 channel; /* Channel where the AP sits */ + u16 noise; /* Noise level */ + u16 level; /* Signal level */ + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ + u16 beacon_interv; /* Beacon interval */ + u16 capabilities; /* Capabilities */ + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ + u16 essid_len; /* ESSID length */ + u8 essid[32]; /* ESSID of the network */ } __attribute__ ((packed)); + +/* Moustafa: Scan structure for Symbol cards */ +struct symbol_scan_apinfo { + u8 channel; /* Channel where the AP sits */ + u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */ + u16 noise; /* Noise level */ + u16 level; /* Signal level */ + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ + u16 beacon_interv; /* Beacon interval */ + u16 capabilities; /* Capabilities */ + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ + u16 essid_len; /* ESSID length */ + u8 essid[32]; /* ESSID of the network */ + u16 rates[5]; /* Bit rate supported */ + u16 basic_rates; /* Basic rates bitmask */ + u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */ + u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */ +} __attribute__ ((packed)); + +union hermes_scan_info { + struct agere_scan_apinfo a; + struct prism2_scan_apinfo p; + struct symbol_scan_apinfo s; +}; + #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) #define HERMES_LINKSTATUS_CONNECTED (0x0001) #define HERMES_LINKSTATUS_DISCONNECTED (0x0002) @@ -262,6 +315,20 @@ struct hermes_linkstatus { u16 linkstatus; /* Link status */ } __attribute__ ((packed)); +struct hermes_response { + u16 status, resp0, resp1, resp2; +}; + +/* "ID" structure - used for ESSID and station nickname */ +struct hermes_idstring { + u16 len; + u16 val[16]; +} __attribute__ ((packed)); + +struct hermes_multicast { + u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; +} __attribute__ ((packed)); + // #define HERMES_DEBUG_BUFFER 1 #define HERMES_DEBUG_BUFSIZE 4096 struct hermes_debug_entry { @@ -294,10 +361,6 @@ typedef struct hermes { #endif } hermes_t; -typedef struct hermes_response { - u16 status, resp0, resp1, resp2; -} hermes_response_t; - /* Register access convenience macros */ #define hermes_read_reg(hw, off) ((hw)->io_space ? \ inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \ @@ -312,9 +375,11 @@ typedef struct hermes_response { #define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val)) /* Function prototypes */ -void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing); +void hermes_struct_init(hermes_t *hw, ulong address, int io_space, + int reg_spacing); int hermes_init(hermes_t *hw); -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp); +int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, + struct hermes_response *resp); int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len, diff --git a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/hermes_rid.h index 761c5422e..4f46b4809 100644 --- a/drivers/net/wireless/hermes_rid.h +++ b/drivers/net/wireless/hermes_rid.h @@ -4,21 +4,21 @@ /* * Configuration RIDs */ -#define HERMES_RID_CNFPORTTYPE 0xFC00 /* used */ -#define HERMES_RID_CNFOWNMACADDR 0xFC01 /* used */ -#define HERMES_RID_CNFDESIREDSSID 0xFC02 /* used */ -#define HERMES_RID_CNFOWNCHANNEL 0xFC03 /* used */ -#define HERMES_RID_CNFOWNSSID 0xFC04 /* used */ +#define HERMES_RID_CNFPORTTYPE 0xFC00 +#define HERMES_RID_CNFOWNMACADDR 0xFC01 +#define HERMES_RID_CNFDESIREDSSID 0xFC02 +#define HERMES_RID_CNFOWNCHANNEL 0xFC03 +#define HERMES_RID_CNFOWNSSID 0xFC04 #define HERMES_RID_CNFOWNATIMWINDOW 0xFC05 -#define HERMES_RID_CNFSYSTEMSCALE 0xFC06 /* used */ +#define HERMES_RID_CNFSYSTEMSCALE 0xFC06 #define HERMES_RID_CNFMAXDATALEN 0xFC07 #define HERMES_RID_CNFWDSADDRESS 0xFC08 -#define HERMES_RID_CNFPMENABLED 0xFC09 /* used */ +#define HERMES_RID_CNFPMENABLED 0xFC09 #define HERMES_RID_CNFPMEPS 0xFC0A -#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B /* used */ -#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C /* used */ -#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D /* used */ -#define HERMES_RID_CNFOWNNAME 0xFC0E /* used */ +#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B +#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C +#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D +#define HERMES_RID_CNFOWNNAME 0xFC0E #define HERMES_RID_CNFOWNDTIMPERIOD 0xFC10 #define HERMES_RID_CNFWDSADDRESS1 0xFC11 #define HERMES_RID_CNFWDSADDRESS2 0xFC12 @@ -27,17 +27,18 @@ #define HERMES_RID_CNFWDSADDRESS5 0xFC15 #define HERMES_RID_CNFWDSADDRESS6 0xFC16 #define HERMES_RID_CNFMULTICASTPMBUFFERING 0xFC17 -#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20 /* used */ +#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20 +#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21 #define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21 -#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23 /* used */ -#define HERMES_RID_CNFDEFAULTKEY0 0xFC24 /* used */ -#define HERMES_RID_CNFDEFAULTKEY1 0xFC25 /* used */ -#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25 /* used */ -#define HERMES_RID_CNFDEFAULTKEY2 0xFC26 /* used */ -#define HERMES_RID_CNFDEFAULTKEY3 0xFC27 /* used */ -#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28 /* used */ +#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23 +#define HERMES_RID_CNFDEFAULTKEY0 0xFC24 +#define HERMES_RID_CNFDEFAULTKEY1 0xFC25 +#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25 +#define HERMES_RID_CNFDEFAULTKEY2 0xFC26 +#define HERMES_RID_CNFDEFAULTKEY3 0xFC27 +#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28 #define HERMES_RID_CNFWEPKEYMAPPINGTABLE 0xFC29 -#define HERMES_RID_CNFAUTHENTICATION 0xFC2A /* used */ +#define HERMES_RID_CNFAUTHENTICATION 0xFC2A #define HERMES_RID_CNFMAXASSOCSTA 0xFC2B #define HERMES_RID_CNFKEYLENGTH_SYMBOL 0xFC2B #define HERMES_RID_CNFTXCONTROL 0xFC2C @@ -53,14 +54,14 @@ #define HERMES_RID_CNFTIMCTRL 0xFC40 #define HERMES_RID_CNFTHIRTY2TALLY 0xFC42 #define HERMES_RID_CNFENHSECURITY 0xFC43 -#define HERMES_RID_CNFGROUPADDRESSES 0xFC80 /* used */ -#define HERMES_RID_CNFCREATEIBSS 0xFC81 /* used */ -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82 /* used */ -#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83 /* used */ -#define HERMES_RID_CNFTXRATECONTROL 0xFC84 /* used */ -#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85 /* used */ +#define HERMES_RID_CNFGROUPADDRESSES 0xFC80 +#define HERMES_RID_CNFCREATEIBSS 0xFC81 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82 +#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83 +#define HERMES_RID_CNFTXRATECONTROL 0xFC84 +#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85 #define HERMES_RID_CNFBASICRATES_SYMBOL 0xFC8A -#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C /* used */ +#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0 0xFC90 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1 0xFC91 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2 0xFC92 @@ -75,18 +76,21 @@ #define HERMES_RID_CNFRTSTHRESHOLD4 0xFC9B #define HERMES_RID_CNFRTSTHRESHOLD5 0xFC9C #define HERMES_RID_CNFRTSTHRESHOLD6 0xFC9D +#define HERMES_RID_CNFHOSTSCAN_SYMBOL 0xFCAB #define HERMES_RID_CNFSHORTPREAMBLE 0xFCB0 -#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0 /* used */ +#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0 #define HERMES_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1 -#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1 /* used */ +#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1 #define HERMES_RID_CNFAUTHENTICATIONRSPTO 0xFCB2 +#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2 #define HERMES_RID_CNFBASICRATES 0xFCB3 #define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4 -#define HERMES_RID_CNFTICKTIME 0xFCE0 /* used */ +#define HERMES_RID_CNFTICKTIME 0xFCE0 #define HERMES_RID_CNFSCANREQUEST 0xFCE1 #define HERMES_RID_CNFJOINREQUEST 0xFCE2 #define HERMES_RID_CNFAUTHENTICATESTATION 0xFCE3 #define HERMES_RID_CNFCHANNELINFOREQUEST 0xFCE4 +#define HERMES_RID_CNFHOSTSCAN 0xFCE5 /* * Information RIDs @@ -100,30 +104,31 @@ #define HERMES_RID_NICID 0xFD0B #define HERMES_RID_MFISUPRANGE 0xFD0C #define HERMES_RID_CFISUPRANGE 0xFD0D -#define HERMES_RID_CHANNELLIST 0xFD10 /* used */ +#define HERMES_RID_CHANNELLIST 0xFD10 #define HERMES_RID_REGULATORYDOMAINS 0xFD11 #define HERMES_RID_TEMPTYPE 0xFD12 #define HERMES_RID_CIS 0xFD13 -#define HERMES_RID_STAID 0xFD20 /* used */ +#define HERMES_RID_STAID 0xFD20 #define HERMES_RID_STASUPRANGE 0xFD21 #define HERMES_RID_MFIACTRANGES 0xFD22 #define HERMES_RID_CFIACTRANGES2 0xFD23 -#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24 /* used */ +#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24 #define HERMES_RID_PORTSTATUS 0xFD40 -#define HERMES_RID_CURRENTSSID 0xFD41 /* used */ -#define HERMES_RID_CURRENTBSSID 0xFD42 /* used */ -#define HERMES_RID_COMMSQUALITY 0xFD43 /* used */ -#define HERMES_RID_CURRENTTXRATE 0xFD44 /* used */ +#define HERMES_RID_CURRENTSSID 0xFD41 +#define HERMES_RID_CURRENTBSSID 0xFD42 +#define HERMES_RID_COMMSQUALITY 0xFD43 +#define HERMES_RID_CURRENTTXRATE 0xFD44 #define HERMES_RID_CURRENTBEACONINTERVAL 0xFD45 #define HERMES_RID_CURRENTSCALETHRESHOLDS 0xFD46 #define HERMES_RID_PROTOCOLRSPTIME 0xFD47 -#define HERMES_RID_SHORTRETRYLIMIT 0xFD48 /* used */ -#define HERMES_RID_LONGRETRYLIMIT 0xFD49 /* used */ -#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A /* used */ +#define HERMES_RID_SHORTRETRYLIMIT 0xFD48 +#define HERMES_RID_LONGRETRYLIMIT 0xFD49 +#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A #define HERMES_RID_MAXRECEIVELIFETIME 0xFD4B #define HERMES_RID_CFPOLLABLE 0xFD4C #define HERMES_RID_AUTHENTICATIONALGORITHMS 0xFD4D #define HERMES_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F +#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL 0xFD51 #define HERMES_RID_CURRENTTXRATE1 0xFD80 #define HERMES_RID_CURRENTTXRATE2 0xFD81 #define HERMES_RID_CURRENTTXRATE3 0xFD82 @@ -133,21 +138,11 @@ #define HERMES_RID_OWNMACADDR 0xFD86 #define HERMES_RID_SCANRESULTSTABLE 0xFD88 #define HERMES_RID_PHYTYPE 0xFDC0 -#define HERMES_RID_CURRENTCHANNEL 0xFDC1 /* used */ +#define HERMES_RID_CURRENTCHANNEL 0xFDC1 #define HERMES_RID_CURRENTPOWERSTATE 0xFDC2 #define HERMES_RID_CCAMODE 0xFDC3 -#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6 /* used */ +#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6 #define HERMES_RID_BUILDSEQ 0xFFFE #define HERMES_RID_FWID 0xFFFF -/* "ID" structure - used for ESSID and station nickname */ -struct hermes_idstring { - u16 len; - u16 val[16]; -} __attribute__ ((packed)); - -typedef struct hermes_multicast { - u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; -} __attribute__ ((packed)) hermes_multicast_t; - #endif diff --git a/drivers/net/wireless/ieee802_11.h b/drivers/net/wireless/ieee802_11.h index 07d626ea1..53dd5248f 100644 --- a/drivers/net/wireless/ieee802_11.h +++ b/drivers/net/wireless/ieee802_11.h @@ -76,4 +76,3 @@ struct ieee802_11_hdr { #define IEEE802_11_SCTL_SEQ 0xFFF0 #endif /* _IEEE802_11_H */ - diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 13641142b..f01634250 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -54,6 +54,7 @@ #include #include #include +#include #ifdef CONFIG_NET_RADIO #include #if WIRELESS_EXT > 12 @@ -70,7 +71,6 @@ #include #include -#include #include #include @@ -219,7 +219,6 @@ static void netwave_reset(struct net_device *dev); /* Misc device stuff */ static int netwave_open(struct net_device *dev); /* Open the device */ static int netwave_close(struct net_device *dev); /* Close the device */ -static int netwave_config(struct net_device *dev, struct ifmap *map); /* Packet transmission and Packet reception */ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev); @@ -482,7 +481,6 @@ static dev_link_t *netwave_attach(void) /* Netwave specific entries in the device structure */ SET_MODULE_OWNER(dev); dev->hard_start_xmit = &netwave_start_xmit; - dev->set_config = &netwave_config; dev->get_stats = &netwave_get_stats; dev->set_multicast_list = &set_multicast_list; /* wireless extensions */ @@ -1288,16 +1286,6 @@ static void netwave_reset(struct net_device *dev) { outb(corConfIENA + corConfLVLREQ, iobase + NETWAVE_REG_COR); } -/* - * Function netwave_config (dev, map) - * - * Configure device, this work is done by netwave_pcmcia_config when a - * card is inserted - */ -static int netwave_config(struct net_device *dev, struct ifmap *map) { - return 0; -} - /* * Function netwave_hw_xmit (data, len, dev) */ diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8161a1c00..284aabeff 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -1,17 +1,23 @@ -/* orinoco.c 0.13e - (formerly known as dldwd_cs.c and orinoco_cs.c) +/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c) * * A driver for Hermes or Prism 2 chipset based PCMCIA wireless * adaptors, with Lucent/Agere, Intersil or Symbol firmware. * - * Copyright (C) 2000 David Gibson, Linuxcare Australia + * Current maintainers (as of 29 September 2003) are: + * Pavel Roskin + * and David Gibson + * + * (C) Copyright David Gibson, IBM Corporation 2001-2003. + * Copyright (C) 2000 David Gibson, Linuxcare Australia. * With some help from : - * Copyright (C) 2001 Jean Tourrilhes, HP Labs - * Copyright (C) 2001 Benjamin Herrenschmidt + * Copyright (C) 2001 Jean Tourrilhes, HP Labs + * Copyright (C) 2001 Benjamin Herrenschmidt * * Based on dummy_cs.c 1.27 2000/06/12 21:27:25 * - * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus - * http://www.fasta.fh-dortmund.de/users/andy/wvlan/ + * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus + * http://www.stud.fh-dortmund.de/~andy/wvlan/ * * 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 @@ -24,7 +30,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David + * . Portions created by David * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights * Reserved. * @@ -58,7 +64,7 @@ * o Add PM timeout (holdover duration) * o Enable "iwconfig eth0 key off" and friends (toggle flags) * o Enable "iwconfig eth0 power unicast/all" (toggle flags) - * o Try with an intel card. It report firmware 1.01, behave like + * o Try with an Intel card. It report firmware 1.01, behave like * an antiquated firmware, however on windows it says 2.00. Yuck ! * o Workaround firmware bug in allocate buffer (Intel 1.01) * o Finish external renaming to orinoco... @@ -68,8 +74,8 @@ * o Update to Wireless 11 -> add retry limit/lifetime support * o Tested with a D-Link DWL 650 card, fill in firmware support * o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot) - * o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-( - * It work on D-Link *only* after a tcpdump. Weird... + * o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-( + * It works on D-Link *only* after a tcpdump. Weird... * And still doesn't work on Intel card. Grrrr... * o Update the mode after a setport3 * o Add preamble setting for Symbol cards (not yet enabled) @@ -82,7 +88,7 @@ * o Clean up RID definitions in hermes.h, other cleanups * * v0.04b -> v0.04c - 24/4/2001 - Jean II - * o Tim Hurley reported a D-Link card + * o Tim Hurley reported a D-Link card * with vendor 02 and firmware 0.08. Added in the capabilities... * o Tested Lucent firmware 7.28, everything works... * @@ -105,15 +111,15 @@ * o Remove deferred power enabling code * * v0.05c -> v0.05d - 5/5/2001 - Jean II - * o Workaround to SNAP decapsulate frame from LinkSys AP - * original patch from : Dong Liu + * o Workaround to SNAP decapsulate frame from Linksys AP + * original patch from : Dong Liu * (note : the memcmp bug was mine - fixed) * o Remove set_retry stuff, no firmware support it (bloat--). * * v0.05d -> v0.06 - 25/5/2001 - Jean II - * Original patch from "Hong Lin" , - * "Ian Kinner" - * and "David Smith" + * Original patch from "Hong Lin" , + * "Ian Kinner" + * and "David Smith" * o Init of priv->tx_rate_ctrl in firmware specific section. * o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh ! * o Spectrum card always need cor_reset (for every reset) @@ -134,15 +140,15 @@ * * v0.06c -> v0.06d - 6/7/2001 - David Gibson * o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus' - * wishes to reduce the number of unecessary messages. + * wishes to reduce the number of unnecessary messages. * o Removed bogus message on CRC error. - * o Merged fixeds for v0.08 Prism 2 firmware from William Waghorn - * + * o Merged fixes for v0.08 Prism 2 firmware from William Waghorn + * * o Slight cleanup/re-arrangement of firmware detection code. * * v0.06d -> v0.06e - 1/8/2001 - David Gibson * o Removed some redundant global initializers (orinoco_cs.c). - * o Added some module metadataa + * o Added some module metadata * * v0.06e -> v0.06f - 14/8/2001 - David Gibson * o Wording fix to license @@ -159,7 +165,7 @@ * v0.07 -> v0.07a - 1/10/3001 - Jean II * o Add code to read Symbol firmware revision, inspired by latest code * in Spectrum24 by Lee John Keyser-Allen - Thanks Lee ! - * o Thanks to Jared Valentine for "providing" me + * o Thanks to Jared Valentine for "providing" me * a 3Com card with a recent firmware, fill out Symbol firmware * capabilities of latest rev (2.20), as well as older Symbol cards. * o Disable Power Management in newer Symbol firmware, the API @@ -172,7 +178,7 @@ * o Turned has_big_wep on for Intersil cards. That's not true for all of * them but we should at least let the capable ones try. * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I - * realised that my assumption that the driver's serialization + * realized that my assumption that the driver's serialization * would prevent the BAP being busy on entry was possibly false, because * things other than seeks may make the BAP busy. * o Use "alternate" (oui 00:00:00) encapsulation by default. @@ -181,12 +187,12 @@ * o Don't try to make __initdata const (the version string). This can't * work because of the way the __initdata sectioning works. * o Added MODULE_LICENSE tags. - * o Support for PLX (transparent PCMCIA->PCI brdge) cards. - * o Changed to using the new type-facist min/max. + * o Support for PLX (transparent PCMCIA->PCI bridge) cards. + * o Changed to using the new type-fascist min/max. * * v0.08 -> v0.08a - 9/10/2001 - David Gibson * o Inserted some missing acknowledgements/info into the Changelog. - * o Fixed some bugs in the normalisation of signel level reporting. + * o Fixed some bugs in the normalization of signal level reporting. * o Fixed bad bug in WEP key handling on Intersil and Symbol firmware, * which led to an instant crash on big-endian machines. * @@ -342,7 +348,7 @@ * o Bugfix in orinoco_stop() - it used to fail if hw_unavailable * was set, which was usually true on PCMCIA hot removes. * o Track LINKSTATUS messages, silently drop Tx packets before - * we are connected (avoids cofusing the firmware), and only + * we are connected (avoids confusing the firmware), and only * give LINKSTATUS printk()s if the status has changed. * * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson @@ -397,7 +403,8 @@ * o Disconnect wireless extensions from fundamental configuration. * o (maybe) Software WEP support (patch from Stano Meduna). * o (maybe) Use multiple Tx buffers - driver handling queue - * rather than firmware. */ + * rather than firmware. + */ /* Locking and synchronization: * @@ -414,7 +421,10 @@ * flag after taking the lock, and if it is set, give up on whatever * they are doing and drop the lock again. The orinoco_lock() * function handles this (it unlocks and returns -EBUSY if - * hw_unavailable is non-zero). */ + * hw_unavailable is non-zero). + */ + +#define DRIVER_NAME "orinoco" #include @@ -444,11 +454,9 @@ /* Module information */ /********************************************************************/ -MODULE_AUTHOR("David Gibson "); +MODULE_AUTHOR("Pavel Roskin & David Gibson "); MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual MPL/GPL"); -#endif /* Level of debugging. Used in the macros in orinoco.h */ #ifdef ORINOCO_DEBUG @@ -464,11 +472,6 @@ MODULE_PARM(suppress_linkstatus, "i"); /* Compile time configuration and compatibility stuff */ /********************************************************************/ -/* Wireless extensions backwards compatibility */ -#ifndef SIOCIWFIRSTPRIV -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif /* SIOCIWFIRSTPRIV */ - /* We do this this way to avoid ifdefs in the actual code */ #ifdef WIRELESS_SPY #define SPY_NUMBER(priv) (priv->spy_number) @@ -497,25 +500,29 @@ MODULE_PARM(suppress_linkstatus, "i"); #define DUMMY_FID 0xFFFF -#define RUP_EVEN(a) (((a) + 1) & (~1)) - /*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \ HERMES_MAX_MULTICAST : 0)*/ #define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST) +#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \ + | HERMES_EV_TX | HERMES_EV_TXEXC \ + | HERMES_EV_WTERR | HERMES_EV_INFO \ + | HERMES_EV_INFDROP ) + /********************************************************************/ /* Data tables */ /********************************************************************/ /* The frequency of each channel in MHz */ -const long channel_frequency[] = { +static const long channel_frequency[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; -#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) ) +#define NUM_CHANNELS ARRAY_SIZE(channel_frequency) -/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */ -struct { +/* This tables gives the actual meanings of the bitrate IDs returned + * by the firmware. */ +static struct { int bitrate; /* in 100s of kilobits */ int automatic; u16 agere_txratectrl; @@ -530,7 +537,7 @@ struct { {55, 1, 7, 7}, {110, 0, 5, 8}, }; -#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0])) +#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table) /********************************************************************/ /* Data types */ @@ -555,133 +562,54 @@ u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; #define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) +struct hermes_rx_descriptor { + u16 status; + u32 time; + u8 silence; + u8 signal; + u8 rate; + u8 rxflow; + u32 reserved; +} __attribute__ ((packed)); + /********************************************************************/ /* Function prototypes */ /********************************************************************/ -static void orinoco_stat_gather(struct net_device *dev, - struct sk_buff *skb, - struct hermes_rx_descriptor *desc); - -static struct net_device_stats *orinoco_get_stats(struct net_device *dev); -static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev); - -/* Hardware control routines */ - +static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int __orinoco_program_rids(struct net_device *dev); - -static int __orinoco_hw_set_bitrate(struct orinoco_private *priv); -static int __orinoco_hw_setup_wep(struct orinoco_private *priv); -static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]); -static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]); -static long orinoco_hw_get_freq(struct orinoco_private *priv); -static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, - s32 *rates, int max); static void __orinoco_set_multicast_list(struct net_device *dev); - -/* Interrupt handling routines */ -static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw); -static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw); - -/* ioctl() routines */ static int orinoco_debug_dump_recs(struct net_device *dev); /********************************************************************/ -/* Function prototypes */ +/* Internal helper functions */ /********************************************************************/ -int __orinoco_up(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - - err = __orinoco_program_rids(dev); - if (err) { - printk(KERN_ERR "%s: Error %d configuring card\n", - dev->name, err); - return err; - } - - /* Fire things up again */ - hermes_set_irqmask(hw, ORINOCO_INTEN); - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_ERR "%s: Error %d enabling MAC port\n", - dev->name, err); - return err; - } - - netif_start_queue(dev); - - return 0; -} - -int __orinoco_down(struct net_device *dev) +static inline void set_port_type(struct orinoco_private *priv) { - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - - netif_stop_queue(dev); - - if (! priv->hw_unavailable) { - if (! priv->broken_disableport) { - err = hermes_disable_port(hw, 0); - if (err) { - /* Some firmwares (e.g. Intersil 1.3.x) seem - * to have problems disabling the port, oh - * well, too bad. */ - printk(KERN_WARNING "%s: Error %d disabling MAC port\n", - dev->name, err); - priv->broken_disableport = 1; - } + switch (priv->iw_mode) { + case IW_MODE_INFRA: + priv->port_type = 1; + priv->createibss = 0; + break; + case IW_MODE_ADHOC: + if (priv->prefer_port3) { + priv->port_type = 3; + priv->createibss = 0; + } else { + priv->port_type = priv->ibss_port; + priv->createibss = 1; } - hermes_set_irqmask(hw, 0); - hermes_write_regn(hw, EVACK, 0xffff); + break; + default: + printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", + priv->ndev->name); } - - /* firmware will have to reassociate */ - priv->last_linkstatus = 0xffff; - priv->connected = 0; - - return 0; } -int orinoco_reinit_firmware(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - - err = hermes_init(hw); - if (err) - return err; - - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err == -EIO) { - /* Try workaround for old Symbol firmware bug */ - printk(KERN_WARNING "%s: firmware ALLOC bug detected " - "(old Symbol firmware?). Trying to work around... ", - dev->name); - - priv->nicbuf_size = TX_NICBUF_SIZE_BUG; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err) - printk("failed!\n"); - else - printk("ok.\n"); - } - - return err; -} +/********************************************************************/ +/* Device methods */ +/********************************************************************/ static int orinoco_open(struct net_device *dev) { @@ -722,843 +650,562 @@ int orinoco_stop(struct net_device *dev) return err; } -static int __orinoco_program_rids(struct net_device *dev) +static struct net_device_stats *orinoco_get_stats(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + + return &priv->stats; +} + +static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; - int err; - struct hermes_idstring idbuf; + struct iw_statistics *wstats = &priv->wstats; + int err = 0; + unsigned long flags; - /* Set the MAC address */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); - if (err) { - printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err); - return err; + if (! netif_device_present(dev)) { + printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n", + dev->name); + return NULL; /* FIXME: Can we do better than this? */ } - /* Set up the link mode */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type); - if (err) { - printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err); - return err; - } - /* Set the channel/frequency */ - if (priv->channel == 0) { - printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name); - if (priv->createibss) - priv->channel = 10; - } - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel); - if (err) { - printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err); - return err; - } + err = orinoco_lock(priv, &flags); + if (err) + return NULL; /* FIXME: Erg, we've been signalled, how + * do we propagate this back up? */ - if (priv->has_ibss) { - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS, - priv->createibss); - if (err) { - printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err); - return err; + if (priv->iw_mode == IW_MODE_ADHOC) { + memset(&wstats->qual, 0, sizeof(wstats->qual)); + /* If a spy address is defined, we report stats of the + * first spy address - Jean II */ + if (SPY_NUMBER(priv)) { + wstats->qual.qual = priv->spy_stat[0].qual; + wstats->qual.level = priv->spy_stat[0].level; + wstats->qual.noise = priv->spy_stat[0].noise; + wstats->qual.updated = priv->spy_stat[0].updated; } + } else { + struct { + u16 qual, signal, noise; + } __attribute__ ((packed)) cq; - if ((strlen(priv->desired_essid) == 0) && (priv->createibss) - && (!priv->has_ibss_any)) { - printk(KERN_WARNING "%s: This firmware requires an \ -ESSID in IBSS-Ad-Hoc mode.\n", dev->name); - /* With wvlan_cs, in this case, we would crash. - * hopefully, this driver will behave better... - * Jean II */ - } + err = HERMES_READ_RECORD(hw, USER_BAP, + HERMES_RID_COMMSQUALITY, &cq); + + wstats->qual.qual = (int)le16_to_cpu(cq.qual); + wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; + wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; + wstats->qual.updated = 7; } - /* Set the desired ESSID */ - idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); - memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); - /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err); - return err; - } - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err); - return err; - } + /* We can't really wait for the tallies inquiry command to + * complete, so we just use the previous results and trigger + * a new tallies inquiry command for next time - Jean II */ + /* FIXME: We're in user context (I think?), so we should just + wait for the tallies to come through */ + err = hermes_inquire(hw, HERMES_INQ_TALLIES); + + orinoco_unlock(priv, &flags); - /* Set the station name */ - idbuf.len = cpu_to_le16(strlen(priv->nick)); - memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err); - return err; - } + if (err) + return NULL; + + return wstats; +} - /* Set AP density */ - if (priv->has_sensitivity) { - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, - priv->ap_density); - if (err) { - printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. " - "Disabling sensitivity control\n", dev->name, err); +static void orinoco_set_multicast_list(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + unsigned long flags; - priv->has_sensitivity = 0; - } + if (orinoco_lock(priv, &flags) != 0) { + printk(KERN_DEBUG "%s: orinoco_set_multicast_list() " + "called when hw_unavailable\n", dev->name); + return; } - /* Set RTS threshold */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh); - if (err) { - printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err); - return err; - } + __orinoco_set_multicast_list(dev); + orinoco_unlock(priv, &flags); +} - /* Set fragmentation threshold or MWO robustness */ - if (priv->has_mwo) - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - priv->mwo_robust); - else - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - priv->frag_thresh); - if (err) { - printk(KERN_ERR "%s: Error %d setting framentation\n", dev->name, err); - return err; - } - - /* Set bitrate */ - err = __orinoco_hw_set_bitrate(priv); - if (err) { - printk(KERN_ERR "%s: Error %d setting bitrate\n", dev->name, err); - return err; - } - - /* Set power management */ - if (priv->has_pm) { - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, - priv->pm_on); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMULTICASTRECEIVE, - priv->pm_mcast); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMAXSLEEPDURATION, - priv->pm_period); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMHOLDOVERDURATION, - priv->pm_timeout); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - } +static int orinoco_change_mtu(struct net_device *dev, int new_mtu) +{ + struct orinoco_private *priv = netdev_priv(dev); - /* Set preamble - only for Symbol so far... */ - if (priv->has_preamble) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPREAMBLE_SYMBOL, - priv->preamble); - if (err) { - printk(KERN_ERR "%s: Error %d setting preamble\n", - dev->name, err); - return err; - } - } + if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) ) + return -EINVAL; - /* Set up encryption */ - if (priv->has_wep) { - err = __orinoco_hw_setup_wep(priv); - if (err) { - printk(KERN_ERR "%s: Error %d activating WEP\n", - dev->name, err); - return err; - } - } + if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) > + (priv->nicbuf_size - ETH_HLEN) ) + return -EINVAL; - /* Set promiscuity / multicast*/ - priv->promiscuous = 0; - priv->mc_count = 0; - __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ + dev->mtu = new_mtu; return 0; } -/* xyzzy */ -static int orinoco_reconfigure(struct net_device *dev) +/********************************************************************/ +/* Tx path */ +/********************************************************************/ + +static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - unsigned long flags; + struct net_device_stats *stats = &priv->stats; + hermes_t *hw = &priv->hw; int err = 0; + u16 txfid = priv->txfid; + char *p; + struct ethhdr *eh; + int len, data_len, data_off; + struct hermes_tx_descriptor desc; + unsigned long flags; - if (priv->broken_disableport) { - schedule_work(&priv->reset_work); - return 0; - } - - err = orinoco_lock(priv, &flags); - if (err) - return err; + TRACE_ENTER(dev->name); - - err = hermes_disable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", + if (! netif_running(dev)) { + printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name); - priv->broken_disableport = 1; - goto out; + TRACE_EXIT(dev->name); + return 1; } - - err = __orinoco_program_rids(dev); - if (err) { - printk(KERN_WARNING "%s: Unable to reconfigure card\n", + + if (netif_queue_stopped(dev)) { + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", dev->name); - goto out; + TRACE_EXIT(dev->name); + return 1; } - - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", + + if (orinoco_lock(priv, &flags) != 0) { + printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", dev->name); - goto out; + TRACE_EXIT(dev->name); + return 1; } - out: - if (err) { - printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); - schedule_work(&priv->reset_work); - err = 0; + if (! priv->connected) { + /* Oops, the firmware hasn't established a connection, + silently drop the packet (this seems to be the + safest approach). */ + stats->tx_errors++; + orinoco_unlock(priv, &flags); + dev_kfree_skb(skb); + TRACE_EXIT(dev->name); + return 0; } - orinoco_unlock(priv, &flags); - return err; - -} - -/* This must be called from user context, without locks held - use - * schedule_work() */ -static void orinoco_reset(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct hermes *hw = &priv->hw; - int err; - unsigned long flags; + /* Length of the packet body */ + /* FIXME: what if the skb is smaller than this? */ + len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); - err = orinoco_lock(priv, &flags); - if (err) - /* When the hardware becomes available again, whatever - * detects that is responsible for re-initializing - * it. So no need for anything further*/ - return; + eh = (struct ethhdr *)skb->data; - netif_stop_queue(dev); + memset(&desc, 0, sizeof(desc)); + desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX); + err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0); + if (err) { + printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n", + dev->name, err); + stats->tx_errors++; + goto fail; + } - /* Shut off interrupts. Depending on what state the hardware - * is in, this might not work, but we'll try anyway */ - hermes_set_irqmask(hw, 0); - hermes_write_regn(hw, EVACK, 0xffff); + /* Clear the 802.11 header and data length fields - some + * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused + * if this isn't done. */ + hermes_clear_words(hw, HERMES_DATA0, + HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); - priv->hw_unavailable++; - priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */ - priv->connected = 0; + /* Encapsulate Ethernet-II frames */ + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ + struct header_struct hdr; + data_len = len; + data_off = HERMES_802_3_OFFSET + sizeof(hdr); + p = skb->data + ETH_HLEN; - orinoco_unlock(priv, &flags); + /* 802.3 header */ + memcpy(hdr.dest, eh->h_dest, ETH_ALEN); + memcpy(hdr.src, eh->h_source, ETH_ALEN); + hdr.len = htons(data_len + ENCAPS_OVERHEAD); + + /* 802.2 header */ + memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr)); + + hdr.ethertype = eh->h_proto; + err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), + txfid, HERMES_802_3_OFFSET); + if (err) { + printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", + dev->name, err); + stats->tx_errors++; + goto fail; + } + } else { /* IEEE 802.3 frame */ + data_len = len + ETH_HLEN; + data_off = HERMES_802_3_OFFSET; + p = skb->data; + } - if (priv->hard_reset) - err = (*priv->hard_reset)(priv); + /* Round up for odd length packets */ + err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2), + txfid, data_off); if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d performing hard reset\n", + printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); - /* FIXME: shutdown of some sort */ - return; + stats->tx_errors++; + goto fail; } - err = orinoco_reinit_firmware(dev); + /* Finally, we actually initiate the send */ + netif_stop_queue(dev); + + err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, + txfid, NULL); if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n", + netif_start_queue(dev); + printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - return; + stats->tx_errors++; + goto fail; } - spin_lock_irq(&priv->lock); /* This has to be called from user context */ + dev->trans_start = jiffies; + stats->tx_bytes += data_off + data_len; - priv->hw_unavailable--; + orinoco_unlock(priv, &flags); - /* priv->open or priv->hw_unavailable might have changed while - * we dropped the lock */ - if (priv->open && (! priv->hw_unavailable)) { - err = __orinoco_up(dev); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", - dev->name, err); - } else - dev->trans_start = jiffies; - } + dev_kfree_skb(skb); - spin_unlock_irq(&priv->lock); + TRACE_EXIT(dev->name); - return; -} + return 0; + fail: + TRACE_EXIT(dev->name); -/********************************************************************/ -/* Internal helper functions */ -/********************************************************************/ - -static inline void -set_port_type(struct orinoco_private *priv) -{ - switch (priv->iw_mode) { - case IW_MODE_INFRA: - priv->port_type = 1; - priv->createibss = 0; - break; - case IW_MODE_ADHOC: - if (priv->prefer_port3) { - priv->port_type = 3; - priv->createibss = 0; - } else { - priv->port_type = priv->ibss_port; - priv->createibss = 1; - } - break; - default: - printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", - priv->ndev->name); - } -} - -/* Does the frame have a SNAP header indicating it should be - * de-encapsulated to Ethernet-II? */ -static inline int -is_ethersnap(struct header_struct *hdr) -{ - /* We de-encapsulate all packets which, a) have SNAP headers - * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header - * and where b) the OUI of the SNAP header is 00:00:00 or - * 00:00:f8 - we need both because different APs appear to use - * different OUIs for some reason */ - return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0) - && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) ); + orinoco_unlock(priv, &flags); + return err; } -static void -orinoco_set_multicast_list(struct net_device *dev) +static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = netdev_priv(dev); - unsigned long flags; + u16 fid = hermes_read_regn(hw, ALLOCFID); - if (orinoco_lock(priv, &flags) != 0) { - printk(KERN_DEBUG "%s: orinoco_set_multicast_list() " - "called when hw_unavailable\n", dev->name); + if (fid != priv->txfid) { + if (fid != DUMMY_FID) + printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n", + dev->name, fid); return; + } else { + netif_wake_queue(dev); } - __orinoco_set_multicast_list(dev); - orinoco_unlock(priv, &flags); + hermes_write_regn(hw, ALLOCFID, DUMMY_FID); } -/********************************************************************/ -/* Hardware control functions */ -/********************************************************************/ +static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct net_device_stats *stats = &priv->stats; + stats->tx_packets++; -static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); +} + +static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) { - hermes_t *hw = &priv->hw; + struct orinoco_private *priv = netdev_priv(dev); + struct net_device_stats *stats = &priv->stats; + u16 fid = hermes_read_regn(hw, TXCOMPLFID); + struct hermes_tx_descriptor desc; int err = 0; - if (priv->bitratemode >= BITRATE_TABLE_SIZE) { - printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n", - priv->ndev->name, priv->bitratemode); - return -EINVAL; - } + if (fid == DUMMY_FID) + return; /* Nothing's really happened */ - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXRATECONTROL, - bitrate_table[priv->bitratemode].agere_txratectrl); - break; - case FIRMWARE_TYPE_INTERSIL: - case FIRMWARE_TYPE_SYMBOL: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXRATECONTROL, - bitrate_table[priv->bitratemode].intersil_txratectrl); - break; - default: - BUG(); + err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " + "(FID=%04X error %d)\n", + dev->name, fid, err); + } else { + DEBUG(1, "%s: Tx error, status %d\n", + dev->name, le16_to_cpu(desc.status)); } + + stats->tx_errors++; - return err; + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } - -static int __orinoco_hw_setup_wep(struct orinoco_private *priv) +static void orinoco_tx_timeout(struct net_device *dev) { - hermes_t *hw = &priv->hw; - int err = 0; - int master_wep_flag; - int auth_flag; + struct orinoco_private *priv = netdev_priv(dev); + struct net_device_stats *stats = &priv->stats; + struct hermes *hw = &priv->hw; - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ - if (priv->wep_on) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXKEY_AGERE, - priv->tx_key); - if (err) - return err; - - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFWEPKEYS_AGERE, - &priv->keys); - if (err) - return err; - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFWEPENABLED_AGERE, - priv->wep_on); - if (err) - return err; - break; + printk(KERN_WARNING "%s: Tx timeout! " + "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n", + dev->name, hermes_read_regn(hw, ALLOCFID), + hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT)); - case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ - case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ - master_wep_flag = 0; /* Off */ - if (priv->wep_on) { - int keylen; - int i; + stats->tx_errors++; - /* Fudge around firmware weirdness */ - keylen = le16_to_cpu(priv->keys[priv->tx_key].len); - - /* Write all 4 keys */ - for(i = 0; i < ORINOCO_MAX_KEYS; i++) { -/* int keylen = le16_to_cpu(priv->keys[i].len); */ - - if (keylen > LARGE_KEY_SIZE) { - printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", - priv->ndev->name, i, keylen); - return -E2BIG; - } + schedule_work(&priv->reset_work); +} - err = hermes_write_ltv(hw, USER_BAP, - HERMES_RID_CNFDEFAULTKEY0 + i, - HERMES_BYTES_TO_RECLEN(keylen), - priv->keys[i].data); - if (err) - return err; - } +/********************************************************************/ +/* Rx path (data frames) */ +/********************************************************************/ - /* Write the index of the key used in transmission */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID, - priv->tx_key); - if (err) - return err; - - if (priv->wep_restrict) { - auth_flag = 2; - master_wep_flag = 3; - } else { - /* Authentication is where Intersil and Symbol - * firmware differ... */ - auth_flag = 1; - if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) - master_wep_flag = 3; /* Symbol */ - else - master_wep_flag = 1; /* Intersil */ - } +/* Does the frame have a SNAP header indicating it should be + * de-encapsulated to Ethernet-II? */ +static inline int is_ethersnap(struct header_struct *hdr) +{ + /* We de-encapsulate all packets which, a) have SNAP headers + * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header + * and where b) the OUI of the SNAP header is 00:00:00 or + * 00:00:f8 - we need both because different APs appear to use + * different OUIs for some reason */ + return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0) + && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) ); +} +static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, + int level, int noise) +{ + struct orinoco_private *priv = netdev_priv(dev); + int i; - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFAUTHENTICATION, auth_flag); - if (err) - return err; + /* Gather wireless spy statistics: for each packet, compare the + * source address with out list, and if match, get the stats... */ + for (i = 0; i < priv->spy_number; i++) + if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { + priv->spy_stat[i].level = level - 0x95; + priv->spy_stat[i].noise = noise - 0x95; + priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0; + priv->spy_stat[i].updated = 7; } - - /* Master WEP setting : on/off */ - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFWEPFLAGS_INTERSIL, - master_wep_flag); - if (err) - return err; +} - break; +static void orinoco_stat_gather(struct net_device *dev, + struct sk_buff *skb, + struct hermes_rx_descriptor *desc) +{ + struct orinoco_private *priv = netdev_priv(dev); - default: - if (priv->wep_on) { - printk(KERN_ERR "%s: WEP enabled, although not supported!\n", - priv->ndev->name); - return -EINVAL; - } + /* Using spy support with lots of Rx packets, like in an + * infrastructure (AP), will really slow down everything, because + * the MAC address must be compared to each entry of the spy list. + * If the user really asks for it (set some address in the + * spy list), we do it, but he will pay the price. + * Note that to get here, you need both WIRELESS_SPY + * compiled in AND some addresses in the list !!! + */ + /* Note : gcc will optimise the whole section away if + * WIRELESS_SPY is not defined... - Jean II */ + if (SPY_NUMBER(priv)) { + orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN, + desc->signal, desc->silence); } - - return 0; } -static int orinoco_hw_get_bssid(struct orinoco_private *priv, - char buf[ETH_ALEN]) +static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { - hermes_t *hw = &priv->hw; - int err = 0; - unsigned long flags; - - err = orinoco_lock(priv, &flags); - if (err) - return err; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, buf); + struct orinoco_private *priv = netdev_priv(dev); + struct net_device_stats *stats = &priv->stats; + struct iw_statistics *wstats = &priv->wstats; + struct sk_buff *skb = NULL; + u16 rxfid, status; + int length, data_len, data_off; + char *p; + struct hermes_rx_descriptor desc; + struct header_struct hdr; + struct ethhdr *eh; + int err; - orinoco_unlock(priv, &flags); + rxfid = hermes_read_regn(hw, RXFID); - return err; -} + err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), + rxfid, 0); + if (err) { + printk(KERN_ERR "%s: error %d reading Rx descriptor. " + "Frame dropped.\n", dev->name, err); + stats->rx_errors++; + goto drop; + } -static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]) -{ - hermes_t *hw = &priv->hw; - int err = 0; - struct hermes_idstring essidbuf; - char *p = (char *)(&essidbuf.val); - int len; - unsigned long flags; + status = le16_to_cpu(desc.status); - err = orinoco_lock(priv, &flags); - if (err) - return err; + if (status & HERMES_RXSTAT_ERR) { + if (status & HERMES_RXSTAT_UNDECRYPTABLE) { + wstats->discard.code++; + DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", + dev->name); + } else { + stats->rx_crc_errors++; + DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); + } + stats->rx_errors++; + goto drop; + } - if (strlen(priv->desired_essid) > 0) { - /* We read the desired SSID from the hardware rather - than from priv->desired_essid, just in case the - firmware is allowed to change it on us. I'm not - sure about this */ - /* My guess is that the OWNSSID should always be whatever - * we set to the card, whereas CURRENT_SSID is the one that - * may change... - Jean II */ - u16 rid; + /* For now we ignore the 802.11 header completely, assuming + that the card's firmware has handled anything vital */ - *active = 1; + err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), + rxfid, HERMES_802_3_OFFSET); + if (err) { + printk(KERN_ERR "%s: error %d reading frame header. " + "Frame dropped.\n", dev->name, err); + stats->rx_errors++; + goto drop; + } - rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : - HERMES_RID_CNFDESIREDSSID; - - err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), - NULL, &essidbuf); - if (err) - goto fail_unlock; - } else { - *active = 0; + length = ntohs(hdr.len); + + /* Sanity checks */ + if (length < 3) { /* No for even an 802.2 LLC header */ + /* At least on Symbol firmware with PCF we get quite a + lot of these legitimately - Poll frames with no + data. */ + stats->rx_dropped++; + goto drop; + } + if (length > IEEE802_11_DATA_LEN) { + printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", + dev->name, length); + stats->rx_length_errors++; + stats->rx_errors++; + goto drop; + } - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, - sizeof(essidbuf), NULL, &essidbuf); - if (err) - goto fail_unlock; + /* We need space for the packet data itself, plus an ethernet + header, plus 2 bytes so we can align the IP header on a + 32bit boundary, plus 1 byte so we can read in odd length + packets from the card, which has an IO granularity of 16 + bits */ + skb = dev_alloc_skb(length+ETH_HLEN+2+1); + if (!skb) { + printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", + dev->name); + goto drop; } - len = le16_to_cpu(essidbuf.len); + skb_reserve(skb, 2); /* This way the IP header is aligned */ - memset(buf, 0, IW_ESSID_MAX_SIZE+1); - memcpy(buf, p, len); - buf[len] = '\0'; + /* Handle decapsulation + * In most cases, the firmware tell us about SNAP frames. + * For some reason, the SNAP frames sent by LinkSys APs + * are not properly recognised by most firmwares. + * So, check ourselves */ + if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || + ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || + is_ethersnap(&hdr)) { + /* These indicate a SNAP within 802.2 LLC within + 802.11 frame which we'll need to de-encapsulate to + the original EthernetII frame. */ - fail_unlock: - orinoco_unlock(priv, &flags); + if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ + stats->rx_length_errors++; + goto drop; + } - return err; -} + /* Remove SNAP header, reconstruct EthernetII frame */ + data_len = length - ENCAPS_OVERHEAD; + data_off = HERMES_802_3_OFFSET + sizeof(hdr); -static long orinoco_hw_get_freq(struct orinoco_private *priv) -{ - - hermes_t *hw = &priv->hw; - int err = 0; - u16 channel; - long freq = 0; - unsigned long flags; + eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); - err = orinoco_lock(priv, &flags); - if (err) - return err; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel); - if (err) - goto out; + memcpy(eh, &hdr, 2 * ETH_ALEN); + eh->h_proto = hdr.ethertype; + } else { + /* All other cases indicate a genuine 802.3 frame. No + decapsulation needed. We just throw the whole + thing in, and hope the protocol layer can deal with + it as 802.3 */ + data_len = length; + data_off = HERMES_802_3_OFFSET; + /* FIXME: we re-read from the card data we already read here */ + } - /* Intersil firmware 1.3.5 returns 0 when the interface is down */ - if (channel == 0) { - err = -EBUSY; - goto out; + p = skb_put(skb, data_len); + err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2), + rxfid, data_off); + if (err) { + printk(KERN_ERR "%s: error %d reading frame. " + "Frame dropped.\n", dev->name, err); + stats->rx_errors++; + goto drop; } - if ( (channel < 1) || (channel > NUM_CHANNELS) ) { - printk(KERN_WARNING "%s: Channel out of range (%d)!\n", - priv->ndev->name, channel); - err = -EBUSY; - goto out; + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_NONE; + + /* Process the wireless stats if needed */ + orinoco_stat_gather(dev, skb, &desc); - } - freq = channel_frequency[channel-1] * 100000; + /* Pass the packet to the networking stack */ + netif_rx(skb); + stats->rx_packets++; + stats->rx_bytes += length; - out: - orinoco_unlock(priv, &flags); + return; - if (err > 0) - err = -EBUSY; - return err ? err : freq; + drop: + stats->rx_dropped++; + + if (skb) + dev_kfree_skb_irq(skb); + return; } -static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, - int *numrates, s32 *rates, int max) -{ - hermes_t *hw = &priv->hw; - struct hermes_idstring list; - unsigned char *p = (unsigned char *)&list.val; - int err = 0; - int num; - int i; - unsigned long flags; +/********************************************************************/ +/* Rx path (info frames) */ +/********************************************************************/ - err = orinoco_lock(priv, &flags); - if (err) - return err; +static void print_linkstatus(struct net_device *dev, u16 status) +{ + char * s; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, - sizeof(list), NULL, &list); - orinoco_unlock(priv, &flags); + if (suppress_linkstatus) + return; - if (err) - return err; + switch (status) { + case HERMES_LINKSTATUS_NOT_CONNECTED: + s = "Not Connected"; + break; + case HERMES_LINKSTATUS_CONNECTED: + s = "Connected"; + break; + case HERMES_LINKSTATUS_DISCONNECTED: + s = "Disconnected"; + break; + case HERMES_LINKSTATUS_AP_CHANGE: + s = "AP Changed"; + break; + case HERMES_LINKSTATUS_AP_OUT_OF_RANGE: + s = "AP Out of Range"; + break; + case HERMES_LINKSTATUS_AP_IN_RANGE: + s = "AP In Range"; + break; + case HERMES_LINKSTATUS_ASSOC_FAILED: + s = "Association Failed"; + break; + default: + s = "UNKNOWN"; + } - num = le16_to_cpu(list.len); - *numrates = num; - num = min(num, max); - - for (i = 0; i < num; i++) { - rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */ - } - - return 0; -} - -#if 0 -static void show_rx_frame(struct orinoco_rxframe_hdr *frame) -{ - printk(KERN_DEBUG "RX descriptor:\n"); - printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); - printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); - printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); - printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); - printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); - printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); - printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); - - printk(KERN_DEBUG "IEEE 802.11 header:\n"); - printk(KERN_DEBUG " frame_ctl = 0x%04x\n", - frame->p80211.frame_ctl); - printk(KERN_DEBUG " duration_id = 0x%04x\n", - frame->p80211.duration_id); - printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr1[0], frame->p80211.addr1[1], - frame->p80211.addr1[2], frame->p80211.addr1[3], - frame->p80211.addr1[4], frame->p80211.addr1[5]); - printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr2[0], frame->p80211.addr2[1], - frame->p80211.addr2[2], frame->p80211.addr2[3], - frame->p80211.addr2[4], frame->p80211.addr2[5]); - printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr3[0], frame->p80211.addr3[1], - frame->p80211.addr3[2], frame->p80211.addr3[3], - frame->p80211.addr3[4], frame->p80211.addr3[5]); - printk(KERN_DEBUG " seq_ctl = 0x%04x\n", - frame->p80211.seq_ctl); - printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr4[0], frame->p80211.addr4[1], - frame->p80211.addr4[2], frame->p80211.addr4[3], - frame->p80211.addr4[4], frame->p80211.addr4[5]); - printk(KERN_DEBUG " data_len = 0x%04x\n", - frame->p80211.data_len); - - printk(KERN_DEBUG "IEEE 802.3 header:\n"); - printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p8023.h_dest[0], frame->p8023.h_dest[1], - frame->p8023.h_dest[2], frame->p8023.h_dest[3], - frame->p8023.h_dest[4], frame->p8023.h_dest[5]); - printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p8023.h_source[0], frame->p8023.h_source[1], - frame->p8023.h_source[2], frame->p8023.h_source[3], - frame->p8023.h_source[4], frame->p8023.h_source[5]); - printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); - - printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); - printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); - printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); - printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); - printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", - frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); - printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); -} -#endif /* 0 */ - -/* - * Interrupt handler - */ -irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - int count = MAX_IRQLOOPS_PER_IRQ; - u16 evstat, events; - /* These are used to detect a runaway interrupt situation */ - /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy, - * we panic and shut down the hardware */ - static int last_irq_jiffy = 0; /* jiffies value the last time we were called */ - static int loops_this_jiffy = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) { - /* If hw is unavailable - we don't know if the irq was - * for us or not */ - return IRQ_HANDLED; - } - - evstat = hermes_read_regn(hw, EVSTAT); - events = evstat & hw->inten; - if (! events) { - orinoco_unlock(priv, &flags); - return IRQ_NONE; - } - - if (jiffies != last_irq_jiffy) - loops_this_jiffy = 0; - last_irq_jiffy = jiffies; - - while (events && count--) { - if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { - printk(KERN_WARNING "%s: IRQ handler is looping too " - "much! Resetting.\n", dev->name); - /* Disable interrupts for now */ - hermes_set_irqmask(hw, 0); - schedule_work(&priv->reset_work); - break; - } - - /* Check the card hasn't been removed */ - if (! hermes_present(hw)) { - DEBUG(0, "orinoco_interrupt(): card removed\n"); - break; - } - - if (events & HERMES_EV_TICK) - __orinoco_ev_tick(dev, hw); - if (events & HERMES_EV_WTERR) - __orinoco_ev_wterr(dev, hw); - if (events & HERMES_EV_INFDROP) - __orinoco_ev_infdrop(dev, hw); - if (events & HERMES_EV_INFO) - __orinoco_ev_info(dev, hw); - if (events & HERMES_EV_RX) - __orinoco_ev_rx(dev, hw); - if (events & HERMES_EV_TXEXC) - __orinoco_ev_txexc(dev, hw); - if (events & HERMES_EV_TX) - __orinoco_ev_tx(dev, hw); - if (events & HERMES_EV_ALLOC) - __orinoco_ev_alloc(dev, hw); - - hermes_write_regn(hw, EVACK, events); - - evstat = hermes_read_regn(hw, EVSTAT); - events = evstat & hw->inten; - }; - - orinoco_unlock(priv, &flags); - return IRQ_HANDLED; -} - -static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) -{ - printk(KERN_DEBUG "%s: TICK\n", dev->name); -} - -static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) -{ - /* This seems to happen a fair bit under load, but ignoring it - seems to work fine...*/ - printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n", - dev->name); -} - -static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) -{ - if (net_ratelimit()) - printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); -} - -static void print_linkstatus(struct net_device *dev, u16 status) -{ - char * s; - - if (suppress_linkstatus) - return; - - switch (status) { - case HERMES_LINKSTATUS_NOT_CONNECTED: - s = "Not Connected"; - break; - case HERMES_LINKSTATUS_CONNECTED: - s = "Connected"; - break; - case HERMES_LINKSTATUS_DISCONNECTED: - s = "Disconnected"; - break; - case HERMES_LINKSTATUS_AP_CHANGE: - s = "AP Changed"; - break; - case HERMES_LINKSTATUS_AP_OUT_OF_RANGE: - s = "AP Out of Range"; - break; - case HERMES_LINKSTATUS_AP_IN_RANGE: - s = "AP In Range"; - break; - case HERMES_LINKSTATUS_ASSOC_FAILED: - s = "Association Failed"; - break; - default: - s = "UNKNOWN"; - } - - printk(KERN_INFO "%s: New link status: %s (%04x)\n", - dev->name, s, status); -} + printk(KERN_INFO "%s: New link status: %s (%04x)\n", + dev->name, s, status); +} static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { @@ -1614,19 +1261,17 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) le16_to_cpu(tallies.RxDiscards_WEPExcluded); wstats->discard.misc += le16_to_cpu(tallies.TxDiscardsWrongSA); -#if WIRELESS_EXT > 11 wstats->discard.fragment += le16_to_cpu(tallies.RxMsgInBadMsgFragments); wstats->discard.retries += le16_to_cpu(tallies.TxRetryLimitExceeded); /* wstats->miss.beacon - no match */ -#endif /* WIRELESS_EXT > 11 */ } break; case HERMES_INQ_LINKSTATUS: { struct hermes_linkstatus linkstatus; u16 newstatus; - + if (len != sizeof(linkstatus)) { printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", dev->name, len); @@ -1654,219 +1299,726 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) } break; default: - printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n", - dev->name, type); + printk(KERN_DEBUG "%s: Unknown information frame received " + "(type %04x).\n", dev->name, type); /* We don't actually do anything about it */ break; } } -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) +{ + if (net_ratelimit()) + printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); +} + +/********************************************************************/ +/* Internal hardware control routines */ +/********************************************************************/ + +int __orinoco_up(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; - struct iw_statistics *wstats = &priv->wstats; - struct sk_buff *skb = NULL; - u16 rxfid, status; - int length, data_len, data_off; - char *p; - struct hermes_rx_descriptor desc; - struct header_struct hdr; - struct ethhdr *eh; + struct hermes *hw = &priv->hw; int err; - rxfid = hermes_read_regn(hw, RXFID); - - err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), - rxfid, 0); + err = __orinoco_program_rids(dev); if (err) { - printk(KERN_ERR "%s: error %d reading Rx descriptor. " - "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + printk(KERN_ERR "%s: Error %d configuring card\n", + dev->name, err); + return err; } - status = le16_to_cpu(desc.status); - - if (status & HERMES_RXSTAT_ERR) { - if (status & HERMES_RXSTAT_UNDECRYPTABLE) { - wstats->discard.code++; - DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", - dev->name); - } else { - stats->rx_crc_errors++; - DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); - } - stats->rx_errors++; - goto drop; + /* Fire things up again */ + hermes_set_irqmask(hw, ORINOCO_INTEN); + err = hermes_enable_port(hw, 0); + if (err) { + printk(KERN_ERR "%s: Error %d enabling MAC port\n", + dev->name, err); + return err; } - /* For now we ignore the 802.11 header completely, assuming - that the card's firmware has handled anything vital */ + netif_start_queue(dev); - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), - rxfid, HERMES_802_3_OFFSET); + return 0; +} + +int __orinoco_down(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + int err; + + netif_stop_queue(dev); + + if (! priv->hw_unavailable) { + if (! priv->broken_disableport) { + err = hermes_disable_port(hw, 0); + if (err) { + /* Some firmwares (e.g. Intersil 1.3.x) seem + * to have problems disabling the port, oh + * well, too bad. */ + printk(KERN_WARNING "%s: Error %d disabling MAC port\n", + dev->name, err); + priv->broken_disableport = 1; + } + } + hermes_set_irqmask(hw, 0); + hermes_write_regn(hw, EVACK, 0xffff); + } + + /* firmware will have to reassociate */ + priv->last_linkstatus = 0xffff; + priv->connected = 0; + + return 0; +} + +int orinoco_reinit_firmware(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + int err; + + err = hermes_init(hw); + if (err) + return err; + + err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); + if (err == -EIO) { + /* Try workaround for old Symbol firmware bug */ + printk(KERN_WARNING "%s: firmware ALLOC bug detected " + "(old Symbol firmware?). Trying to work around... ", + dev->name); + + priv->nicbuf_size = TX_NICBUF_SIZE_BUG; + err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); + if (err) + printk("failed!\n"); + else + printk("ok.\n"); + } + + return err; +} + +static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) +{ + hermes_t *hw = &priv->hw; + int err = 0; + + if (priv->bitratemode >= BITRATE_TABLE_SIZE) { + printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n", + priv->ndev->name, priv->bitratemode); + return -EINVAL; + } + + switch (priv->firmware_type) { + case FIRMWARE_TYPE_AGERE: + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFTXRATECONTROL, + bitrate_table[priv->bitratemode].agere_txratectrl); + break; + case FIRMWARE_TYPE_INTERSIL: + case FIRMWARE_TYPE_SYMBOL: + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFTXRATECONTROL, + bitrate_table[priv->bitratemode].intersil_txratectrl); + break; + default: + BUG(); + } + + return err; +} + +static int __orinoco_hw_setup_wep(struct orinoco_private *priv) +{ + hermes_t *hw = &priv->hw; + int err = 0; + int master_wep_flag; + int auth_flag; + + switch (priv->firmware_type) { + case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ + if (priv->wep_on) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFTXKEY_AGERE, + priv->tx_key); + if (err) + return err; + + err = HERMES_WRITE_RECORD(hw, USER_BAP, + HERMES_RID_CNFWEPKEYS_AGERE, + &priv->keys); + if (err) + return err; + } + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFWEPENABLED_AGERE, + priv->wep_on); + if (err) + return err; + break; + + case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ + case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ + master_wep_flag = 0; /* Off */ + if (priv->wep_on) { + int keylen; + int i; + + /* Fudge around firmware weirdness */ + keylen = le16_to_cpu(priv->keys[priv->tx_key].len); + + /* Write all 4 keys */ + for(i = 0; i < ORINOCO_MAX_KEYS; i++) { +/* int keylen = le16_to_cpu(priv->keys[i].len); */ + + if (keylen > LARGE_KEY_SIZE) { + printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", + priv->ndev->name, i, keylen); + return -E2BIG; + } + + err = hermes_write_ltv(hw, USER_BAP, + HERMES_RID_CNFDEFAULTKEY0 + i, + HERMES_BYTES_TO_RECLEN(keylen), + priv->keys[i].data); + if (err) + return err; + } + + /* Write the index of the key used in transmission */ + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFWEPDEFAULTKEYID, + priv->tx_key); + if (err) + return err; + + if (priv->wep_restrict) { + auth_flag = 2; + master_wep_flag = 3; + } else { + /* Authentication is where Intersil and Symbol + * firmware differ... */ + auth_flag = 1; + if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) + master_wep_flag = 3; /* Symbol */ + else + master_wep_flag = 1; /* Intersil */ + } + + + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFAUTHENTICATION, + auth_flag); + if (err) + return err; + } + + /* Master WEP setting : on/off */ + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFWEPFLAGS_INTERSIL, + master_wep_flag); + if (err) + return err; + + break; + + default: + if (priv->wep_on) { + printk(KERN_ERR "%s: WEP enabled, although not supported!\n", + priv->ndev->name); + return -EINVAL; + } + } + + return 0; +} + +static int __orinoco_program_rids(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + hermes_t *hw = &priv->hw; + int err; + struct hermes_idstring idbuf; + + /* Set the MAC address */ + err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, + HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); if (err) { - printk(KERN_ERR "%s: error %d reading frame header. " - "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + printk(KERN_ERR "%s: Error %d setting MAC address\n", + dev->name, err); + return err; } - length = ntohs(hdr.len); - - /* Sanity checks */ - if (length < 3) { /* No for even an 802.2 LLC header */ - /* At least on Symbol firmware with PCF we get quite a - lot of these legitimately - Poll frames with no - data. */ - stats->rx_dropped++; - goto drop; + /* Set up the link mode */ + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, + priv->port_type); + if (err) { + printk(KERN_ERR "%s: Error %d setting port type\n", + dev->name, err); + return err; } - if (length > IEEE802_11_DATA_LEN) { - printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", - dev->name, length); - stats->rx_length_errors++; - stats->rx_errors++; - goto drop; + /* Set the channel/frequency */ + if (priv->channel == 0) { + printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name); + if (priv->createibss) + priv->channel = 10; + } + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, + priv->channel); + if (err) { + printk(KERN_ERR "%s: Error %d setting channel\n", + dev->name, err); + return err; + } + + if (priv->has_ibss) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFCREATEIBSS, + priv->createibss); + if (err) { + printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err); + return err; + } + + if ((strlen(priv->desired_essid) == 0) && (priv->createibss) + && (!priv->has_ibss_any)) { + printk(KERN_WARNING "%s: This firmware requires an " + "ESSID in IBSS-Ad-Hoc mode.\n", dev->name); + /* With wvlan_cs, in this case, we would crash. + * hopefully, this driver will behave better... + * Jean II */ + } + } + + /* Set the desired ESSID */ + idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); + memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); + /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ + err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), + &idbuf); + if (err) { + printk(KERN_ERR "%s: Error %d setting OWNSSID\n", + dev->name, err); + return err; + } + err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), + &idbuf); + if (err) { + printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", + dev->name, err); + return err; + } + + /* Set the station name */ + idbuf.len = cpu_to_le16(strlen(priv->nick)); + memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); + err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, + HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), + &idbuf); + if (err) { + printk(KERN_ERR "%s: Error %d setting nickname\n", + dev->name, err); + return err; + } + + /* Set AP density */ + if (priv->has_sensitivity) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFSYSTEMSCALE, + priv->ap_density); + if (err) { + printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. " + "Disabling sensitivity control\n", + dev->name, err); + + priv->has_sensitivity = 0; + } + } + + /* Set RTS threshold */ + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, + priv->rts_thresh); + if (err) { + printk(KERN_ERR "%s: Error %d setting RTS threshold\n", + dev->name, err); + return err; + } + + /* Set fragmentation threshold or MWO robustness */ + if (priv->has_mwo) + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFMWOROBUST_AGERE, + priv->mwo_robust); + else + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, + priv->frag_thresh); + if (err) { + printk(KERN_ERR "%s: Error %d setting fragmentation\n", + dev->name, err); + return err; + } + + /* Set bitrate */ + err = __orinoco_hw_set_bitrate(priv); + if (err) { + printk(KERN_ERR "%s: Error %d setting bitrate\n", + dev->name, err); + return err; + } + + /* Set power management */ + if (priv->has_pm) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFPMENABLED, + priv->pm_on); + if (err) { + printk(KERN_ERR "%s: Error %d setting up PM\n", + dev->name, err); + return err; + } + + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFMULTICASTRECEIVE, + priv->pm_mcast); + if (err) { + printk(KERN_ERR "%s: Error %d setting up PM\n", + dev->name, err); + return err; + } + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFMAXSLEEPDURATION, + priv->pm_period); + if (err) { + printk(KERN_ERR "%s: Error %d setting up PM\n", + dev->name, err); + return err; + } + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFPMHOLDOVERDURATION, + priv->pm_timeout); + if (err) { + printk(KERN_ERR "%s: Error %d setting up PM\n", + dev->name, err); + return err; + } + } + + /* Set preamble - only for Symbol so far... */ + if (priv->has_preamble) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFPREAMBLE_SYMBOL, + priv->preamble); + if (err) { + printk(KERN_ERR "%s: Error %d setting preamble\n", + dev->name, err); + return err; + } + } + + /* Set up encryption */ + if (priv->has_wep) { + err = __orinoco_hw_setup_wep(priv); + if (err) { + printk(KERN_ERR "%s: Error %d activating WEP\n", + dev->name, err); + return err; + } + } + + /* Set promiscuity / multicast*/ + priv->promiscuous = 0; + priv->mc_count = 0; + __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ + + return 0; +} + +/* FIXME: return int? */ +static void +__orinoco_set_multicast_list(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + hermes_t *hw = &priv->hw; + int err = 0; + int promisc, mc_count; + + /* The Hermes doesn't seem to have an allmulti mode, so we go + * into promiscuous mode and let the upper levels deal. */ + if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || + (dev->mc_count > MAX_MULTICAST(priv)) ) { + promisc = 1; + mc_count = 0; + } else { + promisc = 0; + mc_count = dev->mc_count; + } + + if (promisc != priv->promiscuous) { + err = hermes_write_wordrec(hw, USER_BAP, + HERMES_RID_CNFPROMISCUOUSMODE, + promisc); + if (err) { + printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n", + dev->name, err); + } else + priv->promiscuous = promisc; + } + + if (! promisc && (mc_count || priv->mc_count) ) { + struct dev_mc_list *p = dev->mc_list; + struct hermes_multicast mclist; + int i; + + for (i = 0; i < mc_count; i++) { + /* paranoia: is list shorter than mc_count? */ + BUG_ON(! p); + /* paranoia: bad address size in list? */ + BUG_ON(p->dmi_addrlen != ETH_ALEN); + + memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN); + p = p->next; + } + + if (p) + printk(KERN_WARNING "Multicast list is longer than mc_count\n"); + + err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES, + HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN), + &mclist); + if (err) + printk(KERN_ERR "%s: Error %d setting multicast list.\n", + dev->name, err); + else + priv->mc_count = mc_count; + } + + /* Since we can set the promiscuous flag when it wasn't asked + for, make sure the net_device knows about it. */ + if (priv->promiscuous) + dev->flags |= IFF_PROMISC; + else + dev->flags &= ~IFF_PROMISC; +} + +static int orinoco_reconfigure(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + unsigned long flags; + int err = 0; + + if (priv->broken_disableport) { + schedule_work(&priv->reset_work); + return 0; + } + + err = orinoco_lock(priv, &flags); + if (err) + return err; + + + err = hermes_disable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", + dev->name); + priv->broken_disableport = 1; + goto out; } - /* We need space for the packet data itself, plus an ethernet - header, plus 2 bytes so we can align the IP header on a - 32bit boundary, plus 1 byte so we can read in odd length - packets from the card, which has an IO granularity of 16 - bits */ - skb = dev_alloc_skb(length+ETH_HLEN+2+1); - if (!skb) { - printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", + err = __orinoco_program_rids(dev); + if (err) { + printk(KERN_WARNING "%s: Unable to reconfigure card\n", dev->name); - goto drop; + goto out; } - skb_reserve(skb, 2); /* This way the IP header is aligned */ + err = hermes_enable_port(hw, 0); + if (err) { + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", + dev->name); + goto out; + } - /* Handle decapsulation - * In most cases, the firmware tell us about SNAP frames. - * For some reason, the SNAP frames sent by LinkSys APs - * are not properly recognised by most firmwares. - * So, check ourselves */ - if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || - ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || - is_ethersnap(&hdr)) { - /* These indicate a SNAP within 802.2 LLC within - 802.11 frame which we'll need to de-encapsulate to - the original EthernetII frame. */ + out: + if (err) { + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); + schedule_work(&priv->reset_work); + err = 0; + } - if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */ - stats->rx_length_errors++; - goto drop; - } + orinoco_unlock(priv, &flags); + return err; - /* Remove SNAP header, reconstruct EthernetII frame */ - data_len = length - ENCAPS_OVERHEAD; - data_off = HERMES_802_3_OFFSET + sizeof(hdr); +} - eh = (struct ethhdr *)skb_put(skb, ETH_HLEN); +/* This must be called from user context, without locks held - use + * schedule_work() */ +static void orinoco_reset(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + int err; + unsigned long flags; - memcpy(eh, &hdr, 2 * ETH_ALEN); - eh->h_proto = hdr.ethertype; - } else { - /* All other cases indicate a genuine 802.3 frame. No - decapsulation needed. We just throw the whole - thing in, and hope the protocol layer can deal with - it as 802.3 */ - data_len = length; - data_off = HERMES_802_3_OFFSET; - /* FIXME: we re-read from the card data we already read here */ + err = orinoco_lock(priv, &flags); + if (err) + /* When the hardware becomes available again, whatever + * detects that is responsible for re-initializing + * it. So no need for anything further */ + return; + + netif_stop_queue(dev); + + /* Shut off interrupts. Depending on what state the hardware + * is in, this might not work, but we'll try anyway */ + hermes_set_irqmask(hw, 0); + hermes_write_regn(hw, EVACK, 0xffff); + + priv->hw_unavailable++; + priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */ + priv->connected = 0; + + orinoco_unlock(priv, &flags); + + if (priv->hard_reset) + err = (*priv->hard_reset)(priv); + if (err) { + printk(KERN_ERR "%s: orinoco_reset: Error %d " + "performing hard reset\n", dev->name, err); + /* FIXME: shutdown of some sort */ + return; } - p = skb_put(skb, data_len); - err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len), - rxfid, data_off); + err = orinoco_reinit_firmware(dev); if (err) { - printk(KERN_ERR "%s: error %d reading frame. " - "Frame dropped.\n", dev->name, err); - stats->rx_errors++; - goto drop; + printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n", + dev->name, err); + return; } - dev->last_rx = jiffies; - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_NONE; - - /* Process the wireless stats if needed */ - orinoco_stat_gather(dev, skb, &desc); + spin_lock_irq(&priv->lock); /* This has to be called from user context */ - /* Pass the packet to the networking stack */ - netif_rx(skb); - stats->rx_packets++; - stats->rx_bytes += length; + priv->hw_unavailable--; - return; + /* priv->open or priv->hw_unavailable might have changed while + * we dropped the lock */ + if (priv->open && (! priv->hw_unavailable)) { + err = __orinoco_up(dev); + if (err) { + printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", + dev->name, err); + } else + dev->trans_start = jiffies; + } - drop: - stats->rx_dropped++; + spin_unlock_irq(&priv->lock); - if (skb) - dev_kfree_skb_irq(skb); return; } -static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; - u16 fid = hermes_read_regn(hw, TXCOMPLFID); - struct hermes_tx_descriptor desc; - int err = 0; - - if (fid == DUMMY_FID) - return; /* Nothing's really happened */ - - err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " - "(FID=%04X error %d)\n", - dev->name, fid, err); - } else { - DEBUG(1, "%s: Tx error, status %d\n", - dev->name, le16_to_cpu(desc.status)); - } - - stats->tx_errors++; +/********************************************************************/ +/* Interrupt handler */ +/********************************************************************/ - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); +static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) +{ + printk(KERN_DEBUG "%s: TICK\n", dev->name); } -static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) +static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) { - struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; - - stats->tx_packets++; - - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); + /* This seems to happen a fair bit under load, but ignoring it + seems to work fine...*/ + printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n", + dev->name); } -static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) +irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct net_device *dev = (struct net_device *)dev_id; struct orinoco_private *priv = netdev_priv(dev); + hermes_t *hw = &priv->hw; + int count = MAX_IRQLOOPS_PER_IRQ; + u16 evstat, events; + /* These are used to detect a runaway interrupt situation */ + /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy, + * we panic and shut down the hardware */ + static int last_irq_jiffy = 0; /* jiffies value the last time + * we were called */ + static int loops_this_jiffy = 0; + unsigned long flags; - u16 fid = hermes_read_regn(hw, ALLOCFID); + if (orinoco_lock(priv, &flags) != 0) { + /* If hw is unavailable - we don't know if the irq was + * for us or not */ + return IRQ_HANDLED; + } - if (fid != priv->txfid) { - if (fid != DUMMY_FID) - printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n", - dev->name, fid); - return; - } else { - netif_wake_queue(dev); + evstat = hermes_read_regn(hw, EVSTAT); + events = evstat & hw->inten; + if (! events) { + orinoco_unlock(priv, &flags); + return IRQ_NONE; } + + if (jiffies != last_irq_jiffy) + loops_this_jiffy = 0; + last_irq_jiffy = jiffies; - hermes_write_regn(hw, ALLOCFID, DUMMY_FID); + while (events && count--) { + if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { + printk(KERN_WARNING "%s: IRQ handler is looping too " + "much! Resetting.\n", dev->name); + /* Disable interrupts for now */ + hermes_set_irqmask(hw, 0); + schedule_work(&priv->reset_work); + break; + } + + /* Check the card hasn't been removed */ + if (! hermes_present(hw)) { + DEBUG(0, "orinoco_interrupt(): card removed\n"); + break; + } + + if (events & HERMES_EV_TICK) + __orinoco_ev_tick(dev, hw); + if (events & HERMES_EV_WTERR) + __orinoco_ev_wterr(dev, hw); + if (events & HERMES_EV_INFDROP) + __orinoco_ev_infdrop(dev, hw); + if (events & HERMES_EV_INFO) + __orinoco_ev_info(dev, hw); + if (events & HERMES_EV_RX) + __orinoco_ev_rx(dev, hw); + if (events & HERMES_EV_TXEXC) + __orinoco_ev_txexc(dev, hw); + if (events & HERMES_EV_TX) + __orinoco_ev_tx(dev, hw); + if (events & HERMES_EV_ALLOC) + __orinoco_ev_alloc(dev, hw); + + hermes_write_regn(hw, EVACK, events); + + evstat = hermes_read_regn(hw, EVSTAT); + events = evstat & hw->inten; + }; + + orinoco_unlock(priv, &flags); + return IRQ_HANDLED; } +/********************************************************************/ +/* Initialization */ +/********************************************************************/ + struct sta_id { u16 id, variant, major, minor; } __attribute__ ((packed)); @@ -1901,11 +2053,11 @@ static void determine_firmware(struct net_device *dev) dev->name, err); memset(&sta_id, 0, sizeof(sta_id)); } + le16_to_cpus(&sta_id.id); le16_to_cpus(&sta_id.variant); le16_to_cpus(&sta_id.major); le16_to_cpus(&sta_id.minor); - printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n", dev->name, sta_id.id, sta_id.variant, sta_id.major, sta_id.minor); @@ -2018,12 +2170,7 @@ static void determine_firmware(struct net_device *dev) } } -/* - * struct net_device methods - */ - -static int -orinoco_init(struct net_device *dev) +static int orinoco_init(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -2112,7 +2259,8 @@ orinoco_init(struct net_device *dev) err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, &priv->rts_thresh); if (err) { - printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name); + printk(KERN_ERR "%s: failed to read RTS threshold!\n", + dev->name); goto out; } @@ -2125,7 +2273,8 @@ orinoco_init(struct net_device *dev) err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, &priv->frag_thresh); if (err) { - printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name); + printk(KERN_ERR "%s: failed to read fragmentation settings!\n", + dev->name); goto out; } @@ -2153,7 +2302,8 @@ orinoco_init(struct net_device *dev) /* Preamble setup */ if (priv->has_preamble) { - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL, + err = hermes_read_wordrec(hw, USER_BAP, + HERMES_RID_CNFPREAMBLE_SYMBOL, &priv->preamble); if (err) goto out; @@ -2202,357 +2352,204 @@ orinoco_init(struct net_device *dev) return err; } -struct net_device_stats * -orinoco_get_stats(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - - return &priv->stats; -} - -struct iw_statistics * -orinoco_get_wireless_stats(struct net_device *dev) +struct net_device *alloc_orinocodev(int sizeof_card, + int (*hard_reset)(struct orinoco_private *)) { - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - struct iw_statistics *wstats = &priv->wstats; - int err = 0; - unsigned long flags; - - if (! netif_device_present(dev)) { - printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n", - dev->name); - return NULL; /* FIXME: Can we do better than this? */ - } + struct net_device *dev; + struct orinoco_private *priv; - err = orinoco_lock(priv, &flags); - if (err) - return NULL; /* FIXME: Erg, we've been signalled, how - * do we propagate this back up? */ + dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card); + if (! dev) + return NULL; + priv = netdev_priv(dev); + priv->ndev = dev; + if (sizeof_card) + priv->card = (void *)((unsigned long)netdev_priv(dev) + + sizeof(struct orinoco_private)); + else + priv->card = NULL; - if (priv->iw_mode == IW_MODE_ADHOC) { - memset(&wstats->qual, 0, sizeof(wstats->qual)); - /* If a spy address is defined, we report stats of the - * first spy address - Jean II */ - if (SPY_NUMBER(priv)) { - wstats->qual.qual = priv->spy_stat[0].qual; - wstats->qual.level = priv->spy_stat[0].level; - wstats->qual.noise = priv->spy_stat[0].noise; - wstats->qual.updated = priv->spy_stat[0].updated; - } - } else { - struct { - u16 qual, signal, noise; - } __attribute__ ((packed)) cq; + /* Setup / override net_device fields */ + dev->init = orinoco_init; + dev->hard_start_xmit = orinoco_xmit; + dev->tx_timeout = orinoco_tx_timeout; + dev->watchdog_timeo = HZ; /* 1 second timeout */ + dev->get_stats = orinoco_get_stats; + dev->get_wireless_stats = orinoco_get_wireless_stats; + dev->do_ioctl = orinoco_ioctl; + dev->change_mtu = orinoco_change_mtu; + dev->set_multicast_list = orinoco_set_multicast_list; + /* we use the default eth_mac_addr for setting the MAC addr */ - err = HERMES_READ_RECORD(hw, USER_BAP, - HERMES_RID_COMMSQUALITY, &cq); - - wstats->qual.qual = (int)le16_to_cpu(cq.qual); - wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; - wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; - wstats->qual.updated = 7; - } + /* Set up default callbacks */ + dev->open = orinoco_open; + dev->stop = orinoco_stop; + priv->hard_reset = hard_reset; - /* We can't really wait for the tallies inquiry command to - * complete, so we just use the previous results and trigger - * a new tallies inquiry command for next time - Jean II */ - /* FIXME: We're in user context (I think?), so we should just - wait for the tallies to come through */ - err = hermes_inquire(hw, HERMES_INQ_TALLIES); - - orinoco_unlock(priv, &flags); + spin_lock_init(&priv->lock); + priv->open = 0; + priv->hw_unavailable = 1; /* orinoco_init() must clear this + * before anything else touches the + * hardware */ + INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - if (err) - return NULL; - - return wstats; -} + priv->last_linkstatus = 0xffff; + priv->connected = 0; -static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, - int level, int noise) -{ - struct orinoco_private *priv = netdev_priv(dev); - int i; + return dev; - /* Gather wireless spy statistics: for each packet, compare the - * source address with out list, and if match, get the stats... */ - for (i = 0; i < priv->spy_number; i++) - if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { - priv->spy_stat[i].level = level - 0x95; - priv->spy_stat[i].noise = noise - 0x95; - priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0; - priv->spy_stat[i].updated = 7; - } } -void -orinoco_stat_gather(struct net_device *dev, - struct sk_buff *skb, - struct hermes_rx_descriptor *desc) -{ - struct orinoco_private *priv = netdev_priv(dev); - - /* Using spy support with lots of Rx packets, like in an - * infrastructure (AP), will really slow down everything, because - * the MAC address must be compared to each entry of the spy list. - * If the user really asks for it (set some address in the - * spy list), we do it, but he will pay the price. - * Note that to get here, you need both WIRELESS_SPY - * compiled in AND some addresses in the list !!! - */ - /* Note : gcc will optimise the whole section away if - * WIRELESS_SPY is not defined... - Jean II */ - if (SPY_NUMBER(priv)) { - orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN, - desc->signal, desc->silence); - } -} +/********************************************************************/ +/* Wireless extensions */ +/********************************************************************/ -static int -orinoco_xmit(struct sk_buff *skb, struct net_device *dev) +static int orinoco_hw_get_bssid(struct orinoco_private *priv, + char buf[ETH_ALEN]) { - struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; hermes_t *hw = &priv->hw; int err = 0; - u16 txfid = priv->txfid; - char *p; - struct ethhdr *eh; - int len, data_len, data_off; - struct hermes_tx_descriptor desc; unsigned long flags; - TRACE_ENTER(dev->name); + err = orinoco_lock(priv, &flags); + if (err) + return err; - if (! netif_running(dev)) { - printk(KERN_ERR "%s: Tx on stopped device!\n", - dev->name); - TRACE_EXIT(dev->name); - return 1; - } - - if (netif_queue_stopped(dev)) { - printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", - dev->name); - TRACE_EXIT(dev->name); - return 1; - } - - if (orinoco_lock(priv, &flags) != 0) { - printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", - dev->name); - TRACE_EXIT(dev->name); -/* BUG(); */ - return 1; - } + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, buf); - if (! priv->connected) { - /* Oops, the firmware hasn't established a connection, - silently drop the packet (this seems to be the - safest approach). */ - stats->tx_errors++; - orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - TRACE_EXIT(dev->name); - return 0; - } + orinoco_unlock(priv, &flags); - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ - len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); + return err; +} - eh = (struct ethhdr *)skb->data; +static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, + char buf[IW_ESSID_MAX_SIZE+1]) +{ + hermes_t *hw = &priv->hw; + int err = 0; + struct hermes_idstring essidbuf; + char *p = (char *)(&essidbuf.val); + int len; + unsigned long flags; - memset(&desc, 0, sizeof(desc)); - desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0); - if (err) { - printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n", - dev->name, err); - stats->tx_errors++; - goto fail; - } + err = orinoco_lock(priv, &flags); + if (err) + return err; - /* Clear the 802.11 header and data length fields - some - * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused - * if this isn't done. */ - hermes_clear_words(hw, HERMES_DATA0, - HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); + if (strlen(priv->desired_essid) > 0) { + /* We read the desired SSID from the hardware rather + than from priv->desired_essid, just in case the + firmware is allowed to change it on us. I'm not + sure about this */ + /* My guess is that the OWNSSID should always be whatever + * we set to the card, whereas CURRENT_SSID is the one that + * may change... - Jean II */ + u16 rid; - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */ - struct header_struct hdr; - data_len = len; - data_off = HERMES_802_3_OFFSET + sizeof(hdr); - p = skb->data + ETH_HLEN; + *active = 1; - /* 802.3 header */ - memcpy(hdr.dest, eh->h_dest, ETH_ALEN); - memcpy(hdr.src, eh->h_source, ETH_ALEN); - hdr.len = htons(data_len + ENCAPS_OVERHEAD); + rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : + HERMES_RID_CNFDESIREDSSID; - /* 802.2 header */ - memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr)); - - hdr.ethertype = eh->h_proto; - err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), - txfid, HERMES_802_3_OFFSET); - if (err) { - printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", - dev->name, err); - stats->tx_errors++; - goto fail; - } - } else { /* IEEE 802.3 frame */ - data_len = len + ETH_HLEN; - data_off = HERMES_802_3_OFFSET; - p = skb->data; - } + err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), + NULL, &essidbuf); + if (err) + goto fail_unlock; + } else { + *active = 0; - /* Round up for odd length packets */ - err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off); - if (err) { - printk(KERN_ERR "%s: Error %d writing packet to BAP\n", - dev->name, err); - stats->tx_errors++; - goto fail; + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, + sizeof(essidbuf), NULL, &essidbuf); + if (err) + goto fail_unlock; } - /* Finally, we actually initiate the send */ - netif_stop_queue(dev); - - err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL); - if (err) { - netif_start_queue(dev); - printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - stats->tx_errors++; - goto fail; - } + len = le16_to_cpu(essidbuf.len); - dev->trans_start = jiffies; - stats->tx_bytes += data_off + data_len; + memset(buf, 0, IW_ESSID_MAX_SIZE+1); + memcpy(buf, p, len); + buf[len] = '\0'; + fail_unlock: orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - - TRACE_EXIT(dev->name); - - return 0; - fail: - TRACE_EXIT(dev->name); - - orinoco_unlock(priv, &flags); - return err; + return err; } -static void -orinoco_tx_timeout(struct net_device *dev) +static long orinoco_hw_get_freq(struct orinoco_private *priv) { - struct orinoco_private *priv = netdev_priv(dev); - struct net_device_stats *stats = &priv->stats; - struct hermes *hw = &priv->hw; - - printk(KERN_WARNING "%s: Tx timeout! " - "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n", - dev->name, hermes_read_regn(hw, ALLOCFID), - hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT)); - - stats->tx_errors++; + + hermes_t *hw = &priv->hw; + int err = 0; + u16 channel; + long freq = 0; + unsigned long flags; - schedule_work(&priv->reset_work); -} + err = orinoco_lock(priv, &flags); + if (err) + return err; + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel); + if (err) + goto out; -static int -orinoco_change_mtu(struct net_device *dev, int new_mtu) -{ - struct orinoco_private *priv = netdev_priv(dev); + /* Intersil firmware 1.3.5 returns 0 when the interface is down */ + if (channel == 0) { + err = -EBUSY; + goto out; + } - if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) ) - return -EINVAL; + if ( (channel < 1) || (channel > NUM_CHANNELS) ) { + printk(KERN_WARNING "%s: Channel out of range (%d)!\n", + priv->ndev->name, channel); + err = -EBUSY; + goto out; - if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) > - (priv->nicbuf_size - ETH_HLEN) ) - return -EINVAL; + } + freq = channel_frequency[channel-1] * 100000; - dev->mtu = new_mtu; + out: + orinoco_unlock(priv, &flags); - return 0; + if (err > 0) + err = -EBUSY; + return err ? err : freq; } -/* FIXME: return int? */ -static void -__orinoco_set_multicast_list(struct net_device *dev) +static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, + int *numrates, s32 *rates, int max) { - struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; + struct hermes_idstring list; + unsigned char *p = (unsigned char *)&list.val; int err = 0; - int promisc, mc_count; - - /* The Hermes doesn't seem to have an allmulti mode, so we go - * into promiscuous mode and let the upper levels deal. */ - if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > MAX_MULTICAST(priv)) ) { - promisc = 1; - mc_count = 0; - } else { - promisc = 0; - mc_count = dev->mc_count; - } + int num; + int i; + unsigned long flags; - if (promisc != priv->promiscuous) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPROMISCUOUSMODE, - promisc); - if (err) { - printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n", - dev->name, err); - } else - priv->promiscuous = promisc; - } + err = orinoco_lock(priv, &flags); + if (err) + return err; - if (! promisc && (mc_count || priv->mc_count) ) { - struct dev_mc_list *p = dev->mc_list; - hermes_multicast_t mclist; - int i; + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, + sizeof(list), NULL, &list); + orinoco_unlock(priv, &flags); - for (i = 0; i < mc_count; i++) { - /* Paranoia: */ - if (! p) - BUG(); /* Multicast list shorter than mc_count */ - if (p->dmi_addrlen != ETH_ALEN) - BUG(); /* Bad address size in multicast list */ - - memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN); - p = p->next; - } - - if (p) - printk(KERN_WARNING "Multicast list is longer than mc_count\n"); + if (err) + return err; + + num = le16_to_cpu(list.len); + *numrates = num; + num = min(num, max); - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES, - HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN), - &mclist); - if (err) - printk(KERN_ERR "%s: Error %d setting multicast list.\n", - dev->name, err); - else - priv->mc_count = mc_count; + for (i = 0; i < num; i++) { + rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */ } - /* Since we can set the promiscuous flag when it wasn't asked - for, make sure the net_device knows about it. */ - if (priv->promiscuous) - dev->flags |= IFF_PROMISC; - else - dev->flags &= ~IFF_PROMISC; + return 0; } -/********************************************************************/ -/* Wireless extensions support */ -/********************************************************************/ - static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) { struct orinoco_private *priv = netdev_priv(dev); @@ -2582,10 +2579,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq /* Much of this shamelessly taken from wvlan_cs.c. No idea * what it all means -dgibson */ -#if WIRELESS_EXT > 10 range.we_version_compiled = WIRELESS_EXT; range.we_version_source = 11; -#endif /* WIRELESS_EXT > 10 */ range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ @@ -2612,22 +2607,17 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq range.max_qual.qual = 0; range.max_qual.level = 0; range.max_qual.noise = 0; -#if WIRELESS_EXT > 11 range.avg_qual.qual = 0; range.avg_qual.level = 0; range.avg_qual.noise = 0; -#endif /* WIRELESS_EXT > 11 */ - } else { range.max_qual.qual = 0x8b - 0x2f; range.max_qual.level = 0x2f - 0x95 - 1; range.max_qual.noise = 0x2f - 0x95 - 1; -#if WIRELESS_EXT > 11 /* Need to get better values */ range.avg_qual.qual = 0x24; range.avg_qual.level = 0xC2; range.avg_qual.noise = 0x9E; -#endif /* WIRELESS_EXT > 11 */ } err = orinoco_hw_get_bitratelist(priv, &numrates, @@ -2680,7 +2670,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq range.txpower[0] = 15; /* 15dBm */ range.txpower_capa = IW_TXPOW_DBM; -#if WIRELESS_EXT > 10 range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; range.retry_flags = IW_RETRY_LIMIT; range.r_time_flags = IW_RETRY_LIFETIME; @@ -2688,7 +2677,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq range.max_retry = 65535; /* ??? */ range.min_r_time = 0; range.max_r_time = 65535 * 1000; /* ??? */ -#endif /* WIRELESS_EXT > 10 */ if (copy_to_user(rrq->pointer, &range, sizeof(range))) return -EFAULT; @@ -2737,7 +2725,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) index = priv->tx_key; - + + /* Adjust key length to a supported value */ if (erq->length > SMALL_KEY_SIZE) { xlen = LARGE_KEY_SIZE; } else if (erq->length > 0) { @@ -2779,14 +2768,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er if (erq->pointer) { priv->keys[index].len = cpu_to_le16(xlen); - memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); + memset(priv->keys[index].data, 0, + sizeof(priv->keys[index].data)); memcpy(priv->keys[index].data, keybuf, erq->length); } priv->tx_key = setindex; priv->wep_on = enable; priv->wep_restrict = restricted; - out: orinoco_unlock(priv, &flags); @@ -3012,7 +3001,8 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) err = orinoco_lock(priv, &flags); if (err) return err; - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, &val); + err = hermes_read_wordrec(hw, USER_BAP, + HERMES_RID_CNFSYSTEMSCALE, &val); orinoco_unlock(priv, &flags); if (err) @@ -3201,8 +3191,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) ratemode = priv->bitratemode; - if ( (ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE) ) - BUG(); + BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE)); rrq->value = bitrate_table[ratemode].bitrate * 100000; rrq->fixed = ! bitrate_table[ratemode].automatic; @@ -3354,7 +3343,6 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) return err; } -#if WIRELESS_EXT > 10 static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) { struct orinoco_private *priv = netdev_priv(dev); @@ -3406,7 +3394,6 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) return err; } -#endif /* WIRELESS_EXT > 10 */ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) { @@ -3500,7 +3487,6 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) *val = priv->prefer_port3; orinoco_unlock(priv, &flags); - return 0; } @@ -3790,7 +3776,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) wrq->u.txpower.flags = IW_TXPOW_DBM; break; -#if WIRELESS_EXT > 10 case SIOCSIWRETRY: err = -EOPNOTSUPP; break; @@ -3798,7 +3783,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) case SIOCGIWRETRY: err = orinoco_ioctl_getretry(dev, &wrq->u.retry); break; -#endif /* WIRELESS_EXT > 10 */ case SIOCSIWSPY: err = orinoco_ioctl_setspy(dev, &wrq->u.data); @@ -4124,51 +4108,68 @@ static int orinoco_debug_dump_recs(struct net_device *dev) return 0; } -struct net_device *alloc_orinocodev(int sizeof_card, int (*hard_reset)(struct orinoco_private *)) -{ - struct net_device *dev; - struct orinoco_private *priv; - - dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card); - if (!dev) - return NULL; - priv = netdev_priv(dev); - priv->ndev = dev; - if (sizeof_card) - priv->card = (void *)((unsigned long)dev->priv + sizeof(struct orinoco_private)); - else - priv->card = NULL; - - /* Setup / override net_device fields */ - dev->init = orinoco_init; - dev->hard_start_xmit = orinoco_xmit; - dev->tx_timeout = orinoco_tx_timeout; - dev->watchdog_timeo = HZ; /* 1 second timeout */ - dev->get_stats = orinoco_get_stats; - dev->get_wireless_stats = orinoco_get_wireless_stats; - dev->do_ioctl = orinoco_ioctl; - dev->change_mtu = orinoco_change_mtu; - dev->set_multicast_list = orinoco_set_multicast_list; - /* we use the default eth_mac_addr for setting the MAC addr */ - - /* Set up default callbacks */ - dev->open = orinoco_open; - dev->stop = orinoco_stop; - priv->hard_reset = hard_reset; +/********************************************************************/ +/* Debugging */ +/********************************************************************/ - spin_lock_init(&priv->lock); - priv->open = 0; - priv->hw_unavailable = 1; /* orinoco_init() must clear this - * before anything else touches the - * hardware */ - INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); +#if 0 +static void show_rx_frame(struct orinoco_rxframe_hdr *frame) +{ + printk(KERN_DEBUG "RX descriptor:\n"); + printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); + printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); + printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); + printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); + printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); + printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); + printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); - priv->last_linkstatus = 0xffff; - priv->connected = 0; + printk(KERN_DEBUG "IEEE 802.11 header:\n"); + printk(KERN_DEBUG " frame_ctl = 0x%04x\n", + frame->p80211.frame_ctl); + printk(KERN_DEBUG " duration_id = 0x%04x\n", + frame->p80211.duration_id); + printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr1[0], frame->p80211.addr1[1], + frame->p80211.addr1[2], frame->p80211.addr1[3], + frame->p80211.addr1[4], frame->p80211.addr1[5]); + printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr2[0], frame->p80211.addr2[1], + frame->p80211.addr2[2], frame->p80211.addr2[3], + frame->p80211.addr2[4], frame->p80211.addr2[5]); + printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr3[0], frame->p80211.addr3[1], + frame->p80211.addr3[2], frame->p80211.addr3[3], + frame->p80211.addr3[4], frame->p80211.addr3[5]); + printk(KERN_DEBUG " seq_ctl = 0x%04x\n", + frame->p80211.seq_ctl); + printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p80211.addr4[0], frame->p80211.addr4[1], + frame->p80211.addr4[2], frame->p80211.addr4[3], + frame->p80211.addr4[4], frame->p80211.addr4[5]); + printk(KERN_DEBUG " data_len = 0x%04x\n", + frame->p80211.data_len); - return dev; + printk(KERN_DEBUG "IEEE 802.3 header:\n"); + printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p8023.h_dest[0], frame->p8023.h_dest[1], + frame->p8023.h_dest[2], frame->p8023.h_dest[3], + frame->p8023.h_dest[4], frame->p8023.h_dest[5]); + printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", + frame->p8023.h_source[0], frame->p8023.h_source[1], + frame->p8023.h_source[2], frame->p8023.h_source[3], + frame->p8023.h_source[4], frame->p8023.h_source[5]); + printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); + printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); + printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); + printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); + printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); + printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", + frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); + printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); } +#endif /* 0 */ /********************************************************************/ /* Module initialization */ @@ -4185,7 +4186,9 @@ EXPORT_SYMBOL(orinoco_interrupt); /* Can't be declared "const" or the whole __initdata section will * become const */ -static char version[] __initdata = "orinoco.c 0.13e (David Gibson and others)"; +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (David Gibson , " + "Pavel Roskin , et al)"; static int __init init_orinoco(void) { diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 972a8510f..c2f5f78f5 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -7,39 +7,19 @@ #ifndef _ORINOCO_H #define _ORINOCO_H +#define DRIVER_VERSION "0.13e" + #include #include #include #include #include -#include "hermes.h" - -/* Workqueue / task queue backwards compatibility stuff */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -#include -#else -#include -#define work_struct tq_struct -#define INIT_WORK INIT_TQUEUE -#define schedule_work schedule_task -#endif - -/* Interrupt handler backwards compatibility stuff */ -#ifndef IRQ_NONE - -#define IRQ_NONE -#define IRQ_HANDLED -typedef void irqreturn_t; -#endif +#include "hermes.h" /* To enable debug messages */ //#define ORINOCO_DEBUG 3 -#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) -#error "orinoco driver requires Wireless extensions v10 or later." -#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */ #define WIRELESS_SPY // enable iwspy support #define ORINOCO_MAX_KEY_SIZE 14 @@ -50,11 +30,6 @@ struct orinoco_key { char data[ORINOCO_MAX_KEY_SIZE]; } __attribute__ ((packed)); -#define ORINOCO_INTEN ( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \ - HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \ - HERMES_EV_INFDROP ) - - struct orinoco_private { void *card; /* Pointer to card dependent structure */ int (*hard_reset)(struct orinoco_private *); @@ -78,7 +53,6 @@ struct orinoco_private { hermes_t hw; u16 txfid; - /* Capabilities of the hardware/firmware */ int firmware_type; #define FIRMWARE_TYPE_AGERE 1 @@ -128,6 +102,10 @@ extern int orinoco_debug; #define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__); #define TRACE_EXIT(devname) DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__); +/********************************************************************/ +/* Exported prototypes */ +/********************************************************************/ + extern struct net_device *alloc_orinocodev(int sizeof_card, int (*hard_reset)(struct orinoco_private *)); extern int __orinoco_up(struct net_device *dev); diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 292eeffb6..4eb92ac6a 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -1,4 +1,4 @@ -/* orinoco_cs.c 0.13e - (formerly known as dldwd_cs.c) +/* orinoco_cs.c (formerly known as dldwd_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -10,6 +10,9 @@ * Copyright notice & release notes in file orinoco.c */ +#define DRIVER_NAME "orinoco_cs" +#define PFX DRIVER_NAME ": " + #include #ifdef __IN_PCMCIA_PACKAGE__ #include @@ -47,9 +50,7 @@ MODULE_AUTHOR("David Gibson "); MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual MPL/GPL"); -#endif /* Module parameters */ @@ -76,7 +77,7 @@ MODULE_PARM(ignore_cis_vcc, "i"); * device driver with appropriate cards, through the card * configuration database. */ -static dev_info_t dev_info = "orinoco_cs"; +static dev_info_t dev_info = DRIVER_NAME; /********************************************************************/ /* Data structures */ @@ -144,15 +145,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) /* PCMCIA stuff */ /********************************************************************/ -/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which - * does this, but it's not in 2.4 so we do our own for now. */ -static void -orinoco_cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); -} - /* * This creates an "instance" of the driver, allocating local data * structures for one device. The device is registered with Card @@ -174,7 +166,7 @@ orinoco_cs_attach(void) dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); if (! dev) return NULL; - priv = dev->priv; + priv = netdev_priv(dev); card = priv->card; /* Link both structures together */ @@ -216,7 +208,7 @@ orinoco_cs_attach(void) ret = pcmcia_register_client(&link->handle, &client_reg); if (ret != CS_SUCCESS) { - orinoco_cs_error(link->handle, RegisterClient, ret); + cs_error(link->handle, RegisterClient, ret); orinoco_cs_detach(link); return NULL; } @@ -230,8 +222,7 @@ orinoco_cs_attach(void) * are freed. Otherwise, the structures will be freed when the device * is released. */ -static void -orinoco_cs_detach(dev_link_t * link) +static void orinoco_cs_detach(dev_link_t *link) { dev_link_t **linkp; struct net_device *dev = link->priv; @@ -240,10 +231,8 @@ orinoco_cs_detach(dev_link_t * link) for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) if (*linkp == link) break; - if (*linkp == NULL) { - BUG(); - return; - } + + BUG_ON(*linkp == NULL); if (link->state & DEV_CONFIG) orinoco_cs_release(link); @@ -254,9 +243,9 @@ orinoco_cs_detach(dev_link_t * link) /* Unlink device structure, and free it */ *linkp = link->next; - DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev); + DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); if (link->dev) { - DEBUG(0, "orinoco_cs: About to unregister net device %p\n", + DEBUG(0, PFX "About to unregister net device %p\n", dev); unregister_netdev(dev); } @@ -269,15 +258,16 @@ orinoco_cs_detach(dev_link_t * link) * device available to the system. */ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) +#define CS_CHECK(fn, ret) do { \ + last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ + } while (0) static void orinoco_cs_config(dev_link_t *link) { struct net_device *dev = link->priv; client_handle_t handle = link->handle; - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; int last_fn, last_ret; @@ -308,7 +298,8 @@ orinoco_cs_config(dev_link_t *link) link->state |= DEV_CONFIG; /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); + CS_CHECK(GetConfigurationInfo, + pcmcia_get_configuration_info(handle, &conf)); link->conf.Vcc = conf.Vcc; /* @@ -412,8 +403,9 @@ orinoco_cs_config(dev_link_t *link) pcmcia_release_io(link->handle, &link->io); last_ret = pcmcia_get_next_tuple(handle, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { - printk(KERN_ERR "GetNextTuple(). No matching CIS configuration, " - "maybe you need the ignore_cis_vcc=1 parameter.\n"); + printk(KERN_ERR PFX "GetNextTuple(): No matching " + "CIS configuration, maybe you need the " + "ignore_cis_vcc=1 parameter.\n"); goto cs_failed; } } @@ -451,7 +443,8 @@ orinoco_cs_config(dev_link_t *link) * the I/O windows and the interrupt mapping, and putting the * card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, + pcmcia_request_configuration(link->handle, &link->conf)); /* Ok, we have the configuration, prepare to register the netdev */ dev->base_addr = link->io.BasePort1; @@ -463,7 +456,7 @@ orinoco_cs_config(dev_link_t *link) dev->name[0] = '\0'; /* Tell the stack we exist */ if (register_netdev(dev) != 0) { - printk(KERN_ERR "orinoco_cs: register_netdev() failed\n"); + printk(KERN_ERR PFX "register_netdev() failed\n"); goto failed; } @@ -495,7 +488,7 @@ orinoco_cs_config(dev_link_t *link) return; cs_failed: - orinoco_cs_error(link->handle, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); failed: orinoco_cs_release(link); @@ -510,7 +503,7 @@ static void orinoco_cs_release(dev_link_t *link) { struct net_device *dev = link->priv; - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; /* We're committed to taking the device away now, so mark the @@ -538,7 +531,7 @@ orinoco_cs_event(event_t event, int priority, { dev_link_t *link = args->client_data; struct net_device *dev = link->priv; - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; int err = 0; unsigned long flags; @@ -635,12 +628,14 @@ orinoco_cs_event(event_t event, int priority, /* Can't be declared "const" or the whole __initdata section will * become const */ -static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson and others)"; +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (David Gibson , " + "Pavel Roskin , et al)"; static struct pcmcia_driver orinoco_driver = { .owner = THIS_MODULE, .drv = { - .name = "orinoco_cs", + .name = DRIVER_NAME, }, .attach = orinoco_cs_attach, .detach = orinoco_cs_detach, @@ -660,7 +655,7 @@ exit_orinoco_cs(void) pcmcia_unregister_driver(&orinoco_driver); if (dev_list) - DEBUG(0, "orinoco_cs: Removing leftover devices.\n"); + DEBUG(0, PFX "Removing leftover devices.\n"); while (dev_list != NULL) { if (dev_list->state & DEV_CONFIG) orinoco_cs_release(dev_list); @@ -670,4 +665,3 @@ exit_orinoco_cs(void) module_init(init_orinoco_cs); module_exit(exit_orinoco_cs); - diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 23222b951..3e58b7583 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c @@ -1,19 +1,23 @@ -/* orinoco_pci.c 0.13e +/* orinoco_pci.c * * Driver for Prism II devices that have a direct PCI interface * (i.e., not in a Pcmcia or PLX bridge) * * Specifically here we're talking about the Linksys WMP11 * + * Current maintainers (as of 29 September 2003) are: + * Pavel Roskin + * and David Gibson + * * Some of this code is borrowed from orinoco_plx.c - * Copyright (C) 2001 Daniel Barlow + * Copyright (C) 2001 Daniel Barlow * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing * has been copied from it. linux-wlan-ng-0.1.10 is originally : * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. * This file originally written by: - * Copyright (C) 2001 Jean Tourrilhes + * Copyright (C) 2001 Jean Tourrilhes * And is now maintained by: - * Copyright (C) 2002 David Gibson, IBM Corporation + * (C) Copyright David Gibson, IBM Corp. 2002-2003. * * 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 @@ -85,6 +89,9 @@ * Jean II */ +#define DRIVER_NAME "orinoco_pci" +#define PFX DRIVER_NAME ": " + #include #include @@ -99,7 +106,6 @@ #include #include #include -#include #include #include #include @@ -174,7 +180,7 @@ orinoco_pci_cor_reset(struct orinoco_private *priv) } /* Did we timeout ? */ if(time_after_eq(jiffies, timeout)) { - printk(KERN_ERR "orinoco_pci: Busy timeout\n"); + printk(KERN_ERR PFX "Busy timeout\n"); return -ETIMEDOUT; } printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies); @@ -206,22 +212,21 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, if (! pci_iorange) goto fail; - /* Usual setup of structures */ + /* Allocate network device */ dev = alloc_orinocodev(0, NULL); if (! dev) { err = -ENOMEM; goto fail; } - priv = dev->priv; + priv = netdev_priv(dev); dev->base_addr = (unsigned long) pci_ioaddr; dev->mem_start = pci_iorange; dev->mem_end = pci_iorange + pci_iolen - 1; - SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - printk(KERN_DEBUG + printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PCI device at %s, mem:0x%lX to 0x%lX -> 0x%p, irq:%d\n", pci_name(pdev), dev->mem_start, dev->mem_end, pci_ioaddr, pdev->irq); @@ -232,12 +237,13 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); if (err) { - printk(KERN_ERR "orinoco_pci: Error allocating IRQ %d.\n", + printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq); err = -EBUSY; goto fail; } dev->irq = pdev->irq; + /* Perform a COR reset to start the card */ if(orinoco_pci_cor_reset(priv) != 0) { printk(KERN_ERR "%s: Failed to start the card\n", dev->name); @@ -255,7 +261,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, goto fail; } - return 0; /* succeeded */ + return 0; + fail: if (dev) { if (dev->irq) @@ -275,11 +282,11 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unregister_netdev(dev); - if (dev->irq) + if (dev->irq) free_irq(dev->irq, dev); if (priv->hw.iobase) @@ -294,7 +301,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; int err; @@ -325,7 +332,7 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state) static int orinoco_pci_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = dev->priv; + struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; int err; @@ -357,7 +364,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev) } static struct pci_device_id orinoco_pci_pci_id_table[] = { + /* Intersil Prism 3 */ {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, + /* Intersil Prism 2.5 */ {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,}, {0,}, }; @@ -365,7 +374,7 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); static struct pci_driver orinoco_pci_driver = { - .name = "orinoco_pci", + .name = DRIVER_NAME, .id_table = orinoco_pci_pci_id_table, .probe = orinoco_pci_init_one, .remove = __devexit_p(orinoco_pci_remove_one), @@ -373,8 +382,11 @@ static struct pci_driver orinoco_pci_driver = { .resume = orinoco_pci_resume, }; -static char version[] __initdata = "orinoco_pci.c 0.13e (David Gibson & Jean Tourrilhes )"; -MODULE_AUTHOR("David Gibson "); +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (Pavel Roskin ," + " David Gibson &" + " Jean Tourrilhes )"; +MODULE_AUTHOR("Pavel Roskin & David Gibson "); MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface"); MODULE_LICENSE("Dual MPL/GPL"); @@ -384,7 +396,7 @@ static int __init orinoco_pci_init(void) return pci_module_init(&orinoco_pci_driver); } -void __exit orinoco_pci_exit(void) +static void __exit orinoco_pci_exit(void) { pci_unregister_driver(&orinoco_pci_driver); } diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index b5660defd..d21ca78f0 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c @@ -1,9 +1,14 @@ -/* orinoco_plx.c 0.13e - * +/* orinoco_plx.c + * * Driver for Prism II devices which would usually be driven by orinoco_cs, - * but are connected to the PCI bus by a PLX9052. + * but are connected to the PCI bus by a PLX9052. + * + * Current maintainers (as of 29 September 2003) are: + * Pavel Roskin + * and David Gibson * - * Copyright (C) 2001 Daniel Barlow + * (C) Copyright David Gibson, IBM Corp. 2001-2003. + * Copyright (C) 2001 Daniel Barlow * * 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 @@ -33,77 +38,83 @@ * drop me mail with the id and "it works"/"it doesn't work". * * Note: if everything gets detected fine but it doesn't actually send - * or receive packets, your first port of call should probably be to + * or receive packets, your first port of call should probably be to * try newer firmware in the card. Especially if you're doing Ad-Hoc - * modes + * modes. * * The actual driving is done by orinoco.c, this is just resource * allocation stuff. The explanation below is courtesy of Ryan Niemi * on the linux-wlan-ng list at * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html + * + * The PLX9052-based cards (WL11000 and several others) are a + * different beast than the usual PCMCIA-based PRISM2 configuration + * expected by wlan-ng. Here's the general details on how the WL11000 + * PCI adapter works: + * + * - Two PCI I/O address spaces, one 0x80 long which contains the + * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA + * slot I/O address space. + * + * - One PCI memory address space, mapped to the PCMCIA memory space + * (containing the CIS). + * + * After identifying the I/O and memory space, you can read through + * the memory space to confirm the CIS's device ID or manufacturer ID + * to make sure it's the expected card. qKeep in mind that the PCMCIA + * spec specifies the CIS as the lower 8 bits of each word read from + * the CIS, so to read the bytes of the CIS, read every other byte + * (0,2,4,...). Passing that test, you need to enable the I/O address + * space on the PCMCIA card via the PCMCIA COR register. This is the + * first byte following the CIS. In my case (which may not have any + * relation to what's on the PRISM2 cards), COR was at offset 0x800 + * within the PCI memory space. Write 0x41 to the COR register to + * enable I/O mode and to select level triggered interrupts. To + * confirm you actually succeeded, read the COR register back and make + * sure it actually got set to 0x41, incase you have an unexpected + * card inserted. + * + * Following that, you can treat the second PCI I/O address space (the + * one that's not 0x80 in length) as the PCMCIA I/O space. + * + * Note that in the Eumitcom's source for their drivers, they register + * the interrupt as edge triggered when registering it with the + * Windows kernel. I don't recall how to register edge triggered on + * Linux (if it can be done at all). But in some experimentation, I + * don't see much operational difference between using either + * interrupt mode. Don't mess with the interrupt mode in the COR + * register though, as the PLX9052 wants level triggers with the way + * the serial EEPROM configures it on the WL11000. + * + * There's some other little quirks related to timing that I bumped + * into, but I don't recall right now. Also, there's two variants of + * the WL11000 I've seen, revision A1 and T2. These seem to differ + * slightly in the timings configured in the wait-state generator in + * the PLX9052. There have also been some comments from Eumitcom that + * cards shouldn't be hot swapped, apparently due to risk of cooking + * the PLX9052. I'm unsure why they believe this, as I can't see + * anything in the design that would really cause a problem, except + * for crashing drivers not written to expect it. And having developed + * drivers for the WL11000, I'd say it's quite tricky to write code + * that will successfully deal with a hot unplug. Very odd things + * happen on the I/O side of things. But anyway, be warned. Despite + * that, I've hot-swapped a number of times during debugging and + * driver development for various reasons (stuck WAIT# line after the + * radio card's firmware locks up). + * + * Hope this is enough info for someone to add PLX9052 support to the + * wlan-ng card. In the case of the WL11000, the PCI ID's are + * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based + * manufacturers other than Eumitcom (or on cards other than the + * WL11000) may have different PCI ID's. + * + * If anyone needs any more specific info, let me know. I haven't had + * time to implement support myself yet, and with the way things are + * going, might not have time for a while.. + */ -The PLX9052-based cards (WL11000 and several others) are a different -beast than the usual PCMCIA-based PRISM2 configuration expected by -wlan-ng. Here's the general details on how the WL11000 PCI adapter -works: - - - Two PCI I/O address spaces, one 0x80 long which contains the PLX9052 - registers, and one that's 0x40 long mapped to the PCMCIA slot I/O - address space. - - - One PCI memory address space, mapped to the PCMCIA memory space - (containing the CIS). - -After identifying the I/O and memory space, you can read through the -memory space to confirm the CIS's device ID or manufacturer ID to make -sure it's the expected card. Keep in mind that the PCMCIA spec specifies -the CIS as the lower 8 bits of each word read from the CIS, so to read the -bytes of the CIS, read every other byte (0,2,4,...). Passing that test, -you need to enable the I/O address space on the PCMCIA card via the PCMCIA -COR register. This is the first byte following the CIS. In my case -(which may not have any relation to what's on the PRISM2 cards), COR was -at offset 0x800 within the PCI memory space. Write 0x41 to the COR -register to enable I/O mode and to select level triggered interrupts. To -confirm you actually succeeded, read the COR register back and make sure -it actually got set to 0x41, incase you have an unexpected card inserted. - -Following that, you can treat the second PCI I/O address space (the one -that's not 0x80 in length) as the PCMCIA I/O space. - -Note that in the Eumitcom's source for their drivers, they register the -interrupt as edge triggered when registering it with the Windows kernel. I -don't recall how to register edge triggered on Linux (if it can be done at -all). But in some experimentation, I don't see much operational -difference between using either interrupt mode. Don't mess with the -interrupt mode in the COR register though, as the PLX9052 wants level -triggers with the way the serial EEPROM configures it on the WL11000. - -There's some other little quirks related to timing that I bumped into, but -I don't recall right now. Also, there's two variants of the WL11000 I've -seen, revision A1 and T2. These seem to differ slightly in the timings -configured in the wait-state generator in the PLX9052. There have also -been some comments from Eumitcom that cards shouldn't be hot swapped, -apparently due to risk of cooking the PLX9052. I'm unsure why they -believe this, as I can't see anything in the design that would really -cause a problem, except for crashing drivers not written to expect it. And -having developed drivers for the WL11000, I'd say it's quite tricky to -write code that will successfully deal with a hot unplug. Very odd things -happen on the I/O side of things. But anyway, be warned. Despite that, -I've hot-swapped a number of times during debugging and driver development -for various reasons (stuck WAIT# line after the radio card's firmware -locks up). - -Hope this is enough info for someone to add PLX9052 support to the wlan-ng -card. In the case of the WL11000, the PCI ID's are 0x1639/0x0200, with -matching subsystem ID's. Other PLX9052-based manufacturers other than -Eumitcom (or on cards other than the WL11000) may have different PCI ID's. - -If anyone needs any more specific info, let me know. I haven't had time -to implement support myself yet, and with the way things are going, might -not have time for a while.. - ----end of mail--- -*/ +#define DRIVER_NAME "orinoco_plx" +#define PFX DRIVER_NAME ": " #include @@ -122,7 +133,6 @@ not have time for a while.. #include #include #include -#include #include #include #include @@ -132,13 +142,11 @@ not have time for a while.. #include "hermes.h" #include "orinoco.h" -static char dev_info[] = "orinoco_plx"; - -#define COR_OFFSET (0x3e0 / 2) /* COR attribute offset of Prism2 PC card */ -#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ +#define COR_OFFSET (0x3e0/2) /* COR attribute offset of Prism2 PC card */ +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ -#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */ -#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ +#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ +#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ static const u16 cis_magic[] = { 0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067 @@ -215,7 +223,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, /* and 3 to the PCMCIA slot I/O address space */ pccard_ioaddr = pci_resource_start(pdev, 3); pccard_iolen = pci_resource_len(pdev, 3); - if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { + if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) { printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n", pccard_iolen, pccard_ioaddr); pccard_ioaddr = 0; @@ -223,28 +231,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, goto fail; } + /* Allocate network device */ dev = alloc_orinocodev(0, NULL); if (! dev) { err = -ENOMEM; goto fail; } - priv = dev->priv; + priv = netdev_priv(dev); dev->base_addr = pccard_ioaddr; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - printk(KERN_DEBUG - "Detected Orinoco/Prism2 PLX device at %s irq:%d, io addr:0x%lx\n", - pci_name(pdev), pdev->irq, pccard_ioaddr); + printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device " + "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, + pccard_ioaddr); - hermes_struct_init(&(priv->hw), dev->base_addr, - HERMES_IO, HERMES_16BIT_REGSPACING); + hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO, + HERMES_16BIT_REGSPACING); pci_set_drvdata(pdev, dev); - err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, + dev->name, dev); if (err) { - printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq); + printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq); err = -EBUSY; goto fail; } @@ -254,10 +264,10 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, if (err) goto fail; - return 0; /* succeeded */ + return 0; - fail: - printk(KERN_DEBUG "orinoco_plx: init_one(), FAIL!\n"); + fail: + printk(KERN_DEBUG PFX "init_one(), FAIL!\n"); if (dev) { if (dev->irq) @@ -281,8 +291,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - if (! dev) - BUG(); + BUG_ON(! dev); unregister_netdev(dev); @@ -305,33 +314,34 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = { {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W, Eumitcom PCI WL11000, - Addtron AWA-100*/ + Addtron AWA-100 */ {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */ {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */ {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */ {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */ {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by - Brendan W. McAdams */ + Brendan W. McAdams */ {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by - Damien Persohn */ + Damien Persohn */ {0,}, }; MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table); static struct pci_driver orinoco_plx_driver = { - .name = "orinoco_plx", + .name = DRIVER_NAME, .id_table = orinoco_plx_pci_id_table, .probe = orinoco_plx_init_one, .remove = __devexit_p(orinoco_plx_remove_one), }; -static char version[] __initdata = "orinoco_plx.c 0.13e (Daniel Barlow , David Gibson )"; +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (Pavel Roskin ," + " David Gibson ," + " Daniel Barlow )"; MODULE_AUTHOR("Daniel Barlow "); MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual MPL/GPL"); -#endif static int __init orinoco_plx_init(void) { @@ -339,7 +349,7 @@ static int __init orinoco_plx_init(void) return pci_module_init(&orinoco_plx_driver); } -void __exit orinoco_plx_exit(void) +static void __exit orinoco_plx_exit(void) { pci_unregister_driver(&orinoco_plx_driver); current->state = TASK_UNINTERRUPTIBLE; diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index 56ab51cf5..b619f6dea 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c @@ -1,10 +1,10 @@ -/* orinoco_tmd.c 0.01 +/* orinoco_tmd.c * * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a TMD7160. * - * Copyright (C) 2003 Joerg Dorchain - * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow + * Copyright (C) 2003 Joerg Dorchain + * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow * * 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 @@ -49,6 +49,9 @@ * Pheecom sells cards with the TMD chip as "ASIC version" */ +#define DRIVER_NAME "orinoco_tmd" +#define PFX DRIVER_NAME ": " + #include #include @@ -66,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -76,10 +78,7 @@ #include "hermes.h" #include "orinoco.h" -static char dev_info[] = "orinoco_tmd"; - -#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA | COR_FUNC_ENA) /* Enable PC card with level triggered irqs and irq requests */ - +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ static int orinoco_tmd_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -95,11 +94,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, if (err) return -EIO; - printk(KERN_DEBUG "TMD setup\n"); + printk(KERN_DEBUG PFX "TMD setup\n"); pccard_ioaddr = pci_resource_start(pdev, 2); pccard_iolen = pci_resource_len(pdev, 2); - if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { - printk(KERN_ERR "orinoco_tmd: I/O resource at 0x%lx len 0x%lx busy\n", + if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) { + printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n", pccard_ioaddr, pccard_iolen); pccard_ioaddr = 0; err = -EBUSY; @@ -110,34 +109,35 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, mdelay(1); reg = inb(addr); if (reg != COR_VALUE) { - printk(KERN_ERR "orinoco_tmd: Error setting TMD COR values %x should be %x\n", reg, COR_VALUE); + printk(KERN_ERR PFX "Error setting TMD COR values %x should be %x\n", reg, COR_VALUE); err = -EIO; goto fail; } + /* Allocate network device */ dev = alloc_orinocodev(0, NULL); if (! dev) { err = -ENOMEM; goto fail; } - priv = dev->priv; + priv = netdev_priv(dev); dev->base_addr = pccard_ioaddr; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - printk(KERN_DEBUG - "Detected Orinoco/Prism2 TMD device at %s irq:%d, io addr:0x%lx\n", - pci_name(pdev), pdev->irq, pccard_ioaddr); + printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device " + "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, + pccard_ioaddr); hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO, HERMES_16BIT_REGSPACING); pci_set_drvdata(pdev, dev); - err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, - dev); + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, + dev->name, dev); if (err) { - printk(KERN_ERR "orinoco_tmd: Error allocating IRQ %d.\n", + printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq); err = -EBUSY; goto fail; @@ -148,10 +148,10 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, if (err) goto fail; - return 0; /* succeeded */ + return 0; - fail: - printk(KERN_DEBUG "orinoco_tmd: init_one(), FAIL!\n"); + fail: + printk(KERN_DEBUG PFX "init_one(), FAIL!\n"); if (dev) { if (dev->irq) @@ -172,8 +172,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - if (! dev) - BUG(); + BUG_ON(! dev); unregister_netdev(dev); @@ -198,18 +197,17 @@ static struct pci_device_id orinoco_tmd_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); static struct pci_driver orinoco_tmd_driver = { - .name = "orinoco_tmd", + .name = DRIVER_NAME, .id_table = orinoco_tmd_pci_id_table, .probe = orinoco_tmd_init_one, .remove = __devexit_p(orinoco_tmd_remove_one), }; -static char version[] __initdata = "orinoco_tmd.c 0.01 (Joerg Dorchain )"; +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION + " (Joerg Dorchain )"; MODULE_AUTHOR("Joerg Dorchain "); MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual MPL/GPL"); -#endif static int __init orinoco_tmd_init(void) { @@ -217,7 +215,7 @@ static int __init orinoco_tmd_init(void) return pci_module_init(&orinoco_tmd_driver); } -void __exit orinoco_tmd_exit(void) +static void __exit orinoco_tmd_exit(void) { pci_unregister_driver(&orinoco_tmd_driver); current->state = TASK_UNINTERRUPTIBLE; diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 3ee31021f..92eda51bd 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -44,7 +44,7 @@ * register located at offset %ISL38XX_INT_IDENT_REG. */ void -isl38xx_disable_interrupts(void *device) +isl38xx_disable_interrupts(void __iomem *device) { isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); @@ -52,7 +52,7 @@ isl38xx_disable_interrupts(void *device) void isl38xx_handle_sleep_request(isl38xx_control_block *control_block, - int *powerstate, void *device_base) + int *powerstate, void __iomem *device_base) { /* device requests to go into sleep mode * check whether the transmit queues for data and management are empty */ @@ -88,7 +88,7 @@ isl38xx_handle_sleep_request(isl38xx_control_block *control_block, void isl38xx_handle_wakeup(isl38xx_control_block *control_block, - int *powerstate, void *device_base) + int *powerstate, void __iomem *device_base) { /* device is in active state, update the powerstate flag */ *powerstate = ISL38XX_PSM_ACTIVE_STATE; @@ -110,7 +110,7 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block, } void -isl38xx_trigger_device(int asleep, void *device_base) +isl38xx_trigger_device(int asleep, void __iomem *device_base) { struct timeval current_time; u32 reg, counter = 0; @@ -133,8 +133,8 @@ isl38xx_trigger_device(int asleep, void *device_base) readl(device_base + ISL38XX_CTRL_STAT_REG)); udelay(ISL38XX_WRITEIO_DELAY); - if (reg = readl(device_base + ISL38XX_INT_IDENT_REG), - reg == 0xabadface) { + reg = readl(device_base + ISL38XX_INT_IDENT_REG); + if (reg == 0xabadface) { #if VERBOSE > SHOW_ERROR_MESSAGES do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, @@ -190,12 +190,10 @@ isl38xx_trigger_device(int asleep, void *device_base) } void -isl38xx_interface_reset(void *device_base, dma_addr_t host_address) +isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address) { - u32 reg; - #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n"); + DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset\n"); #endif /* load the address of the control block in the device */ @@ -203,8 +201,7 @@ isl38xx_interface_reset(void *device_base, dma_addr_t host_address) udelay(ISL38XX_WRITEIO_DELAY); /* set the reset bit in the Device Interrupt Register */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, - ISL38XX_DEV_INT_REG); + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); /* enable the interrupt for detecting initialization */ @@ -212,14 +209,12 @@ isl38xx_interface_reset(void *device_base, dma_addr_t host_address) /* Note: Do not enable other interrupts here. We want the * device to have come up first 100% before allowing any other * interrupts. */ - reg = ISL38XX_INT_IDENT_INIT; - - isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); + isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */ } void -isl38xx_enable_common_interrupts(void *device_base) { +isl38xx_enable_common_interrupts(void __iomem *device_base) { u32 reg; reg = ( ISL38XX_INT_IDENT_UPDATE | ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP); diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index 0bd5ff6ad..e83e4912a 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -75,7 +75,7 @@ * from the %ISL38XX_PCI_POSTING_FLUSH offset. */ static inline void -isl38xx_w32_flush(void *base, u32 val, unsigned long offset) +isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset) { writel(val, base + offset); (void) readl(base + ISL38XX_PCI_POSTING_FLUSH); @@ -95,6 +95,10 @@ isl38xx_w32_flush(void *base, u32 val, unsigned long offset) #define ISL38XX_INT_SOURCES 0x001E /* Control/Status register bits */ +/* Looks like there are other meaningful bits + 0x20004400 seen in normal operation, + 0x200044db at 'timeout waiting for mgmt response' +*/ #define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 #define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 #define ISL38XX_CTRL_STAT_RESET 0x10000000 @@ -157,13 +161,13 @@ typedef struct isl38xx_cb isl38xx_control_block; /* determine number of entries currently in queue */ int isl38xx_in_queue(isl38xx_control_block *cb, int queue); -void isl38xx_disable_interrupts(void *); -void isl38xx_enable_common_interrupts(void *); +void isl38xx_disable_interrupts(void __iomem *); +void isl38xx_enable_common_interrupts(void __iomem *); void isl38xx_handle_sleep_request(isl38xx_control_block *, int *, - void *); -void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *); -void isl38xx_trigger_device(int, void *); -void isl38xx_interface_reset(void *, dma_addr_t); + void __iomem *); +void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void __iomem *); +void isl38xx_trigger_device(int, void __iomem *); +void isl38xx_interface_reset(void __iomem *, dma_addr_t); #endif /* _ISL_38XX_H */ diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 7924b36a7..601e40604 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -36,38 +36,6 @@ #include /* New driver API */ -static int init_mode = CARD_DEFAULT_IW_MODE; -static int init_channel = CARD_DEFAULT_CHANNEL; -static int init_wep = CARD_DEFAULT_WEP; -static int init_filter = CARD_DEFAULT_FILTER; -static int init_authen = CARD_DEFAULT_AUTHEN; -static int init_dot1x = CARD_DEFAULT_DOT1X; -static int init_conformance = CARD_DEFAULT_CONFORMANCE; -static int init_mlme = CARD_DEFAULT_MLME_MODE; - -module_param(init_mode, int, 0); -MODULE_PARM_DESC(init_mode, - "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor"); - -module_param(init_channel, int, 0); -MODULE_PARM_DESC(init_channel, - "Check `iwpriv ethx channel` for available channels"); - -module_param(init_wep, int, 0); -module_param(init_filter, int, 0); - -module_param(init_authen, int, 0); -MODULE_PARM_DESC(init_authen, - "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH"); - -module_param(init_dot1x, int, 0); -MODULE_PARM_DESC(init_dot1x, - "\n0: None/not set (Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED"); - -module_param(init_mlme, int, 0); -MODULE_PARM_DESC(init_mlme, - "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED"); - /** * prism54_mib_mode_helper - MIB change mode helper function * @mib: the &struct islpci_mib object to modify @@ -141,36 +109,34 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode) void prism54_mib_init(islpci_private *priv) { - u32 t; + u32 channel, authen, wep, filter, dot1x, mlme, conformance, power, mode; struct obj_buffer psm_buffer = { .size = PSM_BUFFER_SIZE, .addr = priv->device_psm_buffer }; - mgt_set(priv, DOT11_OID_CHANNEL, &init_channel); - mgt_set(priv, DOT11_OID_AUTHENABLE, &init_authen); - mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &init_wep); - + channel = CARD_DEFAULT_CHANNEL; + authen = CARD_DEFAULT_AUTHEN; + wep = CARD_DEFAULT_WEP; + filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */ + dot1x = CARD_DEFAULT_DOT1X; + mlme = CARD_DEFAULT_MLME_MODE; + conformance = CARD_DEFAULT_CONFORMANCE; + power = 127; + mode = CARD_DEFAULT_IW_MODE; + + mgt_set(priv, DOT11_OID_CHANNEL, &channel); + mgt_set(priv, DOT11_OID_AUTHENABLE, &authen); + mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &wep); mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer); - mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &init_filter); - mgt_set(priv, DOT11_OID_DOT1XENABLE, &init_dot1x); - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &init_mlme); - mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &init_conformance); - - t = 127; - mgt_set(priv, OID_INL_OUTPUTPOWER, &t); - - /* Important: we are setting a default wireless mode and we are - * forcing a valid one, so prism54_mib_mode_helper should just set - * mib values depending on what the wireless mode given is. No need - * for it save old values */ - if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { - printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " - "Using default mode\n", __FUNCTION__); - init_mode = CARD_DEFAULT_IW_MODE; - } + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &filter); + mgt_set(priv, DOT11_OID_DOT1XENABLE, &dot1x); + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlme); + mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &conformance); + mgt_set(priv, OID_INL_OUTPUTPOWER, &power); + /* This sets all of the mode-dependent values */ - prism54_mib_mode_helper(priv, init_mode); + prism54_mib_mode_helper(priv, mode); } /* this will be executed outside of atomic context thanks to @@ -334,9 +300,10 @@ prism54_get_freq(struct net_device *ndev, struct iw_request_info *info, int rvalue; rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r); - + fwrq->i = r.u; + rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r); fwrq->m = r.u; - fwrq->e = 0; + fwrq->e = 3; return rvalue; } @@ -373,7 +340,10 @@ prism54_set_mode(struct net_device *ndev, struct iw_request_info *info, mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); - mgt_commit(priv); + if (mgt_commit(priv)) { + up_write(&priv->mib_sem); + return -EIO; + } priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? priv->monitor_type : ARPHRD_ETHER; up_write(&priv->mib_sem); @@ -484,6 +454,15 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info, /* txpower is supported in dBm's */ range->txpower_capa = IW_TXPOW_DBM; +#if WIRELESS_EXT > 16 + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); +#endif /* WIRELESS_EXT > 16 */ + if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; @@ -628,8 +607,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = channel_of_freq(bss->channel); - iwe.u.freq.e = 0; + iwe.u.freq.m = bss->channel; + iwe.u.freq.e = 6; iwe.cmd = SIOCGIWFREQ; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -689,19 +668,33 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); noise = r.u; - /* Ask the device for a list of known bss. We can report at most - * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of IWMAX_BSS=24. - */ + /* Ask the device for a list of known bss. + * The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64. + * The new API, using SIOCGIWSCAN, is only limited by the buffer size. + * WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes. + * Starting with WE-17, the buffer can be as big as needed. + * But the device won't repport anything if you change the value + * of IWMAX_BSS=24. */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; /* ok now, scan the list and translate its info */ - for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + for (i = 0; i < (int) bsslist->nr; i++) { current_ev = prism54_translate_bss(ndev, current_ev, - extra + IW_SCAN_MAX_DATA, + extra + dwrq->length, &(bsslist->bsslist[i]), noise); +#if WIRELESS_EXT > 16 + /* Check if there is space for one more entry */ + if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { + /* Ask user space to try again with a bigger buffer */ + rvalue = -E2BIG; + break; + } +#endif /* WIRELESS_EXT > 16 */ + } + kfree(bsslist); dwrq->length = (current_ev - extra); dwrq->flags = 0; /* todo */ @@ -1411,7 +1404,10 @@ prism54_set_policy(struct net_device *ndev, struct iw_request_info *info, mlmeautolevel = DOT11_MLME_EXTENDED; mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); /* restart the card with our new policy */ - mgt_commit(priv); + if (mgt_commit(priv)) { + up_write(&priv->mib_sem); + return -EIO; + } up_write(&priv->mib_sem); return 0; @@ -1745,11 +1741,13 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, char *data) { struct obj_mlme *mlme = (struct obj_mlme *) data; - size_t len; - u8 *payload, *pos = (u8 *) (mlme + 1); - - len = pos[0] | (pos[1] << 8); /* little endian data length */ - payload = pos + 2; + struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data; + struct obj_mlmeex *confirm; + u8 wpa_ie[MAX_WPA_IE_LEN]; + int wpa_ie_len; + size_t len = 0; /* u16, better? */ + u8 *payload = 0, *pos = 0; + int ret; /* I think all trapable objects are listed here. * Some oids have a EX version. The difference is that they are emitted @@ -1759,9 +1757,14 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, * suited. We use the more flexible custom event facility. */ + if (oid >= DOT11_OID_BEACON) { + len = mlmeex->size; + payload = pos = mlmeex->data; + } + /* I fear prism54_process_bss_data won't work with big endian data */ if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) - prism54_process_bss_data(priv, oid, mlme->address, + prism54_process_bss_data(priv, oid, mlmeex->address, payload, len); mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); @@ -1821,21 +1824,134 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, case DOT11_OID_AUTHENTICATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Authenticate request", mlme, 1); + send_formatted_event(priv, "Authenticate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_AUTHING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + confirm->id = -1; /* or mlmeex->id ? */ + confirm->state = 0; /* not used */ + confirm->code = 0; + confirm->size = 6; + confirm->data[0] = 0x00; + confirm->data[1] = 0x00; + confirm->data[2] = 0x02; + confirm->data[3] = 0x00; + confirm->data[4] = 0x00; + confirm->data[5] = 0x00; + + ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6); + + kfree(confirm); + if (ret) + return ret; break; case DOT11_OID_DISASSOCIATEEX: - send_formatted_event(priv, "Disassociate request", mlme, 0); + send_formatted_event(priv, "Disassociate request (ex)", mlme, 0); break; case DOT11_OID_ASSOCIATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Associate request", mlme, 1); + send_formatted_event(priv, "Associate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_AUTHING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + + confirm->id = ((struct obj_mlmeex *)mlme)->id; + confirm->state = 0; /* not used */ + confirm->code = 0; + + wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); + + if (!wpa_ie_len) { + printk(KERN_DEBUG "No WPA IE found from " + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + kfree(confirm); + break; + } + + confirm->size = wpa_ie_len; + memcpy(&confirm->data, wpa_ie, wpa_ie_len); + + mgt_set_varlen(priv, oid, confirm, wpa_ie_len); + + kfree(confirm); + break; case DOT11_OID_REASSOCIATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Reassociate request", mlme, 1); + send_formatted_event(priv, "Reassociate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_ASSOCING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + + confirm->id = mlmeex->id; + confirm->state = 0; /* not used */ + confirm->code = 0; + + wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); + + if (!wpa_ie_len) { + printk(KERN_DEBUG "No WPA IE found from " + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + kfree(confirm); + break; + } + + confirm->size = wpa_ie_len; + memcpy(&confirm->data, wpa_ie, wpa_ie_len); + + mgt_set_varlen(priv, oid, confirm, wpa_ie_len); + + kfree(confirm); + break; default: @@ -1878,23 +1994,367 @@ prism54_set_mac_address(struct net_device *ndev, void *addr) return ret; } +/* Note: currently, use hostapd ioctl from the Host AP driver for WPA + * support. This is to be replaced with Linux wireless extensions once they + * get WPA support. */ + +/* Note II: please leave all this together as it will be easier to remove later, + * once wireless extensions add WPA support -mcgrof */ + +/* PRISM54_HOSTAPD ioctl() cmd: */ +enum { + PRISM2_SET_ENCRYPTION = 6, + PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, + PRISM2_HOSTAPD_MLME = 13, + PRISM2_HOSTAPD_SCAN_REQ = 14, +}; + +#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 +#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 +#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 + +#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 +#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ +((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) + +/* Maximum length for algorithm names (-1 for nul termination) + * used in ioctl() */ +#define HOSTAP_CRYPT_ALG_NAME_LEN 16 + +struct prism2_hostapd_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; + u32 flags; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + struct { + u8 len; + u8 data[0]; + } generic_elem; + struct { +#define MLME_STA_DEAUTH 0 +#define MLME_STA_DISASSOC 1 + u16 cmd; + u16 reason_code; + } mlme; + struct { + u8 ssid_len; + u8 ssid[32]; + } scan_req; + } u; +}; + + +static int +prism2_ioctl_set_encryption(struct net_device *dev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(dev); + int rvalue = 0, force = 0; + int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + union oid_res_t r; + + /* with the new API, it's impossible to get a NULL pointer. + * New version of iwconfig set the IW_ENCODE_NOKEY flag + * when no key is given, but older versions don't. */ + + if (param->u.crypt.key_len > 0) { + /* we have a key to set */ + int index = param->u.crypt.idx; + int current_index; + struct obj_key key = { DOT11_PRIV_TKIP, 0, "" }; + + /* get the current key index */ + rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + current_index = r.u; + /* Verify that the key is not marked as invalid */ + if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) { + key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ? + sizeof (param->u.crypt.key) : param->u.crypt.key_len; + memcpy(key.key, param->u.crypt.key, key.length); + if (key.length == 32) + /* we want WPA-PSK */ + key.type = DOT11_PRIV_TKIP; + if ((index < 0) || (index > 3)) + /* no index provided use the current one */ + index = current_index; + + /* now send the key to the card */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYX, index, + &key); + } + /* + * If a valid key is set, encryption should be enabled + * (user may turn it off later). + * This is also how "iwconfig ethX key on" works + */ + if ((index == current_index) && (key.length > 0)) + force = 1; + } else { + int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index <= 3)) { + /* we want to set the key index */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, + &index); + } else { + if (!param->u.crypt.flags & IW_ENCODE_MODE) { + /* we cannot do anything. Complain. */ + return -EINVAL; + } + } + } + /* now read the flags */ + if (param->u.crypt.flags & IW_ENCODE_DISABLED) { + /* Encoding disabled, + * authen = DOT11_AUTH_OS; + * invoke = 0; + * exunencrypt = 0; */ + } + if (param->u.crypt.flags & IW_ENCODE_OPEN) + /* Encode but accept non-encoded packets. No auth */ + invoke = 1; + if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) { + /* Refuse non-encoded packets. Auth */ + authen = DOT11_AUTH_BOTH; + invoke = 1; + exunencrypt = 1; + } + /* do the change if requested */ + if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) { + rvalue |= + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + rvalue |= + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); + rvalue |= + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, + &exunencrypt); + } + return rvalue; +} + +static int +prism2_ioctl_set_generic_element(struct net_device *ndev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(ndev); + int max_len, len, alen, ret=0; + struct obj_attachment *attach; + + len = param->u.generic_elem.len; + max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; + if (max_len < 0 || max_len < len) + return -EINVAL; + + alen = sizeof(*attach) + len; + attach = kmalloc(alen, GFP_KERNEL); + if (attach == NULL) + return -ENOMEM; + + memset(attach, 0, alen); +#define WLAN_FC_TYPE_MGMT 0 +#define WLAN_FC_STYPE_ASSOC_REQ 0 +#define WLAN_FC_STYPE_REASSOC_REQ 2 + + /* Note: endianness is covered by mgt_set_varlen */ + + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_ASSOC_REQ << 4); + attach->id = -1; + attach->size = len; + memcpy(attach->data, param->u.generic_elem.data, len); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) { + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_REASSOC_REQ << 4); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) + printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", + ndev->name); + } + + kfree(attach); + return ret; + +} + +static int +prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param) +{ + return -EOPNOTSUPP; +} + +static int +prism2_ioctl_scan_req(struct net_device *ndev, + struct prism2_hostapd_param *param) +{ + islpci_private *priv = netdev_priv(ndev); + int i, rvalue; + struct obj_bsslist *bsslist; + u32 noise = 0; + char *extra = ""; + char *current_ev = "foo"; + union oid_res_t r; + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + /* device is not ready, fail gently */ + return 0; + } + + /* first get the noise value. We will use it to report the link quality */ + rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); + noise = r.u; + + /* Ask the device for a list of known bss. We can report at most + * IW_MAX_AP=64 to the range struct. But the device won't repport anything + * if you change the value of IWMAX_BSS=24. + */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); + bsslist = r.ptr; + + /* ok now, scan the list and translate its info */ + for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + current_ev = prism54_translate_bss(ndev, current_ev, + extra + IW_SCAN_MAX_DATA, + &(bsslist->bsslist[i]), + noise); + kfree(bsslist); + + return rvalue; +} + +static int +prism54_hostapd(struct net_device *ndev, struct iw_point *p) +{ + struct prism2_hostapd_param *param; + int ret = 0; + u32 uwrq; + + printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length); + if (p->length < sizeof(struct prism2_hostapd_param) || + p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + kfree(param); + return -EFAULT; + } + + switch (param->cmd) { + case PRISM2_SET_ENCRYPTION: + printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n", + ndev->name); + ret = prism2_ioctl_set_encryption(ndev, param, p->length); + break; + case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: + printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n", + ndev->name); + ret = prism2_ioctl_set_generic_element(ndev, param, + p->length); + break; + case PRISM2_HOSTAPD_MLME: + printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n", + ndev->name); + ret = prism2_ioctl_mlme(ndev, param); + break; + case PRISM2_HOSTAPD_SCAN_REQ: + printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n", + ndev->name); + ret = prism2_ioctl_scan_req(ndev, param); + break; + case PRISM54_SET_WPA: + printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n", + ndev->name); + uwrq = 1; + ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL); + break; + case PRISM54_DROP_UNENCRYPTED: + printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n", + ndev->name); +#if 0 + uwrq = 0x01; + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); +#endif + /* Not necessary, as set_wpa does it, should we just do it here though? */ + ret = 0; + break; + default: + printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n", + ndev->name); + ret = -EOPNOTSUPP; + break; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); + + return ret; +} + int prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); + u32 mlme, authen, dot1x, filter, wep; - down_write(&priv->mib_sem); + if (islpci_get_state(priv) < PRV_STATE_INIT) + return 0; + + wep = 1; /* For privacy invoked */ + filter = 1; /* Filter out all unencrypted frames */ + dot1x = 0x01; /* To enable eap filter */ + mlme = DOT11_MLME_EXTENDED; + authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ + down_write(&priv->mib_sem); priv->wpa = *uwrq; - if (priv->wpa) { - u32 l = DOT11_MLME_EXTENDED; - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &l); + + switch (priv->wpa) { + default: + case 0: /* Clears/disables WPA and friends */ + wep = 0; + filter = 0; /* Do not filter un-encrypted data */ + dot1x = 0; + mlme = DOT11_MLME_AUTO; + printk("%s: Disabling WPA\n", ndev->name); + break; + case 2: + case 1: /* WPA */ + printk("%s: Enabling WPA\n", ndev->name); + break; } - /* restart the card with new level. Needed ? */ - mgt_commit(priv); up_write(&priv->mib_sem); + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &wep); + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &filter); + mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); + mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlme); + return 0; } @@ -1946,7 +2406,7 @@ prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response = NULL; + struct islpci_mgmtframe *response; int ret = -EIO; printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); @@ -1982,7 +2442,7 @@ prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response = NULL; + struct islpci_mgmtframe *response; int ret = 0, response_op = PIMFOR_OP_ERROR; printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, @@ -2255,14 +2715,24 @@ const struct iw_handler_def prism54_handler_def = { .standard = (iw_handler *) prism54_handler, .private = (iw_handler *) prism54_private_handler, .private_args = (struct iw_priv_args *) prism54_private_args, +#if WIRELESS_EXT == 16 .spy_offset = offsetof(islpci_private, spy_data), +#endif /* WIRELESS_EXT == 16 */ }; -/* For ioctls that don't work with the new API */ +/* For wpa_supplicant */ int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { - + struct iwreq *wrq = (struct iwreq *) rq; + int ret = -1; + switch (cmd) { + case PRISM54_HOSTAPD: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + ret = prism54_hostapd(ndev, &wrq->u.data); + return ret; + } return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index 3320338e2..f37f313e8 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -48,6 +48,8 @@ size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); int prism54_set_mac_address(struct net_device *, void *); int prism54_ioctl(struct net_device *, struct ifreq *, int); +int prism54_set_wpa(struct net_device *, struct iw_request_info *, + __u32 *, char *); extern const struct iw_handler_def prism54_handler_def; diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index c4b27d24d..419edf7cc 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -91,6 +91,14 @@ struct obj_frequencies { u16 mhz[0]; } __attribute__ ((packed)); +struct obj_attachment { + char type; + char reserved; + short id; + short size; + char data[0]; +} __attribute__((packed)); + /* * in case everything's ok, the inlined function below will be * optimized away by the compiler... @@ -472,6 +480,7 @@ enum oid_num_t { #define OID_TYPE_MLMEEX 0x09 #define OID_TYPE_ADDR 0x0A #define OID_TYPE_RAW 0x0B +#define OID_TYPE_ATTACH 0x0C /* OID_TYPE_MLMEEX is special because of a variable size field when sending. * Not yet implemented (not used in driver anyway). diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index d96d621f1..1ae168527 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -58,7 +58,7 @@ static int isl_upload_firmware(islpci_private *priv) { u32 reg, rc; - void *device_base = priv->device_base; + void __iomem *device_base = priv->device_base; /* clear the RAMBoot and the Reset bit */ reg = readl(device_base + ISL38XX_CTRL_STAT_REG); @@ -105,7 +105,7 @@ isl_upload_firmware(islpci_private *priv) "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", "prism54", priv->firmware); release_firmware(fw_entry); - return EILSEQ; /* Illegal byte sequence */; + return -EILSEQ; /* Illegal byte sequence */; } while (fw_len > 0) { @@ -113,7 +113,7 @@ isl_upload_firmware(islpci_private *priv) (fw_len > ISL38XX_MEMORY_WINDOW_SIZE) ? ISL38XX_MEMORY_WINDOW_SIZE : fw_len; - u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; + u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; /* set the cards base address for writting the data */ isl38xx_w32_flush(device_base, reg, @@ -142,6 +142,10 @@ isl_upload_firmware(islpci_private *priv) BUG_ON(fw_len != 0); + /* Firmware version is at offset 40 (also for "newmac") */ + printk(KERN_DEBUG "%s: firmware version: %.8s\n", + priv->ndev->name, fw_entry->data + 40); + release_firmware(fw_entry); } @@ -183,7 +187,7 @@ islpci_interrupt(int irq, void *config, struct pt_regs *regs) u32 reg; islpci_private *priv = config; struct net_device *ndev = priv->ndev; - void *device = priv->device_base; + void __iomem *device = priv->device_base; int powerstate = ISL38XX_PSM_POWERSAVE_STATE; /* lock the interrupt handler */ @@ -375,8 +379,6 @@ islpci_open(struct net_device *ndev) u32 rc; islpci_private *priv = netdev_priv(ndev); - printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name); - /* reset data structures, upload firmware and reset device */ rc = islpci_reset(priv,1); if (rc) { @@ -405,7 +407,7 @@ islpci_close(struct net_device *ndev) static int prism54_bring_down(islpci_private *priv) { - void *device_base = priv->device_base; + void __iomem *device_base = priv->device_base; u32 reg; /* we are going to shutdown the device */ islpci_set_state(priv, PRV_STATE_PREBOOT); @@ -462,8 +464,7 @@ islpci_upload_fw(islpci_private *priv) return rc; } - printk(KERN_DEBUG - "%s: firmware uploaded done, now triggering reset...\n", + printk(KERN_DEBUG "%s: firmware upload complete\n", priv->ndev->name); islpci_set_state(priv, PRV_STATE_POSTBOOT); @@ -489,6 +490,7 @@ islpci_reset_if(islpci_private *priv) /* The software reset acknowledge needs about 220 msec here. * Be conservative and wait for up to one second. */ + set_current_state(TASK_UNINTERRUPTIBLE); remaining = schedule_timeout(HZ); if(remaining > 0) { @@ -499,15 +501,16 @@ islpci_reset_if(islpci_private *priv) /* If we're here it's because our IRQ hasn't yet gone through. * Retry a bit more... */ - printk(KERN_ERR "%s: device soft reset timed out\n", - priv->ndev->name); - + printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n", + priv->ndev->name); } finish_wait(&priv->reset_done, &wait); - if(result) + if (result) { + printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name); return result; + } islpci_set_state(priv, PRV_STATE_INIT); @@ -519,11 +522,17 @@ islpci_reset_if(islpci_private *priv) isl38xx_enable_common_interrupts(priv->device_base); down_write(&priv->mib_sem); - mgt_commit(priv); + result = mgt_commit(priv); + if (result) { + printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name); + up_write(&priv->mib_sem); + return result; + } up_write(&priv->mib_sem); islpci_set_state(priv, PRV_STATE_READY); + printk(KERN_DEBUG "%s: interface reset complete\n", priv->ndev->name); return 0; } @@ -584,18 +593,18 @@ islpci_reset(islpci_private *priv, int reload_firmware) /* now that the data structures are cleaned up, upload * firmware and reset interface */ rc = islpci_upload_fw(priv); - if (rc) + if (rc) { + printk(KERN_ERR "%s: islpci_reset: failure\n", + priv->ndev->name); return rc; + } } /* finally reset interface */ rc = islpci_reset_if(priv); - if (!rc) /* If successful */ - return rc; - - printk(KERN_DEBUG "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); + if (rc) + printk(KERN_ERR "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); return rc; - } struct net_device_stats * @@ -604,7 +613,7 @@ islpci_statistics(struct net_device *ndev) islpci_private *priv = netdev_priv(ndev); #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics\n"); #endif return &priv->statistics; @@ -830,6 +839,12 @@ islpci_setup(struct pci_dev *pdev) priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? priv->monitor_type : ARPHRD_ETHER; +#if WIRELESS_EXT > 16 + /* Add pointers to enable iwspy support. */ + priv->wireless_data.spy_data = &priv->spy_data; + ndev->wireless_data = &priv->wireless_data; +#endif /* WIRELESS_EXT > 16 */ + /* save the start and end address of the PCI memory area */ ndev->mem_start = (unsigned long) priv->device_base; ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE; diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index e0ec5de03..d71b8bb63 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -100,16 +100,19 @@ typedef struct { struct iw_spy_data spy_data; /* iwspy support */ +#if WIRELESS_EXT > 16 + struct iw_public_data wireless_data; +#endif /* WIRELESS_EXT > 16 */ + int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ struct islpci_acl acl; /* PCI bus allocation & configuration members */ struct pci_dev *pdev; /* PCI structure information */ - u32 pci_state[16]; /* used for suspend/resume */ char firmware[33]; - void *device_base; /* ioremapped device base address */ + void __iomem *device_base; /* ioremapped device base address */ /* consistent DMA region */ void *driver_mem_address; /* base DMA address */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 9ae71e92b..5952e9960 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -508,11 +508,12 @@ islpci_eth_tx_timeout(struct net_device *ndev) /* increment the transmit error counter */ statistics->tx_errors++; + printk(KERN_WARNING "%s: tx_timeout", ndev->name); if (!priv->reset_task_pending) { priv->reset_task_pending = 1; + printk(", scheduling a reset"); netif_stop_queue(ndev); schedule_work(&priv->reset_task); } - - return; + printk("\n"); } diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 11b315ba1..75ebf8a6f 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -107,9 +107,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) islpci_private *priv; int rvalue; - /* TRACE(DRV_NAME); */ - - /* Enable the pci device */ if (pci_enable_device(pdev)) { printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME); @@ -273,7 +270,7 @@ prism54_suspend(struct pci_dev *pdev, u32 state) printk(KERN_NOTICE "%s: got suspend request (state %d)\n", ndev->name, state); - pci_save_state(pdev, priv->pci_state); + pci_save_state(pdev); /* tell the device not to trigger interrupts for now... */ isl38xx_disable_interrupts(priv->device_base); @@ -297,7 +294,7 @@ prism54_resume(struct pci_dev *pdev) printk(KERN_NOTICE "%s: got resume request\n", ndev->name); - pci_restore_state(pdev, priv->pci_state); + pci_restore_state(pdev); /* alright let's go into the PREBOOT state */ islpci_reset(priv, 1); diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 95b709c90..b887beac9 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -319,8 +319,8 @@ islpci_mgt_receive(struct net_device *ndev) } /* Ensure the results of device DMA are visible to the CPU. */ - pci_dma_sync_single(priv->pdev, buf->pci_addr, - buf->size, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(priv->pdev, buf->pci_addr, + buf->size, PCI_DMA_FROMDEVICE); /* Perform endianess conversion for PIMFOR header in-place. */ header = pimfor_decode_header(buf->mem, frag_len); @@ -473,6 +473,7 @@ islpci_mgt_transaction(struct net_device *ndev, int timeleft; struct islpci_mgmtframe *frame; + set_current_state(TASK_UNINTERRUPTIBLE); timeleft = schedule_timeout(wait_cycle_jiffies); frame = xchg(&priv->mgmt_received, NULL); if (frame) { diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h index 21303fc05..2982be336 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ b/drivers/net/wireless/prism54/islpci_mgt.h @@ -31,8 +31,6 @@ #define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0) #define DEBUG(f, args...) K_DEBUG(f, pc_debug, args) -#define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname) - extern int pc_debug; #define init_wds 0 /* help compiler optimize away dead code */ diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index 333926d32..fa60a8f60 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -201,7 +201,8 @@ struct oid_t isl_oid[] = { OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), - OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003), + [DOT11_OID_ATTACHMENT] = {0x19000003, 0, + sizeof(struct obj_attachment), OID_TYPE_ATTACH}, OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, OID_TYPE_BUFFER), @@ -329,6 +330,12 @@ mgt_le_to_cpu(int type, void *data) mlme->size = le16_to_cpu(mlme->size); break; } + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = data; + attach->id = le16_to_cpu(attach->id); + attach->size = le16_to_cpu(attach->size);; + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: @@ -392,6 +399,12 @@ mgt_cpu_to_le(int type, void *data) mlme->size = cpu_to_le16(mlme->size); break; } + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = data; + attach->id = cpu_to_le16(attach->id); + attach->size = cpu_to_le16(attach->size);; + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: @@ -465,6 +478,42 @@ mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data) return ret; } +/* None of these are cached */ +int +mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len) +{ + int ret = 0; + struct islpci_mgmtframe *response; + int response_op = PIMFOR_OP_ERROR; + int dlen; + u32 oid; + + BUG_ON(OID_NUM_LAST <= n); + + dlen = isl_oid[n].size; + oid = isl_oid[n].oid; + + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, data); + + if (islpci_get_state(priv) >= PRV_STATE_READY) { + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, + data, dlen + extra_len, &response); + if (!ret) { + response_op = response->header->operation; + islpci_mgt_release(response); + } + if (ret || response_op == PIMFOR_OP_ERROR) + ret = -EIO; + } else + ret = -EIO; + + /* re-set given data to what it was */ + if (data) + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); + + return ret; +} + int mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data, union oid_res_t *res) @@ -555,15 +604,18 @@ mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n) u32 oid = t->oid; BUG_ON(data == NULL); while (j <= t->range) { - response = NULL; - ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, + int r = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, data, t->size, &response); if (response) { - ret |= (response->header->operation == - PIMFOR_OP_ERROR); + r |= (response->header->operation == PIMFOR_OP_ERROR); islpci_mgt_release(response); } + if (r) + printk(KERN_ERR "%s: mgt_commit_list: failure. " + "oid=%08x err=%d\n", + priv->ndev->name, oid, r); + ret |= r; j++; oid++; data += t->size; @@ -624,7 +676,7 @@ static enum oid_num_t commit_part2[] = { static int mgt_update_addr(islpci_private *priv) { - struct islpci_mgmtframe *res = NULL; + struct islpci_mgmtframe *res; int ret; ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, @@ -638,26 +690,26 @@ mgt_update_addr(islpci_private *priv) if (res) islpci_mgt_release(res); + if (ret) + printk(KERN_ERR "%s: mgt_update_addr: failure\n", priv->ndev->name); return ret; } -void +#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0])) + +int mgt_commit(islpci_private *priv) { int rvalue; u32 u; if (islpci_get_state(priv) < PRV_STATE_INIT) - return; + return 0; - rvalue = mgt_commit_list(priv, commit_part1, - sizeof (commit_part1) / - sizeof (commit_part1[0])); + rvalue = mgt_commit_list(priv, commit_part1, VEC_SIZE(commit_part1)); if (priv->iw_mode != IW_MODE_MONITOR) - rvalue |= mgt_commit_list(priv, commit_part2, - sizeof (commit_part2) / - sizeof (commit_part2[0])); + rvalue |= mgt_commit_list(priv, commit_part2, VEC_SIZE(commit_part2)); u = OID_INL_MODE; rvalue |= mgt_commit_list(priv, &u, 1); @@ -666,9 +718,43 @@ mgt_commit(islpci_private *priv) if (rvalue) { /* some request have failed. The device might be in an incoherent state. We should reset it ! */ - printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " - "device \n", priv->ndev->name); + printk(KERN_DEBUG "%s: mgt_commit: failure\n", priv->ndev->name); } + return rvalue; +} + +/* The following OIDs need to be "unlatched": + * + * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL + * FREQUENCY,EXTENDEDRATES. + * + * The way to do this is to set ESSID. Note though that they may get + * unlatch before though by setting another OID. */ +void +mgt_unlatch_all(islpci_private *priv) +{ + u32 u; + int rvalue = 0; + + if (islpci_get_state(priv) < PRV_STATE_INIT) + return; + + u = DOT11_OID_SSID; + rvalue = mgt_commit_list(priv, &u, 1); + /* Necessary if in MANUAL RUN mode? */ +#if 0 + u = OID_INL_MODE; + rvalue |= mgt_commit_list(priv, &u, 1); + + u = DOT11_OID_MLMEAUTOLEVEL; + rvalue |= mgt_commit_list(priv, &u, 1); + + u = OID_INL_MODE; + rvalue |= mgt_commit_list(priv, &u, 1); +#endif + + if (rvalue) + printk(KERN_DEBUG "%s: Unlatching OIDs failed\n", priv->ndev->name); } /* This will tell you if you are allowed to answer a mlme(ex) request .*/ @@ -771,6 +857,14 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) mlme->state, mlme->code, mlme->size); } break; + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=%d\nsize=%d\n", + attach->id, + attach->size); + } + break; case OID_TYPE_SSID:{ struct obj_ssid *ssid = r->ptr; return snprintf(str, PRIV_STR_SIZE, diff --git a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h index caf5eb3d5..dc0b76af6 100644 --- a/drivers/net/wireless/prism54/oid_mgt.h +++ b/drivers/net/wireless/prism54/oid_mgt.h @@ -36,6 +36,8 @@ int channel_of_freq(int); void mgt_le_to_cpu(int, void *); int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); +int mgt_set_varlen(islpci_private *, enum oid_num_t, void *, int); + int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, union oid_res_t *); @@ -46,7 +48,8 @@ void mgt_set(islpci_private *, enum oid_num_t, void *); void mgt_get(islpci_private *, enum oid_num_t, void *); -void mgt_commit(islpci_private *); +int mgt_commit(islpci_private *); +void mgt_unlatch_all(islpci_private *); int mgt_mlme_answer(islpci_private *); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index e39bcddc3..1bb0ada59 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -54,7 +54,6 @@ #include #include -#ifdef CONFIG_NET_PCMCIA_RADIO #include #include @@ -68,7 +67,6 @@ typedef struct iw_statistics iw_stats; typedef struct iw_quality iw_qual; typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ -#endif /* CONFIG_NET_PCMCIA_RADIO */ #include "rayctl.h" #include "ray_cs.h" @@ -112,9 +110,9 @@ static int ray_open(struct net_device *dev); static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void ray_update_multi_list(struct net_device *dev, int all); -static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, +static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data, int len); -static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, +static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, unsigned char *data); static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); #if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */ @@ -140,14 +138,14 @@ static void verify_dl_startup(u_long); /* Prototypes for interrpt time functions **********************************/ static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs); static void clear_interrupt(ray_dev_t *local); -static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, +static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len); static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); -static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs); -static void release_frag_chain(ray_dev_t *local, struct rcs *prcs); -static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, +static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs); +static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs); +static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len); -static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, +static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len); static void associate(ray_dev_t *local); @@ -540,7 +538,7 @@ static void ray_config(dev_link_t *link) CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); - local->sram = (UCHAR *)(ioremap(req.Base,req.Size)); + local->sram = ioremap(req.Base,req.Size); /*** Set up 16k window for shared memory (receive buffer) ***************/ req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; @@ -550,7 +548,7 @@ static void ray_config(dev_link_t *link) CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle)); mem.CardOffset = 0x8000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); - local->rmem = (UCHAR *)(ioremap(req.Base,req.Size)); + local->rmem = ioremap(req.Base,req.Size); /*** Set up window for attribute memory ***********************************/ req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; @@ -560,7 +558,7 @@ static void ray_config(dev_link_t *link) CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle)); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); - local->amem = (UCHAR *)(ioremap(req.Base,req.Size)); + local->amem = ioremap(req.Base,req.Size); DEBUG(3,"ray_config sram=%p\n",local->sram); DEBUG(3,"ray_config rmem=%p\n",local->rmem); @@ -593,12 +591,30 @@ cs_failed: ray_release(link); } /* ray_config */ + +static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) +{ + return dev->sram + CCS_BASE; +} + +static inline struct rcs __iomem *rcs_base(ray_dev_t *dev) +{ + /* + * This looks nonsensical, since there is a separate + * RCS_BASE. But the difference between a "struct rcs" + * and a "struct ccs" ends up being in the _index_ off + * the base, so the base pointer is the same for both + * ccs/rcs. + */ + return dev->sram + CCS_BASE; +} + /*===========================================================================*/ static int ray_init(struct net_device *dev) { int i; UCHAR *p; - struct ccs *pccs; + struct ccs __iomem *pccs; ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; DEBUG(1, "ray_init(0x%p)\n", dev); @@ -632,7 +648,7 @@ static int ray_init(struct net_device *dev) local->tib_length = local->startup_res.tib_length; DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length); /* Initialize CCS's to buffer free state */ - pccs = (struct ccs *)(local->sram + CCS_BASE); + pccs = ccs_base(local); for (i=0; ibuffer_status); } @@ -661,7 +677,7 @@ static int dl_startup_params(struct net_device *dev) { int ccsindex; ray_dev_t *local = (ray_dev_t *)dev->priv; - struct ccs *pccs; + struct ccs __iomem *pccs; dev_link_t *link = local->finder; DEBUG(1,"dl_startup_params entered\n"); @@ -682,7 +698,7 @@ static int dl_startup_params(struct net_device *dev) /* Fill in the CCS fields for the ECF */ if ((ccsindex = get_free_ccs(local)) < 0) return -1; local->dl_param_ccs = ccsindex; - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs); /* Interrupt the firmware to process the command */ @@ -767,7 +783,7 @@ static void init_startup_params(ray_dev_t *local) static void verify_dl_startup(u_long data) { ray_dev_t *local = (ray_dev_t *)data; - struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs; + struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; UCHAR status; dev_link_t *link = local->finder; @@ -807,7 +823,7 @@ static void verify_dl_startup(u_long data) static void start_net(u_long data) { ray_dev_t *local = (ray_dev_t *)data; - struct ccs *pccs; + struct ccs __iomem *pccs; int ccsindex; dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { @@ -816,7 +832,7 @@ static void start_net(u_long data) } /* Fill in the CCS fields for the ECF */ if ((ccsindex = get_free_ccs(local)) < 0) return; - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; writeb(CCS_START_NETWORK, &pccs->cmd); writeb(0, &pccs->var.start_network.update_param); /* Interrupt the firmware to process the command */ @@ -834,7 +850,7 @@ static void join_net(u_long data) { ray_dev_t *local = (ray_dev_t *)data; - struct ccs *pccs; + struct ccs __iomem *pccs; int ccsindex; dev_link_t *link = local->finder; @@ -844,7 +860,7 @@ static void join_net(u_long data) } /* Fill in the CCS fields for the ECF */ if ((ccsindex = get_free_ccs(local)) < 0) return; - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; writeb(CCS_JOIN_NETWORK, &pccs->cmd); writeb(0, &pccs->var.join_network.update_param); writeb(0, &pccs->var.join_network.net_initiated); @@ -1049,10 +1065,10 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR msg_type) { ray_dev_t *local = (ray_dev_t *)dev->priv; - struct ccs *pccs; + struct ccs __iomem *pccs; int ccsindex; int offset; - struct tx_msg *ptx; /* Address of xmit buffer in PC space */ + struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ short int addr; /* Address of xmit buffer in card space */ DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev); @@ -1079,7 +1095,7 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, local->stats.tx_packets++; } - ptx = (struct tx_msg *)(local->sram + addr); + ptx = local->sram + addr; ray_build_header(local, ptx, msg_type, data); if (translate) { @@ -1092,7 +1108,7 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, } /* fill in the CCS */ - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; len += TX_HEADER_LENGTH + offset; writeb(CCS_TX_REQUEST, &pccs->cmd); writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); @@ -1119,21 +1135,21 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, return XMIT_OK; } /* end ray_hw_xmit */ /*===========================================================================*/ -static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, +static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data, int len) { unsigned short int proto = ((struct ethhdr *)data)->h_proto; if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ DEBUG(3,"ray_cs translate_frame DIX II\n"); /* Copy LLC header to card buffer */ - memcpy_toio((UCHAR *)&ptx->var, eth2_llc, sizeof(eth2_llc)); - memcpy_toio( ((UCHAR *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2); + memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); + memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2); if ((proto == 0xf380) || (proto == 0x3781)) { /* This is the selective translation table, only 2 entries */ - writeb(0xf8, (UCHAR *) &((struct snaphdr_t *)ptx->var)->org[3]); + writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]); } /* Copy body of ethernet packet without ethernet header */ - memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \ + memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \ data + ETH_HLEN, len - ETH_HLEN); return (int) sizeof(struct snaphdr_t) - ETH_HLEN; } @@ -1141,16 +1157,16 @@ static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char * DEBUG(3,"ray_cs translate_frame 802\n"); if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */ DEBUG(3,"ray_cs translate_frame evil IPX\n"); - memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN, len - ETH_HLEN); + memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); return 0 - ETH_HLEN; } - memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN, len - ETH_HLEN); + memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); return 0 - ETH_HLEN; } /* TBD do other frame types */ } /* end translate_frame */ /*===========================================================================*/ -static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, +static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type, unsigned char *data) { writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); @@ -1633,7 +1649,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev) { ray_dev_t * local = (ray_dev_t *) dev->priv; dev_link_t *link = local->finder; - struct status *p = (struct status *)(local->sram + STATUS_BASE); + struct status __iomem *p = local->sram + STATUS_BASE; if(local == (ray_dev_t *) NULL) return (iw_stats *) NULL; @@ -1755,7 +1771,7 @@ static int interrupt_ecf(ray_dev_t *local, int ccs) static int get_free_tx_ccs(ray_dev_t *local) { int i; - struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE); + struct ccs __iomem *pccs = ccs_base(local); dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { @@ -1786,7 +1802,7 @@ static int get_free_tx_ccs(ray_dev_t *local) static int get_free_ccs(ray_dev_t *local) { int i; - struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE); + struct ccs __iomem *pccs = ccs_base(local); dev_link_t *link = local->finder; if (!(link->state & DEV_PRESENT)) { @@ -1863,7 +1879,7 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev) { ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; - struct status *p = (struct status *)(local->sram + STATUS_BASE); + struct status __iomem *p = local->sram + STATUS_BASE; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs net_device_stats - device not present\n"); return &local->stats; @@ -1895,7 +1911,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i dev_link_t *link = local->finder; int ccsindex; int i; - struct ccs *pccs; + struct ccs __iomem *pccs; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_update_parm - device not present\n"); @@ -1907,7 +1923,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i DEBUG(0,"ray_update_parm - No free ccs\n"); return; } - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; writeb(CCS_UPDATE_PARAMS, &pccs->cmd); writeb(objid, &pccs->var.update_param.object_id); writeb(1, &pccs->var.update_param.number_objects); @@ -1926,11 +1942,11 @@ static void ray_update_multi_list(struct net_device *dev, int all) { struct dev_mc_list *dmi, **dmip; int ccsindex; - struct ccs *pccs; + struct ccs __iomem *pccs; int i = 0; ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; - UCHAR *p = local->sram + HOST_TO_ECF_BASE; + void __iomem *p = local->sram + HOST_TO_ECF_BASE; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_update_multi_list - device not present\n"); @@ -1943,7 +1959,7 @@ static void ray_update_multi_list(struct net_device *dev, int all) DEBUG(1,"ray_update_multi - No free ccs\n"); return; } - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); if (all) { @@ -2011,8 +2027,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) struct net_device *dev = (struct net_device *)dev_id; dev_link_t *link; ray_dev_t *local; - struct ccs *pccs; - struct rcs *prcs; + struct ccs __iomem *pccs; + struct rcs __iomem *prcs; UCHAR rcsindex; UCHAR tmp; UCHAR cmd; @@ -2029,7 +2045,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); return IRQ_NONE; } - rcsindex = readb(&((struct scb *)(local->sram))->rcs_index); + rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { @@ -2039,7 +2055,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) } if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */ { - pccs = ((struct ccs *) (local->sram + CCS_BASE)) + rcsindex; + pccs = ccs_base(local) + rcsindex; cmd = readb(&pccs->cmd); status = readb(&pccs->buffer_status); switch (cmd) @@ -2153,7 +2169,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) } else /* It's an RCS */ { - prcs = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex; + prcs = rcs_base(local) + rcsindex; switch (readb(&prcs->interrupt_id)) { @@ -2194,11 +2210,11 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) return IRQ_HANDLED; } /* ray_interrupt */ /*===========================================================================*/ -static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) +static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs) { int rx_len; unsigned int pkt_addr; - UCHAR *pmsg; + void __iomem *pmsg; DEBUG(4,"ray_rx process rx packet\n"); /* Calculate address of packet within Rx buffer */ @@ -2248,11 +2264,11 @@ static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) } /* end ray_rx */ /*===========================================================================*/ -static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, +static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len) { struct sk_buff *skb = NULL; - struct rcs *prcslink = prcs; + struct rcs __iomem *prcslink = prcs; ray_dev_t *local = dev->priv; UCHAR *rx_ptr; int total_len; @@ -2294,7 +2310,7 @@ static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_a + readb(&prcslink->var.rx_packet.rx_data_length[1]); if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF || tmp < 0) break; - prcslink = ((struct rcs *)(local->sram + CCS_BASE)) + prcslink = rcs_base(local) + readb(&prcslink->link_field); } while (1); @@ -2355,7 +2371,7 @@ static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_a prcslink = prcs; DEBUG(1,"ray_cs rx_data in fragment loop\n"); do { - prcslink = ((struct rcs *)(local->sram + CCS_BASE)) + prcslink = rcs_base(local) + readb(&prcslink->var.rx_packet.next_frag_rcs_index); rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8) + readb(&prcslink->var.rx_packet.rx_data_length[1])) @@ -2529,9 +2545,9 @@ static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int le return length; } /*===========================================================================*/ -static void release_frag_chain(ray_dev_t *local, struct rcs* prcs) +static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs) { - struct rcs *prcslink = prcs; + struct rcs __iomem *prcslink = prcs; int tmp = 17; unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); @@ -2541,7 +2557,7 @@ static void release_frag_chain(ray_dev_t *local, struct rcs* prcs) DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); break; } - prcslink = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex; + prcslink = rcs_base(local) + rcsindex; rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); } writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); @@ -2569,7 +2585,7 @@ static void authenticate(ray_dev_t *local) local->authentication_state = AWAITING_RESPONSE; } /* end authenticate */ /*===========================================================================*/ -static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, +static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len) { UCHAR buff[256]; @@ -2614,7 +2630,7 @@ static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, /*===========================================================================*/ static void associate(ray_dev_t *local) { - struct ccs *pccs; + struct ccs __iomem *pccs; dev_link_t *link = local->finder; struct net_device *dev = link->priv; int ccsindex; @@ -2630,7 +2646,7 @@ static void associate(ray_dev_t *local) return; } DEBUG(1,"ray_cs Starting association with access point\n"); - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; /* fill in the CCS */ writeb(CCS_START_ASSOCIATION, &pccs->cmd); /* Interrupt the firmware to process the command */ @@ -2650,7 +2666,7 @@ static void associate(ray_dev_t *local) } /* end associate */ /*===========================================================================*/ -static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, +static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, unsigned int pkt_addr, int rx_len) { /* UCHAR buff[256]; @@ -2798,8 +2814,8 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) { int addr; - struct ccs *pccs; - struct tx_msg *ptx; + struct ccs __iomem *pccs; + struct tx_msg __iomem *ptx; int ccsindex; /* If no tx buffers available, return */ @@ -2809,7 +2825,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) return -1; } - pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex; + pccs = ccs_base(local) + ccsindex; /* Address in card space */ addr = TX_BUF_BASE + (ccsindex << 11); @@ -2821,7 +2837,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1); writeb(0, &pccs->var.tx_request.pow_sav_mode); - ptx = (struct tx_msg *)(local->sram + addr); + ptx = local->sram + addr; /* fill in the mac header */ writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); writeb(0, &ptx->mac.frame_ctl_2); @@ -2931,15 +2947,6 @@ static void __exit exit_ray_cs(void) { DEBUG(0, "ray_cs: cleanup_module\n"); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("ray_cs", proc_root_driver); -#endif - - pcmcia_unregister_driver(&ray_driver); - while (dev_list != NULL) - ray_detach(dev_list); - #ifdef CONFIG_PROC_FS remove_proc_entry("driver/ray_cs/ray_cs", NULL); remove_proc_entry("driver/ray_cs/essid", NULL); @@ -2947,6 +2954,10 @@ static void __exit exit_ray_cs(void) remove_proc_entry("driver/ray_cs/translate", NULL); remove_proc_entry("driver/ray_cs", NULL); #endif + + pcmcia_unregister_driver(&ray_driver); + while (dev_list != NULL) + ray_detach(dev_list); } /* exit_ray_cs */ module_init(init_ray_cs); diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h index 6d4985061..c77afa14f 100644 --- a/drivers/net/wireless/ray_cs.h +++ b/drivers/net/wireless/ray_cs.h @@ -28,9 +28,9 @@ typedef struct ray_dev_t { dev_node_t node; window_handle_t amem_handle; /* handle to window for attribute memory */ window_handle_t rmem_handle; /* handle to window for rx buffer on card */ - UCHAR *sram; /* pointer to beginning of shared RAM */ - UCHAR *amem; /* pointer to attribute mem window */ - UCHAR *rmem; /* pointer to receive buffer window */ + void __iomem *sram; /* pointer to beginning of shared RAM */ + void __iomem *amem; /* pointer to attribute mem window */ + void __iomem *rmem; /* pointer to receive buffer window */ dev_link_t *finder; /* pointer back to dev_link_t for card */ struct timer_list timer; long tx_ccs_lock; diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 98cee21f7..b9cb7be40 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -85,9 +85,9 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include #include #include +#include #include #include -#include # include #include @@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; #include #include #include +#include #include #include @@ -1249,7 +1250,7 @@ static void ResetRadio(struct strip *strip_info) set_baud(tty, strip_info->user_baud); } - tty->driver->write(tty, 0, s.string, s.length); + tty->driver->write(tty, s.string, s.length); #ifdef EXT_COUNTERS strip_info->tx_ebytes += s.length; #endif @@ -1271,7 +1272,7 @@ static void strip_write_some_more(struct tty_struct *tty) if (strip_info->tx_left > 0) { int num_written = - tty->driver->write(tty, 0, strip_info->tx_head, + tty->driver->write(tty, strip_info->tx_head, strip_info->tx_left); strip_info->tx_left -= num_written; strip_info->tx_head += num_written; @@ -1348,14 +1349,17 @@ static unsigned char *strip_make_packet(unsigned char *buffer, */ if (haddr.c[0] == 0xFF) { u32 brd = 0; - struct in_device *in_dev = in_dev_get(strip_info->dev); - if (in_dev == NULL) + struct in_device *in_dev; + + rcu_read_lock(); + in_dev = __in_dev_get(strip_info->dev); + if (in_dev == NULL) { + rcu_read_unlock(); return NULL; - read_lock(&in_dev->lock); + } if (in_dev->ifa_list) brd = in_dev->ifa_list->ifa_broadcast; - read_unlock(&in_dev->lock); - in_dev_put(in_dev); + rcu_read_unlock(); /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ if (!arp_query(haddr.c, brd, strip_info->dev)) { @@ -1500,17 +1504,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb) } if (1) { - struct in_device *in_dev = in_dev_get(strip_info->dev); + struct in_device *in_dev; + brd = addr = 0; + rcu_read_lock(); + in_dev = __in_dev_get(strip_info->dev); if (in_dev) { - read_lock(&in_dev->lock); if (in_dev->ifa_list) { brd = in_dev->ifa_list->ifa_broadcast; addr = in_dev->ifa_list->ifa_local; } - read_unlock(&in_dev->lock); - in_dev_put(in_dev); } + rcu_read_unlock(); } @@ -2661,8 +2666,6 @@ static int strip_open(struct tty_struct *tty) tty->disc_data = strip_info; if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); /* * Restore default settings diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index 1cbd34ba5..2562c1deb 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -2172,6 +2172,11 @@ static int wavelan_get_range(struct net_device *dev, range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | + IW_EVENT_CAPA_MASK(0x8B04)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2403,11 +2408,10 @@ static const struct iw_handler_def wavelan_handler_def = .num_standard = sizeof(wavelan_handler)/sizeof(iw_handler), .num_private = sizeof(wavelan_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) wavelan_handler, - .private = (iw_handler *) wavelan_private_handler, - .private_args = (struct iw_priv_args *) wavelan_private_args, - .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - - (void *) NULL), + .standard = wavelan_handler, + .private = wavelan_private_handler, + .private_args = wavelan_private_args, + .get_wireless_stats = wavelan_get_wireless_stats, }; /*------------------------------------------------------------------*/ @@ -3822,17 +3826,18 @@ static irqreturn_t wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs if ((hasr & HASR_MMC_INTR) && (lp->hacr & HACR_MMC_INT_ENABLE)) { u8 dce_status; -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", - dev->name, dce_status); -#endif /* * Interrupt from the modem management controller. * This will clear it -- ignored for now. */ mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status)); + +#ifdef DEBUG_INTERRUPT_ERROR + printk(KERN_INFO + "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", + dev->name, dce_status); +#endif } /* Check if not controller interrupt */ @@ -4190,8 +4195,9 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr) #endif /* SET_MAC_ADDRESS */ #ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ - dev->get_wireless_stats = wavelan_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; + dev->wireless_handlers = &wavelan_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; #endif dev->mtu = WAVELAN_MTU; diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h index d35ac4dd2..475add67f 100644 --- a/drivers/net/wireless/wavelan.p.h +++ b/drivers/net/wireless/wavelan.p.h @@ -377,8 +377,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -510,6 +510,7 @@ struct net_local iw_stats wstats; /* Wireless-specific statistics */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif #ifdef HISTOGRAM @@ -614,6 +615,8 @@ static inline void /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ static en_stats * wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ +static iw_stats * + wavelan_get_wireless_stats(struct net_device *); static void wavelan_set_multicast_list(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 5eb32a9ca..0579717b9 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -502,7 +502,7 @@ unsigned char WAVELAN_BEACON_ADDRESS[]= {0x09,0x00,0x0e,0x20,0x03,0x00}; void wv_roam_init(struct net_device *dev) { - net_local *lp= (net_local *)dev->priv; + net_local *lp= netdev_priv(dev); /* Do not remove this unless you have a good reason */ printk(KERN_NOTICE "%s: Warning, you have enabled roaming on" @@ -532,7 +532,7 @@ void wv_roam_init(struct net_device *dev) void wv_roam_cleanup(struct net_device *dev) { wavepoint_history *ptr,*old_ptr; - net_local *lp= (net_local *)dev->priv; + net_local *lp= netdev_priv(dev); printk(KERN_DEBUG "WaveLAN: Roaming Disabled on device %s\n",dev->name); @@ -762,7 +762,7 @@ static inline void wl_roam_gather(struct net_device * dev, unsigned short nwid=ntohs(beacon->nwid); unsigned short sigqual=stats[2] & MMR_SGNL_QUAL; /* SNR of beacon */ wavepoint_history *wavepoint=NULL; /* WavePoint table entry */ - net_local *lp=(net_local *)dev->priv; /* Device info */ + net_local *lp = netdev_priv(dev); /* Device info */ #ifdef I_NEED_THIS_FEATURE /* Some people don't need this, some other may need it */ @@ -1006,7 +1006,7 @@ read_ringbuf(struct net_device * dev, static inline void wv_82593_reconfig(struct net_device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); dev_link_t * link = lp->link; unsigned long flags; @@ -1135,7 +1135,7 @@ static void wv_mmc_show(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); mmr_t m; /* Basic check */ @@ -1224,7 +1224,7 @@ wv_mmc_show(struct net_device * dev) static void wv_ru_show(struct net_device * dev) { - net_local *lp = (net_local *) dev->priv; + net_local *lp = netdev_priv(dev); printk(KERN_DEBUG "##### wavelan i82593 receiver status: #####\n"); printk(KERN_DEBUG "ru: rfp %d stop %d", lp->rfp, lp->stop); @@ -1258,9 +1258,7 @@ wv_dev_show(struct net_device * dev) static void wv_local_show(struct net_device * dev) { - net_local *lp; - - lp = (net_local *)dev->priv; + net_local *lp = netdev_priv(dev); printk(KERN_DEBUG "local:"); /* @@ -1418,7 +1416,7 @@ wavelan_get_stats(struct net_device * dev) printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); #endif - return(&((net_local *) dev->priv)->stats); + return(&((net_local *)netdev_priv(dev))->stats); } /*------------------------------------------------------------------*/ @@ -1433,7 +1431,7 @@ wavelan_get_stats(struct net_device * dev) static void wavelan_set_multicast_list(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name); @@ -1550,7 +1548,6 @@ wavelan_set_mac_address(struct net_device * dev, /* * Frequency setting (for hardware able of it) * It's a bit complicated and you don't really want to look into it... - * (called in wavelan_ioctl) */ static inline int wv_set_frequency(u_long base, /* i/o port of the card */ @@ -1826,7 +1823,7 @@ static inline void wl_his_gather(struct net_device * dev, u_char * stats) /* Statistics to gather */ { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); u_char level = stats[0] & MMR_SIGNAL_LVL; int i; @@ -1840,28 +1837,15 @@ wl_his_gather(struct net_device * dev, } #endif /* HISTOGRAM */ -static inline int -wl_netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - - strncpy(info.driver, "wavelan_cs", sizeof(info.driver)-1); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; + strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1); } +static struct ethtool_ops ops = { + .get_drvinfo = wl_get_drvinfo +}; + /*------------------------------------------------------------------*/ /* * Wireless Handler : get protocol name @@ -1885,7 +1869,7 @@ static int wavelan_set_nwid(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; mm_t m; unsigned long flags; @@ -1943,7 +1927,7 @@ static int wavelan_get_nwid(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -1975,7 +1959,7 @@ static int wavelan_set_freq(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret; @@ -2005,7 +1989,7 @@ static int wavelan_get_freq(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2051,7 +2035,7 @@ static int wavelan_set_sens(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2086,7 +2070,7 @@ static int wavelan_get_sens(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2117,7 +2101,7 @@ static int wavelan_set_encode(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; psa_t psa; int ret = 0; @@ -2187,7 +2171,7 @@ static int wavelan_get_encode(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2234,7 +2218,7 @@ static int wavelan_set_essid(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret = 0; @@ -2282,7 +2266,7 @@ static int wavelan_get_essid(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Is the domain ID active ? */ wrqu->data.flags = lp->filter_domains; @@ -2347,7 +2331,7 @@ static int wavelan_set_mode(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret = 0; @@ -2406,7 +2390,7 @@ static int wavelan_get_range(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); struct iw_range *range = (struct iw_range *) extra; unsigned long flags; int ret = 0; @@ -2438,6 +2422,12 @@ static int wavelan_get_range(struct net_device *dev, range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | + IW_EVENT_CAPA_MASK(0x8B04) | + IW_EVENT_CAPA_MASK(0x8B06)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2476,7 +2466,7 @@ static int wavelan_set_qthr(struct net_device *dev, char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; @@ -2507,7 +2497,7 @@ static int wavelan_get_qthr(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; @@ -2535,7 +2525,7 @@ static int wavelan_set_roam(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; /* Disable interrupts and save flags. */ @@ -2580,7 +2570,7 @@ static int wavelan_set_histo(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Check the number of intervals. */ if (wrqu->data.length > 16) { @@ -2623,7 +2613,7 @@ static int wavelan_get_histo(struct net_device *dev, union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Set the number of intervals. */ wrqu->data.length = lp->his_number; @@ -2737,48 +2727,12 @@ static const struct iw_handler_def wavelan_handler_def = .num_standard = sizeof(wavelan_handler)/sizeof(iw_handler), .num_private = sizeof(wavelan_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) wavelan_handler, - .private = (iw_handler *) wavelan_private_handler, - .private_args = (struct iw_priv_args *) wavelan_private_args, - .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - - (void *) NULL), + .standard = wavelan_handler, + .private = wavelan_private_handler, + .private_args = wavelan_private_args, + .get_wireless_stats = wavelan_get_wireless_stats, }; -/*------------------------------------------------------------------*/ -/* - * Perform ioctl : config & info stuff - * This is here that are treated the wireless extensions (iwconfig) - */ -static int -wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */ - struct ifreq * rq, /* Data passed */ - int cmd) /* Ioctl number */ -{ - int ret = 0; - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd); -#endif - - /* Look what is the request */ - switch(cmd) - { - case SIOCETHTOOL: - ret = wl_netdev_ethtool_ioctl(dev, rq->ifr_data); - break; - - /* ------------------- OTHER IOCTL ------------------- */ - - default: - ret = -EOPNOTSUPP; - } - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); -#endif - return ret; -} - /*------------------------------------------------------------------*/ /* * Get wireless statistics @@ -2788,7 +2742,7 @@ static iw_stats * wavelan_get_wireless_stats(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); mmr_t m; iw_stats * wstats; unsigned long flags; @@ -2913,7 +2867,7 @@ wv_packet_read(struct net_device * dev, int fd_p, int sksize) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); struct sk_buff * skb; #ifdef DEBUG_RX_TRACE @@ -3015,7 +2969,7 @@ static inline void wv_packet_rcv(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); int newrfp; int rp; int len; @@ -3150,7 +3104,7 @@ wv_packet_write(struct net_device * dev, void * buf, short length) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int clen = length; @@ -3211,7 +3165,7 @@ static int wavelan_packet_xmit(struct sk_buff * skb, struct net_device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; #ifdef DEBUG_TX_TRACE @@ -3470,7 +3424,7 @@ static int wv_ru_stop(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; int status; int spin; @@ -3533,7 +3487,7 @@ static int wv_ru_start(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; #ifdef DEBUG_CONFIG_TRACE @@ -3621,7 +3575,7 @@ static int wv_82593_config(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); struct i82593_conf_block cfblk; int ret = TRUE; @@ -3796,7 +3750,7 @@ wv_pcmcia_reset(struct net_device * dev) { int i; conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; - dev_link_t * link = ((net_local *) dev->priv)->link; + dev_link_t * link = ((net_local *)netdev_priv(dev))->link; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); @@ -3856,7 +3810,7 @@ wv_pcmcia_reset(struct net_device * dev) static int wv_hw_config(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int ret = FALSE; @@ -3963,7 +3917,7 @@ wv_hw_config(struct net_device * dev) static inline void wv_hw_reset(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name); @@ -4131,8 +4085,8 @@ wv_pcmcia_config(dev_link_t * link) return FALSE; } - strcpy(((net_local *) dev->priv)->node.dev_name, dev->name); - link->dev = &((net_local *) dev->priv)->node; + strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); + link->dev = &((net_local *) netdev_priv(dev))->node; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); @@ -4203,7 +4157,7 @@ wavelan_interrupt(int irq, printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); #endif - lp = (net_local *) dev->priv; + lp = netdev_priv(dev); base = dev->base_addr; #ifdef DEBUG_INTERRUPT_INFO @@ -4453,7 +4407,7 @@ wavelan_interrupt(int irq, static void wavelan_watchdog(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int aborted = FALSE; @@ -4528,8 +4482,8 @@ wavelan_watchdog(struct net_device * dev) static int wavelan_open(struct net_device * dev) { - dev_link_t * link = ((net_local *) dev->priv)->link; - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); + dev_link_t * link = lp->link; ioaddr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4583,7 +4537,7 @@ wavelan_open(struct net_device * dev) static int wavelan_close(struct net_device * dev) { - dev_link_t * link = ((net_local *) dev->priv)->link; + dev_link_t * link = ((net_local *)netdev_priv(dev))->link; ioaddr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4686,7 +4640,7 @@ wavelan_attach(void) } link->priv = link->irq.Instance = dev; - lp = dev->priv; + lp = netdev_priv(dev); /* Init specific data */ lp->configured = 0; @@ -4718,11 +4672,12 @@ wavelan_attach(void) /* Set the watchdog timer */ dev->tx_timeout = &wavelan_watchdog; dev->watchdog_timeo = WATCHDOG_JIFFIES; + SET_ETHTOOL_OPS(dev, &ops); #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ - dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; - dev->do_ioctl = wavelan_ioctl; /* old wireless extensions */ - dev->get_wireless_stats = wavelan_get_wireless_stats; + dev->wireless_handlers = &wavelan_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; #endif /* Other specific data */ @@ -4820,8 +4775,8 @@ wavelan_detach(dev_link_t * link) if (link->dev) unregister_netdev(dev); link->dev = NULL; - ((net_local *) dev->priv)->link = NULL; - ((net_local *) dev->priv)->dev = NULL; + ((net_local *)netdev_priv(dev))->link = NULL; + ((net_local *)netdev_priv(dev))->dev = NULL; free_netdev(dev); } kfree(link); diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index f7dfc2f3a..0c18af262 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -428,10 +428,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -629,6 +629,7 @@ struct net_local iw_stats wstats; /* Wireless specific stats */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif #ifdef HISTOGRAM @@ -725,6 +726,8 @@ static inline void /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ static en_stats * wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ +static iw_stats * + wavelan_get_wireless_stats(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ static inline int wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 4e62fa630..ffd8d7da2 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1487,55 +1487,14 @@ struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) return wstats; } -static inline int wl3501_ethtool_ioctl(struct net_device *dev, void __user *uaddr) +static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - int rc = -EFAULT; - - if (copy_from_user(ðcmd, uaddr, sizeof(ethcmd))) - goto out; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO, }; - - strlcpy(info.driver, wl3501_dev_info, sizeof(info.driver)); - rc = copy_to_user(uaddr, &info, sizeof(info)) ? -EFAULT : 1; - } - default: - rc = -EOPNOTSUPP; - break; - } -out: - return rc; + strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); } -/** - * wl3501_ioctl - Perform IOCTL call functions - * @dev - network device - * @ifreq - request - * @cmd - command - * - * Perform IOCTL call functions here. Some are privileged operations and the - * effective uid is checked in those cases. - * - * This part is optional. Needed only if you want to run wlu (unix version). - * - * CAUTION: To prevent interrupted by wl3501_interrupt() and timer-based - * wl3501_hard_start_xmit() from other interrupts, this should be run - * single-threaded. - */ -static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int rc = -ENODEV; - - if (netif_device_present(dev)) { - rc = -EOPNOTSUPP; - if (cmd == SIOCETHTOOL) - rc = wl3501_ethtool_ioctl(dev, rq->ifr_data); - } - return rc; -} +static struct ethtool_ops ops = { + .get_drvinfo = wl3501_get_drvinfo +}; /** * wl3501_detach - deletes a driver "instance" @@ -2047,8 +2006,8 @@ static dev_link_t *wl3501_attach(void) dev->watchdog_timeo = 5 * HZ; dev->get_stats = wl3501_get_stats; dev->get_wireless_stats = wl3501_get_wireless_stats; - dev->do_ioctl = wl3501_ioctl; dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; + SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); link->priv = link->irq.Instance = dev; diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 814821902..9c2d0752a 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -124,10 +124,10 @@ static int gx_fix; #include #include #include +#include #include #include /* Processor type for cache alignment. */ #include -#include #include /* These identify the driver base version and may not be removed. */ @@ -136,20 +136,6 @@ KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker "); MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver"); MODULE_LICENSE("GPL"); @@ -389,11 +375,12 @@ struct yellowfin_private { u16 advertising; /* NWay media advertisement */ unsigned char phys[MII_CNT]; /* MII device addresses, only first one used */ spinlock_t lock; + void __iomem *base; }; -static int read_eeprom(long ioaddr, int location); -static int mdio_read(long ioaddr, int phy_id, int location); -static void mdio_write(long ioaddr, int phy_id, int location, int value); +static int read_eeprom(void __iomem *ioaddr, int location); +static int mdio_read(void __iomem *ioaddr, int phy_id, int location); +static void mdio_write(void __iomem *ioaddr, int phy_id, int location, int value); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int yellowfin_open(struct net_device *dev); static void yellowfin_timer(unsigned long data); @@ -406,6 +393,7 @@ static void yellowfin_error(struct net_device *dev, int intr_status); static int yellowfin_close(struct net_device *dev); static struct net_device_stats *yellowfin_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +static struct ethtool_ops ethtool_ops; static int __devinit yellowfin_init_one(struct pci_dev *pdev, @@ -416,11 +404,16 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, int irq; int chip_idx = ent->driver_data; static int find_cnt; - long ioaddr, real_ioaddr; + void __iomem *ioaddr; int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0; int drv_flags = pci_id_tbl[chip_idx].drv_flags; void *ring_space; dma_addr_t ring_dma; +#ifdef USE_IO_OPS + int bar = 0; +#else + int bar = 1; +#endif /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -440,26 +433,22 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - np = dev->priv; + np = netdev_priv(dev); if (pci_request_regions(pdev, DRV_NAME)) goto err_out_free_netdev; pci_set_master (pdev); -#ifdef USE_IO_OPS - real_ioaddr = ioaddr = pci_resource_start (pdev, 0); -#else - real_ioaddr = ioaddr = pci_resource_start (pdev, 1); - ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE); + ioaddr = pci_iomap(pdev, bar, YELLOWFIN_SIZE); if (!ioaddr) goto err_out_free_res; -#endif + irq = pdev->irq; if (drv_flags & DontUseEeprom) for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(ioaddr + StnAddr + i); + dev->dev_addr[i] = ioread8(ioaddr + StnAddr + i); else { int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0); for (i = 0; i < 6; i++) @@ -467,9 +456,9 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, } /* Reset the chip. */ - outl(0x80000000, ioaddr + DMACtrl); + iowrite32(0x80000000, ioaddr + DMACtrl); - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; dev->irq = irq; pci_set_drvdata(pdev, dev); @@ -478,6 +467,7 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, np->pci_dev = pdev; np->chip_id = chip_idx; np->drv_flags = drv_flags; + np->base = ioaddr; ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma); if (!ring_space) @@ -521,6 +511,7 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, dev->get_stats = &yellowfin_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = yellowfin_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -531,8 +522,9 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, if (i) goto err_out_unmap_status; - printk(KERN_INFO "%s: %s type %8x at 0x%lx, ", - dev->name, pci_id_tbl[chip_idx].name, inl(ioaddr + ChipRev), ioaddr); + printk(KERN_INFO "%s: %s type %8x at %p, ", + dev->name, pci_id_tbl[chip_idx].name, + ioread32(ioaddr + ChipRev), ioaddr); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); @@ -565,53 +557,51 @@ err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); err_out_cleardev: pci_set_drvdata(pdev, NULL); -#ifndef USE_IO_OPS - iounmap((void *)ioaddr); + pci_iounmap(pdev, ioaddr); err_out_free_res: -#endif pci_release_regions(pdev); err_out_free_netdev: free_netdev (dev); return -ENODEV; } -static int __devinit read_eeprom(long ioaddr, int location) +static int __devinit read_eeprom(void __iomem *ioaddr, int location) { int bogus_cnt = 10000; /* Typical 33Mhz: 1050 ticks */ - outb(location, ioaddr + EEAddr); - outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl); - while ((inb(ioaddr + EEStatus) & 0x80) && --bogus_cnt > 0) + iowrite8(location, ioaddr + EEAddr); + iowrite8(0x30 | ((location >> 8) & 7), ioaddr + EECtrl); + while ((ioread8(ioaddr + EEStatus) & 0x80) && --bogus_cnt > 0) ; - return inb(ioaddr + EERead); + return ioread8(ioaddr + EERead); } /* MII Managemen Data I/O accesses. These routines assume the MDIO controller is idle, and do not exit until the command is finished. */ -static int mdio_read(long ioaddr, int phy_id, int location) +static int mdio_read(void __iomem *ioaddr, int phy_id, int location) { int i; - outw((phy_id<<8) + location, ioaddr + MII_Addr); - outw(1, ioaddr + MII_Cmd); + iowrite16((phy_id<<8) + location, ioaddr + MII_Addr); + iowrite16(1, ioaddr + MII_Cmd); for (i = 10000; i >= 0; i--) - if ((inw(ioaddr + MII_Status) & 1) == 0) + if ((ioread16(ioaddr + MII_Status) & 1) == 0) break; - return inw(ioaddr + MII_Rd_Data); + return ioread16(ioaddr + MII_Rd_Data); } -static void mdio_write(long ioaddr, int phy_id, int location, int value) +static void mdio_write(void __iomem *ioaddr, int phy_id, int location, int value) { int i; - outw((phy_id<<8) + location, ioaddr + MII_Addr); - outw(value, ioaddr + MII_Wr_Data); + iowrite16((phy_id<<8) + location, ioaddr + MII_Addr); + iowrite16(value, ioaddr + MII_Wr_Data); /* Wait for the command to finish. */ for (i = 10000; i >= 0; i--) - if ((inw(ioaddr + MII_Status) & 1) == 0) + if ((ioread16(ioaddr + MII_Status) & 1) == 0) break; return; } @@ -619,12 +609,12 @@ static void mdio_write(long ioaddr, int phy_id, int location, int value) static int yellowfin_open(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; - long ioaddr = dev->base_addr; + struct yellowfin_private *yp = netdev_priv(dev); + void __iomem *ioaddr = yp->base; int i; /* Reset the chip. */ - outl(0x80000000, ioaddr + DMACtrl); + iowrite32(0x80000000, ioaddr + DMACtrl); i = request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev); if (i) return i; @@ -635,30 +625,30 @@ static int yellowfin_open(struct net_device *dev) yellowfin_init_ring(dev); - outl(yp->rx_ring_dma, ioaddr + RxPtr); - outl(yp->tx_ring_dma, ioaddr + TxPtr); + iowrite32(yp->rx_ring_dma, ioaddr + RxPtr); + iowrite32(yp->tx_ring_dma, ioaddr + TxPtr); for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + StnAddr + i); + iowrite8(dev->dev_addr[i], ioaddr + StnAddr + i); /* Set up various condition 'select' registers. There are no options here. */ - outl(0x00800080, ioaddr + TxIntrSel); /* Interrupt on Tx abort */ - outl(0x00800080, ioaddr + TxBranchSel); /* Branch on Tx abort */ - outl(0x00400040, ioaddr + TxWaitSel); /* Wait on Tx status */ - outl(0x00400040, ioaddr + RxIntrSel); /* Interrupt on Rx done */ - outl(0x00400040, ioaddr + RxBranchSel); /* Branch on Rx error */ - outl(0x00400040, ioaddr + RxWaitSel); /* Wait on Rx done */ + iowrite32(0x00800080, ioaddr + TxIntrSel); /* Interrupt on Tx abort */ + iowrite32(0x00800080, ioaddr + TxBranchSel); /* Branch on Tx abort */ + iowrite32(0x00400040, ioaddr + TxWaitSel); /* Wait on Tx status */ + iowrite32(0x00400040, ioaddr + RxIntrSel); /* Interrupt on Rx done */ + iowrite32(0x00400040, ioaddr + RxBranchSel); /* Branch on Rx error */ + iowrite32(0x00400040, ioaddr + RxWaitSel); /* Wait on Rx done */ /* Initialize other registers: with so many this eventually this will converted to an offset/value list. */ - outl(dma_ctrl, ioaddr + DMACtrl); - outw(fifo_cfg, ioaddr + FIFOcfg); + iowrite32(dma_ctrl, ioaddr + DMACtrl); + iowrite16(fifo_cfg, ioaddr + FIFOcfg); /* Enable automatic generation of flow control frames, period 0xffff. */ - outl(0x0030FFFF, ioaddr + FlowCtrl); + iowrite32(0x0030FFFF, ioaddr + FlowCtrl); yp->tx_threshold = 32; - outl(yp->tx_threshold, ioaddr + TxThreshold); + iowrite32(yp->tx_threshold, ioaddr + TxThreshold); if (dev->if_port == 0) dev->if_port = yp->default_port; @@ -669,19 +659,19 @@ static int yellowfin_open(struct net_device *dev) if (yp->drv_flags & IsGigabit) { /* We are always in full-duplex mode with gigabit! */ yp->full_duplex = 1; - outw(0x01CF, ioaddr + Cnfg); + iowrite16(0x01CF, ioaddr + Cnfg); } else { - outw(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */ - outw(0x1018, ioaddr + FrameGap1); - outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); + iowrite16(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */ + iowrite16(0x1018, ioaddr + FrameGap1); + iowrite16(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); } set_rx_mode(dev); /* Enable interrupts by setting the interrupt mask. */ - outw(0x81ff, ioaddr + IntrEnb); /* See enum intr_status_bits */ - outw(0x0000, ioaddr + EventStatus); /* Clear non-interrupting events */ - outl(0x80008000, ioaddr + RxCtrl); /* Start Rx and Tx channels. */ - outl(0x80008000, ioaddr + TxCtrl); + iowrite16(0x81ff, ioaddr + IntrEnb); /* See enum intr_status_bits */ + iowrite16(0x0000, ioaddr + EventStatus); /* Clear non-interrupting events */ + iowrite32(0x80008000, ioaddr + RxCtrl); /* Start Rx and Tx channels. */ + iowrite32(0x80008000, ioaddr + TxCtrl); if (yellowfin_debug > 2) { printk(KERN_DEBUG "%s: Done yellowfin_open().\n", @@ -701,13 +691,13 @@ static int yellowfin_open(struct net_device *dev) static void yellowfin_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct yellowfin_private *yp = dev->priv; - long ioaddr = dev->base_addr; + struct yellowfin_private *yp = netdev_priv(dev); + void __iomem *ioaddr = yp->base; int next_tick = 60*HZ; if (yellowfin_debug > 3) { printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n", - dev->name, inw(ioaddr + IntrStatus)); + dev->name, ioread16(ioaddr + IntrStatus)); } if (yp->mii_cnt) { @@ -721,7 +711,7 @@ static void yellowfin_timer(unsigned long data) yp->full_duplex = mii_duplex(yp->duplex_lock, negotiated); - outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); + iowrite16(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); if (bmsr & BMSR_LSTATUS) next_tick = 60*HZ; @@ -735,13 +725,13 @@ static void yellowfin_timer(unsigned long data) static void yellowfin_tx_timeout(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; - long ioaddr = dev->base_addr; + struct yellowfin_private *yp = netdev_priv(dev); + void __iomem *ioaddr = yp->base; printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx " "status %4.4x, Rx status %4.4x, resetting...\n", dev->name, yp->cur_tx, yp->dirty_tx, - inl(ioaddr + TxStatus), inl(ioaddr + RxStatus)); + ioread32(ioaddr + TxStatus), ioread32(ioaddr + RxStatus)); /* Note: these should be KERN_DEBUG. */ if (yellowfin_debug) { @@ -761,7 +751,7 @@ static void yellowfin_tx_timeout(struct net_device *dev) dev->if_port = 0; /* Wake the potentially-idle transmit channel. */ - outl(0x10001000, dev->base_addr + TxCtrl); + iowrite32(0x10001000, yp->base + TxCtrl); if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE) netif_wake_queue (dev); /* Typical path */ @@ -772,7 +762,7 @@ static void yellowfin_tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void yellowfin_init_ring(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); int i; yp->tx_full = 0; @@ -855,7 +845,7 @@ static void yellowfin_init_ring(struct net_device *dev) static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); unsigned entry; int len = skb->len; @@ -920,7 +910,7 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Non-x86 Todo: explicitly flush cache lines here. */ /* Wake the potentially-idle transmit channel. */ - outl(0x10001000, dev->base_addr + TxCtrl); + iowrite32(0x10001000, yp->base + TxCtrl); if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE) netif_start_queue (dev); /* Typical path */ @@ -941,7 +931,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_re { struct net_device *dev = dev_instance; struct yellowfin_private *yp; - long ioaddr; + void __iomem *ioaddr; int boguscnt = max_interrupt_work; unsigned int handled = 0; @@ -952,13 +942,13 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_re } #endif - ioaddr = dev->base_addr; - yp = dev->priv; + yp = netdev_priv(dev); + ioaddr = yp->base; spin_lock (&yp->lock); do { - u16 intr_status = inw(ioaddr + IntrClear); + u16 intr_status = ioread16(ioaddr + IntrClear); if (yellowfin_debug > 4) printk(KERN_DEBUG "%s: Yellowfin interrupt, status %4.4x.\n", @@ -970,7 +960,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_re if (intr_status & (IntrRxDone | IntrEarlyRx)) { yellowfin_rx(dev); - outl(0x10001000, ioaddr + RxCtrl); /* Wake Rx engine. */ + iowrite32(0x10001000, ioaddr + RxCtrl); /* Wake Rx engine. */ } #ifdef NO_TXSTATS @@ -1085,7 +1075,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_re if (yellowfin_debug > 3) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, inw(ioaddr + IntrStatus)); + dev->name, ioread16(ioaddr + IntrStatus)); spin_unlock (&yp->lock); return IRQ_RETVAL(handled); @@ -1095,7 +1085,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance, struct pt_re for clarity and better register allocation. */ static int yellowfin_rx(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); int entry = yp->cur_rx % RX_RING_SIZE; int boguscnt = yp->dirty_rx + RX_RING_SIZE - yp->cur_rx; @@ -1239,7 +1229,7 @@ static int yellowfin_rx(struct net_device *dev) static void yellowfin_error(struct net_device *dev, int intr_status) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); @@ -1252,8 +1242,8 @@ static void yellowfin_error(struct net_device *dev, int intr_status) static int yellowfin_close(struct net_device *dev) { - long ioaddr = dev->base_addr; - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); + void __iomem *ioaddr = yp->base; int i; netif_stop_queue (dev); @@ -1261,18 +1251,19 @@ static int yellowfin_close(struct net_device *dev) if (yellowfin_debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x " "Rx %4.4x Int %2.2x.\n", - dev->name, inw(ioaddr + TxStatus), - inw(ioaddr + RxStatus), inw(ioaddr + IntrStatus)); + dev->name, ioread16(ioaddr + TxStatus), + ioread16(ioaddr + RxStatus), + ioread16(ioaddr + IntrStatus)); printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx); } /* Disable interrupts by clearing the interrupt mask. */ - outw(0x0000, ioaddr + IntrEnb); + iowrite16(0x0000, ioaddr + IntrEnb); /* Stop the chip's Tx and Rx processes. */ - outl(0x80000000, ioaddr + RxCtrl); - outl(0x80000000, ioaddr + TxCtrl); + iowrite32(0x80000000, ioaddr + RxCtrl); + iowrite32(0x80000000, ioaddr + TxCtrl); del_timer(&yp->timer); @@ -1282,7 +1273,7 @@ static int yellowfin_close(struct net_device *dev) (unsigned long long)yp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE*2; i++) printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", - inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', + ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); @@ -1295,7 +1286,7 @@ static int yellowfin_close(struct net_device *dev) (unsigned long long)yp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", - inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ', + ioread32(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ', i, yp->rx_ring[i].dbdma_cmd, yp->rx_ring[i].addr, yp->rx_ring[i].result_status); if (yellowfin_debug > 6) { @@ -1340,7 +1331,7 @@ static int yellowfin_close(struct net_device *dev) static struct net_device_stats *yellowfin_get_stats(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); return &yp->stats; } @@ -1348,19 +1339,19 @@ static struct net_device_stats *yellowfin_get_stats(struct net_device *dev) static void set_rx_mode(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; - long ioaddr = dev->base_addr; - u16 cfg_value = inw(ioaddr + Cnfg); + struct yellowfin_private *yp = netdev_priv(dev); + void __iomem *ioaddr = yp->base; + u16 cfg_value = ioread16(ioaddr + Cnfg); /* Stop the Rx process to change any value. */ - outw(cfg_value & ~0x1000, ioaddr + Cnfg); + iowrite16(cfg_value & ~0x1000, ioaddr + Cnfg); if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ /* Unconditionally log net taps. */ printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); - outw(0x000F, ioaddr + AddrMode); + iowrite16(0x000F, ioaddr + AddrMode); } else if ((dev->mc_count > 64) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well, or accept all multicasts. */ - outw(0x000B, ioaddr + AddrMode); + iowrite16(0x000B, ioaddr + AddrMode); } else if (dev->mc_count > 0) { /* Must use the multicast hash table. */ struct dev_mc_list *mclist; u16 hash_table[4]; @@ -1385,48 +1376,34 @@ static void set_rx_mode(struct net_device *dev) } /* Copy the hash table to the chip. */ for (i = 0; i < 4; i++) - outw(hash_table[i], ioaddr + HashTbl + i*2); - outw(0x0003, ioaddr + AddrMode); + iowrite16(hash_table[i], ioaddr + HashTbl + i*2); + iowrite16(0x0003, ioaddr + AddrMode); } else { /* Normal, unicast/broadcast-only mode. */ - outw(0x0001, ioaddr + AddrMode); + iowrite16(0x0001, ioaddr + AddrMode); } /* Restart the Rx process. */ - outw(cfg_value | 0x1000, ioaddr + Cnfg); + iowrite16(cfg_value | 0x1000, ioaddr + Cnfg); } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void yellowfin_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct yellowfin_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; + struct yellowfin_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = yellowfin_get_drvinfo +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct yellowfin_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct yellowfin_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; struct mii_ioctl_data *data = if_mii(rq); switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = np->phys[0] & 0x1f; /* Fall Through */ @@ -1466,7 +1443,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev) if (!dev) BUG(); - np = dev->priv; + np = netdev_priv(dev); pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, np->tx_status_dma); @@ -1474,11 +1451,9 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev) pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); unregister_netdev (dev); - pci_release_regions (pdev); + pci_iounmap(pdev, np->base); -#ifndef USE_IO_OPS - iounmap ((void *) dev->base_addr); -#endif + pci_release_regions (pdev); free_netdev (dev); pci_set_drvdata(pdev, NULL); diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 9ebd5ea34..20b26912d 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -98,9 +98,9 @@ #include #include #include +#include #include -#include #include #include @@ -421,7 +421,7 @@ static int __init znet_probe (void) znet->rx_dma = netinfo->dma1; znet->tx_dma = netinfo->dma2; - znet->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&znet->lock); znet->sia_base = 0xe6; /* Magic address for the 82501 SIA */ znet->sia_size = 2; /* maz: Despite the '593 being advertised above as using a diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index e5d06ea62..884a53243 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -32,61 +32,65 @@ #include "cpu_buffer.h" #include "buffer_sync.h" -#define DEFAULT_EXPIRE (HZ / 4) - -static void wq_sync_buffers(void *); -static DECLARE_WORK(sync_wq, wq_sync_buffers, NULL); - -static struct timer_list sync_timer; -static void timer_ping(unsigned long data); -static void sync_cpu_buffers(void); +static LIST_HEAD(dying_tasks); +static LIST_HEAD(dead_tasks); +cpumask_t marked_cpus = CPU_MASK_NONE; +static spinlock_t task_mortuary = SPIN_LOCK_UNLOCKED; +void process_task_mortuary(void); - -/* We must make sure to process every entry in the CPU buffers - * before a task got the PF_EXITING flag, otherwise we will hold - * references to a possibly freed task_struct. We are safe with - * samples past the PF_EXITING point in do_exit(), because we - * explicitly check for that in cpu_buffer.c + +/* Take ownership of the task struct and place it on the + * list for processing. Only after two full buffer syncs + * does the task eventually get freed, because by then + * we are sure we will not reference it again. */ -static int exit_task_notify(struct notifier_block * self, unsigned long val, void * data) +static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) { - sync_cpu_buffers(); - return 0; + struct task_struct * task = (struct task_struct *)data; + spin_lock(&task_mortuary); + list_add(&task->tasks, &dying_tasks); + spin_unlock(&task_mortuary); + return NOTIFY_OK; } - -/* There are two cases of tasks modifying task->mm->mmap list we - * must concern ourselves with. First, when a task is about to - * exit (exit_mmap()), we should process the buffer to deal with - * any samples in the CPU buffer, before we lose the ->mmap information - * we need. It is vital to get this case correct, otherwise we can - * end up trying to access a freed task_struct. + + +/* The task is on its way out. A sync of the buffer means we can catch + * any remaining samples for this task. */ -static int mm_notify(struct notifier_block * self, unsigned long val, void * data) +static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data) { - sync_cpu_buffers(); - return 0; + /* To avoid latency problems, we only process the current CPU, + * hoping that most samples for the task are on this CPU + */ + sync_buffer(smp_processor_id()); + return 0; } -/* Second, a task may unmap (part of) an executable mmap, - * so we want to process samples before that happens too. This is merely - * a QOI issue not a correctness one. +/* The task is about to try a do_munmap(). We peek at what it's going to + * do, and if it's an executable region, process the samples first, so + * we don't lose any. This does not have to be exact, it's a QoI issue + * only. */ static int munmap_notify(struct notifier_block * self, unsigned long val, void * data) { - /* Note that we cannot sync the buffers directly, because we might end up - * taking the the mmap_sem that we hold now inside of event_buffer_read() - * on a page fault, whilst holding buffer_sem - deadlock. - * - * This would mean a threaded reader of the event buffer, but we should - * prevent it anyway. - * - * Delaying the work in a context that doesn't hold the mmap_sem means - * that we won't lose samples from other mappings that current() may - * have. Note that either way, we lose any pending samples for what is - * being unmapped. - */ - schedule_work(&sync_wq); + unsigned long addr = (unsigned long)data; + struct mm_struct * mm = current->mm; + struct vm_area_struct * mpnt; + + down_read(&mm->mmap_sem); + + mpnt = find_vma(mm, addr); + if (mpnt && mpnt->vm_file && (mpnt->vm_flags & VM_EXEC)) { + up_read(&mm->mmap_sem); + /* To avoid latency problems, we only process the current CPU, + * hoping that most samples for the task are on this CPU + */ + sync_buffer(smp_processor_id()); + return 0; + } + + up_read(&mm->mmap_sem); return 0; } @@ -100,7 +104,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v if (val != MODULE_STATE_COMING) return 0; - sync_cpu_buffers(); + /* FIXME: should we process all CPU buffers ? */ down(&buffer_sem); add_event_entry(ESCAPE_CODE); add_event_entry(MODULE_LOADED_CODE); @@ -110,16 +114,16 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v } -static struct notifier_block exit_task_nb = { - .notifier_call = exit_task_notify, +static struct notifier_block task_free_nb = { + .notifier_call = task_free_notify, }; -static struct notifier_block exec_unmap_nb = { - .notifier_call = munmap_notify, +static struct notifier_block task_exit_nb = { + .notifier_call = task_exit_notify, }; -static struct notifier_block exit_mmap_nb = { - .notifier_call = mm_notify, +static struct notifier_block munmap_nb = { + .notifier_call = munmap_notify, }; static struct notifier_block module_load_nb = { @@ -127,11 +131,12 @@ static struct notifier_block module_load_nb = { }; -static void end_sync_timer(void) +static void end_sync(void) { - del_timer_sync(&sync_timer); - /* timer might have queued work, make sure it's completed. */ - flush_scheduled_work(); + end_cpu_work(); + /* make sure we don't leak task structs */ + process_task_mortuary(); + process_task_mortuary(); } @@ -139,18 +144,15 @@ int sync_start(void) { int err; - init_timer(&sync_timer); - sync_timer.function = timer_ping; - sync_timer.expires = jiffies + DEFAULT_EXPIRE; - add_timer(&sync_timer); + start_cpu_work(); - err = profile_event_register(EXIT_TASK, &exit_task_nb); + err = task_handoff_register(&task_free_nb); if (err) goto out1; - err = profile_event_register(EXIT_MMAP, &exit_mmap_nb); + err = profile_event_register(PROFILE_TASK_EXIT, &task_exit_nb); if (err) goto out2; - err = profile_event_register(EXEC_UNMAP, &exec_unmap_nb); + err = profile_event_register(PROFILE_MUNMAP, &munmap_nb); if (err) goto out3; err = register_module_notifier(&module_load_nb); @@ -160,13 +162,13 @@ int sync_start(void) out: return err; out4: - profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb); + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); out3: - profile_event_unregister(EXIT_MMAP, &exit_mmap_nb); + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); out2: - profile_event_unregister(EXIT_TASK, &exit_task_nb); + task_handoff_unregister(&task_free_nb); out1: - end_sync_timer(); + end_sync(); goto out; } @@ -174,10 +176,10 @@ out1: void sync_stop(void) { unregister_module_notifier(&module_load_nb); - profile_event_unregister(EXIT_TASK, &exit_task_nb); - profile_event_unregister(EXIT_MMAP, &exit_mmap_nb); - profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb); - end_sync_timer(); + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); + task_handoff_unregister(&task_free_nb); + end_sync(); } @@ -337,40 +339,25 @@ static void add_sample(struct mm_struct * mm, struct op_sample * s, int in_kerne } } - + static void release_mm(struct mm_struct * mm) { - if (mm) - up_read(&mm->mmap_sem); + if (!mm) + return; + up_read(&mm->mmap_sem); + mmput(mm); } -/* Take the task's mmap_sem to protect ourselves from - * races when we do lookup_dcookie(). - */ static struct mm_struct * take_tasks_mm(struct task_struct * task) { - struct mm_struct * mm; - - /* Subtle. We don't need to keep a reference to this task's mm, - * because, for the mm to be freed on another CPU, that would have - * to go through the task exit notifier, which ends up sleeping - * on the buffer_sem we hold, so we end up with mutual exclusion - * anyway. - */ - task_lock(task); - mm = task->mm; - task_unlock(task); - - if (mm) { - /* needed to walk the task's VMAs */ + struct mm_struct * mm = get_task_mm(task); + if (mm) down_read(&mm->mmap_sem); - } - return mm; } - - + + static inline int is_ctx_switch(unsigned long val) { return val == ~0UL; @@ -417,24 +404,80 @@ static void increment_tail(struct oprofile_cpu_buffer * b) } +/* Move tasks along towards death. Any tasks on dead_tasks + * will definitely have no remaining references in any + * CPU buffers at this point, because we use two lists, + * and to have reached the list, it must have gone through + * one full sync already. + */ +void process_task_mortuary(void) +{ + struct list_head * pos; + struct list_head * pos2; + struct task_struct * task; + + spin_lock(&task_mortuary); + + list_for_each_safe(pos, pos2, &dead_tasks) { + task = list_entry(pos, struct task_struct, tasks); + list_del(&task->tasks); + free_task(task); + } + + list_for_each_safe(pos, pos2, &dying_tasks) { + task = list_entry(pos, struct task_struct, tasks); + list_del(&task->tasks); + list_add_tail(&task->tasks, &dead_tasks); + } + + spin_unlock(&task_mortuary); +} + + +static void mark_done(int cpu) +{ + int i; + + cpu_set(cpu, marked_cpus); + + for_each_online_cpu(i) { + if (!cpu_isset(i, marked_cpus)) + return; + } + + /* All CPUs have been processed at least once, + * we can process the mortuary once + */ + process_task_mortuary(); + + cpus_clear(marked_cpus); +} + + /* Sync one of the CPU's buffers into the global event buffer. * Here we need to go through each batch of samples punctuated * by context switch notes, taking the task's mmap_sem and doing * lookup in task->mm->mmap to convert EIP into dcookie/offset * value. */ -static void sync_buffer(struct oprofile_cpu_buffer * cpu_buf) +void sync_buffer(int cpu) { + struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[cpu]; struct mm_struct *mm = NULL; struct task_struct * new; unsigned long cookie = 0; int in_kernel = 1; unsigned int i; + unsigned long available; + + down(&buffer_sem); + add_cpu_switch(cpu); + /* Remember, only we can modify tail_pos */ - unsigned long const available = get_slots(cpu_buf); - + available = get_slots(cpu_buf); + for (i=0; i < available; ++i) { struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; @@ -462,50 +505,8 @@ static void sync_buffer(struct oprofile_cpu_buffer * cpu_buf) increment_tail(cpu_buf); } release_mm(mm); -} - - -/* Process each CPU's local buffer into the global - * event buffer. - */ -static void sync_cpu_buffers(void) -{ - int i; - down(&buffer_sem); - - for (i = 0; i < NR_CPUS; ++i) { - struct oprofile_cpu_buffer * cpu_buf; - - if (!cpu_possible(i)) - continue; - - cpu_buf = &cpu_buffer[i]; - - add_cpu_switch(i); - sync_buffer(cpu_buf); - } + mark_done(cpu); up(&buffer_sem); - - mod_timer(&sync_timer, jiffies + DEFAULT_EXPIRE); -} - - -static void wq_sync_buffers(void * data) -{ - sync_cpu_buffers(); -} - - -/* It is possible that we could have no munmap() or - * other events for a period of time. This will lead - * the CPU buffers to overflow and lose samples and - * context switches. We try to reduce the problem - * by timing out when nothing happens for a while. - */ -static void timer_ping(unsigned long data) -{ - schedule_work(&sync_wq); - /* timer is re-added by the scheduled task */ } diff --git a/drivers/oprofile/buffer_sync.h b/drivers/oprofile/buffer_sync.h index a8def27d8..08866f6a9 100644 --- a/drivers/oprofile/buffer_sync.h +++ b/drivers/oprofile/buffer_sync.h @@ -16,4 +16,7 @@ int sync_start(void); /* remove the hooks */ void sync_stop(void); +/* sync the given CPU's buffer */ +void sync_buffer(int cpu); + #endif /* OPROFILE_BUFFER_SYNC_H */ diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 7ee6a3d99..420dc8e83 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -9,7 +9,7 @@ * Each CPU has a local buffer that stores PC value/event * pairs. We also log context switches when we notice them. * Eventually each CPU's buffer is processed into the global - * event buffer by sync_cpu_buffers(). + * event buffer by sync_buffer(). * * We use a local buffer for two reasons: an NMI or similar * interrupt cannot synchronise, and high sampling rates @@ -22,21 +22,23 @@ #include #include "cpu_buffer.h" +#include "buffer_sync.h" #include "oprof.h" struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; +static void wq_sync_buffer(void *); + +#define DEFAULT_TIMER_EXPIRE (HZ / 10) +int work_enabled; + static void __free_cpu_buffers(int num) { int i; - for (i=0; i < num; ++i) { - struct oprofile_cpu_buffer * b = &cpu_buffer[i]; - - if (!cpu_possible(i)) - continue; - - vfree(b->buffer); + for_each_online_cpu(i) { + if (cpu_buffer[i].buffer) + vfree(cpu_buffer[i].buffer); } } @@ -47,12 +49,9 @@ int alloc_cpu_buffers(void) unsigned long buffer_size = fs_cpu_buffer_size; - for (i=0; i < NR_CPUS; ++i) { + for_each_online_cpu(i) { struct oprofile_cpu_buffer * b = &cpu_buffer[i]; - if (!cpu_possible(i)) - continue; - b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size); if (!b->buffer) goto fail; @@ -64,9 +63,11 @@ int alloc_cpu_buffers(void) b->head_pos = 0; b->sample_received = 0; b->sample_lost_overflow = 0; - b->sample_lost_task_exit = 0; + b->cpu = i; + INIT_WORK(&b->work, wq_sync_buffer, b); } return 0; + fail: __free_cpu_buffers(i); return -ENOMEM; @@ -79,6 +80,40 @@ void free_cpu_buffers(void) } +void start_cpu_work(void) +{ + int i; + + work_enabled = 1; + + for_each_online_cpu(i) { + struct oprofile_cpu_buffer * b = &cpu_buffer[i]; + + /* + * Spread the work by 1 jiffy per cpu so they dont all + * fire at once. + */ + schedule_delayed_work_on(i, &b->work, DEFAULT_TIMER_EXPIRE + i); + } +} + + +void end_cpu_work(void) +{ + int i; + + work_enabled = 0; + + for_each_online_cpu(i) { + struct oprofile_cpu_buffer * b = &cpu_buffer[i]; + + cancel_delayed_work(&b->work); + } + + flush_scheduled_work(); +} + + /* compute number of available slots in cpu_buffer queue */ static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b) { @@ -145,21 +180,9 @@ void oprofile_add_sample(unsigned long eip, unsigned int is_kernel, /* notice a task switch */ if (cpu_buf->last_task != task) { cpu_buf->last_task = task; - if (!(task->flags & PF_EXITING)) { - cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; - cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task; - increment_head(cpu_buf); - } - } - - /* If the task is exiting it's not safe to take a sample - * as the task_struct is about to be freed. We can't just - * notify at release_task() time because of CLONE_DETACHED - * tasks that release_task() themselves. - */ - if (task->flags & PF_EXITING) { - cpu_buf->sample_lost_task_exit++; - return; + cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; + cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task; + increment_head(cpu_buf); } cpu_buf->buffer[cpu_buf->head_pos].eip = eip; @@ -178,3 +201,25 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf) cpu_buf->last_is_kernel = -1; cpu_buf->last_task = NULL; } + + +/* + * This serves to avoid cpu buffer overflow, and makes sure + * the task mortuary progresses + * + * By using schedule_delayed_work_on and then schedule_delayed_work + * we guarantee this will stay on the correct cpu + */ +static void wq_sync_buffer(void * data) +{ + struct oprofile_cpu_buffer * b = (struct oprofile_cpu_buffer *)data; + if (b->cpu != smp_processor_id()) { + printk("WQ on CPU%d, prefer CPU%d\n", + smp_processor_id(), b->cpu); + } + sync_buffer(b->cpu); + + /* don't re-add the work if we're shutting down */ + if (work_enabled) + schedule_delayed_work(&b->work, DEFAULT_TIMER_EXPIRE); +} diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 66eafcdb1..23be2013a 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -12,15 +12,17 @@ #include #include +#include #include struct task_struct; -/* allocate a sample buffer for each CPU */ int alloc_cpu_buffers(void); - void free_cpu_buffers(void); +void start_cpu_work(void); +void end_cpu_work(void); + /* CPU buffer is composed of such entries (which are * also used for context switch notes) */ @@ -38,11 +40,12 @@ struct oprofile_cpu_buffer { struct op_sample * buffer; unsigned long sample_received; unsigned long sample_lost_overflow; - unsigned long sample_lost_task_exit; + int cpu; + struct work_struct work; } ____cacheline_aligned; extern struct oprofile_cpu_buffer cpu_buffer[]; -void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf); +void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); #endif /* OPROFILE_CPU_BUFFER_H */ diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index 8e92b0388..3ec23d8a6 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -22,14 +22,10 @@ void oprofile_reset_stats(void) struct oprofile_cpu_buffer * cpu_buf; int i; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_possible(i)) - continue; - + for_each_cpu(i) { cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; cpu_buf->sample_lost_overflow = 0; - cpu_buf->sample_lost_task_exit = 0; } atomic_set(&oprofile_stats.sample_lost_no_mm, 0); @@ -50,10 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) if (!dir) return; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_possible(i)) - continue; - + for_each_cpu(i) { cpu_buf = &cpu_buffer[i]; snprintf(buf, 10, "cpu%d", i); cpudir = oprofilefs_mkdir(sb, dir, buf); @@ -66,8 +59,6 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) &cpu_buf->sample_received); oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow", &cpu_buf->sample_lost_overflow); - oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit", - &cpu_buf->sample_lost_task_exit); } oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm", diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index d9746f1b5..17c0aa8fe 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -135,11 +135,8 @@ static struct dentry * __oprofilefs_create_file(struct super_block * sb, { struct dentry * dentry; struct inode * inode; - struct qstr qname; - qname.name = name; - qname.len = strlen(name); - qname.hash = full_name_hash(qname.name, qname.len); - dentry = d_alloc(root, &qname); + + dentry = d_alloc_name(root, name); if (!dentry) return NULL; inode = oprofilefs_get_inode(sb, S_IFREG | perm); @@ -228,11 +225,8 @@ struct dentry * oprofilefs_mkdir(struct super_block * sb, { struct dentry * dentry; struct inode * inode; - struct qstr qname; - qname.name = name; - qname.len = strlen(name); - qname.hash = full_name_hash(qname.name, qname.len); - dentry = d_alloc(root, &qname); + + dentry = d_alloc_name(root, name); if (!dentry) return NULL; inode = oprofilefs_get_inode(sb, S_IFDIR | 0755); diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 3fae2c772..543d2cb5f 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -15,31 +15,24 @@ #include #include -static int timer_notify(struct notifier_block * self, unsigned long val, void * data) +static int timer_notify(struct pt_regs *regs) { - struct pt_regs * regs = (struct pt_regs *)data; int cpu = smp_processor_id(); - unsigned long eip = instruction_pointer(regs); + unsigned long eip = profile_pc(regs); oprofile_add_sample(eip, !user_mode(regs), 0, cpu); return 0; } - - -static struct notifier_block timer_notifier = { - .notifier_call = timer_notify, -}; - static int timer_start(void) { - return register_profile_notifier(&timer_notifier); + return register_timer_hook(timer_notify); } static void timer_stop(void) { - unregister_profile_notifier(&timer_notifier); + unregister_timer_hook(timer_notify); } diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index 6e67ea060..45f2be4cc 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -11,7 +11,7 @@ * (at your option) any later version. * * by Alan Cox and - * Alex deVries + * Alex deVries */ #include diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 8126dbdcd..bcc00e2a9 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1,4 +1,5 @@ /* +** ** PCI Lower Bus Adapter (LBA) manager ** ** (c) Copyright 1999,2000 Grant Grundler @@ -116,7 +117,7 @@ ** bus number for each LBA depending on what firmware does. */ -#define MODULE_NAME "lba" +#define MODULE_NAME "LBA" #define LBA_FUNC_ID 0x0000 /* function id */ #define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */ @@ -163,6 +164,7 @@ #define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */ #define LBA_EIOS_MASK 0x0268 +#define LBA_GLOBAL_MASK 0x0270 /* Mercury only: Global Address Mask */ #define LBA_DMA_CTL 0x0278 /* firmware sets this */ #define LBA_IBASE 0x0300 /* SBA DMA support */ @@ -183,11 +185,7 @@ #define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */ /* non-postable I/O port space, densely packed */ -#ifdef CONFIG_PARISC64 -#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL) -#else -#define LBA_ASTRO_PORT_BASE (0xfee00000UL) -#endif +#define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL) #define ELROY_HVERS 0x782 #define MERCURY_HVERS 0x783 @@ -283,8 +281,8 @@ static u32 lba_t32; ** Extract LBA (Rope) number from HPA ** REVISIT: 16 ropes for Stretch/Ike? */ -#define ROPES_PER_SBA 8 -#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_SBA-1)) +#define ROPES_PER_IOC 8 +#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_IOC-1)) static void @@ -444,7 +442,8 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d) } #define LBA_CFG_TR4_ADDR_SETUP(d, addr) \ - WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR) + WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ + lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR) #define LBA_CFG_ADDR_SETUP(d, addr) { \ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ @@ -520,7 +519,16 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) return(data); } -#ifdef CONFIG_PARISC64 + +#if USE_PAT_PDC_CFG + +/* PAT PDC needs to be relocated in order to perform properly. + * tg3 driver does about 1600 PCI Cfg writes to initialize the card. + * On 440Mhz A500, PDC takes ~20ms/write, or ~30 seconds per card. + * On PA8800, that takes about 5ms/write (8 seconds). + * But relocating PDC will burn at least 4MB of RAM. + * Easier/Cheaper to just maintain our own mercury cfg ops. + */ #define pat_cfg_addr(bus, devfn, addr) (((bus) << 16) | ((devfn) << 8) | (addr)) static int pat_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) @@ -553,11 +561,84 @@ static struct pci_ops pat_cfg_ops = { .read = pat_cfg_read, .write = pat_cfg_write, }; -#else -/* keep the compiler from complaining about undeclared variables */ -#define pat_cfg_ops lba_cfg_ops #endif + +#ifdef CONFIG_PARISC64 +static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) +{ + struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); + u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 tok = LBA_CFG_TOK(local_bus, devfn); + + /* Basic Algorithm + ** Should only get here on fully working LBA rev. + ** This is how simple the original LBA code should have been. + */ + LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); + switch(size) { + case 1: *(u8 *) data = READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + + (pos & 3)); + DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, + *(u8 *)data); + return(*(u8 *)data == (u8) ~0U); + case 2: *(u16 *) data = READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + + (pos & 2)); + DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, + *(u16 *)data); + return(*(u16 *)data == (u16) ~0U); + case 4: *(u32 *) data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA); + DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data); + return(*data == ~0U); + } + DBG_CFG("%s(%x+%2x) -> bad size (%d)\n", __FUNCTION__, tok, pos, size); + *data = ~0U; + return(!PCIBIOS_SUCCESSFUL); /* failed */ +} + +/* + * LBA 4.0 config write code implements non-postable semantics + * by doing a read of CONFIG ADDR after the write. + */ + +static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) +{ + struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); + unsigned long data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; + u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; + u32 tok = LBA_CFG_TOK(local_bus,devfn); + + ASSERT((tok & 0xff) == 0); + ASSERT(pos < 0x100); + + DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data); + + /* Basic Algorithm */ + LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); + switch(size) { + case 1: WRITE_REG8 (data, data_reg + (pos & 3)); break; + case 2: WRITE_REG16(data, data_reg + (pos & 2)); break; + case 4: WRITE_REG32(data, data_reg); break; + default: + DBG_CFG("%s(%x+%2x) WTF! size %d\n", __FUNCTION__, tok, pos, + size); + } + + /* flush posted write */ + lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR); + return PCIBIOS_SUCCESSFUL; +} + + +static struct pci_ops mercury_cfg_ops = { + .read = mercury_cfg_read, + .write = mercury_cfg_write, +}; +#else +#define mercury_cfg_ops lba_cfg_ops +#endif /* CONFIG_PARISC64 */ + + static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); @@ -768,7 +849,7 @@ lba_fixup_bus(struct pci_bus *bus) pci_read_bridge_bases(bus); } else { /* Host-PCI Bridge */ - int err; + int err, i; DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", ldev->hba.io_space.name, @@ -781,30 +862,65 @@ lba_fixup_bus(struct pci_bus *bus) err = request_resource(&ioport_resource, &(ldev->hba.io_space)); if (err < 0) { - BUG(); lba_dump_res(&ioport_resource, 2); + BUG(); + } + + if (ldev->hba.elmmio_space.start) { + err = request_resource(&iomem_resource, + &(ldev->hba.elmmio_space)); + if (err < 0) { + + printk("FAILED: lba_fixup_bus() request for " + "elmmio_space [%lx/%lx]\n", + ldev->hba.elmmio_space.start, + ldev->hba.elmmio_space.end); + + /* lba_dump_res(&iomem_resource, 2); */ + /* BUG(); */ + } } err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); if (err < 0) { - BUG(); - lba_dump_res(&iomem_resource, 2); + /* FIXME overlaps with elmmio will fail here. + * Need to prune (or disable) the distributed range. + * + * BEWARE: conflicts with this lmmio range may be + * elmmio range which is pointing down another rope. + */ + + printk("FAILED: lba_fixup_bus() request for " + "lmmio_space [%lx/%lx]\n", + ldev->hba.lmmio_space.start, + ldev->hba.lmmio_space.end); + /* lba_dump_res(&iomem_resource, 2); */ } #ifdef CONFIG_PARISC64 + /* GMMIO is distributed range. Every LBA/Rope gets part it. */ if (ldev->hba.gmmio_space.flags) { err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space)); if (err < 0) { - BUG(); + printk("FAILED: lba_fixup_bus() request for " + "gmmio_space [%lx/%lx]\n", + ldev->hba.gmmio_space.start, + ldev->hba.gmmio_space.end); lba_dump_res(&iomem_resource, 2); + BUG(); } - bus->resource[2] = &(ldev->hba.gmmio_space); } #endif /* advertize Host bridge resources to PCI bus */ bus->resource[0] = &(ldev->hba.io_space); bus->resource[1] = &(ldev->hba.lmmio_space); + i=2; + if (ldev->hba.elmmio_space.start) + bus->resource[i++] = &(ldev->hba.elmmio_space); + if (ldev->hba.gmmio_space.start) + bus->resource[i++] = &(ldev->hba.gmmio_space); + } list_for_each(ln, &bus->devices) { @@ -837,6 +953,9 @@ lba_fixup_bus(struct pci_bus *bus) res->start = PCI_HOST_ADDR(HBA_DATA(ldev), res->start); res->end = PCI_HOST_ADDR(HBA_DATA(ldev), res->end); DBG("[%lx/%lx]\n", res->start, res->end); + } else { + DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX", + res->flags, res->start, res->end); } } @@ -918,7 +1037,7 @@ struct pci_bios_ops lba_bios_ops = { static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \ { \ u##size t; \ - t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \ + t = READ_REG##size(LBA_PORT_BASE + addr); \ DBG_PORT(" 0x%x\n", t); \ return (t); \ } @@ -960,7 +1079,7 @@ static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) { \ ASSERT(d != NULL); \ DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ - WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \ + WRITE_REG##size(val, LBA_PORT_BASE + addr); \ if (LBA_DEV(d)->hw_rev < 3) \ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ } @@ -1001,7 +1120,6 @@ static struct pci_port_ops lba_astro_port_ops = { static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \ { \ u##size t; \ - ASSERT(bus != NULL); \ DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ DBG_PORT(" 0x%x\n", t); \ @@ -1018,7 +1136,6 @@ LBA_PORT_IN(32, 0) static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ { \ void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ - ASSERT(bus != NULL); \ DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ @@ -1099,10 +1216,23 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_LMMIO: /* used to fix up pre-initialized MEM BARs */ - lba_dev->hba.lmmio_space_offset = p->start - io->start; + if (!lba_dev->hba.lmmio_space.start) { + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", + (int) lba_dev->hba.bus_num.start); + lba_dev->hba.lmmio_space_offset = p->start - io->start; + r = &(lba_dev->hba.lmmio_space); + r->name = lba_dev->hba.lmmio_name; + } else if (!lba_dev->hba.elmmio_space.start) { + sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", + (int) lba_dev->hba.bus_num.start); + r = &(lba_dev->hba.elmmio_space); + r->name = lba_dev->hba.elmmio_name; + } else { + printk(KERN_WARNING MODULE_NAME + " only supports 2 LMMIO resources!\n"); + break; + } - r = &(lba_dev->hba.lmmio_space); - r->name = "LBA LMMIO"; r->start = p->start; r->end = p->end; r->flags = IORESOURCE_MEM; @@ -1111,8 +1241,10 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_GMMIO: /* MMIO space > 4GB phys addr; for 64-bit BAR */ + sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO", + (int) lba_dev->hba.bus_num.start); r = &(lba_dev->hba.gmmio_space); - r->name = "LBA GMMIO"; + r->name = lba_dev->hba.gmmio_name; r->start = p->start; r->end = p->end; r->flags = IORESOURCE_MEM; @@ -1132,8 +1264,10 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) */ lba_dev->iop_base = p->start; + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int) lba_dev->hba.bus_num.start); r = &(lba_dev->hba.io_space); - r->name = "LBA I/O Port"; + r->name = lba_dev->hba.io_name; r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); r->end = r->start + HBA_PORT_SPACE_SIZE - 1; r->flags = IORESOURCE_IO; @@ -1155,24 +1289,17 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) #endif /* CONFIG_PARISC64 */ +extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); +extern void sba_directed_lmmio(struct parisc_device *, struct resource *); + + static void lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) { struct resource *r; - unsigned long rsize; int lba_num; -#ifdef CONFIG_PARISC64 - /* - ** Sign extend all BAR values on "legacy" platforms. - ** "Sprockets" PDC (Forte/Allegro) initializes everything - ** for "legacy" 32-bit OS (HPUX 10.20). - ** Upper 32-bits of 64-bit BAR will be zero too. - */ - lba_dev->hba.lmmio_space_offset = 0xffffffff00000000UL; -#else - lba_dev->hba.lmmio_space_offset = 0UL; -#endif + lba_dev->hba.lmmio_space_offset = PCI_F_EXTEND; /* ** With "legacy" firmware, the lowest byte of FW_SCRATCH @@ -1187,27 +1314,104 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) r->start = lba_num & 0xff; r->end = (lba_num>>8) & 0xff; - /* Set up local PCI Bus resources - we don't really need - ** them for Legacy boxes but it's nice to see in /proc. + /* Set up local PCI Bus resources - we don't need them for + ** Legacy boxes but it's nice to see in /proc/iomem. */ r = &(lba_dev->hba.lmmio_space); - r->name = "LBA PCI LMMIO"; - r->flags = IORESOURCE_MEM; - /* Ignore "Range Enable" bit in the BASE register */ - r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), - ((long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE)) & ~1UL); - rsize = ~READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK) + 1; - + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", + (int) lba_dev->hba.bus_num.start); + r->name = lba_dev->hba.lmmio_name; + +#if 1 + /* We want the CPU -> IO routing of addresses. + * The SBA BASE/MASK registers control CPU -> IO routing. + * Ask SBA what is routed to this rope/LBA. + */ + sba_distributed_lmmio(pa_dev, r); +#else /* - ** Each rope only gets part of the distributed range. - ** Adjust "window" for this rope - */ - rsize /= ROPES_PER_SBA; - r->start += rsize * LBA_NUM(pa_dev->hpa); - r->end = r->start + rsize - 1 ; + * The LBA BASE/MASK registers control IO -> System routing. + * + * The following code works but doesn't get us what we want. + * Well, only because firmware (v5.0) on C3000 doesn't program + * the LBA BASE/MASE registers to be the exact inverse of + * the corresponding SBA registers. Other Astro/Pluto + * based platform firmware may do it right. + * + * Should someone want to mess with MSI, they may need to + * reprogram LBA BASE/MASK registers. Thus preserve the code + * below until MSI is known to work on C3000/A500/N4000/RP3440. + * + * Using the code below, /proc/iomem shows: + * ... + * f0000000-f0ffffff : PCI00 LMMIO + * f05d0000-f05d0000 : lcd_data + * f05d0008-f05d0008 : lcd_cmd + * f1000000-f1ffffff : PCI01 LMMIO + * f4000000-f4ffffff : PCI02 LMMIO + * f4000000-f4001fff : sym53c8xx + * f4002000-f4003fff : sym53c8xx + * f4004000-f40043ff : sym53c8xx + * f4005000-f40053ff : sym53c8xx + * f4007000-f4007fff : ohci_hcd + * f4008000-f40083ff : tulip + * f6000000-f6ffffff : PCI03 LMMIO + * f8000000-fbffffff : PCI00 ELMMIO + * fa100000-fa4fffff : stifb mmio + * fb000000-fb1fffff : stifb fb + * + * But everything listed under PCI02 actually lives under PCI00. + * This is clearly wrong. + * + * Asking SBA how things are routed tells the correct story: + * LMMIO_BASE/MASK/ROUTE f4000001 fc000000 00000000 + * DIR0_BASE/MASK/ROUTE fa000001 fe000000 00000006 + * DIR1_BASE/MASK/ROUTE f9000001 ff000000 00000004 + * DIR2_BASE/MASK/ROUTE f0000000 fc000000 00000000 + * DIR3_BASE/MASK/ROUTE f0000000 fc000000 00000000 + * + * Which looks like this in /proc/iomem: + * f4000000-f47fffff : PCI00 LMMIO + * f4000000-f4001fff : sym53c8xx + * ...[deteled core devices - same as above]... + * f4008000-f40083ff : tulip + * f4800000-f4ffffff : PCI01 LMMIO + * f6000000-f67fffff : PCI02 LMMIO + * f7000000-f77fffff : PCI03 LMMIO + * f9000000-f9ffffff : PCI02 ELMMIO + * fa000000-fbffffff : PCI03 ELMMIO + * fa100000-fa4fffff : stifb mmio + * fb000000-fb1fffff : stifb fb + * + * ie all Built-in core are under now correctly under PCI00. + * The "PCI02 ELMMIO" directed range is for: + * +-[02]---03.0 3Dfx Interactive, Inc. Voodoo 2 + * + * All is well now. + */ + r->start = (long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE); + if (r->start & 1) { + unsigned long rsize; + + r->flags = IORESOURCE_MEM; + /* mmio_mask also clears Enable bit */ + r->start &= mmio_mask; + r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start); + rsize = ~ READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK); + + /* + ** Each rope only gets part of the distributed range. + ** Adjust "window" for this rope. + */ + rsize /= ROPES_PER_IOC; + r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa); + r->end = r->start + rsize; + } else { + r->end = r->start = 0; /* Not enabled. */ + } +#endif /* - ** XXX FIXME - ignore LBA_ELMMIO_BASE for now ** "Directed" ranges are used when the "distributed range" isn't ** sufficient for all devices below a given LBA. Typically devices ** like graphics cards or X25 may need a directed range when the @@ -1216,35 +1420,38 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** ** The main reason for ignoring it now frigging complications. ** Directed ranges may overlap (and have precedence) over - ** distributed ranges. Ie a distributed range assigned to a unused + ** distributed ranges. Or a distributed range assigned to a unused ** rope may be used by a directed range on a different rope. ** Support for graphics devices may require fixing this ** since they may be assigned a directed range which overlaps ** an existing (but unused portion of) distributed range. */ r = &(lba_dev->hba.elmmio_space); - r->name = "extra LBA PCI LMMIO"; - r->flags = IORESOURCE_MEM; + sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", + (int) lba_dev->hba.bus_num.start); + r->name = lba_dev->hba.elmmio_name; + +#if 1 + /* See comment which precedes call to sba_directed_lmmio() */ + sba_directed_lmmio(pa_dev, r); +#else r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE); - r->end = 0; - /* check Range Enable bit */ if (r->start & 1) { - /* First baby step to getting Direct Ranges listed in /proc. - ** AFAIK, only Sprockets PDC will setup a directed Range. - */ - - r->start &= ~1; - r->end = r->start; - r->end += ~READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK); - printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0lx SIZE 0x%lx\n", - r->start, - r->end + 1); - + unsigned long rsize; + r->flags = IORESOURCE_MEM; + /* mmio_mask also clears Enable bit */ + r->start &= mmio_mask; + r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start); + rsize = READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK); + r->end = r->start + ~rsize; } +#endif r = &(lba_dev->hba.io_space); - r->name = "LBA PCI I/O Ports"; + sprintf(lba_dev->hba.io_name, "PCI%02x Ports", + (int) lba_dev->hba.bus_num.start); + r->name = lba_dev->hba.io_name; r->flags = IORESOURCE_IO; r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L; r->end = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1)); @@ -1478,11 +1685,16 @@ lba_driver_probe(struct parisc_device *dev) dev->dev.platform_data = lba_dev; lba_bus = lba_dev->hba.hba_bus = pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, - is_pdc_pat() ? &pat_cfg_ops : &lba_cfg_ops, + IS_ELROY(dev) ? &lba_cfg_ops : &mercury_cfg_ops, NULL); + /* This is in lieu of calling pci_assign_unassigned_resources() */ if (is_pdc_pat()) { /* assign resources to un-initialized devices */ + + DBG_PAT("LBA pci_bus_size_bridges()\n"); + pci_bus_size_bridges(lba_bus); + DBG_PAT("LBA pci_bus_assign_resources()\n"); pci_bus_assign_resources(lba_bus); @@ -1493,6 +1705,8 @@ lba_driver_probe(struct parisc_device *dev) lba_dump_res(&lba_dev->hba.lmmio_space, 2); #endif } + pci_enable_bridges(lba_bus); + /* ** Once PCI register ops has walked the bus, access to config diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 9a2a26c22..d097e7ecd 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c @@ -54,9 +54,9 @@ #ifdef DEBUG -# define DPRINTK(x) printk x +# define DPRINTK(x...) printk(x) #else -# define DPRINTK(x) do { } while (0) +# define DPRINTK(x...) #endif @@ -120,14 +120,14 @@ static int shutdown_timer; static void process_shutdown(void) { if (shutdown_timer == 0) - DPRINTK((KERN_INFO "Shutdown requested...\n")); + DPRINTK(KERN_INFO "Shutdown requested...\n"); shutdown_timer++; /* wait until the button was pressed for 1 second */ if (shutdown_timer == HZ) { static char msg[] = "Shutting down..."; - DPRINTK((KERN_INFO "%s\n", msg)); + DPRINTK(KERN_INFO "%s\n", msg); #ifdef CONFIG_CHASSIS_LCD_LED lcd_print(msg); #endif diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index f3cf291ad..609d5f494 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1,8 +1,9 @@ /* ** System Bus Adapter (SBA) I/O MMU manager ** -** (c) Copyright 2000 Grant Grundler -** (c) Copyright 2000 Hewlett-Packard Company +** (c) Copyright 2000-2004 Grant Grundler +** (c) Copyright 2004 Naresh Kumar Inna +** (c) Copyright 2000-2004 Hewlett-Packard Company ** ** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) ** @@ -167,11 +168,21 @@ extern struct proc_dir_entry * proc_mckinley_root; #define MAX_IOC 2 /* per Ike. Pluto/Astro only have 1. */ +#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */ + /* ** Offsets into MBIB (Function 0 on Ike and hopefully Astro) ** Firmware programs this stuff. Don't touch it. */ +#define LMMIO_DIRECT0_BASE 0x300 +#define LMMIO_DIRECT0_MASK 0x308 +#define LMMIO_DIRECT0_ROUTE 0x310 + +#define LMMIO_DIST_BASE 0x360 +#define LMMIO_DIST_MASK 0x368 +#define LMMIO_DIST_ROUTE 0x370 + #define IOS_DIST_BASE 0x390 #define IOS_DIST_MASK 0x398 #define IOS_DIST_ROUTE 0x3A0 @@ -289,6 +300,9 @@ struct sba_device { unsigned int flags; /* state/functionality enabled */ unsigned int hw_rev; /* HW revision of chip */ + struct resource chip_resv; /* MMIO reserved for chip */ + struct resource iommu_resv; /* MMIO reserved for iommu */ + unsigned int num_ioc; /* number of on-board IOC's */ struct ioc ioc[MAX_IOC]; }; @@ -569,7 +583,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) while(res_ptr < res_end) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); - ASSERT(0 != mask); + BUG_ON(0 == mask); if(0 == ((*res_ptr) & mask)) { *res_ptr |= mask; /* mark resources busy! */ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); @@ -1696,19 +1710,46 @@ sba_hw_init(struct sba_device *sba_dev) } /* if !PLUTO */ if (IS_ASTRO(sba_dev->iodc)) { + int err; /* PAT_PDC (L-class) also reports the same goofy base */ sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET; num_ioc = 1; + + sba_dev->chip_resv.name = "Astro Intr Ack"; + sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfef00000UL; + sba_dev->chip_resv.end = PCI_F_EXTEND | (0xff000000UL - 1) ; + err = request_resource(&iomem_resource, &(sba_dev->chip_resv)); + if (err < 0) { + BUG(); + } + } else if (IS_PLUTO(sba_dev->iodc)) { + int err; + /* We use a negative value for IOC HPA so it gets * corrected when we add it with IKE's IOC offset. * Doesnt look clean, but fewer code. */ sba_dev->ioc[0].ioc_hpa = -PLUTO_IOC_OFFSET; num_ioc = 1; + + sba_dev->chip_resv.name = "Pluto Intr/PIOP/VGA"; + sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfee00000UL; + sba_dev->chip_resv.end = PCI_F_EXTEND | (0xff200000UL - 1); + err = request_resource(&iomem_resource, &(sba_dev->chip_resv)); + BUG_ON(err < 0); + + sba_dev->iommu_resv.name = "IOVA Space"; + sba_dev->iommu_resv.start = 0x40000000UL; + sba_dev->iommu_resv.end = 0x50000000UL - 1; + err = request_resource(&iomem_resource, &(sba_dev->iommu_resv)); + BUG_ON(err < 0); } else { + /* IS_IKE (ie N-class, L3000, L1500) */ sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0; num_ioc = 2; + + /* TODO - LOOKUP Ike/Stretch chipset mem map */ } sba_dev->num_ioc = num_ioc; @@ -1843,8 +1884,9 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) struct sba_device *sba_dev = sba_list; struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ + unsigned long i; #ifdef SBA_COLLECT_STATS - unsigned long i = 0, avg = 0, min, max; + unsigned long avg = 0, min, max; #endif sprintf(buf, "%s rev %d.%d\n", @@ -1860,6 +1902,21 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + sprintf(buf, "%sLMMIO_BASE/MASK/ROUTE %08x %08x %08x\n", + buf, + READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_BASE), + READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_MASK), + READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_ROUTE) + ); + + for (i=0; i<4; i++) + sprintf(buf, "%sDIR%ld_BASE/MASK/ROUTE %08x %08x %08x\n", + buf, i, + READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_BASE + i*0x18), + READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_MASK + i*0x18), + READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_ROUTE + i*0x18) + ); + #ifdef SBA_COLLECT_STATS sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, total_pages - ioc->used_pages, ioc->used_pages, @@ -1949,7 +2006,7 @@ static struct parisc_driver sba_driver = { }; /* -** Determine if lba should claim this chip (return 0) or not (return 1). +** Determine if sba should claim this chip (return 0) or not (return 1). ** If so, initialize the chip and tell other partners in crime they ** have work to do. */ @@ -2062,17 +2119,95 @@ void __init sba_init(void) * sba_get_iommu - Assign the iommu pointer for the pci bus controller. * @dev: The parisc device. * - * This function searches through the registerd IOMMU's and returns the - * appropriate IOMMU data for the given parisc PCI controller. + * Returns the appropriate IOMMU data for the given parisc PCI controller. + * This is cached and used later for PCI DMA Mapping. */ void * sba_get_iommu(struct parisc_device *pci_hba) { - struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata; - char t = pci_hba->parent->id.hw_type; + struct parisc_device *sba_dev = parisc_parent(pci_hba); + struct sba_device *sba = sba_dev->dev.driver_data; + char t = sba_dev->id.hw_type; int iocnum = (pci_hba->hw_path >> 3); /* rope # */ + BUG_ON((t != HPHW_IOA) && (t != HPHW_BCPORT)); + + return &(sba->ioc[iocnum]); +} + + +/** + * sba_directed_lmmio - return first directed LMMIO range routed to rope + * @pa_dev: The parisc device. + * @r: resource PCI host controller wants start/end fields assigned. + * + * For the given parisc PCI controller, determine if any direct ranges + * are routed down the corresponding rope. + */ +void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r) +{ + struct parisc_device *sba_dev = parisc_parent(pci_hba); + struct sba_device *sba = sba_dev->dev.driver_data; + char t = sba_dev->id.hw_type; + int i; + int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ + if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT)) BUG(); - return &(sba->ioc[iocnum]); + r->start = r->end = 0; + + /* Astro has 4 directed ranges. Not sure about Ike/Pluto/et al */ + for (i=0; i<4; i++) { + int base, size; + unsigned long reg = sba->sba_hpa + i*0x18; + + base = READ_REG32(reg + LMMIO_DIRECT0_BASE); + if ((base & 1) == 0) + continue; /* not enabled */ + + size = READ_REG32(reg + LMMIO_DIRECT0_ROUTE); + + if ((size & (ROPES_PER_IOC-1)) != rope) + continue; /* directed down different rope */ + + r->start = (base & ~1UL) | PCI_F_EXTEND; + size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK); + r->end = r->start + size; + } +} + + +/** + * sba_distributed_lmmio - return portion of distributed LMMIO range + * @pa_dev: The parisc device. + * @r: resource PCI host controller wants start/end fields assigned. + * + * For the given parisc PCI controller, return portion of distributed LMMIO + * range. The distributed LMMIO is always present and it's just a question + * of the base address and size of the range. + */ +void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r ) +{ + struct parisc_device *sba_dev = parisc_parent(pci_hba); + struct sba_device *sba = sba_dev->dev.driver_data; + char t = sba_dev->id.hw_type; + int base, size; + int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */ + + if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT)) + BUG(); + + r->start = r->end = 0; + + base = READ_REG32(sba->sba_hpa + LMMIO_DIST_BASE); + if ((base & 1) == 0) { + BUG(); /* Gah! Distr Range wasn't enabled! */ + return; + } + + r->start = (base & ~1UL) | PCI_F_EXTEND; + + size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC; + r->start += rope * (size + 1); /* adjust base for this rope */ + r->end = r->start + size; } diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 6357ec10e..2441bab78 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -8,7 +8,7 @@ * (C) Copyright 2000 Linuxcare, Inc. * (C) Copyright 2000 Linuxcare Canada, Inc. * (C) Copyright 2000 Martin K. Petersen - * (C) Copyright 2000 Alex deVries + * (C) Copyright 2000 Alex deVries * (C) Copyright 2001 John Marvin * (C) Copyright 2003 Grant Grundler * @@ -69,15 +69,12 @@ #include #include #include -#include #include #include #include #include -#define SUPERIO_IDE_MAX_RETRIES 25 - static struct superio_device sio_dev; @@ -101,16 +98,20 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs) results = inb(IC_PIC1+0); + /* + * Bit 7: 1 = active Interrupt; 0 = no Interrupt pending + * Bits 6-3: zero + * Bits 2-0: highest priority, active requesting interrupt ID (0-7) + */ if ((results & 0x80) == 0) { -#ifndef CONFIG_SMP - /* HACK: need to investigate why this happens if SMP enabled */ - BUG(); /* This shouldn't happen */ -#endif + /* I suspect "spurious" interrupts are from unmasking an IRQ. + * We don't know if an interrupt was/is pending and thus + * just call the handler for that IRQ as if it were pending. + */ return IRQ_HANDLED; } /* Check to see which device is interrupting */ - local_irq = results & 0x0f; if (local_irq == 2 || local_irq > 7) { @@ -136,8 +137,9 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs) sio->irq_region->data.irqbase + local_irq, regs); - /* set EOI */ - + /* set EOI - forces a new interrupt if a lower priority device + * still needs service. + */ outb((OCW2_SEOI|local_irq),IC_PIC1 + 0); return IRQ_HANDLED; } @@ -469,11 +471,6 @@ superio_parport_init(void) } -static u8 superio_ide_inb (unsigned long port); -static unsigned long superio_ide_status[2]; -static unsigned long superio_ide_select[2]; -static unsigned long superio_ide_dma_status[2]; - void superio_fixup_pci(struct pci_dev *pdev) { u8 prog; @@ -484,57 +481,8 @@ void superio_fixup_pci(struct pci_dev *pdev) pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog); printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog); } +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); -/* Because of a defect in Super I/O, all reads of the PCI DMA status - * registers, IDE status register and the IDE select register need to be - * retried - */ -static u8 superio_ide_inb (unsigned long port) -{ - if (port == superio_ide_status[0] || - port == superio_ide_status[1] || - port == superio_ide_select[0] || - port == superio_ide_select[1] || - port == superio_ide_dma_status[0] || - port == superio_ide_dma_status[1]) { - u8 tmp; - int retries = SUPERIO_IDE_MAX_RETRIES; - - /* printk(" [ reading port 0x%x with retry ] ", port); */ - - do { - tmp = inb(port); - if (tmp == 0) - udelay(50); - } while (tmp == 0 && retries-- > 0); - - return tmp; - } - - return inb(port); -} - -void __init superio_ide_init_iops (struct hwif_s *hwif) -{ - u32 base, dmabase; - u8 tmp; - struct pci_dev *pdev = hwif->pci_dev; - u8 port = hwif->channel; - - base = pci_resource_start(pdev, port * 2) & ~3; - dmabase = pci_resource_start(pdev, 4) & ~3; - - superio_ide_status[port] = base + IDE_STATUS_OFFSET; - superio_ide_select[port] = base + IDE_SELECT_OFFSET; - superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); - - /* Clear error/interrupt, enable dma */ - tmp = superio_ide_inb(superio_ide_dma_status[port]); - outb(tmp | 0x66, superio_ide_dma_status[port]); - - /* We need to override inb to workaround a SuperIO errata */ - hwif->INB = superio_ide_inb; -} static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 156e46af7..db8fe4c49 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -34,7 +34,7 @@ config PARPORT config PARPORT_PC tristate "PC-style hardware" - depends on PARPORT && (!SPARC64 || PCI) + depends on PARPORT && (!SPARC64 || PCI) && (!SPARC32 || BROKEN) ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index 9f4f5f476..b07e0a329 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c @@ -207,8 +207,7 @@ void parport_daisy_fini (struct parport *port) * * This function is similar to parport_register_device(), except * that it locates a device by its number rather than by the port - * it is attached to. See parport_find_device() and - * parport_find_class(). + * it is attached to. * * All parameters except for @devnum are the same as for * parport_register_device(). The return value is the same as @@ -305,53 +304,6 @@ int parport_device_num (int parport, int mux, int daisy) return res; } -/** - * parport_device_coords - convert canonical device number - * @devnum: device number - * @parport: pointer to storage for parallel port number - * @mux: pointer to storage for multiplexor port number - * @daisy: pointer to storage for daisy chain address - * - * This function converts a device number into its coordinates in - * terms of which parallel port in the system it is attached to, - * which multiplexor port it is attached to if there is a - * multiplexor on that port, and which daisy chain address it has - * if it is in a daisy chain. - * - * The caller must allocate storage for @parport, @mux, and - * @daisy. - * - * If there is no device with the specified device number, -ENXIO - * is returned. Otherwise, the values pointed to by @parport, - * @mux, and @daisy are set to the coordinates of the device, - * with -1 for coordinates with no value. - * - * This function is not actually very useful, but this interface - * was suggested by IEEE 1284.3. - **/ - -int parport_device_coords (int devnum, int *parport, int *mux, int *daisy) -{ - struct daisydev *dev; - - spin_lock(&topology_lock); - - dev = topology; - while (dev && dev->devnum != devnum) - dev = dev->next; - - if (!dev) { - spin_unlock(&topology_lock); - return -ENXIO; - } - - if (parport) *parport = dev->port->portnum; - if (mux) *mux = dev->port->muxport; - if (daisy) *daisy = dev->daisy; - spin_unlock(&topology_lock); - return 0; -} - /* Send a daisy-chain-style CPP command packet. */ static int cpp_daisy (struct parport *port, int cmd) { @@ -558,108 +510,3 @@ static int assign_addrs (struct parport *port) kfree (deviceid); return detected; } - -/* Find a device with a particular manufacturer and model string, - starting from a given device number. Like the PCI equivalent, - 'from' itself is skipped. */ - -/** - * parport_find_device - find a specific device - * @mfg: required manufacturer string - * @mdl: required model string - * @from: previous device number found in search, or %NULL for - * new search - * - * This walks through the list of parallel port devices looking - * for a device whose 'MFG' string matches @mfg and whose 'MDL' - * string matches @mdl in their IEEE 1284 Device ID. - * - * When a device is found matching those requirements, its device - * number is returned; if there is no matching device, a negative - * value is returned. - * - * A new search it initiated by passing %NULL as the @from - * argument. If @from is not %NULL, the search continues from - * that device. - **/ - -int parport_find_device (const char *mfg, const char *mdl, int from) -{ - struct daisydev *d; - int res = -1; - - /* Find where to start. */ - - spin_lock(&topology_lock); - d = topology; /* sorted by devnum */ - while (d && d->devnum <= from) - d = d->next; - - /* Search. */ - while (d) { - struct parport_device_info *info; - info = &d->port->probe_info[1 + d->daisy]; - if ((!mfg || !strcmp (mfg, info->mfr)) && - (!mdl || !strcmp (mdl, info->model))) - break; - - d = d->next; - } - - if (d) - res = d->devnum; - - spin_unlock(&topology_lock); - return res; -} - -/** - * parport_find_class - find a device in a specified class - * @cls: required class - * @from: previous device number found in search, or %NULL for - * new search - * - * This walks through the list of parallel port devices looking - * for a device whose 'CLS' string matches @cls in their IEEE - * 1284 Device ID. - * - * When a device is found matching those requirements, its device - * number is returned; if there is no matching device, a negative - * value is returned. - * - * A new search it initiated by passing %NULL as the @from - * argument. If @from is not %NULL, the search continues from - * that device. - **/ - -int parport_find_class (parport_device_class cls, int from) -{ - struct daisydev *d; - int res = -1; - - spin_lock(&topology_lock); - d = topology; /* sorted by devnum */ - /* Find where to start. */ - while (d && d->devnum <= from) - d = d->next; - - /* Search. */ - while (d && d->port->probe_info[1 + d->daisy].class != cls) - d = d->next; - - if (d) - res = d->devnum; - - spin_unlock(&topology_lock); - return res; -} - -EXPORT_SYMBOL(parport_open); -EXPORT_SYMBOL(parport_close); -EXPORT_SYMBOL(parport_device_num); -EXPORT_SYMBOL(parport_device_coords); -EXPORT_SYMBOL(parport_daisy_deselect_all); -EXPORT_SYMBOL(parport_daisy_select); -EXPORT_SYMBOL(parport_daisy_init); -EXPORT_SYMBOL(parport_find_device); -EXPORT_SYMBOL(parport_find_class); diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 950b78e7c..a1bd5416d 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -40,7 +40,7 @@ /* Make parport_wait_peripheral wake up. * It will be useful to call this from an interrupt handler. */ -void parport_ieee1284_wakeup (struct parport *port) +static void parport_ieee1284_wakeup (struct parport *port) { up (&port->physport->ieee1284.irq); } @@ -813,9 +813,7 @@ long parport_set_timeout (struct pardevice *dev, long inactivity) EXPORT_SYMBOL(parport_negotiate); EXPORT_SYMBOL(parport_write); EXPORT_SYMBOL(parport_read); -EXPORT_SYMBOL(parport_ieee1284_wakeup); EXPORT_SYMBOL(parport_wait_peripheral); -EXPORT_SYMBOL(parport_poll_peripheral); EXPORT_SYMBOL(parport_wait_event); EXPORT_SYMBOL(parport_set_timeout); EXPORT_SYMBOL(parport_ieee1284_interrupt); diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index dfc8a8404..6db242a9f 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -62,6 +62,7 @@ #include #include +#include #include #define PARPORT_PC_MAX_PORTS PARPORT_MAX @@ -1403,6 +1404,9 @@ static void __devinit winbond_check(int io, int key) { int devid,devrev,oldid,x_devid,x_devrev,x_oldid; + if (!request_region(io, 3, __FUNCTION__)) + return; + /* First probe without key */ outb(0x20,io); x_devid=inb(io+1); @@ -1423,15 +1427,20 @@ static void __devinit winbond_check(int io, int key) outb(0xaa,io); /* Magic Seal */ if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) - return; /* protection against false positives */ + goto out; /* protection against false positives */ decode_winbond(io,key,devid,devrev,oldid); +out: + release_region(io, 3); } static void __devinit winbond_check2(int io,int key) { int devid,devrev,oldid,x_devid,x_devrev,x_oldid; + if (!request_region(io, 3, __FUNCTION__)) + return; + /* First probe without the key */ outb(0x20,io+2); x_devid=inb(io+2); @@ -1451,15 +1460,20 @@ static void __devinit winbond_check2(int io,int key) outb(0xaa,io); /* Magic Seal */ if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) - return; /* protection against false positives */ + goto out; /* protection against false positives */ - decode_winbond(io,key,devid,devrev,oldid); + decode_winbond(io,key,devid,devrev,oldid); +out: + release_region(io, 3); } static void __devinit smsc_check(int io, int key) { int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev; + if (!request_region(io, 3, __FUNCTION__)) + return; + /* First probe without the key */ outb(0x0d,io); x_oldid=inb(io+1); @@ -1485,9 +1499,11 @@ static void __devinit smsc_check(int io, int key) if ((x_id == id) && (x_oldrev == oldrev) && (x_oldid == oldid) && (x_rev == rev)) - return; /* protection against false positives */ + goto out; /* protection against false positives */ decode_smsc(io,key,oldid,oldrev); +out: + release_region(io, 3); } @@ -2363,7 +2379,7 @@ EXPORT_SYMBOL (parport_pc_unregister_port); /* ITE support maintained by Rich Liu */ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, - int autodma) + int autodma, struct parport_pc_via_data *via) { short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 }; struct resource *base_res; @@ -2466,71 +2482,161 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, return 0; } -/* Via support maintained by Jeff Garzik */ -static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq, - int autodma) +/* VIA 8231 support by Pavel Fedin + based on VIA 686a support code by Jeff Garzik */ +static int __initdata parport_init_mode = 0; + +/* Data for two known VIA chips */ +static struct parport_pc_via_data via_686a_data __devinitdata = { + 0x51, + 0x50, + 0x85, + 0x02, + 0xE2, + 0xF0, + 0xE6 +}; +static struct parport_pc_via_data via_8231_data __devinitdata = { + 0x45, + 0x44, + 0x50, + 0x04, + 0xF2, + 0xFA, + 0xF6 +}; + +static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, + int autodma, struct parport_pc_via_data *via) { - u8 tmp; + u8 tmp, tmp2, siofunc; + u8 ppcontrol = 0; int dma, irq; - unsigned port1, port2, have_eppecp; + unsigned port1, port2; + unsigned have_epp = 0; + + printk(KERN_DEBUG "parport_pc: VIA 686A/8231 detected\n"); + switch(parport_init_mode) + { + case 1: + printk(KERN_DEBUG "parport_pc: setting SPP mode\n"); + siofunc = VIA_FUNCTION_PARPORT_SPP; + break; + case 2: + printk(KERN_DEBUG "parport_pc: setting PS/2 mode\n"); + siofunc = VIA_FUNCTION_PARPORT_SPP; + ppcontrol = VIA_PARPORT_BIDIR; + break; + case 3: + printk(KERN_DEBUG "parport_pc: setting EPP mode\n"); + siofunc = VIA_FUNCTION_PARPORT_EPP; + ppcontrol = VIA_PARPORT_BIDIR; + have_epp = 1; + break; + case 4: + printk(KERN_DEBUG "parport_pc: setting ECP mode\n"); + siofunc = VIA_FUNCTION_PARPORT_ECP; + ppcontrol = VIA_PARPORT_BIDIR; + break; + case 5: + printk(KERN_DEBUG "parport_pc: setting EPP+ECP mode\n"); + siofunc = VIA_FUNCTION_PARPORT_ECP; + ppcontrol = VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP; + have_epp = 1; + break; + default: + printk(KERN_DEBUG "parport_pc: probing current configuration\n"); + siofunc = VIA_FUNCTION_PROBE; + break; + } /* - * unlock super i/o configuration, set 0x85_1 - */ - pci_read_config_byte (pdev, 0x85, &tmp); - tmp |= (1 << 1); - pci_write_config_byte (pdev, 0x85, tmp); - - /* - * Super I/O configuration, index port == 3f0h, data port == 3f1h + * unlock super i/o configuration */ + pci_read_config_byte(pdev, via->via_pci_superio_config_reg, &tmp); + tmp |= via->via_pci_superio_config_data; + pci_write_config_byte(pdev, via->via_pci_superio_config_reg, tmp); + + /* Bits 1-0: Parallel Port Mode / Enable */ + outb(via->viacfg_function, VIA_CONFIG_INDEX); + tmp = inb (VIA_CONFIG_DATA); + /* Bit 5: EPP+ECP enable; bit 7: PS/2 bidirectional port enable */ + outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); + tmp2 = inb (VIA_CONFIG_DATA); + if (siofunc == VIA_FUNCTION_PROBE) + { + siofunc = tmp & VIA_FUNCTION_PARPORT_DISABLE; + ppcontrol = tmp2; + } + else + { + tmp &= ~VIA_FUNCTION_PARPORT_DISABLE; + tmp |= siofunc; + outb(via->viacfg_function, VIA_CONFIG_INDEX); + outb(tmp, VIA_CONFIG_DATA); + tmp2 &= ~(VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP); + tmp2 |= ppcontrol; + outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); + outb(tmp2, VIA_CONFIG_DATA); + } - /* 0xE2_1-0: Parallel Port Mode / Enable */ - outb (0xE2, 0x3F0); - tmp = inb (0x3F1); + /* Parallel Port I/O Base Address, bits 9-2 */ + outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); + port1 = inb(VIA_CONFIG_DATA) << 2; - if ((tmp & 0x03) == 0x03) { - printk (KERN_INFO "parport_pc: Via 686A parallel port disabled in BIOS\n"); + printk (KERN_DEBUG "parport_pc: Current parallel port base: 0x%X\n",port1); + if ((port1 == 0x3BC) && have_epp) + { + outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); + outb((0x378 >> 2), VIA_CONFIG_DATA); + printk(KERN_DEBUG "parport_pc: Parallel port base changed to 0x378\n"); + port1 = 0x378; + } + + /* + * lock super i/o configuration + */ + pci_read_config_byte(pdev, via->via_pci_superio_config_reg, &tmp); + tmp &= ~via->via_pci_superio_config_data; + pci_write_config_byte(pdev, via->via_pci_superio_config_reg, tmp); + + if (siofunc == VIA_FUNCTION_PARPORT_DISABLE) { + printk(KERN_INFO "parport_pc: VIA parallel port disabled in BIOS\n"); return 0; } - /* 0xE6: Parallel Port I/O Base Address, bits 9-2 */ - outb (0xE6, 0x3F0); - port1 = inb (0x3F1) << 2; - + /* Bits 7-4: PnP Routing for Parallel Port IRQ */ + pci_read_config_byte(pdev, via->via_pci_parport_irq_reg, &tmp); + irq = ((tmp & VIA_IRQCONTROL_PARALLEL) >> 4); + + if (siofunc == VIA_FUNCTION_PARPORT_ECP) + { + /* Bits 3-2: PnP Routing for Parallel Port DMA */ + pci_read_config_byte(pdev, via->via_pci_parport_dma_reg, &tmp); + dma = ((tmp & VIA_DMACONTROL_PARALLEL) >> 2); + } + else + /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */ + dma = PARPORT_DMA_NONE; + + /* Let the user (or defaults) steer us away from interrupts and DMA */ + if (autoirq == PARPORT_IRQ_NONE) { + irq = PARPORT_IRQ_NONE; + dma = PARPORT_DMA_NONE; + } + if (autodma == PARPORT_DMA_NONE) + dma = PARPORT_DMA_NONE; + switch (port1) { case 0x3bc: port2 = 0x7bc; break; case 0x378: port2 = 0x778; break; case 0x278: port2 = 0x678; break; default: - printk (KERN_INFO "parport_pc: Weird Via 686A parport base 0x%X, ignoring\n", + printk(KERN_INFO "parport_pc: Weird VIA parport base 0x%X, ignoring\n", port1); return 0; } - /* 0xF0_5: EPP+ECP enable */ - outb (0xF0, 0x3F0); - have_eppecp = (inb (0x3F1) & (1 << 5)); - - /* - * lock super i/o configuration, clear 0x85_1 - */ - pci_read_config_byte (pdev, 0x85, &tmp); - tmp &= ~(1 << 1); - pci_write_config_byte (pdev, 0x85, tmp); - - /* - * Get DMA and IRQ from PCI->ISA bridge PCI config registers - */ - - /* 0x50_3-2: PnP Routing for Parallel Port DRQ */ - pci_read_config_byte (pdev, 0x50, &tmp); - dma = ((tmp >> 2) & 0x03); - - /* 0x51_7-4: PnP Routing for Parallel Port IRQ */ - pci_read_config_byte (pdev, 0x51, &tmp); - irq = ((tmp >> 4) & 0x0F); - /* filter bogus IRQs */ switch (irq) { case 0: @@ -2544,22 +2650,10 @@ static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq, break; } - /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */ - if (!have_eppecp) - dma = PARPORT_DMA_NONE; - - /* Let the user (or defaults) steer us away from interrupts and DMA */ - if (autoirq != PARPORT_IRQ_AUTO) { - irq = PARPORT_IRQ_NONE; - dma = PARPORT_DMA_NONE; - } - if (autodma != PARPORT_DMA_AUTO) - dma = PARPORT_DMA_NONE; - /* finally, do the probe with values obtained */ if (parport_pc_probe_port (port1, port2, irq, dma, NULL)) { printk (KERN_INFO - "parport_pc: Via 686A parallel port: io=0x%X", port1); + "parport_pc: VIA parallel port: io=0x%X", port1); if (irq != PARPORT_IRQ_NONE) printk (", irq=%d", irq); if (dma != PARPORT_DMA_NONE) @@ -2568,7 +2662,7 @@ static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq, return 1; } - printk (KERN_WARNING "parport_pc: Strange, can't probe Via 686A parallel port: io=0x%X, irq=%d, dma=%d\n", + printk(KERN_WARNING "parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n", port1, irq, dma); return 0; } @@ -2576,19 +2670,21 @@ static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq, enum parport_pc_sio_types { sio_via_686a = 0, /* Via VT82C686A motherboard Super I/O */ + sio_via_8231, /* Via VT8231 south bridge integrated Super IO */ sio_ite_8872, last_sio }; /* each element directly indexed from enum list, above */ static struct parport_pc_superio { - int (*probe) (struct pci_dev *pdev, int autoirq, int autodma); + int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via); + struct parport_pc_via_data *via; } parport_pc_superio_info[] __devinitdata = { - { sio_via_686a_probe, }, - { sio_ite_8872_probe, }, + { sio_via_probe, &via_686a_data, }, + { sio_via_probe, &via_8231_data, }, + { sio_ite_8872_probe, NULL, }, }; - enum parport_pc_pci_cards { siig_1p_10x = last_sio, siig_2p_10x, @@ -2636,6 +2732,10 @@ enum parport_pc_pci_cards { netmos_9805, netmos_9815, netmos_9855, + netmos_9735, + netmos_9835, + netmos_9755, + netmos_9715 }; @@ -2709,11 +2809,16 @@ static struct parport_pc_pci { /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ /* netmos_9855 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ + /* netmos_9735 */ { 1, { { 2, 3 }, } }, /* untested */ + /* netmos_9835 */ { 1, { { 2, 3 }, } }, /* untested */ + /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ + /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ }; static struct pci_device_id parport_pc_pci_tbl[] = { /* Super-IO onboard chips */ { 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a }, + { 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 }, { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_ite_8872 }, @@ -2786,6 +2891,14 @@ static struct pci_device_id parport_pc_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9755 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9715, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9715 }, { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); @@ -2855,7 +2968,7 @@ static int __init parport_pc_init_superio (int autoirq, int autodma) continue; if (parport_pc_superio_info[id->driver_data].probe - (pdev, autoirq, autodma)) { + (pdev, autoirq, autodma,parport_pc_superio_info[id->driver_data].via)) { ret++; } } @@ -2935,7 +3048,7 @@ static struct pnp_driver parport_pc_pnp_driver = { /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */ -static int __init __attribute__((unused)) +static int __devinit __attribute__((unused)) parport_pc_find_isa_ports (int autoirq, int autodma) { int count = 0; @@ -2985,10 +3098,10 @@ static int __init parport_pc_find_ports (int autoirq, int autodma) count += parport_pc_find_nonpci_ports (autoirq, autodma); r = pci_register_driver (&parport_pc_pci_driver); - if (r >= 0) { - pci_registered_parport = 1; - count += r; - } + if (r) + return r; + pci_registered_parport = 1; + count += 1; return count; } @@ -3041,22 +3154,46 @@ static int __init parport_parse_dma(const char *dmastr, int *val) PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); } +#ifdef CONFIG_PCI +static int __init parport_init_mode_setup(char *str) +{ + printk(KERN_DEBUG "parport_pc.c: Specified parameter parport_init_mode=%s\n", str); + + if (!strcmp (str, "spp")) + parport_init_mode=1; + if (!strcmp (str, "ps2")) + parport_init_mode=2; + if (!strcmp (str, "epp")) + parport_init_mode=3; + if (!strcmp (str, "ecp")) + parport_init_mode=4; + if (!strcmp (str, "ecpepp")) + parport_init_mode=5; + return 1; +} +#endif + #ifdef MODULE static const char *irq[PARPORT_PC_MAX_PORTS]; static const char *dma[PARPORT_PC_MAX_PORTS]; +static char *init_mode; MODULE_PARM_DESC(io, "Base I/O address (SPP regs)"); -MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i"); +module_param_array(io, int, NULL, 0); MODULE_PARM_DESC(io_hi, "Base I/O address (ECR)"); -MODULE_PARM(io_hi, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i"); +module_param_array(io_hi, int, NULL, 0); MODULE_PARM_DESC(irq, "IRQ line"); -MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s"); +module_param_array(irq, charp, NULL, 0); MODULE_PARM_DESC(dma, "DMA channel"); -MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s"); +module_param_array(dma, charp, NULL, 0); #if defined(CONFIG_PARPORT_PC_SUPERIO) || \ (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO)) MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation"); -MODULE_PARM(verbose_probing, "i"); +module_param(verbose_probing, int, 0644); +#endif +#ifdef CONFIG_PCI +MODULE_PARM_DESC(init_mode, "Initialise mode for VIA VT8231 port (spp, ps2, epp, ecp or ecpepp)"); +MODULE_PARM(init_mode, "s"); #endif static int __init parse_parport_params(void) @@ -3064,6 +3201,11 @@ static int __init parse_parport_params(void) unsigned int i; int val; +#ifdef CONFIG_PCI + if (init_mode) + parport_init_mode_setup(init_mode); +#endif + for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) { if (parport_parse_irq(irq[i], &val)) return 1; @@ -3171,6 +3313,15 @@ static int __init parse_parport_params(void) } __setup ("parport=", parport_setup); + +/* + * Acceptable parameters: + * + * parport_init_mode=[spp|ps2|epp|ecp|ecpepp] + */ +#ifdef CONFIG_PCI +__setup("parport_init_mode=",parport_init_mode_setup); +#endif #endif /* "Parser" ends here */ diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index c7a7e06dd..13b9b6068 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -52,7 +52,7 @@ static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_reg static void parport_sunbpp_disable_irq(struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; u32 tmp; tmp = sbus_readl(®s->p_csr); @@ -62,7 +62,7 @@ static void parport_sunbpp_disable_irq(struct parport *p) static void parport_sunbpp_enable_irq(struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; u32 tmp; tmp = sbus_readl(®s->p_csr); @@ -72,7 +72,7 @@ static void parport_sunbpp_enable_irq(struct parport *p) static void parport_sunbpp_write_data(struct parport *p, unsigned char d) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; sbus_writeb(d, ®s->p_dr); dprintk((KERN_DEBUG "wrote 0x%x\n", d)); @@ -80,7 +80,7 @@ static void parport_sunbpp_write_data(struct parport *p, unsigned char d) static unsigned char parport_sunbpp_read_data(struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; return sbus_readb(®s->p_dr); } @@ -88,7 +88,7 @@ static unsigned char parport_sunbpp_read_data(struct parport *p) #if 0 static void control_pc_to_sunbpp(struct parport *p, unsigned char status) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; unsigned char value_tcr = sbus_readb(®s->p_tcr); unsigned char value_or = sbus_readb(®s->p_or); @@ -108,7 +108,7 @@ static void control_pc_to_sunbpp(struct parport *p, unsigned char status) static unsigned char status_sunbpp_to_pc(struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; unsigned char bits = 0; unsigned char value_tcr = sbus_readb(®s->p_tcr); unsigned char value_ir = sbus_readb(®s->p_ir); @@ -131,7 +131,7 @@ static unsigned char status_sunbpp_to_pc(struct parport *p) static unsigned char control_sunbpp_to_pc(struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; unsigned char bits = 0; unsigned char value_tcr = sbus_readb(®s->p_tcr); unsigned char value_or = sbus_readb(®s->p_or); @@ -159,7 +159,7 @@ static unsigned char parport_sunbpp_frob_control(struct parport *p, unsigned char mask, unsigned char val) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; unsigned char value_tcr = sbus_readb(®s->p_tcr); unsigned char value_or = sbus_readb(®s->p_or); @@ -216,7 +216,7 @@ static unsigned char parport_sunbpp_read_status(struct parport *p) static void parport_sunbpp_data_forward (struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; unsigned char value_tcr = sbus_readb(®s->p_tcr); dprintk((KERN_DEBUG "forward\n")); @@ -226,7 +226,7 @@ static void parport_sunbpp_data_forward (struct parport *p) static void parport_sunbpp_data_reverse (struct parport *p) { - struct bpp_regs *regs = (struct bpp_regs *)p->base; + struct bpp_regs __iomem *regs = (struct bpp_regs __iomem *)p->base; u8 val = sbus_readb(®s->p_tcr); dprintk((KERN_DEBUG "reverse\n")); @@ -299,9 +299,9 @@ static int __init init_one_port(struct sbus_dev *sdev) struct parport *p; /* at least in theory there may be a "we don't dma" case */ struct parport_operations *ops; - unsigned long base; + void __iomem *base; int irq, dma, err = 0, size; - struct bpp_regs *regs; + struct bpp_regs __iomem *regs; unsigned char value_tcr; Node *node; @@ -328,7 +328,7 @@ static int __init init_one_port(struct sbus_dev *sdev) memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port\n")); - if (!(p = parport_register_port(base, irq, dma, ops))) + if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) goto out3; p->size = size; @@ -343,7 +343,7 @@ static int __init init_one_port(struct sbus_dev *sdev) dprintk(("OK\n")); parport_sunbpp_enable_irq(p); - regs = (struct bpp_regs *)p->base; + regs = (struct bpp_regs __iomem *)p->base; dprintk((KERN_DEBUG "forward\n")); value_tcr = sbus_readb(®s->p_tcr); value_tcr &= ~P_TCR_DIR; @@ -395,7 +395,7 @@ static void __exit parport_sunbpp_exit(void) parport_sunbpp_disable_irq(p); free_irq(p->irq, p); } - sbus_iounmap(p->base, p->size); + sbus_iounmap((void __iomem *)p->base, p->size); parport_put_port(p); kfree (ops); list_del(&node->list); diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index a360928ba..339dd7802 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c @@ -213,4 +213,3 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len) parport_close (dev); return retval; } -EXPORT_SYMBOL(parport_device_id); diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index 061097fd8..cbe17184b 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -529,8 +529,5 @@ static void __exit parport_default_proc_unregister (void) } #endif -EXPORT_SYMBOL(parport_device_proc_register); -EXPORT_SYMBOL(parport_device_proc_unregister); - module_init(parport_default_proc_register) module_exit(parport_default_proc_unregister) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index ea655dbdf..5bce27150 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -1007,7 +1007,6 @@ EXPORT_SYMBOL(parport_register_driver); EXPORT_SYMBOL(parport_unregister_driver); EXPORT_SYMBOL(parport_register_device); EXPORT_SYMBOL(parport_unregister_device); -EXPORT_SYMBOL(parport_get_port); EXPORT_SYMBOL(parport_put_port); EXPORT_SYMBOL(parport_find_number); EXPORT_SYMBOL(parport_find_base); diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 377c7238c..9410012d7 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -3,7 +3,8 @@ # obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ - names.o pci-driver.o search.o pci-sysfs.o + names.o pci-driver.o search.o pci-sysfs.o \ + rom.o obj-$(CONFIG_PROC_FS) += proc.o ifndef CONFIG_SPARC64 @@ -28,6 +29,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_PCI_MSI) += msi.o +# +# ACPI Related PCI FW Functions +# +obj-$(CONFIG_ACPI) += pci-acpi.o + # Cardbus & CompactPCI use setup-bus obj-$(CONFIG_HOTPLUG) += setup-bus.o @@ -35,7 +41,7 @@ ifndef CONFIG_X86 obj-y += syscall.o endif -host-progs := gen-devlist +hostprogs-y := gen-devlist # Dependencies on generated files need to be listed explicitly $(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index e94a854c4..dbd33605c 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -68,6 +68,25 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, return ret; } +/** + * add a single device + * @dev: device to add + * + * This adds a single pci device to the global + * device list and adds sysfs and procfs entries + */ +void __devinit pci_bus_add_device(struct pci_dev *dev) +{ + device_add(&dev->dev); + + spin_lock(&pci_bus_lock); + list_add_tail(&dev->global_list, &pci_devices); + spin_unlock(&pci_bus_lock); + + pci_proc_attach_device(dev); + pci_create_sysfs_dev_files(dev); +} + /** * pci_bus_add_devices - insert newly discovered PCI devices * @bus: bus to check for new devices @@ -91,16 +110,7 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) */ if (!list_empty(&dev->global_list)) continue; - - device_add(&dev->dev); - - spin_lock(&pci_bus_lock); - list_add_tail(&dev->global_list, &pci_devices); - spin_unlock(&pci_bus_lock); - - pci_proc_attach_device(dev); - pci_create_sysfs_dev_files(dev); - + pci_bus_add_device(dev); } list_for_each_entry(dev, &bus->devices, bus_list) { @@ -136,5 +146,6 @@ void pci_enable_bridges(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_alloc_resource); +EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL(pci_bus_add_devices); EXPORT_SYMBOL(pci_enable_bridges); diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 3dc99c18a..9117a95a3 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -88,6 +88,18 @@ config HOTPLUG_PCI_ACPI When in doubt, say N. +config HOTPLUG_PCI_ACPI_IBM + tristate "ACPI PCI Hotplug driver IBM extensions" + depends on HOTPLUG_PCI_ACPI + help + Say Y here if you have an IBM system that supports PCI Hotplug using + ACPI. + + To compile this driver as a module, choose M here: the + module will be called acpiphp_ibm. + + When in doubt, say N. + config HOTPLUG_PCI_CPCI bool "CompactPCI Hotplug driver" depends on HOTPLUG_PCI diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index a972757a0..93c120ddb 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o +obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o @@ -50,7 +51,6 @@ rpadlpar_io-objs := rpadlpar_core.o \ pciehp-objs := pciehp_core.o \ pciehp_ctrl.o \ pciehp_pci.o \ - pciehp_sysfs.o \ pciehp_hpc.o ifdef CONFIG_ACPI_BUS pciehp-objs += pciehprm_acpi.o diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 670c874fe..d9499874c 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -171,6 +171,18 @@ struct acpiphp_func { struct pci_resource *bus_head; }; +/** + * struct acpiphp_attention_info - device specific attention registration + * + * ACPI has no generic method of setting/getting attention status + * this allows for device specific driver registration + */ +struct acpiphp_attention_info +{ + int (*set_attn)(struct hotplug_slot *slot, u8 status); + int (*get_attn)(struct hotplug_slot *slot, u8 *status); + struct module *owner; +}; /* PCI bus bridge HID */ #define ACPI_PCI_HOST_HID "PNP0A03" @@ -212,6 +224,10 @@ struct acpiphp_func { /* function prototypes */ +/* acpiphp_core.c */ +extern int acpiphp_register_attention(struct acpiphp_attention_info*info); +extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); + /* acpiphp_glue.c */ extern int acpiphp_glue_init (void); extern void acpiphp_glue_exit (void); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index fb4155ad7..4539e61a3 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -51,6 +51,7 @@ int acpiphp_debug; /* local variables */ static int num_slots; +static struct acpiphp_attention_info *attention_info; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Takayoshi Kochi " @@ -60,12 +61,17 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); + +/* export the attention callback registration methods */ +EXPORT_SYMBOL_GPL(acpiphp_register_attention); +EXPORT_SYMBOL_GPL(acpiphp_unregister_attention); static int enable_slot (struct hotplug_slot *slot); static int disable_slot (struct hotplug_slot *slot); static int set_attention_status (struct hotplug_slot *slot, u8 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_address (struct hotplug_slot *slot, u32 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); @@ -76,11 +82,54 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { .disable_slot = disable_slot, .set_attention_status = set_attention_status, .get_power_status = get_power_status, + .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, .get_address = get_address, }; + +/** + * acpiphp_register_attention - set attention LED callback + * @info: must be completely filled with LED callbacks + * + * Description: this is used to register a hardware specific ACPI + * driver that manipulates the attention LED. All the fields in + * info must be set. + **/ +int acpiphp_register_attention(struct acpiphp_attention_info *info) +{ + int retval = -EINVAL; + + if (info && info->owner && info->set_attn && + info->get_attn && !attention_info) { + retval = 0; + attention_info = info; + } + return retval; +} + + +/** + * acpiphp_unregister_attention - unset attention LED callback + * @info: must match the pointer used to register + * + * Description: this is used to un-register a hardware specific acpi + * driver that manipulates the attention LED. The pointer to the + * info struct must be the same as the one used to set it. + **/ +int acpiphp_unregister_attention(struct acpiphp_attention_info *info) +{ + int retval = -EINVAL; + + if (info && attention_info == info) { + attention_info = NULL; + retval = 0; + } + return retval; +} + + /** * enable_slot - power on and enable a slot * @hotplug_slot: slot to enable @@ -117,33 +166,29 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) } -/** - * set_attention_status - set attention LED + /** + * set_attention_status - set attention LED + * @hotplug_slot: slot to set attention LED on + * @status: value to set attention LED to (0 or 1) * - * TBD: - * ACPI doesn't have known method to manipulate - * attention status LED. - * - */ -static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) -{ - dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - - switch (status) { - case 0: - /* FIXME turn light off */ - hotplug_slot->info->attention_status = 0; - break; - - case 1: - default: - /* FIXME turn light on */ - hotplug_slot->info->attention_status = 1; - break; - } - - return 0; -} + * attention status LED, so we use a callback that + * was registered with us. This allows hardware specific + * ACPI implementations to blink the light for us. + **/ + static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) + { + int retval = -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + if (attention_info && try_module_get(attention_info->owner)) { + retval = attention_info->set_attn(hotplug_slot, status); + module_put(attention_info->owner); + } else + attention_info = NULL; + return retval; + } + /** * get_power_status - get power status of a slot @@ -165,6 +210,32 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) return 0; } + + /** + * get_attention_status - get attention LED status + * @hotplug_slot: slot to get status from + * @value: returns with value of attention LED + * + * ACPI doesn't have known method to determine the state + * of the attention status LED, so we use a callback that + * was registered with us. This allows hardware specific + * ACPI implementations to determine its state + **/ +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) +{ + int retval = -EINVAL; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + if (attention_info && try_module_get(attention_info->owner)) { + retval = attention_info->get_attn(hotplug_slot, value); + module_put(attention_info->owner); + } else + attention_info = NULL; + return retval; +} + + /** * get_latch_status - get latch status of a slot * @hotplug_slot: slot to get status @@ -307,7 +378,7 @@ static int __init init_slots(void) slot->acpi_slot = get_slot_from_id(i); slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); - slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot); + slot->hotplug_slot->info->attention_status = 0; slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index d41795bb6..e7f41294f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -389,7 +389,7 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus) bridge->pci_bus = pci_find_bus(seg, bus); - bridge->res_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&bridge->res_lock); /* to be overridden when we decode _CRS */ bridge->sub = bridge->bus; @@ -457,7 +457,7 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f return; } - bridge->res_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&bridge->res_lock); bridge->bus = bridge->pci_bus->number; bridge->sub = bridge->pci_bus->subordinate; @@ -1301,20 +1301,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) } -/* - * attention LED ON: 1 - * OFF: 0 - * - * TBD - * no direct attention led status information via ACPI - * - */ -u8 acpiphp_get_attention_status(struct acpiphp_slot *slot) -{ - return 0; -} - - /* * latch closed: 1 * latch open: 0 diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index fe7866c1c..aced66166 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -64,6 +64,8 @@ do { \ #define IBM_HARDWARE_ID1 "IBM37D0" #define IBM_HARDWARE_ID2 "IBM37D4" +#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun) + /* union apci_descriptor - allows access to the * various device descriptors that are embedded in the * aPCI table @@ -84,6 +86,7 @@ union apci_descriptor { u8 attn; u8 status[2]; u8 sun; + u8 res[3]; } slot; struct { u8 type; @@ -128,6 +131,43 @@ static struct acpiphp_attention_info ibm_attention_info = .owner = THIS_MODULE, }; +/** + * ibm_slot_from_id - workaround for bad ibm hardware + * @id: the slot number that linux refers to the slot by + * + * Description: this method returns the aCPI slot descriptor + * corresponding to the Linux slot number. This descriptor + * has info about the aPCI slot id and attention status. + * This descriptor must be freed using kfree when done. + **/ +static union apci_descriptor *ibm_slot_from_id(int id) +{ + int ind = 0, size; + union apci_descriptor *ret = NULL, *des; + char *table; + + size = ibm_get_table_from_acpi(&table); + des = (union apci_descriptor *)table; + if (memcmp(des->header.sig, "aPCI", 4) != 0) + goto ibm_slot_done; + + des = (union apci_descriptor *)&table[ind += des->header.len]; + while (ind < size && (des->generic.type != 0x82 || + des->slot.slot_num != id)) { + des = (union apci_descriptor *)&table[ind += des->generic.len]; + } + + if (ind < size && des->slot.slot_num == id) + ret = des; + +ibm_slot_done: + if (ret) { + ret = kmalloc(sizeof(union apci_descriptor), GFP_KERNEL); + memcpy(ret, des, sizeof(union apci_descriptor)); + } + kfree(table); + return ret; +} /** * ibm_set_attention_status - callback method to set the attention LED @@ -139,32 +179,34 @@ static struct acpiphp_attention_info ibm_attention_info = **/ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) { - int retval = 0; union acpi_object args[2]; struct acpi_object_list params = { .pointer = args, .count = 2 }; acpi_status stat; - unsigned long rc = 0; - struct acpiphp_slot *acpi_slot; + unsigned long rc; + union apci_descriptor *ibm_slot; - acpi_slot = ((struct slot *)(slot->private))->acpi_slot; + ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); - dbg("%s: set slot %d attention status to %d\n", __FUNCTION__, - acpi_slot->sun, (status ? 1 : 0)); + dbg("%s: set slot %d (%d) attention status to %d\n", __FUNCTION__, + ibm_slot->slot.slot_num, ibm_slot->slot.slot_id, + (status ? 1 : 0)); args[0].type = ACPI_TYPE_INTEGER; - args[0].integer.value = acpi_slot->sun; + args[0].integer.value = ibm_slot->slot.slot_id; args[1].type = ACPI_TYPE_INTEGER; args[1].integer.value = (status) ? 1 : 0; + kfree(ibm_slot); + stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", ¶ms, &rc); if (ACPI_FAILURE(stat)) { - retval = -ENODEV; err("APLS evaluation failed: 0x%08x\n", stat); + return -ENODEV; } else if (!rc) { - retval = -ERANGE; err("APLS method failed: 0x%08lx\n", rc); + return -ERANGE; } - return retval; + return 0; } /** @@ -181,38 +223,21 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) **/ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) { - int retval = -EINVAL, ind = 0, size; - char *table = NULL; - struct acpiphp_slot *acpi_slot; - union apci_descriptor *des; + union apci_descriptor *ibm_slot; - acpi_slot = ((struct slot *)(slot->private))->acpi_slot; + ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); - size = ibm_get_table_from_acpi(&table); - if (size <= 0 || !table) - goto get_attn_done; - // read the header - des = (union apci_descriptor *)&table[ind]; - if (memcmp(des->header.sig, "aPCI", 4) != 0) - goto get_attn_done; - des = (union apci_descriptor *)&table[ind += des->header.len]; - while (ind < size && (des->generic.type != 0x82 || - des->slot.slot_id != acpi_slot->sun)) - des = (union apci_descriptor *)&table[ind += des->generic.len]; - if (ind < size && des->slot.slot_id == acpi_slot->sun) { - retval = 0; - if (des->slot.attn & 0xa0 || des->slot.status[1] & 0x08) - *status = 1; - else - *status = 0; - } + if (ibm_slot->slot.attn & 0xa0 || ibm_slot->slot.status[1] & 0x08) + *status = 1; + else + *status = 0; - dbg("%s: get slot %d attention status is %d retval=%x\n", - __FUNCTION__, acpi_slot->sun, *status, retval); + dbg("%s: get slot %d (%d) attention status is %d\n", __FUNCTION__, + ibm_slot->slot.slot_num, ibm_slot->slot.slot_id, + *status); -get_attn_done: - kfree(table); - return retval; + kfree(ibm_slot); + return 0; } /** diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 868623fd6..ed243605d 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "pci_hotplug.h" #include "cpci_hotplug.h" @@ -513,11 +514,10 @@ event_thread(void *data) break; while(controller->ops->query_enum()) { rc = check_slots(); - if(rc > 0) { + if (rc > 0) /* Give userspace a chance to handle extraction */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 2); - } else if(rc < 0) { + msleep(500); + else if (rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; @@ -568,11 +568,10 @@ poll_thread(void *data) while(controller->ops->query_enum()) { rc = check_slots(); - if(rc > 0) { + if(rc > 0) /* Give userspace a chance to handle extraction */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 2); - } else if(rc < 0) { + msleep(500); + else if (rc < 0) { dbg("%s - error checking slots", __FUNCTION__); thread_finished = 1; break; @@ -595,8 +594,7 @@ poll_thread(void *data) } } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + msleep(100); } dbg("poll thread signals exit"); up(&thread_exit); diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index 141941ae3..ef4f598ab 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c @@ -63,7 +63,7 @@ /* local variables */ static int debug; -static char* bridge; +static char *bridge; static u8 bridge_busnr; static u8 bridge_slot; static struct pci_bus *bus; @@ -209,15 +209,15 @@ module_exit(cpcihp_generic_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -MODULE_PARM(bridge, "s"); +module_param(bridge, charp, 0); MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, : (bus and slot are in hexadecimal)"); -MODULE_PARM(first_slot, "b"); +module_param(first_slot, byte, 0); MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number"); -MODULE_PARM(last_slot, "b"); +module_param(last_slot, byte, 0); MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number"); -MODULE_PARM(port, "h"); +module_param(port, ushort, 0); MODULE_PARM_DESC(port, "#ENUM signal I/O port"); -MODULE_PARM(enum_bit, "i"); +module_param(enum_bit, uint, 0); MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)"); diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index cb54fa8ab..e9928024b 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -69,11 +69,11 @@ static struct pci_bus *bus0; static struct pci_dev *hc_dev; /* Host controller register addresses */ -static void *hc_registers; -static void *csr_hc_index; -static void *csr_hc_data; -static void *csr_int_status; -static void *csr_int_mask; +static void __iomem *hc_registers; +static void __iomem *csr_hc_index; +static void __iomem *csr_hc_data; +static void __iomem *csr_int_status; +static void __iomem *csr_int_mask; static int zt5550_hc_config(struct pci_dev *pdev) @@ -219,12 +219,13 @@ static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id dbg("registered controller"); /* Look for first device matching cPCI bus's bridge vendor and device IDs */ - if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC, + if(!(bus0_dev = pci_get_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21154, NULL))) { status = -ENODEV; goto init_register_error; } bus0 = bus0_dev->subordinate; + pci_dev_put(bus0_dev); status = cpci_hp_register_bus(bus0, 0x0a, 0x0f); if(status != 0) { @@ -282,7 +283,7 @@ static int __init zt5550_init(void) if(!r) return -EBUSY; - return pci_module_init(&zt5550_hc_driver); + return pci_register_driver(&zt5550_hc_driver); } static void __exit @@ -298,7 +299,7 @@ module_exit(zt5550_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(poll, bool, 644); +module_param(poll, bool, 0644); MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not"); diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 4da5bac0f..092491e25 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -268,7 +268,7 @@ struct slot { struct timer_list task_event; u8 hp_slot; struct controller *ctrl; - void *p_sm_slot; + void __iomem *p_sm_slot; struct hotplug_slot *hotplug_slot; }; @@ -287,7 +287,7 @@ 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 */ + void __iomem *hpc_reg; /* cookie for our pci controller location */ struct pci_resource *mem_head; struct pci_resource *p_mem_head; struct pci_resource *io_head; @@ -405,7 +405,7 @@ extern void cpqhp_create_ctrl_files (struct controller *ctrl); /* controller functions */ extern void cpqhp_pushbutton_thread (unsigned long event_pointer); extern irqreturn_t cpqhp_ctrl_intr (int IRQ, void *data, struct pt_regs *regs); -extern int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start); +extern int cpqhp_find_available_resources (struct controller *ctrl, void __iomem *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); @@ -707,9 +707,8 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) dbg("%s - start\n", __FUNCTION__); 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); + msleep_interruptible(1000); remove_wait_queue(&ctrl->queue, &wait); if (signal_pending(current)) retval = -EINTR; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index aa8a1a4d7..24e0699ab 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -55,9 +55,9 @@ 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 void __iomem *smbios_table; +static void __iomem *smbios_start; +static void __iomem *cpqhp_rom_start; static int power_mode; static int debug; @@ -69,10 +69,10 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(power_mode, bool, 644); +module_param(power_mode, bool, 0644); MODULE_PARM_DESC(power_mode, "Power mode enabled or not"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); #define CPQHPC_MODULE_MINOR 208 @@ -123,10 +123,10 @@ static inline int is_slot66mhz(struct slot *slot) * Returns pointer to the head of the SMBIOS tables (or NULL) * */ -static void * detect_SMBIOS_pointer(void *begin, void *end) +static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) { - void *fp; - void *endp; + void __iomem *fp; + void __iomem *endp; u8 temp1, temp2, temp3, temp4; int status = 0; @@ -232,13 +232,14 @@ static int pci_print_IRQ_route (void) * * 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) +static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, + void __iomem *smbios_table, + void __iomem *curr) { u8 bail = 0; u8 previous_byte = 1; - void *p_temp; - void *p_max; + void __iomem *p_temp; + void __iomem *p_max; if (!smbios_table || !curr) return(NULL); @@ -282,8 +283,10 @@ static void *get_subsequent_smbios_entry(void *smbios_start, * * 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) +static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, + void __iomem *smbios_table, + u8 type, + void __iomem *previous) { if (!smbios_table) return NULL; @@ -319,8 +322,9 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } -static int ctrl_slot_setup(struct controller * ctrl, void *smbios_start, - void *smbios_table) +static int ctrl_slot_setup(struct controller *ctrl, + void __iomem *smbios_start, + void __iomem *smbios_table) { struct slot *new_slot; u8 number_of_slots; @@ -328,7 +332,7 @@ static int ctrl_slot_setup(struct controller * ctrl, void *smbios_start, u8 slot_number; u8 ctrl_slot; u32 tempdword; - void *slot_entry= NULL; + void __iomem *slot_entry= NULL; int result = -ENOMEM; dbg("%s\n", __FUNCTION__); @@ -1483,8 +1487,8 @@ static int __init cpqhpc_init(void) cpqhp_debug = debug; info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); - result = pci_module_init(&cpqhpc_driver); - dbg("pci_module_init = %d\n", result); + result = pci_register_driver(&cpqhpc_driver); + dbg("pci_register_driver = %d\n", result); return result; } diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 7073a4aeb..10a5a7674 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -69,10 +69,8 @@ static void long_delay(int delay) init_waitqueue_head(&delay_wait); add_wait_queue(&delay_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(delay); + msleep_interruptible(jiffies_to_msecs(delay)); remove_wait_queue(&delay_wait, &wait); - set_current_state(TASK_RUNNING); up(&delay_sem); } diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index 8cf4bd38a..ac98a11bd 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c @@ -92,7 +92,7 @@ static u8 evbuffer_init; static u8 evbuffer_length; static u8 evbuffer[1024]; -static void *compaq_int15_entry_point; +static void __iomem *compaq_int15_entry_point; static spinlock_t int15_lock; /* lock for ordering int15_bios_call() */ @@ -141,7 +141,7 @@ static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail) * * returns 0 for non-Compaq ROM, 1 for Compaq ROM */ -static int check_for_compaq_ROM (void *rom_start) +static int check_for_compaq_ROM (void __iomem *rom_start) { u8 temp1, temp2, temp3, temp4, temp5, temp6; int result = 0; @@ -197,7 +197,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size) * * Read the hot plug Resource Table from NVRAM */ -static int load_HRT (void *rom_start) +static int load_HRT (void __iomem *rom_start) { u32 available; u32 temp_dword; @@ -231,7 +231,7 @@ static int load_HRT (void *rom_start) * * Save the hot plug Resource Table in NVRAM */ -static u32 store_HRT (void *rom_start) +static u32 store_HRT (void __iomem *rom_start) { u32 *buffer; u32 *pFill; @@ -423,7 +423,7 @@ static u32 store_HRT (void *rom_start) } -void compaq_nvram_init (void *rom_start) +void compaq_nvram_init (void __iomem *rom_start) { if (rom_start) { compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); @@ -435,7 +435,7 @@ void compaq_nvram_init (void *rom_start) } -int compaq_nvram_load (void *rom_start, struct controller *ctrl) +int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) { u8 bus, device, function; u8 nummem, numpmem, numio, numbus; @@ -648,7 +648,7 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) } -int compaq_nvram_store (void *rom_start) +int compaq_nvram_store (void __iomem *rom_start) { int rc = 1; diff --git a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h index 9ed417bbb..e89c07021 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.h +++ b/drivers/pci/hotplug/cpqphp_nvram.h @@ -30,26 +30,26 @@ #ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM -static inline void compaq_nvram_init (void *rom_start) +static inline void compaq_nvram_init (void __iomem *rom_start) { return; } -static inline int compaq_nvram_load (void *rom_start, struct controller *ctrl) +static inline int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) { return 0; } -static inline int compaq_nvram_store (void *rom_start) +static inline int compaq_nvram_store (void __iomem *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); +extern void compaq_nvram_init (void __iomem *rom_start); +extern int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl); +extern int compaq_nvram_store (void __iomem *rom_start); #endif diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index bde394f72..225973d86 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -51,10 +51,10 @@ static u16 unused_IRQ; * find the Hot Plug Resource Table in the specified region of memory. * */ -static void *detect_HRT_floating_pointer(void *begin, void *end) +static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iomem *end) { - void *fp; - void *endp; + void __iomem *fp; + void __iomem *endp; u8 temp1, temp2, temp3, temp4; int status = 0; @@ -194,7 +194,7 @@ static int PCI_ScanBusNonBridge (u8 bus, u8 device) static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num) { - u8 tdevice; + u16 tdevice; u32 work; u8 tbus; @@ -1162,12 +1162,13 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) * * returns 0 if success */ -int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start) +int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_start) { u8 temp; u8 populated_slot; u8 bridged_slot; - void *one_slot; + void __iomem *one_slot; + void __iomem *rom_resource_table; struct pci_func *func = NULL; int i = 10, index; u32 temp_dword, rc; @@ -1175,7 +1176,6 @@ int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start) 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); diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 845379538..7cf086a55 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -165,14 +165,123 @@ static void remove_slot(struct dummy_slot *dslot) err("Problem unregistering a slot %s\n", dslot->slot->name); } +/** + * Rescan slot. + * Tries hard not to re-enable already existing devices + * also handles scanning of subfunctions + * + * @param temp Device template. Should be set: bus and devfn. + */ +static void pci_rescan_slot(struct pci_dev *temp) +{ + struct pci_bus *bus = temp->bus; + struct pci_dev *dev; + int func; + u8 hdr_type; + if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { + temp->hdr_type = hdr_type & 0x7f; + if (!pci_find_slot(bus->number, temp->devfn)) { + dev = pci_scan_single_device(bus, temp->devfn); + if (dev) { + dbg("New device on %s function %x:%x\n", + bus->name, temp->devfn >> 3, + temp->devfn & 7); + pci_bus_add_device(dev); + add_slot(dev); + } + } + /* multifunction device? */ + if (!(hdr_type & 0x80)) + return; + + /* continue scanning for other functions */ + for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { + if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) + continue; + temp->hdr_type = hdr_type & 0x7f; + + if (!pci_find_slot(bus->number, temp->devfn)) { + dev = pci_scan_single_device(bus, temp->devfn); + if (dev) { + dbg("New device on %s function %x:%x\n", + bus->name, temp->devfn >> 3, + temp->devfn & 7); + pci_bus_add_device(dev); + add_slot(dev); + } + } + } + } +} + + +/** + * Rescan PCI bus. + * call pci_rescan_slot for each possible function of the bus + * + * @param bus + */ +static void pci_rescan_bus(const struct pci_bus *bus) +{ + unsigned int devfn; + struct pci_dev *dev; + dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!dev) + return; + + memset(dev, 0, sizeof(dev)); + dev->bus = (struct pci_bus*)bus; + dev->sysdata = bus->sysdata; + for (devfn = 0; devfn < 0x100; devfn += 8) { + dev->devfn = devfn; + pci_rescan_slot(dev); + } + kfree(dev); +} + +/* recursively scan all buses */ +static void pci_rescan_buses(const struct list_head *list) +{ + const struct list_head *l; + list_for_each(l,list) { + const struct pci_bus *b = pci_bus_b(l); + pci_rescan_bus(b); + pci_rescan_buses(&b->children); + } +} + +/* initiate rescan of all pci buses */ +static inline void pci_rescan(void) { + pci_rescan_buses(&pci_root_buses); +} + + static int enable_slot(struct hotplug_slot *hotplug_slot) { + /* mis-use enable_slot for rescanning of the pci bus */ + pci_rescan(); return -ENODEV; } +/* find the hotplug_slot for the pci_dev */ +static struct hotplug_slot *get_slot_from_dev(struct pci_dev *dev) +{ + struct dummy_slot *dslot; + + list_for_each_entry(dslot, &slot_list, node) { + if (dslot->dev == dev) + return dslot->slot; + } + return NULL; +} + + static int disable_slot(struct hotplug_slot *slot) { struct dummy_slot *dslot; + struct hotplug_slot *hslot; + struct pci_dev *dev; + int func; if (!slot) return -ENODEV; @@ -185,6 +294,23 @@ static int disable_slot(struct hotplug_slot *slot) err("Can't remove PCI devices with other PCI devices behind it yet.\n"); return -ENODEV; } + /* search for subfunctions and disable them first */ + if (!(dslot->dev->devfn & 7)) { + for (func = 1; func < 8; func++) { + dev = pci_find_slot(dslot->dev->bus->number, + dslot->dev->devfn + func); + if (dev) { + hslot = get_slot_from_dev(dev); + if (hslot) + disable_slot(hslot); + else { + err("Hotplug slot not found for subfunction of PCI device\n"); + return -ENODEV; + } + } else + dbg("No device in slot found\n"); + } + } /* remove the device from the pci core */ pci_remove_bus_device(dslot->dev); @@ -227,6 +353,6 @@ module_exit(dummyphp_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); +module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index b24b8cd45..b42346b02 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -759,11 +759,5 @@ extern int ibmphp_configure_card (struct pci_func *, u8); extern int ibmphp_unconfigure_card (struct slot **, int); extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops; -static inline void long_delay (int delay) -{ - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout (delay); -} - #endif //__IBMPHP_H diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 89354eb0a..048e7ea0e 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -51,7 +51,7 @@ int ibmphp_debug; static int debug; -MODULE_PARM (debug, "i"); +module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC (debug, "Debugging mode enabled or not"); MODULE_LICENSE ("GPL"); MODULE_DESCRIPTION (DRIVER_DESC); @@ -190,7 +190,7 @@ static inline int power_on (struct slot *slot_cur) err ("command not completed successfully in power_on\n"); return -EIO; } - long_delay (3 * HZ); /* For ServeRAID cards, and some 66 PCI */ + msleep(3000); /* For ServeRAID cards, and some 66 PCI */ return 0; } @@ -838,8 +838,11 @@ static int set_bus (struct slot * slot_cur) int rc; u8 speed; u8 cmd = 0x0; - struct pci_dev *dev = NULL; int retval; + static struct pci_device_id ciobx[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) }, + { }, + }; debug ("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number); if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) { @@ -886,8 +889,7 @@ static int set_bus (struct slot * slot_cur) break; case BUS_SPEED_133: /* This is to take care of the bug in CIOBX chip */ - while ((dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, - 0x0101, dev)) != NULL) + if (pci_dev_present(ciobx)) ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE); cmd = HPC_BUS_133PCIXMODE; break; @@ -913,7 +915,7 @@ static int set_bus (struct slot * slot_cur) } /* This is for x440, once Brandon fixes the firmware, will not need this delay */ - long_delay (1 * HZ); + msleep(1000); debug ("%s -Exit\n", __FUNCTION__); return 0; } diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index 470e9afc0..aea1187c7 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -63,7 +63,7 @@ static LIST_HEAD (rio_vg_head); static LIST_HEAD (rio_lo_head); static LIST_HEAD (opt_vg_head); static LIST_HEAD (opt_lo_head); -static void *io_mem; +static void __iomem *io_mem; /* Local functions */ static int ebda_rsrc_controller (void); @@ -1246,7 +1246,7 @@ int ibmphp_register_pci (void) list_for_each (tmp, &ebda_hpc_head) { ctrl = list_entry (tmp, struct controller, ebda_hpc_list); if (ctrl->ctlr_type == 1) { - rc = pci_module_init (&ibmphp_driver); + rc = pci_register_driver(&ibmphp_driver); break; } } diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index 105dc70e6..6894b548c 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -107,8 +108,8 @@ static struct semaphore sem_exit; // make sure polling thread goes away //---------------------------------------------------------------------------- // local function prototypes //---------------------------------------------------------------------------- -static u8 i2c_ctrl_read (struct controller *, void *, u8); -static u8 i2c_ctrl_write (struct controller *, void *, u8, u8); +static u8 i2c_ctrl_read (struct controller *, void __iomem *, u8); +static u8 i2c_ctrl_write (struct controller *, void __iomem *, u8, u8); static u8 hpc_writecmdtoindex (u8, u8); static u8 hpc_readcmdtoindex (u8, u8); static void get_hpc_access (void); @@ -117,7 +118,7 @@ static void poll_hpc (void); static int process_changeinstatus (struct slot *, struct slot *); static int process_changeinlatch (u8, u8, struct controller *); static int hpc_poll_thread (void *); -static int hpc_wait_ctlr_notworking (int, struct controller *, void *, u8 *); +static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u8 *); //---------------------------------------------------------------------------- @@ -146,11 +147,11 @@ void __init ibmphp_hpc_initvars (void) * Action: read from HPC over I2C * *---------------------------------------------------------------------*/ -static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) +static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index) { u8 status; int i; - void *wpg_addr; // base addr + offset + void __iomem *wpg_addr; // base addr + offset unsigned long wpg_data; // data to/from WPG LOHI format unsigned long ultemp; unsigned long data; // actual data HILO format @@ -205,7 +206,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) // READ - step 4 : wait until start operation bit clears i = CMD_COMPLETE_TOUT_SEC; while (i) { - long_delay (1 * HZ / 100); + msleep(10); wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); @@ -221,7 +222,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) // READ - step 5 : read I2C status register i = CMD_COMPLETE_TOUT_SEC; while (i) { - long_delay (1 * HZ / 100); + msleep(10); wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); @@ -254,10 +255,10 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) * * Return 0 or error codes *---------------------------------------------------------------------*/ -static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd) +static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index, u8 cmd) { u8 rc; - void *wpg_addr; // base addr + offset + void __iomem *wpg_addr; // base addr + offset unsigned long wpg_data; // data to/from WPG LOHI format unsigned long ultemp; unsigned long data; // actual data HILO format @@ -316,7 +317,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, // WRITE - step 4 : wait until start operation bit clears i = CMD_COMPLETE_TOUT_SEC; while (i) { - long_delay (1 * HZ / 100); + msleep(10); wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); @@ -333,7 +334,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, // WRITE - step 5 : read I2C status register i = CMD_COMPLETE_TOUT_SEC; while (i) { - long_delay (1 * HZ / 100); + msleep(10); wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); @@ -398,7 +399,7 @@ static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data) return rc; } -static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset) +static u8 ctrl_read (struct controller *ctlr, void __iomem *base, u8 offset) { u8 rc; switch (ctlr->ctlr_type) { @@ -418,7 +419,7 @@ static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset) return rc; } -static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data) +static u8 ctrl_write (struct controller *ctlr, void __iomem *base, u8 offset, u8 data) { u8 rc = 0; switch (ctlr->ctlr_type) { @@ -535,7 +536,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index) *---------------------------------------------------------------------*/ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) { - void *wpg_bbar = NULL; + void __iomem *wpg_bbar = NULL; struct controller *ctlr_ptr; struct list_head *pslotlist; u8 index, status; @@ -659,7 +660,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) // remove physical to logical address mapping if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) - iounmap (wpg_bbar); + iounmap (wpg_bbar); free_hpc_access (); @@ -674,7 +675,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) *---------------------------------------------------------------------*/ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) { - void *wpg_bbar = NULL; + void __iomem *wpg_bbar = NULL; struct controller *ctlr_ptr; u8 index, status; int busindex; @@ -748,7 +749,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) done = TRUE; } if (!done) { - long_delay (1 * HZ); + msleep(1000); if (timeout < 1) { done = TRUE; err ("%s - Error command complete timeout\n", __FUNCTION__); @@ -763,7 +764,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) // remove physical to logical address mapping if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) - iounmap (wpg_bbar); + iounmap (wpg_bbar); free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); @@ -891,7 +892,7 @@ static void poll_hpc (void) case POLL_SLEEP: /* don't sleep with a lock on the hardware */ up (&semOperations); - long_delay (POLL_INTERVAL_SEC * HZ); + msleep(POLL_INTERVAL_SEC * 1000); if (ibmphp_shutdown) break; @@ -908,8 +909,7 @@ static void poll_hpc (void) /* give up the harware semaphore */ up (&semOperations); /* sleep for a short time just for good measure */ - set_current_state (TASK_INTERRUPTIBLE); - schedule_timeout (HZ/10); + msleep(100); } up (&sem_exit); debug ("%s - Exit\n", __FUNCTION__); @@ -974,7 +974,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot) if (SLOT_PWRGD (pslot->status)) { // power goes on and off after closing latch // check again to make sure power is still ON - long_delay (1 * HZ); + msleep(1000); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) update = TRUE; @@ -1130,7 +1130,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void) * Return 0, HPC_ERROR * Value: *---------------------------------------------------------------------*/ -static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void *wpg_bbar, +static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar, u8 * pstatus) { int rc = 0; @@ -1147,7 +1147,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) done = TRUE; if (!done) { - long_delay (1 * HZ); + msleep(1000); if (timeout < 1) { done = TRUE; err ("HPCreadslot - Error ctlr timeout\n"); diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 039213c29..906fd9b3f 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -568,7 +568,7 @@ int pci_hp_register (struct hotplug_slot *slot) if ((slot->info == NULL) || (slot->ops == NULL)) return -EINVAL; - kobject_set_name(&slot->kobj, slot->name); + kobject_set_name(&slot->kobj, "%s", slot->name); kobj_set_kset_s(slot, pci_hotplug_slots_subsys); /* this can fail if we have already registered a slot with the same name */ @@ -701,7 +701,7 @@ module_exit(pci_hotplug_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys); diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index b1504c7c1..c6ce70a87 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include "pci_hotplug.h" @@ -126,8 +127,7 @@ struct controller { enum pci_bus_speed speed; u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ u8 slot_bus; /* Bus where the slots handled by this controller sit */ - u8 push_flag; - u16 ctlrcap; + u8 ctrlcap; u16 vendor_id; }; @@ -179,6 +179,21 @@ struct resource_lists { #define DISABLE_CARD 1 +/* Field definitions in Slot Capabilities Register */ +#define ATTN_BUTTN_PRSN 0x00000001 +#define PWR_CTRL_PRSN 0x00000002 +#define MRL_SENS_PRSN 0x00000004 +#define ATTN_LED_PRSN 0x00000008 +#define PWR_LED_PRSN 0x00000010 +#define HP_SUPR_RM_SUP 0x00000020 + +#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) +#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) +#define MRL_SENS(cap) (cap & MRL_SENS_PRSN) +#define ATTN_LED(cap) (cap & ATTN_LED_PRSN) +#define PWR_LED(cap) (cap & PWR_LED_PRSN) +#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) + /* * error Messages */ @@ -192,9 +207,6 @@ struct resource_lists { #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" -/* sysfs function for the hotplug controller info */ -extern void pciehp_create_ctrl_files (struct controller *ctrl); - /* controller functions */ extern int pciehprm_find_available_resources (struct controller *ctrl); extern int pciehp_event_start_thread (void); @@ -261,14 +273,12 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl) dbg("%s : start\n", __FUNCTION__); add_wait_queue(&ctrl->queue, &wait); - set_current_state(TASK_INTERRUPTIBLE); - if (!pciehp_poll_mode) { + if (!pciehp_poll_mode) /* Sleep for up to 1 second */ - schedule_timeout(1*HZ); - } else - schedule_timeout(2.5*HZ); + msleep_interruptible(1000); + else + msleep_interruptible(2500); - set_current_state(TASK_RUNNING); remove_wait_queue(&ctrl->queue, &wait); if (signal_pending(current)) retval = -EINTR; @@ -313,8 +323,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, int *first_device_num, int *physical_slot_num, - int *updown, - int *flags); + u8 *ctrlcap); struct hpc_ops { int (*power_on_slot) (struct slot *slot); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index b31ccbcea..cb8569e0b 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -57,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(pciehp_debug, bool, 644); -module_param(pciehp_poll_mode, bool, 644); -module_param(pciehp_poll_time, int, 644); +module_param(pciehp_debug, bool, 0644); +module_param(pciehp_poll_mode, bool, 0644); +module_param(pciehp_poll_time, int, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); @@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ int first_device_num; /* Not needed */ int physical_slot_num; - int updown; /* Not needed */ + u8 ctrlcap; int rc; - int flags; /* Not needed */ - rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap); if (rc) { err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); return (-1); @@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ ctrl->slot_device_offset = first_device_num; ctrl->first_slot = physical_slot_num; - ctrl->slot_num_inc = updown; /* Not needed */ /* either -1 or 1 */ + ctrl->ctrlcap = ctrlcap; - dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", - __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, + dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n", + __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap, ctrl->bus, ctrl->device); return (0); @@ -237,7 +236,9 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); hotplug_slot->info->attention_status = status; - slot->hpc_ops->set_attention_status(slot, status); + + if (ATTN_LED(slot->ctrl->ctrlcap)) + slot->hpc_ops->set_attention_status(slot, status); return 0; } @@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ dbg("%s: adpater value %x\n", __FUNCTION__, value); - if (!value) { + + if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ @@ -602,8 +604,8 @@ static int __init pcied_init(void) retval = pciehprm_init(PCI); if (!retval) { - retval = pci_module_init(&pcie_driver); - dbg("pci_module_init = %d\n", retval); + retval = pci_register_driver(&pcie_driver); + dbg("pci_register_driver = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 2015af915..279f53d78 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -38,6 +38,7 @@ #include #include #include +#include "../pci.h" #include "pciehp.h" #include "pciehprm.h" @@ -51,6 +52,7 @@ static struct semaphore event_semaphore; /* mutex for process loop (up if someth static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ static int event_finished; static unsigned long pushbutton_pending; /* = 0 */ +static unsigned long surprise_rm_pending; /* = 0 */ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) { @@ -1063,25 +1065,29 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* turn off slot, turn on Amber LED, turn off Green LED */ - if (pslot->hpc_ops->power_off_slot(pslot)) { - err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return; + /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ + if (POWER_CTRL(ctrl->ctrlcap)) { + if (pslot->hpc_ops->power_off_slot(pslot)) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); } - wait_for_ctrl_irq (ctrl); - pslot->hpc_ops->green_led_off(pslot); - - wait_for_ctrl_irq (ctrl); + if (PWR_LED(ctrl->ctrlcap)) { + pslot->hpc_ops->green_led_off(pslot); + wait_for_ctrl_irq (ctrl); + } - /* turn on Amber LED */ - if (pslot->hpc_ops->set_attention_status(pslot, 1)) { - err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return; + if (ATTN_LED(ctrl->ctrlcap)) { + if (pslot->hpc_ops->set_attention_status(pslot, 1)) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return; + } + wait_for_ctrl_irq (ctrl); } - wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1112,20 +1118,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* Power on slot */ - rc = p_slot->hpc_ops->power_on_slot(p_slot); - if (rc) { - up(&ctrl->crit_sect); - return -1; - } + if (POWER_CTRL(ctrl->ctrlcap)) { + /* Power on slot */ + rc = p_slot->hpc_ops->power_on_slot(p_slot); + if (rc) { + up(&ctrl->crit_sect); + return -1; + } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - p_slot->hpc_ops->green_led_blink(p_slot); + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_blink(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1212,18 +1222,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) } } while (new_func); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - + /* + * Some PCI Express root ports require fixup after hot-plug operation. + */ + if (pcie_mch_quirk) + pci_fixup_device(pci_fixup_final, ctrl->pci_dev); + + if (PWR_LED(ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } } else { set_slot_off(ctrl, p_slot); return -1; @@ -1289,21 +1305,25 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* power off slot */ - rc = p_slot->hpc_ops->power_off_slot(p_slot); - if (rc) { - err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return rc; + if (POWER_CTRL(ctrl->ctrlcap)) { + /* power off slot */ + rc = p_slot->hpc_ops->power_off_slot(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); } - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - /* turn off Green LED */ - p_slot->hpc_ops->green_led_off(p_slot); + if (PWR_LED(ctrl->ctrlcap)) { + /* turn off Green LED */ + p_slot->hpc_ops->green_led_off(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1368,7 +1388,6 @@ static void pushbutton_helper_thread(unsigned long data) up(&event_semaphore); } - /** * pciehp_pushbutton_thread * @@ -1399,7 +1418,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) p_slot->state = POWERON_STATE; dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); - if (pciehp_enable_slot(p_slot)) { + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ down(&p_slot->ctrl->crit_sect); @@ -1417,6 +1436,55 @@ static void pciehp_pushbutton_thread(unsigned long slot) return; } +/** + * pciehp_surprise_rm_thread + * + * Scheduled procedure to handle blocking stuff for the surprise removal + * Handles all pending events and exits. + * + */ +static void pciehp_surprise_rm_thread(unsigned long slot) +{ + struct slot *p_slot = (struct slot *) slot; + u8 getstatus; + + surprise_rm_pending = 0; + + if (!p_slot) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return; + } + + p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (!getstatus) { + p_slot->state = POWEROFF_STATE; + dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + pciehp_disable_slot(p_slot); + p_slot->state = STATIC_STATE; + } else { + p_slot->state = POWERON_STATE; + dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } + + return; +} + + /* this is the main worker thread */ static int event_thread(void* data) @@ -1436,6 +1504,8 @@ static int event_thread(void* data) /* Do stuff here */ if (pushbutton_pending) pciehp_pushbutton_thread(pushbutton_pending); + else if (surprise_rm_pending) + pciehp_surprise_rm_thread(surprise_rm_pending); else for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) interrupt_event_handler(ctrl); @@ -1528,16 +1598,18 @@ static void interrupt_event_handler(struct controller *ctrl) case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - - p_slot->hpc_ops->green_led_on(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - + + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_on(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); break; @@ -1545,14 +1617,16 @@ static void interrupt_event_handler(struct controller *ctrl) /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - p_slot->hpc_ops->green_led_off(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)){ + p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } /* Done with exclusive hardware access */ up(&ctrl->crit_sect); @@ -1566,59 +1640,83 @@ static void interrupt_event_handler(struct controller *ctrl) } /* ***********Button Pressed (No action on 1st press...) */ else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { - dbg("Button pressed\n"); - - p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (getstatus) { - /* 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); - } + + if (ATTN_BUTTN(ctrl->ctrlcap)) { + dbg("Button pressed\n"); + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + /* 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); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); - /* blink green LED and turn off amber */ - p_slot->hpc_ops->green_led_blink(p_slot); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* blink green LED and turn off amber */ + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_blink(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 0); - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); - init_timer(&p_slot->task_event); - p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ - p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; - p_slot->task_event.data = (unsigned long) p_slot; + init_timer(&p_slot->task_event); + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ + p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; + p_slot->task_event.data = (unsigned long) p_slot; - dbg("add_timer p_slot = %p\n", (void *) p_slot); - add_timer(&p_slot->task_event); + dbg("add_timer p_slot = %p\n", (void *) 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"); - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); + if (POWER_CTRL(ctrl->ctrlcap)) { + dbg("power fault\n"); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); - p_slot->hpc_ops->set_attention_status(p_slot, 1); - wait_for_ctrl_irq (ctrl); - - p_slot->hpc_ops->green_led_off(p_slot); - wait_for_ctrl_irq (ctrl); + if (ATTN_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->set_attention_status(p_slot, 1); + wait_for_ctrl_irq (ctrl); + } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_off(p_slot); + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } + /***********SURPRISE REMOVAL********************/ + else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || + (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) { + if (HP_SUPR_RM(ctrl->ctrlcap)) { + dbg("Surprise Removal\n"); + if (p_slot) { + surprise_rm_pending = (unsigned long) p_slot; + up(&event_semaphore); + update_slot_info(p_slot); + } + } } else { /* refresh notification */ if (p_slot) @@ -1648,25 +1746,29 @@ int pciehp_enable_slot(struct slot *p_slot) /* Check to see if (latch closed, card present, power off) */ down(&p_slot->ctrl->crit_sect); + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); up(&p_slot->ctrl->crit_sect); return 1; } - - rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (rc || getstatus) { - info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } up(&p_slot->ctrl->crit_sect); @@ -1735,26 +1837,33 @@ int pciehp_disable_slot(struct slot *p_slot) /* Check to see if (latch closed, card present, power on) */ down(&p_slot->ctrl->crit_sect); - ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); - if (ret || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); - if (ret || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (MRL_SENS(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (ret || getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } - ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); - if (ret || !getstatus) { - info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); - up(&p_slot->ctrl->crit_sect); - return 1; + if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { + ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return 1; + } } + up(&p_slot->ctrl->crit_sect); func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index cb0804b2d..dc1eb106d 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -182,7 +182,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct #define MRL_SENS_PRSN 0x00000004 #define ATTN_LED_PRSN 0x00000008 #define PWR_LED_PRSN 0x00000010 -#define HP_SUPR_RM 0x00000020 +#define HP_SUPR_RM_SUP 0x00000020 #define HP_CAP 0x00000040 #define SLOT_PWR_VALUE 0x000003F8 #define SLOT_PWR_LIMIT 0x00000C00 @@ -237,8 +237,8 @@ struct php_ctlr_state_s { static spinlock_t hpc_event_lock; DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ -static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ -static int ctlr_seq_num; /* Controller sequence # */ +static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */ +static int ctlr_seq_num = 0; /* Controller sequence # */ static spinlock_t list_lock; static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs); @@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ int *first_device_num, /* PCI dev num of the first slot in this PCIE */ int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ - int *updown, /* physical_slot_num increament: 1 or -1 */ - int *flags) + u8 *ctrlcap) { struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 slot_cap; @@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, } *physical_slot_num = slot_cap >> 19; - - *updown = -1; + dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num); + + *ctrlcap = slot_cap & 0x0000007f; DBG_LEAVE_ROUTINE return 0; @@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct controller *ctrl) if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; + if (!pcie_mch_quirk) + pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) @@ -1017,7 +1019,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value) +static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) { struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed; @@ -1120,7 +1122,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value return retval; } -static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value) +static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) { struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; @@ -1259,7 +1261,7 @@ int pcie_init(struct controller * ctrl, static int first = 1; u16 temp_word; u16 cap_reg; - u16 intr_enable; + u16 intr_enable = 0; u32 slot_cap; int cap_base, saved_cap_base; u16 slot_status, slot_ctrl; @@ -1345,6 +1347,9 @@ int pcie_init(struct controller * ctrl, info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); + if (pci_enable_device(pdev)) + goto abort_free_ctlr; + init_MUTEX(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); @@ -1402,8 +1407,8 @@ int pcie_init(struct controller * ctrl, start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ } else { /* Installs the interrupt handler */ - dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk); - if (!pciehp_msi_quirk) { + dbg("%s: pcie_mch_quirk = %x\n", __FUNCTION__, pcie_mch_quirk); + if (!pcie_mch_quirk) { rc = pci_enable_msi(pdev); if (rc) { info("Can't get msi for the hotplug controller\n"); @@ -1412,6 +1417,7 @@ int pcie_init(struct controller * ctrl, } else php_ctlr->irq = pdev->irq; } + rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); if (rc) { @@ -1426,9 +1432,18 @@ int pcie_init(struct controller * ctrl, goto abort_free_ctlr; } dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); + dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap); + + intr_enable = intr_enable | PRSN_DETECT_ENABLE; - intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | - PRSN_DETECT_ENABLE; + if (ATTN_BUTTN(slot_cap)) + intr_enable = intr_enable | ATTN_BUTTN_ENABLE; + + if (POWER_CTRL(slot_cap)) + intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE; + + if (MRL_SENS(slot_cap)) + intr_enable = intr_enable | MRL_DETECT_ENABLE; temp_word = (temp_word & ~intr_enable) | intr_enable; diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 8aa17540f..723b12c0b 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci_func* func) { int rc = 0; int j; + struct pci_bus *pbus; dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + pbus = func->pci_dev->bus; for (j=0; j<8 ; j++) { struct pci_dev* temp = pci_find_slot(func->bus, @@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci_func* func) pci_remove_bus_device(temp); } } + /* + * Some PCI Express root ports require fixup after hot-plug operation. + */ + if (pcie_mch_quirk) + pci_fixup_device(pci_fixup_final, pbus->self); + return rc; } diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c index b127575ec..424e7ac61 100644 --- a/drivers/pci/hotplug/pciehprm_acpi.c +++ b/drivers/pci/hotplug/pciehprm_acpi.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_IA64 @@ -50,6 +51,14 @@ #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" +/* Status code for running acpi method to gain native control */ +#define NC_NOT_RUN 0 +#define OSC_NOT_EXIST 1 +#define OSC_RUN_FAILED 2 +#define OSHP_NOT_EXIST 3 +#define OSHP_RUN_FAILED 4 +#define NC_RUN_SUCCESS 5 + #define PHP_RES_BUS 0xA0 #define PHP_RES_IO 0xA1 #define PHP_RES_MEM 0xA2 @@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle handle) } static void acpi_get__hpp ( struct acpi_bridge *ab); -static void acpi_run_oshp ( struct acpi_bridge *ab); +static int acpi_run_oshp ( struct acpi_bridge *ab); +static int osc_run_status = NC_NOT_RUN; +static int oshp_run_status = NC_NOT_RUN; static int acpi_add_slot_to_php_slots( struct acpi_bridge *ab, @@ -158,8 +169,9 @@ static int acpi_add_slot_to_php_slots( ab->scanned += 1; if (!ab->_hpp) acpi_get__hpp(ab); - - acpi_run_oshp(ab); + + if (osc_run_status == OSC_NOT_EXIST) + oshp_run_status = acpi_run_oshp(ab); if (sun != samesun) { info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", @@ -238,7 +250,7 @@ free_and_return: kfree(ret_buf.pointer); } -static void acpi_run_oshp ( struct acpi_bridge *ab) +static int acpi_run_oshp ( struct acpi_bridge *ab) { acpi_status status; u8 *path_name = acpi_path_name(ab->handle); @@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_bridge *ab) status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf); if (ACPI_FAILURE(status)) { err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); - } else + oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED; + } else { + oshp_run_status = NC_RUN_SUCCESS; dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); - return; + dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status); + } + return oshp_run_status; } static acpi_status acpi_evaluate_crs( @@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bridge( kfree(ab); return NULL; } + + status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); + if (ACPI_FAILURE(status)) { + err("%s: status %x\n", __FUNCTION__, status); + osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED; + } else { + osc_run_status = NC_RUN_SUCCESS; + } + dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status); + build_a_bridge(ab, ab); return ab; @@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctlr_type) if (rc) return rc; + if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) { + err("Fails to gain control of native hot-plug\n"); + rc = -ENODEV; + } + dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); return rc; } diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index f413495a2..6605d6bda 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -70,7 +70,7 @@ static int num_slots; MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); static int enable_slot (struct hotplug_slot *slot); diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index ed4b23c3c..705e5b3e6 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -25,6 +25,10 @@ static DECLARE_MUTEX(rpadlpar_sem); +#define NODE_TYPE_VIO 1 +#define NODE_TYPE_SLOT 2 +#define NODE_TYPE_PHB 3 + static struct device_node *find_php_slot_vio_node(char *drc_name) { struct device_node *child; @@ -44,21 +48,50 @@ static struct device_node *find_php_slot_vio_node(char *drc_name) return NULL; } -static struct device_node *find_php_slot_pci_node(char *drc_name) +/* Find dlpar-capable pci node that contains the specified name and type */ +static struct device_node *find_php_slot_pci_node(char *drc_name, + char *drc_type) { struct device_node *np = NULL; char *name; + char *type; + int rc; - while ((np = of_find_node_by_type(np, "pci"))) - if (is_hotplug_capable(np)) { - name = rpaphp_get_drc_name(np); - if (name && (!strcmp(drc_name, name))) + while ((np = of_find_node_by_type(np, "pci"))) { + rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL); + if (rc == 0) + if (!strcmp(drc_name, name) && !strcmp(drc_type, type)) break; - } + } return np; } +static struct device_node *find_newly_added_node(char *drc_name, int *node_type) +{ + struct device_node *dn; + + dn = find_php_slot_pci_node(drc_name, "SLOT"); + if (dn) { + *node_type = NODE_TYPE_SLOT; + return dn; + } + + dn = find_php_slot_pci_node(drc_name, "PHB"); + if (dn) { + *node_type = NODE_TYPE_PHB; + return dn; + } + + dn = find_php_slot_vio_node(drc_name); + if (dn) { + *node_type = NODE_TYPE_VIO; + return dn; + } + + return NULL; +} + static struct slot *find_slot(char *drc_name) { struct list_head *tmp, *n; @@ -125,12 +158,8 @@ static int pci_add_secondary_bus(struct device_node *dn, dn->bussubno = child->number; - /* ioremap() for child bus */ - if (remap_bus_range(child)) { - printk(KERN_ERR "%s: could not ioremap() child bus\n", - __FUNCTION__); - return 1; - } + /* ioremap() for child bus, which may or may not succeed */ + remap_bus_range(child); return 0; } @@ -205,6 +234,71 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) return 0; } +static int dlpar_remove_root_bus(struct pci_controller *phb) +{ + struct pci_bus *phb_bus; + int rc; + + phb_bus = phb->bus; + if (!(list_empty(&phb_bus->children) && + list_empty(&phb_bus->devices))) { + return -EBUSY; + } + + rc = pcibios_remove_root_bus(phb); + if (rc) + return -EIO; + + device_unregister(phb_bus->bridge); + pci_remove_bus(phb_bus); + + return 0; +} + +static int dlpar_remove_phb(struct slot *slot) +{ + struct pci_controller *phb; + struct device_node *dn; + int rc = 0; + + dn = slot->dn; + if (!dn) { + printk(KERN_ERR "%s: unexpected NULL slot device node\n", + __FUNCTION__); + return -EIO; + } + + phb = dn->phb; + if (!phb) { + printk(KERN_ERR "%s: unexpected NULL phb pointer\n", + __FUNCTION__); + return -EIO; + } + + if (rpaphp_remove_slot(slot)) { + printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", + __FUNCTION__, slot->location); + return -EIO; + } + + rc = dlpar_remove_root_bus(phb); + if (rc) + return rc; + + return 0; +} + +static int dlpar_add_phb(struct device_node *dn) +{ + struct pci_controller *phb; + + phb = init_phb_dynamic(dn); + if (!phb) + return 1; + + return 0; +} + /** * dlpar_add_slot - DLPAR add an I/O Slot * @drc_name: drc-name of newly added slot @@ -220,7 +314,8 @@ static inline int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) */ int dlpar_add_slot(char *drc_name) { - struct device_node *dn; + struct device_node *dn = NULL; + int node_type; int rc = 0; if (down_interruptible(&rpadlpar_sem)) @@ -232,18 +327,27 @@ int dlpar_add_slot(char *drc_name) goto exit; } - dn = find_php_slot_vio_node(drc_name); + dn = find_newly_added_node(drc_name, &node_type); if (!dn) { - dn = find_php_slot_pci_node(drc_name); - if (dn) + rc = -ENODEV; + goto exit; + } + + switch (node_type) { + case NODE_TYPE_VIO: + /* Just add hotplug slot */ + break; + case NODE_TYPE_SLOT: rc = dlpar_add_pci_slot(drc_name, dn); - else { - rc = -ENODEV; - goto exit; - } + break; + case NODE_TYPE_PHB: + rc = dlpar_add_phb(dn); + break; + default: + printk("%s: unexpected node type\n", __FUNCTION__); + return -EIO; } - /* Add hotplug slot for new VIOA or PCI */ if (!rc && rpaphp_add_slot(dn)) { printk(KERN_ERR "%s: unable to add hotplug slot %s\n", __FUNCTION__, drc_name); @@ -337,7 +441,8 @@ int dlpar_remove_slot(char *drc_name) return -ERESTARTSYS; if (!find_php_slot_vio_node(drc_name) && - !find_php_slot_pci_node(drc_name)) { + !find_php_slot_pci_node(drc_name, "SLOT") && + !find_php_slot_pci_node(drc_name, "PHB")) { rc = -ENODEV; goto exit; } @@ -348,17 +453,18 @@ int dlpar_remove_slot(char *drc_name) goto exit; } - switch (slot->dev_type) { - case PCI_DEV: - rc = dlpar_remove_pci_slot(slot, drc_name); - break; - - case VIO_DEV: - rc = dlpar_remove_vio_slot(slot, drc_name); - break; + if (slot->type == PHB) { + rc = dlpar_remove_phb(slot); + } else { + switch (slot->dev_type) { + case PCI_DEV: + rc = dlpar_remove_pci_slot(slot, drc_name); + break; - default: - rc = -EIO; + case VIO_DEV: + rc = dlpar_remove_vio_slot(slot, drc_name); + break; + } } exit: up(&rpadlpar_sem); diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index e155c4c97..28f3dded4 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -30,6 +30,7 @@ #include #include "pci_hotplug.h" +#define PHB 2 #define HOTPLUG 1 #define EMBEDDED 0 @@ -129,7 +130,8 @@ extern struct hotplug_slot *rpaphp_find_hotplug_slot(struct pci_dev *dev); /* rpaphp_core.c */ extern int rpaphp_add_slot(struct device_node *dn); extern int rpaphp_remove_slot(struct slot *slot); -extern char *rpaphp_get_drc_name(struct device_node *dn); +extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, + char **drc_name, char **drc_type, int *drc_power_domain); /* rpaphp_vio.c */ extern int rpaphp_get_vio_adapter_status(struct slot *slot, int is_init, u8 * value); diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index dd6dcdc73..8830f66cc 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -54,8 +54,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -void eeh_register_disable_func(int (*)(struct pci_dev *)); - module_param(debug, bool, 0644); static int enable_slot(struct hotplug_slot *slot); @@ -65,7 +63,6 @@ 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_adapter_status(struct hotplug_slot *slot, u8 * value); static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); -static int rpaphp_disable_slot(struct pci_dev *dev); struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { .owner = THIS_MODULE, @@ -214,32 +211,91 @@ int rpaphp_remove_slot(struct slot *slot) return deregister_slot(slot); } -static int get_dn_properties(struct device_node *dn, int **indexes, int **names, - int **types, int **power_domains) +static int get_children_props(struct device_node *dn, int **drc_indexes, + int **drc_names, int **drc_types, int **drc_power_domains) +{ + int *indexes, *names; + int *types, *domains; + + indexes = (int *) get_property(dn, "ibm,drc-indexes", NULL); + names = (int *) get_property(dn, "ibm,drc-names", NULL); + types = (int *) get_property(dn, "ibm,drc-types", NULL); + domains = (int *) get_property(dn, "ibm,drc-power-domains", NULL); + + if (!indexes || !names || !types || !domains) { + /* Slot does not have dynamically-removable children */ + return 1; + } + if (drc_indexes) + *drc_indexes = indexes; + if (drc_names) + /* &drc_names[1] contains NULL terminated slot names */ + *drc_names = names; + if (drc_types) + /* &drc_types[1] contains NULL terminated slot types */ + *drc_types = types; + if (drc_power_domains) + *drc_power_domains = domains; + + return 0; +} + +/* To get the DRC props describing the current node, first obtain it's + * my-drc-index property. Next obtain the DRC list from it's parent. Use + * the my-drc-index for correlation, and obtain the requested properties. + */ +int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, + char **drc_name, char **drc_type, int *drc_power_domain) { - *indexes = (int *) get_property(dn, "ibm,drc-indexes", NULL); + int *indexes, *names; + int *types, *domains; + unsigned int *my_index; + char *name_tmp, *type_tmp; + int i, rc; + + my_index = (int *) get_property(dn, "ibm,my-drc-index", NULL); + if (!my_index) { + /* Node isn't DLPAR/hotplug capable */ + return 1; + } - /* &names[1] contains NULL terminated slot names */ - *names = (int *) get_property(dn, "ibm,drc-names", NULL); + rc = get_children_props(dn->parent, &indexes, &names, &types, &domains); + if (rc) { + return 1; + } - /* &types[1] contains NULL terminated slot types */ - *types = (int *) get_property(dn, "ibm,drc-types", NULL); + name_tmp = (char *) &names[1]; + type_tmp = (char *) &types[1]; + + /* Iterate through parent properties, looking for my-drc-index */ + for (i = 0; i < indexes[0]; i++) { + if ((unsigned int) indexes[i + 1] == *my_index) { + if (drc_name) + *drc_name = name_tmp; + if (drc_type) + *drc_type = type_tmp; + if (drc_index) + *drc_index = *my_index; + if (drc_power_domain) + *drc_power_domain = domains[i+1]; + return 0; + } + name_tmp += (strlen(name_tmp) + 1); + type_tmp += (strlen(type_tmp) + 1); + } - /* power_domains[1...n] are the slot power domains */ - *power_domains = (int *) get_property(dn, "ibm,drc-power-domains", NULL); - - if (*indexes && *names && *types && *power_domains) - return (1); - - return (0); + return 1; } static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **types, int **power_domains) { + int rc; + if (!is_hotplug_capable(dn)) return (0); - if (!get_dn_properties(dn, indexes, names, types, power_domains)) + rc = get_children_props(dn, indexes, names, types, power_domains); + if (rc) return (0); return (1); } @@ -247,8 +303,7 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **t static int is_dr_dn(struct device_node *dn, int **indexes, int **names, int **types, int **power_domains, int **my_drc_index) { - if (!is_hotplug_capable(dn)) - return (0); + int rc; *my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL); if(!*my_drc_index) @@ -257,7 +312,9 @@ static int is_dr_dn(struct device_node *dn, int **indexes, int **names, int **ty if (!dn->parent) return (0); - return get_dn_properties(dn->parent, indexes, names, types, power_domains); + rc = get_children_props(dn->parent, indexes, names, types, + power_domains); + return (rc == 0); } static inline int is_vdevice_root(struct device_node *dn) @@ -265,34 +322,10 @@ static inline int is_vdevice_root(struct device_node *dn) return !strcmp(dn->name, "vdevice"); } -char *rpaphp_get_drc_name(struct device_node *dn) +int is_dlpar_type(const char *type_str) { - char *name, *ptr = NULL; - int *drc_names, *drc_indexes, i; - struct device_node *parent = dn->parent; - u32 *my_drc_index; - - if (!parent) - return NULL; - - my_drc_index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL); - if (!my_drc_index) - return NULL; - - drc_names = (int *) get_property(parent, "ibm,drc-names", NULL); - drc_indexes = (int *) get_property(parent, "ibm,drc-indexes", NULL); - if (!drc_names || !drc_indexes) - return NULL; - - name = (char *) &drc_names[1]; - for (i = 0; i < drc_indexes[0]; i++, name += (strlen(name) + 1)) { - if (drc_indexes[i + 1] == *my_drc_index) { - ptr = (char *) name; - break; - } - } - - return ptr; + /* Only register DLPAR-capable nodes of drc-type PHB or SLOT */ + return (!strcmp(type_str, "PHB") || !strcmp(type_str, "SLOT")); } /**************************************************************** @@ -331,15 +364,18 @@ int rpaphp_add_slot(struct device_node *dn) for (i = 0; i < indexes[0]; i++, name += (strlen(name) + 1), type += (strlen(type) + 1)) { - if ( slot_type == HOTPLUG || - (slot_type == EMBEDDED && indexes[i + 1] == my_drc_index[0])) { - + if (slot_type == HOTPLUG || + (slot_type == EMBEDDED && + indexes[i + 1] == my_drc_index[0] && + is_dlpar_type(type))) { if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]))) { retval = -ENOMEM; goto exit; } - if (slot_type == EMBEDDED) + if (!strcmp(type, "PHB")) + slot->type = PHB; + else if (slot_type == EMBEDDED) slot->type = EMBEDDED; else slot->type = simple_strtoul(type, NULL, 10); @@ -407,18 +443,12 @@ static int __init rpaphp_init(void) { info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - /* let EEH know they can use hotplug */ - eeh_register_disable_func(&rpaphp_disable_slot); - /* read all the PRA info from the system */ return init_rpa(); } static void __exit rpaphp_exit(void) { - /* let EEH know we are going away */ - eeh_register_disable_func(NULL); - cleanup_slots(); } @@ -450,14 +480,9 @@ exit: return retval; } -static int rpaphp_disable_slot(struct pci_dev *dev) -{ - return disable_slot(rpaphp_find_hotplug_slot(dev)); -} - static int disable_slot(struct hotplug_slot *hotplug_slot) { - int retval; + int retval = -EINVAL; struct slot *slot = (struct slot *)hotplug_slot->private; dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name); @@ -491,4 +516,4 @@ module_exit(rpaphp_exit); EXPORT_SYMBOL_GPL(rpaphp_add_slot); EXPORT_SYMBOL_GPL(rpaphp_remove_slot); EXPORT_SYMBOL_GPL(rpaphp_slot_head); -EXPORT_SYMBOL_GPL(rpaphp_get_drc_name); +EXPORT_SYMBOL_GPL(rpaphp_get_drc_props); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 0dd2d2369..002c91fff 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -31,18 +31,17 @@ struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) { - struct pci_dev *retval_dev = NULL, *dev = NULL; + struct pci_dev *dev = NULL; char bus_id[BUS_ID_SIZE]; - sprintf(bus_id, "%04x:%02x:%02x.%d",dn->phb->global_number, + sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number, dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn)); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { if (!strcmp(pci_name(dev), bus_id)) { - retval_dev = dev; break; } } - return retval_dev; + return dev; } EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); @@ -117,33 +116,40 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state) int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) { int state, rc; - *value = NOT_VALID; + struct device_node *child_dn; + struct pci_dev *child_dev = NULL; + *value = NOT_VALID; rc = rpaphp_get_sensor_state(slot, &state); if (rc) goto exit; - if (state == PRESENT) { + + if ((state == EMPTY) || (slot->type == PHB)) { + dbg("slot is empty\n"); + *value = EMPTY; + } + else if (state == PRESENT) { if (!is_init) /* at run-time slot->state can be changed by */ /* config/unconfig adapter */ *value = slot->state; else { - if (!slot->dn->child) + child_dn = slot->dn->child; + if (child_dn) + child_dev = rpaphp_find_pci_dev(child_dn); + + if (child_dev) + *value = CONFIGURED; + else if (!child_dn) dbg("%s: %s is not valid OFDT node\n", __FUNCTION__, slot->dn->full_name); - else if (rpaphp_find_pci_dev(slot->dn->child)) - *value = CONFIGURED; else { err("%s: can't find pdev of adapter in slot[%s]\n", __FUNCTION__, slot->dn->full_name); *value = NOT_CONFIGURED; } } - } else if (state == EMPTY) { - dbg("slot is empty\n"); - *value = state; } - exit: return rc; } @@ -186,7 +192,7 @@ static struct pci_dev * rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus) { struct device_node *eads_first_child = dn->child; - struct pci_dev *dev; + struct pci_dev *dev = NULL; int num; dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name); @@ -341,7 +347,6 @@ exit: return rc; } - static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) { eeh_remove_device(dev); @@ -363,7 +368,7 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev) int rpaphp_unconfig_pci_adapter(struct slot *slot) { int retval = 0; - struct list_head *ln; + struct list_head *ln, *tmp; dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name); if (list_empty(&slot->dev.pci_funcs)) { @@ -374,7 +379,7 @@ int rpaphp_unconfig_pci_adapter(struct slot *slot) goto exit; } /* remove the devices from the pci core */ - list_for_each (ln, &slot->dev.pci_funcs) { + list_for_each_safe (ln, tmp, &slot->dev.pci_funcs) { struct rpaphp_pci_func *func; func = list_entry(ln, struct rpaphp_pci_func, sibling); @@ -409,15 +414,52 @@ static int setup_pci_hotplug_slot_info(struct slot *slot) return 0; } +static int set_phb_slot_name(struct slot *slot) +{ + struct device_node *dn; + struct pci_controller *phb; + struct pci_bus *bus; + + dn = slot->dn; + if (!dn) { + return 1; + } + phb = dn->phb; + if (!phb) { + return 1; + } + bus = phb->bus; + if (!bus) { + return 1; + } + + sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus), + bus->number, 0, 0); + return 0; +} + static int setup_pci_slot(struct slot *slot) { - slot->bridge = rpaphp_find_bridge_pdev(slot); - if (!slot->bridge) { /* slot being added doesn't have pci_dev yet */ - err("%s: no pci_dev for bridge dn %s\n", __FUNCTION__, slot->name); - goto exit_rc; + int rc; + + if (slot->type == PHB) { + rc = set_phb_slot_name(slot); + if (rc) { + err("%s: failed to set phb slot name\n", __FUNCTION__); + goto exit_rc; + } + } else { + slot->bridge = rpaphp_find_bridge_pdev(slot); + if (!slot->bridge) { + /* slot being added doesn't have pci_dev yet */ + err("%s: no pci_dev for bridge dn %s\n", + __FUNCTION__, slot->name); + goto exit_rc; + } + dbg("%s set slot->name to %s\n", __FUNCTION__, + pci_name(slot->bridge)); + strcpy(slot->name, pci_name(slot->bridge)); } - dbg("%s set slot->name to %s\n", __FUNCTION__, pci_name(slot->bridge)); - strcpy(slot->name, pci_name(slot->bridge)); /* find slot's pci_dev if it's not empty */ if (slot->hotplug_slot->info->adapter_status == EMPTY) { @@ -430,10 +472,26 @@ static int setup_pci_slot(struct slot *slot) __FUNCTION__, slot->name); goto exit_rc; } - if (init_slot_pci_funcs(slot)) { - err("%s: init_slot_pci_funcs failed\n", __FUNCTION__); + + if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { + dbg("%s CONFIGURING pci adapter in slot[%s]\n", + __FUNCTION__, slot->name); + if (rpaphp_config_pci_adapter(slot)) { + err("%s: CONFIG pci adapter failed\n", __FUNCTION__); + goto exit_rc; + } + } else if (slot->hotplug_slot->info->adapter_status == CONFIGURED) { + if (init_slot_pci_funcs(slot)) { + err("%s: init_slot_pci_funcs failed\n", __FUNCTION__); + goto exit_rc; + } + + } else { + err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", + __FUNCTION__, slot->name); goto exit_rc; } + print_slot_pci_funcs(slot); if (!list_empty(&slot->dev.pci_funcs)) { slot->state = CONFIGURED; @@ -455,10 +513,10 @@ int register_pci_slot(struct slot *slot) int rc = 1; slot->dev_type = PCI_DEV; - if (slot->type == EMBEDDED) - slot->removable = EMBEDDED; + if ((slot->type == EMBEDDED) || (slot->type == PHB)) + slot->removable = 0; else - slot->removable = HOTPLUG; + slot->removable = 1; INIT_LIST_HEAD(&slot->dev.pci_funcs); if (setup_pci_hotplug_slot_info(slot)) goto exit_rc; diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index c58541add..2bbd87ef4 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -244,18 +244,21 @@ int register_slot(struct slot *slot) int rpaphp_get_power_status(struct slot *slot, u8 * value) { - int rc = 0; + int rc = 0, level; - if (slot->type == EMBEDDED) { - dbg("%s set to POWER_ON for EMBEDDED slot %s\n", - __FUNCTION__, slot->location); - *value = POWER_ON; - } - else { - rc = rtas_get_power_level(slot->power_domain, (int *) value); - if (rc) + if (slot->type == HOTPLUG) { + rc = rtas_get_power_level(slot->power_domain, &level); + if (!rc) { + dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n", + __FUNCTION__, slot->name, slot->power_domain, level); + *value = level; + } else err("failed to get power-level for slot(%s), rc=0x%x\n", - slot->location, rc); + slot->location, rc); + } else { + dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n", + __FUNCTION__, slot->location); + *value = (u8) POWER_ON; } return rc; diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c index d82b6649e..561c87cf2 100644 --- a/drivers/pci/hotplug/rpaphp_vio.c +++ b/drivers/pci/hotplug/rpaphp_vio.c @@ -74,8 +74,8 @@ int register_vio_slot(struct device_node *dn) int rc = 1; struct slot *slot = NULL; - name = rpaphp_get_drc_name(dn); - if (!name) + rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL); + if (rc) goto exit_rc; index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL); if (!index) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c68b22efb..89f192286 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include "pci_hotplug.h" @@ -311,7 +312,7 @@ struct php_ctlr_state_s { php_intr_callback_t presence_change_callback; php_intr_callback_t power_fault_callback; void *callback_instance_id; - void *creg; /* Ptr to controller register space */ + void __iomem *creg; /* Ptr to controller register space */ }; /* Inline functions */ @@ -381,16 +382,14 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) dbg("%s : start\n",__FUNCTION__); add_wait_queue(&ctrl->queue, &wait); - set_current_state(TASK_INTERRUPTIBLE); if (!shpchp_poll_mode) { /* Sleep for up to 1 second */ - schedule_timeout(1*HZ); + msleep_interruptible(1000); } else { /* Sleep for up to 2 seconds */ - schedule_timeout(2*HZ); + msleep_interruptible(2000); } - set_current_state(TASK_RUNNING); remove_wait_queue(&ctrl->queue, &wait); if (signal_pending(current)) retval = -EINTR; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7f34ec941..f11217230 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -57,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(shpchp_debug, bool, 644); -module_param(shpchp_poll_mode, bool, 644); -module_param(shpchp_poll_time, int, 644); +module_param(shpchp_debug, bool, 0644); +module_param(shpchp_poll_mode, bool, 0644); +module_param(shpchp_poll_time, int, 0644); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); @@ -599,8 +599,8 @@ static int __init shpcd_init(void) retval = shpchprm_init(PCI); if (!retval) { - retval = pci_module_init(&shpc_driver); - dbg("%s: pci_module_init = %d\n", __FUNCTION__, retval); + retval = pci_register_driver(&shpc_driver); + dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 7ca8e9369..9f90eb8e6 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -1050,7 +1050,64 @@ static int is_bridge(struct pci_func * func) /* The following routines constitute the bulk of the hotplug controller logic */ +static u32 change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed) +{ + u32 rc = 0; + dbg("%s: change to speed %d\n", __FUNCTION__, speed); + down(&ctrl->crit_sect); + if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + up(&ctrl->crit_sect); + return rc; +} + +static u32 fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, +enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp) +{ + u32 rc = 0; + + if (flag != 0) { /* Other slots on the same bus are occupied */ + if ( asp < bsp ) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bsp, asp); + return WRONG_BUS_FREQUENCY; + } + } else { + /* Other slots on the same bus are empty */ + if (msp == bsp) { + /* if adapter_speed >= bus_speed, do nothing */ + if (asp < bsp) { + /* + * Try to lower bus speed to accommodate the adapter if other slots + * on the same controller are empty + */ + if ((rc = change_bus_speed(ctrl, pslot, asp))) + return rc; + } + } else { + if (asp < msp) { + if ((rc = change_bus_speed(ctrl, pslot, asp))) + return rc; + } else { + if ((rc = change_bus_speed(ctrl, pslot, msp))) + return rc; + } + } + } + return rc; +} /** * board_added - Called after a board has been added to the system. @@ -1061,14 +1118,13 @@ static int is_bridge(struct pci_func * func) */ static u32 board_added(struct pci_func * func, struct controller * ctrl) { - u8 hp_slot, slot; + u8 hp_slot; u8 slots_not_empty = 0; int index; u32 temp_register = 0xFFFFFFFF; u32 retval, rc = 0; struct pci_func *new_func = NULL; - struct pci_func *t_func = NULL; - struct slot *p_slot, *pslot; + struct slot *p_slot; struct resource_lists res_lists; enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; u8 pi, mode; @@ -1101,6 +1157,40 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) return -1; } + + if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { + if (slots_not_empty) + return WRONG_BUS_FREQUENCY; + + if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* turn on board, blink green LED, turn off Amber LED */ + if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { + err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); + up(&ctrl->crit_sect); + return rc; + } + wait_for_ctrl_irq (ctrl); + + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { + err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); + up(&ctrl->crit_sect); + return rc; + } + } + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ @@ -1132,258 +1222,72 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) /* Done with exclusive hardware access */ up(&ctrl->crit_sect); - rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi); - if (rc) { + if ((rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi))) { err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); pi = 1; } + + /* Check if there are other slots or devices on the same bus */ + if (!list_empty(&ctrl->pci_dev->subordinate->devices)) + slots_not_empty = 1; + + dbg("%s: slots_not_empty %d, pi %d\n", __FUNCTION__, + slots_not_empty, pi); + dbg("adapter_speed %d, bus_speed %d, max_bus_speed %d\n", + adapter_speed, bus_speed, max_bus_speed); + if (pi == 2) { - for ( slot = 0; slot < ctrl->num_slots; slot++) { - if (slot != hp_slot) { - pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset); - t_func = shpchp_slot_find(pslot->bus, pslot->device, 0); - slots_not_empty |= t_func->is_a_board; - } + dbg("%s: In PI = %d\n", __FUNCTION__, pi); + if ((rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode))) { + err("%s: Can't get Mode1_ECC, set mode to 0\n", __FUNCTION__); + mode = 0; } switch (adapter_speed) { - case PCI_SPEED_133MHz_PCIX_533: + case PCI_SPEED_133MHz_PCIX_533: case PCI_SPEED_133MHz_PCIX_266: - if ((( bus_speed < 0xa ) || (bus_speed < 0xd)) && (max_bus_speed > bus_speed) && - ((max_bus_speed <= 0xa) || (max_bus_speed <= 0xd)) && (!slots_not_empty)) { - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } - break; + if ((bus_speed != adapter_speed) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; + break; case PCI_SPEED_133MHz_PCIX_ECC: case PCI_SPEED_133MHz_PCIX: - - rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode); - - if (rc) { - err("%s: PI is 1 \n", __FUNCTION__); - return WRONG_BUS_FREQUENCY; - } - if (mode) { /* Bus - Mode 1 ECC */ - - if (bus_speed > 0x7) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - - if ((bus_speed < 0x7) && (max_bus_speed <= 0x7) && - (bus_speed < max_bus_speed) && (!slots_not_empty)) { - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } + if ((bus_speed != 0x7) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; } else { - if (bus_speed > 0x4) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - - if ((bus_speed < 0x4) && (max_bus_speed <= 0x4) && - (bus_speed < max_bus_speed) && (!slots_not_empty)) { - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } + if ((bus_speed != 0x4) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; } break; case PCI_SPEED_66MHz_PCIX_ECC: case PCI_SPEED_66MHz_PCIX: - - rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode); - - if (rc) { - err("%s: PI is 1 \n", __FUNCTION__); - return WRONG_BUS_FREQUENCY; - } - if (mode) { /* Bus - Mode 1 ECC */ - - if (bus_speed > 0x5) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - - if ((bus_speed < 0x5) && (max_bus_speed <= 0x5) && - (bus_speed < max_bus_speed) && (!slots_not_empty)) { - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } + if ((bus_speed != 0x5) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; } else { - if (bus_speed > 0x2) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - - if ((bus_speed < 0x2) && (max_bus_speed <= 0x2) && - (bus_speed < max_bus_speed) && (!slots_not_empty)) { - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } + if ((bus_speed != 0x2) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; } break; case PCI_SPEED_66MHz: - if (bus_speed > 0x1) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - if (bus_speed == 0x1) - ; - if ((bus_speed == 0x0) && ( max_bus_speed == 0x1)) { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - } + if ((bus_speed != 0x1) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; break; case PCI_SPEED_33MHz: if (bus_speed > 0x0) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; + if (slots_not_empty == 0) { + if ((rc = change_bus_speed(ctrl, p_slot, adapter_speed))) + return rc; + } else { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } } break; default: @@ -1391,133 +1295,34 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) return WRONG_BUS_FREQUENCY; } } else { - /* if adpater_speed == bus_speed, nothing to do here */ - if (adapter_speed != bus_speed) { - for ( slot = 0; slot < ctrl->num_slots; slot++) { - if (slot != hp_slot) { - pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset); - t_func = shpchp_slot_find(pslot->bus, pslot->device, 0); - slots_not_empty |= t_func->is_a_board; - } - } - - if (slots_not_empty != 0) { /* Other slots on the same bus are occupied */ - if ( adapter_speed < bus_speed ) { - err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); - return WRONG_BUS_FREQUENCY; - } - /* Do nothing if adapter_speed >= bus_speed */ - } - } - - if ((adapter_speed != bus_speed) && (slots_not_empty == 0)) { - /* Other slots on the same bus are empty */ - - rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); - if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { - err("%s: Can't get max bus operation speed\n", __FUNCTION__); - max_bus_speed = bus_speed; - } - - if (max_bus_speed == bus_speed) { - /* if adapter_speed >= bus_speed, do nothing */ - if (adapter_speed < bus_speed) { - /* - * Try to lower bus speed to accommodate the adapter if other slots - * on the same controller are empty - */ - - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - } - } else { - /* Wait for exclusive access to hardware */ - down(&ctrl->crit_sect); - - /* max_bus_speed != bus_speed. Note: max_bus_speed should be > than bus_speed */ - if (adapter_speed < max_bus_speed) - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); - else - rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); - - if (rc) { - err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - - /* Wait for the command to complete */ - wait_for_ctrl_irq (ctrl); - - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { - err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", - __FUNCTION__); - err("%s: Error code (%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - return WRONG_BUS_FREQUENCY; - } - /* Done with exclusive hardware access */ - up(&ctrl->crit_sect); - - } - } + /* If adpater_speed == bus_speed, nothing to do here */ + dbg("%s: In PI = %d\n", __FUNCTION__, pi); + if ((adapter_speed != bus_speed) && + ((rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, adapter_speed, bus_speed, max_bus_speed)))) + return rc; } - /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); - /* turn on board, blink green LED, turn off Amber LED */ - rc = p_slot->hpc_ops->slot_enable(p_slot); - - if (rc) { + if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); - /* Done with exclusive hardware access */ up(&ctrl->crit_sect); return rc; } - /* Wait for the command to complete */ wait_for_ctrl_irq (ctrl); - rc = p_slot->hpc_ops->check_cmd_status(ctrl); - if (rc) { + if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) { err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); - /* Done with exclusive hardware access */ up(&ctrl->crit_sect); return rc; } - /* Done with exclusive hardware access */ up(&ctrl->crit_sect); /* Wait for ~1 second */ dbg("%s: before long_delay\n", __FUNCTION__); wait_for_ctrl_irq (ctrl); - dbg("%s: afterlong_delay\n", __FUNCTION__); + dbg("%s: after long_delay\n", __FUNCTION__); dbg("%s: func status = %x\n", __FUNCTION__, func->status); /* Check for a power fault */ @@ -2163,12 +1968,14 @@ int shpchp_disable_slot (struct slot *p_slot) u32 rc = 0; int ret = 0; unsigned int devfn; - struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; + struct pci_bus *pci_bus; struct pci_func *func; if (!p_slot->ctrl) return 1; + pci_bus = p_slot->ctrl->pci_dev->subordinate; + /* Check to see if (latch closed, card present, power on) */ down(&p_slot->ctrl->crit_sect); diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index b1fab4532..38c5d9066 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include "shpchp.h" @@ -300,8 +301,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) if (!(cmd_status & 0x1)) break; /* Check every 0.1 sec for a total of 1 sec*/ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); } cmd_status = readw(php_ctlr->creg + CMD_STATUS); @@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct controller *ctrl) if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; + pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) { @@ -1158,7 +1159,7 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) hp_slot, php_ctlr->callback_instance_id); /* Clear all slot events */ - temp_dword = 0xe01fffff; + temp_dword = 0xe01f3fff; dbg("%s: Clearing slot events, temp_dword = %x\n", __FUNCTION__, temp_dword); writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); @@ -1486,14 +1487,16 @@ int shpc_init(struct controller * ctrl, info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); + + if (pci_enable_device(pdev)) + goto abort_free_ctlr; if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { err("%s: cannot reserve MMIO region\n", __FUNCTION__); goto abort_free_ctlr; } - php_ctlr->creg = (struct ctrl_reg *) - ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); + php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); if (!php_ctlr->creg) { err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), pci_resource_start(pdev, 0) + shpc_base_offset); @@ -1539,7 +1542,7 @@ int shpc_init(struct controller * ctrl, slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xffffffff; + tempdword = 0xffff3fff; writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); } @@ -1592,7 +1595,7 @@ int shpc_init(struct controller * ctrl, slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xe01fffff; + tempdword = 0xe01f3fff; writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); } if (!shpchp_poll_mode) { diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c index 6ea1703c2..f1c51f092 100644 --- a/drivers/pci/hotplug/shpchprm_acpi.c +++ b/drivers/pci/hotplug/shpchprm_acpi.c @@ -1396,17 +1396,19 @@ static int configure_existing_function( static int bind_pci_resources_to_slots ( struct controller *ctrl) { struct pci_func *func, new_func; - int busn = ctrl->bus; + int busn = ctrl->slot_bus; int devn, funn; u32 vid; for (devn = 0; devn < 32; devn++) { for (funn = 0; funn < 8; funn++) { + /* if (devn == ctrl->device && funn == ctrl->function) continue; + */ /* find out if this entry is for an occupied slot */ vid = 0xFFFFFFFF; - pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); + pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); if (vid != 0xFFFFFFFF) { func = shpchp_slot_find(busn, devn, funn); diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d4c89d73e..726a96625 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -66,7 +66,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag) int pos; u32 mask_bits; - pos = entry->mask_base; + pos = (int)entry->mask_base; pci_read_config_dword(entry->dev, pos, &mask_bits); mask_bits &= ~(1); mask_bits |= flag; @@ -548,7 +548,7 @@ static int msi_capability_init(struct pci_dev *dev) dev->irq = vector; entry->dev = dev; if (is_mask_bit_support(control)) { - entry->mask_base = msi_mask_bits_reg(pos, + entry->mask_base = (void __iomem *)msi_mask_bits_reg(pos, is_64bit_address(control)); } /* Replace with MSI handler */ @@ -606,7 +606,7 @@ static int msix_capability_init(struct pci_dev *dev, u32 phys_addr, table_offset; u16 control; u8 bir; - void *base; + void __iomem *base; pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); /* Request & Map MSI-X table region */ @@ -642,7 +642,7 @@ static int msix_capability_init(struct pci_dev *dev, entry->msi_attrib.maskbit = 1; entry->msi_attrib.default_vector = dev->irq; entry->dev = dev; - entry->mask_base = (unsigned long)base; + entry->mask_base = base; if (!head) { entry->link.head = vector; entry->link.tail = vector; @@ -806,7 +806,7 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) { struct msi_desc *entry; int head, entry_nr, type; - unsigned long base = 0L; + void __iomem *base; unsigned long flags; spin_lock_irqsave(&msi_lock, flags); @@ -857,7 +857,7 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) phys_addr = pci_resource_start (dev, bir); phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); - iounmap((void*)base); + iounmap(base); release_mem_region(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); } @@ -869,8 +869,8 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec) { int vector = head, tail = 0; - int i = 0, j = 0, nr_entries = 0; - unsigned long base = 0L; + int i, j = 0, nr_entries = 0; + void __iomem *base; unsigned long flags; spin_lock_irqsave(&msi_lock, flags); @@ -1099,7 +1099,7 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { int vector, head, tail = 0, warning = 0; - unsigned long base = 0L; + void __iomem *base = NULL; vector = head = dev->irq; while (head != tail) { @@ -1129,7 +1129,7 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) phys_addr = pci_resource_start (dev, bir); phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); - iounmap((void*)base); + iounmap(base); release_mem_region(phys_addr, PCI_MSIX_ENTRY_SIZE * multi_msix_capable(control)); printk(KERN_DEBUG "Driver[%d:%d:%d] unloaded wo doing free_irq on all vectors\n", diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 3a7a52854..bef21ae3c 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -152,7 +152,7 @@ struct msi_desc { __u16 tail; }link; - unsigned long mask_base; + void __iomem *mask_base; struct pci_dev *dev; }; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9936879eb..7ce952cd9 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -14,27 +14,6 @@ * Registration of PCI drivers and handling of hot-pluggable devices. */ -/** - * pci_match_one_device - Tell if a PCI device structure has a matching - * PCI device id structure - * @id: single PCI device id structure to match - * @dev: the PCI device structure to match against - * - * Returns the matching pci_device_id structure or %NULL if there is no match. - */ - -static inline const struct pci_device_id * -pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) -{ - if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) && - (id->device == PCI_ANY_ID || id->device == dev->device) && - (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) && - (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) && - !((id->class ^ dev->class) & id->class_mask)) - return id; - return NULL; -} - /* * Dynamic device IDs are disabled for !CONFIG_HOTPLUG */ @@ -291,6 +270,16 @@ static int pci_device_remove(struct device * dev) drv->remove(pci_dev); pci_dev->driver = NULL; } + + /* + * We would love to complain here if pci_dev->is_enabled is set, that + * the driver should have called pci_disable_device(), but the + * unfortunate fact is there are too many odd BIOS and bridge setups + * that don't like drivers doing that all of the time. + * Oh well, we can dream of sane hardware when we sleep, no matter how + * horrible the crap we have to deal with is when we are awake... + */ + pci_dev_put(pci_dev); return 0; } @@ -299,12 +288,25 @@ static int pci_device_suspend(struct device * dev, u32 state) { struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; + u32 dev_state; int i = 0; + /* Translate PM_SUSPEND_xx states to PCI device states */ + static u32 state_conversion[] = { + [PM_SUSPEND_ON] = 0, + [PM_SUSPEND_STANDBY] = 1, + [PM_SUSPEND_MEM] = 3, + [PM_SUSPEND_DISK] = 3, + }; + + if (state >= sizeof(state_conversion) / sizeof(state_conversion[1])) + return -EINVAL; + + dev_state = state_conversion[state]; if (drv && drv->suspend) - i = drv->suspend(pci_dev,state); - - pci_save_state(pci_dev, pci_dev->saved_config_space); + i = drv->suspend(pci_dev, dev_state); + else + pci_save_state(pci_dev); return i; } @@ -316,7 +318,7 @@ static int pci_device_suspend(struct device * dev, u32 state) static void pci_default_resume(struct pci_dev *pci_dev) { /* restore the PCI config space */ - pci_restore_state(pci_dev, pci_dev->saved_config_space); + pci_restore_state(pci_dev); /* if the device was enabled before suspend, reenable */ if (pci_dev->is_enabled) pci_enable_device(pci_dev); @@ -390,32 +392,31 @@ pci_populate_driver_dir(struct pci_driver *drv) * pci_register_driver - register a new pci driver * @drv: the driver structure to register * - * Adds the driver structure to the list of registered drivers - * Returns the number of pci devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. + * Adds the driver structure to the list of registered drivers. + * Returns a negative value on error, otherwise 0. + * If no error occured, the driver remains registered even if + * no device was claimed during registration. */ -int -pci_register_driver(struct pci_driver *drv) +int pci_register_driver(struct pci_driver *drv) { - int count = 0; + int error; /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; drv->driver.probe = pci_device_probe; drv->driver.remove = pci_device_remove; + drv->driver.owner = drv->owner; drv->driver.kobj.ktype = &pci_driver_kobj_type; pci_init_dynids(&drv->dynids); /* register with core */ - count = driver_register(&drv->driver); + error = driver_register(&drv->driver); - if (count >= 0) { + if (!error) pci_populate_driver_dir(drv); - } - return count ? count : 1; + return error; } /** @@ -500,16 +501,9 @@ static int pci_bus_match(struct device * dev, struct device_driver * drv) */ struct pci_dev *pci_dev_get(struct pci_dev *dev) { - struct device *tmp; - - if (!dev) - return NULL; - - tmp = get_device(&dev->dev); - if (tmp) - return to_pci_dev(tmp); - else - return NULL; + if (dev) + get_device(&dev->dev); + return dev; } /** diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 120a441a8..7fcf935c5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -5,6 +5,8 @@ * (C) Copyright 2002-2004 IBM Corp. * (C) Copyright 2003 Matthew Wilcox * (C) Copyright 2003 Hewlett-Packard + * (C) Copyright 2004 Jon Smirl + * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes * * File attributes for PCI devices * @@ -17,9 +19,12 @@ #include #include #include +#include #include "pci.h" +static int sysfs_initialized; /* = 0 */ + /* show configuration fields */ #define pci_config_attr(field, format_string) \ static ssize_t \ @@ -38,6 +43,14 @@ pci_config_attr(subsystem_device, "0x%04x\n"); pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); +static ssize_t local_cpus_show(struct device *dev, char *buf) +{ + cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus->number); + int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); + strcat(buf,"\n"); + return 1+len; +} + /* show resources */ static ssize_t resource_show(struct device * dev, char * buf) @@ -67,6 +80,7 @@ struct device_attribute pci_dev_attrs[] = { __ATTR_RO(subsystem_device), __ATTR_RO(class), __ATTR_RO(irq), + __ATTR_RO(local_cpus), __ATTR_NULL, }; @@ -164,6 +178,65 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) return count; } +/** + * pci_write_rom - used to enable access to the PCI ROM display + * @kobj: kernel object handle + * @buf: user input + * @off: file offset + * @count: number of byte in input + * + * writing anything except 0 enables it + */ +static ssize_t +pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); + + if ((off == 0) && (*buf == '0') && (count == 2)) + pdev->rom_attr_enabled = 0; + else + pdev->rom_attr_enabled = 1; + + return count; +} + +/** + * pci_read_rom - read a PCI ROM + * @kobj: kernel object handle + * @buf: where to put the data we read from the ROM + * @off: file offset + * @count: number of bytes to read + * + * Put @count bytes starting at @off into @buf from the ROM in the PCI + * device corresponding to @kobj. + */ +static ssize_t +pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); + void __iomem *rom; + size_t size; + + if (!pdev->rom_attr_enabled) + return -EINVAL; + + rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ + if (!rom) + return 0; + + if (off >= size) + count = 0; + else { + if (off + count > size) + count = size - off; + + memcpy_fromio(buf, rom + off, count); + } + pci_unmap_rom(pdev, rom); + + return count; +} + static struct bin_attribute pci_config_attr = { .attr = { .name = "config", @@ -186,13 +259,68 @@ static struct bin_attribute pcie_config_attr = { .write = pci_write_config, }; -void pci_create_sysfs_dev_files (struct pci_dev *pdev) +int pci_create_sysfs_dev_files (struct pci_dev *pdev) { + if (!sysfs_initialized) + return -EACCES; + if (pdev->cfg_size < 4096) sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); else sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); + /* If the device has a ROM, try to expose it in sysfs. */ + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { + struct bin_attribute *rom_attr; + + rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC); + if (rom_attr) { + pdev->rom_attr = rom_attr; + rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); + rom_attr->attr.name = "rom"; + rom_attr->attr.mode = S_IRUSR; + rom_attr->attr.owner = THIS_MODULE; + rom_attr->read = pci_read_rom; + rom_attr->write = pci_write_rom; + sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); + } + } /* add platform-specific attributes */ pcibios_add_platform_entries(pdev); + + return 0; } + +/** + * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files + * @pdev: device whose entries we should free + * + * Cleanup when @pdev is removed from sysfs. + */ +void pci_remove_sysfs_dev_files(struct pci_dev *pdev) +{ + if (pdev->cfg_size < 4096) + sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); + else + sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); + + if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { + if (pdev->rom_attr) { + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); + kfree(pdev->rom_attr); + } + } +} + +static int __init pci_sysfs_init(void) +{ + struct pci_dev *pdev = NULL; + + sysfs_initialized = 1; + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) + pci_create_sysfs_dev_files(pdev); + + return 0; +} + +__initcall(pci_sysfs_init); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 05daa8cff..5e7a94a8c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -291,10 +291,7 @@ pci_set_power_state(struct pci_dev *dev, int state) /* Mandatory power management transition delays */ /* see PCI PM 1.1 5.6.1 table 18 */ if(state == 3 || dev->current_state == 3) - { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); - } + msleep(10); else if(state == 2 || dev->current_state == 2) udelay(200); dev->current_state = state; @@ -311,14 +308,12 @@ pci_set_power_state(struct pci_dev *dev, int state) * (>= 64 bytes). */ int -pci_save_state(struct pci_dev *dev, u32 *buffer) +pci_save_state(struct pci_dev *dev) { int i; - if (buffer) { - /* XXX: 100% dword access ok here? */ - for (i = 0; i < 16; i++) - pci_read_config_dword(dev, i * 4,&buffer[i]); - } + /* XXX: 100% dword access ok here? */ + for (i = 0; i < 16; i++) + pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); return 0; } @@ -329,27 +324,12 @@ pci_save_state(struct pci_dev *dev, u32 *buffer) * */ int -pci_restore_state(struct pci_dev *dev, u32 *buffer) +pci_restore_state(struct pci_dev *dev) { int i; - if (buffer) { - for (i = 0; i < 16; i++) - pci_write_config_dword(dev,i * 4, buffer[i]); - } - /* - * otherwise, write the context information we know from bootup. - * This works around a problem where warm-booting from Windows - * combined with a D3(hot)->D0 transition causes PCI config - * header data to be forgotten. - */ - else { - for (i = 0; i < 6; i ++) - pci_write_config_dword(dev, - PCI_BASE_ADDRESS_0 + (i * 4), - dev->resource[i].start); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + for (i = 0; i < 16; i++) + pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]); return 0; } @@ -385,10 +365,25 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) int pci_enable_device(struct pci_dev *dev) { + int err; + dev->is_enabled = 1; - return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1))) + return err; + pci_fixup_device(pci_fixup_enable, dev); + return 0; } +/** + * pcibios_disable_device - disable arch specific PCI resources for device dev + * @dev: the PCI device to disable + * + * Disables architecture specific PCI resources for the device. This + * is the default implementation. Architecture implementations can + * override this. + */ +void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {} + /** * pci_disable_device - Disable PCI device after use * @dev: PCI device to be disabled @@ -409,6 +404,8 @@ pci_disable_device(struct pci_dev *dev) pci_command &= ~PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, pci_command); } + + pcibios_disable_device(dev); } /** @@ -747,8 +744,8 @@ static int __devinit pci_init(void) { struct pci_dev *dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - pci_fixup_device(PCI_FIXUP_FINAL, dev); + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + pci_fixup_device(pci_fixup_final, dev); } return 0; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index a9b243770..afa4164d5 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -2,7 +2,9 @@ extern int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); -extern void pci_create_sysfs_dev_files(struct pci_dev *pdev); +extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); +extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); +extern void pci_cleanup_rom(struct pci_dev *dev); extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, unsigned long size, unsigned long align, unsigned long min, unsigned int type_mask, @@ -61,5 +63,26 @@ extern int pci_visit_dev(struct pci_visit *fn, /* Lock for read/write access to pci device and bus lists */ extern spinlock_t pci_bus_lock; -extern int pciehp_msi_quirk; +extern int pcie_mch_quirk; extern struct device_attribute pci_dev_attrs[]; + +/** + * pci_match_one_device - Tell if a PCI device structure has a matching + * PCI device id structure + * @id: single PCI device id structure to match + * @dev: the PCI device structure to match against + * + * Returns the matching pci_device_id structure or %NULL if there is no match. + */ +static inline const struct pci_device_id * +pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) +{ + if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) && + (id->device == PCI_ANY_ID || id->device == dev->device) && + (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) && + (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) && + !((id->class ^ dev->class) & id->class_mask)) + return id; + return NULL; +} + diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids index c1f3d74cc..7427c2311 100644 --- a/drivers/pci/pci.ids +++ b/drivers/pci/pci.ids @@ -7,7 +7,7 @@ # so if you have anything to contribute, please visit the home page or # send a diff -u against the most recent pci.ids to pci-ids@ucw.cz. # -# Daily snapshot on Thu 2004-04-15 10:00:04 +# Daily snapshot on Mon 2004-07-12 10:00:27 # # Vendors, devices and subsystems. Please keep sorted. @@ -150,37 +150,58 @@ 0e11 4082 Smart Array 532 0e11 4083 Smart Array 5312 b1a4 NC7131 Gigabit Server Adapter + b203 Integrated Lights Out Controller + b204 Integrated Lights Out Processor f130 NetFlex-3/P ThunderLAN 1.0 f150 NetFlex-3/P ThunderLAN 2.3 0e55 HaSoTec GmbH # Formerly NCR 1000 LSI Logic / Symbios Logic 0001 53c810 - 1000 1000 8100S + 1000 1000 LSI53C810AE PCI to SCSI I/O Processor 0002 53c820 0003 53c825 + 1000 1000 LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide) 0004 53c815 0005 53c810AP 0006 53c860 + 1000 1000 LSI53C860E PCI to Ultra SCSI I/O Processor 000a 53c1510 - 000b 53c896 + 1000 1000 LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode) + 000b 53C896/897 + 1000 1000 LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller + 1000 1010 LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter + 1000 1020 LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter +# multifunction PCI card: Dual U2W SCSI, dual 10/100TX, graphics + 13e9 1000 6221L-4U 000c 53c895 + 1000 1010 LSI8951U PCI to Ultra2 SCSI host adapter + 1000 1020 LSI8952U PCI to Ultra2 SCSI host adapter + 1de1 3906 DC-390U2B SCSI adapter 1de1 3907 DC-390U2W 000d 53c885 000f 53c875 0e11 7004 Embedded Ultra Wide SCSI Controller + 1000 1000 LSI53C876/E PCI to Dual Channel SCSI Controller + 1000 1010 LSI22801 PCI to Dual Channel Ultra SCSI host adapter + 1000 1020 LSI22802 PCI to Dual Channel Ultra SCSI host adapter 1092 8760 FirePort 40 Dual SCSI Controller - 1de1 3904 DC390F Ultra Wide SCSI Controller + 1de1 3904 DC390F/U Ultra Wide SCSI Adapter 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard 4c53 1050 CT7 mainboard - 0010 53c895 + 0010 53C1510 0e11 4040 Integrated Array Controller 0e11 4048 Integrated Array Controller + 1000 1000 53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode) 0012 53c895a + 1000 1000 LSI53C895A PCI to Ultra2 SCSI Controller 0013 53c875a + 1000 1000 LSI53C875A PCI to Ultra SCSI Controller 0020 53c1010 Ultra3 SCSI Adapter + 1000 1000 LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller 1de1 1020 DC-390U3W 0021 53c1010 66MHz Ultra3 SCSI Adapter + 1000 1000 LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller 124b 1070 PMC-USCSI3 4c53 1080 CT8 mainboard 4c53 1300 P017 mezzanine (32-bit PMC) @@ -191,6 +212,7 @@ 1028 1010 LSI U320 SCSI Controller 0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI 0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 1000 1000 LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller 0033 1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI 0040 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI 1000 0033 MegaRAID SCSI 320-2XR @@ -203,8 +225,22 @@ 1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller 1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller 1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller - 1028 0533 PowerEgde Expandable RAID Controller 4/QC - 8086 0532 Storage RAID Controller SRCU42X + 1028 0531 PowerEdge Expandable RAID Controller 4/QC + 8086 0530 MegaRAID Intel RAID Controller SRCZCRX + 8086 0532 MegaRAID Intel RAID Controller SRCU42X + 0408 MegaRAID + 1000 0001 MegaRAID SCSI 320-1E RAID Controller + 1000 0002 MegaRAID SCSI 320-2E RAID Controller + 1028 0001 Dell PowerEdge RAID Controller PERC4e/SC + 1028 0002 Dell PowerEdge RAID Controller PERC4e/DC + 1734 1065 FSC MegaRAID PCI Express ROMB + 8086 0002 MegaRAID Intel RAID Controller SRCU42E + 0409 MegaRAID + 1000 3004 MegaRAID SATA 300-4X RAID Controller + 1000 3008 MegaRAID SATA 300-8X RAID Controller + 8086 3008 MegaRAID Intel RAID Controller SRCS28X + 8086 3431 MegaRAID Intel RAID Controller Alief SROMBU42E + 8086 3499 MegaRAID Intel RAID Controller Harwich SROMBU42E 0621 FC909 Fibre Channel Adapter 0622 FC929 Fibre Channel Adapter 1000 1020 44929 O Dual Fibre Channel card @@ -228,13 +264,16 @@ 1960 MegaRAID 1000 0518 MegaRAID 518 SCSI 320-2 Controller 1000 0520 MegaRAID 520 SCSI 320-1 Controller - 1000 0522 MegaRAID 522 i4133 RAID Controller + 1000 0522 MegaRAID 522 i4 133 RAID Controller 1000 0523 MegaRAID SATA 150-6 RAID Controller 1000 4523 MegaRAID SATA 150-4 RAID Controller 1000 a520 MegaRAID ZCR SCSI 320-0 Controller 1028 0518 MegaRAID 518 DELL PERC 4/DC RAID Controller 1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller 1028 0531 PowerEdge Expandable RAID Controller 4/QC + 1028 0533 PowerEdge Expandable RAID Controller 4/QC + 8086 0520 MegaRAID Intel RAID Controller SRCU41L + 8086 0523 MegaRAID Intel RAID Controller SRCS16 1001 Kolter Electronic 0010 PCI 1616 Measurement card with 32 digital I/O lines 0011 OPTO-PCI Opto-Isolated digital I/O board @@ -350,6 +389,8 @@ 1002 8008 Rage XL 1028 00ce PowerEdge 1400 1028 00d1 PowerEdge 2550 + 8086 3411 SDS2 Mainboard + 8086 3427 S875WP1-E mainboard 4753 Rage XC 1002 4753 Rage XC 4754 3D Rage I/II 215GT [Mach64 GT] @@ -435,10 +476,12 @@ 4e44 Radeon R300 ND [Radeon 9700 Pro] 4e45 Radeon R300 NE [Radeon 9500 Pro] 1002 0002 Radeon R300 NE [Radeon 9500 Pro] + 1681 0002 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] # New PCI ID provided by ATI developer relations (correction to above) 4e46 RV350 NF [Radeon 9600] 4e47 Radeon R300 NG [FireGL X1] - 4e48 Radeon R350 [Radeon 9800] +# (added pro) + 4e48 Radeon R350 [Radeon 9800 Pro] # New PCI ID provided by ATI developer relations 4e49 Radeon R350 [Radeon 9800] 4e4a RV350 NJ [Radeon 9800 XT] @@ -451,10 +494,12 @@ 4e64 Radeon R300 [Radeon 9700 Pro] (Secondary) 4e65 Radeon R300 [Radeon 9500 Pro] (Secondary) 1002 0003 Radeon R300 NE [Radeon 9500 Pro] + 1681 0003 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary) # New PCI ID provided by ATI developer relations (correction to above) 4e66 RV350 NF [Radeon 9600] (Secondary) 4e67 Radeon R300 [FireGL X1] (Secondary) - 4e68 Radeon R350 [Radeon 9800] (Secondary) +# (added pro) + 4e68 Radeon R350 [Radeon 9800 Pro] (Secondary) # New PCI ID provided by ATI developer relations 4e69 Radeon R350 [Radeon 9800] (Secondary) 4e6a RV350 NJ [Radeon 9800 XT] (Secondary) @@ -535,6 +580,7 @@ 148c 2024 RV200 QW [Radeon 7500LE Dual Display] 148c 2025 RV200 QW [Radeon 7500 Evil Master Multi Display Edition] 148c 2036 RV200 QW [Radeon 7500 PCI Dual Display] + 174b 7146 RV200 QW [Radeon 7500 LE] 174b 7147 RV200 QW [Sapphire Radeon 7500LE] 174b 7161 Radeon RV200 QW [Radeon 7500 LE] 17af 0202 RV200 QW [Excalibur Radeon 7500LE] @@ -624,6 +670,7 @@ 5d44 RV280 [Radeon 9200 SE] (Secondary) 700f PCI Bridge [IGP 320M] 7010 PCI Bridge [IGP 340M] + 7c37 RV350 AQ [Radeon 9600 SE] cab0 AGP Bridge [IGP 320M] cab2 RS200/RS200M AGP Bridge [IGP 340M] 1003 ULSI Systems @@ -865,6 +912,8 @@ 1014 002e ServeRAID-3x 1014 022e ServeRAID-4H 0031 2 Port Serial Adapter +# AS400 iSeries PCI sync serial card + 1014 0031 2721 WAN IOA - 2 Port Sync Serial Adapter 0036 Miami 003a CPU to PCI Bridge 003c GXT250P/GXT255P Graphics Adapter @@ -924,6 +973,7 @@ 0180 Snipe chipset SCSI controller 1014 0241 iSeries 2757 DASD IOA 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780) + 1014 02BD Quad Channel PCI-X U320 DDR SCSI RAID Adapter (570F) 01a7 PCI-X to PCI-X Bridge 01bd ServeRAID Controller 1014 01be ServeRAID-4M @@ -946,7 +996,9 @@ 0266 PCI-X Dual Channel SCSI 0268 Gigabit Ethernet-SX Adapter (PCI-X) 0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X) - 0302 XA-32 chipset [Summit] + 028C Citrine chipset SCSI controller + 1014 02BE Dual Channel PCI-X U320 DDR SCSI RAID Adapter (571B) + 0302 X-Architecture Bridge [Summit] ffff MPIC-2 interrupt controller 1015 LSI Logic Corp of Canada 1016 ICL Personal Systems @@ -1059,20 +1111,27 @@ 7454 AMD-8151 System Controller 7455 AMD-8151 AGP Bridge 7460 AMD-8111 PCI + 161f 3017 HDAMB 7461 AMD-8111 USB 7462 AMD-8111 Ethernet 7464 AMD-8111 USB + 161f 3017 HDAMB 7468 AMD-8111 LPC + 161f 3017 HDAMB 7469 AMD-8111 IDE + 161f 3017 HDAMB 746a AMD-8111 SMBus 2.0 746b AMD-8111 ACPI + 161f 3017 HDAMB 746d AMD-8111 AC97 Audio + 161f 3017 HDAMB 746e AMD-8111 MC97 Modem 756b AMD-8111 ACPI 1023 Trident Microsystems 0194 82C194 2000 4DWave DX 2001 4DWave NX + 122d 1400 Trident PCI288-Q3DII (NX) 2100 CyberBlade XP4m32 8400 CyberBlade/i7 1023 8400 CyberBlade i7 AGP @@ -1083,7 +1142,7 @@ 0e11 b16e CyberBlade i1 AGP 1023 8520 CyberBlade i1 AGP 8620 CyberBlade/i1 - 1014 0502 ThinkPad T30 + 1014 0502 ThinkPad R30/T30 8820 CyberBlade XPAi1 9320 TGUI 9320 9350 GUI Accelerator @@ -1179,34 +1238,32 @@ 5453 M5453 PCI AC-Link Controller Modem Device 7101 M7101 PCI PMU Power Management Controller 10b9 7101 M7101 PCI PMU Power Management Controller -1028 Dell Computer Corporation +1028 Dell 0001 PowerEdge Expandable RAID Controller 2/Si - 1028 0001 PowerEdge Expandable RAID Controller 2/Si - 0002 PowerEdge Expandable RAID Controller 3 - 1028 0002 PowerEdge Expandable RAID Controller 3/Di - 1028 00d1 PowerEdge Expandable RAID Controller 3/Di - 1028 00d9 PowerEdge Expandable RAID Controller 3/Di + 1028 0001 PowerEdge 2400 + 0002 PowerEdge Expandable RAID Controller 3/Di + 1028 0002 PowerEdge 4400 0003 PowerEdge Expandable RAID Controller 3/Si - 1028 0003 PowerEdge Expandable RAID Controller 3/Si - 0004 PowerEdge Expandable RAID Controller 3/Si - 1028 00d0 PowerEdge Expandable RAID Controller 3/Si + 1028 0003 PowerEdge 2450 0006 PowerEdge Expandable RAID Controller 3/Di - 0007 Remote Access Controller:DRAC III - 0008 Remote Access Controller - 0009 BMC/SMIC device not present - 000a PowerEdge Expandable RAID Controller 3 - 1028 0106 PowerEdge Expandable RAID Controller 3/Di - 1028 011b PowerEdge Expandable RAID Controller 3/Di - 1028 0121 PowerEdge Expandable RAID Controller 3/Di - 000c Remote Access Controller:ERA or ERA/O - 000d BMC/SMIC device - 000e PowerEdge Expandable RAID controller 4 - 1028 0123 PowerEdge Expandable RAID Controller 4/Di - 000f PowerEdge Expandable RAID controller 4 - 1028 013b MegaRAID DELL PERC 4/Di RAID On Motherboard - 1028 014a PowerEdge Expandable RAID Controller 4/Di - 1028 014c MegaRAID DELL PERC 4/Di RAID On Motherboard - 1028 014d MegaRAID DELL PERC 4/Di RAID On Motherboard + 0007 Remote Access Card III + 0008 Remote Access Card III + 0009 Remote Access Card III: BMC/SMIC device not present + 000a PowerEdge Expandable RAID Controller 3/Di + 000c Embedded Remote Access or ERA/O + 000d Embedded Remote Access: BMC/SMIC device + 000e PowerEdge Expandable RAID controller 4/Di + 000f PowerEdge Expandable RAID controller 4/Di + 0010 Remote Access Card 4 + 0011 Remote Access Card 4 Daughter Card + 0012 Remote Access Card 4 Daughter Card Virtual UART + 0013 PowerEdge Expandable RAID controller 4 + 1028 016c PowerEdge Expandable RAID Controller 4e/Si + 1028 016d PowerEdge Expandable RAID Controller 4e/Di + 1028 016e PowerEdge Expandable RAID Controller 4e/Di + 1028 016f PowerEdge Expandable RAID Controller 4e/Di + 1028 0170 PowerEdge Expandable RAID Controller 4e/Di + 0014 Remote Access Card 4 Daughter Card SMIC interface 1029 Siemens Nixdorf IS 102a LSI Logic 0000 HYDRA @@ -1518,6 +1575,7 @@ 1039 5513 SiS5513 EIDE Controller (A,B step) 1043 8035 CUSI-FX motherboard 5517 5517 + 5518 5518 [IDE] 5571 5571 5581 5581 Pentium Chipset 5582 5582 @@ -1542,6 +1600,7 @@ 1092 4920 SpeedStar A70 1569 6326 SiS6326 GUI Accelerator 6330 661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP + 1039 6330 [M]661FX/M661MX/[M]741/[M]760 PCI/AGP VGA Display Adapter 7001 USB 1.0 Controller 1039 7000 Onboard USB Controller 7002 USB 2.0 Controller @@ -1604,7 +1663,7 @@ 103c 1049 Tosca Console 103c 104a Tosca Secondary 103c 104b Maestro SP2 - 103c 1223 Halfdome Console + 103c 1223 Superdome Console 103c 1226 Keystone SP2 103c 1227 Powerbar SP2 103c 1282 Everest SP2 @@ -1642,7 +1701,7 @@ 4057 v8200 GeForce 3 8043 v8240 PAL 128M [P4T] Motherboard 807b v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI] -1044 Distributed Processing Technology +1044 Adaptec (formerly DPT) 1012 Domino RAID Engine a400 SmartCache/Raid I-IV Controller a500 PCI Bridge @@ -1683,6 +1742,7 @@ 1044 c065 3010S Ultra3 Four Channel 1044 c066 3010S Fibre Channel a511 SmartRAID V Controller + 1044 c032 ASR-2005S I2O Zero Channel 1045 OPTi Inc. a0f8 82C750 [Vendetta] USB Controller c101 92C264 @@ -1786,6 +1846,7 @@ 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100) 8029 PCI4510 IEEE-1394 Controller 1071 8160 MIM2900 + 802e PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller 8400 ACX 100 22Mbps Wireless Interface 00fc 16ec U.S. Robotics 22 Mbps Wireless PC Card (model 2210) 00fd 16ec U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216) @@ -1894,6 +1955,8 @@ 0003 MPC8240 [Kahlua] 0004 MPC107 0006 MPC8245 [Unity] + 0008 MPC8540 + 0009 MPC8560 0100 MC145575 [HFC-PCI] 0431 KTI829c 100VG 1801 DSP56301 Digital Signal Processor @@ -1939,44 +2002,49 @@ 1058 Electronics & Telecommunications RSH 1059 Teknor Industrial Computers Inc 105a Promise Technology, Inc. - 0d30 20265 +# more correct description from promise linux sources + 0d30 PDC20265 (FastTrak100 Lite/Ultra100) 105a 4d33 Ultra100 0d38 20263 105a 4d39 Fasttrak66 1275 20275 3318 PDC20318 (SATA150 TX4) - 3319 PDC20319 (SATA150 TX4) - 3373 PDC20378 (SATA150 TX) + 3319 PDC20319 (FastTrak S150 TX4) + 8086 3427 S875WP1-E mainboard + 3371 PDC20371 (FastTrak S150 TX2plus) + 3373 PDC20378 (FastTrak 378/SATA 378) + 1043 80f5 PC-DL Deluxe motherboard 1462 702e K8T NEO FIS2R motherboard 3375 PDC20375 (SATA150 TX2plus) - 3376 PDC20376 + 3376 PDC20376 (FastTrak 376) 1043 809e A7V8X motherboard - 4d30 20267 + 4d30 PDC20267 (FastTrak100/Ultra100) 105a 4d33 Ultra100 - 105a 4d39 Fasttrak100 + 105a 4d39 FastTrak100 4d33 20246 105a 4d33 20246 IDE Controller - 4d38 20262 + 4d38 PDC20262 (FastTrak66/Ultra66) 105a 4d30 Ultra Device on SuperTrak 105a 4d33 Ultra66 - 105a 4d39 Fasttrak66 - 4d68 20268 + 105a 4d39 FastTrak66 + 4d68 PDC20268 (Ultra100 TX2) 105a 4d68 Ultra100TX2 4d69 20269 105a 4d68 Ultra133TX2 - 5275 PDC20276 IDE + 5275 PDC20276 (MBFastTrak133 Lite) 105a 0275 SuperTrak SX6000 IDE 105a 1275 MBFastTrak133 Lite (tm) Controller (RAID mode) 1458 b001 MBUltra 133 5300 DC5300 - 6268 20268R - 6269 PDC20271 + 6268 PDC20270 (FastTrak100 LP/TX2/TX4) + 105a 4d68 FastTrak100 TX2 + 6269 PDC20271 (FastTrak TX2000) 105a 6269 FastTrak TX2/TX2000 - 6621 PDC20621 [SX4000] 4 Channel IDE RAID Controller + 6621 PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite) 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller - 6626 PDC20618 Ultra 618 - 6629 PDC20619 FastTrak TX4000 RAID - 7275 PDC20277 + 6626 PDC20618 (Ultra 618) + 6629 PDC20619 (FastTrak TX4000) + 7275 PDC20277 (SBFastTrak133 Lite) 105b Foxconn International, Inc. 105c Wipro Infotech Limited 105d Number 9 Computer Company @@ -2070,6 +2138,8 @@ 1014 0242 iSeries 2872 DASD IOA 1014 0266 Dual Channel PCI-X U320 SCSI Adapter 1014 0278 Dual Channel PCI-X U320 SCSI RAID Adapter + 1014 02D3 Dual Channel PCI-X U320 SCSI Adapter + 1014 02D4 Dual Channel PCI-X U320 SCSI RAID Adapter ba55 eXtremeRAID 1100 support Device ba56 eXtremeRAID 2000/3000 support Device 106a Aten Research Inc @@ -2199,6 +2269,7 @@ 107c LG Electronics [Lucky Goldstar Co. Ltd] 107d LeadTek Research Inc. 0000 P86C850 + 2134 WinFast 3D S320 II 107e Interphase Corporation 0001 5515 ATM Adapter [Flipper] 0002 100 VG AnyLan Controller @@ -2348,10 +2419,10 @@ 0673 USB0673 0680 PCI0680 Ultra ATA-133 Host Controller 1095 3680 Winic W-680 (Silicon Image 680 based) - 3112 Silicon Image Serial ATARaid Controller [ CMD/Sil 3112/3112A ] + 3112 SiI 3112 [SATALink/SATARaid] Serial ATA Controller 1095 6112 Asus A7N8X - 3114 Silicon Image SiI 3114 SATARaid - 3512 Silicon Image Serial ATARaid Controller [ CMD/Sil 3512 ] + 3114 SiI 3114 [SATALink/SATARaid] Serial ATA Controller + 3512 SiI 3512 [SATALink/SATARaid] Serial ATA Controller 1096 Alacron 1097 Appian Technology 1098 Quantum Designs (H.K.) Ltd @@ -2742,6 +2813,7 @@ 10b7 7000 10/100 Mini PCI Ethernet Adapter 10f1 2466 Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller) 9201 3C920B-EMB Integrated Fast Ethernet Controller [Tornado] + 1043 80ab A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller 9202 3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller 9300 3CSOHO100B-TX 910-A01 [tulip] @@ -2837,6 +2909,7 @@ 5219 M5219 5225 M5225 5229 M5229 IDE + 1014 050f ThinkPad R30 1043 8053 A7A266 Motherboard IDE 5235 M5225 5237 USB 1.1 Controller @@ -2859,8 +2932,8 @@ 545a SmartLink SmartPCI563 56K Modem 5471 M5471 Memory Stick Controller 5473 M5473 SD-MMC Controller - 7101 M7101 PMU - 10b9 7101 ALI M7101 Power Management Controller + 7101 M7101 Power Management Controller [PMU] + 1014 0510 ThinkPad R30 10ba Mitsubishi Electric Corp. 0301 AccelGraphics AccelECLIPSE 0304 AccelGALAXY A2100 [OEM Evans & Sutherland] @@ -3001,6 +3074,7 @@ 1043 0205 PCI-V3800 1043 4000 AGP-V3800PRO 1048 0c21 Synergy II + 107d 2134 WinFast 3D S320 II + TV-Out 1092 4804 Viper V770 1092 4a00 Viper V770 1092 4a02 Viper V770 Ultra @@ -3041,11 +3115,13 @@ 1554 1041 Pixelview RIVA TNT2 M64 002e NV6 [Vanta] 002f NV6 [Vanta] + 0041 NV40 OS1RT00B30 0060 nForce2 ISA Bridge 1043 80ad A7N8X Mainboard 0064 nForce2 SMBus (MCP) 0065 nForce2 IDE 0066 nForce2 Ethernet Controller + 1043 80a7 A7N8X Mainboard onboard nForce2 Ethernet 0067 nForce2 USB Controller 1043 0c11 A7N8X Mainboard 0068 nForce2 USB Controller @@ -3292,6 +3368,7 @@ 1071 8160 MIM2000 10bd 0320 EP-320X-R 10ec 8139 RT8139 + 1113 ec01 FNC-0107TX 1186 1300 DFE-538TX 1186 1320 SN5200 1186 8139 DRN-32TX @@ -3342,7 +3419,7 @@ 10f9 PC Direct 10fa Truevision 000c TARGA 1000 -10fb Thesys Gesellschaft für Mikroelektronik mbH +10fb Thesys Gesellschaft für Mikroelektronik mbH 186f TH 6255 10fc I-O Data Device, Inc. # What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives @@ -3358,6 +3435,7 @@ 9400 INI-940 9401 INI-950 9500 360P + 9502 Initio INI-9100UW Ultra Wide SCSI Controller INIC-950P chip 1102 Creative Labs 0002 SB Live! EMU10k1 1102 0020 CT4850 SBLive! Value @@ -3507,13 +3585,16 @@ 0e11 0097 SoundMax Digital Integrated Audio 0e11 b194 Soundmax integrated digital audio 1019 0985 P6VXA Motherboard + 1043 1106 A7V133/A7V133-C Mainboard 1106 4511 Onboard Audio on EP7KXA 1458 7600 Onboard Audio 1462 3091 MS-6309 Onboard Audio + 1462 3300 MS-6330 Onboard Audio 15dd 7609 Onboard Audio 3059 VT8233/A/8235/8237 AC97 Audio Controller 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) 1043 8095 A7V8X Motherboard (Realtek ALC650 codec) + 1043 80a1 A7V8X-X Motherboard 1043 80b0 A7V600 motherboard (ADI AD1980 codec [SoundMAX]) 1106 3059 L7VMM2 Motherboard 1297 c160 FX41 motherboard (Realtek ALC650 codec) @@ -3526,6 +3607,7 @@ 1186 1401 DFE-530TX rev B 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B) 3068 Intel 537 [AC97 Modem] + 1462 309e MS-6309 Saturn Motherboard 3074 VT8233 PCI to ISA Bridge 1043 8052 VT8233A 3091 VT8633 [Apollo Pro266] @@ -3906,7 +3988,15 @@ 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ 3 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ 3 e01e Diva Server 2PRI + 1133 1e00 Diva Server V-2PRI/E1-60 + 1133 1e01 Diva Server V-2PRI/T1-48 + 1133 1e02 Diva Server 2PRI/E1-60 + 1133 1e03 Diva Server 2PRI/T1-48 e020 Diva Server 4PRI + 1133 2000 Diva Server V-4PRI/E1-120 + 1133 2001 Diva Server V-4PRI/T1-96 + 1133 2002 Diva Server 4PRI/E1-120 + 1133 2003 Diva Server 4PRI/T1-96 e024 Diva Server Analog-4P e028 Diva Server Analog-8P 1134 Mercury Computer Systems @@ -4145,6 +4235,7 @@ 1165 Imagraph Corporation 0001 Motion TPEG Recorder/Player with audio 1166 ServerWorks + 0000 CMIC-LE 0005 CNB20-LE Host Bridge 0006 CNB20HE Host Bridge 0007 CNB20-LE Host Bridge @@ -4152,13 +4243,13 @@ 0009 CNB20LE Host Bridge 0010 CIOB30 0011 CMIC-HE - 0012 CMIC-LE + 0012 CMIC-WS Host Bridge (GC-LE chipset) 0013 CNB20-HE Host Bridge - 0014 CNB20-HE Host Bridge + 0014 CMIC-LE Host Bridge (GC-LE chipset) 0015 CMIC-GC Host Bridge 0016 CMIC-GC Host Bridge 0017 GCNB-LE Host Bridge - 0101 CIOB-X2 + 0101 CIOB-X2 PCI-X I/O Bridge 0110 CIOB-E I/O Bridge with Gigabit Ethernet 0200 OSB4 South Bridge 0201 CSB5 South Bridge @@ -4255,6 +4346,7 @@ 1186 1300 DFE-538TX 10/100 Ethernet Adapter 1186 1301 DFE-530TX+ 10/100 Ethernet Adapter 1340 DFE-690TXD CardBus PC Card + 1541 DFE-680TXD CardBus PC Card 1561 DRP-32TXD Cardbus PC Card 3300 DWL-510 2.4GHz Wireless PCI Adapter 3b05 DWL-G650+ CardBus PC Card @@ -4337,9 +4429,10 @@ 11a9 InnoSys Inc. 4240 AMCC S933Q Intelligent Serial Card 11aa Actel -# (formerly Galileo technologies) -11ab Marvell +# Formerly Galileo Technology, Inc. +11ab Marvell Technology Group Ltd. 0146 GT-64010/64010A System Controller + 1fa6 Marvell W8300 802.11 Adapter 4320 Yukon Gigabit Ethernet 10/100/1000Base-T Adapter 4611 GT-64115 System Controller 4620 GT-64120/64120A/64121A System Controller @@ -4677,6 +4770,7 @@ 6933 OZ6933 Cardbus Controller 1025 1016 Travelmate 612 TX 6972 OZ6912 Cardbus Controller + 1014 020c ThinkPad R30 1179 0001 Magnia Z310 7110 OZ711Mx MultiMediaBay Accelerator 7112 OZ711EC1/M1 SmartCardBus MultiMediaBay Controller @@ -4762,6 +4856,7 @@ 122c Sican GmbH 122d Aztech System Ltd 1206 368DSP + 1400 Trident PCI288-Q3DII (NX) 50dc 3328 Audio 122d 0001 3328 Audio 80da 3328 Audio @@ -4905,11 +5000,15 @@ 3873 Prism 2.5 Wavelan chipset 1186 3501 DWL-520 Wireless PCI Adapter 1186 3700 DWL-520 Wireless PCI Adapter, Rev E1 + 1385 4105 MA311 802.11b wireless adapter 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter 16a5 1601 AIR.mate PC-400 PCI Wireless LAN Adapter 1737 3874 WMP11 Wireless 802.11b PCI Adapter 8086 2513 Wireless 802.11b MiniPCI Adapter + 3886 ISL3886 [Prism Javelin/Prism Xbow] 3890 Intersil ISL3890 [Prism GT/Prism Duette] + 10b8 a835 SMC2835W V2 Wireless Cardbus Adapter + 16a5 1605 ALLNET ALL0271 Wireless PCI Adapter 17cf 0014 Ovislink WL-5400PCM, Prism GT 8130 HMP8130 NTSC/PAL Video Decoder 8131 HMP8131 NTSC/PAL Video Decoder @@ -5155,7 +5254,7 @@ 9132 Ethernet 100/10 MBit 1283 Integrated Technology Express, Inc. 673a IT8330G - 8212 IT/ITE8212 Dual channel ATA RAID + 8212 IT/ITE8212 Dual channel ATA RAID controller 8330 IT8330G 8872 IT8874F PCI Dual Serial Port Controller 8888 IT8888F PCI to ISA Bridge with SMB @@ -5466,7 +5565,8 @@ 0985 NC100 Network Everywhere Fast Ethernet 10/100 1985 21x4x DEC-Tulip compatible 10/100 Ethernet 2850 HSP MicroModem 56 - 8201 [ADMtek] SP906B_V2 Wireless LAN adapter + 8201 ADMtek ADM8211 802.11b Wireless Interface + 10b8 2635 SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card 1317 8201 SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card 9511 21x4x DEC-Tulip compatible 10/100 Ethernet 1318 Packet Engines Inc. @@ -5535,7 +5635,6 @@ 132d Integrated Silicon Solution, Inc. 1330 MMC Networks 1331 Radisys Corp. - 0030 ENP-2611 8200 82600 Host Bridge 8201 82600 IDE 8202 82600 USB @@ -5659,9 +5758,11 @@ 1385 Netgear 4100 802.11b Wireless Adapter (MA301) 4105 MA311 802.11b wireless adapter + 4a00 WAG311 802.11abg Wireless Adapter 620a GA620 Gigabit Ethernet 622a GA622 630a GA630 Gigabit Ethernet + f004 FA310TX 1386 Video Domain Technologies 1387 Systran Corp 1388 Hitachi Information Technology Co Ltd @@ -5720,6 +5821,7 @@ 13a6 Videonics Inc 13a7 Teles AG 13a8 Exar Corp. + 0154 XR17C154 Quad UART 0158 XR17C158 Octal UART 13a9 Siemens Medical Systems, Ultrasound Group 13aa Broadband Networks Inc @@ -5752,6 +5854,7 @@ 13c1 3ware Inc 1000 3ware ATA-RAID 1001 3ware 7000-series ATA-RAID + 13c1 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID 1002 3ware ATA-RAID 13c2 Technotrend Systemtechnik GmbH 13c3 Janz Computer AG @@ -5884,10 +5987,11 @@ 140f Salient Systems Corp 1410 Midas lab Inc 1411 Ikos Systems Inc -1412 IC Ensemble Inc - 1712 ICE1712 [Envy24] +# formerly IC Ensemble Inc. +1412 VIA Technologies Inc. + 1712 ICE1712 [Envy24] PCI Multi-Channel I/O Controller 1412 d638 M-Audio Delta 410 - 1724 ICE1724 [Envy24HT] + 1724 VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller 1413 Addonics 1414 Microsoft Corporation 1415 Oxford Semiconductor Ltd @@ -5990,6 +6094,7 @@ 1460 DYNARC INC 1461 Avermedia Technologies Inc 1462 Micro-Star International Co., Ltd. + 6825 PCI Card wireless 11g [PC54G] 8725 NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter # MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I 9000 NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter @@ -6150,8 +6255,9 @@ 14d6 Accusys Inc 14d7 Hirakawa Hewtech Corp 14d8 HOPF Elektronik GmBH -14d9 Alpha Processor Inc - 0010 AP1011 HyperTransport-PCI Bridge [Sturgeon] +# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc. +14d9 Alliance Semiconductor Corporation + 0010 AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon] 14da National Aerospace Laboratories 14db AFAVLAB Technology Inc 2120 TK9902 @@ -6175,6 +6281,14 @@ 14e2 INFOLIBRIA 14e3 AMTELCO 14e4 Broadcom Corporation + 0800 Sentry5 Chipcommon I/O Controller + 0804 Sentry5 PCI Bridge + 0805 Sentry5 MIPS32 CPU + 0806 Sentry5 Ethernet Controller + 080b Sentry5 Crypto Accelerator + 080f Sentry5 DDR/SDR RAM Controller + 0811 Sentry5 External Interface Core + 0816 BCM3302 Sentry5 MIPS32 CPU 1644 NetXtreme BCM5700 Gigabit Ethernet 1014 0277 Broadcom Vigil B5700 1000Base-T 1028 00d1 Broadcom BCM5700 @@ -6241,21 +6355,14 @@ 164d NetXtreme BCM5702FE Gigabit Ethernet 1653 NetXtreme BCM5705 Gigabit Ethernet 1654 NetXtreme BCM5705_2 Gigabit Ethernet - 1658 NetXtreme BCM5720 Gigabit Ethernet - 1659 NetXtreme BCM5721 Gigabit Ethernet + 1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express 165d NetXtreme BCM5705M Gigabit Ethernet 165e NetXtreme BCM5705M_2 Gigabit Ethernet - 166e NetXtreme BCM5705F Gigabit Ethernet - 1676 NetXtreme BCM5750 Gigabit Ethernet - 1677 NetXtreme BCM5751 Gigabit Ethernet - 167c NetXtreme BCM5750M Gigabit Ethernet - 167d NetXtreme BCM5751M Gigabit Ethernet - 167e NetXtreme BCM5751F Gigabit Ethernet + 1677 NetXtreme BCM5751 Gigabit Ethernet PCI Express 1696 NetXtreme BCM5782 Gigabit Ethernet 103c 12bc HP d530 CMT (DG746A) 14e4 000d NetXtreme BCM5782 1000Base-T 169c NetXtreme BCM5788 Gigabit Ethernet - 169d NetXtreme BCM5789 Gigabit Ethernet 16a6 NetXtreme BCM5702X Gigabit Ethernet 0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T) 1028 0126 BCM5702 1000Base-T @@ -6279,13 +6386,17 @@ 103c 12ca HP Combo FC/GigE-T [A9784A] 14e4 0009 NetXtreme BCM5703 1000Base-T 14e4 000a NetXtreme BCM5703 1000Base-SX - 170d NetXtreme BCM5901 Gigabit Ethernet - 170e NetXtreme BCM5901_2 Gigabit Ethernet + 170c BCM4401-B0 100Base-TX + 170d NetXtreme BCM5901 100Base-TX + 170e NetXtreme BCM5901 100Base-TX + 3352 BCM3352 + 3360 BCM3360 4210 BCM4210 iLine10 HomePNA 2.0 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem 4212 BCM4212 v.90 56k modem 4301 BCM4301 802.11b - 4320 BCM94306 802.11g + 4307 BCM4307 802.11b Wireless LAN Controller + 4320 BCM4306 802.11b/g Wireless LAN Controller 1028 0001 TrueMobile 1300 WLAN Mini-PCI Card 1737 4320 WPC54G 4324 BCM4309 802.11a/b/g @@ -6293,12 +6404,47 @@ 4401 BCM4401 100Base-T 1043 80a8 A7V8X motherboard 4402 BCM4402 Integrated 10/100BaseT + 4403 BCM4402 V.90 56k Modem 4410 BCM4413 iLine32 HomePNA 2.0 4411 BCM4413 V.90 56k modem 4412 BCM4413 10/100BaseT + 4430 BCM44xx CardBus iLine32 HomePNA 2.0 + 4432 BCM44xx CardBus 10/100BaseT + 4610 BCM4610 Sentry5 PCI to SB Bridge + 4611 BCM4610 Sentry5 iLine32 HomePNA 1.0 + 4612 BCM4610 Sentry5 V.90 56k Modem + 4613 BCM4610 Sentry5 Ethernet Controller + 4614 BCM4610 Sentry5 External Interface + 4615 BCM4610 Sentry5 USB Controller + 4704 BCM4704 PCI to SB Bridge + 4708 BCM4708 Sentry5 PCI to SB Bridge + 4710 BCM4710 Sentry5 PCI to SB Bridge + 4711 BCM47xx Sentry5 iLine32 HomePNA 2.0 + 4712 Sentry5 UART + 4713 Sentry5 Ethernet Controller + 4714 BCM47xx Sentry5 External Interface + 4715 Sentry5 USB Controller + 4716 BCM47xx Sentry5 USB Host Controller + 4717 BCM47xx Sentry5 USB Device Controller + 4718 Sentry5 Crypto Accelerator + 5365 BCM5365P Sentry5 Host Bridge + 5600 BCM5600 StrataSwitch 24+2 Ethernet Switch Controller + 5605 BCM5605 StrataSwitch 24+2 Ethernet Switch Controller + 5615 BCM5615 StrataSwitch 24+2 Ethernet Switch Controller + 5625 BCM5625 StrataSwitch 24+2 Ethernet Switch Controller + 5645 BCM5645 StrataSwitch 24+2 Ethernet Switch Controller + 5670 BCM5670 8-Port 10GE Ethernet Switch Fabric + 5680 BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller 5690 BCM5690 12-port Multi-Layer Gigabit Ethernet Switch + 5691 BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller 5820 BCM5820 Crypto Accelerator 5821 BCM5821 Crypto Accelerator + 5822 BCM5822 Crypto Accelerator + 5823 BCM5823 Crypto Accelerator + 5824 BCM5824 Crypto Accelerator + 5840 BCM5840 Crypto Accelerator + 5841 BCM5841 Crypto Accelerator + 5850 BCM5850 Crypto Accelerator 14e5 Pixelfusion Ltd 14e6 SHINING Technology Inc 14e7 3CX @@ -6823,11 +6969,16 @@ 1619 FarSite Communications Ltd 0400 FarSync T2P (2 port X.21/V.35/V.24) 0440 FarSync T4P (4 port X.21/V.35/V.24) +# www.rioworks.com +161f Rioworks 1626 TDK Semiconductor Corp. 8410 RTL81xx Fast Ethernet 1629 Kongsberg Spacetec AS 1003 Format synchronizer v3.0 2002 Fast Universal Data Output +# This seems to occur on their 802.11b Wireless card WMP-11 +1637 Linksys + 3874 Linksys 802.11b WMP11 PCI Wireless card 1638 Standard Microsystems Corp [SMC] 1100 SMC2602W EZConnect/Addtron AWA-100/Eumitcom WL11000 163c Smart Link Ltd. @@ -6862,6 +7013,7 @@ 168c 0013 WG511T Wireless CardBus Adapter 168c 1025 DWL-G650B2 Wireless CardBus Adapter 1014 AR5212 802.11abg NIC +16a5 Tekram Technology Co.,Ltd. 16ab Global Sun Technology Inc 1100 GL24110P 1101 PLX9052 PCMCIA-to-PCI Wireless LAN @@ -6874,9 +7026,13 @@ 16cd Densitron Technologies # www.pikatechnologies.com 16df PIKA Technologies Inc. +16e3 European Space Agency + 1e0f LEON2FT Processor 16ec U.S. Robotics 00ff USR997900 10/100 Mbps PCI Network Card 3685 Wireless Access PCI Adapter Model 022415 +16f4 Vweb Corp + 8000 VW2010 16f6 VideoTele.com, Inc. # www.internetmachines.com 1702 Internet Machines Corporation (IMC) @@ -6884,8 +7040,12 @@ 170b NetOctave 0100 NSP2000-SSL crypto accelerator 170c YottaYotta Inc. +# Seems to be a 2nd ID for Vitesse Semiconductor +1725 Vitesse Semiconductor + 7174 VSC7174 PCI/PCI-X Serial ATA Host Bus Controller 172a Accelerated Encryption 1737 Linksys + 0013 WMP54G Wireless Pci Card 1032 Gigabit Network Adapter 1737 0015 EG1032 v2 Instant Gigabit Network Adapter 1064 Gigabit Network Adapter @@ -6914,10 +7074,12 @@ 0004 CAMAC Controller 0005 PROFIBUS 0006 AMCC HOTlink +1797 JumpTec h, GMBH 1799 Belkin 6001 Wireless PCI Card - F5D6001 6020 Wireless PCMCIA Card - F5D6020 6060 Wireless PDA Card - F5D6060 + 7000 Wireless PCI Card - F5D7000 17af Hightech Information System Ltd. 17b3 Hawking Technologies ab08 PN672TX 10/100 Ethernet @@ -6929,6 +7091,9 @@ 2280 USB 2.0 # S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com 17d5 S2io Inc. +# Supplying full name for a currently green entry +17fe Linksys, A Division of Cisco Systems + 2220 [AirConn] INPROCOMM IPN 2220 WLAN Adapter (rev 01) 1813 Ambient Technologies Inc 4000 HaM controllerless modem 16be 0001 V9x HAM Data Fax Modem @@ -6937,6 +7102,8 @@ 1814 RaLink 0101 Wireless PCI Adpator RT2400 / RT2460 0201 Ralink RT2500 802.11 Cardbus Reference Card +1820 InfiniCon Systems Inc. +1822 Twinhan Technology Co. Ltd 1830 Credence Systems Corporation 1851 Microtune, Inc. 1852 Anritsu Corp. @@ -6952,6 +7119,8 @@ # found e.g. on KNC DVB-S card 1894 KNC One 18a1 Astute Networks Inc. +18bc Info-Tek Corp. +18c9 ARVOO Engineering BV 18ca XGI - Xabre Graphics Inc 0040 Volari V8 18e6 MPL AG @@ -7018,6 +7187,7 @@ 0008 GLINT Gamma G1 0009 Permedia II 2D+3D 1040 0011 AccelStar II + 13e9 1000 6221L-4U 3d3d 0100 AccelStar II 3D Accelerator 3d3d 0111 Permedia 3:16 3d3d 0114 Santa Ana @@ -7269,10 +7439,11 @@ 5555 Genroco, Inc 0003 TURBOstor HFP-832 [HiPPI NIC] 5654 VoiceTronix Pty Ltd + 3132 OpenSwitch12 5700 Netpower 5851 Exacq Technologies 6356 UltraStor -6374 c't Magazin für Computertechnik +6374 c't Magazin für Computertechnik 6773 GPPCI 6409 Logitec Corp. 6666 Decision Computer International Co. @@ -7292,6 +7463,8 @@ 0008 1000 WorldMark 4300 INCA ASIC 0039 21145 Fast Ethernet 0122 82437FX + 0309 80303 I/O Processor PCI-to-PCI Bridge + 030d 80312 I/O Companion Chip PCI-to-PCI Bridge 0326 PCI Bridge Hub I/OxAPIC Interrupt Controller A 0327 PCI Bridge Hub I/OxAPIC Interrupt Controller B 0329 PCI Bridge Hub A @@ -7315,13 +7488,38 @@ 0340 41210 [Lanai] Serial to Parallel PCI Bridge # B-segment bridge 0341 41210 [Lanai] Serial to Parallel PCI Bridge - 0482 82375EB - 0483 82424ZX [Saturn] - 0484 82378IB [SIO ISA Bridge] - 0486 82430ZX [Aries] - 04a3 82434LX [Mercury/Neptune] + 0482 82375EB/SB PCI to EISA Bridge + 0483 82424TX/ZX [Saturn] CPU to PCI bridge + 0484 82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge + 0486 82425EX/ZX [Aries] PCIset with ISA bridge + 04a3 82434LX/NX [Mercury/Neptune] Processor to PCI bridge 04d0 82437FX [Triton FX] + 0500 E8870 Processor bus control + 0501 E8870 Memory controller +# and registers common to both SPs + 0502 E8870 Scalability Port 0 +# and global performance monitoring + 0503 E8870 Scalability Port 1 + 0510 E8870IO Hub Interface Port 0 registers (8-bit compatibility port) + 0511 E8870IO Hub Interface Port 1 registers + 0512 E8870IO Hub Interface Port 2 registers + 0513 E8870IO Hub Interface Port 3 registers + 0514 E8870IO Hub Interface Port 4 registers + 0515 E8870IO General SIOH registers + 0516 E8870IO RAS registers + 0530 E8870SP Scalability Port 0 registers + 0531 E8870SP Scalability Port 1 registers + 0532 E8870SP Scalability Port 2 registers + 0533 E8870SP Scalability Port 3 registers + 0534 E8870SP Scalability Port 4 registers + 0535 E8870SP Scalability Port 5 registers +# (bi-interleave 0) and global registers that are neither per-port nor per-interleave + 0536 E8870SP Interleave registers 0 and 1 +# (bi-interleave 1) + 0537 E8870SP Interleave registers 2 and 3 0600 RAID Controller + 8086 01c1 ICP Vortex GDT8546RZ + 8086 01f7 SCRU32 0960 80960RP [i960 RP Microprocessor/Bridge] 0962 80960RM [i960RM Bridge] 0964 80960RP [i960 RP Microprocessor/Bridge] @@ -7406,6 +7604,7 @@ 1019 82547EI Gigabit Ethernet Controller (LOM) 1458 1019 GA-8IPE1000 Pro2 motherboard (865PE) 8086 1019 PRO/1000 CT Desktop Connection + 8086 3427 S875WP1-E mainboard 101d 82546EB Gigabit Ethernet Controller 8086 1000 PRO/1000 MT Quad Port Server Adapter 101e 82540EP Gigabit Ethernet Controller (Mobile) @@ -7453,13 +7652,16 @@ 16be 1040 V.9X DSP Data Fax Modem 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter 8086 2527 MIM2000/Centrino - 1048 Intel(R) PRO/10GbE LR Server Adapter + 1048 PRO/10GbE LR Server Adapter 8086 a01f PRO/10GbE LR Server Adapter 8086 a11f PRO/10GbE LR Server Adapter 1050 82562EZ 10/100 Ethernet Controller 1462 728c 865PE Neo2 (MS-6728) + 1462 758c MS-6758 (875P Neo) + 8086 3427 S875WP1-E mainboard 1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller 1059 82551QM Ethernet Controller + 1065 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller # Updated controller name from 82547EI to 82547GI 1075 82547GI Gigabit Ethernet Controller 8086 0075 PRO/1000 CT Network Connection @@ -7516,8 +7718,8 @@ 4c53 1050 CT7 mainboard 4c53 1051 CE7 mainboard 4c53 1070 PC6 mainboard - 1221 82092AA_0 - 1222 82092AA_1 + 1221 82092AA PCI to PCMCIA Bridge + 1222 82092AA IDE Controller 1223 SAA7116 1225 82452KX/GX [Orion] 1226 82596 PRO/10 PCI @@ -7587,6 +7789,7 @@ 1259 2560 AT-2560 100 1259 2561 AT-2560 100 FX Ethernet Adapter 1266 0001 NE10/100 Adapter + 13e9 1000 6221L-4U 144d 2501 SEM-2000 MiniPCI LAN Adapter 144d 2502 SEM-2100IL MiniPCI LAN Adapter 1668 1100 EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem) @@ -7675,6 +7878,7 @@ 8086 3010 EtherExpress PRO/100 S Network Connection 8086 3011 EtherExpress PRO/100 S Network Connection 8086 3012 EtherExpress PRO/100 Network Connection + 8086 3411 SDS2 Mainboard 122d 430FX - 82437FX TSC [Triton I] 122e 82371FB PIIX ISA [Triton I] 1230 82371FB PIIX IDE [Triton I] @@ -7682,13 +7886,15 @@ 1234 430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX) 1235 430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP) 1237 440FX - 82441FX PMC [Natoma] - 1239 82371FB - 123b 82380PB - 123c 82380AB + 1239 82371FB PIIX IDE Interface + 123b 82380PB PCI to PCI Docking Bridge + 123c 82380AB (MISA) Mobile PCI-to-ISA Bridge 123d 683053 Programmable Interrupt Device +# in" hidden" mode + 123e 82466GX (IHPC) Integrated Hot-Plug Controller 123f 82466GX Integrated Hot-Plug Controller (IHPC) - 1240 752 AGP - 124b 82380FB + 1240 82752 (752) AGP Graphics Accelerator + 124b 82380FB (MPCI2) Mobile Docking Controller 1250 430HX - 82439HX TXC [Triton II] 1360 82806AA PCI64 Hub PCI Bridge 1361 82806AA PCI64 Hub Controller (HRes) @@ -7782,7 +7988,7 @@ 2446 Intel 537 [82801BA/BAM AC'97 Modem] 1025 1016 Travelmate 612 TX 104d 80df Vaio PCG-FX403 - 2448 82801BAM/CAM PCI Bridge + 2448 82801 PCI Bridge 2449 82801BA/BAM/CA/CAM Ethernet Controller 0e11 0012 EtherExpress PRO/100 VM 0e11 0091 EtherExpress PRO/100 VE @@ -7824,7 +8030,7 @@ 8086 4532 D815EEA2 mainboard 8086 4557 D815EGEW Mainboard 244c 82801BAM ISA Bridge (LPC) - 244e 82801BA/CA/DB/EB/ER Hub interface to PCI Bridge + 244e 82801 PCI Bridge 1014 0267 NetVista A30p 2450 82801E ISA Bridge (LPC) 2452 82801E USB @@ -7879,45 +8085,45 @@ 248b 82801CA Ultra ATA Storage Controller 15d9 3480 P4DP6 248c 82801CAM ISA Bridge (LPC) - 24c0 82801DB (ICH4) LPC Bridge + 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Bridge 1014 0267 NetVista A30p 1462 5800 845PE Max (MS-6580) - 24c2 82801DB (ICH4) USB UHCI #1 + 24c2 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 1014 0267 NetVista A30p 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) - 24c3 82801DB/DBM (ICH4) SMBus Controller + 24c3 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller 1014 0267 NetVista A30p 1071 8160 MIM2000 1458 24c2 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) 4c53 1090 Cx9 / Vx9 mainboard - 24c4 82801DB (ICH4) USB UHCI #2 + 24c4 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 1014 0267 NetVista A30p 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) 4c53 1090 Cx9 / Vx9 mainboard - 24c5 82801DB (ICH4) AC'97 Audio Controller + 24c5 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller 0e11 00b8 Analog Devices Inc. codec [SoundMAX] 1014 0267 NetVista A30p 1071 8160 MIM2000 1458 a002 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) - 24c6 82801DB (ICH4) AC'97 Modem Controller + 24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller 1071 8160 MIM2000 - 24c7 82801DB (ICH4) USB UHCI #3 + 24c7 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 1014 0267 NetVista A30p 1071 8160 MIM2000 1462 5800 845PE Max (MS-6580) 24ca 82801DBM (ICH4) Ultra ATA Storage Controller 1071 8160 MIM2000 - 24cb 82801DB (ICH4) Ultra ATA 100 Storage Controller + 24cb 82801DB/DBL (ICH4/ICH4-L) UltraATA-100 IDE Controller 1014 0267 NetVista A30p 1458 24c2 GA-8PE667 Ultra 1462 5800 845PE Max (MS-6580) 4c53 1090 Cx9 / Vx9 mainboard 24cc 82801DBM LPC Interface Controller - 24cd 82801DB (ICH4) USB2 EHCI Controller + 24cd 82801DB/DBM (ICH4/ICH4-M) USB 2.0 EHCI Controller 1014 0267 NetVista A30p 1071 8160 MIM2000 1462 3981 845PE Max (MS-6580) @@ -7927,19 +8133,23 @@ 103c 12bc d530 CMT (DG746A) 1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI #1 103c 12bc d530 CMT (DG746A) 1043 80a6 P4P800 Mainboard 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller 1043 80a6 P4P800 Mainboard 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI #2 103c 12bc d530 CMT (DG746A) 1043 80a6 P4P800 Mainboard 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller 103c 12bc Analog Devices codec [SoundMAX Integrated Digital Audio] 1043 80f3 P4P800 Mainboard @@ -7950,22 +8160,26 @@ 1043 80a6 P4P800 Mainboard 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24db 82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller 103c 12bc d530 CMT (DG746A) 1043 80a6 P4P800 Mainboard 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) 1462 7580 MSI 875P + 8086 3427 S875WP1-E mainboard 24dc 82801EB LPC Interface Controller 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller 103c 12bc d530 CMT (DG746A) 1043 80a6 P4P800 Mainboard 1458 5006 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24de 82801EB/ER (ICH5/ICH5R) USB UHCI #4 1043 80a6 P4P800 Mainboard 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) 1462 7280 865PE Neo2 (MS-6728) + 8086 3427 S875WP1-E mainboard 24df 82801EB (ICH5R) SATA (cc=RAID) 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1028 0095 Precision Workstation 220 Chipset @@ -7984,23 +8198,23 @@ 2534 82860 860 (Wombat) Chipset PCI Bridge 2540 E7500 Memory Controller Hub 15d9 3480 P4DP6 - 2541 E7000 Series Host RASUM Controller + 2541 E7500/E7501 Host RASUM Controller 15d9 3480 P4DP6 4c53 1090 Cx9 / Vx9 mainboard - 2543 E7000 Series Hub Interface B PCI-to-PCI Bridge - 2544 E7000 Series Hub Interface B RASUM Controller + 2543 E7500/E7501 Hub Interface B PCI-to-PCI Bridge + 2544 E7500/E7501 Hub Interface B RASUM Controller 4c53 1090 Cx9 / Vx9 mainboard - 2545 E7000 Series Hub Interface C PCI-to-PCI Bridge - 2546 E7000 Series Hub Interface C RASUM Controller - 2547 E7000 Series Hub Interface D PCI-to-PCI Bridge - 2548 E7000 Series Hub Interface D RASUM Controller + 2545 E7500/E7501 Hub Interface C PCI-to-PCI Bridge + 2546 E7500/E7501 Hub Interface C RASUM Controller + 2547 E7500/E7501 Hub Interface D PCI-to-PCI Bridge + 2548 E7500/E7501 Hub Interface D RASUM Controller 254c E7501 Memory Controller Hub 4c53 1090 Cx9 / Vx9 mainboard 2550 E7505 Memory Controller Hub - 2551 E7000 Series RAS Controller - 2552 E7000 Series Processor to AGP Controller - 2553 E7000 Series Hub Interface B PCI-to-PCI Bridge - 2554 E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller + 2551 E7505/E7205 Series RAS Controller + 2552 E7505/E7205 PCI-to-AGP Bridge + 2553 E7505 Hub Interface B PCI-to-PCI Bridge + 2554 E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller 255d E7205 Memory Controller Hub 2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface 1458 2560 GA-8PE667 Ultra @@ -8022,14 +8236,17 @@ 2579 82875P Processor to AGP Controller 257b 82875P Processor to PCI to CSA Bridge 257e 82875P Processor to I/O Memory Interface - 2580 Memory Controller Hub - 2581 Memory Controller Hub PCI Express Port - 2582 Graphics Controller - 2584 Workstation Memory Controller Hub - 2585 Workstation Memory Controller Hub PCI Express Port + 2580 915G/P/GV Processor to I/O Controller + 2581 915G/P/GV PCI Express Root Port + 2582 82915G Express Chipset Family Graphics Controller + 2584 925X Memory Controller Hub + 2585 925X PCI Express Root Port 2588 Server Memory Controller Hub 2589 Server Memory Controller Hub PCI Express Port 258a Graphics Controller + 2590 Mobile Memory Controller Hub + 2591 Mobile Memory Controller Hub PCI Express Port + 2592 Mobile Graphics Controller 25a1 6300ESB LPC Interface Controller 25a2 6300ESB PATA Storage Controller 25a3 6300ESB SATA Storage Controller @@ -8043,26 +8260,63 @@ 25ad 6300ESB USB2 Enhanced Host Controller 25ae 6300ESB 64-bit PCI-X Bridge 25b0 6300ESB SATA RAID Controller - 2640 I/O Controller Hub LPC - 2641 I/O Controller Hub LPC - 2642 I/O Controller Hub LPC - 2651 I/O Controller Hub SATA cc=ide - 2652 I/O Controller Hub SATA cc=raid - 2658 I/O Controller Hub USB - 2659 I/O Controller Hub USB - 265a I/O Controller Hub USB - 265b I/O Controller Hub USB - 265c I/O Controller Hub USB2 - 2660 I/O Controller Hub PCI Express Port 0 - 2662 I/O Controller Hub PCI Express Port 1 - 2664 I/O Controller Hub PCI Express Port 2 - 2666 I/O Controller Hub PCI Express Port 3 - 2668 I/O Controller Hub Audio - 266a I/O Controller Hub SMBus - 266d I/O Controller Hub Modem - 266e I/O Controller Hub Audio - 266f I/O Controller Hub PATA - 2782 Graphics Controller + 2600 Server Hub Interface + 2601 Server Hub PCI Express x4 Port D + 2602 Server Hub PCI Express x4 Port C0 + 2603 Server Hub PCI Express x4 Port C1 + 2604 Server Hub PCI Express x4 Port B0 + 2605 Server Hub PCI Express x4 Port B1 + 2606 Server Hub PCI Express x4 Port A0 + 2607 Server Hub PCI Express x4 Port A1 + 2608 Server Hub PCI Express x8 Port C + 2609 Server Hub PCI Express x8 Port B + 260a Server Hub PCI Express x8 Port A + 260c Server Hub IMI Registers + 2610 Server Hub System Bus, Boot, and Interrupt Registers + 2611 Server Hub Address Mapping Registers + 2612 Server Hub RAS Registers + 2613 Server Hub Performance Monitoring Registers + 2614 Server Hub Performance Monitoring Registers + 2615 Server Hub Performance Monitoring Registers + 2617 Server Hub Debug Registers + 2618 Server Hub Debug Registers + 2619 Server Hub Debug Registers + 261a Server Hub Debug Registers + 261b Server Hub Debug Registers + 261c Server Hub Debug Registers + 261d Server Hub Debug Registers + 261e Server Hub Debug Registers + 2620 External Memory Bridge + 2621 External Memory Bridge Control Registers + 2622 External Memory Bridge Memory Interleaving Registers + 2623 External Memory Bridge DDR Initialization and Calibration + 2624 External Memory Bridge Reserved Registers + 2625 External Memory Bridge Reserved Registers + 2626 External Memory Bridge Reserved Registers + 2627 External Memory Bridge Reserved Registers + 2640 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge + 2641 82801FBM (ICH6M) LPC Interface Bridge + 2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge + 2651 82801FB/FW (ICH6/ICH6W) SATA Controller + 2652 82801FR/FRW (ICH6R/ICH6RW) SATA Controller + 2653 82801FBM (ICH6M) SATA Controller + 2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 + 2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 + 265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 + 265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 + 265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller + 2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 + 2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 + 2664 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 + 2666 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 + 2668 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller + 266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller + 266c 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller + 266d 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller + 266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller + 266f 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller + 2782 82915G Express Chipset Family Graphics Controller + 2792 Mobile Graphics Controller 3092 Integrated RAID 3200 GD31244 PCI-X SATA HBA 3340 82855PM Processor to I/O Controller @@ -8092,7 +8346,7 @@ 359a Memory Controller Hub PCI Express Port C1 359b Memory Controller Hub Extended Configuration Registers 359e Workstation Memory Controller Hub - 4220 Intel(R) PRO/Wireless 2200BG + 4220 PRO/Wireless 2200BG 5200 EtherExpress PRO/100 Intelligent Server 5201 EtherExpress PRO/100 Intelligent Server 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter @@ -8155,7 +8409,7 @@ 7601 82372FB PIIX5 IDE 7602 82372FB PIIX5 USB 7603 82372FB PIIX5 SMBus - 7800 i740 + 7800 82740 (i740) AGP Graphics Accelerator 003d 0008 Starfighter AGP 003d 000b Starfighter AGP 1092 0100 Stealth II G460 @@ -8175,7 +8429,9 @@ 84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB) 84ea 460GX - 84460GX AGP Bridge (GXB function 1) 8500 IXP4xx Family Network Processor (IXP420, 421, 422, 425 and IXC1100) - 9000 Intel IXP2000 Familly Network Processor + 9000 IXP2000 Family Network Processor + 9001 IXP2400 Network Processor + 9004 IXP2800 Network Processor 9621 Integrated RAID 9622 Integrated RAID 9641 Integrated RAID @@ -8184,10 +8440,12 @@ # observed, and documented in Intel revision note; new mask of 1011:0026 b154 21154 PCI-to-PCI Bridge b555 21555 Non transparent PCI-to-PCI Bridge + 1331 0030 ENP-2611 4c53 1050 CT7 mainboard 4c53 1051 CE7 mainboard e4bf 1000 CC8-1-BLUES ffff 450NX/GX [Orion] - 82453KX/GX Memory controller [BUG] +8401 TRENDware International Inc. 8800 Trigem Computer Inc. 2008 Video assistent component 8866 T-Square Design Inc. @@ -8352,15 +8610,18 @@ 00c1 AIC-7899B U160/m 00c3 AIC-7899D U160/m 00c5 RAID subsystem HBA - 1028 00c5 PowerEdge 2550 + 1028 00c5 PowerEdge 2400,2500,2550,4400 00cf AIC-7899P U160/m 1028 00ce PowerEdge 1400 1028 00d1 PowerEdge 2550 10f1 2462 Thunder K7 S2462 15d9 9005 Onboard SCSI Host Adapter + 8086 3411 SDS2 Mainboard 0250 ServeRAID Controller 1014 0279 ServeRAID-xx 1014 028c ServeRAID-xx +# from kernel sources + 0279 ServeRAID 6M 0283 AAC-RAID 9005 0283 Catapult 0284 AAC-RAID @@ -8429,7 +8690,7 @@ 1000 0012 1P2S 9845 PCI 9845 Multi-I/O Controller 1000 0006 0P6S (6 port 16550a serial card) - 9855 PCI 9855 Multi-I/O Controller 4 Serial 1 Parallel + 9855 PCI 9855 Multi-I/O Controller 1000 0014 1P4S 9902 Stargen Inc. 0001 SG2010 PCI over Starfabric Bridge @@ -8444,6 +8705,7 @@ a304 Sony a727 3Com Corporation aa42 Scitex Digital Video ac1e Digital Receiver Technology Inc +aecb Adrienne Electronics Corporation b1b3 Shiva Europe Limited # Pinnacle should be 11bd, but they got it wrong several times --mj bd11 Pinnacle Systems, Inc. (Wrong ID) @@ -8464,9 +8726,9 @@ d84d Exsys dead Indigita Corporation e000 Winbond e000 W89C940 -# see : http://www.schoenfeld.de/inside/Inside_CWMK3.txt -e159 Individual Computers - Jens Schoenfeld - 0001 Intel 537 +# see also : http://www.schoenfeld.de/inside/Inside_CWMK3.txt maybe a misuse of TJN id or it use the TJN 3XX chip for other applic +e159 Tiger Jet Network Inc. + 0001 Tiger3XX Modem/ISDN interface 0059 0001 128k ISDN-S/T Adapter 0059 0003 128k ISDN-U Adapter 0002 Tiger100APC ISDN chipset diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ee7b9feb6..1c70dd5a1 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -144,9 +144,11 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) pci_write_config_dword(dev, reg+4, ~0); pci_read_config_dword(dev, reg+4, &sz); pci_write_config_dword(dev, reg+4, l); - if (~sz) - res->end = res->start + 0xffffffff + - (((unsigned long) ~sz) << 32); + sz = pci_size(l, sz, 0xffffffff); + if (sz) { + /* This BAR needs > 4GB? Wow. */ + res->end |= (unsigned long)sz<<32; + } #else if (l) { printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev)); @@ -170,7 +172,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) if (sz && sz != 0xffffffff) { sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); if (sz) { - res->flags = (l & PCI_ROM_ADDRESS_ENABLE) | + res->flags = (l & IORESOURCE_ROM_ENABLE) | IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_READONLY | IORESOURCE_CACHEABLE; res->start = l & PCI_ROM_ADDRESS_MASK; @@ -243,15 +245,23 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) u32 mem_base_hi, mem_limit_hi; pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi); pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi); + + /* + * Some bridges set the base > limit by default, and some + * (broken) BIOSes do not initialize them. If we find + * this, just assume they are not being used. + */ + if (mem_base_hi <= mem_limit_hi) { #if BITS_PER_LONG == 64 - base |= ((long) mem_base_hi) << 32; - limit |= ((long) mem_limit_hi) << 32; + base |= ((long) mem_base_hi) << 32; + limit |= ((long) mem_limit_hi) << 32; #else - if (mem_base_hi || mem_limit_hi) { - printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name); - return; - } + if (mem_base_hi || mem_limit_hi) { + printk(KERN_ERR "PCI: Unable to handle 64-bit address space for bridge %s\n", pci_name(dev)); + return; + } #endif + } } if (base <= limit) { res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; @@ -373,7 +383,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max child->bridge_ctl = bctl; cmax = pci_scan_child_bus(child); - if (cmax > max) max = cmax; + if (cmax > max) + max = cmax; + if (child->subordinate > max) + max = child->subordinate; } else { /* * We need to assign a number to this bus which we always @@ -475,6 +488,9 @@ static int pci_setup_device(struct pci_dev * dev) /* "Unknown power state" */ dev->current_state = 4; + /* Early fixups, before probing the BARs */ + pci_fixup_device(pci_fixup_early, dev); + switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class == PCI_CLASS_BRIDGE_PCI) @@ -571,6 +587,11 @@ static int pci_cfg_space_size(struct pci_dev *dev) return PCI_CFG_SPACE_SIZE; } +static void pci_release_bus_bridge_dev(struct device *dev) +{ + kfree(dev); +} + /* * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... @@ -640,7 +661,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) return NULL; /* Fix up broken headers */ - pci_fixup_device(PCI_FIXUP_HEADER, dev); + pci_fixup_device(pci_fixup_header, dev); /* * Add the device to our list of discovered devices @@ -745,6 +766,7 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { + int error; struct pci_bus *b; struct device *dev; @@ -764,24 +786,31 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, if (pci_find_bus(pci_domain_nr(b), bus)) { /* If we already got to this bus through a different bridge, ignore it */ DBG("PCI: Bus %02x already known\n", bus); - kfree(dev); - kfree(b); - return NULL; + goto err_out; } list_add_tail(&b->node, &pci_root_buses); memset(dev, 0, sizeof(*dev)); dev->parent = parent; + dev->release = pci_release_bus_bridge_dev; sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus); - device_register(dev); + error = device_register(dev); + if (error) + goto dev_reg_err; b->bridge = get_device(dev); b->class_dev.class = &pcibus_class; sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus); - class_device_register(&b->class_dev); - class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity); + error = class_device_register(&b->class_dev); + if (error) + goto class_dev_reg_err; + error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity); + if (error) + goto class_dev_create_file_err; - sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge"); + error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge"); + if (error) + goto sys_create_link_err; b->number = b->secondary = bus; b->resource[0] = &ioport_resource; @@ -792,6 +821,19 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, pci_bus_add_devices(b); return b; + +sys_create_link_err: + class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity); +class_dev_create_file_err: + class_device_unregister(&b->class_dev); +class_dev_reg_err: + device_unregister(dev); +dev_reg_err: + list_del(&b->node); +err_out: + kfree(dev); + kfree(b); + return NULL; } EXPORT_SYMBOL(pci_scan_bus_parented); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 81fd72ef1..da51bf96a 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -379,7 +379,7 @@ static struct seq_operations proc_bus_pci_devices_op = { .show = show_device }; -struct proc_dir_entry *proc_bus_pci_dir; +static struct proc_dir_entry *proc_bus_pci_dir; int pci_proc_attach_device(struct pci_dev *dev) { @@ -599,7 +599,7 @@ static int __init pci_proc_init(void) if (entry) entry->proc_fops = &proc_bus_pci_dev_operations; proc_initialized = 1; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pci_proc_attach_device(dev); } legacy_proc_init(); @@ -612,6 +612,5 @@ __initcall(pci_proc_init); EXPORT_SYMBOL(pci_proc_attach_device); EXPORT_SYMBOL(pci_proc_attach_bus); EXPORT_SYMBOL(pci_proc_detach_bus); -EXPORT_SYMBOL(proc_bus_pci_dir); #endif diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 6e7c35013..fa64253bd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1,10 +1,10 @@ /* - * $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $ - * * This file contains work-arounds for many known PCI hardware * bugs. Devices present only on certain architectures (host * bridges et cetera) should be handled in arch-specific code. * + * Note: any quirks for hotpluggable devices must _NOT_ be declared __init. + * * Copyright (c) 1999 Martin Mares * * The bridge optimization stuff has been removed. If you really @@ -30,7 +30,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev) /* We have to make sure a particular bit is set in the PIIX3 ISA bridge, so we have to go out and find it. */ - while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) { + while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) { pci_read_config_byte(d, 0x82, &dlc); if (!(dlc & 1<<1)) { printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d)); @@ -39,6 +39,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev) } } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release ); /* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround but VIA don't answer queries. If you happen to have good contacts at VIA @@ -46,8 +47,6 @@ static void __devinit quirk_passive_release(struct pci_dev *dev) This appears to be BIOS not version dependent. So presumably there is a chipset level fix */ - - int isa_dma_bridge_buggy; /* Exported */ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) @@ -57,34 +56,47 @@ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) printk(KERN_INFO "Activating ISA DMA hang workarounds.\n"); } } + /* + * Its not totally clear which chipsets are the problematic ones + * We know 82C586 and 82C596 variants are affected. + */ +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs ); int pci_pci_problems; /* * Chipsets where PCI->PCI transfers vanish or hang */ - static void __devinit quirk_nopcipci(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_FAIL)==0) - { + if ((pci_pci_problems & PCIPCI_FAIL)==0) { printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_FAIL; + pci_pci_problems |= PCIPCI_FAIL; } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci ); /* * Triton requires workarounds to be used by the drivers */ - static void __devinit quirk_triton(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_TRITON)==0) - { + if ((pci_pci_problems&PCIPCI_TRITON)==0) { printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_TRITON; + pci_pci_problems |= PCIPCI_TRITON; } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton ); /* * VIA Apollo KT133 needs PCI latency patch @@ -104,24 +116,21 @@ static void __devinit quirk_vialatency(struct pci_dev *dev) /* Ok we have a potential problem chipset here. Now see if we have a buggy southbridge */ - p=pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL); - if(p!=NULL) - { + p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL); + if (p!=NULL) { pci_read_config_byte(p, PCI_CLASS_REVISION, &rev); /* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */ /* Check for buggy part revisions */ - if (rev < 0x40 || rev > 0x42) - return; - } - else - { - p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL); - if(p==NULL) /* No problem parts */ - return; + if (rev < 0x40 || rev > 0x42) + goto exit; + } else { + p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL); + if (p==NULL) /* No problem parts */ + goto exit; pci_read_config_byte(p, PCI_CLASS_REVISION, &rev); /* Check for buggy part revisions */ if (rev < 0x10 || rev > 0x12) - return; + goto exit; } /* @@ -144,28 +153,33 @@ static void __devinit quirk_vialatency(struct pci_dev *dev) busarb |= (1<<4); pci_write_config_byte(dev, 0x76, busarb); printk(KERN_INFO "Applying VIA southbridge workaround.\n"); +exit: + pci_dev_put(p); } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency ); /* * VIA Apollo VP3 needs ETBF on BT848/878 */ - static void __devinit quirk_viaetbf(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_VIAETBF)==0) - { + if ((pci_pci_problems&PCIPCI_VIAETBF)==0) { printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_VIAETBF; + pci_pci_problems |= PCIPCI_VIAETBF; } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf ); + static void __devinit quirk_vsfx(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_VSFX)==0) - { + if ((pci_pci_problems&PCIPCI_VSFX)==0) { printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_VSFX; + pci_pci_problems |= PCIPCI_VSFX; } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx ); /* * Ali Magik requires workarounds to be used by the drivers @@ -173,36 +187,38 @@ static void __devinit quirk_vsfx(struct pci_dev *dev) * workaround applied too * [Info kindly provided by ALi] */ - static void __init quirk_alimagik(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_ALIMAGIK)==0) - { + if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) { printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON; + pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON; } } - +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik ); /* * Natoma has some interesting boundary conditions with Zoran stuff * at least */ - static void __devinit quirk_natoma(struct pci_dev *dev) { - if((pci_pci_problems&PCIPCI_NATOMA)==0) - { + if ((pci_pci_problems&PCIPCI_NATOMA)==0) { printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); - pci_pci_problems|=PCIPCI_NATOMA; + pci_pci_problems |= PCIPCI_NATOMA; } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma ); /* * S3 868 and 968 chips report region size equal to 32M, but they decode 64M. * If it's needed, re-allocate the region. */ - static void __devinit quirk_s3_64M(struct pci_dev *dev) { struct resource *r = &dev->resource[0]; @@ -212,6 +228,8 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev) r->end = 0x3ffffff; } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M ); static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr) { @@ -231,7 +249,6 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsi * ATI Northbridge setups MCE the processor if you even * read somewhere between 0x3b0->0x3bb or read 0x3d3 */ - static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) { printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); @@ -239,6 +256,7 @@ static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) request_region(0x3b0, 0x0C, "RadeonIGP"); request_region(0x3d3, 0x01, "RadeonIGP"); } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce ); /* * Let's make the southbridge information explicit instead @@ -260,6 +278,7 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev) pci_read_config_word(dev, 0xE2, ®ion); quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi ); /* * PIIX4 ACPI: Two IO regions pointed to by longwords at @@ -275,6 +294,7 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev) pci_read_config_dword(dev, 0x90, ®ion); quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi ); /* * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at @@ -291,6 +311,15 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) pci_read_config_dword(dev, 0x58, ®ion); quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi ); /* * VIA ACPI: One IO region pointed to by longword at @@ -308,6 +337,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev) quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi ); /* * VIA VT82C686 ACPI: Three IO region pointed to by (long)words at @@ -330,6 +360,7 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev) smb &= PCI_BASE_ADDRESS_IO_MASK; quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); #ifdef CONFIG_X86_IO_APIC @@ -358,6 +389,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev) /* Offset 0x58: External APIC IRQ output control */ pci_write_config_byte (dev, 0x58, tmp); } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic ); /* * The AMD io apic can hang the box when an apic irq is masked. @@ -368,30 +400,29 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev) * 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 __devinit quirk_amd_ioapic(struct pci_dev *dev) { u8 rev; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if(rev >= 0x02) - { + 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"); } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic ); static void __init quirk_ioapic_rmw(struct pci_dev *dev) { if (dev->devfn == 0 && dev->bus->number == 0) sis_apic_bug = 1; } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw ); #define AMD8131_revA0 0x01 #define AMD8131_revB0 0x11 #define AMD8131_MISC 0x40 #define AMD8131_NIOAMODE_BIT 0 - static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) { unsigned char revid, tmp; @@ -407,6 +438,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) pci_write_config_byte( dev, AMD8131_MISC, tmp); } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic ); #endif /* CONFIG_X86_IO_APIC */ @@ -444,8 +476,10 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) if (irq && (irq != 2)) d->irq = irq; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi ); -static void __devinit quirk_via_irqpic(struct pci_dev *dev) +static void quirk_via_irqpic(struct pci_dev *dev) { u8 irq, new_irq = dev->irq & 0xf; @@ -459,6 +493,10 @@ static void __devinit quirk_via_irqpic(struct pci_dev *dev) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5, quirk_via_irqpic ); /* @@ -480,6 +518,8 @@ static void __devinit quirk_piix3_usb(struct pci_dev *dev) legsup &= 0x50ef; pci_write_config_word(dev, 0xc0, legsup); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb ); /* * VIA VT82C598 has its device ID settable and many BIOSes @@ -492,6 +532,7 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev) pci_write_config_byte(dev, 0xfc, 0); pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id ); /* * CardBus controllers have a legacy base address that enables them @@ -505,6 +546,7 @@ static void __devinit quirk_cardbus_legacy(struct pci_dev *dev) return; pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0); } +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy ); /* * Following the PCI ordering rules is optional on the AMD762. I'm not @@ -513,13 +555,11 @@ static void __devinit quirk_cardbus_legacy(struct pci_dev *dev) * To be fair to AMD, it follows the spec by default, its BIOS people * who turn it off! */ - static void __devinit quirk_amd_ordering(struct pci_dev *dev) { u32 pcic; pci_read_config_dword(dev, 0x4C, &pcic); - if((pcic&6)!=6) - { + if ((pcic&6)!=6) { pcic |= 6; printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n"); pci_write_config_dword(dev, 0x4C, pcic); @@ -528,6 +568,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev) pci_write_config_dword(dev, 0x84, pcic); } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering ); /* * DreamWorks provided workaround for Dunord I-3000 problem @@ -536,18 +577,26 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev) * assigned to it. We force a larger allocation to ensure that * nothing gets put too close to it. */ - static void __devinit quirk_dunord ( struct pci_dev * dev ) { - struct resource * r = & dev -> resource [ 1 ]; - r -> start = 0; - r -> end = 0xffffff; + struct resource *r = &dev->resource [1]; + r->start = 0; + r->end = 0xffffff; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord ); +/* + * i82380FB mobile docking controller: its PCI-to-PCI bridge + * is subtractive decoding (transparent), and does indicate this + * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80 + * instead of 0x01. + */ static void __devinit quirk_transparent_bridge(struct pci_dev *dev) { dev->transparent = 1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge ); /* * Common misconfiguration of the MediaGX/Geode PCI master that will @@ -555,7 +604,6 @@ static void __devinit quirk_transparent_bridge(struct pci_dev *dev) * datasheets found at http://www.national.com/ds/GX for info on what * these bits do. */ - static void __init quirk_mediagx_master(struct pci_dev *dev) { u8 reg; @@ -566,6 +614,7 @@ static void __init quirk_mediagx_master(struct pci_dev *dev) pci_write_config_byte(dev, 0x41, reg); } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master ); /* * As per PCI spec, ignore base address registers 0-3 of the IDE controllers @@ -584,7 +633,6 @@ static void __init quirk_mediagx_master(struct pci_dev *dev) * we do now ? We don't want is pci_enable_device to come along * and assign new resources. Both approaches work for that. */ - static void __devinit quirk_ide_bases(struct pci_dev *dev) { struct resource *res; @@ -616,34 +664,33 @@ static void __devinit quirk_ide_bases(struct pci_dev *dev) printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", first_bar, last_bar, pci_name(dev)); } +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases ); /* * Ensure C0 rev restreaming is off. This is normally done by * the BIOS but in the odd case it is not the results are corruption * hence the presence of a Linux check */ - static void __init quirk_disable_pxb(struct pci_dev *pdev) { u16 config; u8 rev; pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - if(rev != 0x04) /* Only C0 requires this */ + if (rev != 0x04) /* Only C0 requires this */ return; pci_read_config_word(pdev, 0x40, &config); - if(config & (1<<6)) - { + if (config & (1<<6)) { config &= ~(1<<6); pci_write_config_word(pdev, 0x40, config); printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n"); } } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); /* * VIA northbridges care about PCI_INTERRUPT_LINE */ - int interrupt_line_quirk; static void __devinit quirk_via_bridge(struct pci_dev *pdev) @@ -651,6 +698,7 @@ static void __devinit quirk_via_bridge(struct pci_dev *pdev) if(pdev->devfn == 0) interrupt_line_quirk = 1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge ); /* * Serverworks CSB5 IDE does not fully support native mode @@ -667,15 +715,16 @@ static void __init quirk_svwks_csb5ide(struct pci_dev *pdev) quirk_ide_bases(pdev); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide ); /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. */ - static void __init quirk_eisa_bridge(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_EISA << 8; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge ); /* * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge @@ -689,7 +738,6 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev) * becomes necessary to do this tweak in two steps -- I've chosen the Host * bridge as trigger. */ - static int __initdata asus_hides_smbus = 0; static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) @@ -699,6 +747,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) switch(dev->subsystem_device) { case 0x8070: /* P4B */ case 0x8088: /* P4B533 */ + case 0x1626: /* L3C notebook */ asus_hides_smbus = 1; } if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) @@ -723,6 +772,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x1751: /* M2N notebook */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) + switch (dev->subsystem_device) { + case 0x186a: /* M6Ne notebook */ + asus_hides_smbus = 1; + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch(dev->subsystem_device) { @@ -730,8 +784,20 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x0890: /* HP Compaq nc6000 */ asus_hides_smbus = 1; } + if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) + switch (dev->subsystem_device) { + case 0x12bc: /* HP D330L */ + asus_hides_smbus = 1; + } } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge ); static void __init asus_hides_smbus_lpc(struct pci_dev *dev) { @@ -744,12 +810,17 @@ static void __init asus_hides_smbus_lpc(struct pci_dev *dev) if (val & 0x8) { pci_write_config_word(dev, 0xF2, val & (~0x8)); pci_read_config_word(dev, 0xF2, &val); - if(val & 0x8) + if (val & 0x8) printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val); else printk(KERN_INFO "PCI: Enabled i801 SMBus device\n"); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); /* * SiS 96x south bridge: BIOS typically hides SMBus device... @@ -763,6 +834,234 @@ static void __init quirk_sis_96x_smbus(struct pci_dev *dev) pci_read_config_byte(dev, 0x77, &val); } + +#define UHCI_USBLEGSUP 0xc0 /* legacy support */ +#define UHCI_USBCMD 0 /* command register */ +#define UHCI_USBSTS 2 /* status register */ +#define UHCI_USBINTR 4 /* interrupt register */ +#define UHCI_USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ +#define UHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ +#define UHCI_USBCMD_GRESET (1 << 2) /* Global reset */ +#define UHCI_USBCMD_CONFIGURE (1 << 6) /* config semaphore */ +#define UHCI_USBSTS_HALTED (1 << 5) /* HCHalted bit */ + +#define OHCI_CONTROL 0x04 +#define OHCI_CMDSTATUS 0x08 +#define OHCI_INTRSTATUS 0x0c +#define OHCI_INTRENABLE 0x10 +#define OHCI_INTRDISABLE 0x14 +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ + +#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */ +#define EHCI_USBCMD 0 /* command register */ +#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ +#define EHCI_USBSTS 4 /* status register */ +#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ +#define EHCI_USBINTR 8 /* interrupt register */ +#define EHCI_USBLEGSUP 0 /* legacy support register */ +#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ +#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ +#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ +#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ + +int usb_early_handoff __devinitdata = 0; +static int __init usb_handoff_early(char *str) +{ + usb_early_handoff = 1; + return 0; +} +__setup("usb-handoff", usb_handoff_early); + +static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) +{ + unsigned long base = 0; + int wait_time, delta; + u16 val, sts; + int i; + + for (i = 0; i < PCI_ROM_RESOURCE; i++) + if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { + base = pci_resource_start(pdev, i); + break; + } + + if (!base) + return; + + /* + * stop controller + */ + sts = inw(base + UHCI_USBSTS); + val = inw(base + UHCI_USBCMD); + val &= ~(u16)(UHCI_USBCMD_RUN | UHCI_USBCMD_CONFIGURE); + outw(val, base + UHCI_USBCMD); + + /* + * wait while it stops if it was running + */ + if ((sts & UHCI_USBSTS_HALTED) == 0) + { + wait_time = 1000; + delta = 100; + + do { + outw(0x1f, base + UHCI_USBSTS); + udelay(delta); + wait_time -= delta; + val = inw(base + UHCI_USBSTS); + if (val & UHCI_USBSTS_HALTED) + break; + } while (wait_time > 0); + } + + /* + * disable interrupts & legacy support + */ + outw(0, base + UHCI_USBINTR); + outw(0x1f, base + UHCI_USBSTS); + pci_read_config_word(pdev, UHCI_USBLEGSUP, &val); + if (val & 0xbf) + pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT); + +} + +static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) +{ + void __iomem *base; + int wait_time; + + base = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (base == NULL) return; + + if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { + wait_time = 500; /* 0.5 seconds */ + writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); + writel(OHCI_OCR, base + OHCI_CMDSTATUS); + while (wait_time > 0 && + readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { + wait_time -= 10; + msleep(10); + } + } + + /* + * disable interrupts + */ + writel(~(u32)0, base + OHCI_INTRDISABLE); + writel(~(u32)0, base + OHCI_INTRSTATUS); + + iounmap(base); +} + +static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) +{ + int wait_time, delta; + void __iomem *base, *op_reg_base; + u32 hcc_params, val, temp; + u8 cap_length; + + base = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (base == NULL) return; + + cap_length = readb(base); + op_reg_base = base + cap_length; + hcc_params = readl(base + EHCI_HCC_PARAMS); + hcc_params = (hcc_params >> 8) & 0xff; + if (hcc_params) { + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + &val); + if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) { + /* + * Ok, BIOS is in smm mode, try to hand off... + */ + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + &temp); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + temp | EHCI_USBLEGCTLSTS_SOOE); + val |= EHCI_USBLEGSUP_OS; + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + val); + + wait_time = 500; + do { + msleep(10); + wait_time -= 10; + pci_read_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + &val); + } while (wait_time && (val & EHCI_USBLEGSUP_BIOS)); + if (!wait_time) { + /* + * well, possibly buggy BIOS... + */ + printk(KERN_WARNING "EHCI early BIOS handoff " + "failed (BIOS bug ?)\n"); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGSUP, + EHCI_USBLEGSUP_OS); + pci_write_config_dword(pdev, + hcc_params + EHCI_USBLEGCTLSTS, + 0); + } + } + } + + /* + * halt EHCI & disable its interrupts in any case + */ + val = readl(op_reg_base + EHCI_USBSTS); + if ((val & EHCI_USBSTS_HALTED) == 0) { + val = readl(op_reg_base + EHCI_USBCMD); + val &= ~EHCI_USBCMD_RUN; + writel(val, op_reg_base + EHCI_USBCMD); + + wait_time = 2000; + delta = 100; + do { + writel(0x3f, op_reg_base + EHCI_USBSTS); + udelay(delta); + wait_time -= delta; + val = readl(op_reg_base + EHCI_USBSTS); + if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { + break; + } + } while (wait_time > 0); + } + writel(0, op_reg_base + EHCI_USBINTR); + writel(0x3f, op_reg_base + EHCI_USBSTS); + + iounmap(base); + + return; +} + + + +static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) +{ + if (!usb_early_handoff) + return; + + if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x00)) { /* UHCI */ + quirk_usb_handoff_uhci(pdev); + } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) { /* OHCI */ + quirk_usb_handoff_ohci(pdev); + } else if (pdev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x20)) { /* EHCI */ + quirk_usb_disable_ehci(pdev); + } + + return; +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); + /* * ... This is further complicated by the fact that some SiS96x south * bridges pretend to be 85C503/5513 instead. In that case see if we @@ -803,6 +1102,19 @@ static void __init quirk_sis_96x_compatible(struct pci_dev *dev) { sis_96x_compatible = 1; } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); #ifdef CONFIG_X86_IO_APIC static void __init quirk_alder_ioapic(struct pci_dev *pdev) @@ -815,20 +1127,21 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev) /* the first BAR is the location of the IO APIC...we must * not touch this (and it's already covered by the fixmap), so * forcibly insert it into the resource tree */ - if(pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0)) + if (pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0)) insert_resource(&iomem_resource, &pdev->resource[0]); /* The next five BARs all seem to be rubbish, so just clean * them out */ - for(i=1; i < 6; i++) { + for (i=1; i < 6; i++) { memset(&pdev->resource[i], 0, sizeof(pdev->resource[i])); } } +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic ); #endif #ifdef CONFIG_SCSI_SATA -static void __init quirk_intel_ide_combined(struct pci_dev *pdev) +static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev) { u8 prog, comb, tmp; int ich = 0; @@ -898,171 +1211,68 @@ static void __init quirk_intel_ide_combined(struct pci_dev *pdev) else request_region(0x170, 8, "libata"); /* port 1 */ } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_combined ); #endif /* CONFIG_SCSI_SATA */ -int pciehp_msi_quirk; -static void __devinit quirk_pciehp_msi(struct pci_dev *pdev) +int pcie_mch_quirk; + +static void __devinit quirk_pcie_mch(struct pci_dev *pdev) { - pciehp_msi_quirk = 1; + pcie_mch_quirk = 1; } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch ); -/* - * The main table of quirks. - * - * Note: any hooks for hotpluggable devices in this table must _NOT_ - * be declared __init. - */ - -static struct pci_fixup pci_fixups[] __devinitdata = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, - /* - * Its not totally clear which chipsets are the problematic ones - * We know 82C586 and 82C596 variants are affected. - */ - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi }, - - /* Intel LPC interface bridges all have 128 bytes of magic ACPI/TCO regs and 64 bytes of GPIO */ - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi }, - - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge }, - { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy }, - -#ifdef CONFIG_X86_IO_APIC - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, - quirk_amd_8131_ioapic }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic }, -#endif - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic }, - { 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_FE_GATE_700C, quirk_amd_ordering }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce }, - /* - * i82380FB mobile docking controller: its PCI-to-PCI bridge - * is subtractive decoding (transparent), and does indicate this - * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80 - * instead of 0x01. - */ - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge }, - - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, - - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide }, - - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge }, - - /* - * on Asus P4B boards, the i801SMBus device is disabled at startup. - * this also goes for boards in HP Compaq nc6000 and nc8000 notebooks. - */ - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc }, - -#ifdef CONFIG_SCSI_SATA - /* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and - * Serial ATA (SATA) into the same PCI ID. - */ - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, - quirk_intel_ide_combined }, -#endif /* CONFIG_SCSI_SATA */ - - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_pciehp_msi }, - - { 0 } -}; - - -static void pci_do_fixups(struct pci_dev *dev, int pass, struct pci_fixup *f) +static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { - while (f->pass) { - if (f->pass == pass && - (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && + while (f < end) { + if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { -#ifdef DEBUG - printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev)); -#endif + pr_debug("PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev)); f->hook(dev); } f++; } } -void pci_fixup_device(int pass, struct pci_dev *dev) +extern struct pci_fixup __start_pci_fixups_header[]; +extern struct pci_fixup __end_pci_fixups_header[]; +extern struct pci_fixup __start_pci_fixups_final[]; +extern struct pci_fixup __end_pci_fixups_final[]; +extern struct pci_fixup __start_pci_fixups_enable[]; +extern struct pci_fixup __end_pci_fixups_enable[]; + + +void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { - pci_do_fixups(dev, pass, pcibios_fixups); - pci_do_fixups(dev, pass, pci_fixups); + struct pci_fixup *start, *end; + + switch(pass) { + case pci_fixup_header: + start = __start_pci_fixups_header; + end = __end_pci_fixups_header; + break; + + case pci_fixup_final: + start = __start_pci_fixups_final; + end = __end_pci_fixups_final; + break; + + case pci_fixup_enable: + start = __start_pci_fixups_enable; + end = __end_pci_fixups_enable; + break; + + default: + /* stupid compiler warning, you would think with an enum... */ + return; + } + pci_do_fixups(dev, start, end); } -EXPORT_SYMBOL(pciehp_msi_quirk); +EXPORT_SYMBOL(pcie_mch_quirk); +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pci_fixup_device); +#endif diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 5ef19b175..b2942c4b3 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -16,6 +16,7 @@ static void pci_free_resources(struct pci_dev *dev) msi_remove_pci_irq_vectors(dev); + pci_cleanup_rom(dev); for (i = 0; i < PCI_NUM_RESOURCES; i++) { struct resource *res = dev->resource + i; if (res->parent) @@ -26,6 +27,7 @@ static void pci_free_resources(struct pci_dev *dev) static void pci_destroy_dev(struct pci_dev *dev) { pci_proc_detach_device(dev); + pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); /* Remove the device from the device lists, and prevent any further @@ -59,6 +61,18 @@ int pci_remove_device_safe(struct pci_dev *dev) } EXPORT_SYMBOL(pci_remove_device_safe); +void pci_remove_bus(struct pci_bus *b) +{ + pci_proc_detach_bus(b); + + spin_lock(&pci_bus_lock); + list_del(&b->node); + spin_unlock(&pci_bus_lock); + + class_device_unregister(&b->class_dev); +} +EXPORT_SYMBOL(pci_remove_bus); + /** * pci_remove_bus_device - remove a PCI device and any children * @dev: the device to remove @@ -77,13 +91,7 @@ void pci_remove_bus_device(struct pci_dev *dev) struct pci_bus *b = dev->subordinate; pci_remove_behind_bridge(dev); - pci_proc_detach_bus(b); - - spin_lock(&pci_bus_lock); - list_del(&b->node); - spin_unlock(&pci_bus_lock); - - class_device_unregister(&b->class_dev); + pci_remove_bus(b); dev->subordinate = NULL; } diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 701a83be3..a1fb8b57d 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -1,16 +1,17 @@ /* * PCI searching functions. * - * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, - * David Mosberger-Tang - * Copyright 1997 -- 2000 Martin Mares - * Copyright 2003 -- Greg Kroah-Hartman + * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter, + * David Mosberger-Tang + * Copyright (C) 1997 -- 2000 Martin Mares + * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman */ #include #include #include #include +#include "pci.h" spinlock_t pci_bus_lock = SPIN_LOCK_UNLOCKED; @@ -156,10 +157,11 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) * the pci device returned by this function can disappear at any moment in * time. */ -struct pci_dev * -pci_find_subsys(unsigned int vendor, unsigned int device, - unsigned int ss_vendor, unsigned int ss_device, - const struct pci_dev *from) +static struct pci_dev * pci_find_subsys(unsigned int vendor, + unsigned int device, + unsigned int ss_vendor, + unsigned int ss_device, + const struct pci_dev *from) { struct list_head *n; struct pci_dev *dev; @@ -257,12 +259,6 @@ exit: * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor and @device, a pointer to its device structure is - * returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device on the global list. - * - * Iterates through the list of known PCI devices. If a PCI device is * found with a matching @vendor and @device, the reference count to the * device is incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. A new search is initiated by passing %NULL @@ -312,25 +308,26 @@ exit: return dev; } - /** - * pci_find_class - begin or continue searching for a PCI device by class + * pci_get_class - begin or continue searching for a PCI device by class * @class: search for a PCI device with this class designation * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @class, a pointer to its device structure is - * returned. Otherwise, %NULL is returned. + * found with a matching @class, the reference count to the device is + * incremented and a pointer to its device structure is returned. + * Otherwise, %NULL is returned. * A new search is initiated by passing %NULL to the @from argument. * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. + * on the global list. The reference count for @from is always decremented + * if it is not %NULL. */ -struct pci_dev * -pci_find_class(unsigned int class, const struct pci_dev *from) +struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { struct list_head *n; struct pci_dev *dev; + WARN_ON(in_interrupt()); spin_lock(&pci_bus_lock); n = from ? from->global_list.next : pci_devices.next; @@ -342,16 +339,50 @@ pci_find_class(unsigned int class, const struct pci_dev *from) } dev = NULL; exit: + pci_dev_put(from); + dev = pci_dev_get(dev); spin_unlock(&pci_bus_lock); return dev; } +/** + * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. + * @ids: A pointer to a null terminated list of struct pci_device_id structures + * that describe the type of PCI device the caller is trying to find. + * + * Obvious fact: You do not have a reference to any device that might be found + * by this function, so if that device is removed from the system right after + * this function is finished, the value will be stale. Use this function to + * find devices that are usually built into a system, or for a general hint as + * to if another device happens to be present at this specific moment in time. + */ +int pci_dev_present(const struct pci_device_id *ids) +{ + struct pci_dev *dev; + int found = 0; + + WARN_ON(in_interrupt()); + spin_lock(&pci_bus_lock); + while (ids->vendor || ids->subvendor || ids->class_mask) { + list_for_each_entry(dev, &pci_devices, global_list) { + if (pci_match_one_device(ids, dev)) { + found = 1; + goto exit; + } + } + ids++; + } +exit: + spin_unlock(&pci_bus_lock); + return found; +} +EXPORT_SYMBOL(pci_dev_present); + EXPORT_SYMBOL(pci_find_bus); -EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_slot); -EXPORT_SYMBOL(pci_find_subsys); EXPORT_SYMBOL(pci_get_device); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); +EXPORT_SYMBOL(pci_get_class); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 7f0f6c209..830baa225 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -533,15 +533,16 @@ EXPORT_SYMBOL(pci_bus_assign_resources); void __init pci_assign_unassigned_resources(void) { - struct list_head *ln; + struct pci_bus *bus; /* Depth first, calculate sizes and alignments of all subordinate buses. */ - for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) - pci_bus_size_bridges(pci_bus_b(ln)); + list_for_each_entry(bus, &pci_root_buses, node) { + pci_bus_size_bridges(bus); + } /* Depth last, allocate resources and update the hardware. */ - for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) { - pci_bus_assign_resources(pci_bus_b(ln)); - pci_enable_bridges(pci_bus_b(ln)); + list_for_each_entry(bus, &pci_root_buses, node) { + pci_bus_assign_resources(bus); + pci_enable_bridges(bus); } } diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c index c2ddc5059..677f1e7af 100644 --- a/drivers/pci/setup-irq.c +++ b/drivers/pci/setup-irq.c @@ -65,7 +65,7 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), int (*map_irq)(struct pci_dev *, u8, u8)) { struct pci_dev *dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { pdev_fixup_irq(dev, swizzle, map_irq); } } diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 42a5ad477..9fbf0d2d5 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) if (resno < 6) { reg = PCI_BASE_ADDRESS_0 + 4 * resno; } else if (resno == PCI_ROM_RESOURCE) { - new |= res->flags & PCI_ROM_ADDRESS_ENABLE; + new |= res->flags & IORESOURCE_ROM_ENABLE; reg = dev->rom_base_reg; } else { /* Hmm, non-standard resource. */ diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index e9654640d..c071790cc 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -11,12 +11,14 @@ #include #include #include +#include #include asmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, void *buf) + unsigned long off, unsigned long len, + void __user *buf) { struct pci_dev *dev; u8 byte; @@ -88,7 +90,8 @@ error: asmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, void *buf) + unsigned long off, unsigned long len, + void __user *buf) { struct pci_dev *dev; u8 byte; diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 8a4007516..63e5190e5 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -5,30 +5,24 @@ # by the integrated kernel driver. # -menu "PCMCIA/CardBus support" +menu "PCCARD (PCMCIA/CardBus) support" depends on HOTPLUG -config PCMCIA - tristate "PCMCIA/CardBus support" +config PCCARD + tristate "PCCard (PCMCIA/CardBus) support" ---help--- 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 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 - cards, you need to say Y here and also to "CardBus support" below. - - To use your PC-cards, you will need supporting software from David - Hinds' pcmcia-cs package (see the file - for location). Please also read the PCMCIA-HOWTO, available from - . + and the newer 32 bit CardBus cards. To compile this driver as modules, choose M here: the - modules will be called pcmcia_core and ds. + module will be called pcmcia_core. config PCMCIA_DEBUG - bool "Enable PCMCIA debugging" - depends on PCMCIA != n + bool "Enable PCCARD debugging" + depends on PCCARD != n help Say Y here to enable PCMCIA subsystem debugging. You will need to choose the debugging level either via the @@ -45,29 +39,69 @@ config PCMCIA_DEBUG In all the above examples, N is the debugging verbosity level. -config YENTA - tristate "CardBus yenta-compatible bridge support" - depends on PCMCIA && PCI +config PCMCIA_OBSOLETE + bool "Enable obsolete PCCARD code" + depends on PCCARD != n + help + Say Y here to enable some code found in the PCCARD subsystem + which has no in-kernel usage, but might be needed for certain + external PCMCIA drivers. If you do need to say Y here so that + one such driver compiles and/or works correctly, please report + this to linux-pcmcia lists.infradead.org + + If unsure, say N + +config PCMCIA + tristate "16-bit PCMCIA support" + depends on PCCARD + default y + ---help--- + This option enables support for 16-bit PCMCIA cards. Most older + PC-cards are such 16-bit PCMCIA cards, so unless you know you're + only using 32-bit CardBus cards, say Y or M here. + + To use 16-bit PCMCIA cards, you will need supporting software from + David Hinds' pcmcia-cs package (see the file + for location). Please also read the PCMCIA-HOWTO, available from + . + + To compile this driver as modules, choose M here: the + module will be called pcmcia. + + If unsure, say Y. + +config CARDBUS + bool "32-bit CardBus support" + depends on PCCARD && PCI + default y ---help--- CardBus is a bus mastering architecture for PC-cards, which allows for 32 bit PC-cards (the original PCMCIA standard specifies only a 16 bit wide bus). Many newer PC-cards are actually CardBus cards. - 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 - for location). + To use 32 bit PC-cards, you also need a CardBus compatible host + bridge. Virtually all modern PCMCIA bridges do this, and most of + them are "yenta-compatible", so say Y or M there, too. If unsure, say Y. -config CARDBUS - bool - depends on YENTA - default y if YENTA +comment "PC-card bridges" + +config YENTA + tristate "CardBus yenta-compatible bridge support" + depends on PCCARD && PCI +#fixme: remove dependendcy on CARDBUS + depends on CARDBUS + ---help--- + This option enables 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 compile this driver as modules, choose M here: the + module will be called yenta_socket. + + If unsure, say Y. config PD6729 tristate "Cirrus PD6729 compatible bridge support" @@ -133,10 +167,27 @@ config PCMCIA_PXA2XX help Say Y here to include support for the PXA2xx PCMCIA controller - config PCMCIA_PROBE bool default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X -endmenu +config M32R_PCC + bool "M32R PCMCIA I/F" + depends on M32R && CHIP_M32700 && PCMCIA + help + Say Y here to use the M32R PCMCIA controller. + +config M32R_CFC + bool "M32R CF I/F Controller" + depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT) + help + Say Y here to use the M32R CompactFlash controller. + +config M32R_CFC_NUM + int "M32R CF I/F number" + depends on M32R_CFC + default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT + help + Set the number of M32R CF slots. +endmenu diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 86acf410a..dff3caa0d 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -6,7 +6,16 @@ ifeq ($(CONFIG_PCMCIA_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif -obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o +pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o +pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o +obj-$(CONFIG_PCCARD) += pcmcia_core.o + +pcmcia-y += ds.o bulkmem.o pcmcia_compat.o +obj-$(CONFIG_PCMCIA) += pcmcia.o + + +# socket drivers + obj-$(CONFIG_YENTA) += yenta_socket.o obj-$(CONFIG_PD6729) += pd6729.o @@ -17,36 +26,23 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o - -pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o socket_sysfs.o -pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o +obj-$(CONFIG_M32R_PCC) += m32r_pcc.o +obj-$(CONFIG_M32R_CFC) += m32r_cfc.o sa11xx_core-y += soc_common.o sa11xx_base.o pxa2xx_core-y += soc_common.o pxa2xx_base.o sa1111_cs-y += sa1111_generic.o -sa1111_cs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o -sa1111_cs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o -sa1111_cs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o -sa1111_cs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o -sa1111_cs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1100_cs-y += sa1100_generic.o sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o -sa1100_cs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o -sa1100_cs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o -sa1100_cs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o -sa1100_cs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o -sa1100_cs-$(CONFIG_SA1100_STORK) += sa1100_stork.o -sa1100_cs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o -sa1100_cs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index bd79f3bd1..124225edc 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -566,7 +566,6 @@ static int au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) { unsigned int speed; - unsigned long start; u_long flags; if(map->map>=MAX_WIN){ @@ -588,25 +587,19 @@ au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) } spin_lock_irqsave(&pcmcia_lock, flags); - start=map->sys_start; - - if(map->sys_stop==0) - map->sys_stop=MAP_SIZE-1; - if (map->flags & MAP_ATTRIB) { - map->sys_start = pcmcia_socket[sock].phys_attr + + map->static_start = pcmcia_socket[sock].phys_attr + map->card_start; } else { - map->sys_start = pcmcia_socket[sock].phys_mem + + map->static_start = pcmcia_socket[sock].phys_mem + map->card_start; } - map->sys_stop=map->sys_start+(map->sys_stop-start); pcmcia_socket[sock].mem_map[map->map]=*map; spin_unlock_irqrestore(&pcmcia_lock, flags); - debug(3, "set_mem_map %d start %x stop %x card_start %x\n", - map->map, map->sys_start, map->sys_stop, + debug(3, "set_mem_map %d start %x card_start %x\n", + map->map, map->static_start, map->card_start); return 0; diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 3298828e2..855c1f76c 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -48,276 +48,18 @@ #include #include "cs_internal.h" -static void retry_erase_list(erase_busy_t *list, u_int cause); - -/*====================================================================== - - This function handles submitting an MTD request, and retrying - requests when an MTD is busy. - - An MTD request should never block. - -======================================================================*/ - -static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, - caddr_t buf) -{ - int ret, tries; - client_t *mtd; - struct pcmcia_socket *s; - - mtd = handle->mtd; - if (mtd == NULL) - return CS_GENERAL_FAILURE; - s = SOCKET(mtd); - for (ret = tries = 0; tries < 100; tries++) { - mtd->event_callback_args.mtdrequest = req; - mtd->event_callback_args.buffer = buf; - ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW); - if (ret != CS_BUSY) - break; - switch (req->Status) { - case MTD_WAITREQ: - /* Not that we should ever need this... */ - interruptible_sleep_on_timeout(&mtd->mtd_req, HZ); - break; - case MTD_WAITTIMER: - case MTD_WAITRDY: - interruptible_sleep_on_timeout(&mtd->mtd_req, req->Timeout*HZ/1000); - req->Function |= MTD_REQ_TIMEOUT; - break; - case MTD_WAITPOWER: - interruptible_sleep_on(&mtd->mtd_req); - break; - } - if (signal_pending(current)) - printk(KERN_NOTICE "cs: do_mtd_request interrupted!\n"); - } - if (tries == 20) { - printk(KERN_NOTICE "cs: MTD request timed out!\n"); - ret = CS_GENERAL_FAILURE; - } - wake_up_interruptible(&mtd->mtd_req); - retry_erase_list(&mtd->erase_busy, 0); - return ret; -} /* do_mtd_request */ - -/*====================================================================== - - This stuff is all for handling asynchronous erase requests. It - is complicated because all the retry stuff has to be dealt with - in timer interrupts or in the card status event handler. - -======================================================================*/ - -static void insert_queue(struct pcmcia_socket *s, erase_busy_t *head, erase_busy_t *entry) -{ - cs_dbg(s, 2, "adding 0x%p to queue 0x%p\n", entry, head); - entry->next = head; - entry->prev = head->prev; - head->prev->next = entry; - head->prev = entry; -} - -static void remove_queue(struct pcmcia_socket *s, erase_busy_t *entry) -{ - cs_dbg(s, 2, "unqueueing 0x%p\n", entry); - entry->next->prev = entry->prev; - entry->prev->next = entry->next; -} - -static void retry_erase(erase_busy_t *busy, u_int cause) -{ - eraseq_entry_t *erase = busy->erase; - mtd_request_t req; - client_t *mtd; - struct pcmcia_socket *s; - int ret; - - mtd = erase->Handle->mtd; - s = SOCKET(mtd); - - cs_dbg(s, 2, "trying erase request 0x%p...\n", busy); - if (busy->next) - remove_queue(s, busy); - req.Function = MTD_REQ_ERASE | cause; - req.TransferLength = erase->Size; - req.DestCardOffset = erase->Offset + erase->Handle->info.CardOffset; - req.MediaID = erase->Handle->MediaID; - mtd->event_callback_args.mtdrequest = &req; - ret = EVENT(mtd, CS_EVENT_MTD_REQUEST, CS_EVENT_PRI_LOW); - if (ret == CS_BUSY) { - cs_dbg(s, 2, " Status = %d, requeueing.\n", req.Status); - switch (req.Status) { - case MTD_WAITREQ: - case MTD_WAITPOWER: - insert_queue(s, &mtd->erase_busy, busy); - break; - case MTD_WAITTIMER: - case MTD_WAITRDY: - if (req.Status == MTD_WAITRDY) - insert_queue(s, &s->erase_busy, busy); - mod_timer(&busy->timeout, jiffies + req.Timeout*HZ/1000); - break; - } - } else { - /* update erase queue status */ - cs_dbg(s, 2, " Ret = %d\n", ret); - switch (ret) { - case CS_SUCCESS: - erase->State = ERASE_PASSED; break; - case CS_WRITE_PROTECTED: - erase->State = ERASE_MEDIA_WRPROT; break; - case CS_BAD_OFFSET: - erase->State = ERASE_BAD_OFFSET; break; - case CS_BAD_SIZE: - erase->State = ERASE_BAD_SIZE; break; - case CS_NO_CARD: - erase->State = ERASE_BAD_SOCKET; break; - default: - erase->State = ERASE_FAILED; break; - } - busy->client->event_callback_args.info = erase; - EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW); - kfree(busy); - /* Resubmit anything waiting for a request to finish */ - wake_up_interruptible(&mtd->mtd_req); - retry_erase_list(&mtd->erase_busy, 0); - } -} /* retry_erase */ - -static void retry_erase_list(erase_busy_t *list, u_int cause) -{ - erase_busy_t tmp = *list; - - cs_dbg(SOCKET(list->client), 2, "rescanning erase queue list 0x%p\n", list); - if (list->next == list) - return; - /* First, truncate the original list */ - list->prev->next = &tmp; - list->next->prev = &tmp; - list->prev = list->next = list; - tmp.prev->next = &tmp; - tmp.next->prev = &tmp; - - /* Now, retry each request, in order. */ - while (tmp.next != &tmp) - retry_erase(tmp.next, cause); -} /* retry_erase_list */ - -static void handle_erase_timeout(u_long arg) -{ - erase_busy_t *busy = (erase_busy_t *)arg; - cs_dbg(SOCKET(busy->client), 0, "erase timeout for entry 0x%lx\n", arg); - retry_erase(busy, MTD_REQ_TIMEOUT); -} - -static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase) -{ - erase_busy_t *busy; - region_info_t *info; - - if (CHECK_REGION(erase->Handle)) - erase->State = ERASE_BAD_SOCKET; - else { - info = &erase->Handle->info; - if ((erase->Offset >= info->RegionSize) || - (erase->Offset & (info->BlockSize-1))) - erase->State = ERASE_BAD_OFFSET; - else if ((erase->Offset+erase->Size > info->RegionSize) || - (erase->Size & (info->BlockSize-1))) - erase->State = ERASE_BAD_SIZE; - else { - erase->State = 1; - busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL); - if (!busy) { - erase->State = ERASE_FAILED; - return; - } - busy->erase = erase; - busy->client = handle; - init_timer(&busy->timeout); - busy->timeout.data = (u_long)busy; - busy->timeout.function = &handle_erase_timeout; - busy->prev = busy->next = NULL; - retry_erase(busy, 0); - } - } -} /* setup_erase_request */ - -/*====================================================================== - - MTD helper functions - -======================================================================*/ - -static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req) -{ - if ((win == NULL) || (win->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - win->ctl.flags = MAP_16BIT | MAP_ACTIVE; - if (req->Attributes & WIN_USE_WAIT) - win->ctl.flags |= MAP_USE_WAIT; - if (req->Attributes & WIN_MEMORY_TYPE) - win->ctl.flags |= MAP_ATTRIB; - win->ctl.speed = req->AccessSpeed; - win->ctl.card_start = req->CardOffset; - win->sock->ops->set_mem_map(win->sock, &win->ctl); - return CS_SUCCESS; -} - -static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req) -{ - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - if (req->Vpp1 != req->Vpp2) - return CS_BAD_VPP; - s = SOCKET(handle); - s->socket.Vpp = req->Vpp1; - if (s->ops->set_socket(s, &s->socket)) - return CS_BAD_VPP; - return CS_SUCCESS; -} - -static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req) -{ - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (req->Mask & CS_EVENT_READY_CHANGE) - s->socket.csc_mask |= SS_READY; - else - s->socket.csc_mask &= ~SS_READY; - if (s->ops->set_socket(s, &s->socket)) - return CS_GENERAL_FAILURE; - return CS_SUCCESS; -} - -int MTDHelperEntry(int func, void *a1, void *a2) -{ - switch (func) { - case MTDRequestWindow: - { - window_handle_t w; - int ret = pcmcia_request_window(a1, a2, &w); - a1 = w; - return ret; - } - break; - case MTDReleaseWindow: - return pcmcia_release_window(a1); - case MTDModifyWindow: - return mtd_modify_window(a1, a2); break; - case MTDSetVpp: - return mtd_set_vpp(a1, a2); break; - case MTDRDYMask: - return mtd_rdy_mask(a1, a2); break; - default: - return CS_UNSUPPORTED_FUNCTION; break; - } -} /* MTDHelperEntry */ +#ifdef DEBUG +extern int ds_pc_debug; +#define cs_socket_name(skt) ((skt)->dev.class_id) + +#define ds_dbg(skt, lvl, fmt, arg...) do { \ + if (ds_pc_debug >= lvl) \ + printk(KERN_DEBUG "ds: %s: " fmt, \ + cs_socket_name(skt) , ## arg); \ +} while (0) +#else +#define ds_dbg(lvl, fmt, arg...) do { } while (0) +#endif /*====================================================================== @@ -327,8 +69,8 @@ int MTDHelperEntry(int func, void *a1, void *a2) ======================================================================*/ -static void setup_regions(client_handle_t handle, int attr, - memory_handle_t *list) +static void setup_regions(struct pcmcia_socket *s, unsigned int function, + int attr, memory_handle_t *list) { int i, code, has_jedec, has_geo; u_int offset; @@ -337,22 +79,22 @@ static void setup_regions(client_handle_t handle, int attr, cistpl_device_geo_t geo; memory_handle_t r; - cs_dbg(SOCKET(handle), 1, "setup_regions(0x%p, %d, 0x%p)\n", - handle, attr, list); + ds_dbg(s, 1, "setup_regions(0x%d, %d, 0x%p)\n", + function, attr, list); code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE; - if (read_tuple(handle, code, &device) != CS_SUCCESS) + if (pccard_read_tuple(s, function, code, &device) != CS_SUCCESS) return; code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C; - has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS); + has_jedec = (pccard_read_tuple(s, function, code, &jedec) == CS_SUCCESS); if (has_jedec && (device.ndev != jedec.nid)) { - cs_dbg(SOCKET(handle), 0, "Device info does not match JEDEC info.\n"); + ds_dbg(s, 0, "Device info does not match JEDEC info.\n"); has_jedec = 0; } code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO; - has_geo = (read_tuple(handle, code, &geo) == CS_SUCCESS); + has_geo = (pccard_read_tuple(s, function, code, &geo) == CS_SUCCESS); if (has_geo && (device.ndev != geo.ngeo)) { - cs_dbg(SOCKET(handle), 0, "Device info does not match geometry tuple.\n"); + ds_dbg(s, 0, "Device info does not match geometry tuple.\n"); has_geo = 0; } @@ -400,6 +142,37 @@ static void setup_regions(client_handle_t handle, int attr, ======================================================================*/ +static int pccard_match_region(memory_handle_t list, region_info_t *match) +{ + if (list) { + *match = list->info; + return CS_SUCCESS; + } + return CS_NO_MORE_ITEMS; +} /* match_region */ + +int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn) +{ + if (!(s->state & SOCKET_REGION_INFO)) { + setup_regions(s, BIND_FN_ALL, 0, &s->c_region); + setup_regions(s, BIND_FN_ALL, 1, &s->a_region); + s->state |= SOCKET_REGION_INFO; + } + + if (rgn->Attributes & REGION_TYPE_AM) + return pccard_match_region(s->a_region, rgn); + else + return pccard_match_region(s->c_region, rgn); +} /* get_first_region */ + +int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn) +{ + return pccard_match_region(rgn->next, rgn); +} /* get_next_region */ + + +#ifdef CONFIG_PCMCIA_OBSOLETE + static int match_region(client_handle_t handle, memory_handle_t list, region_info_t *match) { @@ -422,8 +195,8 @@ int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn) if ((handle->Attributes & INFO_MASTER_CLIENT) && (!(s->state & SOCKET_REGION_INFO))) { - setup_regions(handle, 0, &s->c_region); - setup_regions(handle, 1, &s->a_region); + setup_regions(s, handle->Function, 0, &s->c_region); + setup_regions(s, handle->Function, 1, &s->a_region); s->state |= SOCKET_REGION_INFO; } @@ -432,6 +205,7 @@ int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn) else return match_region(handle, s->c_region, rgn); } /* get_first_region */ +EXPORT_SYMBOL(pcmcia_get_first_region); int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn) { @@ -439,200 +213,6 @@ int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn) return CS_BAD_HANDLE; return match_region(handle, rgn->next, rgn); } /* get_next_region */ +EXPORT_SYMBOL(pcmcia_get_next_region); -/*====================================================================== - - Connect an MTD with a memory region. - -======================================================================*/ - -int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg) -{ - memory_handle_t list; - struct pcmcia_socket *s; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (reg->Attributes & REGION_TYPE_AM) - list = s->a_region; - else - list = s->c_region; - cs_dbg(s, 1, "register_mtd(0x%p, '%s', 0x%x)\n", - handle, handle->dev_info, reg->Offset); - while (list) { - if (list->info.CardOffset == reg->Offset) break; - list = list->info.next; - } - if (list && (list->mtd == NULL) && - (strcmp(handle->dev_info, list->dev_info) == 0)) { - list->info.Attributes = reg->Attributes; - list->MediaID = reg->MediaID; - list->mtd = handle; - handle->mtd_count++; - return CS_SUCCESS; - } else - return CS_BAD_OFFSET; -} /* register_mtd */ - -/*====================================================================== - - Erase queue management functions - -======================================================================*/ - -int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header, - eraseq_handle_t *e) -{ - eraseq_t *queue; - - if ((handle == NULL) || CHECK_HANDLE(*handle)) - return CS_BAD_HANDLE; - queue = kmalloc(sizeof(*queue), GFP_KERNEL); - if (!queue) return CS_OUT_OF_RESOURCE; - queue->eraseq_magic = ERASEQ_MAGIC; - queue->handle = *handle; - queue->count = header->QueueEntryCnt; - queue->entry = header->QueueEntryArray; - *e = queue; - return CS_SUCCESS; -} /* register_erase_queue */ - -int pcmcia_deregister_erase_queue(eraseq_handle_t eraseq) -{ - int i; - if (CHECK_ERASEQ(eraseq)) - return CS_BAD_HANDLE; - for (i = 0; i < eraseq->count; i++) - if (ERASE_IN_PROGRESS(eraseq->entry[i].State)) break; - if (i < eraseq->count) - return CS_BUSY; - eraseq->eraseq_magic = 0; - kfree(eraseq); - return CS_SUCCESS; -} /* deregister_erase_queue */ - -int pcmcia_check_erase_queue(eraseq_handle_t eraseq) -{ - int i; - if (CHECK_ERASEQ(eraseq)) - return CS_BAD_HANDLE; - for (i = 0; i < eraseq->count; i++) - if (eraseq->entry[i].State == ERASE_QUEUED) - setup_erase_request(eraseq->handle, &eraseq->entry[i]); - return CS_SUCCESS; -} /* check_erase_queue */ - -/*====================================================================== - - Look up the memory region matching the request, and return a - memory handle. - -======================================================================*/ - -int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh) -{ - struct pcmcia_socket *s; - memory_handle_t region; - - if ((handle == NULL) || CHECK_HANDLE(*handle)) - return CS_BAD_HANDLE; - s = (*handle)->Socket; - if (open->Attributes & MEMORY_TYPE_AM) - region = s->a_region; - else - region = s->c_region; - while (region) { - if (region->info.CardOffset == open->Offset) break; - region = region->info.next; - } - if (region && region->mtd) { - *mh = region; - cs_dbg(s, 1, "open_memory(0x%p, 0x%x) = 0x%p\n", - handle, open->Offset, region); - return CS_SUCCESS; - } else - return CS_BAD_OFFSET; -} /* open_memory */ - -/*====================================================================== - - Close a memory handle from an earlier call to OpenMemory. - - For the moment, I don't think this needs to do anything. - -======================================================================*/ - -int pcmcia_close_memory(memory_handle_t handle) -{ - cs_dbg(SOCKET(handle->mtd), 1, "cs: close_memory(0x%p)\n", handle); - if (CHECK_REGION(handle)) - return CS_BAD_HANDLE; - return CS_SUCCESS; -} /* close_memory */ - -/*====================================================================== - - Read from a memory device, using a handle previously returned - by a call to OpenMemory. - -======================================================================*/ - -int pcmcia_read_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf) -{ - mtd_request_t mtd; - if (CHECK_REGION(handle)) - return CS_BAD_HANDLE; - if (req->Offset >= handle->info.RegionSize) - return CS_BAD_OFFSET; - if (req->Offset+req->Count > handle->info.RegionSize) - return CS_BAD_SIZE; - - mtd.SrcCardOffset = req->Offset + handle->info.CardOffset; - mtd.TransferLength = req->Count; - mtd.MediaID = handle->MediaID; - mtd.Function = MTD_REQ_READ; - if (req->Attributes & MEM_OP_BUFFER_KERNEL) - mtd.Function |= MTD_REQ_KERNEL; - return do_mtd_request(handle, &mtd, buf); -} /* read_memory */ - -/*====================================================================== - - Write to a memory device, using a handle previously returned by - a call to OpenMemory. - -======================================================================*/ - -int pcmcia_write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf) -{ - mtd_request_t mtd; - if (CHECK_REGION(handle)) - return CS_BAD_HANDLE; - if (req->Offset >= handle->info.RegionSize) - return CS_BAD_OFFSET; - if (req->Offset+req->Count > handle->info.RegionSize) - return CS_BAD_SIZE; - - mtd.DestCardOffset = req->Offset + handle->info.CardOffset; - mtd.TransferLength = req->Count; - mtd.MediaID = handle->MediaID; - mtd.Function = MTD_REQ_WRITE; - if (req->Attributes & MEM_OP_BUFFER_KERNEL) - mtd.Function |= MTD_REQ_KERNEL; - return do_mtd_request(handle, &mtd, buf); -} /* write_memory */ - -/*====================================================================== - - This isn't needed for anything I could think of. - -======================================================================*/ - -int pcmcia_copy_memory(memory_handle_t handle, copy_op_t *req) -{ - if (CHECK_REGION(handle)) - return CS_BAD_HANDLE; - return CS_UNSUPPORTED_FUNCTION; -} - +#endif diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 4dab2ffc8..1b86c6d3a 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -85,7 +85,7 @@ =====================================================================*/ -static u_int xlate_rom_addr(u_char * b, u_int addr) +static u_int xlate_rom_addr(void __iomem *b, u_int addr) { u_int img = 0, ofs = 0, sz; u_short data; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index b78d41a3c..8cf062339 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -103,7 +103,7 @@ void release_cis_mem(struct pcmcia_socket *s) * If flags & MAP_ATTRIB, map the attribute space, otherwise * map the memory space. */ -static unsigned char * +static void __iomem * set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { pccard_mem_map *mem = &s->cis_mem; @@ -114,8 +114,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag printk(KERN_NOTICE "cs: unable to map card memory!\n"); return NULL; } - mem->sys_start = mem->res->start; - mem->sys_stop = mem->res->end; s->cis_virt = ioremap(mem->res->start, s->map_size); } mem->card_start = card_offset; @@ -124,7 +122,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag if (s->features & SS_CAP_STATIC_MAP) { if (s->cis_virt) iounmap(s->cis_virt); - s->cis_virt = ioremap(mem->sys_start, s->map_size); + s->cis_virt = ioremap(mem->static_start, s->map_size); } return s->cis_virt; } @@ -143,7 +141,8 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { - u_char *sys, *end, *buf = ptr; + void __iomem *sys, *end; + unsigned char *buf = ptr; cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len); @@ -206,7 +205,8 @@ int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { - u_char *sys, *end, *buf = ptr; + void __iomem *sys, *end; + unsigned char *buf = ptr; cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len); @@ -331,6 +331,14 @@ void destroy_cis_cache(struct pcmcia_socket *s) list_del(&cis->node); kfree(cis); } + + /* + * If there was a fake CIS, destroy that as well. + */ + if (s->fake_cis) { + kfree(s->fake_cis); + s->fake_cis = NULL; + } } /*====================================================================== @@ -376,12 +384,8 @@ int verify_cis_cache(struct pcmcia_socket *s) ======================================================================*/ -int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis) +int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) { - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); if (s->fake_cis != NULL) { kfree(s->fake_cis); s->fake_cis = NULL; @@ -414,14 +418,12 @@ typedef struct tuple_flags { #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn) #define SPACE(f) (((tuple_flags *)(&(f)))->space) -int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple); +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple); -int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) +int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple) { - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) + if (!s) return CS_BAD_HANDLE; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; tuple->TupleLink = tuple->Flags = 0; @@ -443,16 +445,17 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) !(tuple->Attributes & TUPLE_RETURN_COMMON)) { cisdata_t req = tuple->DesiredTuple; tuple->DesiredTuple = CISTPL_LONGLINK_MFC; - if (pcmcia_get_next_tuple(handle, tuple) == CS_SUCCESS) { + if (pccard_get_next_tuple(s, function, tuple) == CS_SUCCESS) { tuple->DesiredTuple = CISTPL_LINKTARGET; - if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) + if (pccard_get_next_tuple(s, function, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; } else tuple->CISOffset = tuple->TupleLink = 0; tuple->DesiredTuple = req; } - return pcmcia_get_next_tuple(handle, tuple); + return pccard_get_next_tuple(s, function, tuple); } +EXPORT_SYMBOL(pccard_get_first_tuple); static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) { @@ -494,15 +497,13 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) return -1; } -int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple) { - struct pcmcia_socket *s; u_char link[2], tmp; int ofs, i, attr; - - if (CHECK_HANDLE(handle)) + + if (!s) return CS_BAD_HANDLE; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -554,14 +555,14 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) case CISTPL_LONGLINK_MFC: tuple->LinkOffset = ofs + 3; LINK_SPACE(tuple->Flags) = attr; - if (handle->Function == BIND_FN_ALL) { + if (function == BIND_FN_ALL) { /* Follow all the MFC links */ read_cis_cache(s, attr, ofs+2, 1, &tmp); MFC_FN(tuple->Flags) = tmp; } else { /* Follow exactly one of the links */ MFC_FN(tuple->Flags) = 1; - tuple->LinkOffset += handle->Function * 5; + tuple->LinkOffset += function * 5; } break; case CISTPL_NO_LINK: @@ -589,20 +590,18 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) tuple->CISOffset = ofs + 2; return CS_SUCCESS; } +EXPORT_SYMBOL(pccard_get_next_tuple); /*====================================================================*/ #define _MIN(a, b) (((a) < (b)) ? (a) : (b)) -int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) +int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple) { - struct pcmcia_socket *s; u_int len; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); + if (!s) + return CS_BAD_HANDLE; if (tuple->TupleLink < tuple->TupleOffset) return CS_NO_MORE_ITEMS; @@ -615,6 +614,8 @@ int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) _MIN(len, tuple->TupleDataMax), tuple->TupleData); return CS_SUCCESS; } +EXPORT_SYMBOL(pccard_get_tuple_data); + /*====================================================================== @@ -1320,7 +1321,7 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt) /*====================================================================*/ -int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse) { int ret = CS_SUCCESS; @@ -1401,6 +1402,7 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse } return ret; } +EXPORT_SYMBOL(pccard_parse_tuple); /*====================================================================== @@ -1408,7 +1410,7 @@ int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse ======================================================================*/ -int read_tuple(client_handle_t handle, cisdata_t code, void *parse) +int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse) { tuple_t tuple; cisdata_t *buf; @@ -1419,18 +1421,19 @@ int read_tuple(client_handle_t handle, cisdata_t code, void *parse) return CS_OUT_OF_RESOURCE; tuple.DesiredTuple = code; tuple.Attributes = TUPLE_RETURN_COMMON; - ret = pcmcia_get_first_tuple(handle, &tuple); + ret = pccard_get_first_tuple(s, function, &tuple); if (ret != CS_SUCCESS) goto done; tuple.TupleData = buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - ret = pcmcia_get_tuple_data(handle, &tuple); + ret = pccard_get_tuple_data(s, &tuple); if (ret != CS_SUCCESS) goto done; - ret = pcmcia_parse_tuple(handle, &tuple, parse); + ret = pccard_parse_tuple(&tuple, parse); done: kfree(buf); return ret; } +EXPORT_SYMBOL(pccard_read_tuple); /*====================================================================== @@ -1442,14 +1445,15 @@ done: ======================================================================*/ -int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info) { tuple_t *tuple; cisparse_t *p; int ret, reserved, dev_ok = 0, ident_ok = 0; - if (CHECK_HANDLE(handle)) + if (!s) return CS_BAD_HANDLE; + tuple = kmalloc(sizeof(*tuple), GFP_KERNEL); if (tuple == NULL) return CS_OUT_OF_RESOURCE; @@ -1462,30 +1466,30 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) info->Chains = reserved = 0; tuple->DesiredTuple = RETURN_FIRST_TUPLE; tuple->Attributes = TUPLE_RETURN_COMMON; - ret = pcmcia_get_first_tuple(handle, tuple); + ret = pccard_get_first_tuple(s, function, tuple); if (ret != CS_SUCCESS) goto done; /* First tuple should be DEVICE; we should really have either that or a CFTABLE_ENTRY of some sort */ if ((tuple->TupleCode == CISTPL_DEVICE) || - (read_tuple(handle, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) || - (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS)) + (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS)) dev_ok++; /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 tuple, for card identification. Certain old D-Link and Linksys cards have only a broken VERS_2 tuple; hence the bogus test. */ - if ((read_tuple(handle, CISTPL_MANFID, p) == CS_SUCCESS) || - (read_tuple(handle, CISTPL_VERS_1, p) == CS_SUCCESS) || - (read_tuple(handle, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS)) + if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == CS_SUCCESS) || + (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS)) ident_ok++; if (!dev_ok && !ident_ok) goto done; for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) { - ret = pcmcia_get_next_tuple(handle, tuple); + ret = pccard_get_next_tuple(s, function, tuple); if (ret != CS_SUCCESS) break; if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) || @@ -1501,4 +1505,4 @@ done: kfree(p); return CS_SUCCESS; } - +EXPORT_SYMBOL(pccard_validate_cis); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f796bc99c..4e4c964f7 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -249,7 +249,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) /* base address = 0, map = 0 */ socket->cis_mem.flags = 0; socket->cis_mem.speed = cis_speed; - socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy; + INIT_LIST_HEAD(&socket->cis_cache); spin_lock_init(&socket->lock); @@ -364,10 +364,6 @@ static void shutdown_socket(struct pcmcia_socket *s) s->irq.AssignedIRQ = s->irq.Config = 0; s->lock_count = 0; destroy_cis_cache(s); - if (s->fake_cis) { - kfree(s->fake_cis); - s->fake_cis = NULL; - } #ifdef CONFIG_CARDBUS cb_free(s); #endif @@ -427,8 +423,6 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority) return ret; } /* send_event */ -#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100) - static void socket_remove_drivers(struct pcmcia_socket *skt) { client_t *client; @@ -448,8 +442,7 @@ static void socket_shutdown(struct pcmcia_socket *skt) socket_remove_drivers(skt); skt->state &= SOCKET_INUSE|SOCKET_PRESENT; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(shutdown_delay)); + msleep(shutdown_delay * 10); skt->state &= SOCKET_INUSE; shutdown_socket(skt); } @@ -467,8 +460,7 @@ static int socket_reset(struct pcmcia_socket *skt) skt->socket.flags &= ~SS_RESET; skt->ops->set_socket(skt, &skt->socket); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(unreset_delay)); + msleep(unreset_delay * 10); for (i = 0; i < unreset_limit; i++) { skt->ops->get_status(skt, &status); @@ -478,8 +470,7 @@ static int socket_reset(struct pcmcia_socket *skt) if (status & SS_READY) return CS_SUCCESS; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(unreset_check)); + msleep(unreset_check * 10); } cs_err(skt, "time out after reset.\n"); @@ -496,8 +487,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay) if (!(status & SS_DETECT)) return CS_NO_CARD; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(initial_delay)); + msleep(initial_delay * 10); for (i = 0; i < 100; i++) { skt->ops->get_status(skt, &status); @@ -507,8 +497,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay) if (!(status & SS_PENDING)) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(10)); + msleep(100); } if (status & SS_PENDING) { @@ -541,8 +530,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay) /* * Wait "vcc_settle" for the supply to stabilise. */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(vcc_settle)); + msleep(vcc_settle * 10); skt->ops->get_status(skt, &status); if (!(status & SS_POWERON)) { @@ -621,10 +609,18 @@ static int socket_resume(struct pcmcia_socket *skt) * FIXME: need a better check here for cardbus cards. */ if (verify_cis_cache(skt) != 0) { + cs_dbg(skt, 4, "cis mismatch - different card\n"); socket_remove_drivers(skt); destroy_cis_cache(skt); + /* + * Workaround: give DS time to schedule removal. + * Remove me once the 100ms delay is eliminated + * in ds.c + */ + msleep(200); send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); } else { + cs_dbg(skt, 4, "cis matches cache\n"); send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); } } else { @@ -659,10 +655,8 @@ static void socket_detect_change(struct pcmcia_socket *skt) if (!(skt->state & SOCKET_SUSPEND)) { int status; - if (!(skt->state & SOCKET_PRESENT)) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(cs_to_timeout(2)); - } + if (!(skt->state & SOCKET_PRESENT)) + msleep(20); skt->ops->get_status(skt, &status); if ((skt->state & SOCKET_PRESENT) && @@ -856,23 +850,18 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, ======================================================================*/ -int pcmcia_access_configuration_register(client_handle_t handle, +int pccard_access_configuration_register(struct pcmcia_socket *s, + unsigned int function, conf_reg_t *reg) { - struct pcmcia_socket *s; config_t *c; int addr; u_char val; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (handle->Function == BIND_FN_ALL) { - if (reg->Function >= s->functions) - return CS_BAD_ARGS; - c = &s->config[reg->Function]; - } else - c = CONFIG(handle); + + if (!s || !s->config) + return CS_NO_CARD; + + c = &s->config[function]; if (c == NULL) return CS_NO_CARD; @@ -897,7 +886,7 @@ int pcmcia_access_configuration_register(client_handle_t handle, } return CS_SUCCESS; } /* access_configuration_register */ - +EXPORT_SYMBOL(pccard_access_configuration_register); /*====================================================================*/ @@ -905,7 +894,6 @@ int pcmcia_deregister_client(client_handle_t handle) { client_t **client; struct pcmcia_socket *s; - memory_handle_t region; u_long flags; int i; @@ -922,14 +910,6 @@ int pcmcia_deregister_client(client_handle_t handle) if (handle->state & CLIENT_WIN_REQ(i)) return CS_IN_USE; - /* Disconnect all MTD links */ - if (handle->mtd_count) { - for (region = s->a_region; region; region = region->info.next) - if (region->mtd == handle) region->mtd = NULL; - for (region = s->c_region; region; region = region->info.next) - if (region->mtd == handle) region->mtd = NULL; - } - if ((handle->state & CLIENT_STALE) || (handle->Attributes & INFO_MASTER_CLIENT)) { spin_lock_irqsave(&s->lock, flags); @@ -946,7 +926,6 @@ int pcmcia_deregister_client(client_handle_t handle) spin_unlock_irqrestore(&s->lock, flags); } else { handle->state = CLIENT_UNBOUND; - handle->mtd_count = 0; handle->event_handler = NULL; } @@ -955,29 +934,20 @@ int pcmcia_deregister_client(client_handle_t handle) /*====================================================================*/ -int pcmcia_get_configuration_info(client_handle_t handle, +int pccard_get_configuration_info(struct pcmcia_socket *s, + unsigned int function, config_info_t *config) { - struct pcmcia_socket *s; config_t *c; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - if (handle->Function == BIND_FN_ALL) { - if (config->Function && (config->Function >= s->functions)) - return CS_BAD_ARGS; - } else - config->Function = handle->Function; - + config->Function = function; + #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { - u_char fn = config->Function; memset(config, 0, sizeof(config_info_t)); - config->Function = fn; config->Vcc = s->socket.Vcc; config->Vpp1 = config->Vpp2 = s->socket.Vpp; config->Option = s->cb_dev->subordinate->number; @@ -994,7 +964,7 @@ int pcmcia_get_configuration_info(client_handle_t handle, } #endif - c = (s->config != NULL) ? &s->config[config->Function] : NULL; + c = (s->config != NULL) ? &s->config[function] : NULL; if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { config->Attributes = 0; @@ -1019,6 +989,7 @@ int pcmcia_get_configuration_info(client_handle_t handle, return CS_SUCCESS; } /* get_configuration_info */ +EXPORT_SYMBOL(pccard_get_configuration_info); /*====================================================================== @@ -1043,6 +1014,8 @@ int pcmcia_get_card_services_info(servinfo_t *info) return CS_SUCCESS; } /* get_card_services_info */ +#ifdef CONFIG_PCMCIA_OBSOLETE + /*====================================================================== Note that get_first_client() *does* recognize the Socket field @@ -1066,6 +1039,7 @@ int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req) *handle = socket->clients; return CS_SUCCESS; } /* get_first_client */ +EXPORT_SYMBOL(pcmcia_get_first_client); /*====================================================================*/ @@ -1085,20 +1059,17 @@ int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req) *handle = (*handle)->next; return CS_SUCCESS; } /* get_next_client */ +EXPORT_SYMBOL(pcmcia_get_next_client); +#endif /* CONFIG_PCMCIA_OBSOLETE */ /*====================================================================*/ -int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req) +int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req) { - struct pcmcia_socket *s; window_t *win; int w; - if (idx == 0) - s = ((client_handle_t)*handle)->Socket; - else - s = (*handle)->sock; - if (!(s->state & SOCKET_PRESENT)) + if (!s || !(s->state & SOCKET_PRESENT)) return CS_NO_CARD; for (w = idx; w < MAX_WIN; w++) if (s->state & SOCKET_WIN_REQ(w)) break; @@ -1120,20 +1091,7 @@ int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req) *handle = win; return CS_SUCCESS; } /* get_window */ - -int pcmcia_get_first_window(window_handle_t *win, win_req_t *req) -{ - if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - return pcmcia_get_window(win, 0, req); -} - -int pcmcia_get_next_window(window_handle_t *win, win_req_t *req) -{ - if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - return pcmcia_get_window(win, (*win)->index+1, req); -} +EXPORT_SYMBOL(pcmcia_get_window); /*===================================================================== @@ -1143,14 +1101,9 @@ int pcmcia_get_next_window(window_handle_t *win, win_req_t *req) #ifdef CONFIG_CARDBUS -struct pci_bus *pcmcia_lookup_bus(client_handle_t handle) +struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) { - struct pcmcia_socket *s; - - if (CHECK_HANDLE(handle)) - return NULL; - s = SOCKET(handle); - if (!(s->state & SOCKET_CARDBUS)) + if (!s || !(s->state & SOCKET_CARDBUS)) return NULL; return s->cb_dev->subordinate; @@ -1167,15 +1120,11 @@ EXPORT_SYMBOL(pcmcia_lookup_bus); ======================================================================*/ -int pcmcia_get_status(client_handle_t handle, cs_status_t *status) +int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status) { - struct pcmcia_socket *s; config_t *c; int val; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); s->ops->get_status(s, &val); status->CardState = status->SocketState = 0; status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; @@ -1187,13 +1136,7 @@ int pcmcia_get_status(client_handle_t handle, cs_status_t *status) if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - /* Get info from the PRR, if necessary */ - if (handle->Function == BIND_FN_ALL) { - if (status->Function && (status->Function >= s->functions)) - return CS_BAD_ARGS; - c = (s->config != NULL) ? &s->config[status->Function] : NULL; - } else - c = CONFIG(handle); + c = (s->config != NULL) ? &s->config[function] : NULL; if ((c != NULL) && (c->state & CONFIG_LOCKED) && (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { u_char reg; @@ -1228,6 +1171,7 @@ int pcmcia_get_status(client_handle_t handle, cs_status_t *status) (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; return CS_SUCCESS; } /* get_status */ +EXPORT_SYMBOL(pccard_get_status); /*====================================================================== @@ -1307,6 +1251,8 @@ int pcmcia_modify_configuration(client_handle_t handle, return CS_SUCCESS; } /* modify_configuration */ +#ifdef CONFIG_PCMCIA_OBSOLETE + /*====================================================================== Modify the attributes of a window returned by RequestWindow. @@ -1332,6 +1278,10 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req) return CS_SUCCESS; } /* modify_window */ +EXPORT_SYMBOL(pcmcia_modify_window); + +#endif /* CONFIG_PCMCIA_OBSOLETE */ + /*====================================================================== @@ -1381,7 +1331,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) && (client->Function != BIND_FN_ALL)) { cistpl_longlink_mfc_t mfc; - if (read_tuple(client, CISTPL_LONGLINK_MFC, &mfc) + if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc) == CS_SUCCESS) s->functions = mfc.nfn; else @@ -1886,11 +1836,6 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle (*handle)->dev_info, s); if (!win->ctl.res) return CS_IN_USE; - win->ctl.sys_start = win->ctl.res->start; - win->ctl.sys_stop = win->ctl.res->end; - } else { - win->ctl.sys_start = req->Base; - win->ctl.sys_stop = req->Base + req->Size - 1; } (*handle)->state |= CLIENT_WIN_REQ(w); @@ -1912,7 +1857,11 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle s->state |= SOCKET_WIN_REQ(w); /* Return window handle */ - req->Base = win->ctl.sys_start; + if (s->features & SS_CAP_STATIC_MAP) { + req->Base = win->ctl.static_start; + } else { + req->Base = win->ctl.res->start; + } *wh = win; return CS_SUCCESS; @@ -1926,14 +1875,10 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle ======================================================================*/ -int pcmcia_reset_card(client_handle_t handle, client_req_t *req) +int pccard_reset_card(struct pcmcia_socket *skt) { - struct pcmcia_socket *skt; int ret; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - skt = SOCKET(handle); cs_dbg(skt, 1, "resetting socket\n"); down(&skt->skt_sem); @@ -1958,15 +1903,13 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); } - handle->event_callback_args.info = (void *)(u_long)ret; - EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW); - ret = CS_SUCCESS; } while (0); up(&skt->skt_sem); return ret; } /* reset_card */ +EXPORT_SYMBOL(pccard_reset_card); /*====================================================================== @@ -2084,6 +2027,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) ======================================================================*/ +#ifdef CONFIG_PCMCIA_OBSOLETE int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask) { u_int events, bit; @@ -2101,6 +2045,9 @@ int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask) } return CS_SUCCESS; } /* set_event_mask */ +EXPORT_SYMBOL(pcmcia_set_event_mask); + +#endif /* CONFIG_PCMCIA_OBSOLETE */ /*====================================================================== @@ -2108,37 +2055,14 @@ int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask) ======================================================================*/ /* in alpha order */ -EXPORT_SYMBOL(pcmcia_access_configuration_register); -EXPORT_SYMBOL(pcmcia_adjust_resource_info); -EXPORT_SYMBOL(pcmcia_check_erase_queue); -EXPORT_SYMBOL(pcmcia_close_memory); -EXPORT_SYMBOL(pcmcia_copy_memory); EXPORT_SYMBOL(pcmcia_deregister_client); -EXPORT_SYMBOL(pcmcia_deregister_erase_queue); EXPORT_SYMBOL(pcmcia_eject_card); -EXPORT_SYMBOL(pcmcia_get_first_client); EXPORT_SYMBOL(pcmcia_get_card_services_info); -EXPORT_SYMBOL(pcmcia_get_configuration_info); EXPORT_SYMBOL(pcmcia_get_mem_page); -EXPORT_SYMBOL(pcmcia_get_next_client); -EXPORT_SYMBOL(pcmcia_get_first_region); -EXPORT_SYMBOL(pcmcia_get_first_tuple); -EXPORT_SYMBOL(pcmcia_get_first_window); -EXPORT_SYMBOL(pcmcia_get_next_region); -EXPORT_SYMBOL(pcmcia_get_next_tuple); -EXPORT_SYMBOL(pcmcia_get_next_window); -EXPORT_SYMBOL(pcmcia_get_status); -EXPORT_SYMBOL(pcmcia_get_tuple_data); EXPORT_SYMBOL(pcmcia_insert_card); EXPORT_SYMBOL(pcmcia_map_mem_page); EXPORT_SYMBOL(pcmcia_modify_configuration); -EXPORT_SYMBOL(pcmcia_modify_window); -EXPORT_SYMBOL(pcmcia_open_memory); -EXPORT_SYMBOL(pcmcia_parse_tuple); -EXPORT_SYMBOL(pcmcia_read_memory); EXPORT_SYMBOL(pcmcia_register_client); -EXPORT_SYMBOL(pcmcia_register_erase_queue); -EXPORT_SYMBOL(pcmcia_register_mtd); EXPORT_SYMBOL(pcmcia_release_configuration); EXPORT_SYMBOL(pcmcia_release_io); EXPORT_SYMBOL(pcmcia_release_irq); @@ -2148,15 +2072,10 @@ EXPORT_SYMBOL(pcmcia_request_configuration); EXPORT_SYMBOL(pcmcia_request_io); EXPORT_SYMBOL(pcmcia_request_irq); EXPORT_SYMBOL(pcmcia_request_window); -EXPORT_SYMBOL(pcmcia_reset_card); EXPORT_SYMBOL(pcmcia_resume_card); -EXPORT_SYMBOL(pcmcia_set_event_mask); EXPORT_SYMBOL(pcmcia_suspend_card); -EXPORT_SYMBOL(pcmcia_validate_cis); -EXPORT_SYMBOL(pcmcia_write_memory); EXPORT_SYMBOL(dead_socket); -EXPORT_SYMBOL(MTDHelperEntry); EXPORT_SYMBOL(pcmcia_parse_events); struct class pcmcia_socket_class = { diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index e148fb967..fbce6b679 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -21,14 +21,6 @@ #include -#define ERASEQ_MAGIC 0xFA67 -typedef struct eraseq_t { - u_short eraseq_magic; - client_handle_t handle; - int count; - eraseq_entry_t *entry; -} eraseq_t; - #define CLIENT_MAGIC 0x51E6 typedef struct client_t { u_short client_magic; @@ -42,9 +34,6 @@ typedef struct client_t { event_callback_args_t *); event_callback_args_t event_callback_args; struct client_t *next; - u_int mtd_count; - wait_queue_head_t mtd_req; - erase_busy_t erase_busy; } client_t; /* Flags in client state */ @@ -157,27 +146,7 @@ void write_cis_mem(struct pcmcia_socket *s, int attr, void release_cis_mem(struct pcmcia_socket *s); void destroy_cis_cache(struct pcmcia_socket *s); int verify_cis_cache(struct pcmcia_socket *s); -void preload_cis_cache(struct pcmcia_socket *s); -int get_first_tuple(client_handle_t handle, tuple_t *tuple); -int get_next_tuple(client_handle_t handle, tuple_t *tuple); -int get_tuple_data(client_handle_t handle, tuple_t *tuple); -int parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse); -int validate_cis(client_handle_t handle, cisinfo_t *info); -int replace_cis(client_handle_t handle, cisdump_t *cis); -int read_tuple(client_handle_t handle, cisdata_t code, void *parse); - -/* In bulkmem.c */ -int get_first_region(client_handle_t handle, region_info_t *rgn); -int get_next_region(client_handle_t handle, region_info_t *rgn); -int register_mtd(client_handle_t handle, mtd_reg_t *reg); -int register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header); -int deregister_erase_queue(eraseq_handle_t eraseq); -int check_erase_queue(eraseq_handle_t eraseq); -int open_memory(client_handle_t *handle, open_mem_t *open); -int close_memory(memory_handle_t handle); -int read_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf); -int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf); -int copy_memory(memory_handle_t handle, copy_op_t *req); +int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse); /* In rsrc_mgr */ void pcmcia_validate_mem(struct pcmcia_socket *s); @@ -198,6 +167,11 @@ extern struct class_interface pccard_sysfs_interface; /* In cs.c */ extern struct rw_semaphore pcmcia_socket_list_rwsem; extern struct list_head pcmcia_socket_list; +int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); +int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config); +int pccard_reset_card(struct pcmcia_socket *skt); +int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status); +int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg); #define cs_socket_name(skt) ((skt)->dev.class_id) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 71592c71d..639c5acf2 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -74,12 +75,12 @@ MODULE_DESCRIPTION("PCMCIA Driver Services"); MODULE_LICENSE("Dual MPL/GPL"); #ifdef DEBUG -static int pc_debug; +int ds_pc_debug; -module_param(pc_debug, int, 0644); +module_param_named(pc_debug, ds_pc_debug, int, 0644); #define ds_dbg(lvl, fmt, arg...) do { \ - if (pc_debug > (lvl)) \ + if (ds_pc_debug > (lvl)) \ printk(KERN_DEBUG "ds: " fmt , ## arg); \ } while (0) #else @@ -133,8 +134,6 @@ static dev_info_t dev_info = "Driver Services"; static int major_dev = -1; -extern struct proc_dir_entry *proc_pccard; - /*====================================================================*/ /* code which was in cs.c before */ @@ -166,9 +165,6 @@ static int pcmcia_bind_device(bind_req_t *req) client->Socket = s; client->Function = req->Function; client->state = CLIENT_UNBOUND; - client->erase_busy.next = &client->erase_busy; - client->erase_busy.prev = &client->erase_busy; - init_waitqueue_head(&client->mtd_req); client->next = s->clients; s->clients = client; ds_dbg(1, "%s: bind_device(): client 0x%p, dev %s\n", @@ -629,6 +625,8 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) /*====================================================================*/ +extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s); + static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) { socket_bind_t *b; @@ -642,7 +640,7 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, { struct pci_bus *bus; - bus = pcmcia_lookup_bus(s->handle); + bus = pcmcia_lookup_bus(s->parent); if (bus) { struct list_head *list; struct pci_dev *dev = NULL; @@ -884,6 +882,10 @@ static u_int ds_poll(struct file *file, poll_table *wait) /*====================================================================*/ +extern int pcmcia_adjust_resource_info(adjust_t *adj); +extern int pccard_get_next_region(struct pcmcia_socket *s, region_info_t *rgn); +extern int pccard_get_first_region(struct pcmcia_socket *s, region_info_t *rgn); + static int ds_ioctl(struct inode * inode, struct file * file, u_int cmd, u_long arg) { @@ -932,39 +934,47 @@ static int ds_ioctl(struct inode * inode, struct file * file, switch (cmd) { case DS_ADJUST_RESOURCE_INFO: - ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust); + ret = pcmcia_adjust_resource_info(&buf.adjust); break; case DS_GET_CARD_SERVICES_INFO: ret = pcmcia_get_card_services_info(&buf.servinfo); break; case DS_GET_CONFIGURATION_INFO: - ret = pcmcia_get_configuration_info(s->handle, &buf.config); + if (buf.config.Function && + (buf.config.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_get_configuration_info(s->parent, buf.config.Function, &buf.config); break; case DS_GET_FIRST_TUPLE: pcmcia_validate_mem(s->parent); - ret = pcmcia_get_first_tuple(s->handle, &buf.tuple); + ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf.tuple); break; case DS_GET_NEXT_TUPLE: - ret = pcmcia_get_next_tuple(s->handle, &buf.tuple); + ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf.tuple); break; case DS_GET_TUPLE_DATA: buf.tuple.TupleData = buf.tuple_parse.data; buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); - ret = pcmcia_get_tuple_data(s->handle, &buf.tuple); + ret = pccard_get_tuple_data(s->parent, &buf.tuple); break; case DS_PARSE_TUPLE: buf.tuple.TupleData = buf.tuple_parse.data; - ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse); + ret = pccard_parse_tuple(&buf.tuple, &buf.tuple_parse.parse); break; case DS_RESET_CARD: - ret = pcmcia_reset_card(s->handle, NULL); + ret = pccard_reset_card(s->parent); break; case DS_GET_STATUS: - ret = pcmcia_get_status(s->handle, &buf.status); + if (buf.status.Function && + (buf.status.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_get_status(s->parent, buf.status.Function, &buf.status); break; case DS_VALIDATE_CIS: pcmcia_validate_mem(s->parent); - ret = pcmcia_validate_cis(s->handle, &buf.cisinfo); + ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf.cisinfo); break; case DS_SUSPEND_CARD: ret = pcmcia_suspend_card(s->parent); @@ -981,27 +991,30 @@ static int ds_ioctl(struct inode * inode, struct file * file, case DS_ACCESS_CONFIGURATION_REGISTER: if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; - ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg); + if (buf.conf_reg.Function && + (buf.conf_reg.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_access_configuration_register(s->parent, buf.conf_reg.Function, &buf.conf_reg); break; case DS_GET_FIRST_REGION: - ret = pcmcia_get_first_region(s->handle, &buf.region); + ret = pccard_get_first_region(s->parent, &buf.region); break; case DS_GET_NEXT_REGION: - ret = pcmcia_get_next_region(s->handle, &buf.region); + ret = pccard_get_next_region(s->parent, &buf.region); break; case DS_GET_FIRST_WINDOW: - buf.win_info.handle = (window_handle_t)s->handle; - ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window); + ret = pcmcia_get_window(s->parent, &buf.win_info.handle, 0, &buf.win_info.window); break; case DS_GET_NEXT_WINDOW: - ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window); + ret = pcmcia_get_window(s->parent, &buf.win_info.handle, buf.win_info.handle->index + 1, &buf.win_info.window); break; case DS_GET_MEM_PAGE: ret = pcmcia_get_mem_page(buf.win_info.handle, &buf.win_info.map); break; case DS_REPLACE_CIS: - ret = pcmcia_replace_cis(s->handle, &buf.cisdump); + ret = pcmcia_replace_cis(s->parent, &buf.cisdump); break; case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1045,7 +1058,11 @@ static int ds_ioctl(struct inode * inode, struct file * file, } } - if (cmd & IOC_OUT) __copy_to_user(uarg, (char *)&buf, size); + if (cmd & IOC_OUT) { + if (__copy_to_user(uarg, (char *)&buf, size)) + err = -EFAULT; + } + return err; } /* ds_ioctl */ @@ -1080,8 +1097,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) * Ugly. But we want to wait for the socket threads to have started up. * We really should let the drivers themselves drive some of this.. */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/4); + msleep(250); init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); @@ -1244,3 +1260,5 @@ static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) return cmp.drv; return NULL; } + +MODULE_ALIAS("ds"); diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c index fd08c3a5b..875c9cfae 100644 --- a/drivers/pcmcia/hd64465_ss.c +++ b/drivers/pcmcia/hd64465_ss.c @@ -636,19 +636,17 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); struct pccard_mem_map *smem; int map = mem->map; - unsigned long paddr, size; + unsigned long paddr; #if 0 - DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n", - sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start); + DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n", + sock, map, mem->flags, mem->card_start); #endif if (map >= MAX_WIN) return -EINVAL; smem = &sp->mem_maps[map]; - size = mem->sys_stop - mem->sys_start + 1; - paddr = sp->mem_base; /* base of Attribute mapping */ if (!(mem->flags & MAP_ATTRIB)) paddr += HD64465_PCC_WINDOW; /* base of Common mapping */ @@ -660,8 +658,7 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) * queries our fixed mapping. I wish this fact had been * documented - Greg Banks. */ - mem->sys_start = paddr; - mem->sys_stop = paddr + size - 1; + mem->static_start = paddr; *smem = *mem; diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 3115eb3bc..eb255238a 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -422,7 +422,7 @@ static int i82092aa_init(struct pcmcia_socket *sock) int i; struct resource res = { .start = 0, .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, }; + pccard_mem_map mem = { .res = &res, }; enter("i82092aa_init"); @@ -706,11 +706,15 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) { - unsigned int sock = container_of(socket, struct socket_info, socket)->number; + struct socket_info *sock_info = container_of(socket, struct socket_info, socket); + unsigned int sock = sock_info->number; + struct pci_bus_region region; unsigned short base, i; unsigned char map; enter("i82092aa_set_mem_map"); + + pcibios_resource_to_bus(sock_info->dev, ®ion, mem->res); map = mem->map; if (map > 4) { @@ -719,10 +723,10 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_ } - if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) || + if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) || (mem->speed > 1000) ) { leave("i82092aa_set_mem_map: invalid address / speed"); - 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); + printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,region.start, region.end, mem->card_start); return -EINVAL; } @@ -731,11 +735,11 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_ indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); -/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE); */ +/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE); */ /* write the start address */ base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (region.start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) @@ -744,7 +748,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_ /* write the stop address */ - i= (mem->sys_stop >> 12) & 0x0fff; + i= (region.end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; @@ -763,7 +767,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_ /* card start */ - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - region.start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) { diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index b753c3186..56ced25d9 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -48,9 +48,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -134,7 +134,7 @@ module_param(i365_base, int, 0444); module_param(ignore, int, 0444); module_param(extra_sockets, int, 0444); module_param(irq_mask, int, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(cs_irq, int, 0444); module_param(async_clock, int, 0444); module_param(cable_mode, int, 0444); @@ -513,8 +513,7 @@ static u_int __init test_irq(u_short sock, int irq) if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0) return 1; irq_hits = 0; irq_sock = sock; - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); if (irq_hits) { free_irq(irq, i365_count_irq); debug(2, " spurious hit!\n"); @@ -1159,13 +1158,13 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5" "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed, - mem->sys_start, mem->sys_stop, mem->card_start); + mem->res->start, mem->res->end, mem->card_start); map = mem->map; if ((map > 4) || (mem->card_start > 0x3ffffff) || - (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) + (mem->res->start > mem->res->end) || (mem->speed > 1000)) return -EINVAL; - if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)) + if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff)) return -EINVAL; /* Turn off the window before changing anything */ @@ -1173,12 +1172,12 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map)); base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (mem->res->start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) i |= I365_MEM_0WS; i365_set_pair(sock, base+I365_W_START, i); - i = (mem->sys_stop >> 12) & 0x0fff; + i = (mem->res->end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; case 1: i |= I365_MEM_WS0; break; @@ -1187,7 +1186,7 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) } i365_set_pair(sock, base+I365_W_STOP, i); - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG; i365_set_pair(sock, base+I365_W_OFF, i); @@ -1309,7 +1308,7 @@ static int pcic_init(struct pcmcia_socket *s) int i; struct resource res = { .start = 0, .end = 0x1000 }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, }; + pccard_mem_map mem = { .res = &res, }; for (i = 0; i < 2; i++) { io.map = i; diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index adbe8a724..b1f6e3d9e 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -129,9 +129,24 @@ static int o2micro_override(struct yenta_socket *socket) * ok to write to both registers on all O2 bridges. * from Eric Still, 02Micro. */ + u8 a, b; + if (PCI_FUNC(socket->dev->devfn) == 0) { - config_writeb(socket, 0x94, 0xCA); - config_writeb(socket, 0xD4, 0xCA); + a = config_readb(socket, 0x94); + b = config_readb(socket, 0xD4); + + printk(KERN_INFO "Yenta O2: res at 0x94/0xD4: %02x/%02x\n", a, b); + + switch (socket->dev->device) { + case PCI_DEVICE_ID_O2_6832: + printk(KERN_INFO "Yenta O2: old bridge, not enabling read prefetch / write burst\n"); + break; + + default: + printk(KERN_INFO "Yenta O2: enabling read prefetch/write burst\n"); + config_writeb(socket, 0x94, a | 0x0a); + config_writeb(socket, 0xD4, b | 0x0a); + } } return 0; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 57b1bca00..4f00c9dda 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -502,10 +502,10 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map return -EINVAL; } - if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) { + if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { printk("pd6729_set_mem_map: invalid address / speed"); /* 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); */ + sock, mem->res->start, mem->res->end, mem->card_start); */ return -EINVAL; } @@ -515,7 +515,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map /* write the start address */ base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (mem->res->start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) @@ -524,7 +524,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map /* write the stop address */ - i= (mem->sys_stop >> 12) & 0x0fff; + i= (mem->res->end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; @@ -543,11 +543,11 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map /* Take care of high byte */ indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); - indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24); + indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24); /* card start */ - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) { @@ -577,7 +577,7 @@ static int pd6729_init(struct pcmcia_socket *sock) int i; struct resource res = { .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff }; + pccard_mem_map mem = { .res = &res, }; pd6729_set_socket(sock, &dead_socket); for (i = 0; i < 2; i++) { diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 491d11bc8..a6936a75a 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -178,39 +179,6 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev) first = ops->first; nr = ops->nr; - /* Setup GPIOs for PCMCIA/CF alternate function mode. - * - * It would be nice if set_GPIO_mode included support - * for driving GPIO outputs to default high/low state - * before programming GPIOs as outputs. Setting GPIO - * outputs to default high/low state via GPSR/GPCR - * before defining them as outputs should reduce - * the possibility of glitching outputs during GPIO - * setup. This of course assumes external terminators - * are present to hold GPIOs in a defined state. - * - * In the meantime, setup default state of GPIO - * outputs before we enable them as outputs. - */ - - GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | - GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | - GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - pxa_gpio_mode(GPIO48_nPOE_MD); - pxa_gpio_mode(GPIO49_nPWE_MD); - pxa_gpio_mode(GPIO50_nPIOR_MD); - pxa_gpio_mode(GPIO51_nPIOW_MD); - pxa_gpio_mode(GPIO52_nPCE_1_MD); - pxa_gpio_mode(GPIO53_nPCE_2_MD); - pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */ - pxa_gpio_mode(GPIO55_nPREG_MD); - pxa_gpio_mode(GPIO56_nPWAIT_MD); - pxa_gpio_mode(GPIO57_nIOIS16_MD); - /* Provide our PXA2xx specific timing routines. */ ops->set_timing = pxa2xx_pcmcia_set_timing; #ifdef CONFIG_CPU_FREQ @@ -249,7 +217,13 @@ static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level) { int ret = 0; if (level == RESUME_RESTORE_STATE) + { + struct pcmcia_low_level *ops = dev->platform_data; + int nr = ops ? ops->nr : 0; + + MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); ret = pcmcia_socket_dev_resume(dev); + } return ret; } diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index e22a57a4a..fd1f691c7 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c @@ -25,10 +25,40 @@ #include #include #include +#include #include #include "sa1111_generic.h" +static int +lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + /* + * Setup default state of GPIO outputs + * before we enable them as outputs. + */ + GPSR(GPIO48_nPOE) = + GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | + GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | + GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + + return sa1111_pcmcia_hw_init(skt); +} + static int lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) @@ -201,7 +231,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static struct pcmcia_low_level lubbock_pcmcia_ops = { .owner = THIS_MODULE, - .hw_init = sa1111_pcmcia_hw_init, + .hw_init = lubbock_pcmcia_hw_init, .hw_shutdown = sa1111_pcmcia_hw_shutdown, .socket_state = sa1111_pcmcia_socket_state, .configure_socket = lubbock_pcmcia_configure_socket, @@ -235,3 +265,5 @@ int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) return ret; } + +MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index fe62a597d..5309734e1 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "soc_common.h" @@ -38,6 +39,29 @@ static struct pcmcia_irqs irqs[] = { static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { + /* + * Setup default state of GPIO outputs + * before we enable them as outputs. + */ + GPSR(GPIO48_nPOE) = + GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | + GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | + GPIO_bit(GPIO85_nPCE_1) | + GPIO_bit(GPIO54_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO85_nPCE_1_MD); + pxa_gpio_mode(GPIO54_nPCE_2_MD); + pxa_gpio_mode(GPIO79_pSKTSEL_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ; return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 6869e209d..4e0ca166d 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -88,6 +88,9 @@ static resource_map_t io_db = { }; static DECLARE_MUTEX(rsrc_sem); +static unsigned int rsrc_mem_probe; +#define MEM_PROBE_LOW (1 << 0) +#define MEM_PROBE_HIGH (1 << 1) #ifdef CONFIG_PCMCIA_PROBE @@ -301,19 +304,15 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in { int ret = -1; - s->cis_mem.sys_start = res->start; - s->cis_mem.sys_stop = res->end; s->cis_mem.res = res; s->cis_virt = ioremap(res->start, s->map_size); if (s->cis_virt) { - ret = pcmcia_validate_cis(s->clients, info); + ret = pccard_validate_cis(s, BIND_FN_ALL, info); /* invalidate mapping and CIS cache */ iounmap(s->cis_virt); s->cis_virt = NULL; destroy_cis_cache(s); } - s->cis_mem.sys_start = 0; - s->cis_mem.sys_stop = 0; s->cis_mem.res = NULL; if ((ret != 0) || (info->Chains == 0)) return 0; @@ -325,15 +324,13 @@ static int checksum(struct pcmcia_socket *s, struct resource *res) { pccard_mem_map map; int i, a = 0, b = -1, d; - void *virt; + void __iomem *virt; virt = ioremap(res->start, s->map_size); if (virt) { map.map = 0; map.flags = MAP_ACTIVE; map.speed = 0; - map.sys_start = res->start; - map.sys_stop = res->end; map.res = res; map.card_start = 0; s->ops->set_mem_map(s, &map); @@ -457,24 +454,21 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) return do_mem_probe(m->base, m->num, s); } -static void validate_mem(struct pcmcia_socket *s) +static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) { resource_map_t *m, mm; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; - static int hi = 0, lo = 0; u_long b, i, ok = 0; - int force_low = !(s->features & SS_CAP_PAGE_REGS); - down(&rsrc_sem); /* We do up to four passes through the list */ - if (!force_low) { - if (hi++ || (inv_probe(mem_db.next, s) > 0)) - goto out; + if (probe_mask & MEM_PROBE_HIGH) { + if (inv_probe(mem_db.next, s) > 0) + return; printk(KERN_NOTICE "cs: warning: no high memory space " "available!\n"); } - if (lo++) - goto out; + if ((probe_mask & MEM_PROBE_LOW) == 0) + return; for (m = mem_db.next; m != &mem_db; m = mm.next) { mm = *m; /* Only probe < 1 MB */ @@ -494,38 +488,51 @@ static void validate_mem(struct pcmcia_socket *s) } } } - out: - up(&rsrc_sem); } #else /* CONFIG_PCMCIA_PROBE */ -static void validate_mem(struct pcmcia_socket *s) +static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) { - resource_map_t *m, mm; - static int done = 0; + resource_map_t *m, mm; - if (done++ == 0) { - down(&rsrc_sem); for (m = mem_db.next; m != &mem_db; m = mm.next) { - mm = *m; - if (do_mem_probe(mm.base, mm.num, s)) - break; + mm = *m; + if (do_mem_probe(mm.base, mm.num, s)) + break; } - up(&rsrc_sem); - } } #endif /* CONFIG_PCMCIA_PROBE */ +/* + * Locking note: this is the only place where we take + * both rsrc_sem and skt_sem. + */ void pcmcia_validate_mem(struct pcmcia_socket *s) { - down(&s->skt_sem); + if (probe_mem) { + unsigned int probe_mask; + + down(&rsrc_sem); + + probe_mask = MEM_PROBE_LOW; + if (s->features & SS_CAP_PAGE_REGS) + probe_mask = MEM_PROBE_HIGH; + + if (probe_mask & ~rsrc_mem_probe) { + rsrc_mem_probe |= probe_mask; + + down(&s->skt_sem); - if (probe_mem && s->state & SOCKET_PRESENT) - validate_mem(s); + if (s->state & SOCKET_PRESENT) + validate_mem(s, probe_mask); - up(&s->skt_sem); + up(&s->skt_sem); + } + + up(&rsrc_sem); + } } EXPORT_SYMBOL(pcmcia_validate_mem); @@ -966,11 +973,8 @@ static int adjust_irq(adjust_t *adj) /*====================================================================*/ -int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj) +int pcmcia_adjust_resource_info(adjust_t *adj) { - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - switch (adj->Resource) { case RES_MEMORY_RANGE: return adjust_memory(adj); @@ -984,6 +988,7 @@ int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj) } return CS_UNSUPPORTED_FUNCTION; } +EXPORT_SYMBOL(pcmcia_adjust_resource_info); /*====================================================================*/ diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 0efa9c6e7..874990ebe 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -48,36 +48,15 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = { #ifdef CONFIG_SA1100_CERF pcmcia_cerf_init, #endif -#ifdef CONFIG_SA1100_FLEXANET - pcmcia_flexanet_init, -#endif -#ifdef CONFIG_SA1100_FREEBIRD - pcmcia_freebird_init, -#endif -#ifdef CONFIG_SA1100_GRAPHICSCLIENT - pcmcia_gcplus_init, -#endif #ifdef CONFIG_SA1100_H3600 pcmcia_h3600_init, #endif -#ifdef CONFIG_SA1100_PANGOLIN - pcmcia_pangolin_init, -#endif #ifdef CONFIG_SA1100_SHANNON pcmcia_shannon_init, #endif #ifdef CONFIG_SA1100_SIMPAD pcmcia_simpad_init, #endif -#ifdef CONFIG_SA1100_STORK - pcmcia_stork_init, -#endif -#ifdef CONFIG_SA1100_TRIZEPS - pcmcia_trizeps_init, -#endif -#ifdef CONFIG_SA1100_YOPY - pcmcia_yopy_init, -#endif }; static int sa11x0_drv_pcmcia_probe(struct device *dev) diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index e442953b3..64fd5e37f 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -96,8 +97,7 @@ static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) set_h3600_egpio(IPAQ_EGPIO_OPT_ON); clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10*HZ / 1000); + msleep(10); soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); } diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c index 3f083e8fa..c2ecf1185 100644 --- a/drivers/pcmcia/sa1100_simpad.c +++ b/drivers/pcmcia/sa1100_simpad.c @@ -48,7 +48,7 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { unsigned long levels = GPLR; - unsigned long *cs3reg = CS3_BASE; + long cs3reg = get_cs3_shadow(); state->detect=((levels & GPIO_CF_CD)==0)?1:0; state->ready=(levels & GPIO_CF_IRQ)?1:0; @@ -56,7 +56,7 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt, state->bvd2=1; /* Not available on Simpad. */ state->wrprot=0; /* Not available on Simpad. */ - if((*cs3reg & 0x0c) == 0x0c) { + if((cs3reg & 0x0c) == 0x0c) { state->vs_3v=0; state->vs_Xv=0; } else { diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index c8e0551cd..bd9d6b2fa 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -136,15 +136,9 @@ static int pcmcia_probe(struct sa1111_dev *dev) sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR); sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR); -#ifdef CONFIG_SA1100_ADSBITSY - pcmcia_adsbitsy_init(&dev->dev); -#endif #ifdef CONFIG_SA1100_BADGE4 pcmcia_badge4_init(&dev->dev); #endif -#ifdef CONFIG_SA1100_GRAPHICSMASTER - pcmcia_graphicsmaster_init(&dev->dev); -#endif #ifdef CONFIG_SA1100_JORNADA720 pcmcia_jornada720_init(&dev->dev); #endif @@ -153,15 +147,6 @@ static int pcmcia_probe(struct sa1111_dev *dev) #endif #ifdef CONFIG_ASSABET_NEPONSET pcmcia_neponset_init(dev); -#endif -#ifdef CONFIG_SA1100_PFS168 - pcmcia_pfs_init(&dev->dev); -#endif -#ifdef CONFIG_SA1100_PT_SYSTEM3 - pcmcia_system3_init(&dev->dev); -#endif -#ifdef CONFIG_SA1100_XP860 - pcmcia_xp860_init(&dev->dev); #endif return 0; } diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 6d393e739..a45fee3f4 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -49,6 +49,11 @@ #include "soc_common.h" +/* FIXME: platform dependent resource declaration has to move out of this file */ +#ifdef CONFIG_ARCH_PXA +#include +#endif + #ifdef DEBUG static int pc_debug; @@ -448,9 +453,7 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map skt->ops->set_timing(skt); - map->sys_stop -= map->sys_start; - map->sys_stop += res->start + map->card_start; - map->sys_start = res->start + map->card_start; + map->static_start = res->start + map->card_start; return 0; } @@ -662,6 +665,7 @@ static void soc_pcmcia_cpufreq_unregister(void) int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { struct skt_dev_info *sinfo; + struct soc_pcmcia_socket *skt; int ret, i; down(&soc_pcmcia_sockets_lock); @@ -679,7 +683,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops * Initialise the per-socket structure. */ for (i = 0; i < nr; i++) { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; + skt = &sinfo->skt[i]; skt->socket.ops = &soc_common_pcmcia_operations; skt->socket.owner = ops->owner; @@ -777,7 +781,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops goto out; do { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; + skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index f3b38e96d..a651309eb 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -45,9 +45,9 @@ #include #include #include +#include #include -#include #include #include @@ -109,7 +109,7 @@ module_param(tcic_base, int, 0444); module_param(ignore, int, 0444); module_param(do_scan, int, 0444); module_param(irq_mask, int, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(cs_irq, int, 0444); module_param(poll_interval, int, 0444); module_param(poll_quick, int, 0444); @@ -829,15 +829,15 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, " "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags, - mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); + mem->speed, mem->res->start, mem->res->end, mem->card_start); if ((mem->map > 3) || (mem->card_start > 0x3ffffff) || - (mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) || - (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) + (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) || + (mem->res->start > mem->res->end) || (mem->speed > 1000)) return -EINVAL; tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); addr = TCIC_MWIN(psock, mem->map); - base = mem->sys_start; len = mem->sys_stop - mem->sys_start; + base = mem->res->start; len = mem->res->end - mem->res->start; if ((len & (len+1)) || (base & len)) return -EINVAL; if (len == 0x0fff) base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT; @@ -846,7 +846,7 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X); tcic_setw(TCIC_DATA, base); - mmap = mem->card_start - mem->sys_start; + mmap = mem->card_start - mem->res->start; mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK; if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG; tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X); @@ -870,7 +870,7 @@ static int tcic_init(struct pcmcia_socket *s) int i; struct resource res = { .start = 0, .end = 0x1000 }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, }; + pccard_mem_map mem = { .res = &res, }; for (i = 0; i < 2; i++) { io.map = i; diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 4c8a7a572..4b8b822bc 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -343,14 +343,17 @@ static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + struct pci_bus_region region; int map; unsigned char addr, enable; unsigned int start, stop, card_start; unsigned short word; + pcibios_resource_to_bus(socket->dev, ®ion, mem->res); + map = mem->map; - start = mem->sys_start; - stop = mem->sys_stop; + start = region.start; + stop = region.end; card_start = mem->card_start; if (map > 4 || start > stop || ((start ^ stop) >> 24) || @@ -447,7 +450,7 @@ static void yenta_clear_maps(struct yenta_socket *socket) int i; struct resource res = { .start = 0, .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, }; + pccard_mem_map mem = { .res = &res, }; yenta_set_socket(&socket->socket, &dead_socket); for (i = 0; i < 2; i++) { @@ -650,6 +653,7 @@ static void yenta_close(struct pci_dev *dev) yenta_free_resources(sock); pci_release_regions(dev); + pci_disable_device(dev); pci_set_drvdata(dev, NULL); } @@ -685,7 +689,7 @@ enum { * Different cardbus controllers have slightly different * initialization sequences etc details. List them here.. */ -struct cardbus_type cardbus_type[] = { +static struct cardbus_type cardbus_type[] = { [CARDBUS_TYPE_TI] = { .override = ti_override, .save_state = ti_save_state, @@ -824,8 +828,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); /* disable interrupts */ cb_writel(socket, CB_SOCKET_MASK, 0); @@ -1020,10 +1023,16 @@ static int yenta_dev_suspend (struct pci_dev *dev, u32 state) socket->type->save_state(socket); /* FIXME: pci_save_state needs to have a better interface */ - pci_save_state(dev, socket->saved_state); - pci_read_config_dword(dev, 16*4, &socket->saved_state[16]); - pci_read_config_dword(dev, 17*4, &socket->saved_state[17]); - pci_set_power_state(dev, 3); + pci_save_state(dev); + pci_read_config_dword(dev, 16*4, &socket->saved_state[0]); + pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); + + /* + * Some laptops (IBM T22) do not like us putting the Cardbus + * bridge into D3. At a guess, some other laptop will + * probably require this, so leave it commented out for now. + */ + /* pci_set_power_state(dev, 3); */ } return ret; @@ -1037,9 +1046,9 @@ static int yenta_dev_resume (struct pci_dev *dev) if (socket) { pci_set_power_state(dev, 0); /* FIXME: pci_restore_state needs to have a better interface */ - pci_restore_state(dev, socket->saved_state); - pci_write_config_dword(dev, 16*4, socket->saved_state[16]); - pci_write_config_dword(dev, 17*4, socket->saved_state[17]); + pci_restore_state(dev); + pci_write_config_dword(dev, 16*4, socket->saved_state[0]); + pci_write_config_dword(dev, 17*4, socket->saved_state[1]); if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); @@ -1088,6 +1097,7 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h index 7c3bfbfaa..4e637eef2 100644 --- a/drivers/pcmcia/yenta_socket.h +++ b/drivers/pcmcia/yenta_socket.h @@ -107,7 +107,7 @@ struct cardbus_type { struct yenta_socket { struct pci_dev *dev; int cb_irq, io_irq; - void *base; + void __iomem *base; struct timer_list poll_timer; struct pcmcia_socket socket; @@ -120,7 +120,7 @@ struct yenta_socket { unsigned int private[8]; /* PCI saved state */ - u32 saved_state[18]; + u32 saved_state[2]; }; diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig index 7e227ec42..6776308a1 100644 --- a/drivers/pnp/Kconfig +++ b/drivers/pnp/Kconfig @@ -6,7 +6,7 @@ menu "Plug and Play support" config PNP bool "Plug and Play support" - depends on ISA + depends on ISA || ACPI_BUS ---help--- Plug and Play (PnP) is a standard for peripherals which allows those peripherals to be configured by software, e.g. assign IRQ's or other @@ -35,5 +35,7 @@ source "drivers/pnp/isapnp/Kconfig" source "drivers/pnp/pnpbios/Kconfig" +source "drivers/pnp/pnpacpi/Kconfig" + endmenu diff --git a/drivers/pnp/Makefile b/drivers/pnp/Makefile index a83a4fb54..a381a92fd 100644 --- a/drivers/pnp/Makefile +++ b/drivers/pnp/Makefile @@ -4,5 +4,6 @@ obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o system.o +obj-$(CONFIG_PNPACPI) += pnpacpi/ obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 781a4c064..8527ae626 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -60,8 +60,8 @@ static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq int first = 1, i; pnp_printf(buffer, "%sirq ", space); - for (i = 0; i < 16; i++) - if (irq->map & (1<map)) { if (!first) { pnp_printf(buffer, ","); } else { @@ -72,7 +72,7 @@ static void pnp_print_irq(pnp_info_buffer_t *buffer, char *space, struct pnp_irq else pnp_printf(buffer, "%i", i); } - if (!irq->map) + if (bitmap_empty(irq->map, PNP_IRQ_NR)) pnp_printf(buffer, ""); if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) pnp_printf(buffer, " High-Edge"); @@ -240,12 +240,14 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) { struct pnp_dev *dev = to_pnp_dev(dmdev); int i, ret; - pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) - pnp_alloc(sizeof(pnp_info_buffer_t)); - if (!buffer) - return -ENOMEM; + pnp_info_buffer_t *buffer; + if (!dev) return -EINVAL; + + buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); + if (!buffer) + return -ENOMEM; buffer->len = PAGE_SIZE; buffer->buffer = buf; buffer->curr = buffer->buffer; diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig index 50cc7796f..578651eeb 100644 --- a/drivers/pnp/isapnp/Kconfig +++ b/drivers/pnp/isapnp/Kconfig @@ -3,7 +3,7 @@ # config ISAPNP bool "ISA Plug and Play support" - depends on PNP + depends on PNP && ISA help Say Y here if you would like support for ISA Plug and Play devices. Some information is in . diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index ee6d1ed50..9df2b43db 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -477,12 +477,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, { unsigned char tmp[3]; struct pnp_irq *irq; + unsigned long bits; isapnp_peek(tmp, size); irq = isapnp_alloc(sizeof(struct pnp_irq)); if (!irq) return; - irq->map = (tmp[1] << 8) | tmp[0]; + bits = (tmp[1] << 8) | tmp[0]; + bitmap_copy(irq->map, &bits, 16); if (size > 2) irq->flags = tmp[2]; else @@ -655,8 +657,10 @@ static int __init isapnp_create_device(struct pnp_card *card, if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; option = pnp_register_independent_option(dev); - if (!option) + if (!option) { + kfree(dev); return 1; + } pnp_add_card_device(card,dev); while (1) { diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index b31a33a87..0cbdf9d41 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -150,13 +150,19 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) *flags |= rule->flags | IORESOURCE_IRQ; *flags &= ~IORESOURCE_UNSET; - if (!rule->map) { + if (bitmap_empty(rule->map, PNP_IRQ_NR)) { *flags |= IORESOURCE_DISABLED; return 1; /* skip disabled resource requests */ } + /* TBD: need check for >16 IRQ */ + *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); + if (*start < PNP_IRQ_NR) { + *end = *start; + return 1; + } for (i = 0; i < 16; i++) { - if(rule->map & (1<map)) { *start = *end = xtab[i]; if(pnp_check_irq(dev, idx)) return 1; diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig index ff17c7e96..fbb9f1611 100644 --- a/drivers/pnp/pnpbios/Kconfig +++ b/drivers/pnp/pnpbios/Kconfig @@ -3,7 +3,8 @@ # config PNPBIOS bool "Plug and Play BIOS support (EXPERIMENTAL)" - depends on PNP && X86 && EXPERIMENTAL + depends on PNP && ISA && X86 && EXPERIMENTAL + default n ---help--- Linux uses the PNPBIOS as defined in "Plug and Play BIOS Specification Version 1.0A May 5, 1994" to autodetect built-in diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index c224f74fa..6b7583f49 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -69,14 +69,14 @@ __asm__( #define Q_SET_SEL(cpu, selname, address, size) \ do { \ -set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \ -set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \ +set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \ +set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ } while(0) #define Q2_SET_SEL(cpu, selname, address, size) \ do { \ -set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \ -set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \ +set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \ +set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ } while(0) static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; @@ -115,8 +115,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, return PNP_FUNCTION_NOT_SUPPORTED; cpu = get_cpu(); - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; + save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8]; + per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc; /* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave(&pnp_bios_lock, flags); @@ -158,14 +158,14 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, ); spin_unlock_irqrestore(&pnp_bios_lock, flags); - cpu_gdt_table[cpu][0x40 / 8] = save_desc_40; + per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40; put_cpu(); /* If we get here and this is set then the PnP BIOS faulted on us. */ if(pnp_bios_is_utter_crap) { printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n"); - printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n"); + printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n"); printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n"); } diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 6c9866346..c4220a6ff 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -56,10 +56,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include @@ -177,8 +178,7 @@ static int pnp_dock_thread(void * unused) /* * Poll every 2 seconds */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ*2); + msleep_interruptible(2000); if(signal_pending(current)) break; @@ -252,8 +252,10 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -1; - if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) + if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { + kfree(node); return -ENODEV; + } if(pnpbios_write_resources_to_node(res, node)<0) { kfree(node); return -1; @@ -536,6 +538,14 @@ int __init pnpbios_init(void) return -ENODEV; } +#ifdef CONFIG_ACPI + if (!acpi_disabled) { + pnpbios_disabled = 1; + printk(KERN_INFO "PnPBIOS: Disabled by ACPI\n"); + return -ENODEV; + } +#endif /* CONFIG_ACPI */ + /* scan the system for pnpbios support */ if (!pnpbios_probe_system()) return -ENODEV; @@ -572,6 +582,8 @@ subsys_initcall(pnpbios_init); static int __init pnpbios_thread_init(void) { + if (pnpbios_disabled) + return 0; #ifdef CONFIG_HOTPLUG init_completion(&unload_sem); if (kernel_thread(pnp_dock_thread, NULL, CLONE_KERNEL) > 0) diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index 88fcd1668..2fa4d21c7 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c @@ -90,8 +90,10 @@ static int proc_read_escd(char *buf, char **start, off_t pos, tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL); if (!tmpbuf) return -ENOMEM; - if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) + if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) { + kfree(tmpbuf); return -EIO; + } escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256; @@ -168,8 +170,10 @@ static int proc_read_node(char *buf, char **start, off_t pos, node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); if (!node) return -ENOMEM; - if (pnp_bios_get_dev_node(&nodenum, boot, node)) + if (pnp_bios_get_dev_node(&nodenum, boot, node)) { + kfree(node); return -EIO; + } len = node->size - sizeof(struct pnp_bios_node); memcpy(buf, node->data, len); kfree(node); diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index f990065e1..3c7f9772f 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "pnpbios.h" @@ -58,6 +59,7 @@ pnpbios_parse_allocated_irqresource(struct pnp_resource_table * res, int irq) } res->irq_resource[i].start = res->irq_resource[i].end = (unsigned long) irq; + pcibios_penalize_isa_irq(irq); } } @@ -285,10 +287,13 @@ static void pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option) { struct pnp_irq * irq; + unsigned long bits; + irq = pnpbios_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL); if (!irq) return; - irq->map = (p[2] << 8) | p[1]; + bits = (p[2] << 8) | p[1]; + bitmap_copy(irq->map, &bits, 16); if (size > 2) irq->flags = p[3]; else @@ -346,12 +351,12 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc { unsigned int len, tag; int priority = 0; - struct pnp_option *option; + struct pnp_option *option, *option_independent; if (!p) return NULL; - option = pnp_register_independent_option(dev); + option_independent = option = pnp_register_independent_option(dev); if (!option) return NULL; @@ -428,9 +433,14 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc case SMALL_TAG_ENDDEP: if (len != 0) goto len_err; + if (option_independent == option) + printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); + option = option_independent; break; case SMALL_TAG_END: + if (option_independent != option) + printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_ENDDEP tag\n"); p = p + 2; return (unsigned char *)p; break; diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 74eecb245..596a02d7e 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -63,14 +63,17 @@ static void quirk_awe32_resources(struct pnp_dev *dev) static void quirk_cmi8330_resources(struct pnp_dev *dev) { struct pnp_option *res = dev->dependent; + unsigned long tmp; for ( ; res ; res = res->next ) { struct pnp_irq *irq; struct pnp_dma *dma; - for( irq = res->irq; irq; irq = irq->next ) // Valid irqs are 5, 7, 10 - irq->map = 0x04A0; // 0000 0100 1010 0000 + for( irq = res->irq; irq; irq = irq->next ) { // Valid irqs are 5, 7, 10 + tmp = 0x04A0; + bitmap_copy(irq->map, &tmp, 16); // 0000 0100 1010 0000 + } for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3 if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT ) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 3fc9f6c6f..80a6979ef 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -101,8 +101,8 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { int i; - for (i=0; i<16; i++) - if (data->map & (1<map)) pcibios_penalize_isa_irq(i); } #endif @@ -421,6 +421,7 @@ int pnp_check_irq(struct pnp_dev * dev, int idx) int pnp_check_dma(struct pnp_dev * dev, int idx) { +#ifndef CONFIG_IA64 int tmp; struct pnp_dev *tdev; unsigned long * dma = &dev->res.dma_resource[idx].start; @@ -470,6 +471,10 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) } return 1; +#else + /* IA64 hasn't legacy DMA */ + return 0; +#endif } diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index da52c86dc..d42015c38 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -104,4 +104,8 @@ static int __init pnp_system_init(void) return pnp_register_driver(&system_pnp_driver); } -subsys_initcall(pnp_system_init); +/** + * Reserve motherboard resources after PCI claim BARs, + * but before PCI assign resources for uninitialized PCI devices + */ +fs_initcall(pnp_system_init); diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index e190f21ed..38f2f6b37 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig @@ -51,6 +51,8 @@ config UNIX98_PTY_COUNT When not in use, each additional set of 256 PTYs occupy approximately 8 KB of kernel memory on 32-bit architectures. +source "drivers/char/watchdog/Kconfig" + comment "S/390 character device drivers" config TN3270 @@ -174,6 +176,23 @@ config S390_TAPE_34XX tape subsystems and 100% compatibles. It is safe to say "Y" here. + + +config VMLOGRDR + tristate "Support for the z/VM recording system services (VM only)" + depends on IUCV + help + Select this option if you want to be able to receive records collected + by the z/VM recording system services, eg. from *LOGREC, *ACCOUNT or + *SYMPTOM. + This driver depends on the IUCV support driver. + +config MONREADER + tristate "API for reading z/VM monitor service records" + depends on IUCV + help + Character device driver for reading z/VM monitor service records + endmenu menu "Cryptographic devices" diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 2249b7848..be8ce08e5 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.147 $ + * $Revision: 1.151 $ */ #include @@ -1103,13 +1103,16 @@ static void dasd_end_request_cb(struct dasd_ccw_req * cqr, void *data) { struct request *req; + struct dasd_device *device; + int status; req = (struct request *) data; - dasd_profile_end(cqr->device, cqr, req); - spin_lock_irq(&cqr->device->request_queue_lock); - dasd_end_request(req, (cqr->status == DASD_CQR_DONE)); - spin_unlock_irq(&cqr->device->request_queue_lock); - dasd_sfree_request(cqr, cqr->device); + device = cqr->device; + dasd_profile_end(device, cqr, req); + status = cqr->device->discipline->free_cp(cqr,req); + spin_lock_irq(&device->request_queue_lock); + dasd_end_request(req, status); + spin_unlock_irq(&device->request_queue_lock); } @@ -1595,8 +1598,8 @@ dasd_alloc_queue(struct dasd_device * device) device->request_queue->queuedata = device; #if 0 - elevator_exit(device->request_queue); - rc = elevator_init(device->request_queue, &elevator_noop); + elevator_exit(device->request_queue->elevator); + rc = elevator_init(device->request_queue, "noop"); if (rc) { blk_cleanup_queue(device->request_queue); return rc; @@ -1906,8 +1909,10 @@ dasd_generic_notify(struct ccw_device *cdev, int event) dasd_schedule_bh(device); } else { list_for_each_entry(cqr, &device->ccw_queue, list) - if (cqr->status == DASD_CQR_IN_IO) + if (cqr->status == DASD_CQR_IN_IO) { cqr->status = DASD_CQR_QUEUED; + cqr->retries++; + } device->stopped |= DASD_STOPPED_DC_WAIT; dasd_set_timer(device, 0); } diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 680f2e4d9..6a39ead68 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -5,7 +5,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.33 $ + * $Revision: 1.34 $ */ #include @@ -461,6 +461,12 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) dasd_3990_erp_block_queue(erp, 30*HZ); + } else if (sense[25] == 0x1E) { /* busy */ + DEV_MESSAGE(KERN_INFO, device, + "busy - redriving request later, " + "%d retries left", + erp->retries); + dasd_3990_erp_block_queue(erp, HZ); } else { /* no state change pending - retry */ @@ -1304,8 +1310,8 @@ dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) "fetch mode active"); /* not possible to handle this situation in Linux */ - panic("No way to inform appliction about the possibly " - "incorret data"); + panic("No way to inform application about the possibly " + "incorrect data"); } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { @@ -2203,6 +2209,13 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) erp = dasd_3990_erp_action_4(erp, sense); break; + case 0x1E: /* busy */ + DEV_MESSAGE(KERN_DEBUG, device, "%s", + "Busy condition exists " + "for the subsystem or device"); + erp = dasd_3990_erp_action_4(erp, sense); + break; + default: /* all others errors - default erp */ break; } diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 812bb0066..4a1a4ed6e 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -11,7 +11,7 @@ * functions may not be called from interrupt context. In particular * dasd_get_device is a no-no from interrupt context. * - * $Revision: 1.30 $ + * $Revision: 1.34 $ */ #include @@ -26,6 +26,9 @@ #include "dasd_int.h" +kmem_cache_t *dasd_page_cache; +EXPORT_SYMBOL(dasd_page_cache); + /* * dasd_devmap_t is used to store the features and the relation * between device number and device index. To find a dasd_devmap_t @@ -204,94 +207,144 @@ dasd_feature_list(char *str, char **endp) } /* - * Read comma separated list of dasd ranges. + * Try to match the first element on the comma separated parse string + * with one of the known keywords. If a keyword is found, take the approprate + * action and return a pointer to the residual string. If the first element + * could not be matched to any keyword then return an error code. */ -static inline int -dasd_ranges_list(char *str) -{ +static char * +dasd_parse_keyword( char *parsestring ) { + + char *nextcomma, *residual_str; + int length; + + nextcomma = strchr(parsestring,','); + if (nextcomma) { + length = nextcomma - parsestring; + residual_str = nextcomma + 1; + } else { + length = strlen(parsestring); + residual_str = parsestring + length; + } + if (strncmp ("autodetect", parsestring, length) == 0) { + dasd_autodetect = 1; + MESSAGE (KERN_INFO, "%s", + "turning to autodetection mode"); + return residual_str; + } + if (strncmp ("probeonly", parsestring, length) == 0) { + dasd_probeonly = 1; + MESSAGE(KERN_INFO, "%s", + "turning to probeonly mode"); + return residual_str; + } + if (strncmp ("fixedbuffers", parsestring, length) == 0) { + if (dasd_page_cache) + return residual_str; + dasd_page_cache = + kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0, + SLAB_CACHE_DMA, NULL, NULL ); + if (!dasd_page_cache) + MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " + "fixed buffer mode disabled."); + else + MESSAGE (KERN_INFO, "%s", + "turning on fixed buffer mode"); + return residual_str; + } + return ERR_PTR(-EINVAL); +} + +/* + * Try to interprete the first element on the comma separated parse string + * as a device number or a range of devices. If the interpretation is + * successfull, create the matching dasd_devmap entries and return a pointer + * to the residual string. + * If interpretation fails or in case of an error, return an error code. + */ +static char * +dasd_parse_range( char *parsestring ) { + struct dasd_devmap *devmap; int from, from_id0, from_id1; int to, to_id0, to_id1; int features, rc; - char bus_id[BUS_ID_SIZE+1], *orig_str; - - orig_str = str; - while (1) { - rc = dasd_busid(&str, &from_id0, &from_id1, &from); - if (rc == 0) { - to = from; - to_id0 = from_id0; - to_id1 = from_id1; - if (*str == '-') { - str++; - rc = dasd_busid(&str, &to_id0, &to_id1, &to); - } + char bus_id[BUS_ID_SIZE+1], *str; + + str = parsestring; + rc = dasd_busid(&str, &from_id0, &from_id1, &from); + if (rc == 0) { + to = from; + to_id0 = from_id0; + to_id1 = from_id1; + if (*str == '-') { + str++; + rc = dasd_busid(&str, &to_id0, &to_id1, &to); } - if (rc == 0 && - (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) - rc = -EINVAL; - if (rc) { - MESSAGE(KERN_ERR, "Invalid device range %s", orig_str); - return rc; - } - features = dasd_feature_list(str, &str); - if (features < 0) - return -EINVAL; - while (from <= to) { - sprintf(bus_id, "%01x.%01x.%04x", - from_id0, from_id1, from++); - devmap = dasd_add_busid(bus_id, features); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); - } - if (*str != ',') - break; - str++; } - if (*str != '\0') { - MESSAGE(KERN_WARNING, - "junk at end of dasd parameter string: %s\n", str); - return -EINVAL; + if (rc == 0 && + (from_id0 != to_id0 || from_id1 != to_id1 || from > to)) + rc = -EINVAL; + if (rc) { + MESSAGE(KERN_ERR, "Invalid device range %s", parsestring); + return ERR_PTR(rc); } - return 0; + features = dasd_feature_list(str, &str); + if (features < 0) + return ERR_PTR(-EINVAL); + while (from <= to) { + sprintf(bus_id, "%01x.%01x.%04x", + from_id0, from_id1, from++); + devmap = dasd_add_busid(bus_id, features); + if (IS_ERR(devmap)) + return (char *)devmap; + } + if (*str == ',') + return str + 1; + if (*str == '\0') + return str; + MESSAGE(KERN_WARNING, + "junk at end of dasd parameter string: %s\n", str); + return ERR_PTR(-EINVAL); } -/* - * Parse a single dasd= parameter. - */ -static int -dasd_parameter(char *str) -{ - if (strcmp ("autodetect", str) == 0) { - dasd_autodetect = 1; - MESSAGE (KERN_INFO, "%s", - "turning to autodetection mode"); - return 0; - } - if (strcmp ("probeonly", str) == 0) { - dasd_probeonly = 1; - MESSAGE(KERN_INFO, "%s", - "turning to probeonly mode"); - return 0; - } - /* turn off autodetect mode and scan for dasd ranges */ - dasd_autodetect = 0; - return dasd_ranges_list(str); +static inline char * +dasd_parse_next_element( char *parsestring ) { + char * residual_str; + residual_str = dasd_parse_keyword(parsestring); + if (!IS_ERR(residual_str)) + return residual_str; + residual_str = dasd_parse_range(parsestring); + return residual_str; } /* - * Parse parameters stored in dasd[] and dasd_disciplines[]. + * Parse parameters stored in dasd[] + * The 'dasd=...' parameter allows to specify a comma separated list of + * keywords and device ranges. When the dasd driver is build into the kernel, + * the complete list will be stored as one element of the dasd[] array. + * When the dasd driver is build as a module, then the list is broken into + * it's elements and each dasd[] entry contains one element. */ int dasd_parse(void) { int rc, i; + char *parsestring; rc = 0; for (i = 0; i < 256; i++) { if (dasd[i] == NULL) break; - rc = dasd_parameter(dasd[i]); + parsestring = dasd[i]; + /* loop over the comma separated list in the parsestring */ + while (*parsestring) { + parsestring = dasd_parse_next_element(parsestring); + if(IS_ERR(parsestring)) { + rc = PTR_ERR(parsestring); + break; + } + } if (rc) { DBF_EVENT(DBF_ALERT, "%s", "invalid range found"); break; diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index cc79775b0..fb81ea495 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.37 $ + * $Revision: 1.39 $ */ #include @@ -304,8 +304,11 @@ dasd_diag_check_device(struct dasd_device *device) (device->bp_block >> 10), (device->blocks << device->s2b_shift) >> 1); rc = 0; - } else + } else { + DEV_MESSAGE(KERN_WARNING, device, "%s", + "volume has incompatible disk layout"); rc = -EMEDIUMTYPE; + } free_page((long) label); return rc; } @@ -410,6 +413,16 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) return cqr; } +static int +dasd_diag_free_cp(struct dasd_ccw_req *cqr, struct request *req) +{ + int status; + + status = cqr->status == DASD_CQR_DONE; + dasd_sfree_request(cqr, cqr->device); + return status; +} + static int dasd_diag_fill_info(struct dasd_device * device, struct dasd_information2_t * info) @@ -472,6 +485,7 @@ struct dasd_discipline dasd_diag_discipline = { .erp_action = dasd_diag_erp_action, .erp_postaction = dasd_diag_erp_postaction, .build_cp = dasd_diag_build_cp, + .free_cp = dasd_diag_free_cp, .dump_sense = dasd_diag_dump_sense, .fill_info = dasd_diag_fill_info, }; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 27bf674af..c2396feb2 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.57 $ + * $Revision: 1.65 $ */ #include @@ -68,6 +68,10 @@ static struct ccw_device_id dasd_eckd_ids[] = { { CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4}, { CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5}, { CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6}, + { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), driver_info: 0x7}, + { CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), driver_info: 0x8}, + { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), driver_info: 0x9}, + { CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), driver_info: 0xa}, { /* end of list */ }, }; @@ -274,9 +278,11 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, data->attributes.mode = 0x3; /* ECKD */ - if (private->rdc_data.cu_type == 0x2105 + if ((private->rdc_data.cu_type == 0x2105 || + private->rdc_data.cu_type == 0x2107 || + private->rdc_data.cu_type == 0x1750) && !(private->uses_cdl && trk < 2)) - data->ga_extended |= 0x40; + data->ga_extended |= 0x40; /* Regular Data Format Mode */ geo.cyl = private->rdc_data.no_cyl; geo.head = private->rdc_data.trk_per_cyl; @@ -499,11 +505,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) "sizes of configuration data mismatch" "%d (read) vs %ld (expected)", conf_len, sizeof (struct dasd_eckd_confdata)); + + kfree(conf_data); /* allocated by read_conf_data() */ return 0; /* no errror */ } memcpy(&private->conf_data, conf_data, sizeof (struct dasd_eckd_confdata)); - + kfree(conf_data); /* allocated by read_conf_data() */ return 0; } @@ -903,6 +911,8 @@ dasd_eckd_examine_error(struct dasd_ccw_req * cqr, struct irb * irb) switch (cdev->id.cu_type) { case 0x3990: case 0x2105: + case 0x2107: + case 0x1750: return dasd_3990_erp_examine(cqr, irb); case 0x9343: return dasd_9343_erp_examine(cqr, irb); @@ -923,6 +933,8 @@ dasd_eckd_erp_action(struct dasd_ccw_req * cqr) switch (cdev->id.cu_type) { case 0x3990: case 0x2105: + case 0x2107: + case 0x1750: return dasd_3990_erp_action; case 0x9343: /* Return dasd_9343_erp_action; */ @@ -1023,6 +1035,14 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) } rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { dst = page_address(bv->bv_page) + bv->bv_offset; + if (dasd_page_cache) { + char *copy = kmem_cache_alloc(dasd_page_cache, + SLAB_DMA | __GFP_NOWARN); + if (copy && rq_data_dir(req) == WRITE) + memcpy(copy + bv->bv_offset, dst, bv->bv_len); + if (copy) + dst = copy + bv->bv_offset; + } for (off = 0; off < bv->bv_len; off += blksize) { sector_t trkid = recid; unsigned int recoffs = sector_div(trkid, blk_per_trk); @@ -1076,6 +1096,58 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) return cqr; } +static int +dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) +{ + struct dasd_eckd_private *private; + struct ccw1 *ccw; + struct bio *bio; + struct bio_vec *bv; + char *dst, *cda; + unsigned int blksize, blk_per_trk, off; + sector_t recid; + int i, status; + + if (!dasd_page_cache) + goto out; + private = (struct dasd_eckd_private *) cqr->device->private; + blksize = cqr->device->bp_block; + blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); + recid = req->sector >> cqr->device->s2b_shift; + ccw = cqr->cpaddr; + /* Skip over define extent & locate record. */ + ccw++; + if (private->uses_cdl == 0 || recid > 2*blk_per_trk) + ccw++; + rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += blksize) { + /* Skip locate record. */ + if (private->uses_cdl && recid <= 2*blk_per_trk) + ccw++; + if (dst) { + if (ccw->flags & CCW_FLAG_IDA) + cda = *((char **)((addr_t) ccw->cda)); + else + cda = (char *)((addr_t) ccw->cda); + if (dst != cda) { + if (rq_data_dir(req) == READ) + memcpy(dst, cda, bv->bv_len); + kmem_cache_free(dasd_page_cache, + (void *)((addr_t)cda & PAGE_MASK)); + } + dst = NULL; + } + ccw++; + recid++; + } + } +out: + status = cqr->status == DASD_CQR_DONE; + dasd_sfree_request(cqr, cqr->device); + return status; +} + static int dasd_eckd_fill_info(struct dasd_device * device, struct dasd_information2_t * info) @@ -1462,6 +1534,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .erp_action = dasd_eckd_erp_action, .erp_postaction = dasd_eckd_erp_postaction, .build_cp = dasd_eckd_build_cp, + .free_cp = dasd_eckd_free_cp, .dump_sense = dasd_eckd_dump_sense, .fill_info = dasd_eckd_fill_info, }; diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 8116381cf..e51bae9cc 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -4,7 +4,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.34 $ + * $Revision: 1.37 $ */ #include @@ -311,6 +311,14 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) recid = first_rec; rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { dst = page_address(bv->bv_page) + bv->bv_offset; + if (dasd_page_cache) { + char *copy = kmem_cache_alloc(dasd_page_cache, + SLAB_DMA | __GFP_NOWARN); + if (copy && rq_data_dir(req) == WRITE) + memcpy(copy + bv->bv_offset, dst, bv->bv_len); + if (copy) + dst = copy + bv->bv_offset; + } for (off = 0; off < bv->bv_len; off += blksize) { /* Locate record for stupid devices. */ if (private->rdc_data.mode.bits.data_chain == 0) { @@ -347,6 +355,54 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) return cqr; } +static int +dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req) +{ + struct dasd_fba_private *private; + struct ccw1 *ccw; + struct bio *bio; + struct bio_vec *bv; + char *dst, *cda; + unsigned int blksize, off; + int i, status; + + if (!dasd_page_cache) + goto out; + private = (struct dasd_fba_private *) cqr->device->private; + blksize = cqr->device->bp_block; + ccw = cqr->cpaddr; + /* Skip over define extent & locate record. */ + ccw++; + if (private->rdc_data.mode.bits.data_chain != 0) + ccw++; + rq_for_each_bio(bio, req) bio_for_each_segment(bv, bio, i) { + dst = page_address(bv->bv_page) + bv->bv_offset; + for (off = 0; off < bv->bv_len; off += blksize) { + /* Skip locate record. */ + if (private->rdc_data.mode.bits.data_chain == 0) + ccw++; + if (dst) { + if (ccw->flags & CCW_FLAG_IDA) + cda = *((char **)((addr_t) ccw->cda)); + else + cda = (char *)((addr_t) ccw->cda); + if (dst != cda) { + if (rq_data_dir(req) == READ) + memcpy(dst, cda, bv->bv_len); + kmem_cache_free(dasd_page_cache, + (void *)((addr_t)cda & PAGE_MASK)); + } + dst = NULL; + } + ccw++; + } + } +out: + status = cqr->status == DASD_CQR_DONE; + dasd_sfree_request(cqr, cqr->device); + return status; +} + static int dasd_fba_fill_info(struct dasd_device * device, struct dasd_information2_t * info) @@ -410,6 +466,7 @@ static struct dasd_discipline dasd_fba_discipline = { .erp_action = dasd_fba_erp_action, .erp_postaction = dasd_fba_erp_postaction, .build_cp = dasd_fba_build_cp, + .free_cp = dasd_fba_free_cp, .dump_sense = dasd_fba_dump_sense, .fill_info = dasd_fba_fill_info, }; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 9bdf82fca..7e1f435b5 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.60 $ + * $Revision: 1.61 $ */ #ifndef DASD_INT_H @@ -240,7 +240,7 @@ struct dasd_discipline { int (*term_IO) (struct dasd_ccw_req *); struct dasd_ccw_req *(*format_device) (struct dasd_device *, struct format_data_t *); - + int (*free_cp) (struct dasd_ccw_req *, struct request *); /* * Error recovery functions. examine_error() returns a value that * indicates what to do for an error condition. If examine_error() @@ -438,6 +438,8 @@ extern struct dasd_profile_info_t dasd_global_profile; extern unsigned int dasd_profile_level; extern struct block_device_operations dasd_device_operations; +extern kmem_cache_t *dasd_page_cache; + struct dasd_ccw_req * dasd_kmalloc_request(char *, int, int, struct dasd_device *); struct dasd_ccw_req * diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index ca83f9b0a..a66b17b65 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -19,6 +20,7 @@ //#define DCSSBLK_DEBUG /* Debug messages on/off */ #define DCSSBLK_NAME "dcssblk" #define DCSSBLK_MINORS_PER_DISK 1 +#define DCSSBLK_PARM_LEN 400 #ifdef DCSSBLK_DEBUG #define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x) @@ -34,6 +36,8 @@ static int dcssblk_open(struct inode *inode, struct file *filp); static int dcssblk_release(struct inode *inode, struct file *filp); static int dcssblk_make_request(struct request_queue *q, struct bio *bio); +static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; + static int dcssblk_major; static struct block_device_operations dcssblk_devops = { .owner = THIS_MODULE, @@ -135,6 +139,57 @@ dcssblk_get_device_by_name(char *name) return NULL; } +/* + * print appropriate error message for segment_load()/segment_type() + * return code + */ +static void +dcssblk_segment_warn(int rc, char* seg_name) +{ + switch (rc) { + case -ENOENT: + PRINT_WARN("cannot load/query segment %s, does not exist\n", + seg_name); + break; + case -ENOSYS: + PRINT_WARN("cannot load/query segment %s, not running on VM\n", + seg_name); + break; + case -EIO: + PRINT_WARN("cannot load/query segment %s, hardware error\n", + seg_name); + break; + case -ENOTSUPP: + PRINT_WARN("cannot load/query segment %s, is a multi-part " + "segment\n", seg_name); + break; + case -ENOSPC: + PRINT_WARN("cannot load/query segment %s, overlaps with " + "storage\n", seg_name); + break; + case -EBUSY: + PRINT_WARN("cannot load/query segment %s, overlaps with " + "already loaded dcss\n", seg_name); + break; + case -EPERM: + PRINT_WARN("cannot load/query segment %s, already loaded in " + "incompatible mode\n", seg_name); + break; + case -ENOMEM: + PRINT_WARN("cannot load/query segment %s, out of memory\n", + seg_name); + break; + case -ERANGE: + PRINT_WARN("cannot load/query segment %s, exceeds kernel " + "mapping range\n", seg_name); + break; + default: + PRINT_WARN("cannot load/query segment %s, return value %i\n", + seg_name, rc); + break; + } +} + /* * device attribute for switching shared/nonshared (exclusive) * operation (show + store) @@ -163,80 +218,50 @@ dcssblk_shared_store(struct device *dev, const char *inbuf, size_t count) if (atomic_read(&dev_info->use_count)) { PRINT_ERR("share: segment %s is busy!\n", dev_info->segment_name); - up_write(&dcssblk_devices_sem); - return -EBUSY; - } - if ((inbuf[0] == '1') && (dev_info->is_shared == 1)) { - PRINT_WARN("Segment %s already loaded in shared mode!\n", - dev_info->segment_name); - up_write(&dcssblk_devices_sem); - return count; - } - if ((inbuf[0] == '0') && (dev_info->is_shared == 0)) { - PRINT_WARN("Segment %s already loaded in exclusive mode!\n", - dev_info->segment_name); - up_write(&dcssblk_devices_sem); - return count; + rc = -EBUSY; + goto out; } if (inbuf[0] == '1') { // reload segment in shared mode - segment_unload(dev_info->segment_name); - rc = segment_load(dev_info->segment_name, SEGMENT_SHARED_RO, - &dev_info->start, &dev_info->end); + rc = segment_modify_shared(dev_info->segment_name, + SEGMENT_SHARED); if (rc < 0) { - PRINT_ERR("Segment %s not reloaded, rc=%d\n", - dev_info->segment_name, rc); - goto removeseg; + BUG_ON(rc == -EINVAL); + if (rc == -EIO || rc == -ENOENT) + goto removeseg; + } else { + dev_info->is_shared = 1; + switch (dev_info->segment_type) { + case SEG_TYPE_SR: + case SEG_TYPE_ER: + case SEG_TYPE_SC: + set_disk_ro(dev_info->gd,1); + } } - dev_info->is_shared = 1; - PRINT_INFO("Segment %s reloaded, shared mode.\n", - dev_info->segment_name); } else if (inbuf[0] == '0') { // reload segment in exclusive mode - segment_unload(dev_info->segment_name); - rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE_RW, - &dev_info->start, &dev_info->end); + if (dev_info->segment_type == SEG_TYPE_SC) { + PRINT_ERR("Segment type SC (%s) cannot be loaded in " + "non-shared mode\n", dev_info->segment_name); + rc = -EINVAL; + goto out; + } + rc = segment_modify_shared(dev_info->segment_name, + SEGMENT_EXCLUSIVE); if (rc < 0) { - PRINT_ERR("Segment %s not reloaded, rc=%d\n", - dev_info->segment_name, rc); - goto removeseg; + BUG_ON(rc == -EINVAL); + if (rc == -EIO || rc == -ENOENT) + goto removeseg; + } else { + dev_info->is_shared = 0; + set_disk_ro(dev_info->gd, 0); } - dev_info->is_shared = 0; - PRINT_INFO("Segment %s reloaded, exclusive (read-write) mode.\n", - dev_info->segment_name); } else { - up_write(&dcssblk_devices_sem); PRINT_WARN("Invalid value, must be 0 or 1\n"); - return -EINVAL; + rc = -EINVAL; + goto out; } - dev_info->segment_type = rc; rc = count; - - switch (dev_info->segment_type) { - case SEGMENT_SHARED_RO: - case SEGMENT_EXCLUSIVE_RO: - set_disk_ro(dev_info->gd, 1); - break; - case SEGMENT_SHARED_RW: - case SEGMENT_EXCLUSIVE_RW: - set_disk_ro(dev_info->gd, 0); - break; - } - if ((inbuf[0] == '1') && - ((dev_info->segment_type == SEGMENT_EXCLUSIVE_RO) || - (dev_info->segment_type == SEGMENT_EXCLUSIVE_RW))) { - PRINT_WARN("Could not get shared copy of segment %s\n", - dev_info->segment_name); - rc = -EPERM; - } - if ((inbuf[0] == '0') && - ((dev_info->segment_type == SEGMENT_SHARED_RO) || - (dev_info->segment_type == SEGMENT_SHARED_RW))) { - PRINT_WARN("Could not get exclusive copy of segment %s\n", - dev_info->segment_name); - rc = -EPERM; - } - up_write(&dcssblk_devices_sem); goto out; removeseg: @@ -250,8 +275,8 @@ removeseg: put_disk(dev_info->gd); device_unregister(dev); put_device(dev); - up_write(&dcssblk_devices_sem); out: + up_write(&dcssblk_devices_sem); return rc; } @@ -288,7 +313,7 @@ dcssblk_save_store(struct device *dev, const char *inbuf, size_t count) // device is idle => we save immediately PRINT_INFO("Saving segment %s\n", dev_info->segment_name); - segment_replace(dev_info->segment_name); + segment_save(dev_info->segment_name); } else { // device is busy => we save it when it becomes // idle in dcssblk_release @@ -386,18 +411,17 @@ dcssblk_add_store(struct device *dev, const char *buf, size_t count) /* * load the segment */ - rc = segment_load(local_buf, SEGMENT_SHARED_RO, + rc = segment_load(local_buf, SEGMENT_SHARED, &dev_info->start, &dev_info->end); if (rc < 0) { - PRINT_ERR("Segment %s not loaded, rc=%d\n", local_buf, rc); + dcssblk_segment_warn(rc, dev_info->segment_name); goto dealloc_gendisk; } seg_byte_size = (dev_info->end - dev_info->start + 1); set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors - PRINT_INFO("Loaded segment %s from %p to %p, size = %lu Byte, " - "capacity = %lu sectors (512 Byte)\n", local_buf, - (void *) dev_info->start, (void *) dev_info->end, - seg_byte_size, seg_byte_size >> 9); + PRINT_INFO("Loaded segment %s, size = %lu Byte, " + "capacity = %lu (512 Byte) sectors\n", local_buf, + seg_byte_size, seg_byte_size >> 9); dev_info->segment_type = rc; dev_info->save_pending = 0; @@ -447,12 +471,12 @@ dcssblk_add_store(struct device *dev, const char *buf, size_t count) blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); switch (dev_info->segment_type) { - case SEGMENT_SHARED_RO: - case SEGMENT_EXCLUSIVE_RO: + case SEG_TYPE_SR: + case SEG_TYPE_ER: + case SEG_TYPE_SC: set_disk_ro(dev_info->gd,1); break; - case SEGMENT_SHARED_RW: - case SEGMENT_EXCLUSIVE_RW: + default: set_disk_ro(dev_info->gd,0); break; } @@ -585,7 +609,7 @@ dcssblk_release(struct inode *inode, struct file *filp) && (dev_info->save_pending)) { PRINT_INFO("Segment %s became idle and is being saved now\n", dev_info->segment_name); - segment_replace(dev_info->segment_name); + segment_save(dev_info->segment_name); dev_info->save_pending = 0; } up_write(&dcssblk_devices_sem); @@ -641,6 +665,47 @@ fail: return 0; } +static void +dcssblk_check_params(void) +{ + int rc, i, j, k; + char buf[9]; + struct dcssblk_dev_info *dev_info; + + for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0'); + i++) { + for (j = i; (dcssblk_segments[j] != ',') && + (dcssblk_segments[j] != '\0') && + (dcssblk_segments[j] != '(') && + (j - i) < 8; j++) + { + buf[j-i] = dcssblk_segments[j]; + } + buf[j-i] = '\0'; + rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i); + if ((rc >= 0) && (dcssblk_segments[j] == '(')) { + for (k = 0; buf[k] != '\0'; k++) + buf[k] = toupper(buf[k]); + if (!strncmp(&dcssblk_segments[j], "(local)", 7)) { + down_read(&dcssblk_devices_sem); + dev_info = dcssblk_get_device_by_name(buf); + up_read(&dcssblk_devices_sem); + if (dev_info) + dcssblk_shared_store(&dev_info->dev, + "0\n", 2); + } + } + while ((dcssblk_segments[j] != ',') && + (dcssblk_segments[j] != '\0')) + { + j++; + } + if (dcssblk_segments[j] == '\0') + break; + i = j; + } +} + /* * The init/exit functions. */ @@ -689,6 +754,9 @@ dcssblk_init(void) } dcssblk_major = rc; init_rwsem(&dcssblk_devices_sem); + + dcssblk_check_params(); + PRINT_DEBUG("...finished!\n"); return 0; } @@ -696,4 +764,12 @@ dcssblk_init(void) module_init(dcssblk_init); module_exit(dcssblk_exit); +module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444); +MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, " + "comma-separated list, each name max. 8 chars.\n" + "Adding \"(local)\" to segment name equals echoing 0 to " + "/sys/devices/dcssblk//shared after loading " + "the segment - \n" + "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\""); + MODULE_LICENSE("GPL"); diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 312057e93..d428c909b 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -74,10 +74,9 @@ static int xpram_devs; */ static int devs = XPRAM_DEVS; static unsigned int sizes[XPRAM_MAX_DEVS]; -static unsigned int sizes_count; module_param(devs, int, 0); -module_param_array(sizes, int, sizes_count, 0); +module_param_array(sizes, int, NULL, 0); MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \ "the default is " __MODULE_STRING(XPRAM_DEVS) "\n"); diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index bd989f25c..fe74e0648 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -17,8 +17,12 @@ obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o +obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o +obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o + tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o tape-$(CONFIG_PROC_FS) += tape_proc.o tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o +obj-$(CONFIG_MONREADER) += monreader.o diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index e92bb9473..e74554b9d 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -366,10 +366,7 @@ raw3215_tasklet(void *data) tty = raw->tty; if (tty != NULL && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } @@ -986,35 +983,16 @@ tty3215_write_room(struct tty_struct *tty) * String write routine for 3215 ttys */ static int -tty3215_write(struct tty_struct * tty, int from_user, +tty3215_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct raw3215_info *raw; - int length, ret; if (!tty) return 0; raw = (struct raw3215_info *) tty->driver_data; - if (!from_user) { - raw3215_write(raw, buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < 80 ? count : 80; - length -= copy_from_user(raw->ubuffer, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - raw3215_write(raw, raw->ubuffer, count); - buf += length; - count -= length; - ret += length; - } - return ret; + raw3215_write(raw, buf, count); + return count; } /* @@ -1055,10 +1033,7 @@ tty3215_flush_buffer(struct tty_struct *tty) raw = (struct raw3215_info *) tty->driver_data; raw3215_flush_buffer(raw); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 11c1b3b22..77cbe9c3d 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -73,14 +73,11 @@ void con3270_set_timer(struct con3270 *cp, int expires) { if (expires == 0) { - if (timer_pending(&cp->timer)) - del_timer(&cp->timer); + del_timer(&cp->timer); return; } - if (timer_pending(&cp->timer)) { - if (mod_timer(&cp->timer, jiffies + expires)) - return; - } + if (mod_timer(&cp->timer, jiffies + expires)) + return; cp->timer.function = (void (*)(unsigned long)) con3270_update; cp->timer.data = (unsigned long) cp; cp->timer.expires = jiffies + expires; diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 4a57ba6b1..8e16a9716 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -65,7 +65,7 @@ static int raw3270_registered; /* Module parameters */ static int tubxcorrect = 0; -MODULE_PARM(tubxcorrect, "i"); +module_param(tubxcorrect, bool, 0); /* * Wait queue for device init/delete, view delete. @@ -347,8 +347,11 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) if (IS_ERR(irb)) rc = RAW3270_IO_RETRY; - else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END | - DEV_STAT_UNIT_EXCEP)) { + else if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) { + rq->rc = -EIO; + rc = RAW3270_IO_DONE; + } else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END | + DEV_STAT_UNIT_EXCEP)) { /* Handle CE-DE-UE and subsequent UDE */ set_bit(RAW3270_FLAGS_BUSY, &rp->flags); rc = RAW3270_IO_BUSY; @@ -552,6 +555,8 @@ raw3270_start_init(struct raw3270 *rp, struct raw3270_view *view, rc = wait_event_interruptible(wq, raw3270_request_final(rq)); if (rc == -ERESTARTSYS) { /* Interrupted by a signal. */ raw3270_halt_io(view->dev, rq); + /* No wait for the halt to complete. */ + wait_event(wq, raw3270_request_final(rq)); return -ERESTARTSYS; } return rq->rc; @@ -809,9 +814,15 @@ raw3270_setup_console(struct ccw_device *cdev) if (rc) return ERR_PTR(rc); set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags); - raw3270_reset_device(rp); - raw3270_size_device(rp); - raw3270_reset_device(rp); + rc = raw3270_reset_device(rp); + if (rc) + return ERR_PTR(rc); + rc = raw3270_size_device(rp); + if (rc) + return ERR_PTR(rc); + rc = raw3270_reset_device(rp); + if (rc) + return ERR_PTR(rc); set_bit(RAW3270_FLAGS_READY, &rp->flags); return rp; } @@ -1030,7 +1041,7 @@ raw3270_del_view(struct raw3270_view *view) } spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); /* Wait for reference counter to drop to zero. */ - atomic_sub(2, &view->ref_count); + atomic_dec(&view->ref_count); wait_event(raw3270_wait_queue, atomic_read(&view->ref_count) == 0); if (view->fn->free) view->fn->free(view); @@ -1165,13 +1176,20 @@ raw3270_set_online (struct ccw_device *cdev) { struct raw3270 *rp; struct raw3270_notifier *np; + int rc; rp = raw3270_create_device(cdev); if (IS_ERR(rp)) return PTR_ERR(rp); - raw3270_reset_device(rp); - raw3270_size_device(rp); - raw3270_reset_device(rp); + rc = raw3270_reset_device(rp); + if (rc) + return rc; + rc = raw3270_size_device(rp); + if (rc) + return rc; + rc = raw3270_reset_device(rp); + if (rc) + return rc; raw3270_create_attributes(rp); set_bit(RAW3270_FLAGS_READY, &rp->flags); down(&raw3270_sem); diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 047d305cc..ca0f875bf 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,7 @@ static volatile unsigned long sclp_status = 0; #define SCLP_INIT 0 #define SCLP_RUNNING 1 #define SCLP_READING 2 +#define SCLP_SHUTDOWN 3 #define SCLP_INIT_POLL_INTERVAL 1 #define SCLP_BUSY_POLL_INTERVAL 1 @@ -606,10 +608,12 @@ sclp_init_mask(void) sccb->mask_length = sizeof(sccb_mask_t); /* copy in the sccb mask of the registered event types */ spin_lock_irqsave(&sclp_lock, flags); - list_for_each(l, &sclp_reg_list) { - t = list_entry(l, struct sclp_register, list); - sccb->receive_mask |= t->receive_mask; - sccb->send_mask |= t->send_mask; + if (!test_bit(SCLP_SHUTDOWN, &sclp_status)) { + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + sccb->receive_mask |= t->receive_mask; + sccb->send_mask |= t->send_mask; + } } sccb->sclp_receive_mask = 0; sccb->sclp_send_mask = 0; @@ -647,9 +651,10 @@ sclp_init_mask(void) /* WRITEMASK failed - we cannot rely on receiving a state change event, so initially, polling is the only alternative for us to ever become operational. */ - if (!timer_pending(&retry_timer) || - !mod_timer(&retry_timer, - jiffies + SCLP_INIT_POLL_INTERVAL*HZ)) { + if (!test_bit(SCLP_SHUTDOWN, &sclp_status) && + (!timer_pending(&retry_timer) || + !mod_timer(&retry_timer, + jiffies + SCLP_INIT_POLL_INTERVAL*HZ))) { retry_timer.function = sclp_init_mask_retry; retry_timer.data = 0; retry_timer.expires = jiffies + @@ -671,6 +676,26 @@ sclp_init_mask_retry(unsigned long data) sclp_init_mask(); } +/* Reboot event handler - reset send and receive mask to prevent pending SCLP + * events from interfering with rebooted system. */ +static int +sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + unsigned long flags; + + /* Note: need spinlock to maintain atomicity when accessing global + * variables. */ + spin_lock_irqsave(&sclp_lock, flags); + set_bit(SCLP_SHUTDOWN, &sclp_status); + spin_unlock_irqrestore(&sclp_lock, flags); + sclp_init_mask(); + return NOTIFY_DONE; +} + +static struct notifier_block sclp_reboot_notifier = { + .notifier_call = sclp_reboot_event +}; + /* * sclp setup function. Called early (no kmalloc!) from sclp_console_init(). */ @@ -691,6 +716,10 @@ sclp_init(void) list_add(&sclp_state_change_event.list, &sclp_reg_list); list_add(&sclp_quiesce_event.list, &sclp_reg_list); + rc = register_reboot_notifier(&sclp_reboot_notifier); + if (rc) + return rc; + /* * request the 0x2401 external interrupt * The sclp driver is initialized early (before kmalloc works). We diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index a1ad37580..3491615e3 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -277,10 +277,7 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) wake_up(&sclp_tty_waitq); /* check if the tty needs a wake up call */ if (sclp_tty != NULL) { - if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - sclp_tty->ldisc.write_wakeup) - (sclp_tty->ldisc.write_wakeup)(sclp_tty); - wake_up_interruptible(&sclp_tty->write_wait); + tty_wakeup(sclp_tty); } } @@ -398,36 +395,14 @@ sclp_tty_write_string(const unsigned char *str, int count) * routine will return the number of characters actually accepted for writing. */ static int -sclp_tty_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int length, ret; - if (sclp_tty_chars_count > 0) { sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); sclp_tty_chars_count = 0; } - if (!from_user) { - sclp_tty_write_string(buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < SCLP_TTY_BUF_SIZE ? - count : SCLP_TTY_BUF_SIZE; - length -= copy_from_user(sclp_tty_chars, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - sclp_tty_write_string(sclp_tty_chars, length); - buf += length; - count -= length; - ret += length; - } - return ret; + sclp_tty_write_string(buf, count); + return count; } /* @@ -626,7 +601,7 @@ sclp_get_input(unsigned char *start, unsigned char *end) /* if set in ioctl write operators input to console */ if (sclp_ioctls.echo) - sclp_tty_write(sclp_tty, 0, start, count); + sclp_tty_write(sclp_tty, start, count); /* transfer input to high level driver */ sclp_tty_input(start, count); diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 22760a120..69aed79f3 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -139,10 +139,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request) wake_up(&sclp_vt220_waitq); /* Check if the tty needs a wake up call */ if (sclp_vt220_tty != NULL) { - if ((sclp_vt220_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - (sclp_vt220_tty->ldisc.write_wakeup != NULL)) - (sclp_vt220_tty->ldisc.write_wakeup)(sclp_vt220_tty); - wake_up_interruptible(&sclp_vt220_tty->write_wait); + tty_wakeup(sclp_vt220_tty); } } @@ -476,33 +473,9 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, * number of characters actually accepted for writing. */ static int -sclp_vt220_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int length; - int ret; - - if (!from_user) - return __sclp_vt220_write(buf, count, 1, 0); - /* Use intermediate buffer to prevent calling copy_from_user() while - * holding a lock. */ - ret = 0; - while (count > 0) { - length = count < SCLP_VT220_BUF_SIZE ? - count : SCLP_VT220_BUF_SIZE; - length -= copy_from_user(tty->driver_data, - (const unsigned char __user *)buf, length); - if (length == 0) { - if (!ret) - return -EFAULT; - break; - } - length = __sclp_vt220_write(tty->driver_data, length, 1, 0); - buf += length; - count -= length; - ret += length; - } - return ret; + return __sclp_vt220_write(buf, count, 1, 0); } #define SCLP_VT220_SESSION_ENDED 0x01 diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index b7f4e7b8b..1efc9f212 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -225,8 +225,8 @@ tapeblock_setup_device(struct tape_device * device) if (!blkdat->request_queue) return -ENOMEM; - elevator_exit(blkdat->request_queue); - rc = elevator_init(blkdat->request_queue, &elevator_noop); + elevator_exit(blkdat->request_queue->elevator); + rc = elevator_init(blkdat->request_queue, "noop"); if (rc) goto cleanup_queue; diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index debc2b02c..555f32b55 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -124,16 +124,12 @@ void tty3270_set_timer(struct tty3270 *tp, int expires) { if (expires == 0) { - if (timer_pending(&tp->timer)) { + if (del_timer(&tp->timer)) raw3270_put_view(&tp->view); - del_timer(&tp->timer); - } return; } - if (timer_pending(&tp->timer)) { - if (mod_timer(&tp->timer, jiffies + expires)) - return; - } + if (mod_timer(&tp->timer, jiffies + expires)) + return; raw3270_get_view(&tp->view); tp->timer.function = (void (*)(unsigned long)) tty3270_update; tp->timer.data = (unsigned long) tp; @@ -1599,11 +1595,10 @@ tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count) * String write routine for 3270 ttys */ static int -tty3270_write(struct tty_struct * tty, int from_user, +tty3270_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct tty3270 *tp; - int length, ret; tp = tty->driver_data; if (!tp) @@ -1612,26 +1607,8 @@ tty3270_write(struct tty_struct * tty, int from_user, tty3270_do_write(tp, tp->char_buf, tp->char_count); tp->char_count = 0; } - if (!from_user) { - tty3270_do_write(tp, buf, count); - return count; - } - ret = 0; - while (count > 0) { - length = count < TTY3270_CHAR_BUF_SIZE ? - count : TTY3270_CHAR_BUF_SIZE; - length -= copy_from_user(tp->char_buf, buf, length); - if (length == 0) { - if (!ret) - ret = -EFAULT; - break; - } - tty3270_do_write(tp, tp->char_buf, count); - buf += length; - count -= length; - ret += length; - } - return ret; + tty3270_do_write(tp, buf, count); + return count; } /* diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 29000d5e7..4a06c7d0e 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.31 $ + * $Revision: 1.33 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -229,7 +229,7 @@ s390_redo_validation (void) unsigned int irq; CIO_TRACE_EVENT (0, "redoval"); - for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) { + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { int ret; struct subchannel *sch; diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 9b86522fb..21a75ee28 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.28 $ + * $Revision: 1.29 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -191,14 +191,12 @@ ccwgroup_create(struct device *root, gdev->cdev[i]->dev.driver_data = gdev; del_drvdata = 1; - *gdev = (struct ccwgroup_device) { - .creator_id = creator_id, - .count = argc, - .dev = { - .bus = &ccwgroup_bus_type, - .parent = root, - .release = ccwgroup_release, - }, + gdev->creator_id = creator_id; + gdev->count = argc; + gdev->dev = (struct device ) { + .bus = &ccwgroup_bus_type, + .parent = root, + .release = ccwgroup_release, }; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 38e59dd24..fa6f0b105 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.123 $ + * $Revision: 1.128 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -17,8 +17,8 @@ #include #include #include +#include -#include #include #include #include @@ -141,6 +141,7 @@ cio_tpi(void) sch = (struct subchannel *)(unsigned long)tpi_info->intparm; if (!sch) return 1; + local_bh_disable(); irq_enter (); spin_lock(&sch->lock); memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw)); @@ -148,6 +149,7 @@ cio_tpi(void) sch->driver->irq(&sch->dev); spin_unlock(&sch->lock); irq_exit (); + __local_bh_enable(); return 1; } @@ -409,10 +411,10 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc) if (ccode) return -ENODEV; - sch->schib.pmcw.ena = 1; - sch->schib.pmcw.isc = isc; - sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; for (retry = 5, ret = 0; retry > 0; retry--) { + sch->schib.pmcw.ena = 1; + sch->schib.pmcw.isc = isc; + sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; ret = cio_modify(sch); if (ret == -ENODEV) break; @@ -463,9 +465,8 @@ cio_disable_subchannel (struct subchannel *sch) */ return -EBUSY; - - sch->schib.pmcw.ena = 0; for (retry = 5, ret = 0; retry > 0; retry--) { + sch->schib.pmcw.ena = 0; ret = cio_modify(sch); if (ret == -ENODEV) break; diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 788ae49c5..1708a16e4 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.15 $) + * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $) * * Linux on zSeries Channel Measurement Facility support * @@ -526,29 +526,26 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data) time = get_clock() - cdev->private->cmb_start_time; spin_unlock_irqrestore(cdev->ccwlock, flags); - *data = (struct cmbdata) { - /* we only know values before device_busy_time */ - .size = offsetof(struct cmbdata, device_busy_time), - - /* conver to nanoseconds */ - .elapsed_time = (time * 1000) >> 12, - - /* copy data to new structure */ - .ssch_rsch_count = cmb.ssch_rsch_count, - .sample_count = cmb.sample_count, - - /* time fields are converted to nanoseconds while copying */ - .device_connect_time - = time_to_nsec(cmb.device_connect_time), - .function_pending_time - = time_to_nsec(cmb.function_pending_time), - .device_disconnect_time - = time_to_nsec(cmb.device_disconnect_time), - .control_unit_queuing_time - = time_to_nsec(cmb.control_unit_queuing_time), - .device_active_only_time - = time_to_nsec(cmb.device_active_only_time), - }; + memset(data, sizeof(struct cmbdata), 0); + + /* we only know values before device_busy_time */ + data->size = offsetof(struct cmbdata, device_busy_time); + + /* convert to nanoseconds */ + data->elapsed_time = (time * 1000) >> 12; + + /* copy data to new structure */ + data->ssch_rsch_count = cmb.ssch_rsch_count; + data->sample_count = cmb.sample_count; + + /* time fields are converted to nanoseconds while copying */ + data->device_connect_time = time_to_nsec(cmb.device_connect_time); + data->function_pending_time = time_to_nsec(cmb.function_pending_time); + data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); + data->control_unit_queuing_time + = time_to_nsec(cmb.control_unit_queuing_time); + data->device_active_only_time + = time_to_nsec(cmb.device_active_only_time); return 0; } @@ -739,33 +736,29 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) time = get_clock() - cdev->private->cmb_start_time; spin_unlock_irqrestore(cdev->ccwlock, flags); - *data = (struct cmbdata) { - /* we only know values before device_busy_time */ - .size = offsetof(struct cmbdata, device_busy_time), - - /* conver to nanoseconds */ - .elapsed_time = (time * 1000) >> 12, - - /* copy data to new structure */ - .ssch_rsch_count = cmb.ssch_rsch_count, - .sample_count = cmb.sample_count, - - /* time fields are converted to nanoseconds while copying */ - .device_connect_time - = time_to_nsec(cmb.device_connect_time), - .function_pending_time - = time_to_nsec(cmb.function_pending_time), - .device_disconnect_time - = time_to_nsec(cmb.device_disconnect_time), - .control_unit_queuing_time - = time_to_nsec(cmb.control_unit_queuing_time), - .device_active_only_time - = time_to_nsec(cmb.device_active_only_time), - .device_busy_time - = time_to_nsec(cmb.device_busy_time), - .initial_command_response_time - = time_to_nsec(cmb.initial_command_response_time), - }; + memset (data, sizeof(struct cmbdata), 0); + + /* we only know values before device_busy_time */ + data->size = offsetof(struct cmbdata, device_busy_time); + + /* conver to nanoseconds */ + data->elapsed_time = (time * 1000) >> 12; + + /* copy data to new structure */ + data->ssch_rsch_count = cmb.ssch_rsch_count; + data->sample_count = cmb.sample_count; + + /* time fields are converted to nanoseconds while copying */ + data->device_connect_time = time_to_nsec(cmb.device_connect_time); + data->function_pending_time = time_to_nsec(cmb.function_pending_time); + data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); + data->control_unit_queuing_time + = time_to_nsec(cmb.control_unit_queuing_time); + data->device_active_only_time + = time_to_nsec(cmb.device_active_only_time); + data->device_busy_time = time_to_nsec(cmb.device_busy_time); + data->initial_command_response_time + = time_to_nsec(cmb.initial_command_response_time); return 0; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index dba1bfb9a..64f25944b 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.80 $ + * $Revision: 1.84 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -188,6 +188,12 @@ css_evaluate_subchannel(int irq, int slow) put_device(&sch->dev); return 0; /* Already processed. */ } + /* + * We've got a machine check, so running I/O won't get an interrupt. + * Kill any pending timers. + */ + if (sch) + device_kill_pending_timer(sch); if (!disc && !slow) { if (sch) put_device(&sch->dev); @@ -278,7 +284,7 @@ css_rescan_devices(void) { int irq, ret; - for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) { + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { ret = css_evaluate_subchannel(irq, 1); /* No more memory. It doesn't make sense to continue. No * panic because this can happen in midflight and just @@ -521,6 +527,7 @@ css_enqueue_subchannel_slow(unsigned long schid) new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC); if (!new_slow_sch) return -ENOMEM; + memset(new_slow_sch, sizeof(struct slow_subchannel), 0); new_slow_sch->schid = schid; spin_lock_irqsave(&slow_subchannel_lock, flags); list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head); diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index b834e6a72..8ab01af59 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -66,6 +66,7 @@ struct senseid { struct ccw_device_private { int state; /* device state */ atomic_t onoff; + unsigned long registered; __u16 devno; /* device number */ __u16 irq; /* subchannel number */ __u8 imask; /* lpm mask for SNID/SID/SPGID */ @@ -137,6 +138,9 @@ void device_trigger_reprobe(struct subchannel *); /* Helper functions for vary on/off. */ void device_set_waiting(struct subchannel *); +/* Machine check helper function. */ +void device_kill_pending_timer(struct subchannel *); + /* Helper functions to build lists for the slow path. */ int css_enqueue_subchannel_slow(unsigned long schid); void css_walk_subchannel_slow_list(void (*fn)(unsigned long)); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a921b1fea..7b6f85b3e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.120 $ + * $Revision: 1.129 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -68,9 +68,6 @@ ccw_hotplug (struct device *dev, char **envp, int num_envp, if (!cdev) return -ENODEV; - if (cdev->private->state == DEV_STATE_NOT_OPER) - return -ENODEV; - /* what we want to pass to /sbin/hotplug */ envp[i++] = buffer; @@ -501,9 +498,11 @@ ccw_device_register(struct ccw_device *cdev) if ((ret = device_add(dev))) return ret; - if ((ret = device_add_files(dev))) - device_del(dev); - + set_bit(1, &cdev->private->registered); + if ((ret = device_add_files(dev))) { + if (test_and_clear_bit(1, &cdev->private->registered)) + device_del(dev); + } return ret; } @@ -526,8 +525,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) cdev = to_ccwdev(dev); if ((cdev->private->state == DEV_STATE_DISCONNECTED) && (cdev->private->devno == devno) && - (!strncmp(cdev->dev.bus_id, sibling->dev.bus_id, - BUS_ID_SIZE))) { + (cdev != sibling)) { cdev->private->state = DEV_STATE_NOT_OPER; break; } @@ -540,6 +538,26 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) return cdev; } +static void +ccw_device_add_changed(void *data) +{ + + struct ccw_device *cdev; + + cdev = (struct ccw_device *)data; + if (device_add(&cdev->dev)) { + put_device(&cdev->dev); + return; + } + set_bit(1, &cdev->private->registered); + if (device_add_files(&cdev->dev)) { + if (test_and_clear_bit(1, &cdev->private->registered)) + device_unregister(&cdev->dev); + } +} + +extern int css_get_ssd_info(struct subchannel *sch); + void ccw_device_do_unreg_rereg(void *data) { @@ -581,20 +599,20 @@ ccw_device_do_unreg_rereg(void *data) device_unregister(&other_sch->dev); } } + /* Update ssd info here. */ + css_get_ssd_info(sch); cdev->private->devno = sch->schib.pmcw.dev; } else need_rename = 0; device_remove_files(&cdev->dev); - device_del(&cdev->dev); + if (test_and_clear_bit(1, &cdev->private->registered)) + device_del(&cdev->dev); if (need_rename) snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", sch->schib.pmcw.dev); - if (device_add(&cdev->dev)) { - put_device(&cdev->dev); - return; - } - if (device_add_files(&cdev->dev)) - device_unregister(&cdev->dev); + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_add_changed, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); } static void @@ -616,6 +634,7 @@ io_subchannel_register(void *data) struct ccw_device *cdev; struct subchannel *sch; int ret; + unsigned long flags; cdev = (struct ccw_device *) data; sch = to_subchannel(cdev->dev.parent); @@ -630,10 +649,15 @@ io_subchannel_register(void *data) printk (KERN_WARNING "%s: could not register %s\n", __func__, cdev->dev.bus_id); put_device(&cdev->dev); - sch->dev.driver_data = 0; + spin_lock_irqsave(&sch->lock, flags); + sch->dev.driver_data = NULL; + spin_unlock_irqrestore(&sch->lock, flags); kfree (cdev->private); kfree (cdev); - goto out; + put_device(&sch->dev); + if (atomic_dec_and_test(&ccw_device_init_count)) + wake_up(&ccw_device_init_wq); + return; } ret = subchannel_add_files(cdev->dev.parent); @@ -645,6 +669,8 @@ out: cdev->private->flags.recog_done = 1; put_device(&sch->dev); wake_up(&cdev->private->wait_q); + if (atomic_dec_and_test(&ccw_device_init_count)) + wake_up(&ccw_device_init_wq); } void @@ -681,9 +707,11 @@ io_subchannel_recog_done(struct ccw_device *cdev) if (!get_device(&cdev->dev)) break; sch = to_subchannel(cdev->dev.parent); - INIT_WORK(&cdev->private->kick_work, - ccw_device_call_sch_unregister, (void *) cdev); + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_call_sch_unregister, (void *) cdev); queue_work(slow_path_wq, &cdev->private->kick_work); + if (atomic_dec_and_test(&ccw_device_init_count)) + wake_up(&ccw_device_init_wq); break; case DEV_STATE_BOXED: /* Device did not respond in time. */ @@ -694,31 +722,30 @@ io_subchannel_recog_done(struct ccw_device *cdev) */ if (!get_device(&cdev->dev)) break; - INIT_WORK(&cdev->private->kick_work, - io_subchannel_register, (void *) cdev); - queue_work(ccw_device_work, &cdev->private->kick_work); + PREPARE_WORK(&cdev->private->kick_work, + io_subchannel_register, (void *) cdev); + queue_work(slow_path_wq, &cdev->private->kick_work); break; } - if (atomic_dec_and_test(&ccw_device_init_count)) - wake_up(&ccw_device_init_wq); } static int io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) { int rc; + struct ccw_device_private *priv; sch->dev.driver_data = cdev; sch->driver = &io_subchannel_driver; cdev->ccwlock = &sch->lock; - *cdev->private = (struct ccw_device_private) { - .devno = sch->schib.pmcw.dev, - .irq = sch->irq, - .state = DEV_STATE_NOT_OPER, - .cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list), - }; - init_waitqueue_head(&cdev->private->wait_q); - init_timer(&cdev->private->timer); + /* Init private data. */ + priv = cdev->private; + priv->devno = sch->schib.pmcw.dev; + priv->irq = sch->irq; + priv->state = DEV_STATE_NOT_OPER; + INIT_LIST_HEAD(&priv->cmb_list); + init_waitqueue_head(&priv->wait_q); + init_timer(&priv->timer); /* Set an initial name for the device. */ snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", @@ -744,6 +771,7 @@ io_subchannel_probe (struct device *pdev) struct subchannel *sch; struct ccw_device *cdev; int rc; + unsigned long flags; sch = to_subchannel(pdev); if (sch->dev.driver_data) { @@ -784,6 +812,7 @@ io_subchannel_probe (struct device *pdev) .parent = pdev, .release = ccw_device_release, }; + INIT_LIST_HEAD(&cdev->private->kick_work.entry); /* Do first half of device_register. */ device_initialize(&cdev->dev); @@ -795,7 +824,9 @@ io_subchannel_probe (struct device *pdev) rc = io_subchannel_recog(cdev, to_subchannel(pdev)); if (rc) { - sch->dev.driver_data = 0; + spin_lock_irqsave(&sch->lock, flags); + sch->dev.driver_data = NULL; + spin_unlock_irqrestore(&sch->lock, flags); if (cdev->dev.release) cdev->dev.release(&cdev->dev); } @@ -803,24 +834,40 @@ io_subchannel_probe (struct device *pdev) return rc; } +static void +ccw_device_unregister(void *data) +{ + struct ccw_device *cdev; + + cdev = (struct ccw_device *)data; + if (test_and_clear_bit(1, &cdev->private->registered)) + device_unregister(&cdev->dev); + put_device(&cdev->dev); +} + static int io_subchannel_remove (struct device *dev) { struct ccw_device *cdev; + unsigned long flags; if (!dev->driver_data) return 0; cdev = dev->driver_data; /* Set ccw device to not operational and drop reference. */ + spin_lock_irqsave(cdev->ccwlock, flags); + dev->driver_data = NULL; cdev->private->state = DEV_STATE_NOT_OPER; + spin_unlock_irqrestore(cdev->ccwlock, flags); /* - * Careful here. Our ccw device might be yet unregistered when - * de-registering its subchannel (machine check during device - * recognition). Better look if the subchannel has children. + * Put unregistration on workqueue to avoid livelocks on the css bus + * semaphore. */ - if (!list_empty(&dev->children)) - device_unregister(&cdev->dev); - dev->driver_data = NULL; + if (get_device(&cdev->dev)) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_unregister, (void *) cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } return 0; } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 6a8db8450..cacebad07 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -93,6 +93,18 @@ ccw_device_set_timeout(struct ccw_device *cdev, int expires) add_timer(&cdev->private->timer); } +/* Kill any pending timers after machine check. */ +void +device_kill_pending_timer(struct subchannel *sch) +{ + struct ccw_device *cdev; + + if (!sch->dev.driver_data) + return; + cdev = sch->dev.driver_data; + ccw_device_set_timeout(cdev, 0); +} + /* * Cancel running i/o. This is called repeatedly since halt/clear are * asynchronous operations. We do one try with cio_cancel, two tries @@ -142,7 +154,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) panic("Can't stop i/o on subchannel.\n"); } -static void +static int ccw_device_handle_oper(struct ccw_device *cdev) { struct subchannel *sch; @@ -162,9 +174,10 @@ ccw_device_handle_oper(struct ccw_device *cdev) PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg, (void *)cdev); queue_work(ccw_device_work, &cdev->private->kick_work); - return; + return 0; } cdev->private->flags.donotify = 1; + return 1; } /* @@ -194,7 +207,7 @@ static void ccw_device_recog_done(struct ccw_device *cdev, int state) { struct subchannel *sch; - int notify, old_lpm; + int notify, old_lpm, same_dev; sch = to_subchannel(cdev->dev.parent); @@ -224,6 +237,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) /* Boxed devices don't need extra treatment. */ } notify = 0; + same_dev = 0; /* Keep the compiler quiet... */ switch (state) { case DEV_STATE_NOT_OPER: CIO_DEBUG(KERN_WARNING, 2, @@ -232,7 +246,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) break; case DEV_STATE_OFFLINE: if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { - ccw_device_handle_oper(cdev); + same_dev = ccw_device_handle_oper(cdev); notify = 1; } /* fill out sense information */ @@ -243,10 +257,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) .dev_model = cdev->private->senseid.dev_model, }; if (notify) { - /* Get device online again. */ cdev->private->state = DEV_STATE_OFFLINE; - ccw_device_online(cdev); - wake_up(&cdev->private->wait_q); + if (same_dev) { + /* Get device online again. */ + ccw_device_online(cdev); + wake_up(&cdev->private->wait_q); + } return; } /* Issue device info message. */ @@ -452,7 +468,8 @@ ccw_device_nopath_notify(void *data) (void *)cdev); queue_work(ccw_device_work, &cdev->private->kick_work); - } + } else + put_device(&sch->dev); } } else { cio_disable_subchannel(sch); @@ -995,6 +1012,7 @@ device_trigger_reprobe(struct subchannel *sch) if ((sch->lpm & (sch->lpm - 1)) != 0) sch->schib.pmcw.mp = 1; sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; + /* We should also udate ssd info, but this has to wait. */ ccw_device_start_id(cdev, 0); spin_unlock_irqrestore(&sch->lock, flags); } @@ -1189,8 +1207,8 @@ io_subchannel_irq (struct device *pdev) CIO_TRACE_EVENT (3, "IRQ"); CIO_TRACE_EVENT (3, pdev->bus_id); - - dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); + if (cdev) + dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); } EXPORT_SYMBOL_GPL(ccw_device_set_timeout); diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 32365959c..f6cb89728 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -303,10 +303,10 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) sch = to_subchannel(cdev->dev.parent); irb = (struct irb *) __LC_IRB; - /* Retry sense id for cc=1. */ + /* Retry sense id, if needed. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (irb->scsw.cc == 1) { + if ((irb->scsw.cc == 1) || !irb->scsw.actl) { ret = __ccw_device_sense_id_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_id_done(cdev, ret); diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index bc768b62a..dc7d2888a 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.84 $" +#define VERSION_QDIO_C "$Revision: 1.93 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -365,7 +365,7 @@ qdio_stop_polling(struct qdio_q *q) * small window we can miss between resetting it and * checking for PRIMED state */ - if (q->is_iqdio_q) + if (q->is_thinint_q) tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); return 0; @@ -605,8 +605,8 @@ qdio_kick_outbound_q(struct qdio_q *q) sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, atomic_read(&q->busy_siga_counter)); QDIO_DBF_TEXT3(0,trace,dbf_text); - q->timing.busy_start=0; #endif /* CONFIG_QDIO_DEBUG */ + q->timing.busy_start=0; break; case (2|QDIO_SIGA_ERROR_B_BIT_SET): /* cc=2 and busy bit: */ @@ -808,7 +808,7 @@ check_next: #endif /* QDIO_USE_PROCESSING_STATE */ /* * not needed, as the inbound queue will be synced on the next - * siga-r + * siga-r, resp. tiqdio_is_inbound_q_done will do the siga-s */ /*SYNC_MEMORY;*/ f++; @@ -899,7 +899,7 @@ qdio_has_inbound_q_moved(struct qdio_q *q) /* means, no more buffers to be filled */ inline static int -iqdio_is_inbound_q_done(struct qdio_q *q) +tiqdio_is_inbound_q_done(struct qdio_q *q) { int no_used; #ifdef CONFIG_QDIO_DEBUG @@ -1139,7 +1139,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) goto out; qdio_kick_inbound_handler(q); - if (iqdio_is_inbound_q_done(q)) + if (tiqdio_is_inbound_q_done(q)) if (!qdio_stop_polling(q)) { /* * we set the flags to get into the stuff next time, @@ -2088,7 +2088,10 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) u32 kc:4; u32 reserved4:21; u32 isc:3; - u32 reserved5[2]; + u32 word_with_d_bit; + /* set to 0x10000000 to enable + * time delay disablement facility */ + u32 reserved5; u32 subsystem_id; u32 reserved6[1004]; struct chsc_header response; @@ -2126,6 +2129,12 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) scssc_area->kc = QDIO_STORAGE_KEY; scssc_area->isc = TIQDIO_THININT_ISC; scssc_area->subsystem_id = (1<<16) + irq_ptr->irq; + /* enables the time delay disablement facility. Don't care + * whether it is really there (i.e. we haven't checked for + * it) */ + scssc_area->word_with_d_bit = 0x10000000; + + result = chsc(scssc_area); if (result) { @@ -2620,6 +2629,7 @@ qdio_allocate(struct qdio_initialize *init_data) init_MUTEX(&irq_ptr->setting_up_sema); + /* QDR must be in DMA area since CCW data address is only 32 bit */ irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); if (!(irq_ptr->qdr)) { kfree(irq_ptr); diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index ea15f8661..15edebbea 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile @@ -1,5 +1,5 @@ # -# S/390 miscellaneous devices +# S/390 crypto devices # z90crypt-objs := z90main.o z90hardware.o diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h index 624ef6a03..bcabac7a7 100644 --- a/drivers/s390/crypto/z90common.h +++ b/drivers/s390/crypto/z90common.h @@ -1,11 +1,11 @@ /* - * linux/drivers/s390/misc/z90common.h + * linux/drivers/s390/crypto/z90common.h * - * z90crypt 1.3.1 + * z90crypt 1.3.2 * * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) - * Eric Rossman (edrossma@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * @@ -16,7 +16,7 @@ * * 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 + * 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 @@ -24,15 +24,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _Z90COMMON_ -#define _Z90COMMON_ +#ifndef _Z90COMMON_H_ +#define _Z90COMMON_H_ -#define VERSION_Z90COMMON_H "$Revision: 1.8 $" +#define VERSION_Z90COMMON_H "$Revision: 1.16 $" #define RESPBUFFSIZE 256 #define PCI_FUNC_KEY_DECRYPT 0x5044 #define PCI_FUNC_KEY_ENCRYPT 0x504B +extern int ext_bitlens; enum devstat { DEV_GONE, @@ -56,6 +57,7 @@ enum hdstat { HD_TSQ_EXCEPTION }; +#define Z90C_NO_DEVICES 1 #define Z90C_AMBIGUOUS_DOMAIN 2 #define Z90C_INCORRECT_DOMAIN 3 #define ENOTINIT 4 @@ -74,13 +76,13 @@ enum hdstat { #define REC_OPERAND_SIZE 9 #define REC_EVEN_MOD 10 #define REC_NO_WORK 11 -#define REC_HARDWAR_ERR 12 -#define REC_NO_RESPONSE 13 +#define REC_HARDWAR_ERR 12 +#define REC_NO_RESPONSE 13 #define REC_RETRY_DEV 14 #define REC_USER_GONE 15 -#define REC_BAD_MESSAGE 16 -#define REC_INVALID_PAD 17 -#define REC_RELEASED 28 +#define REC_BAD_MESSAGE 16 +#define REC_INVALID_PAD 17 +#define REC_USE_PCICA 18 #define WRONG_DEVICE_TYPE 20 @@ -89,18 +91,55 @@ enum hdstat { #define TSQ_FATAL_ERROR 34 #define RSQ_FATAL_ERROR 35 -#define PCICA 0 -#define PCICC 1 -#define PCIXCC 2 -#define NILDEV -1 -#define ANYDEV -1 +#define Z90CRYPT_NUM_TYPES 5 +#define PCICA 0 +#define PCICC 1 +#define PCIXCC_MCL2 2 +#define PCIXCC_MCL3 3 +#define CEX2C 4 +#define NILDEV -1 +#define ANYDEV -1 +#define PCIXCC_UNK -2 enum hdevice_type { PCICC_HW = 3, PCICA_HW = 4, PCIXCC_HW = 5, OTHER_HW = 6, - OTHER2_HW = 7 + CEX2C_HW = 7 +}; + +struct CPRBX { + unsigned short cprb_len; + unsigned char cprb_ver_id; + unsigned char pad_000[3]; + unsigned char func_id[2]; + unsigned char cprb_flags[4]; + unsigned int req_parml; + unsigned int req_datal; + unsigned int rpl_msgbl; + unsigned int rpld_parml; + unsigned int rpl_datal; + unsigned int rpld_datal; + unsigned int req_extbl; + unsigned char pad_001[4]; + unsigned int rpld_extbl; + unsigned char req_parmb[16]; + unsigned char req_datab[16]; + unsigned char rpl_parmb[16]; + unsigned char rpl_datab[16]; + unsigned char req_extb[16]; + unsigned char rpl_extb[16]; + unsigned short ccp_rtcode; + unsigned short ccp_rscode; + unsigned int mac_data_len; + unsigned char logon_id[8]; + unsigned char mac_value[8]; + unsigned char mac_content_flgs; + unsigned char pad_002; + unsigned short domain; + unsigned char pad_003[12]; + unsigned char pad_004[36]; }; #ifndef DEV_NAME diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index dbc5dd0a5..82a1d9700 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -1,11 +1,11 @@ /* - * linux/drivers/s390/misc/z90crypt.h + * linux/drivers/s390/crypto/z90crypt.h * - * z90crypt 1.3.1 + * z90crypt 1.3.2 * * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) - * Eric Rossman (edrossma@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * @@ -16,7 +16,7 @@ * * 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 + * 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 @@ -24,16 +24,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _LINUX_Z90CRYPT_H_ -#define _LINUX_Z90CRYPT_H_ +#ifndef _Z90CRYPT_H_ +#define _Z90CRYPT_H_ #include -#define VERSION_Z90CRYPT_H "$Revision: 1.2 $" +#define VERSION_Z90CRYPT_H "$Revision: 1.11 $" #define z90crypt_VERSION 1 #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards -#define z90crypt_VARIANT 1 +#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support + +/** + * If we are not using the sparse checker, __user has no use. + */ +#ifdef __CHECKER__ +# define __user __attribute__((noderef, address_space(1))) +#else +# define __user +#endif /** * struct ica_rsa_modexpo @@ -93,16 +102,16 @@ struct ica_rsa_modexpo_crt { * This takes an ica_rsa_modexpo struct as its arg. * * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block + * for the implementation details for the contents of the + * block * * ICARSACRT * Perform an RSA operation using a Chinese-Remainder Theorem key * This takes an ica_rsa_modexpo_crt struct as its arg. * * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block + * for the implementation details for the contents of the + * block * * Z90STAT_TOTALCOUNT * Return an integer count of all device types together. @@ -113,8 +122,14 @@ struct ica_rsa_modexpo_crt { * Z90STAT_PCICCCOUNT * Return an integer count of all PCICCs. * - * Z90STAT_PCIXCCCOUNT - * Return an integer count of all PCIXCCs. + * Z90STAT_PCIXCCMCL2COUNT + * Return an integer count of all MCL2 PCIXCCs. + * + * Z90STAT_PCIXCCMCL3COUNT + * Return an integer count of all MCL3 PCIXCCs. + * + * Z90STAT_CEX2CCOUNT + * Return an integer count of all CEX2Cs. * * Z90STAT_REQUESTQ_COUNT * Return an integer count of the number of entries waiting to be @@ -133,10 +148,12 @@ struct ica_rsa_modexpo_crt { * Z90STAT_STATUS_MASK * Return an 64 element array of unsigned chars for the status of * all devices. - * 0x01: PCICA - * 0x02: PCICC - * 0x03: PCIXCC - * 0x0d: device is disabled via the proc filesystem + * 0x01: PCICA + * 0x02: PCICC + * 0x03: PCIXCC_MCL2 + * 0x04: PCIXCC_MCL3 + * 0x05: CEX2C + * 0x0d: device is disabled via the proc filesystem * * Z90STAT_QDEPTH_MASK * Return an 64 element array of unsigned chars for the queue @@ -152,18 +169,23 @@ struct ica_rsa_modexpo_crt { * This takes an ica_z90_status struct as its arg. * * NOTE: this ioctl() is deprecated, and has been replaced with - * single ioctl()s for each type of status being requested + * single ioctl()s for each type of status being requested + * + * Z90STAT_PCIXCCCOUNT (deprecated) + * Return an integer count of all PCIXCCs (MCL2 + MCL3). + * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from + * MCL2 PCIXCCs. * * Z90QUIESCE (not recommended) * Quiesce the driver. This is intended to stop all new - * requests from being processed. Its use is not recommended, + * requests from being processed. Its use is NOT recommended, * except in circumstances where there is no other way to stop * callers from accessing the driver. Its original use was to * allow the driver to be "drained" of work in preparation for * a system shutdown. * * NOTE: once issued, this ban on new work cannot be undone - * except by unloading and reloading the driver. + * except by unloading and reloading the driver. */ /** @@ -172,8 +194,9 @@ struct ica_rsa_modexpo_crt { #define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) #define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) -/* DEPRECATED status call (bound for removal SOON) */ +/* DEPRECATED status calls (bound for removal at some point) */ #define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) +#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) /* unrelated to ICA callers */ #define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) @@ -182,7 +205,9 @@ struct ica_rsa_modexpo_crt { #define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) #define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) #define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) -#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) +#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) +#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) +#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) #define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) #define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) #define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) @@ -199,8 +224,9 @@ struct ica_rsa_modexpo_crt { #define ERELEASED 131 // user released while ioctl pending #define EQUIESCE 132 // z90crypt quiescing (no more work allowed) #define ETIMEOUT 133 // request timed out -#define EUNKNOWN 134 // some unrecognized error occured -#define EGETBUFF 135 // Error getting buffer +#define EUNKNOWN 134 // some unrecognized error occured (retry may succeed) +#define EGETBUFF 135 // Error getting buffer or hardware lacks capability + // (retry in software) /** * DEPRECATED STRUCTURES @@ -222,10 +248,11 @@ struct ica_z90_status { int pendingqWaitCount; int totalOpenCount; int cryptoDomain; - // status: 0=not there. 1=PCICA. 2=PCICC. 3=PCIXCC + // status: 0=not there, 1=PCICA, 2=PCICC, 3=PCIXCC_MCL2, 4=PCIXCC_MCL3, + // 5=CEX2C unsigned char status[MASK_LENGTH]; // qdepth: # work elements waiting for each device unsigned char qdepth[MASK_LENGTH]; }; -#endif /* _LINUX_Z90CRYPT_H_ */ +#endif /* _Z90CRYPT_H_ */ diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c index 8c8db43d8..beb6a5e0d 100644 --- a/drivers/s390/crypto/z90hardware.c +++ b/drivers/s390/crypto/z90hardware.c @@ -1,11 +1,11 @@ /* - * linux/drivers/s390/misc/z90hardware.c + * linux/drivers/s390/crypto/z90hardware.c * - * z90crypt 1.3.1 + * z90crypt 1.3.2 * * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) - * Eric Rossman (edrossma@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * @@ -16,7 +16,7 @@ * * 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 + * 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 @@ -32,9 +32,9 @@ #include "z90crypt.h" #include "z90common.h" -#define VERSION_Z90HARDWARE_C "$Revision: 1.19 $" +#define VERSION_Z90HARDWARE_C "$Revision: 1.33 $" -char z90chardware_version[] __initdata = +char z90hardware_version[] __initdata = "z90hardware.o (" VERSION_Z90HARDWARE_C "/" VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; @@ -224,7 +224,7 @@ struct type6_hdr { unsigned char right[4]; unsigned char reserved3[2]; unsigned char reserved4[2]; - unsigned char pfs[4]; + unsigned char apfs[4]; unsigned int offset1; unsigned int offset2; unsigned int offset3; @@ -278,39 +278,6 @@ struct CPRB { unsigned char svr_name[8]; }; -struct CPRBX { - unsigned short cprb_len; - unsigned char cprb_ver_id; - unsigned char pad_000[3]; - unsigned char func_id[2]; - unsigned char cprb_flags[4]; - unsigned int req_parml; - unsigned int req_datal; - unsigned int rpl_msgbl; - unsigned int rpld_parml; - unsigned int rpl_datal; - unsigned int rpld_datal; - unsigned int req_extbl; - unsigned char pad_001[4]; - unsigned int rpld_extbl; - unsigned char req_parmb[16]; - unsigned char req_datab[16]; - unsigned char rpl_parmb[16]; - unsigned char rpl_datab[16]; - unsigned char req_extb[16]; - unsigned char rpl_extb[16]; - unsigned short ccp_rtcode; - unsigned short ccp_rscode; - unsigned int mac_data_len; - unsigned char logon_id[8]; - unsigned char mac_value[8]; - unsigned char mac_content_flgs; - unsigned char pad_002; - unsigned short domain; - unsigned char pad_003[12]; - unsigned char pad_004[36]; -}; - struct type6_msg { struct type6_hdr header; struct CPRB CPRB; @@ -347,12 +314,13 @@ struct type82_hdr { #define REPLY_ERROR_FORMAT_FIELD 0x29 #define REPLY_ERROR_INVALID_COMMAND 0x30 #define REPLY_ERROR_MALFORMED_MSG 0x40 -#define REPLY_ERROR_RESERVED_FIELD 0x50 +#define REPLY_ERROR_RESERVED_FIELDO 0x50 #define REPLY_ERROR_WORD_ALIGNMENT 0x60 #define REPLY_ERROR_MESSAGE_LENGTH 0x80 #define REPLY_ERROR_OPERAND_INVALID 0x82 #define REPLY_ERROR_OPERAND_SIZE 0x84 #define REPLY_ERROR_EVEN_MOD_IN_OPND 0x85 +#define REPLY_ERROR_RESERVED_FIELD 0x88 #define REPLY_ERROR_TRANSPORT_FAIL 0x90 #define REPLY_ERROR_PACKET_TRUNCATED 0xA0 #define REPLY_ERROR_ZERO_BUFFER_LEN 0xB0 @@ -379,7 +347,7 @@ struct type86_fmt2_msg { unsigned int offset2; unsigned int count3; unsigned int offset3; - unsigned int ount4; + unsigned int count4; unsigned int offset4; }; @@ -546,18 +514,30 @@ static struct CPRBX static_cprbx = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }; -static struct function_and_rules_block static_pkd_function_and_rulesX = { +static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = { {0x50,0x44}, {0x00,0x0A}, {'P','K','C','S','-','1','.','2'} }; -static struct function_and_rules_block static_pke_function_and_rulesX = { +static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = { {0x50,0x4B}, {0x00,0x0A}, {'Z','E','R','O','-','P','A','D'} }; +static struct function_and_rules_block static_pkd_function_and_rulesX = { + {0x50,0x44}, + {0x00,0x0A}, + {'Z','E','R','O','-','P','A','D'} +}; + +static struct function_and_rules_block static_pke_function_and_rulesX = { + {0x50,0x4B}, + {0x00,0x0A}, + {'M','R','P',' ',' ',' ',' ',' '} +}; + struct T6_keyBlock_hdrX { unsigned short blen; unsigned short ulen; @@ -701,11 +681,9 @@ static struct cca_public_sec static_cca_pub_sec = { #define FIXED_TYPE6_CR_LENX 0x000001E3 -#ifndef MAX_RESPONSE_SIZE #define MAX_RESPONSE_SIZE 0x00000710 #define MAX_RESPONSEX_SIZE 0x0000077C -#endif #define RESPONSE_CPRB_SIZE 0x000006B8 #define RESPONSE_CPRBX_SIZE 0x00000724 @@ -1063,7 +1041,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) *q_depth = t_depth + 1; switch (t_dev_type) { case OTHER_HW: - case OTHER2_HW: stat = HD_NOT_THERE; *dev_type = NILDEV; break; @@ -1074,7 +1051,10 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) *dev_type = PCICC; break; case PCIXCC_HW: - *dev_type = PCIXCC; + *dev_type = PCIXCC_UNK; + break; + case CEX2C_HW: + *dev_type = CEX2C; break; default: *dev_type = NILDEV; @@ -1133,6 +1113,7 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) default: stat = HD_NOT_THERE; break_out = 1; + break; } if (break_out) break; @@ -1170,18 +1151,11 @@ reset_device(int deviceNr, int cdx, int resetNr) switch (stat_word.response_code) { case AP_RESPONSE_NORMAL: stat = DEV_ONLINE; - if (stat_word.q_stat_flags & - AP_Q_STATUS_EMPTY) + if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) break_out = 1; break; case AP_RESPONSE_Q_NOT_AVAIL: - stat = DEV_GONE; - break_out = 1; - break; case AP_RESPONSE_DECONFIGURED: - stat = DEV_GONE; - break_out = 1; - break; case AP_RESPONSE_CHECKSTOPPED: stat = DEV_GONE; break_out = 1; @@ -1195,6 +1169,7 @@ reset_device(int deviceNr, int cdx, int resetNr) default: stat = DEV_GONE; break_out = 1; + break; } if (break_out == 1) break; @@ -1251,7 +1226,7 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3], msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7], msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]); - print_buffer(msg_ext+12, msg_len); + print_buffer(msg_ext+CALLER_HEADER, msg_len); #endif ccode = sen(msg_len, msg_ext, &stat_word); @@ -1283,14 +1258,15 @@ send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) break; default: stat = DEV_GONE; + break; } return stat; } enum devstat -receive_from_AP(int dev_nr, int cdx, int resplen, - unsigned char *resp, unsigned char *psmid) +receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp, + unsigned char *psmid) { int ccode; struct ap_status_word stat_word; @@ -1543,6 +1519,7 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, struct type6_hdr *tp6Hdr_p; struct CPRB *cprb_p; struct cca_private_ext_ME *key_p; + static int deprecated_msg_count = 0; mod_len = icaMsg_p->inputdatalength; tmp_size = FIXED_TYPE6_ME_LEN + mod_len; @@ -1593,13 +1570,19 @@ ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, return SEN_USER_ERROR; if (is_common_public_key(temp, mod_len)) { - PRINTK("Common public key used for modex decrypt\n"); + if (deprecated_msg_count < 20) { + PRINTK("Common public key used for modex decrypt\n"); + deprecated_msg_count++; + if (deprecated_msg_count == 20) + PRINTK("No longer issuing messages about common" + " public key for modex decrypt.\n"); + } return SEN_NOT_AVAIL; } temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus) - mod_len; - if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len) != 0) + if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) return SEN_RELEASED; if (is_empty(temp, mod_len)) return SEN_USER_ERROR; @@ -1617,24 +1600,33 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, { int mod_len, vud_len, exp_len, key_len; int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i; - unsigned char temp_exp[256], *exp_p, *temp; + unsigned char *temp_exp, *exp_p, *temp; struct type6_hdr *tp6Hdr_p; struct CPRB *cprb_p; struct cca_public_key *key_p; struct T6_keyBlock_hdr *keyb_p; + temp_exp = kmalloc(256, GFP_KERNEL); + if (!temp_exp) + return EGETBUFF; mod_len = icaMsg_p->inputdatalength; - if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) + if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { + kfree(temp_exp); return SEN_RELEASED; - if (is_empty(temp_exp, mod_len)) + } + if (is_empty(temp_exp, mod_len)) { + kfree(temp_exp); return SEN_USER_ERROR; + } exp_p = temp_exp; for (i = 0; i < mod_len; i++) if (exp_p[i]) break; - if (i >= mod_len) + if (i >= mod_len) { + kfree(temp_exp); return SEN_USER_ERROR; + } exp_len = mod_len - i; exp_p += i; @@ -1665,17 +1657,25 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, sizeof(struct function_and_rules_block)); temp += sizeof(struct function_and_rules_block); temp += 2; - if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) + if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) { + kfree(temp_exp); return SEN_RELEASED; - if (is_empty(temp, mod_len)) + } + if (is_empty(temp, mod_len)) { + kfree(temp_exp); return SEN_USER_ERROR; - if (temp[0] != 0x00 || temp[1] != 0x02) + } + if ((temp[0] != 0x00) || (temp[1] != 0x02)) { + kfree(temp_exp); return SEN_NOT_AVAIL; + } for (i = 2; i < mod_len; i++) if (temp[i] == 0x00) break; - if ((i < 9) || (i > (mod_len - 2))) + if ((i < 9) || (i > (mod_len - 2))) { + kfree(temp_exp); return SEN_NOT_AVAIL; + } pad_len = i + 1; vud_len = mod_len - pad_len; memmove(temp, temp+pad_len, vud_len); @@ -1689,6 +1689,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, key_p = (struct cca_public_key *)temp; temp = key_p->pubSec.exponent; memcpy(temp, exp_p, exp_len); + kfree(temp_exp); temp += exp_len; if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) return SEN_RELEASED; @@ -1697,7 +1698,7 @@ ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, key_p->pubSec.modulus_bit_len = 8 * mod_len; key_p->pubSec.modulus_byte_len = mod_len; key_p->pubSec.exponent_len = exp_len; - key_p->pubSec.section_length = 12 + mod_len + exp_len; + key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); key_p->pubHdr.token_length = key_len; key_len += 4; @@ -1824,27 +1825,37 @@ ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, static int ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, - int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, + int dev_type) { int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; int key_len, i; - unsigned char temp_exp[256], *tgt_p, *temp, *exp_p; + unsigned char *temp_exp, *tgt_p, *temp, *exp_p; struct type6_hdr *tp6Hdr_p; struct CPRBX *cprbx_p; struct cca_public_key *key_p; struct T6_keyBlock_hdrX *keyb_p; + temp_exp = kmalloc(256, GFP_KERNEL); + if (!temp_exp) + return EGETBUFF; mod_len = icaMsg_p->inputdatalength; - if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) + if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { + kfree(temp_exp); return SEN_RELEASED; - if (is_empty(temp_exp, mod_len)) + } + if (is_empty(temp_exp, mod_len)) { + kfree(temp_exp); return SEN_USER_ERROR; + } exp_p = temp_exp; for (i = 0; i < mod_len; i++) if (exp_p[i]) break; - if (i >= mod_len) + if (i >= mod_len) { + kfree(temp_exp); return SEN_USER_ERROR; + } exp_len = mod_len - i; exp_p += i; PDEBUG("exp_len after computation: %08x\n", exp_len); @@ -1867,15 +1878,23 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, cprbx_p->domain = (unsigned short)cdx; cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE; tgt_p += sizeof(struct CPRBX); - memcpy(tgt_p, &static_pke_function_and_rulesX, - sizeof(struct function_and_rules_block)); + if (dev_type == PCIXCC_MCL2) + memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2, + sizeof(struct function_and_rules_block)); + else + memcpy(tgt_p, &static_pke_function_and_rulesX, + sizeof(struct function_and_rules_block)); tgt_p += sizeof(struct function_and_rules_block); tgt_p += 2; - if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) - return SEN_RELEASED; - if (is_empty(tgt_p, mod_len)) - return SEN_USER_ERROR; + if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) { + kfree(temp_exp); + return SEN_RELEASED; + } + if (is_empty(tgt_p, mod_len)) { + kfree(temp_exp); + return SEN_USER_ERROR; + } tgt_p -= 2; *((short *)tgt_p) = (short) vud_len; tgt_p += vud_len; @@ -1885,15 +1904,16 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, key_p = (struct cca_public_key *)tgt_p; temp = key_p->pubSec.exponent; memcpy(temp, exp_p, exp_len); + kfree(temp_exp); temp += exp_len; if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) - return SEN_RELEASED; + return SEN_RELEASED; if (is_empty(temp, mod_len)) - return SEN_USER_ERROR; + return SEN_USER_ERROR; key_p->pubSec.modulus_bit_len = 8 * mod_len; key_p->pubSec.modulus_byte_len = mod_len; key_p->pubSec.exponent_len = exp_len; - key_p->pubSec.section_length = 12 + mod_len + exp_len; + key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); key_p->pubHdr.token_length = key_len; key_len += 4; @@ -1908,7 +1928,8 @@ ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, static int ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, - int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, + int dev_type) { int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; int long_len, pad_len, keyPartsLen, tmp_l; @@ -1943,8 +1964,12 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, cprbx_p->req_parml = parmBlock_l; cprbx_p->rpl_msgbl = parmBlock_l; tgt_p += sizeof(struct CPRBX); - memcpy(tgt_p, &static_pkd_function_and_rulesX, - sizeof(struct function_and_rules_block)); + if (dev_type == PCIXCC_MCL2) + memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2, + sizeof(struct function_and_rules_block)); + else + memcpy(tgt_p, &static_pkd_function_and_rulesX, + sizeof(struct function_and_rules_block)); tgt_p += sizeof(struct function_and_rules_block); *((short *)tgt_p) = (short) vud_len; tgt_p += 2; @@ -2043,20 +2068,37 @@ convert_request(unsigned char *buffer, int func, unsigned short function, (struct ica_rsa_modexpo *) buffer, cdx, msg_l_p, (struct type6_msg *) msg_p); } - if (dev_type == PCIXCC) { + if ((dev_type == PCIXCC_MCL2) || + (dev_type == PCIXCC_MCL3) || + (dev_type == CEX2C)) { if (func == ICARSACRT) return ICACRT_msg_to_type6CRT_msgX( (struct ica_rsa_modexpo_crt *) buffer, - cdx, msg_l_p, (struct type6_msg *) msg_p); + cdx, msg_l_p, (struct type6_msg *) msg_p, + dev_type); else return ICAMEX_msg_to_type6MEX_msgX( (struct ica_rsa_modexpo *) buffer, - cdx, msg_l_p, (struct type6_msg *) msg_p); + cdx, msg_l_p, (struct type6_msg *) msg_p, + dev_type); } return 0; } +int ext_bitlens_msg_count = 0; +static inline void +unset_ext_bitlens(void) +{ + if (!ext_bitlens_msg_count) { + PRINTK("Unable to use coprocessors for extended bitlengths. " + "Using PCICAs (if present) for extended bitlengths. " + "This is not an error.\n"); + ext_bitlens_msg_count++; + } + ext_bitlens = 0; +} + int convert_response(unsigned char *response, unsigned char *buffer, int *respbufflen_p, unsigned char *resp_buff) @@ -2064,8 +2106,8 @@ convert_response(unsigned char *response, unsigned char *buffer, struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; struct type82_hdr *t82h_p = (struct type82_hdr *) response; struct type84_hdr *t84h_p = (struct type84_hdr *) response; - struct type86_hdr *t86h_p = (struct type86_hdr *) response; - int rv, reply_code, service_rc, service_rs, src_l; + struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; + int reply_code, service_rc, service_rs, src_l; unsigned char *src_p, *tgt_p; struct CPRB *cprb_p; struct CPRBX *cprbx_p; @@ -2075,11 +2117,9 @@ convert_response(unsigned char *response, unsigned char *buffer, service_rc = 0; service_rs = 0; src_l = 0; - rv = 0; switch (t82h_p->type) { case TYPE82_RSP_CODE: reply_code = t82h_p->reply_code; - rv = 4; src_p = (unsigned char *)t82h_p; PRINTK("Hardware error: Type 82 Message Header: " "%02x%02x%02x%02x%02x%02x%02x%02x\n", @@ -2091,15 +2131,9 @@ convert_response(unsigned char *response, unsigned char *buffer, src_p = response + (int)t84h_p->len - src_l; break; case TYPE86_RSP_CODE: - reply_code = t86h_p->reply_code; - if (t86h_p->format != TYPE86_FMT2) { - rv = 4; - break; - } - if (reply_code != 0) { - rv = 4; + reply_code = t86m_p->hdr.reply_code; + if (reply_code != 0) break; - } cprb_p = (struct CPRB *) (response + sizeof(struct type86_fmt2_msg)); cprbx_p = (struct CPRBX *) cprb_p; @@ -2108,11 +2142,22 @@ convert_response(unsigned char *response, unsigned char *buffer, if (service_rc != 0) { le2toI(cprb_p->ccp_rscode, &service_rs); if ((service_rc == 8) && (service_rs == 66)) - PDEBUG("8/66 on PCICC\n"); + PDEBUG("Bad block format on PCICC\n"); + else if ((service_rc == 8) && (service_rs == 770)) { + PDEBUG("Invalid key length on PCICC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else if ((service_rc == 8) && (service_rs == 783)) { + PDEBUG("Extended bitlengths not enabled" + "on PCICC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } else PRINTK("service rc/rs: %d/%d\n", service_rc, service_rs); - rv = 8; + return REC_OPERAND_INV; } src_p = (unsigned char *)cprb_p + sizeof(struct CPRB); src_p += 4; @@ -2124,11 +2169,22 @@ convert_response(unsigned char *response, unsigned char *buffer, if (service_rc != 0) { service_rs = (int) cprbx_p->ccp_rscode; if ((service_rc == 8) && (service_rs == 66)) - PDEBUG("8/66 on PCIXCC\n"); + PDEBUG("Bad block format on PCXICC\n"); + else if ((service_rc == 8) && (service_rs == 770)) { + PDEBUG("Invalid key length on PCIXCC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else if ((service_rc == 8) && (service_rs == 783)) { + PDEBUG("Extended bitlengths not enabled" + "on PCIXCC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } else PRINTK("service rc/rs: %d/%d\n", service_rc, service_rs); - rv = 8; + return REC_OPERAND_INV; } src_p = (unsigned char *) cprbx_p + sizeof(struct CPRBX); @@ -2139,12 +2195,10 @@ convert_response(unsigned char *response, unsigned char *buffer, } break; default: - break; + return REC_BAD_MESSAGE; } - if (rv == 8) - return 8; - if (rv == 4) + if (reply_code) switch (reply_code) { case REPLY_ERROR_OPERAND_INVALID: return REC_OPERAND_INV; @@ -2154,8 +2208,14 @@ convert_response(unsigned char *response, unsigned char *buffer, return REC_EVEN_MOD; case REPLY_ERROR_MESSAGE_TYPE: return WRONG_DEVICE_TYPE; + case REPLY_ERROR_TRANSPORT_FAIL: + PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n", + t86m_p->apfs[0], t86m_p->apfs[1], + t86m_p->apfs[2], t86m_p->apfs[3]); + return REC_HARDWAR_ERR; default: - return 12; + PRINTKW("reply code = %d\n", reply_code); + return REC_HARDWAR_ERR; } if (service_rc != 0) @@ -2171,14 +2231,13 @@ convert_response(unsigned char *response, unsigned char *buffer, memcpy(tgt_p, src_p, src_l); if ((t82h_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); - rv = pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l); - if (rv != 0) - return rv; + if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l)) + return REC_INVALID_PAD; } *respbufflen_p = icaMsg_p->outputdatalength; if (*respbufflen_p == 0) PRINTK("Zero *respbufflen_p\n"); - return rv; + return 0; } diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 8ac1e9b75..ab92dea8c 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -1,11 +1,11 @@ /* - * linux/drivers/s390/misc/z90main.c + * linux/drivers/s390/crypto/z90main.c * - * z90crypt 1.3.1 + * z90crypt 1.3.2 * * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) - * Eric Rossman (edrossma@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * @@ -16,7 +16,7 @@ * * 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 + * 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 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -50,13 +51,13 @@ # error "This kernel is too recent: not supported by this file" #endif -#define VERSION_Z90MAIN_C "$Revision: 1.31 $" +#define VERSION_Z90MAIN_C "$Revision: 1.57 $" -static char z90cmain_version[] __initdata = +static char z90main_version[] __initdata = "z90main.o (" VERSION_Z90MAIN_C "/" VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; -extern char z90chardware_version[]; +extern char z90hardware_version[]; /** * Defaults that may be modified. @@ -96,7 +97,7 @@ extern char z90chardware_version[]; * older than CLEANUPTIME seconds in the past. */ #ifndef CLEANUPTIME -#define CLEANUPTIME 15 +#define CLEANUPTIME 20 #endif /** @@ -116,9 +117,15 @@ extern char z90chardware_version[]; /** * Reader should run every READERTIME milliseconds + * With the 100Hz patch for s390, z90crypt can lock the system solid while + * under heavy load. We'll try to avoid that. */ #ifndef READERTIME +#if HZ > 1000 #define READERTIME 2 +#else +#define READERTIME 10 +#endif #endif /** @@ -209,18 +216,13 @@ extern char z90chardware_version[]; #ifndef Z90CRYPT_NUM_DEVS #define Z90CRYPT_NUM_DEVS Z90CRYPT_NUM_APS #endif -#ifndef Z90CRYPT_NUM_TYPES -#define Z90CRYPT_NUM_TYPES 3 -#endif /** * Buffer size for receiving responses. The maximum Response Size * is actually the maximum request size, since in an error condition * the request itself may be returned unchanged. */ -#ifndef MAX_RESPONSE_SIZE #define MAX_RESPONSE_SIZE 0x0000077C -#endif /** * A count and status-byte mask @@ -246,7 +248,8 @@ struct device_x { * All devices are arranged in a single array: 64 APs */ struct device { - int dev_type; // PCICA, PCICC, or PCIXCC + int dev_type; // PCICA, PCICC, PCIXCC_MCL2, + // PCIXCC_MCL3, CEX2C enum devstat dev_stat; // current device status int dev_self_x; // Index in array int disabled; // Set when device is in error @@ -328,6 +331,7 @@ static int destroy_crypto_device(int); static void destroy_z90crypt(void); static int refresh_index_array(struct status *, struct device_x *); static int probe_device_type(struct device *); +static int probe_PCIXCC_type(struct device *); /** * proc fs definitions @@ -449,9 +453,9 @@ static struct miscdevice z90crypt_misc_device = { /** * Documentation values. */ -MODULE_AUTHOR("zLinux Crypto Team: Robert H. Burroughs, Eric D. Rossman" +MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman" "and Jochen Roehrig"); -MODULE_DESCRIPTION("zLinux Cryptographic Coprocessor device driver, " +MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, " "Copyright 2001, 2004 IBM Corporation"); MODULE_LICENSE("GPL"); module_param(domain, int, 0); @@ -554,7 +558,8 @@ trans_modexpo_crt32(unsigned int fd, unsigned int cmd, unsigned long arg, static int compatible_ioctls[] = { ICAZ90STATUS, Z90QUIESCE, Z90STAT_TOTALCOUNT, Z90STAT_PCICACOUNT, - Z90STAT_PCICCCOUNT, Z90STAT_PCIXCCCOUNT, Z90STAT_REQUESTQ_COUNT, + Z90STAT_PCICCCOUNT, Z90STAT_PCIXCCCOUNT, Z90STAT_PCIXCCMCL2COUNT, + Z90STAT_PCIXCCMCL3COUNT, Z90STAT_CEX2CCOUNT, Z90STAT_REQUESTQ_COUNT, Z90STAT_PENDINGQ_COUNT, Z90STAT_TOTALOPEN_COUNT, Z90STAT_DOMAIN_INDEX, Z90STAT_STATUS_MASK, Z90STAT_QDEPTH_MASK, Z90STAT_PERDEV_REQCNT, }; @@ -575,20 +580,33 @@ static int z90_register_ioctl32s(void) int result, i; result = register_ioctl32_conversion(ICARSAMODEXPO, trans_modexpo32); + if (result == -EBUSY) { + unregister_ioctl32_conversion(ICARSAMODEXPO); + result = register_ioctl32_conversion(ICARSAMODEXPO, + trans_modexpo32); + } if (result) return result; result = register_ioctl32_conversion(ICARSACRT, trans_modexpo_crt32); + if (result == -EBUSY) { + unregister_ioctl32_conversion(ICARSACRT); + result = register_ioctl32_conversion(ICARSACRT, + trans_modexpo_crt32); + } if (result) return result; for(i = 0; i < ARRAY_SIZE(compatible_ioctls); i++) { - result = register_ioctl32_conversion(compatible_ioctls[i],NULL); - if (result) { - z90_unregister_ioctl32s(); - return result; + result = register_ioctl32_conversion(compatible_ioctls[i], 0); + if (result == -EBUSY) { + unregister_ioctl32_conversion(compatible_ioctls[i]); + result = register_ioctl32_conversion( + compatible_ioctls[i], 0); } + if (result) + return result; } - return result; + return 0; } #else // !CONFIG_COMPAT static inline void z90_unregister_ioctl32s(void) @@ -612,10 +630,15 @@ z90crypt_init_module(void) PDEBUG("PID %d\n", PID()); + if ((domain < -1) || (domain > 15)) { + PRINTKW("Invalid param: domain = %d. Not loading.\n", domain); + return -EINVAL; + } + #ifndef Z90CRYPT_USE_HOTPLUG /* Register as misc device with given minor (or get a dynamic one). */ result = misc_register(&z90crypt_misc_device); - if (result <0) { + if (result < 0) { PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n", z90crypt_misc_device.minor, result); return result; @@ -647,8 +670,8 @@ z90crypt_init_module(void) PRINTKN("Version %d.%d.%d loaded, built on %s %s\n", z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT, __DATE__, __TIME__); - PRINTKN("%s\n", z90cmain_version); - PRINTKN("%s\n", z90chardware_version); + PRINTKN("%s\n", z90main_version); + PRINTKN("%s\n", z90hardware_version); PDEBUG("create_z90crypt (domain index %d) successful.\n", domain); } else @@ -923,7 +946,26 @@ get_status_PCICCcount(void) static inline int get_status_PCIXCCcount(void) { - return z90crypt.hdware_info->type_mask[PCIXCC].st_count; + return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count + + z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count; +} + +static inline int +get_status_PCIXCCMCL2count(void) +{ + return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count; +} + +static inline int +get_status_PCIXCCMCL3count(void) +{ + return z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count; +} + +static inline int +get_status_CEX2Ccount(void) +{ + return z90crypt.hdware_info->type_mask[CEX2C].st_count; } static inline int @@ -1016,8 +1058,8 @@ init_work_element(struct work_element *we_p, we_p->audit[2] = 0x00; we_p->resp_buff_size = 0; we_p->retcode = 0; - we_p->devindex = -1; // send_to_crypto selects the device - we_p->devtype = -1; // getCryptoBuffer selects the type + we_p->devindex = -1; + we_p->devtype = -1; atomic_set(&we_p->alarmrung, 0); init_waitqueue_head(&we_p->waitq); INIT_LIST_HEAD(&(we_p->liste)); @@ -1040,42 +1082,113 @@ allocate_work_element(struct work_element **we_pp, static inline void remove_device(struct device *device_p) { - if (!device_p || device_p->disabled != 0) + if (!device_p || (device_p->disabled != 0)) return; device_p->disabled = 1; z90crypt.hdware_info->type_mask[device_p->dev_type].disabled_count++; z90crypt.hdware_info->hdware_mask.disabled_count++; } +/** + * Bitlength limits for each card + * + * There are new MCLs which allow more bitlengths. See the table for details. + * The MCL must be applied and the newer bitlengths enabled for these to work. + * + * Card Type Old limit New limit + * PCICC 512-1024 512-2048 + * PCIXCC_MCL2 512-2048 no change (applying this MCL == card is MCL3+) + * PCIXCC_MCL3 512-2048 128-2048 + * CEX2C 512-2048 128-2048 + * + * ext_bitlens (extended bitlengths) is a global, since you should not apply an + * MCL to just one card in a machine. We assume, at first, that all cards have + * these capabilities. + */ +int ext_bitlens = 1; // This is global +#define PCIXCC_MIN_MOD_SIZE 16 // 128 bits +#define OLD_PCIXCC_MIN_MOD_SIZE 64 // 512 bits +#define PCICC_MIN_MOD_SIZE 64 // 512 bits +#define OLD_PCICC_MAX_MOD_SIZE 128 // 1024 bits +#define MAX_MOD_SIZE 256 // 2048 bits + static inline int -select_device_type(int *dev_type_p) +select_device_type(int *dev_type_p, int bytelength) { + static int count = 0; + int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use; struct status *stat; if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && - (*dev_type_p != PCIXCC) && (*dev_type_p != ANYDEV)) + (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) && + (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV)) return -1; if (*dev_type_p != ANYDEV) { stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; if (stat->st_count > - stat->disabled_count + stat->user_disabled_count) + (stat->disabled_count + stat->user_disabled_count)) return 0; return -1; } + /* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */ stat = &z90crypt.hdware_info->type_mask[PCICA]; - if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { - *dev_type_p = PCICA; + PCICA_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL3]; + PCIXCC_MCL3_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + stat = &z90crypt.hdware_info->type_mask[CEX2C]; + CEX2C_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) { + /** + * bitlength is a factor, PCICA is the most capable, even with + * the new MCL. + */ + if ((bytelength < PCIXCC_MIN_MOD_SIZE) || + (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { + if (!PCICA_avail) + return -1; + else { + *dev_type_p = PCICA; + return 0; + } + } + + index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail + + CEX2C_avail); + if (index_to_use < PCICA_avail) + *dev_type_p = PCICA; + else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail)) + *dev_type_p = PCIXCC_MCL3; + else + *dev_type_p = CEX2C; + count++; return 0; } - stat = &z90crypt.hdware_info->type_mask[PCIXCC]; - if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { - *dev_type_p = PCIXCC; + /* Less than OLD_PCIXCC_MIN_MOD_SIZE cannot go to a PCIXCC_MCL2 */ + if (bytelength < OLD_PCIXCC_MIN_MOD_SIZE) + return -1; + stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL2]; + if (stat->st_count > + (stat->disabled_count + stat->user_disabled_count)) { + *dev_type_p = PCIXCC_MCL2; return 0; } + /** + * Less than PCICC_MIN_MOD_SIZE or more than OLD_PCICC_MAX_MOD_SIZE + * (if we don't have the MCL applied and the newer bitlengths enabled) + * cannot go to a PCICC + */ + if ((bytelength < PCICC_MIN_MOD_SIZE) || + (!ext_bitlens && (bytelength > OLD_PCICC_MAX_MOD_SIZE))) { + return -1; + } stat = &z90crypt.hdware_info->type_mask[PCICC]; - if (stat->st_count > stat->disabled_count + stat->user_disabled_count) { + if (stat->st_count > + (stat->disabled_count + stat->user_disabled_count)) { *dev_type_p = PCICC; return 0; } @@ -1087,7 +1200,7 @@ select_device_type(int *dev_type_p) * Try the selected number, then the selected type (can be ANYDEV) */ static inline int -select_device(int *dev_type_p, int *device_nr_p) +select_device(int *dev_type_p, int *device_nr_p, int bytelength) { int i, indx, devTp, low_count, low_indx; struct device_x *index_p; @@ -1099,9 +1212,9 @@ select_device(int *dev_type_p, int *device_nr_p) dev_ptr = z90crypt.device_p[*device_nr_p]; if (dev_ptr && - dev_ptr->dev_stat != DEV_GONE && - dev_ptr->disabled == 0 && - dev_ptr->user_disabled == 0) { + (dev_ptr->dev_stat != DEV_GONE) && + (dev_ptr->disabled == 0) && + (dev_ptr->user_disabled == 0)) { PDEBUG("selected by number, index = %d\n", *device_nr_p); *dev_type_p = dev_ptr->dev_type; @@ -1111,7 +1224,7 @@ select_device(int *dev_type_p, int *device_nr_p) *device_nr_p = -1; PDEBUG("trying type = %d\n", *dev_type_p); devTp = *dev_type_p; - if (select_device_type(&devTp) == -1) { + if (select_device_type(&devTp, bytelength) == -1) { PDEBUG("failed to select by type\n"); return -1; } @@ -1123,11 +1236,11 @@ select_device(int *dev_type_p, int *device_nr_p) indx = index_p->device_index[i]; dev_ptr = z90crypt.device_p[indx]; if (dev_ptr && - dev_ptr->dev_stat != DEV_GONE && - dev_ptr->disabled == 0 && - dev_ptr->user_disabled == 0 && - devTp == dev_ptr->dev_type && - low_count > dev_ptr->dev_caller_count) { + (dev_ptr->dev_stat != DEV_GONE) && + (dev_ptr->disabled == 0) && + (dev_ptr->user_disabled == 0) && + (devTp == dev_ptr->dev_type) && + (low_count > dev_ptr->dev_caller_count)) { low_count = dev_ptr->dev_caller_count; low_indx = indx; } @@ -1142,12 +1255,13 @@ send_to_crypto_device(struct work_element *we_p) struct caller *caller_p; struct device *device_p; int dev_nr; + int bytelen = ((struct ica_rsa_modexpo *)we_p->buffer)->inputdatalength; if (!we_p->requestptr) return SEN_FATAL_ERROR; caller_p = (struct caller *)we_p->requestptr; dev_nr = we_p->devindex; - if (select_device(&we_p->devtype, &dev_nr) == -1) { + if (select_device(&we_p->devtype, &dev_nr, bytelen) == -1) { if (z90crypt.hdware_info->hdware_mask.st_count != 0) return SEN_RETRY; else @@ -1296,15 +1410,6 @@ z90crypt_process_results(struct work_element *we_p, char __user *buf) static unsigned char NULL_psmid[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -/** - * MIN_MOD_SIZE is a PCICC and PCIXCC limit. - * MAX_PCICC_MOD_SIZE is a hard limit for the PCICC. - * MAX_MOD_SIZE is a hard limit for the PCIXCC and PCICA. - */ -#define MIN_MOD_SIZE 64 -#define MAX_PCICC_MOD_SIZE 128 -#define MAX_MOD_SIZE 256 - /** * Used in device configuration functions */ @@ -1361,7 +1466,8 @@ build_caller(struct work_element *we_p, short function) struct caller *caller_p = (struct caller *)we_p->requestptr; if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && - (we_p->devtype != PCIXCC)) + (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && + (we_p->devtype != CEX2C)) return SEN_NOT_AVAIL; memcpy(caller_p->caller_id, we_p->caller_id, @@ -1393,9 +1499,8 @@ unbuild_caller(struct device *device_p, struct caller *caller_p) return; if (caller_p->caller_liste.next && caller_p->caller_liste.prev) if (!list_empty(&caller_p->caller_liste)) { - list_del(&caller_p->caller_liste); + list_del_init(&caller_p->caller_liste); device_p->dev_caller_count--; - INIT_LIST_HEAD(&caller_p->caller_liste); } memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id)); } @@ -1430,7 +1535,8 @@ get_crypto_request_buffer(struct work_element *we_p) } if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && - (we_p->devtype != PCIXCC) && (we_p->devtype != ANYDEV)) { + (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && + (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) { PRINTK("invalid device type\n"); return SEN_USER_ERROR; } @@ -1494,7 +1600,7 @@ get_crypto_request_buffer(struct work_element *we_p) if (rv != 0) return rv; - if (select_device_type(&we_p->devtype) < 0) + if (select_device_type(&we_p->devtype, mex_p->inputdatalength) < 0) return SEN_NOT_AVAIL; temp_buffer = (unsigned char *)we_p + sizeof(struct work_element) + @@ -1510,13 +1616,19 @@ get_crypto_request_buffer(struct work_element *we_p) function = PCI_FUNC_KEY_ENCRYPT; break; /** - * PCIXCC does all Mod-Expo form with a simple RSA mod-expo + * PCIXCC_MCL2 does all Mod-Expo form with a simple RSA mod-expo * operation, and all CRT forms with a PKCS-1.2 format decrypt. + * PCIXCC_MCL3 and CEX2C do all Mod-Expo and CRT forms with a simple RSA + * mod-expo operation */ - case PCIXCC: - /* Anything less than MIN_MOD_SIZE MUST go to a PCICA */ - if (mex_p->inputdatalength < MIN_MOD_SIZE) - return SEN_NOT_AVAIL; + case PCIXCC_MCL2: + if (we_p->funccode == ICARSAMODEXPO) + function = PCI_FUNC_KEY_ENCRYPT; + else + function = PCI_FUNC_KEY_DECRYPT; + break; + case PCIXCC_MCL3: + case CEX2C: if (we_p->funccode == ICARSAMODEXPO) function = PCI_FUNC_KEY_ENCRYPT; else @@ -1526,14 +1638,6 @@ get_crypto_request_buffer(struct work_element *we_p) * PCICC does everything as a PKCS-1.2 format request */ case PCICC: - /* Anything less than MIN_MOD_SIZE MUST go to a PCICA */ - if (mex_p->inputdatalength < MIN_MOD_SIZE) { - return SEN_NOT_AVAIL; - } - /* Anythings over MAX_PCICC_MOD_SIZE MUST go to a PCICA */ - if (mex_p->inputdatalength > MAX_PCICC_MOD_SIZE) { - return SEN_NOT_AVAIL; - } /* PCICC cannot handle input that is is PKCS#1.1 padded */ if (is_PKCS11_padded(temp_buffer, mex_p->inputdatalength)) { return SEN_NOT_AVAIL; @@ -1593,6 +1697,7 @@ z90crypt_prepare(struct work_element *we_p, unsigned int funccode, rv = -ENODEV; break; case SEN_NOT_AVAIL: + case EGETBUFF: rv = -EGETBUFF; break; default: @@ -1613,14 +1718,14 @@ purge_work_element(struct work_element *we_p) spin_lock_irq(&queuespinlock); list_for_each(lptr, &request_list) { if (lptr == &we_p->liste) { - list_del(lptr); + list_del_init(lptr); requestq_count--; break; } } list_for_each(lptr, &pending_list) { if (lptr == &we_p->liste) { - list_del(lptr); + list_del_init(lptr); pendingq_count--; break; } @@ -1659,14 +1764,13 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid, if ((we_p->status[0] & STAT_FAILED)) { switch (rv) { /** - * EINVAL *after* receive is almost always padding - * error issued by a PCICC or PCIXCC. We convert this - * return value to -EGETBUFF which should trigger a - * fallback to software. + * EINVAL *after* receive is almost always a padding error or + * length error issued by a coprocessor (not an accelerator). + * We convert this return value to -EGETBUFF which should + * trigger a fallback to software. */ case -EINVAL: - if ((we_p->devtype == PCICC) || - (we_p->devtype == PCIXCC)) + if (we_p->devtype != PCICA) rv = -EGETBUFF; break; case -ETIMEOUT: @@ -1710,7 +1814,8 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, unsigned int *reqcnt; struct ica_z90_status *pstat; int ret, i, loopLim, tempstat; - static int deprecated_msg_count = 0; + static int deprecated_msg_count1 = 0; + static int deprecated_msg_count2 = 0; PDEBUG("filp %p (PID %d), cmd 0x%08X\n", filp, PID(), cmd); PDEBUG("cmd 0x%08X: dir %s, size 0x%04X, type 0x%02X, nr 0x%02X\n", @@ -1765,8 +1870,20 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, ret = -EFAULT; break; - case Z90STAT_PCIXCCCOUNT: - tempstat = get_status_PCIXCCcount(); + case Z90STAT_PCIXCCMCL2COUNT: + tempstat = get_status_PCIXCCMCL2count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PCIXCCMCL3COUNT: + tempstat = get_status_PCIXCCMCL3count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_CEX2CCOUNT: + tempstat = get_status_CEX2Ccount(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) ret = -EFAULT; break; @@ -1838,10 +1955,10 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ case ICAZ90STATUS: - if (deprecated_msg_count < 100) { + if (deprecated_msg_count1 < 20) { PRINTK("deprecated call to ioctl (ICAZ90STATUS)!\n"); - deprecated_msg_count++; - if (deprecated_msg_count == 100) + deprecated_msg_count1++; + if (deprecated_msg_count1 == 20) PRINTK("No longer issuing messages related to " "deprecated call to ICAZ90STATUS.\n"); } @@ -1869,6 +1986,21 @@ z90crypt_ioctl(struct inode *inode, struct file *filp, kfree(pstat); break; + /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ + case Z90STAT_PCIXCCCOUNT: + if (deprecated_msg_count2 < 20) { + PRINTK("deprecated ioctl (Z90STAT_PCIXCCCOUNT)!\n"); + deprecated_msg_count2++; + if (deprecated_msg_count2 == 20) + PRINTK("No longer issuing messages about depre" + "cated ioctl Z90STAT_PCIXCCCOUNT.\n"); + } + + tempstat = get_status_PCIXCCcount(); + if (copy_to_user((int *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + case Z90QUIESCE: if (current->euid != 0) { PRINTK("QUIESCE fails: euid %d\n", @@ -1990,8 +2122,12 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, get_status_PCICAcount()); len += sprintf(resp_buff+len, "PCICC count: %d\n", get_status_PCICCcount()); - len += sprintf(resp_buff+len, "PCIXCC count: %d\n", - get_status_PCIXCCcount()); + len += sprintf(resp_buff+len, "PCIXCC MCL2 count: %d\n", + get_status_PCIXCCMCL2count()); + len += sprintf(resp_buff+len, "PCIXCC MCL3 count: %d\n", + get_status_PCIXCCMCL3count()); + len += sprintf(resp_buff+len, "CEX2C count: %d\n", + get_status_CEX2Ccount()); len += sprintf(resp_buff+len, "requestq count: %d\n", get_status_requestq_count()); len += sprintf(resp_buff+len, "pendingq count: %d\n", @@ -1999,7 +2135,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, len += sprintf(resp_buff+len, "Total open handles: %d\n\n", get_status_totalopen_count()); len += sprinthx( - "Online devices: 1 means PCICA, 2 means PCICC, 3 means PCIXCC", + "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), " + "4: PCIXCC (MCL3), 5: CEX2C", resp_buff+len, get_status_status_mask(workarea), Z90CRYPT_NUM_APS); @@ -2171,6 +2308,8 @@ z90crypt_status_write(struct file *file, const char __user *buffer, case '1': case '2': case '3': + case '4': + case '5': j++; break; case 'd': @@ -2228,13 +2367,12 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, dev_ptr = z90crypt.device_p[index]; rv = 0; do { - PDEBUG("Dequeue called for device %d\n", index); if (!dev_ptr || dev_ptr->disabled) { - rv = REC_NO_RESPONSE; + rv = REC_NO_WORK; // a disabled device can't return work break; } if (dev_ptr->dev_self_x != index) { - PRINTK("Corrupt dev ptr in receive_from_AP\n"); + PRINTKC("Corrupt dev ptr\n"); z90crypt.terminating = 1; rv = REC_FATAL_ERROR; break; @@ -2244,6 +2382,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, PRINTK("dev_resp_l = %d, dev_resp_p = %p\n", dev_ptr->dev_resp_l, dev_ptr->dev_resp_p); } else { + PDEBUG("Dequeue called for device %d\n", index); dv = receive_from_AP(index, z90crypt.cdx, dev_ptr->dev_resp_l, dev_ptr->dev_resp_p, psmid); @@ -2283,15 +2422,18 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, if (!memcmp(caller_p->caller_id, psmid, sizeof(caller_p->caller_id))) { if (!list_empty(&caller_p->caller_liste)) { - list_del(ptr); + list_del_init(ptr); dev_ptr->dev_caller_count--; - INIT_LIST_HEAD(&caller_p->caller_liste); break; } } caller_p = 0; } if (!caller_p) { + PRINTKW("Unable to locate PSMID %02X%02X%02X%02X%02X" + "%02X%02X%02X in device list\n", + psmid[0], psmid[1], psmid[2], psmid[3], + psmid[4], psmid[5], psmid[6], psmid[7]); rv = REC_USER_GONE; break; } @@ -2300,22 +2442,22 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, rv = convert_response(dev_ptr->dev_resp_p, caller_p->caller_buf_p, buff_len_p, buff); switch (rv) { + case REC_USE_PCICA: + break; case REC_OPERAND_INV: - PDEBUG("dev %d: user error %d\n", index, rv); + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + PDEBUG("device %d: 'user error' %d\n", index, rv); break; case WRONG_DEVICE_TYPE: case REC_HARDWAR_ERR: case REC_BAD_MESSAGE: - PRINTK("dev %d: hardware error %d\n", - index, rv); + PRINTKW("device %d: hardware error %d\n", index, rv); rv = REC_NO_RESPONSE; break; - case REC_RELEASED: - PDEBUG("dev %d: REC_RELEASED = %d\n", - index, rv); - break; default: - PDEBUG("dev %d: rv = %d\n", index, rv); + PDEBUG("device %d: rv = %d\n", index, rv); break; } } while (0); @@ -2329,6 +2471,7 @@ receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, PRINTK("Zero *buff_len_p\n"); break; case REC_NO_RESPONSE: + PRINTKW("Removing device %d from availability\n", index); remove_device(dev_ptr); break; } @@ -2349,7 +2492,7 @@ helper_send_work(int index) return; requestq_count--; rq_p = list_entry(request_list.next, struct work_element, liste); - list_del(&rq_p->liste); + list_del_init(&rq_p->liste); rq_p->audit[1] |= FP_REMREQUEST; if (rq_p->devtype == SHRT2DEVPTR(index)->dev_type) { rq_p->devindex = SHRT2LONG(index); @@ -2408,7 +2551,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, list_for_each_safe(lptr, tptr, &pending_list) { pq_p = list_entry(lptr, struct work_element, liste); if (!memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id))) { - list_del(lptr); + list_del_init(lptr); pendingq_count--; pq_p->audit[1] |= FP_NOTPENDING; break; @@ -2441,6 +2584,10 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, pq_p->retcode = -EINVAL; pq_p->status[0] |= STAT_FAILED; break; + case REC_USE_PCICA: + pq_p->retcode = -ERESTARTSYS; + pq_p->status[0] |= STAT_FAILED; + break; case REC_NO_RESPONSE: default: if (z90crypt.mask.st_count > 1) @@ -2461,7 +2608,7 @@ helper_handle_work_element(int index, unsigned char psmid[8], int rc, * return TRUE if the work element should be removed from the queue */ static inline int -helper_receive_rc(int index, int *rc_p, int *workavail_p) +helper_receive_rc(int index, int *rc_p) { switch (*rc_p) { case 0: @@ -2469,26 +2616,26 @@ helper_receive_rc(int index, int *rc_p, int *workavail_p) case REC_OPERAND_SIZE: case REC_EVEN_MOD: case REC_INVALID_PAD: - return 1; + case REC_USE_PCICA: + break; case REC_BUSY: case REC_NO_WORK: case REC_EMPTY: case REC_RETRY_DEV: case REC_FATAL_ERROR: - break; + return 0; case REC_NO_RESPONSE: - *workavail_p = 0; break; default: - PRINTK("rc %d, device %d\n", *rc_p, SHRT2LONG(index)); + PRINTK("rc %d, device %d converted to REC_NO_RESPONSE\n", + *rc_p, SHRT2LONG(index)); *rc_p = REC_NO_RESPONSE; - *workavail_p = 0; break; } - return 0; + return 1; } static inline void @@ -2503,21 +2650,18 @@ z90crypt_schedule_reader_timer(void) static void z90crypt_reader_task(unsigned long ptr) { - int workavail, remaining, index, rc, buff_len; + int workavail, index, rc, buff_len; unsigned char psmid[8]; unsigned char __user *resp_addr; static unsigned char buff[1024]; - PDEBUG("jiffies %ld\n", jiffies); - /** * we use workavail = 2 to ensure 2 passes with nothing dequeued before - * exiting the loop. If remaining == 0 after the loop, there is no work - * remaining on the queues. + * exiting the loop. If pendingq_count == 0 after the loop, there is no + * work remaining on the queues. */ resp_addr = 0; workavail = 2; - remaining = 0; buff_len = 0; while (workavail) { workavail--; @@ -2535,7 +2679,7 @@ z90crypt_reader_task(unsigned long ptr) &resp_addr); PDEBUG("Dequeued: rc = %d.\n", rc); - if (helper_receive_rc(index, &rc, &workavail)) { + if (helper_receive_rc(index, &rc)) { if (rc != REC_NO_RESPONSE) { helper_send_work(index); workavail = 2; @@ -2547,19 +2691,14 @@ z90crypt_reader_task(unsigned long ptr) } if (rc == REC_FATAL_ERROR) - remaining = 0; - else if (rc != REC_NO_RESPONSE) - remaining += - SHRT2DEVPTR(index)->dev_caller_count; + PRINTKW("REC_FATAL_ERROR from device %d!\n", + SHRT2LONG(index)); } spin_unlock_irq(&queuespinlock); } - if (remaining) { - spin_lock_irq(&queuespinlock); + if (pendingq_count) z90crypt_schedule_reader_timer(); - spin_unlock_irq(&queuespinlock); - } } static inline void @@ -2606,7 +2745,7 @@ helper_drain_queues(void) pq_p->status[0] |= STAT_FAILED; unbuild_caller(LONG2DEVPTR(pq_p->devindex), (struct caller *)pq_p->requestptr); - list_del(lptr); + list_del_init(lptr); pendingq_count--; pq_p->audit[1] |= FP_NOTPENDING; pq_p->audit[1] |= FP_AWAKENING; @@ -2618,7 +2757,7 @@ helper_drain_queues(void) pq_p = list_entry(lptr, struct work_element, liste); pq_p->retcode = -ENODEV; pq_p->status[0] |= STAT_FAILED; - list_del(lptr); + list_del_init(lptr); requestq_count--; pq_p->audit[1] |= FP_REMREQUEST; pq_p->audit[1] |= FP_AWAKENING; @@ -2640,12 +2779,21 @@ helper_timeout_requests(void) pq_p = list_entry(lptr, struct work_element, liste); if (pq_p->requestsent >= timelimit) break; + PRINTKW("Purging(PQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct caller *)pq_p->requestptr)->caller_id[0], + ((struct caller *)pq_p->requestptr)->caller_id[1], + ((struct caller *)pq_p->requestptr)->caller_id[2], + ((struct caller *)pq_p->requestptr)->caller_id[3], + ((struct caller *)pq_p->requestptr)->caller_id[4], + ((struct caller *)pq_p->requestptr)->caller_id[5], + ((struct caller *)pq_p->requestptr)->caller_id[6], + ((struct caller *)pq_p->requestptr)->caller_id[7]); pq_p->retcode = -ETIMEOUT; pq_p->status[0] |= STAT_FAILED; /* get this off any caller queue it may be on */ unbuild_caller(LONG2DEVPTR(pq_p->devindex), (struct caller *) pq_p->requestptr); - list_del(lptr); + list_del_init(lptr); pendingq_count--; pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_NOTPENDING; @@ -2663,9 +2811,18 @@ helper_timeout_requests(void) pq_p = list_entry(lptr, struct work_element, liste); if (pq_p->requestsent >= timelimit) break; + PRINTKW("Purging(RQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct caller *)pq_p->requestptr)->caller_id[0], + ((struct caller *)pq_p->requestptr)->caller_id[1], + ((struct caller *)pq_p->requestptr)->caller_id[2], + ((struct caller *)pq_p->requestptr)->caller_id[3], + ((struct caller *)pq_p->requestptr)->caller_id[4], + ((struct caller *)pq_p->requestptr)->caller_id[5], + ((struct caller *)pq_p->requestptr)->caller_id[6], + ((struct caller *)pq_p->requestptr)->caller_id[7]); pq_p->retcode = -ETIMEOUT; pq_p->status[0] |= STAT_FAILED; - list_del(lptr); + list_del_init(lptr); requestq_count--; pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_REMREQUEST; @@ -2737,15 +2894,15 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found) { enum hdstat hd_stat; int q_depth, dev_type; - int i, j, k; + int indx, chkdom, numdomains; - q_depth = dev_type = k = 0; - for (i = 0; i < z90crypt.max_count; i++) { + q_depth = dev_type = numdomains = 0; + for (chkdom = 0; chkdom <= 15; cdx_array[chkdom++] = -1); + for (indx = 0; indx < z90crypt.max_count; indx++) { hd_stat = HD_NOT_THERE; - for (j = 0; j <= 15; cdx_array[j++] = -1); - k = 0; - for (j = 0; j <= 15; j++) { - hd_stat = query_online(i, j, MAX_RESET, + numdomains = 0; + for (chkdom = 0; chkdom <= 15; chkdom++) { + hd_stat = query_online(indx, chkdom, MAX_RESET, &q_depth, &dev_type); if (hd_stat == HD_TSQ_EXCEPTION) { z90crypt.terminating = 1; @@ -2753,29 +2910,30 @@ helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found) break; } if (hd_stat == HD_ONLINE) { - cdx_array[k++] = j; - if (*cdx_p == j) { + cdx_array[numdomains++] = chkdom; + if (*cdx_p == chkdom) { *correct_cdx_found = 1; break; } } } - if ((*correct_cdx_found == 1) || (k != 0)) + if ((*correct_cdx_found == 1) || (numdomains != 0)) break; if (z90crypt.terminating) break; } - return k; + return numdomains; } static inline int probe_crypto_domain(int *cdx_p) { int cdx_array[16]; - int correct_cdx_found, k; + char cdx_array_text[53], temp[5]; + int correct_cdx_found, numdomains; correct_cdx_found = 0; - k = helper_scan_devices(cdx_array, cdx_p, &correct_cdx_found); + numdomains = helper_scan_devices(cdx_array, cdx_p, &correct_cdx_found); if (z90crypt.terminating) return TSQ_FATAL_ERROR; @@ -2783,23 +2941,31 @@ probe_crypto_domain(int *cdx_p) if (correct_cdx_found) return 0; - if (k == 0) { - *cdx_p = 0; - return 0; + if (numdomains == 0) { + PRINTKW("Unable to find crypto domain: No devices found\n"); + return Z90C_NO_DEVICES; } - if (k == 1) { - if ((*cdx_p == -1) || !z90crypt.domain_established) { + if (numdomains == 1) { + if (*cdx_p == -1) { *cdx_p = cdx_array[0]; return 0; } - if (*cdx_p != cdx_array[0]) { - PRINTK("incorrect domain: specified = %d, found = %d\n", - *cdx_p, cdx_array[0]); - return Z90C_INCORRECT_DOMAIN; - } + PRINTKW("incorrect domain: specified = %d, found = %d\n", + *cdx_p, cdx_array[0]); + return Z90C_INCORRECT_DOMAIN; + } + + numdomains--; + sprintf(cdx_array_text, "%d", cdx_array[numdomains]); + while (numdomains) { + numdomains--; + sprintf(temp, ", %d", cdx_array[numdomains]); + strcat(cdx_array_text, temp); } + PRINTKW("ambiguous domain detected: specified = %d, found array = %s\n", + *cdx_p, cdx_array_text); return Z90C_AMBIGUOUS_DOMAIN; } @@ -2807,7 +2973,7 @@ static int refresh_z90crypt(int *cdx_p) { int i, j, indx, rv; - struct status local_mask; + static struct status local_mask; struct device *devPtr; unsigned char oldStat, newStat; int return_unchanged; @@ -2818,25 +2984,14 @@ refresh_z90crypt(int *cdx_p) return TSQ_FATAL_ERROR; rv = 0; if (!z90crypt.hdware_info->hdware_mask.st_count && - !z90crypt.domain_established) + !z90crypt.domain_established) { rv = probe_crypto_domain(cdx_p); - if (z90crypt.terminating) - return TSQ_FATAL_ERROR; - if (rv) { - switch (rv) { - case Z90C_AMBIGUOUS_DOMAIN: - PRINTK("ambiguous domain detected\n"); - break; - case Z90C_INCORRECT_DOMAIN: - PRINTK("incorrect domain specified\n"); - break; - default: - PRINTK("probe domain returned %d\n", rv); - break; - } - return rv; - } - if (*cdx_p) { + if (z90crypt.terminating) + return TSQ_FATAL_ERROR; + if (rv == Z90C_NO_DEVICES) + return 0; // try later + if (rv) + return rv; z90crypt.cdx = *cdx_p; z90crypt.domain_established = 1; } @@ -2999,14 +3154,28 @@ create_crypto_device(int index) return rv; } } + if (dev_ptr->dev_type == PCIXCC_UNK) { + rv = probe_PCIXCC_type(dev_ptr); + if (rv) { + PRINTK("rv = %d from probe_PCIXCC_type %d\n", + rv, index); + kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr); + return rv; + } + } deviceType = dev_ptr->dev_type; z90crypt.dev_type_array[index] = deviceType; if (deviceType == PCICA) z90crypt.hdware_info->device_type_array[index] = 1; else if (deviceType == PCICC) z90crypt.hdware_info->device_type_array[index] = 2; - else if (deviceType == PCIXCC) + else if (deviceType == PCIXCC_MCL2) z90crypt.hdware_info->device_type_array[index] = 3; + else if (deviceType == PCIXCC_MCL3) + z90crypt.hdware_info->device_type_array[index] = 4; + else if (deviceType == CEX2C) + z90crypt.hdware_info->device_type_array[index] = 5; else z90crypt.hdware_info->device_type_array[index] = -1; } @@ -3086,7 +3255,7 @@ destroy_z90crypt(void) memset((void *)&z90crypt, 0, sizeof(z90crypt)); } -static unsigned char static_testmsg[] = { +static unsigned char static_testmsg[384] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x43,0x43, @@ -3118,7 +3287,7 @@ probe_device_type(struct device *devPtr) { int rv, dv, i, index, length; unsigned char psmid[8]; - static unsigned char loc_testmsg[384]; + static unsigned char loc_testmsg[sizeof(static_testmsg)]; index = devPtr->dev_self_x; rv = 0; @@ -3212,8 +3381,146 @@ probe_device_type(struct device *devPtr) return rv; } +static unsigned char MCL3_testmsg[] = { +0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, +0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20, +0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, +0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD, +0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22, +0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54, +0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00, +0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C, +0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9, +0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5, +0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01, +0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91, +0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C, +0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96, +0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47, +0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,0xF1,0x3D,0x93,0x53 +}; + +static int +probe_PCIXCC_type(struct device *devPtr) +{ + int rv, dv, i, index, length; + unsigned char psmid[8]; + static unsigned char loc_testmsg[548]; + struct CPRBX *cprbx_p; + + index = devPtr->dev_self_x; + rv = 0; + do { + memcpy(loc_testmsg, MCL3_testmsg, sizeof(MCL3_testmsg)); + length = sizeof(MCL3_testmsg) - 0x0C; + dv = send_to_AP(index, z90crypt.cdx, length, loc_testmsg); + if (dv) { + PDEBUG("dv returned = %d\n", dv); + if (dv == DEV_SEN_EXCEPTION) { + rv = SEN_FATAL_ERROR; + PRINTKC("exception in send to AP %d\n", index); + break; + } + PDEBUG("return value from send_to_AP: %d\n", rv); + switch (dv) { + case DEV_GONE: + PDEBUG("dev %d not available\n", index); + rv = SEN_NOT_AVAIL; + break; + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = SEN_NOT_AVAIL; + break; + case DEV_NO_WORK: + rv = SEN_FATAL_ERROR; + break; + case DEV_BAD_MESSAGE: + rv = SEN_USER_ERROR; + break; + case DEV_QUEUE_FULL: + rv = SEN_QUEUE_FULL; + break; + default: + PRINTK("unknown dv=%d for dev %d\n", dv, index); + rv = SEN_NOT_AVAIL; + break; + } + } + + if (rv) + break; + + for (i = 0; i < 6; i++) { + mdelay(300); + dv = receive_from_AP(index, z90crypt.cdx, + devPtr->dev_resp_l, + devPtr->dev_resp_p, psmid); + PDEBUG("dv returned by DQ = %d\n", dv); + if (dv == DEV_REC_EXCEPTION) { + rv = REC_FATAL_ERROR; + PRINTKC("exception in dequeue %d\n", + index); + break; + } + switch (dv) { + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = REC_EMPTY; + break; + case DEV_NO_WORK: + rv = REC_NO_WORK; + break; + case DEV_BAD_MESSAGE: + case DEV_GONE: + default: + rv = REC_NO_RESPONSE; + break; + } + if ((rv != 0) && (rv != REC_NO_WORK)) + break; + if (rv == 0) + break; + } + if (rv) + break; + cprbx_p = (struct CPRBX *) (devPtr->dev_resp_p + 48); + if ((cprbx_p->ccp_rtcode == 8) && (cprbx_p->ccp_rscode == 33)) { + devPtr->dev_type = PCIXCC_MCL2; + PDEBUG("device %d is MCL2\n", index); + } else { + devPtr->dev_type = PCIXCC_MCL3; + PDEBUG("device %d is MCL3\n", index); + } + } while (0); + /* In a general error case, the card is not marked online */ + return rv; +} + #ifdef Z90CRYPT_USE_HOTPLUG -void +static void z90crypt_hotplug_event(int dev_major, int dev_minor, int action) { #ifdef CONFIG_HOTPLUG @@ -3241,6 +3548,7 @@ z90crypt_hotplug_event(int dev_major, int dev_minor, int action) break; default: BUG(); + break; } envp[3] = major; envp[4] = minor; diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h index 5c0fcfc05..ef8883951 100644 --- a/drivers/s390/net/ctcdbug.h +++ b/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.3 $) + * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $) * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,7 +9,7 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.3 $ $Date: 2004/07/28 12:27:54 $ + * $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $ * * 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 @@ -59,7 +59,7 @@ debug_event(ctc_dbf_##name,level,(void*)(addr),len); \ } while (0) -extern DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf); +DECLARE_PER_CPU(char[256], ctc_dbf_txt_buf); extern debug_info_t *ctc_dbf_setup; extern debug_info_t *ctc_dbf_data; extern debug_info_t *ctc_dbf_trace; diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 6a1cb3f86..fff33b1b8 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.63 2004/07/28 12:27:54 ptiedem Exp $ + * $Id: ctcmain.c,v 1.65 2004/10/27 09:12:48 mschwide Exp $ * * CTC / ESCON network driver * @@ -36,7 +36,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.63 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.65 $ * */ @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,6 @@ #include #include #include -#include #include #include @@ -320,7 +320,7 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.63 $"; + char vbuf[] = "$Revision: 1.65 $"; char *version = vbuf; if (printed) @@ -1224,7 +1224,9 @@ ch_action_setmode(fsm_instance * fi, int event, void *arg) fsm_deltimer(&ch->timer); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); fsm_newstate(fi, CH_STATE_SETUPWAIT); - if (event == CH_EVENT_TIMER) + saveflags = 0; /* avoids compiler warning with + spin_unlock_irqrestore */ + if (event == CH_EVENT_TIMER) // only for timer not yet locked spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0); if (event == CH_EVENT_TIMER) @@ -1335,7 +1337,9 @@ ch_action_haltio(fsm_instance * fi, int event, void *arg) DBF_TEXT(trace, 3, __FUNCTION__); fsm_deltimer(&ch->timer); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); - if (event == CH_EVENT_STOP) + saveflags = 0; /* avoids comp warning with + spin_unlock_irqrestore */ + if (event == CH_EVENT_STOP) // only for STOP not yet locked spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); oldstate = fsm_getstate(fi); fsm_newstate(fi, CH_STATE_TERM); @@ -1508,7 +1512,9 @@ ch_action_restart(fsm_instance * fi, int event, void *arg) fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); oldstate = fsm_getstate(fi); fsm_newstate(fi, CH_STATE_STARTWAIT); - if (event == CH_EVENT_TIMER) + saveflags = 0; /* avoids compiler warning with + spin_unlock_irqrestore */ + if (event == CH_EVENT_TIMER) // only for timer not yet locked spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); rc = ccw_device_halt(ch->cdev, (unsigned long) ch); if (event == CH_EVENT_TIMER) @@ -1674,7 +1680,9 @@ ch_action_txretry(fsm_instance * fi, int event, void *arg) return; } fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch); - if (event == CH_EVENT_TIMER) + saveflags = 0; /* avoids compiler warning with + spin_unlock_irqrestore */ + if (event == CH_EVENT_TIMER) // only for TIMER not yet locked spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags); rc = ccw_device_start(ch->cdev, &ch->ccw[3], diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c index 6290b5c56..a4fda34df 100644 --- a/drivers/s390/net/ctctty.c +++ b/drivers/s390/net/ctctty.c @@ -307,10 +307,7 @@ ctc_tty_tint(ctc_tty_info * info) info->flags &= ~CTC_ASYNC_TX_LINESTAT; if (tty) { - if (wake && (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } return (skb_queue_empty(&info->tx_queue) ? 0 : 1); @@ -492,7 +489,7 @@ ctc_tty_shutdown(ctc_tty_info * info) * - If dialing, abort dial. */ static int -ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) +ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count) { int c; int total = 0; @@ -509,8 +506,6 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou total = -ENODEV; goto ex; } - if (from_user) - down(&info->write_sem); while (1) { struct sk_buff *skb; int skb_res; @@ -529,11 +524,7 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou break; } skb_reserve(skb, skb_res); - if (from_user) - copy_from_user(skb_put(skb, c), - (const u_char __user *)buf, c); - else - memcpy(skb_put(skb, c), buf, c); + memcpy(skb_put(skb, c), buf, c); skb_queue_tail(&info->tx_queue, skb); buf += c; total += c; @@ -543,8 +534,6 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou info->lsr &= ~UART_LSR_TEMT; tasklet_schedule(&info->tasklet); } - if (from_user) - up(&info->write_sem); ex: DBF_TEXT(trace, 6, __FUNCTION__); return total; @@ -589,9 +578,7 @@ ctc_tty_flush_buffer(struct tty_struct *tty) info->lsr |= UART_LSR_TEMT; spin_unlock_irqrestore(&ctc_tty_lock, flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); ex: DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__); return; @@ -1066,8 +1053,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp) skb_queue_purge(&info->tx_queue); info->lsr |= UART_LSR_TEMT; } - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); info->tty = 0; tty->closing = 0; if (info->blocked_open) { diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index 8c63753c3..3a55d5e98 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.40 2004/08/04 12:29:33 cborntra Exp $ + * $Id: iucv.c,v 1.41 2004/08/11 14:54:14 geraldsc Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.40 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.41 $ * */ @@ -355,7 +355,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.40 $"; + char vbuf[] = "$Revision: 1.41 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -2550,9 +2550,9 @@ EXPORT_SYMBOL (iucv_reject); #if 0 EXPORT_SYMBOL (iucv_reply); EXPORT_SYMBOL (iucv_reply_array); -EXPORT_SYMBOL (iucv_reply_prmmsg); EXPORT_SYMBOL (iucv_resume); #endif +EXPORT_SYMBOL (iucv_reply_prmmsg); EXPORT_SYMBOL (iucv_send); #if 0 EXPORT_SYMBOL (iucv_send2way); diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h index 5c0b29aea..198330217 100644 --- a/drivers/s390/net/iucv.h +++ b/drivers/s390/net/iucv.h @@ -63,7 +63,7 @@ debug_event(iucv_dbf_##name,level,(void*)(addr),len); \ } while (0) -extern DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf); +DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf); #define IUCV_DBF_TEXT_(name,level,text...) \ do { \ @@ -231,7 +231,10 @@ typedef struct { uchar iptype; u32 ipmsgid; u32 iptrgcls; - uchar iprmmsg1[4]; + union u2 { + u32 iprmmsg1_u32; + uchar iprmmsg1[4]; + } ln1msg1; union u1 { u32 ipbfln1f; uchar iprmmsg2[4]; diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index cac57951a..0f76e945b 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.85 $ $Date: 2004/08/04 11:05:43 $ + * $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $ * * 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 @@ -59,7 +59,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.85 $" +#define VERSION_LCS_C "$Revision: 1.96 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char debug_buffer[255]; @@ -70,6 +70,7 @@ static char debug_buffer[255]; static void lcs_tasklet(unsigned long); static void lcs_start_kernel_thread(struct lcs_card *card); static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *); +static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *); /** * Debug Facility Stuff @@ -100,9 +101,9 @@ lcs_register_debug_facility(void) return -ENOMEM; } debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_setup, 2); + debug_set_level(lcs_dbf_setup, 4); debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_trace, 2); + debug_set_level(lcs_dbf_trace, 4); return 0; } @@ -190,6 +191,7 @@ lcs_alloc_card(void) return NULL; memset(card, 0, sizeof(struct lcs_card)); card->lan_type = LCS_FRAME_TYPE_AUTO; + card->pkt_seq = 0; card->lancmd_timeout = LCS_LANCMD_TIMEOUT_DEFAULT; /* Allocate io buffers for the read channel. */ rc = lcs_alloc_channel(&card->read); @@ -316,7 +318,106 @@ lcs_setup_write(struct lcs_card *card) init_waitqueue_head(&card->write.wait_q); } +static void +lcs_set_allowed_threads(struct lcs_card *card, unsigned long threads) +{ + unsigned long flags; + + spin_lock_irqsave(&card->mask_lock, flags); + card->thread_allowed_mask = threads; + spin_unlock_irqrestore(&card->mask_lock, flags); + wake_up(&card->wait_q); +} +static inline int +lcs_threads_running(struct lcs_card *card, unsigned long threads) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&card->mask_lock, flags); + rc = (card->thread_running_mask & threads); + spin_unlock_irqrestore(&card->mask_lock, flags); + return rc; +} + +static int +lcs_wait_for_threads(struct lcs_card *card, unsigned long threads) +{ + return wait_event_interruptible(card->wait_q, + lcs_threads_running(card, threads) == 0); +} + +static inline int +lcs_set_thread_start_bit(struct lcs_card *card, unsigned long thread) +{ + unsigned long flags; + + spin_lock_irqsave(&card->mask_lock, flags); + if ( !(card->thread_allowed_mask & thread) || + (card->thread_start_mask & thread) ) { + spin_unlock_irqrestore(&card->mask_lock, flags); + return -EPERM; + } + card->thread_start_mask |= thread; + spin_unlock_irqrestore(&card->mask_lock, flags); + return 0; +} + +static void +lcs_clear_thread_running_bit(struct lcs_card *card, unsigned long thread) +{ + unsigned long flags; + spin_lock_irqsave(&card->mask_lock, flags); + card->thread_running_mask &= ~thread; + spin_unlock_irqrestore(&card->mask_lock, flags); + wake_up(&card->wait_q); +} + +static inline int +__lcs_do_run_thread(struct lcs_card *card, unsigned long thread) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&card->mask_lock, flags); + if (card->thread_start_mask & thread){ + if ((card->thread_allowed_mask & thread) && + !(card->thread_running_mask & thread)){ + rc = 1; + card->thread_start_mask &= ~thread; + card->thread_running_mask |= thread; + } else + rc = -EPERM; + } + spin_unlock_irqrestore(&card->mask_lock, flags); + return rc; +} + +static int +lcs_do_run_thread(struct lcs_card *card, unsigned long thread) +{ + int rc = 0; + wait_event(card->wait_q, + (rc = __lcs_do_run_thread(card, thread)) >= 0); + return rc; +} + +static int +lcs_do_start_thread(struct lcs_card *card, unsigned long thread) +{ + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&card->mask_lock, flags); + LCS_DBF_TEXT_(4, trace, " %02x%02x%02x", + (u8) card->thread_start_mask, + (u8) card->thread_allowed_mask, + (u8) card->thread_running_mask); + rc = (card->thread_start_mask & thread); + spin_unlock_irqrestore(&card->mask_lock, flags); + return rc; +} /** * Initialize channels,card and state machines. @@ -337,34 +438,53 @@ lcs_setup_card(struct lcs_card *card) /* Initialize kernel thread task used for LGW commands. */ INIT_WORK(&card->kernel_thread_starter, (void *)lcs_start_kernel_thread,card); - card->thread_mask = 0; + card->thread_start_mask = 0; + card->thread_allowed_mask = 0; + card->thread_running_mask = 0; + init_waitqueue_head(&card->wait_q); spin_lock_init(&card->lock); spin_lock_init(&card->ipm_lock); + spin_lock_init(&card->mask_lock); #ifdef CONFIG_IP_MULTICAST INIT_LIST_HEAD(&card->ipm_list); #endif INIT_LIST_HEAD(&card->lancmd_waiters); } +static inline void +lcs_clear_multicast_list(struct lcs_card *card) +{ +#ifdef CONFIG_IP_MULTICAST + struct lcs_ipm_list *ipm; + unsigned long flags; + + /* Free multicast list. */ + LCS_DBF_TEXT(3, setup, "clmclist"); + spin_lock_irqsave(&card->ipm_lock, flags); + while (!list_empty(&card->ipm_list)){ + ipm = list_entry(card->ipm_list.next, + struct lcs_ipm_list, list); + list_del(&ipm->list); + if (ipm->ipm_state != LCS_IPM_STATE_SET_REQUIRED){ + spin_unlock_irqrestore(&card->ipm_lock, flags); + lcs_send_delipm(card, ipm); + spin_lock_irqsave(&card->ipm_lock, flags); + } + kfree(ipm); + } + spin_unlock_irqrestore(&card->ipm_lock, flags); +#endif +} /** * Cleanup channels,card and state machines. */ static void lcs_cleanup_card(struct lcs_card *card) { - struct list_head *l, *n; - struct lcs_ipm_list *ipm_list; LCS_DBF_TEXT(3, setup, "cleancrd"); LCS_DBF_HEX(2,setup,&card,sizeof(void*)); -#ifdef CONFIG_IP_MULTICAST - /* Free multicast list. */ - list_for_each_safe(l, n, &card->ipm_list) { - ipm_list = list_entry(l, struct lcs_ipm_list, list); - list_del(&ipm_list->list); - kfree(ipm_list); - } -#endif + if (card->dev != NULL) free_netdev(card->dev); /* Cleanup channels. */ @@ -430,6 +550,7 @@ lcs_stop_channel(struct lcs_channel *channel) return 0; LCS_DBF_TEXT(4,trace,"haltsch"); LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id); + channel->state = CH_STATE_INIT; spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_halt(channel->ccwdev, (addr_t) channel); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); @@ -651,6 +772,44 @@ lcs_get_lancmd(struct lcs_card *card, int count) return buffer; } + +static void +lcs_get_reply(struct lcs_reply *reply) +{ + WARN_ON(atomic_read(&reply->refcnt) <= 0); + atomic_inc(&reply->refcnt); +} + +static void +lcs_put_reply(struct lcs_reply *reply) +{ + WARN_ON(atomic_read(&reply->refcnt) <= 0); + if (atomic_dec_and_test(&reply->refcnt)) { + kfree(reply); + } + +} + +static struct lcs_reply * +lcs_alloc_reply(struct lcs_cmd *cmd) +{ + struct lcs_reply *reply; + + LCS_DBF_TEXT(4, trace, "getreply"); + + reply = kmalloc(sizeof(struct lcs_reply), GFP_ATOMIC); + if (!reply) + return NULL; + memset(reply,0,sizeof(struct lcs_reply)); + atomic_set(&reply->refcnt,1); + reply->sequence_no = cmd->sequence_no; + reply->received = 0; + reply->rc = 0; + init_waitqueue_head(&reply->wait_q); + + return reply; +} + /** * Notifier function for lancmd replies. Called from read irq. */ @@ -665,12 +824,14 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) list_for_each_safe(l, n, &card->lancmd_waiters) { reply = list_entry(l, struct lcs_reply, list); if (reply->sequence_no == cmd->sequence_no) { - list_del(&reply->list); + lcs_get_reply(reply); + list_del_init(&reply->list); if (reply->callback != NULL) reply->callback(card, cmd); reply->received = 1; reply->rc = cmd->return_code; wake_up(&reply->wait_q); + lcs_put_reply(reply); break; } } @@ -683,50 +844,66 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) void lcs_lancmd_timeout(unsigned long data) { - struct lcs_reply *reply; + struct lcs_reply *reply, *list_reply, *r; + unsigned long flags; LCS_DBF_TEXT(4, trace, "timeout"); reply = (struct lcs_reply *) data; - list_del(&reply->list); - reply->received = 1; - reply->rc = -ETIME; - wake_up(&reply->wait_q); + spin_lock_irqsave(&reply->card->lock, flags); + list_for_each_entry_safe(list_reply, r, + &reply->card->lancmd_waiters,list) { + if (reply == list_reply) { + lcs_get_reply(reply); + list_del_init(&reply->list); + spin_unlock_irqrestore(&reply->card->lock, flags); + reply->received = 1; + reply->rc = -ETIME; + wake_up(&reply->wait_q); + lcs_put_reply(reply); + return; + } + } + spin_unlock_irqrestore(&reply->card->lock, flags); } static int lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer, void (*reply_callback)(struct lcs_card *, struct lcs_cmd *)) { - struct lcs_reply reply; + struct lcs_reply *reply; struct lcs_cmd *cmd; struct timer_list timer; + unsigned long flags; int rc; LCS_DBF_TEXT(4, trace, "sendcmd"); cmd = (struct lcs_cmd *) buffer->data; - cmd->sequence_no = ++card->sequence_no; cmd->return_code = 0; - reply.sequence_no = cmd->sequence_no; - reply.callback = reply_callback; - reply.received = 0; - reply.rc = 0; - init_waitqueue_head(&reply.wait_q); - spin_lock(&card->lock); - list_add_tail(&reply.list, &card->lancmd_waiters); - spin_unlock(&card->lock); + cmd->sequence_no = card->sequence_no++; + reply = lcs_alloc_reply(cmd); + if (!reply) + return -ENOMEM; + reply->callback = reply_callback; + reply->card = card; + spin_lock_irqsave(&card->lock, flags); + list_add_tail(&reply->list, &card->lancmd_waiters); + spin_unlock_irqrestore(&card->lock, flags); + buffer->callback = lcs_release_buffer; rc = lcs_ready_buffer(&card->write, buffer); if (rc) return rc; init_timer(&timer); timer.function = lcs_lancmd_timeout; - timer.data = (unsigned long) &reply; + timer.data = (unsigned long) reply; timer.expires = jiffies + HZ*card->lancmd_timeout; add_timer(&timer); - wait_event(reply.wait_q, reply.received); - del_timer(&timer); - LCS_DBF_TEXT_(4, trace, "rc:%d",reply.rc); - return reply.rc ? -EIO : 0; + wait_event(reply->wait_q, reply->received); + del_timer_sync(&timer); + LCS_DBF_TEXT_(4, trace, "rc:%d",reply->rc); + rc = reply->rc; + lcs_put_reply(reply); + return rc ? -EIO : 0; } /** @@ -940,33 +1117,56 @@ lcs_check_multicast_support(struct lcs_card *card) static void lcs_fix_multicast_list(struct lcs_card *card) { - struct list_head *l, *n; - struct lcs_ipm_list *ipm; + struct list_head failed_list; + struct lcs_ipm_list *ipm, *tmp; + unsigned long flags; + int rc; LCS_DBF_TEXT(4,trace, "fixipm"); - spin_lock(&card->ipm_lock); - list_for_each_safe(l, n, &card->ipm_list) { - ipm = list_entry(l, struct lcs_ipm_list, list); + INIT_LIST_HEAD(&failed_list); + spin_lock_irqsave(&card->ipm_lock, flags); +list_modified: + list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){ switch (ipm->ipm_state) { case LCS_IPM_STATE_SET_REQUIRED: - if (lcs_send_setipm(card, ipm)) + /* del from ipm_list so noone else can tamper with + * this entry */ + list_del_init(&ipm->list); + spin_unlock_irqrestore(&card->ipm_lock, flags); + rc = lcs_send_setipm(card, ipm); + spin_lock_irqsave(&card->ipm_lock, flags); + if (rc) { PRINT_INFO("Adding multicast address failed." "Table possibly full!\n"); - else + /* store ipm in failed list -> will be added + * to ipm_list again, so a retry will be done + * during the next call of this function */ + list_add_tail(&ipm->list, &failed_list); + } else { ipm->ipm_state = LCS_IPM_STATE_ON_CARD; - break; + /* re-insert into ipm_list */ + list_add_tail(&ipm->list, &card->ipm_list); + } + goto list_modified; case LCS_IPM_STATE_DEL_REQUIRED: - lcs_send_delipm(card, ipm); list_del(&ipm->list); + spin_unlock_irqrestore(&card->ipm_lock, flags); + lcs_send_delipm(card, ipm); + spin_lock_irqsave(&card->ipm_lock, flags); kfree(ipm); - break; + goto list_modified; case LCS_IPM_STATE_ON_CARD: break; } } + /* re-insert all entries from the failed_list into ipm_list */ + list_for_each_entry(ipm, &failed_list, list) { + list_del_init(&ipm->list); + list_add_tail(&ipm->list, &card->ipm_list); + } + spin_unlock_irqrestore(&card->ipm_lock, flags); if (card->state == DEV_STATE_UP) netif_wake_queue(card->dev); - spin_unlock(&card->ipm_lock); } /** @@ -985,51 +1185,67 @@ lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev) /** * function called by net device to handle multicast address relevant things */ -static int -lcs_register_mc_addresses(void *data) +static inline void +lcs_remove_mc_addresses(struct lcs_card *card, struct in_device *in4_dev) { - struct lcs_card *card; - char buf[MAX_ADDR_LEN]; - struct list_head *l; struct ip_mc_list *im4; - struct in_device *in4_dev; - struct lcs_ipm_list *ipm, *tmp; - - daemonize("regipm"); - LCS_DBF_TEXT(4, trace, "regmulti"); + struct list_head *l; + struct lcs_ipm_list *ipm; + unsigned long flags; + char buf[MAX_ADDR_LEN]; - card = (struct lcs_card *) data; - in4_dev = in_dev_get(card->dev); - if (in4_dev == NULL) - return 0; - read_lock(&in4_dev->lock); - spin_lock(&card->ipm_lock); - /* Check for multicast addresses to be removed. */ + LCS_DBF_TEXT(4, trace, "remmclst"); + spin_lock_irqsave(&card->ipm_lock, flags); list_for_each(l, &card->ipm_list) { ipm = list_entry(l, struct lcs_ipm_list, list); for (im4 = in4_dev->mc_list; im4 != NULL; im4 = im4->next) { lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); - if (memcmp(buf, &ipm->ipm.mac_addr, - LCS_MAC_LENGTH) == 0 && - ipm->ipm.ip_addr == im4->multiaddr) + if ( (ipm->ipm.ip_addr == im4->multiaddr) && + (memcmp(buf, &ipm->ipm.mac_addr, + LCS_MAC_LENGTH) == 0) ) break; } if (im4 == NULL) ipm->ipm_state = LCS_IPM_STATE_DEL_REQUIRED; } - /* Check for multicast addresses to be added. */ + spin_unlock_irqrestore(&card->ipm_lock, flags); +} + +static inline struct lcs_ipm_list * +lcs_check_addr_entry(struct lcs_card *card, struct ip_mc_list *im4, char *buf) +{ + struct lcs_ipm_list *tmp, *ipm = NULL; + struct list_head *l; + unsigned long flags; + + LCS_DBF_TEXT(4, trace, "chkmcent"); + spin_lock_irqsave(&card->ipm_lock, flags); + list_for_each(l, &card->ipm_list) { + tmp = list_entry(l, struct lcs_ipm_list, list); + if ( (tmp->ipm.ip_addr == im4->multiaddr) && + (memcmp(buf, &tmp->ipm.mac_addr, + LCS_MAC_LENGTH) == 0) ) { + ipm = tmp; + break; + } + } + spin_unlock_irqrestore(&card->ipm_lock, flags); + return ipm; +} + +static inline void +lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev) +{ + + struct ip_mc_list *im4; + struct lcs_ipm_list *ipm; + char buf[MAX_ADDR_LEN]; + unsigned long flags; + + LCS_DBF_TEXT(4, trace, "setmclst"); for (im4 = in4_dev->mc_list; im4; im4 = im4->next) { lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev); - ipm = NULL; - list_for_each(l, &card->ipm_list) { - tmp = list_entry(l, struct lcs_ipm_list, list); - if (memcmp(buf, &tmp->ipm.mac_addr, - LCS_MAC_LENGTH) == 0 && - tmp->ipm.ip_addr == im4->multiaddr) { - ipm = tmp; - break; - } - } + ipm = lcs_check_addr_entry(card, im4, buf); if (ipm != NULL) continue; /* Address already in list. */ ipm = (struct lcs_ipm_list *) @@ -1043,12 +1259,37 @@ lcs_register_mc_addresses(void *data) memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH); ipm->ipm.ip_addr = im4->multiaddr; ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED; + spin_lock_irqsave(&card->ipm_lock, flags); list_add(&ipm->list, &card->ipm_list); + spin_unlock_irqrestore(&card->ipm_lock, flags); } - spin_unlock(&card->ipm_lock); - read_unlock(&in4_dev->lock); +} + +static int +lcs_register_mc_addresses(void *data) +{ + struct lcs_card *card; + struct in_device *in4_dev; + + card = (struct lcs_card *) data; + daemonize("regipm"); + + if (!lcs_do_run_thread(card, LCS_SET_MC_THREAD)) + return 0; + LCS_DBF_TEXT(4, trace, "regmulti"); + + in4_dev = in_dev_get(card->dev); + if (in4_dev == NULL) + goto out; + read_lock(&in4_dev->mc_list_lock); + lcs_remove_mc_addresses(card,in4_dev); + lcs_set_mc_addresses(card, in4_dev); + read_unlock(&in4_dev->mc_list_lock); in_dev_put(in4_dev); + lcs_fix_multicast_list(card); +out: + lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD); return 0; } /** @@ -1062,8 +1303,10 @@ lcs_set_multicast_list(struct net_device *dev) LCS_DBF_TEXT(4, trace, "setmulti"); card = (struct lcs_card *) dev->priv; - set_bit(3, &card->thread_mask); - schedule_work(&card->kernel_thread_starter); + + if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) { + schedule_work(&card->kernel_thread_starter); + } } #endif /* CONFIG_IP_MULTICAST */ @@ -1116,6 +1359,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id); LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat); + LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl); /* How far in the ccw chain have we processed? */ if ((channel->state != CH_STATE_INIT) && @@ -1383,8 +1627,6 @@ lcs_detect(struct lcs_card *card) /* start/reset card */ if (card->dev) netif_stop_queue(card->dev); - card->write.state = CH_STATE_INIT; - card->read.state = CH_STATE_INIT; rc = lcs_stop_channels(card); if (rc == 0) { rc = lcs_start_channels(card); @@ -1427,6 +1669,7 @@ lcs_resetcard(struct lcs_card *card) return -EIO; } + /** * LCS Stop card */ @@ -1440,6 +1683,7 @@ lcs_stopcard(struct lcs_card *card) if (card->read.state != CH_STATE_STOPPED && card->write.state != CH_STATE_STOPPED && card->state == DEV_STATE_UP) { + lcs_clear_multicast_list(card); rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP); rc = lcs_send_shutdown(card); } @@ -1459,6 +1703,9 @@ lcs_lgw_startlan_thread(void *data) card = (struct lcs_card *) data; daemonize("lgwstpln"); + + if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD)) + return 0; LCS_DBF_TEXT(4, trace, "lgwstpln"); if (card->dev) netif_stop_queue(card->dev); @@ -1471,6 +1718,7 @@ lcs_lgw_startlan_thread(void *data) } else PRINT_ERR("LCS Startlan for device %s failed!\n", card->dev->name); + lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD); return 0; } @@ -1485,8 +1733,11 @@ lcs_lgw_startup_thread(void *data) struct lcs_card *card; card = (struct lcs_card *) data; - daemonize("lgwstpln"); - LCS_DBF_TEXT(4, trace, "lgwstpln"); + daemonize("lgwstaln"); + + if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD)) + return 0; + LCS_DBF_TEXT(4, trace, "lgwstaln"); if (card->dev) netif_stop_queue(card->dev); rc = lcs_send_startup(card, LCS_INITIATOR_LGW); @@ -1511,6 +1762,7 @@ Done: else PRINT_ERR("LCS Startup for device %s failed!\n", card->dev->name); + lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD); return 0; } @@ -1526,6 +1778,9 @@ lcs_lgw_stoplan_thread(void *data) card = (struct lcs_card *) data; daemonize("lgwstop"); + + if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD)) + return 0; LCS_DBF_TEXT(4, trace, "lgwstop"); if (card->dev) netif_stop_queue(card->dev); @@ -1539,6 +1794,7 @@ lcs_lgw_stoplan_thread(void *data) rc = lcs_resetcard(card); if (rc != 0) rc = lcs_stopcard(card); + lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD); return rc; } @@ -1549,14 +1805,14 @@ static void lcs_start_kernel_thread(struct lcs_card *card) { LCS_DBF_TEXT(5, trace, "krnthrd"); - if (test_and_clear_bit(0, &card->thread_mask)) + if (lcs_do_start_thread(card, LCS_STARTUP_THREAD)) kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD); - if (test_and_clear_bit(1, &card->thread_mask)) + if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD)) kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD); - if (test_and_clear_bit(2, &card->thread_mask)) + if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD)) kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD); #ifdef CONFIG_IP_MULTICAST - if (test_and_clear_bit(3, &card->thread_mask)) + if (lcs_do_start_thread(card, LCS_SET_MC_THREAD)) kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD); #endif } @@ -1571,16 +1827,19 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd) if (cmd->initiator == LCS_INITIATOR_LGW) { switch(cmd->cmd_code) { case LCS_CMD_STARTUP: - set_bit(0, &card->thread_mask); - schedule_work(&card->kernel_thread_starter); + if (!lcs_set_thread_start_bit(card, + LCS_STARTUP_THREAD)) + schedule_work(&card->kernel_thread_starter); break; case LCS_CMD_STARTLAN: - set_bit(1, &card->thread_mask); - schedule_work(&card->kernel_thread_starter); + if (!lcs_set_thread_start_bit(card, + LCS_STARTLAN_THREAD)) + schedule_work(&card->kernel_thread_starter); break; case LCS_CMD_STOPLAN: - set_bit(2, &card->thread_mask); - schedule_work(&card->kernel_thread_starter); + if (!lcs_set_thread_start_bit(card, + LCS_STOPLAN_THREAD)) + schedule_work(&card->kernel_thread_starter); break; default: PRINT_INFO("UNRECOGNIZED LGW COMMAND\n"); @@ -1616,6 +1875,7 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len) skb->protocol = card->lan_type_trans(skb, card->dev); card->stats.rx_bytes += skb_len; card->stats.rx_packets++; + *((__u32 *)skb->cb) = ++card->pkt_seq; netif_rx(skb); } @@ -1953,7 +2213,9 @@ netdev_out: card->dev->set_multicast_list = lcs_set_multicast_list; #endif netif_stop_queue(card->dev); + lcs_set_allowed_threads(card,0xffffffff); if (recover_state == DEV_STATE_RECOVER) { + lcs_set_multicast_list(card->dev); card->dev->flags |= IFF_UP; netif_wake_queue(card->dev); card->state = DEV_STATE_UP; @@ -1982,7 +2244,9 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev) card = (struct lcs_card *)ccwgdev->dev.driver_data; if (!card) return -ENODEV; - + lcs_set_allowed_threads(card, 0); + if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD)) + return -ERESTARTSYS; LCS_DBF_HEX(3, setup, &card, sizeof(void*)); recover_state = card->state; diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 44cf99060..a7f348ef1 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -6,7 +6,7 @@ #include #include -#define VERSION_LCS_H "$Revision: 1.17 $" +#define VERSION_LCS_H "$Revision: 1.19 $" #define LCS_DBF_TEXT(level, name, text) \ do { \ @@ -152,6 +152,12 @@ enum lcs_dev_states { DEV_STATE_RECOVER, }; +enum lcs_threads { + LCS_SET_MC_THREAD = 1, + LCS_STARTLAN_THREAD = 2, + LCS_STOPLAN_THREAD = 4, + LCS_STARTUP_THREAD = 8, +}; /** * LCS struct declarations */ @@ -247,9 +253,11 @@ struct lcs_buffer { struct lcs_reply { struct list_head list; __u16 sequence_no; + atomic_t refcnt; /* Callback for completion notification. */ void (*callback)(struct lcs_card *, struct lcs_cmd *); wait_queue_head_t wait_q; + struct lcs_card *card; int received; int rc; }; @@ -268,6 +276,7 @@ struct lcs_channel { int buf_idx; }; + /** * definition of the lcs card */ @@ -287,7 +296,11 @@ struct lcs_card { int lancmd_timeout; struct work_struct kernel_thread_starter; - unsigned long thread_mask; + spinlock_t mask_lock; + unsigned long thread_start_mask; + unsigned long thread_running_mask; + unsigned long thread_allowed_mask; + wait_queue_head_t wait_q; #ifdef CONFIG_IP_MULTICAST struct list_head ipm_list; @@ -296,6 +309,7 @@ struct lcs_card { __u16 ip_assists_supported; __u16 ip_assists_enabled; __s8 lan_type; + __u32 pkt_seq; __u16 sequence_no; __s16 portno; /* Some info copied from probeinfo */ diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index e95272f1a..16e8e69af 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -58,7 +59,6 @@ #include #include -#include #include #include "iucv.h" diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index eaae2afab..f42624595 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -15,7 +15,8 @@ #include -#include +#include + #include #include #include @@ -23,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.113 $" +#define VERSION_QETH_H "$Revision: 1.124 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -43,7 +44,7 @@ #define QETH_DBF_SETUP_LEN 8 #define QETH_DBF_SETUP_INDEX 3 #define QETH_DBF_SETUP_NR_AREAS 1 -#define QETH_DBF_SETUP_LEVEL 3 +#define QETH_DBF_SETUP_LEVEL 5 #define QETH_DBF_MISC_NAME "qeth_misc" #define QETH_DBF_MISC_LEN 128 @@ -61,13 +62,13 @@ #define QETH_DBF_CONTROL_LEN 256 #define QETH_DBF_CONTROL_INDEX 3 #define QETH_DBF_CONTROL_NR_AREAS 2 -#define QETH_DBF_CONTROL_LEVEL 2 +#define QETH_DBF_CONTROL_LEVEL 5 #define QETH_DBF_TRACE_NAME "qeth_trace" #define QETH_DBF_TRACE_LEN 8 #define QETH_DBF_TRACE_INDEX 2 #define QETH_DBF_TRACE_NR_AREAS 2 -#define QETH_DBF_TRACE_LEVEL 3 +#define QETH_DBF_TRACE_LEVEL 5 #define QETH_DBF_SENSE_NAME "qeth_sense" #define QETH_DBF_SENSE_LEN 64 @@ -91,7 +92,7 @@ debug_event(qeth_dbf_##name,level,(void*)(addr),len); \ } while (0) -extern DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf); +DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf); #define QETH_DBF_TEXT_(name,level,text...) \ do { \ @@ -329,12 +330,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) #define QETH_WATERMARK_PACK_FUZZ 1 #define QETH_IP_HEADER_SIZE 40 -/* VLAN defines */ -#define QETH_EXT_HDR_VLAN_FRAME 0x01 -#define QETH_EXT_HDR_TOKEN_ID 0x02 -#define QETH_EXT_HDR_INCLUDE_VLAN_TAG 0x04 -struct qeth_hdr { +struct qeth_hdr_layer3 { __u8 id; __u8 flags; __u16 inbound_checksum; @@ -347,6 +344,26 @@ struct qeth_hdr { __u8 dest_addr[16]; } __attribute__ ((packed)); +struct qeth_hdr_layer2 { + __u8 id; + __u8 flags[3]; + __u8 port_no; + __u8 hdr_length; + __u16 pkt_length; + __u16 seq_no; + __u16 vlan_id; + __u32 reserved; + __u8 reserved2[16]; +} __attribute__ ((packed)); + +struct qeth_hdr { + union { + struct qeth_hdr_layer2 l2; + struct qeth_hdr_layer3 l3; + } hdr; +} __attribute__ ((packed)); + + /* flags for qeth_hdr.flags */ #define QETH_HDR_PASSTHRU 0x10 #define QETH_HDR_IPV6 0x80 @@ -359,11 +376,24 @@ enum qeth_cast_flags { QETH_CAST_NOCAST = 0x00, }; +enum qeth_layer2_frame_flags { + QETH_LAYER2_FLAG_MULTICAST = 0x01, + QETH_LAYER2_FLAG_BROADCAST = 0x02, + QETH_LAYER2_FLAG_UNICAST = 0x04, + QETH_LAYER2_FLAG_VLAN = 0x10, +}; + +enum qeth_header_ids { + QETH_HEADER_TYPE_LAYER3 = 0x01, + QETH_HEADER_TYPE_LAYER2 = 0x02, +}; /* flags for qeth_hdr.ext_flags */ -#define QETH_HDR_EXT_VLAN_FRAME 0x01 -#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10 -#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20 -#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08 +#define QETH_HDR_EXT_VLAN_FRAME 0x01 +#define QETH_HDR_EXT_TOKEN_ID 0x02 +#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04 +#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08 +#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10 +#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20 static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale) @@ -525,6 +555,7 @@ enum qeth_ip_types { QETH_IP_TYPE_NORMAL, QETH_IP_TYPE_VIPA, QETH_IP_TYPE_RXIP, + QETH_IP_TYPE_DEL_ALL_MC, }; enum qeth_cmd_buffer_state { @@ -645,6 +676,7 @@ struct qeth_card_info { __u16 func_level; char mcl_level[QETH_MCL_LENGTH + 1]; int guestlan; + int layer2_mac_registered; int portname_required; int portno; char portname[9]; @@ -672,6 +704,7 @@ struct qeth_card_options { int fake_broadcast; int add_hhlen; int fake_ll; + int layer2; }; /* @@ -679,8 +712,7 @@ struct qeth_card_options { */ enum qeth_threads { QETH_SET_IP_THREAD = 1, - QETH_SET_MC_THREAD = 2, - QETH_RECOVER_THREAD = 4, + QETH_RECOVER_THREAD = 2, }; struct qeth_card { @@ -714,7 +746,7 @@ struct qeth_card { volatile unsigned long thread_running_mask; spinlock_t ip_lock; struct list_head ip_list; - struct list_head ip_tbd_list; + struct list_head *ip_tbd_list; struct qeth_ipato ipato; struct list_head cmd_waiter_list; /* QDIO buffer handling */ @@ -779,9 +811,11 @@ qeth_get_hlen(__u8 link_type) } inline static unsigned short -qeth_get_netdev_flags(int cardtype) +qeth_get_netdev_flags(struct qeth_card *card) { - switch (cardtype) { + if (card->options.layer2) + return 0; + switch (card->info.type) { case QETH_CARD_TYPE_IQD: return IFF_NOARP; #ifdef CONFIG_QETH_IPV6 diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 17f0f67d8..0ec53f327 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.170 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.130 $ $Date: 2004/08/05 11:21:50 $ + * $Revision: 1.170 $ $Date: 2004/11/17 09:54:06 $ * * 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 @@ -29,7 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /*** * eye catcher; just for debugging purposes */ @@ -73,12 +72,13 @@ qeth_eyecatcher(void) #include #include #include +#include #include "qeth.h" #include "qeth_mpc.h" #include "qeth_fs.h" -#define VERSION_QETH_C "$Revision: 1.130 $" +#define VERSION_QETH_C "$Revision: 1.170 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -159,6 +159,9 @@ qeth_set_online(struct ccwgroup_device *); static struct qeth_ipaddr * qeth_get_addr_buffer(enum qeth_prot_versions); +static void +qeth_set_multicast_list(struct net_device *); + static void qeth_notify_processes(void) { @@ -196,7 +199,7 @@ qeth_notifier_register(struct task_struct *p, int signum) { struct qeth_notify_list_struct *n_entry; - QETH_DBF_TEXT(trace, 2, "notreg"); + /*check first if entry already exists*/ spin_lock(&qeth_notify_lock); list_for_each_entry(n_entry, &qeth_notify_list, list) { @@ -249,6 +252,7 @@ qeth_free_card(struct qeth_card *card) free_netdev(card->dev); qeth_clear_ip_list(card, 0, 0); qeth_clear_ipato_list(card); + kfree(card->ip_tbd_list); qeth_free_qdio_buffers(card); kfree(card); } @@ -660,7 +664,10 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) struct qeth_ipaddr *tmp, *t; int found = 0; - list_for_each_entry_safe(tmp, t, &card->ip_tbd_list, entry) { + list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) { + if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && + (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) + return 0; if ((tmp->proto == QETH_PROT_IPV4) && (addr->proto == QETH_PROT_IPV4) && (tmp->type == addr->type) && @@ -692,14 +699,18 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) } return 0; } else { - if (addr->users == 0) - addr->users += add? 1:-1; - if (add && (addr->type == QETH_IP_TYPE_NORMAL) && - qeth_is_addr_covered_by_ipato(card, addr)){ - QETH_DBF_TEXT(trace, 2, "tkovaddr"); - addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; + if (addr->type == QETH_IP_TYPE_DEL_ALL_MC) + list_add(&addr->entry, card->ip_tbd_list); + else { + if (addr->users == 0) + addr->users += add? 1:-1; + if (add && (addr->type == QETH_IP_TYPE_NORMAL) && + qeth_is_addr_covered_by_ipato(card, addr)){ + QETH_DBF_TEXT(trace, 2, "tkovaddr"); + addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; + } + list_add_tail(&addr->entry, card->ip_tbd_list); } - list_add_tail(&addr->entry, &card->ip_tbd_list); return 1; } } @@ -717,8 +728,8 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) if (addr->proto == QETH_PROT_IPV4) QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); else { - QETH_DBF_HEX(trace,4,&addr->u.a6.addr,4); - QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+4,4); + QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); + QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); } spin_lock_irqsave(&card->ip_lock, flags); rc = __qeth_insert_ip_todo(card, addr, 0); @@ -736,8 +747,8 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) if (addr->proto == QETH_PROT_IPV4) QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); else { - QETH_DBF_HEX(trace,4,&addr->u.a6.addr,4); - QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+4,4); + QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); + QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); } spin_lock_irqsave(&card->ip_lock, flags); rc = __qeth_insert_ip_todo(card, addr, 1); @@ -745,19 +756,21 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) return rc; } -static void -qeth_reinsert_todos(struct qeth_card *card, struct list_head *todos) +static inline void +__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) { - struct qeth_ipaddr *todo, *tmp; + struct qeth_ipaddr *addr, *tmp; + int rc; - list_for_each_entry_safe(todo, tmp, todos, entry){ - list_del_init(&todo->entry); - if (todo->users < 0) { - if (!qeth_delete_ip(card, todo)) - kfree(todo); - } else { - if (!qeth_add_ip(card, todo)) - kfree(todo); + list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { + if (addr->is_multicast) { + spin_unlock_irqrestore(&card->ip_lock, *flags); + rc = qeth_deregister_addr_entry(card, addr); + spin_lock_irqsave(&card->ip_lock, *flags); + if (!rc) { + list_del(&addr->entry); + kfree(addr); + } } } } @@ -765,7 +778,7 @@ qeth_reinsert_todos(struct qeth_card *card, struct list_head *todos) static void qeth_set_ip_addr_list(struct qeth_card *card) { - struct list_head failed_todos; + struct list_head *tbd_list; struct qeth_ipaddr *todo, *addr; unsigned long flags; int rc; @@ -773,13 +786,25 @@ qeth_set_ip_addr_list(struct qeth_card *card) QETH_DBF_TEXT(trace, 2, "sdiplist"); QETH_DBF_HEX(trace, 2, &card, sizeof(void *)); - INIT_LIST_HEAD(&failed_todos); - spin_lock_irqsave(&card->ip_lock, flags); - while (!list_empty(&card->ip_tbd_list)) { - todo = list_entry(card->ip_tbd_list.next, - struct qeth_ipaddr, entry); - list_del_init(&todo->entry); + tbd_list = card->ip_tbd_list; + card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); + if (!card->ip_tbd_list) { + QETH_DBF_TEXT(trace, 0, "silnomem"); + card->ip_tbd_list = tbd_list; + spin_unlock_irqrestore(&card->ip_lock, flags); + return; + } else + INIT_LIST_HEAD(card->ip_tbd_list); + + while (!list_empty(tbd_list)){ + todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry); + list_del(&todo->entry); + if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){ + __qeth_delete_all_mc(card, &flags); + kfree(todo); + continue; + } rc = __qeth_ref_ip_on_card(card, todo, &addr); if (rc == 0) { /* nothing to be done; only adjusted refcount */ @@ -792,24 +817,22 @@ qeth_set_ip_addr_list(struct qeth_card *card) if (!rc) list_add_tail(&todo->entry, &card->ip_list); else - list_add_tail(&todo->entry, &failed_todos); + kfree(todo); } else if (rc == -1) { /* on-card entry to be removed */ list_del_init(&addr->entry); spin_unlock_irqrestore(&card->ip_lock, flags); rc = qeth_deregister_addr_entry(card, addr); spin_lock_irqsave(&card->ip_lock, flags); - if (!rc) { + if (!rc) kfree(addr); - kfree(todo); - } else { + else list_add_tail(&addr->entry, &card->ip_list); - list_add_tail(&todo->entry, &failed_todos); - } + kfree(todo); } } spin_unlock_irqrestore(&card->ip_lock, flags); - qeth_reinsert_todos(card, &failed_todos); + kfree(tbd_list); } static void qeth_delete_mc_addresses(struct qeth_card *); @@ -887,28 +910,7 @@ qeth_do_run_thread(struct qeth_card *card, unsigned long thread) } static int -qeth_register_mc_addresses(void *ptr) -{ - struct qeth_card *card; - - card = (struct qeth_card *) ptr; - daemonize("qeth_reg_mcaddrs"); - QETH_DBF_TEXT(trace,4,"regmcth1"); - if (!qeth_do_run_thread(card, QETH_SET_MC_THREAD)) - return 0; - QETH_DBF_TEXT(trace,4,"regmcth2"); - qeth_delete_mc_addresses(card); - qeth_add_multicast_ipv4(card); -#ifdef CONFIG_QETH_IPV6 - qeth_add_multicast_ipv6(card); -#endif - qeth_set_ip_addr_list(card); - qeth_clear_thread_running_bit(card, QETH_SET_MC_THREAD); - return 0; -} - -static int -qeth_register_ip_address(void *ptr) +qeth_register_ip_addresses(void *ptr) { struct qeth_card *card; @@ -988,9 +990,7 @@ qeth_start_kernel_thread(struct qeth_card *card) return; if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) - kernel_thread(qeth_register_ip_address, (void *) card, SIGCHLD); - if (qeth_do_start_thread(card, QETH_SET_MC_THREAD)) - kernel_thread(qeth_register_mc_addresses, (void *)card,SIGCHLD); + kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) kernel_thread(qeth_recover, (void *) card, SIGCHLD); } @@ -1009,6 +1009,7 @@ qeth_set_intial_options(struct qeth_card *card) card->options.fake_broadcast = 0; card->options.add_hhlen = DEFAULT_ADD_HHLEN; card->options.fake_ll = 0; + card->options.layer2 = 0; } /** @@ -1040,7 +1041,12 @@ qeth_setup_card(struct qeth_card *card) INIT_WORK(&card->kernel_thread_starter, (void *)qeth_start_kernel_thread,card); INIT_LIST_HEAD(&card->ip_list); - INIT_LIST_HEAD(&card->ip_tbd_list); + card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); + if (!card->ip_tbd_list) { + QETH_DBF_TEXT(setup, 0, "iptbdnom"); + return -ENOMEM; + } + INIT_LIST_HEAD(card->ip_tbd_list); INIT_LIST_HEAD(&card->cmd_waiter_list); init_waitqueue_head(&card->wait_q); /* intial options */ @@ -1574,9 +1580,8 @@ qeth_reset_ip_addresses(struct qeth_card *card) QETH_DBF_TEXT(trace, 2, "rstipadd"); qeth_clear_ip_list(card, 0, 1); - if ( (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) || - (qeth_set_thread_start_bit(card, QETH_SET_MC_THREAD) == 0) ) - schedule_work(&card->kernel_thread_starter); + /* this function will also schedule the SET_IP_THREAD */ + qeth_set_multicast_list(card->dev); } static struct qeth_ipa_cmd * @@ -1599,10 +1604,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) card->info.if_name, card->info.chpid); card->lan_online = 0; - if (netif_carrier_ok(card->dev)) { - netif_carrier_off(card->dev); - netif_stop_queue(card->dev); - } + netif_carrier_off(card->dev); return NULL; case IPA_CMD_STARTLAN: PRINT_INFO("Link reestablished on %s " @@ -1611,10 +1613,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) card->info.if_name, card->info.chpid); card->lan_online = 1; - if (!netif_carrier_ok(card->dev)) { - netif_carrier_on(card->dev); - netif_wake_queue(card->dev); - } + netif_carrier_on(card->dev); qeth_reset_ip_addresses(card); return NULL; case IPA_CMD_REGISTER_LOCAL_ADDR: @@ -1814,10 +1813,18 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, void *reply_param) { int rc; + char prot_type; QETH_DBF_TEXT(trace,4,"sendipa"); memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); + + if (card->options.layer2) + prot_type = QETH_PROT_LAYER2; + else + prot_type = QETH_PROT_TCPIP; + + memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1); memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); @@ -1950,6 +1957,7 @@ static int qeth_ulp_enable(struct qeth_card *card) { int rc; + char prot_type; struct qeth_cmd_buffer *iob; /*FIXME: trace view callbacks*/ @@ -1960,7 +1968,12 @@ qeth_ulp_enable(struct qeth_card *card) *(QETH_ULP_ENABLE_LINKNUM(iob->data)) = (__u8) card->info.portno; + if (card->options.layer2) + prot_type = QETH_PROT_LAYER2; + else + prot_type = QETH_PROT_TCPIP; + memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1); memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data), &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data), @@ -2083,7 +2096,11 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, *hdr = element->addr + offset; offset += sizeof(struct qeth_hdr); - skb_len = (*hdr)->length; + if (card->options.layer2) + skb_len = (*hdr)->hdr.l2.pkt_length; + else + skb_len = (*hdr)->hdr.l3.length; + if (!skb_len) return NULL; if (card->options.fake_ll){ @@ -2133,10 +2150,10 @@ no_mem: static inline unsigned short qeth_type_trans(struct sk_buff *skb, struct net_device *dev) { - struct ethhdr *eth; struct qeth_card *card; + struct ethhdr *eth; - QETH_DBF_TEXT(trace,5,"typtrans"); + QETH_DBF_TEXT(trace,6,"typtrans"); card = (struct qeth_card *)dev->priv; #ifdef CONFIG_TR @@ -2144,19 +2161,18 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) (card->info.link_type == QETH_LINK_TYPE_LANE_TR)) return tr_type_trans(skb,dev); #endif /* CONFIG_TR */ - skb->mac.raw = skb->data; - skb_pull(skb, ETH_ALEN * 2 + sizeof (short)); - eth = skb->mac.ethernet; + skb_pull(skb, ETH_HLEN ); + eth = eth_hdr(skb); if (*eth->h_dest & 1) { if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; - } else { + } else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) skb->pkt_type = PACKET_OTHERHOST; - } + if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; if (*(unsigned short *) (skb->data) == 0xFFFF) @@ -2205,8 +2221,8 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); } /* the source MAC address */ - if (hdr->ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) - memcpy(fake_hdr->h_source, &hdr->dest_addr[2], ETH_ALEN); + if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) + memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN); else memset(fake_hdr->h_source, 0, ETH_ALEN); /* the protocol */ @@ -2220,28 +2236,52 @@ qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, #ifdef CONFIG_QETH_VLAN u16 *vlan_tag; - if (hdr->ext_flags & QETH_HDR_EXT_VLAN_FRAME) { + if (hdr->hdr.l3.ext_flags & + (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { vlan_tag = (u16 *) skb_push(skb, VLAN_HLEN); - *vlan_tag = hdr->vlan_id; + *vlan_tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? + hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); *(vlan_tag + 1) = skb->protocol; skb->protocol = __constant_htons(ETH_P_8021Q); } #endif /* CONFIG_QETH_VLAN */ } +static inline __u16 +qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ + unsigned short vlan_id = 0; + + skb->pkt_type = PACKET_HOST; + if (card->options.checksum_type == NO_CHECKSUMMING) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; +#ifdef CONFIG_QETH_VLAN + if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) { + skb_pull(skb, VLAN_HLEN); + vlan_id = hdr->hdr.l2.vlan_id; + } +#endif + skb->protocol = qeth_type_trans(skb, skb->dev); + return vlan_id; +} + static inline void qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { #ifdef CONFIG_QETH_IPV6 - if (hdr->flags & QETH_HDR_PASSTHRU){ + if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { + skb->pkt_type = PACKET_HOST; skb->protocol = qeth_type_trans(skb, card->dev); return; } #endif /* CONFIG_QETH_IPV6 */ - skb->protocol = htons((hdr->flags & QETH_HDR_IPV6)? ETH_P_IPV6 : + skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : ETH_P_IP); - switch (hdr->flags & QETH_HDR_CAST_MASK){ + switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK){ case QETH_CAST_UNICAST: skb->pkt_type = PACKET_HOST; break; @@ -2258,13 +2298,14 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, default: skb->pkt_type = PACKET_HOST; } + qeth_rebuild_skb_vlan(card, skb, hdr); if (card->options.fake_ll) qeth_rebuild_skb_fake_ll(card, skb, hdr); else skb->mac.raw = skb->data; skb->ip_summed = card->options.checksum_type; if (card->options.checksum_type == HW_CHECKSUMMING){ - if ( (hdr->ext_flags & + if ( (hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_CSUM_HDR_REQ | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == (QETH_HDR_EXT_CSUM_HDR_REQ | @@ -2273,7 +2314,6 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, else skb->ip_summed = SW_CHECKSUMMING; } - qeth_rebuild_skb_vlan(card, skb, hdr); } static inline void @@ -2281,10 +2321,11 @@ qeth_process_inbound_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf, int index) { struct qdio_buffer_element *element; - int offset; struct sk_buff *skb; struct qeth_hdr *hdr; + int offset; int rxrc; + __u16 vlan_tag = 0; /* get first element of current buffer */ element = (struct qdio_buffer_element *)&buf->buffer->element[0]; @@ -2293,14 +2334,22 @@ qeth_process_inbound_buffer(struct qeth_card *card, card->perf_stats.bufs_rec++; #endif while((skb = qeth_get_next_skb(card, buf->buffer, &element, - &offset, &hdr))){ - qeth_rebuild_skb(card, skb, hdr); + &offset, &hdr))) { + skb->dev = card->dev; + if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) + vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); + else + qeth_rebuild_skb(card, skb, hdr); /* is device UP ? */ if (!(card->dev->flags & IFF_UP)){ dev_kfree_skb_any(skb); continue; } - skb->dev = card->dev; +#ifdef CONFIG_QETH_VLAN + if (vlan_tag) + vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); + else +#endif rxrc = netif_rx(skb); card->dev->last_rx = jiffies; card->stats.rx_packets++; @@ -2758,7 +2807,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, } atomic_sub(count, &queue->used_buffers); /* check if we need to do something on this outbound queue */ - qeth_check_outbound_queue(queue); + if (card->info.type != QETH_CARD_TYPE_IQD) + qeth_check_outbound_queue(queue); netif_wake_queue(card->dev); #ifdef CONFIG_QETH_PERF_STATS @@ -3332,13 +3382,16 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb==NULL) { card->stats.tx_dropped++; card->stats.tx_errors++; - return -EIO; + /* return OK; otherwise ksoftirqd goes to 100% */ + return NETDEV_TX_OK; } - if ((card->state != CARD_STATE_UP) || !netif_carrier_ok(dev)) { + if ((card->state != CARD_STATE_UP) || !card->lan_online) { card->stats.tx_dropped++; card->stats.tx_errors++; card->stats.tx_carrier_errors++; - return -EIO; + dev_kfree_skb_any(skb); + /* return OK; otherwise ksoftirqd goes to 100% */ + return NETDEV_TX_OK; } #ifdef CONFIG_QETH_PERF_STATS card->perf_stats.outbound_cnt++; @@ -3349,8 +3402,18 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * got our own synchronization on queues we can keep the stack's * queue running. */ - if ((rc = qeth_send_packet(card, skb))) - netif_stop_queue(dev); + if ((rc = qeth_send_packet(card, skb))){ + if (rc == -EBUSY) { + netif_stop_queue(dev); + rc = NETDEV_TX_BUSY; + } else { + card->stats.tx_errors++; + card->stats.tx_dropped++; + dev_kfree_skb_any(skb); + /* set to OK; otherwise ksoftirqd goes to 100% */ + rc = NETDEV_TX_OK; + } + } #ifdef CONFIG_QETH_PERF_STATS card->perf_stats.outbound_time += qeth_get_micros() - @@ -3441,6 +3504,11 @@ qeth_open(struct net_device *dev) if (card->state != CARD_STATE_SOFTSETUP) return -ENODEV; + if ( (card->options.layer2) && + (!card->info.layer2_mac_registered)) { + QETH_DBF_TEXT(trace,4,"nomacadr"); + return -EPERM; + } card->dev->flags |= IFF_UP; netif_start_queue(dev); card->data.state = CH_STATE_UP; @@ -3449,7 +3517,6 @@ qeth_open(struct net_device *dev) if (!card->lan_online){ if (netif_carrier_ok(dev)) netif_carrier_off(dev); - netif_stop_queue(dev); } return 0; } @@ -3490,12 +3557,12 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) else if (skb->protocol == ETH_P_IP) return ((skb->nh.raw[16] & 0xf0) == 0xe0) ? RTN_MULTICAST : 0; /* ... */ - if (!memcmp(skb->nh.raw, skb->dev->broadcast, 6)) + if (!memcmp(skb->data, skb->dev->broadcast, 6)) return RTN_BROADCAST; else { u16 hdr_mac; - hdr_mac = *((u16 *)skb->nh.raw); + hdr_mac = *((u16 *)skb->data); /* tr multicast? */ switch (card->info.link_type) { case QETH_LINK_TYPE_HSTR: @@ -3580,7 +3647,8 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, *skb = new_skb; } #ifdef CONFIG_QETH_VLAN - if (card->vlangrp && vlan_tx_tag_present(*skb) && (ipv == 6)){ + if (card->vlangrp && vlan_tx_tag_present(*skb) && + ((ipv == 6) || card->options.layer2) ) { /* * Move the mac addresses (6 bytes src, 6 bytes dest) * to the beginning of the new header. We are using three @@ -3590,14 +3658,13 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, memcpy((*skb)->data, (*skb)->data + 4, 4); memcpy((*skb)->data + 4, (*skb)->data + 8, 4); memcpy((*skb)->data + 8, (*skb)->data + 12, 4); - tag = (u16 *) (*skb)->data + 12; + tag = (u16 *)((*skb)->data + 12); /* * first two bytes = ETH_P_8021Q (0x8100) * second two bytes = VLANID */ *tag = __constant_htons(ETH_P_8021Q); - *(tag + 1) = vlan_tx_tag_get(*skb); - *(tag + 1) = htons(*(tag + 1)); + *(tag + 1) = htons(vlan_tx_tag_get(*skb)); } #endif *hdr = (struct qeth_hdr *) skb_push(*skb, sizeof(struct qeth_hdr)); @@ -3640,51 +3707,121 @@ qeth_get_qeth_hdr_flags6(int cast_type) return ct | QETH_CAST_UNICAST; } +static inline void +qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, + struct sk_buff *skb) +{ + __u16 hdr_mac; + + if (!memcmp(skb->data+QETH_HEADER_SIZE, + skb->dev->broadcast,6)) { /* broadcast? */ + *(__u32 *)hdr->hdr.l2.flags |= + QETH_LAYER2_FLAG_BROADCAST << 8; + return; + } + hdr_mac=*((__u16*)skb->data); + /* tr multicast? */ + switch (card->info.link_type) { + case QETH_LINK_TYPE_HSTR: + case QETH_LINK_TYPE_LANE_TR: + if ((hdr_mac == QETH_TR_MAC_NC) || + (hdr_mac == QETH_TR_MAC_C) ) + *(__u32 *)hdr->hdr.l2.flags |= + QETH_LAYER2_FLAG_MULTICAST << 8; + else + *(__u32 *)hdr->hdr.l2.flags |= + QETH_LAYER2_FLAG_UNICAST << 8; + break; + /* eth or so multicast? */ + default: + if ( (hdr_mac==QETH_ETH_MAC_V4) || + (hdr_mac==QETH_ETH_MAC_V6) ) + *(__u32 *)hdr->hdr.l2.flags |= + QETH_LAYER2_FLAG_MULTICAST << 8; + else + *(__u32 *)hdr->hdr.l2.flags |= + QETH_LAYER2_FLAG_UNICAST << 8; + } +} + +static inline void +qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, + struct sk_buff *skb, int cast_type) +{ + memset(hdr, 0, sizeof(struct qeth_hdr)); + hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; + + /* set byte 0 to "0x02" and byte 3 to casting flags */ + if (cast_type==RTN_MULTICAST) + *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_MULTICAST << 8; + else if (cast_type==RTN_BROADCAST) + *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_BROADCAST << 8; + else + qeth_layer2_get_packet_type(card, hdr, skb); + + hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE; +#ifdef CONFIG_QETH_VLAN + /* VSWITCH relies on the VLAN + * information to be present in + * the QDIO header */ + if ((card->vlangrp != NULL) && + vlan_tx_tag_present(skb)) { + *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_VLAN << 8; + hdr->hdr.l2.vlan_id = vlan_tx_tag_get(skb); + } +#endif +} + static inline void qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int ipv, int cast_type) { - hdr->id = 1; - hdr->ext_flags = 0; - QETH_DBF_TEXT(trace, 6, "fillhdr"); + + if (card->options.layer2) { + qeth_layer2_fill_header(card, hdr, skb, cast_type); + return; + } + hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; + hdr->hdr.l3.ext_flags = 0; #ifdef CONFIG_QETH_VLAN /* * before we're going to overwrite this location with next hop ip. * v6 uses passthrough, v4 sets the tag in the QDIO header. */ if (card->vlangrp && vlan_tx_tag_present(skb)) { - hdr->ext_flags = (ipv == 4)? QETH_EXT_HDR_VLAN_FRAME : - QETH_EXT_HDR_INCLUDE_VLAN_TAG; - hdr->vlan_id = vlan_tx_tag_get(skb); + hdr->hdr.l3.ext_flags = (ipv == 4) ? + QETH_HDR_EXT_VLAN_FRAME : + QETH_HDR_EXT_INCLUDE_VLAN_TAG; + hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb); } #endif /* CONFIG_QETH_VLAN */ - hdr->length = skb->len - sizeof(struct qeth_hdr); + hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr); if (ipv == 4) { /* IPv4 */ - hdr->flags = qeth_get_qeth_hdr_flags4(cast_type); - memset(hdr->dest_addr, 0, 12); + hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags4(cast_type); + memset(hdr->hdr.l3.dest_addr, 0, 12); if ((skb->dst) && (skb->dst->neighbour)) { - *((u32 *) (&hdr->dest_addr[12])) = + *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = *((u32 *) skb->dst->neighbour->primary_key); } else { /* fill in destination address used in ip header */ - *((u32 *) (&hdr->dest_addr[12])) = skb->nh.iph->daddr; + *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = skb->nh.iph->daddr; } } else if (ipv == 6) { /* IPv6 or passthru */ - hdr->flags = qeth_get_qeth_hdr_flags6(cast_type); + hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type); if ((skb->dst) && (skb->dst->neighbour)) { - memcpy(hdr->dest_addr, + memcpy(hdr->hdr.l3.dest_addr, skb->dst->neighbour->primary_key, 16); } else { /* fill in destination address used in ip header */ - memcpy(hdr->dest_addr, &skb->nh.ipv6h->daddr, 16); + memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16); } } else { /* passthrough */ if (!memcmp(skb->data + sizeof(struct qeth_hdr), skb->dev->broadcast, 6)) { /* broadcast? */ - hdr->flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU; + hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU; } else { - hdr->flags = (cast_type == RTN_MULTICAST) ? + hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ? QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU : QETH_CAST_UNICAST | QETH_HDR_PASSTHRU; } @@ -3834,6 +3971,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, /* return EBUSY because we sent old packet, not * the current one */ rc = -EBUSY; + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); goto out; } } @@ -3872,7 +4010,7 @@ out: static inline int qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) { - int ipv; + int ipv = 0; int cast_type; struct qeth_qdio_out_q *queue; struct qeth_hdr *hdr; @@ -3881,7 +4019,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) QETH_DBF_TEXT(trace, 6, "sendpkt"); - ipv = qeth_get_ip_version(skb); + if (!card->options.layer2) + ipv = qeth_get_ip_version(skb); cast_type = qeth_get_cast_type(card, skb); queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; @@ -4224,8 +4363,8 @@ qeth_arp_query(struct qeth_card *card, char *udata) * funcs flags); since all zeros is no valueable information, * we say EOPNOTSUPP for all ARP functions */ - if (card->info.guestlan) - return -EOPNOTSUPP; + /*if (card->info.guestlan) + return -EOPNOTSUPP; */ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { PRINT_WARN("ARP processing not supported " @@ -4372,12 +4511,13 @@ qeth_snmp_command(struct qeth_card *card, char *udata) /* skip 4 bytes (data_len struct member) to get req_len */ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int))) return -EFAULT; - ureq = kmalloc(req_len, GFP_KERNEL); + ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL); if (!ureq) { QETH_DBF_TEXT(trace, 2, "snmpnome"); return -ENOMEM; } - if (copy_from_user(ureq, udata, req_len)){ + if (copy_from_user(ureq, udata, + req_len+sizeof(struct qeth_snmp_ureq_hdr))){ kfree(ureq); return -EFAULT; } @@ -4546,26 +4686,30 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!card) return -ENODEV; - if (card->state != CARD_STATE_UP) + if ((card->state != CARD_STATE_UP) && + (card->state != CARD_STATE_SOFTSETUP)) return -ENODEV; switch (cmd){ case SIOC_QETH_ARP_SET_NO_ENTRIES: - if (!capable(CAP_NET_ADMIN)){ + if ( !capable(CAP_NET_ADMIN) || + (card->options.layer2) ) { rc = -EPERM; break; } rc = qeth_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue); break; case SIOC_QETH_ARP_QUERY_INFO: - if (!capable(CAP_NET_ADMIN)){ + if ( !capable(CAP_NET_ADMIN) || + (card->options.layer2) ) { rc = -EPERM; break; } rc = qeth_arp_query(card, rq->ifr_ifru.ifru_data); break; case SIOC_QETH_ARP_ADD_ENTRY: - if (!capable(CAP_NET_ADMIN)){ + if ( !capable(CAP_NET_ADMIN) || + (card->options.layer2) ) { rc = -EPERM; break; } @@ -4576,7 +4720,8 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) rc = qeth_arp_add_entry(card, &arp_entry); break; case SIOC_QETH_ARP_REMOVE_ENTRY: - if (!capable(CAP_NET_ADMIN)){ + if ( !capable(CAP_NET_ADMIN) || + (card->options.layer2) ) { rc = -EPERM; break; } @@ -4587,7 +4732,8 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) rc = qeth_arp_remove_entry(card, &arp_entry); break; case SIOC_QETH_ARP_FLUSH_CACHE: - if (!capable(CAP_NET_ADMIN)){ + if ( !capable(CAP_NET_ADMIN) || + (card->options.layer2) ) { rc = -EPERM; break; } @@ -4733,10 +4879,11 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) QETH_DBF_TEXT(trace, 4, "frvaddr4"); if (!card->vlangrp) return; - in_dev = in_dev_get(card->vlangrp->vlan_devices[vid]); + rcu_read_lock(); + in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]); if (!in_dev) - return; - for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next){ + goto out; + for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { addr = qeth_get_addr_buffer(QETH_PROT_IPV4); if (addr){ addr->u.a4.addr = ifa->ifa_address; @@ -4746,7 +4893,8 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) kfree(addr); } } - in_dev_put(in_dev); +out: + rcu_read_unlock(); } static void @@ -4776,13 +4924,70 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) in6_dev_put(in6_dev); } +static void +qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, + enum qeth_ipa_cmds ipacmd) +{ + int rc; + struct qeth_ipa_cmd *cmd; + struct qeth_cmd_buffer *iob; + + QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd); + iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + cmd->data.setdelvlan.vlan_id = i; + + rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); + if (rc) { + PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " + "Continuing\n",i, card->info.if_name, rc); + QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd); + QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card)); + QETH_DBF_TEXT_(trace, 2, "err%d", rc); + } +} + +static void +qeth_layer2_process_vlans(struct qeth_card *card, int clear) +{ + unsigned short i; + + QETH_DBF_TEXT(trace, 3, "L2prcvln"); + + if (!card->vlangrp) + return; + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (card->vlangrp->vlan_devices[i] == NULL) + continue; + if (clear) + qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN); + else + qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN); + } +} + +/*add_vid is layer 2 used only ....*/ +static void +qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +{ + struct qeth_card *card; + + QETH_DBF_TEXT_(trace, 4, "aid:%d", vid); + + card = (struct qeth_card *) dev->priv; + if (!card->options.layer2) + return; + qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN); +} + +/*... kill_vid used for both modes*/ static void qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct qeth_card *card; unsigned long flags; - QETH_DBF_TEXT(trace,4,"vlkilvid"); + QETH_DBF_TEXT_(trace, 4, "kid:%d", vid); card = (struct qeth_card *) dev->priv; /* free all skbs for the vlan device */ @@ -4794,12 +4999,30 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) if (card->vlangrp) card->vlangrp->vlan_devices[vid] = NULL; spin_unlock_irqrestore(&card->vlanlock, flags); - if ( (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) || - (qeth_set_thread_start_bit(card, QETH_SET_MC_THREAD) == 0) ) - schedule_work(&card->kernel_thread_starter); + if (card->options.layer2) + qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); + qeth_set_multicast_list(card->dev); } #endif +/** + * set multicast address on card + */ +static void +qeth_set_multicast_list(struct net_device *dev) +{ + struct qeth_card *card = (struct qeth_card *) dev->priv; + + QETH_DBF_TEXT(trace,3,"setmulti"); + qeth_delete_mc_addresses(card); + qeth_add_multicast_ipv4(card); +#ifdef CONFIG_QETH_IPV6 + qeth_add_multicast_ipv6(card); +#endif + if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) + schedule_work(&card->kernel_thread_starter); +} + static int qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np) { @@ -4855,24 +5078,19 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot) static void qeth_delete_mc_addresses(struct qeth_card *card) { - struct qeth_ipaddr *ipm, *iptodo; + struct qeth_ipaddr *iptodo; unsigned long flags; QETH_DBF_TEXT(trace,4,"delmc"); - spin_lock_irqsave(&card->ip_lock, flags); - list_for_each_entry(ipm, &card->ip_list, entry){ - if (!ipm->is_multicast) - continue; - iptodo = qeth_get_addr_buffer(ipm->proto); - if (!iptodo) { - QETH_DBF_TEXT(trace, 2, "dmcnomem"); - continue; - } - memcpy(iptodo, ipm, sizeof(struct qeth_ipaddr)); - iptodo->users = iptodo->users * -1; - if (!__qeth_insert_ip_todo(card, iptodo, 0)) - kfree(iptodo); + iptodo = qeth_get_addr_buffer(QETH_PROT_IPV4); + if (!iptodo) { + QETH_DBF_TEXT(trace, 2, "dmcnomem"); + return; } + iptodo->type = QETH_IP_TYPE_DEL_ALL_MC; + spin_lock_irqsave(&card->ip_lock, flags); + if (!__qeth_insert_ip_todo(card, iptodo, 0)) + kfree(iptodo); spin_unlock_irqrestore(&card->ip_lock, flags); } @@ -4906,8 +5124,9 @@ qeth_add_vlan_mc(struct qeth_card *card) int i; QETH_DBF_TEXT(trace,4,"addmcvl"); - if (!qeth_is_supported(card,IPA_FULL_VLAN) || - (card->vlangrp == NULL)) + if ( ((card->options.layer2 == 0) && + (!qeth_is_supported(card,IPA_FULL_VLAN))) || + (card->vlangrp == NULL) ) return ; vg = card->vlangrp; @@ -4918,9 +5137,9 @@ qeth_add_vlan_mc(struct qeth_card *card) in_dev = in_dev_get(vg->vlan_devices[i]); if (!in_dev) continue; - read_lock(&in_dev->lock); + read_lock(&in_dev->mc_list_lock); qeth_add_mc(card,in_dev); - read_unlock(&in_dev->lock); + read_unlock(&in_dev->mc_list_lock); in_dev_put(in_dev); } #endif @@ -4935,10 +5154,10 @@ qeth_add_multicast_ipv4(struct qeth_card *card) in4_dev = in_dev_get(card->dev); if (in4_dev == NULL) return; - read_lock(&in4_dev->lock); + read_lock(&in4_dev->mc_list_lock); qeth_add_mc(card, in4_dev); qeth_add_vlan_mc(card); - read_unlock(&in4_dev->lock); + read_unlock(&in4_dev->mc_list_lock); in_dev_put(in4_dev); } @@ -4974,8 +5193,9 @@ qeth_add_vlan_mc6(struct qeth_card *card) int i; QETH_DBF_TEXT(trace,4,"admc6vl"); - if (!qeth_is_supported(card,IPA_FULL_VLAN) || - (card->vlangrp == NULL)) + if ( ((card->options.layer2 == 0) && + (!qeth_is_supported(card,IPA_FULL_VLAN))) || + (card->vlangrp == NULL)) return ; vg = card->vlangrp; @@ -5014,19 +5234,72 @@ qeth_add_multicast_ipv6(struct qeth_card *card) } #endif /* CONFIG_QETH_IPV6 */ -/** - * set multicast address on card - */ -static void -qeth_set_multicast_list(struct net_device *dev) +static int +qeth_layer2_send_setdelmac(struct qeth_card *card, __u8 *mac, + enum qeth_ipa_cmds ipacmd) +{ + struct qeth_ipa_cmd *cmd; + struct qeth_cmd_buffer *iob; + + QETH_DBF_TEXT(trace, 2, "L2sdmac"); + iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + cmd->data.setdelmac.mac_length = OSA_ADDR_LEN; + memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN); + return qeth_send_ipa_cmd(card, iob, NULL, NULL); +} + + +static int +qeth_layer2_set_mac_address(struct net_device *dev, void *p) { + struct sockaddr *addr = p; struct qeth_card *card; + int rc = 0; - QETH_DBF_TEXT(trace,3,"setmulti"); + QETH_DBF_TEXT(trace, 3, "setmac"); + + if (qeth_verify_dev(dev) != QETH_REAL_CARD) { + QETH_DBF_TEXT(trace, 3, "setmcINV"); + return -EOPNOTSUPP; + } card = (struct qeth_card *) dev->priv; - if (qeth_set_thread_start_bit(card, QETH_SET_MC_THREAD) == 0) - schedule_work(&card->kernel_thread_starter); + if (!card->options.layer2) { + PRINT_WARN("Setting MAC address on %s is not supported" + "in Layer 3 mode.\n", dev->name); + QETH_DBF_TEXT(trace, 3, "setmcLY3"); + return -EOPNOTSUPP; + } + QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card)); + QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN); + if (card->info.layer2_mac_registered) + rc = qeth_layer2_send_setdelmac(card, &card->dev->dev_addr[0], + IPA_CMD_DELVMAC); + if (rc) { + PRINT_WARN("Error in deregistering MAC address on " \ + "device %s: x%x\n", CARD_BUS_ID(card), rc); + QETH_DBF_TEXT_(trace, 2, "err%d", rc); + return -EIO; + } + card->info.layer2_mac_registered = 0; + + rc = qeth_layer2_send_setdelmac(card, addr->sa_data, IPA_CMD_SETVMAC); + if (rc) { + PRINT_WARN("Error in registering MAC address on " \ + "device %s: x%x\n", CARD_BUS_ID(card), rc); + QETH_DBF_TEXT_(trace, 2, "2err%d", rc); + return -EIO; + } + card->info.layer2_mac_registered = 1; + memcpy(dev->dev_addr, addr->sa_data, OSA_ADDR_LEN); + PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " + "successfully registered on device %s\n", + dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], + dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5], + dev->name); + + return rc; } static void @@ -5039,7 +5312,10 @@ qeth_fill_ipacmd_header(struct qeth_card *card, struct qeth_ipa_cmd *cmd, cmd->hdr.seqno = card->seqno.ipa; cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type); cmd->hdr.rel_adapter_no = (__u8) card->info.portno; - cmd->hdr.prim_version_no = 1; + if (card->options.layer2) + cmd->hdr.prim_version_no = 2; + else + cmd->hdr.prim_version_no = 1; cmd->hdr.param_count = 1; cmd->hdr.prot_version = prot; cmd->hdr.ipa_supported = 0; @@ -5130,7 +5406,53 @@ qeth_send_setdelip(struct qeth_card *card, struct qeth_ipaddr *addr, } static int -qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) +qeth_layer2_register_addr_entry(struct qeth_card *card, + struct qeth_ipaddr *addr) +{ + int rc = 0; + + if (!addr->is_multicast) + return 0; + + QETH_DBF_TEXT(trace, 2, "setgmac"); + QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN); + rc = qeth_layer2_send_setdelmac(card, &addr->mac[0], + IPA_CMD_SETGMAC); + if (rc) + PRINT_ERR("Could not set group MAC " \ + "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", + addr->mac[0],addr->mac[1],addr->mac[2], + addr->mac[3],addr->mac[4],addr->mac[5], + card->info.if_name,rc); + return rc; +} + +static int +qeth_layer2_deregister_addr_entry(struct qeth_card *card, + struct qeth_ipaddr *addr) +{ + int rc = 0; + + if (!addr->is_multicast) + return 0; + + QETH_DBF_TEXT(trace, 2, "delgmac"); + QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN); + rc = qeth_layer2_send_setdelmac(card, &addr->mac[0], + IPA_CMD_DELGMAC); + if (rc) + PRINT_ERR("Could not delete group MAC " \ + "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", + addr->mac[0],addr->mac[1],addr->mac[2], + addr->mac[3],addr->mac[4],addr->mac[5], + card->info.if_name,rc); + return rc; + +} + +static int +qeth_layer3_register_addr_entry(struct qeth_card *card, + struct qeth_ipaddr *addr) { //char buf[50]; int rc; @@ -5169,7 +5491,8 @@ qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) } static int -qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) +qeth_layer3_deregister_addr_entry(struct qeth_card *card, + struct qeth_ipaddr *addr) { //char buf[50]; int rc; @@ -5202,6 +5525,24 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) return rc; } +static int +qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) +{ + if (card->options.layer2) + return qeth_layer2_register_addr_entry(card, addr); + + return qeth_layer3_register_addr_entry(card, addr); +} + +static int +qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr) +{ + if (card->options.layer2) + return qeth_layer2_deregister_addr_entry(card, addr); + + return qeth_layer3_deregister_addr_entry(card, addr); +} + static int qeth_netdev_init(struct net_device *dev) { @@ -5224,8 +5565,9 @@ qeth_netdev_init(struct net_device *dev) #ifdef CONFIG_QETH_VLAN dev->vlan_rx_register = qeth_vlan_rx_register; dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid; + dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid; #endif - if (qeth_get_netdev_flags(card->info.type) & IFF_NOARP) { + if (qeth_get_netdev_flags(card) & IFF_NOARP) { dev->rebuild_header = NULL; dev->hard_header = NULL; dev->header_cache_update = NULL; @@ -5240,14 +5582,13 @@ qeth_netdev_init(struct net_device *dev) #endif dev->hard_header_parse = NULL; - dev->set_mac_address = NULL; - dev->flags |= qeth_get_netdev_flags(card->info.type); + dev->set_mac_address = qeth_layer2_set_mac_address; + dev->flags |= qeth_get_netdev_flags(card); if ((card->options.fake_broadcast) || (card->info.broadcast_capable)) dev->flags |= IFF_BROADCAST; - dev->hard_header_len = - qeth_get_hlen(card->info.link_type) + card->options.add_hhlen; + qeth_get_hlen(card->info.link_type) + card->options.add_hhlen; dev->addr_len = OSA_ADDR_LEN; dev->mtu = card->info.initial_mtu; @@ -5554,6 +5895,37 @@ qeth_setadapter_parms(struct qeth_card *card) return rc; } +static int +qeth_layer2_initialize(struct qeth_card *card) +{ + int rc = 0; + + + QETH_DBF_TEXT(setup, 2, "doL2init"); + QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); + + rc = qeth_setadpparms_change_macaddr(card); + if (rc) { + PRINT_WARN("couldn't get MAC address on " + "device %s: x%x\n", + CARD_BUS_ID(card), rc); + QETH_DBF_TEXT_(setup, 2,"1err%d",rc); + return rc; + } + QETH_DBF_HEX(setup,2, card->dev->dev_addr, OSA_ADDR_LEN); + + rc = qeth_layer2_send_setdelmac(card, &card->dev->dev_addr[0], + IPA_CMD_SETVMAC); + if (rc) { + card->info.layer2_mac_registered = 0; + PRINT_WARN("Error in processing MAC address on " \ + "device %s: x%x\n",CARD_BUS_ID(card),rc); + QETH_DBF_TEXT_(setup, 2,"2err%d",rc); + } else + card->info.layer2_mac_registered = 1; + return 0; +} + static int qeth_send_startstoplan(struct qeth_card *card, enum qeth_ipa_cmds ipacmd, @@ -5623,6 +5995,10 @@ qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot) struct qeth_cmd_buffer *iob; QETH_DBF_TEXT_(setup, 2, "qipassi%i", prot); + if (card->options.layer2) { + QETH_DBF_TEXT(setup, 2, "noprmly2"); + return -EPERM; + } iob = qeth_get_ipacmd_buffer(card,IPA_CMD_QIPASSIST,prot); rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL); @@ -5739,7 +6115,7 @@ qeth_start_ipa_ip_fragmentation(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"ipaipfrg"); if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) { - PRINT_INFO("IP fragmentation not supported on %s\n", + PRINT_INFO("Hardware IP fragmentation not supported on %s\n", card->info.if_name); return -EOPNOTSUPP; } @@ -5747,11 +6123,11 @@ qeth_start_ipa_ip_fragmentation(struct qeth_card *card) rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION, IPA_CMD_ASS_START, 0); if (rc) { - PRINT_WARN("Could not start IP fragmentation " + PRINT_WARN("Could not start Hardware IP fragmentation " "assist on %s: 0x%x\n", card->info.if_name, rc); } else - PRINT_INFO("IP fragmentation enabled \n"); + PRINT_INFO("Hardware IP fragmentation enabled \n"); return rc; } @@ -5801,7 +6177,10 @@ qeth_start_ipa_vlan(struct qeth_card *card) card->info.if_name, rc); } else { PRINT_INFO("VLAN enabled \n"); - card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + card->dev->features |= + NETIF_F_HW_VLAN_FILTER | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX; } #endif /* QETH_VLAN */ return rc; @@ -6171,6 +6550,22 @@ qeth_softsetup_card(struct qeth_card *card) return rc; } else card->lan_online = 1; + if (card->options.layer2) { + card->dev->features |= + NETIF_F_HW_VLAN_FILTER | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX; + card->dev->flags|=IFF_MULTICAST|IFF_BROADCAST; + card->info.broadcast_capable=1; + if ((rc = qeth_layer2_initialize(card))) { + QETH_DBF_TEXT_(setup, 2, "L2err%d", rc); + return rc; + } +#ifdef CONFIG_QETH_VLAN + qeth_layer2_process_vlans(card, 0); +#endif + goto out; + } if ((rc = qeth_setadapter_parms(card))) QETH_DBF_TEXT_(setup, 2, "2err%d", rc); if ((rc = qeth_start_ipassists(card))) @@ -6179,6 +6574,7 @@ qeth_softsetup_card(struct qeth_card *card) QETH_DBF_TEXT_(setup, 2, "4err%d", rc); if ((rc = qeth_setrouting_v6(card))) QETH_DBF_TEXT_(setup, 2, "5err%d", rc); +out: netif_stop_queue(card->dev); return 0; } @@ -6249,7 +6645,7 @@ qeth_clear_ip_list(struct qeth_card *card, int clean, int recover) QETH_DBF_TEXT(trace,4,"clearip"); spin_lock_irqsave(&card->ip_lock, flags); /* clear todo list */ - list_for_each_entry_safe(addr, tmp, &card->ip_tbd_list, entry){ + list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry){ list_del(&addr->entry); kfree(addr); } @@ -6267,7 +6663,7 @@ qeth_clear_ip_list(struct qeth_card *card, int clean, int recover) kfree(addr); continue; } - list_add_tail(&addr->entry, &card->ip_tbd_list); + list_add_tail(&addr->entry, card->ip_tbd_list); } spin_unlock_irqrestore(&card->ip_lock, flags); } @@ -6308,7 +6704,6 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads) static int qeth_stop_card(struct qeth_card *card) { - int recover_flag = 0; int rc = 0; QETH_DBF_TEXT(setup ,2,"stopcard"); @@ -6320,22 +6715,31 @@ qeth_stop_card(struct qeth_card *card) if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { - recover_flag = 1; rtnl_lock(); dev_close(card->dev); rtnl_unlock(); - if (!card->use_hard_stop) + if (!card->use_hard_stop) { + __u8 *mac = &card->dev->dev_addr[0]; + if ((rc = qeth_layer2_send_setdelmac(card, mac, + IPA_CMD_DELVMAC))); + QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc); if ((rc = qeth_send_stoplan(card))) QETH_DBF_TEXT_(setup, 2, "1err%d", rc); + } card->state = CARD_STATE_SOFTSETUP; } if (card->state == CARD_STATE_SOFTSETUP) { - qeth_clear_ip_list(card, !card->use_hard_stop, recover_flag); +#ifdef CONFIG_QETH_VLAN + if (card->options.layer2) + qeth_layer2_process_vlans(card, 1); +#endif + qeth_clear_ip_list(card, !card->use_hard_stop, 1); qeth_clear_ipacmd_list(card); card->state = CARD_STATE_HARDSETUP; } if (card->state == CARD_STATE_HARDSETUP) { - if (!card->use_hard_stop) + if ((!card->use_hard_stop) && + (!card->options.layer2)) if ((rc = qeth_put_unique_id(card))) QETH_DBF_TEXT_(setup, 2, "2err%d", rc); qeth_qdio_clear_card(card, 0); @@ -6497,10 +6901,61 @@ qeth_start_again(struct qeth_card *card) rtnl_lock(); dev_open(card->dev); rtnl_unlock(); - if (qeth_set_thread_start_bit(card, QETH_SET_MC_THREAD) == 0) - schedule_work(&card->kernel_thread_starter); + /* this also sets saved unicast addresses */ + qeth_set_multicast_list(card->dev); +} + + +/* Layer 2 specific stuff */ +#define IGNORE_PARAM_EQ(option,value,reset_value,msg) \ + if (card->options.option == value) { \ + PRINT_ERR("%s not supported with layer 2 " \ + "functionality, ignoring option on read" \ + "channel device %s .\n",msg,CARD_RDEV_ID(card)); \ + card->options.option = reset_value; \ + } +#define IGNORE_PARAM_NEQ(option,value,reset_value,msg) \ + if (card->options.option != value) { \ + PRINT_ERR("%s not supported with layer 2 " \ + "functionality, ignoring option on read" \ + "channel device %s .\n",msg,CARD_RDEV_ID(card)); \ + card->options.option = reset_value; \ + } + + +static void qeth_make_parameters_consistent(struct qeth_card *card) +{ + + if (card->options.layer2) { + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_ERR("Device %s does not support " \ + "layer 2 functionality. " \ + "Ignoring layer2 option.\n",CARD_BUS_ID(card)); + } + IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER, + "Routing options are"); +#ifdef CONFIG_QETH_IPV6 + IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER, + "Routing options are"); +#endif + IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING, + QETH_CHECKSUM_DEFAULT, + "Checksumming options are"); + IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS, + QETH_TR_BROADCAST_ALLRINGS, + "Broadcast mode options are"); + IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL, + QETH_TR_MACADDR_NONCANONICAL, + "Canonical MAC addr options are"); + IGNORE_PARAM_NEQ(fake_broadcast, 0, 0, + "Broadcast faking options are"); + IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN, + DEFAULT_ADD_HHLEN,"Option add_hhlen is"); + IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is"); + } } + static int qeth_set_online(struct ccwgroup_device *gdev) { @@ -6527,40 +6982,43 @@ qeth_set_online(struct ccwgroup_device *gdev) return -EIO; } + if (card->options.layer2) + qeth_make_parameters_consistent(card); + if ((rc = qeth_hardsetup_card(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); goto out_remove; } card->state = CARD_STATE_HARDSETUP; - if ((rc = qeth_query_ipassists(card,QETH_PROT_IPV4))){ - QETH_DBF_TEXT_(setup, 2, "3err%d", rc); - /*TODO: rc !=0*/ - } else + if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4))) rc = qeth_get_unique_id(card); - if (rc) { - QETH_DBF_TEXT_(setup, 2, "4err%d", rc); + if (rc && card->options.layer2 == 0) { + QETH_DBF_TEXT_(setup, 2, "3err%d", rc); goto out_remove; } qeth_print_status_message(card); if ((rc = qeth_register_netdev(card))){ - QETH_DBF_TEXT_(setup, 2, "5err%d", rc); + QETH_DBF_TEXT_(setup, 2, "4err%d", rc); goto out_remove; } if ((rc = qeth_softsetup_card(card))){ - QETH_DBF_TEXT_(setup, 2, "6err%d", rc); + QETH_DBF_TEXT_(setup, 2, "5err%d", rc); goto out_remove; } card->state = CARD_STATE_SOFTSETUP; if ((rc = qeth_init_qdio_queues(card))){ - QETH_DBF_TEXT_(setup, 2, "7err%d", rc); + QETH_DBF_TEXT_(setup, 2, "6err%d", rc); goto out_remove; } /*maybe it was set offline without ifconfig down * we can also use this state for recovery purposes*/ - qeth_set_allowed_threads(card, 0xffffffff, 0); + if (card->options.layer2) + qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 0); + else + qeth_set_allowed_threads(card, 0xffffffff, 0); if (recover_flag == CARD_STATE_RECOVER) qeth_start_again(card); qeth_notify_processes(); @@ -6706,23 +7164,35 @@ static int qeth_arp_constructor(struct neighbour *neigh) { struct net_device *dev = neigh->dev; - struct in_device *in_dev = in_dev_get(dev); + struct in_device *in_dev; + struct neigh_parms *parms; + struct qeth_card *card; + + card = qeth_get_card_from_dev(dev); + if (card == NULL) + goto out; + if(card->options.layer2) + goto out; - if (in_dev == NULL) + rcu_read_lock(); + in_dev = rcu_dereference(__in_dev_get(dev)); + if (in_dev == NULL) { + rcu_read_unlock(); return -EINVAL; - if (!qeth_verify_dev(dev)) { - in_dev_put(in_dev); - return qeth_old_arp_constructor(neigh); } + parms = in_dev->arp_parms; + __neigh_parms_put(neigh->parms); + neigh->parms = neigh_parms_clone(parms); + rcu_read_unlock(); + neigh->type = inet_addr_type(*(u32 *) neigh->primary_key); - if (in_dev->arp_parms) - neigh->parms = in_dev->arp_parms; - in_dev_put(in_dev); neigh->nud_state = NUD_NOARP; neigh->ops = arp_direct_ops; neigh->output = neigh->ops->queue_xmit; return 0; +out: + return qeth_old_arp_constructor(neigh); } #endif /*CONFIG_QETH_IPV6*/ @@ -6875,7 +7345,7 @@ qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, return -ENOMEM; spin_lock_irqsave(&card->ip_lock, flags); if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) || - __qeth_address_exists_in_list(&card->ip_tbd_list, ipaddr, 0)) + __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0)) rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc){ @@ -6948,7 +7418,7 @@ qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, return -ENOMEM; spin_lock_irqsave(&card->ip_lock, flags); if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) || - __qeth_address_exists_in_list(&card->ip_tbd_list, ipaddr, 0)) + __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0)) rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc){ @@ -7006,6 +7476,8 @@ qeth_ip_event(struct notifier_block *this, card = qeth_get_card_from_dev(dev); if (!card) return NOTIFY_DONE; + if (card->options.layer2) + return NOTIFY_DONE; addr = qeth_get_addr_buffer(QETH_PROT_IPV4); if (addr != NULL) { diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index a6272361f..052c8406a 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h @@ -14,7 +14,7 @@ #include -#define VERSION_QETH_MPC_H "$Revision: 1.36 $" +#define VERSION_QETH_MPC_H "$Revision: 1.38 $" extern const char *VERSION_QETH_MPC_C; @@ -105,6 +105,12 @@ enum qeth_routing_types { enum qeth_ipa_cmds { IPA_CMD_STARTLAN = 0x01, IPA_CMD_STOPLAN = 0x02, + IPA_CMD_SETVMAC = 0x21, + IPA_CMD_DELVMAC = 0x22, + IPA_CMD_SETGMAC = 0x23, + IPA_CMD_DELGMAC = 0x24, + IPA_CMD_SETVLAN = 0x25, + IPA_CMD_DELVLAN = 0x26, IPA_CMD_SETIP = 0xb1, IPA_CMD_DELIP = 0xb7, IPA_CMD_QIPASSIST = 0xb2, @@ -239,6 +245,16 @@ struct qeth_ipacmd_setdelipm { __u8 ip4[4]; } __attribute__ ((packed)); +struct qeth_ipacmd_layer2setdelmac { + __u32 mac_length; + __u8 mac[6]; +} __attribute__ ((packed)); + +struct qeth_ipacmd_layer2setdelvlan { + __u16 vlan_id; +} __attribute__ ((packed)); + + struct qeth_ipacmd_setassparms_hdr { __u32 assist_no; __u16 length; @@ -381,13 +397,15 @@ struct qeth_ipacmd_hdr { struct qeth_ipa_cmd { struct qeth_ipacmd_hdr hdr; union { - struct qeth_ipacmd_setdelip4 setdelip4; - struct qeth_ipacmd_setdelip6 setdelip6; - struct qeth_ipacmd_setdelipm setdelipm; - struct qeth_ipacmd_setassparms setassparms; - struct qeth_create_destroy_address create_destroy_addr; - struct qeth_ipacmd_setadpparms setadapterparms; - struct qeth_set_routing setrtg; + struct qeth_ipacmd_setdelip4 setdelip4; + struct qeth_ipacmd_setdelip6 setdelip6; + struct qeth_ipacmd_setdelipm setdelipm; + struct qeth_ipacmd_setassparms setassparms; + struct qeth_ipacmd_layer2setdelmac setdelmac; + struct qeth_ipacmd_layer2setdelvlan setdelvlan; + struct qeth_create_destroy_address create_destroy_addr; + struct qeth_ipacmd_setadpparms setadapterparms; + struct qeth_set_routing setrtg; } data; } __attribute__ ((packed)); @@ -459,6 +477,11 @@ extern unsigned char ULP_ENABLE[]; (PDU_ENCAPSULATION(buffer) + 0x17) #define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \ (PDU_ENCAPSULATION(buffer)+ 0x2b) +/* Layer 2 defintions */ +#define QETH_PROT_LAYER2 0x08 +#define QETH_PROT_TCPIP 0x03 +#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50) +#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19) extern unsigned char ULP_SETUP[]; #define ULP_SETUP_SIZE 0x6c diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 902f441f0..15c863fca 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.33 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.40 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.33 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.40 $"; /*****************************************************************************/ /* */ @@ -694,6 +694,44 @@ qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf, static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show, qeth_dev_canonical_macaddr_store); +static ssize_t +qeth_dev_layer2_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.layer2 ? 1:0); +} + +static ssize_t +qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return -EINVAL; + + if ((card->state != CARD_STATE_DOWN) && + (card->state != CARD_STATE_RECOVER)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if ((i == 0) || (i == 1)) + card->options.layer2 = i; + else { + PRINT_WARN("layer2: write 0 or 1 to this file!\n"); + return -EINVAL; + } + return count; +} + +static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, + qeth_dev_layer2_store); + static struct device_attribute * qeth_device_attrs[] = { &dev_attr_state, &dev_attr_chpid, @@ -714,6 +752,7 @@ static struct device_attribute * qeth_device_attrs[] = { &dev_attr_recover, &dev_attr_broadcast_mode, &dev_attr_canonical_macaddr, + &dev_attr_layer2, NULL, }; @@ -729,6 +768,15 @@ struct device_attribute dev_attr_##_id = { \ .store = _store, \ }; +int +qeth_check_layer2(struct qeth_card *card) +{ + if (card->options.layer2) + return -EPERM; + return 0; +} + + static ssize_t qeth_dev_ipato_enable_show(struct device *dev, char *buf) { @@ -737,6 +785,8 @@ qeth_dev_ipato_enable_show(struct device *dev, char *buf) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; return sprintf(buf, "%i\n", card->ipato.enabled? 1:0); } @@ -753,6 +803,9 @@ qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count) (card->state != CARD_STATE_RECOVER)) return -EPERM; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.enabled = (card->ipato.enabled)? 0 : 1; @@ -780,6 +833,9 @@ qeth_dev_ipato_invert4_show(struct device *dev, char *buf) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return sprintf(buf, "%i\n", card->ipato.invert4? 1:0); } @@ -792,6 +848,9 @@ qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.invert4 = (card->ipato.invert4)? 0 : 1; @@ -817,18 +876,31 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, { struct qeth_ipato_entry *ipatoe; unsigned long flags; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + /* add strlen for "/\n" */ + entry_len += (proto == QETH_PROT_IPV4)? 5 : 6; spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipatoe, &card->ipato.entries, entry){ if (ipatoe->proto != proto) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str); - i += sprintf(buf + i, "%s/%i\n", addr_str, ipatoe->mask_bits); + i += snprintf(buf + i, PAGE_SIZE - i, + "%s/%i\n", addr_str, ipatoe->mask_bits); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } @@ -880,6 +952,8 @@ qeth_dev_ipato_add_store(const char *buf, size_t count, int mask_bits; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; @@ -923,6 +997,8 @@ qeth_dev_ipato_del_store(const char *buf, size_t count, int mask_bits; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits))) return rc; @@ -954,6 +1030,9 @@ qeth_dev_ipato_invert6_show(struct device *dev, char *buf) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return sprintf(buf, "%i\n", card->ipato.invert6? 1:0); } @@ -966,6 +1045,9 @@ qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + tmp = strsep((char **) &buf, "\n"); if (!strcmp(tmp, "toggle")){ card->ipato.invert6 = (card->ipato.invert6)? 0 : 1; @@ -1050,21 +1132,32 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { struct qeth_ipaddr *ipaddr; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ unsigned long flags; int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + entry_len += 2; /* \n + terminator */ spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipaddr, &card->ip_list, entry){ if (ipaddr->proto != proto) continue; if (ipaddr->type != QETH_IP_TYPE_VIPA) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); - i += sprintf(buf + i, "%s\n", addr_str); + i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } @@ -1098,6 +1191,8 @@ qeth_dev_vipa_add_store(const char *buf, size_t count, u8 addr[16] = {0, }; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_vipae(buf, proto, addr))) return rc; @@ -1129,6 +1224,8 @@ qeth_dev_vipa_del_store(const char *buf, size_t count, u8 addr[16]; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_vipae(buf, proto, addr))) return rc; @@ -1186,6 +1283,9 @@ qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count) if (!card) return -EINVAL; + if (qeth_check_layer2(card)) + return -EPERM; + return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6); } @@ -1213,21 +1313,32 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, enum qeth_prot_versions proto) { struct qeth_ipaddr *ipaddr; - char addr_str[49]; + char addr_str[40]; + int entry_len; /* length of 1 entry string, differs between v4 and v6 */ unsigned long flags; int i = 0; + if (qeth_check_layer2(card)) + return -EPERM; + + entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; + entry_len += 2; /* \n + terminator */ spin_lock_irqsave(&card->ip_lock, flags); list_for_each_entry(ipaddr, &card->ip_list, entry){ if (ipaddr->proto != proto) continue; if (ipaddr->type != QETH_IP_TYPE_RXIP) continue; + /* String must not be longer than PAGE_SIZE. So we check if + * string length gets near PAGE_SIZE. Then we can savely display + * the next IPv6 address (worst case, compared to IPv4) */ + if ((PAGE_SIZE - i) <= entry_len) + break; qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str); - i += sprintf(buf + i, "%s\n", addr_str); + i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); } spin_unlock_irqrestore(&card->ip_lock, flags); - i += sprintf(buf + i, "\n"); + i += snprintf(buf + i, PAGE_SIZE - i, "\n"); return i; } @@ -1261,6 +1372,8 @@ qeth_dev_rxip_add_store(const char *buf, size_t count, u8 addr[16] = {0, }; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_rxipe(buf, proto, addr))) return rc; @@ -1292,6 +1405,8 @@ qeth_dev_rxip_del_store(const char *buf, size_t count, u8 addr[16]; int rc; + if (qeth_check_layer2(card)) + return -EPERM; if ((rc = qeth_parse_rxipe(buf, proto, addr))) return rc; diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index 167043492..7e26f0f1b 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h @@ -63,10 +63,6 @@ struct crw { #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ -#define MCHCHK_STATUS_TO_PROCESS 0x00000001 -#define MCHCHK_STATUS_IN_PROGRESS 0x00000002 -#define MCHCHK_STATUS_WAITING 0x00000004 - extern __inline__ int stcrw(struct crw *pcrw ) { int ccode; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index dad02890e..007f91597 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -12,6 +12,7 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann * * 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 @@ -28,8 +29,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_AUX_REVISION "$Revision: 1.115 $" +#define ZFCP_AUX_REVISION "$Revision: 1.145 $" #include "zfcp_ext.h" @@ -45,13 +45,12 @@ static int __init zfcp_module_init(void); static void zfcp_ns_gid_pn_handler(unsigned long); /* miscellaneous */ - static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); -static inline int zfcp_sg_list_free(struct zfcp_sg_list *); -static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *, - size_t); -static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *, - size_t); +static inline void zfcp_sg_list_free(struct zfcp_sg_list *); +static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, + void __user *, size_t); +static inline int zfcp_sg_list_copy_to_user(void __user *, + struct zfcp_sg_list *, size_t); static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *, unsigned int, unsigned long); @@ -60,7 +59,7 @@ static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *, #define ZFCP_CFDC_IOC \ _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data) -#ifdef CONFIG_S390_SUPPORT +#ifdef CONFIG_COMPAT static struct ioctl_trans zfcp_ioctl_trans = {ZFCP_CFDC_IOC, (void*) sys_ioctl}; #endif @@ -80,6 +79,7 @@ static struct miscdevice zfcp_cfdc_misc = { module_init(zfcp_module_init); MODULE_AUTHOR("Heiko Carstens , " + "Andreas Herrman , " "Martin Peschke , " "Raimund Schroeder , " "Wolfgang Taphorn , " @@ -95,7 +95,7 @@ MODULE_PARM_DESC(device, "specify initial device"); module_param(loglevel, uint, 0); MODULE_PARM_DESC(loglevel, "log levels, 8 nibbles: " - "(unassigned) ERP QDIO DIO Config FSF SCSI Other, " + "FC ERP QDIO CIO Config FSF SCSI Other, " "levels: 0=none 1=normal 2=devel 3=trace"); #ifdef ZFCP_PRINT_FLAGS @@ -145,7 +145,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, int i; unsigned long flags; - write_lock_irqsave(&adapter->cmd_dbf_lock, flags); + spin_lock_irqsave(&adapter->dbf_lock, flags); if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd; debug_text_event(adapter->cmd_dbf, level, "fsferror"); @@ -164,7 +164,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, (char *) add_data + i, min(ZFCP_CMD_DBF_LENGTH, add_length - i)); } - write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags); + spin_unlock_irqrestore(&adapter->dbf_lock, flags); } /* XXX additionally log unit if available */ @@ -181,7 +181,7 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble; fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL); - write_lock_irqsave(&adapter->cmd_dbf_lock, flags); + spin_lock_irqsave(&adapter->dbf_lock, flags); debug_text_event(adapter->cmd_dbf, level, "hostbyte"); debug_text_event(adapter->cmd_dbf, level, text); debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32)); @@ -198,7 +198,7 @@ zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) debug_text_event(adapter->cmd_dbf, level, ""); debug_text_event(adapter->cmd_dbf, level, ""); } - write_unlock_irqrestore(&adapter->cmd_dbf_lock, flags); + spin_unlock_irqrestore(&adapter->dbf_lock, flags); } void @@ -257,24 +257,20 @@ zfcp_device_setup(char *str) static void __init zfcp_init_device_configure(void) { - int found = 0; struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; down(&zfcp_data.config_sema); read_lock_irq(&zfcp_data.config_lock); - list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) - if (strcmp(zfcp_data.init_busid, - zfcp_get_busid_by_adapter(adapter)) == 0) { - zfcp_adapter_get(adapter); - found = 1; - break; - } + adapter = zfcp_get_adapter_by_busid(zfcp_data.init_busid); + if (adapter) + zfcp_adapter_get(adapter); read_unlock_irq(&zfcp_data.config_lock); - if (!found) + + if (adapter == NULL) goto out_adapter; - port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0); + port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0, 0); if (!port) goto out_port; unit = zfcp_unit_enqueue(port, zfcp_data.init_fcp_lun); @@ -282,7 +278,7 @@ zfcp_init_device_configure(void) goto out_unit; up(&zfcp_data.config_sema); ccw_device_set_online(adapter->ccw_device); - wait_event(unit->scsi_add_wq, atomic_read(&unit->scsi_add_work) == 0); + zfcp_erp_wait(adapter); down(&zfcp_data.config_sema); zfcp_unit_put(unit); out_unit: @@ -312,14 +308,13 @@ zfcp_module_init(void) if (!zfcp_transport_template) return -ENODEV; -#ifdef CONFIG_S390_SUPPORT retval = register_ioctl32_conversion(zfcp_ioctl_trans.cmd, zfcp_ioctl_trans.handler); if (retval != 0) { ZFCP_LOG_INFO("registration of ioctl32 conversion failed\n"); - goto out_ioctl32; + goto out; } -#endif + retval = misc_register(&zfcp_cfdc_misc); if (retval != 0) { ZFCP_LOG_INFO("registration of misc device " @@ -354,11 +349,7 @@ zfcp_module_init(void) out_ccw_register: misc_deregister(&zfcp_cfdc_misc); out_misc_register: -#ifdef CONFIG_S390_SUPPORT unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd); - out_ioctl32: -#endif - out: return retval; } @@ -377,12 +368,13 @@ zfcp_module_init(void) * -ENOMEM - Insufficient memory * -EFAULT - User space memory I/O operation fault * -EPERM - Cannot create or queue FSF request or create SBALs + * -ERESTARTSYS- Received signal (is mapped to EAGAIN by VFS) */ static int zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, unsigned int command, unsigned long buffer) { - struct zfcp_cfdc_sense_data sense_data, *sense_data_user; + struct zfcp_cfdc_sense_data *sense_data, __user *sense_data_user; struct zfcp_adapter *adapter = NULL; struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_sg_list *sg_list = NULL; @@ -390,6 +382,12 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, char *bus_id = NULL; int retval = 0; + sense_data = kmalloc(sizeof(struct zfcp_cfdc_sense_data), GFP_KERNEL); + if (sense_data == NULL) { + retval = -ENOMEM; + goto out; + } + sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); if (sg_list == NULL) { retval = -ENOMEM; @@ -403,27 +401,27 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, goto out; } - if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) { + if ((sense_data_user = (void __user *) buffer) == NULL) { ZFCP_LOG_INFO("sense data record is required\n"); retval = -EINVAL; goto out; } - retval = copy_from_user(&sense_data, sense_data_user, + retval = copy_from_user(sense_data, sense_data_user, sizeof(struct zfcp_cfdc_sense_data)); if (retval) { retval = -EFAULT; goto out; } - if (sense_data.signature != ZFCP_CFDC_SIGNATURE) { + if (sense_data->signature != ZFCP_CFDC_SIGNATURE) { ZFCP_LOG_INFO("invalid sense data request signature 0x%08x\n", ZFCP_CFDC_SIGNATURE); retval = -EINVAL; goto out; } - switch (sense_data.command) { + switch (sense_data->command) { case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL: fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE; @@ -452,7 +450,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, default: ZFCP_LOG_INFO("invalid command code 0x%08x\n", - sense_data.command); + sense_data->command); retval = -EINVAL; goto out; } @@ -463,30 +461,25 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, goto out; } snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x", - (sense_data.devno >> 24), - (sense_data.devno >> 16) & 0xFF, - (sense_data.devno & 0xFFFF)); + (sense_data->devno >> 24), + (sense_data->devno >> 16) & 0xFF, + (sense_data->devno & 0xFFFF)); - retval = -ENXIO; read_lock_irq(&zfcp_data.config_lock); - list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) { - if (strncmp(bus_id, zfcp_get_busid_by_adapter(adapter), - BUS_ID_SIZE) == 0) { - zfcp_adapter_get(adapter); - retval = 0; - break; - } - } + adapter = zfcp_get_adapter_by_busid(bus_id); + if (adapter) + zfcp_adapter_get(adapter); read_unlock_irq(&zfcp_data.config_lock); kfree(bus_id); - if (retval != 0) { + if (adapter == NULL) { ZFCP_LOG_INFO("invalid adapter\n"); + retval = -ENXIO; goto out; } - if (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE) { + if (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE) { retval = zfcp_sg_list_alloc(sg_list, ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); if (retval) { @@ -495,8 +488,8 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, } } - if ((sense_data.command & ZFCP_CFDC_DOWNLOAD) && - (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE)) { + if ((sense_data->command & ZFCP_CFDC_DOWNLOAD) && + (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE)) { retval = zfcp_sg_list_copy_from_user( sg_list, &sense_data_user->control_file, ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); @@ -506,34 +499,31 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, } } - retval = zfcp_fsf_control_file( - adapter, &fsf_req, fsf_command, option, sg_list); - if (retval == -EOPNOTSUPP) { - ZFCP_LOG_INFO("adapter does not support cfdc\n"); + retval = zfcp_fsf_control_file(adapter, &fsf_req, fsf_command, + option, sg_list); + if (retval) goto out; - } else if (retval != 0) { - ZFCP_LOG_INFO("initiation of cfdc up/download failed\n"); - retval = -EPERM; + + if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) && + (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { + retval = -ENXIO; goto out; } - wait_event(fsf_req->completion_wq, - fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - - sense_data.fsf_status = fsf_req->qtcb->header.fsf_status; - memcpy(&sense_data.fsf_status_qual, + sense_data->fsf_status = fsf_req->qtcb->header.fsf_status; + memcpy(&sense_data->fsf_status_qual, &fsf_req->qtcb->header.fsf_status_qual, sizeof(union fsf_status_qual)); - memcpy(&sense_data.payloads, &fsf_req->qtcb->bottom.support.els, 256); + memcpy(&sense_data->payloads, &fsf_req->qtcb->bottom.support.els, 256); - retval = copy_to_user(sense_data_user, &sense_data, + retval = copy_to_user(sense_data_user, sense_data, sizeof(struct zfcp_cfdc_sense_data)); if (retval) { retval = -EFAULT; goto out; } - if (sense_data.command & ZFCP_CFDC_UPLOAD) { + if (sense_data->command & ZFCP_CFDC_UPLOAD) { retval = zfcp_sg_list_copy_to_user( &sense_data_user->control_file, sg_list, ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); @@ -555,17 +545,23 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, kfree(sg_list); } + if (sense_data != NULL) + kfree(sense_data); + return retval; } -/* - * function: zfcp_sg_list_alloc - * - * purpose: Create a scatter-gather list of the specified size +/** + * zfcp_sg_list_alloc - create a scatter-gather list of the specified size + * @sg_list: structure describing a scatter gather list + * @size: size of scatter-gather list + * Return: 0 on success, else -ENOMEM * - * returns: 0 - Scatter gather list is created - * -ENOMEM - Insufficient memory (*list_ptr is then set to NULL) + * In sg_list->sg a pointer to the created scatter-gather list is returned, + * or NULL if we run out of memory. sg_list->count specifies the number of + * elements of the scatter-gather list. The maximum size of a single element + * in the scatter-gather list is PAGE_SIZE. */ static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) @@ -573,6 +569,9 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) struct scatterlist *sg; unsigned int i; int retval = 0; + void *address; + + BUG_ON(sg_list == NULL); sg_list->count = size >> PAGE_SHIFT; if (size & ~PAGE_MASK) @@ -584,17 +583,19 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) retval = -ENOMEM; goto out; } + memset(sg_list->sg, sg_list->count * sizeof(struct scatterlist), 0); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { sg->length = min(size, PAGE_SIZE); sg->offset = 0; - sg->page = alloc_pages(GFP_KERNEL, 0); - if (sg->page == NULL) { + address = (void *) get_zeroed_page(GFP_KERNEL); + if (address == NULL) { sg_list->count = i; zfcp_sg_list_free(sg_list); retval = -ENOMEM; goto out; } + zfcp_address_to_sg(address, sg); size -= sg->length; } @@ -603,41 +604,61 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) } -/* - * function: zfcp_sg_list_free - * - * purpose: Destroy a scatter-gather list and release memory +/** + * zfcp_sg_list_free - free memory of a scatter-gather list + * @sg_list: structure describing a scatter-gather list * - * returns: Always 0 + * Memory for each element in the scatter-gather list is freed. + * Finally sg_list->sg is freed itself and sg_list->count is reset. */ -static inline int +static inline void zfcp_sg_list_free(struct zfcp_sg_list *sg_list) { struct scatterlist *sg; unsigned int i; - int retval = 0; BUG_ON(sg_list == NULL); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) - __free_pages(sg->page, 0); + free_page((unsigned long) zfcp_sg_to_address(sg)); + sg_list->count = 0; kfree(sg_list->sg); +} - return retval; +/** + * zfcp_sg_size - determine size of a scatter-gather list + * @sg: array of (struct scatterlist) + * @sg_count: elements in array + * Return: size of entire scatter-gather list + */ +size_t +zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) +{ + unsigned int i; + struct scatterlist *p; + size_t size; + + size = 0; + for (i = 0, p = sg; i < sg_count; i++, p++) { + BUG_ON(p == NULL); + size += p->length; + } + + return size; } -/* - * function: zfcp_sg_list_copy_from_user - * - * purpose: Copy data from user space memory to the scatter-gather list - * - * returns: 0 - The data has been copied from user - * -EFAULT - Memory I/O operation fault +/** + * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list + * @sg_list: structure describing a scatter-gather list + * @user_buffer: pointer to buffer in user space + * @size: number of bytes to be copied + * Return: 0 on success, -EFAULT if copy_from_user fails. */ static inline int -zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer, +zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, + void __user *user_buffer, size_t size) { struct scatterlist *sg; @@ -645,10 +666,14 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer, void *zfcp_buffer; int retval = 0; + BUG_ON(sg_list == NULL); + + if (zfcp_sg_size(sg_list->sg, sg_list->count) < size) + return -EFAULT; + for (sg = sg_list->sg; size > 0; sg++) { length = min((unsigned int)size, sg->length); - zfcp_buffer = (void*) - ((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset); + zfcp_buffer = zfcp_sg_to_address(sg); if (copy_from_user(zfcp_buffer, user_buffer, length)) { retval = -EFAULT; goto out; @@ -662,16 +687,16 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer, } -/* - * function: zfcp_sg_list_copy_to_user - * - * purpose: Copy data from the scatter-gather list to user space memory - * - * returns: 0 - The data has been copied to user - * -EFAULT - Memory I/O operation fault +/** + * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space + * @user_buffer: pointer to buffer in user space + * @sg_list: structure describing a scatter-gather list + * @size: number of bytes to be copied + * Return: 0 on success, -EFAULT if copy_to_user fails */ static inline int -zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list, +zfcp_sg_list_copy_to_user(void __user *user_buffer, + struct zfcp_sg_list *sg_list, size_t size) { struct scatterlist *sg; @@ -679,10 +704,14 @@ zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list, void *zfcp_buffer; int retval = 0; + BUG_ON(sg_list == NULL); + + if (zfcp_sg_size(sg_list->sg, sg_list->count) < size) + return -EFAULT; + for (sg = sg_list->sg; size > 0; sg++) { - length = min((unsigned int)size, sg->length); - zfcp_buffer = (void*) - ((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset); + length = min((unsigned int) size, sg->length); + zfcp_buffer = zfcp_sg_to_address(sg); if (copy_to_user(user_buffer, zfcp_buffer, length)) { retval = -EFAULT; goto out; @@ -705,13 +734,12 @@ zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list, #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG /** - * zfcp_get_unit_by_lun - find unit in unit list of port by fcp lun + * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN * @port: pointer to port to search for unit - * @fcp_lun: lun to search for - * Traverses list of all units of a port and returns pointer to a unit - * if lun of a unit matches. + * @fcp_lun: FCP LUN to search for + * Traverse list of all units of a port and return pointer to a unit + * with the given FCP LUN. */ - struct zfcp_unit * zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun) { @@ -730,13 +758,12 @@ zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun) } /** - * zfcp_get_port_by_wwpn - find unit in unit list of port by fcp lun + * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn * @adapter: pointer to adapter to search for port * @wwpn: wwpn to search for - * Traverses list of all ports of an adapter and returns a pointer to a port - * if wwpn of a port matches. + * Traverse list of all ports of an adapter and return pointer to a port + * with the given wwpn. */ - struct zfcp_port * zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn) { @@ -745,6 +772,30 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn) list_for_each_entry(port, &adapter->port_list_head, list) { if ((port->wwpn == wwpn) && + !(atomic_read(&port->status) & + (ZFCP_STATUS_PORT_NO_WWPN | ZFCP_STATUS_COMMON_REMOVE))) { + found = 1; + break; + } + } + return found ? port : NULL; +} + +/** + * zfcp_get_port_by_did - find port in port list of adapter by d_id + * @adapter: pointer to adapter to search for port + * @d_id: d_id to search for + * Traverse list of all ports of an adapter and return pointer to a port + * with the given d_id. + */ +struct zfcp_port * +zfcp_get_port_by_did(struct zfcp_adapter *adapter, u32 d_id) +{ + struct zfcp_port *port; + int found = 0; + + list_for_each_entry(port, &adapter->port_list_head, list) { + if ((port->d_id == d_id) && !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) { found = 1; @@ -754,14 +805,38 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn) return found ? port : NULL; } -/* - * Enqueues a logical unit at the end of the unit list associated with the - * specified port. Also sets up some unit internal structures. +/** + * zfcp_get_adapter_by_busid - find adpater in adapter list by bus_id + * @bus_id: bus_id to search for + * Traverse list of all adapters and return pointer to an adapter + * with the given bus_id. + */ +struct zfcp_adapter * +zfcp_get_adapter_by_busid(char *bus_id) +{ + struct zfcp_adapter *adapter; + int found = 0; + + list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) { + if ((strncmp(bus_id, zfcp_get_busid_by_adapter(adapter), + BUS_ID_SIZE) == 0) && + !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, + &adapter->status)){ + found = 1; + break; + } + } + return found ? adapter : NULL; +} + +/** + * zfcp_unit_enqueue - enqueue unit to unit list of a port. + * @port: pointer to port where unit is added + * @fcp_lun: FCP LUN of unit to be enqueued + * Return: pointer to enqueued unit on success, NULL on error + * Locks: config_sema must be held to serialize changes to the unit list * - * returns: pointer to unit with a usecount of 1 if a new unit was - * successfully enqueued - * NULL otherwise - * locks: config_sema must be held to serialise changes to the unit list + * Sets up some unit internal structures and creates sysfs entry. */ struct zfcp_unit * zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) @@ -786,7 +861,6 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) return NULL; memset(unit, 0, sizeof (struct zfcp_unit)); - init_waitqueue_head(&unit->scsi_add_wq); /* initialise reference count stuff */ atomic_set(&unit->refcount, 0); init_waitqueue_head(&unit->remove_wq); @@ -960,11 +1034,11 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter) char dbf_name[20]; /* debug feature area which records SCSI command failures (hostbyte) */ - rwlock_init(&adapter->cmd_dbf_lock); + spin_lock_init(&adapter->dbf_lock); + sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s", zfcp_get_busid_by_adapter(adapter)); - adapter->cmd_dbf = debug_register(dbf_name, - ZFCP_CMD_DBF_INDEX, + adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX, ZFCP_CMD_DBF_AREAS, ZFCP_CMD_DBF_LENGTH); debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view); @@ -973,40 +1047,38 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter) /* debug feature area which records SCSI command aborts */ sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s", zfcp_get_busid_by_adapter(adapter)); - adapter->abort_dbf = debug_register(dbf_name, - ZFCP_ABORT_DBF_INDEX, + adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX, ZFCP_ABORT_DBF_AREAS, ZFCP_ABORT_DBF_LENGTH); debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view); debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL); - /* debug feature area which records SCSI command aborts */ + /* debug feature area which records incoming ELS commands */ sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s", zfcp_get_busid_by_adapter(adapter)); - adapter->in_els_dbf = debug_register(dbf_name, - ZFCP_IN_ELS_DBF_INDEX, + adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX, ZFCP_IN_ELS_DBF_AREAS, ZFCP_IN_ELS_DBF_LENGTH); debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view); debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL); - /* debug feature area which records erp events */ sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s", zfcp_get_busid_by_adapter(adapter)); - adapter->erp_dbf = debug_register(dbf_name, - ZFCP_ERP_DBF_INDEX, + adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX, ZFCP_ERP_DBF_AREAS, ZFCP_ERP_DBF_LENGTH); debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL); - if (adapter->cmd_dbf && adapter->abort_dbf && - adapter->in_els_dbf && adapter->erp_dbf) - return 0; + if (!(adapter->cmd_dbf && adapter->abort_dbf && + adapter->in_els_dbf && adapter->erp_dbf)) { + zfcp_adapter_debug_unregister(adapter); + return -ENOMEM; + } + + return 0; - zfcp_adapter_debug_unregister(adapter); - return -ENOMEM; } /** @@ -1016,10 +1088,20 @@ zfcp_adapter_debug_register(struct zfcp_adapter *adapter) void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) { - debug_unregister(adapter->erp_dbf); - debug_unregister(adapter->cmd_dbf); - debug_unregister(adapter->abort_dbf); - debug_unregister(adapter->in_els_dbf); + debug_unregister(adapter->abort_dbf); + debug_unregister(adapter->cmd_dbf); + debug_unregister(adapter->erp_dbf); + debug_unregister(adapter->in_els_dbf); + adapter->abort_dbf = NULL; + adapter->cmd_dbf = NULL; + adapter->erp_dbf = NULL; + adapter->in_els_dbf = NULL; +} + +void +zfcp_dummy_release(struct device *dev) +{ + return; } /* @@ -1113,6 +1195,14 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) if (zfcp_sysfs_adapter_create_files(&ccw_device->dev)) goto sysfs_failed; + adapter->generic_services.parent = &adapter->ccw_device->dev; + adapter->generic_services.release = zfcp_dummy_release; + snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE, + "generic_services"); + + if (device_register(&adapter->generic_services)) + goto generic_services_failed; + /* put allocated adapter at list tail */ write_lock_irq(&zfcp_data.config_lock); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); @@ -1123,6 +1213,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) goto out; + generic_services_failed: + zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); sysfs_failed: dev_set_drvdata(&ccw_device->dev, NULL); failed_low_mem_buffers: @@ -1153,6 +1245,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) int retval = 0; unsigned long flags; + device_unregister(&adapter->generic_services); zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); dev_set_drvdata(&adapter->ccw_device->dev, NULL); /* sanity check: no pending FSF requests */ @@ -1195,15 +1288,22 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) return; } -/* - * Enqueues a remote port to the port list. All port internal structures - * are set up and the sysfs entry is also generated. +/** + * zfcp_port_enqueue - enqueue port to port list of adapter + * @adapter: adapter where remote port is added + * @wwpn: WWPN of the remote port to be enqueued + * @status: initial status for the port + * @d_id: destination id of the remote port to be enqueued + * Return: pointer to enqueued port on success, NULL on error + * Locks: config_sema must be held to serialize changes to the port list * - * returns: pointer to port or NULL - * locks: config_sema must be held to serialise changes to the port list + * All port internal structures are set up and the sysfs entry is generated. + * d_id is used to enqueue ports with a well known address like the Directory + * Service for nameserver lookup. */ struct zfcp_port * -zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) +zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, + u32 d_id) { struct zfcp_port *port, *tmp_port; int check_wwpn; @@ -1243,12 +1343,39 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) atomic_set_mask(status, &port->status); /* setup for sysfs registration */ - if (status & ZFCP_STATUS_PORT_NAMESERVER) - snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver"); - else + if (status & ZFCP_STATUS_PORT_WKA) { + switch (d_id) { + case ZFCP_DID_DIRECTORY_SERVICE: + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, + "directory"); + break; + case ZFCP_DID_MANAGEMENT_SERVICE: + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, + "management"); + break; + case ZFCP_DID_KEY_DISTRIBUTION_SERVICE: + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, + "key_distribution"); + break; + case ZFCP_DID_ALIAS_SERVICE: + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, + "alias"); + break; + case ZFCP_DID_TIME_SERVICE: + snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, + "time"); + break; + default: + kfree(port); + return NULL; + } + port->d_id = d_id; + port->sysfs_device.parent = &adapter->generic_services; + } else { snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", wwpn); port->sysfs_device.parent = &adapter->ccw_device->dev; + } port->sysfs_device.release = zfcp_sysfs_port_release; dev_set_drvdata(&port->sysfs_device, port); @@ -1287,9 +1414,12 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status) list_add_tail(&port->list, &adapter->port_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); + if (d_id == ZFCP_DID_DIRECTORY_SERVICE) + if (!adapter->nameserver_port) + adapter->nameserver_port = port; + adapter->ports++; write_unlock_irq(&zfcp_data.config_lock); - adapter->ports++; zfcp_adapter_get(adapter); return port; @@ -1301,8 +1431,8 @@ zfcp_port_dequeue(struct zfcp_port *port) zfcp_port_wait(port); write_lock_irq(&zfcp_data.config_lock); list_del(&port->list); - write_unlock_irq(&zfcp_data.config_lock); port->adapter->ports--; + write_unlock_irq(&zfcp_data.config_lock); zfcp_adapter_put(port->adapter); zfcp_sysfs_port_remove_files(&port->sysfs_device, atomic_read(&port->status)); @@ -1315,17 +1445,14 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) { struct zfcp_port *port; - /* generate port structure */ - port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_NAMESERVER); + port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA, + ZFCP_DID_DIRECTORY_SERVICE); if (!port) { ZFCP_LOG_INFO("error: enqueue of nameserver port for " "adapter %s failed\n", zfcp_get_busid_by_adapter(adapter)); return -ENXIO; } - /* set special D_ID */ - port->d_id = ZFCP_DID_NAMESERVER; - adapter->nameserver_port = port; zfcp_port_put(port); return 0; @@ -1389,7 +1516,7 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) { if (atomic_test_mask - (ZFCP_STATUS_PORT_NAMESERVER, &port->status)) + (ZFCP_STATUS_PORT_WKA, &port->status)) continue; /* Do we know this port? If not skip it. */ if (!atomic_test_mask @@ -1521,7 +1648,6 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) zfcp_fsf_incoming_els_rscn(adapter, status_buffer); else zfcp_fsf_incoming_els_unknown(adapter, status_buffer); - } @@ -1646,15 +1772,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) ct_iu_req = zfcp_sg_to_address(ct->req); ct_iu_resp = zfcp_sg_to_address(ct->resp); - if (ct_iu_resp->header.revision != ZFCP_CT_REVISION) - goto failed; - if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE) - goto failed; - if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER) - goto failed; - if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS) - goto failed; - if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { + if ((ct->status != 0) || zfcp_check_ct_response(&ct_iu_resp->header)) { /* FIXME: do we need some specific erp entry points */ atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); goto failed; @@ -1665,7 +1783,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) "lookup does not match expected wwpn 0x%016Lx " "for adapter %s\n", ct_iu_req->wwpn, port->wwpn, zfcp_get_busid_by_port(port)); - goto failed; + goto mismatch; } /* looks like a valid d_id */ @@ -1675,19 +1793,185 @@ static void zfcp_ns_gid_pn_handler(unsigned long data) zfcp_get_busid_by_port(port), port->wwpn, port->d_id); goto out; -failed: - ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn " - "0x%016Lx for adapter %s\n", - port->wwpn, zfcp_get_busid_by_port(port)); + mismatch: ZFCP_LOG_DEBUG("CT IUs do not match:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req, sizeof(struct ct_iu_gid_pn_req)); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp, sizeof(struct ct_iu_gid_pn_resp)); + failed: + ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn " + "0x%016Lx for adapter %s\n", + port->wwpn, zfcp_get_busid_by_port(port)); out: zfcp_gid_pn_buffers_free(gid_pn); return; } +/* reject CT_IU reason codes acc. to FC-GS-4 */ +static const struct zfcp_rc_entry zfcp_ct_rc[] = { + {0x01, "invalid command code"}, + {0x02, "invalid version level"}, + {0x03, "logical error"}, + {0x04, "invalid CT_IU size"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0d, "server not available"}, + {0x0e, "session could not be established"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* LS_RJT reason codes acc. to FC-FS */ +static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = { + {0x01, "invalid LS_Command code"}, + {0x03, "logical error"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0e, "command already in progress"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* reject reason codes according to FC-PH/FC-FS */ +static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { + {0x01, "invalid D_ID"}, + {0x02, "invalid S_ID"}, + {0x03, "Nx_Port not available, temporary"}, + {0x04, "Nx_Port not available, permament"}, + {0x05, "class not supported"}, + {0x06, "delimiter usage error"}, + {0x07, "TYPE not supported"}, + {0x08, "invalid Link_Control"}, + {0x09, "invalid R_CTL field"}, + {0x0a, "invalid F_CTL field"}, + {0x0b, "invalid OX_ID"}, + {0x0c, "invalid RX_ID"}, + {0x0d, "invalid SEQ_ID"}, + {0x0e, "invalid DF_CTL"}, + {0x0f, "invalid SEQ_CNT"}, + {0x10, "invalid parameter field"}, + {0x11, "exchange error"}, + {0x12, "protocol error"}, + {0x13, "incorrect length"}, + {0x14, "unsupported ACK"}, + {0x15, "class of service not supported by entity at FFFFFE"}, + {0x16, "login required"}, + {0x17, "excessive sequences attempted"}, + {0x18, "unable to establish exchange"}, + {0x1a, "fabric path not available"}, + {0x1b, "invalid VC_ID (class 4)"}, + {0x1c, "invalid CS_CTL field"}, + {0x1d, "insufficient resources for VC (class 4)"}, + {0x1f, "invalid class of service"}, + {0x20, "preemption request rejected"}, + {0x21, "preemption not enabled"}, + {0x22, "multicast error"}, + {0x23, "multicast error terminate"}, + {0x24, "process login required"}, + {0xff, "vendor specific reject"}, + {0, NULL}, +}; + +/** + * zfcp_rc_description - return description for given reaon code + * @code: reason code + * @rc_table: table of reason codes and descriptions + */ +static inline const char * +zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) +{ + const char *descr = "unknown reason code"; + + do { + if (code == rc_table->code) { + descr = rc_table->description; + break; + } + rc_table++; + } while (rc_table->code && rc_table->description); + + return descr; +} + +/** + * zfcp_check_ct_response - evaluate reason code for CT_IU + * @rjt: response payload to an CT_IU request + * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code + */ +int +zfcp_check_ct_response(struct ct_hdr *rjt) +{ + if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT) + return 0; + + if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) { + ZFCP_LOG_NORMAL("error: invalid Generic Service command/" + "response code (0x%04hx)\n", + rjt->cmd_rsp_code); + return 1; + } + + ZFCP_LOG_INFO("Generic Service command rejected\n"); + ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n", + zfcp_rc_description(rjt->reason_code, zfcp_ct_rc), + (u32) rjt->reason_code, (u32) rjt->reason_code_expl, + (u32) rjt->vendor_unique); + + return 1; +} + +/** + * zfcp_print_els_rjt - print reject parameter and description for ELS reject + * @rjt_par: reject parameter acc. to FC-PH/FC-FS + * @rc_table: table of reason codes and descriptions + */ +static inline void +zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, + const struct zfcp_rc_entry *rc_table) +{ + ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n", + zfcp_rc_description(rjt_par->reason_code, rc_table), + (u32) rjt_par->action, (u32) rjt_par->reason_code, + (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique); +} + +/** + * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject + * @sq: status qualifier word + * @rjt_par: reject parameter as described in FC-PH and FC-FS + * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else + */ +int +zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par) +{ + int ret = -EIO; + + if (sq == FSF_IOSTAT_NPORT_RJT) { + ZFCP_LOG_INFO("ELS rejected (P_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_FABRIC_RJT) { + ZFCP_LOG_INFO("ELS rejected (F_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_LS_RJT) { + ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc); + ret = -EREMOTEIO; + } else + ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq); + + return ret; +} + #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 001d8067c..0fc46381f 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -10,6 +10,7 @@ * Authors: * Martin Peschke * Heiko Carstens + * Andreas Herrmann * * 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 @@ -26,7 +27,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_CCW_C_REVISION "$Revision: 1.56 $" +#define ZFCP_CCW_C_REVISION "$Revision: 1.58 $" #include "zfcp_ext.h" @@ -301,9 +302,11 @@ zfcp_ccw_shutdown(struct device *dev) { struct zfcp_adapter *adapter; + down(&zfcp_data.config_sema); adapter = dev_get_drvdata(dev); zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_wait(adapter); + up(&zfcp_data.config_sema); } #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index dda20bf00..53fcccbb4 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -12,6 +12,8 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann + * Volker Sameske * * 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 @@ -32,8 +34,7 @@ #ifndef ZFCP_DEF_H #define ZFCP_DEF_H -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.81 $" +#define ZFCP_DEF_REVISION "$Revision: 1.111 $" /*************************** INCLUDES *****************************************/ @@ -43,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -59,9 +61,7 @@ #include #include #include -#ifdef CONFIG_S390_SUPPORT #include -#endif /************************ DEBUG FLAGS *****************************************/ @@ -70,14 +70,24 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.1.3" +#define ZFCP_VERSION "4.2.0" +/** + * zfcp_sg_to_address - determine kernel address from struct scatterlist + * @list: struct scatterlist + * Return: kernel address + */ static inline void * zfcp_sg_to_address(struct scatterlist *list) { return (void *) (page_address(list->page) + list->offset); } +/** + * zfcp_address_to_sg - set up struct scatterlist from kernel address + * @address: kernel address + * @list: struct scatterlist + */ static inline void zfcp_address_to_sg(void *address, struct scatterlist *list) { @@ -146,6 +156,9 @@ typedef u32 scsi_lun_t; #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 6 #define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP 50 +/* timeout value for "default timer" for fsf requests */ +#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); + /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ typedef unsigned long long wwn_t; @@ -158,7 +171,6 @@ typedef unsigned int fcp_dl_t; /* timeout for name-server lookup (in seconds) */ #define ZFCP_NS_GID_PN_TIMEOUT 10 -#define ZFCP_NS_GA_NXT_TIMEOUT 120 /* largest SCSI command we can process */ /* FCP-2 (FCP_CMND IU) allows up to (255-3+16) */ @@ -174,11 +186,11 @@ typedef unsigned int fcp_dl_t; #define UNTAGGED 5 /* task management flags in FCP-2 FCP_CMND IU */ -#define CLEAR_ACA 0x40 -#define TARGET_RESET 0x20 -#define LOGICAL_UNIT_RESET 0x10 -#define CLEAR_TASK_SET 0x04 -#define ABORT_TASK_SET 0x02 +#define FCP_CLEAR_ACA 0x40 +#define FCP_TARGET_RESET 0x20 +#define FCP_LOGICAL_UNIT_RESET 0x10 +#define FCP_CLEAR_TASK_SET 0x04 +#define FCP_ABORT_TASK_SET 0x02 #define FCP_CDB_LENGTH 16 @@ -276,152 +288,41 @@ struct fcp_logo { #define R_A_TOV 10 /* seconds */ #define ZFCP_ELS_TIMEOUT (2 * R_A_TOV) -#define ZFCP_LS_RJT 0x01 -#define ZFCP_LS_ACC 0x02 -#define ZFCP_LS_RTV 0x0E -#define ZFCP_LS_RLS 0x0F -#define ZFCP_LS_PDISC 0x50 +#define ZFCP_LS_RLS 0x0f #define ZFCP_LS_ADISC 0x52 +#define ZFCP_LS_RPS 0x56 #define ZFCP_LS_RSCN 0x61 #define ZFCP_LS_RNID 0x78 -#define ZFCP_LS_RLIR 0x7A -#define ZFCP_LS_RTV_E_D_TOV_FLAG 0x04000000 - -/* LS_ACC Reason Codes */ -#define ZFCP_LS_RJT_INVALID_COMMAND_CODE 0x01 -#define ZFCP_LS_RJT_LOGICAL_ERROR 0x03 -#define ZFCP_LS_RJT_LOGICAL_BUSY 0x05 -#define ZFCP_LS_RJT_PROTOCOL_ERROR 0x07 -#define ZFCP_LS_RJT_UNABLE_TO_PERFORM 0x09 -#define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED 0x0B -#define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR 0xFF - -struct zfcp_ls_rjt { - u8 code; - u8 field[3]; - u8 reserved; - u8 reason_code; - u8 reason_expl; - u8 vendor_unique; -} __attribute__ ((packed)); - -struct zfcp_ls_rtv { - u8 code; - u8 field[3]; -} __attribute__ ((packed)); - -struct zfcp_ls_rtv_acc { - u8 code; - u8 field[3]; - u32 r_a_tov; - u32 e_d_tov; - u32 qualifier; -} __attribute__ ((packed)); -struct zfcp_ls_rls { - u8 code; - u8 field[3]; - fc_id_t port_id; -} __attribute__ ((packed)); - -struct zfcp_ls_rls_acc { - u8 code; - u8 field[3]; - u32 link_failure_count; - u32 loss_of_sync_count; - u32 loss_of_signal_count; - u32 prim_seq_prot_error; - u32 invalid_transmition_word; - u32 invalid_crc_count; -} __attribute__ ((packed)); - -struct zfcp_ls_pdisc { - u8 code; - u8 field[3]; - u8 common_svc_parm[16]; - wwn_t wwpn; - wwn_t wwnn; - struct { - u8 class1[16]; - u8 class2[16]; - u8 class3[16]; - } svc_parm; - u8 reserved[16]; - u8 vendor_version[16]; -} __attribute__ ((packed)); - -struct zfcp_ls_pdisc_acc { - u8 code; - u8 field[3]; - u8 common_svc_parm[16]; - wwn_t wwpn; - wwn_t wwnn; - struct { - u8 class1[16]; - u8 class2[16]; - u8 class3[16]; - } svc_parm; - u8 reserved[16]; - u8 vendor_version[16]; +struct zfcp_ls_rjt_par { + u8 action; + u8 reason_code; + u8 reason_expl; + u8 vendor_unique; } __attribute__ ((packed)); struct zfcp_ls_adisc { u8 code; u8 field[3]; - fc_id_t hard_nport_id; - wwn_t wwpn; - wwn_t wwnn; - fc_id_t nport_id; + u32 hard_nport_id; + u64 wwpn; + u64 wwnn; + u32 nport_id; } __attribute__ ((packed)); struct zfcp_ls_adisc_acc { u8 code; u8 field[3]; - fc_id_t hard_nport_id; - wwn_t wwpn; - wwn_t wwnn; - fc_id_t nport_id; + u32 hard_nport_id; + u64 wwpn; + u64 wwnn; + u32 nport_id; } __attribute__ ((packed)); -struct zfcp_ls_rnid { - u8 code; - u8 field[3]; - u8 node_id_format; - u8 reserved[3]; -} __attribute__((packed)); - -/* common identification data */ -struct zfcp_ls_rnid_common_id { - u64 n_port_name; - u64 node_name; -} __attribute__((packed)); - -/* general topology specific identification data */ -struct zfcp_ls_rnid_general_topology_id { - u8 vendor_unique[16]; - u32 associated_type; - u32 physical_port_number; - u32 nr_attached_nodes; - u8 node_management; - u8 ip_version; - u16 port_number; - u8 ip_address[16]; - u8 reserved[2]; - u16 vendor_specific; -} __attribute__((packed)); - -struct zfcp_ls_rnid_acc { - u8 code; - u8 field[3]; - u8 node_id_format; - u8 common_id_length; - u8 reserved; - u8 specific_id_length; - struct zfcp_ls_rnid_common_id - common_id; - struct zfcp_ls_rnid_general_topology_id - specific_id; -} __attribute__((packed)); +struct zfcp_rc_entry { + u8 code; + const char *description; +}; /* * FC-GS-2 stuff @@ -431,9 +332,9 @@ struct zfcp_ls_rnid_acc { #define ZFCP_CT_NAME_SERVER 0x02 #define ZFCP_CT_SYNCHRONOUS 0x00 #define ZFCP_CT_GID_PN 0x0121 -#define ZFCP_CT_GA_NXT 0x0100 #define ZFCP_CT_MAX_SIZE 0x1020 #define ZFCP_CT_ACCEPT 0x8002 +#define ZFCP_CT_REJECT 0x8001 /* * FC-GS-4 stuff @@ -478,6 +379,9 @@ struct zfcp_ls_rnid_acc { #define ZFCP_NAME "zfcp" +/* read-only LUN sharing switch initial value */ +#define ZFCP_RO_LUN_SHARING_DEFAULTS 0 + /* independent log areas */ #define ZFCP_LOG_AREA_OTHER 0 #define ZFCP_LOG_AREA_SCSI 1 @@ -527,26 +431,32 @@ struct zfcp_ls_rnid_acc { /* logging routine for zfcp */ #define _ZFCP_LOG(fmt, args...) \ printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \ - __LINE__ , ##args); + __LINE__ , ##args) #define ZFCP_LOG(level, fmt, args...) \ +do { \ if (ZFCP_LOG_CHECK(level)) \ - _ZFCP_LOG(fmt , ##args) + _ZFCP_LOG(fmt, ##args); \ +} while (0) #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL # define ZFCP_LOG_NORMAL(fmt, args...) #else # define ZFCP_LOG_NORMAL(fmt, args...) \ +do { \ if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_NORMAL)) \ - printk(KERN_ERR ZFCP_NAME": " fmt , ##args); + printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \ +} while (0) #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO # define ZFCP_LOG_INFO(fmt, args...) #else # define ZFCP_LOG_INFO(fmt, args...) \ +do { \ if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_INFO)) \ - printk(KERN_ERR ZFCP_NAME": " fmt , ##args); + printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \ +} while (0) #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG @@ -568,8 +478,10 @@ struct zfcp_ls_rnid_acc { #else extern u32 flags_dump; # define ZFCP_LOG_FLAGS(level, fmt, args...) \ +do { \ if (level <= flags_dump) \ - _ZFCP_LOG(fmt , ##args) + _ZFCP_LOG(fmt, ##args); \ +} while (0) #endif /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/ @@ -578,8 +490,8 @@ extern u32 flags_dump; * Note, the leftmost status byte is common among adapter, port * and unit */ -#define ZFCP_COMMON_FLAGS 0xff000000 -#define ZFCP_SPECIFIC_FLAGS 0x00ffffff +#define ZFCP_COMMON_FLAGS 0xfff00000 +#define ZFCP_SPECIFIC_FLAGS 0x000fffff /* common status bits */ #define ZFCP_STATUS_COMMON_REMOVE 0x80000000 @@ -590,6 +502,7 @@ extern u32 flags_dump; #define ZFCP_STATUS_COMMON_OPEN 0x04000000 #define ZFCP_STATUS_COMMON_CLOSING 0x02000000 #define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000 +#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000 /* adapter status */ #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 @@ -606,7 +519,12 @@ extern u32 flags_dump; ZFCP_STATUS_ADAPTER_REGISTERED) -#define ZFCP_DID_NAMESERVER 0xFFFFFC +/* FC-PH/FC-GS well-known address identifiers for generic services */ +#define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA +#define ZFCP_DID_TIME_SERVICE 0xFFFFFB +#define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC +#define ZFCP_DID_ALIAS_SERVICE 0xFFFFF8 +#define ZFCP_DID_KEY_DISTRIBUTION_SERVICE 0xFFFFF7 /* remote port status */ #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001 @@ -615,14 +533,18 @@ extern u32 flags_dump; #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 #define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010 #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 +#define ZFCP_STATUS_PORT_ACCESS_DENIED 0x00000040 -#define ZFCP_STATUS_PORT_NAMESERVER \ +/* for ports with well known addresses */ +#define ZFCP_STATUS_PORT_WKA \ (ZFCP_STATUS_PORT_NO_WWPN | \ ZFCP_STATUS_PORT_NO_SCSI_ID) /* logical unit status */ #define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET 0x00000001 - +#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 +#define ZFCP_STATUS_UNIT_SHARED 0x00000004 +#define ZFCP_STATUS_UNIT_READONLY 0x00000008 /* FSF request status (this does not have a common part) */ #define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 @@ -789,43 +711,29 @@ struct ct_iu_gid_pn_req { wwn_t wwpn; } __attribute__ ((packed)); -/* nameserver request CT_IU -- for requests where - * a port identifier is required */ -struct ct_iu_ga_nxt_req { - struct ct_hdr header; - fc_id_t d_id; -} __attribute__ ((packed)); - /* FS_ACC IU and data unit for GID_PN nameserver request */ struct ct_iu_gid_pn_resp { struct ct_hdr header; fc_id_t d_id; } __attribute__ ((packed)); -/* FS_ACC IU and data unit for GA_NXT nameserver request */ -struct ct_iu_ga_nxt_resp { - struct ct_hdr header; - u8 port_type; - u8 port_id[3]; - u64 port_wwn; - u8 port_symbolic_name_length; - u8 port_symbolic_name[255]; - u64 node_wwn; - u8 node_symbolic_name_length; - u8 node_symbolic_name[255]; - u64 initial_process_associator; - u8 node_ip[16]; - u32 cos; - u8 fc4_types[32]; - u8 port_ip[16]; - u64 fabric_wwn; - u8 reserved; - u8 hard_address[3]; -} __attribute__ ((packed)); - typedef void (*zfcp_send_ct_handler_t)(unsigned long); -/* used to pass parameters to zfcp_send_ct() */ +/** + * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct + * @port: port where the request is sent to + * @req: scatter-gather list for request + * @resp: scatter-gather list for response + * @req_count: number of elements in request scatter-gather list + * @resp_count: number of elements in response scatter-gather list + * @handler: handler function (called for response to the request) + * @handler_data: data passed to handler function + * @pool: pointer to memory pool for ct request structure + * @timeout: FSF timeout for this request + * @timer: timer (e.g. for request initiated by erp) + * @completion: completion for synchronization purposes + * @status: used to pass error status to calling function + */ struct zfcp_send_ct { struct zfcp_port *port; struct scatterlist *req; @@ -834,7 +742,7 @@ struct zfcp_send_ct { unsigned int resp_count; zfcp_send_ct_handler_t handler; unsigned long handler_data; - mempool_t *pool; /* mempool for ct not for fsf_req */ + mempool_t *pool; int timeout; struct timer_list *timer; struct completion *completion; @@ -851,18 +759,33 @@ struct zfcp_gid_pn_data { struct zfcp_port *port; }; -typedef int (*zfcp_send_els_handler_t)(unsigned long); - -/* used to pass parameters to zfcp_send_els() */ -/* ToDo merge send_ct() and send_els() and corresponding structs */ +typedef void (*zfcp_send_els_handler_t)(unsigned long); + +/** + * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els + * @adapter: adapter where request is sent from + * @d_id: destiniation id of port where request is sent to + * @req: scatter-gather list for request + * @resp: scatter-gather list for response + * @req_count: number of elements in request scatter-gather list + * @resp_count: number of elements in response scatter-gather list + * @handler: handler function (called for response to the request) + * @handler_data: data passed to handler function + * @timer: timer (e.g. for request initiated by erp) + * @completion: completion for synchronization purposes + * @ls_code: hex code of ELS command + * @status: used to pass error status to calling function + */ struct zfcp_send_els { - struct zfcp_port *port; + struct zfcp_adapter *adapter; + fc_id_t d_id; struct scatterlist *req; struct scatterlist *resp; unsigned int req_count; unsigned int resp_count; zfcp_send_els_handler_t handler; unsigned long handler_data; + struct timer_list *timer; struct completion *completion; int ls_code; int status; @@ -892,6 +815,7 @@ union zfcp_req_data { struct zfcp_send_ct *send_ct; struct zfcp_send_els *send_els; struct zfcp_status_read status_read; + struct fsf_qtcb_bottom_port *port_data; }; struct zfcp_qdio_queue { @@ -976,9 +900,10 @@ struct zfcp_adapter { debug_info_t *abort_dbf; debug_info_t *in_els_dbf; debug_info_t *cmd_dbf; - rwlock_t cmd_dbf_lock; + spinlock_t dbf_lock; struct zfcp_adapter_mempool pool; /* Adapter memory pools */ struct qdio_initialize qdio_init_data; /* for qdio_establish */ + struct device generic_services; /* directory for WKA ports */ }; /* @@ -1025,8 +950,6 @@ struct zfcp_unit { struct scsi_device *device; /* scsi device struct pointer */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; - atomic_t scsi_add_work; /* used to synchronize */ - wait_queue_head_t scsi_add_wq; /* wait for scsi_add_device */ }; /* FSF request */ @@ -1078,8 +1001,14 @@ struct zfcp_data { char init_busid[BUS_ID_SIZE]; wwn_t init_wwpn; fcp_lun_t init_fcp_lun; + char *driver_version; }; +/** + * struct zfcp_sg_list - struct describing a scatter-gather list + * @sg: pointer to array of (struct scatterlist) + * @count: number of elements in scatter-gather list + */ struct zfcp_sg_list { struct scatterlist *sg; unsigned int count; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e0766777e..31bf65991 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -12,6 +12,7 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann * * 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 @@ -30,13 +31,12 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.61 $" +#define ZFCP_ERP_REVISION "$Revision: 1.85 $" #include "zfcp_ext.h" -static int zfcp_els(struct zfcp_port *, u8); -static int zfcp_els_handler(unsigned long); +static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t); +static void zfcp_erp_adisc_handler(unsigned long); static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int); @@ -126,6 +126,25 @@ static void zfcp_erp_memwait_handler(unsigned long); static void zfcp_erp_timeout_handler(unsigned long); static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *); +/** + * zfcp_fsf_request_timeout_handler - called if a request timed out + * @data: pointer to adapter for handler function + * + * This function needs to be called if requests (ELS, Generic Service, + * or SCSI commands) exceed a certain time limit. The assumption is + * that after the time limit the adapter get stuck. So we trigger a reopen of + * the adapter. This should not be used for error recovery, SCSI abort + * commands and SCSI requests from SCSI mid-layer. + */ +void +zfcp_fsf_request_timeout_handler(unsigned long data) +{ + struct zfcp_adapter *adapter; + + adapter = (struct zfcp_adapter *) data; + + zfcp_erp_adapter_reopen(adapter, 0); +} /* * function: zfcp_fsf_scsi_er_timeout_handler @@ -274,341 +293,198 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) } -/* - * function: zfcp_els - * - * purpose: Originator of the ELS commands - * - * returns: 0 - Operation completed successfuly - * -EINVAL - Unknown IOCTL command or invalid sense data record - * -ENOMEM - Insufficient memory - * -EPERM - Cannot create or queue FSF request +/** + * zfcp_erp_adisc - send ADISC ELS command + * @adapter: adapter structure + * @d_id: d_id of port where ADISC is sent to */ int -zfcp_els(struct zfcp_port *port, u8 ls_code) +zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) { struct zfcp_send_els *send_els; - struct zfcp_ls_rls *rls; - struct zfcp_ls_pdisc *pdisc; struct zfcp_ls_adisc *adisc; - struct page *page = NULL; - void *req; + void *address = NULL; int retval = 0; + struct timer_list *timer; send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); if (send_els == NULL) goto nomem; + memset(send_els, 0, sizeof(*send_els)); send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->req == NULL) goto nomem; - send_els->req_count = 1; + memset(send_els->req, 0, sizeof(*send_els->req)); send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->resp == NULL) goto nomem; - send_els->resp_count = 1; + memset(send_els->resp, 0, sizeof(*send_els->resp)); - page = alloc_pages(GFP_ATOMIC, 0); - if (page == NULL) + address = (void *) get_zeroed_page(GFP_ATOMIC); + if (address == NULL) goto nomem; - send_els->req->page = page; - send_els->resp->page = page; - send_els->req->offset = 0; - send_els->resp->offset = PAGE_SIZE >> 1; - - send_els->port = port; - send_els->ls_code = ls_code; - send_els->handler = zfcp_els_handler; - send_els->handler_data = (unsigned long)send_els; - send_els->completion = NULL; - - req = zfcp_sg_to_address(send_els->req); - - *(u32*)req = 0; - *(u8*)req = ls_code; - - switch (ls_code) { - - case ZFCP_LS_RTV: - send_els->req->length = sizeof(struct zfcp_ls_rtv); - send_els->resp->length = sizeof(struct zfcp_ls_rtv_acc); - ZFCP_LOG_INFO("RTV request from s_id 0x%08x to d_id 0x%08x\n", - port->adapter->s_id, port->d_id); - break; - case ZFCP_LS_RLS: - send_els->req->length = sizeof(struct zfcp_ls_rls); - send_els->resp->length = sizeof(struct zfcp_ls_rls_acc); - rls = (struct zfcp_ls_rls*)req; - rls->port_id = port->adapter->s_id; - ZFCP_LOG_INFO("RLS request from s_id 0x%08x to d_id 0x%08x " - "(port_id=0x%08x)\n", - port->adapter->s_id, port->d_id, rls->port_id); - break; - - case ZFCP_LS_PDISC: - send_els->req->length = sizeof(struct zfcp_ls_pdisc); - send_els->resp->length = sizeof(struct zfcp_ls_pdisc_acc); - pdisc = (struct zfcp_ls_pdisc*)req; - pdisc->wwpn = port->adapter->wwpn; - pdisc->wwnn = port->adapter->wwnn; - ZFCP_LOG_INFO("PDISC request from s_id 0x%08x to d_id 0x%08x " - "(wwpn=0x%016Lx, wwnn=0x%016Lx)\n", - port->adapter->s_id, port->d_id, - pdisc->wwpn, pdisc->wwnn); - break; - - case ZFCP_LS_ADISC: - send_els->req->length = sizeof(struct zfcp_ls_adisc); - send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc); - adisc = (struct zfcp_ls_adisc*)req; - adisc->hard_nport_id = port->adapter->s_id; - adisc->wwpn = port->adapter->wwpn; - adisc->wwnn = port->adapter->wwnn; - adisc->nport_id = port->adapter->s_id; - ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " - "(wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%08x, nport_id=0x%08x)\n", - port->adapter->s_id, port->d_id, - adisc->wwpn, adisc->wwnn, - adisc->hard_nport_id, adisc->nport_id); - break; + zfcp_address_to_sg(address, send_els->req); + address += PAGE_SIZE >> 1; + zfcp_address_to_sg(address, send_els->resp); + send_els->req_count = send_els->resp_count = 1; + + send_els->adapter = adapter; + send_els->d_id = d_id; + send_els->handler = zfcp_erp_adisc_handler; + send_els->handler_data = (unsigned long) send_els; + + adisc = zfcp_sg_to_address(send_els->req); + send_els->ls_code = adisc->code = ZFCP_LS_ADISC; + + send_els->req->length = sizeof(struct zfcp_ls_adisc); + send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc); + + /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports + without FC-AL-2 capability, so we don't set it */ + adisc->wwpn = adapter->wwpn; + adisc->wwnn = adapter->wwnn; + adisc->nport_id = adapter->s_id; + ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " + "(wwpn=0x%016Lx, wwnn=0x%016Lx, " + "hard_nport_id=0x%08x, nport_id=0x%08x)\n", + adapter->s_id, d_id, (wwn_t) adisc->wwpn, + (wwn_t) adisc->wwnn, adisc->hard_nport_id, + adisc->nport_id); + + timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC); + if (!timer) + goto nomem; - default: - ZFCP_LOG_NORMAL("ELS command code 0x%02x is not supported\n", - ls_code); - retval = -EINVAL; - goto invalid_ls_code; - } + init_timer(timer); + timer->function = zfcp_fsf_request_timeout_handler; + timer->data = (unsigned long) adapter; + timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; + send_els->timer = timer; retval = zfcp_fsf_send_els(send_els); if (retval != 0) { ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " - "0x%016Lx on adapter %s\n", - port->wwpn, zfcp_get_busid_by_port(port)); - retval = -EPERM; + "0x%08x on adapter %s\n", d_id, + zfcp_get_busid_by_adapter(adapter)); + del_timer_sync(send_els->timer); + goto freemem; } goto out; -nomem: - ZFCP_LOG_DEBUG("out of memory\n"); + nomem: retval = -ENOMEM; - -invalid_ls_code: - if (page != NULL) - __free_pages(page, 0); + freemem: + if (address != NULL) + __free_pages(send_els->req->page, 0); if (send_els != NULL) { - if (send_els->req != NULL) - kfree(send_els->req); - if (send_els->resp != NULL) - kfree(send_els->resp); + kfree(send_els->timer); + kfree(send_els->req); + kfree(send_els->resp); kfree(send_els); } - -out: + out: return retval; } -/* - * function: zfcp_els_handler - * - * purpose: Handler for all kind of ELSs +/** + * zfcp_erp_adisc_handler - handler for ADISC ELS command + * @data: pointer to struct zfcp_send_els * - * returns: 0 - Operation completed successfuly - * -ENXIO - ELS has been rejected - * -EPERM - Port forced reopen failed + * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. */ -int -zfcp_els_handler(unsigned long data) -{ - struct zfcp_send_els *send_els = (struct zfcp_send_els*)data; - struct zfcp_port *port = send_els->port; - struct zfcp_ls_rjt *rjt; - struct zfcp_ls_rtv_acc *rtv; - struct zfcp_ls_rls_acc *rls; - struct zfcp_ls_pdisc_acc *pdisc; +void +zfcp_erp_adisc_handler(unsigned long data) +{ + struct zfcp_send_els *send_els; + struct zfcp_port *port; + struct zfcp_adapter *adapter; + fc_id_t d_id; struct zfcp_ls_adisc_acc *adisc; - void *req, *resp; - u8 req_code, resp_code; - int retval = 0; - - if (send_els->status != 0) { - ZFCP_LOG_NORMAL("ELS request timed out, force physical port " - "reopen of port 0x%016Lx on adapter %s\n", - port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(port->adapter->erp_dbf, 3, "forcreop"); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { - ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx " - "on adapter %s failed\n", port->wwpn, - zfcp_get_busid_by_port(port)); - retval = -EPERM; - } - goto skip_fsfstatus; - } - req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset); - resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset); - req_code = *(u8*)req; - resp_code = *(u8*)resp; + send_els = (struct zfcp_send_els *) data; - switch (resp_code) { + del_timer(send_els->timer); - case ZFCP_LS_RJT: - rjt = (struct zfcp_ls_rjt*)resp; + adapter = send_els->adapter; + d_id = send_els->d_id; - switch (rjt->reason_code) { + read_lock(&zfcp_data.config_lock); + port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id); + read_unlock(&zfcp_data.config_lock); - case ZFCP_LS_RJT_INVALID_COMMAND_CODE: - ZFCP_LOG_INFO("invalid LS command code " - "(wwpn=0x%016Lx, command=0x%02x)\n", - port->wwpn, req_code); - break; - - case ZFCP_LS_RJT_LOGICAL_ERROR: - ZFCP_LOG_INFO("logical error (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_LOGICAL_BUSY: - ZFCP_LOG_INFO("logical busy (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_PROTOCOL_ERROR: - ZFCP_LOG_INFO("protocol error (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_UNABLE_TO_PERFORM: - ZFCP_LOG_INFO("unable to perform command requested " - "(wwpn=0x%016Lx, reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED: - ZFCP_LOG_INFO("command not supported (wwpn=0x%016Lx, " - "command=0x%02x)\n", - port->wwpn, req_code); - break; - - case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR: - ZFCP_LOG_INFO("vendor specific error (wwpn=0x%016Lx, " - "vendor_unique=0x%02x)\n", - port->wwpn, rjt->vendor_unique); - break; + BUG_ON(port == NULL); - default: - ZFCP_LOG_NORMAL("ELS rejected by remote port 0x%016Lx " - "on adapter %s (reason_code=0x%02x)\n", - port->wwpn, + /* request rejected or timed out */ + if (send_els->status != 0) { + ZFCP_LOG_NORMAL("ELS request rejected/timed out, " + "force physical port reopen " + "(adapter %s, port d_id=0x%08x)\n", + zfcp_get_busid_by_adapter(adapter), d_id); + debug_text_event(adapter->erp_dbf, 3, "forcreop"); + if (zfcp_erp_port_forced_reopen(port, 0)) + ZFCP_LOG_NORMAL("failed reopen of port " + "(adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), - rjt->reason_code); - } - retval = -ENXIO; - break; - - case ZFCP_LS_ACC: - switch (req_code) { - - case ZFCP_LS_RTV: - rtv = (struct zfcp_ls_rtv_acc*)resp; - ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id " - "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n", - port->d_id, port->adapter->s_id, - rtv->r_a_tov, rtv->e_d_tov, - rtv->qualifier & - ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm'); - break; - - case ZFCP_LS_RLS: - rls = (struct zfcp_ls_rls_acc*)resp; - ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id " - "0x%08x (link_failure_count=%u, " - "loss_of_sync_count=%u, " - "loss_of_signal_count=%u, " - "primitive_sequence_protocol_error=%u, " - "invalid_transmition_word=%u, " - "invalid_crc_count=%u)\n", - port->d_id, port->adapter->s_id, - rls->link_failure_count, - rls->loss_of_sync_count, - rls->loss_of_signal_count, - rls->prim_seq_prot_error, - rls->invalid_transmition_word, - rls->invalid_crc_count); - break; - - case ZFCP_LS_PDISC: - pdisc = (struct zfcp_ls_pdisc_acc*)resp; - ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "vendor='%-16s')\n", port->d_id, - port->adapter->s_id, pdisc->wwpn, - pdisc->wwnn, pdisc->vendor_version); - break; - - case ZFCP_LS_ADISC: - adisc = (struct zfcp_ls_adisc_acc*)resp; - ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%08x, " - "nport_id=0x%08x)\n", port->d_id, - port->adapter->s_id, adisc->wwpn, - adisc->wwnn, adisc->hard_nport_id, - adisc->nport_id); - /* FIXME: set wwnn in during open port */ - if (port->wwnn == 0) - port->wwnn = adisc->wwnn; - break; - } - break; + port->wwpn); + goto out; + } - default: - ZFCP_LOG_NORMAL("unknown payload code 0x%02x received for " - "request 0x%02x to d_id 0x%08x, reopen needed " - "for port 0x%016Lx on adapter %s\n", resp_code, - req_code, port->d_id, port->wwpn, - zfcp_get_busid_by_port(port)); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { - ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx on " - "adapter %s failed\n", port->wwpn, - zfcp_get_busid_by_port(port)); - retval = -EPERM; - } + adisc = zfcp_sg_to_address(send_els->resp); + + ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "hard_nport_id=0x%08x, nport_id=0x%08x)\n", + d_id, adapter->s_id, (wwn_t) adisc->wwpn, + (wwn_t) adisc->wwnn, adisc->hard_nport_id, + adisc->nport_id); + + /* set wwnn for port */ + if (port->wwnn == 0) + port->wwnn = adisc->wwnn; + + if (port->wwpn != adisc->wwpn) { + ZFCP_LOG_NORMAL("d_id assignment changed, reopening " + "port (adapter %s, wwpn=0x%016Lx, " + "adisc_resp_wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), + port->wwpn, (wwn_t) adisc->wwpn); + if (zfcp_erp_port_reopen(port, 0)) + ZFCP_LOG_NORMAL("failed reopen of port " + "(adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), + port->wwpn); } -skip_fsfstatus: + out: + zfcp_port_put(port); __free_pages(send_els->req->page, 0); + kfree(send_els->timer); kfree(send_els->req); kfree(send_els->resp); - - return retval; + kfree(send_els); } -/* - * function: zfcp_test_link - * - * purpose: Test a status of a link to a remote port using the ELS command ADISC +/** + * zfcp_test_link - lightweight link test procedure + * @port: port to be tested * - * returns: 0 - Link is OK - * -EPERM - Port forced reopen failed + * Test status of a link to a remote port using the ELS command ADISC. */ int zfcp_test_link(struct zfcp_port *port) { int retval; - retval = zfcp_els(port, ZFCP_LS_ADISC); + zfcp_port_get(port); + retval = zfcp_erp_adisc(port->adapter, port->d_id); if (retval != 0) { + zfcp_port_put(port); ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " "on adapter %s\n ", port->wwpn, zfcp_get_busid_by_port(port)); @@ -735,14 +611,15 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask) return retval; } -/* - * function: - * - * purpose: Wrappper for zfcp_erp_port_reopen_internal - * used to ensure the correct locking +/** + * zfcp_erp_port_reopen - initiate reopen of a remote port + * @port: port to be reopened + * @clear_mask: specifies flags in port status to be cleared + * Return: 0 on success, < 0 on error * - * returns: 0 - initiated action succesfully - * <0 - failed to initiate action + * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures + * correct locking. An error recovery task is initiated to do the reopen. + * To wait for the completion of the reopen zfcp_erp_wait should be used. */ int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask) @@ -802,14 +679,15 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask) return retval; } -/* - * function: - * - * purpose: Wrappper for zfcp_erp_unit_reopen_internal - * used to ensure the correct locking +/** + * zfcp_erp_unit_reopen - initiate reopen of a unit + * @unit: unit to be reopened + * @clear_mask: specifies flags in unit status to be cleared + * Return: 0 on success, < 0 on error * - * returns: 0 - initiated action succesfully - * <0 - failed to initiate action + * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct + * locking. An error recovery task is initiated to do the reopen. + * To wait for the completion of the reopen zfcp_erp_wait should be used. */ int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask) @@ -1594,8 +1472,14 @@ zfcp_erp_port_failed(struct zfcp_port *port) zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); - ZFCP_LOG_NORMAL("port erp failed on port 0x%016Lx on adapter %s\n", - port->wwpn, zfcp_get_busid_by_port(port)); + if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) + ZFCP_LOG_NORMAL("port erp failed (adapter %s, " + "port d_id=0x%08x)\n", + zfcp_get_busid_by_port(port), port->d_id); + else + ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), port->wwpn); + debug_text_event(port->adapter->erp_dbf, 2, "p_pfail"); debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t)); } @@ -1731,63 +1615,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); } -/** - * zfcp_erp_scsi_add_device - * @data: pointer to a struct zfcp_unit - * - * Registers a logical unit with the SCSI stack. - */ -static void -zfcp_erp_scsi_add_device(void *data) -{ - struct { - struct zfcp_unit *unit; - struct work_struct work; - } *p; - - p = data; - scsi_add_device(p->unit->port->adapter->scsi_host, - 0, p->unit->port->scsi_id, p->unit->scsi_lun); - atomic_set(&p->unit->scsi_add_work, 0); - wake_up(&p->unit->scsi_add_wq); - zfcp_unit_put(p->unit); - kfree(p); -} - -/** - * zfcp_erp_schedule_work - * @unit: pointer to unit which should be registered with SCSI stack - * - * Schedules work which registers a unit with the SCSI stack - */ -static int -zfcp_erp_schedule_work(struct zfcp_unit *unit) -{ - struct { - struct zfcp_unit * unit; - struct work_struct work; - } *p; - - if (atomic_compare_and_swap(0, 1, &unit->scsi_add_work)) - return 0; - - if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) { - ZFCP_LOG_NORMAL("error: registration at SCSI stack failed for " - "unit 0x%016Lx on port 0x%016Lx on " - "adapter %s\n", unit->fcp_lun, unit->port->wwpn, - zfcp_get_busid_by_unit(unit)); - atomic_set(&unit->scsi_add_work, 0); - return -ENOMEM; - } - - zfcp_unit_get(unit); - memset(p, 0, sizeof(*p)); - INIT_WORK(&p->work, zfcp_erp_scsi_add_device, p); - p->unit = unit; - schedule_work(&p->work); - return 0; -} - /* * function: * @@ -1957,42 +1784,28 @@ zfcp_erp_strategy_followup_actions(int action, static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) { - int retval = 0; unsigned long flags; - struct zfcp_port *nport = adapter->nameserver_port; read_lock_irqsave(&zfcp_data.config_lock, flags); read_lock(&adapter->erp_lock); if (list_empty(&adapter->erp_ready_head) && list_empty(&adapter->erp_running_head)) { - if (nport - && atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, - &nport->status)) { - debug_text_event(adapter->erp_dbf, 4, "a_cq_nspsd"); - /* taking down nameserver port */ - zfcp_erp_port_reopen_internal(nport, - ZFCP_STATUS_COMMON_RUNNING | - ZFCP_STATUS_COMMON_ERP_FAILED); - } else { debug_text_event(adapter->erp_dbf, 4, "a_cq_wake"); atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); wake_up(&adapter->erp_done_wqh); - } } else debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty"); read_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); - return retval; + return 0; } -/* - * function: - * - * purpose: - * - * returns: +/** + * zfcp_erp_wait - wait for completion of error recovery on an adapter + * @adapter: adapter for which to wait for completion of its error recovery + * Return: 0 */ int zfcp_erp_wait(struct zfcp_adapter *adapter) @@ -2130,7 +1943,7 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask) struct zfcp_port *port; list_for_each_entry(port, &adapter->port_list_head, list) - if (!atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER, &port->status)) + if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) zfcp_erp_port_reopen_internal(port, clear_mask); return retval; @@ -2725,7 +2538,7 @@ zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) { int retval; - if (atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER, + if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &erp_action->port->status)) retval = zfcp_erp_port_strategy_open_nameserver(erp_action); else @@ -2772,10 +2585,13 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) /* nameserver port may live again */ atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &adapter->nameserver_port->status); - if (zfcp_erp_port_reopen(adapter->nameserver_port, 0) >= 0) { - erp_action->step = ZFCP_ERP_STEP_NAMESERVER_OPEN; + if (zfcp_erp_port_reopen(adapter->nameserver_port, 0) + >= 0) { + erp_action->step = + ZFCP_ERP_STEP_NAMESERVER_OPEN; retval = ZFCP_ERP_CONTINUES; - } else retval = ZFCP_ERP_FAILED; + } else + retval = ZFCP_ERP_FAILED; break; } /* else nameserver port is already open, fall through */ @@ -2863,10 +2679,10 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) case ZFCP_ERP_STEP_PORT_OPENING: if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) { - ZFCP_LOG_DEBUG("nameserver port is open\n"); + ZFCP_LOG_DEBUG("WKA port is open\n"); retval = ZFCP_ERP_SUCCEEDED; } else { - ZFCP_LOG_DEBUG("open failed for nameserver port\n"); + ZFCP_LOG_DEBUG("open failed for WKA port\n"); retval = ZFCP_ERP_FAILED; } /* this is needed anyway (dont care for retval of wakeup) */ @@ -2979,9 +2795,11 @@ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | ZFCP_STATUS_COMMON_CLOSING | + ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_PORT_DID_DID | ZFCP_STATUS_PORT_PHYS_CLOSING | - ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); + ZFCP_STATUS_PORT_INVALID_WWPN, + &port->status); return retval; } @@ -3185,7 +3003,11 @@ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING | - ZFCP_STATUS_COMMON_CLOSING, &unit->status); + ZFCP_STATUS_COMMON_CLOSING | + ZFCP_STATUS_COMMON_ACCESS_DENIED | + ZFCP_STATUS_UNIT_SHARED | + ZFCP_STATUS_UNIT_READONLY, + &unit->status); return retval; } @@ -3511,21 +3333,22 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) /** * zfcp_erp_action_cleanup * - * registers unit with scsi stack if appropiate and fixes reference counts + * Register unit with scsi stack if appropiate and fix reference counts. + * Note: Temporary units are not registered with scsi stack. */ - static void zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit, int result) { - if ((action == ZFCP_ERP_ACTION_REOPEN_UNIT) - && (result == ZFCP_ERP_SUCCEEDED) - && (!unit->device)) { - zfcp_erp_schedule_work(unit); - } switch (action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: + if ((result == ZFCP_ERP_SUCCEEDED) + && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY, + &unit->status)) + && (!unit->device)) + scsi_add_device(unit->port->adapter->scsi_host, 0, + unit->port->scsi_id, unit->scsi_lun); zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: @@ -3644,4 +3467,119 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); } +/* + * function: zfcp_erp_port_access_denied + * + * purpose: + */ +void +zfcp_erp_port_access_denied(struct zfcp_port *port) +{ + struct zfcp_adapter *adapter = port->adapter; + unsigned long flags; + + debug_text_event(adapter->erp_dbf, 3, "p_access_block"); + debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); + read_lock_irqsave(&zfcp_data.config_lock, flags); + zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); + read_unlock_irqrestore(&zfcp_data.config_lock, flags); +} + +/* + * function: zfcp_erp_unit_access_denied + * + * purpose: + */ +void +zfcp_erp_unit_access_denied(struct zfcp_unit *unit) +{ + struct zfcp_adapter *adapter = unit->port->adapter; + + debug_text_event(adapter->erp_dbf, 3, "u_access_block"); + debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); + zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED | + ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); +} + +/* + * function: zfcp_erp_adapter_access_changed + * + * purpose: + */ +void +zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) +{ + struct zfcp_port *port; + unsigned long flags; + + debug_text_event(adapter->erp_dbf, 3, "a_access_unblock"); + debug_event(adapter->erp_dbf, 3, &adapter->name, 8); + + zfcp_erp_port_access_changed(adapter->nameserver_port); + read_lock_irqsave(&zfcp_data.config_lock, flags); + list_for_each_entry(port, &adapter->port_list_head, list) + if (port != adapter->nameserver_port) + zfcp_erp_port_access_changed(port); + read_unlock_irqrestore(&zfcp_data.config_lock, flags); +} + +/* + * function: zfcp_erp_port_access_changed + * + * purpose: + */ +void +zfcp_erp_port_access_changed(struct zfcp_port *port) +{ + struct zfcp_adapter *adapter = port->adapter; + struct zfcp_unit *unit; + + debug_text_event(adapter->erp_dbf, 3, "p_access_unblock"); + debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t)); + + if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, + &port->status)) { + if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) + list_for_each_entry(unit, &port->unit_list_head, list) + zfcp_erp_unit_access_changed(unit); + return; + } + + ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s " + "(due to ACT update)\n", + port->wwpn, zfcp_get_busid_by_adapter(adapter)); + if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) + ZFCP_LOG_NORMAL("failed reopen of port" + "(adapter %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_adapter(adapter), port->wwpn); +} + +/* + * function: zfcp_erp_unit_access_changed + * + * purpose: + */ +void +zfcp_erp_unit_access_changed(struct zfcp_unit *unit) +{ + struct zfcp_adapter *adapter = unit->port->adapter; + + debug_text_event(adapter->erp_dbf, 3, "u_access_unblock"); + debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t)); + + if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status)) + return; + + ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx " + " on adapter %s (due to ACT update)\n", + unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_adapter(adapter)); + if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0) + ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, " + "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", + zfcp_get_busid_by_adapter(adapter), + unit->port->wwpn, unit->fcp_lun); +} + #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index d99005c01..d5fd43352 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -12,6 +12,7 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann * * 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 @@ -30,8 +31,8 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_EXT_REVISION "$Revision: 1.51 $" + +#define ZFCP_EXT_REVISION "$Revision: 1.62 $" #include "zfcp_def.h" @@ -50,15 +51,16 @@ extern void zfcp_sysfs_port_release(struct device *); extern void zfcp_sysfs_unit_release(struct device *); /**************************** CONFIGURATION *********************************/ -extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, - fcp_lun_t fcp_lun); -extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, - wwn_t wwpn); +extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, fcp_lun_t); +extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, wwn_t); +extern struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *, u32); +struct zfcp_adapter *zfcp_get_adapter_by_busid(char *); extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); extern int zfcp_adapter_debug_register(struct zfcp_adapter *); extern void zfcp_adapter_dequeue(struct zfcp_adapter *); extern void zfcp_adapter_debug_unregister(struct zfcp_adapter *); -extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32); +extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, + u32, u32); extern void zfcp_port_dequeue(struct zfcp_port *); extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t); extern void zfcp_unit_dequeue(struct zfcp_unit *); @@ -94,8 +96,11 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); +extern int zfcp_fsf_exchange_port_data(struct zfcp_adapter *, + struct fsf_qtcb_bottom_port *); extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); +extern void zfcp_fsf_request_timeout_handler(unsigned long); extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long); extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); @@ -108,7 +113,7 @@ extern int zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *); extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, struct zfcp_unit *, struct scsi_cmnd *, - int); + struct timer_list*, int); extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *); extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *); extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *); @@ -117,9 +122,11 @@ extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management( extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command( unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int); -/******************************** FCP ****************************************/ +/******************************* FC/FCP **************************************/ extern int zfcp_nameserver_enqueue(struct zfcp_adapter *); extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *); +extern int zfcp_check_ct_response(struct ct_hdr *); +extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *); /******************************* SCSI ****************************************/ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); @@ -132,10 +139,10 @@ extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *); extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *); -extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *unit, - struct scsi_cmnd *scsi_cmnd); -extern int zfcp_scsi_command_sync(struct zfcp_unit *unit, - struct scsi_cmnd *scsi_cmnd); +extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *, + struct scsi_cmnd *, struct timer_list *); +extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, + struct timer_list *); extern struct scsi_transport_template *zfcp_transport_template; extern struct fc_function_template zfcp_transport_functions; @@ -164,6 +171,12 @@ extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); extern int zfcp_test_link(struct zfcp_port *); +extern void zfcp_erp_port_access_denied(struct zfcp_port *); +extern void zfcp_erp_unit_access_denied(struct zfcp_unit *); +extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *); +extern void zfcp_erp_port_access_changed(struct zfcp_port *); +extern void zfcp_erp_unit_access_changed(struct zfcp_unit *); + /******************************** AUX ****************************************/ extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *, void *, int); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 79451af65..bad894af1 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -12,6 +12,8 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann + * Volker Sameske * * 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 @@ -28,12 +30,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.88 $" #include "zfcp_ext.h" static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *); +static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *); static int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *); static int zfcp_fsf_close_port_handler(struct zfcp_fsf_req *); static int zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *); @@ -48,7 +50,7 @@ static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *); static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); -static inline int zfcp_fsf_req_create_sbal_check( +static inline int zfcp_fsf_req_sbal_check( unsigned long *, struct zfcp_qdio_queue *, int); static inline int zfcp_use_one_sbal( struct scatterlist *, int, struct scatterlist *, int); @@ -79,10 +81,9 @@ static u32 fsf_qtcb_type[] = { }; static const char zfcp_act_subtable_type[5][8] = { - {"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"} + "unknown", "OS", "WWPN", "DID", "LUN" }; - /****************************************************************/ /*************** FSF related Functions *************************/ /****************************************************************/ @@ -684,13 +685,11 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) break; case FSF_SQ_ULP_PROGRAMMING_ERROR: ZFCP_LOG_FLAGS(0, "FSF_SQ_ULP_PROGRAMMING_ERROR\n"); - ZFCP_LOG_NORMAL("bug: An illegal amount of data was attempted " - "to be sent to the adapter %s " - "Stopping all operations on this adapter. ", + ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " + "(adapter %s)\n", zfcp_get_busid_by_adapter(fsf_req->adapter)); debug_text_exception(fsf_req->adapter->erp_dbf, 0, "fsf_sq_ulp_err"); - zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: @@ -785,7 +784,12 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) zfcp_fsf_exchange_config_data_handler(fsf_req); break; - case FSF_QTCB_SEND_ELS : + case FSF_QTCB_EXCHANGE_PORT_DATA: + ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n"); + zfcp_fsf_exchange_port_data_handler(fsf_req); + break; + + case FSF_QTCB_SEND_ELS: ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n"); zfcp_fsf_send_els_handler(fsf_req); break; @@ -989,6 +993,15 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) zfcp_fsf_incoming_els(fsf_req); break; + case FSF_STATUS_READ_SENSE_DATA_AVAIL: + ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SENSE_DATA_AVAIL\n"); + debug_text_event(adapter->erp_dbf, 3, "unsol_sense:"); + ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer, + sizeof(struct fsf_status_read_buffer)); + break; + case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_BIT_ERROR_THRESHOLD\n"); debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:"); @@ -1021,7 +1034,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED); - break; case FSF_STATUS_READ_CFDC_UPDATED: @@ -1029,6 +1041,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:"); ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); + zfcp_erp_adapter_access_changed(adapter); break; case FSF_STATUS_READ_CFDC_HARDENED: @@ -1286,6 +1299,22 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) | ZFCP_STATUS_FSFREQ_RETRY; break; + case FSF_LUN_BOXED: + ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n"); + ZFCP_LOG_INFO( + "unit 0x%016Lx on port 0x%016Lx on adapter %s needs " + "to be reopened\n", + unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_unit(unit)); + debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); + zfcp_erp_unit_reopen(unit, 0); + zfcp_cmd_dbf_event_fsf("unitbox", new_fsf_req, + &new_fsf_req->qtcb->header.fsf_status_qual, + sizeof(union fsf_status_qual)); + new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR + | ZFCP_STATUS_FSFREQ_RETRY; + break; + case FSF_ADAPTER_STATUS_AVAILABLE: /* 2 */ ZFCP_LOG_FLAGS(0, "FSF_ADAPTER_STATUS_AVAILABLE\n"); @@ -1517,20 +1546,18 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) header = &fsf_req->qtcb->header; bottom = &fsf_req->qtcb->bottom.support; - if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { - /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ + if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) goto skip_fsfstatus; - } /* evaluate FSF status in QTCB */ switch (header->fsf_status) { - case FSF_GOOD : + case FSF_GOOD: ZFCP_LOG_FLAGS(2,"FSF_GOOD\n"); retval = 0; break; - case FSF_SERVICE_CLASS_NOT_SUPPORTED : + case FSF_SERVICE_CLASS_NOT_SUPPORTED: ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n"); if (adapter->fc_service_class <= 3) { ZFCP_LOG_INFO("error: adapter %s does not support fc " @@ -1546,21 +1573,21 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) } /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); - zfcp_erp_adapter_shutdown(port->adapter, 0); + zfcp_erp_adapter_shutdown(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_ADAPTER_STATUS_AVAILABLE : + case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); switch (header->fsf_status_qual.word[0]){ - case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE : + case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); /* reopening link to port */ debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); zfcp_test_link(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED : + case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); /* ERP strategy will escalate */ debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); @@ -1576,9 +1603,9 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) case FSF_ACCESS_DENIED: ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); - ZFCP_LOG_NORMAL("Access denied, cannot send generic command " - "to port 0x%016Lx on adapter %s\n", port->wwpn, - zfcp_get_busid_by_port(port)); + ZFCP_LOG_NORMAL("access denied, cannot send generic service " + "command (adapter %s, port d_id=0x%08x)\n", + zfcp_get_busid_by_port(port), port->d_id); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; rule = header->fsf_status_qual.halfword[counter * 2 + 1]; @@ -1592,15 +1619,16 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) break; } } - debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); + zfcp_erp_port_access_denied(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_GENERIC_COMMAND_REJECTED : + case FSF_GENERIC_COMMAND_REJECTED: ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n"); - ZFCP_LOG_INFO("warning: The port 0x%016Lx on adapter %s has " - "rejected a generic services command.\n", - port->wwpn, zfcp_get_busid_by_port(port)); + ZFCP_LOG_INFO("generic service command rejected " + "(adapter %s, port d_id=0x%08x)\n", + zfcp_get_busid_by_port(port), port->d_id); ZFCP_LOG_INFO("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, (char *) &header->fsf_status_qual, @@ -1609,7 +1637,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_PORT_HANDLE_NOT_VALID : + case FSF_PORT_HANDLE_NOT_VALID: ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n"); ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port " "0x%016Lx on adapter %s invalid. This may " @@ -1620,42 +1648,57 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv"); - zfcp_erp_adapter_reopen(port->adapter, 0); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - break; - - case FSF_REQUEST_BUF_NOT_VALID : - ZFCP_LOG_FLAGS(2, "FSF_REQUEST_BUF_NOT_VALID\n"); - ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has " - "rejected a generic services command " - "due to invalid request buffer.\n", - port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(adapter->erp_dbf, 1, "fsf_s_reqiv"); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - break; - - case FSF_RESPONSE_BUF_NOT_VALID : - ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_BUF_NOT_VALID\n"); - ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has " - "rejected a generic services command " - "due to invalid response buffer.\n", - port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(adapter->erp_dbf, 1, "fsf_s_resiv"); + zfcp_erp_adapter_reopen(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_PORT_BOXED : + case FSF_PORT_BOXED: ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n"); - ZFCP_LOG_INFO("The remote port 0x%016Lx on adapter %s " - "needs to be reopened\n", - port->wwpn, zfcp_get_busid_by_port(port)); + ZFCP_LOG_INFO("port needs to be reopened " + "(adapter %s, port d_id=0x%08x)\n", + zfcp_get_busid_by_port(port), port->d_id); debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); zfcp_erp_port_reopen(port, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; - default : + /* following states should never occure, all cases avoided + in zfcp_fsf_send_ct - but who knows ... */ + case FSF_PAYLOAD_SIZE_MISMATCH: + ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n"); + ZFCP_LOG_INFO("payload size mismatch (adapter: %s, " + "req_buf_length=%d, resp_buf_length=%d)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->req_buf_length, bottom->resp_buf_length); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_REQUEST_SIZE_TOO_LARGE: + ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n"); + ZFCP_LOG_INFO("request size too large (adapter: %s, " + "req_buf_length=%d)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->req_buf_length); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_RESPONSE_SIZE_TOO_LARGE: + ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n"); + ZFCP_LOG_INFO("response size too large (adapter: %s, " + "resp_buf_length=%d)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->resp_buf_length); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_SBAL_MISMATCH: + ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n"); + ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " + "resp_buf_length=%d)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->req_buf_length, bottom->resp_buf_length); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + + default: ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " "(debug info 0x%x)\n", header->fsf_status); debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:"); @@ -1665,9 +1708,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) } skip_fsfstatus: - if (send_ct->handler != NULL) { + send_ct->status = retval; + + if (send_ct->handler != NULL) send_ct->handler(send_ct->handler_data); - } return retval; } @@ -1682,22 +1726,22 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) { volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; - struct zfcp_port *port; + fc_id_t d_id; struct zfcp_adapter *adapter; unsigned long lock_flags; int bytes; int ret = 0; - port = els->port; - adapter = port->adapter; + d_id = els->d_id; + adapter = els->adapter; ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, - ZFCP_WAIT_FOR_SBAL|ZFCP_REQ_AUTO_CLEANUP, + ZFCP_REQ_AUTO_CLEANUP, NULL, &lock_flags, &fsf_req); if (ret < 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%08x)\n", - zfcp_get_busid_by_adapter(adapter), port->d_id); + zfcp_get_busid_by_adapter(adapter), d_id); goto failed_req; } @@ -1722,8 +1766,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%08x)\n", - zfcp_get_busid_by_adapter(adapter), - port->d_id); + zfcp_get_busid_by_adapter(adapter), d_id); if (bytes == 0) { ret = -ENOMEM; } else { @@ -1740,8 +1783,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) if (bytes <= 0) { ZFCP_LOG_INFO("error: creation of ELS request failed " "(adapter %s, port d_id: 0x%08x)\n", - zfcp_get_busid_by_adapter(adapter), - port->d_id); + zfcp_get_busid_by_adapter(adapter), d_id); if (bytes == 0) { ret = -ENOMEM; } else { @@ -1755,13 +1797,13 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) ZFCP_LOG_INFO("error: microcode does not support chained SBALs" ", ELS request too big (adapter %s, " "port d_id: 0x%08x)\n", - zfcp_get_busid_by_adapter(adapter), port->d_id); + zfcp_get_busid_by_adapter(adapter), d_id); ret = -EOPNOTSUPP; goto failed_send; } /* settings in QTCB */ - fsf_req->qtcb->bottom.support.d_id = port->d_id; + fsf_req->qtcb->bottom.support.d_id = d_id; fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; fsf_req->data.send_els = els; @@ -1769,16 +1811,16 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); /* start QDIO request for this FSF request */ - ret = zfcp_fsf_req_send(fsf_req, NULL); + ret = zfcp_fsf_req_send(fsf_req, els->timer); if (ret) { ZFCP_LOG_DEBUG("error: initiation of ELS request failed " - "(adapter %s, port 0x%016Lx)\n", - zfcp_get_busid_by_adapter(adapter), port->wwpn); + "(adapter %s, port d_id: 0x%08x)\n", + zfcp_get_busid_by_adapter(adapter), d_id); goto failed_send; } - ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port 0x%016Lx)\n", - zfcp_get_busid_by_adapter(adapter), port->wwpn); + ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: " + "0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id); goto out; failed_send: @@ -1804,6 +1846,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) { struct zfcp_adapter *adapter; + fc_id_t d_id; struct zfcp_port *port; struct fsf_qtcb_header *header; struct fsf_qtcb_bottom_support *bottom; @@ -1811,9 +1854,9 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) int retval = -EINVAL; u16 subtable, rule, counter; - adapter = fsf_req->adapter; send_els = fsf_req->data.send_els; - port = send_els->port; + adapter = send_els->adapter; + d_id = send_els->d_id; header = &fsf_req->qtcb->header; bottom = &fsf_req->qtcb->bottom.support; @@ -1832,37 +1875,44 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) if (adapter->fc_service_class <= 3) { ZFCP_LOG_INFO("error: adapter %s does " "not support fibrechannel class %d.\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), adapter->fc_service_class); } else { ZFCP_LOG_INFO("bug: The fibrechannel class at " "adapter %s is invalid. " "(debug info %d)\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), adapter->fc_service_class); } /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); - zfcp_erp_adapter_shutdown(port->adapter, 0); + zfcp_erp_adapter_shutdown(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); switch (header->fsf_status_qual.word[0]){ - case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: { + case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); - if (send_els->ls_code != ZFCP_LS_ADISC) - zfcp_test_link(port); + if (send_els->ls_code != ZFCP_LS_ADISC) { + read_lock(&zfcp_data.config_lock); + port = zfcp_get_port_by_did(adapter, d_id); + if (port) + zfcp_test_link(port); + read_unlock(&zfcp_data.config_lock); + } fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - } case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); - /* ERP strategy will escalate */ debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = + zfcp_handle_els_rjt(header->fsf_status_qual.word[1], + (struct zfcp_ls_rjt_par *) + &header->fsf_status_qual.word[2]); break; case FSF_SQ_RETRY_IF_POSSIBLE: ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n"); @@ -1881,8 +1931,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n"); ZFCP_LOG_INFO("ELS has been rejected because command filter " "prohibited sending " - "(adapter: %s, wwpn=0x%016Lx)\n", - zfcp_get_busid_by_port(port), port->wwpn); + "(adapter: %s, port d_id: 0x%08x)\n", + zfcp_get_busid_by_adapter(adapter), d_id); break; @@ -1892,7 +1942,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) "ELS request size and ELS response size must be either " "both 0, or both greater than 0 " "(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), bottom->req_buf_length, bottom->resp_buf_length); break; @@ -1905,7 +1955,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) "exceeds the size of the buffers " "that have been allocated for ELS request data " "(adapter: %s, req_buf_length=%d)\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), bottom->req_buf_length); break; @@ -1917,24 +1967,25 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) "exceeds the size of the buffers " "that have been allocated for ELS response data " "(adapter: %s, resp_buf_length=%d)\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), bottom->resp_buf_length); break; - case FSF_UNKNOWN_COMMAND: - ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n"); - ZFCP_LOG_INFO( - "FSF command 0x%x is not supported by FCP adapter " - "(adapter: %s)\n", fsf_req->fsf_command, - zfcp_get_busid_by_port(port)); + case FSF_SBAL_MISMATCH: + /* should never occure, avoided in zfcp_fsf_send_els */ + ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n"); + ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, " + "resp_buf_length=%d)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->req_buf_length, bottom->resp_buf_length); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ACCESS_DENIED: ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); - ZFCP_LOG_NORMAL("Access denied, cannot send ELS " - "(adapter: %s, wwpn=0x%016Lx)\n", - zfcp_get_busid_by_port(port), port->wwpn); + ZFCP_LOG_NORMAL("access denied, cannot send ELS command " + "(adapter %s, port d_id=0x%08x)\n", + zfcp_get_busid_by_adapter(adapter), d_id); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; rule = header->fsf_status_qual.halfword[counter * 2 + 1]; @@ -1949,6 +2000,11 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) } } debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); + read_lock(&zfcp_data.config_lock); + port = zfcp_get_port_by_did(adapter, d_id); + if (port != NULL) + zfcp_erp_port_access_denied(port); + read_unlock(&zfcp_data.config_lock); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -1956,7 +2012,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_NORMAL( "bug: An unknown FSF Status was presented " "(adapter: %s, fsf_status=0x%08x)\n", - zfcp_get_busid_by_port(port), + zfcp_get_busid_by_adapter(adapter), header->fsf_status); debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval"); debug_exception(adapter->erp_dbf, 0, @@ -1971,8 +2027,6 @@ skip_fsfstatus: if (send_els->handler != 0) send_els->handler(send_els->handler_data); - kfree(send_els); - return retval; } @@ -2011,7 +2065,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req->erp_action = erp_action; erp_action->fsf_req->qtcb->bottom.config.feature_selection = - FSF_FEATURE_CFDC; + (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING); /* start QDIO request for this FSF request */ retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); @@ -2219,6 +2273,111 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) return 0; } +/** + * zfcp_fsf_exchange_port_data - request information about local port + * @adapter: for which port data is requested + * @data: response to exchange port data request + */ +int +zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, + struct fsf_qtcb_bottom_port *data) +{ + volatile struct qdio_buffer_element *sbale; + int retval = 0; + unsigned long lock_flags; + struct zfcp_fsf_req *fsf_req; + struct timer_list *timer; + + if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){ + ZFCP_LOG_INFO("error: exchange port data " + "command not supported by adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + return -EOPNOTSUPP; + } + + timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + /* setup new FSF request */ + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, + 0, 0, &lock_flags, &fsf_req); + if (retval < 0) { + ZFCP_LOG_INFO("error: Out of resources. Could not create an " + "exchange port data request for" + "the adapter %s.\n", + zfcp_get_busid_by_adapter(adapter)); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + goto out; + } + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + fsf_req->data.port_data = data; + + init_timer(timer); + timer->function = zfcp_fsf_request_timeout_handler; + timer->data = (unsigned long) adapter; + timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; + + retval = zfcp_fsf_req_send(fsf_req, timer); + if (retval) { + ZFCP_LOG_INFO("error: Could not send an exchange port data " + "command on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + zfcp_fsf_req_free(fsf_req); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + goto out; + } + + ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); + + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + del_timer_sync(timer); + zfcp_fsf_req_cleanup(fsf_req); + out: + kfree(timer); + return retval; +} + + +/** + * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request + * @fsf_req: pointer to struct zfcp_fsf_req + */ +static void +zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) +{ + struct fsf_qtcb_bottom_port *bottom; + struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data; + + if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) + return; + + switch (fsf_req->qtcb->header.fsf_status) { + case FSF_GOOD: + ZFCP_LOG_FLAGS(2,"FSF_GOOD\n"); + bottom = &fsf_req->qtcb->bottom.port; + memcpy(data, bottom, sizeof(*data)); + break; + + default: + debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng"); + debug_event(fsf_req->adapter->erp_dbf, 0, + &fsf_req->qtcb->header.fsf_status, sizeof(u32)); + } +} + + /* * function: zfcp_fsf_open_port * @@ -2324,7 +2483,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx " "on adapter %s\n", - port->wwpn, zfcp_get_busid_by_port(port)); + port->wwpn, zfcp_get_busid_by_port(port)); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; rule = header->fsf_status_qual.halfword[counter * 2 + 1]; @@ -2339,7 +2498,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) } } debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); - zfcp_erp_port_failed(port); + zfcp_erp_port_access_denied(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -2455,6 +2614,16 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) } break; + case FSF_UNKNOWN_OP_SUBTYPE: + /* should never occure, subtype not set in zfcp_fsf_open_port */ + ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n"); + ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, " + "op_subtype=0x%x)\n", + zfcp_get_busid_by_port(port), + fsf_req->qtcb->bottom.support.operation_subtype); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + default: ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " "(debug info 0x%x)\n", @@ -2721,9 +2890,8 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) case FSF_ACCESS_DENIED: ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); ZFCP_LOG_NORMAL("Access denied, cannot close " - "physical port 0x%016Lx on " - "adapter %s\n", port->wwpn, - zfcp_get_busid_by_port(port)); + "physical port 0x%016Lx on adapter %s\n", + port->wwpn, zfcp_get_busid_by_port(port)); for (counter = 0; counter < 2; counter++) { subtable = header->fsf_status_qual.halfword[counter * 2]; rule = header->fsf_status_qual.halfword[counter * 2 + 1]; @@ -2738,6 +2906,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) } } debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + zfcp_erp_port_access_denied(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -2859,6 +3028,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->port->handle; erp_action->fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; + erp_action->fsf_req->qtcb->bottom.support.option = + FSF_OPEN_LUN_SUPPRESS_BOXING; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); erp_action->fsf_req->data.open_unit.unit = erp_action->unit; erp_action->fsf_req->erp_action = erp_action; @@ -2902,18 +3073,31 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) struct zfcp_unit *unit; struct fsf_qtcb_header *header; struct fsf_qtcb_bottom_support *bottom; + struct fsf_queue_designator *queue_designator; u16 subtable, rule, counter; + u32 allowed, exclusive, readwrite; - adapter = fsf_req->adapter; unit = fsf_req->data.open_unit.unit; - header = &fsf_req->qtcb->header; - bottom = &fsf_req->qtcb->bottom.support; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change unit status in our bookkeeping */ goto skip_fsfstatus; } + adapter = fsf_req->adapter; + header = &fsf_req->qtcb->header; + bottom = &fsf_req->qtcb->bottom.support; + queue_designator = &header->fsf_status_qual.fsf_queue_designator; + + allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED; + exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; + readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; + + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | + ZFCP_STATUS_UNIT_SHARED | + ZFCP_STATUS_UNIT_READONLY, + &unit->status); + /* evaluate FSF status in QTCB */ switch (header->fsf_status) { @@ -2964,7 +3148,9 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) } } debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); - zfcp_erp_unit_failed(unit); + zfcp_erp_unit_access_denied(unit); + atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); + atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -2979,17 +3165,18 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) ZFCP_STATUS_FSFREQ_RETRY; break; - case FSF_LUN_SHARING_VIOLATION : + case FSF_LUN_SHARING_VIOLATION: ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n"); if (header->fsf_status_qual.word[0] != 0) { ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port " "with WWPN 0x%Lx " "connected to the adapter %s " - "is already in use in LPAR%d\n", + "is already in use in LPAR%d, CSS%d\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit), - header->fsf_status_qual.fsf_queue_designator.hla); + queue_designator->hla, + queue_designator->cssid); } else { subtable = header->fsf_status_qual.halfword[4]; rule = header->fsf_status_qual.halfword[5]; @@ -3090,6 +3277,38 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) unit->handle); /* mark unit as open */ atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); + + if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){ + if (!exclusive) + atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, + &unit->status); + + if (!readwrite) { + atomic_set_mask(ZFCP_STATUS_UNIT_READONLY, + &unit->status); + ZFCP_LOG_NORMAL("read-only access for unit " + "(adapter %s, wwpn=0x%016Lx, " + "fcp_lun=0x%016Lx)\n", + zfcp_get_busid_by_unit(unit), + unit->port->wwpn, + unit->fcp_lun); + } + + if (exclusive && !readwrite) { + ZFCP_LOG_NORMAL("exclusive access of read-only " + "unit not supported\n"); + zfcp_erp_unit_failed(unit); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + zfcp_erp_unit_shutdown(unit, 0); + } else if (!exclusive && readwrite) { + ZFCP_LOG_NORMAL("shared access of read-write " + "unit not supported\n"); + zfcp_erp_unit_failed(unit); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + zfcp_erp_unit_shutdown(unit, 0); + } + } + retval = 0; break; @@ -3103,7 +3322,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) break; } - skip_fsfstatus: + skip_fsfstatus: atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status); return retval; } @@ -3319,19 +3538,19 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) return retval; } -/* - * function: zfcp_fsf_send_fcp_command_task - * - * purpose: - * - * returns: - * - * note: we do not employ linked commands (not supported by HBA anyway) +/** + * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command) + * @adapter: adapter where scsi command is issued + * @unit: unit where command is sent to + * @scsi_cmnd: scsi command to be sent + * @timer: timer to be started when request is initiated + * @req_flags: flags for fsf_request */ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, struct zfcp_unit *unit, - struct scsi_cmnd * scsi_cmnd, int req_flags) + struct scsi_cmnd * scsi_cmnd, + struct timer_list *timer, int req_flags) { struct zfcp_fsf_req *fsf_req = NULL; struct fcp_cmnd_iu *fcp_cmnd_iu; @@ -3339,6 +3558,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, unsigned long lock_flags; int real_bytes = 0; int retval = 0; + int mask; /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, @@ -3423,14 +3643,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, /* set FCP_LUN in FCP_CMND IU in QTCB */ fcp_cmnd_iu->fcp_lun = unit->fcp_lun; + mask = ZFCP_STATUS_UNIT_READONLY | ZFCP_STATUS_UNIT_SHARED; + /* set task attributes in FCP_CMND IU in QTCB */ - if (likely(scsi_cmnd->device->simple_tags)) { + if (likely((scsi_cmnd->device->simple_tags) || + (atomic_test_mask(mask, &unit->status)))) fcp_cmnd_iu->task_attribute = SIMPLE_Q; - ZFCP_LOG_TRACE("setting SIMPLE_Q task attribute\n"); - } else { + else fcp_cmnd_iu->task_attribute = UNTAGGED; - ZFCP_LOG_TRACE("setting UNTAGGED task attribute\n"); - } /* set additional length of FCP_CDB in FCP_CMND IU in QTCB, if needed */ if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH)) { @@ -3486,7 +3706,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, * start QDIO request for this FSF request * covered by an SBALE) */ - retval = zfcp_fsf_req_send(fsf_req, NULL); + retval = zfcp_fsf_req_send(fsf_req, timer); if (unlikely(retval < 0)) { ZFCP_LOG_INFO("error: Could not send FCP command request " "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n", @@ -3765,6 +3985,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) } } debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + zfcp_erp_unit_access_denied(unit); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3788,44 +4009,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - /* FIXME: this should be obsolete, isn' it? */ - case FSF_INBOUND_DATA_LENGTH_NOT_VALID: - ZFCP_LOG_FLAGS(0, "FSF_INBOUND_DATA_LENGTH_NOT_VALID\n"); - ZFCP_LOG_NORMAL("bug: An invalid inbound data length field " - "was found in a command for unit 0x%016Lx " - "on port 0x%016Lx on adapter %s.\n", - unit->fcp_lun, - unit->port->wwpn, zfcp_get_busid_by_unit(unit)); - /* stop operation for this adapter */ - debug_text_event(fsf_req->adapter->erp_dbf, 0, - "fsf_s_in_dl_nv"); - zfcp_erp_adapter_shutdown(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("idleninv", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - break; - - /* FIXME: this should be obsolete, isn' it? */ - case FSF_OUTBOUND_DATA_LENGTH_NOT_VALID: - ZFCP_LOG_FLAGS(0, "FSF_OUTBOUND_DATA_LENGTH_NOT_VALID\n"); - ZFCP_LOG_NORMAL("bug: An invalid outbound data length field " - "was found in a command unit 0x%016Lx on port " - "0x%016Lx on adapter %s\n", - unit->fcp_lun, - unit->port->wwpn, - zfcp_get_busid_by_unit(unit)); - /* stop operation for this adapter */ - debug_text_event(fsf_req->adapter->erp_dbf, 0, - "fsf_s_out_dl_nv"); - zfcp_erp_adapter_shutdown(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("odleninv", fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - break; - case FSF_CMND_LENGTH_NOT_VALID: ZFCP_LOG_FLAGS(0, "FSF_CMND_LENGTH_NOT_VALID\n"); ZFCP_LOG_NORMAL @@ -3862,16 +4045,15 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) case FSF_LUN_BOXED: ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n"); - ZFCP_LOG_NORMAL( - "unit 0x%016Lx on port 0x%016Lx on adapter %s needs " - "to be reopened\n", - unit->fcp_lun, unit->port->wwpn, - zfcp_get_busid_by_unit(unit)); + ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, " + "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n", + zfcp_get_busid_by_unit(unit), + unit->port->wwpn, unit->fcp_lun); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); zfcp_erp_unit_reopen(unit, 0); zfcp_cmd_dbf_event_fsf("unitbox", fsf_req, - &header->fsf_status_qual, - sizeof(union fsf_status_qual)); + &header->fsf_status_qual, + sizeof(union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; @@ -4157,87 +4339,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) } skip_fsfstatus: -#if 0 - /* - * This nasty chop at the problem is not working anymore - * as we do not adjust the retry count anylonger in order - * to have a number of retries that avoids I/O errors. - * The manipulation of the retry count has been removed - * in favour of a safe tape device handling. We must not - * sent SCSI commands more than once to a device if no - * retries are permitted by the high level driver. Generally - * speaking, it was a mess to change retry counts. So it is - * fine that this sort of workaround is gone. - * Then, we had to face a certain number of immediate retries in case of - * busy and queue full conditions (see below). - * This is not acceptable - * for the latter. Queue full conditions are used - * by devices to indicate to a host that the host can rely - * on the completion (or timeout) of at least one outstanding - * command as a suggested trigger for command retries. - * Busy conditions require a different trigger since - * no commands are outstanding for that initiator from the - * devices perspective. - * The drawback of mapping a queue full condition to a - * busy condition is the chance of wasting all retries prior - * to the time when the device indicates that a command - * rejected due to a queue full condition should be re-driven. - * This case would lead to unnecessary I/O errors that - * have to be considered fatal if for example ext3's - * journaling would be torpedoed by such an avoidable - * I/O error. - * So, what issues are there with not mapping a queue-full - * condition to a busy condition? - * Due to the 'exclusive LUN' - * policy enforced by the zSeries FCP channel, this - * Linux instance is the only initiator with regard to - * this adapter. It is safe to rely on the information - * 'don't disturb me now ... and btw. no other commands - * pending for you' (= queue full) sent by the LU, - * since no other Linux can use this LUN via this adapter - * at the same time. If there is a potential race - * introduced by the FCP channel by not inhibiting Linux A - * to give up a LU with commands pending while Linux B - * grabs this LU and sends commands - thus providing - * an exploit at the 'exclusive LUN' policy - then this - * issue has to be considered a hardware problem. It should - * be tracked as such if it really occurs. Even if the - * FCP Channel spec. begs exploiters to wait for the - * completion of all request sent to a LU prior to - * closing this LU connection. - * This spec. statement in conjunction with - * the 'exclusive LUN' policy is not consistent design. - * Another issue is how resource constraints for SCSI commands - * might be handled by the FCP channel (just guessing for now). - * If the FCP channel would always map resource constraints, - * e.g. no free FC exchange ID due to I/O stress caused by - * other sharing Linux instances, to faked queue-full - * conditions then this would be a misinterpretation and - * violation of SCSI standards. - * If there are SCSI stack races as indicated below - * then they need to be fixed just there. - * Providing all issue above are not applicable or will - * be fixed appropriately, removing the following hack - * is the right thing to do. - */ - - /* - * Note: This is a rather nasty chop at the problem. We cannot - * risk adding to the mlqueue however as this will block the - * device. If it is the last outstanding command for this host - * it will remain blocked indefinitely. This would be quite possible - * on the zSeries FCP adapter. - * Also, there exists a race with scsi_insert_special relying on - * scsi_request_fn to recalculate some command data which may not - * happen when q->plugged is true in scsi_request_fn - */ - if (status_byte(scpnt->result) == QUEUE_FULL) { - ZFCP_LOG_DEBUG("Changing QUEUE_FULL to BUSY....\n"); - scpnt->result &= ~(QUEUE_FULL << 1); - scpnt->result |= (BUSY << 1); - } -#endif - ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); zfcp_cmd_dbf_event_scsi("response", scpnt); @@ -4343,7 +4444,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) * -EOPNOTSUPP - The FCP adapter does not have Control File support * -EINVAL - Invalid direction specified * -ENOMEM - Insufficient memory - * -EPERM - Cannot create FSF request or or place it in QDIO queue + * -EPERM - Cannot create FSF request or place it in QDIO queue */ int zfcp_fsf_control_file(struct zfcp_adapter *adapter, @@ -4355,17 +4456,17 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, struct zfcp_fsf_req *fsf_req; struct fsf_qtcb_bottom_support *bottom; volatile struct qdio_buffer_element *sbale; + struct timer_list *timer; unsigned long lock_flags; int req_flags = 0; int direction; int retval = 0; if (!(adapter->supported_features & FSF_FEATURE_CFDC)) { - ZFCP_LOG_INFO( - "Adapter %s does not support control file\n", - zfcp_get_busid_by_adapter(adapter)); + ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); retval = -EOPNOTSUPP; - goto no_cfdc_support; + goto out; } switch (fsf_command) { @@ -4383,9 +4484,16 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, default: ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); - goto invalid_command; + retval = -EINVAL; + goto out; } + timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); + if (!timer) { + retval = -ENOMEM; + goto out; + } + retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, NULL, &lock_flags, &fsf_req); if (retval < 0) { @@ -4393,7 +4501,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, "adapter %s\n", zfcp_get_busid_by_adapter(adapter)); retval = -EPERM; - goto out; + goto unlock_queue_lock; } sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); @@ -4415,40 +4523,46 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, "SBALS for an FSF request to the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); retval = -ENOMEM; - goto sbals_failed; + goto free_fsf_req; } - } else { + } else sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; - } - retval = zfcp_fsf_req_send(fsf_req, NULL); + init_timer(timer); + timer->function = zfcp_fsf_request_timeout_handler; + timer->data = (unsigned long) adapter; + timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; + + retval = zfcp_fsf_req_send(fsf_req, timer); if (retval < 0) { - ZFCP_LOG_INFO( - "error: Could not send FSF request to the adapter %s\n", - zfcp_get_busid_by_adapter(adapter)); + ZFCP_LOG_INFO("initiation of cfdc up/download failed" + "(adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); retval = -EPERM; - goto queue_failed; + goto free_fsf_req; } + write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - ZFCP_LOG_NORMAL( - "Control file %s FSF request has been sent to the adapter %s\n", - fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? + ZFCP_LOG_NORMAL("Control file %s FSF request has been sent to the " + "adapter %s\n", + fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? "download" : "upload", - zfcp_get_busid_by_adapter(adapter)); + zfcp_get_busid_by_adapter(adapter)); - *fsf_req_ptr = fsf_req; + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - goto out; + *fsf_req_ptr = fsf_req; + del_timer_sync(timer); + goto free_timer; -sbals_failed: -queue_failed: + free_fsf_req: zfcp_fsf_req_free(fsf_req); - -out: + unlock_queue_lock: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - -invalid_command: -no_cfdc_support: + free_timer: + kfree(timer); + out: return retval; } @@ -4585,23 +4699,12 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req) retval = -EIO; break; - case FSF_UNKNOWN_COMMAND: - ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n"); - ZFCP_LOG_NORMAL( - "FSF command 0x%x is not supported by the adapter %s\n", - fsf_req->fsf_command, - zfcp_get_busid_by_adapter(adapter)); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; - retval = -EINVAL; - break; - case FSF_UNKNOWN_OP_SUBTYPE: ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n"); - ZFCP_LOG_NORMAL( - "Invalid operation subtype 0x%x has been specified " - "in QTCB bottom sent to the adapter %s\n", - bottom->operation_subtype, - zfcp_get_busid_by_adapter(adapter)); + ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, " + "op_subtype=0x%x)\n", + zfcp_get_busid_by_adapter(adapter), + bottom->operation_subtype); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; retval = -EINVAL; break; @@ -4682,8 +4785,8 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req, } static inline int -zfcp_fsf_req_create_sbal_check(unsigned long *flags, - struct zfcp_qdio_queue *queue, int needed) +zfcp_fsf_req_sbal_check(unsigned long *flags, + struct zfcp_qdio_queue *queue, int needed) { write_lock_irqsave(&queue->queue_lock, *flags); if (likely(atomic_read(&queue->free_count) >= needed)) @@ -4712,30 +4815,27 @@ zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd) * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue * @adapter: adapter for which request queue is examined * @req_flags: flags indicating whether to wait for needed SBAL or not - * @lock_flags: lock_flags is queue_lock is taken - * - * locking: on success the queue_lock for the request queue of the adapter - * is held + * @lock_flags: lock_flags if queue_lock is taken + * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS + * Locks: lock adapter->request_queue->queue_lock on success */ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, unsigned long *lock_flags) { - int condition; + long ret; struct zfcp_qdio_queue *req_queue = &adapter->request_queue; if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { - wait_event_interruptible_timeout(adapter->request_wq, - (condition = - zfcp_fsf_req_create_sbal_check - (lock_flags, req_queue, 1)), - ZFCP_SBAL_TIMEOUT); - if (!condition) { - return -EIO; - } - } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) { + ret = wait_event_interruptible_timeout(adapter->request_wq, + zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1), + ZFCP_SBAL_TIMEOUT); + if (ret < 0) + return ret; + if (!ret) + return -EIO; + } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) return -EIO; - } return 0; } diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 879313864..5889956bb 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -11,7 +11,9 @@ * Aron Zeh * Wolfgang Taphorn * Stefan Bader - * Heiko Carstens + * Heiko Carstens + * Andreas Herrmann + * Volker Sameske * * 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 @@ -84,19 +86,12 @@ #define FSF_SERVICE_CLASS_NOT_SUPPORTED 0x00000006 #define FSF_FCPLUN_NOT_VALID 0x00000009 #define FSF_ACCESS_DENIED 0x00000010 -#define FSF_ACCESS_TYPE_NOT_VALID 0x00000011 #define FSF_LUN_SHARING_VIOLATION 0x00000012 -#define FSF_COMMAND_ABORTED_ULP 0x00000020 -#define FSF_COMMAND_ABORTED_ADAPTER 0x00000021 #define FSF_FCP_COMMAND_DOES_NOT_EXIST 0x00000022 #define FSF_DIRECTION_INDICATOR_NOT_VALID 0x00000030 -#define FSF_INBOUND_DATA_LENGTH_NOT_VALID 0x00000031 /* FIX: obsolete? */ -#define FSF_OUTBOUND_DATA_LENGTH_NOT_VALID 0x00000032 /* FIX: obsolete? */ #define FSF_CMND_LENGTH_NOT_VALID 0x00000033 #define FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED 0x00000040 #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041 -#define FSF_REQUEST_BUF_NOT_VALID 0x00000042 -#define FSF_RESPONSE_BUF_NOT_VALID 0x00000043 #define FSF_ELS_COMMAND_REJECTED 0x00000050 #define FSF_GENERIC_COMMAND_REJECTED 0x00000051 #define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052 @@ -112,6 +107,8 @@ #define FSF_PAYLOAD_SIZE_MISMATCH 0x00000060 #define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 #define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 +#define FSF_SBAL_MISMATCH 0x00000063 +#define FSF_OPEN_PORT_WITHOUT_PRLI 0x00000064 #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD #define FSF_FCP_RSP_AVAILABLE 0x000000AF #define FSF_UNKNOWN_COMMAND 0x000000E2 @@ -154,6 +151,7 @@ /* status types in status read buffer */ #define FSF_STATUS_READ_PORT_CLOSED 0x00000001 #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 +#define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 #define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ #define FSF_STATUS_READ_LINK_UP 0x00000006 @@ -196,11 +194,13 @@ /* channel features */ #define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 #define FSF_FEATURE_CFDC 0x00000002 +#define FSF_FEATURE_LUN_SHARING 0x00000004 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 /* option */ #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 +#define FSF_OPEN_LUN_REPLICATE_SENSE 0x00000002 /* adapter types */ #define FSF_ADAPTER_TYPE_FICON 0x00000001 @@ -227,6 +227,15 @@ #define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006 #define FSF_HBA_PORTSTATE_ERROR 0x00000007 +/* IO states of adapter */ +#define FSF_IOSTAT_NPORT_RJT 0x00000004 +#define FSF_IOSTAT_FABRIC_RJT 0x00000005 +#define FSF_IOSTAT_LS_RJT 0x00000009 + +/* open LUN access flags*/ +#define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000 +#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 +#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 struct fsf_queue_designator; struct fsf_status_read_buffer; @@ -381,7 +390,8 @@ struct fsf_qtcb_bottom_support { u32 service_class; u8 res3[3]; u8 timeout; - u8 res4[184]; + u32 lun_access_info; + u8 res4[180]; u32 els1_length; u32 els2_length; u32 req_buf_length; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 1939f1fe6..06e862d7b 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -12,6 +12,7 @@ * Raimund Schroeder * Wolfgang Taphorn * Heiko Carstens + * Andreas Herrmann * * 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 @@ -28,7 +29,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_QDIO_C_REVISION "$Revision: 1.19 $" +#define ZFCP_QDIO_C_REVISION "$Revision: 1.20 $" #include "zfcp_ext.h" diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index d0a879f0a..e21b547fd 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -12,6 +12,7 @@ * Wolfgang Taphorn * Stefan Bader * Heiko Carstens + * Andreas Herrmann * * 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 @@ -30,8 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -/* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.65 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.74 $" #include "zfcp_ext.h" @@ -48,6 +48,8 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8); static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, scsi_lun_t); +static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int, + scsi_id_t); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -79,7 +81,8 @@ struct zfcp_data zfcp_data = { unchecked_isa_dma: 0, use_clustering: 1, sdev_attrs: zfcp_sysfs_sdev_attrs, - } + }, + .driver_version = ZFCP_VERSION, /* rest initialised with zeros */ }; @@ -247,15 +250,16 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) /** * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and * zfcp_scsi_command_sync - * @adapter: adapter for where scsi command is issued + * @adapter: adapter where scsi command is issued * @unit: unit to which scsi command is sent * @scpnt: scsi command to be sent + * @timer: timer to be started if request is successfully initiated * * Note: In scsi_done function must be set in scpnt. */ int zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, - struct scsi_cmnd *scpnt) + struct scsi_cmnd *scpnt, struct timer_list *timer) { int tmp; int retval; @@ -291,7 +295,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, goto out; } - tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, + tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer, ZFCP_REQ_AUTO_CLEANUP); if (unlikely(tmp < 0)) { @@ -313,17 +317,27 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) /** * zfcp_scsi_command_sync - send a SCSI command and wait for completion - * returns 0, errors are indicated by scsi_cmnd->result + * @unit: unit where command is sent to + * @scpnt: scsi command to be sent + * @timer: timer to be started if request is successfully initiated + * Return: 0 + * + * Errors are indicated in scpnt->result */ int -zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt) +zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, + struct timer_list *timer) { + int ret; DECLARE_COMPLETION(wait); scpnt->SCp.ptr = (void *) &wait; /* silent re-use */ - scpnt->done = zfcp_scsi_command_sync_handler; - zfcp_scsi_command_async(unit->port->adapter, unit, scpnt); - wait_for_completion(&wait); + scpnt->scsi_done = zfcp_scsi_command_sync_handler; + ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer); + if (ret == 0) + wait_for_completion(&wait); + + scpnt->SCp.ptr = NULL; return 0; } @@ -355,7 +369,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; unit = (struct zfcp_unit *) scpnt->device->hostdata; - return zfcp_scsi_command_async(adapter, unit, scpnt); + return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); } /* @@ -388,6 +402,18 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, return retval; } +static struct zfcp_port * +zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) +{ + struct zfcp_port *port; + + list_for_each_entry(port, &adapter->port_list_head, list) { + if (id == port->scsi_id) + return port; + } + return (struct zfcp_port *) NULL; +} + /* * function: zfcp_scsi_eh_abort_handler * @@ -430,7 +456,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) u64 dbf_fsf_req = 0; u64 dbf_fsf_status = 0; u64 dbf_fsf_qual[2] = { 0, 0 }; - char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" }; + char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); memcpy(dbf_opcode, @@ -618,7 +644,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, &unit->status)) { retval = - zfcp_task_management_function(unit, LOGICAL_UNIT_RESET); + zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET); if (retval) { ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); if (retval == -ENOTSUPP) @@ -634,7 +660,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) goto out; } } - retval = zfcp_task_management_function(unit, TARGET_RESET); + retval = zfcp_task_management_function(unit, FCP_TARGET_RESET); if (retval) { ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); retval = FAILED; @@ -828,39 +854,63 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) * Support functions for FC transport class */ static void -zfcp_get_port_id(struct scsi_device *sdev) +zfcp_get_port_id(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_port_id(sdev) = unit->port->d_id; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_port_id(starget) = port->d_id; + else + fc_starget_port_id(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } static void -zfcp_get_port_name(struct scsi_device *sdev) +zfcp_get_port_name(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_port_name(sdev) = unit->port->wwpn; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_port_name(starget) = port->wwpn; + else + fc_starget_port_name(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } static void -zfcp_get_node_name(struct scsi_device *sdev) +zfcp_get_node_name(struct scsi_target *starget) { - struct zfcp_unit *unit; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; + struct zfcp_port *port; + unsigned long flags; - unit = (struct zfcp_unit *) sdev->hostdata; - fc_node_name(sdev) = unit->port->wwnn; + read_lock_irqsave(&zfcp_data.config_lock, flags); + port = zfcp_port_lookup(adapter, starget->channel, starget->id); + if (port) + fc_starget_node_name(starget) = port->wwnn; + else + fc_starget_node_name(starget) = -1; + read_unlock_irqrestore(&zfcp_data.config_lock, flags); } struct fc_function_template zfcp_transport_functions = { - .get_port_id = zfcp_get_port_id, - .get_port_name = zfcp_get_port_name, - .get_node_name = zfcp_get_node_name, - .show_port_id = 1, - .show_port_name = 1, - .show_node_name = 1, + .get_starget_port_id = zfcp_get_port_id, + .get_starget_port_name = zfcp_get_port_name, + .get_starget_node_name = zfcp_get_node_name, + .show_starget_port_id = 1, + .show_starget_port_name = 1, + .show_starget_node_name = 1, }; /** diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index d7536a11a..ff28ade1d 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -10,6 +10,7 @@ * Authors: * Martin Peschke * Heiko Carstens + * Andreas Herrmann * * 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 @@ -26,18 +27,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.33 $" +#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.38 $" #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG static const char fc_topologies[5][25] = { - {""}, - {"point-to-point"}, - {"fabric"}, - {"arbitrated loop"}, - {"fabric (virt. adapter)"} + "", + "point-to-point", + "fabric", + "arbitrated loop", + "fabric (virt. adapter)" }; /** @@ -74,29 +75,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); - -/** - * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of adapter. Will be - * "0" if no error recovery is pending for adapter, otherwise "1". - */ -static ssize_t -zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_adapter *adapter; - - adapter = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, - zfcp_sysfs_adapter_in_recovery_show, NULL); +ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); /** * zfcp_sysfs_port_add_store - add a port to sysfs tree @@ -127,7 +107,7 @@ zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count) if ((endp + 1) < (buf + count)) goto out; - port = zfcp_port_enqueue(adapter, wwpn, 0); + port = zfcp_port_enqueue(adapter, wwpn, 0, 0); if (!port) goto out; @@ -138,7 +118,7 @@ zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count) zfcp_port_put(port); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store); @@ -197,7 +177,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count) zfcp_port_dequeue(port); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store); @@ -241,7 +221,7 @@ zfcp_sysfs_adapter_failed_store(struct device *dev, zfcp_erp_wait(adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c index e0d6eecfe..77a5e2dcc 100644 --- a/drivers/s390/scsi/zfcp_sysfs_driver.c +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c @@ -10,6 +10,7 @@ * Authors: * Martin Peschke * Heiko Carstens + * Andreas Herrmann * * 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 @@ -26,7 +27,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.14 $" +#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.17 $" #include "zfcp_ext.h" @@ -65,7 +66,7 @@ static ssize_t zfcp_sysfs_loglevel_##_name##_store(struct device_driver *drv, \ static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev, \ char *buf) \ { \ - return sprintf(buf,"%d\n", \ + return sprintf(buf,"%d\n", (unsigned int) \ ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define)); \ } \ \ @@ -85,7 +86,7 @@ ZFCP_DEFINE_DRIVER_ATTR(fc, FC); static ssize_t zfcp_sysfs_version_show(struct device_driver *dev, char *buf) { - return sprintf(buf, "%s\n", ZFCP_VERSION); + return sprintf(buf, "%s\n", zfcp_data.driver_version); } static DRIVER_ATTR(version, S_IRUGO, zfcp_sysfs_version_show, NULL); diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index 11a27c1ff..6aafb2abb 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -10,6 +10,8 @@ * Authors: * Martin Peschke * Heiko Carstens + * Andreas Herrmann + * Volker Sameske * * 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 @@ -26,7 +28,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $" +#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.47 $" #include "zfcp_ext.h" @@ -66,6 +68,10 @@ ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status)); ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn); ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id); ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id); +ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); +ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status)); /** * zfcp_sysfs_unit_add_store - add a unit to sysfs tree @@ -107,7 +113,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count) zfcp_unit_put(unit); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); @@ -164,7 +170,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count) zfcp_unit_dequeue(unit); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); @@ -206,7 +212,7 @@ zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count) zfcp_erp_wait(port->adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** @@ -232,29 +238,6 @@ zfcp_sysfs_port_failed_show(struct device *dev, char *buf) static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show, zfcp_sysfs_port_failed_store); -/** - * zfcp_sysfs_port_in_recovery_show - recovery state of port - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of port. Will be - * "0" if no error recovery is pending for port, otherwise "1". - */ -static ssize_t -zfcp_sysfs_port_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_port *port; - - port = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show, - NULL); - /** * zfcp_port_common_attrs * sysfs attributes that are common for all kind of fc ports. @@ -265,6 +248,7 @@ static struct attribute *zfcp_port_common_attrs[] = { &dev_attr_status.attr, &dev_attr_wwnn.attr, &dev_attr_d_id.attr, + &dev_attr_access_denied.attr, NULL }; @@ -300,7 +284,7 @@ zfcp_sysfs_port_create_files(struct device *dev, u32 flags) retval = sysfs_create_group(&dev->kobj, &zfcp_port_common_attr_group); - if ((flags & ZFCP_STATUS_PORT_NAMESERVER) || retval) + if ((flags & ZFCP_STATUS_PORT_WKA) || retval) return retval; retval = sysfs_create_group(&dev->kobj, &zfcp_port_no_ns_attr_group); @@ -320,7 +304,7 @@ void zfcp_sysfs_port_remove_files(struct device *dev, u32 flags) { sysfs_remove_group(&dev->kobj, &zfcp_port_common_attr_group); - if (!(flags & ZFCP_STATUS_PORT_NAMESERVER)) + if (!(flags & ZFCP_STATUS_PORT_WKA)) sysfs_remove_group(&dev->kobj, &zfcp_port_no_ns_attr_group); } diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 904c8aead..87c0b4618 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -10,6 +10,8 @@ * Authors: * Martin Peschke * Heiko Carstens + * Andreas Herrmann + * Volker Sameske * * 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 @@ -26,7 +28,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.25 $" +#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.30 $" #include "zfcp_ext.h" @@ -64,6 +66,14 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL); ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun); +ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); +ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status)); +ZFCP_DEFINE_UNIT_ATTR(access_shared, "%d\n", atomic_test_mask + (ZFCP_STATUS_UNIT_SHARED, &unit->status)); +ZFCP_DEFINE_UNIT_ATTR(access_readonly, "%d\n", atomic_test_mask + (ZFCP_STATUS_UNIT_READONLY, &unit->status)); /** * zfcp_sysfs_unit_failed_store - failed state of unit @@ -101,7 +111,7 @@ zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count) zfcp_erp_wait(unit->port->adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** @@ -127,34 +137,14 @@ zfcp_sysfs_unit_failed_show(struct device *dev, char *buf) static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show, zfcp_sysfs_unit_failed_store); -/** - * zfcp_sysfs_unit_in_recovery_show - recovery state of unit - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of unit. Will be - * "0" if no error recovery is pending for unit, otherwise "1". - */ -static ssize_t -zfcp_sysfs_unit_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_unit *unit; - - unit = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_unit_in_recovery_show, - NULL); - static struct attribute *zfcp_unit_attrs[] = { &dev_attr_scsi_lun.attr, &dev_attr_failed.attr, &dev_attr_in_recovery.attr, &dev_attr_status.attr, + &dev_attr_access_denied.attr, + &dev_attr_access_shared.attr, + &dev_attr_access_readonly.attr, NULL }; diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index d45619f3b..a433252a5 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -60,12 +60,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -1531,8 +1531,7 @@ static void aurora_close(struct tty_struct * tty, struct file * filp) aurora_shutdown_port(bp, port); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; port->event = 0; port->tty = 0; @@ -1551,7 +1550,7 @@ static void aurora_close(struct tty_struct * tty, struct file * filp) #endif } -static int aurora_write(struct tty_struct * tty, int from_user, +static int aurora_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; @@ -1574,51 +1573,22 @@ static int aurora_write(struct tty_struct * tty, int from_user, return 0; save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, + SERIAL_XMIT_SIZE - port->xmit_head)); + if (c <= 0) { restore_flags(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - restore_flags(flags); + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + port->xmit_cnt += c; + restore_flags(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } cli(); @@ -1743,10 +1713,7 @@ static void aurora_flush_buffer(struct tty_struct *tty) port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; restore_flags(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); #ifdef AURORA_DEBUG printk("aurora_flush_buffer: end\n"); #endif @@ -2223,10 +2190,7 @@ static void do_softint(void *private_) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } #ifdef AURORA_DEBUG printk("do_softint: end\n"); @@ -2375,10 +2339,10 @@ int irq = 0; int irq1 = 0; int irq2 = 0; int irq3 = 0; -MODULE_PARM(irq , "i"); -MODULE_PARM(irq1, "i"); -MODULE_PARM(irq2, "i"); -MODULE_PARM(irq3, "i"); +module_param(irq , int, 0); +module_param(irq1, int, 0); +module_param(irq2, int, 0); +module_param(irq3, int, 0); static int __init aurora_init(void) { diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 37189ef06..d5259f7fe 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -452,7 +452,7 @@ static void fans_full_blast(void) } } -#define POLL_INTERVAL (5 * HZ) +#define POLL_INTERVAL (5 * 1000) static unsigned long last_warning_jiffies; static struct task_struct *kenvctrld_task; @@ -468,8 +468,7 @@ static int kenvctrld(void *__unused) struct bbc_cpu_temperature *tp; struct bbc_fan_control *fp; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(POLL_INTERVAL); + msleep_interruptible(POLL_INTERVAL); if (signal_pending(current)) break; diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index a489c544f..1c8b612d8 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -57,8 +57,8 @@ struct bbc_i2c_bus { struct bbc_i2c_bus *next; int index; spinlock_t lock; - void *i2c_bussel_reg; - void *i2c_control_regs; + void __iomem *i2c_bussel_reg; + void __iomem *i2c_control_regs; unsigned char own, clock; wait_queue_head_t wq; @@ -189,13 +189,13 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status) while (limit-- > 0) { u8 val; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); *status = val = readb(bp->i2c_control_regs + 0); if ((val & I2C_PCF_PIN) == 0) { ret = 0; break; } - schedule_timeout(HZ/4); + msleep_interruptible(250); } remove_wait_queue(&bp->wq, &wait); bp->waiting = 0; diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c index 8067aea1d..cf83dfd44 100644 --- a/drivers/sbus/char/bpp.c +++ b/drivers/sbus/char/bpp.c @@ -89,7 +89,7 @@ static struct inst instances[BPP_NO]; #if defined(__i386__) -const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; +static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; /* * These are for data access. @@ -246,7 +246,7 @@ static unsigned short get_pins(unsigned minor) #define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ #define P_ERR_IRQ_EN 0x0001 /* RW */ -unsigned long base_addrs[BPP_NO]; +static void __iomem *base_addrs[BPP_NO]; #define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) #define bpp_inb_p(base) sbus_readb((base) + BPP_DR) @@ -254,7 +254,7 @@ unsigned long base_addrs[BPP_NO]; static void set_pins(unsigned short pins, unsigned minor) { - unsigned long base = base_addrs[minor]; + void __iomem *base = base_addrs[minor]; unsigned char bits_tcr = 0, bits_or = 0; if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; @@ -275,7 +275,7 @@ static void set_pins(unsigned short pins, unsigned minor) */ static unsigned short get_pins(unsigned minor) { - unsigned long base = base_addrs[minor]; + void __iomem *base = base_addrs[minor]; unsigned short bits = 0; unsigned value_tcr = sbus_readb(base + BPP_TCR); unsigned value_ir = sbus_readb(base + BPP_IR); @@ -940,7 +940,7 @@ static inline void freeLptPort(int idx) #if defined(__sparc__) -static unsigned long map_bpp(struct sbus_dev *dev, int idx) +static void __iomem *map_bpp(struct sbus_dev *dev, int idx) { return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); } @@ -969,7 +969,7 @@ static int collectLptPorts(void) static void probeLptPort(unsigned idx) { - unsigned long rp = base_addrs[idx]; + void __iomem *rp = base_addrs[idx]; __u32 csr; char *brand; @@ -983,7 +983,7 @@ static void probeLptPort(unsigned idx) init_timer(&instances[idx].timer_list); instances[idx].timer_list.function = bpp_wake_up; - if (rp == 0) return; + if (!rp) return; instances[idx].present = 1; instances[idx].enhanced = 1; /* Sure */ @@ -1014,7 +1014,7 @@ static void probeLptPort(unsigned idx) default: brand = "Unknown"; } - printk("bpp%d: %s at 0x%lx\n", idx, brand, rp); + printk("bpp%d: %s at %p\n", idx, brand, rp); /* * Leave the port in compat idle mode. diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index ad870a300..c82abeb59 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -118,40 +118,26 @@ * UNKNOWN, MAGICAL MYSTERY REGISTER * */ -struct wd_timer_regblk { - volatile __u16 dcntr; /* down counter - hw */ - volatile __u16 dcntr_pad; - volatile __u16 limit; /* limit register - hw */ - volatile __u16 limit_pad; - volatile __u8 status; /* status register - b */ - volatile __u8 status_pad; - volatile __u16 status_pad2; - volatile __u32 pad32; /* yet more padding */ -}; +#define WD_TIMER_REGSZ 16 +#define WD0_OFF 0 +#define WD1_OFF (WD_TIMER_REGSZ * 1) +#define WD2_OFF (WD_TIMER_REGSZ * 2) +#define PLD_OFF (WD_TIMER_REGSZ * 3) -struct wd_pld_regblk { - volatile __u8 intr_mask; /* interrupt mask - b */ - volatile __u8 intr_mask_pad; - volatile __u16 intr_mask_pad2; - volatile __u8 status; /* device status - b */ - volatile __u8 status_pad; - volatile __u16 status_pad2; -}; +#define WD_DCNTR 0x00 +#define WD_LIMIT 0x04 +#define WD_STATUS 0x08 -struct wd_regblk { - volatile struct wd_timer_regblk wd0_regs; - volatile struct wd_timer_regblk wd1_regs; - volatile struct wd_timer_regblk wd2_regs; - volatile struct wd_pld_regblk pld_regs; -}; +#define PLD_IMASK (PLD_OFF + 0x00) +#define PLD_STATUS (PLD_OFF + 0x04) /* Individual timer structure */ struct wd_timer { __u16 timeout; __u8 intr_mask; - unsigned char runstatus; - volatile struct wd_timer_regblk* regs; + unsigned char runstatus; + void __iomem *regs; }; /* Device structure @@ -165,7 +151,7 @@ struct wd_device { unsigned short opt_timeout; unsigned char initialized; struct wd_timer watchdog[WD_NUMDEVS]; - volatile struct wd_regblk* regs; + void __iomem *regs; }; static struct wd_device wd_dev = { @@ -179,11 +165,11 @@ static int wd1_timeout = 0; static int wd2_timeout = 0; #ifdef MODULE -MODULE_PARM (wd0_timeout, "i"); +module_param (wd0_timeout, int, 0); MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); -MODULE_PARM (wd1_timeout, "i"); +module_param (wd1_timeout, int, 0); MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); -MODULE_PARM (wd2_timeout, "i"); +module_param (wd2_timeout, int, 0); MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); MODULE_AUTHOR @@ -495,12 +481,12 @@ static void wd_dumpregs(void) i, wd_getstatus(&wd_dev.watchdog[i])); } - printk("\tintr_mask at 0x%lx: 0x%x\n", - (unsigned long)(&wd_dev.regs->pld_regs.intr_mask), - readb(&wd_dev.regs->pld_regs.intr_mask)); - printk("\tpld_status at 0x%lx: 0x%x\n", - (unsigned long)(&wd_dev.regs->pld_regs.status), - readb(&wd_dev.regs->pld_regs.status)); + printk("\tintr_mask at %p: 0x%x\n", + wd_dev.regs + PLD_IMASK, + readb(wd_dev.regs + PLD_IMASK)); + printk("\tpld_status at %p: 0x%x\n", + wd_dev.regs + PLD_STATUS, + readb(wd_dev.regs + PLD_STATUS)); } #endif @@ -513,7 +499,7 @@ static void wd_dumpregs(void) */ static void wd_toggleintr(struct wd_timer* pTimer, int enable) { - unsigned char curregs = wd_readb(&wd_dev.regs->pld_regs.intr_mask); + unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK); unsigned char setregs = (NULL == pTimer) ? (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : @@ -523,7 +509,7 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable) (curregs &= ~setregs): (curregs |= setregs); - wd_writeb(curregs, &wd_dev.regs->pld_regs.intr_mask); + wd_writeb(curregs, wd_dev.regs + PLD_IMASK); return; } @@ -534,8 +520,8 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable) */ static void wd_pingtimer(struct wd_timer* pTimer) { - if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) { - wd_readw(&pTimer->regs->dcntr); + if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { + wd_readw(pTimer->regs + WD_DCNTR); } } @@ -547,7 +533,7 @@ static void wd_pingtimer(struct wd_timer* pTimer) */ static void wd_stoptimer(struct wd_timer* pTimer) { - if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) { + if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { wd_toggleintr(pTimer, WD_INTR_OFF); if(wd_dev.isbaddoggie) { @@ -574,7 +560,7 @@ static void wd_starttimer(struct wd_timer* pTimer) } pTimer->runstatus &= ~WD_STAT_SVCD; - wd_writew(pTimer->timeout, &pTimer->regs->limit); + wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT); wd_toggleintr(pTimer, WD_INTR_ON); } @@ -584,7 +570,7 @@ static void wd_starttimer(struct wd_timer* pTimer) static void wd_resetbrokentimer(struct wd_timer* pTimer) { wd_toggleintr(pTimer, WD_INTR_ON); - wd_writew(WD_BLIMIT, &pTimer->regs->limit); + wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT); } /* Timer device initialization helper. @@ -593,7 +579,7 @@ static void wd_resetbrokentimer(struct wd_timer* pTimer) static int wd_inittimer(int whichdog) { struct miscdevice *whichmisc; - volatile struct wd_timer_regblk *whichregs; + void __iomem *whichregs; char whichident[8]; int whichmask; __u16 whichlimit; @@ -603,7 +589,7 @@ static int wd_inittimer(int whichdog) case WD0_ID: whichmisc = &wd0_miscdev; strcpy(whichident, "RIC"); - whichregs = &wd_dev.regs->wd0_regs; + whichregs = wd_dev.regs + WD0_OFF; whichmask = WD0_INTR_MASK; whichlimit= (0 == wd0_timeout) ? (wd_dev.opt_timeout): @@ -612,7 +598,7 @@ static int wd_inittimer(int whichdog) case WD1_ID: whichmisc = &wd1_miscdev; strcpy(whichident, "XIR"); - whichregs = &wd_dev.regs->wd1_regs; + whichregs = wd_dev.regs + WD1_OFF; whichmask = WD1_INTR_MASK; whichlimit= (0 == wd1_timeout) ? (wd_dev.opt_timeout): @@ -621,7 +607,7 @@ static int wd_inittimer(int whichdog) case WD2_ID: whichmisc = &wd2_miscdev; strcpy(whichident, "POR"); - whichregs = &wd_dev.regs->wd2_regs; + whichregs = wd_dev.regs + WD2_OFF; whichmask = WD2_INTR_MASK; whichlimit= (0 == wd2_timeout) ? (wd_dev.opt_timeout): @@ -686,8 +672,8 @@ static void wd_brokentimer(unsigned long data) static int wd_getstatus(struct wd_timer* pTimer) { - unsigned char stat = wd_readb(&pTimer->regs->status); - unsigned char intr = wd_readb(&wd_dev.regs->pld_regs.intr_mask); + unsigned char stat = wd_readb(pTimer->regs + WD_STATUS); + unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK); unsigned char ret = WD_STOPPED; /* determine STOPPED */ @@ -757,7 +743,7 @@ ebus_done: } wd_dev.regs = - ioremap(edev->resource[0].start, sizeof(struct wd_regblk)); + ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */ if(NULL == wd_dev.regs) { printk("%s: unable to map registers\n", WD_OBPNAME); @@ -805,7 +791,7 @@ static void __exit wd_cleanup(void) * also now eventually trip. */ for(id = WD0_ID; id < WD_NUMDEVS; ++id) { - if(WD_S_RUNNING == wd_readb(&wd_dev.watchdog[id].regs->status)) { + if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) { if(wd_dev.opt_enable) { printk(KERN_WARNING "%s%i: timer not stopped at release\n", WD_OBPNAME, id); @@ -818,7 +804,7 @@ static void __exit wd_cleanup(void) "%s%i: defect workaround disabled at release, "\ "timer expires in ~%01i sec\n", WD_OBPNAME, id, - wd_readw(&wd_dev.watchdog[id].regs->limit) / 10); + wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10); } } } diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index e8ac0b4d3..dbad7f35e 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -44,8 +44,8 @@ static int sol_compat = 0; /* Solaris compatibility mode */ * If you wish the device to operate as under Solaris, * omitting above features, set this parameter to non-zero. */ -MODULE_PARM - (sol_compat, "1i"); +module_param + (sol_compat, int, 0); MODULE_PARM_DESC (sol_compat, "Disables documented functionality omitted from Solaris driver"); @@ -70,7 +70,7 @@ MODULE_SUPPORTED_DEVICE * FLIP - Inverts display for upside-down mounted board * bits 0-4 - 7-segment display contents */ -volatile u8* d7s_regs = NULL; +static void __iomem* d7s_regs; static inline void d7s_free(void) { diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index cd6e2d39f..f6ed35b24 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -130,10 +130,8 @@ static int errno; */ #define ENVCTRL_CPCI_IGNORED_NODE 0x70 -struct pcf8584_reg { - unsigned char data; - unsigned char csr; -}; +#define PCF8584_DATA 0x00 +#define PCF8584_CSR 0x01 /* Each child device can be monitored by up to PCF8584_MAX_CHANNELS. * Property of a port or channel as defined by the firmware. @@ -175,7 +173,7 @@ struct i2c_child_t { char mon_type[PCF8584_MAX_CHANNELS]; }; -volatile static struct pcf8584_reg *i2c = NULL; +static void __iomem *i2c; static struct i2c_child_t i2c_childlist[ENVCTRL_MAX_CPU*2]; static unsigned char chnls_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static unsigned int warning_temperature = 0; @@ -185,22 +183,6 @@ static char read_cpu; /* Forward declarations. */ static struct i2c_child_t *envctrl_get_i2c_child(unsigned char); -/* Function description: Read a byte from an i2c controller register. - * Return: A byte from the passed in address. - */ -static inline unsigned char envctrl_readb(volatile unsigned char *p) -{ - return readb(p); -} - -/* Function description: Write a byte to an i2c controller register. - * Return: Nothing. - */ -static inline void envctrl_writeb(unsigned char val, volatile unsigned char *p) -{ - writeb(val, p); -} - /* Function Description: Test the PIN bit (Pending Interrupt Not) * to test when serial transmission is completed . * Return : None. @@ -210,7 +192,7 @@ static void envtrl_i2c_test_pin(void) int limit = 1000000; while (--limit > 0) { - if (!(envctrl_readb(&i2c->csr) & STATUS_PIN)) + if (!(readb(i2c + PCF8584_CSR) & STATUS_PIN)) break; udelay(1); } @@ -228,7 +210,7 @@ static void envctrl_i2c_test_bb(void) while (--limit > 0) { /* Busy bit 0 means busy. */ - if (envctrl_readb(&i2c->csr) & STATUS_BB) + if (readb(i2c + PCF8584_CSR) & STATUS_BB) break; udelay(1); } @@ -245,20 +227,20 @@ static int envctrl_i2c_read_addr(unsigned char addr) envctrl_i2c_test_bb(); /* Load address. */ - envctrl_writeb(addr + 1, &i2c->data); + writeb(addr + 1, i2c + PCF8584_DATA); envctrl_i2c_test_bb(); - envctrl_writeb(OBD_SEND_START, &i2c->csr); + writeb(OBD_SEND_START, i2c + PCF8584_CSR); /* Wait for PIN. */ envtrl_i2c_test_pin(); /* CSR 0 means acknowledged. */ - if (!(envctrl_readb(&i2c->csr) & STATUS_LRB)) { - return envctrl_readb(&i2c->data); + if (!(readb(i2c + PCF8584_CSR) & STATUS_LRB)) { + return readb(i2c + PCF8584_DATA); } else { - envctrl_writeb(OBD_SEND_STOP, &i2c->csr); + writeb(OBD_SEND_STOP, i2c + PCF8584_CSR); return 0; } } @@ -269,10 +251,10 @@ static int envctrl_i2c_read_addr(unsigned char addr) static void envctrl_i2c_write_addr(unsigned char addr) { envctrl_i2c_test_bb(); - envctrl_writeb(addr, &i2c->data); + writeb(addr, i2c + PCF8584_DATA); /* Generate Start condition. */ - envctrl_writeb(OBD_SEND_START, &i2c->csr); + writeb(OBD_SEND_START, i2c + PCF8584_CSR); } /* Function Description: Read 1 byte of data from addr @@ -282,8 +264,8 @@ static void envctrl_i2c_write_addr(unsigned char addr) static unsigned char envctrl_i2c_read_data(void) { envtrl_i2c_test_pin(); - envctrl_writeb(CONTROL_ES0, &i2c->csr); /* Send neg ack. */ - return envctrl_readb(&i2c->data); + writeb(CONTROL_ES0, i2c + PCF8584_CSR); /* Send neg ack. */ + return readb(i2c + PCF8584_DATA); } /* Function Description: Instruct the device which port to read data from. @@ -292,7 +274,7 @@ static unsigned char envctrl_i2c_read_data(void) static void envctrl_i2c_write_data(unsigned char port) { envtrl_i2c_test_pin(); - envctrl_writeb(port, &i2c->data); + writeb(port, i2c + PCF8584_DATA); } /* Function Description: Generate Stop condition after last byte is sent. @@ -301,7 +283,7 @@ static void envctrl_i2c_write_data(unsigned char port) static void envctrl_i2c_stop(void) { envtrl_i2c_test_pin(); - envctrl_writeb(OBD_SEND_STOP, &i2c->csr); + writeb(OBD_SEND_STOP, i2c + PCF8584_CSR); } /* Function Description: Read adc device. @@ -323,7 +305,7 @@ static unsigned char envctrl_i2c_read_8591(unsigned char addr, unsigned char por envctrl_i2c_read_data(); envctrl_i2c_stop(); - return envctrl_readb(&i2c->data); + return readb(i2c + PCF8584_DATA); } /* Function Description: Read gpio device. @@ -1084,8 +1066,7 @@ static int __init envctrl_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if (!strcmp(edev->prom_name, "i2c")) { - i2c = ioremap( edev->resource[0].start, - sizeof(struct pcf8584_reg)); + i2c = ioremap(edev->resource[0].start, 0x2); for_each_edevchild(edev, edev_child) { if (!strcmp("gpio", edev_child->prom_name)) { i2c_childlist[i].i2ctype = I2C_GPIO; @@ -1108,15 +1089,15 @@ done: } /* Set device address. */ - envctrl_writeb(CONTROL_PIN, &i2c->csr); - envctrl_writeb(PCF8584_ADDRESS, &i2c->data); + writeb(CONTROL_PIN, i2c + PCF8584_CSR); + writeb(PCF8584_ADDRESS, i2c + PCF8584_DATA); /* Set system clock and SCL frequencies. */ - envctrl_writeb(CONTROL_PIN | CONTROL_ES1, &i2c->csr); - envctrl_writeb(CLK_4_43 | BUS_CLK_90, &i2c->data); + writeb(CONTROL_PIN | CONTROL_ES1, i2c + PCF8584_CSR); + writeb(CLK_4_43 | BUS_CLK_90, i2c + PCF8584_DATA); /* Enable serial interface. */ - envctrl_writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, &i2c->csr); + writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c + PCF8584_CSR); udelay(200); /* Register the device as a minor miscellaneous device. */ diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index f35cb3276..40a400e26 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -22,6 +22,7 @@ #include #include #include +#include static spinlock_t flash_lock = SPIN_LOCK_UNLOCKED; static struct { @@ -65,7 +66,7 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) if ((vma->vm_pgoff << PAGE_SHIFT) > size) return -ENXIO; - addr += (vma->vm_pgoff << PAGE_SHIFT); + addr = vma->vm_pgoff + (addr >> PAGE_SHIFT); if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size) size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); @@ -74,7 +75,7 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) pgprot_val(vma->vm_page_prot) |= _PAGE_E; vma->vm_flags |= (VM_SHM | VM_LOCKED); - if (remap_page_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) + if (remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) return -EAGAIN; return 0; @@ -115,7 +116,7 @@ flash_read(struct file * file, char __user * buf, count = flash.read_size - p; for (i = 0; i < count; i++) { - u8 data = readb(flash.read_base + p + i); + u8 data = upa_readb(flash.read_base + p + i); if (put_user(data, buf)) return -EFAULT; buf++; diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 399c6c7b1..0b886c69b 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -21,7 +21,7 @@ * as a silly safeguard. * * XXX The flash.c manipulates page caching characteristics in a certain - * dubious way; also it assumes that remap_page_range() can remap + * dubious way; also it assumes that remap_pfn_range() can remap * PCI bus locations, which may be false. ioremap() must be used * instead. We should discuss this. */ diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c index 7f8e109f9..9325cf783 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/sbus/char/riowatchdog.c @@ -54,12 +54,12 @@ MODULE_LICENSE("GPL"); static spinlock_t riowd_lock = SPIN_LOCK_UNLOCKED; -static void *bbc_regs; -static void *riowd_regs; +static void __iomem *bbc_regs; +static void __iomem *riowd_regs; #define WDTO_INDEX 0x05 static int riowd_timeout = 1; /* in minutes */ -MODULE_PARM(riowd_timeout,"i"); +module_param(riowd_timeout, int, 0); MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); #if 0 /* Currently unused. */ diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c index c095308db..378a1d680 100644 --- a/drivers/sbus/dvma.c +++ b/drivers/sbus/dvma.c @@ -17,14 +17,6 @@ struct sbus_dma *dma_chain; -/* Print out the current values in the DMA control registers */ -extern __inline__ void dump_dma_regs(unsigned long dregs) -{ - printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n", - sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR), - sbus_readl(dregs + DMA_COUNT), sbus_readl(dregs + DMA_TEST)); -} - void __init init_one_dvma(struct sbus_dma *dma, int num_dma) { printk("dma%d: ", num_dma); @@ -64,9 +56,6 @@ void __init init_one_dvma(struct sbus_dma *dma, int num_dma) break; } printk("\n"); -#if 0 /* Clutters up the screen */ - dump_dma_regs(dma->regs); -#endif } /* Probe this SBus DMA module(s) */ diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 2bac40c0e..199698597 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1746,6 +1746,7 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd twa_free_request_id(tw_dev, request_id); SCpnt->result = (DID_ERROR << 16); done(SCpnt); + retval = 0; } return retval; diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 3c91ce6ed..29f70d531 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -453,13 +453,13 @@ static twa_message_type twa_error_table[] = { /* Macros */ #define TW_CONTROL_REG_ADDR(x) (x->base_addr) -#define TW_STATUS_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x4) +#define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) #if BITS_PER_LONG > 32 -#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x20) +#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x20) #else -#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0x8) +#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x8) #endif -#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char *)x->base_addr + 0xC) +#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) @@ -655,7 +655,7 @@ typedef struct TAG_TW_Compatibility_Info } TW_Compatibility_Info; typedef struct TAG_TW_Device_Extension { - u32 *base_addr; + u32 __iomem *base_addr; unsigned long *generic_buffer_virt[TW_Q_LENGTH]; unsigned long generic_buffer_phys[TW_Q_LENGTH]; TW_Command_Full *command_packet_virt[TW_Q_LENGTH]; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index b8731f204..9073638c8 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -184,327 +184,386 @@ 1.26.00.039 - Fix bug in tw_chrdev_ioctl() polling code. Fix data_buffer_length usage in tw_chrdev_ioctl(). Update contact information. + 1.26.02.000 - Convert driver to pci_driver format. */ #include - -MODULE_AUTHOR ("3ware Inc."); -#ifdef CONFIG_SMP -MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver (SMP)"); -#else -MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver"); -#endif -MODULE_LICENSE("GPL"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include - -#include +#include +#include +#include +#include +#include #include #include #include - -#define __3W_C /* let 3w-xxxx.h know it is use */ - -#include "scsi.h" +#include #include - +#include +#include #include "3w-xxxx.h" -static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int tw_chrdev_open(struct inode *inode, struct file *file); -static int tw_chrdev_release(struct inode *inode, struct file *file); -static int tw_copy_info(TW_Info *info, char *fmt, ...); -static void tw_copy_mem_info(TW_Info *info, char *data, int len); -static int tw_halt(struct notifier_block *nb, ulong event, void *buf); -static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd); -static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd); -static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd); - -/* Notifier block to get a notify on system shutdown/halt/reboot */ -static struct notifier_block tw_notifier = { - tw_halt, NULL, 0 -}; - -/* File operations struct for character device */ -static struct file_operations tw_fops = { - .owner = THIS_MODULE, - .ioctl = tw_chrdev_ioctl, - .open = tw_chrdev_open, - .release = tw_chrdev_release -}; - /* Globals */ -char *tw_driver_version="1.26.00.039"; -TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; -int tw_device_extension_count = 0; +#define TW_DRIVER_VERSION "1.26.02.000" +static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; +static int tw_device_extension_count = 0; static int twe_major = -1; -static int cmds_per_lun; /* Module parameters */ -module_param(cmds_per_lun, int, 0); -MODULE_PARM_DESC(cmds_per_lun, "Maximum commands per LUN"); +MODULE_AUTHOR("AMCC"); +MODULE_DESCRIPTION("3ware Storage Controller Linux Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(TW_DRIVER_VERSION); + +/* Function prototypes */ +static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); /* Functions */ -/* This function will complete an aen request from the isr */ -int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) +/* This function will check the status register for unexpected bits */ +static int tw_check_bits(u32 status_reg_value) { - TW_Param *param; - unsigned short aen; - int error = 0, table_max = 0; - - dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n"); - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n"); + if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { + dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value); + return 1; + } + if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) { + dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value); return 1; } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - aen = *(unsigned short *)(param->data); - dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen); - /* Print some useful info when certain aen codes come out */ - if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); - } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); - if ((aen & 0x0ff) < table_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 { - if (aen != 0x0) - 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); - } + return 0; +} /* End tw_check_bits() */ + +/* This function will print readable messages from status register errors */ +static int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host) +{ + char host[16]; + + dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n"); + + if (print_host) + sprintf(host, " scsi%d:", tw_dev->host->host_no); + else + host[0] = '\0'; + + if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) { + printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host); + outl(TW_CONTROL_CLEAR_PARITY_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); } - if (aen != TW_AEN_QUEUE_EMPTY) { - tw_dev->aen_count++; - /* Now queue the code */ - tw_dev->aen_queue[tw_dev->aen_tail] = aen; - if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { - tw_dev->aen_tail = TW_Q_START; - } else { - tw_dev->aen_tail = tw_dev->aen_tail + 1; - } - if (tw_dev->aen_head == tw_dev->aen_tail) { - if (tw_dev->aen_head == TW_Q_LENGTH - 1) { - tw_dev->aen_head = TW_Q_START; - } else { - tw_dev->aen_head = tw_dev->aen_head + 1; - } - } + if (status_reg_value & TW_STATUS_PCI_ABORT) { + printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host); + outl(TW_CONTROL_CLEAR_PCI_ABORT, TW_CONTROL_REG_ADDR(tw_dev)); + pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); + } - error = tw_aen_read_queue(tw_dev, request_id); - if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - } - } else { - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); + if (status_reg_value & TW_STATUS_QUEUE_ERROR) { + printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host); + outl(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); } + if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { + printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host); + outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); + } + + if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { + if (tw_dev->reset_print == 0) { + printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); + tw_dev->reset_print = 1; + } + return 1; + } + return 0; -} /* End tw_aen_complete() */ +} /* End tw_decode_bits() */ -/* This function will drain the aen queue after a soft reset */ -int tw_aen_drain_queue(TW_Device_Extension *tw_dev) +/* This function will poll the status register for a flag */ +static int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds) { - TW_Command *command_packet; - TW_Param *param; - int request_id = 0; - u32 command_que_addr; - unsigned long command_que_value; - unsigned long param_value; - TW_Response_Queue response_queue; - u32 response_que_addr; - unsigned short aen; - unsigned short aen_code; - int finished = 0; - int first_reset = 0; - int queue = 0; - int found = 0, table_max = 0; + u32 status_reg_value; + unsigned long before; + int retval = 1; - dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n"); + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + before = jiffies; - command_que_addr = tw_dev->registers.command_que_addr; - response_que_addr = tw_dev->registers.response_que_addr; + if (tw_check_bits(status_reg_value)) + tw_decode_bits(tw_dev, status_reg_value, 0); - if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) { - dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count); - return 1; + while ((status_reg_value & flag) != flag) { + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + + if (tw_check_bits(status_reg_value)) + tw_decode_bits(tw_dev, status_reg_value, 0); + + if (time_after(jiffies, before + HZ * seconds)) + goto out; + + msleep(50); } - tw_clear_attention_interrupt(tw_dev); + retval = 0; +out: + return retval; +} /* End tw_poll_status() */ - /* Empty response queue */ - tw_empty_response_que(tw_dev); +/* This function will poll the status register for disappearance of a flag */ +static int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds) +{ + u32 status_reg_value; + unsigned long before; + int retval = 1; - /* Initialize command packet */ - if (tw_dev->command_packet_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n"); - return 1; + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + before = jiffies; + + if (tw_check_bits(status_reg_value)) + tw_decode_bits(tw_dev, status_reg_value, 0); + + while ((status_reg_value & flag) != 0) { + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + + if (tw_check_bits(status_reg_value)) + tw_decode_bits(tw_dev, status_reg_value, 0); + + if (time_after(jiffies, before + HZ * seconds)) + goto out; + + msleep(50); } - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; + retval = 0; +out: + return retval; +} /* End tw_poll_status_gone() */ + +/* This function will attempt to post a command packet to the board */ +static int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id) +{ + u32 status_reg_value; + unsigned long command_que_value; + + dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n"); command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n"); - return 1; - } + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); - /* Now setup the param */ - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n"); - return 1; + if (tw_check_bits(status_reg_value)) { + dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); + tw_decode_bits(tw_dev, status_reg_value, 1); } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - memset(param, 0, sizeof(TW_Sector)); - param->table_id = 0x401; /* AEN table */ - param->parameter_id = 2; /* Unit code */ - param->parameter_size_bytes = 2; - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n"); + + if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) { + /* We successfully posted the command packet */ + outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + tw_dev->state[request_id] = TW_S_POSTED; + tw_dev->posted_request_count++; + if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) { + tw_dev->max_posted_request_count = tw_dev->posted_request_count; + } + } else { + /* Couldn't post the command packet, so we do it in the isr */ + if (tw_dev->state[request_id] != TW_S_PENDING) { + tw_dev->state[request_id] = TW_S_PENDING; + tw_dev->pending_request_count++; + if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) { + tw_dev->max_pending_request_count = tw_dev->pending_request_count; + } + tw_dev->pending_queue[tw_dev->pending_tail] = request_id; + if (tw_dev->pending_tail == TW_Q_LENGTH-1) { + tw_dev->pending_tail = TW_Q_START; + } else { + tw_dev->pending_tail = tw_dev->pending_tail + 1; + } + } + TW_UNMASK_COMMAND_INTERRUPT(tw_dev); return 1; } - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + return 0; +} /* End tw_post_command_packet() */ - /* Now drain the controller's aen queue */ - do { - /* Post command packet */ - outl(command_que_value, command_que_addr); +/* This function will return valid sense buffer information for failed cmds */ +static int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense) +{ + int i; + TW_Command *command; - /* Now poll for completion */ - if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { - response_queue.value = inl(response_que_addr); - request_id = (unsigned char)response_queue.u.response_id; + dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n"); + command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (request_id != 0) { - /* Unexpected request id */ - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n"); - return 1; - } - - if (command_packet->status != 0) { - if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) { - /* Bad response */ - tw_decode_sense(tw_dev, request_id, 0); - return 1; - } else { - /* We know this is a 3w-1x00, and doesn't support aen's */ - return 0; - } - } + printk(KERN_WARNING "3w-xxxx: scsi%d: Command failed: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, command->status, command->flags, TW_UNIT_OUT(command->unit__hostid)); - /* Now check the aen */ - aen = *(unsigned short *)(param->data); - aen_code = (aen & 0x0ff); - queue = 0; - switch (aen_code) { - case TW_AEN_QUEUE_EMPTY: - dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); - if (first_reset != 1) { - return 1; - } else { - finished = 1; - } - break; - case TW_AEN_SOFT_RESET: - if (first_reset == 0) { - first_reset = 1; - } else { - printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); - tw_dev->aen_count++; - queue = 1; - } - break; - default: - if (aen == 0x0ff) { - printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); - } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); - if ((aen & 0x0ff) < table_max) { - if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { - printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8); - } else { - printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); - } - } else - printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen); - } - tw_dev->aen_count++; - queue = 1; - } + /* Attempt to return intelligent sense information */ + if (fill_sense) { + if ((command->status == 0xc7) || (command->status == 0xcb)) { + for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) { + if (command->flags == tw_sense_table[i][0]) { - /* Now put the aen on the aen_queue */ - if (queue == 1) { - tw_dev->aen_queue[tw_dev->aen_tail] = aen; - if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { - tw_dev->aen_tail = TW_Q_START; - } else { - tw_dev->aen_tail = tw_dev->aen_tail + 1; - } - if (tw_dev->aen_head == tw_dev->aen_tail) { - if (tw_dev->aen_head == TW_Q_LENGTH - 1) { - tw_dev->aen_head = TW_Q_START; - } else { - tw_dev->aen_head = tw_dev->aen_head + 1; - } + /* Valid bit and 'current errors' */ + tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70); + + /* Sense key */ + tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1]; + + /* Additional sense length */ + tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */ + + /* Additional sense code */ + tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2]; + + /* Additional sense code qualifier */ + tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3]; + + tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */ } } - found = 1; - } - if (found == 0) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n"); - return 1; } - } while (finished == 0); + + /* If no table match, error so we get a reset */ + return 1; + } return 0; -} /* End tw_aen_drain_queue() */ +} /* End tw_decode_sense() */ + +/* This function will report controller error status */ +static int tw_check_errors(TW_Device_Extension *tw_dev) +{ + u32 status_reg_value; + + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + + if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) { + tw_decode_bits(tw_dev, status_reg_value, 0); + return 1; + } + + return 0; +} /* End tw_check_errors() */ + +/* This function will empty the response que */ +static void tw_empty_response_que(TW_Device_Extension *tw_dev) +{ + u32 status_reg_value, response_que_value; + + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + + while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { + response_que_value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + } +} /* End tw_empty_response_que() */ + +/* This function will free a request_id */ +static void tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id) +{ + tw_dev->free_queue[tw_dev->free_tail] = request_id; + tw_dev->state[request_id] = TW_S_FINISHED; + tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; +} /* End tw_state_request_finish() */ + +/* This function will assign an available request_id */ +static void tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id) +{ + *request_id = tw_dev->free_queue[tw_dev->free_head]; + tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH; + tw_dev->state[*request_id] = TW_S_STARTED; +} /* End tw_state_request_start() */ + +/* Show some statistics about the card */ +static ssize_t tw_show_stats(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(class_dev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; + unsigned long flags = 0; + ssize_t len; + + spin_lock_irqsave(tw_dev->host->host_lock, flags); + len = snprintf(buf, PAGE_SIZE, "3w-xxxx Driver version: %s\n" + "Current commands posted: %4d\n" + "Max commands posted: %4d\n" + "Current pending commands: %4d\n" + "Max pending commands: %4d\n" + "Last sgl length: %4d\n" + "Max sgl length: %4d\n" + "Last sector count: %4d\n" + "Max sector count: %4d\n" + "SCSI Host Resets: %4d\n" + "AEN's: %4d\n", + TW_DRIVER_VERSION, + tw_dev->posted_request_count, + tw_dev->max_posted_request_count, + tw_dev->pending_request_count, + tw_dev->max_pending_request_count, + tw_dev->sgl_entries, + tw_dev->max_sgl_entries, + tw_dev->sector_count, + tw_dev->max_sector_count, + tw_dev->num_resets, + tw_dev->aen_count); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + return len; +} /* End tw_show_stats() */ + +/* This function will set a devices queue depth */ +static ssize_t tw_store_queue_depth(struct device *dev, const char *buf, size_t count) +{ + int queue_depth; + struct scsi_device *sdev = to_scsi_device(dev); + + queue_depth = simple_strtoul(buf, NULL, 0); + if (queue_depth > TW_Q_LENGTH-2) + return -EINVAL; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + + return count; +} /* End tw_store_queue_depth() */ + +/* Create sysfs 'queue_depth' entry */ +static struct device_attribute tw_queue_depth_attr = { + .attr = { + .name = "queue_depth", + .mode = S_IRUSR | S_IWUSR, + }, + .store = tw_store_queue_depth +}; + +/* Device attributes initializer */ +static struct device_attribute *tw_dev_attrs[] = { + &tw_queue_depth_attr, + NULL, +}; + +/* Create sysfs 'stats' entry */ +static struct class_device_attribute tw_host_stats_attr = { + .attr = { + .name = "stats", + .mode = S_IRUGO, + }, + .show = tw_show_stats +}; + +/* Host attributes initializer */ +static struct class_device_attribute *tw_host_attrs[] = { + &tw_host_stats_attr, + NULL, +}; /* This function will read the aen queue from the isr */ -int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) +static int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) { TW_Command *command_packet; TW_Param *param; - u32 command_que_addr; unsigned long command_que_value; - u32 status_reg_value = 0, status_reg_addr; + u32 status_reg_value; unsigned long param_value = 0; dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n"); - command_que_addr = tw_dev->registers.command_que_addr; - status_reg_addr = tw_dev->registers.status_reg_addr; - status_reg_value = inl(status_reg_addr); + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); if (tw_check_bits(status_reg_value)) { dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value, 1); @@ -516,12 +575,9 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) } command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); command_packet->size = 4; command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; command_packet->status = 0; command_packet->flags = 0; command_packet->byte6.parameter_count = 1; @@ -551,9 +607,9 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) /* Now post the command packet */ if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) { dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n"); - tw_dev->srb[request_id] = 0; /* Flag internal command */ + tw_dev->srb[request_id] = NULL; /* Flag internal command */ tw_dev->state[request_id] = TW_S_POSTED; - outl(command_que_value, command_que_addr); + outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); } else { printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n"); return 1; @@ -562,86 +618,277 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) return 0; } /* End tw_aen_read_queue() */ -/* This function will allocate memory */ -int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) +/* This function will complete an aen request from the isr */ +static int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id) { - int i; - dma_addr_t dma_handle; - unsigned long *cpu_addr = NULL; - - dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n"); + TW_Param *param; + unsigned short aen; + int error = 0, table_max = 0; - cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle); - if (cpu_addr == NULL) { - printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n"); + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n"); return 1; } + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + aen = *(unsigned short *)(param->data); + dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen); - if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { - printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); - pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle); - return 1; + /* Print some useful info when certain aen codes come out */ + if (aen == 0x0ff) { + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); + } else { + table_max = sizeof(tw_aen_string)/sizeof(char *); + if ((aen & 0x0ff) < table_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 { + if (aen != 0x0) + 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); + } } + if (aen != TW_AEN_QUEUE_EMPTY) { + tw_dev->aen_count++; - memset(cpu_addr, 0, size*TW_Q_LENGTH); + /* Now queue the code */ + tw_dev->aen_queue[tw_dev->aen_tail] = aen; + if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { + tw_dev->aen_tail = TW_Q_START; + } else { + tw_dev->aen_tail = tw_dev->aen_tail + 1; + } + if (tw_dev->aen_head == tw_dev->aen_tail) { + if (tw_dev->aen_head == TW_Q_LENGTH - 1) { + tw_dev->aen_head = TW_Q_START; + } else { + tw_dev->aen_head = tw_dev->aen_head + 1; + } + } - for (i=0;icommand_packet_physical_address[i] = dma_handle+(i*size); - tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); - break; - case 1: - tw_dev->alignment_physical_address[i] = dma_handle+(i*size); - tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); - break; - default: - printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n"); - return 1; + error = tw_aen_read_queue(tw_dev, request_id); + if (error) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); } + } else { + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); } return 0; -} /* End tw_allocate_memory() */ +} /* End tw_aen_complete() */ -/* This function will check the status register for unexpected bits */ -int tw_check_bits(u32 status_reg_value) +/* This function will drain the aen queue after a soft reset */ +static int tw_aen_drain_queue(TW_Device_Extension *tw_dev) { - if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { - dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value); - return 1; - } - if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) { - dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value); - return 1; - } - - return 0; -} /* End tw_check_bits() */ + TW_Command *command_packet; + TW_Param *param; + int request_id = 0; + unsigned long command_que_value; + unsigned long param_value; + TW_Response_Queue response_queue; + unsigned short aen; + unsigned short aen_code; + int finished = 0; + int first_reset = 0; + int queue = 0; + int found = 0, table_max = 0; -/* This function will report controller error status */ -int tw_check_errors(TW_Device_Extension *tw_dev) -{ - u32 status_reg_addr, status_reg_value; - - status_reg_addr = tw_dev->registers.status_reg_addr; - status_reg_value = inl(status_reg_addr); + dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n"); - if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) { - tw_decode_bits(tw_dev, status_reg_value, 0); + if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) { + dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count); return 1; } + TW_CLEAR_ATTENTION_INTERRUPT(tw_dev); - return 0; -} /* End tw_check_errors() */ + /* Empty response queue */ + tw_empty_response_que(tw_dev); -/* This function handles ioctl for the character device */ -static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - int error, request_id; - dma_addr_t dma_handle; - unsigned short tw_aen_code; - unsigned long flags; + /* Initialize command packet */ + if (tw_dev->command_packet_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n"); + return 1; + } + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n"); + return 1; + } + + /* Now setup the param */ + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n"); + return 1; + } + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + memset(param, 0, sizeof(TW_Sector)); + param->table_id = 0x401; /* AEN table */ + param->parameter_id = 2; /* Unit code */ + param->parameter_size_bytes = 2; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n"); + return 1; + } + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + + /* Now drain the controller's aen queue */ + do { + /* Post command packet */ + outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + + /* Now poll for completion */ + if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { + response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + request_id = TW_RESID_OUT(response_queue.response_id); + + if (request_id != 0) { + /* Unexpected request id */ + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n"); + return 1; + } + + if (command_packet->status != 0) { + if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) { + /* Bad response */ + tw_decode_sense(tw_dev, request_id, 0); + return 1; + } else { + /* We know this is a 3w-1x00, and doesn't support aen's */ + return 0; + } + } + + /* Now check the aen */ + aen = *(unsigned short *)(param->data); + aen_code = (aen & 0x0ff); + queue = 0; + switch (aen_code) { + case TW_AEN_QUEUE_EMPTY: + dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); + if (first_reset != 1) { + return 1; + } else { + finished = 1; + } + break; + case TW_AEN_SOFT_RESET: + if (first_reset == 0) { + first_reset = 1; + } else { + printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); + tw_dev->aen_count++; + queue = 1; + } + break; + default: + if (aen == 0x0ff) { + printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); + } else { + table_max = sizeof(tw_aen_string)/sizeof(char *); + if ((aen & 0x0ff) < table_max) { + if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { + printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8); + } else { + printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]); + } + } else + printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen); + } + tw_dev->aen_count++; + queue = 1; + } + + /* Now put the aen on the aen_queue */ + if (queue == 1) { + tw_dev->aen_queue[tw_dev->aen_tail] = aen; + if (tw_dev->aen_tail == TW_Q_LENGTH - 1) { + tw_dev->aen_tail = TW_Q_START; + } else { + tw_dev->aen_tail = tw_dev->aen_tail + 1; + } + if (tw_dev->aen_head == tw_dev->aen_tail) { + if (tw_dev->aen_head == TW_Q_LENGTH - 1) { + tw_dev->aen_head = TW_Q_START; + } else { + tw_dev->aen_head = tw_dev->aen_head + 1; + } + } + } + found = 1; + } + if (found == 0) { + printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n"); + return 1; + } + } while (finished == 0); + + return 0; +} /* End tw_aen_drain_queue() */ + +/* This function will allocate memory */ +static int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which) +{ + int i; + dma_addr_t dma_handle; + unsigned long *cpu_addr = NULL; + + dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n"); + + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle); + if (cpu_addr == NULL) { + printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n"); + return 1; + } + + if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) { + printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n"); + pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle); + return 1; + } + + memset(cpu_addr, 0, size*TW_Q_LENGTH); + + for (i=0;icommand_packet_physical_address[i] = dma_handle+(i*size); + tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); + break; + case 1: + tw_dev->alignment_physical_address[i] = dma_handle+(i*size); + tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size)); + break; + default: + printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n"); + return 1; + } + } + + return 0; +} /* End tw_allocate_memory() */ + +/* This function handles ioctl for the character device */ +static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int request_id; + dma_addr_t dma_handle; + unsigned short tw_aen_code; + unsigned long flags; unsigned int data_buffer_length = 0; unsigned long data_buffer_length_adjusted = 0; unsigned long *cpu_addr; @@ -659,8 +906,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int return -EINTR; /* First copy down the buffer length */ - error = copy_from_user(&data_buffer_length, argp, sizeof(unsigned int)); - if (error) + if (copy_from_user(&data_buffer_length, argp, sizeof(unsigned int))) goto out; /* Check size */ @@ -673,7 +919,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int data_buffer_length_adjusted = (data_buffer_length + 511) & ~511; /* Now allocate ioctl buf memory */ - cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle); + cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle, GFP_KERNEL); if (cpu_addr == NULL) { retval = -ENOMEM; goto out; @@ -682,8 +928,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int tw_ioctl = (TW_New_Ioctl *)cpu_addr; /* Now copy down the entire ioctl */ - error = copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1); - if (error) + if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1)) goto out2; passthru = (TW_Passthru *)&tw_ioctl->firmware_command; @@ -713,12 +958,12 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int break; case TW_CMD_PACKET_WITH_DATA: dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n"); - spin_lock_irqsave(&tw_dev->tw_lock, flags); + spin_lock_irqsave(tw_dev->host->host_lock, flags); tw_state_request_start(tw_dev, &request_id); /* Flag internal command */ - tw_dev->srb[request_id] = 0; + tw_dev->srb[request_id] = NULL; /* Flag chrdev ioctl */ tw_dev->chrdev_request_id = request_id; @@ -726,7 +971,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int tw_ioctl->firmware_command.request_id = request_id; /* Load the sg list */ - switch (tw_ioctl->firmware_command.byte0.sgl_offset) { + switch (TW_SGL_OUT(tw_ioctl->firmware_command.opcode__sgloffset)) { case 2: tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1; tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted; @@ -745,13 +990,20 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int /* Now post the command packet to the controller */ tw_post_command_packet(tw_dev, request_id); - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ; /* Now wait for the command to complete */ timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); + /* See if we reset while waiting for the ioctl to complete */ + if (test_bit(TW_IN_RESET, &tw_dev->flags)) { + clear_bit(TW_IN_RESET, &tw_dev->flags); + retval = -ERESTARTSYS; + goto out2; + } + /* Check if we timed out, got a signal, or didn't get an interrupt */ if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) { @@ -762,14 +1014,14 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd); retval = -EIO; } - spin_lock_irqsave(&tw_dev->tw_lock, flags); + spin_lock_irqsave(tw_dev->host->host_lock, flags); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); tw_dev->posted_request_count--; - if (tw_reset_device_extension(tw_dev)) { + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + if (tw_reset_device_extension(tw_dev, 1)) { printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); } - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); goto out2; } @@ -777,11 +1029,11 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command)); /* Now complete the io */ - spin_lock_irqsave(&tw_dev->tw_lock, flags); + spin_lock_irqsave(tw_dev->host->host_lock, flags); tw_dev->posted_request_count--; tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); break; default: retval = -ENOTTY; @@ -789,12 +1041,12 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int } /* Now copy the response to userspace */ - error = copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1); - if (error == 0) - retval = 0; + if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1)) + goto out2; + retval = 0; out2: /* Now free ioctl buf memory */ - pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); out: up(&tw_dev->ioctl_sem); return retval; @@ -814,535 +1066,201 @@ static int tw_chrdev_open(struct inode *inode, struct file *file) return 0; } /* End tw_chrdev_open() */ -/* This function handles close for the character device */ -static int tw_chrdev_release(struct inode *inode, struct file *file) -{ - dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_release()\n"); - - return 0; -} /* End tw_chrdev_release() */ +/* File operations struct for character device */ +static struct file_operations tw_fops = { + .owner = THIS_MODULE, + .ioctl = tw_chrdev_ioctl, + .open = tw_chrdev_open, + .release = NULL +}; -/* This function will clear all interrupts on the controller */ -void tw_clear_all_interrupts(TW_Device_Extension *tw_dev) +/* This function will free up device extension resources */ +static void tw_free_device_extension(TW_Device_Extension *tw_dev) { - u32 control_reg_addr, control_reg_value; + dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n"); - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_STATUS_VALID_INTERRUPT; - outl(control_reg_value, control_reg_addr); -} /* End tw_clear_all_interrupts() */ + /* Free command packet and generic buffer memory */ + if (tw_dev->command_packet_virtual_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]); -/* This function will clear the attention interrupt */ -void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev) -{ - u32 control_reg_addr, control_reg_value; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_CONTROL_CLEAR_ATTENTION_INTERRUPT; - outl(control_reg_value, control_reg_addr); -} /* End tw_clear_attention_interrupt() */ + if (tw_dev->alignment_virtual_address[0]) + pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]); +} /* End tw_free_device_extension() */ -/* This function will clear the host interrupt */ -void tw_clear_host_interrupt(TW_Device_Extension *tw_dev) +/* This function will send an initconnection command to controller */ +static int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits) { - u32 control_reg_addr, control_reg_value; + unsigned long command_que_value; + TW_Command *command_packet; + TW_Response_Queue response_queue; + int request_id = 0; - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_CONTROL_CLEAR_HOST_INTERRUPT; - outl(control_reg_value, control_reg_addr); -} /* End tw_clear_host_interrupt() */ + dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n"); -/* This function is called by tw_scsi_proc_info */ -static int tw_copy_info(TW_Info *info, char *fmt, ...) -{ - va_list args; - char buf[81]; - int len; - - va_start(args, fmt); - len = vsprintf(buf, fmt, args); - va_end(args); - tw_copy_mem_info(info, buf, len); - return len; -} /* End tw_copy_info() */ + /* Initialize InitConnection command packet */ + if (tw_dev->command_packet_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n"); + return 1; + } -/* This function is called by tw_scsi_proc_info */ -static void tw_copy_mem_info(TW_Info *info, char *data, int len) -{ - if (info->position + len > info->length) - len = info->length - info->position; + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_INIT_CONNECTION); + command_packet->size = TW_INIT_COMMAND_PACKET_SIZE; + command_packet->request_id = request_id; + command_packet->status = 0x0; + command_packet->flags = 0x0; + command_packet->byte6.message_credits = message_credits; + command_packet->byte8.init_connection.response_queue_pointer = 0x0; + command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (info->position + len < info->offset) { - info->position += len; - return; - } - if (info->position < info->offset) { - data += (info->offset - info->position); - len -= (info->offset - info->position); + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n"); + return 1; } - if (len > 0) { - memcpy(info->buffer + info->position, data, len); - info->position += len; + + /* Send command packet to the board */ + outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + + /* Poll for completion */ + if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { + response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + request_id = TW_RESID_OUT(response_queue.response_id); + + if (request_id != 0) { + /* unexpected request id */ + printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n"); + return 1; + } + if (command_packet->status != 0) { + /* bad response */ + tw_decode_sense(tw_dev, request_id, 0); + return 1; + } } -} /* End tw_copy_mem_info() */ + return 0; +} /* End tw_initconnection() */ -/* This function will print readable messages from status register errors */ -int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host) +/* Set a value in the features table */ +static int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, + unsigned char *val) { - char host[16]; - - dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n"); - - if (print_host) - sprintf(host, " scsi%d:", tw_dev->host->host_no); - else - host[0] = '\0'; + TW_Param *param; + TW_Command *command_packet; + TW_Response_Queue response_queue; + int request_id = 0; + unsigned long command_que_value; + unsigned long param_value; - if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) { - printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host); - outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr); + /* Initialize SetParam command packet */ + if (tw_dev->command_packet_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n"); + return 1; } + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + memset(command_packet, 0, sizeof(TW_Sector)); + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - if (status_reg_value & TW_STATUS_PCI_ABORT) { - printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host); - outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr); - pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); - } + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM); + param->table_id = 0x404; /* Features table */ + param->parameter_id = parm; + param->parameter_size_bytes = param_size; + memcpy(param->data, val, param_size); - if (status_reg_value & TW_STATUS_QUEUE_ERROR) { - printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host); - outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr); + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad alignment physical address.\n"); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->srb[request_id]->result = (DID_OK << 16); + tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); } + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { - printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host); - outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr); - } + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->byte6.parameter_count = 1; - if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { - if (tw_dev->reset_print == 0) { - printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host); - tw_dev->reset_print = 1; - } - return 1; + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n"); + return 1; } - - return 0; -} /* End tw_decode_bits() */ - -/* This function will return valid sense buffer information for failed cmds */ -int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense) -{ - int i; - TW_Command *command; - - dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n"); - command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - printk(KERN_WARNING "3w-xxxx: scsi%d: Command failed: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, command->status, command->flags, command->byte3.unit); - - /* Attempt to return intelligent sense information */ - if (fill_sense) { - if ((command->status == 0xc7) || (command->status == 0xcb)) { - for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) { - if (command->flags == tw_sense_table[i][0]) { - - /* Valid bit and 'current errors' */ - tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70); - - /* Sense key */ - tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1]; - - /* Additional sense length */ - tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */ - - /* Additional sense code */ - tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2]; + /* Send command packet to the board */ + outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); - /* Additional sense code qualifier */ - tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3]; + /* Poll for completion */ + if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { + response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + request_id = TW_RESID_OUT(response_queue.response_id); - tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */ - } - } + if (request_id != 0) { + /* unexpected request id */ + printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n"); + return 1; + } + if (command_packet->status != 0) { + /* bad response */ + tw_decode_sense(tw_dev, request_id, 0); + return 1; } - - /* If no table match, error so we get a reset */ - return 1; } return 0; -} /* End tw_decode_sense() */ - -/* This function will disable interrupts on the controller */ -void tw_disable_interrupts(TW_Device_Extension *tw_dev) -{ - u32 control_reg_value, control_reg_addr; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_CONTROL_DISABLE_INTERRUPTS; - outl(control_reg_value, control_reg_addr); -} /* End tw_disable_interrupts() */ - -/* This function will empty the response que */ -void tw_empty_response_que(TW_Device_Extension *tw_dev) -{ - u32 status_reg_addr, status_reg_value; - u32 response_que_addr, response_que_value; - - status_reg_addr = tw_dev->registers.status_reg_addr; - response_que_addr = tw_dev->registers.response_que_addr; - - status_reg_value = inl(status_reg_addr); - - while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { - response_que_value = inl(response_que_addr); - status_reg_value = inl(status_reg_addr); - } -} /* End tw_empty_response_que() */ - -/* This function will enable interrupts on the controller */ -void tw_enable_interrupts(TW_Device_Extension *tw_dev) -{ - u32 control_reg_value, control_reg_addr; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = (TW_CONTROL_ENABLE_INTERRUPTS | - TW_CONTROL_UNMASK_RESPONSE_INTERRUPT); - outl(control_reg_value, control_reg_addr); -} /* End tw_enable_interrupts() */ - -/* This function will enable interrupts on the controller */ -void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev) -{ - u32 control_reg_value, control_reg_addr; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | - TW_CONTROL_UNMASK_RESPONSE_INTERRUPT | - TW_CONTROL_ENABLE_INTERRUPTS); - outl(control_reg_value, control_reg_addr); -} /* End tw_enable_and_clear_interrupts() */ +} /* End tw_setfeature() */ -/* This function will find and initialize all cards */ -int tw_findcards(Scsi_Host_Template *tw_host) +/* This function will reset a controller */ +static int tw_reset_sequence(TW_Device_Extension *tw_dev) { - int numcards = 0, tries = 0, error = 0; - struct Scsi_Host *host; - TW_Device_Extension *tw_dev; - TW_Device_Extension *tw_dev2; - struct pci_dev *tw_pci_dev = NULL; - u32 status_reg_value; + int error = 0; + int tries = 0; unsigned char c = 1; - int i, j = -1; - u16 device[TW_NUMDEVICES] = { TW_DEVICE_ID, TW_DEVICE_ID2 }; - dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n"); - - for (i=0;itw_pci_dev = tw_pci_dev; - - error = tw_initialize_device_extension(tw_dev); - if (error) { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", j); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Calculate the cards register addresses */ - tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0); - tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0); - tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4; - tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8; - tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC; - - /* Check for errors and clear them */ - status_reg_value = inl(tw_dev->registers.status_reg_addr); - if (TW_STATUS_ERRORS(status_reg_value)) - tw_decode_bits(tw_dev, status_reg_value, 0); - - /* Poll status register for 60 secs for 'Controller Ready' flag */ - if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", j); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Disable interrupts on the card */ - tw_disable_interrupts(tw_dev); - - tries = 0; - - while (tries < TW_MAX_RESET_TRIES) { - /* Do soft reset */ - tw_soft_reset(tw_dev); - - error = tw_aen_drain_queue(tw_dev); - if (error) { - printk(KERN_WARNING "3w-xxxx: AEN drain failed for card %d.\n", j); - tries++; - continue; - } - - /* Check for controller errors */ - if (tw_check_errors(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: Controller errors found, retrying for card %d.\n", j); - tries++; - continue; - } - - /* Now the controller is in a good state */ - break; - } - - if (tries >= TW_MAX_RESET_TRIES) { - printk(KERN_WARNING "3w-xxxx: Controller errors, card not responding, check all cabling for card %d.\n", j); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Reserve the io address space */ - if (!request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME)) { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n", - (tw_dev->tw_pci_dev->resource[0].start), - (tw_dev->tw_pci_dev->resource[0].start) + - TW_IO_ADDRESS_RANGE, j); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - error = tw_initialize_units(tw_dev); - if (error) { - printk(KERN_WARNING "3w-xxxx: No valid units for for card %d.\n", j); - } - - error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS); - if (error) { - printk(KERN_WARNING "3w-xxxx: Connection initialization failed for card %d.\n", j); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Set card status as online */ - tw_dev->online = 1; - - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->free_wrap = TW_Q_LENGTH - 1; - - /* Register the card with the kernel SCSI layer */ - host = scsi_register(tw_host, sizeof(TW_Device_Extension)); - if (host == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", j); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Set max target id's */ - host->max_id = TW_MAX_UNITS; - - /* Set max cdb size in bytes */ - host->max_cmd_len = 16; - - /* Set max sectors per io */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) - host->max_sectors = TW_MAX_SECTORS; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_set_device(host, &tw_pci_dev->dev); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) - scsi_set_pci_device(host, tw_pci_dev); -#endif - - status_reg_value = inl(tw_dev->registers.status_reg_addr); - - printk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d, P-chip: %d.%d\n", host->host_no, - (u32)(tw_pci_dev->resource[0].start), tw_pci_dev->irq, - (status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28, - (status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24); - - if (host->hostdata) { - tw_dev2 = (TW_Device_Extension *)host->hostdata; - memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension)); - /* Need to init the sem/wqueue after the copy */ - init_MUTEX(&tw_dev2->ioctl_sem); - init_waitqueue_head(&tw_dev2->ioctl_wqueue); - - tw_device_extension_list[tw_device_extension_count] = tw_dev2; - numcards++; - tw_device_extension_count = numcards; - tw_dev2->host = host; - } else { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", j); - scsi_unregister(host); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; - } - - /* Tell the firmware we support shutdown notification*/ - error = tw_setfeature(tw_dev2, 2, 1, &c); - if (error) { - printk(KERN_WARNING "3w-xxxx: Unable to set features for card %d, old firmware or card.\n", j); - } - - /* Now setup the interrupt handler */ - error = tw_setup_irq(tw_dev2); - if (error) { - printk(KERN_WARNING "3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", j); - scsi_unregister(host); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - - tw_free_device_extension(tw_dev); - kfree(tw_dev); - numcards--; - continue; - } - - /* Re-enable interrupts on the card */ - tw_enable_interrupts(tw_dev2); + /* Reset the board */ + while (tries < TW_MAX_RESET_TRIES) { + TW_SOFT_RESET(tw_dev); - /* Free the temporary device extension */ - if (tw_dev) - kfree(tw_dev); + error = tw_aen_drain_queue(tw_dev); + if (error) { + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no); + tries++; + continue; } - } - if (numcards == 0) { - printk(KERN_WARNING "3w-xxxx: No cards found.\n"); - } else { - register_reboot_notifier(&tw_notifier); - if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0) { - printk(KERN_WARNING "3w-xxxx: Unable to register \"twe\" character device, error = %d.\n", twe_major); + /* Check for controller errors */ + if (tw_check_errors(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no); + tries++; + continue; } - } - - return numcards; -} /* End tw_findcards() */ - -/* This function will free up device extension resources */ -void tw_free_device_extension(TW_Device_Extension *tw_dev) -{ - dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n"); - - /* Free command packet and generic buffer memory */ - if (tw_dev->command_packet_virtual_address[0]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]); - - if (tw_dev->alignment_virtual_address[0]) - pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]); -} /* End tw_free_device_extension() */ - -/* Clean shutdown routine */ -static int tw_halt(struct notifier_block *nb, ulong event, void *buf) -{ - int i; - for (i=0;ionline == 1) { - printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i); - tw_shutdown_device(tw_device_extension_list[i]); - tw_device_extension_list[i]->online = 0; - } + /* Now the controller is in a good state */ + break; } - unregister_reboot_notifier(&tw_notifier); - - return NOTIFY_OK; -} /* End tw_halt() */ - -/* This function will send an initconnection command to controller */ -int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits) -{ - unsigned long command_que_value; - u32 command_que_addr; - u32 response_que_addr; - TW_Command *command_packet; - TW_Response_Queue response_queue; - int request_id = 0; - dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n"); - command_que_addr = tw_dev->registers.command_que_addr; - response_que_addr = tw_dev->registers.response_que_addr; - - /* Initialize InitConnection command packet */ - if (tw_dev->command_packet_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n"); + if (tries >= TW_MAX_RESET_TRIES) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no); return 1; } - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_INIT_CONNECTION; - command_packet->byte0.sgl_offset = 0x0; - command_packet->size = TW_INIT_COMMAND_PACKET_SIZE; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0x0; - command_packet->byte3.host_id = 0x0; - command_packet->status = 0x0; - command_packet->flags = 0x0; - command_packet->byte6.message_credits = message_credits; - command_packet->byte8.init_connection.response_queue_pointer = 0x0; - command_que_value = tw_dev->command_packet_physical_address[request_id]; - - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n"); + error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS); + if (error) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no); return 1; } - - /* Send command packet to the board */ - outl(command_que_value, command_que_addr); - - /* Poll for completion */ - if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { - response_queue.value = inl(response_que_addr); - request_id = (unsigned char)response_queue.u.response_id; - if (request_id != 0) { - /* unexpected request id */ - printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n"); - return 1; - } - if (command_packet->status != 0) { - /* bad response */ - tw_decode_sense(tw_dev, request_id, 0); - return 1; - } + + error = tw_setfeature(tw_dev, 2, 1, &c); + if (error) { + printk(KERN_WARNING "3w-xxxx: Unable to set features for card, probable old firmware or card.\n"); } + return 0; -} /* End tw_initconnection() */ +} /* End tw_reset_sequence() */ /* This function will initialize the fields of a device extension */ -int tw_initialize_device_extension(TW_Device_Extension *tw_dev) +static int tw_initialize_device_extension(TW_Device_Extension *tw_dev) { int i, error=0; @@ -1369,1263 +1287,737 @@ int tw_initialize_device_extension(TW_Device_Extension *tw_dev) tw_dev->pending_head = TW_Q_START; tw_dev->pending_tail = TW_Q_START; - spin_lock_init(&tw_dev->tw_lock); tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + init_MUTEX(&tw_dev->ioctl_sem); + init_waitqueue_head(&tw_dev->ioctl_wqueue); + return 0; } /* End tw_initialize_device_extension() */ -/* This function will get unit info from the controller */ -int tw_initialize_units(TW_Device_Extension *tw_dev) +static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +{ + int use_sg; + + dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); + + if (cmd->use_sg == 0) + return 0; + + use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + + if (use_sg == 0) { + printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); + return 0; + } + + cmd->SCp.phase = TW_PHASE_SGLIST; + cmd->SCp.have_data_in = use_sg; + + return use_sg; +} /* End tw_map_scsi_sg_data() */ + +static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +{ + dma_addr_t mapping; + + dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n"); + + if (cmd->request_bufflen == 0) + return 0; + + mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL); + + if (mapping == 0) { + printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n"); + return 0; + } + + cmd->SCp.phase = TW_PHASE_SINGLE; + cmd->SCp.have_data_in = mapping; + + return mapping; +} /* End tw_map_scsi_single_data() */ + +static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +{ + dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); + + switch(cmd->SCp.phase) { + case TW_PHASE_SINGLE: + pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); + break; + case TW_PHASE_SGLIST: + pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + break; + } +} /* End tw_unmap_scsi_data() */ + +/* This function will reset a device extension */ +static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) +{ + int i = 0; + struct scsi_cmnd *srb; + unsigned long flags = 0; + + dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n"); + + set_bit(TW_IN_RESET, &tw_dev->flags); + TW_DISABLE_INTERRUPTS(tw_dev); + TW_MASK_COMMAND_INTERRUPT(tw_dev); + spin_lock_irqsave(tw_dev->host->host_lock, flags); + + /* Abort all requests that are in progress */ + for (i=0;istate[i] != TW_S_FINISHED) && + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { + srb = tw_dev->srb[i]; + if (srb != NULL) { + srb->result = (DID_RESET << 16); + tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); + tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); + } + } + } + + /* Reset queues and counts */ + for (i=0;ifree_queue[i] = i; + tw_dev->state[i] = TW_S_INITIAL; + } + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_START; + tw_dev->posted_request_count = 0; + tw_dev->pending_request_count = 0; + tw_dev->pending_head = TW_Q_START; + tw_dev->pending_tail = TW_Q_START; + tw_dev->reset_print = 0; + + spin_unlock_irqrestore(tw_dev->host->host_lock, flags); + + if (tw_reset_sequence(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no); + return 1; + } + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); + + /* Wake up any ioctl that was pending before the reset */ + if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) { + clear_bit(TW_IN_RESET, &tw_dev->flags); + } else { + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + wake_up(&tw_dev->ioctl_wqueue); + } + + return 0; +} /* End tw_reset_device_extension() */ + +/* This funciton returns unit geometry in cylinders/heads/sectors */ +static int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) +{ + int heads, sectors, cylinders; + TW_Device_Extension *tw_dev; + + dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n"); + tw_dev = (TW_Device_Extension *)sdev->host->hostdata; + + heads = 64; + sectors = 32; + cylinders = sector_div(capacity, heads * sectors); + + if (capacity >= 0x200000) { + heads = 255; + sectors = 63; + cylinders = sector_div(capacity, heads * sectors); + } + + dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders); + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return 0; +} /* End tw_scsi_biosparam() */ + +/* This is the new scsi eh reset function */ +static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt) +{ + TW_Device_Extension *tw_dev=NULL; + int retval = FAILED; + + tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; + + spin_unlock_irq(tw_dev->host->host_lock); + + tw_dev->num_resets++; + + printk(KERN_WARNING "3w-xxxx: scsi%d: WARNING: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, SCpnt->device->id, SCpnt->cmnd[0]); + + /* Now reset the card and some of the device extension data */ + if (tw_reset_device_extension(tw_dev, 0)) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no); + goto out; + } + + retval = SUCCESS; +out: + spin_lock_irq(tw_dev->host->host_lock); + return retval; +} /* End tw_scsi_eh_reset() */ + +/* This function handles scsi inquiry commands */ +static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id) { - int found = 0; - unsigned char request_id = 0; - TW_Command *command_packet; TW_Param *param; - int i, imax, num_units = 0; + TW_Command *command_packet; unsigned long command_que_value; - u32 command_que_addr; - u32 response_que_addr; - TW_Response_Queue response_queue; unsigned long param_value; - unsigned char *is_unit_present; - dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n"); - command_que_addr = tw_dev->registers.command_que_addr; - response_que_addr = tw_dev->registers.response_que_addr; - - /* Setup the command packet */ + /* Initialize command packet */ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n"); + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n"); return 1; } memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.block_count = 1; + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; /* Now setup the param */ if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n"); + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n"); return 1; } param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; memset(param, 0, sizeof(TW_Sector)); - param->table_id = 3; /* unit summary table */ - param->parameter_id = 3; /* unitstatus parameter */ + param->table_id = 3; /* unit summary table */ + param->parameter_id = 3; /* unitsstatus parameter */ param->parameter_size_bytes = TW_MAX_UNITS; param_value = tw_dev->alignment_physical_address[request_id]; if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n"); + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n"); return 1; } command_packet->byte8.param.sgl[0].address = param_value; command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - - /* Post the command packet to the board */ command_que_value = tw_dev->command_packet_physical_address[request_id]; if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n"); + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n"); return 1; } - outl(command_que_value, command_que_addr); - /* Poll for completion */ - if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { - response_queue.value = inl(response_que_addr); - request_id = (unsigned char)response_queue.u.response_id; - if (request_id != 0) { - /* unexpected request id */ - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n"); - return 1; - } - if (command_packet->status != 0) { - /* bad response */ - tw_decode_sense(tw_dev, request_id, 0); - return 1; - } - found = 1; - } - if (found == 0) { - /* response never received */ - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n"); + /* Now try to post the command packet */ + tw_post_command_packet(tw_dev, request_id); + + return 0; +} /* End tw_scsiop_inquiry() */ + +/* This function is called by the isr to complete an inquiry command */ +static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) +{ + unsigned char *is_unit_present; + unsigned char *request_buffer; + TW_Param *param; + + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); + + /* Fill request buffer */ + if (tw_dev->srb[request_id]->request_buffer == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n"); return 1; } + request_buffer = tw_dev->srb[request_id]->request_buffer; + memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); + request_buffer[0] = TYPE_DISK; /* Peripheral device type */ + request_buffer[1] = 0; /* Device type modifier */ + request_buffer[2] = 0; /* No ansi/iso compliance */ + request_buffer[4] = 31; /* Additional length */ + memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ + sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); + memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3); param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - is_unit_present = (unsigned char *)&(param->data[0]); - - /* Show all units present */ - imax = TW_MAX_UNITS; - for(i=0; iis_unit_present[i] = FALSE; - } else { - if (is_unit_present[i] & TW_UNIT_ONLINE) { - dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i); - tw_dev->is_unit_present[i] = TRUE; - num_units++; - } - } + if (param == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n"); + return 1; } - tw_dev->num_units = num_units; + is_unit_present = &(param->data[0]); - if (num_units == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n"); - return 1; + if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1; + } else { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0; + tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); + return TW_ISR_DONT_RESULT; } return 0; -} /* End tw_initialize_units() */ +} /* End tw_scsiop_inquiry_complete() */ -/* This function is the interrupt service routine */ -static irqreturn_t tw_interrupt(int irq, void *dev_instance, - struct pt_regs *regs) +/* This function handles scsi mode_sense commands */ +static int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id) { - int request_id; - u32 status_reg_addr, status_reg_value; - u32 response_que_addr; - TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; - TW_Response_Queue response_que; - int error = 0, retval = 0; - unsigned long flags = 0; + TW_Param *param; TW_Command *command_packet; - int handled = 0; + unsigned long command_que_value; + unsigned long param_value; - dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n"); - /* See if we are already running on another processor */ - if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags)) - return IRQ_NONE; + /* Only page control = 0, page code = 0x8 (cache page) supported */ + if (tw_dev->srb[request_id]->cmnd[2] != 0x8) { + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->srb[request_id]->result = (DID_OK << 16); + tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + return 0; + } - /* Get the host lock for io completions */ - spin_lock_irqsave(tw_dev->host->host_lock, flags); + /* Now read firmware cache setting for this unit */ + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n"); + return 1; + } - /* See if the interrupt matches this instance */ - if (tw_dev->tw_pci_dev->irq == irq) { + /* Setup the command packet */ + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; - handled = 1; - /* Make sure io isn't queueing */ - spin_lock(&tw_dev->tw_lock); + /* Setup the param */ + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n"); + return 1; + } - /* Read the registers */ - status_reg_addr = tw_dev->registers.status_reg_addr; - response_que_addr = tw_dev->registers.response_que_addr; - status_reg_value = inl(status_reg_addr); - - /* Check if this is our interrupt, otherwise bail */ - if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT)) - goto tw_interrupt_bail; - - /* Check controller for errors */ - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); - if (tw_decode_bits(tw_dev, status_reg_value, 1)) { - tw_clear_all_interrupts(tw_dev); - goto tw_interrupt_bail; - } - } - - /* Handle host interrupt */ - if (status_reg_value & TW_STATUS_HOST_INTERRUPT) { - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n"); - tw_clear_host_interrupt(tw_dev); - } - - /* Handle attention interrupt */ - if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) { - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n"); - tw_clear_attention_interrupt(tw_dev); - tw_state_request_start(tw_dev, &request_id); - error = tw_aen_read_queue(tw_dev, request_id); - if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - } - } - - /* Handle command interrupt */ - if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) { - /* Drain as many pending commands as we can */ - while (tw_dev->pending_request_count > 0) { - request_id = tw_dev->pending_queue[tw_dev->pending_head]; - if (tw_dev->state[request_id] != TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no); - break; - } - if (tw_post_command_packet(tw_dev, request_id)==0) { - if (tw_dev->pending_head == TW_Q_LENGTH-1) { - tw_dev->pending_head = TW_Q_START; - } else { - tw_dev->pending_head = tw_dev->pending_head + 1; - } - tw_dev->pending_request_count--; - } else { - /* If we get here, we will continue re-posting on the next command interrupt */ - break; - } - } - /* If there are no more pending requests, we mask command interrupt */ - if (tw_dev->pending_request_count == 0) - tw_mask_command_interrupt(tw_dev); - } - - /* Handle response interrupt */ - if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) { - /* Drain the response queue from the board */ - while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { - /* Read response queue register */ - response_que.value = inl(response_que_addr); - request_id = response_que.u.response_id; - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - error = 0; - - /* Check for bad response */ - if (command_packet->status != 0) { - /* If internal command, don't error, don't fill sense */ - if (tw_dev->srb[request_id] == 0) { - tw_decode_sense(tw_dev, request_id, 0); - } else { - error = tw_decode_sense(tw_dev, request_id, 1); - } - } - - /* Check for correct state */ - if (tw_dev->state[request_id] != TW_S_POSTED) { - /* Handle timed out ioctl's */ - if (tw_dev->srb[request_id] != 0) { - if (tw_dev->srb[request_id]->cmnd[0] != TW_IOCTL) { - 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); - error = 1; - } - } - } + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + memset(param, 0, sizeof(TW_Sector)); + param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id; + param->parameter_id = 7; /* unit flags */ + param->parameter_size_bytes = 1; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n"); + return 1; + } - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n"); + return 1; + } - /* Check for internal command completion */ - if (tw_dev->srb[request_id] == 0) { - dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); - /* Check for chrdev ioctl completion */ - if (request_id != tw_dev->chrdev_request_id) { - retval = tw_aen_complete(tw_dev, request_id); - if (retval) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); - } - } else { - tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - wake_up(&tw_dev->ioctl_wqueue); - } - } else { - switch (tw_dev->srb[request_id]->cmnd[0]) { - case READ_10: - case READ_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n"); - break; - case WRITE_10: - case WRITE_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n"); - break; - case TEST_UNIT_READY: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n"); - error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id); - break; - case INQUIRY: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n"); - error = tw_scsiop_inquiry_complete(tw_dev, request_id); - break; - case READ_CAPACITY: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n"); - error = tw_scsiop_read_capacity_complete(tw_dev, request_id); - break; - case MODE_SENSE: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n"); - error = tw_scsiop_mode_sense_complete(tw_dev, request_id); - break; - case SYNCHRONIZE_CACHE: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n"); - break; - case TW_IOCTL: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n"); - error = tw_ioctl_complete(tw_dev, request_id); - break; - default: - printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n"); - error = 1; - } + /* Now try to post the command packet */ + tw_post_command_packet(tw_dev, request_id); + + return 0; +} /* End tw_scsiop_mode_sense() */ - /* If no error command was a success */ - if (error == 0) { - tw_dev->srb[request_id]->result = (DID_OK << 16); - } +/* This function is called by the isr to complete a mode sense command */ +static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id) +{ + TW_Param *param; + unsigned char *flags; + unsigned char *request_buffer; - /* If error, command failed */ - if (error == 1) { - /* Ask for a host reset */ - tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - } + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); - /* Now complete the io */ - if ((error != TW_ISR_DONT_COMPLETE)) { - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->posted_request_count--; - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + if (param == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n"); + return 1; + } + flags = (char *)&(param->data[0]); + request_buffer = tw_dev->srb[request_id]->buffer; + memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); - tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); - } - } - - /* Check for valid status after each drain */ - status_reg_value = inl(status_reg_addr); - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); - if (tw_decode_bits(tw_dev, status_reg_value, 1)) { - tw_clear_all_interrupts(tw_dev); - goto tw_interrupt_bail; - } - } - } - } -tw_interrupt_bail: - spin_unlock(&tw_dev->tw_lock); - } else - dprintk(KERN_WARNING "3w-xxxx: tw_interrupt() called for wrong instance.\n"); + request_buffer[0] = 0xf; /* mode data length */ + request_buffer[1] = 0; /* default medium type */ + request_buffer[2] = 0x10; /* dpo/fua support on */ + request_buffer[3] = 0; /* no block descriptors */ + request_buffer[4] = 0x8; /* caching page */ + request_buffer[5] = 0xa; /* page length */ + if (*flags & 0x1) + request_buffer[6] = 0x4; /* WCE on */ + else + request_buffer[6] = 0x0; /* WCE off */ - spin_unlock_irqrestore(tw_dev->host->host_lock, flags); - clear_bit(TW_IN_INTR, &tw_dev->flags); - return IRQ_RETVAL(handled); -} /* End tw_interrupt() */ + return 0; +} /* End tw_scsiop_mode_sense_complete() */ -/* This function handles ioctls from userspace to the driver */ -int tw_ioctl(TW_Device_Extension *tw_dev, int request_id) +/* This function handles scsi read_capacity commands */ +static int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id) { - unsigned char opcode; - int bufflen, error = 0; TW_Param *param; - TW_Command *command_packet, *command_save; + TW_Command *command_packet; + unsigned long command_que_value; unsigned long param_value; - TW_Ioctl *ioctl = NULL; - TW_Passthru *passthru = NULL; - int tw_aen_code, i, use_sg; - unsigned long *data_ptr; - int total_bytes = 0, posted = 0; - dma_addr_t dma_handle; - struct timeval before, timeout; - ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; - if (ioctl == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\n"); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; - } - bufflen = tw_dev->srb[request_id]->request_bufflen; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n"); /* Initialize command packet */ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad command packet virtual address.\n"); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n"); + return 1; } memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id); + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.block_count = 1; - /* Initialize param */ + /* Now setup the param */ if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n"); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n"); + return 1; } param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; memset(param, 0, sizeof(TW_Sector)); - - dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); - opcode = ioctl->opcode; - - switch (opcode) { - case TW_OP_NOP: - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n"); - command_packet->byte0.opcode = TW_OP_NOP; - break; - case TW_OP_GET_PARAM: - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n"); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte3.unit = ioctl->unit_index; - param->table_id = ioctl->table_id; - param->parameter_id = ioctl->parameter_id; - param->parameter_size_bytes = ioctl->parameter_size_bytes; - tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes; - dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes); - break; - case TW_OP_SET_PARAM: - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n", - ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes); - if (ioctl->data != NULL) { - command_packet->byte0.opcode = TW_OP_SET_PARAM; - param->table_id = ioctl->table_id; - param->parameter_id = ioctl->parameter_id; - param->parameter_size_bytes = ioctl->parameter_size_bytes; - memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes); - break; - } else { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); - return 1; - } - case TW_OP_AEN_LISTEN: - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n"); - if (tw_dev->aen_head == tw_dev->aen_tail) { - /* aen queue empty */ - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n"); - tw_aen_code = TW_AEN_QUEUE_EMPTY; - memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes); - } else { - /* Copy aen queue entry to request buffer */ - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]); - tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head]; - memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes); - if (tw_dev->aen_head == TW_Q_LENGTH - 1) { - tw_dev->aen_head = TW_Q_START; - } else { - tw_dev->aen_head = tw_dev->aen_head + 1; - } - } - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; - 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]; - /* Don't load sg_list for non-data ATA cmds */ - if ((passthru->param != 0) && (passthru->param != 0x8)) { - 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 (%d) too big.\n", passthru->sg_list[0].length); - return 1; - } - passthru->sg_list[0].address = tw_dev->alignment_physical_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"); - if (ioctl->data != NULL) { - memcpy(command_packet, ioctl->data, sizeof(TW_Command)); - command_packet->request_id = request_id; - tw_post_command_packet(tw_dev, request_id); - return 0; - } else { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); - return 1; - } - case TW_CMD_PACKET_WITH_DATA: - dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n"); - command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id]; - if (command_save == NULL) { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no); - return 1; - } - if (ioctl->data != NULL) { - /* Copy down the command packet */ - memcpy(command_packet, ioctl->data, sizeof(TW_Command)); - memcpy(command_save, ioctl->data, sizeof(TW_Command)); - command_packet->request_id = request_id; - - /* Now deal with the two possible sglists */ - if (command_packet->byte0.sgl_offset == 2) { - use_sg = command_packet->size - 3; - for (i=0;ibyte8.param.sgl[i].length; - tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle); - - if (!tw_dev->ioctl_data[request_id]) { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id); - return 1; - } - - /* Copy param sglist into the kernel */ - data_ptr = tw_dev->ioctl_data[request_id]; - for (i=0;ibyte8.param.sgl[i].address != 0) { - error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length); - if (error) { - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no); - goto tw_ioctl_bail; - } - } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no); - tw_dev->srb[request_id]->result = (DID_RESET << 16); - goto tw_ioctl_bail; - } - data_ptr+=command_packet->byte8.param.sgl[i].length; - } - command_packet->size = 4; - command_packet->byte8.param.sgl[0].address = dma_handle; - command_packet->byte8.param.sgl[0].length = total_bytes; - } - if (command_packet->byte0.sgl_offset == 3) { - use_sg = command_packet->size - 4; - for (i=0;ibyte8.io.sgl[i].length; - tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle); - - if (!tw_dev->ioctl_data[request_id]) { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id); - return 1; - } - if (command_packet->byte0.opcode == TW_OP_WRITE) { - /* Copy io sglist into the kernel */ - data_ptr = tw_dev->ioctl_data[request_id]; - for (i=0;ibyte8.io.sgl[i].address != 0) { - error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length); - if (error) { - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no); - goto tw_ioctl_bail; - } - } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no); - tw_dev->srb[request_id]->result = (DID_RESET << 16); - goto tw_ioctl_bail; - } - data_ptr+=command_packet->byte8.io.sgl[i].length; - } - } - command_packet->size = 5; - command_packet->byte8.io.sgl[0].address = dma_handle; - command_packet->byte8.io.sgl[0].length = total_bytes; - } - - spin_unlock(&tw_dev->tw_lock); - spin_unlock_irq(tw_dev->host->host_lock); - - set_bit(TW_IN_IOCTL, &tw_dev->flags); - - /* Finally post the command packet */ - tw_post_command_packet(tw_dev, request_id); - posted = 1; - do_gettimeofday(&before); - - tw_ioctl_retry: - mdelay(TW_IOCTL_WAIT_TIME); - if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) { - do_gettimeofday(&timeout); - if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) { - spin_lock_irq(tw_dev->host->host_lock); - spin_lock(&tw_dev->tw_lock); - goto tw_ioctl_bail; - } else { - goto tw_ioctl_retry; - } - } - - spin_lock_irq(tw_dev->host->host_lock); - spin_lock(&tw_dev->tw_lock); - - if (signal_pending(current)) { - dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no); - tw_dev->srb[request_id]->result = (DID_OK << 16); - goto tw_ioctl_bail; - } - - tw_dev->srb[request_id]->result = (DID_OK << 16); - /* Now copy up the param or io sglist to userspace */ - if (command_packet->byte0.sgl_offset == 2) { - use_sg = command_save->size - 3; - data_ptr = tw_dev->ioctl_data[request_id]; - for (i=0;ibyte8.param.sgl[i].address != 0) { - error = copy_to_user((void *)(unsigned long)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length); - if (error) { - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no); - goto tw_ioctl_bail; - } - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid); - data_ptr+=command_save->byte8.param.sgl[i].length; - } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no); - tw_dev->srb[request_id]->result = (DID_RESET << 16); - goto tw_ioctl_bail; - } - } - } - if (command_packet->byte0.sgl_offset == 3) { - use_sg = command_save->size - 4; - if (command_packet->byte0.opcode == TW_OP_READ) { - data_ptr = tw_dev->ioctl_data[request_id]; - for(i=0;ibyte8.io.sgl[i].address != 0) { - error = copy_to_user((void *)(unsigned long)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length); - if (error) { - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no); - goto tw_ioctl_bail; - } - dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid); - data_ptr+=command_save->byte8.io.sgl[i].length; - } else { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no); - tw_dev->srb[request_id]->result = (DID_RESET << 16); - goto tw_ioctl_bail; - } - } - } - } - - tw_ioctl_bail: - - /* Free up sglist memory */ - if (tw_dev->ioctl_data[request_id]) - pci_free_consistent(tw_dev->tw_pci_dev, total_bytes, tw_dev->ioctl_data[request_id], dma_handle); - else - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Error freeing ioctl data.\n", tw_dev->host->host_no); - - /* Now complete the io */ - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - if (posted) - tw_dev->posted_request_count--; - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; - } else { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); - return 1; - } - default: - dprintk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; - } - - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n"); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - } - - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; + param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + + tw_dev->srb[request_id]->device->id; + param->parameter_id = 4; /* unitcapacity parameter */ + param->parameter_size_bytes = 4; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n"); + return 1; + } + + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n"); + return 1; + } /* Now try to post the command to the board */ tw_post_command_packet(tw_dev, request_id); - + return 0; -} /* End tw_ioctl() */ +} /* End tw_scsiop_read_capacity() */ -/* This function is called by the isr to complete ioctl requests */ -int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id) +/* This function is called by the isr to complete a readcapacity command */ +static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id) { unsigned char *param_data; - unsigned char *buff; + u32 capacity; + char *buff; TW_Param *param; - TW_Ioctl *ioctl = NULL; - TW_Passthru *passthru = NULL; - TW_Command *command_packet; - ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); + buff = tw_dev->srb[request_id]->request_buffer; if (buff == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n"); + printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n"); return 1; } - - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl_complete(): Bad command packet virtual address.\n", tw_dev->host->host_no); + 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]); - dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen); + capacity = (param_data[3] << 24) | (param_data[2] << 16) | + (param_data[1] << 8) | param_data[0]; - ioctl = (TW_Ioctl *)buff; - switch (ioctl->opcode) { - case TW_ATA_PASSTHRU: - passthru = (TW_Passthru *)ioctl->data; - /* Don't return data for non-data ATA cmds */ - if ((passthru->param != 0) && (passthru->param != 0x8)) - memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512); - else { - /* For non-data cmds, return cmd pkt */ - if (tw_dev->srb[request_id]->request_bufflen >= sizeof(TW_Command)) - memcpy(buff, tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command)); - } - break; - case TW_CMD_PACKET_WITH_DATA: - dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n"); - clear_bit(TW_IN_IOCTL, &tw_dev->flags); - return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */ - 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]); - } - return 0; -} /* End tw_ioctl_complete() */ + /* Subtract one sector to fix get last sector ioctl */ + capacity -= 1; -static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd) -{ - int use_sg; - int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity); - dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); - - if (cmd->use_sg == 0) - return 0; + /* Number of LBA's */ + buff[0] = (capacity >> 24); + buff[1] = (capacity >> 16) & 0xff; + buff[2] = (capacity >> 8) & 0xff; + buff[3] = capacity & 0xff; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); - - if (use_sg == 0) { - printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); - return 0; - } + /* Block size in bytes (512) */ + buff[4] = (TW_BLOCK_SIZE >> 24); + buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff; + buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; + buff[7] = TW_BLOCK_SIZE & 0xff; - cmd->SCp.phase = 2; - cmd->SCp.have_data_in = use_sg; - - return use_sg; -} /* End tw_map_scsi_sg_data() */ + return 0; +} /* End tw_scsiop_read_capacity_complete() */ -static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd) +/* This function handles scsi read or write commands */ +static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) { - dma_addr_t mapping; - int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); - - dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n"); + TW_Command *command_packet; + unsigned long command_que_value; + u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0; + int i, use_sg; + struct scsi_cmnd *srb; + struct scatterlist *sglist; - if (cmd->request_bufflen == 0) - return 0; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n"); - mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, dma_dir); + if (tw_dev->srb[request_id]->request_buffer == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n"); + return 1; + } + sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; + srb = tw_dev->srb[request_id]; - if (mapping == 0) { - printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n"); - return 0; + /* Initialize command packet */ + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n"); + return 1; } - cmd->SCp.phase = 1; - cmd->SCp.have_data_in = mapping; + if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) { + command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_READ); + } else { + command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_WRITE); + } - return mapping; -} /* End tw_map_scsi_single_data() */ + command_packet->size = 3; + command_packet->request_id = request_id; + command_packet->unit__hostid = TW_UNITHOST_IN(0, srb->device->id); + command_packet->status = 0; + command_packet->flags = 0; -/* This function will mask the command interrupt */ -void tw_mask_command_interrupt(TW_Device_Extension *tw_dev) -{ - u32 control_reg_addr, control_reg_value; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_CONTROL_MASK_COMMAND_INTERRUPT; - outl(control_reg_value, control_reg_addr); -} /* End tw_mask_command_interrupt() */ + if (srb->cmnd[0] == WRITE_10) { + if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10)) + command_packet->flags = 1; + } -/* This function will poll the status register for a flag */ -int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds) -{ - u32 status_reg_addr, status_reg_value; - struct timeval before, timeout; + if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) { + lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3]; + num_sectors = (u32)srb->cmnd[4]; + } else { + lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5]; + num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8); + } + + /* Update sector statistic */ + tw_dev->sector_count = num_sectors; + if (tw_dev->sector_count > tw_dev->max_sector_count) + tw_dev->max_sector_count = tw_dev->sector_count; + + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors); + command_packet->byte8.io.lba = lba; + command_packet->byte6.block_count = num_sectors; - status_reg_addr = tw_dev->registers.status_reg_addr; - do_gettimeofday(&before); - status_reg_value = inl(status_reg_addr); + /* Do this if there are no sg list entries */ + if (tw_dev->srb[request_id]->use_sg == 0) { + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); + buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + if (buffaddr == 0) + return 1; - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n"); - tw_decode_bits(tw_dev, status_reg_value, 0); + command_packet->byte8.io.sgl[0].address = buffaddr; + command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; + command_packet->size+=2; } - - while ((status_reg_value & flag) != flag) { - status_reg_value = inl(status_reg_addr); - - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n"); - tw_decode_bits(tw_dev, status_reg_value, 0); - } - do_gettimeofday(&timeout); - if (before.tv_sec + seconds < timeout.tv_sec) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag); + /* Do this if we have multiple sg list entries */ + if (tw_dev->srb[request_id]->use_sg > 0) { + use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + if (use_sg == 0) return 1; + + for (i=0;ibyte8.io.sgl[i].address = sg_dma_address(&sglist[i]); + command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]); + command_packet->size+=2; } - mdelay(5); } - return 0; -} /* End tw_poll_status() */ - -/* This function will poll the status register for disappearance of a flag */ -int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds) -{ - u32 status_reg_addr, status_reg_value; - struct timeval before, timeout; - status_reg_addr = tw_dev->registers.status_reg_addr; - do_gettimeofday(&before); - status_reg_value = inl(status_reg_addr); + /* Update SG statistics */ + tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; + if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) + tw_dev->max_sgl_entries = tw_dev->sgl_entries; - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n"); - tw_decode_bits(tw_dev, status_reg_value, 0); + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n"); + return 1; } + + /* Now try to post the command to the board */ + tw_post_command_packet(tw_dev, request_id); - while ((status_reg_value & flag) != 0) { - status_reg_value = inl(status_reg_addr); - - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n"); - tw_decode_bits(tw_dev, status_reg_value, 0); - } - - do_gettimeofday(&timeout); - if (before.tv_sec + seconds < timeout.tv_sec) { - dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Flag 0x%x never disappeared.\n", flag); - return 1; - } - mdelay(5); - } return 0; -} /* End tw_poll_status_gone() */ +} /* End tw_scsiop_read_write() */ -/* This function will attempt to post a command packet to the board */ -int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id) +/* This function will handle the request sense scsi command */ +static int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id) { - u32 status_reg_addr, status_reg_value; - unsigned long command_que_value; - u32 command_que_addr; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n"); - dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n"); - command_que_addr = tw_dev->registers.command_que_addr; - command_que_value = tw_dev->command_packet_physical_address[request_id]; - status_reg_addr = tw_dev->registers.status_reg_addr; - status_reg_value = inl(status_reg_addr); + /* For now we just zero the request buffer */ + memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); - if (tw_check_bits(status_reg_value)) { - dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); - tw_decode_bits(tw_dev, status_reg_value, 1); - } + /* If we got a request_sense, we probably want a reset, return error */ + tw_dev->srb[request_id]->result = (DID_ERROR << 16); + tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) { - /* We successfully posted the command packet */ - outl(command_que_value, command_que_addr); - tw_dev->state[request_id] = TW_S_POSTED; - tw_dev->posted_request_count++; - if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) { - tw_dev->max_posted_request_count = tw_dev->posted_request_count; - } - } else { - /* Couldn't post the command packet, so we do it in the isr */ - if (tw_dev->state[request_id] != TW_S_PENDING) { - tw_dev->state[request_id] = TW_S_PENDING; - tw_dev->pending_request_count++; - if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) { - tw_dev->max_pending_request_count = tw_dev->pending_request_count; - } - tw_dev->pending_queue[tw_dev->pending_tail] = request_id; - if (tw_dev->pending_tail == TW_Q_LENGTH-1) { - tw_dev->pending_tail = TW_Q_START; - } else { - tw_dev->pending_tail = tw_dev->pending_tail + 1; - } - } - tw_unmask_command_interrupt(tw_dev); - return 1; - } return 0; -} /* End tw_post_command_packet() */ +} /* End tw_scsiop_request_sense() */ -/* This function will reset a device extension */ -int tw_reset_device_extension(TW_Device_Extension *tw_dev) +/* This function will handle synchronize cache scsi command */ +static int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id) { - int imax = 0; - int i = 0; - Scsi_Cmnd *srb; + TW_Command *command_packet; + unsigned long command_que_value; - dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n"); - imax = TW_Q_LENGTH; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n"); - if (tw_reset_sequence(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no); + /* Send firmware flush command for this unit */ + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n"); return 1; } - /* Abort all requests that are in progress */ - for (i=0;istate[i] != TW_S_FINISHED) && - (tw_dev->state[i] != TW_S_INITIAL) && - (tw_dev->state[i] != TW_S_COMPLETED)) { - srb = tw_dev->srb[i]; - if (srb != NULL) { - srb->result = (DID_RESET << 16); - tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); - tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); - } - } + /* Setup the command packet */ + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_FLUSH_CACHE); + command_packet->size = 2; + command_packet->request_id = request_id; + command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id); + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n"); + return 1; } - /* Reset queues and counts */ - for (i=0;ifree_queue[i] = i; - tw_dev->state[i] = TW_S_INITIAL; - } - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_START; - tw_dev->posted_request_count = 0; - tw_dev->pending_request_count = 0; - tw_dev->pending_head = TW_Q_START; - tw_dev->pending_tail = TW_Q_START; - tw_dev->reset_print = 0; - tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + /* Now try to post the command packet */ + tw_post_command_packet(tw_dev, request_id); return 0; -} /* End tw_reset_device_extension() */ +} /* End tw_scsiop_synchronize_cache() */ -/* This function will reset a controller */ -int tw_reset_sequence(TW_Device_Extension *tw_dev) +/* This function will handle test unit ready scsi command */ +static int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id) { - int error = 0; - int tries = 0; - - /* Disable interrupts */ - tw_disable_interrupts(tw_dev); - - /* Reset the board */ - while (tries < TW_MAX_RESET_TRIES) { - tw_soft_reset(tw_dev); - - error = tw_aen_drain_queue(tw_dev); - if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no); - tries++; - continue; - } + TW_Param *param; + TW_Command *command_packet; + unsigned long command_que_value; + unsigned long param_value; - /* Check for controller errors */ - if (tw_check_errors(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no); - tries++; - continue; - } + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n"); - /* Now the controller is in a good state */ - break; + /* Initialize command packet */ + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n"); + return 1; } + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM); + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; - if (tries >= TW_MAX_RESET_TRIES) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no); + /* Now setup the param */ + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n"); return 1; } - - error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS); - if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no); + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + memset(param, 0, sizeof(TW_Sector)); + param->table_id = 3; /* unit summary table */ + param->parameter_id = 3; /* unitsstatus parameter */ + param->parameter_size_bytes = TW_MAX_UNITS; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n"); return 1; } - /* Re-enable interrupts */ - tw_enable_and_clear_interrupts(tw_dev); - - return 0; -} /* End tw_reset_sequence() */ - -/* This funciton returns unit geometry in cylinders/heads/sectors */ -int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) -{ - int heads, sectors, cylinders; - TW_Device_Extension *tw_dev; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n"); - tw_dev = (TW_Device_Extension *)sdev->host->hostdata; - - heads = 64; - sectors = 32; - cylinders = (unsigned long)capacity / (heads * sectors); - - if (capacity >= 0x200000) { - heads = 255; - sectors = 63; - cylinders = (unsigned long)capacity / (heads * sectors); + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n"); + return 1; } - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders); - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + /* Now try to post the command packet */ + tw_post_command_packet(tw_dev, request_id); return 0; -} /* End tw_scsi_biosparam() */ - -/* This function will find and initialize any cards */ -int tw_scsi_detect(Scsi_Host_Template *tw_host) -{ - int ret; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n"); - - printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", tw_driver_version); - - ret = tw_findcards(tw_host); - - return ret; -} /* End tw_scsi_detect() */ +} /* End tw_scsiop_test_unit_ready() */ -/* This is the new scsi eh abort function */ -int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt) +/* This function is called by the isr to complete a testunitready command */ +static int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id) { - TW_Device_Extension *tw_dev=NULL; - int i = 0; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n"); + unsigned char *is_unit_present; + TW_Param *param; - if (!SCpnt) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n"); - return (FAILED); - } + dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n"); - tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; - if (tw_dev == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n"); - return (FAILED); + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + if (param == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n"); + return 1; } + is_unit_present = &(param->data[0]); - spin_lock(&tw_dev->tw_lock); - tw_dev->num_aborts++; - - /* If the command hasn't been posted yet, we can do the abort */ - for (i=0;isrb[i] == SCpnt) { - if (tw_dev->state[i] == TW_S_STARTED) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt); - tw_dev->state[i] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, i); - spin_unlock(&tw_dev->tw_lock); - return (SUCCESS); - } - if (tw_dev->state[i] == TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt); - if (tw_dev->pending_head == TW_Q_LENGTH-1) { - tw_dev->pending_head = TW_Q_START; - } else { - tw_dev->pending_head = tw_dev->pending_head + 1; - } - tw_dev->pending_request_count--; - tw_dev->state[i] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, i); - spin_unlock(&tw_dev->tw_lock); - return (SUCCESS); - } - if (tw_dev->state[i] == TW_S_POSTED) { - /* If the command has already been posted, we have to reset the card */ - printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out, resetting card.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt); - /* We have to let AEN requests through before the reset */ - spin_unlock(&tw_dev->tw_lock); - spin_unlock_irq(tw_dev->host->host_lock); - mdelay(TW_AEN_WAIT_TIME); - spin_lock_irq(tw_dev->host->host_lock); - spin_lock(&tw_dev->tw_lock); - - if (tw_reset_device_extension(tw_dev)) { - dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no); - spin_unlock(&tw_dev->tw_lock); - return (FAILED); - } - } - } + if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1; + } else { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0; + tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); + return TW_ISR_DONT_RESULT; } - spin_unlock(&tw_dev->tw_lock); - return (SUCCESS); -} /* End tw_scsi_eh_abort() */ + return 0; +} /* End tw_scsiop_test_unit_ready_complete() */ -/* This is the new scsi eh reset function */ -int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt) +/* This is the main scsi queue function to handle scsi opcodes */ +static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - TW_Device_Extension *tw_dev=NULL; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n"); - - if (!SCpnt) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n"); - return (FAILED); - } + unsigned char *command = SCpnt->cmnd; + int request_id = 0; + int retval = 1; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; - tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; - if (tw_dev == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n"); - return (FAILED); - } + /* Save done function into Scsi_Cmnd struct */ + SCpnt->scsi_done = done; + + /* Queue the command and get a request id */ + tw_state_request_start(tw_dev, &request_id); - /* We have to let AEN requests through before the reset */ - spin_unlock_irq(tw_dev->host->host_lock); - mdelay(TW_AEN_WAIT_TIME); - spin_lock_irq(tw_dev->host->host_lock); + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; - spin_lock(&tw_dev->tw_lock); - tw_dev->num_resets++; - - /* Now reset the card and some of the device extension data */ - if (tw_reset_device_extension(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no); - spin_unlock(&tw_dev->tw_lock); - return (FAILED); - } - printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no); - spin_unlock(&tw_dev->tw_lock); - - return (SUCCESS); -} /* End tw_scsi_eh_reset() */ - -/* This function handles input and output from /proc/scsi/3w-xxxx/x */ -int tw_scsi_proc_info(struct Scsi_Host *shost, char *buffer, char **start, - off_t offset, int length, int inout) -{ - TW_Device_Extension *tw_dev = NULL; - TW_Info info; - int i; - int j; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_proc_info()\n"); - - /* Find the correct device extension */ - for (i=0;ihost->host_no == shost->host_no) - tw_dev = tw_device_extension_list[i]; - if (tw_dev == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n"); - return (-EINVAL); - } - - info.buffer = buffer; - info.length = length; - info.offset = offset; - info.position = 0; - - if (inout) { - /* Write */ - if (strncmp(buffer, "debug", 5) == 0) { - printk(KERN_INFO "3w-xxxx: Posted commands:\n"); - for (j=0;jstate[j] == TW_S_POSTED) { - TW_Command *command = (TW_Command *)tw_dev->command_packet_virtual_address[j]; - printk(KERN_INFO "3w-xxxx: Request_id: %d\n", j); - printk(KERN_INFO "Opcode: 0x%x\n", command->byte0.opcode); - printk(KERN_INFO "Block_count: 0x%x\n", command->byte6.block_count); - printk(KERN_INFO "LBA: 0x%x\n", command->byte8.io.lba); - printk(KERN_INFO "Physical command packet addr: 0x%lx\n", tw_dev->command_packet_physical_address[j]); - printk(KERN_INFO "Scsi_Cmnd: %p\n", tw_dev->srb[j]); - } - } - printk(KERN_INFO "3w-xxxx: Free_head: %3d\n", tw_dev->free_head); - printk(KERN_INFO "3w-xxxx: Free_tail: %3d\n", tw_dev->free_tail); - } - return length; - } else { - /* Read */ - if (start) { - *start = buffer; - } - tw_copy_info(&info, "scsi%d: 3ware Storage Controller\n", shost->host_no); - tw_copy_info(&info, "Driver version: %s\n", tw_driver_version); - tw_copy_info(&info, "Current commands posted: %3d\n", tw_dev->posted_request_count); - tw_copy_info(&info, "Max commands posted: %3d\n", tw_dev->max_posted_request_count); - tw_copy_info(&info, "Current pending commands: %3d\n", tw_dev->pending_request_count); - tw_copy_info(&info, "Max pending commands: %3d\n", tw_dev->max_pending_request_count); - tw_copy_info(&info, "Last sgl length: %3d\n", tw_dev->sgl_entries); - tw_copy_info(&info, "Max sgl length: %3d\n", tw_dev->max_sgl_entries); - tw_copy_info(&info, "Last sector count: %3d\n", tw_dev->sector_count); - tw_copy_info(&info, "Max sector count: %3d\n", tw_dev->max_sector_count); - tw_copy_info(&info, "Resets: %3d\n", tw_dev->num_resets); - tw_copy_info(&info, "Aborts: %3d\n", tw_dev->num_aborts); - tw_copy_info(&info, "AEN's: %3d\n", tw_dev->aen_count); - } - if (info.position > info.offset) { - return (info.position - info.offset); - } else { - return 0; - } -} /* End tw_scsi_proc_info() */ - -/* This is the main scsi queue function to handle scsi opcodes */ -int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - unsigned char *command = SCpnt->cmnd; - int request_id = 0; - int error = 0; - TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; - - if (tw_dev == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n"); - SCpnt->result = (DID_ERROR << 16); - done(SCpnt); - return 0; - } - - spin_lock(&tw_dev->tw_lock); - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n"); - - /* Skip scsi command if it isn't for us */ - if ((SCpnt->device->channel != 0) || (SCpnt->device->lun != 0)) { - SCpnt->result = (DID_BAD_TARGET << 16); - done(SCpnt); - spin_unlock(&tw_dev->tw_lock); - return 0; - } - - /* Save done function into Scsi_Cmnd struct */ - SCpnt->scsi_done = done; - - /* Queue the command and get a request id */ - tw_state_request_start(tw_dev, &request_id); - - /* Save the scsi command for use by the ISR */ - tw_dev->srb[request_id] = SCpnt; - - /* Initialize phase to zero */ - SCpnt->SCp.phase = 0; + /* Initialize phase to zero */ + SCpnt->SCp.phase = TW_PHASE_INITIAL; switch (*command) { case READ_10: @@ -2633,35 +2025,34 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) case WRITE_10: case WRITE_6: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n"); - error = tw_scsiop_read_write(tw_dev, request_id); + retval = tw_scsiop_read_write(tw_dev, request_id); break; case TEST_UNIT_READY: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n"); - error = tw_scsiop_test_unit_ready(tw_dev, request_id); + retval = tw_scsiop_test_unit_ready(tw_dev, request_id); break; case INQUIRY: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n"); - error = tw_scsiop_inquiry(tw_dev, request_id); + retval = tw_scsiop_inquiry(tw_dev, request_id); break; case READ_CAPACITY: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n"); - error = tw_scsiop_read_capacity(tw_dev, request_id); + retval = tw_scsiop_read_capacity(tw_dev, request_id); break; case REQUEST_SENSE: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught REQUEST_SENSE.\n"); - error = tw_scsiop_request_sense(tw_dev, request_id); + retval = tw_scsiop_request_sense(tw_dev, request_id); break; case MODE_SENSE: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught MODE_SENSE.\n"); - error = tw_scsiop_mode_sense(tw_dev, request_id); + retval = tw_scsiop_mode_sense(tw_dev, request_id); break; case SYNCHRONIZE_CACHE: dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught SYNCHRONIZE_CACHE.\n"); - error = tw_scsiop_synchronize_cache(tw_dev, request_id); + retval = tw_scsiop_synchronize_cache(tw_dev, request_id); break; case TW_IOCTL: - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n"); - error = tw_ioctl(tw_dev, request_id); + printk(KERN_WARNING "3w-xxxx: SCSI_IOCTL_SEND_COMMAND deprecated, please update your 3ware tools.\n"); break; default: printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command); @@ -2669,837 +2060,441 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) tw_state_request_finish(tw_dev, request_id); SCpnt->result = (DID_BAD_TARGET << 16); done(SCpnt); + goto out; } - if (error) { + if (retval) { tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); SCpnt->result = (DID_ERROR << 16); done(SCpnt); + retval = 0; } - spin_unlock(&tw_dev->tw_lock); - - return 0; +out: + return retval; } /* End tw_scsi_queue() */ -/* This function will release the resources on an rmmod call */ -int tw_scsi_release(struct Scsi_Host *tw_host) -{ - TW_Device_Extension *tw_dev; - tw_dev = (TW_Device_Extension *)tw_host->hostdata; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n"); - - /* Fake like we just shut down, so notify the card that - * we "shut down cleanly". - */ - tw_halt(0, 0, 0); // parameters aren't actually used - - /* Free up the IO region */ - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - - /* Free up the IRQ */ - free_irq(tw_dev->tw_pci_dev->irq, tw_dev); - - /* Unregister character device */ - if (twe_major >= 0) { - unregister_chrdev(twe_major, "twe"); - twe_major = -1; - } - - /* Free up device extension resources */ - tw_free_device_extension(tw_dev); - - /* Tell kernel scsi-layer we are gone */ - scsi_unregister(tw_host); - - return 0; -} /* End tw_scsi_release() */ - -/* This function handles scsi inquiry commands */ -int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id) +/* This function is the interrupt service routine */ +static irqreturn_t tw_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) { - TW_Param *param; + int request_id; + u32 status_reg_value; + TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; + TW_Response_Queue response_que; + int error = 0, retval = 0; TW_Command *command_packet; - unsigned long command_que_value; - u32 command_que_addr; - unsigned long param_value; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n"); - - /* Initialize command packet */ - command_que_addr = tw_dev->registers.command_que_addr; - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n"); - return 1; - } - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; - - /* Now setup the param */ - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n"); - return 1; - } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - memset(param, 0, sizeof(TW_Sector)); - param->table_id = 3; /* unit summary table */ - param->parameter_id = 3; /* unitsstatus parameter */ - param->parameter_size_bytes = TW_MAX_UNITS; - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n"); - return 1; - } + int handled = 0; - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n"); - return 1; - } + /* Get the host lock for io completions */ + spin_lock(tw_dev->host->host_lock); - /* Now try to post the command packet */ - tw_post_command_packet(tw_dev, request_id); + /* See if the interrupt matches this instance */ + if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) { - return 0; -} /* End tw_scsiop_inquiry() */ + handled = 1; -/* This function is called by the isr to complete an inquiry command */ -int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) -{ - unsigned char *is_unit_present; - unsigned char *request_buffer; - TW_Param *param; + /* Read the registers */ + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); + /* Check if this is our interrupt, otherwise bail */ + if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT)) + goto tw_interrupt_bail; - /* Fill request buffer */ - if (tw_dev->srb[request_id]->request_buffer == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n"); - return 1; - } - request_buffer = tw_dev->srb[request_id]->request_buffer; - memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); - request_buffer[0] = TYPE_DISK; /* Peripheral device type */ - request_buffer[1] = 0; /* Device type modifier */ - request_buffer[2] = 0; /* No ansi/iso compliance */ - request_buffer[4] = 31; /* Additional length */ - memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ - sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); - memcpy(&request_buffer[32], tw_driver_version, 3); + /* Check controller for errors */ + if (tw_check_bits(status_reg_value)) { + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + if (tw_decode_bits(tw_dev, status_reg_value, 1)) { + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto tw_interrupt_bail; + } + } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - if (param == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n"); - return 1; - } - is_unit_present = &(param->data[0]); + /* Handle host interrupt */ + if (status_reg_value & TW_STATUS_HOST_INTERRUPT) { + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n"); + TW_CLEAR_HOST_INTERRUPT(tw_dev); + } - if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { - tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE; - } else { - tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE; - tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); - return TW_ISR_DONT_RESULT; - } + /* Handle attention interrupt */ + if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) { + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n"); + TW_CLEAR_ATTENTION_INTERRUPT(tw_dev); + tw_state_request_start(tw_dev, &request_id); + error = tw_aen_read_queue(tw_dev, request_id); + if (error) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + } + } - return 0; -} /* End tw_scsiop_inquiry_complete() */ + /* Handle command interrupt */ + if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) { + /* Drain as many pending commands as we can */ + while (tw_dev->pending_request_count > 0) { + request_id = tw_dev->pending_queue[tw_dev->pending_head]; + if (tw_dev->state[request_id] != TW_S_PENDING) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no); + break; + } + if (tw_post_command_packet(tw_dev, request_id)==0) { + if (tw_dev->pending_head == TW_Q_LENGTH-1) { + tw_dev->pending_head = TW_Q_START; + } else { + tw_dev->pending_head = tw_dev->pending_head + 1; + } + tw_dev->pending_request_count--; + } else { + /* If we get here, we will continue re-posting on the next command interrupt */ + break; + } + } + /* If there are no more pending requests, we mask command interrupt */ + if (tw_dev->pending_request_count == 0) + TW_MASK_COMMAND_INTERRUPT(tw_dev); + } -/* This function handles scsi mode_sense commands */ -int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id) -{ - TW_Param *param; - TW_Command *command_packet; - unsigned long command_que_value; - unsigned long param_value; + /* Handle response interrupt */ + if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) { + /* Drain the response queue from the board */ + while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { + /* Read response queue register */ + response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev)); + request_id = TW_RESID_OUT(response_que.response_id); + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + error = 0; - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n"); + /* Check for bad response */ + if (command_packet->status != 0) { + /* If internal command, don't error, don't fill sense */ + if (tw_dev->srb[request_id] == NULL) { + tw_decode_sense(tw_dev, request_id, 0); + } else { + error = tw_decode_sense(tw_dev, request_id, 1); + } + } - /* Only page control = 0, page code = 0x8 (cache page) supported */ - if (tw_dev->srb[request_id]->cmnd[2] != 0x8) { - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - return 0; - } + /* Check for correct state */ + if (tw_dev->state[request_id] != TW_S_POSTED) { + if (tw_dev->srb[request_id] != NULL) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no); + error = 1; + } + } - /* Now read firmware cache setting for this unit */ - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n"); - return 1; - } + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); - /* Setup the command packet */ - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; - - /* Setup the param */ - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n"); - return 1; - } - - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - memset(param, 0, sizeof(TW_Sector)); - param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id; - param->parameter_id = 7; /* unit flags */ - param->parameter_size_bytes = 1; - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n"); - return 1; - } - - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n"); - return 1; - } - - /* Now try to post the command packet */ - tw_post_command_packet(tw_dev, request_id); - - return 0; -} /* End tw_scsiop_mode_sense() */ - -/* This function is called by the isr to complete a mode sense command */ -int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id) -{ - TW_Param *param; - unsigned char *flags; - unsigned char *request_buffer; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n"); - - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - if (param == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n"); - return 1; - } - flags = (char *)&(param->data[0]); - request_buffer = tw_dev->srb[request_id]->buffer; - memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); - - request_buffer[0] = 0xf; /* mode data length */ - request_buffer[1] = 0; /* default medium type */ - request_buffer[2] = 0x10; /* dpo/fua support on */ - request_buffer[3] = 0; /* no block descriptors */ - request_buffer[4] = 0x8; /* caching page */ - request_buffer[5] = 0xa; /* page length */ - if (*flags & 0x1) - request_buffer[6] = 0x4; /* WCE on */ - else - request_buffer[6] = 0x0; /* WCE off */ - - return 0; -} /* End tw_scsiop_mode_sense_complete() */ - -/* This function handles scsi read_capacity commands */ -int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id) -{ - TW_Param *param; - TW_Command *command_packet; - unsigned long command_que_value; - u32 command_que_addr; - unsigned long param_value; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n"); - - /* Initialize command packet */ - command_que_addr = tw_dev->registers.command_que_addr; - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - - if (command_packet == NULL) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n"); - return 1; - } - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = tw_dev->srb[request_id]->device->id; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.block_count = 1; - - /* Now setup the param */ - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n"); - return 1; - } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - memset(param, 0, sizeof(TW_Sector)); - param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + - tw_dev->srb[request_id]->device->id; - param->parameter_id = 4; /* unitcapacity parameter */ - param->parameter_size_bytes = 4; - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n"); - return 1; - } - - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n"); - return 1; - } - - /* Now try to post the command to the board */ - tw_post_command_packet(tw_dev, request_id); - - return 0; -} /* End tw_scsiop_read_capacity() */ - -/* This function is called by the isr to complete a readcapacity command */ -int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id) -{ - unsigned char *param_data; - u32 capacity; - char *buff; - TW_Param *param; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n"); - - buff = tw_dev->srb[request_id]->request_buffer; - if (buff == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n"); - return 1; - } - 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]); - - capacity = (param_data[3] << 24) | (param_data[2] << 16) | - (param_data[1] << 8) | param_data[0]; - - /* Subtract one sector to fix get last sector ioctl */ - capacity -= 1; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity); - - /* Number of LBA's */ - buff[0] = (capacity >> 24); - buff[1] = (capacity >> 16) & 0xff; - buff[2] = (capacity >> 8) & 0xff; - buff[3] = capacity & 0xff; - - /* Block size in bytes (512) */ - buff[4] = (TW_BLOCK_SIZE >> 24); - buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff; - buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff; - buff[7] = TW_BLOCK_SIZE & 0xff; - - return 0; -} /* End tw_scsiop_read_capacity_complete() */ - -/* This function handles scsi read or write commands */ -int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) -{ - TW_Command *command_packet; - unsigned long command_que_value; - u32 command_que_addr = 0x0; - u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0; - int i, use_sg; - Scsi_Cmnd *srb; - struct scatterlist *sglist; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n"); - - if (tw_dev->srb[request_id]->request_buffer == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n"); - return 1; - } - sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; - srb = tw_dev->srb[request_id]; - - /* Initialize command packet */ - command_que_addr = tw_dev->registers.command_que_addr; - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n"); - return 1; - } - - if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) { - command_packet->byte0.opcode = TW_OP_READ; - } else { - command_packet->byte0.opcode = TW_OP_WRITE; - } - - command_packet->byte0.sgl_offset = 3; - command_packet->size = 3; - command_packet->request_id = request_id; - command_packet->byte3.unit = srb->device->id; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - - if (srb->cmnd[0] == WRITE_10) { - if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10)) - command_packet->flags = 1; - } - - if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) { - lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3]; - num_sectors = (u32)srb->cmnd[4]; - } else { - lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5]; - num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8); - } - - /* Update sector statistic */ - tw_dev->sector_count = num_sectors; - if (tw_dev->sector_count > tw_dev->max_sector_count) - tw_dev->max_sector_count = tw_dev->sector_count; - - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors); - command_packet->byte8.io.lba = lba; - command_packet->byte6.block_count = num_sectors; - - /* Do this if there are no sg list entries */ - if (tw_dev->srb[request_id]->use_sg == 0) { - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); - buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); - if (buffaddr == 0) - return 1; - - command_packet->byte8.io.sgl[0].address = buffaddr; - command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; - command_packet->size+=2; - } - - /* Do this if we have multiple sg list entries */ - if (tw_dev->srb[request_id]->use_sg > 0) { - use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); - if (use_sg == 0) - return 1; - - for (i=0;ibyte8.io.sgl[i].address = sg_dma_address(&sglist[i]); - command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]); - command_packet->size+=2; - } - } - - /* Update SG statistics */ - tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; - if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) - tw_dev->max_sgl_entries = tw_dev->sgl_entries; - - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n"); - return 1; - } - - /* Now try to post the command to the board */ - tw_post_command_packet(tw_dev, request_id); - - return 0; -} /* End tw_scsiop_read_write() */ - -/* This function will handle the request sense scsi command */ -int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id) -{ - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n"); - - /* For now we just zero the request buffer */ - memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - - /* If we got a request_sense, we probably want a reset, return error */ - tw_dev->srb[request_id]->result = (DID_ERROR << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - - return 0; -} /* End tw_scsiop_request_sense() */ + /* Check for internal command completion */ + if (tw_dev->srb[request_id] == NULL) { + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); + /* Check for chrdev ioctl completion */ + if (request_id != tw_dev->chrdev_request_id) { + retval = tw_aen_complete(tw_dev, request_id); + if (retval) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); + } + } else { + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + wake_up(&tw_dev->ioctl_wqueue); + } + } else { + switch (tw_dev->srb[request_id]->cmnd[0]) { + case READ_10: + case READ_6: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n"); + break; + case WRITE_10: + case WRITE_6: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n"); + break; + case TEST_UNIT_READY: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n"); + error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id); + break; + case INQUIRY: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n"); + error = tw_scsiop_inquiry_complete(tw_dev, request_id); + break; + case READ_CAPACITY: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n"); + error = tw_scsiop_read_capacity_complete(tw_dev, request_id); + break; + case MODE_SENSE: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n"); + error = tw_scsiop_mode_sense_complete(tw_dev, request_id); + break; + case SYNCHRONIZE_CACHE: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n"); + break; + default: + printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n"); + error = 1; + } -/* This function will handle synchronize cache scsi command */ -int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id) -{ - TW_Command *command_packet; - unsigned long command_que_value; + /* If no error command was a success */ + if (error == 0) { + tw_dev->srb[request_id]->result = (DID_OK << 16); + } - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n"); + /* If error, command failed */ + if (error == 1) { + /* Ask for a host reset */ + tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + } - /* Send firmware flush command for this unit */ - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n"); - return 1; - } + /* Now complete the io */ + if ((error != TW_ISR_DONT_COMPLETE)) { + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; + tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); - /* Setup the command packet */ - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_FLUSH_CACHE; - command_packet->byte0.sgl_offset = 0; - command_packet->size = 2; - command_packet->request_id = request_id; - command_packet->byte3.unit = tw_dev->srb[request_id]->device->id; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n"); - return 1; + tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + } + } + + /* Check for valid status after each drain */ + status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev)); + if (tw_check_bits(status_reg_value)) { + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + if (tw_decode_bits(tw_dev, status_reg_value, 1)) { + TW_CLEAR_ALL_INTERRUPTS(tw_dev); + goto tw_interrupt_bail; + } + } + } + } } +tw_interrupt_bail: + spin_unlock(tw_dev->host->host_lock); + return IRQ_RETVAL(handled); +} /* End tw_interrupt() */ - /* Now try to post the command packet */ - tw_post_command_packet(tw_dev, request_id); - - return 0; -} /* End tw_scsiop_synchronize_cache() */ - -/* This function will handle test unit ready scsi command */ -int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id) +/* This function tells the controller to shut down */ +static void __tw_shutdown(TW_Device_Extension *tw_dev) { - TW_Param *param; - TW_Command *command_packet; - unsigned long command_que_value; - u32 command_que_addr; - unsigned long param_value; + /* Disable interrupts */ + TW_DISABLE_INTERRUPTS(tw_dev); - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n"); + printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no); - /* Initialize command packet */ - command_que_addr = tw_dev->registers.command_que_addr; - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - if (command_packet == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n"); - return 1; + /* Tell the card we are shutting down */ + if (tw_initconnection(tw_dev, 1)) { + printk(KERN_WARNING "3w-xxxx: Connection shutdown failed.\n"); + } else { + printk(KERN_WARNING "3w-xxxx: Shutdown complete.\n"); } - memset(command_packet, 0, sizeof(TW_Sector)); - command_packet->byte0.opcode = TW_OP_GET_PARAM; - command_packet->byte0.sgl_offset = 2; - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte3.unit = 0; - command_packet->byte3.host_id = 0; - command_packet->status = 0; - command_packet->flags = 0; - command_packet->byte6.parameter_count = 1; - /* Now setup the param */ - if (tw_dev->alignment_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n"); - return 1; - } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - memset(param, 0, sizeof(TW_Sector)); - param->table_id = 3; /* unit summary table */ - param->parameter_id = 3; /* unitsstatus parameter */ - param->parameter_size_bytes = TW_MAX_UNITS; - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n"); - return 1; - } + /* Clear all interrupts just before exit */ + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); +} /* End __tw_shutdown() */ - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n"); - return 1; - } +/* Wrapper for __tw_shutdown */ +static void tw_shutdown(struct device *dev) +{ + struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev)); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; - /* Now try to post the command packet */ - tw_post_command_packet(tw_dev, request_id); + __tw_shutdown(tw_dev); +} /* End tw_shutdown() */ - return 0; -} /* End tw_scsiop_test_unit_ready() */ +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = "3ware Storage Controller", + .queuecommand = tw_scsi_queue, + .eh_host_reset_handler = tw_scsi_eh_reset, + .bios_param = tw_scsi_biosparam, + .can_queue = TW_Q_LENGTH-2, + .this_id = -1, + .sg_tablesize = TW_MAX_SGL_LENGTH, + .max_sectors = TW_MAX_SECTORS, + .cmd_per_lun = TW_MAX_CMDS_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = tw_host_attrs, + .sdev_attrs = tw_dev_attrs, + .emulated = 1 +}; -/* This function is called by the isr to complete a testunitready command */ -int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id) +/* This function will probe and initialize a card */ +static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) { - unsigned char *is_unit_present; - TW_Param *param; + struct Scsi_Host *host = NULL; + TW_Device_Extension *tw_dev; + int retval = -ENODEV; - dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n"); + retval = pci_enable_device(pdev); + if (retval) { + printk(KERN_WARNING "3w-xxxx: Failed to enable pci device."); + goto out_disable_device; + } - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - if (param == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n"); - return 1; + pci_set_master(pdev); + + retval = pci_set_dma_mask(pdev, TW_DMA_MASK); + if (retval) { + printk(KERN_WARNING "3w-xxxx: Failed to set dma mask."); + goto out_disable_device; } - is_unit_present = &(param->data[0]); - if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { - tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE; - } else { - tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE; - tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); - return TW_ISR_DONT_RESULT; + host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); + if (!host) { + printk(KERN_WARNING "3w-xxxx: Failed to allocate memory for device extension."); + retval = -ENOMEM; + goto out_disable_device; } + tw_dev = (TW_Device_Extension *)host->hostdata; - return 0; -} /* End tw_scsiop_test_unit_ready_complete() */ + memset(tw_dev, 0, sizeof(TW_Device_Extension)); -/* Set a value in the features table */ -int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, - unsigned char *val) -{ - TW_Param *param; - TW_Command *command_packet; - TW_Response_Queue response_queue; - int request_id = 0; - unsigned long command_que_value; - u32 command_que_addr; - u32 response_que_addr; - unsigned long param_value; + /* Save values to device extension */ + tw_dev->host = host; + tw_dev->tw_pci_dev = pdev; - /* Initialize SetParam command packet */ - if (tw_dev->command_packet_virtual_address[request_id] == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n"); - return 1; + if (tw_initialize_device_extension(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension."); + goto out_free_device_extension; } - command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; - memset(command_packet, 0, sizeof(TW_Sector)); - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - - command_packet->byte0.opcode = TW_OP_SET_PARAM; - command_packet->byte0.sgl_offset = 2; - param->table_id = 0x404; /* Features table */ - param->parameter_id = parm; - param->parameter_size_bytes = param_size; - memcpy(param->data, val, param_size); - param_value = tw_dev->alignment_physical_address[request_id]; - if (param_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n"); - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + /* Request IO regions */ + retval = pci_request_regions(pdev, "3w-xxxx"); + if (retval) { + printk(KERN_WARNING "3w-xxxx: Failed to get mem region."); + goto out_free_device_extension; } - command_packet->byte8.param.sgl[0].address = param_value; - command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); - - command_packet->size = 4; - command_packet->request_id = request_id; - command_packet->byte6.parameter_count = 1; - command_que_value = tw_dev->command_packet_physical_address[request_id]; - if (command_que_value == 0) { - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n"); - return 1; + /* Save base address */ + tw_dev->base_addr = pci_resource_start(pdev, 0); + if (!tw_dev->base_addr) { + printk(KERN_WARNING "3w-xxxx: Failed to get io address."); + goto out_release_mem_region; } - command_que_addr = tw_dev->registers.command_que_addr; - response_que_addr = tw_dev->registers.response_que_addr; - - /* Send command packet to the board */ - outl(command_que_value, command_que_addr); - /* Poll for completion */ - if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) { - response_queue.value = inl(response_que_addr); - request_id = (unsigned char)response_queue.u.response_id; - if (request_id != 0) { - /* unexpected request id */ - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n"); - return 1; - } - if (command_packet->status != 0) { - /* bad response */ - tw_decode_sense(tw_dev, request_id, 0); - return 1; - } - } + /* Disable interrupts on the card */ + TW_DISABLE_INTERRUPTS(tw_dev); - return 0; -} /* End tw_setfeature() */ + /* Initialize the card */ + if (tw_reset_sequence(tw_dev)) + goto out_release_mem_region; -/* This function will setup the interrupt handler */ -int tw_setup_irq(TW_Device_Extension *tw_dev) -{ - char *device = TW_DEVICE_NAME; - int error; + /* Set host specific parameters */ + host->max_id = TW_MAX_UNITS; + host->max_cmd_len = TW_MAX_CDB_LEN; - dprintk(KERN_NOTICE "3w-xxxx: tw_setup_irq()\n"); - error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev); + /* Luns and channels aren't supported by adapter */ + host->max_lun = 0; + host->max_channel = 0; - if (error < 0) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq); - return 1; + /* Register the card with the kernel SCSI layer */ + retval = scsi_add_host(host, &pdev->dev); + if (retval) { + printk(KERN_WARNING "3w-xxxx: scsi add host failed"); + goto out_release_mem_region; } - return 0; -} /* End tw_setup_irq() */ -/* This function will tell the controller we're shutting down by sending - initconnection with a 1 */ -int tw_shutdown_device(TW_Device_Extension *tw_dev) -{ - int error; + pci_set_drvdata(pdev, host); - /* Disable interrupts */ - tw_disable_interrupts(tw_dev); + printk(KERN_WARNING "3w-xxxx: scsi%d: Found a 3ware Storage Controller at 0x%x, IRQ: %d.\n", host->host_no, tw_dev->base_addr, pdev->irq); - /* poke the board */ - error = tw_initconnection(tw_dev, 1); - if (error) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no); - } else { - printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n"); + /* Now setup the interrupt handler */ + retval = request_irq(pdev->irq, tw_interrupt, SA_SHIRQ, "3w-xxxx", tw_dev); + if (retval) { + printk(KERN_WARNING "3w-xxxx: Error requesting IRQ."); + goto out_remove_host; } - /* Re-enable interrupts */ - tw_enable_and_clear_interrupts(tw_dev); - - return 0; -} /* End tw_shutdown_device() */ + tw_device_extension_list[tw_device_extension_count] = tw_dev; + tw_device_extension_count++; -/* This function will configure individual target parameters */ -int tw_slave_configure(Scsi_Device *SDptr) -{ - int max_cmds; + /* Re-enable interrupts on the card */ + TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); - dprintk(KERN_WARNING "3w-xxxx: tw_slave_configure()\n"); + /* Finally, scan the host */ + scsi_scan_host(host); - if (cmds_per_lun) { - max_cmds = cmds_per_lun; - if (max_cmds > TW_MAX_CMDS_PER_LUN) - max_cmds = TW_MAX_CMDS_PER_LUN; - } else { - max_cmds = TW_MAX_CMDS_PER_LUN; + if (twe_major == -1) { + if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0) + printk(KERN_WARNING "3w-xxxx: Failed to register character device."); } - scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, max_cmds); - return 0; -} /* End tw_slave_configure() */ -/* This function will soft reset the controller */ -void tw_soft_reset(TW_Device_Extension *tw_dev) -{ - u32 control_reg_addr, control_reg_value; - - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = ( TW_CONTROL_ISSUE_SOFT_RESET | - TW_CONTROL_CLEAR_HOST_INTERRUPT | - TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | - TW_CONTROL_MASK_COMMAND_INTERRUPT | - TW_CONTROL_MASK_RESPONSE_INTERRUPT | - TW_CONTROL_CLEAR_ERROR_STATUS | - TW_CONTROL_DISABLE_INTERRUPTS); - outl(control_reg_value, control_reg_addr); -} /* End tw_soft_reset() */ +out_remove_host: + scsi_remove_host(host); +out_release_mem_region: + pci_release_regions(pdev); +out_free_device_extension: + tw_free_device_extension(tw_dev); + scsi_host_put(host); +out_disable_device: + pci_disable_device(pdev); -/* This function will free a request_id */ -int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id) + return retval; +} /* End tw_probe() */ + +/* This function is called to remove a device */ +static void tw_remove(struct pci_dev *pdev) { - dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n"); - - tw_dev->free_queue[tw_dev->free_tail] = request_id; - tw_dev->state[request_id] = TW_S_FINISHED; - if (tw_dev->free_tail == tw_dev->free_wrap) - tw_dev->free_tail = TW_Q_START; - else - tw_dev->free_tail++; + struct Scsi_Host *host = pci_get_drvdata(pdev); + TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; - dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id); + scsi_remove_host(tw_dev->host); - return 0; -} /* End tw_state_request_finish() */ + __tw_shutdown(tw_dev); -/* This function will assign an available request_id */ -int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id) -{ - int id = 0; + /* Free up the IRQ */ + free_irq(tw_dev->tw_pci_dev->irq, tw_dev); - dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n"); - - /* Obtain next free request_id */ - id = tw_dev->free_queue[tw_dev->free_head]; - if (tw_dev->free_head == tw_dev->free_wrap) - tw_dev->free_head = TW_Q_START; - else - tw_dev->free_head++; + /* Free up the mem region */ + pci_release_regions(pdev); - *request_id = id; - tw_dev->state[id] = TW_S_STARTED; + /* Free up device extension resources */ + tw_free_device_extension(tw_dev); - dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id); - return 0; -} /* End tw_state_request_start() */ + /* Unregister character device */ + if (twe_major >= 0) { + unregister_chrdev(twe_major, "twe"); + twe_major = -1; + } -static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd) -{ - int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + scsi_host_put(tw_dev->host); + pci_disable_device(pdev); + tw_device_extension_count--; +} /* End tw_remove() */ - dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); +/* PCI Devices supported by this driver */ +static struct pci_device_id tw_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_1000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_7000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; +MODULE_DEVICE_TABLE(pci, tw_pci_tbl); - switch(cmd->SCp.phase) { - case 1: - pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, dma_dir); - break; - case 2: - pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir); - break; +/* pci_driver initializer */ +static struct pci_driver tw_driver = { + .name = "3w-xxxx", + .id_table = tw_pci_tbl, + .probe = tw_probe, + .remove = tw_remove, + .driver = { + .shutdown = tw_shutdown } -} /* End tw_unmap_scsi_data() */ +}; -/* This function will unmask the command interrupt on the controller */ -void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev) +/* This function is called on driver initialization */ +static int __init tw_init(void) { - u32 control_reg_addr, control_reg_value; + printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION); - control_reg_addr = tw_dev->registers.control_reg_addr; - control_reg_value = TW_CONTROL_UNMASK_COMMAND_INTERRUPT; - outl(control_reg_value, control_reg_addr); -} /* End tw_unmask_command_interrupt() */ + return pci_module_init(&tw_driver); +} /* End tw_init() */ -static Scsi_Host_Template driver_template = { - .proc_name = "3w-xxxx", - .proc_info = tw_scsi_proc_info, - .name = "3ware Storage Controller", - .detect = tw_scsi_detect, - .release = tw_scsi_release, - .queuecommand = tw_scsi_queue, - .eh_abort_handler = tw_scsi_eh_abort, - .eh_host_reset_handler = tw_scsi_eh_reset, - .bios_param = tw_scsi_biosparam, - .slave_configure = tw_slave_configure, - .can_queue = TW_Q_LENGTH-2, - .this_id = -1, - .sg_tablesize = TW_MAX_SGL_LENGTH, - .max_sectors = TW_MAX_SECTORS, - .cmd_per_lun = TW_MAX_CMDS_PER_LUN, - .use_clustering = ENABLE_CLUSTERING, - .emulated = 1 -}; -#include "scsi_module.c" +/* This function is called on driver exit */ +static void __exit tw_exit(void) +{ + pci_unregister_driver(&tw_driver); +} /* End tw_exit() */ + +module_init(tw_init); +module_exit(tw_exit); diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 7b9bb938b..df070a8f8 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -180,7 +180,6 @@ static unsigned char tw_sense_table[][4] = #define TW_OP_AEN_LISTEN 0x1c #define TW_OP_FLUSH_CACHE 0x0e #define TW_CMD_PACKET 0x1d -#define TW_ATA_PASSTHRU 0x1e #define TW_CMD_PACKET_WITH_DATA 0x1f /* Asynchronous Event Notification (AEN) Codes */ @@ -197,6 +196,11 @@ static unsigned char tw_sense_table[][4] = #define TW_AEN_SMART_FAIL 0x000F #define TW_AEN_SBUF_FAIL 0x0024 +/* Phase defines */ +#define TW_PHASE_INITIAL 0 +#define TW_PHASE_SINGLE 1 +#define TW_PHASE_SGLIST 2 + /* Misc defines */ #define TW_ALIGNMENT_6000 64 /* 64 bytes */ #define TW_ALIGNMENT_7000 4 /* 4 bytes */ @@ -207,7 +211,6 @@ static unsigned char tw_sense_table[][4] = #define TW_POLL_MAX_RETRIES 20000 #define TW_MAX_SGL_LENGTH 62 #define TW_ATA_PASS_SGL_MAX 60 -#define TW_MAX_PASSTHRU_BYTES 4096 #define TW_Q_LENGTH 256 #define TW_Q_START 0 #define TW_MAX_SLOT 32 @@ -221,7 +224,7 @@ static unsigned char tw_sense_table[][4] = #define TW_IOCTL 0x80 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 -#define TW_IN_IOCTL 2 +#define TW_IN_RESET 2 #define TW_IN_CHRDEV_IOCTL 3 #define TW_MAX_SECTORS 256 #define TW_AEN_WAIT_TIME 1000 @@ -231,8 +234,41 @@ static unsigned char tw_sense_table[][4] = #define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ #define TW_IOCTL_CHRDEV_TIMEOUT 60 /* 60 seconds */ #define TW_IOCTL_CHRDEV_FREE -1 +#define TW_DMA_MASK DMA_32BIT_MASK +#define TW_MAX_CDB_LEN 16 + +/* Bitmask macros to eliminate bitfields */ + +/* opcode: 5, sgloffset: 3 */ +#define TW_OPSGL_IN(x,y) ((x << 5) | (y & 0x1f)) +#define TW_SGL_OUT(x) ((x >> 5) & 0x7) + +/* reserved_1: 4, response_id: 8, reserved_2: 20 */ +#define TW_RESID_OUT(x) ((x >> 4) & 0xff) + +/* unit: 4, host_id: 4 */ +#define TW_UNITHOST_IN(x,y) ((x << 4) | ( y & 0xf)) +#define TW_UNIT_OUT(x) (x & 0xf) /* Macros */ +#define TW_CONTROL_REG_ADDR(x) (x->base_addr) +#define TW_STATUS_REG_ADDR(x) (x->base_addr + 0x4) +#define TW_COMMAND_QUEUE_REG_ADDR(x) (x->base_addr + 0x8) +#define TW_RESPONSE_QUEUE_REG_ADDR(x) (x->base_addr + 0xC) +#define TW_CLEAR_ALL_INTERRUPTS(x) (outl(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_CLEAR_ATTENTION_INTERRUPT(x) (outl(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_CLEAR_HOST_INTERRUPT(x) (outl(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_DISABLE_INTERRUPTS(x) (outl(TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) +#define TW_ENABLE_AND_CLEAR_INTERRUPTS(x) (outl(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | TW_CONTROL_UNMASK_RESPONSE_INTERRUPT | TW_CONTROL_ENABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) +#define TW_MASK_COMMAND_INTERRUPT(x) (outl(TW_CONTROL_MASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_UNMASK_COMMAND_INTERRUPT(x) (outl(TW_CONTROL_UNMASK_COMMAND_INTERRUPT, TW_CONTROL_REG_ADDR(x))) +#define TW_SOFT_RESET(x) (outl(TW_CONTROL_ISSUE_SOFT_RESET | \ + TW_CONTROL_CLEAR_HOST_INTERRUPT | \ + TW_CONTROL_CLEAR_ATTENTION_INTERRUPT | \ + TW_CONTROL_MASK_COMMAND_INTERRUPT | \ + TW_CONTROL_MASK_RESPONSE_INTERRUPT | \ + TW_CONTROL_CLEAR_ERROR_STATUS | \ + TW_CONTROL_DISABLE_INTERRUPTS, TW_CONTROL_REG_ADDR(x))) #define TW_STATUS_ERRORS(x) \ (((x & TW_STATUS_PCI_ABORT) || \ (x & TW_STATUS_PCI_PARITY_ERROR) || \ @@ -258,17 +294,10 @@ typedef unsigned char TW_Sector[512]; /* Command Packet */ typedef struct TW_Command { - /* First DWORD */ - struct { - unsigned char opcode:5; - unsigned char sgl_offset:3; - } byte0; + unsigned char opcode__sgloffset; unsigned char size; unsigned char request_id; - struct { - unsigned char unit:4; - unsigned char host_id:4; - } byte3; + unsigned char unit__hostid; /* Second DWORD */ unsigned char status; unsigned char flags; @@ -328,29 +357,10 @@ typedef struct { /* Response queue */ typedef union TAG_TW_Response_Queue { - struct { - u32 undefined_1: 4; - u32 response_id: 8; - u32 undefined_2: 20; - } u; + u32 response_id; u32 value; } TW_Response_Queue; -typedef struct TAG_TW_Registers { - u32 base_addr; - u32 control_reg_addr; - u32 status_reg_addr; - u32 command_que_addr; - u32 response_que_addr; -} TW_Registers; - -typedef struct TAG_TW_Info { - char *buffer; - int length; - int offset; - int position; -} TW_Info; - typedef int TW_Cmd_State; #define TW_S_INITIAL 0x1 /* Initial state */ @@ -364,16 +374,10 @@ typedef int TW_Cmd_State; /* Command header for ATA pass-thru */ typedef struct TAG_TW_Passthru { - struct { - unsigned char opcode:5; - unsigned char sgloff:3; - } byte0; + unsigned char opcode__sgloffset; unsigned char size; unsigned char request_id; - struct { - unsigned char aport:4; - unsigned char host_id:4; - } byte3; + unsigned char aport__hostid; unsigned char status; unsigned char flags; unsigned short param; @@ -389,7 +393,7 @@ typedef struct TAG_TW_Passthru } TW_Passthru; typedef struct TAG_TW_Device_Extension { - TW_Registers registers; + u32 base_addr; unsigned long *alignment_virtual_address[TW_Q_LENGTH]; unsigned long alignment_physical_address[TW_Q_LENGTH]; int is_unit_present[TW_MAX_UNITS]; @@ -397,11 +401,10 @@ typedef struct TAG_TW_Device_Extension { unsigned long *command_packet_virtual_address[TW_Q_LENGTH]; unsigned long command_packet_physical_address[TW_Q_LENGTH]; struct pci_dev *tw_pci_dev; - Scsi_Cmnd *srb[TW_Q_LENGTH]; + struct scsi_cmnd *srb[TW_Q_LENGTH]; unsigned char free_queue[TW_Q_LENGTH]; unsigned char free_head; unsigned char free_tail; - unsigned char free_wrap; unsigned char pending_queue[TW_Q_LENGTH]; unsigned char pending_head; unsigned char pending_tail; @@ -413,83 +416,21 @@ typedef struct TAG_TW_Device_Extension { u32 max_pending_request_count; u32 max_sgl_entries; u32 sgl_entries; - u32 num_aborts; u32 num_resets; u32 sector_count; u32 max_sector_count; u32 aen_count; struct Scsi_Host *host; - spinlock_t tw_lock; struct semaphore ioctl_sem; - int ioctl_size[TW_Q_LENGTH]; unsigned short aen_queue[TW_Q_LENGTH]; unsigned char aen_head; unsigned char aen_tail; volatile long flags; /* long req'd for set_bit --RR */ - unsigned long *ioctl_data[TW_Q_LENGTH]; int reset_print; - char online; volatile int chrdev_request_id; wait_queue_head_t ioctl_wqueue; } TW_Device_Extension; #pragma pack() -/* Function prototypes */ -int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id); -int tw_aen_drain_queue(TW_Device_Extension *tw_dev); -int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id); -int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which); -int tw_check_bits(u32 status_reg_value); -int tw_check_errors(TW_Device_Extension *tw_dev); -void tw_clear_all_interrupts(TW_Device_Extension *tw_dev); -void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev); -void tw_clear_host_interrupt(TW_Device_Extension *tw_dev); -int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host); -int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense); -void tw_disable_interrupts(TW_Device_Extension *tw_dev); -void tw_empty_response_que(TW_Device_Extension *tw_dev); -void tw_enable_interrupts(TW_Device_Extension *tw_dev); -void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev); -int tw_findcards(Scsi_Host_Template *tw_host); -void tw_free_device_extension(TW_Device_Extension *tw_dev); -int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits); -int tw_initialize_device_extension(TW_Device_Extension *tw_dev); -int tw_initialize_units(TW_Device_Extension *tw_dev); -int tw_ioctl(TW_Device_Extension *tw_dev, int request_id); -int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id); -void tw_mask_command_interrupt(TW_Device_Extension *tw_dev); -int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds); -int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); -int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id); -int tw_reset_device_extension(TW_Device_Extension *tw_dev); -int tw_reset_sequence(TW_Device_Extension *tw_dev); -int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]); -int tw_scsi_detect(Scsi_Host_Template *tw_host); -int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt); -int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt); -int tw_scsi_queue(Scsi_Cmnd *cmd, void (*done) (Scsi_Cmnd *)); -int tw_scsi_release(struct Scsi_Host *tw_host); -int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id); -int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id); -int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, - unsigned char *val); -int tw_setup_irq(TW_Device_Extension *tw_dev); -int tw_shutdown_device(TW_Device_Extension *tw_dev); -int tw_slave_configure(Scsi_Device *SDptr); -void tw_soft_reset(TW_Device_Extension *tw_dev); -int tw_state_request_finish(TW_Device_Extension *tw_dev,int request_id); -int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id); -void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev); - #endif /* _3W_XXXX_H */ diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 1495f0f8d..d9b355366 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -287,13 +287,15 @@ NCR_700_get_SXFER(struct scsi_device *SDp) struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; - return NCR_700_offset_period_to_sxfer(hostdata, spi_offset(SDp), - spi_period(SDp)); + return NCR_700_offset_period_to_sxfer(hostdata, + spi_offset(SDp->sdev_target), + spi_period(SDp->sdev_target)); } struct Scsi_Host * NCR_700_detect(struct scsi_host_template *tpnt, - struct NCR_700_Host_Parameters *hostdata) + struct NCR_700_Host_Parameters *hostdata, struct device *dev, + unsigned long irq, u8 scsi_id) { dma_addr_t pScript, pSlots; __u8 *memory; @@ -320,6 +322,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, * if this isn't sufficient separation to avoid dma flushing issues */ BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); + hostdata->dev = dev; pSlots = pScript + SLOTS_OFFSET; @@ -386,6 +389,8 @@ NCR_700_detect(struct scsi_host_template *tpnt, host->unique_id = hostdata->base; host->base = hostdata->base; hostdata->eh_complete = NULL; + host->irq = irq; + host->this_id = scsi_id; host->hostdata[0] = (unsigned long)hostdata; /* kick the chip */ NCR_700_writeb(0xff, host, CTEST9_REG); @@ -406,7 +411,28 @@ NCR_700_detect(struct scsi_host_template *tpnt, /* reset the chip */ NCR_700_chip_reset(host); + if (request_irq(irq, NCR_700_intr, SA_SHIRQ, dev->bus_id, host)) { + dev_printk(KERN_ERR, dev, "53c700: irq %lu request failed\n ", + irq); + goto out_put_host; + } + + if (scsi_add_host(host, dev)) { + dev_printk(KERN_ERR, dev, "53c700: scsi_add_host failed\n"); + goto out_release_irq; + } + + spi_signalling(host) = hostdata->differential ? SPI_SIGNAL_HVD : + SPI_SIGNAL_SE; + return host; + + out_release_irq: + free_irq(irq, host); + out_put_host: + scsi_host_put(host); + + return NULL; } int @@ -803,7 +829,7 @@ process_extended_message(struct Scsi_Host *host, } if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) { - if(spi_offset(SCp->device) != 0) + if(spi_offset(SCp->device->sdev_target) != 0) printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", host->host_no, pun, lun, offset, period*4); @@ -813,8 +839,8 @@ process_extended_message(struct Scsi_Host *host, NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); } - spi_offset(SCp->device) = offset; - spi_period(SCp->device) = period; + spi_offset(SCp->device->sdev_target) = offset; + spi_period(SCp->device->sdev_target) = period; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); @@ -894,7 +920,8 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata case A_REJECT_MSG: if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { /* Rejected our sync negotiation attempt */ - spi_period(SCp->device) = spi_offset(SCp->device) = 0; + spi_period(SCp->device->sdev_target) = + spi_offset(SCp->device->sdev_target) = 0; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { @@ -1420,8 +1447,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp) NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, sizeof(NCR_700_SDTR_msg)); - hostdata->msgout[count+3] = spi_period(SCp->device); - hostdata->msgout[count+4] = spi_offset(SCp->device); + hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); + hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target); count += sizeof(NCR_700_SDTR_msg); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } @@ -1961,7 +1988,7 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp) * reset via sg or something */ while(hostdata->eh_complete != NULL) { spin_unlock_irq(SCp->device->host->host_lock); - schedule_timeout(HZ/10); + msleep_interruptible(100); spin_lock_irq(SCp->device->host->host_lock); } hostdata->eh_complete = &complete; @@ -1999,10 +2026,11 @@ NCR_700_host_reset(struct scsi_cmnd * SCp) } STATIC void -NCR_700_set_period(struct scsi_device *SDp, int period) +NCR_700_set_period(struct scsi_target *STp, int period) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; if(!hostdata->fast) return; @@ -2010,17 +2038,18 @@ NCR_700_set_period(struct scsi_device *SDp, int period) if(period < hostdata->min_period) period = hostdata->min_period; - spi_period(SDp) = period; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + spi_period(STp) = period; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } STATIC void -NCR_700_set_offset(struct scsi_device *SDp, int offset) +NCR_700_set_offset(struct scsi_target *STp, int offset) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; int max_offset = hostdata->chip710 ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET; @@ -2031,14 +2060,14 @@ NCR_700_set_offset(struct scsi_device *SDp, int offset) offset = max_offset; /* if we're currently async, make sure the period is reasonable */ - if(spi_offset(SDp) == 0 && (spi_period(SDp) < hostdata->min_period || - spi_period(SDp) > 0xff)) - spi_period(SDp) = hostdata->min_period; - - spi_offset(SDp) = offset; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + if(spi_offset(STp) == 0 && (spi_period(STp) < hostdata->min_period || + spi_period(STp) > 0xff)) + spi_period(STp) = hostdata->min_period; + + spi_offset(STp) = offset; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } @@ -2058,10 +2087,11 @@ NCR_700_slave_configure(struct scsi_device *SDp) } if(hostdata->fast) { /* Find the correct offset and period via domain validation */ - spi_dv_device(SDp); + if (!spi_initial_dv(SDp->sdev_target)) + spi_dv_device(SDp); } else { - spi_offset(SDp) = 0; - spi_period(SDp) = 0; + spi_offset(SDp->sdev_target) = 0; + spi_period(SDp->sdev_target) = 0; } return 0; } diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index b357a4aeb..c84c2b7f9 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -60,7 +60,8 @@ struct NCR_700_Host_Parameters; /* These are the externally used routines */ struct Scsi_Host *NCR_700_detect(struct scsi_host_template *, - struct NCR_700_Host_Parameters *); + struct NCR_700_Host_Parameters *, struct device *, + unsigned long, u8); int NCR_700_release(struct Scsi_Host *host); irqreturn_t NCR_700_intr(int, void *, struct pt_regs *); @@ -121,22 +122,22 @@ NCR_700_get_depth(struct scsi_device *SDp) static inline int NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag) { - return (((unsigned long)SDp->hostdata) & flag) == flag; + return (spi_flags(SDp->sdev_target) & flag) == flag; } static inline int NCR_700_is_flag_clear(struct scsi_device *SDp, __u32 flag) { - return (((unsigned long)SDp->hostdata) & flag) == 0; + return (spi_flags(SDp->sdev_target) & flag) == 0; } static inline void NCR_700_set_flag(struct scsi_device *SDp, __u32 flag) { - SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000)); + spi_flags(SDp->sdev_target) |= flag; } static inline void NCR_700_clear_flag(struct scsi_device *SDp, __u32 flag) { - SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000)); + spi_flags(SDp->sdev_target) &= ~flag; } struct NCR_700_command_slot { diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index e4d60d1d1..41b5197ce 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -47,8 +47,11 @@ #include #include -#include "scsi.h" +#include +#include +#include #include +#include #include "BusLogic.h" #include "FlashPoint.c" @@ -56,6 +59,8 @@ #define FAILURE (-1) #endif +static struct scsi_host_template Bus_Logic_template; + /* BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver Options specifications provided via the Linux Kernel Command Line or via @@ -81,7 +86,7 @@ static struct BusLogic_DriverOptions BusLogic_DriverOptions[BusLogic_MaxHostAdap MODULE_LICENSE("GPL"); #ifdef MODULE static char *BusLogic; -MODULE_PARM(BusLogic, "s"); +module_param(BusLogic, charp, 0); #endif @@ -100,15 +105,7 @@ static struct BusLogic_ProbeOptions BusLogic_ProbeOptions; static struct BusLogic_GlobalOptions BusLogic_GlobalOptions; - -/* - BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter - are pointers to the first and last registered BusLogic Host Adapters. -*/ - -static struct BusLogic_HostAdapter *BusLogic_FirstRegisteredHostAdapter; -static struct BusLogic_HostAdapter *BusLogic_LastRegisteredHostAdapter; - +static LIST_HEAD(BusLogic_host_list); /* BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList. @@ -142,11 +139,8 @@ static char *BusLogic_CommandFailureReason; static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter) { - BusLogic_Announce("***** BusLogic SCSI Driver Version " - BusLogic_DriverVersion " of " - BusLogic_DriverDate " *****\n", HostAdapter); - BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " - "\n", HostAdapter); + BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter); + BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "\n", HostAdapter); } @@ -157,94 +151,39 @@ static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter) static const char *BusLogic_DriverInfo(struct Scsi_Host *Host) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) Host->hostdata; - return HostAdapter->FullModelName; -} - - -/* - BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered - BusLogic Host Adapters. -*/ - -static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter) -{ - HostAdapter->Next = NULL; - if (BusLogic_FirstRegisteredHostAdapter == NULL) - { - BusLogic_FirstRegisteredHostAdapter = HostAdapter; - BusLogic_LastRegisteredHostAdapter = HostAdapter; - } - else - { - BusLogic_LastRegisteredHostAdapter->Next = HostAdapter; - BusLogic_LastRegisteredHostAdapter = HostAdapter; - } + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata; + return HostAdapter->FullModelName; } - -/* - BusLogic_UnregisterHostAdapter removes Host Adapter from the list of - registered BusLogic Host Adapters. -*/ - -static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter) -{ - if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) - { - BusLogic_FirstRegisteredHostAdapter = - BusLogic_FirstRegisteredHostAdapter->Next; - if (HostAdapter == BusLogic_LastRegisteredHostAdapter) - BusLogic_LastRegisteredHostAdapter = NULL; - } - else - { - struct BusLogic_HostAdapter *PreviousHostAdapter = - BusLogic_FirstRegisteredHostAdapter; - while (PreviousHostAdapter != NULL && - PreviousHostAdapter->Next != HostAdapter) - PreviousHostAdapter = PreviousHostAdapter->Next; - if (PreviousHostAdapter != NULL) - PreviousHostAdapter->Next = HostAdapter->Next; - } - HostAdapter->Next = NULL; -} - - /* BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs) for Host Adapter from the BlockSize bytes located at BlockPointer. The newly created CCBs are added to Host Adapter's free list. */ -static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, - void *BlockPointer, int BlockSize, - dma_addr_t BlockPointerHandle) +static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle) { - struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer; - unsigned int offset = 0; - memset(BlockPointer, 0, BlockSize); - CCB->AllocationGroupHead = BlockPointerHandle; - CCB->AllocationGroupSize = BlockSize; - while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) - { - CCB->Status = BusLogic_CCB_Free; - CCB->HostAdapter = HostAdapter; - CCB->DMA_Handle = (u32)BlockPointerHandle + offset; - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - CCB->CallbackFunction = BusLogic_QueueCompletedCCB; - CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress; + struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer; + unsigned int offset = 0; + memset(BlockPointer, 0, BlockSize); + CCB->AllocationGroupHead = BlockPointerHandle; + CCB->AllocationGroupSize = BlockSize; + while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) { + CCB->Status = BusLogic_CCB_Free; + CCB->HostAdapter = HostAdapter; + CCB->DMA_Handle = (u32) BlockPointerHandle + offset; + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) { + CCB->CallbackFunction = BusLogic_QueueCompletedCCB; + CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress; + } + CCB->Next = HostAdapter->Free_CCBs; + CCB->NextAll = HostAdapter->All_CCBs; + HostAdapter->Free_CCBs = CCB; + HostAdapter->All_CCBs = CCB; + HostAdapter->AllocatedCCBs++; + CCB++; + offset += sizeof(struct BusLogic_CCB); } - CCB->Next = HostAdapter->Free_CCBs; - CCB->NextAll = HostAdapter->All_CCBs; - HostAdapter->Free_CCBs = CCB; - HostAdapter->All_CCBs = CCB; - HostAdapter->AllocatedCCBs++; - CCB++; - offset += sizeof(struct BusLogic_CCB); - } } @@ -254,23 +193,18 @@ static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter) { - int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); - void *BlockPointer; - dma_addr_t BlockPointerHandle; - while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) - { - BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, - &BlockPointerHandle); - if (BlockPointer == NULL) - { - BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", - HostAdapter); - return false; + int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); + void *BlockPointer; + dma_addr_t BlockPointerHandle; + while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) { + BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle); + if (BlockPointer == NULL) { + BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter); + return false; + } + BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle); } - BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, - BlockPointerHandle); - } - return true; + return true; } @@ -280,25 +214,19 @@ static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *Ho static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter) { - struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL; - HostAdapter->All_CCBs = NULL; - HostAdapter->Free_CCBs = NULL; - while ((CCB = NextCCB) != NULL) - { - NextCCB = CCB->NextAll; - if (CCB->AllocationGroupHead) - { - if (Last_CCB) - pci_free_consistent(HostAdapter->PCI_Device, - Last_CCB->AllocationGroupSize, Last_CCB, - Last_CCB->AllocationGroupHead); - Last_CCB = CCB; + struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL; + HostAdapter->All_CCBs = NULL; + HostAdapter->Free_CCBs = NULL; + while ((CCB = NextCCB) != NULL) { + NextCCB = CCB->NextAll; + if (CCB->AllocationGroupHead) { + if (Last_CCB) + pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead); + Last_CCB = CCB; + } } - } - if (Last_CCB) - pci_free_consistent(HostAdapter->PCI_Device, - Last_CCB->AllocationGroupSize, Last_CCB, - Last_CCB->AllocationGroupHead); + if (Last_CCB) + pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead); } @@ -309,40 +237,30 @@ static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter) multiple host adapters share the same IRQ Channel. */ -static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, - int AdditionalCCBs, - boolean SuccessMessageP) +static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP) { - int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); - int PreviouslyAllocated = HostAdapter->AllocatedCCBs; - void *BlockPointer; - dma_addr_t BlockPointerHandle; - if (AdditionalCCBs <= 0) return; - while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) - { - BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, - &BlockPointerHandle); - if (BlockPointer == NULL) break; - BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, - BlockPointerHandle); - } - if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) - { - if (SuccessMessageP) - BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", - HostAdapter, - HostAdapter->AllocatedCCBs - PreviouslyAllocated, - HostAdapter->AllocatedCCBs); - return; - } - BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter); - if (HostAdapter->DriverQueueDepth > - HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) - { - HostAdapter->DriverQueueDepth = - HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount; - HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth; - } + int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); + int PreviouslyAllocated = HostAdapter->AllocatedCCBs; + void *BlockPointer; + dma_addr_t BlockPointerHandle; + if (AdditionalCCBs <= 0) + return; + while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) { + BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle); + if (BlockPointer == NULL) + break; + BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle); + } + if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) { + if (SuccessMessageP) + BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs); + return; + } + BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter); + if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) { + HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount; + HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth; + } } /* @@ -352,31 +270,27 @@ static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapt */ static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter - *HostAdapter) + *HostAdapter) { - static unsigned long SerialNumber = 0; - struct BusLogic_CCB *CCB; - CCB = HostAdapter->Free_CCBs; - if (CCB != NULL) - { - CCB->SerialNumber = ++SerialNumber; - HostAdapter->Free_CCBs = CCB->Next; - CCB->Next = NULL; - if (HostAdapter->Free_CCBs == NULL) - BusLogic_CreateAdditionalCCBs(HostAdapter, - HostAdapter->IncrementalCCBs, - true); - return CCB; - } - BusLogic_CreateAdditionalCCBs(HostAdapter, - HostAdapter->IncrementalCCBs, - true); - CCB = HostAdapter->Free_CCBs; - if (CCB == NULL) return NULL; - CCB->SerialNumber = ++SerialNumber; - HostAdapter->Free_CCBs = CCB->Next; - CCB->Next = NULL; - return CCB; + static unsigned long SerialNumber = 0; + struct BusLogic_CCB *CCB; + CCB = HostAdapter->Free_CCBs; + if (CCB != NULL) { + CCB->SerialNumber = ++SerialNumber; + HostAdapter->Free_CCBs = CCB->Next; + CCB->Next = NULL; + if (HostAdapter->Free_CCBs == NULL) + BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true); + return CCB; + } + BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true); + CCB = HostAdapter->Free_CCBs; + if (CCB == NULL) + return NULL; + CCB->SerialNumber = ++SerialNumber; + HostAdapter->Free_CCBs = CCB->Next; + CCB->Next = NULL; + return CCB; } @@ -388,26 +302,24 @@ static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB) { - struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter; - if (CCB->Command->use_sg != 0) - { - pci_unmap_sg(HostAdapter->PCI_Device, - (struct scatterlist *)CCB->Command->request_buffer, - CCB->Command->use_sg, - scsi_to_pci_dma_dir(CCB->Command->sc_data_direction)); - } - else if (CCB->Command->request_bufflen != 0) - { - pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, - CCB->DataLength, - scsi_to_pci_dma_dir(CCB->Command->sc_data_direction)); - } - pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, - CCB->SenseDataLength, PCI_DMA_FROMDEVICE); - CCB->Command = NULL; - CCB->Status = BusLogic_CCB_Free; - CCB->Next = HostAdapter->Free_CCBs; - HostAdapter->Free_CCBs = CCB; + struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter; + struct scsi_cmnd *cmd = CCB->Command; + + if (cmd->use_sg != 0) { + pci_unmap_sg(HostAdapter->PCI_Device, + (struct scatterlist *)cmd->request_buffer, + cmd->use_sg, cmd->sc_data_direction); + } else if (cmd->request_bufflen != 0) { + pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, + CCB->DataLength, cmd->sc_data_direction); + } + pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, + CCB->SenseDataLength, PCI_DMA_FROMDEVICE); + + CCB->Command = NULL; + CCB->Status = BusLogic_CCB_Free; + CCB->Next = HostAdapter->Free_CCBs; + HostAdapter->Free_CCBs = CCB; } @@ -429,228 +341,205 @@ static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB) waiting for the Host Adapter Ready bit to be set in the Status Register. */ -static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, - enum BusLogic_OperationCode OperationCode, - void *ParameterData, - int ParameterLength, - void *ReplyData, - int ReplyLength) +static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength) { - unsigned char *ParameterPointer = (unsigned char *) ParameterData; - unsigned char *ReplyPointer = (unsigned char *) ReplyData; - union BusLogic_StatusRegister StatusRegister; - union BusLogic_InterruptRegister InterruptRegister; - unsigned long ProcessorFlags = 0; - int ReplyBytes = 0, Result; - long TimeoutCounter; - /* - Clear out the Reply Data if provided. - */ - if (ReplyLength > 0) - memset(ReplyData, 0, ReplyLength); - /* - If the IRQ Channel has not yet been acquired, then interrupts must be - disabled while issuing host adapter commands since a Command Complete - interrupt could occur if the IRQ Channel was previously enabled by another - BusLogic Host Adapter or another driver sharing the same IRQ Channel. - */ - if (!HostAdapter->IRQ_ChannelAcquired) - { - local_irq_save(ProcessorFlags); - local_irq_disable(); - } - /* - Wait for the Host Adapter Ready bit to be set and the Command/Parameter - Register Busy bit to be reset in the Status Register. - */ - TimeoutCounter = 10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.sr.HostAdapterReady && - !StatusRegister.sr.CommandParameterRegisterBusy) - break; - udelay(100); - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; - Result = -2; - goto Done; - } - /* - Write the OperationCode to the Command/Parameter Register. - */ - HostAdapter->HostAdapterCommandCompleted = false; - BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); - /* - Write any additional Parameter Bytes. - */ - TimeoutCounter = 10000; - while (ParameterLength > 0 && --TimeoutCounter >= 0) - { - /* - Wait 100 microseconds to give the Host Adapter enough time to determine - whether the last value written to the Command/Parameter Register was - valid or not. If the Command Complete bit is set in the Interrupt - Register, then the Command Invalid bit in the Status Register will be - reset if the Operation Code or Parameter was valid and the command - has completed, or set if the Operation Code or Parameter was invalid. - If the Data In Register Ready bit is set in the Status Register, then - the Operation Code was valid, and data is waiting to be read back - from the Host Adapter. Otherwise, wait for the Command/Parameter - Register Busy bit in the Status Register to be reset. - */ - udelay(100); - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.ir.CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.sr.DataInRegisterReady) break; - if (StatusRegister.sr.CommandParameterRegisterBusy) continue; - BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); - ParameterLength--; - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = - "Timeout waiting for Parameter Acceptance"; - Result = -2; - goto Done; - } - /* - The Modify I/O Address command does not cause a Command Complete Interrupt. - */ - if (OperationCode == BusLogic_ModifyIOAddress) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.sr.CommandInvalid) - { - BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; - Result = -1; - goto Done; + unsigned char *ParameterPointer = (unsigned char *) ParameterData; + unsigned char *ReplyPointer = (unsigned char *) ReplyData; + union BusLogic_StatusRegister StatusRegister; + union BusLogic_InterruptRegister InterruptRegister; + unsigned long ProcessorFlags = 0; + int ReplyBytes = 0, Result; + long TimeoutCounter; + /* + Clear out the Reply Data if provided. + */ + if (ReplyLength > 0) + memset(ReplyData, 0, ReplyLength); + /* + If the IRQ Channel has not yet been acquired, then interrupts must be + disabled while issuing host adapter commands since a Command Complete + interrupt could occur if the IRQ Channel was previously enabled by another + BusLogic Host Adapter or another driver sharing the same IRQ Channel. + */ + if (!HostAdapter->IRQ_ChannelAcquired) { + local_irq_save(ProcessorFlags); + local_irq_disable(); + } + /* + Wait for the Host Adapter Ready bit to be set and the Command/Parameter + Register Busy bit to be reset in the Status Register. + */ + TimeoutCounter = 10000; + while (--TimeoutCounter >= 0) { + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.sr.HostAdapterReady && !StatusRegister.sr.CommandParameterRegisterBusy) + break; + udelay(100); + } + if (TimeoutCounter < 0) { + BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; + Result = -2; + goto Done; + } + /* + Write the OperationCode to the Command/Parameter Register. + */ + HostAdapter->HostAdapterCommandCompleted = false; + BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode); + /* + Write any additional Parameter Bytes. + */ + TimeoutCounter = 10000; + while (ParameterLength > 0 && --TimeoutCounter >= 0) { + /* + Wait 100 microseconds to give the Host Adapter enough time to determine + whether the last value written to the Command/Parameter Register was + valid or not. If the Command Complete bit is set in the Interrupt + Register, then the Command Invalid bit in the Status Register will be + reset if the Operation Code or Parameter was valid and the command + has completed, or set if the Operation Code or Parameter was invalid. + If the Data In Register Ready bit is set in the Status Register, then + the Operation Code was valid, and data is waiting to be read back + from the Host Adapter. Otherwise, wait for the Command/Parameter + Register Busy bit in the Status Register to be reset. + */ + udelay(100); + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (InterruptRegister.ir.CommandComplete) + break; + if (HostAdapter->HostAdapterCommandCompleted) + break; + if (StatusRegister.sr.DataInRegisterReady) + break; + if (StatusRegister.sr.CommandParameterRegisterBusy) + continue; + BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); + ParameterLength--; + } + if (TimeoutCounter < 0) { + BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; + Result = -2; + goto Done; + } + /* + The Modify I/O Address command does not cause a Command Complete Interrupt. + */ + if (OperationCode == BusLogic_ModifyIOAddress) { + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.sr.CommandInvalid) { + BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; + Result = -1; + goto Done; + } + if (BusLogic_GlobalOptions.TraceConfiguration) + BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All); + Result = 0; + goto Done; + } + /* + Select an appropriate timeout value for awaiting command completion. + */ + switch (OperationCode) { + case BusLogic_InquireInstalledDevicesID0to7: + case BusLogic_InquireInstalledDevicesID8to15: + case BusLogic_InquireTargetDevices: + /* Approximately 60 seconds. */ + TimeoutCounter = 60 * 10000; + break; + default: + /* Approximately 1 second. */ + TimeoutCounter = 10000; + break; + } + /* + Receive any Reply Bytes, waiting for either the Command Complete bit to + be set in the Interrupt Register, or for the Interrupt Handler to set the + Host Adapter Command Completed bit in the Host Adapter structure. + */ + while (--TimeoutCounter >= 0) { + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (InterruptRegister.ir.CommandComplete) + break; + if (HostAdapter->HostAdapterCommandCompleted) + break; + if (StatusRegister.sr.DataInRegisterReady) { + if (++ReplyBytes <= ReplyLength) + *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); + else + BusLogic_ReadDataInRegister(HostAdapter); + } + if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.HostAdapterReady) + break; + udelay(100); } - if (BusLogic_GlobalOptions.TraceConfiguration) - BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " - "(Modify I/O Address)\n", HostAdapter, - OperationCode, StatusRegister.All); - Result = 0; - goto Done; - } - /* - Select an appropriate timeout value for awaiting command completion. - */ - switch (OperationCode) - { - case BusLogic_InquireInstalledDevicesID0to7: - case BusLogic_InquireInstalledDevicesID8to15: - case BusLogic_InquireTargetDevices: - /* Approximately 60 seconds. */ - TimeoutCounter = 60*10000; - break; - default: - /* Approximately 1 second. */ - TimeoutCounter = 10000; - break; - } - /* - Receive any Reply Bytes, waiting for either the Command Complete bit to - be set in the Interrupt Register, or for the Interrupt Handler to set the - Host Adapter Command Completed bit in the Host Adapter structure. - */ - while (--TimeoutCounter >= 0) - { - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.ir.CommandComplete) break; - if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.sr.DataInRegisterReady) - { - if (++ReplyBytes <= ReplyLength) - *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); - else BusLogic_ReadDataInRegister(HostAdapter); + if (TimeoutCounter < 0) { + BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; + Result = -2; + goto Done; } - if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && - StatusRegister.sr.HostAdapterReady) break; - udelay(100); - } - if (TimeoutCounter < 0) - { - BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; - Result = -2; - goto Done; - } - /* - Clear any pending Command Complete Interrupt. - */ - BusLogic_InterruptReset(HostAdapter); - /* - Provide tracing information if requested. - */ - if (BusLogic_GlobalOptions.TraceConfiguration) - { - int i; - BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", - HostAdapter, OperationCode, - StatusRegister.All, ReplyLength, ReplyBytes); - if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes; - for (i = 0; i < ReplyLength; i++) - BusLogic_Notice(" %02X", HostAdapter, - ((unsigned char *) ReplyData)[i]); - BusLogic_Notice("\n", HostAdapter); - } - /* - Process Command Invalid conditions. - */ - if (StatusRegister.sr.CommandInvalid) - { - /* - Some early BusLogic Host Adapters may not recover properly from - a Command Invalid condition, so if this appears to be the case, - a Soft Reset is issued to the Host Adapter. Potentially invalid - commands are never attempted after Mailbox Initialization is - performed, so there should be no Host Adapter state lost by a - Soft Reset in response to a Command Invalid condition. - */ - udelay(1000); - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.sr.CommandInvalid || - StatusRegister.sr.Reserved || - StatusRegister.sr.DataInRegisterReady || - StatusRegister.sr.CommandParameterRegisterBusy || - !StatusRegister.sr.HostAdapterReady || - !StatusRegister.sr.InitializationRequired || - StatusRegister.sr.DiagnosticActive || - StatusRegister.sr.DiagnosticFailure) - { - BusLogic_SoftReset(HostAdapter); - udelay(1000); + /* + Clear any pending Command Complete Interrupt. + */ + BusLogic_InterruptReset(HostAdapter); + /* + Provide tracing information if requested. + */ + if (BusLogic_GlobalOptions.TraceConfiguration) { + int i; + BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes); + if (ReplyLength > ReplyBytes) + ReplyLength = ReplyBytes; + for (i = 0; i < ReplyLength; i++) + BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]); + BusLogic_Notice("\n", HostAdapter); } - BusLogic_CommandFailureReason = "Command Invalid"; - Result = -1; - goto Done; - } - /* - Handle Excess Parameters Supplied conditions. - */ - if (ParameterLength > 0) - { - BusLogic_CommandFailureReason = "Excess Parameters Supplied"; - Result = -1; - goto Done; - } - /* - Indicate the command completed successfully. - */ - BusLogic_CommandFailureReason = NULL; - Result = ReplyBytes; - /* - Restore the interrupt status if necessary and return. - */ -Done: - if (!HostAdapter->IRQ_ChannelAcquired) - local_irq_restore(ProcessorFlags); - return Result; + /* + Process Command Invalid conditions. + */ + if (StatusRegister.sr.CommandInvalid) { + /* + Some early BusLogic Host Adapters may not recover properly from + a Command Invalid condition, so if this appears to be the case, + a Soft Reset is issued to the Host Adapter. Potentially invalid + commands are never attempted after Mailbox Initialization is + performed, so there should be no Host Adapter state lost by a + Soft Reset in response to a Command Invalid condition. + */ + udelay(1000); + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.sr.CommandInvalid || + StatusRegister.sr.Reserved || + StatusRegister.sr.DataInRegisterReady || + StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.DiagnosticFailure) { + BusLogic_SoftReset(HostAdapter); + udelay(1000); + } + BusLogic_CommandFailureReason = "Command Invalid"; + Result = -1; + goto Done; + } + /* + Handle Excess Parameters Supplied conditions. + */ + if (ParameterLength > 0) { + BusLogic_CommandFailureReason = "Excess Parameters Supplied"; + Result = -1; + goto Done; + } + /* + Indicate the command completed successfully. + */ + BusLogic_CommandFailureReason = NULL; + Result = ReplyBytes; + /* + Restore the interrupt status if necessary and return. + */ + Done: + if (!HostAdapter->IRQ_ChannelAcquired) + local_irq_restore(ProcessorFlags); + return Result; } @@ -662,13 +551,14 @@ Done: static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address) { - struct BusLogic_ProbeInfo *ProbeInfo; - if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return; - ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_MultiMaster; - ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; - ProbeInfo->IO_Address = IO_Address; - ProbeInfo->PCI_Device = NULL; + struct BusLogic_ProbeInfo *ProbeInfo; + if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) + return; + ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; + ProbeInfo->IO_Address = IO_Address; + ProbeInfo->PCI_Device = NULL; } @@ -681,38 +571,27 @@ static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address) static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter *PrototypeHostAdapter) { - /* - If BusLogic Driver Options specifications requested that ISA Bus Probes - be inhibited, do not proceed further. - */ - if (BusLogic_ProbeOptions.NoProbeISA) return; - /* - Append the list of standard BusLogic MultiMaster ISA I/O Addresses. - */ - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe330 - : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x330); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe334 - : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x334); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe230 - : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x230); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe234 - : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x234); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe130 - : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x130); - if (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe134 - : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) - BusLogic_AppendProbeAddressISA(0x134); + /* + If BusLogic Driver Options specifications requested that ISA Bus Probes + be inhibited, do not proceed further. + */ + if (BusLogic_ProbeOptions.NoProbeISA) + return; + /* + Append the list of standard BusLogic MultiMaster ISA I/O Addresses. + */ + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x330); + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x334); + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x230); + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x234); + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x130); + if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0) + BusLogic_AppendProbeAddressISA(0x134); } @@ -724,30 +603,24 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt of increasing PCI Bus and Device Number. */ -static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, - int ProbeInfoCount) +static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount) { - int LastInterchange = ProbeInfoCount-1, Bound, j; - while (LastInterchange > 0) - { - Bound = LastInterchange; - LastInterchange = 0; - for (j = 0; j < Bound; j++) - { - struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j]; - struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j+1]; - if (ProbeInfo1->Bus > ProbeInfo2->Bus || - (ProbeInfo1->Bus == ProbeInfo2->Bus && - (ProbeInfo1->Device > ProbeInfo2->Device))) - { - struct BusLogic_ProbeInfo TempProbeInfo; - memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo)); - memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo)); - memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo)); - LastInterchange = j; - } + int LastInterchange = ProbeInfoCount - 1, Bound, j; + while (LastInterchange > 0) { + Bound = LastInterchange; + LastInterchange = 0; + for (j = 0; j < Bound; j++) { + struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j]; + struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1]; + if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) { + struct BusLogic_ProbeInfo TempProbeInfo; + memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo)); + memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo)); + memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo)); + LastInterchange = j; + } + } } - } } @@ -762,292 +635,226 @@ static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoLi static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter *PrototypeHostAdapter) { - struct BusLogic_ProbeInfo *PrimaryProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; - int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; - int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; - boolean ForceBusDeviceScanningOrder = false; - boolean ForceBusDeviceScanningOrderChecked = false; - boolean StandardAddressSeen[6]; - struct pci_dev *PCI_Device = NULL; - int i; - if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0; - BusLogic_ProbeInfoCount++; - for (i = 0; i < 6; i++) - StandardAddressSeen[i] = false; - /* - Iterate over the MultiMaster PCI Host Adapters. For each enumerated host - adapter, determine whether its ISA Compatible I/O Port is enabled and if - so, whether it is assigned the Primary I/O Address. A host adapter that is - assigned the Primary I/O Address will always be the preferred boot device. - The MultiMaster BIOS will first recognize a host adapter at the Primary I/O - Address, then any other PCI host adapters, and finally any host adapters - located at the remaining standard ISA I/O Addresses. When a PCI host - adapter is found with its ISA Compatible I/O Port enabled, a command is - issued to disable the ISA Compatible I/O Port, and it is noted that the - particular standard ISA I/O Address need not be probed. - */ - PrimaryProbeInfo->IO_Address = 0; - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, - PCI_Device)) != NULL) - { - struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; - struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation; - enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest; - unsigned char Bus; - unsigned char Device; - unsigned int IRQ_Channel; - unsigned long BaseAddress0; - unsigned long BaseAddress1; - unsigned long IO_Address; - unsigned long PCI_Address; - - if (pci_enable_device(PCI_Device)) - continue; - - if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff)) - continue; - - Bus = PCI_Device->bus->number; - Device = PCI_Device->devfn >> 3; - IRQ_Channel = PCI_Device->irq; - IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0); - PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1); - - if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) - { - BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " - "MultiMaster Host Adapter\n", NULL, BaseAddress0); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO) - { - BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " - "MultiMaster Host Adapter\n", NULL, BaseAddress1); - BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", - NULL, Bus, Device, PCI_Address); - continue; - } - if (IRQ_Channel == 0) - { - BusLogic_Error("BusLogic: IRQ Channel %d invalid for " - "MultiMaster Host Adapter\n", NULL, IRQ_Channel); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (BusLogic_GlobalOptions.TraceProbe) - { - BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " - "detected at\n", NULL); - BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " - "0x%X PCI Address 0x%X\n", NULL, - Bus, Device, IO_Address, PCI_Address); - } - /* - Issue the Inquire PCI Host Adapter Information command to determine - the ISA Compatible I/O Port. If the ISA Compatible I/O Port is - known and enabled, note that the particular Standard ISA I/O - Address should not be probed. - */ - HostAdapter->IO_Address = IO_Address; - BusLogic_InterruptReset(HostAdapter); - if (BusLogic_Command(HostAdapter, - BusLogic_InquirePCIHostAdapterInformation, - NULL, 0, &PCIHostAdapterInformation, - sizeof(PCIHostAdapterInformation)) - == sizeof(PCIHostAdapterInformation)) - { - if (PCIHostAdapterInformation.ISACompatibleIOPort < 6) - StandardAddressSeen[PCIHostAdapterInformation - .ISACompatibleIOPort] = true; - } - else PCIHostAdapterInformation.ISACompatibleIOPort = - BusLogic_IO_Disable; - /* - * Issue the Modify I/O Address command to disable the ISA Compatible - * I/O Port. On PCI Host Adapters, the Modify I/O Address command - * allows modification of the ISA compatible I/O Address that the Host - * Adapter responds to; it does not affect the PCI compliant I/O Address - * assigned at system initialization. - */ - ModifyIOAddressRequest = BusLogic_IO_Disable; - BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, - &ModifyIOAddressRequest, - sizeof(ModifyIOAddressRequest), NULL, 0); - /* - For the first MultiMaster Host Adapter enumerated, issue the Fetch - Host Adapter Local RAM command to read byte 45 of the AutoSCSI area, - for the setting of the "Use Bus And Device # For PCI Scanning Seq." - option. Issue the Inquire Board ID command since this option is - only valid for the BT-948/958/958D. - */ - if (!ForceBusDeviceScanningOrderChecked) - { - struct BusLogic_FetchHostAdapterLocalRAMRequest - FetchHostAdapterLocalRAMRequest; - struct BusLogic_AutoSCSIByte45 AutoSCSIByte45; - struct BusLogic_BoardID BoardID; - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset + 45; - FetchHostAdapterLocalRAMRequest.ByteCount = - sizeof(AutoSCSIByte45); - BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIByte45, sizeof(AutoSCSIByte45)); - BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, - NULL, 0, &BoardID, sizeof(BoardID)); - if (BoardID.FirmwareVersion1stDigit == '5') - ForceBusDeviceScanningOrder = - AutoSCSIByte45.ForceBusDeviceScanningOrder; - ForceBusDeviceScanningOrderChecked = true; - } - /* - Determine whether this MultiMaster Host Adapter has its ISA - Compatible I/O Port enabled and is assigned the Primary I/O Address. - If it does, then it is the Primary MultiMaster Host Adapter and must - be recognized first. If it does not, then it is added to the list - for probing after any Primary MultiMaster Host Adapter is probed. - */ - if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) - { - PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; - PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - PrimaryProbeInfo->IO_Address = IO_Address; - PrimaryProbeInfo->PCI_Address = PCI_Address; - PrimaryProbeInfo->Bus = Bus; - PrimaryProbeInfo->Device = Device; - PrimaryProbeInfo->IRQ_Channel = IRQ_Channel; - PrimaryProbeInfo->PCI_Device = PCI_Device; - PCIMultiMasterCount++; + struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; + int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; + int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; + boolean ForceBusDeviceScanningOrder = false; + boolean ForceBusDeviceScanningOrderChecked = false; + boolean StandardAddressSeen[6]; + struct pci_dev *PCI_Device = NULL; + int i; + if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) + return 0; + BusLogic_ProbeInfoCount++; + for (i = 0; i < 6; i++) + StandardAddressSeen[i] = false; + /* + Iterate over the MultiMaster PCI Host Adapters. For each enumerated host + adapter, determine whether its ISA Compatible I/O Port is enabled and if + so, whether it is assigned the Primary I/O Address. A host adapter that is + assigned the Primary I/O Address will always be the preferred boot device. + The MultiMaster BIOS will first recognize a host adapter at the Primary I/O + Address, then any other PCI host adapters, and finally any host adapters + located at the remaining standard ISA I/O Addresses. When a PCI host + adapter is found with its ISA Compatible I/O Port enabled, a command is + issued to disable the ISA Compatible I/O Port, and it is noted that the + particular standard ISA I/O Address need not be probed. + */ + PrimaryProbeInfo->IO_Address = 0; + while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_Device)) != NULL) { + struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; + struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation; + enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest; + unsigned char Bus; + unsigned char Device; + unsigned int IRQ_Channel; + unsigned long BaseAddress0; + unsigned long BaseAddress1; + unsigned long IO_Address; + unsigned long PCI_Address; + + if (pci_enable_device(PCI_Device)) + continue; + + if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + continue; + + Bus = PCI_Device->bus->number; + Device = PCI_Device->devfn >> 3; + IRQ_Channel = PCI_Device->irq; + IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0); + PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1); + + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { + BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address); + continue; + } + if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) { + BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1); + BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address); + continue; + } + if (IRQ_Channel == 0) { + BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, IRQ_Channel); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address); + continue; + } + if (BusLogic_GlobalOptions.TraceProbe) { + BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL); + BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address); + } + /* + Issue the Inquire PCI Host Adapter Information command to determine + the ISA Compatible I/O Port. If the ISA Compatible I/O Port is + known and enabled, note that the particular Standard ISA I/O + Address should not be probed. + */ + HostAdapter->IO_Address = IO_Address; + BusLogic_InterruptReset(HostAdapter); + if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation)) + == sizeof(PCIHostAdapterInformation)) { + if (PCIHostAdapterInformation.ISACompatibleIOPort < 6) + StandardAddressSeen[PCIHostAdapterInformation.ISACompatibleIOPort] = true; + } else + PCIHostAdapterInformation.ISACompatibleIOPort = BusLogic_IO_Disable; + /* + * Issue the Modify I/O Address command to disable the ISA Compatible + * I/O Port. On PCI Host Adapters, the Modify I/O Address command + * allows modification of the ISA compatible I/O Address that the Host + * Adapter responds to; it does not affect the PCI compliant I/O Address + * assigned at system initialization. + */ + ModifyIOAddressRequest = BusLogic_IO_Disable; + BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, &ModifyIOAddressRequest, sizeof(ModifyIOAddressRequest), NULL, 0); + /* + For the first MultiMaster Host Adapter enumerated, issue the Fetch + Host Adapter Local RAM command to read byte 45 of the AutoSCSI area, + for the setting of the "Use Bus And Device # For PCI Scanning Seq." + option. Issue the Inquire Board ID command since this option is + only valid for the BT-948/958/958D. + */ + if (!ForceBusDeviceScanningOrderChecked) { + struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest; + struct BusLogic_AutoSCSIByte45 AutoSCSIByte45; + struct BusLogic_BoardID BoardID; + FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset + 45; + FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45); + BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIByte45, sizeof(AutoSCSIByte45)); + BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)); + if (BoardID.FirmwareVersion1stDigit == '5') + ForceBusDeviceScanningOrder = AutoSCSIByte45.ForceBusDeviceScanningOrder; + ForceBusDeviceScanningOrderChecked = true; + } + /* + Determine whether this MultiMaster Host Adapter has its ISA + Compatible I/O Port enabled and is assigned the Primary I/O Address. + If it does, then it is the Primary MultiMaster Host Adapter and must + be recognized first. If it does not, then it is added to the list + for probing after any Primary MultiMaster Host Adapter is probed. + */ + if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) { + PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; + PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + PrimaryProbeInfo->IO_Address = IO_Address; + PrimaryProbeInfo->PCI_Address = PCI_Address; + PrimaryProbeInfo->Bus = Bus; + PrimaryProbeInfo->Device = Device; + PrimaryProbeInfo->IRQ_Channel = IRQ_Channel; + PrimaryProbeInfo->PCI_Device = PCI_Device; + PCIMultiMasterCount++; + } else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) { + struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->HostAdapterType = BusLogic_MultiMaster; + ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + ProbeInfo->IO_Address = IO_Address; + ProbeInfo->PCI_Address = PCI_Address; + ProbeInfo->Bus = Bus; + ProbeInfo->Device = Device; + ProbeInfo->IRQ_Channel = IRQ_Channel; + ProbeInfo->PCI_Device = PCI_Device; + NonPrimaryPCIMultiMasterCount++; + PCIMultiMasterCount++; + } else + BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL); } - else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) - { - struct BusLogic_ProbeInfo *ProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_MultiMaster; - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->IO_Address = IO_Address; - ProbeInfo->PCI_Address = PCI_Address; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - ProbeInfo->PCI_Device = PCI_Device; - NonPrimaryPCIMultiMasterCount++; - PCIMultiMasterCount++; + /* + If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON + for the first enumerated MultiMaster Host Adapter, and if that host adapter + is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster + Host Adapters in the order of increasing PCI Bus and Device Number. In + that case, sort the probe information into the same order the BIOS uses. + If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster + Host Adapters in the order they are enumerated by the PCI BIOS, and hence + no sorting is necessary. + */ + if (ForceBusDeviceScanningOrder) + BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[NonPrimaryPCIMultiMasterIndex], NonPrimaryPCIMultiMasterCount); + /* + If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address, + then the Primary I/O Address must be probed explicitly before any PCI + host adapters are probed. + */ + if (!BusLogic_ProbeOptions.NoProbeISA) + if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) { + PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; + PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; + PrimaryProbeInfo->IO_Address = 0x330; + } + /* + Append the list of standard BusLogic MultiMaster ISA I/O Addresses, + omitting the Primary I/O Address which has already been handled. + */ + if (!BusLogic_ProbeOptions.NoProbeISA) { + if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)) + BusLogic_AppendProbeAddressISA(0x334); + if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)) + BusLogic_AppendProbeAddressISA(0x230); + if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)) + BusLogic_AppendProbeAddressISA(0x234); + if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)) + BusLogic_AppendProbeAddressISA(0x130); + if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)) + BusLogic_AppendProbeAddressISA(0x134); } - else BusLogic_Warning("BusLogic: Too many Host Adapters " - "detected\n", NULL); - } - /* - If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON - for the first enumerated MultiMaster Host Adapter, and if that host adapter - is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster - Host Adapters in the order of increasing PCI Bus and Device Number. In - that case, sort the probe information into the same order the BIOS uses. - If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster - Host Adapters in the order they are enumerated by the PCI BIOS, and hence - no sorting is necessary. - */ - if (ForceBusDeviceScanningOrder) - BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[ - NonPrimaryPCIMultiMasterIndex], - NonPrimaryPCIMultiMasterCount); - /* - If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address, - then the Primary I/O Address must be probed explicitly before any PCI - host adapters are probed. - */ - if (!BusLogic_ProbeOptions.NoProbeISA) - if (PrimaryProbeInfo->IO_Address == 0 && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe330 - : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) - { - PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster; - PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus; - PrimaryProbeInfo->IO_Address = 0x330; - } - /* - Append the list of standard BusLogic MultiMaster ISA I/O Addresses, - omitting the Primary I/O Address which has already been handled. - */ - if (!BusLogic_ProbeOptions.NoProbeISA) - { - if (!StandardAddressSeen[1] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe334 - : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x334); - if (!StandardAddressSeen[2] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe230 - : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x230); - if (!StandardAddressSeen[3] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe234 - : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x234); - if (!StandardAddressSeen[4] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe130 - : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x130); - if (!StandardAddressSeen[5] && - (BusLogic_ProbeOptions.LimitedProbeISA - ? BusLogic_ProbeOptions.Probe134 - : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)) - BusLogic_AppendProbeAddressISA(0x134); - } - /* - Iterate over the older non-compliant MultiMaster PCI Host Adapters, - noting the PCI bus location and assigned IRQ Channel. - */ - PCI_Device = NULL; - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, - PCI_Device)) != NULL) - { - unsigned char Bus; - unsigned char Device; - unsigned int IRQ_Channel; - unsigned long IO_Address; - - if (pci_enable_device(PCI_Device)) - continue; - - if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff)) - continue; - - Bus = PCI_Device->bus->number; - Device = PCI_Device->devfn >> 3; - IRQ_Channel = PCI_Device->irq; - IO_Address = pci_resource_start(PCI_Device, 0); - - if (IO_Address == 0 || IRQ_Channel == 0) continue; - for (i = 0; i < BusLogic_ProbeInfoCount; i++) - { - struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i]; - if (ProbeInfo->IO_Address == IO_Address && - ProbeInfo->HostAdapterType == BusLogic_MultiMaster) - { - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->PCI_Address = 0; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - ProbeInfo->PCI_Device = PCI_Device; - break; - } + /* + Iterate over the older non-compliant MultiMaster PCI Host Adapters, + noting the PCI bus location and assigned IRQ Channel. + */ + PCI_Device = NULL; + while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, PCI_Device)) != NULL) { + unsigned char Bus; + unsigned char Device; + unsigned int IRQ_Channel; + unsigned long IO_Address; + + if (pci_enable_device(PCI_Device)) + continue; + + if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + continue; + + Bus = PCI_Device->bus->number; + Device = PCI_Device->devfn >> 3; + IRQ_Channel = PCI_Device->irq; + IO_Address = pci_resource_start(PCI_Device, 0); + + if (IO_Address == 0 || IRQ_Channel == 0) + continue; + for (i = 0; i < BusLogic_ProbeInfoCount; i++) { + struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i]; + if (ProbeInfo->IO_Address == IO_Address && ProbeInfo->HostAdapterType == BusLogic_MultiMaster) { + ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + ProbeInfo->PCI_Address = 0; + ProbeInfo->Bus = Bus; + ProbeInfo->Device = Device; + ProbeInfo->IRQ_Channel = IRQ_Channel; + ProbeInfo->PCI_Device = PCI_Device; + break; + } + } } - } - return PCIMultiMasterCount; + return PCIMultiMasterCount; } @@ -1061,100 +868,77 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAdapter *PrototypeHostAdapter) { - int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0; - struct pci_dev *PCI_Device = NULL; - /* - Interrogate PCI Configuration Space for any FlashPoint Host Adapters. - */ - while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, - PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, - PCI_Device)) != NULL) - { - unsigned char Bus; - unsigned char Device; - unsigned int IRQ_Channel; - unsigned long BaseAddress0; - unsigned long BaseAddress1; - unsigned long IO_Address; - unsigned long PCI_Address; - - if (pci_enable_device(PCI_Device)) - continue; - - if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff)) - continue; - - Bus = PCI_Device->bus->number; - Device = PCI_Device->devfn >> 3; - IRQ_Channel = PCI_Device->irq; - IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0); - PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1); + int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0; + struct pci_dev *PCI_Device = NULL; + /* + Interrogate PCI Configuration Space for any FlashPoint Host Adapters. + */ + while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, PCI_Device)) != NULL) { + unsigned char Bus; + unsigned char Device; + unsigned int IRQ_Channel; + unsigned long BaseAddress0; + unsigned long BaseAddress1; + unsigned long IO_Address; + unsigned long PCI_Address; + + if (pci_enable_device(PCI_Device)) + continue; + + if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) + continue; + + Bus = PCI_Device->bus->number; + Device = PCI_Device->devfn >> 3; + IRQ_Channel = PCI_Device->irq; + IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0); + PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1); #ifndef CONFIG_SCSI_OMIT_FLASHPOINT - if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) - { - BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " - "FlashPoint Host Adapter\n", NULL, BaseAddress0); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) - { - BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " - "FlashPoint Host Adapter\n", NULL, BaseAddress1); - BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", - NULL, Bus, Device, PCI_Address); - continue; - } - if (IRQ_Channel == 0) - { - BusLogic_Error("BusLogic: IRQ Channel %d invalid for " - "FlashPoint Host Adapter\n", NULL, IRQ_Channel); - BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", - NULL, Bus, Device, IO_Address); - continue; - } - if (BusLogic_GlobalOptions.TraceProbe) - { - BusLogic_Notice("BusLogic: FlashPoint Host Adapter " - "detected at\n", NULL); - BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " - "0x%X PCI Address 0x%X\n", NULL, - Bus, Device, IO_Address, PCI_Address); - } - if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) - { - struct BusLogic_ProbeInfo *ProbeInfo = - &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; - ProbeInfo->HostAdapterType = BusLogic_FlashPoint; - ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; - ProbeInfo->IO_Address = IO_Address; - ProbeInfo->PCI_Address = PCI_Address; - ProbeInfo->Bus = Bus; - ProbeInfo->Device = Device; - ProbeInfo->IRQ_Channel = IRQ_Channel; - ProbeInfo->PCI_Device = PCI_Device; - FlashPointCount++; - } - else BusLogic_Warning("BusLogic: Too many Host Adapters " - "detected\n", NULL); + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { + BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address); + continue; + } + if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) { + BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1); + BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address); + continue; + } + if (IRQ_Channel == 0) { + BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, IRQ_Channel); + BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address); + continue; + } + if (BusLogic_GlobalOptions.TraceProbe) { + BusLogic_Notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL); + BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address); + } + if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) { + struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++]; + ProbeInfo->HostAdapterType = BusLogic_FlashPoint; + ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus; + ProbeInfo->IO_Address = IO_Address; + ProbeInfo->PCI_Address = PCI_Address; + ProbeInfo->Bus = Bus; + ProbeInfo->Device = Device; + ProbeInfo->IRQ_Channel = IRQ_Channel; + ProbeInfo->PCI_Device = PCI_Device; + FlashPointCount++; + } else + BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL); #else - BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " - "PCI Bus %d Device %d\n", NULL, Bus, Device); - BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " - "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel); - BusLogic_Error("BusLogic: support was omitted in this kernel " - "configuration.\n", NULL); + BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device); + BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel); + BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL); #endif - } - /* - The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of - increasing PCI Bus and Device Number, so sort the probe information into - the same order the BIOS uses. - */ - BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], - FlashPointCount); - return FlashPointCount; + } + /* + The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of + increasing PCI Bus and Device Number, so sort the probe information into + the same order the BIOS uses. + */ + BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], FlashPointCount); + return FlashPointCount; } @@ -1174,106 +958,70 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter *PrototypeHostAdapter) { - /* - If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint - Host Adapters; otherwise, default to the standard ISA MultiMaster probe. - */ - if (!BusLogic_ProbeOptions.NoProbePCI) - { - if (BusLogic_ProbeOptions.MultiMasterFirst) - { - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - } - else if (BusLogic_ProbeOptions.FlashPointFirst) - { - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - } - else - { - int FlashPointCount = - BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); - int PCIMultiMasterCount = - BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); - if (FlashPointCount > 0 && PCIMultiMasterCount > 0) - { - struct BusLogic_ProbeInfo *ProbeInfo = - &BusLogic_ProbeInfoList[FlashPointCount]; - struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; - struct BusLogic_FetchHostAdapterLocalRAMRequest - FetchHostAdapterLocalRAMRequest; - struct BusLogic_BIOSDriveMapByte Drive0MapByte; - while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus) - ProbeInfo++; - HostAdapter->IO_Address = ProbeInfo->IO_Address; - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0; - FetchHostAdapterLocalRAMRequest.ByteCount = - sizeof(Drive0MapByte); - BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &Drive0MapByte, sizeof(Drive0MapByte)); - /* - If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0 - is controlled by this PCI MultiMaster Host Adapter, then - reverse the probe order so that MultiMaster Host Adapters are - probed before FlashPoint Host Adapters. - */ - if (Drive0MapByte.DiskGeometry != - BusLogic_BIOS_Disk_Not_Installed) - { - struct BusLogic_ProbeInfo - SavedProbeInfo[BusLogic_MaxHostAdapters]; - int MultiMasterCount = - BusLogic_ProbeInfoCount - FlashPointCount; - memcpy(SavedProbeInfo, - BusLogic_ProbeInfoList, - BusLogic_ProbeInfoCount - * sizeof(struct BusLogic_ProbeInfo)); - memcpy(&BusLogic_ProbeInfoList[0], - &SavedProbeInfo[FlashPointCount], - MultiMasterCount * sizeof(struct BusLogic_ProbeInfo)); - memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], - &SavedProbeInfo[0], - FlashPointCount * sizeof(struct BusLogic_ProbeInfo)); + /* + If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint + Host Adapters; otherwise, default to the standard ISA MultiMaster probe. + */ + if (!BusLogic_ProbeOptions.NoProbePCI) { + if (BusLogic_ProbeOptions.MultiMasterFirst) { + BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); + BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); + } else if (BusLogic_ProbeOptions.FlashPointFirst) { + BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); + BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); + } else { + int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter); + int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter); + if (FlashPointCount > 0 && PCIMultiMasterCount > 0) { + struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[FlashPointCount]; + struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; + struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest; + struct BusLogic_BIOSDriveMapByte Drive0MapByte; + while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus) + ProbeInfo++; + HostAdapter->IO_Address = ProbeInfo->IO_Address; + FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0; + FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(Drive0MapByte); + BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &Drive0MapByte, sizeof(Drive0MapByte)); + /* + If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0 + is controlled by this PCI MultiMaster Host Adapter, then + reverse the probe order so that MultiMaster Host Adapters are + probed before FlashPoint Host Adapters. + */ + if (Drive0MapByte.DiskGeometry != BusLogic_BIOS_Disk_Not_Installed) { + struct BusLogic_ProbeInfo SavedProbeInfo[BusLogic_MaxHostAdapters]; + int MultiMasterCount = BusLogic_ProbeInfoCount - FlashPointCount; + memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, BusLogic_ProbeInfoCount * sizeof(struct BusLogic_ProbeInfo)); + memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(struct BusLogic_ProbeInfo)); + memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], &SavedProbeInfo[0], FlashPointCount * sizeof(struct BusLogic_ProbeInfo)); + } + } } - } - } - } - else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter); + } else + BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter); } -#endif /* CONFIG_PCI */ +#endif /* CONFIG_PCI */ /* BusLogic_Failure prints a standardized error message, and then returns false. */ -static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, - char *ErrorMessage) +static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage) { - BusLogic_AnnounceDriver(HostAdapter); - if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) - { - BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", - HostAdapter); - BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", - HostAdapter, HostAdapter->Bus, HostAdapter->Device, - HostAdapter->IO_Address, HostAdapter->PCI_Address); - } - else BusLogic_Error("While configuring BusLogic Host Adapter at " - "I/O Address 0x%X:\n", HostAdapter, - HostAdapter->IO_Address); - BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage); - if (BusLogic_CommandFailureReason != NULL) - BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, - BusLogic_CommandFailureReason); - return false; + BusLogic_AnnounceDriver(HostAdapter); + if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) { + BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", HostAdapter); + BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device, HostAdapter->IO_Address, HostAdapter->PCI_Address); + } else + BusLogic_Error("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", HostAdapter, HostAdapter->IO_Address); + BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage); + if (BusLogic_CommandFailureReason != NULL) + BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, BusLogic_CommandFailureReason); + return false; } @@ -1283,81 +1031,64 @@ static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { - union BusLogic_StatusRegister StatusRegister; - union BusLogic_InterruptRegister InterruptRegister; - union BusLogic_GeometryRegister GeometryRegister; - /* - FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; - FlashPointInfo->BaseAddress = - (u32) HostAdapter->IO_Address; - FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel; - FlashPointInfo->Present = false; - if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && - FlashPointInfo->Present)) - { - BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " - "PCI Bus %d Device %d\n", HostAdapter, - HostAdapter->Bus, HostAdapter->Device); - BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " - "but FlashPoint\n", HostAdapter, - HostAdapter->IO_Address, HostAdapter->PCI_Address); - BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", - HostAdapter); - return false; + union BusLogic_StatusRegister StatusRegister; + union BusLogic_InterruptRegister InterruptRegister; + union BusLogic_GeometryRegister GeometryRegister; + /* + FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) { + struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; + FlashPointInfo->BaseAddress = (u32) HostAdapter->IO_Address; + FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel; + FlashPointInfo->Present = false; + if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && FlashPointInfo->Present)) { + BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device); + BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", HostAdapter, HostAdapter->IO_Address, HostAdapter->PCI_Address); + BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", HostAdapter); + return false; + } + if (BusLogic_GlobalOptions.TraceProbe) + BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", HostAdapter, HostAdapter->IO_Address); + /* + Indicate the Host Adapter Probe completed successfully. + */ + return true; } - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", - HostAdapter, HostAdapter->IO_Address); - /* - Indicate the Host Adapter Probe completed successfully. - */ - return true; - } - /* - Read the Status, Interrupt, and Geometry Registers to test if there are I/O - ports that respond, and to check the values to determine if they are from a - BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which - case there is definitely no BusLogic Host Adapter at this base I/O Address. - The test here is a subset of that used by the BusLogic Host Adapter BIOS. - */ - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " - "Geometry 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All, - InterruptRegister.All, GeometryRegister.All); - if (StatusRegister.All == 0 || - StatusRegister.sr.DiagnosticActive || - StatusRegister.sr.CommandParameterRegisterBusy || - StatusRegister.sr.Reserved || - StatusRegister.sr.CommandInvalid || - InterruptRegister.ir.Reserved != 0) - return false; - /* - Check the undocumented Geometry Register to test if there is an I/O port - that responded. Adaptec Host Adapters do not implement the Geometry - Register, so this test helps serve to avoid incorrectly recognizing an - Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C - series does respond to the Geometry Register I/O port, but it will be - rejected later when the Inquire Extended Setup Information command is - issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a - BusLogic clone that implements the same interface as earlier BusLogic - Host Adapters, including the undocumented commands, and is therefore - supported by this driver. However, the AMI FastDisk always returns 0x00 - upon reading the Geometry Register, so the extended translation option - should always be left disabled on the AMI FastDisk. - */ - if (GeometryRegister.All == 0xFF) return false; - /* - Indicate the Host Adapter Probe completed successfully. - */ - return true; + /* + Read the Status, Interrupt, and Geometry Registers to test if there are I/O + ports that respond, and to check the values to determine if they are from a + BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which + case there is definitely no BusLogic Host Adapter at this base I/O Address. + The test here is a subset of that used by the BusLogic Host Adapter BIOS. + */ + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); + if (BusLogic_GlobalOptions.TraceProbe) + BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All); + if (StatusRegister.All == 0 || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.CommandParameterRegisterBusy || StatusRegister.sr.Reserved || StatusRegister.sr.CommandInvalid || InterruptRegister.ir.Reserved != 0) + return false; + /* + Check the undocumented Geometry Register to test if there is an I/O port + that responded. Adaptec Host Adapters do not implement the Geometry + Register, so this test helps serve to avoid incorrectly recognizing an + Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C + series does respond to the Geometry Register I/O port, but it will be + rejected later when the Inquire Extended Setup Information command is + issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a + BusLogic clone that implements the same interface as earlier BusLogic + Host Adapters, including the undocumented commands, and is therefore + supported by this driver. However, the AMI FastDisk always returns 0x00 + upon reading the Geometry Register, so the extended translation option + should always be left disabled on the AMI FastDisk. + */ + if (GeometryRegister.All == 0xFF) + return false; + /* + Indicate the Host Adapter Probe completed successfully. + */ + return true; } @@ -1370,113 +1101,101 @@ static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *Hos */ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter - *HostAdapter, - boolean HardReset) + *HostAdapter, boolean HardReset) { - union BusLogic_StatusRegister StatusRegister; - int TimeoutCounter; - /* - FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; - FlashPointInfo->HostSoftReset = !HardReset; - FlashPointInfo->ReportDataUnderrun = true; - HostAdapter->CardHandle = - FlashPoint_HardwareResetHostAdapter(FlashPointInfo); - if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false; - /* - Indicate the Host Adapter Hard Reset completed successfully. - */ - return true; - } - /* - Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host - Adapter should respond by setting Diagnostic Active in the Status Register. - */ - if (HardReset) - BusLogic_HardReset(HostAdapter); - else BusLogic_SoftReset(HostAdapter); - /* - Wait until Diagnostic Active is set in the Status Register. - */ - TimeoutCounter = 5*10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.sr.DiagnosticActive) break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - Wait 100 microseconds to allow completion of any initial diagnostic - activity which might leave the contents of the Status Register - unpredictable. - */ - udelay(100); - /* - Wait until Diagnostic Active is reset in the Status Register. - */ - TimeoutCounter = 10*10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (!StatusRegister.sr.DiagnosticActive) break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - Wait until at least one of the Diagnostic Failure, Host Adapter Ready, - or Data In Register Ready bits is set in the Status Register. - */ - TimeoutCounter = 10000; - while (--TimeoutCounter >= 0) - { - StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.sr.DiagnosticFailure || - StatusRegister.sr.HostAdapterReady || - StatusRegister.sr.DataInRegisterReady) - break; - udelay(100); - } - if (BusLogic_GlobalOptions.TraceHardwareReset) - BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " - "Status 0x%02X\n", HostAdapter, - HostAdapter->IO_Address, StatusRegister.All); - if (TimeoutCounter < 0) return false; - /* - If Diagnostic Failure is set or Host Adapter Ready is reset, then an - error occurred during the Host Adapter diagnostics. If Data In Register - Ready is set, then there is an Error Code available. - */ - if (StatusRegister.sr.DiagnosticFailure || - !StatusRegister.sr.HostAdapterReady) - { - BusLogic_CommandFailureReason = NULL; - BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); - BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", - HostAdapter, StatusRegister.All); - if (StatusRegister.sr.DataInRegisterReady) - { - unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); - BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", - HostAdapter, ErrorCode); + union BusLogic_StatusRegister StatusRegister; + int TimeoutCounter; + /* + FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) { + struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; + FlashPointInfo->HostSoftReset = !HardReset; + FlashPointInfo->ReportDataUnderrun = true; + HostAdapter->CardHandle = FlashPoint_HardwareResetHostAdapter(FlashPointInfo); + if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) + return false; + /* + Indicate the Host Adapter Hard Reset completed successfully. + */ + return true; + } + /* + Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host + Adapter should respond by setting Diagnostic Active in the Status Register. + */ + if (HardReset) + BusLogic_HardReset(HostAdapter); + else + BusLogic_SoftReset(HostAdapter); + /* + Wait until Diagnostic Active is set in the Status Register. + */ + TimeoutCounter = 5 * 10000; + while (--TimeoutCounter >= 0) { + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.sr.DiagnosticActive) + break; + udelay(100); + } + if (BusLogic_GlobalOptions.TraceHardwareReset) + BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All); + if (TimeoutCounter < 0) + return false; + /* + Wait 100 microseconds to allow completion of any initial diagnostic + activity which might leave the contents of the Status Register + unpredictable. + */ + udelay(100); + /* + Wait until Diagnostic Active is reset in the Status Register. + */ + TimeoutCounter = 10 * 10000; + while (--TimeoutCounter >= 0) { + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (!StatusRegister.sr.DiagnosticActive) + break; + udelay(100); } - return false; - } - /* - Indicate the Host Adapter Hard Reset completed successfully. - */ - return true; + if (BusLogic_GlobalOptions.TraceHardwareReset) + BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All); + if (TimeoutCounter < 0) + return false; + /* + Wait until at least one of the Diagnostic Failure, Host Adapter Ready, + or Data In Register Ready bits is set in the Status Register. + */ + TimeoutCounter = 10000; + while (--TimeoutCounter >= 0) { + StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); + if (StatusRegister.sr.DiagnosticFailure || StatusRegister.sr.HostAdapterReady || StatusRegister.sr.DataInRegisterReady) + break; + udelay(100); + } + if (BusLogic_GlobalOptions.TraceHardwareReset) + BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All); + if (TimeoutCounter < 0) + return false; + /* + If Diagnostic Failure is set or Host Adapter Ready is reset, then an + error occurred during the Host Adapter diagnostics. If Data In Register + Ready is set, then there is an Error Code available. + */ + if (StatusRegister.sr.DiagnosticFailure || !StatusRegister.sr.HostAdapterReady) { + BusLogic_CommandFailureReason = NULL; + BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); + BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All); + if (StatusRegister.sr.DataInRegisterReady) { + unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); + BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", HostAdapter, ErrorCode); + } + return false; + } + /* + Indicate the Host Adapter Hard Reset completed successfully. + */ + return true; } @@ -1487,35 +1206,30 @@ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { - struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; - unsigned char RequestedReplyLength; - boolean Result = true; - /* - FlashPoint Host Adapters do not require this protection. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; - /* - Issue the Inquire Extended Setup Information command. Only genuine - BusLogic Host Adapters and true clones support this command. Adaptec 1542C - series Host Adapters that respond to the Geometry Register I/O port will - fail this command. - */ - RequestedReplyLength = sizeof(ExtendedSetupInformation); - if (BusLogic_Command(HostAdapter, - BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, - sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)) - != sizeof(ExtendedSetupInformation)) - Result = false; - /* - Provide tracing information if requested and return. - */ - if (BusLogic_GlobalOptions.TraceProbe) - BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, - HostAdapter->IO_Address, (Result ? "Found" : "Not Found")); - return Result; + struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; + unsigned char RequestedReplyLength; + boolean Result = true; + /* + FlashPoint Host Adapters do not require this protection. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + return true; + /* + Issue the Inquire Extended Setup Information command. Only genuine + BusLogic Host Adapters and true clones support this command. Adaptec 1542C + series Host Adapters that respond to the Geometry Register I/O port will + fail this command. + */ + RequestedReplyLength = sizeof(ExtendedSetupInformation); + if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation)) + != sizeof(ExtendedSetupInformation)) + Result = false; + /* + Provide tracing information if requested and return. + */ + if (BusLogic_GlobalOptions.TraceProbe) + BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, HostAdapter->IO_Address, (Result ? "Found" : "Not Found")); + return Result; } @@ -1527,513 +1241,442 @@ static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *Hos static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { - struct BusLogic_BoardID BoardID; - struct BusLogic_Configuration Configuration; - struct BusLogic_SetupInformation SetupInformation; - struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; - unsigned char HostAdapterModelNumber[5]; - unsigned char FirmwareVersion3rdDigit; - unsigned char FirmwareVersionLetter; - struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation; - struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest; - struct BusLogic_AutoSCSIData AutoSCSIData; - union BusLogic_GeometryRegister GeometryRegister; - unsigned char RequestedReplyLength; - unsigned char *TargetPointer, Character; - int TargetID, i; - /* - Configuration Information for FlashPoint Host Adapters is provided in the - FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function. - Initialize fields in the Host Adapter structure from the FlashPoint_Info - structure. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; - TargetPointer = HostAdapter->ModelName; - *TargetPointer++ = 'B'; - *TargetPointer++ = 'T'; - *TargetPointer++ = '-'; - for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++) - *TargetPointer++ = FlashPointInfo->ModelNumber[i]; - *TargetPointer++ = '\0'; - strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion); - HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID; - HostAdapter->ExtendedTranslationEnabled = - FlashPointInfo->ExtendedTranslationEnabled; - HostAdapter->ParityCheckingEnabled = - FlashPointInfo->ParityCheckingEnabled; - HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset; - HostAdapter->LevelSensitiveInterrupt = true; - HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI; - HostAdapter->HostDifferentialSCSI = false; - HostAdapter->HostSupportsSCAM = true; - HostAdapter->HostUltraSCSI = true; - HostAdapter->ExtendedLUNSupport = true; - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated; - HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated; - HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled; - HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2; - HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); - HostAdapter->MaxLogicalUnits = 32; - HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; - HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; - HostAdapter->DriverQueueDepth = 255; - HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth; - HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted; - HostAdapter->FastPermitted = FlashPointInfo->FastPermitted; - HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted; - HostAdapter->WidePermitted = FlashPointInfo->WidePermitted; - HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted; - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - goto Common; - } - /* - Issue the Inquire Board ID command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, - &BoardID, sizeof(BoardID)) != sizeof(BoardID)) - return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); - /* - Issue the Inquire Configuration command. - */ - if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, - &Configuration, sizeof(Configuration)) - != sizeof(Configuration)) - return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - /* - Issue the Inquire Extended Setup Information command. - */ - RequestedReplyLength = sizeof(ExtendedSetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &ExtendedSetupInformation, - sizeof(ExtendedSetupInformation)) - != sizeof(ExtendedSetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); - /* - Issue the Inquire Firmware Version 3rd Digit command. - */ - FirmwareVersion3rdDigit = '\0'; - if (BoardID.FirmwareVersion1stDigit > '0') - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, - NULL, 0, &FirmwareVersion3rdDigit, - sizeof(FirmwareVersion3rdDigit)) - != sizeof(FirmwareVersion3rdDigit)) - return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); - /* - Issue the Inquire Host Adapter Model Number command. - */ - if (ExtendedSetupInformation.BusType == 'A' && - BoardID.FirmwareVersion1stDigit == '2') - /* BusLogic BT-542B ISA 2.xx */ - strcpy(HostAdapterModelNumber, "542B"); - else if (ExtendedSetupInformation.BusType == 'E' && - BoardID.FirmwareVersion1stDigit == '2' && - (BoardID.FirmwareVersion2ndDigit <= '1' || - (BoardID.FirmwareVersion2ndDigit == '2' && - FirmwareVersion3rdDigit == '0'))) - /* BusLogic BT-742A EISA 2.1x or 2.20 */ - strcpy(HostAdapterModelNumber, "742A"); - else if (ExtendedSetupInformation.BusType == 'E' && - BoardID.FirmwareVersion1stDigit == '0') - /* AMI FastDisk EISA Series 441 0.x */ - strcpy(HostAdapterModelNumber, "747A"); - else - { - RequestedReplyLength = sizeof(HostAdapterModelNumber); - if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &HostAdapterModelNumber, - sizeof(HostAdapterModelNumber)) - != sizeof(HostAdapterModelNumber)) - return BusLogic_Failure(HostAdapter, - "INQUIRE HOST ADAPTER MODEL NUMBER"); - } - /* - BusLogic MultiMaster Host Adapters can be identified by their model number - and the major version number of their firmware as follows: - - 5.xx BusLogic "W" Series Host Adapters: - BT-948/958/958D - 4.xx BusLogic "C" Series Host Adapters: - BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF - 3.xx BusLogic "S" Series Host Adapters: - BT-747S/747D/757S/757D/445S/545S/542D - BT-542B/742A (revision H) - 2.xx BusLogic "A" Series Host Adapters: - BT-542B/742A (revision G and below) - 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter - */ - /* - Save the Model Name and Host Adapter Name in the Host Adapter structure. - */ - TargetPointer = HostAdapter->ModelName; - *TargetPointer++ = 'B'; - *TargetPointer++ = 'T'; - *TargetPointer++ = '-'; - for (i = 0; i < sizeof(HostAdapterModelNumber); i++) - { - Character = HostAdapterModelNumber[i]; - if (Character == ' ' || Character == '\0') break; - *TargetPointer++ = Character; - } - *TargetPointer++ = '\0'; - /* - Save the Firmware Version in the Host Adapter structure. - */ - TargetPointer = HostAdapter->FirmwareVersion; - *TargetPointer++ = BoardID.FirmwareVersion1stDigit; - *TargetPointer++ = '.'; - *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; - if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') - *TargetPointer++ = FirmwareVersion3rdDigit; - *TargetPointer = '\0'; - /* - Issue the Inquire Firmware Version Letter command. - */ - if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) - { - if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, - NULL, 0, &FirmwareVersionLetter, - sizeof(FirmwareVersionLetter)) - != sizeof(FirmwareVersionLetter)) - return BusLogic_Failure(HostAdapter, - "INQUIRE FIRMWARE VERSION LETTER"); - if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') - *TargetPointer++ = FirmwareVersionLetter; - *TargetPointer = '\0'; - } - /* - Save the Host Adapter SCSI ID in the Host Adapter structure. - */ - HostAdapter->SCSI_ID = Configuration.HostAdapterID; - /* - Determine the Bus Type and save it in the Host Adapter structure, determine - and save the IRQ Channel if necessary, and determine and save the DMA - Channel for ISA Host Adapters. - */ - HostAdapter->HostAdapterBusType = - BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; - if (HostAdapter->IRQ_Channel == 0) - { - if (Configuration.IRQ_Channel9) - HostAdapter->IRQ_Channel = 9; - else if (Configuration.IRQ_Channel10) - HostAdapter->IRQ_Channel = 10; - else if (Configuration.IRQ_Channel11) - HostAdapter->IRQ_Channel = 11; - else if (Configuration.IRQ_Channel12) - HostAdapter->IRQ_Channel = 12; - else if (Configuration.IRQ_Channel14) - HostAdapter->IRQ_Channel = 14; - else if (Configuration.IRQ_Channel15) - HostAdapter->IRQ_Channel = 15; - } - if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) - { - if (Configuration.DMA_Channel5) - HostAdapter->DMA_Channel = 5; - else if (Configuration.DMA_Channel6) - HostAdapter->DMA_Channel = 6; - else if (Configuration.DMA_Channel7) - HostAdapter->DMA_Channel = 7; - } - /* - Determine whether Extended Translation is enabled and save it in - the Host Adapter structure. - */ - GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); - HostAdapter->ExtendedTranslationEnabled = - GeometryRegister.gr.ExtendedTranslationEnabled; - /* - Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide - SCSI flag, Differential SCSI flag, SCAM Supported flag, and - Ultra SCSI flag in the Host Adapter structure. - */ - HostAdapter->HostAdapterScatterGatherLimit = - ExtendedSetupInformation.ScatterGatherLimit; - HostAdapter->DriverScatterGatherLimit = - HostAdapter->HostAdapterScatterGatherLimit; - if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) - HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; - if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) - HostAdapter->LevelSensitiveInterrupt = true; - HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; - HostAdapter->HostDifferentialSCSI = - ExtendedSetupInformation.HostDifferentialSCSI; - HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; - HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; - /* - Determine whether Extended LUN Format CCBs are supported and save the - information in the Host Adapter structure. - */ - if (HostAdapter->FirmwareVersion[0] == '5' || - (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) - HostAdapter->ExtendedLUNSupport = true; - /* - Issue the Inquire PCI Host Adapter Information command to read the - Termination Information from "W" series MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] == '5') - { - if (BusLogic_Command(HostAdapter, - BusLogic_InquirePCIHostAdapterInformation, - NULL, 0, &PCIHostAdapterInformation, - sizeof(PCIHostAdapterInformation)) - != sizeof(PCIHostAdapterInformation)) - return BusLogic_Failure(HostAdapter, - "INQUIRE PCI HOST ADAPTER INFORMATION"); - /* - Save the Termination Information in the Host Adapter structure. - */ - if (PCIHostAdapterInformation.GenericInfoValid) - { - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = - PCIHostAdapterInformation.LowByteTerminated; - HostAdapter->HighByteTerminated = - PCIHostAdapterInformation.HighByteTerminated; + struct BusLogic_BoardID BoardID; + struct BusLogic_Configuration Configuration; + struct BusLogic_SetupInformation SetupInformation; + struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; + unsigned char HostAdapterModelNumber[5]; + unsigned char FirmwareVersion3rdDigit; + unsigned char FirmwareVersionLetter; + struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation; + struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest; + struct BusLogic_AutoSCSIData AutoSCSIData; + union BusLogic_GeometryRegister GeometryRegister; + unsigned char RequestedReplyLength; + unsigned char *TargetPointer, Character; + int TargetID, i; + /* + Configuration Information for FlashPoint Host Adapters is provided in the + FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function. + Initialize fields in the Host Adapter structure from the FlashPoint_Info + structure. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) { + struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo; + TargetPointer = HostAdapter->ModelName; + *TargetPointer++ = 'B'; + *TargetPointer++ = 'T'; + *TargetPointer++ = '-'; + for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++) + *TargetPointer++ = FlashPointInfo->ModelNumber[i]; + *TargetPointer++ = '\0'; + strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion); + HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID; + HostAdapter->ExtendedTranslationEnabled = FlashPointInfo->ExtendedTranslationEnabled; + HostAdapter->ParityCheckingEnabled = FlashPointInfo->ParityCheckingEnabled; + HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset; + HostAdapter->LevelSensitiveInterrupt = true; + HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI; + HostAdapter->HostDifferentialSCSI = false; + HostAdapter->HostSupportsSCAM = true; + HostAdapter->HostUltraSCSI = true; + HostAdapter->ExtendedLUNSupport = true; + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated; + HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated; + HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled; + HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2; + HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; + HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); + HostAdapter->MaxLogicalUnits = 32; + HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; + HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; + HostAdapter->DriverQueueDepth = 255; + HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth; + HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted; + HostAdapter->FastPermitted = FlashPointInfo->FastPermitted; + HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted; + HostAdapter->WidePermitted = FlashPointInfo->WidePermitted; + HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted; + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + goto Common; + } + /* + Issue the Inquire Board ID command. + */ + if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)) != sizeof(BoardID)) + return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID"); + /* + Issue the Inquire Configuration command. + */ + if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, &Configuration, sizeof(Configuration)) + != sizeof(Configuration)) + return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION"); + /* + Issue the Inquire Setup Information command. + */ + RequestedReplyLength = sizeof(SetupInformation); + if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation)) + != sizeof(SetupInformation)) + return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); + /* + Issue the Inquire Extended Setup Information command. + */ + RequestedReplyLength = sizeof(ExtendedSetupInformation); + if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation)) + != sizeof(ExtendedSetupInformation)) + return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION"); + /* + Issue the Inquire Firmware Version 3rd Digit command. + */ + FirmwareVersion3rdDigit = '\0'; + if (BoardID.FirmwareVersion1stDigit > '0') + if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, NULL, 0, &FirmwareVersion3rdDigit, sizeof(FirmwareVersion3rdDigit)) + != sizeof(FirmwareVersion3rdDigit)) + return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT"); + /* + Issue the Inquire Host Adapter Model Number command. + */ + if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2') + /* BusLogic BT-542B ISA 2.xx */ + strcpy(HostAdapterModelNumber, "542B"); + else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '2' && (BoardID.FirmwareVersion2ndDigit <= '1' || (BoardID.FirmwareVersion2ndDigit == '2' && FirmwareVersion3rdDigit == '0'))) + /* BusLogic BT-742A EISA 2.1x or 2.20 */ + strcpy(HostAdapterModelNumber, "742A"); + else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0') + /* AMI FastDisk EISA Series 441 0.x */ + strcpy(HostAdapterModelNumber, "747A"); + else { + RequestedReplyLength = sizeof(HostAdapterModelNumber); + if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), &HostAdapterModelNumber, sizeof(HostAdapterModelNumber)) + != sizeof(HostAdapterModelNumber)) + return BusLogic_Failure(HostAdapter, "INQUIRE HOST ADAPTER MODEL NUMBER"); + } + /* + BusLogic MultiMaster Host Adapters can be identified by their model number + and the major version number of their firmware as follows: + + 5.xx BusLogic "W" Series Host Adapters: + BT-948/958/958D + 4.xx BusLogic "C" Series Host Adapters: + BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF + 3.xx BusLogic "S" Series Host Adapters: + BT-747S/747D/757S/757D/445S/545S/542D + BT-542B/742A (revision H) + 2.xx BusLogic "A" Series Host Adapters: + BT-542B/742A (revision G and below) + 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter + */ + /* + Save the Model Name and Host Adapter Name in the Host Adapter structure. + */ + TargetPointer = HostAdapter->ModelName; + *TargetPointer++ = 'B'; + *TargetPointer++ = 'T'; + *TargetPointer++ = '-'; + for (i = 0; i < sizeof(HostAdapterModelNumber); i++) { + Character = HostAdapterModelNumber[i]; + if (Character == ' ' || Character == '\0') + break; + *TargetPointer++ = Character; + } + *TargetPointer++ = '\0'; + /* + Save the Firmware Version in the Host Adapter structure. + */ + TargetPointer = HostAdapter->FirmwareVersion; + *TargetPointer++ = BoardID.FirmwareVersion1stDigit; + *TargetPointer++ = '.'; + *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; + if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') + *TargetPointer++ = FirmwareVersion3rdDigit; + *TargetPointer = '\0'; + /* + Issue the Inquire Firmware Version Letter command. + */ + if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) { + if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter)) + != sizeof(FirmwareVersionLetter)) + return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER"); + if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') + *TargetPointer++ = FirmwareVersionLetter; + *TargetPointer = '\0'; + } + /* + Save the Host Adapter SCSI ID in the Host Adapter structure. + */ + HostAdapter->SCSI_ID = Configuration.HostAdapterID; + /* + Determine the Bus Type and save it in the Host Adapter structure, determine + and save the IRQ Channel if necessary, and determine and save the DMA + Channel for ISA Host Adapters. + */ + HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; + if (HostAdapter->IRQ_Channel == 0) { + if (Configuration.IRQ_Channel9) + HostAdapter->IRQ_Channel = 9; + else if (Configuration.IRQ_Channel10) + HostAdapter->IRQ_Channel = 10; + else if (Configuration.IRQ_Channel11) + HostAdapter->IRQ_Channel = 11; + else if (Configuration.IRQ_Channel12) + HostAdapter->IRQ_Channel = 12; + else if (Configuration.IRQ_Channel14) + HostAdapter->IRQ_Channel = 14; + else if (Configuration.IRQ_Channel15) + HostAdapter->IRQ_Channel = 15; + } + if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) { + if (Configuration.DMA_Channel5) + HostAdapter->DMA_Channel = 5; + else if (Configuration.DMA_Channel6) + HostAdapter->DMA_Channel = 6; + else if (Configuration.DMA_Channel7) + HostAdapter->DMA_Channel = 7; + } + /* + Determine whether Extended Translation is enabled and save it in + the Host Adapter structure. + */ + GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); + HostAdapter->ExtendedTranslationEnabled = GeometryRegister.gr.ExtendedTranslationEnabled; + /* + Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide + SCSI flag, Differential SCSI flag, SCAM Supported flag, and + Ultra SCSI flag in the Host Adapter structure. + */ + HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit; + HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit; + if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) + HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; + if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) + HostAdapter->LevelSensitiveInterrupt = true; + HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; + HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI; + HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; + HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; + /* + Determine whether Extended LUN Format CCBs are supported and save the + information in the Host Adapter structure. + */ + if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) + HostAdapter->ExtendedLUNSupport = true; + /* + Issue the Inquire PCI Host Adapter Information command to read the + Termination Information from "W" series MultiMaster Host Adapters. + */ + if (HostAdapter->FirmwareVersion[0] == '5') { + if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation)) + != sizeof(PCIHostAdapterInformation)) + return BusLogic_Failure(HostAdapter, "INQUIRE PCI HOST ADAPTER INFORMATION"); + /* + Save the Termination Information in the Host Adapter structure. + */ + if (PCIHostAdapterInformation.GenericInfoValid) { + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated; + HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated; + } } - } - /* - Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data - from "W" and "C" series MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] >= '4') - { - FetchHostAdapterLocalRAMRequest.ByteOffset = - BusLogic_AutoSCSI_BaseOffset; - FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); - if (BusLogic_Command(HostAdapter, - BusLogic_FetchHostAdapterLocalRAM, - &FetchHostAdapterLocalRAMRequest, - sizeof(FetchHostAdapterLocalRAMRequest), - &AutoSCSIData, sizeof(AutoSCSIData)) - != sizeof(AutoSCSIData)) - return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); - /* - Save the Parity Checking Enabled, Bus Reset Enabled, and Termination - Information in the Host Adapter structure. - */ - HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; - HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; - if (HostAdapter->FirmwareVersion[0] == '4') - { - HostAdapter->TerminationInfoValid = true; - HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated; - HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated; + /* + Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data + from "W" and "C" series MultiMaster Host Adapters. + */ + if (HostAdapter->FirmwareVersion[0] >= '4') { + FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset; + FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); + if (BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIData, sizeof(AutoSCSIData)) + != sizeof(AutoSCSIData)) + return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM"); + /* + Save the Parity Checking Enabled, Bus Reset Enabled, and Termination + Information in the Host Adapter structure. + */ + HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; + HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; + if (HostAdapter->FirmwareVersion[0] == '4') { + HostAdapter->TerminationInfoValid = true; + HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated; + HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated; + } + /* + Save the Wide Permitted, Fast Permitted, Synchronous Permitted, + Disconnect Permitted, Ultra Permitted, and SCAM Information in the + Host Adapter structure. + */ + HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; + HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; + HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted; + HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted; + if (HostAdapter->HostUltraSCSI) + HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; + if (HostAdapter->HostSupportsSCAM) { + HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; + HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; + } } - /* - Save the Wide Permitted, Fast Permitted, Synchronous Permitted, - Disconnect Permitted, Ultra Permitted, and SCAM Information in the - Host Adapter structure. - */ - HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; - HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; - HostAdapter->SynchronousPermitted = - AutoSCSIData.SynchronousPermitted; - HostAdapter->DisconnectPermitted = - AutoSCSIData.DisconnectPermitted; - if (HostAdapter->HostUltraSCSI) - HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; - if (HostAdapter->HostSupportsSCAM) - { - HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; - HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; + /* + Initialize fields in the Host Adapter structure for "S" and "A" series + MultiMaster Host Adapters. + */ + if (HostAdapter->FirmwareVersion[0] < '4') { + if (SetupInformation.SynchronousInitiationEnabled) { + HostAdapter->SynchronousPermitted = 0xFF; + if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) { + if (ExtendedSetupInformation.Misc.FastOnEISA) + HostAdapter->FastPermitted = 0xFF; + if (strcmp(HostAdapter->ModelName, "BT-757") == 0) + HostAdapter->WidePermitted = 0xFF; + } + } + HostAdapter->DisconnectPermitted = 0xFF; + HostAdapter->ParityCheckingEnabled = SetupInformation.ParityCheckingEnabled; + HostAdapter->BusResetEnabled = true; } - } - /* - Initialize fields in the Host Adapter structure for "S" and "A" series - MultiMaster Host Adapters. - */ - if (HostAdapter->FirmwareVersion[0] < '4') - { - if (SetupInformation.SynchronousInitiationEnabled) - { - HostAdapter->SynchronousPermitted = 0xFF; - if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) - { - if (ExtendedSetupInformation.Misc.FastOnEISA) - HostAdapter->FastPermitted = 0xFF; - if (strcmp(HostAdapter->ModelName, "BT-757") == 0) - HostAdapter->WidePermitted = 0xFF; - } + /* + Determine the maximum number of Target IDs and Logical Units supported by + this driver for Wide and Narrow Host Adapters. + */ + HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); + HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); + /* + Select appropriate values for the Mailbox Count, Driver Queue Depth, + Initial CCBs, and Incremental CCBs variables based on whether or not Strict + Round Robin Mode is supported. If Strict Round Robin Mode is supported, + then there is no performance degradation in using the maximum possible + number of Outgoing and Incoming Mailboxes and allowing the Tagged and + Untagged Queue Depths to determine the actual utilization. If Strict Round + Robin Mode is not supported, then the Host Adapter must scan all the + Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can + cause a substantial performance penalty. The host adapters actually have + room to store the following number of CCBs internally; that is, they can + internally queue and manage this many active commands on the SCSI bus + simultaneously. Performance measurements demonstrate that the Driver Queue + Depth should be set to the Mailbox Count, rather than the Host Adapter + Queue Depth (internal CCB capacity), as it is more efficient to have the + queued commands waiting in Outgoing Mailboxes if necessary than to block + the process in the higher levels of the SCSI Subsystem. + + 192 BT-948/958/958D + 100 BT-946C/956C/956CD/747C/757C/757CD/445C + 50 BT-545C/540CF + 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A + */ + if (HostAdapter->FirmwareVersion[0] == '5') + HostAdapter->HostAdapterQueueDepth = 192; + else if (HostAdapter->FirmwareVersion[0] == '4') + HostAdapter->HostAdapterQueueDepth = (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50); + else + HostAdapter->HostAdapterQueueDepth = 30; + if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) { + HostAdapter->StrictRoundRobinModeSupport = true; + HostAdapter->MailboxCount = BusLogic_MaxMailboxes; + } else { + HostAdapter->StrictRoundRobinModeSupport = false; + HostAdapter->MailboxCount = 32; + } + HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount; + HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; + HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; + /* + Tagged Queuing support is available and operates properly on all "W" series + MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with + firmware version 4.22 and above, and on "S" series MultiMaster Host + Adapters with firmware version 3.35 and above. + */ + HostAdapter->TaggedQueuingPermitted = 0; + switch (HostAdapter->FirmwareVersion[0]) { + case '5': + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; + case '4': + if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; + case '3': + if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) + HostAdapter->TaggedQueuingPermitted = 0xFFFF; + break; } - HostAdapter->DisconnectPermitted = 0xFF; - HostAdapter->ParityCheckingEnabled = - SetupInformation.ParityCheckingEnabled; - HostAdapter->BusResetEnabled = true; - } - /* - Determine the maximum number of Target IDs and Logical Units supported by - this driver for Wide and Narrow Host Adapters. - */ - HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); - HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); - /* - Select appropriate values for the Mailbox Count, Driver Queue Depth, - Initial CCBs, and Incremental CCBs variables based on whether or not Strict - Round Robin Mode is supported. If Strict Round Robin Mode is supported, - then there is no performance degradation in using the maximum possible - number of Outgoing and Incoming Mailboxes and allowing the Tagged and - Untagged Queue Depths to determine the actual utilization. If Strict Round - Robin Mode is not supported, then the Host Adapter must scan all the - Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can - cause a substantial performance penalty. The host adapters actually have - room to store the following number of CCBs internally; that is, they can - internally queue and manage this many active commands on the SCSI bus - simultaneously. Performance measurements demonstrate that the Driver Queue - Depth should be set to the Mailbox Count, rather than the Host Adapter - Queue Depth (internal CCB capacity), as it is more efficient to have the - queued commands waiting in Outgoing Mailboxes if necessary than to block - the process in the higher levels of the SCSI Subsystem. - - 192 BT-948/958/958D - 100 BT-946C/956C/956CD/747C/757C/757CD/445C - 50 BT-545C/540CF - 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A - */ - if (HostAdapter->FirmwareVersion[0] == '5') - HostAdapter->HostAdapterQueueDepth = 192; - else if (HostAdapter->FirmwareVersion[0] == '4') - HostAdapter->HostAdapterQueueDepth = - (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50); - else HostAdapter->HostAdapterQueueDepth = 30; - if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) - { - HostAdapter->StrictRoundRobinModeSupport = true; - HostAdapter->MailboxCount = BusLogic_MaxMailboxes; - } - else - { - HostAdapter->StrictRoundRobinModeSupport = false; - HostAdapter->MailboxCount = 32; - } - HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount; - HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize; - HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize; - /* - Tagged Queuing support is available and operates properly on all "W" series - MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with - firmware version 4.22 and above, and on "S" series MultiMaster Host - Adapters with firmware version 3.35 and above. - */ - HostAdapter->TaggedQueuingPermitted = 0; - switch (HostAdapter->FirmwareVersion[0]) - { - case '5': - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - case '4': - if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0) - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - case '3': - if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0) - HostAdapter->TaggedQueuingPermitted = 0xFFFF; - break; - } - /* - Determine the Host Adapter BIOS Address if the BIOS is enabled and - save it in the Host Adapter structure. The BIOS is disabled if the - BIOS_Address is 0. - */ - HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; - /* - ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. - */ - if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && - (void *) high_memory > (void *) MAX_DMA_ADDRESS) - HostAdapter->BounceBuffersRequired = true; - /* - BusLogic BT-445S Host Adapters prior to board revision E have a hardware - bug whereby when the BIOS is enabled, transfers to/from the same address - range the BIOS occupies modulo 16MB are handled incorrectly. Only properly - functioning BT-445S Host Adapters have firmware version 3.37, so require - that ISA Bounce Buffers be used for the buggy BT-445S models if there is - more than 16MB memory. - */ - if (HostAdapter->BIOS_Address > 0 && - strcmp(HostAdapter->ModelName, "BT-445S") == 0 && - strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && - (void *) high_memory > (void *) MAX_DMA_ADDRESS) - HostAdapter->BounceBuffersRequired = true; - /* - Initialize parameters common to MultiMaster and FlashPoint Host Adapters. - */ -Common: - /* - Initialize the Host Adapter Full Model Name from the Model Name. - */ - strcpy(HostAdapter->FullModelName, "BusLogic "); - strcat(HostAdapter->FullModelName, HostAdapter->ModelName); - /* - Select an appropriate value for the Tagged Queue Depth either from a - BusLogic Driver Options specification, or based on whether this Host - Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth - is left at 0 for automatic determination in BusLogic_SelectQueueDepths. - Initialize the Untagged Queue Depth. - */ - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - { - unsigned char QueueDepth = 0; - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->QueueDepth[TargetID] > 0) - QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID]; - else if (HostAdapter->BounceBuffersRequired) - QueueDepth = BusLogic_TaggedQueueDepthBB; - HostAdapter->QueueDepth[TargetID] = QueueDepth; - } - if (HostAdapter->BounceBuffersRequired) - HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB; - else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth; - if (HostAdapter->DriverOptions != NULL) - HostAdapter->CommonQueueDepth = - HostAdapter->DriverOptions->CommonQueueDepth; - if (HostAdapter->CommonQueueDepth > 0 && - HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth) - HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth; - /* - Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. - Therefore, mask the Tagged Queuing Permitted Default bits with the - Disconnect/Reconnect Permitted bits. - */ - HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; - /* - Combine the default Tagged Queuing Permitted bits with any BusLogic Driver - Options Tagged Queuing specification. - */ - if (HostAdapter->DriverOptions != NULL) - HostAdapter->TaggedQueuingPermitted = - (HostAdapter->DriverOptions->TaggedQueuingPermitted & - HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | - (HostAdapter->TaggedQueuingPermitted & - ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask); - - /* - Select an appropriate value for Bus Settle Time either from a BusLogic - Driver Options specification, or from BusLogic_DefaultBusSettleTime. - */ - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->BusSettleTime > 0) - HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime; - else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; - /* - Indicate reading the Host Adapter Configuration completed successfully. - */ - return true; + /* + Determine the Host Adapter BIOS Address if the BIOS is enabled and + save it in the Host Adapter structure. The BIOS is disabled if the + BIOS_Address is 0. + */ + HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; + /* + ISA Host Adapters require Bounce Buffers if there is more than 16MB memory. + */ + if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *) MAX_DMA_ADDRESS) + HostAdapter->BounceBuffersRequired = true; + /* + BusLogic BT-445S Host Adapters prior to board revision E have a hardware + bug whereby when the BIOS is enabled, transfers to/from the same address + range the BIOS occupies modulo 16MB are handled incorrectly. Only properly + functioning BT-445S Host Adapters have firmware version 3.37, so require + that ISA Bounce Buffers be used for the buggy BT-445S models if there is + more than 16MB memory. + */ + if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && (void *) high_memory > (void *) MAX_DMA_ADDRESS) + HostAdapter->BounceBuffersRequired = true; + /* + Initialize parameters common to MultiMaster and FlashPoint Host Adapters. + */ + Common: + /* + Initialize the Host Adapter Full Model Name from the Model Name. + */ + strcpy(HostAdapter->FullModelName, "BusLogic "); + strcat(HostAdapter->FullModelName, HostAdapter->ModelName); + /* + Select an appropriate value for the Tagged Queue Depth either from a + BusLogic Driver Options specification, or based on whether this Host + Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth + is left at 0 for automatic determination in BusLogic_SelectQueueDepths. + Initialize the Untagged Queue Depth. + */ + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) { + unsigned char QueueDepth = 0; + if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->QueueDepth[TargetID] > 0) + QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID]; + else if (HostAdapter->BounceBuffersRequired) + QueueDepth = BusLogic_TaggedQueueDepthBB; + HostAdapter->QueueDepth[TargetID] = QueueDepth; + } + if (HostAdapter->BounceBuffersRequired) + HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB; + else + HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth; + if (HostAdapter->DriverOptions != NULL) + HostAdapter->CommonQueueDepth = HostAdapter->DriverOptions->CommonQueueDepth; + if (HostAdapter->CommonQueueDepth > 0 && HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth) + HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth; + /* + Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. + Therefore, mask the Tagged Queuing Permitted Default bits with the + Disconnect/Reconnect Permitted bits. + */ + HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; + /* + Combine the default Tagged Queuing Permitted bits with any BusLogic Driver + Options Tagged Queuing specification. + */ + if (HostAdapter->DriverOptions != NULL) + HostAdapter->TaggedQueuingPermitted = + (HostAdapter->DriverOptions->TaggedQueuingPermitted & HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask); + + /* + Select an appropriate value for Bus Settle Time either from a BusLogic + Driver Options specification, or from BusLogic_DefaultBusSettleTime. + */ + if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->BusSettleTime > 0) + HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime; + else + HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; + /* + Indicate reading the Host Adapter Configuration completed successfully. + */ + return true; } @@ -2045,210 +1688,144 @@ Common: static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { - unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; - unsigned short SynchronousPermitted, FastPermitted; - unsigned short UltraPermitted, WidePermitted; - unsigned short DisconnectPermitted, TaggedQueuingPermitted; - boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; - char SynchronousString[BusLogic_MaxTargetDevices+1]; - char WideString[BusLogic_MaxTargetDevices+1]; - char DisconnectString[BusLogic_MaxTargetDevices+1]; - char TaggedQueuingString[BusLogic_MaxTargetDevices+1]; - char *SynchronousMessage = SynchronousString; - char *WideMessage = WideString; - char *DisconnectMessage = DisconnectString; - char *TaggedQueuingMessage = TaggedQueuingString; - int TargetID; - BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", - HostAdapter, HostAdapter->ModelName, - BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], - (HostAdapter->HostWideSCSI ? " Wide" : ""), - (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), - (HostAdapter->HostUltraSCSI ? " Ultra" : "")); - BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " - "IRQ Channel: %d/%s\n", HostAdapter, - HostAdapter->FirmwareVersion, - HostAdapter->IO_Address, HostAdapter->IRQ_Channel, - (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge")); - if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) - { - BusLogic_Info(" DMA Channel: ", HostAdapter); - if (HostAdapter->DMA_Channel > 0) - BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel); - else BusLogic_Info("None, ", HostAdapter); - if (HostAdapter->BIOS_Address > 0) - BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, - HostAdapter->BIOS_Address); - else BusLogic_Info("BIOS Address: None, ", HostAdapter); - } - else - { - BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", - HostAdapter, HostAdapter->Bus, HostAdapter->Device); - if (HostAdapter->PCI_Address > 0) - BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address); - else BusLogic_Info("Unassigned, ", HostAdapter); - } - BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, - HostAdapter->SCSI_ID); - BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", - HostAdapter, - (HostAdapter->ParityCheckingEnabled - ? "Enabled" : "Disabled"), - (HostAdapter->ExtendedTranslationEnabled - ? "Enabled" : "Disabled")); - AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID); - SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask; - FastPermitted = HostAdapter->FastPermitted & AllTargetsMask; - UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask; - if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && - (HostAdapter->FirmwareVersion[0] >= '4' || - HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || - BusLogic_FlashPointHostAdapterP(HostAdapter)) - { - CommonSynchronousNegotiation = false; - if (SynchronousPermitted == 0) - { - SynchronousMessage = "Disabled"; - CommonSynchronousNegotiation = true; - } - else if (SynchronousPermitted == AllTargetsMask) - { - if (FastPermitted == 0) - { - SynchronousMessage = "Slow"; - CommonSynchronousNegotiation = true; - } - else if (FastPermitted == AllTargetsMask) - { - if (UltraPermitted == 0) - { - SynchronousMessage = "Fast"; - CommonSynchronousNegotiation = true; + unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; + unsigned short SynchronousPermitted, FastPermitted; + unsigned short UltraPermitted, WidePermitted; + unsigned short DisconnectPermitted, TaggedQueuingPermitted; + boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; + char SynchronousString[BusLogic_MaxTargetDevices + 1]; + char WideString[BusLogic_MaxTargetDevices + 1]; + char DisconnectString[BusLogic_MaxTargetDevices + 1]; + char TaggedQueuingString[BusLogic_MaxTargetDevices + 1]; + char *SynchronousMessage = SynchronousString; + char *WideMessage = WideString; + char *DisconnectMessage = DisconnectString; + char *TaggedQueuingMessage = TaggedQueuingString; + int TargetID; + BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", + HostAdapter, HostAdapter->ModelName, + BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], (HostAdapter->HostWideSCSI ? " Wide" : ""), (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), (HostAdapter->HostUltraSCSI ? " Ultra" : "")); + BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", HostAdapter, HostAdapter->FirmwareVersion, HostAdapter->IO_Address, HostAdapter->IRQ_Channel, (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge")); + if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) { + BusLogic_Info(" DMA Channel: ", HostAdapter); + if (HostAdapter->DMA_Channel > 0) + BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel); + else + BusLogic_Info("None, ", HostAdapter); + if (HostAdapter->BIOS_Address > 0) + BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, HostAdapter->BIOS_Address); + else + BusLogic_Info("BIOS Address: None, ", HostAdapter); + } else { + BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", HostAdapter, HostAdapter->Bus, HostAdapter->Device); + if (HostAdapter->PCI_Address > 0) + BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address); + else + BusLogic_Info("Unassigned, ", HostAdapter); + } + BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, HostAdapter->SCSI_ID); + BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", HostAdapter, (HostAdapter->ParityCheckingEnabled ? "Enabled" : "Disabled"), (HostAdapter->ExtendedTranslationEnabled ? "Enabled" : "Disabled")); + AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID); + SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask; + FastPermitted = HostAdapter->FastPermitted & AllTargetsMask; + UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask; + if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && (HostAdapter->FirmwareVersion[0] >= '4' || HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || BusLogic_FlashPointHostAdapterP(HostAdapter)) { + CommonSynchronousNegotiation = false; + if (SynchronousPermitted == 0) { + SynchronousMessage = "Disabled"; + CommonSynchronousNegotiation = true; + } else if (SynchronousPermitted == AllTargetsMask) { + if (FastPermitted == 0) { + SynchronousMessage = "Slow"; + CommonSynchronousNegotiation = true; + } else if (FastPermitted == AllTargetsMask) { + if (UltraPermitted == 0) { + SynchronousMessage = "Fast"; + CommonSynchronousNegotiation = true; + } else if (UltraPermitted == AllTargetsMask) { + SynchronousMessage = "Ultra"; + CommonSynchronousNegotiation = true; + } + } } - else if (UltraPermitted == AllTargetsMask) - { - SynchronousMessage = "Ultra"; - CommonSynchronousNegotiation = true; + if (!CommonSynchronousNegotiation) { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + SynchronousString[TargetID] = ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : (!(FastPermitted & (1 << TargetID)) ? 'S' : (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U'))); + SynchronousString[HostAdapter->SCSI_ID] = '#'; + SynchronousString[HostAdapter->MaxTargetDevices] = '\0'; } - } - } - if (!CommonSynchronousNegotiation) - { - for (TargetID = 0; - TargetID < HostAdapter->MaxTargetDevices; - TargetID++) - SynchronousString[TargetID] = - ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : - (!(FastPermitted & (1 << TargetID)) ? 'S' : - (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U'))); - SynchronousString[HostAdapter->SCSI_ID] = '#'; - SynchronousString[HostAdapter->MaxTargetDevices] = '\0'; + } else + SynchronousMessage = (SynchronousPermitted == 0 ? "Disabled" : "Enabled"); + WidePermitted = HostAdapter->WidePermitted & AllTargetsMask; + if (WidePermitted == 0) + WideMessage = "Disabled"; + else if (WidePermitted == AllTargetsMask) + WideMessage = "Enabled"; + else { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + WideString[TargetID] = ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N'); + WideString[HostAdapter->SCSI_ID] = '#'; + WideString[HostAdapter->MaxTargetDevices] = '\0'; + } + DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; + if (DisconnectPermitted == 0) + DisconnectMessage = "Disabled"; + else if (DisconnectPermitted == AllTargetsMask) + DisconnectMessage = "Enabled"; + else { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + DisconnectString[TargetID] = ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); + DisconnectString[HostAdapter->SCSI_ID] = '#'; + DisconnectString[HostAdapter->MaxTargetDevices] = '\0'; + } + TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask; + if (TaggedQueuingPermitted == 0) + TaggedQueuingMessage = "Disabled"; + else if (TaggedQueuingPermitted == AllTargetsMask) + TaggedQueuingMessage = "Enabled"; + else { + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + TaggedQueuingString[TargetID] = ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); + TaggedQueuingString[HostAdapter->SCSI_ID] = '#'; + TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0'; + } + BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", HostAdapter, SynchronousMessage, WideMessage); + BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", HostAdapter, DisconnectMessage, TaggedQueuingMessage); + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { + BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", HostAdapter, HostAdapter->DriverScatterGatherLimit, HostAdapter->HostAdapterScatterGatherLimit, HostAdapter->MailboxCount); + BusLogic_Info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->HostAdapterQueueDepth); + } else + BusLogic_Info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->DriverScatterGatherLimit); + BusLogic_Info(" Tagged Queue Depth: ", HostAdapter); + CommonTaggedQueueDepth = true; + for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) { + CommonTaggedQueueDepth = false; + break; + } + if (CommonTaggedQueueDepth) { + if (HostAdapter->QueueDepth[0] > 0) + BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]); + else + BusLogic_Info("Automatic", HostAdapter); + } else + BusLogic_Info("Individual", HostAdapter); + BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, HostAdapter->UntaggedQueueDepth); + if (HostAdapter->TerminationInfoValid) { + if (HostAdapter->HostWideSCSI) + BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? (HostAdapter->HighByteTerminated ? "Both Enabled" : "Low Enabled") + : (HostAdapter->HighByteTerminated ? "High Enabled" : "Both Disabled"))); + else + BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled")); + if (HostAdapter->HostSupportsSCAM) + BusLogic_Info(", SCAM: %s", HostAdapter, (HostAdapter->SCAM_Enabled ? (HostAdapter->SCAM_Level2 ? "Enabled, Level 2" : "Enabled, Level 1") + : "Disabled")); + BusLogic_Info("\n", HostAdapter); } - } - else SynchronousMessage = - (SynchronousPermitted == 0 ? "Disabled" : "Enabled"); - WidePermitted = HostAdapter->WidePermitted & AllTargetsMask; - if (WidePermitted == 0) - WideMessage = "Disabled"; - else if (WidePermitted == AllTargetsMask) - WideMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - WideString[TargetID] = - ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N'); - WideString[HostAdapter->SCSI_ID] = '#'; - WideString[HostAdapter->MaxTargetDevices] = '\0'; - } - DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask; - if (DisconnectPermitted == 0) - DisconnectMessage = "Disabled"; - else if (DisconnectPermitted == AllTargetsMask) - DisconnectMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - DisconnectString[TargetID] = - ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N'); - DisconnectString[HostAdapter->SCSI_ID] = '#'; - DisconnectString[HostAdapter->MaxTargetDevices] = '\0'; - } - TaggedQueuingPermitted = - HostAdapter->TaggedQueuingPermitted & AllTargetsMask; - if (TaggedQueuingPermitted == 0) - TaggedQueuingMessage = "Disabled"; - else if (TaggedQueuingPermitted == AllTargetsMask) - TaggedQueuingMessage = "Enabled"; - else - { - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - TaggedQueuingString[TargetID] = - ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N'); - TaggedQueuingString[HostAdapter->SCSI_ID] = '#'; - TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0'; - } - BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", - HostAdapter, SynchronousMessage, WideMessage); - BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", - HostAdapter, DisconnectMessage, TaggedQueuingMessage); - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " - "Mailboxes: %d\n", HostAdapter, - HostAdapter->DriverScatterGatherLimit, - HostAdapter->HostAdapterScatterGatherLimit, - HostAdapter->MailboxCount); - BusLogic_Info(" Driver Queue Depth: %d, " - "Host Adapter Queue Depth: %d\n", - HostAdapter, HostAdapter->DriverQueueDepth, - HostAdapter->HostAdapterQueueDepth); - } - else BusLogic_Info(" Driver Queue Depth: %d, " - "Scatter/Gather Limit: %d segments\n", - HostAdapter, HostAdapter->DriverQueueDepth, - HostAdapter->DriverScatterGatherLimit); - BusLogic_Info(" Tagged Queue Depth: ", HostAdapter); - CommonTaggedQueueDepth = true; - for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) - { - CommonTaggedQueueDepth = false; - break; - } - if (CommonTaggedQueueDepth) - { - if (HostAdapter->QueueDepth[0] > 0) - BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]); - else BusLogic_Info("Automatic", HostAdapter); - } - else BusLogic_Info("Individual", HostAdapter); - BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, - HostAdapter->UntaggedQueueDepth); - if (HostAdapter->TerminationInfoValid) - { - if (HostAdapter->HostWideSCSI) - BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, - (HostAdapter->LowByteTerminated - ? (HostAdapter->HighByteTerminated - ? "Both Enabled" : "Low Enabled") - : (HostAdapter->HighByteTerminated - ? "High Enabled" : "Both Disabled"))); - else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, - (HostAdapter->LowByteTerminated ? - "Enabled" : "Disabled")); - if (HostAdapter->HostSupportsSCAM) - BusLogic_Info(", SCAM: %s", HostAdapter, - (HostAdapter->SCAM_Enabled - ? (HostAdapter->SCAM_Level2 - ? "Enabled, Level 2" : "Enabled, Level 1") - : "Disabled")); - BusLogic_Info("\n", HostAdapter); - } - /* - Indicate reporting the Host Adapter configuration completed successfully. - */ - return true; + /* + Indicate reporting the Host Adapter configuration completed successfully. + */ + return true; } @@ -2259,43 +1836,34 @@ static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_Ho static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter) { - if (HostAdapter->IRQ_Channel == 0) - { - BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", - HostAdapter); - return false; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, - SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0) - { - BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", - HostAdapter, HostAdapter->IRQ_Channel); - return false; - } - HostAdapter->IRQ_ChannelAcquired = true; - /* - Acquire exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_Channel > 0) - { - if (request_dma(HostAdapter->DMA_Channel, - HostAdapter->FullModelName) < 0) - { - BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", - HostAdapter, HostAdapter->DMA_Channel); - return false; + if (HostAdapter->IRQ_Channel == 0) { + BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter); + return false; + } + /* + Acquire shared access to the IRQ Channel. + */ + if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0) { + BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->IRQ_Channel); + return false; + } + HostAdapter->IRQ_ChannelAcquired = true; + /* + Acquire exclusive access to the DMA Channel. + */ + if (HostAdapter->DMA_Channel > 0) { + if (request_dma(HostAdapter->DMA_Channel, HostAdapter->FullModelName) < 0) { + BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->DMA_Channel); + return false; + } + set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); + enable_dma(HostAdapter->DMA_Channel); + HostAdapter->DMA_ChannelAcquired = true; } - set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE); - enable_dma(HostAdapter->DMA_Channel); - HostAdapter->DMA_ChannelAcquired = true; - } - /* - Indicate the System Resource Acquisition completed successfully, - */ - return true; + /* + Indicate the System Resource Acquisition completed successfully, + */ + return true; } @@ -2306,26 +1874,24 @@ static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *Hos static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter) { - /* - Release shared access to the IRQ Channel. - */ - if (HostAdapter->IRQ_ChannelAcquired) - free_irq(HostAdapter->IRQ_Channel, HostAdapter); - /* - Release exclusive access to the DMA Channel. - */ - if (HostAdapter->DMA_ChannelAcquired) - free_dma(HostAdapter->DMA_Channel); - /* - Release any allocated memory structs not released elsewhere - */ - if (HostAdapter->MailboxSpace) - pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, - HostAdapter->MailboxSpace, - HostAdapter->MailboxSpaceHandle); - HostAdapter->MailboxSpace = NULL; - HostAdapter->MailboxSpaceHandle = 0; - HostAdapter->MailboxSize = 0; + /* + Release shared access to the IRQ Channel. + */ + if (HostAdapter->IRQ_ChannelAcquired) + free_irq(HostAdapter->IRQ_Channel, HostAdapter); + /* + Release exclusive access to the DMA Channel. + */ + if (HostAdapter->DMA_ChannelAcquired) + free_dma(HostAdapter->DMA_Channel); + /* + Release any allocated memory structs not released elsewhere + */ + if (HostAdapter->MailboxSpace) + pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, HostAdapter->MailboxSpace, HostAdapter->MailboxSpaceHandle); + HostAdapter->MailboxSpace = NULL; + HostAdapter->MailboxSpaceHandle = 0; + HostAdapter->MailboxSize = 0; } @@ -2338,114 +1904,94 @@ static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter) static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { - struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest; - enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest; - enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest; - int TargetID; - /* - Initialize the pointers to the first and last CCBs that are queued for - completion processing. - */ - HostAdapter->FirstCompletedCCB = NULL; - HostAdapter->LastCompletedCCB = NULL; - /* - Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, - Command Successful Flag, Active Commands, and Commands Since Reset - for each Target Device. - */ - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; - HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; - HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; - HostAdapter->ActiveCommands[TargetID] = 0; - HostAdapter->CommandsSinceReset[TargetID] = 0; - } - /* - FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done; - /* - Initialize the Outgoing and Incoming Mailbox pointers. - */ - HostAdapter->MailboxSize = HostAdapter->MailboxCount * - (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox)); - HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, - HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle); - if (HostAdapter->MailboxSpace == NULL) - return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION"); - HostAdapter->FirstOutgoingMailbox = - (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace; - HostAdapter->LastOutgoingMailbox = - HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; - HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->FirstIncomingMailbox = - (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1); - HostAdapter->LastIncomingMailbox = - HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; - HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - - /* - Initialize the Outgoing and Incoming Mailbox structures. - */ - memset(HostAdapter->FirstOutgoingMailbox, 0, - HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox)); - memset(HostAdapter->FirstIncomingMailbox, 0, - HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox)); - /* - Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. - */ - ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; - ExtendedMailboxRequest.BaseMailboxAddress = - (u32) HostAdapter->MailboxSpaceHandle; - if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, - &ExtendedMailboxRequest, - sizeof(ExtendedMailboxRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); - /* - Enable Strict Round Robin Mode if supported by the Host Adapter. In - Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing - Mailbox for each new command, rather than scanning through all the - Outgoing Mailboxes to find any that have new commands in them. Strict - Round Robin Mode is significantly more efficient. - */ - if (HostAdapter->StrictRoundRobinModeSupport) - { - RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; - if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, - &RoundRobinModeRequest, - sizeof(RoundRobinModeRequest), NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); - } - /* - For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB - Format command to allow 32 Logical Units per Target Device. - */ - if (HostAdapter->ExtendedLUNSupport) - { - SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; - if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, - &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), - NULL, 0) < 0) - return BusLogic_Failure(HostAdapter, "SET CCB FORMAT"); - } - /* - Announce Successful Initialization. - */ -Done: - if (!HostAdapter->HostAdapterInitialized) - { - BusLogic_Info("*** %s Initialized Successfully ***\n", - HostAdapter, HostAdapter->FullModelName); - BusLogic_Info("\n", HostAdapter); - } - else BusLogic_Warning("*** %s Initialized Successfully ***\n", - HostAdapter, HostAdapter->FullModelName); - HostAdapter->HostAdapterInitialized = true; - /* - Indicate the Host Adapter Initialization completed successfully. - */ - return true; + struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest; + enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest; + enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest; + int TargetID; + /* + Initialize the pointers to the first and last CCBs that are queued for + completion processing. + */ + HostAdapter->FirstCompletedCCB = NULL; + HostAdapter->LastCompletedCCB = NULL; + /* + Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, + Command Successful Flag, Active Commands, and Commands Since Reset + for each Target Device. + */ + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; + HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; + HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false; + HostAdapter->ActiveCommands[TargetID] = 0; + HostAdapter->CommandsSinceReset[TargetID] = 0; + } + /* + FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + goto Done; + /* + Initialize the Outgoing and Incoming Mailbox pointers. + */ + HostAdapter->MailboxSize = HostAdapter->MailboxCount * (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox)); + HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle); + if (HostAdapter->MailboxSpace == NULL) + return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION"); + HostAdapter->FirstOutgoingMailbox = (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace; + HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; + HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; + HostAdapter->FirstIncomingMailbox = (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1); + HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; + HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; + + /* + Initialize the Outgoing and Incoming Mailbox structures. + */ + memset(HostAdapter->FirstOutgoingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox)); + memset(HostAdapter->FirstIncomingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox)); + /* + Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes. + */ + ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; + ExtendedMailboxRequest.BaseMailboxAddress = (u32) HostAdapter->MailboxSpaceHandle; + if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, &ExtendedMailboxRequest, sizeof(ExtendedMailboxRequest), NULL, 0) < 0) + return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION"); + /* + Enable Strict Round Robin Mode if supported by the Host Adapter. In + Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing + Mailbox for each new command, rather than scanning through all the + Outgoing Mailboxes to find any that have new commands in them. Strict + Round Robin Mode is significantly more efficient. + */ + if (HostAdapter->StrictRoundRobinModeSupport) { + RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; + if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, &RoundRobinModeRequest, sizeof(RoundRobinModeRequest), NULL, 0) < 0) + return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE"); + } + /* + For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB + Format command to allow 32 Logical Units per Target Device. + */ + if (HostAdapter->ExtendedLUNSupport) { + SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; + if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0) + return BusLogic_Failure(HostAdapter, "SET CCB FORMAT"); + } + /* + Announce Successful Initialization. + */ + Done: + if (!HostAdapter->HostAdapterInitialized) { + BusLogic_Info("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName); + BusLogic_Info("\n", HostAdapter); + } else + BusLogic_Warning("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName); + HostAdapter->HostAdapterInitialized = true; + /* + Indicate the Host Adapter Initialization completed successfully. + */ + return true; } @@ -2457,127 +2003,106 @@ Done: static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter *HostAdapter) { - u16 InstalledDevices; - u8 InstalledDevicesID0to7[8]; - struct BusLogic_SetupInformation SetupInformation; - u8 SynchronousPeriod[BusLogic_MaxTargetDevices]; - unsigned char RequestedReplyLength; - int TargetID; - /* - Wait a few seconds between the Host Adapter Hard Reset which initiates - a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get - confused if they receive SCSI Commands too soon after a SCSI Bus Reset. - */ - BusLogic_Delay(HostAdapter->BusSettleTime); - /* - FlashPoint Host Adapters do not provide for Target Device Inquiry. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true; - /* - Inhibit the Target Device Inquiry if requested. - */ - if (HostAdapter->DriverOptions != NULL && - HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) - return true; - /* - Issue the Inquire Target Devices command for host adapters with firmware - version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command - for older host adapters. This is necessary to force Synchronous Transfer - Negotiation so that the Inquire Setup Information and Inquire Synchronous - Period commands will return valid data. The Inquire Target Devices command - is preferable to Inquire Installed Devices ID 0 to 7 since it only probes - Logical Unit 0 of each Target Device. - */ - if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) - { - - /* - * Issue a Inquire Target Devices command. Inquire Target Devices only - * tests Logical Unit 0 of each Target Device unlike the Inquire Installed - * Devices commands which test Logical Units 0 - 7. Two bytes are - * returned, where byte 0 bit 0 set indicates that Target Device 0 exists, - * and so on. - */ - - if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, - &InstalledDevices, sizeof(InstalledDevices)) - != sizeof(InstalledDevices)) - return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->TargetFlags[TargetID].TargetExists = - (InstalledDevices & (1 << TargetID) ? true : false); - } - else - { - - /* - * Issue an Inquire Installed Devices command. For each Target Device, - * a byte is returned where bit 0 set indicates that Logical Unit 0 - * exists, bit 1 set indicates that Logical Unit 1 exists, and so on. - */ - - if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, - NULL, 0, &InstalledDevicesID0to7, - sizeof(InstalledDevicesID0to7)) - != sizeof(InstalledDevicesID0to7)) - return BusLogic_Failure(HostAdapter, - "INQUIRE INSTALLED DEVICES ID 0 TO 7"); - for (TargetID = 0; TargetID < 8; TargetID++) - HostAdapter->TargetFlags[TargetID].TargetExists = - (InstalledDevicesID0to7[TargetID] != 0 ? true : false); - } - /* - Issue the Inquire Setup Information command. - */ - RequestedReplyLength = sizeof(SetupInformation); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SetupInformation, sizeof(SetupInformation)) - != sizeof(SetupInformation)) - return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->SynchronousOffset[TargetID] = - (TargetID < 8 - ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset - : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset); - if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0) - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->TargetFlags[TargetID].WideTransfersActive = - (TargetID < 8 - ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) - ? true : false) - : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8)) - ? true : false)); - /* - Issue the Inquire Synchronous Period command. - */ - if (HostAdapter->FirmwareVersion[0] >= '3') - { - - /* Issue a Inquire Synchronous Period command. For each Target Device, - * a byte is returned which represents the Synchronous Transfer Period - * in units of 10 nanoseconds. - */ - - RequestedReplyLength = sizeof(SynchronousPeriod); - if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, - &RequestedReplyLength, sizeof(RequestedReplyLength), - &SynchronousPeriod, sizeof(SynchronousPeriod)) - != sizeof(SynchronousPeriod)) - return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; - } - else - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) - HostAdapter->SynchronousPeriod[TargetID] = - 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] - .TransferPeriod; - /* - Indicate the Target Device Inquiry completed successfully. - */ - return true; + u16 InstalledDevices; + u8 InstalledDevicesID0to7[8]; + struct BusLogic_SetupInformation SetupInformation; + u8 SynchronousPeriod[BusLogic_MaxTargetDevices]; + unsigned char RequestedReplyLength; + int TargetID; + /* + Wait a few seconds between the Host Adapter Hard Reset which initiates + a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get + confused if they receive SCSI Commands too soon after a SCSI Bus Reset. + */ + BusLogic_Delay(HostAdapter->BusSettleTime); + /* + FlashPoint Host Adapters do not provide for Target Device Inquiry. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + return true; + /* + Inhibit the Target Device Inquiry if requested. + */ + if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry) + return true; + /* + Issue the Inquire Target Devices command for host adapters with firmware + version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command + for older host adapters. This is necessary to force Synchronous Transfer + Negotiation so that the Inquire Setup Information and Inquire Synchronous + Period commands will return valid data. The Inquire Target Devices command + is preferable to Inquire Installed Devices ID 0 to 7 since it only probes + Logical Unit 0 of each Target Device. + */ + if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) { + + /* + * Issue a Inquire Target Devices command. Inquire Target Devices only + * tests Logical Unit 0 of each Target Device unlike the Inquire Installed + * Devices commands which test Logical Units 0 - 7. Two bytes are + * returned, where byte 0 bit 0 set indicates that Target Device 0 exists, + * and so on. + */ + + if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, &InstalledDevices, sizeof(InstalledDevices)) + != sizeof(InstalledDevices)) + return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? true : false); + } else { + + /* + * Issue an Inquire Installed Devices command. For each Target Device, + * a byte is returned where bit 0 set indicates that Logical Unit 0 + * exists, bit 1 set indicates that Logical Unit 1 exists, and so on. + */ + + if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, NULL, 0, &InstalledDevicesID0to7, sizeof(InstalledDevicesID0to7)) + != sizeof(InstalledDevicesID0to7)) + return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7"); + for (TargetID = 0; TargetID < 8; TargetID++) + HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevicesID0to7[TargetID] != 0 ? true : false); + } + /* + Issue the Inquire Setup Information command. + */ + RequestedReplyLength = sizeof(SetupInformation); + if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation)) + != sizeof(SetupInformation)) + return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset : SetupInformation.SynchronousValuesID8to15[TargetID - 8].Offset); + if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0) + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) + ? true : false) + : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID - 8)) + ? true : false)); + /* + Issue the Inquire Synchronous Period command. + */ + if (HostAdapter->FirmwareVersion[0] >= '3') { + + /* Issue a Inquire Synchronous Period command. For each Target Device, + * a byte is returned which represents the Synchronous Transfer Period + * in units of 10 nanoseconds. + */ + + RequestedReplyLength = sizeof(SynchronousPeriod); + if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, &RequestedReplyLength, sizeof(RequestedReplyLength), &SynchronousPeriod, sizeof(SynchronousPeriod)) + != sizeof(SynchronousPeriod)) + return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD"); + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; + } else + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0) + HostAdapter->SynchronousPeriod[TargetID] = 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID] + .TransferPeriod; + /* + Indicate the Target Device Inquiry completed successfully. + */ + return true; } /* @@ -2590,18 +2115,17 @@ static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter */ static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter - *HostAdapter, - struct Scsi_Host *Host) + *HostAdapter, struct Scsi_Host *Host) { - Host->max_id = HostAdapter->MaxTargetDevices; - Host->max_lun = HostAdapter->MaxLogicalUnits; - Host->max_channel = 0; - Host->unique_id = HostAdapter->IO_Address; - Host->this_id = HostAdapter->SCSI_ID; - Host->can_queue = HostAdapter->DriverQueueDepth; - Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; - Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; - Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth; + Host->max_id = HostAdapter->MaxTargetDevices; + Host->max_lun = HostAdapter->MaxLogicalUnits; + Host->max_channel = 0; + Host->unique_id = HostAdapter->IO_Address; + Host->this_id = HostAdapter->SCSI_ID; + Host->can_queue = HostAdapter->DriverQueueDepth; + Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit; + Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired; + Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth; } /* @@ -2614,38 +2138,29 @@ static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter */ static int BusLogic_SlaveConfigure(struct scsi_device *Device) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) Device->host->hostdata; - int TargetID = Device->id; - int QueueDepth = HostAdapter->QueueDepth[TargetID]; - - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) - { - if (QueueDepth == 0) - QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth; - HostAdapter->QueueDepth[TargetID] = QueueDepth; - scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth); - } - else - { - HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); - QueueDepth = HostAdapter->UntaggedQueueDepth; - HostAdapter->QueueDepth[TargetID] = QueueDepth; - scsi_adjust_queue_depth(Device, 0, QueueDepth); - } - QueueDepth = 0; - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - if (HostAdapter->TargetFlags[TargetID].TargetExists) - { - QueueDepth += HostAdapter->QueueDepth[TargetID]; - } - if (QueueDepth > HostAdapter->AllocatedCCBs) - BusLogic_CreateAdditionalCCBs(HostAdapter, - QueueDepth - - HostAdapter->AllocatedCCBs, - false); - return 0; + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Device->host->hostdata; + int TargetID = Device->id; + int QueueDepth = HostAdapter->QueueDepth[TargetID]; + + if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) { + if (QueueDepth == 0) + QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth; + HostAdapter->QueueDepth[TargetID] = QueueDepth; + scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth); + } else { + HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID); + QueueDepth = HostAdapter->UntaggedQueueDepth; + HostAdapter->QueueDepth[TargetID] = QueueDepth; + scsi_adjust_queue_depth(Device, 0, QueueDepth); + } + QueueDepth = 0; + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) + if (HostAdapter->TargetFlags[TargetID].TargetExists) { + QueueDepth += HostAdapter->QueueDepth[TargetID]; + } + if (QueueDepth > HostAdapter->AllocatedCCBs) + BusLogic_CreateAdditionalCCBs(HostAdapter, QueueDepth - HostAdapter->AllocatedCCBs, false); + return 0; } /* @@ -2656,164 +2171,154 @@ static int BusLogic_SlaveConfigure(struct scsi_device *Device) registered. */ -static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemplate) +static int __init BusLogic_init(void) { - int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; - struct BusLogic_HostAdapter *PrototypeHostAdapter; - if (BusLogic_ProbeOptions.NoProbe) return 0; - BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *) - kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), - GFP_ATOMIC); - if (BusLogic_ProbeInfoList == NULL) - { - BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); - return 0; - } - memset(BusLogic_ProbeInfoList, 0, - BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo)); - PrototypeHostAdapter = (struct BusLogic_HostAdapter *) - kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC); - if (PrototypeHostAdapter == NULL) - { - kfree(BusLogic_ProbeInfoList); - BusLogic_Error("BusLogic: Unable to allocate Prototype " - "Host Adapter\n", NULL); - return 0; - } - memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); + int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex; + struct BusLogic_HostAdapter *PrototypeHostAdapter; + #ifdef MODULE - if (BusLogic != NULL) - BusLogic_Setup(BusLogic); + if (BusLogic) + BusLogic_Setup(BusLogic); #endif - BusLogic_InitializeProbeInfoList(PrototypeHostAdapter); - for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) - { - struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex]; - struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; - struct Scsi_Host *Host; - if (ProbeInfo->IO_Address == 0) continue; - memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); - HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType; - HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType; - HostAdapter->IO_Address = ProbeInfo->IO_Address; - HostAdapter->PCI_Address = ProbeInfo->PCI_Address; - HostAdapter->Bus = ProbeInfo->Bus; - HostAdapter->Device = ProbeInfo->Device; - HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; - HostAdapter->AddressCount = - BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; - /* - Probe the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue; - /* - Hard Reset the Host Adapter. If unsuccessful, abort further - initialization. - */ - if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue; - /* - Check the Host Adapter. If unsuccessful, abort further initialization. - */ - if (!BusLogic_CheckHostAdapter(HostAdapter)) continue; - /* - Initialize the Driver Options field if provided. - */ - if (DriverOptionsIndex < BusLogic_DriverOptionsCount) - HostAdapter->DriverOptions = - &BusLogic_DriverOptions[DriverOptionsIndex++]; - /* - Announce the Driver Version and Date, Author's Name, Copyright Notice, - and Electronic Mail Address. - */ - BusLogic_AnnounceDriver(HostAdapter); - /* - Register usage of the I/O Address range. From this point onward, any - failure will be assumed to be due to a problem with the Host Adapter, - rather than due to having mistakenly identified this port as belonging - to a BusLogic Host Adapter. The I/O Address range will not be - released, thereby preventing it from being incorrectly identified as - any other type of Host Adapter. - */ - if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, - "BusLogic")) continue; - /* - Register the SCSI Host structure. - */ - - Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter)); - if(Host==NULL) - { - release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); - continue; - } - HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata; - memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter)); - HostAdapter->SCSI_Host = Host; - HostAdapter->HostNumber = Host->host_no; - /* - Add Host Adapter to the end of the list of registered BusLogic - Host Adapters. - */ - BusLogic_RegisterHostAdapter(HostAdapter); - /* - Read the Host Adapter Configuration, Configure the Host Adapter, - Acquire the System Resources necessary to use the Host Adapter, then - Create the Initial CCBs, Initialize the Host Adapter, and finally - perform Target Device Inquiry. - */ - if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && - BusLogic_ReportHostAdapterConfiguration(HostAdapter) && - BusLogic_AcquireResources(HostAdapter) && - BusLogic_CreateInitialCCBs(HostAdapter) && - BusLogic_InitializeHostAdapter(HostAdapter) && - BusLogic_TargetDeviceInquiry(HostAdapter)) - { - /* - Initialization has been completed successfully. Release and - re-register usage of the I/O Address range so that the Model - Name of the Host Adapter will appear, and initialize the SCSI - Host structure. - */ - release_region(HostAdapter->IO_Address, - HostAdapter->AddressCount); - if(!request_region(HostAdapter->IO_Address, - HostAdapter->AddressCount, - HostAdapter->FullModelName)) { - printk(KERN_WARNING "BusLogic: Release and re-register of " - "port 0x%04lx failed \n", - (unsigned long)HostAdapter->IO_Address); - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - BusLogic_UnregisterHostAdapter(HostAdapter); - scsi_host_put(Host); - } - else { - BusLogic_InitializeHostStructure(HostAdapter, Host); - scsi_add_host(Host, NULL); - scsi_scan_host(Host); - BusLogicHostAdapterCount++; - } - } - else - { - /* - An error occurred during Host Adapter Configuration Querying, Host - Adapter Configuration, Resource Acquisition, CCB Creation, Host - Adapter Initialization, or Target Device Inquiry, so remove Host - Adapter from the list of registered BusLogic Host Adapters, destroy - the CCBs, Release the System Resources, and Unregister the SCSI - Host. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - BusLogic_UnregisterHostAdapter(HostAdapter); - scsi_host_put(Host); + + if (BusLogic_ProbeOptions.NoProbe) + return -ENODEV; + BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *) + kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC); + if (BusLogic_ProbeInfoList == NULL) { + BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); + return -ENOMEM; + } + memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo)); + PrototypeHostAdapter = (struct BusLogic_HostAdapter *) + kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC); + if (PrototypeHostAdapter == NULL) { + kfree(BusLogic_ProbeInfoList); + BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL); + return -ENOMEM; + } + memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); +#ifdef MODULE + if (BusLogic != NULL) + BusLogic_Setup(BusLogic); +#endif + BusLogic_InitializeProbeInfoList(PrototypeHostAdapter); + for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) { + struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex]; + struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter; + struct Scsi_Host *Host; + if (ProbeInfo->IO_Address == 0) + continue; + memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); + HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType; + HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType; + HostAdapter->IO_Address = ProbeInfo->IO_Address; + HostAdapter->PCI_Address = ProbeInfo->PCI_Address; + HostAdapter->Bus = ProbeInfo->Bus; + HostAdapter->Device = ProbeInfo->Device; + HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; + HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; + /* + Probe the Host Adapter. If unsuccessful, abort further initialization. + */ + if (!BusLogic_ProbeHostAdapter(HostAdapter)) + continue; + /* + Hard Reset the Host Adapter. If unsuccessful, abort further + initialization. + */ + if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) + continue; + /* + Check the Host Adapter. If unsuccessful, abort further initialization. + */ + if (!BusLogic_CheckHostAdapter(HostAdapter)) + continue; + /* + Initialize the Driver Options field if provided. + */ + if (DriverOptionsIndex < BusLogic_DriverOptionsCount) + HostAdapter->DriverOptions = &BusLogic_DriverOptions[DriverOptionsIndex++]; + /* + Announce the Driver Version and Date, Author's Name, Copyright Notice, + and Electronic Mail Address. + */ + BusLogic_AnnounceDriver(HostAdapter); + /* + Register usage of the I/O Address range. From this point onward, any + failure will be assumed to be due to a problem with the Host Adapter, + rather than due to having mistakenly identified this port as belonging + to a BusLogic Host Adapter. The I/O Address range will not be + released, thereby preventing it from being incorrectly identified as + any other type of Host Adapter. + */ + if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic")) + continue; + /* + Register the SCSI Host structure. + */ + + Host = scsi_host_alloc(&Bus_Logic_template, sizeof(struct BusLogic_HostAdapter)); + if (Host == NULL) { + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); + continue; + } + HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata; + memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter)); + HostAdapter->SCSI_Host = Host; + HostAdapter->HostNumber = Host->host_no; + /* + Add Host Adapter to the end of the list of registered BusLogic + Host Adapters. + */ + list_add_tail(&HostAdapter->host_list, &BusLogic_host_list); + + /* + Read the Host Adapter Configuration, Configure the Host Adapter, + Acquire the System Resources necessary to use the Host Adapter, then + Create the Initial CCBs, Initialize the Host Adapter, and finally + perform Target Device Inquiry. + */ + if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && + BusLogic_ReportHostAdapterConfiguration(HostAdapter) && BusLogic_AcquireResources(HostAdapter) && BusLogic_CreateInitialCCBs(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter) && BusLogic_TargetDeviceInquiry(HostAdapter)) { + /* + Initialization has been completed successfully. Release and + re-register usage of the I/O Address range so that the Model + Name of the Host Adapter will appear, and initialize the SCSI + Host structure. + */ + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); + if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, HostAdapter->FullModelName)) { + printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address); + BusLogic_DestroyCCBs(HostAdapter); + BusLogic_ReleaseResources(HostAdapter); + list_del(&HostAdapter->host_list); + scsi_host_put(Host); + } else { + BusLogic_InitializeHostStructure(HostAdapter, Host); + scsi_add_host(Host, NULL); + scsi_scan_host(Host); + BusLogicHostAdapterCount++; + } + } else { + /* + An error occurred during Host Adapter Configuration Querying, Host + Adapter Configuration, Resource Acquisition, CCB Creation, Host + Adapter Initialization, or Target Device Inquiry, so remove Host + Adapter from the list of registered BusLogic Host Adapters, destroy + the CCBs, Release the System Resources, and Unregister the SCSI + Host. + */ + BusLogic_DestroyCCBs(HostAdapter); + BusLogic_ReleaseResources(HostAdapter); + list_del(&HostAdapter->host_list); + scsi_host_put(Host); + } } - } - kfree(PrototypeHostAdapter); - kfree(BusLogic_ProbeInfoList); - BusLogic_ProbeInfoList = NULL; - return BusLogicHostAdapterCount; + kfree(PrototypeHostAdapter); + kfree(BusLogic_ProbeInfoList); + BusLogic_ProbeInfoList = NULL; + return 0; } @@ -2823,31 +2328,35 @@ static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemp unregisters the BusLogic Host Adapter. */ -static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host) +static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) Host->hostdata; - /* - FlashPoint Host Adapters must first be released by the FlashPoint - SCCB Manager. - */ - if (BusLogic_FlashPointHostAdapterP(HostAdapter)) - FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle); - /* - Destroy the CCBs and release any system resources acquired to - support Host Adapter. - */ - BusLogic_DestroyCCBs(HostAdapter); - BusLogic_ReleaseResources(HostAdapter); - /* - Release usage of the I/O Address range. - */ - release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); - /* - Remove Host Adapter from the list of registered BusLogic Host Adapters. - */ - BusLogic_UnregisterHostAdapter(HostAdapter); - return 0; + struct Scsi_Host *Host = HostAdapter->SCSI_Host; + + scsi_remove_host(Host); + + /* + FlashPoint Host Adapters must first be released by the FlashPoint + SCCB Manager. + */ + if (BusLogic_FlashPointHostAdapterP(HostAdapter)) + FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle); + /* + Destroy the CCBs and release any system resources acquired to + support Host Adapter. + */ + BusLogic_DestroyCCBs(HostAdapter); + BusLogic_ReleaseResources(HostAdapter); + /* + Release usage of the I/O Address range. + */ + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); + /* + Remove Host Adapter from the list of registered BusLogic Host Adapters. + */ + list_del(&HostAdapter->host_list); + + scsi_host_put(Host); + return 0; } @@ -2857,20 +2366,17 @@ static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host) static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB) { - struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter; - CCB->Status = BusLogic_CCB_Completed; - CCB->Next = NULL; - if (HostAdapter->FirstCompletedCCB == NULL) - { - HostAdapter->FirstCompletedCCB = CCB; - HostAdapter->LastCompletedCCB = CCB; - } - else - { - HostAdapter->LastCompletedCCB->Next = CCB; - HostAdapter->LastCompletedCCB = CCB; - } - HostAdapter->ActiveCommands[CCB->TargetID]--; + struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter; + CCB->Status = BusLogic_CCB_Completed; + CCB->Next = NULL; + if (HostAdapter->FirstCompletedCCB == NULL) { + HostAdapter->FirstCompletedCCB = CCB; + HostAdapter->LastCompletedCCB = CCB; + } else { + HostAdapter->LastCompletedCCB->Next = CCB; + HostAdapter->LastCompletedCCB = CCB; + } + HostAdapter->ActiveCommands[CCB->TargetID]--; } @@ -2879,57 +2385,50 @@ static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB) the Host Adapter Status and Target Device Status. */ -static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, - enum BusLogic_HostAdapterStatus - HostAdapterStatus, - enum BusLogic_TargetDeviceStatus - TargetDeviceStatus) +static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_HostAdapterStatus HostAdapterStatus, enum BusLogic_TargetDeviceStatus TargetDeviceStatus) { - int HostStatus; - switch (HostAdapterStatus) - { - case BusLogic_CommandCompletedNormally: - case BusLogic_LinkedCommandCompleted: - case BusLogic_LinkedCommandCompletedWithFlag: - HostStatus = DID_OK; - break; - case BusLogic_SCSISelectionTimeout: - HostStatus = DID_TIME_OUT; - break; - case BusLogic_InvalidOutgoingMailboxActionCode: - case BusLogic_InvalidCommandOperationCode: - case BusLogic_InvalidCommandParameter: - BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", - HostAdapter, HostAdapterStatus); - case BusLogic_DataUnderRun: - case BusLogic_DataOverRun: - case BusLogic_UnexpectedBusFree: - case BusLogic_LinkedCCBhasInvalidLUN: - case BusLogic_AutoRequestSenseFailed: - case BusLogic_TaggedQueuingMessageRejected: - case BusLogic_UnsupportedMessageReceived: - case BusLogic_HostAdapterHardwareFailed: - case BusLogic_TargetDeviceReconnectedImproperly: - case BusLogic_AbortQueueGenerated: - case BusLogic_HostAdapterSoftwareError: - case BusLogic_HostAdapterHardwareTimeoutError: - case BusLogic_SCSIParityErrorDetected: - HostStatus = DID_ERROR; - break; - case BusLogic_InvalidBusPhaseRequested: - case BusLogic_TargetFailedResponseToATN: - case BusLogic_HostAdapterAssertedRST: - case BusLogic_OtherDeviceAssertedRST: - case BusLogic_HostAdapterAssertedBusDeviceReset: - HostStatus = DID_RESET; - break; - default: - BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", - HostAdapter, HostAdapterStatus); - HostStatus = DID_ERROR; - break; - } - return (HostStatus << 16) | TargetDeviceStatus; + int HostStatus; + switch (HostAdapterStatus) { + case BusLogic_CommandCompletedNormally: + case BusLogic_LinkedCommandCompleted: + case BusLogic_LinkedCommandCompletedWithFlag: + HostStatus = DID_OK; + break; + case BusLogic_SCSISelectionTimeout: + HostStatus = DID_TIME_OUT; + break; + case BusLogic_InvalidOutgoingMailboxActionCode: + case BusLogic_InvalidCommandOperationCode: + case BusLogic_InvalidCommandParameter: + BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", HostAdapter, HostAdapterStatus); + case BusLogic_DataUnderRun: + case BusLogic_DataOverRun: + case BusLogic_UnexpectedBusFree: + case BusLogic_LinkedCCBhasInvalidLUN: + case BusLogic_AutoRequestSenseFailed: + case BusLogic_TaggedQueuingMessageRejected: + case BusLogic_UnsupportedMessageReceived: + case BusLogic_HostAdapterHardwareFailed: + case BusLogic_TargetDeviceReconnectedImproperly: + case BusLogic_AbortQueueGenerated: + case BusLogic_HostAdapterSoftwareError: + case BusLogic_HostAdapterHardwareTimeoutError: + case BusLogic_SCSIParityErrorDetected: + HostStatus = DID_ERROR; + break; + case BusLogic_InvalidBusPhaseRequested: + case BusLogic_TargetFailedResponseToATN: + case BusLogic_HostAdapterAssertedRST: + case BusLogic_OtherDeviceAssertedRST: + case BusLogic_HostAdapterAssertedBusDeviceReset: + HostStatus = DID_RESET; + break; + default: + BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", HostAdapter, HostAdapterStatus); + HostStatus = DID_ERROR; + break; + } + return (HostStatus << 16) | TargetDeviceStatus; } @@ -2940,62 +2439,51 @@ static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdapter) { - /* - Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving - any completed CCBs for further processing. It is essential that for each - CCB and SCSI Command issued, command completion processing is performed - exactly once. Therefore, only Incoming Mailboxes with completion code - Command Completed Without Error, Command Completed With Error, or Command - Aborted At Host Request are saved for completion processing. When an - Incoming Mailbox has a completion code of Aborted Command Not Found, the - CCB had already completed or been aborted before the current Abort request - was processed, and so completion processing has already occurred and no - further action should be taken. - */ - struct BusLogic_IncomingMailbox *NextIncomingMailbox = - HostAdapter->NextIncomingMailbox; - enum BusLogic_CompletionCode CompletionCode; - while ((CompletionCode = NextIncomingMailbox->CompletionCode) != - BusLogic_IncomingMailboxFree) - { - /* - We are only allowed to do this because we limit our architectures we - run on to machines where bus_to_virt() actually works. There *needs* - to be a dma_addr_to_virt() in the new PCI DMA mapping interface to - replace bus_to_virt() or else this code is going to become very - innefficient. - */ - struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) - Bus_to_Virtual(NextIncomingMailbox->CCB); - if (CompletionCode != BusLogic_AbortedCommandNotFound) - { - if (CCB->Status == BusLogic_CCB_Active || - CCB->Status == BusLogic_CCB_Reset) - { - /* - Save the Completion Code for this CCB and queue the CCB - for completion processing. - */ - CCB->CompletionCode = CompletionCode; - BusLogic_QueueCompletedCCB(CCB); - } - else - { - /* - If a CCB ever appears in an Incoming Mailbox and is not marked - as status Active or Reset, then there is most likely a bug in - the Host Adapter firmware. - */ - BusLogic_Warning("Illegal CCB #%ld status %d in " - "Incoming Mailbox\n", HostAdapter, - CCB->SerialNumber, CCB->Status); - } + /* + Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving + any completed CCBs for further processing. It is essential that for each + CCB and SCSI Command issued, command completion processing is performed + exactly once. Therefore, only Incoming Mailboxes with completion code + Command Completed Without Error, Command Completed With Error, or Command + Aborted At Host Request are saved for completion processing. When an + Incoming Mailbox has a completion code of Aborted Command Not Found, the + CCB had already completed or been aborted before the current Abort request + was processed, and so completion processing has already occurred and no + further action should be taken. + */ + struct BusLogic_IncomingMailbox *NextIncomingMailbox = HostAdapter->NextIncomingMailbox; + enum BusLogic_CompletionCode CompletionCode; + while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) { + /* + We are only allowed to do this because we limit our architectures we + run on to machines where bus_to_virt() actually works. There *needs* + to be a dma_addr_to_virt() in the new PCI DMA mapping interface to + replace bus_to_virt() or else this code is going to become very + innefficient. + */ + struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) Bus_to_Virtual(NextIncomingMailbox->CCB); + if (CompletionCode != BusLogic_AbortedCommandNotFound) { + if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) { + /* + Save the Completion Code for this CCB and queue the CCB + for completion processing. + */ + CCB->CompletionCode = CompletionCode; + BusLogic_QueueCompletedCCB(CCB); + } else { + /* + If a CCB ever appears in an Incoming Mailbox and is not marked + as status Active or Reset, then there is most likely a bug in + the Host Adapter firmware. + */ + BusLogic_Warning("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", HostAdapter, CCB->SerialNumber, CCB->Status); + } + } + NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; + if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) + NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; } - NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; - if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) - NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; - } - HostAdapter->NextIncomingMailbox = NextIncomingMailbox; + HostAdapter->NextIncomingMailbox = NextIncomingMailbox; } @@ -3008,153 +2496,126 @@ static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdap static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapter) { - if (HostAdapter->ProcessCompletedCCBsActive) return; - HostAdapter->ProcessCompletedCCBsActive = true; - while (HostAdapter->FirstCompletedCCB != NULL) - { - struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB; - struct scsi_cmnd *Command = CCB->Command; - HostAdapter->FirstCompletedCCB = CCB->Next; - if (HostAdapter->FirstCompletedCCB == NULL) - HostAdapter->LastCompletedCCB = NULL; - /* - Process the Completed CCB. - */ - if (CCB->Opcode == BusLogic_BusDeviceReset) - { - int TargetID = CCB->TargetID; - BusLogic_Warning("Bus Device Reset CCB #%ld to Target " - "%d Completed\n", HostAdapter, - CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); - HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; - HostAdapter->CommandsSinceReset[TargetID] = 0; - HostAdapter->LastResetCompleted[TargetID] = jiffies; - /* - Place CCB back on the Host Adapter's free list. - */ - BusLogic_DeallocateCCB(CCB); -#if 0 /* this needs to be redone different for new EH */ - /* - Bus Device Reset CCBs have the Command field non-NULL only when a - Bus Device Reset was requested for a Command that did not have a - currently active CCB in the Host Adapter (i.e., a Synchronous - Bus Device Reset), and hence would not have its Completion Routine - called otherwise. - */ - while (Command != NULL) - { - struct scsi_cmnd *NextCommand = Command->reset_chain; - Command->reset_chain = NULL; - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - Command = NextCommand; - } + if (HostAdapter->ProcessCompletedCCBsActive) + return; + HostAdapter->ProcessCompletedCCBsActive = true; + while (HostAdapter->FirstCompletedCCB != NULL) { + struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB; + struct scsi_cmnd *Command = CCB->Command; + HostAdapter->FirstCompletedCCB = CCB->Next; + if (HostAdapter->FirstCompletedCCB == NULL) + HostAdapter->LastCompletedCCB = NULL; + /* + Process the Completed CCB. + */ + if (CCB->Opcode == BusLogic_BusDeviceReset) { + int TargetID = CCB->TargetID; + BusLogic_Warning("Bus Device Reset CCB #%ld to Target " "%d Completed\n", HostAdapter, CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); + HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false; + HostAdapter->CommandsSinceReset[TargetID] = 0; + HostAdapter->LastResetCompleted[TargetID] = jiffies; + /* + Place CCB back on the Host Adapter's free list. + */ + BusLogic_DeallocateCCB(CCB); +#if 0 /* this needs to be redone different for new EH */ + /* + Bus Device Reset CCBs have the Command field non-NULL only when a + Bus Device Reset was requested for a Command that did not have a + currently active CCB in the Host Adapter (i.e., a Synchronous + Bus Device Reset), and hence would not have its Completion Routine + called otherwise. + */ + while (Command != NULL) { + struct scsi_cmnd *NextCommand = Command->reset_chain; + Command->reset_chain = NULL; + Command->result = DID_RESET << 16; + Command->scsi_done(Command); + Command = NextCommand; + } #endif - /* - Iterate over the CCBs for this Host Adapter performing completion - processing for any CCBs marked as Reset for this Target. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) - { - Command = CCB->Command; - BusLogic_DeallocateCCB(CCB); - HostAdapter->ActiveCommands[TargetID]--; - Command->result = DID_RESET << 16; - Command->scsi_done(Command); - } - HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; - } - else - { - /* - Translate the Completion Code, Host Adapter Status, and Target - Device Status into a SCSI Subsystem Result Code. - */ - switch (CCB->CompletionCode) - { - case BusLogic_IncomingMailboxFree: - case BusLogic_AbortedCommandNotFound: - case BusLogic_InvalidCCB: - BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", - HostAdapter, CCB->SerialNumber, CCB->TargetID); - break; - case BusLogic_CommandCompletedWithoutError: - HostAdapter->TargetStatistics[CCB->TargetID] - .CommandsCompleted++; - HostAdapter->TargetFlags[CCB->TargetID] - .CommandSuccessfulFlag = true; - Command->result = DID_OK << 16; - break; - case BusLogic_CommandAbortedAtHostRequest: - BusLogic_Warning("CCB #%ld to Target %d Aborted\n", - HostAdapter, CCB->SerialNumber, CCB->TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[CCB->TargetID] - .CommandAbortsCompleted); - Command->result = DID_ABORT << 16; - break; - case BusLogic_CommandCompletedWithError: - Command->result = - BusLogic_ComputeResultCode(HostAdapter, - CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) - { - HostAdapter->TargetStatistics[CCB->TargetID] - .CommandsCompleted++; - if (BusLogic_GlobalOptions.TraceErrors) - { - int i; - BusLogic_Notice("CCB #%ld Target %d: Result %X Host " - "Adapter Status %02X " - "Target Status %02X\n", - HostAdapter, CCB->SerialNumber, - CCB->TargetID, Command->result, - CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - BusLogic_Notice("CDB ", HostAdapter); - for (i = 0; i < CCB->CDB_Length; i++) - BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); - BusLogic_Notice("\n", HostAdapter); - BusLogic_Notice("Sense ", HostAdapter); - for (i = 0; i < CCB->SenseDataLength; i++) - BusLogic_Notice(" %02X", HostAdapter, - Command->sense_buffer[i]); - BusLogic_Notice("\n", HostAdapter); - } + /* + Iterate over the CCBs for this Host Adapter performing completion + processing for any CCBs marked as Reset for this Target. + */ + for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) + if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) { + Command = CCB->Command; + BusLogic_DeallocateCCB(CCB); + HostAdapter->ActiveCommands[TargetID]--; + Command->result = DID_RESET << 16; + Command->scsi_done(Command); + } + HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; + } else { + /* + Translate the Completion Code, Host Adapter Status, and Target + Device Status into a SCSI Subsystem Result Code. + */ + switch (CCB->CompletionCode) { + case BusLogic_IncomingMailboxFree: + case BusLogic_AbortedCommandNotFound: + case BusLogic_InvalidCCB: + BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", HostAdapter, CCB->SerialNumber, CCB->TargetID); + break; + case BusLogic_CommandCompletedWithoutError: + HostAdapter->TargetStatistics[CCB->TargetID] + .CommandsCompleted++; + HostAdapter->TargetFlags[CCB->TargetID] + .CommandSuccessfulFlag = true; + Command->result = DID_OK << 16; + break; + case BusLogic_CommandAbortedAtHostRequest: + BusLogic_Warning("CCB #%ld to Target %d Aborted\n", HostAdapter, CCB->SerialNumber, CCB->TargetID); + BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID] + .CommandAbortsCompleted); + Command->result = DID_ABORT << 16; + break; + case BusLogic_CommandCompletedWithError: + Command->result = BusLogic_ComputeResultCode(HostAdapter, CCB->HostAdapterStatus, CCB->TargetDeviceStatus); + if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) { + HostAdapter->TargetStatistics[CCB->TargetID] + .CommandsCompleted++; + if (BusLogic_GlobalOptions.TraceErrors) { + int i; + BusLogic_Notice("CCB #%ld Target %d: Result %X Host " + "Adapter Status %02X " "Target Status %02X\n", HostAdapter, CCB->SerialNumber, CCB->TargetID, Command->result, CCB->HostAdapterStatus, CCB->TargetDeviceStatus); + BusLogic_Notice("CDB ", HostAdapter); + for (i = 0; i < CCB->CDB_Length; i++) + BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); + BusLogic_Notice("\n", HostAdapter); + BusLogic_Notice("Sense ", HostAdapter); + for (i = 0; i < CCB->SenseDataLength; i++) + BusLogic_Notice(" %02X", HostAdapter, Command->sense_buffer[i]); + BusLogic_Notice("\n", HostAdapter); + } + } + break; + } + /* + When an INQUIRY command completes normally, save the + CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit + Wide Data Transfers Supported) bits. + */ + if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID]; + struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer; + TargetFlags->TargetExists = true; + TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; + TargetFlags->WideTransfersSupported = InquiryResult->WBus16; + } + /* + Place CCB back on the Host Adapter's free list. + */ + BusLogic_DeallocateCCB(CCB); + /* + Call the SCSI Command Completion Routine. + */ + Command->scsi_done(Command); } - break; - } - /* - When an INQUIRY command completes normally, save the - CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit - Wide Data Transfers Supported) bits. - */ - if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && - CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) - { - struct BusLogic_TargetFlags *TargetFlags = - &HostAdapter->TargetFlags[CCB->TargetID]; - struct SCSI_Inquiry *InquiryResult = - (struct SCSI_Inquiry *) Command->request_buffer; - TargetFlags->TargetExists = true; - TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; - TargetFlags->WideTransfersSupported = InquiryResult->WBus16; - } - /* - Place CCB back on the Host Adapter's free list. - */ - BusLogic_DeallocateCCB(CCB); - /* - Call the SCSI Command Completion Routine. - */ - Command->scsi_done(Command); } - } - HostAdapter->ProcessCompletedCCBsActive = false; + HostAdapter->ProcessCompletedCCBsActive = false; } @@ -3163,97 +2624,83 @@ static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapt Adapters. */ -static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - struct pt_regs *InterruptRegisters) +static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, struct pt_regs *InterruptRegisters) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) DeviceIdentifier; - unsigned long ProcessorFlags; - /* - Acquire exclusive access to Host Adapter. - */ - BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags); - /* - Handle Interrupts appropriately for each Host Adapter type. - */ - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - union BusLogic_InterruptRegister InterruptRegister; - /* - Read the Host Adapter Interrupt Register. - */ - InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - if (InterruptRegister.ir.InterruptValid) - { - /* - Acknowledge the interrupt and reset the Host Adapter - Interrupt Register. - */ - BusLogic_InterruptReset(HostAdapter); - /* - Process valid External SCSI Bus Reset and Incoming Mailbox - Loaded Interrupts. Command Complete Interrupts are noted, - and Outgoing Mailbox Available Interrupts are ignored, as - they are never enabled. - */ - if (InterruptRegister.ir.ExternalBusReset) - HostAdapter->HostAdapterExternalReset = true; - else if (InterruptRegister.ir.IncomingMailboxLoaded) - BusLogic_ScanIncomingMailboxes(HostAdapter); - else if (InterruptRegister.ir.CommandComplete) - HostAdapter->HostAdapterCommandCompleted = true; + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier; + unsigned long ProcessorFlags; + /* + Acquire exclusive access to Host Adapter. + */ + spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags); + /* + Handle Interrupts appropriately for each Host Adapter type. + */ + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { + union BusLogic_InterruptRegister InterruptRegister; + /* + Read the Host Adapter Interrupt Register. + */ + InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); + if (InterruptRegister.ir.InterruptValid) { + /* + Acknowledge the interrupt and reset the Host Adapter + Interrupt Register. + */ + BusLogic_InterruptReset(HostAdapter); + /* + Process valid External SCSI Bus Reset and Incoming Mailbox + Loaded Interrupts. Command Complete Interrupts are noted, + and Outgoing Mailbox Available Interrupts are ignored, as + they are never enabled. + */ + if (InterruptRegister.ir.ExternalBusReset) + HostAdapter->HostAdapterExternalReset = true; + else if (InterruptRegister.ir.IncomingMailboxLoaded) + BusLogic_ScanIncomingMailboxes(HostAdapter); + else if (InterruptRegister.ir.CommandComplete) + HostAdapter->HostAdapterCommandCompleted = true; + } + } else { + /* + Check if there is a pending interrupt for this Host Adapter. + */ + if (FlashPoint_InterruptPending(HostAdapter->CardHandle)) + switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) { + case FlashPoint_NormalInterrupt: + break; + case FlashPoint_ExternalBusReset: + HostAdapter->HostAdapterExternalReset = true; + break; + case FlashPoint_InternalError: + BusLogic_Warning("Internal FlashPoint Error detected" " - Resetting Host Adapter\n", HostAdapter); + HostAdapter->HostAdapterInternalError = true; + break; + } } - } - else - { - /* - Check if there is a pending interrupt for this Host Adapter. - */ - if (FlashPoint_InterruptPending(HostAdapter->CardHandle)) - switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) - { - case FlashPoint_NormalInterrupt: - break; - case FlashPoint_ExternalBusReset: - HostAdapter->HostAdapterExternalReset = true; - break; - case FlashPoint_InternalError: - BusLogic_Warning("Internal FlashPoint Error detected" - " - Resetting Host Adapter\n", HostAdapter); - HostAdapter->HostAdapterInternalError = true; - break; - } - } - /* - Process any completed CCBs. - */ - if (HostAdapter->FirstCompletedCCB != NULL) - BusLogic_ProcessCompletedCCBs(HostAdapter); - /* - Reset the Host Adapter if requested. - */ - if (HostAdapter->HostAdapterExternalReset) - { - BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", - HostAdapter, HostAdapter->FullModelName); - BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); - BusLogic_ResetHostAdapter(HostAdapter, false); - HostAdapter->HostAdapterExternalReset = false; - } - else if (HostAdapter->HostAdapterInternalError) - { - BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", - HostAdapter, HostAdapter->FullModelName); - BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); - BusLogic_ResetHostAdapter(HostAdapter, true); - HostAdapter->HostAdapterInternalError = false; - } - /* - Release exclusive access to Host Adapter. - */ - BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags); - return IRQ_HANDLED; + /* + Process any completed CCBs. + */ + if (HostAdapter->FirstCompletedCCB != NULL) + BusLogic_ProcessCompletedCCBs(HostAdapter); + /* + Reset the Host Adapter if requested. + */ + if (HostAdapter->HostAdapterExternalReset) { + BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", HostAdapter, HostAdapter->FullModelName); + BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); + BusLogic_ResetHostAdapter(HostAdapter, false); + HostAdapter->HostAdapterExternalReset = false; + } else if (HostAdapter->HostAdapterInternalError) { + BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", HostAdapter, HostAdapter->FullModelName); + BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); + BusLogic_ResetHostAdapter(HostAdapter, true); + HostAdapter->HostAdapterInternalError = false; + } + /* + Release exclusive access to Host Adapter. + */ + spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags); + return IRQ_HANDLED; } @@ -3264,43 +2711,38 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, */ static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter - *HostAdapter, - enum BusLogic_ActionCode ActionCode, - struct BusLogic_CCB *CCB) + *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB) { - struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; - NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; - if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) - { - CCB->Status = BusLogic_CCB_Active; - /* - The CCB field must be written before the Action Code field since - the Host Adapter is operating asynchronously and the locking code - does not protect against simultaneous access by the Host Adapter. - */ - NextOutgoingMailbox->CCB = CCB->DMA_Handle; - NextOutgoingMailbox->ActionCode = ActionCode; - BusLogic_StartMailboxCommand(HostAdapter); - if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) - NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; - HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; - if (ActionCode == BusLogic_MailboxStartCommand) - { - HostAdapter->ActiveCommands[CCB->TargetID]++; - if (CCB->Opcode != BusLogic_BusDeviceReset) - HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; + struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; + NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; + if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) { + CCB->Status = BusLogic_CCB_Active; + /* + The CCB field must be written before the Action Code field since + the Host Adapter is operating asynchronously and the locking code + does not protect against simultaneous access by the Host Adapter. + */ + NextOutgoingMailbox->CCB = CCB->DMA_Handle; + NextOutgoingMailbox->ActionCode = ActionCode; + BusLogic_StartMailboxCommand(HostAdapter); + if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) + NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; + HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; + if (ActionCode == BusLogic_MailboxStartCommand) { + HostAdapter->ActiveCommands[CCB->TargetID]++; + if (CCB->Opcode != BusLogic_BusDeviceReset) + HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; + } + return true; } - return true; - } - return false; + return false; } /* Error Handling (EH) support */ -static int BusLogic_host_reset(Scsi_Cmnd *SCpnt) +static int BusLogic_host_reset(struct scsi_cmnd * SCpnt) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata; + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata; unsigned int id = SCpnt->device->id; struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id]; @@ -3314,237 +2756,193 @@ static int BusLogic_host_reset(Scsi_Cmnd *SCpnt) Outgoing Mailbox for execution by the associated Host Adapter. */ -static int BusLogic_QueueCommand(struct scsi_cmnd *Command, - void (*CompletionRoutine)(struct scsi_cmnd *)) +static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRoutine) (struct scsi_cmnd *)) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) Command->device->host->hostdata; - struct BusLogic_TargetFlags *TargetFlags = - &HostAdapter->TargetFlags[Command->device->id]; - struct BusLogic_TargetStatistics *TargetStatistics = - HostAdapter->TargetStatistics; - unsigned char *CDB = Command->cmnd; - int CDB_Length = Command->cmd_len; - int TargetID = Command->device->id; - int LogicalUnit = Command->device->lun; - void *BufferPointer = Command->request_buffer; - int BufferLength = Command->request_bufflen; - int SegmentCount = Command->use_sg; - struct BusLogic_CCB *CCB; - /* - SCSI REQUEST_SENSE commands will be executed automatically by the Host - Adapter for any errors, so they should not be executed explicitly unless - the Sense Data is zero indicating that no error occurred. - */ - if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) - { - Command->result = DID_OK << 16; - CompletionRoutine(Command); - return 0; - } - /* - Allocate a CCB from the Host Adapter's free list. In the unlikely event - that there are none available and memory allocation fails, wait 1 second - and try again. If that fails, the Host Adapter is probably hung so signal - an error as a Host Adapter Hard Reset should be initiated soon. - */ - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) - { - BusLogic_ReleaseHostAdapterLock(HostAdapter); - BusLogic_Delay(1); - BusLogic_AcquireHostAdapterLock(HostAdapter); - CCB = BusLogic_AllocateCCB(HostAdapter); - if (CCB == NULL) - { - Command->result = DID_ERROR << 16; - CompletionRoutine(Command); - return 0; - } - } - /* - Initialize the fields in the BusLogic Command Control Block (CCB). - */ - if (SegmentCount == 0 && BufferLength != 0) - { - CCB->Opcode = BusLogic_InitiatorCCB; - CCB->DataLength = BufferLength; - CCB->DataPointer = - pci_map_single(HostAdapter->PCI_Device, BufferPointer, BufferLength, - scsi_to_pci_dma_dir(Command->sc_data_direction)); - } - else if (SegmentCount != 0) - { - struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer; - int Segment, Count; - - Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, - scsi_to_pci_dma_dir(Command->sc_data_direction)); - CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; - CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment); - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - CCB->DataPointer = (unsigned int)CCB->DMA_Handle + - ((unsigned long)&CCB->ScatterGatherList - - (unsigned long)CCB); - else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList); - for (Segment = 0; Segment < Count; Segment++) - { - CCB->ScatterGatherList[Segment].SegmentByteCount = - sg_dma_len(ScatterList+Segment); - CCB->ScatterGatherList[Segment].SegmentDataPointer = - sg_dma_address(ScatterList+Segment); - } - } - else - { - CCB->Opcode = BusLogic_InitiatorCCB; - CCB->DataLength = BufferLength; - CCB->DataPointer = 0; - } - switch (CDB[0]) - { - case READ_6: - case READ_10: - CCB->DataDirection = BusLogic_DataInLengthChecked; - TargetStatistics[TargetID].ReadCommands++; - BusLogic_IncrementByteCounter( - &TargetStatistics[TargetID].TotalBytesRead, BufferLength); - BusLogic_IncrementSizeBucket( - TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength); - break; - case WRITE_6: - case WRITE_10: - CCB->DataDirection = BusLogic_DataOutLengthChecked; - TargetStatistics[TargetID].WriteCommands++; - BusLogic_IncrementByteCounter( - &TargetStatistics[TargetID].TotalBytesWritten, BufferLength); - BusLogic_IncrementSizeBucket( - TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength); - break; - default: - CCB->DataDirection = BusLogic_UncheckedDataTransfer; - break; - } - CCB->CDB_Length = CDB_Length; - CCB->HostAdapterStatus = 0; - CCB->TargetDeviceStatus = 0; - CCB->TargetID = TargetID; - CCB->LogicalUnit = LogicalUnit; - CCB->TagEnable = false; - CCB->LegacyTagEnable = false; - /* - BusLogic recommends that after a Reset the first couple of commands that - are sent to a Target Device be sent in a non Tagged Queue fashion so that - the Host Adapter and Target Device can establish Synchronous and Wide - Transfer before Queue Tag messages can interfere with the Synchronous and - Wide Negotiation messages. By waiting to enable Tagged Queuing until after - the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is - assured that after a Reset any pending commands are requeued before Tagged - Queuing is enabled and that the Tagged Queuing message will not occur while - the partition table is being printed. In addition, some devices do not - properly handle the transition from non-tagged to tagged commands, so it is - necessary to wait until there are no pending commands for a target device - before queuing tagged commands. - */ - if (HostAdapter->CommandsSinceReset[TargetID]++ >= - BusLogic_MaxTaggedQueueDepth && - !TargetFlags->TaggedQueuingActive && - HostAdapter->ActiveCommands[TargetID] == 0 && - TargetFlags->TaggedQueuingSupported && - (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) - { - TargetFlags->TaggedQueuingActive = true; - BusLogic_Notice("Tagged Queuing now active for Target %d\n", - HostAdapter, TargetID); - } - if (TargetFlags->TaggedQueuingActive) - { - enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag; - /* - When using Tagged Queuing with Simple Queue Tags, it appears that disk - drive controllers do not guarantee that a queued command will not - remain in a disconnected state indefinitely if commands that read or - write nearer the head position continue to arrive without interruption. - Therefore, for each Target Device this driver keeps track of the last - time either the queue was empty or an Ordered Queue Tag was issued. If - more than 4 seconds (one fifth of the 20 second disk timeout) have - elapsed since this last sequence point, this command will be issued - with an Ordered Queue Tag rather than a Simple Queue Tag, which forces - the Target Device to complete all previously queued commands before - this command may be executed. - */ - if (HostAdapter->ActiveCommands[TargetID] == 0) - HostAdapter->LastSequencePoint[TargetID] = jiffies; - else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ) - { - HostAdapter->LastSequencePoint[TargetID] = jiffies; - QueueTag = BusLogic_OrderedQueueTag; - } - if (HostAdapter->ExtendedLUNSupport) - { - CCB->TagEnable = true; - CCB->QueueTag = QueueTag; + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata; + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[Command->device->id]; + struct BusLogic_TargetStatistics *TargetStatistics = HostAdapter->TargetStatistics; + unsigned char *CDB = Command->cmnd; + int CDB_Length = Command->cmd_len; + int TargetID = Command->device->id; + int LogicalUnit = Command->device->lun; + void *BufferPointer = Command->request_buffer; + int BufferLength = Command->request_bufflen; + int SegmentCount = Command->use_sg; + struct BusLogic_CCB *CCB; + /* + SCSI REQUEST_SENSE commands will be executed automatically by the Host + Adapter for any errors, so they should not be executed explicitly unless + the Sense Data is zero indicating that no error occurred. + */ + if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) { + Command->result = DID_OK << 16; + CompletionRoutine(Command); + return 0; } - else - { - CCB->LegacyTagEnable = true; - CCB->LegacyQueueTag = QueueTag; + /* + Allocate a CCB from the Host Adapter's free list. In the unlikely event + that there are none available and memory allocation fails, wait 1 second + and try again. If that fails, the Host Adapter is probably hung so signal + an error as a Host Adapter Hard Reset should be initiated soon. + */ + CCB = BusLogic_AllocateCCB(HostAdapter); + if (CCB == NULL) { + spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_Delay(1); + spin_lock_irq(HostAdapter->SCSI_Host->host_lock); + CCB = BusLogic_AllocateCCB(HostAdapter); + if (CCB == NULL) { + Command->result = DID_ERROR << 16; + CompletionRoutine(Command); + return 0; + } } - } - memcpy(CCB->CDB, CDB, CDB_Length); - CCB->SenseDataLength = sizeof(Command->sense_buffer); - CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, - Command->sense_buffer, - CCB->SenseDataLength, - PCI_DMA_FROMDEVICE); - CCB->Command = Command; - Command->scsi_done = CompletionRoutine; - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI - Subsystem should not attempt to queue more commands than can be placed - in Outgoing Mailboxes, so there should always be one free. In the - unlikely event that there are none available, wait 1 second and try - again. If that fails, the Host Adapter is probably hung so signal an - error as a Host Adapter Hard Reset should be initiated soon. - */ - if (!BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxStartCommand, CCB)) - { - BusLogic_ReleaseHostAdapterLock(HostAdapter); - BusLogic_Warning("Unable to write Outgoing Mailbox - " - "Pausing for 1 second\n", HostAdapter); - BusLogic_Delay(1); - BusLogic_AcquireHostAdapterLock(HostAdapter); - if (!BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxStartCommand, CCB)) - { - BusLogic_Warning("Still unable to write Outgoing Mailbox - " - "Host Adapter Dead?\n", HostAdapter); - BusLogic_DeallocateCCB(CCB); - Command->result = DID_ERROR << 16; - Command->scsi_done(Command); - } + /* + Initialize the fields in the BusLogic Command Control Block (CCB). + */ + if (SegmentCount == 0 && BufferLength != 0) { + CCB->Opcode = BusLogic_InitiatorCCB; + CCB->DataLength = BufferLength; + CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device, + BufferPointer, BufferLength, + Command->sc_data_direction); + } else if (SegmentCount != 0) { + struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer; + int Segment, Count; + + Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, + Command->sc_data_direction); + CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; + CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment); + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) + CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB); + else + CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList); + for (Segment = 0; Segment < Count; Segment++) { + CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment); + CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment); + } + } else { + CCB->Opcode = BusLogic_InitiatorCCB; + CCB->DataLength = BufferLength; + CCB->DataPointer = 0; + } + switch (CDB[0]) { + case READ_6: + case READ_10: + CCB->DataDirection = BusLogic_DataInLengthChecked; + TargetStatistics[TargetID].ReadCommands++; + BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, BufferLength); + BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength); + break; + case WRITE_6: + case WRITE_10: + CCB->DataDirection = BusLogic_DataOutLengthChecked; + TargetStatistics[TargetID].WriteCommands++; + BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, BufferLength); + BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength); + break; + default: + CCB->DataDirection = BusLogic_UncheckedDataTransfer; + break; + } + CCB->CDB_Length = CDB_Length; + CCB->HostAdapterStatus = 0; + CCB->TargetDeviceStatus = 0; + CCB->TargetID = TargetID; + CCB->LogicalUnit = LogicalUnit; + CCB->TagEnable = false; + CCB->LegacyTagEnable = false; + /* + BusLogic recommends that after a Reset the first couple of commands that + are sent to a Target Device be sent in a non Tagged Queue fashion so that + the Host Adapter and Target Device can establish Synchronous and Wide + Transfer before Queue Tag messages can interfere with the Synchronous and + Wide Negotiation messages. By waiting to enable Tagged Queuing until after + the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is + assured that after a Reset any pending commands are requeued before Tagged + Queuing is enabled and that the Tagged Queuing message will not occur while + the partition table is being printed. In addition, some devices do not + properly handle the transition from non-tagged to tagged commands, so it is + necessary to wait until there are no pending commands for a target device + before queuing tagged commands. + */ + if (HostAdapter->CommandsSinceReset[TargetID]++ >= + BusLogic_MaxTaggedQueueDepth && !TargetFlags->TaggedQueuingActive && HostAdapter->ActiveCommands[TargetID] == 0 && TargetFlags->TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) { + TargetFlags->TaggedQueuingActive = true; + BusLogic_Notice("Tagged Queuing now active for Target %d\n", HostAdapter, TargetID); + } + if (TargetFlags->TaggedQueuingActive) { + enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag; + /* + When using Tagged Queuing with Simple Queue Tags, it appears that disk + drive controllers do not guarantee that a queued command will not + remain in a disconnected state indefinitely if commands that read or + write nearer the head position continue to arrive without interruption. + Therefore, for each Target Device this driver keeps track of the last + time either the queue was empty or an Ordered Queue Tag was issued. If + more than 4 seconds (one fifth of the 20 second disk timeout) have + elapsed since this last sequence point, this command will be issued + with an Ordered Queue Tag rather than a Simple Queue Tag, which forces + the Target Device to complete all previously queued commands before + this command may be executed. + */ + if (HostAdapter->ActiveCommands[TargetID] == 0) + HostAdapter->LastSequencePoint[TargetID] = jiffies; + else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) { + HostAdapter->LastSequencePoint[TargetID] = jiffies; + QueueTag = BusLogic_OrderedQueueTag; + } + if (HostAdapter->ExtendedLUNSupport) { + CCB->TagEnable = true; + CCB->QueueTag = QueueTag; + } else { + CCB->LegacyTagEnable = true; + CCB->LegacyQueueTag = QueueTag; + } } - } - else - { - /* - Call the FlashPoint SCCB Manager to start execution of the CCB. - */ - CCB->Status = BusLogic_CCB_Active; - HostAdapter->ActiveCommands[TargetID]++; - TargetStatistics[TargetID].CommandsAttempted++; - FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); - /* - The Command may have already completed and BusLogic_QueueCompletedCCB - been called, or it may still be pending. - */ - if (CCB->Status == BusLogic_CCB_Completed) - BusLogic_ProcessCompletedCCBs(HostAdapter); - } - return 0; + memcpy(CCB->CDB, CDB, CDB_Length); + CCB->SenseDataLength = sizeof(Command->sense_buffer); + CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, Command->sense_buffer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE); + CCB->Command = Command; + Command->scsi_done = CompletionRoutine; + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { + /* + Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI + Subsystem should not attempt to queue more commands than can be placed + in Outgoing Mailboxes, so there should always be one free. In the + unlikely event that there are none available, wait 1 second and try + again. If that fails, the Host Adapter is probably hung so signal an + error as a Host Adapter Hard Reset should be initiated soon. + */ + if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) { + spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); + BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter); + BusLogic_Delay(1); + spin_lock_irq(HostAdapter->SCSI_Host->host_lock); + if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) { + BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter); + BusLogic_DeallocateCCB(CCB); + Command->result = DID_ERROR << 16; + Command->scsi_done(Command); + } + } + } else { + /* + Call the FlashPoint SCCB Manager to start execution of the CCB. + */ + CCB->Status = BusLogic_CCB_Active; + HostAdapter->ActiveCommands[TargetID]++; + TargetStatistics[TargetID].CommandsAttempted++; + FlashPoint_StartCCB(HostAdapter->CardHandle, CCB); + /* + The Command may have already completed and BusLogic_QueueCompletedCCB + been called, or it may still be pending. + */ + if (CCB->Status == BusLogic_CCB_Completed) + BusLogic_ProcessCompletedCCBs(HostAdapter); + } + return 0; } @@ -3554,105 +2952,75 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, static int BusLogic_AbortCommand(struct scsi_cmnd *Command) { - struct BusLogic_HostAdapter *HostAdapter = - (struct BusLogic_HostAdapter *) Command->device->host->hostdata; - - int TargetID = Command->device->id; - struct BusLogic_CCB *CCB; - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested); - /* - If this Command has already completed, then no Abort is necessary. - */ - if (Command->serial_number != Command->serial_number_at_timeout) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "Already Completed\n", HostAdapter, TargetID); - return SUCCESS; - } - /* - Attempt to find an Active CCB for this Command. If no Active CCB for this - Command is found, then no Abort is necessary. - */ - for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) - if (CCB->Command == Command) break; - if (CCB == NULL) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "No CCB Found\n", HostAdapter, TargetID); - return SUCCESS; - } - else if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "CCB Completed\n", HostAdapter, TargetID); - return SUCCESS; - } - else if (CCB->Status == BusLogic_CCB_Reset) - { - BusLogic_Warning("Unable to Abort Command to Target %d - " - "CCB Reset\n", HostAdapter, TargetID); - return SUCCESS; - } - if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) - { - /* - Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx - do not generate Abort Tag messages, but only generate the non-tagged - Abort message. Since non-tagged commands are not sent by the Host - Adapter until the queue of outstanding tagged commands has completed, - and the Abort message is treated as a non-tagged command, it is - effectively impossible to abort commands when Tagged Queuing is active. - Firmware version 5.xx does generate Abort Tag messages, so it is - possible to abort commands when Tagged Queuing is active. - */ - if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && - HostAdapter->FirmwareVersion[0] < '5') - { - BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " - "Abort Tag Not Supported\n", - HostAdapter, CCB->SerialNumber, TargetID); - return FAILURE; - } - else if (BusLogic_WriteOutgoingMailbox( - HostAdapter, BusLogic_MailboxAbortCommand, CCB)) - { - BusLogic_Warning("Aborting CCB #%ld to Target %d\n", - HostAdapter, CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); - return SUCCESS; - } - else - { - BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " - "No Outgoing Mailboxes\n", - HostAdapter, CCB->SerialNumber, TargetID); - return FAILURE; + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata; + + int TargetID = Command->device->id; + struct BusLogic_CCB *CCB; + BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested); + /* + If this Command has already completed, then no Abort is necessary. + */ + if (Command->serial_number != Command->serial_number_at_timeout) { + BusLogic_Warning("Unable to Abort Command to Target %d - " "Already Completed\n", HostAdapter, TargetID); + return SUCCESS; } - } - else - { - /* - Call the FlashPoint SCCB Manager to abort execution of the CCB. - */ - BusLogic_Warning("Aborting CCB #%ld to Target %d\n", - HostAdapter, CCB->SerialNumber, TargetID); - BusLogic_IncrementErrorCounter( - &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); - FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB); - /* - The Abort may have already been completed and - BusLogic_QueueCompletedCCB been called, or it - may still be pending. - */ - if (CCB->Status == BusLogic_CCB_Completed) - { - BusLogic_ProcessCompletedCCBs(HostAdapter); + /* + Attempt to find an Active CCB for this Command. If no Active CCB for this + Command is found, then no Abort is necessary. + */ + for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll) + if (CCB->Command == Command) + break; + if (CCB == NULL) { + BusLogic_Warning("Unable to Abort Command to Target %d - " "No CCB Found\n", HostAdapter, TargetID); + return SUCCESS; + } else if (CCB->Status == BusLogic_CCB_Completed) { + BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Completed\n", HostAdapter, TargetID); + return SUCCESS; + } else if (CCB->Status == BusLogic_CCB_Reset) { + BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Reset\n", HostAdapter, TargetID); + return SUCCESS; + } + if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) { + /* + Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx + do not generate Abort Tag messages, but only generate the non-tagged + Abort message. Since non-tagged commands are not sent by the Host + Adapter until the queue of outstanding tagged commands has completed, + and the Abort message is treated as a non-tagged command, it is + effectively impossible to abort commands when Tagged Queuing is active. + Firmware version 5.xx does generate Abort Tag messages, so it is + possible to abort commands when Tagged Queuing is active. + */ + if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && HostAdapter->FirmwareVersion[0] < '5') { + BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "Abort Tag Not Supported\n", HostAdapter, CCB->SerialNumber, TargetID); + return FAILURE; + } else if (BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxAbortCommand, CCB)) { + BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); + return SUCCESS; + } else { + BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "No Outgoing Mailboxes\n", HostAdapter, CCB->SerialNumber, TargetID); + return FAILURE; + } + } else { + /* + Call the FlashPoint SCCB Manager to abort execution of the CCB. + */ + BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID); + BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted); + FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB); + /* + The Abort may have already been completed and + BusLogic_QueueCompletedCCB been called, or it + may still be pending. + */ + if (CCB->Status == BusLogic_CCB_Completed) { + BusLogic_ProcessCompletedCCBs(HostAdapter); + } + return SUCCESS; } - return SUCCESS; - } - return SUCCESS; + return SUCCESS; } /* @@ -3660,8 +3028,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command) currently executing SCSI Commands as having been Reset. */ -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, - boolean HardReset) +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset) { struct BusLogic_CCB *CCB; int TargetID; @@ -3670,10 +3037,8 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, * Attempt to Reset and Reinitialize the Host Adapter. */ - if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && - BusLogic_InitializeHostAdapter(HostAdapter))) { - BusLogic_Error("Resetting %s Failed\n", HostAdapter, - HostAdapter->FullModelName); + if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(HostAdapter))) { + BusLogic_Error("Resetting %s Failed\n", HostAdapter, HostAdapter->FullModelName); return FAILURE; } @@ -3692,9 +3057,9 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, */ if (HardReset) { - BusLogic_ReleaseHostAdapterLock(HostAdapter); + spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); BusLogic_Delay(HostAdapter->BusSettleTime); - BusLogic_AcquireHostAdapterLock(HostAdapter); + spin_lock_irq(HostAdapter->SCSI_Host->host_lock); } for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { @@ -3721,98 +3086,70 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, the BIOS, and a warning may be displayed. */ -static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, - sector_t capacity, int *Parameters) +static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, sector_t capacity, int *Parameters) { - struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata; - struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters; - unsigned char *buf; - if (HostAdapter->ExtendedTranslationEnabled && - capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */) - { - if (capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */) - { - DiskParameters->Heads = 255; - DiskParameters->Sectors = 63; - } - else - { - DiskParameters->Heads = 128; - DiskParameters->Sectors = 32; - } - } - else - { - DiskParameters->Heads = 64; - DiskParameters->Sectors = 32; - } - DiskParameters->Cylinders = - (unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors); - buf = scsi_bios_ptable(Device); - if (buf == NULL) return 0; - /* - If the boot sector partition table flag is valid, search for a partition - table entry whose end_head matches one of the standard BusLogic geometry - translations (64/32, 128/32, or 255/63). - */ - if (*(unsigned short *) (buf+64) == 0xAA55) - { - struct partition *FirstPartitionEntry = (struct partition *) buf; - struct partition *PartitionEntry = FirstPartitionEntry; - int SavedCylinders = DiskParameters->Cylinders, PartitionNumber; - unsigned char PartitionEntryEndHead=0, PartitionEntryEndSector=0; - for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) - { - PartitionEntryEndHead = PartitionEntry->end_head; - PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F; - if (PartitionEntryEndHead == 64-1) - { - DiskParameters->Heads = 64; - DiskParameters->Sectors = 32; - break; - } - else if (PartitionEntryEndHead == 128-1) - { - DiskParameters->Heads = 128; - DiskParameters->Sectors = 32; - break; - } - else if (PartitionEntryEndHead == 255-1) - { - DiskParameters->Heads = 255; - DiskParameters->Sectors = 63; - break; - } - PartitionEntry++; - } - if (PartitionNumber == 4) - { - PartitionEntryEndHead = FirstPartitionEntry->end_head; - PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F; - } - DiskParameters->Cylinders = - (unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors); - if (PartitionNumber < 4 && - PartitionEntryEndSector == DiskParameters->Sectors) - { - if (DiskParameters->Cylinders != SavedCylinders) - BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", - HostAdapter, - DiskParameters->Heads, DiskParameters->Sectors); + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata; + struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters; + unsigned char *buf; + if (HostAdapter->ExtendedTranslationEnabled && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */ ) { + if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */ ) { + DiskParameters->Heads = 255; + DiskParameters->Sectors = 63; + } else { + DiskParameters->Heads = 128; + DiskParameters->Sectors = 32; + } + } else { + DiskParameters->Heads = 64; + DiskParameters->Sectors = 32; } - else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) - { - BusLogic_Warning("Warning: Partition Table appears to " - "have Geometry %d/%d which is\n", HostAdapter, - PartitionEntryEndHead + 1, - PartitionEntryEndSector); - BusLogic_Warning("not compatible with current BusLogic " - "Host Adapter Geometry %d/%d\n", HostAdapter, - DiskParameters->Heads, DiskParameters->Sectors); + DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors); + buf = scsi_bios_ptable(Device); + if (buf == NULL) + return 0; + /* + If the boot sector partition table flag is valid, search for a partition + table entry whose end_head matches one of the standard BusLogic geometry + translations (64/32, 128/32, or 255/63). + */ + if (*(unsigned short *) (buf + 64) == 0xAA55) { + struct partition *FirstPartitionEntry = (struct partition *) buf; + struct partition *PartitionEntry = FirstPartitionEntry; + int SavedCylinders = DiskParameters->Cylinders, PartitionNumber; + unsigned char PartitionEntryEndHead = 0, PartitionEntryEndSector = 0; + for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) { + PartitionEntryEndHead = PartitionEntry->end_head; + PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F; + if (PartitionEntryEndHead == 64 - 1) { + DiskParameters->Heads = 64; + DiskParameters->Sectors = 32; + break; + } else if (PartitionEntryEndHead == 128 - 1) { + DiskParameters->Heads = 128; + DiskParameters->Sectors = 32; + break; + } else if (PartitionEntryEndHead == 255 - 1) { + DiskParameters->Heads = 255; + DiskParameters->Sectors = 63; + break; + } + PartitionEntry++; + } + if (PartitionNumber == 4) { + PartitionEntryEndHead = FirstPartitionEntry->end_head; + PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F; + } + DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors); + if (PartitionNumber < 4 && PartitionEntryEndSector == DiskParameters->Sectors) { + if (DiskParameters->Cylinders != SavedCylinders) + BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors); + } else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) { + BusLogic_Warning("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", HostAdapter, PartitionEntryEndHead + 1, PartitionEntryEndSector); + BusLogic_Warning("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors); + } } - } - kfree(buf); - return 0; + kfree(buf); + return 0; } @@ -3820,178 +3157,118 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_de BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/. */ -static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, - char **StartPointer, off_t Offset, - int BytesAvailable, int WriteFlag) +static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag) { - struct BusLogic_HostAdapter *HostAdapter; - struct BusLogic_TargetStatistics *TargetStatistics; - int TargetID, Length; - char *Buffer; - for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; - HostAdapter != NULL; - HostAdapter = HostAdapter->Next) - if (HostAdapter->HostNumber == shost->host_no) break; - if (HostAdapter == NULL) - { - BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", - NULL, shost->host_no); - return 0; - } - TargetStatistics = HostAdapter->TargetStatistics; - if (WriteFlag) - { - HostAdapter->ExternalHostAdapterResets = 0; - HostAdapter->HostAdapterInternalErrors = 0; - memset(TargetStatistics, 0, - BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics)); - return 0; - } - Buffer = HostAdapter->MessageBuffer; - Length = HostAdapter->MessageBufferLength; - Length += sprintf(&Buffer[Length], "\n\ + struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata; + struct BusLogic_TargetStatistics *TargetStatistics; + int TargetID, Length; + char *Buffer; + + TargetStatistics = HostAdapter->TargetStatistics; + if (WriteFlag) { + HostAdapter->ExternalHostAdapterResets = 0; + HostAdapter->HostAdapterInternalErrors = 0; + memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics)); + return 0; + } + Buffer = HostAdapter->MessageBuffer; + Length = HostAdapter->MessageBufferLength; + Length += sprintf(&Buffer[Length], "\n\ Current Driver Queue Depth: %d\n\ -Currently Allocated CCBs: %d\n", - HostAdapter->DriverQueueDepth, - HostAdapter->AllocatedCCBs); - Length += sprintf(&Buffer[Length], "\n\n\ +Currently Allocated CCBs: %d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs); + Length += sprintf(&Buffer[Length], "\n\n\ DATA TRANSFER STATISTICS\n\ \n\ Target Tagged Queuing Queue Depth Active Attempted Completed\n\ ====== ============== =========== ====== ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], " %2d %s", TargetID, - (TargetFlags->TaggedQueuingSupported - ? (TargetFlags->TaggedQueuingActive - ? " Active" - : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID) - ? " Permitted" : " Disabled")) - : "Not Supported")); - Length += sprintf(&Buffer[Length], - " %3d %3u %9u %9u\n", - HostAdapter->QueueDepth[TargetID], - HostAdapter->ActiveCommands[TargetID], - TargetStatistics[TargetID].CommandsAttempted, - TargetStatistics[TargetID].CommandsCompleted); - } - Length += sprintf(&Buffer[Length], "\n\ + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; + if (!TargetFlags->TargetExists) + continue; + Length += sprintf(&Buffer[Length], " %2d %s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? " Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID) + ? " Permitted" : " Disabled")) + : "Not Supported")); + Length += sprintf(&Buffer[Length], + " %3d %3u %9u %9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted); + } + Length += sprintf(&Buffer[Length], "\n\ Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\ ====== ============= ============== =================== ===================\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, - TargetStatistics[TargetID].ReadCommands, - TargetStatistics[TargetID].WriteCommands); - if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0) - Length += - sprintf(&Buffer[Length], " %9u%09u", - TargetStatistics[TargetID].TotalBytesRead.Billions, - TargetStatistics[TargetID].TotalBytesRead.Units); - else - Length += - sprintf(&Buffer[Length], " %9u", - TargetStatistics[TargetID].TotalBytesRead.Units); - if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0) - Length += - sprintf(&Buffer[Length], " %9u%09u\n", - TargetStatistics[TargetID].TotalBytesWritten.Billions, - TargetStatistics[TargetID].TotalBytesWritten.Units); - else - Length += - sprintf(&Buffer[Length], " %9u\n", - TargetStatistics[TargetID].TotalBytesWritten.Units); - } - Length += sprintf(&Buffer[Length], "\n\ + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; + if (!TargetFlags->TargetExists) + continue; + Length += sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands); + if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0) + Length += sprintf(&Buffer[Length], " %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units); + else + Length += sprintf(&Buffer[Length], " %9u", TargetStatistics[TargetID].TotalBytesRead.Units); + if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0) + Length += sprintf(&Buffer[Length], " %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units); + else + Length += sprintf(&Buffer[Length], " %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units); + } + Length += sprintf(&Buffer[Length], "\n\ Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\ ====== ======= ========= ========= ========= ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], - " %2d Read %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].ReadCommandSizeBuckets[0], - TargetStatistics[TargetID].ReadCommandSizeBuckets[1], - TargetStatistics[TargetID].ReadCommandSizeBuckets[2], - TargetStatistics[TargetID].ReadCommandSizeBuckets[3], - TargetStatistics[TargetID].ReadCommandSizeBuckets[4]); - Length += - sprintf(&Buffer[Length], - " %2d Write %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].WriteCommandSizeBuckets[0], - TargetStatistics[TargetID].WriteCommandSizeBuckets[1], - TargetStatistics[TargetID].WriteCommandSizeBuckets[2], - TargetStatistics[TargetID].WriteCommandSizeBuckets[3], - TargetStatistics[TargetID].WriteCommandSizeBuckets[4]); - } - Length += sprintf(&Buffer[Length], "\n\ + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; + if (!TargetFlags->TargetExists) + continue; + Length += + sprintf(&Buffer[Length], + " %2d Read %9u %9u %9u %9u %9u\n", TargetID, + TargetStatistics[TargetID].ReadCommandSizeBuckets[0], + TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]); + Length += + sprintf(&Buffer[Length], + " %2d Write %9u %9u %9u %9u %9u\n", TargetID, + TargetStatistics[TargetID].WriteCommandSizeBuckets[0], + TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]); + } + Length += sprintf(&Buffer[Length], "\n\ Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\ ====== ======= ========= ========= ========= ========= =========\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], - " %2d Read %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].ReadCommandSizeBuckets[5], - TargetStatistics[TargetID].ReadCommandSizeBuckets[6], - TargetStatistics[TargetID].ReadCommandSizeBuckets[7], - TargetStatistics[TargetID].ReadCommandSizeBuckets[8], - TargetStatistics[TargetID].ReadCommandSizeBuckets[9]); - Length += - sprintf(&Buffer[Length], - " %2d Write %9u %9u %9u %9u %9u\n", TargetID, - TargetStatistics[TargetID].WriteCommandSizeBuckets[5], - TargetStatistics[TargetID].WriteCommandSizeBuckets[6], - TargetStatistics[TargetID].WriteCommandSizeBuckets[7], - TargetStatistics[TargetID].WriteCommandSizeBuckets[8], - TargetStatistics[TargetID].WriteCommandSizeBuckets[9]); - } - Length += sprintf(&Buffer[Length], "\n\n\ + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; + if (!TargetFlags->TargetExists) + continue; + Length += + sprintf(&Buffer[Length], + " %2d Read %9u %9u %9u %9u %9u\n", TargetID, + TargetStatistics[TargetID].ReadCommandSizeBuckets[5], + TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]); + Length += + sprintf(&Buffer[Length], + " %2d Write %9u %9u %9u %9u %9u\n", TargetID, + TargetStatistics[TargetID].WriteCommandSizeBuckets[5], + TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]); + } + Length += sprintf(&Buffer[Length], "\n\n\ ERROR RECOVERY STATISTICS\n\ \n\ Command Aborts Bus Device Resets Host Adapter Resets\n\ Target Requested Completed Requested Completed Requested Completed\n\ ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\ ====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n"); - for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) - { - struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; - if (!TargetFlags->TargetExists) continue; - Length += - sprintf(&Buffer[Length], "\ - %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, - TargetStatistics[TargetID].CommandAbortsRequested, - TargetStatistics[TargetID].CommandAbortsAttempted, - TargetStatistics[TargetID].CommandAbortsCompleted, - TargetStatistics[TargetID].BusDeviceResetsRequested, - TargetStatistics[TargetID].BusDeviceResetsAttempted, - TargetStatistics[TargetID].BusDeviceResetsCompleted, - TargetStatistics[TargetID].HostAdapterResetsRequested, - TargetStatistics[TargetID].HostAdapterResetsAttempted, - TargetStatistics[TargetID].HostAdapterResetsCompleted); - } - Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", - HostAdapter->ExternalHostAdapterResets); - Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", - HostAdapter->HostAdapterInternalErrors); - if (Length >= BusLogic_MessageBufferSize) - BusLogic_Error("Message Buffer length %d exceeds size %d\n", - HostAdapter, Length, BusLogic_MessageBufferSize); - if ((Length -= Offset) <= 0) return 0; - if (Length >= BytesAvailable) Length = BytesAvailable; - memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length); - *StartPointer = ProcBuffer; - return Length; + for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { + struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID]; + if (!TargetFlags->TargetExists) + continue; + Length += sprintf(&Buffer[Length], "\ + %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted); + } + Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets); + Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors); + if (Length >= BusLogic_MessageBufferSize) + BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize); + if ((Length -= Offset) <= 0) + return 0; + if (Length >= BytesAvailable) + Length = BytesAvailable; + memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length); + *StartPointer = ProcBuffer; + return Length; } @@ -3999,52 +3276,39 @@ Target Requested Completed Requested Completed Requested Completed\n\ BusLogic_Message prints Driver Messages. */ -static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, - char *Format, - struct BusLogic_HostAdapter *HostAdapter, - ...) +static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...) { - static char Buffer[BusLogic_LineBufferSize]; - static boolean BeginningOfLine = true; - va_list Arguments; - int Length = 0; - va_start(Arguments, HostAdapter); - Length = vsprintf(Buffer, Format, Arguments); - va_end(Arguments); - if (MessageLevel == BusLogic_AnnounceLevel) - { - static int AnnouncementLines = 0; - strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], - Buffer); - HostAdapter->MessageBufferLength += Length; - if (++AnnouncementLines <= 2) - printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer); - } - else if (MessageLevel == BusLogic_InfoLevel) - { - strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], - Buffer); - HostAdapter->MessageBufferLength += Length; - if (BeginningOfLine) - { - if (Buffer[0] != '\n' || Length > 1) - printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], - HostAdapter->HostNumber, Buffer); - } - else printk("%s", Buffer); - } - else - { - if (BeginningOfLine) - { - if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized) - printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], - HostAdapter->HostNumber, Buffer); - else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer); - } - else printk("%s", Buffer); - } - BeginningOfLine = (Buffer[Length-1] == '\n'); + static char Buffer[BusLogic_LineBufferSize]; + static boolean BeginningOfLine = true; + va_list Arguments; + int Length = 0; + va_start(Arguments, HostAdapter); + Length = vsprintf(Buffer, Format, Arguments); + va_end(Arguments); + if (MessageLevel == BusLogic_AnnounceLevel) { + static int AnnouncementLines = 0; + strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer); + HostAdapter->MessageBufferLength += Length; + if (++AnnouncementLines <= 2) + printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer); + } else if (MessageLevel == BusLogic_InfoLevel) { + strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer); + HostAdapter->MessageBufferLength += Length; + if (BeginningOfLine) { + if (Buffer[0] != '\n' || Length > 1) + printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer); + } else + printk("%s", Buffer); + } else { + if (BeginningOfLine) { + if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized) + printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer); + else + printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer); + } else + printk("%s", Buffer); + } + BeginningOfLine = (Buffer[Length - 1] == '\n'); } @@ -4055,19 +3319,19 @@ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) { - char *Pointer = *StringPointer; - while (*Keyword != '\0') - { - char StringChar = *Pointer++; - char KeywordChar = *Keyword++; - if (StringChar >= 'A' && StringChar <= 'Z') - StringChar += 'a' - 'Z'; - if (KeywordChar >= 'A' && KeywordChar <= 'Z') - KeywordChar += 'a' - 'Z'; - if (StringChar != KeywordChar) return false; - } - *StringPointer = Pointer; - return true; + char *Pointer = *StringPointer; + while (*Keyword != '\0') { + char StringChar = *Pointer++; + char KeywordChar = *Keyword++; + if (StringChar >= 'A' && StringChar <= 'Z') + StringChar += 'a' - 'Z'; + if (KeywordChar >= 'A' && KeywordChar <= 'Z') + KeywordChar += 'a' - 'Z'; + if (StringChar != KeywordChar) + return false; + } + *StringPointer = Pointer; + return true; } @@ -4090,247 +3354,187 @@ static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) static int __init BusLogic_ParseDriverOptions(char *OptionsString) { - while (true) - { - struct BusLogic_DriverOptions *DriverOptions = - &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++]; - int TargetID; - memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions)); - while (*OptionsString != '\0' && *OptionsString != ';') - { - /* Probing Options. */ - if (BusLogic_ParseKeyword(&OptionsString, "IO:")) - { - unsigned long IO_Address = - simple_strtoul(OptionsString, &OptionsString, 0); - BusLogic_ProbeOptions.LimitedProbeISA = true; - switch (IO_Address) - { - case 0x330: - BusLogic_ProbeOptions.Probe330 = true; - break; - case 0x334: - BusLogic_ProbeOptions.Probe334 = true; - break; - case 0x230: - BusLogic_ProbeOptions.Probe230 = true; - break; - case 0x234: - BusLogic_ProbeOptions.Probe234 = true; - break; - case 0x130: - BusLogic_ProbeOptions.Probe130 = true; - break; - case 0x134: - BusLogic_ProbeOptions.Probe134 = true; - break; - default: - BusLogic_Error("BusLogic: Invalid Driver Options " - "(invalid I/O Address 0x%X)\n", - NULL, IO_Address); - return 0; - } - } - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA")) - BusLogic_ProbeOptions.NoProbeISA = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI")) - BusLogic_ProbeOptions.NoProbePCI = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe")) - BusLogic_ProbeOptions.NoProbe = true; - else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI")) - BusLogic_ProbeOptions.NoSortPCI = true; - else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst")) - BusLogic_ProbeOptions.MultiMasterFirst = true; - else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst")) - BusLogic_ProbeOptions.FlashPointFirst = true; - /* Tagged Queuing Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || - BusLogic_ParseKeyword(&OptionsString, "QD:[")) - { - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - { - unsigned short QueueDepth = - simple_strtoul(OptionsString, &OptionsString, 0); - if (QueueDepth > BusLogic_MaxTaggedQueueDepth) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(invalid Queue Depth %d)\n", - NULL, QueueDepth); - return 0; - } - DriverOptions->QueueDepth[TargetID] = QueueDepth; - if (*OptionsString == ',') - OptionsString++; - else if (*OptionsString == ']') - break; - else - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(',' or ']' expected at '%s')\n", - NULL, OptionsString); - return 0; - } - } - if (*OptionsString != ']') - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(']' expected at '%s')\n", - NULL, OptionsString); - return 0; - } - else OptionsString++; - } - else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || - BusLogic_ParseKeyword(&OptionsString, "QD:")) - { - unsigned short QueueDepth = - simple_strtoul(OptionsString, &OptionsString, 0); - if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(invalid Queue Depth %d)\n", - NULL, QueueDepth); - return 0; + while (true) { + struct BusLogic_DriverOptions *DriverOptions = &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++]; + int TargetID; + memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions)); + while (*OptionsString != '\0' && *OptionsString != ';') { + /* Probing Options. */ + if (BusLogic_ParseKeyword(&OptionsString, "IO:")) { + unsigned long IO_Address = simple_strtoul(OptionsString, &OptionsString, 0); + BusLogic_ProbeOptions.LimitedProbeISA = true; + switch (IO_Address) { + case 0x330: + BusLogic_ProbeOptions.Probe330 = true; + break; + case 0x334: + BusLogic_ProbeOptions.Probe334 = true; + break; + case 0x230: + BusLogic_ProbeOptions.Probe230 = true; + break; + case 0x234: + BusLogic_ProbeOptions.Probe234 = true; + break; + case 0x130: + BusLogic_ProbeOptions.Probe130 = true; + break; + case 0x134: + BusLogic_ProbeOptions.Probe134 = true; + break; + default: + BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, IO_Address); + return 0; + } + } else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA")) + BusLogic_ProbeOptions.NoProbeISA = true; + else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI")) + BusLogic_ProbeOptions.NoProbePCI = true; + else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe")) + BusLogic_ProbeOptions.NoProbe = true; + else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI")) + BusLogic_ProbeOptions.NoSortPCI = true; + else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst")) + BusLogic_ProbeOptions.MultiMasterFirst = true; + else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst")) + BusLogic_ProbeOptions.FlashPointFirst = true; + /* Tagged Queuing Options. */ + else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || BusLogic_ParseKeyword(&OptionsString, "QD:[")) { + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) { + unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0); + if (QueueDepth > BusLogic_MaxTaggedQueueDepth) { + BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth); + return 0; + } + DriverOptions->QueueDepth[TargetID] = QueueDepth; + if (*OptionsString == ',') + OptionsString++; + else if (*OptionsString == ']') + break; + else { + BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString); + return 0; + } + } + if (*OptionsString != ']') { + BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString); + return 0; + } else + OptionsString++; + } else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || BusLogic_ParseKeyword(&OptionsString, "QD:")) { + unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0); + if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) { + BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth); + return 0; + } + DriverOptions->CommonQueueDepth = QueueDepth; + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) + DriverOptions->QueueDepth[TargetID] = QueueDepth; + } else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || BusLogic_ParseKeyword(&OptionsString, "TQ:")) { + if (BusLogic_ParseKeyword(&OptionsString, "Default")) { + DriverOptions->TaggedQueuingPermitted = 0x0000; + DriverOptions->TaggedQueuingPermittedMask = 0x0000; + } else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) { + DriverOptions->TaggedQueuingPermitted = 0xFFFF; + DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; + } else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) { + DriverOptions->TaggedQueuingPermitted = 0x0000; + DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; + } else { + unsigned short TargetBit; + for (TargetID = 0, TargetBit = 1; TargetID < BusLogic_MaxTargetDevices; TargetID++, TargetBit <<= 1) + switch (*OptionsString++) { + case 'Y': + DriverOptions->TaggedQueuingPermitted |= TargetBit; + DriverOptions->TaggedQueuingPermittedMask |= TargetBit; + break; + case 'N': + DriverOptions->TaggedQueuingPermitted &= ~TargetBit; + DriverOptions->TaggedQueuingPermittedMask |= TargetBit; + break; + case 'X': + break; + default: + OptionsString--; + TargetID = BusLogic_MaxTargetDevices; + break; + } + } + } + /* Miscellaneous Options. */ + else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || BusLogic_ParseKeyword(&OptionsString, "BST:")) { + unsigned short BusSettleTime = simple_strtoul(OptionsString, &OptionsString, 0); + if (BusSettleTime > 5 * 60) { + BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, BusSettleTime); + return 0; + } + DriverOptions->BusSettleTime = BusSettleTime; + } else if (BusLogic_ParseKeyword(&OptionsString, "InhibitTargetInquiry")) + DriverOptions->LocalOptions.InhibitTargetInquiry = true; + /* Debugging Options. */ + else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe")) + BusLogic_GlobalOptions.TraceProbe = true; + else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset")) + BusLogic_GlobalOptions.TraceHardwareReset = true; + else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration")) + BusLogic_GlobalOptions.TraceConfiguration = true; + else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors")) + BusLogic_GlobalOptions.TraceErrors = true; + else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) { + BusLogic_GlobalOptions.TraceProbe = true; + BusLogic_GlobalOptions.TraceHardwareReset = true; + BusLogic_GlobalOptions.TraceConfiguration = true; + BusLogic_GlobalOptions.TraceErrors = true; + } + if (*OptionsString == ',') + OptionsString++; + else if (*OptionsString != ';' && *OptionsString != '\0') { + BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, OptionsString); + *OptionsString = '\0'; + } } - DriverOptions->CommonQueueDepth = QueueDepth; - for (TargetID = 0; - TargetID < BusLogic_MaxTargetDevices; - TargetID++) - DriverOptions->QueueDepth[TargetID] = QueueDepth; - } - else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || - BusLogic_ParseKeyword(&OptionsString, "TQ:")) - { - if (BusLogic_ParseKeyword(&OptionsString, "Default")) - { - DriverOptions->TaggedQueuingPermitted = 0x0000; - DriverOptions->TaggedQueuingPermittedMask = 0x0000; + if (!(BusLogic_DriverOptionsCount == 0 || BusLogic_ProbeInfoCount == 0 || BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) { + BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL); + return 0; } - else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) - { - DriverOptions->TaggedQueuingPermitted = 0xFFFF; - DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; - } - else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) - { - DriverOptions->TaggedQueuingPermitted = 0x0000; - DriverOptions->TaggedQueuingPermittedMask = 0xFFFF; - } - else - { - unsigned short TargetBit; - for (TargetID = 0, TargetBit = 1; - TargetID < BusLogic_MaxTargetDevices; - TargetID++, TargetBit <<= 1) - switch (*OptionsString++) - { - case 'Y': - DriverOptions->TaggedQueuingPermitted |= TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - break; - case 'N': - DriverOptions->TaggedQueuingPermitted &= ~TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - break; - case 'X': - break; - default: - OptionsString--; - TargetID = BusLogic_MaxTargetDevices; - break; - } - } - } - /* Miscellaneous Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || - BusLogic_ParseKeyword(&OptionsString, "BST:")) - { - unsigned short BusSettleTime = - simple_strtoul(OptionsString, &OptionsString, 0); - if (BusSettleTime > 5 * 60) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(invalid Bus Settle Time %d)\n", - NULL, BusSettleTime); - return 0; - } - DriverOptions->BusSettleTime = BusSettleTime; - } - else if (BusLogic_ParseKeyword(&OptionsString, - "InhibitTargetInquiry")) - DriverOptions->LocalOptions.InhibitTargetInquiry = true; - /* Debugging Options. */ - else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe")) - BusLogic_GlobalOptions.TraceProbe = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset")) - BusLogic_GlobalOptions.TraceHardwareReset = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration")) - BusLogic_GlobalOptions.TraceConfiguration = true; - else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors")) - BusLogic_GlobalOptions.TraceErrors = true; - else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) - { - BusLogic_GlobalOptions.TraceProbe = true; - BusLogic_GlobalOptions.TraceHardwareReset = true; - BusLogic_GlobalOptions.TraceConfiguration = true; - BusLogic_GlobalOptions.TraceErrors = true; - } - if (*OptionsString == ',') - OptionsString++; - else if (*OptionsString != ';' && *OptionsString != '\0') - { - BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " - "ignored\n", NULL, OptionsString); - *OptionsString = '\0'; - } - } - if (!(BusLogic_DriverOptionsCount == 0 || - BusLogic_ProbeInfoCount == 0 || - BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) - { - BusLogic_Error("BusLogic: Invalid Driver Options " - "(all or no I/O Addresses must be specified)\n", NULL); - return 0; - } - /* - Tagged Queuing is disabled when the Queue Depth is 1 since queuing - multiple commands is not possible. - */ - for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) - if (DriverOptions->QueueDepth[TargetID] == 1) - { - unsigned short TargetBit = 1 << TargetID; - DriverOptions->TaggedQueuingPermitted &= ~TargetBit; - DriverOptions->TaggedQueuingPermittedMask |= TargetBit; - } - if (*OptionsString == ';') OptionsString++; - if (*OptionsString == '\0') return 0; - } - return 1; + /* + Tagged Queuing is disabled when the Queue Depth is 1 since queuing + multiple commands is not possible. + */ + for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) + if (DriverOptions->QueueDepth[TargetID] == 1) { + unsigned short TargetBit = 1 << TargetID; + DriverOptions->TaggedQueuingPermitted &= ~TargetBit; + DriverOptions->TaggedQueuingPermittedMask |= TargetBit; + } + if (*OptionsString == ';') + OptionsString++; + if (*OptionsString == '\0') + return 0; + } + return 1; } /* Get it all started */ -static struct scsi_host_template driver_template = { - .module = THIS_MODULE, - .proc_name = "BusLogic", - .proc_info = BusLogic_ProcDirectoryInfo, - .name = "BusLogic", - .info = BusLogic_DriverInfo, - .queuecommand = BusLogic_QueueCommand, - .slave_configure = BusLogic_SlaveConfigure, - .bios_param = BusLogic_BIOSDiskParameters, - .eh_host_reset_handler = BusLogic_host_reset, +static struct scsi_host_template Bus_Logic_template = { + .module = THIS_MODULE, + .proc_name = "BusLogic", + .proc_info = BusLogic_ProcDirectoryInfo, + .name = "BusLogic", + .info = BusLogic_DriverInfo, + .queuecommand = BusLogic_QueueCommand, + .slave_configure = BusLogic_SlaveConfigure, + .bios_param = BusLogic_BIOSDiskParameters, + .eh_host_reset_handler = BusLogic_host_reset, #if 0 - .eh_abort_handler = BusLogic_AbortCommand, + .eh_abort_handler = BusLogic_AbortCommand, #endif - .unchecked_isa_dma = 1, - .max_sectors = 128, - .use_clustering = ENABLE_CLUSTERING, + .unchecked_isa_dma = 1, + .max_sectors = 128, + .use_clustering = ENABLE_CLUSTERING, }; /* @@ -4341,11 +3545,10 @@ static int __init BusLogic_Setup(char *str) { int ints[3]; - (void)get_options(str, ARRAY_SIZE(ints), ints); + (void) get_options(str, ARRAY_SIZE(ints), ints); if (ints[0] != 0) { - BusLogic_Error("BusLogic: Obsolete Command Line Entry " - "Format Ignored\n", NULL); + BusLogic_Error("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL); return 0; } if (str == NULL || *str == '\0') @@ -4353,38 +3556,16 @@ static int __init BusLogic_Setup(char *str) return BusLogic_ParseDriverOptions(str); } -/* - * Initialization function - */ - -static int __init BusLogic_init(void) { - -#ifdef MODULE - if (BusLogic) - BusLogic_Setup(BusLogic); -#endif - - return BusLogic_DetectHostAdapter(&driver_template) ? 0 : -ENODEV; -} - /* * Exit function. Deletes all hosts associated with this driver. */ static void __exit BusLogic_exit(void) { - struct BusLogic_HostAdapter *HostAdapter; - for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; - HostAdapter != NULL; HostAdapter = HostAdapter->Next) { - struct Scsi_Host *host = HostAdapter->SCSI_Host; - scsi_remove_host(host); + struct BusLogic_HostAdapter *ha, *next; - } - for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; - HostAdapter != NULL; HostAdapter = HostAdapter->Next) { - struct Scsi_Host *host = HostAdapter->SCSI_Host; - BusLogic_ReleaseHostAdapter(host); - } + list_for_each_entry_safe(ha, next, &BusLogic_host_list, host_list) + BusLogic_ReleaseHostAdapter(ha); } __setup("BusLogic=", BusLogic_Setup); diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h index 2dd778f57..1aaa6569e 100644 --- a/drivers/scsi/BusLogic.h +++ b/drivers/scsi/BusLogic.h @@ -128,17 +128,15 @@ Define the Driver Message Levels. */ -enum BusLogic_MessageLevel -{ - BusLogic_AnnounceLevel = 0, - BusLogic_InfoLevel = 1, - BusLogic_NoticeLevel = 2, - BusLogic_WarningLevel = 3, - BusLogic_ErrorLevel = 4 +enum BusLogic_MessageLevel { + BusLogic_AnnounceLevel = 0, + BusLogic_InfoLevel = 1, + BusLogic_NoticeLevel = 2, + BusLogic_WarningLevel = 3, + BusLogic_ErrorLevel = 4 }; -static char *BusLogic_MessageLevelMap[] = - { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR }; +static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR }; /* @@ -166,17 +164,15 @@ static char *BusLogic_MessageLevelMap[] = of I/O Addresses required by each type. */ -enum BusLogic_HostAdapterType -{ - BusLogic_MultiMaster = 1, - BusLogic_FlashPoint = 2 +enum BusLogic_HostAdapterType { + BusLogic_MultiMaster = 1, + BusLogic_FlashPoint = 2 } PACKED; #define BusLogic_MultiMasterAddressCount 4 #define BusLogic_FlashPointAddressCount 256 -static int BusLogic_HostAdapterAddressCount[3] = - { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount }; +static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount }; /* @@ -206,39 +202,35 @@ static int BusLogic_HostAdapterAddressCount[3] = Define the possible Host Adapter Bus Types. */ -enum BusLogic_HostAdapterBusType -{ - BusLogic_Unknown_Bus = 0, - BusLogic_ISA_Bus = 1, - BusLogic_EISA_Bus = 2, - BusLogic_PCI_Bus = 3, - BusLogic_VESA_Bus = 4, - BusLogic_MCA_Bus = 5 +enum BusLogic_HostAdapterBusType { + BusLogic_Unknown_Bus = 0, + BusLogic_ISA_Bus = 1, + BusLogic_EISA_Bus = 2, + BusLogic_PCI_Bus = 3, + BusLogic_VESA_Bus = 4, + BusLogic_MCA_Bus = 5 } PACKED; -static char *BusLogic_HostAdapterBusNames[] = - { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" }; +static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" }; -static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = -{ - BusLogic_VESA_Bus, /* BT-4xx */ - BusLogic_ISA_Bus, /* BT-5xx */ - BusLogic_MCA_Bus, /* BT-6xx */ - BusLogic_EISA_Bus, /* BT-7xx */ - BusLogic_Unknown_Bus, /* BT-8xx */ - BusLogic_PCI_Bus /* BT-9xx */ +static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = { + BusLogic_VESA_Bus, /* BT-4xx */ + BusLogic_ISA_Bus, /* BT-5xx */ + BusLogic_MCA_Bus, /* BT-6xx */ + BusLogic_EISA_Bus, /* BT-7xx */ + BusLogic_Unknown_Bus, /* BT-8xx */ + BusLogic_PCI_Bus /* BT-9xx */ }; /* Define the possible Host Adapter BIOS Disk Geometry Translations. */ -enum BusLogic_BIOS_DiskGeometryTranslation -{ - BusLogic_BIOS_Disk_Not_Installed = 0, - BusLogic_BIOS_Disk_Installed_64x32 = 1, - BusLogic_BIOS_Disk_Installed_128x32 = 2, - BusLogic_BIOS_Disk_Installed_255x63 = 3 +enum BusLogic_BIOS_DiskGeometryTranslation { + BusLogic_BIOS_Disk_Not_Installed = 0, + BusLogic_BIOS_Disk_Installed_64x32 = 1, + BusLogic_BIOS_Disk_Installed_128x32 = 2, + BusLogic_BIOS_Disk_Installed_255x63 = 3 } PACKED; @@ -247,18 +239,17 @@ enum BusLogic_BIOS_DiskGeometryTranslation */ typedef enum { - false, - true + false, + true } PACKED boolean; /* Define a 10^18 Statistics Byte Counter data type. */ -struct BusLogic_ByteCounter -{ - unsigned int Units; - unsigned int Billions; +struct BusLogic_ByteCounter { + unsigned int Units; + unsigned int Billions; }; @@ -266,58 +257,54 @@ struct BusLogic_ByteCounter Define the structure for I/O Address and Bus Probing Information. */ -struct BusLogic_ProbeInfo -{ - enum BusLogic_HostAdapterType HostAdapterType; - enum BusLogic_HostAdapterBusType HostAdapterBusType; - unsigned long IO_Address; - unsigned long PCI_Address; - struct pci_dev *PCI_Device; - unsigned char Bus; - unsigned char Device; - unsigned char IRQ_Channel; +struct BusLogic_ProbeInfo { + enum BusLogic_HostAdapterType HostAdapterType; + enum BusLogic_HostAdapterBusType HostAdapterBusType; + unsigned long IO_Address; + unsigned long PCI_Address; + struct pci_dev *PCI_Device; + unsigned char Bus; + unsigned char Device; + unsigned char IRQ_Channel; }; /* Define the Probe Options. */ -struct BusLogic_ProbeOptions -{ - boolean NoProbe:1; /* Bit 0 */ - boolean NoProbeISA:1; /* Bit 1 */ - boolean NoProbePCI:1; /* Bit 2 */ - boolean NoSortPCI:1; /* Bit 3 */ - boolean MultiMasterFirst:1; /* Bit 4 */ - boolean FlashPointFirst:1; /* Bit 5 */ - boolean LimitedProbeISA:1; /* Bit 6 */ - boolean Probe330:1; /* Bit 7 */ - boolean Probe334:1; /* Bit 8 */ - boolean Probe230:1; /* Bit 9 */ - boolean Probe234:1; /* Bit 10 */ - boolean Probe130:1; /* Bit 11 */ - boolean Probe134:1; /* Bit 12 */ +struct BusLogic_ProbeOptions { + boolean NoProbe:1; /* Bit 0 */ + boolean NoProbeISA:1; /* Bit 1 */ + boolean NoProbePCI:1; /* Bit 2 */ + boolean NoSortPCI:1; /* Bit 3 */ + boolean MultiMasterFirst:1; /* Bit 4 */ + boolean FlashPointFirst:1; /* Bit 5 */ + boolean LimitedProbeISA:1; /* Bit 6 */ + boolean Probe330:1; /* Bit 7 */ + boolean Probe334:1; /* Bit 8 */ + boolean Probe230:1; /* Bit 9 */ + boolean Probe234:1; /* Bit 10 */ + boolean Probe130:1; /* Bit 11 */ + boolean Probe134:1; /* Bit 12 */ }; /* Define the Global Options. */ -struct BusLogic_GlobalOptions -{ - boolean TraceProbe:1; /* Bit 0 */ - boolean TraceHardwareReset:1; /* Bit 1 */ - boolean TraceConfiguration:1; /* Bit 2 */ - boolean TraceErrors:1; /* Bit 3 */ +struct BusLogic_GlobalOptions { + boolean TraceProbe:1; /* Bit 0 */ + boolean TraceHardwareReset:1; /* Bit 1 */ + boolean TraceConfiguration:1; /* Bit 2 */ + boolean TraceErrors:1; /* Bit 3 */ }; /* Define the Local Options. */ -struct BusLogic_LocalOptions -{ - boolean InhibitTargetInquiry:1; /* Bit 0 */ +struct BusLogic_LocalOptions { + boolean InhibitTargetInquiry:1; /* Bit 0 */ }; /* @@ -335,198 +322,188 @@ struct BusLogic_LocalOptions Define the structure of the write-only Control Register. */ -union BusLogic_ControlRegister -{ - unsigned char All; - struct { - unsigned char :4; /* Bits 0-3 */ - boolean SCSIBusReset:1; /* Bit 4 */ - boolean InterruptReset:1; /* Bit 5 */ - boolean SoftReset:1; /* Bit 6 */ - boolean HardReset:1; /* Bit 7 */ - } cr; +union BusLogic_ControlRegister { + unsigned char All; + struct { + unsigned char:4; /* Bits 0-3 */ + boolean SCSIBusReset:1; /* Bit 4 */ + boolean InterruptReset:1; /* Bit 5 */ + boolean SoftReset:1; /* Bit 6 */ + boolean HardReset:1; /* Bit 7 */ + } cr; }; /* Define the structure of the read-only Status Register. */ -union BusLogic_StatusRegister -{ - unsigned char All; - struct { - boolean CommandInvalid:1; /* Bit 0 */ - boolean Reserved:1; /* Bit 1 */ - boolean DataInRegisterReady:1; /* Bit 2 */ - boolean CommandParameterRegisterBusy:1; /* Bit 3 */ - boolean HostAdapterReady:1; /* Bit 4 */ - boolean InitializationRequired:1; /* Bit 5 */ - boolean DiagnosticFailure:1; /* Bit 6 */ - boolean DiagnosticActive:1; /* Bit 7 */ - } sr; +union BusLogic_StatusRegister { + unsigned char All; + struct { + boolean CommandInvalid:1; /* Bit 0 */ + boolean Reserved:1; /* Bit 1 */ + boolean DataInRegisterReady:1; /* Bit 2 */ + boolean CommandParameterRegisterBusy:1; /* Bit 3 */ + boolean HostAdapterReady:1; /* Bit 4 */ + boolean InitializationRequired:1; /* Bit 5 */ + boolean DiagnosticFailure:1; /* Bit 6 */ + boolean DiagnosticActive:1; /* Bit 7 */ + } sr; }; /* Define the structure of the read-only Interrupt Register. */ -union BusLogic_InterruptRegister -{ - unsigned char All; - struct { - boolean IncomingMailboxLoaded:1; /* Bit 0 */ - boolean OutgoingMailboxAvailable:1; /* Bit 1 */ - boolean CommandComplete:1; /* Bit 2 */ - boolean ExternalBusReset:1; /* Bit 3 */ - unsigned char Reserved:3; /* Bits 4-6 */ - boolean InterruptValid:1; /* Bit 7 */ - } ir; +union BusLogic_InterruptRegister { + unsigned char All; + struct { + boolean IncomingMailboxLoaded:1; /* Bit 0 */ + boolean OutgoingMailboxAvailable:1; /* Bit 1 */ + boolean CommandComplete:1; /* Bit 2 */ + boolean ExternalBusReset:1; /* Bit 3 */ + unsigned char Reserved:3; /* Bits 4-6 */ + boolean InterruptValid:1; /* Bit 7 */ + } ir; }; /* Define the structure of the read-only Geometry Register. */ -union BusLogic_GeometryRegister -{ - unsigned char All; - struct { - enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;/* Bits 0-1 */ - enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;/* Bits 2-3 */ - unsigned char :3; /* Bits 4-6 */ - boolean ExtendedTranslationEnabled:1; /* Bit 7 */ - } gr; +union BusLogic_GeometryRegister { + unsigned char All; + struct { + enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2; /* Bits 0-1 */ + enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2; /* Bits 2-3 */ + unsigned char:3; /* Bits 4-6 */ + boolean ExtendedTranslationEnabled:1; /* Bit 7 */ + } gr; }; /* Define the BusLogic SCSI Host Adapter Command Register Operation Codes. */ -enum BusLogic_OperationCode -{ - BusLogic_TestCommandCompleteInterrupt = 0x00, - BusLogic_InitializeMailbox = 0x01, - BusLogic_ExecuteMailboxCommand = 0x02, - BusLogic_ExecuteBIOSCommand = 0x03, - BusLogic_InquireBoardID = 0x04, - BusLogic_EnableOutgoingMailboxAvailableInt = 0x05, - BusLogic_SetSCSISelectionTimeout = 0x06, - BusLogic_SetPreemptTimeOnBus = 0x07, - BusLogic_SetTimeOffBus = 0x08, - BusLogic_SetBusTransferRate = 0x09, - BusLogic_InquireInstalledDevicesID0to7 = 0x0A, - BusLogic_InquireConfiguration = 0x0B, - BusLogic_EnableTargetMode = 0x0C, - BusLogic_InquireSetupInformation = 0x0D, - BusLogic_WriteAdapterLocalRAM = 0x1A, - BusLogic_ReadAdapterLocalRAM = 0x1B, - BusLogic_WriteBusMasterChipFIFO = 0x1C, - BusLogic_ReadBusMasterChipFIFO = 0x1D, - BusLogic_EchoCommandData = 0x1F, - BusLogic_HostAdapterDiagnostic = 0x20, - BusLogic_SetAdapterOptions = 0x21, - BusLogic_InquireInstalledDevicesID8to15 = 0x23, - BusLogic_InquireTargetDevices = 0x24, - BusLogic_DisableHostAdapterInterrupt = 0x25, - BusLogic_InitializeExtendedMailbox = 0x81, - BusLogic_ExecuteSCSICommand = 0x83, - BusLogic_InquireFirmwareVersion3rdDigit = 0x84, - BusLogic_InquireFirmwareVersionLetter = 0x85, - BusLogic_InquirePCIHostAdapterInformation = 0x86, - BusLogic_InquireHostAdapterModelNumber = 0x8B, - BusLogic_InquireSynchronousPeriod = 0x8C, - BusLogic_InquireExtendedSetupInformation = 0x8D, - BusLogic_EnableStrictRoundRobinMode = 0x8F, - BusLogic_StoreHostAdapterLocalRAM = 0x90, - BusLogic_FetchHostAdapterLocalRAM = 0x91, - BusLogic_StoreLocalDataInEEPROM = 0x92, - BusLogic_UploadAutoSCSICode = 0x94, - BusLogic_ModifyIOAddress = 0x95, - BusLogic_SetCCBFormat = 0x96, - BusLogic_WriteInquiryBuffer = 0x9A, - BusLogic_ReadInquiryBuffer = 0x9B, - BusLogic_FlashROMUploadDownload = 0xA7, - BusLogic_ReadSCAMData = 0xA8, - BusLogic_WriteSCAMData = 0xA9 +enum BusLogic_OperationCode { + BusLogic_TestCommandCompleteInterrupt = 0x00, + BusLogic_InitializeMailbox = 0x01, + BusLogic_ExecuteMailboxCommand = 0x02, + BusLogic_ExecuteBIOSCommand = 0x03, + BusLogic_InquireBoardID = 0x04, + BusLogic_EnableOutgoingMailboxAvailableInt = 0x05, + BusLogic_SetSCSISelectionTimeout = 0x06, + BusLogic_SetPreemptTimeOnBus = 0x07, + BusLogic_SetTimeOffBus = 0x08, + BusLogic_SetBusTransferRate = 0x09, + BusLogic_InquireInstalledDevicesID0to7 = 0x0A, + BusLogic_InquireConfiguration = 0x0B, + BusLogic_EnableTargetMode = 0x0C, + BusLogic_InquireSetupInformation = 0x0D, + BusLogic_WriteAdapterLocalRAM = 0x1A, + BusLogic_ReadAdapterLocalRAM = 0x1B, + BusLogic_WriteBusMasterChipFIFO = 0x1C, + BusLogic_ReadBusMasterChipFIFO = 0x1D, + BusLogic_EchoCommandData = 0x1F, + BusLogic_HostAdapterDiagnostic = 0x20, + BusLogic_SetAdapterOptions = 0x21, + BusLogic_InquireInstalledDevicesID8to15 = 0x23, + BusLogic_InquireTargetDevices = 0x24, + BusLogic_DisableHostAdapterInterrupt = 0x25, + BusLogic_InitializeExtendedMailbox = 0x81, + BusLogic_ExecuteSCSICommand = 0x83, + BusLogic_InquireFirmwareVersion3rdDigit = 0x84, + BusLogic_InquireFirmwareVersionLetter = 0x85, + BusLogic_InquirePCIHostAdapterInformation = 0x86, + BusLogic_InquireHostAdapterModelNumber = 0x8B, + BusLogic_InquireSynchronousPeriod = 0x8C, + BusLogic_InquireExtendedSetupInformation = 0x8D, + BusLogic_EnableStrictRoundRobinMode = 0x8F, + BusLogic_StoreHostAdapterLocalRAM = 0x90, + BusLogic_FetchHostAdapterLocalRAM = 0x91, + BusLogic_StoreLocalDataInEEPROM = 0x92, + BusLogic_UploadAutoSCSICode = 0x94, + BusLogic_ModifyIOAddress = 0x95, + BusLogic_SetCCBFormat = 0x96, + BusLogic_WriteInquiryBuffer = 0x9A, + BusLogic_ReadInquiryBuffer = 0x9B, + BusLogic_FlashROMUploadDownload = 0xA7, + BusLogic_ReadSCAMData = 0xA8, + BusLogic_WriteSCAMData = 0xA9 }; /* Define the Inquire Board ID reply structure. */ -struct BusLogic_BoardID -{ - unsigned char BoardType; /* Byte 0 */ - unsigned char CustomFeatures; /* Byte 1 */ - unsigned char FirmwareVersion1stDigit; /* Byte 2 */ - unsigned char FirmwareVersion2ndDigit; /* Byte 3 */ +struct BusLogic_BoardID { + unsigned char BoardType; /* Byte 0 */ + unsigned char CustomFeatures; /* Byte 1 */ + unsigned char FirmwareVersion1stDigit; /* Byte 2 */ + unsigned char FirmwareVersion2ndDigit; /* Byte 3 */ }; /* Define the Inquire Configuration reply structure. */ -struct BusLogic_Configuration -{ - unsigned char :5; /* Byte 0 Bits 0-4 */ - boolean DMA_Channel5:1; /* Byte 0 Bit 5 */ - boolean DMA_Channel6:1; /* Byte 0 Bit 6 */ - boolean DMA_Channel7:1; /* Byte 0 Bit 7 */ - boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */ - boolean IRQ_Channel10:1; /* Byte 1 Bit 1 */ - boolean IRQ_Channel11:1; /* Byte 1 Bit 2 */ - boolean IRQ_Channel12:1; /* Byte 1 Bit 3 */ - unsigned char :1; /* Byte 1 Bit 4 */ - boolean IRQ_Channel14:1; /* Byte 1 Bit 5 */ - boolean IRQ_Channel15:1; /* Byte 1 Bit 6 */ - unsigned char :1; /* Byte 1 Bit 7 */ - unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */ - unsigned char :4; /* Byte 2 Bits 4-7 */ +struct BusLogic_Configuration { + unsigned char:5; /* Byte 0 Bits 0-4 */ + boolean DMA_Channel5:1; /* Byte 0 Bit 5 */ + boolean DMA_Channel6:1; /* Byte 0 Bit 6 */ + boolean DMA_Channel7:1; /* Byte 0 Bit 7 */ + boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */ + boolean IRQ_Channel10:1; /* Byte 1 Bit 1 */ + boolean IRQ_Channel11:1; /* Byte 1 Bit 2 */ + boolean IRQ_Channel12:1; /* Byte 1 Bit 3 */ + unsigned char:1; /* Byte 1 Bit 4 */ + boolean IRQ_Channel14:1; /* Byte 1 Bit 5 */ + boolean IRQ_Channel15:1; /* Byte 1 Bit 6 */ + unsigned char:1; /* Byte 1 Bit 7 */ + unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */ + unsigned char:4; /* Byte 2 Bits 4-7 */ }; /* Define the Inquire Setup Information reply structure. */ -struct BusLogic_SynchronousValue -{ - unsigned char Offset:4; /* Bits 0-3 */ - unsigned char TransferPeriod:3; /* Bits 4-6 */ - boolean Synchronous:1; /* Bit 7 */ +struct BusLogic_SynchronousValue { + unsigned char Offset:4; /* Bits 0-3 */ + unsigned char TransferPeriod:3; /* Bits 4-6 */ + boolean Synchronous:1; /* Bit 7 */ }; -struct BusLogic_SetupInformation -{ - boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ - unsigned char :6; /* Byte 0 Bits 2-7 */ - unsigned char BusTransferRate; /* Byte 1 */ - unsigned char PreemptTimeOnBus; /* Byte 2 */ - unsigned char TimeOffBus; /* Byte 3 */ - unsigned char MailboxCount; /* Byte 4 */ - unsigned char MailboxAddress[3]; /* Bytes 5-7 */ - struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];/* Bytes 8-15 */ - unsigned char DisconnectPermittedID0to7; /* Byte 16 */ - unsigned char Signature; /* Byte 17 */ - unsigned char CharacterD; /* Byte 18 */ - unsigned char HostBusType; /* Byte 19 */ - unsigned char WideTransfersPermittedID0to7; /* Byte 20 */ - unsigned char WideTransfersActiveID0to7; /* Byte 21 */ - struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */ - unsigned char DisconnectPermittedID8to15; /* Byte 30 */ - unsigned char :8; /* Byte 31 */ - unsigned char WideTransfersPermittedID8to15; /* Byte 32 */ - unsigned char WideTransfersActiveID8to15; /* Byte 33 */ +struct BusLogic_SetupInformation { + boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ + boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ + unsigned char:6; /* Byte 0 Bits 2-7 */ + unsigned char BusTransferRate; /* Byte 1 */ + unsigned char PreemptTimeOnBus; /* Byte 2 */ + unsigned char TimeOffBus; /* Byte 3 */ + unsigned char MailboxCount; /* Byte 4 */ + unsigned char MailboxAddress[3]; /* Bytes 5-7 */ + struct BusLogic_SynchronousValue SynchronousValuesID0to7[8]; /* Bytes 8-15 */ + unsigned char DisconnectPermittedID0to7; /* Byte 16 */ + unsigned char Signature; /* Byte 17 */ + unsigned char CharacterD; /* Byte 18 */ + unsigned char HostBusType; /* Byte 19 */ + unsigned char WideTransfersPermittedID0to7; /* Byte 20 */ + unsigned char WideTransfersActiveID0to7; /* Byte 21 */ + struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */ + unsigned char DisconnectPermittedID8to15; /* Byte 30 */ + unsigned char:8; /* Byte 31 */ + unsigned char WideTransfersPermittedID8to15; /* Byte 32 */ + unsigned char WideTransfersActiveID8to15; /* Byte 33 */ }; /* Define the Initialize Extended Mailbox request structure. */ -struct BusLogic_ExtendedMailboxRequest -{ - unsigned char MailboxCount; /* Byte 0 */ - u32 BaseMailboxAddress; /* Bytes 1-4 */ +struct BusLogic_ExtendedMailboxRequest { + unsigned char MailboxCount; /* Byte 0 */ + u32 BaseMailboxAddress; /* Bytes 1-4 */ } PACKED; @@ -536,67 +513,63 @@ struct BusLogic_ExtendedMailboxRequest the Modify I/O Address command. */ -enum BusLogic_ISACompatibleIOPort -{ - BusLogic_IO_330 = 0, - BusLogic_IO_334 = 1, - BusLogic_IO_230 = 2, - BusLogic_IO_234 = 3, - BusLogic_IO_130 = 4, - BusLogic_IO_134 = 5, - BusLogic_IO_Disable = 6, - BusLogic_IO_Disable2 = 7 +enum BusLogic_ISACompatibleIOPort { + BusLogic_IO_330 = 0, + BusLogic_IO_334 = 1, + BusLogic_IO_230 = 2, + BusLogic_IO_234 = 3, + BusLogic_IO_130 = 4, + BusLogic_IO_134 = 5, + BusLogic_IO_Disable = 6, + BusLogic_IO_Disable2 = 7 } PACKED; -struct BusLogic_PCIHostAdapterInformation -{ - enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;/* Byte 0 */ - unsigned char PCIAssignedIRQChannel; /* Byte 1 */ - boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ - boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ - unsigned char :2; /* Byte 2 Bits 2-3 */ - boolean JP1:1; /* Byte 2 Bit 4 */ - boolean JP2:1; /* Byte 2 Bit 5 */ - boolean JP3:1; /* Byte 2 Bit 6 */ - boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ - unsigned char :8; /* Byte 3 */ +struct BusLogic_PCIHostAdapterInformation { + enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort; /* Byte 0 */ + unsigned char PCIAssignedIRQChannel; /* Byte 1 */ + boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ + boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ + unsigned char:2; /* Byte 2 Bits 2-3 */ + boolean JP1:1; /* Byte 2 Bit 4 */ + boolean JP2:1; /* Byte 2 Bit 5 */ + boolean JP3:1; /* Byte 2 Bit 6 */ + boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ + unsigned char:8; /* Byte 3 */ }; /* Define the Inquire Extended Setup Information reply structure. */ -struct BusLogic_ExtendedSetupInformation -{ - unsigned char BusType; /* Byte 0 */ - unsigned char BIOS_Address; /* Byte 1 */ - unsigned short ScatterGatherLimit; /* Bytes 2-3 */ - unsigned char MailboxCount; /* Byte 4 */ - u32 BaseMailboxAddress; /* Bytes 5-8 */ - struct { - unsigned char :2; /* Byte 9 Bits 0-1 */ - boolean FastOnEISA:1; /* Byte 9 Bit 2 */ - unsigned char :3; /* Byte 9 Bits 3-5 */ - boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ - unsigned char :1; /* Byte 9 Bit 7 */ - } Misc; - unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ - boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ - boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ - boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ - boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ - unsigned char :3; /* Byte 13 Bits 5-7 */ +struct BusLogic_ExtendedSetupInformation { + unsigned char BusType; /* Byte 0 */ + unsigned char BIOS_Address; /* Byte 1 */ + unsigned short ScatterGatherLimit; /* Bytes 2-3 */ + unsigned char MailboxCount; /* Byte 4 */ + u32 BaseMailboxAddress; /* Bytes 5-8 */ + struct { + unsigned char:2; /* Byte 9 Bits 0-1 */ + boolean FastOnEISA:1; /* Byte 9 Bit 2 */ + unsigned char:3; /* Byte 9 Bits 3-5 */ + boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ + unsigned char:1; /* Byte 9 Bit 7 */ + } Misc; + unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ + boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ + boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ + boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ + boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ + boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ + unsigned char:3; /* Byte 13 Bits 5-7 */ } PACKED; /* Define the Enable Strict Round Robin Mode request type. */ -enum BusLogic_RoundRobinModeRequest -{ - BusLogic_AggressiveRoundRobinMode = 0, - BusLogic_StrictRoundRobinMode = 1 +enum BusLogic_RoundRobinModeRequest { + BusLogic_AggressiveRoundRobinMode = 0, + BusLogic_StrictRoundRobinMode = 1 } PACKED; @@ -607,96 +580,93 @@ enum BusLogic_RoundRobinModeRequest #define BusLogic_BIOS_BaseOffset 0 #define BusLogic_AutoSCSI_BaseOffset 64 -struct BusLogic_FetchHostAdapterLocalRAMRequest -{ - unsigned char ByteOffset; /* Byte 0 */ - unsigned char ByteCount; /* Byte 1 */ +struct BusLogic_FetchHostAdapterLocalRAMRequest { + unsigned char ByteOffset; /* Byte 0 */ + unsigned char ByteCount; /* Byte 1 */ }; /* Define the Host Adapter Local RAM AutoSCSI structure. */ -struct BusLogic_AutoSCSIData -{ - unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */ - unsigned char InformationByteCount; /* Byte 2 */ - unsigned char HostAdapterType[6]; /* Bytes 3-8 */ - unsigned char :8; /* Byte 9 */ - boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ - boolean FloppySecondary:1; /* Byte 10 Bit 1 */ - boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ - unsigned char :2; /* Byte 10 Bits 3-4 */ - unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ - unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ - boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ - unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ - boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ - unsigned char DMA_TransferRate; /* Byte 13 */ - unsigned char SCSI_ID; /* Byte 14 */ - boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ - boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ - boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ - boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ - boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ - boolean :1; /* Byte 15 Bit 6 */ - boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ - unsigned char BusOnDelay; /* Byte 16 */ - unsigned char BusOffDelay; /* Byte 17 */ - boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ - boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ - boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ - boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ - boolean :1; /* Byte 18 Bit 4 */ - boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ - boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ - boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ - unsigned short DeviceEnabled; /* Bytes 19-20 */ - unsigned short WidePermitted; /* Bytes 21-22 */ - unsigned short FastPermitted; /* Bytes 23-24 */ - unsigned short SynchronousPermitted; /* Bytes 25-26 */ - unsigned short DisconnectPermitted; /* Bytes 27-28 */ - unsigned short SendStartUnitCommand; /* Bytes 29-30 */ - unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ - unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ - unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ - boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ - boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ - boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ - boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ - unsigned short UltraPermitted; /* Bytes 34-35 */ - unsigned int :32; /* Bytes 36-39 */ - unsigned char :8; /* Byte 40 */ - unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ - boolean :1; /* Byte 42 Bit 0 */ - boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ - boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ - boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ - unsigned char :4; /* Byte 42 Bits 4-7 */ - boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ - boolean :1; /* Byte 43 Bit 1 */ - boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ - unsigned char :5; /* Byte 43 Bits 3-7 */ - unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ - unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ - unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */ - unsigned char :7; /* Byte 45 Bits 1-7 */ - unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */ - unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */ - unsigned char Reserved[10]; /* Bytes 50-59 */ - unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */ - unsigned short Checksum; /* Bytes 62-63 */ +struct BusLogic_AutoSCSIData { + unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */ + unsigned char InformationByteCount; /* Byte 2 */ + unsigned char HostAdapterType[6]; /* Bytes 3-8 */ + unsigned char:8; /* Byte 9 */ + boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ + boolean FloppySecondary:1; /* Byte 10 Bit 1 */ + boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ + unsigned char:2; /* Byte 10 Bits 3-4 */ + unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ + unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ + boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ + unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ + boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ + unsigned char DMA_TransferRate; /* Byte 13 */ + unsigned char SCSI_ID; /* Byte 14 */ + boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ + boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ + boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ + boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ + boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ + boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ + boolean:1; /* Byte 15 Bit 6 */ + boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ + unsigned char BusOnDelay; /* Byte 16 */ + unsigned char BusOffDelay; /* Byte 17 */ + boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ + boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ + boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ + boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ + boolean:1; /* Byte 18 Bit 4 */ + boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ + boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ + boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ + unsigned short DeviceEnabled; /* Bytes 19-20 */ + unsigned short WidePermitted; /* Bytes 21-22 */ + unsigned short FastPermitted; /* Bytes 23-24 */ + unsigned short SynchronousPermitted; /* Bytes 25-26 */ + unsigned short DisconnectPermitted; /* Bytes 27-28 */ + unsigned short SendStartUnitCommand; /* Bytes 29-30 */ + unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ + unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ + unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ + boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ + boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ + boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ + boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ + unsigned short UltraPermitted; /* Bytes 34-35 */ + unsigned int:32; /* Bytes 36-39 */ + unsigned char:8; /* Byte 40 */ + unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ + boolean:1; /* Byte 42 Bit 0 */ + boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ + boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ + boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ + unsigned char:4; /* Byte 42 Bits 4-7 */ + boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ + boolean:1; /* Byte 43 Bit 1 */ + boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ + unsigned char:5; /* Byte 43 Bits 3-7 */ + unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ + unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ + unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */ + unsigned char:7; /* Byte 45 Bits 1-7 */ + unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */ + unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */ + unsigned char Reserved[10]; /* Bytes 50-59 */ + unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */ + unsigned short Checksum; /* Bytes 62-63 */ } PACKED; /* Define the Host Adapter Local RAM Auto SCSI Byte 45 structure. */ -struct BusLogic_AutoSCSIByte45 -{ - unsigned char ForceBusDeviceScanningOrder:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ +struct BusLogic_AutoSCSIByte45 { + unsigned char ForceBusDeviceScanningOrder:1; /* Bit 0 */ + unsigned char:7; /* Bits 1-7 */ }; /* @@ -705,12 +675,11 @@ struct BusLogic_AutoSCSIByte45 #define BusLogic_BIOS_DriveMapOffset 17 -struct BusLogic_BIOSDriveMapByte -{ - unsigned char TargetIDBit3:1; /* Bit 0 */ - unsigned char :2; /* Bits 1-2 */ - enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */ - unsigned char TargetID:3; /* Bits 5-7 */ +struct BusLogic_BIOSDriveMapByte { + unsigned char TargetIDBit3:1; /* Bit 0 */ + unsigned char:2; /* Bits 1-2 */ + enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */ + unsigned char TargetID:3; /* Bits 5-7 */ }; /* @@ -718,21 +687,19 @@ struct BusLogic_BIOSDriveMapByte necessary to support more than 8 Logical Units per Target Device. */ -enum BusLogic_SetCCBFormatRequest -{ - BusLogic_LegacyLUNFormatCCB = 0, - BusLogic_ExtendedLUNFormatCCB = 1 +enum BusLogic_SetCCBFormatRequest { + BusLogic_LegacyLUNFormatCCB = 0, + BusLogic_ExtendedLUNFormatCCB = 1 } PACKED; /* Define the Outgoing Mailbox Action Codes. */ -enum BusLogic_ActionCode -{ - BusLogic_OutgoingMailboxFree = 0x00, - BusLogic_MailboxStartCommand = 0x01, - BusLogic_MailboxAbortCommand = 0x02 +enum BusLogic_ActionCode { + BusLogic_OutgoingMailboxFree = 0x00, + BusLogic_MailboxStartCommand = 0x01, + BusLogic_MailboxAbortCommand = 0x02 } PACKED; @@ -742,28 +709,26 @@ enum BusLogic_ActionCode completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5. */ -enum BusLogic_CompletionCode -{ - BusLogic_IncomingMailboxFree = 0x00, - BusLogic_CommandCompletedWithoutError = 0x01, - BusLogic_CommandAbortedAtHostRequest = 0x02, - BusLogic_AbortedCommandNotFound = 0x03, - BusLogic_CommandCompletedWithError = 0x04, - BusLogic_InvalidCCB = 0x05 +enum BusLogic_CompletionCode { + BusLogic_IncomingMailboxFree = 0x00, + BusLogic_CommandCompletedWithoutError = 0x01, + BusLogic_CommandAbortedAtHostRequest = 0x02, + BusLogic_AbortedCommandNotFound = 0x03, + BusLogic_CommandCompletedWithError = 0x04, + BusLogic_InvalidCCB = 0x05 } PACKED; /* Define the Command Control Block (CCB) Opcodes. */ -enum BusLogic_CCB_Opcode -{ - BusLogic_InitiatorCCB = 0x00, - BusLogic_TargetCCB = 0x01, - BusLogic_InitiatorCCB_ScatterGather = 0x02, - BusLogic_InitiatorCCB_ResidualDataLength = 0x03, - BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, - BusLogic_BusDeviceReset = 0x81 +enum BusLogic_CCB_Opcode { + BusLogic_InitiatorCCB = 0x00, + BusLogic_TargetCCB = 0x01, + BusLogic_InitiatorCCB_ScatterGather = 0x02, + BusLogic_InitiatorCCB_ResidualDataLength = 0x03, + BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, + BusLogic_BusDeviceReset = 0x81 } PACKED; @@ -771,12 +736,11 @@ enum BusLogic_CCB_Opcode Define the CCB Data Direction Codes. */ -enum BusLogic_DataDirection -{ - BusLogic_UncheckedDataTransfer = 0, - BusLogic_DataInLengthChecked = 1, - BusLogic_DataOutLengthChecked = 2, - BusLogic_NoDataTransfer = 3 +enum BusLogic_DataDirection { + BusLogic_UncheckedDataTransfer = 0, + BusLogic_DataInLengthChecked = 1, + BusLogic_DataOutLengthChecked = 2, + BusLogic_NoDataTransfer = 3 }; @@ -785,33 +749,32 @@ enum BusLogic_DataDirection return status code 0x0C; it uses 0x12 for both overruns and underruns. */ -enum BusLogic_HostAdapterStatus -{ - BusLogic_CommandCompletedNormally = 0x00, - BusLogic_LinkedCommandCompleted = 0x0A, - BusLogic_LinkedCommandCompletedWithFlag = 0x0B, - BusLogic_DataUnderRun = 0x0C, - BusLogic_SCSISelectionTimeout = 0x11, - BusLogic_DataOverRun = 0x12, - BusLogic_UnexpectedBusFree = 0x13, - BusLogic_InvalidBusPhaseRequested = 0x14, - BusLogic_InvalidOutgoingMailboxActionCode = 0x15, - BusLogic_InvalidCommandOperationCode = 0x16, - BusLogic_LinkedCCBhasInvalidLUN = 0x17, - BusLogic_InvalidCommandParameter = 0x1A, - BusLogic_AutoRequestSenseFailed = 0x1B, - BusLogic_TaggedQueuingMessageRejected = 0x1C, - BusLogic_UnsupportedMessageReceived = 0x1D, - BusLogic_HostAdapterHardwareFailed = 0x20, - BusLogic_TargetFailedResponseToATN = 0x21, - BusLogic_HostAdapterAssertedRST = 0x22, - BusLogic_OtherDeviceAssertedRST = 0x23, - BusLogic_TargetDeviceReconnectedImproperly = 0x24, - BusLogic_HostAdapterAssertedBusDeviceReset = 0x25, - BusLogic_AbortQueueGenerated = 0x26, - BusLogic_HostAdapterSoftwareError = 0x27, - BusLogic_HostAdapterHardwareTimeoutError = 0x30, - BusLogic_SCSIParityErrorDetected = 0x34 +enum BusLogic_HostAdapterStatus { + BusLogic_CommandCompletedNormally = 0x00, + BusLogic_LinkedCommandCompleted = 0x0A, + BusLogic_LinkedCommandCompletedWithFlag = 0x0B, + BusLogic_DataUnderRun = 0x0C, + BusLogic_SCSISelectionTimeout = 0x11, + BusLogic_DataOverRun = 0x12, + BusLogic_UnexpectedBusFree = 0x13, + BusLogic_InvalidBusPhaseRequested = 0x14, + BusLogic_InvalidOutgoingMailboxActionCode = 0x15, + BusLogic_InvalidCommandOperationCode = 0x16, + BusLogic_LinkedCCBhasInvalidLUN = 0x17, + BusLogic_InvalidCommandParameter = 0x1A, + BusLogic_AutoRequestSenseFailed = 0x1B, + BusLogic_TaggedQueuingMessageRejected = 0x1C, + BusLogic_UnsupportedMessageReceived = 0x1D, + BusLogic_HostAdapterHardwareFailed = 0x20, + BusLogic_TargetFailedResponseToATN = 0x21, + BusLogic_HostAdapterAssertedRST = 0x22, + BusLogic_OtherDeviceAssertedRST = 0x23, + BusLogic_TargetDeviceReconnectedImproperly = 0x24, + BusLogic_HostAdapterAssertedBusDeviceReset = 0x25, + BusLogic_AbortQueueGenerated = 0x26, + BusLogic_HostAdapterSoftwareError = 0x27, + BusLogic_HostAdapterHardwareTimeoutError = 0x30, + BusLogic_SCSIParityErrorDetected = 0x34 } PACKED; @@ -819,23 +782,21 @@ enum BusLogic_HostAdapterStatus Define the SCSI Target Device Status Codes. */ -enum BusLogic_TargetDeviceStatus -{ - BusLogic_OperationGood = 0x00, - BusLogic_CheckCondition = 0x02, - BusLogic_DeviceBusy = 0x08 +enum BusLogic_TargetDeviceStatus { + BusLogic_OperationGood = 0x00, + BusLogic_CheckCondition = 0x02, + BusLogic_DeviceBusy = 0x08 } PACKED; /* Define the Queue Tag Codes. */ -enum BusLogic_QueueTag -{ - BusLogic_SimpleQueueTag = 0, - BusLogic_HeadOfQueueTag = 1, - BusLogic_OrderedQueueTag = 2, - BusLogic_ReservedQT = 3 +enum BusLogic_QueueTag { + BusLogic_SimpleQueueTag = 0, + BusLogic_HeadOfQueueTag = 1, + BusLogic_OrderedQueueTag = 2, + BusLogic_ReservedQT = 3 }; /* @@ -852,22 +813,20 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength]; Firmware Interface and the FlashPoint SCCB Manager. */ -struct BusLogic_ScatterGatherSegment -{ - u32 SegmentByteCount; /* Bytes 0-3 */ - u32 SegmentDataPointer; /* Bytes 4-7 */ +struct BusLogic_ScatterGatherSegment { + u32 SegmentByteCount; /* Bytes 0-3 */ + u32 SegmentDataPointer; /* Bytes 4-7 */ }; /* Define the Driver CCB Status Codes. */ -enum BusLogic_CCB_Status -{ - BusLogic_CCB_Free = 0, - BusLogic_CCB_Active = 1, - BusLogic_CCB_Completed = 2, - BusLogic_CCB_Reset = 3 +enum BusLogic_CCB_Status { + BusLogic_CCB_Free = 0, + BusLogic_CCB_Active = 1, + BusLogic_CCB_Completed = 2, + BusLogic_CCB_Reset = 3 } PACKED; @@ -890,82 +849,79 @@ enum BusLogic_CCB_Status 32 Logical Units per Target Device. */ -struct BusLogic_CCB -{ - /* - MultiMaster Firmware and FlashPoint SCCB Manager Common Portion. - */ - enum BusLogic_CCB_Opcode Opcode; /* Byte 0 */ - unsigned char :3; /* Byte 1 Bits 0-2 */ - enum BusLogic_DataDirection DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean TagEnable:1; /* Byte 1 Bit 5 */ - enum BusLogic_QueueTag QueueTag:2; /* Byte 1 Bits 6-7 */ - unsigned char CDB_Length; /* Byte 2 */ - unsigned char SenseDataLength; /* Byte 3 */ - u32 DataLength; /* Bytes 4-7 */ - u32 DataPointer; /* Bytes 8-11 */ - unsigned char :8; /* Byte 12 */ - unsigned char :8; /* Byte 13 */ - enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 14 */ - enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */ - unsigned char TargetID; /* Byte 16 */ - unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ - boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ - enum BusLogic_QueueTag LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ - SCSI_CDB_T CDB; /* Bytes 18-29 */ - unsigned char :8; /* Byte 30 */ - unsigned char :8; /* Byte 31 */ - unsigned int :32; /* Bytes 32-35 */ - u32 SenseDataPointer; /* Bytes 36-39 */ - /* - FlashPoint SCCB Manager Defined Portion. - */ - void (*CallbackFunction)(struct BusLogic_CCB *); /* Bytes 40-43 */ - u32 BaseAddress; /* Bytes 44-47 */ - enum BusLogic_CompletionCode CompletionCode; /* Byte 48 */ +struct BusLogic_CCB { + /* + MultiMaster Firmware and FlashPoint SCCB Manager Common Portion. + */ + enum BusLogic_CCB_Opcode Opcode; /* Byte 0 */ + unsigned char:3; /* Byte 1 Bits 0-2 */ + enum BusLogic_DataDirection DataDirection:2; /* Byte 1 Bits 3-4 */ + boolean TagEnable:1; /* Byte 1 Bit 5 */ + enum BusLogic_QueueTag QueueTag:2; /* Byte 1 Bits 6-7 */ + unsigned char CDB_Length; /* Byte 2 */ + unsigned char SenseDataLength; /* Byte 3 */ + u32 DataLength; /* Bytes 4-7 */ + u32 DataPointer; /* Bytes 8-11 */ + unsigned char:8; /* Byte 12 */ + unsigned char:8; /* Byte 13 */ + enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 14 */ + enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */ + unsigned char TargetID; /* Byte 16 */ + unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ + boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ + enum BusLogic_QueueTag LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ + SCSI_CDB_T CDB; /* Bytes 18-29 */ + unsigned char:8; /* Byte 30 */ + unsigned char:8; /* Byte 31 */ + unsigned int:32; /* Bytes 32-35 */ + u32 SenseDataPointer; /* Bytes 36-39 */ + /* + FlashPoint SCCB Manager Defined Portion. + */ + void (*CallbackFunction) (struct BusLogic_CCB *); /* Bytes 40-43 */ + u32 BaseAddress; /* Bytes 44-47 */ + enum BusLogic_CompletionCode CompletionCode; /* Byte 48 */ #ifndef CONFIG_SCSI_OMIT_FLASHPOINT - unsigned char :8; /* Byte 49 */ - unsigned short OS_Flags; /* Bytes 50-51 */ - unsigned char Private[48]; /* Bytes 52-99 */ + unsigned char:8; /* Byte 49 */ + unsigned short OS_Flags; /* Bytes 50-51 */ + unsigned char Private[48]; /* Bytes 52-99 */ #endif - /* - BusLogic Linux Driver Defined Portion. - */ - dma_addr_t AllocationGroupHead; - unsigned int AllocationGroupSize; - u32 DMA_Handle; - enum BusLogic_CCB_Status Status; - unsigned long SerialNumber; - struct scsi_cmnd *Command; - struct BusLogic_HostAdapter *HostAdapter; - struct BusLogic_CCB *Next; - struct BusLogic_CCB *NextAll; - struct BusLogic_ScatterGatherSegment - ScatterGatherList[BusLogic_ScatterGatherLimit]; + /* + BusLogic Linux Driver Defined Portion. + */ + dma_addr_t AllocationGroupHead; + unsigned int AllocationGroupSize; + u32 DMA_Handle; + enum BusLogic_CCB_Status Status; + unsigned long SerialNumber; + struct scsi_cmnd *Command; + struct BusLogic_HostAdapter *HostAdapter; + struct BusLogic_CCB *Next; + struct BusLogic_CCB *NextAll; + struct BusLogic_ScatterGatherSegment + ScatterGatherList[BusLogic_ScatterGatherLimit]; }; /* Define the 32 Bit Mode Outgoing Mailbox structure. */ -struct BusLogic_OutgoingMailbox -{ - u32 CCB; /* Bytes 0-3 */ - unsigned int :24; /* Bytes 4-6 */ - enum BusLogic_ActionCode ActionCode; /* Byte 7 */ +struct BusLogic_OutgoingMailbox { + u32 CCB; /* Bytes 0-3 */ + unsigned int:24; /* Bytes 4-6 */ + enum BusLogic_ActionCode ActionCode; /* Byte 7 */ }; /* Define the 32 Bit Mode Incoming Mailbox structure. */ -struct BusLogic_IncomingMailbox -{ - u32 CCB; /* Bytes 0-3 */ - enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 4 */ - enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - enum BusLogic_CompletionCode CompletionCode; /* Byte 7 */ +struct BusLogic_IncomingMailbox { + u32 CCB; /* Bytes 0-3 */ + enum BusLogic_HostAdapterStatus HostAdapterStatus; /* Byte 4 */ + enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 5 */ + unsigned char:8; /* Byte 6 */ + enum BusLogic_CompletionCode CompletionCode; /* Byte 7 */ }; @@ -973,29 +929,27 @@ struct BusLogic_IncomingMailbox Define the BusLogic Driver Options structure. */ -struct BusLogic_DriverOptions -{ - unsigned short TaggedQueuingPermitted; - unsigned short TaggedQueuingPermittedMask; - unsigned short BusSettleTime; - struct BusLogic_LocalOptions LocalOptions; - unsigned char CommonQueueDepth; - unsigned char QueueDepth[BusLogic_MaxTargetDevices]; +struct BusLogic_DriverOptions { + unsigned short TaggedQueuingPermitted; + unsigned short TaggedQueuingPermittedMask; + unsigned short BusSettleTime; + struct BusLogic_LocalOptions LocalOptions; + unsigned char CommonQueueDepth; + unsigned char QueueDepth[BusLogic_MaxTargetDevices]; }; /* Define the Host Adapter Target Flags structure. */ -struct BusLogic_TargetFlags -{ - boolean TargetExists:1; - boolean TaggedQueuingSupported:1; - boolean WideTransfersSupported:1; - boolean TaggedQueuingActive:1; - boolean WideTransfersActive:1; - boolean CommandSuccessfulFlag:1; - boolean TargetInfoReported:1; +struct BusLogic_TargetFlags { + boolean TargetExists:1; + boolean TaggedQueuingSupported:1; + boolean WideTransfersSupported:1; + boolean TaggedQueuingActive:1; + boolean WideTransfersActive:1; + boolean CommandSuccessfulFlag:1; + boolean TargetInfoReported:1; }; /* @@ -1006,25 +960,24 @@ struct BusLogic_TargetFlags typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets]; -struct BusLogic_TargetStatistics -{ - unsigned int CommandsAttempted; - unsigned int CommandsCompleted; - unsigned int ReadCommands; - unsigned int WriteCommands; - struct BusLogic_ByteCounter TotalBytesRead; - struct BusLogic_ByteCounter TotalBytesWritten; - BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets; - BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets; - unsigned short CommandAbortsRequested; - unsigned short CommandAbortsAttempted; - unsigned short CommandAbortsCompleted; - unsigned short BusDeviceResetsRequested; - unsigned short BusDeviceResetsAttempted; - unsigned short BusDeviceResetsCompleted; - unsigned short HostAdapterResetsRequested; - unsigned short HostAdapterResetsAttempted; - unsigned short HostAdapterResetsCompleted; +struct BusLogic_TargetStatistics { + unsigned int CommandsAttempted; + unsigned int CommandsCompleted; + unsigned int ReadCommands; + unsigned int WriteCommands; + struct BusLogic_ByteCounter TotalBytesRead; + struct BusLogic_ByteCounter TotalBytesWritten; + BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets; + BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets; + unsigned short CommandAbortsRequested; + unsigned short CommandAbortsAttempted; + unsigned short CommandAbortsCompleted; + unsigned short BusDeviceResetsRequested; + unsigned short BusDeviceResetsAttempted; + unsigned short BusDeviceResetsCompleted; + unsigned short HostAdapterResetsRequested; + unsigned short HostAdapterResetsAttempted; + unsigned short HostAdapterResetsCompleted; }; /* @@ -1041,227 +994,181 @@ typedef unsigned int FlashPoint_CardHandle_T; by the FlashPoint SCCB Manager. */ -struct FlashPoint_Info -{ - u32 BaseAddress; /* Bytes 0-3 */ - boolean Present; /* Byte 4 */ - unsigned char IRQ_Channel; /* Byte 5 */ - unsigned char SCSI_ID; /* Byte 6 */ - unsigned char SCSI_LUN; /* Byte 7 */ - unsigned short FirmwareRevision; /* Bytes 8-9 */ - unsigned short SynchronousPermitted; /* Bytes 10-11 */ - unsigned short FastPermitted; /* Bytes 12-13 */ - unsigned short UltraPermitted; /* Bytes 14-15 */ - unsigned short DisconnectPermitted; /* Bytes 16-17 */ - unsigned short WidePermitted; /* Bytes 18-19 */ - boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ - boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ - boolean HostSoftReset:1; /* Byte 20 Bit 2 */ - boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ - boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ - boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ - boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ - boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ - boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ - unsigned char :7; /* Byte 21 Bits 1-7 */ - unsigned char Family; /* Byte 22 */ - unsigned char BusType; /* Byte 23 */ - unsigned char ModelNumber[3]; /* Bytes 24-26 */ - unsigned char RelativeCardNumber; /* Byte 27 */ - unsigned char Reserved[4]; /* Bytes 28-31 */ - unsigned int OS_Reserved; /* Bytes 32-35 */ - unsigned char TranslationInfo[4]; /* Bytes 36-39 */ - unsigned int Reserved2[5]; /* Bytes 40-59 */ - unsigned int SecondaryRange; /* Bytes 60-63 */ +struct FlashPoint_Info { + u32 BaseAddress; /* Bytes 0-3 */ + boolean Present; /* Byte 4 */ + unsigned char IRQ_Channel; /* Byte 5 */ + unsigned char SCSI_ID; /* Byte 6 */ + unsigned char SCSI_LUN; /* Byte 7 */ + unsigned short FirmwareRevision; /* Bytes 8-9 */ + unsigned short SynchronousPermitted; /* Bytes 10-11 */ + unsigned short FastPermitted; /* Bytes 12-13 */ + unsigned short UltraPermitted; /* Bytes 14-15 */ + unsigned short DisconnectPermitted; /* Bytes 16-17 */ + unsigned short WidePermitted; /* Bytes 18-19 */ + boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ + boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ + boolean HostSoftReset:1; /* Byte 20 Bit 2 */ + boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ + boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ + boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ + boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ + boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ + boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ + unsigned char:7; /* Byte 21 Bits 1-7 */ + unsigned char Family; /* Byte 22 */ + unsigned char BusType; /* Byte 23 */ + unsigned char ModelNumber[3]; /* Bytes 24-26 */ + unsigned char RelativeCardNumber; /* Byte 27 */ + unsigned char Reserved[4]; /* Bytes 28-31 */ + unsigned int OS_Reserved; /* Bytes 32-35 */ + unsigned char TranslationInfo[4]; /* Bytes 36-39 */ + unsigned int Reserved2[5]; /* Bytes 40-59 */ + unsigned int SecondaryRange; /* Bytes 60-63 */ }; /* Define the BusLogic Driver Host Adapter structure. */ -struct BusLogic_HostAdapter -{ - struct Scsi_Host *SCSI_Host; - struct pci_dev *PCI_Device; - enum BusLogic_HostAdapterType HostAdapterType; - enum BusLogic_HostAdapterBusType HostAdapterBusType; - unsigned long IO_Address; - unsigned long PCI_Address; - unsigned short AddressCount; - unsigned char HostNumber; - unsigned char ModelName[9]; - unsigned char FirmwareVersion[6]; - unsigned char FullModelName[18]; - unsigned char Bus; - unsigned char Device; - unsigned char IRQ_Channel; - unsigned char DMA_Channel; - unsigned char SCSI_ID; - boolean IRQ_ChannelAcquired:1; - boolean DMA_ChannelAcquired:1; - boolean ExtendedTranslationEnabled:1; - boolean ParityCheckingEnabled:1; - boolean BusResetEnabled:1; - boolean LevelSensitiveInterrupt:1; - boolean HostWideSCSI:1; - boolean HostDifferentialSCSI:1; - boolean HostSupportsSCAM:1; - boolean HostUltraSCSI:1; - boolean ExtendedLUNSupport:1; - boolean TerminationInfoValid:1; - boolean LowByteTerminated:1; - boolean HighByteTerminated:1; - boolean BounceBuffersRequired:1; - boolean StrictRoundRobinModeSupport:1; - boolean SCAM_Enabled:1; - boolean SCAM_Level2:1; - boolean HostAdapterInitialized:1; - boolean HostAdapterExternalReset:1; - boolean HostAdapterInternalError:1; - boolean ProcessCompletedCCBsActive; - volatile boolean HostAdapterCommandCompleted; - unsigned short HostAdapterScatterGatherLimit; - unsigned short DriverScatterGatherLimit; - unsigned short MaxTargetDevices; - unsigned short MaxLogicalUnits; - unsigned short MailboxCount; - unsigned short InitialCCBs; - unsigned short IncrementalCCBs; - unsigned short AllocatedCCBs; - unsigned short DriverQueueDepth; - unsigned short HostAdapterQueueDepth; - unsigned short UntaggedQueueDepth; - unsigned short CommonQueueDepth; - unsigned short BusSettleTime; - unsigned short SynchronousPermitted; - unsigned short FastPermitted; - unsigned short UltraPermitted; - unsigned short WidePermitted; - unsigned short DisconnectPermitted; - unsigned short TaggedQueuingPermitted; - unsigned short ExternalHostAdapterResets; - unsigned short HostAdapterInternalErrors; - unsigned short TargetDeviceCount; - unsigned short MessageBufferLength; - u32 BIOS_Address; - struct BusLogic_DriverOptions *DriverOptions; - struct FlashPoint_Info FlashPointInfo; - FlashPoint_CardHandle_T CardHandle; - struct BusLogic_HostAdapter *Next; - struct BusLogic_CCB *All_CCBs; - struct BusLogic_CCB *Free_CCBs; - struct BusLogic_CCB *FirstCompletedCCB; - struct BusLogic_CCB *LastCompletedCCB; - struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices]; - struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices]; - unsigned char QueueDepth[BusLogic_MaxTargetDevices]; - unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices]; - unsigned char SynchronousOffset[BusLogic_MaxTargetDevices]; - unsigned char ActiveCommands[BusLogic_MaxTargetDevices]; - unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices]; - unsigned long LastSequencePoint[BusLogic_MaxTargetDevices]; - unsigned long LastResetAttempted[BusLogic_MaxTargetDevices]; - unsigned long LastResetCompleted[BusLogic_MaxTargetDevices]; - struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox; - struct BusLogic_OutgoingMailbox *LastOutgoingMailbox; - struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; - struct BusLogic_IncomingMailbox *FirstIncomingMailbox; - struct BusLogic_IncomingMailbox *LastIncomingMailbox; - struct BusLogic_IncomingMailbox *NextIncomingMailbox; - struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices]; - unsigned char *MailboxSpace; - dma_addr_t MailboxSpaceHandle; - unsigned int MailboxSize; - unsigned long CCB_Offset; - char MessageBuffer[BusLogic_MessageBufferSize]; +struct BusLogic_HostAdapter { + struct Scsi_Host *SCSI_Host; + struct pci_dev *PCI_Device; + enum BusLogic_HostAdapterType HostAdapterType; + enum BusLogic_HostAdapterBusType HostAdapterBusType; + unsigned long IO_Address; + unsigned long PCI_Address; + unsigned short AddressCount; + unsigned char HostNumber; + unsigned char ModelName[9]; + unsigned char FirmwareVersion[6]; + unsigned char FullModelName[18]; + unsigned char Bus; + unsigned char Device; + unsigned char IRQ_Channel; + unsigned char DMA_Channel; + unsigned char SCSI_ID; + boolean IRQ_ChannelAcquired:1; + boolean DMA_ChannelAcquired:1; + boolean ExtendedTranslationEnabled:1; + boolean ParityCheckingEnabled:1; + boolean BusResetEnabled:1; + boolean LevelSensitiveInterrupt:1; + boolean HostWideSCSI:1; + boolean HostDifferentialSCSI:1; + boolean HostSupportsSCAM:1; + boolean HostUltraSCSI:1; + boolean ExtendedLUNSupport:1; + boolean TerminationInfoValid:1; + boolean LowByteTerminated:1; + boolean HighByteTerminated:1; + boolean BounceBuffersRequired:1; + boolean StrictRoundRobinModeSupport:1; + boolean SCAM_Enabled:1; + boolean SCAM_Level2:1; + boolean HostAdapterInitialized:1; + boolean HostAdapterExternalReset:1; + boolean HostAdapterInternalError:1; + boolean ProcessCompletedCCBsActive; + volatile boolean HostAdapterCommandCompleted; + unsigned short HostAdapterScatterGatherLimit; + unsigned short DriverScatterGatherLimit; + unsigned short MaxTargetDevices; + unsigned short MaxLogicalUnits; + unsigned short MailboxCount; + unsigned short InitialCCBs; + unsigned short IncrementalCCBs; + unsigned short AllocatedCCBs; + unsigned short DriverQueueDepth; + unsigned short HostAdapterQueueDepth; + unsigned short UntaggedQueueDepth; + unsigned short CommonQueueDepth; + unsigned short BusSettleTime; + unsigned short SynchronousPermitted; + unsigned short FastPermitted; + unsigned short UltraPermitted; + unsigned short WidePermitted; + unsigned short DisconnectPermitted; + unsigned short TaggedQueuingPermitted; + unsigned short ExternalHostAdapterResets; + unsigned short HostAdapterInternalErrors; + unsigned short TargetDeviceCount; + unsigned short MessageBufferLength; + u32 BIOS_Address; + struct BusLogic_DriverOptions *DriverOptions; + struct FlashPoint_Info FlashPointInfo; + FlashPoint_CardHandle_T CardHandle; + struct list_head host_list; + struct BusLogic_CCB *All_CCBs; + struct BusLogic_CCB *Free_CCBs; + struct BusLogic_CCB *FirstCompletedCCB; + struct BusLogic_CCB *LastCompletedCCB; + struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices]; + struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices]; + unsigned char QueueDepth[BusLogic_MaxTargetDevices]; + unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices]; + unsigned char SynchronousOffset[BusLogic_MaxTargetDevices]; + unsigned char ActiveCommands[BusLogic_MaxTargetDevices]; + unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices]; + unsigned long LastSequencePoint[BusLogic_MaxTargetDevices]; + unsigned long LastResetAttempted[BusLogic_MaxTargetDevices]; + unsigned long LastResetCompleted[BusLogic_MaxTargetDevices]; + struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox; + struct BusLogic_OutgoingMailbox *LastOutgoingMailbox; + struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; + struct BusLogic_IncomingMailbox *FirstIncomingMailbox; + struct BusLogic_IncomingMailbox *LastIncomingMailbox; + struct BusLogic_IncomingMailbox *NextIncomingMailbox; + struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices]; + unsigned char *MailboxSpace; + dma_addr_t MailboxSpaceHandle; + unsigned int MailboxSize; + unsigned long CCB_Offset; + char MessageBuffer[BusLogic_MessageBufferSize]; }; /* Define a structure for the BIOS Disk Parameters. */ -struct BIOS_DiskParameters -{ - int Heads; - int Sectors; - int Cylinders; +struct BIOS_DiskParameters { + int Heads; + int Sectors; + int Cylinders; }; /* Define a structure for the SCSI Inquiry command results. */ -struct SCSI_Inquiry -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ - unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ - unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ - unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ - unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ - unsigned char :2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ - unsigned char AdditionalLength; /* Byte 4 */ - unsigned char :8; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean :1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ - unsigned char VendorIdentification[8]; /* Bytes 8-15 */ - unsigned char ProductIdentification[16]; /* Bytes 16-31 */ - unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ +struct SCSI_Inquiry { + unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ + unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ + unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ + boolean RMB:1; /* Byte 1 Bit 7 */ + unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ + unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ + unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ + unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ + unsigned char:2; /* Byte 3 Bits 4-5 */ + boolean TrmIOP:1; /* Byte 3 Bit 6 */ + boolean AENC:1; /* Byte 3 Bit 7 */ + unsigned char AdditionalLength; /* Byte 4 */ + unsigned char:8; /* Byte 5 */ + unsigned char:8; /* Byte 6 */ + boolean SftRe:1; /* Byte 7 Bit 0 */ + boolean CmdQue:1; /* Byte 7 Bit 1 */ + boolean:1; /* Byte 7 Bit 2 */ + boolean Linked:1; /* Byte 7 Bit 3 */ + boolean Sync:1; /* Byte 7 Bit 4 */ + boolean WBus16:1; /* Byte 7 Bit 5 */ + boolean WBus32:1; /* Byte 7 Bit 6 */ + boolean RelAdr:1; /* Byte 7 Bit 7 */ + unsigned char VendorIdentification[8]; /* Bytes 8-15 */ + unsigned char ProductIdentification[16]; /* Bytes 16-31 */ + unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ }; -/* - BusLogic_AcquireHostAdapterLock acquires exclusive access to Host Adapter. -*/ - -static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter) -{ - spin_lock_irq(HostAdapter->SCSI_Host->host_lock); -} - -/* - BusLogic_ReleaseHostAdapterLock releases exclusive access to Host Adapter. -*/ - -static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter) -{ - spin_unlock_irq(HostAdapter->SCSI_Host->host_lock); -} - - -/* - BusLogic_AcquireHostAdapterLockIH acquires exclusive access to Host Adapter, - but is only called from the interrupt handler. -*/ - -static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, - unsigned long *ProcessorFlags) -{ - spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags); -} - - -/* - BusLogic_ReleaseHostAdapterLockIH releases exclusive access to Host Adapter, - but is only called from the interrupt handler. -*/ - -static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, - unsigned long *ProcessorFlags) -{ - spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags); -} - /* Define functions to provide an abstraction for reading and writing the @@ -1270,65 +1177,60 @@ static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter static inline void BusLogic_SCSIBusReset(struct BusLogic_HostAdapter *HostAdapter) { - union BusLogic_ControlRegister ControlRegister; - ControlRegister.All = 0; - ControlRegister.cr.SCSIBusReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); + union BusLogic_ControlRegister ControlRegister; + ControlRegister.All = 0; + ControlRegister.cr.SCSIBusReset = true; + outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } static inline void BusLogic_InterruptReset(struct BusLogic_HostAdapter *HostAdapter) { - union BusLogic_ControlRegister ControlRegister; - ControlRegister.All = 0; - ControlRegister.cr.InterruptReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); + union BusLogic_ControlRegister ControlRegister; + ControlRegister.All = 0; + ControlRegister.cr.InterruptReset = true; + outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } static inline void BusLogic_SoftReset(struct BusLogic_HostAdapter *HostAdapter) { - union BusLogic_ControlRegister ControlRegister; - ControlRegister.All = 0; - ControlRegister.cr.SoftReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); + union BusLogic_ControlRegister ControlRegister; + ControlRegister.All = 0; + ControlRegister.cr.SoftReset = true; + outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } static inline void BusLogic_HardReset(struct BusLogic_HostAdapter *HostAdapter) { - union BusLogic_ControlRegister ControlRegister; - ControlRegister.All = 0; - ControlRegister.cr.HardReset = true; - outb(ControlRegister.All, - HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); + union BusLogic_ControlRegister ControlRegister; + ControlRegister.All = 0; + ControlRegister.cr.HardReset = true; + outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } static inline unsigned char BusLogic_ReadStatusRegister(struct BusLogic_HostAdapter *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset); + return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset); } static inline void BusLogic_WriteCommandParameterRegister(struct BusLogic_HostAdapter - *HostAdapter, - unsigned char Value) + *HostAdapter, unsigned char Value) { - outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset); + outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset); } static inline unsigned char BusLogic_ReadDataInRegister(struct BusLogic_HostAdapter *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset); + return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset); } static inline unsigned char BusLogic_ReadInterruptRegister(struct BusLogic_HostAdapter *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset); + return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset); } static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAdapter *HostAdapter) { - return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset); + return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset); } /* @@ -1339,7 +1241,7 @@ static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAd static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *HostAdapter) { - BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand); + BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand); } /* @@ -1348,7 +1250,7 @@ static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *Hos static inline void BusLogic_Delay(int Seconds) { - mdelay(1000 * Seconds); + mdelay(1000 * Seconds); } /* @@ -1358,12 +1260,12 @@ static inline void BusLogic_Delay(int Seconds) static inline u32 Virtual_to_Bus(void *VirtualAddress) { - return (u32) virt_to_bus(VirtualAddress); + return (u32) virt_to_bus(VirtualAddress); } static inline void *Bus_to_Virtual(u32 BusAddress) { - return (void *) bus_to_virt(BusAddress); + return (void *) bus_to_virt(BusAddress); } /* @@ -1374,7 +1276,7 @@ static inline void *Bus_to_Virtual(u32 BusAddress) static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress) { - return (u32) (unsigned long) VirtualAddress; + return (u32) (unsigned long) VirtualAddress; } /* @@ -1384,7 +1286,8 @@ static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress) static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter) { - if (*ErrorCounter < 65535) (*ErrorCounter)++; + if (*ErrorCounter < 65535) + (*ErrorCounter)++; } /* @@ -1392,40 +1295,35 @@ static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter) */ static inline void BusLogic_IncrementByteCounter(struct BusLogic_ByteCounter - *ByteCounter, - unsigned int Amount) + *ByteCounter, unsigned int Amount) { - ByteCounter->Units += Amount; - if (ByteCounter->Units > 999999999) - { - ByteCounter->Units -= 1000000000; - ByteCounter->Billions++; - } + ByteCounter->Units += Amount; + if (ByteCounter->Units > 999999999) { + ByteCounter->Units -= 1000000000; + ByteCounter->Billions++; + } } /* BusLogic_IncrementSizeBucket increments the Bucket for Amount. */ -static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T - CommandSizeBuckets, - unsigned int Amount) -{ - int Index = 0; - if (Amount < 8*1024) - { - if (Amount < 2*1024) - Index = (Amount < 1*1024 ? 0 : 1); - else Index = (Amount < 4*1024 ? 2 : 3); - } - else if (Amount < 128*1024) - { - if (Amount < 32*1024) - Index = (Amount < 16*1024 ? 4 : 5); - else Index = (Amount < 64*1024 ? 6 : 7); - } - else Index = (Amount < 256*1024 ? 8 : 9); - CommandSizeBuckets[Index]++; +static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets, unsigned int Amount) +{ + int Index = 0; + if (Amount < 8 * 1024) { + if (Amount < 2 * 1024) + Index = (Amount < 1 * 1024 ? 0 : 1); + else + Index = (Amount < 4 * 1024 ? 2 : 3); + } else if (Amount < 128 * 1024) { + if (Amount < 32 * 1024) + Index = (Amount < 16 * 1024 ? 4 : 5); + else + Index = (Amount < 64 * 1024 ? 6 : 7); + } else + Index = (Amount < 256 * 1024 ? 8 : 9); + CommandSizeBuckets[Index]++; } /* @@ -1448,22 +1346,14 @@ static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T */ static const char *BusLogic_DriverInfo(struct Scsi_Host *); -static int BusLogic_DetectHostAdapter(struct scsi_host_template *); -static int BusLogic_ReleaseHostAdapter(struct Scsi_Host *); -static int BusLogic_QueueCommand(struct scsi_cmnd *, - void (*CompletionRoutine)(struct scsi_cmnd *)); -static int BusLogic_BIOSDiskParameters(struct scsi_device *, - struct block_device *, - sector_t, int *); -static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, - char **, off_t, int, int); +static int BusLogic_QueueCommand(struct scsi_cmnd *, void (*CompletionRoutine) (struct scsi_cmnd *)); +static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *); +static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int); static int BusLogic_SlaveConfigure(struct scsi_device *); static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *); static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *); -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, - boolean HardReset); -static void BusLogic_Message(enum BusLogic_MessageLevel, char *, - struct BusLogic_HostAdapter *, ...); +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset); +static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...); static int __init BusLogic_Setup(char *); -#endif /* _BUSLOGIC_H */ +#endif /* _BUSLOGIC_H */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 711865972..fbd8ffa04 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -313,14 +313,14 @@ config SCSI_AHA1740 module will be called aha1740. config SCSI_AACRAID - tristate "Adaptec AACRAID support (EXPERIMENTAL)" - depends on EXPERIMENTAL && SCSI && PCI + tristate "Adaptec AACRAID support" + depends on SCSI && PCI source "drivers/scsi/aic7xxx/Kconfig.aic7xxx" config SCSI_AIC7XXX_OLD tristate "Adaptec AIC7xxx support (old driver)" - depends on SCSI + depends on (ISA || EISA || PCI ) && SCSI help WARNING This driver is an older aic7xxx driver and is no longer under active development. Adaptec, Inc. is writing a new driver to @@ -395,28 +395,28 @@ config SCSI_IN2000 To compile this driver as a module, choose M here: the module will be called in2000. -config SCSI_MEGARAID - tristate "AMI MegaRAID support" - depends on PCI && SCSI - help - This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490 - and 467 SCSI host adapters. - - To compile this driver as a module, choose M here: the - module will be called megaraid. +source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_SATA bool "Serial ATA (SATA) support" - depends on SCSI && EXPERIMENTAL + depends on SCSI help This driver family supports Serial ATA host controllers and devices. If unsure, say N. +config SCSI_SATA_AHCI + tristate "AHCI SATA support" + depends on SCSI_SATA && PCI + help + This option enables support for AHCI Serial ATA. + + If unsure, say N. + config SCSI_SATA_SVW - tristate "ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)" - depends on SCSI_SATA && PCI && EXPERIMENTAL + tristate "ServerWorks Frodo / Apple K2 SATA support" + depends on SCSI_SATA && PCI help This option enables support for Broadcom/Serverworks/Apple K2 SATA support. @@ -467,15 +467,23 @@ config SCSI_SATA_SIL config SCSI_SATA_SIS tristate "SiS 964/180 SATA support" - depends on SCSI_SATA && PCI + depends on SCSI_SATA && PCI && EXPERIMENTAL help This option enables support for SiS Serial ATA 964/180. If unsure, say N. +config SCSI_SATA_ULI + tristate "ULi Electronics SATA support" + depends on SCSI_SATA && PCI && EXPERIMENTAL + help + This option enables support for ULi Electronics SATA. + + If unsure, say N. + config SCSI_SATA_VIA tristate "VIA SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL + depends on SCSI_SATA && PCI help This option enables support for VIA Serial ATA. @@ -483,7 +491,7 @@ config SCSI_SATA_VIA config SCSI_SATA_VITESSE tristate "VITESSE VSC-7174 SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL + depends on SCSI_SATA && PCI help This option enables support for Vitesse VSC7174 Serial ATA. @@ -595,7 +603,7 @@ config SCSI_EATA_MAX_TAGS config SCSI_EATA_PIO tristate "EATA-PIO (old DPT PM2001, PM2012A) support" - depends on SCSI + depends on (ISA || EISA || PCI) && SCSI ---help--- This driver supports all EATA-PIO protocol compliant SCSI Host Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant @@ -780,9 +788,18 @@ config SCSI_IPS To compile this driver as a module, choose M here: the module will be called ips. +config SCSI_IBMVSCSI + tristate "IBM Virtual SCSI support" + depends on PPC_PSERIES || PPC_ISERIES + help + This is the IBM POWER Virtual SCSI Client + + To compile this driver as a module, choose M here: the + module will be called ibmvscsic. + config SCSI_INITIO tristate "Initio 9100U(W) support" - depends on PCI && SCSI && BROKEN + depends on PCI && SCSI help This is support for the Initio 91XXU(W) SCSI host adapter. Please read the SCSI-HOWTO, available from @@ -1027,6 +1044,7 @@ config SCSI_IPR_DUMP config SCSI_ZALON tristate "Zalon SCSI support" depends on GSC && SCSI + select SCSI_SPI_ATTRS help The Zalon is a GSC/HSC bus interface chip that sits between the PA-RISC processor and the NCR 53c720 SCSI controller on C100, @@ -1037,6 +1055,7 @@ config SCSI_ZALON config SCSI_NCR_Q720 tristate "NCR Quad 720 MCA SCSI support" depends on MCA && SCSI + select SCSI_SPI_ATTRS help This is a driver for the MicroChannel Quad 720 card produced by NCR and commonly used in 345x/35xx/4100 class machines. It always @@ -1221,7 +1240,7 @@ config SCSI_QLOGIC_FAS module will be called qlogicfas. config SCSI_QLOGIC_ISP - tristate "Qlogic ISP SCSI support" + tristate "Qlogic ISP SCSI support (old driver)" depends on PCI && SCSI ---help--- This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, @@ -1238,6 +1257,9 @@ config SCSI_QLOGIC_ISP To compile this driver as a module, choose M here: the module will be called qlogicisp. + These days the hardware is also supported by the more modern qla1280 + driver. In doubt use that one instead of qlogicisp. + config SCSI_QLOGIC_FC tristate "Qlogic ISP FC SCSI support" depends on PCI && SCSI @@ -1256,14 +1278,22 @@ config SCSI_QLOGIC_FC_FIRMWARE qlogicfc driver. This is required on some platforms. config SCSI_QLOGIC_1280 - tristate "Qlogic QLA 1280 SCSI support" + tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" depends on PCI && SCSI help - Say Y if you have a QLogic ISP1x80/1x160 SCSI host adapter. + Say Y if you have a QLogic ISP1240/1x80/1x160 SCSI host adapter. To compile this driver as a module, choose M here: the module will be called qla1280. +config SCSI_QLOGIC_1280_1040 + bool "Qlogic QLA 1020/1040 SCSI support" + depends on SCSI_QLOGIC_1280 && SCSI_QLOGIC_ISP!=y + help + Say Y here if you have a QLogic ISP1020/1040 SCSI host adapter and + do not want to use the old driver. This option enables support in + the qla1280 driver for those host adapters. + config SCSI_QLOGICPTI tristate "PTI Qlogic, ISP Driver" depends on SBUS && SCSI @@ -1462,7 +1492,7 @@ config SCSI_DEBUG config SCSI_MESH tristate "MESH (Power Mac internal SCSI) support" - depends on PPC_PMAC && SCSI + depends on PPC32 && PPC_PMAC && SCSI help Many Power Macintoshes and clones have a MESH (Macintosh Enhanced SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the @@ -1493,7 +1523,7 @@ config SCSI_MESH_RESET_DELAY_MS config SCSI_MAC53C94 tristate "53C94 (Power Mac external SCSI) support" - depends on PPC_PMAC && SCSI + depends on PPC32 && PPC_PMAC && SCSI help On Power Macintoshes (and clones) with two SCSI buses, the external SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older @@ -1507,7 +1537,7 @@ source "drivers/scsi/arm/Kconfig" config JAZZ_ESP bool "MIPS JAZZ FAS216 SCSI support" - depends on MIPS_JAZZ && SCSI + depends on MACH_JAZZ && SCSI help This is the driver for the onboard SCSI host adapter of MIPS Magnum 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM @@ -1737,7 +1767,7 @@ config SCSI_SUNESP config ZFCP tristate "FCP host bus adapter driver for IBM eServer zSeries" - depends on ARCH_S390 && SCSI + depends on ARCH_S390 && QDIO && SCSI select SCSI_FC_ATTRS help If you want to access SCSI devices attached to your IBM eServer diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 7aebabba4..07e42255d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -95,7 +95,8 @@ obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_DC390T) += tmscsim.o -obj-$(CONFIG_SCSI_MEGARAID) += megaraid.o +obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o +obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ obj-$(CONFIG_SCSI_ACARD) += atp870u.o obj-$(CONFIG_SCSI_SUNESP) += esp.o obj-$(CONFIG_SCSI_GDTH) += gdth.o @@ -119,6 +120,8 @@ obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o +obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ +obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o @@ -128,6 +131,7 @@ obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o +obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o obj-$(CONFIG_ARM) += arm/ @@ -146,8 +150,6 @@ scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o -initio-objs := ini9100u.o i91uscsi.o -a100u2w-objs := inia100.o i60uscsi.o ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ := -DCONFIG_NCR53C8XX_PREFETCH -DSCSI_NCR_BIG_ENDIAN \ -DCONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index e3bb9dde6..6b3d2b2ad 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -113,32 +113,18 @@ /* * Design - * Issues : * - * The other Linux SCSI drivers were written when Linux was Intel PC-only, - * and specifically for each board rather than each chip. This makes their - * adaptation to platforms like the Mac (Some of which use NCR5380's) - * more difficult than it has to be. - * - * Also, many of the SCSI drivers were written before the command queuing - * routines were implemented, meaning their implementations of queued - * commands were hacked on rather than designed in from the start. - * - * When I designed the Linux SCSI drivers I figured that - * while having two different SCSI boards in a system might be useful - * for debugging things, two of the same type wouldn't be used. - * Well, I was wrong and a number of users have mailed me about running - * multiple high-performance SCSI boards in a server. - * - * Finally, when I get questions from users, I have no idea what - * revision of my driver they are running. - * - * This driver attempts to address these problems : * This is a generic 5380 driver. To use it on a different platform, * one simply writes appropriate system specific macros (ie, data * transfer - some PC's will use the I/O bus, 68K's must use * memory mapped) and drops this file in their 'C' wrapper. * + * (Note from hch: unfortunately it was not enough for the different + * m68k folks and instead of improving this driver they copied it + * and hacked it up for their needs. As a consequence they lost + * most updates to this driver. Maybe someone will fix all these + * drivers to use a common core one day..) + * * As far as command queueing, two queues are maintained for * each 5380 in the system - commands that haven't been issued yet, * and commands that are currently executing. This means that an @@ -148,17 +134,6 @@ * allowing multiple commands to propagate all the way to a SCSI-II device * while a command is already executing. * - * To solve the multiple-boards-in-the-same-system problem, - * there is a separate instance structure for each instance - * of a 5380 in the system. So, multiple NCR5380 drivers will - * be able to coexist with appropriate changes to the high level - * SCSI code. - * - * A NCR5380_PUBLIC_REVISION macro is provided, with the release - * number (updated for each public release) printed by the - * NCR5380_print_options command, which should be called from the - * wrapper detect function, so that I know what release of the driver - * users are using. * * Issues specific to the NCR5380 : * @@ -183,11 +158,10 @@ * Architecture : * * At the heart of the design is a coroutine, NCR5380_main, - * which is started when not running by the interrupt handler, - * timer, and queue command function. It attempts to establish - * I_T_L or I_T_L_Q nexuses by removing the commands from the - * issue queue and calling NCR5380_select() if a nexus - * is not established. + * which is started from a workqueue for each NCR5380 host in the + * system. It attempts to establish I_T_L or I_T_L_Q nexuses by + * removing the commands from the issue queue and calling + * NCR5380_select() if a nexus is not established. * * Once a nexus is established, the NCR5380_information_transfer() * phase goes through the various phases as instructed by the target. @@ -289,33 +263,14 @@ * NCR5380_pwrite(instance, src, count) * NCR5380_pread(instance, dst, count); * - * If nothing specific to this implementation needs doing (ie, with external - * hardware), you must also define - * - * NCR5380_queue_command - * NCR5380_reset - * NCR5380_abort - * NCR5380_proc_info - * - * to be the global entry points into the specific driver, ie - * #define NCR5380_queue_command t128_queue_command. - * - * If this is not done, the routines will be defined as static functions - * with the NCR5380* names and the user must provide a globally - * accessible wrapper function. - * * The generic driver is initialized by calling NCR5380_init(instance), * after setting the appropriate host specific fields and ID. If the * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, - * possible) function may be used. Before the specific driver initialization - * code finishes, NCR5380_print_options should be called. + * possible) function may be used. */ static int do_abort(struct Scsi_Host *host); static void do_reset(struct Scsi_Host *host); -static struct NCR5380_hostdata *first_host = NULL; -static struct NCR5380_hostdata *last_host = NULL; -static struct timer_list usleep_timer; /* * initialize_SCp - init the scsi pointer field @@ -533,9 +488,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) #define USLEEP_WAITLONG USLEEP_SLEEP #endif -static struct Scsi_Host *expires_first = NULL; -static spinlock_t timer_lock; /* Guards expires list */ - /* * Function : int should_disconnect (unsigned char cmd) * @@ -578,90 +530,10 @@ static int should_disconnect(unsigned char cmd) } } -/* - * Assumes instance->time_expires has been set in higher level code. - * We should move to a timer per host - * - * Locks: Takes the timer queue lock - */ - -static int NCR5380_set_timer(struct Scsi_Host *instance) -{ - struct Scsi_Host *tmp, **prev; - unsigned long flags; - - if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) { - return -1; - } - - spin_lock_irqsave(&timer_lock, flags); - for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer) - if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires) - break; - - ((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp; - *prev = instance; - - mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires); - - spin_unlock_irqrestore(&timer_lock, flags); - return 0; -} - -/** - * NCR5380_timer_fn - handle polled timeouts - * @unused: unused - * - * Walk the list of controllers, find which controllers have exceeded - * their expiry timeout and then schedule the processing co-routine to - * do the real work. - * - * Doing something about unwanted reentrancy here might be useful - * - * Locks: disables irqs, takes and frees the timer lock - */ - -static void NCR5380_timer_fn(unsigned long unused) -{ - struct Scsi_Host *instance; - struct NCR5380_hostdata *hostdata; - unsigned long flags; - - spin_lock_irqsave(&timer_lock, flags); - for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) - { - hostdata = (struct NCR5380_hostdata *) expires_first->hostdata; - schedule_work(&hostdata->coroutine); - instance = hostdata->next_timer; - hostdata->next_timer = NULL; - hostdata->time_expires = 0; - expires_first = instance; - } - - del_timer(&usleep_timer); - if (expires_first) { - usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires; - add_timer(&usleep_timer); - } - spin_unlock_irqrestore(&timer_lock, flags); -} - -/** - * NCR5380_all_init - global setup - * - * Set up the global values and timers needed by the NCR5380 driver - */ - -static inline void NCR5380_all_init(void) +static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout) { - static int done = 0; - if (!done) { - dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n")); - done = 1; - init_timer(&usleep_timer); - spin_lock_init(&timer_lock); - usleep_timer.function = NCR5380_timer_fn; - } + hostdata->time_expires = jiffies + timeout; + schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires); } @@ -787,22 +659,6 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance) } } -/** - * NCR5380_coroutine_running - coroutine status - * @instance: controller to check - * - * Return true if the co-routine for this controller is running - * or scheduled to run - * - * FIXME: this test function belongs in the workqueue code! - */ - -static int NCR5380_coroutine_running(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata; - return test_bit(0, &hostdata->coroutine.pending); -} - /** * NCR5380_print_status - dump controller info * @instance: controller to dump @@ -819,8 +675,6 @@ static void NCR5380_print_status(struct Scsi_Host *instance) char *start; int len; - printk("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance)? "" : "n't"); - NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); @@ -900,7 +754,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi); #endif spin_lock_irq(instance->host_lock); - SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't"); if (!hostdata->connected) SPRINTF("scsi%d: no currently connected command\n", instance->host_no); else @@ -912,7 +765,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of SPRINTF("scsi%d: disconnected_queue\n", instance->host_no); for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); - spin_unlock_irq(instance->host_lock); *start = buffer; @@ -964,7 +816,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length) * Locks: interrupts must be enabled when we are called */ -static int __init NCR5380_init(struct Scsi_Host *instance, int flags) +static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags) { NCR5380_local_declare(); int i, pass; @@ -984,7 +836,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #endif NCR5380_setup(instance); - NCR5380_all_init(); hostdata->aborted = 0; hostdata->id_mask = 1 << instance->this_id; @@ -1021,18 +872,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) else hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; - hostdata->next = NULL; - - if (!first_host) - first_host = hostdata; - else - last_host->next = hostdata; - - last_host = hostdata; - hostdata->host = instance; hostdata->time_expires = 0; - hostdata->next_timer = NULL; #ifndef AUTOSENSE if ((instance->cmd_per_lun > 1) || instance->can_queue > 1) @@ -1088,6 +929,19 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) return 0; } +/** + * NCR5380_exit - remove an NCR5380 + * @instance: adapter to remove + */ + +static void __devexit NCR5380_exit(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + + cancel_delayed_work(&hostdata->coroutine); + flush_scheduled_work(); +} + /** * NCR5380_queue_command - queue a command * @cmd: SCSI command @@ -1169,6 +1023,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) return 0; } + /** * NCR5380_main - NCR state machines * @@ -1184,28 +1039,11 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) static void NCR5380_main(void *p) { struct NCR5380_hostdata *hostdata = p; + struct Scsi_Host *instance = hostdata->host; Scsi_Cmnd *tmp, *prev; - struct Scsi_Host *instance; int done; - unsigned long flags = 0; - /* - * We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we can exit - * - * Interrupts are enabled before doing various other internal - * instructions, after we've decided that we need to run through - * the loop again. - * - * this should prevent any race conditions. - */ - - instance = hostdata->host; - - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irqsave(instance->host_lock, flags); - + spin_lock_irq(instance->host_lock); do { /* Lock held here */ done = 1; @@ -1286,8 +1124,7 @@ static void NCR5380_main(void *p) LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; - hostdata->time_expires = jiffies + USLEEP_WAITLONG; - NCR5380_set_timer(instance); + NCR5380_set_timer(hostdata, USLEEP_WAITLONG); } } /* if hostdata->selecting */ if (hostdata->connected @@ -1304,8 +1141,7 @@ static void NCR5380_main(void *p) break; } while (!done); - if(instance->irq != SCSI_IRQ_NONE) - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irq(instance->host_lock); } #ifndef DONT_USE_INTR @@ -1330,12 +1166,13 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; int done; unsigned char basr; + unsigned long flags; dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq)); do { done = 1; - spin_lock_irq(instance->host_lock); + spin_lock_irqsave(instance->host_lock, flags); /* Look for pending interrupts */ NCR5380_setup(instance); basr = NCR5380_read(BUS_AND_STATUS_REG); @@ -1386,7 +1223,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) #endif } } /* if BASR_IRQ */ - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(instance->host_lock, flags); if(!done) schedule_work(&hostdata->coroutine); } while (!done); @@ -1469,12 +1306,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) int err; NCR5380_setup(instance); - if (hostdata->selecting) { - if(instance->irq != SCSI_IRQ_NONE) - spin_unlock_irq(instance->host_lock); - goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the - rest of the code nearly the same */ - } + if (hostdata->selecting) + goto part2; hostdata->restart_select = 0; @@ -1495,16 +1328,12 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(MODE_REG, MR_ARBITRATE); - if(instance->irq != SCSI_IRQ_NONE) - spin_unlock_irq(instance->host_lock); /* We can be relaxed here, interrupts are on, we are in workqueue context, the birds are singing in the trees */ - + spin_unlock_irq(instance->host_lock); err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ); - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irq(instance->host_lock); - + spin_lock_irq(instance->host_lock); if (err < 0) { printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); NCR5380_write(MODE_REG, MR_BASE); @@ -1628,8 +1457,7 @@ part2: if (!value && (hostdata->select_time < HZ/4)) { /* RvC: we still must wait for a device response */ hostdata->select_time++; /* after 25 ticks the device has failed */ - hostdata->time_expires = jiffies + 1; - NCR5380_set_timer(instance); + NCR5380_set_timer(hostdata, 1); return 0; /* RvC: we return here with hostdata->selecting set, to go to sleep */ } @@ -1638,8 +1466,6 @@ part2: waiting period */ if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irq(instance->host_lock); NCR5380_reselect(instance); printk("scsi%d : reselection after won arbitration?\n", instance->host_no); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -1665,8 +1491,6 @@ part2: NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irq(instance->host_lock); cmd->result = DID_BAD_TARGET << 16; collect_stats(hostdata, cmd); cmd->scsi_done(cmd); @@ -1693,11 +1517,13 @@ part2: */ /* Wait for start of REQ/ACK handshake */ - + + spin_unlock_irq(instance->host_lock); err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + spin_lock_irq(instance->host_lock); - if(err) - { printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); + if(err) { + printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); goto failed; } @@ -1705,9 +1531,6 @@ part2: dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id)); tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun); - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irq(instance->host_lock); - len = 1; cmd->tag = 0; @@ -1720,15 +1543,14 @@ part2: hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); - initialize_SCp(cmd); - + if (cmd->SCp.ptr != (char *)cmd->sense_buffer) { + initialize_SCp(cmd); + } return 0; /* Selection failed */ failed: - if(instance->irq != SCSI_IRQ_NONE) - spin_lock_irq(instance->host_lock); return -1; } @@ -1804,8 +1626,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed); if (!(tmp & SR_REQ)) { /* timeout condition */ - hostdata->time_expires = jiffies + USLEEP_SLEEP; - NCR5380_set_timer(instance); + NCR5380_set_timer(hostdata, USLEEP_SLEEP); break; } @@ -2643,9 +2464,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { */ NCR5380_transfer_pio(instance, &phase, &len, &data); if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) { - hostdata->time_expires = jiffies + USLEEP_SLEEP; + NCR5380_set_timer(hostdata, USLEEP_SLEEP); dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires)); - NCR5380_set_timer(instance); return; } break; @@ -2664,9 +2484,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* RvC: go to sleep if polling time expired */ if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) { - hostdata->time_expires = jiffies + USLEEP_SLEEP; + NCR5380_set_timer(hostdata, USLEEP_SLEEP); dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires)); - NCR5380_set_timer(instance); return; } } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 321540cb4..b5103f94d 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -251,7 +251,6 @@ struct NCR5380_hostdata { NCR5380_implementation_fields; /* implementation specific */ struct Scsi_Host *host; /* Host backpointer */ - struct NCR5380_hostdata *next; /* Next in our hot chain */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ unsigned char targets_present; /* targets we have connected to, so we can call a select @@ -270,7 +269,6 @@ struct NCR5380_hostdata { volatile unsigned aborted:1; /* flag, says aborted */ int flags; unsigned long time_expires; /* in jiffies, set prior to sleeping */ - struct Scsi_Host *next_timer; int select_time; /* timer in select for target response */ volatile Scsi_Cmnd *selecting; struct work_struct coroutine; /* our co-routine */ @@ -295,6 +293,7 @@ struct NCR5380_hostdata { static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); #endif static int NCR5380_init(struct Scsi_Host *instance, int flags); +static void NCR5380_exit(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs); diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 9f70a7b0b..9cd6f27d7 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -94,7 +94,7 @@ enum { }; /* The master ring of all esp hosts we are managing in this driver. */ -struct NCR_ESP *espchain = 0; +struct NCR_ESP *espchain; int nesps = 0, esps_in_use = 0, esps_running = 0; irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs); @@ -555,7 +555,7 @@ struct NCR_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev) } else { espchain = esp; } - esp->next = 0; + esp->next = NULL; return esp; } @@ -565,7 +565,7 @@ void esp_deallocate(struct NCR_ESP *esp) struct NCR_ESP *elink; if(espchain == esp) { - espchain = 0; + espchain = NULL; } else { for(elink = espchain; elink && (elink->next != esp); elink = elink->next); if(elink) @@ -708,9 +708,9 @@ void esp_initialize(struct NCR_ESP *esp) } /* Initialize the command queues */ - esp->current_SC = 0; - esp->disconnected_SC = 0; - esp->issue_SC = 0; + esp->current_SC = NULL; + esp->disconnected_SC = NULL; + esp->issue_SC = NULL; /* Clear the state machines. */ esp->targets_present = 0; @@ -1728,7 +1728,7 @@ static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp) ESPLOG(("esp%d: Weird, being reselected but disconnected " "command queue is empty.\n", esp->esp_id)); esp->snip = 0; - esp->current_SC = 0; + esp->current_SC = NULL; sp->SCp.phase = not_issued; append_SC(&esp->issue_SC, sp); } @@ -3393,7 +3393,7 @@ static int esp_work_bus(struct NCR_ESP *esp, struct ESP_regs *eregs) } static espfunc_t isvc_vector[] = { - 0, + NULL, esp_do_phase_determine, esp_do_resetbus, esp_finish_reset, diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 3f457dc1b..c685d546f 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -46,9 +46,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -606,22 +606,24 @@ static int NCR53c406a_release(struct Scsi_Host *shost) } /* called from init/main.c */ -static void __init NCR53c406a_setup(char *str, int *ints) +static int __init NCR53c406a_setup(char *str) { static size_t setup_idx = 0; size_t i; + int ints[4]; DEB(printk("NCR53c406a: Setup called\n"); ); if (setup_idx >= PORT_COUNT - 1) { printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); - return; + return 0; } + get_options(str, 4, ints); if (ints[0] < 1 || ints[0] > 3) { printk("NCR53c406a: Malformed command line\n"); printk("NCR53c406a: Usage: ncr53c406a=[,[,]]\n"); - return; + return 0; } for (i = 0; i < PORT_COUNT && !port_base; i++) if (ports[i] == ints[1]) { @@ -631,7 +633,7 @@ static void __init NCR53c406a_setup(char *str, int *ints) } if (!port_base) { printk("NCR53c406a: Invalid PORTBASE 0x%x specified\n", ints[1]); - return; + return 0; } if (ints[0] > 1) { @@ -654,6 +656,7 @@ static void __init NCR53c406a_setup(char *str, int *ints) fast_pio = ints[3]; DEB(printk("NCR53c406a: port_base=0x%x, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);) + return 1; } __setup("ncr53c406a=", NCR53c406a_setup); diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index 802f907a5..c2a31517b 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -99,6 +99,9 @@ #include #include #include +#include +#include +#include #include "53c700.h" #include "NCR_D700.h" @@ -198,34 +201,20 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, NCR_700_set_io_mapped(hostdata); /* and register the siop */ - host = NCR_700_detect(&NCR_D700_driver_template, hostdata); + host = NCR_700_detect(&NCR_D700_driver_template, hostdata, + p->dev, irq, + /* FIXME: read this from SUS */ + id_array[slot * 2 + siop]); if (!host) { ret = -ENOMEM; goto detect_failed; } - host->irq = irq; - /* FIXME: Read this from SUS */ - host->this_id = id_array[slot * 2 + siop]; - printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n", - siop, host->this_id); - if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) { - printk(KERN_ERR "NCR D700: SIOP%d: irq problem, " - "detatching\n", siop); - ret = -ENODEV; - goto irq_failed; - } - - scsi_add_host(host, p->dev); /* XXX handle failure */ scsi_scan_host(host); p->hosts[siop] = host; - hostdata->dev = p->dev; return 0; - irq_failed: - scsi_host_put(host); - NCR_700_release(host); detect_failed: release_region(host->base, 64); region_failed: diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c index d47a86ef5..365d70f42 100644 --- a/drivers/scsi/NCR_Q720.c +++ b/drivers/scsi/NCR_Q720.c @@ -39,7 +39,7 @@ MODULE_LICENSE("GPL"); /* We needs this helper because we have up to four hosts per struct device */ struct NCR_Q720_private { struct device *dev; - __u32 mem_base; + void __iomem * mem_base; __u32 phys_mem_base; __u32 mem_size; __u8 irq; @@ -75,7 +75,7 @@ NCR_Q720_intr(int irq, void *data, struct pt_regs * regs) static int __init NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop, - int irq, int slot, __u32 paddr, __u32 vaddr) + int irq, int slot, __u32 paddr, void __iomem *vaddr) { struct ncr_device device; __u8 scsi_id; @@ -146,7 +146,7 @@ NCR_Q720_probe(struct device *dev) __u8 pos2, pos4, asr2, asr9, asr10; __u16 io_base; __u32 base_addr, mem_size; - __u32 mem_base; + void __iomem *mem_base; p = kmalloc(sizeof(*p), GFP_KERNEL); if (!p) @@ -216,7 +216,21 @@ NCR_Q720_probe(struct device *dev) goto out_free; } - mem_base = (__u32)ioremap(base_addr, mem_size); + if (dma_declare_coherent_memory(dev, base_addr, base_addr, + mem_size, DMA_MEMORY_MAP) + != DMA_MEMORY_MAP) { + printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n"); + goto out_release_region; + } + + /* The first 1k of the memory buffer is a memory map of the registers + */ + mem_base = (__u32)dma_mark_declared_memory_occupied(dev, base_addr, + 1024); + if (IS_ERR(mem_base)) { + printk("NCR_Q720 failed to reserve memory mapped region\n"); + goto out_release; + } /* now also enable accesses in asr 2 */ asr2 = inb(io_base + 0x0a); @@ -257,7 +271,7 @@ NCR_Q720_probe(struct device *dev) } /* disable all the siop interrupts */ for(i = 0; i < siops; i++) { - __u32 reg_scsr1 = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + void __iomem *reg_scsr1 = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + i*NCR_Q720_SIOP_SHIFT + NCR_Q720_SCSR_OFFSET + 1; __u8 scsr1 = readb(reg_scsr1); scsr1 |= 0x01; @@ -266,7 +280,7 @@ NCR_Q720_probe(struct device *dev) /* plumb in all 720 chips */ for (i = 0; i < siops; i++) { - __u32 siop_v_base = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + void __iomem *siop_v_base = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + i*NCR_Q720_SIOP_SHIFT; __u32 siop_p_base = base_addr + NCR_Q720_CHIP_REGISTER_OFFSET + i*NCR_Q720_SIOP_SHIFT; @@ -296,7 +310,8 @@ NCR_Q720_probe(struct device *dev) return 0; out_release: - iounmap((void *)mem_base); + dma_release_declared_memory(dev); + out_release_region: release_mem_region(base_addr, mem_size); out_free: kfree(p); @@ -321,7 +336,7 @@ NCR_Q720_remove(struct device *dev) if(p->hosts[i]) NCR_Q720_remove_one(p->hosts[i]); - iounmap((void *)p->mem_base); + dma_release_declared_memory(dev); release_mem_region(p->phys_mem_base, p->mem_size); free_irq(p->irq, p); kfree(p); @@ -343,13 +358,19 @@ struct mca_driver NCR_Q720_driver = { static int __init NCR_Q720_init(void) { - return mca_register_driver(&NCR_Q720_driver); + int ret = ncr53c8xx_init(); + if (!ret) + ret = mca_register_driver(&NCR_Q720_driver); + if (ret) + ncr53c8xx_exit(); + return ret; } static void __exit NCR_Q720_exit(void) { mca_unregister_driver(&NCR_Q720_driver); + ncr53c8xx_exit(); } module_init(NCR_Q720_init); diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README index 6abbe026b..52015523c 100644 --- a/drivers/scsi/aacraid/README +++ b/drivers/scsi/aacraid/README @@ -10,14 +10,23 @@ the original). Supported Cards/Chipsets ------------------------- - AAR-2410SA SATA + Adaptec 2020S + Adaptec 2025S Adaptec 2120S Adaptec 2200S Adaptec 2230S + Adaptec 2240S + Adaptec 2410SA + Adaptec 2610SA + Adaptec 2810SA + Adaptec 21610SA Adaptec 3230S Adaptec 3240S + Adaptec 4000SAS + Adaptec 4005SAS + Adaptec 4800SAS + Adaptec 4805SAS Adaptec 5400S - ASR-2020S PCI-X Dell PERC 2 Quad Channel Dell PERC 2/Si Dell PERC 3/Si @@ -49,7 +58,6 @@ Adaptec Unix OEM Product Group Mailing List ------------------------- linux-scsi@vger.kernel.org (Interested parties troll here) -http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) Also note this is very different to Brian's original driver so don't expect him to support it. Adaptec does support this driver. Contact either tech support or Mark Salyzyn. diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7b02a48a2..ef4702f23 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -131,47 +131,10 @@ struct inquiry_data { u8 inqd_prl[4]; /* Product Revision Level */ }; -struct sense_data { - u8 error_code; /* 70h (current errors), 71h(deferred errors) */ - u8 valid:1; /* A valid bit of one indicates that the information */ - /* field contains valid information as defined in the - * SCSI-2 Standard. - */ - u8 segment_number; /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */ - u8 sense_key:4; /* Sense Key */ - u8 reserved:1; - u8 ILI:1; /* Incorrect Length Indicator */ - u8 EOM:1; /* End Of Medium - reserved for random access devices */ - u8 filemark:1; /* Filemark - reserved for random access devices */ - - u8 information[4]; /* for direct-access devices, contains the unsigned - * logical block address or residue associated with - * the sense key - */ - u8 add_sense_len; /* number of additional sense bytes to follow this field */ - u8 cmnd_info[4]; /* not used */ - u8 ASC; /* Additional Sense Code */ - u8 ASCQ; /* Additional Sense Code Qualifier */ - u8 FRUC; /* Field Replaceable Unit Code - not used */ - u8 bit_ptr:3; /* indicates which byte of the CDB or parameter data - * was in error - */ - u8 BPV:1; /* bit pointer valid (BPV): 1- indicates that - * the bit_ptr field has valid value - */ - u8 reserved2:2; - u8 CD:1; /* command data bit: 1- illegal parameter in CDB. - * 0- illegal parameter in data. - */ - u8 SKSV:1; - u8 field_ptr[2]; /* byte of the CDB or parameter data in error */ -}; - /* * M O D U L E G L O B A L S */ -static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS]; static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); @@ -179,6 +142,94 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); static char *aac_get_status_string(u32 status); #endif +/* + * Non dasd selection is handled entirely in aachba now + */ + +MODULE_PARM(nondasd, "i"); +MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); +MODULE_PARM(dacmode, "i"); +MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on"); +MODULE_PARM(commit, "i"); +MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on"); + +static int nondasd = -1; +static int dacmode = -1; + +static int commit = -1; + +/** + * aac_get_config_status - check the adapter configuration + * @common: adapter to query + * + * Query config status, and commit the configuration if needed. + */ +int aac_get_config_status(struct aac_dev *dev) +{ + int status = 0; + struct fib * fibptr; + + if (!(fibptr = fib_alloc(dev))) + return -ENOMEM; + + fib_init(fibptr); + { + struct aac_get_config_status *dinfo; + dinfo = (struct aac_get_config_status *) fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_GET_CONFIG_STATUS); + dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data)); + } + + status = fib_send(ContainerCommand, + fibptr, + sizeof (struct aac_get_config_status), + FsaNormal, + 1, 1, + NULL, NULL); + if (status < 0 ) { + printk(KERN_WARNING "aac_get_config_status: SendFIB failed.\n"); + } else { + struct aac_get_config_status_resp *reply + = (struct aac_get_config_status_resp *) fib_data(fibptr); + dprintk((KERN_WARNING + "aac_get_config_status: response=%d status=%d action=%d\n", + reply->response, reply->status, reply->data.action)); + if ((reply->response != ST_OK) + || (reply->status != CT_OK) + || (reply->data.action > CFACT_PAUSE)) { + printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n"); + status = -EINVAL; + } + } + fib_complete(fibptr); + /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ + if (status >= 0) { + if (commit == 1) { + struct aac_commit_config * dinfo; + fib_init(fibptr); + dinfo = (struct aac_commit_config *) fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG); + + status = fib_send(ContainerCommand, + fibptr, + sizeof (struct aac_commit_config), + FsaNormal, + 1, 1, + NULL, NULL); + fib_complete(fibptr); + } else if (commit == 0) { + printk(KERN_WARNING + "aac_get_config_status: Foreign device configurations are being ignored\n"); + } + } + fib_free(fibptr); + return status; +} + /** * aac_get_containers - list containers * @common: adapter to probe @@ -187,21 +238,57 @@ static char *aac_get_status_string(u32 status); */ int aac_get_containers(struct aac_dev *dev) { - struct fsa_scsi_hba *fsa_dev_ptr; + struct fsa_dev_info *fsa_dev_ptr; u32 index; int status = 0; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; struct fib * fibptr; unsigned instance; + struct aac_get_container_count *dinfo; + struct aac_get_container_count_resp *dresp; + int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - fsa_dev_ptr = &(dev->fsa_dev); instance = dev->scsi_host_ptr->unique_id; if (!(fibptr = fib_alloc(dev))) return -ENOMEM; - for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) { + fib_init(fibptr); + dinfo = (struct aac_get_container_count *) fib_data(fibptr); + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT); + + status = fib_send(ContainerCommand, + fibptr, + sizeof (struct aac_get_container_count), + FsaNormal, + 1, 1, + NULL, NULL); + if (status >= 0) { + dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); + maximum_num_containers = dresp->ContainerSwitchEntries; + fib_complete(fibptr); + } + + if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) + maximum_num_containers = MAXIMUM_NUM_CONTAINERS; + + fsa_dev_ptr = (struct fsa_dev_info *) kmalloc( + sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); + if (!fsa_dev_ptr) { + fib_free(fibptr); + return -ENOMEM; + } + memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); + + dev->fsa_dev = fsa_dev_ptr; + dev->maximum_num_containers = maximum_num_containers; + + for (index = 0; index < dev->maximum_num_containers; index++) { + struct aac_query_mount *dinfo; + struct aac_mount *dresp; + + fsa_dev_ptr[index].devname[0] = '\0'; + fib_init(fibptr); dinfo = (struct aac_query_mount *) fib_data(fibptr); @@ -221,14 +308,20 @@ int aac_get_containers(struct aac_dev *dev) } dresp = (struct aac_mount *)fib_data(fibptr); + dprintk ((KERN_DEBUG + "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%u\n", + (int)index, (int)le32_to_cpu(dresp->status), + (int)le32_to_cpu(dresp->mnt[0].vol), + (int)le32_to_cpu(dresp->mnt[0].state), + (unsigned)le32_to_cpu(dresp->mnt[0].capacity))); if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr->valid[index] = 1; - fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); + fsa_dev_ptr[index].valid = 1; + fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr[index].size = le32_to_cpu(dresp->mnt[0].capacity); if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[index] = 1; + fsa_dev_ptr[index].ro = 1; } fib_complete(fibptr); /* @@ -242,25 +335,111 @@ int aac_get_containers(struct aac_dev *dev) return status; } +static void aac_io_done(struct scsi_cmnd * scsicmd) +{ + unsigned long cpu_flags; + struct Scsi_Host *host = scsicmd->device->host; + spin_lock_irqsave(host->host_lock, cpu_flags); + scsicmd->scsi_done(scsicmd); + spin_unlock_irqrestore(host->host_lock, cpu_flags); +} + +static void get_container_name_callback(void *context, struct fib * fibptr) +{ + struct aac_get_name_resp * get_name_reply; + struct scsi_cmnd * scsicmd; + + scsicmd = (struct scsi_cmnd *) context; + + dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); + if (fibptr == NULL) + BUG(); + + get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr); + /* Failure is irrelevant, using default value instead */ + if ((le32_to_cpu(get_name_reply->status) == CT_OK) + && (get_name_reply->data[0] != '\0')) { + int count; + char * dp; + char * sp = get_name_reply->data; + sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; + while (*sp == ' ') + ++sp; + count = sizeof(((struct inquiry_data *)NULL)->inqd_pid); + dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid; + if (*sp) do { + *dp++ = (*sp) ? *sp++ : ' '; + } while (--count > 0); + } + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + + fib_complete(fibptr); + fib_free(fibptr); + aac_io_done(scsicmd); +} + +/** + * aac_get_container_name - get container name, none blocking. + */ +static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) +{ + int status; + struct aac_get_name *dinfo; + struct fib * cmd_fibcontext; + struct aac_dev * dev; + + dev = (struct aac_dev *)scsicmd->device->host->hostdata; + + if (!(cmd_fibcontext = fib_alloc(dev))) + return -ENOMEM; + + fib_init(cmd_fibcontext); + dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext); + + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_READ_NAME); + dinfo->cid = cpu_to_le32(cid); + dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); + + status = fib_send(ContainerCommand, + cmd_fibcontext, + sizeof (struct aac_get_name), + FsaNormal, + 0, 1, + (fib_callback) get_container_name_callback, + (void *) scsicmd); + + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) + return 0; + + printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status); + fib_complete(cmd_fibcontext); + fib_free(cmd_fibcontext); + return -1; +} + /** * probe_container - query a logical volume * @dev: device to query * @cid: container identifier * * Queries the controller about the given volume. The volume information - * is updated in the struct fsa_scsi_hba structure rather than returned. + * is updated in the struct fsa_dev_info structure rather than returned. */ static int probe_container(struct aac_dev *dev, int cid) { - struct fsa_scsi_hba *fsa_dev_ptr; + struct fsa_dev_info *fsa_dev_ptr; int status; struct aac_query_mount *dinfo; struct aac_mount *dresp; struct fib * fibptr; unsigned instance; - fsa_dev_ptr = &(dev->fsa_dev); + fsa_dev_ptr = dev->fsa_dev; instance = dev->scsi_host_ptr->unique_id; if (!(fibptr = fib_alloc(dev))) @@ -290,11 +469,11 @@ static int probe_container(struct aac_dev *dev, int cid) if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr->valid[cid] = 1; - fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); + fsa_dev_ptr[cid].valid = 1; + fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr[cid].size = le32_to_cpu(dresp->mnt[0].capacity); if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr->ro[cid] = 1; + fsa_dev_ptr[cid].ro = 1; } error: @@ -353,14 +532,13 @@ static char *container_types[] = { * Arguments: [1] pointer to void [1] int * * Purpose: Sets SCSI inquiry data strings for vendor, product - * and revision level. Allows strings to be set in platform dependent - * files instead of in OS dependent driver source. + * and revision level. Allows strings to be set in platform dependant + * files instead of in OS dependant driver source. */ static void setinqstr(int devtype, void *data, int tindex) { struct scsi_inq *str; - char *findit; struct aac_driver_ident *mp; mp = aac_get_driver_ident(devtype); @@ -370,13 +548,14 @@ static void setinqstr(int devtype, void *data, int tindex) inqstrcpy (mp->vname, str->vid); inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */ - findit = str->pid; - - for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */ - findit++; - if (tindex < (sizeof(container_types)/sizeof(char *))){ - inqstrcpy (container_types[tindex], findit); + char *findit = str->pid; + + for ( ; *findit != ' '; findit++); /* walk till we find a space */ + /* RAID is superfluous in the context of a RAID device */ + if (memcmp(findit-4, "RAID", 4) == 0) + *(findit -= 4) = ' '; + inqstrcpy (container_types[tindex], findit + 1); } inqstrcpy ("V1.0", str->prl); } @@ -421,20 +600,6 @@ void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, } } -static void aac_io_done(struct scsi_cmnd * scsicmd) -{ - unsigned long cpu_flags; - struct Scsi_Host *host = scsicmd->device->host; - spin_lock_irqsave(host->host_lock, cpu_flags); - scsicmd->scsi_done(scsicmd); - spin_unlock_irqrestore(host->host_lock, cpu_flags); -} - -static void __aac_io_done(struct scsi_cmnd * scsicmd) -{ - scsicmd->scsi_done(scsicmd); -} - int aac_get_adapter_info(struct aac_dev* dev) { struct fib* fibptr; @@ -480,10 +645,31 @@ int aac_get_adapter_info(struct aac_dev* dev) dev->adapter_info.serial[1]); dev->nondasd_support = 0; + dev->raid_scsi_mode = 0; if(dev->adapter_info.options & AAC_OPT_NONDASD){ -// dev->nondasd_support = 1; -// dmb - temporarily disable nondasd + dev->nondasd_support = 1; } + + /* + * If the firmware supports ROMB RAID/SCSI mode and we are currently + * in RAID/SCSI mode, set the flag. For now if in this mode we will + * force nondasd support on. If we decide to allow the non-dasd flag + * additional changes changes will have to be made to support + * RAID/SCSI. the function aac_scsi_cmd in this module will have to be + * changed to support the new dev->raid_scsi_mode flag instead of + * leaching off of the dev->nondasd_support flag. Also in linit.c the + * function aac_detect will have to be modified where it sets up the + * max number of channels based on the aac->nondasd_support flag only. + */ + if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) && + (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) { + dev->nondasd_support = 1; + dev->raid_scsi_mode = 1; + } + if (dev->raid_scsi_mode != 0) + printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n", + dev->name, dev->id); + if(nondasd != -1) { dev->nondasd_support = (nondasd!=0); } @@ -491,18 +677,30 @@ int aac_get_adapter_info(struct aac_dev* dev) printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id); } - dev->pae_support = 0; + dev->dac_support = 0; if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ printk(KERN_INFO "%s%d: 64bit support enabled.\n", dev->name, dev->id); - dev->pae_support = 1; + dev->dac_support = 1; } - if(paemode != -1){ - dev->pae_support = (paemode!=0); + if(dacmode != -1) { + dev->dac_support = (dacmode!=0); } - if(dev->pae_support != 0) { - printk(KERN_INFO"%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); - pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL); + if(dev->dac_support != 0) { + if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL) && + !pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL)) { + printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n", + dev->name, dev->id); + } else if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFULL) && + !pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFULL)) { + printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n", + dev->name, dev->id); + dev->dac_support = 0; + } else { + printk(KERN_WARNING"%s%d: No suitable DMA available.\n", + dev->name, dev->id); + rcode = -ENOMEM; + } } fib_complete(fibptr); @@ -537,7 +735,7 @@ static void read_callback(void *context, struct fib * fibptr) scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr, + pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen, scsicmd->sc_data_direction); readreply = (struct aac_read_reply *)fib_data(fibptr); @@ -546,12 +744,15 @@ static void read_callback(void *context, struct fib * fibptr) else { printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data)); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); } fib_complete(fibptr); fib_free(fibptr); @@ -582,7 +783,7 @@ static void write_callback(void *context, struct fib * fibptr) scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr, + pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen, scsicmd->sc_data_direction); @@ -592,12 +793,13 @@ static void write_callback(void *context, struct fib * fibptr) else { printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data)); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + sizeof(struct sense_data)); } fib_complete(fibptr); @@ -644,7 +846,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid) fib_init(cmd_fibcontext); - if(dev->pae_support == 1){ + if(dev->dac_support == 1) { struct aac_read64 *readcmd; readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); readcmd->command = cpu_to_le32(VM_CtHostRead64); @@ -714,7 +916,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid) aac_io_done(scsicmd); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); - return -1; + return 0; } static int aac_write(struct scsi_cmnd * scsicmd, int cid) @@ -748,11 +950,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) if (!(cmd_fibcontext = fib_alloc(dev))) { scsicmd->result = DID_ERROR << 16; aac_io_done(scsicmd); - return -1; + return 0; } fib_init(cmd_fibcontext); - if(dev->pae_support == 1){ + if(dev->dac_support == 1) { struct aac_write64 *writecmd; writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); writecmd->command = cpu_to_le32(VM_CtHostWrite64); @@ -824,7 +1026,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); - return -1; + return 0; } @@ -839,11 +1041,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) int aac_scsi_cmd(struct scsi_cmnd * scsicmd) { u32 cid = 0; - int ret; struct Scsi_Host *host = scsicmd->device->host; struct aac_dev *dev = (struct aac_dev *)host->hostdata; - struct fsa_scsi_hba *fsa_dev_ptr = &dev->fsa_dev; + struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; int cardtype = dev->cardtype; + int ret; /* * If the bus, id or lun is out of range, return fail @@ -852,9 +1054,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) */ if (scsicmd->device->id != host->this_id) { if ((scsicmd->device->channel == 0) ){ - if( (scsicmd->device->id >= MAXIMUM_NUM_CONTAINERS) || (scsicmd->device->lun != 0)){ + if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); @@ -863,7 +1065,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * If the target container doesn't exist, it may have * been newly created */ - if (fsa_dev_ptr->valid[cid] == 0) { + if ((fsa_dev_ptr[cid].valid & 1) == 0) { switch (scsicmd->cmnd[0]) { case INQUIRY: case READ_CAPACITY: @@ -871,9 +1073,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) spin_unlock_irq(host->host_lock); probe_container(dev, cid); spin_lock_irq(host->host_lock); - if (fsa_dev_ptr->valid[cid] == 0) { + if (fsa_dev_ptr[cid].valid == 0) { scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } default: @@ -884,9 +1086,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * If the target container still doesn't exist, * return failure */ - if (fsa_dev_ptr->valid[cid] == 0) { + if (fsa_dev_ptr[cid].valid == 0) { scsicmd->result = DID_BAD_TARGET << 16; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } } else { /* check for physical non-dasd devices */ @@ -894,7 +1096,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) return aac_send_srb_fib(scsicmd); } else { scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } } @@ -907,12 +1109,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) { dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - __aac_io_done(scsicmd); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof(struct sense_data)); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + scsicmd->scsi_done(scsicmd); return 0; } @@ -937,22 +1142,27 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * Set the Vendor, Product, and Revision Level * see: .c i.e. aac.c */ - setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->device->id == host->this_id) + if (scsicmd->device->id == host->this_id) { + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *))); inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ - else - inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); - return 0; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + scsicmd->scsi_done(scsicmd); + return 0; + } + setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type); + inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ + return aac_get_container_name(scsicmd, cid); } case READ_CAPACITY: { - int capacity; + u32 capacity; char *cp; dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - capacity = fsa_dev_ptr->size[cid] - 1; + if (fsa_dev_ptr[cid].size <= 0x100000000LL) + capacity = fsa_dev_ptr[cid].size - 1; + else + capacity = (u32)-1; cp = scsicmd->request_buffer; cp[0] = (capacity >> 24) & 0xff; cp[1] = (capacity >> 16) & 0xff; @@ -964,7 +1174,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) cp[7] = 0; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } @@ -981,7 +1191,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[3] = 0; /* Block descriptor length */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } @@ -1001,27 +1211,27 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[7] = 0; /* Block descriptor length (LSB) */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } case REQUEST_SENSE: dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); - memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); - memset(&sense_data[cid], 0, sizeof (struct sense_data)); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data)); + memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; case ALLOW_MEDIUM_REMOVAL: dprintk((KERN_DEBUG "LOCK command.\n")); if (scsicmd->cmnd[4]) - fsa_dev_ptr->locked[cid] = 1; + fsa_dev_ptr[cid].locked = 1; else - fsa_dev_ptr->locked[cid] = 0; + fsa_dev_ptr[cid].locked = 0; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; /* * These commands are all No-Ops @@ -1034,7 +1244,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case SEEK_10: case START_STOP: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } @@ -1050,7 +1260,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) spin_unlock_irq(host->host_lock); if (scsicmd->request->rq_disk) - memcpy(fsa_dev_ptr->devname[cid], + memcpy(fsa_dev_ptr[cid].devname, scsicmd->request->rq_disk->disk_name, 8); @@ -1070,12 +1280,14 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) */ printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &sense_data[cid], + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND, - ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); - memcpy(scsicmd->sense_buffer, &sense_data[cid], - sizeof(struct sense_data)); - __aac_io_done(scsicmd); + ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + scsicmd->scsi_done(scsicmd); return 0; } } @@ -1083,16 +1295,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) static int query_disk(struct aac_dev *dev, void __user *arg) { struct aac_query_disk qd; - struct fsa_scsi_hba *fsa_dev_ptr; + struct fsa_dev_info *fsa_dev_ptr; - fsa_dev_ptr = &(dev->fsa_dev); + fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) return -EFAULT; if (qd.cnum == -1) qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun); else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) { - if (qd.cnum < 0 || qd.cnum >= MAXIMUM_NUM_CONTAINERS) + if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers) return -EINVAL; qd.instance = dev->scsi_host_ptr->host_no; qd.bus = 0; @@ -1101,16 +1313,17 @@ static int query_disk(struct aac_dev *dev, void __user *arg) } else return -EINVAL; - qd.valid = fsa_dev_ptr->valid[qd.cnum]; - qd.locked = fsa_dev_ptr->locked[qd.cnum]; - qd.deleted = fsa_dev_ptr->deleted[qd.cnum]; + qd.valid = fsa_dev_ptr[qd.cnum].valid; + qd.locked = fsa_dev_ptr[qd.cnum].locked; + qd.deleted = fsa_dev_ptr[qd.cnum].deleted; - if (fsa_dev_ptr->devname[qd.cnum][0] == '\0') + if (fsa_dev_ptr[qd.cnum].devname[0] == '\0') qd.unmapped = 1; else qd.unmapped = 0; - strlcpy(qd.name, fsa_dev_ptr->devname[qd.cnum], sizeof(qd.name)); + strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname, + min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1)); if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) return -EFAULT; @@ -1120,49 +1333,49 @@ static int query_disk(struct aac_dev *dev, void __user *arg) static int force_delete_disk(struct aac_dev *dev, void __user *arg) { struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; + struct fsa_dev_info *fsa_dev_ptr; - fsa_dev_ptr = &(dev->fsa_dev); + fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) return -EFAULT; - if (dd.cnum >= MAXIMUM_NUM_CONTAINERS) + if (dd.cnum >= dev->maximum_num_containers) return -EINVAL; /* * Mark this container as being deleted. */ - fsa_dev_ptr->deleted[dd.cnum] = 1; + fsa_dev_ptr[dd.cnum].deleted = 1; /* * Mark the container as no longer valid */ - fsa_dev_ptr->valid[dd.cnum] = 0; + fsa_dev_ptr[dd.cnum].valid = 0; return 0; } static int delete_disk(struct aac_dev *dev, void __user *arg) { struct aac_delete_disk dd; - struct fsa_scsi_hba *fsa_dev_ptr; + struct fsa_dev_info *fsa_dev_ptr; - fsa_dev_ptr = &(dev->fsa_dev); + fsa_dev_ptr = dev->fsa_dev; if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) return -EFAULT; - if (dd.cnum >= MAXIMUM_NUM_CONTAINERS) + if (dd.cnum >= dev->maximum_num_containers) return -EINVAL; /* * If the container is locked, it can not be deleted by the API. */ - if (fsa_dev_ptr->locked[dd.cnum]) + if (fsa_dev_ptr[dd.cnum].locked) return -EBUSY; else { /* * Mark the container as no longer being valid. */ - fsa_dev_ptr->valid[dd.cnum] = 0; - fsa_dev_ptr->devname[dd.cnum][0] = '\0'; + fsa_dev_ptr[dd.cnum].valid = 0; + fsa_dev_ptr[dd.cnum].devname[0] = '\0'; return 0; } } @@ -1220,7 +1433,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, + pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen, scsicmd->sc_data_direction); /* @@ -1255,8 +1468,17 @@ static void aac_srb_callback(void *context, struct fib * fibptr) if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if ((dev->raid_scsi_mode) && + (scsicmd->device->channel == 2)) { + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8; } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + scsicmd->result = DID_NO_CONNECT << 16 | + COMMAND_COMPLETE << 8; } } else { scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; @@ -1288,8 +1510,17 @@ static void aac_srb_callback(void *context, struct fib * fibptr) if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER || (b==TYPE_DISK && (b1&0x80)) ){ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + /* + * We will allow disk devices if in RAID/SCSI mode and + * the channel is 2 + */ + } else if ((dev->raid_scsi_mode) && + (scsicmd->device->channel == 2)) { + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8; } else { - scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + scsicmd->result = DID_NO_CONNECT << 16 | + COMMAND_COMPLETE << 8; } break; } @@ -1348,7 +1579,12 @@ static void aac_srb_callback(void *context, struct fib * fibptr) case SRB_STATUS_DOMAIN_VALIDATION_FAIL: default: #ifdef AAC_DETAILED_STATUS_INFO - printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) ); + printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n", + le32_to_cpu(srbreply->srb_status & 0x3F), + aac_get_status_string( + le32_to_cpu(srbreply->srb_status) & 0x3F), + scsicmd->cmnd[0], + le32_to_cpu(srbreply->scsi_status)); #endif scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; @@ -1358,7 +1594,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd->result |= SAM_STAT_CHECK_CONDITION; len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len)); +#ifdef AAC_DETAILED_STATUS_INFO + dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", + le32_to_cpu(srbreply->status), len)); +#endif memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); } @@ -1393,7 +1632,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) if( scsicmd->device->id > 15 || scsicmd->device->lun > 7) { scsicmd->result = DID_NO_CONNECT << 16; - __aac_io_done(scsicmd); + scsicmd->scsi_done(scsicmd); return 0; } @@ -1437,7 +1676,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); - if( dev->pae_support ==1 ) { + if( dev->dac_support == 1 ) { aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); @@ -1532,7 +1771,7 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.ptr = (char *)(ulong)addr; + scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count; @@ -1593,7 +1832,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p psg->sg[0].addr[1] = (u32)(le_addr>>32); psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.ptr = (char *)(ulong)addr; + scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 8b077f224..013cc8988 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -7,7 +7,6 @@ *----------------------------------------------------------------------------*/ #define MAXIMUM_NUM_CONTAINERS 32 -#define MAXIMUM_NUM_ADAPTERS 8 #define AAC_NUM_FIB (256 + 64) #define AAC_NUM_IO_FIB 100 @@ -28,10 +27,7 @@ #define aac_phys_to_logical(x) (x+1) #define aac_logical_to_phys(x) (x?x-1:0) -#define AAC_DETAILED_STATUS_INFO - -extern int nondasd; -extern int paemode; +/* #define AAC_DETAILED_STATUS_INFO */ struct diskparm { @@ -60,6 +56,7 @@ struct diskparm #define CT_VOLUME_OF_MIRRORS 12 /* volume of mirror */ #define CT_PSEUDO_RAID 13 /* really raid4 */ #define CT_LAST_VOLUME_TYPE 14 +#define CT_OK 218 /* * Types of objects addressable in some fashion by the client. @@ -404,15 +401,15 @@ struct aac_init }; enum aac_log_level { - LOG_INIT = 10, - LOG_INFORMATIONAL = 20, - LOG_WARNING = 30, - LOG_LOW_ERROR = 40, - LOG_MEDIUM_ERROR = 50, - LOG_HIGH_ERROR = 60, - LOG_PANIC = 70, - LOG_DEBUG = 80, - LOG_WINDBG_PRINT = 90 + LOG_AAC_INIT = 10, + LOG_AAC_INFORMATIONAL = 20, + LOG_AAC_WARNING = 30, + LOG_AAC_LOW_ERROR = 40, + LOG_AAC_MEDIUM_ERROR = 50, + LOG_AAC_HIGH_ERROR = 60, + LOG_AAC_PANIC = 70, + LOG_AAC_DEBUG = 80, + LOG_AAC_WINDBG_PRINT = 90 }; #define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT 0x030b @@ -424,8 +421,6 @@ struct adapter_ops { void (*adapter_interrupt)(struct aac_dev *dev); void (*adapter_notify)(struct aac_dev *dev, u32 event); - void (*adapter_enable_int)(struct aac_dev *dev, u32 event); - void (*adapter_disable_int)(struct aac_dev *dev, u32 event); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status); int (*adapter_check_health)(struct aac_dev *dev); }; @@ -665,14 +660,53 @@ struct aac_fib_context { struct list_head fib_list; // this holds fibs and their attachd hw_fibs }; -struct fsa_scsi_hba { - u32 size[MAXIMUM_NUM_CONTAINERS]; - u32 type[MAXIMUM_NUM_CONTAINERS]; - u8 valid[MAXIMUM_NUM_CONTAINERS]; - u8 ro[MAXIMUM_NUM_CONTAINERS]; - u8 locked[MAXIMUM_NUM_CONTAINERS]; - u8 deleted[MAXIMUM_NUM_CONTAINERS]; - char devname[MAXIMUM_NUM_CONTAINERS][8]; +struct sense_data { + u8 error_code; /* 70h (current errors), 71h(deferred errors) */ + u8 valid:1; /* A valid bit of one indicates that the information */ + /* field contains valid information as defined in the + * SCSI-2 Standard. + */ + u8 segment_number; /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */ + u8 sense_key:4; /* Sense Key */ + u8 reserved:1; + u8 ILI:1; /* Incorrect Length Indicator */ + u8 EOM:1; /* End Of Medium - reserved for random access devices */ + u8 filemark:1; /* Filemark - reserved for random access devices */ + + u8 information[4]; /* for direct-access devices, contains the unsigned + * logical block address or residue associated with + * the sense key + */ + u8 add_sense_len; /* number of additional sense bytes to follow this field */ + u8 cmnd_info[4]; /* not used */ + u8 ASC; /* Additional Sense Code */ + u8 ASCQ; /* Additional Sense Code Qualifier */ + u8 FRUC; /* Field Replaceable Unit Code - not used */ + u8 bit_ptr:3; /* indicates which byte of the CDB or parameter data + * was in error + */ + u8 BPV:1; /* bit pointer valid (BPV): 1- indicates that + * the bit_ptr field has valid value + */ + u8 reserved2:2; + u8 CD:1; /* command data bit: 1- illegal parameter in CDB. + * 0- illegal parameter in data. + */ + u8 SKSV:1; + u8 field_ptr[2]; /* byte of the CDB or parameter data in error */ +}; + +struct fsa_dev_info { + u64 last; + u64 size; + u32 type; + u16 queue_depth; + u8 valid; + u8 ro; + u8 locked; + u8 deleted; + char devname[8]; + struct sense_data sense_data; }; struct fib { @@ -771,10 +805,12 @@ struct aac_adapter_info #define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) #define AAC_OPT_ALARM cpu_to_le32(1<<11) #define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13) +#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14) struct aac_dev { - struct aac_dev *next; + struct list_head entry; const char *name; int id; @@ -817,7 +853,8 @@ struct aac_dev size_t comm_size; struct Scsi_Host *scsi_host_ptr; - struct fsa_scsi_hba fsa_dev; + int maximum_num_containers; + struct fsa_dev_info *fsa_dev; pid_t thread_pid; int cardtype; @@ -826,9 +863,9 @@ struct aac_dev */ union { - struct sa_registers *sa; - struct rx_registers *rx; - struct rkt_registers *rkt; + struct sa_registers __iomem *sa; + struct rx_registers __iomem *rx; + struct rkt_registers __iomem *rkt; } regs; u32 OIMR; /* Mask Register Cache */ /* @@ -841,26 +878,16 @@ struct aac_dev * lets break them out so we don't have to do an AND to check them */ u8 nondasd_support; - u8 pae_support; + u8 dac_support; + u8 raid_scsi_mode; }; -#define AllocateAndMapFibSpace(dev, MapFibContext) \ - (dev)->a_ops.AllocateAndMapFibSpace(dev, MapFibContext) - -#define UnmapAndFreeFibSpace(dev, MapFibContext) \ - (dev)->a_ops.UnmapAndFreeFibSpace(dev, MapFibContext) - #define aac_adapter_interrupt(dev) \ (dev)->a_ops.adapter_interrupt(dev) #define aac_adapter_notify(dev, event) \ (dev)->a_ops.adapter_notify(dev, event) -#define aac_adapter_enable_int(dev, event) \ - (dev)->a_ops.adapter_enable_int(dev, event) - -#define aac_adapter_disable_int(dev, event) \ - dev->a_ops.adapter_disable_int(dev, event) #define aac_adapter_check_health(dev) \ (dev)->a_ops.adapter_check_health(dev) @@ -1171,6 +1198,71 @@ union aac_contentinfo { struct aac_fsinfo filesys; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ }; +/* + * Query for Container Configuration Status + */ + +#define CT_GET_CONFIG_STATUS 147 +struct aac_get_config_status { + u32 command; /* VM_ContainerConfig */ + u32 type; /* CT_GET_CONFIG_STATUS */ + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 parm5; + u32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */ +}; + +#define CFACT_CONTINUE 0 +#define CFACT_PAUSE 1 +#define CFACT_ABORT 2 +struct aac_get_config_status_resp { + u32 response; /* ST_OK */ + u32 dummy0; + u32 status; /* CT_OK */ + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 parm5; + struct { + u32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */ + u16 flags; + s16 count; + } data; +}; + +/* + * Accept the configuration as-is + */ + +#define CT_COMMIT_CONFIG 152 + +struct aac_commit_config { + u32 command; /* VM_ContainerConfig */ + u32 type; /* CT_COMMIT_CONFIG */ +}; + +/* + * Query for Container Configuration Count + */ + +#define CT_GET_CONTAINER_COUNT 4 +struct aac_get_container_count { + u32 command; /* VM_ContainerConfig */ + u32 type; /* CT_GET_CONTAINER_COUNT */ +}; + +struct aac_get_container_count_resp { + u32 response; /* ST_OK */ + u32 dummy0; + u32 MaxContainers; + u32 ContainerSwitchEntries; + u32 MaxPartitions; +}; + + /* * Query for "mountable" objects, ie, objects that are typically * associated with a drive letter on the client (host) side. @@ -1205,6 +1297,31 @@ struct aac_mount { struct aac_mntent mnt[1]; }; +#define CT_READ_NAME 130 +struct aac_get_name { + u32 command; /* VM_ContainerConfig */ + u32 type; /* CT_READ_NAME */ + u32 cid; + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */ +}; + +#define CT_OK 218 +struct aac_get_name_resp { + u32 dummy0; + u32 dummy1; + u32 status; /* CT_OK */ + u32 parm1; + u32 parm2; + u32 parm3; + u32 parm4; + u32 parm5; + u8 data[16]; +}; + /* * The following command is sent to shut down each container. */ @@ -1446,6 +1563,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); int fib_complete(struct fib * context); #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) struct aac_dev *aac_init_adapter(struct aac_dev *dev); +int aac_get_config_status(struct aac_dev *dev); int aac_get_containers(struct aac_dev *dev); int aac_scsi_cmd(struct scsi_cmnd *cmd); int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 36ae4af39..7f3a22200 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -480,7 +480,7 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) default: data_dir = DMA_NONE; } - if (dev->pae_support == 1) { + if (dev->dac_support == 1) { struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; byte_count = 0; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index b5ac3c270..f53956f77 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -761,7 +761,7 @@ void aac_printf(struct aac_dev *dev, u32 val) length = 255; if (cp[length] != 0) cp[length] = 0; - if (level == LOG_HIGH_ERROR) + if (level == LOG_AAC_HIGH_ERROR) printk(KERN_WARNING "aacraid:%s", cp); else printk(KERN_INFO "aacraid:%s", cp); diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c55219142..127fb8925 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -62,18 +63,9 @@ MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, " "Adaptec Advanced Raid Products, " "and HP NetRAID-4M SCSI driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(AAC_DRIVER_VERSION); - -int nondasd = -1; -module_param(nondasd, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); - -int paemode = -1; -module_param(paemode, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); - -struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; -static unsigned aac_count; +static LIST_HEAD(aac_devices); static int aac_cfg_major = -1; /* @@ -83,44 +75,54 @@ static int aac_cfg_major = -1; * Note: The last field is used to index into aac_drivers below. */ static struct pci_device_id aac_pci_tbl[] = { - { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si */ - { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di */ - { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si */ - { 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Si */ - { 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di */ - { 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di */ - { 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di */ - { 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult*/ - { 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat*/ - { 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader)*/ - { 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan)*/ - { 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m)*/ - { 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220*/ - { 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230*/ - - { 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier)*/ - { 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado)*/ - { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020 ZCR PCI-X U320 */ - { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025 ZCR DIMM U320 */ - { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - - { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/ - { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */ - + { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ + { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ + { 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */ + { 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di (Viper/PERC3DiV) */ + { 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult */ + { 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat */ + { 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader) */ + { 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan) */ + { 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m) */ + { 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220 (Legend Crusader) */ + { 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230 (Legend Vulcan) */ + + { 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier) */ + { 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado) */ + { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 20 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x028d, 0, 0, 21 }, /* ASR-2130S (Lancer) */ + { 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 22 }, /* Jupiter Platform */ + { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 23 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ + { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 24 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ + { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 25 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ - { 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */ - - { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ - { 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 32 }, /* ASR-2020SA (ZCR PCI-X SATA) */ - { 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 33 }, /* ASR-2025SA (ZCR DIMM SATA) */ + { 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* AAR-2610SA PCI SATA 6ch */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 31 }, /* ASR-2240S */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 32 }, /* ASR-4005SAS */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 33 }, /* ASR-4000SAS */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 34 }, /* ASR-4800SAS */ + { 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 35 }, /* ASR-4805SAS */ + + { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 36 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 37 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 38 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 39 }, /* Dell PERC2/QC */ + { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 40 }, /* HP NetRAID-4M */ + + { 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 41 }, /* Dell Catchall */ + { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 42 }, /* Legend Catchall */ + { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 43 }, /* Adaptec Catch All */ + { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 44 }, /* Adaptec Rocket Catch All */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -131,44 +133,54 @@ MODULE_DEVICE_TABLE(pci, aac_pci_tbl); * for the card. At that time we can remove the channels from here */ static struct aac_driver_ident aac_drivers[] = { - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */ - { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT }, /* catapult*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT }, /* tomcat*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m)*/ - { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT }, /* Legend S220*/ - { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT }, /* Legend S230*/ - - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020ZCR ", 2 }, /* ASR-2020 ZCR PCI-X U320 */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025ZCR ", 2 }, /* ASR-2025 ZCR DIMM U320 */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - - { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/ - { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ - { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ - { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */ - { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ - + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si (Iguana/PERC2Si) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Opal/PERC3Di) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si (SlimFast/PERC3Si */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Viper/PERC3DiV) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Lexus/PERC3DiL) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 1, AAC_QUIRK_31BIT }, /* PERC 3/Di (Jaguar/PERC3DiJ) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Dagger/PERC3DiD) */ + { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Boxster/PERC3DiB) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT }, /* catapult */ + { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT }, /* tomcat */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT }, /* Legend S220 (Legend Crusader) */ + { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT }, /* Legend S230 (Legend Vulcan) */ + + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020ZCR ", 2 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025ZCR ", 2 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-2130S PCI-X ", 1 }, /* ASR-2130S (Lancer) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2 }, /* Jupiter Platform */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ { aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "SATA 6Channel ", 1 }, /* SATA 6Ch (Bearcat) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4005SAS ", 1 }, /* ASR-4005SAS */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS */ + { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS */ + + { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/ + { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ + { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ + { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2/QC */ + { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ - { aac_rkt_init,"aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA (ZCR PCI-X SATA) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA (ZCR DIMM SATA) */ + { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT }, /* Dell Catchall */ + { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT }, /* Legend Catchall */ + { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT }, /* Adaptec Catch All */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */ }; #ifdef CONFIG_COMPAT @@ -408,15 +420,17 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) } } spin_unlock_irqrestore(&dev->list_lock, flags); + if (active) + break; - /* - * We can exit If all the commands are complete - */ - if (active == 0) - return SUCCESS; } + /* + * We can exit If all the commands are complete + */ + if (active == 0) + return SUCCESS; spin_unlock_irq(host->host_lock); - scsi_sleep(HZ); + ssleep(1); spin_lock_irq(host->host_lock); } printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); @@ -437,11 +451,18 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) static int aac_cfg_open(struct inode *inode, struct file *file) { + struct aac_dev *aac; unsigned minor = iminor(inode); + int err = -ENODEV; + + list_for_each_entry(aac, &aac_devices, entry) { + if (aac->id == minor) { + file->private_data = aac; + err = 0; + break; + } + } - if (minor >= aac_count) - return -ENODEV; - file->private_data = aac_devices[minor]; return 0; } @@ -500,10 +521,18 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, { unsigned index = id->driver_data; struct Scsi_Host *shost; - struct fsa_scsi_hba *fsa_dev_ptr; struct aac_dev *aac; - int container; + struct list_head *insert = &aac_devices; int error = -ENODEV; + int unique_id = 0; + + list_for_each_entry(aac, &aac_devices, entry) { + if (aac->id > unique_id) { + insert = &aac->entry; + break; + } + unique_id++; + } if (pci_enable_device(pdev)) goto out; @@ -522,16 +551,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, pci_set_master(pdev); - /* Increment the host adapter count */ - aac_count++; - shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev)); if (!shost) goto out_disable_pdev; shost->irq = pdev->irq; shost->base = pci_resource_start(pdev, 0); - shost->unique_id = aac_count - 1; + shost->unique_id = unique_id; aac = (struct aac_dev *)shost->hostdata; aac->scsi_host_ptr = shost; @@ -539,17 +565,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, aac->name = aac_driver_template.name; aac->id = shost->unique_id; aac->cardtype = index; + INIT_LIST_HEAD(&aac->entry); aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL); if (!aac->fibs) goto out_free_host; spin_lock_init(&aac->fib_lock); - /* Initialize the ordinal number of the device to -1 */ - fsa_dev_ptr = &aac->fsa_dev; - for (container = 0; container < MAXIMUM_NUM_CONTAINERS; container++) - fsa_dev_ptr->devname[container][0] = '\0'; - if ((*aac_drivers[index].init)(aac)) goto out_free_fibs; @@ -574,26 +596,32 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, else shost->max_channel = 1; + aac_get_config_status(aac); aac_get_containers(aac); - aac_devices[aac_count-1] = aac; + list_add(&aac->entry, insert); + + shost->max_id = aac->maximum_num_containers; + if (shost->max_id < MAXIMUM_NUM_CONTAINERS) + shost->max_id = MAXIMUM_NUM_CONTAINERS; + else + shost->this_id = shost->max_id; /* * dmb - we may need to move the setting of these parms somewhere else once * we get a fib that can report the actual numbers */ - shost->max_id = MAXIMUM_NUM_CONTAINERS; shost->max_lun = AAC_MAX_LUN; + pci_set_drvdata(pdev, shost); + error = scsi_add_host(shost, &pdev->dev); if (error) goto out_deinit; - - pci_set_drvdata(pdev, shost); scsi_scan_host(shost); return 0; - out_deinit: +out_deinit: kill_proc(aac->thread_pid, SIGKILL, 0); wait_for_completion(&aac->aif_completion); @@ -602,14 +630,14 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); kfree(aac->queues); free_irq(pdev->irq, aac); - iounmap((void * )aac->regs.sa); + iounmap(aac->regs.sa); out_free_fibs: kfree(aac->fibs); + kfree(aac->fsa_dev); out_free_host: scsi_host_put(shost); out_disable_pdev: pci_disable_device(pdev); - aac_count--; out: return error; } @@ -631,22 +659,13 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) kfree(aac->queues); free_irq(pdev->irq, aac); - iounmap((void * )aac->regs.sa); + iounmap(aac->regs.sa); kfree(aac->fibs); + list_del(&aac->entry); scsi_host_put(shost); pci_disable_device(pdev); - - /* - * We don't decrement aac_count here because adapters can be unplugged - * in a different order than they were detected. If we're ever going - * to overflow MAXIMUM_NUM_ADAPTERS we'll have to consider using a - * bintmap of free aac_devices slots. - */ -#if 0 - aac_count--; -#endif } static struct pci_driver aac_pci_driver = { diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 7a7b3d7bc..df8ccb93f 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -87,66 +87,6 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } -/** - * aac_rkt_enable_interrupt - Enable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Enable event reporting from the i960 for a given event. - */ - -static void aac_rkt_enable_interrupt(struct aac_dev * dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); - break; - } -} - -/** - * aac_rkt_disable_interrupt - Disable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Disable event reporting from the i960 for a given event. - */ - -static void aac_rkt_disable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_4); - break; - } -} - /** * rkt_sync_cmd - send a command and wait * @dev: Adapter @@ -180,7 +120,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) /* * Disable doorbell interrupts */ - rkt_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); /* * Force the completion of the mask register write before issuing * the interrupt. @@ -221,13 +161,14 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) /* * Restore interrupt mask even though we timed out */ - rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); return -ETIMEDOUT; } /* * Pull the synch status from Mailbox 0. */ - *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0])); + if (status) + *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0])); /* * Clear the synch command doorbell. */ @@ -235,7 +176,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) /* * Restore interrupt mask */ - rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); return 0; } @@ -334,7 +275,7 @@ static void aac_rkt_start_adapter(struct aac_dev *dev) */ static int aac_rkt_check_health(struct aac_dev *dev) { - long status = rkt_readl(dev, IndexRegs.Mailbox[7]); + u32 status = le32_to_cpu(rkt_readl(dev, MUnit.OMRx[0])); /* * Check to see if the board failed any self tests. @@ -344,34 +285,42 @@ static int aac_rkt_check_health(struct aac_dev *dev) /* * Check to see if the board panic'd. */ - if (status & KERNEL_PANIC) - { - char * buffer = kmalloc(512, GFP_KERNEL|__GFP_DMA); + if (status & KERNEL_PANIC) { + char * buffer; struct POSTSTATUS { u32 Post_Command; u32 Post_Address; - } * post = kmalloc(sizeof(struct POSTSTATUS), GFP_KERNEL); - dma_addr_t paddr = pci_map_single(dev->pdev, post, sizeof(struct POSTSTATUS), 2); - dma_addr_t baddr = pci_map_single(dev->pdev, buffer, 512, 1); - u32 status = -1; - int ret = -2; - - memset(buffer, 0, 512); - post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS); - post->Post_Address = cpu_to_le32(baddr); - rkt_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr)); - rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status); - pci_unmap_single(dev->pdev, paddr, sizeof(struct POSTSTATUS),2); - kfree(post); - if ((buffer[0] == '0') && (buffer[1] == 'x')) { - ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); - ret <<= 4; - ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); + } * post; + dma_addr_t paddr, baddr; + int ret; + + if ((status & 0xFF000000L) == 0xBC000000L) + return (status >> 16) & 0xFF; + buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); + ret = -2; + if (buffer == NULL) + return ret; + post = pci_alloc_consistent(dev->pdev, + sizeof(struct POSTSTATUS), &paddr); + if (post == NULL) { + pci_free_consistent(dev->pdev, 512, buffer, baddr); + return ret; } - pci_unmap_single(dev->pdev, baddr, 512, 1); - kfree(buffer); - return ret; - } + memset(buffer, 0, 512); + post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS); + post->Post_Address = cpu_to_le32(baddr); + rkt_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr)); + rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status); + pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), + post, paddr); + if ((buffer[0] == '0') && (buffer[1] == 'x')) { + ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); + ret <<= 4; + ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); + } + pci_free_consistent(dev->pdev, 512, buffer, baddr); + return ret; + } /* * Wait for the adapter to be up and running. */ @@ -405,7 +354,7 @@ int aac_rkt_init(struct aac_dev *dev) /* * Map in the registers from the adapter. */ - if((dev->regs.rkt = (struct rkt_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + if((dev->regs.rkt = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) { printk(KERN_WARNING "aacraid: unable to map i960.\n" ); goto error_iounmap; @@ -455,8 +404,6 @@ int aac_rkt_init(struct aac_dev *dev) * Fill in the function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_rkt_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt; dev->a_ops.adapter_notify = aac_rkt_notify_adapter; dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; dev->a_ops.adapter_check_health = aac_rkt_check_health; diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index e111087c0..df12f5301 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -87,66 +87,6 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } -/** - * aac_rx_enable_interrupt - Enable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Enable event reporting from the i960 for a given event. - */ - -static void aac_rx_enable_interrupt(struct aac_dev * dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); - break; - } -} - -/** - * aac_rx_disable_interrupt - Disable event reporting - * @dev: Adapter - * @event: Event to enable - * - * Disable event reporting from the i960 for a given event. - */ - -static void aac_rx_disable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_1); - break; - - case HostNormRespQue: - dev->irq_mask |= (OUTBOUNDDOORBELL_2); - break; - - case AdapNormCmdNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_3); - break; - - case AdapNormRespNotFull: - dev->irq_mask |= (OUTBOUNDDOORBELL_4); - break; - } -} - /** * rx_sync_cmd - send a command and wait * @dev: Adapter @@ -334,7 +274,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev) */ static int aac_rx_check_health(struct aac_dev *dev) { - long status = rx_readl(dev, IndexRegs.Mailbox[7]); + u32 status = le32_to_cpu(rx_readl(dev, MUnit.OMRx[0])); /* * Check to see if the board failed any self tests. @@ -345,29 +285,39 @@ static int aac_rx_check_health(struct aac_dev *dev) * Check to see if the board panic'd. */ if (status & KERNEL_PANIC) { - char * buffer = kmalloc(512, GFP_KERNEL); + char * buffer; struct POSTSTATUS { u32 Post_Command; u32 Post_Address; - } * post = kmalloc(sizeof(struct POSTSTATUS), GFP_KERNEL); - dma_addr_t paddr = pci_map_single(dev->pdev, post, sizeof(struct POSTSTATUS), 2); - dma_addr_t baddr = pci_map_single(dev->pdev, buffer, 512, 1); - u32 status = -1; - int ret = -2; + } * post; + dma_addr_t paddr, baddr; + int ret; + + if ((status & 0xFF000000L) == 0xBC000000L) + return (status >> 16) & 0xFF; + buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); + ret = -2; + if (buffer == NULL) + return ret; + post = pci_alloc_consistent(dev->pdev, + sizeof(struct POSTSTATUS), &paddr); + if (post == NULL) { + pci_free_consistent(dev->pdev, 512, buffer, baddr); + return ret; + } memset(buffer, 0, 512); post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS); post->Post_Address = cpu_to_le32(baddr); rx_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr)); rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status); - pci_unmap_single(dev->pdev, paddr, sizeof(struct POSTSTATUS), 2); - kfree(post); + pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), + post, paddr); if ((buffer[0] == '0') && (buffer[1] == 'x')) { ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); ret <<= 4; ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); } - pci_unmap_single(dev->pdev, baddr, 512, 1); - kfree(buffer); + pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; } /* @@ -379,7 +329,7 @@ static int aac_rx_check_health(struct aac_dev *dev) * Everything is OK */ return 0; -} /* aac_rx_check_health */ +} /** * aac_rx_init - initialize an i960 based AAC card @@ -403,7 +353,7 @@ int aac_rx_init(struct aac_dev *dev) /* * Map in the registers from the adapter. */ - if((dev->regs.rx = (struct rx_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + if((dev->regs.rx = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) { printk(KERN_WARNING "aacraid: unable to map i960.\n" ); return -1; @@ -454,8 +404,6 @@ int aac_rx_init(struct aac_dev *dev) * Fill in the function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; dev->a_ops.adapter_notify = aac_rx_notify_adapter; dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_check_health = aac_rx_check_health; diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 23e3b7644..13e881884 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -81,68 +81,6 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } -/** - * aac_sa_enable_interrupt - enable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_enable_interrupt(struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_4); - break; - } -} - -/** - * aac_sa_disable_interrupt - disable an interrupt event - * @dev: Which adapter to enable. - * @event: Which adapter event. - * - * This routine will enable the corresponding adapter event to cause an interrupt on - * the host. - */ - -void aac_sa_disable_interrupt (struct aac_dev *dev, u32 event) -{ - switch (event) { - - case HostNormCmdQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_1); - break; - - case HostNormRespQue: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_2); - break; - - case AdapNormCmdNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_3); - break; - - case AdapNormRespNotFull: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_4); - break; - } -} - /** * aac_sa_notify_adapter - handle adapter notification * @dev: Adapter that notification is for @@ -357,7 +295,7 @@ int aac_sa_init(struct aac_dev *dev) */ dprintk(("PREMAP\n")); - if((dev->regs.sa = (struct sa_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + if((dev->regs.sa = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) { printk(KERN_WARNING "aacraid: unable to map ARM.\n" ); goto error_iounmap; @@ -401,8 +339,6 @@ int aac_sa_init(struct aac_dev *dev) */ dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; - dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; - dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; dev->a_ops.adapter_notify = aac_sa_notify_adapter; dev->a_ops.adapter_sync_cmd = sa_sync_cmd; dev->a_ops.adapter_check_health = aac_sa_check_health; diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index d796cac2a..5a6d74dec 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -15,16 +15,6 @@ * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) * changed its name to ConnectCom Solutions, Inc. * - * There is an AdvanSys Linux WWW page at: - * http://www.connectcom.net/downloads/software/os/linux.html - * http://www.advansys.com/linux.html - * - * The latest released version of the AdvanSys driver is available at: - * ftp://ftp.advansys.com/pub/linux/linux.tgz - * ftp://ftp.connectcom.net/pub/linux/linux.tgz - * - * Please send questions, comments, bug reports to: - * support@connectcom.net */ /* @@ -41,7 +31,6 @@ H. Release History I. Known Problems/Fix List J. Credits (Chronological Order) - K. ConnectCom (AdvanSys) Contact Information A. Linux Kernels Supported by this Driver @@ -807,6 +796,7 @@ #include #include +#include #include #include #include "advansys.h" @@ -2032,9 +2022,6 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); #define ADV_LIB_VERSION_MAJOR 5 #define ADV_LIB_VERSION_MINOR 14 -/* d_os_dep.h */ -#define ADV_OS_LINUX - /* * Define Adv Library required special types. */ @@ -3370,9 +3357,9 @@ do { \ /* * Default EEPROM Configuration structure defined in a_init.c. */ -extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config; -extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config; -extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; +static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config; +static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config; +static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; /* * DvcGetPhyAddr() flag arguments @@ -4580,7 +4567,7 @@ advansys_detect(struct scsi_host_template *tpnt) boardp->id = asc_board_count - 1; /* Initialize spinlock. */ - boardp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&boardp->lock); /* * Handle both narrow and wide boards. diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h index 5230ba01c..3f4bde023 100644 --- a/drivers/scsi/advansys.h +++ b/drivers/scsi/advansys.h @@ -13,37 +13,11 @@ * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) * changed its name to ConnectCom Solutions, Inc. * - * There is an AdvanSys Linux WWW page at: - * http://www.connectcom.net/downloads/software/os/linux.html - * http://www.advansys.com/linux.html - * - * The latest released version of the AdvanSys driver is available at: - * ftp://ftp.advansys.com/pub/linux/linux.tgz - * ftp://ftp.connectcom.net/pub/linux/linux.tgz - * - * Please send questions, comments, bug reports to: - * linux@connectcom.net or bfrey@turbolinux.com.cn */ #ifndef _ADVANSYS_H #define _ADVANSYS_H -#include -#ifndef LINUX_VERSION_CODE -#include -#endif /* LINUX_VERSION_CODE */ - -/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ -#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) -/* Driver supported only in version 2.2 and version >= 2.4. */ -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \ - (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \ - LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0)) -#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels." -#endif -#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0)) -#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0)) - /* * Scsi_Host_Template function prototypes. */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index d11f86948..50cb2be49 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -3830,10 +3830,15 @@ static int __init aha152x_init(void) if (setup_countdevice->host->host_lock); - scsi_sleep(4 * HZ); + ssleep(4); spin_lock_irq(SCpnt->device->host->host_lock); WAIT(STATUS(SCpnt->device->host->io_port), @@ -1543,7 +1543,7 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt) * we are pretty desperate anyways. */ spin_unlock_irq(SCpnt->device->host->host_lock); - scsi_sleep(4 * HZ); + ssleep(4); spin_lock_irq(SCpnt->device->host->host_lock); WAIT(STATUS(SCpnt->device->host->io_port), diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h index cba290ce9..c402351dc 100644 --- a/drivers/scsi/aha1542.h +++ b/drivers/scsi/aha1542.h @@ -91,10 +91,12 @@ struct chain { }; /* These belong in scsi.h also */ -#define any2scsi(up, p) \ -(up)[0] = (((unsigned long)(p)) >> 16) ; \ -(up)[1] = (((unsigned long)(p)) >> 8); \ -(up)[2] = ((unsigned long)(p)); +static inline void any2scsi(u8 *p, u32 v) +{ + p[0] = v >> 16; + p[1] = v >> 8; + p[2] = v; +} #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 8dd5d1f09..e0cd4ba41 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -272,7 +272,7 @@ static void ahci_host_stop(struct ata_host_set *host_set) static int ahci_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp; int rc; @@ -291,7 +291,7 @@ static int ahci_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - mem = pci_alloc_consistent(pdev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma); + mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { rc = -ENOMEM; goto err_out_kfree; @@ -355,7 +355,7 @@ err_out: static void ahci_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct ahci_port_priv *pp = ap->private_data; void *mmio = ap->host_set->mmio_base; void *port_mmio = ahci_port_base(mmio, ap->port_no); @@ -372,8 +372,8 @@ static void ahci_port_stop(struct ata_port *ap) msleep(500); ap->private_data = NULL; - pci_free_consistent(pdev, AHCI_PORT_PRIV_DMA_SZ, - pp->cmd_slot, pp->cmd_slot_dma); + dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, + pp->cmd_slot, pp->cmd_slot_dma); kfree(pp); ata_port_stop(ap); } @@ -705,7 +705,7 @@ static void ahci_setup_port(struct ata_ioports *port, unsigned long base, static int ahci_host_init(struct ata_probe_ent *probe_ent) { struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = probe_ent->pdev; + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void __iomem *mmio = probe_ent->mmio_base; u32 tmp, cap_save; u16 tmp16; @@ -863,7 +863,7 @@ static void pci_enable_intx(struct pci_dev *pdev) static void ahci_print_info(struct ata_probe_ent *probe_ent) { struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = probe_ent->pdev; + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void *mmio = probe_ent->mmio_base; u32 vers, cap, impl, speed; const char *speed_s; @@ -946,10 +946,6 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; @@ -967,7 +963,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, AHCI_PCI_BAR), @@ -1039,7 +1035,6 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("AHCI SATA low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); -MODULE_VERSION(DRV_VERSION); module_init(ahci_init); module_exit(ahci_exit); diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx index b29981521..c2523a30a 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic79xx +++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx @@ -46,7 +46,7 @@ config AIC79XX_RESET_DELAY_MS config AIC79XX_BUILD_FIRMWARE bool "Build Adapter Firmware with Kernel Build" - depends on SCSI_AIC79XX + depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD help This option should only be enabled if you are modifying the firmware source to the aic79xx driver and wish to have the generated firmware diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index 473a658d2..8398e0dd4 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -61,7 +61,7 @@ config AIC7XXX_PROBE_EISA_VL config AIC7XXX_BUILD_FIRMWARE bool "Build Adapter Firmware with Kernel Build" - depends on SCSI_AIC7XXX + depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD help This option should only be enabled if you are modifying the firmware source to the aic7xxx driver and wish to have the generated firmware diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index 54a09155e..d97a8b137 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -185,10 +185,8 @@ aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev, return (ENOMEM); strcpy(name, buf); ahc = ahc_alloc(&aic7xxx_driver_template, name); - if (ahc == NULL) { - free(name, M_DEVBUF); + if (ahc == NULL) return (ENOMEM); - } error = aic7770_config(ahc, entry, eisaBase); if (error != 0) { ahc->bsh.ioport = 0; diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index be65968ac..fd4b2f3eb 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -549,7 +549,7 @@ struct ahd_dma64_seg { struct map_node { bus_dmamap_t dmamap; - bus_addr_t physaddr; + dma_addr_t physaddr; uint8_t *vaddr; SLIST_ENTRY(map_node) links; }; @@ -626,8 +626,8 @@ struct scb { struct map_node *sense_map; void *sg_list; uint8_t *sense_data; - bus_addr_t sg_list_busaddr; - bus_addr_t sense_busaddr; + dma_addr_t sg_list_busaddr; + dma_addr_t sense_busaddr; u_int sg_count;/* How full ahd_dma_seg is */ #define AHD_MAX_LQ_CRC_ERRORS 5 u_int crc_retry_count; @@ -1198,7 +1198,7 @@ struct ahd_softc { bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; + dma_addr_t shared_data_busaddr; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index 449fe95ae..cca58edc8 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg @@ -1199,7 +1199,7 @@ register TARGPCISTAT { /* * LQ Packet In - * The last LQ Packet recieved + * The last LQ Packet received */ register LQIN { address 0x020 diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 4440afca5..137fb1a37 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -5270,7 +5270,6 @@ ahd_free(struct ahd_softc *ahd) default: case 5: ahd_shutdown(ahd); - TAILQ_REMOVE(&ahd_tailq, ahd, links); /* FALLTHROUGH */ case 4: ahd_dmamap_unload(ahd, ahd->shared_data_dmat, @@ -5493,9 +5492,9 @@ ahd_probe_scbs(struct ahd_softc *ahd) { static void ahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { - bus_addr_t *baddr; + dma_addr_t *baddr; - baddr = (bus_addr_t *)arg; + baddr = (dma_addr_t *)arg; *baddr = segs->ds_addr; } @@ -5926,9 +5925,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd) struct map_node *sense_map; uint8_t *segs; uint8_t *sense_data; - bus_addr_t hscb_busaddr; - bus_addr_t sg_busaddr; - bus_addr_t sense_busaddr; + dma_addr_t hscb_busaddr; + dma_addr_t sg_busaddr; + dma_addr_t sense_busaddr; int newcount; int i; @@ -6161,7 +6160,7 @@ ahd_init(struct ahd_softc *ahd) { uint8_t *base_vaddr; uint8_t *next_vaddr; - bus_addr_t next_baddr; + dma_addr_t next_baddr; size_t driver_data_size; int i; int error; @@ -6205,7 +6204,7 @@ ahd_init(struct ahd_softc *ahd) if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahd->flags & AHD_39BIT_ADDRESSING - ? (bus_addr_t)0x7FFFFFFFFFULL + ? (dma_addr_t)0x7FFFFFFFFFULL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index 440212af4..d80bc5161 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -231,7 +231,7 @@ ahd_unpause(struct ahd_softc *ahd) /*********************** Scatter Gather List Handling *************************/ static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, - void *sgptr, bus_addr_t addr, + void *sgptr, dma_addr_t addr, bus_size_t len, int last); static __inline void ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb); @@ -242,10 +242,10 @@ static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, static __inline void * ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, - void *sgptr, bus_addr_t addr, bus_size_t len, int last) + void *sgptr, dma_addr_t addr, bus_size_t len, int last) { scb->sg_count++; - if (sizeof(bus_addr_t) > 4 + if (sizeof(dma_addr_t) > 4 && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { struct ahd_dma64_seg *sg; @@ -361,7 +361,7 @@ ahd_sg_size(struct ahd_softc *ahd) static __inline void * ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) { - bus_addr_t sg_offset; + dma_addr_t sg_offset; /* sg_list_phys points to entry 1, not 0 */ sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); @@ -371,7 +371,7 @@ ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) static __inline uint32_t ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) { - bus_addr_t sg_offset; + dma_addr_t sg_offset; /* sg_list_phys points to entry 1, not 0 */ sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 68b4539a4..e7f688f19 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -52,29 +52,20 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ #endif #include /* For fetching system memory size */ +#include /* For ssleep/msleep */ /* * Lock protecting manipulation of the ahd softc list. */ spinlock_t ahd_list_spinlock; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic79xx = { - PROC_SCSI_AIC79XX, 7, "aic79xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* For dynamic sglist size calculation. */ u_int ahd_linux_nseg; @@ -415,7 +406,6 @@ uint32_t aic79xx_periodic_otag; /* * Module information and settable options. */ -#ifdef MODULE static char *aic79xx = NULL; /* * Just in case someone uses commas to separate items on the insmod @@ -426,9 +416,8 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); -#endif +MODULE_VERSION(AIC79XX_DRIVER_VERSION); MODULE_PARM(aic79xx, "s"); MODULE_PARM_DESC(aic79xx, "period delimited, options string.\n" @@ -463,7 +452,6 @@ MODULE_PARM_DESC(aic79xx, " Change Read Streaming for Controller's 2 and 3\n" "\n" " options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'"); -#endif static void ahd_linux_handle_scsi_status(struct ahd_softc *, struct ahd_linux_device *, @@ -513,9 +501,6 @@ static void ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, struct ahd_linux_target *targ); -static __inline int - ahd_linux_dv_fallback(struct ahd_softc *ahd, - struct ahd_devinfo *devinfo); static int ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, @@ -566,7 +551,7 @@ static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, struct ahd_dma_seg *sg, - bus_addr_t addr, bus_size_t len); + dma_addr_t addr, bus_size_t len); static __inline void ahd_schedule_completeq(struct ahd_softc *ahd) @@ -584,31 +569,20 @@ ahd_schedule_completeq(struct ahd_softc *ahd) static __inline void ahd_schedule_runq(struct ahd_softc *ahd) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_schedule(&ahd->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahd_runq_tasklet((unsigned long)ahd); -#endif } static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet, (unsigned long)ahd); -#endif } static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_kill(&ahd->platform_data->runq_tasklet); -#endif } static __inline struct ahd_linux_device* @@ -739,7 +713,7 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, - struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len) + struct ahd_dma_seg *sg, dma_addr_t addr, bus_size_t len) { int consumed; @@ -751,7 +725,7 @@ ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, sg->addr = ahd_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; - if (sizeof(bus_addr_t) > 4 + if (sizeof(dma_addr_t) > 4 && (ahd->flags & AHD_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK; @@ -856,6 +830,7 @@ ahd_linux_detect(Scsi_Host_Template *template) { struct ahd_softc *ahd; int found; + int error = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* @@ -894,11 +869,7 @@ ahd_linux_detect(Scsi_Host_Template *template) "aic79xx: insmod or else it might trash certain memory areas.\n"); #endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic79xx"; -#else - template->proc_dir = &proc_scsi_aic79xx; -#endif /* * Initialize our softc list lock prior to @@ -907,7 +878,9 @@ ahd_linux_detect(Scsi_Host_Template *template) ahd_list_lockinit(); #ifdef CONFIG_PCI - ahd_linux_pci_init(); + error = ahd_linux_pci_init(); + if (error) + return error; #endif /* @@ -924,7 +897,7 @@ ahd_linux_detect(Scsi_Host_Template *template) spin_lock_irq(&io_request_lock); #endif aic79xx_detect_complete++; - return (found); + return 0; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) @@ -1565,6 +1538,8 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) ahd = *(struct ahd_softc **)cmd->device->host->hostdata; recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); + if (!recovery_cmd) + return (FAILED); memset(recovery_cmd, 0, sizeof(struct scsi_cmnd)); recovery_cmd->device = cmd->device; recovery_cmd->scsi_done = ahd_linux_dev_reset_complete; @@ -1580,10 +1555,12 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd) cmd->device->lun, /*alloc*/FALSE); if (dev == NULL) { ahd_midlayer_entrypoint_unlock(ahd, &s); + kfree(recovery_cmd); return (FAILED); } if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) { ahd_midlayer_entrypoint_unlock(ahd, &s); + kfree(recovery_cmd); return (FAILED); } tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, @@ -1699,35 +1676,27 @@ ahd_runq_tasklet(unsigned long data) { struct ahd_softc* ahd; struct ahd_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) u_long flags; -#endif ahd = (struct ahd_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahd_lock(ahd, &flags); -#endif while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) { TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); dev->flags &= ~AHD_DEV_ON_RUN_LIST; ahd_linux_check_device_queue(ahd, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahd_unlock(ahd, &flags); ahd_lock(ahd, &flags); -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahd_unlock(ahd, &flags); -#endif } /******************************** Bus DMA *************************************/ int ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, + dma_addr_t lowaddr, dma_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) @@ -1764,7 +1733,6 @@ ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, { bus_dmamap_t map; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); if (map == NULL) return (ENOMEM); @@ -1776,28 +1744,20 @@ ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, * our dma mask when doing allocations. */ if (ahd->dev_softc != NULL) - if (ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) { + if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) { printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); + kfree(map); return (ENODEV); } *vaddr = pci_alloc_consistent(ahd->dev_softc, dmat->maxsize, &map->bus_addr); if (ahd->dev_softc != NULL) - if (ahd_pci_set_dma_mask(ahd->dev_softc, + if (pci_set_dma_mask(ahd->dev_softc, ahd->platform_data->hw_dma_mask)) { printk(KERN_WARNING "aic79xx: No suitable DMA available.\n"); + kfree(map); return (ENODEV); } -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif if (*vaddr == NULL) return (ENOMEM); *mapp = map; @@ -1808,12 +1768,8 @@ void ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) pci_free_consistent(ahd->dev_softc, dmat->maxsize, vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif } int @@ -1827,12 +1783,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map, */ bus_dma_segment_t stack_sg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif stack_sg.ds_len = dmat->maxsize; cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); return (0); @@ -2064,9 +2015,7 @@ aic79xx_setup(char *s) return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic79xx=", aic79xx_setup); -#endif uint32_t aic79xx_verbose; @@ -2109,8 +2058,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) ahd_set_name(ahd, new_name); } host->unique_id = ahd->unit; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) scsi_set_pci_device(host, ahd->dev_softc); #endif ahd_linux_setup_user_rd_strm_settings(ahd); @@ -2262,15 +2210,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) ahd->platform_data->completeq_timer.data = (u_long)ahd; ahd->platform_data->completeq_timer.function = (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_sem); init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem); -#else - ahd->platform_data->eh_sem = MUTEX_LOCKED; - ahd->platform_data->dv_sem = MUTEX_LOCKED; - ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif ahd_setup_runq_tasklet(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; return (0); @@ -2325,18 +2267,11 @@ ahd_platform_free(struct ahd_softc *ahd) release_region(ahd->bshs[1].ioport, 256); if (ahd->tags[0] == BUS_SPACE_MEMIO && ahd->bshs[0].maddr != NULL) { - u_long base_addr; - - base_addr = (u_long)ahd->bshs[0].maddr; - base_addr &= PAGE_MASK; - iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + iounmap(ahd->bshs[0].maddr); release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we detach from the scsi midlayer before the PCI * layer invokes our remove callback. No per-instance @@ -2915,6 +2850,19 @@ out: ahd_unlock(ahd, &s); } +static __inline int +ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) +{ + u_long s; + int retval; + + ahd_lock(ahd, &s); + retval = ahd_linux_fallback(ahd, devinfo); + ahd_unlock(ahd, &s); + + return (retval); +} + static void ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, @@ -3163,7 +3111,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, break; } if (status & SSQ_DELAY) - scsi_sleep(1 * HZ); + ssleep(1); break; case SS_START: @@ -3323,7 +3271,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) - scsi_sleep(ahd->our_id*HZ/10); + msleep(ahd->our_id*1000/10); break; } #ifdef AHD_DEBUG @@ -3367,7 +3315,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd, targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { if ((status & SSQ_DELAY) != 0) - scsi_sleep(1 * HZ); + ssleep(1); } else { #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_DV) { @@ -3551,19 +3499,6 @@ ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd, cmd->cmnd[4] = le | SSS_START; } -static __inline int -ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) -{ - u_long s; - int retval; - - ahd_lock(ahd, &s); - retval = ahd_linux_fallback(ahd, devinfo); - ahd_unlock(ahd, &s); - - return (retval); -} - static int ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { @@ -4126,7 +4061,7 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) cmd->use_sg, dir); scb->platform_data->xfer_len = 0; for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { - bus_addr_t addr; + dma_addr_t addr; bus_size_t len; addr = sg_dma_address(cur_seg); @@ -4137,7 +4072,7 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) } } else if (cmd->request_bufflen != 0) { void *sg; - bus_addr_t addr; + dma_addr_t addr; int dir; sg = scb->sg_list; @@ -4371,7 +4306,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel, WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahd->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#else Scsi_Device *scsi_dev; /* @@ -4392,12 +4327,10 @@ ahd_send_async(struct ahd_softc *ahd, char channel, break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahd->platform_data->host != NULL) { scsi_report_bus_reset(ahd->platform_data->host, channel - 'A'); } -#endif break; default: panic("ahd_send_async: Unexpected async event"); @@ -5078,7 +5011,7 @@ static int __init ahd_linux_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return (ahd_linux_detect(&aic79xx_driver_template) ? 0 : -ENODEV); + return ahd_linux_detect(&aic79xx_driver_template); #else scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); if (aic79xx_driver_template.present == 0) { @@ -5095,7 +5028,6 @@ static void __exit ahd_linux_exit(void) { struct ahd_softc *ahd; - u_long l; /* * Shutdown DV threads before going into the SCSI mid-layer. @@ -5103,12 +5035,11 @@ ahd_linux_exit(void) * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahd_list_lock(&l); TAILQ_FOREACH(ahd, &ahd_tailq, links) { ahd_linux_kill_dv_thread(ahd); } - ahd_list_unlock(&l); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we have to unregister from the PCI core _after_ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index f5c284dd4..605f92b6c 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -53,17 +53,9 @@ #include #include -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include /* For tasklet support. */ #include #include -#else -#include -#endif /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahd @@ -144,11 +136,6 @@ extern Scsi_Host_Template aic79xx_driver_template; /***************************** Bus Space/DMA **********************************/ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif typedef uint32_t bus_size_t; typedef enum { @@ -158,12 +145,12 @@ typedef enum { typedef union { u_long ioport; - volatile uint8_t *maddr; + volatile uint8_t __iomem *maddr; } bus_space_handle_t; typedef struct bus_dma_segment { - bus_addr_t ds_addr; + dma_addr_t ds_addr; bus_size_t ds_len; } bus_dma_segment_t; @@ -177,11 +164,11 @@ typedef struct ahd_linux_dma_tag* bus_dma_tag_t; struct ahd_linux_dmamap { - bus_addr_t bus_addr; + dma_addr_t bus_addr; }; typedef struct ahd_linux_dmamap* bus_dmamap_t; -typedef int bus_dma_filter_t(void*, bus_addr_t); +typedef int bus_dma_filter_t(void*, dma_addr_t); typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); #define BUS_DMA_WAITOK 0x0 @@ -198,7 +185,7 @@ typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); int ahd_dma_tag_create(struct ahd_softc *, bus_dma_tag_t /*parent*/, bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, + dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/, bus_dma_filter_t*/*filter*/, void */*filterarg*/, bus_size_t /*maxsize*/, int /*nsegments*/, bus_size_t /*maxsegsz*/, int /*flags*/, @@ -280,11 +267,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) } /***************************** SMP support ************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -#include -#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) #define AHD_SCSI_HAS_HOST_LOCK 1 @@ -509,11 +492,8 @@ typedef enum { struct scb_platform_data { struct ahd_linux_device *dev; - bus_addr_t buf_busaddr; + dma_addr_t buf_busaddr; uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif uint32_t sense_resid; /* Auto-Sense residual */ ahd_linux_scb_flags flags; }; @@ -543,9 +523,7 @@ struct ahd_platform_data { struct ahd_completeq completeq; spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; -#endif u_int qfrozen; pid_t dv_pid; struct timer_list completeq_timer; @@ -562,7 +540,7 @@ struct ahd_platform_data { uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; + uint64_t hw_dma_mask; ahd_linux_softc_flags flags; }; @@ -859,9 +837,7 @@ ahd_list_unlock(unsigned long *flags) #define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ #define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic79xx_pci_driver; -#endif typedef enum { @@ -965,25 +941,6 @@ ahd_flush_device_writes(struct ahd_softc *ahd) ahd_inb(ahd, INTSTAT); } -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahd_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahd_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahd_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1091,35 +1048,13 @@ u_long ahd_get_transfer_length(struct scb *scb) static __inline int ahd_get_transfer_dir(struct scb *scb) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif } static __inline void ahd_set_residual(struct scb *scb, u_long resid) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif } static __inline @@ -1131,11 +1066,7 @@ void ahd_set_sense_residual(struct scb *scb, u_long resid) static __inline u_long ahd_get_residual(struct scb *scb) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif } static __inline @@ -1212,4 +1143,5 @@ void ahd_platform_dump_card_state(struct ahd_softc *ahd); #endif #define bootverbose aic79xx_verbose extern uint32_t aic79xx_verbose; + #endif /* _AIC79XX_LINUX_H_ */ diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index d30823d00..91daf0c7f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -41,12 +41,7 @@ #include "aic79xx_osm.h" #include "aic79xx_inline.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -struct pci_device_id -{ -}; -#endif +#include "aic79xx_pci.h" static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -54,16 +49,34 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, u_long *base2); static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, - uint8_t **maddr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + uint8_t __iomem **maddr); static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); -/* We do our own ID filtering. So, grab all SCSI storage class devices. */ +/* Define the macro locally since it's different for different class of chips. + */ +#define ID(x) \ + ID2C(x), \ + ID2C(IDIROC(x)) + static struct pci_device_id ahd_linux_pci_id_table[] = { - { - 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, + /* aic7901 based controllers */ + ID(ID_AHA_29320A), + ID(ID_AHA_29320ALP), + /* aic7902 based controllers */ + ID(ID_AHA_29320), + ID(ID_AHA_29320B), + ID(ID_AHA_29320LP), + ID(ID_AHA_39320), + ID(ID_AHA_39320_B), + ID(ID_AHA_39320A), + ID(ID_AHA_39320D), + ID(ID_AHA_39320D_HP), + ID(ID_AHA_39320D_B), + ID(ID_AHA_39320D_B_HP), + /* Generic chip probes for devices we don't know exactly. */ + ID16(ID_AIC7901 & ID_9005_GENERIC_MASK), + ID(ID_AIC7901A & ID_DEV_VENDOR_MASK), + ID16(ID_AIC7902 & ID_9005_GENERIC_MASK), { 0 } }; @@ -92,14 +105,15 @@ ahd_linux_pci_dev_remove(struct pci_dev *pdev) if (ahd != NULL) { u_long s; + TAILQ_REMOVE(&ahd_tailq, ahd, links); + ahd_list_unlock(&l); ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); ahd_free(ahd); - } - ahd_list_unlock(&l); + } else + ahd_list_unlock(&l); } -#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ static int ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -148,42 +162,37 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (pci_enable_device(pdev)) { ahd_free(ahd); return (-ENODEV); } pci_set_master(pdev); - if (sizeof(bus_addr_t) > 4) { + if (sizeof(dma_addr_t) > 4) { uint64_t memsize; - bus_addr_t mask_64bit; - bus_addr_t mask_39bit; + const uint64_t mask_39bit = 0x7FFFFFFFFFULL; memsize = ahd_linux_get_memsize(); - mask_64bit = (bus_addr_t)0xFFFFFFFFFFFFFFFFULL; - mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; + if (memsize >= 0x8000000000ULL - && ahd_pci_set_dma_mask(pdev, mask_64bit) == 0) { + && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { ahd->flags |= AHD_64BIT_ADDRESSING; - ahd->platform_data->hw_dma_mask = mask_64bit; + ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK; } else if (memsize > 0x80000000 - && ahd_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahd->flags |= AHD_39BIT_ADDRESSING; ahd->platform_data->hw_dma_mask = mask_39bit; } } else { - ahd_pci_set_dma_mask(pdev, 0xFFFFFFFF); - ahd->platform_data->hw_dma_mask = 0xFFFFFFFF; + pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK; } -#endif ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); if (error != 0) { ahd_free(ahd); return (-error); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_drvdata(pdev, ahd); if (aic79xx_detect_complete) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) @@ -194,38 +203,13 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (-ENODEV); #endif } -#endif return (0); } int ahd_linux_pci_init(void) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) return (pci_module_init(&aic79xx_pci_driver)); -#else - struct pci_dev *pdev; - u_int class; - int found; - - /* If we don't have a PCI bus, we can't find any adapters. */ - if (pci_present() == 0) - return (0); - - found = 0; - pdev = NULL; - class = PCI_CLASS_STORAGE_SCSI << 8; - while ((pdev = pci_find_class(class, pdev)) != NULL) { - ahd_dev_softc_t pci; - int error; - - pci = pdev; - error = ahd_linux_pci_dev_probe(pdev, /*pci_devid*/NULL); - if (error == 0) - found++; - } - return (found); -#endif } void @@ -238,7 +222,6 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, u_long *base2) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) *base = pci_resource_start(ahd->dev_softc, 0); /* * This is really the 3rd bar and should be at index 2, @@ -246,35 +229,21 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, * bars. */ *base2 = pci_resource_start(ahd->dev_softc, 3); -#else - *base = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR0, 4); - *base2 = ahd_pci_read_config(ahd->dev_softc, AHD_PCI_IOADDR1, 4); - *base &= PCI_BASE_ADDRESS_IO_MASK; - *base2 &= PCI_BASE_ADDRESS_IO_MASK; -#endif if (*base == 0 || *base2 == 0) return (ENOMEM); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) - if (check_region(*base, 256) != 0 - || check_region(*base2, 256) != 0) - return (ENOMEM); - request_region(*base, 256, "aic79xx"); - request_region(*base2, 256, "aic79xx"); -#else if (request_region(*base, 256, "aic79xx") == 0) return (ENOMEM); if (request_region(*base2, 256, "aic79xx") == 0) { release_region(*base2, 256); return (ENOMEM); } -#endif return (0); } static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, - uint8_t **maddr) + uint8_t __iomem **maddr) { u_long start; u_long base_page; @@ -288,29 +257,18 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, return (ENOMEM); error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) start = pci_resource_start(ahd->dev_softc, 1); base_page = start & PAGE_MASK; base_offset = start - base_page; -#else - start = ahd_pci_read_config(ahd->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (request_mem_region(start, 0x1000, "aic79xx") == 0) error = ENOMEM; -#endif if (error == 0) { *maddr = ioremap_nocache(base_page, base_offset + 256); if (*maddr == NULL) { error = ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); -#endif } else *maddr += base_offset; } @@ -324,7 +282,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd) { uint32_t command; u_long base; - uint8_t *maddr; + uint8_t __iomem *maddr; int error; /* @@ -351,11 +309,9 @@ ahd_pci_map_registers(struct ahd_softc *ahd) ahd_get_pci_bus(ahd->dev_softc), ahd_get_pci_slot(ahd->dev_softc), ahd_get_pci_function(ahd->dev_softc)); - iounmap((void *)((u_long)maddr & PAGE_MASK)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + iounmap(maddr); release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); -#endif ahd->bshs[0].maddr = NULL; maddr = NULL; } else @@ -408,38 +364,5 @@ ahd_pci_map_int(struct ahd_softc *ahd) void ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_set_power_state(ahd->dev_softc, new_state); -#else - uint32_t cap; - u_int cap_offset; - - /* - * Traverse the capability list looking for - * the power management capability. - */ - cap = 0; - cap_offset = ahd_pci_read_config(ahd->dev_softc, - PCIR_CAP_PTR, /*bytes*/1); - while (cap_offset != 0) { - - cap = ahd_pci_read_config(ahd->dev_softc, - cap_offset, /*bytes*/4); - if ((cap & 0xFF) == 1 - && ((cap >> 16) & 0x3) > 0) { - uint32_t pm_control; - - pm_control = ahd_pci_read_config(ahd->dev_softc, - cap_offset + 4, - /*bytes*/4); - pm_control &= ~0x3; - pm_control |= new_state; - ahd_pci_write_config(ahd->dev_softc, - cap_offset + 4, - pm_control, /*bytes*/2); - break; - } - cap_offset = (cap >> 8) & 0xFF; - } -#endif } diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 913984539..4c3bb7bb8 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -51,6 +51,8 @@ #include #endif +#include "aic79xx_pci.h" + static __inline uint64_t ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { @@ -64,34 +66,12 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) return (id); } -#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_ALL_IROC_MASK 0xFFFFFF7FFFFFFFFFull -#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull -#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_GENERIC_IROC_MASK 0xFFF0FF7F00000000ull - -#define ID_AIC7901 0x800F9005FFFF9005ull -#define ID_AHA_29320A 0x8000900500609005ull -#define ID_AHA_29320ALP 0x8017900500449005ull - -#define ID_AIC7901A 0x801E9005FFFF9005ull -#define ID_AHA_29320 0x8012900500429005ull -#define ID_AHA_29320B 0x8013900500439005ull -#define ID_AHA_29320LP 0x8014900500449005ull - -#define ID_AIC7902 0x801F9005FFFF9005ull -#define ID_AIC7902_B 0x801D9005FFFF9005ull -#define ID_AHA_39320 0x8010900500409005ull -#define ID_AHA_39320_B 0x8015900500409005ull -#define ID_AHA_39320A 0x8016900500409005ull -#define ID_AHA_39320D 0x8011900500419005ull -#define ID_AHA_39320D_B 0x801C900500419005ull -#define ID_AHA_39320D_HP 0x8011900500AC0E11ull -#define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull #define ID_AIC7902_PCI_REV_A4 0x3 #define ID_AIC7902_PCI_REV_B0 0x10 #define SUBID_HP 0x0E11 +#define DEVID_9005_HOSTRAID(id) ((id) & 0x80) + #define DEVID_9005_TYPE(id) ((id) & 0xF) #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ @@ -134,18 +114,18 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec 29320ALP Ultra320 SCSI adapter", ahd_aic7901_setup }, - /* aic7901A based controllers */ + /* aic7902 based controllers */ { ID_AHA_29320, ID_ALL_MASK, "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7901A_setup + ahd_aic7902_setup }, { ID_AHA_29320B, ID_ALL_MASK, "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7901A_setup + ahd_aic7902_setup }, { ID_AHA_29320LP, @@ -153,7 +133,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec 29320LP Ultra320 SCSI adapter", ahd_aic7901A_setup }, - /* aic7902 based controllers */ { ID_AHA_39320, ID_ALL_MASK, @@ -196,22 +175,10 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", ahd_aic7902_setup }, - { - ID_AHA_29320, - ID_ALL_MASK, - "Adaptec 29320 Ultra320 SCSI adapter", - ahd_aic7902_setup - }, - { - ID_AHA_29320B, - ID_ALL_MASK, - "Adaptec 29320B Ultra320 SCSI adapter", - ahd_aic7902_setup - }, /* Generic chip probes for devices we don't know 'exactly' */ { - ID_AIC7901 & ID_DEV_VENDOR_MASK, - ID_DEV_VENDOR_MASK, + ID_AIC7901 & ID_9005_GENERIC_MASK, + ID_9005_GENERIC_MASK, "Adaptec AIC7901 Ultra320 SCSI adapter", ahd_aic7901_setup }, @@ -294,6 +261,12 @@ ahd_find_pci_device(ahd_dev_softc_t pci) subdevice, subvendor); + /* + * Controllers, mask out the IROC/HostRAID bit + */ + + full_id &= ID_ALL_IROC_MASK; + for (i = 0; i < ahd_num_pci_devs; i++) { entry = &ahd_pci_ident_table[i]; if (entry->full_id == (full_id & entry->id_mask)) { @@ -452,8 +425,10 @@ ahd_pci_test_register_access(struct ahd_softc *ahd) * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flaged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); while (ahd_is_paused(ahd) == 0) ; diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index ef1214c31..8ff16fd8e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -521,7 +521,7 @@ struct ahc_dma_seg { struct sg_map_node { bus_dmamap_t sg_dmamap; - bus_addr_t sg_physaddr; + dma_addr_t sg_physaddr; struct ahc_dma_seg* sg_vaddr; SLIST_ENTRY(sg_map_node) links; }; @@ -584,7 +584,7 @@ struct scb { struct scb_platform_data *platform_data; struct sg_map_node *sg_map; struct ahc_dma_seg *sg_list; - bus_addr_t sg_list_phys; + dma_addr_t sg_list_phys; u_int sg_count;/* How full ahc_dma_seg is */ }; @@ -611,10 +611,10 @@ struct scb_data { */ bus_dma_tag_t hscb_dmat; /* dmat for our hardware SCB array */ bus_dmamap_t hscb_dmamap; - bus_addr_t hscb_busaddr; + dma_addr_t hscb_busaddr; bus_dma_tag_t sense_dmat; bus_dmamap_t sense_dmamap; - bus_addr_t sense_busaddr; + dma_addr_t sense_busaddr; bus_dma_tag_t sg_dmat; /* dmat for our sg segments */ SLIST_HEAD(, sg_map_node) sg_maps; uint8_t numscbs; @@ -1069,14 +1069,14 @@ struct ahc_softc { bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; bus_dmamap_t shared_data_dmamap; - bus_addr_t shared_data_busaddr; + dma_addr_t shared_data_busaddr; /* * Bus address of the one byte buffer used to * work-around a DMA bug for chips <= aic7880 * in target mode. */ - bus_addr_t dma_bug_buf; + dma_addr_t dma_bug_buf; /* Number of enabled target mode device on this card */ u_int enabled_luns; diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 22944e89f..9a6b4a570 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -3973,7 +3973,6 @@ ahc_free(struct ahc_softc *ahc) default: case 5: ahc_shutdown(ahc); - TAILQ_REMOVE(&ahc_tailq, ahc, links); /* FALLTHROUGH */ case 4: ahc_dmamap_unload(ahc, ahc->shared_data_dmat, @@ -4199,9 +4198,9 @@ ahc_probe_scbs(struct ahc_softc *ahc) { static void ahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { - bus_addr_t *baddr; + dma_addr_t *baddr; - baddr = (bus_addr_t *)arg; + baddr = (dma_addr_t *)arg; *baddr = segs->ds_addr; } @@ -4456,7 +4455,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) struct scb_data *scb_data; struct scb *next_scb; struct sg_map_node *sg_map; - bus_addr_t physaddr; + dma_addr_t physaddr; struct ahc_dma_seg *segs; int newcount; int i; @@ -4820,7 +4819,7 @@ ahc_init(struct ahc_softc *ahc) if (ahc_dma_tag_create(ahc, ahc->parent_dmat, /*alignment*/1, /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1, /*lowaddr*/ahc->flags & AHC_39BIT_ADDRESSING - ? (bus_addr_t)0x7FFFFFFFFFULL + ? (dma_addr_t)0x7FFFFFFFFFULL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 3c7a4854d..89bfdcdd5 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -129,10 +129,7 @@ */ #include "aiclib.c" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include /* __setup */ -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include "sd.h" /* For geometry detection */ @@ -140,6 +137,7 @@ #include /* For fetching system memory size */ #include /* For block_size() */ +#include /* For ssleep/msleep */ /* * Lock protecting manipulation of the ahc softc list. @@ -151,14 +149,6 @@ spinlock_t ahc_list_spinlock; u_int ahc_linux_nseg; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - /* * Set this to the delay in seconds after SCSI bus reset. * Note, we honor this only for the initial bus reset. @@ -436,7 +426,6 @@ uint32_t aic7xxx_periodic_otag; /* * Module information and settable options. */ -#ifdef MODULE static char *aic7xxx = NULL; /* * Just in case someone uses commas to separate items on the insmod @@ -447,10 +436,9 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n"; MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); -#ifdef MODULE_LICENSE MODULE_LICENSE("Dual BSD/GPL"); -#endif -MODULE_PARM(aic7xxx, "s"); +MODULE_VERSION(AIC7XXX_DRIVER_VERSION); +module_param(aic7xxx, charp, 0444); MODULE_PARM_DESC(aic7xxx, "period delimited, options string.\n" " verbose Enable verbose/diagnostic logging\n" @@ -479,7 +467,6 @@ MODULE_PARM_DESC(aic7xxx, "\n" " options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n" ); -#endif static void ahc_linux_handle_scsi_status(struct ahc_softc *, struct ahc_linux_device *, @@ -574,7 +561,7 @@ static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, struct ahc_dma_seg *sg, - bus_addr_t addr, bus_size_t len); + dma_addr_t addr, bus_size_t len); static __inline void ahc_schedule_completeq(struct ahc_softc *ahc) @@ -592,14 +579,7 @@ ahc_schedule_completeq(struct ahc_softc *ahc) static __inline void ahc_schedule_runq(struct ahc_softc *ahc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_schedule(&ahc->platform_data->runq_tasklet); -#else - /* - * Tasklets are not available, so run inline. - */ - ahc_runq_tasklet((unsigned long)ahc); -#endif } static __inline struct ahc_linux_device* @@ -730,7 +710,7 @@ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, - struct ahc_dma_seg *sg, bus_addr_t addr, bus_size_t len) + struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len) { int consumed; @@ -742,7 +722,7 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, sg->addr = ahc_htole32(addr & 0xFFFFFFFF); scb->platform_data->xfer_len += len; - if (sizeof(bus_addr_t) > 4 + if (sizeof(dma_addr_t) > 4 && (ahc->flags & AHC_39BIT_ADDRESSING) != 0) len |= (addr >> 8) & AHC_SG_HIGH_ADDR_MASK; @@ -865,7 +845,6 @@ ahc_linux_detect(Scsi_Host_Template *template) return (0); } ahc_linux_size_nseg(); -#ifdef MODULE /* * If we've been passed any parameters, process them now. */ @@ -877,13 +856,8 @@ ahc_linux_detect(Scsi_Host_Template *template) "aic7xxx: to see the proper way to specify options to the aic7xxx module\n" "aic7xxx: Specifically, don't use any commas when passing arguments to\n" "aic7xxx: insmod or else it might trash certain memory areas.\n"); -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) template->proc_name = "aic7xxx"; -#else - template->proc_dir = &proc_scsi_aic7xxx; -#endif /* * Initialize our softc list lock prior to @@ -1325,28 +1299,20 @@ ahc_runq_tasklet(unsigned long data) { struct ahc_softc* ahc; struct ahc_linux_device *dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) u_long flags; -#endif ahc = (struct ahc_softc *)data; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahc_lock(ahc, &flags); -#endif while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) { TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); dev->flags &= ~AHC_DEV_ON_RUN_LIST; ahc_linux_check_device_queue(ahc, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahc_unlock(ahc, &flags); ahc_lock(ahc, &flags); -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahc_unlock(ahc, &flags); -#endif } /******************************** Macros **************************************/ @@ -1359,7 +1325,7 @@ ahc_runq_tasklet(unsigned long data) int ahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent, bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, + dma_addr_t lowaddr, dma_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag) @@ -1396,7 +1362,6 @@ ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, { bus_dmamap_t map; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT); if (map == NULL) return (ENOMEM); @@ -1408,28 +1373,20 @@ ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr, * our dma mask when doing allocations. */ if (ahc->dev_softc != NULL) - if (ahc_pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) { + if (pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); + kfree(map); return (ENODEV); } *vaddr = pci_alloc_consistent(ahc->dev_softc, dmat->maxsize, &map->bus_addr); if (ahc->dev_softc != NULL) - if (ahc_pci_set_dma_mask(ahc->dev_softc, + if (pci_set_dma_mask(ahc->dev_softc, ahc->platform_data->hw_dma_mask)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); + kfree(map); return (ENODEV); } -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ - /* - * At least in 2.2.14, malloc is a slab allocator so all - * allocations are aligned. We assume for these kernel versions - * that all allocations will be bellow 4Gig, physically contiguous, - * and accessible via DMA by the controller. - */ - map = NULL; /* No additional information to store */ - *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT); -#endif if (*vaddr == NULL) return (ENOMEM); *mapp = map; @@ -1440,12 +1397,8 @@ void ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat, void* vaddr, bus_dmamap_t map) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) pci_free_consistent(ahc->dev_softc, dmat->maxsize, vaddr, map->bus_addr); -#else - free(vaddr, M_DEVBUF); -#endif } int @@ -1459,12 +1412,7 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map, */ bus_dma_segment_t stack_sg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) stack_sg.ds_addr = map->bus_addr; -#else -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) - stack_sg.ds_addr = VIRT_TO_BUS(buf); -#endif stack_sg.ds_len = dmat->maxsize; cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); return (0); @@ -1475,9 +1423,10 @@ ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) { /* * The map may is NULL in our < 2.3.X implementation. + * Now it's 2.6.5, but just in case... */ - if (map != NULL) - free(map, M_DEVBUF); + BUG_ON(map == NULL); + free(map, M_DEVBUF); } int @@ -1693,9 +1642,7 @@ aic7xxx_setup(char *s) return 1; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) __setup("aic7xxx=", aic7xxx_setup); -#endif uint32_t aic7xxx_verbose; @@ -1738,8 +1685,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ahc_set_name(ahc, new_name); } host->unique_id = ahc->unit; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) scsi_set_pci_device(host, ahc->dev_softc); #endif ahc_linux_initialize_scsi_bus(ahc); @@ -1925,19 +1871,11 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) ahc->platform_data->completeq_timer.data = (u_long)ahc; ahc->platform_data->completeq_timer.function = (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_sem); init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem); -#else - ahc->platform_data->eh_sem = MUTEX_LOCKED; - ahc->platform_data->dv_sem = MUTEX_LOCKED; - ahc->platform_data->dv_cmd_sem = MUTEX_LOCKED; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, (unsigned long)ahc); -#endif ahc->seltime = (aic7xxx_seltime & 0x3) << 4; ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; if (aic7xxx_pci_parity == 0) @@ -1956,9 +1894,7 @@ ahc_platform_free(struct ahc_softc *ahc) if (ahc->platform_data != NULL) { del_timer_sync(&ahc->platform_data->completeq_timer); ahc_linux_kill_dv_thread(ahc); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_kill(&ahc->platform_data->runq_tasklet); -#endif if (ahc->platform_data->host != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) scsi_remove_host(ahc->platform_data->host); @@ -1994,18 +1930,11 @@ ahc_platform_free(struct ahc_softc *ahc) release_region(ahc->bsh.ioport, 256); if (ahc->tag == BUS_SPACE_MEMIO && ahc->bsh.maddr != NULL) { - u_long base_addr; - - base_addr = (u_long)ahc->bsh.maddr; - base_addr &= PAGE_MASK; - iounmap((void *)base_addr); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + iounmap(ahc->bsh.maddr); release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); -#endif } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* * In 2.4 we detach from the scsi midlayer before the PCI * layer invokes our remove callback. No per-instance @@ -2825,7 +2754,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, break; } if (status & SSQ_DELAY) - scsi_sleep(1 * HZ); + ssleep(1); break; case SS_START: @@ -2985,7 +2914,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, } if (targ->dv_state_retry <= 10) { if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0) - scsi_sleep(ahc->our_id*HZ/10); + msleep(ahc->our_id*1000/10); break; } #ifdef AHC_DEBUG @@ -3029,7 +2958,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd, targ->dv_state_retry--; } else if (targ->dv_state_retry < 60) { if ((status & SSQ_DELAY) != 0) - scsi_sleep(1 * HZ); + ssleep(1); } else { #ifdef AHC_DEBUG if (ahc_debug & AHC_SHOW_DV) { @@ -3751,7 +3680,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) * a transfer crosses a 32bit page. */ while (cur_seg < end_seg) { - bus_addr_t addr; + dma_addr_t addr; bus_size_t len; int consumed; @@ -3780,7 +3709,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) scb->hscb->datacnt = scb->sg_list->len; } else if (cmd->request_bufflen != 0) { struct ahc_dma_seg *sg; - bus_addr_t addr; + dma_addr_t addr; sg = scb->sg_list; addr = pci_map_single(ahc->dev_softc, @@ -4064,7 +3993,7 @@ ahc_send_async(struct ahc_softc *ahc, char channel, WARN_ON(lun != CAM_LUN_WILDCARD); scsi_report_device_reset(ahc->platform_data->host, channel - 'A', target); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#else Scsi_Device *scsi_dev; /* @@ -4085,12 +4014,10 @@ ahc_send_async(struct ahc_softc *ahc, char channel, break; } case AC_BUS_RESET: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) if (ahc->platform_data->host != NULL) { scsi_report_bus_reset(ahc->platform_data->host, channel - 'A'); } -#endif break; default: panic("ahc_send_async: Unexpected async event"); @@ -5100,7 +5027,6 @@ static void ahc_linux_exit(void) { struct ahc_softc *ahc; - u_long l; /* * Shutdown DV threads before going into the SCSI mid-layer. @@ -5108,12 +5034,10 @@ ahc_linux_exit(void) * kernel so that waiting for our DV threads to exit leads * to deadlock. */ - ahc_list_lock(&l); TAILQ_FOREACH(ahc, &ahc_tailq, links) { ahc_linux_kill_dv_thread(ahc); } - ahc_list_unlock(&l); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index f9c21e704..539ae081f 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -70,17 +70,9 @@ #include #include -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include /* For tasklet support. */ #include #include -#else -#include -#endif /* Core SCSI definitions */ #define AIC_LIB_PREFIX ahc @@ -156,11 +148,6 @@ extern Scsi_Host_Template aic7xxx_driver_template; /***************************** Bus Space/DMA **********************************/ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17) -typedef dma_addr_t bus_addr_t; -#else -typedef uint32_t bus_addr_t; -#endif typedef uint32_t bus_size_t; typedef enum { @@ -170,12 +157,12 @@ typedef enum { typedef union { u_long ioport; - volatile uint8_t *maddr; + volatile uint8_t __iomem *maddr; } bus_space_handle_t; typedef struct bus_dma_segment { - bus_addr_t ds_addr; + dma_addr_t ds_addr; bus_size_t ds_len; } bus_dma_segment_t; @@ -189,11 +176,11 @@ typedef struct ahc_linux_dma_tag* bus_dma_tag_t; struct ahc_linux_dmamap { - bus_addr_t bus_addr; + dma_addr_t bus_addr; }; typedef struct ahc_linux_dmamap* bus_dmamap_t; -typedef int bus_dma_filter_t(void*, bus_addr_t); +typedef int bus_dma_filter_t(void*, dma_addr_t); typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); #define BUS_DMA_WAITOK 0x0 @@ -210,7 +197,7 @@ typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); int ahc_dma_tag_create(struct ahc_softc *, bus_dma_tag_t /*parent*/, bus_size_t /*alignment*/, bus_size_t /*boundary*/, - bus_addr_t /*lowaddr*/, bus_addr_t /*highaddr*/, + dma_addr_t /*lowaddr*/, dma_addr_t /*highaddr*/, bus_dma_filter_t*/*filter*/, void */*filterarg*/, bus_size_t /*maxsize*/, int /*nsegments*/, bus_size_t /*maxsegsz*/, int /*flags*/, @@ -292,11 +279,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec) } /***************************** SMP support ************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) -#include -#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK)) #define AHC_SCSI_HAS_HOST_LOCK 1 @@ -515,11 +498,8 @@ typedef enum { struct scb_platform_data { struct ahc_linux_device *dev; - bus_addr_t buf_busaddr; + dma_addr_t buf_busaddr; uint32_t xfer_len; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - uint32_t resid; /* Transfer residual */ -#endif uint32_t sense_resid; /* Auto-Sense residual */ ahc_linux_scb_flags flags; }; @@ -549,9 +529,7 @@ struct ahc_platform_data { struct ahc_completeq completeq; spinlock_t spin_lock; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; -#endif u_int qfrozen; pid_t dv_pid; struct timer_list completeq_timer; @@ -567,7 +545,7 @@ struct ahc_platform_data { uint32_t irq; /* IRQ for this adapter */ uint32_t bios_address; uint32_t mem_busaddr; /* Mem Base Addr */ - bus_addr_t hw_dma_mask; + uint64_t hw_dma_mask; ahc_linux_softc_flags flags; }; @@ -819,9 +797,7 @@ ahc_list_unlock(unsigned long *flags) #define PCIR_SUBVEND_0 0x2c #define PCIR_SUBDEV_0 0x2e -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) extern struct pci_driver aic7xxx_pci_driver; -#endif typedef enum { @@ -954,25 +930,6 @@ ahc_flush_device_writes(struct ahc_softc *ahc) ahc_inb(ahc, INTSTAT); } -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0) -#define pci_map_sg(pdev, sg_list, nseg, direction) (nseg) -#define pci_unmap_sg(pdev, sg_list, nseg, direction) -#define sg_dma_address(sg) (VIRT_TO_BUS((sg)->address)) -#define sg_dma_len(sg) ((sg)->length) -#define pci_map_single(pdev, buffer, bufflen, direction) \ - (VIRT_TO_BUS(buffer)) -#define pci_unmap_single(pdev, buffer, buflen, direction) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) -#define ahc_pci_set_dma_mask pci_set_dma_mask -#else -/* - * Always "return" 0 for success. - */ -#define ahc_pci_set_dma_mask(dev_softc, mask) \ - (((dev_softc)->dma_mask = mask) && 0) -#endif /**************************** Proc FS Support *********************************/ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) int ahc_linux_proc_info(char *, char **, off_t, int, int, int); @@ -1080,35 +1037,13 @@ u_long ahc_get_transfer_length(struct scb *scb) static __inline int ahc_get_transfer_dir(struct scb *scb) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,40) return (scb->io_ctx->sc_data_direction); -#else - if (scb->io_ctx->bufflen == 0) - return (CAM_DIR_NONE); - - switch(scb->io_ctx->cmnd[0]) { - case 0x08: /* READ(6) */ - case 0x28: /* READ(10) */ - case 0xA8: /* READ(12) */ - return (CAM_DIR_IN); - case 0x0A: /* WRITE(6) */ - case 0x2A: /* WRITE(10) */ - case 0xAA: /* WRITE(12) */ - return (CAM_DIR_OUT); - default: - return (CAM_DIR_NONE); - } -#endif } static __inline void ahc_set_residual(struct scb *scb, u_long resid) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) scb->io_ctx->resid = resid; -#else - scb->platform_data->resid = resid; -#endif } static __inline @@ -1120,11 +1055,7 @@ void ahc_set_sense_residual(struct scb *scb, u_long resid) static __inline u_long ahc_get_residual(struct scb *scb) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) return (scb->io_ctx->resid); -#else - return (scb->platform_data->resid); -#endif } static __inline diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 2a6fc40a8..49d799ac6 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -40,6 +40,7 @@ */ #include "aic7xxx_osm.h" +#include "aic7xxx_pci.h" #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) struct pci_device_id @@ -53,20 +54,84 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base); static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, - uint8_t **maddr); + uint8_t __iomem **maddr); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); -/* We do our own ID filtering. So, grab all SCSI storage class devices. */ +/* Define the macro locally since it's different for different class of chips. +*/ +#define ID(x) ID_C(x, PCI_CLASS_STORAGE_SCSI) + static struct pci_device_id ahc_linux_pci_id_table[] = { - { - 0x9004, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, - { - 0x9005, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_SCSI << 8, 0xFFFF00, 0 - }, + /* aic7850 based controllers */ + ID(ID_AHA_2902_04_10_15_20C_30C), + /* aic7860 based controllers */ + ID(ID_AHA_2930CU), + ID(ID_AHA_1480A & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK), + /* aic7870 based controllers */ + ID(ID_AHA_2940), + ID(ID_AHA_3940), + ID(ID_AHA_398X), + ID(ID_AHA_2944), + ID(ID_AHA_3944), + ID(ID_AHA_4944), + /* aic7880 based controllers */ + ID(ID_AHA_2940U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_3940U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2944U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_3944U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_398XU & ID_DEV_VENDOR_MASK), + ID(ID_AHA_4944U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2930U & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK), + ID(ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK), + /* aic7890 based controllers */ + ID(ID_AHA_2930U2), + ID(ID_AHA_2940U2B), + ID(ID_AHA_2940U2_OEM), + ID(ID_AHA_2940U2), + ID(ID_AHA_2950U2B), + ID16(ID_AIC7890_ARO & ID_AIC7895_ARO_MASK), + ID(ID_AAA_131U2), + /* aic7890 based controllers */ + ID(ID_AHA_29160), + ID(ID_AHA_29160_CPQ), + ID(ID_AHA_29160N), + ID(ID_AHA_29160C), + ID(ID_AHA_29160B), + ID(ID_AHA_19160B), + ID(ID_AIC7892_ARO), + /* aic7892 based controllers */ + ID(ID_AHA_2940U_DUAL), + ID(ID_AHA_3940AU), + ID(ID_AHA_3944AU), + ID(ID_AIC7895_ARO), + ID(ID_AHA_3950U2B_0), + ID(ID_AHA_3950U2B_1), + ID(ID_AHA_3950U2D_0), + ID(ID_AHA_3950U2D_1), + ID(ID_AIC7896_ARO), + /* aic7899 based controllers */ + ID(ID_AHA_3960D), + ID(ID_AHA_3960D_CPQ), + ID(ID_AIC7899_ARO), + /* Generic chip probes for devices we don't know exactly. */ + ID(ID_AIC7850 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7855 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7859 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7860 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7870 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7880 & ID_DEV_VENDOR_MASK), + ID16(ID_AIC7890 & ID_9005_GENERIC_MASK), + ID16(ID_AIC7892 & ID_9005_GENERIC_MASK), + ID(ID_AIC7895 & ID_DEV_VENDOR_MASK), + ID16(ID_AIC7896 & ID_9005_GENERIC_MASK), + ID16(ID_AIC7899 & ID_9005_GENERIC_MASK), + ID(ID_AIC7810 & ID_DEV_VENDOR_MASK), + ID(ID_AIC7815 & ID_DEV_VENDOR_MASK), { 0 } }; @@ -95,12 +160,14 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev) if (ahc != NULL) { u_long s; + TAILQ_REMOVE(&ahc_tailq, ahc, links); + ahc_list_unlock(&l); ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); ahc_free(ahc); - } - ahc_list_unlock(&l); + } else + ahc_list_unlock(&l); } #endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */ @@ -108,7 +175,7 @@ static int ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { char buf[80]; - bus_addr_t mask_39bit; + const uint64_t mask_39bit = 0x7FFFFFFFFFULL; struct ahc_softc *ahc; ahc_dev_softc_t pci; struct ahc_pci_identity *entry; @@ -159,18 +226,17 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } pci_set_master(pdev); - mask_39bit = (bus_addr_t)0x7FFFFFFFFFULL; - if (sizeof(bus_addr_t) > 4 + if (sizeof(dma_addr_t) > 4 && ahc_linux_get_memsize() > 0x80000000 - && ahc_pci_set_dma_mask(pdev, mask_39bit) == 0) { + && pci_set_dma_mask(pdev, mask_39bit) == 0) { ahc->flags |= AHC_39BIT_ADDRESSING; ahc->platform_data->hw_dma_mask = mask_39bit; } else { - if (ahc_pci_set_dma_mask(pdev, 0xFFFFFFFF)) { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); return (-ENODEV); } - ahc->platform_data->hw_dma_mask = 0xFFFFFFFF; + ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK; } #endif ahc->dev_softc = pci; @@ -259,24 +325,13 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base) static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, - uint8_t **maddr) + uint8_t __iomem **maddr) { u_long start; - u_long base_page; - u_long base_offset; int error; error = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) start = pci_resource_start(ahc->dev_softc, 1); - base_page = start & PAGE_MASK; - base_offset = start - base_page; -#else - start = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS+4, 4); - base_offset = start & PCI_BASE_ADDRESS_MEM_MASK; - base_page = base_offset & PAGE_MASK; - base_offset -= base_page; -#endif if (start != 0) { *bus_addr = start; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) @@ -284,14 +339,13 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, error = ENOMEM; #endif if (error == 0) { - *maddr = ioremap_nocache(base_page, base_offset + 256); + *maddr = ioremap_nocache(start, 256); if (*maddr == NULL) { error = ENOMEM; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(start, 0x1000); #endif - } else - *maddr += base_offset; + } } } else error = ENOMEM; @@ -303,7 +357,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) { uint32_t command; u_long base; - uint8_t *maddr; + uint8_t __iomem *maddr; int error; /* @@ -332,7 +386,7 @@ ahc_pci_map_registers(struct ahc_softc *ahc) ahc_get_pci_bus(ahc->dev_softc), ahc_get_pci_slot(ahc->dev_softc), ahc_get_pci_function(ahc->dev_softc)); - iounmap((void *)((u_long)maddr & PAGE_MASK)); + iounmap(maddr); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) release_mem_region(ahc->platform_data->mem_busaddr, 0x1000); diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 01cfab0e3..e3b50fcf6 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -54,8 +54,7 @@ #include #endif -#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ -#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ +#include "aic7xxx_pci.h" static __inline uint64_t ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) @@ -70,84 +69,8 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) return (id); } -#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull -#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull -#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull -#define ID_9005_SISL_MASK 0x000FFFFF00000000ull -#define ID_9005_SISL_ID 0x0005900500000000ull -#define ID_AIC7850 0x5078900400000000ull -#define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull -#define ID_AIC7855 0x5578900400000000ull -#define ID_AIC7859 0x3860900400000000ull -#define ID_AHA_2930CU 0x3860900438699004ull -#define ID_AIC7860 0x6078900400000000ull -#define ID_AIC7860C 0x6078900478609004ull -#define ID_AHA_1480A 0x6075900400000000ull -#define ID_AHA_2940AU_0 0x6178900400000000ull -#define ID_AHA_2940AU_1 0x6178900478619004ull -#define ID_AHA_2940AU_CN 0x2178900478219004ull -#define ID_AHA_2930C_VAR 0x6038900438689004ull - -#define ID_AIC7870 0x7078900400000000ull -#define ID_AHA_2940 0x7178900400000000ull -#define ID_AHA_3940 0x7278900400000000ull -#define ID_AHA_398X 0x7378900400000000ull -#define ID_AHA_2944 0x7478900400000000ull -#define ID_AHA_3944 0x7578900400000000ull -#define ID_AHA_4944 0x7678900400000000ull - -#define ID_AIC7880 0x8078900400000000ull -#define ID_AIC7880_B 0x8078900478809004ull -#define ID_AHA_2940U 0x8178900400000000ull -#define ID_AHA_3940U 0x8278900400000000ull -#define ID_AHA_2944U 0x8478900400000000ull -#define ID_AHA_3944U 0x8578900400000000ull -#define ID_AHA_398XU 0x8378900400000000ull -#define ID_AHA_4944U 0x8678900400000000ull -#define ID_AHA_2940UB 0x8178900478819004ull -#define ID_AHA_2930U 0x8878900478889004ull -#define ID_AHA_2940U_PRO 0x8778900478879004ull -#define ID_AHA_2940U_CN 0x0078900478009004ull - -#define ID_AIC7895 0x7895900478959004ull -#define ID_AIC7895_ARO 0x7890900478939004ull -#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull -#define ID_AHA_2940U_DUAL 0x7895900478919004ull -#define ID_AHA_3940AU 0x7895900478929004ull -#define ID_AHA_3944AU 0x7895900478949004ull - -#define ID_AIC7890 0x001F9005000F9005ull -#define ID_AIC7890_ARO 0x00139005000F9005ull -#define ID_AAA_131U2 0x0013900500039005ull -#define ID_AHA_2930U2 0x0011900501819005ull -#define ID_AHA_2940U2B 0x00109005A1009005ull -#define ID_AHA_2940U2_OEM 0x0010900521809005ull -#define ID_AHA_2940U2 0x00109005A1809005ull -#define ID_AHA_2950U2B 0x00109005E1009005ull - -#define ID_AIC7892 0x008F9005FFFF9005ull -#define ID_AIC7892_ARO 0x00839005FFFF9005ull -#define ID_AHA_29160 0x00809005E2A09005ull -#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull -#define ID_AHA_29160N 0x0080900562A09005ull -#define ID_AHA_29160C 0x0080900562209005ull -#define ID_AHA_29160B 0x00809005E2209005ull -#define ID_AHA_19160B 0x0081900562A19005ull - -#define ID_AIC7896 0x005F9005FFFF9005ull -#define ID_AIC7896_ARO 0x00539005FFFF9005ull -#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull -#define ID_AHA_3950U2B_1 0x00509005F5009005ull -#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull -#define ID_AHA_3950U2D_1 0x00519005B5009005ull - -#define ID_AIC7899 0x00CF9005FFFF9005ull -#define ID_AIC7899_ARO 0x00C39005FFFF9005ull -#define ID_AHA_3960D 0x00C09005F6209005ull -#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull - -#define ID_AIC7810 0x1078900400000000ull -#define ID_AIC7815 0x7815900400000000ull +#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ +#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ #define DEVID_9005_TYPE(id) ((id) & 0xF) #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ @@ -1284,8 +1207,10 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flagged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); while (ahc_is_paused(ahc) == 0) ; diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile index e8c345b8e..8c91fda64 100644 --- a/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/drivers/scsi/aic7xxx/aicasm/Makefile @@ -34,10 +34,14 @@ $(PROG): ${GENHDRS} $(SRCS) $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS) aicdb.h: - @if [ -e "/usr/include/db3/db_185.h" ]; then \ + @if [ -e "/usr/include/db4/db_185.h" ]; then \ + echo "#include " > aicdb.h; \ + elif [ -e "/usr/include/db3/db_185.h" ]; then \ echo "#include " > aicdb.h; \ elif [ -e "/usr/include/db2/db_185.h" ]; then \ echo "#include " > aicdb.h; \ + elif [ -e "/usr/include/db1/db_185.h" ]; then \ + echo "#include " > aicdb.h; \ elif [ -e "/usr/include/db/db_185.h" ]; then \ echo "#include " > aicdb.h; \ elif [ -e "/usr/include/db_185.h" ]; then \ diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h index a0243ee22..bfe6f954d 100644 --- a/drivers/scsi/aic7xxx/aiclib.h +++ b/drivers/scsi/aic7xxx/aiclib.h @@ -1043,4 +1043,43 @@ scsi_4btoul(uint8_t *bytes) return (rv); } +/* Macros for generating the elements of the PCI ID tables. */ + +#define GETID(v, s) (unsigned)(((v) >> (s)) & 0xFFFF ?: PCI_ANY_ID) + +#define ID_C(x, c) \ +{ \ + GETID(x,32), GETID(x,48), GETID(x,0), GETID(x,16), \ + (c) << 8, 0xFFFF00, 0 \ +} + +#define ID2C(x) \ + ID_C(x, PCI_CLASS_STORAGE_SCSI), \ + ID_C(x, PCI_CLASS_STORAGE_RAID) + +#define IDIROC(x) ((x) | ~ID_ALL_IROC_MASK) + +/* Generate IDs for all 16 possibilites. + * The argument has already masked out + * the 4 least significant bits of the device id. + * (e.g., mask: ID_9005_GENERIC_MASK). + */ +#define ID16(x) \ + ID(x), \ + ID((x) | 0x0001000000000000ull), \ + ID((x) | 0x0002000000000000ull), \ + ID((x) | 0x0003000000000000ull), \ + ID((x) | 0x0004000000000000ull), \ + ID((x) | 0x0005000000000000ull), \ + ID((x) | 0x0006000000000000ull), \ + ID((x) | 0x0007000000000000ull), \ + ID((x) | 0x0008000000000000ull), \ + ID((x) | 0x0009000000000000ull), \ + ID((x) | 0x000A000000000000ull), \ + ID((x) | 0x000B000000000000ull), \ + ID((x) | 0x000C000000000000ull), \ + ID((x) | 0x000D000000000000ull), \ + ID((x) | 0x000E000000000000ull), \ + ID((x) | 0x000F000000000000ull) + #endif /*_AICLIB_H */ diff --git a/drivers/scsi/aic7xxx/cam.h b/drivers/scsi/aic7xxx/cam.h index b9ba333a1..d40ba0760 100644 --- a/drivers/scsi/aic7xxx/cam.h +++ b/drivers/scsi/aic7xxx/cam.h @@ -85,12 +85,6 @@ typedef enum { CAM_STATUS_MASK = 0x3F } cam_status; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#define SCSI_DATA_READ 1 -#define SCSI_DATA_WRITE 2 -#define SCSI_DATA_NONE 3 -#endif - /* * Definitions for the asynchronous callback CCB fields. */ diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 3d6149675..ba414d73d 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -924,7 +924,7 @@ struct aic7xxx_host { volatile long flags; ahc_feature features; /* chip features */ unsigned long base; /* card base address */ - volatile unsigned char *maddr; /* memory mapped address */ + volatile unsigned char __iomem *maddr; /* memory mapped address */ unsigned long isr_count; /* Interrupt count */ unsigned long spurious_int; scb_data_type *scb_data; @@ -1233,7 +1233,7 @@ static int aic7xxx_seltime = 0x10; */ #ifdef MODULE static char * aic7xxx = NULL; -MODULE_PARM(aic7xxx, "s"); +module_param(aic7xxx, charp, 0); #endif #define VERBOSE_NORMAL 0x0000 @@ -7967,8 +7967,8 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p, printk(KERN_INFO "(scsi%d) BIOS %sabled, IO Port 0x%lx, IRQ %d\n", p->host_no, (p->flags & AHC_BIOS_ENABLED) ? "en" : "dis", p->base, p->irq); - printk(KERN_INFO "(scsi%d) IO Memory at 0x%lx, MMAP Memory at 0x%lx\n", - p->host_no, p->mbase, (unsigned long)p->maddr); + printk(KERN_INFO "(scsi%d) IO Memory at 0x%lx, MMAP Memory at %p\n", + p->host_no, p->mbase, p->maddr); } #ifdef CONFIG_PCI @@ -9243,6 +9243,7 @@ aic7xxx_detect(Scsi_Host_Template *template) { /* duplicate PCI entry, skip it */ kfree(temp_p); + temp_p = NULL; continue; } current_p = current_p->next; @@ -9310,14 +9311,9 @@ aic7xxx_detect(Scsi_Host_Template *template) ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) && (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) ) { - unsigned long page_offset, base; - - base = temp_p->mbase & PAGE_MASK; - page_offset = temp_p->mbase - base; - temp_p->maddr = ioremap_nocache(base, page_offset + 256); + temp_p->maddr = ioremap_nocache(temp_p->mbase, 256); if(temp_p->maddr) { - temp_p->maddr += page_offset; /* * We need to check the I/O with the MMAPed address. Some machines * simply fail to work with MMAPed I/O and certain controllers. @@ -9334,7 +9330,7 @@ aic7xxx_detect(Scsi_Host_Template *template) PCI_FUNC(temp_p->pci_device_fn)); printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to " "Programmed I/O.\n"); - iounmap((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK)); + iounmap(temp_p->maddr); temp_p->maddr = NULL; if(temp_p->base == 0) { @@ -10489,7 +10485,7 @@ aic7xxx_bus_device_reset(Scsi_Cmnd *cmd) aic_outb(p, lastphase | ATNO, SCSISIGO); unpause_sequencer(p, FALSE); spin_unlock_irq(p->host->host_lock); - scsi_sleep(HZ); + ssleep(1); spin_lock_irq(p->host->host_lock); if(aic_dev->flags & BUS_DEVICE_RESET_PENDING) return FAILED; @@ -10548,7 +10544,7 @@ aic7xxx_bus_device_reset(Scsi_Cmnd *cmd) aic_outb(p, saved_scbptr, SCBPTR); unpause_sequencer(p, FALSE); spin_unlock_irq(p->host->host_lock); - scsi_sleep(HZ/4); + msleep(1000/4); spin_lock_irq(p->host->host_lock); if(aic_dev->flags & BUS_DEVICE_RESET_PENDING) return FAILED; @@ -10786,7 +10782,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd) } unpause_sequencer(p, FALSE); spin_unlock_irq(p->host->host_lock); - scsi_sleep(HZ/4); + msleep(1000/4); spin_lock_irq(p->host->host_lock); if (p->flags & AHC_ABORT_PENDING) { @@ -10887,7 +10883,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd) aic7xxx_run_done_queue(p, TRUE); unpause_sequencer(p, FALSE); spin_unlock_irq(p->host->host_lock); - scsi_sleep(2 * HZ); + ssleep(2); spin_lock_irq(p->host->host_lock); return SUCCESS; } @@ -10964,7 +10960,7 @@ aic7xxx_release(struct Scsi_Host *host) #ifdef MMAPIO if(p->maddr) { - iounmap((void *) (((unsigned long) p->maddr) & PAGE_MASK)); + iounmap(p->maddr); } #endif /* MMAPIO */ if(!p->pdev) @@ -11139,6 +11135,7 @@ aic7xxx_print_scratch_ram(struct aic7xxx_host *p) #include "aic7xxx_old/aic7xxx_proc.c" MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(AIC7XXX_H_VERSION); static Scsi_Host_Template driver_template = { diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index e5e86962f..24dd0b890 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -142,8 +142,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c index cd5a63ca7..8397c6321 100644 --- a/drivers/scsi/arm/arxescsi.c +++ b/drivers/scsi/arm/arxescsi.c @@ -286,14 +286,12 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id) unsigned char *base; int ret; - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - if (!request_mem_region(resbase, reslen, "arxescsi")) { - ret = -EBUSY; + ret = ecard_request_resources(ec); + if (ret) goto out; - } + resbase = ecard_resource_start(ec, ECARD_RES_MEMC); + reslen = ecard_resource_len(ec, ECARD_RES_MEMC); base = ioremap(resbase, reslen); if (!base) { ret = -ENOMEM; @@ -345,7 +343,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id) out_unmap: iounmap(base); out_region: - release_mem_region(resbase, reslen); + ecard_release_resources(ec); out: return ret; } @@ -353,20 +351,15 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id) static void __devexit arxescsi_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); - unsigned long resbase, reslen; ecard_set_drvdata(ec, NULL); fas216_remove(host); iounmap((void *)host->base); - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - release_mem_region(resbase, reslen); - fas216_release(host); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id arxescsi_cids[] = { diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 6dad72222..27271bfc0 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -321,6 +321,7 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec) scsi_remove_host(host); free_irq(host->irq, host); + NCR5380_exit(host); release_region(host->io_port, host->n_io_port); scsi_host_put(host); } diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index 92bfdd9d8..e54885fd8 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -408,14 +408,12 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id) unsigned char *base; int ret; - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - if (!request_mem_region(resbase, reslen, "cumanascsi2")) { - ret = -EBUSY; + ret = ecard_request_resources(ec); + if (ret) goto out; - } + resbase = ecard_resource_start(ec, ECARD_RES_MEMC); + reslen = ecard_resource_len(ec, ECARD_RES_MEMC); base = ioremap(resbase, reslen); if (!base) { ret = -ENOMEM; @@ -504,7 +502,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id) iounmap(base); out_region: - release_mem_region(resbase, reslen); + ecard_release_resources(ec); out: return ret; @@ -514,7 +512,6 @@ static void __devexit cumanascsi2_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - unsigned long resbase, reslen; ecard_set_drvdata(ec, NULL); fas216_remove(host); @@ -525,13 +522,9 @@ static void __devexit cumanascsi2_remove(struct expansion_card *ec) iounmap((void *)host->base); - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - release_mem_region(resbase, reslen); - fas216_release(host); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id cumanascsi2_cids[] = { diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c index 57e79614f..303648a84 100644 --- a/drivers/scsi/arm/ecoscsi.c +++ b/drivers/scsi/arm/ecoscsi.c @@ -222,6 +222,7 @@ static void __exit ecoscsi_exit(void) if (shpnt->irq != IRQ_NONE) free_irq(shpnt->irq, NULL); + NCR5380_exit(host); if (shpnt->io_port) release_region(shpnt->io_port, shpnt->n_io_port); diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index 530b59c01..70ba49f29 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -231,7 +231,8 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base) * Align buffer. */ if (((u32)buf) & 2 && status >= 2) { - *((u16 *)buf)++ = readl(reg_dmadata); + *(u16 *)buf = readl(reg_dmadata); + buf += 2; status -= 2; length -= 2; } @@ -243,8 +244,10 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base) l1 |= readl(reg_dmadata) << 16; l2 = readl(reg_dmadata) & mask; l2 |= readl(reg_dmadata) << 16; - *((u32 *)buf)++ = l1; - *((u32 *)buf)++ = l2; + *(u32 *)buf = l1; + buf += 4; + *(u32 *)buf = l2; + buf += 4; length -= 8; continue; } @@ -255,13 +258,15 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base) l1 = readl(reg_dmadata) & mask; l1 |= readl(reg_dmadata) << 16; - *((u32 *)buf)++ = l1; + *(u32 *)buf = l1; + buf += 4; length -= 4; continue; } if (status >= 2) { - *((u16 *)buf)++ = readl(reg_dmadata); + *(u16 *)buf = readl(reg_dmadata); + buf += 2; length -= 2; } } while (length); @@ -305,7 +310,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base) * Align buffer. */ if (((u32)buf) & 2 && status >= 2) { - writel(*((u16 *)buf)++ << 16, reg_dmadata); + writel(*(u16 *)buf << 16, reg_dmadata); + buf += 2; status -= 2; length -= 2; } @@ -313,8 +319,10 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base) if (status >= 8) { unsigned long l1, l2; - l1 = *((u32 *)buf)++; - l2 = *((u32 *)buf)++; + l1 = *(u32 *)buf; + buf += 4; + l2 = *(u32 *)buf; + buf += 4; writel(l1 << 16, reg_dmadata); writel(l1, reg_dmadata); @@ -327,7 +335,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base) if (status >= 4) { unsigned long l1; - l1 = *((u32 *)buf)++; + l1 = *(u32 *)buf; + buf += 4; writel(l1 << 16, reg_dmadata); writel(l1, reg_dmadata); @@ -336,7 +345,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base) } if (status >= 2) { - writel(*((u16 *)buf)++ << 16, reg_dmadata); + writel(*(u16 *)buf << 16, reg_dmadata); + buf += 2; length -= 2; } } while (length); @@ -515,14 +525,12 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) unsigned char *base; int ret; - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - if (!request_mem_region(resbase, reslen, "eesoxscsi")) { - ret = -EBUSY; + ret = ecard_request_resources(ec); + if (ret) goto out; - } + resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); + reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); base = ioremap(resbase, reslen); if (!base) { ret = -ENOMEM; @@ -612,7 +620,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) iounmap(base); out_region: - release_mem_region(resbase, reslen); + ecard_release_resources(ec); out: return ret; @@ -622,7 +630,6 @@ static void __devexit eesoxscsi_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - unsigned long resbase, reslen; ecard_set_drvdata(ec, NULL); fas216_remove(host); @@ -635,13 +642,9 @@ static void __devexit eesoxscsi_remove(struct expansion_card *ec) iounmap((void *)host->base); - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - release_mem_region(resbase, reslen); - fas216_release(host); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id eesoxscsi_cids[] = { diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index f54b47025..b10257eef 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -96,7 +96,7 @@ static int level_mask = LOG_ERROR; -MODULE_PARM(level_mask, "i"); +module_param(level_mask, int, 0644); static int __init fas216_log_setup(char *str) { @@ -2681,7 +2681,7 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) * IRQs after the sleep. */ spin_unlock_irq(info->host->host_lock); - scsi_sleep(50 * HZ/100); + msleep(50 * 1000/100); spin_lock_irq(info->host->host_lock); /* @@ -2920,7 +2920,7 @@ int fas216_add(struct Scsi_Host *host, struct device *dev) * scsi standard says wait 250ms */ spin_unlock_irq(info->host->host_lock); - scsi_sleep(100*HZ/100); + msleep(100*1000/100); spin_lock_irq(info->host->host_lock); fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index ecfee930c..ff2554f4c 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -179,6 +179,7 @@ static void __devexit oakscsi_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); scsi_remove_host(host); + NCR5380_exit(host); release_region(host->io_port, host->n_io_port); scsi_host_put(host); } diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index d53b0c281..87c5cc108 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -318,14 +318,12 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id) unsigned char *base; int ret; - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - if (!request_mem_region(resbase, reslen, "powertecscsi")) { - ret = -EBUSY; + ret = ecard_request_resources(ec); + if (ret) goto out; - } + resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); + reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); base = ioremap(resbase, reslen); if (!base) { ret = -ENOMEM; @@ -413,7 +411,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id) iounmap(base); out_region: - release_mem_region(resbase, reslen); + ecard_release_resources(ec); out: return ret; @@ -423,7 +421,6 @@ static void __devexit powertecscsi_remove(struct expansion_card *ec) { struct Scsi_Host *host = ecard_get_drvdata(ec); struct powertecscsi_info *info = (struct powertecscsi_info *)host->hostdata; - unsigned long resbase, reslen; ecard_set_drvdata(ec, NULL); fas216_remove(host); @@ -436,13 +433,9 @@ static void __devexit powertecscsi_remove(struct expansion_card *ec) iounmap((void *)host->base); - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - release_mem_region(resbase, reslen); - fas216_release(host); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id powertecscsi_cids[] = { diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index c030c0a68..e0501a699 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -32,13 +32,14 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "1.02" +#define DRV_VERSION "1.03" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ ICH5_PMR = 0x90, /* port mapping register */ ICH5_PCS = 0x92, /* port control and status */ + PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ @@ -58,6 +59,7 @@ enum { ich5_sata = 1, piix4_pata = 2, ich6_sata = 3, + ich6_sata_rm = 4, }; static int piix_init_one (struct pci_dev *pdev, @@ -65,10 +67,8 @@ static int piix_init_one (struct pci_dev *pdev, static void piix_pata_phy_reset(struct ata_port *ap); static void piix_sata_phy_reset(struct ata_port *ap); -static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio); -static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma); +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); +static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); static unsigned int in_module_init = 1; @@ -87,13 +87,9 @@ static struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, - - /* ICH6 operates in two modes, "looks-like-ICH5" mode, - * and enhanced mode, with queueing and other fancy stuff. - * This is distinguished by PCI class code. - */ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, - { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm }, + { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm }, { } /* terminate list */ }; @@ -108,6 +104,7 @@ static struct pci_driver piix_pci_driver = { static Scsi_Host_Template piix_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -126,17 +123,18 @@ static Scsi_Host_Template piix_sht = { static struct ata_port_operations piix_pata_ops = { .port_disable = ata_port_disable, .set_piomode = piix_set_piomode, - .set_udmamode = piix_set_udmamode, + .set_dmamode = piix_set_dmamode, - .tf_load = ata_tf_load_pio, - .tf_read = ata_tf_read_pio, - .check_status = ata_check_status_pio, - .exec_command = ata_exec_command_pio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = piix_pata_phy_reset, - .bmdma_setup = ata_bmdma_setup_pio, - .bmdma_start = ata_bmdma_start_pio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -151,18 +149,17 @@ static struct ata_port_operations piix_pata_ops = { static struct ata_port_operations piix_sata_ops = { .port_disable = ata_port_disable, - .set_piomode = piix_set_piomode, - .set_udmamode = piix_set_udmamode, - .tf_load = ata_tf_load_pio, - .tf_read = ata_tf_read_pio, - .check_status = ata_check_status_pio, - .exec_command = ata_exec_command_pio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = piix_sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_pio, - .bmdma_start = ata_bmdma_start_pio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -181,8 +178,13 @@ static struct ata_port_info piix_port_info[] = { .sht = &piix_sht, .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &piix_pata_ops, }, @@ -191,8 +193,9 @@ static struct ata_port_info piix_port_info[] = { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -200,8 +203,13 @@ static struct ata_port_info piix_port_info[] = { { .sht = &piix_sht, .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = ATA_UDMA_MASK_40C, .port_ops = &piix_pata_ops, }, @@ -211,8 +219,21 @@ static struct ata_port_info piix_port_info[] = { .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x03, /* pio3-4 */ - .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + }, + + /* ich6_sata_rm */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR | + ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, }; @@ -226,12 +247,13 @@ MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik"); MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, piix_pci_tbl); +MODULE_VERSION(DRV_VERSION); /** * piix_pata_cbl_detect - Probe host controller cable detect info * @ap: Port for which cable detect info is desired * - * Read 80c cable indicator from SATA PCI device's PCI config + * Read 80c cable indicator from ATA PCI device's PCI config * register. This register is normally set by firmware (BIOS). * * LOCKING: @@ -239,7 +261,7 @@ MODULE_DEVICE_TABLE(pci, piix_pci_tbl); */ static void piix_pata_cbl_detect(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); u8 tmp, mask; /* no 80c support in host controller? */ @@ -247,7 +269,7 @@ static void piix_pata_cbl_detect(struct ata_port *ap) goto cbl40; /* check BIOS cable detect results */ - mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; + mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); if ((tmp & mask) == 0) goto cbl40; @@ -272,8 +294,9 @@ cbl40: static void piix_pata_phy_reset(struct ata_port *ap) { - if (!pci_test_config_bits(ap->host_set->pdev, - &piix_enable_bits[ap->port_no])) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); + + if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { ata_port_disable(ap); printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); return; @@ -301,13 +324,13 @@ static void piix_pata_phy_reset(struct ata_port *ap) */ static int piix_sata_probe (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); int orig_mask, mask, i; u8 pcs; - mask = (PIIX_PORT_PRESENT << ap->port_no) | - (PIIX_PORT_ENABLED << ap->port_no); + mask = (PIIX_PORT_PRESENT << ap->hard_port_no) | + (PIIX_PORT_ENABLED << ap->hard_port_no); pci_read_config_byte(pdev, ICH5_PCS, &pcs); orig_mask = (int) pcs & 0xff; @@ -324,7 +347,7 @@ static int piix_sata_probe (struct ata_port *ap) mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i); if ((orig_mask & mask) == mask) - if (combined || (i == ap->port_no)) + if (combined || (i == ap->hard_port_no)) return 1; } @@ -368,12 +391,12 @@ static void piix_sata_phy_reset(struct ata_port *ap) * None (inherited from caller). */ -static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio) +static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) { - struct pci_dev *dev = ap->host_set->pdev; - unsigned int is_slave = (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1; - unsigned int master_port= ap->port_no ? 0x42 : 0x40; + unsigned int pio = adev->pio_mode - XFER_PIO_0; + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); + unsigned int is_slave = (adev->devno != 0); + unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; u16 master_data; u8 slave_data; @@ -391,10 +414,10 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, /* enable PPE, IE and TIME */ master_data |= 0x0070; pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= (ap->port_no ? 0x0f : 0xf0); + slave_data &= (ap->hard_port_no ? 0x0f : 0xf0); slave_data |= (timings[pio][0] << 2) | - (timings[pio][1] << (ap->port_no ? 4 : 0)); + (timings[pio][1] << (ap->hard_port_no ? 4 : 0)); } else { master_data &= 0xccf8; /* enable PPE, IE and TIME */ @@ -409,7 +432,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, } /** - * piix_set_udmamode - Initialize host controller PATA PIO timings + * piix_set_dmamode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring * @adev: um * @udma: udma mode, 0 - 6 @@ -420,13 +443,13 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev, * None (inherited from caller). */ -static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma) +static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) { - struct pci_dev *dev = ap->host_set->pdev; - u8 maslave = ap->port_no ? 0x42 : 0x40; + unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); + u8 maslave = ap->hard_port_no ? 0x42 : 0x40; u8 speed = udma; - unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno; int a_speed = 3 << (drive_dn * 4); int u_flag = 1 << drive_dn; int v_flag = 0x01 << drive_dn; @@ -452,25 +475,38 @@ static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev, case XFER_UDMA_3: case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break; case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: break; default: BUG(); return; } - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed == XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + if (speed >= XFER_UDMA_0) { + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } - if ((reg4a & a_speed) != u_speed) - pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) - pci_write_config_byte(dev, 0x54, reg54 | v_flag); - } else - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } /* move to PCI layer, integrate w/ MSI stuff */ @@ -485,6 +521,42 @@ static void pci_enable_intx(struct pci_dev *pdev) } } +#define AHCI_PCI_BAR 5 +#define AHCI_GLOBAL_CTL 0x04 +#define AHCI_ENABLE (1 << 31) +static int piix_disable_ahci(struct pci_dev *pdev) +{ + void *mmio; + unsigned long addr; + u32 tmp; + int rc = 0; + + /* BUG: pci_enable_device has not yet been called. This + * works because this device is usually set up by BIOS. + */ + + addr = pci_resource_start(pdev, AHCI_PCI_BAR); + if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR)) + return 0; + + mmio = ioremap(addr, 64); + if (!mmio) + return -ENOMEM; + + tmp = readl(mmio + AHCI_GLOBAL_CTL); + if (tmp & AHCI_ENABLE) { + tmp &= ~AHCI_ENABLE; + writel(tmp, mmio + AHCI_GLOBAL_CTL); + + tmp = readl(mmio + AHCI_GLOBAL_CTL); + if (tmp & AHCI_ENABLE) + rc = -EIO; + } + + iounmap(mmio); + return rc; +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -517,6 +589,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port_info[0] = &piix_port_info[ent->driver_data]; port_info[1] = NULL; + if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { + int rc = piix_disable_ahci(pdev); + if (rc) + return rc; + } + if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { u8 tmp; pci_read_config_byte(pdev, ICH5_PMR, &tmp); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index c3d8bc82e..af8adb629 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -99,7 +100,6 @@ #include #include #include -#include #include "scsi.h" #include diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 9cf23b9f2..27136a20a 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -363,7 +363,7 @@ go_42: /* * Clear it off the queue */ - dev->id[target_id].curr_req = 0; + dev->id[target_id].curr_req = NULL; dev->working--; spin_unlock_irqrestore(dev->host->host_lock, flags); /* @@ -1085,7 +1085,7 @@ G2Q_QUIN: /* k=binID#, */ } -void is870(struct Scsi_Host *host, unsigned int wkport) +static void is870(struct Scsi_Host *host, unsigned int wkport) { unsigned int tmport; unsigned char i, j, k, rmb, n; @@ -2263,10 +2263,10 @@ static int atp870u_init_tables(struct Scsi_Host *host) dev->in_snd = 0; dev->in_int = 0; for (k = 0; k < qcnt; k++) { - dev->querequ[k] = 0; + dev->querequ[k] = NULL; } for (k = 0; k < 16; k++) { - dev->id[k].curr_req = 0; + dev->id[k].curr_req = NULL; dev->sp[k] = 0x04; } return 0; diff --git a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c index a69bd792e..bd94c70f4 100644 --- a/drivers/scsi/cpqfcTScontrol.c +++ b/drivers/scsi/cpqfcTScontrol.c @@ -116,7 +116,6 @@ int CpqTsCreateTachLiteQues( void* pHBA, int opcode) cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev, sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle); /* printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH); */ - memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE)); if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!! { diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c index 8778aac34..80af7b5a5 100644 --- a/drivers/scsi/cpqfcTSinit.c +++ b/drivers/scsi/cpqfcTSinit.c @@ -302,10 +302,16 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) cpqfc_boards[i].device_id, PciDev))) { + if (pci_enable_device(PciDev)) { + printk(KERN_ERR + "cpqfc: can't enable PCI device at %s\n", pci_name(PciDev)); + goto err_continue; + } + if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) { printk(KERN_WARNING "cpqfc: HBA cannot support required DMA mask, skipping.\n"); - continue; + goto err_disable_dev; } // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes... @@ -314,8 +320,11 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) ); - if(HostAdapter == NULL) - continue; + if(HostAdapter == NULL) { + printk(KERN_WARNING + "cpqfc: can't register SCSI HBA, skipping.\n"); + goto err_disable_dev; + } DEBUG_PCI( printk(" HBA found!\n")); DEBUG_PCI( printk(" HostAdapter->PciDev->irq = %u\n", PciDev->irq) ); DEBUG_PCI(printk(" PciDev->baseaddress[0]= %lx\n", @@ -358,7 +367,7 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) Cpqfc_initHBAdata( cpqfcHBAdata, PciDev ); // fill MOST fields cpqfcHBAdata->HBAnum = NumberOfAdapters; - cpqfcHBAdata->hba_spinlock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&cpqfcHBAdata->hba_spinlock); // request necessary resources and check for conflicts if( request_irq( HostAdapter->irq, @@ -367,9 +376,8 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) DEV_NAME, HostAdapter) ) { - printk(" IRQ %u already used\n", HostAdapter->irq); - scsi_unregister( HostAdapter); - continue; + printk(KERN_WARNING "cpqfc: IRQ %u already used\n", HostAdapter->irq); + goto err_unregister; } // Since we have two 256-byte I/O port ranges (upper @@ -377,22 +385,17 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME ) ) { - printk(" cpqfcTS address in use: %x\n", + printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU); - free_irq( HostAdapter->irq, HostAdapter); - scsi_unregister( HostAdapter); - continue; + goto err_free_irq; } if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME ) ) { - printk(" cpqfcTS address in use: %x\n", + printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL); - release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff ); - free_irq( HostAdapter->irq, HostAdapter); - scsi_unregister( HostAdapter); - continue; + goto err_release_region_U; } // OK, we have grabbed everything we need now. @@ -424,7 +427,7 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) // now initialize our hardware... if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) { printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n"); - // FIXME: might want to do something better than nothing here. + goto err_release_region_L; } cpqfcHBAdata->fcStatsTime = jiffies; // (for FC Statistics delta) @@ -455,6 +458,21 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate) spin_lock_irq(HostAdapter->host_lock); NumberOfAdapters++; spin_unlock_irq(HostAdapter->host_lock); + + continue; + +err_release_region_L: + release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff ); +err_release_region_U: + release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff ); +err_free_irq: + free_irq( HostAdapter->irq, HostAdapter); +err_unregister: + scsi_unregister( HostAdapter); +err_disable_dev: + pci_disable_device( PciDev ); +err_continue: + continue; } // end of while() } @@ -811,6 +829,7 @@ int cpqfcTS_release(struct Scsi_Host *HostAdapter) cpqfcHBAdata->fcChip.Registers.ReMapMemBase) vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase); */ + pci_disable_device( cpqfcHBAdata->PciDev); LEAVE("cpqfcTS_release"); return 0; diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index bde847c73..5f27f835d 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -295,8 +295,8 @@ struct DeviceCtlBlk { struct AdapterCtlBlk { struct Scsi_Host *scsi_host; - u16 io_port_base; - u16 io_port_len; + unsigned long io_port_base; + unsigned long io_port_len; struct list_head dcb_list; /* head of going dcb list */ struct DeviceCtlBlk *dcb_run_robin; @@ -311,7 +311,7 @@ struct AdapterCtlBlk { u8 sel_timeout; - u8 irq_level; + unsigned int irq_level; u8 tag_max_num; u8 acb_flag; u8 gmode2; @@ -376,6 +376,8 @@ static void disconnect(struct AdapterCtlBlk *acb); static void reselect(struct AdapterCtlBlk *acb); static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); +static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb); static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code, @@ -384,13 +386,11 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb); static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb); -static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb); static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb); -static inline void set_xfer_rate(struct AdapterCtlBlk *acb, +static void set_xfer_rate(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb); static void waiting_timeout(unsigned long ptr); @@ -989,7 +989,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, srb->sg_count = 0; srb->total_xfer_length = 0; srb->sg_bus_addr = 0; - srb->virt_addr = 0; + srb->virt_addr = NULL; srb->sg_index = 0; srb->adapter_status = 0; srb->target_status = 0; @@ -1676,6 +1676,23 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, } +#define DC395x_ENABLE_MSGOUT \ + DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \ + srb->state |= SRB_MSGOUT + + +/* abort command */ +static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, + struct ScsiReqBlk *srb) +{ + srb->msgout_buf[0] = ABORT; + srb->msg_count = 1; + DC395x_ENABLE_MSGOUT; + srb->state &= ~SRB_MSGIN; + srb->state |= SRB_MSGOUT; +} + + /** * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to * have been triggered for this card. @@ -1999,7 +2016,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) } dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); - srb->virt_addr = 0; + srb->virt_addr = NULL; } @@ -2583,11 +2600,6 @@ static inline u8 msgin_completed(u8 * msgbuf, u32 len) return 1; } -#define DC395x_ENABLE_MSGOUT \ - DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \ - srb->state |= SRB_MSGOUT - - /* reject_msg */ static inline void msgin_reject(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) @@ -2603,18 +2615,6 @@ static inline void msgin_reject(struct AdapterCtlBlk *acb, } -/* abort command */ -static inline void enable_msgout_abort(struct AdapterCtlBlk *acb, - struct ScsiReqBlk *srb) -{ - srb->msgout_buf[0] = ABORT; - srb->msg_count = 1; - DC395x_ENABLE_MSGOUT; - srb->state &= ~SRB_MSGIN; - srb->state |= SRB_MSGOUT; -} - - static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, u8 tag) { @@ -3656,7 +3656,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb) } else { acb->acb_flag |= RESET_DETECT; reset_dev_param(acb); - doing_srb_done(acb, DID_RESET, 0, 1); + doing_srb_done(acb, DID_RESET, NULL, 1); /*DC395x_RecoverSRB( acb ); */ acb->active_dcb = NULL; acb->acb_flag = 0; @@ -3931,7 +3931,7 @@ static void dc395x_slave_destroy(struct scsi_device *scsi_device) * * @io_port: base I/O address **/ -static void __init trms1040_wait_30us(u16 io_port) +static void __init trms1040_wait_30us(unsigned long io_port) { /* ScsiPortStallExecution(30); wait 30 us */ outb(5, io_port + TRM_S1040_GEN_TIMER); @@ -3948,7 +3948,7 @@ static void __init trms1040_wait_30us(u16 io_port) * @cmd: SB + op code (command) to send * @addr: address to send **/ -static void __init trms1040_write_cmd(u16 io_port, u8 cmd, u8 addr) +static void __init trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr) { int i; u8 send_data; @@ -3993,7 +3993,7 @@ static void __init trms1040_write_cmd(u16 io_port, u8 cmd, u8 addr) * @addr: offset into EEPROM * @byte: bytes to write **/ -static void __init trms1040_set_data(u16 io_port, u8 addr, u8 byte) +static void __init trms1040_set_data(unsigned long io_port, u8 addr, u8 byte) { int i; u8 send_data; @@ -4047,7 +4047,7 @@ static void __init trms1040_set_data(u16 io_port, u8 addr, u8 byte) * @eeprom: the data to write * @io_port: the base io port **/ -static void __init trms1040_write_all(struct NvRamType *eeprom, u16 io_port) +static void __init trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port) { u8 *b_eeprom = (u8 *)eeprom; u8 addr; @@ -4087,7 +4087,7 @@ static void __init trms1040_write_all(struct NvRamType *eeprom, u16 io_port) * * Returns the the byte read. **/ -static u8 __init trms1040_get_data(u16 io_port, u8 addr) +static u8 __init trms1040_get_data(unsigned long io_port, u8 addr) { int i; u8 read_byte; @@ -4125,7 +4125,7 @@ static u8 __init trms1040_get_data(u16 io_port, u8 addr) * @eeprom: where to store the data * @io_port: the base io port **/ -static void __init trms1040_read_all(struct NvRamType *eeprom, u16 io_port) +static void __init trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port) { u8 *b_eeprom = (u8 *)eeprom; u8 addr; @@ -4155,7 +4155,7 @@ static void __init trms1040_read_all(struct NvRamType *eeprom, u16 io_port) * @eeprom: caller allocated strcuture to read the eeprom data into * @io_port: io port to read from **/ -static void __init check_eeprom(struct NvRamType *eeprom, u16 io_port) +static void __init check_eeprom(struct NvRamType *eeprom, unsigned long io_port) { u16 *w_eeprom = (u16 *)eeprom; u16 w_addr; @@ -4447,7 +4447,7 @@ static void __init adapter_init_scsi_host(struct Scsi_Host *host) * * @acb: The adapter which we are to init. **/ -void __init adapter_init_chip(struct AdapterCtlBlk *acb) +static void __init adapter_init_chip(struct AdapterCtlBlk *acb) { struct NvRamType *eeprom = &acb->eeprom; @@ -4500,11 +4500,11 @@ void __init adapter_init_chip(struct AdapterCtlBlk *acb) * Returns 0 if the initialization succeeds, any other value on * failure. **/ -static int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, - u32 io_port_len, u8 irq) +static int __init adapter_init(struct AdapterCtlBlk *acb, + unsigned long io_port, u32 io_port_len, unsigned int irq) { if (!request_region(io_port, io_port_len, DC395X_NAME)) { - dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port); + dprintkl(KERN_ERR, "Failed to reserve IO region 0x%lx\n", io_port); goto failed; } /* store port base to indicate we have registered it */ @@ -4520,7 +4520,7 @@ static int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, acb->irq_level = irq; /* get eeprom configuration information and command line settings etc */ - check_eeprom(&acb->eeprom, (u16)io_port); + check_eeprom(&acb->eeprom, io_port); print_eeprom_settings(&acb->eeprom); /* setup adapter control block */ @@ -4638,8 +4638,8 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer, SPRINTF("SCSI Host Nr %i, ", host->host_no); SPRINTF("DC395U/UW/F DC315/U %s\n", (acb->config & HCC_WIDE_CARD) ? "Wide" : ""); - SPRINTF("io_port_base 0x%04x, ", acb->io_port_base); - SPRINTF("irq_level 0x%02x, ", acb->irq_level); + SPRINTF("io_port_base 0x%04lx, ", acb->io_port_base); + SPRINTF("irq_level 0x%04x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun); @@ -4792,11 +4792,11 @@ static void banner_display(void) static int __devinit dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - struct Scsi_Host *scsi_host; - struct AdapterCtlBlk *acb; - unsigned int io_port_base; + struct Scsi_Host *scsi_host = NULL; + struct AdapterCtlBlk *acb = NULL; + unsigned long io_port_base; unsigned int io_port_len; - u8 irq; + unsigned int irq; dprintkdbg(DBG_0, "Init one instance (%s)\n", pci_name(dev)); banner_display(); @@ -4809,23 +4809,23 @@ static int __devinit dc395x_init_one(struct pci_dev *dev, io_port_base = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK; io_port_len = pci_resource_len(dev, 0); irq = dev->irq; - dprintkdbg(DBG_0, "IO_PORT=%04x, IRQ=%x\n", io_port_base, dev->irq); + dprintkdbg(DBG_0, "IO_PORT=0x%04lx, IRQ=0x%x\n", io_port_base, dev->irq); /* allocate scsi host information (includes out adapter) */ scsi_host = scsi_host_alloc(&dc395x_driver_template, sizeof(struct AdapterCtlBlk)); if (!scsi_host) { dprintkl(KERN_INFO, "scsi_host_alloc failed\n"); - return -ENOMEM; + goto fail; } acb = (struct AdapterCtlBlk*)scsi_host->hostdata; acb->scsi_host = scsi_host; + acb->dev = dev; /* initialise the adapter and everything we need */ if (adapter_init(acb, io_port_base, io_port_len, irq)) { dprintkl(KERN_INFO, "adapter init failed\n"); - scsi_host_put(scsi_host); - return -ENODEV; + goto fail; } pci_set_master(dev); @@ -4833,14 +4833,20 @@ static int __devinit dc395x_init_one(struct pci_dev *dev, /* get the scsi mid level to scan for new devices on the bus */ if (scsi_add_host(scsi_host, &dev->dev)) { dprintkl(KERN_ERR, "scsi_add_host failed\n"); - adapter_uninit(acb); - scsi_host_put(scsi_host); - return -ENODEV; + goto fail; } pci_set_drvdata(dev, scsi_host); scsi_scan_host(scsi_host); return 0; + +fail: + if (acb != NULL) + adapter_uninit(acb); + if (scsi_host != NULL) + scsi_host_put(scsi_host); + pci_disable_device(dev); + return -ENODEV; } @@ -4859,6 +4865,7 @@ static void __devexit dc395x_remove_one(struct pci_dev *dev) scsi_remove_host(scsi_host); adapter_uninit(acb); + pci_disable_device(dev); scsi_host_put(scsi_host); pci_set_drvdata(dev, NULL); } diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c index f4bdec16d..247c7ca01 100644 --- a/drivers/scsi/dec_esp.c +++ b/drivers/scsi/dec_esp.c @@ -120,7 +120,7 @@ static int dec_esp_release(struct Scsi_Host *shost) } static Scsi_Host_Template driver_template = { - .proc_name = "esp", + .proc_name = "dec_esp", .proc_info = &esp_proc_info, .name = "NCR53C94", .detect = dec_esp_detect, diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 26e060bb8..1d2242403 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -1,7 +1,7 @@ - /* - dmx3191d.c - midlevel driver for the Domex DMX3191D SCSI card. + dmx3191d.c - driver for the Domex DMX3191D SCSI card. Copyright (C) 2000 by Massimo Piccioni + Portions Copyright (C) 2004 by Christoph Hellwig Based on the generic NCR5380 driver by Drew Eckhardt et al. @@ -20,117 +20,154 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include #include #include +#include #include #include -#include -#include -#include #include -#include +#include -#include "scsi.h" #include -#include "dmx3191d.h" +/* + * Defintions for the generic 5380 driver. + */ +#define AUTOSENSE + +#define NCR5380_read(reg) inb(port + reg) +#define NCR5380_write(reg, value) outb(value, port + reg) + +#define NCR5380_implementation_fields unsigned int port +#define NCR5380_local_declare() NCR5380_implementation_fields +#define NCR5380_setup(instance) port = instance->io_port -/* play with these values to tune up your system performances */ -/* default setting from g_NCR5380.c */ /* -#define USLEEP -#define USLEEP_POLL 1 -#define USLEEP_SLEEP 20 -#define USLEEP_WAITLONG 500 -*/ + * Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h) + */ +#include +#include "scsi.h" -#define AUTOSENSE #include "NCR5380.h" #include "NCR5380.c" +#define DMX3191D_DRIVER_NAME "dmx3191d" +#define DMX3191D_REGION_LEN 8 + -static int __init dmx3191d_detect(Scsi_Host_Template *tmpl) { - int boards = 0; - struct Scsi_Host *instance = NULL; - struct pci_dev *pdev = NULL; - - tmpl->proc_name = DMX3191D_DRIVER_NAME; - - while ((pdev = pci_find_device(PCI_VENDOR_ID_DOMEX, - PCI_DEVICE_ID_DOMEX_DMX3191D, pdev))) { - - unsigned long port; - if (pci_enable_device(pdev)) - continue; - - port = pci_resource_start (pdev, 0); - - if (!request_region(port, DMX3191D_REGION, DMX3191D_DRIVER_NAME)) { - printk(KERN_ERR "dmx3191: region 0x%lx-0x%lx already reserved\n", - port, port + DMX3191D_REGION); - continue; - } - - instance = scsi_register(tmpl, sizeof(struct NCR5380_hostdata)); - if(instance == NULL) - { - release_region(port, DMX3191D_REGION); - continue; - } - scsi_set_device(instance, &pdev->dev); - instance->io_port = port; - instance->irq = pdev->irq; - NCR5380_init(instance, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); - - if (request_irq(pdev->irq, dmx3191d_intr, SA_SHIRQ, - DMX3191D_DRIVER_NAME, instance)) { - printk(KERN_WARNING "dmx3191: IRQ %d not available - switching to polled mode.\n", pdev->irq); - /* Steam powered scsi controllers run without an IRQ - anyway */ - instance->irq = SCSI_IRQ_NONE; - } - - boards++; +static struct scsi_host_template dmx3191d_driver_template = { + .proc_name = DMX3191D_DRIVER_NAME, + .name = "Domex DMX3191D", + .queuecommand = NCR5380_queue_command, + .eh_abort_handler = NCR5380_abort, + .eh_bus_reset_handler = NCR5380_bus_reset, + .eh_device_reset_handler= NCR5380_device_reset, + .eh_host_reset_handler = NCR5380_host_reset, + .can_queue = 32, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, +}; + +static int __devinit dmx3191d_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct Scsi_Host *shost; + unsigned long io; + int error = -ENODEV; + + if (pci_enable_device(pdev)) + goto out; + + io = pci_resource_start(pdev, 0); + if (!request_region(io, DMX3191D_REGION_LEN, DMX3191D_DRIVER_NAME)) { + printk(KERN_ERR "dmx3191: region 0x%lx-0x%lx already reserved\n", + io, io + DMX3191D_REGION_LEN); + goto out_disable_device; } - return boards; -} -static const char * dmx3191d_info(struct Scsi_Host *host) { - static const char *info ="Domex DMX3191D"; + shost = scsi_host_alloc(&dmx3191d_driver_template, + sizeof(struct NCR5380_hostdata)); + if (!shost) + goto out_release_region; + shost->io_port = io; + shost->irq = pdev->irq; + + NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + + if (request_irq(pdev->irq, NCR5380_intr, SA_SHIRQ, + DMX3191D_DRIVER_NAME, shost)) { + /* + * Steam powered scsi controllers run without an IRQ anyway + */ + printk(KERN_WARNING "dmx3191: IRQ %d not available - " + "switching to polled mode.\n", pdev->irq); + shost->irq = SCSI_IRQ_NONE; + } - return info; + pci_set_drvdata(pdev, shost); + + error = scsi_add_host(shost, &pdev->dev); + if (error) + goto out_free_irq; + + scsi_scan_host(shost); + return 0; + + out_free_irq: + free_irq(shost->irq, shost); + out_release_region: + release_region(shost->io_port, DMX3191D_REGION_LEN); + out_disable_device: + pci_disable_device(pdev); + out: + return error; } -static int dmx3191d_release_resources(struct Scsi_Host *instance) +static void __devexit dmx3191d_remove_one(struct pci_dev *pdev) { - release_region(instance->io_port, DMX3191D_REGION); - if(instance->irq!=SCSI_IRQ_NONE) - free_irq(instance->irq, instance); + struct Scsi_Host *shost = pci_get_drvdata(pdev); - return 0; + scsi_remove_host(shost); + + NCR5380_exit(shost); + + if (shost->irq != SCSI_IRQ_NONE) + free_irq(shost->irq, shost); + release_region(shost->io_port, DMX3191D_REGION_LEN); + pci_disable_device(pdev); + + scsi_host_put(shost); } -MODULE_LICENSE("GPL"); +static struct pci_device_id dmx3191d_pci_tbl[] = { + {PCI_VENDOR_ID_DOMEX, PCI_DEVICE_ID_DOMEX_DMX3191D, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { } +}; +MODULE_DEVICE_TABLE(pci, dmx3191d_pci_tbl); -static Scsi_Host_Template driver_template = { - .proc_info = dmx3191d_proc_info, - .name = "Domex DMX3191D", - .detect = dmx3191d_detect, - .release = dmx3191d_release_resources, - .info = dmx3191d_info, - .queuecommand = dmx3191d_queue_command, - .eh_abort_handler = dmx3191d_abort, - .eh_bus_reset_handler = dmx3191d_bus_reset, - .eh_device_reset_handler = dmx3191d_device_reset, - .eh_host_reset_handler = dmx3191d_host_reset, - .can_queue = 32, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING, +static struct pci_driver dmx3191d_pci_driver = { + .name = DMX3191D_DRIVER_NAME, + .id_table = dmx3191d_pci_tbl, + .probe = dmx3191d_probe_one, + .remove = __devexit_p(dmx3191d_remove_one), }; -#include "scsi_module.c" +static int __init dmx3191d_init(void) +{ + return pci_module_init(&dmx3191d_pci_driver); +} + +static void __exit dmx3191d_exit(void) +{ + pci_unregister_driver(&dmx3191d_pci_driver); +} + +module_init(dmx3191d_init); +module_exit(dmx3191d_exit); + +MODULE_AUTHOR("Massimo Piccioni "); +MODULE_DESCRIPTION("Domex DMX3191D SCSI driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 77cf39f3b..c623c60f6 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -872,8 +872,8 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev ulong base_addr1_phys = 0; u32 hba_map0_area_size = 0; u32 hba_map1_area_size = 0; - ulong base_addr_virt = 0; - ulong msg_addr_virt = 0; + void __iomem *base_addr_virt = NULL; + void __iomem *msg_addr_virt = NULL; int raptorFlag = FALSE; int i; @@ -907,17 +907,17 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev } - base_addr_virt = (ulong)ioremap(base_addr0_phys,hba_map0_area_size); - if(base_addr_virt == 0) { + base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); + if (!base_addr_virt) { PERROR("dpti: adpt_config_hba: io remap failed\n"); return -EINVAL; } if(raptorFlag == TRUE) { - msg_addr_virt = (ulong)ioremap(base_addr1_phys, hba_map1_area_size ); - if(msg_addr_virt == 0) { + msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size ); + if (!msg_addr_virt) { PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); - iounmap((void*)base_addr_virt); + iounmap(base_addr_virt); return -EINVAL; } } else { @@ -928,9 +928,9 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL); if( pHba == NULL) { if(msg_addr_virt != base_addr_virt){ - iounmap((void*)msg_addr_virt); + iounmap(msg_addr_virt); } - iounmap((void*)base_addr_virt); + iounmap(base_addr_virt); return -ENOMEM; } memset(pHba, 0, sizeof(adpt_hba)); @@ -961,10 +961,10 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev // Set up the Virtual Base Address of the I2O Device pHba->base_addr_virt = base_addr_virt; - pHba->msg_addr_virt = msg_addr_virt; - pHba->irq_mask = (ulong)(base_addr_virt+0x30); - pHba->post_port = (ulong)(base_addr_virt+0x40); - pHba->reply_port = (ulong)(base_addr_virt+0x44); + pHba->msg_addr_virt = msg_addr_virt; + pHba->irq_mask = base_addr_virt+0x30; + pHba->post_port = base_addr_virt+0x40; + pHba->reply_port = base_addr_virt+0x44; pHba->hrt = NULL; pHba->lct = NULL; @@ -980,12 +980,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev spin_lock_init(&adpt_post_wait_lock); if(raptorFlag == 0){ - printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", + printk(KERN_INFO"Adaptec I2O RAID controller %d at %p size=%x irq=%d\n", hba_count-1, base_addr_virt, hba_map0_area_size, pDev->irq); } else { printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d\n",hba_count-1, pDev->irq); - printk(KERN_INFO" BAR0 %lx - size= %x\n",base_addr_virt,hba_map0_area_size); - printk(KERN_INFO" BAR1 %lx - size= %x\n",msg_addr_virt,hba_map1_area_size); + printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size); + printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size); } if (request_irq (pDev->irq, adpt_isr, SA_SHIRQ, pHba->name, pHba)) { @@ -1036,9 +1036,9 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) hba_count--; up(&adpt_configuration_lock); - iounmap((void*)pHba->base_addr_virt); + iounmap(pHba->base_addr_virt); if(pHba->msg_addr_virt != pHba->base_addr_virt){ - iounmap((void*)pHba->msg_addr_virt); + iounmap(pHba->msg_addr_virt); } if(pHba->hrt) { kfree(pHba->hrt); @@ -1222,7 +1222,7 @@ static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len) { u32 m = EMPTY_QUEUE; - u32 *msg; + u32 __iomem *msg; ulong timeout = jiffies + 30*HZ; do { rmb(); @@ -1238,7 +1238,7 @@ static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len) schedule_timeout(1); } while(m == EMPTY_QUEUE); - msg = (u32*) (pHba->msg_addr_virt + m); + msg = pHba->msg_addr_virt + m; memcpy_toio(msg, data, len); wmb(); @@ -2638,7 +2638,7 @@ static int adpt_i2o_online_hba(adpt_hba* pHba) static s32 adpt_send_nop(adpt_hba*pHba,u32 m) { - u32 *msg; + u32 __iomem *msg; ulong timeout = jiffies + 5*HZ; while(m == EMPTY_QUEUE){ @@ -2654,7 +2654,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m) set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } - msg = (u32*)(pHba->msg_addr_virt + m); + msg = (u32 __iomem *)(pHba->msg_addr_virt + m); writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]); writel( 0,&msg[2]); @@ -2668,7 +2668,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m) static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) { u8 *status; - u32 *msg = NULL; + u32 __iomem *msg = NULL; int i; ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ; u32* ptr; @@ -2690,7 +2690,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) schedule_timeout(1); } while(m == EMPTY_QUEUE); - msg=(u32 *)(pHba->msg_addr_virt+m); + msg=(u32 __iomem *)(pHba->msg_addr_virt+m); status = kmalloc(4,GFP_KERNEL|ADDR32); if (status==NULL) { @@ -2775,7 +2775,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) { ulong timeout; u32 m; - u32 *msg; + u32 __iomem *msg; u8 *status_block=NULL; ulong status_block_bus; @@ -2809,7 +2809,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) } while(m==EMPTY_QUEUE); - msg=(u32*)(pHba->msg_addr_virt+m); + msg=(u32 __iomem *)(pHba->msg_addr_virt+m); writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index c43673bbe..a80273160 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -228,12 +228,12 @@ typedef struct _adpt_hba { char name[32]; char detail[55]; - ulong base_addr_virt; - ulong msg_addr_virt; + void __iomem *base_addr_virt; + void __iomem *msg_addr_virt; ulong base_addr_phys; - ulong post_port; - ulong reply_port; - ulong irq_mask; + void __iomem *post_port; + void __iomem *reply_port; + void __iomem *irq_mask; u16 post_count; u32 post_fifo_size; u32 reply_fifo_size; @@ -251,12 +251,12 @@ typedef struct _adpt_hba { struct adpt_channel channel[MAX_CHANNEL]; struct proc_dir_entry* proc_entry; /* /proc dir */ - ulong FwDebugBuffer_P; // Virtual Address Of FW Debug Buffer + void __iomem *FwDebugBuffer_P; // Virtual Address Of FW Debug Buffer u32 FwDebugBufferSize; // FW Debug Buffer Size In Bytes - ulong FwDebugStrLength_P; // Virtual Addr Of FW Debug String Len - ulong FwDebugFlags_P; // Virtual Address Of FW Debug Flags - ulong FwDebugBLEDflag_P; // Virtual Addr Of FW Debug BLED - ulong FwDebugBLEDvalue_P; // Virtual Addr Of FW Debug BLED + void __iomem *FwDebugStrLength_P;// Virtual Addr Of FW Debug String Len + void __iomem *FwDebugFlags_P; // Virtual Address Of FW Debug Flags + void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED + void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED u32 FwDebugFlags; } adpt_hba; diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 624c7ee5d..da1aaa413 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -219,44 +219,58 @@ static int __init dtc_detect(Scsi_Host_Template * tpnt) { static int current_override = 0, current_base = 0; struct Scsi_Host *instance; - unsigned int base; + unsigned int addr; + void __iomem *base; int sig, count; tpnt->proc_name = "dtc3x80"; tpnt->proc_info = &dtc_proc_info; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - base = 0; - - if (overrides[current_override].address) - base = overrides[current_override].address; - else - for (; !base && (current_base < NO_BASES); ++current_base) { + addr = 0; + base = NULL; + + if (overrides[current_override].address) { + addr = overrides[current_override].address; + base = ioremap(addr, 0x2000); + if (!base) + addr = 0; + } else + for (; !addr && (current_base < NO_BASES); ++current_base) { #if (DTCDEBUG & DTCDEBUG_INIT) printk("scsi-dtc : probing address %08x\n", bases[current_base].address); #endif - for (sig = 0; sig < NO_SIGNATURES; ++sig) - if (!bases[current_base].noauto && isa_check_signature(bases[current_base].address + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { - base = bases[current_base].address; + if (bases[current_base].noauto) + continue; + base = ioremap(bases[current_base].address, 0x2000); + if (!base) + continue; + for (sig = 0; sig < NO_SIGNATURES; ++sig) { + if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { + addr = bases[current_base].address; #if (DTCDEBUG & DTCDEBUG_INIT) printk("scsi-dtc : detected board.\n"); #endif - break; + goto found; } + } + iounmap(base); } #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) - printk("scsi-dtc : base = %08x\n", base); + printk("scsi-dtc : base = %08x\n", addr); #endif - if (!base) + if (!addr) break; +found: instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) break; - instance->base = base; + instance->base = addr; + ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; NCR5380_init(instance, 0); @@ -372,7 +386,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) ++i; rtrc(3); - isa_memcpy_fromio(d, base + DTC_DATA_BUF, 128); + memcpy_fromio(d, base + DTC_DATA_BUF, 128); d += 128; len -= 128; rtrc(7); @@ -423,7 +437,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) ++i; rtrc(3); - isa_memcpy_toio(base + DTC_DATA_BUF, src, 128); + memcpy_toio(base + DTC_DATA_BUF, src, 128); src += 128; len -= 128; } @@ -449,11 +463,15 @@ MODULE_LICENSE("GPL"); static int dtc_release(struct Scsi_Host *shost) { + NCR5380_local_declare(); + NCR5380_setup(shost); if (shost->irq) free_irq(shost->irq, NULL); + NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); + iounmap(base); return 0; } diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index e15d8216d..c4bcdbf33 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -46,40 +46,40 @@ static int dtc_host_reset(Scsi_Cmnd *); #endif #define NCR5380_implementation_fields \ - unsigned int base + void __iomem *base #define NCR5380_local_declare() \ - unsigned int base + void __iomem *base #define NCR5380_setup(instance) \ - base = (unsigned int)(instance)->base + base = ((struct NCR5380_hostdata *)(instance)->hostdata)->base #define DTC_address(reg) (base + DTC_5380_OFFSET + reg) #define dbNCR5380_read(reg) \ - (rval=isa_readb(DTC_address(reg)), \ - (((unsigned char) printk("DTC : read register %d at addr %08x is: %02x\n"\ - , (reg), (int)DTC_address(reg), rval)), rval ) ) + (rval=readb(DTC_address(reg)), \ + (((unsigned char) printk("DTC : read register %d at addr %p is: %02x\n"\ + , (reg), DTC_address(reg), rval)), rval ) ) #define dbNCR5380_write(reg, value) do { \ - printk("DTC : write %02x to register %d at address %08x\n", \ - (value), (reg), (int)DTC_address(reg)); \ - isa_writeb(value, DTC_address(reg));} while(0) + printk("DTC : write %02x to register %d at address %p\n", \ + (value), (reg), DTC_address(reg)); \ + writeb(value, DTC_address(reg));} while(0) #if !(DTCDEBUG & DTCDEBUG_TRANSFER) -#define NCR5380_read(reg) (isa_readb(DTC_address(reg))) -#define NCR5380_write(reg, value) (isa_writeb(value, DTC_address(reg))) +#define NCR5380_read(reg) (readb(DTC_address(reg))) +#define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) #else -#define NCR5380_read(reg) (isa_readb(DTC_address(reg))) +#define NCR5380_read(reg) (readb(DTC_address(reg))) #define xNCR5380_read(reg) \ - (((unsigned char) printk("DTC : read register %d at address %08x\n"\ - , (reg), DTC_address(reg))), isa_readb(DTC_address(reg))) + (((unsigned char) printk("DTC : read register %d at address %p\n"\ + , (reg), DTC_address(reg))), readb(DTC_address(reg))) #define NCR5380_write(reg, value) do { \ - printk("DTC : write %02x to register %d at address %08x\n", \ - (value), (reg), (int)DTC_address(reg)); \ - isa_writeb(value, DTC_address(reg));} while(0) + printk("DTC : write %02x to register %d at address %p\n", \ + (value), (reg), DTC_address(reg)); \ + writeb(value, DTC_address(reg));} while(0) #endif #define NCR5380_intr dtc_intr diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index 0e245e318..bab481034 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -474,7 +474,7 @@ * The boards are named EATA0, EATA1,... according to the detection order. * * In order to support multiple ISA boards in a reliable way, - * the driver sets host->wish_block = TRUE for all ISA boards. + * the driver sets host->wish_block = 1 for all ISA boards. */ #include @@ -482,9 +482,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -493,22 +490,29 @@ #include #include #include -#include -#include "scsi.h" -#include +#include #include +#include #include -static int eata2x_detect(Scsi_Host_Template *); +#include +#include +#include +#include +#include +#include + +static int eata2x_detect(struct scsi_host_template *); static int eata2x_release(struct Scsi_Host *); -static int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int eata2x_eh_abort(Scsi_Cmnd *); -static int eata2x_eh_host_reset(Scsi_Cmnd *); +static int eata2x_queuecommand(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); +static int eata2x_eh_abort(struct scsi_cmnd *); +static int eata2x_eh_host_reset(struct scsi_cmnd *); static int eata2x_bios_param(struct scsi_device *, struct block_device *, sector_t, int *); -static int eata2x_slave_configure(Scsi_Device *); +static int eata2x_slave_configure(struct scsi_device *); -static Scsi_Host_Template driver_template = { +static struct scsi_host_template driver_template = { .name = "EATA/DMA 2.0x rev. 8.10.00 ", .detect = eata2x_detect, .release = eata2x_release, @@ -558,8 +562,6 @@ static Scsi_Host_Template driver_template = { #define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN) #define SKIP ULONG_MAX -#define FALSE 0 -#define TRUE 1 #define FREE 0 #define IN_USE 1 #define LOCKED 2 @@ -766,7 +768,7 @@ struct mscp { u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */ /* Additional fields begin here. */ - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; /* All the cp structure is zero filled by queuecommand except the following CP_TAIL_SIZE bytes, initialized by detect */ @@ -785,12 +787,12 @@ struct hostdata { char board_name[16]; /* Name of this board */ int in_reset; /* True if board is doing a reset */ int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */ - int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */ + int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If 1 redo i/o on target */ unsigned int retries; /* Number of internal retries */ unsigned long last_retried_pid; /* Pid of last retried command */ unsigned char subversion; /* Bus type, either ISA or EISA/PCI */ unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */ - unsigned char is_pci; /* TRUE is bus type is PCI */ + unsigned char is_pci; /* 1 is bus type is PCI */ struct pci_dev *pdev; /* pdev for PCI bus, NULL otherwise */ struct mssp *sp_cpu_addr; /* cpu addr for DMA buffer sp */ dma_addr_t sp_dma_addr; /* dma handle for DMA buffer sp */ @@ -842,12 +844,12 @@ static unsigned long io_port[] = { #define REG2H(x) le16_to_cpu(x) static irqreturn_t do_interrupt_handler(int, void *, struct pt_regs *); -static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); -static int do_trace = FALSE; -static int setup_done = FALSE; +static void flush_dev(struct scsi_device *, unsigned long, unsigned int, unsigned int); +static int do_trace = 0; +static int setup_done = 0; static int link_statistics; -static int ext_tran = FALSE; -static int rev_scan = TRUE; +static int ext_tran = 0; +static int rev_scan = 1; #if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) static int tag_mode = TAG_SIMPLE; @@ -856,9 +858,9 @@ static int tag_mode = TAG_DISABLED; #endif #if defined(CONFIG_SCSI_EATA_LINKED_COMMANDS) -static int linked_comm = TRUE; +static int linked_comm = 1; #else -static int linked_comm = FALSE; +static int linked_comm = 0; #endif #if defined(CONFIG_SCSI_EATA_MAX_TAGS) @@ -868,21 +870,21 @@ static int max_queue_depth = MAX_CMD_PER_LUN; #endif #if defined(CONFIG_ISA) -static int isa_probe = TRUE; +static int isa_probe = 1; #else -static int isa_probe = FALSE; +static int isa_probe = 0; #endif #if defined(CONFIG_EISA) -static int eisa_probe = TRUE; +static int eisa_probe = 1; #else -static int eisa_probe = FALSE; +static int eisa_probe = 0; #endif #if defined(CONFIG_PCI) -static int pci_probe = TRUE; +static int pci_probe = 1; #else -static int pci_probe = FALSE; +static int pci_probe = 0; #endif #define MAX_INT_PARAM 10 @@ -902,7 +904,7 @@ MODULE_DESCRIPTION("EATA/DMA SCSI Driver"); #endif -static int eata2x_slave_configure(Scsi_Device *dev) { +static int eata2x_slave_configure(struct scsi_device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; @@ -948,24 +950,24 @@ static int eata2x_slave_configure(Scsi_Device *dev) { BN(j), host->host_no, dev->channel, dev->id, dev->lun, dev->queue_depth, link_suffix, tag_suffix); - return FALSE; + return 0; } static int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { udelay(1L); - if (--loop == 0) return TRUE; + if (--loop == 0) return 1; } - return FALSE; + return 0; } static int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { unsigned char *byaddr; unsigned long devaddr; - if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; + if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return 1; if (addr) { devaddr = H2DEV(addr); @@ -977,7 +979,7 @@ static int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { } outb(cmd, iobase + REG_CMD); - return FALSE; + return 0; } static int read_pio(unsigned long iobase, ushort *start, ushort *end) { @@ -988,14 +990,14 @@ static int read_pio(unsigned long iobase, ushort *start, ushort *end) { while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { udelay(1L); - if (--loop == 0) return TRUE; + if (--loop == 0) return 1; } loop = MAXLOOP; *p = REG2H(inw(iobase)); } - return FALSE; + return 0; } static struct pci_dev *get_pci_dev(unsigned long port_base) { @@ -1005,7 +1007,7 @@ static struct pci_dev *get_pci_dev(unsigned long port_base) { unsigned int addr; struct pci_dev *dev = NULL; - while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { + while((dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { addr = pci_resource_start (dev, 0); #if defined(DEBUG_PCI_DETECT) @@ -1013,6 +1015,11 @@ static struct pci_dev *get_pci_dev(unsigned long port_base) { driver_name, dev->bus->number, dev->devfn, addr); #endif + /* we are in so much trouble for a pci hotplug system with this driver + * anyway, so doing this at least lets people unload the driver and not + * cause memory problems, but in general this is a bad thing to do (this + * driver needs to be converted to the proper PCI api someday... */ + pci_dev_put(dev); if (addr + PCI_BASE_ADDRESS_0 == port_base) return dev; } @@ -1027,7 +1034,7 @@ static void enable_pci_ports(void) { struct pci_dev *dev = NULL; - while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { + while((dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { #if defined(DEBUG_PCI_DETECT) printk("%s: enable_pci_ports, bus %d, devfn 0x%x.\n", @@ -1043,8 +1050,8 @@ static void enable_pci_ports(void) { } static int port_detect \ - (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { - unsigned char irq, dma_channel, subversion, i, is_pci = FALSE; + (unsigned long port_base, unsigned int j, struct scsi_host_template *tpnt) { + unsigned char irq, dma_channel, subversion, i, is_pci = 0; unsigned char protocol_rev; struct eata_info info; char *bus_type, dma_name[16]; @@ -1112,12 +1119,12 @@ static int port_detect \ if (protocol_rev != 'A' && info.forcaddr) { printk("%s: warning, port address has been forced.\n", name); bus_type = "PCI"; - is_pci = TRUE; + is_pci = 1; subversion = ESA; } else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) { bus_type = "PCI"; - is_pci = TRUE; + is_pci = 1; subversion = ESA; } else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) { @@ -1130,7 +1137,7 @@ static int port_detect \ } else if (port_base > MAX_ISA_ADDR) { bus_type = "PCI"; - is_pci = TRUE; + is_pci = 1; subversion = ESA; } else { @@ -1212,7 +1219,7 @@ static int port_detect \ /* Set board configuration */ memset((char *)cf, 0, sizeof(struct eata_config)); cf->len = (ushort) H2DEV16((ushort)510); - cf->ocena = TRUE; + cf->ocena = 1; if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); @@ -1249,10 +1256,10 @@ static int port_detect \ HD(j)->board_number = j; if (HD(j)->subversion == ESA) - sh[j]->unchecked_isa_dma = FALSE; + sh[j]->unchecked_isa_dma = 0; else { unsigned long flags; - sh[j]->unchecked_isa_dma = TRUE; + sh[j]->unchecked_isa_dma = 1; flags=claim_dma_lock(); disable_dma(dma_channel); @@ -1373,7 +1380,7 @@ static int port_detect \ printk("%s: warning, pci_set_dma_mask failed.\n", BN(j)); } - return TRUE; + return 1; freedma: if (subversion == ISA) free_dma(dma_channel); @@ -1383,11 +1390,11 @@ freelock: spin_unlock_irq(&driver_lock); release_region(port_base, REGION_SIZE); fail: - return FALSE; + return 0; release: eata2x_release(sh[j]); - return FALSE; + return 0; } static void internal_setup(char *str, int *ints) { @@ -1401,14 +1408,14 @@ static void internal_setup(char *str, int *ints) { for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; io_port[i] = 0; - setup_done = TRUE; + setup_done = 1; } while (cur && (pc = strchr(cur, ':'))) { int val = 0, c = *++pc; - if (c == 'n' || c == 'N') val = FALSE; - else if (c == 'y' || c == 'Y') val = TRUE; + if (c == 'n' || c == 'N') val = 0; + else if (c == 'y' || c == 'Y') val = 1; else val = (int) simple_strtoul(pc, NULL, 0); if (!strncmp(cur, "lc:", 3)) linked_comm = val; @@ -1454,7 +1461,7 @@ static void add_pci_ports(void) { for (k = 0; k < MAX_PCI; k++) { - if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; + if (!(dev = pci_get_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; if (pci_enable_device (dev)) { @@ -1478,12 +1485,13 @@ static void add_pci_ports(void) { addr + PCI_BASE_ADDRESS_0; } + pci_dev_put(dev); #endif /* end CONFIG_PCI */ return; } -static int eata2x_detect(Scsi_Host_Template *tpnt) { +static int eata2x_detect(struct scsi_host_template *tpnt) { unsigned int j = 0, k; tpnt->proc_name = "eata2x"; @@ -1493,7 +1501,7 @@ static int eata2x_detect(Scsi_Host_Template *tpnt) { #if defined(MODULE) /* io_port could have been modified when loading as a module */ if(io_port[0] != SKIP) { - setup_done = TRUE; + setup_done = 1; io_port[MAX_INT_PARAM] = 0; } #endif @@ -1529,10 +1537,10 @@ static void map_dma(unsigned int i, unsigned int j) { unsigned int k, count, pci_dir; struct scatterlist *sgpnt; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (SCpnt->sense_buffer) cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer, @@ -1561,7 +1569,7 @@ static void map_dma(unsigned int i, unsigned int j) { cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k])); } - cpp->sg = TRUE; + cpp->sg = 1; cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist, SCpnt->use_sg * sizeof(struct sg_list), pci_dir)); cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list))); @@ -1570,10 +1578,10 @@ static void map_dma(unsigned int i, unsigned int j) { static void unmap_dma(unsigned int i, unsigned int j) { unsigned int pci_dir; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (DEV2H(cpp->sense_addr)) pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), @@ -1592,10 +1600,10 @@ static void unmap_dma(unsigned int i, unsigned int j) { static void sync_dma(unsigned int i, unsigned int j) { unsigned int pci_dir; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (DEV2H(cpp->sense_addr)) pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr), @@ -1628,45 +1636,45 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) { }; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - if (SCpnt->sc_data_direction == SCSI_DATA_READ) { - cpp->din = TRUE; - cpp->dout = FALSE; + if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { + cpp->din = 1; + cpp->dout = 0; return; } - else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) { - cpp->din = FALSE; - cpp->dout = TRUE; + else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { + cpp->din = 0; + cpp->dout = 1; return; } - else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) { - cpp->din = FALSE; - cpp->dout = FALSE; + else if (SCpnt->sc_data_direction == DMA_NONE) { + cpp->din = 0; + cpp->dout = 0; return; } - if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) + if (SCpnt->sc_data_direction != DMA_BIDIRECTIONAL) panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j)); for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) if (SCpnt->cmnd[0] == data_out_cmds[k]) { - cpp->dout = TRUE; + cpp->dout = 1; break; } if ((cpp->din = !cpp->dout)) for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) if (SCpnt->cmnd[0] == data_none_cmds[k]) { - cpp->din = FALSE; + cpp->din = 0; break; } } -static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { +static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { unsigned int i, j, k; struct mscp *cpp; @@ -1712,12 +1720,12 @@ static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { BN(j), i, SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, SCpnt->pid); - cpp->reqsen = TRUE; - cpp->dispri = TRUE; + cpp->reqsen = 1; + cpp->dispri = 1; #if 0 - if (SCpnt->device->type == TYPE_TAPE) cpp->hbaci = TRUE; + if (SCpnt->device->type == TYPE_TAPE) cpp->hbaci = 1; #endif - cpp->one = TRUE; + cpp->one = 1; cpp->channel = SCpnt->device->channel; cpp->target = SCpnt->device->id; cpp->lun = SCpnt->device->lun; @@ -1733,7 +1741,7 @@ static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { if (linked_comm && SCpnt->device->queue_depth > 2 && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; - flush_dev(SCpnt->device, SCpnt->request->sector, j, FALSE); + flush_dev(SCpnt->device, SCpnt->request->sector, j, 0); return 0; } @@ -1750,7 +1758,7 @@ static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { return 0; } -static int eata2x_eh_abort(Scsi_Cmnd *SCarg) { +static int eata2x_eh_abort(struct scsi_cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; @@ -1824,10 +1832,10 @@ static int eata2x_eh_abort(Scsi_Cmnd *SCarg) { panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { +static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; - int arg_done = FALSE; - Scsi_Cmnd *SCpnt; + int arg_done = 0; + struct scsi_cmnd *SCpnt; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", @@ -1850,7 +1858,7 @@ static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { for (c = 0; c <= sh[j]->max_channel; c++) for (k = 0; k < sh[j]->max_id; k++) { - HD(j)->target_redo[k][c] = TRUE; + HD(j)->target_redo[k][c] = 1; HD(j)->target_to[k][c] = 0; } @@ -1888,7 +1896,7 @@ static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { if (SCpnt->scsi_done == NULL) panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - if (SCpnt == SCarg) arg_done = TRUE; + if (SCpnt == SCarg) arg_done = 1; } if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { @@ -1899,10 +1907,10 @@ static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); #if defined(DEBUG_RESET) - do_trace = TRUE; + do_trace = 1; #endif - HD(j)->in_reset = TRUE; + HD(j)->in_reset = 1; spin_unlock_irq(sh[j]->host_lock); time = jiffies; @@ -1947,8 +1955,8 @@ static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { SCpnt->scsi_done(SCpnt); } - HD(j)->in_reset = FALSE; - do_trace = FALSE; + HD(j)->in_reset = 0; + do_trace = 0; if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); else printk("%s: reset, exit.\n", BN(j)); @@ -1971,7 +1979,7 @@ int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev, dkinfo[0], dkinfo[1], dkinfo[2]); #endif - return FALSE; + return 0; } static void sort(unsigned long sk[], unsigned int da[], unsigned int n, @@ -2001,11 +2009,11 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, static int reorder(unsigned int j, unsigned long cursec, unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; struct mscp *cpp; unsigned int k, n; - unsigned int rev = FALSE, s = TRUE, r = TRUE; - unsigned int input_only = TRUE, overlap = FALSE; + unsigned int rev = 0, s = 1, r = 1; + unsigned int input_only = 1, overlap = 0; unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; unsigned long ioseek = 0; @@ -2022,12 +2030,12 @@ static int reorder(unsigned int j, unsigned long cursec, seeknosort / (readycount + 1), seeksorted / (readycount + 1)); - if (n_ready <= 1) return FALSE; + if (n_ready <= 1) return 0; for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - if (!cpp->din) input_only = FALSE; + if (!cpp->din) input_only = 0; if (SCpnt->request->sector < minsec) minsec = SCpnt->request->sector; if (SCpnt->request->sector > maxsec) maxsec = SCpnt->request->sector; @@ -2037,8 +2045,8 @@ static int reorder(unsigned int j, unsigned long cursec, if (!n) continue; - if (sl[n] < sl[n - 1]) s = FALSE; - if (sl[n] > sl[n - 1]) r = FALSE; + if (sl[n] < sl[n - 1]) s = 0; + if (sl[n] > sl[n - 1]) r = 0; if (link_statistics) { if (sl[n] > sl[n - 1]) @@ -2053,9 +2061,9 @@ static int reorder(unsigned int j, unsigned long cursec, if (cursec > sl[0]) seek += cursec - sl[0]; else seek += sl[0] - cursec; } - if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; + if (cursec > ((maxsec + minsec) / 2)) rev = 1; - if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE; + if (ioseek > ((maxsec - minsec) / 2)) rev = 0; if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); @@ -2066,10 +2074,10 @@ static int reorder(unsigned int j, unsigned long cursec, if (!n) continue; if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) - || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE; + || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = 1; } - if (overlap) sort(pl, il, n_ready, FALSE); + if (overlap) sort(pl, il, n_ready, 0); if (link_statistics) { if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; @@ -2097,9 +2105,9 @@ static int reorder(unsigned int j, unsigned long cursec, return overlap; } -static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, +static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned int j, unsigned int ihdlr) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; struct mscp *cpp; unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES]; @@ -2135,7 +2143,7 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, } static irqreturn_t ihdlr(int irq, unsigned int j) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg; struct mssp *spp; struct mscp *cpp; @@ -2184,13 +2192,13 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { #endif /* Reject any sp with supspect data */ - if (spp->eoc == FALSE && HD(j)->iocount > 1) - printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n", + if (spp->eoc == 0 && HD(j)->iocount > 1) + printk("%s: ihdlr, spp->eoc == 0, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); if (spp->cpp_index < 0 || spp->cpp_index >= sh[j]->can_queue) printk("%s: ihdlr, bad spp->cpp_index %d, irq %d, reg 0x%x, count %d.\n", BN(j), spp->cpp_index, irq, reg, HD(j)->iocount); - if (spp->eoc == FALSE || spp->cpp_index < 0 + if (spp->eoc == 0 || spp->cpp_index < 0 || spp->cpp_index >= sh[j]->can_queue) goto handled; /* Find the mailbox to be serviced on this board */ @@ -2240,7 +2248,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { if (linked_comm && SCpnt->device->queue_depth > 2 && TLDEV(SCpnt->device->type)) - flush_dev(SCpnt->device, SCpnt->request->sector, j, TRUE); + flush_dev(SCpnt->device, SCpnt->request->sector, j, 1); tstatus = status_byte(spp->target_status); @@ -2271,7 +2279,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { status = DID_OK << 16; if (tstatus == GOOD) - HD(j)->target_redo[SCpnt->device->id][SCpnt->device->channel] = FALSE; + HD(j)->target_redo[SCpnt->device->id][SCpnt->device->channel] = 0; if (spp->target_status && SCpnt->device->type == TYPE_DISK && (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 && @@ -2305,7 +2313,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { for (c = 0; c <= sh[j]->max_channel; c++) for (k = 0; k < sh[j]->max_id; k++) - HD(j)->target_redo[k][c] = TRUE; + HD(j)->target_redo[k][c] = 1; if (SCpnt->device->type != TYPE_TAPE && HD(j)->retries < MAX_INTERNAL_RETRIES) { @@ -2408,7 +2416,7 @@ static int eata2x_release(struct Scsi_Host *shpnt) { release_region(sh[j]->io_port, sh[j]->n_io_port); scsi_unregister(sh[j]); - return FALSE; + return 0; } #include "scsi_module.c" diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index e2c07fca0..0ee49dc50 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -59,6 +59,8 @@ #include #include #include +#include + #include #include @@ -511,8 +513,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd) HD(cmd)->state = RESET; spin_unlock_irq(host->host_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3 * HZ); + msleep(3000); spin_lock_irq(host->host_lock); DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit)); diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h index 85beb4750..73f7d6968 100644 --- a/drivers/scsi/esp.h +++ b/drivers/scsi/esp.h @@ -77,8 +77,8 @@ struct scsi_cmnd; /* We get one of these for each ESP probed. */ struct esp { - unsigned long eregs; /* ESP controller registers */ - unsigned long dregs; /* DMA controller registers */ + void __iomem *eregs; /* ESP controller registers */ + void __iomem *dregs; /* DMA controller registers */ struct sbus_dma *dma; /* DMA controller sw state */ struct Scsi_Host *ehost; /* Backpointer to SCSI Host */ struct sbus_dev *sdev; /* Pointer to SBus entry */ diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index 763e33b13..32e0cd597 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -78,6 +78,7 @@ **************************************************************************/ #include +#include #include #include #include @@ -288,7 +289,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs); static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 }; static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; -static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; +static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; /* host information */ static int found = 0; @@ -297,16 +298,20 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; static int user_fifo_count = 0; static int user_fifo_size = 0; -static void fd_mcs_setup(char *str, int *ints) +static int __init fd_mcs_setup(char *str) { static int done_setup = 0; + int ints[3]; + get_options(str, 3, ints); if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) { printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n"); + return 0; } user_fifo_count = ints[0] >= 1 ? ints[1] : 0; user_fifo_size = ints[0] >= 2 ? ints[2] : 0; + return 1; } __setup("fd_mcs=", fd_mcs_setup); @@ -391,7 +396,7 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt) } else { bios = addresses[pos2 >> 6]; port = ports[(pos2 >> 4) & 0x03]; - irq = ints[(pos2 >> 1) & 0x07]; + irq = interrupts[(pos2 >> 1) & 0x07]; } if (irq) { diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 6529f0c55..075312fcc 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -384,6 +384,7 @@ enum out_port_type { /* .bss will zero all the static variables below */ static int port_base; static unsigned long bios_base; +static void __iomem * bios_mem; static int bios_major; static int bios_minor; static int PCI_bus; @@ -400,20 +401,6 @@ static int setup_called; static volatile int in_interrupt_flag; #endif -static int SCSI_Mode_Cntl_port; -static int FIFO_Data_Count_port; -static int Interrupt_Cntl_port; -static int Interrupt_Status_port; -static int Read_FIFO_port; -static int Read_SCSI_Data_port; -static int SCSI_Cntl_port; -static int SCSI_Data_NoACK_port; -static int SCSI_Status_port; -static int TMC_Cntl_port; -static int TMC_Status_port; -static int Write_FIFO_port; -static int Write_SCSI_Data_port; - static int FIFO_Size = 0x2000; /* 8k FIFO for pre-tmc18c30 chips */ @@ -472,7 +459,7 @@ static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; */ -struct signature { +static struct signature { const char *signature; int sig_offset; int sig_length; @@ -585,12 +572,12 @@ static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ inline static void fdomain_make_bus_idle( void ) { - outb( 0, SCSI_Cntl_port ); - outb( 0, SCSI_Mode_Cntl_port ); + outb(0, port_base + SCSI_Cntl); + outb(0, port_base + SCSI_Mode_Cntl); if (chip == tmc18c50 || chip == tmc18c30) - outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ + outb(0x21 | PARITY_MASK, port_base + TMC_Cntl); /* Clear forced intr. */ else - outb( 0x01 | PARITY_MASK, TMC_Cntl_port ); + outb(0x01 | PARITY_MASK, port_base + TMC_Cntl); } static int fdomain_is_valid_port( int port ) @@ -690,12 +677,15 @@ static int fdomain_isa_detect( int *irq, int *iobase ) printk( "scsi: fdomain_isa_detect:" ); #endif - for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { + for (i = 0; i < ADDRESS_COUNT; i++) { + void __iomem *p = ioremap(addresses[i], 0x2000); + if (!p) + continue; #if DEBUG_DETECT printk( " %lx(%lx),", addresses[i], bios_base ); #endif - for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { - if (isa_check_signature(addresses[i] + signatures[j].sig_offset, + for (j = 0; j < SIGNATURE_COUNT; j++) { + if (check_signature(p + signatures[j].sig_offset, signatures[j].signature, signatures[j].sig_length )) { bios_major = signatures[j].major_bios_version; @@ -703,10 +693,14 @@ static int fdomain_isa_detect( int *irq, int *iobase ) PCI_bus = (signatures[j].flag == 1); Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; bios_base = addresses[i]; + bios_mem = p; + goto found; } } + iounmap(p); } - + +found: if (bios_major == 2) { /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. Assuming the ROM is enabled (otherwise we wouldn't have been @@ -719,13 +713,13 @@ static int fdomain_isa_detect( int *irq, int *iobase ) switch (Quantum) { case 2: /* ISA_200S */ case 3: /* ISA_250MG */ - base = isa_readb(bios_base + 0x1fa2) + (isa_readb(bios_base + 0x1fa3) << 8); + base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8); break; case 4: /* ISA_200S (another one) */ - base = isa_readb(bios_base + 0x1fa3) + (isa_readb(bios_base + 0x1fa4) << 8); + base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8); break; default: - base = isa_readb(bios_base + 0x1fcc) + (isa_readb(bios_base + 0x1fcd) << 8); + base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8); break; } @@ -733,17 +727,20 @@ static int fdomain_isa_detect( int *irq, int *iobase ) printk( " %x,", base ); #endif - for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { - if (base == ports[i]) - ++flag; + for (i = 0; i < PORT_COUNT; i++) { + if (base == ports[i]) { + if (!request_region(base, 0x10, "fdomain")) + break; + if (!fdomain_is_valid_port(base)) { + release_region(base, 0x10); + break; + } + *irq = fdomain_get_irq( base ); + *iobase = base; + return 1; + } } - if (flag && fdomain_is_valid_port( base )) { - *irq = fdomain_get_irq( base ); - *iobase = base; - return 1; - } - /* This is a bad sign. It usually means that someone patched the BIOS signature list (the signatures variable) to contain a BIOS signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ @@ -764,7 +761,7 @@ static int fdomain_isa_detect( int *irq, int *iobase ) for (i = 0; i < PORT_COUNT; i++) { base = ports[i]; - if (check_region( base, 0x10 )) { + if (!request_region(base, 0x10, "fdomain")) { #if DEBUG_DETECT printk( " (%x inuse),", base ); #endif @@ -773,7 +770,10 @@ static int fdomain_isa_detect( int *irq, int *iobase ) #if DEBUG_DETECT printk( " %x,", base ); #endif - if ((flag = fdomain_is_valid_port( base ))) break; + flag = fdomain_is_valid_port(base); + if (flag) + break; + release_region(base, 0x10); } #if DEBUG_DETECT @@ -832,6 +832,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_ pci_base = pci_resource_start(pdev, 0); pci_irq = pdev->irq; + if (!request_region( pci_base, 0x10, "fdomain" )) + return 0; + /* Now we have the I/O base address and interrupt from the PCI configuration registers. */ @@ -844,8 +847,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_ " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base ); #endif - if (!fdomain_is_valid_port( *iobase )) { + if (!fdomain_is_valid_port(pci_base)) { printk(KERN_ERR "scsi: PCI card detected, but driver not loaded (invalid port)\n" ); + release_region(pci_base, 0x10); return 0; } @@ -870,10 +874,16 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", port_base, interrupt_level ); #endif + if (!request_region(port_base, 0x10, "fdomain")) { + printk( "scsi: port 0x%x is busy\n", port_base ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); + return NULL; + } if (!fdomain_is_valid_port( port_base )) { printk( "scsi: Cannot locate chip at port base 0x%x\n", port_base ); printk( "scsi: Bad LILO/INSMOD parameters?\n" ); + release_region(port_base, 0x10); return NULL; } } else { @@ -894,20 +904,6 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) } } - SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; - FIFO_Data_Count_port = port_base + FIFO_Data_Count; - Interrupt_Cntl_port = port_base + Interrupt_Cntl; - Interrupt_Status_port = port_base + Interrupt_Status; - Read_FIFO_port = port_base + Read_FIFO; - Read_SCSI_Data_port = port_base + Read_SCSI_Data; - SCSI_Cntl_port = port_base + SCSI_Cntl; - SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; - SCSI_Status_port = port_base + SCSI_Status; - TMC_Cntl_port = port_base + TMC_Cntl; - TMC_Status_port = port_base + TMC_Status; - Write_FIFO_port = port_base + Write_FIFO; - Write_SCSI_Data_port = port_base + Write_SCSI_Data; - fdomain_16x0_bus_reset(NULL); if (fdomain_test_loopback()) { @@ -915,6 +911,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) if (setup_called) { printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); } + release_region(port_base, 0x10); return NULL; } @@ -935,8 +932,10 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) get resources. */ shpnt = scsi_register( tpnt, 0 ); - if(shpnt == NULL) + if(shpnt == NULL) { + release_region(port_base, 0x10); return NULL; + } shpnt->irq = interrupt_level; shpnt->io_port = port_base; scsi_set_device(shpnt, &pdev->dev); @@ -946,6 +945,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) /* Log IRQ with kernel */ if (!interrupt_level) { printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); + release_region(port_base, 0x10); return NULL; } else { /* Register the IRQ with the kernel */ @@ -967,13 +967,10 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) printk(KERN_ERR " Send mail to faith@acm.org\n" ); } printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); + release_region(port_base, 0x10); return NULL; } } - - /* Log I/O ports with kernel */ - request_region( port_base, 0x10, "fdomain" ); - return shpnt; } @@ -1015,13 +1012,13 @@ static int fdomain_arbitrate( void ) printk( "fdomain_arbitrate()\n" ); #endif - outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ - outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ - outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ + outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */ + outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */ + outb(0x04 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */ timeout = 500; do { - status = inb( TMC_Status_port ); /* Read adapter status */ + status = inb(port_base + TMC_Status); /* Read adapter status */ if (status & 0x02) /* Arbitration complete */ return 0; mdelay(1); /* Wait one millisecond */ @@ -1048,19 +1045,19 @@ static int fdomain_select( int target ) static int flag = 0; #endif - outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ - outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); + outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */ + outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK); /* Stop arbitration and enable parity */ - outb( PARITY_MASK, TMC_Cntl_port ); + outb(PARITY_MASK, port_base + TMC_Cntl); timeout = 350; /* 350 msec */ do { - status = inb( SCSI_Status_port ); /* Read adapter status */ + status = inb(port_base + SCSI_Status); /* Read adapter status */ if (status & 1) { /* Busy asserted */ /* Enable SCSI Bus (on error, should make bus idle with 0) */ - outb( 0x80, SCSI_Cntl_port ); + outb(0x80, port_base + SCSI_Cntl); return 0; } mdelay(1); /* wait one msec */ @@ -1085,7 +1082,7 @@ static void my_done(int error) { if (in_command) { in_command = 0; - outb( 0x00, Interrupt_Cntl_port ); + outb(0x00, port_base + Interrupt_Cntl); fdomain_make_bus_idle(); current_SC->result = error; if (current_SC->scsi_done) @@ -1114,11 +1111,11 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, running. */ /* Check for other IRQ sources */ - if((inb(TMC_Status_port)&0x01)==0) + if ((inb(port_base + TMC_Status) & 0x01) == 0) return IRQ_NONE; /* It is our IRQ */ - outb( 0x00, Interrupt_Cntl_port ); + outb(0x00, port_base + Interrupt_Cntl); /* We usually have one spurious interrupt after each command. Ignore it. */ if (!in_command || !current_SC) { /* Spurious interrupt */ @@ -1143,7 +1140,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, #endif if (current_SC->SCp.phase & in_arbitration) { - status = inb( TMC_Status_port ); /* Read adapter status */ + status = inb(port_base + TMC_Status); /* Read adapter status */ if (!(status & 0x02)) { #if EVERY_ACCESS printk( " AFAIL " ); @@ -1155,19 +1152,19 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, } current_SC->SCp.phase = in_selection; - outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); + outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl); - outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ - outb( adapter_mask | (1 << current_SC->device->id), SCSI_Data_NoACK_port ); + outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */ + outb(adapter_mask | (1 << current_SC->device->id), port_base + SCSI_Data_NoACK); /* Stop arbitration and enable parity */ - outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); + outb(0x10 | PARITY_MASK, port_base + TMC_Cntl); #if DEBUG_RACE in_interrupt_flag = 0; #endif return IRQ_HANDLED; } else if (current_SC->SCp.phase & in_selection) { - status = inb( SCSI_Status_port ); + status = inb(port_base + SCSI_Status); if (!(status & 0x01)) { /* Try again, for slow devices */ if (fdomain_select( current_SC->device->id )) { @@ -1183,12 +1180,12 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, printk( " AltSel " ); #endif /* Stop arbitration and enable parity */ - outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); + outb(0x10 | PARITY_MASK, port_base + TMC_Cntl); } } current_SC->SCp.phase = in_other; - outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); - outb( 0x80, SCSI_Cntl_port ); + outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl); + outb(0x80, port_base + SCSI_Cntl); #if DEBUG_RACE in_interrupt_flag = 0; #endif @@ -1197,15 +1194,15 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, /* current_SC->SCp.phase == in_other: this is the body of the routine */ - status = inb( SCSI_Status_port ); + status = inb(port_base + SCSI_Status); if (status & 0x10) { /* REQ */ switch (status & 0x0e) { case 0x08: /* COMMAND OUT */ - outb( current_SC->cmnd[current_SC->SCp.sent_command++], - Write_SCSI_Data_port ); + outb(current_SC->cmnd[current_SC->SCp.sent_command++], + port_base + Write_SCSI_Data); #if EVERY_ACCESS printk( "CMD = %x,", current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); @@ -1214,17 +1211,17 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ if (chip != tmc1800 && !current_SC->SCp.have_data_in) { current_SC->SCp.have_data_in = -1; - outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl); } break; case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ if (chip != tmc1800 && !current_SC->SCp.have_data_in) { current_SC->SCp.have_data_in = 1; - outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + outb(0x90 | PARITY_MASK, port_base + TMC_Cntl); } break; case 0x0c: /* STATUS IN */ - current_SC->SCp.Status = inb( Read_SCSI_Data_port ); + current_SC->SCp.Status = inb(port_base + Read_SCSI_Data); #if EVERY_ACCESS printk( "Status = %x, ", current_SC->SCp.Status ); #endif @@ -1240,10 +1237,10 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, #endif break; case 0x0a: /* MESSAGE OUT */ - outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ + outb(MESSAGE_REJECT, port_base + Write_SCSI_Data); /* Reject */ break; case 0x0e: /* MESSAGE IN */ - current_SC->SCp.Message = inb( Read_SCSI_Data_port ); + current_SC->SCp.Message = inb(port_base + Read_SCSI_Data); #if EVERY_ACCESS printk( "Message = %x, ", current_SC->SCp.Message ); #endif @@ -1264,17 +1261,17 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, if(current_SC->sc_data_direction == DMA_TO_DEVICE) { current_SC->SCp.have_data_in = -1; - outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl); } else { current_SC->SCp.have_data_in = 1; - outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + outb(0x90 | PARITY_MASK, port_base + TMC_Cntl); } } if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ - while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) { + while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) { #if EVERY_ACCESS printk( "DC=%d, ", data_count ) ; #endif @@ -1285,11 +1282,11 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, printk( "%d OUT, ", data_count ); #endif if (data_count == 1) { - outb( *current_SC->SCp.ptr++, Write_FIFO_port ); + outb(*current_SC->SCp.ptr++, port_base + Write_FIFO); --current_SC->SCp.this_residual; } else { data_count >>= 1; - outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count ); + outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count); current_SC->SCp.ptr += 2 * data_count; current_SC->SCp.this_residual -= 2 * data_count; } @@ -1307,7 +1304,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, } if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ - while ((data_count = inw( FIFO_Data_Count_port )) > 0) { + while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) { #if EVERY_ACCESS printk( "DC=%d, ", data_count ); #endif @@ -1318,11 +1315,11 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, printk( "%d IN, ", data_count ); #endif if (data_count == 1) { - *current_SC->SCp.ptr++ = inb( Read_FIFO_port ); + *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO); --current_SC->SCp.this_residual; } else { data_count >>= 1; /* Number of words */ - insw( Read_FIFO_port, current_SC->SCp.ptr, data_count ); + insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count); current_SC->SCp.ptr += 2 * data_count; current_SC->SCp.this_residual -= 2 * data_count; } @@ -1382,10 +1379,10 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id, } else { if (current_SC->SCp.phase & disconnect) { - outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port ); - outb( 0x00, SCSI_Cntl_port ); + outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl); + outb(0x00, port_base + SCSI_Cntl); } else { - outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); + outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl); } } #if DEBUG_RACE @@ -1436,12 +1433,12 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt, current_SC->SCp.phase = in_arbitration; /* Start arbitration */ - outb( 0x00, Interrupt_Cntl_port ); - outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ - outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */ + outb(0x00, port_base + Interrupt_Cntl); + outb(0x00, port_base + SCSI_Cntl); /* Disable data drivers */ + outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */ ++in_command; - outb( 0x20, Interrupt_Cntl_port ); - outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ + outb(0x20, port_base + Interrupt_Cntl); + outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */ return 0; } @@ -1497,17 +1494,17 @@ static void print_info(struct scsi_cmnd *SCpnt) printk( " (masked)" ); printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); - printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) ); - printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) ); - if (inb( TMC_Status_port & 1)) + printk( "SCSI Status = 0x%02x\n", inb(port_base + SCSI_Status)); + printk( "TMC Status = 0x%02x", inb(port_base + TMC_Status)); + if (inb((port_base + TMC_Status) & 1)) printk( " (interrupt)" ); printk( "\n" ); - printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) ); - if (inb( Interrupt_Status_port ) & 0x08) + printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status)); + if (inb(port_base + Interrupt_Status) & 0x08) printk( " (enabled)" ); printk( "\n" ); if (chip == tmc18c50 || chip == tmc18c30) { - printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) ); + printk("FIFO Status = 0x%02x\n", inb(port_base + FIFO_Status)); printk( "Int. Condition = 0x%02x\n", inb( port_base + Interrupt_Cond ) ); } @@ -1546,12 +1543,12 @@ static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt) int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt) { - outb( 1, SCSI_Cntl_port ); + outb(1, port_base + SCSI_Cntl); do_pause( 2 ); - outb( 0, SCSI_Cntl_port ); + outb(0, port_base + SCSI_Cntl); do_pause( 115 ); - outb( 0, SCSI_Mode_Cntl_port ); - outb( PARITY_MASK, TMC_Cntl_port ); + outb(0, port_base + SCSI_Mode_Cntl); + outb(PARITY_MASK, port_base + TMC_Cntl); return SUCCESS; } @@ -1622,26 +1619,26 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev, case 2: /* ISA_200S */ /* The value of 25 has never been verified. It should probably be 15. */ - offset = bios_base + 0x1f33 + drive * 25; + offset = 0x1f33 + drive * 25; break; case 3: /* ISA_250MG */ - offset = bios_base + 0x1f36 + drive * 15; + offset = 0x1f36 + drive * 15; break; case 4: /* ISA_200S (another one) */ - offset = bios_base + 0x1f34 + drive * 15; + offset = 0x1f34 + drive * 15; break; default: - offset = bios_base + 0x1f31 + drive * 25; + offset = 0x1f31 + drive * 25; break; } - isa_memcpy_fromio( &i, offset, sizeof( struct drive_info ) ); + memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) ); info_array[0] = i.heads; info_array[1] = i.sectors; info_array[2] = i.cylinders; } else if (bios_major == 3 && bios_minor >= 0 && bios_minor < 4) { /* 3.0 and 3.2 BIOS */ - memcpy_fromio( &i, bios_base + 0x1f71 + drive * 10, + memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10, sizeof( struct drive_info ) ); info_array[0] = i.heads + 1; info_array[1] = i.sectors; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index bcf97ec03..9c1f8cc4d 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -501,6 +501,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) { NCR5380_local_declare(); NCR5380_setup(instance); + + if (instance->irq != SCSI_IRQ_NONE) + free_irq(instance->irq, NULL); + NCR5380_exit(instance); #ifndef CONFIG_SCSI_G_NCR5380_MEM release_region(instance->NCR5380_instance_name, instance->n_io_port); @@ -508,8 +512,6 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); #endif - if (instance->irq != SCSI_IRQ_NONE) - free_irq(instance->irq, NULL); return 0; } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 6cb8fa2bd..df28e91a6 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -571,12 +571,12 @@ static struct timer_list gdth_timer; #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) +#define gdth_readb(addr) readb(addr) +#define gdth_readw(addr) readw(addr) +#define gdth_readl(addr) readl(addr) +#define gdth_writeb(b,addr) writeb((b),(addr)) +#define gdth_writew(b,addr) writew((b),(addr)) +#define gdth_writel(b,addr) writel((b),(addr)) static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ @@ -618,9 +618,6 @@ static unchar gdth_direction_tab[0x100] = { }; /* __initfunc, __initdata macros */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define __devinitdata -#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #define GDTH_INITFUNC(type, func) type __init func #include @@ -778,7 +775,7 @@ GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr)) GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr)) { - void *addr; + void __iomem *addr; ulong32 id; TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); @@ -1053,7 +1050,7 @@ GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)) GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) { - register gdt2_dpram_str *dp2_ptr; + register gdt2_dpram_str __iomem *dp2_ptr; int i; unchar irq_drq,prot_ver; ulong32 retries; @@ -1065,10 +1062,10 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); return 0; } - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ - memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); + memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u)); if (gdth_readl(&dp2_ptr->u) != 0) { printk("GDT-ISA: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); @@ -1153,9 +1150,9 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) { - register gdt6_dpram_str *dp6_ptr; - register gdt6c_dpram_str *dp6c_ptr; - register gdt6m_dpram_str *dp6m_ptr; + register gdt6_dpram_str __iomem *dp6_ptr; + register gdt6c_dpram_str __iomem *dp6c_ptr; + register gdt6m_dpram_str __iomem *dp6m_ptr; ulong32 retries; unchar prot_ver; ushort command; @@ -1183,7 +1180,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) return 0; } /* check and reset interface area */ - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", @@ -1208,7 +1205,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1222,7 +1219,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) return 0; } } - memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); + memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u)); if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); @@ -1293,7 +1290,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) return 0; } /* check and reset interface area */ - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", @@ -1318,7 +1315,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1332,7 +1329,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) return 0; } } - memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); + memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u)); if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); @@ -1428,13 +1425,14 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) pcistr->pdev->rom_address); #endif + dp6m_ptr = ha->brd; + /* Ensure that it is safe to access the non HW portions of DPMEM. * Aditional check needed for Xscale based RAID controllers */ - while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 ) + while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) gdth_delay(1); /* check and reset interface area */ - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", @@ -1459,7 +1457,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); @@ -1473,7 +1471,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) return 0; } } - memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u)); + memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u)); /* disable board interrupts, deinit services */ gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, @@ -1556,9 +1554,9 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum)) { gdth_ha_str *ha; ulong flags; - gdt2_dpram_str *dp2_ptr; - gdt6_dpram_str *dp6_ptr; - gdt6m_dpram_str *dp6m_ptr; + gdt2_dpram_str __iomem *dp2_ptr; + gdt6_dpram_str __iomem *dp6_ptr; + gdt6m_dpram_str __iomem *dp6m_ptr; TRACE(("gdth_enable_int() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); @@ -1569,12 +1567,12 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum)) outb(0xff, ha->bmic + EDENABREG); outb(0x01, ha->bmic + EINTENABREG); } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writeb(1, &dp2_ptr->io.irqdel); gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); gdth_writeb(1, &dp2_ptr->io.irqen); } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writeb(1, &dp6_ptr->io.irqdel); gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); gdth_writeb(1, &dp6_ptr->io.irqen); @@ -1582,7 +1580,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum)) outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x03, PTR2USHORT(&ha->plx->control1)); } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, &dp6m_ptr->i960r.edoor_en_reg); @@ -1608,15 +1606,15 @@ static int gdth_get_status(unchar *pIStatus,int irq) *pIStatus = inb((ushort)ha->bmic + EDOORREG); else if (ha->type == GDT_ISA) *pIStatus = - gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index); + gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCI) *pIStatus = - gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index); + gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCINEW) *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); else if (ha->type == GDT_PCIMPR) *pIStatus = - gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg); + gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); if (*pIStatus) return i; /* board found */ @@ -1636,14 +1634,14 @@ static int gdth_test_busy(int hanum) if (ha->type == GDT_EISA) gdtsema0 = (int)inb(ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) - gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) - gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCINEW) gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg)); else if (ha->type == GDT_PCIMPR) gdtsema0 = - (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); return (gdtsema0 & 1); } @@ -1679,13 +1677,13 @@ static void gdth_set_sema0(int hanum) if (ha->type == GDT_EISA) { outb(1, ha->bmic + SEMA0REG); } else if (ha->type == GDT_ISA) { - gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); + gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCI) { - gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); + gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->sema0_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); } } @@ -1694,10 +1692,10 @@ static void gdth_copy_command(int hanum) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; - register gdt6m_dpram_str *dp6m_ptr; - register gdt6c_dpram_str *dp6c_ptr; - gdt6_dpram_str *dp6_ptr; - gdt2_dpram_str *dp2_ptr; + register gdt6m_dpram_str __iomem *dp6m_ptr; + register gdt6c_dpram_str __iomem *dp6c_ptr; + gdt6_dpram_str __iomem *dp6_ptr; + gdt2_dpram_str __iomem *dp2_ptr; ushort cp_count,dp_offset,cmd_no; TRACE(("gdth_copy_command() hanum %d\n",hanum)); @@ -1720,28 +1718,28 @@ static void gdth_copy_command(int hanum) /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp2_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCINEW) { - dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + dp6c_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); gdth_writew((ushort)cmd_ptr->Service, @@ -1780,13 +1778,13 @@ static void gdth_release_event(int hanum) outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { - gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); + gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCI) { - gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event); + gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->ldoor_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); } } @@ -3419,7 +3417,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, /* no GDTH_LOCK_HA() ! */ TRACE2(("gdth_store_event() source %d idx %d\n", source, idx)); if (source == 0) /* no source -> no event */ - return 0; + return NULL; if (ebuffer[elastidx].event_source == source && ebuffer[elastidx].event_idx == idx && @@ -3538,9 +3536,9 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) #endif { register gdth_ha_str *ha; - gdt6m_dpram_str *dp6m_ptr = NULL; - gdt6_dpram_str *dp6_ptr; - gdt2_dpram_str *dp2_ptr; + gdt6m_dpram_str __iomem *dp6m_ptr = NULL; + gdt6_dpram_str __iomem *dp6_ptr; + gdt2_dpram_str __iomem *dp2_ptr; Scsi_Cmnd *scp; int hanum, rval, i; unchar IStatus; @@ -3619,7 +3617,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; + dp2_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; ha->status = gdth_readw(&dp2_ptr->u.ic.Status); @@ -3634,7 +3632,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; + dp6_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; ha->status = gdth_readw(&dp6_ptr->u.ic.Status); @@ -3662,7 +3660,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + dp6m_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; #ifdef INT_COAL @@ -3692,10 +3690,10 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) if (ha->service != SCREENSERVICE && (ha->fw_vers & 0xff) >= 0x1a) { ha->dvr.severity = gdth_readb - (&((gdt6m_dpram_str *)ha->brd)->i960r.severity); + (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity); for (i = 0; i < 256; ++i) { ha->dvr.event_string[i] = gdth_readb - (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); + (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]); if (ha->dvr.event_string[i] == 0) break; } diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 78a93cbac..bf269f05e 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -868,7 +868,7 @@ typedef struct { ushort raw_feat; /* feat. raw service (s/g,..)*/ ushort screen_feat; /* feat. raw service (s/g,..)*/ ushort bmic; /* BMIC address (EISA) */ - void *brd; /* DPRAM address */ + void __iomem *brd; /* DPRAM address */ ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ gdth_cmd_str *pccb; /* address command structure */ diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 12c5245c2..6b2fd2e70 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -50,11 +50,6 @@ static struct class shost_class = { .release = scsi_host_cls_release, }; -static int scsi_device_cancel_cb(struct device *dev, void *data) -{ - return scsi_device_cancel(to_scsi_device(dev), *(int *)data); -} - /** * scsi_host_cancel - cancel outstanding IO to this host * @shost: pointer to struct Scsi_Host @@ -62,9 +57,12 @@ static int scsi_device_cancel_cb(struct device *dev, void *data) **/ void scsi_host_cancel(struct Scsi_Host *shost, int recovery) { + struct scsi_device *sdev; + set_bit(SHOST_CANCEL, &shost->shost_state); - device_for_each_child(&shost->shost_gendev, &recovery, - scsi_device_cancel_cb); + shost_for_each_device(sdev, shost) { + scsi_device_cancel(sdev, recovery); + } wait_event(shost->host_wait, (!test_bit(SHOST_RECOVERY, &shost->shost_state))); } @@ -75,13 +73,15 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery) **/ void scsi_remove_host(struct Scsi_Host *shost) { + scsi_forget_host(shost); scsi_host_cancel(shost, 0); scsi_proc_host_rm(shost); - scsi_forget_host(shost); set_bit(SHOST_DEL, &shost->shost_state); class_device_unregister(&shost->shost_classdev); + if (shost->transport_classdev.class) + class_device_unregister(&shost->transport_classdev); device_del(&shost->shost_gendev); } @@ -96,7 +96,7 @@ void scsi_remove_host(struct Scsi_Host *shost) int scsi_add_host(struct Scsi_Host *shost, struct device *dev) { struct scsi_host_template *sht = shost->hostt; - int error; + int error = -EINVAL; printk(KERN_INFO "scsi%d : %s\n", shost->host_no, sht->info ? sht->info(shost) : sht->name); @@ -104,7 +104,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) if (!shost->can_queue) { printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", sht->name); - return -EINVAL; + goto out; } if (!shost->shost_gendev.parent) @@ -123,6 +123,14 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) get_device(&shost->shost_gendev); + if (shost->transportt->host_size && + (shost->shost_data = kmalloc(shost->transportt->host_size, + GFP_KERNEL)) == NULL) + goto out_del_classdev; + + if (shost->transportt->host_setup) + shost->transportt->host_setup(shost); + error = scsi_sysfs_add_host(shost); if (error) goto out_del_classdev; @@ -154,6 +162,7 @@ static void scsi_host_dev_release(struct device *dev) scsi_proc_hostdir_rm(shost->hostt); scsi_destroy_command_freelist(shost); + kfree(shost->shost_data); /* * Some drivers (eg aha1542) do scsi_register()/scsi_unregister() @@ -221,10 +230,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->max_id = 8; shost->max_lun = 8; - /* Give each shost a default transportt if the driver - * doesn't yet support Transport Attributes */ - if (!shost->transportt) - shost->transportt = &blank_transport_template; + /* Give each shost a default transportt */ + shost->transportt = &blank_transport_template; /* * All drivers right now should be able to handle 12 byte @@ -284,6 +291,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) goto fail_destroy_freelist; wait_for_completion(&complete); shost->eh_notify = NULL; + scsi_proc_hostdir_add(shost->hostt); return shost; diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index b4e82654e..50cb909f3 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -204,7 +204,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, } queue->cur = 0; - queue->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&queue->lock); tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task, (unsigned long)hostdata); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 4f2a284c2..f12a58702 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -45,13 +45,17 @@ #include #include #include +#include #include #include #include -#include "scsi.h" +#include +#include +#include #include +#include #include #define IDESCSI_DEBUG_LOG 0 @@ -66,8 +70,8 @@ typedef struct idescsi_pc_s { u8 *current_position; /* Pointer into the above buffer */ struct scatterlist *sg; /* Scatter gather table */ int b_count; /* Bytes transferred from current entry */ - Scsi_Cmnd *scsi_cmd; /* SCSI command */ - void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ + struct scsi_cmnd *scsi_cmd; /* SCSI command */ + void (*done)(struct scsi_cmnd *); /* Scsi completion routine */ unsigned long flags; /* Status/Action flags */ unsigned long timeout; /* Command timeout */ } idescsi_pc_t; @@ -250,17 +254,6 @@ static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc) kfree(atapi_buf); } -static inline void idescsi_free_bio (struct bio *bio) -{ - struct bio *bhp; - - while (bio) { - bhp = bio; - bio = bio->bi_next; - bio_put(bhp); - } -} - static void hexdump(u8 *x, int len) { int i; @@ -418,7 +411,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) spin_lock_irqsave(host->host_lock, flags); pc->done(pc->scsi_cmd); spin_unlock_irqrestore(host->host_lock, flags); - idescsi_free_bio(rq->bio); kfree(pc); kfree(rq); scsi->pc = NULL; @@ -552,6 +544,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; idescsi_scsi_t *scsi = drive_to_idescsi(drive); idescsi_pc_t *pc = scsi->pc; atapi_ireason_t ireason; @@ -576,20 +569,64 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) atapi_output_bytes(drive, scsi->pc->c, 12); if (test_bit (PC_DMA_OK, &pc->flags)) { set_bit (PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); + hwif->dma_start(drive); } return ide_started; } +static inline int idescsi_set_direction(idescsi_pc_t *pc) +{ + switch (pc->c[0]) { + case READ_6: case READ_10: case READ_12: + clear_bit(PC_WRITING, &pc->flags); + return 0; + case WRITE_6: case WRITE_10: case WRITE_12: + set_bit(PC_WRITING, &pc->flags); + return 0; + default: + return 1; + } +} + +static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc) +{ + ide_hwif_t *hwif = drive->hwif; + struct scatterlist *sg, *scsi_sg; + int segments; + + if (!pc->request_transfer || pc->request_transfer % 1024) + return 1; + + if (idescsi_set_direction(pc)) + return 1; + + sg = hwif->sg_table; + scsi_sg = pc->scsi_cmd->request_buffer; + segments = pc->scsi_cmd->use_sg; + + if (segments > hwif->sg_max_nents) + return 1; + + if (!segments) { + hwif->sg_nents = 1; + sg_init_one(sg, pc->scsi_cmd->request_buffer, pc->request_transfer); + } else { + hwif->sg_nents = segments; + memcpy(sg, scsi_sg, sizeof(*sg) * segments); + } + + return 0; +} + /* * Issue a packet command */ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); + ide_hwif_t *hwif = drive->hwif; atapi_feature_t feature; atapi_bcount_t bcount; - struct request *rq = pc->rq; scsi->pc=pc; /* Set the current packet command */ pc->actually_transferred=0; /* We haven't transferred any data yet */ @@ -597,11 +634,10 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) bcount.all = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ feature.all = 0; - if (drive->using_dma && rq->bio) { - if (test_bit(PC_WRITING, &pc->flags)) - feature.b.dma = !HWIF(drive)->ide_dma_write(drive); - else - feature.b.dma = !HWIF(drive)->ide_dma_read(drive); + if (drive->using_dma && !idescsi_map_sg(drive, pc)) { + hwif->sg_mapped = 1; + feature.b.dma = !hwif->dma_setup(drive); + hwif->sg_mapped = 0; } SELECT_DRIVE(drive); @@ -747,7 +783,7 @@ static struct block_device_operations idescsi_ops = { static int idescsi_attach(ide_drive_t *drive); -static int idescsi_slave_configure(Scsi_Device * sdp) +static int idescsi_slave_configure(struct scsi_device * sdp) { /* Configure detected device */ scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun); @@ -759,7 +795,7 @@ static const char *idescsi_info (struct Scsi_Host *host) return "SCSI host adapter emulation for IDE ATAPI devices"; } -static int idescsi_ioctl (Scsi_Device *dev, int cmd, void __user *arg) +static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg) { idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host); @@ -774,82 +810,7 @@ static int idescsi_ioctl (Scsi_Device *dev, int cmd, void __user *arg) return -EINVAL; } -static inline struct bio *idescsi_kmalloc_bio (int count) -{ - struct bio *bh, *bhp, *first_bh; - - if ((first_bh = bhp = bh = bio_alloc(GFP_ATOMIC, 1)) == NULL) - goto abort; - bio_init(bh); - bh->bi_vcnt = 1; - while (--count) { - if ((bh = bio_alloc(GFP_ATOMIC, 1)) == NULL) - goto abort; - bio_init(bh); - bh->bi_vcnt = 1; - bhp->bi_next = bh; - bhp = bh; - bh->bi_next = NULL; - } - return first_bh; -abort: - idescsi_free_bio (first_bh); - return NULL; -} - -static inline int idescsi_set_direction (idescsi_pc_t *pc) -{ - switch (pc->c[0]) { - case READ_6: case READ_10: case READ_12: - clear_bit (PC_WRITING, &pc->flags); - return 0; - case WRITE_6: case WRITE_10: case WRITE_12: - set_bit (PC_WRITING, &pc->flags); - return 0; - default: - return 1; - } -} - -static inline struct bio *idescsi_dma_bio(ide_drive_t *drive, idescsi_pc_t *pc) -{ - struct bio *bh = NULL, *first_bh = NULL; - int segments = pc->scsi_cmd->use_sg; - struct scatterlist *sg = pc->scsi_cmd->request_buffer; - - if (!drive->using_dma || !pc->request_transfer || pc->request_transfer % 1024) - return NULL; - if (idescsi_set_direction(pc)) - return NULL; - if (segments) { - if ((first_bh = bh = idescsi_kmalloc_bio (segments)) == NULL) - return NULL; -#if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10); -#endif /* IDESCSI_DEBUG_LOG */ - while (segments--) { - bh->bi_io_vec[0].bv_page = sg->page; - bh->bi_io_vec[0].bv_len = sg->length; - bh->bi_io_vec[0].bv_offset = sg->offset; - bh->bi_size = sg->length; - bh = bh->bi_next; - sg++; - } - } else { - if ((first_bh = bh = idescsi_kmalloc_bio (1)) == NULL) - return NULL; -#if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10); -#endif /* IDESCSI_DEBUG_LOG */ - bh->bi_io_vec[0].bv_page = virt_to_page(pc->scsi_cmd->request_buffer); - bh->bi_io_vec[0].bv_offset = offset_in_page(pc->scsi_cmd->request_buffer); - bh->bi_io_vec[0].bv_len = pc->request_transfer; - bh->bi_size = pc->request_transfer; - } - return first_bh; -} - -static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd) +static inline int should_transform(ide_drive_t *drive, struct scsi_cmnd *cmd) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); @@ -867,7 +828,8 @@ static inline int should_transform(ide_drive_t *drive, Scsi_Cmnd *cmd) return test_bit(IDESCSI_TRANSFORM, &scsi->transform); } -static int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +static int idescsi_queue (struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { struct Scsi_Host *host = cmd->device->host; idescsi_scsi_t *scsi = scsihost_to_idescsi(host); @@ -919,7 +881,6 @@ static int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ide_init_drive_cmd (rq); rq->special = (char *) pc; - rq->bio = idescsi_dma_bio (drive, pc); rq->flags = REQ_SPECIAL; spin_unlock_irq(host->host_lock); (void) ide_do_drive_cmd (drive, rq, ide_end); @@ -930,10 +891,10 @@ abort: if (rq) kfree (rq); cmd->result = DID_ERROR << 16; done(cmd); - return 1; + return 0; } -static int idescsi_eh_abort (Scsi_Cmnd *cmd) +static int idescsi_eh_abort (struct scsi_cmnd *cmd) { idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); ide_drive_t *drive = scsi->drive; @@ -973,7 +934,6 @@ static int idescsi_eh_abort (Scsi_Cmnd *cmd) */ printk (KERN_ERR "ide-scsi: cmd aborted!\n"); - idescsi_free_bio(scsi->pc->rq->bio); if (scsi->pc->rq->flags & REQ_SENSE) kfree(scsi->pc->buffer); kfree(scsi->pc->rq); @@ -992,7 +952,7 @@ no_drive: return ret; } -static int idescsi_eh_reset (Scsi_Cmnd *cmd) +static int idescsi_eh_reset (struct scsi_cmnd *cmd) { struct request *req; idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); @@ -1022,7 +982,6 @@ static int idescsi_eh_reset (Scsi_Cmnd *cmd) /* kill current request */ blkdev_dequeue_request(req); end_that_request_last(req); - idescsi_free_bio(req->bio); if (req->flags & REQ_SENSE) kfree(scsi->pc->buffer); kfree(scsi->pc); @@ -1075,7 +1034,7 @@ static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev, return 0; } -static Scsi_Host_Template idescsi_template = { +static struct scsi_host_template idescsi_template = { .module = THIS_MODULE, .name = "idescsi", .info = idescsi_info, diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 915d593fb..1a5c91042 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -758,7 +758,7 @@ static void imm_interrupt(void *data) case DID_OK: break; case DID_NO_CONNECT: - printk("imm: no device at SCSI ID %i\n", cmd->target); + printk("imm: no device at SCSI ID %i\n", cmd->device->id); break; case DID_BUS_BUSY: printk("imm: BUS BUSY - EPP timeout detected\n"); @@ -1140,6 +1140,10 @@ static struct scsi_host_template imm_template = { .use_clustering = ENABLE_CLUSTERING, .can_queue = 1, .slave_alloc = imm_adjust_queue, + .unchecked_isa_dma = 1, /* imm cannot deal with highmem, so + * this is an easy trick to ensure + * all io pages for this host reside + * in low memory */ }; /*************************************************************************** diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index bf3942769..923dcf98f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1,7 +1,7 @@ /* * ipr.c -- driver for IBM Power Linux RAID adapters * - * Written By: Brian King, IBM Corporation + * Written By: Brian King , IBM Corporation * * Copyright (C) 2003, 2004 IBM Corporation * @@ -93,7 +93,7 @@ static spinlock_t ipr_driver_lock = SPIN_LOCK_UNLOCKED; /* This table describes the differences between DMA controller chips */ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { - { /* Gemstone */ + { /* Gemstone and Citrine */ .mailbox = 0x0042C, .cache_line_size = 0x20, { @@ -208,6 +208,8 @@ struct ipr_error_table_t ipr_error_table[] = { "Synchronization required"}, {0x024E0000, 0, 0, "No ready, IOA shutdown"}, + {0x025A0000, 0, 0, + "Not ready, IOA has been shutdown"}, {0x02670100, 0, 1, "3020: Storage subsystem configuration error"}, {0x03110B00, 0, 0, @@ -880,11 +882,13 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) **/ static void ipr_log_vpd(struct ipr_std_inq_vpids *vpids, u8 *serial_num) { - char buffer[max_t(int, sizeof(struct ipr_std_inq_vpids), - IPR_SERIAL_NUM_LEN) + 1]; + char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + + IPR_SERIAL_NUM_LEN]; - memcpy(buffer, vpids, sizeof(struct ipr_std_inq_vpids)); - buffer[sizeof(struct ipr_std_inq_vpids)] = '\0'; + memcpy(buffer, vpids->vendor_id, IPR_VENDOR_ID_LEN); + memcpy(buffer + IPR_VENDOR_ID_LEN, vpids->product_id, + IPR_PROD_ID_LEN); + buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN] = '\0'; ipr_err("Vendor/Product ID: %s\n", buffer); memcpy(buffer, serial_num, IPR_SERIAL_NUM_LEN); @@ -1765,6 +1769,33 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump) #define ipr_get_ioa_dump(ioa_cfg, dump) do { } while(0) #endif +/** + * ipr_release_dump - Free adapter dump memory + * @kref: kref struct + * + * Return value: + * nothing + **/ +static void ipr_release_dump(struct kref *kref) +{ + struct ipr_dump *dump = container_of(kref,struct ipr_dump,kref); + struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg; + unsigned long lock_flags = 0; + int i; + + ENTER; + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + ioa_cfg->dump = NULL; + ioa_cfg->sdt_state = INACTIVE; + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + + for (i = 0; i < dump->ioa_dump.next_page_index; i++) + free_page((unsigned long) dump->ioa_dump.ioa_data[i]); + + kfree(dump); + LEAVE; +} + /** * ipr_worker_thread - Worker thread * @data: ioa config struct @@ -1791,13 +1822,14 @@ static void ipr_worker_thread(void *data) if (ioa_cfg->sdt_state == GET_DUMP) { dump = ioa_cfg->dump; - if (!dump || !kobject_get(&dump->kobj)) { + if (!dump) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return; } + kref_get(&dump->kref); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); ipr_get_ioa_dump(ioa_cfg, dump); - kobject_put(&dump->kobj); + kref_put(&dump->kref, ipr_release_dump); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); if (ioa_cfg->sdt_state == DUMP_OBTAINED) @@ -2008,7 +2040,7 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev, wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); /* Wait for a second for any errors to be logged */ - schedule_timeout(HZ); + msleep(1000); } else { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return -EIO; @@ -2392,15 +2424,15 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf, spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); dump = ioa_cfg->dump; - if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump || !kobject_get(&dump->kobj)) { + if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump) { spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return 0; } - + kref_get(&dump->kref); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); if (off > dump->driver_dump.hdr.len) { - kobject_put(&dump->kobj); + kref_put(&dump->kref, ipr_release_dump); return 0; } @@ -2450,41 +2482,10 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf, count -= len; } - kobject_put(&dump->kobj); + kref_put(&dump->kref, ipr_release_dump); return rc; } -/** - * ipr_release_dump - Free adapter dump memory - * @kobj: kobject struct - * - * Return value: - * nothing - **/ -static void ipr_release_dump(struct kobject *kobj) -{ - struct ipr_dump *dump = container_of(kobj,struct ipr_dump,kobj); - struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg; - unsigned long lock_flags = 0; - int i; - - ENTER; - spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - ioa_cfg->dump = NULL; - ioa_cfg->sdt_state = INACTIVE; - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - - for (i = 0; i < dump->ioa_dump.next_page_index; i++) - free_page((unsigned long) dump->ioa_dump.ioa_data[i]); - - kfree(dump); - LEAVE; -} - -static struct kobj_type ipr_dump_kobj_type = { - .release = ipr_release_dump, -}; - /** * ipr_alloc_dump - Prepare for adapter dump * @ioa_cfg: ioa config struct @@ -2506,8 +2507,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) } memset(dump, 0, sizeof(struct ipr_dump)); - kobject_init(&dump->kobj); - dump->kobj.ktype = &ipr_dump_kobj_type; + kref_init(&dump->kref); dump->ioa_cfg = ioa_cfg; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -2554,7 +2554,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) ioa_cfg->dump = NULL; spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - kobject_put(&dump->kobj); + kref_put(&dump->kref, ipr_release_dump); LEAVE; return 0; @@ -2690,8 +2690,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev, struct ipr_resource_entry *res; unsigned long lock_flags = 0; int tcq_active = simple_strtoul(buf, NULL, 10); - int qdepth = IPR_MAX_CMD_PER_LUN; - int tagged = 0; ssize_t len = -ENXIO; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -2699,13 +2697,13 @@ static ssize_t ipr_store_tcq_enable(struct device *dev, res = (struct ipr_resource_entry *)sdev->hostdata; if (res) { - res->tcq_active = 0; - qdepth = res->qdepth; - if (ipr_is_gscsi(res) && sdev->tagged_supported) { if (tcq_active) { - tagged = MSG_ORDERED_TAG; res->tcq_active = 1; + scsi_activate_tcq(sdev, res->qdepth); + } else { + res->tcq_active = 0; + scsi_deactivate_tcq(sdev, res->qdepth); } len = strlen(buf); @@ -2715,7 +2713,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev, } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - scsi_adjust_queue_depth(sdev, tagged, qdepth); return len; } @@ -2785,7 +2782,8 @@ static int ipr_biosparam(struct scsi_device *sdev, struct block_device *block_device, sector_t capacity, int *parm) { - int heads, sectors, cylinders; + int heads, sectors; + sector_t cylinders; heads = 128; sectors = 32; @@ -2849,8 +2847,8 @@ static int ipr_slave_configure(struct scsi_device *sdev) sdev->scsi_level = 4; if (ipr_is_vset_device(res)) sdev->timeout = IPR_VSET_RW_TIMEOUT; - - sdev->allow_restart = 1; + if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) + sdev->allow_restart = 1; scsi_adjust_queue_depth(sdev, 0, res->qdepth); } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); @@ -3080,7 +3078,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) struct ipr_ioa_cfg *ioa_cfg; struct ipr_resource_entry *res; struct ipr_cmd_pkt *cmd_pkt; - u32 ioasc, ioarcb_addr; + u32 ioasc; int op_found = 0; ENTER; @@ -3101,21 +3099,15 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) if (!op_found) return SUCCESS; - ioarcb_addr = be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr); - ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle; cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; cmd_pkt->request_type = IPR_RQTYPE_IOACMD; - cmd_pkt->cdb[0] = IPR_ABORT_TASK; - cmd_pkt->cdb[2] = (ioarcb_addr >> 24) & 0xff; - cmd_pkt->cdb[3] = (ioarcb_addr >> 16) & 0xff; - cmd_pkt->cdb[4] = (ioarcb_addr >> 8) & 0xff; - cmd_pkt->cdb[5] = ioarcb_addr & 0xff; + cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS; ipr_cmd->u.sdev = scsi_cmd->device; ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]); - ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_ABORT_TASK_TIMEOUT); + ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); /* @@ -3737,7 +3729,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, switch (ioasc & IPR_IOASC_IOASC_MASK) { case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST: - scsi_cmd->result |= (DID_ERROR << 16); + scsi_cmd->result |= (DID_IMM_RETRY << 16); break; case IPR_IOASC_IR_RESOURCE_HANDLE: scsi_cmd->result |= (DID_NO_CONNECT << 16); @@ -3873,7 +3865,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, * We have told the host to stop giving us new requests, but * ERP ops don't count. FIXME */ - if (unlikely(!ioa_cfg->allow_cmds)) + if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead)) return SCSI_MLQUEUE_HOST_BUSY; /* @@ -4943,7 +4935,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; - rc = pci_restore_state(ioa_cfg->pdev, ioa_cfg->pci_cfg_buf); + rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); @@ -5437,13 +5429,15 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) **/ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) { + struct pci_dev *pdev = ioa_cfg->pdev; + ENTER; - free_irq(ioa_cfg->pdev->irq, ioa_cfg); - iounmap((void *) ioa_cfg->hdw_dma_regs); - release_mem_region(ioa_cfg->hdw_dma_regs_pci, - pci_resource_len(ioa_cfg->pdev, 0)); + free_irq(pdev->irq, ioa_cfg); + iounmap(ioa_cfg->hdw_dma_regs); + pci_release_regions(pdev); ipr_free_mem(ioa_cfg); scsi_host_put(ioa_cfg->host); + pci_disable_device(pdev); LEAVE; } @@ -5458,7 +5452,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) { struct ipr_cmnd *ipr_cmd; struct ipr_ioarcb *ioarcb; - u32 dma_addr; + dma_addr_t dma_addr; int i; ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev, @@ -5508,14 +5502,15 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) **/ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) { - int i; + struct pci_dev *pdev = ioa_cfg->pdev; + int i, rc = -ENOMEM; ENTER; ioa_cfg->res_entries = kmalloc(sizeof(struct ipr_resource_entry) * IPR_MAX_PHYSICAL_DEVS, GFP_KERNEL); if (!ioa_cfg->res_entries) - goto cleanup; + goto out; memset(ioa_cfg->res_entries, 0, sizeof(struct ipr_resource_entry) * IPR_MAX_PHYSICAL_DEVS); @@ -5528,24 +5523,24 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) &ioa_cfg->vpd_cbs_dma); if (!ioa_cfg->vpd_cbs) - goto cleanup; + goto out_free_res_entries; if (ipr_alloc_cmd_blks(ioa_cfg)) - goto cleanup; + goto out_free_vpd_cbs; ioa_cfg->host_rrq = pci_alloc_consistent(ioa_cfg->pdev, sizeof(u32) * IPR_NUM_CMD_BLKS, &ioa_cfg->host_rrq_dma); if (!ioa_cfg->host_rrq) - goto cleanup; + goto out_ipr_free_cmd_blocks; ioa_cfg->cfg_table = pci_alloc_consistent(ioa_cfg->pdev, sizeof(struct ipr_config_table), &ioa_cfg->cfg_table_dma); if (!ioa_cfg->cfg_table) - goto cleanup; + goto out_free_host_rrq; for (i = 0; i < IPR_NUM_HCAMS; i++) { ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev, @@ -5553,9 +5548,8 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) &ioa_cfg->hostrcb_dma[i]); if (!ioa_cfg->hostrcb[i]) - goto cleanup; + goto out_free_hostrcb_dma; - memset(ioa_cfg->hostrcb[i], 0, sizeof(struct ipr_hostrcb)); ioa_cfg->hostrcb[i]->hostrcb_dma = ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); @@ -5565,19 +5559,35 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) IPR_NUM_TRACE_ENTRIES, GFP_KERNEL); if (!ioa_cfg->trace) - goto cleanup; + goto out_free_hostrcb_dma; memset(ioa_cfg->trace, 0, sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES); + rc = 0; +out: LEAVE; - return 0; - -cleanup: - ipr_free_mem(ioa_cfg); + return rc; - LEAVE; - return -ENOMEM; +out_free_hostrcb_dma: + while (i-- > 0) { + pci_free_consistent(pdev, sizeof(struct ipr_hostrcb), + ioa_cfg->hostrcb[i], + ioa_cfg->hostrcb_dma[i]); + } + pci_free_consistent(pdev, sizeof(struct ipr_config_table), + ioa_cfg->cfg_table, ioa_cfg->cfg_table_dma); +out_free_host_rrq: + pci_free_consistent(pdev, sizeof(u32) * IPR_NUM_CMD_BLKS, + ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma); +out_ipr_free_cmd_blocks: + ipr_free_cmd_blks(ioa_cfg); +out_free_vpd_cbs: + pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs), + ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma); +out_free_res_entries: + kfree(ioa_cfg->res_entries); + goto out; } /** @@ -5614,6 +5624,10 @@ static void __devinit ipr_initialize_bus_attr(struct ipr_ioa_cfg *ioa_cfg) static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, struct Scsi_Host *host, struct pci_dev *pdev) { + const struct ipr_interrupt_offsets *p; + struct ipr_interrupts *t; + void __iomem *base; + ioa_cfg->host = host; ioa_cfg->pdev = pdev; ioa_cfg->log_level = ipr_log_level; @@ -5645,17 +5659,19 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, host->max_cmd_len = IPR_MAX_CDB_LEN; pci_set_drvdata(pdev, ioa_cfg); - memcpy(&ioa_cfg->regs, &ioa_cfg->chip_cfg->regs, sizeof(ioa_cfg->regs)); + p = &ioa_cfg->chip_cfg->regs; + t = &ioa_cfg->regs; + base = ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.set_interrupt_mask_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.clr_interrupt_mask_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.sense_interrupt_mask_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.clr_interrupt_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.sense_interrupt_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.ioarrin_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.sense_uproc_interrupt_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.set_uproc_interrupt_reg += ioa_cfg->hdw_dma_regs; - ioa_cfg->regs.clr_uproc_interrupt_reg += ioa_cfg->hdw_dma_regs; + t->set_interrupt_mask_reg = base + p->set_interrupt_mask_reg; + t->clr_interrupt_mask_reg = base + p->clr_interrupt_mask_reg; + t->sense_interrupt_mask_reg = base + p->sense_interrupt_mask_reg; + t->clr_interrupt_reg = base + p->clr_interrupt_reg; + t->sense_interrupt_reg = base + p->sense_interrupt_reg; + t->ioarrin_reg = base + p->ioarrin_reg; + t->sense_uproc_interrupt_reg = base + p->sense_uproc_interrupt_reg; + t->set_uproc_interrupt_reg = base + p->set_uproc_interrupt_reg; + t->clr_uproc_interrupt_reg = base + p->clr_uproc_interrupt_reg; } /** @@ -5671,14 +5687,15 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, { struct ipr_ioa_cfg *ioa_cfg; struct Scsi_Host *host; - unsigned long ipr_regs, ipr_regs_pci; + unsigned long ipr_regs_pci; + void __iomem *ipr_regs; u32 rc = PCIBIOS_SUCCESSFUL; ENTER; if ((rc = pci_enable_device(pdev))) { dev_err(&pdev->dev, "Cannot enable adapter\n"); - return rc; + goto out; } dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq); @@ -5687,7 +5704,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, if (!host) { dev_err(&pdev->dev, "call to scsi_host_alloc failed!\n"); - return -ENOMEM; + rc = -ENOMEM; + goto out_disable; } ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; @@ -5697,23 +5715,20 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ipr_regs_pci = pci_resource_start(pdev, 0); - if (!request_mem_region(ipr_regs_pci, - pci_resource_len(pdev, 0), IPR_NAME)) { + rc = pci_request_regions(pdev, IPR_NAME); + if (rc < 0) { dev_err(&pdev->dev, "Couldn't register memory range of registers\n"); - scsi_host_put(host); - return -ENOMEM; + goto out_scsi_host_put; } - ipr_regs = (unsigned long)ioremap(ipr_regs_pci, - pci_resource_len(pdev, 0)); + ipr_regs = ioremap(ipr_regs_pci, pci_resource_len(pdev, 0)); if (!ipr_regs) { dev_err(&pdev->dev, "Couldn't map memory range of registers\n"); - release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0)); - scsi_host_put(host); - return -ENOMEM; + rc = -ENOMEM; + goto out_release_regions; } ioa_cfg->hdw_dma_regs = ipr_regs; @@ -5723,11 +5738,10 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ipr_init_ioa_cfg(ioa_cfg, host, pdev); pci_set_master(pdev); - rc = pci_set_dma_mask(pdev, 0xffffffff); - if (rc != PCIBIOS_SUCCESSFUL) { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc < 0) { dev_err(&pdev->dev, "Failed to set PCI DMA mask\n"); - rc = -EIO; goto cleanup_nomem; } @@ -5741,7 +5755,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, } /* Save away PCI config space for use following IOA reset */ - rc = pci_save_state(pdev, ioa_cfg->pci_cfg_buf); + rc = pci_save_state(pdev); if (rc != PCIBIOS_SUCCESSFUL) { dev_err(&pdev->dev, "Failed to save PCI config space\n"); @@ -5755,8 +5769,12 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg))) goto cleanup_nomem; - if ((rc = ipr_alloc_mem(ioa_cfg))) - goto cleanup; + rc = ipr_alloc_mem(ioa_cfg); + if (rc < 0) { + dev_err(&pdev->dev, + "Couldn't allocate enough memory for device driver!\n"); + goto cleanup_nomem; + } ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg); @@ -5772,18 +5790,20 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, spin_unlock(&ipr_driver_lock); LEAVE; - return 0; +out: + return rc; -cleanup: - dev_err(&pdev->dev, "Couldn't allocate enough memory for device driver!\n"); cleanup_nolog: ipr_free_mem(ioa_cfg); cleanup_nomem: - iounmap((void *) ipr_regs); - release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0)); + iounmap(ipr_regs); +out_release_regions: + pci_release_regions(pdev); +out_scsi_host_put: scsi_host_put(host); - - return rc; +out_disable: + pci_disable_device(pdev); + goto out; } /** @@ -5988,9 +6008,15 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_570F, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); @@ -6009,16 +6035,14 @@ static struct pci_driver ipr_driver = { * ipr_init - Module entry point * * Return value: - * 0 on success / non-zero on failure + * 0 on success / negative value on failure **/ static int __init ipr_init(void) { ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n", IPR_DRIVER_VERSION, IPR_DRIVER_DATE); - pci_register_driver(&ipr_driver); - - return 0; + return pci_module_init(&ipr_driver); } /** diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 6d616ac42..1a5f24798 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1,7 +1,7 @@ /* * ipr.h -- driver for IBM Power Linux RAID adapters * - * Written By: Brian King, IBM Corporation + * Written By: Brian King , IBM Corporation * * Copyright (C) 2003, 2004 IBM Corporation * @@ -19,6 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * Alan Cox - Removed several careless u32/dma_addr_t errors + * that broke 64bit platforms. */ #ifndef _IPR_H @@ -27,6 +29,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_KDB @@ -36,8 +39,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.0.10" -#define IPR_DRIVER_DATE "(June 7, 2004)" +#define IPR_DRIVER_VERSION "2.0.11" +#define IPR_DRIVER_DATE "(August 3, 2004)" /* * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing @@ -72,6 +75,8 @@ #define IPR_SUBS_DEV_ID_5703 0x0278 #define IPR_SUBS_DEV_ID_572E 0x02D3 #define IPR_SUBS_DEV_ID_573D 0x02D4 +#define IPR_SUBS_DEV_ID_570F 0x02BD +#define IPR_SUBS_DEV_ID_571B 0x02BE #define IPR_NAME "ipr" @@ -148,7 +153,6 @@ #define IPR_BUS_RESET 0x10 #define IPR_ID_HOST_RR_Q 0xC4 #define IPR_QUERY_IOA_CONFIG 0xC5 -#define IPR_ABORT_TASK 0xC7 #define IPR_CANCEL_ALL_REQUESTS 0xCE #define IPR_HOST_CONTROLLED_ASYNC 0xCF #define IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE 0x01 @@ -667,7 +671,7 @@ struct ipr_hcam { struct ipr_hostrcb { struct ipr_hcam hcam; - u32 hostrcb_dma; + dma_addr_t hostrcb_dma; struct list_head queue; }; @@ -745,7 +749,7 @@ struct ipr_misc_cbs { struct ipr_supported_device supp_dev; }; -struct ipr_interrupts { +struct ipr_interrupt_offsets { unsigned long set_interrupt_mask_reg; unsigned long clr_interrupt_mask_reg; unsigned long sense_interrupt_mask_reg; @@ -758,10 +762,23 @@ struct ipr_interrupts { unsigned long clr_uproc_interrupt_reg; }; +struct ipr_interrupts { + void __iomem *set_interrupt_mask_reg; + void __iomem *clr_interrupt_mask_reg; + void __iomem *sense_interrupt_mask_reg; + void __iomem *clr_interrupt_reg; + + void __iomem *sense_interrupt_reg; + void __iomem *ioarrin_reg; + void __iomem *sense_uproc_interrupt_reg; + void __iomem *set_uproc_interrupt_reg; + void __iomem *clr_uproc_interrupt_reg; +}; + struct ipr_chip_cfg_t { u32 mailbox; u8 cache_line_size; - struct ipr_interrupts regs; + struct ipr_interrupt_offsets regs; }; enum ipr_shutdown_type { @@ -850,7 +867,7 @@ struct ipr_ioa_cfg { char cfg_table_start[8]; #define IPR_CFG_TBL_START "cfg" struct ipr_config_table *cfg_table; - u32 cfg_table_dma; + dma_addr_t cfg_table_dma; char resource_table_label[8]; #define IPR_RES_TABLE_LABEL "res_tbl" @@ -861,12 +878,12 @@ struct ipr_ioa_cfg { char ipr_hcam_label[8]; #define IPR_HCAM_LABEL "hcams" struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS]; - u32 hostrcb_dma[IPR_NUM_HCAMS]; + dma_addr_t hostrcb_dma[IPR_NUM_HCAMS]; struct list_head hostrcb_free_q; struct list_head hostrcb_pending_q; u32 *host_rrq; - u32 host_rrq_dma; + dma_addr_t host_rrq_dma; #define IPR_HRRQ_REQ_RESP_HANDLE_MASK 0xfffffffc #define IPR_HRRQ_RESP_BIT_SET 0x00000002 #define IPR_HRRQ_TOGGLE_BIT 0x00000001 @@ -880,12 +897,11 @@ struct ipr_ioa_cfg { const struct ipr_chip_cfg_t *chip_cfg; - unsigned long hdw_dma_regs; /* iomapped PCI memory space */ + void __iomem *hdw_dma_regs; /* iomapped PCI memory space */ unsigned long hdw_dma_regs_pci; /* raw PCI memory space */ - unsigned long ioa_mailbox; + void __iomem *ioa_mailbox; struct ipr_interrupts regs; - u32 pci_cfg_buf[64]; u16 saved_pcix_cmd_reg; u16 reset_retries; @@ -905,7 +921,7 @@ struct ipr_ioa_cfg { enum ipr_sdt_state sdt_state; struct ipr_misc_cbs *vpd_cbs; - u32 vpd_cbs_dma; + dma_addr_t vpd_cbs_dma; struct pci_pool *ipr_cmd_pool; @@ -1029,7 +1045,7 @@ struct ipr_ioa_dump { }__attribute__((packed, aligned (4))); struct ipr_dump { - struct kobject kobj; + struct kref kref; struct ipr_ioa_cfg *ioa_cfg; struct ipr_driver_dump driver_dump; struct ipr_ioa_dump ioa_dump; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index dc110cc80..f96c49066 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -133,6 +133,10 @@ /* 6.10.00 - Remove 1G Addressing Limitations */ /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ +/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */ +/* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ +/* - Fix sort order of 7k */ +/* - Remove 3 unused "inline" functions */ /*****************************************************************************/ /* @@ -176,7 +180,13 @@ #include #include "scsi.h" + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) +#include "hosts.h" +#else #include +#endif + #include "ips.h" #include @@ -191,14 +201,14 @@ #ifdef MODULE static char *ips = NULL; -MODULE_PARM(ips, "s"); +module_param(ips, charp, 0); #endif /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "7.00" -#define IPS_VERSION_LOW ".15 " +#define IPS_VERSION_HIGH "7.10" +#define IPS_VERSION_LOW ".18 " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" @@ -215,7 +225,7 @@ MODULE_PARM(ips, "s"); #endif #else #define IPS_SG_ADDRESS(sg) (page_address((sg)->page) ? \ - page_address((sg)->page)+(sg)->offset : 0) + page_address((sg)->page)+(sg)->offset : NULL) #define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0) #define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0) #endif @@ -278,6 +288,9 @@ static Scsi_Host_Template ips_driver_template = { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) .use_new_eh_code = 1, #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + .highmem_io = 1, +#endif }; IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */ @@ -474,21 +487,17 @@ static uint32_t ips_statupd_copperhead(ips_ha_t *); static uint32_t ips_statupd_copperhead_memio(ips_ha_t *); static uint32_t ips_statupd_morpheus(ips_ha_t *); static ips_scb_t *ips_getscb(ips_ha_t *); -static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); -static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *); -static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *); -static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); -static inline void ips_putq_copp_head(ips_copp_queue_t *, +static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); +static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); +static void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *); -static inline void ips_putq_copp_tail(ips_copp_queue_t *, - ips_copp_wait_item_t *); -static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *); -static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *); -static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *); -static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); -static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *, +static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *); +static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *); +static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *); +static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); +static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *); -static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *); +static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *); static int ips_is_passthru(Scsi_Cmnd *); static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int); @@ -1885,7 +1894,7 @@ ips_flash_bios(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb) /* Fill in a single scb sg_list element from an address */ /* return a -1 if a breakup occurred */ /****************************************************************************/ -static inline int +static int ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr, ips_scb_t * scb, int indx, unsigned int e_len) { @@ -2950,7 +2959,7 @@ ips_next(ips_ha_t * ha, int intr) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item) { METHOD_TRACE("ips_putq_scb_head", 1); @@ -2967,38 +2976,6 @@ ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item) queue->count++; } -/****************************************************************************/ -/* */ -/* Routine Name: ips_putq_scb_tail */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the tail of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item) -{ - METHOD_TRACE("ips_putq_scb_tail", 1); - - if (!item) - return; - - item->q_next = NULL; - - if (queue->tail) - queue->tail->q_next = item; - - queue->tail = item; - - if (!queue->head) - queue->head = item; - - queue->count++; -} - /****************************************************************************/ /* */ /* Routine Name: ips_removeq_scb_head */ @@ -3010,7 +2987,7 @@ ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_scb_t * +static ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t * queue) { ips_scb_t *item; @@ -3045,7 +3022,7 @@ ips_removeq_scb_head(ips_scb_queue_t * queue) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_scb_t * +static ips_scb_t * ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item) { ips_scb_t *p; @@ -3080,34 +3057,6 @@ ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item) return (NULL); } -/****************************************************************************/ -/* */ -/* Routine Name: ips_putq_wait_head */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the head of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item) -{ - METHOD_TRACE("ips_putq_wait_head", 1); - - if (!item) - return; - - item->host_scribble = (char *) queue->head; - queue->head = item; - - if (!queue->tail) - queue->tail = item; - - queue->count++; -} - /****************************************************************************/ /* */ /* Routine Name: ips_putq_wait_tail */ @@ -3119,7 +3068,7 @@ ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item) { METHOD_TRACE("ips_putq_wait_tail", 1); @@ -3151,7 +3100,7 @@ ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * +static Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t * queue) { Scsi_Cmnd *item; @@ -3186,7 +3135,7 @@ ips_removeq_wait_head(ips_wait_queue_t * queue) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * +static Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item) { Scsi_Cmnd *p; @@ -3221,34 +3170,6 @@ ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item) return (NULL); } -/****************************************************************************/ -/* */ -/* Routine Name: ips_putq_copp_head */ -/* */ -/* Routine Description: */ -/* */ -/* Add an item to the head of the queue */ -/* */ -/* ASSUMED to be called from within the HA lock */ -/* */ -/****************************************************************************/ -static inline void -ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) -{ - METHOD_TRACE("ips_putq_copp_head", 1); - - if (!item) - return; - - item->next = queue->head; - queue->head = item; - - if (!queue->tail) - queue->tail = item; - - queue->count++; -} - /****************************************************************************/ /* */ /* Routine Name: ips_putq_copp_tail */ @@ -3260,7 +3181,7 @@ ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline void +static void ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) { METHOD_TRACE("ips_putq_copp_tail", 1); @@ -3292,7 +3213,7 @@ ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_copp_wait_item_t * +static ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t * queue) { ips_copp_wait_item_t *item; @@ -3327,7 +3248,7 @@ ips_removeq_copp_head(ips_copp_queue_t * queue) /* ASSUMED to be called from within the HA lock */ /* */ /****************************************************************************/ -static inline ips_copp_wait_item_t * +static ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item) { ips_copp_wait_item_t *p; @@ -6946,8 +6867,8 @@ ips_abort_init(ips_ha_t * ha, int index) { ha->active = 0; ips_free(ha); - ips_ha[index] = 0; - ips_sh[index] = 0; + ips_ha[index] = NULL; + ips_sh[index] = NULL; return -1; } @@ -6996,7 +6917,6 @@ ips_order_controllers(void) for (j = position; j < ips_num_controllers; j++) { switch (ips_ha[j]->ad_type) { case IPS_ADTYPE_SERVERAID6M: - case IPS_ADTYPE_SERVERAID7k: case IPS_ADTYPE_SERVERAID7M: if (nvram->adapter_order[i] == 'M') { ips_shift_controllers(position, @@ -7017,6 +6937,7 @@ ips_order_controllers(void) case IPS_ADTYPE_SERVERAID6I: case IPS_ADTYPE_SERVERAID5I2: case IPS_ADTYPE_SERVERAID5I1: + case IPS_ADTYPE_SERVERAID7k: if (nvram->adapter_order[i] == 'S') { ips_shift_controllers(position, j); @@ -7254,8 +7175,8 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) int j; int index; dma_addr_t dma_address; - char *ioremap_ptr; - char *mem_ptr; + char __iomem *ioremap_ptr; + char __iomem *mem_ptr; uint32_t IsDead; METHOD_TRACE("ips_init_phase1", 1); @@ -7545,6 +7466,13 @@ ips_init_phase2(int index) MODULE_LICENSE("GPL"); #endif +MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING); + +#ifdef MODULE_VERSION +MODULE_VERSION(IPS_VER_STRING); +#endif + + /* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index afa57b7e4..d1553a0a3 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -96,7 +96,11 @@ #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - typedef void irqreturn_t; + + #ifndef irqreturn_t + typedef void irqreturn_t; + #endif + #define IRQ_NONE #define IRQ_HANDLED #define IRQ_RETVAL(x) @@ -1113,8 +1117,8 @@ typedef struct ips_ha { uint32_t mem_addr; /* Memory mapped address */ uint32_t io_len; /* Size of IO Address */ uint32_t mem_len; /* Size of memory address */ - char *mem_ptr; /* Memory mapped Ptr */ - char *ioremap_ptr; /* ioremapped memory pointer */ + char __iomem *mem_ptr; /* Memory mapped Ptr */ + char __iomem *ioremap_ptr;/* ioremapped memory pointer */ ips_hw_func_t func; /* hw function pointers */ struct pci_dev *pcidev; /* PCI device handle */ char *flash_data; /* Save Area for flash data */ @@ -1210,13 +1214,13 @@ typedef struct { #define IPS_VER_MAJOR 7 #define IPS_VER_MAJOR_STRING "7" -#define IPS_VER_MINOR 00 -#define IPS_VER_MINOR_STRING "00" -#define IPS_VER_BUILD 15 -#define IPS_VER_BUILD_STRING "15" -#define IPS_VER_STRING "7.00.15" +#define IPS_VER_MINOR 10 +#define IPS_VER_MINOR_STRING "10" +#define IPS_VER_BUILD 18 +#define IPS_VER_BUILD_STRING "18" +#define IPS_VER_STRING "7.10.18" #define IPS_RELEASE_ID 0x00020000 -#define IPS_BUILD_IDENT 625 +#define IPS_BUILD_IDENT 731 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." @@ -1227,32 +1231,35 @@ typedef struct { #define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_SERVERAID3 "6.10.24" -#define IPS_VER_SERVERAID4H "7.00.15" -#define IPS_VER_SERVERAID4MLx "7.00.15" -#define IPS_VER_SARASOTA "7.00.15" -#define IPS_VER_MARCO "7.00.15" -#define IPS_VER_SEBRING "7.00.15" +#define IPS_VER_SERVERAID4H "7.10.11" +#define IPS_VER_SERVERAID4MLx "7.10.18" +#define IPS_VER_SARASOTA "7.10.18" +#define IPS_VER_MARCO "7.10.18" +#define IPS_VER_SEBRING "7.10.18" +#define IPS_VER_KEYWEST "7.10.18" /* Compatability IDs for various adapters */ #define IPS_COMPAT_UNKNOWN "" -#define IPS_COMPAT_CURRENT "SB610" +#define IPS_COMPAT_CURRENT "KW710" #define IPS_COMPAT_SERVERAID1 "2.25.01" #define IPS_COMPAT_SERVERAID2 "2.88.13" #define IPS_COMPAT_NAVAJO "2.88.13" #define IPS_COMPAT_KIOWA "2.88.13" #define IPS_COMPAT_SERVERAID3H "SB610" #define IPS_COMPAT_SERVERAID3L "SB610" -#define IPS_COMPAT_SERVERAID4H "SB610" -#define IPS_COMPAT_SERVERAID4M "SB610" -#define IPS_COMPAT_SERVERAID4L "SB610" -#define IPS_COMPAT_SERVERAID4Mx "SB610" -#define IPS_COMPAT_SERVERAID4Lx "SB610" -#define IPS_COMPAT_SARASOTA "SB610" -#define IPS_COMPAT_MARCO "SB610" -#define IPS_COMPAT_SEBRING "SB610" -#define IPS_COMPAT_BIOS "SB610" - -#define IPS_COMPAT_MAX_ADAPTER_TYPE 16 +#define IPS_COMPAT_SERVERAID4H "KW710" +#define IPS_COMPAT_SERVERAID4M "KW710" +#define IPS_COMPAT_SERVERAID4L "KW710" +#define IPS_COMPAT_SERVERAID4Mx "KW710" +#define IPS_COMPAT_SERVERAID4Lx "KW710" +#define IPS_COMPAT_SARASOTA "KW710" +#define IPS_COMPAT_MARCO "KW710" +#define IPS_COMPAT_SEBRING "KW710" +#define IPS_COMPAT_TAMPA "KW710" +#define IPS_COMPAT_KEYWEST "KW710" +#define IPS_COMPAT_BIOS "KW710" + +#define IPS_COMPAT_MAX_ADAPTER_TYPE 18 #define IPS_COMPAT_ID_LENGTH 8 #define IPS_DEFINE_COMPAT_TABLE(tablename) \ @@ -1272,7 +1279,9 @@ typedef struct { IPS_COMPAT_SARASOTA, /* one-channel variety of SARASOTA */ \ IPS_COMPAT_SARASOTA, /* two-channel variety of SARASOTA */ \ IPS_COMPAT_MARCO, \ - IPS_COMPAT_SEBRING \ + IPS_COMPAT_SEBRING, \ + IPS_COMPAT_TAMPA, \ + IPS_COMPAT_KEYWEST \ } diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c index 22f74cf70..afbea8db0 100644 --- a/drivers/scsi/jazz_esp.c +++ b/drivers/scsi/jazz_esp.c @@ -286,7 +286,7 @@ static void dma_led_on(struct NCR_ESP *esp) } static Scsi_Host_Template driver_template = { - .proc_name = "esp", + .proc_name = "jazz_esp", .proc_info = &esp_proc_info, .name = "ESP 100/100a/200", .detect = jazz_esp_detect, diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 874010865..35110f4d1 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -50,6 +50,9 @@ #include #include +#include +#include +#include #include "lasi700.h" #include "53c700.h" @@ -104,29 +107,16 @@ lasi700_probe(struct parisc_device *dev) NCR_700_set_mem_mapped(hostdata); - host = NCR_700_detect(&lasi700_template, hostdata); + host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev, + dev->irq, 7); if (!host) goto out_kfree; - host->irq = dev->irq; - if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, - dev->dev.bus_id, host)) { - printk(KERN_ERR "%s: irq problem, detaching\n", - dev->dev.bus_id); - goto out_put_host; - } - - if (scsi_add_host(host, &dev->dev)) - goto out_free_irq; dev_set_drvdata(&dev->dev, host); scsi_scan_host(host); return 0; - out_free_irq: - free_irq(host->irq, host); - out_put_host: - scsi_host_put(host); out_kfree: kfree(hostdata); return -ENODEV; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 7f2d11d87..93d987433 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -39,22 +39,27 @@ #include #include #include "scsi.h" +#include "scsi_priv.h" #include #include #include #include +#include #include "libata.h" static unsigned int ata_busy_sleep (struct ata_port *ap, unsigned long tmout_pat, unsigned long tmout); -static void __ata_dev_select (struct ata_port *ap, unsigned int device); -static void ata_host_set_pio(struct ata_port *ap); -static void ata_host_set_udma(struct ata_port *ap); -static void ata_dev_set_pio(struct ata_port *ap, unsigned int device); -static void ata_dev_set_udma(struct ata_port *ap, unsigned int device); static void ata_set_mode(struct ata_port *ap); +static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); +static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift); +static int fgb(u32 bitmap); +static int ata_choose_xfer_mode(struct ata_port *ap, + u8 *xfer_mode_out, + unsigned int *xfer_shift_out); +static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); +static void __ata_qc_complete(struct ata_queued_cmd *qc); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -62,19 +67,20 @@ static struct workqueue_struct *ata_wq; MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); /** - * ata_tf_load_pio - send taskfile registers to host controller + * ata_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set * - * Outputs ATA taskfile to standard ATA host controller using PIO. + * Outputs ATA taskfile to standard ATA host controller. * * LOCKING: * Inherited from caller. */ -void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; @@ -132,23 +138,23 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) * Inherited from caller. */ -void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; if (tf->ctl != ap->last_ctl) { - writeb(tf->ctl, ap->ioaddr.ctl_addr); + writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr); ap->last_ctl = tf->ctl; ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - writeb(tf->hob_feature, (void *) ioaddr->feature_addr); - writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr); - writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr); - writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr); - writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr); + writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr); + writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr); + writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr); + writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr); + writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr); VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", tf->hob_feature, tf->hob_nsect, @@ -158,11 +164,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) } if (is_addr) { - writeb(tf->feature, (void *) ioaddr->feature_addr); - writeb(tf->nsect, (void *) ioaddr->nsect_addr); - writeb(tf->lbal, (void *) ioaddr->lbal_addr); - writeb(tf->lbam, (void *) ioaddr->lbam_addr); - writeb(tf->lbah, (void *) ioaddr->lbah_addr); + writeb(tf->feature, (void __iomem *) ioaddr->feature_addr); + writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr); + writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr); + writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr); + writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr); VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", tf->feature, tf->nsect, @@ -172,26 +178,34 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) } if (tf->flags & ATA_TFLAG_DEVICE) { - writeb(tf->device, (void *) ioaddr->device_addr); + writeb(tf->device, (void __iomem *) ioaddr->device_addr); VPRINTK("device 0x%X\n", tf->device); } ata_wait_idle(ap); } +void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_tf_load_mmio(ap, tf); + else + ata_tf_load_pio(ap, tf); +} + /** - * ata_exec_command_pio - issue ATA command to host controller + * ata_exec_command - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * - * Issues PIO write to ATA command register, with proper + * Issues PIO/MMIO write to ATA command register, with proper * synchronization with interrupt handler / other threads. * * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf) { DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); @@ -212,20 +226,28 @@ void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf) * spin_lock_irqsave(host_set lock) */ -void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - writeb(tf->command, (void *) ap->ioaddr.command_addr); + writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr); ata_pause(ap); } +void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_exec_command_mmio(ap, tf); + else + ata_exec_command_pio(ap, tf); +} + /** * ata_exec - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * - * Issues PIO write to ATA command register, with proper + * Issues PIO/MMIO write to ATA command register, with proper * synchronization with interrupt handler / other threads. * * LOCKING: @@ -248,7 +270,7 @@ static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf) * @tf: ATA taskfile register set * * Issues ATA taskfile register set to ATA host controller, - * via PIO, with proper synchronization with interrupt handler and + * with proper synchronization with interrupt handler and * other threads. * * LOCKING: @@ -268,7 +290,7 @@ static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf) * @tf: ATA taskfile register set * * Issues ATA taskfile register set to ATA host controller, - * via PIO, with proper synchronization with interrupt handler and + * with proper synchronization with interrupt handler and * other threads. * * LOCKING: @@ -282,18 +304,18 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf) } /** - * ata_tf_read_pio - input device's ATA taskfile shadow registers + * ata_tf_read - input device's ATA taskfile shadow registers * @ap: Port from which input is read * @tf: ATA taskfile register set for storing input * * Reads ATA taskfile registers for currently-selected device - * into @tf via PIO. + * into @tf. * * LOCKING: * Inherited from caller. */ -void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; @@ -325,38 +347,46 @@ void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf) * Inherited from caller. */ -void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) +static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; - tf->nsect = readb((void *)ioaddr->nsect_addr); - tf->lbal = readb((void *)ioaddr->lbal_addr); - tf->lbam = readb((void *)ioaddr->lbam_addr); - tf->lbah = readb((void *)ioaddr->lbah_addr); - tf->device = readb((void *)ioaddr->device_addr); + tf->nsect = readb((void __iomem *)ioaddr->nsect_addr); + tf->lbal = readb((void __iomem *)ioaddr->lbal_addr); + tf->lbam = readb((void __iomem *)ioaddr->lbam_addr); + tf->lbah = readb((void __iomem *)ioaddr->lbah_addr); + tf->device = readb((void __iomem *)ioaddr->device_addr); if (tf->flags & ATA_TFLAG_LBA48) { - writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr); - tf->hob_feature = readb((void *)ioaddr->error_addr); - tf->hob_nsect = readb((void *)ioaddr->nsect_addr); - tf->hob_lbal = readb((void *)ioaddr->lbal_addr); - tf->hob_lbam = readb((void *)ioaddr->lbam_addr); - tf->hob_lbah = readb((void *)ioaddr->lbah_addr); + writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr); + tf->hob_feature = readb((void __iomem *)ioaddr->error_addr); + tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr); + tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr); + tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr); + tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr); } } +void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_tf_read_mmio(ap, tf); + else + ata_tf_read_pio(ap, tf); +} + /** - * ata_check_status_pio - Read device status reg & clear interrupt + * ata_check_status - Read device status reg & clear interrupt * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device - * via PIO and return it's value. This also clears pending interrupts + * and return it's value. This also clears pending interrupts * from this device * * LOCKING: * Inherited from caller. */ -u8 ata_check_status_pio(struct ata_port *ap) +static u8 ata_check_status_pio(struct ata_port *ap) { return inb(ap->ioaddr.status_addr); } @@ -372,9 +402,16 @@ u8 ata_check_status_pio(struct ata_port *ap) * LOCKING: * Inherited from caller. */ -u8 ata_check_status_mmio(struct ata_port *ap) +static u8 ata_check_status_mmio(struct ata_port *ap) +{ + return readb((void __iomem *) ap->ioaddr.status_addr); +} + +u8 ata_check_status(struct ata_port *ap) { - return readb((void *) ap->ioaddr.status_addr); + if (ap->flags & ATA_FLAG_MMIO) + return ata_check_status_mmio(ap); + return ata_check_status_pio(ap); } /** @@ -524,7 +561,7 @@ static void ata_dev_set_protocol(struct ata_device *dev) dev->write_cmd = (cmd >> 8) & 0xff; } -static const char * udma_str[] = { +static const char * xfer_mode_str[] = { "UDMA/16", "UDMA/25", "UDMA/33", @@ -533,11 +570,19 @@ static const char * udma_str[] = { "UDMA/100", "UDMA/133", "UDMA7", + "MWDMA0", + "MWDMA1", + "MWDMA2", + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", }; /** * ata_udma_string - convert UDMA bit offset to string - * @udma_mask: mask of bits supported; only highest bit counts. + * @mask: mask of bits supported; only highest bit counts. * * Determine string which represents the highest speed * (highest bit in @udma_mask). @@ -550,16 +595,24 @@ static const char * udma_str[] = { * @udma_mask, or the constant C string "". */ -static const char *ata_udma_string(unsigned int udma_mask) +static const char *ata_mode_string(unsigned int mask) { int i; - for (i = 7; i >= 0; i--) { - if (udma_mask & (1 << i)) - return udma_str[i]; - } + for (i = 7; i >= 0; i--) + if (mask & (1 << i)) + goto out; + for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--) + if (mask & (1 << i)) + goto out; + for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--) + if (mask & (1 << i)) + goto out; return ""; + +out: + return xfer_mode_str[i]; } /** @@ -586,7 +639,7 @@ static unsigned int ata_pio_devchk(struct ata_port *ap, struct ata_ioports *ioaddr = &ap->ioaddr; u8 nsect, lbal; - __ata_dev_select(ap, device); + ap->ops->dev_select(ap, device); outb(0x55, ioaddr->nsect_addr); outb(0xaa, ioaddr->lbal_addr); @@ -630,19 +683,19 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap, struct ata_ioports *ioaddr = &ap->ioaddr; u8 nsect, lbal; - __ata_dev_select(ap, device); + ap->ops->dev_select(ap, device); - writeb(0x55, (void *) ioaddr->nsect_addr); - writeb(0xaa, (void *) ioaddr->lbal_addr); + writeb(0x55, (void __iomem *) ioaddr->nsect_addr); + writeb(0xaa, (void __iomem *) ioaddr->lbal_addr); - writeb(0xaa, (void *) ioaddr->nsect_addr); - writeb(0x55, (void *) ioaddr->lbal_addr); + writeb(0xaa, (void __iomem *) ioaddr->nsect_addr); + writeb(0x55, (void __iomem *) ioaddr->lbal_addr); - writeb(0x55, (void *) ioaddr->nsect_addr); - writeb(0xaa, (void *) ioaddr->lbal_addr); + writeb(0x55, (void __iomem *) ioaddr->nsect_addr); + writeb(0xaa, (void __iomem *) ioaddr->lbal_addr); - nsect = readb((void *) ioaddr->nsect_addr); - lbal = readb((void *) ioaddr->lbal_addr); + nsect = readb((void __iomem *) ioaddr->nsect_addr); + lbal = readb((void __iomem *) ioaddr->lbal_addr); if ((nsect == 0x55) && (lbal == 0xaa)) return 1; /* we found a device */ @@ -651,7 +704,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap, } /** - * ata_dev_devchk - PATA device presence detection + * ata_devchk - PATA device presence detection * @ap: ATA channel to examine * @device: Device to examine (starting at zero) * @@ -663,7 +716,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap, * caller. */ -static unsigned int ata_dev_devchk(struct ata_port *ap, +static unsigned int ata_devchk(struct ata_port *ap, unsigned int device) { if (ap->flags & ATA_FLAG_MMIO) @@ -687,7 +740,7 @@ static unsigned int ata_dev_devchk(struct ata_port *ap, * the event of failure. */ -static unsigned int ata_dev_classify(struct ata_taskfile *tf) +unsigned int ata_dev_classify(struct ata_taskfile *tf) { /* Apple's open source Darwin code hints that some devices only * put a proper signature into the LBA mid/high registers, @@ -735,7 +788,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) unsigned int class; u8 err; - __ata_dev_select(ap, device); + ap->ops->dev_select(ap, device); memset(&tf, 0, sizeof(tf)); @@ -766,7 +819,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) /** * ata_dev_id_string - Convert IDENTIFY DEVICE page into string - * @dev: Device whose IDENTIFY DEVICE results we will examine + * @id: IDENTIFY DEVICE results we will examine * @s: string into which data is output * @ofs: offset into identify device page * @len: length of string to return. must be an even number. @@ -779,17 +832,17 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) * caller. */ -void ata_dev_id_string(struct ata_device *dev, unsigned char *s, +void ata_dev_id_string(u16 *id, unsigned char *s, unsigned int ofs, unsigned int len) { unsigned int c; while (len > 0) { - c = dev->id[ofs] >> 8; + c = id[ofs] >> 8; *s = c; s++; - c = dev->id[ofs] & 0xff; + c = id[ofs] & 0xff; *s = c; s++; @@ -798,8 +851,12 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s, } } +void ata_noop_dev_select (struct ata_port *ap, unsigned int device) +{ +} + /** - * __ata_dev_select - Select device 0/1 on ATA bus + * ata_std_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * @@ -811,7 +868,7 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s, * caller. */ -static void __ata_dev_select (struct ata_port *ap, unsigned int device) +void ata_std_dev_select (struct ata_port *ap, unsigned int device) { u8 tmp; @@ -821,7 +878,7 @@ static void __ata_dev_select (struct ata_port *ap, unsigned int device) tmp = ATA_DEVICE_OBS | ATA_DEV1; if (ap->flags & ATA_FLAG_MMIO) { - writeb(tmp, (void *) ap->ioaddr.device_addr); + writeb(tmp, (void __iomem *) ap->ioaddr.device_addr); } else { outb(tmp, ap->ioaddr.device_addr); } @@ -839,7 +896,7 @@ static void __ata_dev_select (struct ata_port *ap, unsigned int device) * make either device 0, or device 1, active on the * ATA channel. * - * This is a high-level version of __ata_dev_select(), + * This is a high-level version of ata_std_dev_select(), * which additionally provides the services of inserting * the proper pauses and status polling, where needed. * @@ -856,7 +913,7 @@ void ata_dev_select(struct ata_port *ap, unsigned int device, if (wait) ata_wait_idle(ap); - __ata_dev_select(ap, device); + ap->ops->dev_select(ap, device); if (wait) { if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI) @@ -930,10 +987,14 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int i; - u16 tmp, udma_modes; + u16 tmp; + unsigned long xfer_modes; u8 status; - struct ata_taskfile tf; unsigned int using_edd; + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + unsigned long flags; + int rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", @@ -953,27 +1014,34 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ata_dev_select(ap, device, 1, 1); /* select device 0/1 */ -retry: - ata_tf_init(ap, &tf, device); - tf.ctl |= ATA_NIEN; - tf.protocol = ATA_PROT_PIO; + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); + + ata_sg_init_one(qc, dev->id, sizeof(dev->id)); + qc->dma_dir = DMA_FROM_DEVICE; + qc->tf.protocol = ATA_PROT_PIO; + qc->nsect = 1; +retry: if (dev->class == ATA_DEV_ATA) { - tf.command = ATA_CMD_ID_ATA; + qc->tf.command = ATA_CMD_ID_ATA; DPRINTK("do ATA identify\n"); } else { - tf.command = ATA_CMD_ID_ATAPI; + qc->tf.command = ATA_CMD_ID_ATAPI; DPRINTK("do ATAPI identify\n"); } - ata_tf_to_host(ap, &tf); + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; - /* crazy ATAPI devices... */ - if (dev->class == ATA_DEV_ATAPI) - msleep(150); + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) + if (rc) goto err_out; + else + wait_for_completion(&wait); status = ata_chk_status(ap); if (status & ATA_ERR) { @@ -988,44 +1056,21 @@ retry: * ATA software reset (SRST, the default) does not appear * to have this problem. */ - if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) { + if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) { u8 err = ata_chk_err(ap); if (err & ATA_ABORTED) { dev->class = ATA_DEV_ATAPI; + qc->cursg = 0; + qc->cursg_ofs = 0; + qc->cursect = 0; + qc->nsect = 1; goto retry; } } goto err_out; } - /* make sure we have BSY=0, DRQ=1 */ - if ((status & ATA_DRQ) == 0) { - printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n", - ap->id, device, - dev->class == ATA_DEV_ATA ? "" : "PI", - status); - goto err_out; - } - - /* read IDENTIFY [X] DEVICE page */ - if (ap->flags & ATA_FLAG_MMIO) { - for (i = 0; i < ATA_ID_WORDS; i++) - dev->id[i] = readw((void *)ap->ioaddr.data_addr); - } else - for (i = 0; i < ATA_ID_WORDS; i++) - dev->id[i] = inw(ap->ioaddr.data_addr); - - /* wait for host_idle */ - status = ata_wait_idle(ap); - if (status & (ATA_BUSY | ATA_DRQ)) { - printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n", - ap->id, device, - dev->class == ATA_DEV_ATA ? "" : "PI", - status); - goto err_out; - } - - ata_irq_on(ap); /* re-enable interrupts */ + swap_buf_le16(dev->id, ATA_ID_WORDS); /* print device capabilities */ printk(KERN_DEBUG "ata%u: dev %u cfg " @@ -1040,24 +1085,25 @@ retry: */ /* we require LBA and DMA support (bits 8 & 9 of word 49) */ - if (!ata_id_has_dma(dev) || !ata_id_has_lba(dev)) { + if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) { printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id); goto err_out_nosup; } - /* we require UDMA support */ - udma_modes = - tmp = dev->id[ATA_ID_UDMA_MODES]; - if ((tmp & 0xff) == 0) { - printk(KERN_DEBUG "ata%u: no udma\n", ap->id); - goto err_out_nosup; + /* quick-n-dirty find max transfer mode; for printk only */ + xfer_modes = dev->id[ATA_ID_UDMA_MODES]; + if (!xfer_modes) + xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA; + if (!xfer_modes) { + xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3); + xfer_modes |= (0x7 << ATA_SHIFT_PIO); } ata_dump_id(dev); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { - if (!ata_id_is_ata(dev)) /* sanity check */ + if (!ata_id_is_ata(dev->id)) /* sanity check */ goto err_out_nosup; tmp = dev->id[ATA_ID_MAJOR_VER]; @@ -1071,11 +1117,11 @@ retry: goto err_out_nosup; } - if (ata_id_has_lba48(dev)) { + if (ata_id_has_lba48(dev->id)) { dev->flags |= ATA_DFLAG_LBA48; - dev->n_sectors = ata_id_u64(dev, 100); + dev->n_sectors = ata_id_u64(dev->id, 100); } else { - dev->n_sectors = ata_id_u32(dev, 60); + dev->n_sectors = ata_id_u32(dev->id, 60); } ap->host->max_cmd_len = 16; @@ -1083,25 +1129,28 @@ retry: /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", ap->id, device, - ata_udma_string(udma_modes), + ata_mode_string(xfer_modes), (unsigned long long)dev->n_sectors, dev->flags & ATA_DFLAG_LBA48 ? " lba48" : ""); } /* ATAPI-specific feature tests */ else { - if (ata_id_is_ata(dev)) /* sanity check */ + if (ata_id_is_ata(dev->id)) /* sanity check */ goto err_out_nosup; - /* see if 16-byte commands supported */ - tmp = dev->id[0] & 0x3; - if (tmp == 1) - ap->host->max_cmd_len = 16; + rc = atapi_cdb_len(dev->id); + if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { + printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + goto err_out_nosup; + } + ap->cdb_len = (unsigned int) rc; + ap->host->max_cmd_len = (unsigned char) ap->cdb_len; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", ap->id, device, - ata_udma_string(udma_modes)); + ata_mode_string(xfer_modes)); } DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); @@ -1171,13 +1220,13 @@ void ata_port_probe(struct ata_port *ap) } /** - * sata_phy_reset - + * __sata_phy_reset - * @ap: * * LOCKING: * */ -void sata_phy_reset(struct ata_port *ap) +void __sata_phy_reset(struct ata_port *ap) { u32 sstatus; unsigned long timeout = jiffies + (HZ * 5); @@ -1215,6 +1264,21 @@ void sata_phy_reset(struct ata_port *ap) return; } + ap->cbl = ATA_CBL_SATA; +} + +/** + * __sata_phy_reset - + * @ap: + * + * LOCKING: + * + */ +void sata_phy_reset(struct ata_port *ap) +{ + __sata_phy_reset(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; ata_bus_reset(ap); } @@ -1232,6 +1296,101 @@ void ata_port_disable(struct ata_port *ap) ap->flags |= ATA_FLAG_PORT_DISABLED; } +static struct { + unsigned int shift; + u8 base; +} xfer_mode_classes[] = { + { ATA_SHIFT_UDMA, XFER_UDMA_0 }, + { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 }, + { ATA_SHIFT_PIO, XFER_PIO_0 }, +}; + +static inline u8 base_from_shift(unsigned int shift) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) + if (xfer_mode_classes[i].shift == shift) + return xfer_mode_classes[i].base; + + return 0xff; +} + +static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +{ + int ofs, idx; + u8 base; + + if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + return; + + if (dev->xfer_shift == ATA_SHIFT_PIO) + dev->flags |= ATA_DFLAG_PIO; + + ata_dev_set_xfermode(ap, dev); + + base = base_from_shift(dev->xfer_shift); + ofs = dev->xfer_mode - base; + idx = ofs + dev->xfer_shift; + WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); + + DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", + idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); + + printk(KERN_INFO "ata%u: dev %u configured for %s\n", + ap->id, dev->devno, xfer_mode_str[idx]); +} + +static int ata_host_set_pio(struct ata_port *ap) +{ + unsigned int mask; + int x, i; + u8 base, xfer_mode; + + mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); + x = fgb(mask); + if (x < 0) { + printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + return -1; + } + + base = base_from_shift(ATA_SHIFT_PIO); + xfer_mode = base + x; + + DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", + (int)base, (int)xfer_mode, mask, x); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_present(dev)) { + dev->pio_mode = xfer_mode; + dev->xfer_mode = xfer_mode; + dev->xfer_shift = ATA_SHIFT_PIO; + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + } + + return 0; +} + +static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, + unsigned int xfer_shift) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_present(dev)) { + dev->dma_mode = xfer_mode; + dev->xfer_mode = xfer_mode; + dev->xfer_shift = xfer_shift; + if (ap->ops->set_dmamode) + ap->ops->set_dmamode(ap, dev); + } + } +} + /** * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed @@ -1241,29 +1400,28 @@ void ata_port_disable(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { - unsigned int force_pio, i; + unsigned int i, xfer_shift; + u8 xfer_mode; + int rc; - ata_host_set_pio(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + /* step 1: always set host PIO timings */ + rc = ata_host_set_pio(ap); + if (rc) + goto err_out; - ata_host_set_udma(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; + /* step 2: choose the best data xfer mode */ + xfer_mode = xfer_shift = 0; + rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); + if (rc) + goto err_out; -#ifdef ATA_FORCE_PIO - force_pio = 1; -#else - force_pio = 0; -#endif + /* step 3: if that xfer mode isn't PIO, set host DMA timings */ + if (xfer_shift != ATA_SHIFT_PIO) + ata_host_set_dma(ap, xfer_mode, xfer_shift); - if (force_pio) { - ata_dev_set_pio(ap, 0); - ata_dev_set_pio(ap, 1); - } else { - ata_dev_set_udma(ap, 0); - ata_dev_set_udma(ap, 1); - } + /* step 4: update devices' xfer mode */ + ata_dev_set_mode(ap, &ap->device[0]); + ata_dev_set_mode(ap, &ap->device[1]); if (ap->flags & ATA_FLAG_PORT_DISABLED) return; @@ -1275,6 +1433,11 @@ static void ata_set_mode(struct ata_port *ap) struct ata_device *dev = &ap->device[i]; ata_dev_set_protocol(dev); } + + return; + +err_out: + ata_port_disable(ap); } /** @@ -1328,23 +1491,23 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) unsigned int dev1 = devmask & (1 << 1); unsigned long timeout; - /* if device 0 was found in ata_dev_devchk, wait for its + /* if device 0 was found in ata_devchk, wait for its * BSY bit to clear */ if (dev0) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); - /* if device 1 was found in ata_dev_devchk, wait for + /* if device 1 was found in ata_devchk, wait for * register access, then wait for BSY to clear */ timeout = jiffies + ATA_TMOUT_BOOT; while (dev1) { u8 nsect, lbal; - __ata_dev_select(ap, 1); + ap->ops->dev_select(ap, 1); if (ap->flags & ATA_FLAG_MMIO) { - nsect = readb((void *) ioaddr->nsect_addr); - lbal = readb((void *) ioaddr->lbal_addr); + nsect = readb((void __iomem *) ioaddr->nsect_addr); + lbal = readb((void __iomem *) ioaddr->lbal_addr); } else { nsect = inb(ioaddr->nsect_addr); lbal = inb(ioaddr->lbal_addr); @@ -1361,11 +1524,11 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); /* is all this really necessary? */ - __ata_dev_select(ap, 0); + ap->ops->dev_select(ap, 0); if (dev1) - __ata_dev_select(ap, 1); + ap->ops->dev_select(ap, 1); if (dev0) - __ata_dev_select(ap, 0); + ap->ops->dev_select(ap, 0); } /** @@ -1408,11 +1571,11 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, /* software reset. causes dev0 to be selected */ if (ap->flags & ATA_FLAG_MMIO) { - writeb(ap->ctl, ioaddr->ctl_addr); + writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ - writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr); + writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ - writeb(ap->ctl, ioaddr->ctl_addr); + writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); } else { outb(ap->ctl, ioaddr->ctl_addr); udelay(10); @@ -1469,9 +1632,9 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & ATA_FLAG_SATA_RESET) dev0 = 1; else { - dev0 = ata_dev_devchk(ap, 0); + dev0 = ata_devchk(ap, 0); if (slave_possible) - dev1 = ata_dev_devchk(ap, 1); + dev1 = ata_devchk(ap, 1); } if (dev0) @@ -1480,7 +1643,7 @@ void ata_bus_reset(struct ata_port *ap) devmask |= (1 << 1); /* select device 0 again */ - __ata_dev_select(ap, 0); + ap->ops->dev_select(ap, 0); /* issue bus reset */ if (ap->flags & ATA_FLAG_SRST) @@ -1488,7 +1651,7 @@ void ata_bus_reset(struct ata_port *ap) else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { /* set up device control */ if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, ioaddr->ctl_addr); + writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); else outb(ap->ctl, ioaddr->ctl_addr); rc = ata_bus_edd(ap); @@ -1509,9 +1672,9 @@ void ata_bus_reset(struct ata_port *ap) /* is double-select really necessary? */ if (ap->device[1].class != ATA_DEV_NONE) - __ata_dev_select(ap, 1); + ap->ops->dev_select(ap, 1); if (ap->device[0].class != ATA_DEV_NONE) - __ata_dev_select(ap, 0); + ap->ops->dev_select(ap, 0); /* if no devices were detected, disable this port */ if ((ap->device[0].class == ATA_DEV_NONE) && @@ -1521,7 +1684,7 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { /* set up device control for ATA_FLAG_SATA_RESET */ if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, ioaddr->ctl_addr); + writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); else outb(ap->ctl, ioaddr->ctl_addr); } @@ -1536,116 +1699,104 @@ err_out: DPRINTK("EXIT\n"); } -/** - * ata_host_set_pio - - * @ap: - * - * LOCKING: - */ - -static void ata_host_set_pio(struct ata_port *ap) +static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift) { struct ata_device *master, *slave; - unsigned int pio, i; - u16 mask; + unsigned int mask; master = &ap->device[0]; slave = &ap->device[1]; assert (ata_dev_present(master) || ata_dev_present(slave)); - mask = ap->pio_mask; - if (ata_dev_present(master)) - mask &= (master->id[ATA_ID_PIO_MODES] & 0x03); - if (ata_dev_present(slave)) - mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03); - - /* require pio mode 3 or 4 support for host and all devices */ - if (mask == 0) { - printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n", - ap->id); - goto err_out; + if (shift == ATA_SHIFT_UDMA) { + mask = ap->udma_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); + } + else if (shift == ATA_SHIFT_MWDMA) { + mask = ap->mwdma_mask; + if (ata_dev_present(master)) + mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); + if (ata_dev_present(slave)) + mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); + } + else if (shift == ATA_SHIFT_PIO) { + mask = ap->pio_mask; + if (ata_dev_present(master)) { + /* spec doesn't return explicit support for + * PIO0-2, so we fake it + */ + u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; + tmp_mode <<= 3; + tmp_mode |= 0x7; + mask &= tmp_mode; + } + if (ata_dev_present(slave)) { + /* spec doesn't return explicit support for + * PIO0-2, so we fake it + */ + u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; + tmp_mode <<= 3; + tmp_mode |= 0x7; + mask &= tmp_mode; + } + } + else { + mask = 0xffffffff; /* shut up compiler warning */ + BUG(); } - pio = (mask & ATA_ID_PIO4) ? 4 : 3; - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (ata_dev_present(&ap->device[i])) { - ap->device[i].pio_mode = (pio == 3) ? - XFER_PIO_3 : XFER_PIO_4; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, &ap->device[i], pio); - } + return mask; +} - return; +/* find greatest bit */ +static int fgb(u32 bitmap) +{ + unsigned int i; + int x = -1; -err_out: - ap->ops->port_disable(ap); + for (i = 0; i < 32; i++) + if (bitmap & (1 << i)) + x = i; + + return x; } /** - * ata_host_set_udma - - * @ap: + * ata_choose_xfer_mode - attempt to find best transfer mode + * @ap: Port for which an xfer mode will be selected + * @xfer_mode_out: (output) SET FEATURES - XFER MODE code + * @xfer_shift_out: (output) bit shift that selects this mode * * LOCKING: + * + * RETURNS: + * Zero on success, negative on error. */ -static void ata_host_set_udma(struct ata_port *ap) +static int ata_choose_xfer_mode(struct ata_port *ap, + u8 *xfer_mode_out, + unsigned int *xfer_shift_out) { - struct ata_device *master, *slave; - u16 mask; - unsigned int i, j; - int udma_mode = -1; + unsigned int mask, shift; + int x, i; - master = &ap->device[0]; - slave = &ap->device[1]; + for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { + shift = xfer_mode_classes[i].shift; + mask = ata_get_mode_mask(ap, shift); - assert (ata_dev_present(master) || ata_dev_present(slave)); - assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0); - - DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n", - ap->udma_mask, - (!ata_dev_present(master)) ? 0xff : - (master->id[ATA_ID_UDMA_MODES] & 0xff), - (!ata_dev_present(slave)) ? 0xff : - (slave->id[ATA_ID_UDMA_MODES] & 0xff)); - - mask = ap->udma_mask; - if (ata_dev_present(master)) - mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dev_present(slave)) - mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); - - i = XFER_UDMA_7; - while (i >= XFER_UDMA_0) { - j = i - XFER_UDMA_0; - DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j); - if (mask & (1 << j)) { - udma_mode = i; - break; + x = fgb(mask); + if (x >= 0) { + *xfer_mode_out = xfer_mode_classes[i].base + x; + *xfer_shift_out = shift; + return 0; } - - i--; - } - - /* require udma for host and all attached devices */ - if (udma_mode < 0) { - printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n", - ap->id); - goto err_out; } - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (ata_dev_present(&ap->device[i])) { - ap->device[i].udma_mode = udma_mode; - if (ap->ops->set_udmamode) - ap->ops->set_udmamode(ap, &ap->device[i], - udma_mode); - } - - return; - -err_out: - ap->ops->port_disable(ap); + return -1; } /** @@ -1658,88 +1809,38 @@ err_out: static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) { - struct ata_taskfile tf; + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + int rc; + unsigned long flags; /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); - ata_tf_init(ap, &tf, dev->devno); - tf.ctl |= ATA_NIEN; - tf.command = ATA_CMD_SET_FEATURES; - tf.feature = SETFEATURES_XFER; - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_NODATA; - if (dev->flags & ATA_DFLAG_PIO) - tf.nsect = dev->pio_mode; - else - tf.nsect = dev->udma_mode; - /* do bus reset */ - ata_tf_to_host(ap, &tf); + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); - /* crazy ATAPI devices... */ - if (dev->class == ATA_DEV_ATAPI) - msleep(150); + qc->tf.command = ATA_CMD_SET_FEATURES; + qc->tf.feature = SETFEATURES_XFER; + qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + qc->tf.protocol = ATA_PROT_NODATA; + qc->tf.nsect = dev->xfer_mode; - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; - ata_irq_on(ap); /* re-enable interrupts */ + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); - ata_wait_idle(ap); + if (rc) + ata_port_disable(ap); + else + wait_for_completion(&wait); DPRINTK("EXIT\n"); } -/** - * ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA - * @ap: Port associated with device @dev - * @device: Device whose mode will be set - * - * LOCKING: - */ - -static void ata_dev_set_udma(struct ata_port *ap, unsigned int device) -{ - struct ata_device *dev = &ap->device[device]; - - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - return; - - ata_dev_set_xfermode(ap, dev); - - assert((dev->udma_mode >= XFER_UDMA_0) && - (dev->udma_mode <= XFER_UDMA_7)); - printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, device, - udma_str[dev->udma_mode - XFER_UDMA_0]); -} - -/** - * ata_dev_set_pio - Set ATA device's transfer mode to PIO - * @ap: Port associated with device @dev - * @device: Device whose mode will be set - * - * LOCKING: - */ - -static void ata_dev_set_pio(struct ata_port *ap, unsigned int device) -{ - struct ata_device *dev = &ap->device[device]; - - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - return; - - /* force PIO mode */ - dev->flags |= ATA_DFLAG_PIO; - - ata_dev_set_xfermode(ap, dev); - - assert((dev->pio_mode >= XFER_PIO_3) && - (dev->pio_mode <= XFER_PIO_4)); - printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n", - ap->id, device, - dev->pio_mode == 3 ? '3' : '4'); -} - /** * ata_sg_clean - * @qc: @@ -1751,7 +1852,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct scatterlist *sg = qc->sg; - int dir = qc->pci_dma_dir; + int dir = qc->dma_dir; assert(qc->flags & ATA_QCFLAG_DMAMAP); assert(sg != NULL); @@ -1762,9 +1863,9 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) DPRINTK("unmapping %u sg elements\n", qc->n_elem); if (qc->flags & ATA_QCFLAG_SG) - pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); else - pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]), + dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; @@ -1789,7 +1890,7 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) idx = 0; for (nelem = qc->n_elem; nelem; nelem--,sg++) { - u32 addr, boundary; + u32 addr, offset; u32 sg_len, len; /* determine if physical DMA addr spans 64K boundary. @@ -1800,10 +1901,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) sg_len = sg_dma_len(sg); while (sg_len) { - boundary = (addr & ~0xffff) + (0xffff + 1); + offset = addr & 0xffff; len = sg_len; - if ((addr + sg_len) > boundary) - len = boundary - addr; + if ((offset + sg_len) > 0x10000) + len = 0x10000 - offset; ap->prd[idx].addr = cpu_to_le32(addr); ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); @@ -1849,8 +1950,6 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen) sg->page = virt_to_page(buf); sg->offset = (unsigned long) buf & ~PAGE_MASK; sg_dma_len(sg) = buflen; - - WARN_ON(buflen > PAGE_SIZE); } void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, @@ -1875,13 +1974,13 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, static int ata_sg_setup_one(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - int dir = qc->pci_dma_dir; + int dir = qc->dma_dir; struct scatterlist *sg = qc->sg; dma_addr_t dma_address; - dma_address = pci_map_single(ap->host_set->pdev, qc->buf_virt, + dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, sg_dma_len(sg), dir); - if (pci_dma_mapping_error(dma_address)) + if (dma_mapping_error(dma_address)) return -1; sg_dma_address(sg) = dma_address; @@ -1912,8 +2011,8 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) VPRINTK("ENTER, ata%u\n", ap->id); assert(qc->flags & ATA_QCFLAG_SG); - dir = qc->pci_dma_dir; - n_elem = pci_map_sg(ap->host_set->pdev, sg, qc->n_elem, dir); + dir = qc->dma_dir; + n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir); if (n_elem < 1) return -1; @@ -2003,7 +2102,7 @@ static void ata_pio_complete (struct ata_port *ap) } drv_stat = ata_wait_idle(ap); - if (drv_stat & (ATA_BUSY | ATA_DRQ)) { + if (!ata_ok(drv_stat)) { ap->pio_task_state = PIO_ST_ERR; return; } @@ -2018,30 +2117,197 @@ static void ata_pio_complete (struct ata_port *ap) ata_qc_complete(qc, drv_stat); } -/** - * ata_pio_sector - - * @ap: - * - * LOCKING: - */ +void swap_buf_le16(u16 *buf, unsigned int buf_words) +{ +#ifdef __BIG_ENDIAN + unsigned int i; + + for (i = 0; i < buf_words; i++) + buf[i] = le16_to_cpu(buf[i]); +#endif /* __BIG_ENDIAN */ +} -static void ata_pio_sector(struct ata_port *ap) +static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int write_data) { - struct ata_queued_cmd *qc; - struct scatterlist *sg; - struct page *page; - unsigned char *buf; - u8 status; + unsigned int i; + unsigned int words = buflen >> 1; + u16 *buf16 = (u16 *) buf; + void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; - /* - * This is purely hueristic. This is a fast path. - * Sometimes when we enter, BSY will be cleared in - * a chk-status or two. If not, the drive is probably seeking - * or something. Snooze for a couple msecs, then - * chk-status again. If still busy, fall back to - * PIO_ST_POLL state. - */ - status = ata_busy_wait(ap, ATA_BUSY, 5); + if (write_data) { + for (i = 0; i < words; i++) + writew(le16_to_cpu(buf16[i]), mmio); + } else { + for (i = 0; i < words; i++) + buf16[i] = cpu_to_le16(readw(mmio)); + } +} + +static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned int dwords = buflen >> 1; + + if (write_data) + outsw(ap->ioaddr.data_addr, buf, dwords); + else + insw(ap->ioaddr.data_addr, buf, dwords); +} + +static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, + unsigned int buflen, int do_write) +{ + if (ap->flags & ATA_FLAG_MMIO) + ata_mmio_data_xfer(ap, buf, buflen, do_write); + else + ata_pio_data_xfer(ap, buf, buflen, do_write); +} + +static void ata_pio_sector(struct ata_queued_cmd *qc) +{ + int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct page *page; + unsigned int offset; + unsigned char *buf; + + if (qc->cursect == (qc->nsect - 1)) + ap->pio_task_state = PIO_ST_LAST; + + page = sg[qc->cursg].page; + offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE; + + /* get the current page and offset */ + page = nth_page(page, (offset >> PAGE_SHIFT)); + offset %= PAGE_SIZE; + + buf = kmap(page) + offset; + + qc->cursect++; + qc->cursg_ofs++; + + if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { + qc->cursg++; + qc->cursg_ofs = 0; + } + + DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + + /* do the actual data transfer */ + do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); + + kunmap(page); +} + +static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) +{ + int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct page *page; + unsigned char *buf; + unsigned int offset, count; + + if (qc->curbytes == qc->nbytes - bytes) + ap->pio_task_state = PIO_ST_LAST; + +next_sg: + sg = &qc->sg[qc->cursg]; + +next_page: + page = sg->page; + offset = sg->offset + qc->cursg_ofs; + + /* get the current page and offset */ + page = nth_page(page, (offset >> PAGE_SHIFT)); + offset %= PAGE_SIZE; + + count = min(sg_dma_len(sg) - qc->cursg_ofs, bytes); + + /* don't cross page boundaries */ + count = min(count, (unsigned int)PAGE_SIZE - offset); + + buf = kmap(page) + offset; + + bytes -= count; + qc->curbytes += count; + qc->cursg_ofs += count; + + if (qc->cursg_ofs == sg_dma_len(sg)) { + qc->cursg++; + qc->cursg_ofs = 0; + } + + DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + + /* do the actual data transfer */ + ata_data_xfer(ap, buf, count, do_write); + + kunmap(page); + + if (bytes) { + if (qc->cursg_ofs < sg_dma_len(sg)) + goto next_page; + goto next_sg; + } +} + +static void atapi_pio_bytes(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_device *dev = qc->dev; + unsigned int ireason, bc_lo, bc_hi, bytes; + int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0; + + ap->ops->tf_read(ap, &qc->tf); + ireason = qc->tf.nsect; + bc_lo = qc->tf.lbam; + bc_hi = qc->tf.lbah; + bytes = (bc_hi << 8) | bc_lo; + + /* shall be cleared to zero, indicating xfer of data */ + if (ireason & (1 << 0)) + goto err_out; + + /* make sure transfer direction matches expected */ + i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; + if (do_write != i_write) + goto err_out; + + __atapi_pio_bytes(qc, bytes); + + return; + +err_out: + printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", + ap->id, dev->devno); + ap->pio_task_state = PIO_ST_ERR; +} + +/** + * ata_pio_sector - + * @ap: + * + * LOCKING: + */ + +static void ata_pio_block(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + u8 status; + + /* + * This is purely hueristic. This is a fast path. + * Sometimes when we enter, BSY will be cleared in + * a chk-status or two. If not, the drive is probably seeking + * or something. Snooze for a couple msecs, then + * chk-status again. If still busy, fall back to + * PIO_ST_POLL state. + */ + status = ata_busy_wait(ap, ATA_BUSY, 5); if (status & ATA_BUSY) { msleep(2); status = ata_busy_wait(ap, ATA_BUSY, 10); @@ -2052,45 +2318,49 @@ static void ata_pio_sector(struct ata_port *ap) } } - /* handle BSY=0, DRQ=0 as error */ - if ((status & ATA_DRQ) == 0) { - ap->pio_task_state = PIO_ST_ERR; - return; - } - qc = ata_qc_from_tag(ap, ap->active_tag); assert(qc != NULL); - sg = qc->sg; - - if (qc->cursect == (qc->nsect - 1)) - ap->pio_task_state = PIO_ST_LAST; + if (is_atapi_taskfile(&qc->tf)) { + /* no more data to transfer or unsupported ATAPI command */ + if ((status & ATA_DRQ) == 0) { + ap->pio_task_state = PIO_ST_IDLE; - page = sg[qc->cursg].page; - buf = kmap(page) + - sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE); + ata_irq_on(ap); - qc->cursect++; - qc->cursg_ofs++; + ata_qc_complete(qc, status); + return; + } - if (qc->flags & ATA_QCFLAG_SG) - if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) { - qc->cursg++; - qc->cursg_ofs = 0; + atapi_pio_bytes(qc); + } else { + /* handle BSY=0, DRQ=0 as error */ + if ((status & ATA_DRQ) == 0) { + ap->pio_task_state = PIO_ST_ERR; + return; } - DPRINTK("data %s, drv_stat 0x%X\n", - qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read", - status); + ata_pio_sector(qc); + } +} + +static void ata_pio_error(struct ata_port *ap) +{ + struct ata_queued_cmd *qc; + u8 drv_stat; - /* do the actual data transfer */ - /* FIXME: mmio-ize */ - if (qc->tf.flags & ATA_TFLAG_WRITE) - outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); - else - insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS); + qc = ata_qc_from_tag(ap, ap->active_tag); + assert(qc != NULL); - kunmap(page); + drv_stat = ata_chk_status(ap); + printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n", + ap->id, drv_stat); + + ap->pio_task_state = PIO_ST_IDLE; + + ata_irq_on(ap); + + ata_qc_complete(qc, drv_stat | ATA_ERR); } static void ata_pio_task(void *_data) @@ -2100,7 +2370,7 @@ static void ata_pio_task(void *_data) switch (ap->pio_task_state) { case PIO_ST: - ata_pio_sector(ap); + ata_pio_block(ap); break; case PIO_ST_LAST: @@ -2113,15 +2383,8 @@ static void ata_pio_task(void *_data) break; case PIO_ST_TMOUT: - printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; - break; - case PIO_ST_ERR: - printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */ - ap->id); - timeout = 11 * HZ; + ata_pio_error(ap); break; } @@ -2136,6 +2399,59 @@ static void ata_pio_task(void *_data) } } +static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, + struct scsi_cmnd *cmd) +{ + DECLARE_COMPLETION(wait); + struct ata_queued_cmd *qc; + unsigned long flags; + int using_pio = dev->flags & ATA_DFLAG_PIO; + int rc; + + DPRINTK("ATAPI request sense\n"); + + qc = ata_qc_new_init(ap, dev); + BUG_ON(qc == NULL); + + /* FIXME: is this needed? */ + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + + ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); + qc->dma_dir = DMA_FROM_DEVICE; + + memset(&qc->cdb, 0, sizeof(ap->cdb_len)); + qc->cdb[0] = REQUEST_SENSE; + qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; + + qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + qc->tf.command = ATA_CMD_PACKET; + + if (using_pio) { + qc->tf.protocol = ATA_PROT_ATAPI; + qc->tf.lbam = (8 * 1024) & 0xff; + qc->tf.lbah = (8 * 1024) >> 8; + + qc->nbytes = SCSI_SENSE_BUFFERSIZE; + } else { + qc->tf.protocol = ATA_PROT_ATAPI_DMA; + qc->tf.feature |= ATAPI_PKT_DMA; + } + + qc->waiting = &wait; + qc->complete_fn = ata_qc_complete_noop; + + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + if (rc) + ata_port_disable(ap); + else + wait_for_completion(&wait); + + DPRINTK("EXIT\n"); +} + /** * ata_qc_timeout - Handle timeout of queued command * @qc: Command that timed out @@ -2157,10 +2473,29 @@ static void ata_pio_task(void *_data) static void ata_qc_timeout(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + struct ata_device *dev = qc->dev; u8 host_stat = 0, drv_stat; DPRINTK("ENTER\n"); + /* FIXME: doesn't this conflict with timeout handling? */ + if (qc->dev->class == ATA_DEV_ATAPI && qc->scsicmd) { + struct scsi_cmnd *cmd = qc->scsicmd; + + if (!scsi_eh_eflags_chk(cmd, SCSI_EH_CANCEL_CMD)) { + + /* finish completing original command */ + __ata_qc_complete(qc); + + atapi_request_sense(ap, dev, cmd); + + cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); + scsi_finish_command(cmd); + + goto out; + } + } + /* hack alert! We cannot use the supplied completion * function from inside the ->eh_strategy_handler() thread. * libata is the only user of ->eh_strategy_handler() in @@ -2180,7 +2515,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* fall through */ - case ATA_PROT_NODATA: default: ata_altstatus(ap); drv_stat = ata_chk_status(ap); @@ -2195,7 +2529,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ata_qc_complete(qc, drv_stat); break; } - +out: DPRINTK("EXIT\n"); } @@ -2284,11 +2618,10 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, qc->dev = dev; qc->cursect = qc->cursg = qc->cursg_ofs = 0; qc->nsect = 0; + qc->nbytes = qc->curbytes = 0; ata_tf_init(ap, &qc->tf, dev->devno); - if (likely((dev->flags & ATA_DFLAG_PIO) == 0)) - qc->flags |= ATA_QCFLAG_DMA; if (dev->flags & ATA_DFLAG_LBA48) qc->tf.flags |= ATA_TFLAG_LBA48; } @@ -2296,6 +2629,35 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, return qc; } +static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat) +{ + return 0; +} + +static void __ata_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int tag, do_clear = 0; + + qc->flags = 0; + tag = qc->tag; + if (likely(ata_tag_valid(tag))) { + if (tag == ap->active_tag) + ap->active_tag = ATA_TAG_POISON; + qc->tag = ATA_TAG_POISON; + do_clear = 1; + } + + if (qc->waiting) { + struct completion *waiting = qc->waiting; + qc->waiting = NULL; + complete(waiting); + } + + if (likely(do_clear)) + clear_bit(tag, &ap->qactive); +} + /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete @@ -2307,8 +2669,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) { - struct ata_port *ap = qc->ap; - unsigned int tag, do_clear = 0; int rc; assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ @@ -2326,20 +2686,33 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) if (rc != 0) return; - qc->flags = 0; - tag = qc->tag; - if (likely(ata_tag_valid(tag))) { - if (tag == ap->active_tag) - ap->active_tag = ATA_TAG_POISON; - qc->tag = ATA_TAG_POISON; - do_clear = 1; - } + __ata_qc_complete(qc); - if (qc->waiting) - complete(qc->waiting); + VPRINTK("EXIT\n"); +} - if (likely(do_clear)) - clear_bit(tag, &ap->qactive); +static inline int ata_should_dma_map(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + return 1; + + case ATA_PROT_ATAPI: + case ATA_PROT_PIO: + case ATA_PROT_PIO_MULT: + if (ap->flags & ATA_FLAG_PIO_DMA) + return 1; + + /* fall through */ + + default: + return 0; + } + + /* never reached */ } /** @@ -2362,12 +2735,16 @@ int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - if (qc->flags & ATA_QCFLAG_SG) { - if (ata_sg_setup(qc)) - goto err_out; - } else if (qc->flags & ATA_QCFLAG_SINGLE) { - if (ata_sg_setup_one(qc)) - goto err_out; + if (ata_should_dma_map(qc)) { + if (qc->flags & ATA_QCFLAG_SG) { + if (ata_sg_setup(qc)) + goto err_out; + } else if (qc->flags & ATA_QCFLAG_SINGLE) { + if (ata_sg_setup_one(qc)) + goto err_out; + } + } else { + qc->flags &= ~ATA_QCFLAG_DMAMAP; } ap->ops->qc_prep(qc); @@ -2422,6 +2799,12 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI: + ata_qc_set_polling(qc); + ata_tf_to_host_nolock(ap, &qc->tf); + queue_work(ata_wq, &ap->packet_task); + break; + + case ATA_PROT_ATAPI_NODATA: ata_tf_to_host_nolock(ap, &qc->tf); queue_work(ata_wq, &ap->packet_task); break; @@ -2441,19 +2824,19 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) } /** - * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO) + * ata_bmdma_setup - Set up PCI IDE BMDMA transaction * @qc: Info associated with this ATA transaction. * * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) +static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); u8 dmactl; - void *mmio = (void *) ap->ioaddr.bmdma_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; /* load PRD table addr. */ mb(); /* make sure PRD table writes are visible to controller */ @@ -2471,17 +2854,17 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) } /** - * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO) + * ata_bmdma_start - Start a PCI IDE BMDMA transaction * @qc: Info associated with this ATA transaction. * * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) +static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void *mmio = (void *) ap->ioaddr.bmdma_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; u8 dmactl; /* start host DMA transaction */ @@ -2509,7 +2892,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ -void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) +static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); @@ -2537,7 +2920,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) * spin_lock_irqsave(host_set lock) */ -void ata_bmdma_start_pio (struct ata_queued_cmd *qc) +static void ata_bmdma_start_pio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; u8 dmactl; @@ -2548,6 +2931,22 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc) ap->ioaddr.bmdma_addr + ATA_DMA_CMD); } +void ata_bmdma_start(struct ata_queued_cmd *qc) +{ + if (qc->ap->flags & ATA_FLAG_MMIO) + ata_bmdma_start_mmio(qc); + else + ata_bmdma_start_pio(qc); +} + +void ata_bmdma_setup(struct ata_queued_cmd *qc) +{ + if (qc->ap->flags & ATA_FLAG_MMIO) + ata_bmdma_setup_mmio(qc); + else + ata_bmdma_setup_pio(qc); +} + void ata_bmdma_irq_clear(struct ata_port *ap) { ata_bmdma_ack_irq(ap); @@ -2581,7 +2980,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, case ATA_PROT_ATAPI: /* check status of DMA engine */ host_stat = ata_bmdma_status(ap); - VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat); + VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); /* if it's not our irq... */ if (!(host_stat & ATA_DMA_INTR)) @@ -2592,6 +2991,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* fall through */ + case ATA_PROT_ATAPI_NODATA: case ATA_PROT_NODATA: /* check altstatus */ status = ata_altstatus(ap); @@ -2602,7 +3002,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap, status = ata_chk_status(ap); if (unlikely(status & ATA_BUSY)) goto idle_irq; - DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status); + DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, status); /* ack bmdma irq events */ ata_bmdma_ack_irq(ap); @@ -2701,21 +3102,20 @@ static void atapi_packet_task(void *_data) /* make sure DRQ is set */ status = ata_chk_status(ap); - if ((status & ATA_DRQ) == 0) + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) goto err_out; /* send SCSI cdb */ - /* FIXME: mmio-ize */ DPRINTK("send cdb\n"); - outsl(ap->ioaddr.data_addr, - qc->scsicmd->cmnd, ap->host->max_cmd_len / 4); + assert(ap->cdb_len >= 12); + ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); /* if we are DMA'ing, irq handler takes over from here */ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ /* non-data commands are also handled via irq */ - else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) { + else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { /* do nothing */ } @@ -2733,9 +3133,9 @@ err_out: int ata_port_start (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; - ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma); + ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) return -ENOMEM; @@ -2746,9 +3146,9 @@ int ata_port_start (struct ata_port *ap) void ata_port_stop (struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; - pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); + dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } /** @@ -2794,7 +3194,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, host->max_channel = 1; host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - scsi_set_device(host, &ent->pdev->dev); + scsi_set_device(host, ent->dev); scsi_assign_lock(host, &host_set->lock); ap->flags = ATA_FLAG_PORT_DISABLED; @@ -2803,12 +3203,14 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->ctl = ATA_DEVCTL_OBS; ap->host_set = host_set; ap->port_no = port_no; + ap->hard_port_no = + ent->legacy_mode ? ent->hard_port_no : port_no; ap->pio_mask = ent->pio_mask; + ap->mwdma_mask = ent->mwdma_mask; ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; ap->cbl = ATA_CBL_NONE; - ap->device[0].flags = ATA_DFLAG_MASTER; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; @@ -2879,7 +3281,7 @@ err_out: int ata_device_add(struct ata_probe_ent *ent) { unsigned int count = 0, i; - struct pci_dev *pdev = ent->pdev; + struct device *dev = ent->dev; struct ata_host_set *host_set; DPRINTK("ENTER\n"); @@ -2891,7 +3293,7 @@ int ata_device_add(struct ata_probe_ent *ent) memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *))); spin_lock_init(&host_set->lock); - host_set->pdev = pdev; + host_set->dev = dev; host_set->n_ports = ent->n_ports; host_set->irq = ent->irq; host_set->mmio_base = ent->mmio_base; @@ -2901,19 +3303,23 @@ int ata_device_add(struct ata_probe_ent *ent) /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { struct ata_port *ap; + unsigned long xfer_mode_mask; ap = ata_host_add(ent, host_set, i); if (!ap) goto err_out; host_set->ports[i] = ap; + xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | + (ap->mwdma_mask << ATA_SHIFT_MWDMA) | + (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " "bmdma 0x%lX irq %lu\n", ap->id, ap->flags & ATA_FLAG_SATA ? 'S' : 'P', - ata_udma_string(ent->udma_mask), + ata_mode_string(xfer_mode_mask), ap->ioaddr.cmd_addr, ap->ioaddr.ctl_addr, ap->ioaddr.bmdma_addr, @@ -2955,7 +3361,7 @@ int ata_device_add(struct ata_probe_ent *ent) */ } - rc = scsi_add_host(ap->host, &pdev->dev); + rc = scsi_add_host(ap->host, dev); if (rc) { printk(KERN_ERR "ata%u: scsi_add_host failed\n", ap->id); @@ -2975,7 +3381,7 @@ int ata_device_add(struct ata_probe_ent *ent) scsi_scan_host(ap->host); } - pci_set_drvdata(pdev, host_set); + dev_set_drvdata(dev, host_set); VPRINTK("EXIT, returning %u\n", ent->n_ports); return ent->n_ports; /* success */ @@ -3035,6 +3441,104 @@ void ata_std_ports(struct ata_ioports *ioaddr) ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD; } +static struct ata_probe_ent * +ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port) +{ + struct ata_probe_ent *probe_ent; + int i; + + probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL); + if (!probe_ent) { + printk(KERN_ERR DRV_NAME "(%s): out of memory\n", + kobject_name(&(dev->kobj))); + return NULL; + } + + memset(probe_ent, 0, sizeof(*probe_ent) * n); + + for (i = 0; i < n; i++) { + INIT_LIST_HEAD(&probe_ent[i].node); + probe_ent[i].dev = dev; + + probe_ent[i].sht = port[i]->sht; + probe_ent[i].host_flags = port[i]->host_flags; + probe_ent[i].pio_mask = port[i]->pio_mask; + probe_ent[i].mwdma_mask = port[i]->mwdma_mask; + probe_ent[i].udma_mask = port[i]->udma_mask; + probe_ent[i].port_ops = port[i]->port_ops; + + } + + return probe_ent; +} + +#ifdef CONFIG_PCI +struct ata_probe_ent * +ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) +{ + struct ata_probe_ent *probe_ent = + ata_probe_ent_alloc(1, pci_dev_to_dev(pdev), port); + if (!probe_ent) + return NULL; + + probe_ent->n_ports = 2; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; + + ata_std_ports(&probe_ent->port[0]); + ata_std_ports(&probe_ent->port[1]); + + return probe_ent; +} + +struct ata_probe_ent * +ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port) +{ + struct ata_probe_ent *probe_ent = + ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port); + if (!probe_ent) + return NULL; + + probe_ent[0].n_ports = 1; + probe_ent[0].irq = 14; + + probe_ent[0].hard_port_no = 0; + probe_ent[0].legacy_mode = 1; + + probe_ent[1].n_ports = 1; + probe_ent[1].irq = 15; + + probe_ent[1].hard_port_no = 1; + probe_ent[1].legacy_mode = 1; + + probe_ent[0].port[0].cmd_addr = 0x1f0; + probe_ent[0].port[0].altstatus_addr = + probe_ent[0].port[0].ctl_addr = 0x3f6; + probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4); + + probe_ent[1].port[0].cmd_addr = 0x170; + probe_ent[1].port[0].altstatus_addr = + probe_ent[1].port[0].ctl_addr = 0x376; + probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; + + ata_std_ports(&probe_ent[0].port[0]); + ata_std_ports(&probe_ent[1].port[0]); + + return probe_ent; +} + /** * ata_pci_init_one - Initialize/register PCI IDE host controller * @pdev: Controller to be initialized @@ -3052,20 +3556,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, unsigned int n_ports) { struct ata_probe_ent *probe_ent, *probe_ent2 = NULL; - struct ata_port_info *port0, *port1; + struct ata_port_info *port[2]; u8 tmp8, mask; unsigned int legacy_mode = 0; int rc; DPRINTK("ENTER\n"); - port0 = port_info[0]; + port[0] = port_info[0]; if (n_ports > 1) - port1 = port_info[1]; + port[1] = port_info[1]; else - port1 = port0; + port[1] = port[0]; - if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) { + if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) { /* TODO: support transitioning to native mode? */ pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); mask = (1 << 2) | (1 << 0); @@ -3126,75 +3630,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (legacy_mode) { + probe_ent = ata_pci_init_legacy_mode(pdev, port); + if (probe_ent) + probe_ent2 = &probe_ent[1]; + } else + probe_ent = ata_pci_init_native_mode(pdev, port); if (!probe_ent) { rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; - INIT_LIST_HEAD(&probe_ent->node); - - if (legacy_mode) { - probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL); - if (!probe_ent2) { - rc = -ENOMEM; - goto err_out_free_ent; - } - - memset(probe_ent2, 0, sizeof(*probe_ent)); - probe_ent2->pdev = pdev; - INIT_LIST_HEAD(&probe_ent2->node); - } - - probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); - probe_ent->sht = port0->sht; - probe_ent->host_flags = port0->host_flags; - probe_ent->pio_mask = port0->pio_mask; - probe_ent->udma_mask = port0->udma_mask; - probe_ent->port_ops = port0->port_ops; - - if (legacy_mode) { - probe_ent->port[0].cmd_addr = 0x1f0; - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = 0x3f6; - probe_ent->n_ports = 1; - probe_ent->irq = 14; - ata_std_ports(&probe_ent->port[0]); - - probe_ent2->port[0].cmd_addr = 0x170; - probe_ent2->port[0].altstatus_addr = - probe_ent2->port[0].ctl_addr = 0x376; - probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; - probe_ent2->n_ports = 1; - probe_ent2->irq = 15; - ata_std_ports(&probe_ent2->port[0]); - - probe_ent2->sht = port1->sht; - probe_ent2->host_flags = port1->host_flags; - probe_ent2->pio_mask = port1->pio_mask; - probe_ent2->udma_mask = port1->udma_mask; - probe_ent2->port_ops = port1->port_ops; - } else { - probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); - ata_std_ports(&probe_ent->port[0]); - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - - probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); - ata_std_ports(&probe_ent->port[1]); - probe_ent->port[1].altstatus_addr = - probe_ent->port[1].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; - - probe_ent->n_ports = 2; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - } - pci_set_master(pdev); /* FIXME: check ata_device_add return */ @@ -3203,17 +3649,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ata_device_add(probe_ent); if (legacy_mode & (1 << 1)) ata_device_add(probe_ent2); - kfree(probe_ent2); } else { ata_device_add(probe_ent); - assert(probe_ent2 == NULL); } kfree(probe_ent); return 0; -err_out_free_ent: - kfree(probe_ent); err_out_regions: if (legacy_mode & (1 << 0)) release_region(0x1f0, 8); @@ -3241,7 +3683,8 @@ err_out: void ata_pci_remove_one (struct pci_dev *pdev) { - struct ata_host_set *host_set = pci_get_drvdata(pdev); + struct device *dev = pci_dev_to_dev(pdev); + struct ata_host_set *host_set = dev_get_drvdata(dev); struct ata_port *ap; unsigned int i; @@ -3282,7 +3725,7 @@ void ata_pci_remove_one (struct pci_dev *pdev) kfree(host_set); pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); + dev_set_drvdata(dev, NULL); } /* move to PCI subsystem */ @@ -3318,6 +3761,7 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits) return (tmp == bits->val) ? 1 : 0; } +#endif /* CONFIG_PCI */ /** @@ -3354,7 +3798,6 @@ module_exit(ata_exit); * Do not depend on ABI/API stability. */ -EXPORT_SYMBOL_GPL(pci_test_config_bits); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); @@ -3363,34 +3806,40 @@ EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_qc_complete); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_eng_timeout); -EXPORT_SYMBOL_GPL(ata_tf_load_pio); -EXPORT_SYMBOL_GPL(ata_tf_load_mmio); -EXPORT_SYMBOL_GPL(ata_tf_read_pio); -EXPORT_SYMBOL_GPL(ata_tf_read_mmio); +EXPORT_SYMBOL_GPL(ata_tf_load); +EXPORT_SYMBOL_GPL(ata_tf_read); +EXPORT_SYMBOL_GPL(ata_noop_dev_select); +EXPORT_SYMBOL_GPL(ata_std_dev_select); EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); -EXPORT_SYMBOL_GPL(ata_check_status_pio); -EXPORT_SYMBOL_GPL(ata_check_status_mmio); -EXPORT_SYMBOL_GPL(ata_exec_command_pio); -EXPORT_SYMBOL_GPL(ata_exec_command_mmio); +EXPORT_SYMBOL_GPL(ata_check_status); +EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); -EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio); -EXPORT_SYMBOL_GPL(ata_bmdma_start_pio); -EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio); -EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio); +EXPORT_SYMBOL_GPL(ata_bmdma_setup); +EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); +EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_port_disable); -EXPORT_SYMBOL_GPL(ata_pci_init_one); -EXPORT_SYMBOL_GPL(ata_pci_remove_one); +EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); +EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_id_string); +EXPORT_SYMBOL_GPL(ata_scsi_simulate); + +#ifdef CONFIG_PCI +EXPORT_SYMBOL_GPL(pci_test_config_bits); +EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode); +EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); +EXPORT_SYMBOL_GPL(ata_pci_init_one); +EXPORT_SYMBOL_GPL(ata_pci_remove_one); +#endif /* CONFIG_PCI */ diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b3340607b..36320e8a3 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -29,13 +29,13 @@ #include "scsi.h" #include #include +#include #include "libata.h" typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd); -static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)); +static struct ata_device * +ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev); /** @@ -67,6 +67,43 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, return 0; } +int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) +{ + struct ata_port *ap; + struct ata_device *dev; + int val = -EINVAL, rc = -EINVAL; + + ap = (struct ata_port *) &scsidev->host->hostdata[0]; + if (!ap) + goto out; + + dev = ata_scsi_find_dev(ap, scsidev); + if (!dev) { + rc = -ENODEV; + goto out; + } + + switch (cmd) { + case ATA_IOC_GET_IO32: + val = 0; + if (copy_to_user(arg, &val, 1)) + return -EFAULT; + return 0; + + case ATA_IOC_SET_IO32: + val = (unsigned long) arg; + if (val != 0) + return -EINVAL; + return 0; + + default: + rc = -ENOTTY; + break; + } + +out: + return rc; +} /** * ata_scsi_qc_new - acquire new ata_queued_cmd reference @@ -119,35 +156,160 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, /** * ata_to_sense_error - convert ATA error to SCSI error * @qc: Command that we are erroring out + * @drv_stat: value contained in ATA status register * - * Converts an ATA error into a SCSI error. - * - * Right now, this routine is laughably primitive. We - * don't even examine what ATA told us, we just look at - * the command data direction, and return a fatal SCSI - * sense error based on that. + * Converts an ATA error into a SCSI error. While we are at it + * we decode and dump the ATA error for the user so that they + * have some idea what really happened at the non make-believe + * layer. * * LOCKING: * spin_lock_irqsave(host_set lock) */ -void ata_to_sense_error(struct ata_queued_cmd *qc) +void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) { struct scsi_cmnd *cmd = qc->scsicmd; + u8 err = 0; + unsigned char *sb = cmd->sense_buffer; + /* Based on the 3ware driver translation table */ + static unsigned char sense_table[][4] = { + /* BBD|ECC|ID|MAR */ + {0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + /* BBD|ECC|ID */ + {0xd0, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command + /* ECC|MC|MARK */ + {0x61, HARDWARE_ERROR, 0x00, 0x00}, // Device fault Hardware error + /* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */ + {0x84, ABORTED_COMMAND, 0x47, 0x00}, // Data CRC error SCSI parity error + /* MC|ID|ABRT|TRK0|MARK */ + {0x37, NOT_READY, 0x04, 0x00}, // Unit offline Not ready + /* MCR|MARK */ + {0x09, NOT_READY, 0x04, 0x00}, // Unrecovered disk error Not ready + /* Bad address mark */ + {0x01, MEDIUM_ERROR, 0x13, 0x00}, // Address mark not found Address mark not found for data field + /* TRK0 */ + {0x02, HARDWARE_ERROR, 0x00, 0x00}, // Track 0 not found Hardware error + /* Abort & !ICRC */ + {0x04, ABORTED_COMMAND, 0x00, 0x00}, // Aborted command Aborted command + /* Media change request */ + {0x08, NOT_READY, 0x04, 0x00}, // Media change request FIXME: faking offline + /* SRV */ + {0x10, ABORTED_COMMAND, 0x14, 0x00}, // ID not found Recorded entity not found + /* Media change */ + {0x08, NOT_READY, 0x04, 0x00}, // Media change FIXME: faking offline + /* ECC */ + {0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error + /* BBD - block marked bad */ + {0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error + {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + static unsigned char stat_table[][4] = { + /* Must be first because BUSY means no other bits valid */ + {0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now + {0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault + {0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now + {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered + {0xFF, 0xFF, 0xFF, 0xFF}, // END mark + }; + int i = 0; cmd->result = SAM_STAT_CHECK_CONDITION; - - cmd->sense_buffer[0] = 0x70; - cmd->sense_buffer[2] = MEDIUM_ERROR; - cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ - + + /* + * Is this an error we can process/parse + */ + + if(drv_stat & ATA_ERR) + /* Read the err bits */ + err = ata_chk_err(qc->ap); + + /* Display the ATA level error info */ + + printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat); + if(drv_stat & 0x80) + { + printk("Busy "); + err = 0; /* Data is not valid in this case */ + } + else { + if(drv_stat & 0x40) printk("DriveReady "); + if(drv_stat & 0x20) printk("DeviceFault "); + if(drv_stat & 0x10) printk("SeekComplete "); + if(drv_stat & 0x08) printk("DataRequest "); + if(drv_stat & 0x04) printk("CorrectedError "); + if(drv_stat & 0x02) printk("Index "); + if(drv_stat & 0x01) printk("Error "); + } + printk("}\n"); + + if(err) + { + printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err); + if(err & 0x04) printk("DriveStatusError "); + if(err & 0x80) + { + if(err & 0x04) + printk("BadCRC "); + else + printk("Sector "); + } + if(err & 0x40) printk("UncorrectableError "); + if(err & 0x10) printk("SectorIdNotFound "); + if(err & 0x02) printk("TrackZeroNotFound "); + if(err & 0x01) printk("AddrMarkNotFound "); + printk("}\n"); + + /* Should we dump sector info here too ?? */ + } + + + /* Look for err */ + while(sense_table[i][0] != 0xFF) + { + /* Look for best matches first */ + if((sense_table[i][0] & err) == sense_table[i][0]) + { + sb[0] = 0x70; + sb[2] = sense_table[i][1]; + sb[7] = 0x0a; + sb[12] = sense_table[i][2]; + sb[13] = sense_table[i][3]; + return; + } + i++; + } + /* No immediate match */ + if(err) + printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err); + + /* Fall back to interpreting status bits */ + while(stat_table[i][0] != 0xFF) + { + if(stat_table[i][0] & drv_stat) + { + sb[0] = 0x70; + sb[2] = stat_table[i][1]; + sb[7] = 0x0a; + sb[12] = stat_table[i][2]; + sb[13] = stat_table[i][3]; + return; + } + i++; + } + /* No error ?? */ + printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); /* additional-sense-code[-qualifier] */ + + sb[0] = 0x70; + sb[2] = MEDIUM_ERROR; + sb[7] = 0x0A; if (cmd->sc_data_direction == SCSI_DATA_READ) { - cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */ - cmd->sense_buffer[13] = 0x04; + sb[12] = 0x11; /* "unrecovered read error" */ + sb[13] = 0x04; } else { - cmd->sense_buffer[12] = 0x0C; /* "write error - */ - cmd->sense_buffer[13] = 0x02; /* auto-reallocation failed" */ + sb[12] = 0x0C; /* "write error - */ + sb[13] = 0x02; /* auto-reallocation failed" */ } } @@ -214,10 +376,134 @@ int ata_scsi_error(struct Scsi_Host *host) ap = (struct ata_port *) &host->hostdata[0]; ap->ops->eng_timeout(ap); + /* TODO: this is per-command; when queueing is supported + * this code will either change or move to a more + * appropriate place + */ + host->host_failed--; + DPRINTK("EXIT\n"); return 0; } +/** + * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command + * @qc: Storage for translated ATA taskfile + * @scsicmd: SCSI command to translate (ignored) + * + * Sets up an ATA taskfile to issue FLUSH CACHE or + * FLUSH CACHE EXT. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &qc->tf; + + tf->flags |= ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; + + if ((tf->flags & ATA_TFLAG_LBA48) && + (ata_id_has_flush_ext(qc->dev->id))) + tf->command = ATA_CMD_FLUSH_EXT; + else + tf->command = ATA_CMD_FLUSH; + + return 0; +} + +/** + * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one + * @qc: Storage for translated ATA taskfile + * @scsicmd: SCSI command to translate + * + * Converts SCSI VERIFY command to an ATA READ VERIFY command. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) +{ + struct ata_taskfile *tf = &qc->tf; + unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; + u64 dev_sectors = qc->dev->n_sectors; + u64 sect = 0; + u32 n_sect = 0; + + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; + tf->device |= ATA_LBA; + + if (scsicmd[0] == VERIFY) { + sect |= ((u64)scsicmd[2]) << 24; + sect |= ((u64)scsicmd[3]) << 16; + sect |= ((u64)scsicmd[4]) << 8; + sect |= ((u64)scsicmd[5]); + + n_sect |= ((u32)scsicmd[7]) << 8; + n_sect |= ((u32)scsicmd[8]); + } + + else if (scsicmd[0] == VERIFY_16) { + sect |= ((u64)scsicmd[2]) << 56; + sect |= ((u64)scsicmd[3]) << 48; + sect |= ((u64)scsicmd[4]) << 40; + sect |= ((u64)scsicmd[5]) << 32; + sect |= ((u64)scsicmd[6]) << 24; + sect |= ((u64)scsicmd[7]) << 16; + sect |= ((u64)scsicmd[8]) << 8; + sect |= ((u64)scsicmd[9]); + + n_sect |= ((u32)scsicmd[10]) << 24; + n_sect |= ((u32)scsicmd[11]) << 16; + n_sect |= ((u32)scsicmd[12]) << 8; + n_sect |= ((u32)scsicmd[13]); + } + + else + return 1; + + if (!n_sect) + return 1; + if (sect >= dev_sectors) + return 1; + if ((sect + n_sect) > dev_sectors) + return 1; + if (lba48) { + if (n_sect > (64 * 1024)) + return 1; + } else { + if (n_sect > 256) + return 1; + } + + if (lba48) { + tf->hob_nsect = (n_sect >> 8) & 0xff; + + tf->hob_lbah = (sect >> 40) & 0xff; + tf->hob_lbam = (sect >> 32) & 0xff; + tf->hob_lbal = (sect >> 24) & 0xff; + } else + tf->device |= (sect >> 24) & 0xf; + + tf->nsect = n_sect & 0xff; + + tf->hob_lbah = (sect >> 16) & 0xff; + tf->hob_lbam = (sect >> 8) & 0xff; + tf->hob_lbal = sect & 0xff; + + return 0; +} + /** * ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one * @qc: Storage for translated ATA taskfile @@ -244,10 +530,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; - tf->hob_nsect = 0; - tf->hob_lbal = 0; - tf->hob_lbam = 0; - tf->hob_lbah = 0; tf->protocol = qc->dev->xfer_protocol; tf->device |= ATA_LBA; @@ -339,14 +621,10 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) { struct scsi_cmnd *cmd = qc->scsicmd; - if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { - if (is_atapi_taskfile(&qc->tf)) - cmd->result = SAM_STAT_CHECK_CONDITION; - else - ata_to_sense_error(qc); - } else { + if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) + ata_to_sense_error(qc, drv_stat); + else cmd->result = SAM_STAT_GOOD; - } qc->scsidone(cmd); @@ -401,7 +679,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ata_sg_init_one(qc, cmd->request_buffer, cmd->request_bufflen); - qc->pci_dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + qc->dma_dir = cmd->sc_data_direction; } qc->complete_fn = ata_scsi_qc_complete; @@ -451,7 +729,6 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) buflen = cmd->request_bufflen; } - memset(buf, 0, buflen); *buf_out = buf; return buflen; } @@ -459,6 +736,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) /** * ata_scsi_rbuf_put - Unmap response buffer. * @cmd: SCSI command containing buffer to be unmapped. + * @buf: buffer to unmap * * Unmaps response buffer contained within @cmd. * @@ -466,19 +744,19 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) * spin_lock_irqsave(host_set lock) */ -static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd) +static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf) { if (cmd->use_sg) { struct scatterlist *sg; sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(sg->page, KM_USER0); + kunmap_atomic(buf - sg->offset, KM_USER0); } } /** * ata_scsi_rbuf_fill - wrapper for SCSI command simulators - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @actor: Callback hook for desired SCSI command simulator * * Takes care of the hard work of simulating a SCSI command... @@ -500,8 +778,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, struct scsi_cmnd *cmd = args->cmd; buflen = ata_scsi_rbuf_get(cmd, &rbuf); + memset(rbuf, 0, buflen); rc = actor(args, rbuf, buflen); - ata_scsi_rbuf_put(cmd); + ata_scsi_rbuf_put(cmd, rbuf); if (rc) ata_bad_cdb(cmd, args->done); @@ -513,7 +792,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, /** * ata_scsiop_inq_std - Simulate INQUIRY command - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -527,28 +806,26 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - struct ata_device *dev = args->dev; - u8 hdr[] = { TYPE_DISK, 0, 0x5, /* claim SPC-3 version compatibility */ 2, - 96 - 4 + 95 - 4 }; /* set scsi removeable (RMB) bit per ata bit */ - if (ata_id_removeable(dev)) + if (ata_id_removeable(args->id)) hdr[1] |= (1 << 7); VPRINTK("ENTER\n"); memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > 36) { + if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_dev_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); + ata_dev_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -572,7 +849,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, /** * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -600,7 +877,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, /** * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -621,8 +898,8 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, }; memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > (ATA_SERNO_LEN + 4)) - ata_dev_id_string(args->dev, (unsigned char *) &rbuf[4], + if (buflen > (ATA_SERNO_LEN + 4 - 1)) + ata_dev_id_string(args->id, (unsigned char *) &rbuf[4], ATA_ID_SERNO_OFS, ATA_SERNO_LEN); return 0; @@ -632,7 +909,7 @@ static const char *inq_83_str = "Linux ATA-SCSI simulator"; /** * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -650,7 +927,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, rbuf[3] = 4 + strlen(inq_83_str); /* page len */ /* our one and only identification descriptor (vendor-specific) */ - if (buflen > (strlen(inq_83_str) + 4 + 4)) { + if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) { rbuf[4 + 0] = 2; /* code set: ASCII */ rbuf[4 + 3] = strlen(inq_83_str); memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); @@ -661,7 +938,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, /** * ata_scsiop_noop - - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -709,7 +986,7 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last, /** * ata_msense_caching - Simulate MODE SENSE caching info page - * @dev: Device associated with this MODE SENSE command + * @id: device IDENTIFY data * @ptr_io: (input/output) Location to store more output data * @last: End of output data buffer * @@ -721,7 +998,7 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last, * None. */ -static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io, +static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, const u8 *last) { u8 page[] = { @@ -731,9 +1008,9 @@ static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io, 0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */ }; - if (ata_id_wcache_enabled(dev)) + if (ata_id_wcache_enabled(id)) page[2] |= (1 << 2); /* write cache enable */ - if (!ata_id_rahead_enabled(dev)) + if (!ata_id_rahead_enabled(id)) page[12] |= (1 << 5); /* disable read ahead */ ata_msense_push(ptr_io, last, page, sizeof(page)); @@ -787,7 +1064,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) /** * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -801,7 +1078,6 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { u8 *scsicmd = args->cmd->cmnd, *p, *last; - struct ata_device *dev = args->dev; unsigned int page_control, six_byte, output_len; VPRINTK("ENTER\n"); @@ -829,7 +1105,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, break; case 0x08: /* caching */ - output_len += ata_msense_caching(dev, &p, last); + output_len += ata_msense_caching(args->id, &p, last); break; case 0x0a: { /* control mode */ @@ -839,7 +1115,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, case 0x3f: /* all pages */ output_len += ata_msense_rw_recovery(&p, last); - output_len += ata_msense_caching(dev, &p, last); + output_len += ata_msense_caching(args->id, &p, last); output_len += ata_msense_ctl_mode(&p, last); break; @@ -861,7 +1137,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, /** * ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -874,11 +1150,15 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - u64 n_sectors = args->dev->n_sectors; + u64 n_sectors; u32 tmp; VPRINTK("ENTER\n"); + if (ata_id_has_lba48(args->id)) + n_sectors = ata_id_u64(args->id, 100); + else + n_sectors = ata_id_u32(args->id, 60); n_sectors--; /* ATA TotalUserSectors - 1 */ tmp = n_sectors; /* note: truncates, if lba48 */ @@ -916,7 +1196,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, /** * ata_scsiop_report_luns - Simulate REPORT LUNS command - * @args: Port / device / SCSI command of interest. + * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * @@ -964,6 +1244,37 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 done(cmd); } +static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + + if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { + DPRINTK("request check condition\n"); + + cmd->result = SAM_STAT_CHECK_CONDITION; + + qc->scsidone(cmd); + + return 1; + } else { + u8 *scsicmd = cmd->cmnd; + + if (scsicmd[0] == INQUIRY) { + u8 *buf = NULL; + unsigned int buflen; + + buflen = ata_scsi_rbuf_get(cmd, &buf); + buf[2] = 0x5; + buf[3] = (buf[3] & 0xf0) | 2; + ata_scsi_rbuf_put(cmd, buf); + } + cmd->result = SAM_STAT_GOOD; + } + + qc->scsidone(cmd); + + return 0; +} /** * atapi_xlat - Initialize PACKET taskfile * @qc: command structure to be initialized @@ -979,6 +1290,13 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_device *dev = qc->dev; + int using_pio = (dev->flags & ATA_DFLAG_PIO); + int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); + + memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); + + qc->complete_fn = atapi_qc_complete; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (cmd->sc_data_direction == SCSI_DATA_WRITE) { @@ -988,19 +1306,18 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) qc->tf.command = ATA_CMD_PACKET; - /* no data - interrupt-driven */ - if (cmd->sc_data_direction == SCSI_DATA_NONE) - qc->tf.protocol = ATA_PROT_ATAPI; - - /* PIO data xfer - polling */ - else if ((qc->flags & ATA_QCFLAG_DMA) == 0) { - ata_qc_set_polling(qc); - qc->tf.protocol = ATA_PROT_ATAPI; + /* no data, or PIO data xfer */ + if (using_pio || nodata) { + if (nodata) + qc->tf.protocol = ATA_PROT_ATAPI_NODATA; + else + qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbah = (8 * 1024) >> 8; + } - /* DMA data xfer - interrupt-driven */ - } else { + /* DMA data xfer */ + else { qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; @@ -1011,13 +1328,15 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) #endif } + qc->nbytes = cmd->bufflen; + return 0; } /** * ata_scsi_find_dev - lookup ata_device from scsi_cmnd * @ap: ATA port to which the device is attached - * @cmd: SCSI command to be sent to the device + * @scsidev: SCSI device from which we derive the ATA device * * Given various information provided in struct scsi_cmnd, * map that onto an ATA bus, and using that mapping @@ -1031,19 +1350,19 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) * Associated ATA device, or %NULL if not found. */ -static inline struct ata_device * -ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd) +static struct ata_device * +ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev) { struct ata_device *dev; /* skip commands not addressed to targets we simulate */ - if (likely(cmd->device->id < ATA_MAX_DEVICES)) - dev = &ap->device[cmd->device->id]; + if (likely(scsidev->id < ATA_MAX_DEVICES)) + dev = &ap->device[scsidev->id]; else return NULL; - if (unlikely((cmd->device->channel != 0) || - (cmd->device->lun != 0))) + if (unlikely((scsidev->channel != 0) || + (scsidev->lun != 0))) return NULL; if (unlikely(!ata_dev_present(dev))) @@ -1059,6 +1378,7 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd) /** * ata_get_xlat_func - check if SCSI to ATA translation is possible + * @dev: ATA device * @cmd: SCSI command opcode to consider * * Look up the SCSI command given, and determine whether the @@ -1068,7 +1388,7 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd) * Pointer to translation function if possible, %NULL if not. */ -static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd) +static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) { switch (cmd) { case READ_6: @@ -1079,6 +1399,15 @@ static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd) case WRITE_10: case WRITE_16: return ata_scsi_rw_xlat; + + case SYNCHRONIZE_CACHE: + if (ata_try_flush_cache(dev)) + return ata_scsi_flush_xlat; + break; + + case VERIFY: + case VERIFY_16: + return ata_scsi_verify_xlat; } return NULL; @@ -1096,11 +1425,12 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, struct scsi_cmnd *cmd) { #ifdef ATA_DEBUG + struct scsi_device *scsidev = cmd->device; u8 *scsicmd = cmd->cmnd; DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ap->id, - cmd->device->channel, cmd->device->id, cmd->device->lun, + scsidev->channel, scsidev->id, scsidev->lun, scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3], scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7], scsicmd[8]); @@ -1130,12 +1460,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_port *ap; struct ata_device *dev; + struct scsi_device *scsidev = cmd->device; - ap = (struct ata_port *) &cmd->device->host->hostdata[0]; + ap = (struct ata_port *) &scsidev->host->hostdata[0]; ata_scsi_dump_cdb(ap, cmd); - dev = ata_scsi_find_dev(ap, cmd); + dev = ata_scsi_find_dev(ap, scsidev); if (unlikely(!dev)) { cmd->result = (DID_BAD_TARGET << 16); done(cmd); @@ -1143,12 +1474,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) } if (dev->class == ATA_DEV_ATA) { - ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]); + ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, + cmd->cmnd[0]); if (xlat_func) ata_scsi_translate(ap, dev, cmd, done, xlat_func); else - ata_scsi_simulate(ap, dev, cmd, done); + ata_scsi_simulate(dev->id, cmd, done); } else ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); @@ -1158,8 +1490,7 @@ out_unlock: /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @ap: Port to which ATA device is attached. - * @dev: Target device for CDB. + * @id: current IDENTIFY data for target device. * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. * @@ -1170,21 +1501,20 @@ out_unlock: * spin_lock_irqsave(host_set lock) */ -static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) +void ata_scsi_simulate(u16 *id, + struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { struct ata_scsi_args args; u8 *scsicmd = cmd->cmnd; - args.ap = ap; - args.dev = dev; + args.id = id; args.cmd = cmd; args.done = done; switch(scsicmd[0]) { /* no-op's, complete with success */ - case SYNCHRONIZE_CACHE: /* FIXME: temporary */ + case SYNCHRONIZE_CACHE: case REZERO_UNIT: case SEEK_6: case SEEK_10: diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 460c72c1b..f54c93152 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -26,12 +26,11 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.02" /* must be exactly four chars */ +#define DRV_VERSION "1.10" /* must be exactly four chars */ struct ata_scsi_args { - struct ata_port *ap; - struct ata_device *dev; - struct scsi_cmnd *cmd; + u16 *id; + struct scsi_cmnd *cmd; void (*done)(struct scsi_cmnd *); }; @@ -42,10 +41,11 @@ extern int ata_qc_issue(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); +extern void swap_buf_le16(u16 *buf, unsigned int buf_words); /* libata-scsi.c */ -extern void ata_to_sense_error(struct ata_queued_cmd *qc); +extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat); extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 42654a7e4..3ef2a1443 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -41,9 +41,9 @@ enum fsc_phase { }; struct fsc_state { - struct mac53c94_regs *regs; + struct mac53c94_regs __iomem *regs; int intr; - struct dbdma_regs *dma; + struct dbdma_regs __iomem *dma; int dmaintr; int clk_freq; struct Scsi_Host *host; @@ -106,10 +106,10 @@ static int mac53c94_abort(struct scsi_cmnd *cmd) static int mac53c94_host_reset(struct scsi_cmnd *cmd) { struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata; - struct mac53c94_regs *regs = state->regs; - struct dbdma_regs *dma = state->dma; + struct mac53c94_regs __iomem *regs = state->regs; + struct dbdma_regs __iomem *dma = state->dma; - st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); + writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control); writeb(CMD_SCSI_RESET, ®s->command); /* assert RST */ udelay(100); /* leave it on for a while (>= 25us) */ writeb(CMD_RESET, ®s->command); @@ -121,8 +121,8 @@ static int mac53c94_host_reset(struct scsi_cmnd *cmd) static void mac53c94_init(struct fsc_state *state) { - struct mac53c94_regs *regs = state->regs; - struct dbdma_regs *dma = state->dma; + struct mac53c94_regs __iomem *regs = state->regs; + struct dbdma_regs __iomem *dma = state->dma; int x; writeb(state->host->this_id | CF1_PAR_ENABLE, ®s->config1); @@ -143,7 +143,7 @@ static void mac53c94_init(struct fsc_state *state) static void mac53c94_start(struct fsc_state *state) { struct scsi_cmnd *cmd; - struct mac53c94_regs *regs = state->regs; + struct mac53c94_regs __iomem *regs = state->regs; int i; if (state->phase != idle || state->current_req != NULL) @@ -191,8 +191,8 @@ static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs * static void mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { struct fsc_state *state = (struct fsc_state *) dev_id; - struct mac53c94_regs *regs = state->regs; - struct dbdma_regs *dma = state->dma; + struct mac53c94_regs __iomem *regs = state->regs; + struct dbdma_regs __iomem *dma = state->dma; struct scsi_cmnd *cmd = state->current_req; int nb, stat, seq, intr; static int mac53c94_errors; @@ -458,10 +458,10 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_match *match) state->pdev = pdev; state->mdev = mdev; - state->regs = (struct mac53c94_regs *) + state->regs = (struct mac53c94_regs __iomem *) ioremap(macio_resource_start(mdev, 0), 0x1000); state->intr = macio_irq(mdev, 0); - state->dma = (struct dbdma_regs *) + state->dma = (struct dbdma_regs __iomem *) ioremap(macio_resource_start(mdev, 1), 0x1000); state->dmaintr = macio_irq(mdev, 1); if (state->regs == NULL || state->dma == NULL) { diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 5b656df5f..c94c8db84 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -731,7 +731,7 @@ static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int wri } static Scsi_Host_Template driver_template = { - .proc_name = "esp", + .proc_name = "mac_esp", .name = "Mac 53C9x SCSI", .detect = mac_esp_detect, .slave_alloc = esp_slave_alloc, diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index f343fc704..ef6a0c807 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -326,6 +326,7 @@ int macscsi_release (struct Scsi_Host *shpnt) { if (shpnt->irq != SCSI_IRQ_NONE) free_irq (shpnt->irq, NCR5380_intr); + NCR5380_exit(shpnt); return 0; } diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c index e64b8ec2f..d8ce3bab7 100644 --- a/drivers/scsi/mca_53c9x.c +++ b/drivers/scsi/mca_53c9x.c @@ -238,15 +238,15 @@ int mca_esp_detect(Scsi_Host_Template *tpnt) /* Optional functions */ - esp->dma_barrier = 0; - esp->dma_drain = 0; - esp->dma_invalidate = 0; - esp->dma_irq_entry = 0; - esp->dma_irq_exit = 0; + esp->dma_barrier = NULL; + esp->dma_drain = NULL; + esp->dma_invalidate = NULL; + esp->dma_irq_entry = NULL; + esp->dma_irq_exit = NULL; esp->dma_led_on = dma_led_on; esp->dma_led_off = dma_led_off; - esp->dma_poll = 0; - esp->dma_reset = 0; + esp->dma_poll = NULL; + esp->dma_reset = NULL; /* Set the command buffer */ @@ -445,7 +445,7 @@ static void dma_led_off(struct NCR_ESP *esp) } static Scsi_Host_Template driver_template = { - .proc_name = "esp", + .proc_name = "mca_53c9x", .name = "NCR 53c9x SCSI", .detect = mca_esp_detect, .slave_alloc = esp_slave_alloc, diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 5fd685e9a..a84d5e7d9 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -25,11 +25,8 @@ * 518, 520, 531, 532 * * This driver is supported by LSI Logic, with assistance from Red Hat, Dell, - * and others. Please send updates to the public mailing list - * linux-megaraid-devel@dell.com, and subscribe to and read archives of this - * list at http://lists.us.dell.com/. - * - * For history of changes, see ChangeLog.megaraid. + * and others. Please send updates to the mailing list + * linux-scsi@vger.kernel.org . * */ @@ -53,21 +50,24 @@ #include "megaraid.h" +#define MEGARAID_MODULE_VERSION "2.00.3" + MODULE_AUTHOR ("LSI Logic Corporation"); MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); MODULE_LICENSE ("GPL"); +MODULE_VERSION(MEGARAID_MODULE_VERSION); static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN; -MODULE_PARM(max_cmd_per_lun, "i"); +module_param(max_cmd_per_lun, uint, 0); MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)"); static unsigned short int max_sectors_per_io = MAX_SECTORS_PER_IO; -MODULE_PARM(max_sectors_per_io, "h"); +module_param(max_sectors_per_io, ushort, 0); MODULE_PARM_DESC(max_sectors_per_io, "Maximum number of sectors per I/O request (default=MAX_SECTORS_PER_IO=128)"); static unsigned short int max_mbox_busy_wait = MBOX_BUSY_WAIT; -MODULE_PARM(max_mbox_busy_wait, "h"); +module_param(max_mbox_busy_wait, ushort, 0); MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)"); #define RDINDOOR(adapter) readl((adapter)->base + 0x20) @@ -634,11 +634,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) } if(!(scb = mega_allocate_scb(adapter, cmd))) { - - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); *busy = 1; - return NULL; } @@ -677,11 +673,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) /* Allocate a SCB and initialize passthru */ if(!(scb = mega_allocate_scb(adapter, cmd))) { - - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); *busy = 1; - return NULL; } pthru = scb->pthru; @@ -723,11 +715,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) /* Allocate a SCB and initialize mailbox */ if(!(scb = mega_allocate_scb(adapter, cmd))) { - - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); *busy = 1; - return NULL; } mbox = (mbox_t *)scb->raw_mbox; @@ -867,11 +855,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) /* Allocate a SCB and initialize mailbox */ if(!(scb = mega_allocate_scb(adapter, cmd))) { - - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); *busy = 1; - return NULL; } @@ -899,11 +883,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) else { /* Allocate a SCB and initialize passthru */ if(!(scb = mega_allocate_scb(adapter, cmd))) { - - cmd->result = (DID_ERROR << 16); - cmd->scsi_done(cmd); *busy = 1; - return NULL; } @@ -4006,7 +3986,7 @@ mega_enum_raid_scsi(adapter_t *adapter) mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle; /* - * Non-ROMB firware fail this command, so all channels + * Non-ROMB firmware fail this command, so all channels * must be shown RAID */ adapter->mega_ch_class = 0xFF; diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h index 44584ca08..4bf0430dd 100644 --- a/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/drivers/scsi/megaraid/megaraid_ioctl.h @@ -142,9 +142,11 @@ typedef struct uioc { caddr_t buf_vaddr; dma_addr_t buf_paddr; - uint8_t pool_index; + int8_t pool_index; uint8_t free_buf; + uint8_t timedout; + } __attribute__ ((aligned(1024),packed)) uioc_t; @@ -247,6 +249,7 @@ typedef struct mm_dmapool { * @pdev : pci dev; used for allocating dma'ble memory * @issue_uioc : Driver supplied routine to issue uioc_t commands * : issue_uioc(drvr_data, kioc, ISSUE/ABORT, uioc_done) + * @quiescent : flag to indicate if ioctl can be issued to this adp * @list : attach with the global list of adapters * @kioc_list : block of mem for @max_kioc number of kiocs * @kioc_pool : pool of free kiocs @@ -264,7 +267,7 @@ typedef struct mraid_mmadp { uint32_t unique_id; uint32_t drvr_type; unsigned long drvr_data; - uint8_t timeout; + uint16_t timeout; uint8_t max_kioc; struct pci_dev *pdev; @@ -272,6 +275,7 @@ typedef struct mraid_mmadp { int(*issue_uioc)(unsigned long, uioc_t *, uint32_t); /* Maintained by common module */ + uint32_t quiescent; struct list_head list; uioc_t *kioc_list; diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 7afd6a5f1..c38df6c26 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mbox.c - * Version : v2.20.4 (September 27 2004) + * Version : v2.20.4.1 (Nov 04 2004) * * Authors: * Atul Mukker @@ -294,6 +294,12 @@ static struct pci_device_id pci_id_table_g[] = { PCI_VENDOR_ID_DELL, PCI_SUBSYS_ID_PERC3_SC, }, + { + PCI_VENDOR_ID_AMI, + PCI_DEVICE_ID_AMI_MEGARAID3, + PCI_VENDOR_ID_AMI, + PCI_SUBSYS_ID_PERC3_SC, + }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_MEGARAID_SCSI_320_0, @@ -872,8 +878,7 @@ megaraid_init_mbox(adapter_t *adapter) goto out_free_raid_dev; } - raid_dev->baseaddr = (unsigned long) - ioremap_nocache(raid_dev->baseport, 128); + raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128); if (!raid_dev->baseaddr) { @@ -996,7 +1001,7 @@ out_alloc_cmds: out_free_irq: free_irq(adapter->irq, adapter); out_iounmap: - iounmap((caddr_t)raid_dev->baseaddr); + iounmap(raid_dev->baseaddr); out_release_regions: pci_release_regions(pdev); out_free_raid_dev: @@ -1024,7 +1029,7 @@ megaraid_fini_mbox(adapter_t *adapter) free_irq(adapter->irq, adapter); - iounmap((caddr_t)raid_dev->baseaddr); + iounmap(raid_dev->baseaddr); pci_release_regions(adapter->pdev); @@ -1554,12 +1559,12 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) if (scb->dma_direction == PCI_DMA_TODEVICE) { if (!scb->scp->use_sg) { // sg list not used - pci_dma_sync_single(adapter->pdev, ccb->buf_dma_h, + pci_dma_sync_single_for_device(adapter->pdev, ccb->buf_dma_h, scb->scp->request_bufflen, PCI_DMA_TODEVICE); } else { - pci_dma_sync_sg(adapter->pdev, scb->scp->request_buffer, + pci_dma_sync_sg_for_device(adapter->pdev, scb->scp->request_buffer, scb->scp->use_sg, PCI_DMA_TODEVICE); } } @@ -1618,6 +1623,7 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) if (!scb) { // command already completed done(scp); + return 0; } return if_busy; @@ -2332,7 +2338,7 @@ megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) case MRAID_DMA_WBUF: if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_single(adapter->pdev, + pci_dma_sync_single_for_cpu(adapter->pdev, ccb->buf_dma_h, scb->scp->request_bufflen, PCI_DMA_FROMDEVICE); @@ -2345,7 +2351,7 @@ megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) case MRAID_DMA_WSG: if (scb->dma_direction == PCI_DMA_FROMDEVICE) { - pci_dma_sync_sg(adapter->pdev, + pci_dma_sync_sg_for_cpu(adapter->pdev, scb->scp->request_buffer, scb->scp->use_sg, PCI_DMA_FROMDEVICE); } @@ -3591,7 +3597,7 @@ megaraid_cmm_register(adapter_t *adapter) adp.drvr_data = (unsigned long)adapter; adp.pdev = adapter->pdev; adp.issue_uioc = megaraid_mbox_mm_handler; - adp.timeout = 30; + adp.timeout = 300; adp.max_kioc = MBOX_MAX_USER_CMDS; if ((rval = mraid_mm_register_adp(&adp)) != 0) { diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 2f195abc6..582802446 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -21,8 +21,8 @@ #include "megaraid_ioctl.h" -#define MEGARAID_VERSION "2.20.4.0" -#define MEGARAID_EXT_VERSION "(Release Date: Mon Sep 27 22:15:07 EDT 2004)" +#define MEGARAID_VERSION "2.20.4.1" +#define MEGARAID_EXT_VERSION "(Release Date: Thu Nov 4 17:44:59 EST 2004)" /* @@ -231,7 +231,7 @@ typedef struct { dma_addr_t mbox_dma; spinlock_t mailbox_lock; unsigned long baseport; - unsigned long baseaddr; + void __iomem * baseaddr; struct mraid_pci_blk mbox_pool[MBOX_MAX_SCSI_CMDS]; struct dma_pool *mbox_pool_handle; struct mraid_pci_blk epthru_pool[MBOX_MAX_SCSI_CMDS]; diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 8a6bc9391..301ebef9f 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mm.c - * Version : v2.20.2.0 (August 19 2004) + * Version : v2.20.2.3 (Dec 09 2004) * * Common management module */ @@ -60,7 +60,7 @@ EXPORT_SYMBOL(mraid_mm_register_adp); EXPORT_SYMBOL(mraid_mm_unregister_adp); static int majorno; -static uint32_t drvr_ver = 0x02200100; +static uint32_t drvr_ver = 0x02200201; static int adapters_count_g; static struct list_head adapters_list_g; @@ -155,6 +155,17 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, return rval; } + /* + * Check if adapter can accept ioctl. We may have marked it offline + * if any previous kioc had timedout on this controller. + */ + if (!adp->quiescent) { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: controller cannot accept cmds due to " + "earlier errors\n" )); + return -EFAULT; + } + /* * The following call will block till a kioc is available */ @@ -171,10 +182,15 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, kioc->done = ioctl_done; /* - * Issue the IOCTL to the low level driver + * Issue the IOCTL to the low level driver. After the IOCTL completes + * release the kioc if and only if it was _not_ timedout. If it was + * timedout, that means that resources are still with low level driver. */ if ((rval = lld_ioctl(adp, kioc))) { - mraid_mm_dealloc_kioc(adp, kioc); + + if (!kioc->timedout) + mraid_mm_dealloc_kioc(adp, kioc); + return rval; } @@ -581,6 +597,7 @@ mraid_mm_alloc_kioc(mraid_mmadp_t *adp) kioc->user_data = NULL; kioc->user_data_len = 0; kioc->user_pthru = NULL; + kioc->timedout = 0; return kioc; } @@ -597,23 +614,27 @@ mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) mm_dmapool_t *pool; unsigned long flags; - pool = &adp->dma_pool_list[kioc->pool_index]; - - /* This routine may be called in non-isr context also */ - spin_lock_irqsave(&pool->lock, flags); + if (kioc->pool_index != -1) { + pool = &adp->dma_pool_list[kioc->pool_index]; - /* - * While attaching the dma buffer, if we didn't get the required - * buffer from the pool, we would have allocated it at the run time - * and set the free_buf flag. We must free that buffer. Otherwise, - * just mark that the buffer is not in use - */ - if (kioc->free_buf == 1) - pci_pool_free(pool->handle, kioc->buf_vaddr, kioc->buf_paddr); - else - pool->in_use = 0; + /* This routine may be called in non-isr context also */ + spin_lock_irqsave(&pool->lock, flags); - spin_unlock_irqrestore(&pool->lock, flags); + /* + * While attaching the dma buffer, if we didn't get the + * required buffer from the pool, we would have allocated + * it at the run time and set the free_buf flag. We must + * free that buffer. Otherwise, just mark that the buffer is + * not in use + */ + if (kioc->free_buf == 1) + pci_pool_free(pool->handle, kioc->buf_vaddr, + kioc->buf_paddr); + else + pool->in_use = 0; + + spin_unlock_irqrestore(&pool->lock, flags); + } /* Return the kioc to the free pool */ spin_lock_irqsave(&adp->kioc_pool_lock, flags); @@ -667,6 +688,14 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) del_timer_sync(tp); } + /* + * If the command had timedout, we mark the controller offline + * before returning + */ + if (kioc->timedout) { + adp->quiescent = 0; + } + return kioc->status; } @@ -679,6 +708,10 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) static void ioctl_done(uioc_t *kioc) { + uint32_t adapno; + int iterator; + mraid_mmadp_t* adapter; + /* * When the kioc returns from driver, make sure it still doesn't * have ENODATA in status. Otherwise, driver will hang on wait_event @@ -691,7 +724,32 @@ ioctl_done(uioc_t *kioc) kioc->status = -EINVAL; } - wake_up(&wait_q); + /* + * Check if this kioc was timedout before. If so, nobody is waiting + * on this kioc. We don't have to wake up anybody. Instead, we just + * have to free the kioc + */ + if (kioc->timedout) { + iterator = 0; + adapter = NULL; + adapno = kioc->adapno; + + con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed " + "ioctl that was timedout before\n")); + + list_for_each_entry(adapter, &adapters_list_g, list) { + if (iterator++ == adapno) break; + } + + kioc->timedout = 0; + + if (adapter) { + mraid_mm_dealloc_kioc( adapter, kioc ); + } + } + else { + wake_up(&wait_q); + } } @@ -706,6 +764,7 @@ lld_timedout(unsigned long ptr) uioc_t *kioc = (uioc_t *)ptr; kioc->status = -ETIME; + kioc->timedout = 1; con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n")); @@ -850,6 +909,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp) adapter->issue_uioc = lld_adp->issue_uioc; adapter->timeout = lld_adp->timeout; adapter->max_kioc = lld_adp->max_kioc; + adapter->quiescent = 1; /* * Allocate single blocks of memory for all required kiocs, @@ -1120,9 +1180,7 @@ mraid_mm_init(void) INIT_LIST_HEAD(&adapters_list_g); -#ifdef CONFIG_COMPAT register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl); -#endif return 0; } diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h index effc23a63..28f1fb495 100644 --- a/drivers/scsi/megaraid/megaraid_mm.h +++ b/drivers/scsi/megaraid/megaraid_mm.h @@ -29,10 +29,9 @@ #include "megaraid_ioctl.h" -#define LSI_COMMON_MOD_VERSION "2.20.2.0" +#define LSI_COMMON_MOD_VERSION "2.20.2.3" #define LSI_COMMON_MOD_EXT_VERSION \ - "(Release Date: Thu Aug 19 09:58:33 EDT 2004)" - + "(Release Date: Thu Dec 9 19:02:14 EST 2004)" #define LSI_DBGLVL dbglevel diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 1700d4e6c..85f3a74ac 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -60,23 +60,23 @@ MODULE_AUTHOR("Paul Mackerras (paulus@samba.org)"); MODULE_DESCRIPTION("PowerMac MESH SCSI driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(sync_rate, "i"); -MODULE_PARM_DESC(sync_rate, "Synchronous rate (0..10, 0=async)"); -MODULE_PARM(sync_targets, "i"); -MODULE_PARM_DESC(sync_targets, "Bitmask of targets allowed to set synchronous"); -MODULE_PARM(resel_targets, "i"); -MODULE_PARM_DESC(resel_targets, "Bitmask of targets allowed to set disconnect"); -MODULE_PARM(debug_targets, "i"); -MODULE_PARM_DESC(debug_targets, "Bitmask of debugged targets"); -MODULE_PARM(init_reset_delay, "i"); -MODULE_PARM_DESC(init_reset_delay, "Initial bus reset delay (0=no reset)"); - static int sync_rate = CONFIG_SCSI_MESH_SYNC_RATE; static int sync_targets = 0xff; static int resel_targets = 0xff; static int debug_targets = 0; /* print debug for these targets */ static int init_reset_delay = CONFIG_SCSI_MESH_RESET_DELAY_MS; +module_param(sync_rate, int, 0); +MODULE_PARM_DESC(sync_rate, "Synchronous rate (0..10, 0=async)"); +module_param(sync_targets, int, 0); +MODULE_PARM_DESC(sync_targets, "Bitmask of targets allowed to set synchronous"); +module_param(resel_targets, int, 0); +MODULE_PARM_DESC(resel_targets, "Bitmask of targets allowed to set disconnect"); +module_param(debug_targets, int, 0644); +MODULE_PARM_DESC(debug_targets, "Bitmask of debugged targets"); +module_param(init_reset_delay, int, 0); +MODULE_PARM_DESC(init_reset_delay, "Initial bus reset delay (0=no reset)"); + static int mesh_sync_period = 100; static int mesh_sync_offset = 0; static unsigned char use_active_neg = 0; /* bit mask for SEQ_ACTIVE_NEG if used */ @@ -144,9 +144,9 @@ struct mesh_target { }; struct mesh_state { - volatile struct mesh_regs *mesh; + volatile struct mesh_regs __iomem *mesh; int meshintr; - volatile struct dbdma_regs *dma; + volatile struct dbdma_regs __iomem *dma; int dmaintr; struct Scsi_Host *host; struct mesh_state *next; @@ -304,8 +304,8 @@ static inline void dumpslog(struct mesh_state *ms) static void mesh_dump_regs(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; - volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs __iomem *mr = ms->mesh; + volatile struct dbdma_regs __iomem *md = ms->dma; int t; struct mesh_target *tp; @@ -338,7 +338,7 @@ mesh_dump_regs(struct mesh_state *ms) /* * Flush write buffers on the bus path to the mesh */ -static inline void mesh_flush_io(volatile struct mesh_regs *mr) +static inline void mesh_flush_io(volatile struct mesh_regs __iomem *mr) { (void)in_8(&mr->mesh_id); } @@ -359,8 +359,8 @@ static void mesh_completed(struct mesh_state *ms, struct scsi_cmnd *cmd) */ static void mesh_init(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; - volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs __iomem *mr = ms->mesh; + volatile struct dbdma_regs __iomem *md = ms->dma; mesh_flush_io(mr); udelay(100); @@ -388,8 +388,7 @@ static void mesh_init(struct mesh_state *ms) mesh_flush_io(mr); /* Wait for bus to come back */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((init_reset_delay * HZ) / 1000); + msleep(init_reset_delay); } /* Reconfigure controller */ @@ -407,7 +406,7 @@ static void mesh_init(struct mesh_state *ms) static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd) { - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; int t, id; id = cmd->device->id; @@ -468,7 +467,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd) dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x", MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); - mesh_interrupt(0, (void *)ms, 0); + mesh_interrupt(0, (void *)ms, NULL); if (ms->phase != arbitrating) return; } @@ -506,7 +505,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd) dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x", MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count)); - mesh_interrupt(0, (void *)ms, 0); + mesh_interrupt(0, (void *)ms, NULL); if (ms->phase != arbitrating) return; dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x", @@ -596,8 +595,8 @@ static void mesh_done(struct mesh_state *ms, int start_next) struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; cmd = ms->current_req; - ms->current_req = 0; - tp->current_req = 0; + ms->current_req = NULL; + tp->current_req = NULL; if (cmd) { cmd->result = (ms->stat << 16) + cmd->SCp.Status; if (ms->stat == DID_OK) @@ -639,7 +638,7 @@ static inline void add_sdtr_msg(struct mesh_state *ms) static void set_sdtr(struct mesh_state *ms, int period, int offset) { struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; int v, tr; tp->sdtr_state = sdtr_done; @@ -680,8 +679,8 @@ static void set_sdtr(struct mesh_state *ms, int period, int offset) static void start_phase(struct mesh_state *ms) { int i, seq, nb; - volatile struct mesh_regs *mr = ms->mesh; - volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs __iomem *mr = ms->mesh; + volatile struct dbdma_regs __iomem *md = ms->dma; struct scsi_cmnd *cmd = ms->current_req; struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; @@ -824,7 +823,7 @@ static void start_phase(struct mesh_state *ms) static inline void get_msgin(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; int i, n; n = mr->fifo_count; @@ -856,7 +855,7 @@ static inline int msgin_length(struct mesh_state *ms) static void reselected(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; struct scsi_cmnd *cmd; struct mesh_target *tp; int b, t, prev; @@ -989,7 +988,7 @@ static void handle_reset(struct mesh_state *ms) int tgt; struct mesh_target *tp; struct scsi_cmnd *cmd; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; for (tgt = 0; tgt < 8; ++tgt) { tp = &ms->tgts[tgt]; @@ -1031,7 +1030,7 @@ static irqreturn_t do_mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptre static void handle_error(struct mesh_state *ms) { int err, exc, count; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; err = in_8(&mr->error); exc = in_8(&mr->exception); @@ -1125,7 +1124,7 @@ static void handle_error(struct mesh_state *ms) static void handle_exception(struct mesh_state *ms) { int exc; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; exc = in_8(&mr->exception); out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE); @@ -1232,8 +1231,8 @@ static void handle_msgin(struct mesh_state *ms) } else if (code != cmd->device->lun + IDENTIFY_BASE) { printk(KERN_WARNING "mesh: lun mismatch " "(%d != %d) on reselection from " - "target %d\n", i, cmd->device->lun, - ms->conn_tgt); + "target %d\n", code - IDENTIFY_BASE, + cmd->device->lun, ms->conn_tgt); } break; } @@ -1325,8 +1324,8 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd) static void halt_dma(struct mesh_state *ms) { - volatile struct dbdma_regs *md = ms->dma; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct dbdma_regs __iomem *md = ms->dma; + volatile struct mesh_regs __iomem *mr = ms->mesh; struct scsi_cmnd *cmd = ms->current_req; int t, nb; @@ -1374,7 +1373,7 @@ static void halt_dma(struct mesh_state *ms) static void phase_mismatch(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; int phase; dlog(ms, "phasemm ch/cl/seq/fc=%.8x", @@ -1453,7 +1452,7 @@ static void phase_mismatch(struct mesh_state *ms) static void cmd_complete(struct mesh_state *ms) { - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; struct scsi_cmnd *cmd = ms->current_req; struct mesh_target *tp = &ms->tgts[ms->conn_tgt]; int seq, n, t; @@ -1619,7 +1618,7 @@ static void cmd_complete(struct mesh_state *ms) mesh_done(ms, 1); return; case disconnecting: - ms->current_req = 0; + ms->current_req = NULL; ms->phase = idle; mesh_start(ms); return; @@ -1666,7 +1665,7 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) static void mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { struct mesh_state *ms = (struct mesh_state *) dev_id; - volatile struct mesh_regs *mr = ms->mesh; + volatile struct mesh_regs __iomem *mr = ms->mesh; int intr; #if 0 @@ -1714,8 +1713,8 @@ static int mesh_abort(struct scsi_cmnd *cmd) static int mesh_host_reset(struct scsi_cmnd *cmd) { struct mesh_state *ms = (struct mesh_state *) cmd->device->host->hostdata; - volatile struct mesh_regs *mr = ms->mesh; - volatile struct dbdma_regs *md = ms->dma; + volatile struct mesh_regs __iomem *mr = ms->mesh; + volatile struct dbdma_regs __iomem *md = ms->dma; printk(KERN_DEBUG "mesh_host_reset\n"); @@ -1749,12 +1748,10 @@ static void set_mesh_power(struct mesh_state *ms, int state) return; if (state) { pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/5); + msleep(200); } else { pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); } } @@ -1765,15 +1762,14 @@ static int mesh_suspend(struct macio_dev *mdev, u32 state) struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev); unsigned long flags; - if (state == mdev->ofdev.dev.power_state || state < 2) + if (state == mdev->ofdev.dev.power.power_state || state < 2) return 0; scsi_block_requests(ms->host); spin_lock_irqsave(ms->host->host_lock, flags); while(ms->phase != idle) { spin_unlock_irqrestore(ms->host->host_lock, flags); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/100); + msleep(10); spin_lock_irqsave(ms->host->host_lock, flags); } ms->phase = sleeping; @@ -1781,7 +1777,7 @@ static int mesh_suspend(struct macio_dev *mdev, u32 state) disable_irq(ms->meshintr); set_mesh_power(ms, 0); - mdev->ofdev.dev.power_state = state; + mdev->ofdev.dev.power.power_state = state; return 0; } @@ -1791,7 +1787,7 @@ static int mesh_resume(struct macio_dev *mdev) struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev); unsigned long flags; - if (mdev->ofdev.dev.power_state == 0) + if (mdev->ofdev.dev.power.power_state == 0) return 0; set_mesh_power(ms, 1); @@ -1802,7 +1798,7 @@ static int mesh_resume(struct macio_dev *mdev) enable_irq(ms->meshintr); scsi_unblock_requests(ms->host); - mdev->ofdev.dev.power_state = 0; + mdev->ofdev.dev.power.power_state = 0; return 0; } @@ -1817,7 +1813,7 @@ static int mesh_resume(struct macio_dev *mdev) static int mesh_shutdown(struct macio_dev *mdev) { struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev); - volatile struct mesh_regs *mr; + volatile struct mesh_regs __iomem *mr; unsigned long flags; printk(KERN_INFO "resetting MESH scsi bus(es)\n"); @@ -1896,17 +1892,15 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_match *match) ms->mdev = mdev; ms->pdev = pdev; - ms->mesh = (volatile struct mesh_regs *) - ioremap(macio_resource_start(mdev, 0), 0x1000); + ms->mesh = ioremap(macio_resource_start(mdev, 0), 0x1000); if (ms->mesh == NULL) { printk(KERN_ERR "mesh: can't map registers\n"); goto out_free; } - ms->dma = (volatile struct dbdma_regs *) - ioremap(macio_resource_start(mdev, 1), 0x1000); + ms->dma = ioremap(macio_resource_start(mdev, 1), 0x1000); if (ms->dma == NULL) { printk(KERN_ERR "mesh: can't map registers\n"); - iounmap((void *)ms->mesh); + iounmap(ms->mesh); goto out_free; } @@ -1938,7 +1932,7 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_match *match) for (tgt = 0; tgt < 8; ++tgt) { ms->tgts[tgt].sdtr_state = do_sdtr; ms->tgts[tgt].sync_params = ASYNC_PARAMS; - ms->tgts[tgt].current_req = 0; + ms->tgts[tgt].current_req = NULL; } if ((cfp = (int *) get_property(mesh, "clock-frequency", NULL))) @@ -1972,8 +1966,8 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_match *match) return 0; out_unmap: - iounmap((void *)ms->dma); - iounmap((void *)ms->mesh); + iounmap(ms->dma); + iounmap(ms->mesh); out_free: scsi_host_put(mesh_host); out_release: @@ -1998,8 +1992,8 @@ static int mesh_remove(struct macio_dev *mdev) set_mesh_power(ms, 0); /* Unmap registers & dma controller */ - iounmap((void *) ms->mesh); - iounmap((void *) ms->dma); + iounmap(ms->mesh); + iounmap(ms->dma); /* Free DMA commands memory */ pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size, diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 3fcefa3d4..9b91b2efe 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -83,11 +83,6 @@ ** ** Supported NCR/SYMBIOS chips: ** 53C720 (Wide, Fast SCSI-2, intfly problems) -** -** Other features: -** Memory mapped IO (linux-1.3.X and above only) -** Module -** Shared IRQ (since linux-1.3.72) */ /* Name and version of the driver */ @@ -124,23 +119,17 @@ #include #include -#include "scsi.h" -#include +#include +#include +#include +#include +#include +#include #include "ncr53c8xx.h" -/* -** Donnot compile integrity checking code for Linux-2.3.0 -** and above since SCSI data structures are not ready yet. -*/ -/* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */ -#if 0 -#define SCSI_NCR_INTEGRITY_CHECKING -#endif - #define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" -#define DRIVER_SMP_LOCK ncr53c8xx_lock #include "sym53c8xx_comm.h" @@ -316,10 +305,6 @@ typedef u32 tagmap_t; #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) -static void ncr53c8xx_timeout(unsigned long np); -static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, - int length, int func); - #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) @@ -413,31 +398,6 @@ static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **star #define NS_WIDE (2) #define NS_PPR (4) -/*========================================================== -** -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct ccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_NOSYNC (0x10) -#define QUIRK_NOWIDE16 (0x20) - -/*========================================================== -** -** Capability bits in Inquire response byte 7. -** -**========================================================== -*/ - -#define INQ7_QUEUE (0x02) -#define INQ7_SYNC (0x10) -#define INQ7_WIDE16 (0x20) - /*========================================================== ** ** Misc. @@ -454,6 +414,8 @@ static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **star **========================================================== */ +static struct scsi_transport_template *ncr53c8xx_transport_template = NULL; + struct tcb; struct lcb; struct ccb; @@ -531,8 +493,6 @@ struct tcb { */ struct link jump_lcb[4]; /* JUMPs for reselection */ struct lcb * lp[MAX_LUN]; /* The lcb's of this tcb */ - u_char inq_done; /* Target capabilities received */ - u_char inq_byte7; /* Contains these capabilities */ /*---------------------------------------------------------------- ** Pointer to the ccb used for negotiation. @@ -571,18 +531,12 @@ struct tcb { /*3*/ u_char wval; #endif -#ifdef SCSI_NCR_INTEGRITY_CHECKING - u_char ic_min_sync; - u_char ic_max_width; - u_char ic_maximums_set; - u_char ic_done; -#endif - /* User settable limits and options. */ u_char usrsync; u_char usrwide; u_char usrtags; u_char usrflag; + struct scsi_target *starget; }; /*======================================================================== @@ -626,10 +580,10 @@ struct lcb { ** CCB queue management. **---------------------------------------------------------------- */ - XPT_QUEHEAD free_ccbq; /* Queue of available CCBs */ - XPT_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ - XPT_QUEHEAD wait_ccbq; /* Queue of waiting for IO CCBs */ - XPT_QUEHEAD skip_ccbq; /* Queue of skipped CCBs */ + struct list_head free_ccbq; /* Queue of available CCBs */ + struct list_head busy_ccbq; /* Queue of busy CCBs */ + struct list_head wait_ccbq; /* Queue of waiting for IO CCBs */ + struct list_head skip_ccbq; /* Queue of skipped CCBs */ u_char actccbs; /* Number of allocated CCBs */ u_char busyccbs; /* CCBs busy for this lun */ u_char queuedccbs; /* CCBs queued to the controller*/ @@ -649,7 +603,6 @@ struct lcb { u_char usetags; /* Command queuing is active */ u_char maxtags; /* Max nr of tags asked by user */ u_char numtags; /* Current number of tags */ - u_char inq_byte7; /* Store unit CmdQ capabitility */ /*---------------------------------------------------------------- ** QUEUE FULL control and ORDERED tag control. @@ -920,7 +873,7 @@ struct ccb { u_char queued; u_char auto_sense; struct ccb * link_ccb; /* Host adapter CCB chain */ - XPT_QUEHEAD link_ccbq; /* Link to unit CCB queue */ + struct list_head link_ccbq; /* Link to unit CCB queue */ u32 startp; /* Initial data pointer */ u_long magic; /* Free / busy CCB flag */ }; @@ -997,11 +950,11 @@ struct ncb { ** Virtual and physical bus addresses of the chip. **---------------------------------------------------------------- */ - vm_offset_t vaddr; /* Virtual and bus address of */ - vm_offset_t paddr; /* chip's IO registers. */ - vm_offset_t paddr2; /* On-chip RAM bus address. */ + void __iomem *vaddr; /* Virtual and bus address of */ + unsigned long paddr; /* chip's IO registers. */ + unsigned long paddr2; /* On-chip RAM bus address. */ volatile /* Pointer to volatile for */ - struct ncr_reg *reg; /* memory mapped IO. */ + struct ncr_reg __iomem *reg; /* memory mapped IO. */ /*---------------------------------------------------------------- ** SCRIPTS virtual and physical bus addresses. @@ -1096,17 +1049,6 @@ struct ncb { struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ volatile u_char release_stage; /* Synchronisation stage on release */ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /*---------------------------------------------------------------- - ** Fields that are used for integrity check - **---------------------------------------------------------------- - */ - unsigned char check_integrity; /* Enable midlayer integ.check on - * bus scan. */ - unsigned char check_integ_par; /* Set if par or Init. Det. error - * used only during integ check */ -#endif }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -1186,7 +1128,7 @@ struct script { #endif ncrcmd save_dp [ 7]; ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 17]; + ncrcmd disconnect [ 10]; ncrcmd msg_out [ 9]; ncrcmd msg_out_done [ 7]; ncrcmd idle [ 2]; @@ -1274,8 +1216,7 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp); static void ncr_init_ccb (struct ncb *np, struct ccb *cp); static void ncr_init_tcb (struct ncb *np, u_char tn); static struct lcb * ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln); -static struct lcb * ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, - u_char *inq_data); +static struct lcb * ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev); static void ncr_getclock (struct ncb *np, int mult); static void ncr_selectclock (struct ncb *np, u_char scntl3); static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln); @@ -1286,12 +1227,8 @@ static int ncr_int_par (struct ncb *np); static void ncr_int_ma (struct ncb *np); static void ncr_int_sir (struct ncb *np); static void ncr_int_sto (struct ncb *np); -static u_long ncr_lookup (char* id); static void ncr_negotiate (struct ncb* np, struct tcb* tp); static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr); -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd, u_char *msgptr); -#endif static void ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len); @@ -1299,7 +1236,7 @@ static void ncr_script_fill (struct script * scr, struct scripth * scripth); static int ncr_scatter (struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd); static void ncr_getsync (struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl3p); static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer); -static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln); +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev); static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack); static int ncr_show_msg (u_char * msg); static void ncr_print_msg (struct ccb *cp, char *label, u_char *msg); @@ -1882,21 +1819,6 @@ static struct script script0 __initdata = { */ SCR_LOAD_REG (HS_REG, HS_DISCONNECT), 0, - /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - PADDR (cleanup_ok), - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), SCR_JUMP, PADDR (cleanup_ok), @@ -2826,7 +2748,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *p++ =PADDR (idle); }; - assert ((u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); + BUG_ON((u_long)p != (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); #ifdef SCSI_NCR_CCB_DONE_SUPPORT @@ -2839,7 +2761,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *p++ =PADDR (done_end); } - assert ((u_long)p ==(u_long)&scrh->done_queue+sizeof(scrh->done_queue)); + BUG_ON((u_long)p != (u_long)&scrh->done_queue+sizeof(scrh->done_queue)); #endif /* SCSI_NCR_CCB_DONE_SUPPORT */ @@ -2850,7 +2772,8 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh) *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; *p++ =offsetof (struct dsb, data[i]); }; - assert ((u_long)p == (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); + + BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in)); p = scr->data_in; for (i=MAX_SCATTERH; idata_in + sizeof (scr->data_in)); + + BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in)); p = scrh->hdata_out; for (i=0; ihdata_out + sizeof (scrh->hdata_out)); + + BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out)); p = scr->data_out; for (i=MAX_SCATTERH; idata_out + sizeof (scr->data_out)); + BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out)); } /*========================================================== @@ -2916,7 +2841,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) if (opcode == 0) { printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - MDELAY (1000); + mdelay(1000); }; if (DEBUG_FLAGS & DEBUG_SCRIPT) @@ -2946,7 +2871,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) if ((tmp1 ^ tmp2) & 3) { printk (KERN_ERR"%s: ERROR1 IN SCRIPT at %d.\n", ncr_name(np), (int) (src-start-1)); - MDELAY (1000); + mdelay(1000); } /* ** If PREFETCH feature not enabled, remove @@ -3036,21 +2961,8 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) }; } -/*========================================================== -** -** -** Auto configuration: attach and init a host adapter. -** -** -**========================================================== -*/ - /* ** Linux host data structure -** -** The script area is allocated in the host data structure -** because kmalloc() returns NULL during scsi initialisations -** with Linux 1.2.X */ struct host_data { @@ -3436,182 +3348,6 @@ static inline void ncr_flush_done_cmds(struct scsi_cmnd *lcmd) } } -/*========================================================== -** -** -** Prepare the next negotiation message for integrity check, -** 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. -** -** -**========================================================== -*/ - -#ifdef SCSI_NCR_INTEGRITY_CHECKING -static int ncr_ic_nego(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd, u_char *msgptr) -{ - struct tcb *tp = &np->target[cp->target]; - int msglen = 0; - int nego = 0; - u_char no_increase; - - if (tp->inq_done) { - - if (!tp->ic_maximums_set) { - tp->ic_maximums_set = 1; - - /* check target and host adapter capabilities */ - if ( (tp->inq_byte7 & INQ7_WIDE16) && - np->maxwide && tp->usrwide ) - tp->ic_max_width = 1; - else - tp->ic_max_width = 0; - - if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) { - tp->ic_min_sync = (tp->minsync < np->minsync) ? - np->minsync : tp->minsync; - } - else - tp->ic_min_sync = 255; - - tp->period = 1; - tp->widedone = 1; - } - - if (DEBUG_FLAGS & DEBUG_IC) { - printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", - ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); - } - - /* First command from integrity check routine will request - * a PPR message. Disable. - */ - if ((cmd->ic_nego & NS_PPR) == NS_PPR) - cmd->ic_nego &= ~NS_PPR; - /* Previous command recorded a parity or an initiator - * detected error condition. Force bus to narrow for this - * target. Clear flag. Negotation on request sense. - * Note: kernel forces 2 bus resets :o( but clears itself out. - * Minor bug? in scsi_obsolete.c (ugly) - */ - if (np->check_integ_par) { - printk("%s: Parity Error. Target set to narrow.\n", - ncr_name(np)); - tp->ic_max_width = 0; - tp->widedone = tp->period = 0; - } - - /* In case of a bus reset, ncr_negotiate will reset - * the flags tp->widedone and tp->period to 0, forcing - * a new negotiation. - */ - no_increase = 0; - if (tp->widedone == 0) { - cmd->ic_nego = NS_WIDE; - tp->widedone = 1; - no_increase = 1; - } - else if (tp->period == 0) { - cmd->ic_nego = NS_SYNC; - tp->period = 1; - no_increase = 1; - } - - switch (cmd->ic_nego) { - case NS_WIDE: - /* - ** negotiate wide transfers ? - ** Do NOT negotiate if device only supports - ** narrow. - */ - if (tp->ic_max_width | np->check_integ_par) { - nego = NS_WIDE; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = cmd->ic_nego_width & tp->ic_max_width; - } - else - cmd->ic_nego_width &= tp->ic_max_width; - - break; - - case NS_SYNC: - /* - ** negotiate synchronous transfers? - ** Target must support sync transfers. - ** - ** If period becomes longer than max, reset to async - */ - - if (tp->inq_byte7 & INQ7_SYNC) { - - nego = NS_SYNC; - - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - - switch (cmd->ic_nego_sync) { - case 2: /* increase the period */ - if (!no_increase) { - if (tp->ic_min_sync <= 0x0A) - tp->ic_min_sync = 0x0C; - else if (tp->ic_min_sync <= 0x0C) - tp->ic_min_sync = 0x19; - else if (tp->ic_min_sync <= 0x19) - tp->ic_min_sync *= 2; - else { - tp->ic_min_sync = 255; - cmd->ic_nego_sync = 0; - tp->maxoffs = 0; - } - } - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 1: /* nego. to maximum */ - msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; - msgptr[msglen++] = tp->maxoffs; - break; - - case 0: /* nego to async */ - default: - msgptr[msglen++] = 0; - msgptr[msglen++] = 0; - break; - }; - } - else - cmd->ic_nego_sync = 0; - break; - - case NS_NOCHANGE: - default: - break; - }; - }; - - cp->nego_status = nego; - np->check_integ_par = 0; - - if (nego) { - tp->nego_cp = cp; - if (DEBUG_FLAGS & DEBUG_NEGO) { - ncr_print_msg(cp, nego == NS_WIDE ? - "wide/narrow msgout": "sync/async msgout", msgptr); - }; - }; - - return msglen; -} -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ - /*========================================================== ** ** @@ -3631,20 +3367,17 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) struct tcb *tp = &np->target[cp->target]; int msglen = 0; int nego = 0; + struct scsi_target *starget = tp->starget; - if (tp->inq_done) { + if (likely(starget)) { /* ** negotiate wide transfers ? */ if (!tp->widedone) { - if (tp->inq_byte7 & INQ7_WIDE16) { + if (spi_support_wide(starget)) { nego = NS_WIDE; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if (tp->ic_done) - tp->usrwide &= tp->ic_max_width; -#endif } else tp->widedone=1; @@ -3655,13 +3388,8 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr) */ if (!nego && !tp->period) { - if (tp->inq_byte7 & INQ7_SYNC) { + if (spi_support_sync(starget)) { nego = NS_SYNC; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((tp->ic_done) && - (tp->minsync < tp->ic_min_sync)) - tp->minsync = tp->ic_min_sync; -#endif } else { tp->period =0xffff; PRINT_TARGET(np, cp->target); @@ -3843,8 +3571,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) **---------------------------------------------------- */ - direction = scsi_data_direction(cmd); - if (direction != SCSI_DATA_NONE) { + direction = cmd->sc_data_direction; + if (direction != DMA_NONE) { segments = ncr_scatter(np, cp, cp->cmd); if (segments < 0) { ncr_free_ccb(np, cp); @@ -3867,72 +3595,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) cp->nego_status = 0; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { - if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { - msglen += ncr_prepare_nego (np, cp, msgptr + msglen); - } - } - else if (np->check_integrity && (cmd->ic_in_progress)) { - msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); - } - else if (np->check_integrity && cmd->ic_complete) { - /* - * Midlayer signal to the driver that all of the scsi commands - * for the integrity check have completed. Save the negotiated - * parameters (extracted from sval and wval). - */ - - { - u_char idiv; - idiv = (tp->wval>>4) & 0x07; - if ((tp->sval&0x1f) && idiv ) - tp->period = (((tp->sval>>5)+4) - *div_10M[idiv-1])/np->clock_khz; - else - tp->period = 0xffff; - } - /* - * tp->period contains 10 times the transfer period, - * which itself is 4 * the requested negotiation rate. - */ - if (tp->period <= 250) tp->ic_min_sync = 10; - else if (tp->period <= 303) tp->ic_min_sync = 11; - else if (tp->period <= 500) tp->ic_min_sync = 12; - else - tp->ic_min_sync = (tp->period + 40 - 1) / 40; - - - /* - * Negotiation for this target it complete. - */ - tp->ic_max_width = (tp->wval & EWS) ? 1: 0; - tp->ic_done = 1; - tp->widedone = 1; - - printk("%s: Integrity Check Complete: \n", ncr_name(np)); - - printk("%s: %s %s SCSI", ncr_name(np), - (tp->sval&0x1f)?"SYNC":"ASYNC", - tp->ic_max_width?"WIDE":"NARROW"); - - if (tp->sval&0x1f) { - u_long mbs = 10000 * (tp->ic_max_width + 1); - - printk(" %d.%d MB/s", (int) (mbs / tp->period), - (int) (mbs % tp->period)); - - printk(" (%d ns, %d offset)\n", - tp->period/10, tp->sval&0x1f); - } else { - printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); - } - } -#else if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { msglen += ncr_prepare_nego (np, cp, msgptr + msglen); } -#endif /* SCSI_NCR_INTEGRITY_CHECKING */ /*---------------------------------------------------- ** @@ -3941,17 +3606,17 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) **---------------------------------------------------- */ if (!cp->data_len) - direction = SCSI_DATA_NONE; + direction = DMA_NONE; /* - ** If data direction is UNKNOWN, speculate DATA_READ - ** but prepare alternate pointers for WRITE in case + ** If data direction is BIDIRECTIONAL, speculate FROM_DEVICE + ** but prepare alternate pointers for TO_DEVICE in case ** of our speculation will be just wrong. ** SCRIPTS will swap values if needed. */ switch(direction) { - case SCSI_DATA_UNKNOWN: - case SCSI_DATA_WRITE: + case DMA_BIDIRECTIONAL: + case DMA_TO_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -3959,12 +3624,12 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) lastp = NCB_SCRIPTH_PHYS (np, hdata_out2); lastp -= (segments - MAX_SCATTERL) * 16; } - if (direction != SCSI_DATA_UNKNOWN) + if (direction != DMA_BIDIRECTIONAL) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); cp->phys.header.wlastp = cpu_to_scr(lastp); /* fall through */ - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; if (segments <= MAX_SCATTERL) lastp = goalp - 8 - (segments * 16); @@ -3974,7 +3639,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) } break; default: - case SCSI_DATA_NONE: + case DMA_NONE: lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); break; } @@ -3986,7 +3651,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) cp->phys.header.lastp = cpu_to_scr(lastp); cp->phys.header.goalp = cpu_to_scr(goalp); - if (direction == SCSI_DATA_UNKNOWN) + if (direction == DMA_BIDIRECTIONAL) cp->phys.header.savep = cpu_to_scr(NCB_SCRIPTH_PHYS (np, data_io)); else @@ -4036,7 +3701,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) /* ** status */ - cp->actualquirks = tp->quirks; + cp->actualquirks = 0; cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY; cp->scsi_status = S_ILLEGAL; cp->parity_status = 0; @@ -4089,19 +3754,19 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) static void ncr_start_next_ccb(struct ncb *np, struct lcb *lp, int maxn) { - XPT_QUEHEAD *qp; + struct list_head *qp; struct ccb *cp; if (lp->held_ccb) return; while (maxn-- && lp->queuedccbs < lp->queuedepth) { - qp = xpt_remque_head(&lp->wait_ccbq); + qp = ncr_list_pop(&lp->wait_ccbq); if (!qp) break; ++lp->queuedccbs; - cp = xpt_que_entry(qp, struct ccb, link_ccbq); - xpt_insque_tail(qp, &lp->busy_ccbq); + cp = list_entry(qp, struct ccb, link_ccbq); + list_add_tail(qp, &lp->busy_ccbq); lp->jump_ccb[cp->tag == NO_TAG ? 0 : cp->tag] = cpu_to_scr(CCB_PHYS (cp, restart)); ncr_put_start_queue(np, cp); @@ -4152,7 +3817,7 @@ static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay) ncr_name(np), settle_delay); ncr_chip_reset(np, 100); - UDELAY (2000); /* The 895 needs time for the bus mode to settle */ + udelay(2000); /* The 895 needs time for the bus mode to settle */ if (enab_int) OUTW (nc_sien, RST); /* @@ -4161,7 +3826,7 @@ static int ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay) */ OUTB (nc_stest3, TE); OUTB (nc_scntl1, CRST); - UDELAY (200); + udelay(200); if (!driver_setup.bus_check) goto out; @@ -4280,6 +3945,7 @@ static int ncr_reset_bus (struct ncb *np, struct scsi_cmnd *cmd, int sync_reset) return SUCCESS; } +#if 0 /* unused and broken.. */ /*========================================================== ** ** @@ -4360,17 +4026,7 @@ static int ncr_abort_command (struct ncb *np, struct scsi_cmnd *cmd) return retv; } - -/*========================================================== -** -** Linux release module stuff. -** -** Called before unloading the module -** Detach the host. -** We have to free resources and halt the NCR chip -** -**========================================================== -*/ +#endif static void ncr_detach(struct ncb *np) { @@ -4395,7 +4051,8 @@ static void ncr_detach(struct ncb *np) printk("%s: stopping the timer\n", ncr_name(np)); #endif np->release_stage = 1; - for (i = 50 ; i && np->release_stage != 2 ; i--) MDELAY (100); + for (i = 50 ; i && np->release_stage != 2 ; i--) + mdelay(100); if (np->release_stage != 2) printk("%s: the timer seems to be already stopped\n", ncr_name(np)); else np->release_stage = 2; @@ -4536,8 +4193,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) if (lp && lp->held_ccb) { if (cp == lp->held_ccb) { - xpt_que_splice(&lp->skip_ccbq, &lp->wait_ccbq); - xpt_que_init(&lp->skip_ccbq); + list_splice_init(&lp->skip_ccbq, &lp->wait_ccbq); lp->held_ccb = NULL; } } @@ -4609,19 +4265,6 @@ void ncr_complete (struct ncb *np, struct ccb *cp) if (!lp) ncr_alloc_lcb (np, cmd->device->id, cmd->device->lun); - /* - ** On standard INQUIRY response (EVPD and CmDt - ** not set), setup logical unit according to - ** announced capabilities (we need the 1rst 7 bytes). - */ - if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) && - cmd->cmnd[4] >= 7 && !cmd->use_sg) { - sync_scsi_data_for_cpu(np, cmd); /* SYNC the data */ - ncr_setup_lcb (np, cmd->device->id, cmd->device->lun, - (char *) cmd->request_buffer); - sync_scsi_data_for_device(np, cmd); /* SYNC the data */ - } - tp->bytes += cp->data_len; tp->transfers ++; @@ -4634,7 +4277,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) if (lp->num_good >= 1000) { lp->num_good = 0; ++lp->numtags; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } } } else if ((cp->host_status == HS_COMPLETE) @@ -4748,7 +4391,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) ** requeue awaiting scsi commands for this lun. */ if (lp && lp->queuedccbs < lp->queuedepth && - !xpt_que_empty(&lp->wait_ccbq)) + !list_empty(&lp->wait_ccbq)) ncr_start_next_ccb(np, lp, 2); /* @@ -4785,8 +4428,8 @@ static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp) cp->host_status &= ~HS_SKIPMASK; cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); - xpt_remque(&cp->link_ccbq); - xpt_insque_tail(&cp->link_ccbq, &lp->skip_ccbq); + list_del(&cp->link_ccbq); + list_add_tail(&cp->link_ccbq, &lp->skip_ccbq); if (cp->queued) { --lp->queuedccbs; } @@ -4871,7 +4514,7 @@ void ncr_wakeup (struct ncb *np, u_long code) static void ncr_chip_reset(struct ncb *np, int delay) { OUTB (nc_istat, SRST); - UDELAY (delay); + udelay(delay); OUTB (nc_istat, 0 ); if (np->features & FE_EHP) @@ -4900,7 +4543,7 @@ void ncr_init (struct ncb *np, int reset, char * msg, u_long code) if (reset) { OUTB (nc_istat, SRST); - UDELAY (100); + udelay(100); } else { OUTB (nc_stest3, TE|CSF); @@ -5084,8 +4727,11 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) if (minsync > np->maxsync) minsync = 255; + if (tp->maxoffs > np->maxoffs) + tp->maxoffs = np->maxoffs; + tp->minsync = minsync; - tp->maxoffs = (minsync<255 ? np->maxoffs : 0); + tp->maxoffs = (minsync<255 ? tp->maxoffs : 0); /* ** period=0: has to negotiate sync transfer @@ -5215,18 +4861,12 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target) static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer) { - struct scsi_cmnd *cmd; + struct scsi_cmnd *cmd = cp->cmd; struct tcb *tp; u_char target = INB (nc_sdid) & 0x0f; u_char idiv; - assert (cp && cp->cmd); - if (!cp) return; - - cmd = cp->cmd; - if (!cmd) return; - - assert (target == (cmd->device->id & 0xf)); + BUG_ON(target != (cmd->device->id & 0xf)); tp = &np->target[target]; @@ -5299,19 +4939,13 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char s static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack) { - struct scsi_cmnd *cmd; + struct scsi_cmnd *cmd = cp->cmd; u16 target = INB (nc_sdid) & 0x0f; struct tcb *tp; u_char scntl3; u_char sxfer; - assert (cp && cp->cmd); - if (!cp) return; - - cmd = cp->cmd; - if (!cmd) return; - - assert (target == (cmd->device->id & 0xf)); + BUG_ON(target != (cmd->device->id & 0xf)); tp = &np->target[target]; tp->widedone = wide+1; @@ -5351,8 +4985,9 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack **========================================================== */ -static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) +static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev) { + unsigned char tn = sdev->id, ln = sdev->lun; struct tcb *tp = &np->target[tn]; struct lcb *lp = tp->lp[ln]; u_char reqtags, maxdepth; @@ -5360,7 +4995,7 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) /* ** Just in case ... */ - if ((!tp) || (!lp)) + if ((!tp) || (!lp) || !sdev) return; /* @@ -5384,7 +5019,7 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) ** only devices capable of tagged commands ** only if enabled by user .. */ - if ((lp->inq_byte7 & INQ7_QUEUE) && lp->numtags > 1) { + if (sdev->tagged_supported && lp->numtags > 1) { reqtags = lp->numtags; } else { reqtags = 1; @@ -5438,86 +5073,6 @@ static void ncr_setup_tags (struct ncb *np, u_char tn, u_char ln) } } -/*---------------------------------------------------- -** -** handle user commands -** -**---------------------------------------------------- -*/ - -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - -static void ncr_usercmd (struct ncb *np) -{ - u_char t; - struct tcb *tp; - - switch (np->user.cmd) { - - case 0: return; - - case UC_SETSYNC: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrsync = np->user.data; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETTAGS: - for (t=0; tuser.target>>t)&1)) continue; - np->target[t].usrtags = np->user.data; - for (ln = 0; ln < MAX_LUN; ln++) { - struct lcb *lp = np->target[t].lp[ln]; - if (!lp) - continue; - lp->maxtags = lp->numtags = np->user.data; - ncr_setup_tags (np, t, ln); - } - }; - break; - - case UC_SETDEBUG: -#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT - ncr_debug = np->user.data; -#endif - break; - - case UC_SETORDER: - np->order = np->user.data; - break; - - case UC_SETVERBOSE: - np->verbose = np->user.data; - break; - - case UC_SETWIDE: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - size = np->user.data; - if (size > np->maxwide) size=np->maxwide; - tp->usrwide = size; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETFLAG: - for (t=0; tuser.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrflag = np->user.data; - }; - break; - } - np->user.cmd=0; -} -#endif - /*========================================================== ** ** @@ -6002,13 +5557,6 @@ static int ncr_int_par (struct ncb *np) else msg = M_ID_ERROR; -#ifdef SCSI_NCR_INTEGRITY_CHECKING - /* - ** Save error message. For integrity check use only. - */ - if (np->check_integrity) - np->check_integ_par = msg; -#endif /* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a @@ -6353,7 +5901,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) struct scsi_cmnd *cmd = cp->cmd; struct tcb *tp = &np->target[cmd->device->id]; struct lcb *lp = tp->lp[cmd->device->lun]; - XPT_QUEHEAD *qp; + struct list_head *qp; struct ccb * cp2; int disc_cnt = 0; int busy_cnt = 0; @@ -6367,10 +5915,10 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) ** are before cp and busy ones after. */ if (lp) { - qp = lp->busy_ccbq.blink; + qp = lp->busy_ccbq.prev; while (qp != &lp->busy_ccbq) { - cp2 = xpt_que_entry(qp, struct ccb, link_ccbq); - qp = qp->blink; + cp2 = list_entry(qp, struct ccb, link_ccbq); + qp = qp->prev; ++busy_cnt; if (cp2 == cp) break; @@ -6398,7 +5946,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) if (disc_cnt < lp->numtags) { lp->numtags = disc_cnt > 2 ? disc_cnt : 2; lp->num_good = 0; - ncr_setup_tags (np, cmd->device->id, cmd->device->lun); + ncr_setup_tags (np, cmd->device); } /* ** Requeue the command to the start queue. @@ -6450,7 +5998,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) /* ** sense data */ - bzero(cp->sense_buf, sizeof(cp->sense_buf)); + memset(cp->sense_buf, 0, sizeof(cp->sense_buf)); cp->phys.sense.addr = cpu_to_scr(CCB_PHYS(cp,sense_buf[0])); cp->phys.sense.size = cpu_to_scr(sizeof(cp->sense_buf)); @@ -6475,7 +6023,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) /* ** Select without ATN for quirky devices. */ - if (tp->quirks & QUIRK_NOMSG) + if (cmd->device->select_no_atn) cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, select_no_atn)); @@ -6537,6 +6085,7 @@ void ncr_int_sir (struct ncb *np) u_long dsa = INL (nc_dsa); u_char target = INB (nc_sdid) & 0x0f; struct tcb *tp = &np->target[target]; + struct scsi_target *starget = tp->starget; if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num); @@ -6591,7 +6140,8 @@ void ncr_int_sir (struct ncb *np) while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; - assert (cp && cp == np->header.cp); + BUG_ON(!cp); + BUG_ON(cp != np->header.cp); if (!cp || cp != np->header.cp) goto out; @@ -6693,10 +6243,13 @@ void ncr_int_sir (struct ncb *np) case NS_SYNC: ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; break; case NS_WIDE: ncr_setwide (np, cp, 0, 0); + spi_width(starget) = 0; break; }; @@ -6731,8 +6284,8 @@ void ncr_int_sir (struct ncb *np) ** it CAN transfer synch. */ - if (ofs) - tp->inq_byte7 |= INQ7_SYNC; + if (ofs && tp->starget) + spi_support_sync(tp->starget) = 1; /* ** check values against driver limits. @@ -6783,18 +6336,23 @@ void ncr_int_sir (struct ncb *np) ** Answer wasn't acceptable. */ ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + spi_period(starget) = per; + spi_offset(starget) = ofs; OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_WIDE: ncr_setwide (np, cp, 0, 0); + spi_width(starget) = 0; break; }; }; @@ -6805,6 +6363,8 @@ void ncr_int_sir (struct ncb *np) */ ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + spi_period(starget) = per; + spi_offset(starget) = ofs; np->msgout[0] = M_EXTENDED; np->msgout[1] = 3; @@ -6852,8 +6412,8 @@ void ncr_int_sir (struct ncb *np) ** it CAN transfer wide. */ - if (wide) - tp->inq_byte7 |= INQ7_WIDE16; + if (wide && tp->starget) + spi_support_wide(tp->starget) = 1; /* ** check values against driver limits. @@ -6880,18 +6440,22 @@ void ncr_int_sir (struct ncb *np) ** Answer wasn't acceptable. */ ncr_setwide (np, cp, 0, 1); + spi_width(starget) = 0; OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ ncr_setwide (np, cp, wide, 1); + spi_width(starget) = wide; OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_SYNC: ncr_setsync (np, cp, 0, 0xe0); + spi_period(starget) = 0; + spi_offset(starget) = 0; break; }; }; @@ -6902,6 +6466,7 @@ void ncr_int_sir (struct ncb *np) */ ncr_setwide (np, cp, wide, 1); + spi_width(starget) = wide; np->msgout[0] = M_EXTENDED; np->msgout[1] = 2; @@ -7017,7 +6582,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln) ** Lun structure available ? */ if (lp) { - XPT_QUEHEAD *qp; + struct list_head *qp; /* ** Keep from using more tags than we can handle. */ @@ -7027,29 +6592,21 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln) /* ** Allocate a new CCB if needed. */ - if (xpt_que_empty(&lp->free_ccbq)) + if (list_empty(&lp->free_ccbq)) ncr_alloc_ccb(np, tn, ln); - /* - ** Tune tag mode if asked by user. - */ - if (lp->queuedepth != lp->numtags) { - ncr_setup_tags(np, tn, ln); - } - /* ** Look for free CCB */ - qp = xpt_remque_head(&lp->free_ccbq); + qp = ncr_list_pop(&lp->free_ccbq); if (qp) { - cp = xpt_que_entry(qp, struct ccb, link_ccbq); + cp = list_entry(qp, struct ccb, link_ccbq); if (cp->magic) { PRINT_LUN(np, tn, ln); printk ("ccb free list corrupted (@%p)\n", cp); cp = NULL; - } - else { - xpt_insque_tail(qp, &lp->wait_ccbq); + } else { + list_add_tail(qp, &lp->wait_ccbq); ++lp->busyccbs; } } @@ -7159,10 +6716,8 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp) */ if (lp) { - if (cp != np->ccb) { - xpt_remque(&cp->link_ccbq); - xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - } + if (cp != np->ccb) + list_move(&cp->link_ccbq, &lp->free_ccbq); --lp->busyccbs; if (cp->queued) { --lp->queuedccbs; @@ -7200,9 +6755,9 @@ static void ncr_init_ccb(struct ncb *np, struct ccb *cp) cp->phys.header.cp = cp; /* - ** This allows xpt_remque to work for the default ccb. + ** This allows list_del to work for the default ccb. */ - xpt_que_init(&cp->link_ccbq); + INIT_LIST_HEAD(&cp->link_ccbq); /* ** Initialyze the start and restart launch script. @@ -7246,7 +6801,7 @@ static void ncr_alloc_ccb(struct ncb *np, u_char tn, u_char ln) */ lp->actccbs++; np->actccbs++; - bzero (cp, sizeof (*cp)); + memset(cp, 0, sizeof (*cp)); ncr_init_ccb(np, cp); /* @@ -7256,8 +6811,7 @@ static void ncr_alloc_ccb(struct ncb *np, u_char tn, u_char ln) cp->link_ccb = np->ccb->link_ccb; np->ccb->link_ccb = cp; - xpt_insque_head(&cp->link_ccbq, &lp->free_ccbq); - ncr_setup_tags (np, tn, ln); + list_add(&cp->link_ccbq, &lp->free_ccbq); } /*========================================================== @@ -7345,15 +6899,15 @@ static void ncr_init_tcb (struct ncb *np, u_char tn) ** These assert's should be moved at driver initialisations. */ #ifdef SCSI_NCR_BIG_ENDIAN - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 3); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 3); + BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) != 3); + BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) != 3); #else - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 0); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 0); + BUG_ON(((offsetof(struct ncr_reg, nc_sxfer) ^ + offsetof(struct tcb , sval )) &3) != 0); + BUG_ON(((offsetof(struct ncr_reg, nc_scntl3) ^ + offsetof(struct tcb , wval )) &3) != 0); #endif } @@ -7384,7 +6938,7 @@ static struct lcb *ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln) lp = m_calloc_dma(sizeof(struct lcb), "LCB"); if (!lp) goto fail; - bzero(lp, sizeof(*lp)); + memset(lp, 0, sizeof(*lp)); tp->lp[ln] = lp; /* @@ -7396,10 +6950,10 @@ static struct lcb *ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln) /* ** Initialize the CCB queue headers. */ - xpt_que_init(&lp->free_ccbq); - xpt_que_init(&lp->busy_ccbq); - xpt_que_init(&lp->wait_ccbq); - xpt_que_init(&lp->skip_ccbq); + INIT_LIST_HEAD(&lp->free_ccbq); + INIT_LIST_HEAD(&lp->busy_ccbq); + INIT_LIST_HEAD(&lp->wait_ccbq); + INIT_LIST_HEAD(&lp->skip_ccbq); /* ** Set max CCBs to 1 and use the default 1 entry @@ -7455,11 +7009,12 @@ fail: ** will play with CHANGE DEFINITION commands. :-) **------------------------------------------------------------------------ */ -static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char *inq_data) +static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev) { + unsigned char tn = sdev->id, ln = sdev->lun; struct tcb *tp = &np->target[tn]; struct lcb *lp = tp->lp[ln]; - u_char inq_byte7; + struct scsi_target *starget = tp->starget; /* ** If no lcb, try to allocate it. @@ -7468,55 +7023,16 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char * goto fail; /* - ** Get device quirks from a speciality table. - */ - tp->quirks = ncr_lookup (inq_data); - if (tp->quirks && bootverbose) { - PRINT_LUN(np, tn, ln); - printk ("quirks=%x.\n", tp->quirks); - } - - /* - ** Evaluate trustable target/unit capabilities. - ** We only believe device version >= SCSI-2 that - ** use appropriate response data format (2). - ** But it seems that some CCS devices also - ** support SYNC and I donnot want to frustrate - ** anybody. ;-) - */ - inq_byte7 = 0; - if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2) - inq_byte7 = inq_data[7]; - else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1) - inq_byte7 = INQ7_SYNC; - - /* - ** Throw away announced LUN capabilities if we are told - ** that there is no real device supported by the logical unit. - */ - if ((inq_data[0] & 0xe0) > 0x20 || (inq_data[0] & 0x1f) == 0x1f) - inq_byte7 &= (INQ7_SYNC | INQ7_WIDE16); - - /* - ** If user is wanting SYNC, force this feature. + ** Prepare negotiation */ - if (driver_setup.force_sync_nego) - inq_byte7 |= INQ7_SYNC; - - /* - ** Prepare negotiation if SIP capabilities have changed. - */ - tp->inq_done = 1; - if ((inq_byte7 ^ tp->inq_byte7) & (INQ7_SYNC | INQ7_WIDE16)) { - tp->inq_byte7 = inq_byte7; + if (spi_support_wide(starget) || spi_support_sync(starget)) ncr_negotiate(np, tp); - } /* ** If unit supports tagged commands, allocate the ** CCB JUMP table if not yet. */ - if ((inq_byte7 & INQ7_QUEUE) && lp->jump_ccb == &lp->jump_ccb_0) { + if (sdev->tagged_supported && lp->jump_ccb == &lp->jump_ccb_0) { int i; lp->jump_ccb = m_calloc_dma(256, "JUMP_CCB"); if (!lp->jump_ccb) { @@ -7531,16 +7047,9 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, u_char tn, u_char ln, u_char * lp->cb_tags[i] = i; lp->maxnxs = MAX_TAGS; lp->tags_stime = ktime_get(3*HZ); + ncr_setup_tags (np, sdev); } - /* - ** Adjust tagged queueing status if needed. - */ - if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) { - lp->inq_byte7 = inq_byte7; - lp->numtags = lp->maxtags; - ncr_setup_tags (np, tn, ln); - } fail: return lp; @@ -7746,62 +7255,6 @@ static int __init ncr_snooptest (struct ncb* np) return (err); } -/*========================================================== -** -** -** Device lookup. -** -** @GENSCSI@ should be integrated to scsiconf.c -** -** -**========================================================== -*/ - -struct table_entry { - char * manufacturer; - char * model; - char * version; - u_long info; -}; - -static struct table_entry device_tab[] = -{ -#if 0 - {"", "", "", QUIRK_NOMSG}, -#endif - {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, - {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, - {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, - {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, - {"", "", "", 0} /* catch all: must be last entry. */ -}; - -static u_long ncr_lookup(char * id) -{ - struct table_entry * p = device_tab; - char *d, *r, c; - - for (;;p++) { - - d = id+8; - r = p->manufacturer; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+16; - r = p->model; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+32; - r = p->version; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - return (p->info); - } -} - /*========================================================== ** ** Determine the ncr's clock frequency. @@ -7842,11 +7295,11 @@ static void ncr_selectclock(struct ncb *np, u_char scntl3) if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ int i = 20; while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) - UDELAY (20); + udelay(20); if (!i) printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); } else /* Wait 20 micro-seconds for doubler */ - UDELAY (20); + udelay(20); OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ @@ -7887,7 +7340,7 @@ static unsigned __init ncrgetfreq (struct ncb *np, int gen) OUTB (nc_stime1, gen); /* set to nominal delay of 1<host; - struct ncb *np; - struct tcb *tp; - struct lcb *lp; + struct ncb *np = ((struct host_data *) host->hostdata)->ncb; + struct tcb *tp = &np->target[device->id]; + struct lcb *lp = tp->lp[device->lun]; int numtags, depth_to_use; - np = ((struct host_data *) host->hostdata)->ncb; - tp = &np->target[device->id]; - lp = tp->lp[device->lun]; + tp->starget = device->sdev_target; + + ncr_setup_lcb(np, device); /* ** Select queue depth from driver setup. @@ -8013,26 +7462,29 @@ int ncr53c8xx_slave_configure(struct scsi_device *device) ** Since the queue depth is not tunable under Linux, ** we need to know this value in order not to ** announce stupid things to user. + ** + ** XXX(hch): As of Linux 2.6 it certainly _is_ tunable.. + ** In fact we just tuned it, or did I miss + ** something important? :) */ if (lp) { lp->numtags = lp->maxtags = numtags; lp->scdev_depth = depth_to_use; } - ncr_setup_tags (np, device->id, device->lun); + ncr_setup_tags (np, device); #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx_select_queue_depth: host=%d, id=%d, lun=%d, depth=%d\n", np->unit, device->id, device->lun, depth_to_use); #endif + if (spi_support_sync(device->sdev_target) && + !spi_initial_dv(device->sdev_target)) + spi_dv_device(device); return 0; } -/* -** Linux entry point of queuecommand() function -*/ - -int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) +static int ncr53c8xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; unsigned long flags; @@ -8047,7 +7499,7 @@ printk("ncr53c8xx_queue_command\n"); cmd->__data_mapped = 0; cmd->__data_mapping = 0; - NCR_LOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); if ((sts = ncr_queue_command(np, cmd)) != DID_OK) { cmd->result = ScsiResult(sts, 0); @@ -8060,24 +7512,17 @@ printk("ncr53c8xx : command not queued - result=%d\n", sts); printk("ncr53c8xx : command successfully queued\n"); #endif - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); if (sts != DID_OK) { unmap_scsi_data(np, cmd); done(cmd); + sts = 0; } return sts; } -/* -** Linux entry point of the interrupt handler. -** Since linux versions > 1.3.70, we trust the kernel for -** passing the internal host descriptor as 'dev_id'. -** Otherwise, we scan the host list and call the interrupt -** routine for each host that uses this IRQ. -*/ - irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) { unsigned long flags; @@ -8092,58 +7537,42 @@ irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) if (DEBUG_FLAGS & DEBUG_TINY) printk ("["); - NCR_LOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); ncr_exception(np); done_list = np->done_list; np->done_list = NULL; - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n"); - if (done_list) { - NCR_LOCK_SCSI_DONE(done_list->device->host, flags); - ncr_flush_done_cmds(done_list); - NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); - } + if (done_list) + ncr_flush_done_cmds(done_list); return IRQ_HANDLED; } -/* -** Linux entry point of the timer handler -*/ - static void ncr53c8xx_timeout(unsigned long npref) { - struct ncb *np = (struct ncb *) npref; - unsigned long flags; - struct scsi_cmnd *done_list; + struct ncb *np = (struct ncb *) npref; + unsigned long flags; + struct scsi_cmnd *done_list; - NCR_LOCK_NCB(np, flags); - ncr_timeout(np); - done_list = np->done_list; - np->done_list = NULL; - NCR_UNLOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); + ncr_timeout(np); + done_list = np->done_list; + np->done_list = NULL; + spin_unlock_irqrestore(&np->smp_lock, flags); - if (done_list) { - NCR_LOCK_SCSI_DONE(done_list->device->host, flags); - ncr_flush_done_cmds(done_list); - NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); - } + if (done_list) + ncr_flush_done_cmds(done_list); } -/* -** Linux entry point of reset() function -*/ - -int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) +static int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; unsigned long flags; struct scsi_cmnd *done_list; - NCR_LOCK_NCB(np, flags); - /* * If the mid-level driver told us reset is synchronous, it seems * that we must call the done() callback for the involved command, @@ -8151,22 +7580,20 @@ int ncr53c8xx_bus_reset(struct scsi_cmnd *cmd) * before returning SUCCESS. */ + spin_lock_irqsave(&np->smp_lock, flags); sts = ncr_reset_bus(np, cmd, 1); done_list = np->done_list; np->done_list = NULL; - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); ncr_flush_done_cmds(done_list); return sts; } -/* -** Linux entry point of abort() function -*/ - -int ncr53c8xx_abort(struct scsi_cmnd *cmd) +#if 0 /* unused and broken */ +static int ncr53c8xx_abort(struct scsi_cmnd *cmd) { struct ncb *np = ((struct host_data *) cmd->device->host->hostdata)->ncb; int sts; @@ -8202,6 +7629,7 @@ out: return sts; } +#endif /* @@ -8286,291 +7714,23 @@ static void process_waiting_list(struct ncb *np, int sts) #undef next_wcmd -#ifdef SCSI_NCR_PROC_INFO_SUPPORT - -/*========================================================================= -** Proc file system stuff -** -** A read operation returns profile information. -** A write operation is a control command. -** The string is parsed in the driver code and the command is passed -** to the ncr_usercmd() function. -**========================================================================= -*/ - -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - -#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) +static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf) { - 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); + struct Scsi_Host *host = class_to_shost(dev); + struct host_data *host_data = (struct host_data *)host->hostdata; + + return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id); } - -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 ncr_user_command(struct ncb *np, char *buffer, int length) -{ - char *ptr = buffer; - int len = length; - struct usrcmd *uc = &np->user; - 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, "setorder")) != 0) - uc->cmd = UC_SETORDER; - 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; - else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0) - uc->cmd = UC_SETDEBUG; - else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0) - uc->cmd = UC_SETFLAG; - else - arg_len = 0; - -#ifdef DEBUG_PROC_INFO -printk("ncr_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: - 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<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("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETORDER: - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "simple"))) - uc->data = M_SIMPLE_TAG; - else if ((arg_len = is_keyword(ptr, len, "ordered"))) - uc->data = M_ORDERED_TAG; - else if ((arg_len = is_keyword(ptr, len, "default"))) - uc->data = 0; - else - return -EINVAL; - break; - 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 - return -EINVAL; - ptr += arg_len; len -= arg_len; - } -#ifdef DEBUG_PROC_INFO -printk("ncr_user_command: data=%ld\n", uc->data); -#endif - break; - case UC_SETFLAG: - while (len > 0) { - SKIP_SPACES(1); - if ((arg_len = is_keyword(ptr, len, "trace"))) - uc->data |= UF_TRACE; - else if ((arg_len = is_keyword(ptr, len, "no_disc"))) - uc->data |= UF_NODISC; - else - return -EINVAL; - ptr += arg_len; len -= arg_len; - } - break; - default: - break; - } - - if (len) - return -EINVAL; - else { - unsigned long flags; - - NCR_LOCK_NCB(np, flags); - ncr_usercmd (np); - NCR_UNLOCK_NCB(np, flags); - } - return length; -} - -#endif /* SCSI_NCR_USER_COMMAND_SUPPORT */ - - -#ifdef SCSI_NCR_USER_INFO_SUPPORT -/* -** Copy formatted information into the input buffer. -*/ - -static int ncr_host_info(struct ncb *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 NCR53C720, revision id 0x%x, IRQ %d\n", - np->revision_id, (int) np->irq); - copy_info(&info, " Synchronous period factor %d, " - "max commands per lun %d\n", - (int) np->minsync, MAX_TAGS); - - if (driver_setup.debug || driver_setup.verbose > 1) { - copy_info(&info, " Debug flags 0x%x, verbosity level %d\n", - driver_setup.debug, driver_setup.verbose); - } - - return info.pos > info.offset? info.pos - info.offset : 0; -} - -#endif /* SCSI_NCR_USER_INFO_SUPPORT */ - -/* -** Entry point of the scsi proc fs of the driver. -** - func = 0 means read (returns profile data) -** - func = 1 means write (parse user control command) -*/ - -static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, - int length, int func) -{ - struct host_data *host_data; - struct ncb *ncb = NULL; - int retv; - -#ifdef DEBUG_PROC_INFO -printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); -#endif - - host_data = (struct host_data *) host->hostdata; - ncb = host_data->ncb; - - if (func) { -#ifdef SCSI_NCR_USER_COMMAND_SUPPORT - retv = ncr_user_command(ncb, buffer, length); -#else - retv = -EINVAL; -#endif - } - else { - if (start) - *start = buffer; -#ifdef SCSI_NCR_USER_INFO_SUPPORT - retv = ncr_host_info(ncb, buffer, offset, length); -#else - retv = -EINVAL; -#endif - } - - return retv; -} - -/*========================================================================= -** End of proc file system stuff -**========================================================================= -*/ -#endif - + +static struct class_device_attribute ncr53c8xx_revision_attr = { + .attr = { .name = "revision", .mode = S_IRUGO, }, + .show = show_ncr53c8xx_revision, +}; + +static struct class_device_attribute *ncr53c8xx_host_attrs[] = { + &ncr53c8xx_revision_attr, + NULL +}; /*========================================================== ** @@ -8580,10 +7740,10 @@ printk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", host->host_no, func); */ #ifdef MODULE char *ncr53c8xx; /* command line passed by insmod */ -MODULE_PARM(ncr53c8xx, "s"); +module_param(ncr53c8xx, charp, 0); #endif -int __init ncr53c8xx_setup(char *str) +static int __init ncr53c8xx_setup(char *str) { return sym53c8xx__setup(str); } @@ -8592,17 +7752,6 @@ int __init ncr53c8xx_setup(char *str) __setup("ncr53c8xx=", ncr53c8xx_setup); #endif -/*========================================================== -** -** Entry point for info() function -** -**========================================================== -*/ -const char *ncr53c8xx_info (struct Scsi_Host *host) -{ - return SCSI_NCR_DRIVER_NAME; -} - /* * Host attach and initialisations. @@ -8622,13 +7771,14 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, u_long flags = 0; int i; -#ifdef SCSI_NCR_PROC_INFO_SUPPORT - tpnt->proc_info = ncr53c8xx_proc_info, -#endif - tpnt->info = ncr53c8xx_info; + if (!tpnt->name) + tpnt->name = SCSI_NCR_DRIVER_NAME; + if (!tpnt->shost_attrs) + tpnt->shost_attrs = ncr53c8xx_host_attrs; + tpnt->queuecommand = ncr53c8xx_queue_command; tpnt->slave_configure = ncr53c8xx_slave_configure; - tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; + tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; tpnt->can_queue = SCSI_NCR_CAN_QUEUE; tpnt->this_id = 7; tpnt->sg_tablesize = SCSI_NCR_SG_TABLESIZE; @@ -8649,7 +7799,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, np = __m_calloc_dma(device->dev, sizeof(struct ncb), "NCB"); if (!np) goto attach_error; - NCR_INIT_LOCK_NCB(np); + spin_lock_init(&np->smp_lock); np->dev = device->dev; np->p_ncb = vtobus(np); host_data->ncb = np; @@ -8689,7 +7839,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, if (device->slot.base_v) np->vaddr = device->slot.base_v; else - np->vaddr = (unsigned long)ioremap(device->slot.base_c, 128); + np->vaddr = ioremap(device->slot.base_c, 128); if (!np->vaddr) { printk(KERN_ERR @@ -8705,7 +7855,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, * OUTB OUTW OUTL macros can be used safely. */ - np->reg = (struct ncr_reg*) np->vaddr; + np->reg = (struct ncr_reg __iomem *)np->vaddr; /* Do chip dependent initialization. */ ncr_prepare_setting(np); @@ -8716,7 +7866,6 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, ncr_name(np)); } - /* Fill Linux host instance structure */ instance->max_channel = 0; instance->this_id = np->myaddr; instance->max_id = np->maxwide ? 16 : 8; @@ -8727,19 +7876,12 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, instance->dma_channel = 0; instance->cmd_per_lun = MAX_TAGS; instance->can_queue = (MAX_START-4); + /* This can happen if you forget to call ncr53c8xx_init from + * your module_init */ + BUG_ON(!ncr53c8xx_transport_template); + instance->transportt = ncr53c8xx_transport_template; scsi_set_device(instance, device->dev); -#ifdef SCSI_NCR_INTEGRITY_CHECKING - np->check_integrity = 0; - instance->check_integrity = 0; - -#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK - if ( !(driver_setup.bus_check & 0x04) ) { - np->check_integrity = 1; - instance->check_integrity = 1; - } -#endif -#endif /* Patch script to physical addresses */ ncr_script_fill(&script0, &scripth0); @@ -8797,11 +7939,11 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, * Process the reset exception if interrupts are not enabled yet. * Then enable disconnects. */ - NCR_LOCK_NCB(np, flags); + spin_lock_irqsave(&np->smp_lock, flags); if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); goto attach_error; } ncr_exception(np); @@ -8815,7 +7957,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, if (driver_setup.settle_delay > 2) { printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n", ncr_name(np), driver_setup.settle_delay); - MDELAY (1000 * driver_setup.settle_delay); + mdelay(1000 * driver_setup.settle_delay); } /* start the timeout daemon */ @@ -8827,7 +7969,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, np->order = M_SIMPLE_TAG; #endif - NCR_UNLOCK_NCB(np, flags); + spin_unlock_irqrestore(&np->smp_lock, flags); return instance; @@ -8866,3 +8008,73 @@ int ncr53c8xx_release(struct Scsi_Host *host) ncr_detach(host_data->ncb); return 1; } + +static void ncr53c8xx_set_period(struct scsi_target *starget, int period) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (period > np->maxsync) + period = np->maxsync; + else if (period < np->minsync) + period = np->minsync; + + tp->usrsync = period; + + ncr_negotiate(np, tp); +} + +static void ncr53c8xx_set_offset(struct scsi_target *starget, int offset) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (offset > np->maxoffs) + offset = np->maxoffs; + else if (offset < 0) + offset = 0; + + tp->maxoffs = offset; + + ncr_negotiate(np, tp); +} + +static void ncr53c8xx_set_width(struct scsi_target *starget, int width) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct ncb *np = ((struct host_data *)shost->hostdata)->ncb; + struct tcb *tp = &np->target[starget->id]; + + if (width > np->maxwide) + width = np->maxwide; + else if (width < 0) + width = 0; + + tp->usrwide = width; + + ncr_negotiate(np, tp); +} + +static struct spi_function_template ncr53c8xx_transport_functions = { + .set_period = ncr53c8xx_set_period, + .show_period = 1, + .set_offset = ncr53c8xx_set_offset, + .show_offset = 1, + .set_width = ncr53c8xx_set_width, + .show_width = 1, +}; + +int __init ncr53c8xx_init(void) +{ + ncr53c8xx_transport_template = spi_attach_transport(&ncr53c8xx_transport_functions); + if (!ncr53c8xx_transport_template) + return -ENODEV; + return 0; +} + +void ncr53c8xx_exit(void) +{ + spi_release_transport(ncr53c8xx_transport_template); +} diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index adbb47c92..05c7b83ce 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -44,8 +44,6 @@ #include -typedef u_long vm_offset_t; - #include "sym53c8xx_defs.h" /* @@ -72,11 +70,11 @@ struct ncr_slot { u_long base_2; u_long base_c; u_long base_2_c; - u_long base_v; - u_long base_2_v; + void __iomem *base_v; + void __iomem *base_2_v; int irq; /* port and reg fields to use INB, OUTB macros */ - volatile struct ncr_reg *reg; + volatile struct ncr_reg __iomem *reg; }; /*========================================================== @@ -97,5 +95,7 @@ struct ncr_device { extern struct Scsi_Host *ncr_attach(struct scsi_host_template *tpnt, int unit, struct ncr_device *device); extern int ncr53c8xx_release(struct Scsi_Host *host); irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); +extern int ncr53c8xx_init(void); +extern void ncr53c8xx_exit(void); #endif /* NCR53C8XX_H */ diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index b43feb93c..ddb60c018 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -43,10 +43,11 @@ #include #include -#include "scsi.h" +#include +#include +#include #include #include -#include #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) # include @@ -209,37 +210,38 @@ static int nsp32_detect (struct pci_dev *pdev); #else static int nsp32_detect (Scsi_Host_Template *); #endif -static int nsp32_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int nsp32_queuecommand(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); static const char *nsp32_info (struct Scsi_Host *); static int nsp32_release (struct Scsi_Host *); /* SCSI error handler */ -static int nsp32_eh_abort (Scsi_Cmnd *); -static int nsp32_eh_bus_reset (Scsi_Cmnd *); -static int nsp32_eh_host_reset(Scsi_Cmnd *); +static int nsp32_eh_abort (struct scsi_cmnd *); +static int nsp32_eh_bus_reset (struct scsi_cmnd *); +static int nsp32_eh_host_reset(struct scsi_cmnd *); /* generate SCSI message */ -static void nsp32_build_identify(Scsi_Cmnd *); -static void nsp32_build_nop (Scsi_Cmnd *); -static void nsp32_build_reject (Scsi_Cmnd *); -static void nsp32_build_sdtr (Scsi_Cmnd *, unsigned char, unsigned char); +static void nsp32_build_identify(struct scsi_cmnd *); +static void nsp32_build_nop (struct scsi_cmnd *); +static void nsp32_build_reject (struct scsi_cmnd *); +static void nsp32_build_sdtr (struct scsi_cmnd *, unsigned char, unsigned char); /* SCSI message handler */ -static int nsp32_busfree_occur(Scsi_Cmnd *, unsigned short); -static void nsp32_msgout_occur (Scsi_Cmnd *); -static void nsp32_msgin_occur (Scsi_Cmnd *, unsigned long, unsigned short); - -static int nsp32_setup_sg_table (Scsi_Cmnd *); -static int nsp32_selection_autopara(Scsi_Cmnd *); -static int nsp32_selection_autoscsi(Scsi_Cmnd *); -static void nsp32_scsi_done (Scsi_Cmnd *); -static int nsp32_arbitration (Scsi_Cmnd *, unsigned int); -static int nsp32_reselection (Scsi_Cmnd *, unsigned char); -static void nsp32_adjust_busfree (Scsi_Cmnd *, unsigned int); -static void nsp32_restart_autoscsi (Scsi_Cmnd *, unsigned short); +static int nsp32_busfree_occur(struct scsi_cmnd *, unsigned short); +static void nsp32_msgout_occur (struct scsi_cmnd *); +static void nsp32_msgin_occur (struct scsi_cmnd *, unsigned long, unsigned short); + +static int nsp32_setup_sg_table (struct scsi_cmnd *); +static int nsp32_selection_autopara(struct scsi_cmnd *); +static int nsp32_selection_autoscsi(struct scsi_cmnd *); +static void nsp32_scsi_done (struct scsi_cmnd *); +static int nsp32_arbitration (struct scsi_cmnd *, unsigned int); +static int nsp32_reselection (struct scsi_cmnd *, unsigned char); +static void nsp32_adjust_busfree (struct scsi_cmnd *, unsigned int); +static void nsp32_restart_autoscsi (struct scsi_cmnd *, unsigned short); /* SCSI SDTR */ -static void nsp32_analyze_sdtr (Scsi_Cmnd *); +static void nsp32_analyze_sdtr (struct scsi_cmnd *); static int nsp32_search_period_entry(nsp32_hw_data *, nsp32_target *, unsigned char); static void nsp32_set_async (nsp32_hw_data *, nsp32_target *); static void nsp32_set_max_sync (nsp32_hw_data *, nsp32_target *, unsigned char *, unsigned char *); @@ -267,8 +269,8 @@ static void nsp32_prom_stop (nsp32_hw_data *); static int nsp32_prom_read (nsp32_hw_data *, int); static int nsp32_prom_read_bit (nsp32_hw_data *); static void nsp32_prom_write_bit(nsp32_hw_data *, int); -static inline void nsp32_prom_set (nsp32_hw_data *, int, int); -static inline int nsp32_prom_get (nsp32_hw_data *, int); +static void nsp32_prom_set (nsp32_hw_data *, int, int); +static int nsp32_prom_get (nsp32_hw_data *, int); /* debug/warning/info message */ static void nsp32_message (const char *, int, char *, char *, ...); @@ -279,7 +281,7 @@ static void nsp32_dmessage(const char *, int, int, char *, ...); /* * max_sectors is currently limited up to 128. */ -static Scsi_Host_Template nsp32_template = { +static struct scsi_host_template nsp32_template = { .proc_name = "nsp32", .name = "Workbit NinjaSCSI-32Bi/UDE", .proc_info = nsp32_proc_info, @@ -388,7 +390,7 @@ static void nsp32_dmessage(const char *func, int line, int mask, char *fmt, ...) /* * IDENTIFY Message */ -static void nsp32_build_identify(Scsi_Cmnd *SCpnt) +static void nsp32_build_identify(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; @@ -407,7 +409,7 @@ static void nsp32_build_identify(Scsi_Cmnd *SCpnt) /* * SDTR Message Routine */ -static void nsp32_build_sdtr(Scsi_Cmnd *SCpnt, +static void nsp32_build_sdtr(struct scsi_cmnd *SCpnt, unsigned char period, unsigned char offset) { @@ -426,7 +428,7 @@ static void nsp32_build_sdtr(Scsi_Cmnd *SCpnt, /* * No Operation Message */ -static void nsp32_build_nop(Scsi_Cmnd *SCpnt) +static void nsp32_build_nop(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; @@ -444,7 +446,7 @@ static void nsp32_build_nop(Scsi_Cmnd *SCpnt) /* * Reject Message */ -static void nsp32_build_reject(Scsi_Cmnd *SCpnt) +static void nsp32_build_reject(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; @@ -457,7 +459,7 @@ static void nsp32_build_reject(Scsi_Cmnd *SCpnt) * timer */ #if 0 -static void nsp32_start_timer(Scsi_Cmnd *SCpnt, int time) +static void nsp32_start_timer(struct scsi_cmnd *SCpnt, int time) { unsigned int base = SCpnt->host->io_port; @@ -475,7 +477,7 @@ static void nsp32_start_timer(Scsi_Cmnd *SCpnt, int time) /* * set SCSI command and other parameter to asic, and start selection phase */ -static int nsp32_selection_autopara(Scsi_Cmnd *SCpnt) +static int nsp32_selection_autopara(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -606,7 +608,7 @@ static int nsp32_selection_autopara(Scsi_Cmnd *SCpnt) /* * Selection with AUTO SCSI (without AUTO PARAMETER) */ -static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt) +static int nsp32_selection_autoscsi(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -781,7 +783,7 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt) * arbitration delay time is defined minimal 2.4us in SCSI * specification, thus udelay works as coarse grained wait timer. */ -static int nsp32_arbitration(Scsi_Cmnd *SCpnt, unsigned int base) +static int nsp32_arbitration(struct scsi_cmnd *SCpnt, unsigned int base) { unsigned char arbit; int status = TRUE; @@ -830,7 +832,7 @@ static int nsp32_arbitration(Scsi_Cmnd *SCpnt, unsigned int base) * reselection target id&lun must be already set. * SCSI-2 says IDENTIFY implies RESTORE_POINTER operation. */ -static int nsp32_reselection(Scsi_Cmnd *SCpnt, unsigned char newlun) +static int nsp32_reselection(struct scsi_cmnd *SCpnt, unsigned char newlun) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int host_id = SCpnt->device->host->this_id; @@ -884,7 +886,7 @@ static int nsp32_reselection(Scsi_Cmnd *SCpnt, unsigned char newlun) * * Note: NinjaSCSI-32Bi/UDE bus master can not transfer over 64KB at a time. */ -static int nsp32_setup_sg_table(Scsi_Cmnd *SCpnt) +static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; struct scatterlist *sgl; @@ -904,7 +906,7 @@ static int nsp32_setup_sg_table(Scsi_Cmnd *SCpnt) if (SCpnt->use_sg) { sgl = (struct scatterlist *)SCpnt->request_buffer; num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->sc_data_direction); for (i = 0; i < num; i++) { /* * Build nsp32_sglist, substitute sg dma addresses. @@ -932,7 +934,7 @@ static int nsp32_setup_sg_table(Scsi_Cmnd *SCpnt) } else { SCpnt->SCp.have_data_in = pci_map_single(data->Pci, SCpnt->request_buffer, SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->sc_data_direction); sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in); sgt[0].len = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */ @@ -950,7 +952,7 @@ static int nsp32_setup_sg_table(Scsi_Cmnd *SCpnt) return TRUE; } -static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static int nsp32_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; nsp32_target *target; @@ -968,8 +970,7 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) data->CurrentSC = NULL; SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); - - return SCSI_MLQUEUE_HOST_BUSY; + return 0; } /* check target ID is not same as this initiator ID */ @@ -977,7 +978,7 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???"); SCpnt->result = DID_BAD_TARGET << 16; done(SCpnt); - return SCSI_MLQUEUE_DEVICE_BUSY; + return 0; } /* check target LUN is allowable value */ @@ -985,7 +986,7 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "no more lun"); SCpnt->result = DID_BAD_TARGET << 16; done(SCpnt); - return SCSI_MLQUEUE_DEVICE_BUSY; + return 0; } show_command(SCpnt); @@ -1017,7 +1018,7 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) nsp32_msg(KERN_ERR, "SGT fail"); SCpnt->result = DID_ERROR << 16; nsp32_scsi_done(SCpnt); - return SCSI_MLQUEUE_HOST_BUSY; + return 0; } /* Build IDENTIFY */ @@ -1087,7 +1088,6 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) if (ret != TRUE) { nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "selection fail"); nsp32_scsi_done(SCpnt); - return SCSI_MLQUEUE_DEVICE_BUSY; } return 0; @@ -1205,7 +1205,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs) { nsp32_hw_data *data = dev_id; unsigned int base = data->BaseAddress; - Scsi_Cmnd *SCpnt = data->CurrentSC; + struct scsi_cmnd *SCpnt = data->CurrentSC; unsigned short auto_stat, irq_stat, trans_stat; unsigned char busmon, busphase; unsigned long flags; @@ -1622,7 +1622,7 @@ static int nsp32_proc_info( * Reset parameters and call scsi_done for data->cur_lunt. * Be careful setting SCpnt->result = DID_* before calling this function. */ -static void nsp32_scsi_done(Scsi_Cmnd *SCpnt) +static void nsp32_scsi_done(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -1637,13 +1637,12 @@ static void nsp32_scsi_done(Scsi_Cmnd *SCpnt) if (SCpnt->use_sg) { pci_unmap_sg(data->Pci, (struct scatterlist *)SCpnt->buffer, - SCpnt->use_sg, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->use_sg, SCpnt->sc_data_direction); } else { pci_unmap_single(data->Pci, (u32)SCpnt->SCp.have_data_in, SCpnt->request_bufflen, - scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); + SCpnt->sc_data_direction); } skip: @@ -1678,7 +1677,7 @@ static void nsp32_scsi_done(Scsi_Cmnd *SCpnt) * MsgIn 04: Diconnect. * In other case, unexpected BUSFREE is detected. */ -static int nsp32_busfree_occur(Scsi_Cmnd *SCpnt, unsigned short execph) +static int nsp32_busfree_occur(struct scsi_cmnd *SCpnt, unsigned short execph) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -1836,7 +1835,7 @@ static int nsp32_busfree_occur(Scsi_Cmnd *SCpnt, unsigned short execph) * Note: This driver adjust the SG table using SCSI ACK * counter instead of BMCNT counter! */ -static void nsp32_adjust_busfree(Scsi_Cmnd *SCpnt, unsigned int s_sacklen) +static void nsp32_adjust_busfree(struct scsi_cmnd *SCpnt, unsigned int s_sacklen) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int old_entry = data->cur_entry; @@ -1909,7 +1908,7 @@ static void nsp32_adjust_busfree(Scsi_Cmnd *SCpnt, unsigned int s_sacklen) * message out phase. It, however, has more than 3 messages, * HBA creates the interrupt and we have to process by hand. */ -static void nsp32_msgout_occur(Scsi_Cmnd *SCpnt) +static void nsp32_msgout_occur(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -1985,7 +1984,7 @@ static void nsp32_msgout_occur(Scsi_Cmnd *SCpnt) * Note: Restarting AutoSCSI needs set: * SYNC_REG, ACK_WIDTH, SGT_ADR, TRANSFER_CONTROL */ -static void nsp32_restart_autoscsi(Scsi_Cmnd *SCpnt, unsigned short command) +static void nsp32_restart_autoscsi(struct scsi_cmnd *SCpnt, unsigned short command) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = data->BaseAddress; @@ -2051,7 +2050,7 @@ static void nsp32_restart_autoscsi(Scsi_Cmnd *SCpnt, unsigned short command) /* * cannot run automatically message in occur */ -static void nsp32_msgin_occur(Scsi_Cmnd *SCpnt, +static void nsp32_msgin_occur(struct scsi_cmnd *SCpnt, unsigned long irq_status, unsigned short execph) { @@ -2348,7 +2347,7 @@ static void nsp32_msgin_occur(Scsi_Cmnd *SCpnt, /* * */ -static void nsp32_analyze_sdtr(Scsi_Cmnd *SCpnt) +static void nsp32_analyze_sdtr(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; nsp32_target *target = data->cur_target; @@ -2720,7 +2719,7 @@ static int nsp32_detect(Scsi_Host_Template *sht) host->io_port = data->BaseAddress; host->unique_id = data->BaseAddress; host->n_io_port = data->NumAddress; - host->base = data->MmioAddress; + host->base = (unsigned long)data->MmioAddress; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,63)) scsi_set_device(host, &PCIDEV->dev); #else @@ -2938,8 +2937,8 @@ static int nsp32_release(struct Scsi_Host *host) release_region(host->io_port, host->n_io_port); } - if (data->MmioAddress != 0) { - iounmap((void *)(data->MmioAddress)); + if (data->MmioAddress) { + iounmap(data->MmioAddress); } return 0; @@ -2956,7 +2955,7 @@ static const char *nsp32_info(struct Scsi_Host *shpnt) /**************************************************************************** * error handler */ -static int nsp32_eh_abort(Scsi_Cmnd *SCpnt) +static int nsp32_eh_abort(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -2984,7 +2983,7 @@ static int nsp32_eh_abort(Scsi_Cmnd *SCpnt) return SUCCESS; } -static int nsp32_eh_bus_reset(Scsi_Cmnd *SCpnt) +static int nsp32_eh_bus_reset(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; @@ -3041,7 +3040,7 @@ static void nsp32_do_bus_reset(nsp32_hw_data *data) data->CurrentSC = NULL; } -static int nsp32_eh_host_reset(Scsi_Cmnd *SCpnt) +static int nsp32_eh_host_reset(struct scsi_cmnd *SCpnt) { struct Scsi_Host *host = SCpnt->device->host; unsigned int base = SCpnt->device->host->io_port; @@ -3342,7 +3341,7 @@ static int nsp32_prom_read(nsp32_hw_data *data, int romaddr) return val; } -static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val) +static void nsp32_prom_set(nsp32_hw_data *data, int bit, int val) { int base = data->BaseAddress; int tmp; @@ -3360,7 +3359,7 @@ static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val) udelay(10); } -static inline int nsp32_prom_get(nsp32_hw_data *data, int bit) +static int nsp32_prom_get(nsp32_hw_data *data, int bit) { int base = data->BaseAddress; int tmp, ret; @@ -3439,11 +3438,10 @@ static int nsp32_prom_read_bit(nsp32_hw_data *data) static int nsp32_suspend(struct pci_dev *pdev, u32 state) { struct Scsi_Host *host = pci_get_drvdata(pdev); - nsp32_hw_data *data = (nsp32_hw_data *)host->hostdata; nsp32_msg(KERN_INFO, "pci-suspend: pdev=0x%p, state=%ld, slot=%s, host=0x%p", pdev, state, pci_name(pdev), host); - pci_save_state (pdev, data->PciState); + pci_save_state (pdev); pci_disable_device (pdev); pci_set_power_state(pdev, state); @@ -3461,7 +3459,7 @@ static int nsp32_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_enable_wake (pdev, 0, 0); - pci_restore_state (pdev, data->PciState); + pci_restore_state (pdev); reg = nsp32_read2(data->BaseAddress, INDEX_REG); @@ -3512,8 +3510,7 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i data->IrqNumber = pdev->irq; data->BaseAddress = pci_resource_start(pdev, 0); data->NumAddress = pci_resource_len (pdev, 0); - data->MmioAddress = - (unsigned long)ioremap_nocache(pci_resource_start(pdev, 1), + data->MmioAddress = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len (pdev, 1)); data->MmioLength = pci_resource_len (pdev, 1); @@ -3525,7 +3522,7 @@ static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_i ret = scsi_register_host(&nsp32_template); #endif - nsp32_msg(KERN_INFO, "irq: %i mmio: 0x%lx+0x%lx slot: %s model: %s", + nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s", pdev->irq, data->MmioAddress, data->MmioLength, pci_name(pdev), diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index eddb950c5..5664398fa 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -499,7 +499,7 @@ typedef struct _nsp32_autoparam { #define MSGIN03 BIT(1) /* Auto Msg In 03 Flag */ typedef struct _nsp32_lunt { - Scsi_Cmnd *SCpnt; /* Current Handling Scsi_Cmnd */ + struct scsi_cmnd *SCpnt; /* Current Handling struct scsi_cmnd */ unsigned long save_datp; /* Save Data Pointer - saved position from initial address */ int msgin03; /* auto msg in 03 flag */ unsigned int sg_num; /* Total number of SG entries */ @@ -563,11 +563,11 @@ typedef struct _nsp32_hw_data { int IrqNumber; int BaseAddress; int NumAddress; - unsigned long MmioAddress; + void __iomem *MmioAddress; #define NSP32_MMIO_OFFSET 0x0800 unsigned long MmioLength; - Scsi_Cmnd *CurrentSC; + struct scsi_cmnd *CurrentSC; struct pci_dev *Pci; const struct pci_device_id *pci_devid; @@ -605,9 +605,6 @@ typedef struct _nsp32_hw_data { unsigned char msginbuf [MSGINBUF_MAX]; /* megin buffer */ char msgin_len; /* msginbuf length */ -#ifdef CONFIG_PM - u32 PciState[16]; /* save PCI state to this area */ -#endif } nsp32_hw_data; /* diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index fb74a2f64..8b81553a3 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -47,6 +47,7 @@ const char * osst_version = "0.99.1"; #include #include #include +#include #include #include #include @@ -81,13 +82,13 @@ MODULE_AUTHOR("Willem Riede"); MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(max_dev, "i"); +module_param(max_dev, int, 0); MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)"); -MODULE_PARM(write_threshold_kbs, "i"); +module_param(write_threshold_kbs, int, 0); MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)"); -MODULE_PARM(max_sg_segs, "i"); +module_param(max_sg_segs, int, 0); MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)"); #else static struct osst_dev_parm { @@ -472,7 +473,7 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet char * name = tape_name(STp); os_aux_t * aux = STp->buffer->aux; os_partition_t * par = &(aux->partition); - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); int blk_cnt, blk_sz, i; if (STp->raw) { @@ -613,10 +614,8 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name); #endif - if (initial_delay > 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(initial_delay); - } + if (initial_delay > 0) + msleep(jiffies_to_msecs(initial_delay)); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; @@ -637,8 +636,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned debugging = 0; } #endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + msleep(100); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; @@ -697,8 +695,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi debugging = 0; } #endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + msleep(100); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; @@ -818,8 +815,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, notyetprinted--; } #endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout (HZ / OSST_POLL_PER_SEC); + msleep(1000 / OSST_POLL_PER_SEC); } #if DEBUG printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n", @@ -906,7 +902,7 @@ static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeo static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) { - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); Scsi_Request * SRpnt ; unsigned char cmd[MAX_COMMAND_SIZE]; int retval = 0; @@ -944,7 +940,7 @@ static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet) { - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); char * name = tape_name(STp); int cnt = 0, bad = 0, @@ -1070,7 +1066,7 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num) { - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); char * name = tape_name(STp); int retries = 0; int frame_seq_estimate, ppos_estimate, move; @@ -1209,7 +1205,7 @@ static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector) { - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); int frame = sector >> OSST_FRAME_SHIFT, offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, r; @@ -1420,8 +1416,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) { /* in the process of becoming ready */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + msleep(100); continue; } if (STp->buffer->syscall_result) @@ -1571,7 +1566,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending) { Scsi_Request * SRpnt = * aSRpnt; - ST_partstat * STps = & STp->ps[STp->partition]; + struct st_partstat * STps = & STp->ps[STp->partition]; char * name = tape_name(STp); int retval = 0; int rw_state; @@ -2761,7 +2756,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, in { unsigned char scmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; - ST_partstat * STps; + struct st_partstat * STps; int result = 0; int pp = (ppos == 3000 && !skip)? 0 : ppos; char * name = tape_name(STp); @@ -2817,7 +2812,7 @@ static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, in static int osst_write_trailer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int leave_at_EOT) { - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_partstat * STps = &(STp->ps[STp->partition]); int result = 0; if (STp->write_type != OS_WRITE_NEW_MARK) { @@ -2848,7 +2843,7 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt) int result = 0; unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt = *aSRpnt; - ST_partstat * STps; + struct st_partstat * STps; char * name = tape_name(STp); if ((STp->buffer)->writing) { @@ -2974,7 +2969,7 @@ static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt) seek_next is true. */ static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next) { - ST_partstat * STps; + struct st_partstat * STps; int backspace = 0, result = 0; #if DEBUG char * name = tape_name(STp); @@ -3139,7 +3134,7 @@ static int do_door_lock(OS_Scsi_Tape * STp, int do_lock) static void reset_state(OS_Scsi_Tape *STp) { int i; - ST_partstat *STps; + struct st_partstat *STps; STp->pos_unknown = 0; for (i = 0; i < ST_NBR_PARTITIONS; i++) { @@ -3165,8 +3160,8 @@ static ssize_t osst_write(struct file * filp, const char __user * buf, size_t co int doing_write = 0; const char __user * b_point; Scsi_Request * SRpnt = NULL; - ST_mode * STm; - ST_partstat * STps; + struct st_modedef * STm; + struct st_partstat * STps; OS_Scsi_Tape * STp = filp->private_data; char * name = tape_name(STp); @@ -3485,8 +3480,8 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo ssize_t total, retval = 0; ssize_t i, transfer; int special; - ST_mode * STm; - ST_partstat * STps; + struct st_modedef * STm; + struct st_partstat * STps; Scsi_Request * SRpnt = NULL; OS_Scsi_Tape * STp = filp->private_data; char * name = tape_name(STp); @@ -3665,7 +3660,8 @@ out: /* Set the driver options */ -static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, char *name) +static void osst_log_options(OS_Scsi_Tape *STp, struct st_modedef *STm, + char *name) { printk(KERN_INFO "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", @@ -3692,12 +3688,12 @@ static int osst_set_options(OS_Scsi_Tape *STp, long options) { int value; long code; - ST_mode * STm; + struct st_modedef * STm; char * name = tape_name(STp); STm = &(STp->modes[STp->current_mode]); if (!STm->defined) { - memcpy(STm, &(STp->modes[0]), sizeof(ST_mode)); + memcpy(STm, &(STp->modes[0]), sizeof(*STm)); modes_defined = TRUE; #if DEBUG if (debugging) @@ -3852,7 +3848,7 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i int chg_eof = TRUE; unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt = * aSRpnt; - ST_partstat * STps; + struct st_partstat * STps; int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num; int datalen = 0, direction = SCSI_DATA_NONE; char * name = tape_name(STp); @@ -4236,8 +4232,8 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt = NULL; OS_Scsi_Tape * STp; - ST_mode * STm; - ST_partstat * STps; + struct st_modedef * STm; + struct st_partstat * STps; char * name; int dev = TAPE_NR(inode); int mode = TAPE_MODE(inode); @@ -4594,8 +4590,8 @@ static int os_scsi_tape_flush(struct file * filp) { int result = 0, result2; OS_Scsi_Tape * STp = filp->private_data; - ST_mode * STm = &(STp->modes[STp->current_mode]); - ST_partstat * STps = &(STp->ps[STp->partition]); + struct st_modedef * STm = &(STp->modes[STp->current_mode]); + struct st_partstat * STps = &(STp->ps[STp->partition]); Scsi_Request * SRpnt = NULL; char * name = tape_name(STp); @@ -4709,8 +4705,8 @@ static int osst_ioctl(struct inode * inode,struct file * file, { int i, cmd_nr, cmd_type, retval = 0; unsigned int blk; - ST_mode * STm; - ST_partstat * STps; + struct st_modedef * STm; + struct st_partstat * STps; Scsi_Request * SRpnt = NULL; OS_Scsi_Tape * STp = file->private_data; char * name = tape_name(STp); @@ -5417,8 +5413,8 @@ static int osst_probe(struct device *dev) { Scsi_Device * SDp = to_scsi_device(dev); OS_Scsi_Tape * tpnt; - ST_mode * STm; - ST_partstat * STps; + struct st_modedef * STm; + struct st_partstat * STps; OSST_buffer * buffer; struct gendisk * drive; int i, mode, dev_num; diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index 7e8e7fb40..84bbc591a 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -552,14 +552,14 @@ typedef struct { int long_timeout; /* timeout for commands known to take long time*/ /* Mode characteristics */ - ST_mode modes[ST_NBR_MODES]; + struct st_modedef modes[ST_NBR_MODES]; int current_mode; /* Status variables */ int partition; int new_partition; int nbr_partitions; /* zero until partition support enabled */ - ST_partstat ps[ST_NBR_PARTITIONS]; + struct st_partstat ps[ST_NBR_PARTITIONS]; unsigned char dirty; unsigned char ready; unsigned char write_prot; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 1c9788e2d..e70dedb0d 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -605,6 +605,7 @@ static int pas16_release(struct Scsi_Host *shost) { if (shost->irq) free_irq(shost->irq, NULL); + NCR5380_exit(shost); if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) @@ -632,7 +633,7 @@ static Scsi_Host_Template driver_template = { #include "scsi_module.c" #ifdef MODULE -MODULE_PARM(pas16_addr, "h"); -MODULE_PARM(pas16_irq, "i"); +module_param(pas16_addr, ushort, 0); +module_param(pas16_irq, int, 0); #endif MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 42cdba92b..0520121af 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -58,7 +58,7 @@ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); +module_param(pc_debug, int, 0644); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = "aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)"; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 363d79399..93161b01b 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -226,7 +226,7 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen"); SCpnt->result = DID_BAD_TARGET << 16; nsp_scsi_done(SCpnt); - return SCSI_MLQUEUE_HOST_BUSY; + return 0; } #if 0 @@ -273,7 +273,7 @@ static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail"); SCpnt->result = DID_BUS_BUSY << 16; nsp_scsi_done(SCpnt); - return SCSI_MLQUEUE_DEVICE_BUSY; + return 0; } @@ -1528,7 +1528,7 @@ nsp_proc_info( thislength = pos - (buffer + offset); if(thislength < 0) { - *start = 0; + *start = NULL; return 0; } diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 9ea9a108b..abb755f94 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -66,7 +66,7 @@ static char qlogic_name[] = "qlogic_cs"; #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); +module_param(pc_debug, int, 0644); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = "qlogic_cs.c 1.79-ac 2002/10/26 (David Hinds)"; #else diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 4277db3b6..84d063456 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -85,7 +85,7 @@ static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"sym53c500_cs.c 0.9b 2004/05/10 (Bob Tracy)"; +"sym53c500_cs.c 0.9c 2004/10/27 (Bob Tracy)"; #else #define DEBUG(n, args...) #endif @@ -95,13 +95,12 @@ static char *version = /* Parameters that can be set with 'insmod' */ /* Bit map of interrupts to choose from */ -static unsigned int irq_mask = 0xdeb8; /* 3, 6, 7, 9-12, 14, 15 */ +static unsigned int irq_mask = 0xdeb8; /* 3-5, 7, 9-12, 14, 15 */ static int irq_list[4] = { -1 }; -static int num_irqs = 1; module_param(irq_mask, int, 0); MODULE_PARM_DESC(irq_mask, "IRQ mask bits (default: 0xdeb8)"); -module_param_array(irq_list, int, num_irqs, 0); +module_param_array(irq_list, int, NULL, 0); MODULE_PARM_DESC(irq_list, "Comma-separated list of up to 4 IRQs to try (default: auto select)."); /* ================================================================== */ @@ -830,7 +829,7 @@ next_entry: data = (struct sym53c500_data *)host->hostdata; if (irq_level > 0) { - if (request_irq(irq_level, SYM53C500_intr, 0, "SYM53C500", host)) { + if (request_irq(irq_level, SYM53C500_intr, SA_SHIRQ, "SYM53C500", host)) { printk("SYM53C500: unable to allocate IRQ %d\n", irq_level); goto err_free_scsi; } diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index aa505c1ba..03df5b630 100644 --- a/drivers/scsi/psi240i.c +++ b/drivers/scsi/psi240i.c @@ -641,41 +641,6 @@ static int Psi240i_Release(struct Scsi_Host *shost) return 0; } -/**************************************************************** - * Name: Psi240i_Abort - * - * Description: Process the Abort command from the SCSI manager. - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * - * Returns: Allways snooze. - * - ****************************************************************/ -int Psi240i_Abort (Scsi_Cmnd *SCpnt) - { - DEB (printk ("psi240i_abort\n")); - return SCSI_ABORT_SNOOZE; - } -/**************************************************************** - * Name: Psi240i_Reset - * - * Description: Process the Reset command from the SCSI manager. - * - * Parameters: SCpnt - Pointer to SCSI command structure. - * flags - Flags about the reset command - * - * Returns: No active command at this time, so this means - * that each time we got some kind of response the - * last time through. Tell the mid-level code to - * request sense information in order to decide what - * to do next. - * - ****************************************************************/ -int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) - { - return SCSI_RESET_PUNT; - } - /**************************************************************** * Name: Psi240i_BiosParam * @@ -710,8 +675,6 @@ static Scsi_Host_Template driver_template = { .detect = Psi240i_Detect, .release = Psi240i_Release, .queuecommand = Psi240i_QueueCommand, - .abort = Psi240i_Abort, - .reset = Psi240i_Reset, .bios_param = Psi240i_BiosParam, .can_queue = 1, .this_id = -1, diff --git a/drivers/scsi/ql12160_fw.h b/drivers/scsi/ql12160_fw.h index 73074e658..9db6a208c 100644 --- a/drivers/scsi/ql12160_fw.h +++ b/drivers/scsi/ql12160_fw.h @@ -26,15 +26,9 @@ */ #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_version = 10*1024+4; +static unsigned char fw12160i_version_str[] = {10,4,32}; #else -unsigned short risc_code_version = 10*1024+4; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw12160i_version_str[] = {10,4,32}; -#else -unsigned char firmware_version[] = {10,4,32}; +static unsigned char firmware_version[] = {10,4,32}; #endif #ifdef UNIQUE_FW_NAME @@ -44,15 +38,15 @@ unsigned char firmware_version[] = {10,4,32}; #endif #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_addr01 = 0x1000; +static unsigned short fw12160i_addr01 = 0x1000; #else -unsigned short risc_code_addr01 = 0x1000; +static unsigned short risc_code_addr01 = 0x1000; #endif #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_code01[] = { +static unsigned short fw12160i_code01[] = { #else -unsigned short risc_code01[] = { +static unsigned short risc_code01[] = { #endif 0x0804, 0x1041, 0x0000, 0x35e6, 0x0000, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, @@ -1781,7 +1775,7 @@ unsigned short risc_code01[] = { 0x681f, 0x000c, 0x70a0, 0x70a2, 0x0005, 0x7c12 }; #ifdef UNIQUE_FW_NAME -unsigned short fw12160i_length01 = 0x35e6; +static unsigned short fw12160i_length01 = 0x35e6; #else -unsigned short risc_code_length01 = 0x35e6; +static unsigned short risc_code_length01 = 0x35e6; #endif diff --git a/drivers/scsi/ql1280_fw.h b/drivers/scsi/ql1280_fw.h index 7ad051de9..2621e99a4 100644 --- a/drivers/scsi/ql1280_fw.h +++ b/drivers/scsi/ql1280_fw.h @@ -27,15 +27,9 @@ */ #ifdef UNIQUE_FW_NAME -unsigned short fw1280ei_version = 8*1024+15; +static unsigned char fw1280ei_version_str[] = {8,15,0}; #else -unsigned short risc_code_version = 8*1024+15; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw1280ei_version_str[] = {8,15,0}; -#else -unsigned char firmware_version[] = {8,15,0}; +static unsigned char firmware_version[] = {8,15,0}; #endif #ifdef UNIQUE_FW_NAME @@ -45,15 +39,15 @@ unsigned char firmware_version[] = {8,15,0}; #endif #ifdef UNIQUE_FW_NAME -unsigned short fw1280ei_addr01 = 0x1000; +static unsigned short fw1280ei_addr01 = 0x1000; #else -unsigned short risc_code_addr01 = 0x1000; +static unsigned short risc_code_addr01 = 0x1000; #endif #ifdef UNIQUE_FW_NAME -unsigned short fw1280ei_code01[] = { +static unsigned short fw1280ei_code01[] = { #else -unsigned short risc_code01[] = { +static unsigned short risc_code01[] = { #endif 0x0078, 0x1041, 0x0000, 0x3d3b, 0x0000, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, @@ -2017,7 +2011,7 @@ unsigned short risc_code01[] = { 0x70a2, 0x007c, 0x205b }; #ifdef UNIQUE_FW_NAME -unsigned short fw1280ei_length01 = 0x3d3b; +static unsigned short fw1280ei_length01 = 0x3d3b; #else -unsigned short risc_code_length01 = 0x3d3b; +static unsigned short risc_code_length01 = 0x3d3b; #endif diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 917a208d1..f1eb31b95 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4,7 +4,7 @@ * QLogic QLA1280 (Ultra2) and QLA12160 (Ultra3) SCSI driver * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com) * Copyright (C) 2001-2004 Jes Sorensen, Wild Open Source Inc. -* Copyright (C) 2003 Christoph Hellwig +* Copyright (C) 2003-2004 Christoph Hellwig * * 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 @@ -17,9 +17,15 @@ * General Public License for more details. * ******************************************************************************/ -#define QLA1280_VERSION "3.24.3" +#define QLA1280_VERSION "3.25" /***************************************************************************** Revision History: + Rev 3.25, September 28, 2004, Christoph Hellwig + - add support for ISP1020/1040 + - don't include "scsi.h" anymore for 2.6.x + Rev 3.24.4 June 7, 2004 Christoph Hellwig + - restructure firmware loading, cleanup initialization code + - prepare support for ISP1020/1040 chips Rev 3.24.3 January 19, 2004, Jes Sorensen - Handle PCI DMA mask settings correctly - Correct order of error handling in probe_one, free_irq should not @@ -353,7 +359,6 @@ #include #include #include -#include "scsi.h" #else #include #include "scsi.h" @@ -361,6 +366,10 @@ #include "sd.h" #endif +#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) +#include +#endif + #if LINUX_VERSION_CODE < 0x020407 #error "Kernels older than 2.4.7 are no longer supported" #endif @@ -387,6 +396,7 @@ #include "qla1280.h" #include "ql12160_fw.h" /* ISP RISC codes */ #include "ql1280_fw.h" +#include "ql1040_fw.h" /* @@ -419,13 +429,6 @@ #define QLA_64BIT_PTR 1 #endif -#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) -#include -/* Ugly hack needed for the virtual channel fix on SN2 */ -extern int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, - int *count_vchan0, int *count_vchan1); -#endif - #ifdef QLA_64BIT_PTR #define pci_dma_hi32(a) ((a >> 16) >> 16) #else @@ -485,6 +488,14 @@ static inline void scsi_host_put(struct Scsi_Host *h) #define ia64_platform_is(foo) (!strcmp(x, platform_name)) #endif + +#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020) +#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \ + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240) +#define IS_ISP1x160(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160 || \ + ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160) + + static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *); static void qla1280_remove_one(struct pci_dev *); @@ -501,9 +512,7 @@ static int qla1280_setup(char *s) __init; /* * QLogic ISP1280 Hardware Support Function Prototypes. */ -static int qla1280_isp_firmware(struct scsi_qla_host *); -static int qla1280_chip_diag(struct scsi_qla_host *); -static int qla1280_setup_chip(struct scsi_qla_host *); +static int qla1280_load_firmware(struct scsi_qla_host *); static int qla1280_init_rings(struct scsi_qla_host *); static int qla1280_nvram_config(struct scsi_qla_host *); static int qla1280_mailbox_command(struct scsi_qla_host *, @@ -531,7 +540,7 @@ static void qla1280_error_entry(struct scsi_qla_host *, struct response *, struct list_head *); static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t); static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t); -static uint16_t qla1280_debounce_register(volatile uint16_t *); +static uint16_t qla1280_debounce_register(volatile uint16_t __iomem *); static request_t *qla1280_req_pkt(struct scsi_qla_host *); static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *, unsigned int); @@ -540,7 +549,7 @@ static void qla1280_get_target_parameters(struct scsi_qla_host *, static int qla1280_set_target_parameters(struct scsi_qla_host *, int, int); -static struct qla_driver_setup driver_setup __initdata; +static struct qla_driver_setup driver_setup; /* * convert scsi data direction to request_t control flags @@ -579,7 +588,7 @@ static void __qla1280_dump_buffer(char *, int); static char *qla1280; /* insmod qla1280 options=verbose" */ -MODULE_PARM(qla1280, "s"); +module_param(qla1280, charp, 0); #else __setup("qla1280=", qla1280_setup); #endif @@ -623,18 +632,22 @@ struct qla_boards { unsigned char *fwver; /* Ptr to F/W version array */ }; -/* NOTE: qla1280_pci_tbl and ql1280_board_tbl must be in the same order */ +/* NOTE: the last argument in each entry is used to index ql1280_board_tbl */ static struct pci_device_id qla1280_pci_tbl[] = { {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP12160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080, +#ifdef CONFIG_SCSI_QLOGIC_1280_1040 + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240, +#endif + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, - {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, {0,} }; MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl); @@ -643,6 +656,8 @@ static struct qla_boards ql1280_board_tbl[] = { /* Name , Number of ports, FW details */ {"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, + {"QLA1040", 1, &risc_code01[0], &risc_code_length01, + &risc_code_addr01, &firmware_version[0]}, {"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, {"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01, @@ -934,7 +949,7 @@ static void qla1280_error_wait_timeout(unsigned long __data) static void qla1280_mailbox_timeout(unsigned long __data) { struct scsi_qla_host *ha = (struct scsi_qla_host *)__data; - struct device_reg *reg; + struct device_reg __iomem *reg; reg = ha->iobase; ha->mailbox_out[0] = RD_REG_WORD(®->mailbox0); @@ -1345,7 +1360,7 @@ static irqreturn_t qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { struct scsi_qla_host *ha; - struct device_reg *reg; + struct device_reg __iomem *reg; u16 data; int handled = 0; @@ -1384,16 +1399,10 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) uint8_t mr; uint16_t mb[MAILBOX_REGISTER_COUNT]; struct nvram *nv; - int is1x160, status; + int status; nv = &ha->nvram; - if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) - is1x160 = 1; - else - is1x160 = 0; - mr = BIT_3 | BIT_2 | BIT_1 | BIT_0; /* Set Target Parameters. */ @@ -1403,17 +1412,16 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target) mb[2] = (nv->bus[bus].target[target].parameter.c << 8); - if (is1x160) - mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; - else - mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; - mb[3] |= nv->bus[bus].target[target].sync_period; - - if (is1x160) { + if (IS_ISP1x160(ha)) { mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; - mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; - mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; + mb[3] = (nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) | + nv->bus[bus].target[target].sync_period; + mb[6] = (nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) | + nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; mr |= BIT_6; + } else { + mb[3] = (nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) | + nv->bus[bus].target[target].sync_period; } status = qla1280_mailbox_command(ha, mr, &mb[0]); @@ -1476,8 +1484,7 @@ qla1280_slave_configure(struct scsi_device *device) (driver_setup.wide_mask && (~driver_setup.wide_mask & (1 << target)))) nv->bus[bus].target[target].parameter.f.enable_wide = 0; - if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) { + if (IS_ISP1x160(ha)) { if (driver_setup.no_ppr || (driver_setup.ppr_mask && (~driver_setup.ppr_mask & (1 << target)))) @@ -1709,7 +1716,7 @@ qla1280_return_status(struct response * sts, struct scsi_cmnd *cp) static inline void qla1280_enable_intrs(struct scsi_qla_host *ha) { - struct device_reg *reg; + struct device_reg __iomem *reg; reg = ha->iobase; /* enable risc and host interrupts */ @@ -1721,7 +1728,7 @@ qla1280_enable_intrs(struct scsi_qla_host *ha) static inline void qla1280_disable_intrs(struct scsi_qla_host *ha) { - struct device_reg *reg; + struct device_reg __iomem *reg; reg = ha->iobase; /* disable risc and host interrupts */ @@ -1743,7 +1750,7 @@ qla1280_disable_intrs(struct scsi_qla_host *ha) static int __devinit qla1280_initialize_adapter(struct scsi_qla_host *ha) { - struct device_reg *reg; + struct device_reg __iomem *reg; int status; int bus; #if LINUX_VERSION_CODE > 0x020500 @@ -1761,23 +1768,17 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) ha->flags.ints_enabled = 0; #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ia64_platform_is("sn2")) { - int count1, count2; - int c; - - count1 = 3; - count2 = 3; printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " "dual channel lockup workaround\n", ha->host_no); - if ((c = snia_pcibr_rrb_alloc(ha->pdev, &count1, &count2)) < 0) - printk(KERN_ERR "scsi(%li): Unable to allocate SN2 " - "virtual DMA channels\n", ha->host_no); - else - ha->flags.use_pci_vchannel = 1; - + ha->flags.use_pci_vchannel = 1; driver_setup.no_nvram = 1; } #endif + /* TODO: implement support for the 1040 nvram format */ + if (IS_ISP1040(ha)) + driver_setup.no_nvram = 1; + dprintk(1, "Configure PCI space for adapter...\n"); reg = ha->iobase; @@ -1802,17 +1803,8 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) */ spin_lock_irqsave(HOST_LOCK, flags); #endif - /* If firmware needs to be loaded */ - if (qla1280_isp_firmware(ha)) { - if (!(status = qla1280_chip_diag(ha))) { - status = qla1280_setup_chip(ha); - } - } else { - printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n", - ha->host_no); - status = 1; - } + status = qla1280_load_firmware(ha); if (status) { printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n", ha->host_no); @@ -1823,36 +1815,24 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha) dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no); qla1280_nvram_config(ha); - if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) { - /* Issue SCSI reset. */ - /* dg 03/13 if we can't reset twice then bus is dead */ - for (bus = 0; bus < ha->ports; bus++) { - if (!ha->bus_settings[bus].disable_scsi_reset){ - if (qla1280_bus_reset(ha, bus)) { - if (qla1280_bus_reset(ha, bus)) { - ha->bus_settings[bus].scsi_bus_dead = 1; - } - } - } - } + if (ha->flags.disable_host_adapter) { + status = 1; + goto out; + } - /* - * qla1280_bus_reset() will take care of issueing markers, - * no need to do that here as well! - */ -#if 0 - /* Issue marker command. */ - ha->flags.reset_marker = 0; - for (bus = 0; bus < ha->ports; bus++) { - ha->bus_settings[bus].reset_marker = 0; - qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL); - } -#endif + status = qla1280_init_rings(ha); + if (status) + goto out; - ha->flags.online = 1; - } else - status = 1; + /* Issue SCSI reset, if we can't reset twice then bus is dead */ + for (bus = 0; bus < ha->ports; bus++) { + if (!ha->bus_settings[bus].disable_scsi_reset && + qla1280_bus_reset(ha, bus) && + qla1280_bus_reset(ha, bus)) + ha->bus_settings[bus].scsi_bus_dead = 1; + } + ha->flags.online = 1; out: #if LINUX_VERSION_CODE >= 0x020500 spin_unlock_irqrestore(HOST_LOCK, flags); @@ -1941,17 +1921,17 @@ static int qla1280_chip_diag(struct scsi_qla_host *ha) { uint16_t mb[MAILBOX_REGISTER_COUNT]; - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; int status = 0; int cnt; uint16_t data; - dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", ®->id_l); dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no); /* Soft reset chip and wait for it to finish. */ WRT_REG_WORD(®->ictrl, ISP_RESET); + /* * We can't do a traditional PCI write flush here by reading * back the register. The card will not respond once the reset @@ -1969,145 +1949,138 @@ qla1280_chip_diag(struct scsi_qla_host *ha) data = RD_REG_WORD(®->ictrl); } - if (cnt) { - /* Reset register cleared by chip reset. */ - dprintk(3, "qla1280_chip_diag: reset register cleared by " - "chip reset\n"); + if (!cnt) + goto fail; - WRT_REG_WORD(®->cfg_1, 0); + /* Reset register cleared by chip reset. */ + dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n"); - /* Reset RISC and disable BIOS which - allows RISC to execute out of RAM. */ -#if 0 - WRT_REG_WORD(®->host_cmd, HC_RESET_RISC); - RD_REG_WORD(®->id_l); /* Flush PCI write */ - WRT_REG_WORD(®->host_cmd, HC_RELEASE_RISC); - RD_REG_WORD(®->id_l); /* Flush PCI write */ - WRT_REG_WORD(®->host_cmd, HC_DISABLE_BIOS); -#else - WRT_REG_WORD(®->host_cmd, HC_RESET_RISC | - HC_RELEASE_RISC | HC_DISABLE_BIOS); -#endif - RD_REG_WORD(®->id_l); /* Flush PCI write */ - data = qla1280_debounce_register(®->mailbox0); - /* - * I *LOVE* this code! - */ - for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) { - udelay(5); - data = RD_REG_WORD(®->mailbox0); - } + WRT_REG_WORD(®->cfg_1, 0); - if (cnt) { - /* Check product ID of chip */ - dprintk(3, "qla1280_chip_diag: Checking product " - "ID of chip\n"); - - if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || - (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && - RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || - RD_REG_WORD(®->mailbox3) != PROD_ID_3 || - RD_REG_WORD(®->mailbox4) != PROD_ID_4) { - printk(KERN_INFO "qla1280: Wrong product ID = " - "0x%x,0x%x,0x%x,0x%x\n", - RD_REG_WORD(®->mailbox1), - RD_REG_WORD(®->mailbox2), - RD_REG_WORD(®->mailbox3), - RD_REG_WORD(®->mailbox4)); - status = 1; - } else { - /* - * Enable ints early!!! - */ - qla1280_enable_intrs(ha); - - dprintk(1, "qla1280_chip_diag: Checking " - "mailboxes of chip\n"); - /* Wrap Incoming Mailboxes Test. */ - mb[0] = MBC_MAILBOX_REGISTER_TEST; - mb[1] = 0xAAAA; - mb[2] = 0x5555; - mb[3] = 0xAA55; - mb[4] = 0x55AA; - mb[5] = 0xA5A5; - mb[6] = 0x5A5A; - mb[7] = 0x2525; - if (!(status = qla1280_mailbox_command(ha, - 0xff, - &mb - [0]))) { - if (mb[1] != 0xAAAA || - mb[2] != 0x5555 || - mb[3] != 0xAA55 || - mb[4] != 0x55AA || - mb[5] != 0xA5A5 || - mb[6] != 0x5A5A || - mb[7] != 0x2525) { - status = 1; - printk(KERN_INFO "qla1280: " - "Failed mbox check\n"); - } - } - } - } else - status = 1; - } else - status = 1; + /* Reset RISC and disable BIOS which + allows RISC to execute out of RAM. */ + WRT_REG_WORD(®->host_cmd, HC_RESET_RISC | + HC_RELEASE_RISC | HC_DISABLE_BIOS); + + RD_REG_WORD(®->id_l); /* Flush PCI write */ + data = qla1280_debounce_register(®->mailbox0); + /* + * I *LOVE* this code! + */ + for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) { + udelay(5); + data = RD_REG_WORD(®->mailbox0); + } + + if (!cnt) + goto fail; + + /* Check product ID of chip */ + dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n"); + + if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || + (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && + RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || + RD_REG_WORD(®->mailbox3) != PROD_ID_3 || + RD_REG_WORD(®->mailbox4) != PROD_ID_4) { + printk(KERN_INFO "qla1280: Wrong product ID = " + "0x%x,0x%x,0x%x,0x%x\n", + RD_REG_WORD(®->mailbox1), + RD_REG_WORD(®->mailbox2), + RD_REG_WORD(®->mailbox3), + RD_REG_WORD(®->mailbox4)); + goto fail; + } + + /* + * Enable ints early!!! + */ + qla1280_enable_intrs(ha); + + dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n"); + /* Wrap Incoming Mailboxes Test. */ + mb[0] = MBC_MAILBOX_REGISTER_TEST; + mb[1] = 0xAAAA; + mb[2] = 0x5555; + mb[3] = 0xAA55; + mb[4] = 0x55AA; + mb[5] = 0xA5A5; + mb[6] = 0x5A5A; + mb[7] = 0x2525; + + status = qla1280_mailbox_command(ha, 0xff, mb); if (status) - dprintk(2, "qla1280_chip_diag: **** FAILED ****\n"); - else - dprintk(3, "qla1280_chip_diag: exiting normally\n"); + goto fail; + + if (mb[1] != 0xAAAA || mb[2] != 0x5555 || mb[3] != 0xAA55 || + mb[4] != 0x55AA || mb[5] != 0xA5A5 || mb[6] != 0x5A5A || + mb[7] != 0x2525) { + printk(KERN_INFO "qla1280: Failed mbox check\n"); + goto fail; + } + dprintk(3, "qla1280_chip_diag: exiting normally\n"); + return 0; + fail: + dprintk(2, "qla1280_chip_diag: **** FAILED ****\n"); return status; } -/* - * Setup chip - * Load and start RISC firmware. - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * 0 = success. - */ -#define DUMP_IT_BACK 0 /* for debug of RISC loading */ static int -qla1280_setup_chip(struct scsi_qla_host *ha) +qla1280_load_firmware_pio(struct scsi_qla_host *ha) { - int status = 0; - uint16_t risc_address; - uint16_t *risc_code_address; - int risc_code_size; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - uint16_t cnt; - int num, i; -#if DUMP_IT_BACK - uint8_t *sp; - uint8_t *tbuf; - dma_addr_t p_tbuf; -#endif + uint16_t risc_address, *risc_code_address, risc_code_size; + uint16_t mb[MAILBOX_REGISTER_COUNT], i; + int err; - ENTER("qla1280_setup_chip"); + /* Load RISC code. */ + risc_address = *ql1280_board_tbl[ha->devnum].fwstart; + risc_code_address = ql1280_board_tbl[ha->devnum].fwcode; + risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen; + + for (i = 0; i < risc_code_size; i++) { + mb[0] = MBC_WRITE_RAM_WORD; + mb[1] = risc_address + i; + mb[2] = risc_code_address[i]; + + err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb); + if (err) { + printk(KERN_ERR "scsi(%li): Failed to load firmware\n", + ha->host_no); + return err; + } + } - dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no); + return 0; +} +#define DUMP_IT_BACK 0 /* for debug of RISC loading */ +static int +qla1280_load_firmware_dma(struct scsi_qla_host *ha) +{ + uint16_t risc_address, *risc_code_address, risc_code_size; + uint16_t mb[MAILBOX_REGISTER_COUNT], cnt; + int err = 0, num, i; #if DUMP_IT_BACK - /* get consistent memory allocated for setup_chip */ + uint8_t *sp, *tbuf; + dma_addr_t p_tbuf; + tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf); + if (!tbuf) + return -ENOMEM; #endif /* Load RISC code. */ risc_address = *ql1280_board_tbl[ha->devnum].fwstart; risc_code_address = ql1280_board_tbl[ha->devnum].fwcode; - risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen; + risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen; - dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n", - risc_code_size); + dprintk(1, "%s: DMA RISC code (%i) words\n", + __FUNCTION__, risc_code_size); num = 0; - while (risc_code_size > 0 && !status) { + while (risc_code_size > 0) { int warn __attribute__((unused)) = 0; cnt = 2000 >> 1; @@ -2129,15 +2102,16 @@ qla1280_setup_chip(struct scsi_qla_host *ha) mb[2] = (ha->request_dma >> 16) & 0xffff; mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff; mb[6] = pci_dma_hi32(ha->request_dma) >> 16; - dprintk(2, "qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x," - "0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma, - mb[6], mb[7], mb[2], mb[3]); - if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | - BIT_2 | BIT_1 | BIT_0, - &mb[0]))) { + dprintk(2, "%s: op=%d 0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n", + __FUNCTION__, mb[0], + (void *)(long)ha->request_dma, + mb[6], mb[7], mb[2], mb[3]); + err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 | + BIT_1 | BIT_0, mb); + if (err) { printk(KERN_ERR "scsi(%li): Failed to load partial " "segment of f\n", ha->host_no); - break; + goto out; } #if DUMP_IT_BACK @@ -2149,22 +2123,22 @@ qla1280_setup_chip(struct scsi_qla_host *ha) mb[7] = pci_dma_hi32(p_tbuf) & 0xffff; mb[6] = pci_dma_hi32(p_tbuf) >> 16; - if ((status = qla1280_mailbox_command(ha, - BIT_4 | BIT_3 | BIT_2 | - BIT_1 | BIT_0, - &mb[0]))) { + err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 | + BIT_1 | BIT_0, mb); + if (err) { printk(KERN_ERR "Failed to dump partial segment of f/w\n"); - break; + goto out; } sp = (uint8_t *)ha->request_ring; for (i = 0; i < (cnt << 1); i++) { if (tbuf[i] != sp[i] && warn++ < 10) { - printk(KERN_ERR "qla1280_setup_chip: FW " - "compare error @ byte(0x%x) loop#=%x\n", - i, num); - printk(KERN_ERR "setup_chip: FWbyte=%x " - "FWfromChip=%x\n", sp[i], tbuf[i]); + printk(KERN_ERR "%s: FW compare error @ " + "byte(0x%x) loop#=%x\n", + __FUNCTION__, i, num); + printk(KERN_ERR "%s: FWbyte=%x " + "FWfromChip=%x\n", + __FUNCTION__, sp[i], tbuf[i]); /*break; */ } } @@ -2175,37 +2149,69 @@ qla1280_setup_chip(struct scsi_qla_host *ha) num++; } + out: +#if DUMP_IT_BACK + pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); +#endif + return err; +} + +static int +qla1280_start_firmware(struct scsi_qla_host *ha) +{ + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int err; + + dprintk(1, "%s: Verifying checksum of loaded RISC code.\n", + __FUNCTION__); + /* Verify checksum of loaded RISC code. */ - if (!status) { - dprintk(1, "qla1280_setup_chip: Verifying checksum of " - "loaded RISC code.\n"); - mb[0] = MBC_VERIFY_CHECKSUM; - /* mb[1] = ql12_risc_code_addr01; */ - mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + mb[0] = MBC_VERIFY_CHECKSUM; + /* mb[1] = ql12_risc_code_addr01; */ + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); + if (err) { + printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no); + return err; + } - if (!(status = - qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) { - /* Start firmware execution. */ - dprintk(1, - "qla1280_setup_chip: start firmware running.\n"); - mb[0] = MBC_EXECUTE_FIRMWARE; - mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; - qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); - } else - printk(KERN_ERR "scsi(%li): qla1280_setup_chip: " - "Failed checksum\n", ha->host_no); + /* Start firmware execution. */ + dprintk(1, "%s: start firmware running.\n", __FUNCTION__); + mb[0] = MBC_EXECUTE_FIRMWARE; + mb[1] = *ql1280_board_tbl[ha->devnum].fwstart; + err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + if (err) { + printk(KERN_ERR "scsi(%li): Failed to start firmware\n", + ha->host_no); } -#if DUMP_IT_BACK - /* free consistent memory allocated for setup_chip */ - pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf); -#endif + return err; +} - if (status) - dprintk(2, "qla1280_setup_chip: **** FAILED ****\n"); +static int +qla1280_load_firmware(struct scsi_qla_host *ha) +{ + int err = -ENODEV; - LEAVE("qla1280_setup_chip"); - return status; + /* If firmware needs to be loaded */ + if (!qla1280_isp_firmware(ha)) { + printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n", + ha->host_no); + goto out; + } + + err = qla1280_chip_diag(ha); + if (err) + goto out; + if (IS_ISP1040(ha)) + err = qla1280_load_firmware_pio(ha); + else + err = qla1280_load_firmware_dma(ha); + if (err) + goto out; + err = qla1280_start_firmware(ha); + out: + return err; } /* @@ -2271,123 +2277,9 @@ qla1280_init_rings(struct scsi_qla_host *ha) return status; } -/* - * NVRAM configuration. - * - * Input: - * ha = adapter block pointer. - * ha->request_ring = request ring virtual address - * - * Output: - * host adapters parameters in host adapter block - * - * Returns: - * 0 = success. - */ -static int -qla1280_nvram_config(struct scsi_qla_host *ha) +static void +qla1280_print_settings(struct nvram *nv) { - struct device_reg *reg = ha->iobase; - struct nvram *nv; - int is1x160, status = 0; - int bus, target, lun; - uint16_t mb[MAILBOX_REGISTER_COUNT]; - uint16_t mask; - - ENTER("qla1280_nvram_config"); - - if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 || - ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) - is1x160 = 1; - else - is1x160 = 0; - - nv = &ha->nvram; - if (!ha->nvram_valid) { - dprintk(1, "Using defaults for NVRAM: \n"); - memset(nv, 0, sizeof(struct nvram)); - - /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ - nv->firmware_feature.f.enable_fast_posting = 1; - nv->firmware_feature.f.disable_synchronous_backoff = 1; - - nv->termination.f.scsi_bus_0_control = 3; - nv->termination.f.scsi_bus_1_control = 3; - nv->termination.f.auto_term_support = 1; - - /* - * Set default FIFO magic - What appropriate values - * would be here is unknown. This is what I have found - * testing with 12160s. - * Now, I would love the magic decoder ring for this one, - * the header file provided by QLogic seems to be bogus - * or incomplete at best. - */ - nv->isp_config.c = 0x44; - - if (is1x160) - nv->isp_parameter = 0x01; - - for (bus = 0; bus < MAX_BUSES; bus++) { - nv->bus[bus].config_1.initiator_id = 7; - nv->bus[bus].bus_reset_delay = 5; - /* 8 = 5.0 clocks */ - nv->bus[bus].config_2.async_data_setup_time = 8; - nv->bus[bus].config_2.req_ack_active_negation = 1; - nv->bus[bus].config_2.data_line_active_negation = 1; - nv->bus[bus].selection_timeout = 250; - nv->bus[bus].max_queue_depth = 256; - - for (target = 0; target < MAX_TARGETS; target++) { - nv->bus[bus].target[target].parameter.f. - renegotiate_on_error = 1; - nv->bus[bus].target[target].parameter.f. - auto_request_sense = 1; - nv->bus[bus].target[target].parameter.f. - tag_queuing = 1; - nv->bus[bus].target[target].parameter.f. - enable_sync = 1; -#if 1 /* Some SCSI Processors do not seem to like this */ - nv->bus[bus].target[target].parameter.f. - enable_wide = 1; -#endif - nv->bus[bus].target[target].parameter.f. - parity_checking = 1; - nv->bus[bus].target[target].parameter.f. - disconnect_allowed = 1; - nv->bus[bus].target[target].execution_throttle= - nv->bus[bus].max_queue_depth - 1; - if (is1x160) { - nv->bus[bus].target[target].flags. - flags1x160.device_enable = 1; - nv->bus[bus].target[target].flags. - flags1x160.sync_offset = 0x0e; - nv->bus[bus].target[target]. - sync_period = 9; - nv->bus[bus].target[target]. - ppr_1x160.flags.enable_ppr = 1; - nv->bus[bus].target[target].ppr_1x160. - flags.ppr_options = 2; - nv->bus[bus].target[target].ppr_1x160. - flags.ppr_bus_width = 1; - } else { - nv->bus[bus].target[target].flags. - flags1x80.device_enable = 1; - nv->bus[bus].target[target].flags. - flags1x80.sync_offset = 0x8; - nv->bus[bus].target[target]. - sync_period = 10; - } - } - } - } else { - /* Always force AUTO sense for LINUX SCSI */ - for (bus = 0; bus < MAX_BUSES; bus++) - for (target = 0; target < MAX_TARGETS; target++) { - nv->bus[bus].target[target].parameter.f. - auto_request_sense = 1; - } - } dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n", nv->bus[0].config_1.initiator_id); dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n", @@ -2433,36 +2325,262 @@ qla1280_nvram_config(struct scsi_qla_host *ha) nv->bus[0].max_queue_depth); dprintk(1, "qla1280 : max queue depth[1]=%d\n", nv->bus[1].max_queue_depth); +} + +static void +qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target) +{ + struct nvram *nv = &ha->nvram; + + nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1; + nv->bus[bus].target[target].parameter.f.auto_request_sense = 1; + nv->bus[bus].target[target].parameter.f.tag_queuing = 1; + nv->bus[bus].target[target].parameter.f.enable_sync = 1; +#if 1 /* Some SCSI Processors do not seem to like this */ + nv->bus[bus].target[target].parameter.f.enable_wide = 1; +#endif + nv->bus[bus].target[target].parameter.f.parity_checking = 1; + nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1; + nv->bus[bus].target[target].execution_throttle = + nv->bus[bus].max_queue_depth - 1; + + if (IS_ISP1x160(ha)) { + nv->bus[bus].target[target].flags.flags1x160.device_enable = 1; + nv->bus[bus].target[target].flags.flags1x160.sync_offset = 0x0e; + nv->bus[bus].target[target].sync_period = 9; + nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1; + nv->bus[bus].target[target].ppr_1x160.flags.ppr_options = 2; + nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width = 1; + } else { + nv->bus[bus].target[target].flags.flags1x80.device_enable = 1; + nv->bus[bus].target[target].flags.flags1x80.sync_offset = 12; + nv->bus[bus].target[target].sync_period = 10; + } +} + +static void +qla1280_set_defaults(struct scsi_qla_host *ha) +{ + struct nvram *nv = &ha->nvram; + int bus, target; + + dprintk(1, "Using defaults for NVRAM: \n"); + memset(nv, 0, sizeof(struct nvram)); + + /* nv->cntr_flags_1.disable_loading_risc_code = 1; */ + nv->firmware_feature.f.enable_fast_posting = 1; + nv->firmware_feature.f.disable_synchronous_backoff = 1; + nv->termination.f.scsi_bus_0_control = 3; + nv->termination.f.scsi_bus_1_control = 3; + nv->termination.f.auto_term_support = 1; + + /* + * Set default FIFO magic - What appropriate values would be here + * is unknown. This is what I have found testing with 12160s. + * + * Now, I would love the magic decoder ring for this one, the + * header file provided by QLogic seems to be bogus or incomplete + * at best. + */ + nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128; + if (IS_ISP1x160(ha)) + nv->isp_parameter = 0x01; /* fast memory enable */ + + for (bus = 0; bus < MAX_BUSES; bus++) { + nv->bus[bus].config_1.initiator_id = 7; + nv->bus[bus].config_2.req_ack_active_negation = 1; + nv->bus[bus].config_2.data_line_active_negation = 1; + nv->bus[bus].selection_timeout = 250; + nv->bus[bus].max_queue_depth = 256; + + if (IS_ISP1040(ha)) { + nv->bus[bus].bus_reset_delay = 3; + nv->bus[bus].config_2.async_data_setup_time = 6; + nv->bus[bus].retry_delay = 1; + } else { + nv->bus[bus].bus_reset_delay = 5; + nv->bus[bus].config_2.async_data_setup_time = 8; + } + + for (target = 0; target < MAX_TARGETS; target++) + qla1280_set_target_defaults(ha, bus, target); + } +} + +static int +qla1280_config_target(struct scsi_qla_host *ha, int bus, int target) +{ + struct nvram *nv = &ha->nvram; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int status, lun; + + /* Set Target Parameters. */ + mb[0] = MBC_SET_TARGET_PARAMETERS; + mb[1] = (uint16_t) (bus ? target | BIT_7 : target); + mb[1] <<= 8; + + /* + * Do not enable wide, sync, and ppr for the initial + * INQUIRY run. We enable this later if we determine + * the target actually supports it. + */ + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + nv->bus[bus].target[target].parameter.f. + stop_queue_on_check = 0; + + if (IS_ISP1x160(ha)) + nv->bus[bus].target[target].ppr_1x160. + flags.enable_ppr = 0; + + /* + * No sync, wide, etc. while probing + */ + mb[2] = (nv->bus[bus].target[target].parameter.c << 8) & + ~(TP_SYNC /*| TP_WIDE | TP_PPR*/); + + if (IS_ISP1x160(ha)) + mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; + else + mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; + mb[3] |= nv->bus[bus].target[target].sync_period; + + status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]); + + /* Save Tag queuing enable flag. */ + mb[0] = BIT_0 << target; + if (nv->bus[bus].target[target].parameter.f.tag_queuing) + ha->bus_settings[bus].qtag_enables |= mb[0]; + + /* Save Device enable flag. */ + if (IS_ISP1x160(ha)) { + if (nv->bus[bus].target[target].flags.flags1x160.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + ha->bus_settings[bus].lun_disables |= 0; + } else { + if (nv->bus[bus].target[target].flags.flags1x80.device_enable) + ha->bus_settings[bus].device_enables |= mb[0]; + /* Save LUN disable flag. */ + if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) + ha->bus_settings[bus].lun_disables |= mb[0]; + } + + /* Set Device Queue Parameters. */ + for (lun = 0; lun < MAX_LUNS; lun++) { + mb[0] = MBC_SET_DEVICE_QUEUE; + mb[1] = (uint16_t)(bus ? target | BIT_7 : target); + mb[1] = mb[1] << 8 | lun; + mb[2] = nv->bus[bus].max_queue_depth; + mb[3] = nv->bus[bus].target[target].execution_throttle; + status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]); + } + + return status; +} + +static int +qla1280_config_bus(struct scsi_qla_host *ha, int bus) +{ + struct nvram *nv = &ha->nvram; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + int target, status; + + /* SCSI Reset Disable. */ + ha->bus_settings[bus].disable_scsi_reset = + nv->bus[bus].config_1.scsi_reset_disable; + + /* Initiator ID. */ + ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id; + mb[0] = MBC_SET_INITIATOR_ID; + mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 : + ha->bus_settings[bus].id; + status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + + /* Reset Delay. */ + ha->bus_settings[bus].bus_reset_delay = + nv->bus[bus].bus_reset_delay; + + /* Command queue depth per device. */ + ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1; + + /* Set target parameters. */ + for (target = 0; target < MAX_TARGETS; target++) + status |= qla1280_config_target(ha, bus, target); + + return status; +} + +static int +qla1280_nvram_config(struct scsi_qla_host *ha) +{ + struct device_reg __iomem *reg = ha->iobase; + struct nvram *nv = &ha->nvram; + int bus, target, status = 0; + uint16_t mb[MAILBOX_REGISTER_COUNT]; + uint16_t mask; + + ENTER("qla1280_nvram_config"); + + if (ha->nvram_valid) { + /* Always force AUTO sense for LINUX SCSI */ + for (bus = 0; bus < MAX_BUSES; bus++) + for (target = 0; target < MAX_TARGETS; target++) { + nv->bus[bus].target[target].parameter.f. + auto_request_sense = 1; + } + } else { + qla1280_set_defaults(ha); + } + + qla1280_print_settings(nv); /* Disable RISC load of firmware. */ ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code; - /* Set ISP hardware DMA burst */ - mb[0] = nv->isp_config.c; - /* Enable DMA arbitration on dual channel controllers */ - if (ha->ports > 1) - mb[0] |= BIT_13; - WRT_REG_WORD(®->cfg_1, mb[0]); - -#if 1 /* Is this safe? */ - /* Set SCSI termination. */ - WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); - mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); - WRT_REG_WORD(®->gpio_data, mb[0]); -#endif + if (IS_ISP1040(ha)) { + uint16_t hwrev, cfg1, cdma_conf, ddma_conf; + + hwrev = RD_REG_WORD(®->cfg_0) & ISP_CFG0_HWMSK; + + cfg1 = RD_REG_WORD(®->cfg_1); + cdma_conf = RD_REG_WORD(®->cdma_cfg); + ddma_conf = RD_REG_WORD(®->ddma_cfg); + + /* Busted fifo, says mjacob. */ + if (hwrev == ISP_CFG0_1040A) + WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64); + else + WRT_REG_WORD(®->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB); + + WRT_REG_WORD(®->cdma_cfg, cdma_conf | CDMA_CONF_BENAB); + WRT_REG_WORD(®->ddma_cfg, cdma_conf | DDMA_CONF_BENAB); + } else { + /* Set ISP hardware DMA burst */ + mb[0] = nv->isp_config.c; + /* Enable DMA arbitration on dual channel controllers */ + if (ha->ports > 1) + mb[0] |= BIT_13; + WRT_REG_WORD(®->cfg_1, mb[0]); + + /* Set SCSI termination. */ + WRT_REG_WORD(®->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0)); + mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0); + WRT_REG_WORD(®->gpio_data, mb[0]); + } /* ISP parameter word. */ mb[0] = MBC_SET_SYSTEM_PARAMETER; mb[1] = nv->isp_parameter; status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); -#if 0 - /* clock rate - for qla1240 and older, only */ - mb[0] = MBC_SET_CLOCK_RATE; - mb[1] = 0x50; - status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); -#endif + if (IS_ISP1x40(ha)) { + /* clock rate - for qla1240 and older, only */ + mb[0] = MBC_SET_CLOCK_RATE; + mb[1] = 40; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb); + } + /* Firmware feature word. */ mb[0] = MBC_SET_FIRMWARE_FEATURES; mask = BIT_5 | BIT_1 | BIT_0; @@ -2515,112 +2633,18 @@ qla1280_nvram_config(struct scsi_qla_host *ha) mb[2] = 2; /* Command DMA Channel Burst Enable */ status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); + mb[0] = MBC_SET_TAG_AGE_LIMIT; + mb[1] = 8; + status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); + /* Selection timeout. */ mb[0] = MBC_SET_SELECTION_TIMEOUT; mb[1] = nv->bus[0].selection_timeout; mb[2] = nv->bus[1].selection_timeout; status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]); - for (bus = 0; bus < ha->ports; bus++) { - /* SCSI Reset Disable. */ - ha->bus_settings[bus].disable_scsi_reset = - nv->bus[bus].config_1.scsi_reset_disable; - - /* Initiator ID. */ - ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id; - mb[0] = MBC_SET_INITIATOR_ID; - mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 : - ha->bus_settings[bus].id; - status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]); - - /* Reset Delay. */ - ha->bus_settings[bus].bus_reset_delay = - nv->bus[bus].bus_reset_delay; - - /* Command queue depth per device. */ - ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1; - - /* Set target parameters. */ - for (target = 0; target < MAX_TARGETS; target++) { - uint8_t mr = BIT_2 | BIT_1 | BIT_0; - - /* Set Target Parameters. */ - mb[0] = MBC_SET_TARGET_PARAMETERS; - mb[1] = (uint16_t) (bus ? target | BIT_7 : target); - mb[1] <<= 8; - /* - * Do not enable wide, sync, and ppr for the initial - * INQUIRY run. We enable this later if we determine - * the target actually supports it. - */ - nv->bus[bus].target[target].parameter.f. - auto_request_sense = 1; - nv->bus[bus].target[target].parameter.f. - stop_queue_on_check = 0; - - if (is1x160) - nv->bus[bus].target[target].ppr_1x160. - flags.enable_ppr = 0; - /* - * No sync, wide, etc. while probing - */ - mb[2] = (nv->bus[bus].target[target].parameter.c << 8)& - ~(TP_SYNC /*| TP_WIDE | TP_PPR*/); - - if (is1x160) - mb[3] = nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8; - else - mb[3] = nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8; - mb[3] |= nv->bus[bus].target[target].sync_period; - mr |= BIT_3; - - /* - * We don't want to enable ppr etc. before we have - * determined that the target actually supports it - */ -#if 0 - if (is1x160) { - mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5; - - mb[6] = nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8; - mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width; - mr |= BIT_6; - } -#endif - - status = qla1280_mailbox_command(ha, mr, &mb[0]); - - /* Save Tag queuing enable flag. */ - mb[0] = BIT_0 << target; - if (nv->bus[bus].target[target].parameter.f.tag_queuing) - ha->bus_settings[bus].qtag_enables |= mb[0]; - - /* Save Device enable flag. */ - if (is1x160) { - if (nv->bus[bus].target[target].flags.flags1x160.device_enable) - ha->bus_settings[bus].device_enables |= mb[0]; - ha->bus_settings[bus].lun_disables |= 0; - } else { - if (nv->bus[bus].target[target].flags.flags1x80.device_enable) - ha->bus_settings[bus].device_enables |= mb[0]; - /* Save LUN disable flag. */ - if (nv->bus[bus].target[target].flags.flags1x80.lun_disable) - ha->bus_settings[bus].lun_disables |= mb[0]; - } - - - /* Set Device Queue Parameters. */ - for (lun = 0; lun < MAX_LUNS; lun++) { - mb[0] = MBC_SET_DEVICE_QUEUE; - mb[1] = (uint16_t)(bus ? target | BIT_7 : target); - mb[1] = mb[1] << 8 | lun; - mb[2] = nv->bus[bus].max_queue_depth; - mb[3] = nv->bus[bus].target[target].execution_throttle; - status |= qla1280_mailbox_command(ha, 0x0f, - &mb[0]); - } - } - } + for (bus = 0; bus < ha->ports; bus++) + status |= qla1280_config_bus(ha, bus); if (status) dprintk(2, "qla1280_nvram_config: **** FAILED ****\n"); @@ -2675,7 +2699,7 @@ qla1280_get_nvram_word(struct scsi_qla_host *ha, uint32_t address) static uint16_t qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; int cnt; uint16_t data = 0; uint16_t reg_data; @@ -2718,7 +2742,7 @@ qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd) static void qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; WRT_REG_WORD(®->nvram, data | NV_SELECT); RD_REG_WORD(®->id_l); /* Flush PCI write */ @@ -2749,13 +2773,14 @@ qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data) static int qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; #if 0 LIST_HEAD(done_q); #endif int status = 0; int cnt; uint16_t *optr, *iptr; + uint16_t __iomem *mptr; uint16_t data; DECLARE_COMPLETION(wait); struct timer_list timer; @@ -2772,15 +2797,15 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) * available before starting sending the command data */ /* Load mailbox registers. */ - optr = (uint16_t *) ®->mailbox0; + mptr = (uint16_t __iomem *) ®->mailbox0; iptr = mb; for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) { if (mr & BIT_0) { - WRT_REG_WORD(optr, (*iptr)); + WRT_REG_WORD(mptr, (*iptr)); } mr >>= 1; - optr++; + mptr++; iptr++; } @@ -2856,7 +2881,7 @@ qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t *mb) static void qla1280_poll(struct scsi_qla_host *ha) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; uint16_t data; LIST_HEAD(done_q); @@ -3059,7 +3084,7 @@ qla1280_abort_command(struct scsi_qla_host *ha, struct srb * sp, int handle) static void qla1280_reset_adapter(struct scsi_qla_host *ha) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; ENTER("qla1280_reset_adapter"); @@ -3123,7 +3148,7 @@ qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type) static int qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; cmd_a64_entry_t *pkt; struct scatterlist *sg = NULL; @@ -3246,7 +3271,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) dma_handle = sg_dma_address(sg); #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) - sn_pci_set_vchan(ha->pdev, &dma_handle, + sn_pci_set_vchan(ha->pdev, + (unsigned long *)&dma_handle, SCSI_BUS_32(cmd)); #endif *dword_ptr++ = @@ -3304,7 +3330,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) dma_handle = sg_dma_address(sg); #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) - sn_pci_set_vchan(ha->pdev, &dma_handle, + sn_pci_set_vchan(ha->pdev, + (unsigned long *)&dma_handle, SCSI_BUS_32(cmd)); #endif *dword_ptr++ = @@ -3338,7 +3365,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) sp->saved_dma_handle = dma_handle; #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ha->flags.use_pci_vchannel) - sn_pci_set_vchan(ha->pdev, &dma_handle, + sn_pci_set_vchan(ha->pdev, + (unsigned long *)&dma_handle, SCSI_BUS_32(cmd)); #endif *dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle)); @@ -3406,7 +3434,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) static int qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; struct scsi_cmnd *cmd = sp->cmd; struct cmd_entry *pkt; struct scatterlist *sg = NULL; @@ -3666,7 +3694,7 @@ out: static request_t * qla1280_req_pkt(struct scsi_qla_host *ha) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; request_t *pkt = NULL; int cnt; uint32_t timer; @@ -3734,7 +3762,7 @@ qla1280_req_pkt(struct scsi_qla_host *ha) static void qla1280_isp_cmd(struct scsi_qla_host *ha) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; ENTER("qla1280_isp_cmd"); @@ -3772,7 +3800,7 @@ qla1280_isp_cmd(struct scsi_qla_host *ha) static void qla1280_isr(struct scsi_qla_host *ha, struct list_head *done_q) { - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; struct response *pkt; struct srb *sp = NULL; uint16_t mailbox[MAILBOX_REGISTER_COUNT]; @@ -4231,6 +4259,7 @@ qla1280_error_entry(struct scsi_qla_host *ha, struct response *pkt, static int qla1280_abort_isp(struct scsi_qla_host *ha) { + struct device_reg __iomem *reg = ha->iobase; struct srb *sp; int status = 0; int cnt; @@ -4238,69 +4267,53 @@ qla1280_abort_isp(struct scsi_qla_host *ha) ENTER("qla1280_abort_isp"); - if (!ha->flags.abort_isp_active && ha->flags.online) { - struct device_reg *reg = ha->iobase; - ha->flags.abort_isp_active = 1; - - /* Disable ISP interrupts. */ - qla1280_disable_intrs(ha); - WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); - RD_REG_WORD(®->id_l); + if (ha->flags.abort_isp_active || !ha->flags.online) + goto out; + + ha->flags.abort_isp_active = 1; - printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n", - ha->host_no); - /* Dequeue all commands in outstanding command list. */ - for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { - struct scsi_cmnd *cmd; - sp = ha->outstanding_cmds[cnt]; - if (sp) { + /* Disable ISP interrupts. */ + qla1280_disable_intrs(ha); + WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); + RD_REG_WORD(®->id_l); - cmd = sp->cmd; - CMD_RESULT(cmd) = DID_RESET << 16; + printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n", + ha->host_no); + /* Dequeue all commands in outstanding command list. */ + for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + struct scsi_cmnd *cmd; + sp = ha->outstanding_cmds[cnt]; + if (sp) { - sp->cmd = NULL; - ha->outstanding_cmds[cnt] = NULL; + cmd = sp->cmd; + CMD_RESULT(cmd) = DID_RESET << 16; - (*cmd->scsi_done)(cmd); + sp->cmd = NULL; + ha->outstanding_cmds[cnt] = NULL; - sp->flags = 0; - } - } + (*cmd->scsi_done)(cmd); - /* If firmware needs to be loaded */ - if (qla1280_isp_firmware (ha)) { - if (!(status = qla1280_chip_diag(ha))) - status = qla1280_setup_chip(ha); + sp->flags = 0; } + } - if (!status) { - /* Setup adapter based on NVRAM parameters. */ - qla1280_nvram_config (ha); + status = qla1280_load_firmware(ha); + if (status) + goto out; - if (!(status = qla1280_init_rings(ha))) { - /* Issue SCSI reset. */ - for (bus = 0; bus < ha->ports; bus++) { - qla1280_bus_reset(ha, bus); - } - /* - * qla1280_bus_reset() will do the marker - * dance - no reason to repeat here! - */ -#if 0 - /* Issue marker command. */ - ha->flags.reset_marker = 0; - for (bus = 0; bus < ha->ports; bus++) { - ha->bus_settings[bus]. - reset_marker = 0; - qla1280_marker(ha, bus, 0, 0, - MK_SYNC_ALL); - } -#endif - ha->flags.abort_isp_active = 0; - } - } - } + /* Setup adapter based on NVRAM parameters. */ + qla1280_nvram_config (ha); + status = qla1280_init_rings(ha); + if (status) + goto out; + + /* Issue SCSI reset. */ + for (bus = 0; bus < ha->ports; bus++) + qla1280_bus_reset(ha, bus); + + ha->flags.abort_isp_active = 0; + out: if (status) { printk(KERN_WARNING "qla1280: ISP error recovery failed, board disabled"); @@ -4324,7 +4337,7 @@ qla1280_abort_isp(struct scsi_qla_host *ha) * register value. */ static u16 -qla1280_debounce_register(volatile u16 * addr) +qla1280_debounce_register(volatile u16 __iomem * addr) { volatile u16 ret; volatile u16 ret2; @@ -4356,7 +4369,7 @@ static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus) { uint16_t config_reg, scsi_control; - struct device_reg *reg = ha->iobase; + struct device_reg __iomem *reg = ha->iobase; if (ha->bus_settings[bus].scsi_bus_dead) { WRT_REG_WORD(®->host_cmd, HC_PAUSE_RISC); @@ -4630,6 +4643,7 @@ qla1280_get_token(char *str) #if LINUX_VERSION_CODE >= 0x020600 static struct scsi_host_template qla1280_driver_template = { + .module = THIS_MODULE, .proc_name = "qla1280", .name = "Qlogic ISP 1280/12160", .info = qla1280_info, @@ -4774,7 +4788,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } host->base = (unsigned long)ha->mmpbase; - ha->iobase = (struct device_reg *)ha->mmpbase; + ha->iobase = (struct device_reg __iomem *)ha->mmpbase; #else host->io_port = pci_resource_start(ha->pdev, 0); if (!request_region(host->io_port, 0xff, "qla1280")) { @@ -4936,6 +4950,7 @@ module_exit(qla1280_exit); MODULE_AUTHOR("Qlogic & Jes Sorensen"); MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA1280_VERSION); /* * Overrides for Emacs so that we almost follow Linus's tabbing style. diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h index 0027485bf..d245ae075 100644 --- a/drivers/scsi/qla1280.h +++ b/drivers/scsi/qla1280.h @@ -62,6 +62,7 @@ #define WRT_REG_WORD(addr, data) writew(data, addr) #else /* MEMORY_MAPPED_IO */ #define RD_REG_WORD(addr) inw((unsigned long)addr) +#define RD_REG_WORD_dmasync(addr) RD_REG_WORD(addr) #define WRT_REG_WORD(addr, data) outw(data, (unsigned long)addr) #endif /* MEMORY_MAPPED_IO */ @@ -126,7 +127,20 @@ struct device_reg { uint16_t id_l; /* ID low */ uint16_t id_h; /* ID high */ uint16_t cfg_0; /* Configuration 0 */ +#define ISP_CFG0_HWMSK 0x000f /* Hardware revision mask */ +#define ISP_CFG0_1020 BIT_0 /* ISP1020 */ +#define ISP_CFG0_1020A BIT_1 /* ISP1020A */ +#define ISP_CFG0_1040 BIT_2 /* ISP1040 */ +#define ISP_CFG0_1040A BIT_3 /* ISP1040A */ +#define ISP_CFG0_1040B BIT_4 /* ISP1040B */ +#define ISP_CFG0_1040C BIT_5 /* ISP1040C */ uint16_t cfg_1; /* Configuration 1 */ +#define ISP_CFG1_F128 BIT_6 /* 128-byte FIFO threshold */ +#define ISP_CFG1_F64 BIT_4|BIT_5 /* 128-byte FIFO threshold */ +#define ISP_CFG1_F32 BIT_5 /* 128-byte FIFO threshold */ +#define ISP_CFG1_F16 BIT_4 /* 128-byte FIFO threshold */ +#define ISP_CFG1_BENAB BIT_2 /* Global Bus burst enable */ +#define ISP_CFG1_SXP BIT_0 /* SXP register select */ uint16_t ictrl; /* Interface control */ #define ISP_RESET BIT_0 /* ISP soft reset */ #define ISP_EN_INT BIT_1 /* ISP enable interrupts. */ @@ -147,7 +161,42 @@ struct device_reg { uint16_t flash_data; /* Flash BIOS data */ uint16_t flash_address; /* Flash BIOS address */ - uint16_t unused_1[0x2e]; /* 0x14-0x6f Gap */ + uint16_t unused_1[0x06]; + + /* cdma_* and ddma_* are 1040 only */ + uint16_t cdma_cfg; +#define CDMA_CONF_SENAB BIT_3 /* SXP to DMA Data enable */ +#define CDMA_CONF_RIRQ BIT_2 /* RISC interrupt enable */ +#define CDMA_CONF_BENAB BIT_1 /* Bus burst enable */ +#define CDMA_CONF_DIR BIT_0 /* DMA direction (0=fifo->host 1=host->fifo) */ + uint16_t cdma_ctrl; + uint16_t cdma_status; + uint16_t cdma_fifo_status; + uint16_t cdma_count; + uint16_t cdma_reserved; + uint16_t cdma_address_count_0; + uint16_t cdma_address_count_1; + uint16_t cdma_address_count_2; + uint16_t cdma_address_count_3; + + uint16_t unused_2[0x06]; + + uint16_t ddma_cfg; +#define DDMA_CONF_SENAB BIT_3 /* SXP to DMA Data enable */ +#define DDMA_CONF_RIRQ BIT_2 /* RISC interrupt enable */ +#define DDMA_CONF_BENAB BIT_1 /* Bus burst enable */ +#define DDMA_CONF_DIR BIT_0 /* DMA direction (0=fifo->host 1=host->fifo) */ + uint16_t ddma_ctrl; + uint16_t ddma_status; + uint16_t ddma_fifo_status; + uint16_t ddma_xfer_count_low; + uint16_t ddma_xfer_count_high; + uint16_t ddma_addr_count_0; + uint16_t ddma_addr_count_1; + uint16_t ddma_addr_count_2; + uint16_t ddma_addr_count_3; + + uint16_t unused_3[0x0e]; uint16_t mailbox0; /* Mailbox 0 */ uint16_t mailbox1; /* Mailbox 1 */ @@ -158,18 +207,18 @@ struct device_reg { uint16_t mailbox6; /* Mailbox 6 */ uint16_t mailbox7; /* Mailbox 7 */ - uint16_t unused_2[0x20];/* 0x80-0xbf Gap */ + uint16_t unused_4[0x20];/* 0x80-0xbf Gap */ uint16_t host_cmd; /* Host command and control */ #define HOST_INT BIT_7 /* host interrupt bit */ #define BIOS_ENABLE BIT_0 - uint16_t unused_6[0x5]; /* 0xc2-0xcb Gap */ + uint16_t unused_5[0x5]; /* 0xc2-0xcb Gap */ uint16_t gpio_data; uint16_t gpio_enable; - uint16_t unused_7[0x11]; /* d0-f0 */ + uint16_t unused_6[0x11]; /* d0-f0 */ uint16_t scsiControlPins; /* f2 */ }; @@ -989,9 +1038,9 @@ struct scsi_qla_host { /* Linux adapter configuration data */ struct Scsi_Host *host; /* pointer to host data */ struct scsi_qla_host *next; - struct device_reg *iobase; /* Base Memory-mapped I/O address */ + struct device_reg __iomem *iobase; /* Base Memory-mapped I/O address */ - unsigned char *mmpbase; /* memory mapped address */ + unsigned char __iomem *mmpbase; /* memory mapped address */ unsigned long host_no; struct pci_dev *pdev; uint8_t devnum; diff --git a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c index 77de0f4f9..ea136a61a 100644 --- a/drivers/scsi/qla2xxx/ql2100.c +++ b/drivers/scsi/qla2xxx/ql2100.c @@ -89,3 +89,4 @@ module_exit(qla2100_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c index c254daaa0..2f5698d52 100644 --- a/drivers/scsi/qla2xxx/ql2200.c +++ b/drivers/scsi/qla2xxx/ql2200.c @@ -89,3 +89,4 @@ module_exit(qla2200_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c index 177aa3617..1f6fc895c 100644 --- a/drivers/scsi/qla2xxx/ql2300.c +++ b/drivers/scsi/qla2xxx/ql2300.c @@ -100,3 +100,4 @@ module_exit(qla2300_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP2300 FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2300_fw.c b/drivers/scsi/qla2xxx/ql2300_fw.c index 9563c67cf..2486c1c18 100644 --- a/drivers/scsi/qla2xxx/ql2300_fw.c +++ b/drivers/scsi/qla2xxx/ql2300_fw.c @@ -18,25 +18,25 @@ *************************************************************************/ /* - * Firmware Version 3.02.30 (07:51 Jun 16, 2004) + * Firmware Version 3.03.02 (16:50 Aug 10, 2004) */ #ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_version = 3*1024+2; +unsigned short fw2300ipx_version = 3*1024+3; #else -unsigned short risc_code_version = 3*1024+2; +unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2300ipx_version_str[] = {3, 2,30}; +unsigned char fw2300ipx_version_str[] = {3, 3, 2}; #else -unsigned char firmware_version[] = {3, 2,30}; +unsigned char firmware_version[] = {3, 3, 2}; #endif #ifdef UNIQUE_FW_NAME -#define fw2300ipx_VERSION_STRING "3.02.30" +#define fw2300ipx_VERSION_STRING "3.03.02" #else -#define FW_VERSION_STRING "3.02.30" +#define FW_VERSION_STRING "3.03.02" #endif #ifdef UNIQUE_FW_NAME @@ -50,12 +50,12 @@ unsigned short fw2300ipx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xe9e8, 0x0000, 0x0003, 0x0002, 0x001e, + 0x0470, 0x0000, 0x0000, 0xea02, 0x0000, 0x0003, 0x0003, 0x0002, 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3032, 0x2e33, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x332e, 0x3033, 0x2e30, 0x3220, 0x2020, 0x2020, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, @@ -64,7 +64,7 @@ unsigned short risc_code01[] = { 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1bff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2d2b, 0x2051, 0x1800, 0x2a70, 0x20e1, + 0x7883, 0x0004, 0x2089, 0x2d36, 0x2051, 0x1800, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e51, 0x2029, 0x4d00, 0x2031, 0xffff, 0x2039, 0x4cd0, 0x2021, 0x0200, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, @@ -78,161 +78,161 @@ unsigned short risc_code01[] = { 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x0f17, 0x080c, - 0x6031, 0x080c, 0xae07, 0x080c, 0x10ce, 0x080c, 0x12ed, 0x080c, - 0x1ba6, 0x080c, 0x0d69, 0x080c, 0x1053, 0x080c, 0x3427, 0x080c, - 0x76a1, 0x080c, 0x699f, 0x080c, 0x86df, 0x080c, 0x8413, 0x080c, - 0x247a, 0x080c, 0x8f81, 0x080c, 0x7d6b, 0x080c, 0x22b3, 0x080c, - 0x23e7, 0x080c, 0x246f, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, + 0x603b, 0x080c, 0xadf5, 0x080c, 0x10ce, 0x080c, 0x12ed, 0x080c, + 0x1bb1, 0x080c, 0x0d69, 0x080c, 0x1053, 0x080c, 0x3432, 0x080c, + 0x76ad, 0x080c, 0x69ad, 0x080c, 0x86fc, 0x080c, 0x8430, 0x080c, + 0x2485, 0x080c, 0x8fa0, 0x080c, 0x7d78, 0x080c, 0x22be, 0x080c, + 0x23f2, 0x080c, 0x247a, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x091f, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0913, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x2071, 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, - 0x1178, 0x080c, 0x4bd9, 0x080c, 0x344e, 0x080c, 0x7712, 0x080c, - 0x6ed0, 0x080c, 0x87bd, 0x080c, 0x843c, 0x080c, 0x2c95, 0x0c58, + 0x1178, 0x080c, 0x4be3, 0x080c, 0x3459, 0x080c, 0x771e, 0x080c, + 0x6ede, 0x080c, 0x87da, 0x080c, 0x8459, 0x080c, 0x2ca0, 0x0c58, 0x000b, 0x0c78, 0x0944, 0x0945, 0x0ae7, 0x0942, 0x0bae, 0x0d68, 0x0d68, 0x0d68, 0x080c, 0x0dd5, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aba, 0x080c, 0x56e7, + 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aba, 0x080c, 0x56f1, 0x1130, 0x0026, 0x2011, 0x0080, 0x080c, 0x0edf, 0x002e, 0x080c, - 0x73a5, 0x0150, 0x080c, 0x73c8, 0x15a0, 0x2079, 0x0100, 0x7828, - 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x72d7, 0x7000, 0x9086, + 0x73b3, 0x0150, 0x080c, 0x73d6, 0x15a0, 0x2079, 0x0100, 0x7828, + 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x72e5, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aba, 0x7098, 0x9086, 0x0028, 0x1904, 0x0aba, - 0x080c, 0x840b, 0x080c, 0x83fd, 0x2001, 0x0161, 0x2003, 0x0001, + 0x080c, 0x8428, 0x080c, 0x841a, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, - 0x2011, 0x723b, 0x080c, 0x84dc, 0x2011, 0x722e, 0x080c, 0x85b6, - 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x2011, 0x8030, 0x901e, 0x7396, - 0x04d0, 0x080c, 0x5739, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, - 0x0aba, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x2011, 0x723b, 0x080c, - 0x84dc, 0x2011, 0x722e, 0x080c, 0x85b6, 0x2001, 0x0265, 0x2001, + 0x2011, 0x7249, 0x080c, 0x84f9, 0x2011, 0x723c, 0x080c, 0x85d3, + 0x2011, 0x5e96, 0x080c, 0x84f9, 0x2011, 0x8030, 0x901e, 0x7396, + 0x04d0, 0x080c, 0x5743, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, + 0x0aba, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x2011, 0x7249, 0x080c, + 0x84f9, 0x2011, 0x723c, 0x080c, 0x85d3, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, 0x19a5, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, - 0x5fd9, 0x00ce, 0x0804, 0x0aba, 0x780f, 0x006b, 0x7a28, 0x080c, - 0x73ad, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, 0x7a2a, + 0x5fe3, 0x00ce, 0x0804, 0x0aba, 0x780f, 0x006b, 0x7a28, 0x080c, + 0x73bb, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a6, 0x2003, 0x0001, 0x080c, - 0x2b5b, 0x080c, 0x4b14, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c, - 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa51e, 0x2011, 0x0004, - 0x080c, 0xcb5a, 0x080c, 0x682b, 0x080c, 0x73a5, 0x1120, 0x080c, - 0x2b9f, 0x02e0, 0x0400, 0x080c, 0x5fe0, 0x0140, 0x7097, 0x0001, - 0x70d3, 0x0000, 0x080c, 0x5906, 0x0804, 0x0aba, 0x080c, 0x56d8, + 0x2b66, 0x080c, 0x4b1e, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c, + 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa52f, 0x2011, 0x0004, + 0x080c, 0xcb6a, 0x080c, 0x6839, 0x080c, 0x73b3, 0x1120, 0x080c, + 0x2baa, 0x02e0, 0x0400, 0x080c, 0x5fea, 0x0140, 0x7097, 0x0001, + 0x70d3, 0x0000, 0x080c, 0x5910, 0x0804, 0x0aba, 0x080c, 0x56e2, 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, - 0x56dc, 0xd0d4, 0x1118, 0x080c, 0x2b9f, 0x1270, 0x2011, 0x180c, - 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x56dc, 0xd0d4, 0x1db8, 0x2011, + 0x56e6, 0xd0d4, 0x1118, 0x080c, 0x2baa, 0x1270, 0x2011, 0x180c, + 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x56e6, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x2012, 0x080c, 0x6973, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, - 0x2012, 0x080c, 0x6939, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, - 0x707f, 0x0000, 0x080c, 0x73a5, 0x1130, 0x70b0, 0x9005, 0x1168, - 0x080c, 0xcf9b, 0x0050, 0x080c, 0xcf9b, 0x70dc, 0xd09c, 0x1128, - 0x70b0, 0x9005, 0x0110, 0x080c, 0x5fb6, 0x70e7, 0x0000, 0x70e3, - 0x0000, 0x70a7, 0x0000, 0x080c, 0x2ba7, 0x0228, 0x2011, 0x0101, - 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x73a5, 0x1178, 0x9016, - 0x0016, 0x080c, 0x2958, 0x2019, 0x196c, 0x211a, 0x001e, 0x705f, + 0x2012, 0x080c, 0x6981, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, + 0x2012, 0x080c, 0x6947, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, + 0x707f, 0x0000, 0x080c, 0x73b3, 0x1130, 0x70b0, 0x9005, 0x1168, + 0x080c, 0xcfab, 0x0050, 0x080c, 0xcfab, 0x70dc, 0xd09c, 0x1128, + 0x70b0, 0x9005, 0x0110, 0x080c, 0x5fc0, 0x70e7, 0x0000, 0x70e3, + 0x0000, 0x70a7, 0x0000, 0x080c, 0x2bb2, 0x0228, 0x2011, 0x0101, + 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x73b3, 0x1178, 0x9016, + 0x0016, 0x080c, 0x2963, 0x2019, 0x196c, 0x211a, 0x001e, 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019, 0x196c, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, 0xc295, - 0x72de, 0x080c, 0x73a5, 0x0118, 0x9296, 0x0004, 0x0548, 0x2011, - 0x0001, 0x080c, 0xcb5a, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, + 0x72de, 0x080c, 0x73b3, 0x0118, 0x9296, 0x0004, 0x0548, 0x2011, + 0x0001, 0x080c, 0xcb6a, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, - 0x782a, 0x00fe, 0x080c, 0x2f98, 0x2011, 0x0005, 0x080c, 0xa654, - 0x080c, 0x9687, 0x080c, 0x73a5, 0x0148, 0x00c6, 0x2061, 0x0100, - 0x0016, 0x080c, 0x2958, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, + 0x782a, 0x00fe, 0x080c, 0x2fa3, 0x2011, 0x0005, 0x080c, 0xa63e, + 0x080c, 0x96a6, 0x080c, 0x73b3, 0x0148, 0x00c6, 0x2061, 0x0100, + 0x0016, 0x080c, 0x2963, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, 0x00fe, - 0x2011, 0x0005, 0x080c, 0xa654, 0x080c, 0x9687, 0x080c, 0x73a5, - 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2958, 0x61e2, + 0x2011, 0x0005, 0x080c, 0xa63e, 0x080c, 0x96a6, 0x080c, 0x73b3, + 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2963, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, 0x080c, - 0x73a5, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, - 0x73a5, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, + 0x73b3, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, + 0x73b3, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, 0x090c, - 0x32bd, 0x8108, 0x1f04, 0x0ace, 0x707f, 0x0000, 0x7080, 0x9084, + 0x32c8, 0x8108, 0x1f04, 0x0ace, 0x707f, 0x0000, 0x7080, 0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0bab, - 0x70ac, 0x9086, 0xffff, 0x0130, 0x080c, 0x2f98, 0x080c, 0x9687, + 0x70ac, 0x9086, 0xffff, 0x0130, 0x080c, 0x2fa3, 0x080c, 0x96a6, 0x0804, 0x0bab, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, - 0x0508, 0x080c, 0x3320, 0x11d0, 0x70e0, 0x9086, 0xffff, 0x01b0, - 0x080c, 0x312d, 0x080c, 0x9687, 0x70dc, 0xd094, 0x1904, 0x0bab, - 0x2011, 0x0001, 0x080c, 0xd24a, 0x0110, 0x2011, 0x0003, 0x901e, - 0x080c, 0x3167, 0x080c, 0x9687, 0x0804, 0x0bab, 0x70e4, 0x9005, + 0x0508, 0x080c, 0x332b, 0x11d0, 0x70e0, 0x9086, 0xffff, 0x01b0, + 0x080c, 0x3138, 0x080c, 0x96a6, 0x70dc, 0xd094, 0x1904, 0x0bab, + 0x2011, 0x0001, 0x080c, 0xd25a, 0x0110, 0x2011, 0x0003, 0x901e, + 0x080c, 0x3172, 0x080c, 0x96a6, 0x0804, 0x0bab, 0x70e4, 0x9005, 0x1904, 0x0bab, 0x70a8, 0x9005, 0x1904, 0x0bab, 0x70dc, 0xd0a4, - 0x0118, 0xd0b4, 0x0904, 0x0bab, 0x080c, 0x6939, 0x1904, 0x0bab, - 0x080c, 0x698c, 0x1904, 0x0bab, 0x080c, 0x6973, 0x01c0, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6608, 0x1118, + 0x0118, 0xd0b4, 0x0904, 0x0bab, 0x080c, 0x6947, 0x1904, 0x0bab, + 0x080c, 0x699a, 0x1904, 0x0bab, 0x080c, 0x6981, 0x01c0, 0x0156, + 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6616, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b44, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0bab, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b2, 0x080c, 0x0f87, 0x2011, 0x19cc, 0x080c, 0x0f87, 0x7030, 0xc08c, 0x7032, - 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x56e7, 0x1130, 0x0026, - 0x2011, 0x0040, 0x080c, 0x0edf, 0x002e, 0x9006, 0x080c, 0x27ec, - 0x080c, 0x3320, 0x0118, 0x080c, 0x4cb1, 0x0050, 0x0036, 0x0046, - 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4ccb, 0x004e, 0x003e, - 0x00f6, 0x2079, 0x0100, 0x080c, 0x73c8, 0x0150, 0x080c, 0x73a5, + 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x56f1, 0x1130, 0x0026, + 0x2011, 0x0040, 0x080c, 0x0edf, 0x002e, 0x9006, 0x080c, 0x27f7, + 0x080c, 0x332b, 0x0118, 0x080c, 0x4cbb, 0x0050, 0x0036, 0x0046, + 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4cd5, 0x004e, 0x003e, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x73d6, 0x0150, 0x080c, 0x73b3, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0x19e7, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, - 0x0000, 0x080c, 0xa654, 0x2011, 0x0000, 0x080c, 0xa65e, 0x080c, - 0x9687, 0x080c, 0x97b5, 0x012e, 0x00be, 0x0005, 0x0016, 0x0046, + 0x0000, 0x080c, 0xa63e, 0x2011, 0x0000, 0x080c, 0xa648, 0x080c, + 0x96a6, 0x080c, 0x97d4, 0x012e, 0x00be, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, - 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x5f9f, 0x7940, 0x918c, + 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x5fa9, 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x0c3b, 0x2001, 0x19a6, 0x2004, 0x9005, 0x1518, 0x080c, - 0x2c22, 0x1148, 0x2001, 0x0001, 0x080c, 0x2b8a, 0x2001, 0x0001, - 0x080c, 0x2b6d, 0x00b8, 0x080c, 0x2c2a, 0x1138, 0x9006, 0x080c, - 0x2b8a, 0x9006, 0x080c, 0x2b6d, 0x0068, 0x080c, 0x2c32, 0x1d50, - 0x2001, 0x1997, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x2984, - 0x0804, 0x0d1a, 0x080c, 0x73b6, 0x0148, 0x080c, 0x73c8, 0x1118, - 0x080c, 0x769c, 0x0050, 0x080c, 0x73ad, 0x0dd0, 0x080c, 0x7697, - 0x080c, 0x768d, 0x080c, 0x72d7, 0x0058, 0x080c, 0x73a5, 0x0140, - 0x2009, 0x00f8, 0x080c, 0x5f9f, 0x7843, 0x0090, 0x7843, 0x0010, - 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x73a5, 0x0138, + 0x2c2d, 0x1148, 0x2001, 0x0001, 0x080c, 0x2b95, 0x2001, 0x0001, + 0x080c, 0x2b78, 0x00b8, 0x080c, 0x2c35, 0x1138, 0x9006, 0x080c, + 0x2b95, 0x9006, 0x080c, 0x2b78, 0x0068, 0x080c, 0x2c3d, 0x1d50, + 0x2001, 0x1997, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x298f, + 0x0804, 0x0d1a, 0x080c, 0x73c4, 0x0148, 0x080c, 0x73d6, 0x1118, + 0x080c, 0x76a8, 0x0050, 0x080c, 0x73bb, 0x0dd0, 0x080c, 0x76a3, + 0x080c, 0x7699, 0x080c, 0x72e5, 0x0058, 0x080c, 0x73b3, 0x0140, + 0x2009, 0x00f8, 0x080c, 0x5fa9, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x73b3, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d1f, 0x1f04, 0x0c1a, 0x0070, 0x7824, - 0x080c, 0x73bf, 0x0118, 0xd0ac, 0x1904, 0x0d1f, 0x9084, 0x1800, + 0x080c, 0x73cd, 0x0118, 0xd0ac, 0x1904, 0x0d1f, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d1f, 0x2001, 0x0001, 0x080c, - 0x27ec, 0x0804, 0x0d32, 0x2001, 0x19a6, 0x2004, 0x9005, 0x1518, - 0x080c, 0x2c22, 0x1148, 0x2001, 0x0001, 0x080c, 0x2b8a, 0x2001, - 0x0001, 0x080c, 0x2b6d, 0x00b8, 0x080c, 0x2c2a, 0x1138, 0x9006, - 0x080c, 0x2b8a, 0x9006, 0x080c, 0x2b6d, 0x0068, 0x080c, 0x2c32, + 0x27f7, 0x0804, 0x0d32, 0x2001, 0x19a6, 0x2004, 0x9005, 0x1518, + 0x080c, 0x2c2d, 0x1148, 0x2001, 0x0001, 0x080c, 0x2b95, 0x2001, + 0x0001, 0x080c, 0x2b78, 0x00b8, 0x080c, 0x2c35, 0x1138, 0x9006, + 0x080c, 0x2b95, 0x9006, 0x080c, 0x2b78, 0x0068, 0x080c, 0x2c3d, 0x1d50, 0x2001, 0x1997, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, - 0x2984, 0x0804, 0x0d1a, 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, - 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c3a, 0x9085, 0x2000, - 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c74, 0x080c, 0x8596, + 0x298f, 0x0804, 0x0d1a, 0x7850, 0x9085, 0x0040, 0x7852, 0x7938, + 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c45, 0x9085, 0x2000, + 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c74, 0x080c, 0x85b3, 0x1f04, 0x0c74, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, - 0x793a, 0x080c, 0x73b6, 0x0148, 0x080c, 0x73c8, 0x1118, 0x080c, - 0x769c, 0x0050, 0x080c, 0x73ad, 0x0dd0, 0x080c, 0x7697, 0x080c, - 0x768d, 0x080c, 0x72d7, 0x0020, 0x2009, 0x00f8, 0x080c, 0x5f9f, + 0x793a, 0x080c, 0x73c4, 0x0148, 0x080c, 0x73d6, 0x1118, 0x080c, + 0x76a8, 0x0050, 0x080c, 0x73bb, 0x0dd0, 0x080c, 0x76a3, 0x080c, + 0x7699, 0x080c, 0x72e5, 0x0020, 0x2009, 0x00f8, 0x080c, 0x5fa9, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c9a, 0x7850, 0x9085, 0x1400, - 0x7852, 0x080c, 0x73a5, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, - 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x8596, 0x7820, 0xd09c, - 0x1580, 0x080c, 0x73a5, 0x0904, 0x0cff, 0x7824, 0xd0ac, 0x1904, - 0x0d1f, 0x080c, 0x73c8, 0x1528, 0x0046, 0x2021, 0x0320, 0x8421, - 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c3a, 0x7824, 0x9084, + 0x7852, 0x080c, 0x73b3, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, + 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x85b3, 0x7820, 0xd09c, + 0x1580, 0x080c, 0x73b3, 0x0904, 0x0cff, 0x7824, 0xd0ac, 0x1904, + 0x0d1f, 0x080c, 0x73d6, 0x1528, 0x0046, 0x2021, 0x0320, 0x8421, + 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c45, 0x7824, 0x9084, 0x1800, 0x1160, 0x9484, 0x0fff, 0x1138, 0x2001, 0x1810, 0x2004, 0xd0fc, 0x0110, 0x080c, 0x0d45, 0x8421, 0x1158, 0x1d04, 0x0cda, - 0x080c, 0x8596, 0x080c, 0x7697, 0x080c, 0x768d, 0x7003, 0x0001, - 0x04f0, 0x8319, 0x1948, 0x1d04, 0x0ce7, 0x080c, 0x8596, 0x2009, + 0x080c, 0x85b3, 0x080c, 0x76a3, 0x080c, 0x7699, 0x7003, 0x0001, + 0x04f0, 0x8319, 0x1948, 0x1d04, 0x0ce7, 0x080c, 0x85b3, 0x2009, 0x199a, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, 0x1178, 0x200b, - 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, 0x2c1b, 0x7924, - 0x080c, 0x2c3a, 0xd19c, 0x0110, 0x080c, 0x2b5b, 0x00d8, 0x080c, - 0x73b6, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x737d, 0x7003, - 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2c3a, 0x7824, 0x080c, - 0x73bf, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, 0x0950, 0x7003, - 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x27ec, 0x0078, 0x2009, + 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, 0x2c26, 0x7924, + 0x080c, 0x2c45, 0xd19c, 0x0110, 0x080c, 0x2b66, 0x00d8, 0x080c, + 0x73c4, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, 0x738b, 0x7003, + 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2c45, 0x7824, 0x080c, + 0x73cd, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, 0x0950, 0x7003, + 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x27f7, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x19a6, 0x2003, 0x0000, 0x9006, 0x78f2, - 0x015e, 0x003e, 0x000e, 0x080c, 0x56e7, 0x1110, 0x080c, 0x0e62, + 0x015e, 0x003e, 0x000e, 0x080c, 0x56f1, 0x1110, 0x080c, 0x0e62, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, - 0x0d0c, 0x8596, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, + 0x0d0c, 0x85b3, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, - 0x7004, 0x9086, 0x0001, 0x1110, 0x080c, 0x344e, 0x00ee, 0x0005, - 0x0005, 0x2a70, 0x2061, 0x19aa, 0x2063, 0x0003, 0x6007, 0x0002, - 0x600b, 0x001e, 0x600f, 0x0137, 0x2001, 0x197b, 0x900e, 0x2102, + 0x7004, 0x9086, 0x0001, 0x1110, 0x080c, 0x3459, 0x00ee, 0x0005, + 0x0005, 0x2a70, 0x2061, 0x19aa, 0x2063, 0x0003, 0x6007, 0x0003, + 0x600b, 0x0002, 0x600f, 0x0137, 0x2001, 0x197b, 0x900e, 0x2102, 0x7196, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, - 0xcf9b, 0x2061, 0x196b, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, + 0xcfab, 0x2061, 0x196b, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x1973, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, 0x1988, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6608, + 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6616, 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, @@ -251,11 +251,11 @@ unsigned short risc_code01[] = { 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a18, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, - 0x2003, 0x1001, 0x080c, 0x56e7, 0x1110, 0x080c, 0x0e99, 0x0cd0, + 0x2003, 0x1001, 0x080c, 0x56f1, 0x1110, 0x080c, 0x0e99, 0x0cd0, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x2800, 0x0010, 0x918d, 0x2000, 0x2001, 0x017f, 0x2102, 0x0005, 0x00f6, 0x0006, 0x2079, 0x1827, 0x2f04, 0x8000, - 0x207a, 0x080c, 0x2c32, 0x1150, 0x0006, 0x2001, 0x1997, 0x2004, + 0x207a, 0x080c, 0x2c3d, 0x1150, 0x0006, 0x2001, 0x1997, 0x2004, 0xd0fc, 0x000e, 0x1118, 0x9082, 0x7530, 0x0010, 0x9082, 0x000f, 0x0258, 0x9006, 0x207a, 0x2079, 0x182a, 0x2f04, 0x9084, 0x0001, 0x9086, 0x0001, 0x207a, 0x0090, 0x2079, 0x182a, 0x2f7c, 0x8fff, @@ -266,8 +266,8 @@ unsigned short risc_code01[] = { 0x080c, 0x0f00, 0x0c80, 0x7038, 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0040, 0x0469, 0x002e, 0x0005, 0x7038, 0xd0b4, 0x1128, 0x0026, 0x2011, 0x0080, 0x0421, 0x002e, 0x0005, 0x0026, 0x70ef, 0x0000, - 0x0459, 0x1148, 0x080c, 0x2c32, 0x1118, 0x2011, 0x8484, 0x0058, - 0x2011, 0x8282, 0x0040, 0x080c, 0x2c32, 0x1118, 0x2011, 0xcdc5, + 0x0459, 0x1148, 0x080c, 0x2c3d, 0x1118, 0x2011, 0x8484, 0x0058, + 0x2011, 0x8282, 0x0040, 0x080c, 0x2c3d, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x00e9, 0x002e, 0x0005, 0xd0b4, 0x0130, 0x0006, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x0005, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, @@ -315,7 +315,7 @@ unsigned short risc_code01[] = { 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x83fd, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, @@ -380,15 +380,15 @@ unsigned short risc_code01[] = { 0x080c, 0x1108, 0x0005, 0x00de, 0x009e, 0x080c, 0x1108, 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0dd5, 0xa06c, 0x908e, 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, - 0xa897, 0x4002, 0x080c, 0x6c7a, 0xa09f, 0x0000, 0xa0a3, 0x0000, + 0xa897, 0x4002, 0x080c, 0x6c88, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x1031, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0dd5, 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x10e9, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, - 0x6c7a, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, - 0x2060, 0x080c, 0xae71, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, + 0x6c88, 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, + 0x2060, 0x080c, 0xae5f, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, 0x1031, 0x7007, 0x0000, 0x080c, 0x1108, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, @@ -397,12 +397,12 @@ unsigned short risc_code01[] = { 0x8000, 0x782b, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, 0x012e, 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x0096, 0x2001, 0x192e, 0x204c, 0xaa7c, - 0x009e, 0x080c, 0x89f5, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, - 0x200a, 0x080c, 0x8868, 0x7007, 0x0000, 0x080c, 0x1119, 0x0005, + 0x009e, 0x080c, 0x8a12, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, + 0x200a, 0x080c, 0x8885, 0x7007, 0x0000, 0x080c, 0x1119, 0x0005, 0x7007, 0x0000, 0x080c, 0x1119, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x1a61, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b, 0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, - 0x03d0, 0x2061, 0xea39, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, + 0x03d0, 0x2061, 0xea53, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x1303, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0120, 0x7820, 0x080c, 0x1362, 0x0cc8, 0x2001, 0x1a62, 0x2003, @@ -411,13 +411,13 @@ unsigned short risc_code01[] = { 0x782b, 0x1a81, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a81, 0x602f, 0x1cd0, 0x2001, 0x181a, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, - 0x2092, 0x2001, 0x3327, 0xd0fc, 0x190c, 0x0dd5, 0x2001, 0x0003, - 0x2004, 0xd0d4, 0x1118, 0x783f, 0x3327, 0x0020, 0x9084, 0xc000, - 0x783f, 0xb327, 0x604f, 0x193c, 0x2001, 0x1927, 0x2004, 0x6042, + 0x209d, 0x2001, 0x3332, 0xd0fc, 0x190c, 0x0dd5, 0x2001, 0x0003, + 0x2004, 0xd0d4, 0x1118, 0x783f, 0x3332, 0x0020, 0x9084, 0xc000, + 0x783f, 0xb332, 0x604f, 0x193c, 0x2001, 0x1927, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d, 0x11d0, 0x7808, 0xd09c, 0x01b8, - 0x7820, 0x0026, 0x2010, 0x080c, 0xcb38, 0x0180, 0x2260, 0x6000, + 0x7820, 0x0026, 0x2010, 0x080c, 0xcb48, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, - 0x0020, 0x2009, 0x004c, 0x080c, 0xaeec, 0x001e, 0x002e, 0x0005, + 0x0020, 0x2009, 0x004c, 0x080c, 0xaeda, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, 0x9184, 0x0070, 0x190c, 0x0dce, 0xd19c, 0x0158, 0x7820, 0x908c, 0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0dd5, 0x0023, 0x012e, 0x0005, 0x012e, 0x0005, 0x13bb, @@ -426,18 +426,18 @@ unsigned short risc_code01[] = { 0x155d, 0x1568, 0x156f, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13e2, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bb, 0x13bf, 0x13bd, 0x080c, 0x0dd5, 0x080c, 0x0dce, 0x080c, - 0x157a, 0x2009, 0x1a7a, 0x2104, 0x8000, 0x200a, 0x080c, 0x7e3f, - 0x080c, 0x1aab, 0x0005, 0x2009, 0x0048, 0x2060, 0x080c, 0xaeec, + 0x157a, 0x2009, 0x1a7a, 0x2104, 0x8000, 0x200a, 0x080c, 0x7e4c, + 0x080c, 0x1abb, 0x0005, 0x2009, 0x0048, 0x2060, 0x080c, 0xaeda, 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, 0x157a, 0x080c, 0x16bd, 0x0005, 0x080c, 0x0dd5, 0x080c, 0x157a, 0x2060, 0x6014, 0x0096, 0x2048, - 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0xaeec, 0x2001, + 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0xaeda, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x157f, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, 0x157a, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, - 0xaeec, 0x0005, 0x080c, 0x157a, 0x080c, 0x0dd5, 0x080c, 0x157a, + 0xaeda, 0x0005, 0x080c, 0x157a, 0x080c, 0x0dd5, 0x080c, 0x157a, 0x080c, 0x14d6, 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0904, 0x1487, 0x7827, 0x0015, 0x7828, 0x782b, 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x148d, 0x7004, @@ -446,20 +446,20 @@ unsigned short risc_code01[] = { 0x2003, 0x0020, 0x0804, 0x14bb, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x14ef, 0x0005, 0x7827, 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, 0x0110, 0x79ac, 0x08e0, 0x00e6, - 0x2071, 0x0200, 0x702c, 0xd0c4, 0x0140, 0x00ee, 0x080c, 0x1aab, + 0x2071, 0x0200, 0x702c, 0xd0c4, 0x0140, 0x00ee, 0x080c, 0x1abb, 0x080c, 0x1313, 0x7803, 0x0001, 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x14ef, 0x2001, 0x020d, 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, 0x0dd5, 0x6014, 0x2048, 0x78ab, - 0x0004, 0x918c, 0x0700, 0x01a8, 0x080c, 0x7e3f, 0x080c, 0x1aab, - 0x080c, 0xcb4a, 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, + 0x0004, 0x918c, 0x0700, 0x01a8, 0x080c, 0x7e4c, 0x080c, 0x1abb, + 0x080c, 0xcb5a, 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, 0xc0bd, 0xa882, 0x080c, 0xc77b, 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x2009, 0x004c, 0x080c, - 0xaeec, 0x0048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x6024, 0x190c, 0xcf34, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xe9e2, 0xd5a4, - 0x1118, 0x080c, 0x157f, 0x0005, 0x080c, 0x7e3f, 0x080c, 0x1aab, + 0xaeda, 0x0048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, + 0x6024, 0x190c, 0xcf44, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, + 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xe9fc, 0xd5a4, + 0x1118, 0x080c, 0x157f, 0x0005, 0x080c, 0x7e4c, 0x080c, 0x1abb, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x15f0, 0x00fe, 0x007e, @@ -477,9 +477,9 @@ unsigned short risc_code01[] = { 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x1313, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0461, 0x0ca8, 0x0429, 0x2060, 0x2009, 0x0053, - 0x080c, 0xaeec, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, 0x00d1, - 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x8d52, 0x0005, - 0x0089, 0x9005, 0x0118, 0x080c, 0x8955, 0x0cd0, 0x0005, 0x2001, + 0x080c, 0xaeda, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, 0x00d1, + 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x8d71, 0x0005, + 0x0089, 0x9005, 0x0118, 0x080c, 0x8972, 0x0cd0, 0x0005, 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, 0x080c, 0x15f0, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, 0x14d6, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0510, @@ -489,7 +489,7 @@ unsigned short risc_code01[] = { 0x080c, 0x15e2, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, 0x080c, - 0x7e3f, 0x080c, 0x1aab, 0x0090, 0x7827, 0x0015, 0x782b, 0x0000, + 0x7e4c, 0x080c, 0x1abb, 0x0090, 0x7827, 0x0015, 0x782b, 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, 0x0015, @@ -505,17 +505,17 @@ unsigned short risc_code01[] = { 0x1669, 0x9284, 0x0048, 0x9086, 0x0008, 0x1904, 0x1669, 0x2001, 0x0109, 0x2004, 0xd08c, 0x01f0, 0x0006, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x0126, 0x2091, 0x2800, 0x00f6, 0x0026, 0x0016, - 0x2009, 0x1a7c, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0x908b, + 0x2009, 0x1a7c, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0x90aa, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x000e, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x01d0, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x00f6, 0x0016, - 0x2009, 0x1a7d, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0x1eb6, + 0x2009, 0x1a7d, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0x1ec1, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x7818, 0xd0bc, 0x1904, 0x1619, 0x0005, 0x2001, 0x180c, 0x2004, 0xd0f4, 0x1528, 0x7a18, 0x9284, 0x0030, 0x0508, 0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19f5, 0x2004, 0x9005, 0x01b8, 0x2001, 0x1a65, 0x2004, 0x9086, 0x0000, 0x0188, 0x2009, - 0x1a7b, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa2f8, 0x2009, + 0x1a7b, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa30d, 0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, 0x0804, 0x1619, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x080c, 0x1612, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, @@ -526,32 +526,32 @@ unsigned short risc_code01[] = { 0x171c, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x171c, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x171c, 0x9c06, 0x15f0, 0x0126, 0x2091, - 0x2600, 0x080c, 0x7d86, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, + 0x2600, 0x080c, 0x7d93, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x190c, 0xcf0f, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, + 0x190c, 0xcf1f, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, - 0x20b2, 0x1190, 0x080c, 0x1909, 0x2a00, 0xa816, 0x0130, 0x2800, + 0x20bd, 0x1190, 0x080c, 0x1909, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x157f, 0x0005, 0x080c, 0x0dd5, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, - 0x2092, 0x2165, 0x0002, 0x1752, 0x17c0, 0x1752, 0x1752, 0x1756, + 0x209d, 0x2165, 0x0002, 0x1752, 0x17c0, 0x1752, 0x1752, 0x1756, 0x17a1, 0x1752, 0x1776, 0x174b, 0x17b7, 0x1752, 0x1752, 0x175b, 0x18ac, 0x178a, 0x1780, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x17b7, 0x9085, 0x0001, 0x0804, 0x18a3, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x17c7, 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x1832, 0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, - 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x8f19, 0x2005, 0x9005, + 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x8f38, 0x2005, 0x9005, 0x090c, 0x0dd5, 0x2004, 0xa8ae, 0x0804, 0x188b, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x17c7, 0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1832, 0xa87c, 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, 0x0dd5, 0xa164, 0xa91a, 0x91ec, - 0x000f, 0x9d80, 0x2092, 0x2065, 0xa888, 0xd19c, 0x1904, 0x1832, + 0x000f, 0x9d80, 0x209d, 0x2065, 0xa888, 0xd19c, 0x1904, 0x1832, 0x0430, 0xa87c, 0xd0ac, 0x0904, 0x1752, 0xa804, 0x9045, 0x090c, - 0x0dd5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x2092, 0x2065, + 0x0dd5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x209d, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x1832, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x1752, 0x9006, 0xa842, 0xa83e, 0x0804, 0x1832, 0xa87c, 0xd0ac, 0x0904, 0x1752, 0x9006, 0xa842, 0xa83e, 0x2c05, @@ -585,7 +585,7 @@ unsigned short risc_code01[] = { 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c78, 0x0804, 0x1752, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, - 0x2061, 0x208d, 0xa813, 0x208d, 0x2c05, 0xa80a, 0xa964, 0xa91a, + 0x2061, 0x2098, 0xa813, 0x2098, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, 0x0dd5, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dd5, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, @@ -594,7 +594,7 @@ unsigned short risc_code01[] = { 0x0002, 0xa916, 0x1158, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0dd5, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, - 0x2092, 0x2015, 0x82ff, 0x090c, 0x0dd5, 0xaa12, 0x2205, 0xa80a, + 0x209d, 0x2015, 0x82ff, 0x090c, 0x0dd5, 0xaa12, 0x2205, 0xa80a, 0x0c10, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a33, 0x1960, 0x1960, 0x1a33, 0x1960, 0x1a2d, 0x1a33, 0x1960, 0x19d0, 0x19d0, 0x19d0, 0x1a33, 0x19d0, 0x1a33, 0x1a2a, 0x19d0, @@ -631,5534 +631,5534 @@ unsigned short risc_code01[] = { 0x9d86, 0x000c, 0x0510, 0xa3ac, 0xa2b0, 0x00f8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, 0x000c, 0x01c0, 0xa3c4, 0xa2c8, 0x00a8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x000c, 0x0170, 0xa3dc, - 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x204a, 0x1904, + 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x2055, 0x1904, 0x1909, 0x900e, 0x0050, 0x080c, 0x0dd5, 0xab2e, 0xaa32, 0xad1e, - 0xac22, 0xaf26, 0xae2a, 0x080c, 0x204a, 0x0005, 0x6014, 0x2048, + 0xac22, 0xaf26, 0xae2a, 0x080c, 0x2055, 0x0005, 0x6014, 0x2048, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, - 0x0008, 0xa986, 0x601b, 0x0002, 0xa974, 0xd1dc, 0x1108, 0x0005, + 0x0008, 0xa986, 0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, + 0x0008, 0x0150, 0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, + 0x0048, 0x080c, 0xaeda, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, - 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0xaeec, 0x0005, + 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0xaeda, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x1380, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1380, - 0x00ce, 0x2001, 0x0038, 0x080c, 0x1b38, 0x7930, 0x9186, 0x0040, + 0x00ce, 0x2001, 0x0038, 0x080c, 0x1b43, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0dd5, 0x2001, 0x001e, 0x8001, - 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1b47, 0x000e, 0x6022, 0x012e, - 0x0005, 0x080c, 0x1b34, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, + 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1b52, 0x000e, 0x6022, 0x012e, + 0x0005, 0x080c, 0x1b3f, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, - 0x78ab, 0x0004, 0x00fe, 0x080c, 0x73a5, 0x11b0, 0x2001, 0x0138, + 0x78ab, 0x0004, 0x00fe, 0x080c, 0x73b3, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, - 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, 0x0000, - 0x080c, 0x7455, 0x006e, 0x0005, 0x0479, 0x0039, 0x2001, 0x0160, - 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, - 0x080c, 0x2c46, 0x2009, 0x003c, 0x080c, 0x23d4, 0x2001, 0x015d, - 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x83fd, - 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, - 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1313, 0x7803, - 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, - 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x73a5, - 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, - 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, - 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, - 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, - 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, - 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, - 0x2c08, 0x621c, 0x080c, 0x15f0, 0x7930, 0x0005, 0x2c08, 0x621c, - 0x080c, 0x169b, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, - 0x0005, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, - 0x9186, 0x0040, 0x0904, 0x1ba5, 0x2001, 0x001e, 0x0c69, 0x8631, - 0x1d80, 0x080c, 0x0dd5, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, - 0x0000, 0x2001, 0x0b10, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, - 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, - 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, - 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, - 0x1b3e, 0x9186, 0x0040, 0x190c, 0x0dd5, 0x00d6, 0x2069, 0x0200, - 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, - 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, - 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, - 0x0dd5, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, - 0x2400, 0x2071, 0x1a65, 0x2079, 0x0090, 0x012e, 0x0005, 0x9280, - 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1c47, 0xa964, - 0x9184, 0x0007, 0x0002, 0x1bc3, 0x1c32, 0x1bda, 0x1bdc, 0x1bda, - 0x1c1a, 0x1bfa, 0x1be9, 0x918c, 0x00ff, 0x9186, 0x0008, 0x1170, - 0xa87c, 0xd0b4, 0x0904, 0x1e71, 0x9006, 0xa842, 0xa83e, 0xa988, - 0x2900, 0xa85a, 0xa813, 0x208d, 0x0804, 0x1c43, 0x9186, 0x0048, - 0x0904, 0x1c32, 0x080c, 0x0dd5, 0x9184, 0x00ff, 0x9086, 0x0013, - 0x0904, 0x1c32, 0x9184, 0x00ff, 0x9086, 0x001b, 0x0904, 0x1c32, - 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1e71, 0xa890, 0xa842, 0xa83a, - 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa988, - 0x0804, 0x1c3a, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x19d0, - 0xa87c, 0xd0b4, 0x0904, 0x1e71, 0xa890, 0xa842, 0xa83a, 0xa88c, - 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa804, 0xa85a, - 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x2092, 0x2005, 0xa812, - 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1540, 0xa87c, - 0xd0b4, 0x0904, 0x1e71, 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, - 0x000f, 0x9080, 0x2092, 0x2005, 0xa812, 0xa988, 0x9006, 0xa842, - 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1e71, 0xa988, 0x9006, - 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, 0x000f, 0x9080, - 0x2092, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, 0xa87e, 0x0005, - 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x1eb6, 0x00e6, - 0x2071, 0x1a65, 0x7000, 0x9005, 0x1904, 0x1cb0, 0x7206, 0x9280, - 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, 0x782b, 0x0004, 0x00f6, - 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, 0x00b6, 0x2058, 0xb86c, - 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, 0x2079, - 0x0100, 0x8004, 0x78d6, 0x00fe, 0xa814, 0x2050, 0xa858, 0x2040, - 0xa810, 0x2060, 0xa064, 0x90ec, 0x000f, 0xa944, 0x791a, 0x7116, - 0xa848, 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, 0xa940, - 0xa838, 0x9106, 0x1500, 0xa93c, 0xa834, 0x9106, 0x11e0, 0x0006, - 0x0016, 0xa938, 0xa834, 0x9105, 0x0118, 0x001e, 0x000e, 0x0098, - 0x001e, 0x000e, 0x8aff, 0x01c8, 0x0126, 0x2091, 0x8000, 0x2009, - 0x0306, 0x200b, 0x0808, 0x00d9, 0x0108, 0x00c9, 0x012e, 0x9006, - 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, 0xac34, 0x080c, - 0x20b2, 0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, - 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e6a, - 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x1e69, - 0x9705, 0x0904, 0x1e69, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, - 0x2d00, 0x0002, 0x1df3, 0x1d32, 0x1d32, 0x1df3, 0x1df3, 0x1dd0, - 0x1df3, 0x1d32, 0x1dd7, 0x1d81, 0x1d81, 0x1df3, 0x1df3, 0x1df3, - 0x1dca, 0x1d81, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, - 0xdd9c, 0x0904, 0x1e00, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dd5, - 0x9082, 0x001b, 0x0002, 0x1d1e, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d1c, - 0x1d1c, 0x1d22, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d26, - 0x1d1c, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d1c, 0x1d2a, 0x1d1c, 0x1d1c, - 0x1d1c, 0x1d1c, 0x1d1c, 0x1d2e, 0x080c, 0x0dd5, 0xa774, 0xa678, - 0x0804, 0x1e00, 0xa78c, 0xa690, 0x0804, 0x1e00, 0xa7a4, 0xa6a8, - 0x0804, 0x1e00, 0xa7bc, 0xa6c0, 0x0804, 0x1e00, 0xa7d4, 0xa6d8, - 0x0804, 0x1e00, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x9082, - 0x001b, 0x0002, 0x1d55, 0x1d55, 0x1d57, 0x1d55, 0x1d55, 0x1d55, - 0x1d5d, 0x1d55, 0x1d55, 0x1d55, 0x1d63, 0x1d55, 0x1d55, 0x1d55, - 0x1d69, 0x1d55, 0x1d55, 0x1d55, 0x1d6f, 0x1d55, 0x1d55, 0x1d55, - 0x1d75, 0x1d55, 0x1d55, 0x1d55, 0x1d7b, 0x080c, 0x0dd5, 0xa574, - 0xa478, 0xa37c, 0xa280, 0x0804, 0x1e00, 0xa584, 0xa488, 0xa38c, - 0xa290, 0x0804, 0x1e00, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, - 0x1e00, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e00, 0xa5b4, - 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1e00, 0xa5c4, 0xa4c8, 0xa3cc, - 0xa2d0, 0x0804, 0x1e00, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, - 0x1e00, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dd5, 0x9082, 0x001b, - 0x0002, 0x1da4, 0x1da2, 0x1da2, 0x1da2, 0x1da2, 0x1da2, 0x1dac, - 0x1da2, 0x1da2, 0x1da2, 0x1da2, 0x1da2, 0x1db4, 0x1da2, 0x1da2, - 0x1da2, 0x1da2, 0x1da2, 0x1dbc, 0x1da2, 0x1da2, 0x1da2, 0x1da2, - 0x1da2, 0x1dc3, 0x080c, 0x0dd5, 0xa56c, 0xa470, 0xa774, 0xa678, - 0xa37c, 0xa280, 0x0804, 0x1e00, 0xa584, 0xa488, 0xa78c, 0xa690, - 0xa394, 0xa298, 0x0804, 0x1e00, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, - 0xa3ac, 0xa2b0, 0x0804, 0x1e00, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, - 0xa3c4, 0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, - 0xa2e0, 0x04b0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, - 0x080c, 0x204a, 0x1904, 0x1ccd, 0x900e, 0x0804, 0x1e6a, 0xab64, - 0x939c, 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, - 0x6004, 0x9086, 0x0043, 0x00ce, 0x0904, 0x1d81, 0xab9c, 0x9016, - 0xad8c, 0xac90, 0xaf94, 0xae98, 0x0098, 0x9386, 0x0008, 0x0904, - 0x1d81, 0x080c, 0x0dd5, 0xa964, 0x918c, 0x00ff, 0x9186, 0x0013, - 0x0904, 0x1d32, 0x9186, 0x001b, 0x0904, 0x1d81, 0x080c, 0x0dd5, - 0x2009, 0x030f, 0x2104, 0xd0fc, 0x0530, 0x0066, 0x2009, 0x0306, - 0x2104, 0x9084, 0x0030, 0x15c8, 0x2031, 0x1000, 0x200b, 0x4000, - 0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, 0x9105, - 0x0168, 0x2011, 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, 0x9481, - 0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, 0x0000, - 0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, - 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, 0x9300, - 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, 0x7010, - 0x9201, 0x7012, 0x080c, 0x204a, 0x0428, 0x2031, 0x0080, 0x9584, - 0x007f, 0x0108, 0x9632, 0x7124, 0x7000, 0x9086, 0x0000, 0x1198, - 0xc185, 0x7126, 0x2009, 0x0306, 0x2104, 0xd0b4, 0x1904, 0x1e10, - 0x200b, 0x4040, 0x2009, 0x1a7e, 0x2104, 0x8000, 0x0a04, 0x1e10, - 0x200a, 0x0804, 0x1e10, 0xc18d, 0x7126, 0xd184, 0x1d58, 0x0804, - 0x1e10, 0x9006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x0005, 0x080c, 0x0dd5, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, - 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, 0x0016, 0x080c, 0x1cc0, - 0x001e, 0x2060, 0x6014, 0x2048, 0x080c, 0xcb4a, 0x0118, 0xa880, - 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, - 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, - 0x60c4, 0xa89a, 0x60c8, 0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, - 0xc77b, 0x00ce, 0x2001, 0x19f5, 0x2004, 0x9c06, 0x1160, 0x2009, - 0x0040, 0x080c, 0x23d4, 0x080c, 0xa7cd, 0x2011, 0x0000, 0x080c, - 0xa65e, 0x080c, 0x97b5, 0x002e, 0x0804, 0x1ffa, 0x0126, 0x2091, - 0x2400, 0xa858, 0x2040, 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, - 0x1904, 0x1e73, 0x7000, 0x0002, 0x1ffa, 0x1ec8, 0x1f48, 0x1ff8, - 0x8001, 0x7002, 0x7027, 0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, - 0x1f15, 0x080c, 0x1cc7, 0x0904, 0x1ffa, 0x080c, 0x1cc7, 0x0804, - 0x1ffa, 0x782b, 0x0004, 0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, - 0x8aff, 0x1518, 0xa87c, 0xc0f5, 0xa87e, 0x00f8, 0x0026, 0x0036, - 0xab3c, 0xaa40, 0x0016, 0x7910, 0xa82c, 0x9100, 0xa82e, 0x7914, - 0xa830, 0x9101, 0xa832, 0x001e, 0x7810, 0x931a, 0x7814, 0x9213, - 0x7800, 0xa81e, 0x7804, 0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, - 0x080c, 0x2065, 0xa880, 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, - 0xa85a, 0x2c00, 0xa812, 0x7003, 0x0000, 0x2009, 0x0306, 0x200b, - 0x4800, 0x7027, 0x0000, 0x0804, 0x1ffa, 0x00f6, 0x0026, 0x781c, - 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, - 0x0dd5, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, - 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, - 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, - 0x782b, 0x0008, 0x7003, 0x0000, 0x080c, 0x1cc0, 0x0804, 0x1ffa, - 0x8001, 0x7002, 0x7024, 0x8004, 0x7026, 0xd194, 0x0170, 0x782c, - 0xd0fc, 0x1904, 0x1ebb, 0xd19c, 0x1904, 0x1ff6, 0x8aff, 0x0904, - 0x1ffa, 0x080c, 0x1cc7, 0x0804, 0x1ffa, 0x0026, 0x0036, 0xab3c, - 0xaa40, 0x080c, 0x2065, 0xdd9c, 0x1904, 0x1fb5, 0x2c05, 0x908a, - 0x0036, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x1f89, 0x1f89, - 0x1f8b, 0x1f89, 0x1f89, 0x1f89, 0x1f91, 0x1f89, 0x1f89, 0x1f89, - 0x1f97, 0x1f89, 0x1f89, 0x1f89, 0x1f9d, 0x1f89, 0x1f89, 0x1f89, - 0x1fa3, 0x1f89, 0x1f89, 0x1f89, 0x1fa9, 0x1f89, 0x1f89, 0x1f89, - 0x1faf, 0x080c, 0x0dd5, 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, - 0x1eea, 0xa08c, 0x931a, 0xa090, 0x9213, 0x0804, 0x1eea, 0xa09c, - 0x931a, 0xa0a0, 0x9213, 0x0804, 0x1eea, 0xa0ac, 0x931a, 0xa0b0, - 0x9213, 0x0804, 0x1eea, 0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, - 0x1eea, 0xa0cc, 0x931a, 0xa0d0, 0x9213, 0x0804, 0x1eea, 0xa0dc, - 0x931a, 0xa0e0, 0x9213, 0x0804, 0x1eea, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x1fd8, 0x1fd6, 0x1fd6, - 0x1fd6, 0x1fd6, 0x1fd6, 0x1fde, 0x1fd6, 0x1fd6, 0x1fd6, 0x1fd6, - 0x1fd6, 0x1fe4, 0x1fd6, 0x1fd6, 0x1fd6, 0x1fd6, 0x1fd6, 0x1fea, - 0x1fd6, 0x1fd6, 0x1fd6, 0x1fd6, 0x1fd6, 0x1ff0, 0x080c, 0x0dd5, - 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1eea, 0xa094, 0x931a, - 0xa098, 0x9213, 0x0804, 0x1eea, 0xa0ac, 0x931a, 0xa0b0, 0x9213, - 0x0804, 0x1eea, 0xa0c4, 0x931a, 0xa0c8, 0x9213, 0x0804, 0x1eea, - 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, 0x1eea, 0x0804, 0x1ee6, - 0x080c, 0x0dd5, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a65, - 0x7000, 0x9086, 0x0000, 0x0904, 0x2045, 0x2079, 0x0090, 0x2009, - 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, - 0x0003, 0x0188, 0x080c, 0xea2b, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0dd5, 0x0016, 0x2009, 0x0040, 0x080c, 0x23d4, 0x001e, - 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, - 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x23d4, 0x782c, - 0xd0fc, 0x09a8, 0x080c, 0x1eb6, 0x7000, 0x9086, 0x0000, 0x1978, - 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, - 0x23d4, 0x782b, 0x0002, 0x7003, 0x0000, 0x080c, 0x1cc0, 0x00ee, - 0x00fe, 0x0005, 0xa880, 0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, - 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, - 0xa064, 0x9084, 0x000f, 0x9080, 0x2092, 0x2065, 0x8cff, 0x090c, - 0x0dd5, 0x8a51, 0x0005, 0x2050, 0x0005, 0xa880, 0xd0fc, 0x11b8, - 0x8a50, 0x8c61, 0x2c05, 0x9005, 0x1190, 0x2800, 0x9906, 0x0120, - 0xa000, 0x9005, 0x1108, 0x2900, 0x2040, 0xa85a, 0xa064, 0x9084, - 0x000f, 0x9080, 0x20a2, 0x2065, 0x8cff, 0x090c, 0x0dd5, 0x0005, - 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, - 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, - 0x0023, 0x0000, 0x0000, 0x2085, 0x2081, 0x2085, 0x2085, 0x208f, - 0x0000, 0x2085, 0x208c, 0x208c, 0x2089, 0x208c, 0x208c, 0x0000, - 0x208f, 0x208c, 0x0000, 0x2087, 0x2087, 0x0000, 0x2087, 0x208f, - 0x0000, 0x2087, 0x208d, 0x208d, 0x208d, 0x0000, 0x208d, 0x0000, - 0x208f, 0x208d, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, - 0x9055, 0x0904, 0x2291, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, - 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x208d, 0x00d0, 0x9de0, - 0x2092, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, - 0x000f, 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, - 0x1140, 0x0310, 0x0804, 0x2291, 0xa004, 0x9045, 0x0904, 0x2291, - 0x08d8, 0x2c05, 0x9005, 0x0904, 0x2179, 0xdd9c, 0x1904, 0x2135, - 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x210a, - 0x210a, 0x210c, 0x210a, 0x210a, 0x210a, 0x2112, 0x210a, 0x210a, - 0x210a, 0x2118, 0x210a, 0x210a, 0x210a, 0x211e, 0x210a, 0x210a, - 0x210a, 0x2124, 0x210a, 0x210a, 0x210a, 0x212a, 0x210a, 0x210a, - 0x210a, 0x2130, 0x080c, 0x0dd5, 0xa07c, 0x9422, 0xa080, 0x931b, - 0x0804, 0x216f, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x216f, - 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x216f, 0xa0ac, 0x9422, - 0xa0b0, 0x931b, 0x0804, 0x216f, 0xa0bc, 0x9422, 0xa0c0, 0x931b, - 0x0804, 0x216f, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x216f, - 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, - 0x0dd5, 0x9082, 0x001b, 0x0002, 0x2157, 0x2155, 0x2155, 0x2155, - 0x2155, 0x2155, 0x215c, 0x2155, 0x2155, 0x2155, 0x2155, 0x2155, - 0x2161, 0x2155, 0x2155, 0x2155, 0x2155, 0x2155, 0x2166, 0x2155, - 0x2155, 0x2155, 0x2155, 0x2155, 0x216b, 0x080c, 0x0dd5, 0xa07c, - 0x9422, 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, - 0x0070, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, - 0xa0c8, 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, - 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x2291, 0x8c60, 0x0804, - 0x20e1, 0xa004, 0x9045, 0x0904, 0x2291, 0x0804, 0x20bc, 0x8a51, - 0x0904, 0x2291, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, - 0x0904, 0x2291, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x2092, 0x2c05, - 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x2286, 0x2c05, 0x8422, - 0x8420, 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, - 0x2223, 0x9082, 0x001b, 0x0002, 0x21bf, 0x21bf, 0x21c1, 0x21bf, - 0x21bf, 0x21bf, 0x21cf, 0x21bf, 0x21bf, 0x21bf, 0x21dd, 0x21bf, - 0x21bf, 0x21bf, 0x21eb, 0x21bf, 0x21bf, 0x21bf, 0x21f9, 0x21bf, - 0x21bf, 0x21bf, 0x2207, 0x21bf, 0x21bf, 0x21bf, 0x2215, 0x080c, - 0x0dd5, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, - 0x0dd5, 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x2281, 0xa18c, - 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa084, - 0x9420, 0xa088, 0x9319, 0x0804, 0x2281, 0xa19c, 0x2400, 0x9122, - 0xa1a0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa094, 0x9420, 0xa098, - 0x9319, 0x0804, 0x2281, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, - 0x911b, 0x0a0c, 0x0dd5, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, - 0x2281, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, - 0x0dd5, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x2281, 0xa1cc, - 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa0c4, - 0x9420, 0xa0c8, 0x9319, 0x0804, 0x2281, 0xa1dc, 0x2400, 0x9122, - 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa0d4, 0x9420, 0xa0d8, - 0x9319, 0x0804, 0x2281, 0x9082, 0x001b, 0x0002, 0x2241, 0x223f, - 0x223f, 0x223f, 0x223f, 0x223f, 0x224e, 0x223f, 0x223f, 0x223f, - 0x223f, 0x223f, 0x225b, 0x223f, 0x223f, 0x223f, 0x223f, 0x223f, - 0x2268, 0x223f, 0x223f, 0x223f, 0x223f, 0x223f, 0x2275, 0x080c, - 0x0dd5, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, - 0x0dd5, 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, - 0x9122, 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa084, 0x9420, - 0xa088, 0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, - 0x911b, 0x0a0c, 0x0dd5, 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, - 0xa1c4, 0x2400, 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0dd5, - 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, - 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa0cc, 0x9420, 0xa0d0, - 0x9319, 0xac1e, 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, - 0x2c00, 0xa812, 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, - 0x0028, 0x008e, 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, 0x2001, - 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0dce, 0x9084, 0x0007, 0x0002, - 0x22b2, 0x1eb6, 0x22b2, 0x22a8, 0x22ab, 0x22ae, 0x22ab, 0x22ae, - 0x080c, 0x1eb6, 0x0005, 0x080c, 0x11a3, 0x0005, 0x080c, 0x1eb6, - 0x080c, 0x11a3, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, - 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, - 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, - 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, - 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x23d1, - 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, - 0x0002, 0x22f9, 0x22f1, 0x7d86, 0x22f1, 0x22f3, 0x22f3, 0x22f3, - 0x22f3, 0x7d6c, 0x22f1, 0x22f5, 0x22f1, 0x22f3, 0x22f1, 0x22f3, - 0x22f1, 0x080c, 0x0dd5, 0x0031, 0x0020, 0x080c, 0x7d6c, 0x080c, - 0x7d86, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xea2b, 0x7930, - 0x9184, 0x0003, 0x01c0, 0x2001, 0x19f5, 0x2004, 0x9005, 0x0170, - 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dd5, 0x00c6, 0x2001, - 0x19f5, 0x2064, 0x080c, 0xc77b, 0x00ce, 0x00f8, 0x2009, 0x0040, - 0x080c, 0x23d4, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, - 0x0003, 0x0160, 0x080c, 0x73a5, 0x1138, 0x080c, 0x768d, 0x080c, - 0x6023, 0x080c, 0x72d7, 0x0010, 0x080c, 0x5ee2, 0x080c, 0x7e35, - 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, - 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a61, 0x080c, - 0x1aab, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x2e00, 0x2071, 0x1800, 0x7128, 0x2001, 0x196e, 0x2102, 0x2001, - 0x1976, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, - 0x0201, 0x789e, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, - 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, - 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, - 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, - 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, - 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, - 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, - 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, - 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, - 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, - 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, - 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, - 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, - 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, - 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, - 0x0005, 0x7938, 0x080c, 0x0dce, 0x00f6, 0x2079, 0x0200, 0x7902, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, - 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, - 0x080c, 0x2c40, 0x080c, 0x2b5b, 0x6054, 0x8004, 0x8004, 0x8004, - 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, - 0x6050, 0x9084, 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, 0x199c, - 0x2011, 0x199d, 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x2b9f, - 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, - 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, - 0x2b8a, 0x9006, 0x080c, 0x2b6d, 0x20a9, 0x0012, 0x1d04, 0x2426, - 0x2091, 0x6000, 0x1f04, 0x2426, 0x602f, 0x0100, 0x602f, 0x0000, - 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, - 0x080c, 0x2879, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x2889, - 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, - 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x349f, 0x60bb, - 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x2453, 0x60bb, - 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, - 0x0014, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, - 0x001e, 0x600f, 0x006b, 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, - 0x2079, 0x0140, 0x78c3, 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, - 0x00fe, 0x0005, 0x2001, 0x1835, 0x2003, 0x0000, 0x2001, 0x1834, - 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x6124, 0x0066, 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, - 0x006e, 0x1138, 0x6020, 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, - 0x1198, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, - 0x0004, 0x9284, 0x0007, 0x0082, 0x0016, 0x2001, 0x188b, 0x200c, - 0xd184, 0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, 0x188b, 0x200c, - 0xd194, 0x001e, 0x0d30, 0x0c58, 0x24d6, 0x24bc, 0x24bf, 0x24c2, - 0x24c7, 0x24c9, 0x24cd, 0x24d1, 0x080c, 0x8fbe, 0x00b8, 0x080c, - 0x908b, 0x00a0, 0x080c, 0x908b, 0x080c, 0x8fbe, 0x0078, 0x0099, - 0x0068, 0x080c, 0x8fbe, 0x0079, 0x0048, 0x080c, 0x908b, 0x0059, - 0x0028, 0x080c, 0x908b, 0x080c, 0x8fbe, 0x0029, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, - 0xd19c, 0x1904, 0x273e, 0xd1f4, 0x190c, 0x0dce, 0x080c, 0x73a5, - 0x0904, 0x2531, 0x080c, 0xd24a, 0x1120, 0x7000, 0x9086, 0x0003, - 0x0570, 0x6024, 0x9084, 0x1800, 0x0550, 0x080c, 0x73c8, 0x0118, - 0x080c, 0x73b6, 0x1520, 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, - 0xd24a, 0x0168, 0x080c, 0x73c8, 0x1150, 0x2001, 0x19a6, 0x2003, - 0x0001, 0x6027, 0x1800, 0x080c, 0x723b, 0x0804, 0x2741, 0x70a4, - 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, - 0x73fc, 0x00de, 0x1904, 0x2741, 0x080c, 0x7697, 0x0428, 0x080c, - 0x73c8, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, - 0x7697, 0x080c, 0x768d, 0x080c, 0x6023, 0x080c, 0x72d7, 0x0804, - 0x273e, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, - 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, 0x9086, 0x0028, 0x1110, - 0x080c, 0x757a, 0x0804, 0x273e, 0x080c, 0x7692, 0x0048, 0x2001, - 0x197c, 0x2003, 0x0002, 0x0020, 0x080c, 0x74df, 0x0804, 0x273e, - 0x080c, 0x7615, 0x0804, 0x273e, 0x6220, 0xd1bc, 0x0138, 0xd2bc, - 0x1904, 0x27b1, 0xd2b4, 0x1904, 0x27c4, 0x0000, 0xd1ac, 0x0904, - 0x2653, 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e, 0x080c, 0x73a5, - 0x11c0, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x73bf, - 0x1158, 0x080c, 0x768d, 0x080c, 0x6023, 0x080c, 0x72d7, 0x003e, - 0x002e, 0x000e, 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, - 0x737d, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, - 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74da, - 0x948c, 0xff00, 0x7038, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, - 0x7048, 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, - 0x8016, 0x080c, 0x4b14, 0x003e, 0x080c, 0xd243, 0x1904, 0x2630, - 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, - 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x331b, - 0x0128, 0xc18d, 0x7132, 0x080c, 0x6973, 0x1510, 0x6240, 0x9294, - 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, - 0x7030, 0xd08c, 0x0904, 0x2630, 0x7038, 0xd08c, 0x1140, 0x2001, - 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2630, 0xc1ad, 0x2102, 0x0036, - 0x73d8, 0x2011, 0x8013, 0x080c, 0x4b14, 0x003e, 0x0804, 0x2630, - 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, - 0x2630, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, - 0x4b14, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, - 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, - 0x86c6, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xe543, - 0x00ce, 0x9484, 0x00ff, 0x9080, 0x3327, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xe5cf, 0x001e, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x318c, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6608, - 0x1110, 0x080c, 0x603d, 0x8108, 0x1f04, 0x2626, 0x00be, 0x015e, - 0x00ce, 0x004e, 0x080c, 0xade2, 0x60e3, 0x0000, 0x001e, 0x2001, - 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, - 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, - 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x1826, 0x2003, - 0x0000, 0x6027, 0x0020, 0xd194, 0x0904, 0x273e, 0x0016, 0x6220, - 0xd2b4, 0x0904, 0x26db, 0x080c, 0x8562, 0x080c, 0xa274, 0x6027, - 0x0004, 0x00f6, 0x2019, 0x19ef, 0x2304, 0x907d, 0x0904, 0x26aa, - 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, - 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, - 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, - 0x8001, 0x1df0, 0x080c, 0x2d01, 0x2001, 0x001e, 0x8001, 0x0240, - 0x20a9, 0x0009, 0x080c, 0x2c1b, 0x6904, 0xd1dc, 0x1140, 0x0cb0, - 0x2001, 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x080c, - 0x957b, 0x080c, 0x9687, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, - 0x080c, 0xae71, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, - 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2d01, 0x00de, 0x00c6, 0x2061, 0x19e6, - 0x6028, 0x080c, 0xd24a, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, - 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0xa250, - 0x0804, 0x273d, 0x2061, 0x0100, 0x62c0, 0x080c, 0xac68, 0x2019, - 0x19ef, 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0xaeec, - 0x00ce, 0x0804, 0x273d, 0xd2bc, 0x0904, 0x2724, 0x080c, 0x856f, - 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, - 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, - 0x2d01, 0x00de, 0x00c6, 0x2061, 0x19e6, 0x6044, 0x080c, 0xd24a, - 0x0120, 0x909a, 0x0003, 0x1658, 0x0018, 0x909a, 0x00c8, 0x1638, - 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, - 0x080c, 0x8567, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, - 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, 0x6116, 0x0430, 0x9080, - 0x0008, 0x2004, 0x9086, 0x0009, 0x0d98, 0x6114, 0x918c, 0x1984, - 0x918d, 0x0016, 0x6116, 0x00c8, 0x6027, 0x0004, 0x00b0, 0x0036, - 0x2019, 0x0001, 0x080c, 0xa5b7, 0x003e, 0x2019, 0x19f5, 0x2304, - 0x9065, 0x0150, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, - 0x2009, 0x004f, 0x080c, 0xaeec, 0x00ce, 0x001e, 0xd19c, 0x0904, - 0x27ac, 0x7038, 0xd0ac, 0x1904, 0x2785, 0x0016, 0x0156, 0x6027, - 0x0008, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, 0xfbcf, - 0x6052, 0x080c, 0x2c3a, 0x9085, 0x2000, 0x6052, 0x20a9, 0x0012, - 0x1d04, 0x2758, 0x080c, 0x8596, 0x1f04, 0x2758, 0x6050, 0x9085, - 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, 0x1f04, - 0x2766, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, - 0x276f, 0x080c, 0x8596, 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, - 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x2c02, 0x1f04, 0x276f, - 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, - 0x602a, 0x080c, 0xade2, 0x60e3, 0x0000, 0x080c, 0xea0a, 0x080c, - 0xea25, 0x080c, 0x56dc, 0xd0fc, 0x1138, 0x080c, 0xd243, 0x1120, - 0x9085, 0x0001, 0x080c, 0x73ec, 0x9006, 0x080c, 0x2cf1, 0x2009, - 0x0002, 0x080c, 0x2c40, 0x2001, 0x1800, 0x2003, 0x0004, 0x6027, - 0x0008, 0x080c, 0x0bae, 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, - 0x0005, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0904, - 0x255e, 0x0016, 0x2009, 0x27bd, 0x00d0, 0x2001, 0x188b, 0x200c, - 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, 0x188b, 0x200c, - 0xd194, 0x001e, 0x0904, 0x255e, 0x0016, 0x2009, 0x27d0, 0x0038, - 0x2001, 0x188b, 0x200c, 0xc194, 0x2102, 0x001e, 0x08a8, 0x6028, - 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003, - 0xffff, 0x6043, 0x0001, 0x080c, 0x2c3a, 0x6027, 0x0080, 0x6017, - 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, - 0x70d2, 0x9116, 0x05e8, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, - 0x2c40, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, - 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x4b14, - 0x0438, 0x2001, 0x19a7, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, - 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, - 0x8012, 0x080c, 0x4b14, 0x080c, 0x56dc, 0xd0fc, 0x1188, 0x080c, - 0xd243, 0x1170, 0x00c6, 0x080c, 0x28d4, 0x080c, 0xa51e, 0x2061, - 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x318c, 0x00ce, - 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, - 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, - 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181f, - 0x2204, 0x9106, 0x1190, 0x2011, 0x1820, 0x2214, 0x9294, 0xff00, - 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, 0x1820, 0x2214, 0x9294, - 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, 0x2500, 0x080c, 0x80a7, - 0x0048, 0x9584, 0x00ff, 0x9080, 0x3327, 0x200d, 0x918c, 0xff00, - 0x810f, 0x9006, 0x0005, 0x9080, 0x3327, 0x200d, 0x918c, 0x00ff, - 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1818, 0x2003, 0x00ef, - 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x2884, 0x00de, - 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1818, - 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, - 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xf1d7, - 0x2005, 0x6856, 0x8211, 0x1f04, 0x2899, 0x002e, 0x00de, 0x000e, - 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, 0x0110, 0xc09d, 0x0008, - 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, - 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, - 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, - 0x0404, 0x680e, 0x1f04, 0x28c9, 0x680f, 0x0000, 0x000e, 0x001e, - 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, 0x56d8, 0xd0c4, 0x0150, - 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, - 0xe5cf, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, - 0x78c4, 0xd0dc, 0x0904, 0x2940, 0x080c, 0x2b9f, 0x0660, 0x9084, - 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, - 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, - 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, - 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, - 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, - 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, - 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, - 0x8f51, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, - 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x73a5, - 0x1118, 0x2009, 0x196c, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, - 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, - 0x0110, 0x080c, 0x0dce, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, - 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, - 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, - 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, - 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, - 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, - 0x00e6, 0x2001, 0x198f, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dd5, - 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x299e, - 0x29bc, 0x29e0, 0x29e2, 0x2a0b, 0x2a0d, 0x2a0f, 0x2001, 0x0001, - 0x080c, 0x27ec, 0x080c, 0x2bfd, 0x2001, 0x1991, 0x2003, 0x0000, - 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, - 0x2bbb, 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2a10, 0x080c, 0x8574, 0x0005, 0x2009, 0x1994, 0x200b, 0x0000, - 0x2001, 0x1999, 0x2003, 0x0036, 0x2001, 0x1998, 0x2003, 0x002a, - 0x2001, 0x1991, 0x2003, 0x0001, 0x9006, 0x080c, 0x2b6d, 0x2001, - 0xffff, 0x20a9, 0x0009, 0x080c, 0x2bbb, 0x2001, 0x198f, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2a10, 0x080c, 0x8574, 0x0005, - 0x080c, 0x0dd5, 0x2001, 0x1999, 0x2003, 0x0036, 0x2001, 0x1991, - 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2b6d, 0x2001, 0x1995, - 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2bbb, - 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2a10, - 0x080c, 0x8574, 0x0005, 0x080c, 0x0dd5, 0x080c, 0x0dd5, 0x0005, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, - 0x8000, 0x2079, 0x0100, 0x2001, 0x1991, 0x2004, 0x908a, 0x0007, - 0x1a0c, 0x0dd5, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, - 0x001e, 0x000e, 0x0005, 0x2a32, 0x2a52, 0x2a92, 0x2ac2, 0x2ae6, - 0x2af6, 0x2af8, 0x080c, 0x2baf, 0x11b0, 0x7850, 0x9084, 0xefff, - 0x7852, 0x2009, 0x1997, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x198f, - 0x2003, 0x0001, 0x0030, 0x080c, 0x2b1c, 0x2001, 0xffff, 0x080c, - 0x29ad, 0x0005, 0x080c, 0x2afa, 0x05e0, 0x2009, 0x1998, 0x2104, - 0x8001, 0x200a, 0x080c, 0x2baf, 0x1178, 0x7850, 0x9084, 0xefff, - 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, - 0x1997, 0x2104, 0xc085, 0x200a, 0x2009, 0x1994, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x2b02, 0x00c0, 0x200b, - 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2b8a, 0x2001, 0x1991, 0x2003, - 0x0002, 0x0028, 0x2001, 0x198f, 0x2003, 0x0003, 0x0010, 0x080c, - 0x29cf, 0x0005, 0x080c, 0x2afa, 0x0560, 0x2009, 0x1998, 0x2104, - 0x8001, 0x200a, 0x080c, 0x2baf, 0x1168, 0x7850, 0x9084, 0xefff, - 0x7852, 0x2001, 0x198f, 0x2003, 0x0003, 0x2001, 0x1990, 0x2003, - 0x0000, 0x00b8, 0x2009, 0x1998, 0x2104, 0x9005, 0x1118, 0x080c, - 0x2b3f, 0x0010, 0x080c, 0x2b0f, 0x080c, 0x2b02, 0x2009, 0x1994, - 0x200b, 0x0000, 0x2001, 0x1991, 0x2003, 0x0001, 0x080c, 0x29cf, - 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x2baf, 0x11b8, 0x7850, - 0x9084, 0xefff, 0x7852, 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, - 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x199a, 0x2003, 0x000a, - 0x2009, 0x1997, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, - 0x1991, 0x2003, 0x0004, 0x080c, 0x29fa, 0x0005, 0x0099, 0x0168, - 0x080c, 0x2baf, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, - 0x29e6, 0x0018, 0x0079, 0x080c, 0x29fa, 0x0005, 0x080c, 0x0dd5, - 0x080c, 0x0dd5, 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x090c, - 0x2b5b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2b8a, 0x0005, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2b6d, 0x0005, 0x2009, 0x1994, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2b8a, 0x0005, 0x0086, - 0x2001, 0x1997, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dd5, 0x2009, - 0x1996, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, - 0xd084, 0x1120, 0x080c, 0x0dd5, 0x9006, 0x0010, 0x2001, 0x0001, - 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x198f, 0x20a9, - 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x2b61, 0x2001, 0x1996, - 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, - 0x783a, 0x2009, 0x199c, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199d, 0x210c, 0x795a, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, - 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, - 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, - 0x20a9, 0x0064, 0x7820, 0x080c, 0x2c3a, 0xd09c, 0x1110, 0x1f04, - 0x2bb2, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, - 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, - 0x080c, 0x2c3a, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, - 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, - 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, - 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, - 0x1d04, 0x2be8, 0x080c, 0x8596, 0x1f04, 0x2be8, 0x7850, 0x9085, - 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2c3a, 0x9085, 0x1000, - 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, - 0x7852, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, - 0x000a, 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, - 0x2c0c, 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2c12, 0x00fe, - 0x015e, 0x000e, 0x0005, 0x1d04, 0x2c1b, 0x080c, 0x8596, 0x1f04, - 0x2c1b, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0000, - 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0001, - 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0002, - 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, - 0x0006, 0x2001, 0x19a7, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, - 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, - 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, - 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, - 0x1588, 0x2009, 0x00a2, 0x080c, 0x0e51, 0x2019, 0x0160, 0x2324, - 0x2011, 0x0003, 0x2009, 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, - 0x918c, 0x0007, 0x910e, 0x1db0, 0x9086, 0x0003, 0x11b8, 0x2304, - 0x9402, 0x02a0, 0x1d60, 0x8211, 0x1d68, 0x84ff, 0x0170, 0x2001, - 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, - 0x180c, 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0419, 0x2009, 0x0000, - 0x080c, 0x0e51, 0x004e, 0x003e, 0x0005, 0x2001, 0x180c, 0x2004, - 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, - 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, - 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, - 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, - 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, - 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, - 0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016, - 0x2019, 0x0141, 0x6124, 0x918c, 0x0028, 0x1120, 0x2304, 0x9084, - 0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, - 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, - 0x6016, 0x003e, 0x2001, 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce, - 0x0005, 0x0016, 0x0026, 0x080c, 0x73bf, 0x0108, 0xc0bc, 0x2009, - 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, - 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, - 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x73bf, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, - 0x001e, 0x000e, 0x0005, 0x2f97, 0x2f97, 0x2dbb, 0x2dbb, 0x2dc7, - 0x2dc7, 0x2dd3, 0x2dd3, 0x2de1, 0x2de1, 0x2ded, 0x2ded, 0x2dfb, - 0x2dfb, 0x2e09, 0x2e09, 0x2e1b, 0x2e1b, 0x2e27, 0x2e27, 0x2e35, - 0x2e35, 0x2e53, 0x2e53, 0x2e73, 0x2e73, 0x2e43, 0x2e43, 0x2e63, - 0x2e63, 0x2e81, 0x2e81, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e93, 0x2e93, 0x2e9f, 0x2e9f, 0x2ead, - 0x2ead, 0x2ebb, 0x2ebb, 0x2ecb, 0x2ecb, 0x2ed9, 0x2ed9, 0x2ee9, - 0x2ee9, 0x2ef9, 0x2ef9, 0x2f0b, 0x2f0b, 0x2f19, 0x2f19, 0x2f29, - 0x2f29, 0x2f4b, 0x2f4b, 0x2f6d, 0x2f6d, 0x2f39, 0x2f39, 0x2f5c, - 0x2f5c, 0x2f7c, 0x2f7c, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, 0x2e19, - 0x2e19, 0x2e19, 0x2e19, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2483, 0x0804, 0x2f8f, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2297, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2297, 0x080c, 0x2483, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2483, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2297, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2297, 0x080c, 0x2483, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1380, 0x0804, 0x2f8f, 0x0106, + 0xa001, 0xa001, 0x8211, 0x1de0, 0x0059, 0x0804, 0x7463, 0x0479, + 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, + 0x00e6, 0x2071, 0x0200, 0x080c, 0x2c51, 0x2009, 0x003c, 0x080c, + 0x23df, 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, + 0x1de0, 0x080c, 0x841a, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, + 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, + 0x080c, 0x1313, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, + 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, + 0x0000, 0x080c, 0x73b3, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, + 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, + 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, + 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, + 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, + 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, + 0xc084, 0x601e, 0x0005, 0x2c08, 0x621c, 0x080c, 0x15f0, 0x7930, + 0x0005, 0x2c08, 0x621c, 0x080c, 0x169b, 0x7930, 0x0005, 0x8001, + 0x1df0, 0x0005, 0x2031, 0x0005, 0x781c, 0x9084, 0x0007, 0x0170, + 0x2001, 0x0038, 0x0c41, 0x9186, 0x0040, 0x0904, 0x1bb0, 0x2001, + 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, 0x0dd5, 0x781f, 0x0202, + 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0b10, 0x0c01, 0x781c, + 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, + 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, + 0x0014, 0x0869, 0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, + 0x2001, 0x0030, 0x080c, 0x1b49, 0x9186, 0x0040, 0x190c, 0x0dd5, + 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, + 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, + 0x6908, 0x9184, 0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, + 0x9184, 0x0007, 0x090c, 0x0dd5, 0xa001, 0xa001, 0x781f, 0x0200, + 0x0005, 0x0126, 0x2091, 0x2400, 0x2071, 0x1a65, 0x2079, 0x0090, + 0x012e, 0x0005, 0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, + 0x1904, 0x1c52, 0xa964, 0x9184, 0x0007, 0x0002, 0x1bce, 0x1c3d, + 0x1be5, 0x1be7, 0x1be5, 0x1c25, 0x1c05, 0x1bf4, 0x918c, 0x00ff, + 0x9186, 0x0008, 0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1e7c, 0x9006, + 0xa842, 0xa83e, 0xa988, 0x2900, 0xa85a, 0xa813, 0x2098, 0x0804, + 0x1c4e, 0x9186, 0x0048, 0x0904, 0x1c3d, 0x080c, 0x0dd5, 0x9184, + 0x00ff, 0x9086, 0x0013, 0x0904, 0x1c3d, 0x9184, 0x00ff, 0x9086, + 0x001b, 0x0904, 0x1c3d, 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1e7c, + 0xa890, 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, + 0xa8b0, 0xa84a, 0xa988, 0x0804, 0x1c45, 0xa864, 0x9084, 0x00ff, + 0x9086, 0x001e, 0x19d0, 0xa87c, 0xd0b4, 0x0904, 0x1e7c, 0xa890, + 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, + 0xa84a, 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, + 0x209d, 0x2005, 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, + 0x0015, 0x1540, 0xa87c, 0xd0b4, 0x0904, 0x1e7c, 0xa804, 0xa85a, + 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x209d, 0x2005, 0xa812, + 0xa988, 0x9006, 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, + 0x1e7c, 0xa988, 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, + 0x9084, 0x000f, 0x9080, 0x209d, 0x2005, 0xa812, 0xa916, 0xa87c, + 0xc0dd, 0xa87e, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, + 0x190c, 0x1ec1, 0x00e6, 0x2071, 0x1a65, 0x7000, 0x9005, 0x1904, + 0x1cbb, 0x7206, 0x9280, 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, + 0x782b, 0x0004, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, + 0x00b6, 0x2058, 0xb86c, 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, + 0x0200, 0x7803, 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0xa001, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0xa814, + 0x2050, 0xa858, 0x2040, 0xa810, 0x2060, 0xa064, 0x90ec, 0x000f, + 0xa944, 0x791a, 0x7116, 0xa848, 0x781e, 0x701a, 0x9006, 0x700e, + 0x7012, 0x7004, 0xa940, 0xa838, 0x9106, 0x1500, 0xa93c, 0xa834, + 0x9106, 0x11e0, 0x0006, 0x0016, 0xa938, 0xa834, 0x9105, 0x0118, + 0x001e, 0x000e, 0x0098, 0x001e, 0x000e, 0x8aff, 0x01c8, 0x0126, + 0x2091, 0x8000, 0x2009, 0x0306, 0x200b, 0x0808, 0x00d9, 0x0108, + 0x00c9, 0x012e, 0x9006, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, + 0xab38, 0xac34, 0x080c, 0x20bd, 0x004e, 0x003e, 0x0d30, 0x0c98, + 0x9085, 0x0001, 0x0c80, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, + 0x0000, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, + 0x8aff, 0x0904, 0x1e75, 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, + 0x9203, 0x0a04, 0x1e74, 0x9705, 0x0904, 0x1e74, 0x903e, 0x2730, + 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1dfe, 0x1d3d, 0x1d3d, + 0x1dfe, 0x1dfe, 0x1ddb, 0x1dfe, 0x1d3d, 0x1de2, 0x1d8c, 0x1d8c, + 0x1dfe, 0x1dfe, 0x1dfe, 0x1dd5, 0x1d8c, 0xc0fc, 0xa882, 0xab2c, + 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1e0b, 0x2c05, 0x908a, + 0x0034, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x1d29, 0x1d27, + 0x1d27, 0x1d27, 0x1d27, 0x1d27, 0x1d2d, 0x1d27, 0x1d27, 0x1d27, + 0x1d27, 0x1d27, 0x1d31, 0x1d27, 0x1d27, 0x1d27, 0x1d27, 0x1d27, + 0x1d35, 0x1d27, 0x1d27, 0x1d27, 0x1d27, 0x1d27, 0x1d39, 0x080c, + 0x0dd5, 0xa774, 0xa678, 0x0804, 0x1e0b, 0xa78c, 0xa690, 0x0804, + 0x1e0b, 0xa7a4, 0xa6a8, 0x0804, 0x1e0b, 0xa7bc, 0xa6c0, 0x0804, + 0x1e0b, 0xa7d4, 0xa6d8, 0x0804, 0x1e0b, 0x2c05, 0x908a, 0x0036, + 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x1d60, 0x1d60, 0x1d62, + 0x1d60, 0x1d60, 0x1d60, 0x1d68, 0x1d60, 0x1d60, 0x1d60, 0x1d6e, + 0x1d60, 0x1d60, 0x1d60, 0x1d74, 0x1d60, 0x1d60, 0x1d60, 0x1d7a, + 0x1d60, 0x1d60, 0x1d60, 0x1d80, 0x1d60, 0x1d60, 0x1d60, 0x1d86, + 0x080c, 0x0dd5, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, 0x1e0b, + 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x1e0b, 0xa594, 0xa498, + 0xa39c, 0xa2a0, 0x0804, 0x1e0b, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, + 0x0804, 0x1e0b, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1e0b, + 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1e0b, 0xa5d4, 0xa4d8, + 0xa3dc, 0xa2e0, 0x0804, 0x1e0b, 0x2c05, 0x908a, 0x0034, 0x1a0c, + 0x0dd5, 0x9082, 0x001b, 0x0002, 0x1daf, 0x1dad, 0x1dad, 0x1dad, + 0x1dad, 0x1dad, 0x1db7, 0x1dad, 0x1dad, 0x1dad, 0x1dad, 0x1dad, + 0x1dbf, 0x1dad, 0x1dad, 0x1dad, 0x1dad, 0x1dad, 0x1dc7, 0x1dad, + 0x1dad, 0x1dad, 0x1dad, 0x1dad, 0x1dce, 0x080c, 0x0dd5, 0xa56c, + 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0804, 0x1e0b, 0xa584, + 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0804, 0x1e0b, 0xa59c, + 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e0b, 0xa5b4, + 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, + 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x04b0, 0xa864, 0x9084, 0x00ff, + 0x9086, 0x001e, 0x1518, 0x080c, 0x2055, 0x1904, 0x1cd8, 0x900e, + 0x0804, 0x1e75, 0xab64, 0x939c, 0x00ff, 0x9386, 0x0048, 0x1180, + 0x00c6, 0x7004, 0x2060, 0x6004, 0x9086, 0x0043, 0x00ce, 0x0904, + 0x1d8c, 0xab9c, 0x9016, 0xad8c, 0xac90, 0xaf94, 0xae98, 0x0098, + 0x9386, 0x0008, 0x0904, 0x1d8c, 0x080c, 0x0dd5, 0xa964, 0x918c, + 0x00ff, 0x9186, 0x0013, 0x0904, 0x1d3d, 0x9186, 0x001b, 0x0904, + 0x1d8c, 0x080c, 0x0dd5, 0x2009, 0x030f, 0x2104, 0xd0fc, 0x0530, + 0x0066, 0x2009, 0x0306, 0x2104, 0x9084, 0x0030, 0x15c8, 0x2031, + 0x1000, 0x200b, 0x4000, 0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, + 0xa932, 0x0278, 0x9105, 0x0168, 0x2011, 0x0000, 0x2618, 0x2600, + 0x9500, 0xa81e, 0x9481, 0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, + 0x0020, 0xa82f, 0x0000, 0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, + 0x7d02, 0x7c06, 0x7f0a, 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, + 0x7002, 0xa83c, 0x9300, 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, + 0x9300, 0x700e, 0x7010, 0x9201, 0x7012, 0x080c, 0x2055, 0x0428, + 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, 0x9632, 0x7124, 0x7000, + 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, 0x2009, 0x0306, 0x2104, + 0xd0b4, 0x1904, 0x1e1b, 0x200b, 0x4040, 0x2009, 0x1a7e, 0x2104, + 0x8000, 0x0a04, 0x1e1b, 0x200a, 0x0804, 0x1e1b, 0xc18d, 0x7126, + 0xd184, 0x1d58, 0x0804, 0x1e1b, 0x9006, 0x002e, 0x003e, 0x004e, + 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0dd5, 0x0026, 0x2001, + 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, + 0x0016, 0x080c, 0x1ccb, 0x001e, 0x2060, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, + 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, + 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, 0xa896, 0x7004, + 0x2060, 0x00c6, 0x080c, 0xc77b, 0x00ce, 0x2001, 0x19f5, 0x2004, + 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, 0x23df, 0x080c, 0xa7b7, + 0x2011, 0x0000, 0x080c, 0xa648, 0x080c, 0x97d4, 0x002e, 0x0804, + 0x2005, 0x0126, 0x2091, 0x2400, 0xa858, 0x2040, 0x792c, 0x782b, + 0x0002, 0x9184, 0x0700, 0x1904, 0x1e7e, 0x7000, 0x0002, 0x2005, + 0x1ed3, 0x1f53, 0x2003, 0x8001, 0x7002, 0x7027, 0x0000, 0xd19c, + 0x1158, 0x8aff, 0x0904, 0x1f20, 0x080c, 0x1cd2, 0x0904, 0x2005, + 0x080c, 0x1cd2, 0x0804, 0x2005, 0x782b, 0x0004, 0xd194, 0x0148, + 0xa880, 0xc0fc, 0xa882, 0x8aff, 0x1518, 0xa87c, 0xc0f5, 0xa87e, + 0x00f8, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x0016, 0x7910, 0xa82c, + 0x9100, 0xa82e, 0x7914, 0xa830, 0x9101, 0xa832, 0x001e, 0x7810, + 0x931a, 0x7814, 0x9213, 0x7800, 0xa81e, 0x7804, 0xa822, 0xab3e, + 0xaa42, 0x003e, 0x002e, 0x080c, 0x2070, 0xa880, 0xc0fd, 0xa882, + 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, 0xa812, 0x7003, 0x0000, + 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0804, 0x2005, + 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, + 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, + 0x1000, 0x8319, 0x090c, 0x0dd5, 0x7820, 0xd0bc, 0x1dd0, 0x003e, + 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, + 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, + 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, 0x0000, 0x080c, + 0x1ccb, 0x0804, 0x2005, 0x8001, 0x7002, 0x7024, 0x8004, 0x7026, + 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, 0x1ec6, 0xd19c, 0x1904, + 0x2001, 0x8aff, 0x0904, 0x2005, 0x080c, 0x1cd2, 0x0804, 0x2005, + 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, 0x2070, 0xdd9c, 0x1904, + 0x1fc0, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x9082, 0x001b, + 0x0002, 0x1f94, 0x1f94, 0x1f96, 0x1f94, 0x1f94, 0x1f94, 0x1f9c, + 0x1f94, 0x1f94, 0x1f94, 0x1fa2, 0x1f94, 0x1f94, 0x1f94, 0x1fa8, + 0x1f94, 0x1f94, 0x1f94, 0x1fae, 0x1f94, 0x1f94, 0x1f94, 0x1fb4, + 0x1f94, 0x1f94, 0x1f94, 0x1fba, 0x080c, 0x0dd5, 0xa07c, 0x931a, + 0xa080, 0x9213, 0x0804, 0x1ef5, 0xa08c, 0x931a, 0xa090, 0x9213, + 0x0804, 0x1ef5, 0xa09c, 0x931a, 0xa0a0, 0x9213, 0x0804, 0x1ef5, + 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1ef5, 0xa0bc, 0x931a, + 0xa0c0, 0x9213, 0x0804, 0x1ef5, 0xa0cc, 0x931a, 0xa0d0, 0x9213, + 0x0804, 0x1ef5, 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, 0x1ef5, + 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, + 0x1fe3, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe9, 0x1fe1, + 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fef, 0x1fe1, 0x1fe1, 0x1fe1, + 0x1fe1, 0x1fe1, 0x1ff5, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe1, 0x1fe1, + 0x1ffb, 0x080c, 0x0dd5, 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, + 0x1ef5, 0xa094, 0x931a, 0xa098, 0x9213, 0x0804, 0x1ef5, 0xa0ac, + 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1ef5, 0xa0c4, 0x931a, 0xa0c8, + 0x9213, 0x0804, 0x1ef5, 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, + 0x1ef5, 0x0804, 0x1ef1, 0x080c, 0x0dd5, 0x012e, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0x1a65, 0x7000, 0x9086, 0x0000, 0x0904, 0x2050, + 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, + 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xea45, 0x2001, + 0x0133, 0x2004, 0x9005, 0x090c, 0x0dd5, 0x0016, 0x2009, 0x0040, + 0x080c, 0x23df, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, + 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, + 0x080c, 0x23df, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x1ec1, 0x7000, + 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, + 0x2009, 0x0040, 0x080c, 0x23df, 0x782b, 0x0002, 0x7003, 0x0000, + 0x080c, 0x1ccb, 0x00ee, 0x00fe, 0x0005, 0xa880, 0xd0fc, 0x11a8, + 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, + 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x209d, + 0x2065, 0x8cff, 0x090c, 0x0dd5, 0x8a51, 0x0005, 0x2050, 0x0005, + 0xa880, 0xd0fc, 0x11b8, 0x8a50, 0x8c61, 0x2c05, 0x9005, 0x1190, + 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, 0x1108, 0x2900, 0x2040, + 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, 0x20ad, 0x2065, 0x8cff, + 0x090c, 0x0dd5, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, + 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, + 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x2090, 0x208c, + 0x2090, 0x2090, 0x209a, 0x0000, 0x2090, 0x2097, 0x2097, 0x2094, + 0x2097, 0x2097, 0x0000, 0x209a, 0x2097, 0x0000, 0x2092, 0x2092, + 0x0000, 0x2092, 0x209a, 0x0000, 0x2092, 0x2098, 0x2098, 0x2098, + 0x0000, 0x2098, 0x0000, 0x209a, 0x2098, 0x00c6, 0x00d6, 0x0086, + 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x229c, 0x2940, 0xa064, + 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, + 0x2098, 0x00d0, 0x9de0, 0x209d, 0x9d86, 0x0007, 0x0130, 0x9d86, + 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, 0xa090, + 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, 0x229c, 0xa004, + 0x9045, 0x0904, 0x229c, 0x08d8, 0x2c05, 0x9005, 0x0904, 0x2184, + 0xdd9c, 0x1904, 0x2140, 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x9082, + 0x001b, 0x0002, 0x2115, 0x2115, 0x2117, 0x2115, 0x2115, 0x2115, + 0x211d, 0x2115, 0x2115, 0x2115, 0x2123, 0x2115, 0x2115, 0x2115, + 0x2129, 0x2115, 0x2115, 0x2115, 0x212f, 0x2115, 0x2115, 0x2115, + 0x2135, 0x2115, 0x2115, 0x2115, 0x213b, 0x080c, 0x0dd5, 0xa07c, + 0x9422, 0xa080, 0x931b, 0x0804, 0x217a, 0xa08c, 0x9422, 0xa090, + 0x931b, 0x0804, 0x217a, 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, + 0x217a, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, 0x217a, 0xa0bc, + 0x9422, 0xa0c0, 0x931b, 0x0804, 0x217a, 0xa0cc, 0x9422, 0xa0d0, + 0x931b, 0x0804, 0x217a, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, + 0x908a, 0x0034, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x2162, + 0x2160, 0x2160, 0x2160, 0x2160, 0x2160, 0x2167, 0x2160, 0x2160, + 0x2160, 0x2160, 0x2160, 0x216c, 0x2160, 0x2160, 0x2160, 0x2160, + 0x2160, 0x2171, 0x2160, 0x2160, 0x2160, 0x2160, 0x2160, 0x2176, + 0x080c, 0x0dd5, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0098, 0xa094, + 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422, 0xa0b0, 0x931b, + 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020, 0xa0dc, 0x9422, + 0xa0e0, 0x931b, 0x0630, 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, + 0x229c, 0x8c60, 0x0804, 0x20ec, 0xa004, 0x9045, 0x0904, 0x229c, + 0x0804, 0x20c7, 0x8a51, 0x0904, 0x229c, 0x8c60, 0x2c05, 0x9005, + 0x1158, 0xa004, 0x9045, 0x0904, 0x229c, 0xa064, 0x90ec, 0x000f, + 0x9de0, 0x209d, 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, + 0x2291, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, 0xac2e, + 0xab32, 0xdd9c, 0x1904, 0x222e, 0x9082, 0x001b, 0x0002, 0x21ca, + 0x21ca, 0x21cc, 0x21ca, 0x21ca, 0x21ca, 0x21da, 0x21ca, 0x21ca, + 0x21ca, 0x21e8, 0x21ca, 0x21ca, 0x21ca, 0x21f6, 0x21ca, 0x21ca, + 0x21ca, 0x2204, 0x21ca, 0x21ca, 0x21ca, 0x2212, 0x21ca, 0x21ca, + 0x21ca, 0x2220, 0x080c, 0x0dd5, 0xa17c, 0x2400, 0x9122, 0xa180, + 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa074, 0x9420, 0xa078, 0x9319, + 0x0804, 0x228c, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, + 0x0a0c, 0x0dd5, 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, 0x228c, + 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, + 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x228c, 0xa1ac, 0x2400, + 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa0a4, 0x9420, + 0xa0a8, 0x9319, 0x0804, 0x228c, 0xa1bc, 0x2400, 0x9122, 0xa1c0, + 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa0b4, 0x9420, 0xa0b8, 0x9319, + 0x0804, 0x228c, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, + 0x0a0c, 0x0dd5, 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, 0x228c, + 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, + 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x228c, 0x9082, 0x001b, + 0x0002, 0x224c, 0x224a, 0x224a, 0x224a, 0x224a, 0x224a, 0x2259, + 0x224a, 0x224a, 0x224a, 0x224a, 0x224a, 0x2266, 0x224a, 0x224a, + 0x224a, 0x224a, 0x224a, 0x2273, 0x224a, 0x224a, 0x224a, 0x224a, + 0x224a, 0x2280, 0x080c, 0x0dd5, 0xa17c, 0x2400, 0x9122, 0xa180, + 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa06c, 0x9420, 0xa070, 0x9319, + 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, 0x0a0c, + 0x0dd5, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, 0xa1ac, 0x2400, + 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, 0xa09c, 0x9420, + 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122, 0xa1c8, 0x2300, + 0x911b, 0x0a0c, 0x0dd5, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0060, + 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0dd5, + 0xa0cc, 0x9420, 0xa0d0, 0x9319, 0xac1e, 0xab22, 0xa880, 0xc0fd, + 0xa882, 0x2800, 0xa85a, 0x2c00, 0xa812, 0x2a00, 0xa816, 0x000e, + 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x00de, 0x00ce, 0x9085, + 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0dce, + 0x9084, 0x0007, 0x0002, 0x22bd, 0x1ec1, 0x22bd, 0x22b3, 0x22b6, + 0x22b9, 0x22b6, 0x22b9, 0x080c, 0x1ec1, 0x0005, 0x080c, 0x11a3, + 0x0005, 0x080c, 0x1ec1, 0x080c, 0x11a3, 0x0005, 0x0126, 0x2091, + 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, + 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, + 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, + 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, + 0xd0a4, 0x190c, 0x23dc, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, + 0x001a, 0x9084, 0x000e, 0x0002, 0x2304, 0x22fc, 0x7d93, 0x22fc, + 0x22fe, 0x22fe, 0x22fe, 0x22fe, 0x7d79, 0x22fc, 0x2300, 0x22fc, + 0x22fe, 0x22fc, 0x22fe, 0x22fc, 0x080c, 0x0dd5, 0x0031, 0x0020, + 0x080c, 0x7d79, 0x080c, 0x7d93, 0x0005, 0x0006, 0x0016, 0x0026, + 0x080c, 0xea45, 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, 0x19f5, + 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, + 0x0dd5, 0x00c6, 0x2001, 0x19f5, 0x2064, 0x080c, 0xc77b, 0x00ce, + 0x00f8, 0x2009, 0x0040, 0x080c, 0x23df, 0x00d0, 0x9184, 0x0014, + 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, 0x73b3, 0x1138, + 0x080c, 0x7699, 0x080c, 0x602d, 0x080c, 0x72e5, 0x0010, 0x080c, + 0x5eec, 0x080c, 0x7e42, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, + 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, + 0x2071, 0x1a61, 0x080c, 0x1abb, 0x005e, 0x004e, 0x003e, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, 0x2001, + 0x196e, 0x2102, 0x2001, 0x1976, 0x2102, 0x2001, 0x013b, 0x2102, + 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, 0x9198, + 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, + 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, + 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, + 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, + 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, + 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, + 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, + 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, + 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, + 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, + 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, + 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, + 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, + 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, + 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, 0x0dce, 0x00f6, + 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, + 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, + 0x1800, 0x2009, 0x0000, 0x080c, 0x2c4b, 0x080c, 0x2b66, 0x6054, + 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, + 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f, 0x9085, 0x2000, + 0x6052, 0x2009, 0x199c, 0x2011, 0x199d, 0x6358, 0x939c, 0x38f0, + 0x2320, 0x080c, 0x2baa, 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, + 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, + 0x2412, 0x9006, 0x080c, 0x2b95, 0x9006, 0x080c, 0x2b78, 0x20a9, + 0x0012, 0x1d04, 0x2431, 0x2091, 0x6000, 0x1f04, 0x2431, 0x602f, + 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, + 0x6052, 0x6024, 0x6026, 0x080c, 0x2884, 0x2009, 0x00ef, 0x6132, + 0x6136, 0x080c, 0x2894, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, + 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, + 0x6007, 0x349f, 0x60bb, 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, + 0x1f04, 0x245e, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, + 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, 0x60bf, 0x0018, + 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402f, + 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, 0x78c3, + 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, 0x1835, 0x2003, + 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, 0x2031, 0x1837, + 0x2634, 0x96b4, 0x0028, 0x006e, 0x1138, 0x6020, 0xd1bc, 0x0120, + 0xd0bc, 0x1168, 0xd0b4, 0x1198, 0x9184, 0x5e2c, 0x1118, 0x9184, + 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007, 0x0082, 0x0016, + 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0d70, 0x0c98, 0x0016, + 0x2001, 0x188b, 0x200c, 0xd194, 0x001e, 0x0d30, 0x0c58, 0x24e1, + 0x24c7, 0x24ca, 0x24cd, 0x24d2, 0x24d4, 0x24d8, 0x24dc, 0x080c, + 0x8fdd, 0x00b8, 0x080c, 0x90aa, 0x00a0, 0x080c, 0x90aa, 0x080c, + 0x8fdd, 0x0078, 0x0099, 0x0068, 0x080c, 0x8fdd, 0x0079, 0x0048, + 0x080c, 0x90aa, 0x0059, 0x0028, 0x080c, 0x90aa, 0x080c, 0x8fdd, + 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, + 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2749, 0xd1f4, 0x190c, + 0x0dce, 0x080c, 0x73b3, 0x0904, 0x253c, 0x080c, 0xd25a, 0x1120, + 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, 0x1800, 0x0550, + 0x080c, 0x73d6, 0x0118, 0x080c, 0x73c4, 0x1520, 0x6027, 0x0020, + 0x6043, 0x0000, 0x080c, 0xd25a, 0x0168, 0x080c, 0x73d6, 0x1150, + 0x2001, 0x19a6, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x7249, + 0x0804, 0x274c, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, + 0x2069, 0x0140, 0x080c, 0x740a, 0x00de, 0x1904, 0x274c, 0x080c, + 0x76a3, 0x0428, 0x080c, 0x73d6, 0x1590, 0x6024, 0x9084, 0x1800, + 0x1108, 0x0468, 0x080c, 0x76a3, 0x080c, 0x7699, 0x080c, 0x602d, + 0x080c, 0x72e5, 0x0804, 0x2749, 0xd1ac, 0x1508, 0x6024, 0xd0dc, + 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, + 0x9086, 0x0028, 0x1110, 0x080c, 0x7586, 0x0804, 0x2749, 0x080c, + 0x769e, 0x0048, 0x2001, 0x197c, 0x2003, 0x0002, 0x0020, 0x080c, + 0x74eb, 0x0804, 0x2749, 0x080c, 0x7621, 0x0804, 0x2749, 0x6220, + 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x27bc, 0xd2b4, 0x1904, 0x27cf, + 0x0000, 0xd1ac, 0x0904, 0x265e, 0x0036, 0x6328, 0xc3bc, 0x632a, + 0x003e, 0x080c, 0x73b3, 0x11c0, 0x6027, 0x0020, 0x0006, 0x0026, + 0x0036, 0x080c, 0x73cd, 0x1158, 0x080c, 0x7699, 0x080c, 0x602d, + 0x080c, 0x72e5, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, 0x003e, + 0x002e, 0x000e, 0x080c, 0x738b, 0x0016, 0x0046, 0x00c6, 0x644c, + 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, + 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, 0xd084, 0x0178, + 0x9186, 0xf800, 0x1160, 0x7048, 0xd084, 0x1148, 0xc085, 0x704a, + 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x4b1e, 0x003e, 0x080c, + 0xd253, 0x1904, 0x263b, 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, + 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, + 0x1550, 0x080c, 0x3326, 0x0128, 0xc18d, 0x7132, 0x080c, 0x6981, + 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, + 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x263b, 0x7038, + 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x263b, + 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4b1e, + 0x003e, 0x0804, 0x263b, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, + 0x200c, 0xd1ac, 0x1904, 0x263b, 0xc1ad, 0x2102, 0x0036, 0x73d8, + 0x2011, 0x8013, 0x080c, 0x4b1e, 0x003e, 0x7130, 0xc185, 0x7132, + 0x2011, 0x1848, 0x220c, 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, + 0x2011, 0x0100, 0x080c, 0x86e3, 0x2019, 0x000e, 0x00c6, 0x2061, + 0x0000, 0x080c, 0xe55d, 0x00ce, 0x9484, 0x00ff, 0x9080, 0x3332, + 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, + 0x080c, 0xe5e9, 0x001e, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x3197, 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, + 0x900e, 0x080c, 0x6616, 0x1110, 0x080c, 0x6047, 0x8108, 0x1f04, + 0x2631, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, 0xadd0, 0x60e3, + 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, + 0xd19c, 0x11a0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, + 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, + 0x2001, 0x1826, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0904, + 0x2749, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x26e6, 0x080c, 0x857f, + 0x080c, 0xa28f, 0x6027, 0x0004, 0x00f6, 0x2019, 0x19ef, 0x2304, + 0x907d, 0x0904, 0x26b5, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, + 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, + 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, + 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, 0x080c, 0x2d0c, 0x2001, + 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, 0x2c26, 0x6904, + 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, 0x2cfc, 0x9006, + 0x080c, 0x2cfc, 0x080c, 0x959a, 0x080c, 0x96a6, 0x7814, 0x2048, + 0xa867, 0x0103, 0x2f60, 0x080c, 0xae5f, 0x009e, 0x00ee, 0x00ce, + 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, + 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d0c, 0x00de, + 0x00c6, 0x2061, 0x19e6, 0x6028, 0x080c, 0xd25a, 0x0120, 0x909a, + 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, + 0x00ce, 0x080c, 0xa26b, 0x0804, 0x2748, 0x2061, 0x0100, 0x62c0, + 0x080c, 0xac56, 0x2019, 0x19ef, 0x2304, 0x9065, 0x0120, 0x2009, + 0x0027, 0x080c, 0xaeda, 0x00ce, 0x0804, 0x2748, 0xd2bc, 0x0904, + 0x272f, 0x080c, 0x858c, 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, + 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, + 0x4000, 0x0110, 0x080c, 0x2d0c, 0x00de, 0x00c6, 0x2061, 0x19e6, + 0x6044, 0x080c, 0xd25a, 0x0120, 0x909a, 0x0003, 0x1658, 0x0018, + 0x909a, 0x00c8, 0x1638, 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, + 0x05b8, 0x2009, 0x07d0, 0x080c, 0x8584, 0x9080, 0x0008, 0x2004, + 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, + 0x6116, 0x0430, 0x9080, 0x0008, 0x2004, 0x9086, 0x0009, 0x0d98, + 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, 0x00c8, 0x6027, + 0x0004, 0x00b0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa5c8, 0x003e, + 0x2019, 0x19f5, 0x2304, 0x9065, 0x0150, 0x2009, 0x004f, 0x6020, + 0x9086, 0x0009, 0x1110, 0x2009, 0x004f, 0x080c, 0xaeda, 0x00ce, + 0x001e, 0xd19c, 0x0904, 0x27b7, 0x7038, 0xd0ac, 0x1904, 0x2790, + 0x0016, 0x0156, 0x6027, 0x0008, 0x6050, 0x9085, 0x0040, 0x6052, + 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2c45, 0x9085, 0x2000, + 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2763, 0x080c, 0x85b3, 0x1f04, + 0x2763, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, + 0x0028, 0xa001, 0x1f04, 0x2771, 0x6150, 0x9185, 0x1400, 0x6052, + 0x20a9, 0x0366, 0x1d04, 0x277a, 0x080c, 0x85b3, 0x6020, 0xd09c, + 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, + 0x2c0d, 0x1f04, 0x277a, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, + 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xadd0, 0x60e3, 0x0000, + 0x080c, 0xea24, 0x080c, 0xea3f, 0x080c, 0x56e6, 0xd0fc, 0x1138, + 0x080c, 0xd253, 0x1120, 0x9085, 0x0001, 0x080c, 0x73fa, 0x9006, + 0x080c, 0x2cfc, 0x2009, 0x0002, 0x080c, 0x2c4b, 0x2001, 0x1800, + 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, 0x0bae, 0x001e, 0x918c, + 0xffd0, 0x6126, 0x00ae, 0x0005, 0x0016, 0x2001, 0x188b, 0x200c, + 0xd184, 0x001e, 0x0904, 0x2569, 0x0016, 0x2009, 0x27c8, 0x00d0, + 0x2001, 0x188b, 0x200c, 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, + 0x2001, 0x188b, 0x200c, 0xd194, 0x001e, 0x0904, 0x2569, 0x0016, + 0x2009, 0x27db, 0x0038, 0x2001, 0x188b, 0x200c, 0xc194, 0x2102, + 0x001e, 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, + 0xbc91, 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2c45, + 0x6027, 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, + 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1800, 0x71d0, 0x70d2, 0x9116, 0x05e8, 0x81ff, 0x01a0, + 0x2009, 0x0000, 0x080c, 0x2c4b, 0x2011, 0x8011, 0x2019, 0x010e, + 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, + 0x0000, 0x080c, 0x4b1e, 0x0438, 0x2001, 0x19a7, 0x200c, 0x81ff, + 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, + 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, 0x4b1e, 0x080c, 0x56e6, + 0xd0fc, 0x1188, 0x080c, 0xd253, 0x1170, 0x00c6, 0x080c, 0x28df, + 0x080c, 0xa52f, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, + 0x080c, 0x3197, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, + 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, + 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff, + 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, 0x1820, + 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, + 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, + 0x2500, 0x080c, 0x80b4, 0x0048, 0x9584, 0x00ff, 0x9080, 0x3332, + 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x3332, + 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, + 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, + 0x1f04, 0x288f, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, + 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, + 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, + 0x000f, 0x9080, 0xf1f1, 0x2005, 0x6856, 0x8211, 0x1f04, 0x28a4, + 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, + 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, + 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, + 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, + 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28d4, 0x680f, + 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, + 0x56e2, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, + 0x2009, 0x002e, 0x080c, 0xe5e9, 0x004e, 0x0005, 0x00f6, 0x0016, + 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x294b, 0x080c, + 0x2baa, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, + 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, + 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, + 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, + 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, + 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, + 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, + 0x0020, 0x2018, 0x080c, 0x8f70, 0x928c, 0xff00, 0x0110, 0x2011, + 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, + 0x220a, 0x080c, 0x73b3, 0x1118, 0x2009, 0x196c, 0x220a, 0x002e, + 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, + 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, + 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0dce, 0x002e, 0x001e, + 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, + 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, + 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, + 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, + 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x198f, 0x2004, 0x908a, + 0x0007, 0x1a0c, 0x0dd5, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, + 0x015e, 0x0005, 0x29a9, 0x29c7, 0x29eb, 0x29ed, 0x2a16, 0x2a18, + 0x2a1a, 0x2001, 0x0001, 0x080c, 0x27f7, 0x080c, 0x2c08, 0x2001, + 0x1991, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, + 0x20a9, 0x0009, 0x080c, 0x2bc6, 0x2001, 0x198f, 0x2003, 0x0006, + 0x2009, 0x001e, 0x2011, 0x2a1b, 0x080c, 0x8591, 0x0005, 0x2009, + 0x1994, 0x200b, 0x0000, 0x2001, 0x1999, 0x2003, 0x0036, 0x2001, + 0x1998, 0x2003, 0x002a, 0x2001, 0x1991, 0x2003, 0x0001, 0x9006, + 0x080c, 0x2b78, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2bc6, + 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2a1b, + 0x080c, 0x8591, 0x0005, 0x080c, 0x0dd5, 0x2001, 0x1999, 0x2003, + 0x0036, 0x2001, 0x1991, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x2b78, 0x2001, 0x1995, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, + 0x0009, 0x080c, 0x2bc6, 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, + 0x001e, 0x2011, 0x2a1b, 0x080c, 0x8591, 0x0005, 0x080c, 0x0dd5, + 0x080c, 0x0dd5, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, + 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1991, + 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dd5, 0x0043, 0x012e, 0x015e, + 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2a3d, 0x2a5d, + 0x2a9d, 0x2acd, 0x2af1, 0x2b01, 0x2b03, 0x080c, 0x2bba, 0x11b0, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1997, 0x2104, 0x7a38, + 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, + 0x200a, 0x2001, 0x198f, 0x2003, 0x0001, 0x0030, 0x080c, 0x2b27, + 0x2001, 0xffff, 0x080c, 0x29b8, 0x0005, 0x080c, 0x2b05, 0x05e0, + 0x2009, 0x1998, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bba, 0x1178, + 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0005, 0x0518, 0x2009, 0x1997, 0x2104, 0xc085, 0x200a, 0x2009, + 0x1994, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, + 0x2b0d, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, + 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2b95, + 0x2001, 0x1991, 0x2003, 0x0002, 0x0028, 0x2001, 0x198f, 0x2003, + 0x0003, 0x0010, 0x080c, 0x29da, 0x0005, 0x080c, 0x2b05, 0x0560, + 0x2009, 0x1998, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bba, 0x1168, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x198f, 0x2003, 0x0003, + 0x2001, 0x1990, 0x2003, 0x0000, 0x00b8, 0x2009, 0x1998, 0x2104, + 0x9005, 0x1118, 0x080c, 0x2b4a, 0x0010, 0x080c, 0x2b1a, 0x080c, + 0x2b0d, 0x2009, 0x1994, 0x200b, 0x0000, 0x2001, 0x1991, 0x2003, + 0x0001, 0x080c, 0x29da, 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, + 0x2bba, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1995, + 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, + 0x199a, 0x2003, 0x000a, 0x2009, 0x1997, 0x2104, 0xc0fd, 0x200a, + 0x0038, 0x0419, 0x2001, 0x1991, 0x2003, 0x0004, 0x080c, 0x2a05, + 0x0005, 0x0099, 0x0168, 0x080c, 0x2bba, 0x1138, 0x7850, 0x9084, + 0xefff, 0x7852, 0x080c, 0x29f1, 0x0018, 0x0079, 0x080c, 0x2a05, + 0x0005, 0x080c, 0x0dd5, 0x080c, 0x0dd5, 0x2009, 0x1999, 0x2104, + 0x8001, 0x200a, 0x090c, 0x2b66, 0x0005, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x2b95, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2b78, 0x0005, 0x2009, + 0x1994, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, + 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, + 0x2b95, 0x0005, 0x0086, 0x2001, 0x1997, 0x2004, 0x9084, 0x7fff, + 0x090c, 0x0dd5, 0x2009, 0x1996, 0x2144, 0x8846, 0x280a, 0x9844, + 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, 0x0dd5, 0x9006, + 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, + 0x2001, 0x198f, 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, + 0x2b6c, 0x2001, 0x1996, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, + 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x199c, 0x210c, 0x795a, + 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, + 0x199d, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0138, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, + 0x783a, 0x0030, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, + 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, + 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0009, + 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2c45, + 0xd09c, 0x1110, 0x1f04, 0x2bbd, 0x015e, 0x0005, 0x0126, 0x0016, + 0x0006, 0x2091, 0x8000, 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, + 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c45, 0x9085, 0x2000, 0x7852, + 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, + 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, + 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, + 0x0004, 0x0000, 0x0006, 0x1d04, 0x2bf3, 0x080c, 0x85b3, 0x1f04, + 0x2bf3, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, + 0x2c45, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, + 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, 0x0156, 0x00f6, + 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1130, 0x7820, + 0xd0e4, 0x1140, 0x1f04, 0x2c17, 0x0028, 0x7854, 0xd08c, 0x1110, + 0x1f04, 0x2c1d, 0x00fe, 0x015e, 0x000e, 0x0005, 0x1d04, 0x2c26, + 0x080c, 0x85b3, 0x1f04, 0x2c26, 0x0005, 0x0006, 0x2001, 0x199b, + 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, + 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, + 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x19a7, 0x2102, 0x000e, + 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, + 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, + 0x0046, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, + 0x0118, 0x9186, 0x0100, 0x1588, 0x2009, 0x00a2, 0x080c, 0x0e51, + 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, 0x0169, 0x2104, + 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e, 0x1db0, 0x9086, + 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d60, 0x8211, 0x1d68, + 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, + 0x0100, 0x0130, 0x2009, 0x180c, 0x2104, 0xc0dd, 0x200a, 0x0008, + 0x0419, 0x2009, 0x0000, 0x080c, 0x0e51, 0x004e, 0x003e, 0x0005, + 0x2001, 0x180c, 0x2004, 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, + 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, + 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, + 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, + 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, + 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, + 0x0010, 0x6106, 0x6017, 0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, + 0x01e0, 0x0036, 0x0016, 0x2019, 0x0141, 0x6124, 0x918c, 0x0028, + 0x1120, 0x2304, 0x9084, 0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, + 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, + 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, 0x180c, 0x200c, + 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, 0x080c, 0x73cd, + 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, + 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, + 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, + 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, + 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, + 0x2009, 0x0140, 0x2104, 0x1128, 0x080c, 0x73cd, 0x0110, 0xc0bc, + 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, 0x0005, 0x2fa2, 0x2fa2, + 0x2dc6, 0x2dc6, 0x2dd2, 0x2dd2, 0x2dde, 0x2dde, 0x2dec, 0x2dec, + 0x2df8, 0x2df8, 0x2e06, 0x2e06, 0x2e14, 0x2e14, 0x2e26, 0x2e26, + 0x2e32, 0x2e32, 0x2e40, 0x2e40, 0x2e5e, 0x2e5e, 0x2e7e, 0x2e7e, + 0x2e4e, 0x2e4e, 0x2e6e, 0x2e6e, 0x2e8c, 0x2e8c, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e9e, 0x2e9e, + 0x2eaa, 0x2eaa, 0x2eb8, 0x2eb8, 0x2ec6, 0x2ec6, 0x2ed6, 0x2ed6, + 0x2ee4, 0x2ee4, 0x2ef4, 0x2ef4, 0x2f04, 0x2f04, 0x2f16, 0x2f16, + 0x2f24, 0x2f24, 0x2f34, 0x2f34, 0x2f56, 0x2f56, 0x2f78, 0x2f78, + 0x2f44, 0x2f44, 0x2f67, 0x2f67, 0x2f87, 0x2f87, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, + 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x2e24, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x248e, + 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x22a2, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, + 0x080c, 0x248e, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22dd, 0x0804, 0x2f9a, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x248e, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, 0x080c, 0x248e, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0xa001, 0x0cf0, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1380, + 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x248e, 0x080c, 0x1380, 0x0804, 0x2f9a, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x22a2, 0x080c, 0x1380, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x248e, + 0x080c, 0x1380, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, + 0x080c, 0x248e, 0x080c, 0x1380, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, + 0x080c, 0x1380, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1380, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22a2, 0x080c, 0x248e, + 0x080c, 0x1380, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, + 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x248e, 0x0804, 0x2f9a, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x294e, 0x080c, 0x22a2, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, + 0x080c, 0x22a2, 0x080c, 0x248e, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x248e, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x22a2, + 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x22a2, + 0x080c, 0x248e, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, + 0x080c, 0x1380, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x248e, + 0x080c, 0x1380, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x22a2, + 0x080c, 0x1380, 0x0804, 0x2f9a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, 0x080c, 0x248e, + 0x080c, 0x1380, 0x080c, 0x22dd, 0x0804, 0x2f9a, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x294e, + 0x080c, 0x22a2, 0x080c, 0x248e, 0x080c, 0x1380, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2483, 0x080c, 0x1380, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2297, 0x080c, - 0x1380, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2483, 0x080c, 0x1380, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2297, 0x080c, 0x2483, 0x080c, - 0x1380, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2297, 0x080c, 0x1380, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1380, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2297, 0x080c, 0x2483, 0x080c, 0x1380, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x0804, 0x2f8f, 0x0106, + 0x294e, 0x080c, 0x22a2, 0x080c, 0x1380, 0x080c, 0x22dd, 0x0410, + 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, + 0x080c, 0x294e, 0x080c, 0x1380, 0x080c, 0x22dd, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2943, 0x080c, 0x2483, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, - 0x2297, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, 0x080c, - 0x2483, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2483, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, 0x080c, 0x22d2, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, 0x080c, 0x2483, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x1380, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2483, 0x080c, 0x1380, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, 0x080c, 0x1380, 0x0804, - 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2943, 0x080c, 0x2483, 0x080c, 0x1380, 0x080c, - 0x22d2, 0x0804, 0x2f8f, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, 0x080c, - 0x2483, 0x080c, 0x1380, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, - 0x080c, 0x1380, 0x080c, 0x22d2, 0x0410, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, - 0x1380, 0x080c, 0x22d2, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2943, 0x080c, 0x2297, - 0x080c, 0x2483, 0x080c, 0x1380, 0x080c, 0x22d2, 0x0000, 0x015e, - 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, - 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6939, 0x1904, - 0x30a8, 0x72dc, 0x2001, 0x197b, 0x2004, 0x9005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x30a8, 0x080c, 0x30ad, - 0x0804, 0x30a8, 0xd2cc, 0x1904, 0x30a8, 0x080c, 0x73a5, 0x1120, - 0x70af, 0xffff, 0x0804, 0x30a8, 0xd294, 0x0120, 0x70af, 0xffff, - 0x0804, 0x30a8, 0x080c, 0x3316, 0x0160, 0x080c, 0xd24a, 0x0128, - 0x2001, 0x1818, 0x203c, 0x0804, 0x3035, 0x70af, 0xffff, 0x0804, - 0x30a8, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x3035, - 0xd28c, 0x1904, 0x3035, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001, - 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, - 0x05d0, 0x908e, 0x0000, 0x05b8, 0x908e, 0x00ff, 0x1150, 0x7230, - 0xd284, 0x15b0, 0x7294, 0xc28d, 0x7296, 0x70af, 0xffff, 0x003e, - 0x04a0, 0x900e, 0x080c, 0x2840, 0x080c, 0x65a7, 0x1538, 0x9006, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, - 0x896a, 0x00ce, 0x090c, 0x8d0e, 0xb8af, 0x0000, 0x080c, 0x697b, - 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, 0x080c, - 0x6828, 0x0120, 0x080c, 0x30c6, 0x0148, 0x0028, 0x080c, 0x3206, - 0x080c, 0x30f2, 0x0118, 0x8318, 0x0804, 0x2fe2, 0x73ae, 0x0010, - 0x70af, 0xffff, 0x003e, 0x0804, 0x30a8, 0x9780, 0x3327, 0x203d, - 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, 0x9096, 0xffff, - 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, - 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x30a8, 0x2700, 0x0156, - 0x0016, 0x9106, 0x0904, 0x309d, 0xc484, 0x080c, 0x6608, 0x0148, - 0x080c, 0xd24a, 0x1904, 0x309d, 0x080c, 0x65a7, 0x1904, 0x30a5, - 0x0008, 0xc485, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, - 0x2060, 0x080c, 0x896a, 0x00ce, 0x090c, 0x8d0e, 0xb8af, 0x0000, - 0x080c, 0x697b, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, - 0x11e0, 0x7294, 0xd28c, 0x0180, 0x080c, 0x697b, 0x9082, 0x0006, - 0x02e0, 0xd484, 0x1118, 0x080c, 0x65cc, 0x0028, 0x080c, 0x3292, - 0x01a0, 0x080c, 0x32bd, 0x0088, 0x080c, 0x3206, 0x080c, 0xd24a, - 0x1160, 0x080c, 0x30f2, 0x0188, 0x0040, 0x080c, 0xd24a, 0x1118, - 0x080c, 0x3292, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, - 0x1f04, 0x304e, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, - 0x004e, 0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, - 0x0001, 0x2009, 0x007e, 0x080c, 0x65a7, 0x1168, 0xb813, 0x00ff, - 0xb817, 0xfffe, 0x080c, 0x3206, 0x04a9, 0x0128, 0x70dc, 0xc0bd, - 0x70de, 0x080c, 0xcf9b, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, - 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, - 0x080c, 0xaebf, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xcfc4, 0x6023, - 0x0001, 0x9006, 0x080c, 0x6544, 0x2001, 0x0000, 0x080c, 0x6558, - 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, - 0x0004, 0x080c, 0xaeec, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, - 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, - 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xaebf, 0x0548, 0x2b00, - 0x6012, 0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x31c1, - 0x080c, 0xcfc4, 0x6023, 0x0001, 0x9006, 0x080c, 0x6544, 0x2001, - 0x0002, 0x080c, 0x6558, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, - 0x70aa, 0x012e, 0x2009, 0x0002, 0x080c, 0xaeec, 0x9085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, - 0x2009, 0x0080, 0x080c, 0x65a7, 0x1140, 0xb813, 0x00ff, 0xb817, - 0xfffc, 0x0039, 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xae1b, 0x01d0, - 0x2b00, 0x6012, 0x080c, 0xcfc4, 0x6023, 0x0001, 0x9006, 0x080c, - 0x6544, 0x2001, 0x0002, 0x080c, 0x6558, 0x0126, 0x2091, 0x8000, - 0x70e4, 0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xaeec, - 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, - 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x65a7, - 0x11b8, 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8cf, 0x0004, 0x080c, - 0xae1b, 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, - 0x080c, 0xcfc4, 0x2009, 0x0022, 0x080c, 0xaeec, 0x9085, 0x0001, - 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, - 0x0026, 0x00b6, 0x21f0, 0x080c, 0x9289, 0x080c, 0x9209, 0x080c, - 0xacaf, 0x080c, 0xbd8a, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, - 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, - 0x6608, 0x1140, 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, - 0x080c, 0x603d, 0x001e, 0x8108, 0x1f04, 0x31a6, 0x9686, 0x0001, - 0x190c, 0x32ea, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, - 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x927e, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9151, 0x2c08, 0x080c, 0xe30c, - 0x007e, 0x001e, 0xba10, 0xbb14, 0xbcc0, 0x080c, 0x603d, 0xba12, - 0xbb16, 0xbcc2, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, - 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, - 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a8, 0x9005, - 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, 0xb800, 0xc08c, - 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, - 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, - 0x0078, 0x080c, 0x56d8, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, - 0x2020, 0x2009, 0x002d, 0x080c, 0xe5cf, 0x20a9, 0x0800, 0x9016, - 0x0026, 0x928e, 0x007e, 0x0904, 0x3271, 0x928e, 0x007f, 0x0904, - 0x3271, 0x928e, 0x0080, 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, - 0x05c0, 0x8fff, 0x1148, 0x2001, 0x198d, 0x0006, 0x2003, 0x0001, - 0x04f1, 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, - 0x0001, 0x080c, 0x6945, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, - 0x927e, 0x0076, 0x2039, 0x0000, 0x080c, 0x9151, 0x00b6, 0x00c6, - 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, - 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, - 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xe30c, 0x001e, - 0x007e, 0x002e, 0x8210, 0x1f04, 0x3228, 0x015e, 0x001e, 0x002e, - 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, - 0x0026, 0x0016, 0x080c, 0x56d8, 0xd0c4, 0x0140, 0xd0a4, 0x0130, - 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xe5cf, 0x001e, 0x002e, - 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, - 0x01e8, 0x080c, 0x6973, 0x11d0, 0x2100, 0x080c, 0x2873, 0x81ff, - 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0xd384, - 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, - 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, - 0x1000, 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1aaf, - 0x001e, 0x6112, 0x080c, 0x31c1, 0x001e, 0x080c, 0x65cc, 0x012e, - 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xa80e, - 0x080c, 0xe938, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, - 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x73a5, 0x1118, 0x20a9, - 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x73a5, 0x1110, 0x900e, - 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, - 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x65cc, 0x8108, 0x1f04, - 0x32fb, 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, - 0x6082, 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, - 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, - 0x0026, 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, - 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, - 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, - 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, - 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, - 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, - 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, - 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, - 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, - 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, - 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, - 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, - 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, - 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, - 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, - 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, - 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, - 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, - 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, - 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, - 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, - 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, - 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, - 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, - 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, - 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, - 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, + 0x294e, 0x080c, 0x22a2, 0x080c, 0x248e, 0x080c, 0x1380, 0x080c, + 0x22dd, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, + 0x000e, 0x010e, 0x000d, 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, + 0x080c, 0x6947, 0x1904, 0x30b3, 0x72dc, 0x2001, 0x197b, 0x2004, + 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, + 0x30b3, 0x080c, 0x30b8, 0x0804, 0x30b3, 0xd2cc, 0x1904, 0x30b3, + 0x080c, 0x73b3, 0x1120, 0x70af, 0xffff, 0x0804, 0x30b3, 0xd294, + 0x0120, 0x70af, 0xffff, 0x0804, 0x30b3, 0x080c, 0x3321, 0x0160, + 0x080c, 0xd25a, 0x0128, 0x2001, 0x1818, 0x203c, 0x0804, 0x3040, + 0x70af, 0xffff, 0x0804, 0x30b3, 0x2001, 0x1818, 0x203c, 0x7294, + 0xd284, 0x0904, 0x3040, 0xd28c, 0x1904, 0x3040, 0x0036, 0x73ac, + 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, + 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, + 0x9084, 0x00ff, 0x970e, 0x05d0, 0x908e, 0x0000, 0x05b8, 0x908e, + 0x00ff, 0x1150, 0x7230, 0xd284, 0x15b0, 0x7294, 0xc28d, 0x7296, + 0x70af, 0xffff, 0x003e, 0x04a0, 0x900e, 0x080c, 0x284b, 0x080c, + 0x65b5, 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, + 0x00c6, 0x2060, 0x080c, 0x8987, 0x00ce, 0x090c, 0x8d2d, 0xb8af, + 0x0000, 0x080c, 0x6989, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, + 0xd0bc, 0x0138, 0x080c, 0x6836, 0x0120, 0x080c, 0x30d1, 0x0148, + 0x0028, 0x080c, 0x3211, 0x080c, 0x30fd, 0x0118, 0x8318, 0x0804, + 0x2fed, 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x30b3, + 0x9780, 0x3332, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, + 0x70ac, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, + 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, + 0x30b3, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x30a8, 0xc484, + 0x080c, 0x6616, 0x0148, 0x080c, 0xd25a, 0x1904, 0x30a8, 0x080c, + 0x65b5, 0x1904, 0x30b0, 0x0008, 0xc485, 0xb8bb, 0x0520, 0xb8ac, + 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, 0x8987, 0x00ce, 0x090c, + 0x8d2d, 0xb8af, 0x0000, 0x080c, 0x6989, 0x1130, 0x7030, 0xd08c, + 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294, 0xd28c, 0x0180, 0x080c, + 0x6989, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, 0x080c, 0x65da, + 0x0028, 0x080c, 0x329d, 0x01a0, 0x080c, 0x32c8, 0x0088, 0x080c, + 0x3211, 0x080c, 0xd25a, 0x1160, 0x080c, 0x30fd, 0x0188, 0x0040, + 0x080c, 0xd25a, 0x1118, 0x080c, 0x329d, 0x0110, 0x0451, 0x0140, + 0x001e, 0x8108, 0x015e, 0x1f04, 0x3059, 0x70af, 0xffff, 0x0018, + 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, 0x00ce, 0x00be, 0x0005, + 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009, 0x007e, 0x080c, 0x65b5, + 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, 0x080c, 0x3211, 0x04a9, + 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c, 0xcfab, 0x001e, 0x00ce, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, + 0x9084, 0x00ff, 0xb842, 0x080c, 0xaead, 0x01d0, 0x2b00, 0x6012, + 0x080c, 0xcfd4, 0x6023, 0x0001, 0x9006, 0x080c, 0x6552, 0x2001, + 0x0000, 0x080c, 0x6566, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, + 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c, 0xaeda, 0x9085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, + 0xaead, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, 0xb8a0, + 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x1110, 0x080c, 0x31cc, 0x080c, 0xcfd4, 0x6023, 0x0001, 0x9006, + 0x080c, 0x6552, 0x2001, 0x0002, 0x080c, 0x6566, 0x0126, 0x2091, + 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0002, 0x080c, + 0xaeda, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, + 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x65b5, 0x1140, + 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70e3, 0xffff, + 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x080c, 0xae09, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xcfd4, 0x6023, + 0x0001, 0x9006, 0x080c, 0x6552, 0x2001, 0x0002, 0x080c, 0x6566, + 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000, 0x70e6, 0x012e, 0x2009, + 0x0002, 0x080c, 0xaeda, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, + 0x007f, 0x080c, 0x65b5, 0x11b8, 0xb813, 0x00ff, 0xb817, 0xfffd, + 0xb8cf, 0x0004, 0x080c, 0xae09, 0x0170, 0x2b00, 0x6012, 0x6316, + 0x6023, 0x0001, 0x620a, 0x080c, 0xcfd4, 0x2009, 0x0022, 0x080c, + 0xaeda, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, + 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, 0x21f0, 0x080c, 0x92a8, + 0x080c, 0x9228, 0x080c, 0xac9d, 0x080c, 0xbd87, 0x3e08, 0x2130, + 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, + 0x900e, 0x0016, 0x080c, 0x6616, 0x1140, 0x9686, 0x0002, 0x1118, + 0xb800, 0xd0bc, 0x1110, 0x080c, 0x6047, 0x001e, 0x8108, 0x1f04, + 0x31b1, 0x9686, 0x0001, 0x190c, 0x32f5, 0x00be, 0x002e, 0x003e, + 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, 0x0036, + 0x0026, 0x0016, 0x00b6, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, + 0x0029, 0x080c, 0x929d, 0x0076, 0x2039, 0x0000, 0x080c, 0x9170, + 0x2c08, 0x080c, 0xe326, 0x007e, 0x001e, 0xba10, 0xbb14, 0xbcc0, + 0x080c, 0x6047, 0xba12, 0xbb16, 0xbcc2, 0x00be, 0x001e, 0x002e, + 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, + 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, + 0x1800, 0x70a8, 0x9005, 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, + 0x0005, 0x2071, 0x1800, 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, + 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, + 0x1118, 0x20a9, 0x0001, 0x0078, 0x080c, 0x56e2, 0xd0c4, 0x0140, + 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d, 0x080c, 0xe5e9, + 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, 0x327c, + 0x928e, 0x007f, 0x0904, 0x327c, 0x928e, 0x0080, 0x05e8, 0x9288, + 0x1000, 0x210c, 0x81ff, 0x05c0, 0x8fff, 0x1148, 0x2001, 0x198d, + 0x0006, 0x2003, 0x0001, 0x04f1, 0x000e, 0x2003, 0x0000, 0x00b6, + 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, 0x6953, 0x00ce, 0x00be, + 0x2019, 0x0029, 0x080c, 0x929d, 0x0076, 0x2039, 0x0000, 0x080c, + 0x9170, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, + 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, + 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, + 0x080c, 0xe326, 0x001e, 0x007e, 0x002e, 0x8210, 0x1f04, 0x3233, + 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, + 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x56e2, 0xd0c4, + 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, + 0xe5e9, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x7294, 0x82ff, 0x01e8, 0x080c, 0x6981, 0x11d0, 0x2100, + 0x080c, 0x287e, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, + 0x1c80, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, + 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, + 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0036, 0x2019, 0x0029, + 0x00a9, 0x003e, 0x9180, 0x1000, 0x2004, 0x9065, 0x0158, 0x0016, + 0x00c6, 0x2061, 0x1aaf, 0x001e, 0x6112, 0x080c, 0x31cc, 0x001e, + 0x080c, 0x65da, 0x012e, 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, + 0x2110, 0x080c, 0xa7f8, 0x080c, 0xe952, 0x002e, 0x001e, 0x0005, + 0x2001, 0x1837, 0x2004, 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, + 0x73b3, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, + 0x73b3, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, + 0x2004, 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, + 0x65da, 0x8108, 0x1f04, 0x3306, 0x2061, 0x1800, 0x607f, 0x0000, + 0x6080, 0x9084, 0x00ff, 0x6082, 0x60b3, 0x0000, 0x00be, 0x00ce, + 0x0005, 0x2001, 0x1869, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1848, + 0x2214, 0xd2ec, 0x0005, 0x0026, 0x2011, 0x1867, 0x2214, 0xd2dc, + 0x002e, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, + 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, + 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, + 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, + 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, + 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, + 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, + 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, + 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, + 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, + 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, + 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, + 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, + 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, + 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, + 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, + 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, + 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, + 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, + 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, + 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, + 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, + 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, + 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, + 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, + 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, + 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, - 0x189e, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, - 0x700e, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, - 0x0001, 0x080c, 0x1018, 0x090c, 0x0dd5, 0x2900, 0x706a, 0xa867, - 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1018, 0x090c, 0x0dd5, 0x2900, - 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, - 0x7004, 0x0002, 0x3456, 0x3457, 0x346a, 0x347e, 0x0005, 0x1004, - 0x3467, 0x0e04, 0x3467, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, - 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, - 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, - 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x3552, 0x0005, - 0x7018, 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, - 0xa864, 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, - 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, - 0x2061, 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, - 0x0040, 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, - 0x354f, 0x61d0, 0x0804, 0x34e4, 0x3526, 0x355e, 0x354f, 0x3568, - 0x3572, 0x3578, 0x357c, 0x358c, 0x3590, 0x35a6, 0x35ac, 0x35b2, - 0x35bd, 0x35c8, 0x35d7, 0x35e6, 0x35f4, 0x360b, 0x3626, 0x354f, - 0x36cf, 0x370d, 0x37b3, 0x37c4, 0x37e7, 0x354f, 0x354f, 0x354f, - 0x381f, 0x383b, 0x3844, 0x3873, 0x3879, 0x354f, 0x38bf, 0x354f, - 0x354f, 0x354f, 0x354f, 0x354f, 0x38ca, 0x38d3, 0x38db, 0x38dd, - 0x354f, 0x354f, 0x354f, 0x354f, 0x354f, 0x354f, 0x3909, 0x354f, - 0x354f, 0x354f, 0x354f, 0x354f, 0x3926, 0x3987, 0x354f, 0x354f, - 0x354f, 0x354f, 0x354f, 0x354f, 0x0002, 0x39b1, 0x39b4, 0x3a13, - 0x3a2c, 0x3a5c, 0x3cfa, 0x354f, 0x52b1, 0x354f, 0x354f, 0x354f, - 0x354f, 0x354f, 0x354f, 0x354f, 0x354f, 0x35a6, 0x35ac, 0x421b, - 0x56fc, 0x4239, 0x5340, 0x5391, 0x5494, 0x354f, 0x54f6, 0x5532, - 0x5563, 0x5667, 0x5590, 0x55e7, 0x354f, 0x423d, 0x43fe, 0x4414, - 0x4439, 0x449e, 0x4512, 0x4532, 0x45a9, 0x4605, 0x4661, 0x4664, - 0x4689, 0x4726, 0x478c, 0x4794, 0x48c6, 0x4a3e, 0x4a72, 0x4cd6, - 0x354f, 0x4cf4, 0x4d99, 0x4e7b, 0x4ed5, 0x354f, 0x4f8a, 0x354f, - 0x4ff0, 0x500b, 0x4794, 0x5251, 0x714c, 0x0000, 0x2021, 0x4000, - 0x080c, 0x4af0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3530, 0x0010, - 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, - 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x7007, - 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, - 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, - 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, - 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x4afd, - 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, - 0x0804, 0x4b00, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x3526, - 0x7984, 0x2114, 0x0804, 0x3526, 0x20e1, 0x0000, 0x2099, 0x0021, - 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, - 0x7a88, 0x7b8c, 0x0804, 0x3526, 0x7884, 0x2060, 0x0804, 0x35d9, - 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, 0x001e, 0x789b, 0x0137, - 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, 0x7896, - 0x0804, 0x3526, 0x7897, 0x0001, 0x0804, 0x3526, 0x2039, 0x0001, - 0x7d98, 0x7c9c, 0x0804, 0x3562, 0x2039, 0x0001, 0x7d98, 0x7c9c, - 0x0804, 0x356c, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x355b, - 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x3562, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x355b, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x356c, - 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x355b, 0x21e8, 0x7984, - 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x3526, 0x2061, - 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, - 0x2010, 0x9005, 0x0904, 0x3526, 0x0804, 0x3555, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x355b, 0x21e0, 0x20a9, 0x0001, 0x7984, - 0x2198, 0x4012, 0x0804, 0x3526, 0x2069, 0x1847, 0x7884, 0x7990, - 0x911a, 0x1a04, 0x355b, 0x8019, 0x0904, 0x355b, 0x684a, 0x6942, - 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, - 0x76be, 0x0804, 0x3526, 0x2069, 0x1847, 0x7884, 0x7994, 0x911a, - 0x1a04, 0x355b, 0x8019, 0x0904, 0x355b, 0x684e, 0x6946, 0x788c, - 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, - 0x8000, 0x080c, 0x69e1, 0x012e, 0x0804, 0x3526, 0x902e, 0x2520, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3558, 0x7984, 0x7b88, - 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, 0x4101, - 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, 0x0804, 0x3558, 0x2009, - 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4afd, 0x701f, - 0x364a, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, - 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, - 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x3558, 0x810f, 0x918c, - 0x00ff, 0x0904, 0x3558, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, - 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, 0x0804, 0x3558, 0x2009, - 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, - 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, - 0x9080, 0x0019, 0xaf60, 0x080c, 0x4afd, 0x701f, 0x3688, 0x0005, - 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, - 0x1904, 0x3558, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, - 0xa864, 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, - 0x080c, 0x6194, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, - 0x012e, 0x0050, 0x080c, 0x64bd, 0x1128, 0x7007, 0x0003, 0x701f, - 0x36b4, 0x0005, 0x080c, 0x6eb9, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, 0x400a, 0x2100, 0x9210, - 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, - 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, 0x0804, 0x4b00, 0x2091, - 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, - 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, - 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, - 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, - 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x0180, 0x2001, 0x1a18, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, - 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, - 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3558, - 0x7984, 0x080c, 0x6608, 0x1904, 0x355b, 0x7e98, 0x9684, 0x3fff, - 0x9082, 0x4000, 0x1a04, 0x355b, 0x7c88, 0x7d8c, 0x080c, 0x676b, - 0x080c, 0x673a, 0x0000, 0x1518, 0x2061, 0x1cd0, 0x0126, 0x2091, - 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, - 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150, 0x012e, 0x9ce0, - 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04, 0x3558, 0x0c30, - 0x080c, 0xc77b, 0x012e, 0x0904, 0x3558, 0x0804, 0x3526, 0x900e, - 0x2001, 0x0005, 0x080c, 0x6eb9, 0x0126, 0x2091, 0x8000, 0x080c, - 0xce44, 0x080c, 0x6c86, 0x012e, 0x0804, 0x3526, 0x00a6, 0x2950, - 0xb198, 0x080c, 0x6608, 0x1904, 0x37a0, 0xb6a4, 0x9684, 0x3fff, - 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x676b, 0x080c, - 0x673a, 0x1520, 0x2061, 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, - 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, - 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, - 0xc77b, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, - 0x0005, 0x080c, 0x6eb9, 0x0126, 0x2091, 0x8000, 0x080c, 0xce44, - 0x080c, 0x6c7a, 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, - 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2a48, - 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, - 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x3558, 0x080c, 0x4acb, - 0x0904, 0x355b, 0x080c, 0x66cf, 0x0904, 0x3558, 0x080c, 0x6771, - 0x0904, 0x3558, 0x0804, 0x4529, 0x81ff, 0x1904, 0x3558, 0x080c, - 0x4ae7, 0x0904, 0x355b, 0x080c, 0x67ff, 0x0904, 0x3558, 0x2019, - 0x0005, 0x79a8, 0x080c, 0x678c, 0x0904, 0x3558, 0x7888, 0x908a, - 0x1000, 0x1a04, 0x355b, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, - 0x84ea, 0x7984, 0xd184, 0x1904, 0x3526, 0x0804, 0x4529, 0x0126, - 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, - 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x6608, - 0x11d8, 0x080c, 0x67ff, 0x1128, 0x2009, 0x0002, 0x62c0, 0x2518, - 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x678c, 0x1118, 0x2009, - 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, - 0x810b, 0x9108, 0x080c, 0x84ea, 0x8529, 0x1ae0, 0x012e, 0x0804, - 0x3526, 0x012e, 0x0804, 0x3558, 0x012e, 0x0804, 0x355b, 0x080c, - 0x4acb, 0x0904, 0x355b, 0x080c, 0x66cf, 0x0904, 0x3558, 0xbaa0, - 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x927e, 0x0076, 0x903e, - 0x080c, 0x9151, 0x900e, 0x080c, 0xe30c, 0x007e, 0x00ce, 0x080c, - 0x676b, 0x0804, 0x3526, 0x080c, 0x4acb, 0x0904, 0x355b, 0x080c, - 0x676b, 0x2208, 0x0804, 0x3526, 0x0156, 0x00d6, 0x00e6, 0x2069, - 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, - 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, 0x2d04, 0x905d, 0x0118, - 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04, 0x3855, 0x2300, 0x9218, - 0x00ee, 0x00de, 0x015e, 0x0804, 0x3526, 0x00f6, 0x0016, 0x907d, - 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, - 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, 0x6910, 0x62bc, 0x0804, - 0x3526, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3558, 0x0126, - 0x2091, 0x8000, 0x080c, 0x56ec, 0x0128, 0x2009, 0x0007, 0x012e, - 0x0804, 0x3558, 0x012e, 0x615c, 0x9190, 0x3327, 0x2215, 0x9294, - 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, 0x67dc, 0x97c4, 0x000a, - 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, 0x00e8, 0x97c4, 0x0022, - 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, 0x00a8, 0x97c4, 0x0012, - 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, 0x73a5, - 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, - 0x0804, 0x3558, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x3526, 0x614c, - 0x6250, 0x2019, 0x1985, 0x231c, 0x2001, 0x1986, 0x2004, 0x789a, - 0x0804, 0x3526, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, - 0x012e, 0x0804, 0x3526, 0x080c, 0x4ae7, 0x0904, 0x355b, 0xba44, - 0xbb38, 0x0804, 0x3526, 0x080c, 0x0dd5, 0x080c, 0x4ae7, 0x2110, - 0x0904, 0x355b, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, - 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x3558, - 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, - 0xa80e, 0x080c, 0x927e, 0x0076, 0x903e, 0x080c, 0x9151, 0x900e, - 0x080c, 0xe30c, 0x007e, 0x00ce, 0xb807, 0x0407, 0x012e, 0x0804, - 0x3526, 0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, - 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1985, 0x2d1c, - 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, - 0x1986, 0x2d04, 0x266a, 0x789a, 0x0804, 0x3526, 0x0126, 0x2091, - 0x8000, 0x7884, 0x603a, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, - 0x199c, 0x200a, 0x78ac, 0x2011, 0x199d, 0x2012, 0x2069, 0x0100, - 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, - 0x695a, 0x00de, 0x7884, 0xd0b4, 0x0120, 0x3b00, 0x9084, 0xff3f, - 0x20d8, 0x7888, 0x603e, 0x2011, 0x0114, 0x220c, 0x7888, 0xd08c, - 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, 0xff7f, 0x2112, 0x788c, - 0x6042, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, 0x0001, - 0x090c, 0x421b, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, - 0x2012, 0x012e, 0x0804, 0x3526, 0x00f6, 0x2079, 0x1800, 0x7a38, - 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, 0x8002, - 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, 0x4000, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, - 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x355b, 0x788c, 0x902d, - 0x0904, 0x355b, 0x900e, 0x080c, 0x6608, 0x1120, 0xba44, 0xbb38, - 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, - 0x4ae7, 0x0904, 0x355b, 0x7888, 0x900d, 0x0904, 0x355b, 0x788c, - 0x9005, 0x0904, 0x355b, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, - 0x3526, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x56ec, - 0x1904, 0x3558, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, - 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, - 0x007f, 0x16e0, 0x9188, 0x3327, 0x210d, 0x918c, 0x00ff, 0x2001, - 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, - 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xae1b, 0x000e, 0x0510, - 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x65ad, 0x2b08, 0x00be, - 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4ab4, 0x01d0, 0x9006, - 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, - 0x3a0c, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xaeec, 0x012e, - 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3558, 0x00ce, 0x0804, - 0x355b, 0x080c, 0xae71, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, - 0x3558, 0x0804, 0x3526, 0x2061, 0x1a70, 0x0126, 0x2091, 0x8000, - 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, 0x6354, - 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e, 0x0804, - 0x3526, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x3558, 0x080c, - 0x73a5, 0x0904, 0x3558, 0x0126, 0x2091, 0x8000, 0x6254, 0x6074, - 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x28a9, 0x080c, 0x5906, - 0x012e, 0x0804, 0x3526, 0x012e, 0x0804, 0x355b, 0x0006, 0x0016, - 0x00c6, 0x00e6, 0x2001, 0x19a8, 0x2070, 0x2061, 0x1847, 0x6008, - 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x8f51, 0x7206, 0x00ee, - 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3528, 0x7884, 0xd0fc, - 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, - 0x0804, 0x355b, 0x2001, 0x002a, 0x2004, 0x2069, 0x1847, 0x6908, - 0x9102, 0x1230, 0x012e, 0x0804, 0x355b, 0x012e, 0x0804, 0x3558, - 0x080c, 0xaddb, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3ad7, 0x00c6, - 0x080c, 0x4ab4, 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, - 0x7898, 0xa80e, 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, - 0x2001, 0x002f, 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, - 0x2001, 0x0031, 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, - 0x2001, 0x0035, 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, - 0x0003, 0x9084, 0x00fc, 0x8004, 0xa816, 0x080c, 0x3c5d, 0x0928, - 0x7014, 0x2048, 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, - 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, - 0x4afd, 0x701f, 0x3b9a, 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3a46, 0x2001, 0x199e, 0x2003, 0x0000, 0x2021, 0x000a, - 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, - 0x60bf, 0x0012, 0x080c, 0x3ccc, 0x080c, 0x3c8b, 0x00f6, 0x00e6, - 0x0086, 0x2940, 0x2071, 0x1a65, 0x2079, 0x0090, 0x00d6, 0x2069, - 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, - 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x405f, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3f8c, 0x080c, 0x3e91, - 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, - 0x40d3, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, - 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, - 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, - 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, - 0x715c, 0x9106, 0x1190, 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, - 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, - 0x080c, 0x3e9b, 0x080c, 0x3c86, 0x0058, 0x080c, 0x3c86, 0x080c, - 0x3ff7, 0x080c, 0x3f82, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, - 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x12ed, 0x2009, 0x0028, 0x080c, 0x23d4, - 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x199e, 0x2004, - 0x9005, 0x1118, 0x012e, 0x0804, 0x3526, 0x012e, 0x2021, 0x400c, - 0x0804, 0x3528, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, - 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, - 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3bf6, 0x2048, 0x1f04, - 0x3baa, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, - 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, - 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x080c, 0x4afd, 0x701f, 0x3b9a, 0x00b0, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, - 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f7c, 0x000e, 0x080c, - 0x4b00, 0x701f, 0x3b9a, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, - 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3c5b, 0x0450, 0x7014, - 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, 0x080c, 0x65a7, - 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, - 0xd013, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, - 0x003e, 0x002e, 0x001e, 0x0904, 0x3558, 0x0016, 0x0026, 0x0036, - 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, - 0x3c2d, 0x7007, 0x0003, 0x0804, 0x3beb, 0xa830, 0x9086, 0x0100, - 0x2021, 0x400c, 0x0904, 0x3528, 0x0076, 0xad10, 0xac0c, 0xab24, - 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, + 0x8000, 0x8000, 0x2071, 0x189e, 0x7003, 0x0002, 0x9006, 0x7016, + 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, 0x7046, 0x703b, 0x18ba, + 0x703f, 0x18ba, 0x7007, 0x0001, 0x080c, 0x1018, 0x090c, 0x0dd5, + 0x2900, 0x706a, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1018, + 0x090c, 0x0dd5, 0x2900, 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, + 0x0005, 0x2071, 0x189e, 0x7004, 0x0002, 0x3461, 0x3462, 0x3475, + 0x3489, 0x0005, 0x1004, 0x3472, 0x0e04, 0x3472, 0x2079, 0x0000, + 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, + 0x012e, 0x0468, 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, + 0x18b8, 0x2c4c, 0xa86c, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, + 0x0904, 0x355d, 0x0005, 0x7018, 0x2048, 0x2061, 0x1800, 0x701c, + 0x0807, 0x7014, 0x2048, 0xa864, 0x9094, 0x00ff, 0x9296, 0x0029, + 0x1120, 0xaa78, 0xd2fc, 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, + 0x0005, 0x2079, 0x0000, 0x2061, 0x1800, 0x701c, 0x0807, 0x2061, + 0x1800, 0x7880, 0x908a, 0x0040, 0x1210, 0x61d0, 0x0042, 0x2100, + 0x908a, 0x003f, 0x1a04, 0x355a, 0x61d0, 0x0804, 0x34ef, 0x3531, + 0x3569, 0x355a, 0x3573, 0x357d, 0x3583, 0x3587, 0x3597, 0x359b, + 0x35b1, 0x35b7, 0x35bd, 0x35c8, 0x35d3, 0x35e2, 0x35f1, 0x35ff, + 0x3616, 0x3631, 0x355a, 0x36da, 0x3718, 0x37be, 0x37cf, 0x37f2, + 0x355a, 0x355a, 0x355a, 0x382a, 0x3846, 0x384f, 0x387e, 0x3884, + 0x355a, 0x38ca, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x38d5, + 0x38de, 0x38e6, 0x38e8, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, + 0x355a, 0x3914, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x3931, + 0x3992, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x0002, + 0x39bc, 0x39bf, 0x3a1e, 0x3a37, 0x3a67, 0x3d05, 0x355a, 0x52bb, + 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, 0x355a, + 0x35b1, 0x35b7, 0x4226, 0x5706, 0x4244, 0x534a, 0x539b, 0x549e, + 0x355a, 0x5500, 0x553c, 0x556d, 0x5671, 0x559a, 0x55f1, 0x355a, + 0x4248, 0x4409, 0x441f, 0x4444, 0x44a9, 0x451d, 0x453d, 0x45b4, + 0x4610, 0x466c, 0x466f, 0x4694, 0x4730, 0x4796, 0x479e, 0x48d0, + 0x4a48, 0x4a7c, 0x4ce0, 0x355a, 0x4cfe, 0x4da3, 0x4e85, 0x4edf, + 0x355a, 0x4f94, 0x355a, 0x4ffa, 0x5015, 0x479e, 0x525b, 0x714c, + 0x0000, 0x2021, 0x4000, 0x080c, 0x4afa, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x353b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, + 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, + 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x119b, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, + 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, + 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, + 0x0850, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, + 0x7990, 0x0804, 0x4b07, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, + 0x7a8c, 0x7884, 0x7990, 0x0804, 0x4b0a, 0x7984, 0x7888, 0x2114, + 0x200a, 0x0804, 0x3531, 0x7984, 0x2114, 0x0804, 0x3531, 0x20e1, + 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, + 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x3531, 0x7884, + 0x2060, 0x0804, 0x35e4, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, + 0x0002, 0x789b, 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, + 0x9005, 0x0118, 0x7896, 0x0804, 0x3531, 0x7897, 0x0001, 0x0804, + 0x3531, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x356d, 0x2039, + 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x3577, 0x79a0, 0x9182, 0x0040, + 0x0210, 0x0804, 0x3566, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x356d, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x3566, 0x2138, 0x7d98, + 0x7c9c, 0x0804, 0x3577, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x3566, 0x21e8, 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, + 0x0804, 0x3531, 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, + 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, 0x0904, 0x3531, 0x0804, + 0x3560, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x3566, 0x21e0, + 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, 0x0804, 0x3531, 0x2069, + 0x1847, 0x7884, 0x7990, 0x911a, 0x1a04, 0x3566, 0x8019, 0x0904, + 0x3566, 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, + 0x685a, 0x685e, 0x080c, 0x76ca, 0x0804, 0x3531, 0x2069, 0x1847, + 0x7884, 0x7994, 0x911a, 0x1a04, 0x3566, 0x8019, 0x0904, 0x3566, + 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, + 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, 0x69ef, 0x012e, 0x0804, + 0x3531, 0x902e, 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, + 0x3563, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, + 0x20a1, 0x18a6, 0x4101, 0x080c, 0x4abe, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3563, 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, + 0x080c, 0x4b07, 0x701f, 0x3655, 0x0005, 0xa864, 0x2008, 0x9084, + 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, + 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, + 0x3563, 0x810f, 0x918c, 0x00ff, 0x0904, 0x3563, 0x7112, 0x7010, + 0x8001, 0x0560, 0x7012, 0x080c, 0x4abe, 0x1120, 0x2009, 0x0002, + 0x0804, 0x3563, 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, + 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, + 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4b07, + 0x701f, 0x3693, 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, + 0x0120, 0x9096, 0x000a, 0x1904, 0x3563, 0x0888, 0x7014, 0x2048, + 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0029, + 0x1160, 0xc2fd, 0xaa7a, 0x080c, 0x619e, 0x0150, 0x0126, 0x2091, + 0x8000, 0xa87a, 0xa982, 0x012e, 0x0050, 0x080c, 0x64cb, 0x1128, + 0x7007, 0x0003, 0x701f, 0x36bf, 0x0005, 0x080c, 0x6ec7, 0x0126, + 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, + 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, + 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, + 0x0804, 0x4b0a, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, + 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, + 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, + 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, + 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a18, 0x2004, 0x9005, + 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, + 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, + 0x81ff, 0x1904, 0x3563, 0x7984, 0x080c, 0x6616, 0x1904, 0x3566, + 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x3566, 0x7c88, + 0x7d8c, 0x080c, 0x6779, 0x080c, 0x6748, 0x0000, 0x1518, 0x2061, + 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, + 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, + 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, + 0x1a04, 0x3563, 0x0c30, 0x080c, 0xc77b, 0x012e, 0x0904, 0x3563, + 0x0804, 0x3531, 0x900e, 0x2001, 0x0005, 0x080c, 0x6ec7, 0x0126, + 0x2091, 0x8000, 0x080c, 0xce54, 0x080c, 0x6c94, 0x012e, 0x0804, + 0x3531, 0x00a6, 0x2950, 0xb198, 0x080c, 0x6616, 0x1904, 0x37ab, + 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, + 0x080c, 0x6779, 0x080c, 0x6748, 0x1520, 0x2061, 0x1cd0, 0x0126, + 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, + 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, + 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, + 0x12b0, 0x0c28, 0x080c, 0xc77b, 0x012e, 0x2009, 0x0003, 0x0178, + 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x6ec7, 0x0126, 0x2091, + 0x8000, 0x080c, 0xce54, 0x080c, 0x6c88, 0x012e, 0x0070, 0xb097, + 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, + 0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, + 0x3563, 0x080c, 0x4ad5, 0x0904, 0x3566, 0x080c, 0x66dd, 0x0904, + 0x3563, 0x080c, 0x677f, 0x0904, 0x3563, 0x0804, 0x4534, 0x81ff, + 0x1904, 0x3563, 0x080c, 0x4af1, 0x0904, 0x3566, 0x080c, 0x680d, + 0x0904, 0x3563, 0x2019, 0x0005, 0x79a8, 0x080c, 0x679a, 0x0904, + 0x3563, 0x7888, 0x908a, 0x1000, 0x1a04, 0x3566, 0x8003, 0x800b, + 0x810b, 0x9108, 0x080c, 0x8507, 0x7984, 0xd184, 0x1904, 0x3531, + 0x0804, 0x4534, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, + 0x0001, 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, + 0x2508, 0x080c, 0x6616, 0x11d8, 0x080c, 0x680d, 0x1128, 0x2009, + 0x0002, 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, + 0x679a, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, + 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8507, 0x8529, + 0x1ae0, 0x012e, 0x0804, 0x3531, 0x012e, 0x0804, 0x3563, 0x012e, + 0x0804, 0x3566, 0x080c, 0x4ad5, 0x0904, 0x3566, 0x080c, 0x66dd, + 0x0904, 0x3563, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, + 0x929d, 0x0076, 0x903e, 0x080c, 0x9170, 0x900e, 0x080c, 0xe326, + 0x007e, 0x00ce, 0x080c, 0x6779, 0x0804, 0x3531, 0x080c, 0x4ad5, + 0x0904, 0x3566, 0x080c, 0x6779, 0x2208, 0x0804, 0x3531, 0x0156, + 0x00d6, 0x00e6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, + 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, + 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04, + 0x3860, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x3531, + 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, + 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, + 0x6910, 0x62bc, 0x0804, 0x3531, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x3563, 0x0126, 0x2091, 0x8000, 0x080c, 0x56f6, 0x0128, + 0x2009, 0x0007, 0x012e, 0x0804, 0x3563, 0x012e, 0x615c, 0x9190, + 0x3332, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, + 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, + 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, + 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, + 0x0068, 0x080c, 0x73b3, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, + 0x0120, 0x2009, 0x0005, 0x0804, 0x3563, 0x9036, 0x7e9a, 0x7f9e, + 0x0804, 0x3531, 0x614c, 0x6250, 0x2019, 0x1985, 0x231c, 0x2001, + 0x1986, 0x2004, 0x789a, 0x0804, 0x3531, 0x0126, 0x2091, 0x8000, + 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x3531, 0x080c, 0x4af1, + 0x0904, 0x3566, 0xba44, 0xbb38, 0x0804, 0x3531, 0x080c, 0x0dd5, + 0x080c, 0x4af1, 0x2110, 0x0904, 0x3566, 0xb804, 0x908c, 0x00ff, + 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, + 0x0009, 0x1904, 0x3563, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, + 0x00c6, 0x9066, 0x080c, 0xa7f8, 0x080c, 0x929d, 0x0076, 0x903e, + 0x080c, 0x9170, 0x900e, 0x080c, 0xe326, 0x007e, 0x00ce, 0xb807, + 0x0407, 0x012e, 0x0804, 0x3531, 0x614c, 0x6250, 0x7884, 0x604e, + 0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, + 0x2069, 0x1985, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, + 0x2031, 0x07d0, 0x2069, 0x1986, 0x2d04, 0x266a, 0x789a, 0x0804, + 0x3531, 0x0126, 0x2091, 0x8000, 0x7884, 0x603a, 0xd0c4, 0x01a8, + 0x00d6, 0x78a8, 0x2009, 0x199c, 0x200a, 0x78ac, 0x2011, 0x199d, + 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, + 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7884, 0xd0b4, 0x0120, + 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x7888, 0x603e, 0x2011, 0x0114, + 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, + 0xff7f, 0x2112, 0x788c, 0x6042, 0x9084, 0x0020, 0x0130, 0x78b4, + 0x6046, 0x9084, 0x0001, 0x090c, 0x4226, 0x6040, 0xd0cc, 0x0120, + 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x3531, 0x00f6, + 0x2079, 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, + 0x9084, 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, + 0x7a3a, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, + 0x00fe, 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, + 0x3566, 0x788c, 0x902d, 0x0904, 0x3566, 0x900e, 0x080c, 0x6616, + 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, + 0x8108, 0x0ca0, 0x080c, 0x4af1, 0x0904, 0x3566, 0x7888, 0x900d, + 0x0904, 0x3566, 0x788c, 0x9005, 0x0904, 0x3566, 0xba44, 0xb946, + 0xbb38, 0xb83a, 0x0804, 0x3531, 0x2011, 0xbc09, 0x0010, 0x2011, + 0xbc05, 0x080c, 0x56f6, 0x1904, 0x3563, 0x00c6, 0x2061, 0x0100, + 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, + 0xff00, 0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, 0x3332, 0x210d, + 0x918c, 0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, + 0x0580, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, + 0xae09, 0x000e, 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, + 0x65bb, 0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, + 0x4abe, 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, + 0xc0fd, 0xa86a, 0x701f, 0x3a17, 0x2900, 0x6016, 0x2009, 0x0032, + 0x080c, 0xaeda, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, + 0x3563, 0x00ce, 0x0804, 0x3566, 0x080c, 0xae5f, 0x0cb0, 0xa830, + 0x9086, 0x0100, 0x0904, 0x3563, 0x0804, 0x3531, 0x2061, 0x1a70, + 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, + 0x2061, 0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, + 0x78aa, 0x012e, 0x0804, 0x3531, 0x900e, 0x2110, 0x0c88, 0x81ff, + 0x1904, 0x3563, 0x080c, 0x73b3, 0x0904, 0x3563, 0x0126, 0x2091, + 0x8000, 0x6254, 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, + 0x28b4, 0x080c, 0x5910, 0x012e, 0x0804, 0x3531, 0x012e, 0x0804, + 0x3566, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19a8, 0x2070, + 0x2061, 0x1847, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, + 0x8f70, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, + 0x3533, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, + 0x00e1, 0x0288, 0x012e, 0x0804, 0x3566, 0x2001, 0x002a, 0x2004, + 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, 0x012e, 0x0804, 0x3566, + 0x012e, 0x0804, 0x3563, 0x080c, 0xadc9, 0x0dd0, 0x7884, 0xd0fc, + 0x0904, 0x3ae2, 0x00c6, 0x080c, 0x4abe, 0x00ce, 0x0d88, 0xa867, + 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, 0xa812, 0x2001, + 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, 0xa81e, 0x2001, + 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, 0xa826, 0x2001, + 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, 0xa82e, 0x2001, + 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, 0x8004, 0xa816, + 0x080c, 0x3c68, 0x0928, 0x7014, 0x2048, 0xad2c, 0xac28, 0xab1c, + 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, - 0x080c, 0x0f7c, 0x000e, 0x080c, 0x4b00, 0x007e, 0x701f, 0x3b9a, - 0x7023, 0x0001, 0x0005, 0x0804, 0x3526, 0x0156, 0x00c6, 0xa814, - 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, - 0x81ff, 0x0168, 0x0016, 0x080c, 0x4ab4, 0x001e, 0x0130, 0xa800, - 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, - 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, - 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, 0x199e, - 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, - 0x2001, 0x19a9, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19a8, - 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x4ab4, 0xa813, - 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, - 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, - 0x0100, 0x2001, 0x19a8, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, - 0x23d4, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, - 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x4ab4, 0x2940, - 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, - 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, - 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, - 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, - 0x2c32, 0x1130, 0x9006, 0x080c, 0x2b8a, 0x9006, 0x080c, 0x2b6d, - 0x7884, 0x9084, 0x0007, 0x0002, 0x3d17, 0x3d20, 0x3d29, 0x3d14, - 0x3d14, 0x3d14, 0x3d14, 0x3d14, 0x012e, 0x0804, 0x355b, 0x2009, - 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3ee5, 0x00c0, - 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, 0x3ee5, - 0x0078, 0x080c, 0x73a5, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, - 0x3558, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3528, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3a46, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, - 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, 0x41ae, 0x080c, 0x40fe, - 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a65, - 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, - 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x405f, 0x080c, 0x2c3a, 0x080c, 0x2c3a, 0x080c, 0x2c3a, 0x080c, - 0x2c3a, 0x080c, 0x405f, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3f8c, - 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, 0x3e9b, 0x2001, 0x0004, - 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, - 0x3558, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, - 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, - 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x3f6a, 0x2d00, 0x9c05, - 0x9b05, 0x0120, 0x080c, 0x3e9b, 0x0804, 0x3e48, 0x080c, 0x40d3, - 0x080c, 0x3ff7, 0x080c, 0x3f4d, 0x080c, 0x3f82, 0x00f6, 0x2079, - 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3e9b, 0x00fe, - 0x0804, 0x3e48, 0x00fe, 0x080c, 0x3e91, 0x1150, 0x8d68, 0x2001, - 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, 0x3e9b, 0x0080, - 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, - 0x0038, 0x2001, 0x1a61, 0x2004, 0x9086, 0x0000, 0x1904, 0x3d98, - 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, - 0x9605, 0x0904, 0x3e48, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, - 0x9b05, 0x1904, 0x3e48, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, - 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a61, 0x2003, 0x0003, - 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, - 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, - 0x23d4, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, - 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, - 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3e1f, 0x00ce, 0x0030, - 0xa817, 0x0001, 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, - 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, - 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3d52, - 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, - 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, - 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x12ed, 0x7884, - 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, - 0x23d4, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, - 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, - 0x0010, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, + 0x9080, 0x001b, 0x080c, 0x4b07, 0x701f, 0x3ba5, 0x7023, 0x0001, + 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3a51, 0x2001, 0x199e, 0x2003, + 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, + 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3cd7, 0x080c, + 0x3c96, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a65, 0x2079, + 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, + 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x406a, 0x008e, 0x00ee, 0x00fe, 0x080c, + 0x3f97, 0x080c, 0x3e9c, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, + 0x0140, 0x1db8, 0x080c, 0x40de, 0x00f6, 0x2079, 0x0300, 0x78bc, + 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, + 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, + 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, + 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x1820, + 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, + 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3ea6, 0x080c, 0x3c91, 0x0058, + 0x080c, 0x3c91, 0x080c, 0x4002, 0x080c, 0x3f8d, 0x2001, 0x020b, + 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, + 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, + 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x12ed, 0x2009, + 0x0028, 0x080c, 0x23df, 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, + 0x2001, 0x199e, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x3531, + 0x012e, 0x2021, 0x400c, 0x0804, 0x3533, 0x0016, 0x0026, 0x0036, + 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, + 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, + 0x3c01, 0x2048, 0x1f04, 0x3bb5, 0x7068, 0x2040, 0xa28c, 0xa390, + 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, + 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, + 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, + 0xffc0, 0x9080, 0x001b, 0x080c, 0x4b07, 0x701f, 0x3ba5, 0x00b0, + 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, + 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, + 0x0f7c, 0x000e, 0x080c, 0x4b0a, 0x701f, 0x3ba5, 0x015e, 0x00de, + 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, + 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, + 0x3c66, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, + 0x007f, 0x080c, 0x65b5, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, + 0xb817, 0xfffd, 0x080c, 0xd023, 0x015e, 0x00de, 0x009e, 0x008e, + 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x3563, + 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, + 0x00d6, 0x0156, 0x701f, 0x3c38, 0x7007, 0x0003, 0x0804, 0x3bf6, + 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x3533, 0x0076, + 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, + 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, + 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, + 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f7c, 0x000e, 0x080c, 0x4b0a, + 0x007e, 0x701f, 0x3ba5, 0x7023, 0x0001, 0x0005, 0x0804, 0x3531, + 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, + 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x4abe, + 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, + 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, + 0x0005, 0x2001, 0x199e, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x2061, 0x0200, 0x2001, 0x19a9, 0x2004, 0x601a, 0x2061, + 0x0100, 0x2001, 0x19a8, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, + 0x080c, 0x4abe, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, + 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, + 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19a8, 0x2004, 0x6036, + 0x2009, 0x0040, 0x080c, 0x23df, 0x2001, 0x002a, 0x2004, 0x9084, + 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, + 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, + 0x080c, 0x4abe, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, + 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, + 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, + 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, + 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, + 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x81ff, 0x0148, 0x080c, 0x2c3d, 0x1130, 0x9006, 0x080c, 0x2b95, + 0x9006, 0x080c, 0x2b78, 0x7884, 0x9084, 0x0007, 0x0002, 0x3d22, + 0x3d2b, 0x3d34, 0x3d1f, 0x3d1f, 0x3d1f, 0x3d1f, 0x3d1f, 0x012e, + 0x0804, 0x3566, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, + 0x080c, 0x3ef0, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, + 0x200a, 0x080c, 0x3ef0, 0x0078, 0x080c, 0x73b3, 0x1128, 0x012e, + 0x2009, 0x0016, 0x0804, 0x3563, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x3533, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3a51, 0x2009, 0x0101, 0x210c, + 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, + 0x41b9, 0x080c, 0x4109, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, + 0x2940, 0x2071, 0x1a65, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, + 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, + 0x2011, 0x0001, 0x080c, 0x406a, 0x080c, 0x2c45, 0x080c, 0x2c45, + 0x080c, 0x2c45, 0x080c, 0x2c45, 0x080c, 0x406a, 0x008e, 0x00ee, + 0x00fe, 0x080c, 0x3f97, 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, + 0x3ea6, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, - 0x1118, 0x012e, 0x0804, 0x3526, 0x012e, 0x2021, 0x400c, 0x0804, - 0x3528, 0x9085, 0x0001, 0x1d04, 0x3e9a, 0x2091, 0x6000, 0x8420, - 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2001, 0x1a61, 0x2003, 0x0000, 0x0071, - 0x2009, 0x0048, 0x080c, 0x23d4, 0x2001, 0x0227, 0x2024, 0x2402, - 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, - 0x2071, 0x1a65, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x23d4, 0x782c, 0xd0fc, 0x0d88, 0x080c, - 0x40d3, 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x23d4, 0x782b, 0x0002, - 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, 0x2889, 0x7850, - 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, - 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, - 0x1d04, 0x3f00, 0x2091, 0x6000, 0x1f04, 0x3f00, 0x7850, 0x9085, - 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, - 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, - 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, - 0xa001, 0x1f04, 0x3f20, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, - 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, - 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, - 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, - 0x080c, 0x2cf1, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, - 0x2cf1, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, - 0x00f6, 0x00e6, 0x2071, 0x1a61, 0x2079, 0x0320, 0x2001, 0x0201, - 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, - 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, - 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, - 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, - 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, - 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, - 0x19a9, 0x2004, 0x70e2, 0x080c, 0x3c7c, 0x1188, 0x2001, 0x1820, - 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, - 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, - 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, 0x210c, 0x716e, 0x7063, - 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, - 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, - 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, - 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, - 0x7016, 0x080c, 0x40d3, 0x00f6, 0x2071, 0x1a61, 0x2079, 0x0320, - 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, - 0x6898, 0x780a, 0x00de, 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, - 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x405f, - 0x2011, 0x0001, 0x080c, 0x405f, 0x00fe, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x1a61, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, - 0x405c, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x4058, 0x7000, - 0x0002, 0x405c, 0x400d, 0x403d, 0x4058, 0xd1bc, 0x1170, 0xd1dc, - 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x405f, 0x0904, - 0x405c, 0x080c, 0x405f, 0x0804, 0x405c, 0x00f6, 0x2079, 0x0300, - 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, - 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3f6a, - 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, - 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, - 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x4001, 0x2011, 0x0001, - 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, - 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, 0x0828, - 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0xa014, - 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, 0x2048, - 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a, 0x0007, - 0x1a0c, 0x0dd5, 0x9398, 0x408d, 0x231d, 0x083f, 0x9080, 0x0004, - 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, 0x0035, - 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001, 0x0019, - 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x40ca, 0x40c1, 0x40b8, - 0x40af, 0x40a6, 0x409d, 0x4094, 0xa964, 0x7902, 0xa968, 0x7906, - 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, 0xa978, - 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, 0x7902, - 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005, 0xa994, - 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, 0xa9a0, 0x7916, 0x0005, - 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0, 0x7916, - 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912, 0xa9c0, - 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, 0x7912, - 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, 0x1a65, - 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2940, - 0x9026, 0x7000, 0x0002, 0x40fa, 0x40e6, 0x40f1, 0x8001, 0x7002, - 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x405f, 0x190c, 0x405f, - 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, - 0x080c, 0x405f, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19a9, 0x2004, 0x601a, - 0x2061, 0x0100, 0x2001, 0x19a8, 0x2004, 0x60ce, 0x6104, 0xc1ac, - 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, - 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4ab4, 0xa813, - 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, - 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4176, 0x1d68, 0x2900, - 0xa85a, 0x00d0, 0x080c, 0x4ab4, 0xa813, 0x0019, 0xa817, 0x0001, - 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, - 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, - 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, 0x0100, - 0x2001, 0x19a8, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x23d4, - 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, - 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, - 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, - 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, - 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, - 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, - 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, - 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, 0x4ab4, - 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, 0x00ae, - 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, - 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030, 0x2024, - 0x2001, 0x0031, 0x201c, 0x080c, 0x4ab4, 0x2940, 0xa813, 0x0019, - 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, - 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, - 0x9080, 0x0019, 0x009e, 0x080c, 0x4176, 0x1d68, 0x2900, 0xa85a, - 0x00d8, 0x080c, 0x4ab4, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, - 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, 0x0031, - 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa06e, - 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003, 0x0004, - 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, 0x0200, - 0x2102, 0xa017, 0x0000, 0x2001, 0x1a61, 0x2003, 0x0003, 0x2001, - 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, - 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, - 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0007, - 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x20a9, 0x000c, - 0x20a1, 0xfff4, 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009, 0x013c, - 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, - 0x3526, 0x7d98, 0x7c9c, 0x0804, 0x3628, 0x080c, 0x73a5, 0x190c, - 0x5fe8, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847, 0x2d00, - 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, - 0x080c, 0x4afd, 0x701f, 0x4255, 0x0005, 0x080c, 0x56e7, 0x1130, - 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, 0x1847, - 0x6800, 0x9005, 0x0904, 0x355b, 0x6804, 0xd0ac, 0x0118, 0xd0a4, - 0x0904, 0x355b, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, - 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, - 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, - 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, - 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x355b, 0x9288, - 0x3327, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, 0x0130, 0x6828, - 0x908a, 0x007f, 0x1a04, 0x355b, 0x605e, 0x6888, 0x9084, 0x0030, - 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x19b0, 0x9080, - 0x297c, 0x2005, 0x200a, 0x000e, 0x2009, 0x19b1, 0x9080, 0x2980, - 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x355b, 0x908a, - 0x0841, 0x1a04, 0x355b, 0x9084, 0x0007, 0x1904, 0x355b, 0x680c, - 0x9005, 0x0904, 0x355b, 0x6810, 0x9005, 0x0904, 0x355b, 0x6848, - 0x6940, 0x910a, 0x1a04, 0x355b, 0x8001, 0x0904, 0x355b, 0x684c, - 0x6944, 0x910a, 0x1a04, 0x355b, 0x8001, 0x0904, 0x355b, 0x2009, - 0x1980, 0x200b, 0x0000, 0x2001, 0x1869, 0x2004, 0xd0c4, 0x0140, - 0x7884, 0x200a, 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, - 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, 0x00ff, 0x6052, - 0x080c, 0x76be, 0x080c, 0x69ad, 0x080c, 0x69e1, 0x6808, 0x602a, - 0x080c, 0x2346, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, - 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x28e3, 0x003e, 0x6000, - 0x9086, 0x0000, 0x1904, 0x43ec, 0x6818, 0x691c, 0x6a20, 0x6b24, - 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, - 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, - 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, - 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, - 0x20a1, 0x19b2, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, - 0x19cc, 0x20e9, 0x0001, 0x4001, 0x080c, 0x85d8, 0x00c6, 0x900e, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, - 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, - 0x12b0, 0x3508, 0x8109, 0x080c, 0x7c74, 0x6878, 0x6016, 0x6874, - 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, - 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, - 0x4346, 0x00ce, 0x00c6, 0x2061, 0x199b, 0x6a88, 0x9284, 0xc000, - 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, - 0x080c, 0x2b8a, 0x2001, 0x0001, 0x080c, 0x2b6d, 0x0088, 0x9286, - 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x2b8a, 0x9006, - 0x080c, 0x2b6d, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, - 0x00ce, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, - 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, - 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197b, 0x6a80, - 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, - 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2958, 0x2001, - 0x196c, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, - 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x73a5, 0x0128, 0x080c, - 0x4fe4, 0x0110, 0x080c, 0x28a9, 0x60d4, 0x9005, 0x01c0, 0x6003, - 0x0001, 0x2009, 0x43d4, 0x00e0, 0x080c, 0x73a5, 0x1168, 0x2011, - 0x723b, 0x080c, 0x84dc, 0x2011, 0x722e, 0x080c, 0x85b6, 0x080c, - 0x7692, 0x080c, 0x72d7, 0x0040, 0x080c, 0x5ee2, 0x0028, 0x6003, - 0x0004, 0x2009, 0x43ec, 0x0020, 0x080c, 0x68dd, 0x0804, 0x3526, - 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, - 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, - 0x0000, 0x0904, 0x3558, 0x2069, 0x1847, 0x7890, 0x6842, 0x7894, - 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x0804, 0x4b00, 0x9006, 0x080c, 0x28a9, 0x81ff, - 0x1904, 0x3558, 0x080c, 0x73a5, 0x11b0, 0x080c, 0x768d, 0x080c, - 0x6023, 0x080c, 0x331b, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, - 0xd24a, 0x0130, 0x080c, 0x73c8, 0x1118, 0x080c, 0x737d, 0x0038, - 0x080c, 0x72d7, 0x0020, 0x080c, 0x5fe8, 0x080c, 0x5ee2, 0x0804, - 0x3526, 0x81ff, 0x1904, 0x3558, 0x080c, 0x73a5, 0x1110, 0x0804, - 0x3558, 0x6194, 0x81ff, 0x01a8, 0x704f, 0x0000, 0x2001, 0x1c80, - 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, - 0x8000, 0x2039, 0x0001, 0x080c, 0x4b00, 0x701f, 0x3524, 0x012e, - 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1c80, 0x20a9, 0x0040, - 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, 0xffff, 0x4304, 0x655c, - 0x9588, 0x3327, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, - 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x6608, 0x1190, 0xb814, - 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085, 0xff00, 0x8007, 0x201a, - 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, - 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, - 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1c80, - 0x2099, 0x1c80, 0x080c, 0x5f73, 0x0804, 0x4446, 0x080c, 0x4ae7, - 0x0904, 0x355b, 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x3558, 0x080c, 0x56d8, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, - 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, - 0x3316, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xcd13, 0x1120, 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, - 0x0003, 0x701f, 0x44d4, 0x0005, 0x080c, 0x4ae7, 0x0904, 0x355b, - 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, - 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, - 0x080c, 0x0f7c, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, - 0x0f7c, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x0804, 0x4b00, 0x81ff, 0x1904, 0x3558, 0x080c, 0x4acb, 0x0904, - 0x355b, 0x080c, 0x677a, 0x0904, 0x3558, 0x0058, 0xa878, 0x9005, - 0x0120, 0x2009, 0x0004, 0x0804, 0x3558, 0xa974, 0xaa94, 0x0804, - 0x3526, 0x080c, 0x56e0, 0x0904, 0x3526, 0x701f, 0x451e, 0x7007, - 0x0003, 0x0005, 0x81ff, 0x1904, 0x3558, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x355b, 0x080c, 0x4ae7, 0x0904, 0x355b, 0x080c, 0x697b, - 0x0120, 0x080c, 0x6983, 0x1904, 0x355b, 0x080c, 0x67ff, 0x0904, - 0x3558, 0x2019, 0x0004, 0x900e, 0x080c, 0x678c, 0x0904, 0x3558, - 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, - 0x080c, 0x4ae5, 0x01e0, 0x080c, 0x697b, 0x0118, 0x080c, 0x6983, - 0x11b0, 0x080c, 0x67ff, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x678c, 0x2009, 0x0003, 0x0120, 0xa998, - 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x080c, 0x56e0, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, - 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x645c, 0x2400, 0x9506, - 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x6608, - 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x84ea, - 0x0005, 0x81ff, 0x1904, 0x3558, 0x798c, 0x2001, 0x197f, 0x918c, - 0x8000, 0x2102, 0x080c, 0x4acb, 0x0904, 0x355b, 0x080c, 0x697b, - 0x0120, 0x080c, 0x6983, 0x1904, 0x355b, 0x080c, 0x66cf, 0x0904, - 0x3558, 0x080c, 0x6783, 0x0904, 0x3558, 0x2001, 0x197f, 0x2004, - 0xd0fc, 0x1904, 0x3526, 0x0804, 0x4529, 0xa9a0, 0x2001, 0x197f, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4ad8, 0x01a0, 0x080c, - 0x697b, 0x0118, 0x080c, 0x6983, 0x1170, 0x080c, 0x66cf, 0x2009, - 0x0002, 0x0128, 0x080c, 0x6783, 0x1170, 0x2009, 0x0003, 0xa897, + 0x2009, 0x0017, 0x080c, 0x3563, 0x0cf8, 0x2001, 0x020b, 0x2004, + 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, + 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, + 0x3f75, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, 0x3ea6, 0x0804, + 0x3e53, 0x080c, 0x40de, 0x080c, 0x4002, 0x080c, 0x3f58, 0x080c, + 0x3f8d, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, + 0x080c, 0x3ea6, 0x00fe, 0x0804, 0x3e53, 0x00fe, 0x080c, 0x3e9c, + 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, + 0x080c, 0x3ea6, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, + 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a61, 0x2004, 0x9086, + 0x0000, 0x1904, 0x3da3, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, + 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3e53, 0x7884, 0xd0bc, + 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3e53, 0xa013, 0x0019, + 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, + 0x1a61, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, + 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, + 0x2009, 0x0040, 0x080c, 0x23df, 0x2900, 0xa85a, 0xa813, 0x0019, + 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, + 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, + 0x3e2a, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, 0x9005, 0x0108, + 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, + 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, + 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, + 0x00fe, 0x0804, 0x3d5d, 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, + 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, + 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, + 0x080c, 0x12ed, 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, + 0x2009, 0x0028, 0x080c, 0x23df, 0x2001, 0x0227, 0x200c, 0x2102, + 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, + 0x6043, 0x0090, 0x6043, 0x0010, 0x00ce, 0x2d08, 0x2c10, 0x2b18, + 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, + 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x3531, 0x012e, + 0x2021, 0x400c, 0x0804, 0x3533, 0x9085, 0x0001, 0x1d04, 0x3ea5, + 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, + 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x1a61, + 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, 0x23df, 0x2001, + 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, + 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a65, 0x7000, 0x9086, 0x0000, + 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, + 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x23df, 0x782c, + 0xd0fc, 0x0d88, 0x080c, 0x40de, 0x7000, 0x9086, 0x0000, 0x1d58, + 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, + 0x23df, 0x782b, 0x0002, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, + 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, + 0x080c, 0x2894, 0x7850, 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, + 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, + 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3f0b, 0x2091, 0x6000, 0x1f04, + 0x3f0b, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, + 0x0021, 0x2004, 0x9084, 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, + 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, + 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x3f2b, 0x7850, 0x9085, + 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, + 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, + 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, + 0x1de0, 0x2001, 0x0100, 0x080c, 0x2cfc, 0x7827, 0x0020, 0x7843, + 0x0000, 0x9006, 0x080c, 0x2cfc, 0x7827, 0x0048, 0x00fe, 0x0005, + 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1a61, 0x2079, + 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, + 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, + 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, + 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, + 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, + 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, + 0x2071, 0x0100, 0x2001, 0x19a9, 0x2004, 0x70e2, 0x080c, 0x3c87, + 0x1188, 0x2001, 0x1820, 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, + 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, + 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, + 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, + 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, + 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, + 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, + 0x1984, 0x9085, 0x0092, 0x7016, 0x080c, 0x40de, 0x00f6, 0x2071, + 0x1a61, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, + 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2009, 0x03e8, + 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, + 0x0011, 0x080c, 0x406a, 0x2011, 0x0001, 0x080c, 0x406a, 0x00fe, + 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a61, 0x2079, 0x0320, + 0x792c, 0xd1fc, 0x0904, 0x4067, 0x782b, 0x0002, 0x9026, 0xd19c, + 0x1904, 0x4063, 0x7000, 0x0002, 0x4067, 0x4018, 0x4048, 0x4063, + 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, + 0x080c, 0x406a, 0x0904, 0x4067, 0x080c, 0x406a, 0x0804, 0x4067, + 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, + 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, + 0x0de8, 0x080c, 0x3f75, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, + 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, + 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, + 0x400c, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, + 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, + 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, + 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, + 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, + 0x831c, 0x938a, 0x0007, 0x1a0c, 0x0dd5, 0x9398, 0x4098, 0x231d, + 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, + 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, + 0xa05a, 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, + 0x40d5, 0x40cc, 0x40c3, 0x40ba, 0x40b1, 0x40a8, 0x409f, 0xa964, + 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, + 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, + 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, + 0x7916, 0x0005, 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, + 0xa9a0, 0x7916, 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, + 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, + 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, + 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, + 0x0086, 0x2071, 0x1a65, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, + 0x782b, 0x0002, 0x2940, 0x9026, 0x7000, 0x0002, 0x4105, 0x40f1, + 0x40fc, 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, + 0x406a, 0x190c, 0x406a, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, + 0x1d38, 0x2011, 0x0001, 0x080c, 0x406a, 0x008e, 0x00ee, 0x00fe, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, + 0x19a9, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19a8, 0x2004, + 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, + 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, + 0x080c, 0x4abe, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, + 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, + 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, + 0x4181, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4abe, 0xa813, + 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, + 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, + 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, + 0x0090, 0x2079, 0x0100, 0x2001, 0x19a8, 0x2004, 0x6036, 0x2009, + 0x0040, 0x080c, 0x23df, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, + 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, + 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, + 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, + 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, + 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, + 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, + 0x0086, 0x080c, 0x4abe, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, + 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, + 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, + 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4abe, + 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, + 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, + 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4181, + 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4abe, 0x2940, 0xa013, + 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, + 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, + 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, + 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, + 0x200c, 0x918d, 0x0200, 0x2102, 0xa017, 0x0000, 0x2001, 0x1a61, + 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, + 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, + 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, + 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, + 0x4004, 0x20a9, 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, 0x9006, + 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, + 0x0108, 0x0005, 0x0804, 0x3531, 0x7d98, 0x7c9c, 0x0804, 0x3633, + 0x080c, 0x73b3, 0x190c, 0x5ff2, 0x6040, 0x9084, 0x0020, 0x09b1, + 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x2039, 0x0001, 0x080c, 0x4b07, 0x701f, 0x4260, 0x0005, + 0x080c, 0x56f1, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, + 0x21d0, 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x3566, 0x6804, + 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3566, 0xd094, 0x00c6, 0x2061, + 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, + 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, + 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, + 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, + 0x1a04, 0x3566, 0x9288, 0x3332, 0x210d, 0x918c, 0x00ff, 0x6166, + 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x3566, 0x605e, + 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, + 0x2009, 0x19b0, 0x9080, 0x2987, 0x2005, 0x200a, 0x000e, 0x2009, + 0x19b1, 0x9080, 0x298b, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, + 0x0a04, 0x3566, 0x908a, 0x0841, 0x1a04, 0x3566, 0x9084, 0x0007, + 0x1904, 0x3566, 0x680c, 0x9005, 0x0904, 0x3566, 0x6810, 0x9005, + 0x0904, 0x3566, 0x6848, 0x6940, 0x910a, 0x1a04, 0x3566, 0x8001, + 0x0904, 0x3566, 0x684c, 0x6944, 0x910a, 0x1a04, 0x3566, 0x8001, + 0x0904, 0x3566, 0x2009, 0x1980, 0x200b, 0x0000, 0x2001, 0x1869, + 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, 0x2009, 0x017f, 0x200a, + 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, + 0x9084, 0x00ff, 0x6052, 0x080c, 0x76ca, 0x080c, 0x69bb, 0x080c, + 0x69ef, 0x6808, 0x602a, 0x080c, 0x2351, 0x2009, 0x0170, 0x200b, + 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, + 0x28ee, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x43f7, 0x6818, + 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, + 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, + 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, + 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, + 0x831f, 0x20a9, 0x0004, 0x20a1, 0x19b2, 0x20e9, 0x0001, 0x4001, + 0x20a9, 0x0004, 0x20a1, 0x19cc, 0x20e9, 0x0001, 0x4001, 0x080c, + 0x85f5, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, + 0x0068, 0x2009, 0x0100, 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, + 0x0010, 0x83f5, 0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7c81, + 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, + 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, + 0x6003, 0x0001, 0x1f04, 0x4351, 0x00ce, 0x00c6, 0x2061, 0x199b, + 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, + 0x0000, 0x2001, 0x0001, 0x080c, 0x2b95, 0x2001, 0x0001, 0x080c, + 0x2b78, 0x0088, 0x9286, 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, + 0x080c, 0x2b95, 0x9006, 0x080c, 0x2b78, 0x0028, 0x9286, 0x8000, + 0x1d30, 0x2063, 0x0002, 0x00ce, 0x6888, 0xd0ec, 0x0130, 0x2011, + 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, + 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, + 0x2001, 0x197b, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, + 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, + 0x080c, 0x2963, 0x2001, 0x196c, 0x2102, 0x0008, 0x2102, 0x00c6, + 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, + 0x73b3, 0x0128, 0x080c, 0x4fee, 0x0110, 0x080c, 0x28b4, 0x60d4, + 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, 0x43df, 0x00e0, 0x080c, + 0x73b3, 0x1168, 0x2011, 0x7249, 0x080c, 0x84f9, 0x2011, 0x723c, + 0x080c, 0x85d3, 0x080c, 0x769e, 0x080c, 0x72e5, 0x0040, 0x080c, + 0x5eec, 0x0028, 0x6003, 0x0004, 0x2009, 0x43f7, 0x0020, 0x080c, + 0x68eb, 0x0804, 0x3531, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, + 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, + 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x3563, 0x2069, 0x1847, + 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4b0a, 0x9006, + 0x080c, 0x28b4, 0x81ff, 0x1904, 0x3563, 0x080c, 0x73b3, 0x11b0, + 0x080c, 0x7699, 0x080c, 0x602d, 0x080c, 0x3326, 0x0118, 0x6130, + 0xc18d, 0x6132, 0x080c, 0xd25a, 0x0130, 0x080c, 0x73d6, 0x1118, + 0x080c, 0x738b, 0x0038, 0x080c, 0x72e5, 0x0020, 0x080c, 0x5ff2, + 0x080c, 0x5eec, 0x0804, 0x3531, 0x81ff, 0x1904, 0x3563, 0x080c, + 0x73b3, 0x1110, 0x0804, 0x3563, 0x6194, 0x81ff, 0x01a8, 0x704f, + 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, 0x080c, 0x4b0a, + 0x701f, 0x352f, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, + 0x1c80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, + 0xffff, 0x4304, 0x655c, 0x9588, 0x3332, 0x210d, 0x918c, 0x00ff, + 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, + 0x6616, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085, + 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4, + 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, + 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, + 0x0040, 0x20a1, 0x1c80, 0x2099, 0x1c80, 0x080c, 0x5f7d, 0x0804, + 0x4451, 0x080c, 0x4af1, 0x0904, 0x3566, 0x080c, 0x4abe, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3563, 0x080c, 0x56e2, 0xd0b4, 0x0558, + 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, + 0x0080, 0x0508, 0x080c, 0x3321, 0x1148, 0xb800, 0xd08c, 0x11d8, + 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, + 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd23, 0x1120, 0x2009, 0x0003, + 0x0804, 0x3563, 0x7007, 0x0003, 0x701f, 0x44df, 0x0005, 0x080c, + 0x4af1, 0x0904, 0x3566, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, + 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, + 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, + 0x9080, 0x0006, 0x2098, 0x080c, 0x0f7c, 0x0070, 0x20a9, 0x0004, + 0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, + 0x000a, 0x2098, 0x080c, 0x0f7c, 0x8906, 0x8006, 0x8007, 0x90bc, + 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b0a, 0x81ff, 0x1904, 0x3563, + 0x080c, 0x4ad5, 0x0904, 0x3566, 0x080c, 0x6788, 0x0904, 0x3563, + 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x3563, + 0xa974, 0xaa94, 0x0804, 0x3531, 0x080c, 0x56ea, 0x0904, 0x3531, + 0x701f, 0x4529, 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x3563, + 0x7888, 0x908a, 0x1000, 0x1a04, 0x3566, 0x080c, 0x4af1, 0x0904, + 0x3566, 0x080c, 0x6989, 0x0120, 0x080c, 0x6991, 0x1904, 0x3566, + 0x080c, 0x680d, 0x0904, 0x3563, 0x2019, 0x0004, 0x900e, 0x080c, + 0x679a, 0x0904, 0x3563, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, + 0x908a, 0x1000, 0x12f8, 0x080c, 0x4aef, 0x01e0, 0x080c, 0x6989, + 0x0118, 0x080c, 0x6991, 0x11b0, 0x080c, 0x680d, 0x2009, 0x0002, + 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x679a, 0x2009, + 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, + 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x0005, 0xa897, 0x4000, 0x080c, 0x56ea, 0x0110, 0x9006, + 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, + 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, + 0x645c, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, + 0x0005, 0x080c, 0x6616, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, + 0x9108, 0x080c, 0x8507, 0x0005, 0x81ff, 0x1904, 0x3563, 0x798c, + 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c, 0x4ad5, 0x0904, + 0x3566, 0x080c, 0x6989, 0x0120, 0x080c, 0x6991, 0x1904, 0x3566, + 0x080c, 0x66dd, 0x0904, 0x3563, 0x080c, 0x6791, 0x0904, 0x3563, + 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, 0x3531, 0x0804, 0x4534, + 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, + 0x4ae2, 0x01a0, 0x080c, 0x6989, 0x0118, 0x080c, 0x6991, 0x1170, + 0x080c, 0x66dd, 0x2009, 0x0002, 0x0128, 0x080c, 0x6791, 0x1170, + 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, + 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56ea, 0x0110, + 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, + 0x81ff, 0x1904, 0x3563, 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, + 0x2102, 0x080c, 0x4ad5, 0x0904, 0x3566, 0x080c, 0x6989, 0x0120, + 0x080c, 0x6991, 0x1904, 0x3566, 0x080c, 0x66dd, 0x0904, 0x3563, + 0x080c, 0x677f, 0x0904, 0x3563, 0x2001, 0x197e, 0x2004, 0xd0fc, + 0x1904, 0x3531, 0x0804, 0x4534, 0xa9a0, 0x2001, 0x197e, 0x918c, + 0x8000, 0xc18d, 0x2102, 0x080c, 0x4ae2, 0x01a0, 0x080c, 0x6989, + 0x0118, 0x080c, 0x6991, 0x1170, 0x080c, 0x66dd, 0x2009, 0x0002, + 0x0128, 0x080c, 0x677f, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, + 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, + 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197e, 0x2004, 0xd0fc, + 0x1128, 0x080c, 0x56ea, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0000, 0x0005, 0x6100, 0x0804, 0x3531, 0x080c, + 0x4af1, 0x0904, 0x3566, 0x080c, 0x56f6, 0x1904, 0x3563, 0x79a8, + 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, + 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, + 0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, + 0x918c, 0x0200, 0x0804, 0x3531, 0x78a8, 0x909c, 0x0003, 0xd0ac, + 0x1150, 0xd0b4, 0x1140, 0x939a, 0x0003, 0x1a04, 0x3563, 0x625c, + 0x7884, 0x9206, 0x15e8, 0x080c, 0x85df, 0x2001, 0xffec, 0x7a8c, + 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, + 0x0080, 0x11c8, 0x0006, 0x0036, 0x2001, 0x1a7e, 0x201c, 0x7b9a, + 0x2003, 0x0000, 0x2001, 0x1a7f, 0x201c, 0x7b9e, 0x2003, 0x0000, + 0x2001, 0x1a80, 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, + 0x000e, 0x0804, 0x4b0a, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, + 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, + 0xa59a, 0x080c, 0x10e9, 0x7007, 0x0002, 0x701f, 0x4700, 0x0005, + 0x81ff, 0x1904, 0x3563, 0x080c, 0x4af1, 0x0904, 0x3566, 0x080c, + 0x6989, 0x1904, 0x3563, 0x00c6, 0x080c, 0x4abe, 0x00ce, 0x0904, + 0x3563, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, + 0xccc9, 0x0904, 0x3563, 0x7007, 0x0003, 0x701f, 0x471a, 0x0005, + 0x080c, 0x4226, 0x0006, 0x0036, 0x2001, 0x1a7e, 0x201c, 0x7b9a, + 0x2003, 0x0000, 0x2001, 0x1a7f, 0x201c, 0x7b9e, 0x2003, 0x0000, + 0x2001, 0x1a80, 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, + 0x0804, 0x3531, 0xa830, 0x9086, 0x0100, 0x0904, 0x3563, 0x8906, + 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, + 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b0a, + 0x9006, 0x080c, 0x28b4, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, + 0x0118, 0x81ff, 0x1904, 0x3563, 0x080c, 0x73b3, 0x0110, 0x080c, + 0x5ff2, 0x7888, 0x908a, 0x1000, 0x1a04, 0x3566, 0x7984, 0x9186, + 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x3566, 0x2100, 0x080c, + 0x287e, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x19f9, + 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, 0x0000, + 0x080c, 0x73b3, 0x1158, 0x080c, 0x7699, 0x080c, 0x602d, 0x9085, + 0x0001, 0x080c, 0x73fa, 0x080c, 0x72e5, 0x00d0, 0x080c, 0xadd0, + 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, + 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1998, + 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5f18, 0x080c, 0x8591, + 0x7984, 0x080c, 0x73b3, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, + 0x4597, 0x012e, 0x00ce, 0x002e, 0x0804, 0x3531, 0x7984, 0x080c, + 0x65b5, 0x2b08, 0x1904, 0x3566, 0x0804, 0x3531, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3563, 0x60dc, 0xd0ac, 0x1130, 0xd09c, + 0x1120, 0x2009, 0x0005, 0x0804, 0x3563, 0x080c, 0x4abe, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3563, 0x7984, 0x9192, 0x0021, 0x1a04, + 0x3566, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, + 0x702a, 0xaf60, 0x7736, 0x080c, 0x4b07, 0x701f, 0x47ce, 0x7880, + 0x9086, 0x006e, 0x0110, 0x701f, 0x51a0, 0x0005, 0x2009, 0x0080, + 0x080c, 0x6616, 0x1118, 0x080c, 0x6989, 0x0120, 0x2021, 0x400a, + 0x0804, 0x3533, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, + 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, 0x4867, 0x90be, + 0x0112, 0x0904, 0x4867, 0x90be, 0x0113, 0x0904, 0x4867, 0x90be, + 0x0114, 0x0904, 0x4867, 0x90be, 0x0117, 0x0904, 0x4867, 0x90be, + 0x011a, 0x0904, 0x4867, 0x90be, 0x011c, 0x0904, 0x4867, 0x90be, + 0x0121, 0x0904, 0x484e, 0x90be, 0x0131, 0x0904, 0x484e, 0x90be, + 0x0171, 0x0904, 0x4867, 0x90be, 0x0173, 0x0904, 0x4867, 0x90be, + 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, 0x4872, 0x90be, + 0x0212, 0x0904, 0x485b, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, + 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, + 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, + 0x05b0, 0x009e, 0x00de, 0x0804, 0x3566, 0x7028, 0x9080, 0x0010, + 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, + 0x48b0, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, + 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48b0, 0x00c8, 0x7028, 0x9080, + 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, + 0x080c, 0x48bd, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, + 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48bd, 0x7028, + 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, + 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4abe, 0x0550, 0xa868, 0xc0fd, + 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, + 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, + 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, + 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c, 0xcce4, 0x1120, 0x2009, + 0x0003, 0x0804, 0x3563, 0x7007, 0x0003, 0x701f, 0x48a7, 0x0005, + 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, 0x3563, 0xa820, + 0x9086, 0x8001, 0x1904, 0x3531, 0x2009, 0x0004, 0x0804, 0x3563, + 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, + 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, + 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, + 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3563, 0x60dc, 0xd0ac, + 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3563, 0x7984, + 0x78a8, 0x2040, 0x080c, 0xadc9, 0x1120, 0x9182, 0x007f, 0x0a04, + 0x3566, 0x9186, 0x00ff, 0x0904, 0x3566, 0x9182, 0x0800, 0x1a04, + 0x3566, 0x7a8c, 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, 0x924e, + 0x0904, 0x3566, 0x080c, 0xadc9, 0x1120, 0x99cc, 0xff00, 0x0904, + 0x3566, 0x0126, 0x2091, 0x8000, 0x080c, 0x49d1, 0x0904, 0x4951, + 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, + 0xb818, 0xbb1c, 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, + 0x9305, 0xbb2c, 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, 0x003e, + 0x0570, 0xd88c, 0x1128, 0x080c, 0x6989, 0x0110, 0xc89d, 0x0438, + 0x900e, 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, + 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, + 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, + 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, + 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x3533, 0x000e, + 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, + 0x080c, 0xaead, 0x0904, 0x49a6, 0x2b00, 0x6012, 0x080c, 0xcfd4, + 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4abe, 0x00ce, 0x2b70, + 0x1158, 0x080c, 0xae5f, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, + 0x2009, 0x0002, 0x0804, 0x3563, 0x900e, 0xa966, 0xa96a, 0x2900, + 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, + 0xd89c, 0x1110, 0x080c, 0x31cc, 0x6023, 0x0001, 0x9006, 0x080c, + 0x6552, 0xd89c, 0x0138, 0x2001, 0x0004, 0x080c, 0x6566, 0x2009, + 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, 0x6566, 0x2009, 0x0002, + 0x080c, 0xaeda, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, + 0x2058, 0xb8cc, 0xc08d, 0xb8ce, 0x9085, 0x0001, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x3563, + 0x7007, 0x0003, 0x701f, 0x49b5, 0x0005, 0xa830, 0x9086, 0x0100, + 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, + 0x0804, 0x563f, 0x900e, 0xa868, 0xd0f4, 0x1904, 0x3531, 0x080c, + 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, + 0x3531, 0x00e6, 0x00d6, 0x0096, 0x83ff, 0x0904, 0x4a20, 0x902e, + 0x080c, 0xadc9, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, + 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, + 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, 0x4a31, 0x2428, 0x94ce, + 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, + 0x1130, 0x92ce, 0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, + 0x0480, 0x2058, 0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, + 0x9206, 0x11c8, 0x2400, 0x9106, 0x1180, 0xd884, 0x0598, 0xd894, + 0x1588, 0x080c, 0x6929, 0x1570, 0x2001, 0x4000, 0x0460, 0x080c, + 0x6989, 0x1540, 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, + 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, + 0x1128, 0x86ff, 0x0918, 0x080c, 0xadc9, 0x1900, 0x2001, 0x4008, + 0x0090, 0x8420, 0x8e70, 0x1f04, 0x49e7, 0x85ff, 0x1130, 0x2001, + 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x65b5, 0x1dd0, + 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3563, 0x080c, 0x4abe, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3563, 0xa867, 0x0000, 0xa868, + 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, 0x3566, 0x9096, 0x00ff, + 0x0120, 0x9092, 0x0004, 0x1a04, 0x3566, 0x2010, 0x2918, 0x080c, + 0x3172, 0x1120, 0x2009, 0x0003, 0x0804, 0x3563, 0x7007, 0x0003, + 0x701f, 0x4a73, 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x3531, + 0x2009, 0x0004, 0x0804, 0x3563, 0x7984, 0x080c, 0xadc9, 0x1120, + 0x9182, 0x007f, 0x0a04, 0x3566, 0x9186, 0x00ff, 0x0904, 0x3566, + 0x9182, 0x0800, 0x1a04, 0x3566, 0x2001, 0x9000, 0x080c, 0x569a, + 0x1904, 0x3563, 0x0804, 0x3531, 0xa998, 0x080c, 0xadc9, 0x1118, + 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, + 0x1250, 0x2001, 0x9000, 0x080c, 0x569a, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x56e0, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x3558, - 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4acb, - 0x0904, 0x355b, 0x080c, 0x697b, 0x0120, 0x080c, 0x6983, 0x1904, - 0x355b, 0x080c, 0x66cf, 0x0904, 0x3558, 0x080c, 0x6771, 0x0904, - 0x3558, 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1904, 0x3526, 0x0804, - 0x4529, 0xa9a0, 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x4ad8, 0x01a0, 0x080c, 0x697b, 0x0118, 0x080c, 0x6983, - 0x1170, 0x080c, 0x66cf, 0x2009, 0x0002, 0x0128, 0x080c, 0x6771, - 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56e0, - 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x6100, 0x0804, 0x3526, 0x080c, 0x4ae7, 0x0904, 0x355b, - 0x080c, 0x56ec, 0x1904, 0x3558, 0x79a8, 0xd184, 0x1158, 0xb834, - 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, 0xba28, - 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, 0x789a, - 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, - 0x3526, 0x78a8, 0x909c, 0x0003, 0xd0b4, 0x1148, 0x939a, 0x0003, - 0x1a04, 0x3558, 0x625c, 0x7884, 0x9206, 0x1904, 0x46d6, 0x080c, - 0x85c2, 0x2001, 0xfff4, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, 0x0080, 0x11c8, - 0x0006, 0x0036, 0x2001, 0x1a7e, 0x201c, 0x7b9a, 0x2003, 0x0000, - 0x2001, 0x1a7f, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a80, - 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, 0x000e, 0x0804, - 0x4b00, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, + 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0000, 0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x0fff, + 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, + 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, + 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6616, + 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, + 0x8bff, 0x0005, 0xa998, 0x080c, 0x6616, 0x1130, 0xae9c, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, + 0x0008, 0x7e84, 0x2608, 0x080c, 0x6616, 0x1108, 0x0008, 0x905e, + 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, + 0x080c, 0x1031, 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, + 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, - 0x10e9, 0x7007, 0x0002, 0x701f, 0x46f6, 0x0005, 0x81ff, 0x1904, - 0x3558, 0x080c, 0x4ae7, 0x0904, 0x355b, 0x080c, 0x697b, 0x1904, - 0x3558, 0x00c6, 0x080c, 0x4ab4, 0x00ce, 0x0904, 0x3558, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xccb9, 0x0904, - 0x3558, 0x7007, 0x0003, 0x701f, 0x4710, 0x0005, 0x080c, 0x421b, - 0x0006, 0x0036, 0x2001, 0x1a7e, 0x201c, 0x7b9a, 0x2003, 0x0000, - 0x2001, 0x1a7f, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a80, - 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, 0x0804, 0x3526, - 0xa830, 0x9086, 0x0100, 0x0904, 0x3558, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b00, 0x9006, 0x080c, - 0x28a9, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, - 0x1904, 0x3558, 0x080c, 0x73a5, 0x0110, 0x080c, 0x5fe8, 0x7888, - 0x908a, 0x1000, 0x1a04, 0x355b, 0x7984, 0x9186, 0x00ff, 0x0138, - 0x9182, 0x007f, 0x1a04, 0x355b, 0x2100, 0x080c, 0x2873, 0x0026, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x19f9, 0x601b, 0x0000, - 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, 0x0000, 0x080c, 0x73a5, - 0x1158, 0x080c, 0x768d, 0x080c, 0x6023, 0x9085, 0x0001, 0x080c, - 0x73ec, 0x080c, 0x72d7, 0x00d0, 0x080c, 0xade2, 0x2061, 0x0100, - 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1998, 0x200b, 0x0000, - 0x2009, 0x002d, 0x2011, 0x5f0e, 0x080c, 0x8574, 0x7984, 0x080c, - 0x73a5, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x458c, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x3526, 0x7984, 0x080c, 0x65a7, 0x2b08, - 0x1904, 0x355b, 0x0804, 0x3526, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x3558, 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, - 0x0005, 0x0804, 0x3558, 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3558, 0x7984, 0x9192, 0x0021, 0x1a04, 0x355b, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, - 0x7736, 0x080c, 0x4afd, 0x701f, 0x47c4, 0x7880, 0x9086, 0x006e, - 0x0110, 0x701f, 0x5196, 0x0005, 0x2009, 0x0080, 0x080c, 0x6608, - 0x1118, 0x080c, 0x697b, 0x0120, 0x2021, 0x400a, 0x0804, 0x3528, - 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, - 0xa884, 0x90be, 0x0100, 0x0904, 0x485d, 0x90be, 0x0112, 0x0904, - 0x485d, 0x90be, 0x0113, 0x0904, 0x485d, 0x90be, 0x0114, 0x0904, - 0x485d, 0x90be, 0x0117, 0x0904, 0x485d, 0x90be, 0x011a, 0x0904, - 0x485d, 0x90be, 0x011c, 0x0904, 0x485d, 0x90be, 0x0121, 0x0904, - 0x4844, 0x90be, 0x0131, 0x0904, 0x4844, 0x90be, 0x0171, 0x0904, - 0x485d, 0x90be, 0x0173, 0x0904, 0x485d, 0x90be, 0x01a1, 0x1128, - 0xa894, 0x8007, 0xa896, 0x0804, 0x4868, 0x90be, 0x0212, 0x0904, - 0x4851, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, - 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, - 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, - 0x00de, 0x0804, 0x355b, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, - 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x48a6, 0x7028, - 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0001, 0x080c, 0x48a6, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48b3, - 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48b3, 0x7028, 0x9080, 0x000c, - 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, - 0x00c6, 0x080c, 0x4ab4, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, - 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, - 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, - 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, - 0xa804, 0x2048, 0x080c, 0xccd4, 0x1120, 0x2009, 0x0003, 0x0804, - 0x3558, 0x7007, 0x0003, 0x701f, 0x489d, 0x0005, 0x00ce, 0x009e, - 0x00de, 0x2009, 0x0002, 0x0804, 0x3558, 0xa820, 0x9086, 0x8001, - 0x1904, 0x3526, 0x2009, 0x0004, 0x0804, 0x3558, 0x0016, 0x0026, - 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, - 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, - 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, - 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x3558, 0x60dc, 0xd0ac, 0x1130, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x3558, 0x7984, 0x78a8, 0x2040, - 0x080c, 0xaddb, 0x1120, 0x9182, 0x007f, 0x0a04, 0x355b, 0x9186, - 0x00ff, 0x0904, 0x355b, 0x9182, 0x0800, 0x1a04, 0x355b, 0x7a8c, - 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, 0x924e, 0x0904, 0x355b, - 0x080c, 0xaddb, 0x1120, 0x99cc, 0xff00, 0x0904, 0x355b, 0x0126, - 0x2091, 0x8000, 0x080c, 0x49c7, 0x0904, 0x4947, 0x0086, 0x90c6, - 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, 0xb818, 0xbb1c, - 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, 0x9305, 0xbb2c, - 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c, - 0x1128, 0x080c, 0x697b, 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, - 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e, - 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, - 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, - 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, - 0x000a, 0x2020, 0x012e, 0x0804, 0x3528, 0x000e, 0x00ce, 0x2b00, - 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xaebf, - 0x0904, 0x499c, 0x2b00, 0x6012, 0x080c, 0xcfc4, 0x2e58, 0x00ee, - 0x00e6, 0x00c6, 0x080c, 0x4ab4, 0x00ce, 0x2b70, 0x1158, 0x080c, - 0xae71, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, - 0x0804, 0x3558, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, - 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, - 0x080c, 0x31c1, 0x6023, 0x0001, 0x9006, 0x080c, 0x6544, 0xd89c, - 0x0138, 0x2001, 0x0004, 0x080c, 0x6558, 0x2009, 0x0003, 0x0030, - 0x2001, 0x0002, 0x080c, 0x6558, 0x2009, 0x0002, 0x080c, 0xaeec, - 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8cc, - 0xc08d, 0xb8ce, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, 0x0003, - 0x701f, 0x49ab, 0x0005, 0xa830, 0x9086, 0x0100, 0x7024, 0x2058, - 0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, 0x0804, 0x5635, - 0x900e, 0xa868, 0xd0f4, 0x1904, 0x3526, 0x080c, 0x6828, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3526, 0x00e6, - 0x00d6, 0x0096, 0x83ff, 0x0904, 0x4a16, 0x902e, 0x080c, 0xaddb, - 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, - 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, - 0x2100, 0x9406, 0x1904, 0x4a27, 0x2428, 0x94ce, 0x007f, 0x1120, - 0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, - 0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, - 0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, - 0x2400, 0x9106, 0x1180, 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, - 0x691b, 0x1570, 0x2001, 0x4000, 0x0460, 0x080c, 0x697b, 0x1540, - 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, - 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, - 0x0918, 0x080c, 0xaddb, 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, - 0x8e70, 0x1f04, 0x49dd, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, - 0x2001, 0x0001, 0x0030, 0x080c, 0x65a7, 0x1dd0, 0xbb12, 0xba16, - 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x3558, 0x080c, 0x4ab4, 0x1120, 0x2009, - 0x0002, 0x0804, 0x3558, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x7884, 0x9005, 0x0904, 0x355b, 0x9096, 0x00ff, 0x0120, 0x9092, - 0x0004, 0x1a04, 0x355b, 0x2010, 0x2918, 0x080c, 0x3167, 0x1120, - 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, 0x0003, 0x701f, 0x4a69, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x3526, 0x2009, 0x0004, - 0x0804, 0x3558, 0x7984, 0x080c, 0xaddb, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x355b, 0x9186, 0x00ff, 0x0904, 0x355b, 0x9182, 0x0800, - 0x1a04, 0x355b, 0x2001, 0x9000, 0x080c, 0x5690, 0x1904, 0x3558, - 0x0804, 0x3526, 0xa998, 0x080c, 0xaddb, 0x1118, 0x9182, 0x007f, - 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, - 0x9000, 0x080c, 0x5690, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x0fff, 0x0198, 0x9006, - 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, - 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, - 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6608, 0x1130, 0x7e88, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, - 0xa998, 0x080c, 0x6608, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, - 0x2608, 0x080c, 0x6608, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, - 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1031, - 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, - 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10e9, 0x7007, - 0x0002, 0x701f, 0x3526, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2079, 0x0000, 0x2001, 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, - 0x4b31, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x0804, - 0x4b97, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, - 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, - 0x2060, 0x080c, 0x0fff, 0x0904, 0x4b8f, 0xa84b, 0x0000, 0x2900, - 0x7046, 0x2001, 0x0002, 0x9080, 0x2092, 0x2005, 0xa846, 0x0098, - 0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, - 0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, - 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, - 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x2060, - 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x0fff, - 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, - 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, - 0x2001, 0x0002, 0x9080, 0x2092, 0x2005, 0xa846, 0x0058, 0x2262, - 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, - 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4bb9, 0x4bb9, - 0x4bbb, 0x4bb9, 0x4bb9, 0x4bb9, 0x4bbf, 0x4bb9, 0x4bb9, 0x4bb9, - 0x4bc3, 0x4bb9, 0x4bb9, 0x4bb9, 0x4bc7, 0x4bb9, 0x4bb9, 0x4bb9, - 0x4bcb, 0x4bb9, 0x4bb9, 0x4bb9, 0x4bcf, 0x4bb9, 0x4bb9, 0x4bb9, - 0x4bd4, 0x080c, 0x0dd5, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, - 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, - 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, - 0xa3ca, 0xa4ce, 0x0804, 0x4b92, 0xa2d6, 0xa3da, 0xa4de, 0x0804, - 0x4b92, 0x00e6, 0x2071, 0x189e, 0x7048, 0x9005, 0x0904, 0x4c6b, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x4c6a, 0x00f6, 0x2079, 0x0000, - 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, - 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, - 0x0dd5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, - 0x4c6d, 0xa804, 0x9005, 0x090c, 0x0dd5, 0x7042, 0x2938, 0x2040, - 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x2092, 0x2005, 0xa04a, - 0x0804, 0x4c6d, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, - 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, - 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x119b, 0x87ff, 0x0118, 0x2748, 0x080c, 0x1031, 0x7048, 0x8001, - 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, - 0x1031, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, - 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, - 0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, - 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0dd5, - 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, - 0x9080, 0x2092, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, - 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, - 0x0002, 0x4c8c, 0x4c8c, 0x4c8e, 0x4c8c, 0x4c8c, 0x4c8c, 0x4c93, - 0x4c8c, 0x4c8c, 0x4c8c, 0x4c98, 0x4c8c, 0x4c8c, 0x4c8c, 0x4c9d, - 0x4c8c, 0x4c8c, 0x4c8c, 0x4ca2, 0x4c8c, 0x4c8c, 0x4c8c, 0x4ca7, - 0x4c8c, 0x4c8c, 0x4c8c, 0x4cac, 0x080c, 0x0dd5, 0xaa74, 0xab78, - 0xac7c, 0x0804, 0x4c18, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4c18, - 0xaa94, 0xab98, 0xac9c, 0x0804, 0x4c18, 0xaaa4, 0xaba8, 0xacac, - 0x0804, 0x4c18, 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x4c18, 0xaac4, - 0xabc8, 0xaccc, 0x0804, 0x4c18, 0xaad4, 0xabd8, 0xacdc, 0x0804, - 0x4c18, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, - 0x080c, 0x6608, 0x2019, 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, - 0x0000, 0x2011, 0x801b, 0x080c, 0x4b14, 0x00ce, 0x00be, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x56d8, 0xd0c4, 0x0120, - 0x2011, 0x8014, 0x080c, 0x4b14, 0x002e, 0x0005, 0x81ff, 0x1904, - 0x3558, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, - 0x6032, 0x080c, 0x73a5, 0x1158, 0x080c, 0x768d, 0x080c, 0x6023, - 0x9085, 0x0001, 0x080c, 0x73ec, 0x080c, 0x72d7, 0x0010, 0x080c, - 0x5ee2, 0x012e, 0x0804, 0x3526, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x3558, 0x080c, 0x56ec, 0x0120, 0x2009, 0x0007, 0x0804, - 0x3558, 0x080c, 0x6973, 0x0120, 0x2009, 0x0008, 0x0804, 0x3558, - 0x7984, 0x080c, 0x65a7, 0x1904, 0x355b, 0x2b00, 0x7026, 0x080c, - 0x697b, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, - 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x3526, 0x080c, 0x4ab4, 0x0904, 0x3558, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd72, 0x0904, 0x3558, 0x7888, - 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, 0x0003, 0x701f, - 0x4d86, 0x0005, 0x2061, 0x1800, 0x080c, 0x56ec, 0x2009, 0x0007, - 0x1578, 0x080c, 0x6973, 0x0118, 0x2009, 0x0008, 0x0448, 0x080c, - 0x3316, 0x0120, 0xa998, 0x080c, 0x65a7, 0x1530, 0x080c, 0x4ae5, - 0x0518, 0x080c, 0x697b, 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, - 0x900e, 0x080c, 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, 0xcd72, 0x11e0, - 0xa89c, 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x2009, 0x0003, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, - 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, 0xa830, 0x9086, - 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x5635, 0x900e, 0x080c, - 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x3526, 0x080c, 0x56ec, 0x0120, 0x2009, 0x0007, 0x0804, 0x3558, - 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4ab4, 0x1120, - 0x2009, 0x0002, 0x0804, 0x3558, 0x900e, 0x2130, 0x7126, 0x7132, - 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, - 0x080c, 0x6608, 0x1904, 0x4e28, 0x080c, 0x697b, 0x0138, 0x080c, - 0x6983, 0x0120, 0x080c, 0x691b, 0x1904, 0x4e28, 0xd794, 0x1110, - 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, - 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, - 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x48b3, 0x0048, 0x20a9, - 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x48b3, - 0x9186, 0x007e, 0x0170, 0x9186, 0x0080, 0x0158, 0x080c, 0x697b, - 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6828, 0x1108, - 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, 0xb8c8, - 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, - 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, - 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, - 0x080c, 0x48a6, 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, - 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, - 0x8108, 0x080c, 0xaddb, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, - 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, - 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, - 0x0804, 0x4db8, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x3526, - 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, - 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10e9, 0x7007, - 0x0002, 0x701f, 0x4e64, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, - 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, - 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4db8, 0x7124, - 0x810b, 0x0804, 0x3526, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, - 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x355b, - 0x9502, 0x0a04, 0x355b, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, - 0x355b, 0x9502, 0x0a04, 0x355b, 0x9284, 0xff00, 0x8007, 0x90e2, - 0x0020, 0x0a04, 0x355b, 0x9502, 0x0a04, 0x355b, 0x9284, 0x00ff, - 0x90e2, 0x0020, 0x0a04, 0x355b, 0x9502, 0x0a04, 0x355b, 0x9384, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x355b, 0x9502, 0x0a04, - 0x355b, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x355b, 0x9502, - 0x0a04, 0x355b, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x355b, 0x9502, 0x0a04, 0x355b, 0x9484, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x355b, 0x9502, 0x0a04, 0x355b, 0x2061, 0x1988, 0x6102, - 0x6206, 0x630a, 0x640e, 0x0804, 0x3526, 0x080c, 0x4ab4, 0x0904, - 0x3558, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, - 0x9080, 0x0019, 0xaf60, 0x080c, 0x4afd, 0x701f, 0x4ee8, 0x0005, - 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, - 0xd0a4, 0x1de8, 0x00ee, 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, - 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, - 0x2069, 0x1877, 0x20e9, 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, - 0x0904, 0x4f69, 0x6804, 0x2008, 0x918c, 0xfff8, 0x1904, 0x4f69, - 0x680c, 0x9005, 0x0904, 0x4f69, 0x9082, 0xff01, 0x1a04, 0x4f69, - 0x6810, 0x9082, 0x005c, 0x0a04, 0x4f69, 0x6824, 0x2008, 0x9082, - 0x0008, 0x0a04, 0x4f69, 0x9182, 0x0400, 0x1a04, 0x4f69, 0x0056, - 0x2029, 0x0000, 0x080c, 0x8ae4, 0x005e, 0x6944, 0x6820, 0x9102, - 0x06c0, 0x6820, 0x9082, 0x0019, 0x16a0, 0x6828, 0x6944, 0x810c, - 0x9102, 0x0678, 0x6840, 0x9082, 0x000f, 0x1658, 0x080c, 0x1018, - 0x2900, 0x0904, 0x4f83, 0x684e, 0x00e6, 0x2071, 0x1930, 0x00b6, - 0x2059, 0x0000, 0x080c, 0x89a0, 0x00be, 0x00ee, 0x0558, 0x080c, - 0x86fa, 0x080c, 0x8740, 0x11e0, 0x6857, 0x0000, 0x00c6, 0x2061, - 0x0100, 0x6104, 0x918d, 0x2000, 0x6106, 0x6b10, 0x2061, 0x1a61, - 0x630a, 0x00ce, 0x080c, 0x2958, 0x2001, 0x0138, 0x2102, 0x0804, - 0x3526, 0x080c, 0x2958, 0x2001, 0x0138, 0x2102, 0x0804, 0x355b, - 0x00e6, 0x2071, 0x1930, 0x080c, 0x8b75, 0x080c, 0x8b84, 0x080c, - 0x898f, 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, 0x1031, 0x2001, - 0x188a, 0x2003, 0x0000, 0x080c, 0x2958, 0x2001, 0x0138, 0x2102, - 0x0804, 0x3558, 0x2001, 0x1924, 0x200c, 0x918e, 0x0000, 0x0904, - 0x4fe2, 0x080c, 0x898a, 0x0904, 0x4fe2, 0x2001, 0x0101, 0x200c, - 0x918c, 0xdfff, 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, - 0x2071, 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x898f, - 0x2001, 0x0035, 0x080c, 0x15f0, 0x00c6, 0x2061, 0x193c, 0x6004, - 0x6100, 0x9106, 0x1de0, 0x00ce, 0x080c, 0x2958, 0x2001, 0x0138, - 0x2102, 0x00e6, 0x00f6, 0x2071, 0x1923, 0x080c, 0x88cb, 0x0120, - 0x2f00, 0x080c, 0x8955, 0x0cc8, 0x00fe, 0x00ee, 0x0126, 0x2091, - 0x8000, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0138, 0x2148, 0x080c, - 0x1031, 0x2001, 0x188a, 0x2003, 0x0000, 0x2001, 0x183c, 0x2003, - 0x0020, 0x00e6, 0x2071, 0x1930, 0x080c, 0x8b75, 0x080c, 0x8b84, - 0x00ee, 0x012e, 0x0804, 0x3526, 0x0006, 0x080c, 0x56d8, 0xd0cc, - 0x000e, 0x0005, 0x0006, 0x080c, 0x56dc, 0xd0bc, 0x000e, 0x0005, - 0x6174, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x3526, - 0x83ff, 0x1904, 0x355b, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x355b, - 0x2019, 0xffff, 0x6078, 0x9302, 0x9200, 0x0a04, 0x355b, 0x7986, - 0x6276, 0x0804, 0x3526, 0x080c, 0x56ec, 0x1904, 0x3558, 0x7c88, - 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x4ab4, 0x0904, 0x3558, 0x900e, - 0x901e, 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, - 0x0003, 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, - 0x080c, 0x697b, 0x0118, 0x080c, 0x6983, 0x1148, 0x20a9, 0x0001, - 0xb814, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, - 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, - 0x1148, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x8f51, 0x2208, - 0x0804, 0x3526, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, - 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, - 0x7034, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x10e9, - 0x7007, 0x0002, 0x701f, 0x5065, 0x0005, 0x7030, 0x9005, 0x1178, - 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, - 0x2c44, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x5023, 0x7224, - 0x900e, 0x2001, 0x0003, 0x080c, 0x8f51, 0x2208, 0x0804, 0x3526, - 0x00f6, 0x00e6, 0x080c, 0x56ec, 0x2009, 0x0007, 0x1904, 0x50f8, - 0x2071, 0x189e, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x50f8, - 0xac9c, 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1018, 0x2009, - 0x0002, 0x0904, 0x50f8, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, - 0x7362, 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, - 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x697b, 0x0118, - 0x080c, 0x6983, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, - 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, - 0x9386, 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, - 0x2001, 0x0003, 0x080c, 0x8f51, 0x2208, 0x009e, 0xa897, 0x4000, - 0xa99a, 0x715c, 0x81ff, 0x090c, 0x0dd5, 0x2148, 0x080c, 0x1031, - 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, - 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, 0x2c44, 0xa37a, - 0x7058, 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, - 0xa09f, 0x5104, 0x000e, 0xa0a2, 0x080c, 0x10e9, 0x9006, 0x0048, - 0x009e, 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, - 0x0dd5, 0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, 0x0100, 0x0138, - 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, - 0x9005, 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, - 0xa48c, 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, - 0x8f51, 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0dd5, 0x2148, 0x080c, - 0x1031, 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6c86, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, - 0x00fe, 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, - 0x697b, 0x0118, 0x080c, 0x6983, 0x1148, 0xb814, 0x20a9, 0x0001, + 0x10e9, 0x7007, 0x0002, 0x701f, 0x3531, 0x0005, 0x00f6, 0x0126, + 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x18b0, 0x2004, 0x9005, + 0x1190, 0x0e04, 0x4b3b, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, + 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x119b, 0x0804, 0x4ba1, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, + 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, + 0x0288, 0x7038, 0x2060, 0x080c, 0x0fff, 0x0904, 0x4b99, 0xa84b, + 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, 0x9080, 0x209d, 0x2005, + 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, + 0x18fa, 0x0210, 0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, + 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, + 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, + 0x0dd5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, + 0x080c, 0x0fff, 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, + 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, + 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, 0x209d, 0x2005, 0xa846, + 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, + 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, + 0x4bc3, 0x4bc3, 0x4bc5, 0x4bc3, 0x4bc3, 0x4bc3, 0x4bc9, 0x4bc3, + 0x4bc3, 0x4bc3, 0x4bcd, 0x4bc3, 0x4bc3, 0x4bc3, 0x4bd1, 0x4bc3, + 0x4bc3, 0x4bc3, 0x4bd5, 0x4bc3, 0x4bc3, 0x4bc3, 0x4bd9, 0x4bc3, + 0x4bc3, 0x4bc3, 0x4bde, 0x080c, 0x0dd5, 0xa276, 0xa37a, 0xa47e, + 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, + 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, + 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, 0x4b9c, 0xa2d6, 0xa3da, + 0xa4de, 0x0804, 0x4b9c, 0x00e6, 0x2071, 0x189e, 0x7048, 0x9005, + 0x0904, 0x4c75, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4c74, 0x00f6, + 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, + 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, + 0x0036, 0x1a0c, 0x0dd5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, + 0xa94a, 0x1904, 0x4c77, 0xa804, 0x9005, 0x090c, 0x0dd5, 0x7042, + 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x209d, + 0x2005, 0xa04a, 0x0804, 0x4c77, 0x703c, 0x2060, 0x2c14, 0x6304, + 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, + 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x119b, 0x87ff, 0x0118, 0x2748, 0x080c, 0x1031, + 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, + 0x0128, 0x080c, 0x1031, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, + 0x703f, 0x18ba, 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, + 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, + 0x18ba, 0x703e, 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, + 0x090c, 0x0dd5, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, + 0x2001, 0x0002, 0x9080, 0x209d, 0x2005, 0xa84a, 0x0000, 0x007e, + 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, + 0x9082, 0x001b, 0x0002, 0x4c96, 0x4c96, 0x4c98, 0x4c96, 0x4c96, + 0x4c96, 0x4c9d, 0x4c96, 0x4c96, 0x4c96, 0x4ca2, 0x4c96, 0x4c96, + 0x4c96, 0x4ca7, 0x4c96, 0x4c96, 0x4c96, 0x4cac, 0x4c96, 0x4c96, + 0x4c96, 0x4cb1, 0x4c96, 0x4c96, 0x4c96, 0x4cb6, 0x080c, 0x0dd5, + 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4c22, 0xaa84, 0xab88, 0xac8c, + 0x0804, 0x4c22, 0xaa94, 0xab98, 0xac9c, 0x0804, 0x4c22, 0xaaa4, + 0xaba8, 0xacac, 0x0804, 0x4c22, 0xaab4, 0xabb8, 0xacbc, 0x0804, + 0x4c22, 0xaac4, 0xabc8, 0xaccc, 0x0804, 0x4c22, 0xaad4, 0xabd8, + 0xacdc, 0x0804, 0x4c22, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, + 0x2009, 0x007e, 0x080c, 0x6616, 0x2019, 0x0001, 0xb85c, 0xd0ac, + 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, 0x080c, 0x4b1e, 0x00ce, + 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x56e2, + 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x4b1e, 0x002e, 0x0005, + 0x81ff, 0x1904, 0x3563, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, + 0xc085, 0xc0ac, 0x6032, 0x080c, 0x73b3, 0x1158, 0x080c, 0x7699, + 0x080c, 0x602d, 0x9085, 0x0001, 0x080c, 0x73fa, 0x080c, 0x72e5, + 0x0010, 0x080c, 0x5eec, 0x012e, 0x0804, 0x3531, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3563, 0x080c, 0x56f6, 0x0120, 0x2009, + 0x0007, 0x0804, 0x3563, 0x080c, 0x6981, 0x0120, 0x2009, 0x0008, + 0x0804, 0x3563, 0x7984, 0x080c, 0x65b5, 0x1904, 0x3566, 0x2b00, + 0x7026, 0x080c, 0x6989, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, + 0x900e, 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, + 0xc18d, 0x0804, 0x3531, 0x080c, 0x4abe, 0x0904, 0x3563, 0x9006, + 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd82, 0x0904, + 0x3563, 0x7888, 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, + 0x0003, 0x701f, 0x4d90, 0x0005, 0x2061, 0x1800, 0x080c, 0x56f6, + 0x2009, 0x0007, 0x1578, 0x080c, 0x6981, 0x0118, 0x2009, 0x0008, + 0x0448, 0x080c, 0x3321, 0x0120, 0xa998, 0x080c, 0x65b5, 0x1530, + 0x080c, 0x4aef, 0x0518, 0x080c, 0x6989, 0xa89c, 0x1168, 0x9084, + 0x0005, 0x1150, 0x900e, 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, + 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, + 0xcd82, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, + 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, + 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, + 0xa830, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x563f, + 0x900e, 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, + 0xc18d, 0x0804, 0x3531, 0x080c, 0x56f6, 0x0120, 0x2009, 0x0007, + 0x0804, 0x3563, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, + 0x4abe, 0x1120, 0x2009, 0x0002, 0x0804, 0x3563, 0x900e, 0x2130, + 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, + 0x702a, 0x20a0, 0x080c, 0x6616, 0x1904, 0x4e32, 0x080c, 0x6989, + 0x0138, 0x080c, 0x6991, 0x0120, 0x080c, 0x6929, 0x1904, 0x4e32, + 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, + 0x0006, 0x2098, 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, 0x4003, + 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x48bd, + 0x0048, 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, + 0x080c, 0x48bd, 0x9186, 0x007e, 0x0170, 0x9186, 0x0080, 0x0158, + 0x080c, 0x6989, 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, + 0x6836, 0x1108, 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, + 0x20e0, 0xb8c8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, + 0x4003, 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, + 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, + 0x3d00, 0x20e0, 0x080c, 0x48b0, 0x9c80, 0x0026, 0x2098, 0xb8c4, + 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, + 0x96b0, 0x0005, 0x8108, 0x080c, 0xadc9, 0x0118, 0x9186, 0x0800, + 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, + 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, + 0x0028, 0x0150, 0x0804, 0x4dc2, 0x86ff, 0x1120, 0x7124, 0x810b, + 0x0804, 0x3531, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, + 0x772e, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, + 0xa072, 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, + 0x10e9, 0x7007, 0x0002, 0x701f, 0x4e6e, 0x0005, 0x7030, 0x9005, + 0x1180, 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, + 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, + 0x4dc2, 0x7124, 0x810b, 0x0804, 0x3531, 0x2029, 0x007e, 0x7984, + 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x3566, 0x9502, 0x0a04, 0x3566, 0x9184, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x3566, 0x9502, 0x0a04, 0x3566, 0x9284, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x3566, 0x9502, 0x0a04, 0x3566, + 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3566, 0x9502, 0x0a04, + 0x3566, 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x3566, + 0x9502, 0x0a04, 0x3566, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x3566, 0x9502, 0x0a04, 0x3566, 0x9484, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x3566, 0x9502, 0x0a04, 0x3566, 0x9484, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x3566, 0x9502, 0x0a04, 0x3566, 0x2061, + 0x1988, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x3531, 0x080c, + 0x4abe, 0x0904, 0x3563, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, + 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4b07, 0x701f, + 0x4ef2, 0x0005, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, + 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x20a9, 0x0016, 0x896e, + 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098, 0x9d84, + 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, 0x0001, 0x2da0, 0x4003, + 0x6800, 0x9005, 0x0904, 0x4f73, 0x6804, 0x2008, 0x918c, 0xfff8, + 0x1904, 0x4f73, 0x680c, 0x9005, 0x0904, 0x4f73, 0x9082, 0xff01, + 0x1a04, 0x4f73, 0x6810, 0x9082, 0x005c, 0x0a04, 0x4f73, 0x6824, + 0x2008, 0x9082, 0x0008, 0x0a04, 0x4f73, 0x9182, 0x0400, 0x1a04, + 0x4f73, 0x0056, 0x2029, 0x0000, 0x080c, 0x8b01, 0x005e, 0x6944, + 0x6820, 0x9102, 0x06c0, 0x6820, 0x9082, 0x0019, 0x16a0, 0x6828, + 0x6944, 0x810c, 0x9102, 0x0678, 0x6840, 0x9082, 0x000f, 0x1658, + 0x080c, 0x1018, 0x2900, 0x0904, 0x4f8d, 0x684e, 0x00e6, 0x2071, + 0x1930, 0x00b6, 0x2059, 0x0000, 0x080c, 0x89bd, 0x00be, 0x00ee, + 0x0558, 0x080c, 0x8717, 0x080c, 0x875d, 0x11e0, 0x6857, 0x0000, + 0x00c6, 0x2061, 0x0100, 0x6104, 0x918d, 0x2000, 0x6106, 0x6b10, + 0x2061, 0x1a61, 0x630a, 0x00ce, 0x080c, 0x2963, 0x2001, 0x0138, + 0x2102, 0x0804, 0x3531, 0x080c, 0x2963, 0x2001, 0x0138, 0x2102, + 0x0804, 0x3566, 0x00e6, 0x2071, 0x1930, 0x080c, 0x8b92, 0x080c, + 0x8ba1, 0x080c, 0x89ac, 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, + 0x1031, 0x2001, 0x188a, 0x2003, 0x0000, 0x080c, 0x2963, 0x2001, + 0x0138, 0x2102, 0x0804, 0x3563, 0x2001, 0x1924, 0x200c, 0x918e, + 0x0000, 0x0904, 0x4fec, 0x080c, 0x89a7, 0x0904, 0x4fec, 0x2001, + 0x0101, 0x200c, 0x918c, 0xdfff, 0x2102, 0x2001, 0x0138, 0x2003, + 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, + 0x080c, 0x89ac, 0x2001, 0x0035, 0x080c, 0x15f0, 0x00c6, 0x2061, + 0x193c, 0x6004, 0x6100, 0x9106, 0x1de0, 0x00ce, 0x080c, 0x2963, + 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, 0x2071, 0x1923, 0x080c, + 0x88e8, 0x0120, 0x2f00, 0x080c, 0x8972, 0x0cc8, 0x00fe, 0x00ee, + 0x0126, 0x2091, 0x8000, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0138, + 0x2148, 0x080c, 0x1031, 0x2001, 0x188a, 0x2003, 0x0000, 0x2001, + 0x183c, 0x2003, 0x0020, 0x00e6, 0x2071, 0x1930, 0x080c, 0x8b92, + 0x080c, 0x8ba1, 0x00ee, 0x012e, 0x0804, 0x3531, 0x0006, 0x080c, + 0x56e2, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, 0x56e6, 0xd0bc, + 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, + 0x0804, 0x3531, 0x83ff, 0x1904, 0x3566, 0x2001, 0xfff0, 0x9200, + 0x1a04, 0x3566, 0x2019, 0xffff, 0x6078, 0x9302, 0x9200, 0x0a04, + 0x3566, 0x7986, 0x6276, 0x0804, 0x3531, 0x080c, 0x56f6, 0x1904, + 0x3563, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x4abe, 0x0904, + 0x3563, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, + 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, + 0x8bff, 0x0178, 0x080c, 0x6989, 0x0118, 0x080c, 0x6991, 0x1148, + 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, + 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, + 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, + 0x8f70, 0x2208, 0x0804, 0x3531, 0x7033, 0x0001, 0x7122, 0x7024, + 0x9300, 0x7026, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, + 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, + 0x080c, 0x10e9, 0x7007, 0x0002, 0x701f, 0x506f, 0x0005, 0x7030, + 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, + 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, + 0x502d, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x8f70, 0x2208, + 0x0804, 0x3531, 0x00f6, 0x00e6, 0x080c, 0x56f6, 0x2009, 0x0007, + 0x1904, 0x5102, 0x2071, 0x189e, 0x745c, 0x84ff, 0x2009, 0x000e, + 0x1904, 0x5102, 0xac9c, 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, + 0x1018, 0x2009, 0x0002, 0x0904, 0x5102, 0x2900, 0x705e, 0x900e, + 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, + 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, + 0x6989, 0x0118, 0x080c, 0x6991, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, - 0x0800, 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, - 0x7154, 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, - 0x0dd5, 0x2148, 0x080c, 0x1031, 0x9006, 0x705e, 0x918d, 0x0001, - 0x2008, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c86, - 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, - 0x7152, 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, - 0xa79a, 0x080c, 0x10e9, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, - 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, - 0x0118, 0x009e, 0x0804, 0x355b, 0xa884, 0xa988, 0x080c, 0x2840, - 0x1518, 0x080c, 0x65a7, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, - 0x080c, 0x4ab4, 0x01c8, 0x080c, 0x4ab4, 0x01b0, 0x009e, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, - 0x080c, 0xccf4, 0x1120, 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, - 0x0003, 0x701f, 0x51d1, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, - 0x3558, 0x7124, 0x080c, 0x32bd, 0xa820, 0x9086, 0x8001, 0x1120, - 0x2009, 0x0004, 0x0804, 0x3558, 0x2900, 0x7022, 0xa804, 0x0096, - 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x009e, 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, - 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f7c, 0xaa6c, 0xab70, 0xac74, - 0xad78, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, - 0x97c6, 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, - 0x0600, 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x4b00, 0x97c6, - 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, - 0x18b8, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x10e9, 0x7007, 0x0002, 0x701f, 0x522d, - 0x0005, 0x000e, 0x007e, 0x0804, 0x355b, 0x7020, 0x2048, 0xa804, - 0x2048, 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, - 0x20a9, 0x002a, 0x080c, 0x0f7c, 0x2100, 0x2238, 0x2061, 0x18b8, - 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, - 0x4b00, 0x81ff, 0x1904, 0x3558, 0x798c, 0x2001, 0x197d, 0x918c, - 0x8000, 0x2102, 0x080c, 0x4acb, 0x0904, 0x355b, 0x080c, 0x697b, - 0x0120, 0x080c, 0x6983, 0x1904, 0x355b, 0x080c, 0x66cf, 0x0904, - 0x3558, 0x0126, 0x2091, 0x8000, 0x080c, 0x6795, 0x012e, 0x0904, - 0x3558, 0x2001, 0x197d, 0x2004, 0xd0fc, 0x1904, 0x3526, 0x0804, - 0x4529, 0xa9a0, 0x2001, 0x197d, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x4ad8, 0x01a0, 0x080c, 0x697b, 0x0118, 0x080c, 0x6983, - 0x1170, 0x080c, 0x66cf, 0x2009, 0x0002, 0x0128, 0x080c, 0x6795, - 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, - 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x197d, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56e0, - 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x449e, 0x080c, - 0x4ae7, 0x0904, 0x355b, 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3558, 0x080c, 0x697b, 0x0130, 0x908e, 0x0004, 0x0118, - 0x908e, 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, - 0xb802, 0x0028, 0x080c, 0x56d8, 0xd0b4, 0x0904, 0x44d8, 0x7884, - 0x908e, 0x007e, 0x0904, 0x44d8, 0x908e, 0x007f, 0x0904, 0x44d8, - 0x908e, 0x0080, 0x0904, 0x44d8, 0xb800, 0xd08c, 0x1904, 0x44d8, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd13, 0x1120, - 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, 0x0003, 0x701f, 0x52f9, - 0x0005, 0x080c, 0x4ae7, 0x0904, 0x355b, 0x0804, 0x44d8, 0x080c, - 0x3316, 0x0108, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x3558, 0x080c, 0x56ec, 0x0120, 0x2009, - 0x0007, 0x0804, 0x3558, 0x080c, 0x6973, 0x0120, 0x2009, 0x0008, - 0x0804, 0x3558, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x44d8, - 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd72, - 0x1120, 0x2009, 0x0003, 0x0804, 0x3558, 0x7007, 0x0003, 0x701f, - 0x5332, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, - 0x0804, 0x5635, 0x080c, 0x4ae7, 0x0904, 0x355b, 0x0804, 0x52cb, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x3558, 0x080c, 0x56ec, 0x2009, - 0x0007, 0x1904, 0x3558, 0x080c, 0x6973, 0x0120, 0x2009, 0x0008, - 0x0804, 0x3558, 0x080c, 0x4ae7, 0x0904, 0x355b, 0x080c, 0x697b, - 0x2009, 0x0009, 0x1904, 0x3558, 0x080c, 0x4ab4, 0x2009, 0x0002, - 0x0904, 0x3558, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, - 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, - 0x355b, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xcfc5, 0x2009, - 0x0003, 0x0904, 0x3558, 0x7007, 0x0003, 0x701f, 0x5388, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x3558, 0x0804, - 0x3526, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, - 0x56ec, 0x1188, 0x2009, 0x0014, 0x0804, 0x3558, 0xd2dc, 0x1568, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x3558, 0x080c, 0x56ec, 0x2009, - 0x0007, 0x1904, 0x3558, 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, - 0x56b3, 0x0804, 0x3526, 0xd2fc, 0x0158, 0x080c, 0x4ae7, 0x0904, - 0x355b, 0x7984, 0x9284, 0x9000, 0x080c, 0x5690, 0x0804, 0x3526, - 0x080c, 0x4ae7, 0x0904, 0x355b, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x2009, 0x0009, 0x1904, 0x5471, 0x080c, 0x4ab4, 0x2009, - 0x0002, 0x0904, 0x5471, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, - 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4afd, 0x701f, - 0x53e2, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, - 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x355b, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4ae7, 0x1110, 0x0804, - 0x355b, 0x2009, 0x0043, 0x080c, 0xd02d, 0x2009, 0x0003, 0x0904, - 0x5471, 0x7007, 0x0003, 0x701f, 0x5406, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x5471, 0x7984, 0x7aa8, 0x9284, - 0x1000, 0x080c, 0x5690, 0x0804, 0x3526, 0x00c6, 0xaab0, 0x9284, - 0xc000, 0x0140, 0xd2ec, 0x0168, 0x080c, 0x56ec, 0x1150, 0x2009, - 0x0014, 0x04f0, 0x2061, 0x1800, 0x080c, 0x56ec, 0x2009, 0x0007, - 0x15b8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, 0x56b3, 0x0050, - 0xd2fc, 0x0178, 0x080c, 0x4ae5, 0x0588, 0xa998, 0x9284, 0x9000, - 0x080c, 0x5690, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x0438, 0x080c, 0x4ae5, 0x0510, 0x080c, 0x697b, 0x2009, 0x0009, - 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, - 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, 0x4ae5, 0x1108, 0x0070, - 0x2009, 0x004b, 0x080c, 0xd02d, 0x2009, 0x0003, 0x0108, 0x0078, - 0x0429, 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, - 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x3558, 0x0016, 0x7984, 0x9284, - 0x1000, 0xc0fd, 0x080c, 0x5690, 0x001e, 0x1904, 0x3558, 0x0804, - 0x3526, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0xaab0, 0xd2dc, - 0x0150, 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5690, - 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x3558, 0x080c, 0x56ec, 0x0120, 0x2009, 0x0007, 0x0804, - 0x3558, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6608, 0x1904, - 0x355b, 0x9186, 0x007f, 0x0138, 0x080c, 0x697b, 0x0120, 0x2009, - 0x0009, 0x0804, 0x3558, 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3558, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, - 0x0100, 0x8007, 0xa80a, 0x080c, 0xcd2d, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3558, 0x7007, 0x0003, 0x701f, 0x54cf, 0x0005, 0xa808, - 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3558, - 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, - 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b00, 0x080c, 0x4ab4, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3558, 0x7984, 0x9194, 0xff00, - 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b2, 0x0040, - 0x92c6, 0x0001, 0x1118, 0x7023, 0x19cc, 0x0010, 0x0804, 0x355b, - 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x4afd, 0x701f, 0x551f, 0x0005, 0x2001, - 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, - 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, - 0x0804, 0x3526, 0x080c, 0x4ab4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x3558, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x1118, 0x2099, 0x19b2, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, - 0x19cc, 0x0010, 0x0804, 0x355b, 0xa85c, 0x9080, 0x0019, 0x20a0, - 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, - 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x0804, 0x4b00, 0x7884, 0x908a, 0x1000, 0x1a04, 0x355b, - 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, - 0x2061, 0x19f9, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3526, 0x00c6, - 0x080c, 0x73a5, 0x1160, 0x080c, 0x768d, 0x080c, 0x6023, 0x9085, - 0x0001, 0x080c, 0x73ec, 0x080c, 0x72d7, 0x080c, 0x0dd5, 0x2061, - 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5ee2, 0x00ce, 0x0005, - 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x3558, - 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x199b, 0x2c0c, 0x2062, - 0x080c, 0x2c22, 0x01a0, 0x080c, 0x2c2a, 0x0188, 0x080c, 0x2c32, - 0x0170, 0x2162, 0x0804, 0x355b, 0x2061, 0x0100, 0x6038, 0x9086, - 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, - 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, - 0x0026, 0x2011, 0x0003, 0x080c, 0xa654, 0x2011, 0x0002, 0x080c, - 0xa65e, 0x002e, 0x080c, 0xa541, 0x0036, 0x901e, 0x080c, 0xa5b7, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xea0a, 0x080c, 0xea25, 0x9085, - 0x0001, 0x080c, 0x73ec, 0x9006, 0x080c, 0x2cf1, 0x2001, 0x1800, - 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, 0x3526, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x3558, 0x080c, 0x56ec, 0x0120, - 0x2009, 0x0007, 0x0804, 0x3558, 0x7984, 0x7ea8, 0x96b4, 0x00ff, - 0x080c, 0x6608, 0x1904, 0x355b, 0x9186, 0x007f, 0x0138, 0x080c, - 0x697b, 0x0120, 0x2009, 0x0009, 0x0804, 0x3558, 0x080c, 0x4ab4, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3558, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xcd30, 0x1120, 0x2009, 0x0003, 0x0804, - 0x3558, 0x7007, 0x0003, 0x701f, 0x561e, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3558, 0xa8e0, 0xa866, - 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4b00, 0xa898, 0x9086, 0x000d, - 0x1904, 0x3558, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x5642, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, - 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0xa998, - 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x4af0, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x7007, - 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x2061, 0x19f9, 0x7984, 0x6152, 0x614e, - 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, - 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x1a07, 0x2044, 0x2001, - 0x1a0e, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, - 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, 0x3526, - 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, - 0x0006, 0x080c, 0xcb97, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, - 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x603d, 0x080c, 0xaddb, - 0x0110, 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, - 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, - 0x900e, 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, - 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, - 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, - 0x002e, 0x001e, 0x8108, 0x1f04, 0x56bb, 0x015e, 0x012e, 0x0005, - 0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, - 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, - 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, - 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x9182, 0x0081, 0x1a04, - 0x355b, 0x810c, 0x0016, 0x080c, 0x4ab4, 0x080c, 0x0f07, 0x2100, - 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x4afd, - 0x701f, 0x5713, 0x0005, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, - 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, 0xa074, - 0x2071, 0x189e, 0x080c, 0x4b00, 0x701f, 0x5727, 0x0005, 0x2061, - 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f0f, - 0x002e, 0x001e, 0x080c, 0x0fbc, 0x9006, 0xa802, 0xa806, 0x0804, - 0x3526, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, - 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x58e2, - 0x0068, 0xd08c, 0x0118, 0x080c, 0x57eb, 0x0040, 0xd094, 0x0118, - 0x080c, 0x57bb, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, - 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, - 0x0c68, 0x0006, 0x7098, 0x9005, 0x000e, 0x0120, 0x709b, 0x0000, - 0x7093, 0x0000, 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, - 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, - 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, - 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, - 0x00f7, 0x080c, 0x5f9f, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, - 0x0140, 0x6042, 0x6043, 0x0000, 0x7087, 0x0000, 0x70a3, 0x0001, - 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009, 0x1c80, 0x200b, 0x0000, - 0x7097, 0x0000, 0x708b, 0x000f, 0x2009, 0x000f, 0x2011, 0x5e85, - 0x080c, 0x8574, 0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, 0x0110, - 0x705f, 0xffff, 0x7088, 0x9005, 0x1528, 0x2011, 0x5e85, 0x080c, - 0x84dc, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, - 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x57d1, 0x6242, 0x709b, - 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, - 0x0048, 0x6242, 0x709b, 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, - 0x6028, 0x0000, 0x0005, 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0dd5, - 0x000b, 0x0005, 0x57f5, 0x5846, 0x58e1, 0x00f6, 0x0016, 0x6900, - 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, - 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, - 0x1f04, 0x5804, 0x080c, 0x0dd5, 0x68a0, 0x68a2, 0x689c, 0x689e, - 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, - 0x0020, 0x080c, 0x6004, 0x2079, 0x1c00, 0x7833, 0x1101, 0x7837, - 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, - 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0xab2c, 0x20e1, 0x0001, - 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, - 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x5eb6, 0x00fe, - 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7090, - 0x7093, 0x0000, 0x9025, 0x0904, 0x58be, 0x6020, 0xd0b4, 0x1904, - 0x58bc, 0x71a0, 0x81ff, 0x0904, 0x58aa, 0x9486, 0x000c, 0x1904, - 0x58b7, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x5ffd, 0x2011, - 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, - 0x8318, 0x1f04, 0x5863, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, - 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708f, - 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x5e8c, 0x080c, - 0x8574, 0x080c, 0x6004, 0x04c0, 0x080c, 0x5ffd, 0x2079, 0x0260, - 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, - 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x5ffd, - 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, - 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x589e, 0x0078, - 0x70a3, 0x0000, 0x080c, 0x5ffd, 0x20e1, 0x0000, 0x2099, 0x0260, - 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9, 0x0014, 0x4003, 0x6043, - 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, - 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0xab2c, 0x20e1, - 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19f0, 0x2013, 0x0000, - 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa26b, - 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d, 0x1a0c, 0x0dd5, 0x000b, - 0x0005, 0x5913, 0x5926, 0x594f, 0x596f, 0x5995, 0x59c4, 0x59ea, - 0x5a22, 0x5a48, 0x5a76, 0x5ab1, 0x5ae9, 0x5b07, 0x5b32, 0x5b54, - 0x5b6f, 0x5b79, 0x5bad, 0x5bd3, 0x5c02, 0x5c28, 0x5c60, 0x5ca4, - 0x5ce1, 0x5d02, 0x5d5b, 0x5d7d, 0x5dab, 0x5dab, 0x00c6, 0x2061, - 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, - 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, - 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, - 0x07d0, 0x2011, 0x5e8c, 0x080c, 0x8574, 0x0005, 0x00f6, 0x7090, - 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, - 0x5ffd, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, - 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, - 0x70c7, 0x0001, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x709b, 0x0010, - 0x080c, 0x5b79, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x0003, 0x6043, 0x0004, 0x2011, 0x5e8c, 0x080c, 0x84dc, - 0x080c, 0x5f81, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, - 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, - 0x5964, 0x60c3, 0x0014, 0x080c, 0x5eb6, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x0500, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x5ffd, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, - 0x0010, 0x080c, 0x5fd9, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, - 0x080c, 0x5f81, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, - 0x080c, 0x5ffd, 0x080c, 0x5fe0, 0x1170, 0x7084, 0x9005, 0x1158, - 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5e39, - 0x0168, 0x080c, 0x5fb6, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, + 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x8f70, 0x2208, 0x009e, + 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c, 0x0dd5, 0x2148, + 0x080c, 0x1031, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, + 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, + 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, + 0xa696, 0xa79a, 0xa09f, 0x510e, 0x000e, 0xa0a2, 0x080c, 0x10e9, + 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, + 0x904d, 0x090c, 0x0dd5, 0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, + 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, + 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, + 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, + 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, + 0x0003, 0x080c, 0x8f70, 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0dd5, + 0x2148, 0x080c, 0x1031, 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6c94, 0x012e, 0xa09f, 0x0000, 0xa0a3, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, + 0x0178, 0x080c, 0x6989, 0x0118, 0x080c, 0x6991, 0x1148, 0xb814, + 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, + 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, + 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, + 0x81ff, 0x090c, 0x0dd5, 0x2148, 0x080c, 0x1031, 0x9006, 0x705e, + 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6c94, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, + 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, + 0xa592, 0xa696, 0xa79a, 0x080c, 0x10e9, 0x9006, 0x00ee, 0x0005, + 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, + 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x3566, 0xa884, 0xa988, + 0x080c, 0x284b, 0x1518, 0x080c, 0x65b5, 0x1500, 0x7126, 0xbe12, + 0xbd16, 0xae7c, 0x080c, 0x4abe, 0x01c8, 0x080c, 0x4abe, 0x01b0, + 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, + 0xa804, 0x2048, 0x080c, 0xcd04, 0x1120, 0x2009, 0x0003, 0x0804, + 0x3563, 0x7007, 0x0003, 0x701f, 0x51db, 0x0005, 0x009e, 0x2009, + 0x0002, 0x0804, 0x3563, 0x7124, 0x080c, 0x32c8, 0xa820, 0x9086, + 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x3563, 0x2900, 0x7022, + 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, + 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, + 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f7c, 0xaa6c, + 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, + 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, + 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, + 0x4b0a, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, + 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, + 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10e9, 0x7007, 0x0002, + 0x701f, 0x5237, 0x0005, 0x000e, 0x007e, 0x0804, 0x3566, 0x7020, + 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, + 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f7c, 0x2100, 0x2238, + 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, + 0x002a, 0x0804, 0x4b0a, 0x81ff, 0x1904, 0x3563, 0x798c, 0x2001, + 0x197d, 0x918c, 0x8000, 0x2102, 0x080c, 0x4ad5, 0x0904, 0x3566, + 0x080c, 0x6989, 0x0120, 0x080c, 0x6991, 0x1904, 0x3566, 0x080c, + 0x66dd, 0x0904, 0x3563, 0x0126, 0x2091, 0x8000, 0x080c, 0x67a3, + 0x012e, 0x0904, 0x3563, 0x2001, 0x197d, 0x2004, 0xd0fc, 0x1904, + 0x3531, 0x0804, 0x4534, 0xa9a0, 0x2001, 0x197d, 0x918c, 0x8000, + 0xc18d, 0x2102, 0x080c, 0x4ae2, 0x01a0, 0x080c, 0x6989, 0x0118, + 0x080c, 0x6991, 0x1170, 0x080c, 0x66dd, 0x2009, 0x0002, 0x0128, + 0x080c, 0x67a3, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, + 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x0005, 0xa897, 0x4000, 0x2001, 0x197d, 0x2004, 0xd0fc, 0x1128, + 0x080c, 0x56ea, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, + 0x44a9, 0x080c, 0x4af1, 0x0904, 0x3566, 0x080c, 0x4abe, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3563, 0x080c, 0x6989, 0x0130, 0x908e, + 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, + 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, 0x56e2, 0xd0b4, 0x0904, + 0x44e3, 0x7884, 0x908e, 0x007e, 0x0904, 0x44e3, 0x908e, 0x007f, + 0x0904, 0x44e3, 0x908e, 0x0080, 0x0904, 0x44e3, 0xb800, 0xd08c, + 0x1904, 0x44e3, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, + 0xcd23, 0x1120, 0x2009, 0x0003, 0x0804, 0x3563, 0x7007, 0x0003, + 0x701f, 0x5303, 0x0005, 0x080c, 0x4af1, 0x0904, 0x3566, 0x0804, + 0x44e3, 0x080c, 0x3321, 0x0108, 0x0005, 0x2009, 0x1834, 0x210c, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3563, 0x080c, 0x56f6, + 0x0120, 0x2009, 0x0007, 0x0804, 0x3563, 0x080c, 0x6981, 0x0120, + 0x2009, 0x0008, 0x0804, 0x3563, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, + 0x1904, 0x44e3, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, + 0x080c, 0xcd82, 0x1120, 0x2009, 0x0003, 0x0804, 0x3563, 0x7007, + 0x0003, 0x701f, 0x533c, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, + 0x2009, 0x0004, 0x0804, 0x563f, 0x080c, 0x4af1, 0x0904, 0x3566, + 0x0804, 0x52d5, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3563, 0x080c, + 0x56f6, 0x2009, 0x0007, 0x1904, 0x3563, 0x080c, 0x6981, 0x0120, + 0x2009, 0x0008, 0x0804, 0x3563, 0x080c, 0x4af1, 0x0904, 0x3566, + 0x080c, 0x6989, 0x2009, 0x0009, 0x1904, 0x3563, 0x080c, 0x4abe, + 0x2009, 0x0002, 0x0904, 0x3563, 0x9006, 0xa866, 0xa832, 0xa868, + 0xc0fd, 0xa86a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, + 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, + 0x0100, 0x1904, 0x3566, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, + 0xcfd5, 0x2009, 0x0003, 0x0904, 0x3563, 0x7007, 0x0003, 0x701f, + 0x5392, 0x0005, 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, + 0x3563, 0x0804, 0x3531, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, + 0x01a0, 0x080c, 0x56f6, 0x1188, 0x2009, 0x0014, 0x0804, 0x3563, + 0xd2dc, 0x1568, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3563, 0x080c, + 0x56f6, 0x2009, 0x0007, 0x1904, 0x3563, 0xd2f4, 0x0130, 0x9284, + 0x5000, 0x080c, 0x56bd, 0x0804, 0x3531, 0xd2fc, 0x0158, 0x080c, + 0x4af1, 0x0904, 0x3566, 0x7984, 0x9284, 0x9000, 0x080c, 0x569a, + 0x0804, 0x3531, 0x080c, 0x4af1, 0x0904, 0x3566, 0xb804, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x547b, 0x080c, + 0x4abe, 0x2009, 0x0002, 0x0904, 0x547b, 0xa85c, 0x9080, 0x001b, + 0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, + 0x4b07, 0x701f, 0x53ec, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, + 0xa870, 0x9005, 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, + 0x3566, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4af1, + 0x1110, 0x0804, 0x3566, 0x2009, 0x0043, 0x080c, 0xd03d, 0x2009, + 0x0003, 0x0904, 0x547b, 0x7007, 0x0003, 0x701f, 0x5410, 0x0005, + 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x547b, 0x7984, + 0x7aa8, 0x9284, 0x1000, 0x080c, 0x569a, 0x0804, 0x3531, 0x00c6, + 0xaab0, 0x9284, 0xc000, 0x0140, 0xd2ec, 0x0168, 0x080c, 0x56f6, + 0x1150, 0x2009, 0x0014, 0x04f0, 0x2061, 0x1800, 0x080c, 0x56f6, + 0x2009, 0x0007, 0x15b8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, + 0x56bd, 0x0050, 0xd2fc, 0x0178, 0x080c, 0x4aef, 0x0588, 0xa998, + 0x9284, 0x9000, 0x080c, 0x569a, 0xa87b, 0x0000, 0xa883, 0x0000, + 0xa897, 0x4000, 0x0438, 0x080c, 0x4aef, 0x0510, 0x080c, 0x6989, + 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, + 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, 0x4aef, + 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd03d, 0x2009, 0x0003, + 0x0108, 0x0078, 0x0429, 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, + 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, + 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x3563, 0x0016, + 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x569a, 0x001e, 0x1904, + 0x3563, 0x0804, 0x3531, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, + 0xaab0, 0xd2dc, 0x0150, 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x569a, 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3563, 0x080c, 0x56f6, 0x0120, 0x2009, + 0x0007, 0x0804, 0x3563, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, + 0x6616, 0x1904, 0x3566, 0x9186, 0x007f, 0x0138, 0x080c, 0x6989, + 0x0120, 0x2009, 0x0009, 0x0804, 0x3563, 0x080c, 0x4abe, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3563, 0xa867, 0x0000, 0xa868, 0xc0fd, + 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a, 0x080c, 0xcd3d, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3563, 0x7007, 0x0003, 0x701f, 0x54d9, + 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x3563, 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, + 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, + 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b0a, + 0x080c, 0x4abe, 0x1120, 0x2009, 0x0002, 0x0804, 0x3563, 0x7984, + 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, + 0x19b2, 0x0040, 0x92c6, 0x0001, 0x1118, 0x7023, 0x19cc, 0x0010, + 0x0804, 0x3566, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4b07, 0x701f, 0x5529, + 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, + 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, + 0x0001, 0x4003, 0x0804, 0x3531, 0x080c, 0x4abe, 0x1120, 0x2009, + 0x0002, 0x0804, 0x3563, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, + 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b2, 0x0040, 0x92c6, 0x0001, + 0x1118, 0x2099, 0x19cc, 0x0010, 0x0804, 0x3566, 0xa85c, 0x9080, + 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, + 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, + 0x9080, 0x0019, 0xaf60, 0x0804, 0x4b0a, 0x7884, 0x908a, 0x1000, + 0x1a04, 0x3566, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, + 0x9108, 0x00c6, 0x2061, 0x19f9, 0x6142, 0x00ce, 0x012e, 0x0804, + 0x3531, 0x00c6, 0x080c, 0x73b3, 0x1160, 0x080c, 0x7699, 0x080c, + 0x602d, 0x9085, 0x0001, 0x080c, 0x73fa, 0x080c, 0x72e5, 0x080c, + 0x0dd5, 0x2061, 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5eec, + 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, + 0x0904, 0x3563, 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x199b, + 0x2c0c, 0x2062, 0x080c, 0x2c2d, 0x01a0, 0x080c, 0x2c35, 0x0188, + 0x080c, 0x2c3d, 0x0170, 0x2162, 0x0804, 0x3566, 0x2061, 0x0100, + 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, + 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, + 0xc09c, 0x602a, 0x0026, 0x2011, 0x0003, 0x080c, 0xa63e, 0x2011, + 0x0002, 0x080c, 0xa648, 0x002e, 0x080c, 0xa552, 0x0036, 0x901e, + 0x080c, 0xa5c8, 0x003e, 0x60e3, 0x0000, 0x080c, 0xea24, 0x080c, + 0xea3f, 0x9085, 0x0001, 0x080c, 0x73fa, 0x9006, 0x080c, 0x2cfc, + 0x2001, 0x1800, 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, + 0x3531, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3563, 0x080c, + 0x56f6, 0x0120, 0x2009, 0x0007, 0x0804, 0x3563, 0x7984, 0x7ea8, + 0x96b4, 0x00ff, 0x080c, 0x6616, 0x1904, 0x3566, 0x9186, 0x007f, + 0x0138, 0x080c, 0x6989, 0x0120, 0x2009, 0x0009, 0x0804, 0x3563, + 0x080c, 0x4abe, 0x1120, 0x2009, 0x0002, 0x0804, 0x3563, 0xa867, + 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xcd40, 0x1120, 0x2009, + 0x0003, 0x0804, 0x3563, 0x7007, 0x0003, 0x701f, 0x5628, 0x0005, + 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3563, + 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4b0a, 0xa898, + 0x9086, 0x000d, 0x1904, 0x3563, 0x2021, 0x4005, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x564c, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, + 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, + 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, + 0x4afa, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x119b, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x19f9, 0x7984, + 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, + 0x789c, 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x1a07, + 0x2044, 0x2001, 0x1a0e, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, + 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, + 0x0804, 0x3531, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, + 0xc000, 0x0128, 0x0006, 0x080c, 0xcba7, 0x000e, 0x1198, 0xd0e4, + 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x6047, + 0x080c, 0xadc9, 0x0110, 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, + 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, + 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, + 0x2004, 0x9005, 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, + 0x0150, 0x9186, 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, + 0x2200, 0x0801, 0x002e, 0x001e, 0x8108, 0x1f04, 0x56c5, 0x015e, + 0x012e, 0x0005, 0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, + 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, + 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, + 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, + 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x9182, + 0x0081, 0x1a04, 0x3566, 0x810c, 0x0016, 0x080c, 0x4abe, 0x080c, + 0x0f07, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, + 0x080c, 0x4b07, 0x701f, 0x571d, 0x0005, 0x2079, 0x0000, 0x7d94, + 0x7c98, 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, + 0xa770, 0xa074, 0x2071, 0x189e, 0x080c, 0x4b0a, 0x701f, 0x5731, + 0x0005, 0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, + 0x080c, 0x0f0f, 0x002e, 0x001e, 0x080c, 0x0fbc, 0x9006, 0xa802, + 0xa806, 0x0804, 0x3531, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, + 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, + 0x0200, 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, + 0x080c, 0x58ec, 0x0068, 0xd08c, 0x0118, 0x080c, 0x57f5, 0x0040, + 0xd094, 0x0118, 0x080c, 0x57c5, 0x0018, 0xd09c, 0x0108, 0x0099, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, + 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, + 0x612a, 0x001e, 0x0c68, 0x0006, 0x7098, 0x9005, 0x000e, 0x0120, + 0x709b, 0x0000, 0x7093, 0x0000, 0x624c, 0x9286, 0xf0f0, 0x1150, + 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, + 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, + 0x0128, 0x2009, 0x00f7, 0x080c, 0x5fa9, 0x00f0, 0x6040, 0x9084, + 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7087, 0x0000, + 0x70a3, 0x0001, 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009, 0x1c80, + 0x200b, 0x0000, 0x7097, 0x0000, 0x708b, 0x000f, 0x2009, 0x000f, + 0x2011, 0x5e8f, 0x080c, 0x8591, 0x0005, 0x2001, 0x1869, 0x2004, + 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, 0x1528, 0x2011, + 0x5e8f, 0x080c, 0x84f9, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, + 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x57db, + 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, + 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, 0x708f, 0x0000, + 0x9006, 0x080c, 0x6032, 0x0000, 0x0005, 0x708c, 0x908a, 0x0003, + 0x1a0c, 0x0dd5, 0x000b, 0x0005, 0x57ff, 0x5850, 0x58eb, 0x00f6, + 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, 0x015d, + 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, + 0x00fc, 0x0120, 0x1f04, 0x580e, 0x080c, 0x0dd5, 0x68a0, 0x68a2, + 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, + 0x001e, 0x6837, 0x0020, 0x080c, 0x600e, 0x2079, 0x1c00, 0x7833, + 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, + 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0xab1a, + 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, + 0x5ec0, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, 0x0005, + 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, 0x58c8, 0x6020, + 0xd0b4, 0x1904, 0x58c6, 0x71a0, 0x81ff, 0x0904, 0x58b4, 0x9486, + 0x000c, 0x1904, 0x58c1, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, + 0x6007, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304, 0x9106, + 0x11e8, 0x8210, 0x8318, 0x1f04, 0x586d, 0x6043, 0x0004, 0x2061, + 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, + 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0, 0x2011, + 0x5e96, 0x080c, 0x8591, 0x080c, 0x600e, 0x04c0, 0x080c, 0x6007, + 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, + 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, + 0x080c, 0x6007, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, + 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, + 0x58a8, 0x0078, 0x70a3, 0x0000, 0x080c, 0x6007, 0x20e1, 0x0000, + 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9, 0x0014, + 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, + 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, + 0xab1a, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19f0, + 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x080c, 0xa286, 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d, 0x1a0c, + 0x0dd5, 0x000b, 0x0005, 0x591d, 0x5930, 0x5959, 0x5979, 0x599f, + 0x59ce, 0x59f4, 0x5a2c, 0x5a52, 0x5a80, 0x5abb, 0x5af3, 0x5b11, + 0x5b3c, 0x5b5e, 0x5b79, 0x5b83, 0x5bb7, 0x5bdd, 0x5c0c, 0x5c32, + 0x5c6a, 0x5cae, 0x5ceb, 0x5d0c, 0x5d65, 0x5d87, 0x5db5, 0x5db5, + 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, + 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, + 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x709b, + 0x0001, 0x2009, 0x07d0, 0x2011, 0x5e96, 0x080c, 0x8591, 0x0005, + 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, + 0x11f0, 0x080c, 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, + 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c4, + 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, 0x5e96, 0x080c, 0x84f9, + 0x709b, 0x0010, 0x080c, 0x5b83, 0x0010, 0x7093, 0x0000, 0x00fe, + 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, 0x2011, 0x5e96, + 0x080c, 0x84f9, 0x080c, 0x5f8b, 0x2079, 0x0240, 0x7833, 0x1102, + 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, + 0x8108, 0x1f04, 0x596e, 0x60c3, 0x0014, 0x080c, 0x5ec0, 0x00fe, + 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5e96, 0x080c, + 0x84f9, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6007, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, + 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, + 0x0004, 0x0029, 0x0010, 0x080c, 0x5fe3, 0x00fe, 0x0005, 0x00f6, + 0x709b, 0x0005, 0x080c, 0x5f8b, 0x2079, 0x0240, 0x7833, 0x1103, + 0x7837, 0x0000, 0x080c, 0x6007, 0x080c, 0x5fea, 0x1170, 0x7084, + 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, + 0x080c, 0x5e43, 0x0168, 0x080c, 0x5fc0, 0x20a9, 0x0008, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, + 0x9005, 0x0500, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, + 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0006, 0x0029, 0x0010, + 0x080c, 0x5fe3, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007, 0x080c, + 0x5f8b, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, + 0x6007, 0x080c, 0x5fea, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, + 0x9186, 0xffff, 0x0180, 0x9180, 0x3332, 0x200d, 0x918c, 0xff00, + 0x810f, 0x2011, 0x0008, 0x080c, 0x5e43, 0x0180, 0x080c, 0x4ff4, + 0x0110, 0x080c, 0x28b4, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x5eb6, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, - 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x9086, 0x0014, 0x11b8, 0x080c, - 0x5ffd, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, + 0x080c, 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, + 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, - 0x70c7, 0x0001, 0x709b, 0x0006, 0x0029, 0x0010, 0x080c, 0x5fd9, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007, 0x080c, 0x5f81, 0x2079, - 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5ffd, 0x080c, - 0x5fe0, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, - 0x0180, 0x9180, 0x3327, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, - 0x0008, 0x080c, 0x5e39, 0x0180, 0x080c, 0x4fea, 0x0110, 0x080c, - 0x28a9, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb6, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5e8c, - 0x080c, 0x84dc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5ffd, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0008, 0x0029, 0x0010, 0x080c, 0x5fd9, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0009, 0x080c, 0x5f81, 0x2079, 0x0240, 0x7833, - 0x1105, 0x7837, 0x0100, 0x080c, 0x5fe0, 0x1150, 0x7084, 0x9005, - 0x1138, 0x080c, 0x5dac, 0x1188, 0x9085, 0x0001, 0x080c, 0x28a9, - 0x20a9, 0x0008, 0x080c, 0x5ffd, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5eb6, 0x0010, 0x080c, 0x5906, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x05a8, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x9086, 0x0014, - 0x1560, 0x080c, 0x5ffd, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, - 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, 0x0000, - 0x709b, 0x000e, 0x080c, 0x5b54, 0x0010, 0x080c, 0x5fd9, 0x00fe, - 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, 0x1c0e, 0x20e9, 0x0001, - 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x5f81, - 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5fe0, - 0x0118, 0x2013, 0x0000, 0x0020, 0x7060, 0x9085, 0x0100, 0x2012, - 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x1c0e, 0x220e, 0x8210, - 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x1f04, 0x5ad6, 0x60c3, 0x0084, 0x080c, 0x5eb6, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0, 0x2011, 0x5e8c, 0x080c, - 0x84dc, 0x9086, 0x0084, 0x1178, 0x080c, 0x5ffd, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x709b, - 0x000c, 0x0029, 0x0010, 0x080c, 0x5fd9, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x000d, 0x080c, 0x5f81, 0x2079, 0x0240, 0x7833, 0x1107, - 0x7837, 0x0000, 0x080c, 0x5ffd, 0x20a9, 0x0040, 0x2011, 0x026e, - 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, - 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, - 0x2011, 0x0260, 0x1f04, 0x5b1a, 0x60c3, 0x0084, 0x080c, 0x5eb6, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x5e8c, - 0x080c, 0x84dc, 0x9086, 0x0084, 0x1198, 0x080c, 0x5ffd, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, - 0x7097, 0x0001, 0x080c, 0x5f53, 0x709b, 0x000e, 0x0029, 0x0010, - 0x080c, 0x5fd9, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x6028, - 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, - 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, - 0x2009, 0x07d0, 0x2011, 0x5e8c, 0x080c, 0x84d0, 0x0005, 0x7090, - 0x9005, 0x0130, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x709b, 0x0000, - 0x0005, 0x709b, 0x0011, 0x080c, 0xab2c, 0x080c, 0x5ffd, 0x20e1, - 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7490, - 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, - 0x4003, 0x080c, 0x5fe0, 0x11a0, 0x717c, 0x81ff, 0x0188, 0x900e, - 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c, 0x2840, 0x9186, 0x007e, - 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5e39, - 0x60c3, 0x0014, 0x080c, 0x5eb6, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x5ffd, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0013, 0x080c, 0x5f8f, - 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5ffd, - 0x080c, 0x5fe0, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, - 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5e39, 0x0168, 0x080c, - 0x5fb6, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb6, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5e8c, - 0x080c, 0x84dc, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5ffd, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, + 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, 0x080c, 0x5fe3, + 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, 0x5f8b, 0x2079, + 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x5fea, 0x1150, + 0x7084, 0x9005, 0x1138, 0x080c, 0x5db6, 0x1188, 0x9085, 0x0001, + 0x080c, 0x28b4, 0x20a9, 0x0008, 0x080c, 0x6007, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x5ec0, 0x0010, 0x080c, 0x5910, 0x00fe, 0x0005, + 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, 0x5e96, 0x080c, 0x84f9, + 0x9086, 0x0014, 0x1560, 0x080c, 0x6007, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, + 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, + 0x70c7, 0x0001, 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0014, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0015, 0x080c, 0x5f8f, 0x2079, 0x0240, 0x7833, - 0x1104, 0x7837, 0x0000, 0x080c, 0x5ffd, 0x080c, 0x5fe0, 0x11b8, - 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, - 0x3327, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, - 0x5e39, 0x0180, 0x080c, 0x4fea, 0x0110, 0x080c, 0x28a9, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb6, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011, 0x5e8c, 0x080c, 0x84dc, - 0x9086, 0x0014, 0x15a8, 0x080c, 0x5ffd, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, - 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x6028, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, 0x9005, - 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x9085, 0x0001, 0x080c, 0x6028, 0x7097, 0x0000, 0x7a38, - 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, 0x0016, 0x0029, 0x0010, - 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c, 0xab2c, 0x080c, 0x5ffd, - 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, - 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, - 0x5fe0, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5dac, 0x1188, - 0x9085, 0x0001, 0x080c, 0x28a9, 0x20a9, 0x0008, 0x080c, 0x5ffd, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb6, 0x0010, 0x080c, 0x5906, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8, 0x2011, 0x5e8c, 0x080c, - 0x84dc, 0x9086, 0x0084, 0x1190, 0x080c, 0x5ffd, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, - 0x080c, 0x6028, 0x709b, 0x0018, 0x0029, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019, 0x080c, 0x5f8f, 0x2079, - 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5ffd, 0x2009, - 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, - 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, - 0x1f04, 0x5d15, 0x2039, 0x1c0e, 0x080c, 0x5fe0, 0x11e8, 0x2728, - 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, - 0x8007, 0x9205, 0x202a, 0x7060, 0x2310, 0x8214, 0x92a0, 0x1c0e, - 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, - 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, - 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, - 0x6812, 0x2009, 0x0240, 0x1f04, 0x5d48, 0x60c3, 0x0084, 0x080c, - 0x5eb6, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, - 0x5e8c, 0x080c, 0x84dc, 0x9086, 0x0084, 0x1198, 0x080c, 0x5ffd, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, - 0x1140, 0x7097, 0x0001, 0x080c, 0x5f53, 0x709b, 0x001a, 0x0029, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, - 0x6028, 0x709b, 0x001b, 0x080c, 0xab2c, 0x080c, 0x5ffd, 0x2011, - 0x0260, 0x2009, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, - 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, + 0x7097, 0x0000, 0x709b, 0x000e, 0x080c, 0x5b5e, 0x0010, 0x080c, + 0x5fe3, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, 0x1c0e, + 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, + 0x080c, 0x5f8b, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, + 0x080c, 0x5fea, 0x0118, 0x2013, 0x0000, 0x0020, 0x7060, 0x9085, + 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x1c0e, + 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, + 0x6812, 0x2009, 0x0240, 0x1f04, 0x5ae0, 0x60c3, 0x0084, 0x080c, + 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0, 0x2011, + 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0084, 0x1178, 0x080c, 0x6007, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, + 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, 0x5fe3, 0x00fe, + 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, 0x5f8b, 0x2079, 0x0240, + 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x6007, 0x20a9, 0x0040, + 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, - 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5d94, 0x60c3, 0x0084, - 0x080c, 0x5eb6, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1848, - 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e, 0x20e9, 0x0001, 0x28a0, - 0x080c, 0x5ffd, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, - 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, - 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, - 0x8211, 0x1f04, 0x5dc6, 0x0804, 0x5e35, 0x82ff, 0x1160, 0xd5d4, - 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, - 0x5e35, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, - 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, - 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, - 0x5dec, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, - 0x5dfe, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, - 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, - 0x5e0d, 0x755e, 0x95c8, 0x3327, 0x292d, 0x95ac, 0x00ff, 0x7582, - 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2889, 0x001e, 0x60e7, - 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x7087, 0x0001, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, - 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, - 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, - 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, - 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, - 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, - 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, - 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, - 0x91a0, 0x3327, 0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, - 0x0016, 0x2508, 0x080c, 0x2889, 0x001e, 0x60e7, 0x0000, 0x65ea, - 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, - 0x2071, 0x0140, 0x080c, 0x5f42, 0x080c, 0xa274, 0x7004, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2d01, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1826, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, - 0x080c, 0x5f9f, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, - 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x080c, 0x2ba7, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, - 0x2012, 0x2011, 0x19f0, 0x2013, 0x0000, 0x7093, 0x0000, 0x012e, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa26b, 0x6144, 0xd184, - 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, 0x718c, 0x918d, 0x1000, - 0x2011, 0x1998, 0x2112, 0x2009, 0x07d0, 0x2011, 0x5e8c, 0x080c, - 0x8574, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xade2, 0x2009, 0x00f7, 0x080c, 0x5f9f, 0x2061, 0x19f9, - 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, 0x1800, 0x6003, - 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, - 0x1998, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5f0e, 0x080c, - 0x84d0, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, - 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, 0x080c, 0xa274, - 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d01, - 0x080c, 0x73ad, 0x0188, 0x080c, 0x73c8, 0x1170, 0x080c, 0x7697, - 0x0016, 0x080c, 0x2958, 0x2001, 0x196c, 0x2102, 0x001e, 0x080c, - 0x7692, 0x080c, 0x72d7, 0x0050, 0x2009, 0x0001, 0x080c, 0x2c40, - 0x2001, 0x0001, 0x080c, 0x27ec, 0x080c, 0x5ee2, 0x012e, 0x000e, - 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, 0x0158, 0x0026, - 0x0036, 0x2011, 0x8017, 0x2001, 0x1998, 0x201c, 0x080c, 0x4b14, - 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, 0x20a1, - 0x1c80, 0x080c, 0x5ffd, 0x20e9, 0x0000, 0x2099, 0x026e, 0x0099, - 0x20a9, 0x0020, 0x080c, 0x5ff7, 0x2099, 0x0260, 0x20a1, 0x1c92, - 0x0051, 0x20a9, 0x000e, 0x080c, 0x5ffa, 0x2099, 0x0260, 0x20a1, - 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, - 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5f77, 0x002e, 0x001e, - 0x0005, 0x080c, 0xab2c, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x080c, - 0xab2c, 0x080c, 0x5ffd, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, - 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834, 0x2004, 0x9005, - 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, - 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, - 0x080c, 0x6977, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, - 0xe5cf, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, - 0x900e, 0x080c, 0x318c, 0x080c, 0xd24a, 0x0140, 0x0036, 0x2019, - 0xffff, 0x2021, 0x0007, 0x080c, 0x4ccb, 0x003e, 0x004e, 0x001e, - 0x0005, 0x080c, 0x5ee2, 0x709b, 0x0000, 0x7093, 0x0000, 0x0005, - 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, - 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, - 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x2009, - 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, 0x6814, 0x9084, - 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, 0x0146, 0x01d6, - 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x4004, - 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, 0x00ef, - 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, 0x014e, - 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, 0x0001, 0x0005, - 0x2001, 0x19a5, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, 0x0000, - 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, 0x9006, 0x200a, - 0x8108, 0x1f04, 0x6037, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, - 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802, 0xb8ce, 0xb807, - 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x3327, 0x231d, 0x939c, - 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8c2, 0x080c, 0xaddb, 0x1120, - 0x9192, 0x007e, 0x1208, 0xbbc2, 0x20a9, 0x0004, 0xb8c4, 0x20e8, - 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, 0x20a9, 0x0004, - 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, 0xb83e, 0xb842, - 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e, 0xb862, 0xb866, 0xb86a, - 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, - 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, 0x0096, 0xb8a4, - 0x904d, 0x0110, 0x080c, 0x1031, 0xb8a7, 0x0000, 0x009e, 0x9006, - 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, 0x0520, 0xb8ac, - 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1cd0, 0x0a0c, 0x0dd5, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0dd5, 0x080c, 0x896a, - 0x00ce, 0x090c, 0x8d0e, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff, - 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1a04, 0x6125, 0x9182, 0x0800, 0x1a04, 0x6129, 0x2001, 0x180c, - 0x2004, 0x9084, 0x0003, 0x1904, 0x612f, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1508, - 0xb8a4, 0x900d, 0x1904, 0x6141, 0xb850, 0x900d, 0x1148, 0xa802, - 0x2900, 0xb852, 0xb84e, 0x080c, 0x90f6, 0x9006, 0x012e, 0x0005, - 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803, 0x0000, 0x00ae, 0xb852, - 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e, - 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0xaddb, 0x1160, 0xb8a0, - 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0990, 0x2001, 0x0029, - 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, 0xd1fc, 0x0118, - 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, - 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, - 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x905d, - 0x09a8, 0x080c, 0x697b, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, - 0x60d8, 0x080c, 0x67a4, 0x0904, 0x60f1, 0x0804, 0x60dc, 0x00b6, - 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, 0x1120, - 0x2001, 0x196a, 0x205c, 0x0060, 0xa974, 0x9182, 0x0800, 0x1690, - 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0, 0x080c, 0x691b, 0x11d0, - 0x080c, 0xae1b, 0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, - 0x0009, 0x600b, 0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, 0x600b, - 0x8000, 0x2009, 0x0043, 0x080c, 0xaeec, 0x9006, 0x00b0, 0x2001, - 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, - 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, - 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, 0x620f, 0x9188, 0x1000, - 0x2104, 0x905d, 0x0904, 0x61e7, 0xb8a0, 0x9086, 0x007f, 0x0178, - 0x080c, 0x6983, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, - 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x697b, 0x1598, 0xa87c, - 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, - 0x080c, 0xcb38, 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, 0x6211, - 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, 0x6211, - 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, 0xae1b, - 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, - 0x000a, 0x2009, 0x0003, 0x080c, 0xaeec, 0x9006, 0x0458, 0x2001, - 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, 0xaddb, 0x1160, - 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, - 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, - 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, - 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, - 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, - 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, 0x9005, - 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, 0x1518, - 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, 0x9182, - 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, 0xab94, - 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, - 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, - 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, - 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, - 0x0005, 0x62a6, 0x6261, 0x6278, 0x62a6, 0x62a6, 0x62a6, 0x62a6, - 0x62a6, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, 0x65a7, 0x0148, - 0x9046, 0xb810, 0x9306, 0x1904, 0x62ae, 0xb814, 0x9206, 0x15f0, - 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x49c7, 0x0150, 0x04b0, - 0x080c, 0x6608, 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, - 0x1568, 0x080c, 0xae1b, 0x0530, 0x2b00, 0x6012, 0x080c, 0xcfc4, - 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, - 0x0001, 0x1170, 0x080c, 0x31c1, 0x9006, 0x080c, 0x6544, 0x2001, - 0x0002, 0x080c, 0x6558, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, - 0x2009, 0x0003, 0x080c, 0xaeec, 0x9006, 0x0068, 0x2001, 0x0001, - 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, - 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, - 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, - 0x0904, 0x6495, 0x90c6, 0x0056, 0x0904, 0x6499, 0x90c6, 0x0066, - 0x0904, 0x649d, 0x90c6, 0x0067, 0x0904, 0x64a1, 0x90c6, 0x0068, - 0x0904, 0x64a5, 0x90c6, 0x0071, 0x0904, 0x64a9, 0x90c6, 0x0074, - 0x0904, 0x64ad, 0x90c6, 0x007c, 0x0904, 0x64b1, 0x90c6, 0x007e, - 0x0904, 0x64b5, 0x90c6, 0x0037, 0x0904, 0x64b9, 0x9016, 0x2079, - 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x6490, 0x9182, 0x0800, - 0x1a04, 0x6490, 0x080c, 0x6608, 0x1198, 0xb804, 0x9084, 0x00ff, - 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, - 0xaddb, 0x1904, 0x6479, 0xb8a0, 0x9084, 0xff80, 0x1904, 0x6479, - 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x63d9, - 0x90c6, 0x0064, 0x0904, 0x6402, 0x2008, 0x0804, 0x639b, 0xa998, - 0xa8b0, 0x2040, 0x080c, 0xaddb, 0x1120, 0x9182, 0x007f, 0x0a04, - 0x639b, 0x9186, 0x00ff, 0x0904, 0x639b, 0x9182, 0x0800, 0x1a04, - 0x639b, 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x1188, 0x7880, 0x0096, - 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, 0x639b, 0x99cc, - 0xff00, 0x009e, 0x1120, 0x2208, 0x2310, 0x0804, 0x639b, 0x080c, - 0x49c7, 0x0904, 0x63a5, 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, - 0x0006, 0x080c, 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, - 0x0f7c, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, - 0x0f7c, 0xa8c4, 0xabc8, 0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, - 0xabd4, 0x9305, 0xabd8, 0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, - 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, - 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, - 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, - 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, - 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c, 0xae1b, 0x1130, - 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, - 0x080c, 0xcfc4, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x31c1, - 0x012e, 0x9006, 0x080c, 0x6544, 0x2001, 0x0002, 0x080c, 0x6558, - 0x2009, 0x0002, 0x080c, 0xaeec, 0xa8b0, 0xd094, 0x0118, 0xb8cc, - 0xc08d, 0xb8ce, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, - 0x0005, 0x080c, 0x56ec, 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, - 0xaeb0, 0x080c, 0x6608, 0x1904, 0x6396, 0x9186, 0x007f, 0x0130, - 0x080c, 0x697b, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, - 0x0fff, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, - 0xa806, 0x080c, 0xcd30, 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x639d, 0xa998, 0xaeb0, 0x080c, 0x6608, 0x1904, 0x6396, - 0x0096, 0x080c, 0x0fff, 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, - 0x6456, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, - 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, - 0xbbc8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f7c, 0x009e, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, - 0x56d8, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, - 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x697b, 0x0118, 0xa89b, - 0x0009, 0x0080, 0x080c, 0x56ec, 0x0118, 0xa89b, 0x0007, 0x0050, - 0x080c, 0xcd13, 0x1904, 0x63d2, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x639d, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, - 0x2041, 0x1243, 0x080c, 0xb38b, 0x1904, 0x63d2, 0x2009, 0x0002, - 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x63d3, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x63d3, - 0x2001, 0x0029, 0x900e, 0x0804, 0x63d3, 0x080c, 0x3756, 0x0804, - 0x63d4, 0x080c, 0x5415, 0x0804, 0x63d4, 0x080c, 0x4554, 0x0804, - 0x63d4, 0x080c, 0x45cd, 0x0804, 0x63d4, 0x080c, 0x4629, 0x0804, - 0x63d4, 0x080c, 0x4a8a, 0x0804, 0x63d4, 0x080c, 0x4d3a, 0x0804, - 0x63d4, 0x080c, 0x5080, 0x0804, 0x63d4, 0x080c, 0x5279, 0x0804, - 0x63d4, 0x080c, 0x396c, 0x0804, 0x63d4, 0x00b6, 0xa974, 0xae78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182, 0x0800, 0x1268, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, 0x080c, 0x697b, 0x1148, - 0x00e9, 0x080c, 0x6733, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, - 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d88, 0x2001, - 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, - 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, 0x0126, 0x2091, - 0x8000, 0xb850, 0x900d, 0x0150, 0x2900, 0x0096, 0x2148, 0xa802, - 0x009e, 0xa803, 0x0000, 0xb852, 0x012e, 0x0005, 0x2900, 0xb852, - 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0xb84c, - 0x9005, 0x0170, 0x00e6, 0x2071, 0x19e6, 0x7004, 0x9086, 0x0002, - 0x0168, 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e, 0x012e, 0x0005, - 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x701c, 0x9b06, - 0x1d80, 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802, 0x2900, 0xb002, - 0x00ae, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0xb84c, - 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, - 0x012e, 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, - 0xb852, 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, - 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, - 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, - 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, - 0x6977, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, - 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, - 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0dd5, 0x000e, - 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, - 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6973, 0x1138, 0x9284, 0x00ff, - 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, - 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, - 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, - 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, 0x0fff, 0x2958, - 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, 0xb860, 0xb8c6, - 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x603d, 0x9006, 0x0010, 0x9085, - 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, - 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, - 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1031, 0x00d6, 0x00c6, 0xb8bc, - 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, - 0xcb4a, 0x0110, 0x080c, 0x0fb1, 0x080c, 0xae71, 0x00ce, 0x0c88, - 0x00ce, 0x00de, 0x2b48, 0xb8c8, 0xb85e, 0xb8c4, 0xb862, 0x080c, - 0x1041, 0x00de, 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, - 0x0016, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, - 0x1000, 0x2104, 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, - 0x0156, 0x0136, 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, - 0xb802, 0x080c, 0x73a5, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, - 0x080c, 0xaddb, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, - 0x2061, 0x1981, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, - 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, - 0x2001, 0x0001, 0x6886, 0x2069, 0x1800, 0x68b6, 0x7040, 0xb85e, - 0x7048, 0xb862, 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, - 0xb8c4, 0x20e8, 0xb8c8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, - 0x4003, 0x2099, 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, - 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, - 0xb96e, 0x7048, 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, - 0x0000, 0xb8a0, 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, - 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, - 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, - 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, - 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, - 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, - 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, - 0x7034, 0xb896, 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbcc, - 0xc384, 0xba00, 0x2009, 0x1867, 0x210c, 0xd0bc, 0x0120, 0xd1ec, - 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, - 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, - 0xba02, 0xbbce, 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, - 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, - 0x15c0, 0xaa04, 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, - 0x01d6, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, - 0xffc0, 0x9080, 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, - 0x4002, 0x9086, 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0dd5, - 0x3c00, 0x20e8, 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x0060, 0x080c, 0x0fff, 0x0170, - 0x2900, 0xb8a6, 0xa803, 0x0000, 0x080c, 0x67c4, 0xa807, 0x0001, - 0xae12, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, - 0x0126, 0x2091, 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, - 0x9005, 0x1150, 0x080c, 0x67d3, 0x1158, 0xa804, 0x908a, 0x0002, - 0x0218, 0x8001, 0xa806, 0x0020, 0x080c, 0x1031, 0xb8a7, 0x0000, - 0x009e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x90f6, - 0x012e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, - 0x2091, 0x8000, 0xb84c, 0x2048, 0xb800, 0xd0dc, 0x1170, 0x89ff, - 0x0500, 0x83ff, 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, - 0x9406, 0x1118, 0xa870, 0x9506, 0x0120, 0x2908, 0xa800, 0x2048, - 0x0c70, 0x080c, 0xa693, 0xaa00, 0xb84c, 0x9906, 0x1110, 0xba4e, - 0x0020, 0x00a6, 0x2150, 0xb202, 0x00ae, 0x82ff, 0x1110, 0xb952, - 0x89ff, 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, - 0x0005, 0x080c, 0x6828, 0x0128, 0x080c, 0xcc07, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x6828, 0x0128, 0x080c, 0xcbac, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x6828, 0x0128, 0x080c, 0xcc04, - 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6828, 0x0128, 0x080c, - 0xcbcb, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6828, 0x0128, - 0x080c, 0xcc48, 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, - 0x1118, 0x9085, 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, - 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, - 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, - 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, - 0x9006, 0x01ce, 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, - 0x4104, 0x01de, 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, - 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, - 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, - 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, - 0x01d6, 0x3300, 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, - 0x4004, 0x01de, 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, - 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x0fff, - 0x0168, 0x2900, 0xb8a6, 0x080c, 0x67c4, 0xa803, 0x0001, 0xa807, - 0x0000, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, - 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, - 0x0000, 0x080c, 0x1031, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, - 0xb89c, 0xd0a4, 0x0005, 0x00b6, 0x00f6, 0x080c, 0x73a5, 0x01b0, - 0x71c4, 0x81ff, 0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, - 0x9080, 0x1000, 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, - 0x7804, 0xd0a4, 0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, - 0x080c, 0x6608, 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, - 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, - 0x001e, 0x8108, 0x1f04, 0x684f, 0x015e, 0x080c, 0x6939, 0x0120, - 0x2001, 0x1984, 0x200c, 0x0038, 0x2079, 0x1847, 0x7804, 0xd0a4, - 0x0130, 0x2009, 0x07d0, 0x2011, 0x687a, 0x080c, 0x8574, 0x00fe, - 0x00be, 0x0005, 0x00b6, 0x2011, 0x687a, 0x080c, 0x84dc, 0x080c, - 0x6939, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, - 0xb902, 0x080c, 0x6977, 0x0130, 0x2009, 0x07d0, 0x2011, 0x687a, - 0x080c, 0x8574, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, - 0x7082, 0x080c, 0x2f98, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x6608, 0x1538, 0xb800, 0xd0ec, - 0x0520, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, - 0xe5cf, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6973, 0x2001, - 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, - 0x2019, 0x0029, 0x080c, 0x927e, 0x0076, 0x903e, 0x080c, 0x9151, - 0x900e, 0x080c, 0xe30c, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, - 0x68a2, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, - 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, - 0x080c, 0x1018, 0x090c, 0x0dd5, 0x2958, 0x009e, 0x2001, 0x196a, - 0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, - 0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x603d, - 0xb807, 0x0006, 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, - 0xb86c, 0xb893, 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, - 0x0000, 0x00ce, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, - 0x00be, 0xd0bc, 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, - 0x00ff, 0x9196, 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, - 0x0005, 0x0158, 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, - 0x9196, 0x0004, 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, - 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, - 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, - 0x0dd5, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0x1982, 0x200c, 0x2011, 0x6969, 0x080c, 0x8574, - 0x0005, 0x2011, 0x6969, 0x080c, 0x84dc, 0x2011, 0x1837, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x080c, 0x56d8, 0xd0ac, 0x0005, 0x080c, - 0x56d8, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, - 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, - 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd24a, - 0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, - 0x905d, 0x0110, 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x2071, - 0x1910, 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, - 0x701a, 0x701e, 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, - 0x1947, 0x900e, 0x710a, 0x080c, 0x56d8, 0xd0fc, 0x1140, 0x080c, - 0x56d8, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x00f8, 0x2001, - 0x1867, 0x200c, 0x9184, 0x0007, 0x0002, 0x69b7, 0x69b7, 0x69b7, - 0x69b7, 0x69b7, 0x69cd, 0x69db, 0x69b7, 0x7003, 0x0003, 0x2009, - 0x1868, 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, - 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, - 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, - 0x2071, 0x1910, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, - 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, 0x76ff, 0x6a60, 0x9200, - 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, - 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, - 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, - 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, - 0x1910, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, - 0x00ee, 0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1947, - 0x7000, 0x9015, 0x0904, 0x6c8b, 0x9286, 0x0003, 0x0904, 0x6b21, - 0x9286, 0x0005, 0x0904, 0x6b21, 0x2071, 0x1877, 0xa87c, 0x9005, - 0x0904, 0x6a82, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6c8b, 0xa878, - 0xd084, 0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, - 0x1910, 0x701c, 0x9005, 0x1904, 0x6e21, 0x0e04, 0x6e8f, 0x2071, - 0x0000, 0xa850, 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, - 0x708a, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, - 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, - 0x013e, 0x01de, 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x119b, 0x0804, 0x6b04, 0xa853, 0x001b, 0x2001, - 0x8027, 0x0820, 0x7004, 0xd08c, 0x1904, 0x6c8b, 0xa853, 0x001a, - 0x2001, 0x8024, 0x0804, 0x6a46, 0x00e6, 0x0026, 0x2071, 0x1947, - 0x7000, 0x9015, 0x0904, 0x6c8b, 0x9286, 0x0003, 0x0904, 0x6b21, - 0x9286, 0x0005, 0x0904, 0x6b21, 0xa84f, 0x8022, 0xa853, 0x0018, - 0x0804, 0x6ae9, 0xa868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, 0x2001, - 0x1947, 0x2004, 0x9005, 0x0904, 0x6c8b, 0xa87c, 0xd0bc, 0x1904, - 0x6c8b, 0xa978, 0xa874, 0x9105, 0x1904, 0x6c8b, 0x2001, 0x1947, - 0x2004, 0x0002, 0x6c8b, 0x6ae5, 0x6b21, 0x6b21, 0x6c8b, 0x6b21, - 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x1947, - 0x210c, 0x81ff, 0x0904, 0x6c8b, 0xa87c, 0xd0cc, 0x0904, 0x6c8b, - 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6c8b, 0x9186, - 0x0003, 0x0904, 0x6b21, 0x9186, 0x0005, 0x0904, 0x6b21, 0xa84f, - 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, - 0x0016, 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, 0x6e21, 0x0e04, - 0x6e8f, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, - 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x119b, 0x2071, 0x1800, 0x2011, 0x0001, - 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x83fd, 0x002e, 0x00ee, 0x0005, 0x0096, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, - 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, - 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x6c10, 0x782c, 0x908c, - 0x0780, 0x190c, 0x6fdb, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, - 0x0002, 0x6b3f, 0x6c10, 0x6b64, 0x6bab, 0x080c, 0x0dd5, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1170, 0x2071, 0x19f9, - 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x83fd, 0x0c10, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1580, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, - 0xd19c, 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, - 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, - 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x83fd, 0x782c, 0x9094, - 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x19f0, 0x2071, 0x19f9, 0x703c, + 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5b24, 0x60c3, 0x0084, + 0x080c, 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, + 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0084, 0x1198, 0x080c, + 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, + 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x5f5d, 0x709b, 0x000e, + 0x0029, 0x0010, 0x080c, 0x5fe3, 0x00fe, 0x0005, 0x918d, 0x0001, + 0x080c, 0x6032, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, 0x0140, + 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, + 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5e96, 0x080c, 0x84ed, + 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, 0x5e96, 0x080c, 0x84f9, + 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, 0xab1a, 0x080c, + 0x6007, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, + 0x8004, 0x20a8, 0x4003, 0x080c, 0x5fea, 0x11a0, 0x717c, 0x81ff, + 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c, 0x284b, + 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, + 0x080c, 0x5e43, 0x60c3, 0x0014, 0x080c, 0x5ec0, 0x0005, 0x00f6, + 0x7090, 0x9005, 0x0500, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012, 0x0029, + 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0013, + 0x080c, 0x5f99, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, + 0x080c, 0x6007, 0x080c, 0x5fea, 0x1170, 0x7084, 0x9005, 0x1158, + 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5e43, + 0x0168, 0x080c, 0x5fc0, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, + 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, + 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, + 0x70c7, 0x0001, 0x709b, 0x0014, 0x0029, 0x0010, 0x7093, 0x0000, + 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0015, 0x080c, 0x5f99, 0x2079, + 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6007, 0x080c, + 0x5fea, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, + 0x0180, 0x9180, 0x3332, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, + 0x0008, 0x080c, 0x5e43, 0x0180, 0x080c, 0x4ff4, 0x0110, 0x080c, + 0x28b4, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ec0, + 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011, 0x5e96, + 0x080c, 0x84f9, 0x9086, 0x0014, 0x15a8, 0x080c, 0x6007, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, + 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x6032, + 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, + 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, + 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, 0x6032, 0x7097, + 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, 0x0016, + 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c, 0xab1a, + 0x080c, 0x6007, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, + 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, + 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x709b, + 0x0017, 0x080c, 0x5fea, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, + 0x5db6, 0x1188, 0x9085, 0x0001, 0x080c, 0x28b4, 0x20a9, 0x0008, + 0x080c, 0x6007, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ec0, 0x0010, + 0x080c, 0x5910, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8, 0x2011, + 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0084, 0x1190, 0x080c, 0x6007, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, + 0x1138, 0x9006, 0x080c, 0x6032, 0x709b, 0x0018, 0x0029, 0x0010, + 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019, 0x080c, + 0x5f99, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, + 0x6007, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040, 0x213e, + 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, + 0x2009, 0x0260, 0x1f04, 0x5d1f, 0x2039, 0x1c0e, 0x080c, 0x5fea, + 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, + 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7060, 0x2310, 0x8214, + 0x92a0, 0x1c0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, + 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, + 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, + 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5d52, 0x60c3, + 0x0084, 0x080c, 0x5ec0, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, + 0x01e0, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x9086, 0x0084, 0x1198, + 0x080c, 0x6007, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, + 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x5f5d, 0x709b, + 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x9085, + 0x0001, 0x080c, 0x6032, 0x709b, 0x001b, 0x080c, 0xab1a, 0x080c, + 0x6007, 0x2011, 0x0260, 0x2009, 0x0240, 0x7490, 0x9480, 0x0018, + 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, + 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, + 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5d9e, + 0x60c3, 0x0084, 0x080c, 0x5ec0, 0x0005, 0x0005, 0x0086, 0x0096, + 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e, 0x20e9, + 0x0001, 0x28a0, 0x080c, 0x6007, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, + 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, + 0x8210, 0x0008, 0x8211, 0x1f04, 0x5dd0, 0x0804, 0x5e3f, 0x82ff, + 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, + 0x3fff, 0x0904, 0x5e3f, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, + 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, + 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, + 0x8318, 0x1f04, 0x5df6, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, + 0x8425, 0x1f04, 0x5e08, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, + 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, + 0x0010, 0x1f04, 0x5e17, 0x755e, 0x95c8, 0x3332, 0x292d, 0x95ac, + 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2894, + 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, + 0x7087, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, + 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, + 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, + 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, + 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, + 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, + 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, + 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, + 0x203a, 0x715e, 0x91a0, 0x3332, 0x242d, 0x95ac, 0x00ff, 0x7582, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2894, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, + 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, + 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x5f4c, 0x080c, 0xa28f, + 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d0c, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, + 0x2009, 0x00f7, 0x080c, 0x5fa9, 0x001e, 0x9094, 0x0010, 0x9285, + 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x2bb2, 0x0228, 0x2011, 0x0101, + 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f0, 0x2013, 0x0000, 0x7093, + 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa286, + 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, 0x718c, + 0x918d, 0x1000, 0x2011, 0x1998, 0x2112, 0x2009, 0x07d0, 0x2011, + 0x5e96, 0x080c, 0x8591, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x080c, 0xadd0, 0x2009, 0x00f7, 0x080c, 0x5fa9, + 0x2061, 0x19f9, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, + 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, + 0x0010, 0x2009, 0x1998, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, + 0x5f18, 0x080c, 0x84ed, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, + 0x080c, 0xa28f, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, + 0x080c, 0x2d0c, 0x080c, 0x73bb, 0x0188, 0x080c, 0x73d6, 0x1170, + 0x080c, 0x76a3, 0x0016, 0x080c, 0x2963, 0x2001, 0x196c, 0x2102, + 0x001e, 0x080c, 0x769e, 0x080c, 0x72e5, 0x0050, 0x2009, 0x0001, + 0x080c, 0x2c4b, 0x2001, 0x0001, 0x080c, 0x27f7, 0x080c, 0x5eec, + 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, + 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1998, 0x201c, + 0x080c, 0x4b1e, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, + 0x0001, 0x20a1, 0x1c80, 0x080c, 0x6007, 0x20e9, 0x0000, 0x2099, + 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6001, 0x2099, 0x0260, + 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6004, 0x2099, + 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, + 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5f81, + 0x002e, 0x001e, 0x0005, 0x080c, 0xab1a, 0x20e1, 0x0001, 0x2099, + 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, + 0x0005, 0x080c, 0xab1a, 0x080c, 0x6007, 0x20e1, 0x0000, 0x2099, + 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, + 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834, + 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, + 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, + 0x0016, 0x0046, 0x080c, 0x6985, 0x0158, 0x9006, 0x2020, 0x2009, + 0x002a, 0x080c, 0xe5e9, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, + 0x2019, 0x002a, 0x900e, 0x080c, 0x3197, 0x080c, 0xd25a, 0x0140, + 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4cd5, 0x003e, + 0x004e, 0x001e, 0x0005, 0x080c, 0x5eec, 0x709b, 0x0000, 0x7093, + 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, + 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, + 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, + 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, + 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, + 0x1c00, 0x4004, 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807, 0x00ef, + 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, + 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, + 0x0001, 0x0005, 0x2001, 0x19a5, 0x0118, 0x2003, 0x0001, 0x0010, + 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, + 0x9006, 0x200a, 0x8108, 0x1f04, 0x6041, 0x015e, 0x0005, 0x00d6, + 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802, + 0xb8ce, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x3332, + 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8c2, 0x080c, + 0xadc9, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbc2, 0x20a9, 0x0004, + 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, + 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, + 0xb83e, 0xb842, 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e, 0xb862, + 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, + 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, + 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1031, 0xb8a7, 0x0000, + 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, + 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1cd0, + 0x0a0c, 0x0dd5, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0dd5, + 0x080c, 0x8987, 0x00ce, 0x090c, 0x8d2d, 0xb8af, 0x0000, 0x6814, + 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1a04, 0x612f, 0x9182, 0x0800, 0x1a04, 0x6133, + 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x6139, 0x9188, + 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff, 0x908e, + 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x614b, 0xb850, 0x900d, + 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, 0x9115, 0x9006, + 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803, 0x0000, + 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, + 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0xadc9, + 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0990, + 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, + 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, + 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, + 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, + 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, + 0x2104, 0x905d, 0x09a8, 0x080c, 0x6989, 0x1990, 0xb800, 0xd0bc, + 0x0978, 0x0804, 0x60e2, 0x080c, 0x67b2, 0x0904, 0x60fb, 0x0804, + 0x60e6, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, 0x908e, + 0x00ff, 0x1120, 0x2001, 0x196a, 0x205c, 0x0060, 0xa974, 0x9182, + 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0, 0x080c, + 0x6929, 0x11d0, 0x080c, 0xae09, 0x0570, 0x2b00, 0x6012, 0x2900, + 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0xa874, 0x908e, 0x00ff, + 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, 0xaeda, 0x9006, + 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, + 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, 0x6219, + 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x61f1, 0xb8a0, 0x9086, + 0x007f, 0x0178, 0x080c, 0x6991, 0x0160, 0xa994, 0x81ff, 0x0130, + 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x6989, + 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, + 0x0026, 0x2010, 0x080c, 0xcb48, 0x002e, 0x1120, 0x2001, 0x0008, + 0x0804, 0x621b, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, + 0x0804, 0x621b, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, + 0x080c, 0xae09, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, + 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xaeda, 0x9006, + 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, + 0xadc9, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, + 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, + 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, + 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, + 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, + 0x2001, 0x002c, 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, + 0xa8e0, 0x9005, 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, + 0x9005, 0x1518, 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, + 0x1800, 0x9182, 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, + 0xaa98, 0xab94, 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, + 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, + 0x00be, 0x00fe, 0x0005, 0x62b0, 0x626b, 0x6282, 0x62b0, 0x62b0, + 0x62b0, 0x62b0, 0x62b0, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, + 0x65b5, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x62b8, 0xb814, + 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x49d1, + 0x0150, 0x04b0, 0x080c, 0x6616, 0x1598, 0xb810, 0x9306, 0x1580, + 0xb814, 0x9206, 0x1568, 0x080c, 0xae09, 0x0530, 0x2b00, 0x6012, + 0x080c, 0xcfd4, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, + 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x31cc, 0x9006, 0x080c, + 0x6552, 0x2001, 0x0002, 0x080c, 0x6566, 0x2001, 0x0200, 0xb86e, + 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0xaeda, 0x9006, 0x0068, + 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, + 0x2001, 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, + 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, + 0x90c6, 0x0015, 0x0904, 0x64a3, 0x90c6, 0x0056, 0x0904, 0x64a7, + 0x90c6, 0x0066, 0x0904, 0x64ab, 0x90c6, 0x0067, 0x0904, 0x64af, + 0x90c6, 0x0068, 0x0904, 0x64b3, 0x90c6, 0x0071, 0x0904, 0x64b7, + 0x90c6, 0x0074, 0x0904, 0x64bb, 0x90c6, 0x007c, 0x0904, 0x64bf, + 0x90c6, 0x007e, 0x0904, 0x64c3, 0x90c6, 0x0037, 0x0904, 0x64c7, + 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x649e, + 0x9182, 0x0800, 0x1a04, 0x649e, 0x080c, 0x6616, 0x1198, 0xb804, + 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, + 0x0148, 0x080c, 0xadc9, 0x1904, 0x6487, 0xb8a0, 0x9084, 0xff80, + 0x1904, 0x6487, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, + 0x0904, 0x63e7, 0x90c6, 0x0064, 0x0904, 0x6410, 0x2008, 0x0804, + 0x63a9, 0xa998, 0xa8b0, 0x2040, 0x080c, 0xadc9, 0x1120, 0x9182, + 0x007f, 0x0a04, 0x63a9, 0x9186, 0x00ff, 0x0904, 0x63a9, 0x9182, + 0x0800, 0x1a04, 0x63a9, 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x11a8, + 0x7880, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, + 0x63a9, 0x080c, 0xadc9, 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, + 0x2208, 0x2310, 0x0804, 0x63a9, 0x009e, 0x080c, 0x49d1, 0x0904, + 0x63b3, 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, + 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, + 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, + 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f7c, 0x20a9, + 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c4, + 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f7c, 0xa8c4, + 0xabc8, 0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, 0xabd4, 0x9305, + 0xabd8, 0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, 0x9005, 0x0510, + 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, + 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, + 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, + 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, + 0x900e, 0x0478, 0x000e, 0x080c, 0xae09, 0x1130, 0x2001, 0x4005, + 0x2009, 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, 0x080c, 0xcfd4, + 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, + 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x31cc, 0x012e, 0x9006, + 0x080c, 0x6552, 0x2001, 0x0002, 0x080c, 0x6566, 0x2009, 0x0002, + 0x080c, 0xaeda, 0xa8b0, 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, + 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, + 0x56f6, 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, + 0x6616, 0x1904, 0x63a4, 0x9186, 0x007f, 0x0130, 0x080c, 0x6989, + 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x0fff, 0x1120, + 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, + 0xcd40, 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x63ab, + 0xa998, 0xaeb0, 0x080c, 0x6616, 0x1904, 0x63a4, 0x0096, 0x080c, + 0x0fff, 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x6464, 0x2900, + 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8c4, 0x20e0, + 0xb8c8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, + 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbc8, 0x9398, + 0x0006, 0x2398, 0x080c, 0x0f7c, 0x009e, 0xa87b, 0x0000, 0xa883, + 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x56e2, 0xd0b4, + 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, + 0x000c, 0x00b0, 0x080c, 0x6989, 0x0118, 0xa89b, 0x0009, 0x0080, + 0x080c, 0x56f6, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xcd23, + 0x1904, 0x63e0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x63ab, + 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, + 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1243, + 0x080c, 0xb379, 0x1904, 0x63e0, 0x2009, 0x0002, 0x08e8, 0x2001, + 0x0028, 0x900e, 0x0804, 0x63e1, 0x2009, 0x180c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x63e1, 0x2001, 0x0029, + 0x900e, 0x0804, 0x63e1, 0x080c, 0x3761, 0x0804, 0x63e2, 0x080c, + 0x541f, 0x0804, 0x63e2, 0x080c, 0x455f, 0x0804, 0x63e2, 0x080c, + 0x45d8, 0x0804, 0x63e2, 0x080c, 0x4634, 0x0804, 0x63e2, 0x080c, + 0x4a94, 0x0804, 0x63e2, 0x080c, 0x4d44, 0x0804, 0x63e2, 0x080c, + 0x508a, 0x0804, 0x63e2, 0x080c, 0x5283, 0x0804, 0x63e2, 0x080c, + 0x3977, 0x0804, 0x63e2, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1618, 0x9182, 0x0800, 0x1268, 0x9188, 0x1000, + 0x2104, 0x905d, 0x0140, 0x080c, 0x6989, 0x1148, 0x00e9, 0x080c, + 0x6741, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, + 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d88, 0x2001, 0x0029, 0x2009, + 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, + 0x900e, 0x9005, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0xb850, + 0x900d, 0x0150, 0x2900, 0x0096, 0x2148, 0xa802, 0x009e, 0xa803, + 0x0000, 0xb852, 0x012e, 0x0005, 0x2900, 0xb852, 0xb84e, 0xa803, + 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0xb84c, 0x9005, 0x0170, + 0x00e6, 0x2071, 0x19e6, 0x7004, 0x9086, 0x0002, 0x0168, 0x00ee, + 0xb84c, 0xa802, 0x2900, 0xb84e, 0x012e, 0x0005, 0x2900, 0xb852, + 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x701c, 0x9b06, 0x1d80, 0xb84c, + 0x00a6, 0x2050, 0xb000, 0xa802, 0x2900, 0xb002, 0x00ae, 0x00ee, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0xb84c, 0x904d, 0x0130, + 0xa800, 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, 0x012e, 0x0005, + 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, 0xb84e, + 0x9905, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, + 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, + 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, + 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, + 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, 0x6985, 0x0140, + 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, + 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, 0x9086, 0x0006, + 0x1120, 0xba90, 0x82ff, 0x090c, 0x0dd5, 0x000e, 0x00ce, 0x012e, + 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, + 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, 0xb89c, 0xd0a4, + 0x0150, 0x080c, 0x6981, 0x1138, 0x9284, 0x00ff, 0x9086, 0x0007, + 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, 0x9215, + 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, 0x0800, 0x0218, + 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, 0x1000, 0x2204, + 0x905d, 0x1188, 0x0096, 0x080c, 0x0fff, 0x2958, 0x009e, 0x0168, + 0x2b00, 0x2012, 0xb85c, 0xb8ca, 0xb860, 0xb8c6, 0x9006, 0xb8a6, + 0xb8ae, 0x080c, 0x6047, 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, + 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, 0x8000, 0x0026, + 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, + 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, 0xb8a4, 0x904d, + 0x0110, 0x080c, 0x1031, 0x00d6, 0x00c6, 0xb8bc, 0x2060, 0x8cff, + 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, 0xcb5a, 0x0110, + 0x080c, 0x0fb1, 0x080c, 0xae5f, 0x00ce, 0x0c88, 0x00ce, 0x00de, + 0x2b48, 0xb8c8, 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x1041, 0x00de, + 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, + 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, + 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, + 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, + 0x73b3, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xadc9, + 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1981, + 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, + 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, + 0x6886, 0x2069, 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, + 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, + 0xb8c8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, + 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, + 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, + 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, + 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, + 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, + 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, + 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, + 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, + 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, + 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, + 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbcc, 0xc384, 0xba00, + 0x2009, 0x1867, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, + 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, + 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbce, + 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, + 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, + 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, + 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, + 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, + 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0dd5, 0x3c00, 0x20e8, + 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, + 0x014e, 0x013e, 0x0060, 0x080c, 0x0fff, 0x0170, 0x2900, 0xb8a6, + 0xa803, 0x0000, 0x080c, 0x67d2, 0xa807, 0x0001, 0xae12, 0x9085, + 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, + 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, + 0x080c, 0x67e1, 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, + 0xa806, 0x0020, 0x080c, 0x1031, 0xb8a7, 0x0000, 0x009e, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x9115, 0x012e, 0x0005, + 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, + 0xb84c, 0x2048, 0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, 0x83ff, + 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, + 0xa870, 0x9506, 0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, 0x080c, + 0xa67d, 0xaa00, 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, + 0x2150, 0xb202, 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, + 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, + 0x6836, 0x0128, 0x080c, 0xcc17, 0x0010, 0x9085, 0x0001, 0x0005, + 0x080c, 0x6836, 0x0128, 0x080c, 0xcbbc, 0x0010, 0x9085, 0x0001, + 0x0005, 0x080c, 0x6836, 0x0128, 0x080c, 0xcc14, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x6836, 0x0128, 0x080c, 0xcbdb, 0x0010, + 0x9085, 0x0001, 0x0005, 0x080c, 0x6836, 0x0128, 0x080c, 0xcc58, + 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, + 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, + 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, + 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, + 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, + 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, + 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, + 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, + 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, + 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, + 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, + 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, + 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x0fff, 0x0168, 0x2900, + 0xb8a6, 0x080c, 0x67d2, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, + 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, + 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, + 0x1031, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, + 0x0005, 0x00b6, 0x00f6, 0x080c, 0x73b3, 0x01b0, 0x71c4, 0x81ff, + 0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, + 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, + 0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6616, + 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, + 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, + 0x1f04, 0x685d, 0x015e, 0x080c, 0x6947, 0x0120, 0x2001, 0x1984, + 0x200c, 0x0038, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0130, 0x2009, + 0x07d0, 0x2011, 0x6888, 0x080c, 0x8591, 0x00fe, 0x00be, 0x0005, + 0x00b6, 0x2011, 0x6888, 0x080c, 0x84f9, 0x080c, 0x6947, 0x01d8, + 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, + 0x6985, 0x0130, 0x2009, 0x07d0, 0x2011, 0x6888, 0x080c, 0x8591, + 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, 0x7082, 0x080c, + 0x2fa3, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x6616, 0x1538, 0xb800, 0xd0ec, 0x0520, 0x0046, + 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, 0xe5e9, 0xb800, + 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6981, 0x2001, 0x0707, 0x1128, + 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, 0x2019, 0x0029, + 0x080c, 0x929d, 0x0076, 0x903e, 0x080c, 0x9170, 0x900e, 0x080c, + 0xe326, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x68b0, 0x00ce, + 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, + 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, 0x1018, + 0x090c, 0x0dd5, 0x2958, 0x009e, 0x2001, 0x196a, 0x2b02, 0x8b07, + 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, 0xb9ca, + 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x6047, 0xb807, 0x0006, + 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, 0xb86c, 0xb893, + 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, 0x0000, 0x00ce, + 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, + 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, + 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, 0x00ff, 0x9196, + 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, + 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, + 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, + 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, + 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, + 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0dd5, 0x000e, + 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, + 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, 0x0138, 0x2001, + 0x1982, 0x200c, 0x2011, 0x6977, 0x080c, 0x8591, 0x0005, 0x2011, + 0x6977, 0x080c, 0x84f9, 0x2011, 0x1837, 0x2204, 0xc0cc, 0x2012, + 0x0005, 0x080c, 0x56e2, 0xd0ac, 0x0005, 0x080c, 0x56e2, 0xd0a4, + 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, + 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, + 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd25a, 0x0158, 0x70dc, + 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, + 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x2071, 0x1910, 0x7003, + 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, + 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1947, 0x900e, + 0x710a, 0x080c, 0x56e2, 0xd0fc, 0x1140, 0x080c, 0x56e2, 0x900e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x00f8, 0x2001, 0x1867, 0x200c, + 0x9184, 0x0007, 0x0002, 0x69c5, 0x69c5, 0x69c5, 0x69c5, 0x69c5, + 0x69db, 0x69e9, 0x69c5, 0x7003, 0x0003, 0x2009, 0x1868, 0x210c, + 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, + 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, 0x0005, 0x00e6, + 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, 0x1910, + 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, + 0x9005, 0x0158, 0x080c, 0x770b, 0x6a60, 0x9200, 0x7002, 0x6864, + 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, + 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, + 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, + 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, 0x7028, + 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, + 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1947, 0x7000, 0x9015, + 0x0904, 0x6c99, 0x9286, 0x0003, 0x0904, 0x6b2f, 0x9286, 0x0005, + 0x0904, 0x6b2f, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, 0x6a90, + 0x7140, 0xa868, 0x9102, 0x0a04, 0x6c99, 0xa878, 0xd084, 0x15d8, + 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, + 0x9005, 0x1904, 0x6e2f, 0x0e04, 0x6e9d, 0x2071, 0x0000, 0xa850, + 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, 0xa880, + 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, + 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, + 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, + 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x119b, 0x0804, 0x6b12, 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, + 0x7004, 0xd08c, 0x1904, 0x6c99, 0xa853, 0x001a, 0x2001, 0x8024, + 0x0804, 0x6a54, 0x00e6, 0x0026, 0x2071, 0x1947, 0x7000, 0x9015, + 0x0904, 0x6c99, 0x9286, 0x0003, 0x0904, 0x6b2f, 0x9286, 0x0005, + 0x0904, 0x6b2f, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, 0x6af7, + 0xa868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, 0x2001, 0x1947, 0x2004, + 0x9005, 0x0904, 0x6c99, 0xa87c, 0xd0bc, 0x1904, 0x6c99, 0xa978, + 0xa874, 0x9105, 0x1904, 0x6c99, 0x2001, 0x1947, 0x2004, 0x0002, + 0x6c99, 0x6af3, 0x6b2f, 0x6b2f, 0x6c99, 0x6b2f, 0x0005, 0xa868, + 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x1947, 0x210c, 0x81ff, + 0x0904, 0x6c99, 0xa87c, 0xd0cc, 0x0904, 0x6c99, 0xa880, 0x9084, + 0x00ff, 0x9086, 0x0001, 0x1904, 0x6c99, 0x9186, 0x0003, 0x0904, + 0x6b2f, 0x9186, 0x0005, 0x0904, 0x6b2f, 0xa84f, 0x8021, 0xa853, + 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, + 0x1910, 0x701c, 0x9005, 0x1904, 0x6e2f, 0x0e04, 0x6e9d, 0x2071, + 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, + 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x119b, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, + 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, + 0x080c, 0x841a, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, + 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, + 0x7010, 0x9005, 0x1904, 0x6c1e, 0x782c, 0x908c, 0x0780, 0x190c, + 0x6fe9, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6b4d, + 0x6c1e, 0x6b72, 0x6bb9, 0x080c, 0x0dd5, 0x2071, 0x1800, 0x2900, + 0x7822, 0xa804, 0x900d, 0x1170, 0x2071, 0x19f9, 0x703c, 0x9005, + 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, + 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, + 0x841a, 0x0c10, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, + 0x1580, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, + 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, + 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, + 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6fe9, 0xd0a4, 0x19f0, 0x2071, 0x19f9, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x841a, + 0x0800, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x1d60, 0x00ee, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd09c, 0x11a0, 0x009e, + 0x2900, 0x7822, 0xa804, 0x900d, 0x1560, 0x2071, 0x19f9, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, + 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, + 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, + 0xa804, 0x900d, 0x1170, 0x2071, 0x19f9, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, - 0x080c, 0x83fd, 0x0800, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, - 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd09c, - 0x11a0, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1560, 0x2071, - 0x19f9, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, - 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, + 0x080c, 0x841a, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, - 0x711e, 0x2148, 0xa804, 0x900d, 0x1170, 0x2071, 0x19f9, 0x703c, + 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6c73, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6fe9, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, + 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, + 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd09c, 0x0d68, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x01b0, 0x00e6, + 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, + 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6fe9, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x19f9, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x83fd, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6c65, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd09c, 0x1198, 0x701c, - 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, - 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, - 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, - 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x83fd, 0x782c, - 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x1d60, 0x00ee, 0x2071, - 0x19f9, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, - 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x83fd, 0x00ee, - 0x0804, 0x6c20, 0xa868, 0xd0fc, 0x1560, 0x0096, 0xa804, 0xa807, - 0x0000, 0x904d, 0x190c, 0x0fb1, 0x009e, 0x0018, 0xa868, 0xd0fc, - 0x1500, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, - 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x6d9f, - 0x782c, 0x908c, 0x0780, 0x190c, 0x6fdb, 0x8004, 0x8004, 0x8004, - 0x9084, 0x0003, 0x0002, 0x6caa, 0x6d9f, 0x6cc5, 0x6d32, 0x080c, - 0x0dd5, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x83fd, 0x0c60, 0x2071, 0x1800, 0x2900, - 0x7822, 0xa804, 0x900d, 0x1904, 0x6d21, 0x7830, 0x8007, 0x9084, - 0x001f, 0x9082, 0x0001, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, - 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, - 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, - 0x70c2, 0x080c, 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, - 0xd0a4, 0x19f0, 0x0e04, 0x6d18, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, - 0x1921, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x119b, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x83fd, - 0x0804, 0x6cd8, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x6d72, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, - 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x119b, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd09c, 0x1170, - 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x83fd, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6e0c, 0x782c, - 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd09c, 0x11b0, 0x701c, 0x904d, - 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, - 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6fdb, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6fdb, 0xd0a4, 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, + 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, + 0x70c0, 0x9200, 0x70c2, 0x080c, 0x841a, 0x00ee, 0x0804, 0x6c2e, + 0xa868, 0xd0fc, 0x1560, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, + 0x190c, 0x0fb1, 0x009e, 0x0018, 0xa868, 0xd0fc, 0x1500, 0x00e6, + 0x0026, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, + 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x6dad, 0x782c, 0x908c, + 0x0780, 0x190c, 0x6fe9, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, + 0x0002, 0x6cb8, 0x6dad, 0x6cd3, 0x6d40, 0x080c, 0x0dd5, 0x0005, + 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, + 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, + 0x080c, 0x841a, 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, + 0x900d, 0x1904, 0x6d2f, 0x7830, 0x8007, 0x9084, 0x001f, 0x9082, + 0x0001, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830, 0x210c, + 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x6e05, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, - 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x119b, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, + 0x841a, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x19f0, + 0x0e04, 0x6d26, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, + 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, + 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x119b, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1921, + 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x83fd, 0x00ee, 0x0804, - 0x6daf, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, + 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x841a, 0x0804, 0x6ce6, + 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, + 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, + 0x6d80, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, + 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd09c, 0x1170, 0x009e, 0x2900, + 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x6e4c, 0x002e, 0x00ee, - 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, - 0x080c, 0x83fd, 0x0e04, 0x6e36, 0x2071, 0x1910, 0x701c, 0x2048, - 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, - 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, - 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x119b, 0x2071, 0x1910, 0x080c, 0x6fc7, 0x002e, 0x00ee, 0x0005, - 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, - 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, - 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, - 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2071, + 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, + 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, + 0x841a, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, + 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, + 0x2148, 0xa804, 0x900d, 0x1904, 0x6e1a, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6fe9, 0xd09c, 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, + 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, + 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, + 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, + 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, + 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, + 0x6e13, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, + 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, + 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, + 0x9200, 0x70c2, 0x080c, 0x841a, 0x00ee, 0x0804, 0x6dbd, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x83fd, 0x002e, 0x00ee, - 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, - 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, - 0x2071, 0x1910, 0x7004, 0x0002, 0x6eda, 0x6edb, 0x6fc6, 0x6edb, - 0x0dd5, 0x6fc6, 0x0005, 0x2001, 0x1947, 0x2004, 0x0002, 0x6ee5, - 0x6ee5, 0x6f5f, 0x6f60, 0x6ee5, 0x6f60, 0x0126, 0x2091, 0x8000, - 0x1e0c, 0x6fe6, 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, - 0x6f30, 0x0e04, 0x6f0e, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, - 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, - 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x119b, 0x2071, 0x1910, 0x080c, 0x6fc7, 0x012e, 0x0804, - 0x6f5e, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, - 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, - 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, - 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, - 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd09c, - 0x2071, 0x1910, 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, - 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, - 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, - 0x00de, 0x2071, 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, - 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, - 0x00d6, 0x2008, 0x2069, 0x19f9, 0x683c, 0x9005, 0x0760, 0x0158, - 0x9186, 0x0003, 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1ac7, - 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, - 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x6f92, 0x2069, 0x0000, - 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x2069, 0x19f9, - 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, - 0x7047, 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, - 0x0780, 0x15c9, 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, - 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, - 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, - 0x6822, 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, - 0x2091, 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, - 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1031, - 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x6fdd, 0x0006, - 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0dde, 0x0096, 0x00f6, - 0x2079, 0x0050, 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, 0x7838, - 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x119b, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, - 0x1991, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, - 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830, 0x210c, - 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x19f0, - 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, - 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x119b, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x00f6, - 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, - 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x119b, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6fdb, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x83fd, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fdb, 0xd0a4, 0x1d70, - 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1947, 0x6808, 0x690a, - 0x2069, 0x19f9, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, - 0x1948, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x7098, 0x908a, 0x0029, 0x1a0c, 0x0dd5, 0x9082, 0x001d, 0x001b, - 0x6027, 0x1e00, 0x0005, 0x716f, 0x70f5, 0x7111, 0x713b, 0x715e, - 0x719e, 0x71b0, 0x7111, 0x7186, 0x70b0, 0x70de, 0x70af, 0x0005, - 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, - 0x1518, 0x709b, 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, 0x080c, - 0x74df, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0028, - 0x2069, 0x198e, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, - 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a61, 0x080c, 0x1aab, - 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, - 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, 0x080c, 0x757a, 0x6028, - 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, - 0x080c, 0x2cf1, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x721d, - 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, - 0x080c, 0x721d, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, - 0x0005, 0x2001, 0x0088, 0x080c, 0x2cf1, 0x6124, 0xd1cc, 0x11e8, - 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, - 0x1ad5, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x73d1, - 0x2001, 0x0080, 0x080c, 0x2cf1, 0x709b, 0x0028, 0x0058, 0x709b, - 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, - 0x709b, 0x001f, 0x0005, 0x080c, 0x1ad5, 0x60e3, 0x0001, 0x600c, - 0xc0b4, 0x600e, 0x080c, 0x73d1, 0x2001, 0x0080, 0x080c, 0x2cf1, - 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, - 0x1e00, 0x1158, 0x709b, 0x0028, 0x0040, 0x709b, 0x001e, 0x0028, - 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, - 0x080c, 0x2cf1, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, - 0x1ad5, 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, - 0x72a0, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x721d, 0x0016, 0x080c, - 0x1ad5, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, - 0x0020, 0x709b, 0x001f, 0x080c, 0x721d, 0x0005, 0x0006, 0x2001, - 0x00a0, 0x080c, 0x2cf1, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, + 0x900d, 0x1128, 0x1e04, 0x6e5a, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x841a, + 0x0e04, 0x6e44, 0x2071, 0x1910, 0x701c, 0x2048, 0xa84c, 0x900d, + 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, + 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, 0x2071, + 0x1910, 0x080c, 0x6fd5, 0x002e, 0x00ee, 0x0005, 0xa850, 0x9082, + 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, + 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, + 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, + 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2071, 0x1910, 0xa803, + 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, + 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, + 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, + 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, + 0x9200, 0x70c2, 0x080c, 0x841a, 0x002e, 0x00ee, 0x0005, 0x0006, + 0xa87c, 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, + 0x00ff, 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1910, + 0x7004, 0x0002, 0x6ee8, 0x6ee9, 0x6fd4, 0x6ee9, 0x0dd5, 0x6fd4, + 0x0005, 0x2001, 0x1947, 0x2004, 0x0002, 0x6ef3, 0x6ef3, 0x6f6d, + 0x6f6e, 0x6ef3, 0x6f6e, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6ff4, + 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x6f3e, 0x0e04, + 0x6f1c, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, + 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, + 0x2071, 0x1910, 0x080c, 0x6fd5, 0x012e, 0x0804, 0x6f6c, 0xa850, + 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, + 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, + 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, + 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, 0x005b, + 0x2004, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd09c, 0x2071, 0x1910, + 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, + 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, + 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, + 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, + 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, + 0x2069, 0x19f9, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, + 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1ac7, 0x210c, 0x9102, + 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, + 0x9106, 0x0190, 0x0e04, 0x6fa0, 0x2069, 0x0000, 0x6837, 0x8040, + 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x119b, 0x2069, 0x19f9, 0x683f, 0xffff, + 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x7055, 0x701c, + 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, + 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, + 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, + 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, + 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, + 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, + 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, + 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1031, 0x0005, 0x012e, + 0x0005, 0x2091, 0x8000, 0x0e04, 0x6feb, 0x0006, 0x0016, 0x2001, + 0x8004, 0x0006, 0x0804, 0x0dde, 0x0096, 0x00f6, 0x2079, 0x0050, + 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, + 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, 0x1991, 0xd0a4, + 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, + 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, + 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, + 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x19f0, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x119b, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, + 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x119b, + 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, + 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, + 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x841a, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6fe9, 0xd0a4, 0x1d70, 0x00d6, 0x2069, + 0x0050, 0x693c, 0x2069, 0x1947, 0x6808, 0x690a, 0x2069, 0x19f9, + 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, 0x1948, 0x200c, + 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, + 0x0029, 0x1a0c, 0x0dd5, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, + 0x0005, 0x717d, 0x7103, 0x711f, 0x7149, 0x716c, 0x71ac, 0x71be, + 0x711f, 0x7194, 0x70be, 0x70ec, 0x70bd, 0x0005, 0x00d6, 0x2069, + 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x709b, + 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, 0x080c, 0x74eb, 0x6028, + 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0028, 0x2069, 0x198e, + 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, + 0x0046, 0x0056, 0x2071, 0x1a61, 0x080c, 0x1abb, 0x005e, 0x004e, + 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, + 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, 0x0028, 0x2069, + 0x198e, 0x2d04, 0x7002, 0x080c, 0x7586, 0x6028, 0x9085, 0x0600, + 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2cfc, + 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x722b, 0xd1d4, 0x1160, + 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, 0x080c, 0x722b, + 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, + 0x0088, 0x080c, 0x2cfc, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, + 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1ae0, 0x60e3, + 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x73df, 0x2001, 0x0080, + 0x080c, 0x2cfc, 0x709b, 0x0028, 0x0058, 0x709b, 0x001e, 0x0040, + 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, + 0x0005, 0x080c, 0x1ae0, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, + 0x080c, 0x73df, 0x2001, 0x0080, 0x080c, 0x2cfc, 0x6124, 0xd1d4, + 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, + 0x709b, 0x0028, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, + 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, 0x2cfc, + 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1ae0, 0x709b, + 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, 0x72ae, 0x6124, + 0xd1dc, 0x1188, 0x080c, 0x722b, 0x0016, 0x080c, 0x1ae0, 0x001e, + 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, 0x0020, 0x709b, + 0x001f, 0x080c, 0x722b, 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, + 0x2cfc, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, + 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, + 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x72ae, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, - 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x72a0, - 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, - 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, - 0x0006, 0x2001, 0x0090, 0x080c, 0x2cf1, 0x000e, 0x6124, 0xd1d4, - 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, - 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, - 0x709b, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, - 0x080c, 0x73a5, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, - 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2c3a, 0x6024, 0xd0cc, - 0x0148, 0x2001, 0x00a0, 0x080c, 0x2cf1, 0x080c, 0x768d, 0x080c, - 0x6023, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x73bf, - 0x0150, 0x080c, 0x73b6, 0x1138, 0x2001, 0x0001, 0x080c, 0x27ec, - 0x080c, 0x737d, 0x00a0, 0x080c, 0x729d, 0x0178, 0x2001, 0x0001, - 0x080c, 0x27ec, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, - 0x0022, 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, - 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x722e, - 0x080c, 0x85b6, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, - 0x722e, 0x080c, 0x85ad, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, - 0x0016, 0x080c, 0xa274, 0x2071, 0x1800, 0x080c, 0x71cb, 0x001e, - 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x0126, 0x080c, 0xa274, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, - 0x2011, 0x0003, 0x080c, 0xa654, 0x2011, 0x0002, 0x080c, 0xa65e, - 0x080c, 0xa541, 0x080c, 0x8562, 0x0036, 0x901e, 0x080c, 0xa5b7, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xea0a, 0x080c, 0xea25, 0x2009, - 0x0004, 0x080c, 0x2c40, 0x080c, 0x2b5b, 0x2001, 0x1800, 0x2003, - 0x0004, 0x6027, 0x0008, 0x2011, 0x722e, 0x080c, 0x85b6, 0x080c, - 0x73bf, 0x0118, 0x9006, 0x080c, 0x2cf1, 0x080c, 0x0bae, 0x2001, - 0x0001, 0x080c, 0x27ec, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x723b, - 0x2071, 0x19f9, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, - 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, - 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x0170, 0x2001, 0x00c0, - 0x080c, 0x2cf1, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x72ad, 0x2091, - 0x6000, 0x1f04, 0x72ad, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x769c, - 0x2001, 0x196c, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, - 0x080c, 0x28b4, 0x9006, 0x080c, 0x2cf1, 0x080c, 0x5ee2, 0x6027, - 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, + 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x0006, 0x2001, + 0x0090, 0x080c, 0x2cfc, 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, 0x001e, 0x0040, + 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, + 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c, 0x73b3, + 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4, 0x2102, + 0x6027, 0x0200, 0x080c, 0x2c45, 0x6024, 0xd0cc, 0x0148, 0x2001, + 0x00a0, 0x080c, 0x2cfc, 0x080c, 0x7699, 0x080c, 0x602d, 0x0428, + 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x73cd, 0x0150, 0x080c, + 0x73c4, 0x1138, 0x2001, 0x0001, 0x080c, 0x27f7, 0x080c, 0x738b, + 0x00a0, 0x080c, 0x72ab, 0x0178, 0x2001, 0x0001, 0x080c, 0x27f7, + 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, 0x1118, + 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x723c, 0x080c, 0x85d3, + 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x723c, 0x080c, + 0x85ca, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, + 0xa28f, 0x2071, 0x1800, 0x080c, 0x71d9, 0x001e, 0x00fe, 0x00ee, + 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x0126, 0x080c, 0xa28f, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, + 0x080c, 0xa63e, 0x2011, 0x0002, 0x080c, 0xa648, 0x080c, 0xa552, + 0x080c, 0x857f, 0x0036, 0x901e, 0x080c, 0xa5c8, 0x003e, 0x60e3, + 0x0000, 0x080c, 0xea24, 0x080c, 0xea3f, 0x2009, 0x0004, 0x080c, + 0x2c4b, 0x080c, 0x2b66, 0x2001, 0x1800, 0x2003, 0x0004, 0x6027, + 0x0008, 0x2011, 0x723c, 0x080c, 0x85d3, 0x080c, 0x73cd, 0x0118, + 0x9006, 0x080c, 0x2cfc, 0x080c, 0x0bae, 0x2001, 0x0001, 0x080c, + 0x27f7, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x7249, 0x2071, 0x19f9, + 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, + 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, + 0xfffe, 0x9086, 0x00c0, 0x0170, 0x2001, 0x00c0, 0x080c, 0x2cfc, + 0x0156, 0x20a9, 0x002d, 0x1d04, 0x72bb, 0x2091, 0x6000, 0x1f04, + 0x72bb, 0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x76a8, 0x2001, 0x196c, + 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28bf, + 0x9006, 0x080c, 0x2cfc, 0x080c, 0x5eec, 0x6027, 0xffff, 0x602b, + 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197c, + 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, + 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x737b, 0x709b, + 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, + 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, + 0x080c, 0x28bf, 0x0026, 0x080c, 0xadd0, 0x002e, 0x7000, 0x908e, + 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, + 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, + 0x012e, 0x015e, 0x080c, 0xd25a, 0x0118, 0x9006, 0x080c, 0x2d26, + 0x0804, 0x7387, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, + 0x2c45, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2cfc, + 0x1f04, 0x7325, 0x080c, 0x740a, 0x012e, 0x015e, 0x080c, 0x73c4, + 0x01a8, 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, + 0x6052, 0x080c, 0x740a, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, + 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x740a, 0x080c, 0xd25a, + 0x0118, 0x9006, 0x080c, 0x2d26, 0x0016, 0x0026, 0x7000, 0x908e, + 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x7249, 0x080c, 0x8591, + 0x002e, 0x001e, 0x080c, 0x8411, 0x7034, 0xc085, 0x7036, 0x2001, + 0x197c, 0x2003, 0x0004, 0x080c, 0x70a6, 0x080c, 0x73c4, 0x0138, + 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x769e, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x8428, 0x080c, 0x841a, + 0x080c, 0x76a8, 0x2001, 0x196c, 0x2003, 0x0000, 0x9006, 0x709a, + 0x60e2, 0x6886, 0x080c, 0x28bf, 0x9006, 0x080c, 0x2cfc, 0x6043, + 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x197b, 0x2004, 0x9086, + 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, 0x56e6, 0x9084, 0x0030, + 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x56e6, 0x9084, + 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x56e6, + 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, + 0x56e6, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, + 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, 0x0180, 0x0020, + 0x080c, 0x28df, 0x900e, 0x0028, 0x080c, 0x6981, 0x1dc8, 0x2009, + 0x0002, 0x2019, 0x0028, 0x080c, 0x3197, 0x9006, 0x0019, 0x001e, + 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, + 0xd253, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, + 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, + 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, + 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, + 0x741f, 0x2091, 0x6000, 0x1f04, 0x741f, 0x602f, 0x0100, 0x602f, + 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, + 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, + 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, + 0x0001, 0x2001, 0x0001, 0x080c, 0x28bf, 0x2001, 0x00a0, 0x0006, + 0x080c, 0xd25a, 0x000e, 0x0130, 0x080c, 0x2d1a, 0x9006, 0x080c, + 0x2d26, 0x0010, 0x080c, 0x2cfc, 0x000e, 0x6052, 0x6050, 0x0006, + 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2bba, 0x00fe, + 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x2001, 0x197c, 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, - 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, - 0x736d, 0x709b, 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, - 0x0023, 0x0010, 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, - 0x2001, 0x0001, 0x080c, 0x28b4, 0x0026, 0x080c, 0xade2, 0x002e, - 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, - 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, - 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, 0xd24a, 0x0118, 0x9006, - 0x080c, 0x2d1b, 0x0804, 0x7379, 0x6800, 0x9084, 0x00a1, 0xc0bd, - 0x6802, 0x080c, 0x2c3a, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, - 0x080c, 0x2cf1, 0x1f04, 0x7317, 0x080c, 0x73fc, 0x012e, 0x015e, - 0x080c, 0x73b6, 0x01a8, 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, - 0x9085, 0x0020, 0x6052, 0x080c, 0x73fc, 0x9006, 0x8001, 0x1df0, - 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x73fc, - 0x080c, 0xd24a, 0x0118, 0x9006, 0x080c, 0x2d1b, 0x0016, 0x0026, - 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x723b, - 0x080c, 0x8574, 0x002e, 0x001e, 0x080c, 0x83f4, 0x7034, 0xc085, - 0x7036, 0x2001, 0x197c, 0x2003, 0x0004, 0x080c, 0x7098, 0x080c, - 0x73b6, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, - 0x7692, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x840b, - 0x080c, 0x83fd, 0x080c, 0x769c, 0x2001, 0x196c, 0x2003, 0x0000, - 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28b4, 0x9006, 0x080c, - 0x2cf1, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, - 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x197b, - 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, 0x56dc, - 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, - 0x56dc, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, - 0x080c, 0x56dc, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, - 0x0006, 0x080c, 0x56dc, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, - 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, - 0x0180, 0x0020, 0x080c, 0x28d4, 0x900e, 0x0028, 0x080c, 0x6973, - 0x1dc8, 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x318c, 0x9006, - 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, - 0x0130, 0x080c, 0xd243, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, - 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, - 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, - 0x6050, 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, - 0x0012, 0x1d04, 0x7411, 0x2091, 0x6000, 0x1f04, 0x7411, 0x602f, - 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, - 0x6052, 0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, - 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, - 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28b4, 0x2001, - 0x00a0, 0x0006, 0x080c, 0xd24a, 0x000e, 0x0130, 0x080c, 0x2d0f, - 0x9006, 0x080c, 0x2d1b, 0x0010, 0x080c, 0x2cf1, 0x000e, 0x6052, - 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, - 0x2baf, 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, - 0x200c, 0xc1c5, 0x2102, 0x0804, 0x74d1, 0x2001, 0x180c, 0x200c, - 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, - 0x2001, 0x0090, 0x080c, 0x2cf1, 0x20a9, 0x0366, 0x6024, 0xd0cc, - 0x1518, 0x1d04, 0x747e, 0x2091, 0x6000, 0x1f04, 0x747e, 0x2011, - 0x0003, 0x080c, 0xa654, 0x2011, 0x0002, 0x080c, 0xa65e, 0x080c, - 0xa541, 0x901e, 0x080c, 0xa5b7, 0x2001, 0x00a0, 0x080c, 0x2cf1, - 0x080c, 0x768d, 0x080c, 0x6023, 0x080c, 0xd24a, 0x0110, 0x080c, - 0x0d45, 0x9085, 0x0001, 0x0498, 0x86ff, 0x1110, 0x080c, 0x1ad5, - 0x60e3, 0x0000, 0x2001, 0x196c, 0x2004, 0x080c, 0x28b4, 0x60e2, - 0x2001, 0x0080, 0x080c, 0x2cf1, 0x20a9, 0x0366, 0x6027, 0x1e00, - 0x2009, 0x1e00, 0x080c, 0x2c3a, 0x6024, 0x910c, 0x0138, 0x1d04, - 0x74b6, 0x2091, 0x6000, 0x1f04, 0x74b6, 0x0808, 0x6028, 0x9085, - 0x1e00, 0x602a, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x080c, 0xd24a, 0x0110, 0x080c, 0x0d45, 0x9006, 0x00ee, - 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7000, 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, - 0x2004, 0x9084, 0x5540, 0x9086, 0x5540, 0x1128, 0x2069, 0x1a78, - 0x2d04, 0x8000, 0x206a, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, - 0x0120, 0x6884, 0x9005, 0x1904, 0x7544, 0x2001, 0x0088, 0x080c, - 0x2cf1, 0x9006, 0x60e2, 0x6886, 0x080c, 0x28b4, 0x2069, 0x0200, - 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, - 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0x198e, 0x7000, 0x206a, - 0x709b, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7526, - 0x2091, 0x6000, 0x1f04, 0x7526, 0x0804, 0x7572, 0x2069, 0x0140, - 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c3a, - 0x6024, 0x910c, 0x0508, 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x7532, - 0x2091, 0x6000, 0x1f04, 0x7532, 0x2011, 0x0003, 0x080c, 0xa654, - 0x2011, 0x0002, 0x080c, 0xa65e, 0x080c, 0xa541, 0x901e, 0x080c, - 0xa5b7, 0x2001, 0x00a0, 0x080c, 0x2cf1, 0x080c, 0x768d, 0x080c, - 0x6023, 0x9085, 0x0001, 0x00b0, 0x2001, 0x0080, 0x080c, 0x2cf1, - 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, - 0x0001, 0x0008, 0x6886, 0x2001, 0x196c, 0x2004, 0x080c, 0x28b4, - 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, - 0x01c8, 0x2011, 0x0003, 0x080c, 0xa654, 0x2011, 0x0002, 0x080c, - 0xa65e, 0x080c, 0xa541, 0x901e, 0x080c, 0xa5b7, 0x2069, 0x0140, - 0x2001, 0x00a0, 0x080c, 0x2cf1, 0x080c, 0x768d, 0x080c, 0x6023, - 0x0804, 0x760d, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, - 0x2102, 0x080c, 0x7223, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, - 0x2cf1, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, - 0x0200, 0x2069, 0x198e, 0x7000, 0x206a, 0x709b, 0x0027, 0x7003, - 0x0001, 0x0804, 0x760d, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, - 0x2c3a, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, - 0x75cb, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x843c, - 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19f9, - 0x7018, 0x00ee, 0x9005, 0x19f8, 0x0500, 0x0026, 0x2011, 0x723b, - 0x080c, 0x84dc, 0x2011, 0x722e, 0x080c, 0x85b6, 0x002e, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0x196c, 0x2004, 0x080c, 0x28b4, 0x60e2, - 0x2001, 0x180c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, - 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, - 0x080c, 0xd243, 0x1904, 0x767b, 0x7130, 0xd184, 0x1170, 0x080c, - 0x331b, 0x0138, 0xc18d, 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, - 0x1120, 0x7030, 0xd08c, 0x0904, 0x767b, 0x2011, 0x1848, 0x220c, - 0xd1a4, 0x0538, 0x0016, 0x2019, 0x000e, 0x080c, 0xe543, 0x0156, - 0x00b6, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, - 0x0080, 0x0188, 0x080c, 0x6608, 0x1170, 0x2120, 0x9006, 0x0016, - 0x2009, 0x000e, 0x080c, 0xe5cf, 0x2009, 0x0001, 0x2011, 0x0100, - 0x080c, 0x86c6, 0x001e, 0x8108, 0x1f04, 0x7644, 0x00be, 0x015e, - 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, - 0x080c, 0x318c, 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x080c, 0x6608, 0x1110, 0x080c, 0x603d, 0x8108, 0x1f04, - 0x7671, 0x00be, 0x015e, 0x080c, 0x1ad5, 0x080c, 0xade2, 0x60e3, - 0x0000, 0x080c, 0x6023, 0x080c, 0x72d7, 0x00ee, 0x00ce, 0x004e, - 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197c, 0x2003, - 0x0001, 0x0005, 0x2001, 0x197c, 0x2003, 0x0000, 0x0005, 0x2001, - 0x197b, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197b, 0x2003, 0x0000, - 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, - 0x1018, 0x090c, 0x0dd5, 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, - 0x1018, 0x090c, 0x0dd5, 0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, - 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, - 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, - 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, - 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, - 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, - 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18fa, 0x6807, - 0x0001, 0x00de, 0x080c, 0x7c79, 0x9006, 0x00ee, 0x0005, 0x900e, - 0x0156, 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, - 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x7703, - 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, - 0x7722, 0x7723, 0x775a, 0x77b5, 0x78c5, 0x7720, 0x7720, 0x78ef, - 0x080c, 0x0dd5, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, - 0x190c, 0x7d5b, 0xd0a4, 0x01f0, 0x7824, 0x2048, 0x9006, 0xa802, - 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x0608, 0x00b8, - 0x2001, 0x1800, 0x200c, 0x9186, 0x0003, 0x1160, 0x7104, 0x9186, - 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, 0x0003, 0x19e8, - 0x080c, 0x77b5, 0x782c, 0xd09c, 0x090c, 0x7c79, 0x0005, 0x9082, - 0x005a, 0x1218, 0x2100, 0x003b, 0x0c18, 0x080c, 0x77eb, 0x0c90, - 0x00e3, 0x08f0, 0x0005, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x780d, 0x77eb, 0x77eb, 0x77eb, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77f7, - 0x77eb, 0x79e0, 0x77eb, 0x77eb, 0x77eb, 0x780d, 0x77eb, 0x77f7, - 0x7a21, 0x7a62, 0x7aa9, 0x7abd, 0x77eb, 0x77eb, 0x780d, 0x77f7, - 0x7821, 0x77eb, 0x7899, 0x7b68, 0x7b83, 0x77eb, 0x780d, 0x77eb, - 0x7821, 0x77eb, 0x77eb, 0x788f, 0x7b83, 0x77eb, 0x77eb, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x7835, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, - 0x7cff, 0x77eb, 0x7ca9, 0x77eb, 0x7ca9, 0x77eb, 0x784a, 0x77eb, - 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x77eb, 0x2079, 0x0040, 0x7004, - 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x7ca2, 0xd0a4, 0x0170, + 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c, 0xc1c5, + 0x2102, 0x0804, 0x74dd, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, + 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, + 0x080c, 0x2cfc, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, 0x1d04, + 0x748c, 0x2091, 0x6000, 0x1f04, 0x748c, 0x2011, 0x0003, 0x080c, + 0xa63e, 0x2011, 0x0002, 0x080c, 0xa648, 0x080c, 0xa552, 0x901e, + 0x080c, 0xa5c8, 0x2001, 0x00a0, 0x080c, 0x2cfc, 0x080c, 0x7699, + 0x080c, 0x602d, 0x080c, 0xd25a, 0x0110, 0x080c, 0x0d45, 0x9085, + 0x0001, 0x0488, 0x080c, 0x1ae0, 0x60e3, 0x0000, 0x2001, 0x196c, + 0x2004, 0x080c, 0x28bf, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2cfc, + 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c45, + 0x6024, 0x910c, 0x0138, 0x1d04, 0x74c2, 0x2091, 0x6000, 0x1f04, + 0x74c2, 0x0818, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd25a, 0x0110, + 0x080c, 0x0d45, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, 0x9086, + 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, 0x9086, + 0x5540, 0x1128, 0x2069, 0x1a78, 0x2d04, 0x8000, 0x206a, 0x2069, + 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, + 0x7550, 0x2001, 0x0088, 0x080c, 0x2cfc, 0x9006, 0x60e2, 0x6886, + 0x080c, 0x28bf, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, + 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, + 0x2069, 0x198e, 0x7000, 0x206a, 0x709b, 0x0026, 0x7003, 0x0001, + 0x20a9, 0x0002, 0x1d04, 0x7532, 0x2091, 0x6000, 0x1f04, 0x7532, + 0x0804, 0x757e, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, + 0x2009, 0x1e00, 0x080c, 0x2c45, 0x6024, 0x910c, 0x0508, 0x9084, + 0x1a00, 0x11f0, 0x1d04, 0x753e, 0x2091, 0x6000, 0x1f04, 0x753e, + 0x2011, 0x0003, 0x080c, 0xa63e, 0x2011, 0x0002, 0x080c, 0xa648, + 0x080c, 0xa552, 0x901e, 0x080c, 0xa5c8, 0x2001, 0x00a0, 0x080c, + 0x2cfc, 0x080c, 0x7699, 0x080c, 0x602d, 0x9085, 0x0001, 0x00b0, + 0x2001, 0x0080, 0x080c, 0x2cfc, 0x2069, 0x0140, 0x60e3, 0x0000, + 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, + 0x196c, 0x2004, 0x080c, 0x28bf, 0x60e2, 0x9006, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x1800, 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, + 0xa63e, 0x2011, 0x0002, 0x080c, 0xa648, 0x080c, 0xa552, 0x901e, + 0x080c, 0xa5c8, 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2cfc, + 0x080c, 0x7699, 0x080c, 0x602d, 0x0804, 0x7619, 0x2001, 0x180c, + 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, 0x7231, 0x2069, + 0x0140, 0x2001, 0x0080, 0x080c, 0x2cfc, 0x60e3, 0x0000, 0x2069, + 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, + 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0x198e, 0x7000, + 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x7619, 0x6027, + 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c45, 0x6024, 0x910c, 0x01c8, + 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x75d7, 0x0006, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x080c, 0x8459, 0x00ee, 0x00de, 0x00ce, 0x001e, + 0x000e, 0x00e6, 0x2071, 0x19f9, 0x7070, 0x00ee, 0x9005, 0x19f8, + 0x0400, 0x0026, 0x2011, 0x7249, 0x080c, 0x84f9, 0x2011, 0x723c, + 0x080c, 0x85d3, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, + 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x196c, + 0x2004, 0x080c, 0x28bf, 0x60e2, 0x2001, 0x180c, 0x200c, 0xc1b4, + 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd253, 0x1904, 0x7687, + 0x7130, 0xd184, 0x1170, 0x080c, 0x3326, 0x0138, 0xc18d, 0x7132, + 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, + 0x7687, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, 0x2019, + 0x000e, 0x080c, 0xe55d, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, + 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, 0x6616, + 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, 0xe5e9, + 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x86e3, 0x001e, 0x8108, + 0x1f04, 0x7650, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, + 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x3197, 0x001e, 0x0078, + 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6616, 0x1110, + 0x080c, 0x6047, 0x8108, 0x1f04, 0x767d, 0x00be, 0x015e, 0x080c, + 0x1ae0, 0x080c, 0xadd0, 0x60e3, 0x0000, 0x080c, 0x602d, 0x080c, + 0x72e5, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x2001, 0x197c, 0x2003, 0x0001, 0x0005, 0x2001, 0x197c, + 0x2003, 0x0000, 0x0005, 0x2001, 0x197b, 0x2003, 0xaaaa, 0x0005, + 0x2001, 0x197b, 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, + 0x0000, 0x7007, 0x0000, 0x080c, 0x1018, 0x090c, 0x0dd5, 0xa8ab, + 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1018, 0x090c, 0x0dd5, 0xa8ab, + 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, + 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, + 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, + 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, + 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, + 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, + 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, + 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, + 0x00d6, 0x2069, 0x18fa, 0x6807, 0x0001, 0x00de, 0x080c, 0x7c86, + 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, + 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, 0x0010, + 0x81f5, 0x3e08, 0x1f04, 0x770f, 0x015e, 0x0005, 0x2079, 0x0040, + 0x2071, 0x18fa, 0x7004, 0x0002, 0x772e, 0x772f, 0x7767, 0x77c2, + 0x78d2, 0x772c, 0x772c, 0x78fc, 0x080c, 0x0dd5, 0x0005, 0x2079, + 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x7d68, 0xd0a4, 0x01f8, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, - 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7c79, - 0x0005, 0x77eb, 0x77f7, 0x79cc, 0x77eb, 0x77f7, 0x77eb, 0x77f7, - 0x77f7, 0x77eb, 0x77f7, 0x79cc, 0x77f7, 0x77f7, 0x77f7, 0x77f7, - 0x77f7, 0x77eb, 0x77f7, 0x79cc, 0x77eb, 0x77eb, 0x77f7, 0x77eb, - 0x77eb, 0x77eb, 0x77f7, 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, - 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, - 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, - 0x0001, 0xa868, 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6c86, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x796e, - 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x796e, - 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, - 0x7007, 0x0001, 0x0804, 0x7989, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x7989, 0x0005, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0904, 0x77f3, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x79a5, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, - 0x79a5, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, - 0x1904, 0x77f3, 0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, - 0x11a8, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, - 0x62b7, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, - 0xa87a, 0xa982, 0x080c, 0x6c86, 0x012e, 0x0ca0, 0xa994, 0x9186, - 0x0071, 0x0d38, 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, - 0x9186, 0x0028, 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, - 0x09c0, 0x9186, 0x005f, 0x09a8, 0x9186, 0x0056, 0x0990, 0xa897, - 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, 0x08a0, 0xa87c, - 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, - 0x7b9a, 0x2900, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, - 0xa05c, 0x9080, 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, - 0x0401, 0x1a04, 0x77fb, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x77fb, - 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x792c, - 0x0018, 0x9280, 0x7922, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, - 0x790d, 0x080c, 0x1018, 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, - 0x7022, 0x7054, 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, - 0xe004, 0x9100, 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, - 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, - 0x0108, 0x9108, 0xa17a, 0x810b, 0xa17e, 0x080c, 0x10e9, 0xa06c, - 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, - 0x0005, 0x7020, 0x2048, 0x080c, 0x1031, 0x7014, 0x2048, 0x0804, - 0x77fb, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, - 0x2048, 0xa906, 0x711a, 0x0804, 0x78c5, 0x7014, 0x2048, 0x7007, - 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, - 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7b9a, - 0x0804, 0x796e, 0x7924, 0x7928, 0x0002, 0x001d, 0x0007, 0x0004, - 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, - 0x0076, 0x0066, 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, - 0xb0bc, 0xb0de, 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, - 0xb0b0, 0xb0ca, 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, - 0xb6c2, 0xb7be, 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, - 0xb094, 0xb09e, 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, - 0xb088, 0xb08a, 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, - 0xb07c, 0xb07e, 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, - 0xb004, 0x9055, 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, - 0x210c, 0x81ff, 0x1178, 0x080c, 0x60b7, 0x1108, 0x0005, 0x080c, - 0x6eb9, 0x0126, 0x2091, 0x8000, 0x080c, 0xce3e, 0x080c, 0x6c86, - 0x012e, 0x0ca0, 0x080c, 0xd243, 0x1d70, 0x2001, 0x0028, 0x900e, - 0x0c70, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, - 0x0188, 0xa883, 0x0000, 0x080c, 0x6147, 0x1108, 0x0005, 0xa87a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6c86, 0x012e, 0x0cb8, 0x2001, - 0x0028, 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2009, 0x1834, 0x210c, - 0x81ff, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, - 0xd0f4, 0x0120, 0x080c, 0x6219, 0x1138, 0x0005, 0x9006, 0xa87a, - 0x080c, 0x6194, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, - 0xa982, 0x080c, 0x6c86, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, - 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, - 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, - 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, - 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, - 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, - 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, - 0x080c, 0x6608, 0x11b8, 0x0066, 0xae80, 0x080c, 0x6718, 0x006e, - 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, - 0x00c6, 0x080c, 0x6608, 0x1110, 0x080c, 0x6818, 0x8108, 0x1f04, - 0x7a09, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, 0x1031, 0x00be, - 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c86, 0x012e, 0x00be, - 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6977, - 0x0580, 0x2061, 0x1a70, 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, - 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, - 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, - 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, - 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, - 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, - 0x7c63, 0x012e, 0x0804, 0x7c5d, 0x012e, 0x0804, 0x7c57, 0x012e, - 0x0804, 0x7c5a, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, - 0x6977, 0x05e0, 0x2061, 0x1a70, 0x6000, 0xd084, 0x05b8, 0x6204, - 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, - 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, - 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, - 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, - 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, - 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, - 0x012e, 0x0804, 0x7c63, 0x012e, 0x0804, 0x7c60, 0x012e, 0x0804, - 0x7c5d, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1a70, - 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, - 0x0804, 0x7c71, 0x012e, 0x0804, 0x7c60, 0x00b6, 0x0126, 0x00c6, - 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, - 0x2061, 0x1a70, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, - 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, 0x2001, 0x1834, - 0x2004, 0x9005, 0x0118, 0x080c, 0xaea2, 0x0068, 0x6017, 0xf400, - 0x605b, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, 0x615a, 0x2009, - 0x0041, 0x080c, 0xaeec, 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, - 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x86c6, 0x002e, - 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a70, 0x6000, 0xd08c, 0x1120, - 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, - 0x7c63, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7c5d, 0xa984, 0x9186, - 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, - 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, - 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, - 0x080c, 0x6608, 0x1968, 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, - 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1985, 0x2004, 0x601a, - 0x0804, 0x7af8, 0xa88c, 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, 0x080c, 0xaea2, 0x8eff, - 0x0118, 0x2e60, 0x080c, 0xaea2, 0x00ee, 0x0804, 0x7af8, 0x6024, - 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, - 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, - 0x0001, 0x080c, 0x90d9, 0x080c, 0x9687, 0x00ee, 0x0804, 0x7af8, - 0x2061, 0x1a70, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x7c71, - 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, - 0x0804, 0x7c71, 0x012e, 0xa883, 0x0016, 0x0804, 0x7c6a, 0xa883, - 0x0007, 0x0804, 0x7c6a, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, - 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x77f3, - 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, - 0x7b9a, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, - 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, 0x7c1c, 0x6130, 0xd194, - 0x1904, 0x7c46, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x0a04, 0x7c10, - 0x6068, 0x9e02, 0x1a04, 0x7c10, 0x7120, 0x9186, 0x0006, 0x1904, - 0x7c02, 0x7010, 0x905d, 0x0904, 0x7c1c, 0xb800, 0xd0e4, 0x1904, - 0x7c40, 0x2061, 0x1a70, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, - 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7c49, 0xa883, 0x0000, 0xa803, - 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, - 0x1904, 0x7c4c, 0x080c, 0x56d8, 0xd09c, 0x1118, 0xa87c, 0xc0cc, - 0xa87e, 0x2e60, 0x080c, 0x85e6, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, - 0x1904, 0x7c4c, 0x012e, 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, - 0xa883, 0x0006, 0x00be, 0x0804, 0x7c6a, 0xd184, 0x0db8, 0xd1c4, - 0x1190, 0x00a0, 0xa974, 0x080c, 0x6608, 0x15d0, 0xb800, 0xd0e4, - 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, - 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, - 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x56dc, 0xd0fc, 0x01e8, - 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x02c0, 0x6068, 0x9e02, 0x12a8, - 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, - 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, - 0x7ba6, 0x7003, 0x0002, 0x0804, 0x7ba6, 0xa883, 0x0028, 0x0010, - 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, - 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, - 0x0014, 0x080c, 0xe155, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, - 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, - 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, - 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c86, 0x012e, - 0x0005, 0x080c, 0x1031, 0x0005, 0x00d6, 0x080c, 0x85dd, 0x00de, - 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, - 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, 0x7d5b, 0xd09c, - 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, 0x0020, 0x0278, 0x8001, - 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, - 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, - 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, 0x7d5b, 0x000e, - 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c, 0xae1b, 0x05d8, - 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x1138, - 0x6008, 0xc0fd, 0x600a, 0x2001, 0x196a, 0x2004, 0x0098, 0xa8a0, - 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105, 0xa99c, 0x918c, - 0x00ff, 0x080c, 0x2840, 0x1540, 0x00b6, 0x080c, 0x6608, 0x2b00, - 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, 0x2009, 0x0040, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009, 0x0041, 0x080c, - 0xaeec, 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6c86, 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6c86, 0x012e, 0x0005, 0xa87b, 0x0028, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6c86, 0x012e, 0x080c, 0xae71, 0x0005, 0x00d6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, - 0x9282, 0x0004, 0x1a04, 0x7d4c, 0xa97c, 0x9188, 0x1000, 0x2104, - 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, - 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, 0xae1b, 0x1118, - 0x080c, 0xaebf, 0x05a8, 0x6212, 0xa874, 0x0002, 0x7d2a, 0x7d2f, - 0x7d32, 0x7d38, 0x2019, 0x0002, 0x080c, 0xe543, 0x0060, 0x080c, - 0xe4df, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, 0xe4fa, 0x0018, - 0xa980, 0x080c, 0xe4df, 0x080c, 0xae71, 0xa887, 0x0000, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6c86, 0x012e, 0x00be, 0x001e, 0x002e, - 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, 0x0c80, 0xa887, - 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, 0x0004, 0x0c38, - 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, 0x7d5d, 0x0006, - 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0dde, 0x2001, 0x1834, - 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, - 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, - 0xd1ec, 0x1120, 0x080c, 0x157f, 0x00fe, 0x0005, 0x2001, 0x020d, - 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, - 0x0904, 0x7ddd, 0x68c0, 0x90aa, 0x0005, 0x0a04, 0x83f4, 0x7d44, - 0x7c40, 0x9584, 0x00f6, 0x1510, 0x9484, 0x7000, 0x0140, 0x908a, - 0x2000, 0x1260, 0x9584, 0x0700, 0x8007, 0x0804, 0x7de4, 0x7000, - 0x9084, 0xff00, 0x9086, 0x8100, 0x0da8, 0x00b0, 0x9484, 0x0fff, - 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, - 0xe9e2, 0x080c, 0x82e9, 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, - 0x1118, 0x080c, 0x8347, 0x19c0, 0xd5a4, 0x0148, 0x0046, 0x0056, - 0x080c, 0x7e3f, 0x080c, 0x2339, 0x005e, 0x004e, 0x0020, 0x080c, - 0xe9e2, 0x7817, 0x0140, 0x080c, 0x73a5, 0x0168, 0x2001, 0x0111, - 0x2004, 0xd08c, 0x0140, 0x6893, 0x0000, 0x2001, 0x0110, 0x2003, - 0x0008, 0x2003, 0x0000, 0x080c, 0x7e20, 0x2001, 0x19ef, 0x2004, - 0x9005, 0x090c, 0x9687, 0x0005, 0x0002, 0x7df6, 0x810b, 0x7ded, - 0x7ded, 0x7ded, 0x7ded, 0x7ded, 0x7ded, 0x7817, 0x0140, 0x2001, - 0x19ef, 0x2004, 0x9005, 0x090c, 0x9687, 0x0005, 0x7000, 0x908c, - 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, - 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x5739, - 0x0070, 0x080c, 0x7e5f, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, - 0x8046, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x8219, 0x7817, - 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, 0x9687, 0x0005, - 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, - 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, - 0x080c, 0x4b14, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, 0x0056, - 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, 0x0036, - 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, 0x2019, - 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, 0x080c, - 0x4b14, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, - 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, - 0x9096, 0x0023, 0x1904, 0x8017, 0x9186, 0x0023, 0x15c0, 0x080c, - 0x82ae, 0x0904, 0x8017, 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, - 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, - 0x8017, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, - 0x0015, 0x080c, 0xaeec, 0x0804, 0x8017, 0x908e, 0x0214, 0x0118, - 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xaeec, 0x0804, - 0x8017, 0x908e, 0x0100, 0x1904, 0x8017, 0x7034, 0x9005, 0x1904, - 0x8017, 0x2009, 0x0016, 0x080c, 0xaeec, 0x0804, 0x8017, 0x9186, - 0x0022, 0x1904, 0x8017, 0x7030, 0x908e, 0x0300, 0x1580, 0x68dc, - 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, 0x918c, 0x00ff, 0x697e, - 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, - 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x2889, 0x7932, 0x7936, - 0x001e, 0x000e, 0x00fe, 0x080c, 0x2840, 0x695e, 0x703c, 0x00e6, - 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee, 0x7034, - 0x9005, 0x1904, 0x8017, 0x2009, 0x0017, 0x0804, 0x7fc7, 0x908e, - 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8017, 0x080c, 0x73a5, - 0x0120, 0x2009, 0x001d, 0x0804, 0x7fc7, 0x68dc, 0xc0a5, 0x68de, - 0x2009, 0x0030, 0x0804, 0x7fc7, 0x908e, 0x0500, 0x1140, 0x7034, - 0x9005, 0x1904, 0x8017, 0x2009, 0x0018, 0x0804, 0x7fc7, 0x908e, - 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x7fc7, 0x908e, 0x2110, - 0x1120, 0x2009, 0x001a, 0x0804, 0x7fc7, 0x908e, 0x5200, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8017, 0x2009, 0x001b, 0x0804, 0x7fc7, - 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x8017, 0x2009, - 0x001c, 0x0804, 0x7fc7, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, - 0x0804, 0x7fc7, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, - 0x8017, 0x2009, 0x0024, 0x0804, 0x7fc7, 0x908c, 0xff00, 0x918e, - 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, - 0x0904, 0x7fc7, 0x080c, 0xd924, 0x1904, 0x8017, 0x0804, 0x7fc5, - 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, - 0x7fc7, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x7fc7, - 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, - 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, - 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4b14, 0x004e, 0x8108, - 0x0f04, 0x7f7b, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, - 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, 0x0804, - 0x7fc7, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, 0x7fc7, - 0x908e, 0x5400, 0x1138, 0x080c, 0x83a4, 0x1904, 0x8017, 0x2009, - 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x83cc, 0x1118, - 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e, 0x7800, - 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, - 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, - 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, - 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, - 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2840, 0x1904, - 0x801a, 0x080c, 0x65a7, 0x1904, 0x801a, 0xbe12, 0xbd16, 0x001e, - 0x0016, 0x080c, 0x73a5, 0x01c0, 0x68dc, 0xd08c, 0x1148, 0x7000, - 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, - 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, 0x9084, 0xff00, 0x1120, - 0x9584, 0x00ff, 0xb8c2, 0x0080, 0xb8c0, 0x9005, 0x1168, 0x9186, - 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, 0x6880, 0x9506, 0x9084, - 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0xae1b, 0x01a8, 0x2b08, - 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, - 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xaeec, 0x00ce, - 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x4b14, 0x080c, 0xaebf, 0x0d90, - 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, - 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, - 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, - 0x0009, 0x6003, 0x0001, 0x080c, 0x9121, 0x08a0, 0x080c, 0x32e5, - 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, - 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, - 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x82ae, 0x0904, 0x80a3, - 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, - 0x15d0, 0x2009, 0x0015, 0x080c, 0xaeec, 0x04a8, 0x908e, 0x0100, - 0x1590, 0x7034, 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0xaeec, - 0x0450, 0x9186, 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, - 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2840, 0x11b8, 0x080c, 0x65a7, 0x11a0, 0xbe12, 0xbd16, - 0x080c, 0xae1b, 0x0178, 0x2b08, 0x6112, 0x080c, 0xcfc4, 0x6023, - 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0xaeec, 0x080c, 0x9687, - 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, - 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, - 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, - 0x0804, 0x8105, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, - 0x8105, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, - 0x0000, 0x2019, 0x1837, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, - 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, - 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, - 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, - 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, - 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, - 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x80da, 0x82ff, 0x1118, - 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, - 0x004e, 0x00be, 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, - 0x000f, 0x0002, 0x8122, 0x8122, 0x8122, 0x82c0, 0x8122, 0x812b, - 0x8156, 0x81e4, 0x8122, 0x8122, 0x8122, 0x8122, 0x8122, 0x8122, - 0x8122, 0x8122, 0x7817, 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, - 0x090c, 0x9687, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, - 0x2160, 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6868, - 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, - 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, - 0x2009, 0x0046, 0x080c, 0xaeec, 0x7817, 0x0140, 0x2001, 0x19ef, - 0x2004, 0x9005, 0x090c, 0x9687, 0x00be, 0x0005, 0x00b6, 0x00c6, - 0x9484, 0x0fff, 0x0904, 0x81ba, 0x7110, 0xd1bc, 0x1904, 0x81ba, - 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, - 0x15b0, 0x81ff, 0x15a0, 0x9080, 0x3327, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x81ba, 0x080c, 0x65a7, - 0x1904, 0x81ba, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, - 0x9294, 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0xae1b, 0x05e8, - 0x2b08, 0x7028, 0x604a, 0x702c, 0x6046, 0x6112, 0x6023, 0x0006, - 0x7120, 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xdb84, - 0x0408, 0x080c, 0x697b, 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, - 0x80a7, 0x11c0, 0x0898, 0x080c, 0xae1b, 0x2b08, 0x0198, 0x6112, - 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, - 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9121, - 0x080c, 0x9687, 0x7817, 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, - 0x090c, 0x9687, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b14, 0x080c, 0xaebf, - 0x0d48, 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, - 0x6156, 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, - 0x7020, 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, - 0x6868, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, - 0x610a, 0x2009, 0x0045, 0x080c, 0xaeec, 0x7817, 0x0140, 0x2001, - 0x19ef, 0x2004, 0x9005, 0x090c, 0x9687, 0x00be, 0x0005, 0x6120, - 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, - 0x0005, 0x080c, 0x32e5, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, - 0x000b, 0x0005, 0x8230, 0x8231, 0x8230, 0x8230, 0x8290, 0x829f, - 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, - 0x828e, 0x700c, 0x7108, 0x080c, 0x2840, 0x1904, 0x828e, 0x080c, - 0x65a7, 0x1904, 0x828e, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x01d8, - 0x080c, 0x697b, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, - 0x82ae, 0x00ce, 0x05d8, 0x080c, 0xae1b, 0x2b08, 0x05b8, 0x6112, - 0x080c, 0xcfc4, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xaeec, 0x0458, 0x080c, 0x697b, 0x0148, 0x9086, 0x0004, - 0x0130, 0x080c, 0x6983, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, - 0xae1b, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0005, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xaeec, 0x0078, 0x080c, - 0xae1b, 0x2b08, 0x0158, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0004, - 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xaeec, 0x00be, 0x0005, - 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x820f, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xaeec, 0x0005, 0x7110, - 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x820f, 0x1130, 0x7124, - 0x610a, 0x2009, 0x008a, 0x080c, 0xaeec, 0x0005, 0x7020, 0x2060, - 0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x181a, - 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, - 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007, - 0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008, - 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, - 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0xaeec, 0x7817, - 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, 0x9687, 0x00be, - 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, - 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, - 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, - 0xc000, 0x05d0, 0x080c, 0xae1b, 0x05b8, 0x0066, 0x00c6, 0x0046, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2840, 0x15a0, - 0x080c, 0x65a7, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, - 0x6012, 0x080c, 0xcfc4, 0x080c, 0x0fff, 0x0510, 0x2900, 0x605a, - 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, - 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, - 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9121, 0x080c, 0x9687, 0x00fe, 0x009e, 0x00ce, 0x0005, - 0x080c, 0xae71, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, - 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, - 0x1904, 0x839e, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, - 0x9005, 0x1904, 0x83a0, 0x7030, 0x908e, 0x0400, 0x0904, 0x83a0, - 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, - 0x11d8, 0x2009, 0x1837, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, - 0x080c, 0x6939, 0x0558, 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c, - 0x00ff, 0x9106, 0x1518, 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105, - 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, - 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, - 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x82ae, - 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, - 0x9085, 0x0001, 0x00ce, 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x027a, 0x080c, 0xbe1c, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, - 0x080c, 0xbe1c, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0272, 0x080c, 0xbe1c, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, - 0x080c, 0xbe1c, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, - 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, - 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, - 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, - 0x7036, 0x00ee, 0x0005, 0x2071, 0x19f9, 0x7003, 0x0003, 0x700f, - 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x1cd0, 0x7007, - 0x0000, 0x7026, 0x702b, 0xa28a, 0x7032, 0x7037, 0xa2f8, 0x703f, - 0xffff, 0x7042, 0x7047, 0x5577, 0x704a, 0x705b, 0x857d, 0x080c, - 0x1018, 0x090c, 0x0dd5, 0x2900, 0x703a, 0xa867, 0x0003, 0xa86f, - 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19f9, 0x1d04, 0x84cb, - 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1530, 0x2001, 0x013c, - 0x2004, 0x9005, 0x190c, 0x85c2, 0x2001, 0x1869, 0x2004, 0xd0c4, - 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, - 0x20d1, 0x0000, 0x080c, 0x0dd5, 0x700f, 0x0361, 0x7007, 0x0001, - 0x0126, 0x2091, 0x8000, 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, - 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, - 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, - 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, - 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, - 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, - 0x007f, 0x090c, 0xa419, 0x0010, 0x7034, 0x080f, 0x703c, 0x9005, - 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, - 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, - 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, - 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, - 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, - 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, - 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x84f3, 0x84f4, 0x8510, - 0x00e6, 0x2071, 0x19f9, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, - 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19f9, - 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19f9, 0xb888, 0x9102, 0x0208, - 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x7110, 0x080c, 0x6608, - 0x1168, 0xb888, 0x8001, 0x0250, 0xb88a, 0x1140, 0x0126, 0x2091, - 0x8000, 0x0016, 0x080c, 0x9687, 0x001e, 0x012e, 0x8108, 0x9182, - 0x0800, 0x0218, 0x900e, 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, - 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, - 0x8001, 0x6042, 0x1110, 0x080c, 0xce55, 0x6018, 0x9005, 0x0558, - 0x8001, 0x601a, 0x1540, 0x6120, 0x9186, 0x0003, 0x0148, 0x9186, - 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, 0xd1c4, 0x1100, - 0x080c, 0xcb4a, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, - 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, - 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, - 0x0110, 0x080c, 0xc846, 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, - 0x181a, 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, - 0x0005, 0x00e6, 0x2071, 0x19f9, 0x7027, 0x07d0, 0x7023, 0x0009, - 0x00ee, 0x0005, 0x2001, 0x1a02, 0x2003, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x19f9, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, - 0x1a05, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19f9, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, - 0x8000, 0x7056, 0x2001, 0x1a07, 0x2044, 0xa06c, 0x9086, 0x0000, - 0x0150, 0x7068, 0xa09a, 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, - 0xa08e, 0x080c, 0x10e9, 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, - 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, - 0x080c, 0x843c, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x19f9, - 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0x19f9, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, - 0x00ee, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfffc, 0x210d, 0x2061, - 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009, 0xfffc, 0x200f, - 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, - 0x00c6, 0x2061, 0x1a70, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, - 0x8003, 0x8003, 0x9080, 0x1a70, 0x2060, 0x0005, 0xa884, 0x908a, - 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a70, 0x6014, - 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, - 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, - 0x00c0, 0x918e, 0x00c0, 0x0904, 0x8670, 0xd0b4, 0x1168, 0xd0bc, - 0x1904, 0x8649, 0x2009, 0x0006, 0x080c, 0x869d, 0x0005, 0x900e, - 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, 0x908c, 0x0003, - 0x0120, 0x918e, 0x0003, 0x1904, 0x8697, 0x908c, 0x2020, 0x918e, - 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, - 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xaeec, - 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0xaeec, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, - 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, - 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, - 0x1904, 0x8697, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, - 0x00f6, 0x2c78, 0x080c, 0x1727, 0x00fe, 0x007e, 0x87ff, 0x1120, - 0x2009, 0x0042, 0x080c, 0xaeec, 0x0005, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, - 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, - 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, - 0x080c, 0xaeec, 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, - 0x0043, 0x080c, 0xaeec, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, - 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xcb4a, - 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, - 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, - 0x2061, 0x1a70, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, - 0x6206, 0x00ce, 0x080c, 0x6ac1, 0x6014, 0x904d, 0x0076, 0x2039, - 0x0000, 0x190c, 0x85e6, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, - 0x2061, 0x1a70, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, - 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, - 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, - 0x1923, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, - 0x0001, 0x080c, 0x1018, 0x090c, 0x0dd5, 0xa867, 0x0006, 0xa86b, - 0x0001, 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, - 0x0000, 0x0005, 0x0096, 0x00e6, 0x2071, 0x1923, 0x702c, 0x2048, - 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0xa896, 0x6838, - 0x702a, 0xa89a, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, - 0x200a, 0x9005, 0x0148, 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, - 0x2100, 0x9210, 0x1208, 0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, - 0x0178, 0xc084, 0x7007, 0x0001, 0x700f, 0x0000, 0x0006, 0x2009, - 0x181d, 0x2104, 0x9082, 0x0007, 0x2009, 0x1ac7, 0x200a, 0x000e, - 0xc095, 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x15f0, 0x9006, - 0x2071, 0x193c, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x0005, - 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, - 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, - 0x9080, 0x0008, 0x1f04, 0x8750, 0x71c0, 0x9102, 0x02e0, 0x2071, - 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c, 0xae1b, 0x6023, 0x0009, - 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, - 0x080c, 0x88d6, 0x012e, 0x1f04, 0x875c, 0x9006, 0x00ce, 0x015e, - 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, - 0x0096, 0x0086, 0x0056, 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, - 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, - 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, 0x0fff, 0x090c, 0x0dd5, - 0x2900, 0x6016, 0x2058, 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, - 0xa87a, 0xa8aa, 0xa887, 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, - 0x7010, 0xa89e, 0xae8a, 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, - 0x0160, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0xad66, 0x2b00, 0xa802, - 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, - 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, - 0x1923, 0x7004, 0x004b, 0x700c, 0x0002, 0x87c8, 0x87c1, 0x87c1, - 0x0005, 0x87d2, 0x8833, 0x8833, 0x8833, 0x8834, 0x8845, 0x8845, - 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, - 0x0128, 0x78a0, 0x79a0, 0x9106, 0x1904, 0x8826, 0x2001, 0x0005, - 0x2004, 0xd0bc, 0x0130, 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, - 0x0ca8, 0x012e, 0x7018, 0x910a, 0x1130, 0x7030, 0x9005, 0x05a8, - 0x080c, 0x8874, 0x0490, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, - 0x0210, 0x2009, 0x000a, 0x2001, 0x1888, 0x2014, 0x2001, 0x1935, - 0x2004, 0x9100, 0x9202, 0x0e48, 0x080c, 0x89c0, 0x2200, 0x9102, - 0x0208, 0x2208, 0x0096, 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, - 0x080c, 0x8ac9, 0x2100, 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, - 0x2091, 0x8000, 0x2009, 0x1a17, 0x2104, 0xc085, 0x200a, 0x700f, - 0x0002, 0x012e, 0x080c, 0x1108, 0x1de8, 0x0005, 0x2001, 0x0005, - 0x2004, 0xd0bc, 0x0130, 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, - 0x0ca8, 0x012e, 0x0005, 0x0005, 0x700c, 0x0002, 0x8839, 0x883c, - 0x883b, 0x080c, 0x87d0, 0x0005, 0x8001, 0x700e, 0x0096, 0x702c, - 0x2048, 0xa974, 0x009e, 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c, - 0x2048, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e, - 0x7020, 0xa892, 0x9006, 0x0068, 0x0006, 0x080c, 0x8ac9, 0x2100, - 0xaa8c, 0x9210, 0xaa8e, 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, - 0x000e, 0x009e, 0x2f08, 0x9188, 0x0028, 0x200a, 0x701a, 0x0005, - 0x00e6, 0x2071, 0x1923, 0x700c, 0x0002, 0x8872, 0x8872, 0x8870, - 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, - 0x9005, 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x88df, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193c, - 0x080c, 0x8926, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1018, 0x2900, - 0x009e, 0x0148, 0xa8aa, 0x04b9, 0x0041, 0x2001, 0x1946, 0x2003, - 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, - 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, - 0x000f, 0x2068, 0x9d88, 0x2092, 0x2165, 0x0056, 0x2029, 0x0000, - 0x080c, 0x8a4e, 0x080c, 0x204a, 0x1dd8, 0x005e, 0x00ae, 0x2001, - 0x187f, 0x2004, 0xa88a, 0x080c, 0x1727, 0x781f, 0x0101, 0x7813, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x8935, 0x012e, 0x008e, - 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, 0x2078, 0x780c, - 0x7032, 0x2001, 0x1946, 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, - 0x1923, 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, 0x0005, 0x00d6, - 0x00c6, 0x0026, 0x9b80, 0x8ba8, 0x2005, 0x906d, 0x090c, 0x0dd5, - 0x9b80, 0x8ba0, 0x2005, 0x9065, 0x090c, 0x0dd5, 0x6114, 0x2600, - 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085, 0x0001, 0x002e, - 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, 0x0148, 0x6854, 0xd084, - 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, 0x080c, 0x4b14, 0x684c, - 0x0096, 0x904d, 0x090c, 0x0dd5, 0xa804, 0x8000, 0xa806, 0x009e, - 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, 0xc08d, 0x6856, - 0x2011, 0x8025, 0x080c, 0x4b14, 0x684c, 0x0096, 0x904d, 0x090c, - 0x0dd5, 0xa800, 0x8000, 0xa802, 0x009e, 0x0888, 0x7000, 0x2019, - 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, - 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, - 0x090c, 0x0dd5, 0x781c, 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, - 0x0dd5, 0x2069, 0x193c, 0x6804, 0x9080, 0x193e, 0x2f08, 0x2102, - 0x6904, 0x8108, 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, - 0x193e, 0x2003, 0x0000, 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, - 0x6014, 0x2048, 0xa8a8, 0x0096, 0x2048, 0x9005, 0x190c, 0x1031, - 0x009e, 0xa8ab, 0x0000, 0x080c, 0x0fb1, 0x080c, 0xae71, 0x00ce, - 0x009e, 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, - 0x0110, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, - 0x0000, 0x0178, 0x6010, 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, - 0x8cdb, 0x00be, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, - 0x0861, 0x0005, 0x2009, 0x1927, 0x210c, 0xd194, 0x0005, 0x00e6, - 0x2071, 0x1923, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, - 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x15f0, 0x00ee, 0x0005, - 0x0096, 0x00d6, 0x9006, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, - 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x8b28, 0x0170, - 0x080c, 0x8b5d, 0x0158, 0x2900, 0x7002, 0x700a, 0x701a, 0x7013, - 0x0001, 0x701f, 0x000a, 0x00de, 0x009e, 0x0005, 0x900e, 0x0cd8, - 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6, 0x2071, 0x1930, 0x721c, - 0x2100, 0x9202, 0x1618, 0x080c, 0x8b5d, 0x090c, 0x0dd5, 0x7018, - 0x9005, 0x1160, 0x2900, 0x7002, 0x700a, 0x701a, 0x9006, 0x7006, - 0x700e, 0xa806, 0xa802, 0x7012, 0x701e, 0x0038, 0x2040, 0xa806, - 0x2900, 0xa002, 0x701a, 0xa803, 0x0000, 0x7010, 0x8000, 0x7012, - 0x701c, 0x9080, 0x000a, 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, - 0x00de, 0x008e, 0x009e, 0x00ee, 0x0005, 0x0096, 0x0156, 0x0136, - 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1930, 0x7300, - 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, 0x20e8, 0x939c, 0xffc0, - 0x9398, 0x0003, 0x7104, 0x080c, 0x8ac9, 0x810c, 0x2100, 0x9318, - 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, - 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, - 0x080c, 0x8ad2, 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, - 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, 0x1190, - 0x7000, 0x2048, 0xa800, 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, - 0x080c, 0x89c0, 0x002e, 0x7000, 0x2048, 0xa800, 0x7002, 0x7007, - 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, 0x1904, 0x89ff, 0x012e, - 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e, 0x0005, 0x0016, 0x0026, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580, 0x8ba0, 0x2005, 0x9075, - 0x090c, 0x0dd5, 0x080c, 0x8aa4, 0x012e, 0x9580, 0x8b9c, 0x2005, - 0x9075, 0x090c, 0x0dd5, 0x0156, 0x0136, 0x01c6, 0x0146, 0x01d6, - 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, 0x20e0, 0x9384, 0xffc0, - 0x9100, 0x2098, 0xa860, 0x20e8, 0xa95c, 0x2c05, 0x9100, 0x20a0, - 0x20a9, 0x0002, 0x4003, 0x2e0c, 0x2d00, 0x0002, 0x8a8e, 0x8a8e, - 0x8a90, 0x8a8e, 0x8a90, 0x8a8e, 0x8a8e, 0x8a8e, 0x8a8e, 0x8a8e, - 0x8a96, 0x8a8e, 0x8a96, 0x8a8e, 0x8a8e, 0x8a8e, 0x080c, 0x0dd5, - 0x4104, 0x20a9, 0x0002, 0x4002, 0x4003, 0x0028, 0x20a9, 0x0002, - 0x4003, 0x4104, 0x4003, 0x01de, 0x014e, 0x01ce, 0x013e, 0x015e, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x7014, 0x8001, 0x7016, - 0x710c, 0x2110, 0x00f1, 0x810c, 0x9188, 0x0003, 0x7308, 0x8210, - 0x9282, 0x000a, 0x1198, 0x7008, 0x2048, 0xa800, 0x9005, 0x0158, - 0x0006, 0x080c, 0x8b6c, 0x009e, 0xa807, 0x0000, 0x2900, 0x700a, - 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x009e, - 0x0005, 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, 0x9100, 0x2008, - 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, 0x9005, 0x0158, 0x9092, - 0x000c, 0x0240, 0x900e, 0x8108, 0x9082, 0x000c, 0x1de0, 0x002e, - 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00, 0x90b8, 0x0008, 0x690c, - 0x6810, 0x2019, 0x0001, 0x2031, 0x8b12, 0x9112, 0x0220, 0x0118, - 0x8318, 0x2208, 0x0cd0, 0x6808, 0x9005, 0x0108, 0x8318, 0x233a, - 0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, - 0x0967, 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, - 0x9082, 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, - 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0x90b8, 0x0007, 0x00e6, 0x2071, - 0x1800, 0x7128, 0x6810, 0x2019, 0x0001, 0x910a, 0x0118, 0x0210, - 0x8318, 0x0cd8, 0x2031, 0x8b25, 0x0870, 0x6c16, 0x00ee, 0x0005, - 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, 0x9080, 0x8ba4, - 0x2005, 0x9005, 0x090c, 0x0dd5, 0x2004, 0x90a0, 0x000a, 0x080c, - 0x1018, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, - 0x080c, 0x1018, 0x0188, 0x7024, 0xa802, 0xa807, 0x0000, 0x2900, - 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, - 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2048, - 0xac00, 0x080c, 0x1031, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, - 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, 0x7026, 0xa803, 0x0000, - 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, - 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, 0x0096, 0x9e80, 0x0009, - 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x1031, - 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, 0x9005, 0x0138, - 0x2048, 0xa800, 0x0006, 0x080c, 0x1031, 0x000e, 0x0cb8, 0x9006, - 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, - 0x7026, 0x702e, 0x009e, 0x0005, 0x1a63, 0x0000, 0x0000, 0x0000, - 0x1930, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, 0x0000, 0x0000, - 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, 0x00b6, 0x00a6, - 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x8cc6, 0xa067, 0x0023, - 0x6010, 0x905d, 0x0904, 0x8c9b, 0xb814, 0xa06e, 0xb910, 0xa172, - 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834, 0xa082, 0xa07b, - 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, 0xc085, 0xa07a, 0x2858, - 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c, 0x0dd5, 0x2020, - 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, 0x000f, 0x91e0, - 0x2092, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, 0x908a, 0x0036, - 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x8c08, 0x8c08, 0x8c0a, - 0x8c08, 0x8c08, 0x8c08, 0x8c0c, 0x8c08, 0x8c08, 0x8c08, 0x8c0e, - 0x8c08, 0x8c08, 0x8c08, 0x8c10, 0x8c08, 0x8c08, 0x8c08, 0x8c12, - 0x8c08, 0x8c08, 0x8c08, 0x8c14, 0x8c08, 0x8c08, 0x8c08, 0x8c16, - 0x080c, 0x0dd5, 0xa180, 0x04b8, 0xa190, 0x04a8, 0xa1a0, 0x0498, - 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, 0xa1e0, 0x0458, - 0x908a, 0x0034, 0x1a0c, 0x0dd5, 0x9082, 0x001b, 0x0002, 0x8c3a, - 0x8c38, 0x8c38, 0x8c38, 0x8c38, 0x8c38, 0x8c3c, 0x8c38, 0x8c38, - 0x8c38, 0x8c38, 0x8c38, 0x8c3e, 0x8c38, 0x8c38, 0x8c38, 0x8c38, - 0x8c38, 0x8c40, 0x8c38, 0x8c38, 0x8c38, 0x8c38, 0x8c38, 0x8c42, - 0x080c, 0x0dd5, 0xa180, 0x0038, 0xa198, 0x0028, 0xa1b0, 0x0018, - 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x8c5e, 0x8c60, 0x8c62, - 0x8c64, 0x8c66, 0x8c68, 0x8c6a, 0x8c6c, 0x8c6e, 0x8c70, 0x8c72, - 0x8c74, 0x8c76, 0x8c78, 0x8c7a, 0x8c7c, 0x8c7e, 0x8c80, 0x8c82, - 0x8c84, 0x8c86, 0x8c88, 0x8c8a, 0x8c8c, 0x8c8e, 0x080c, 0x0dd5, - 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448, 0xb9d6, 0x0438, - 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408, 0xb9c6, 0x00f8, - 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8, 0xb9b6, 0x00b8, - 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088, 0xb9a6, 0x0078, - 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048, 0xb996, 0x0038, - 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008, 0xb986, 0x8631, - 0x8421, 0x0120, 0x080c, 0x204a, 0x0804, 0x8be2, 0x00ae, 0x00be, - 0x00ce, 0x00ee, 0x0005, 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, - 0x00ff, 0x9006, 0x0804, 0x8bc4, 0x0006, 0x0016, 0x00b6, 0x6010, - 0x2058, 0xb810, 0x9005, 0x01b0, 0x2001, 0x1924, 0x2004, 0x9005, - 0x0188, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0xbba0, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4b14, - 0x004e, 0x003e, 0x00be, 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, - 0xa834, 0x910a, 0xa936, 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, - 0x0238, 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, 0x0cd8, - 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, 0x0300, - 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, 0xa001, - 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, 0x9005, 0x01b8, 0x2068, - 0x2079, 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, 0xb8ae, 0x0060, - 0x9106, 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, 0x0dd5, - 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, - 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, - 0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, - 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, - 0x1f04, 0x8d1b, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, - 0x1d90, 0xb8ac, 0x9005, 0x01d0, 0x2060, 0x600c, 0xb8ae, 0x6003, - 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, 0x6014, - 0x2048, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, 0x0000, 0x904d, 0x090c, - 0x0dd5, 0x080c, 0x1031, 0x080c, 0x88d6, 0x0c18, 0x2071, 0x0300, - 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x009e, 0x00de, - 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, 0x0006, 0x0156, 0x080c, - 0x2840, 0x015e, 0x11b0, 0x080c, 0x65a7, 0x190c, 0x0dd5, 0x000e, - 0x001e, 0xb912, 0xb816, 0x080c, 0xae1b, 0x0140, 0x2b00, 0x6012, - 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, 0xaeec, 0x00be, 0x00ce, - 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, 0x0016, - 0x1a0c, 0x0dd5, 0x0013, 0x006e, 0x0005, 0x8d8d, 0x8d8d, 0x8d8d, - 0x8d8f, 0x8de0, 0x8d8d, 0x8d8d, 0x8d8d, 0x8e43, 0x8d8d, 0x8e80, - 0x8d8d, 0x8d8d, 0x8d8d, 0x8d8d, 0x8d8d, 0x080c, 0x0dd5, 0x9182, - 0x0040, 0x0002, 0x8da2, 0x8da2, 0x8da2, 0x8da2, 0x8da2, 0x8da2, - 0x8da2, 0x8da2, 0x8da2, 0x8da4, 0x8db9, 0x8da2, 0x8da2, 0x8da2, - 0x8da2, 0x8dcc, 0x080c, 0x0dd5, 0x0096, 0x080c, 0x9637, 0x080c, - 0x97b5, 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, - 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6a8c, 0x080c, 0xae71, 0x009e, - 0x0005, 0x080c, 0x9637, 0x00d6, 0x6114, 0x080c, 0xcb4a, 0x0130, - 0x0096, 0x6114, 0x2148, 0x080c, 0x6c86, 0x009e, 0x00de, 0x080c, - 0xae71, 0x080c, 0x97b5, 0x0005, 0x080c, 0x9637, 0x080c, 0x31c1, - 0x6114, 0x0096, 0x2148, 0x080c, 0xcb4a, 0x0120, 0xa87b, 0x0029, - 0x080c, 0x6c86, 0x009e, 0x080c, 0xae71, 0x080c, 0x97b5, 0x0005, - 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, 0x0002, 0x8dfb, 0x8dfb, - 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfd, 0x8dfb, - 0x8dfb, 0x8dfb, 0x8e3f, 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfb, 0x8dfb, - 0x8dfb, 0x8e03, 0x8dfb, 0x080c, 0x0dd5, 0x6114, 0x2148, 0xa938, - 0x918e, 0xffff, 0x05e0, 0x00e6, 0x6114, 0x2148, 0x080c, 0x8bac, - 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6a24, 0x009e, 0xa8ab, 0x0000, - 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x8cdb, 0x00be, - 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x88df, 0x00be, 0x01e0, - 0x2071, 0x193c, 0x080c, 0x8926, 0x01b8, 0x9086, 0x0001, 0x1128, - 0x2001, 0x1946, 0x2004, 0x9005, 0x1178, 0x0096, 0x080c, 0x0fff, - 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, 0x080c, 0x889d, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x88d6, 0x0cd0, 0x080c, - 0x8eed, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, 0x0002, 0x8e57, - 0x8e57, 0x8e57, 0x8e59, 0x8e57, 0x8e57, 0x8e57, 0x8e7e, 0x8e57, - 0x8e57, 0x8e57, 0x8e57, 0x8e57, 0x8e57, 0x8e57, 0x8e57, 0x080c, - 0x0dd5, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa8ac, 0xa846, - 0xa8b0, 0xa84a, 0xa837, 0x0000, 0xa83b, 0x0000, 0xa884, 0x9092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, - 0x621a, 0x2c10, 0x080c, 0x1baf, 0x080c, 0x913e, 0x0126, 0x2091, - 0x8000, 0x080c, 0x97b5, 0x012e, 0x009e, 0x0005, 0x080c, 0x0dd5, - 0x080c, 0x9637, 0x080c, 0x97b5, 0x6114, 0x2148, 0xa87b, 0x0000, - 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6c86, - 0x080c, 0xae71, 0x009e, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, - 0x0dd5, 0x0096, 0x0013, 0x009e, 0x0005, 0x8ead, 0x8ead, 0x8ead, - 0x8eaf, 0x8ec0, 0x8ead, 0x8ead, 0x8ead, 0x8ead, 0x8ead, 0x8ead, - 0x8ead, 0x8ead, 0x8ead, 0x8ead, 0x8ead, 0x080c, 0x0dd5, 0x080c, - 0xa7cd, 0x6114, 0x2148, 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, - 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6c86, 0x080c, 0xae71, 0x0005, - 0x0461, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x0096, - 0x0013, 0x009e, 0x0005, 0x8edb, 0x8edb, 0x8edb, 0x8edd, 0x8eed, - 0x8edb, 0x8edb, 0x8edb, 0x8edb, 0x8edb, 0x8edb, 0x8edb, 0x8edb, - 0x8edb, 0x8edb, 0x8edb, 0x080c, 0x0dd5, 0x0036, 0x00e6, 0x2071, - 0x19e6, 0x703c, 0x9c06, 0x1120, 0x2019, 0x0000, 0x080c, 0xa5b7, - 0x080c, 0xa7cd, 0x00ee, 0x003e, 0x0005, 0x00f6, 0x00e6, 0x601b, - 0x0000, 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, - 0x080c, 0x8cdb, 0x00be, 0x2071, 0x193c, 0x080c, 0x8926, 0x0160, - 0x2001, 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, - 0x889d, 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, - 0x2048, 0x080c, 0x1031, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x88d6, - 0x0c80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x187a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, - 0x9006, 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, - 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, - 0x9200, 0x1f04, 0x8f32, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, - 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, - 0x9005, 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, - 0x97be, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, - 0x911a, 0x1220, 0x1f04, 0x8f5c, 0x0028, 0x911a, 0x2308, 0x8210, - 0x1f04, 0x8f5c, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, - 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, - 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e6, 0x012e, 0x00d6, - 0x2069, 0x19e6, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, - 0x0000, 0x2069, 0x0200, 0x080c, 0xab2c, 0x0401, 0x080c, 0xab17, - 0x00e9, 0x080c, 0xab1a, 0x00d1, 0x080c, 0xab1d, 0x00b9, 0x080c, - 0xab20, 0x00a1, 0x080c, 0xab23, 0x0089, 0x080c, 0xab26, 0x0071, - 0x080c, 0xab29, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, - 0x2d04, 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, - 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x6027, - 0x0001, 0x7804, 0x9084, 0x0007, 0x0002, 0x8fcf, 0x8ff3, 0x9032, - 0x8fd5, 0x8ff3, 0x8fcf, 0x8fcd, 0x8fcd, 0x080c, 0x0dd5, 0x080c, - 0x8562, 0x080c, 0x9687, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x7828, 0x9092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x5ecc, 0x0c88, 0x62c0, - 0x080c, 0xac68, 0x080c, 0x5e8c, 0x7807, 0x0003, 0x7827, 0x0000, - 0x782b, 0x0000, 0x0c28, 0x080c, 0x8562, 0x6220, 0xd2a4, 0x0160, + 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186, + 0x0003, 0x1168, 0x7004, 0x0002, 0x7757, 0x7731, 0x7757, 0x7755, + 0x7757, 0x7757, 0x7757, 0x7757, 0x7757, 0x080c, 0x77c2, 0x782c, + 0xd09c, 0x090c, 0x7c86, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, + 0x003b, 0x0c10, 0x080c, 0x77f8, 0x0c90, 0x00e3, 0x08e8, 0x0005, + 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x781a, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x7804, 0x77f8, 0x79ed, 0x77f8, + 0x77f8, 0x77f8, 0x781a, 0x77f8, 0x7804, 0x7a2e, 0x7a6f, 0x7ab6, + 0x7aca, 0x77f8, 0x77f8, 0x781a, 0x7804, 0x782e, 0x77f8, 0x78a6, + 0x7b75, 0x7b90, 0x77f8, 0x781a, 0x77f8, 0x782e, 0x77f8, 0x77f8, + 0x789c, 0x7b90, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x77f8, 0x77f8, 0x77f8, 0x7842, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x77f8, 0x7d0c, 0x77f8, 0x7cb6, + 0x77f8, 0x7cb6, 0x77f8, 0x7857, 0x77f8, 0x77f8, 0x77f8, 0x77f8, + 0x77f8, 0x77f8, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, + 0x782c, 0x080c, 0x7caf, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, + 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, + 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7c86, 0x0005, 0x77f8, 0x7804, + 0x79d9, 0x77f8, 0x7804, 0x77f8, 0x7804, 0x7804, 0x77f8, 0x7804, + 0x79d9, 0x7804, 0x7804, 0x7804, 0x7804, 0x7804, 0x77f8, 0x7804, + 0x79d9, 0x77f8, 0x77f8, 0x7804, 0x77f8, 0x77f8, 0x77f8, 0x7804, + 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, + 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, + 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, + 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c94, + 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x797b, 0x7007, 0x0003, 0x7012, + 0x2900, 0x7016, 0x701a, 0x704b, 0x797b, 0x0005, 0xa864, 0x8007, + 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, + 0x7996, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, + 0x7996, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, 0x7800, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x79b2, 0x7007, 0x0003, + 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x79b2, 0x0005, 0xa864, + 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7800, 0x7007, + 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x11a8, 0xa868, 0x9084, + 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x62c1, 0x1108, 0x0005, + 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, + 0x6c94, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0d38, 0x9186, + 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, 0x09f0, + 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, 0x005f, + 0x09a8, 0x9186, 0x0056, 0x0990, 0xa897, 0x4005, 0xa89b, 0x0001, + 0x2001, 0x0030, 0x900e, 0x08a0, 0xa87c, 0x9084, 0x00c0, 0x9086, + 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7ba7, 0x2900, 0x7016, + 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, + 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, + 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x7808, + 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7808, 0x82ff, 0x1138, 0xa8b8, + 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7939, 0x0018, 0x9280, 0x792f, + 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x791a, 0x080c, 0x1018, + 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, + 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, + 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, + 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, + 0x810b, 0xa17e, 0x080c, 0x10e9, 0xa06c, 0x908e, 0x0100, 0x0170, + 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, + 0x080c, 0x1031, 0x7014, 0x2048, 0x0804, 0x7808, 0x7020, 0x2048, + 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, + 0x0804, 0x78d2, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, + 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x0904, 0x7ba7, 0x0804, 0x797b, 0x7931, + 0x7935, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, + 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, + 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, + 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, + 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, + 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, + 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, + 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, + 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, + 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1178, + 0x080c, 0x60c1, 0x1108, 0x0005, 0x080c, 0x6ec7, 0x0126, 0x2091, + 0x8000, 0x080c, 0xce4e, 0x080c, 0x6c94, 0x012e, 0x0ca0, 0x080c, + 0xd253, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834, + 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, 0x0000, + 0x080c, 0x6151, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6c94, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, + 0x0000, 0x0c90, 0x2009, 0x1834, 0x210c, 0x81ff, 0x11d8, 0xa888, + 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, + 0x6223, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, 0x619e, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6c94, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, + 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, + 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, + 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, + 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, + 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, + 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, 0x080c, 0x6616, 0x11b8, + 0x0066, 0xae80, 0x080c, 0x6726, 0x006e, 0x0088, 0x0046, 0x2011, + 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6616, + 0x1110, 0x080c, 0x6826, 0x8108, 0x1f04, 0x7a16, 0x00ce, 0xa87c, + 0xd084, 0x1120, 0x080c, 0x1031, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6c94, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x080c, 0x6985, 0x0580, 0x2061, 0x1a70, + 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, + 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, + 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, + 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, + 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, + 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x7c70, 0x012e, 0x0804, + 0x7c6a, 0x012e, 0x0804, 0x7c64, 0x012e, 0x0804, 0x7c67, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6985, 0x05e0, 0x2061, + 0x1a70, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, + 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, + 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, + 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, + 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, + 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, + 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x7c70, + 0x012e, 0x0804, 0x7c6d, 0x012e, 0x0804, 0x7c6a, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x2061, 0x1a70, 0x6300, 0xd38c, 0x1120, + 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x7c7e, 0x012e, + 0x0804, 0x7c6d, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, + 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a70, 0x6000, + 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, + 0xa88c, 0x9065, 0x0598, 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, + 0x080c, 0xae90, 0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, + 0xd1a4, 0x0110, 0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0xaeda, + 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, + 0x2011, 0xfdff, 0x080c, 0x86e3, 0x002e, 0xa87c, 0xd0c4, 0x0148, + 0x2061, 0x1a70, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, + 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7c70, 0x00ce, 0x012e, + 0x00be, 0x0804, 0x7c6a, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, + 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, + 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, + 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, 0x080c, 0x6616, 0x1968, + 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, + 0x0024, 0x2001, 0x1985, 0x2004, 0x601a, 0x0804, 0x7b05, 0xa88c, + 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, + 0x9005, 0x0150, 0x080c, 0xae90, 0x8eff, 0x0118, 0x2e60, 0x080c, + 0xae90, 0x00ee, 0x0804, 0x7b05, 0x6024, 0xc0dc, 0xc0d5, 0x6026, + 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, + 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x90f8, + 0x080c, 0x96a6, 0x00ee, 0x0804, 0x7b05, 0x2061, 0x1a70, 0x6000, + 0xd084, 0x0190, 0xd08c, 0x1904, 0x7c7e, 0x0126, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x7c7e, 0x012e, + 0xa883, 0x0016, 0x0804, 0x7c77, 0xa883, 0x0007, 0x0804, 0x7c77, + 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, + 0x0001, 0x0069, 0x0005, 0x080c, 0x7800, 0x0040, 0x7007, 0x0003, + 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7ba7, 0x0005, 0x00b6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, + 0x81ff, 0x1904, 0x7c29, 0x6130, 0xd194, 0x1904, 0x7c53, 0xa878, + 0x2070, 0x9e82, 0x1cd0, 0x0a04, 0x7c1d, 0x6068, 0x9e02, 0x1a04, + 0x7c1d, 0x7120, 0x9186, 0x0006, 0x1904, 0x7c0f, 0x7010, 0x905d, + 0x0904, 0x7c29, 0xb800, 0xd0e4, 0x1904, 0x7c4d, 0x2061, 0x1a70, + 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, + 0x1904, 0x7c56, 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, + 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7c59, 0x080c, + 0x56e2, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, + 0x8603, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, + 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7c59, 0x012e, + 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, + 0x0804, 0x7c77, 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, + 0x080c, 0x6616, 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, + 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, + 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, + 0x0430, 0x080c, 0x56e6, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, + 0x1cd0, 0x02c0, 0x6068, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, + 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, + 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x7bb3, 0x7003, 0x0002, + 0x0804, 0x7bb3, 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, + 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, + 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xe16f, + 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, + 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, + 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6c94, 0x012e, 0x0005, 0x080c, 0x1031, + 0x0005, 0x00d6, 0x080c, 0x85fa, 0x00de, 0x0005, 0x00d6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, + 0x908c, 0x0780, 0x190c, 0x7d68, 0xd09c, 0x11a8, 0x2071, 0x1800, + 0x70c0, 0x90ea, 0x0020, 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, + 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, + 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, + 0x9084, 0x0780, 0x190c, 0x7d68, 0x000e, 0x0005, 0xa898, 0x9084, + 0x0003, 0x05a8, 0x080c, 0xae09, 0x05d8, 0x2900, 0x6016, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x0035, 0x1138, 0x6008, 0xc0fd, 0x600a, + 0x2001, 0x196a, 0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, + 0x918c, 0xff00, 0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, 0x284b, + 0x1540, 0x00b6, 0x080c, 0x6616, 0x2b00, 0x00be, 0x1510, 0x6012, + 0x6023, 0x0001, 0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x0035, 0x0110, 0x2009, 0x0041, 0x080c, 0xaeda, 0x0005, 0xa87b, + 0x0101, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c94, 0x012e, 0x0005, + 0xa87b, 0x002c, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c94, 0x012e, + 0x0005, 0xa87b, 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c94, + 0x012e, 0x080c, 0xae5f, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, + 0x7d59, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, + 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, + 0x04b0, 0x2b10, 0x080c, 0xae09, 0x1118, 0x080c, 0xaead, 0x05a8, + 0x6212, 0xa874, 0x0002, 0x7d37, 0x7d3c, 0x7d3f, 0x7d45, 0x2019, + 0x0002, 0x080c, 0xe55d, 0x0060, 0x080c, 0xe4f9, 0x0048, 0x2019, + 0x0002, 0xa980, 0x080c, 0xe514, 0x0018, 0xa980, 0x080c, 0xe4f9, + 0x080c, 0xae5f, 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6c94, 0x012e, 0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, + 0x0005, 0xa887, 0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, + 0x0005, 0x0c50, 0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, + 0x2091, 0x8000, 0x0e04, 0x7d6a, 0x0006, 0x0016, 0x2001, 0x8003, + 0x0006, 0x0804, 0x0dde, 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, + 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, + 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, + 0x157f, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, + 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, 0x7dea, 0x68c0, + 0x90aa, 0x0005, 0x0a04, 0x8411, 0x7d44, 0x7c40, 0x9584, 0x00f6, + 0x1510, 0x9484, 0x7000, 0x0140, 0x908a, 0x2000, 0x1260, 0x9584, + 0x0700, 0x8007, 0x0804, 0x7df1, 0x7000, 0x9084, 0xff00, 0x9086, + 0x8100, 0x0da8, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, + 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, 0xe9fc, 0x080c, 0x82f6, + 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x8354, + 0x19c0, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x7e4c, 0x080c, + 0x2344, 0x005e, 0x004e, 0x0020, 0x080c, 0xe9fc, 0x7817, 0x0140, + 0x080c, 0x73b3, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, + 0x6893, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, + 0x080c, 0x7e2d, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, 0x96a6, + 0x0005, 0x0002, 0x7e03, 0x8118, 0x7dfa, 0x7dfa, 0x7dfa, 0x7dfa, + 0x7dfa, 0x7dfa, 0x7817, 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, + 0x090c, 0x96a6, 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, + 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000, 0x1150, 0x6800, + 0x9086, 0x0001, 0x1118, 0x080c, 0x5743, 0x0070, 0x080c, 0x7e6c, + 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x8053, 0x0028, 0x9286, + 0x8000, 0x1110, 0x080c, 0x8226, 0x7817, 0x0140, 0x2001, 0x19ef, + 0x2004, 0x9005, 0x090c, 0x96a6, 0x0005, 0x2001, 0x1810, 0x2004, + 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, + 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x4b1e, 0x003e, + 0x002e, 0x0005, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, + 0x2019, 0xfffe, 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, + 0x2079, 0x0200, 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, + 0x2004, 0xd08c, 0x0160, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, + 0x1130, 0x0026, 0x2011, 0x8048, 0x080c, 0x4b1e, 0x002e, 0x00fe, + 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, + 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, + 0x8024, 0x9186, 0x0023, 0x15c0, 0x080c, 0x82bb, 0x0904, 0x8024, + 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, + 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x8024, 0x7124, 0x610a, + 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xaeda, + 0x0804, 0x8024, 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, + 0x2009, 0x0015, 0x080c, 0xaeda, 0x0804, 0x8024, 0x908e, 0x0100, + 0x1904, 0x8024, 0x7034, 0x9005, 0x1904, 0x8024, 0x2009, 0x0016, + 0x080c, 0xaeda, 0x0804, 0x8024, 0x9186, 0x0022, 0x1904, 0x8024, + 0x7030, 0x908e, 0x0300, 0x1580, 0x68dc, 0xd0a4, 0x0528, 0xc0b5, + 0x68de, 0x7100, 0x918c, 0x00ff, 0x697e, 0x7004, 0x6882, 0x00f6, + 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, + 0x2008, 0x080c, 0x2894, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, + 0x080c, 0x284b, 0x695e, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, + 0x2071, 0x1800, 0x70b6, 0x00ee, 0x7034, 0x9005, 0x1904, 0x8024, + 0x2009, 0x0017, 0x0804, 0x7fd4, 0x908e, 0x0400, 0x1190, 0x7034, + 0x9005, 0x1904, 0x8024, 0x080c, 0x73b3, 0x0120, 0x2009, 0x001d, + 0x0804, 0x7fd4, 0x68dc, 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, + 0x7fd4, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x8024, + 0x2009, 0x0018, 0x0804, 0x7fd4, 0x908e, 0x2010, 0x1120, 0x2009, + 0x0019, 0x0804, 0x7fd4, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, + 0x0804, 0x7fd4, 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, + 0x8024, 0x2009, 0x001b, 0x0804, 0x7fd4, 0x908e, 0x5000, 0x1140, + 0x7034, 0x9005, 0x1904, 0x8024, 0x2009, 0x001c, 0x0804, 0x7fd4, + 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x7fd4, 0x908e, + 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8024, 0x2009, 0x0024, + 0x0804, 0x7fd4, 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, + 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, 0x7fd4, 0x080c, + 0xd934, 0x1904, 0x8024, 0x0804, 0x7fd2, 0x908c, 0xff00, 0x918e, + 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x7fd4, 0x908e, 0x0f00, + 0x1120, 0x2009, 0x0020, 0x0804, 0x7fd4, 0x908e, 0x6104, 0x1530, + 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, + 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, + 0x2124, 0x080c, 0x4b1e, 0x004e, 0x8108, 0x0f04, 0x7f88, 0x9186, + 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, + 0x202b, 0x0000, 0x2009, 0x0023, 0x0804, 0x7fd4, 0x908e, 0x6000, + 0x1120, 0x2009, 0x003f, 0x0804, 0x7fd4, 0x908e, 0x5400, 0x1138, + 0x080c, 0x83c1, 0x1904, 0x8024, 0x2009, 0x0046, 0x04a8, 0x908e, + 0x5500, 0x1148, 0x080c, 0x83e9, 0x1118, 0x2009, 0x0041, 0x0460, + 0x2009, 0x0042, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, + 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, + 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, + 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, + 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, + 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x284b, 0x1904, 0x8027, 0x080c, 0x65b5, + 0x1904, 0x8027, 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x73b3, + 0x01c0, 0x68dc, 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, + 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, 0x687c, 0x9606, 0x1148, + 0x6880, 0x9506, 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb8c2, + 0x0080, 0xb8c0, 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x687c, + 0x9606, 0x1138, 0x6880, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, + 0x0098, 0x080c, 0xae09, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, + 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, + 0x0016, 0x001e, 0x080c, 0xaeda, 0x00ce, 0x00be, 0x0005, 0x001e, + 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, + 0x080c, 0x4b1e, 0x080c, 0xaead, 0x0d90, 0x2b08, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, + 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, + 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, + 0x080c, 0x9140, 0x08a0, 0x080c, 0x32f0, 0x1140, 0x7010, 0x9084, + 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, + 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, + 0x11e8, 0x080c, 0x82bb, 0x0904, 0x80b0, 0x7124, 0x610a, 0x7030, + 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d0, 0x2009, 0x0015, + 0x080c, 0xaeda, 0x04a8, 0x908e, 0x0100, 0x1590, 0x7034, 0x9005, + 0x1578, 0x2009, 0x0016, 0x080c, 0xaeda, 0x0450, 0x9186, 0x0032, + 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, 0x2009, 0x0038, 0x0016, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x284b, 0x11b8, + 0x080c, 0x65b5, 0x11a0, 0xbe12, 0xbd16, 0x080c, 0xae09, 0x0178, + 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0004, 0x7120, 0x610a, + 0x001e, 0x080c, 0xaeda, 0x080c, 0x96a6, 0x0010, 0x00ce, 0x001e, + 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, + 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, + 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x8112, 0x9596, + 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x8112, 0x9596, 0xfffc, + 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019, 0x1837, + 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, + 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, + 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, + 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, + 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, + 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, + 0x8e70, 0x1f04, 0x80e7, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, + 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, + 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x0002, 0x812f, + 0x812f, 0x812f, 0x82cd, 0x812f, 0x8138, 0x8163, 0x81f1, 0x812f, + 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x7817, + 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, 0x96a6, 0x0005, + 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, 0x9c8c, 0x0007, + 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6868, 0x9c02, 0x1290, 0x7008, + 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1150, 0x700c, + 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, + 0xaeda, 0x7817, 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, + 0x96a6, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, 0x0fff, 0x0904, + 0x81c7, 0x7110, 0xd1bc, 0x1904, 0x81c7, 0x7108, 0x700c, 0x2028, + 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b0, 0x81ff, 0x15a0, + 0x9080, 0x3332, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, + 0x9106, 0x0904, 0x81c7, 0x080c, 0x65b5, 0x1904, 0x81c7, 0xbe12, + 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, 0x9294, 0xff00, 0x9286, + 0x0600, 0x11a0, 0x080c, 0xae09, 0x05e8, 0x2b08, 0x7028, 0x604a, + 0x702c, 0x6046, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, + 0x6156, 0x2009, 0x0044, 0x080c, 0xdb94, 0x0408, 0x080c, 0x6989, + 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, 0x80b4, 0x11c0, 0x0898, + 0x080c, 0xae09, 0x2b08, 0x0198, 0x6112, 0x6023, 0x0004, 0x7120, + 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, 0x96a6, 0x7817, + 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, 0x090c, 0x96a6, 0x00ce, + 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x4b1e, 0x080c, 0xaead, 0x0d48, 0x2b08, 0x6112, + 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x6017, 0xf300, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x90f8, 0x080c, 0x96a6, + 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7020, 0x2060, 0x9c84, + 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, 0x6868, 0x9c02, 0x1290, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1150, + 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0045, + 0x080c, 0xaeda, 0x7817, 0x0140, 0x2001, 0x19ef, 0x2004, 0x9005, + 0x090c, 0x96a6, 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, + 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x32f0, + 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, + 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, 0x823d, + 0x823e, 0x823d, 0x823d, 0x829d, 0x82ac, 0x0005, 0x00b6, 0x7110, + 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x829b, 0x700c, 0x7108, + 0x080c, 0x284b, 0x1904, 0x829b, 0x080c, 0x65b5, 0x1904, 0x829b, + 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x01d8, 0x080c, 0x6989, 0x0118, + 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, 0x82bb, 0x00ce, 0x05d8, + 0x080c, 0xae09, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xcfd4, 0x6023, + 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xaeda, 0x0458, + 0x080c, 0x6989, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6991, + 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, 0xae09, 0x2b08, 0x01d8, + 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, + 0x0088, 0x080c, 0xaeda, 0x0078, 0x080c, 0xae09, 0x2b08, 0x0158, + 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, + 0x0001, 0x080c, 0xaeda, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, + 0x00d1, 0x0148, 0x080c, 0x821c, 0x1130, 0x7124, 0x610a, 0x2009, + 0x0089, 0x080c, 0xaeda, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, + 0x0148, 0x080c, 0x821c, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, + 0x080c, 0xaeda, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0007, 0x1158, + 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1218, + 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, + 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007, 0x11b0, 0x9c82, 0x1cd0, + 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, + 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, + 0x2009, 0x0051, 0x080c, 0xaeda, 0x7817, 0x0140, 0x2001, 0x19ef, + 0x2004, 0x9005, 0x090c, 0x96a6, 0x00be, 0x0005, 0x2031, 0x0105, + 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, + 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x0096, + 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05d0, 0x080c, + 0xae09, 0x05b8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x284b, 0x15a0, 0x080c, 0x65b5, 0x1588, + 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xcfd4, + 0x080c, 0x0fff, 0x0510, 0x2900, 0x605a, 0x9006, 0xa802, 0xa866, + 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860, 0x20e8, + 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, 0x6007, + 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xae5f, 0x006e, + 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, + 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x83ab, 0x9186, + 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x83ad, + 0x7030, 0x908e, 0x0400, 0x0904, 0x83ad, 0x908e, 0x6000, 0x05e8, + 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, + 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6947, 0x0588, + 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, + 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, + 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, + 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, + 0x9186, 0x0023, 0x1140, 0x080c, 0x82bb, 0x0128, 0x6004, 0x9086, + 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, + 0x0005, 0x7030, 0x908e, 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, + 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, + 0x0c50, 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, + 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, + 0x2011, 0x027a, 0x080c, 0xbe19, 0x1178, 0xd48c, 0x0148, 0x20a9, + 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xbe19, 0x1120, + 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, + 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, + 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, + 0x2011, 0x0272, 0x080c, 0xbe19, 0x1178, 0xd48c, 0x0148, 0x20a9, + 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xbe19, 0x1120, + 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, + 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, + 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, + 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, + 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, + 0x2071, 0x19f9, 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, + 0x7072, 0x7012, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x7026, 0x702b, + 0xa2a5, 0x7032, 0x7037, 0xa30d, 0x703f, 0xffff, 0x7042, 0x7047, + 0x5581, 0x704a, 0x705b, 0x859a, 0x080c, 0x1018, 0x090c, 0x0dd5, + 0x2900, 0x703a, 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, + 0x0005, 0x2071, 0x19f9, 0x1d04, 0x84e8, 0x2091, 0x6000, 0x700c, + 0x8001, 0x700e, 0x1530, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, + 0x85df, 0x2001, 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, + 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, + 0x0dd5, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, + 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, + 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, + 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, + 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, + 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, + 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0xa42a, + 0x0010, 0x7034, 0x080f, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, + 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, + 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, + 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, + 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, + 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, + 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, + 0x7004, 0x0002, 0x8510, 0x8511, 0x852d, 0x00e6, 0x2071, 0x19f9, + 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0x19f9, 0x701c, 0x9206, 0x1120, + 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0x19f9, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, + 0x0005, 0x00b6, 0x7110, 0x080c, 0x6616, 0x1168, 0xb888, 0x8001, + 0x0250, 0xb88a, 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, + 0x96a6, 0x001e, 0x012e, 0x8108, 0x9182, 0x0800, 0x0218, 0x900e, + 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x7014, 0x2060, 0x0126, + 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, + 0x080c, 0xce65, 0x6018, 0x9005, 0x0558, 0x8001, 0x601a, 0x1540, + 0x6120, 0x9186, 0x0003, 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, + 0x0009, 0x11e0, 0x611c, 0xd1c4, 0x1100, 0x080c, 0xcb5a, 0x01b0, + 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, + 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, 0x0110, 0x080c, 0xc846, + 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, + 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x19f9, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, + 0x1a02, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19f9, 0x7132, + 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x1a05, 0x2013, 0x0000, + 0x0005, 0x00e6, 0x2071, 0x19f9, 0x711a, 0x721e, 0x700b, 0x0009, + 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, 0x8000, 0x7056, 0x2001, + 0x1a07, 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, 0x7068, 0xa09a, + 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, 0xa08e, 0x080c, 0x10e9, + 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, 0x00a6, 0x00b6, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x8459, 0x015e, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, + 0x000e, 0x0005, 0x00e6, 0x2071, 0x19f9, 0x7172, 0x7276, 0x706f, + 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19f9, 0x7074, + 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x0016, + 0x00c6, 0x2009, 0xfff4, 0x210d, 0x2061, 0x0100, 0x60f0, 0x9100, + 0x60f3, 0x0000, 0x2009, 0xfff4, 0x200f, 0x1220, 0x8108, 0x2105, + 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x2061, 0x1a70, + 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, + 0x1a70, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, + 0x1150, 0x00c6, 0x2061, 0x1a70, 0x6014, 0x00ce, 0x9005, 0x1130, + 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, + 0x0904, 0x868d, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8666, 0x2009, + 0x0006, 0x080c, 0x86ba, 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, + 0x08b0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, + 0x1904, 0x86b4, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, + 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138, 0x87ff, + 0x1120, 0x2009, 0x0043, 0x0804, 0xaeda, 0x0005, 0x87ff, 0x1de8, + 0x2009, 0x0042, 0x0804, 0xaeda, 0x6110, 0x00b6, 0x2158, 0xb900, + 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, + 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, + 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x86b4, 0x908c, + 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, + 0x1727, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, + 0xaeda, 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, + 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, + 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, + 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0xaeda, 0x0005, + 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0xaeda, + 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, + 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, + 0x2009, 0x0001, 0x0096, 0x080c, 0xcb5a, 0x0518, 0x6014, 0x2048, + 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, + 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a70, 0x6200, + 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, + 0x6acf, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, 0x8603, + 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a70, 0x6000, + 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, + 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, + 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x1923, 0x7003, 0x0006, + 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x080c, 0x1018, + 0x090c, 0x0dd5, 0xa867, 0x0006, 0xa86b, 0x0001, 0xa8ab, 0xdcb0, + 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, 0x0005, 0x0096, + 0x00e6, 0x2071, 0x1923, 0x702c, 0x2048, 0x6a2c, 0x721e, 0x6b30, + 0x7322, 0x6834, 0x7026, 0xa896, 0x6838, 0x702a, 0xa89a, 0x6824, + 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148, + 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208, + 0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, 0x0178, 0xc084, 0x7007, + 0x0001, 0x700f, 0x0000, 0x0006, 0x2009, 0x181d, 0x2104, 0x9082, + 0x0007, 0x2009, 0x1ac7, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, + 0x2001, 0x003b, 0x080c, 0x15f0, 0x9006, 0x2071, 0x193c, 0x7002, + 0x7006, 0x702a, 0x00ee, 0x009e, 0x0005, 0x00e6, 0x0126, 0x0156, + 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, 0x2001, 0x0008, 0x910a, + 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, + 0x876d, 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877, 0x20a9, 0x0007, + 0x00c6, 0x080c, 0xae09, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, + 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, 0x080c, 0x88f3, 0x012e, + 0x1f04, 0x8779, 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, + 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, 0x0096, 0x0086, 0x0056, + 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, + 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, + 0x000a, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0x2900, 0x6016, 0x2058, + 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, 0xa87a, 0xa8aa, 0xa887, + 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, 0x7010, 0xa89e, 0xae8a, + 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, 0x0160, 0x080c, 0x0fff, + 0x090c, 0x0dd5, 0xad66, 0x2b00, 0xa802, 0x2900, 0xb806, 0x2058, + 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, 0x008e, 0x009e, 0x00be, + 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, 0x1923, 0x7004, 0x004b, + 0x700c, 0x0002, 0x87e5, 0x87de, 0x87de, 0x0005, 0x87ef, 0x8850, + 0x8850, 0x8850, 0x8851, 0x8862, 0x8862, 0x700c, 0x0cba, 0x0126, + 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, 0x0128, 0x78a0, 0x79a0, + 0x9106, 0x1904, 0x8843, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x0130, + 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, 0x0ca8, 0x012e, 0x7018, + 0x910a, 0x1130, 0x7030, 0x9005, 0x05a8, 0x080c, 0x8891, 0x0490, + 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, + 0x2001, 0x1888, 0x2014, 0x2001, 0x1935, 0x2004, 0x9100, 0x9202, + 0x0e48, 0x080c, 0x89dd, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, + 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, 0x080c, 0x8ae6, 0x2100, + 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, + 0x1a17, 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, + 0x1108, 0x1de8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x0130, + 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, 0x0ca8, 0x012e, 0x0005, + 0x0005, 0x700c, 0x0002, 0x8856, 0x8859, 0x8858, 0x080c, 0x87ed, + 0x0005, 0x8001, 0x700e, 0x0096, 0x702c, 0x2048, 0xa974, 0x009e, + 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c, 0x2048, 0x7018, 0x9100, + 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e, 0x7020, 0xa892, 0x9006, + 0x0068, 0x0006, 0x080c, 0x8ae6, 0x2100, 0xaa8c, 0x9210, 0xaa8e, + 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x2f08, + 0x9188, 0x0028, 0x200a, 0x701a, 0x0005, 0x00e6, 0x2071, 0x1923, + 0x700c, 0x0002, 0x888f, 0x888f, 0x888d, 0x700f, 0x0001, 0x00ee, + 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, 0x9005, 0x0508, 0x2078, + 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x88fc, + 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193c, 0x080c, 0x8943, 0x00ee, + 0x0178, 0x0096, 0x080c, 0x1018, 0x2900, 0x009e, 0x0148, 0xa8aa, + 0x04b9, 0x0041, 0x2001, 0x1946, 0x2003, 0x0000, 0x012e, 0x08c8, + 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6, 0x2940, 0x2650, + 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, 0x000f, 0x2068, 0x9d88, + 0x209d, 0x2165, 0x0056, 0x2029, 0x0000, 0x080c, 0x8a6b, 0x080c, + 0x2055, 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f, 0x2004, 0xa88a, + 0x080c, 0x1727, 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8952, 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, + 0x7030, 0x9005, 0x0138, 0x2078, 0x780c, 0x7032, 0x2001, 0x1946, + 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, 0x1923, 0x7030, 0x600e, + 0x2c00, 0x7032, 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, + 0x8bc5, 0x2005, 0x906d, 0x090c, 0x0dd5, 0x9b80, 0x8bbd, 0x2005, + 0x9065, 0x090c, 0x0dd5, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, + 0x9102, 0x02f0, 0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, + 0x6804, 0xd094, 0x0148, 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, + 0x2011, 0x8026, 0x080c, 0x4b1e, 0x684c, 0x0096, 0x904d, 0x090c, + 0x0dd5, 0xa804, 0x8000, 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, + 0x6854, 0xd08c, 0x1d08, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, + 0x4b1e, 0x684c, 0x0096, 0x904d, 0x090c, 0x0dd5, 0xa800, 0x8000, + 0xa802, 0x009e, 0x0888, 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, + 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, + 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, 0x090c, 0x0dd5, 0x781c, + 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, 0x0dd5, 0x2069, 0x193c, + 0x6804, 0x9080, 0x193e, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, + 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x193e, 0x2003, 0x0000, + 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, + 0x0096, 0x2048, 0x9005, 0x190c, 0x1031, 0x009e, 0xa8ab, 0x0000, + 0x080c, 0x0fb1, 0x080c, 0xae5f, 0x00ce, 0x009e, 0x0005, 0x6020, + 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, + 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, + 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, 0x8cfa, 0x00be, 0x6013, + 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, + 0x1927, 0x210c, 0xd194, 0x0005, 0x00e6, 0x2071, 0x1923, 0x7110, + 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, + 0x003b, 0x080c, 0x15f0, 0x00ee, 0x0005, 0x0096, 0x00d6, 0x9006, + 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, + 0x702f, 0x0000, 0x080c, 0x8b45, 0x0170, 0x080c, 0x8b7a, 0x0158, + 0x2900, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, + 0x00de, 0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, + 0x00d6, 0x00c6, 0x2071, 0x1930, 0x721c, 0x2100, 0x9202, 0x1618, + 0x080c, 0x8b7a, 0x090c, 0x0dd5, 0x7018, 0x9005, 0x1160, 0x2900, + 0x7002, 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, + 0x7012, 0x701e, 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, + 0xa803, 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, + 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, + 0x00ee, 0x0005, 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1930, 0x7300, 0x831f, 0x831e, 0x831e, + 0x9384, 0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, + 0x080c, 0x8ae6, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, + 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, + 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x8aef, 0x2130, + 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, + 0x9600, 0x2008, 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, + 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x89dd, 0x002e, + 0x7000, 0x2048, 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, + 0x2500, 0x9212, 0x1904, 0x8a1c, 0x012e, 0x00ee, 0x014e, 0x013e, + 0x015e, 0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, + 0x8000, 0x9580, 0x8bbd, 0x2005, 0x9075, 0x090c, 0x0dd5, 0x080c, + 0x8ac1, 0x012e, 0x9580, 0x8bb9, 0x2005, 0x9075, 0x090c, 0x0dd5, + 0x0156, 0x0136, 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, + 0x9384, 0x003f, 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, + 0x20e8, 0xa95c, 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, + 0x2e0c, 0x2d00, 0x0002, 0x8aab, 0x8aab, 0x8aad, 0x8aab, 0x8aad, + 0x8aab, 0x8aab, 0x8aab, 0x8aab, 0x8aab, 0x8ab3, 0x8aab, 0x8ab3, + 0x8aab, 0x8aab, 0x8aab, 0x080c, 0x0dd5, 0x4104, 0x20a9, 0x0002, + 0x4002, 0x4003, 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, + 0x01de, 0x014e, 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, + 0x0005, 0x0096, 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, + 0x810c, 0x9188, 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, + 0x7008, 0x2048, 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x8b89, + 0x009e, 0xa807, 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, + 0x700f, 0x0000, 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, + 0x810b, 0x2100, 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, + 0x0026, 0x2100, 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, + 0x8108, 0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, + 0x0cd8, 0x2d00, 0x90b8, 0x0008, 0x690c, 0x6810, 0x2019, 0x0001, + 0x2031, 0x8b2f, 0x9112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, + 0x6808, 0x9005, 0x0108, 0x8318, 0x233a, 0x6804, 0xd084, 0x2300, + 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, 0x0a67, 0x8420, + 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, 0x0002, 0x0967, + 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, 0x0cd0, 0x6c1a, + 0x2d00, 0x90b8, 0x0007, 0x00e6, 0x2071, 0x1800, 0x7128, 0x6810, + 0x2019, 0x0001, 0x910a, 0x0118, 0x0210, 0x8318, 0x0cd8, 0x2031, + 0x8b42, 0x0870, 0x6c16, 0x00ee, 0x0005, 0x0096, 0x0046, 0x0126, + 0x2091, 0x8000, 0x2b00, 0x9080, 0x8bc1, 0x2005, 0x9005, 0x090c, + 0x0dd5, 0x2004, 0x90a0, 0x000a, 0x080c, 0x1018, 0x01d0, 0x2900, + 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x080c, 0x1018, 0x0188, + 0x7024, 0xa802, 0xa807, 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, + 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, + 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2048, 0xac00, 0x080c, 0x1031, + 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, + 0x0130, 0xa800, 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, + 0x012e, 0x0005, 0x0096, 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, + 0x2048, 0xa800, 0x0006, 0x080c, 0x1031, 0x000e, 0x0cb8, 0x009e, + 0x0005, 0x0096, 0x7008, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, + 0x080c, 0x1031, 0x000e, 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, + 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, + 0x0005, 0x1a63, 0x0000, 0x0000, 0x0000, 0x1930, 0x0000, 0x0000, + 0x0000, 0x1888, 0x0000, 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, + 0x0000, 0x00e6, 0x00c6, 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, + 0x1877, 0x080c, 0x8ce5, 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, + 0x8cba, 0xb814, 0xa06e, 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, + 0x0003, 0xa07e, 0xa834, 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, + 0x0118, 0xa078, 0xc085, 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, + 0x908a, 0x0019, 0x1a0c, 0x0dd5, 0x2020, 0x2050, 0x2940, 0xa864, + 0x90bc, 0x00ff, 0x908c, 0x000f, 0x91e0, 0x209d, 0x2c65, 0x9786, + 0x0024, 0x2c05, 0x1590, 0x908a, 0x0036, 0x1a0c, 0x0dd5, 0x9082, + 0x001b, 0x0002, 0x8c25, 0x8c25, 0x8c27, 0x8c25, 0x8c25, 0x8c25, + 0x8c29, 0x8c25, 0x8c25, 0x8c25, 0x8c2b, 0x8c25, 0x8c25, 0x8c25, + 0x8c2d, 0x8c25, 0x8c25, 0x8c25, 0x8c2f, 0x8c25, 0x8c25, 0x8c25, + 0x8c31, 0x8c25, 0x8c25, 0x8c25, 0x8c33, 0x080c, 0x0dd5, 0xa180, + 0x04b8, 0xa190, 0x04a8, 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, + 0x0478, 0xa1d0, 0x0468, 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, + 0x0dd5, 0x9082, 0x001b, 0x0002, 0x8c57, 0x8c55, 0x8c55, 0x8c55, + 0x8c55, 0x8c55, 0x8c59, 0x8c55, 0x8c55, 0x8c55, 0x8c55, 0x8c55, + 0x8c5b, 0x8c55, 0x8c55, 0x8c55, 0x8c55, 0x8c55, 0x8c5d, 0x8c55, + 0x8c55, 0x8c55, 0x8c55, 0x8c55, 0x8c5f, 0x080c, 0x0dd5, 0xa180, + 0x0038, 0xa198, 0x0028, 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, + 0x2600, 0x0002, 0x8c7b, 0x8c7d, 0x8c7f, 0x8c81, 0x8c83, 0x8c85, + 0x8c87, 0x8c89, 0x8c8b, 0x8c8d, 0x8c8f, 0x8c91, 0x8c93, 0x8c95, + 0x8c97, 0x8c99, 0x8c9b, 0x8c9d, 0x8c9f, 0x8ca1, 0x8ca3, 0x8ca5, + 0x8ca7, 0x8ca9, 0x8cab, 0x080c, 0x0dd5, 0xb9e2, 0x0468, 0xb9de, + 0x0458, 0xb9da, 0x0448, 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, + 0x0418, 0xb9ca, 0x0408, 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, + 0x00d8, 0xb9ba, 0x00c8, 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, + 0x0098, 0xb9aa, 0x0088, 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, + 0x0058, 0xb99a, 0x0048, 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, + 0x0018, 0xb98a, 0x0008, 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, + 0x2055, 0x090c, 0x0dd5, 0x0804, 0x8bff, 0x00ae, 0x00be, 0x00ce, + 0x00ee, 0x0005, 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, + 0x9006, 0x0804, 0x8be1, 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, + 0xb810, 0x9005, 0x01b0, 0x2001, 0x1924, 0x2004, 0x9005, 0x0188, + 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, + 0xbba0, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4b1e, 0x004e, + 0x003e, 0x00be, 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, + 0x910a, 0xa936, 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0238, + 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, 0x0cd8, 0xaa8a, + 0xa26a, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, + 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, + 0x7818, 0xd094, 0x1da0, 0xb8ac, 0x9005, 0x01b8, 0x2068, 0x2079, + 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, 0xb8ae, 0x0060, 0x9106, + 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, 0x0dd5, 0x2068, + 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, 0x781b, + 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, 0x0096, + 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, 0x01ff, + 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, 0x1f04, + 0x8d3a, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90, + 0xb8ac, 0x9005, 0x01d0, 0x2060, 0x600c, 0xb8ae, 0x6003, 0x0004, + 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, 0x6014, 0x2048, + 0xa88b, 0x0000, 0xa8a8, 0xa8ab, 0x0000, 0x904d, 0x090c, 0x0dd5, + 0x080c, 0x1031, 0x080c, 0x88f3, 0x0c18, 0x2071, 0x0300, 0x701b, + 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x009e, 0x00de, 0x00ee, + 0x0005, 0x00c6, 0x00b6, 0x0016, 0x0006, 0x0156, 0x080c, 0x284b, + 0x015e, 0x11b0, 0x080c, 0x65b5, 0x190c, 0x0dd5, 0x000e, 0x001e, + 0xb912, 0xb816, 0x080c, 0xae09, 0x0140, 0x2b00, 0x6012, 0x6023, + 0x0001, 0x2009, 0x0001, 0x080c, 0xaeda, 0x00be, 0x00ce, 0x0005, + 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0dd5, 0x0013, 0x006e, 0x0005, 0x8dac, 0x8dac, 0x8dac, 0x8dae, + 0x8dff, 0x8dac, 0x8dac, 0x8dac, 0x8e62, 0x8dac, 0x8e9f, 0x8dac, + 0x8dac, 0x8dac, 0x8dac, 0x8dac, 0x080c, 0x0dd5, 0x9182, 0x0040, + 0x0002, 0x8dc1, 0x8dc1, 0x8dc1, 0x8dc1, 0x8dc1, 0x8dc1, 0x8dc1, + 0x8dc1, 0x8dc1, 0x8dc3, 0x8dd8, 0x8dc1, 0x8dc1, 0x8dc1, 0x8dc1, + 0x8deb, 0x080c, 0x0dd5, 0x0096, 0x080c, 0x9656, 0x080c, 0x97d4, + 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, + 0x0500, 0x00be, 0x080c, 0x6a9a, 0x080c, 0xae5f, 0x009e, 0x0005, + 0x080c, 0x9656, 0x00d6, 0x6114, 0x080c, 0xcb5a, 0x0130, 0x0096, + 0x6114, 0x2148, 0x080c, 0x6c94, 0x009e, 0x00de, 0x080c, 0xae5f, + 0x080c, 0x97d4, 0x0005, 0x080c, 0x9656, 0x080c, 0x31cc, 0x6114, + 0x0096, 0x2148, 0x080c, 0xcb5a, 0x0120, 0xa87b, 0x0029, 0x080c, + 0x6c94, 0x009e, 0x080c, 0xae5f, 0x080c, 0x97d4, 0x0005, 0x601b, + 0x0000, 0x9182, 0x0040, 0x0096, 0x0002, 0x8e1a, 0x8e1a, 0x8e1a, + 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1c, 0x8e1a, 0x8e1a, + 0x8e1a, 0x8e5e, 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1a, 0x8e1a, + 0x8e22, 0x8e1a, 0x080c, 0x0dd5, 0x6114, 0x2148, 0xa938, 0x918e, + 0xffff, 0x05e0, 0x00e6, 0x6114, 0x2148, 0x080c, 0x8bc9, 0x0096, + 0xa8a8, 0x2048, 0x080c, 0x6a32, 0x009e, 0xa8ab, 0x0000, 0x6010, + 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x8cfa, 0x00be, 0xae88, + 0x00b6, 0x2059, 0x0000, 0x080c, 0x88fc, 0x00be, 0x01e0, 0x2071, + 0x193c, 0x080c, 0x8943, 0x01b8, 0x9086, 0x0001, 0x1128, 0x2001, + 0x1946, 0x2004, 0x9005, 0x1178, 0x0096, 0x080c, 0x0fff, 0x2900, + 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, 0x080c, 0x88ba, 0x00fe, + 0x00ee, 0x009e, 0x0005, 0x080c, 0x88f3, 0x0cd0, 0x080c, 0x8f0c, + 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, 0x0002, 0x8e76, 0x8e76, + 0x8e76, 0x8e78, 0x8e76, 0x8e76, 0x8e76, 0x8e9d, 0x8e76, 0x8e76, + 0x8e76, 0x8e76, 0x8e76, 0x8e76, 0x8e76, 0x8e76, 0x080c, 0x0dd5, + 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa8ac, 0xa846, 0xa8b0, + 0xa84a, 0xa837, 0x0000, 0xa83b, 0x0000, 0xa884, 0x9092, 0x199a, + 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, + 0x2c10, 0x080c, 0x1bba, 0x080c, 0x915d, 0x0126, 0x2091, 0x8000, + 0x080c, 0x97d4, 0x012e, 0x009e, 0x0005, 0x080c, 0x0dd5, 0x080c, + 0x9656, 0x080c, 0x97d4, 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, + 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6c94, 0x080c, + 0xae5f, 0x009e, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, + 0x0096, 0x0013, 0x009e, 0x0005, 0x8ecc, 0x8ecc, 0x8ecc, 0x8ece, + 0x8edf, 0x8ecc, 0x8ecc, 0x8ecc, 0x8ecc, 0x8ecc, 0x8ecc, 0x8ecc, + 0x8ecc, 0x8ecc, 0x8ecc, 0x8ecc, 0x080c, 0x0dd5, 0x080c, 0xa7b7, + 0x6114, 0x2148, 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, + 0x0500, 0x00be, 0x080c, 0x6c94, 0x080c, 0xae5f, 0x0005, 0x0461, + 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x0096, 0x0013, + 0x009e, 0x0005, 0x8efa, 0x8efa, 0x8efa, 0x8efc, 0x8f0c, 0x8efa, + 0x8efa, 0x8efa, 0x8efa, 0x8efa, 0x8efa, 0x8efa, 0x8efa, 0x8efa, + 0x8efa, 0x8efa, 0x080c, 0x0dd5, 0x0036, 0x00e6, 0x2071, 0x19e6, + 0x703c, 0x9c06, 0x1120, 0x2019, 0x0000, 0x080c, 0xa5c8, 0x080c, + 0xa7b7, 0x00ee, 0x003e, 0x0005, 0x00f6, 0x00e6, 0x601b, 0x0000, + 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, + 0x8cfa, 0x00be, 0x2071, 0x193c, 0x080c, 0x8943, 0x0160, 0x2001, + 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x88ba, + 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, + 0x080c, 0x1031, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x88f3, 0x0c80, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x187a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, + 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, + 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, + 0x1f04, 0x8f51, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, + 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, + 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, + 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, + 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, + 0x1220, 0x1f04, 0x8f7b, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, + 0x8f7b, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, + 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, + 0x0126, 0x2091, 0x2800, 0x2079, 0x19e6, 0x012e, 0x00d6, 0x2069, + 0x19e6, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, + 0x2069, 0x0200, 0x080c, 0xab1a, 0x0401, 0x080c, 0xab05, 0x00e9, + 0x080c, 0xab08, 0x00d1, 0x080c, 0xab0b, 0x00b9, 0x080c, 0xab0e, + 0x00a1, 0x080c, 0xab11, 0x0089, 0x080c, 0xab14, 0x0071, 0x080c, + 0xab17, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, + 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, + 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, + 0x7804, 0x9084, 0x0007, 0x0002, 0x8fee, 0x9012, 0x9051, 0x8ff4, + 0x9012, 0x8fee, 0x8fec, 0x8fec, 0x080c, 0x0dd5, 0x080c, 0x857f, + 0x080c, 0x96a6, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, + 0x0005, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x7828, 0x9092, 0x00c8, + 0x1228, 0x8000, 0x782a, 0x080c, 0x5ed6, 0x0c88, 0x62c0, 0x080c, + 0xac56, 0x080c, 0x5e96, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, + 0x0000, 0x0c28, 0x080c, 0x857f, 0x6220, 0xd2a4, 0x0160, 0x782b, + 0x0000, 0x7824, 0x9065, 0x090c, 0x0dd5, 0x2009, 0x0013, 0x080c, + 0xaeda, 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0dd5, + 0x7828, 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, + 0x2bb2, 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, + 0x0dd5, 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x96a6, + 0x0c00, 0x080c, 0xa26b, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, + 0xac56, 0x080c, 0xea39, 0x2009, 0x0014, 0x080c, 0xaeda, 0x00ce, + 0x0880, 0x2001, 0x1a02, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0dd5, 0x2009, 0x0013, - 0x080c, 0xaeec, 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, - 0x0dd5, 0x7828, 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, - 0x080c, 0x2ba7, 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, - 0x090c, 0x0dd5, 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, - 0x9687, 0x0c00, 0x080c, 0xa250, 0x08e8, 0x2011, 0x0130, 0x2214, - 0x080c, 0xac68, 0x080c, 0xea1f, 0x2009, 0x0014, 0x080c, 0xaeec, - 0x00ce, 0x0880, 0x2001, 0x1a02, 0x2003, 0x0000, 0x62c0, 0x82ff, - 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0dd5, 0x2009, - 0x0013, 0x080c, 0xaf3e, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, - 0x7824, 0x9005, 0x090c, 0x0dd5, 0x7828, 0x9092, 0xc350, 0x1648, - 0x8000, 0x782a, 0x00de, 0x00ce, 0x00be, 0x080c, 0x2ba7, 0x02f0, - 0x00b6, 0x00c6, 0x00d6, 0x781c, 0x905d, 0x090c, 0x0dd5, 0xb800, - 0xc0dc, 0xb802, 0x7924, 0x2160, 0x080c, 0xae71, 0xb93c, 0x81ff, - 0x090c, 0x0dd5, 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, - 0x00de, 0x00ce, 0x00be, 0x080c, 0x9687, 0x0868, 0x080c, 0xa250, - 0x0850, 0x2011, 0x0130, 0x2214, 0x080c, 0xac68, 0x080c, 0xea1f, - 0x7824, 0x9065, 0x2009, 0x0014, 0x080c, 0xaeec, 0x00de, 0x00ce, - 0x00be, 0x0804, 0x9043, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, - 0x190c, 0x1eb6, 0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, - 0x60c4, 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, - 0x080c, 0xaeec, 0x00ce, 0x0005, 0x2011, 0x1a05, 0x2013, 0x0000, - 0x0cc8, 0x793c, 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, - 0x8108, 0x7946, 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, - 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, - 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, - 0x2009, 0x004a, 0x080c, 0xaeec, 0x0868, 0x7848, 0xc085, 0x784a, - 0x0848, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, - 0x0000, 0x2c08, 0x2061, 0x19e6, 0x6020, 0x8000, 0x6022, 0x6010, - 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, - 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, - 0x19e6, 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, - 0x0001, 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, 0x9687, 0x00de, - 0x0005, 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, - 0x0000, 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, - 0x2069, 0x19e6, 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, - 0x08d8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, - 0x0000, 0x2c08, 0x2061, 0x19e6, 0x6020, 0x8000, 0x6022, 0x6008, - 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, - 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, - 0x0000, 0x2c08, 0x2061, 0x19e6, 0x6034, 0x9005, 0x0130, 0x9080, - 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, - 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, - 0x2071, 0x19e6, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, - 0x0904, 0x91cd, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x91c8, - 0x87ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x91c8, 0x703c, 0x9c06, - 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0xa5b7, 0x7033, 0x0000, - 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, - 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, - 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, - 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0xcb4a, 0x01f0, 0x6014, 0x2048, 0x6020, - 0x9086, 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0xa7bd, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, - 0x080c, 0xce3e, 0x080c, 0xe929, 0x080c, 0x6c86, 0x007e, 0x003e, - 0x001e, 0x080c, 0xcd33, 0x080c, 0xaea2, 0x00ce, 0x0804, 0x9167, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x9167, 0x85ff, 0x0120, 0x0036, - 0x080c, 0x97b5, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, - 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, - 0x0076, 0x080c, 0xe929, 0x080c, 0xe572, 0x007e, 0x003e, 0x001e, - 0x0890, 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, - 0x0036, 0x0076, 0x080c, 0x6c86, 0x080c, 0xae71, 0x007e, 0x003e, - 0x001e, 0x0818, 0x6020, 0x9086, 0x000a, 0x0904, 0x91b2, 0x0804, - 0x91ab, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, - 0x0126, 0x2091, 0x8000, 0x2079, 0x19e6, 0x7838, 0x9065, 0x0904, - 0x925e, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, - 0x0036, 0x2019, 0x0001, 0x080c, 0xa5b7, 0x7833, 0x0000, 0x901e, - 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xcb4a, 0x0548, - 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, - 0x0002, 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1987, - 0x2004, 0x6042, 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0xa7bd, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c7a, 0x080c, - 0xcd33, 0x080c, 0xaea2, 0x000e, 0x0804, 0x9216, 0x7e3a, 0x7e36, - 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xe572, 0x0c50, 0x6020, - 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x6c86, 0x080c, 0xae71, - 0x0c10, 0x6020, 0x9086, 0x000a, 0x09a8, 0x0868, 0x0016, 0x0026, - 0x0086, 0x9046, 0x0099, 0x080c, 0x9367, 0x008e, 0x002e, 0x001e, - 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e6, 0x2091, 0x8000, 0x080c, - 0x93fe, 0x080c, 0x948c, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e6, 0x7614, 0x2660, 0x2678, 0x8cff, - 0x0904, 0x932c, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x9327, - 0x88ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x9327, 0x7024, 0x9c06, - 0x1558, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x8562, - 0x080c, 0xa274, 0x68c3, 0x0000, 0x080c, 0xa7bd, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, - 0x0009, 0x630a, 0x0804, 0x9327, 0x7014, 0x9c36, 0x1110, 0x660c, - 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xcb4a, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, - 0xcd50, 0x1118, 0x080c, 0xb824, 0x0098, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xce3e, 0x080c, - 0xe929, 0x080c, 0x6c86, 0x008e, 0x003e, 0x001e, 0x080c, 0xcd33, - 0x080c, 0xaea2, 0x080c, 0xa693, 0x00ce, 0x0804, 0x92a7, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x92a7, 0x012e, 0x000e, 0x001e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xe929, - 0x080c, 0xe572, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xb824, - 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0904, 0x930d, 0x9086, 0x008b, 0x0904, 0x930d, 0x0840, - 0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9320, 0x00b6, - 0x00a6, 0x0096, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, - 0x1000, 0x2004, 0x905d, 0x0904, 0x93f7, 0x00f6, 0x00e6, 0x00d6, - 0x0066, 0x2071, 0x19e6, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a, - 0x701c, 0x9b06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, - 0x761e, 0xb858, 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110, - 0x2900, 0xb05a, 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4, - 0xc0dc, 0xb802, 0x080c, 0x653a, 0x0904, 0x93f3, 0x7624, 0x86ff, - 0x0904, 0x93e2, 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x8562, 0x080c, - 0xa274, 0x68c3, 0x0000, 0x080c, 0xa7bd, 0x7027, 0x0000, 0x0036, + 0x080c, 0xaf2c, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, + 0x9005, 0x090c, 0x0dd5, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, + 0x782a, 0x00de, 0x00ce, 0x00be, 0x080c, 0x2bb2, 0x02f0, 0x00b6, + 0x00c6, 0x00d6, 0x781c, 0x905d, 0x090c, 0x0dd5, 0xb800, 0xc0dc, + 0xb802, 0x7924, 0x2160, 0x080c, 0xae5f, 0xb93c, 0x81ff, 0x090c, + 0x0dd5, 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, + 0x00ce, 0x00be, 0x080c, 0x96a6, 0x0868, 0x080c, 0xa26b, 0x0850, + 0x2011, 0x0130, 0x2214, 0x080c, 0xac56, 0x080c, 0xea39, 0x7824, + 0x9065, 0x2009, 0x0014, 0x080c, 0xaeda, 0x00de, 0x00ce, 0x00be, + 0x0804, 0x9062, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, + 0x1ec1, 0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, 0x60c4, + 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, + 0xaeda, 0x00ce, 0x0005, 0x2011, 0x1a05, 0x2013, 0x0000, 0x0cc8, + 0x793c, 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, 0x8108, + 0x7946, 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, + 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x793c, + 0x9188, 0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, + 0x1984, 0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, 0x2009, + 0x004a, 0x080c, 0xaeda, 0x0868, 0x7848, 0xc085, 0x784a, 0x0848, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19e6, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19e6, + 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, + 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, 0x96a6, 0x00de, 0x0005, + 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, + 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, + 0x19e6, 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19e6, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19e6, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, + 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, + 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, + 0x19e6, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, + 0x91ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x91e7, 0x87ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x91e7, 0x703c, 0x9c06, 0x1178, + 0x0036, 0x2019, 0x0001, 0x080c, 0xa5c8, 0x7033, 0x0000, 0x9006, + 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, + 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xcb5a, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, + 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0xa7a7, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0xce4e, 0x080c, 0xe943, 0x080c, 0x6c94, 0x007e, 0x003e, 0x001e, + 0x080c, 0xcd43, 0x080c, 0xae90, 0x00ce, 0x0804, 0x9186, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x9186, 0x85ff, 0x0120, 0x0036, 0x080c, + 0x97d4, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, + 0x080c, 0xe943, 0x080c, 0xe58c, 0x007e, 0x003e, 0x001e, 0x0890, + 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, + 0x0076, 0x080c, 0x6c94, 0x080c, 0xae5f, 0x007e, 0x003e, 0x001e, + 0x0818, 0x6020, 0x9086, 0x000a, 0x0904, 0x91d1, 0x0804, 0x91ca, + 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, + 0x2091, 0x8000, 0x2079, 0x19e6, 0x7838, 0x9065, 0x0904, 0x927d, + 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, + 0x2019, 0x0001, 0x080c, 0xa5c8, 0x7833, 0x0000, 0x901e, 0x7b3e, + 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xcb5a, 0x0548, 0x6014, + 0x2048, 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, + 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1987, 0x2004, + 0x6042, 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0xa7a7, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c88, 0x080c, 0xcd43, + 0x080c, 0xae90, 0x000e, 0x0804, 0x9235, 0x7e3a, 0x7e36, 0x012e, + 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, + 0x9086, 0x0006, 0x1118, 0x080c, 0xe58c, 0x0c50, 0x6020, 0x9086, + 0x0009, 0x1130, 0xab7a, 0x080c, 0x6c94, 0x080c, 0xae5f, 0x0c10, + 0x6020, 0x9086, 0x000a, 0x09a8, 0x0868, 0x0016, 0x0026, 0x0086, + 0x9046, 0x0099, 0x080c, 0x9386, 0x008e, 0x002e, 0x001e, 0x0005, + 0x00f6, 0x0126, 0x2079, 0x19e6, 0x2091, 0x8000, 0x080c, 0x941d, + 0x080c, 0x94ab, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x19e6, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, + 0x934b, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x9346, 0x88ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x9346, 0x7024, 0x9c06, 0x1558, + 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x857f, 0x080c, + 0xa28f, 0x68c3, 0x0000, 0x080c, 0xa7a7, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xaea2, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x939a, 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0xce3e, 0x080c, 0xe929, 0x080c, 0x6c86, 0x080c, - 0xa693, 0x0804, 0x939a, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, - 0x000e, 0x00ce, 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x945f, - 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1570, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x8562, 0x080c, 0xa274, - 0x68c3, 0x0000, 0x080c, 0xa7bd, 0x7827, 0x0000, 0x0036, 0x2069, + 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, + 0x630a, 0x0804, 0x9346, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, + 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, + 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xcd60, + 0x1118, 0x080c, 0xb821, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, + 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xce4e, 0x080c, 0xe943, + 0x080c, 0x6c94, 0x008e, 0x003e, 0x001e, 0x080c, 0xcd43, 0x080c, + 0xae90, 0x080c, 0xa67d, 0x00ce, 0x0804, 0x92c6, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x92c6, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xe943, 0x080c, + 0xe58c, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xb821, 0x6020, + 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, + 0x0904, 0x932c, 0x9086, 0x008b, 0x0904, 0x932c, 0x0840, 0x6020, + 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, + 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x933f, 0x00b6, 0x00a6, + 0x0096, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, + 0x2004, 0x905d, 0x0904, 0x9416, 0x00f6, 0x00e6, 0x00d6, 0x0066, + 0x2071, 0x19e6, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a, 0x701c, + 0x9b06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, + 0xb858, 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110, 0x2900, + 0xb05a, 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4, 0xc0dc, + 0xb802, 0x080c, 0x6548, 0x0904, 0x9412, 0x7624, 0x86ff, 0x0904, + 0x9401, 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, 0x2069, + 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x857f, 0x080c, 0xa28f, + 0x68c3, 0x0000, 0x080c, 0xa7a7, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x080c, 0x6913, 0x1520, - 0x6003, 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, - 0xcb48, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xcd50, - 0x1118, 0x080c, 0xb824, 0x0060, 0x080c, 0x6913, 0x1168, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c86, 0x080c, 0xcd33, - 0x080c, 0xaea2, 0x080c, 0xa693, 0x000e, 0x0804, 0x9405, 0x7e16, - 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1118, 0x080c, 0xe572, 0x0c50, 0x080c, 0xb824, - 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, - 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, - 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0066, 0x0096, 0x00b6, - 0x00c6, 0x00d6, 0x7818, 0x905d, 0x0904, 0x950c, 0xb854, 0x0006, - 0x9006, 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, - 0x653a, 0x0904, 0x9509, 0x7e24, 0x86ff, 0x0904, 0x94fc, 0x9680, - 0x0005, 0x2004, 0x9906, 0x1904, 0x94fc, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0x94f3, 0x080c, 0x8562, 0x080c, 0xa274, - 0x68c3, 0x0000, 0x080c, 0xa7bd, 0x7827, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, - 0x0002, 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, - 0x81ff, 0x1518, 0x2009, 0x1987, 0x210c, 0x2102, 0x00f0, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f, 0x0000, 0x080c, - 0xaea2, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, - 0x630a, 0x00ce, 0x0804, 0x949f, 0x89ff, 0x0138, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c86, 0x080c, 0xa693, 0x0804, - 0x949f, 0x000e, 0x0804, 0x9493, 0x781e, 0x781a, 0x00de, 0x00ce, - 0x00be, 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, - 0x0066, 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d, 0x0188, 0xa878, - 0x9606, 0x1170, 0x2071, 0x19e6, 0x7024, 0x9035, 0x0148, 0x9080, - 0x0005, 0x2004, 0x9906, 0x1120, 0xb800, 0xc0dc, 0xb802, 0x0029, - 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, - 0x00ce, 0x04b8, 0x080c, 0xa274, 0x78c3, 0x0000, 0x080c, 0xa7bd, - 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, - 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, - 0xa7bd, 0x003e, 0x080c, 0x653a, 0x00c6, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x080c, 0xae71, 0x00ce, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0xce3e, 0x080c, 0x6c86, 0x080c, - 0xa693, 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x2011, 0x0101, - 0x2204, 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014, 0xc2e4, 0x2202, - 0x2071, 0x19e6, 0x7004, 0x9084, 0x0007, 0x0002, 0x9598, 0x959c, - 0x95ba, 0x95e3, 0x9621, 0x9598, 0x95b3, 0x9596, 0x080c, 0x0dd5, - 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, - 0x8001, 0x7022, 0x600c, 0x9015, 0x0158, 0x7216, 0x600f, 0x0000, - 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, - 0x7216, 0x7212, 0x0ca8, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, - 0x9005, 0x0070, 0x6010, 0x2058, 0x080c, 0x653a, 0xb800, 0xc0dc, - 0xb802, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, - 0x1148, 0x2001, 0x180c, 0x2014, 0xd2ec, 0x1180, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0xb854, 0x9015, 0x0120, 0x721e, 0x080c, 0x9687, - 0x0ca8, 0x7218, 0x721e, 0x080c, 0x9687, 0x0c80, 0xc2ec, 0x2202, - 0x080c, 0x97b5, 0x0c58, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, - 0x1160, 0x080c, 0xa693, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, - 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, - 0x080c, 0xa693, 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, - 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, - 0x6010, 0x2058, 0x080c, 0x653a, 0xb800, 0xc0dc, 0xb802, 0x080c, - 0xa693, 0x701c, 0x9065, 0x0138, 0xb854, 0x9015, 0x0110, 0x721e, - 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, - 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0xa693, 0x600c, 0x9015, - 0x0158, 0x720e, 0x600f, 0x0000, 0x080c, 0xa7bd, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a, 0x0ca8, 0x00d6, - 0x2069, 0x19e6, 0x6830, 0x9084, 0x0003, 0x0002, 0x9644, 0x9646, - 0x966a, 0x9642, 0x080c, 0x0dd5, 0x00de, 0x0005, 0x00c6, 0x6840, - 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, - 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x2011, 0x1a05, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, - 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, - 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, - 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, - 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, - 0x0005, 0x2001, 0x180c, 0x200c, 0xc1e5, 0x2102, 0x0005, 0x2001, - 0x180c, 0x200c, 0xd1ec, 0x0120, 0xc1ec, 0x2102, 0x080c, 0x97b5, - 0x2001, 0x19f2, 0x2004, 0x9086, 0x0001, 0x0d58, 0x00d6, 0x2069, - 0x19e6, 0x6804, 0x9084, 0x0007, 0x0006, 0x9005, 0x11c8, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0028, 0x1198, 0x2001, 0x197b, 0x2004, - 0x9086, 0xaaaa, 0x0168, 0x2001, 0x188b, 0x2004, 0xd08c, 0x1118, - 0xd084, 0x1118, 0x0028, 0x080c, 0x97b5, 0x000e, 0x00de, 0x0005, - 0x000e, 0x0002, 0x96c4, 0x9783, 0x9783, 0x9783, 0x9783, 0x9785, - 0x9783, 0x96c2, 0x080c, 0x0dd5, 0x6820, 0x9005, 0x1110, 0x00de, - 0x0005, 0x00c6, 0x680c, 0x9065, 0x0520, 0x6114, 0x0096, 0x2148, - 0xa964, 0x009e, 0x918c, 0x00ff, 0x918e, 0x0035, 0x1180, 0x2009, - 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, 0x080c, 0x73a5, 0x0138, - 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x9862, 0x00ce, 0x00de, - 0x0005, 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x080c, 0x9862, 0x00ce, 0x00de, 0x0005, 0x00b6, 0x00e6, - 0x6a1c, 0x92dd, 0x0000, 0x0904, 0x976d, 0xb84c, 0x900d, 0x0118, - 0xb888, 0x9005, 0x01a0, 0xb854, 0x905d, 0x0120, 0x920e, 0x0904, - 0x976d, 0x0028, 0x6818, 0x920e, 0x0904, 0x976d, 0x2058, 0xb84c, - 0x900d, 0x0d88, 0xb888, 0x9005, 0x1d70, 0x2b00, 0x681e, 0xbb3c, - 0xb838, 0x9302, 0x1e40, 0x080c, 0xae48, 0x0904, 0x976d, 0x8318, - 0xbb3e, 0x6116, 0x2b10, 0x6212, 0x0096, 0x2148, 0xa880, 0x9084, - 0x00ff, 0x605e, 0xa883, 0x0000, 0xa884, 0x009e, 0x908a, 0x199a, - 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, + 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, 0x9005, + 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xae90, 0x00ce, 0x0048, + 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, + 0x93b9, 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, + 0x080c, 0xce4e, 0x080c, 0xe943, 0x080c, 0x6c94, 0x080c, 0xa67d, + 0x0804, 0x93b9, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, + 0x00ce, 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x947e, 0x600c, + 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1570, 0x2069, 0x0100, + 0x6820, 0xd0a4, 0x1508, 0x080c, 0x857f, 0x080c, 0xa28f, 0x68c3, + 0x0000, 0x080c, 0xa7a7, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2cfc, + 0x9006, 0x080c, 0x2cfc, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0040, 0x080c, 0x6921, 0x1520, 0x6003, + 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xcb58, + 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xcd60, 0x1118, + 0x080c, 0xb821, 0x0060, 0x080c, 0x6921, 0x1168, 0xa867, 0x0103, + 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c94, 0x080c, 0xcd43, 0x080c, + 0xae90, 0x080c, 0xa67d, 0x000e, 0x0804, 0x9424, 0x7e16, 0x7e12, + 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1118, 0x080c, 0xe58c, 0x0c50, 0x080c, 0xb821, 0x6020, + 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, + 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, + 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, + 0x008b, 0x0d00, 0x0860, 0x0006, 0x0066, 0x0096, 0x00b6, 0x00c6, + 0x00d6, 0x7818, 0x905d, 0x0904, 0x952b, 0xb854, 0x0006, 0x9006, + 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, 0x6548, + 0x0904, 0x9528, 0x7e24, 0x86ff, 0x0904, 0x951b, 0x9680, 0x0005, + 0x2004, 0x9906, 0x1904, 0x951b, 0x00d6, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x0904, 0x9512, 0x080c, 0x857f, 0x080c, 0xa28f, 0x68c3, + 0x0000, 0x080c, 0xa7a7, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2cfc, + 0x9006, 0x080c, 0x2cfc, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, + 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, + 0x1518, 0x2009, 0x1987, 0x210c, 0x2102, 0x00f0, 0xb83c, 0x9005, + 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f, 0x0000, 0x080c, 0xae90, + 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, + 0x00ce, 0x0804, 0x94be, 0x89ff, 0x0138, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0x6c94, 0x080c, 0xa67d, 0x0804, 0x94be, + 0x000e, 0x0804, 0x94b2, 0x781e, 0x781a, 0x00de, 0x00ce, 0x00be, + 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, + 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d, 0x0188, 0xa878, 0x9606, + 0x1170, 0x2071, 0x19e6, 0x7024, 0x9035, 0x0148, 0x9080, 0x0005, + 0x2004, 0x9906, 0x1120, 0xb800, 0xc0dc, 0xb802, 0x0029, 0x006e, + 0x009e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, + 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, + 0x04b8, 0x080c, 0xa28f, 0x78c3, 0x0000, 0x080c, 0xa7a7, 0x7027, + 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x2079, + 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0xa7a7, + 0x003e, 0x080c, 0x6548, 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, + 0xb83e, 0x2660, 0x080c, 0xae5f, 0x00ce, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0xce4e, 0x080c, 0x6c94, 0x080c, 0xa67d, + 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x2011, 0x0101, 0x2204, + 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014, 0xc2e4, 0x2202, 0x2071, + 0x19e6, 0x7004, 0x9084, 0x0007, 0x0002, 0x95b7, 0x95bb, 0x95d9, + 0x9602, 0x9640, 0x95b7, 0x95d2, 0x95b5, 0x080c, 0x0dd5, 0x00ce, + 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, 0x8001, + 0x7022, 0x600c, 0x9015, 0x0158, 0x7216, 0x600f, 0x0000, 0x7007, + 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7216, + 0x7212, 0x0ca8, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x9005, + 0x0070, 0x6010, 0x2058, 0x080c, 0x6548, 0xb800, 0xc0dc, 0xb802, + 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, 0x1148, + 0x2001, 0x180c, 0x2014, 0xd2ec, 0x1180, 0x00ce, 0x00ee, 0x00be, + 0x0005, 0xb854, 0x9015, 0x0120, 0x721e, 0x080c, 0x96a6, 0x0ca8, + 0x7218, 0x721e, 0x080c, 0x96a6, 0x0c80, 0xc2ec, 0x2202, 0x080c, + 0x97d4, 0x0c58, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, + 0x080c, 0xa67d, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, + 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, + 0xa67d, 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, + 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, + 0x2058, 0x080c, 0x6548, 0xb800, 0xc0dc, 0xb802, 0x080c, 0xa67d, + 0x701c, 0x9065, 0x0138, 0xb854, 0x9015, 0x0110, 0x721e, 0x0010, + 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, + 0x7024, 0x9065, 0x0140, 0x080c, 0xa67d, 0x600c, 0x9015, 0x0158, + 0x720e, 0x600f, 0x0000, 0x080c, 0xa7a7, 0x7027, 0x0000, 0x00ce, + 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a, 0x0ca8, 0x00d6, 0x2069, + 0x19e6, 0x6830, 0x9084, 0x0003, 0x0002, 0x9663, 0x9665, 0x9689, + 0x9661, 0x080c, 0x0dd5, 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, + 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, + 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, + 0x1a05, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, + 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, + 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, + 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, + 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, + 0x2001, 0x180c, 0x200c, 0xc1e5, 0x2102, 0x0005, 0x2001, 0x180c, + 0x200c, 0xd1ec, 0x0120, 0xc1ec, 0x2102, 0x080c, 0x97d4, 0x2001, + 0x19f2, 0x2004, 0x9086, 0x0001, 0x0d58, 0x00d6, 0x2069, 0x19e6, + 0x6804, 0x9084, 0x0007, 0x0006, 0x9005, 0x11c8, 0x2001, 0x1837, + 0x2004, 0x9084, 0x0028, 0x1198, 0x2001, 0x197b, 0x2004, 0x9086, + 0xaaaa, 0x0168, 0x2001, 0x188b, 0x2004, 0xd08c, 0x1118, 0xd084, + 0x1118, 0x0028, 0x080c, 0x97d4, 0x000e, 0x00de, 0x0005, 0x000e, + 0x0002, 0x96e3, 0x97a2, 0x97a2, 0x97a2, 0x97a2, 0x97a4, 0x97a2, + 0x96e1, 0x080c, 0x0dd5, 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, + 0x00c6, 0x680c, 0x9065, 0x0520, 0x6114, 0x0096, 0x2148, 0xa964, + 0x009e, 0x918c, 0x00ff, 0x918e, 0x0035, 0x1180, 0x2009, 0x1837, + 0x210c, 0x918c, 0x0028, 0x1150, 0x080c, 0x73b3, 0x0138, 0x0006, + 0x2009, 0x188b, 0x2104, 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x080c, 0x987d, 0x00ce, 0x00de, 0x0005, + 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, + 0x080c, 0x987d, 0x00ce, 0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, + 0x92dd, 0x0000, 0x0904, 0x978c, 0xb84c, 0x900d, 0x0118, 0xb888, + 0x9005, 0x01a0, 0xb854, 0x905d, 0x0120, 0x920e, 0x0904, 0x978c, + 0x0028, 0x6818, 0x920e, 0x0904, 0x978c, 0x2058, 0xb84c, 0x900d, + 0x0d88, 0xb888, 0x9005, 0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, + 0x9302, 0x1e40, 0x080c, 0xae36, 0x0904, 0x978c, 0x8318, 0xbb3e, + 0x6116, 0x2b10, 0x6212, 0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, + 0x605e, 0xa883, 0x0000, 0xa884, 0x009e, 0x908a, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, + 0x0096, 0x2148, 0xa964, 0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, + 0x0538, 0x00f6, 0x2c78, 0x2061, 0x0100, 0xbac0, 0x629a, 0x2069, + 0x0200, 0x2071, 0x0240, 0x080c, 0x9dca, 0x2069, 0x19e6, 0xbb00, + 0xc3dd, 0xbb02, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, + 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, + 0x00be, 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, + 0x6807, 0x0006, 0x2c18, 0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, + 0x0000, 0x080c, 0x6548, 0x080c, 0xac76, 0x00ee, 0x00be, 0x00ce, + 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0508, 0x6114, 0x0096, 0x2148, 0xa964, 0x009e, 0x918c, 0x00ff, 0x918e, - 0x0048, 0x0538, 0x00f6, 0x2c78, 0x2061, 0x0100, 0xbac0, 0x629a, - 0x2069, 0x0200, 0x2071, 0x0240, 0x080c, 0x9daf, 0x2069, 0x19e6, - 0xbb00, 0xc3dd, 0xbb02, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, - 0x0000, 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, - 0x00ee, 0x00be, 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00be, 0x00ce, - 0x0cd0, 0x6807, 0x0006, 0x2c18, 0x6b26, 0x6820, 0x8001, 0x6822, - 0x682b, 0x0000, 0x080c, 0x653a, 0x080c, 0xac88, 0x00ee, 0x00be, - 0x00ce, 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, - 0x0508, 0x6114, 0x0096, 0x2148, 0xa964, 0x009e, 0x918c, 0x00ff, - 0x918e, 0x0035, 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, - 0x1150, 0x080c, 0x73a5, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, - 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, - 0x080c, 0x9862, 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, - 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, - 0x19e6, 0x6830, 0x9086, 0x0000, 0x1570, 0x2001, 0x180c, 0x2014, - 0xd2e4, 0x0130, 0xc2e4, 0x2202, 0x080c, 0x9696, 0x2069, 0x19e6, - 0x2001, 0x180c, 0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, - 0x6a04, 0x9296, 0x0000, 0x1904, 0x9856, 0x7920, 0x918e, 0x0009, - 0x0588, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, - 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c48, 0x1178, - 0x012e, 0x080c, 0xa0d1, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, - 0x0066, 0x2031, 0x0001, 0x080c, 0x7455, 0x006e, 0x08b0, 0x012e, - 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, - 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, - 0x6836, 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833, 0x0001, 0x683e, - 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, - 0x002e, 0x080c, 0x1c48, 0x19d8, 0x012e, 0x080c, 0xa052, 0x0858, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1188, 0x2001, 0x197b, - 0x2004, 0x9086, 0xaaaa, 0x0158, 0x2001, 0x19e7, 0x2004, 0x9005, - 0x11f0, 0x2001, 0x188b, 0x200c, 0xc185, 0xc18c, 0x2102, 0x2f00, + 0x0035, 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, + 0x080c, 0x73b3, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, + 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, + 0x987d, 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, + 0x2202, 0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19e6, + 0x6830, 0x9086, 0x0000, 0x1570, 0x2001, 0x180c, 0x2014, 0xd2e4, + 0x0130, 0xc2e4, 0x2202, 0x080c, 0x96b5, 0x2069, 0x19e6, 0x2001, + 0x180c, 0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, 0x6a04, + 0x9296, 0x0000, 0x1904, 0x9871, 0x7920, 0x918e, 0x0009, 0x0568, + 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, + 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c53, 0x1158, 0x012e, + 0x080c, 0xa0ec, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x080c, + 0x7463, 0x08d0, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, + 0x9015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, + 0x0000, 0x0c40, 0x683a, 0x6836, 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, - 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c48, 0x1904, 0x97f7, - 0x012e, 0x6a3c, 0x2278, 0x080c, 0x9fdc, 0x0804, 0x97eb, 0x2011, - 0x188b, 0x2204, 0xc08d, 0x2012, 0x0804, 0x97eb, 0x6a04, 0x9296, - 0x0006, 0x1904, 0x97ad, 0x6a30, 0x9296, 0x0000, 0x0904, 0x97d5, - 0x0804, 0x97ad, 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, 0x9876, - 0x987b, 0x9ce9, 0x9d78, 0x987b, 0x9ce9, 0x9d78, 0x9876, 0x987b, - 0x9876, 0x9876, 0x9876, 0x9876, 0x9876, 0x9876, 0x080c, 0x957b, - 0x080c, 0x9687, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146, 0x01c6, - 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, - 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dd5, 0x6110, 0x2158, - 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, - 0x98e7, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9a6c, 0x9aa7, 0x9ad0, - 0x9b78, 0x9b9a, 0x9ba0, 0x9bad, 0x9bb5, 0x9bc1, 0x9bc7, 0x9bd8, - 0x9bc7, 0x9c30, 0x9bb5, 0x9c3c, 0x9c42, 0x9bc1, 0x9c42, 0x9c4e, - 0x98e5, 0x98e5, 0x98e5, 0x98e5, 0x98e5, 0x98e5, 0x98e5, 0x98e5, - 0x98e5, 0x98e5, 0x98e5, 0xa46e, 0xa491, 0xa4a2, 0xa4c2, 0xa4f4, - 0x9bad, 0x98e5, 0x9bad, 0x9bc7, 0x98e5, 0x9ad0, 0x9b78, 0x98e5, - 0xa8b4, 0x9bc7, 0x98e5, 0xa8d0, 0x9bc7, 0x98e5, 0x9bc1, 0x9a66, - 0x9908, 0x98e5, 0xa8ec, 0xa959, 0xaa30, 0x98e5, 0xaa3d, 0x9baa, - 0xaa68, 0x98e5, 0xa4fe, 0xaa95, 0x98e5, 0x080c, 0x0dd5, 0x2100, - 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, - 0x013e, 0x015e, 0x00be, 0x0005, 0xab30, 0xabe2, 0x9906, 0x992f, - 0x99db, 0x99e6, 0x9906, 0x9bad, 0x9906, 0x9a2d, 0x9a39, 0x994a, - 0x9906, 0x9965, 0x9999, 0xad4f, 0xad94, 0x9bc7, 0x080c, 0x0dd5, - 0x00d6, 0x0096, 0x080c, 0x9c61, 0x7003, 0x2414, 0x7007, 0x0018, - 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, 0x700e, 0xa850, 0x7022, - 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, 0xa248, 0x009e, 0x00de, - 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x080c, 0xaddb, - 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x0096, 0x080c, 0x9c61, 0x7003, 0x0500, 0x7814, 0x2048, 0xa874, - 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, 0x7016, 0xa884, - 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, 0xa248, 0x009e, - 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9c61, 0x7003, 0x0500, - 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, 0xa8d4, 0x7012, - 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, 0x60c3, 0x0010, - 0x080c, 0xa248, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9c61, 0x20e9, 0x0000, 0x2001, 0x19a2, - 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, 0x60c2, 0xa830, - 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, - 0x19a2, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, 0x23b9, 0x080c, - 0xd886, 0x9006, 0x080c, 0x23b9, 0x001e, 0xa804, 0x9005, 0x0110, - 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa248, 0x012e, 0x009e, 0x00de, - 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9cac, - 0x20e9, 0x0000, 0x2001, 0x19a2, 0x2003, 0x0000, 0x7814, 0x2048, - 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, 0x60c2, 0xa830, - 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, - 0x19a2, 0x0016, 0x200c, 0x080c, 0xd886, 0x001e, 0xa804, 0x9005, - 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, 0x080c, 0x0fb1, - 0x080c, 0xa248, 0x012e, 0x009e, 0x00de, 0x0005, 0x60c0, 0x8004, - 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, - 0x8000, 0x1de0, 0x0005, 0x080c, 0x9c61, 0x7003, 0x7800, 0x7808, - 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0xa248, 0x00d6, 0x00e6, - 0x080c, 0x9cac, 0x7814, 0x9084, 0xff00, 0x2073, 0x0200, 0x8e70, - 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, - 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, - 0x99fc, 0x2069, 0x1801, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, - 0x1f04, 0x9a05, 0x2069, 0x19b2, 0x9086, 0xdf00, 0x0110, 0x2069, - 0x19cc, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, - 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, - 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x9a13, 0x60c3, 0x004c, - 0x080c, 0xa248, 0x00ee, 0x00de, 0x0005, 0x080c, 0x9c61, 0x7003, - 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, - 0xa248, 0x00d6, 0x0026, 0x0016, 0x080c, 0x9cac, 0x7003, 0x0200, - 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, - 0x000c, 0x2069, 0x1923, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, - 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, - 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, - 0x080c, 0xa248, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, - 0x2004, 0x609a, 0x0804, 0xa248, 0x080c, 0x9c61, 0x7003, 0x5200, - 0x2069, 0x1847, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, - 0x2873, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, 0xaddb, 0x1120, - 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, - 0x2001, 0x1820, 0x2004, 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, - 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, 0xa248, 0x080c, - 0x9c61, 0x7003, 0x0500, 0x080c, 0xaddb, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, - 0x2004, 0x700e, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0xa248, - 0x080c, 0x9c61, 0x9006, 0x080c, 0x6945, 0xb8a0, 0x9086, 0x007e, - 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, - 0x0096, 0x904d, 0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, - 0x7003, 0x0300, 0xb8a0, 0x9086, 0x007e, 0x1904, 0x9b3f, 0x00d6, - 0x2069, 0x196b, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, - 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x080c, 0xadf2, 0x680c, - 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0090, - 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x73a5, 0x1118, - 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0xadf2, - 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0xab17, - 0x2069, 0x1973, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, - 0x56dc, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04a8, 0x2001, - 0x1837, 0x2004, 0xd0a4, 0x0170, 0x0016, 0x2001, 0x196c, 0x200c, - 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x28b4, - 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196b, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x080c, 0xab17, 0x20a1, 0x024e, 0x20a9, - 0x0008, 0x2099, 0x1973, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa248, - 0x080c, 0x9c61, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, - 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, - 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, - 0x9085, 0x0002, 0x00d6, 0x0804, 0x9c11, 0x7026, 0x60c3, 0x0014, - 0x0804, 0xa248, 0x080c, 0x9c61, 0x7003, 0x5000, 0x0804, 0x9aea, - 0x080c, 0x9c61, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, - 0x0804, 0xa248, 0x080c, 0x9ca3, 0x0010, 0x080c, 0x9cac, 0x7003, - 0x0200, 0x60c3, 0x0004, 0x0804, 0xa248, 0x080c, 0x9cac, 0x7003, + 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c53, 0x19d8, 0x012e, + 0x080c, 0xa06d, 0x0878, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, + 0x1188, 0x2001, 0x197b, 0x2004, 0x9086, 0xaaaa, 0x0158, 0x2001, + 0x19e7, 0x2004, 0x9005, 0x11f0, 0x2001, 0x188b, 0x200c, 0xc185, + 0xc18c, 0x2102, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, + 0x684b, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, + 0x1c53, 0x1904, 0x9812, 0x012e, 0x6a3c, 0x2278, 0x080c, 0x9ff7, + 0x0804, 0x980a, 0x2011, 0x188b, 0x2204, 0xc08d, 0x2012, 0x0804, + 0x980a, 0x6a04, 0x9296, 0x0006, 0x1904, 0x97cc, 0x6a30, 0x9296, + 0x0000, 0x0904, 0x97f4, 0x0804, 0x97cc, 0x6020, 0x9084, 0x000f, + 0x000b, 0x0005, 0x9891, 0x9896, 0x9d04, 0x9d93, 0x9896, 0x9d04, + 0x9d93, 0x9891, 0x9896, 0x9891, 0x9891, 0x9891, 0x9891, 0x9891, + 0x9891, 0x080c, 0x959a, 0x080c, 0x96a6, 0x0005, 0x00b6, 0x0156, + 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0dd5, 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, + 0x908a, 0x0040, 0x1a04, 0x9902, 0x005b, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, + 0x9a87, 0x9ac2, 0x9aeb, 0x9b93, 0x9bb5, 0x9bbb, 0x9bc8, 0x9bd0, + 0x9bdc, 0x9be2, 0x9bf3, 0x9be2, 0x9c4b, 0x9bd0, 0x9c57, 0x9c5d, + 0x9bdc, 0x9c5d, 0x9c69, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, + 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0x9900, 0xa47f, 0xa4a2, + 0xa4b3, 0xa4d3, 0xa505, 0x9bc8, 0x9900, 0x9bc8, 0x9be2, 0x9900, + 0x9aeb, 0x9b93, 0x9900, 0xa89e, 0x9be2, 0x9900, 0xa8ba, 0x9be2, + 0x9900, 0x9bdc, 0x9a81, 0x9923, 0x9900, 0xa8d6, 0xa943, 0xaa1e, + 0x9900, 0xaa2b, 0x9bc5, 0xaa56, 0x9900, 0xa50f, 0xaa83, 0x9900, + 0x080c, 0x0dd5, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xab1e, + 0xabd0, 0x9921, 0x994a, 0x99f6, 0x9a01, 0x9921, 0x9bc8, 0x9921, + 0x9a48, 0x9a54, 0x9965, 0x9921, 0x9980, 0x99b4, 0xad3d, 0xad82, + 0x9be2, 0x080c, 0x0dd5, 0x00d6, 0x0096, 0x080c, 0x9c7c, 0x7003, + 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, + 0x700e, 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, + 0xa263, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, + 0x00be, 0x080c, 0xadc9, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9c7c, 0x7003, 0x0500, + 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, + 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, + 0x080c, 0xa263, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, + 0x9c7c, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, + 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, + 0x701e, 0x60c3, 0x0010, 0x080c, 0xa263, 0x009e, 0x00de, 0x0005, + 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c7c, 0x20e9, + 0x0000, 0x2001, 0x19a2, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, + 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x001b, 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x2001, 0x0001, + 0x080c, 0x23c4, 0x080c, 0xd896, 0x9006, 0x080c, 0x23c4, 0x001e, + 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa263, + 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9cc7, 0x20e9, 0x0000, 0x2001, 0x19a2, 0x2003, + 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, + 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x001b, 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x080c, 0xd896, + 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, + 0x2048, 0x080c, 0x0fb1, 0x080c, 0xa263, 0x012e, 0x009e, 0x00de, + 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, + 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9c7c, + 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, + 0xa263, 0x00d6, 0x00e6, 0x080c, 0x9cc7, 0x7814, 0x9084, 0xff00, + 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, + 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, + 0x8d68, 0x8e70, 0x1f04, 0x9a17, 0x2069, 0x1801, 0x20a9, 0x0004, + 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9a20, 0x2069, 0x19b2, 0x9086, + 0xdf00, 0x0110, 0x2069, 0x19cc, 0x20a9, 0x001a, 0x9e86, 0x0260, + 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, + 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, + 0x9a2e, 0x60c3, 0x004c, 0x080c, 0xa263, 0x00ee, 0x00de, 0x0005, + 0x080c, 0x9c7c, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, + 0x60c3, 0x0008, 0x0804, 0xa263, 0x00d6, 0x0026, 0x0016, 0x080c, + 0x9cc7, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, + 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, 0x1923, 0x6810, 0xd084, + 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, + 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, + 0x7206, 0x710a, 0x62c2, 0x080c, 0xa263, 0x001e, 0x002e, 0x00de, + 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, 0xa263, 0x080c, + 0x9c7c, 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, 0xd084, 0x0130, + 0x6828, 0x0016, 0x080c, 0x287e, 0x710e, 0x001e, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, + 0x080c, 0xadc9, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, + 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, 0x7036, 0x0030, + 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, + 0x0804, 0xa263, 0x080c, 0x9c7c, 0x7003, 0x0500, 0x080c, 0xadc9, + 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, + 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, 0x0030, 0x2001, 0x1818, + 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, + 0x0010, 0x0804, 0xa263, 0x080c, 0x9c7c, 0x9006, 0x080c, 0x6953, + 0xb8a0, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, + 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, 0x9006, 0xa89a, + 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, 0x9086, 0x007e, + 0x1904, 0x9b5a, 0x00d6, 0x2069, 0x196b, 0x2001, 0x1837, 0x2004, + 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, + 0x080c, 0xade0, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, + 0x681c, 0x7026, 0x0090, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, + 0x080c, 0x73b3, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, + 0x7012, 0x080c, 0xade0, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, + 0x00d6, 0x080c, 0xab05, 0x2069, 0x1973, 0x2071, 0x024e, 0x6800, + 0xc0dd, 0x7002, 0x080c, 0x56e6, 0xd0e4, 0x0110, 0x680c, 0x700e, + 0x00de, 0x04a8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0170, 0x0016, + 0x2001, 0x196c, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, + 0x0000, 0x080c, 0x28bf, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, + 0x196b, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, + 0x20a9, 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0xab05, + 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, 0x1973, 0x4003, 0x60c3, + 0x0074, 0x0804, 0xa263, 0x080c, 0x9c7c, 0x7003, 0x2010, 0x7007, + 0x0014, 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, + 0x1847, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, + 0x0110, 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x9c2c, + 0x7026, 0x60c3, 0x0014, 0x0804, 0xa263, 0x080c, 0x9c7c, 0x7003, + 0x5000, 0x0804, 0x9b05, 0x080c, 0x9c7c, 0x7003, 0x2110, 0x7007, + 0x0014, 0x60c3, 0x0014, 0x0804, 0xa263, 0x080c, 0x9cbe, 0x0010, + 0x080c, 0x9cc7, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0xa263, + 0x080c, 0x9cc7, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, + 0x60c3, 0x0008, 0x0804, 0xa263, 0x080c, 0x9cc7, 0x7003, 0x0200, + 0x0804, 0x9b05, 0x080c, 0x9cc7, 0x7003, 0x0100, 0x782c, 0x9005, + 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x0804, 0xa263, 0x00d6, 0x080c, 0x9cc7, 0x7003, 0x0210, + 0x7007, 0x0014, 0x700b, 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, + 0xb99c, 0x9184, 0x0030, 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, + 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, + 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, + 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, + 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, + 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, + 0xd1e4, 0x0150, 0xc0c5, 0xbacc, 0xd28c, 0x1108, 0xc0cd, 0x9094, + 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, + 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, + 0x00de, 0x0804, 0xa263, 0x080c, 0x9cc7, 0x7003, 0x0210, 0x7007, + 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0xa263, 0x080c, + 0x9cc7, 0x7003, 0x0200, 0x0804, 0x9a8b, 0x080c, 0x9cc7, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, - 0xa248, 0x080c, 0x9cac, 0x7003, 0x0200, 0x0804, 0x9aea, 0x080c, - 0x9cac, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, - 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa248, - 0x00d6, 0x080c, 0x9cac, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, - 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, - 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, - 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, - 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, - 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, - 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, - 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, - 0xbacc, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, - 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, - 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa248, - 0x080c, 0x9cac, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, - 0x60c3, 0x0014, 0x0804, 0xa248, 0x080c, 0x9cac, 0x7003, 0x0200, - 0x0804, 0x9a70, 0x080c, 0x9cac, 0x7003, 0x0100, 0x700b, 0x0003, - 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa248, 0x080c, 0x9cac, - 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa248, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, - 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, - 0x0100, 0x080c, 0xab2c, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, - 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa236, 0x721a, 0x9f95, - 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, - 0x0026, 0x080c, 0xab2c, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, - 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, - 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, - 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0xab2c, 0xb810, 0x9305, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, - 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, - 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0xa236, 0x721a, 0x7a08, 0x7222, - 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa236, - 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, - 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dd5, 0x908a, - 0x0092, 0x1a0c, 0x0dd5, 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, - 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x0005, 0x9d1a, 0x9d29, 0x9d34, 0x9d18, 0x9d18, - 0x9d18, 0x9d1a, 0x9d18, 0x9d18, 0x9d18, 0x9d18, 0x9d18, 0x9d18, - 0x080c, 0x0dd5, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2ba7, - 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, - 0xa248, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, - 0x60c3, 0x000c, 0x0804, 0xa248, 0x0479, 0x7003, 0x0003, 0x7007, - 0x0300, 0x60c3, 0x0004, 0x0804, 0xa248, 0x0026, 0x080c, 0xab2c, - 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0x9c7c, - 0x0026, 0x080c, 0xab2c, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, - 0x0099, 0x7012, 0x0804, 0x9cde, 0x0026, 0x080c, 0xab2c, 0xb810, - 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, - 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x9cde, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, - 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0dd5, 0x908a, - 0x0054, 0x1a0c, 0x0dd5, 0x7910, 0x2158, 0xb9c0, 0x2061, 0x0100, - 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x0005, 0x9daf, 0x9e6b, 0x9e3e, 0x9f8d, 0x9dad, 0x9dad, - 0x9dad, 0x9dad, 0x9dad, 0x9dad, 0x9dad, 0xa670, 0xa678, 0xa680, - 0xa688, 0x9dad, 0xaa74, 0x9dad, 0xa668, 0x080c, 0x0dd5, 0x0096, - 0x780b, 0xffff, 0x080c, 0x9e1a, 0x7914, 0x2148, 0xa978, 0x7956, - 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, 0x1148, 0xa8b4, 0x7032, - 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, 0x703e, 0x0008, 0x7132, - 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, - 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006, 0x8004, 0x2010, - 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042, 0xd1ac, 0x0158, - 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, 0x080c, 0x18ae, 0x0010, - 0x080c, 0x1727, 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, - 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0xaab0, 0xaeac, 0x726a, - 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, - 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, - 0x2001, 0x1a02, 0x2003, 0x07d0, 0x2001, 0x1a01, 0x2003, 0x0009, - 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8cc, 0xd084, - 0x0128, 0x7a46, 0x7b14, 0x7b4a, 0x722e, 0x732a, 0x9294, 0x00ff, - 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, - 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, - 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, - 0x0081, 0x7814, 0x2048, 0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, - 0x700a, 0xa8ac, 0x700e, 0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, - 0xa248, 0x6813, 0x0008, 0xb810, 0x9085, 0x0500, 0x7002, 0xb814, + 0xa263, 0x080c, 0x9cc7, 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, + 0x0008, 0x0804, 0xa263, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, + 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, 0xab1a, 0xb810, 0x9305, + 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, + 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, + 0xa251, 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, + 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, 0xab1a, 0x7003, 0x02ff, + 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, + 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, + 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, + 0xab1a, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, + 0xb810, 0x9005, 0x1140, 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffe, 0x0020, 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, + 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa251, + 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, + 0x0005, 0x080c, 0xa251, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, + 0x2071, 0x024c, 0x002e, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, + 0x0a0c, 0x0dd5, 0x908a, 0x0092, 0x1a0c, 0x0dd5, 0x6110, 0x2158, + 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9d35, 0x9d44, + 0x9d4f, 0x9d33, 0x9d33, 0x9d33, 0x9d35, 0x9d33, 0x9d33, 0x9d33, + 0x9d33, 0x9d33, 0x9d33, 0x080c, 0x0dd5, 0x0411, 0x60c3, 0x0000, + 0x0026, 0x080c, 0x2bb2, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, + 0x2012, 0x002e, 0x0804, 0xa263, 0x0431, 0x7808, 0x700a, 0x7814, + 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0xa263, 0x0479, + 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, 0xa263, + 0x0026, 0x080c, 0xab1a, 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, - 0x0889, 0x080c, 0xa236, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x2071, 0x024c, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9f6b, 0x7814, - 0x2048, 0x080c, 0xcb48, 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, - 0x0033, 0x0010, 0x9006, 0x001b, 0x009e, 0x00de, 0x0005, 0x9e89, - 0x9ef2, 0x9f02, 0x9f28, 0x9f34, 0x9f45, 0x9f4d, 0x9e87, 0x080c, - 0x0dd5, 0x0016, 0x0036, 0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, - 0x0003, 0x1198, 0xaba8, 0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, - 0x701a, 0xa894, 0x701e, 0x003e, 0x001e, 0x2001, 0x19b0, 0x2004, - 0x60c2, 0x0804, 0xa248, 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, - 0x0dd5, 0xaba8, 0x7824, 0xd0cc, 0x1904, 0x9eef, 0x7316, 0xa898, - 0x701a, 0xa894, 0x701e, 0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, - 0x0018, 0x9384, 0x0300, 0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, - 0xd3cc, 0x0110, 0xa8a4, 0x9108, 0x6810, 0x9085, 0x0010, 0x6812, - 0x2011, 0x0258, 0x20e9, 0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x002c, 0x2098, 0x4003, 0x6810, - 0x8000, 0x6812, 0x2011, 0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, - 0x6810, 0xc084, 0x6812, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, - 0x0245, 0x201a, 0x61c2, 0x003e, 0x001e, 0x0804, 0xa248, 0xc3e5, - 0x0804, 0x9eae, 0x2011, 0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, - 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, - 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, - 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, - 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, - 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, - 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x0804, 0xa248, - 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, - 0x0804, 0xa248, 0x0cd0, 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, - 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, - 0x7036, 0x60c3, 0x0020, 0x0804, 0xa248, 0x2011, 0x0008, 0x7824, - 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, - 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, - 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, - 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, - 0x701e, 0x003e, 0x0818, 0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, - 0x0700, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x7824, 0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, - 0xa236, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, - 0x00de, 0x0005, 0x7013, 0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, - 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x9f9d, 0x9f9d, 0x9f9f, - 0x9f9d, 0x9f9d, 0x9f9d, 0x9fb9, 0x9f9d, 0x080c, 0x0dd5, 0x7914, - 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, - 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, - 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, - 0xa248, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, - 0x080c, 0xab2c, 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, - 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0xa236, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, - 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028, 0x0110, 0x737c, - 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, - 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, - 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, 0x0000, 0x616e, - 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, - 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, - 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, - 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128, 0x609f, 0x0000, - 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, - 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, 0x2009, 0x07d0, 0x080c, - 0x8567, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00be, 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, - 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, - 0x2058, 0xb8a0, 0x2028, 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, - 0x1250, 0x2500, 0x9094, 0xff80, 0x1130, 0x9080, 0x3327, 0x2015, - 0x9294, 0x00ff, 0x0020, 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, - 0xd0ac, 0x1130, 0x9582, 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, - 0x9185, 0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, - 0x0400, 0x6266, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, - 0x0000, 0xb864, 0xd0a4, 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, - 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, - 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, + 0x0009, 0x0804, 0x9c97, 0x0026, 0x080c, 0xab1a, 0xb810, 0x9085, + 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, + 0x6880, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x9cf9, 0x0026, + 0x080c, 0xab1a, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, + 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, + 0x7012, 0x0804, 0x9cf9, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, + 0x0a0c, 0x0dd5, 0x908a, 0x0054, 0x1a0c, 0x0dd5, 0x7910, 0x2158, + 0xb9c0, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9dca, 0x9e86, 0x9e59, + 0x9fa8, 0x9dc8, 0x9dc8, 0x9dc8, 0x9dc8, 0x9dc8, 0x9dc8, 0x9dc8, + 0xa65a, 0xa662, 0xa66a, 0xa672, 0x9dc8, 0xaa62, 0x9dc8, 0xa652, + 0x080c, 0x0dd5, 0x0096, 0x780b, 0xffff, 0x080c, 0x9e35, 0x7914, + 0x2148, 0xa978, 0x7956, 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, + 0x1148, 0xa8b4, 0x7032, 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, + 0x703e, 0x0008, 0x7132, 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, + 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, + 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, + 0x7042, 0xd1ac, 0x0158, 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, + 0x080c, 0x18ae, 0x0010, 0x080c, 0x1727, 0x0050, 0xd1b4, 0x0118, + 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, + 0xaab0, 0xaeac, 0x726a, 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, + 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, + 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, + 0x0020, 0x6017, 0x0009, 0x2001, 0x1a02, 0x2003, 0x07d0, 0x2001, + 0x1a01, 0x2003, 0x0009, 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, + 0x8210, 0xb8cc, 0xd084, 0x0128, 0x7a46, 0x7b14, 0x7b4a, 0x722e, + 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, + 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, + 0x6a80, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, + 0x0005, 0x00d6, 0x0096, 0x0081, 0x7814, 0x2048, 0xa890, 0x7002, + 0xa88c, 0x7006, 0xa8b0, 0x700a, 0xa8ac, 0x700e, 0x60c3, 0x000c, + 0x009e, 0x00de, 0x0804, 0xa263, 0x6813, 0x0008, 0xb810, 0x9085, + 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, + 0x6880, 0x700e, 0x7013, 0x0889, 0x080c, 0xa251, 0x721a, 0x7a08, + 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005, 0x00d6, 0x0096, + 0x080c, 0x9f86, 0x7814, 0x2048, 0x080c, 0xcb58, 0x1130, 0x7814, + 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006, 0x001b, 0x009e, + 0x00de, 0x0005, 0x9ea4, 0x9f0d, 0x9f1d, 0x9f43, 0x9f4f, 0x9f60, + 0x9f68, 0x9ea2, 0x080c, 0x0dd5, 0x0016, 0x0036, 0xa97c, 0x918c, + 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8, 0x7824, 0xd0cc, + 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, 0x003e, 0x001e, + 0x2001, 0x19b0, 0x2004, 0x60c2, 0x0804, 0xa263, 0xc3e5, 0x0c88, + 0x9186, 0x0001, 0x190c, 0x0dd5, 0xaba8, 0x7824, 0xd0cc, 0x1904, + 0x9f0a, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, 0xa8a4, 0x7026, + 0xa8ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, 0x0570, 0xd3c4, + 0x0110, 0xa8ac, 0x9108, 0xd3cc, 0x0110, 0xa8a4, 0x9108, 0x6810, + 0x9085, 0x0010, 0x6812, 0x2011, 0x0258, 0x20e9, 0x0000, 0x22a0, + 0x0156, 0x20a9, 0x0008, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x002c, + 0x2098, 0x4003, 0x6810, 0x8000, 0x6812, 0x2011, 0x0240, 0x22a0, + 0x20a9, 0x0005, 0x4003, 0x6810, 0xc084, 0x6812, 0x015e, 0x9184, + 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2, 0x003e, 0x001e, + 0x0804, 0xa263, 0xc3e5, 0x0804, 0x9ec9, 0x2011, 0x0008, 0x2001, + 0x180f, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, + 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, + 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, + 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, + 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, + 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, + 0x0032, 0x0804, 0xa263, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, + 0x7216, 0x60c3, 0x0018, 0x0804, 0xa263, 0x0cd0, 0xc2e5, 0x2011, + 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, + 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, 0x0804, 0xa263, + 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x0c08, + 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, + 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0888, + 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, + 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818, 0x00d6, 0x6813, + 0x0008, 0xb810, 0x9085, 0x0700, 0x7002, 0xb814, 0x7006, 0x2069, + 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7824, 0xd0cc, 0x1168, + 0x7013, 0x0898, 0x080c, 0xa251, 0x721a, 0x7a08, 0x7222, 0x2f10, + 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013, 0x0889, 0x0c90, + 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, + 0x9fb8, 0x9fb8, 0x9fba, 0x9fb8, 0x9fb8, 0x9fb8, 0x9fd4, 0x9fb8, + 0x080c, 0x0dd5, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, + 0x2009, 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, + 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, + 0x60c3, 0x0001, 0x0804, 0xa263, 0x2009, 0x0003, 0x0019, 0x7033, + 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xab1a, 0x001e, 0xb810, 0x9085, + 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, + 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, + 0xa251, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, + 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, + 0x0028, 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, + 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, + 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, + 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, + 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, + 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, + 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, + 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, + 0x0128, 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, 0x6028, 0xc0bd, + 0x602a, 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, 0x00b2, 0x6016, + 0x2009, 0x07d0, 0x080c, 0x8584, 0x003e, 0x004e, 0x005e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, + 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, 0x2028, 0x76dc, 0xd6ac, + 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, 0x9094, 0xff80, 0x1130, + 0x9080, 0x3332, 0x2015, 0x9294, 0x00ff, 0x0020, 0xb910, 0xba14, + 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, 0x9582, 0x007e, 0x1218, + 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, 0x0000, 0x616e, + 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, 0xd0a4, 0x0110, 0x6077, + 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, + 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, + 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, + 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, 0x00f6, 0x2079, + 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, 0x0092, 0x6116, 0x2009, + 0x07d0, 0x080c, 0x8584, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, + 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, + 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, + 0x7820, 0x90be, 0x0006, 0x0904, 0xa1c0, 0x90be, 0x000a, 0x1904, + 0xa17c, 0xb8c0, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, + 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, + 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, + 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, + 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, + 0x0129, 0x6077, 0x0000, 0xb8c0, 0x609e, 0x0050, 0x2039, 0x0029, + 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, + 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, + 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, - 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xbac0, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, - 0x00fe, 0x2009, 0x0092, 0x6116, 0x2009, 0x07d0, 0x080c, 0x8567, - 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, - 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, - 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, - 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x90be, 0x0006, - 0x0904, 0xa1a5, 0x90be, 0x000a, 0x1904, 0xa161, 0xb8c0, 0x609e, - 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, 0xaf90, 0x9784, 0xff00, - 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, 0x2048, - 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, 0xaf94, 0x87ff, 0x0198, - 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, - 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, - 0xb8c0, 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0cc0, - 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, 0xa87c, 0xd0fc, 0x0118, - 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, - 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, - 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0xa838, 0x608a, 0xa834, - 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, - 0x95d5, 0x60d7, 0x0000, 0x080c, 0xab11, 0x2009, 0x07d0, 0x60c4, - 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x8567, - 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, - 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, 0xa1e1, 0x9185, 0x0100, - 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, - 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, - 0x6086, 0x7814, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, - 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, 0xbac0, 0x629e, 0x080c, - 0xab11, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, - 0x2009, 0x1b58, 0x080c, 0x8567, 0x003e, 0x004e, 0x005e, 0x00ce, - 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7814, 0x2048, 0xa87c, - 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, 0xa1fd, 0x9185, 0x0100, - 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, - 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x7838, - 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0xa890, 0x608a, 0xa88c, - 0x608e, 0xa8b0, 0x60c6, 0xa8ac, 0x60ca, 0xa8ac, 0x7930, 0x9108, - 0x7932, 0xa8b0, 0x792c, 0x9109, 0x792e, 0xb86c, 0x60ce, 0x60af, - 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, 0x080c, 0xaaee, 0x0804, - 0xa191, 0xb8cc, 0xd084, 0x0148, 0xb88c, 0x7814, 0x2048, 0xb88c, - 0x7846, 0xa836, 0x2900, 0xa83a, 0xb04a, 0x9185, 0x0600, 0x6062, - 0x6266, 0x636a, 0x646e, 0x6073, 0x0829, 0x6077, 0x0000, 0x60af, - 0x9575, 0x60d7, 0x0000, 0x0804, 0xa174, 0x9185, 0x0700, 0x6062, - 0x6266, 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, - 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0xb88c, 0x8000, - 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, - 0x6086, 0x7808, 0x6082, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, - 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xbac0, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, 0xab11, - 0x0804, 0xa191, 0x080c, 0xaaee, 0x0804, 0xa191, 0x7a10, 0x00b6, - 0x2258, 0xba8c, 0x8210, 0x9294, 0x00ff, 0xba8e, 0x00be, 0x8217, - 0x0005, 0x00d6, 0x2069, 0x19e6, 0x6843, 0x0001, 0x00de, 0x0005, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8559, 0x0005, - 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, - 0x0128, 0x0089, 0x080c, 0x8559, 0x001e, 0x0005, 0xc1e5, 0x2001, - 0x180c, 0x2102, 0x2001, 0x19e7, 0x2003, 0x0000, 0x2001, 0x19ef, - 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, - 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, - 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x73a5, 0x11e8, 0x2001, 0x1a02, 0x2004, - 0x9005, 0x1904, 0xa2da, 0x0066, 0x2031, 0x0001, 0x080c, 0x7455, - 0x006e, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, - 0xd084, 0x090c, 0x0dd5, 0x080c, 0x8559, 0x0460, 0x00c6, 0x2061, - 0x19e6, 0x00d0, 0x6904, 0x9194, 0x4000, 0x0548, 0x080c, 0xa274, - 0x080c, 0x2d01, 0x00c6, 0x2061, 0x19e6, 0x6128, 0x9192, 0x0008, - 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, - 0x8559, 0x080c, 0xa26b, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, - 0x080c, 0xea1f, 0x080c, 0x8562, 0x2009, 0x0014, 0x080c, 0xaeec, - 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, - 0x1a02, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19e6, 0x6128, - 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x8559, - 0x080c, 0x5ee2, 0x2009, 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, - 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x856f, - 0x2071, 0x19e6, 0x713c, 0x81ff, 0x0904, 0xa37e, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x73a5, 0x1500, 0x0036, 0x2019, 0x0002, - 0x080c, 0xa5b7, 0x003e, 0x713c, 0x2160, 0x080c, 0xea1f, 0x2009, - 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, - 0x0006, 0x2009, 0x004a, 0x080c, 0xaeec, 0x0066, 0x2031, 0x0001, - 0x080c, 0x7455, 0x006e, 0x0804, 0xa37e, 0x080c, 0xa38a, 0x0904, - 0xa37e, 0x6904, 0xd1f4, 0x0904, 0xa385, 0x080c, 0x2d01, 0x00c6, - 0x703c, 0x9065, 0x090c, 0x0dd5, 0x6020, 0x00ce, 0x9086, 0x0006, - 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x180c, 0x2104, - 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, - 0x0002, 0x1560, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, - 0x2c54, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, - 0x2060, 0x2009, 0x0049, 0x080c, 0xaeec, 0x00c0, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa5b7, 0x003e, 0x713c, 0x2160, 0x080c, 0xea1f, - 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, - 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c, 0xaeec, 0x002e, 0x001e, - 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, 0xa335, - 0x0804, 0xa337, 0x00d6, 0x00c6, 0x0096, 0x703c, 0x9065, 0x090c, - 0x0dd5, 0x2001, 0x1837, 0x2004, 0xd09c, 0x1904, 0xa416, 0x2001, - 0x0306, 0x200c, 0x9184, 0x0030, 0x0904, 0xa416, 0x9184, 0x0048, - 0x9086, 0x0008, 0x1904, 0xa416, 0x2001, 0x020b, 0x2004, 0xd0fc, - 0x0904, 0xa416, 0xd08c, 0x0904, 0xa416, 0x2009, 0x1a7f, 0x2104, - 0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, 0x0184, - 0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, 0x9106, - 0x1570, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, 0x2001, - 0x009a, 0x2003, 0x0004, 0x2001, 0x1a65, 0x2003, 0x0000, 0x2001, - 0x1a6e, 0x2003, 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, 0x1120, - 0x2c10, 0x080c, 0x1baf, 0x0040, 0x6014, 0x2048, 0xaa3a, 0xa936, - 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6, 0x2091, 0x2400, - 0x002e, 0x080c, 0x1c48, 0x190c, 0x0dd5, 0x012e, 0x0090, 0x2009, - 0x1a80, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8, 0x2011, 0x0020, - 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4, 0x68c8, 0x9105, - 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002, 0x7048, 0xc085, - 0x704a, 0x0079, 0x7048, 0xc084, 0x704a, 0x2009, 0x07d0, 0x080c, - 0x8567, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, 0x9085, 0x0001, - 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e6, 0x7048, 0xd084, 0x01d8, - 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, - 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, - 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014, 0x9084, 0x1984, - 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00b6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, - 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19e6, 0x7018, 0x2058, - 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, 0x2058, 0x0cc0, - 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, 0x009e, 0x080c, - 0x673a, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x080c, 0x9c61, - 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, - 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, 0x2058, - 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, 0x607c, 0x6180, - 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, 0x0804, - 0xa248, 0x080c, 0x9c61, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, - 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0xa248, 0x0156, 0x080c, 0x9cac, 0x7003, 0x0200, 0x080c, - 0x85c2, 0x20a9, 0x0006, 0x2011, 0xfff4, 0x2019, 0xfff5, 0x9ef0, - 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, - 0x0002, 0x9290, 0x0002, 0x1f04, 0xa4b1, 0x60c3, 0x001c, 0x015e, - 0x0804, 0xa248, 0x0016, 0x0026, 0x080c, 0x9c88, 0x080c, 0x9c9a, - 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, 0x2048, - 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, - 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, - 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, 0xa248, 0x002e, - 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0xab17, 0x20a1, - 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x9c61, 0x7003, 0x6200, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa248, 0x0016, 0x0026, - 0x080c, 0x9c61, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, - 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, - 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, - 0x60c2, 0x080c, 0xa248, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x700c, 0x2060, - 0x8cff, 0x0178, 0x080c, 0xcd50, 0x1110, 0x080c, 0xb824, 0x600c, - 0x0006, 0x080c, 0xcfbc, 0x080c, 0xae71, 0x080c, 0xa693, 0x00ce, - 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, 0x00ee, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19e6, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, 0xa274, 0x6ac0, - 0x68c3, 0x0000, 0x080c, 0x8562, 0x00c6, 0x2061, 0x0100, 0x080c, - 0xac68, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, 0x0013, 0x080c, - 0xaeec, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, - 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x8562, 0x6814, - 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x2011, 0x5e8c, 0x080c, 0x84dc, 0x20a9, 0x01f4, 0x0009, - 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, - 0x4000, 0x190c, 0x2d01, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, - 0x0010, 0x1f04, 0xa599, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x0005, 0x0126, - 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, - 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, - 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e6, 0x703c, - 0x2060, 0x8cff, 0x0904, 0xa649, 0x9386, 0x0002, 0x1128, 0x6814, - 0x9084, 0x0002, 0x0904, 0xa649, 0x68af, 0x95f5, 0x6817, 0x0010, - 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, 0x080c, - 0x856f, 0x080c, 0x1ffc, 0x0046, 0x2009, 0x00a5, 0x080c, 0x0e51, - 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, 0x0004, 0x11f8, - 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, - 0x0090, 0x2071, 0x1a65, 0x6814, 0x9084, 0x1984, 0x9085, 0x0012, - 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0x9386, - 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, 0x0001, 0x2001, - 0x1980, 0x200c, 0x080c, 0x0e51, 0x004e, 0x20a9, 0x03e8, 0x6824, - 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, - 0x2d01, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, - 0xa61f, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x6827, 0x4000, 0x6824, 0x83ff, - 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0110, 0x080c, - 0xaeec, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0x19e6, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a32, 0x012e, 0x00de, 0x0005, - 0x080c, 0x9e1a, 0x7854, 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, - 0x080c, 0x9e1a, 0x7854, 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, - 0x080c, 0x9e1a, 0x7854, 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, - 0x080c, 0x9e1a, 0x7854, 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, - 0x080c, 0x9e1a, 0x7854, 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, - 0x0020, 0x0804, 0xa248, 0x00e6, 0x2071, 0x19e6, 0x7020, 0x9005, - 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e6, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, - 0xa738, 0x8cff, 0x0904, 0xa738, 0x6020, 0x9086, 0x0006, 0x1904, - 0xa733, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0xa733, 0x2039, - 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa733, 0x85ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0xa733, 0x7024, 0x9c06, 0x15b0, 0x2069, - 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, - 0x0001, 0x080c, 0x8562, 0x080c, 0xa7bd, 0x7027, 0x0000, 0x0428, - 0x080c, 0x8562, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x080c, 0xa7bd, 0x7027, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, - 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, - 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xcb48, 0x0110, 0x080c, - 0xe572, 0x009e, 0x080c, 0xaea2, 0x080c, 0xa693, 0x88ff, 0x1190, - 0x00ce, 0x0804, 0xa6ae, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa6ae, - 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, - 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7638, 0x2660, 0x2678, - 0x8cff, 0x0904, 0xa7ac, 0x6020, 0x9086, 0x0006, 0x1904, 0xa7a7, - 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa7a7, 0x0040, 0x6010, - 0x9b06, 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, - 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0xa5b7, 0x7033, - 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, - 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6014, 0x2048, 0x080c, 0xcb48, 0x0110, 0x080c, 0xe572, - 0x080c, 0xaea2, 0x87ff, 0x1198, 0x00ce, 0x0804, 0xa758, 0x2c78, - 0x600c, 0x2060, 0x0804, 0xa758, 0x9006, 0x012e, 0x000e, 0x002e, - 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, - 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e6, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, - 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, - 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, - 0x1508, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, + 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xaaff, + 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, + 0x1b58, 0x080c, 0x8584, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, + 0xa1fc, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xb88c, + 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, + 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2048, 0xa838, 0x608a, + 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, + 0xbac0, 0x629e, 0x080c, 0xaaff, 0x2009, 0x07d0, 0x60c4, 0x9084, + 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x8584, 0x003e, + 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, + 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, + 0xa218, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x0880, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, + 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, + 0xa890, 0x608a, 0xa88c, 0x608e, 0xa8b0, 0x60c6, 0xa8ac, 0x60ca, + 0xa8ac, 0x7930, 0x9108, 0x7932, 0xa8b0, 0x792c, 0x9109, 0x792e, + 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, + 0x080c, 0xaadc, 0x0804, 0xa1ac, 0xb8cc, 0xd084, 0x0148, 0xb88c, + 0x7814, 0x2048, 0xb88c, 0x7846, 0xa836, 0x2900, 0xa83a, 0xb04a, + 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0829, + 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000, 0x0804, 0xa18f, + 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x7824, 0xd0cc, + 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, + 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0xa838, 0x608a, + 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, 0x7824, 0xd0cc, + 0x0120, 0x080c, 0xaaff, 0x0804, 0xa1ac, 0x080c, 0xaadc, 0x0804, + 0xa1ac, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210, 0x9294, 0x00ff, + 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069, 0x19e6, 0x6843, + 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, + 0x080c, 0x8576, 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, + 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x8576, 0x001e, + 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, 0x19e7, 0x2003, + 0x0000, 0x2001, 0x19ef, 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, + 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, + 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x73b3, 0x11c0, + 0x2001, 0x1a02, 0x2004, 0x9005, 0x15d0, 0x080c, 0x7463, 0x1160, + 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, 0x090c, + 0x0dd5, 0x080c, 0x8576, 0x0458, 0x00c6, 0x2061, 0x19e6, 0x00c8, + 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c, 0x2d0c, 0x00c6, + 0x2061, 0x19e6, 0x6128, 0x9192, 0x0008, 0x1258, 0x8108, 0x612a, + 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x8576, 0x080c, 0xa286, + 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, 0xea39, 0x080c, + 0x857f, 0x2009, 0x0014, 0x080c, 0xaeda, 0x00ce, 0x0000, 0x002e, + 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a02, 0x2004, 0x9005, + 0x1db0, 0x00c6, 0x2061, 0x19e6, 0x6128, 0x9192, 0x0003, 0x1e08, + 0x8108, 0x612a, 0x00ce, 0x080c, 0x8576, 0x080c, 0x5eec, 0x2009, + 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x0026, 0x080c, 0x858c, 0x2071, 0x19e6, 0x713c, + 0x81ff, 0x0904, 0xa38f, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, + 0x73b3, 0x11e0, 0x0036, 0x2019, 0x0002, 0x080c, 0xa5c8, 0x003e, + 0x713c, 0x2160, 0x080c, 0xea39, 0x2009, 0x004a, 0x6220, 0x9296, + 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, + 0x080c, 0xaeda, 0x080c, 0x7463, 0x0804, 0xa38f, 0x080c, 0xa39b, + 0x0904, 0xa38f, 0x6904, 0xd1f4, 0x0904, 0xa396, 0x080c, 0x2d0c, + 0x00c6, 0x703c, 0x9065, 0x090c, 0x0dd5, 0x6020, 0x00ce, 0x9086, + 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x180c, + 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, + 0x9294, 0x0002, 0x1560, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, + 0x080c, 0x2c5f, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, + 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0xaeda, 0x00c0, 0x0036, + 0x2019, 0x0001, 0x080c, 0xa5c8, 0x003e, 0x713c, 0x2160, 0x080c, + 0xea39, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, + 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c, 0xaeda, 0x002e, + 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, + 0xa346, 0x0804, 0xa348, 0x00d6, 0x00c6, 0x0096, 0x703c, 0x9065, + 0x090c, 0x0dd5, 0x2001, 0x1837, 0x2004, 0xd09c, 0x1904, 0xa427, + 0x2001, 0x0306, 0x200c, 0x9184, 0x0030, 0x0904, 0xa427, 0x9184, + 0x0048, 0x9086, 0x0008, 0x1904, 0xa427, 0x2001, 0x020b, 0x2004, + 0xd0fc, 0x0904, 0xa427, 0xd08c, 0x0904, 0xa427, 0x2009, 0x1a7f, + 0x2104, 0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, + 0x0184, 0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, + 0x9106, 0x1570, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, + 0x2001, 0x009a, 0x2003, 0x0004, 0x2001, 0x1a65, 0x2003, 0x0000, + 0x2001, 0x1a6e, 0x2003, 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, + 0x1120, 0x2c10, 0x080c, 0x1bba, 0x0040, 0x6014, 0x2048, 0xaa3a, + 0xa936, 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6, 0x2091, + 0x2400, 0x002e, 0x080c, 0x1c53, 0x190c, 0x0dd5, 0x012e, 0x0090, + 0x2009, 0x1a80, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8, 0x2011, + 0x0020, 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4, 0x68c8, + 0x9105, 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002, 0x7048, + 0xc085, 0x704a, 0x0079, 0x7048, 0xc084, 0x704a, 0x2009, 0x07d0, + 0x080c, 0x8584, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, 0x9085, + 0x0001, 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e6, 0x7048, 0xd084, + 0x01d8, 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, + 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, + 0x0012, 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014, 0x9084, + 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00b6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, + 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19e6, 0x7018, + 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, 0x2058, + 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, 0x009e, + 0x080c, 0x6748, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, + 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x080c, + 0x9c7c, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, + 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, + 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, 0x607c, + 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, + 0x0804, 0xa263, 0x080c, 0x9c7c, 0x7003, 0x0f00, 0x7808, 0xd09c, + 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, + 0x0008, 0x0804, 0xa263, 0x0156, 0x080c, 0x9cc7, 0x7003, 0x0200, + 0x080c, 0x85df, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, + 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, + 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa4c2, 0x60c3, 0x001c, + 0x015e, 0x0804, 0xa263, 0x0016, 0x0026, 0x080c, 0x9ca3, 0x080c, + 0x9cb5, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, + 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, + 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, + 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, 0xa263, + 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0xab05, + 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x9c7c, 0x7003, + 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa263, 0x0016, + 0x0026, 0x080c, 0x9c7c, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, + 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, + 0x8003, 0x60c2, 0x080c, 0xa263, 0x002e, 0x001e, 0x0005, 0x00e6, + 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x700c, + 0x2060, 0x8cff, 0x0178, 0x080c, 0xcd60, 0x1110, 0x080c, 0xb821, + 0x600c, 0x0006, 0x080c, 0xcfcc, 0x080c, 0xae5f, 0x080c, 0xa67d, + 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, + 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, + 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, + 0x2071, 0x19e6, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, 0xa28f, + 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x857f, 0x00c6, 0x2061, 0x0100, + 0x080c, 0xac56, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, 0x0013, + 0x080c, 0xaeda, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, + 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x857f, + 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, + 0x68c3, 0x0000, 0x2011, 0x5e96, 0x080c, 0x84f9, 0x20a9, 0x01f4, + 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, + 0x9084, 0x4000, 0x190c, 0x2d0c, 0x0090, 0xd084, 0x0118, 0x6827, + 0x0001, 0x0010, 0x1f04, 0xa5aa, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x0005, + 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, + 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, + 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e6, + 0x703c, 0x2060, 0x8cff, 0x0904, 0xa633, 0x9386, 0x0002, 0x1128, + 0x6814, 0x9084, 0x0002, 0x0904, 0xa633, 0x68af, 0x95f5, 0x6817, + 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, + 0x080c, 0x858c, 0x080c, 0x2007, 0x2001, 0x0032, 0x6920, 0xd1bc, + 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x20a9, + 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, + 0x4000, 0x190c, 0x2d0c, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, + 0x0010, 0x1f04, 0xa609, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x6827, 0x4000, + 0x6824, 0x83ff, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, + 0x0110, 0x080c, 0xaeda, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a32, 0x012e, + 0x00de, 0x0005, 0x080c, 0x9e35, 0x7854, 0x7032, 0x7042, 0x7047, + 0x1000, 0x00f8, 0x080c, 0x9e35, 0x7854, 0x7032, 0x7042, 0x7047, + 0x4000, 0x00b8, 0x080c, 0x9e35, 0x7854, 0x7032, 0x7042, 0x7047, + 0x2000, 0x0078, 0x080c, 0x9e35, 0x7854, 0x7032, 0x7042, 0x7047, + 0x0400, 0x0038, 0x080c, 0x9e35, 0x7854, 0x7032, 0x7042, 0x7047, + 0x0200, 0x60c3, 0x0020, 0x0804, 0xa263, 0x00e6, 0x2071, 0x19e6, + 0x7020, 0x9005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x19e6, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, + 0x87ff, 0x0904, 0xa722, 0x8cff, 0x0904, 0xa722, 0x6020, 0x9086, + 0x0006, 0x1904, 0xa71d, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, + 0xa71d, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa71d, + 0x85ff, 0x0120, 0x6054, 0x9106, 0x1904, 0xa71d, 0x7024, 0x9c06, + 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, + 0x0148, 0x6827, 0x0001, 0x080c, 0x857f, 0x080c, 0xa7a7, 0x7027, + 0x0000, 0x0428, 0x080c, 0x857f, 0x6820, 0xd0b4, 0x0110, 0x68a7, + 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0xa7a7, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, + 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1168, 0x600f, 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xcb58, + 0x0110, 0x080c, 0xe58c, 0x009e, 0x080c, 0xae90, 0x080c, 0xa67d, + 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa698, 0x2c78, 0x600c, 0x2060, + 0x0804, 0xa698, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, + 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, + 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7638, + 0x2660, 0x2678, 0x8cff, 0x0904, 0xa796, 0x6020, 0x9086, 0x0006, + 0x1904, 0xa791, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa791, + 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, + 0x15c0, 0x703c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, + 0xa5c8, 0x7033, 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, + 0x003e, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, - 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, 0x957b, 0x9085, - 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, - 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e6, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, - 0xa8a3, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, - 0xa89e, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0904, 0xa875, 0x080c, 0xa274, 0x68c3, 0x0000, 0x080c, 0xa7bd, - 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, - 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, - 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0xcd3f, 0x1180, 0x080c, 0x31ea, 0x080c, - 0xcd50, 0x1518, 0x080c, 0xb824, 0x0400, 0x080c, 0xa7bd, 0x6824, - 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xcd50, 0x1118, - 0x080c, 0xb824, 0x0090, 0x6014, 0x2048, 0x080c, 0xcb48, 0x0168, - 0x6020, 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6c7a, 0x080c, 0xcd33, 0x080c, 0xcfbc, 0x080c, - 0xaea2, 0x080c, 0xa693, 0x00ce, 0x0804, 0xa81e, 0x2c78, 0x600c, - 0x2060, 0x0804, 0xa81e, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1d20, 0x080c, 0xe572, 0x0c08, 0x00d6, 0x080c, 0x9cac, 0x7003, - 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, - 0x1988, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, - 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0xa248, 0x00de, 0x0005, - 0x080c, 0x9cac, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, - 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, - 0x00ff, 0x9085, 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, - 0x7006, 0x60c2, 0x0804, 0xa248, 0x00b6, 0x00d6, 0x0016, 0x00d6, - 0x2f68, 0x2009, 0x0035, 0x080c, 0xd1c2, 0x00de, 0x1904, 0xa951, - 0x080c, 0x9c61, 0x7003, 0x1300, 0x782c, 0x080c, 0xaa53, 0x2068, - 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, - 0xaddb, 0x11d8, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, - 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, - 0xfffd, 0x0458, 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, - 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, - 0xb810, 0x700a, 0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, - 0x080c, 0xaddb, 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, - 0x0250, 0x00d6, 0x2069, 0x181f, 0x2d04, 0x700a, 0x8d68, 0x2d04, - 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, - 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0xa248, 0x00be, - 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, - 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, - 0x9186, 0x0003, 0x0904, 0xa9cb, 0x9186, 0x0005, 0x0904, 0xa9b4, - 0x9186, 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, 0xa9bc, 0x7807, - 0x0037, 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0xaa30, 0x0005, - 0x080c, 0xa9f1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, - 0x6800, 0x0002, 0xa995, 0xa9a0, 0xa997, 0xa9a0, 0xa99c, 0xa995, - 0xa995, 0xa9a0, 0xa9a0, 0xa9a0, 0xa9a0, 0xa995, 0xa995, 0xa995, - 0xa995, 0xa995, 0xa9a0, 0xa995, 0xa9a0, 0x080c, 0x0dd5, 0x6824, - 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, - 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0xa9ea, 0x080c, 0xa9f1, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, - 0x0002, 0x1108, 0x900e, 0x04b0, 0x04e1, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x2009, 0x4000, 0x0470, 0x04a1, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, - 0x1108, 0x900e, 0x00f8, 0x0429, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x6814, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, 0xa838, - 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, - 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, - 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, - 0xa248, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x9cac, - 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, - 0x2058, 0xb8a0, 0x080c, 0xaddb, 0x1118, 0x9092, 0x007e, 0x0268, - 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, - 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, - 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, - 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, - 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, - 0x080c, 0x9cac, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa248, 0x080c, 0x9c58, 0x7003, - 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, - 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, - 0x0010, 0x0804, 0xa248, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, - 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8cc, 0xd084, 0x0120, 0x7848, - 0x702a, 0x7844, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, - 0x080c, 0x9ca3, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0xa248, 0x0021, 0x60c3, 0x0000, 0x0804, - 0xa248, 0x00d6, 0x080c, 0xab2c, 0xb810, 0x9085, 0x0300, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x7013, 0x0819, 0x080c, 0xa236, 0x721a, 0x2f10, 0x7222, 0x7a08, - 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x00a9, 0x7914, 0x712a, - 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x2ba7, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa26b, - 0x080c, 0x8559, 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7858, - 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0xfffd, 0xaa7e, 0xaa80, - 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, - 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, - 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, - 0xab2c, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, - 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, - 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, - 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, - 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, - 0xc1d5, 0x2102, 0x2009, 0x19b1, 0x210c, 0x009e, 0x918d, 0x0092, - 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2009, - 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, - 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, - 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, - 0x080c, 0x9c61, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, - 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, - 0x2001, 0x197b, 0x2004, 0x9086, 0xaaaa, 0x1904, 0xabd1, 0x7003, - 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0xa998, - 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080, 0x700e, 0xa998, - 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2e10, - 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab62, - 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xab6c, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, - 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, 0xab17, 0x00de, - 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, - 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, + 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, 0x080c, 0xcb58, 0x0110, + 0x080c, 0xe58c, 0x080c, 0xae90, 0x87ff, 0x1198, 0x00ce, 0x0804, + 0xa742, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa742, 0x9006, 0x012e, + 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, + 0x2071, 0x19e6, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, + 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x19e6, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0540, + 0x2200, 0x9c06, 0x1508, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, + 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, + 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, + 0x959a, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08b0, + 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, + 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x760c, 0x2660, 0x2678, + 0x8cff, 0x0904, 0xa88d, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, + 0x9206, 0x1904, 0xa888, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, + 0x68c0, 0x9005, 0x0904, 0xa85f, 0x080c, 0xa28f, 0x68c3, 0x0000, + 0x080c, 0xa7a7, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2cfc, 0x9006, + 0x080c, 0x2cfc, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, + 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, + 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xcd4f, 0x1180, 0x080c, + 0x31f5, 0x080c, 0xcd60, 0x1518, 0x080c, 0xb821, 0x0400, 0x080c, + 0xa7a7, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, + 0xcd60, 0x1118, 0x080c, 0xb821, 0x0090, 0x6014, 0x2048, 0x080c, + 0xcb58, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, + 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c88, 0x080c, 0xcd43, 0x080c, + 0xcfcc, 0x080c, 0xae90, 0x080c, 0xa67d, 0x00ce, 0x0804, 0xa808, + 0x2c78, 0x600c, 0x2060, 0x0804, 0xa808, 0x012e, 0x000e, 0x002e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, + 0x9086, 0x0006, 0x1d20, 0x080c, 0xe58c, 0x0c08, 0x00d6, 0x080c, + 0x9cc7, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, + 0x0001, 0x2099, 0x1988, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, + 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0xa263, + 0x00de, 0x0005, 0x080c, 0x9cc7, 0x700b, 0x0800, 0x7814, 0x9084, + 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, + 0x7858, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, 0x7858, 0x9084, + 0xff00, 0x8007, 0x7006, 0x60c2, 0x0804, 0xa263, 0x00b6, 0x00d6, + 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, 0xd1d2, 0x00de, + 0x1904, 0xa93b, 0x080c, 0x9c7c, 0x7003, 0x1300, 0x782c, 0x080c, + 0xaa41, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, + 0xbaa0, 0x080c, 0xadc9, 0x11d8, 0x9286, 0x007e, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, 0x0180, 0x9286, + 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0400, 0x92d8, + 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, 0x00c0, 0x6098, + 0x700e, 0x00a8, 0x080c, 0xadc9, 0x1130, 0x7810, 0x2058, 0xb8a0, + 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f, 0x2d04, 0x700a, + 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, + 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, + 0xa263, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, + 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, + 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xa9b6, 0x9186, 0x0005, + 0x0904, 0xa99e, 0x9186, 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, + 0xa9a7, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, + 0xaa1e, 0x0005, 0x080c, 0xa9df, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x2009, 0x4000, 0x6800, 0x0002, 0xa97f, 0xa98a, 0xa981, 0xa98a, + 0xa986, 0xa97f, 0xa97f, 0xa98a, 0xa98a, 0xa98a, 0xa98a, 0xa97f, + 0xa97f, 0xa97f, 0xa97f, 0xa97f, 0xa98a, 0xa97f, 0xa98a, 0x080c, + 0x0dd5, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, + 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0xa9d8, + 0x080c, 0xa9df, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, + 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04d0, 0x080c, 0xa9df, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x0488, 0x04b9, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, + 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, 0x0410, 0x0441, 0x00d6, + 0x0026, 0x792c, 0x2168, 0x6814, 0x6924, 0xc185, 0x6926, 0x0096, + 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, + 0x7022, 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, + 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, + 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0xa263, 0x00b6, + 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x9cc7, 0x9006, 0x7003, + 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, + 0x080c, 0xadc9, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, + 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, + 0xbc14, 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, + 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, + 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, + 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, 0x080c, 0x9cc7, + 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, + 0x0008, 0x0804, 0xa263, 0x080c, 0x9c73, 0x7003, 0x1400, 0x7838, + 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, + 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, + 0xa263, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, + 0x00b6, 0x2058, 0xb8cc, 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, + 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x9cbe, + 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, + 0x0804, 0xa263, 0x0021, 0x60c3, 0x0000, 0x0804, 0xa263, 0x00d6, + 0x080c, 0xab1a, 0xb810, 0x9085, 0x0300, 0x7002, 0xb814, 0x7006, + 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0819, + 0x080c, 0xa251, 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, + 0x024c, 0x00de, 0x0005, 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, + 0x60a7, 0x9575, 0x0026, 0x080c, 0x2bb2, 0x0228, 0x2011, 0x0101, + 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa286, 0x080c, 0x8576, + 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7858, 0x2048, 0xaa7c, + 0x9296, 0x00c0, 0x9294, 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, + 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, + 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, + 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, 0xab1a, 0x00de, + 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, + 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, + 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, + 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, + 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, + 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, + 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, + 0x2009, 0x19b1, 0x210c, 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, + 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, + 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, + 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, + 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x080c, 0x9c7c, + 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, + 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, 0x2001, 0x197b, + 0x2004, 0x9086, 0xaaaa, 0x1904, 0xabbf, 0x7003, 0x5400, 0x00c6, + 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, + 0xff00, 0x9105, 0x700a, 0x6080, 0x700e, 0xa998, 0x918c, 0xff00, + 0x7112, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2e10, 0x9290, 0x0006, + 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab50, 0x20a9, 0x0004, + 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab5a, + 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008, 0x20a9, 0x0001, - 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00ce, 0x60c3, - 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x1168, 0x080c, 0x73a5, 0x0150, 0x6028, 0xc0bd, - 0x602a, 0x6014, 0x9084, 0x1804, 0x9085, 0x0029, 0x6016, 0x0010, - 0x080c, 0xa248, 0x080c, 0x8559, 0x00de, 0x009e, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, - 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, - 0x0804, 0xab47, 0x080c, 0x9c61, 0x0016, 0x0026, 0x0096, 0x00d6, - 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500, 0x00c6, 0xa89c, - 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, - 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff, 0x9105, 0x700e, - 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, - 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290, 0x0006, 0x20a9, - 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x20a9, - 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, - 0xac23, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xac2d, 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, - 0xab17, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, - 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, - 0xac43, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0xac54, - 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa248, 0x080c, 0x8559, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, - 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, - 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, - 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, - 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x6014, 0x2048, 0xa878, 0x6056, 0x9006, 0xa836, - 0xa83a, 0xa99c, 0xa946, 0xa84a, 0x6023, 0x0003, 0x6007, 0x0040, - 0x6003, 0x0003, 0x600b, 0xffff, 0xa817, 0x0001, 0xa842, 0xa83e, - 0x2900, 0xa85a, 0xa813, 0x2090, 0x080c, 0x913e, 0x0126, 0x2091, - 0x8000, 0x080c, 0x97b5, 0x012e, 0x009e, 0x00de, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e6, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, - 0xad3b, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0904, 0xad0d, 0x080c, 0xa274, 0x68c3, 0x0000, 0x080c, 0xa7bd, - 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2cf1, 0x9006, 0x080c, 0x2cf1, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, - 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, - 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x080c, 0xcd3f, 0x1180, 0x080c, 0x31ea, 0x080c, - 0xcd50, 0x1518, 0x080c, 0xb824, 0x0400, 0x080c, 0xa7bd, 0x6824, - 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xcd50, 0x1118, - 0x080c, 0xb824, 0x0090, 0x6014, 0x2048, 0x080c, 0xcb48, 0x0168, - 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6c86, 0x080c, 0xcd33, 0x080c, 0xcfbc, 0x080c, - 0xaea2, 0x080c, 0xa693, 0x00ce, 0x0804, 0xacbe, 0x2c78, 0x600c, - 0x2060, 0x0804, 0xacbe, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, - 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xe572, 0x08f0, 0x00d6, - 0x0156, 0x080c, 0x9cac, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, - 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, - 0xc38d, 0x0060, 0x080c, 0x73a5, 0x1110, 0xc3ad, 0x0008, 0xc3a5, - 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, - 0x85c2, 0x20a9, 0x0006, 0x2011, 0xfff4, 0x2019, 0xfff5, 0x2071, - 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, - 0x0002, 0x9290, 0x0002, 0x1f04, 0xad81, 0x60c3, 0x0020, 0x080c, - 0xa248, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9cac, 0x7a14, - 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, - 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, - 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19bc, 0x2204, - 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, - 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7022, - 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, 0x2004, - 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, - 0x015e, 0x0804, 0xa248, 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, - 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xa654, 0x2011, 0x0002, - 0x080c, 0xa65e, 0x080c, 0xa541, 0x0036, 0x901e, 0x080c, 0xa5b7, - 0x003e, 0x0005, 0x080c, 0x3320, 0x0188, 0x0016, 0x00b6, 0x00c6, - 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x6608, - 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, - 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976, 0x2071, 0x1800, - 0x7076, 0x707a, 0x706b, 0xffe0, 0x2071, 0x1800, 0x7074, 0x7056, - 0x705b, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, - 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, 0x7058, 0x2060, 0x6000, + 0x00d6, 0x2069, 0x0200, 0x080c, 0xab05, 0x00de, 0x2071, 0x0240, + 0x2011, 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, 0x4002, 0x8007, + 0x2012, 0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, 0x20a9, 0x0001, + 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0xa85c, 0x9080, + 0x0031, 0x2098, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, + 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00ce, 0x60c3, 0x004c, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, + 0x1168, 0x080c, 0x73b3, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0029, 0x6016, 0x0010, 0x080c, 0xa263, + 0x080c, 0x8576, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00e6, + 0x2071, 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, + 0xffff, 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, 0x0804, 0xab35, + 0x080c, 0x9c7c, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, + 0x7013, 0x0138, 0x7003, 0x5500, 0x00c6, 0xa89c, 0x9084, 0x00ff, + 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0xa99c, 0x918c, + 0xff00, 0xa8a0, 0x9084, 0x00ff, 0x9105, 0x700e, 0xa998, 0x918c, + 0xff00, 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0x910d, 0x7112, + 0x6180, 0x7116, 0x2009, 0x0008, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0029, 0x2098, 0x2e10, 0x9290, 0x0006, 0x20a9, 0x0001, 0x4002, + 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x20a9, 0x0004, 0x2009, + 0x1805, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xac11, 0x20a9, + 0x0002, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, + 0xac1b, 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, 0xab05, 0x001e, + 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, 0x1803, 0x2011, + 0x0240, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xac31, 0x2009, + 0x0008, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dd0, 0x9006, + 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, 0xac42, 0x00ce, 0x60c3, + 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa263, 0x080c, + 0x8576, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x9290, + 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, + 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, + 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, + 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, 0x0096, + 0x6014, 0x2048, 0xa878, 0x6056, 0x9006, 0xa836, 0xa83a, 0xa99c, + 0xa946, 0xa84a, 0x6023, 0x0003, 0x6007, 0x0040, 0x6003, 0x0003, + 0x600b, 0xffff, 0xa817, 0x0001, 0xa842, 0xa83e, 0x2900, 0xa85a, + 0xa813, 0x209b, 0x080c, 0x915d, 0x0126, 0x2091, 0x8000, 0x080c, + 0x97d4, 0x012e, 0x009e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, + 0x19e6, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0xad29, 0x7024, + 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacfb, + 0x080c, 0xa28f, 0x68c3, 0x0000, 0x080c, 0xa7a7, 0x7027, 0x0000, + 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, + 0x0100, 0x080c, 0x2cfc, 0x9006, 0x080c, 0x2cfc, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, + 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, + 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, + 0x080c, 0xcd4f, 0x1180, 0x080c, 0x31f5, 0x080c, 0xcd60, 0x1518, + 0x080c, 0xb821, 0x0400, 0x080c, 0xa7a7, 0x6824, 0xd084, 0x09b0, + 0x6827, 0x0001, 0x0898, 0x080c, 0xcd60, 0x1118, 0x080c, 0xb821, + 0x0090, 0x6014, 0x2048, 0x080c, 0xcb58, 0x0168, 0x6020, 0x9086, + 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0x6c94, 0x080c, 0xcd43, 0x080c, 0xcfcc, 0x080c, 0xae90, 0x080c, + 0xa67d, 0x00ce, 0x0804, 0xacac, 0x2c78, 0x600c, 0x2060, 0x0804, + 0xacac, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x006e, 0x009e, + 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1d08, 0x080c, 0xe58c, 0x08f0, 0x00d6, 0x0156, 0x080c, + 0x9cc7, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, + 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, + 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, + 0x080c, 0x73b3, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6adc, 0xd29c, + 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, 0x85df, 0x20a9, + 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x2071, 0x0250, 0x2305, + 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, + 0x0002, 0x1f04, 0xad6f, 0x60c3, 0x0020, 0x080c, 0xa263, 0x015e, + 0x00de, 0x0005, 0x0156, 0x080c, 0x9cc7, 0x7a14, 0x82ff, 0x0168, + 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, + 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, + 0x001c, 0x700f, 0x0001, 0x2011, 0x19bc, 0x2204, 0x8007, 0x701a, + 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, + 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7022, 0x2001, 0x1820, + 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, + 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, + 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, + 0xa263, 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, 0x000e, 0x0005, + 0x2011, 0x0003, 0x080c, 0xa63e, 0x2011, 0x0002, 0x080c, 0xa648, + 0x080c, 0xa552, 0x0036, 0x901e, 0x080c, 0xa5c8, 0x003e, 0x0005, + 0x080c, 0x332b, 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, 0x9085, + 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x6616, 0xb85c, 0xc0ac, + 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, 0x188d, 0x7000, + 0x9005, 0x0140, 0x2001, 0x0976, 0x2071, 0x1800, 0x7076, 0x707a, + 0x706b, 0xffe0, 0x2071, 0x1800, 0x7074, 0x7056, 0x705b, 0x1cd0, + 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, + 0x9582, 0x0010, 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, + 0x0148, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, + 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x0018, + 0x7068, 0x9502, 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, + 0x0005, 0x705b, 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, + 0x1800, 0x7554, 0x9582, 0x0010, 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, - 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, 0x9085, 0x0001, - 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, - 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, 0x0010, 0x0600, 0x7058, + 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1228, 0x755a, 0x9085, 0x0001, + 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, + 0x1cd0, 0x0a0c, 0x0dd5, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, + 0x0dd5, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, + 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, 0x605a, 0x6026, + 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x6042, 0x602a, + 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x9086, 0x0001, 0x0108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x96a6, 0x012e, 0x0cc0, + 0x0006, 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, 0xd084, 0x190c, + 0x1a70, 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, 0x1985, 0x2004, + 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, + 0xe846, 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, + 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1228, 0x755a, - 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc8, 0x9006, - 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0dd5, 0x2001, 0x181a, 0x2004, - 0x9c02, 0x1a0c, 0x0dd5, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, - 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, - 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, - 0x6042, 0x602a, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x9086, - 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x9687, - 0x012e, 0x0cc0, 0x0006, 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, - 0xd084, 0x190c, 0x1a60, 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, - 0x1985, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, - 0x601a, 0x080c, 0xe82c, 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, - 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, - 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, - 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, - 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, - 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, - 0xaeff, 0xaf08, 0xaf23, 0xaf3e, 0xd270, 0xd28d, 0xd2a8, 0xaeff, - 0xaf08, 0x8d74, 0xaf5a, 0xaeff, 0xaeff, 0xaeff, 0xaeff, 0x9186, - 0x0013, 0x1128, 0x080c, 0x957b, 0x080c, 0x9687, 0x0005, 0x0005, + 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, + 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, + 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xaeed, 0xaef6, + 0xaf11, 0xaf2c, 0xd280, 0xd29d, 0xd2b8, 0xaeed, 0xaef6, 0x8d93, + 0xaf48, 0xaeed, 0xaeed, 0xaeed, 0xaeed, 0x9186, 0x0013, 0x1128, + 0x080c, 0x959a, 0x080c, 0x96a6, 0x0005, 0x0005, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0dd5, 0x0013, 0x006e, 0x0005, 0xaf0f, + 0xb68b, 0xb868, 0xaf0f, 0xb8fe, 0xb22b, 0xaf0f, 0xaf0f, 0xb60d, + 0xbe65, 0xaf0f, 0xaf0f, 0xaf0f, 0xaf0f, 0xaf0f, 0xaf0f, 0x080c, + 0x0dd5, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dd5, 0x0013, + 0x006e, 0x0005, 0xaf2a, 0xc53c, 0xaf2a, 0xaf2a, 0xaf2a, 0xaf2a, + 0xaf2a, 0xaf2a, 0xc4de, 0xc6be, 0xaf2a, 0xc57d, 0xc5fc, 0xc57d, + 0xc5fc, 0xaf2a, 0x080c, 0x0dd5, 0x6000, 0x9082, 0x0016, 0x1a0c, + 0x0dd5, 0x6000, 0x0002, 0xaf46, 0xbeac, 0xbf91, 0xc0c1, 0xc26c, + 0xaf46, 0xaf46, 0xaf46, 0xbe80, 0xc46a, 0xc46d, 0xaf46, 0xaf46, + 0xaf46, 0xaf46, 0xc49c, 0xaf46, 0xaf46, 0xaf46, 0x080c, 0x0dd5, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dd5, 0x0013, 0x006e, - 0x0005, 0xaf21, 0xb690, 0xb86b, 0xaf21, 0xb901, 0xb23d, 0xaf21, - 0xaf21, 0xb612, 0xbe68, 0xaf21, 0xaf21, 0xaf21, 0xaf21, 0xaf21, - 0xaf21, 0x080c, 0x0dd5, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, - 0x0dd5, 0x0013, 0x006e, 0x0005, 0xaf3c, 0xc53c, 0xaf3c, 0xaf3c, - 0xaf3c, 0xaf3c, 0xaf3c, 0xaf3c, 0xc4e1, 0xc6be, 0xaf3c, 0xc57d, - 0xc5fc, 0xc57d, 0xc5fc, 0xaf3c, 0x080c, 0x0dd5, 0x6000, 0x9082, - 0x0016, 0x1a0c, 0x0dd5, 0x6000, 0x0002, 0xaf58, 0xbeaf, 0xbf94, - 0xc0c4, 0xc26f, 0xaf58, 0xaf58, 0xaf58, 0xbe83, 0xc46d, 0xc470, - 0xaf58, 0xaf58, 0xaf58, 0xaf58, 0xc49f, 0xaf58, 0xaf58, 0xaf58, - 0x080c, 0x0dd5, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dd5, - 0x0013, 0x006e, 0x0005, 0xaf73, 0xaf73, 0xafb6, 0xb055, 0xb0ea, - 0xaf73, 0xaf73, 0xaf73, 0xaf75, 0xaf73, 0xaf73, 0xaf73, 0xaf73, - 0xaf73, 0xaf73, 0xaf73, 0x080c, 0x0dd5, 0x9186, 0x004c, 0x0588, - 0x9186, 0x0003, 0x190c, 0x0dd5, 0x0096, 0x601c, 0xc0ed, 0x601e, - 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, - 0xc0b5, 0xa87e, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0x9006, 0xa836, - 0xa83a, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, 0x2c10, 0x080c, 0x1baf, - 0x080c, 0x913e, 0x0126, 0x2091, 0x8000, 0x080c, 0x97b5, 0x012e, - 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, - 0xb10c, 0x080c, 0xd262, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, - 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, - 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, - 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, - 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, - 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, - 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, - 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, - 0xb01d, 0xb01d, 0xb018, 0xb01b, 0xb01d, 0xb015, 0xb008, 0xb008, - 0xb008, 0xb008, 0xb008, 0xb008, 0xb008, 0xb008, 0xb008, 0xb008, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, - 0x00fe, 0x009e, 0x00de, 0x080c, 0x0dd5, 0x080c, 0xbac0, 0x0028, - 0x080c, 0xbba5, 0x0010, 0x080c, 0xbc9b, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xb1ca, - 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x125d, - 0x080c, 0xb38b, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, - 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0xae71, 0x2001, - 0x002c, 0x900e, 0x080c, 0xb230, 0x0c70, 0x91b6, 0x0015, 0x0170, - 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0dd5, 0x91b2, - 0x0050, 0x1a0c, 0x0dd5, 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, - 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x080c, 0x908b, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, - 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0xafb6, 0x0005, 0xb088, - 0xb088, 0xb08a, 0xb0c0, 0xb088, 0xb088, 0xb088, 0xb088, 0xb0d3, - 0x080c, 0x0dd5, 0x00d6, 0x0016, 0x0096, 0x080c, 0x9637, 0x080c, - 0x97b5, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, - 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, - 0x0000, 0x900e, 0x080c, 0xb230, 0x080c, 0xae71, 0x00a8, 0x6003, - 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, - 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, - 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, - 0x080c, 0x9637, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xcb4a, - 0x0120, 0xa87b, 0x0006, 0x080c, 0x6c86, 0x009e, 0x00de, 0x080c, - 0xae71, 0x0804, 0x97b5, 0x080c, 0x9637, 0x080c, 0x31c1, 0x080c, - 0xd25f, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xcb4a, 0x0120, - 0xa87b, 0x0029, 0x080c, 0x6c86, 0x009e, 0x00de, 0x080c, 0xae71, - 0x0804, 0x97b5, 0x9182, 0x0047, 0x0002, 0xb0fa, 0xb0fc, 0xb0fa, - 0xb0fa, 0xb0fa, 0xb0fa, 0xb0fa, 0xb0fa, 0xb0fa, 0xb0fa, 0xb0fa, - 0xb0fa, 0xb0fc, 0x080c, 0x0dd5, 0x00d6, 0x0096, 0x601f, 0x0000, - 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, 0x6c86, - 0x009e, 0x00de, 0x0804, 0xae71, 0x0026, 0x0036, 0x0056, 0x0066, - 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x0fff, 0x000e, 0x090c, + 0x0005, 0xaf61, 0xaf61, 0xafa4, 0xb043, 0xb0d8, 0xaf61, 0xaf61, + 0xaf61, 0xaf63, 0xaf61, 0xaf61, 0xaf61, 0xaf61, 0xaf61, 0xaf61, + 0xaf61, 0x080c, 0x0dd5, 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, + 0x190c, 0x0dd5, 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, + 0x6106, 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, + 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0x9006, 0xa836, 0xa83a, 0xa884, + 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, + 0x9210, 0x621a, 0x009e, 0x2c10, 0x080c, 0x1bba, 0x080c, 0x915d, + 0x0126, 0x2091, 0x8000, 0x080c, 0x97d4, 0x012e, 0x0005, 0x6010, + 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, 0xb0fa, 0x080c, + 0xd272, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, + 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, + 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, + 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, + 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, + 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, + 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, + 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, + 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0xb00b, 0xb00b, + 0xb006, 0xb009, 0xb00b, 0xb003, 0xaff6, 0xaff6, 0xaff6, 0xaff6, + 0xaff6, 0xaff6, 0xaff6, 0xaff6, 0xaff6, 0xaff6, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, + 0x00de, 0x080c, 0x0dd5, 0x080c, 0xbabd, 0x0028, 0x080c, 0xbba2, + 0x0010, 0x080c, 0xbc98, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, + 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xb1b8, 0x0530, 0xa804, + 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, + 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x125d, 0x080c, 0xb379, + 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, + 0x00fe, 0x009e, 0x00de, 0x0804, 0xae5f, 0x2001, 0x002c, 0x900e, + 0x080c, 0xb21e, 0x0c70, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, + 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0dd5, 0x91b2, 0x0050, 0x1a0c, + 0x0dd5, 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, + 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, + 0x90aa, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, + 0x0002, 0x1110, 0x0804, 0xafa4, 0x0005, 0xb076, 0xb076, 0xb078, + 0xb0ae, 0xb076, 0xb076, 0xb076, 0xb076, 0xb0c1, 0x080c, 0x0dd5, + 0x00d6, 0x0016, 0x0096, 0x080c, 0x9656, 0x080c, 0x97d4, 0x6003, + 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, + 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, + 0x080c, 0xb21e, 0x080c, 0xae5f, 0x00a8, 0x6003, 0x0002, 0xa8a4, + 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, + 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, + 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, 0x080c, 0x9656, + 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xcb5a, 0x0120, 0xa87b, + 0x0006, 0x080c, 0x6c94, 0x009e, 0x00de, 0x080c, 0xae5f, 0x0804, + 0x97d4, 0x080c, 0x9656, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x00d6, + 0x0096, 0x6114, 0x2148, 0x080c, 0xcb5a, 0x0120, 0xa87b, 0x0029, + 0x080c, 0x6c94, 0x009e, 0x00de, 0x080c, 0xae5f, 0x0804, 0x97d4, + 0x9182, 0x0047, 0x0002, 0xb0e8, 0xb0ea, 0xb0e8, 0xb0e8, 0xb0e8, + 0xb0e8, 0xb0e8, 0xb0e8, 0xb0e8, 0xb0e8, 0xb0e8, 0xb0e8, 0xb0ea, + 0x080c, 0x0dd5, 0x00d6, 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, + 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, 0x6c94, 0x009e, 0x00de, + 0x0804, 0xae5f, 0x0026, 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, + 0x00f6, 0x0006, 0x080c, 0x0fff, 0x000e, 0x090c, 0x0dd5, 0xa960, + 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, + 0x4104, 0xa87a, 0x2079, 0x1800, 0x7990, 0x9188, 0x0018, 0x918c, + 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, + 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, 0x2011, + 0x001f, 0x080c, 0xc743, 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, + 0x001f, 0x080c, 0xc743, 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, + 0x080c, 0x0fb1, 0x080c, 0x0fff, 0x01d0, 0x8528, 0xa867, 0x0110, + 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, + 0x2011, 0x001b, 0x080c, 0xc743, 0x00b8, 0x96b2, 0x003c, 0x2009, + 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, 0xc743, 0x0c18, 0x2001, + 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, + 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, + 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, + 0x0000, 0x0006, 0x080c, 0x6c94, 0x000e, 0x2048, 0x9005, 0x1db0, + 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, + 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, 0x0fff, 0x000e, 0x090c, 0x0dd5, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, - 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, 0x7990, 0x9188, - 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, - 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, - 0x1228, 0x2011, 0x001f, 0x080c, 0xc743, 0x04c0, 0x2130, 0x2009, - 0x0034, 0x2011, 0x001f, 0x080c, 0xc743, 0x96b2, 0x0034, 0xb004, - 0x904d, 0x0110, 0x080c, 0x0fb1, 0x080c, 0x0fff, 0x01d0, 0x8528, - 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, - 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xc743, 0x00b8, 0x96b2, - 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, 0xc743, - 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, - 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, - 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x6c86, 0x000e, 0x2048, - 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, - 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, 0x0fff, - 0x000e, 0x090c, 0x0dd5, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, - 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, - 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, - 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, - 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, 0x6c86, 0x009e, 0x00fe, - 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, - 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, - 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, - 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, - 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, 0x0fff, 0x2900, 0x009e, - 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, - 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, - 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, - 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, - 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, - 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, - 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb1df, 0x0804, 0xb1e1, 0x9085, - 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, - 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, - 0x6c7a, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, - 0x080c, 0xae71, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0dd5, 0x080c, - 0xae71, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, - 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, - 0x0136, 0x9080, 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, - 0x3418, 0x8318, 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, - 0x1db8, 0x2011, 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, - 0x4003, 0x3418, 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, - 0xcb4a, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0x009e, 0x0804, 0xae71, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, - 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8cf, 0x0000, 0x00be, - 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xab32, 0x080c, 0xae71, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, - 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xd24a, 0x0188, 0x6014, - 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, - 0x2009, 0x0022, 0x080c, 0xb668, 0x9006, 0x001e, 0x000e, 0x0005, - 0x9085, 0x0001, 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, - 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, - 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, - 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, - 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, - 0x0020, 0x4003, 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x080c, 0xae71, 0x001e, 0x009e, 0x0005, 0x0096, - 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, - 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, - 0x9108, 0x810b, 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, - 0x080c, 0xc743, 0x080c, 0xcb4a, 0x0140, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xae71, 0x001e, - 0x009e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, - 0x0110, 0x2009, 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dd5, - 0xa97a, 0x080c, 0x6c86, 0x009e, 0x080c, 0xae71, 0x001e, 0x0005, - 0x0016, 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, - 0x0010, 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, - 0x6014, 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, - 0xc743, 0x009e, 0x080c, 0xcb4a, 0x0148, 0xa804, 0x9005, 0x1158, - 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xae71, - 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, - 0x0100, 0x1118, 0x080c, 0xb824, 0x00e0, 0xa034, 0x8007, 0x800c, - 0x8806, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x000c, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1243, 0x0019, - 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x0fff, 0x000e, - 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, - 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, - 0x0086, 0x2940, 0x080c, 0x10e9, 0x008e, 0x9085, 0x0001, 0x009e, - 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, - 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, - 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, - 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xd1c2, 0x001e, 0x1158, - 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, - 0x9386, 0x0006, 0x0128, 0x080c, 0xae71, 0x0020, 0x0039, 0x0010, - 0x080c, 0xb49d, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, - 0x2048, 0x9186, 0x0015, 0x0904, 0xb485, 0x918e, 0x0016, 0x1904, - 0xb49b, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, - 0x0300, 0x1904, 0xb45f, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, - 0x0904, 0xb442, 0x0804, 0xb499, 0x6808, 0x9086, 0xffff, 0x1904, - 0xb487, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, - 0xa940, 0x9105, 0x1904, 0xb487, 0x6824, 0xd0b4, 0x1904, 0xb487, - 0x080c, 0xcd33, 0x685c, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, - 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x8f51, - 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, - 0x00c6, 0x2d60, 0x080c, 0xc86d, 0x00ce, 0x0804, 0xb499, 0x00c6, - 0xa868, 0xd0fc, 0x1118, 0x080c, 0x60b7, 0x0010, 0x080c, 0x64bd, - 0x00ce, 0x1904, 0xb487, 0x00c6, 0x2d60, 0x080c, 0xae71, 0x00ce, - 0x0804, 0xb499, 0x00c6, 0x080c, 0xaebf, 0x0198, 0x6017, 0x0000, - 0x6810, 0x6012, 0x080c, 0xcfc4, 0x6023, 0x0003, 0x6904, 0x00c6, - 0x2d60, 0x080c, 0xae71, 0x00ce, 0x080c, 0xaeec, 0x00ce, 0x0804, - 0xb499, 0x2001, 0x1987, 0x2004, 0x6842, 0x00ce, 0x04d0, 0x7008, - 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, 0xc1bc, - 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, 0xd204, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x90d9, - 0x080c, 0x9687, 0x00ce, 0x00e8, 0x700c, 0x9086, 0x2a00, 0x1138, - 0x2001, 0x1987, 0x2004, 0x6842, 0x00a0, 0x0479, 0x00a0, 0x89ff, - 0x090c, 0x0dd5, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, 0xa87b, - 0x0003, 0x080c, 0x6aa2, 0x080c, 0xcd33, 0x080c, 0xaea2, 0x00de, - 0x00ce, 0x080c, 0xae71, 0x009e, 0x0005, 0x9186, 0x0015, 0x1128, - 0x2001, 0x1987, 0x2004, 0x6842, 0x0068, 0x918e, 0x0016, 0x1160, - 0x00c6, 0x2d00, 0x2060, 0x080c, 0xe82c, 0x080c, 0x869b, 0x080c, - 0xae71, 0x00ce, 0x080c, 0xae71, 0x0005, 0x0026, 0x0036, 0x0046, - 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, 0x1987, 0x2004, - 0x6842, 0x0804, 0xb517, 0x00c6, 0x2d60, 0x080c, 0xc76e, 0x00ce, - 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, - 0x0001, 0x6007, 0x0050, 0x080c, 0x90d9, 0x080c, 0x9687, 0x00ce, - 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, 0x090c, 0x0dd5, - 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, 0x0178, 0xa843, - 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, 0x2001, 0x0001, - 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, 0xa87c, 0xd0b4, - 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, 0xa838, 0xa934, - 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, 0x9306, 0x1118, - 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, - 0x0005, 0x6832, 0x080c, 0xcebb, 0x080c, 0x9687, 0x0010, 0x080c, - 0xae71, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, - 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, - 0x9206, 0x1904, 0xb582, 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, - 0x00be, 0x9206, 0x1904, 0xb582, 0x6038, 0x2068, 0x6824, 0xc0dc, - 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb582, 0x9286, 0x0002, - 0x0904, 0xb582, 0x9286, 0x0000, 0x05e8, 0x6808, 0x633c, 0x9306, - 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, 0x918e, 0x0016, - 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01c0, - 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, 0x9186, 0x004e, - 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, 0x2048, 0x080c, - 0xcb4a, 0x090c, 0x0dd5, 0xa87b, 0x0003, 0x009e, 0x080c, 0xd204, - 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x90d9, - 0x080c, 0x9687, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, 0x1987, - 0x2004, 0x7042, 0x080c, 0xae71, 0x002e, 0x00de, 0x00ee, 0x0005, - 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, 0x2058, 0x91b6, - 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, 0xbc02, 0x0460, - 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0010, 0x2019, - 0x000a, 0x20a9, 0x0004, 0x080c, 0xbe30, 0x002e, 0x003e, 0x015e, - 0x009e, 0x1904, 0xb5f1, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, - 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, 0x080c, 0xbe30, - 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, 0xba0a, 0x733c, - 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, - 0x009e, 0x00be, 0x0804, 0xb276, 0x0096, 0x2048, 0xaa12, 0xab16, - 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, - 0xada4, 0x2031, 0x0000, 0x2041, 0x1243, 0x080c, 0xb38b, 0x0130, - 0x00fe, 0x009e, 0x080c, 0xae71, 0x00be, 0x0005, 0x080c, 0xb824, - 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x31c1, 0x080c, 0xd25f, 0x00fe, - 0x00c6, 0x080c, 0xae1b, 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, - 0x6558, 0x080c, 0x6584, 0x080c, 0x9121, 0x080c, 0x9687, 0x00ce, - 0x0804, 0xb5c4, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0dd5, 0x91b2, - 0x0040, 0x1a04, 0xb67a, 0x0002, 0xb668, 0xb668, 0xb65e, 0xb668, - 0xb668, 0xb668, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, - 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, - 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, - 0xb65c, 0xb65c, 0xb65c, 0xb668, 0xb65c, 0xb668, 0xb668, 0xb65c, - 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65e, 0xb65c, 0xb65c, 0xb65c, - 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb668, 0xb668, - 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, 0xb65c, - 0xb65c, 0xb668, 0xb65c, 0xb65c, 0x080c, 0x0dd5, 0x0066, 0x00b6, - 0x6610, 0x2658, 0xb8cc, 0xc08c, 0xb8ce, 0x00be, 0x006e, 0x0000, - 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, 0x9121, - 0x0010, 0x080c, 0x90d9, 0x0126, 0x2091, 0x8000, 0x080c, 0x9687, - 0x012e, 0x0005, 0x2600, 0x0002, 0xb668, 0xb668, 0xb68e, 0xb668, - 0xb668, 0xb68e, 0xb68e, 0xb68e, 0xb68e, 0xb668, 0xb68e, 0xb668, - 0xb68e, 0xb668, 0xb68e, 0xb68e, 0xb68e, 0xb68e, 0x080c, 0x0dd5, - 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dd5, 0x91b6, 0x0013, 0x0904, - 0xb752, 0x91b6, 0x0027, 0x1904, 0xb70d, 0x080c, 0x957b, 0x6004, - 0x080c, 0xcd3f, 0x01b0, 0x080c, 0xcd50, 0x01a8, 0x908e, 0x0021, - 0x0904, 0xb70a, 0x908e, 0x0022, 0x1130, 0x080c, 0xb2a2, 0x0904, - 0xb706, 0x0804, 0xb707, 0x908e, 0x003d, 0x0904, 0xb70a, 0x0804, - 0xb700, 0x080c, 0x31ea, 0x2001, 0x0007, 0x080c, 0x6558, 0x6010, - 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xb824, 0x9186, 0x007e, - 0x1148, 0x2001, 0x1837, 0x2014, 0xc285, 0x080c, 0x73a5, 0x1108, - 0xc2ad, 0x2202, 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, - 0xe938, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, - 0x0028, 0x080c, 0x927e, 0x0076, 0x903e, 0x080c, 0x9151, 0x6010, - 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, 0xe30c, 0x007e, - 0x003e, 0x002e, 0x001e, 0x080c, 0xd25f, 0x0016, 0x080c, 0xcfbc, - 0x080c, 0xae71, 0x001e, 0x080c, 0x32bd, 0x080c, 0x9687, 0x0030, - 0x080c, 0xcfbc, 0x080c, 0xae71, 0x080c, 0x9687, 0x0005, 0x080c, - 0xb824, 0x0cb0, 0x080c, 0xb860, 0x0c98, 0x9186, 0x0014, 0x1db0, - 0x080c, 0x957b, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb2a2, - 0x0d68, 0x080c, 0x31c1, 0x080c, 0xd25f, 0x080c, 0xcd3f, 0x1190, - 0x080c, 0x31ea, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, - 0xb824, 0x9186, 0x007e, 0x1128, 0x2001, 0x1837, 0x200c, 0xc185, - 0x2102, 0x0870, 0x080c, 0xcd50, 0x1118, 0x080c, 0xb824, 0x0840, - 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, - 0x2079, 0x0000, 0x080c, 0x3558, 0x00fe, 0x00ee, 0x0804, 0xb700, - 0x6004, 0x908e, 0x0021, 0x0d48, 0x908e, 0x0022, 0x090c, 0xb824, - 0x0804, 0xb700, 0x90b2, 0x0040, 0x1a04, 0xb800, 0x2008, 0x0002, - 0xb79a, 0xb79b, 0xb79e, 0xb7a1, 0xb7a4, 0xb7a7, 0xb798, 0xb798, - 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, - 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, - 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb7aa, 0xb7b5, - 0xb798, 0xb7b7, 0xb7b5, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, - 0xb7b5, 0xb7b5, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, 0xb798, - 0xb798, 0xb798, 0xb7e7, 0xb7b5, 0xb798, 0xb7b1, 0xb798, 0xb798, - 0xb798, 0xb7b2, 0xb798, 0xb798, 0xb798, 0xb7b5, 0xb7de, 0xb798, - 0x080c, 0x0dd5, 0x00d0, 0x2001, 0x000b, 0x0410, 0x2001, 0x0003, - 0x00f8, 0x2001, 0x0005, 0x00e0, 0x2001, 0x0001, 0x00c8, 0x2001, - 0x0009, 0x00b0, 0x080c, 0x957b, 0x6003, 0x0005, 0x080c, 0x9687, - 0x0070, 0x0018, 0x0010, 0x080c, 0x6558, 0x0804, 0xb7f8, 0x080c, - 0x957b, 0x080c, 0xd262, 0x6003, 0x0004, 0x080c, 0x9687, 0x0005, - 0x080c, 0x6558, 0x080c, 0x957b, 0x6003, 0x0002, 0x0036, 0x2019, - 0x1852, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, 0x1985, 0x201c, - 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, - 0x9318, 0x631a, 0x003e, 0x080c, 0x9687, 0x0c08, 0x080c, 0x957b, - 0x080c, 0xcfbc, 0x080c, 0xae71, 0x080c, 0x9687, 0x08c0, 0x00e6, - 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x3558, 0x00fe, - 0x00ee, 0x080c, 0x957b, 0x080c, 0xae71, 0x080c, 0x9687, 0x0838, - 0x080c, 0x957b, 0x6003, 0x0002, 0x080c, 0xd262, 0x0804, 0x9687, - 0x2600, 0x2008, 0x0002, 0xb817, 0xb7f8, 0xb815, 0xb7f8, 0xb7f8, - 0xb815, 0xb815, 0xb815, 0xb815, 0xb7f8, 0xb815, 0xb7f8, 0xb815, - 0xb7f8, 0xb815, 0xb815, 0xb815, 0xb815, 0x080c, 0x0dd5, 0x080c, - 0x957b, 0x0096, 0x6014, 0x2048, 0x080c, 0x6c86, 0x009e, 0x080c, - 0xae71, 0x080c, 0x9687, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, - 0x080c, 0xcb4a, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, - 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x5481, 0x0130, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4005, 0x080c, 0xd129, 0x0090, 0xa868, 0xd0fc, - 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, - 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, - 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, - 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, - 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, - 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0dd5, 0x6604, 0x96b6, 0x004d, - 0x1120, 0x080c, 0xd048, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x0043, - 0x1120, 0x080c, 0xd091, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x004b, - 0x1120, 0x080c, 0xd0bd, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x0033, - 0x1120, 0x080c, 0xcfde, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x0028, - 0x1120, 0x080c, 0xcd8e, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x0029, - 0x1120, 0x080c, 0xcdcf, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x001f, - 0x1120, 0x080c, 0xb24a, 0x0804, 0xb8f0, 0x6604, 0x96b6, 0x0000, - 0x1118, 0x080c, 0xb588, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, - 0x080c, 0xb283, 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, - 0xb3a9, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb51d, - 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xb2bb, 0x0400, - 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb2f7, 0x00c8, 0x6604, - 0x96b6, 0x0049, 0x1118, 0x080c, 0xb338, 0x0090, 0x6604, 0x96b6, - 0x0041, 0x1118, 0x080c, 0xb322, 0x0058, 0x91b6, 0x0015, 0x1110, - 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbb4c, - 0x00be, 0x0005, 0x080c, 0xaf07, 0x0cd8, 0xb90d, 0xb910, 0xb90d, - 0xb957, 0xb90d, 0xbac0, 0xbb59, 0xb90d, 0xb90d, 0xbb22, 0xb90d, - 0xbb38, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x009e, 0x0804, 0xae71, 0xa001, 0xa001, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, 0x0074, 0x1540, 0x080c, - 0xe2dd, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, - 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, 0x00f9, 0x00be, 0x2001, - 0x0006, 0x080c, 0x6558, 0x080c, 0x31ea, 0x080c, 0xae71, 0x0098, - 0x2001, 0x000a, 0x080c, 0x6558, 0x080c, 0x31ea, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9121, 0x080c, 0x9687, 0x0020, 0x2001, - 0x0001, 0x080c, 0xba90, 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, - 0x0160, 0x9006, 0x080c, 0x6544, 0x2069, 0x1847, 0x6804, 0xd0a4, - 0x0120, 0x2001, 0x0006, 0x080c, 0x6584, 0x00de, 0x0005, 0x00b6, - 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1904, - 0xba65, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, - 0xbca6, 0x0804, 0xb9c9, 0x080c, 0xbc9b, 0x6010, 0x2058, 0xbaa0, - 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, 0x2048, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, - 0x2011, 0x4000, 0x080c, 0xd129, 0x0030, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, 0x6558, 0x080c, - 0x31ea, 0x080c, 0xae71, 0x0804, 0xba6a, 0x080c, 0xba78, 0x6014, - 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xd129, 0x08f8, 0x080c, 0xba6e, 0x0160, 0x9006, - 0x080c, 0x6544, 0x2001, 0x0004, 0x080c, 0x6584, 0x2001, 0x0007, - 0x080c, 0x6558, 0x08a0, 0x2001, 0x0004, 0x080c, 0x6558, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x9121, 0x080c, 0x9687, 0x0804, - 0xba6a, 0xb85c, 0xd0e4, 0x01d8, 0x080c, 0xcf5e, 0x080c, 0x73a5, - 0x0118, 0xd0dc, 0x1904, 0xb98b, 0x2011, 0x1837, 0x2204, 0xc0ad, - 0x2012, 0x2001, 0x196c, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, - 0x0000, 0x080c, 0x28b4, 0x78e2, 0x00fe, 0x0804, 0xb98b, 0x080c, - 0xcf9b, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, - 0xe462, 0x000e, 0x1904, 0xb98b, 0xc0b5, 0x2012, 0x2001, 0x0006, - 0x080c, 0x6558, 0x9006, 0x080c, 0x6544, 0x00c6, 0x2001, 0x180f, - 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, - 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, - 0x7082, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, - 0x080c, 0x2889, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2840, 0x795e, - 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, - 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, - 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x2889, 0x00f6, 0x2079, 0x1800, - 0x7982, 0x2100, 0x900e, 0x080c, 0x2840, 0x795e, 0x00fe, 0x8108, - 0x080c, 0x65a7, 0x2b00, 0x00ce, 0x1904, 0xb98b, 0x6012, 0x2009, - 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, - 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, 0x0002, - 0x080c, 0x6558, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x9121, 0x080c, 0x9687, 0x0028, 0x080c, 0xb824, 0x2001, - 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, - 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, 0xd0ac, 0x0005, - 0x00e6, 0x080c, 0xe991, 0x0190, 0x2071, 0x0260, 0x7108, 0x720c, - 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, 0x2058, - 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, 0x0005, - 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, 0x080c, 0x6558, 0x080c, - 0x56ec, 0x1120, 0x2001, 0x0007, 0x080c, 0x6584, 0x2600, 0x9005, - 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x1178, - 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0004, 0x2011, 0x8014, 0x080c, 0x4b14, 0x004e, 0x003e, 0x080c, - 0x31ea, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, 0xae71, - 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x7090, 0x9086, - 0x0014, 0x1904, 0xbb18, 0x080c, 0x56ec, 0x1170, 0x6014, 0x9005, - 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, - 0x080c, 0x4ccb, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, - 0x66a3, 0x080c, 0xb945, 0x00de, 0x080c, 0xbd6c, 0x1588, 0x6010, - 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x6558, - 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, + 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, + 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, + 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, + 0x2003, 0x0000, 0x080c, 0x6c94, 0x009e, 0x00fe, 0x00de, 0x0005, + 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, + 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, + 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, + 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, + 0x1170, 0x0096, 0x080c, 0x0fff, 0x2900, 0x009e, 0x05c0, 0xa806, + 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, + 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, + 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, + 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, + 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, + 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, + 0x84ff, 0x0904, 0xb1cd, 0x0804, 0xb1cf, 0x9085, 0x0001, 0x7817, + 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, 0x6c88, 0x009e, + 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0xae5f, + 0x0030, 0x91b6, 0x0016, 0x190c, 0x0dd5, 0x080c, 0xae5f, 0x0005, + 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, + 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, 0x0136, 0x9080, + 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, + 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, + 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, + 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xcb5a, 0x0130, + 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, + 0xae5f, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, + 0x6010, 0x00b6, 0x2058, 0xb8cf, 0x0000, 0x00be, 0x6014, 0x9005, + 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, + 0xae5f, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, + 0x0006, 0x0016, 0x080c, 0xd25a, 0x0188, 0x6014, 0x9005, 0x1170, + 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, + 0x080c, 0xb663, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, + 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, + 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, + 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, + 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, + 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, + 0x080c, 0xae5f, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, + 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, + 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, + 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xc743, + 0x080c, 0xcb5a, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, + 0xa8e2, 0xa867, 0x0103, 0x080c, 0xae5f, 0x001e, 0x009e, 0x0005, + 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, + 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dd5, 0xa97a, 0x080c, + 0x6c94, 0x009e, 0x080c, 0xae5f, 0x001e, 0x0005, 0x0016, 0x0096, + 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, + 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, + 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xc743, 0x009e, + 0x080c, 0xcb5a, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, + 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xae5f, 0x009e, 0x001e, + 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, + 0x080c, 0xb821, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, + 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, + 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, + 0xada4, 0x2031, 0x0000, 0x2041, 0x1243, 0x0019, 0x0d08, 0x008e, + 0x0898, 0x0096, 0x0006, 0x080c, 0x0fff, 0x000e, 0x01b0, 0xa8ab, + 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, + 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, + 0x080c, 0x10e9, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, + 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, + 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, + 0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, + 0x2009, 0x0035, 0x080c, 0xd1d2, 0x001e, 0x1158, 0x622c, 0x2268, + 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, + 0x0128, 0x080c, 0xae5f, 0x0020, 0x0039, 0x0010, 0x080c, 0xb498, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, + 0x0015, 0x0904, 0xb480, 0x918e, 0x0016, 0x1904, 0xb496, 0x700c, + 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, + 0xb45a, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb43d, + 0x0804, 0xb494, 0x6808, 0x9086, 0xffff, 0x1904, 0xb482, 0xa87c, + 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, + 0x1904, 0xb482, 0x6824, 0xd084, 0x1904, 0xb482, 0xd0b4, 0x0158, + 0x0016, 0x2001, 0x1985, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, + 0x001e, 0x1a04, 0xb482, 0x080c, 0xcd43, 0x685c, 0xa882, 0xa87c, + 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, + 0x000a, 0x080c, 0x8f70, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, + 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xc86d, 0x00ce, + 0x0804, 0xb494, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x60c1, + 0x0010, 0x080c, 0x64cb, 0x00ce, 0x1904, 0xb482, 0x00c6, 0x2d60, + 0x080c, 0xae5f, 0x00ce, 0x0804, 0xb494, 0x00c6, 0x080c, 0xaead, + 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xcfd4, 0x6023, + 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0xae5f, 0x00ce, 0x080c, + 0xaeda, 0x00ce, 0x0804, 0xb494, 0x2001, 0x1987, 0x2004, 0x6842, + 0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, + 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, + 0x0003, 0x080c, 0xd214, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x00ce, 0x00e8, 0x700c, + 0x9086, 0x2a00, 0x1138, 0x2001, 0x1987, 0x2004, 0x6842, 0x00a0, + 0x0479, 0x00a0, 0x89ff, 0x090c, 0x0dd5, 0x00c6, 0x00d6, 0x2d60, + 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x6ab0, 0x080c, 0xcd43, + 0x080c, 0xae90, 0x00de, 0x00ce, 0x080c, 0xae5f, 0x009e, 0x0005, + 0x9186, 0x0015, 0x1128, 0x2001, 0x1987, 0x2004, 0x6842, 0x0068, + 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xe846, + 0x080c, 0x86b8, 0x080c, 0xae5f, 0x00ce, 0x080c, 0xae5f, 0x0005, + 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, + 0x2001, 0x1987, 0x2004, 0x6842, 0x0804, 0xb512, 0x00c6, 0x2d60, + 0x080c, 0xc76e, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, + 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x90f8, + 0x080c, 0x96a6, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, + 0x89ff, 0x090c, 0x0dd5, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, + 0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, + 0xa882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, + 0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, + 0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, + 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, + 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xcecb, 0x080c, + 0x96a6, 0x0010, 0x080c, 0xae5f, 0x004e, 0x003e, 0x002e, 0x0005, + 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, + 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xb57d, 0x700c, 0x6210, + 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb57d, 0x6038, + 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, + 0xb57d, 0x9286, 0x0002, 0x0904, 0xb57d, 0x9286, 0x0000, 0x05e8, + 0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, + 0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, + 0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, + 0x0190, 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, + 0x0096, 0x2048, 0x080c, 0xcb5a, 0x090c, 0x0dd5, 0xa87b, 0x0003, + 0x009e, 0x080c, 0xd214, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x00ce, 0x0030, 0x6038, + 0x2070, 0x2001, 0x1987, 0x2004, 0x7042, 0x080c, 0xae5f, 0x002e, + 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, + 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, + 0xc48c, 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, + 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xbe2d, + 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xb5ec, 0x0096, 0x0156, + 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, + 0x0004, 0x080c, 0xbe2d, 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, + 0x7238, 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, + 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xb264, 0x0096, + 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, + 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1243, + 0x080c, 0xb379, 0x0130, 0x00fe, 0x009e, 0x080c, 0xae5f, 0x00be, + 0x0005, 0x080c, 0xb821, 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x31cc, + 0x080c, 0xd26f, 0x00fe, 0x00c6, 0x080c, 0xae09, 0x2f00, 0x6012, + 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, + 0x2001, 0x0007, 0x080c, 0x6566, 0x080c, 0x6592, 0x080c, 0x9140, + 0x080c, 0x96a6, 0x00ce, 0x0804, 0xb5bf, 0x2100, 0x91b2, 0x0053, + 0x1a0c, 0x0dd5, 0x91b2, 0x0040, 0x1a04, 0xb675, 0x0002, 0xb663, + 0xb663, 0xb659, 0xb663, 0xb663, 0xb663, 0xb657, 0xb657, 0xb657, + 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, + 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, + 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb663, 0xb657, + 0xb663, 0xb663, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb659, + 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, + 0xb657, 0xb663, 0xb663, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, + 0xb657, 0xb657, 0xb657, 0xb657, 0xb663, 0xb657, 0xb657, 0x080c, + 0x0dd5, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8cc, 0xc08c, 0xb8ce, + 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, + 0x0118, 0x080c, 0x9140, 0x0010, 0x080c, 0x90f8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x96a6, 0x012e, 0x0005, 0x2600, 0x0002, 0xb663, + 0xb663, 0xb689, 0xb663, 0xb663, 0xb689, 0xb689, 0xb689, 0xb689, + 0xb663, 0xb689, 0xb663, 0xb689, 0xb663, 0xb689, 0xb689, 0xb689, + 0xb689, 0x080c, 0x0dd5, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dd5, + 0x91b6, 0x0013, 0x0904, 0xb74d, 0x91b6, 0x0027, 0x1904, 0xb708, + 0x080c, 0x959a, 0x6004, 0x080c, 0xcd4f, 0x01b0, 0x080c, 0xcd60, + 0x01a8, 0x908e, 0x0021, 0x0904, 0xb705, 0x908e, 0x0022, 0x1130, + 0x080c, 0xb290, 0x0904, 0xb701, 0x0804, 0xb702, 0x908e, 0x003d, + 0x0904, 0xb705, 0x0804, 0xb6fb, 0x080c, 0x31f5, 0x2001, 0x0007, + 0x080c, 0x6566, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, + 0xb821, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, 0xc285, + 0x080c, 0x73b3, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x0026, 0x2019, + 0x0028, 0x2110, 0x080c, 0xe952, 0x002e, 0x003e, 0x0016, 0x0026, + 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x929d, 0x0076, 0x903e, + 0x080c, 0x9170, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, + 0x080c, 0xe326, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xd26f, + 0x0016, 0x080c, 0xcfcc, 0x080c, 0xae5f, 0x001e, 0x080c, 0x32c8, + 0x080c, 0x96a6, 0x0030, 0x080c, 0xcfcc, 0x080c, 0xae5f, 0x080c, + 0x96a6, 0x0005, 0x080c, 0xb821, 0x0cb0, 0x080c, 0xb85d, 0x0c98, + 0x9186, 0x0014, 0x1db0, 0x080c, 0x959a, 0x6004, 0x908e, 0x0022, + 0x1118, 0x080c, 0xb290, 0x0d68, 0x080c, 0x31cc, 0x080c, 0xd26f, + 0x080c, 0xcd4f, 0x1190, 0x080c, 0x31f5, 0x6010, 0x00b6, 0x2058, + 0xb9a0, 0x00be, 0x080c, 0xb821, 0x9186, 0x007e, 0x1128, 0x2001, + 0x1837, 0x200c, 0xc185, 0x2102, 0x0870, 0x080c, 0xcd60, 0x1118, + 0x080c, 0xb821, 0x0840, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, + 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x3563, 0x00fe, + 0x00ee, 0x0804, 0xb6fb, 0x6004, 0x908e, 0x0021, 0x0d48, 0x908e, + 0x0022, 0x090c, 0xb821, 0x0804, 0xb6fb, 0x90b2, 0x0040, 0x1a04, + 0xb7fd, 0x2008, 0x0002, 0xb795, 0xb796, 0xb799, 0xb79c, 0xb79f, + 0xb7a2, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, + 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, + 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, + 0xb793, 0xb7a5, 0xb7b2, 0xb793, 0xb7b4, 0xb7b2, 0xb793, 0xb793, + 0xb793, 0xb793, 0xb793, 0xb7b2, 0xb7b2, 0xb793, 0xb793, 0xb793, + 0xb793, 0xb793, 0xb793, 0xb793, 0xb793, 0xb7e4, 0xb7b2, 0xb793, + 0xb7ae, 0xb793, 0xb793, 0xb793, 0xb7af, 0xb793, 0xb793, 0xb793, + 0xb7b2, 0xb7db, 0xb793, 0x080c, 0x0dd5, 0x00e0, 0x2001, 0x000b, + 0x0420, 0x2001, 0x0003, 0x0408, 0x2001, 0x0005, 0x00f0, 0x2001, + 0x0001, 0x00d8, 0x2001, 0x0009, 0x00c0, 0x080c, 0x959a, 0x6003, + 0x0005, 0x080c, 0xd272, 0x080c, 0x96a6, 0x0070, 0x0018, 0x0010, + 0x080c, 0x6566, 0x0804, 0xb7f5, 0x080c, 0x959a, 0x080c, 0xd272, + 0x6003, 0x0004, 0x080c, 0x96a6, 0x0005, 0x080c, 0x6566, 0x080c, + 0x959a, 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, + 0xff00, 0x1120, 0x2001, 0x1985, 0x201c, 0x0040, 0x8007, 0x909a, + 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, + 0x080c, 0x96a6, 0x0c08, 0x080c, 0x959a, 0x080c, 0xcfcc, 0x080c, + 0xae5f, 0x080c, 0x96a6, 0x08c0, 0x00e6, 0x00f6, 0x2071, 0x189e, + 0x2079, 0x0000, 0x080c, 0x3563, 0x00fe, 0x00ee, 0x080c, 0x959a, + 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0838, 0x080c, 0x959a, 0x6003, + 0x0002, 0x080c, 0xd272, 0x0804, 0x96a6, 0x2600, 0x2008, 0x0002, + 0xb814, 0xb7f5, 0xb812, 0xb7f5, 0xb7f5, 0xb812, 0xb812, 0xb812, + 0xb812, 0xb7f5, 0xb812, 0xb7f5, 0xb812, 0xb7f5, 0xb812, 0xb812, + 0xb812, 0xb812, 0x080c, 0x0dd5, 0x080c, 0x959a, 0x0096, 0x6014, + 0x2048, 0x080c, 0x6c94, 0x009e, 0x080c, 0xae5f, 0x080c, 0x96a6, + 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, 0x080c, 0xcb5a, 0x0568, + 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, + 0x0056, 0x1148, 0x080c, 0x548b, 0x0130, 0x2001, 0x0000, 0x900e, + 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, + 0x080c, 0xd139, 0x0090, 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, + 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, + 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, + 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, + 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, + 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, + 0x1a0c, 0x0dd5, 0x6604, 0x96b6, 0x004d, 0x1120, 0x080c, 0xd058, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, 0xd0a1, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, 0xd0cd, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, 0xcfee, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, 0xcd9e, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, 0xcddf, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x001f, 0x1120, 0x080c, 0xb238, + 0x0804, 0xb8ed, 0x6604, 0x96b6, 0x0000, 0x1118, 0x080c, 0xb583, + 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, 0xb271, 0x04a8, + 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0xb397, 0x0470, 0x6604, + 0x96b6, 0x0039, 0x1118, 0x080c, 0xb518, 0x0438, 0x6604, 0x96b6, + 0x003d, 0x1118, 0x080c, 0xb2a9, 0x0400, 0x6604, 0x96b6, 0x0044, + 0x1118, 0x080c, 0xb2e5, 0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, + 0x080c, 0xb326, 0x0090, 0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, + 0xb310, 0x0058, 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, + 0x0016, 0x1128, 0x00be, 0x0804, 0xbb49, 0x00be, 0x0005, 0x080c, + 0xaef5, 0x0cd8, 0xb90a, 0xb90d, 0xb90a, 0xb954, 0xb90a, 0xbabd, + 0xbb56, 0xb90a, 0xb90a, 0xbb1f, 0xb90a, 0xbb35, 0x0096, 0x601f, + 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, + 0x0804, 0xae5f, 0xa001, 0xa001, 0x0005, 0x00e6, 0x2071, 0x1800, + 0x7090, 0x9086, 0x0074, 0x1540, 0x080c, 0xe2f7, 0x11b0, 0x6010, + 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, + 0xc0c5, 0xb802, 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x6566, + 0x080c, 0x31f5, 0x080c, 0xae5f, 0x0098, 0x2001, 0x000a, 0x080c, + 0x6566, 0x080c, 0x31f5, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x9140, 0x080c, 0x96a6, 0x0020, 0x2001, 0x0001, 0x080c, 0xba8d, + 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, + 0x6552, 0x2069, 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, + 0x080c, 0x6592, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, + 0x1824, 0x2204, 0x9086, 0x0074, 0x1904, 0xba62, 0x6010, 0x2058, + 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xbca3, 0x0804, 0xb9c6, + 0x080c, 0xbc98, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, + 0x6014, 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, - 0xd129, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, - 0x31ea, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0xae71, 0x0028, - 0x080c, 0xb824, 0x9006, 0x080c, 0xba90, 0x001e, 0x002e, 0x00ee, - 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x1160, - 0x2001, 0x0002, 0x080c, 0x6558, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x9121, 0x0804, 0x9687, 0x2001, 0x0001, 0x0804, 0xba90, - 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, - 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x6558, 0x0804, 0xae71, - 0x2001, 0x0001, 0x0804, 0xba90, 0x0002, 0xb90d, 0xbb64, 0xb90d, - 0xbba5, 0xb90d, 0xbc52, 0xbb59, 0xb90d, 0xb90d, 0xbc66, 0xb90d, - 0xbc78, 0x6604, 0x9686, 0x0003, 0x0904, 0xbac0, 0x96b6, 0x001e, - 0x1110, 0x080c, 0xae71, 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, - 0xbc8a, 0x11a0, 0x9006, 0x080c, 0x6544, 0x080c, 0x31c1, 0x080c, - 0xd25f, 0x2001, 0x0002, 0x080c, 0x6558, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x9121, 0x080c, 0x9687, 0x0418, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0170, 0x8001, 0xb842, 0x601b, 0x000a, 0x0088, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x1900, 0x1108, - 0x08a0, 0x080c, 0x31c1, 0x080c, 0xd25f, 0x2001, 0x0001, 0x080c, - 0xba90, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, 0x00b6, 0x0026, - 0x9016, 0x080c, 0xbc98, 0x00d6, 0x2069, 0x197b, 0x2d04, 0x9005, - 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x2069, - 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, - 0x9006, 0x080c, 0x6544, 0x2001, 0x0002, 0x080c, 0x6558, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9121, 0x080c, 0x9687, 0x0804, - 0xbc22, 0x080c, 0xcb4a, 0x01b0, 0x6014, 0x2048, 0xa864, 0x2010, - 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, 0x0002, 0x080c, - 0xd183, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, 0x0118, 0x2001, - 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, 0x0148, 0x6010, - 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c38, - 0x080c, 0xb824, 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, - 0x0005, 0x0520, 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, - 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01c0, 0x9086, 0x1900, - 0x1168, 0x9686, 0x0009, 0x0190, 0x2001, 0x0004, 0x080c, 0x6558, - 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, 0x2001, 0x0001, - 0x080c, 0xba90, 0x002e, 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, - 0x0160, 0x6014, 0x2048, 0x080c, 0xcb4a, 0x0140, 0xa864, 0x9086, - 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c40, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, - 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fb6, 0x00ee, 0x0010, 0x080c, - 0x31c1, 0x0860, 0x080c, 0xbc98, 0x1160, 0x2001, 0x0004, 0x080c, - 0x6558, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x9121, 0x0804, - 0x9687, 0x080c, 0xb824, 0x9006, 0x0804, 0xba90, 0x0489, 0x1160, - 0x2001, 0x0008, 0x080c, 0x6558, 0x6003, 0x0001, 0x6007, 0x0005, - 0x080c, 0x9121, 0x0804, 0x9687, 0x2001, 0x0001, 0x0804, 0xba90, - 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x6558, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9121, 0x0804, 0x9687, 0x2001, 0x0001, - 0x0804, 0xba90, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, - 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, 0x6110, 0x2158, - 0x080c, 0x6617, 0x001e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x00f6, - 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, 0x2009, 0x1837, - 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xbd3e, 0x0560, 0x2009, - 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6977, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xe5cf, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x318c, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x2f98, 0x00ee, 0x00c6, 0x0156, - 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x32bd, 0x8108, 0x1f04, - 0xbcdc, 0x015e, 0x00ce, 0x080c, 0xbc9b, 0x2071, 0x0260, 0x2079, - 0x0200, 0x7817, 0x0001, 0x2001, 0x1837, 0x200c, 0xc1c5, 0x7018, - 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, - 0x7817, 0x0000, 0x2001, 0x1837, 0x2102, 0x2079, 0x0100, 0x2e04, - 0x9084, 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, - 0x2e04, 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, - 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, 0x2200, - 0x9084, 0x00ff, 0x2008, 0x080c, 0x2889, 0x080c, 0x73a5, 0x0170, - 0x2071, 0x0260, 0x2069, 0x1981, 0x7048, 0x206a, 0x704c, 0x6806, - 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xcf5e, 0x0040, 0x2001, - 0x0006, 0x080c, 0x6558, 0x080c, 0x31ea, 0x080c, 0xae71, 0x001e, - 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, - 0x0036, 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, - 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, - 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, - 0x2019, 0x000a, 0x080c, 0xbe30, 0x1148, 0x2011, 0x027a, 0x20a9, - 0x0004, 0x2019, 0x0006, 0x080c, 0xbe30, 0x1100, 0x015e, 0x00ee, - 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, - 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, - 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19ef, 0x252c, - 0x2021, 0x19f5, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7254, - 0x7074, 0x9202, 0x1a04, 0xbdfc, 0x080c, 0x896a, 0x0904, 0xbdf5, - 0x080c, 0xe600, 0x0904, 0xbdf5, 0x6720, 0x9786, 0x0007, 0x0904, - 0xbdf5, 0x2500, 0x9c06, 0x0904, 0xbdf5, 0x2400, 0x9c06, 0x05e8, - 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000, 0x9086, - 0x0004, 0x1110, 0x080c, 0x1a60, 0x9786, 0x000a, 0x0148, 0x080c, - 0xcd50, 0x1130, 0x00ce, 0x080c, 0xb824, 0x080c, 0xaea2, 0x00e8, - 0x6014, 0x2048, 0x080c, 0xcb4a, 0x01a8, 0x9786, 0x0003, 0x1530, - 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, - 0x080c, 0x0fb1, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c7a, - 0x080c, 0xcd33, 0x080c, 0xaea2, 0x00ce, 0x9ce0, 0x0018, 0x7068, - 0x9c02, 0x1210, 0x0804, 0xbd9f, 0x012e, 0x000e, 0x002e, 0x004e, - 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, - 0x1118, 0x080c, 0xe572, 0x0c30, 0x9786, 0x0009, 0x1148, 0x6000, - 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, 0xaeec, 0x08e0, - 0x9786, 0x000a, 0x0938, 0x0820, 0x220c, 0x2304, 0x9106, 0x1130, - 0x8210, 0x8318, 0x1f04, 0xbe1c, 0x9006, 0x0005, 0x2304, 0x9102, - 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, 0x0005, - 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, - 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, 0x0001, - 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, 0x9006, - 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, 0x2001, - 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, 0x01ce, - 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, 0x1130, 0x8210, - 0x8318, 0x1f04, 0xbe5a, 0x9006, 0x0005, 0x918d, 0x0001, 0x0005, - 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dd5, 0x080c, 0xcd3f, 0x0120, - 0x080c, 0xcd50, 0x0168, 0x0028, 0x080c, 0x31ea, 0x080c, 0xcd50, - 0x0138, 0x080c, 0x957b, 0x080c, 0xae71, 0x080c, 0x9687, 0x0005, - 0x080c, 0xb824, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xbe9f, 0xbe9f, 0xbe9f, 0xbe9f, 0xbe9f, - 0xbe9f, 0xbe9f, 0xbe9f, 0xbe9f, 0xbe9f, 0xbe9f, 0xbea1, 0xbea1, - 0xbea1, 0xbea1, 0xbe9f, 0xbe9f, 0xbe9f, 0xbea1, 0xbe9f, 0x080c, - 0x0dd5, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x90d9, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9687, 0x012e, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xbf56, 0x9186, - 0x0027, 0x1520, 0x080c, 0x957b, 0x080c, 0x31c1, 0x080c, 0xd25f, - 0x0096, 0x6114, 0x2148, 0x080c, 0xcb4a, 0x0198, 0x080c, 0xcd50, - 0x1118, 0x080c, 0xb824, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, - 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6c86, 0x080c, - 0xcd33, 0x009e, 0x080c, 0xae71, 0x0804, 0x9687, 0x9186, 0x0014, - 0x1120, 0x6004, 0x9082, 0x0040, 0x04a0, 0x9186, 0x0046, 0x0150, - 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, - 0x190c, 0x0dd5, 0x2001, 0x0109, 0x2004, 0xd084, 0x0508, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, - 0x00c6, 0x2079, 0x19e6, 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, - 0x8fbe, 0x00ce, 0x00ee, 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, - 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0xbf94, - 0x0005, 0x0002, 0xbf30, 0xbf2e, 0xbf2e, 0xbf2e, 0xbf2e, 0xbf2e, - 0xbf2e, 0xbf2e, 0xbf2e, 0xbf2e, 0xbf2e, 0xbf4b, 0xbf4b, 0xbf4b, - 0xbf4b, 0xbf2e, 0xbf4b, 0xbf2e, 0xbf4b, 0xbf2e, 0x080c, 0x0dd5, - 0x080c, 0x957b, 0x0096, 0x6114, 0x2148, 0x080c, 0xcb4a, 0x0168, - 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ec, - 0xa882, 0x080c, 0x6c86, 0x080c, 0xcd33, 0x009e, 0x080c, 0xae71, - 0x080c, 0x9687, 0x0005, 0x080c, 0x957b, 0x080c, 0xcd50, 0x090c, - 0xb824, 0x080c, 0xae71, 0x080c, 0x9687, 0x0005, 0x0002, 0xbf6d, - 0xbf6b, 0xbf6b, 0xbf6b, 0xbf6b, 0xbf6b, 0xbf6b, 0xbf6b, 0xbf6b, - 0xbf6b, 0xbf6b, 0xbf84, 0xbf84, 0xbf84, 0xbf84, 0xbf6b, 0xbf8e, - 0xbf6b, 0xbf84, 0xbf6b, 0x080c, 0x0dd5, 0x0096, 0x080c, 0x957b, - 0x6014, 0x2048, 0x2001, 0x1987, 0x2004, 0x6042, 0xa97c, 0xd1ac, - 0x0140, 0x6003, 0x0004, 0xa87c, 0x9085, 0x0400, 0xa87e, 0x009e, - 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, 0x957b, 0x080c, 0xd262, - 0x080c, 0xd267, 0x6003, 0x000f, 0x0804, 0x9687, 0x080c, 0x957b, - 0x080c, 0xae71, 0x0804, 0x9687, 0x9182, 0x0054, 0x1220, 0x9182, - 0x0040, 0x0208, 0x000a, 0x0005, 0xbfb0, 0xbfb0, 0xbfb0, 0xbfb0, - 0xbfb0, 0xbfb2, 0xc08f, 0xbfb0, 0xc0c3, 0xbfb0, 0xbfb0, 0xbfb0, - 0xbfb0, 0xbfb0, 0xbfb0, 0xbfb0, 0xbfb0, 0xbfb0, 0xbfb0, 0xc0c3, - 0x080c, 0x0dd5, 0x00b6, 0x0096, 0x6114, 0x2148, 0x7644, 0x96b4, - 0x0fff, 0x86ff, 0x1528, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, - 0xc07e, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc258, 0x080c, 0x6aa2, - 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x7044, - 0xd0e4, 0x1904, 0xc062, 0x080c, 0xae71, 0x009e, 0x00be, 0x0005, - 0x968c, 0x0c00, 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, - 0xc066, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, - 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, - 0xd6dc, 0x01a0, 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, - 0xaa34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, - 0x9206, 0x0118, 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, - 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, - 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, - 0x1118, 0xc6c4, 0x0804, 0xbfb9, 0x735c, 0xab86, 0x83ff, 0x0170, - 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, - 0x0018, 0x2011, 0x0025, 0x080c, 0xc743, 0x003e, 0xd6cc, 0x0904, - 0xbfce, 0x7154, 0xa98a, 0x81ff, 0x0904, 0xbfce, 0x9192, 0x0021, - 0x1278, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xc743, - 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xd1ef, 0x0804, 0xbfce, - 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, - 0x2950, 0x080c, 0xc6e2, 0x00ae, 0x080c, 0xd1ef, 0x080c, 0xc733, - 0x0804, 0xbfd0, 0x080c, 0xce48, 0x0804, 0xbfdd, 0xa87c, 0xd0ac, - 0x0904, 0xbfe9, 0xa880, 0xd0bc, 0x1904, 0xbfe9, 0x7348, 0xa838, - 0x9306, 0x11c8, 0x734c, 0xa834, 0x931e, 0x0904, 0xbfe9, 0xd6d4, - 0x0190, 0xab38, 0x9305, 0x0904, 0xbfe9, 0x0068, 0xa87c, 0xd0ac, - 0x0904, 0xbfc1, 0xa838, 0xa934, 0x9105, 0x0904, 0xbfc1, 0xa880, - 0xd0bc, 0x1904, 0xbfc1, 0x080c, 0xce82, 0x0804, 0xbfdd, 0x0096, - 0x00f6, 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, - 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, - 0x6003, 0x0002, 0x00fe, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, - 0x2400, 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, - 0x2500, 0x9203, 0x0e90, 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, - 0x6043, 0x0000, 0x2c10, 0x080c, 0x1baf, 0x080c, 0x913e, 0x080c, - 0x97b5, 0x009e, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, - 0x0040, 0x0208, 0x000a, 0x0005, 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e0, - 0xc0e0, 0xc0e2, 0xc178, 0xc0e0, 0xc0e0, 0xc18f, 0xc21b, 0xc0e0, - 0xc0e0, 0xc0e0, 0xc0e0, 0xc230, 0xc0e0, 0xc0e0, 0xc0e0, 0xc0e0, + 0xd139, 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, + 0x2001, 0x0006, 0x080c, 0x6566, 0x080c, 0x31f5, 0x080c, 0xae5f, + 0x0804, 0xba67, 0x080c, 0xba75, 0x6014, 0x9005, 0x0190, 0x2048, + 0xa868, 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, + 0x1d08, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd139, + 0x08f8, 0x080c, 0xba6b, 0x0160, 0x9006, 0x080c, 0x6552, 0x2001, + 0x0004, 0x080c, 0x6592, 0x2001, 0x0007, 0x080c, 0x6566, 0x08a0, + 0x2001, 0x0004, 0x080c, 0x6566, 0x6003, 0x0001, 0x6007, 0x0003, + 0x080c, 0x9140, 0x080c, 0x96a6, 0x0804, 0xba67, 0xb85c, 0xd0e4, + 0x01d8, 0x080c, 0xcf6e, 0x080c, 0x73b3, 0x0118, 0xd0dc, 0x1904, + 0xb988, 0x2011, 0x1837, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x196c, + 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x28bf, + 0x78e2, 0x00fe, 0x0804, 0xb988, 0x080c, 0xcfab, 0x2011, 0x1837, + 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe47c, 0x000e, 0x1904, + 0xb988, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x6566, 0x9006, + 0x080c, 0x6552, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, 0x0520, + 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, 0x9084, + 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, 0x7082, 0x908c, 0x00ff, + 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x2894, 0x00f6, + 0x2100, 0x900e, 0x080c, 0x284b, 0x795e, 0x00fe, 0x9186, 0x0081, + 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, + 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, + 0x080c, 0x2894, 0x00f6, 0x2079, 0x1800, 0x7982, 0x2100, 0x900e, + 0x080c, 0x284b, 0x795e, 0x00fe, 0x8108, 0x080c, 0x65b5, 0x2b00, + 0x00ce, 0x1904, 0xb988, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, + 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, + 0x027d, 0x210c, 0xb916, 0x2001, 0x0002, 0x080c, 0x6566, 0x6023, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x0028, 0x080c, 0xb821, 0x2001, 0x0001, 0x0431, 0x00de, + 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, + 0x2001, 0x1848, 0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xe9ab, + 0x0190, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, + 0x9284, 0xff00, 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, + 0x1110, 0xb912, 0xba16, 0x00ee, 0x0005, 0x2030, 0x9005, 0x0158, + 0x2001, 0x0007, 0x080c, 0x6566, 0x080c, 0x56f6, 0x1120, 0x2001, + 0x0007, 0x080c, 0x6592, 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, + 0x2048, 0xa868, 0x009e, 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, + 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, + 0x080c, 0x4b1e, 0x004e, 0x003e, 0x080c, 0x31f5, 0x6020, 0x9086, + 0x000a, 0x1108, 0x0005, 0x0804, 0xae5f, 0x00b6, 0x00e6, 0x0026, + 0x0016, 0x2071, 0x1800, 0x7090, 0x9086, 0x0014, 0x1904, 0xbb15, + 0x080c, 0x56f6, 0x1170, 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, + 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4cd5, 0x004e, + 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, 0x66b1, 0x080c, 0xb942, + 0x00de, 0x080c, 0xbd69, 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, + 0x0560, 0x2001, 0x0006, 0x080c, 0x6566, 0x0096, 0x6014, 0x904d, + 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, + 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd139, 0x0060, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, + 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, 0x31f5, 0x6020, 0x9086, + 0x000a, 0x0140, 0x080c, 0xae5f, 0x0028, 0x080c, 0xb821, 0x9006, + 0x080c, 0xba8d, 0x001e, 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, + 0x1824, 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, + 0x6566, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9140, 0x0804, + 0x96a6, 0x2001, 0x0001, 0x0804, 0xba8d, 0x2030, 0x2011, 0x1824, + 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, + 0x0007, 0x080c, 0x6566, 0x0804, 0xae5f, 0x2001, 0x0001, 0x0804, + 0xba8d, 0x0002, 0xb90a, 0xbb61, 0xb90a, 0xbba2, 0xb90a, 0xbc4f, + 0xbb56, 0xb90a, 0xb90a, 0xbc63, 0xb90a, 0xbc75, 0x6604, 0x9686, + 0x0003, 0x0904, 0xbabd, 0x96b6, 0x001e, 0x1110, 0x080c, 0xae5f, + 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, 0xbc87, 0x11a0, 0x9006, + 0x080c, 0x6552, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x2001, 0x0002, + 0x080c, 0x6566, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9140, + 0x080c, 0x96a6, 0x0418, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, + 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0170, + 0x8001, 0xb842, 0x601b, 0x000a, 0x0088, 0x2009, 0x026f, 0x2104, + 0x9084, 0xff00, 0x9086, 0x1900, 0x1108, 0x08a0, 0x080c, 0x31cc, + 0x080c, 0xd26f, 0x2001, 0x0001, 0x080c, 0xba8d, 0x00ce, 0x00de, + 0x00be, 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xbc95, + 0x00d6, 0x2069, 0x197b, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, + 0xb8a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, + 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x6552, + 0x2001, 0x0002, 0x080c, 0x6566, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x9140, 0x080c, 0x96a6, 0x0804, 0xbc1f, 0x080c, 0xcb5a, + 0x01b0, 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, + 0x6007, 0x0016, 0x2001, 0x0002, 0x080c, 0xd193, 0x00b0, 0x6014, + 0x2048, 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, + 0x180e, 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, + 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, 0xb821, 0x2009, + 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, + 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, + 0x9686, 0x0009, 0x01c0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, + 0x0190, 0x2001, 0x0004, 0x080c, 0x6566, 0x2001, 0x0028, 0x601a, + 0x6007, 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xba8d, 0x002e, + 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, + 0x080c, 0xcb5a, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, + 0xd0fc, 0x0108, 0x0c40, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, + 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, + 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, + 0x080c, 0x5fc0, 0x00ee, 0x0010, 0x080c, 0x31cc, 0x0860, 0x080c, + 0xbc95, 0x1160, 0x2001, 0x0004, 0x080c, 0x6566, 0x6003, 0x0001, + 0x6007, 0x0003, 0x080c, 0x9140, 0x0804, 0x96a6, 0x080c, 0xb821, + 0x9006, 0x0804, 0xba8d, 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, + 0x6566, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x9140, 0x0804, + 0x96a6, 0x2001, 0x0001, 0x0804, 0xba8d, 0x00f9, 0x1160, 0x2001, + 0x000a, 0x080c, 0x6566, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x9140, 0x0804, 0x96a6, 0x2001, 0x0001, 0x0804, 0xba8d, 0x2009, + 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, + 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, + 0x00b6, 0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6625, 0x001e, + 0x00ce, 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, + 0x0016, 0x6010, 0x2058, 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, + 0x200a, 0x080c, 0xbd3b, 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, + 0x200a, 0x080c, 0x6985, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xe5e9, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x2009, 0x0001, 0x080c, 0x3197, 0x00e6, 0x2071, 0x1800, + 0x080c, 0x2fa3, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, + 0x007f, 0x080c, 0x32c8, 0x8108, 0x1f04, 0xbcd9, 0x015e, 0x00ce, + 0x080c, 0xbc98, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, + 0x2001, 0x1837, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, + 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, + 0x1837, 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, 0x2069, + 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0x1820, + 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, 0x001e, + 0x9105, 0x2009, 0x182c, 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, + 0x080c, 0x2894, 0x080c, 0x73b3, 0x0170, 0x2071, 0x0260, 0x2069, + 0x1981, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, + 0x680e, 0x080c, 0xcf6e, 0x0040, 0x2001, 0x0006, 0x080c, 0x6566, + 0x080c, 0x31f5, 0x080c, 0xae5f, 0x001e, 0x003e, 0x00de, 0x00ee, + 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, 0x00e6, 0x0156, + 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, 0x2071, 0x0260, 0x7200, + 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1198, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019, 0x000a, 0x080c, + 0xbe2d, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, 0x2019, 0x0006, + 0x080c, 0xbe2d, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x009e, + 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, + 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, + 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, + 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, + 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2029, 0x19ef, 0x252c, 0x2021, 0x19f5, 0x2424, + 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7254, 0x7074, 0x9202, 0x1a04, + 0xbdf9, 0x080c, 0x8987, 0x0904, 0xbdf2, 0x080c, 0xe61a, 0x0904, + 0xbdf2, 0x6720, 0x9786, 0x0007, 0x0904, 0xbdf2, 0x2500, 0x9c06, + 0x0904, 0xbdf2, 0x2400, 0x9c06, 0x05e8, 0x3e08, 0x9186, 0x0002, + 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x1580, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, + 0x1a70, 0x9786, 0x000a, 0x0148, 0x080c, 0xcd60, 0x1130, 0x00ce, + 0x080c, 0xb821, 0x080c, 0xae90, 0x00e8, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, + 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fb1, 0x009e, + 0xab7a, 0xa877, 0x0000, 0x080c, 0x6c88, 0x080c, 0xcd43, 0x080c, + 0xae90, 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1210, 0x0804, + 0xbd9c, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, + 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xe58c, + 0x0c30, 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, + 0x2009, 0x004c, 0x080c, 0xaeda, 0x08e0, 0x9786, 0x000a, 0x0938, + 0x0820, 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, + 0xbe19, 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, + 0x0008, 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, + 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, + 0x9300, 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, + 0x1140, 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, + 0x0005, 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, + 0x0000, 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, + 0x810f, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xbe57, + 0x9006, 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, + 0x1a0c, 0x0dd5, 0x080c, 0xcd4f, 0x0120, 0x080c, 0xcd60, 0x0168, + 0x0028, 0x080c, 0x31f5, 0x080c, 0xcd60, 0x0138, 0x080c, 0x959a, + 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0005, 0x080c, 0xb821, 0x0cb0, + 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9c, + 0xbe9c, 0xbe9c, 0xbe9c, 0xbe9e, 0xbe9e, 0xbe9e, 0xbe9e, 0xbe9c, + 0xbe9c, 0xbe9c, 0xbe9e, 0xbe9c, 0x080c, 0x0dd5, 0x600b, 0xffff, + 0x6003, 0x0001, 0x6106, 0x080c, 0x90f8, 0x0126, 0x2091, 0x8000, + 0x080c, 0x96a6, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, + 0x9082, 0x0040, 0x0804, 0xbf53, 0x9186, 0x0027, 0x1520, 0x080c, + 0x959a, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x0096, 0x6114, 0x2148, + 0x080c, 0xcb5a, 0x0198, 0x080c, 0xcd60, 0x1118, 0x080c, 0xb821, + 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c, + 0xc1c5, 0xa97e, 0x080c, 0x6c94, 0x080c, 0xcd43, 0x009e, 0x080c, + 0xae5f, 0x0804, 0x96a6, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, + 0x0040, 0x04a0, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, 0x0138, + 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0dd5, 0x2001, + 0x0109, 0x2004, 0xd084, 0x0508, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x19e6, + 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x8fdd, 0x00ce, 0x00ee, + 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, + 0x9086, 0x0002, 0x1110, 0x0804, 0xbf91, 0x0005, 0x0002, 0xbf2d, + 0xbf2b, 0xbf2b, 0xbf2b, 0xbf2b, 0xbf2b, 0xbf2b, 0xbf2b, 0xbf2b, + 0xbf2b, 0xbf2b, 0xbf48, 0xbf48, 0xbf48, 0xbf48, 0xbf2b, 0xbf48, + 0xbf2b, 0xbf48, 0xbf2b, 0x080c, 0x0dd5, 0x080c, 0x959a, 0x0096, + 0x6114, 0x2148, 0x080c, 0xcb5a, 0x0168, 0xa867, 0x0103, 0xa87b, + 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6c94, + 0x080c, 0xcd43, 0x009e, 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0005, + 0x080c, 0x959a, 0x080c, 0xcd60, 0x090c, 0xb821, 0x080c, 0xae5f, + 0x080c, 0x96a6, 0x0005, 0x0002, 0xbf6a, 0xbf68, 0xbf68, 0xbf68, + 0xbf68, 0xbf68, 0xbf68, 0xbf68, 0xbf68, 0xbf68, 0xbf68, 0xbf81, + 0xbf81, 0xbf81, 0xbf81, 0xbf68, 0xbf8b, 0xbf68, 0xbf81, 0xbf68, + 0x080c, 0x0dd5, 0x0096, 0x080c, 0x959a, 0x6014, 0x2048, 0x2001, + 0x1987, 0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, + 0xa87c, 0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, + 0x0cb8, 0x080c, 0x959a, 0x080c, 0xd272, 0x080c, 0xd277, 0x6003, + 0x000f, 0x0804, 0x96a6, 0x080c, 0x959a, 0x080c, 0xae5f, 0x0804, + 0x96a6, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xbfad, 0xbfad, 0xbfad, 0xbfad, 0xbfad, 0xbfaf, 0xc08c, + 0xbfad, 0xc0c0, 0xbfad, 0xbfad, 0xbfad, 0xbfad, 0xbfad, 0xbfad, + 0xbfad, 0xbfad, 0xbfad, 0xbfad, 0xc0c0, 0x080c, 0x0dd5, 0x00b6, + 0x0096, 0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, + 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc07b, 0xa87b, 0x0000, + 0xa867, 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, + 0x9115, 0x190c, 0xc255, 0x080c, 0x6ab0, 0x6210, 0x2258, 0xba3c, + 0x82ff, 0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xc05f, + 0x080c, 0xae5f, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, + 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc063, 0x7348, 0xab92, + 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, + 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, + 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, 0x9205, + 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, 0xa992, + 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, + 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, + 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, + 0xbfb6, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, + 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, + 0x080c, 0xc743, 0x003e, 0xd6cc, 0x0904, 0xbfcb, 0x7154, 0xa98a, + 0x81ff, 0x0904, 0xbfcb, 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, + 0x0018, 0x2011, 0x0029, 0x080c, 0xc743, 0x2011, 0x0205, 0x2013, + 0x0000, 0x080c, 0xd1ff, 0x0804, 0xbfcb, 0xa868, 0xd0fc, 0x0120, + 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, 0xc6e2, + 0x00ae, 0x080c, 0xd1ff, 0x080c, 0xc733, 0x0804, 0xbfcd, 0x080c, + 0xce58, 0x0804, 0xbfda, 0xa87c, 0xd0ac, 0x0904, 0xbfe6, 0xa880, + 0xd0bc, 0x1904, 0xbfe6, 0x7348, 0xa838, 0x9306, 0x11c8, 0x734c, + 0xa834, 0x931e, 0x0904, 0xbfe6, 0xd6d4, 0x0190, 0xab38, 0x9305, + 0x0904, 0xbfe6, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xbfbe, 0xa838, + 0xa934, 0x9105, 0x0904, 0xbfbe, 0xa880, 0xd0bc, 0x1904, 0xbfbe, + 0x080c, 0xce92, 0x0804, 0xbfda, 0x0096, 0x00f6, 0x6003, 0x0003, + 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, 0x6003, 0x0002, 0x00fe, + 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, + 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, + 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, 0x6043, 0x0000, 0x2c10, + 0x080c, 0x1bba, 0x080c, 0x915d, 0x080c, 0x97d4, 0x009e, 0x0005, + 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xc0dd, 0xc0dd, 0xc0dd, 0xc0dd, 0xc0dd, 0xc0df, 0xc175, + 0xc0dd, 0xc0dd, 0xc18c, 0xc218, 0xc0dd, 0xc0dd, 0xc0dd, 0xc0dd, + 0xc22d, 0xc0dd, 0xc0dd, 0xc0dd, 0xc0dd, 0x080c, 0x0dd5, 0x0076, + 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, 0x7644, + 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, + 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, + 0x0904, 0xc170, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, + 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc170, 0x080c, + 0x0fff, 0x090c, 0x0dd5, 0x2900, 0xb07a, 0xb77c, 0xc7cd, 0xb77e, + 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, + 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, + 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, + 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, + 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, + 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, + 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, + 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xc743, + 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, + 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, + 0xc743, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, + 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xc6e2, + 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x00f6, 0x00a6, 0x6003, + 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, + 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, 0x00ae, 0x00fe, 0x2c10, + 0x080c, 0x1bba, 0x0804, 0xa25c, 0x6003, 0x0002, 0x6004, 0x9086, + 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0160, + 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078, 0x080c, 0x1727, + 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002, 0x009e, 0x080c, + 0x959a, 0x080c, 0x96a6, 0x0096, 0x2001, 0x1987, 0x2004, 0x6042, + 0x080c, 0x9656, 0x080c, 0x97d4, 0x6114, 0x2148, 0xa97c, 0xd1e4, + 0x0904, 0xc213, 0xd1cc, 0x05a8, 0xa978, 0xa868, 0xd0fc, 0x0538, + 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, 0x810f, 0x9184, 0x003f, + 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, 0x2098, 0x0156, 0x20a9, + 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, 0x000e, 0xa87e, 0x001e, + 0xa874, 0x0006, 0x2148, 0x080c, 0x0fb1, 0x001e, 0x0440, 0x0016, + 0x080c, 0x0fb1, 0x009e, 0xa974, 0x0016, 0x080c, 0xc733, 0x001e, + 0x00f0, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, + 0x0180, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd1dc, + 0x0118, 0xa87b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0xa87b, 0x0007, + 0x0010, 0xa87b, 0x0000, 0x0016, 0x080c, 0x6ab0, 0x001e, 0xd1e4, + 0x1120, 0x080c, 0xae5f, 0x009e, 0x0005, 0x080c, 0xce58, 0x0cd8, + 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x959a, 0x080c, 0x96a6, + 0x2019, 0x0001, 0x080c, 0xa5c8, 0x6003, 0x0002, 0x080c, 0xd277, + 0x080c, 0x9656, 0x080c, 0x97d4, 0x0005, 0x6004, 0x9086, 0x0040, + 0x1120, 0x080c, 0x959a, 0x080c, 0x96a6, 0x2019, 0x0001, 0x080c, + 0xa5c8, 0x080c, 0x9656, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x0096, + 0x6114, 0x2148, 0x080c, 0xcb5a, 0x0150, 0xa867, 0x0103, 0xa87b, + 0x0029, 0xa877, 0x0000, 0x080c, 0x6c94, 0x080c, 0xcd43, 0x009e, + 0x080c, 0xae5f, 0x080c, 0x97d4, 0x0005, 0xa87b, 0x0015, 0xd1fc, + 0x0180, 0xa87b, 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, + 0x0006, 0x0016, 0x2009, 0x1a79, 0x2104, 0x8000, 0x200a, 0x001e, + 0x000e, 0xa992, 0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, + 0x0040, 0x0208, 0x000a, 0x0005, 0xc288, 0xc288, 0xc288, 0xc288, + 0xc288, 0xc28a, 0xc288, 0xc288, 0xc330, 0xc288, 0xc288, 0xc288, + 0xc288, 0xc288, 0xc288, 0xc288, 0xc288, 0xc288, 0xc288, 0xc461, 0x080c, 0x0dd5, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, - 0xba3e, 0x00be, 0x86ff, 0x0904, 0xc173, 0x9694, 0xff00, 0x9284, + 0xba3e, 0x00be, 0x86ff, 0x0904, 0xc329, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, - 0x0904, 0xc173, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0x2900, 0xb07a, - 0xb77c, 0xc7cd, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, - 0xa86e, 0xb070, 0xa872, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, - 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, - 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, - 0xa87b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, - 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, - 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, - 0x0025, 0x080c, 0xc743, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, - 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, - 0x2011, 0x0029, 0x080c, 0xc743, 0x2011, 0x0205, 0x2013, 0x0000, - 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, - 0x2950, 0x080c, 0xc6e2, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, - 0x00f6, 0x00a6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6014, 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, - 0x00ae, 0x00fe, 0x2c10, 0x080c, 0x1baf, 0x0804, 0xa241, 0x6003, - 0x0002, 0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, - 0xa87c, 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, - 0x2078, 0x080c, 0x1727, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, - 0x0002, 0x009e, 0x080c, 0x957b, 0x080c, 0x9687, 0x0096, 0x2001, - 0x1987, 0x2004, 0x6042, 0x080c, 0x9637, 0x080c, 0x97b5, 0x6114, - 0x2148, 0xa97c, 0xd1e4, 0x0904, 0xc216, 0xd1cc, 0x05a8, 0xa978, - 0xa868, 0xd0fc, 0x0538, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, - 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, - 0x2098, 0x0156, 0x20a9, 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, - 0x000e, 0xa87e, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fb1, - 0x001e, 0x0440, 0x0016, 0x080c, 0x0fb1, 0x009e, 0xa974, 0x0016, - 0x080c, 0xc733, 0x001e, 0x00f0, 0xa867, 0x0103, 0xa974, 0x9184, - 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x0060, 0xd1dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd1d4, - 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0x0016, 0x080c, - 0x6aa2, 0x001e, 0xd1e4, 0x1120, 0x080c, 0xae71, 0x009e, 0x0005, - 0x080c, 0xce48, 0x0cd8, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, - 0x957b, 0x080c, 0x9687, 0x2019, 0x0001, 0x080c, 0xa5b7, 0x6003, - 0x0002, 0x080c, 0xd267, 0x080c, 0x9637, 0x080c, 0x97b5, 0x0005, - 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x957b, 0x080c, 0x9687, - 0x2019, 0x0001, 0x080c, 0xa5b7, 0x080c, 0x9637, 0x080c, 0x31c1, - 0x080c, 0xd25f, 0x0096, 0x6114, 0x2148, 0x080c, 0xcb4a, 0x0150, - 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, 0x6c86, - 0x080c, 0xcd33, 0x009e, 0x080c, 0xae71, 0x080c, 0x97b5, 0x0005, - 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, 0x8000, - 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a79, 0x2104, - 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, 0x9182, - 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc28b, - 0xc28b, 0xc28b, 0xc28b, 0xc28b, 0xc28d, 0xc28b, 0xc28b, 0xc333, - 0xc28b, 0xc28b, 0xc28b, 0xc28b, 0xc28b, 0xc28b, 0xc28b, 0xc28b, - 0xc28b, 0xc28b, 0xc464, 0x080c, 0x0dd5, 0x0076, 0x00a6, 0x00e6, - 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, 0x7644, 0xb676, 0x96b4, - 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, - 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xc32c, - 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, - 0xb08e, 0x9284, 0x0300, 0x0904, 0xc32c, 0x9686, 0x0100, 0x1130, - 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x0fff, - 0x090c, 0x0dd5, 0x2900, 0xb07a, 0xb77c, 0x97bd, 0x0200, 0xb77e, - 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, - 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, 0x968c, 0x0c00, 0x0120, - 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, - 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, - 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, - 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, - 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, - 0x2011, 0x0025, 0x080c, 0xc743, 0x003e, 0xd6cc, 0x01e8, 0x7154, - 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, - 0x0018, 0x2011, 0x0029, 0x080c, 0xc743, 0x2011, 0x0205, 0x2013, - 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, - 0x0c68, 0x2950, 0x080c, 0xc6e2, 0x080c, 0x1a3e, 0x009e, 0x00ee, - 0x00ae, 0x007e, 0x0005, 0x2001, 0x1987, 0x2004, 0x6042, 0x0096, - 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, - 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, 0x0904, 0xc45f, 0x6043, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, - 0xd1cc, 0x0904, 0xc42e, 0xa978, 0xa868, 0xd0fc, 0x0904, 0xc3ef, - 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, - 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xc3bd, 0x9086, 0x0028, - 0x1904, 0xc3a9, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, 0xc3c5, - 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, 0x9205, 0x09c8, 0xa838, - 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, 0x9206, 0x0988, 0x6024, - 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, 0x603a, 0xa9b0, 0xa838, - 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00b6, 0x2058, - 0xb83c, 0x8000, 0xb83e, 0x00be, 0x9006, 0xa876, 0xa892, 0xa88e, - 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, - 0xa878, 0x2048, 0x080c, 0x0fb1, 0x009e, 0x080c, 0xce82, 0x0804, - 0xc45f, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, - 0xd112, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, - 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xc258, 0xa87c, 0xb07e, 0xa890, - 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, - 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, - 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, - 0x000e, 0xa882, 0x000e, 0xa87e, 0x080c, 0xd1ef, 0x001e, 0xa874, - 0x0006, 0x2148, 0x080c, 0x0fb1, 0x001e, 0x0804, 0xc45b, 0x0016, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, - 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, - 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd112, - 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, - 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, - 0xa938, 0x9115, 0x190c, 0xc258, 0xa890, 0xb092, 0xa88c, 0xb08e, - 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0fb1, 0x009e, 0x080c, 0xd1ef, - 0xa974, 0x0016, 0x080c, 0xc733, 0x001e, 0x0468, 0xa867, 0x0103, - 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, - 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, - 0x080c, 0xd112, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, - 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc258, 0xa974, 0x0016, - 0x080c, 0x6aa2, 0x001e, 0xd1e4, 0x1120, 0x080c, 0xae71, 0x009e, - 0x0005, 0x080c, 0xce48, 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, - 0xd1e4, 0x190c, 0x1a4c, 0x009e, 0x0005, 0x080c, 0x957b, 0x0010, - 0x080c, 0x9637, 0x080c, 0xcb4a, 0x01f0, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcd50, 0x1118, 0x080c, 0xb824, 0x00a0, 0xa867, 0x0103, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, - 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xe929, 0xa877, 0x0000, - 0x080c, 0x6c86, 0x009e, 0x080c, 0xae71, 0x080c, 0x9687, 0x0804, - 0x97b5, 0xa87b, 0x0004, 0x0c90, 0xa87b, 0x0004, 0x0c78, 0x9182, - 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc4bb, - 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bd, 0xc4bb, 0xc4bb, 0xc4bb, - 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, 0xc4bb, - 0xc4bb, 0xc4bb, 0xc4bb, 0x080c, 0x0dd5, 0x080c, 0x56e0, 0x01f8, - 0x6014, 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, - 0x9294, 0x00ff, 0x0096, 0x904d, 0x0188, 0xa87b, 0x0000, 0xa864, - 0x9086, 0x0139, 0x0128, 0xa867, 0x0103, 0xa976, 0xaa96, 0x0030, - 0xa897, 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x6c86, 0x009e, 0x0804, - 0xae71, 0x9182, 0x0085, 0x0002, 0xc4f3, 0xc4f1, 0xc4f1, 0xc4ff, - 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, 0xc4f1, - 0xc4f1, 0x080c, 0x0dd5, 0x6003, 0x0001, 0x6106, 0x080c, 0x90d9, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9687, 0x012e, 0x0005, 0x0026, - 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, - 0x080c, 0xcb38, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, - 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xc76e, - 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, - 0x0087, 0x6003, 0x0001, 0x080c, 0x90d9, 0x080c, 0x9687, 0x9280, - 0x0004, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6824, - 0xd0ec, 0x0128, 0x00c6, 0x2260, 0x080c, 0xce82, 0x00ce, 0x00ee, + 0x0904, 0xc329, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, + 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0x2900, + 0xb07a, 0xb77c, 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, + 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, + 0x9635, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, + 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, + 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, + 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, + 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, + 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, + 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, + 0xc743, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, + 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, + 0x080c, 0xc743, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, + 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, + 0xc6e2, 0x080c, 0x1a3e, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, + 0x2001, 0x1987, 0x2004, 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, + 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, + 0xa97c, 0xd1e4, 0x0904, 0xc45c, 0x6043, 0x0000, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc42b, + 0xa978, 0xa868, 0xd0fc, 0x0904, 0xc3ec, 0x0016, 0xa87c, 0x0006, + 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, + 0x0002, 0x0904, 0xc3ba, 0x9086, 0x0028, 0x1904, 0xc3a6, 0xa87b, + 0x001c, 0xb07b, 0x001c, 0x0804, 0xc3c2, 0x6024, 0xd0f4, 0x11d0, + 0xa838, 0xaa34, 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, + 0xa88c, 0xaa34, 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, + 0xa834, 0x9102, 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, + 0xc0f5, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, + 0x00be, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, + 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, + 0x0fb1, 0x009e, 0x080c, 0xce92, 0x0804, 0xc45c, 0xd1dc, 0x0158, + 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd122, 0x0118, 0xb174, + 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, + 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, + 0x190c, 0xc255, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, + 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, + 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, + 0xa87e, 0x080c, 0xd1ff, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, + 0x0fb1, 0x001e, 0x0804, 0xc458, 0x0016, 0x00a6, 0x2150, 0xb174, + 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, + 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, + 0x0015, 0xb07b, 0x0015, 0x080c, 0xd122, 0x0118, 0xb174, 0xc1dc, + 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, + 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, + 0xc255, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, + 0x080c, 0x0fb1, 0x009e, 0x080c, 0xd1ff, 0xa974, 0x0016, 0x080c, + 0xc733, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, + 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, + 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xd122, 0x0118, + 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, + 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, + 0x9115, 0x190c, 0xc255, 0xa974, 0x0016, 0x080c, 0x6ab0, 0x001e, + 0xd1e4, 0x1120, 0x080c, 0xae5f, 0x009e, 0x0005, 0x080c, 0xce58, + 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1a5c, + 0x009e, 0x0005, 0x080c, 0x959a, 0x0010, 0x080c, 0x9656, 0x080c, + 0xcb5a, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xcd60, 0x1118, + 0x080c, 0xb821, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, + 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, + 0x1110, 0x080c, 0xe943, 0xa877, 0x0000, 0x080c, 0x6c94, 0x009e, + 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0804, 0x97d4, 0xa87b, 0x0004, + 0x0c90, 0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, + 0x0040, 0x0208, 0x000a, 0x0005, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, + 0xc4b8, 0xc4ba, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, + 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, 0xc4b8, + 0x080c, 0x0dd5, 0x080c, 0x56ea, 0x01f8, 0x6014, 0x7144, 0x918c, + 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, + 0x904d, 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, + 0xa867, 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, + 0xaa9e, 0x080c, 0x6c94, 0x009e, 0x0804, 0xae5f, 0x9182, 0x0085, + 0x0002, 0xc4f0, 0xc4ee, 0xc4ee, 0xc4fc, 0xc4ee, 0xc4ee, 0xc4ee, + 0xc4ee, 0xc4ee, 0xc4ee, 0xc4ee, 0xc4ee, 0xc4ee, 0x080c, 0x0dd5, + 0x6003, 0x0001, 0x6106, 0x080c, 0x90f8, 0x0126, 0x2091, 0x8000, + 0x080c, 0x96a6, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, + 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xcb48, 0x01a0, + 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, 0x6d10, 0x952e, + 0x1158, 0x00c6, 0x2d60, 0x080c, 0xc76e, 0x00ce, 0x0128, 0x6803, + 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, + 0x080c, 0x90f8, 0x080c, 0x96a6, 0x7220, 0x080c, 0xcb48, 0x0178, + 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6824, + 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xce92, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dd5, 0x908a, 0x0092, 0x1a0c, 0x0dd5, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, 0x0014, - 0x190c, 0x0dd5, 0x080c, 0x957b, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcb4a, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, - 0x080c, 0x6c86, 0x009e, 0x080c, 0xaea2, 0x0804, 0x9687, 0xc574, + 0x190c, 0x0dd5, 0x080c, 0x959a, 0x0096, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, + 0x080c, 0x6c94, 0x009e, 0x080c, 0xae90, 0x0804, 0x96a6, 0xc574, 0xc576, 0xc576, 0xc574, 0xc574, 0xc574, 0xc574, 0xc574, 0xc574, - 0xc574, 0xc574, 0xc574, 0xc574, 0x080c, 0x0dd5, 0x080c, 0x957b, - 0x080c, 0xaea2, 0x080c, 0x9687, 0x0005, 0x9186, 0x0013, 0x1128, + 0xc574, 0xc574, 0xc574, 0xc574, 0x080c, 0x0dd5, 0x080c, 0x959a, + 0x080c, 0xae90, 0x080c, 0x96a6, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, 0x0027, 0x11f8, - 0x080c, 0x957b, 0x080c, 0x31c1, 0x080c, 0xd25f, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcb4a, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6c86, 0x080c, 0xcd33, 0x009e, 0x080c, - 0xae71, 0x080c, 0x9687, 0x0005, 0x080c, 0xaf07, 0x0ce0, 0x9186, - 0x0014, 0x1dd0, 0x080c, 0x957b, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcb4a, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, + 0x080c, 0x959a, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x0096, 0x6014, + 0x2048, 0x080c, 0xcb5a, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, + 0xa87b, 0x0029, 0x080c, 0x6c94, 0x080c, 0xcd43, 0x009e, 0x080c, + 0xae5f, 0x080c, 0x96a6, 0x0005, 0x080c, 0xaef5, 0x0ce0, 0x9186, + 0x0014, 0x1dd0, 0x080c, 0x959a, 0x0096, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xc5cc, 0xc5ca, 0xc5ca, 0xc5ca, 0xc5ca, 0xc5ca, 0xc5e4, 0xc5ca, 0xc5ca, 0xc5ca, 0xc5ca, - 0xc5ca, 0xc5ca, 0x080c, 0x0dd5, 0x080c, 0x957b, 0x6034, 0x908c, + 0xc5ca, 0xc5ca, 0x080c, 0x0dd5, 0x080c, 0x959a, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1985, 0x0010, 0x2001, 0x1986, 0x2004, 0x601a, 0x6003, - 0x000c, 0x080c, 0x9687, 0x0005, 0x080c, 0x957b, 0x6034, 0x908c, + 0x000c, 0x080c, 0x96a6, 0x0005, 0x080c, 0x959a, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1985, 0x0010, 0x2001, 0x1986, 0x2004, 0x601a, 0x6003, - 0x000e, 0x080c, 0x9687, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, - 0x0085, 0x0208, 0x0012, 0x0804, 0xaf07, 0xc612, 0xc612, 0xc612, + 0x000e, 0x080c, 0x96a6, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, + 0x0085, 0x0208, 0x0012, 0x0804, 0xaef5, 0xc612, 0xc612, 0xc612, 0xc612, 0xc614, 0xc661, 0xc612, 0xc612, 0xc612, 0xc612, 0xc612, 0xc612, 0xc612, 0x080c, 0x0dd5, 0x0096, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x009e, 0x0804, - 0xc675, 0x080c, 0xcb4a, 0x1118, 0x080c, 0xcd33, 0x0068, 0x6014, - 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xcd33, 0xa867, 0x0103, - 0x080c, 0xd22a, 0x080c, 0x6c86, 0x00d6, 0x2c68, 0x080c, 0xae1b, + 0xc675, 0x080c, 0xcb5a, 0x1118, 0x080c, 0xcd43, 0x0068, 0x6014, + 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xcd43, 0xa867, 0x0103, + 0x080c, 0xd23a, 0x080c, 0x6c94, 0x00d6, 0x2c68, 0x080c, 0xae09, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, - 0x6112, 0x080c, 0xcfc4, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x2d60, 0x00de, 0x080c, 0xae71, 0x009e, + 0x6112, 0x080c, 0xcfd4, 0x6954, 0x6156, 0x6023, 0x0001, 0x080c, + 0x90f8, 0x080c, 0x96a6, 0x2d60, 0x00de, 0x080c, 0xae5f, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, 0x2c68, 0x080c, - 0xd1c2, 0x11f0, 0x080c, 0xae1b, 0x01d8, 0x6106, 0x6003, 0x0001, + 0xd1d2, 0x11f0, 0x080c, 0xae09, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, - 0x6954, 0x6156, 0x080c, 0xcfc4, 0x080c, 0x90d9, 0x080c, 0x9687, - 0x2d60, 0x00de, 0x0804, 0xae71, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcb4a, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, + 0x6954, 0x6156, 0x080c, 0xcfd4, 0x080c, 0x90f8, 0x080c, 0x96a6, + 0x2d60, 0x00de, 0x0804, 0xae5f, 0x0096, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, - 0x0020, 0xa87b, 0x0005, 0x080c, 0xce44, 0xa877, 0x0000, 0x080c, - 0x6c86, 0x080c, 0xcd33, 0x009e, 0x0804, 0xae71, 0x0016, 0x0096, - 0x6014, 0x2048, 0x080c, 0xcb4a, 0x0140, 0xa867, 0x0103, 0xa87b, - 0x0028, 0xa877, 0x0000, 0x080c, 0x6c86, 0x009e, 0x001e, 0x9186, + 0x0020, 0xa87b, 0x0005, 0x080c, 0xce54, 0xa877, 0x0000, 0x080c, + 0x6c94, 0x080c, 0xcd43, 0x009e, 0x0804, 0xae5f, 0x0016, 0x0096, + 0x6014, 0x2048, 0x080c, 0xcb5a, 0x0140, 0xa867, 0x0103, 0xa87b, + 0x0028, 0xa877, 0x0000, 0x080c, 0x6c94, 0x009e, 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, - 0x080c, 0xaf07, 0x0030, 0x080c, 0x957b, 0x080c, 0xaea2, 0x080c, - 0x9687, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, + 0x080c, 0xaef5, 0x0030, 0x080c, 0x959a, 0x080c, 0xae90, 0x080c, + 0x96a6, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xc743, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x0fb1, 0x080c, @@ -6169,8 +6169,8 @@ unsigned short risc_code01[] = { 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, - 0x0130, 0xa807, 0x0000, 0x080c, 0x6c86, 0x2a48, 0x0cb8, 0x080c, - 0x6c86, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, + 0x0130, 0xa807, 0x0000, 0x080c, 0x6c94, 0x2a48, 0x0cb8, 0x080c, + 0x6c94, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, @@ -6180,58 +6180,58 @@ unsigned short risc_code01[] = { 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xc7a9, 0xc7a9, 0xc7a4, 0xc7cb, 0xc797, 0xc7a4, 0xc7cb, 0xc7a4, - 0xc797, 0x8ec2, 0xc7a4, 0xc7a4, 0xc7a4, 0xc797, 0xc797, 0x080c, - 0x0dd5, 0x0036, 0x2019, 0x0010, 0x080c, 0xe155, 0x6023, 0x0006, + 0xc797, 0x8ee1, 0xc7a4, 0xc7a4, 0xc7a4, 0xc797, 0xc797, 0x080c, + 0x0dd5, 0x0036, 0x2019, 0x0010, 0x080c, 0xe16f, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, - 0x0005, 0x0096, 0x86ff, 0x11d8, 0x6014, 0x2048, 0x080c, 0xcb4a, + 0x0005, 0x0096, 0x86ff, 0x11d8, 0x6014, 0x2048, 0x080c, 0xcb5a, 0x01c0, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, 0xa883, - 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x6eb9, 0x080c, - 0xce44, 0x080c, 0x6c7a, 0x080c, 0xaea2, 0x9085, 0x0001, 0x009e, + 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x6ec7, 0x080c, + 0xce54, 0x080c, 0x6c88, 0x080c, 0xae90, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x0002, 0xc7e1, 0xc80f, 0xc7e3, 0xc830, 0xc80a, 0xc7e1, 0xc7a4, 0xc7a9, 0xc7a9, 0xc7a4, 0xc7a4, 0xc7a4, 0xc7a4, 0xc7a4, 0xc7a4, 0xc7a4, 0x080c, 0x0dd5, 0x86ff, 0x1510, 0x6020, 0x9086, 0x0006, - 0x01f0, 0x0096, 0x6014, 0x2048, 0x080c, 0xcb4a, 0x0158, 0xa87c, + 0x01f0, 0x0096, 0x6014, 0x2048, 0x080c, 0xcb5a, 0x0158, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fb1, 0x009e, - 0x080c, 0xce44, 0x009e, 0x080c, 0xd204, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x080c, 0x90d9, 0x080c, 0x9687, 0x9085, - 0x0001, 0x0005, 0x0066, 0x080c, 0x1a60, 0x006e, 0x08a0, 0x00e6, - 0x2071, 0x19e6, 0x7024, 0x9c06, 0x1120, 0x080c, 0xa541, 0x00ee, + 0x080c, 0xce54, 0x009e, 0x080c, 0xd214, 0x6007, 0x0085, 0x6003, + 0x000b, 0x6023, 0x0002, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x9085, + 0x0001, 0x0005, 0x0066, 0x080c, 0x1a70, 0x006e, 0x08a0, 0x00e6, + 0x2071, 0x19e6, 0x7024, 0x9c06, 0x1120, 0x080c, 0xa552, 0x00ee, 0x0850, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, - 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0xa69d, 0x009e, 0x008e, - 0x0010, 0x080c, 0xa43e, 0x00ee, 0x1904, 0xc7e3, 0x0804, 0xc7a4, + 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0xa687, 0x009e, 0x008e, + 0x0010, 0x080c, 0xa44f, 0x00ee, 0x1904, 0xc7e3, 0x0804, 0xc7a4, 0x0036, 0x00e6, 0x2071, 0x19e6, 0x703c, 0x9c06, 0x1138, 0x901e, - 0x080c, 0xa5b7, 0x00ee, 0x003e, 0x0804, 0xc7e3, 0x080c, 0xa7cd, + 0x080c, 0xa5c8, 0x00ee, 0x003e, 0x0804, 0xc7e3, 0x080c, 0xa7b7, 0x00ee, 0x003e, 0x1904, 0xc7e3, 0x0804, 0xc7a4, 0x00c6, 0x6020, - 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xc863, 0xc92e, 0xca95, - 0xc86d, 0xaea2, 0xc863, 0xe147, 0xd26c, 0xc92e, 0x8e94, 0xcb14, - 0xc85c, 0xc85c, 0xc85c, 0xc85c, 0x080c, 0x0dd5, 0x080c, 0xcd50, - 0x1110, 0x080c, 0xb824, 0x0005, 0x080c, 0x957b, 0x080c, 0x9687, - 0x0804, 0xae71, 0x601b, 0x0001, 0x0005, 0x080c, 0xcb4a, 0x0130, + 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xc863, 0xc92e, 0xca98, + 0xc86d, 0xae90, 0xc863, 0xe161, 0xd27c, 0xc92e, 0x8eb3, 0xcb24, + 0xc85c, 0xc85c, 0xc85c, 0xc85c, 0x080c, 0x0dd5, 0x080c, 0xcd60, + 0x1110, 0x080c, 0xb821, 0x0005, 0x080c, 0x959a, 0x080c, 0x96a6, + 0x0804, 0xae5f, 0x601b, 0x0001, 0x0005, 0x080c, 0xcb5a, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x0002, 0xc88c, 0xc88e, 0xc8b2, 0xc8c6, 0xc8ec, 0xc88c, 0xc863, 0xc863, 0xc863, 0xc8c6, 0xc8c6, 0xc88c, 0xc88c, 0xc88c, 0xc88c, 0xc8d0, 0x080c, 0x0dd5, 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e6, - 0x7024, 0x9c06, 0x01a0, 0x080c, 0xa43e, 0x080c, 0xd204, 0x6007, + 0x7024, 0x9c06, 0x01a0, 0x080c, 0xa44f, 0x080c, 0xd214, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1986, 0x2004, - 0x601a, 0x080c, 0x90d9, 0x080c, 0x9687, 0x00ee, 0x0005, 0x601b, + 0x601a, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, - 0x009e, 0x080c, 0xd204, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x90d9, 0x080c, 0x9687, 0x0005, 0x0096, 0x601b, + 0x009e, 0x080c, 0xd214, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0005, 0x0096, 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, - 0x080c, 0x56e0, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, + 0x080c, 0x56ea, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, - 0x6c86, 0x009e, 0x0804, 0xae71, 0x6014, 0x0096, 0x904d, 0x05c8, + 0x6c94, 0x009e, 0x0804, 0xae5f, 0x6014, 0x0096, 0x904d, 0x05c8, 0xa97c, 0xd1e4, 0x05b0, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0030, 0x2c08, 0x080c, 0x15f0, 0x2001, 0x030c, 0x2004, 0x9086, 0x0041, 0x11a0, 0x6014, 0x0096, 0x904d, 0x090c, 0x0dd5, 0xa880, 0xd0f4, 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0070, 0x009e, 0x2001, 0x0037, 0x2c08, 0x080c, 0x15f0, - 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xaeec, - 0x0005, 0x009e, 0x080c, 0x1a60, 0x0804, 0xc8b2, 0x6000, 0x908a, + 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xaeda, + 0x0005, 0x009e, 0x080c, 0x1a70, 0x0804, 0xc8b2, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x000b, 0x0005, 0xc945, 0xc86a, 0xc947, 0xc945, 0xc947, 0xc947, 0xc864, 0xc945, 0xc85e, 0xc85e, 0xc945, 0xc945, 0xc945, 0xc945, 0xc945, 0xc945, 0x080c, 0x0dd5, 0x6010, @@ -6240,175 +6240,177 @@ unsigned short risc_code01[] = { 0xc964, 0xc9a4, 0xc964, 0xc9a4, 0xc964, 0xc972, 0xc962, 0xc9a4, 0xc962, 0xc993, 0x080c, 0x0dd5, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, - 0x0904, 0xca2b, 0x6004, 0x080c, 0xcd50, 0x0904, 0xca48, 0x908e, - 0x0004, 0x1110, 0x080c, 0x31ea, 0x908e, 0x0021, 0x0904, 0xca4c, - 0x908e, 0x0022, 0x0904, 0xca90, 0x908e, 0x003d, 0x0904, 0xca4c, + 0x0904, 0xca2b, 0x6004, 0x080c, 0xcd60, 0x0904, 0xca48, 0x908e, + 0x0004, 0x1110, 0x080c, 0x31f5, 0x908e, 0x0021, 0x0904, 0xca4c, + 0x908e, 0x0022, 0x0904, 0xca93, 0x908e, 0x003d, 0x0904, 0xca4c, 0x908e, 0x0039, 0x0904, 0xca50, 0x908e, 0x0035, 0x0904, 0xca50, 0x908e, 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x31c1, - 0x080c, 0xb824, 0x0804, 0xaea2, 0x00c6, 0x00d6, 0x6104, 0x9186, + 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x31cc, + 0x080c, 0xb821, 0x0804, 0xae90, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xca1c, 0x9186, 0x0002, 0x1904, 0xc9f1, 0x2001, - 0x1837, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x73a5, 0x11b0, 0x080c, - 0xd24a, 0x0138, 0x080c, 0x73c8, 0x1120, 0x080c, 0x72b5, 0x0804, - 0xca79, 0x2001, 0x197c, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, - 0x0001, 0x080c, 0x72d7, 0x0804, 0xca79, 0x6010, 0x2058, 0x2001, - 0x1837, 0x2004, 0xd0ac, 0x1904, 0xca79, 0xb8a0, 0x9084, 0xff80, - 0x1904, 0xca79, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, + 0x1837, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x73b3, 0x11b0, 0x080c, + 0xd25a, 0x0138, 0x080c, 0x73d6, 0x1120, 0x080c, 0x72c3, 0x0804, + 0xca7c, 0x2001, 0x197c, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, + 0x0001, 0x080c, 0x72e5, 0x0804, 0xca7c, 0x6010, 0x2058, 0x2001, + 0x1837, 0x2004, 0xd0ac, 0x1904, 0xca7c, 0xb8a0, 0x9084, 0xff80, + 0x1904, 0xca7c, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, - 0x0000, 0x080c, 0xae1b, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, + 0x0000, 0x080c, 0xae09, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, 0x2104, - 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fb6, 0x00ee, - 0x080c, 0xb824, 0x0030, 0x080c, 0xb824, 0x080c, 0x31c1, 0x080c, - 0xd25f, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x31ea, 0x012e, - 0x00ee, 0x080c, 0xaea2, 0x0005, 0x2001, 0x0002, 0x080c, 0x6558, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9121, 0x080c, 0x9687, - 0x00de, 0x00ce, 0x0c80, 0x080c, 0x31ea, 0x0804, 0xc9a0, 0x00c6, + 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fc0, 0x00ee, + 0x080c, 0xb821, 0x0030, 0x080c, 0xb821, 0x080c, 0x31cc, 0x080c, + 0xd26f, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x31f5, 0x012e, + 0x00ee, 0x080c, 0xae90, 0x0005, 0x2001, 0x0002, 0x080c, 0x6566, + 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9140, 0x080c, 0x96a6, + 0x00de, 0x00ce, 0x0c80, 0x080c, 0x31f5, 0x0804, 0xc9a0, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xc9f1, 0x8001, 0xb842, 0x6003, - 0x0001, 0x080c, 0x9121, 0x080c, 0x9687, 0x00de, 0x00ce, 0x0898, - 0x080c, 0xb824, 0x0804, 0xc9a2, 0x080c, 0xb860, 0x0804, 0xc9a2, - 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd1c2, 0x00de, 0x0118, 0x080c, - 0xae71, 0x00f0, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, + 0x0001, 0x080c, 0x9140, 0x080c, 0x96a6, 0x00de, 0x00ce, 0x0898, + 0x080c, 0xb821, 0x0804, 0xc9a2, 0x080c, 0xb85d, 0x0804, 0xc9a2, + 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd1d2, 0x00de, 0x0118, 0x080c, + 0xae5f, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, 0x2001, 0x1986, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, - 0x6024, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x90d9, 0x080c, 0x9687, - 0x0005, 0x00de, 0x00ce, 0x080c, 0xb824, 0x080c, 0x31c1, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x31ea, 0x6017, 0x0000, 0x6023, - 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, 0x00ee, 0x0005, - 0x080c, 0xb2a2, 0x1904, 0xca48, 0x0005, 0x6000, 0x908a, 0x0016, - 0x1a0c, 0x0dd5, 0x0096, 0x00d6, 0x001b, 0x00de, 0x009e, 0x0005, - 0xcab0, 0xcab0, 0xcab0, 0xcab0, 0xcab0, 0xcab0, 0xcab0, 0xcab0, - 0xcab0, 0xc863, 0xcab0, 0xc86a, 0xcab2, 0xc86a, 0xcabf, 0xcab0, - 0x080c, 0x0dd5, 0x6004, 0x9086, 0x008b, 0x0148, 0x6007, 0x008b, - 0x6003, 0x000d, 0x080c, 0x90d9, 0x080c, 0x9687, 0x0005, 0x080c, - 0xd23e, 0x0118, 0x080c, 0xd251, 0x0010, 0x080c, 0xd25f, 0x080c, - 0xcd33, 0x080c, 0xcb4a, 0x0570, 0x080c, 0x31c1, 0x080c, 0xcb4a, + 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x080c, + 0x90f8, 0x080c, 0x96a6, 0x0005, 0x00de, 0x00ce, 0x080c, 0xb821, + 0x080c, 0x31cc, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x31f5, + 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, + 0x012e, 0x00ee, 0x0005, 0x080c, 0xb290, 0x1904, 0xca48, 0x0005, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0dd5, 0x0096, 0x00d6, 0x001b, + 0x00de, 0x009e, 0x0005, 0xcab3, 0xcab3, 0xcab3, 0xcab3, 0xcab3, + 0xcab3, 0xcab3, 0xcab3, 0xcab3, 0xc863, 0xcab3, 0xc86a, 0xcab5, + 0xc86a, 0xcacf, 0xcab3, 0x080c, 0x0dd5, 0x6004, 0x9086, 0x008b, + 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, + 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, + 0x6003, 0x000d, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0005, 0x080c, + 0xd24e, 0x0118, 0x080c, 0xd261, 0x0010, 0x080c, 0xd26f, 0x080c, + 0xcd43, 0x080c, 0xcb5a, 0x0570, 0x080c, 0x31cc, 0x080c, 0xcb5a, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, - 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6c86, 0x2c68, 0x080c, - 0xae1b, 0x0150, 0x6810, 0x6012, 0x080c, 0xcfc4, 0x00c6, 0x2d60, - 0x080c, 0xaea2, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, - 0x9687, 0x00c8, 0x080c, 0xd23e, 0x0138, 0x6034, 0x9086, 0x4000, - 0x1118, 0x080c, 0x31c1, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x31c1, - 0x0868, 0x080c, 0xaea2, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, - 0x0dd5, 0x0002, 0xcb2a, 0xcb2a, 0xcb2c, 0xcb2c, 0xcb2c, 0xcb2a, - 0xcb2a, 0xaea2, 0xcb2a, 0xcb2a, 0xcb2a, 0xcb2a, 0xcb2a, 0xcb2a, - 0xcb2a, 0xcb2a, 0x080c, 0x0dd5, 0x080c, 0xa7cd, 0x6114, 0x0096, - 0x2148, 0xa87b, 0x0006, 0x080c, 0x6c86, 0x009e, 0x0804, 0xae71, + 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6c94, 0x2c68, 0x080c, + 0xae09, 0x0150, 0x6810, 0x6012, 0x080c, 0xcfd4, 0x00c6, 0x2d60, + 0x080c, 0xae90, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, + 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x00c8, 0x080c, 0xd24e, 0x0138, 0x6034, 0x9086, 0x4000, + 0x1118, 0x080c, 0x31cc, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x31cc, + 0x0868, 0x080c, 0xae90, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, + 0x0dd5, 0x0002, 0xcb3a, 0xcb3a, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3a, + 0xcb3a, 0xae90, 0xcb3a, 0xcb3a, 0xcb3a, 0xcb3a, 0xcb3a, 0xcb3a, + 0xcb3a, 0xcb3a, 0x080c, 0x0dd5, 0x080c, 0xa7b7, 0x6114, 0x0096, + 0x2148, 0xa87b, 0x0006, 0x080c, 0x6c94, 0x009e, 0x0804, 0xae5f, 0x9284, 0x0007, 0x1158, 0x9282, 0x1cd0, 0x0240, 0x2001, 0x181a, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x10aa, 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7354, 0x7074, 0x9302, - 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd24a, 0x0180, 0x9286, - 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x31c1, - 0x080c, 0xd25f, 0x00c6, 0x080c, 0xaea2, 0x00ce, 0x0060, 0x080c, - 0xcf3e, 0x0148, 0x080c, 0xcd50, 0x1110, 0x080c, 0xb824, 0x00c6, - 0x080c, 0xae71, 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, + 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd25a, 0x0180, 0x9286, + 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x31cc, + 0x080c, 0xd26f, 0x00c6, 0x080c, 0xae90, 0x00ce, 0x0060, 0x080c, + 0xcf4e, 0x0148, 0x080c, 0xcd60, 0x1110, 0x080c, 0xb821, 0x00c6, + 0x080c, 0xae5f, 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, - 0x1aaf, 0x6112, 0x080c, 0x31c1, 0x9006, 0x0010, 0x9085, 0x0001, + 0x1aaf, 0x6112, 0x080c, 0x31cc, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xae1b, 0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, 0x56e0, - 0x0118, 0x080c, 0xcc77, 0x0168, 0x080c, 0xcfc4, 0x6023, 0x0003, - 0x2009, 0x004b, 0x080c, 0xaeec, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x080c, 0xae09, 0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, 0x56ea, + 0x0118, 0x080c, 0xcc87, 0x0168, 0x080c, 0xcfd4, 0x6023, 0x0003, + 0x2009, 0x004b, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, - 0x080c, 0xaebf, 0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, 0x080c, - 0xcfc4, 0x6023, 0x0003, 0x0016, 0x080c, 0x927e, 0x0076, 0x903e, - 0x080c, 0x9151, 0x2c08, 0x080c, 0xe30c, 0x007e, 0x001e, 0xd184, - 0x0128, 0x080c, 0xae71, 0x9085, 0x0001, 0x0070, 0x080c, 0x56e0, - 0x0128, 0xd18c, 0x1170, 0x080c, 0xcc77, 0x0148, 0x2009, 0x004c, - 0x080c, 0xaeec, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x080c, 0xaead, 0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, 0x080c, + 0xcfd4, 0x6023, 0x0003, 0x0016, 0x080c, 0x929d, 0x0076, 0x903e, + 0x080c, 0x9170, 0x2c08, 0x080c, 0xe326, 0x007e, 0x001e, 0xd184, + 0x0128, 0x080c, 0xae5f, 0x9085, 0x0001, 0x0070, 0x080c, 0x56ea, + 0x0128, 0xd18c, 0x1170, 0x080c, 0xcc87, 0x0148, 0x2009, 0x004c, + 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, - 0x004e, 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, 0xae1b, 0x2c78, + 0x004e, 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, 0xae09, 0x2c78, 0x0590, 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, 0x2021, 0x0005, - 0x080c, 0xcc89, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, - 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xae71, + 0x080c, 0xcc99, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, + 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xae5f, 0x00d0, 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xae71, 0x0088, 0x2f60, 0x080c, 0x56e0, 0x0138, 0xd18c, 0x1118, + 0xae5f, 0x0088, 0x2f60, 0x080c, 0x56ea, 0x0138, 0xd18c, 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, - 0xaeec, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x00f6, 0x00c6, 0x0046, 0x080c, 0xae1b, 0x2c78, 0x0508, 0x7e56, + 0xaeda, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, + 0x00f6, 0x00c6, 0x0046, 0x080c, 0xae09, 0x2c78, 0x0508, 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, 0x2001, 0x197d, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xae71, 0x0060, 0x2f60, 0x080c, 0x56e0, 0x0120, 0xd18c, 0x1160, - 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0xaeec, 0x9085, 0x0001, + 0xae5f, 0x0060, 0x2f60, 0x080c, 0x56ea, 0x0120, 0xd18c, 0x1160, + 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0xaeda, 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, - 0x080c, 0x4ab4, 0x00ce, 0x1120, 0x080c, 0xae71, 0x9006, 0x0005, + 0x080c, 0x4abe, 0x00ce, 0x1120, 0x080c, 0xae5f, 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, - 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x673c, - 0x0158, 0x2001, 0xcc8e, 0x0006, 0x900e, 0x2400, 0x080c, 0x6eb9, - 0x080c, 0x6c86, 0x000e, 0x0807, 0x2418, 0x080c, 0x9515, 0xbaa0, - 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x9296, - 0x008e, 0x080c, 0x9151, 0x2f08, 0x2648, 0x080c, 0xe30c, 0xb93c, - 0x81ff, 0x090c, 0x9367, 0x080c, 0x9687, 0x012e, 0x007e, 0x009e, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xae1b, 0x0190, - 0x660a, 0x2b08, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x001f, 0x080c, 0xaeec, 0x9085, 0x0001, 0x012e, + 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x674a, + 0x0158, 0x2001, 0xcc9e, 0x0006, 0x900e, 0x2400, 0x080c, 0x6ec7, + 0x080c, 0x6c94, 0x000e, 0x0807, 0x2418, 0x080c, 0x9534, 0xbaa0, + 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x92b5, + 0x008e, 0x080c, 0x9170, 0x2f08, 0x2648, 0x080c, 0xe326, 0xb93c, + 0x81ff, 0x090c, 0x9386, 0x080c, 0x96a6, 0x012e, 0x007e, 0x009e, + 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xae09, 0x0190, + 0x660a, 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0001, 0x2900, + 0x6016, 0x2009, 0x001f, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xaebf, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xcfc4, + 0x080c, 0xaead, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1727, - 0x00fe, 0x2009, 0x0021, 0x080c, 0xaeec, 0x9085, 0x0001, 0x012e, + 0x00fe, 0x2009, 0x0021, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, - 0x0016, 0x2091, 0x8000, 0x080c, 0xae1b, 0x0198, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x0016, 0x080c, 0xaeec, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, + 0x0016, 0x2091, 0x8000, 0x080c, 0xae09, 0x0198, 0x660a, 0x2b08, + 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, + 0x0016, 0x080c, 0xaeda, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0xaebf, 0x0188, 0x2b08, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xaeec, 0x9085, 0x0001, + 0xaead, 0x0188, 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0001, + 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, - 0x904d, 0x080c, 0xcb4a, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, + 0x904d, 0x080c, 0xcb5a, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, - 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xaebf, - 0x0198, 0x2b08, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0001, 0x2900, - 0x6016, 0x080c, 0x31c1, 0x2009, 0x0028, 0x080c, 0xaeec, 0x9085, + 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xaead, + 0x0198, 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0001, 0x2900, + 0x6016, 0x080c, 0x31cc, 0x2009, 0x0028, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, - 0x080c, 0xba78, 0x00be, 0x080c, 0xbc9b, 0x6003, 0x0001, 0x6007, - 0x0029, 0x080c, 0x9121, 0x080c, 0x9687, 0x0078, 0x6014, 0x0096, + 0x080c, 0xba75, 0x00be, 0x080c, 0xbc98, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x9140, 0x080c, 0x96a6, 0x0078, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, - 0xd183, 0x080c, 0xb824, 0x080c, 0xae71, 0x0005, 0x0096, 0x6014, + 0xd193, 0x080c, 0xb821, 0x080c, 0xae5f, 0x0005, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dd5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6c86, 0x012e, 0x009e, 0x080c, 0xae71, 0x0c30, 0x0096, - 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x6558, 0x00e8, + 0x080c, 0x6c94, 0x012e, 0x009e, 0x080c, 0xae5f, 0x0c30, 0x0096, + 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x6566, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, - 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x66a3, 0x00be, 0x080c, - 0xbd6c, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, - 0x0160, 0x2001, 0x0006, 0x080c, 0x6558, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0170, 0x080c, 0xb276, 0x0048, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0528, 0x080c, 0xb824, 0x080c, 0xae71, 0x009e, 0x0005, + 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x66b1, 0x00be, 0x080c, + 0xbd69, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, + 0x0160, 0x2001, 0x0006, 0x080c, 0x6566, 0x6014, 0x2048, 0xa868, + 0xd0fc, 0x0170, 0x080c, 0xb264, 0x0048, 0x6014, 0x2048, 0xa868, + 0xd0fc, 0x0528, 0x080c, 0xb821, 0x080c, 0xae5f, 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0dd5, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6828, 0x1108, + 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6c86, 0x012e, 0x080c, 0xae71, 0x08f8, 0x6014, + 0x8000, 0x080c, 0x6c94, 0x012e, 0x080c, 0xae5f, 0x08f8, 0x6014, 0x904d, 0x090c, 0x0dd5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6c86, 0x012e, 0x080c, 0xae71, 0x0840, 0xa878, 0x9086, + 0x080c, 0x6c94, 0x012e, 0x080c, 0xae5f, 0x0840, 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x90d9, 0x080c, 0x9687, 0x0005, 0x00c6, 0x6010, 0x00b6, + 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xc863, 0xce74, 0xce74, 0xce77, 0xe61e, - 0xe639, 0xe63c, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, + 0x0013, 0x00ce, 0x0005, 0xc863, 0xce84, 0xce84, 0xce87, 0xe638, + 0xe653, 0xe656, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, 0xc863, 0x080c, 0x0dd5, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, - 0x080c, 0xae1b, 0x0508, 0x7810, 0x6012, 0x080c, 0xcfc4, 0x7820, + 0x080c, 0xae09, 0x0508, 0x7810, 0x6012, 0x080c, 0xcfd4, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, - 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x90d9, 0x080c, - 0x9687, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1987, + 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x90f8, 0x080c, + 0x96a6, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1987, 0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, 0xa87c, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, @@ -6419,7 +6421,7 @@ unsigned short risc_code01[] = { 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, - 0x080c, 0x90d9, 0x080c, 0x9687, 0x009e, 0x001e, 0x0005, 0x6024, + 0x080c, 0x90f8, 0x080c, 0x96a6, 0x009e, 0x001e, 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, @@ -6431,273 +6433,273 @@ unsigned short risc_code01[] = { 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1981, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x080c, 0x8f51, 0x2001, 0x1985, 0x82ff, 0x1110, + 0x2001, 0x0032, 0x080c, 0x8f70, 0x2001, 0x1985, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1983, 0x200c, 0x8000, 0x2014, - 0x2071, 0x196b, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x8f51, + 0x2071, 0x196b, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x8f70, 0x2001, 0x1986, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1987, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a90, 0x2102, 0x2001, - 0x0032, 0x080c, 0x15f0, 0x080c, 0x695c, 0x00ee, 0x003e, 0x002e, + 0x0032, 0x080c, 0x15f0, 0x080c, 0x696a, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1985, 0x2003, 0x0028, 0x2001, 0x1986, 0x2003, 0x0014, 0x2071, 0x196b, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1987, 0x2009, 0x001e, 0x2102, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, 0x080c, 0x15f0, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110, 0x080c, 0x1031, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xae1b, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xaeec, 0x9085, + 0x8000, 0x080c, 0xae09, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, + 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, 0x7090, 0x9086, 0x0018, 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, - 0x080c, 0x9921, 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, + 0x080c, 0x993c, 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, - 0x900e, 0x080c, 0x320a, 0x080c, 0xb276, 0x0020, 0x080c, 0xb824, - 0x080c, 0xae71, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, + 0x900e, 0x080c, 0x3215, 0x080c, 0xb264, 0x0020, 0x080c, 0xb821, + 0x080c, 0xae5f, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0xae1b, 0x0188, 0x2b08, 0x6112, 0x080c, 0xcfc4, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0xaeec, 0x9085, 0x0001, + 0xae09, 0x0188, 0x2b08, 0x6112, 0x080c, 0xcfd4, 0x6023, 0x0001, + 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x0016, 0x080c, 0xae1b, 0x0180, 0x2b08, 0x6112, 0x080c, - 0xcfc4, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xaeec, + 0x8000, 0x0016, 0x080c, 0xae09, 0x0180, 0x2b08, 0x6112, 0x080c, + 0xcfd4, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xaeda, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x199f, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, - 0x001b, 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, 0x080c, 0xd83a, + 0x001b, 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, 0x080c, 0xd84a, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, - 0xa867, 0x0103, 0x0010, 0x080c, 0xb824, 0x080c, 0xae71, 0x00fe, + 0xa867, 0x0103, 0x0010, 0x080c, 0xb821, 0x080c, 0xae5f, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, - 0x080c, 0x9921, 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, - 0xaa78, 0x9206, 0x1110, 0x080c, 0x31c1, 0x080c, 0xb276, 0x0020, - 0x080c, 0xb824, 0x080c, 0xae71, 0x00fe, 0x00ee, 0x009e, 0x0005, + 0x080c, 0x993c, 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, + 0xaa78, 0x9206, 0x1110, 0x080c, 0x31cc, 0x080c, 0xb264, 0x0020, + 0x080c, 0xb821, 0x080c, 0xae5f, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1550, 0x7090, 0x9086, 0x0004, - 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9921, 0x05f0, 0x707c, + 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x993c, 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, - 0x31c1, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, - 0x5690, 0x001e, 0x0010, 0x080c, 0x5481, 0x080c, 0xcb4a, 0x0508, + 0x31cc, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, + 0x569a, 0x001e, 0x0010, 0x080c, 0x548b, 0x080c, 0xcb5a, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, - 0xcb4a, 0x01b8, 0x6014, 0x2048, 0x080c, 0x5481, 0x1d70, 0xa87b, + 0xcb5a, 0x01b8, 0x6014, 0x2048, 0x080c, 0x548b, 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, - 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6c86, 0x012e, 0x080c, - 0xae71, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, + 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6c94, 0x012e, 0x080c, + 0xae5f, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, - 0x0005, 0x00b6, 0x00d6, 0x0036, 0x080c, 0xcb4a, 0x0904, 0xd17f, + 0x0005, 0x00b6, 0x00d6, 0x0036, 0x080c, 0xcb5a, 0x0904, 0xd18f, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, - 0x080c, 0x6828, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, + 0x080c, 0x6836, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f7c, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f7c, 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, - 0x00ff, 0xa89e, 0x080c, 0x6c7a, 0x6017, 0x0000, 0x009e, 0x003e, + 0x00ff, 0xa89e, 0x080c, 0x6c88, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, - 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x2840, + 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x284b, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, - 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4b14, 0x00a8, 0x9096, 0x0001, + 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4b1e, 0x00a8, 0x9096, 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, - 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xcb38, 0x01f0, 0x2260, 0x6120, + 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xcb48, 0x01f0, 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, 0xa9a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0xa834, 0xa938, - 0x9115, 0x190c, 0xc258, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, - 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xcb4a, 0x01c8, 0x080c, - 0xcd33, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, - 0xa87c, 0x080c, 0xcd50, 0x1118, 0x080c, 0xb824, 0x0040, 0xa867, - 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6c86, 0x009e, + 0x9115, 0x190c, 0xc255, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, + 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xcb5a, 0x01c8, 0x080c, + 0xcd43, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, + 0xa87c, 0x080c, 0xcd60, 0x1118, 0x080c, 0xb821, 0x0040, 0xa867, + 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6c94, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, - 0x0005, 0x080c, 0xce44, 0xa877, 0x0000, 0x0005, 0x2001, 0x1810, + 0x0005, 0x080c, 0xce54, 0xa877, 0x0000, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, - 0x2021, 0x0007, 0x080c, 0x4ccb, 0x004e, 0x003e, 0x0005, 0x0c51, + 0x2021, 0x0007, 0x080c, 0x4cd5, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1985, 0x2004, 0x601a, 0x0005, 0x2001, - 0x1987, 0x2004, 0x6042, 0x0005, 0x080c, 0xae71, 0x0804, 0x9687, + 0x1987, 0x2004, 0x6042, 0x0005, 0x080c, 0xae5f, 0x0804, 0x96a6, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0dd5, 0x001b, - 0x006e, 0x00be, 0x0005, 0xd28b, 0xd997, 0xdaf4, 0xd28b, 0xd28b, - 0xd28b, 0xd28b, 0xd28b, 0xd2c2, 0xdb78, 0xd28b, 0xd28b, 0xd28b, - 0xd28b, 0xd28b, 0xd28b, 0x080c, 0x0dd5, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0dd5, 0x0013, 0x006e, 0x0005, 0xd2a6, 0xe0e0, - 0xd2a6, 0xd2a6, 0xd2a6, 0xd2a6, 0xd2a6, 0xd2a6, 0xe08d, 0xe134, - 0xd2a6, 0xe759, 0xe78f, 0xe759, 0xe78f, 0xd2a6, 0x080c, 0x0dd5, + 0x006e, 0x00be, 0x0005, 0xd29b, 0xd9a7, 0xdb04, 0xd29b, 0xd29b, + 0xd29b, 0xd29b, 0xd29b, 0xd2d2, 0xdb88, 0xd29b, 0xd29b, 0xd29b, + 0xd29b, 0xd29b, 0xd29b, 0x080c, 0x0dd5, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0dd5, 0x0013, 0x006e, 0x0005, 0xd2b6, 0xe0fa, + 0xd2b6, 0xd2b6, 0xd2b6, 0xd2b6, 0xd2b6, 0xd2b6, 0xe0a7, 0xe14e, + 0xd2b6, 0xe773, 0xe7a9, 0xe773, 0xe7a9, 0xd2b6, 0x080c, 0x0dd5, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0dd5, 0x6000, 0x000a, 0x0005, - 0xd2c0, 0xdd55, 0xde45, 0xde67, 0xdf26, 0xd2c0, 0xe004, 0xdfae, - 0xdb84, 0xe063, 0xe078, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c0, + 0xd2d0, 0xdd66, 0xde58, 0xde7b, 0xdf3b, 0xd2d0, 0xe01a, 0xdfc3, + 0xdb94, 0xe07d, 0xe092, 0xd2d0, 0xd2d0, 0xd2d0, 0xd2d0, 0xd2d0, 0x080c, 0x0dd5, 0x91b2, 0x0053, 0x1a0c, 0x0dd5, 0x2100, 0x91b2, - 0x0040, 0x1a04, 0xd70b, 0x0002, 0xd30c, 0xd4fc, 0xd30c, 0xd30c, - 0xd30c, 0xd505, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, - 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, - 0xd30c, 0xd30c, 0xd30c, 0xd30e, 0xd371, 0xd380, 0xd3e4, 0xd40f, - 0xd488, 0xd4e7, 0xd30c, 0xd30c, 0xd508, 0xd30c, 0xd30c, 0xd51d, - 0xd52a, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd5ad, 0xd30c, - 0xd30c, 0xd5c1, 0xd30c, 0xd30c, 0xd57c, 0xd30c, 0xd30c, 0xd30c, - 0xd5d9, 0xd30c, 0xd30c, 0xd30c, 0xd656, 0xd30c, 0xd30c, 0xd30c, - 0xd30c, 0xd30c, 0xd30c, 0xd6d3, 0x080c, 0x0dd5, 0x080c, 0x6939, + 0x0040, 0x1a04, 0xd71b, 0x0002, 0xd31c, 0xd50c, 0xd31c, 0xd31c, + 0xd31c, 0xd515, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, + 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, + 0xd31c, 0xd31c, 0xd31c, 0xd31e, 0xd381, 0xd390, 0xd3f4, 0xd41f, + 0xd498, 0xd4f7, 0xd31c, 0xd31c, 0xd518, 0xd31c, 0xd31c, 0xd52d, + 0xd53a, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd5bd, 0xd31c, + 0xd31c, 0xd5d1, 0xd31c, 0xd31c, 0xd58c, 0xd31c, 0xd31c, 0xd31c, + 0xd5e9, 0xd31c, 0xd31c, 0xd31c, 0xd666, 0xd31c, 0xd31c, 0xd31c, + 0xd31c, 0xd31c, 0xd31c, 0xd6e3, 0x080c, 0x0dd5, 0x080c, 0x6947, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, 0x6017, - 0x0000, 0x0804, 0xd4f5, 0x080c, 0x68d5, 0x00e6, 0x00c6, 0x0036, + 0x0000, 0x0804, 0xd505, 0x080c, 0x68e3, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, - 0x080c, 0x927e, 0x0076, 0x903e, 0x080c, 0x9151, 0x2c08, 0x080c, - 0xe30c, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x6610, 0x2658, 0x080c, 0x6617, 0xbe04, 0x9684, 0x00ff, 0x9082, + 0x080c, 0x929d, 0x0076, 0x903e, 0x080c, 0x9170, 0x2c08, 0x080c, + 0xe326, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, + 0x6610, 0x2658, 0x080c, 0x6625, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, - 0x00be, 0x2c08, 0x080c, 0xe9b8, 0x002e, 0x001e, 0x1178, 0x080c, - 0xe23e, 0x1904, 0xd3dc, 0x080c, 0xe1da, 0x1120, 0x6007, 0x0008, - 0x0804, 0xd4f5, 0x6007, 0x0009, 0x0804, 0xd4f5, 0x080c, 0xe462, - 0x0128, 0x080c, 0xe23e, 0x0d78, 0x0804, 0xd3dc, 0x6017, 0x1900, - 0x0c88, 0x080c, 0x32e5, 0x1904, 0xd708, 0x6106, 0x080c, 0xe18f, - 0x6007, 0x0006, 0x0804, 0xd4f5, 0x6007, 0x0007, 0x0804, 0xd4f5, - 0x080c, 0xe7cb, 0x1904, 0xd708, 0x080c, 0x32e5, 0x1904, 0xd708, + 0x00be, 0x2c08, 0x080c, 0xe9d2, 0x002e, 0x001e, 0x1178, 0x080c, + 0xe258, 0x1904, 0xd3ec, 0x080c, 0xe1f4, 0x1120, 0x6007, 0x0008, + 0x0804, 0xd505, 0x6007, 0x0009, 0x0804, 0xd505, 0x080c, 0xe47c, + 0x0128, 0x080c, 0xe258, 0x0d78, 0x0804, 0xd3ec, 0x6017, 0x1900, + 0x0c88, 0x080c, 0x32f0, 0x1904, 0xd718, 0x6106, 0x080c, 0xe1a9, + 0x6007, 0x0006, 0x0804, 0xd505, 0x6007, 0x0007, 0x0804, 0xd505, + 0x080c, 0xe7e5, 0x1904, 0xd718, 0x080c, 0x32f0, 0x1904, 0xd718, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, - 0x1220, 0x2001, 0x0001, 0x080c, 0x6544, 0x96b4, 0xff00, 0x8637, + 0x1220, 0x2001, 0x0001, 0x080c, 0x6552, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, - 0x00b0, 0x00ee, 0x080c, 0xe2a2, 0x1190, 0x9686, 0x0006, 0x1140, - 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x320a, 0x002e, - 0x080c, 0x66a3, 0x6007, 0x000a, 0x00de, 0x0804, 0xd4f5, 0x6007, - 0x000b, 0x00de, 0x0804, 0xd4f5, 0x080c, 0x31c1, 0x080c, 0xd25f, - 0x6007, 0x0001, 0x0804, 0xd4f5, 0x080c, 0xe7cb, 0x1904, 0xd708, - 0x080c, 0x32e5, 0x1904, 0xd708, 0x2071, 0x0260, 0x7034, 0x90b4, + 0x00b0, 0x00ee, 0x080c, 0xe2bc, 0x1190, 0x9686, 0x0006, 0x1140, + 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3215, 0x002e, + 0x080c, 0x66b1, 0x6007, 0x000a, 0x00de, 0x0804, 0xd505, 0x6007, + 0x000b, 0x00de, 0x0804, 0xd505, 0x080c, 0x31cc, 0x080c, 0xd26f, + 0x6007, 0x0001, 0x0804, 0xd505, 0x080c, 0xe7e5, 0x1904, 0xd718, + 0x080c, 0x32f0, 0x1904, 0xd718, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, - 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x320a, 0x002e, 0x6007, - 0x000c, 0x2001, 0x0001, 0x080c, 0xe998, 0x0804, 0xd4f5, 0x080c, - 0x6939, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, - 0x0008, 0x1110, 0x0804, 0xd31b, 0x080c, 0x68d5, 0x6610, 0x2658, + 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3215, 0x002e, 0x6007, + 0x000c, 0x2001, 0x0001, 0x080c, 0xe9b2, 0x0804, 0xd505, 0x080c, + 0x6947, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, + 0x0008, 0x1110, 0x0804, 0xd32b, 0x080c, 0x68e3, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, 0x0026, - 0x2001, 0x0006, 0x080c, 0x6584, 0x002e, 0x0050, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd3dc, - 0x080c, 0xe2af, 0x1120, 0x6007, 0x000e, 0x0804, 0xd4f5, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31c1, 0x080c, 0xd25f, + 0x2001, 0x0006, 0x080c, 0x6592, 0x002e, 0x0050, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd3ec, + 0x080c, 0xe2c9, 0x1120, 0x6007, 0x000e, 0x0804, 0xd505, 0x0046, + 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, - 0x2009, 0x0029, 0x080c, 0xe5cf, 0x6010, 0x2058, 0xb800, 0xc0e5, - 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xd4f5, 0x2001, - 0x0001, 0x080c, 0x6544, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xbe1c, 0x003e, + 0x2009, 0x0029, 0x080c, 0xe5e9, 0x6010, 0x2058, 0xb800, 0xc0e5, + 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xd505, 0x2001, + 0x0001, 0x080c, 0x6552, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xbe19, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, - 0x9682, 0x0004, 0x0a04, 0xd3dc, 0x9682, 0x0007, 0x0a04, 0xd438, - 0x0804, 0xd3dc, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd4f5, - 0x080c, 0x6939, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1110, 0x0804, 0xd31b, 0x080c, 0x68d5, 0x6610, + 0x9682, 0x0004, 0x0a04, 0xd3ec, 0x9682, 0x0007, 0x0a04, 0xd448, + 0x0804, 0xd3ec, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd505, + 0x080c, 0x6947, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, + 0x9086, 0x0008, 0x1110, 0x0804, 0xd32b, 0x080c, 0x68e3, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, 0x9086, 0x0001, 0x000e, 0x0170, 0x9082, 0x0006, 0x0698, 0x0150, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd3dc, 0x080c, - 0xe2dd, 0x1130, 0x080c, 0xe1da, 0x1118, 0x6007, 0x0010, 0x04e8, - 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31c1, 0x080c, - 0xd25f, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, - 0x0148, 0x2009, 0x0029, 0x080c, 0xe5cf, 0x6010, 0x2058, 0xb800, + 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd3ec, 0x080c, + 0xe2f7, 0x1130, 0x080c, 0xe1f4, 0x1118, 0x6007, 0x0010, 0x04e8, + 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31cc, 0x080c, + 0xd26f, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, + 0x0148, 0x2009, 0x0029, 0x080c, 0xe5e9, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, - 0xe462, 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0978, - 0x0804, 0xd3dc, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, - 0x32e5, 0x1904, 0xd708, 0x080c, 0xe7cb, 0x1904, 0xd708, 0x080c, - 0xd8d5, 0x1904, 0xd3dc, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, - 0x9121, 0x080c, 0x9687, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9121, 0x080c, 0x9687, 0x0cb0, 0x6007, 0x0005, 0x0c68, - 0x080c, 0xe7cb, 0x1904, 0xd708, 0x080c, 0x32e5, 0x1904, 0xd708, - 0x080c, 0xd8d5, 0x1904, 0xd3dc, 0x6007, 0x0020, 0x6003, 0x0001, - 0x080c, 0x9121, 0x080c, 0x9687, 0x0005, 0x080c, 0x32e5, 0x1904, - 0xd708, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, - 0x9687, 0x0005, 0x080c, 0xe7cb, 0x1904, 0xd708, 0x080c, 0x32e5, - 0x1904, 0xd708, 0x080c, 0xd8d5, 0x1904, 0xd3dc, 0x0016, 0x0026, + 0xe47c, 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0978, + 0x0804, 0xd3ec, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, + 0x32f0, 0x1904, 0xd718, 0x080c, 0xe7e5, 0x1904, 0xd718, 0x080c, + 0xd8e5, 0x1904, 0xd3ec, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, + 0x9140, 0x080c, 0x96a6, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x9140, 0x080c, 0x96a6, 0x0cb0, 0x6007, 0x0005, 0x0c68, + 0x080c, 0xe7e5, 0x1904, 0xd718, 0x080c, 0x32f0, 0x1904, 0xd718, + 0x080c, 0xd8e5, 0x1904, 0xd3ec, 0x6007, 0x0020, 0x6003, 0x0001, + 0x080c, 0x9140, 0x080c, 0x96a6, 0x0005, 0x080c, 0x32f0, 0x1904, + 0xd718, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x0005, 0x080c, 0xe7e5, 0x1904, 0xd718, 0x080c, 0x32f0, + 0x1904, 0xd718, 0x080c, 0xd8e5, 0x1904, 0xd3ec, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, - 0x080c, 0xcb38, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, + 0x080c, 0xcb48, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, - 0x2c08, 0x9006, 0x080c, 0xe599, 0x1180, 0x7244, 0x9286, 0xffff, + 0x2c08, 0x9006, 0x080c, 0xe5b3, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, - 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, 0xae71, 0x2160, - 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, 0x9687, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x6544, + 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, 0xae5f, 0x2160, + 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, 0x96a6, + 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x6552, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0276, 0x080c, 0xbe1c, 0x003e, 0x002e, 0x001e, 0x015e, - 0x0120, 0x6007, 0x0031, 0x0804, 0xd4f5, 0x080c, 0xba90, 0x080c, - 0x73a5, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x73bf, 0x1138, - 0x080c, 0x768d, 0x080c, 0x6023, 0x080c, 0x72d7, 0x0010, 0x080c, - 0x737d, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x32e5, 0x1904, - 0xd708, 0x080c, 0xd8d5, 0x1904, 0xd3dc, 0x6106, 0x080c, 0xd8f1, - 0x1120, 0x6007, 0x002b, 0x0804, 0xd4f5, 0x6007, 0x002c, 0x0804, - 0xd4f5, 0x080c, 0xe7cb, 0x1904, 0xd708, 0x080c, 0x32e5, 0x1904, - 0xd708, 0x080c, 0xd8d5, 0x1904, 0xd3dc, 0x6106, 0x080c, 0xd8f6, - 0x1120, 0x6007, 0x002e, 0x0804, 0xd4f5, 0x6007, 0x002f, 0x0804, - 0xd4f5, 0x080c, 0x32e5, 0x1904, 0xd708, 0x00e6, 0x00d6, 0x00c6, + 0x2011, 0x0276, 0x080c, 0xbe19, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0120, 0x6007, 0x0031, 0x0804, 0xd505, 0x080c, 0xba8d, 0x080c, + 0x73b3, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x73cd, 0x1138, + 0x080c, 0x7699, 0x080c, 0x602d, 0x080c, 0x72e5, 0x0010, 0x080c, + 0x738b, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x32f0, 0x1904, + 0xd718, 0x080c, 0xd8e5, 0x1904, 0xd3ec, 0x6106, 0x080c, 0xd901, + 0x1120, 0x6007, 0x002b, 0x0804, 0xd505, 0x6007, 0x002c, 0x0804, + 0xd505, 0x080c, 0xe7e5, 0x1904, 0xd718, 0x080c, 0x32f0, 0x1904, + 0xd718, 0x080c, 0xd8e5, 0x1904, 0xd3ec, 0x6106, 0x080c, 0xd906, + 0x1120, 0x6007, 0x002e, 0x0804, 0xd505, 0x6007, 0x002f, 0x0804, + 0xd505, 0x080c, 0x32f0, 0x1904, 0xd718, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, - 0x00ee, 0x0804, 0xd4fc, 0x080c, 0x56dc, 0xd0e4, 0x0904, 0xd653, + 0x00ee, 0x0804, 0xd50c, 0x080c, 0x56e6, 0xd0e4, 0x0904, 0xd663, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, - 0x080c, 0x6977, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, - 0xb814, 0x9206, 0x0510, 0x080c, 0x6973, 0x15b8, 0x2069, 0x1800, + 0x080c, 0x6985, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, + 0xb814, 0x9206, 0x0510, 0x080c, 0x6981, 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578, 0x7210, 0x080c, - 0xcb38, 0x0590, 0x080c, 0xd7c0, 0x0578, 0x080c, 0xe64b, 0x0560, - 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x90d9, 0x080c, - 0x9687, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, - 0x0150, 0x080c, 0xcb38, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, + 0xcb48, 0x0590, 0x080c, 0xd7d0, 0x0578, 0x080c, 0xe665, 0x0560, + 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x90f8, 0x080c, + 0x96a6, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, + 0x0150, 0x080c, 0xcb48, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, - 0xe599, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, + 0xe5b3, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, - 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x32e5, - 0x1904, 0xd708, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0006, 0x1904, 0xd4fc, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0x56dc, 0xd0e4, 0x0904, 0xd6cb, 0x2069, 0x1800, 0x2071, 0x026c, + 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x32f0, + 0x1904, 0xd718, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, + 0x9086, 0x0006, 0x1904, 0xd50c, 0x00e6, 0x00d6, 0x00c6, 0x080c, + 0x56e6, 0xd0e4, 0x0904, 0xd6db, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xe599, 0x2c10, 0x00ce, - 0x05e8, 0x080c, 0xcb38, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, + 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xe5b3, 0x2c10, 0x00ce, + 0x05e8, 0x080c, 0xcb48, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, 0xc76e, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, - 0x2004, 0x9005, 0x0170, 0x080c, 0xd7c0, 0x0904, 0xd64c, 0x0056, - 0x7510, 0x7614, 0x080c, 0xe664, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x2004, 0x9005, 0x0170, 0x080c, 0xd7d0, 0x0904, 0xd65c, 0x0056, + 0x7510, 0x7614, 0x080c, 0xe67e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, - 0x0001, 0x080c, 0x90d9, 0x080c, 0x9687, 0x0c78, 0x6007, 0x003b, - 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x90d9, - 0x080c, 0x9687, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, - 0x0000, 0x0804, 0xd623, 0x00e6, 0x0026, 0x080c, 0x6939, 0x0550, - 0x080c, 0x68d5, 0x080c, 0xe83d, 0x1518, 0x2071, 0x1800, 0x70dc, + 0x0001, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0c78, 0x6007, 0x003b, + 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x90f8, + 0x080c, 0x96a6, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, + 0x0000, 0x0804, 0xd633, 0x00e6, 0x0026, 0x080c, 0x6947, 0x0550, + 0x080c, 0x68e3, 0x080c, 0xe857, 0x1518, 0x2071, 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, 0x0100, 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, 0x7280, 0x9205, 0x7082, - 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6977, 0x0120, 0x2011, - 0x19ff, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2f98, 0x0010, - 0x080c, 0xe86f, 0x002e, 0x00ee, 0x080c, 0xae71, 0x0804, 0xd4fb, - 0x080c, 0xae71, 0x0005, 0x2600, 0x0002, 0xd71f, 0xd750, 0xd761, - 0xd71f, 0xd71f, 0xd721, 0xd772, 0xd71f, 0xd71f, 0xd71f, 0xd73e, - 0xd71f, 0xd71f, 0xd71f, 0xd77d, 0xd78a, 0xd7bb, 0xd71f, 0x080c, - 0x0dd5, 0x080c, 0xe7cb, 0x1d20, 0x080c, 0x32e5, 0x1d08, 0x080c, - 0xd8d5, 0x1148, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, - 0x080c, 0x9121, 0x0005, 0x080c, 0x31c1, 0x080c, 0xd25f, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x9121, 0x0005, 0x080c, 0xe7cb, - 0x1938, 0x080c, 0x32e5, 0x1920, 0x080c, 0xd8d5, 0x1d60, 0x703c, - 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9121, 0x0005, - 0x080c, 0x32e5, 0x1904, 0xd708, 0x2009, 0x0041, 0x080c, 0xe878, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, 0x9687, - 0x0005, 0x080c, 0x32e5, 0x1904, 0xd708, 0x2009, 0x0042, 0x080c, - 0xe878, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, - 0x9687, 0x0005, 0x080c, 0x32e5, 0x1904, 0xd708, 0x2009, 0x0046, - 0x080c, 0xe878, 0x080c, 0xae71, 0x0005, 0x080c, 0xd7dd, 0x0904, - 0xd708, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x9121, 0x080c, - 0x9687, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, + 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6985, 0x0120, 0x2011, + 0x19ff, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2fa3, 0x0010, + 0x080c, 0xe889, 0x002e, 0x00ee, 0x080c, 0xae5f, 0x0804, 0xd50b, + 0x080c, 0xae5f, 0x0005, 0x2600, 0x0002, 0xd72f, 0xd760, 0xd771, + 0xd72f, 0xd72f, 0xd731, 0xd782, 0xd72f, 0xd72f, 0xd72f, 0xd74e, + 0xd72f, 0xd72f, 0xd72f, 0xd78d, 0xd79a, 0xd7cb, 0xd72f, 0x080c, + 0x0dd5, 0x080c, 0xe7e5, 0x1d20, 0x080c, 0x32f0, 0x1d08, 0x080c, + 0xd8e5, 0x1148, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, + 0x080c, 0x9140, 0x0005, 0x080c, 0x31cc, 0x080c, 0xd26f, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x9140, 0x0005, 0x080c, 0xe7e5, + 0x1938, 0x080c, 0x32f0, 0x1920, 0x080c, 0xd8e5, 0x1d60, 0x703c, + 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9140, 0x0005, + 0x080c, 0x32f0, 0x1904, 0xd718, 0x2009, 0x0041, 0x080c, 0xe892, + 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, 0x96a6, + 0x0005, 0x080c, 0x32f0, 0x1904, 0xd718, 0x2009, 0x0042, 0x080c, + 0xe892, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x0005, 0x080c, 0x32f0, 0x1904, 0xd718, 0x2009, 0x0046, + 0x080c, 0xe892, 0x080c, 0xae5f, 0x0005, 0x080c, 0xd7ed, 0x0904, + 0xd718, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x9140, 0x080c, + 0x96a6, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x19bc, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19bd, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xbe30, - 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9121, - 0x080c, 0x9687, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, + 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xbe2d, + 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9140, + 0x080c, 0x96a6, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, 0x2058, 0xb8cc, 0xd084, 0x0150, 0x7128, 0x6048, 0x9106, 0x1120, 0x712c, 0x6044, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, @@ -6714,831 +6716,833 @@ unsigned short risc_code01[] = { 0x0048, 0x2071, 0x1800, 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, 0x0fb1, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, - 0xffff, 0x11a8, 0x080c, 0x23ad, 0x2099, 0x026c, 0x2001, 0x0014, + 0xffff, 0x11a8, 0x080c, 0x23b8, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, - 0x22a8, 0x8108, 0x080c, 0x23ad, 0x2099, 0x0260, 0x0ca8, 0x080c, - 0x23ad, 0x2061, 0x199f, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, + 0x22a8, 0x8108, 0x080c, 0x23b8, 0x2099, 0x0260, 0x0ca8, 0x080c, + 0x23b8, 0x2061, 0x199f, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, - 0x080c, 0x23ad, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x199f, 0x2019, + 0x080c, 0x23b8, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x199f, 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x23c5, 0x20a1, + 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x23d0, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, - 0x23c5, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x23c5, 0x2061, 0x19a2, + 0x23d0, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x23d0, 0x2061, 0x19a2, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, - 0x23c5, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a2, 0x2019, 0x0260, + 0x23d0, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a2, 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, - 0x0005, 0x00d6, 0x080c, 0xd96d, 0x00de, 0x0005, 0x00d6, 0x080c, - 0xd97a, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, + 0x0005, 0x00d6, 0x080c, 0xd97d, 0x00de, 0x0005, 0x00d6, 0x080c, + 0xd98a, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, - 0xe998, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, - 0x00ff, 0x6824, 0x080c, 0x2840, 0x1148, 0x2001, 0x0001, 0x080c, - 0xe998, 0x2110, 0x900e, 0x080c, 0x320a, 0x0018, 0x9085, 0x0001, - 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xaebf, + 0xe9b2, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, + 0x00ff, 0x6824, 0x080c, 0x284b, 0x1148, 0x2001, 0x0001, 0x080c, + 0xe9b2, 0x2110, 0x900e, 0x080c, 0x3215, 0x0018, 0x9085, 0x0001, + 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xaead, 0x05a8, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2840, 0x1578, 0x080c, 0x65a7, 0x1560, 0xbe12, - 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xe7cb, - 0x11d8, 0x080c, 0x32e5, 0x11c0, 0x080c, 0xd8d5, 0x0510, 0x2001, - 0x0007, 0x080c, 0x6558, 0x2001, 0x0007, 0x080c, 0x6584, 0x6017, + 0x220c, 0x080c, 0x284b, 0x1578, 0x080c, 0x65b5, 0x1560, 0xbe12, + 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xe7e5, + 0x11d8, 0x080c, 0x32f0, 0x11c0, 0x080c, 0xd8e5, 0x0510, 0x2001, + 0x0007, 0x080c, 0x6566, 0x2001, 0x0007, 0x080c, 0x6592, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9121, 0x080c, 0x9687, 0x0010, 0x080c, 0xae71, 0x9085, 0x0001, - 0x00ce, 0x00be, 0x0005, 0x080c, 0xae71, 0x00ce, 0x002e, 0x001e, - 0x0ca8, 0x080c, 0xae71, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, + 0x9140, 0x080c, 0x96a6, 0x0010, 0x080c, 0xae5f, 0x9085, 0x0001, + 0x00ce, 0x00be, 0x0005, 0x080c, 0xae5f, 0x00ce, 0x002e, 0x001e, + 0x0ca8, 0x080c, 0xae5f, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0dd5, 0x91b6, 0x0013, 0x1130, 0x2008, - 0x91b2, 0x0040, 0x1a04, 0xdac4, 0x0092, 0x91b6, 0x0027, 0x0120, - 0x91b6, 0x0014, 0x190c, 0x0dd5, 0x2001, 0x0007, 0x080c, 0x6584, - 0x080c, 0x957b, 0x080c, 0xaea2, 0x080c, 0x9687, 0x0005, 0xd9f7, - 0xd9f9, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f9, 0xda08, 0xdabd, 0xda5a, - 0xdabd, 0xda6e, 0xdabd, 0xda08, 0xdabd, 0xdab5, 0xdabd, 0xdab5, - 0xdabd, 0xdabd, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, - 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f9, 0xd9f7, 0xdabd, - 0xd9f7, 0xd9f7, 0xdabd, 0xd9f7, 0xdaba, 0xdabd, 0xd9f7, 0xd9f7, - 0xd9f7, 0xd9f7, 0xdabd, 0xdabd, 0xd9f7, 0xdabd, 0xdabd, 0xd9f7, - 0xda03, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0xdab9, 0xdabd, 0xd9f7, - 0xd9f7, 0xdabd, 0xdabd, 0xd9f7, 0xd9f7, 0xd9f7, 0xd9f7, 0x080c, - 0x0dd5, 0x080c, 0x957b, 0x080c, 0xd262, 0x6003, 0x0002, 0x080c, - 0x9687, 0x0804, 0xdac3, 0x9006, 0x080c, 0x6544, 0x0804, 0xdabd, - 0x080c, 0x6973, 0x1904, 0xdabd, 0x9006, 0x080c, 0x6544, 0x6010, + 0x91b2, 0x0040, 0x1a04, 0xdad4, 0x0092, 0x91b6, 0x0027, 0x0120, + 0x91b6, 0x0014, 0x190c, 0x0dd5, 0x2001, 0x0007, 0x080c, 0x6592, + 0x080c, 0x959a, 0x080c, 0xae90, 0x080c, 0x96a6, 0x0005, 0xda07, + 0xda09, 0xda07, 0xda07, 0xda07, 0xda09, 0xda18, 0xdacd, 0xda6a, + 0xdacd, 0xda7e, 0xdacd, 0xda18, 0xdacd, 0xdac5, 0xdacd, 0xdac5, + 0xdacd, 0xdacd, 0xda07, 0xda07, 0xda07, 0xda07, 0xda07, 0xda07, + 0xda07, 0xda07, 0xda07, 0xda07, 0xda07, 0xda09, 0xda07, 0xdacd, + 0xda07, 0xda07, 0xdacd, 0xda07, 0xdaca, 0xdacd, 0xda07, 0xda07, + 0xda07, 0xda07, 0xdacd, 0xdacd, 0xda07, 0xdacd, 0xdacd, 0xda07, + 0xda13, 0xda07, 0xda07, 0xda07, 0xda07, 0xdac9, 0xdacd, 0xda07, + 0xda07, 0xdacd, 0xdacd, 0xda07, 0xda07, 0xda07, 0xda07, 0x080c, + 0x0dd5, 0x080c, 0x959a, 0x080c, 0xd272, 0x6003, 0x0002, 0x080c, + 0x96a6, 0x0804, 0xdad3, 0x9006, 0x080c, 0x6552, 0x0804, 0xdacd, + 0x080c, 0x6981, 0x1904, 0xdacd, 0x9006, 0x080c, 0x6552, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0428, 0x6010, 0x2058, 0xb8c0, - 0x9005, 0x1178, 0x080c, 0xd24a, 0x1904, 0xdabd, 0x0036, 0x0046, - 0xbba0, 0x2021, 0x0007, 0x080c, 0x4ccb, 0x004e, 0x003e, 0x0804, - 0xdabd, 0x080c, 0x3316, 0x1904, 0xdabd, 0x2001, 0x1800, 0x2004, + 0x9005, 0x1178, 0x080c, 0xd25a, 0x1904, 0xdacd, 0x0036, 0x0046, + 0xbba0, 0x2021, 0x0007, 0x080c, 0x4cd5, 0x004e, 0x003e, 0x0804, + 0xdacd, 0x080c, 0x3321, 0x1904, 0xdacd, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, - 0x78aa, 0x00fe, 0x2001, 0x0002, 0x080c, 0x6558, 0x080c, 0x957b, - 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9121, - 0x080c, 0x9687, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x84ea, - 0x0804, 0xdac3, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0006, 0x0904, 0xdabd, 0x9686, 0x0004, 0x0904, 0xdabd, - 0x080c, 0x8ca4, 0x2001, 0x0004, 0x0804, 0xdabb, 0x2001, 0x1800, + 0x78aa, 0x00fe, 0x2001, 0x0002, 0x080c, 0x6566, 0x080c, 0x959a, + 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9140, + 0x080c, 0x96a6, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x8507, + 0x0804, 0xdad3, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x0904, 0xdacd, 0x9686, 0x0004, 0x0904, 0xdacd, + 0x080c, 0x8cc3, 0x2001, 0x0004, 0x0804, 0xdacb, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, - 0xbba0, 0x2021, 0x0006, 0x080c, 0x4ccb, 0x004e, 0x003e, 0x2001, - 0x0006, 0x080c, 0xdae1, 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, + 0xbba0, 0x2021, 0x0006, 0x080c, 0x4cd5, 0x004e, 0x003e, 0x2001, + 0x0006, 0x080c, 0xdaf1, 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, 0x0006, - 0x080c, 0x6584, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, 0x2001, - 0x0006, 0x080c, 0x6558, 0x080c, 0x6973, 0x11f8, 0x2001, 0x1837, + 0x080c, 0x6592, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, 0x2001, + 0x0006, 0x080c, 0x6566, 0x080c, 0x6981, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, - 0x0804, 0xda42, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, - 0x0020, 0x0018, 0x0010, 0x080c, 0x6584, 0x080c, 0x957b, 0x080c, - 0xae71, 0x080c, 0x9687, 0x0005, 0x2600, 0x0002, 0xdad8, 0xdad8, - 0xdad8, 0xdad8, 0xdad8, 0xdada, 0xdad8, 0xdada, 0xdad8, 0xdad8, - 0xdada, 0xdad8, 0xdad8, 0xdad8, 0xdada, 0xdada, 0xdada, 0xdada, - 0x080c, 0x0dd5, 0x080c, 0x957b, 0x080c, 0xae71, 0x080c, 0x9687, + 0x0804, 0xda52, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, + 0x0020, 0x0018, 0x0010, 0x080c, 0x6592, 0x080c, 0x959a, 0x080c, + 0xae5f, 0x080c, 0x96a6, 0x0005, 0x2600, 0x0002, 0xdae8, 0xdae8, + 0xdae8, 0xdae8, 0xdae8, 0xdaea, 0xdae8, 0xdaea, 0xdae8, 0xdae8, + 0xdaea, 0xdae8, 0xdae8, 0xdae8, 0xdaea, 0xdaea, 0xdaea, 0xdaea, + 0x080c, 0x0dd5, 0x080c, 0x959a, 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, - 0x0138, 0x080c, 0x6558, 0x9006, 0x080c, 0x6544, 0x080c, 0x31ea, + 0x0138, 0x080c, 0x6566, 0x9006, 0x080c, 0x6552, 0x080c, 0x31f5, 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0dd5, 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0dd5, 0x006b, - 0x0005, 0xb90d, 0xb90d, 0xb90d, 0xb90d, 0xdb76, 0xb90d, 0xdb60, - 0xdb21, 0xb90d, 0xb90d, 0xb90d, 0xb90d, 0xb90d, 0xb90d, 0xb90d, - 0xb90d, 0xdb76, 0xb90d, 0xdb60, 0xdb67, 0xb90d, 0xb90d, 0xb90d, - 0xb90d, 0x00f6, 0x080c, 0x6973, 0x11d8, 0x080c, 0xd24a, 0x11c0, + 0x0005, 0xb90a, 0xb90a, 0xb90a, 0xb90a, 0xdb86, 0xb90a, 0xdb70, + 0xdb31, 0xb90a, 0xb90a, 0xb90a, 0xb90a, 0xb90a, 0xb90a, 0xb90a, + 0xb90a, 0xdb86, 0xb90a, 0xdb70, 0xdb77, 0xb90a, 0xb90a, 0xb90a, + 0xb90a, 0x00f6, 0x080c, 0x6981, 0x11d8, 0x080c, 0xd25a, 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb8c0, 0x9005, 0x0190, 0x9006, 0x080c, - 0x6544, 0x2001, 0x0002, 0x080c, 0x6558, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9121, 0x080c, 0x9687, 0x00f0, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2840, 0x11b0, - 0x080c, 0x6608, 0x0118, 0x080c, 0xae71, 0x0080, 0xb810, 0x0006, - 0xb814, 0x0006, 0xb8c0, 0x0006, 0x080c, 0x603d, 0x000e, 0xb8c2, - 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0xae71, 0x00fe, 0x0005, - 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0xae71, 0x0005, 0x080c, - 0xbc98, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9121, - 0x080c, 0x9687, 0x0010, 0x080c, 0xae71, 0x0005, 0x0804, 0xae71, - 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dd5, 0x080c, 0x957b, 0x080c, - 0xaea2, 0x080c, 0x9687, 0x0005, 0x9182, 0x0040, 0x0002, 0xdb9a, - 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9c, 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, - 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, 0xdb9a, - 0xdb9a, 0xdb9a, 0x080c, 0x0dd5, 0x0096, 0x00b6, 0x00d6, 0x00e6, - 0x00f6, 0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11a8, - 0x6106, 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xdc02, - 0x080c, 0xe98c, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, - 0x2011, 0x0200, 0x080c, 0x86c6, 0x0020, 0x9026, 0x080c, 0xe810, - 0x0c38, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0x6003, 0x0007, 0xa867, - 0x010d, 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, - 0xa8e2, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, - 0xa87f, 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x6c86, - 0x001e, 0x080c, 0xe98c, 0x1904, 0xdc62, 0x9486, 0x2000, 0x1130, - 0x2019, 0x0017, 0x080c, 0xe543, 0x0804, 0xdc62, 0x9486, 0x0200, - 0x1120, 0x080c, 0xe4df, 0x0804, 0xdc62, 0x9486, 0x0400, 0x0120, - 0x9486, 0x1000, 0x1904, 0xdc62, 0x2019, 0x0002, 0x080c, 0xe4fa, - 0x0804, 0xdc62, 0x2069, 0x1a70, 0x6a00, 0xd284, 0x0904, 0xdccc, - 0x9284, 0x0300, 0x1904, 0xdcc5, 0x6804, 0x9005, 0x0904, 0xdcad, - 0x2d78, 0x6003, 0x0007, 0x080c, 0x1018, 0x0904, 0xdc6e, 0x7800, - 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, - 0x180f, 0x2004, 0xd084, 0x1904, 0xdcd0, 0x9006, 0xa802, 0xa867, - 0x0116, 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, - 0xb8a0, 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, - 0xb930, 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, - 0x0003, 0x9080, 0xdc6a, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, - 0x0270, 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, - 0x20e1, 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, - 0x0000, 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, - 0x080c, 0x6c86, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, - 0x009e, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, - 0x2004, 0xd084, 0x0120, 0x080c, 0x0fff, 0x1904, 0xdc17, 0x6017, - 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x90d9, 0x080c, - 0x9687, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, - 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, - 0xf700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, - 0x080c, 0x90d9, 0x080c, 0x9687, 0x0828, 0x6868, 0x602e, 0x686c, - 0x6032, 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x0804, 0xdc62, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b14, 0x6017, 0xf300, - 0x0010, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x0804, 0xdc62, 0x6017, 0xf500, 0x0c98, - 0x6017, 0xf600, 0x0804, 0xdc82, 0x6017, 0xf200, 0x0804, 0xdc82, - 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, - 0x7044, 0x9084, 0x0003, 0x9080, 0xdc6a, 0x2005, 0xa87e, 0x2928, - 0x6010, 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, - 0xb830, 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, - 0x2104, 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, - 0x2214, 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0dd5, - 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0029, 0x20a0, 0x2011, 0xdd4c, 0x2041, 0x0001, 0x223d, - 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, - 0x0530, 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, - 0x2098, 0x0c68, 0x2950, 0x080c, 0x1018, 0x0170, 0x2900, 0xb002, - 0xa867, 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, - 0x080c, 0x1031, 0x0cc8, 0x080c, 0x1031, 0x0804, 0xdc6e, 0x2548, - 0x8847, 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, - 0x080c, 0xe572, 0x0804, 0xdc62, 0x8010, 0x0004, 0x801a, 0x0006, - 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0054, 0x1a0c, 0x0dd5, 0x9082, 0x0040, 0x0a0c, - 0x0dd5, 0x2008, 0x0804, 0xddfd, 0x9186, 0x0051, 0x0108, 0x00c0, - 0x2001, 0x0109, 0x2004, 0xd084, 0x0904, 0xddae, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x8fbe, 0x002e, 0x001e, - 0x000e, 0x012e, 0x6000, 0x9086, 0x0002, 0x1580, 0x0804, 0xde45, - 0x9186, 0x0027, 0x0530, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, - 0x0500, 0x190c, 0x0dd5, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, - 0x00c6, 0x0126, 0x2091, 0x2800, 0x00c6, 0x2061, 0x0100, 0x0006, - 0x0016, 0x0026, 0x080c, 0x8fbe, 0x002e, 0x001e, 0x000e, 0x00ce, - 0x012e, 0x00ce, 0x6000, 0x9086, 0x0004, 0x190c, 0x0dd5, 0x0804, - 0xdf26, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xaf07, - 0x0005, 0xddc4, 0xddc6, 0xddc6, 0xdded, 0xddc4, 0xddc4, 0xddc4, - 0xddc4, 0xddc4, 0xddc4, 0xddc4, 0xddc4, 0xddc4, 0xddc4, 0xddc4, - 0xddc4, 0xddc4, 0xddc4, 0xddc4, 0x080c, 0x0dd5, 0x080c, 0x957b, - 0x080c, 0x9687, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, - 0xcb4a, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xe572, 0x6017, - 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1986, 0x2004, 0x601a, - 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, 0x957b, - 0x080c, 0x9687, 0x080c, 0xcb4a, 0x0120, 0x6014, 0x2048, 0x080c, - 0x1031, 0x080c, 0xaea2, 0x009e, 0x0005, 0x0002, 0xde11, 0xde28, - 0xde13, 0xde3f, 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, - 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, 0xde11, - 0xde11, 0x080c, 0x0dd5, 0x0096, 0x080c, 0x957b, 0x6014, 0x2048, - 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0xaeec, 0x0010, 0x6003, 0x0004, 0x080c, 0x9687, 0x009e, 0x0005, - 0x080c, 0x957b, 0x080c, 0xcb4a, 0x0138, 0x6114, 0x0096, 0x2148, - 0xa97c, 0x009e, 0xd1ec, 0x1138, 0x080c, 0x869b, 0x080c, 0xae71, - 0x080c, 0x9687, 0x0005, 0x080c, 0xe7d4, 0x0db0, 0x0cc8, 0x080c, - 0x957b, 0x2009, 0x0041, 0x0804, 0xdfae, 0x9182, 0x0040, 0x0002, - 0xde5b, 0xde5d, 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, - 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, 0xde5b, - 0xde5b, 0xde5e, 0xde5b, 0x080c, 0x0dd5, 0x0005, 0x00d6, 0x080c, - 0x869b, 0x00de, 0x080c, 0xe82c, 0x080c, 0xae71, 0x0005, 0x9182, - 0x0040, 0x0002, 0xde7d, 0xde7d, 0xde7d, 0xde7d, 0xde7d, 0xde7d, - 0xde7d, 0xde7d, 0xde7d, 0xde7f, 0xdeee, 0xde7d, 0xde7d, 0xde7d, - 0xde7d, 0xdeee, 0xde7d, 0xde7d, 0xde7d, 0x080c, 0x0dd5, 0x2001, - 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, - 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xdeee, 0x2009, 0x180c, - 0x2104, 0xd0d4, 0x0904, 0xdeee, 0xc0d4, 0x200a, 0x2009, 0x0105, - 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1867, - 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x9637, 0x6014, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, - 0x0002, 0x0508, 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, - 0x97b5, 0x2009, 0x0041, 0x009e, 0x0804, 0xdfae, 0x080c, 0x97b5, - 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x869b, 0x009e, 0x0005, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, - 0x2004, 0x603a, 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0xd1cc, 0x0110, 0x080c, 0x2c54, 0x080c, 0x97b5, 0x6014, 0x2048, - 0xa97c, 0xd1ec, 0x1130, 0x080c, 0x869b, 0x080c, 0xae71, 0x009e, - 0x0005, 0x080c, 0xe7d4, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, - 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9637, 0x080c, 0x97b5, - 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, - 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, - 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xe572, 0x6018, - 0x9005, 0x1128, 0x2001, 0x1986, 0x2004, 0x8003, 0x601a, 0x6017, - 0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, - 0x0002, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, - 0xdf3d, 0xdf3f, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, - 0xdf3d, 0xdf3d, 0xdf3d, 0xdf3d, 0xdf8a, 0x080c, 0x0dd5, 0x6014, - 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, - 0x2009, 0x0041, 0x009e, 0x0804, 0xdfae, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x869b, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, - 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, - 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, - 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, - 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, - 0x0006, 0x00e9, 0x080c, 0x869d, 0x009e, 0x0005, 0x6003, 0x0002, - 0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x15e7, 0x1904, - 0xdf3f, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, - 0x9105, 0x1120, 0x080c, 0x15e7, 0x1904, 0xdf3f, 0x0005, 0xd2fc, - 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, - 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, - 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, - 0x0dd5, 0x6024, 0xd0dc, 0x090c, 0x0dd5, 0x0005, 0xdfd1, 0xdfdd, - 0xdfe9, 0xdff5, 0xdfd1, 0xdfd1, 0xdfd1, 0xdfd1, 0xdfd8, 0xdfd3, - 0xdfd3, 0xdfd1, 0xdfd1, 0xdfd1, 0xdfd1, 0xdfd3, 0xdfd1, 0xdfd3, - 0xdfd1, 0x080c, 0x0dd5, 0x6024, 0xd0dc, 0x090c, 0x0dd5, 0x0005, - 0x6014, 0x9005, 0x190c, 0x0dd5, 0x0005, 0x6003, 0x0001, 0x6106, - 0x080c, 0x90d9, 0x0126, 0x2091, 0x8000, 0x080c, 0x9687, 0x012e, - 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x90d9, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9687, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x080c, 0x1baf, 0x0126, 0x2091, 0x8000, 0x080c, 0x913e, - 0x080c, 0x97b5, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, - 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, - 0xe020, 0xe022, 0xe034, 0xe04e, 0xe020, 0xe020, 0xe020, 0xe020, - 0xe020, 0xe020, 0xe020, 0xe020, 0xe020, 0xe020, 0xe020, 0xe020, - 0x080c, 0x0dd5, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x01f8, 0x909c, - 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, - 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, - 0x6106, 0x080c, 0x90d9, 0x080c, 0x9687, 0x00e0, 0x901e, 0x6316, - 0x631a, 0x2019, 0x0004, 0x080c, 0xe572, 0x00a0, 0x6014, 0x2048, - 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, - 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1baf, 0x080c, 0x913e, - 0x080c, 0x97b5, 0x0005, 0x080c, 0x957b, 0x6114, 0x81ff, 0x0158, - 0x0096, 0x2148, 0x080c, 0xe929, 0x0036, 0x2019, 0x0029, 0x080c, - 0xe572, 0x003e, 0x009e, 0x080c, 0xaea2, 0x080c, 0x9687, 0x0005, - 0x080c, 0x9637, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, - 0xe929, 0x0036, 0x2019, 0x0029, 0x080c, 0xe572, 0x003e, 0x009e, - 0x080c, 0xaea2, 0x080c, 0x97b5, 0x0005, 0x9182, 0x0085, 0x0002, - 0xe09f, 0xe09d, 0xe09d, 0xe0ab, 0xe09d, 0xe09d, 0xe09d, 0xe09d, - 0xe09d, 0xe09d, 0xe09d, 0xe09d, 0xe09d, 0x080c, 0x0dd5, 0x6003, - 0x000b, 0x6106, 0x080c, 0x90d9, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9687, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xe7cb, 0x0118, - 0x080c, 0xae71, 0x0450, 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, - 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, - 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xb192, 0x7220, 0x080c, - 0xe418, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, - 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x080c, 0x97b5, 0x00ee, 0x002e, 0x0005, - 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dd5, - 0x908a, 0x0092, 0x1a0c, 0x0dd5, 0x9082, 0x0085, 0x00a2, 0x9186, - 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0xaf07, 0x0050, - 0x2001, 0x0007, 0x080c, 0x6584, 0x080c, 0x957b, 0x080c, 0xaea2, - 0x080c, 0x9687, 0x0005, 0xe110, 0xe112, 0xe112, 0xe110, 0xe110, - 0xe110, 0xe110, 0xe110, 0xe110, 0xe110, 0xe110, 0xe110, 0xe110, - 0x080c, 0x0dd5, 0x080c, 0x957b, 0x080c, 0xaea2, 0x080c, 0x9687, - 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0dd5, 0x9182, 0x0092, 0x1a0c, - 0x0dd5, 0x9182, 0x0085, 0x0002, 0xe131, 0xe131, 0xe131, 0xe133, - 0xe131, 0xe131, 0xe131, 0xe131, 0xe131, 0xe131, 0xe131, 0xe131, - 0xe131, 0x080c, 0x0dd5, 0x0005, 0x9186, 0x0013, 0x0148, 0x9186, - 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xaf07, 0x0030, - 0x080c, 0x957b, 0x080c, 0xaea2, 0x080c, 0x9687, 0x0005, 0x0036, - 0x080c, 0xe82c, 0x6043, 0x0000, 0x2019, 0x000b, 0x0031, 0x6023, - 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, - 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0xa69d, 0x009e, - 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0xa748, 0x007e, 0x1520, - 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, 0x01e0, - 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xe82c, 0x080c, 0xd262, - 0x080c, 0x1a60, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xcb4a, - 0x0110, 0x080c, 0xe572, 0x009e, 0x6017, 0x0000, 0x080c, 0xe82c, - 0x6023, 0x0007, 0x080c, 0xd262, 0x003e, 0x012e, 0x0005, 0x00f6, - 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, - 0x080c, 0x2840, 0x15c8, 0x0016, 0x00c6, 0x080c, 0x6608, 0x1590, - 0x001e, 0x00c6, 0x2160, 0x080c, 0xd25f, 0x00ce, 0x002e, 0x0026, - 0x0016, 0x2019, 0x0029, 0x080c, 0xa80e, 0x080c, 0x927e, 0x0076, - 0x903e, 0x080c, 0x9151, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, - 0xe30c, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, - 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, 0x327f, - 0x002e, 0xbcc0, 0x001e, 0x080c, 0x603d, 0xbe12, 0xbd16, 0xbcc2, - 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, - 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, - 0x2104, 0x9086, 0x0074, 0x1904, 0xe233, 0x2069, 0x0260, 0x6944, - 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, 0xe230, - 0x2001, 0x197b, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb8c0, - 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, - 0x0648, 0x080c, 0xe991, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, - 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, - 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, - 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, - 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, - 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, - 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, - 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, - 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, - 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, - 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, - 0x6617, 0x0804, 0xe29b, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xbe30, 0x009e, 0x15a8, 0x2011, - 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, - 0xbe30, 0x009e, 0x1548, 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, - 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, - 0xe5cf, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, 0x927e, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9151, 0x2c08, 0x080c, 0xe30c, - 0x007e, 0x2001, 0x0007, 0x080c, 0x6584, 0x2001, 0x0007, 0x080c, - 0x6558, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, - 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, - 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, - 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, - 0x7834, 0x080c, 0x2840, 0x11d0, 0x080c, 0x6608, 0x11b8, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xbe30, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xbe30, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2840, 0x11d0, 0x080c, 0x6608, 0x11b8, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbe30, - 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xbe30, 0x009e, 0x015e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2029, 0x19ef, 0x252c, 0x2021, 0x19f5, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, - 0x1aaf, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xe3a9, 0x0018, - 0x9606, 0x0904, 0xe3a9, 0x080c, 0x896a, 0x0904, 0xe3a0, 0x2100, - 0x9c06, 0x0904, 0xe3a0, 0x080c, 0xe610, 0x1904, 0xe3a0, 0x080c, - 0xe9ae, 0x0904, 0xe3a0, 0x080c, 0xe600, 0x0904, 0xe3a0, 0x6720, - 0x9786, 0x0001, 0x1148, 0x080c, 0x3316, 0x0904, 0xe3e8, 0x6004, - 0x9086, 0x0000, 0x1904, 0xe3e8, 0x9786, 0x0004, 0x0904, 0xe3e8, - 0x9786, 0x0007, 0x0904, 0xe3a0, 0x2500, 0x9c06, 0x0904, 0xe3a0, - 0x2400, 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, 0x9906, 0x15c0, - 0x0096, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a60, - 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xcd50, 0x1130, 0x080c, - 0xb824, 0x009e, 0x080c, 0xaea2, 0x0418, 0x6014, 0x2048, 0x080c, - 0xcb4a, 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, 0x0103, 0xa87c, - 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fb1, 0x009e, - 0xab7a, 0xa877, 0x0000, 0x080c, 0xe929, 0x0016, 0x080c, 0xce3e, - 0x080c, 0x6c7a, 0x001e, 0x080c, 0xcd33, 0x009e, 0x080c, 0xaea2, - 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, - 0xe320, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, - 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, - 0x0128, 0x080c, 0xe929, 0x080c, 0xe572, 0x08f8, 0x009e, 0x0c00, - 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, - 0x9086, 0x0003, 0x11a0, 0x080c, 0x9637, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcb4a, 0x0118, 0x6010, 0x080c, 0x6c86, 0x009e, 0x00c6, - 0x080c, 0xae71, 0x00ce, 0x0036, 0x080c, 0x97b5, 0x003e, 0x009e, - 0x0804, 0xe3a0, 0x9786, 0x000a, 0x0904, 0xe387, 0x0804, 0xe385, - 0x81ff, 0x0904, 0xe3a0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, - 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904, 0xe3a0, - 0x6000, 0x9086, 0x0002, 0x1904, 0xe3a0, 0x080c, 0xcd3f, 0x0138, - 0x080c, 0xcd50, 0x1904, 0xe3a0, 0x080c, 0xb824, 0x0038, 0x080c, - 0x31ea, 0x080c, 0xcd50, 0x1110, 0x080c, 0xb824, 0x080c, 0xaea2, - 0x0804, 0xe3a0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, - 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, 0xe599, - 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, - 0x0005, 0xe437, 0xe437, 0xe437, 0xe437, 0xe437, 0xe437, 0xe439, - 0xe437, 0xe437, 0xe437, 0xe437, 0xaea2, 0xaea2, 0xe437, 0x9006, - 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, - 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xe5cf, 0x001e, 0x004e, - 0x2019, 0x0002, 0x080c, 0xe155, 0x003e, 0x9085, 0x0001, 0x0005, - 0x0096, 0x080c, 0xcb4a, 0x0140, 0x6014, 0x904d, 0x080c, 0xc77b, - 0x687b, 0x0005, 0x080c, 0x6c86, 0x009e, 0x080c, 0xaea2, 0x9085, - 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x6544, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, - 0x080c, 0xbe1c, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, - 0x2091, 0x8000, 0x2740, 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, - 0x0904, 0xe4d2, 0x2071, 0x1800, 0x7654, 0x7074, 0x8001, 0x9602, - 0x1a04, 0xe4d2, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, - 0x080c, 0xe600, 0x0570, 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, - 0x0006, 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, - 0x9b06, 0x11f8, 0x85ff, 0x0118, 0x6054, 0x9106, 0x11d0, 0x0096, - 0x601c, 0xd084, 0x0140, 0x080c, 0xe82c, 0x080c, 0xd262, 0x080c, - 0x1a60, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xcb4a, 0x0120, - 0x0046, 0x080c, 0xe572, 0x004e, 0x009e, 0x080c, 0xaea2, 0x88ff, - 0x1198, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, - 0x0804, 0xe487, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x00b6, - 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, - 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa69d, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa748, 0x080c, 0xe478, 0x005e, 0x007e, - 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, - 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, - 0x6608, 0x1190, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, - 0x0096, 0x904e, 0x080c, 0xa69d, 0x009e, 0x008e, 0x903e, 0x080c, - 0xa748, 0x080c, 0xe478, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xe505, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, - 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, - 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, 0xa69d, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa748, 0x2c20, 0x080c, 0xe478, 0x005e, - 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, - 0x6608, 0x11a0, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xe810, 0x004e, 0x0096, 0x904e, 0x080c, 0xa69d, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa748, 0x080c, 0xe478, 0x003e, 0x001e, - 0x8108, 0x1f04, 0xe54d, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, - 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xcb48, 0x0198, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, - 0xa803, 0x0000, 0xab82, 0x080c, 0x6c86, 0x2f48, 0x0cb0, 0xab82, - 0x080c, 0x6c86, 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, - 0xa803, 0x0000, 0x080c, 0x6c86, 0x2f48, 0x0cb8, 0x080c, 0x6c86, - 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0, 0x9005, 0x1138, - 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, 0x12f8, 0x2100, - 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, 0x6008, 0x9206, - 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, 0x91a0, 0x0004, - 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, - 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, - 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, - 0x0006, 0x080c, 0x0fff, 0x000e, 0x090c, 0x0dd5, 0xaae2, 0xa867, - 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xcb38, 0x2001, 0x0000, - 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, 0xa87a, 0x9186, - 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, - 0x2001, 0x198d, 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6c86, 0x012e, 0x009e, 0x0005, - 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, - 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, - 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, - 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, - 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, - 0x1986, 0x2004, 0x601a, 0x080c, 0x90d9, 0x080c, 0x9687, 0x001e, - 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, - 0x0118, 0x080c, 0xce82, 0x0030, 0x080c, 0xe82c, 0x080c, 0x869b, - 0x080c, 0xae71, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, - 0x0002, 0xe65f, 0xe65f, 0xe65f, 0xe661, 0xe65f, 0xe661, 0xe661, - 0xe65f, 0xe661, 0xe65f, 0xe65f, 0xe65f, 0xe65f, 0xe65f, 0x9006, - 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, - 0x000f, 0x0002, 0xe678, 0xe678, 0xe678, 0xe678, 0xe678, 0xe678, - 0xe685, 0xe678, 0xe678, 0xe678, 0xe678, 0xe678, 0xe678, 0xe678, - 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, - 0x080c, 0x90d9, 0x080c, 0x9687, 0x0005, 0x0096, 0x00c6, 0x2260, - 0x080c, 0xe82c, 0x6043, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, - 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, - 0xe6de, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, - 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, - 0x1904, 0xe755, 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, - 0x190c, 0x0dd5, 0x0804, 0xe755, 0x2048, 0x080c, 0xcb4a, 0x1130, - 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, - 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, - 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xdfae, - 0x0804, 0xe755, 0x2009, 0x0041, 0x0804, 0xe74f, 0x9186, 0x0005, - 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, - 0x0804, 0xe678, 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0dd5, 0x0804, - 0xe699, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x90d9, 0x080c, - 0x9687, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, - 0x0004, 0x1904, 0xe755, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, - 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, - 0x1727, 0x00fe, 0x2009, 0x0042, 0x04d0, 0x0036, 0x080c, 0x0fff, - 0x090c, 0x0dd5, 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, - 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, - 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, - 0x00be, 0x2004, 0x6354, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, - 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6c86, 0x2019, 0x0045, - 0x6008, 0x2068, 0x080c, 0xe155, 0x2d00, 0x600a, 0x6023, 0x0006, - 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, 0x003e, 0x0038, 0x6043, - 0x0000, 0x6003, 0x0007, 0x080c, 0xdfae, 0x00ce, 0x00de, 0x009e, - 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, - 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, 0x957b, 0x0036, 0x0096, - 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, 0xe572, 0x009e, 0x003e, - 0x080c, 0x9687, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xaf07, - 0x0005, 0xe788, 0xe786, 0xe786, 0xe786, 0xe786, 0xe786, 0xe788, - 0xe786, 0xe786, 0xe786, 0xe786, 0xe786, 0xe786, 0x080c, 0x0dd5, - 0x080c, 0x957b, 0x6003, 0x000c, 0x080c, 0x9687, 0x0005, 0x9182, - 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0xaf07, - 0x0005, 0xe7a6, 0xe7a6, 0xe7a6, 0xe7a6, 0xe7a8, 0xe7c8, 0xe7a6, - 0xe7a6, 0xe7a6, 0xe7a6, 0xe7a6, 0xe7a6, 0xe7a6, 0x080c, 0x0dd5, - 0x00d6, 0x2c68, 0x080c, 0xae1b, 0x01b0, 0x6003, 0x0001, 0x6007, - 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, - 0x90d9, 0x080c, 0x9687, 0x2d60, 0x080c, 0xae71, 0x00de, 0x0005, - 0x080c, 0xae71, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, - 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, - 0x2001, 0x1987, 0x2004, 0x6042, 0x2009, 0x1867, 0x210c, 0xd1f4, - 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, - 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, 0x1987, 0x200c, 0x2001, - 0x1985, 0x2004, 0x9100, 0x9080, 0x000a, 0x6042, 0x6010, 0x00b6, - 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, - 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, - 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8bc, 0x2060, 0x8cff, 0x0180, - 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, - 0x869b, 0x080c, 0xae71, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, - 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, - 0xb8bc, 0x2068, 0x9005, 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, - 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, - 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, - 0x9636, 0x1508, 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, - 0x11d0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, - 0x2019, 0x000a, 0x080c, 0xbe30, 0x009e, 0x1168, 0x2011, 0x0274, - 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, - 0xbe30, 0x009e, 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x5fb6, 0x080c, 0x2f98, 0x00ee, 0x0005, - 0x0096, 0x0026, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0xa85c, 0x9080, - 0x001a, 0x20a0, 0x20a9, 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, - 0x9186, 0x0046, 0x1118, 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, - 0x9186, 0x0041, 0x0110, 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, - 0x7240, 0x9294, 0xff00, 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, - 0x1168, 0x7038, 0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, - 0xaa9e, 0x723c, 0x9294, 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, - 0x00ff, 0x7244, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, - 0x00ff, 0xaaa2, 0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, - 0x9e90, 0x001a, 0x2204, 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, - 0xa8aa, 0x8210, 0x2204, 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, - 0xa8b2, 0x8210, 0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, - 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, - 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, - 0x0205, 0x2013, 0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, - 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, - 0x0001, 0x2011, 0x0260, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, - 0x8007, 0xa8c2, 0x9186, 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, - 0x2011, 0x026a, 0x0146, 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, - 0x0008, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, - 0x8007, 0x4004, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, - 0x2011, 0x0205, 0x2013, 0x0000, 0x002e, 0x080c, 0x6c86, 0x009e, - 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, - 0x0108, 0x0011, 0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x19ef, 0x252c, 0x2021, - 0x19f5, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7654, 0x7074, - 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, - 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, - 0xe600, 0x01b8, 0x080c, 0xe610, 0x11a0, 0x6000, 0x9086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x1a60, 0x001e, 0x080c, 0xcd3f, 0x1110, - 0x080c, 0x31ea, 0x080c, 0xcd50, 0x1110, 0x080c, 0xb824, 0x080c, - 0xaea2, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, - 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, - 0x0005, 0x0006, 0x2001, 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, - 0x0006, 0x0036, 0x0046, 0x080c, 0xd24a, 0x0168, 0x2019, 0xffff, - 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0004, 0x080c, 0x4ccb, 0x004e, 0x003e, 0x000e, 0x6004, 0x9086, - 0x0001, 0x1128, 0x080c, 0xa80e, 0x080c, 0xaea2, 0x9006, 0x0005, - 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1cd0, 0x2071, 0x1800, - 0x7454, 0x7074, 0x8001, 0x9402, 0x12b8, 0x2100, 0x9c06, 0x0148, - 0x6000, 0x9086, 0x0000, 0x0128, 0x6010, 0x2058, 0xb8a0, 0x9206, - 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, - 0x0c60, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be, 0x00ce, - 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, - 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, - 0x0118, 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, - 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, - 0x0005, 0x0118, 0x2071, 0xfffe, 0x0089, 0x001e, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, - 0xfff6, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, - 0x2077, 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, - 0x2071, 0xfff4, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff8, - 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x0003, 0x000b, 0x079e, 0x0000, 0xc000, 0x0001, 0x8064, - 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, 0x0008, 0x4407, - 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x580d, 0x000b, 0x79a8, - 0x000b, 0x50ee, 0x000b, 0x4c0a, 0x0003, 0xbac0, 0x0009, 0x008a, - 0x0000, 0x0c0a, 0x000b, 0x15fe, 0x0008, 0x340a, 0x0003, 0xc4c0, - 0x0009, 0x7000, 0x0000, 0xffa0, 0x0001, 0x2000, 0x0000, 0x1668, - 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x0000, 0x0007, 0x4028, - 0x0000, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, 0x0822, - 0x0003, 0x4022, 0x0000, 0x0028, 0x000b, 0x4122, 0x0008, 0x94c0, - 0x0009, 0xff00, 0x0008, 0xffe0, 0x0009, 0x0500, 0x0008, 0x0a93, - 0x000b, 0x4447, 0x0002, 0x0e90, 0x0003, 0x0bfe, 0x0008, 0x11a0, - 0x0001, 0x126e, 0x0003, 0x0ca0, 0x0001, 0x126e, 0x0003, 0x9180, - 0x0001, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4436, 0x000b, 0x808c, - 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, - 0x0000, 0x8066, 0x0000, 0x0411, 0x0000, 0x443e, 0x0003, 0x03fe, - 0x0000, 0x43e0, 0x0001, 0x0e6b, 0x000b, 0xc2c0, 0x0009, 0x00ff, - 0x0008, 0x02e0, 0x0001, 0x0e6b, 0x000b, 0x9180, 0x0001, 0x0005, - 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, - 0x0000, 0x0019, 0x0000, 0x444d, 0x000b, 0x0240, 0x0002, 0x0a68, - 0x0003, 0x00fe, 0x0000, 0x326b, 0x000b, 0x0248, 0x000a, 0x085c, - 0x0003, 0x9180, 0x0001, 0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, - 0x0008, 0x0003, 0x0008, 0x8066, 0x0000, 0x020a, 0x0000, 0x445b, - 0x0003, 0x112a, 0x0000, 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, - 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, 0x0002, 0x0000, 0x1760, - 0x0008, 0x8062, 0x0008, 0x000f, 0x0008, 0x8066, 0x0000, 0x0011, - 0x0008, 0x4468, 0x0003, 0x01fe, 0x0008, 0x42e0, 0x0009, 0x0e5c, - 0x0003, 0x00fe, 0x0000, 0x43e0, 0x0001, 0x0e5c, 0x0003, 0x1734, - 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, - 0x0001, 0x0010, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x447a, 0x0003, 0x808a, - 0x0008, 0x0003, 0x0008, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, - 0x0000, 0x5880, 0x000b, 0x8066, 0x0000, 0x3679, 0x0000, 0x4483, - 0x0003, 0x5884, 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002, 0x088a, - 0x000b, 0x0d00, 0x0000, 0x0092, 0x000c, 0x8054, 0x0008, 0x0011, - 0x0008, 0x8074, 0x0000, 0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, - 0x000b, 0x00c8, 0x000c, 0x000a, 0x000b, 0x00fe, 0x0000, 0x349a, - 0x0003, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, - 0x0000, 0x0231, 0x0008, 0x4499, 0x000b, 0x03fe, 0x0000, 0x04d0, - 0x0001, 0x0cc0, 0x000b, 0x82c0, 0x0001, 0x1f00, 0x0000, 0xffa0, - 0x0001, 0x0400, 0x0000, 0x08af, 0x0003, 0x14c0, 0x000b, 0x01fe, - 0x0008, 0x0580, 0x0009, 0x7f06, 0x0000, 0x02fe, 0x0008, 0xffc0, - 0x0001, 0x00ff, 0x0008, 0x0690, 0x0001, 0x10af, 0x0003, 0x7f08, - 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008, 0x08c0, 0x0003, 0x00fe, - 0x0000, 0x34b6, 0x000b, 0x8072, 0x0000, 0x1010, 0x0008, 0x3944, - 0x0002, 0x08b1, 0x0003, 0x00ba, 0x0003, 0x8072, 0x0000, 0x2020, - 0x0008, 0x3945, 0x000a, 0x08b6, 0x000b, 0x3946, 0x000a, 0x0cc7, - 0x0003, 0x0000, 0x0007, 0x3943, 0x000a, 0x08c7, 0x000b, 0x00ba, - 0x0003, 0x00fe, 0x0000, 0x34c5, 0x0003, 0x8072, 0x0000, 0x1000, - 0x0000, 0x00c7, 0x0003, 0x8072, 0x0000, 0x2000, 0x0000, 0x4000, - 0x000f, 0x1c60, 0x0000, 0x1b62, 0x0000, 0x8066, 0x0000, 0x0231, - 0x0008, 0x44cc, 0x000b, 0x58cd, 0x000b, 0x0140, 0x0008, 0x0242, - 0x0000, 0x1f43, 0x0002, 0x0cdb, 0x000b, 0x0d44, 0x0000, 0x0d46, - 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, 0x030a, 0x0008, 0x040c, - 0x0000, 0x0d06, 0x0000, 0x0d08, 0x0008, 0x00df, 0x0003, 0x0344, - 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, 0x064a, 0x0000, 0x1948, - 0x000a, 0x08e2, 0x0003, 0x0d4a, 0x0008, 0x58e2, 0x0003, 0x3efe, - 0x0008, 0x7f4f, 0x0002, 0x08e9, 0x000b, 0x8000, 0x0000, 0x0001, - 0x0000, 0x0092, 0x000c, 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, - 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, - 0x0003, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x58f2, 0x000b, 0x8054, - 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x0940, 0x0003, 0x3a45, - 0x000a, 0x092f, 0x0003, 0x8072, 0x0000, 0x1000, 0x0000, 0x3945, - 0x000a, 0x08ff, 0x0003, 0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, - 0x000a, 0x7f3c, 0x0000, 0x092a, 0x0003, 0x1d00, 0x0002, 0x7f3a, - 0x0000, 0x0d60, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, - 0x0008, 0x4508, 0x000b, 0x00fe, 0x0000, 0x3527, 0x000b, 0x1c60, + 0x6552, 0x2001, 0x0002, 0x080c, 0x6566, 0x6023, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x9140, 0x080c, 0x96a6, 0x00f0, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x284b, 0x11b0, + 0x080c, 0x6616, 0x0118, 0x080c, 0xae5f, 0x0080, 0xb810, 0x0006, + 0xb814, 0x0006, 0xb8c0, 0x0006, 0x080c, 0x6047, 0x000e, 0xb8c2, + 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0xae5f, 0x00fe, 0x0005, + 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0xae5f, 0x0005, 0x080c, + 0xbc95, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9140, + 0x080c, 0x96a6, 0x0010, 0x080c, 0xae5f, 0x0005, 0x0804, 0xae5f, + 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dd5, 0x080c, 0x959a, 0x080c, + 0xae90, 0x080c, 0x96a6, 0x0005, 0x9182, 0x0040, 0x0002, 0xdbab, + 0xdbab, 0xdbab, 0xdbab, 0xdbad, 0xdbab, 0xdbab, 0xdbab, 0xdbab, + 0xdbab, 0xdbab, 0xdbab, 0xdbab, 0xdbab, 0xdbab, 0xdbab, 0xdbab, + 0xdbab, 0xdbab, 0xdbab, 0x080c, 0x0dd5, 0x0096, 0x00b6, 0x00d6, + 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, + 0x11a8, 0x6106, 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, + 0xdc13, 0x080c, 0xe9a6, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, + 0x0001, 0x2011, 0x0200, 0x080c, 0x86e3, 0x0020, 0x9026, 0x080c, + 0xe82a, 0x0c38, 0x080c, 0x0fff, 0x090c, 0x0dd5, 0x6003, 0x0007, + 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, + 0x6008, 0xa8e2, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, + 0xa876, 0xa87f, 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, + 0x6c94, 0x001e, 0x080c, 0xe9a6, 0x1904, 0xdc73, 0x9486, 0x2000, + 0x1130, 0x2019, 0x0017, 0x080c, 0xe55d, 0x0804, 0xdc73, 0x9486, + 0x0200, 0x1120, 0x080c, 0xe4f9, 0x0804, 0xdc73, 0x9486, 0x0400, + 0x0120, 0x9486, 0x1000, 0x1904, 0xdc73, 0x2019, 0x0002, 0x080c, + 0xe514, 0x0804, 0xdc73, 0x2069, 0x1a70, 0x6a00, 0xd284, 0x0904, + 0xdcdd, 0x9284, 0x0300, 0x1904, 0xdcd6, 0x6804, 0x9005, 0x0904, + 0xdcbe, 0x2d78, 0x6003, 0x0007, 0x080c, 0x1018, 0x0904, 0xdc7f, + 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, + 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, 0xdce1, 0x9006, 0xa802, + 0xa867, 0x0116, 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, + 0x2058, 0xb8a0, 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, + 0xa9be, 0xb930, 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, + 0x9084, 0x0003, 0x9080, 0xdc7b, 0x2005, 0xa87e, 0x20a9, 0x000a, + 0x2001, 0x0270, 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, + 0x0080, 0x20e1, 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, + 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, + 0xa9ae, 0x080c, 0x6c94, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, + 0x00be, 0x009e, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, + 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, 0x0fff, 0x1904, 0xdc28, + 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x90f8, + 0x080c, 0x96a6, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, + 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, + 0x918c, 0xf700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, + 0x0043, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0828, 0x6868, 0x602e, + 0x686c, 0x6032, 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0804, 0xdc73, 0x2001, 0x180e, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b1e, 0x6017, + 0xf300, 0x0010, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0804, 0xdc73, 0x6017, 0xf500, + 0x0c98, 0x6017, 0xf600, 0x0804, 0xdc93, 0x6017, 0xf200, 0x0804, + 0xdc93, 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, + 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, 0xdc7b, 0x2005, 0xa87e, + 0x2928, 0x6010, 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, + 0xa88e, 0xb830, 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, + 0x0205, 0x2104, 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, + 0x0210, 0x2214, 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, + 0x0dd5, 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, 0xdd5d, 0x2041, 0x0001, + 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, + 0x931a, 0x0530, 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, + 0x0260, 0x2098, 0x0c68, 0x2950, 0x080c, 0x1018, 0x0170, 0x2900, + 0xb002, 0xa867, 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x001b, 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, + 0x0118, 0x080c, 0x1031, 0x0cc8, 0x080c, 0x1031, 0x0804, 0xdc7f, + 0x2548, 0x8847, 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, + 0x0000, 0x080c, 0xe58c, 0x0804, 0xdc73, 0x8010, 0x0004, 0x801a, + 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, + 0x1160, 0x6004, 0x908a, 0x0054, 0x1a0c, 0x0dd5, 0x9082, 0x0040, + 0x0a0c, 0x0dd5, 0x2008, 0x0804, 0xde0f, 0x9186, 0x0051, 0x0108, + 0x00c0, 0x2001, 0x0109, 0x2004, 0xd084, 0x0904, 0xddbf, 0x0126, + 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x8fdd, 0x002e, + 0x001e, 0x000e, 0x012e, 0x6000, 0x9086, 0x0002, 0x1580, 0x0804, + 0xde58, 0x9186, 0x0027, 0x0530, 0x9186, 0x0048, 0x0128, 0x9186, + 0x0014, 0x0500, 0x190c, 0x0dd5, 0x2001, 0x0109, 0x2004, 0xd084, + 0x01f0, 0x00c6, 0x0126, 0x2091, 0x2800, 0x00c6, 0x2061, 0x0100, + 0x0006, 0x0016, 0x0026, 0x080c, 0x8fdd, 0x002e, 0x001e, 0x000e, + 0x00ce, 0x012e, 0x00ce, 0x6000, 0x9086, 0x0004, 0x190c, 0x0dd5, + 0x0804, 0xdf3b, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, + 0xaef5, 0x0005, 0xddd6, 0xddd8, 0xddd8, 0xddff, 0xddd6, 0xddd6, + 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, + 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0xddd6, 0x080c, 0x0dd5, + 0x080c, 0x959a, 0x080c, 0x96a6, 0x0036, 0x0096, 0x6014, 0x904d, + 0x01d8, 0x080c, 0xcb5a, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xe58c, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1986, + 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, + 0x080c, 0x959a, 0x080c, 0x96a6, 0x080c, 0xcb5a, 0x0120, 0x6014, + 0x2048, 0x080c, 0x1031, 0x080c, 0xae90, 0x009e, 0x0005, 0x0002, + 0xde24, 0xde3b, 0xde26, 0xde52, 0xde24, 0xde24, 0xde24, 0xde24, + 0xde24, 0xde24, 0xde24, 0xde24, 0xde24, 0xde24, 0xde24, 0xde24, + 0xde24, 0xde24, 0xde24, 0xde24, 0x080c, 0x0dd5, 0x0096, 0x080c, + 0x959a, 0x6014, 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, + 0x2009, 0x0043, 0x080c, 0xaeda, 0x0010, 0x6003, 0x0004, 0x080c, + 0x96a6, 0x009e, 0x0005, 0x080c, 0x959a, 0x080c, 0xcb5a, 0x0138, + 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, 0x080c, + 0x86b8, 0x080c, 0xae5f, 0x080c, 0x96a6, 0x0005, 0x080c, 0xe7ee, + 0x0db0, 0x0cc8, 0x080c, 0x959a, 0x2009, 0x0041, 0x0804, 0xdfc3, + 0x9182, 0x0040, 0x0002, 0xde6f, 0xde71, 0xde6f, 0xde6f, 0xde6f, + 0xde6f, 0xde6f, 0xde6f, 0xde6f, 0xde6f, 0xde6f, 0xde6f, 0xde6f, + 0xde6f, 0xde6f, 0xde6f, 0xde6f, 0xde72, 0xde6f, 0xde6f, 0x080c, + 0x0dd5, 0x0005, 0x00d6, 0x080c, 0x86b8, 0x00de, 0x080c, 0xe846, + 0x080c, 0xae5f, 0x0005, 0x9182, 0x0040, 0x0002, 0xde92, 0xde92, + 0xde92, 0xde92, 0xde92, 0xde92, 0xde92, 0xde92, 0xde92, 0xde94, + 0xdf03, 0xde92, 0xde92, 0xde92, 0xde92, 0xdf03, 0xde92, 0xde92, + 0xde92, 0xde92, 0x080c, 0x0dd5, 0x2001, 0x0105, 0x2004, 0x9084, + 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, + 0x9105, 0x1904, 0xdf03, 0x2009, 0x180c, 0x2104, 0xd0d4, 0x0904, + 0xdf03, 0xc0d4, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, + 0x9085, 0x0010, 0x200a, 0x2001, 0x1867, 0x2004, 0xd0e4, 0x1528, + 0x603b, 0x0000, 0x080c, 0x9656, 0x6014, 0x0096, 0x2048, 0xa87c, + 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, + 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, 0x97d4, 0x2009, 0x0041, + 0x009e, 0x0804, 0xdfc3, 0x080c, 0x97d4, 0x6003, 0x0007, 0x601b, + 0x0000, 0x080c, 0x86b8, 0x009e, 0x0005, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, + 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, + 0x2c5f, 0x080c, 0x97d4, 0x6014, 0x2048, 0xa97c, 0xd1ec, 0x1130, + 0x080c, 0x86b8, 0x080c, 0xae5f, 0x009e, 0x0005, 0x080c, 0xe7ee, + 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, + 0x0036, 0x080c, 0x9656, 0x080c, 0x97d4, 0x6014, 0x0096, 0x2048, + 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0188, 0xa87c, + 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, 0x6330, 0x931a, + 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, 0x0080, + 0x2019, 0x0004, 0x080c, 0xe58c, 0x6018, 0x9005, 0x1128, 0x2001, + 0x1986, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, + 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xdf52, 0xdf52, + 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf54, 0xdf52, + 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, 0xdf52, + 0xdf52, 0xdf9f, 0x080c, 0x0dd5, 0x6014, 0x0096, 0x2048, 0xa834, + 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, + 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x009e, + 0x0804, 0xdfc3, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x86b8, + 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0xacac, + 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, + 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x00b6, 0x2158, + 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, 0x210c, 0xd19c, + 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, + 0x86ba, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, 0x6024, + 0xd0f4, 0x0128, 0x080c, 0x15e7, 0x1904, 0xdf54, 0x0005, 0x6014, + 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, 0x080c, + 0x15e7, 0x1904, 0xdf54, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, + 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, + 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, + 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0dd5, 0x6024, 0xd0dc, + 0x090c, 0x0dd5, 0x0005, 0xdfe7, 0xdff3, 0xdfff, 0xe00b, 0xdfe7, + 0xdfe7, 0xdfe7, 0xdfe7, 0xdfee, 0xdfe9, 0xdfe9, 0xdfe7, 0xdfe7, + 0xdfe7, 0xdfe7, 0xdfe9, 0xdfe7, 0xdfe9, 0xdfe7, 0xdfee, 0x080c, + 0x0dd5, 0x6024, 0xd0dc, 0x090c, 0x0dd5, 0x0005, 0x6014, 0x9005, + 0x190c, 0x0dd5, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x90f8, + 0x0126, 0x2091, 0x8000, 0x080c, 0x96a6, 0x012e, 0x0005, 0x6003, + 0x0001, 0x6106, 0x080c, 0x90f8, 0x0126, 0x2091, 0x8000, 0x080c, + 0x96a6, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, + 0x1bba, 0x0126, 0x2091, 0x8000, 0x080c, 0x915d, 0x080c, 0x97d4, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, + 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xe03a, 0xe03c, + 0xe04e, 0xe068, 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, + 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, 0xe03a, + 0xe03a, 0xe03a, 0x080c, 0x0dd5, 0x6014, 0x2048, 0xa87c, 0xd0fc, + 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, + 0x6106, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0470, 0x6014, 0x2048, + 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, + 0x6003, 0x0001, 0x6106, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x00e0, + 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xe58c, 0x00a0, + 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, + 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1bba, + 0x080c, 0x915d, 0x080c, 0x97d4, 0x0005, 0x080c, 0x959a, 0x6114, + 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xe943, 0x0036, 0x2019, + 0x0029, 0x080c, 0xe58c, 0x003e, 0x009e, 0x080c, 0xae90, 0x080c, + 0x96a6, 0x0005, 0x080c, 0x9656, 0x6114, 0x81ff, 0x0158, 0x0096, + 0x2148, 0x080c, 0xe943, 0x0036, 0x2019, 0x0029, 0x080c, 0xe58c, + 0x003e, 0x009e, 0x080c, 0xae90, 0x080c, 0x97d4, 0x0005, 0x9182, + 0x0085, 0x0002, 0xe0b9, 0xe0b7, 0xe0b7, 0xe0c5, 0xe0b7, 0xe0b7, + 0xe0b7, 0xe0b7, 0xe0b7, 0xe0b7, 0xe0b7, 0xe0b7, 0xe0b7, 0x080c, + 0x0dd5, 0x6003, 0x000b, 0x6106, 0x080c, 0x90f8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x96a6, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, + 0xe7e5, 0x0118, 0x080c, 0xae5f, 0x0450, 0x2071, 0x0260, 0x7224, + 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, + 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xb180, + 0x7220, 0x080c, 0xe432, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, + 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, + 0x0001, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x080c, 0x97d4, 0x00ee, + 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, + 0x0a0c, 0x0dd5, 0x908a, 0x0092, 0x1a0c, 0x0dd5, 0x9082, 0x0085, + 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, + 0xaef5, 0x0050, 0x2001, 0x0007, 0x080c, 0x6592, 0x080c, 0x959a, + 0x080c, 0xae90, 0x080c, 0x96a6, 0x0005, 0xe12a, 0xe12c, 0xe12c, + 0xe12a, 0xe12a, 0xe12a, 0xe12a, 0xe12a, 0xe12a, 0xe12a, 0xe12a, + 0xe12a, 0xe12a, 0x080c, 0x0dd5, 0x080c, 0x959a, 0x080c, 0xae90, + 0x080c, 0x96a6, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0dd5, 0x9182, + 0x0092, 0x1a0c, 0x0dd5, 0x9182, 0x0085, 0x0002, 0xe14b, 0xe14b, + 0xe14b, 0xe14d, 0xe14b, 0xe14b, 0xe14b, 0xe14b, 0xe14b, 0xe14b, + 0xe14b, 0xe14b, 0xe14b, 0x080c, 0x0dd5, 0x0005, 0x9186, 0x0013, + 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, + 0xaef5, 0x0030, 0x080c, 0x959a, 0x080c, 0xae90, 0x080c, 0x96a6, + 0x0005, 0x0036, 0x080c, 0xe846, 0x6043, 0x0000, 0x2019, 0x000b, + 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, + 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, + 0xa687, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0xa732, + 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, + 0x0007, 0x01e0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xe846, + 0x080c, 0xd272, 0x080c, 0x1a70, 0x6023, 0x0007, 0x6014, 0x2048, + 0x080c, 0xcb5a, 0x0110, 0x080c, 0xe58c, 0x009e, 0x6017, 0x0000, + 0x080c, 0xe846, 0x6023, 0x0007, 0x080c, 0xd272, 0x003e, 0x012e, + 0x0005, 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, + 0x7938, 0x783c, 0x080c, 0x284b, 0x15c8, 0x0016, 0x00c6, 0x080c, + 0x6616, 0x1590, 0x001e, 0x00c6, 0x2160, 0x080c, 0xd26f, 0x00ce, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0xa7f8, 0x080c, + 0x929d, 0x0076, 0x903e, 0x080c, 0x9170, 0x007e, 0x001e, 0x0076, + 0x903e, 0x080c, 0xe326, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, + 0x080c, 0x328a, 0x002e, 0xbcc0, 0x001e, 0x080c, 0x6047, 0xbe12, + 0xbd16, 0xbcc2, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, + 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, + 0x2009, 0x1824, 0x2104, 0x9086, 0x0074, 0x1904, 0xe24d, 0x2069, + 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, + 0x0904, 0xe24a, 0x2001, 0x197b, 0x2004, 0x9005, 0x1140, 0x6010, + 0x2058, 0xb8c0, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, + 0x918a, 0x0001, 0x0648, 0x080c, 0xe9ab, 0x0118, 0x6978, 0xd1fc, + 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, + 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, + 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, + 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, + 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, + 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, + 0x0001, 0x0008, 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, + 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, + 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, + 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, + 0x0120, 0x080c, 0x6625, 0x0804, 0xe2b5, 0x2011, 0x0276, 0x20a9, + 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbe2d, 0x009e, + 0x15a8, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, + 0x0006, 0x080c, 0xbe2d, 0x009e, 0x1548, 0x0046, 0x0016, 0xbaa0, + 0x2220, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, + 0x0029, 0x080c, 0xe5e9, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, + 0x080c, 0x929d, 0x0076, 0x2039, 0x0000, 0x080c, 0x9170, 0x2c08, + 0x080c, 0xe326, 0x007e, 0x2001, 0x0007, 0x080c, 0x6592, 0x2001, + 0x0007, 0x080c, 0x6566, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, + 0x002e, 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, + 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, + 0x0005, 0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, + 0x026c, 0x7930, 0x7834, 0x080c, 0x284b, 0x11d0, 0x080c, 0x6616, + 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, + 0x000a, 0x080c, 0xbe2d, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, + 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xbe2d, 0x009e, + 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, + 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x284b, 0x11d0, 0x080c, 0x6616, 0x11b8, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, + 0x080c, 0xbe2d, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, + 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xbe2d, 0x009e, 0x015e, + 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2029, 0x19ef, 0x252c, 0x2021, 0x19f5, 0x2424, + 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, + 0x0006, 0x9186, 0x1aaf, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, + 0xe3c3, 0x0018, 0x9606, 0x0904, 0xe3c3, 0x080c, 0x8987, 0x0904, + 0xe3ba, 0x2100, 0x9c06, 0x0904, 0xe3ba, 0x080c, 0xe62a, 0x1904, + 0xe3ba, 0x080c, 0xe9c8, 0x0904, 0xe3ba, 0x080c, 0xe61a, 0x0904, + 0xe3ba, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x3321, 0x0904, + 0xe402, 0x6004, 0x9086, 0x0000, 0x1904, 0xe402, 0x9786, 0x0004, + 0x0904, 0xe402, 0x9786, 0x0007, 0x0904, 0xe3ba, 0x2500, 0x9c06, + 0x0904, 0xe3ba, 0x2400, 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, + 0x9906, 0x15c0, 0x0096, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x1a70, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xcd60, + 0x1130, 0x080c, 0xb821, 0x009e, 0x080c, 0xae90, 0x0418, 0x6014, + 0x2048, 0x080c, 0xcb5a, 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, + 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, + 0x0fb1, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xe943, 0x0016, + 0x080c, 0xce4e, 0x080c, 0x6c88, 0x001e, 0x080c, 0xcd43, 0x009e, + 0x080c, 0xae90, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, + 0x1210, 0x0804, 0xe33a, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, + 0x9386, 0x0005, 0x0128, 0x080c, 0xe943, 0x080c, 0xe58c, 0x08f8, + 0x009e, 0x0c00, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, + 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x9656, 0x0096, + 0x6114, 0x2148, 0x080c, 0xcb5a, 0x0118, 0x6010, 0x080c, 0x6c94, + 0x009e, 0x00c6, 0x080c, 0xae5f, 0x00ce, 0x0036, 0x080c, 0x97d4, + 0x003e, 0x009e, 0x0804, 0xe3ba, 0x9786, 0x000a, 0x0904, 0xe3a1, + 0x0804, 0xe39f, 0x81ff, 0x0904, 0xe3ba, 0x9180, 0x0001, 0x2004, + 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, + 0x1904, 0xe3ba, 0x6000, 0x9086, 0x0002, 0x1904, 0xe3ba, 0x080c, + 0xcd4f, 0x0138, 0x080c, 0xcd60, 0x1904, 0xe3ba, 0x080c, 0xb821, + 0x0038, 0x080c, 0x31f5, 0x080c, 0xcd60, 0x1110, 0x080c, 0xb821, + 0x080c, 0xae90, 0x0804, 0xe3ba, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, + 0x080c, 0xe5b3, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, + 0x00ee, 0x00ce, 0x0005, 0xe451, 0xe451, 0xe451, 0xe451, 0xe451, + 0xe451, 0xe453, 0xe451, 0xe451, 0xe451, 0xe451, 0xae90, 0xae90, + 0xe451, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, + 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xe5e9, + 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, 0xe16f, 0x003e, 0x9085, + 0x0001, 0x0005, 0x0096, 0x080c, 0xcb5a, 0x0140, 0x6014, 0x904d, + 0x080c, 0xc77b, 0x687b, 0x0005, 0x080c, 0x6c94, 0x009e, 0x080c, + 0xae90, 0x9085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x6552, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, + 0x2011, 0x0276, 0x080c, 0xbe19, 0x003e, 0x002e, 0x001e, 0x015e, + 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, + 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1cd0, 0x2079, + 0x0001, 0x8fff, 0x0904, 0xe4ec, 0x2071, 0x1800, 0x7654, 0x7074, + 0x8001, 0x9602, 0x1a04, 0xe4ec, 0x88ff, 0x0120, 0x2800, 0x9c06, + 0x1590, 0x2078, 0x080c, 0xe61a, 0x0570, 0x2400, 0x9c06, 0x0558, + 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, + 0x1140, 0x6010, 0x9b06, 0x11f8, 0x85ff, 0x0118, 0x6054, 0x9106, + 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xe846, 0x080c, + 0xd272, 0x080c, 0x1a70, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, + 0xcb5a, 0x0120, 0x0046, 0x080c, 0xe58c, 0x004e, 0x009e, 0x080c, + 0xae90, 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, + 0x9c02, 0x1210, 0x0804, 0xe4a1, 0x9006, 0x012e, 0x00be, 0x006e, + 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, + 0x0ca0, 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, + 0x2c20, 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, + 0xa687, 0x009e, 0x008e, 0x903e, 0x080c, 0xa732, 0x080c, 0xe492, + 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, + 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, + 0x0036, 0x080c, 0x6616, 0x1190, 0x0056, 0x0086, 0x9046, 0x2508, + 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0xa687, 0x009e, 0x008e, + 0x903e, 0x080c, 0xa732, 0x080c, 0xe492, 0x005e, 0x003e, 0x001e, + 0x8108, 0x1f04, 0xe51f, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, + 0x00be, 0x0005, 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, + 0xa687, 0x009e, 0x008e, 0x903e, 0x080c, 0xa732, 0x2c20, 0x080c, + 0xe492, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, + 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, + 0x0036, 0x080c, 0x6616, 0x11a0, 0x0086, 0x9046, 0x2828, 0x0046, + 0x2021, 0x0001, 0x080c, 0xe82a, 0x004e, 0x0096, 0x904e, 0x080c, + 0xa687, 0x009e, 0x008e, 0x903e, 0x080c, 0xa732, 0x080c, 0xe492, + 0x003e, 0x001e, 0x8108, 0x1f04, 0xe567, 0x015e, 0x00ce, 0x007e, + 0x005e, 0x004e, 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xcb58, + 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, + 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, 0x6c94, 0x2f48, + 0x0cb0, 0xab82, 0x080c, 0x6c94, 0x00fe, 0x001e, 0x0005, 0xa800, + 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6c94, 0x2f48, 0x0cb8, + 0x080c, 0x6c94, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0, + 0x9005, 0x1138, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, + 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, + 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, + 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, + 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, + 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, + 0x0c30, 0x0096, 0x0006, 0x080c, 0x0fff, 0x000e, 0x090c, 0x0dd5, + 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xcb48, + 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, + 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, + 0xa87f, 0x0000, 0x2001, 0x198d, 0x2004, 0xa882, 0x9006, 0xa802, + 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c94, 0x012e, + 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, + 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, + 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, + 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, + 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0005, 0x2001, 0x1986, 0x2004, 0x601a, 0x080c, 0x90f8, 0x080c, + 0x96a6, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, + 0x0158, 0xd0cc, 0x0118, 0x080c, 0xce92, 0x0030, 0x080c, 0xe846, + 0x080c, 0x86b8, 0x080c, 0xae5f, 0x0005, 0x9280, 0x0008, 0x2004, + 0x9084, 0x000f, 0x0002, 0xe679, 0xe679, 0xe679, 0xe67b, 0xe679, + 0xe67b, 0xe67b, 0xe679, 0xe67b, 0xe679, 0xe679, 0xe679, 0xe679, + 0xe679, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, + 0x2004, 0x9084, 0x000f, 0x0002, 0xe692, 0xe692, 0xe692, 0xe692, + 0xe692, 0xe692, 0xe69f, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, + 0xe692, 0xe692, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, + 0x6003, 0x0001, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x0005, 0x0096, + 0x00c6, 0x2260, 0x080c, 0xe846, 0x6043, 0x0000, 0x6024, 0xc0f4, + 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, + 0x0007, 0x1904, 0xe6f8, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, + 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, + 0x0001, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x00c6, 0x2d60, 0x6100, + 0x9186, 0x0002, 0x1904, 0xe76f, 0x6014, 0x9005, 0x1138, 0x6000, + 0x9086, 0x0007, 0x190c, 0x0dd5, 0x0804, 0xe76f, 0x2048, 0x080c, + 0xcb5a, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, + 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, + 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, + 0x080c, 0xdfc3, 0x0804, 0xe76f, 0x2009, 0x0041, 0x0804, 0xe769, + 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, + 0x00de, 0x009e, 0x0804, 0xe692, 0xd0b4, 0x0128, 0xd0fc, 0x090c, + 0x0dd5, 0x0804, 0xe6b3, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, + 0x90f8, 0x080c, 0x96a6, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, + 0x0120, 0x9186, 0x0004, 0x1904, 0xe76f, 0x6814, 0x2048, 0xa97c, + 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, + 0x2c78, 0x080c, 0x1727, 0x00fe, 0x2009, 0x0042, 0x04d0, 0x0036, + 0x080c, 0x0fff, 0x090c, 0x0dd5, 0xa867, 0x010d, 0x9006, 0xa802, + 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, + 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, + 0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, 0xab7a, 0xa876, 0x9006, + 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6c94, + 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xe16f, 0x2d00, 0x600a, + 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x6342, 0x003e, + 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, 0xdfc3, 0x00ce, + 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, + 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, 0x959a, + 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, 0xe58c, + 0x009e, 0x003e, 0x080c, 0x96a6, 0x0005, 0x9186, 0x0014, 0x0d70, + 0x080c, 0xaef5, 0x0005, 0xe7a2, 0xe7a0, 0xe7a0, 0xe7a0, 0xe7a0, + 0xe7a0, 0xe7a2, 0xe7a0, 0xe7a0, 0xe7a0, 0xe7a0, 0xe7a0, 0xe7a0, + 0x080c, 0x0dd5, 0x080c, 0x959a, 0x6003, 0x000c, 0x080c, 0x96a6, + 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, + 0x080c, 0xaef5, 0x0005, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c2, + 0xe7e2, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c0, 0xe7c0, + 0x080c, 0x0dd5, 0x00d6, 0x2c68, 0x080c, 0xae09, 0x01b0, 0x6003, + 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, + 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, + 0x0004, 0x080c, 0x90f8, 0x080c, 0x96a6, 0x2d60, 0x080c, 0xae5f, + 0x00de, 0x0005, 0x080c, 0xae5f, 0x0005, 0x00e6, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1867, + 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, + 0xd0cc, 0x0150, 0x2001, 0x1987, 0x2004, 0x6042, 0x2009, 0x1867, + 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c, 0xd1f4, + 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, 0x1987, + 0x200c, 0x2001, 0x1985, 0x2004, 0x9100, 0x9080, 0x000a, 0x6042, + 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104, 0x9005, + 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, + 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8bc, 0x2060, + 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, 0x600c, + 0x2072, 0x080c, 0x86b8, 0x080c, 0xae5f, 0x0010, 0x9cf0, 0x0003, + 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x00b6, + 0x6010, 0x2058, 0xb8bc, 0x2068, 0x9005, 0x0130, 0x9c06, 0x0110, + 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, + 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019, + 0x026e, 0x2334, 0x9636, 0x1508, 0x8318, 0x2334, 0x2204, 0x9084, + 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, + 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xbe2d, 0x009e, 0x1168, + 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, + 0x0006, 0x080c, 0xbe2d, 0x009e, 0x1100, 0x015e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fc0, 0x080c, 0x2fa3, + 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, 0x0fff, 0x090c, 0x0dd5, + 0xa85c, 0x9080, 0x001a, 0x20a0, 0x20a9, 0x000c, 0xa860, 0x20e8, + 0x9006, 0x4004, 0x9186, 0x0046, 0x1118, 0xa867, 0x0136, 0x0038, + 0xa867, 0x0138, 0x9186, 0x0041, 0x0110, 0xa87b, 0x0001, 0x7038, + 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, 0x8007, 0x9215, 0xaa9a, + 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff, 0x723c, 0x9294, + 0xff00, 0x9215, 0xaa9e, 0x723c, 0x9294, 0x00ff, 0xaaa2, 0x0060, + 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00, 0x9215, 0xaa9e, + 0x7244, 0x9294, 0x00ff, 0xaaa2, 0x9186, 0x0046, 0x1118, 0x9e90, + 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007, 0xa8a6, 0x8210, + 0x2204, 0x8007, 0xa8aa, 0x8210, 0x2204, 0x8007, 0xa8ae, 0x8210, + 0x2204, 0x8007, 0xa8b2, 0x8210, 0x9186, 0x0046, 0x11b8, 0x9e90, + 0x0016, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, + 0x8210, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, + 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0, 0x9e90, 0x001e, + 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, 0x2011, + 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, 0x2204, 0x8007, 0xa8be, + 0x8210, 0x2204, 0x8007, 0xa8c2, 0x9186, 0x0046, 0x1118, 0x2011, + 0x0262, 0x0010, 0x2011, 0x026a, 0x0146, 0x01d6, 0x0036, 0x20a9, + 0x0001, 0x2019, 0x0008, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, + 0x20a0, 0x2204, 0x8007, 0x4004, 0x8210, 0x8319, 0x1dd0, 0x003e, + 0x01ce, 0x013e, 0x2011, 0x0205, 0x2013, 0x0000, 0x002e, 0x080c, + 0x6c94, 0x009e, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, + 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0xa880, 0xc0e5, + 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, + 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x19ef, + 0x252c, 0x2021, 0x19f5, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, + 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, + 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, + 0x01d0, 0x080c, 0xe61a, 0x01b8, 0x080c, 0xe62a, 0x11a0, 0x6000, + 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a70, 0x001e, 0x080c, + 0xcd4f, 0x1110, 0x080c, 0x31f5, 0x080c, 0xcd60, 0x1110, 0x080c, + 0xb821, 0x080c, 0xae90, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, + 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, 0x1810, + 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1837, 0x2004, 0xd09c, + 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, 0xd25a, 0x0168, + 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, + 0x00be, 0x2021, 0x0004, 0x080c, 0x4cd5, 0x004e, 0x003e, 0x000e, + 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0xa7f8, 0x080c, 0xae90, + 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1cd0, + 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, 0x12b8, 0x2100, + 0x9c06, 0x0148, 0x6000, 0x9086, 0x0000, 0x0128, 0x6010, 0x2058, + 0xb8a0, 0x9206, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, + 0x9c02, 0x1220, 0x0c60, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, + 0x00be, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, + 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, + 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, + 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, + 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0xfff6, 0x0089, 0x001e, + 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, + 0x8000, 0x2071, 0xffee, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, + 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, + 0x0005, 0x00e6, 0x2071, 0xffec, 0x0c99, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0xfff0, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, + 0x2091, 0x8000, 0x2071, 0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0003, 0x000b, 0x079e, 0x0000, 0xc000, + 0x0001, 0x8064, 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, 0x0101, + 0x0008, 0x4407, 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x580d, + 0x000b, 0x79a8, 0x000b, 0x50ee, 0x000b, 0x4c0a, 0x0003, 0xbac0, + 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b, 0x15fe, 0x0008, 0x340a, + 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffa0, 0x0001, 0x2000, + 0x0000, 0x1668, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x0000, + 0x0007, 0x4028, 0x0000, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, + 0x0000, 0x0822, 0x0003, 0x4022, 0x0000, 0x0028, 0x000b, 0x4122, + 0x0008, 0x94c0, 0x0009, 0xff00, 0x0008, 0xffe0, 0x0009, 0x0500, + 0x0008, 0x0a93, 0x000b, 0x4447, 0x0002, 0x0e90, 0x0003, 0x0bfe, + 0x0008, 0x11a0, 0x0001, 0x126e, 0x0003, 0x0ca0, 0x0001, 0x126e, + 0x0003, 0x9180, 0x0001, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4436, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, + 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, 0x0411, 0x0000, 0x443e, + 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001, 0x0e6b, 0x000b, 0xc2c0, + 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, 0x0e6b, 0x000b, 0x9180, + 0x0001, 0x0005, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0019, 0x0000, 0x444d, 0x000b, 0x0240, + 0x0002, 0x0a68, 0x0003, 0x00fe, 0x0000, 0x326b, 0x000b, 0x0248, + 0x000a, 0x085c, 0x0003, 0x9180, 0x0001, 0x0006, 0x0008, 0x7f62, + 0x0008, 0x8002, 0x0008, 0x0003, 0x0008, 0x8066, 0x0000, 0x020a, + 0x0000, 0x445b, 0x0003, 0x112a, 0x0000, 0x002e, 0x0008, 0x022c, + 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, 0x0002, + 0x0000, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0008, 0x8066, + 0x0000, 0x0011, 0x0008, 0x4468, 0x0003, 0x01fe, 0x0008, 0x42e0, + 0x0009, 0x0e5c, 0x0003, 0x00fe, 0x0000, 0x43e0, 0x0001, 0x0e5c, + 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, 0x0d2a, + 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x8060, 0x0000, 0x0400, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, 0x447a, + 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, 0x1a60, 0x0000, 0x8062, + 0x0008, 0x0002, 0x0000, 0x5880, 0x000b, 0x8066, 0x0000, 0x3679, + 0x0000, 0x4483, 0x0003, 0x5884, 0x0003, 0x3efe, 0x0008, 0x7f4f, + 0x0002, 0x088a, 0x000b, 0x0d00, 0x0000, 0x0092, 0x000c, 0x8054, + 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, 0x1010, 0x0008, 0x1efe, + 0x0000, 0x300a, 0x000b, 0x00c8, 0x000c, 0x000a, 0x000b, 0x00fe, + 0x0000, 0x349a, 0x0003, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0007, + 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x4499, 0x000b, 0x03fe, + 0x0000, 0x04d0, 0x0001, 0x0cc0, 0x000b, 0x82c0, 0x0001, 0x1f00, + 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000, 0x08af, 0x0003, 0x14c0, + 0x000b, 0x01fe, 0x0008, 0x0580, 0x0009, 0x7f06, 0x0000, 0x02fe, + 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0690, 0x0001, 0x10af, + 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008, 0x08c0, + 0x0003, 0x00fe, 0x0000, 0x34b6, 0x000b, 0x8072, 0x0000, 0x1010, + 0x0008, 0x3944, 0x0002, 0x08b1, 0x0003, 0x00ba, 0x0003, 0x8072, + 0x0000, 0x2020, 0x0008, 0x3945, 0x000a, 0x08b6, 0x000b, 0x3946, + 0x000a, 0x0cc7, 0x0003, 0x0000, 0x0007, 0x3943, 0x000a, 0x08c7, + 0x000b, 0x00ba, 0x0003, 0x00fe, 0x0000, 0x34c5, 0x0003, 0x8072, + 0x0000, 0x1000, 0x0000, 0x00c7, 0x0003, 0x8072, 0x0000, 0x2000, + 0x0000, 0x4000, 0x000f, 0x1c60, 0x0000, 0x1b62, 0x0000, 0x8066, + 0x0000, 0x0231, 0x0008, 0x44cc, 0x000b, 0x58cd, 0x000b, 0x0140, + 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0cdb, 0x000b, 0x0d44, + 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, 0x030a, + 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000, 0x0d08, 0x0008, 0x00df, + 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, 0x064a, + 0x0000, 0x1948, 0x000a, 0x08e2, 0x0003, 0x0d4a, 0x0008, 0x58e2, + 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002, 0x08e9, 0x000b, 0x8000, + 0x0000, 0x0001, 0x0000, 0x0092, 0x000c, 0x8054, 0x0008, 0x0001, + 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, 0x4000, 0x000f, 0x3a40, + 0x000a, 0x0c0d, 0x0003, 0x2b24, 0x0008, 0x2b24, 0x0008, 0x58f2, + 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, 0x1242, 0x0002, 0x0940, + 0x0003, 0x3a45, 0x000a, 0x092f, 0x0003, 0x8072, 0x0000, 0x1000, + 0x0000, 0x3945, 0x000a, 0x08ff, 0x0003, 0x8072, 0x0000, 0x3010, + 0x0000, 0x1e10, 0x000a, 0x7f3c, 0x0000, 0x092a, 0x0003, 0x1d00, + 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0009, 0x0008, 0x4508, 0x000b, 0x00fe, 0x0000, 0x3527, + 0x000b, 0x1c60, 0x0000, 0x8062, 0x0008, 0x0001, 0x0000, 0x8066, + 0x0000, 0x0009, 0x0008, 0x4510, 0x000b, 0x00fe, 0x0000, 0x3243, + 0x000b, 0x0038, 0x0000, 0x0060, 0x0008, 0x8062, 0x0008, 0x0019, + 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x4519, 0x000b, 0x80c0, + 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, 0x0d60, 0x0000, 0x0efe, + 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, + 0x0008, 0x4523, 0x000b, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x0104, + 0x000b, 0x0036, 0x0008, 0x00c8, 0x000c, 0x0140, 0x000b, 0x8074, + 0x0000, 0x2000, 0x0000, 0x8072, 0x0000, 0x2000, 0x0000, 0x0140, + 0x000b, 0x3a44, 0x0002, 0x0a71, 0x000b, 0x8074, 0x0000, 0x1000, + 0x0000, 0x8072, 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, + 0x0000, 0x3640, 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, + 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, 0x0d52, 0x000b, 0x8074, + 0x0000, 0x4040, 0x0008, 0x5940, 0x0003, 0x50ee, 0x000b, 0x3a46, + 0x000a, 0x0d52, 0x000b, 0x3a47, 0x0002, 0x094d, 0x000b, 0x8054, + 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x8072, + 0x0000, 0x3000, 0x0008, 0x019c, 0x0003, 0x92c0, 0x0009, 0x0fc8, + 0x0000, 0x080a, 0x0003, 0x1246, 0x000a, 0x0e3a, 0x0003, 0x1a60, + 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, 0x8066, 0x0000, 0x362a, + 0x0000, 0x4557, 0x000b, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, + 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, + 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, + 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, + 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, + 0x0000, 0x2912, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0007, + 0x0000, 0x8066, 0x0000, 0x0052, 0x0000, 0x4571, 0x0003, 0x92c0, + 0x0009, 0x0780, 0x0008, 0x0e56, 0x0003, 0x124b, 0x0002, 0x097a, + 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a40, 0x0003, 0x3a46, + 0x000a, 0x0d8a, 0x000b, 0x597c, 0x0003, 0x8054, 0x0008, 0x0004, + 0x0000, 0x1243, 0x000a, 0x0998, 0x0003, 0x8010, 0x0008, 0x000d, + 0x0000, 0x021b, 0x000c, 0x1948, 0x000a, 0x0987, 0x000b, 0x0210, + 0x0004, 0x1810, 0x0000, 0x021b, 0x000c, 0x0198, 0x000b, 0x1948, + 0x000a, 0x098e, 0x000b, 0x1243, 0x000a, 0x0a43, 0x0003, 0x194d, + 0x000a, 0x0992, 0x0003, 0x1243, 0x000a, 0x0a4a, 0x0003, 0x5992, + 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x0210, 0x0004, 0x1810, + 0x0000, 0x021b, 0x000c, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, + 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, 0x3a42, 0x0002, 0x0da2, + 0x000b, 0x15fe, 0x0008, 0x3461, 0x000b, 0x000a, 0x000b, 0x8074, + 0x0000, 0x0501, 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x021b, + 0x000c, 0x000a, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0db8, + 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x09b5, 0x0003, 0x15fe, + 0x0008, 0x3ce0, 0x0009, 0x09b5, 0x0003, 0x020b, 0x0004, 0x8076, + 0x0008, 0x0040, 0x0000, 0x0208, 0x000b, 0x8076, 0x0008, 0x0041, + 0x0008, 0x0208, 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0dbd, + 0x0003, 0x3c1e, 0x0008, 0x0208, 0x000b, 0xbbe0, 0x0009, 0x003b, + 0x0000, 0x0dc2, 0x000b, 0x3c20, 0x0000, 0x0208, 0x000b, 0xbbe0, + 0x0009, 0x0035, 0x0008, 0x0dc8, 0x000b, 0x8072, 0x0000, 0x8000, + 0x0000, 0x0384, 0x000b, 0xbbe0, 0x0009, 0x0036, 0x0008, 0x0aa5, + 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, 0x0de9, 0x000b, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x0db5, 0x000b, 0x8076, 0x0008, 0x0040, + 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x000d, 0x0000, 0x2604, + 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, 0x0008, 0x2808, + 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, 0x0000, 0x8066, + 0x0000, 0x0422, 0x0000, 0x45e0, 0x000b, 0x0210, 0x0004, 0x8054, + 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, + 0x0000, 0xb000, 0x0000, 0x019c, 0x0003, 0xbbe0, 0x0009, 0x0038, + 0x0000, 0x0dfb, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x09f8, + 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0db1, 0x0003, 0x020b, + 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, 0x8000, + 0x0000, 0x0268, 0x000b, 0x8076, 0x0008, 0x0042, 0x0008, 0x0208, + 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0e08, 0x000b, 0x8074, + 0x0000, 0x0808, 0x0008, 0x3a44, 0x0002, 0x0c0c, 0x000b, 0x8074, + 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x8000, + 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x000a, + 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, 0x0007, + 0x0000, 0x0214, 0x0003, 0x1930, 0x000a, 0x7f00, 0x0000, 0x9880, + 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0x4619, 0x000b, 0x4000, + 0x000f, 0x221e, 0x000b, 0x0870, 0x0008, 0x4000, 0x000f, 0x7e1b, + 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0e1b, 0x0003, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x0a2c, 0x0003, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x0a2c, 0x0003, 0x020b, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x022e, 0x0003, 0x8076, 0x0008, 0x0041, 0x0008, 0x8072, + 0x0000, 0x8000, 0x0000, 0x021b, 0x0003, 0xbac0, 0x0009, 0x0090, + 0x0008, 0x0a37, 0x0003, 0x8074, 0x0000, 0x0706, 0x0000, 0x0239, + 0x0003, 0x8074, 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, + 0x0008, 0x0023, 0x0000, 0x0276, 0x000b, 0x8010, 0x0008, 0x0008, + 0x0000, 0x0276, 0x000b, 0x8010, 0x0008, 0x0022, 0x0008, 0x0276, + 0x000b, 0x0210, 0x0004, 0x8010, 0x0008, 0x0007, 0x0000, 0x021b, + 0x000c, 0x1810, 0x0000, 0x021b, 0x000c, 0x0282, 0x0003, 0x0210, + 0x0004, 0x8010, 0x0008, 0x001b, 0x0008, 0x021b, 0x000c, 0x1810, + 0x0000, 0x021b, 0x000c, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, + 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, 0x000a, 0x000b, 0x8010, + 0x0008, 0x0009, 0x0008, 0x0276, 0x000b, 0x8010, 0x0008, 0x0005, + 0x0008, 0x0276, 0x000b, 0x1648, 0x000a, 0x0c6f, 0x000b, 0x808c, + 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, + 0x000a, 0x086f, 0x0003, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x0d2a, + 0x0008, 0x0276, 0x000b, 0x8010, 0x0008, 0x0003, 0x0008, 0x027a, + 0x000b, 0x8010, 0x0008, 0x000b, 0x0000, 0x027a, 0x000b, 0x8010, + 0x0008, 0x0002, 0x0000, 0x027a, 0x000b, 0x3a47, 0x0002, 0x0d40, + 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, 0x027a, 0x000b, 0x8074, + 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x021b, + 0x000c, 0x0231, 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, 0x8010, + 0x0008, 0x000c, 0x0008, 0x021b, 0x000c, 0x000a, 0x000b, 0x8074, + 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, + 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a8d, 0x000b, 0x8054, + 0x0008, 0x0019, 0x0000, 0x000a, 0x000b, 0x8054, 0x0008, 0x0009, + 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x026b, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x4447, 0x0002, 0x0ab9, + 0x0003, 0xc0c0, 0x0001, 0x00ff, 0x0008, 0xffe0, 0x0009, 0x00ff, + 0x0008, 0x0e90, 0x0003, 0xc1e0, 0x0001, 0xffff, 0x0008, 0x0e90, + 0x0003, 0x8010, 0x0008, 0x0013, 0x0000, 0x021b, 0x000c, 0x8074, + 0x0000, 0x0202, 0x0008, 0x000a, 0x000b, 0x3a40, 0x000a, 0x0eb6, + 0x000b, 0x8074, 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe, + 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x43e0, 0x0001, 0x0eb4, + 0x0003, 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x00e0, + 0x0009, 0x0a90, 0x000b, 0x0d08, 0x0008, 0x0309, 0x000b, 0x8072, + 0x0000, 0x8000, 0x0000, 0x000a, 0x000b, 0x038d, 0x0004, 0x808c, + 0x0008, 0x0001, 0x0000, 0x04fe, 0x0008, 0x3370, 0x0003, 0x0460, 0x0000, 0x8062, 0x0008, 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, - 0x0008, 0x4510, 0x000b, 0x00fe, 0x0000, 0x3243, 0x000b, 0x0038, - 0x0000, 0x0060, 0x0008, 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, - 0x0000, 0x0009, 0x0008, 0x4519, 0x000b, 0x80c0, 0x0009, 0x00ff, - 0x0008, 0x7f3e, 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, - 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4523, - 0x000b, 0x003a, 0x0008, 0x1dfe, 0x0000, 0x0104, 0x000b, 0x0036, - 0x0008, 0x00c8, 0x000c, 0x0140, 0x000b, 0x8074, 0x0000, 0x2000, - 0x0000, 0x8072, 0x0000, 0x2000, 0x0000, 0x0140, 0x000b, 0x3a44, - 0x0002, 0x0a71, 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x8072, - 0x0000, 0x1000, 0x0000, 0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3640, - 0x0003, 0x26fe, 0x0008, 0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, - 0x0008, 0x00d0, 0x0009, 0x0d52, 0x000b, 0x8074, 0x0000, 0x4040, - 0x0008, 0x5940, 0x0003, 0x50ee, 0x000b, 0x3a46, 0x000a, 0x0d52, - 0x000b, 0x3a47, 0x0002, 0x094d, 0x000b, 0x8054, 0x0008, 0x0004, - 0x0000, 0x8074, 0x0000, 0x8000, 0x0000, 0x8072, 0x0000, 0x3000, - 0x0008, 0x019c, 0x0003, 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, - 0x0003, 0x1246, 0x000a, 0x0e3a, 0x0003, 0x1a60, 0x0000, 0x8062, - 0x0008, 0x0002, 0x0000, 0x8066, 0x0000, 0x362a, 0x0000, 0x4557, - 0x000b, 0x2000, 0x0000, 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, - 0x0000, 0x2204, 0x0000, 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, - 0x0000, 0x2408, 0x0000, 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, - 0x0000, 0x260c, 0x0000, 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, - 0x0000, 0x2810, 0x0000, 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, - 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, - 0x0000, 0x0052, 0x0000, 0x4571, 0x0003, 0x92c0, 0x0009, 0x0780, - 0x0008, 0x0e56, 0x0003, 0x124b, 0x0002, 0x097a, 0x0003, 0x2e4d, - 0x0002, 0x2e4d, 0x0002, 0x0a40, 0x0003, 0x3a46, 0x000a, 0x0d8a, - 0x000b, 0x597c, 0x0003, 0x8054, 0x0008, 0x0004, 0x0000, 0x1243, - 0x000a, 0x0998, 0x0003, 0x8010, 0x0008, 0x000d, 0x0000, 0x021b, - 0x000c, 0x1948, 0x000a, 0x0987, 0x000b, 0x0210, 0x0004, 0x1810, - 0x0000, 0x021b, 0x000c, 0x0198, 0x000b, 0x1948, 0x000a, 0x098e, - 0x000b, 0x1243, 0x000a, 0x0a43, 0x0003, 0x194d, 0x000a, 0x0992, - 0x0003, 0x1243, 0x000a, 0x0a4a, 0x0003, 0x5992, 0x0003, 0x8054, - 0x0008, 0x0004, 0x0000, 0x0210, 0x0004, 0x1810, 0x0000, 0x021b, - 0x000c, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, - 0x0008, 0x0d30, 0x0000, 0x3a42, 0x0002, 0x0da2, 0x000b, 0x15fe, - 0x0008, 0x3461, 0x000b, 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, - 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x021b, 0x000c, 0x000a, - 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0db8, 0x0003, 0x18fe, - 0x0000, 0x3ce0, 0x0009, 0x09b5, 0x0003, 0x15fe, 0x0008, 0x3ce0, - 0x0009, 0x09b5, 0x0003, 0x020b, 0x0004, 0x8076, 0x0008, 0x0040, - 0x0000, 0x0208, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x0208, - 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0dbd, 0x0003, 0x3c1e, - 0x0008, 0x0208, 0x000b, 0xbbe0, 0x0009, 0x003b, 0x0000, 0x0dc2, - 0x000b, 0x3c20, 0x0000, 0x0208, 0x000b, 0xbbe0, 0x0009, 0x0035, - 0x0008, 0x0dc8, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x0384, - 0x000b, 0xbbe0, 0x0009, 0x0036, 0x0008, 0x0aa5, 0x000b, 0xbbe0, - 0x0009, 0x0037, 0x0000, 0x0de9, 0x000b, 0x18fe, 0x0000, 0x3ce0, - 0x0009, 0x0db5, 0x000b, 0x8076, 0x0008, 0x0040, 0x0000, 0x1a60, - 0x0000, 0x8062, 0x0008, 0x000d, 0x0000, 0x2604, 0x0008, 0x2604, - 0x0008, 0x2706, 0x0008, 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, - 0x0000, 0x290a, 0x0000, 0x290a, 0x0000, 0x8066, 0x0000, 0x0422, - 0x0000, 0x45e0, 0x000b, 0x0210, 0x0004, 0x8054, 0x0008, 0x0004, - 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0xb000, - 0x0000, 0x019c, 0x0003, 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0dfb, - 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x09f8, 0x0003, 0x15fe, - 0x0008, 0x3ce0, 0x0009, 0x0db1, 0x0003, 0x020b, 0x0004, 0x8076, - 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x0268, - 0x000b, 0x8076, 0x0008, 0x0042, 0x0008, 0x0208, 0x000b, 0xbbe0, - 0x0009, 0x0016, 0x0000, 0x0e08, 0x000b, 0x8074, 0x0000, 0x0808, - 0x0008, 0x3a44, 0x0002, 0x0c0c, 0x000b, 0x8074, 0x0000, 0x0800, - 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, 0x8000, 0x000f, 0x000a, - 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x000a, 0x000b, 0x3d30, - 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, 0x0007, 0x0000, 0x0214, - 0x0003, 0x1930, 0x000a, 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, + 0x0008, 0x46c3, 0x0003, 0x0004, 0x0000, 0x80c0, 0x0009, 0x00ff, + 0x0008, 0x7f00, 0x0000, 0x80e0, 0x0001, 0x0004, 0x0000, 0x0add, + 0x000b, 0x80e0, 0x0001, 0x0005, 0x0008, 0x0add, 0x000b, 0x80e0, + 0x0001, 0x0006, 0x0008, 0x0add, 0x000b, 0x82c0, 0x0001, 0xff00, + 0x0008, 0x7f04, 0x0008, 0x82e0, 0x0009, 0x0600, 0x0008, 0x0add, + 0x000b, 0x82e0, 0x0009, 0x0500, 0x0008, 0x0add, 0x000b, 0x82e0, + 0x0009, 0x0400, 0x0000, 0x0f70, 0x0003, 0xc4c0, 0x0009, 0x7000, + 0x0000, 0xffe0, 0x0009, 0x1000, 0x0000, 0x0b09, 0x0003, 0x037e, + 0x0004, 0x3941, 0x0002, 0x0ae8, 0x000b, 0x8072, 0x0000, 0x0400, + 0x0000, 0x000a, 0x000b, 0x0460, 0x0000, 0x80fe, 0x0008, 0x002b, + 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x46ee, + 0x0003, 0x11fe, 0x0000, 0x3304, 0x0003, 0x9180, 0x0001, 0x0002, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, - 0x0000, 0x000a, 0x0008, 0x4619, 0x000b, 0x4000, 0x000f, 0x221e, - 0x000b, 0x0870, 0x0008, 0x4000, 0x000f, 0x7e1b, 0x000b, 0xbbe0, - 0x0009, 0x0030, 0x0008, 0x0e1b, 0x0003, 0x18fe, 0x0000, 0x3ce0, - 0x0009, 0x0a2c, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0a2c, - 0x0003, 0x020b, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x022e, - 0x0003, 0x8076, 0x0008, 0x0041, 0x0008, 0x8072, 0x0000, 0x8000, - 0x0000, 0x021b, 0x0003, 0xbac0, 0x0009, 0x0090, 0x0008, 0x0a37, - 0x0003, 0x8074, 0x0000, 0x0706, 0x0000, 0x0239, 0x0003, 0x8074, - 0x0000, 0x0703, 0x0000, 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, - 0x0000, 0x0276, 0x000b, 0x8010, 0x0008, 0x0008, 0x0000, 0x0276, - 0x000b, 0x8010, 0x0008, 0x0022, 0x0008, 0x0276, 0x000b, 0x0210, - 0x0004, 0x8010, 0x0008, 0x0007, 0x0000, 0x021b, 0x000c, 0x1810, - 0x0000, 0x021b, 0x000c, 0x0282, 0x0003, 0x0210, 0x0004, 0x8010, - 0x0008, 0x001b, 0x0008, 0x021b, 0x000c, 0x1810, 0x0000, 0x021b, - 0x000c, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, - 0x0008, 0x0d30, 0x0000, 0x000a, 0x000b, 0x8010, 0x0008, 0x0009, - 0x0008, 0x0276, 0x000b, 0x8010, 0x0008, 0x0005, 0x0008, 0x0276, - 0x000b, 0x1648, 0x000a, 0x0c6f, 0x000b, 0x808c, 0x0008, 0x0001, - 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, 0x000a, 0x086f, - 0x0003, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x0d2a, 0x0008, 0x0276, - 0x000b, 0x8010, 0x0008, 0x0003, 0x0008, 0x027a, 0x000b, 0x8010, - 0x0008, 0x000b, 0x0000, 0x027a, 0x000b, 0x8010, 0x0008, 0x0002, - 0x0000, 0x027a, 0x000b, 0x3a47, 0x0002, 0x0d40, 0x000b, 0x8010, - 0x0008, 0x0006, 0x0008, 0x027a, 0x000b, 0x8074, 0x0000, 0xf000, - 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x021b, 0x000c, 0x0231, - 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, 0x8010, 0x0008, 0x000c, - 0x0008, 0x021b, 0x000c, 0x000a, 0x000b, 0x8074, 0x0000, 0xf080, - 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, 0x2e4d, - 0x0002, 0x2e4d, 0x0002, 0x0a8d, 0x000b, 0x8054, 0x0008, 0x0019, - 0x0000, 0x000a, 0x000b, 0x8054, 0x0008, 0x0009, 0x0008, 0x000a, - 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x026b, 0x000b, 0x808c, - 0x0008, 0x0000, 0x0008, 0x4447, 0x0002, 0x0ab9, 0x0003, 0xc0c0, - 0x0001, 0x00ff, 0x0008, 0xffe0, 0x0009, 0x00ff, 0x0008, 0x0e90, - 0x0003, 0xc1e0, 0x0001, 0xffff, 0x0008, 0x0e90, 0x0003, 0x8010, - 0x0008, 0x0013, 0x0000, 0x021b, 0x000c, 0x8074, 0x0000, 0x0202, - 0x0008, 0x000a, 0x000b, 0x3a40, 0x000a, 0x0eb6, 0x000b, 0x8074, - 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe, 0x0000, 0x8072, - 0x0000, 0x8000, 0x0000, 0x43e0, 0x0001, 0x0eb4, 0x0003, 0x42fe, - 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x00e0, 0x0009, 0x0a90, - 0x000b, 0x0d08, 0x0008, 0x0309, 0x000b, 0x8072, 0x0000, 0x8000, - 0x0000, 0x000a, 0x000b, 0x038d, 0x0004, 0x808c, 0x0008, 0x0001, - 0x0000, 0x04fe, 0x0008, 0x3370, 0x0003, 0x0460, 0x0000, 0x8062, - 0x0008, 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x46c3, - 0x0003, 0x0004, 0x0000, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f00, - 0x0000, 0x80e0, 0x0001, 0x0004, 0x0000, 0x0add, 0x000b, 0x80e0, - 0x0001, 0x0005, 0x0008, 0x0add, 0x000b, 0x80e0, 0x0001, 0x0006, - 0x0008, 0x0add, 0x000b, 0x82c0, 0x0001, 0xff00, 0x0008, 0x7f04, - 0x0008, 0x82e0, 0x0009, 0x0600, 0x0008, 0x0add, 0x000b, 0x82e0, - 0x0009, 0x0500, 0x0008, 0x0add, 0x000b, 0x82e0, 0x0009, 0x0400, - 0x0000, 0x0f70, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, - 0x0009, 0x1000, 0x0000, 0x0b09, 0x0003, 0x037e, 0x0004, 0x3941, - 0x0002, 0x0ae8, 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, - 0x000b, 0x0460, 0x0000, 0x80fe, 0x0008, 0x002b, 0x0008, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x46ee, 0x0003, 0x11fe, - 0x0000, 0x3304, 0x0003, 0x9180, 0x0001, 0x0002, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0609, - 0x0008, 0x46f8, 0x000b, 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, - 0x0008, 0x03e0, 0x0009, 0x0f01, 0x0003, 0x8072, 0x0000, 0x0400, - 0x0000, 0x0046, 0x0003, 0x9180, 0x0001, 0x0003, 0x0008, 0x02eb, - 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x8010, 0x0008, 0x0010, - 0x0000, 0x0361, 0x0003, 0x037e, 0x0004, 0x3941, 0x0002, 0x0b0f, - 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, 0x000b, 0x0346, - 0x000c, 0x11fe, 0x0000, 0x3717, 0x0003, 0x8072, 0x0000, 0x0400, - 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x0361, 0x0003, 0x8060, - 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x372c, 0x000b, 0x808c, - 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4722, 0x000b, 0x0060, - 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, 0x4206, - 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x472a, 0x0003, 0x0343, - 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, 0x0000, 0x8062, - 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x4733, - 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x4736, 0x000b, 0x42fe, - 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x8060, - 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x4742, 0x000b, 0x8072, - 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, 0x0000, 0x0400, - 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, 0x474b, - 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f51, 0x0003, 0x0d22, - 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, 0x1380, - 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, 0x4757, - 0x0003, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, 0x7f06, - 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, 0x475f, - 0x000b, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x2f44, - 0x000a, 0x2f44, 0x000a, 0x0e6b, 0x000b, 0x808a, 0x0008, 0x0003, - 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, - 0x0008, 0x5b6c, 0x0003, 0x8054, 0x0008, 0x0019, 0x0000, 0x000a, - 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, 0x0000, - 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x021b, 0x000c, 0x42fe, - 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, 0x0008, 0x021b, - 0x000c, 0x4310, 0x0008, 0x027a, 0x000b, 0x3941, 0x0002, 0x0b81, - 0x0003, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, 0x0008, 0x4000, - 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x021b, 0x000c, 0x0346, - 0x000c, 0x1110, 0x0000, 0x021b, 0x000c, 0x11fe, 0x0000, 0x3787, - 0x0003, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x7f00, - 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, 0x0009, 0x0bb2, - 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, 0x7f62, - 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, 0x0000, 0x0809, - 0x0000, 0x479c, 0x000b, 0x04fe, 0x0008, 0x33ab, 0x0003, 0x0460, - 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, 0x0211, - 0x0000, 0x47a4, 0x0003, 0x01fe, 0x0008, 0x00e0, 0x0009, 0x0fab, - 0x0003, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bb1, 0x0003, 0x0500, - 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, 0x0000, 0x0f95, - 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, 0x0008, 0x3e80, - 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, 0x0000, 0x7f62, - 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47ba, 0x0003, 0x8060, - 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, 0x0008, 0x7f60, + 0x0000, 0x0609, 0x0008, 0x46f8, 0x000b, 0x42fe, 0x0000, 0xffc0, + 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009, 0x0f01, 0x0003, 0x8072, + 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x9180, 0x0001, 0x0003, + 0x0008, 0x02eb, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x8010, + 0x0008, 0x0010, 0x0000, 0x0361, 0x0003, 0x037e, 0x0004, 0x3941, + 0x0002, 0x0b0f, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, + 0x000b, 0x0346, 0x000c, 0x11fe, 0x0000, 0x3717, 0x0003, 0x8072, + 0x0000, 0x0400, 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x0361, + 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x372c, + 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, + 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4722, + 0x000b, 0x0060, 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, + 0x0008, 0x4206, 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x472a, + 0x0003, 0x0343, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, + 0x0000, 0x8062, 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, + 0x0008, 0x4733, 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x4736, + 0x000b, 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, + 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x4742, + 0x000b, 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, + 0x0000, 0x0400, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, + 0x0000, 0x474b, 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f51, + 0x0003, 0x0d22, 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, + 0x0000, 0x1380, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, + 0x0008, 0x4757, 0x0003, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, + 0x0000, 0x7f06, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, + 0x0008, 0x475f, 0x000b, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, + 0x000b, 0x2f44, 0x000a, 0x2f44, 0x000a, 0x0e6b, 0x000b, 0x808a, + 0x0008, 0x0003, 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, + 0x0000, 0x3000, 0x0008, 0x5b6c, 0x0003, 0x8054, 0x0008, 0x0019, + 0x0000, 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, + 0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x021b, + 0x000c, 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, + 0x0008, 0x021b, 0x000c, 0x4310, 0x0008, 0x027a, 0x000b, 0x3941, + 0x0002, 0x0b81, 0x0003, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, + 0x0008, 0x4000, 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x021b, + 0x000c, 0x0346, 0x000c, 0x1110, 0x0000, 0x021b, 0x000c, 0x11fe, + 0x0000, 0x3787, 0x0003, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, + 0x0008, 0x7f00, 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, + 0x0009, 0x0bb2, 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, + 0x0000, 0x7f62, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, + 0x0000, 0x0809, 0x0000, 0x479c, 0x000b, 0x04fe, 0x0008, 0x33ab, + 0x0003, 0x0460, 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, + 0x0000, 0x0211, 0x0000, 0x47a4, 0x0003, 0x01fe, 0x0008, 0x00e0, + 0x0009, 0x0fab, 0x0003, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bb1, + 0x0003, 0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, + 0x0000, 0x0f95, 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, + 0x0008, 0x3e80, 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47ba, + 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, + 0x0008, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, - 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0xff80, - 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, - 0x0000, 0x47cc, 0x000b, 0x4000, 0x000f, 0x5ff4, 0xebed, 0x0001, - 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, - 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x4464 + 0x000a, 0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0809, 0x0000, 0x47cc, 0x000b, 0x4000, 0x000f, 0x5ff4, + 0xebed, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, + 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, + 0x8000, 0x74b9 }; #ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_length01 = 0xe9e8; +unsigned short fw2300ipx_length01 = 0xea02; #else -unsigned short risc_code_length01 = 0xe9e8; +unsigned short risc_code_length01 = 0xea02; #endif diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c index ebbb51ea6..70b6d75ed 100644 --- a/drivers/scsi/qla2xxx/ql2322.c +++ b/drivers/scsi/qla2xxx/ql2322.c @@ -105,3 +105,4 @@ module_exit(qla2322_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2322_fw.c b/drivers/scsi/qla2xxx/ql2322_fw.c index 796206533..a99e9632a 100644 --- a/drivers/scsi/qla2xxx/ql2322_fw.c +++ b/drivers/scsi/qla2xxx/ql2322_fw.c @@ -18,25 +18,25 @@ *************************************************************************/ /* - * Firmware Version 3.02.30 (07:55 Jun 16, 2004) + * Firmware Version 3.03.02 (16:54 Aug 10, 2004) */ #ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_version = 3*1024+2; +unsigned short fw2322ipx_version = 3*1024+3; #else -unsigned short risc_code_version = 3*1024+2; +unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2322ipx_version_str[] = {3, 2,30}; +unsigned char fw2322ipx_version_str[] = {3, 3, 2}; #else -unsigned char firmware_version[] = {3, 2,30}; +unsigned char firmware_version[] = {3, 3, 2}; #endif #ifdef UNIQUE_FW_NAME -#define fw2322ipx_VERSION_STRING "3.02.30" +#define fw2322ipx_VERSION_STRING "3.03.02" #else -#define FW_VERSION_STRING "3.02.30" +#define FW_VERSION_STRING "3.03.02" #endif #ifdef UNIQUE_FW_NAME @@ -50,12 +50,12 @@ unsigned short fw2322ipx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xdf52, 0x0000, 0x0003, 0x0002, 0x001e, + 0x0470, 0x0000, 0x0000, 0xdf8f, 0x0000, 0x0003, 0x0003, 0x0002, 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3032, 0x2e33, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x332e, 0x3033, 0x2e30, 0x3220, 0x2020, 0x2020, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, @@ -64,11 +64,11 @@ unsigned short risc_code01[] = { 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1cff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2ac3, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e55, 0x00f6, - 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x2067, 0x1170, - 0x2079, 0x0300, 0x080c, 0x207d, 0x2061, 0xe000, 0x080c, 0x2067, - 0x1128, 0x2079, 0x0380, 0x080c, 0x207d, 0x0060, 0x00fe, 0x7883, + 0x7883, 0x0004, 0x2089, 0x2ae3, 0x2051, 0x1800, 0x2a70, 0x20e1, + 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e62, 0x00f6, + 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x207f, 0x1170, + 0x2079, 0x0300, 0x080c, 0x2095, 0x2061, 0xe000, 0x080c, 0x207f, + 0x1128, 0x2079, 0x0380, 0x080c, 0x2095, 0x0060, 0x00fe, 0x7883, 0x4010, 0x7837, 0x4010, 0x7833, 0x0010, 0x2091, 0x5000, 0x2091, 0x4080, 0x0cf8, 0x00fe, 0x2029, 0x5600, 0x2031, 0xffff, 0x2039, 0x55dc, 0x2021, 0x0200, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, @@ -82,146 +82,146 @@ unsigned short risc_code01[] = { 0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, - 0x1dd8, 0x080c, 0x0f52, 0x080c, 0x6032, 0x080c, 0xab75, 0x080c, - 0x1109, 0x080c, 0x1333, 0x080c, 0x1bbd, 0x080c, 0x916f, 0x080c, - 0x0d0f, 0x080c, 0x108e, 0x080c, 0x3468, 0x080c, 0x77e0, 0x080c, - 0x6a8e, 0x080c, 0x88e7, 0x080c, 0x8548, 0x080c, 0x2258, 0x080c, - 0x7eb5, 0x080c, 0x2096, 0x080c, 0x21d4, 0x080c, 0x224d, 0x2091, + 0x1dd8, 0x080c, 0x0f5f, 0x080c, 0x6052, 0x080c, 0xab86, 0x080c, + 0x1116, 0x080c, 0x1340, 0x080c, 0x1bd5, 0x080c, 0x91a8, 0x080c, + 0x0d0f, 0x080c, 0x109b, 0x080c, 0x3488, 0x080c, 0x7803, 0x080c, + 0x6ab2, 0x080c, 0x891b, 0x080c, 0x857c, 0x080c, 0x2270, 0x080c, + 0x7ed9, 0x080c, 0x20ae, 0x080c, 0x21ec, 0x080c, 0x2265, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x0943, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0937, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11e1, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c, + 0xd084, 0x190c, 0x11ee, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c, 0x9084, 0x0030, 0x9086, 0x0000, 0x190c, 0x0d7d, 0x2071, 0x1800, - 0x7000, 0x908e, 0x0003, 0x1168, 0x080c, 0x4bce, 0x080c, 0x348f, - 0x080c, 0x7848, 0x080c, 0x6fc6, 0x080c, 0x89c5, 0x080c, 0x8571, + 0x7000, 0x908e, 0x0003, 0x1168, 0x080c, 0x4bee, 0x080c, 0x34af, + 0x080c, 0x786b, 0x080c, 0x6fea, 0x080c, 0x89f9, 0x080c, 0x85a5, 0x0c68, 0x000b, 0x0c88, 0x096d, 0x096e, 0x0b09, 0x096b, 0x0bc3, 0x0d0e, 0x0d0e, 0x0d0e, 0x080c, 0x0d7d, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0adc, 0x080c, - 0x0ea5, 0x080c, 0x74c8, 0x0150, 0x080c, 0x74eb, 0x15b0, 0x2079, - 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, 0x0478, 0x080c, 0x73f9, + 0x0eb2, 0x080c, 0x74ec, 0x0150, 0x080c, 0x750f, 0x15b0, 0x2079, + 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, 0x0478, 0x080c, 0x741d, 0x7000, 0x9086, 0x0001, 0x1904, 0x0adc, 0x7098, 0x9086, 0x0028, - 0x1904, 0x0adc, 0x080c, 0x8540, 0x080c, 0x8532, 0x2001, 0x0161, - 0x2003, 0x0001, 0x2079, 0x0100, 0x2011, 0xffff, 0x080c, 0x2a63, - 0x7a28, 0x9295, 0x5e2c, 0x7a2a, 0x2011, 0x733e, 0x080c, 0x861d, - 0x2011, 0x7331, 0x080c, 0x8729, 0x2011, 0x5e89, 0x080c, 0x861d, - 0x2011, 0x8030, 0x901e, 0x7396, 0x04d0, 0x080c, 0x5736, 0x2079, - 0x0100, 0x7844, 0x9005, 0x1904, 0x0adc, 0x2011, 0x5e89, 0x080c, - 0x861d, 0x2011, 0x733e, 0x080c, 0x861d, 0x2011, 0x7331, 0x080c, - 0x8729, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, + 0x1904, 0x0adc, 0x080c, 0x8574, 0x080c, 0x8566, 0x2001, 0x0161, + 0x2003, 0x0001, 0x2079, 0x0100, 0x2011, 0xffff, 0x080c, 0x2a83, + 0x7a28, 0x9295, 0x5e2c, 0x7a2a, 0x2011, 0x7362, 0x080c, 0x8651, + 0x2011, 0x7355, 0x080c, 0x875d, 0x2011, 0x5ea9, 0x080c, 0x8651, + 0x2011, 0x8030, 0x901e, 0x7396, 0x04d0, 0x080c, 0x5756, 0x2079, + 0x0100, 0x7844, 0x9005, 0x1904, 0x0adc, 0x2011, 0x5ea9, 0x080c, + 0x8651, 0x2011, 0x7362, 0x080c, 0x8651, 0x2011, 0x7355, 0x080c, + 0x875d, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, 0x19a5, 0x2004, 0x9005, 0x1140, - 0x00c6, 0x2061, 0x0100, 0x080c, 0x5fda, 0x00ce, 0x0804, 0x0adc, - 0x780f, 0x006b, 0x7a28, 0x080c, 0x74d0, 0x0118, 0x9295, 0x5e2c, + 0x00c6, 0x2061, 0x0100, 0x080c, 0x5ffa, 0x00ce, 0x0804, 0x0adc, + 0x780f, 0x006b, 0x7a28, 0x080c, 0x74f4, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, - 0x19a6, 0x2003, 0x0001, 0x080c, 0x292f, 0x080c, 0x4b09, 0x7248, + 0x19a6, 0x2003, 0x0001, 0x080c, 0x294b, 0x080c, 0x4b29, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, - 0x2001, 0x0390, 0x2003, 0x0400, 0x080c, 0xa888, 0x080c, 0xa055, - 0x2011, 0x0004, 0x080c, 0xc842, 0x080c, 0xa8a4, 0x080c, 0x6916, - 0x080c, 0x74c8, 0x1120, 0x080c, 0x2990, 0x0600, 0x0420, 0x080c, - 0x5fe1, 0x0140, 0x7097, 0x0001, 0x70d3, 0x0000, 0x080c, 0x5903, - 0x0804, 0x0adc, 0x080c, 0x56d5, 0xd094, 0x01a8, 0x2001, 0x0390, + 0x2001, 0x0390, 0x2003, 0x0400, 0x080c, 0xa899, 0x080c, 0xa08e, + 0x2011, 0x0004, 0x080c, 0xc875, 0x080c, 0xa8b5, 0x080c, 0x693a, + 0x080c, 0x74ec, 0x1120, 0x080c, 0x29ac, 0x0600, 0x0420, 0x080c, + 0x6001, 0x0140, 0x7097, 0x0001, 0x70d3, 0x0000, 0x080c, 0x5923, + 0x0804, 0x0adc, 0x080c, 0x56f5, 0xd094, 0x01a8, 0x2001, 0x0390, 0x2003, 0x0404, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, - 0x56d9, 0xd0d4, 0x1118, 0x080c, 0x2990, 0x1270, 0x2011, 0x180c, - 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x56d9, 0xd0d4, 0x1db8, 0x2011, + 0x56f9, 0xd0d4, 0x1118, 0x080c, 0x29ac, 0x1270, 0x2011, 0x180c, + 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x56f9, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x2012, 0x080c, 0x6a62, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, - 0x2012, 0x080c, 0x6a28, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, - 0x707f, 0x0000, 0x080c, 0x74c8, 0x1130, 0x70b0, 0x9005, 0x1168, - 0x080c, 0xcc9e, 0x0050, 0x080c, 0xcc9e, 0x70dc, 0xd09c, 0x1128, - 0x70b0, 0x9005, 0x0110, 0x080c, 0x5fb7, 0x70e7, 0x0000, 0x70e3, - 0x0000, 0x70a7, 0x0000, 0x080c, 0x2998, 0x0228, 0x2011, 0x0101, - 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x74c8, 0x1178, 0x9016, - 0x0016, 0x080c, 0x272c, 0x2019, 0x196c, 0x211a, 0x001e, 0x705f, + 0x2012, 0x080c, 0x6a86, 0x1128, 0xd0a4, 0x0118, 0x2204, 0xc0fd, + 0x2012, 0x080c, 0x6a4c, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, + 0x707f, 0x0000, 0x080c, 0x74ec, 0x1130, 0x70b0, 0x9005, 0x1168, + 0x080c, 0xccd1, 0x0050, 0x080c, 0xccd1, 0x70dc, 0xd09c, 0x1128, + 0x70b0, 0x9005, 0x0110, 0x080c, 0x5fd7, 0x70e7, 0x0000, 0x70e3, + 0x0000, 0x70a7, 0x0000, 0x080c, 0x29b4, 0x0228, 0x2011, 0x0101, + 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x74ec, 0x1178, 0x9016, + 0x0016, 0x080c, 0x2748, 0x2019, 0x196c, 0x211a, 0x001e, 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019, 0x196c, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, 0xc295, - 0x72de, 0x080c, 0x74c8, 0x0118, 0x9296, 0x0004, 0x0518, 0x2011, - 0x0001, 0x080c, 0xc842, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, - 0x0002, 0x00fe, 0x080c, 0x2fc0, 0x080c, 0xa888, 0x2011, 0x0005, - 0x080c, 0xa1b1, 0x080c, 0xa8a4, 0x080c, 0x74c8, 0x0148, 0x00c6, - 0x2061, 0x0100, 0x0016, 0x080c, 0x272c, 0x61e2, 0x001e, 0x00ce, + 0x72de, 0x080c, 0x74ec, 0x0118, 0x9296, 0x0004, 0x0518, 0x2011, + 0x0001, 0x080c, 0xc875, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, + 0x0002, 0x00fe, 0x080c, 0x2fe0, 0x080c, 0xa899, 0x2011, 0x0005, + 0x080c, 0xa1be, 0x080c, 0xa8b5, 0x080c, 0x74ec, 0x0148, 0x00c6, + 0x2061, 0x0100, 0x0016, 0x080c, 0x2748, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x00e0, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, - 0x080c, 0xa888, 0x2011, 0x0005, 0x080c, 0xa1b1, 0x080c, 0xa8a4, - 0x080c, 0x74c8, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, - 0x272c, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, - 0x00b6, 0x080c, 0x74c8, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, - 0x0782, 0x080c, 0x74c8, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, + 0x080c, 0xa899, 0x2011, 0x0005, 0x080c, 0xa1be, 0x080c, 0xa8b5, + 0x080c, 0x74ec, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, + 0x2748, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, + 0x00b6, 0x080c, 0x74ec, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, + 0x0782, 0x080c, 0x74ec, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, - 0xd0bc, 0x090c, 0x32f8, 0x8108, 0x1f04, 0x0af0, 0x707f, 0x0000, + 0xd0bc, 0x090c, 0x3318, 0x8108, 0x1f04, 0x0af0, 0x707f, 0x0000, 0x7080, 0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, - 0x1904, 0x0bc0, 0x70ac, 0x9086, 0xffff, 0x0120, 0x080c, 0x2fc0, + 0x1904, 0x0bc0, 0x70ac, 0x9086, 0xffff, 0x0120, 0x080c, 0x2fe0, 0x0804, 0x0bc0, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0538, 0xd084, 0x0528, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0xd08c, - 0x01e8, 0x080c, 0x3361, 0x11b0, 0x70e0, 0x9086, 0xffff, 0x0190, - 0x080c, 0x3155, 0x70dc, 0xd094, 0x1904, 0x0bc0, 0x2011, 0x0001, - 0x080c, 0xcf51, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x318f, + 0x01e8, 0x080c, 0x3381, 0x11b0, 0x70e0, 0x9086, 0xffff, 0x0190, + 0x080c, 0x3175, 0x70dc, 0xd094, 0x1904, 0x0bc0, 0x2011, 0x0001, + 0x080c, 0xcf84, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x31af, 0x0804, 0x0bc0, 0x70e4, 0x9005, 0x1904, 0x0bc0, 0x70a8, 0x9005, 0x1904, 0x0bc0, 0x70dc, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0bc0, - 0x080c, 0x6a28, 0x1904, 0x0bc0, 0x080c, 0x6a7b, 0x1904, 0x0bc0, - 0x080c, 0x6a62, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x080c, 0x6620, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, + 0x080c, 0x6a4c, 0x1904, 0x0bc0, 0x080c, 0x6a9f, 0x1904, 0x0bc0, + 0x080c, 0x6a86, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x6644, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b60, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0bc0, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, - 0x000e, 0x2011, 0x19b2, 0x080c, 0x0fc2, 0x2011, 0x19cc, 0x080c, - 0x0fc2, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x70af, 0xffff, - 0x080c, 0x0e79, 0x9006, 0x080c, 0x25b9, 0x080c, 0x3361, 0x0118, - 0x080c, 0x4ca6, 0x0050, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, - 0x0006, 0x080c, 0x4cc0, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x74eb, 0x0150, 0x080c, 0x74c8, 0x7828, 0x0118, 0x9084, - 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x080c, 0xa888, + 0x000e, 0x2011, 0x19b2, 0x080c, 0x0fcf, 0x2011, 0x19cc, 0x080c, + 0x0fcf, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x70af, 0xffff, + 0x080c, 0x0e86, 0x9006, 0x080c, 0x25d5, 0x080c, 0x3381, 0x0118, + 0x080c, 0x4cc6, 0x0050, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, + 0x0006, 0x080c, 0x4ce0, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, + 0x080c, 0x750f, 0x0150, 0x080c, 0x74ec, 0x7828, 0x0118, 0x9084, + 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x080c, 0xa899, 0x2001, 0x19e7, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, - 0x080c, 0xa1b1, 0x2011, 0x0000, 0x080c, 0xa1bb, 0x080c, 0xa8a4, + 0x080c, 0xa1be, 0x2011, 0x0000, 0x080c, 0xa1c8, 0x080c, 0xa8b5, 0x012e, 0x00be, 0x0005, 0x0016, 0x0026, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, - 0x2009, 0x00f7, 0x080c, 0x5fa0, 0x7940, 0x918c, 0x0010, 0x7942, - 0x7924, 0xd1b4, 0x0120, 0x2011, 0x0040, 0x080c, 0x2a63, 0xd19c, - 0x0120, 0x2011, 0x0008, 0x080c, 0x2a63, 0x0006, 0x0036, 0x0156, - 0x0000, 0x2001, 0x19a6, 0x2004, 0x9005, 0x1518, 0x080c, 0x29f7, - 0x1148, 0x2001, 0x0001, 0x080c, 0x295e, 0x2001, 0x0001, 0x080c, - 0x2941, 0x00b8, 0x080c, 0x29ff, 0x1138, 0x9006, 0x080c, 0x295e, - 0x9006, 0x080c, 0x2941, 0x0068, 0x080c, 0x2a07, 0x1d50, 0x2001, - 0x1997, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x2758, 0x0804, - 0x0cc1, 0x080c, 0x2a86, 0x080c, 0x2ab9, 0x20a9, 0x003a, 0x1d04, - 0x0c17, 0x080c, 0x8709, 0x1f04, 0x0c17, 0x080c, 0x74d9, 0x0148, - 0x080c, 0x74eb, 0x1118, 0x080c, 0x77db, 0x0050, 0x080c, 0x74d0, - 0x0dd0, 0x080c, 0x77d6, 0x080c, 0x77cc, 0x080c, 0x73f9, 0x0020, - 0x2009, 0x00f8, 0x080c, 0x5fa0, 0x7850, 0xc0e5, 0x7852, 0x080c, - 0x74c8, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, - 0x2019, 0xea60, 0x0d0c, 0x8709, 0x7820, 0xd09c, 0x15a0, 0x080c, - 0x74c8, 0x0904, 0x0ca3, 0x7824, 0xd0ac, 0x1904, 0x0cc6, 0x080c, - 0x74eb, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, - 0x2011, 0x1800, 0x080c, 0x2a63, 0x080c, 0x2a0f, 0x7824, 0x9084, + 0x2009, 0x00f7, 0x080c, 0x5fc0, 0x7940, 0x918c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0120, 0x2011, 0x0040, 0x080c, 0x2a83, 0xd19c, + 0x0120, 0x2011, 0x0008, 0x080c, 0x2a83, 0x0006, 0x0036, 0x0156, + 0x0000, 0x2001, 0x19a6, 0x2004, 0x9005, 0x1518, 0x080c, 0x2a17, + 0x1148, 0x2001, 0x0001, 0x080c, 0x297a, 0x2001, 0x0001, 0x080c, + 0x295d, 0x00b8, 0x080c, 0x2a1f, 0x1138, 0x9006, 0x080c, 0x297a, + 0x9006, 0x080c, 0x295d, 0x0068, 0x080c, 0x2a27, 0x1d50, 0x2001, + 0x1997, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x2774, 0x0804, + 0x0cc1, 0x080c, 0x2aa6, 0x080c, 0x2ad9, 0x20a9, 0x003a, 0x1d04, + 0x0c17, 0x080c, 0x873d, 0x1f04, 0x0c17, 0x080c, 0x74fd, 0x0148, + 0x080c, 0x750f, 0x1118, 0x080c, 0x77fe, 0x0050, 0x080c, 0x74f4, + 0x0dd0, 0x080c, 0x77f9, 0x080c, 0x77ef, 0x080c, 0x741d, 0x0020, + 0x2009, 0x00f8, 0x080c, 0x5fc0, 0x7850, 0xc0e5, 0x7852, 0x080c, + 0x74ec, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, + 0x2019, 0xea60, 0x0d0c, 0x873d, 0x7820, 0xd09c, 0x15a0, 0x080c, + 0x74ec, 0x0904, 0x0ca3, 0x7824, 0xd0ac, 0x1904, 0x0cc6, 0x080c, + 0x750f, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, + 0x2011, 0x1800, 0x080c, 0x2a83, 0x080c, 0x2a2f, 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0ce9, 0x8421, 0x1160, 0x1d04, - 0x0c73, 0x080c, 0x8709, 0x080c, 0x77d6, 0x080c, 0x77cc, 0x7003, + 0x0c73, 0x080c, 0x873d, 0x080c, 0x77f9, 0x080c, 0x77ef, 0x7003, 0x0001, 0x0804, 0x0cc6, 0x8319, 0x1928, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0ce9, 0x1d04, 0x0c89, 0x080c, - 0x8709, 0x2009, 0x199a, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, - 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x2a63, 0x20a9, - 0x0002, 0x080c, 0x29f0, 0x7924, 0x080c, 0x2a0f, 0xd19c, 0x0110, - 0x080c, 0x292f, 0x00f0, 0x080c, 0x74d9, 0x1140, 0x94a2, 0x03e8, - 0x1128, 0x080c, 0x749c, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, - 0x080c, 0x2a63, 0x080c, 0x2a0f, 0x7824, 0x080c, 0x74e2, 0x0110, + 0x873d, 0x2009, 0x199a, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, + 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x2a83, 0x20a9, + 0x0002, 0x080c, 0x2a10, 0x7924, 0x080c, 0x2a2f, 0xd19c, 0x0110, + 0x080c, 0x294b, 0x00f0, 0x080c, 0x74fd, 0x1140, 0x94a2, 0x03e8, + 0x1128, 0x080c, 0x74c0, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, + 0x080c, 0x2a83, 0x080c, 0x2a2f, 0x7824, 0x080c, 0x7506, 0x0110, 0xd0ac, 0x1160, 0x9084, 0x1800, 0x0904, 0x0c7b, 0x7003, 0x0001, - 0x0028, 0x2001, 0x0001, 0x080c, 0x25b9, 0x00a0, 0x7850, 0xc0e4, + 0x0028, 0x2001, 0x0001, 0x080c, 0x25d5, 0x00a0, 0x7850, 0xc0e4, 0x7852, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, - 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x2a63, 0x7828, 0x9085, + 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x2a83, 0x7828, 0x9085, 0x0028, 0x782a, 0x2001, 0x19a6, 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x8709, 0x015e, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x873d, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x348f, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19aa, 0x2063, 0x0003, 0x6007, 0x0002, 0x600b, 0x001e, + 0x0001, 0x1110, 0x080c, 0x34af, 0x00ee, 0x0005, 0x0005, 0x2a70, + 0x2061, 0x19aa, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0002, 0x600f, 0x0137, 0x2001, 0x197b, 0x900e, 0x2102, 0x7196, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, - 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xcc9e, 0x70ef, + 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xccd1, 0x70ef, 0x00c0, 0x2061, 0x196b, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, 0x07d0, 0x2061, 0x1973, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, 0x1988, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6620, + 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6644, 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, @@ -236,447 +236,450 @@ unsigned short risc_code01[] = { 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x1b32, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x1a79, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, - 0x8318, 0x1f04, 0x0dcc, 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, - 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x0180, 0x2001, 0x1a21, 0x2004, 0x9005, 0x0128, - 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, - 0x0002, 0x2003, 0x1001, 0x080c, 0x56e4, 0x1170, 0x080c, 0x0f13, - 0x0110, 0x080c, 0x0e66, 0x080c, 0x56e4, 0x1130, 0x2071, 0x1800, - 0x2011, 0x8000, 0x080c, 0x0f27, 0x0c70, 0x0005, 0x2001, 0x0382, - 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, - 0x080c, 0xa879, 0x2079, 0x0380, 0x2069, 0x1b03, 0x7818, 0x6802, - 0x781c, 0x6806, 0x7840, 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, - 0x2019, 0x1b0e, 0x9016, 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, - 0x8210, 0x8318, 0x8210, 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, - 0x6a2a, 0x7830, 0x681a, 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, - 0x6826, 0x7803, 0x0000, 0x2069, 0x1ac3, 0x901e, 0x20a9, 0x0020, - 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e40, 0x2069, - 0x1ae3, 0x2019, 0x00b0, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, - 0x8d68, 0x8318, 0x1f04, 0x0e4d, 0x0005, 0x918c, 0x03ff, 0x2001, - 0x0003, 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, - 0x918d, 0x6400, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, - 0x2011, 0x0080, 0x080c, 0x0f05, 0x20a9, 0x0900, 0x080c, 0x0f3b, - 0x2011, 0x0040, 0x080c, 0x0f05, 0x20a9, 0x0900, 0x080c, 0x0f3b, - 0x0c78, 0x0026, 0x080c, 0x0f13, 0x1188, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, - 0x2011, 0x1b47, 0x080c, 0x0f27, 0x002e, 0x0005, 0x2011, 0x010e, - 0x2214, 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, - 0x0010, 0x2011, 0x6840, 0xd0e4, 0x70f3, 0x0000, 0x1128, 0x70f3, - 0x0fa0, 0x080c, 0x0f18, 0x002e, 0x0005, 0x0026, 0x080c, 0x0f13, - 0x0148, 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, - 0x080c, 0x0f18, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x080c, - 0x0f13, 0x1130, 0x2011, 0x8040, 0x080c, 0x0f27, 0x002e, 0x0005, - 0x080c, 0x2a07, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, - 0x080c, 0x0f18, 0x002e, 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, - 0x1800, 0xd0b4, 0x70ec, 0x71e8, 0x1118, 0xc0e4, 0xc1f4, 0x0050, - 0x0006, 0x3b00, 0x9084, 0xff3e, 0x20d8, 0x000e, 0x70f3, 0x0000, - 0xc0e5, 0xc1f5, 0x0099, 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x1800, 0xd0e4, 0x70ec, 0x1110, 0xc0dc, 0x0008, 0xc0dd, - 0x0016, 0x71e8, 0x0019, 0x001e, 0x00ee, 0x0005, 0x70ee, 0x71ea, - 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0ecb, 0x0ea5, 0x0ea5, - 0x0e79, 0x0eb4, 0x0ea5, 0x0ea5, 0x0eb4, 0xc284, 0x0016, 0x3b08, - 0x3a00, 0x9104, 0x918d, 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, - 0x20d0, 0x001e, 0x0005, 0x2001, 0x183b, 0x2004, 0xd0dc, 0x0005, - 0x9e86, 0x1800, 0x190c, 0x0d7d, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, - 0x72ee, 0xd0e4, 0x1118, 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, - 0x1800, 0x190c, 0x0d7d, 0x70e8, 0xd0f4, 0x0108, 0xc2f5, 0x72ea, - 0xd0f4, 0x1140, 0x9284, 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, - 0x00c1, 0x0861, 0x0005, 0x1d04, 0x0f3b, 0x2091, 0x6000, 0x1f04, - 0x0f3b, 0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, - 0xffc0, 0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, - 0x000e, 0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, 0x188d, - 0x600b, 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, - 0x2009, 0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, - 0x5555, 0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, - 0x9306, 0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, - 0x0c98, 0x000e, 0x200f, 0x2001, 0x189d, 0x928a, 0x000e, 0x1638, - 0x928a, 0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, - 0x9006, 0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, - 0x6003, 0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, - 0x0001, 0x20e8, 0x21a0, 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, - 0x1da0, 0x002e, 0x009e, 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, - 0x000e, 0x08e8, 0x0016, 0x0026, 0x0096, 0x3348, 0x080c, 0x0f42, - 0x2100, 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, - 0x3518, 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, - 0x003e, 0x0005, 0x20e9, 0x0001, 0x71b8, 0x81ff, 0x11c0, 0x9006, - 0x2009, 0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, - 0x2009, 0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, - 0x707c, 0x8007, 0x7180, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, - 0x000c, 0x23a0, 0x900e, 0x080c, 0x0d5d, 0x2001, 0x0000, 0x810f, - 0x20a9, 0x0002, 0x4001, 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, - 0x0000, 0x0006, 0x080c, 0x106c, 0x009e, 0x0cb0, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x10e5, 0x090c, 0x0d7d, 0x00ee, 0x0005, - 0x0086, 0x00e6, 0x0006, 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, - 0x00c9, 0x2071, 0x1800, 0x73c0, 0x702c, 0x9016, 0x9045, 0x0158, - 0x8210, 0x9906, 0x090c, 0x0d7d, 0x2300, 0x9202, 0x0120, 0x1a0c, - 0x0d7d, 0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, - 0x008e, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1910, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, - 0x9906, 0x090c, 0x0d7d, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, - 0x008e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, - 0x70c0, 0x8001, 0x0270, 0x70c2, 0x702c, 0x2048, 0x9085, 0x0001, - 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, - 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x70c0, 0x90ca, 0x0020, 0x0268, 0x8001, 0x70c2, 0x702c, - 0x2048, 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x0016, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, - 0xffc0, 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, - 0x70c2, 0x080c, 0x8532, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9026, 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, - 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, - 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7000, - 0x9005, 0x11a0, 0x2001, 0x0558, 0xa802, 0x2048, 0x2009, 0x5600, - 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, - 0x0800, 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, - 0x7104, 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, - 0x831b, 0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, - 0xa802, 0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, - 0x2848, 0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, - 0x2071, 0x1800, 0x74be, 0x74c2, 0x0005, 0x00e6, 0x0016, 0x9984, - 0xfc00, 0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, - 0x9982, 0x0440, 0x0278, 0x9982, 0x0558, 0x0288, 0x9982, 0x0800, - 0x1270, 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x188d, 0x7010, - 0x9902, 0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, - 0x0cd8, 0x00e6, 0x2071, 0x1a20, 0x7007, 0x0000, 0x9006, 0x701e, - 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, - 0x2071, 0x0080, 0x9006, 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, - 0x1f04, 0x111f, 0x702b, 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, - 0x7022, 0x1f04, 0x1128, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a20, 0x701c, - 0x9088, 0x1a2a, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, - 0x9106, 0x090c, 0x0d7d, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, - 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00e6, 0x2071, 0x1a20, 0x7004, 0x9005, 0x1128, 0x00f6, - 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, - 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1171, - 0x12f4, 0x116f, 0x116f, 0x12e8, 0x12e8, 0x12e8, 0x12e8, 0x080c, - 0x0d7d, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, - 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, - 0x1a2a, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, - 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, - 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, - 0xa868, 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, - 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, - 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, - 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, - 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, - 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, - 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, - 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, - 0x0005, 0x2009, 0x1a20, 0x2104, 0xc095, 0x200a, 0x080c, 0x114e, - 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a20, 0x00f6, 0x2079, 0x0080, - 0x792c, 0xd1bc, 0x190c, 0x0d76, 0x782b, 0x0002, 0xd1fc, 0x0120, - 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, - 0x115f, 0x1207, 0x123b, 0x1313, 0x0d7d, 0x132e, 0x0d7d, 0x918c, - 0x0700, 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, - 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, - 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, - 0x9005, 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11a4, - 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, - 0x0000, 0x080c, 0x115f, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, - 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, - 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11b9, 0x0005, - 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, - 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, - 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, - 0x0000, 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, 0x2004, - 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, - 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, - 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x114e, - 0x0005, 0x00de, 0x009e, 0x080c, 0x114e, 0x0005, 0xa8a8, 0xd08c, - 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0d7d, 0xa06c, 0x908e, - 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, - 0x080c, 0x6d6f, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, - 0x106c, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d7d, - 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, - 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, - 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x112f, - 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6d6f, 0x000e, - 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, - 0xabdf, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, - 0x080c, 0x106c, 0x7007, 0x0000, 0x080c, 0x114e, 0x00ae, 0x0005, - 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, - 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192e, 0x204c, - 0xa87c, 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, - 0xa898, 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, - 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, - 0x012e, 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, - 0x0040, 0x0096, 0x2001, 0x192e, 0x204c, 0xaa7c, 0x009e, 0x080c, - 0x8bfd, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, - 0x8a70, 0x7007, 0x0000, 0x080c, 0x115f, 0x0005, 0x7007, 0x0000, - 0x080c, 0x115f, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, - 0x2071, 0x1a6a, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, - 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, - 0x7803, 0x0000, 0x2001, 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, - 0x0118, 0x7820, 0x04e9, 0x0cd0, 0x2001, 0x1a6b, 0x2003, 0x0000, - 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, - 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a79, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, 0x0200, 0x2004, - 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a79, 0x602f, 0x1ddc, - 0x2001, 0x181a, 0x2004, 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1e62, - 0x602b, 0x1ab9, 0x6007, 0x1a99, 0x2061, 0x1a99, 0x60af, 0x193c, - 0x2001, 0x1927, 0x2004, 0x60ba, 0x783f, 0x3368, 0x00ce, 0x0005, - 0x9086, 0x000d, 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, - 0x2010, 0x080c, 0xc820, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, - 0x1158, 0x0016, 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, - 0x004c, 0x080c, 0xac7c, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, - 0x2200, 0x7908, 0x9184, 0x0070, 0x190c, 0x0d76, 0xd19c, 0x05a0, - 0x7820, 0x908c, 0xf000, 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, - 0x1550, 0x6000, 0x9086, 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, - 0xa87a, 0xa867, 0x0103, 0x080c, 0x6b91, 0x00b6, 0x6010, 0x2058, - 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x190c, 0x674b, - 0x00be, 0x6044, 0xd0fc, 0x190c, 0xa8b1, 0x080c, 0xac08, 0x7808, - 0xd09c, 0x19b0, 0x012e, 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d7d, - 0x002b, 0x012e, 0x0005, 0x04b0, 0x012e, 0x0005, 0x1412, 0x1438, - 0x1468, 0x146d, 0x1471, 0x1476, 0x149e, 0x14a2, 0x14b0, 0x14b4, - 0x1412, 0x1581, 0x1585, 0x15ea, 0x15f1, 0x1412, 0x15f2, 0x15f3, - 0x15fe, 0x1605, 0x1412, 0x1412, 0x1412, 0x1412, 0x1412, 0x1412, - 0x1412, 0x1478, 0x1412, 0x1440, 0x1465, 0x142c, 0x1412, 0x144c, - 0x1416, 0x1414, 0x080c, 0x0d7d, 0x080c, 0x0d76, 0x080c, 0x1610, - 0x2009, 0x1a78, 0x2104, 0x8000, 0x200a, 0x080c, 0x7f78, 0x080c, - 0x1ac2, 0x0005, 0x6044, 0xd0fc, 0x190c, 0xa8b1, 0x2009, 0x0055, - 0x080c, 0xac7c, 0x012e, 0x0005, 0x080c, 0x1610, 0x2060, 0x6044, - 0xd0fc, 0x190c, 0xa8b1, 0x2009, 0x0055, 0x080c, 0xac7c, 0x0005, - 0x2009, 0x0048, 0x080c, 0x1610, 0x2060, 0x080c, 0xac7c, 0x0005, - 0x2009, 0x0054, 0x080c, 0x1610, 0x2060, 0x6044, 0xd0fc, 0x190c, - 0xa8b1, 0x080c, 0xac7c, 0x0005, 0x080c, 0x1610, 0x2060, 0x0056, - 0x0066, 0x080c, 0x1610, 0x2028, 0x080c, 0x1610, 0x2030, 0x0036, - 0x0046, 0x2021, 0x0000, 0x2418, 0x2009, 0x0056, 0x080c, 0xac7c, - 0x004e, 0x003e, 0x006e, 0x005e, 0x0005, 0x080c, 0x1610, 0x0005, - 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, - 0x0005, 0x080c, 0x1610, 0x080c, 0x16d4, 0x0005, 0x080c, 0x0d7d, - 0x080c, 0x1610, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0xac7c, 0x2001, 0x015d, 0x2003, - 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, - 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, - 0x1615, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, - 0x7006, 0x0005, 0x080c, 0x1610, 0x2060, 0x6014, 0x0096, 0x2048, - 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0xac7c, 0x0005, - 0x080c, 0x1610, 0x080c, 0x0d7d, 0x080c, 0x1610, 0x080c, 0x156c, - 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0904, 0x151d, 0x7827, 0x0015, - 0x7828, 0x782b, 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, - 0x0050, 0x2003, 0x0020, 0x0804, 0x1523, 0x7004, 0x9005, 0x01c8, - 0x1188, 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, - 0x090c, 0x0d7d, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, - 0x0804, 0x1551, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1585, - 0x0005, 0x7827, 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, - 0x7928, 0x9106, 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, - 0x702c, 0xd0c4, 0x0140, 0x00ee, 0x080c, 0x1ac2, 0x080c, 0x1347, - 0x7803, 0x0001, 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, - 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, - 0xc09d, 0x7006, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1585, - 0x2001, 0x020d, 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, - 0x9065, 0x090c, 0x0d7d, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, - 0x0700, 0x01a8, 0x080c, 0x7f78, 0x080c, 0x1ac2, 0x080c, 0xc832, - 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, - 0xffff, 0xa880, 0xc0bd, 0xa882, 0x080c, 0xc430, 0x0005, 0x6020, - 0x9086, 0x0009, 0x1128, 0x2009, 0x004c, 0x080c, 0xac7c, 0x0048, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, - 0xcc33, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, - 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xe6ea, 0xd5a4, 0x1118, 0x080c, - 0x1615, 0x0005, 0x080c, 0x7f78, 0x080c, 0x1ac2, 0x0005, 0x781f, - 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, - 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, - 0x2001, 0x0016, 0x080c, 0x1686, 0x00fe, 0x007e, 0x006e, 0x001e, - 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, - 0x190c, 0x0d7d, 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, 0x7106, - 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, 0x1615, - 0x0005, 0x81ff, 0x190c, 0x0d7d, 0x0005, 0xc184, 0xd1b4, 0xc1b4, - 0x7106, 0x0016, 0x00e6, 0x15f0, 0x2071, 0x0200, 0x080c, 0x16c1, - 0x05c8, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, - 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, - 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x173e, 0x00fe, - 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x18c5, 0x00fe, 0x2009, 0x01f4, - 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, - 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x1615, 0x0040, 0x2001, - 0x020d, 0x2003, 0x0020, 0x080c, 0x1347, 0x7803, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, - 0x0461, 0x0ca8, 0x0429, 0x2060, 0x2009, 0x0053, 0x080c, 0xac7c, - 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, 0x00d1, 0x0006, 0x7004, - 0xc09d, 0x7006, 0x000e, 0x080c, 0x8f5a, 0x0005, 0x0089, 0x9005, - 0x0118, 0x080c, 0x8b5d, 0x0cd0, 0x0005, 0x2001, 0x0036, 0x2009, - 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, 0x080c, 0x1686, 0x0005, - 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, 0x156c, 0x00d6, - 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0510, 0x6804, 0x9005, - 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1528, - 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, 0x0841, 0x1268, 0x9188, - 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, 0x080c, 0x1678, - 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, - 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, - 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, 0x080c, 0x7f78, 0x080c, - 0x1ac2, 0x0090, 0x7827, 0x0015, 0x782b, 0x0000, 0x7827, 0x0018, - 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, - 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, - 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, 0x0015, 0x782b, 0x0000, - 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0005, - 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, 0x2001, 0x0030, 0x2c08, - 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, 0x0005, 0x00f6, 0x2079, - 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, - 0x080c, 0x13ae, 0x00ce, 0x002e, 0x001e, 0x000e, 0x0006, 0x7832, - 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059, 0x1118, 0x000e, 0x00fe, - 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d7d, - 0x2009, 0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, - 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, - 0x0c79, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, - 0x0d7d, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, - 0xd1bc, 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, - 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, - 0x0c41, 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, 0x0904, 0x1733, - 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x1733, - 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, - 0x0039, 0x1904, 0x1733, 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, - 0x080c, 0x7ed0, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, - 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, - 0xcc0e, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, - 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, 0x1e82, - 0x1190, 0x080c, 0x1920, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, - 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, - 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, - 0x00ee, 0x080c, 0x1615, 0x0005, 0x080c, 0x0d7d, 0x2cf0, 0x0126, - 0x2091, 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, - 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1e62, - 0x2165, 0x0002, 0x1769, 0x17d7, 0x1769, 0x1769, 0x176d, 0x17b8, - 0x1769, 0x178d, 0x1762, 0x17ce, 0x1769, 0x1769, 0x1772, 0x18c3, - 0x17a1, 0x1797, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, - 0x17ce, 0x9085, 0x0001, 0x0804, 0x18ba, 0xa87c, 0xd0ac, 0x0dc8, - 0x0804, 0x17de, 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x1849, 0xa898, - 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, 0x3e00, - 0x9080, 0x0008, 0x2004, 0x9080, 0x9123, 0x2005, 0x9005, 0x090c, - 0x0d7d, 0x2004, 0xa8ae, 0x0804, 0x18a2, 0xa87c, 0xd0bc, 0x09c8, - 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x17de, 0xa87c, - 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, - 0x1849, 0xa87c, 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, - 0xa804, 0x9045, 0x090c, 0x0d7d, 0xa164, 0xa91a, 0x91ec, 0x000f, - 0x9d80, 0x1e62, 0x2065, 0xa888, 0xd19c, 0x1904, 0x1849, 0x0430, - 0xa87c, 0xd0ac, 0x0904, 0x1769, 0xa804, 0x9045, 0x090c, 0x0d7d, - 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1e62, 0x2065, 0x9006, - 0xa842, 0xa83e, 0xd19c, 0x1904, 0x1849, 0x0080, 0xa87c, 0xd0ac, - 0x0904, 0x1769, 0x9006, 0xa842, 0xa83e, 0x0804, 0x1849, 0xa87c, - 0xd0ac, 0x0904, 0x1769, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, - 0x0036, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1801, 0x1801, - 0x1803, 0x1801, 0x1801, 0x1801, 0x180d, 0x1801, 0x1801, 0x1801, - 0x1817, 0x1801, 0x1801, 0x1801, 0x1821, 0x1801, 0x1801, 0x1801, - 0x182b, 0x1801, 0x1801, 0x1801, 0x1835, 0x1801, 0x1801, 0x1801, - 0x183f, 0x080c, 0x0d7d, 0xa574, 0xa478, 0x9d86, 0x0024, 0x0904, - 0x1777, 0xa37c, 0xa280, 0x0804, 0x18a2, 0xa584, 0xa488, 0x9d86, - 0x0024, 0x0904, 0x1777, 0xa38c, 0xa290, 0x0804, 0x18a2, 0xa594, - 0xa498, 0x9d86, 0x0024, 0x0904, 0x1777, 0xa39c, 0xa2a0, 0x0804, - 0x18a2, 0xa5a4, 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x1777, 0xa3ac, - 0xa2b0, 0x0804, 0x18a2, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, 0x0904, - 0x1777, 0xa3bc, 0xa2c0, 0x0804, 0x18a2, 0xa5c4, 0xa4c8, 0x9d86, - 0x0024, 0x0904, 0x1777, 0xa3cc, 0xa2d0, 0x0804, 0x18a2, 0xa5d4, - 0xa4d8, 0x9d86, 0x0024, 0x0904, 0x1777, 0xa3dc, 0xa2e0, 0x0804, - 0x18a2, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, - 0x0002, 0x186c, 0x186a, 0x186a, 0x186a, 0x186a, 0x186a, 0x1877, - 0x186a, 0x186a, 0x186a, 0x186a, 0x186a, 0x1882, 0x186a, 0x186a, - 0x186a, 0x186a, 0x186a, 0x188d, 0x186a, 0x186a, 0x186a, 0x186a, - 0x186a, 0x1898, 0x080c, 0x0d7d, 0xa56c, 0xa470, 0xa774, 0xa678, - 0x9d86, 0x002c, 0x0904, 0x1777, 0xa37c, 0xa280, 0x0458, 0xa584, - 0xa488, 0xa78c, 0xa690, 0x9d86, 0x002c, 0x0904, 0x1777, 0xa394, - 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x002c, - 0x0904, 0x1777, 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0x9d86, 0x002c, 0x0904, 0x1777, 0xa3c4, 0xa2c8, 0x0050, - 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, 0x1777, - 0xa3dc, 0xa2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, - 0xa988, 0x8c60, 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, - 0xa916, 0x1158, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, - 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, - 0x2c00, 0xa812, 0x0c78, 0x0804, 0x1769, 0x2ff0, 0x0126, 0x2091, - 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, - 0x1e5d, 0xa813, 0x1e5d, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, - 0xd0ac, 0x090c, 0x0d7d, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, - 0x0034, 0x1a0c, 0x0d7d, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, - 0xaae0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, - 0xaab0, 0xa836, 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0008, 0x1120, 0x8109, 0xa916, 0x0128, 0x0078, 0x918a, 0x0002, - 0xa916, 0x1158, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, - 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, - 0x0d7d, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1e62, - 0x2015, 0x82ff, 0x090c, 0x0d7d, 0xaa12, 0x2205, 0xa80a, 0x0c10, - 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a4a, - 0x1977, 0x1977, 0x1a4a, 0x1977, 0x1a44, 0x1a4a, 0x1977, 0x19e7, - 0x19e7, 0x19e7, 0x1a4a, 0x19e7, 0x1a4a, 0x1a41, 0x19e7, 0xc0fc, - 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a4c, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, - 0x1963, 0x1961, 0x1961, 0x1961, 0x1961, 0x1961, 0x1967, 0x1961, - 0x1961, 0x1961, 0x1961, 0x1961, 0x196b, 0x1961, 0x1961, 0x1961, - 0x1961, 0x1961, 0x196f, 0x1961, 0x1961, 0x1961, 0x1961, 0x1961, - 0x1973, 0x080c, 0x0d7d, 0xa774, 0xa678, 0x0804, 0x1a4c, 0xa78c, - 0xa690, 0x0804, 0x1a4c, 0xa7a4, 0xa6a8, 0x0804, 0x1a4c, 0xa7bc, - 0xa6c0, 0x0804, 0x1a4c, 0xa7d4, 0xa6d8, 0x0804, 0x1a4c, 0xa898, - 0x901d, 0x1108, 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0d7d, 0x9082, 0x001b, 0x0002, 0x199f, 0x199f, 0x19a1, 0x199f, - 0x199f, 0x199f, 0x19ab, 0x199f, 0x199f, 0x199f, 0x19b5, 0x199f, - 0x199f, 0x199f, 0x19bf, 0x199f, 0x199f, 0x199f, 0x19c9, 0x199f, - 0x199f, 0x199f, 0x19d3, 0x199f, 0x199f, 0x199f, 0x19dd, 0x080c, - 0x0d7d, 0xa574, 0xa478, 0x9d86, 0x0004, 0x0904, 0x1a4c, 0xa37c, - 0xa280, 0x0804, 0x1a4c, 0xa584, 0xa488, 0x9d86, 0x0004, 0x0904, - 0x1a4c, 0xa38c, 0xa290, 0x0804, 0x1a4c, 0xa594, 0xa498, 0x9d86, - 0x0004, 0x0904, 0x1a4c, 0xa39c, 0xa2a0, 0x0804, 0x1a4c, 0xa5a4, - 0xa4a8, 0x9d86, 0x0004, 0x0904, 0x1a4c, 0xa3ac, 0xa2b0, 0x0804, - 0x1a4c, 0xa5b4, 0xa4b8, 0x9d86, 0x0004, 0x0904, 0x1a4c, 0xa3bc, - 0xa2c0, 0x0804, 0x1a4c, 0xa5c4, 0xa4c8, 0x9d86, 0x0004, 0x0904, - 0x1a4c, 0xa3cc, 0xa2d0, 0x0804, 0x1a4c, 0xa5d4, 0xa4d8, 0x9d86, - 0x0004, 0x0904, 0x1a4c, 0xa3dc, 0xa2e0, 0x0804, 0x1a4c, 0xa898, - 0x901d, 0x1108, 0xab9c, 0x9016, 0x2c05, 0x908a, 0x0034, 0x1a0c, - 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1a0f, 0x1a0d, 0x1a0d, 0x1a0d, - 0x1a0d, 0x1a0d, 0x1a19, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a0d, - 0x1a23, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a2d, 0x1a0d, - 0x1a0d, 0x1a0d, 0x1a0d, 0x1a0d, 0x1a37, 0x080c, 0x0d7d, 0xa56c, - 0xa470, 0xa774, 0xa678, 0x9d86, 0x000c, 0x05b0, 0xa37c, 0xa280, - 0x0498, 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x000c, 0x0560, - 0xa394, 0xa298, 0x0448, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, - 0x000c, 0x0510, 0xa3ac, 0xa2b0, 0x00f8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0x9d86, 0x000c, 0x01c0, 0xa3c4, 0xa2c8, 0x00a8, 0xa5cc, - 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x000c, 0x0170, 0xa3dc, 0xa2e0, - 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1e38, 0x1904, 0x1920, - 0x900e, 0x0050, 0x080c, 0x0d7d, 0xab2e, 0xaa32, 0xad1e, 0xac22, - 0xaf26, 0xae2a, 0x080c, 0x1e38, 0x0005, 0x6014, 0x2048, 0x6118, - 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, - 0xa986, 0x601b, 0x0002, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, - 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, - 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0xac7c, 0x0005, 0x0126, - 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, - 0x0000, 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, - 0x0006, 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, - 0x0120, 0x080c, 0x13ae, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, - 0x2031, 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x13ae, 0x00ce, - 0x2001, 0x0038, 0x080c, 0x1b4f, 0x7930, 0x9186, 0x0040, 0x0160, - 0x9186, 0x0042, 0x190c, 0x0d7d, 0x2001, 0x001e, 0x8001, 0x1df0, - 0x8631, 0x1d40, 0x080c, 0x1b5e, 0x000e, 0x6022, 0x012e, 0x0005, - 0x080c, 0x1b4b, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, - 0x0000, 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, - 0x0004, 0x00fe, 0x080c, 0x74c8, 0x11b0, 0x2001, 0x0138, 0x2003, - 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, - 0xa001, 0x8211, 0x1de0, 0x0081, 0x2001, 0x0386, 0x2003, 0x2020, - 0x080c, 0x7569, 0x0005, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, + 0x8318, 0x1f04, 0x0dcc, 0x2069, 0x1a99, 0x2019, 0x0050, 0x20a9, + 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dd9, + 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, 0x1800, 0x7803, + 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, + 0x2001, 0x1a21, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, + 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, + 0x080c, 0x5704, 0x1170, 0x080c, 0x0f20, 0x0110, 0x080c, 0x0e73, + 0x080c, 0x5704, 0x1130, 0x2071, 0x1800, 0x2011, 0x8000, 0x080c, + 0x0f34, 0x0c70, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, 0x080c, 0xa88a, 0x2079, + 0x0380, 0x2069, 0x1b03, 0x7818, 0x6802, 0x781c, 0x6806, 0x7840, + 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, 0x2019, 0x1b0e, 0x9016, + 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, 0x8210, 0x8318, 0x8210, + 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, 0x6a2a, 0x7830, 0x681a, + 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, 0x6826, 0x7803, 0x0000, + 0x2069, 0x1ac3, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, + 0x8d68, 0x8318, 0x1f04, 0x0e4d, 0x2069, 0x1ae3, 0x2019, 0x00b0, + 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, + 0x0e5a, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, + 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d, 0x6400, 0x2001, + 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, + 0x0f12, 0x20a9, 0x0900, 0x080c, 0x0f48, 0x2011, 0x0040, 0x080c, + 0x0f12, 0x20a9, 0x0900, 0x080c, 0x0f48, 0x0c78, 0x0026, 0x080c, + 0x0f20, 0x1188, 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, 0x9296, + 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, 0x2011, 0x1b47, 0x080c, + 0x0f34, 0x002e, 0x0005, 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, + 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, 0x2011, 0x6840, + 0xd0e4, 0x70f3, 0x0000, 0x1128, 0x70f3, 0x0fa0, 0x080c, 0x0f25, + 0x002e, 0x0005, 0x0026, 0x080c, 0x0f20, 0x0148, 0xd0a4, 0x1138, + 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, 0x0f25, 0x002e, + 0x0005, 0x0026, 0x70f3, 0x0000, 0x080c, 0x0f20, 0x1130, 0x2011, + 0x8040, 0x080c, 0x0f34, 0x002e, 0x0005, 0x080c, 0x2a27, 0x1118, + 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, 0x0f25, 0x002e, + 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, 0x1800, 0xd0b4, 0x70ec, + 0x71e8, 0x1118, 0xc0e4, 0xc1f4, 0x0050, 0x0006, 0x3b00, 0x9084, + 0xff3e, 0x20d8, 0x000e, 0x70f3, 0x0000, 0xc0e5, 0xc1f5, 0x0099, + 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0xd0e4, + 0x70ec, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0016, 0x71e8, 0x0019, + 0x001e, 0x00ee, 0x0005, 0x70ee, 0x71ea, 0x7000, 0x9084, 0x0007, + 0x000b, 0x0005, 0x0ed8, 0x0eb2, 0x0eb2, 0x0e86, 0x0ec1, 0x0eb2, + 0x0eb2, 0x0ec1, 0xc284, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, + 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, 0x20d0, 0x001e, 0x0005, + 0x2001, 0x183b, 0x2004, 0xd0dc, 0x0005, 0x9e86, 0x1800, 0x190c, + 0x0d7d, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee, 0xd0e4, 0x1118, + 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, 0x1800, 0x190c, 0x0d7d, + 0x70e8, 0xd0f4, 0x0108, 0xc2f5, 0x72ea, 0xd0f4, 0x1140, 0x9284, + 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, 0x00c1, 0x0861, 0x0005, + 0x1d04, 0x0f48, 0x2091, 0x6000, 0x1f04, 0x0f48, 0x0005, 0x890e, + 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, + 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, + 0x0146, 0x0036, 0x0096, 0x2061, 0x188d, 0x600b, 0x0000, 0x600f, + 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, + 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, + 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, + 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, 0x000e, 0x200f, + 0x2001, 0x189d, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, + 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, + 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, + 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, 0x20e8, 0x21a0, + 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, 0x002e, 0x009e, + 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, 0x08e8, 0x0016, + 0x0026, 0x0096, 0x3348, 0x080c, 0x0f4f, 0x2100, 0x9300, 0x2098, + 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, + 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, + 0x0001, 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, + 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, + 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, 0x8007, 0x7180, + 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, + 0x080c, 0x0d5d, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, + 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, + 0x1079, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x10f2, 0x090c, 0x0d7d, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, + 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, + 0x73c0, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, + 0x0d7d, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0d7d, 0xa000, 0x0c98, + 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1910, 0x7010, + 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0d7d, + 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, + 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, 0x8001, 0x0270, + 0x70c2, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, + 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70c0, 0x90ca, + 0x0020, 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, + 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, + 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, + 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, + 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, + 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, + 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, + 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, + 0x0040, 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, 0x11a0, 0x2001, + 0x0558, 0xa802, 0x2048, 0x2009, 0x5600, 0x8940, 0x2800, 0xa802, + 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, + 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, 0x7200, 0x82ff, + 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, + 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, + 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, + 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74be, + 0x74c2, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, + 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, + 0x9982, 0x0558, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, + 0x0800, 0x0250, 0x2071, 0x188d, 0x7010, 0x9902, 0x1228, 0x9085, + 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, + 0x1a20, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, + 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, + 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x112c, 0x702b, + 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x1135, + 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, + 0xa06f, 0x0000, 0x2071, 0x1a20, 0x701c, 0x9088, 0x1a2a, 0x280a, + 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, 0x0d7d, + 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, + 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, + 0x1a20, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, + 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, + 0x7007, 0x0006, 0x7000, 0x0002, 0x117e, 0x1301, 0x117c, 0x117c, + 0x12f5, 0x12f5, 0x12f5, 0x12f5, 0x080c, 0x0d7d, 0x701c, 0x7120, + 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, 0x1110, + 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x1a2a, 0x2004, 0x700a, + 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, 0x0026, 0xa88c, + 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, 0x780e, 0xa878, + 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868, 0x009e, 0xd084, + 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, + 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, + 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, 0x7812, 0x782b, + 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, + 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, 0x2098, 0x20e9, + 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, 0x2011, 0x0040, + 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, + 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, + 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x2009, 0x1a20, + 0x2104, 0xc095, 0x200a, 0x080c, 0x115b, 0x0005, 0x0016, 0x00e6, + 0x2071, 0x1a20, 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, 0x190c, + 0x0d76, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, + 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x116c, 0x1214, 0x1248, + 0x1320, 0x0d7d, 0x133b, 0x0d7d, 0x918c, 0x0700, 0x1550, 0x0136, + 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, 0x20e1, 0x0000, + 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, 0x4005, 0x3400, + 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, 0x0578, 0x7800, + 0x7802, 0x7804, 0x7806, 0x080c, 0x11b1, 0x0005, 0x7008, 0x0096, + 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x080c, 0x116c, + 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x0ca0, + 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180, 0x7800, 0x7802, + 0x7804, 0x7806, 0x080c, 0x11c6, 0x0005, 0x7008, 0x0096, 0x2048, + 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080, 0x0096, 0x7008, + 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808, 0xa896, 0x780c, + 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x0096, 0x00d6, + 0x7008, 0x2048, 0x2001, 0x18b9, 0x2004, 0x9906, 0x1128, 0xa89c, + 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, 0x0096, 0x00d6, + 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, 0x2940, 0x080f, + 0x008e, 0x00de, 0x009e, 0x080c, 0x115b, 0x0005, 0x00de, 0x009e, + 0x080c, 0x115b, 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, + 0x904d, 0x090c, 0x0d7d, 0xa06c, 0x908e, 0x0100, 0x0130, 0xa87b, + 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, 0x6d93, 0xa09f, + 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x1079, 0x009e, 0x0005, + 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d7d, 0xa06c, 0x908e, 0x0100, + 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, 0xa80c, 0x2050, + 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, 0x8006, 0x8007, + 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xa076, 0xa172, + 0xb000, 0xa07a, 0x2810, 0x080c, 0x113c, 0x00e8, 0xa97c, 0xa894, + 0x0016, 0x0006, 0x080c, 0x6d93, 0x000e, 0x001e, 0xd1fc, 0x1138, + 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0xabf0, 0x00ce, 0x7008, + 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, 0x1079, 0x7007, + 0x0000, 0x080c, 0x115b, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, + 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, + 0x0005, 0x0096, 0x2001, 0x192e, 0x204c, 0xa87c, 0x7812, 0xa88c, + 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, 0x780e, 0x782b, + 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, 0x0041, 0x7007, 0x0003, + 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, 0x012e, 0x009e, 0x0005, + 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x0096, 0x2001, + 0x192e, 0x204c, 0xaa7c, 0x009e, 0x080c, 0x8c34, 0x2009, 0x188c, + 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, 0x8aa4, 0x7007, 0x0000, + 0x080c, 0x116c, 0x0005, 0x7007, 0x0000, 0x080c, 0x116c, 0x0005, + 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x1a6a, 0x7003, + 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, 0x0007, 0x7803, 0x0000, + 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x2001, + 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, 0x0118, 0x7820, 0x04e9, + 0x0cd0, 0x2001, 0x1a6b, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, + 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, + 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, 0x1a79, 0x781f, 0xff00, + 0x781b, 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, + 0x0303, 0x2061, 0x1a79, 0x602f, 0x1ddc, 0x2001, 0x181a, 0x2004, + 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1e7a, 0x602b, 0x1ab9, 0x6007, + 0x1a99, 0x2061, 0x1a99, 0x606f, 0x193c, 0x2001, 0x1927, 0x2004, + 0x607a, 0x783f, 0x3388, 0x00ce, 0x0005, 0x9086, 0x000d, 0x11d0, + 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, 0xc853, + 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, 0x6120, + 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, 0xac8d, + 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, 0x9184, + 0x0070, 0x190c, 0x0d76, 0xd19c, 0x05a0, 0x7820, 0x908c, 0xf000, + 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, 0x6000, 0x9086, + 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, 0xa867, 0x0103, + 0x080c, 0x6bb5, 0x00b6, 0x6010, 0x2058, 0xba3c, 0x8211, 0x0208, + 0xba3e, 0xb8d0, 0x9005, 0x190c, 0x676f, 0x00be, 0x6044, 0xd0fc, + 0x190c, 0xa8c2, 0x080c, 0xac19, 0x7808, 0xd09c, 0x19b0, 0x012e, + 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d7d, 0x002b, 0x012e, 0x0005, + 0x04b0, 0x012e, 0x0005, 0x141f, 0x1445, 0x1475, 0x147a, 0x147e, + 0x1483, 0x14ab, 0x14af, 0x14bd, 0x14c1, 0x141f, 0x158e, 0x1592, + 0x15f7, 0x15fe, 0x141f, 0x15ff, 0x1600, 0x160b, 0x1612, 0x141f, + 0x141f, 0x141f, 0x141f, 0x141f, 0x141f, 0x141f, 0x1485, 0x141f, + 0x144d, 0x1472, 0x1439, 0x141f, 0x1459, 0x1423, 0x1421, 0x080c, + 0x0d7d, 0x080c, 0x0d76, 0x080c, 0x161d, 0x2009, 0x1a78, 0x2104, + 0x8000, 0x200a, 0x080c, 0x7f9c, 0x080c, 0x1adf, 0x0005, 0x6044, + 0xd0fc, 0x190c, 0xa8c2, 0x2009, 0x0055, 0x080c, 0xac8d, 0x012e, + 0x0005, 0x080c, 0x161d, 0x2060, 0x6044, 0xd0fc, 0x190c, 0xa8c2, + 0x2009, 0x0055, 0x080c, 0xac8d, 0x0005, 0x2009, 0x0048, 0x080c, + 0x161d, 0x2060, 0x080c, 0xac8d, 0x0005, 0x2009, 0x0054, 0x080c, + 0x161d, 0x2060, 0x6044, 0xd0fc, 0x190c, 0xa8c2, 0x080c, 0xac8d, + 0x0005, 0x080c, 0x161d, 0x2060, 0x0056, 0x0066, 0x080c, 0x161d, + 0x2028, 0x080c, 0x161d, 0x2030, 0x0036, 0x0046, 0x2021, 0x0000, + 0x2418, 0x2009, 0x0056, 0x080c, 0xac8d, 0x004e, 0x003e, 0x006e, + 0x005e, 0x0005, 0x080c, 0x161d, 0x0005, 0x7004, 0xc085, 0xc0b5, + 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, 0x161d, + 0x080c, 0x16e1, 0x0005, 0x080c, 0x0d7d, 0x080c, 0x161d, 0x2060, + 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, + 0x080c, 0xac8d, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, + 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, + 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x1622, 0x2001, 0x0307, + 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, + 0x161d, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, + 0x2009, 0x0048, 0x080c, 0xac8d, 0x0005, 0x080c, 0x161d, 0x080c, + 0x0d7d, 0x080c, 0x161d, 0x080c, 0x1579, 0x7827, 0x0018, 0x79ac, + 0xd1dc, 0x0904, 0x152a, 0x7827, 0x0015, 0x7828, 0x782b, 0x0000, + 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, + 0x0804, 0x1530, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab, 0x0004, + 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d7d, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x155e, 0x78ab, + 0x0004, 0x7803, 0x0001, 0x080c, 0x1592, 0x0005, 0x7827, 0x0018, + 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, 0x0110, + 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4, 0x0140, + 0x00ee, 0x080c, 0x1adf, 0x080c, 0x1354, 0x7803, 0x0001, 0x0005, + 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, 0x9186, + 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, 0x78ab, + 0x0004, 0x7803, 0x0001, 0x080c, 0x1592, 0x2001, 0x020d, 0x2003, + 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, 0x0d7d, + 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, 0x080c, + 0x7f9c, 0x080c, 0x1adf, 0x080c, 0xc865, 0x0158, 0xa9ac, 0xa936, + 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, 0xc0bd, + 0xa882, 0x080c, 0xc453, 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, + 0x2009, 0x004c, 0x080c, 0xac8d, 0x0048, 0x6010, 0x00b6, 0x2058, + 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xcc66, 0x2029, 0x00c8, + 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, + 0x080c, 0xe727, 0xd5a4, 0x1118, 0x080c, 0x1622, 0x0005, 0x080c, + 0x7f9c, 0x080c, 0x1adf, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, + 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, + 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, + 0x1693, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, + 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0d7d, 0xd184, + 0x1189, 0xd19c, 0x0158, 0xc19c, 0x7106, 0x2001, 0x020d, 0x2003, + 0x0050, 0x2003, 0x0020, 0x080c, 0x1622, 0x0005, 0x81ff, 0x190c, + 0x0d7d, 0x0005, 0xc184, 0xd1b4, 0xc1b4, 0x7106, 0x0016, 0x00e6, + 0x15f0, 0x2071, 0x0200, 0x080c, 0x16ce, 0x05c8, 0x6014, 0x9005, + 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, 0x9084, 0x00ff, 0x908e, + 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, 0x601c, 0xd084, 0x11e0, + 0x00f6, 0x2c78, 0x080c, 0x174b, 0x00fe, 0x00b0, 0x00f6, 0x2c78, + 0x080c, 0x18d2, 0x00fe, 0x2009, 0x01f4, 0x8109, 0x0168, 0x2001, + 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, + 0x1118, 0x080c, 0x1622, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, + 0x080c, 0x1354, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, + 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0461, 0x0ca8, 0x0429, + 0x2060, 0x2009, 0x0053, 0x080c, 0xac8d, 0x0005, 0x0005, 0x0005, + 0x00e1, 0x2008, 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, + 0x080c, 0x8f93, 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8b94, + 0x0cd0, 0x0005, 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, + 0x181f, 0x2214, 0x080c, 0x1693, 0x0005, 0x7808, 0xd09c, 0x0de8, + 0x7820, 0x0005, 0x080c, 0x1579, 0x00d6, 0x2069, 0x0200, 0x2009, + 0x01f4, 0x8109, 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, + 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, + 0x0180, 0x9182, 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, + 0x810c, 0x810c, 0x810c, 0x080c, 0x1685, 0x6827, 0x0001, 0x8109, + 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, + 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, + 0x1130, 0x08c0, 0x080c, 0x7f9c, 0x080c, 0x1adf, 0x0090, 0x7827, + 0x0015, 0x782b, 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, + 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, + 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, + 0x0d30, 0x7827, 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, + 0x9085, 0x1800, 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, + 0x1de0, 0x0005, 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, + 0x9086, 0x0041, 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, + 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, 0x13bb, 0x00ce, + 0x002e, 0x001e, 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, + 0x8080, 0x0059, 0x1118, 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, + 0x3900, 0x8000, 0x2004, 0x080c, 0x0d7d, 0x2009, 0xff00, 0x8109, + 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, 0x9085, 0x0001, 0x0005, + 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0c79, 0x1108, 0x0005, + 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d7d, 0x7037, 0x0001, + 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, + 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, 0x9085, 0x0001, + 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c41, 0x6124, 0xd1dc, + 0x01f8, 0x701c, 0xd08c, 0x0904, 0x1740, 0x7017, 0x0000, 0x2001, + 0x0264, 0x2004, 0xd0bc, 0x0904, 0x1740, 0x2001, 0x0268, 0x00c6, + 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x1740, + 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, 0x7ef4, 0x012e, + 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, 0xcc41, 0xab42, 0xac3e, + 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, + 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, + 0x7fff, 0xa837, 0xffff, 0x080c, 0x1e9a, 0x1190, 0x080c, 0x192d, + 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, + 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, + 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x1622, + 0x0005, 0x080c, 0x0d7d, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x00c6, + 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, + 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1e7a, 0x2165, 0x0002, 0x1776, + 0x17e4, 0x1776, 0x1776, 0x177a, 0x17c5, 0x1776, 0x179a, 0x176f, + 0x17db, 0x1776, 0x1776, 0x177f, 0x18d0, 0x17ae, 0x17a4, 0xa964, + 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x17db, 0x9085, 0x0001, + 0x0804, 0x18c7, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x17eb, 0xa87c, + 0xd0ac, 0x0da0, 0x0804, 0x1856, 0xa898, 0x901d, 0x1108, 0xab9c, + 0x9016, 0xaab2, 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008, 0x2004, + 0x9080, 0x915c, 0x2005, 0x9005, 0x090c, 0x0d7d, 0x2004, 0xa8ae, + 0x0804, 0x18af, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, 0xa88c, + 0xa83e, 0xa888, 0x0804, 0x17eb, 0xa87c, 0xd0bc, 0x0978, 0xa890, + 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1856, 0xa87c, 0xd0bc, + 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, + 0x0d7d, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1e7a, 0x2065, + 0xa888, 0xd19c, 0x1904, 0x1856, 0x0430, 0xa87c, 0xd0ac, 0x0904, + 0x1776, 0xa804, 0x9045, 0x090c, 0x0d7d, 0xa164, 0xa91a, 0x91ec, + 0x000f, 0x9d80, 0x1e7a, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, + 0x1904, 0x1856, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x1776, 0x9006, + 0xa842, 0xa83e, 0x0804, 0x1856, 0xa87c, 0xd0ac, 0x0904, 0x1776, + 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d7d, + 0x9082, 0x001b, 0x0002, 0x180e, 0x180e, 0x1810, 0x180e, 0x180e, + 0x180e, 0x181a, 0x180e, 0x180e, 0x180e, 0x1824, 0x180e, 0x180e, + 0x180e, 0x182e, 0x180e, 0x180e, 0x180e, 0x1838, 0x180e, 0x180e, + 0x180e, 0x1842, 0x180e, 0x180e, 0x180e, 0x184c, 0x080c, 0x0d7d, + 0xa574, 0xa478, 0x9d86, 0x0024, 0x0904, 0x1784, 0xa37c, 0xa280, + 0x0804, 0x18af, 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904, 0x1784, + 0xa38c, 0xa290, 0x0804, 0x18af, 0xa594, 0xa498, 0x9d86, 0x0024, + 0x0904, 0x1784, 0xa39c, 0xa2a0, 0x0804, 0x18af, 0xa5a4, 0xa4a8, + 0x9d86, 0x0024, 0x0904, 0x1784, 0xa3ac, 0xa2b0, 0x0804, 0x18af, + 0xa5b4, 0xa4b8, 0x9d86, 0x0024, 0x0904, 0x1784, 0xa3bc, 0xa2c0, + 0x0804, 0x18af, 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904, 0x1784, + 0xa3cc, 0xa2d0, 0x0804, 0x18af, 0xa5d4, 0xa4d8, 0x9d86, 0x0024, + 0x0904, 0x1784, 0xa3dc, 0xa2e0, 0x0804, 0x18af, 0x2c05, 0x908a, + 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1879, 0x1877, + 0x1877, 0x1877, 0x1877, 0x1877, 0x1884, 0x1877, 0x1877, 0x1877, + 0x1877, 0x1877, 0x188f, 0x1877, 0x1877, 0x1877, 0x1877, 0x1877, + 0x189a, 0x1877, 0x1877, 0x1877, 0x1877, 0x1877, 0x18a5, 0x080c, + 0x0d7d, 0xa56c, 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c, 0x0904, + 0x1784, 0xa37c, 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c, 0xa690, + 0x9d86, 0x002c, 0x0904, 0x1784, 0xa394, 0xa298, 0x0400, 0xa59c, + 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x1784, 0xa3ac, + 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, 0x002c, + 0x0904, 0x1784, 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0, 0xa7d4, + 0xa6d8, 0x9d86, 0x002c, 0x0904, 0x1784, 0xa3dc, 0xa2e0, 0xab2e, + 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60, 0x2c1d, + 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1158, 0x3e60, + 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, + 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c78, + 0x0804, 0x1776, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, + 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1e75, 0xa813, 0x1e75, + 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, 0x0d7d, + 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d7d, + 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, 0xaa32, + 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, + 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1120, 0x8109, + 0xa916, 0x0128, 0x0078, 0x918a, 0x0002, 0xa916, 0x1158, 0x3e60, + 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, + 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0d7d, 0xa80e, 0xa064, + 0xa81a, 0x9084, 0x000f, 0x9080, 0x1e7a, 0x2015, 0x82ff, 0x090c, + 0x0d7d, 0xaa12, 0x2205, 0xa80a, 0x0c10, 0x903e, 0x2730, 0xa880, + 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a57, 0x1984, 0x1984, 0x1a57, + 0x1984, 0x1a51, 0x1a57, 0x1984, 0x19f4, 0x19f4, 0x19f4, 0x1a57, + 0x19f4, 0x1a57, 0x1a4e, 0x19f4, 0xc0fc, 0xa882, 0xab2c, 0xaa30, + 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a59, 0x2c05, 0x908a, 0x0034, + 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1970, 0x196e, 0x196e, + 0x196e, 0x196e, 0x196e, 0x1974, 0x196e, 0x196e, 0x196e, 0x196e, + 0x196e, 0x1978, 0x196e, 0x196e, 0x196e, 0x196e, 0x196e, 0x197c, + 0x196e, 0x196e, 0x196e, 0x196e, 0x196e, 0x1980, 0x080c, 0x0d7d, + 0xa774, 0xa678, 0x0804, 0x1a59, 0xa78c, 0xa690, 0x0804, 0x1a59, + 0xa7a4, 0xa6a8, 0x0804, 0x1a59, 0xa7bc, 0xa6c0, 0x0804, 0x1a59, + 0xa7d4, 0xa6d8, 0x0804, 0x1a59, 0xa898, 0x901d, 0x1108, 0xab9c, + 0x9016, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x9082, 0x001b, + 0x0002, 0x19ac, 0x19ac, 0x19ae, 0x19ac, 0x19ac, 0x19ac, 0x19b8, + 0x19ac, 0x19ac, 0x19ac, 0x19c2, 0x19ac, 0x19ac, 0x19ac, 0x19cc, + 0x19ac, 0x19ac, 0x19ac, 0x19d6, 0x19ac, 0x19ac, 0x19ac, 0x19e0, + 0x19ac, 0x19ac, 0x19ac, 0x19ea, 0x080c, 0x0d7d, 0xa574, 0xa478, + 0x9d86, 0x0004, 0x0904, 0x1a59, 0xa37c, 0xa280, 0x0804, 0x1a59, + 0xa584, 0xa488, 0x9d86, 0x0004, 0x0904, 0x1a59, 0xa38c, 0xa290, + 0x0804, 0x1a59, 0xa594, 0xa498, 0x9d86, 0x0004, 0x0904, 0x1a59, + 0xa39c, 0xa2a0, 0x0804, 0x1a59, 0xa5a4, 0xa4a8, 0x9d86, 0x0004, + 0x0904, 0x1a59, 0xa3ac, 0xa2b0, 0x0804, 0x1a59, 0xa5b4, 0xa4b8, + 0x9d86, 0x0004, 0x0904, 0x1a59, 0xa3bc, 0xa2c0, 0x0804, 0x1a59, + 0xa5c4, 0xa4c8, 0x9d86, 0x0004, 0x0904, 0x1a59, 0xa3cc, 0xa2d0, + 0x0804, 0x1a59, 0xa5d4, 0xa4d8, 0x9d86, 0x0004, 0x0904, 0x1a59, + 0xa3dc, 0xa2e0, 0x0804, 0x1a59, 0xa898, 0x901d, 0x1108, 0xab9c, + 0x9016, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, + 0x0002, 0x1a1c, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a26, + 0x1a1a, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a30, 0x1a1a, 0x1a1a, + 0x1a1a, 0x1a1a, 0x1a1a, 0x1a3a, 0x1a1a, 0x1a1a, 0x1a1a, 0x1a1a, + 0x1a1a, 0x1a44, 0x080c, 0x0d7d, 0xa56c, 0xa470, 0xa774, 0xa678, + 0x9d86, 0x000c, 0x05b0, 0xa37c, 0xa280, 0x0498, 0xa584, 0xa488, + 0xa78c, 0xa690, 0x9d86, 0x000c, 0x0560, 0xa394, 0xa298, 0x0448, + 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x000c, 0x0510, 0xa3ac, + 0xa2b0, 0x00f8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, 0x000c, + 0x01c0, 0xa3c4, 0xa2c8, 0x00a8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, + 0x9d86, 0x000c, 0x0170, 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, + 0x1130, 0x080c, 0x1e50, 0x1904, 0x192d, 0x900e, 0x0050, 0x080c, + 0x0d7d, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, + 0x1e50, 0x0005, 0x6014, 0x2048, 0x6118, 0x810c, 0x810c, 0x810c, + 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, 0x601b, 0x0002, + 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, 0x00e9, 0x6000, + 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xac8d, 0x0005, + 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, + 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, + 0x0048, 0x0804, 0xac8d, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, + 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, + 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, + 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x13bb, + 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, + 0x7808, 0xd09c, 0x190c, 0x13bb, 0x00ce, 0x2001, 0x0038, 0x080c, + 0x1b67, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, + 0x0d7d, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, + 0x1b76, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, 0x1b63, 0x7827, + 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, + 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, 0x00fe, 0x080c, + 0x74ec, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, + 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, + 0x0059, 0x0804, 0x7591, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, - 0x2a1b, 0x2009, 0x003c, 0x080c, 0x21c1, 0x2001, 0x015d, 0x2003, - 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x8532, 0x70a0, + 0x2a3b, 0x2009, 0x003c, 0x080c, 0x21d9, 0x2001, 0x015d, 0x2003, + 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x8566, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, - 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1347, 0x7803, 0x0001, + 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1354, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, - 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x74c8, 0x1108, + 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x74ec, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, 0x2c08, - 0x621c, 0x080c, 0x1686, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, - 0x16b3, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0005, + 0x621c, 0x080c, 0x1693, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, + 0x16c0, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0005, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, - 0x0040, 0x0904, 0x1bbc, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, + 0x0040, 0x0904, 0x1bd4, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, 0x0d7d, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0b10, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, - 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x1b55, + 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x1b6d, 0x9186, 0x0040, 0x190c, 0x0d7d, 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, @@ -684,42 +687,42 @@ unsigned short risc_code01[] = { 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, 0x2079, 0x0380, 0x2001, 0x19e6, 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa964, 0xa91a, - 0x918c, 0x00ff, 0x9184, 0x000f, 0x0002, 0x1bf1, 0x1bf1, 0x1bf1, - 0x1bf3, 0x1bf1, 0x1bf1, 0x1bf1, 0x1bf1, 0x1be5, 0x1bfb, 0x1bf1, - 0x1bf7, 0x1bf1, 0x1bf1, 0x1bf1, 0x1bf1, 0x9086, 0x0008, 0x1148, - 0xa87c, 0xd0b4, 0x0904, 0x1d6b, 0x2011, 0x1e5d, 0x2205, 0xab88, + 0x918c, 0x00ff, 0x9184, 0x000f, 0x0002, 0x1c09, 0x1c09, 0x1c09, + 0x1c0b, 0x1c09, 0x1c09, 0x1c09, 0x1c09, 0x1bfd, 0x1c13, 0x1c09, + 0x1c0f, 0x1c09, 0x1c09, 0x1c09, 0x1c09, 0x9086, 0x0008, 0x1148, + 0xa87c, 0xd0b4, 0x0904, 0x1d83, 0x2011, 0x1e75, 0x2205, 0xab88, 0x00a8, 0x080c, 0x0d7d, 0x9186, 0x0013, 0x0128, 0x0cd0, 0x9186, - 0x001b, 0x0108, 0x0cb0, 0xa87c, 0xd0b4, 0x0904, 0x1d6b, 0x9184, - 0x000f, 0x9080, 0x1e62, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, + 0x001b, 0x0108, 0x0cb0, 0xa87c, 0xd0b4, 0x0904, 0x1d83, 0x9184, + 0x000f, 0x9080, 0x1e7a, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x9006, 0xa842, 0xa83e, 0x012e, 0x0005, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa88c, 0xa990, 0xaaac, 0xabb0, 0xaa36, 0xab3a, 0xa83e, 0xa942, 0xa846, 0xa94a, 0xa964, 0x918c, 0x00ff, 0x9186, 0x001e, 0x0198, 0x2940, - 0xa064, 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1e62, 0x2065, 0x2c05, + 0xa064, 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1e7a, 0x2065, 0x2c05, 0x2808, 0x2c10, 0xab88, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x012e, 0x3e60, 0x0005, 0xa804, 0x2040, 0x0c58, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa97c, 0x2950, 0xd1dc, 0x1904, - 0x1d35, 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, - 0xa916, 0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, 0x1e62, 0x2145, - 0x0002, 0x1c69, 0x1c77, 0x1c69, 0x1c69, 0x1c69, 0x1c6b, 0x1c69, - 0x1c69, 0x1ccc, 0x1ccc, 0x1c69, 0x1c69, 0x1c69, 0x1cca, 0x1c69, - 0x1c69, 0x080c, 0x0d7d, 0xa804, 0x2050, 0xb164, 0xa91a, 0x9184, - 0x000f, 0x9080, 0x1e62, 0x2045, 0xd19c, 0x1904, 0x1ccc, 0x9036, + 0x1d4d, 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, + 0xa916, 0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, 0x1e7a, 0x2145, + 0x0002, 0x1c81, 0x1c8f, 0x1c81, 0x1c81, 0x1c81, 0x1c83, 0x1c81, + 0x1c81, 0x1ce4, 0x1ce4, 0x1c81, 0x1c81, 0x1c81, 0x1ce2, 0x1c81, + 0x1c81, 0x080c, 0x0d7d, 0xa804, 0x2050, 0xb164, 0xa91a, 0x9184, + 0x000f, 0x9080, 0x1e7a, 0x2045, 0xd19c, 0x1904, 0x1ce4, 0x9036, 0x2638, 0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x9082, 0x001b, - 0x0002, 0x1c9c, 0x1c9c, 0x1c9e, 0x1c9c, 0x1c9c, 0x1c9c, 0x1ca4, - 0x1c9c, 0x1c9c, 0x1c9c, 0x1caa, 0x1c9c, 0x1c9c, 0x1c9c, 0x1cb0, - 0x1c9c, 0x1c9c, 0x1c9c, 0x1cb6, 0x1c9c, 0x1c9c, 0x1c9c, 0x1cbc, - 0x1c9c, 0x1c9c, 0x1c9c, 0x1cc2, 0x080c, 0x0d7d, 0xb574, 0xb478, - 0xb37c, 0xb280, 0x0804, 0x1d11, 0xb584, 0xb488, 0xb38c, 0xb290, - 0x0804, 0x1d11, 0xb594, 0xb498, 0xb39c, 0xb2a0, 0x0804, 0x1d11, - 0xb5a4, 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1d11, 0xb5b4, 0xb4b8, - 0xb3bc, 0xb2c0, 0x0804, 0x1d11, 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, - 0x0804, 0x1d11, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, 0x0804, 0x1d11, - 0x0804, 0x1d11, 0x080c, 0x0d7d, 0x2805, 0x908a, 0x0034, 0x1a0c, - 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1cef, 0x1ced, 0x1ced, 0x1ced, - 0x1ced, 0x1ced, 0x1cf6, 0x1ced, 0x1ced, 0x1ced, 0x1ced, 0x1ced, - 0x1cfd, 0x1ced, 0x1ced, 0x1ced, 0x1ced, 0x1ced, 0x1d04, 0x1ced, - 0x1ced, 0x1ced, 0x1ced, 0x1ced, 0x1d0b, 0x080c, 0x0d7d, 0xb56c, + 0x0002, 0x1cb4, 0x1cb4, 0x1cb6, 0x1cb4, 0x1cb4, 0x1cb4, 0x1cbc, + 0x1cb4, 0x1cb4, 0x1cb4, 0x1cc2, 0x1cb4, 0x1cb4, 0x1cb4, 0x1cc8, + 0x1cb4, 0x1cb4, 0x1cb4, 0x1cce, 0x1cb4, 0x1cb4, 0x1cb4, 0x1cd4, + 0x1cb4, 0x1cb4, 0x1cb4, 0x1cda, 0x080c, 0x0d7d, 0xb574, 0xb478, + 0xb37c, 0xb280, 0x0804, 0x1d29, 0xb584, 0xb488, 0xb38c, 0xb290, + 0x0804, 0x1d29, 0xb594, 0xb498, 0xb39c, 0xb2a0, 0x0804, 0x1d29, + 0xb5a4, 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1d29, 0xb5b4, 0xb4b8, + 0xb3bc, 0xb2c0, 0x0804, 0x1d29, 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, + 0x0804, 0x1d29, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, 0x0804, 0x1d29, + 0x0804, 0x1d29, 0x080c, 0x0d7d, 0x2805, 0x908a, 0x0034, 0x1a0c, + 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1d07, 0x1d05, 0x1d05, 0x1d05, + 0x1d05, 0x1d05, 0x1d0e, 0x1d05, 0x1d05, 0x1d05, 0x1d05, 0x1d05, + 0x1d15, 0x1d05, 0x1d05, 0x1d05, 0x1d05, 0x1d05, 0x1d1c, 0x1d05, + 0x1d05, 0x1d05, 0x1d05, 0x1d05, 0x1d23, 0x080c, 0x0d7d, 0xb56c, 0xb470, 0xb774, 0xb678, 0xb37c, 0xb280, 0x00d8, 0xb584, 0xb488, 0xb78c, 0xb690, 0xb394, 0xb298, 0x00a0, 0xb59c, 0xb4a0, 0xb7a4, 0xb6a8, 0xb3ac, 0xb2b0, 0x0068, 0xb5b4, 0xb4b8, 0xb7bc, 0xb6c0, @@ -727,23 +730,23 @@ unsigned short risc_code01[] = { 0xb2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8109, 0xa916, 0x1118, 0x9006, 0x012e, 0x0005, 0x8840, 0x2805, 0x9005, 0x1168, 0xb004, 0x9005, 0x090c, 0x0d7d, 0x2050, 0xb164, - 0xa91a, 0x9184, 0x000f, 0x9080, 0x1e62, 0x2045, 0x2805, 0x2810, + 0xa91a, 0x9184, 0x000f, 0x9080, 0x1e7a, 0x2045, 0x2805, 0x2810, 0x2a08, 0xa80a, 0xa90e, 0xaa12, 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c, 0x0d7d, 0xa93c, 0xaa40, 0xa844, 0x9106, 0x1118, 0xa848, - 0x9206, 0x0508, 0x2958, 0xab48, 0xac44, 0x2940, 0x080c, 0x1e82, + 0x9206, 0x0508, 0x2958, 0xab48, 0xac44, 0x2940, 0x080c, 0x1e9a, 0x1998, 0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, 0x1140, 0xa810, 0x2005, 0xa80a, 0x2a00, 0xa80e, 0x2009, 0x8015, 0x0070, 0x00c6, 0x3e60, 0x6044, 0xc0a4, 0x9085, 0x8005, 0x6046, 0x00ce, 0x8319, - 0xab16, 0x1904, 0x1d1e, 0x2009, 0x8005, 0x3e60, 0x6044, 0x9105, - 0x6046, 0x0804, 0x1d1b, 0x080c, 0x0d7d, 0x00f6, 0x00e6, 0x0096, + 0xab16, 0x1904, 0x1d36, 0x2009, 0x8005, 0x3e60, 0x6044, 0x9105, + 0x6046, 0x0804, 0x1d33, 0x080c, 0x0d7d, 0x00f6, 0x00e6, 0x0096, 0x00c6, 0x0026, 0x704c, 0x9c06, 0x190c, 0x0d7d, 0x2079, 0x0090, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7057, 0x0000, - 0x6014, 0x2048, 0x080c, 0xc832, 0x0118, 0xa880, 0xc0bd, 0xa882, + 0x6014, 0x2048, 0x080c, 0xc865, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, 0x1170, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, - 0x60c8, 0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, 0xc430, 0x080c, - 0xa888, 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, 0x0040, 0x080c, - 0x21c1, 0x080c, 0xa331, 0x2011, 0x0000, 0x080c, 0xa1bb, 0x002e, + 0x60c8, 0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, 0xc453, 0x080c, + 0xa899, 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, 0x0040, 0x080c, + 0x21d9, 0x080c, 0xa33e, 0x2011, 0x0000, 0x080c, 0xa1c8, 0x002e, 0x00ce, 0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0090, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x2019, 0x1000, 0x8319, 0x090c, @@ -751,75 +754,75 @@ unsigned short risc_code01[] = { 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x2079, 0x0090, 0x782b, 0x0008, 0x7057, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x2071, - 0x19e6, 0x7054, 0x9086, 0x0000, 0x0904, 0x1e33, 0x2079, 0x0090, + 0x19e6, 0x7054, 0x9086, 0x0000, 0x0904, 0x1e4b, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, - 0x9184, 0x0003, 0x0188, 0x080c, 0xe733, 0x2001, 0x0133, 0x2004, - 0x9005, 0x090c, 0x0d7d, 0x0016, 0x2009, 0x0040, 0x080c, 0x21c1, + 0x9184, 0x0003, 0x0188, 0x080c, 0xe770, 0x2001, 0x0133, 0x2004, + 0x9005, 0x090c, 0x0d7d, 0x0016, 0x2009, 0x0040, 0x080c, 0x21d9, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, - 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x21c1, - 0x782c, 0xd0fc, 0x09a8, 0x080c, 0xa8a4, 0x782c, 0xd0fc, 0x1de8, - 0x080c, 0xa888, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, - 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x21c1, 0x782b, + 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x21d9, + 0x782c, 0xd0fc, 0x09a8, 0x080c, 0xa8b5, 0x782c, 0xd0fc, 0x1de8, + 0x080c, 0xa899, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, + 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x21d9, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x0d7d, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, - 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1e62, + 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1e7a, 0x2065, 0x8cff, 0x090c, 0x0d7d, 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, - 0x0023, 0x0000, 0x0000, 0x1e55, 0x1e51, 0x1e55, 0x1e55, 0x1e5f, - 0x0000, 0x1e55, 0x1e5c, 0x1e5c, 0x1e59, 0x1e5c, 0x1e5c, 0x0000, - 0x1e5f, 0x1e5c, 0x0000, 0x1e57, 0x1e57, 0x0000, 0x1e57, 0x1e5f, - 0x0000, 0x1e57, 0x1e5d, 0x1e5d, 0x1e5d, 0x0000, 0x1e5d, 0x0000, - 0x1e5f, 0x1e5d, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, - 0x9055, 0x0904, 0x2061, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, - 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x1e5d, 0x00d0, 0x9de0, - 0x1e62, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, + 0x0023, 0x0000, 0x0000, 0x1e6d, 0x1e69, 0x1e6d, 0x1e6d, 0x1e77, + 0x0000, 0x1e6d, 0x1e74, 0x1e74, 0x1e71, 0x1e74, 0x1e74, 0x0000, + 0x1e77, 0x1e74, 0x0000, 0x1e6f, 0x1e6f, 0x0000, 0x1e6f, 0x1e77, + 0x0000, 0x1e6f, 0x1e75, 0x1e75, 0x1e75, 0x0000, 0x1e75, 0x0000, + 0x1e77, 0x1e75, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, + 0x9055, 0x0904, 0x2079, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, + 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x1e75, 0x00d0, 0x9de0, + 0x1e7a, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, - 0x1140, 0x0310, 0x0804, 0x2061, 0xa004, 0x9045, 0x0904, 0x2061, - 0x08d8, 0x2c05, 0x9005, 0x0904, 0x1f49, 0xdd9c, 0x1904, 0x1f05, - 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1eda, - 0x1eda, 0x1edc, 0x1eda, 0x1eda, 0x1eda, 0x1ee2, 0x1eda, 0x1eda, - 0x1eda, 0x1ee8, 0x1eda, 0x1eda, 0x1eda, 0x1eee, 0x1eda, 0x1eda, - 0x1eda, 0x1ef4, 0x1eda, 0x1eda, 0x1eda, 0x1efa, 0x1eda, 0x1eda, - 0x1eda, 0x1f00, 0x080c, 0x0d7d, 0xa07c, 0x9422, 0xa080, 0x931b, - 0x0804, 0x1f3f, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x1f3f, - 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1f3f, 0xa0ac, 0x9422, - 0xa0b0, 0x931b, 0x0804, 0x1f3f, 0xa0bc, 0x9422, 0xa0c0, 0x931b, - 0x0804, 0x1f3f, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x1f3f, + 0x1140, 0x0310, 0x0804, 0x2079, 0xa004, 0x9045, 0x0904, 0x2079, + 0x08d8, 0x2c05, 0x9005, 0x0904, 0x1f61, 0xdd9c, 0x1904, 0x1f1d, + 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1ef2, + 0x1ef2, 0x1ef4, 0x1ef2, 0x1ef2, 0x1ef2, 0x1efa, 0x1ef2, 0x1ef2, + 0x1ef2, 0x1f00, 0x1ef2, 0x1ef2, 0x1ef2, 0x1f06, 0x1ef2, 0x1ef2, + 0x1ef2, 0x1f0c, 0x1ef2, 0x1ef2, 0x1ef2, 0x1f12, 0x1ef2, 0x1ef2, + 0x1ef2, 0x1f18, 0x080c, 0x0d7d, 0xa07c, 0x9422, 0xa080, 0x931b, + 0x0804, 0x1f57, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x1f57, + 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1f57, 0xa0ac, 0x9422, + 0xa0b0, 0x931b, 0x0804, 0x1f57, 0xa0bc, 0x9422, 0xa0c0, 0x931b, + 0x0804, 0x1f57, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x1f57, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, - 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1f27, 0x1f25, 0x1f25, 0x1f25, - 0x1f25, 0x1f25, 0x1f2c, 0x1f25, 0x1f25, 0x1f25, 0x1f25, 0x1f25, - 0x1f31, 0x1f25, 0x1f25, 0x1f25, 0x1f25, 0x1f25, 0x1f36, 0x1f25, - 0x1f25, 0x1f25, 0x1f25, 0x1f25, 0x1f3b, 0x080c, 0x0d7d, 0xa07c, + 0x0d7d, 0x9082, 0x001b, 0x0002, 0x1f3f, 0x1f3d, 0x1f3d, 0x1f3d, + 0x1f3d, 0x1f3d, 0x1f44, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f3d, + 0x1f49, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f4e, 0x1f3d, + 0x1f3d, 0x1f3d, 0x1f3d, 0x1f3d, 0x1f53, 0x080c, 0x0d7d, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, - 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x2061, 0x8c60, 0x0804, - 0x1eb1, 0xa004, 0x9045, 0x0904, 0x2061, 0x0804, 0x1e8c, 0x8a51, - 0x0904, 0x2061, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, - 0x0904, 0x2061, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1e62, 0x2c05, - 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x2056, 0x2c05, 0x8422, + 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x2079, 0x8c60, 0x0804, + 0x1ec9, 0xa004, 0x9045, 0x0904, 0x2079, 0x0804, 0x1ea4, 0x8a51, + 0x0904, 0x2079, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, + 0x0904, 0x2079, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1e7a, 0x2c05, + 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x206e, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, - 0x1ff3, 0x9082, 0x001b, 0x0002, 0x1f8f, 0x1f8f, 0x1f91, 0x1f8f, - 0x1f8f, 0x1f8f, 0x1f9f, 0x1f8f, 0x1f8f, 0x1f8f, 0x1fad, 0x1f8f, - 0x1f8f, 0x1f8f, 0x1fbb, 0x1f8f, 0x1f8f, 0x1f8f, 0x1fc9, 0x1f8f, - 0x1f8f, 0x1f8f, 0x1fd7, 0x1f8f, 0x1f8f, 0x1f8f, 0x1fe5, 0x080c, + 0x200b, 0x9082, 0x001b, 0x0002, 0x1fa7, 0x1fa7, 0x1fa9, 0x1fa7, + 0x1fa7, 0x1fa7, 0x1fb7, 0x1fa7, 0x1fa7, 0x1fa7, 0x1fc5, 0x1fa7, + 0x1fa7, 0x1fa7, 0x1fd3, 0x1fa7, 0x1fa7, 0x1fa7, 0x1fe1, 0x1fa7, + 0x1fa7, 0x1fa7, 0x1fef, 0x1fa7, 0x1fa7, 0x1fa7, 0x1ffd, 0x080c, 0x0d7d, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, - 0x0d7d, 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x2051, 0xa18c, + 0x0d7d, 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x2069, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa084, - 0x9420, 0xa088, 0x9319, 0x0804, 0x2051, 0xa19c, 0x2400, 0x9122, + 0x9420, 0xa088, 0x9319, 0x0804, 0x2069, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa094, 0x9420, 0xa098, - 0x9319, 0x0804, 0x2051, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, + 0x9319, 0x0804, 0x2069, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, - 0x2051, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, - 0x0d7d, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x2051, 0xa1cc, + 0x2069, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, + 0x0d7d, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x2069, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa0c4, - 0x9420, 0xa0c8, 0x9319, 0x0804, 0x2051, 0xa1dc, 0x2400, 0x9122, + 0x9420, 0xa0c8, 0x9319, 0x0804, 0x2069, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa0d4, 0x9420, 0xa0d8, - 0x9319, 0x0804, 0x2051, 0x9082, 0x001b, 0x0002, 0x2011, 0x200f, - 0x200f, 0x200f, 0x200f, 0x200f, 0x201e, 0x200f, 0x200f, 0x200f, - 0x200f, 0x200f, 0x202b, 0x200f, 0x200f, 0x200f, 0x200f, 0x200f, - 0x2038, 0x200f, 0x200f, 0x200f, 0x200f, 0x200f, 0x2045, 0x080c, + 0x9319, 0x0804, 0x2069, 0x9082, 0x001b, 0x0002, 0x2029, 0x2027, + 0x2027, 0x2027, 0x2027, 0x2027, 0x2036, 0x2027, 0x2027, 0x2027, + 0x2027, 0x2027, 0x2043, 0x2027, 0x2027, 0x2027, 0x2027, 0x2027, + 0x2050, 0x2027, 0x2027, 0x2027, 0x2027, 0x2027, 0x205d, 0x080c, 0x0d7d, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0d7d, 0xa084, 0x9420, @@ -836,26 +839,26 @@ unsigned short risc_code01[] = { 0x000f, 0x9405, 0x001e, 0x00ce, 0x0005, 0x7803, 0x0003, 0x780f, 0x0000, 0x6004, 0x7812, 0x2c04, 0x7816, 0x9ce0, 0x0002, 0x918a, 0x0002, 0x1db8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, - 0x0d76, 0xd094, 0x0110, 0x080c, 0x11e9, 0x0005, 0x0126, 0x2091, + 0x0d76, 0xd094, 0x0110, 0x080c, 0x11f6, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, - 0xd0a4, 0x190c, 0x21be, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, - 0x001a, 0x9084, 0x000e, 0x0002, 0x20dc, 0x20d4, 0x7ed0, 0x20d4, - 0x20d6, 0x20d6, 0x20d6, 0x20d6, 0x7eb6, 0x20d4, 0x20d8, 0x20d4, - 0x20d6, 0x20d4, 0x20d6, 0x20d4, 0x080c, 0x0d7d, 0x0031, 0x0020, - 0x080c, 0x7eb6, 0x080c, 0x7ed0, 0x0005, 0x0006, 0x0016, 0x0026, - 0x080c, 0xe733, 0x7930, 0x9184, 0x0003, 0x0510, 0x080c, 0xa888, + 0xd0a4, 0x190c, 0x21d6, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, + 0x001a, 0x9084, 0x000e, 0x0002, 0x20f4, 0x20ec, 0x7ef4, 0x20ec, + 0x20ee, 0x20ee, 0x20ee, 0x20ee, 0x7eda, 0x20ec, 0x20f0, 0x20ec, + 0x20ee, 0x20ec, 0x20ee, 0x20ec, 0x080c, 0x0d7d, 0x0031, 0x0020, + 0x080c, 0x7eda, 0x080c, 0x7ef4, 0x0005, 0x0006, 0x0016, 0x0026, + 0x080c, 0xe770, 0x7930, 0x9184, 0x0003, 0x0510, 0x080c, 0xa899, 0x2001, 0x19f9, 0x2004, 0x9005, 0x01a0, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0d7d, 0x00c6, 0x2001, 0x19f9, 0x2064, 0x080c, - 0xa8a4, 0x080c, 0xc430, 0x2009, 0x0040, 0x080c, 0x21c1, 0x00ce, - 0x0408, 0x2009, 0x0040, 0x080c, 0x21c1, 0x080c, 0xa8a4, 0x00d0, + 0xa8b5, 0x080c, 0xc453, 0x2009, 0x0040, 0x080c, 0x21d9, 0x00ce, + 0x0408, 0x2009, 0x0040, 0x080c, 0x21d9, 0x080c, 0xa8b5, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, - 0x74c8, 0x1138, 0x080c, 0x77cc, 0x080c, 0x6024, 0x080c, 0x73f9, - 0x0010, 0x080c, 0x5edf, 0x080c, 0x7f6e, 0x0041, 0x0018, 0x9184, + 0x74ec, 0x1138, 0x080c, 0x77ef, 0x080c, 0x6044, 0x080c, 0x741d, + 0x0010, 0x080c, 0x5eff, 0x080c, 0x7f92, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0x1a6a, 0x080c, 0x1ac2, 0x005e, 0x004e, + 0x0046, 0x0056, 0x2071, 0x1a6a, 0x080c, 0x1adf, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, 0x2001, 0x196e, 0x2102, 0x2001, 0x1976, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, @@ -877,18 +880,18 @@ unsigned short risc_code01[] = { 0x0d76, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, - 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a15, 0x080c, - 0x292f, 0x2001, 0x199c, 0x2003, 0x0000, 0x2001, 0x199d, 0x2003, - 0x0000, 0x080c, 0x2a86, 0x9006, 0x080c, 0x295e, 0x9006, 0x080c, - 0x2941, 0x20a9, 0x0012, 0x1d04, 0x21f3, 0x2091, 0x6000, 0x1f04, - 0x21f3, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, - 0x9084, 0xdfff, 0x6052, 0x6224, 0x080c, 0x2a63, 0x080c, 0x264d, - 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x265d, 0x60e7, 0x0000, + 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a35, 0x080c, + 0x294b, 0x2001, 0x199c, 0x2003, 0x0700, 0x2001, 0x199d, 0x2003, + 0x0700, 0x080c, 0x2aa6, 0x9006, 0x080c, 0x297a, 0x9006, 0x080c, + 0x295d, 0x20a9, 0x0012, 0x1d04, 0x220b, 0x2091, 0x6000, 0x1f04, + 0x220b, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, + 0x9084, 0xdfff, 0x6052, 0x6224, 0x080c, 0x2a83, 0x080c, 0x2669, + 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x2679, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x349f, 0x00c6, 0x2061, 0x0140, 0x608b, 0x000b, 0x608f, 0x10b8, 0x6093, 0x0000, 0x6097, 0x0198, 0x00ce, 0x6004, 0x9085, 0x8000, 0x6006, 0x60bb, 0x0000, 0x20a9, - 0x0018, 0x60bf, 0x0000, 0x1f04, 0x2231, 0x60bb, 0x0000, 0x60bf, + 0x0018, 0x60bf, 0x0000, 0x1f04, 0x2249, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402c, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, @@ -900,542 +903,543 @@ unsigned short risc_code01[] = { 0x1198, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007, 0x0082, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4, 0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, 0x0387, 0x200c, - 0xd1b4, 0x001e, 0x0d30, 0x0c58, 0x229f, 0x229c, 0x229c, 0x229c, - 0x229e, 0x229c, 0x229c, 0x229c, 0x080c, 0x0d7d, 0x0029, 0x002e, + 0xd1b4, 0x001e, 0x0d30, 0x0c58, 0x22b7, 0x22b4, 0x22b4, 0x22b4, + 0x22b6, 0x22b4, 0x22b4, 0x22b4, 0x080c, 0x0d7d, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, - 0x0118, 0xd19c, 0x1904, 0x2519, 0xd1f4, 0x190c, 0x0d76, 0x080c, - 0x74c8, 0x0904, 0x22fc, 0x080c, 0xcf51, 0x1120, 0x7000, 0x9086, - 0x0003, 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x74eb, - 0x0118, 0x080c, 0x74d9, 0x1530, 0x2011, 0x0020, 0x080c, 0x2a63, - 0x6043, 0x0000, 0x080c, 0xcf51, 0x0168, 0x080c, 0x74eb, 0x1150, - 0x2001, 0x19a6, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x733e, - 0x0804, 0x251c, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, - 0x2069, 0x0140, 0x080c, 0x751f, 0x00de, 0x1904, 0x251c, 0x080c, - 0x77d6, 0x0428, 0x080c, 0x74eb, 0x1590, 0x6024, 0x9084, 0x1800, - 0x1108, 0x0468, 0x080c, 0x77d6, 0x080c, 0x77cc, 0x080c, 0x6024, - 0x080c, 0x73f9, 0x0804, 0x2519, 0xd1ac, 0x1508, 0x6024, 0xd0dc, + 0x0118, 0xd19c, 0x1904, 0x2531, 0xd1f4, 0x190c, 0x0d76, 0x080c, + 0x74ec, 0x0904, 0x2314, 0x080c, 0xcf84, 0x1120, 0x7000, 0x9086, + 0x0003, 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x750f, + 0x0118, 0x080c, 0x74fd, 0x1530, 0x2011, 0x0020, 0x080c, 0x2a83, + 0x6043, 0x0000, 0x080c, 0xcf84, 0x0168, 0x080c, 0x750f, 0x1150, + 0x2001, 0x19a6, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x7362, + 0x0804, 0x2534, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, + 0x2069, 0x0140, 0x080c, 0x7543, 0x00de, 0x1904, 0x2534, 0x080c, + 0x77f9, 0x0428, 0x080c, 0x750f, 0x1590, 0x6024, 0x9084, 0x1800, + 0x1108, 0x0468, 0x080c, 0x77f9, 0x080c, 0x77ef, 0x080c, 0x6044, + 0x080c, 0x741d, 0x0804, 0x2531, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, - 0x9086, 0x0028, 0x1110, 0x080c, 0x76ad, 0x0804, 0x2519, 0x080c, - 0x77d1, 0x0048, 0x2001, 0x197c, 0x2003, 0x0002, 0x0020, 0x080c, - 0x760a, 0x0804, 0x2519, 0x080c, 0x7750, 0x0804, 0x2519, 0x6220, - 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x257e, 0xd2b4, 0x1904, 0x2590, - 0x0000, 0xd1ac, 0x0904, 0x2426, 0x0036, 0x6328, 0xc3bc, 0x632a, - 0x003e, 0x080c, 0x74c8, 0x11d0, 0x2011, 0x0020, 0x080c, 0x2a63, - 0x0006, 0x0026, 0x0036, 0x080c, 0x74e2, 0x1158, 0x080c, 0x77cc, - 0x080c, 0x6024, 0x080c, 0x73f9, 0x003e, 0x002e, 0x000e, 0x00ae, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x749c, 0x0016, 0x0046, + 0x9086, 0x0028, 0x1110, 0x080c, 0x76d0, 0x0804, 0x2531, 0x080c, + 0x77f4, 0x0048, 0x2001, 0x197c, 0x2003, 0x0002, 0x0020, 0x080c, + 0x762d, 0x0804, 0x2531, 0x080c, 0x7773, 0x0804, 0x2531, 0x6220, + 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x259a, 0xd2b4, 0x1904, 0x25ac, + 0x0000, 0xd1ac, 0x0904, 0x243e, 0x0036, 0x6328, 0xc3bc, 0x632a, + 0x003e, 0x080c, 0x74ec, 0x11d0, 0x2011, 0x0020, 0x080c, 0x2a83, + 0x0006, 0x0026, 0x0036, 0x080c, 0x7506, 0x1158, 0x080c, 0x77ef, + 0x080c, 0x6044, 0x080c, 0x741d, 0x003e, 0x002e, 0x000e, 0x00ae, + 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x74c0, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7048, 0xd084, 0x1148, - 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x4b09, - 0x003e, 0x080c, 0xcf4a, 0x1904, 0x23fd, 0x9196, 0xff00, 0x05a8, + 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x4b29, + 0x003e, 0x080c, 0xcf7d, 0x1904, 0x2415, 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, - 0x7130, 0xd184, 0x1550, 0x080c, 0x335c, 0x0128, 0xc18d, 0x7132, - 0x080c, 0x6a62, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, + 0x7130, 0xd184, 0x1550, 0x080c, 0x337c, 0x0128, 0xc18d, 0x7132, + 0x080c, 0x6a86, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, - 0x23fd, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, - 0x1904, 0x23fd, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, - 0x080c, 0x4b09, 0x003e, 0x0804, 0x23fd, 0x7038, 0xd08c, 0x1140, - 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x23fd, 0xc1ad, 0x2102, - 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4b09, 0x003e, 0x7130, + 0x2415, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, + 0x1904, 0x2415, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, + 0x080c, 0x4b29, 0x003e, 0x0804, 0x2415, 0x7038, 0xd08c, 0x1140, + 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2415, 0xc1ad, 0x2102, + 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4b29, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x01f0, 0x0016, - 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x88ce, 0x2019, 0x000e, - 0x00c6, 0x2061, 0x0000, 0x080c, 0xe249, 0x00ce, 0x9484, 0x00ff, - 0x9080, 0x3368, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, - 0x2009, 0x000e, 0x080c, 0xe2d9, 0x001e, 0x0016, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x31b4, 0x001e, 0x0078, 0x0156, 0x00b6, - 0x20a9, 0x007f, 0x900e, 0x080c, 0x6620, 0x1110, 0x080c, 0x603e, - 0x8108, 0x1f04, 0x23f3, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, - 0xa888, 0x080c, 0xab50, 0x080c, 0xa8a4, 0x60e3, 0x0000, 0x001e, + 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8902, 0x2019, 0x000e, + 0x00c6, 0x2061, 0x0000, 0x080c, 0xe286, 0x00ce, 0x9484, 0x00ff, + 0x9080, 0x3388, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, + 0x2009, 0x000e, 0x080c, 0xe316, 0x001e, 0x0016, 0x2009, 0x0002, + 0x2019, 0x0004, 0x080c, 0x31d4, 0x001e, 0x0078, 0x0156, 0x00b6, + 0x20a9, 0x007f, 0x900e, 0x080c, 0x6644, 0x1110, 0x080c, 0x605e, + 0x8108, 0x1f04, 0x240b, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, + 0xa899, 0x080c, 0xab61, 0x080c, 0xa8b5, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11b0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x1826, - 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x2a63, 0xd194, 0x0904, - 0x2519, 0x0016, 0x080c, 0xa888, 0x6220, 0xd2b4, 0x0904, 0x24b4, - 0x080c, 0x86d5, 0x080c, 0x9e16, 0x2011, 0x0004, 0x080c, 0x2a63, - 0x00f6, 0x2019, 0x19f2, 0x2304, 0x907d, 0x0904, 0x2481, 0x7804, + 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x2a83, 0xd194, 0x0904, + 0x2531, 0x0016, 0x080c, 0xa899, 0x6220, 0xd2b4, 0x0904, 0x24cc, + 0x080c, 0x8709, 0x080c, 0x9e4f, 0x2011, 0x0004, 0x080c, 0x2a83, + 0x00f6, 0x2019, 0x19f2, 0x2304, 0x907d, 0x0904, 0x2499, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, - 0x1df0, 0x080c, 0x2a39, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, - 0x0009, 0x080c, 0x29f0, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, - 0x0100, 0x080c, 0x2a29, 0x9006, 0x080c, 0x2a29, 0x080c, 0x95c6, - 0x080c, 0xa8a4, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, - 0xabdf, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, + 0x1df0, 0x080c, 0x2a59, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, + 0x0009, 0x080c, 0x2a10, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, + 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, 0x2a49, 0x080c, 0x95ff, + 0x080c, 0xa8b5, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, + 0xabf0, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, - 0x0110, 0x080c, 0x2a39, 0x00de, 0x00c6, 0x2061, 0x19e6, 0x6034, - 0x080c, 0xcf51, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, - 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, 0x9dee, 0x0804, - 0x2516, 0x2061, 0x0100, 0x62c0, 0x080c, 0xa7b9, 0x2019, 0x19f2, + 0x0110, 0x080c, 0x2a59, 0x00de, 0x00c6, 0x2061, 0x19e6, 0x6034, + 0x080c, 0xcf84, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, + 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, 0x9e27, 0x0804, + 0x252e, 0x2061, 0x0100, 0x62c0, 0x080c, 0xa7ca, 0x2019, 0x19f2, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, 0x0027, 0x080c, - 0xac7c, 0x00ce, 0x0804, 0x2516, 0xd2bc, 0x0904, 0x24f9, 0x080c, - 0x86e2, 0x2011, 0x0004, 0x080c, 0x2a63, 0x00d6, 0x2069, 0x0140, - 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2a39, 0x00de, 0x00c6, - 0x2061, 0x19e6, 0x6050, 0x080c, 0xcf51, 0x0120, 0x909a, 0x0003, + 0xac8d, 0x00ce, 0x0804, 0x252e, 0xd2bc, 0x0904, 0x2511, 0x080c, + 0x8716, 0x2011, 0x0004, 0x080c, 0x2a83, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2a59, 0x00de, 0x00c6, + 0x2061, 0x19e6, 0x6050, 0x080c, 0xcf84, 0x0120, 0x909a, 0x0003, 0x1668, 0x0018, 0x909a, 0x00c8, 0x1648, 0x8000, 0x6052, 0x604c, - 0x00ce, 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c, 0x86da, 0x9080, + 0x00ce, 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c, 0x870e, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, - 0x0012, 0x080c, 0x2a72, 0x0450, 0x9080, 0x0008, 0x2004, 0x9086, - 0x0009, 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2a72, - 0x00e8, 0x2011, 0x0004, 0x080c, 0x2a63, 0x00c0, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa0fa, 0x003e, 0x2019, 0x19f9, 0x2304, 0x9065, + 0x0012, 0x080c, 0x2a92, 0x0450, 0x9080, 0x0008, 0x2004, 0x9086, + 0x0009, 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2a92, + 0x00e8, 0x2011, 0x0004, 0x080c, 0x2a83, 0x00c0, 0x0036, 0x2019, + 0x0001, 0x080c, 0xa133, 0x003e, 0x2019, 0x19f9, 0x2304, 0x9065, 0x0160, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, - 0x004f, 0x6003, 0x0003, 0x080c, 0xac7c, 0x00ce, 0x080c, 0xa8a4, - 0x001e, 0xd19c, 0x0904, 0x2577, 0x7038, 0xd0ac, 0x1538, 0x0016, - 0x0156, 0x2011, 0x0008, 0x080c, 0x2a63, 0x6050, 0xc0e5, 0x6052, - 0x20a9, 0x0367, 0x1f04, 0x2544, 0x1d04, 0x252c, 0x080c, 0x8709, - 0x6020, 0xd09c, 0x1db8, 0x00f6, 0x2079, 0x0100, 0x080c, 0x29a0, - 0x00fe, 0x1d80, 0x6050, 0xc0e4, 0x6052, 0x2011, 0x0008, 0x080c, - 0x2a63, 0x015e, 0x001e, 0x0498, 0x015e, 0x001e, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x080c, 0xa888, 0x080c, 0xab50, 0x080c, 0xa8a4, - 0x60e3, 0x0000, 0x080c, 0xe712, 0x080c, 0xe72d, 0x080c, 0x56d9, - 0xd0fc, 0x1138, 0x080c, 0xcf4a, 0x1120, 0x9085, 0x0001, 0x080c, - 0x750f, 0x9006, 0x080c, 0x2a29, 0x2009, 0x0002, 0x080c, 0x2a15, - 0x00e6, 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0eb4, 0x00ee, - 0x2011, 0x0008, 0x080c, 0x2a63, 0x080c, 0x0bc3, 0x001e, 0x918c, - 0xffd0, 0x2110, 0x080c, 0x2a63, 0x00ae, 0x0005, 0x0016, 0x2001, - 0x0387, 0x200c, 0xd1a4, 0x001e, 0x0904, 0x2329, 0x0016, 0x2009, - 0x258a, 0x00c0, 0x2001, 0x0387, 0x2003, 0x1000, 0x001e, 0x0c38, - 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, 0x001e, 0x0904, 0x2329, - 0x0016, 0x2009, 0x259c, 0x0030, 0x2001, 0x0387, 0x2003, 0x4000, - 0x001e, 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, - 0xbc91, 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2a0f, - 0x2011, 0x0080, 0x080c, 0x2a63, 0x6017, 0x0000, 0x6043, 0x0000, - 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, - 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, 0x70d2, 0x9116, 0x0904, - 0x260c, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x2a15, 0x2011, - 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, - 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x4b09, 0x0468, 0x2001, - 0x19a7, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, - 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, - 0x4b09, 0x080c, 0x0eb4, 0x080c, 0x56d9, 0xd0fc, 0x11a8, 0x080c, - 0xcf4a, 0x1190, 0x00c6, 0x080c, 0x26a8, 0x080c, 0xa888, 0x080c, - 0xa055, 0x080c, 0xa8a4, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, - 0x0002, 0x080c, 0x31b4, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, - 0x9094, 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, - 0x81ff, 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, - 0x1820, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, - 0x2011, 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, - 0x1120, 0x2500, 0x080c, 0x81de, 0x0048, 0x9584, 0x00ff, 0x9080, - 0x3368, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, - 0x3368, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, - 0x2001, 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, - 0x6856, 0x1f04, 0x2658, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, - 0x2069, 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, - 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, - 0x9184, 0x000f, 0x9080, 0xe741, 0x2005, 0x6856, 0x8211, 0x1f04, - 0x266d, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, - 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, - 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, - 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, - 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x269d, - 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, - 0x080c, 0x56d5, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xe2d9, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2714, - 0x080c, 0x2990, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, - 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, - 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, - 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, - 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, - 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, - 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, - 0x9080, 0x0020, 0x2018, 0x080c, 0x9148, 0x928c, 0xff00, 0x0110, - 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, - 0x0138, 0x220a, 0x080c, 0x74c8, 0x1118, 0x2009, 0x196c, 0x220a, - 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, - 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0d76, 0x002e, - 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, - 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, - 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, - 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, - 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, - 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, - 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x198f, 0x2004, - 0x908a, 0x0007, 0x1a0c, 0x0d7d, 0x0033, 0x00ee, 0x002e, 0x001e, - 0x000e, 0x015e, 0x0005, 0x2772, 0x2790, 0x27b4, 0x27b6, 0x27df, - 0x27e1, 0x27e3, 0x2001, 0x0001, 0x080c, 0x25b9, 0x080c, 0x29da, - 0x2001, 0x1991, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, - 0x9006, 0x20a9, 0x0009, 0x080c, 0x29ac, 0x2001, 0x198f, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x27e4, 0x080c, 0x86e7, 0x0005, - 0x2009, 0x1994, 0x200b, 0x0000, 0x2001, 0x1999, 0x2003, 0x0036, - 0x2001, 0x1998, 0x2003, 0x002a, 0x2001, 0x1991, 0x2003, 0x0001, - 0x9006, 0x080c, 0x2941, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, - 0x29ac, 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x27e4, 0x080c, 0x86e7, 0x0005, 0x080c, 0x0d7d, 0x2001, 0x1999, - 0x2003, 0x0036, 0x2001, 0x1991, 0x2003, 0x0003, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x2941, 0x2001, 0x1995, 0x2003, 0x0000, 0x2001, 0xffff, - 0x20a9, 0x0009, 0x080c, 0x29ac, 0x2001, 0x198f, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x27e4, 0x080c, 0x86e7, 0x0005, 0x080c, - 0x0d7d, 0x080c, 0x0d7d, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, - 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, - 0x1991, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d7d, 0x0043, 0x012e, - 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2806, - 0x2826, 0x2866, 0x2896, 0x28ba, 0x28ca, 0x28cc, 0x080c, 0x29a0, - 0x11b0, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1997, 0x2104, - 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, - 0xc085, 0x200a, 0x2001, 0x198f, 0x2003, 0x0001, 0x0030, 0x080c, - 0x28f0, 0x2001, 0xffff, 0x080c, 0x2781, 0x0005, 0x080c, 0x28ce, - 0x05e0, 0x2009, 0x1998, 0x2104, 0x8001, 0x200a, 0x080c, 0x29a0, - 0x1178, 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0005, 0x0518, 0x2009, 0x1997, 0x2104, 0xc085, 0x200a, - 0x2009, 0x1994, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, - 0x080c, 0x28d6, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, - 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, - 0x295e, 0x2001, 0x1991, 0x2003, 0x0002, 0x0028, 0x2001, 0x198f, - 0x2003, 0x0003, 0x0010, 0x080c, 0x27a3, 0x0005, 0x080c, 0x28ce, - 0x0560, 0x2009, 0x1998, 0x2104, 0x8001, 0x200a, 0x080c, 0x29a0, - 0x1168, 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x198f, 0x2003, - 0x0003, 0x2001, 0x1990, 0x2003, 0x0000, 0x00b8, 0x2009, 0x1998, - 0x2104, 0x9005, 0x1118, 0x080c, 0x2913, 0x0010, 0x080c, 0x28e3, - 0x080c, 0x28d6, 0x2009, 0x1994, 0x200b, 0x0000, 0x2001, 0x1991, - 0x2003, 0x0001, 0x080c, 0x27a3, 0x0000, 0x0005, 0x04b9, 0x0508, - 0x080c, 0x29a0, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, - 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, - 0x2001, 0x199a, 0x2003, 0x000a, 0x2009, 0x1997, 0x2104, 0xc0fd, - 0x200a, 0x0038, 0x0419, 0x2001, 0x1991, 0x2003, 0x0004, 0x080c, - 0x27ce, 0x0005, 0x0099, 0x0168, 0x080c, 0x29a0, 0x1138, 0x7850, - 0x9084, 0xefff, 0x7852, 0x080c, 0x27ba, 0x0018, 0x0079, 0x080c, - 0x27ce, 0x0005, 0x080c, 0x0d7d, 0x080c, 0x0d7d, 0x2009, 0x1999, - 0x2104, 0x8001, 0x200a, 0x090c, 0x292f, 0x0005, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x295e, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, - 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2941, 0x0005, - 0x2009, 0x1994, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, - 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, - 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x295e, 0x0005, 0x0086, 0x2001, 0x1997, 0x2004, 0x9084, - 0x7fff, 0x090c, 0x0d7d, 0x2009, 0x1996, 0x2144, 0x8846, 0x280a, - 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, 0x0d7d, - 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, - 0x0156, 0x2001, 0x198f, 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, - 0x1f04, 0x2935, 0x2001, 0x1996, 0x2003, 0x8000, 0x015e, 0x000e, - 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, - 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x199c, 0x210c, - 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, - 0x2009, 0x199d, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfffa, 0x9085, - 0x0004, 0x783a, 0x7850, 0x9084, 0xfff0, 0x7852, 0x00f8, 0x7838, - 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x7850, 0x9084, 0xfff0, - 0x0016, 0x2009, 0x017f, 0x210c, 0x918e, 0x0005, 0x0140, 0x2009, - 0x0003, 0x210c, 0x918c, 0x0600, 0x918e, 0x0400, 0x0118, 0x9085, - 0x000a, 0x0010, 0x9085, 0x0000, 0x001e, 0x7852, 0x00fe, 0x0005, - 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, - 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, - 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2a0f, 0xd09c, 0x1110, - 0x1f04, 0x29a3, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, - 0x8000, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, + 0x004f, 0x6003, 0x0003, 0x080c, 0xac8d, 0x00ce, 0x080c, 0xa8b5, + 0x001e, 0xd19c, 0x0904, 0x2593, 0x7038, 0xd0ac, 0x1558, 0x0016, + 0x0156, 0x2011, 0x0008, 0x080c, 0x2a83, 0x080c, 0x2aa6, 0x080c, + 0x2ad9, 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367, 0x1f04, 0x2560, + 0x1d04, 0x2548, 0x080c, 0x873d, 0x6020, 0xd09c, 0x1db8, 0x00f6, + 0x2079, 0x0100, 0x080c, 0x29bc, 0x00fe, 0x1d80, 0x6050, 0xc0e4, + 0x6052, 0x2011, 0x0008, 0x080c, 0x2a83, 0x015e, 0x001e, 0x0498, + 0x015e, 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xa899, + 0x080c, 0xab61, 0x080c, 0xa8b5, 0x60e3, 0x0000, 0x080c, 0xe74f, + 0x080c, 0xe76a, 0x080c, 0x56f9, 0xd0fc, 0x1138, 0x080c, 0xcf7d, + 0x1120, 0x9085, 0x0001, 0x080c, 0x7533, 0x9006, 0x080c, 0x2a49, + 0x2009, 0x0002, 0x080c, 0x2a35, 0x00e6, 0x2071, 0x1800, 0x7003, + 0x0004, 0x080c, 0x0ec1, 0x00ee, 0x2011, 0x0008, 0x080c, 0x2a83, + 0x080c, 0x0bc3, 0x001e, 0x918c, 0xffd0, 0x2110, 0x080c, 0x2a83, + 0x00ae, 0x0005, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4, 0x001e, + 0x0904, 0x2341, 0x0016, 0x2009, 0x25a6, 0x00c0, 0x2001, 0x0387, + 0x2003, 0x1000, 0x001e, 0x0c38, 0x0016, 0x2001, 0x0387, 0x200c, + 0xd1b4, 0x001e, 0x0904, 0x2341, 0x0016, 0x2009, 0x25b8, 0x0030, + 0x2001, 0x0387, 0x2003, 0x4000, 0x001e, 0x08a8, 0x6028, 0xc0bc, + 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003, 0xffff, + 0x6043, 0x0001, 0x080c, 0x2a2f, 0x2011, 0x0080, 0x080c, 0x2a83, + 0x6017, 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, + 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, + 0x71d0, 0x70d2, 0x9116, 0x0904, 0x2628, 0x81ff, 0x01a0, 0x2009, + 0x0000, 0x080c, 0x2a35, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, + 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, + 0x080c, 0x4b29, 0x0468, 0x2001, 0x19a7, 0x200c, 0x81ff, 0x1140, + 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, + 0x2118, 0x2011, 0x8012, 0x080c, 0x4b29, 0x080c, 0x0ec1, 0x080c, + 0x56f9, 0xd0fc, 0x11a8, 0x080c, 0xcf7d, 0x1190, 0x00c6, 0x080c, + 0x26c4, 0x080c, 0xa899, 0x080c, 0xa08e, 0x080c, 0xa8b5, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x31d4, 0x00ce, + 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, + 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181f, + 0x2204, 0x9106, 0x1190, 0x2011, 0x1820, 0x2214, 0x9294, 0xff00, + 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, 0x1820, 0x2214, 0x9294, + 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, 0x2500, 0x080c, 0x8202, + 0x0048, 0x9584, 0x00ff, 0x9080, 0x3388, 0x200d, 0x918c, 0xff00, + 0x810f, 0x9006, 0x0005, 0x9080, 0x3388, 0x200d, 0x918c, 0x00ff, + 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1818, 0x2003, 0x00ef, + 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x2674, 0x00de, + 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1818, + 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, + 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xe77e, + 0x2005, 0x6856, 0x8211, 0x1f04, 0x2689, 0x002e, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, 0x0110, 0xc09d, 0x0008, + 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, + 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, + 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, + 0x0404, 0x680e, 0x1f04, 0x26b9, 0x680f, 0x0000, 0x000e, 0x001e, + 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, 0x56f5, 0xd0c4, 0x0150, + 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, + 0xe316, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, + 0x78c4, 0xd0dc, 0x0904, 0x2730, 0x080c, 0x29ac, 0x0660, 0x9084, + 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, + 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, + 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, + 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, + 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, + 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, + 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, + 0x9181, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, + 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x74ec, + 0x1118, 0x2009, 0x196c, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, + 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, + 0x0110, 0x080c, 0x0d76, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, + 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, + 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, + 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, + 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, + 0x00e6, 0x2001, 0x198f, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d7d, + 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x278e, + 0x27ac, 0x27d0, 0x27d2, 0x27fb, 0x27fd, 0x27ff, 0x2001, 0x0001, + 0x080c, 0x25d5, 0x080c, 0x29fa, 0x2001, 0x1991, 0x2003, 0x0000, + 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, + 0x29c8, 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, + 0x2800, 0x080c, 0x871b, 0x0005, 0x2009, 0x1994, 0x200b, 0x0000, + 0x2001, 0x1999, 0x2003, 0x0036, 0x2001, 0x1998, 0x2003, 0x002a, + 0x2001, 0x1991, 0x2003, 0x0001, 0x9006, 0x080c, 0x295d, 0x2001, + 0xffff, 0x20a9, 0x0009, 0x080c, 0x29c8, 0x2001, 0x198f, 0x2003, + 0x0006, 0x2009, 0x001e, 0x2011, 0x2800, 0x080c, 0x871b, 0x0005, + 0x080c, 0x0d7d, 0x2001, 0x1999, 0x2003, 0x0036, 0x2001, 0x1991, + 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x295d, 0x2001, 0x1995, + 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x29c8, + 0x2001, 0x198f, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2800, + 0x080c, 0x871b, 0x0005, 0x080c, 0x0d7d, 0x080c, 0x0d7d, 0x0005, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0100, 0x2001, 0x1991, 0x2004, 0x908a, 0x0007, + 0x1a0c, 0x0d7d, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, + 0x001e, 0x000e, 0x0005, 0x2822, 0x2842, 0x2882, 0x28b2, 0x28d6, + 0x28e6, 0x28e8, 0x080c, 0x29bc, 0x11b0, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2009, 0x1997, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x198f, + 0x2003, 0x0001, 0x0030, 0x080c, 0x290c, 0x2001, 0xffff, 0x080c, + 0x279d, 0x0005, 0x080c, 0x28ea, 0x05e0, 0x2009, 0x1998, 0x2104, + 0x8001, 0x200a, 0x080c, 0x29bc, 0x1178, 0x7850, 0x9084, 0xefff, + 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, + 0x1997, 0x2104, 0xc085, 0x200a, 0x2009, 0x1994, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x28f2, 0x00c0, 0x200b, + 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x297a, 0x2001, 0x1991, 0x2003, + 0x0002, 0x0028, 0x2001, 0x198f, 0x2003, 0x0003, 0x0010, 0x080c, + 0x27bf, 0x0005, 0x080c, 0x28ea, 0x0560, 0x2009, 0x1998, 0x2104, + 0x8001, 0x200a, 0x080c, 0x29bc, 0x1168, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2001, 0x198f, 0x2003, 0x0003, 0x2001, 0x1990, 0x2003, + 0x0000, 0x00b8, 0x2009, 0x1998, 0x2104, 0x9005, 0x1118, 0x080c, + 0x292f, 0x0010, 0x080c, 0x28ff, 0x080c, 0x28f2, 0x2009, 0x1994, + 0x200b, 0x0000, 0x2001, 0x1991, 0x2003, 0x0001, 0x080c, 0x27bf, + 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x29bc, 0x11b8, 0x7850, + 0x9084, 0xefff, 0x7852, 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, + 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x199a, 0x2003, 0x000a, + 0x2009, 0x1997, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, + 0x1991, 0x2003, 0x0004, 0x080c, 0x27ea, 0x0005, 0x0099, 0x0168, + 0x080c, 0x29bc, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, + 0x27d6, 0x0018, 0x0079, 0x080c, 0x27ea, 0x0005, 0x080c, 0x0d7d, + 0x080c, 0x0d7d, 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x090c, + 0x294b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x297a, 0x0005, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, + 0x0001, 0x080c, 0x295d, 0x0005, 0x2009, 0x1994, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, + 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x297a, 0x0005, 0x0086, + 0x2001, 0x1997, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d7d, 0x2009, + 0x1996, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, + 0xd084, 0x1120, 0x080c, 0x0d7d, 0x9006, 0x0010, 0x2001, 0x0001, + 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x198f, 0x20a9, + 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x2951, 0x2001, 0x1996, + 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, + 0x783a, 0x2009, 0x199c, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, + 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199d, 0x210c, 0x795a, + 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, + 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x7850, 0x9084, + 0xfff0, 0x7852, 0x00f8, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, + 0x783a, 0x7850, 0x9084, 0xfff0, 0x0016, 0x2009, 0x017f, 0x210c, + 0x918e, 0x0005, 0x0140, 0x2009, 0x0003, 0x210c, 0x918c, 0x0600, + 0x918e, 0x0400, 0x0118, 0x9085, 0x000a, 0x0010, 0x9085, 0x0000, + 0x001e, 0x7852, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, + 0x080c, 0x2a2f, 0xd09c, 0x1110, 0x1f04, 0x29bf, 0x015e, 0x0005, + 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x080c, 0x2aa6, 0x080c, + 0x2ad9, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, 0x1118, - 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x29cc, 0x080c, 0x8709, - 0x1f04, 0x29cc, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, - 0x012e, 0x0005, 0x080c, 0x2ab9, 0x0005, 0x0006, 0x0156, 0x00f6, + 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x29ec, 0x080c, 0x873d, + 0x1f04, 0x29ec, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, + 0x012e, 0x0005, 0x080c, 0x2ad9, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x29e7, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x1d04, 0x29f0, 0x080c, 0x8709, 0x1f04, 0x29f0, 0x0005, 0x0006, + 0xd08c, 0x1110, 0x1f04, 0x2a07, 0x00fe, 0x015e, 0x000e, 0x0005, + 0x1d04, 0x2a10, 0x080c, 0x873d, 0x1f04, 0x2a10, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, 0x2001, 0x199b, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x19a7, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, - 0x0005, 0x0016, 0x0026, 0x080c, 0x74e2, 0x0108, 0xc0bc, 0x2009, + 0x0005, 0x0016, 0x0026, 0x080c, 0x7506, 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x74e2, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, + 0x1128, 0x080c, 0x7506, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0101, 0x7844, 0xd084, 0x1de8, 0x2001, 0x0109, 0x2202, 0x7843, 0x0100, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0202, 0x7844, 0xd08c, 0x1de8, 0x2079, 0x0100, 0x7814, 0x9104, 0x9205, 0x7a16, 0x2079, 0x0380, 0x7843, 0x0200, 0x00fe, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, 0x9084, 0xfbff, 0x9085, - 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x29f0, 0x6050, 0x9085, - 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, 0x29f0, - 0x6054, 0xd0bc, 0x090c, 0x0d7d, 0x20a9, 0x0005, 0x080c, 0x29f0, + 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2a10, 0x6050, 0x9085, + 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, 0x2a10, + 0x6054, 0xd0bc, 0x090c, 0x0d7d, 0x20a9, 0x0005, 0x080c, 0x2a10, 0x6054, 0xd0ac, 0x090c, 0x0d7d, 0x2009, 0x19ae, 0x9084, 0x7e00, 0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, 0x6050, 0xc0cd, 0x6052, - 0x00ce, 0x000e, 0x0005, 0x2fbf, 0x2fbf, 0x2bc3, 0x2bc3, 0x2bcf, - 0x2bcf, 0x2bdb, 0x2bdb, 0x2be9, 0x2be9, 0x2bf5, 0x2bf5, 0x2c03, - 0x2c03, 0x2c11, 0x2c11, 0x2c23, 0x2c23, 0x2c2f, 0x2c2f, 0x2c3d, - 0x2c3d, 0x2c5b, 0x2c5b, 0x2c7b, 0x2c7b, 0x2c4b, 0x2c4b, 0x2c6b, - 0x2c6b, 0x2c89, 0x2c89, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c9b, 0x2c9b, 0x2ca7, 0x2ca7, 0x2cb5, - 0x2cb5, 0x2cc3, 0x2cc3, 0x2cd3, 0x2cd3, 0x2ce1, 0x2ce1, 0x2cf1, - 0x2cf1, 0x2d01, 0x2d01, 0x2d13, 0x2d13, 0x2d21, 0x2d21, 0x2d31, - 0x2d31, 0x2d53, 0x2d53, 0x2d77, 0x2d77, 0x2d41, 0x2d41, 0x2d65, - 0x2d65, 0x2d87, 0x2d87, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2d9b, 0x2d9b, 0x2da7, 0x2da7, 0x2db5, - 0x2db5, 0x2dc3, 0x2dc3, 0x2dd3, 0x2dd3, 0x2de1, 0x2de1, 0x2df1, - 0x2df1, 0x2e01, 0x2e01, 0x2e13, 0x2e13, 0x2e21, 0x2e21, 0x2e31, - 0x2e31, 0x2e41, 0x2e41, 0x2e53, 0x2e53, 0x2e63, 0x2e63, 0x2e75, - 0x2e75, 0x2e87, 0x2e87, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2e9b, 0x2e9b, 0x2ea9, 0x2ea9, 0x2eb9, - 0x2eb9, 0x2ec9, 0x2ec9, 0x2edb, 0x2edb, 0x2eeb, 0x2eeb, 0x2efd, - 0x2efd, 0x2f0f, 0x2f0f, 0x2f23, 0x2f23, 0x2f33, 0x2f33, 0x2f45, - 0x2f45, 0x2f57, 0x2f57, 0x2f6b, 0x2f6b, 0x2f7c, 0x2f7c, 0x2f8f, - 0x2f8f, 0x2fa2, 0x2fa2, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, 0x2c21, - 0x2c21, 0x2c21, 0x2c21, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2261, 0x0804, 0x2fb7, 0x0106, + 0x00ce, 0x000e, 0x0005, 0x2fdf, 0x2fdf, 0x2be3, 0x2be3, 0x2bef, + 0x2bef, 0x2bfb, 0x2bfb, 0x2c09, 0x2c09, 0x2c15, 0x2c15, 0x2c23, + 0x2c23, 0x2c31, 0x2c31, 0x2c43, 0x2c43, 0x2c4f, 0x2c4f, 0x2c5d, + 0x2c5d, 0x2c7b, 0x2c7b, 0x2c9b, 0x2c9b, 0x2c6b, 0x2c6b, 0x2c8b, + 0x2c8b, 0x2ca9, 0x2ca9, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2cbb, 0x2cbb, 0x2cc7, 0x2cc7, 0x2cd5, + 0x2cd5, 0x2ce3, 0x2ce3, 0x2cf3, 0x2cf3, 0x2d01, 0x2d01, 0x2d11, + 0x2d11, 0x2d21, 0x2d21, 0x2d33, 0x2d33, 0x2d41, 0x2d41, 0x2d51, + 0x2d51, 0x2d73, 0x2d73, 0x2d97, 0x2d97, 0x2d61, 0x2d61, 0x2d85, + 0x2d85, 0x2da7, 0x2da7, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2dbb, 0x2dbb, 0x2dc7, 0x2dc7, 0x2dd5, + 0x2dd5, 0x2de3, 0x2de3, 0x2df3, 0x2df3, 0x2e01, 0x2e01, 0x2e11, + 0x2e11, 0x2e21, 0x2e21, 0x2e33, 0x2e33, 0x2e41, 0x2e41, 0x2e51, + 0x2e51, 0x2e61, 0x2e61, 0x2e73, 0x2e73, 0x2e83, 0x2e83, 0x2e95, + 0x2e95, 0x2ea7, 0x2ea7, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2ebb, 0x2ebb, 0x2ec9, 0x2ec9, 0x2ed9, + 0x2ed9, 0x2ee9, 0x2ee9, 0x2efb, 0x2efb, 0x2f0b, 0x2f0b, 0x2f1d, + 0x2f1d, 0x2f2f, 0x2f2f, 0x2f43, 0x2f43, 0x2f53, 0x2f53, 0x2f65, + 0x2f65, 0x2f77, 0x2f77, 0x2f8b, 0x2f8b, 0x2f9c, 0x2f9c, 0x2faf, + 0x2faf, 0x2fc2, 0x2fc2, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, 0x2c41, + 0x2c41, 0x2c41, 0x2c41, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x208b, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, 0x2261, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2261, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0x2261, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x13ae, 0x0804, 0x2fb7, 0x0106, + 0x20a3, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, 0x2279, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2279, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0x2279, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2261, 0x080c, 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, - 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, 0x2261, 0x080c, - 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x0804, 0x2fb7, 0x0106, + 0x2279, 0x080c, 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, + 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, 0x2279, 0x080c, + 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x2261, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, - 0x208b, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, - 0x2261, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x2261, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0x2261, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x2261, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, - 0x2261, 0x080c, 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, - 0x208b, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, + 0x2733, 0x080c, 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, + 0x20a3, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, + 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x2279, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0x2279, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x2279, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, + 0x2279, 0x080c, 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, + 0x20a3, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, + 0x2733, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x208b, 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ee, 0x0804, 0x2fb7, 0x0106, + 0x2733, 0x080c, 0x20a3, 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ff, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0xa8ee, 0x080c, 0x2261, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, - 0xa8ee, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, - 0x2261, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ee, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x20b5, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ee, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x13ae, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, - 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ee, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, - 0x13ae, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x208b, 0x080c, - 0xa8ee, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, + 0xa8ff, 0x080c, 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, + 0xa8ff, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, + 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ff, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x20cd, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ff, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x13bb, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, + 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ff, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, + 0x13bb, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20a3, 0x080c, + 0xa8ff, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x208b, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x0804, - 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, - 0x2261, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, - 0x2261, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, - 0x208b, 0x080c, 0xa8ee, 0x080c, 0x20b5, 0x0804, 0x2fb7, 0x0106, + 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x0804, + 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, + 0x2279, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, + 0x2279, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, + 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, - 0x20b5, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, - 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, - 0x2261, 0x080c, 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, - 0x208b, 0x080c, 0xa8ee, 0x080c, 0x13ae, 0x0804, 0x2fb7, 0x0106, + 0x2733, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, + 0x20cd, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, + 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, + 0x2279, 0x080c, 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, + 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x208b, 0x080c, 0xa8ee, 0x080c, 0x2261, 0x080c, - 0x13ae, 0x0804, 0x2fb7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, 0x080c, - 0x13ae, 0x080c, 0x20b5, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0xa8ee, - 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0440, 0x0106, + 0x2733, 0x080c, 0x20a3, 0x080c, 0xa8ff, 0x080c, 0x2279, 0x080c, + 0x13bb, 0x0804, 0x2fd7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, 0x080c, + 0x13bb, 0x080c, 0x20cd, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0xa8ff, + 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0440, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2717, 0x080c, 0x208b, 0x080c, 0x13ae, 0x080c, 0xa8ee, 0x080c, - 0x20b5, 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2717, 0x080c, 0x208b, 0x080c, 0xa8ee, - 0x080c, 0x2261, 0x080c, 0x13ae, 0x080c, 0x20b5, 0x0000, 0x015e, + 0x2733, 0x080c, 0x20a3, 0x080c, 0x13bb, 0x080c, 0xa8ff, 0x080c, + 0x20cd, 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x2733, 0x080c, 0x20a3, 0x080c, 0xa8ff, + 0x080c, 0x2279, 0x080c, 0x13bb, 0x080c, 0x20cd, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, - 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a28, 0x1904, - 0x30d0, 0x72dc, 0x2001, 0x197b, 0x2004, 0x9005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x30d0, 0x080c, 0x30d5, - 0x0804, 0x30d0, 0xd2cc, 0x1904, 0x30d0, 0x080c, 0x74c8, 0x1120, - 0x70af, 0xffff, 0x0804, 0x30d0, 0xd294, 0x0120, 0x70af, 0xffff, - 0x0804, 0x30d0, 0x080c, 0x3357, 0x0160, 0x080c, 0xcf51, 0x0128, - 0x2001, 0x1818, 0x203c, 0x0804, 0x305d, 0x70af, 0xffff, 0x0804, - 0x30d0, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x305d, - 0xd28c, 0x1904, 0x305d, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, + 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a4c, 0x1904, + 0x30f0, 0x72dc, 0x2001, 0x197b, 0x2004, 0x9005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x30f0, 0x080c, 0x30f5, + 0x0804, 0x30f0, 0xd2cc, 0x1904, 0x30f0, 0x080c, 0x74ec, 0x1120, + 0x70af, 0xffff, 0x0804, 0x30f0, 0xd294, 0x0120, 0x70af, 0xffff, + 0x0804, 0x30f0, 0x080c, 0x3377, 0x0160, 0x080c, 0xcf84, 0x0128, + 0x2001, 0x1818, 0x203c, 0x0804, 0x307d, 0x70af, 0xffff, 0x0804, + 0x30f0, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x307d, + 0xd28c, 0x1904, 0x307d, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x05d0, 0x908e, 0x0000, 0x05b8, 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x15b0, 0x7294, 0xc28d, 0x7296, 0x70af, 0xffff, 0x003e, - 0x04a0, 0x900e, 0x080c, 0x2614, 0x080c, 0x65bf, 0x1538, 0x9006, + 0x04a0, 0x900e, 0x080c, 0x2630, 0x080c, 0x65e3, 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, - 0x8b72, 0x00ce, 0x090c, 0x8f16, 0xb8af, 0x0000, 0x080c, 0x6a6a, + 0x8ba9, 0x00ce, 0x090c, 0x8f4f, 0xb8af, 0x0000, 0x080c, 0x6a8e, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, 0x080c, - 0x6913, 0x0120, 0x080c, 0x30ee, 0x0148, 0x0028, 0x080c, 0x323a, - 0x080c, 0x311a, 0x0118, 0x8318, 0x0804, 0x300a, 0x73ae, 0x0010, - 0x70af, 0xffff, 0x003e, 0x0804, 0x30d0, 0x9780, 0x3368, 0x203d, + 0x6937, 0x0120, 0x080c, 0x310e, 0x0148, 0x0028, 0x080c, 0x325a, + 0x080c, 0x313a, 0x0118, 0x8318, 0x0804, 0x302a, 0x73ae, 0x0010, + 0x70af, 0xffff, 0x003e, 0x0804, 0x30f0, 0x9780, 0x3388, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, - 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x30d0, 0x2700, 0x0156, - 0x0016, 0x9106, 0x0904, 0x30c5, 0xc484, 0x080c, 0x6620, 0x0148, - 0x080c, 0xcf51, 0x1904, 0x30c5, 0x080c, 0x65bf, 0x1904, 0x30cd, + 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x30f0, 0x2700, 0x0156, + 0x0016, 0x9106, 0x0904, 0x30e5, 0xc484, 0x080c, 0x6644, 0x0148, + 0x080c, 0xcf84, 0x1904, 0x30e5, 0x080c, 0x65e3, 0x1904, 0x30ed, 0x0008, 0xc485, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, - 0x2060, 0x080c, 0x8b72, 0x00ce, 0x090c, 0x8f16, 0xb8af, 0x0000, - 0x080c, 0x6a6a, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, - 0x11e0, 0x7294, 0xd28c, 0x0180, 0x080c, 0x6a6a, 0x9082, 0x0006, - 0x02e0, 0xd484, 0x1118, 0x080c, 0x65e4, 0x0028, 0x080c, 0x32cd, - 0x01a0, 0x080c, 0x32f8, 0x0088, 0x080c, 0x323a, 0x080c, 0xcf51, - 0x1160, 0x080c, 0x311a, 0x0188, 0x0040, 0x080c, 0xcf51, 0x1118, - 0x080c, 0x32cd, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, - 0x1f04, 0x3076, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, + 0x2060, 0x080c, 0x8ba9, 0x00ce, 0x090c, 0x8f4f, 0xb8af, 0x0000, + 0x080c, 0x6a8e, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, + 0x11e0, 0x7294, 0xd28c, 0x0180, 0x080c, 0x6a8e, 0x9082, 0x0006, + 0x02e0, 0xd484, 0x1118, 0x080c, 0x6608, 0x0028, 0x080c, 0x32ed, + 0x01a0, 0x080c, 0x3318, 0x0088, 0x080c, 0x325a, 0x080c, 0xcf84, + 0x1160, 0x080c, 0x313a, 0x0188, 0x0040, 0x080c, 0xcf84, 0x1118, + 0x080c, 0x32ed, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, + 0x1f04, 0x3096, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, - 0x0001, 0x2009, 0x007e, 0x080c, 0x65bf, 0x1168, 0xb813, 0x00ff, - 0xb817, 0xfffe, 0x080c, 0x323a, 0x04a9, 0x0128, 0x70dc, 0xc0bd, - 0x70de, 0x080c, 0xcc9e, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, + 0x0001, 0x2009, 0x007e, 0x080c, 0x65e3, 0x1168, 0xb813, 0x00ff, + 0xb817, 0xfffe, 0x080c, 0x325a, 0x04a9, 0x0128, 0x70dc, 0xc0bd, + 0x70de, 0x080c, 0xccd1, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, - 0x080c, 0xac4f, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xcccb, 0x6023, - 0x0001, 0x9006, 0x080c, 0x655c, 0x2001, 0x0000, 0x080c, 0x6570, + 0x080c, 0xac60, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xccfe, 0x6023, + 0x0001, 0x9006, 0x080c, 0x6580, 0x2001, 0x0000, 0x080c, 0x6594, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, - 0x0004, 0x080c, 0xac7c, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, + 0x0004, 0x080c, 0xac8d, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, - 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xac4f, 0x0548, 0x2b00, + 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xac60, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x31ef, - 0x080c, 0xcccb, 0x6023, 0x0001, 0x9006, 0x080c, 0x655c, 0x2001, - 0x0002, 0x080c, 0x6570, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, - 0x70aa, 0x012e, 0x2009, 0x0002, 0x080c, 0xac7c, 0x9085, 0x0001, + 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x320f, + 0x080c, 0xccfe, 0x6023, 0x0001, 0x9006, 0x080c, 0x6580, 0x2001, + 0x0002, 0x080c, 0x6594, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, + 0x70aa, 0x012e, 0x2009, 0x0002, 0x080c, 0xac8d, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, - 0x2009, 0x0080, 0x080c, 0x65bf, 0x1140, 0xb813, 0x00ff, 0xb817, + 0x2009, 0x0080, 0x080c, 0x65e3, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xab89, 0x01d0, - 0x2b00, 0x6012, 0x080c, 0xcccb, 0x6023, 0x0001, 0x9006, 0x080c, - 0x655c, 0x2001, 0x0002, 0x080c, 0x6570, 0x0126, 0x2091, 0x8000, - 0x70e4, 0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xac7c, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xab9a, 0x01d0, + 0x2b00, 0x6012, 0x080c, 0xccfe, 0x6023, 0x0001, 0x9006, 0x080c, + 0x6580, 0x2001, 0x0002, 0x080c, 0x6594, 0x0126, 0x2091, 0x8000, + 0x70e4, 0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xac8d, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, - 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x65bf, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x65e3, 0x11b8, 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8d7, 0x0004, 0x080c, - 0xab89, 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, - 0x080c, 0xcccb, 0x2009, 0x0022, 0x080c, 0xac7c, 0x9085, 0x0001, + 0xab9a, 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, + 0x080c, 0xccfe, 0x2009, 0x0022, 0x080c, 0xac8d, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, - 0x0026, 0x00b6, 0x21f0, 0x080c, 0xa888, 0x0106, 0x080c, 0x9398, - 0x080c, 0x9309, 0x080c, 0xa7d9, 0x080c, 0xbb0c, 0x010e, 0x090c, - 0xa8a4, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, - 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6620, 0x1140, - 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x603e, - 0x001e, 0x8108, 0x1f04, 0x31d4, 0x9686, 0x0001, 0x190c, 0x332b, + 0x0026, 0x00b6, 0x21f0, 0x080c, 0xa899, 0x0106, 0x080c, 0x93d1, + 0x080c, 0x9342, 0x080c, 0xa7ea, 0x080c, 0xbb2c, 0x010e, 0x090c, + 0xa8b5, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, + 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6644, 0x1140, + 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x605e, + 0x001e, 0x8108, 0x1f04, 0x31f4, 0x9686, 0x0001, 0x190c, 0x334b, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0xa888, + 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0xa899, 0x0106, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, - 0x938d, 0x0076, 0x2039, 0x0000, 0x080c, 0x9256, 0x2c08, 0x080c, - 0xdffb, 0x007e, 0x001e, 0x010e, 0x090c, 0xa8a4, 0xba10, 0xbb14, - 0xbc84, 0x080c, 0x603e, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, + 0x93c6, 0x0076, 0x2039, 0x0000, 0x080c, 0x928f, 0x2c08, 0x080c, + 0xe038, 0x007e, 0x001e, 0x010e, 0x090c, 0xa8b5, 0xba10, 0xbb14, + 0xbc84, 0x080c, 0x605e, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a8, 0x9005, 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, - 0x080c, 0xa888, 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, - 0x080c, 0x56d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, - 0x2009, 0x002d, 0x080c, 0xe2d9, 0x20a9, 0x0800, 0x9016, 0x0026, - 0x928e, 0x007e, 0x0904, 0x32a9, 0x928e, 0x007f, 0x0904, 0x32a9, + 0x080c, 0xa899, 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, + 0x080c, 0x56f5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, + 0x2009, 0x002d, 0x080c, 0xe316, 0x20a9, 0x0800, 0x9016, 0x0026, + 0x928e, 0x007e, 0x0904, 0x32c9, 0x928e, 0x007f, 0x0904, 0x32c9, 0x928e, 0x0080, 0x05f0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150, 0x2001, 0x198d, 0x0006, 0x2003, 0x0001, 0x080c, - 0x32ba, 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, - 0x0001, 0x080c, 0x6a34, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, - 0x938d, 0x0076, 0x2039, 0x0000, 0x080c, 0x9256, 0x00b6, 0x00c6, + 0x32da, 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, + 0x0001, 0x080c, 0x6a58, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, + 0x93c6, 0x0076, 0x2039, 0x0000, 0x080c, 0x928f, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, - 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xdffb, 0x001e, - 0x007e, 0x002e, 0x8210, 0x1f04, 0x325f, 0x010e, 0x090c, 0xa8a4, + 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xe038, 0x001e, + 0x007e, 0x002e, 0x8210, 0x1f04, 0x327f, 0x010e, 0x090c, 0xa8b5, 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x56d5, 0xd0c4, + 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x56f5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, - 0xe2d9, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x7294, 0x82ff, 0x01e8, 0x080c, 0x6a62, 0x11d0, 0x2100, - 0x080c, 0x2647, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, + 0xe316, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x7294, 0x82ff, 0x01e8, 0x080c, 0x6a86, 0x11d0, 0x2100, + 0x080c, 0x2663, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa888, 0x0106, - 0x0036, 0x2019, 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0xa8a4, + 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa899, 0x0106, + 0x0036, 0x2019, 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0xa8b5, 0x9180, 0x1000, 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, - 0x1b31, 0x001e, 0x6112, 0x080c, 0x31ef, 0x001e, 0x080c, 0x65e4, + 0x1b31, 0x001e, 0x6112, 0x080c, 0x320f, 0x001e, 0x080c, 0x6608, 0x012e, 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, - 0xa372, 0x080c, 0xe640, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, - 0x2004, 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x74c8, 0x1118, - 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x74c8, 0x1110, + 0xa37f, 0x080c, 0xe67d, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, + 0x2004, 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x74ec, 0x1118, + 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x74ec, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, - 0x0130, 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x65e4, 0x8108, - 0x1f04, 0x333c, 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, + 0x0130, 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x6608, 0x8108, + 0x1f04, 0x335c, 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082, 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026, 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, @@ -1473,89 +1477,89 @@ unsigned short risc_code01[] = { 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, - 0x7007, 0x0001, 0x080c, 0x1053, 0x090c, 0x0d7d, 0x2900, 0x706a, - 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1053, 0x090c, 0x0d7d, + 0x7007, 0x0001, 0x080c, 0x1060, 0x090c, 0x0d7d, 0x2900, 0x706a, + 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1060, 0x090c, 0x0d7d, 0x2900, 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, - 0x189e, 0x7004, 0x0002, 0x3497, 0x3498, 0x34ab, 0x34bf, 0x0005, - 0x1004, 0x34a8, 0x0e04, 0x34a8, 0x2079, 0x0000, 0x0126, 0x2091, + 0x189e, 0x7004, 0x0002, 0x34b7, 0x34b8, 0x34cb, 0x34df, 0x0005, + 0x1004, 0x34c8, 0x0e04, 0x34c8, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, - 0xa86c, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x3593, + 0xa86c, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x35b3, 0x0005, 0x7018, 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, - 0x1a04, 0x3590, 0x61d0, 0x0804, 0x3525, 0x3567, 0x359f, 0x3590, - 0x35a9, 0x35b3, 0x35b9, 0x35bd, 0x35cd, 0x35d1, 0x35e7, 0x35ed, - 0x35f3, 0x35fe, 0x3609, 0x3618, 0x3627, 0x3635, 0x364c, 0x3667, - 0x3590, 0x3710, 0x374e, 0x37f3, 0x3804, 0x3827, 0x3590, 0x3590, - 0x3590, 0x385f, 0x387f, 0x3888, 0x38b4, 0x38ba, 0x3590, 0x3900, - 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x390b, 0x3914, 0x391c, - 0x391e, 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x394e, - 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x396b, 0x39cf, 0x3590, - 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x0002, 0x39f9, 0x39fc, - 0x3a5b, 0x3a74, 0x3aa4, 0x3d46, 0x3590, 0x52a6, 0x3590, 0x3590, - 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x3590, 0x35e7, 0x35ed, - 0x4245, 0x56f9, 0x4263, 0x5335, 0x5386, 0x5489, 0x3590, 0x54eb, - 0x5527, 0x5558, 0x5664, 0x5585, 0x55e4, 0x3590, 0x4267, 0x441c, - 0x4432, 0x4457, 0x44bc, 0x4530, 0x4550, 0x45c7, 0x4623, 0x467f, - 0x4682, 0x46a7, 0x4717, 0x4781, 0x4789, 0x48bb, 0x4a33, 0x4a67, - 0x4ccb, 0x3590, 0x4ce9, 0x4d8e, 0x4e70, 0x4eca, 0x3590, 0x4f7f, - 0x3590, 0x4fe5, 0x5000, 0x4789, 0x5246, 0x714c, 0x0000, 0x2021, - 0x4000, 0x080c, 0x4ae5, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3571, + 0x1a04, 0x35b0, 0x61d0, 0x0804, 0x3545, 0x3587, 0x35bf, 0x35b0, + 0x35c9, 0x35d3, 0x35d9, 0x35dd, 0x35ed, 0x35f1, 0x3607, 0x360d, + 0x3613, 0x361e, 0x3629, 0x3638, 0x3647, 0x3655, 0x366c, 0x3687, + 0x35b0, 0x3730, 0x376e, 0x3813, 0x3824, 0x3847, 0x35b0, 0x35b0, + 0x35b0, 0x387f, 0x389f, 0x38a8, 0x38d4, 0x38da, 0x35b0, 0x3920, + 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x392b, 0x3934, 0x393c, + 0x393e, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x396e, + 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x398b, 0x39ef, 0x35b0, + 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x0002, 0x3a19, 0x3a1c, + 0x3a7b, 0x3a94, 0x3ac4, 0x3d66, 0x35b0, 0x52c6, 0x35b0, 0x35b0, + 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x35b0, 0x3607, 0x360d, + 0x4265, 0x5719, 0x4283, 0x5355, 0x53a6, 0x54a9, 0x35b0, 0x550b, + 0x5547, 0x5578, 0x5684, 0x55a5, 0x5604, 0x35b0, 0x4287, 0x443c, + 0x4452, 0x4477, 0x44dc, 0x4550, 0x4570, 0x45e7, 0x4643, 0x469f, + 0x46a2, 0x46c7, 0x4737, 0x47a1, 0x47a9, 0x48db, 0x4a53, 0x4a87, + 0x4ceb, 0x35b0, 0x4d09, 0x4dae, 0x4e90, 0x4eea, 0x35b0, 0x4f9f, + 0x35b0, 0x5005, 0x5020, 0x47a9, 0x5266, 0x714c, 0x0000, 0x2021, + 0x4000, 0x080c, 0x4b05, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3591, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, - 0x4af2, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x4af5, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, - 0x3567, 0x7984, 0x2114, 0x0804, 0x3567, 0x20e1, 0x0000, 0x2099, + 0x4b12, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, + 0x7990, 0x0804, 0x4b15, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, + 0x3587, 0x7984, 0x2114, 0x0804, 0x3587, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, - 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x3567, 0x7884, 0x2060, 0x0804, - 0x361a, 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, 0x001e, 0x789b, + 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x3587, 0x7884, 0x2060, 0x0804, + 0x363a, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0002, 0x789b, 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, - 0x7896, 0x0804, 0x3567, 0x7897, 0x0001, 0x0804, 0x3567, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x35a3, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x35ad, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x359c, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35a3, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x359c, 0x2138, 0x7d98, 0x7c9c, 0x0804, - 0x35ad, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x359c, 0x21e8, - 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x3567, + 0x7896, 0x0804, 0x3587, 0x7897, 0x0001, 0x0804, 0x3587, 0x2039, + 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x35c3, 0x2039, 0x0001, 0x7d98, + 0x7c9c, 0x0804, 0x35cd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x35bc, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35c3, 0x79a0, 0x9182, + 0x0040, 0x0210, 0x0804, 0x35bc, 0x2138, 0x7d98, 0x7c9c, 0x0804, + 0x35cd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x35bc, 0x21e8, + 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x3587, 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0x9005, 0x0904, 0x3567, 0x0804, 0x3596, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x359c, 0x21e0, 0x20a9, 0x0001, - 0x7984, 0x2198, 0x4012, 0x0804, 0x3567, 0x2069, 0x1847, 0x7884, - 0x7990, 0x911a, 0x1a04, 0x359c, 0x8019, 0x0904, 0x359c, 0x684a, + 0x1dd8, 0x2010, 0x9005, 0x0904, 0x3587, 0x0804, 0x35b6, 0x79a0, + 0x9182, 0x0040, 0x0210, 0x0804, 0x35bc, 0x21e0, 0x20a9, 0x0001, + 0x7984, 0x2198, 0x4012, 0x0804, 0x3587, 0x2069, 0x1847, 0x7884, + 0x7990, 0x911a, 0x1a04, 0x35bc, 0x8019, 0x0904, 0x35bc, 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, - 0x080c, 0x77fd, 0x0804, 0x3567, 0x2069, 0x1847, 0x7884, 0x7994, - 0x911a, 0x1a04, 0x359c, 0x8019, 0x0904, 0x359c, 0x684e, 0x6946, + 0x080c, 0x7820, 0x0804, 0x3587, 0x2069, 0x1847, 0x7884, 0x7994, + 0x911a, 0x1a04, 0x35bc, 0x8019, 0x0904, 0x35bc, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6ad0, 0x012e, 0x0804, 0x3567, 0x902e, - 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3599, 0x7984, + 0x2091, 0x8000, 0x080c, 0x6af4, 0x012e, 0x0804, 0x3587, 0x902e, + 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35b9, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, - 0x4101, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, - 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4af2, - 0x701f, 0x368b, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, + 0x4101, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, + 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4b12, + 0x701f, 0x36ab, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, - 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x3599, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x3599, 0x7112, 0x7010, 0x8001, 0x0560, - 0x7012, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, + 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x35b9, 0x810f, + 0x918c, 0x00ff, 0x0904, 0x35b9, 0x7112, 0x7010, 0x8001, 0x0560, + 0x7012, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4af2, 0x701f, 0x36c9, + 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4b12, 0x701f, 0x36e9, 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, - 0x000a, 0x1904, 0x3599, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, + 0x000a, 0x1904, 0x35b9, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, - 0xaa7a, 0x080c, 0x6191, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, - 0xa982, 0x012e, 0x0050, 0x080c, 0x64ba, 0x1128, 0x7007, 0x0003, - 0x701f, 0x36f5, 0x0005, 0x080c, 0x6faf, 0x0126, 0x2091, 0x8000, + 0xaa7a, 0x080c, 0x61b1, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, + 0xa982, 0x012e, 0x0050, 0x080c, 0x64de, 0x1128, 0x7007, 0x0003, + 0x701f, 0x3715, 0x0005, 0x080c, 0x6fd3, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, - 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, 0x0804, 0x4af5, + 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, 0x0804, 0x4b15, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, @@ -1564,267 +1568,267 @@ unsigned short risc_code01[] = { 0xd084, 0x0180, 0x2001, 0x1a21, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, - 0x3599, 0x7984, 0x080c, 0x6620, 0x1904, 0x359c, 0x7e98, 0x9684, - 0x3fff, 0x9082, 0x4000, 0x1a04, 0x359c, 0x7c88, 0x7d8c, 0x080c, - 0x6856, 0x080c, 0x67e3, 0x1518, 0x2061, 0x1ddc, 0x0126, 0x2091, + 0x35b9, 0x7984, 0x080c, 0x6644, 0x1904, 0x35bc, 0x7e98, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x1a04, 0x35bc, 0x7c88, 0x7d8c, 0x080c, + 0x687a, 0x080c, 0x6807, 0x1518, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150, 0x012e, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04, 0x3599, 0x0c30, - 0x080c, 0xc430, 0x012e, 0x0904, 0x3599, 0x0804, 0x3567, 0x900e, - 0x2001, 0x0005, 0x080c, 0x6faf, 0x0126, 0x2091, 0x8000, 0x080c, - 0xcb3b, 0x080c, 0x6d7b, 0x012e, 0x0804, 0x3567, 0x00a6, 0x2950, - 0xb198, 0x080c, 0x6620, 0x1904, 0x37e0, 0xb6a4, 0x9684, 0x3fff, - 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x6856, 0x080c, - 0x6800, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, 0x6000, + 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04, 0x35b9, 0x0c30, + 0x080c, 0xc453, 0x012e, 0x0904, 0x35b9, 0x0804, 0x3587, 0x900e, + 0x2001, 0x0005, 0x080c, 0x6fd3, 0x0126, 0x2091, 0x8000, 0x080c, + 0xcb6e, 0x080c, 0x6d9f, 0x012e, 0x0804, 0x3587, 0x00a6, 0x2950, + 0xb198, 0x080c, 0x6644, 0x1904, 0x3800, 0xb6a4, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x687a, 0x080c, + 0x6824, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, - 0xc430, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, - 0x0005, 0x080c, 0x6faf, 0x0126, 0x2091, 0x8000, 0x080c, 0xcb3b, - 0x080c, 0x6d6f, 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, + 0xc453, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, + 0x0005, 0x080c, 0x6fd3, 0x0126, 0x2091, 0x8000, 0x080c, 0xcb6e, + 0x080c, 0x6d93, 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, - 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x3599, 0x080c, 0x4ac0, - 0x0904, 0x359c, 0x080c, 0x66e7, 0x0904, 0x3599, 0x080c, 0x685c, - 0x0904, 0x3599, 0x0804, 0x4547, 0x81ff, 0x1904, 0x3599, 0x080c, - 0x4adc, 0x0904, 0x359c, 0x080c, 0x68ea, 0x0904, 0x3599, 0x2019, - 0x0005, 0x79a8, 0x080c, 0x6877, 0x0904, 0x3599, 0x7888, 0x908a, - 0x1000, 0x1a04, 0x359c, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, - 0x862b, 0x7984, 0xd184, 0x1904, 0x3567, 0x0804, 0x4547, 0x0126, + 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x35b9, 0x080c, 0x4ae0, + 0x0904, 0x35bc, 0x080c, 0x670b, 0x0904, 0x35b9, 0x080c, 0x6880, + 0x0904, 0x35b9, 0x0804, 0x4567, 0x81ff, 0x1904, 0x35b9, 0x080c, + 0x4afc, 0x0904, 0x35bc, 0x080c, 0x690e, 0x0904, 0x35b9, 0x2019, + 0x0005, 0x79a8, 0x080c, 0x689b, 0x0904, 0x35b9, 0x7888, 0x908a, + 0x1000, 0x1a04, 0x35bc, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, + 0x865f, 0x7984, 0xd184, 0x1904, 0x3587, 0x0804, 0x4567, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, - 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x6620, - 0x11d8, 0x080c, 0x68ea, 0x1128, 0x2009, 0x0002, 0x62c0, 0x2518, - 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x6877, 0x1118, 0x2009, + 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x6644, + 0x11d8, 0x080c, 0x690e, 0x1128, 0x2009, 0x0002, 0x62c0, 0x2518, + 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x689b, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, - 0x810b, 0x9108, 0x080c, 0x862b, 0x8529, 0x1ae0, 0x012e, 0x0804, - 0x3567, 0x012e, 0x0804, 0x3599, 0x012e, 0x0804, 0x359c, 0x080c, - 0x4ac0, 0x0904, 0x359c, 0x080c, 0x66e7, 0x0904, 0x3599, 0x080c, - 0xa888, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x938d, - 0x0076, 0x903e, 0x080c, 0x9256, 0x900e, 0x080c, 0xdffb, 0x007e, - 0x00ce, 0x080c, 0xa8a4, 0x080c, 0x6856, 0x0804, 0x3567, 0x080c, - 0x4ac0, 0x0904, 0x359c, 0x080c, 0x6856, 0x2208, 0x0804, 0x3567, + 0x810b, 0x9108, 0x080c, 0x865f, 0x8529, 0x1ae0, 0x012e, 0x0804, + 0x3587, 0x012e, 0x0804, 0x35b9, 0x012e, 0x0804, 0x35bc, 0x080c, + 0x4ae0, 0x0904, 0x35bc, 0x080c, 0x670b, 0x0904, 0x35b9, 0x080c, + 0xa899, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x93c6, + 0x0076, 0x903e, 0x080c, 0x928f, 0x900e, 0x080c, 0xe038, 0x007e, + 0x00ce, 0x080c, 0xa8b5, 0x080c, 0x687a, 0x0804, 0x3587, 0x080c, + 0x4ae0, 0x0904, 0x35bc, 0x080c, 0x687a, 0x2208, 0x0804, 0x3587, 0x0156, 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x2071, 0x19e6, 0x7028, 0x9065, 0x0118, 0x8210, 0x600c, 0x0cd8, 0x2300, 0x9218, - 0x00ce, 0x00ee, 0x00de, 0x015e, 0x0804, 0x3567, 0x00f6, 0x0016, + 0x00ce, 0x00ee, 0x00de, 0x015e, 0x0804, 0x3587, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, 0x6910, 0x62bc, - 0x0804, 0x3567, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3599, - 0x0126, 0x2091, 0x8000, 0x080c, 0x56e9, 0x0128, 0x2009, 0x0007, - 0x012e, 0x0804, 0x3599, 0x012e, 0x615c, 0x9190, 0x3368, 0x2215, + 0x0804, 0x3587, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35b9, + 0x0126, 0x2091, 0x8000, 0x080c, 0x5709, 0x0128, 0x2009, 0x0007, + 0x012e, 0x0804, 0x35b9, 0x012e, 0x615c, 0x9190, 0x3388, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, - 0x74c8, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, - 0x0005, 0x0804, 0x3599, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x3567, + 0x74ec, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, + 0x0005, 0x0804, 0x35b9, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x3587, 0x614c, 0x6250, 0x2019, 0x1985, 0x231c, 0x2001, 0x1986, 0x2004, - 0x789a, 0x0804, 0x3567, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, - 0x6340, 0x012e, 0x0804, 0x3567, 0x080c, 0x4adc, 0x0904, 0x359c, - 0xba44, 0xbb38, 0x0804, 0x3567, 0x080c, 0x0d7d, 0x080c, 0x4adc, - 0x2110, 0x0904, 0x359c, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, + 0x789a, 0x0804, 0x3587, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, + 0x6340, 0x012e, 0x0804, 0x3587, 0x080c, 0x4afc, 0x0904, 0x35bc, + 0xba44, 0xbb38, 0x0804, 0x3587, 0x080c, 0x0d7d, 0x080c, 0x4afc, + 0x2110, 0x0904, 0x35bc, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, - 0x3599, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, - 0x080c, 0xa888, 0x080c, 0xa372, 0x080c, 0x938d, 0x0076, 0x903e, - 0x080c, 0x9256, 0x900e, 0x080c, 0xdffb, 0x007e, 0x00ce, 0x080c, - 0xa8a4, 0xb807, 0x0407, 0x012e, 0x0804, 0x3567, 0x614c, 0x6250, + 0x35b9, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, + 0x080c, 0xa899, 0x080c, 0xa37f, 0x080c, 0x93c6, 0x0076, 0x903e, + 0x080c, 0x928f, 0x900e, 0x080c, 0xe038, 0x007e, 0x00ce, 0x080c, + 0xa8b5, 0xb807, 0x0407, 0x012e, 0x0804, 0x3587, 0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1985, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1986, 0x2d04, 0x266a, - 0x789a, 0x0804, 0x3567, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, - 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0ecc, 0xd0c4, 0x01a8, 0x00d6, + 0x789a, 0x0804, 0x3587, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, + 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0ed9, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x199c, 0x200a, 0x78ac, 0x2011, 0x199d, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0x603e, 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040, 0x0010, 0x918c, 0xff7f, 0x2112, 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, 0x190c, - 0x0ee7, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, 0x0001, - 0x090c, 0x4245, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, - 0x2012, 0x012e, 0x0804, 0x3567, 0x00f6, 0x2079, 0x1800, 0x7a38, + 0x0ef4, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, 0x0001, + 0x090c, 0x4265, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, + 0x2012, 0x012e, 0x0804, 0x3587, 0x00f6, 0x2079, 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, - 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x359c, 0x788c, 0x902d, - 0x0904, 0x359c, 0x900e, 0x080c, 0x6620, 0x1120, 0xba44, 0xbb38, + 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x35bc, 0x788c, 0x902d, + 0x0904, 0x35bc, 0x900e, 0x080c, 0x6644, 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, - 0x4adc, 0x0904, 0x359c, 0x7888, 0x900d, 0x0904, 0x359c, 0x788c, - 0x9005, 0x0904, 0x359c, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, - 0x3567, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x56e9, - 0x1904, 0x3599, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, + 0x4afc, 0x0904, 0x35bc, 0x7888, 0x900d, 0x0904, 0x35bc, 0x788c, + 0x9005, 0x0904, 0x35bc, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, + 0x3587, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x5709, + 0x1904, 0x35b9, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, - 0x007f, 0x16e0, 0x9188, 0x3368, 0x210d, 0x918c, 0x00ff, 0x2001, + 0x007f, 0x16e0, 0x9188, 0x3388, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, - 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xab89, 0x000e, 0x0510, - 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x65c5, 0x2b08, 0x00be, - 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4aa9, 0x01d0, 0x9006, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xab9a, 0x000e, 0x0510, + 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x65e9, 0x2b08, 0x00be, + 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4ac9, 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, - 0x3a54, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xac7c, 0x012e, - 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3599, 0x00ce, 0x0804, - 0x359c, 0x080c, 0xabdf, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, - 0x3599, 0x0804, 0x3567, 0x2061, 0x1a6e, 0x0126, 0x2091, 0x8000, + 0x3a74, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xac8d, 0x012e, + 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x35b9, 0x00ce, 0x0804, + 0x35bc, 0x080c, 0xabf0, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, + 0x35b9, 0x0804, 0x3587, 0x2061, 0x1a6e, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e, 0x0804, - 0x3567, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x3599, 0x080c, - 0x74c8, 0x0904, 0x3599, 0x0126, 0x2091, 0x8000, 0x6254, 0x6074, - 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x267d, 0x080c, 0x5903, - 0x012e, 0x0804, 0x3567, 0x012e, 0x0804, 0x359c, 0x0006, 0x0016, + 0x3587, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x35b9, 0x080c, + 0x74ec, 0x0904, 0x35b9, 0x0126, 0x2091, 0x8000, 0x6254, 0x6074, + 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x2699, 0x080c, 0x5923, + 0x012e, 0x0804, 0x3587, 0x012e, 0x0804, 0x35bc, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19a8, 0x2070, 0x2061, 0x1847, 0x6008, - 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x9148, 0x7206, 0x00ee, + 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x9181, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3569, 0x7884, 0xd0fc, + 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3589, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, - 0x0804, 0x359c, 0x2001, 0x002a, 0x2004, 0x2069, 0x1847, 0x6908, - 0x9102, 0x1230, 0x012e, 0x0804, 0x359c, 0x012e, 0x0804, 0x3599, - 0x080c, 0xab49, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3b1f, 0x00c6, - 0x080c, 0x4aa9, 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, + 0x0804, 0x35bc, 0x2001, 0x002a, 0x2004, 0x2069, 0x1847, 0x6908, + 0x9102, 0x1230, 0x012e, 0x0804, 0x35bc, 0x012e, 0x0804, 0x35b9, + 0x080c, 0xab5a, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3b3f, 0x00c6, + 0x080c, 0x4ac9, 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, - 0x0003, 0x9084, 0x00fc, 0x8004, 0xa816, 0x080c, 0x3ca9, 0x0928, + 0x0003, 0x9084, 0x00fc, 0x8004, 0xa816, 0x080c, 0x3cc9, 0x0928, 0x7014, 0x2048, 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, - 0x4af2, 0x701f, 0x3be6, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, - 0xa888, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x080c, 0x3a8e, 0x2001, 0x199e, 0x2003, 0x0000, + 0x4b12, 0x701f, 0x3c06, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, + 0xa899, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x080c, 0x3aae, 0x2001, 0x199e, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, - 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3d18, 0x080c, 0x3cd7, + 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, 0x3d38, 0x080c, 0x3cf7, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x19e6, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, - 0x0001, 0x080c, 0x4089, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3fb6, - 0x080c, 0x3ee3, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, - 0x1db8, 0x080c, 0x40fd, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, + 0x0001, 0x080c, 0x40a9, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3fd6, + 0x080c, 0x3f03, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, + 0x1db8, 0x080c, 0x411d, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, - 0x00ce, 0x0138, 0x080c, 0x3eed, 0x080c, 0x3cd2, 0x0058, 0x080c, - 0x3cd2, 0x080c, 0x4021, 0x080c, 0x3fac, 0x2001, 0x020b, 0x2004, + 0x00ce, 0x0138, 0x080c, 0x3f0d, 0x080c, 0x3cf2, 0x0058, 0x080c, + 0x3cf2, 0x080c, 0x4041, 0x080c, 0x3fcc, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, - 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x1333, 0x2009, 0x0028, - 0x080c, 0x21c1, 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0xa8a4, + 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x1340, 0x2009, 0x0028, + 0x080c, 0x21d9, 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0xa8b5, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x199e, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, - 0x3567, 0x012e, 0x2021, 0x400c, 0x0804, 0x3569, 0x0016, 0x0026, + 0x3587, 0x012e, 0x2021, 0x400c, 0x0804, 0x3589, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, - 0x0904, 0x3c42, 0x2048, 0x1f04, 0x3bf6, 0x7068, 0x2040, 0xa28c, + 0x0904, 0x3c62, 0x2048, 0x1f04, 0x3c16, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4af2, 0x701f, 0x3be6, + 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4b12, 0x701f, 0x3c06, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, - 0x080c, 0x0fb7, 0x000e, 0x080c, 0x4af5, 0x701f, 0x3be6, 0x015e, + 0x080c, 0x0fc4, 0x000e, 0x080c, 0x4b15, 0x701f, 0x3c06, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, - 0x701f, 0x3ca7, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, - 0x2009, 0x007f, 0x080c, 0x65bf, 0x0110, 0x9006, 0x0030, 0xb813, - 0x00ff, 0xb817, 0xfffd, 0x080c, 0xcd1a, 0x015e, 0x00de, 0x009e, + 0x701f, 0x3cc7, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, + 0x2009, 0x007f, 0x080c, 0x65e3, 0x0110, 0x9006, 0x0030, 0xb813, + 0x00ff, 0xb817, 0xfffd, 0x080c, 0xcd4d, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, - 0x3599, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, - 0x0096, 0x00d6, 0x0156, 0x701f, 0x3c79, 0x7007, 0x0003, 0x0804, - 0x3c37, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x3569, + 0x35b9, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, + 0x0096, 0x00d6, 0x0156, 0x701f, 0x3c99, 0x7007, 0x0003, 0x0804, + 0x3c57, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x3589, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, - 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fb7, 0x000e, 0x080c, - 0x4af5, 0x007e, 0x701f, 0x3be6, 0x7023, 0x0001, 0x0005, 0x0804, - 0x3567, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, + 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fc4, 0x000e, 0x080c, + 0x4b15, 0x007e, 0x701f, 0x3c06, 0x7023, 0x0001, 0x0005, 0x0804, + 0x3587, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, - 0x4aa9, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, + 0x4ac9, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, 0x199e, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x19a9, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19a8, 0x2004, 0x60ce, 0x6104, 0xc1ac, - 0x6106, 0x080c, 0x4aa9, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, + 0x6106, 0x080c, 0x4ac9, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19a8, 0x2004, - 0x6036, 0x2009, 0x0040, 0x080c, 0x21c1, 0x2001, 0x002a, 0x2004, + 0x6036, 0x2009, 0x0040, 0x080c, 0x21d9, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x00e6, 0x080c, 0x4aa9, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, + 0x00e6, 0x080c, 0x4ac9, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0148, 0x080c, 0x2a07, 0x1130, 0x9006, 0x080c, - 0x295e, 0x9006, 0x080c, 0x2941, 0x7884, 0x9084, 0x0007, 0x0002, - 0x3d63, 0x3d6c, 0x3d75, 0x3d60, 0x3d60, 0x3d60, 0x3d60, 0x3d60, - 0x012e, 0x0804, 0x359c, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, - 0x200a, 0x080c, 0x3f37, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, - 0x4000, 0x200a, 0x080c, 0x3f37, 0x0078, 0x080c, 0x74c8, 0x1128, - 0x012e, 0x2009, 0x0016, 0x0804, 0x3599, 0x81ff, 0x0128, 0x012e, - 0x2021, 0x400b, 0x0804, 0x3569, 0x080c, 0xa888, 0x0086, 0x0096, - 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3a8e, + 0x8000, 0x81ff, 0x0148, 0x080c, 0x2a27, 0x1130, 0x9006, 0x080c, + 0x297a, 0x9006, 0x080c, 0x295d, 0x7884, 0x9084, 0x0007, 0x0002, + 0x3d83, 0x3d8c, 0x3d95, 0x3d80, 0x3d80, 0x3d80, 0x3d80, 0x3d80, + 0x012e, 0x0804, 0x35bc, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, + 0x200a, 0x080c, 0x3f57, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, + 0x4000, 0x200a, 0x080c, 0x3f57, 0x0078, 0x080c, 0x74ec, 0x1128, + 0x012e, 0x2009, 0x0016, 0x0804, 0x35b9, 0x81ff, 0x0128, 0x012e, + 0x2021, 0x400b, 0x0804, 0x3589, 0x080c, 0xa899, 0x0086, 0x0096, + 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aae, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, - 0x2060, 0x2058, 0x080c, 0x41d8, 0x080c, 0x4128, 0x903e, 0x2720, + 0x2060, 0x2058, 0x080c, 0x41f8, 0x080c, 0x4148, 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x19e6, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, - 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4089, 0x080c, - 0x2a0f, 0x080c, 0x2a0f, 0x080c, 0x2a0f, 0x080c, 0x2a0f, 0x080c, - 0x4089, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3fb6, 0x2009, 0x9c40, - 0x8109, 0x11b0, 0x080c, 0x3eed, 0x2001, 0x0004, 0x200c, 0x918c, + 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x40a9, 0x080c, + 0x2a2f, 0x080c, 0x2a2f, 0x080c, 0x2a2f, 0x080c, 0x2a2f, 0x080c, + 0x40a9, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3fd6, 0x2009, 0x9c40, + 0x8109, 0x11b0, 0x080c, 0x3f0d, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x3599, 0x0cf8, + 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x35b9, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, - 0x81ff, 0x0150, 0x080c, 0x3f94, 0x2d00, 0x9c05, 0x9b05, 0x0120, - 0x080c, 0x3eed, 0x0804, 0x3e96, 0x080c, 0x40fd, 0x080c, 0x4021, - 0x080c, 0x3f77, 0x080c, 0x3fac, 0x00f6, 0x2079, 0x0100, 0x7824, - 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3eed, 0x00fe, 0x0804, 0x3e96, - 0x00fe, 0x080c, 0x3ee3, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, - 0x2001, 0x0033, 0x2502, 0x080c, 0x3eed, 0x0080, 0x87ff, 0x0138, + 0x81ff, 0x0150, 0x080c, 0x3fb4, 0x2d00, 0x9c05, 0x9b05, 0x0120, + 0x080c, 0x3f0d, 0x0804, 0x3eb6, 0x080c, 0x411d, 0x080c, 0x4041, + 0x080c, 0x3f97, 0x080c, 0x3fcc, 0x00f6, 0x2079, 0x0100, 0x7824, + 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3f0d, 0x00fe, 0x0804, 0x3eb6, + 0x00fe, 0x080c, 0x3f03, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, + 0x2001, 0x0033, 0x2502, 0x080c, 0x3f0d, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, - 0x1a6a, 0x2004, 0x9086, 0x0000, 0x1904, 0x3de6, 0x2001, 0x032f, + 0x1a6a, 0x2004, 0x9086, 0x0000, 0x1904, 0x3e06, 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, - 0x3e96, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, - 0x3e96, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, + 0x3eb6, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, + 0x3eb6, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a6a, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, - 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x21c1, 0x2900, + 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x21d9, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, - 0x0203, 0x2004, 0x1f04, 0x3e6d, 0x00ce, 0x0030, 0xa817, 0x0001, + 0x0203, 0x2004, 0x1f04, 0x3e8d, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3da0, 0x001e, 0x00c6, + 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3dc0, 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfffd, 0x2102, 0x080c, 0x1333, 0x7884, 0x9084, 0x0003, - 0x9086, 0x0002, 0x01b0, 0x2009, 0x0028, 0x080c, 0x21c1, 0x2001, - 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2ab9, + 0x918c, 0xfffd, 0x2102, 0x080c, 0x1340, 0x7884, 0x9084, 0x0003, + 0x9086, 0x0002, 0x01b0, 0x2009, 0x0028, 0x080c, 0x21d9, 0x2001, + 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2ad9, 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, - 0x0010, 0x080c, 0xa8a4, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, + 0x0010, 0x080c, 0xa8b5, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x3567, 0x012e, 0x2021, - 0x400c, 0x0804, 0x3569, 0x9085, 0x0001, 0x1d04, 0x3eec, 0x2091, + 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x3587, 0x012e, 0x2021, + 0x400c, 0x0804, 0x3589, 0x9085, 0x0001, 0x1d04, 0x3f0c, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x1a6a, 0x2003, - 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, 0x21c1, 0x2001, 0x0227, + 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, 0x21d9, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x19e6, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, - 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x21c1, 0x782c, 0xd0fc, - 0x0d88, 0x080c, 0x40fd, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, - 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x21c1, + 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x21d9, 0x782c, 0xd0fc, + 0x0d88, 0x080c, 0x411d, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, + 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x21d9, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, - 0x265d, 0x080c, 0x2a86, 0x080c, 0x2ab9, 0x784b, 0xf7f7, 0x7843, + 0x2679, 0x080c, 0x2aa6, 0x080c, 0x2ad9, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x7850, 0xc0e5, 0x7852, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x0110, 0x8319, 0x1dd8, 0x7850, 0xc0e4, 0x7852, - 0x2011, 0x0048, 0x080c, 0x2a63, 0x7843, 0x0040, 0x2019, 0x01f4, - 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2a29, - 0x2011, 0x0020, 0x080c, 0x2a63, 0x7843, 0x0000, 0x9006, 0x080c, - 0x2a29, 0x2011, 0x0048, 0x080c, 0x2a63, 0x00fe, 0x0005, 0x7884, + 0x2011, 0x0048, 0x080c, 0x2a83, 0x7843, 0x0040, 0x2019, 0x01f4, + 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2a49, + 0x2011, 0x0020, 0x080c, 0x2a83, 0x7843, 0x0000, 0x9006, 0x080c, + 0x2a49, 0x2011, 0x0048, 0x080c, 0x2a83, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1a6a, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, @@ -1833,7 +1837,7 @@ unsigned short risc_code01[] = { 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, - 0x0100, 0x2001, 0x19a9, 0x2004, 0x70e2, 0x080c, 0x3cc8, 0x1188, + 0x0100, 0x2001, 0x19a9, 0x2004, 0x70e2, 0x080c, 0x3ce8, 0x1188, 0x2001, 0x1820, 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, 0x210c, @@ -1841,31 +1845,31 @@ unsigned short risc_code01[] = { 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, - 0x9085, 0x0092, 0x7016, 0x080c, 0x40fd, 0x00f6, 0x2071, 0x1a6a, + 0x9085, 0x0092, 0x7016, 0x080c, 0x411d, 0x00f6, 0x2071, 0x1a6a, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, - 0x080c, 0x4089, 0x2011, 0x0001, 0x080c, 0x4089, 0x00fe, 0x00ee, + 0x080c, 0x40a9, 0x2011, 0x0001, 0x080c, 0x40a9, 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a6a, 0x2079, 0x0320, 0x792c, - 0xd1fc, 0x0904, 0x4086, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, - 0x4082, 0x7000, 0x0002, 0x4086, 0x4037, 0x4067, 0x4082, 0xd1bc, + 0xd1fc, 0x0904, 0x40a6, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, + 0x40a2, 0x7000, 0x0002, 0x40a6, 0x4057, 0x4087, 0x40a2, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, - 0x4089, 0x0904, 0x4086, 0x080c, 0x4089, 0x0804, 0x4086, 0x00f6, + 0x40a9, 0x0904, 0x40a6, 0x080c, 0x40a9, 0x0804, 0x40a6, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, - 0x080c, 0x3f94, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, + 0x080c, 0x3fb4, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, - 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x402b, + 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x404b, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, - 0x938a, 0x0007, 0x1a0c, 0x0d7d, 0x9398, 0x40b7, 0x231d, 0x083f, + 0x938a, 0x0007, 0x1a0c, 0x0d7d, 0x9398, 0x40d7, 0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, - 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x40f4, - 0x40eb, 0x40e2, 0x40d9, 0x40d0, 0x40c7, 0x40be, 0xa964, 0x7902, + 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x4114, + 0x410b, 0x4102, 0x40f9, 0x40f0, 0x40e7, 0x40de, 0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, @@ -1875,23 +1879,23 @@ unsigned short risc_code01[] = { 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, 0x19e6, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, - 0x0002, 0x2940, 0x9026, 0x7054, 0x0002, 0x4124, 0x4110, 0x411b, - 0x8001, 0x7056, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x4089, - 0x190c, 0x4089, 0x0048, 0x8001, 0x7056, 0x782c, 0xd0fc, 0x1d38, - 0x2011, 0x0001, 0x080c, 0x4089, 0x008e, 0x00ee, 0x00fe, 0x0005, + 0x0002, 0x2940, 0x9026, 0x7054, 0x0002, 0x4144, 0x4130, 0x413b, + 0x8001, 0x7056, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x40a9, + 0x190c, 0x40a9, 0x0048, 0x8001, 0x7056, 0x782c, 0xd0fc, 0x1d38, + 0x2011, 0x0001, 0x080c, 0x40a9, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19a9, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19a8, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, - 0x4aa9, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, + 0x4ac9, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, - 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x41a0, - 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4aa9, 0xa813, 0x0019, + 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x41c0, + 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4ac9, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19a8, 0x2004, 0x6036, 0x2009, 0x0040, - 0x080c, 0x21c1, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, + 0x080c, 0x21d9, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, @@ -1899,14 +1903,14 @@ unsigned short risc_code01[] = { 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, - 0x080c, 0x4aa9, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, + 0x080c, 0x4ac9, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, - 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4aa9, 0x2940, + 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4ac9, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, - 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x41a0, 0x1d68, - 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4aa9, 0x2940, 0xa013, 0x0019, + 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x41c0, 0x1d68, + 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4ac9, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, @@ -1916,679 +1920,679 @@ unsigned short risc_code01[] = { 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, - 0x20a9, 0x000c, 0x20a1, 0xfff4, 0x20e9, 0x0000, 0x9006, 0x4004, + 0x20a9, 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, - 0x0005, 0x0804, 0x3567, 0x7d98, 0x7c9c, 0x0804, 0x3669, 0x080c, - 0x74c8, 0x190c, 0x5fe9, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, + 0x0005, 0x0804, 0x3587, 0x7d98, 0x7c9c, 0x0804, 0x3689, 0x080c, + 0x74ec, 0x190c, 0x6009, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x2039, 0x0001, 0x080c, 0x4af2, 0x701f, 0x427f, 0x0005, 0x080c, - 0x56e4, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, - 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x359c, 0x6804, 0xd0ac, - 0x0118, 0xd0a4, 0x0904, 0x359c, 0xd094, 0x00c6, 0x2061, 0x0100, + 0x2039, 0x0001, 0x080c, 0x4b12, 0x701f, 0x429f, 0x0005, 0x080c, + 0x5704, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, + 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x35bc, 0x6804, 0xd0ac, + 0x0118, 0xd0a4, 0x0904, 0x35bc, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, - 0x359c, 0x9288, 0x3368, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, - 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x359c, 0x605e, 0x6888, + 0x35bc, 0x9288, 0x3388, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, + 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x35bc, 0x605e, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, - 0x19b0, 0x9080, 0x2750, 0x2005, 0x200a, 0x2008, 0x2001, 0x0018, - 0x080c, 0xa879, 0x2009, 0x0390, 0x200b, 0x0400, 0x000e, 0x2009, - 0x19b1, 0x9080, 0x2754, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, - 0x0a04, 0x359c, 0x908a, 0x0841, 0x1a04, 0x359c, 0x9084, 0x0007, - 0x1904, 0x359c, 0x680c, 0x9005, 0x0904, 0x359c, 0x6810, 0x9005, - 0x0904, 0x359c, 0x6848, 0x6940, 0x910a, 0x1a04, 0x359c, 0x8001, - 0x0904, 0x359c, 0x684c, 0x6944, 0x910a, 0x1a04, 0x359c, 0x8001, - 0x0904, 0x359c, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, - 0x00ff, 0x6052, 0x080c, 0x77fd, 0x080c, 0x6a9c, 0x080c, 0x6ad0, - 0x6808, 0x602a, 0x080c, 0x2133, 0x2009, 0x0170, 0x200b, 0x0080, - 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x26b7, - 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x440a, 0x6818, 0x691c, + 0x19b0, 0x9080, 0x276c, 0x2005, 0x200a, 0x2008, 0x2001, 0x0018, + 0x080c, 0xa88a, 0x2009, 0x0390, 0x200b, 0x0400, 0x000e, 0x2009, + 0x19b1, 0x9080, 0x2770, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, + 0x0a04, 0x35bc, 0x908a, 0x0841, 0x1a04, 0x35bc, 0x9084, 0x0007, + 0x1904, 0x35bc, 0x680c, 0x9005, 0x0904, 0x35bc, 0x6810, 0x9005, + 0x0904, 0x35bc, 0x6848, 0x6940, 0x910a, 0x1a04, 0x35bc, 0x8001, + 0x0904, 0x35bc, 0x684c, 0x6944, 0x910a, 0x1a04, 0x35bc, 0x8001, + 0x0904, 0x35bc, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, + 0x00ff, 0x6052, 0x080c, 0x7820, 0x080c, 0x6ac0, 0x080c, 0x6af4, + 0x6808, 0x602a, 0x080c, 0x214b, 0x2009, 0x0170, 0x200b, 0x0080, + 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x26d3, + 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x442a, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x19b2, 0x20e9, 0x0001, 0x4001, 0x20a9, - 0x0004, 0x20a1, 0x19cc, 0x20e9, 0x0001, 0x4001, 0x080c, 0x87b0, + 0x0004, 0x20a1, 0x19cc, 0x20e9, 0x0001, 0x4001, 0x080c, 0x87e4, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, - 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7dbe, 0x6878, 0x6016, + 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7de2, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, - 0x1f04, 0x4368, 0x00ce, 0x00c6, 0x2061, 0x199b, 0x6a88, 0x9284, + 0x1f04, 0x4388, 0x00ce, 0x00c6, 0x2061, 0x199b, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, - 0x0001, 0x080c, 0x295e, 0x2001, 0x0001, 0x080c, 0x2941, 0x0088, - 0x9286, 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x295e, - 0x9006, 0x080c, 0x2941, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, - 0x0002, 0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0eb4, 0x00ee, 0x6888, + 0x0001, 0x080c, 0x297a, 0x2001, 0x0001, 0x080c, 0x295d, 0x0088, + 0x9286, 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x297a, + 0x9006, 0x080c, 0x295d, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, + 0x0002, 0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0ec1, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197b, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, - 0x0140, 0x2003, 0xaaaa, 0x080c, 0x272c, 0x2001, 0x196c, 0x2102, + 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2748, 0x2001, 0x196c, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, - 0x0000, 0x00ce, 0x080c, 0x74c8, 0x0128, 0x080c, 0x4fd9, 0x0110, - 0x080c, 0x267d, 0x60d4, 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, - 0x43f2, 0x00e0, 0x080c, 0x74c8, 0x1168, 0x2011, 0x733e, 0x080c, - 0x861d, 0x2011, 0x7331, 0x080c, 0x8729, 0x080c, 0x77d1, 0x080c, - 0x73f9, 0x0040, 0x080c, 0x5edf, 0x0028, 0x6003, 0x0004, 0x2009, - 0x440a, 0x0020, 0x080c, 0x69cc, 0x0804, 0x3567, 0x2001, 0x0170, + 0x0000, 0x00ce, 0x080c, 0x74ec, 0x0128, 0x080c, 0x4ff9, 0x0110, + 0x080c, 0x2699, 0x60d4, 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, + 0x4412, 0x00e0, 0x080c, 0x74ec, 0x1168, 0x2011, 0x7362, 0x080c, + 0x8651, 0x2011, 0x7355, 0x080c, 0x875d, 0x080c, 0x77f4, 0x080c, + 0x741d, 0x0040, 0x080c, 0x5eff, 0x0028, 0x6003, 0x0004, 0x2009, + 0x442a, 0x0020, 0x080c, 0x69f0, 0x0804, 0x3587, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, - 0x3599, 0x2069, 0x1847, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, + 0x35b9, 0x2069, 0x1847, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, - 0x0804, 0x4af5, 0x9006, 0x080c, 0x267d, 0x81ff, 0x1904, 0x3599, - 0x080c, 0x74c8, 0x11b0, 0x080c, 0x77cc, 0x080c, 0x6024, 0x080c, - 0x335c, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xcf51, 0x0130, - 0x080c, 0x74eb, 0x1118, 0x080c, 0x749c, 0x0038, 0x080c, 0x73f9, - 0x0020, 0x080c, 0x5fe9, 0x080c, 0x5edf, 0x0804, 0x3567, 0x81ff, - 0x1904, 0x3599, 0x080c, 0x74c8, 0x1110, 0x0804, 0x3599, 0x6194, + 0x0804, 0x4b15, 0x9006, 0x080c, 0x2699, 0x81ff, 0x1904, 0x35b9, + 0x080c, 0x74ec, 0x11b0, 0x080c, 0x77ef, 0x080c, 0x6044, 0x080c, + 0x337c, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xcf84, 0x0130, + 0x080c, 0x750f, 0x1118, 0x080c, 0x74c0, 0x0038, 0x080c, 0x741d, + 0x0020, 0x080c, 0x6009, 0x080c, 0x5eff, 0x0804, 0x3587, 0x81ff, + 0x1904, 0x35b9, 0x080c, 0x74ec, 0x1110, 0x0804, 0x35b9, 0x6194, 0x81ff, 0x01a8, 0x704f, 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, - 0x0001, 0x080c, 0x4af5, 0x701f, 0x3565, 0x012e, 0x0005, 0x704f, + 0x0001, 0x080c, 0x4b15, 0x701f, 0x3585, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9, 0x0040, 0x20e9, 0x0001, - 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, 0x655c, 0x9588, 0x3368, + 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, 0x655c, 0x9588, 0x3388, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, - 0x9506, 0x01a8, 0x080c, 0x6620, 0x1190, 0xb814, 0x821c, 0x0238, + 0x9506, 0x01a8, 0x080c, 0x6644, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1d80, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1d80, 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1d80, 0x2099, 0x1d80, - 0x080c, 0x5f74, 0x0804, 0x4464, 0x080c, 0x4adc, 0x0904, 0x359c, - 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, 0x080c, - 0x56d5, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, - 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, 0x3357, 0x1148, + 0x080c, 0x5f94, 0x0804, 0x4484, 0x080c, 0x4afc, 0x0904, 0x35bc, + 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0x080c, + 0x56f5, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, + 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, 0x3377, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xca01, - 0x1120, 0x2009, 0x0003, 0x0804, 0x3599, 0x7007, 0x0003, 0x701f, - 0x44f2, 0x0005, 0x080c, 0x4adc, 0x0904, 0x359c, 0x20a9, 0x002b, + 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xca34, + 0x1120, 0x2009, 0x0003, 0x0804, 0x35b9, 0x7007, 0x0003, 0x701f, + 0x4512, 0x0005, 0x080c, 0x4afc, 0x0904, 0x35bc, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, - 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fb7, + 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fc4, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8c4, - 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fb7, 0x8906, + 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fc4, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4af5, - 0x81ff, 0x1904, 0x3599, 0x080c, 0x4ac0, 0x0904, 0x359c, 0x080c, - 0x6865, 0x0904, 0x3599, 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, - 0x0004, 0x0804, 0x3599, 0xa974, 0xaa94, 0x0804, 0x3567, 0x080c, - 0x56dd, 0x0904, 0x3567, 0x701f, 0x453c, 0x7007, 0x0003, 0x0005, - 0x81ff, 0x1904, 0x3599, 0x7888, 0x908a, 0x1000, 0x1a04, 0x359c, - 0x080c, 0x4adc, 0x0904, 0x359c, 0x080c, 0x6a6a, 0x0120, 0x080c, - 0x6a72, 0x1904, 0x359c, 0x080c, 0x68ea, 0x0904, 0x3599, 0x2019, - 0x0004, 0x900e, 0x080c, 0x6877, 0x0904, 0x3599, 0x7984, 0x7a88, - 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, 0x080c, 0x4ada, - 0x01e0, 0x080c, 0x6a6a, 0x0118, 0x080c, 0x6a72, 0x11b0, 0x080c, - 0x68ea, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, - 0x080c, 0x6877, 0x2009, 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, + 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b15, + 0x81ff, 0x1904, 0x35b9, 0x080c, 0x4ae0, 0x0904, 0x35bc, 0x080c, + 0x6889, 0x0904, 0x35b9, 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, + 0x0004, 0x0804, 0x35b9, 0xa974, 0xaa94, 0x0804, 0x3587, 0x080c, + 0x56fd, 0x0904, 0x3587, 0x701f, 0x455c, 0x7007, 0x0003, 0x0005, + 0x81ff, 0x1904, 0x35b9, 0x7888, 0x908a, 0x1000, 0x1a04, 0x35bc, + 0x080c, 0x4afc, 0x0904, 0x35bc, 0x080c, 0x6a8e, 0x0120, 0x080c, + 0x6a96, 0x1904, 0x35bc, 0x080c, 0x690e, 0x0904, 0x35b9, 0x2019, + 0x0004, 0x900e, 0x080c, 0x689b, 0x0904, 0x35b9, 0x7984, 0x7a88, + 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, 0x080c, 0x4afa, + 0x01e0, 0x080c, 0x6a8e, 0x0118, 0x080c, 0x6a96, 0x11b0, 0x080c, + 0x690e, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x689b, 0x2009, 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x080c, - 0x56dd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, + 0x56fd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x645c, 0x2400, 0x9506, 0x0110, 0x2508, - 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x6620, 0x1138, 0x2200, - 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x862b, 0x0005, 0x81ff, - 0x1904, 0x3599, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, - 0x080c, 0x4ac0, 0x0904, 0x359c, 0x080c, 0x6a6a, 0x0120, 0x080c, - 0x6a72, 0x1904, 0x359c, 0x080c, 0x66e7, 0x0904, 0x3599, 0x080c, - 0x686e, 0x0904, 0x3599, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, - 0x3567, 0x0804, 0x4547, 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, - 0xc18d, 0x2102, 0x080c, 0x4acd, 0x01a0, 0x080c, 0x6a6a, 0x0118, - 0x080c, 0x6a72, 0x1170, 0x080c, 0x66e7, 0x2009, 0x0002, 0x0128, - 0x080c, 0x686e, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, + 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x6644, 0x1138, 0x2200, + 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x865f, 0x0005, 0x81ff, + 0x1904, 0x35b9, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, + 0x080c, 0x4ae0, 0x0904, 0x35bc, 0x080c, 0x6a8e, 0x0120, 0x080c, + 0x6a96, 0x1904, 0x35bc, 0x080c, 0x670b, 0x0904, 0x35b9, 0x080c, + 0x6892, 0x0904, 0x35b9, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, + 0x3587, 0x0804, 0x4567, 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, + 0xc18d, 0x2102, 0x080c, 0x4aed, 0x01a0, 0x080c, 0x6a8e, 0x0118, + 0x080c, 0x6a96, 0x1170, 0x080c, 0x670b, 0x2009, 0x0002, 0x0128, + 0x080c, 0x6892, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1128, - 0x080c, 0x56dd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x3599, 0x798c, 0x2001, - 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4ac0, 0x0904, 0x359c, - 0x080c, 0x6a6a, 0x0120, 0x080c, 0x6a72, 0x1904, 0x359c, 0x080c, - 0x66e7, 0x0904, 0x3599, 0x080c, 0x685c, 0x0904, 0x3599, 0x2001, - 0x197e, 0x2004, 0xd0fc, 0x1904, 0x3567, 0x0804, 0x4547, 0xa9a0, - 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4acd, - 0x01a0, 0x080c, 0x6a6a, 0x0118, 0x080c, 0x6a72, 0x1170, 0x080c, - 0x66e7, 0x2009, 0x0002, 0x0128, 0x080c, 0x685c, 0x1170, 0x2009, + 0x080c, 0x56fd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x35b9, 0x798c, 0x2001, + 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4ae0, 0x0904, 0x35bc, + 0x080c, 0x6a8e, 0x0120, 0x080c, 0x6a96, 0x1904, 0x35bc, 0x080c, + 0x670b, 0x0904, 0x35b9, 0x080c, 0x6880, 0x0904, 0x35b9, 0x2001, + 0x197e, 0x2004, 0xd0fc, 0x1904, 0x3587, 0x0804, 0x4567, 0xa9a0, + 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4aed, + 0x01a0, 0x080c, 0x6a8e, 0x0118, 0x080c, 0x6a96, 0x1170, 0x080c, + 0x670b, 0x2009, 0x0002, 0x0128, 0x080c, 0x6880, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, - 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56dd, 0x0110, 0x9006, + 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56fd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x6100, - 0x0804, 0x3567, 0x080c, 0x4adc, 0x0904, 0x359c, 0x080c, 0x56e9, - 0x1904, 0x3599, 0x79a8, 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, + 0x0804, 0x3587, 0x080c, 0x4afc, 0x0904, 0x35bc, 0x080c, 0x5709, + 0x1904, 0x35b9, 0x79a8, 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, - 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, 0x3567, 0x78a8, - 0x909c, 0x0003, 0xd0b4, 0x1140, 0x939a, 0x0003, 0x1a04, 0x3599, - 0x625c, 0x7884, 0x9206, 0x1548, 0x080c, 0x879a, 0x2001, 0xfff4, - 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, - 0x0006, 0x78a8, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x4af5, + 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, 0x3587, 0x78a8, + 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, 0x1140, 0x939a, 0x0003, + 0x1a04, 0x35b9, 0x625c, 0x7884, 0x9206, 0x1538, 0x080c, 0x87ce, + 0x2001, 0xffec, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, + 0x0006, 0x78a8, 0x9084, 0x0080, 0x1118, 0x000e, 0x0804, 0x4b15, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, - 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x112f, - 0x7007, 0x0002, 0x701f, 0x46fd, 0x0005, 0x81ff, 0x1904, 0x3599, - 0x080c, 0x4adc, 0x0904, 0x359c, 0x080c, 0x6a6a, 0x1904, 0x3599, - 0x00c6, 0x080c, 0x4aa9, 0x00ce, 0x0904, 0x3599, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xc9a7, 0x0904, 0x3599, - 0x7007, 0x0003, 0x701f, 0x4701, 0x0005, 0x080c, 0x4245, 0x0804, - 0x3567, 0xa830, 0x9086, 0x0100, 0x0904, 0x3599, 0x8906, 0x8006, + 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x113c, + 0x7007, 0x0002, 0x701f, 0x471d, 0x0005, 0x81ff, 0x1904, 0x35b9, + 0x080c, 0x4afc, 0x0904, 0x35bc, 0x080c, 0x6a8e, 0x1904, 0x35b9, + 0x00c6, 0x080c, 0x4ac9, 0x00ce, 0x0904, 0x35b9, 0xa867, 0x0000, + 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xc9da, 0x0904, 0x35b9, + 0x7007, 0x0003, 0x701f, 0x4721, 0x0005, 0x080c, 0x4265, 0x0804, + 0x3587, 0xa830, 0x9086, 0x0100, 0x0904, 0x35b9, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, - 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4af5, 0x9006, - 0x080c, 0x267d, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, - 0x81ff, 0x1904, 0x3599, 0x080c, 0x74c8, 0x0110, 0x080c, 0x5fe9, - 0x7888, 0x908a, 0x1000, 0x1a04, 0x359c, 0x7984, 0x9186, 0x00ff, - 0x0138, 0x9182, 0x007f, 0x1a04, 0x359c, 0x2100, 0x080c, 0x2647, + 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4b15, 0x9006, + 0x080c, 0x2699, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, + 0x81ff, 0x1904, 0x35b9, 0x080c, 0x74ec, 0x0110, 0x080c, 0x6009, + 0x7888, 0x908a, 0x1000, 0x1a04, 0x35bc, 0x7984, 0x9186, 0x00ff, + 0x0138, 0x9182, 0x007f, 0x1a04, 0x35bc, 0x2100, 0x080c, 0x2663, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x1a02, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, 0x0000, 0x080c, - 0x74c8, 0x1158, 0x080c, 0x77cc, 0x080c, 0x6024, 0x9085, 0x0001, - 0x080c, 0x750f, 0x080c, 0x73f9, 0x00f0, 0x080c, 0xa888, 0x080c, - 0xab50, 0x080c, 0xa8a4, 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, + 0x74ec, 0x1158, 0x080c, 0x77ef, 0x080c, 0x6044, 0x9085, 0x0001, + 0x080c, 0x7533, 0x080c, 0x741d, 0x00f0, 0x080c, 0xa899, 0x080c, + 0xab61, 0x080c, 0xa8b5, 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1998, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x5f0f, 0x080c, 0x86e7, 0x7984, 0x080c, 0x74c8, 0x1110, 0x2009, - 0x00ff, 0x7a88, 0x080c, 0x45aa, 0x012e, 0x00ce, 0x002e, 0x0804, - 0x3567, 0x7984, 0x080c, 0x65bf, 0x2b08, 0x1904, 0x359c, 0x0804, - 0x3567, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3599, 0x60dc, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3599, - 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, 0x7984, - 0x9192, 0x0021, 0x1a04, 0x359c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4af2, - 0x701f, 0x47b9, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x518b, - 0x0005, 0x2009, 0x0080, 0x080c, 0x6620, 0x1118, 0x080c, 0x6a6a, - 0x0120, 0x2021, 0x400a, 0x0804, 0x3569, 0x00d6, 0x0096, 0xa964, + 0x5f2f, 0x080c, 0x871b, 0x7984, 0x080c, 0x74ec, 0x1110, 0x2009, + 0x00ff, 0x7a88, 0x080c, 0x45ca, 0x012e, 0x00ce, 0x002e, 0x0804, + 0x3587, 0x7984, 0x080c, 0x65e3, 0x2b08, 0x1904, 0x35bc, 0x0804, + 0x3587, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35b9, 0x60dc, + 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35b9, + 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0x7984, + 0x9192, 0x0021, 0x1a04, 0x35bc, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4b12, + 0x701f, 0x47d9, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x51ab, + 0x0005, 0x2009, 0x0080, 0x080c, 0x6644, 0x1118, 0x080c, 0x6a8e, + 0x0120, 0x2021, 0x400a, 0x0804, 0x3589, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, - 0x0904, 0x4852, 0x90be, 0x0112, 0x0904, 0x4852, 0x90be, 0x0113, - 0x0904, 0x4852, 0x90be, 0x0114, 0x0904, 0x4852, 0x90be, 0x0117, - 0x0904, 0x4852, 0x90be, 0x011a, 0x0904, 0x4852, 0x90be, 0x011c, - 0x0904, 0x4852, 0x90be, 0x0121, 0x0904, 0x4839, 0x90be, 0x0131, - 0x0904, 0x4839, 0x90be, 0x0171, 0x0904, 0x4852, 0x90be, 0x0173, - 0x0904, 0x4852, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, - 0x0804, 0x485d, 0x90be, 0x0212, 0x0904, 0x4846, 0x90be, 0x0213, + 0x0904, 0x4872, 0x90be, 0x0112, 0x0904, 0x4872, 0x90be, 0x0113, + 0x0904, 0x4872, 0x90be, 0x0114, 0x0904, 0x4872, 0x90be, 0x0117, + 0x0904, 0x4872, 0x90be, 0x011a, 0x0904, 0x4872, 0x90be, 0x011c, + 0x0904, 0x4872, 0x90be, 0x0121, 0x0904, 0x4859, 0x90be, 0x0131, + 0x0904, 0x4859, 0x90be, 0x0171, 0x0904, 0x4872, 0x90be, 0x0173, + 0x0904, 0x4872, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, + 0x0804, 0x487d, 0x90be, 0x0212, 0x0904, 0x4866, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, - 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x359c, + 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x35bc, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0007, 0x080c, 0x489b, 0x7028, 0x9080, 0x000e, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x489b, + 0x20a9, 0x0007, 0x080c, 0x48bb, 0x7028, 0x9080, 0x000e, 0x2098, + 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48bb, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48a8, 0x00b8, 0x7028, 0x9080, + 0x20e8, 0x20a9, 0x0001, 0x080c, 0x48c8, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, - 0x080c, 0x48a8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4aa9, + 0x080c, 0x48c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, + 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4ac9, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c, - 0xc9c2, 0x1120, 0x2009, 0x0003, 0x0804, 0x3599, 0x7007, 0x0003, - 0x701f, 0x4892, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, - 0x0804, 0x3599, 0xa820, 0x9086, 0x8001, 0x1904, 0x3567, 0x2009, - 0x0004, 0x0804, 0x3599, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, + 0xc9f5, 0x1120, 0x2009, 0x0003, 0x0804, 0x35b9, 0x7007, 0x0003, + 0x701f, 0x48b2, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, + 0x0804, 0x35b9, 0xa820, 0x9086, 0x8001, 0x1904, 0x3587, 0x2009, + 0x0004, 0x0804, 0x35b9, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3599, 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, - 0x0804, 0x3599, 0x7984, 0x78a8, 0x2040, 0x080c, 0xab49, 0x1120, - 0x9182, 0x007f, 0x0a04, 0x359c, 0x9186, 0x00ff, 0x0904, 0x359c, - 0x9182, 0x0800, 0x1a04, 0x359c, 0x7a8c, 0x7b88, 0x607c, 0x9306, - 0x1158, 0x6080, 0x924e, 0x0904, 0x359c, 0x080c, 0xab49, 0x1120, - 0x99cc, 0xff00, 0x0904, 0x359c, 0x0126, 0x2091, 0x8000, 0x080c, - 0x49bc, 0x0904, 0x493c, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, + 0x35b9, 0x60dc, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, + 0x0804, 0x35b9, 0x7984, 0x78a8, 0x2040, 0x080c, 0xab5a, 0x1120, + 0x9182, 0x007f, 0x0a04, 0x35bc, 0x9186, 0x00ff, 0x0904, 0x35bc, + 0x9182, 0x0800, 0x1a04, 0x35bc, 0x7a8c, 0x7b88, 0x607c, 0x9306, + 0x1158, 0x6080, 0x924e, 0x0904, 0x35bc, 0x080c, 0xab5a, 0x1120, + 0x99cc, 0xff00, 0x0904, 0x35bc, 0x0126, 0x2091, 0x8000, 0x080c, + 0x49dc, 0x0904, 0x495c, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, 0xb818, 0xbb1c, 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, 0x9305, 0xbb2c, 0x9305, 0xbb30, 0x9305, - 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c, 0x1128, 0x080c, 0x6a6a, - 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, 0x6913, 0x1108, 0xc185, + 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c, 0x1128, 0x080c, 0x6a8e, + 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, - 0x0804, 0x3569, 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, - 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xac4f, 0x0904, 0x4991, 0x2b00, - 0x6012, 0x080c, 0xcccb, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, - 0x4aa9, 0x00ce, 0x2b70, 0x1158, 0x080c, 0xabdf, 0x00ee, 0x00ce, - 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x3599, 0x900e, + 0x0804, 0x3589, 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, + 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xac60, 0x0904, 0x49b1, 0x2b00, + 0x6012, 0x080c, 0xccfe, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, + 0x4ac9, 0x00ce, 0x2b70, 0x1158, 0x080c, 0xabf0, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x35b9, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, 0x080c, 0x31ef, 0x6023, - 0x0001, 0x9006, 0x080c, 0x655c, 0xd89c, 0x0138, 0x2001, 0x0004, - 0x080c, 0x6570, 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, - 0x6570, 0x2009, 0x0002, 0x080c, 0xac7c, 0x78a8, 0xd094, 0x0138, + 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, 0x080c, 0x320f, 0x6023, + 0x0001, 0x9006, 0x080c, 0x6580, 0xd89c, 0x0138, 0x2001, 0x0004, + 0x080c, 0x6594, 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, + 0x6594, 0x2009, 0x0002, 0x080c, 0xac8d, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8d4, 0xc08d, 0xb8d6, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x3599, 0x7007, 0x0003, 0x701f, 0x49a0, 0x0005, + 0x0003, 0x0804, 0x35b9, 0x7007, 0x0003, 0x701f, 0x49c0, 0x0005, 0xa830, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, - 0xba04, 0x9294, 0x00ff, 0x0804, 0x5632, 0x900e, 0xa868, 0xd0f4, - 0x1904, 0x3567, 0x080c, 0x6913, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x3567, 0x00e6, 0x00d6, 0x0096, 0x83ff, - 0x0904, 0x4a0b, 0x902e, 0x080c, 0xab49, 0x0130, 0x9026, 0x20a9, + 0xba04, 0x9294, 0x00ff, 0x0804, 0x5652, 0x900e, 0xa868, 0xd0f4, + 0x1904, 0x3587, 0x080c, 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x3587, 0x00e6, 0x00d6, 0x0096, 0x83ff, + 0x0904, 0x4a2b, 0x902e, 0x080c, 0xab5a, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, - 0x4a1c, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558, + 0x4a3c, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, 0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, 0x2400, 0x9106, 0x1180, - 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, 0x6a0a, 0x1570, 0x2001, - 0x4000, 0x0460, 0x080c, 0x6a6a, 0x1540, 0x2001, 0x4000, 0x0430, + 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, 0x6a2e, 0x1570, 0x2001, + 0x4000, 0x0460, 0x080c, 0x6a8e, 0x1540, 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, - 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xab49, - 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x49d2, + 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xab5a, + 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x49f2, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x65bf, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, + 0x080c, 0x65e3, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3599, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, + 0x35b9, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, - 0x359c, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x359c, - 0x2010, 0x2918, 0x080c, 0x318f, 0x1120, 0x2009, 0x0003, 0x0804, - 0x3599, 0x7007, 0x0003, 0x701f, 0x4a5e, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1904, 0x3567, 0x2009, 0x0004, 0x0804, 0x3599, 0x7984, - 0x080c, 0xab49, 0x1120, 0x9182, 0x007f, 0x0a04, 0x359c, 0x9186, - 0x00ff, 0x0904, 0x359c, 0x9182, 0x0800, 0x1a04, 0x359c, 0x2001, - 0x9000, 0x080c, 0x568d, 0x1904, 0x3599, 0x0804, 0x3567, 0xa998, - 0x080c, 0xab49, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, - 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9000, 0x080c, 0x568d, + 0x35bc, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x35bc, + 0x2010, 0x2918, 0x080c, 0x31af, 0x1120, 0x2009, 0x0003, 0x0804, + 0x35b9, 0x7007, 0x0003, 0x701f, 0x4a7e, 0x0005, 0xa830, 0x9086, + 0x0100, 0x1904, 0x3587, 0x2009, 0x0004, 0x0804, 0x35b9, 0x7984, + 0x080c, 0xab5a, 0x1120, 0x9182, 0x007f, 0x0a04, 0x35bc, 0x9186, + 0x00ff, 0x0904, 0x35bc, 0x9182, 0x0800, 0x1a04, 0x35bc, 0x2001, + 0x9000, 0x080c, 0x56ad, 0x1904, 0x35b9, 0x0804, 0x3587, 0xa998, + 0x080c, 0xab5a, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, + 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9000, 0x080c, 0x56ad, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, 0x000a, - 0x0c48, 0x080c, 0x103a, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, + 0x0c48, 0x080c, 0x1047, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, - 0x7984, 0x080c, 0x6620, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x6620, + 0x7984, 0x080c, 0x6644, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, + 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x6644, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, - 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x6620, + 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x6644, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, - 0x0128, 0x2148, 0xa904, 0x080c, 0x106c, 0x0cc8, 0x7116, 0x711a, + 0x0128, 0x2148, 0xa904, 0x080c, 0x1079, 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x112f, 0x7007, 0x0002, 0x701f, 0x3567, + 0xa496, 0xa59a, 0x080c, 0x113c, 0x7007, 0x0002, 0x701f, 0x3587, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, - 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4b26, 0x7a36, 0x7833, + 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4b46, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e1, 0x0804, 0x4b8c, 0x0016, 0x0086, + 0x2004, 0xd084, 0x190c, 0x11ee, 0x0804, 0x4bac, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, - 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x103a, - 0x0904, 0x4b84, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, - 0x9080, 0x1e62, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, + 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x1047, + 0x0904, 0x4ba4, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, + 0x9080, 0x1e7a, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, 0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x2060, 0x001e, 0x8108, 0x2105, - 0x9005, 0xa146, 0x1520, 0x080c, 0x103a, 0x1130, 0x8109, 0xa946, + 0x9005, 0xa146, 0x1520, 0x080c, 0x1047, 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, - 0x1e62, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, + 0x1e7a, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, - 0x9082, 0x001b, 0x0002, 0x4bae, 0x4bae, 0x4bb0, 0x4bae, 0x4bae, - 0x4bae, 0x4bb4, 0x4bae, 0x4bae, 0x4bae, 0x4bb8, 0x4bae, 0x4bae, - 0x4bae, 0x4bbc, 0x4bae, 0x4bae, 0x4bae, 0x4bc0, 0x4bae, 0x4bae, - 0x4bae, 0x4bc4, 0x4bae, 0x4bae, 0x4bae, 0x4bc9, 0x080c, 0x0d7d, + 0x9082, 0x001b, 0x0002, 0x4bce, 0x4bce, 0x4bd0, 0x4bce, 0x4bce, + 0x4bce, 0x4bd4, 0x4bce, 0x4bce, 0x4bce, 0x4bd8, 0x4bce, 0x4bce, + 0x4bce, 0x4bdc, 0x4bce, 0x4bce, 0x4bce, 0x4be0, 0x4bce, 0x4bce, + 0x4bce, 0x4be4, 0x4bce, 0x4bce, 0x4bce, 0x4be9, 0x080c, 0x0d7d, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, - 0x4b87, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4b87, 0x00e6, 0x2071, - 0x189e, 0x7048, 0x9005, 0x0904, 0x4c60, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x4c5f, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, + 0x4ba7, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4ba7, 0x00e6, 0x2071, + 0x189e, 0x7048, 0x9005, 0x0904, 0x4c80, 0x0126, 0x2091, 0x8000, + 0x0e04, 0x4c7f, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d7d, 0x2060, 0x001e, - 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4c62, 0xa804, 0x9005, + 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4c82, 0xa804, 0x9005, 0x090c, 0x0d7d, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, - 0x0002, 0x9080, 0x1e62, 0x2005, 0xa04a, 0x0804, 0x4c62, 0x703c, + 0x0002, 0x9080, 0x1e7a, 0x2005, 0xa04a, 0x0804, 0x4c82, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x87ff, 0x0118, - 0x2748, 0x080c, 0x106c, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, - 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x106c, 0x9006, 0x7042, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, 0x87ff, 0x0118, + 0x2748, 0x080c, 0x1079, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, + 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x1079, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0d7d, 0x2048, 0xa800, 0x9005, - 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1e62, 0x2005, + 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1e7a, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, - 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4c81, 0x4c81, - 0x4c83, 0x4c81, 0x4c81, 0x4c81, 0x4c88, 0x4c81, 0x4c81, 0x4c81, - 0x4c8d, 0x4c81, 0x4c81, 0x4c81, 0x4c92, 0x4c81, 0x4c81, 0x4c81, - 0x4c97, 0x4c81, 0x4c81, 0x4c81, 0x4c9c, 0x4c81, 0x4c81, 0x4c81, - 0x4ca1, 0x080c, 0x0d7d, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4c0d, - 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4c0d, 0xaa94, 0xab98, 0xac9c, - 0x0804, 0x4c0d, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4c0d, 0xaab4, - 0xabb8, 0xacbc, 0x0804, 0x4c0d, 0xaac4, 0xabc8, 0xaccc, 0x0804, - 0x4c0d, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4c0d, 0x0016, 0x0026, - 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x6620, 0x2019, + 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4ca1, 0x4ca1, + 0x4ca3, 0x4ca1, 0x4ca1, 0x4ca1, 0x4ca8, 0x4ca1, 0x4ca1, 0x4ca1, + 0x4cad, 0x4ca1, 0x4ca1, 0x4ca1, 0x4cb2, 0x4ca1, 0x4ca1, 0x4ca1, + 0x4cb7, 0x4ca1, 0x4ca1, 0x4ca1, 0x4cbc, 0x4ca1, 0x4ca1, 0x4ca1, + 0x4cc1, 0x080c, 0x0d7d, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4c2d, + 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4c2d, 0xaa94, 0xab98, 0xac9c, + 0x0804, 0x4c2d, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4c2d, 0xaab4, + 0xabb8, 0xacbc, 0x0804, 0x4c2d, 0xaac4, 0xabc8, 0xaccc, 0x0804, + 0x4c2d, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4c2d, 0x0016, 0x0026, + 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x6644, 0x2019, 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, - 0x080c, 0x4b09, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0026, 0x080c, 0x56d5, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, - 0x4b09, 0x002e, 0x0005, 0x81ff, 0x1904, 0x3599, 0x0126, 0x2091, - 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x74c8, - 0x1158, 0x080c, 0x77cc, 0x080c, 0x6024, 0x9085, 0x0001, 0x080c, - 0x750f, 0x080c, 0x73f9, 0x0010, 0x080c, 0x5edf, 0x012e, 0x0804, - 0x3567, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3599, 0x080c, - 0x56e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x3599, 0x080c, 0x6a62, - 0x0120, 0x2009, 0x0008, 0x0804, 0x3599, 0x7984, 0x080c, 0x65bf, - 0x1904, 0x359c, 0x2b00, 0x7026, 0x080c, 0x6a6a, 0x7888, 0x1170, - 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6913, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3567, 0x080c, 0x4aa9, - 0x0904, 0x3599, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xca69, 0x0904, 0x3599, 0x7888, 0xd094, 0x0118, 0xb8d4, - 0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, 0x4d7b, 0x0005, 0x2061, - 0x1800, 0x080c, 0x56e9, 0x2009, 0x0007, 0x1578, 0x080c, 0x6a62, - 0x0118, 0x2009, 0x0008, 0x0448, 0x080c, 0x3357, 0x0120, 0xa998, - 0x080c, 0x65bf, 0x1530, 0x080c, 0x4ada, 0x0518, 0x080c, 0x6a6a, - 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6913, + 0x080c, 0x4b29, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, + 0x0026, 0x080c, 0x56f5, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, + 0x4b29, 0x002e, 0x0005, 0x81ff, 0x1904, 0x35b9, 0x0126, 0x2091, + 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x74ec, + 0x1158, 0x080c, 0x77ef, 0x080c, 0x6044, 0x9085, 0x0001, 0x080c, + 0x7533, 0x080c, 0x741d, 0x0010, 0x080c, 0x5eff, 0x012e, 0x0804, + 0x3587, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35b9, 0x080c, + 0x5709, 0x0120, 0x2009, 0x0007, 0x0804, 0x35b9, 0x080c, 0x6a86, + 0x0120, 0x2009, 0x0008, 0x0804, 0x35b9, 0x7984, 0x080c, 0x65e3, + 0x1904, 0x35bc, 0x2b00, 0x7026, 0x080c, 0x6a8e, 0x7888, 0x1170, + 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6937, 0x1108, 0xc185, + 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3587, 0x080c, 0x4ac9, + 0x0904, 0x35b9, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, + 0x080c, 0xca9c, 0x0904, 0x35b9, 0x7888, 0xd094, 0x0118, 0xb8d4, + 0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, 0x4d9b, 0x0005, 0x2061, + 0x1800, 0x080c, 0x5709, 0x2009, 0x0007, 0x1578, 0x080c, 0x6a86, + 0x0118, 0x2009, 0x0008, 0x0448, 0x080c, 0x3377, 0x0120, 0xa998, + 0x080c, 0x65e3, 0x1530, 0x080c, 0x4afa, 0x0518, 0x080c, 0x6a8e, + 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, - 0xc0fc, 0xa86a, 0x080c, 0xca69, 0x11e0, 0xa89c, 0xd094, 0x0118, + 0xc0fc, 0xa86a, 0x080c, 0xca9c, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, 0xa830, 0x9086, 0x0100, 0x7024, 0x2058, - 0x1110, 0x0804, 0x5632, 0x900e, 0x080c, 0x6913, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3567, 0x080c, 0x56e9, - 0x0120, 0x2009, 0x0007, 0x0804, 0x3599, 0x7f84, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, - 0x3599, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, - 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, 0x6620, 0x1904, - 0x4e1d, 0x080c, 0x6a6a, 0x0138, 0x080c, 0x6a72, 0x0120, 0x080c, - 0x6a0a, 0x1904, 0x4e1d, 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, + 0x1110, 0x0804, 0x5652, 0x900e, 0x080c, 0x6937, 0x1108, 0xc185, + 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3587, 0x080c, 0x5709, + 0x0120, 0x2009, 0x0007, 0x0804, 0x35b9, 0x7f84, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, + 0x35b9, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, + 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, 0x6644, 0x1904, + 0x4e3d, 0x080c, 0x6a8e, 0x0138, 0x080c, 0x6a96, 0x0120, 0x080c, + 0x6a2e, 0x1904, 0x4e3d, 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, - 0x0002, 0x080c, 0x48a8, 0x0048, 0x20a9, 0x0004, 0x4003, 0x2098, - 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x48a8, 0x9186, 0x007e, 0x0170, - 0x9186, 0x0080, 0x0158, 0x080c, 0x6a6a, 0x90c2, 0x0006, 0x1210, - 0xc1fd, 0x0020, 0x080c, 0x6913, 0x1108, 0xc1fd, 0x4104, 0xc1fc, + 0x0002, 0x080c, 0x48c8, 0x0048, 0x20a9, 0x0004, 0x4003, 0x2098, + 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x48c8, 0x9186, 0x007e, 0x0170, + 0x9186, 0x0080, 0x0158, 0x080c, 0x6a8e, 0x90c2, 0x0006, 0x1210, + 0xc1fd, 0x0020, 0x080c, 0x6937, 0x1108, 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, 0xb8c8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, - 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x489b, 0x9c80, + 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x48bb, 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, - 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0xab49, + 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, 0xab5a, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, - 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4dad, 0x86ff, - 0x1120, 0x7124, 0x810b, 0x0804, 0x3567, 0x7033, 0x0001, 0x7122, + 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4dcd, 0x86ff, + 0x1120, 0x7124, 0x810b, 0x0804, 0x3587, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x112f, 0x7007, 0x0002, 0x701f, 0x4e59, + 0xa496, 0xa59a, 0x080c, 0x113c, 0x7007, 0x0002, 0x701f, 0x4e79, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, - 0xa494, 0xa598, 0x0804, 0x4dad, 0x7124, 0x810b, 0x0804, 0x3567, + 0xa494, 0xa598, 0x0804, 0x4dcd, 0x7124, 0x810b, 0x0804, 0x3587, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x359c, 0x9502, 0x0a04, 0x359c, - 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x359c, 0x9502, 0x0a04, - 0x359c, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x359c, - 0x9502, 0x0a04, 0x359c, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, - 0x359c, 0x9502, 0x0a04, 0x359c, 0x9384, 0xff00, 0x8007, 0x90e2, - 0x0020, 0x0a04, 0x359c, 0x9502, 0x0a04, 0x359c, 0x9384, 0x00ff, - 0x90e2, 0x0020, 0x0a04, 0x359c, 0x9502, 0x0a04, 0x359c, 0x9484, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x359c, 0x9502, 0x0a04, - 0x359c, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x359c, 0x9502, - 0x0a04, 0x359c, 0x2061, 0x1988, 0x6102, 0x6206, 0x630a, 0x640e, - 0x0804, 0x3567, 0x080c, 0x4aa9, 0x0904, 0x3599, 0x2009, 0x0016, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35bc, 0x9502, 0x0a04, 0x35bc, + 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35bc, 0x9502, 0x0a04, + 0x35bc, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35bc, + 0x9502, 0x0a04, 0x35bc, 0x9284, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x35bc, 0x9502, 0x0a04, 0x35bc, 0x9384, 0xff00, 0x8007, 0x90e2, + 0x0020, 0x0a04, 0x35bc, 0x9502, 0x0a04, 0x35bc, 0x9384, 0x00ff, + 0x90e2, 0x0020, 0x0a04, 0x35bc, 0x9502, 0x0a04, 0x35bc, 0x9484, + 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35bc, 0x9502, 0x0a04, + 0x35bc, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35bc, 0x9502, + 0x0a04, 0x35bc, 0x2061, 0x1988, 0x6102, 0x6206, 0x630a, 0x640e, + 0x0804, 0x3587, 0x080c, 0x4ac9, 0x0904, 0x35b9, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x080c, 0x4af2, 0x701f, 0x4edd, 0x0005, 0x2001, 0x0138, 0x2003, + 0x080c, 0x4b12, 0x701f, 0x4efd, 0x0005, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, 0xd0a4, 0x1de8, 0x00ee, 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, - 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x4f5e, 0x6804, - 0x2008, 0x918c, 0xfff8, 0x1904, 0x4f5e, 0x680c, 0x9005, 0x0904, - 0x4f5e, 0x9082, 0xff01, 0x1a04, 0x4f5e, 0x6810, 0x9082, 0x005c, - 0x0a04, 0x4f5e, 0x6824, 0x2008, 0x9082, 0x0008, 0x0a04, 0x4f5e, - 0x9182, 0x0400, 0x1a04, 0x4f5e, 0x0056, 0x2029, 0x0000, 0x080c, - 0x8cec, 0x005e, 0x6944, 0x6820, 0x9102, 0x06c0, 0x6820, 0x9082, + 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x4f7e, 0x6804, + 0x2008, 0x918c, 0xfff8, 0x1904, 0x4f7e, 0x680c, 0x9005, 0x0904, + 0x4f7e, 0x9082, 0xff01, 0x1a04, 0x4f7e, 0x6810, 0x9082, 0x005c, + 0x0a04, 0x4f7e, 0x6824, 0x2008, 0x9082, 0x0008, 0x0a04, 0x4f7e, + 0x9182, 0x0400, 0x1a04, 0x4f7e, 0x0056, 0x2029, 0x0000, 0x080c, + 0x8d23, 0x005e, 0x6944, 0x6820, 0x9102, 0x06c0, 0x6820, 0x9082, 0x0019, 0x16a0, 0x6828, 0x6944, 0x810c, 0x9102, 0x0678, 0x6840, - 0x9082, 0x000f, 0x1658, 0x080c, 0x1053, 0x2900, 0x0904, 0x4f78, + 0x9082, 0x000f, 0x1658, 0x080c, 0x1060, 0x2900, 0x0904, 0x4f98, 0x684e, 0x00e6, 0x2071, 0x1930, 0x00b6, 0x2059, 0x0000, 0x080c, - 0x8ba8, 0x00be, 0x00ee, 0x0558, 0x080c, 0x8902, 0x080c, 0x8948, + 0x8bdf, 0x00be, 0x00ee, 0x0558, 0x080c, 0x8936, 0x080c, 0x897c, 0x11e0, 0x6857, 0x0000, 0x00c6, 0x2061, 0x0100, 0x6104, 0x918d, 0x2000, 0x6106, 0x6b10, 0x2061, 0x1a6a, 0x630a, 0x00ce, 0x080c, - 0x272c, 0x2001, 0x0138, 0x2102, 0x0804, 0x3567, 0x080c, 0x272c, - 0x2001, 0x0138, 0x2102, 0x0804, 0x359c, 0x00e6, 0x2071, 0x1930, - 0x080c, 0x8d7d, 0x080c, 0x8d8c, 0x080c, 0x8b97, 0x00ee, 0x2001, - 0x188a, 0x204c, 0x080c, 0x106c, 0x2001, 0x188a, 0x2003, 0x0000, - 0x080c, 0x272c, 0x2001, 0x0138, 0x2102, 0x0804, 0x3599, 0x2001, - 0x1924, 0x200c, 0x918e, 0x0000, 0x0904, 0x4fd7, 0x080c, 0x8b92, - 0x0904, 0x4fd7, 0x2001, 0x0101, 0x200c, 0x918c, 0xdfff, 0x2102, + 0x2748, 0x2001, 0x0138, 0x2102, 0x0804, 0x3587, 0x080c, 0x2748, + 0x2001, 0x0138, 0x2102, 0x0804, 0x35bc, 0x00e6, 0x2071, 0x1930, + 0x080c, 0x8db4, 0x080c, 0x8dc3, 0x080c, 0x8bce, 0x00ee, 0x2001, + 0x188a, 0x204c, 0x080c, 0x1079, 0x2001, 0x188a, 0x2003, 0x0000, + 0x080c, 0x2748, 0x2001, 0x0138, 0x2102, 0x0804, 0x35b9, 0x2001, + 0x1924, 0x200c, 0x918e, 0x0000, 0x0904, 0x4ff7, 0x080c, 0x8bc9, + 0x0904, 0x4ff7, 0x2001, 0x0101, 0x200c, 0x918c, 0xdfff, 0x2102, 0x2001, 0x0138, 0x2003, 0x0000, 0x00e6, 0x2071, 0x0300, 0x701c, - 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x8b97, 0x2001, 0x0035, 0x080c, - 0x1686, 0x00c6, 0x2061, 0x193c, 0x6004, 0x6100, 0x9106, 0x1de0, - 0x00ce, 0x080c, 0x272c, 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, - 0x2071, 0x1923, 0x080c, 0x8ad3, 0x0120, 0x2f00, 0x080c, 0x8b5d, + 0xd0a4, 0x1de8, 0x00ee, 0x080c, 0x8bce, 0x2001, 0x0035, 0x080c, + 0x1693, 0x00c6, 0x2061, 0x193c, 0x6004, 0x6100, 0x9106, 0x1de0, + 0x00ce, 0x080c, 0x2748, 0x2001, 0x0138, 0x2102, 0x00e6, 0x00f6, + 0x2071, 0x1923, 0x080c, 0x8b0a, 0x0120, 0x2f00, 0x080c, 0x8b94, 0x0cc8, 0x00fe, 0x00ee, 0x0126, 0x2091, 0x8000, 0x2001, 0x188a, - 0x200c, 0x81ff, 0x0138, 0x2148, 0x080c, 0x106c, 0x2001, 0x188a, + 0x200c, 0x81ff, 0x0138, 0x2148, 0x080c, 0x1079, 0x2001, 0x188a, 0x2003, 0x0000, 0x2001, 0x183d, 0x2003, 0x0020, 0x00e6, 0x2071, - 0x1930, 0x080c, 0x8d7d, 0x080c, 0x8d8c, 0x00ee, 0x012e, 0x0804, - 0x3567, 0x0006, 0x080c, 0x56d5, 0xd0cc, 0x000e, 0x0005, 0x0006, - 0x080c, 0x56d9, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, - 0x82ff, 0x1118, 0x7986, 0x0804, 0x3567, 0x83ff, 0x1904, 0x359c, - 0x2001, 0xfff0, 0x9200, 0x1a04, 0x359c, 0x2019, 0xffff, 0x6078, - 0x9302, 0x9200, 0x0a04, 0x359c, 0x7986, 0x6276, 0x0804, 0x3567, - 0x080c, 0x56e9, 0x1904, 0x3599, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, - 0x080c, 0x4aa9, 0x0904, 0x3599, 0x900e, 0x901e, 0x7326, 0x7332, + 0x1930, 0x080c, 0x8db4, 0x080c, 0x8dc3, 0x00ee, 0x012e, 0x0804, + 0x3587, 0x0006, 0x080c, 0x56f5, 0xd0cc, 0x000e, 0x0005, 0x0006, + 0x080c, 0x56f9, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, + 0x82ff, 0x1118, 0x7986, 0x0804, 0x3587, 0x83ff, 0x1904, 0x35bc, + 0x2001, 0xfff0, 0x9200, 0x1a04, 0x35bc, 0x2019, 0xffff, 0x6078, + 0x9302, 0x9200, 0x0a04, 0x35bc, 0x7986, 0x6276, 0x0804, 0x3587, + 0x080c, 0x5709, 0x1904, 0x35b9, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, + 0x080c, 0x4ac9, 0x0904, 0x35b9, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, - 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a6a, 0x0118, - 0x080c, 0x6a72, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, + 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a8e, 0x0118, + 0x080c, 0x6a96, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, - 0x2001, 0x0003, 0x080c, 0x9148, 0x2208, 0x0804, 0x3567, 0x7033, + 0x2001, 0x0003, 0x080c, 0x9181, 0x2208, 0x0804, 0x3587, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, - 0xa592, 0xa696, 0xa79a, 0x080c, 0x112f, 0x7007, 0x0002, 0x701f, - 0x505a, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, + 0xa592, 0xa696, 0xa79a, 0x080c, 0x113c, 0x7007, 0x0002, 0x701f, + 0x507a, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, - 0xa694, 0xa798, 0x0804, 0x5018, 0x7224, 0x900e, 0x2001, 0x0003, - 0x080c, 0x9148, 0x2208, 0x0804, 0x3567, 0x00f6, 0x00e6, 0x080c, - 0x56e9, 0x2009, 0x0007, 0x1904, 0x50ed, 0x2071, 0x189e, 0x745c, - 0x84ff, 0x2009, 0x000e, 0x1904, 0x50ed, 0xac9c, 0xad98, 0xaea4, - 0xafa0, 0x0096, 0x080c, 0x1053, 0x2009, 0x0002, 0x0904, 0x50ed, + 0xa694, 0xa798, 0x0804, 0x5038, 0x7224, 0x900e, 0x2001, 0x0003, + 0x080c, 0x9181, 0x2208, 0x0804, 0x3587, 0x00f6, 0x00e6, 0x080c, + 0x5709, 0x2009, 0x0007, 0x1904, 0x510d, 0x2071, 0x189e, 0x745c, + 0x84ff, 0x2009, 0x000e, 0x1904, 0x510d, 0xac9c, 0xad98, 0xaea4, + 0xafa0, 0x0096, 0x080c, 0x1060, 0x2009, 0x0002, 0x0904, 0x510d, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, - 0x8bff, 0x0178, 0x080c, 0x6a6a, 0x0118, 0x080c, 0x6a72, 0x1148, + 0x8bff, 0x0178, 0x080c, 0x6a8e, 0x0118, 0x080c, 0x6a96, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, - 0x9148, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, - 0x090c, 0x0d7d, 0x2148, 0x080c, 0x106c, 0x9006, 0x705e, 0x918d, + 0x9181, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, + 0x090c, 0x0d7d, 0x2148, 0x080c, 0x1079, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, - 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x50f9, 0x000e, - 0xa0a2, 0x080c, 0x112f, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, + 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x5119, 0x000e, + 0xa0a2, 0x080c, 0x113c, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0d7d, 0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x9148, 0xaa9a, 0x715c, - 0x81ff, 0x090c, 0x0d7d, 0x2148, 0x080c, 0x106c, 0x705f, 0x0000, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, + 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x9181, 0xaa9a, 0x715c, + 0x81ff, 0x090c, 0x0d7d, 0x2148, 0x080c, 0x1079, 0x705f, 0x0000, + 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a6a, 0x0118, 0x080c, - 0x6a72, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, + 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6a8e, 0x0118, 0x080c, + 0x6a96, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, 0x0d7d, 0x2148, 0x080c, - 0x106c, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, 0xa09f, 0x0000, + 0x1079, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, - 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x112f, + 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x113c, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, - 0x359c, 0xa884, 0xa988, 0x080c, 0x2614, 0x1518, 0x080c, 0x65bf, - 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4aa9, 0x01c8, - 0x080c, 0x4aa9, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xc9e2, 0x1120, - 0x2009, 0x0003, 0x0804, 0x3599, 0x7007, 0x0003, 0x701f, 0x51c6, - 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x3599, 0x7124, 0x080c, - 0x32f8, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, - 0x3599, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, + 0x35bc, 0xa884, 0xa988, 0x080c, 0x2630, 0x1518, 0x080c, 0x65e3, + 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4ac9, 0x01c8, + 0x080c, 0x4ac9, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, + 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xca15, 0x1120, + 0x2009, 0x0003, 0x0804, 0x35b9, 0x7007, 0x0003, 0x701f, 0x51e6, + 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x35b9, 0x7124, 0x080c, + 0x3318, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, + 0x35b9, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, - 0x080c, 0x0fb7, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, + 0x080c, 0x0fc4, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, - 0x000e, 0x007e, 0x0804, 0x4af5, 0x97c6, 0x7200, 0x11b8, 0x96c2, + 0x000e, 0x007e, 0x0804, 0x4b15, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, - 0x112f, 0x7007, 0x0002, 0x701f, 0x5222, 0x0005, 0x000e, 0x007e, - 0x0804, 0x359c, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, + 0x113c, 0x7007, 0x0002, 0x701f, 0x5242, 0x0005, 0x000e, 0x007e, + 0x0804, 0x35bc, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, - 0x0fb7, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, - 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4af5, 0x81ff, 0x1904, - 0x3599, 0x798c, 0x2001, 0x197d, 0x918c, 0x8000, 0x2102, 0x080c, - 0x4ac0, 0x0904, 0x359c, 0x080c, 0x6a6a, 0x0120, 0x080c, 0x6a72, - 0x1904, 0x359c, 0x080c, 0x66e7, 0x0904, 0x3599, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6880, 0x012e, 0x0904, 0x3599, 0x2001, 0x197d, - 0x2004, 0xd0fc, 0x1904, 0x3567, 0x0804, 0x4547, 0xa9a0, 0x2001, - 0x197d, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4acd, 0x01a0, - 0x080c, 0x6a6a, 0x0118, 0x080c, 0x6a72, 0x1170, 0x080c, 0x66e7, - 0x2009, 0x0002, 0x0128, 0x080c, 0x6880, 0x1170, 0x2009, 0x0003, + 0x0fc4, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, + 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4b15, 0x81ff, 0x1904, + 0x35b9, 0x798c, 0x2001, 0x197d, 0x918c, 0x8000, 0x2102, 0x080c, + 0x4ae0, 0x0904, 0x35bc, 0x080c, 0x6a8e, 0x0120, 0x080c, 0x6a96, + 0x1904, 0x35bc, 0x080c, 0x670b, 0x0904, 0x35b9, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a4, 0x012e, 0x0904, 0x35b9, 0x2001, 0x197d, + 0x2004, 0xd0fc, 0x1904, 0x3587, 0x0804, 0x4567, 0xa9a0, 0x2001, + 0x197d, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4aed, 0x01a0, + 0x080c, 0x6a8e, 0x0118, 0x080c, 0x6a96, 0x1170, 0x080c, 0x670b, + 0x2009, 0x0002, 0x0128, 0x080c, 0x68a4, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197d, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56dd, 0x0110, 0x9006, 0x0018, + 0x2004, 0xd0fc, 0x1128, 0x080c, 0x56fd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, - 0x1118, 0xd084, 0x0904, 0x44bc, 0x080c, 0x4adc, 0x0904, 0x359c, - 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, 0x080c, - 0x6a6a, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, + 0x1118, 0xd084, 0x0904, 0x44dc, 0x080c, 0x4afc, 0x0904, 0x35bc, + 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0x080c, + 0x6a8e, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, - 0x56d5, 0xd0b4, 0x0904, 0x44f6, 0x7884, 0x908e, 0x007e, 0x0904, - 0x44f6, 0x908e, 0x007f, 0x0904, 0x44f6, 0x908e, 0x0080, 0x0904, - 0x44f6, 0xb800, 0xd08c, 0x1904, 0x44f6, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xca01, 0x1120, 0x2009, 0x0003, 0x0804, - 0x3599, 0x7007, 0x0003, 0x701f, 0x52ee, 0x0005, 0x080c, 0x4adc, - 0x0904, 0x359c, 0x0804, 0x44f6, 0x080c, 0x3357, 0x0108, 0x0005, + 0x56f5, 0xd0b4, 0x0904, 0x4516, 0x7884, 0x908e, 0x007e, 0x0904, + 0x4516, 0x908e, 0x007f, 0x0904, 0x4516, 0x908e, 0x0080, 0x0904, + 0x4516, 0xb800, 0xd08c, 0x1904, 0x4516, 0xa867, 0x0000, 0xa868, + 0xc0fd, 0xa86a, 0x080c, 0xca34, 0x1120, 0x2009, 0x0003, 0x0804, + 0x35b9, 0x7007, 0x0003, 0x701f, 0x530e, 0x0005, 0x080c, 0x4afc, + 0x0904, 0x35bc, 0x0804, 0x4516, 0x080c, 0x3377, 0x0108, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3599, 0x080c, 0x56e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x3599, - 0x080c, 0x6a62, 0x0120, 0x2009, 0x0008, 0x0804, 0x3599, 0xb89c, - 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x44f6, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xca69, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3599, 0x7007, 0x0003, 0x701f, 0x5327, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x5632, 0x080c, - 0x4adc, 0x0904, 0x359c, 0x0804, 0x52c0, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x3599, 0x080c, 0x56e9, 0x2009, 0x0007, 0x1904, 0x3599, - 0x080c, 0x6a62, 0x0120, 0x2009, 0x0008, 0x0804, 0x3599, 0x080c, - 0x4adc, 0x0904, 0x359c, 0x080c, 0x6a6a, 0x2009, 0x0009, 0x1904, - 0x3599, 0x080c, 0x4aa9, 0x2009, 0x0002, 0x0904, 0x3599, 0x9006, + 0x35b9, 0x080c, 0x5709, 0x0120, 0x2009, 0x0007, 0x0804, 0x35b9, + 0x080c, 0x6a86, 0x0120, 0x2009, 0x0008, 0x0804, 0x35b9, 0xb89c, + 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x4516, 0x9006, 0xa866, 0xa832, + 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xca9c, 0x1120, 0x2009, 0x0003, + 0x0804, 0x35b9, 0x7007, 0x0003, 0x701f, 0x5347, 0x0005, 0xa830, + 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x5652, 0x080c, + 0x4afc, 0x0904, 0x35bc, 0x0804, 0x52e0, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x35b9, 0x080c, 0x5709, 0x2009, 0x0007, 0x1904, 0x35b9, + 0x080c, 0x6a86, 0x0120, 0x2009, 0x0008, 0x0804, 0x35b9, 0x080c, + 0x4afc, 0x0904, 0x35bc, 0x080c, 0x6a8e, 0x2009, 0x0009, 0x1904, + 0x35b9, 0x080c, 0x4ac9, 0x2009, 0x0002, 0x0904, 0x35b9, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, - 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x359c, 0xc0e5, 0xa952, - 0xa956, 0xa83e, 0x080c, 0xcccc, 0x2009, 0x0003, 0x0904, 0x3599, - 0x7007, 0x0003, 0x701f, 0x537d, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x3599, 0x0804, 0x3567, 0x7aa8, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x56e9, 0x1188, 0x2009, - 0x0014, 0x0804, 0x3599, 0xd2dc, 0x1568, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x3599, 0x080c, 0x56e9, 0x2009, 0x0007, 0x1904, 0x3599, - 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, 0x56b0, 0x0804, 0x3567, - 0xd2fc, 0x0158, 0x080c, 0x4adc, 0x0904, 0x359c, 0x7984, 0x9284, - 0x9000, 0x080c, 0x568d, 0x0804, 0x3567, 0x080c, 0x4adc, 0x0904, - 0x359c, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, - 0x1904, 0x5466, 0x080c, 0x4aa9, 0x2009, 0x0002, 0x0904, 0x5466, + 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x35bc, 0xc0e5, 0xa952, + 0xa956, 0xa83e, 0x080c, 0xccff, 0x2009, 0x0003, 0x0904, 0x35b9, + 0x7007, 0x0003, 0x701f, 0x539d, 0x0005, 0xa830, 0x9086, 0x0100, + 0x2009, 0x0004, 0x0904, 0x35b9, 0x0804, 0x3587, 0x7aa8, 0x9284, + 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x5709, 0x1188, 0x2009, + 0x0014, 0x0804, 0x35b9, 0xd2dc, 0x1568, 0x81ff, 0x2009, 0x0001, + 0x1904, 0x35b9, 0x080c, 0x5709, 0x2009, 0x0007, 0x1904, 0x35b9, + 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, 0x56d0, 0x0804, 0x3587, + 0xd2fc, 0x0158, 0x080c, 0x4afc, 0x0904, 0x35bc, 0x7984, 0x9284, + 0x9000, 0x080c, 0x56ad, 0x0804, 0x3587, 0x080c, 0x4afc, 0x0904, + 0x35bc, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, + 0x1904, 0x5486, 0x080c, 0x4ac9, 0x2009, 0x0002, 0x0904, 0x5486, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x080c, 0x4af2, 0x701f, 0x53d7, 0x0005, 0xa86c, + 0x7c9c, 0x7d98, 0x080c, 0x4b12, 0x701f, 0x53f7, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, 0x1120, 0xa874, 0x9084, - 0xff00, 0x0110, 0x1904, 0x359c, 0xa866, 0xa832, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0x4adc, 0x1110, 0x0804, 0x359c, 0x2009, 0x0043, - 0x080c, 0xcd34, 0x2009, 0x0003, 0x0904, 0x5466, 0x7007, 0x0003, - 0x701f, 0x53fb, 0x0005, 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, - 0x0904, 0x5466, 0x7984, 0x7aa8, 0x9284, 0x1000, 0x080c, 0x568d, - 0x0804, 0x3567, 0x00c6, 0xaab0, 0x9284, 0xc000, 0x0140, 0xd2ec, - 0x0168, 0x080c, 0x56e9, 0x1150, 0x2009, 0x0014, 0x04f0, 0x2061, - 0x1800, 0x080c, 0x56e9, 0x2009, 0x0007, 0x15b8, 0xd2f4, 0x0128, - 0x9284, 0x5000, 0x080c, 0x56b0, 0x0050, 0xd2fc, 0x0178, 0x080c, - 0x4ada, 0x0588, 0xa998, 0x9284, 0x9000, 0x080c, 0x568d, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4ada, - 0x0510, 0x080c, 0x6a6a, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, + 0xff00, 0x0110, 0x1904, 0x35bc, 0xa866, 0xa832, 0xa868, 0xc0fd, + 0xa86a, 0x080c, 0x4afc, 0x1110, 0x0804, 0x35bc, 0x2009, 0x0043, + 0x080c, 0xcd67, 0x2009, 0x0003, 0x0904, 0x5486, 0x7007, 0x0003, + 0x701f, 0x541b, 0x0005, 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, + 0x0904, 0x5486, 0x7984, 0x7aa8, 0x9284, 0x1000, 0x080c, 0x56ad, + 0x0804, 0x3587, 0x00c6, 0xaab0, 0x9284, 0xc000, 0x0140, 0xd2ec, + 0x0168, 0x080c, 0x5709, 0x1150, 0x2009, 0x0014, 0x04f0, 0x2061, + 0x1800, 0x080c, 0x5709, 0x2009, 0x0007, 0x15b8, 0xd2f4, 0x0128, + 0x9284, 0x5000, 0x080c, 0x56d0, 0x0050, 0xd2fc, 0x0178, 0x080c, + 0x4afa, 0x0588, 0xa998, 0x9284, 0x9000, 0x080c, 0x56ad, 0xa87b, + 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4afa, + 0x0510, 0x080c, 0x6a8e, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, - 0x1190, 0x080c, 0x4ada, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, - 0xcd34, 0x2009, 0x0003, 0x0108, 0x0078, 0x0429, 0x19c0, 0xa897, + 0x1190, 0x080c, 0x4afa, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, + 0xcd67, 0x2009, 0x0003, 0x0108, 0x0078, 0x0429, 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, - 0x0904, 0x3599, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, - 0x568d, 0x001e, 0x1904, 0x3599, 0x0804, 0x3567, 0x00f6, 0x2d78, + 0x0904, 0x35b9, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, + 0x56ad, 0x001e, 0x1904, 0x35b9, 0x0804, 0x3587, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0xaab0, 0xd2dc, 0x0150, 0x0016, 0xa998, - 0x9284, 0x1000, 0xc0fd, 0x080c, 0x568d, 0x001e, 0x9085, 0x0001, - 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3599, 0x080c, - 0x56e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x3599, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x6620, 0x1904, 0x359c, 0x9186, 0x007f, - 0x0138, 0x080c, 0x6a6a, 0x0120, 0x2009, 0x0009, 0x0804, 0x3599, - 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, 0xa867, + 0x9284, 0x1000, 0xc0fd, 0x080c, 0x56ad, 0x001e, 0x9085, 0x0001, + 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35b9, 0x080c, + 0x5709, 0x0120, 0x2009, 0x0007, 0x0804, 0x35b9, 0x7984, 0x7ea8, + 0x96b4, 0x00ff, 0x080c, 0x6644, 0x1904, 0x35bc, 0x9186, 0x007f, + 0x0138, 0x080c, 0x6a8e, 0x0120, 0x2009, 0x0009, 0x0804, 0x35b9, + 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a, - 0x080c, 0xca1b, 0x1120, 0x2009, 0x0003, 0x0804, 0x3599, 0x7007, - 0x0003, 0x701f, 0x54c4, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x3599, 0xa8e0, 0xa866, 0xa810, + 0x080c, 0xca4e, 0x1120, 0x2009, 0x0003, 0x0804, 0x35b9, 0x7007, + 0x0003, 0x701f, 0x54e4, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, + 0x1120, 0x2009, 0x0004, 0x0804, 0x35b9, 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4af5, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3599, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, + 0x7d98, 0x0804, 0x4b15, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, + 0x0804, 0x35b9, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b2, 0x0040, 0x92c6, 0x0001, 0x1118, - 0x7023, 0x19cc, 0x0010, 0x0804, 0x359c, 0x2009, 0x001a, 0x7a8c, + 0x7023, 0x19cc, 0x0010, 0x0804, 0x35bc, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, - 0x4af2, 0x701f, 0x5514, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, + 0x4b12, 0x701f, 0x5534, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, - 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x3567, 0x080c, - 0x4aa9, 0x1120, 0x2009, 0x0002, 0x0804, 0x3599, 0x7984, 0x9194, + 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x3587, 0x080c, + 0x4ac9, 0x1120, 0x2009, 0x0002, 0x0804, 0x35b9, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b2, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19cc, 0x0010, 0x0804, - 0x359c, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, + 0x35bc, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, 0x4af5, - 0x7884, 0x908a, 0x1000, 0x1a04, 0x359c, 0x0126, 0x2091, 0x8000, + 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, 0x4b15, + 0x7884, 0x908a, 0x1000, 0x1a04, 0x35bc, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1a02, 0x6142, - 0x00ce, 0x012e, 0x0804, 0x3567, 0x00c6, 0x080c, 0x74c8, 0x1160, - 0x080c, 0x77cc, 0x080c, 0x6024, 0x9085, 0x0001, 0x080c, 0x750f, - 0x080c, 0x73f9, 0x080c, 0x0d7d, 0x2061, 0x1800, 0x6030, 0xc09d, - 0x6032, 0x080c, 0x5edf, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, - 0x2004, 0x908e, 0x0000, 0x0904, 0x3599, 0x7884, 0x9005, 0x0188, - 0x7888, 0x2061, 0x199b, 0x2c0c, 0x2062, 0x080c, 0x29f7, 0x01a0, - 0x080c, 0x29ff, 0x0188, 0x080c, 0x2a07, 0x0170, 0x2162, 0x0804, - 0x359c, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, + 0x00ce, 0x012e, 0x0804, 0x3587, 0x00c6, 0x080c, 0x74ec, 0x1160, + 0x080c, 0x77ef, 0x080c, 0x6044, 0x9085, 0x0001, 0x080c, 0x7533, + 0x080c, 0x741d, 0x080c, 0x0d7d, 0x2061, 0x1800, 0x6030, 0xc09d, + 0x6032, 0x080c, 0x5eff, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, + 0x2004, 0x908e, 0x0000, 0x0904, 0x35b9, 0x7884, 0x9005, 0x0188, + 0x7888, 0x2061, 0x199b, 0x2c0c, 0x2062, 0x080c, 0x2a17, 0x01a0, + 0x080c, 0x2a1f, 0x0188, 0x080c, 0x2a27, 0x0170, 0x2162, 0x0804, + 0x35bc, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1588, - 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x080c, 0xa888, 0x0026, - 0x2011, 0x0003, 0x080c, 0xa1b1, 0x2011, 0x0002, 0x080c, 0xa1bb, - 0x002e, 0x080c, 0xa07a, 0x0036, 0x901e, 0x080c, 0xa0fa, 0x003e, - 0x080c, 0xa8a4, 0x60e3, 0x0000, 0x080c, 0xe712, 0x080c, 0xe72d, - 0x9085, 0x0001, 0x080c, 0x750f, 0x9006, 0x080c, 0x2a29, 0x2001, - 0x1800, 0x2003, 0x0004, 0x0026, 0x2011, 0x0008, 0x080c, 0x2a63, - 0x002e, 0x00ce, 0x0804, 0x3567, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x3599, 0x080c, 0x56e9, 0x0120, 0x2009, 0x0007, 0x0804, - 0x3599, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6620, 0x1904, - 0x359c, 0x9186, 0x007f, 0x0138, 0x080c, 0x6a6a, 0x0120, 0x2009, - 0x0009, 0x0804, 0x3599, 0x080c, 0x4aa9, 0x1120, 0x2009, 0x0002, - 0x0804, 0x3599, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, - 0xca1e, 0x1120, 0x2009, 0x0003, 0x0804, 0x3599, 0x7007, 0x0003, - 0x701f, 0x561b, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, - 0x0004, 0x0804, 0x3599, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, + 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x080c, 0xa899, 0x0026, + 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, 0x080c, 0xa1c8, + 0x002e, 0x080c, 0xa0b3, 0x0036, 0x901e, 0x080c, 0xa133, 0x003e, + 0x080c, 0xa8b5, 0x60e3, 0x0000, 0x080c, 0xe74f, 0x080c, 0xe76a, + 0x9085, 0x0001, 0x080c, 0x7533, 0x9006, 0x080c, 0x2a49, 0x2001, + 0x1800, 0x2003, 0x0004, 0x0026, 0x2011, 0x0008, 0x080c, 0x2a83, + 0x002e, 0x00ce, 0x0804, 0x3587, 0x81ff, 0x0120, 0x2009, 0x0001, + 0x0804, 0x35b9, 0x080c, 0x5709, 0x0120, 0x2009, 0x0007, 0x0804, + 0x35b9, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6644, 0x1904, + 0x35bc, 0x9186, 0x007f, 0x0138, 0x080c, 0x6a8e, 0x0120, 0x2009, + 0x0009, 0x0804, 0x35b9, 0x080c, 0x4ac9, 0x1120, 0x2009, 0x0002, + 0x0804, 0x35b9, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, + 0xca51, 0x1120, 0x2009, 0x0003, 0x0804, 0x35b9, 0x7007, 0x0003, + 0x701f, 0x563b, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, + 0x0004, 0x0804, 0x35b9, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, - 0x0804, 0x4af5, 0xa898, 0x9086, 0x000d, 0x1904, 0x3599, 0x2021, - 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x563f, 0x0010, 0x012e, + 0x0804, 0x4b15, 0xa898, 0x9086, 0x000d, 0x1904, 0x35b9, 0x2021, + 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x565f, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, - 0xa9a8, 0x799e, 0x080c, 0x4ae5, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e1, 0x7007, 0x0001, 0x2091, 0x5000, + 0xa9a8, 0x799e, 0x080c, 0x4b05, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x11ee, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1a02, 0x7984, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x1a10, 0x2044, 0x2001, 0x1a17, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, - 0x0000, 0x00ce, 0x012e, 0x0804, 0x3567, 0x0126, 0x2091, 0x8000, - 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, 0x0006, 0x080c, 0xc87f, + 0x0000, 0x00ce, 0x012e, 0x0804, 0x3587, 0x0126, 0x2091, 0x8000, + 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, 0x0006, 0x080c, 0xc8b2, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, - 0x0160, 0x080c, 0x603e, 0x080c, 0xab49, 0x0110, 0xb817, 0x0000, + 0x0160, 0x080c, 0x605e, 0x080c, 0xab5a, 0x0110, 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, 0x002e, 0x001e, 0x8108, - 0x1f04, 0x56b8, 0x015e, 0x012e, 0x0005, 0x2001, 0x1848, 0x2004, + 0x1f04, 0x56d8, 0x015e, 0x012e, 0x0005, 0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, - 0x0005, 0x79a4, 0x9182, 0x0081, 0x1a04, 0x359c, 0x810c, 0x0016, - 0x080c, 0x4aa9, 0x080c, 0x0f42, 0x2100, 0x2238, 0x7d84, 0x7c88, - 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x4af2, 0x701f, 0x5710, 0x0005, + 0x0005, 0x79a4, 0x9182, 0x0081, 0x1a04, 0x35bc, 0x810c, 0x0016, + 0x080c, 0x4ac9, 0x080c, 0x0f4f, 0x2100, 0x2238, 0x7d84, 0x7c88, + 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x4b12, 0x701f, 0x5730, 0x0005, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189e, 0x080c, - 0x4af5, 0x701f, 0x5724, 0x0005, 0x2061, 0x18b8, 0x2c44, 0x0016, - 0x0026, 0xa270, 0xa174, 0x080c, 0x0f4a, 0x002e, 0x001e, 0x080c, - 0x0ff7, 0x9006, 0xa802, 0xa806, 0x0804, 0x3567, 0x0126, 0x0156, + 0x4b15, 0x701f, 0x5744, 0x0005, 0x2061, 0x18b8, 0x2c44, 0x0016, + 0x0026, 0xa270, 0xa174, 0x080c, 0x0f57, 0x002e, 0x001e, 0x080c, + 0x1004, 0x9006, 0xa802, 0xa806, 0x0804, 0x3587, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044, 0xd0a4, - 0x11e8, 0xd084, 0x0118, 0x080c, 0x58df, 0x0068, 0xd08c, 0x0118, - 0x080c, 0x57e8, 0x0040, 0xd094, 0x0118, 0x080c, 0x57b8, 0x0018, + 0x11e8, 0xd084, 0x0118, 0x080c, 0x58ff, 0x0068, 0xd08c, 0x0118, + 0x080c, 0x5808, 0x0040, 0xd094, 0x0118, 0x080c, 0x57d8, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7098, @@ -2596,216 +2600,216 @@ unsigned short risc_code01[] = { 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, - 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x5fa0, + 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x5fc0, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7087, 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009, 0x1d80, 0x200b, 0x0000, 0x7097, 0x0000, 0x708b, - 0x000f, 0x2009, 0x000f, 0x2011, 0x5e82, 0x080c, 0x86e7, 0x0005, + 0x000f, 0x2009, 0x000f, 0x2011, 0x5ea2, 0x080c, 0x871b, 0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, - 0x9005, 0x1528, 0x2011, 0x5e82, 0x080c, 0x861d, 0x6040, 0x9094, + 0x9005, 0x1528, 0x2011, 0x5ea2, 0x080c, 0x8651, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, - 0x1168, 0x1f04, 0x57ce, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, + 0x1168, 0x1f04, 0x57ee, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, - 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, 0x6029, 0x0000, 0x0005, - 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0d7d, 0x000b, 0x0005, 0x57f2, - 0x5843, 0x58de, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, + 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, 0x6049, 0x0000, 0x0005, + 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0d7d, 0x000b, 0x0005, 0x5812, + 0x5863, 0x58fe, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, - 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x5801, 0x080c, + 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x5821, 0x080c, 0x0d7d, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, - 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x6005, + 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x6025, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1d0e, 0x20a9, 0x0004, - 0x4003, 0x080c, 0xa67d, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, + 0x4003, 0x080c, 0xa68e, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, - 0x600f, 0x0000, 0x080c, 0x5eb3, 0x00fe, 0x9006, 0x7092, 0x6043, + 0x600f, 0x0000, 0x080c, 0x5ed3, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, - 0x0904, 0x58bb, 0x6020, 0xd0b4, 0x1904, 0x58b9, 0x71a0, 0x81ff, - 0x0904, 0x58a7, 0x9486, 0x000c, 0x1904, 0x58b4, 0x9480, 0x0018, - 0x8004, 0x20a8, 0x080c, 0x5ffe, 0x2011, 0x0260, 0x2019, 0x1d00, - 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x5860, + 0x0904, 0x58db, 0x6020, 0xd0b4, 0x1904, 0x58d9, 0x71a0, 0x81ff, + 0x0904, 0x58c7, 0x9486, 0x000c, 0x1904, 0x58d4, 0x9480, 0x0018, + 0x8004, 0x20a8, 0x080c, 0x601e, 0x2011, 0x0260, 0x2019, 0x1d00, + 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x5880, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, - 0x2009, 0x07d0, 0x2011, 0x5e89, 0x080c, 0x86e7, 0x080c, 0x6005, - 0x04c0, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, + 0x2009, 0x07d0, 0x2011, 0x5ea9, 0x080c, 0x871b, 0x080c, 0x6025, + 0x04c0, 0x080c, 0x601e, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, - 0x7804, 0x9005, 0x0190, 0x080c, 0x5ffe, 0x2011, 0x026e, 0x2019, + 0x7804, 0x9005, 0x0190, 0x080c, 0x601e, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, - 0x8210, 0x8318, 0x1f04, 0x589b, 0x0078, 0x70a3, 0x0000, 0x080c, - 0x5ffe, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, + 0x8210, 0x8318, 0x1f04, 0x58bb, 0x0078, 0x70a3, 0x0000, 0x080c, + 0x601e, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1d00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, - 0xd0b4, 0x1db8, 0x080c, 0xa67d, 0x20e1, 0x0001, 0x2099, 0x1d00, + 0xd0b4, 0x1db8, 0x080c, 0xa68e, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19f3, 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, - 0x0056, 0x60a7, 0x9575, 0x080c, 0x9e09, 0x08d8, 0x0005, 0x7098, - 0x908a, 0x001d, 0x1a0c, 0x0d7d, 0x000b, 0x0005, 0x5910, 0x5923, - 0x594c, 0x596c, 0x5992, 0x59c1, 0x59e7, 0x5a1f, 0x5a45, 0x5a73, - 0x5aae, 0x5ae6, 0x5b04, 0x5b2f, 0x5b51, 0x5b6c, 0x5b76, 0x5baa, - 0x5bd0, 0x5bff, 0x5c25, 0x5c5d, 0x5ca1, 0x5cde, 0x5cff, 0x5d58, - 0x5d7a, 0x5da8, 0x5da8, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, + 0x0056, 0x60a7, 0x9575, 0x080c, 0x9e42, 0x08d8, 0x0005, 0x7098, + 0x908a, 0x001d, 0x1a0c, 0x0d7d, 0x000b, 0x0005, 0x5930, 0x5943, + 0x596c, 0x598c, 0x59b2, 0x59e1, 0x5a07, 0x5a3f, 0x5a65, 0x5a93, + 0x5ace, 0x5b06, 0x5b24, 0x5b4f, 0x5b71, 0x5b8c, 0x5b96, 0x5bca, + 0x5bf0, 0x5c1f, 0x5c45, 0x5c7d, 0x5cc1, 0x5cfe, 0x5d1f, 0x5d78, + 0x5d9a, 0x5dc8, 0x5dc8, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, - 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5e89, - 0x080c, 0x86e7, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, - 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x5ffe, 0x2079, 0x0260, + 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5ea9, + 0x080c, 0x871b, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, + 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, - 0x5e89, 0x080c, 0x861d, 0x709b, 0x0010, 0x080c, 0x5b76, 0x0010, + 0x5ea9, 0x080c, 0x8651, 0x709b, 0x0010, 0x080c, 0x5b96, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, - 0x0004, 0x2011, 0x5e89, 0x080c, 0x861d, 0x080c, 0x5f82, 0x2079, + 0x0004, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x080c, 0x5fa2, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, - 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x5961, 0x60c3, 0x0014, - 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, - 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, 0x0014, 0x11b8, 0x080c, - 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, + 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x5981, 0x60c3, 0x0014, + 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, + 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, - 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x5fda, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x5f82, 0x2079, - 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5ffe, 0x080c, - 0x5fe1, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, - 0x0138, 0x2011, 0x0008, 0x080c, 0x5e36, 0x0168, 0x080c, 0x5fb7, + 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x5ffa, + 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x5fa2, 0x2079, + 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x601e, 0x080c, + 0x6001, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, + 0x0138, 0x2011, 0x0008, 0x080c, 0x5e56, 0x0168, 0x080c, 0x5fd7, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb3, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5e89, 0x080c, - 0x861d, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5ffe, 0x2079, 0x0260, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ed3, 0x00fe, + 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5ea9, 0x080c, + 0x8651, 0x9086, 0x0014, 0x11b8, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, - 0x0006, 0x0029, 0x0010, 0x080c, 0x5fda, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x0007, 0x080c, 0x5f82, 0x2079, 0x0240, 0x7833, 0x1104, - 0x7837, 0x0000, 0x080c, 0x5ffe, 0x080c, 0x5fe1, 0x11b8, 0x7084, - 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x3368, - 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5e36, - 0x0180, 0x080c, 0x4fdf, 0x0110, 0x080c, 0x267d, 0x20a9, 0x0008, + 0x0006, 0x0029, 0x0010, 0x080c, 0x5ffa, 0x00fe, 0x0005, 0x00f6, + 0x709b, 0x0007, 0x080c, 0x5fa2, 0x2079, 0x0240, 0x7833, 0x1104, + 0x7837, 0x0000, 0x080c, 0x601e, 0x080c, 0x6001, 0x11b8, 0x7084, + 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x3388, + 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5e56, + 0x0180, 0x080c, 0x4fff, 0x0110, 0x080c, 0x2699, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x0500, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, + 0x7090, 0x9005, 0x0500, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, - 0x0010, 0x080c, 0x5fda, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, - 0x080c, 0x5f82, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, - 0x080c, 0x5fe1, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5da9, - 0x1188, 0x9085, 0x0001, 0x080c, 0x267d, 0x20a9, 0x0008, 0x080c, - 0x5ffe, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb3, 0x0010, 0x080c, - 0x5903, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, - 0x5e89, 0x080c, 0x861d, 0x9086, 0x0014, 0x1560, 0x080c, 0x5ffe, + 0x0010, 0x080c, 0x5ffa, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, + 0x080c, 0x5fa2, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, + 0x080c, 0x6001, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5dc9, + 0x1188, 0x9085, 0x0001, 0x080c, 0x2699, 0x20a9, 0x0008, 0x080c, + 0x601e, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ed3, 0x0010, 0x080c, + 0x5923, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, + 0x5ea9, 0x080c, 0x8651, 0x9086, 0x0014, 0x1560, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, 0x0000, 0x709b, 0x000e, 0x080c, - 0x5b51, 0x0010, 0x080c, 0x5fda, 0x00fe, 0x0005, 0x00f6, 0x709b, + 0x5b71, 0x0010, 0x080c, 0x5ffa, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, 0x1d0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, - 0x2019, 0xffff, 0x4304, 0x080c, 0x5f82, 0x2079, 0x0240, 0x7833, - 0x1106, 0x7837, 0x0000, 0x080c, 0x5fe1, 0x0118, 0x2013, 0x0000, + 0x2019, 0xffff, 0x4304, 0x080c, 0x5fa2, 0x2079, 0x0240, 0x7833, + 0x1106, 0x7837, 0x0000, 0x080c, 0x6001, 0x0118, 0x2013, 0x0000, 0x0020, 0x7060, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x1d0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, - 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5ad3, - 0x60c3, 0x0084, 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x01c0, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, 0x0084, - 0x1178, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, + 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5af3, + 0x60c3, 0x0084, 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, 0x7090, + 0x9005, 0x01c0, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, 0x0084, + 0x1178, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, - 0x080c, 0x5fda, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, - 0x5f82, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, - 0x5ffe, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, + 0x080c, 0x5ffa, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, + 0x5fa2, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, + 0x601e, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, - 0x5b17, 0x60c3, 0x0084, 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01e0, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, - 0x0084, 0x1198, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x5b37, 0x60c3, 0x0084, 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, + 0x7090, 0x9005, 0x01e0, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, + 0x0084, 0x1198, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, - 0x5f54, 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x5fda, 0x00fe, - 0x0005, 0x918d, 0x0001, 0x080c, 0x6029, 0x709b, 0x000f, 0x7093, + 0x5f74, 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x5ffa, 0x00fe, + 0x0005, 0x918d, 0x0001, 0x080c, 0x6049, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, - 0x5e89, 0x080c, 0x8611, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, - 0x5e89, 0x080c, 0x861d, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, - 0x080c, 0xa67d, 0x080c, 0x5ffe, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x5ea9, 0x080c, 0x8645, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, + 0x5ea9, 0x080c, 0x8651, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, + 0x080c, 0xa68e, 0x080c, 0x601e, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, - 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x5fe1, + 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x6001, 0x11a0, 0x717c, 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, - 0x0160, 0x080c, 0x2614, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, - 0x0120, 0x2011, 0x0008, 0x080c, 0x5e36, 0x60c3, 0x0014, 0x080c, - 0x5eb3, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5e89, - 0x080c, 0x861d, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5ffe, 0x2079, + 0x0160, 0x080c, 0x2630, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, + 0x0120, 0x2011, 0x0008, 0x080c, 0x5e56, 0x60c3, 0x0014, 0x080c, + 0x5ed3, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5ea9, + 0x080c, 0x8651, 0x9086, 0x0014, 0x11b8, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0013, 0x080c, 0x5f90, 0x2079, 0x0240, 0x7833, - 0x1103, 0x7837, 0x0000, 0x080c, 0x5ffe, 0x080c, 0x5fe1, 0x1170, + 0x00f6, 0x709b, 0x0013, 0x080c, 0x5fb0, 0x2079, 0x0240, 0x7833, + 0x1103, 0x7837, 0x0000, 0x080c, 0x601e, 0x080c, 0x6001, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, - 0x0008, 0x080c, 0x5e36, 0x0168, 0x080c, 0x5fb7, 0x20a9, 0x0008, + 0x0008, 0x080c, 0x5e56, 0x0168, 0x080c, 0x5fd7, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x0500, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x4003, 0x60c3, 0x0014, 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, + 0x7090, 0x9005, 0x0500, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0015, - 0x080c, 0x5f90, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, - 0x080c, 0x5ffe, 0x080c, 0x5fe1, 0x11b8, 0x7084, 0x9005, 0x11a0, - 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x3368, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5e36, 0x0180, 0x080c, - 0x4fdf, 0x0110, 0x080c, 0x267d, 0x20a9, 0x0008, 0x20e1, 0x0000, + 0x080c, 0x5fb0, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, + 0x080c, 0x601e, 0x080c, 0x6001, 0x11b8, 0x7084, 0x9005, 0x11a0, + 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x3388, 0x200d, 0x918c, + 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5e56, 0x0180, 0x080c, + 0x4fff, 0x0110, 0x080c, 0x2699, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x5eb3, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x05f0, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, 0x0014, 0x15a8, - 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, + 0x0014, 0x080c, 0x5ed3, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, + 0x05f0, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, 0x0014, 0x15a8, + 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, - 0x0001, 0x080c, 0x6029, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, + 0x0001, 0x080c, 0x6049, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, - 0x080c, 0x6029, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, + 0x080c, 0x6049, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, - 0x0005, 0x080c, 0xa67d, 0x080c, 0x5ffe, 0x20e1, 0x0000, 0x2099, + 0x0005, 0x080c, 0xa68e, 0x080c, 0x601e, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, - 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, 0x5fe1, 0x1150, 0x7084, - 0x9005, 0x1138, 0x080c, 0x5da9, 0x1188, 0x9085, 0x0001, 0x080c, - 0x267d, 0x20a9, 0x0008, 0x080c, 0x5ffe, 0x20e1, 0x0000, 0x2099, + 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, 0x6001, 0x1150, 0x7084, + 0x9005, 0x1138, 0x080c, 0x5dc9, 0x1188, 0x9085, 0x0001, 0x080c, + 0x2699, 0x20a9, 0x0008, 0x080c, 0x601e, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x5eb3, 0x0010, 0x080c, 0x5903, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x01d8, 0x2011, 0x5e89, 0x080c, 0x861d, 0x9086, 0x0084, - 0x1190, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, - 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x6029, 0x709b, + 0x080c, 0x5ed3, 0x0010, 0x080c, 0x5923, 0x0005, 0x00f6, 0x7090, + 0x9005, 0x01d8, 0x2011, 0x5ea9, 0x080c, 0x8651, 0x9086, 0x0084, + 0x1190, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, + 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x6049, 0x709b, 0x0018, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x0019, 0x080c, 0x5f90, 0x2079, 0x0240, 0x7833, 0x1106, - 0x7837, 0x0000, 0x080c, 0x5ffe, 0x2009, 0x026e, 0x2039, 0x1d0e, + 0x709b, 0x0019, 0x080c, 0x5fb0, 0x2079, 0x0240, 0x7833, 0x1106, + 0x7837, 0x0000, 0x080c, 0x601e, 0x2009, 0x026e, 0x2039, 0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, - 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5d12, 0x2039, - 0x1d0e, 0x080c, 0x5fe1, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, + 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5d32, 0x2039, + 0x1d0e, 0x080c, 0x6001, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7060, 0x2310, 0x8214, 0x92a0, 0x1d0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, - 0x1f04, 0x5d45, 0x60c3, 0x0084, 0x080c, 0x5eb3, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x5e89, 0x080c, 0x861d, - 0x9086, 0x0084, 0x1198, 0x080c, 0x5ffe, 0x2079, 0x0260, 0x7a30, + 0x1f04, 0x5d65, 0x60c3, 0x0084, 0x080c, 0x5ed3, 0x00fe, 0x0005, + 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x5ea9, 0x080c, 0x8651, + 0x9086, 0x0084, 0x1198, 0x080c, 0x601e, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, - 0x080c, 0x5f54, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x6029, 0x709b, 0x001b, - 0x080c, 0xa67d, 0x080c, 0x5ffe, 0x2011, 0x0260, 0x2009, 0x0240, + 0x080c, 0x5f74, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, + 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x6049, 0x709b, 0x001b, + 0x080c, 0xa68e, 0x080c, 0x601e, 0x2011, 0x0260, 0x2009, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, - 0x0260, 0x1f04, 0x5d91, 0x60c3, 0x0084, 0x080c, 0x5eb3, 0x0005, + 0x0260, 0x1f04, 0x5db1, 0x60c3, 0x0084, 0x080c, 0x5ed3, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, - 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x5ffe, 0x20e1, + 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x601e, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, - 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5dc3, - 0x0804, 0x5e32, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, - 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5e32, 0x918d, 0xc000, + 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5de3, + 0x0804, 0x5e52, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, + 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5e52, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, - 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5de9, 0x04d8, 0x23a8, - 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5dfb, 0x2328, 0x8529, + 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5e09, 0x04d8, 0x23a8, + 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5e1b, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, - 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5e0a, 0x755e, 0x95c8, - 0x3368, 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, - 0x2508, 0x080c, 0x265d, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, + 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5e2a, 0x755e, 0x95c8, + 0x3388, 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, + 0x2508, 0x080c, 0x2679, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, @@ -2815,53 +2819,53 @@ unsigned short risc_code01[] = { 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, - 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, 0x91a0, 0x3368, 0x242d, + 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, 0x91a0, 0x3388, 0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x265d, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, + 0x2679, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, - 0x5f43, 0x080c, 0x9e16, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, - 0x2a39, 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, - 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x5fa0, 0x001e, + 0x5f63, 0x080c, 0x9e4f, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, + 0x2a59, 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, + 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x5fc0, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, - 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x2998, + 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x29b4, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f3, 0x2013, 0x0000, 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0x9e09, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, + 0x9575, 0x080c, 0x9e42, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, 0x718c, 0x918d, 0x1000, 0x2011, 0x1998, 0x2112, - 0x2009, 0x07d0, 0x2011, 0x5e89, 0x080c, 0x86e7, 0x0005, 0x0016, - 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa888, 0x080c, - 0xab50, 0x080c, 0xa8a4, 0x2009, 0x00f7, 0x080c, 0x5fa0, 0x2061, + 0x2009, 0x07d0, 0x2011, 0x5ea9, 0x080c, 0x871b, 0x0005, 0x0016, + 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xa899, 0x080c, + 0xab61, 0x080c, 0xa8b5, 0x2009, 0x00f7, 0x080c, 0x5fc0, 0x2061, 0x1a02, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, - 0x2009, 0x1998, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5f0f, - 0x080c, 0x8611, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, + 0x2009, 0x1998, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5f2f, + 0x080c, 0x8645, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, 0x080c, - 0x9e16, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, - 0x2a39, 0x080c, 0x74d0, 0x0188, 0x080c, 0x74eb, 0x1170, 0x080c, - 0x77d6, 0x0016, 0x080c, 0x272c, 0x2001, 0x196c, 0x2102, 0x001e, - 0x080c, 0x77d1, 0x080c, 0x73f9, 0x0050, 0x2009, 0x0001, 0x080c, - 0x2a15, 0x2001, 0x0001, 0x080c, 0x25b9, 0x080c, 0x5edf, 0x012e, + 0x9e4f, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, + 0x2a59, 0x080c, 0x74f4, 0x0188, 0x080c, 0x750f, 0x1170, 0x080c, + 0x77f9, 0x0016, 0x080c, 0x2748, 0x2001, 0x196c, 0x2102, 0x001e, + 0x080c, 0x77f4, 0x080c, 0x741d, 0x0050, 0x2009, 0x0001, 0x080c, + 0x2a35, 0x2001, 0x0001, 0x080c, 0x25d5, 0x080c, 0x5eff, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1998, 0x201c, 0x080c, - 0x4b09, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, - 0x20a1, 0x1d80, 0x080c, 0x5ffe, 0x20e9, 0x0000, 0x2099, 0x026e, - 0x0099, 0x20a9, 0x0020, 0x080c, 0x5ff8, 0x2099, 0x0260, 0x20a1, - 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x5ffb, 0x2099, 0x0260, + 0x4b29, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, + 0x20a1, 0x1d80, 0x080c, 0x601e, 0x20e9, 0x0000, 0x2099, 0x026e, + 0x0099, 0x20a9, 0x0020, 0x080c, 0x6018, 0x2099, 0x0260, 0x20a1, + 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x601b, 0x2099, 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, - 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5f78, 0x002e, - 0x001e, 0x0005, 0x080c, 0xa67d, 0x20e1, 0x0001, 0x2099, 0x1d00, + 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5f98, 0x002e, + 0x001e, 0x0005, 0x080c, 0xa68e, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, - 0x080c, 0xa67d, 0x080c, 0x5ffe, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x080c, 0xa68e, 0x080c, 0x601e, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834, 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, - 0x0046, 0x080c, 0x6a66, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, - 0x080c, 0xe2d9, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, - 0x002a, 0x900e, 0x080c, 0x31b4, 0x080c, 0xcf51, 0x0140, 0x0036, - 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4cc0, 0x003e, 0x004e, - 0x001e, 0x0005, 0x080c, 0x5edf, 0x709b, 0x0000, 0x7093, 0x0000, + 0x0046, 0x080c, 0x6a8a, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, + 0x080c, 0xe316, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x900e, 0x080c, 0x31d4, 0x080c, 0xcf84, 0x0140, 0x0036, + 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4ce0, 0x003e, 0x004e, + 0x001e, 0x0005, 0x080c, 0x5eff, 0x709b, 0x0000, 0x7093, 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, @@ -2873,29 +2877,29 @@ unsigned short risc_code01[] = { 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, 0x0001, 0x0005, 0x2001, 0x19a5, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, 0x9006, - 0x200a, 0x8108, 0x1f04, 0x6038, 0x015e, 0x0005, 0x00d6, 0x0036, + 0x200a, 0x8108, 0x1f04, 0x6058, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802, 0xb8d6, - 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x3368, 0x231d, - 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb886, 0x080c, 0xab49, + 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x3388, 0x231d, + 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb886, 0x080c, 0xab5a, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, 0x20a9, 0x0004, 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, 0xb83e, 0xb842, 0xb8ce, 0xb8d2, 0xb85e, 0xb862, 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, 0x0096, 0xb8a4, 0x904d, - 0x0110, 0x080c, 0x106c, 0xb8a7, 0x0000, 0x009e, 0x9006, 0xb84a, + 0x0110, 0x080c, 0x1079, 0xb8a7, 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1ddc, 0x0a0c, 0x0d7d, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d7d, 0x080c, 0x8b72, 0x00ce, - 0x090c, 0x8f16, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff, 0xb842, + 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d7d, 0x080c, 0x8ba9, 0x00ce, + 0x090c, 0x8f4f, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, - 0x6114, 0x9182, 0x0800, 0x1a04, 0x6118, 0x2001, 0x180c, 0x2004, - 0x9084, 0x0003, 0x1904, 0x611e, 0x9188, 0x1000, 0x2104, 0x905d, + 0x6134, 0x9182, 0x0800, 0x1a04, 0x6138, 0x2001, 0x180c, 0x2004, + 0x9084, 0x0003, 0x1904, 0x613e, 0x9188, 0x1000, 0x2104, 0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1188, 0xb8a4, - 0x900d, 0x1904, 0x6130, 0x080c, 0x64e9, 0x9006, 0x012e, 0x0005, + 0x900d, 0x1904, 0x6150, 0x080c, 0x650d, 0x9006, 0x012e, 0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e, 0x0498, - 0x9082, 0x0006, 0x1290, 0x080c, 0xab49, 0x1160, 0xb8a0, 0x9084, + 0x9082, 0x0006, 0x1290, 0x080c, 0xab5a, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0d10, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, @@ -2903,31 +2907,31 @@ unsigned short risc_code01[] = { 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, 0x09a8, - 0x080c, 0x6a6a, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, 0x60d7, - 0x080c, 0x688f, 0x0904, 0x60e0, 0x0804, 0x60db, 0x00e6, 0x2071, + 0x080c, 0x6a8e, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, 0x60f7, + 0x080c, 0x68b3, 0x0904, 0x6100, 0x0804, 0x60fb, 0x00e6, 0x2071, 0x19e6, 0x7004, 0x9086, 0x0002, 0x1128, 0x7030, 0x9080, 0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, 0x1120, 0x2001, 0x196a, 0x205c, 0x0060, 0xa974, 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, - 0x905d, 0x01d0, 0x080c, 0x6a0a, 0x11d0, 0x080c, 0xab89, 0x0570, + 0x905d, 0x01d0, 0x080c, 0x6a2e, 0x11d0, 0x080c, 0xab9a, 0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, 0x0009, 0x602b, 0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, 0x602b, 0x8000, 0x2009, 0x0043, - 0x080c, 0xac7c, 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, + 0x080c, 0xac8d, 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, - 0x0800, 0x1a04, 0x620c, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, - 0x61e4, 0xb8a0, 0x9086, 0x007f, 0x0178, 0x080c, 0x6a72, 0x0160, + 0x0800, 0x1a04, 0x622c, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, + 0x6204, 0xb8a0, 0x9086, 0x007f, 0x0178, 0x080c, 0x6a96, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, - 0x0118, 0x080c, 0x6a6a, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, - 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xc820, 0x002e, - 0x1120, 0x2001, 0x0008, 0x0804, 0x620e, 0x6020, 0x9086, 0x000a, - 0x0120, 0x2001, 0x0008, 0x0804, 0x620e, 0x601a, 0x6003, 0x0008, - 0x2900, 0x6016, 0x0058, 0x080c, 0xab89, 0x05e8, 0x2b00, 0x6012, + 0x0118, 0x080c, 0x6a8e, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, + 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xc853, 0x002e, + 0x1120, 0x2001, 0x0008, 0x0804, 0x622e, 0x6020, 0x9086, 0x000a, + 0x0120, 0x2001, 0x0008, 0x0804, 0x622e, 0x601a, 0x6003, 0x0008, + 0x2900, 0x6016, 0x0058, 0x080c, 0xab9a, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, - 0x080c, 0xac7c, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, - 0x0006, 0x1290, 0x080c, 0xab49, 0x1160, 0xb8a0, 0x9084, 0xff80, + 0x080c, 0xac8d, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, + 0x0006, 0x1290, 0x080c, 0xab5a, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, @@ -2940,2841 +2944,2841 @@ unsigned short risc_code01[] = { 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, - 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x62a3, 0x625e, - 0x6275, 0x62a3, 0x62a3, 0x62a3, 0x62a3, 0x62a3, 0x2100, 0x9082, - 0x007e, 0x1278, 0x080c, 0x65bf, 0x0148, 0x9046, 0xb810, 0x9306, - 0x1904, 0x62ab, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, - 0x0010, 0x080c, 0x49bc, 0x0150, 0x04b0, 0x080c, 0x6620, 0x1598, - 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0xab89, - 0x0530, 0x2b00, 0x6012, 0x080c, 0xcccb, 0x2900, 0x6016, 0x600b, + 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x62c3, 0x627e, + 0x6295, 0x62c3, 0x62c3, 0x62c3, 0x62c3, 0x62c3, 0x2100, 0x9082, + 0x007e, 0x1278, 0x080c, 0x65e3, 0x0148, 0x9046, 0xb810, 0x9306, + 0x1904, 0x62cb, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, + 0x0010, 0x080c, 0x49dc, 0x0150, 0x04b0, 0x080c, 0x6644, 0x1598, + 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0xab9a, + 0x0530, 0x2b00, 0x6012, 0x080c, 0xccfe, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, - 0x31ef, 0x9006, 0x080c, 0x655c, 0x2001, 0x0002, 0x080c, 0x6570, + 0x320f, 0x9006, 0x080c, 0x6580, 0x2001, 0x0002, 0x080c, 0x6594, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, - 0xac7c, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, + 0xac8d, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x6492, 0x90c6, - 0x0056, 0x0904, 0x6496, 0x90c6, 0x0066, 0x0904, 0x649a, 0x90c6, - 0x0067, 0x0904, 0x649e, 0x90c6, 0x0068, 0x0904, 0x64a2, 0x90c6, - 0x0071, 0x0904, 0x64a6, 0x90c6, 0x0074, 0x0904, 0x64aa, 0x90c6, - 0x007c, 0x0904, 0x64ae, 0x90c6, 0x007e, 0x0904, 0x64b2, 0x90c6, - 0x0037, 0x0904, 0x64b6, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, - 0x00ff, 0x0904, 0x648d, 0x9182, 0x0800, 0x1a04, 0x648d, 0x080c, - 0x6620, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, - 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xab49, 0x1904, 0x6476, - 0xb8a0, 0x9084, 0xff80, 0x1904, 0x6476, 0xa894, 0x90c6, 0x006f, - 0x0158, 0x90c6, 0x005e, 0x0904, 0x63d6, 0x90c6, 0x0064, 0x0904, - 0x63ff, 0x2008, 0x0804, 0x6398, 0xa998, 0xa8b0, 0x2040, 0x080c, - 0xab49, 0x1120, 0x9182, 0x007f, 0x0a04, 0x6398, 0x9186, 0x00ff, - 0x0904, 0x6398, 0x9182, 0x0800, 0x1a04, 0x6398, 0xaaa0, 0xab9c, - 0x787c, 0x9306, 0x1188, 0x7880, 0x0096, 0x924e, 0x1128, 0x2208, - 0x2310, 0x009e, 0x0804, 0x6398, 0x99cc, 0xff00, 0x009e, 0x1120, - 0x2208, 0x2310, 0x0804, 0x6398, 0x080c, 0x49bc, 0x0904, 0x63a2, - 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, 0x6913, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fb7, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fb7, 0xa8c4, 0xabc8, - 0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, - 0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, - 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, - 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, - 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, - 0x0478, 0x000e, 0x080c, 0xab89, 0x1130, 0x2001, 0x4005, 0x2009, - 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, 0x080c, 0xcccb, 0x2900, - 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x31ef, 0x012e, 0x9006, 0x080c, - 0x655c, 0x2001, 0x0002, 0x080c, 0x6570, 0x2009, 0x0002, 0x080c, - 0xac7c, 0xa8b0, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x9006, - 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x56e9, - 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x6620, - 0x1904, 0x6393, 0x9186, 0x007f, 0x0130, 0x080c, 0x6a6a, 0x0118, - 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x103a, 0x1120, 0x009e, - 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xca1e, - 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x639a, 0xa998, - 0xaeb0, 0x080c, 0x6620, 0x1904, 0x6393, 0x0096, 0x080c, 0x103a, - 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x6453, 0x2900, 0x009e, - 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, - 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, - 0x2398, 0x080c, 0x0fb7, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x56d5, 0xd0b4, 0x1118, - 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, - 0x00b0, 0x080c, 0x6a6a, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, - 0x56e9, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xca01, 0x1904, - 0x63cf, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x639a, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1289, 0x080c, - 0xb103, 0x1904, 0x63cf, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, - 0x900e, 0x0804, 0x63d0, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, - 0x2001, 0x0029, 0x900e, 0x0804, 0x63d0, 0x2001, 0x0029, 0x900e, - 0x0804, 0x63d0, 0x080c, 0x3796, 0x0804, 0x63d1, 0x080c, 0x540a, - 0x0804, 0x63d1, 0x080c, 0x4572, 0x0804, 0x63d1, 0x080c, 0x45eb, - 0x0804, 0x63d1, 0x080c, 0x4647, 0x0804, 0x63d1, 0x080c, 0x4a7f, - 0x0804, 0x63d1, 0x080c, 0x4d2f, 0x0804, 0x63d1, 0x080c, 0x5075, - 0x0804, 0x63d1, 0x080c, 0x526e, 0x0804, 0x63d1, 0x080c, 0x39b4, - 0x0804, 0x63d1, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x1608, 0x9182, 0x0800, 0x1258, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0130, 0x080c, 0x6a6a, 0x1138, 0x00d9, 0x9006, 0x00b0, - 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, - 0xd1fc, 0x0d98, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, - 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, - 0x0005, 0xa877, 0x0000, 0xb8d0, 0x9005, 0x1904, 0x6550, 0xb888, - 0x9005, 0x1904, 0x6550, 0xb838, 0xb93c, 0x9102, 0x1a04, 0x6550, - 0x2b10, 0x080c, 0xabb6, 0x0904, 0x654c, 0x8108, 0xb93e, 0x6212, - 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, - 0xa878, 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, - 0xa87c, 0xd0ac, 0x0588, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1530, - 0xa816, 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x11f8, 0x9084, - 0x00ff, 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, - 0x000f, 0x8001, 0x1df0, 0x2001, 0x8004, 0x6003, 0x0004, 0x6046, - 0x00f6, 0x2079, 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0010, - 0x2c00, 0x7836, 0x781b, 0x8080, 0x00fe, 0x0005, 0x080c, 0x173e, - 0x601c, 0xc0bd, 0x601e, 0x0c38, 0xd0b4, 0x190c, 0x1c3d, 0x2001, - 0x8004, 0x6003, 0x0002, 0x0c18, 0x81ff, 0x1110, 0xb88b, 0x0001, - 0x2908, 0xb8cc, 0xb9ce, 0x9005, 0x1110, 0xb9d2, 0x0020, 0x0096, - 0x2048, 0xa902, 0x009e, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, - 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, - 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, - 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, - 0x6a66, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, - 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, - 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0d7d, 0x000e, + 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x64b6, 0x90c6, + 0x0056, 0x0904, 0x64ba, 0x90c6, 0x0066, 0x0904, 0x64be, 0x90c6, + 0x0067, 0x0904, 0x64c2, 0x90c6, 0x0068, 0x0904, 0x64c6, 0x90c6, + 0x0071, 0x0904, 0x64ca, 0x90c6, 0x0074, 0x0904, 0x64ce, 0x90c6, + 0x007c, 0x0904, 0x64d2, 0x90c6, 0x007e, 0x0904, 0x64d6, 0x90c6, + 0x0037, 0x0904, 0x64da, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, + 0x00ff, 0x0904, 0x64b1, 0x9182, 0x0800, 0x1a04, 0x64b1, 0x080c, + 0x6644, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, + 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xab5a, 0x1904, 0x649a, + 0xb8a0, 0x9084, 0xff80, 0x1904, 0x649a, 0xa894, 0x90c6, 0x006f, + 0x0158, 0x90c6, 0x005e, 0x0904, 0x63fa, 0x90c6, 0x0064, 0x0904, + 0x6423, 0x2008, 0x0804, 0x63bc, 0xa998, 0xa8b0, 0x2040, 0x080c, + 0xab5a, 0x1120, 0x9182, 0x007f, 0x0a04, 0x63bc, 0x9186, 0x00ff, + 0x0904, 0x63bc, 0x9182, 0x0800, 0x1a04, 0x63bc, 0xaaa0, 0xab9c, + 0x787c, 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, 0x1128, 0x2208, + 0x2310, 0x009e, 0x0804, 0x63bc, 0x080c, 0xab5a, 0x1140, 0x99cc, + 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x63bc, 0x009e, + 0x080c, 0x49dc, 0x0904, 0x63c6, 0x900e, 0x9016, 0x90c6, 0x4000, + 0x15e0, 0x0006, 0x080c, 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, + 0x080c, 0x0fc4, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0035, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, + 0x080c, 0x0fc4, 0xa8c4, 0xabc8, 0x9305, 0xabcc, 0x9305, 0xabd0, + 0x9305, 0xabd4, 0x9305, 0xabd8, 0x9305, 0xabdc, 0x9305, 0xabe0, + 0x9305, 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, + 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, + 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, + 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, + 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c, 0xab9a, + 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, 0x2b00, + 0x6012, 0x080c, 0xccfe, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, + 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x320f, 0x012e, 0x9006, 0x080c, 0x6580, 0x2001, 0x0002, 0x080c, + 0x6594, 0x2009, 0x0002, 0x080c, 0xac8d, 0xa8b0, 0xd094, 0x0118, + 0xb8d4, 0xc08d, 0xb8d6, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, + 0x00be, 0x0005, 0x080c, 0x5709, 0x0118, 0x2009, 0x0007, 0x00f8, + 0xa998, 0xaeb0, 0x080c, 0x6644, 0x1904, 0x63b7, 0x9186, 0x007f, + 0x0130, 0x080c, 0x6a8e, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, + 0x080c, 0x1047, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, + 0x009e, 0xa806, 0x080c, 0xca51, 0x19b0, 0x2009, 0x0003, 0x2001, + 0x4005, 0x0804, 0x63be, 0xa998, 0xaeb0, 0x080c, 0x6644, 0x1904, + 0x63b7, 0x0096, 0x080c, 0x1047, 0x1128, 0x009e, 0x2009, 0x0002, + 0x0804, 0x6477, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, + 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, + 0x20a0, 0xbbc8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0fc4, 0x009e, + 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, + 0x080c, 0x56f5, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, + 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6a8e, 0x0118, + 0xa89b, 0x0009, 0x0080, 0x080c, 0x5709, 0x0118, 0xa89b, 0x0007, + 0x0050, 0x080c, 0xca34, 0x1904, 0x63f3, 0x2009, 0x0003, 0x2001, + 0x4005, 0x0804, 0x63be, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, + 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, + 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, + 0x0000, 0x2041, 0x1296, 0x080c, 0xb114, 0x1904, 0x63f3, 0x2009, + 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x63f4, 0x2009, + 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, + 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, + 0x63f4, 0x2001, 0x0029, 0x900e, 0x0804, 0x63f4, 0x080c, 0x37b6, + 0x0804, 0x63f5, 0x080c, 0x542a, 0x0804, 0x63f5, 0x080c, 0x4592, + 0x0804, 0x63f5, 0x080c, 0x460b, 0x0804, 0x63f5, 0x080c, 0x4667, + 0x0804, 0x63f5, 0x080c, 0x4a9f, 0x0804, 0x63f5, 0x080c, 0x4d4f, + 0x0804, 0x63f5, 0x080c, 0x5095, 0x0804, 0x63f5, 0x080c, 0x528e, + 0x0804, 0x63f5, 0x080c, 0x39d4, 0x0804, 0x63f5, 0x00b6, 0xa974, + 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1608, 0x9182, 0x0800, + 0x1258, 0x9188, 0x1000, 0x2104, 0x905d, 0x0130, 0x080c, 0x6a8e, + 0x1138, 0x00d9, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, + 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d98, 0x2001, 0x0029, + 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, + 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, 0xa877, 0x0000, 0xb8d0, + 0x9005, 0x1904, 0x6574, 0xb888, 0x9005, 0x1904, 0x6574, 0xb838, + 0xb93c, 0x9102, 0x1a04, 0x6574, 0x2b10, 0x080c, 0xabc7, 0x0904, + 0x6570, 0x8108, 0xb93e, 0x6212, 0x2900, 0x6016, 0x6023, 0x0003, + 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, 0x605e, 0xa880, 0x9084, + 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, 0x0588, 0xc0dd, + 0xa87e, 0xa888, 0x8001, 0x1530, 0xa816, 0xa864, 0x9094, 0x00f7, + 0x9296, 0x0011, 0x11f8, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, + 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x000f, 0x8001, 0x1df0, 0x2001, + 0x8004, 0x6003, 0x0004, 0x6046, 0x00f6, 0x2079, 0x0380, 0x7818, + 0xd0bc, 0x1de8, 0x7833, 0x0010, 0x2c00, 0x7836, 0x781b, 0x8080, + 0x00fe, 0x0005, 0x080c, 0x174b, 0x601c, 0xc0bd, 0x601e, 0x0c38, + 0xd0b4, 0x190c, 0x1c55, 0x2001, 0x8004, 0x6003, 0x0002, 0x0c18, + 0x81ff, 0x1110, 0xb88b, 0x0001, 0x2908, 0xb8cc, 0xb9ce, 0x9005, + 0x1110, 0xb9d2, 0x0020, 0x0096, 0x2048, 0xa902, 0x009e, 0x0005, + 0x00b6, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, + 0xba00, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, - 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6a62, 0x1138, 0x9284, 0x00ff, - 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, - 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, - 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, - 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, 0x103a, 0x2958, - 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, 0xb860, 0xb8c6, - 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x603e, 0x9006, 0x0010, 0x9085, - 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, - 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, - 0xb8a4, 0x904d, 0x0110, 0x080c, 0x106c, 0x00d6, 0x00c6, 0xb8bc, - 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, - 0xc832, 0x0110, 0x080c, 0x0fec, 0x080c, 0xabdf, 0x00ce, 0x0c88, - 0x00ce, 0x00de, 0x2b48, 0xb8c8, 0xb85e, 0xb8c4, 0xb862, 0x080c, - 0x107c, 0x00de, 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, - 0x0016, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, - 0x1000, 0x2104, 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, - 0x0156, 0x0136, 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, - 0xb802, 0x080c, 0x74c8, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, - 0x080c, 0xab49, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, - 0x2061, 0x1981, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, - 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, - 0x2001, 0x0001, 0x6886, 0x2069, 0x1800, 0x68b6, 0x7040, 0xb85e, - 0x7048, 0xb862, 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, - 0xb8c4, 0x20e8, 0xb8c8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, - 0x4003, 0x2099, 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, - 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, - 0xb96e, 0x7048, 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, - 0x0000, 0xb8a0, 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, - 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, - 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, - 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, - 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, - 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, - 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, - 0x7034, 0xb896, 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbd4, - 0xc384, 0xba00, 0x2009, 0x1867, 0x210c, 0xd0bc, 0x0120, 0xd1ec, - 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, - 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, - 0xba02, 0xbbd6, 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, - 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, - 0x15c0, 0xaa04, 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, - 0x01d6, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, - 0xffc0, 0x9080, 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, - 0x4002, 0x9086, 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0d7d, - 0x3c00, 0x20e8, 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x0060, 0x080c, 0x103a, 0x0170, - 0x2900, 0xb8a6, 0xa803, 0x0000, 0x080c, 0x68af, 0xa807, 0x0001, - 0xae12, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, - 0x0126, 0x2091, 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, - 0x9005, 0x1150, 0x080c, 0x68be, 0x1158, 0xa804, 0x908a, 0x0002, - 0x0218, 0x8001, 0xa806, 0x0020, 0x080c, 0x106c, 0xb8a7, 0x0000, - 0x009e, 0x012e, 0x0005, 0x0096, 0x00c6, 0xb888, 0x9005, 0x1904, - 0x67a4, 0xb8d0, 0x904d, 0x0904, 0x67a4, 0x080c, 0xabb6, 0x0904, - 0x67a0, 0x8210, 0xba3e, 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, - 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, - 0x6007, 0x0040, 0xa878, 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, - 0xa883, 0x0000, 0xa87c, 0xd0ac, 0x01c8, 0xc0dd, 0xa87e, 0xa888, - 0x8001, 0x1568, 0xa816, 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, - 0x1530, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, - 0xaa3a, 0x2001, 0x8004, 0x6003, 0x0004, 0x0030, 0x080c, 0x1c3d, - 0x2001, 0x8004, 0x6003, 0x0002, 0x6046, 0x2001, 0x0010, 0x2c08, - 0x080c, 0xa879, 0xb838, 0xba3c, 0x9202, 0x0a04, 0x6751, 0x0020, - 0x82ff, 0x1110, 0xb88b, 0x0001, 0x00ce, 0x009e, 0x0005, 0x080c, - 0x173e, 0x601c, 0xc0bd, 0x601e, 0x08e0, 0x00b6, 0x0096, 0x0016, - 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c, 0x6620, 0x1158, 0xb8d0, - 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002, 0x1118, 0xb800, 0xd0bc, - 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04, 0x67b3, 0x001e, 0x00be, - 0x009e, 0x0005, 0x0096, 0x0016, 0xb8d0, 0x904d, 0x0188, 0xa800, - 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x9006, 0xa802, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0xcb35, 0x080c, 0x6d7b, 0x0c60, - 0x001e, 0x009e, 0x0005, 0x0086, 0x9046, 0xb8d0, 0x904d, 0x01b0, - 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0128, 0x2940, 0xa800, - 0x904d, 0x0160, 0x0ca8, 0xa800, 0x88ff, 0x1128, 0xb8d2, 0x9005, - 0x1118, 0xb8ce, 0x0008, 0xa002, 0xa803, 0x0000, 0x008e, 0x0005, - 0x901e, 0x0010, 0x2019, 0x0001, 0x0126, 0x2091, 0x8000, 0x00e6, - 0x0096, 0x00c6, 0x0086, 0x0026, 0x2071, 0x19e6, 0x9046, 0x7028, - 0x9065, 0x01e8, 0x6014, 0x2068, 0x83ff, 0x0120, 0x605c, 0x9606, - 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0120, - 0x2c40, 0x600c, 0x2060, 0x0c60, 0x600c, 0x0006, 0x0066, 0x2830, - 0x080c, 0x9f84, 0x006e, 0x000e, 0x83ff, 0x0508, 0x0c08, 0x9046, - 0xb8d0, 0x904d, 0x01e0, 0x83ff, 0x0120, 0xa878, 0x9606, 0x0158, - 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0120, 0x2940, - 0xa800, 0x2048, 0x0c70, 0xb8d0, 0xaa00, 0x0026, 0x9906, 0x1110, - 0xbad2, 0x0008, 0xa202, 0x000e, 0x83ff, 0x0108, 0x0c10, 0x002e, - 0x008e, 0x00ce, 0x009e, 0x00ee, 0x012e, 0x0005, 0x9016, 0x0489, - 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x6913, 0x0128, 0x080c, - 0xc8f3, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6913, 0x0128, - 0x080c, 0xc894, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6913, - 0x0128, 0x080c, 0xc8f0, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x6913, 0x0128, 0x080c, 0xc8b3, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6913, 0x0128, 0x080c, 0xc934, 0x0010, 0x9085, 0x0001, - 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, 0x0136, - 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, - 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, - 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, - 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0146, - 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0004, 0x20a0, 0x20a9, - 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, 0x014e, 0x0136, 0x01c6, - 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, - 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, - 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, - 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, 0x8001, 0x20a0, 0x3c00, - 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, 0x014e, 0x9006, 0x01ce, - 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, - 0x1128, 0x080c, 0x103a, 0x0168, 0x2900, 0xb8a6, 0x080c, 0x68af, - 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, 0x009e, - 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x106c, 0x9085, 0x0001, - 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, 0x00f6, - 0x080c, 0x74c8, 0x01b0, 0x71c4, 0x81ff, 0x1198, 0x71dc, 0xd19c, - 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d, 0x0148, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, - 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x01d0, 0x0156, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x6620, 0x1168, 0xb804, 0x9084, - 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, - 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x693a, 0x015e, - 0x080c, 0x6a28, 0x0120, 0x2001, 0x1984, 0x200c, 0x0038, 0x2079, - 0x1847, 0x7804, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x6965, - 0x080c, 0x86e7, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, 0x6965, - 0x080c, 0x861d, 0x080c, 0x6a28, 0x01d8, 0x2001, 0x107e, 0x2004, - 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6a66, 0x0130, 0x2009, - 0x07d0, 0x2011, 0x6965, 0x080c, 0x86e7, 0x00e6, 0x2071, 0x1800, - 0x9006, 0x707e, 0x7060, 0x7082, 0x080c, 0x2fc0, 0x00ee, 0x04d0, - 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6620, - 0x1558, 0xb800, 0xd0ec, 0x0540, 0x0046, 0xbaa0, 0x2220, 0x9006, - 0x2009, 0x0029, 0x080c, 0xe2d9, 0xb800, 0xc0e5, 0xc0ec, 0xb802, - 0x080c, 0x6a62, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, - 0x9085, 0x0700, 0xb806, 0x080c, 0xa888, 0x2019, 0x0029, 0x080c, - 0x938d, 0x0076, 0x903e, 0x080c, 0x9256, 0x900e, 0x080c, 0xdffb, - 0x007e, 0x004e, 0x080c, 0xa8a4, 0x001e, 0x8108, 0x1f04, 0x698d, - 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, - 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, - 0x1053, 0x090c, 0x0d7d, 0x2958, 0x009e, 0x2001, 0x196a, 0x2b02, - 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, - 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x603e, 0xb807, - 0x0006, 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, 0xb86c, - 0xb893, 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, 0x0000, - 0x00ce, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, - 0xd0bc, 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, 0x00ff, - 0x9196, 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, - 0x0158, 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, - 0x0004, 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, - 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, - 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, - 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0d7d, - 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, - 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, 0x0138, - 0x2001, 0x1982, 0x200c, 0x2011, 0x6a58, 0x080c, 0x86e7, 0x0005, - 0x2011, 0x6a58, 0x080c, 0x861d, 0x2011, 0x1837, 0x2204, 0xc0cc, - 0x2012, 0x0005, 0x080c, 0x56d5, 0xd0ac, 0x0005, 0x080c, 0x56d5, - 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, - 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, - 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xcf51, 0x0158, - 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, - 0x0110, 0xb8d4, 0xd094, 0x00fe, 0x00be, 0x0005, 0x2071, 0x1910, - 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, - 0x701e, 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1947, - 0x900e, 0x710a, 0x080c, 0x56d5, 0xd0fc, 0x1140, 0x080c, 0x56d5, - 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x00f8, 0x2001, 0x1867, - 0x200c, 0x9184, 0x0007, 0x0002, 0x6aa6, 0x6aa6, 0x6aa6, 0x6aa6, - 0x6aa6, 0x6abc, 0x6aca, 0x6aa6, 0x7003, 0x0003, 0x2009, 0x1868, - 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, - 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, 0x0005, - 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, - 0x1910, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, - 0x6844, 0x9005, 0x0158, 0x080c, 0x783e, 0x6a60, 0x9200, 0x7002, - 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, - 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, - 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, - 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, - 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, - 0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1947, 0x7000, - 0x9015, 0x0904, 0x6d80, 0x9286, 0x0003, 0x0904, 0x6c10, 0x9286, - 0x0005, 0x0904, 0x6c10, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, - 0x6b71, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6d80, 0xa878, 0xd084, - 0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, - 0x701c, 0x9005, 0x1904, 0x6f17, 0x0e04, 0x6f85, 0x2071, 0x0000, - 0xa850, 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, - 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, - 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, - 0x01de, 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e1, 0x0804, 0x6bf3, 0xa853, 0x001b, 0x2001, 0x8027, - 0x0820, 0x7004, 0xd08c, 0x1904, 0x6d80, 0xa853, 0x001a, 0x2001, - 0x8024, 0x0804, 0x6b35, 0x00e6, 0x0026, 0x2071, 0x1947, 0x7000, - 0x9015, 0x0904, 0x6d80, 0x9286, 0x0003, 0x0904, 0x6c10, 0x9286, - 0x0005, 0x0904, 0x6c10, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, - 0x6bd8, 0xa868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, 0x2001, 0x1947, - 0x2004, 0x9005, 0x0904, 0x6d80, 0xa87c, 0xd0bc, 0x1904, 0x6d80, - 0xa978, 0xa874, 0x9105, 0x1904, 0x6d80, 0x2001, 0x1947, 0x2004, - 0x0002, 0x6d80, 0x6bd4, 0x6c10, 0x6c10, 0x6d80, 0x6c10, 0x0005, - 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, 0x1947, 0x210c, - 0x81ff, 0x0904, 0x6d80, 0xa87c, 0xd0cc, 0x0904, 0x6d80, 0xa880, - 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6d80, 0x9186, 0x0003, - 0x0904, 0x6c10, 0x9186, 0x0005, 0x0904, 0x6c10, 0xa84f, 0x8021, - 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, - 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, 0x6f17, 0x0e04, 0x6f85, - 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, - 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11e1, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, - 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8532, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, - 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, - 0x0000, 0x7010, 0x9005, 0x1904, 0x6d05, 0x782c, 0x908c, 0x0780, - 0x190c, 0x70d1, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, - 0x6c2e, 0x6d05, 0x6c53, 0x6ca0, 0x080c, 0x0d7d, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1170, 0x2071, 0x1a02, 0x703c, + 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, + 0xb89c, 0xd0ac, 0x0158, 0x080c, 0x6a8a, 0x0140, 0x9284, 0xff00, + 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, + 0xff00, 0x9215, 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, + 0x82ff, 0x090c, 0x0d7d, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, + 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, + 0x0006, 0x9086, 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, + 0x6a86, 0x1138, 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, + 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, + 0x012e, 0x00be, 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, + 0x0005, 0x00d6, 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, + 0x0096, 0x080c, 0x1047, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, + 0xb85c, 0xb8ca, 0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, + 0x605e, 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, + 0x00b6, 0x0096, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, + 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, + 0x905d, 0x0518, 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, + 0x1079, 0x00d6, 0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, + 0x0006, 0x6014, 0x2048, 0x080c, 0xc865, 0x0110, 0x080c, 0x0ff9, + 0x080c, 0xabf0, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x2b48, 0xb8c8, + 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x1089, 0x00de, 0x9006, 0x002e, + 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, + 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, + 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, + 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x74ec, 0x1510, + 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xab5a, 0x11d8, 0x0078, + 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1981, 0x7048, 0x2062, + 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, + 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, + 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, + 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088, + 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, + 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, + 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, + 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, + 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, + 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, + 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, + 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, + 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, + 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, + 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, + 0x7054, 0xb89e, 0x0036, 0xbbd4, 0xc384, 0xba00, 0x2009, 0x1867, + 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, + 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, + 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbd6, 0x003e, 0x00ee, + 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, + 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, + 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, + 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, + 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, + 0x8109, 0x1dd0, 0x080c, 0x0d7d, 0x3c00, 0x20e8, 0x3300, 0x8001, + 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, + 0x0060, 0x080c, 0x1047, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, + 0x080c, 0x68d3, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, + 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, + 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x68e2, + 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, + 0x080c, 0x1079, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096, + 0x00c6, 0xb888, 0x9005, 0x1904, 0x67c8, 0xb8d0, 0x904d, 0x0904, + 0x67c8, 0x080c, 0xabc7, 0x0904, 0x67c4, 0x8210, 0xba3e, 0xa800, + 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x2b00, 0x6012, 0x2900, 0x6016, + 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, 0x605e, + 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, + 0x01c8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1568, 0xa816, 0xa864, + 0x9094, 0x00f7, 0x9296, 0x0011, 0x1530, 0x9084, 0x00ff, 0xc0bd, + 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x8004, 0x6003, + 0x0004, 0x0030, 0x080c, 0x1c55, 0x2001, 0x8004, 0x6003, 0x0002, + 0x6046, 0x2001, 0x0010, 0x2c08, 0x080c, 0xa88a, 0xb838, 0xba3c, + 0x9202, 0x0a04, 0x6775, 0x0020, 0x82ff, 0x1110, 0xb88b, 0x0001, + 0x00ce, 0x009e, 0x0005, 0x080c, 0x174b, 0x601c, 0xc0bd, 0x601e, + 0x08e0, 0x00b6, 0x0096, 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, + 0x080c, 0x6644, 0x1158, 0xb8d0, 0x904d, 0x0140, 0x3e00, 0x9086, + 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, + 0x1f04, 0x67d7, 0x001e, 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, + 0xb8d0, 0x904d, 0x0188, 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, + 0x9006, 0xa802, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0xcb68, 0x080c, 0x6d9f, 0x0c60, 0x001e, 0x009e, 0x0005, 0x0086, + 0x9046, 0xb8d0, 0x904d, 0x01b0, 0xa86c, 0x9406, 0x1118, 0xa870, + 0x9506, 0x0128, 0x2940, 0xa800, 0x904d, 0x0160, 0x0ca8, 0xa800, + 0x88ff, 0x1128, 0xb8d2, 0x9005, 0x1118, 0xb8ce, 0x0008, 0xa002, + 0xa803, 0x0000, 0x008e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, + 0x0126, 0x2091, 0x8000, 0x00e6, 0x0096, 0x00c6, 0x0086, 0x0026, + 0x2071, 0x19e6, 0x9046, 0x7028, 0x9065, 0x01e8, 0x6014, 0x2068, + 0x83ff, 0x0120, 0x605c, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, + 0x1118, 0xa870, 0x9506, 0x0120, 0x2c40, 0x600c, 0x2060, 0x0c60, + 0x600c, 0x0006, 0x0066, 0x2830, 0x080c, 0x9fbd, 0x006e, 0x000e, + 0x83ff, 0x0508, 0x0c08, 0x9046, 0xb8d0, 0x904d, 0x01e0, 0x83ff, + 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, + 0xa870, 0x9506, 0x0120, 0x2940, 0xa800, 0x2048, 0x0c70, 0xb8d0, + 0xaa00, 0x0026, 0x9906, 0x1110, 0xbad2, 0x0008, 0xa202, 0x000e, + 0x83ff, 0x0108, 0x0c10, 0x002e, 0x008e, 0x00ce, 0x009e, 0x00ee, + 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, + 0x080c, 0x6937, 0x0128, 0x080c, 0xc926, 0x0010, 0x9085, 0x0001, + 0x0005, 0x080c, 0x6937, 0x0128, 0x080c, 0xc8c7, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x6937, 0x0128, 0x080c, 0xc923, 0x0010, + 0x9085, 0x0001, 0x0005, 0x080c, 0x6937, 0x0128, 0x080c, 0xc8e6, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6937, 0x0128, 0x080c, + 0xc967, 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, + 0x9085, 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, + 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, + 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, + 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, + 0x01ce, 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, + 0x01de, 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, + 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, + 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, + 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, + 0x3300, 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, + 0x01de, 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, + 0x2091, 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x1047, 0x0168, + 0x2900, 0xb8a6, 0x080c, 0x68d3, 0xa803, 0x0001, 0xa807, 0x0000, + 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, + 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, + 0x080c, 0x1079, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, + 0xd0a4, 0x0005, 0x00b6, 0x00f6, 0x080c, 0x74ec, 0x01b0, 0x71c4, + 0x81ff, 0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, + 0x1000, 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, + 0xd0a4, 0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, + 0x6644, 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, + 0x0118, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, + 0x8108, 0x1f04, 0x695e, 0x015e, 0x080c, 0x6a4c, 0x0120, 0x2001, + 0x1984, 0x200c, 0x0038, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0130, + 0x2009, 0x07d0, 0x2011, 0x6989, 0x080c, 0x871b, 0x00fe, 0x00be, + 0x0005, 0x00b6, 0x2011, 0x6989, 0x080c, 0x8651, 0x080c, 0x6a4c, + 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, + 0x080c, 0x6a8a, 0x0130, 0x2009, 0x07d0, 0x2011, 0x6989, 0x080c, + 0x871b, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, 0x7082, + 0x080c, 0x2fe0, 0x00ee, 0x04d0, 0x0156, 0x00c6, 0x20a9, 0x007f, + 0x900e, 0x0016, 0x080c, 0x6644, 0x1558, 0xb800, 0xd0ec, 0x0540, + 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, 0xe316, + 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6a86, 0x2001, 0x0707, + 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, 0x080c, + 0xa899, 0x2019, 0x0029, 0x080c, 0x93c6, 0x0076, 0x903e, 0x080c, + 0x928f, 0x900e, 0x080c, 0xe038, 0x007e, 0x004e, 0x080c, 0xa8b5, + 0x001e, 0x8108, 0x1f04, 0x69b1, 0x00ce, 0x015e, 0x00be, 0x0005, + 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, + 0x00b6, 0x00c6, 0x0096, 0x080c, 0x1060, 0x090c, 0x0d7d, 0x2958, + 0x009e, 0x2001, 0x196a, 0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, + 0x003f, 0xb9c6, 0x908c, 0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, + 0x00ff, 0x080c, 0x605e, 0xb807, 0x0006, 0xb813, 0x00ff, 0xb817, + 0xffff, 0xb86f, 0x0200, 0xb86c, 0xb893, 0x0002, 0xb8bb, 0x0520, + 0xb8a3, 0x00ff, 0xb8af, 0x0000, 0x00ce, 0x00be, 0x0005, 0x7810, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, + 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, 0x0005, 0x0006, 0x0016, + 0x0026, 0xb804, 0x908c, 0x00ff, 0x9196, 0x0006, 0x0188, 0x9196, + 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, 0x908c, 0xff00, 0x810f, + 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, 0x0110, 0x9196, 0x0005, + 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, + 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, + 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, + 0x2204, 0x9b06, 0x190c, 0x0d7d, 0x000e, 0xba00, 0x9005, 0x0110, + 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, + 0x1837, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x1982, 0x200c, 0x2011, + 0x6a7c, 0x080c, 0x871b, 0x0005, 0x2011, 0x6a7c, 0x080c, 0x8651, + 0x2011, 0x1837, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x080c, 0x56f5, + 0xd0ac, 0x0005, 0x080c, 0x56f5, 0xd0a4, 0x0005, 0x0016, 0xb904, + 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, + 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, + 0x00f6, 0x080c, 0xcf84, 0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, + 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, 0xb8d4, 0xd094, 0x00fe, + 0x00be, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, 0x7007, 0x0000, + 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x0005, + 0x0016, 0x00e6, 0x2071, 0x1947, 0x900e, 0x710a, 0x080c, 0x56f5, + 0xd0fc, 0x1140, 0x080c, 0x56f5, 0x900e, 0xd09c, 0x0108, 0x8108, + 0x7102, 0x00f8, 0x2001, 0x1867, 0x200c, 0x9184, 0x0007, 0x0002, + 0x6aca, 0x6aca, 0x6aca, 0x6aca, 0x6aca, 0x6ae0, 0x6aee, 0x6aca, + 0x7003, 0x0003, 0x2009, 0x1868, 0x210c, 0x9184, 0xff00, 0x8007, + 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, + 0x0c88, 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, + 0x9005, 0x1150, 0x00e6, 0x2071, 0x1910, 0x7028, 0xc085, 0x702a, + 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, + 0x7861, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, + 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, + 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, + 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, + 0x0001, 0x00e6, 0x2071, 0x1910, 0x7028, 0xc084, 0x702a, 0x7007, + 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee, 0x0005, 0x00e6, + 0x0026, 0x2071, 0x1947, 0x7000, 0x9015, 0x0904, 0x6da4, 0x9286, + 0x0003, 0x0904, 0x6c34, 0x9286, 0x0005, 0x0904, 0x6c34, 0x2071, + 0x1877, 0xa87c, 0x9005, 0x0904, 0x6b95, 0x7140, 0xa868, 0x9102, + 0x0a04, 0x6da4, 0xa878, 0xd084, 0x15d8, 0xa853, 0x0019, 0x2001, + 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, 0x9005, 0x1904, 0x6f3b, + 0x0e04, 0x6fa9, 0x2071, 0x0000, 0xa850, 0x7032, 0xa84c, 0x7082, + 0xa870, 0x7086, 0xa86c, 0x708a, 0xa880, 0x708e, 0x7036, 0x0146, + 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, + 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, + 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, 0x0804, 0x6c17, + 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, 0x7004, 0xd08c, 0x1904, + 0x6da4, 0xa853, 0x001a, 0x2001, 0x8024, 0x0804, 0x6b59, 0x00e6, + 0x0026, 0x2071, 0x1947, 0x7000, 0x9015, 0x0904, 0x6da4, 0x9286, + 0x0003, 0x0904, 0x6c34, 0x9286, 0x0005, 0x0904, 0x6c34, 0xa84f, + 0x8022, 0xa853, 0x0018, 0x0804, 0x6bfc, 0xa868, 0xd0fc, 0x11d8, + 0x00e6, 0x0026, 0x2001, 0x1947, 0x2004, 0x9005, 0x0904, 0x6da4, + 0xa87c, 0xd0bc, 0x1904, 0x6da4, 0xa978, 0xa874, 0x9105, 0x1904, + 0x6da4, 0x2001, 0x1947, 0x2004, 0x0002, 0x6da4, 0x6bf8, 0x6c34, + 0x6c34, 0x6da4, 0x6c34, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, + 0x0026, 0x2009, 0x1947, 0x210c, 0x81ff, 0x0904, 0x6da4, 0xa87c, + 0xd0cc, 0x0904, 0x6da4, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, + 0x1904, 0x6da4, 0x9186, 0x0003, 0x0904, 0x6c34, 0x9186, 0x0005, + 0x0904, 0x6c34, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, + 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, 0x701c, 0x9005, + 0x1904, 0x6f3b, 0x0e04, 0x6fa9, 0x2071, 0x0000, 0xa84c, 0x7082, + 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, 0x2071, + 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, + 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, 0x002e, + 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, + 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, + 0x6d29, 0x782c, 0x908c, 0x0780, 0x190c, 0x70f5, 0x8004, 0x8004, + 0x8004, 0x9084, 0x0003, 0x0002, 0x6c52, 0x6d29, 0x6c77, 0x6cc4, + 0x080c, 0x0d7d, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, + 0x1170, 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, + 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, + 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, 0x0c10, 0x2071, + 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x15a8, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, + 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, + 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, + 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, 0x782c, 0x9094, + 0x0780, 0x190c, 0x70f5, 0xd0a4, 0x19c8, 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, - 0x080c, 0x8532, 0x0c10, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, - 0x900d, 0x15a8, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, - 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8532, 0x782c, 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, - 0x19c8, 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, - 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8532, 0x0804, 0x6c5a, - 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x1d60, 0x00ee, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd09c, 0x11a0, 0x009e, 0x2900, - 0x7822, 0xa804, 0x900d, 0x1560, 0x2071, 0x1a02, 0x703c, 0x9005, - 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1170, 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, - 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8532, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1904, 0x6d5a, 0x782c, 0x9094, 0x0780, - 0x190c, 0x70d1, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x70d1, 0xd09c, 0x0d68, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x01b0, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, 0x9094, 0x0780, 0x190c, - 0x70d1, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x1a02, 0x703c, 0x9005, - 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8532, 0x00ee, 0x0804, 0x6d15, 0xa868, - 0xd0fc, 0x1560, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, - 0x0fec, 0x009e, 0x0018, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, - 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, - 0x0000, 0x7010, 0x9005, 0x1904, 0x6e95, 0x782c, 0x908c, 0x0780, - 0x190c, 0x70d1, 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, - 0x6d9f, 0x6e95, 0x6dba, 0x6e28, 0x080c, 0x0d7d, 0x0005, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8532, 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1904, 0x6e17, 0x7830, 0xd0dc, 0x1120, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, - 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, - 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8532, 0x782c, 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x19c8, - 0x0e04, 0x6e0e, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, - 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, - 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11e1, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1921, - 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8532, 0x0804, 0x6dc9, - 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, - 0x6e68, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd09c, 0x1170, 0x009e, 0x2900, - 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8532, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1904, 0x6f02, 0x782c, 0x9094, 0x0780, - 0x190c, 0x70d1, 0xd09c, 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, - 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, - 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x70d1, - 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, - 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, - 0x6efb, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8532, 0x00ee, 0x0804, 0x6ea5, 0x2071, - 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1128, 0x1e04, 0x6f42, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x080c, 0x8566, 0x0804, 0x6c7e, 0x0096, 0x00e6, 0x7824, 0x2048, + 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, + 0x70c2, 0x080c, 0x8566, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd09c, 0x11a0, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1560, + 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1170, 0x2071, 0x1a02, + 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, + 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, + 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, + 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, + 0x6d7e, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, 0xd09c, 0x1198, + 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, + 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, + 0x70f5, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, + 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, 0xd0a4, 0x1d60, 0x00ee, + 0x2071, 0x1a02, 0x703c, 0x9005, 0x1328, 0x2001, 0x1948, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8532, - 0x0e04, 0x6f2c, 0x2071, 0x1910, 0x701c, 0x2048, 0xa84c, 0x900d, - 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, - 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x2071, - 0x1910, 0x080c, 0x70bd, 0x002e, 0x00ee, 0x0005, 0xa850, 0x9082, - 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, - 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, - 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2071, 0x1910, 0xa803, - 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, + 0x00ee, 0x0804, 0x6d39, 0xa868, 0xd0fc, 0x1560, 0x0096, 0xa804, + 0xa807, 0x0000, 0x904d, 0x190c, 0x0ff9, 0x009e, 0x0018, 0xa868, + 0xd0fc, 0x1500, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, 0x2079, + 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, + 0x6eb9, 0x782c, 0x908c, 0x0780, 0x190c, 0x70f5, 0x8004, 0x8004, + 0x8004, 0x9084, 0x0003, 0x0002, 0x6dc3, 0x6eb9, 0x6dde, 0x6e4c, + 0x080c, 0x0d7d, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, + 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, + 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, 0x0c60, 0x2071, 0x1800, + 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6e3b, 0x7830, 0xd0dc, + 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, + 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, + 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, + 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, + 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, 0x782c, 0x9094, 0x0780, + 0x190c, 0x70f5, 0xd0a4, 0x19c8, 0x0e04, 0x6e32, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, + 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, + 0x080c, 0x8566, 0x0804, 0x6ded, 0x0096, 0x00e6, 0x7824, 0x2048, + 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, + 0x70c2, 0x080c, 0x8566, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6e8c, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x11ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd09c, 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, + 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, + 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, + 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, + 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, + 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, + 0x6f26, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, 0xd09c, 0x11b0, + 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, + 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, + 0x9094, 0x0780, 0x190c, 0x70f5, 0xd09c, 0x0d50, 0x782c, 0x9094, + 0x0780, 0x190c, 0x70f5, 0xd0a4, 0x05a8, 0x00e6, 0x7824, 0x2048, + 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, + 0x70c2, 0x080c, 0x8566, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6f1f, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x11ee, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, + 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, + 0x00ee, 0x0804, 0x6ec9, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x6f66, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8532, 0x002e, 0x00ee, 0x0005, 0x0006, - 0xa87c, 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, - 0x00ff, 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1910, - 0x7004, 0x0002, 0x6fd0, 0x6fd1, 0x70bc, 0x6fd1, 0x0d7d, 0x70bc, - 0x0005, 0x2001, 0x1947, 0x2004, 0x0002, 0x6fdb, 0x6fdb, 0x7055, - 0x7056, 0x6fdb, 0x7056, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x70dc, - 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x7026, 0x0e04, - 0x7004, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, - 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, - 0x2071, 0x1910, 0x080c, 0x70bd, 0x012e, 0x0804, 0x7054, 0xa850, - 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, - 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, - 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, - 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, 0x005b, - 0x2004, 0x9094, 0x0780, 0x190c, 0x70d1, 0xd09c, 0x2071, 0x1910, - 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, - 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, - 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, - 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, - 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, - 0x2069, 0x1a02, 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, - 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1b4d, 0x210c, 0x9102, - 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, - 0x9106, 0x0190, 0x0e04, 0x7088, 0x2069, 0x0000, 0x6837, 0x8040, - 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11e1, 0x2069, 0x1a02, 0x683f, 0xffff, - 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x7142, 0x701c, - 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, - 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, - 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, - 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, - 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, - 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, - 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, - 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x106c, 0x0005, 0x012e, - 0x0005, 0x2091, 0x8000, 0x0e04, 0x70d3, 0x0006, 0x0016, 0x2001, - 0x8004, 0x0006, 0x0804, 0x0d86, 0x0096, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, - 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, 0x1991, 0xd0a4, - 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, - 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, - 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, - 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, 0x9094, 0x0780, 0x190c, - 0x70d1, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x00ee, 0x00fe, - 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, - 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, - 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11e1, 0x00fe, 0x0005, 0x782c, - 0x9094, 0x0780, 0x190c, 0x70d1, 0xd0a4, 0x0db8, 0x00e6, 0x2071, - 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8532, 0x782c, 0x9094, 0x0780, 0x190c, - 0x70d1, 0xd0a4, 0x1d70, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, - 0x1947, 0x6808, 0x690a, 0x2069, 0x1a02, 0x9102, 0x1118, 0x683c, - 0x9005, 0x1328, 0x2001, 0x1948, 0x200c, 0x810d, 0x693e, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x0029, 0x1a0c, 0x0d7d, - 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00, 0x080c, 0x2a63, - 0x002e, 0x0005, 0x726e, 0x71f4, 0x7210, 0x723a, 0x725d, 0x729d, - 0x72af, 0x7210, 0x7285, 0x71af, 0x71dd, 0x71ae, 0x0005, 0x00d6, - 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, - 0x709b, 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, 0x080c, 0x760a, - 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0028, 0x2069, - 0x198e, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, - 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6a, 0x080c, 0x1ac2, 0x005e, - 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, 0x0028, - 0x2069, 0x198e, 0x2d04, 0x7002, 0x080c, 0x76ad, 0x6028, 0x9085, - 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, - 0x2a29, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x7320, 0xd1d4, - 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, 0x080c, - 0x7320, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, - 0x2001, 0x0088, 0x080c, 0x2a29, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, - 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1aec, - 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x74f4, 0x2001, - 0x0080, 0x080c, 0x2a29, 0x709b, 0x0028, 0x0058, 0x709b, 0x001e, - 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, - 0x001f, 0x0005, 0x080c, 0x1aec, 0x60e3, 0x0001, 0x600c, 0xc0b4, - 0x600e, 0x080c, 0x74f4, 0x2001, 0x0080, 0x080c, 0x2a29, 0x6124, - 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, - 0x1158, 0x709b, 0x0028, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, - 0x2a29, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1aec, - 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, 0x73a9, - 0x6124, 0xd1dc, 0x1188, 0x080c, 0x7320, 0x0016, 0x080c, 0x1aec, - 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, 0x0020, - 0x709b, 0x001f, 0x080c, 0x7320, 0x0005, 0x0006, 0x2001, 0x00a0, - 0x080c, 0x2a29, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, - 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x73a9, 0x6124, - 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x0006, - 0x2001, 0x0090, 0x080c, 0x2a29, 0x000e, 0x6124, 0xd1d4, 0x1178, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, 0x001e, - 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, - 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c, - 0x74c8, 0x11f8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01d0, 0xc1b4, - 0x2102, 0x0026, 0x2011, 0x0200, 0x080c, 0x2a63, 0x002e, 0x080c, - 0x2a0f, 0x6024, 0xd0cc, 0x0148, 0x2001, 0x00a0, 0x080c, 0x2a29, - 0x080c, 0x77cc, 0x080c, 0x6024, 0x0428, 0x6028, 0xc0cd, 0x602a, - 0x0408, 0x080c, 0x74e2, 0x0150, 0x080c, 0x74d9, 0x1138, 0x2001, - 0x0001, 0x080c, 0x25b9, 0x080c, 0x749c, 0x00a0, 0x080c, 0x73a6, - 0x0178, 0x2001, 0x0001, 0x080c, 0x25b9, 0x7098, 0x9086, 0x001e, - 0x0120, 0x7098, 0x9086, 0x0022, 0x1118, 0x709b, 0x0025, 0x0010, - 0x709b, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, - 0x0026, 0x2011, 0x7331, 0x080c, 0x8729, 0x002e, 0x0016, 0x0026, - 0x2009, 0x0064, 0x2011, 0x7331, 0x080c, 0x8720, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x9e16, 0x2071, 0x1800, - 0x080c, 0x72ca, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x9e16, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, - 0x6028, 0xc09c, 0x602a, 0x080c, 0xa888, 0x2011, 0x0003, 0x080c, - 0xa1b1, 0x2011, 0x0002, 0x080c, 0xa1bb, 0x080c, 0xa07a, 0x080c, - 0x86d5, 0x0036, 0x901e, 0x080c, 0xa0fa, 0x003e, 0x080c, 0xa8a4, - 0x60e3, 0x0000, 0x080c, 0xe712, 0x080c, 0xe72d, 0x2009, 0x0004, - 0x080c, 0x2a15, 0x080c, 0x292f, 0x2001, 0x1800, 0x2003, 0x0004, - 0x2011, 0x0008, 0x080c, 0x2a63, 0x2011, 0x7331, 0x080c, 0x8729, - 0x080c, 0x74e2, 0x0118, 0x9006, 0x080c, 0x2a29, 0x080c, 0x0bc3, - 0x2001, 0x0001, 0x080c, 0x25b9, 0x012e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, - 0x733e, 0x2071, 0x1a02, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, - 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, - 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, - 0x00c0, 0x080c, 0x2a29, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x73b6, - 0x2091, 0x6000, 0x1f04, 0x73b6, 0x015e, 0x00d6, 0x2069, 0x1800, - 0x689c, 0x8001, 0x0220, 0x0118, 0x689e, 0x00de, 0x0005, 0x689f, - 0x0014, 0x68ec, 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, - 0x080c, 0x8735, 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x77db, 0x2001, 0x196c, - 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x2688, - 0x9006, 0x080c, 0x2a29, 0x080c, 0x5edf, 0x0026, 0x2011, 0xffff, - 0x080c, 0x2a63, 0x002e, 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x2001, 0x197c, 0x200c, 0x9186, 0x0000, 0x0158, - 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, - 0x0158, 0x0804, 0x748c, 0x709b, 0x0022, 0x0040, 0x709b, 0x0021, - 0x0028, 0x709b, 0x0023, 0x0010, 0x709b, 0x0024, 0x60e3, 0x0000, - 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2688, 0x080c, 0xa888, - 0x0026, 0x080c, 0xab50, 0x002e, 0x080c, 0xa8a4, 0x7000, 0x908e, - 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, - 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, - 0x012e, 0x015e, 0x080c, 0xcf51, 0x0118, 0x9006, 0x080c, 0x2a53, - 0x0804, 0x7498, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, - 0x2a0f, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2a29, - 0x1f04, 0x743d, 0x080c, 0x751f, 0x012e, 0x015e, 0x080c, 0x74d9, - 0x0170, 0x6044, 0x9005, 0x0130, 0x080c, 0x751f, 0x9006, 0x8001, - 0x1df0, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x751f, 0x080c, - 0xcf51, 0x0118, 0x9006, 0x080c, 0x2a53, 0x0016, 0x0026, 0x7000, - 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x733e, 0x080c, - 0x86e7, 0x002e, 0x001e, 0x080c, 0x8529, 0x7034, 0xc085, 0x7036, - 0x2001, 0x197c, 0x2003, 0x0004, 0x080c, 0x7193, 0x080c, 0x74d9, - 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x77d1, - 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x8540, 0x080c, - 0x8532, 0x080c, 0x77db, 0x2001, 0x196c, 0x2003, 0x0000, 0x9006, - 0x709a, 0x60e2, 0x6886, 0x080c, 0x2688, 0x9006, 0x080c, 0x2a29, - 0x6043, 0x0090, 0x6043, 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, - 0x2a63, 0x002e, 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x0006, 0x2001, 0x197b, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, - 0x0006, 0x080c, 0x56d9, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, - 0x0005, 0x0006, 0x080c, 0x56d9, 0x9084, 0x0030, 0x9086, 0x0030, - 0x000e, 0x0005, 0x0006, 0x080c, 0x56d9, 0x9084, 0x0030, 0x9086, - 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, 0x56d9, 0x9084, 0x0030, - 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, - 0x2004, 0x908c, 0x0013, 0x0180, 0x0020, 0x080c, 0x26a8, 0x900e, - 0x0028, 0x080c, 0x6a62, 0x1dc8, 0x2009, 0x0002, 0x2019, 0x0028, - 0x080c, 0x31b4, 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, - 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, 0xcf4a, 0x1128, 0x9085, - 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, - 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, - 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, - 0x0000, 0x20a9, 0x0002, 0x080c, 0x29f0, 0x0026, 0x2011, 0x0040, - 0x080c, 0x2a63, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, + 0x9200, 0x70c2, 0x080c, 0x8566, 0x0e04, 0x6f50, 0x2071, 0x1910, + 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, + 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, + 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, + 0xd084, 0x190c, 0x11ee, 0x2071, 0x1910, 0x080c, 0x70e1, 0x002e, + 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, + 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, + 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, + 0x0890, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, + 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, + 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, + 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8566, + 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103, + 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0, + 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a, + 0xa982, 0x0005, 0x2071, 0x1910, 0x7004, 0x0002, 0x6ff4, 0x6ff5, + 0x70e0, 0x6ff5, 0x0d7d, 0x70e0, 0x0005, 0x2001, 0x1947, 0x2004, + 0x0002, 0x6fff, 0x6fff, 0x7079, 0x707a, 0x6fff, 0x707a, 0x0126, + 0x2091, 0x8000, 0x1e0c, 0x7100, 0x701c, 0x904d, 0x0508, 0xa84c, + 0x9005, 0x0904, 0x704a, 0x0e04, 0x7028, 0xa94c, 0x2071, 0x0000, + 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, + 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x11ee, 0x2071, 0x1910, 0x080c, 0x70e1, + 0x012e, 0x0804, 0x7078, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, + 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, + 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, + 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, + 0x014e, 0x0890, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, + 0x70f5, 0xd09c, 0x2071, 0x1910, 0x1510, 0x2071, 0x1910, 0x700f, + 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, + 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, + 0x0050, 0x6822, 0x00de, 0x2071, 0x1910, 0x701c, 0x2048, 0x7010, + 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, + 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x1a02, 0x683c, 0x9005, + 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, 0x1815, 0x2004, + 0x2009, 0x1b4d, 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, + 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x70ac, + 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11ee, + 0x2069, 0x1a02, 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, + 0x8000, 0x1e0c, 0x7166, 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, + 0x2004, 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500, 0x2071, 0x1910, + 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, + 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, + 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, + 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, + 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, + 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, + 0x080c, 0x1079, 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, + 0x70f7, 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0d86, + 0x0096, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01c0, 0xc084, + 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, + 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x11ee, 0x00fe, 0x009e, 0x0005, 0x782c, + 0x9094, 0x0780, 0x1991, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, + 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, + 0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, + 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, + 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, 0xd0a4, 0x19c8, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x11ee, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, + 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, + 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, + 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x11ee, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, + 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8566, + 0x782c, 0x9094, 0x0780, 0x190c, 0x70f5, 0xd0a4, 0x1d70, 0x00d6, + 0x2069, 0x0050, 0x693c, 0x2069, 0x1947, 0x6808, 0x690a, 0x2069, + 0x1a02, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, 0x1948, + 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, + 0x908a, 0x0029, 0x1a0c, 0x0d7d, 0x9082, 0x001d, 0x003b, 0x0026, + 0x2011, 0x1e00, 0x080c, 0x2a83, 0x002e, 0x0005, 0x7292, 0x7218, + 0x7234, 0x725e, 0x7281, 0x72c1, 0x72d3, 0x7234, 0x72a9, 0x71d3, + 0x7201, 0x71d2, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1180, 0x6808, 0x9005, 0x1518, 0x709b, 0x0028, 0x2069, 0x198e, + 0x2d04, 0x7002, 0x080c, 0x762d, 0x6028, 0x9085, 0x0600, 0x602a, + 0x00b0, 0x709b, 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, 0x6028, + 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, + 0x1a6a, 0x080c, 0x1adf, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, + 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, + 0x9005, 0x1160, 0x709b, 0x0028, 0x2069, 0x198e, 0x2d04, 0x7002, + 0x080c, 0x76d0, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, + 0x0006, 0x2001, 0x0090, 0x080c, 0x2a49, 0x000e, 0x6124, 0xd1e4, + 0x1190, 0x080c, 0x7344, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, + 0x0150, 0x709b, 0x0020, 0x080c, 0x7344, 0x0028, 0x709b, 0x001d, + 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2a49, + 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, + 0x1e00, 0x11d8, 0x080c, 0x1b04, 0x60e3, 0x0001, 0x600c, 0xc0b4, + 0x600e, 0x080c, 0x7518, 0x2001, 0x0080, 0x080c, 0x2a49, 0x709b, + 0x0028, 0x0058, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, + 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x080c, 0x1b04, + 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x7518, 0x2001, + 0x0080, 0x080c, 0x2a49, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, + 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x709b, 0x0028, 0x0040, + 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, + 0x0005, 0x2001, 0x00a0, 0x080c, 0x2a49, 0x6124, 0xd1dc, 0x1138, + 0xd1e4, 0x0138, 0x080c, 0x1b04, 0x709b, 0x001e, 0x0010, 0x709b, + 0x001d, 0x0005, 0x080c, 0x73cd, 0x6124, 0xd1dc, 0x1188, 0x080c, + 0x7344, 0x0016, 0x080c, 0x1b04, 0x001e, 0xd1d4, 0x1128, 0xd1e4, + 0x0138, 0x709b, 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x7344, + 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2a49, 0x000e, 0x6124, + 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, + 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, + 0x0005, 0x080c, 0x73cd, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, + 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, + 0x709b, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2a49, + 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, + 0xd1e4, 0x0158, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, + 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x0016, 0x00c6, + 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1800, 0x2091, 0x8000, 0x080c, 0x74ec, 0x11f8, 0x2001, 0x180c, + 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200, + 0x080c, 0x2a83, 0x002e, 0x080c, 0x2a2f, 0x6024, 0xd0cc, 0x0148, + 0x2001, 0x00a0, 0x080c, 0x2a49, 0x080c, 0x77ef, 0x080c, 0x6044, + 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x7506, 0x0150, + 0x080c, 0x74fd, 0x1138, 0x2001, 0x0001, 0x080c, 0x25d5, 0x080c, + 0x74c0, 0x00a0, 0x080c, 0x73ca, 0x0178, 0x2001, 0x0001, 0x080c, + 0x25d5, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, + 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, + 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x7355, 0x080c, + 0x875d, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x7355, + 0x080c, 0x8754, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, + 0x080c, 0x9e4f, 0x2071, 0x1800, 0x080c, 0x72ee, 0x001e, 0x00fe, + 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x0126, 0x080c, 0x9e4f, 0x2061, 0x0100, 0x2069, 0x0140, + 0x2071, 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c, + 0xa899, 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, 0x080c, + 0xa1c8, 0x080c, 0xa0b3, 0x080c, 0x8709, 0x0036, 0x901e, 0x080c, + 0xa133, 0x003e, 0x080c, 0xa8b5, 0x60e3, 0x0000, 0x080c, 0xe74f, + 0x080c, 0xe76a, 0x2009, 0x0004, 0x080c, 0x2a35, 0x080c, 0x294b, + 0x2001, 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x2a83, + 0x2011, 0x7355, 0x080c, 0x875d, 0x080c, 0x7506, 0x0118, 0x9006, + 0x080c, 0x2a49, 0x080c, 0x0bc3, 0x2001, 0x0001, 0x080c, 0x25d5, + 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x0005, 0x0026, 0x00e6, 0x2011, 0x7362, 0x2071, 0x1a02, 0x701c, + 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, + 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, + 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2a49, 0x0156, + 0x20a9, 0x002d, 0x1d04, 0x73da, 0x2091, 0x6000, 0x1f04, 0x73da, + 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, 0x0220, 0x0118, + 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68ec, 0xd0dc, 0x0dc8, + 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8769, 0x0c90, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, + 0x080c, 0x77fe, 0x2001, 0x196c, 0x2003, 0x0000, 0x9006, 0x709a, + 0x60e2, 0x6886, 0x080c, 0x26a4, 0x9006, 0x080c, 0x2a49, 0x080c, + 0x5eff, 0x0026, 0x2011, 0xffff, 0x080c, 0x2a83, 0x002e, 0x602b, + 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197c, + 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, + 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x74b0, 0x709b, + 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, + 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, + 0x080c, 0x26a4, 0x080c, 0xa899, 0x0026, 0x080c, 0xab61, 0x002e, + 0x080c, 0xa8b5, 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, + 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, 0xcf84, + 0x0118, 0x9006, 0x080c, 0x2a73, 0x0804, 0x74bc, 0x6800, 0x9084, + 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a2f, 0x6904, 0xd1d4, 0x1140, + 0x2001, 0x0100, 0x080c, 0x2a49, 0x1f04, 0x7461, 0x080c, 0x7543, + 0x012e, 0x015e, 0x080c, 0x74fd, 0x0170, 0x6044, 0x9005, 0x0130, + 0x080c, 0x7543, 0x9006, 0x8001, 0x1df0, 0x0028, 0x6804, 0xd0d4, + 0x1110, 0x080c, 0x7543, 0x080c, 0xcf84, 0x0118, 0x9006, 0x080c, + 0x2a73, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, + 0x00c8, 0x2011, 0x7362, 0x080c, 0x871b, 0x002e, 0x001e, 0x080c, + 0x855d, 0x7034, 0xc085, 0x7036, 0x2001, 0x197c, 0x2003, 0x0004, + 0x080c, 0x71b7, 0x080c, 0x74fd, 0x0138, 0x6804, 0xd0d4, 0x1120, + 0xd0dc, 0x1100, 0x080c, 0x77f4, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x1800, 0x080c, 0x8574, 0x080c, 0x8566, 0x080c, 0x77fe, 0x2001, + 0x196c, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, + 0x26a4, 0x9006, 0x080c, 0x2a49, 0x6043, 0x0090, 0x6043, 0x0010, + 0x0026, 0x2011, 0xffff, 0x080c, 0x2a83, 0x002e, 0x602b, 0x182c, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x197b, 0x2004, + 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, 0x56f9, 0x9084, + 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x56f9, + 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, + 0x56f9, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, + 0x080c, 0x56f9, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, + 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, 0x0180, + 0x0020, 0x080c, 0x26c4, 0x900e, 0x0028, 0x080c, 0x6a86, 0x1dc8, + 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x31d4, 0x9006, 0x0019, + 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, + 0x080c, 0xcf7d, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, + 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, + 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x080c, 0x2aa6, 0x080c, + 0x2ad9, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, + 0x0000, 0x20a9, 0x0002, 0x080c, 0x2a10, 0x0026, 0x2011, 0x0040, + 0x080c, 0x2a83, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, - 0x0001, 0x080c, 0x2688, 0x2001, 0x00a0, 0x0006, 0x080c, 0xcf51, - 0x000e, 0x0130, 0x080c, 0x2a47, 0x9006, 0x080c, 0x2a53, 0x0010, - 0x080c, 0x2a29, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, - 0x00f6, 0x2079, 0x0100, 0x080c, 0x29a0, 0x00fe, 0x000e, 0x6052, + 0x0001, 0x080c, 0x26a4, 0x2001, 0x00a0, 0x0006, 0x080c, 0xcf84, + 0x000e, 0x0130, 0x080c, 0x2a67, 0x9006, 0x080c, 0x2a73, 0x0010, + 0x080c, 0x2a49, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, + 0x00f6, 0x2079, 0x0100, 0x080c, 0x29bc, 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xa8e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xa8f7, 0x0158, 0x2001, 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, - 0x080c, 0xa879, 0x0804, 0x75fc, 0x2001, 0x180c, 0x200c, 0xc1c4, + 0x080c, 0xa88a, 0x0804, 0x761f, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, - 0x2a63, 0x2001, 0x0090, 0x080c, 0x2a29, 0x20a9, 0x0366, 0x6024, - 0xd0cc, 0x1558, 0x1d04, 0x7597, 0x2091, 0x6000, 0x1f04, 0x7597, - 0x080c, 0xa888, 0x2011, 0x0003, 0x080c, 0xa1b1, 0x2011, 0x0002, - 0x080c, 0xa1bb, 0x080c, 0xa07a, 0x901e, 0x080c, 0xa0fa, 0x2001, - 0x0386, 0x2003, 0x7000, 0x080c, 0xa8a4, 0x2001, 0x00a0, 0x080c, - 0x2a29, 0x080c, 0x77cc, 0x080c, 0x6024, 0x080c, 0xcf51, 0x0110, - 0x080c, 0x0ce9, 0x9085, 0x0001, 0x04e8, 0x2001, 0x0386, 0x2004, - 0xd0ac, 0x0110, 0x080c, 0x1aec, 0x60e3, 0x0000, 0x2001, 0x196c, - 0x2004, 0x080c, 0x2688, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2a29, - 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x2a63, 0x2009, 0x1e00, - 0x080c, 0x2a0f, 0x6024, 0x910c, 0x0140, 0x1d04, 0x75da, 0x2091, - 0x6000, 0x1f04, 0x75da, 0x0804, 0x75a0, 0x2001, 0x0386, 0x2003, - 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, 0x9005, 0x1118, - 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xcf51, 0x0110, 0x080c, - 0x0ce9, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, 0x9086, 0x0003, - 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, 0x9086, 0x5540, - 0x1128, 0x2069, 0x1a76, 0x2d04, 0x8000, 0x206a, 0x2069, 0x0140, - 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x7673, - 0x2001, 0x0088, 0x080c, 0x2a29, 0x9006, 0x60e2, 0x6886, 0x080c, - 0x2688, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, - 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011, 0x0400, 0x080c, - 0x2a63, 0x2069, 0x198e, 0x7000, 0x206a, 0x709b, 0x0026, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7653, 0x2091, 0x6000, 0x1f04, - 0x7653, 0x0804, 0x76a5, 0x2069, 0x0140, 0x20a9, 0x0384, 0x2011, - 0x1e00, 0x080c, 0x2a63, 0x2009, 0x1e00, 0x080c, 0x2a0f, 0x6024, - 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, 0x765f, 0x2091, - 0x6000, 0x1f04, 0x765f, 0x080c, 0xa888, 0x2011, 0x0003, 0x080c, - 0xa1b1, 0x2011, 0x0002, 0x080c, 0xa1bb, 0x080c, 0xa07a, 0x901e, - 0x080c, 0xa0fa, 0x080c, 0xa8a4, 0x2001, 0x00a0, 0x080c, 0x2a29, - 0x080c, 0x77cc, 0x080c, 0x6024, 0x9085, 0x0001, 0x00b0, 0x2001, - 0x0080, 0x080c, 0x2a29, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x196c, - 0x2004, 0x080c, 0x2688, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, + 0x2a83, 0x2001, 0x0090, 0x080c, 0x2a49, 0x20a9, 0x0366, 0x6024, + 0xd0cc, 0x1558, 0x1d04, 0x75bf, 0x2091, 0x6000, 0x1f04, 0x75bf, + 0x080c, 0xa899, 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, + 0x080c, 0xa1c8, 0x080c, 0xa0b3, 0x901e, 0x080c, 0xa133, 0x2001, + 0x0386, 0x2003, 0x7000, 0x080c, 0xa8b5, 0x2001, 0x00a0, 0x080c, + 0x2a49, 0x080c, 0x77ef, 0x080c, 0x6044, 0x080c, 0xcf84, 0x0110, + 0x080c, 0x0ce9, 0x9085, 0x0001, 0x04c0, 0x080c, 0x1b04, 0x60e3, + 0x0000, 0x2001, 0x196c, 0x2004, 0x080c, 0x26a4, 0x60e2, 0x2001, + 0x0080, 0x080c, 0x2a49, 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, + 0x2a83, 0x2009, 0x1e00, 0x080c, 0x2a2f, 0x6024, 0x910c, 0x0140, + 0x1d04, 0x75fd, 0x2091, 0x6000, 0x1f04, 0x75fd, 0x0804, 0x75c8, + 0x2001, 0x0386, 0x2003, 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, + 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, + 0xcf84, 0x0110, 0x080c, 0x0ce9, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, - 0x6020, 0x9084, 0x00c0, 0x01e8, 0x080c, 0xa888, 0x2011, 0x0003, - 0x080c, 0xa1b1, 0x2011, 0x0002, 0x080c, 0xa1bb, 0x080c, 0xa07a, - 0x901e, 0x080c, 0xa0fa, 0x080c, 0xa8a4, 0x2069, 0x0140, 0x2001, - 0x00a0, 0x080c, 0x2a29, 0x080c, 0x77cc, 0x080c, 0x6024, 0x0804, - 0x7748, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, - 0x080c, 0x7326, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2a29, - 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, - 0x9005, 0x0190, 0x6028, 0x9084, 0xfdff, 0x602a, 0x2011, 0x0200, - 0x080c, 0x2a63, 0x2069, 0x198e, 0x7000, 0x206a, 0x709b, 0x0027, - 0x7003, 0x0001, 0x0804, 0x7748, 0x2011, 0x1e00, 0x080c, 0x2a63, - 0x2009, 0x1e00, 0x080c, 0x2a0f, 0x6024, 0x910c, 0x01c8, 0x9084, - 0x1c00, 0x11b0, 0x1d04, 0x7704, 0x0006, 0x0016, 0x00c6, 0x00d6, - 0x00e6, 0x080c, 0x8571, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, - 0x00e6, 0x2071, 0x1a02, 0x7018, 0x00ee, 0x9005, 0x19e8, 0x0500, - 0x0026, 0x2011, 0x733e, 0x080c, 0x861d, 0x2011, 0x7331, 0x080c, - 0x8729, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, - 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x196c, 0x2004, - 0x080c, 0x2688, 0x60e2, 0x2001, 0x180c, 0x200c, 0xc1b4, 0x2102, + 0x7000, 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, + 0x5540, 0x9086, 0x5540, 0x1128, 0x2069, 0x1a76, 0x2d04, 0x8000, + 0x206a, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, + 0x9005, 0x1904, 0x7696, 0x2001, 0x0088, 0x080c, 0x2a49, 0x9006, + 0x60e2, 0x6886, 0x080c, 0x26a4, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1118, 0x6808, 0x9005, 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, + 0x2011, 0x0400, 0x080c, 0x2a83, 0x2069, 0x198e, 0x7000, 0x206a, + 0x709b, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7676, + 0x2091, 0x6000, 0x1f04, 0x7676, 0x0804, 0x76c8, 0x2069, 0x0140, + 0x20a9, 0x0384, 0x2011, 0x1e00, 0x080c, 0x2a83, 0x2009, 0x1e00, + 0x080c, 0x2a2f, 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, + 0x1d04, 0x7682, 0x2091, 0x6000, 0x1f04, 0x7682, 0x080c, 0xa899, + 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, 0x080c, 0xa1c8, + 0x080c, 0xa0b3, 0x901e, 0x080c, 0xa133, 0x080c, 0xa8b5, 0x2001, + 0x00a0, 0x080c, 0x2a49, 0x080c, 0x77ef, 0x080c, 0x6044, 0x9085, + 0x0001, 0x00b0, 0x2001, 0x0080, 0x080c, 0x2a49, 0x2069, 0x0140, + 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, + 0x6886, 0x2001, 0x196c, 0x2004, 0x080c, 0x26a4, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x080c, 0xcf4a, 0x1904, 0x77b6, 0x7130, - 0xd184, 0x1170, 0x080c, 0x335c, 0x0138, 0xc18d, 0x7132, 0x2011, - 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x77b6, - 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, 0x2019, 0x000e, - 0x080c, 0xe249, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x9186, - 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, 0x6620, 0x1170, - 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, 0xe2d9, 0x2009, - 0x0001, 0x2011, 0x0100, 0x080c, 0x88ce, 0x001e, 0x8108, 0x1f04, - 0x777f, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, - 0x0002, 0x2019, 0x0004, 0x080c, 0x31b4, 0x001e, 0x0078, 0x0156, - 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6620, 0x1110, 0x080c, - 0x603e, 0x8108, 0x1f04, 0x77ac, 0x00be, 0x015e, 0x080c, 0x1aec, - 0x080c, 0xa888, 0x080c, 0xab50, 0x080c, 0xa8a4, 0x60e3, 0x0000, - 0x080c, 0x6024, 0x080c, 0x73f9, 0x00ee, 0x00ce, 0x004e, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197c, 0x2003, 0x0001, - 0x0005, 0x2001, 0x197c, 0x2003, 0x0000, 0x0005, 0x2001, 0x197b, - 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197b, 0x2003, 0x0000, 0x0005, - 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1053, - 0x090c, 0x0d7d, 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1053, - 0x090c, 0x0d7d, 0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, - 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, - 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, - 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, - 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, - 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, - 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, - 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, - 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18fa, 0x6807, 0x0001, - 0x00de, 0x080c, 0x7dc3, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, - 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, 0x7842, 0x015e, 0x0005, - 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, 0x7858, 0x7859, - 0x78a4, 0x78ff, 0x7a0f, 0x7856, 0x7856, 0x7a39, 0x080c, 0x0d7d, - 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, 0x2003, 0x0000, 0x782c, - 0x908c, 0x0780, 0x190c, 0x7ea5, 0xd0a4, 0x0570, 0x2001, 0x1dc0, - 0x2004, 0x9082, 0x0080, 0x1640, 0x1d04, 0x7876, 0x2001, 0x1a05, - 0x200c, 0x8109, 0x0508, 0x2091, 0x6000, 0x2102, 0x7824, 0x2048, - 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, - 0x0608, 0x00b8, 0x2001, 0x1800, 0x200c, 0x9186, 0x0003, 0x1160, - 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, - 0x0003, 0x1968, 0x080c, 0x78ff, 0x782c, 0xd09c, 0x090c, 0x7dc3, - 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, 0x0c18, 0x080c, - 0x7935, 0x0c90, 0x00e3, 0x08f0, 0x0005, 0x7935, 0x7935, 0x7935, - 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7957, 0x7935, 0x7935, - 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, - 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, - 0x7935, 0x7941, 0x7935, 0x7b2a, 0x7935, 0x7935, 0x7935, 0x7957, - 0x7935, 0x7941, 0x7b6b, 0x7bac, 0x7bf3, 0x7c07, 0x7935, 0x7935, - 0x7957, 0x7941, 0x796b, 0x7935, 0x79e3, 0x7cb2, 0x7ccd, 0x7935, - 0x7957, 0x7935, 0x796b, 0x7935, 0x7935, 0x79d9, 0x7ccd, 0x7935, - 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, - 0x797f, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, - 0x7935, 0x7935, 0x7e49, 0x7935, 0x7df3, 0x7935, 0x7df3, 0x7935, - 0x7994, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x7935, 0x2079, - 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x7dec, - 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, - 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, - 0x080c, 0x7dc3, 0x0005, 0x7935, 0x7941, 0x7b16, 0x7935, 0x7941, - 0x7935, 0x7941, 0x7941, 0x7935, 0x7941, 0x7b16, 0x7941, 0x7941, - 0x7941, 0x7941, 0x7941, 0x7935, 0x7941, 0x7b16, 0x7935, 0x7935, - 0x7941, 0x7935, 0x7935, 0x7935, 0x7941, 0x00e6, 0x2071, 0x18fa, - 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, - 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, - 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, 0x00ff, 0x9105, 0xa86a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7ab8, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7ab8, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7ad3, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7ad3, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0904, 0x793d, 0x8001, 0x1120, 0x7007, - 0x0001, 0x0804, 0x7aef, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, - 0x701a, 0x704b, 0x7aef, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, - 0x9086, 0x0001, 0x1904, 0x793d, 0x7007, 0x0001, 0x2009, 0x1834, - 0x210c, 0x81ff, 0x11a8, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, - 0x0000, 0x080c, 0x62b4, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, - 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, 0x6d7b, 0x012e, 0x0ca0, - 0xa994, 0x9186, 0x0071, 0x0d38, 0x9186, 0x0064, 0x0d20, 0x9186, - 0x007c, 0x0d08, 0x9186, 0x0028, 0x09f0, 0x9186, 0x0038, 0x09d8, - 0x9186, 0x0078, 0x09c0, 0x9186, 0x005f, 0x09a8, 0x9186, 0x0056, - 0x0990, 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, - 0x08a0, 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, - 0x0001, 0x0804, 0x7ce4, 0x2900, 0x7016, 0x701a, 0x20a9, 0x0004, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, 0x2098, 0x7050, 0x2040, - 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, 0x20a0, 0x4003, 0xa888, - 0x7012, 0x9082, 0x0401, 0x1a04, 0x7945, 0xaab4, 0x928a, 0x0002, - 0x1a04, 0x7945, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, - 0x2001, 0x7a76, 0x0018, 0x9280, 0x7a6c, 0x2005, 0x7056, 0x7010, - 0x9015, 0x0904, 0x7a57, 0x080c, 0x1053, 0x1118, 0x7007, 0x0004, - 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, 0xe000, 0xa866, 0x7050, - 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, 0xa860, 0xa072, 0xe008, - 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, - 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, 0x810b, 0xa17e, 0x080c, - 0x112f, 0xa06c, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, - 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, 0x080c, 0x106c, 0x7014, - 0x2048, 0x0804, 0x7945, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, - 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x7a0f, 0x7014, - 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, - 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x0904, 0x7ce4, 0x0804, 0x7ab8, 0x7a6e, 0x7a72, 0x0002, 0x001d, - 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, 0x001d, - 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, 0xaebc, 0xa804, 0x2050, - 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, - 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, - 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, - 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, 0xb7a6, 0xb090, 0xb09a, - 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, 0xb086, 0xb692, 0xb78e, - 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, 0xb072, 0xb074, 0xb06e, - 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, 0x006e, 0x007e, 0x0005, - 0x2009, 0x1834, 0x210c, 0x81ff, 0x1178, 0x080c, 0x60b6, 0x1108, - 0x0005, 0x080c, 0x6faf, 0x0126, 0x2091, 0x8000, 0x080c, 0xcb35, - 0x080c, 0x6d7b, 0x012e, 0x0ca0, 0x080c, 0xcf4a, 0x1d70, 0x2001, - 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1188, - 0xa888, 0x9005, 0x0188, 0xa883, 0x0000, 0x080c, 0x6144, 0x1108, - 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, - 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, 0x0000, 0x0c90, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, - 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6216, 0x1138, 0x0005, - 0x9006, 0xa87a, 0x080c, 0x6191, 0x1108, 0x0005, 0x0126, 0x2091, - 0x8000, 0xa87a, 0xa982, 0x080c, 0x6d7b, 0x012e, 0x0cb0, 0x2001, - 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0xa802, - 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, - 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, - 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, - 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, - 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, - 0x11d8, 0xa974, 0x080c, 0x6620, 0x11b8, 0x0066, 0xae80, 0x080c, - 0x6730, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x6620, 0x1110, 0x080c, 0x6903, - 0x8108, 0x1f04, 0x7b53, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, - 0x106c, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, - 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x080c, 0x6a66, 0x0580, 0x2061, 0x1a6e, 0x6100, 0xd184, 0x0178, - 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, - 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, - 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, - 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, - 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, - 0x012e, 0x0804, 0x7dad, 0x012e, 0x0804, 0x7da7, 0x012e, 0x0804, - 0x7da1, 0x012e, 0x0804, 0x7da4, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6a66, 0x05e0, 0x2061, 0x1a6e, 0x6000, 0xd084, - 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, - 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, - 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, - 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, - 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, - 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, - 0x6206, 0x630a, 0x012e, 0x0804, 0x7dad, 0x012e, 0x0804, 0x7daa, - 0x012e, 0x0804, 0x7da7, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2061, 0x1a6e, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, - 0x630a, 0x012e, 0x0804, 0x7dbb, 0x012e, 0x0804, 0x7daa, 0x00b6, - 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, - 0x0148, 0x00c6, 0x2061, 0x1a6e, 0x6000, 0x9084, 0xfcff, 0x6002, - 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xac1a, 0x0068, - 0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, - 0x6162, 0x2009, 0x0041, 0x080c, 0xac7c, 0xa988, 0x918c, 0xff00, - 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, - 0x88ce, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a6e, 0x6000, - 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, - 0x00be, 0x0804, 0x7dad, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7da7, - 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, - 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, - 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, - 0x1d10, 0xa974, 0x080c, 0x6620, 0x1968, 0xb800, 0xc0e4, 0xb802, - 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1985, - 0x2004, 0x601a, 0x0804, 0x7c42, 0xa88c, 0x9065, 0x0960, 0x00e6, - 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, 0x080c, - 0xac1a, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xac1a, 0x00ee, 0x0804, - 0x7c42, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, - 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, - 0x6016, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x00ee, - 0x0804, 0x7c42, 0x2061, 0x1a6e, 0x6000, 0xd084, 0x0190, 0xd08c, - 0x1904, 0x7dbb, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, - 0x6206, 0x012e, 0x0804, 0x7dbb, 0x012e, 0xa883, 0x0016, 0x0804, - 0x7db4, 0xa883, 0x0007, 0x0804, 0x7db4, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, - 0x080c, 0x793d, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, - 0x701a, 0x704b, 0x7ce4, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, 0x7d66, - 0x6130, 0xd194, 0x1904, 0x7d90, 0xa878, 0x2070, 0x9e82, 0x1ddc, - 0x0a04, 0x7d5a, 0x6068, 0x9e02, 0x1a04, 0x7d5a, 0x7120, 0x9186, - 0x0006, 0x1904, 0x7d4c, 0x7010, 0x905d, 0x0904, 0x7d66, 0xb800, - 0xd0e4, 0x1904, 0x7d8a, 0x2061, 0x1a6e, 0x6100, 0x9184, 0x0301, - 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7d93, 0xa883, - 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, - 0xa87c, 0xd0f4, 0x1904, 0x7d96, 0x080c, 0x56d5, 0xd09c, 0x1118, - 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x87be, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, - 0xa87c, 0xd0f4, 0x1904, 0x7d96, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7db4, 0xd184, - 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x6620, 0x15d0, - 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, - 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, - 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x56d9, - 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x02c0, 0x6068, - 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, - 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, - 0x0007, 0x1904, 0x7cf0, 0x7003, 0x0002, 0x0804, 0x7cf0, 0xa883, - 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, - 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, - 0x0002, 0x601b, 0x0014, 0x080c, 0xde2a, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, - 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, - 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6d7b, 0x012e, 0x0005, 0x080c, 0x106c, 0x0005, 0x00d6, 0x080c, - 0x87b5, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, - 0x7ea5, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, 0x0020, - 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, - 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, - 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, - 0x7ea5, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c, - 0xab89, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0035, 0x1138, 0x6028, 0xc0fd, 0x602a, 0x2001, 0x196a, 0x2004, - 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105, - 0xa99c, 0x918c, 0x00ff, 0x080c, 0x2614, 0x1540, 0x00b6, 0x080c, - 0x6620, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, 0x2009, - 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009, - 0x0041, 0x080c, 0xac7c, 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6d7b, 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, 0x0005, 0xa87b, 0x0028, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, 0x080c, 0xabdf, - 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, - 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x7e96, 0xa97c, 0x9188, - 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, - 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, - 0xab89, 0x1118, 0x080c, 0xac4f, 0x05a8, 0x6212, 0xa874, 0x0002, - 0x7e74, 0x7e79, 0x7e7c, 0x7e82, 0x2019, 0x0002, 0x080c, 0xe249, - 0x0060, 0x080c, 0xe1d9, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, - 0xe1f8, 0x0018, 0xa980, 0x080c, 0xe1d9, 0x080c, 0xabdf, 0xa887, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, 0x00be, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, - 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, - 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, - 0x7ea7, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0d86, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, - 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, - 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1615, 0x00fe, 0x0005, - 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, - 0x781c, 0xd08c, 0x0904, 0x7f28, 0x68c0, 0x90aa, 0x0005, 0x0a04, - 0x8529, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d7d, 0x9584, 0x00f6, - 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, - 0x0700, 0x8007, 0x04f0, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, - 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, - 0x9086, 0x8100, 0x11c0, 0x080c, 0xe6ea, 0x080c, 0x8420, 0x7817, - 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x847c, 0x19c8, - 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x7f78, 0x080c, 0x2126, - 0x005e, 0x004e, 0x0020, 0x080c, 0xe6ea, 0x7817, 0x0140, 0x080c, - 0x74c8, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, - 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x0489, - 0x0005, 0x0002, 0x7f35, 0x8242, 0x7f32, 0x7f32, 0x7f32, 0x7f32, - 0x7f32, 0x7f32, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, 0xff00, - 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000, - 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x5736, 0x0070, - 0x080c, 0x7f98, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x817f, - 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x8356, 0x7817, 0x0140, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, - 0x2518, 0x080c, 0x4b09, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, - 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, - 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, - 0x080c, 0x4b09, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, - 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, - 0x0120, 0x9096, 0x0023, 0x1904, 0x8150, 0x9186, 0x0023, 0x15c0, - 0x080c, 0x83eb, 0x0904, 0x8150, 0x6120, 0x9186, 0x0001, 0x0150, - 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, - 0x1904, 0x8150, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, - 0x2009, 0x0015, 0x080c, 0xac7c, 0x0804, 0x8150, 0x908e, 0x0214, - 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xac7c, - 0x0804, 0x8150, 0x908e, 0x0100, 0x1904, 0x8150, 0x7034, 0x9005, - 0x1904, 0x8150, 0x2009, 0x0016, 0x080c, 0xac7c, 0x0804, 0x8150, - 0x9186, 0x0022, 0x1904, 0x8150, 0x7030, 0x908e, 0x0300, 0x1580, - 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, 0x918c, 0x00ff, - 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, - 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x265d, 0x7932, - 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2614, 0x695e, 0x703c, - 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee, - 0x7034, 0x9005, 0x1904, 0x8150, 0x2009, 0x0017, 0x0804, 0x8100, - 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8150, 0x080c, - 0x74c8, 0x0120, 0x2009, 0x001d, 0x0804, 0x8100, 0x68dc, 0xc0a5, - 0x68de, 0x2009, 0x0030, 0x0804, 0x8100, 0x908e, 0x0500, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8150, 0x2009, 0x0018, 0x0804, 0x8100, - 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x8100, 0x908e, - 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x8100, 0x908e, 0x5200, - 0x1140, 0x7034, 0x9005, 0x1904, 0x8150, 0x2009, 0x001b, 0x0804, - 0x8100, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x8150, - 0x2009, 0x001c, 0x0804, 0x8100, 0x908e, 0x1300, 0x1120, 0x2009, - 0x0034, 0x0804, 0x8100, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, - 0x1904, 0x8150, 0x2009, 0x0024, 0x0804, 0x8100, 0x908c, 0xff00, - 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, - 0xd09c, 0x0904, 0x8100, 0x080c, 0xd65c, 0x1904, 0x8150, 0x0804, - 0x80fe, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, - 0x0804, 0x8100, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, - 0x8100, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d, - 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, - 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4b09, 0x004e, - 0x8108, 0x0f04, 0x80b4, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, - 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, - 0x0804, 0x8100, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, - 0x8100, 0x908e, 0x5400, 0x1138, 0x080c, 0x84d9, 0x1904, 0x8150, - 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x8501, - 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e, - 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, - 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, - 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, - 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, - 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2614, - 0x1904, 0x8153, 0x080c, 0x65bf, 0x1904, 0x8153, 0xbe12, 0xbd16, - 0x001e, 0x0016, 0x080c, 0x74c8, 0x01c0, 0x68dc, 0xd08c, 0x1148, - 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, - 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, 0x9084, 0xff00, - 0x1120, 0x9584, 0x00ff, 0xb886, 0x0080, 0xb884, 0x9005, 0x1168, - 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, 0x6880, 0x9506, - 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0xab89, 0x01a8, - 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, - 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xac7c, - 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b09, 0x080c, 0xac4f, - 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, - 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, - 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x9207, 0x08a0, 0x080c, - 0x3326, 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, - 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x83eb, 0x0904, - 0x81da, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, - 0x9005, 0x15c0, 0x2009, 0x0015, 0x080c, 0xac7c, 0x0498, 0x908e, - 0x0100, 0x1580, 0x7034, 0x9005, 0x1568, 0x2009, 0x0016, 0x080c, - 0xac7c, 0x0440, 0x9186, 0x0032, 0x1528, 0x7030, 0x908e, 0x1400, - 0x1508, 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2614, 0x11a8, 0x080c, 0x65bf, 0x1190, 0xbe12, - 0xbd16, 0x080c, 0xab89, 0x0168, 0x2b08, 0x6112, 0x080c, 0xcccb, - 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0xac7c, 0x0010, - 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, - 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, - 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, - 0x823c, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x823c, - 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, - 0x2019, 0x1837, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, - 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, - 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, - 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, - 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, - 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, - 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x8211, 0x82ff, 0x1118, 0x9085, - 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, - 0x00be, 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, - 0x0002, 0x8259, 0x8259, 0x8259, 0x83fd, 0x8259, 0x825c, 0x8281, - 0x830a, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, - 0x8259, 0x7817, 0x0140, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, - 0x7120, 0x2160, 0x9c8c, 0x0003, 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, - 0x6868, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, - 0x610a, 0x2009, 0x0046, 0x080c, 0xac7c, 0x7817, 0x0140, 0x00be, - 0x0005, 0x00b6, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x82e6, 0x7110, - 0xd1bc, 0x1904, 0x82e6, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, - 0x2130, 0x9094, 0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x3368, - 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, - 0x82e6, 0x9182, 0x0801, 0x1a04, 0x82e6, 0x9190, 0x1000, 0x2204, - 0x905d, 0x05e0, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, - 0x9294, 0xff00, 0x9286, 0x0600, 0x1190, 0x080c, 0xab89, 0x0598, - 0x2b08, 0x7028, 0x6052, 0x702c, 0x604e, 0x6112, 0x6023, 0x0006, - 0x7120, 0x610a, 0x7130, 0x615e, 0x080c, 0xd8c4, 0x00f8, 0x080c, - 0x6a6a, 0x1138, 0xb807, 0x0606, 0x0c40, 0x190c, 0x81de, 0x11b0, - 0x0880, 0x080c, 0xab89, 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, - 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, - 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9207, 0x7817, 0x0140, - 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, - 0x2011, 0x8049, 0x080c, 0x4b09, 0x080c, 0xac4f, 0x0d78, 0x2b08, - 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, - 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x9200, 0x08e0, 0x00b6, 0x7110, 0xd1bc, 0x05d0, 0x7020, 0x2060, - 0x9c84, 0x0003, 0x15a8, 0x9c82, 0x1ddc, 0x0690, 0x6868, 0x9c02, - 0x1678, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0650, 0x7008, 0x9084, - 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1510, 0x700c, 0xb914, - 0x9106, 0x11f0, 0x7124, 0x610a, 0x601c, 0xd0fc, 0x11c8, 0x2001, - 0x0271, 0x2004, 0x9005, 0x1180, 0x9484, 0x0fff, 0x9082, 0x000c, - 0x0158, 0x0066, 0x2031, 0x0100, 0xa001, 0xa001, 0x8631, 0x1de0, - 0x006e, 0x601c, 0xd0fc, 0x1120, 0x2009, 0x0045, 0x080c, 0xac7c, - 0x7817, 0x0140, 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, - 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x3326, - 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, - 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, 0x836d, - 0x836e, 0x836d, 0x836d, 0x83cd, 0x83dc, 0x0005, 0x00b6, 0x7110, - 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x83cb, 0x700c, 0x7108, - 0x080c, 0x2614, 0x1904, 0x83cb, 0x080c, 0x65bf, 0x1904, 0x83cb, - 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x01d8, 0x080c, 0x6a6a, 0x0118, - 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, 0x83eb, 0x00ce, 0x05d8, - 0x080c, 0xab89, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xcccb, 0x6023, - 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xac7c, 0x0458, - 0x080c, 0x6a6a, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6a72, - 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, 0xab89, 0x2b08, 0x01d8, - 0x6112, 0x080c, 0xcccb, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, - 0x0088, 0x080c, 0xac7c, 0x0078, 0x080c, 0xab89, 0x2b08, 0x0158, - 0x6112, 0x080c, 0xcccb, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, - 0x0001, 0x080c, 0xac7c, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, - 0x00d1, 0x0148, 0x080c, 0x834c, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0089, 0x080c, 0xac7c, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, - 0x0148, 0x080c, 0x834c, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, - 0x080c, 0xac7c, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0003, 0x1158, - 0x9c82, 0x1ddc, 0x0240, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1218, - 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, - 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0003, 0x11b0, 0x9c82, 0x1ddc, - 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, - 0x2009, 0x0051, 0x080c, 0xac7c, 0x7817, 0x0140, 0x00be, 0x0005, - 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, - 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, - 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, - 0x05c0, 0x080c, 0xab89, 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2614, 0x1590, 0x080c, - 0x65bf, 0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, - 0x080c, 0xcccb, 0x080c, 0x103a, 0x0500, 0x2900, 0x6062, 0x9006, - 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, - 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, - 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9207, 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xabdf, 0x006e, - 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, - 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x84d3, 0x9186, - 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x84d5, - 0x7030, 0x908e, 0x0400, 0x0904, 0x84d5, 0x908e, 0x6000, 0x05e8, - 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, - 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6a28, 0x0558, - 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, - 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, - 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, - 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, - 0x9186, 0x0023, 0x1140, 0x080c, 0x83eb, 0x0128, 0x6004, 0x9086, - 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, - 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, - 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x027a, 0x080c, 0xbba1, 0x1178, 0xd48c, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xbba1, 0x1120, - 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, - 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, - 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0272, 0x080c, 0xbba1, 0x1178, 0xd48c, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xbba1, 0x1120, - 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, - 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, - 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, - 0x2071, 0x1a02, 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, - 0x7072, 0x7012, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, - 0x9e36, 0x7032, 0x7037, 0x9eb3, 0x703f, 0xffff, 0x7042, 0x7047, - 0x556c, 0x704a, 0x705b, 0x86f0, 0x080c, 0x1053, 0x090c, 0x0d7d, - 0x2900, 0x703a, 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, - 0x0005, 0x2071, 0x1a02, 0x1d04, 0x860c, 0x2091, 0x6000, 0x700c, - 0x8001, 0x700e, 0x1590, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, - 0x879a, 0x2001, 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, - 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, - 0x0d7d, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, - 0x2069, 0x1800, 0x69ec, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, - 0x875e, 0x0010, 0x080c, 0x8735, 0x7040, 0x900d, 0x0148, 0x8109, - 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, - 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, - 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, - 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, - 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, - 0x9184, 0x007f, 0x090c, 0x9f4f, 0x0010, 0x7034, 0x080f, 0x703c, - 0x9005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, - 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, - 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, - 0x0016, 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, - 0x706f, 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, - 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, - 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x8634, 0x8635, - 0x865f, 0x00e6, 0x2071, 0x1a02, 0x7018, 0x9005, 0x1120, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, - 0x1a02, 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x7072, 0x7076, - 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1a02, 0xb888, 0x9102, - 0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, - 0x7110, 0x080c, 0x6620, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, - 0x1180, 0x0126, 0x2091, 0x8000, 0x0066, 0xb8d0, 0x9005, 0x0138, - 0x0026, 0xba3c, 0x0016, 0x080c, 0x674b, 0x001e, 0x002e, 0x006e, - 0x012e, 0x8108, 0x9182, 0x0800, 0x1220, 0x8631, 0x0128, 0x7112, - 0x0c00, 0x900e, 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x2031, - 0x0010, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6048, 0x9005, - 0x0128, 0x8001, 0x604a, 0x1110, 0x080c, 0xcb4c, 0x6018, 0x9005, - 0x0904, 0x86b7, 0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, - 0x86ca, 0x781b, 0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, - 0x2000, 0x0804, 0x86ca, 0x8001, 0x601a, 0x0106, 0x781b, 0x2000, - 0xa001, 0x7918, 0xd1ac, 0x1dd0, 0x010e, 0x00fe, 0x1540, 0x6120, - 0x9186, 0x0003, 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, - 0x11e0, 0x611c, 0xd1c4, 0x1100, 0x080c, 0xc832, 0x01b0, 0x6014, - 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, - 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, - 0x9108, 0x611a, 0x080c, 0xcf7d, 0x0110, 0x080c, 0xc523, 0x012e, - 0x9c88, 0x001c, 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, 0x1228, - 0x8631, 0x0138, 0x2160, 0x0804, 0x8663, 0x7017, 0x1ddc, 0x7007, - 0x0000, 0x0005, 0x00fe, 0x0c58, 0x00e6, 0x2071, 0x1a02, 0x7027, - 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a0b, 0x2003, - 0x0000, 0x0005, 0x00e6, 0x2071, 0x1a02, 0x7132, 0x702f, 0x0009, - 0x00ee, 0x0005, 0x2011, 0x1a0e, 0x2013, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x1a02, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, - 0x0086, 0x0026, 0x7054, 0x8000, 0x7056, 0x2001, 0x1a10, 0x2044, - 0xa06c, 0x9086, 0x0000, 0x0150, 0x7068, 0xa09a, 0x7064, 0xa096, - 0x7060, 0xa092, 0x705c, 0xa08e, 0x080c, 0x112f, 0x002e, 0x008e, - 0x0005, 0x0006, 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x0156, 0x080c, 0x8571, 0x015e, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, - 0x00e6, 0x2071, 0x1a02, 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a02, 0x7074, 0x9206, 0x1110, - 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69ec, - 0xd1e4, 0x1518, 0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, - 0x0288, 0x8117, 0x9294, 0x00c1, 0x0088, 0x9184, 0x0007, 0x01a0, - 0x8109, 0x9184, 0x0007, 0x0110, 0x69ee, 0x0070, 0x8107, 0x9084, - 0x0007, 0x910d, 0x8107, 0x9106, 0x9094, 0x00c1, 0x9184, 0xff3e, - 0x9205, 0x68ee, 0x080c, 0x0f05, 0x002e, 0x0005, 0x69e8, 0x9184, - 0x003f, 0x05b8, 0x8109, 0x9184, 0x003f, 0x01a8, 0x6a54, 0x6874, - 0x9202, 0x0220, 0xd1bc, 0x0168, 0xc1bc, 0x0018, 0xd1bc, 0x1148, - 0xc1bd, 0x2110, 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f27, 0x00ee, - 0x0400, 0x69ea, 0x00f0, 0x0026, 0x8107, 0x9094, 0x0007, 0x0128, - 0x8001, 0x8007, 0x9085, 0x0007, 0x0050, 0x2010, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0007, 0x9205, 0x8007, 0x9085, 0x0028, 0x9086, - 0x0040, 0x2010, 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f27, 0x00ee, - 0x002e, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfffc, 0x210d, 0x2061, - 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009, 0xfffc, 0x200f, - 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, - 0x00c6, 0x2061, 0x1a6e, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, - 0x8003, 0x8003, 0x9080, 0x1a6e, 0x2060, 0x0005, 0xa884, 0x908a, - 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a6e, 0x6014, - 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, - 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, - 0x00c0, 0x918e, 0x00c0, 0x0904, 0x8878, 0xd0b4, 0x1168, 0xd0bc, - 0x1904, 0x8851, 0x2009, 0x0006, 0x080c, 0x88a5, 0x0005, 0x900e, - 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x05e0, 0x908c, 0x2023, - 0x1568, 0x87ff, 0x1558, 0xa9a8, 0x81ff, 0x1540, 0x6124, 0x918c, - 0x0500, 0x1520, 0x6100, 0x918e, 0x0007, 0x1500, 0x2009, 0x1869, - 0x210c, 0xd184, 0x11d8, 0x6003, 0x0003, 0x6007, 0x0043, 0x6047, - 0xb035, 0x080c, 0x1c10, 0xa87c, 0xc0dd, 0xa87e, 0x600f, 0x0000, - 0x00f6, 0x2079, 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0013, - 0x2c00, 0x7836, 0x781b, 0x8080, 0x00fe, 0x0005, 0x908c, 0x0003, - 0x0120, 0x918e, 0x0003, 0x1904, 0x889f, 0x908c, 0x2020, 0x918e, - 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, - 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xac7c, - 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0xac7c, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, - 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, - 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, - 0x1904, 0x889f, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, - 0x00f6, 0x2c78, 0x080c, 0x173e, 0x00fe, 0x007e, 0x87ff, 0x1120, - 0x2009, 0x0042, 0x080c, 0xac7c, 0x0005, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, - 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, - 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, - 0x080c, 0xac7c, 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, - 0x0043, 0x080c, 0xac7c, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, - 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xc832, - 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, - 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, - 0x2061, 0x1a6e, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, - 0x6206, 0x00ce, 0x080c, 0x6bb0, 0x6014, 0x904d, 0x0076, 0x2039, - 0x0000, 0x190c, 0x87be, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, - 0x2061, 0x1a6e, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, - 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, - 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, - 0x1923, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, - 0x0001, 0x080c, 0x1053, 0x090c, 0x0d7d, 0xa867, 0x0006, 0xa86b, - 0x0001, 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, - 0x0000, 0x0005, 0x0096, 0x00e6, 0x2071, 0x1923, 0x702c, 0x2048, - 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0xa896, 0x6838, - 0x702a, 0xa89a, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, - 0x200a, 0x9005, 0x0148, 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, - 0x2100, 0x9210, 0x1208, 0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, - 0x0178, 0xc084, 0x7007, 0x0001, 0x700f, 0x0000, 0x0006, 0x2009, - 0x181d, 0x2104, 0x9082, 0x0007, 0x2009, 0x1b4d, 0x200a, 0x000e, - 0xc095, 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x1686, 0x9006, - 0x2071, 0x193c, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x0005, - 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, - 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, - 0x9080, 0x0008, 0x1f04, 0x8958, 0x71c0, 0x9102, 0x02e0, 0x2071, - 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c, 0xab89, 0x6023, 0x0009, - 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, - 0x080c, 0x8ade, 0x012e, 0x1f04, 0x8964, 0x9006, 0x00ce, 0x015e, - 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, - 0x0096, 0x0086, 0x0056, 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, - 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, - 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, 0x103a, 0x090c, 0x0d7d, - 0x2900, 0x6016, 0x2058, 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, - 0xa87a, 0xa8aa, 0xa887, 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, - 0x7010, 0xa89e, 0xae8a, 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, - 0x0160, 0x080c, 0x103a, 0x090c, 0x0d7d, 0xad66, 0x2b00, 0xa802, - 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, - 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, - 0x1923, 0x7004, 0x004b, 0x700c, 0x0002, 0x89d0, 0x89c9, 0x89c9, - 0x0005, 0x89da, 0x8a3b, 0x8a3b, 0x8a3b, 0x8a3c, 0x8a4d, 0x8a4d, - 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, - 0x0128, 0x78a0, 0x79a0, 0x9106, 0x1904, 0x8a2e, 0x2001, 0x0005, - 0x2004, 0xd0bc, 0x0130, 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, - 0x0ca8, 0x012e, 0x7018, 0x910a, 0x1130, 0x7030, 0x9005, 0x05a8, - 0x080c, 0x8a7c, 0x0490, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, - 0x0210, 0x2009, 0x000a, 0x2001, 0x1888, 0x2014, 0x2001, 0x1935, - 0x2004, 0x9100, 0x9202, 0x0e48, 0x080c, 0x8bc8, 0x2200, 0x9102, - 0x0208, 0x2208, 0x0096, 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, - 0x080c, 0x8cd1, 0x2100, 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, - 0x2091, 0x8000, 0x2009, 0x1a20, 0x2104, 0xc085, 0x200a, 0x700f, - 0x0002, 0x012e, 0x080c, 0x114e, 0x1de8, 0x0005, 0x2001, 0x0005, - 0x2004, 0xd0bc, 0x0130, 0x2011, 0x0004, 0x2204, 0xc0c5, 0x2012, - 0x0ca8, 0x012e, 0x0005, 0x0005, 0x700c, 0x0002, 0x8a41, 0x8a44, - 0x8a43, 0x080c, 0x89d8, 0x0005, 0x8001, 0x700e, 0x0096, 0x702c, - 0x2048, 0xa974, 0x009e, 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c, - 0x2048, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e, - 0x7020, 0xa892, 0x9006, 0x0068, 0x0006, 0x080c, 0x8cd1, 0x2100, - 0xaa8c, 0x9210, 0xaa8e, 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, - 0x000e, 0x009e, 0x2f08, 0x9188, 0x0028, 0x200a, 0x701a, 0x0005, - 0x00e6, 0x2071, 0x1923, 0x700c, 0x0002, 0x8a7a, 0x8a7a, 0x8a78, - 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, - 0x9005, 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x8ae7, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193c, - 0x080c, 0x8b2e, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1053, 0x2900, - 0x009e, 0x0148, 0xa8aa, 0x04b9, 0x0041, 0x2001, 0x1946, 0x2003, - 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, - 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, - 0x000f, 0x2068, 0x9d88, 0x1e62, 0x2165, 0x0056, 0x2029, 0x0000, - 0x080c, 0x8c56, 0x080c, 0x1e38, 0x1dd8, 0x005e, 0x00ae, 0x2001, - 0x187f, 0x2004, 0xa88a, 0x080c, 0x173e, 0x781f, 0x0101, 0x7813, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x8b3d, 0x012e, 0x008e, - 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, 0x2078, 0x780c, - 0x7032, 0x2001, 0x1946, 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, - 0x1923, 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, 0x0005, 0x00d6, - 0x00c6, 0x0026, 0x9b80, 0x8db0, 0x2005, 0x906d, 0x090c, 0x0d7d, - 0x9b80, 0x8da8, 0x2005, 0x9065, 0x090c, 0x0d7d, 0x6114, 0x2600, - 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085, 0x0001, 0x002e, - 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, 0x0148, 0x6854, 0xd084, - 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, 0x080c, 0x4b09, 0x684c, - 0x0096, 0x904d, 0x090c, 0x0d7d, 0xa804, 0x8000, 0xa806, 0x009e, - 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, 0xc08d, 0x6856, - 0x2011, 0x8025, 0x080c, 0x4b09, 0x684c, 0x0096, 0x904d, 0x090c, - 0x0d7d, 0xa800, 0x8000, 0xa802, 0x009e, 0x0888, 0x7000, 0x2019, - 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, - 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, - 0x090c, 0x0d7d, 0x781c, 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, - 0x0d7d, 0x2069, 0x193c, 0x6804, 0x9080, 0x193e, 0x2f08, 0x2102, - 0x6904, 0x8108, 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, - 0x193e, 0x2003, 0x0000, 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, - 0x6014, 0x2048, 0xa8a8, 0x0096, 0x2048, 0x9005, 0x190c, 0x106c, - 0x009e, 0xa8ab, 0x0000, 0x080c, 0x0fec, 0x080c, 0xabdf, 0x00ce, - 0x009e, 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, - 0x0110, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, - 0x0000, 0x0178, 0x6010, 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, - 0x8ee3, 0x00be, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, - 0x0861, 0x0005, 0x2009, 0x1927, 0x210c, 0xd194, 0x0005, 0x00e6, - 0x2071, 0x1923, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, - 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x1686, 0x00ee, 0x0005, - 0x0096, 0x00d6, 0x9006, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, - 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x8d30, 0x0170, - 0x080c, 0x8d65, 0x0158, 0x2900, 0x7002, 0x700a, 0x701a, 0x7013, - 0x0001, 0x701f, 0x000a, 0x00de, 0x009e, 0x0005, 0x900e, 0x0cd8, - 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6, 0x2071, 0x1930, 0x721c, - 0x2100, 0x9202, 0x1618, 0x080c, 0x8d65, 0x090c, 0x0d7d, 0x7018, - 0x9005, 0x1160, 0x2900, 0x7002, 0x700a, 0x701a, 0x9006, 0x7006, - 0x700e, 0xa806, 0xa802, 0x7012, 0x701e, 0x0038, 0x2040, 0xa806, - 0x2900, 0xa002, 0x701a, 0xa803, 0x0000, 0x7010, 0x8000, 0x7012, - 0x701c, 0x9080, 0x000a, 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, - 0x00de, 0x008e, 0x009e, 0x00ee, 0x0005, 0x0096, 0x0156, 0x0136, - 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1930, 0x7300, - 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, 0x20e8, 0x939c, 0xffc0, - 0x9398, 0x0003, 0x7104, 0x080c, 0x8cd1, 0x810c, 0x2100, 0x9318, - 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, - 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, - 0x080c, 0x8cda, 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, - 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, 0x1190, - 0x7000, 0x2048, 0xa800, 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, - 0x080c, 0x8bc8, 0x002e, 0x7000, 0x2048, 0xa800, 0x7002, 0x7007, - 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, 0x1904, 0x8c07, 0x012e, - 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e, 0x0005, 0x0016, 0x0026, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580, 0x8da8, 0x2005, 0x9075, - 0x090c, 0x0d7d, 0x080c, 0x8cac, 0x012e, 0x9580, 0x8da4, 0x2005, - 0x9075, 0x090c, 0x0d7d, 0x0156, 0x0136, 0x01c6, 0x0146, 0x01d6, - 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, 0x20e0, 0x9384, 0xffc0, - 0x9100, 0x2098, 0xa860, 0x20e8, 0xa95c, 0x2c05, 0x9100, 0x20a0, - 0x20a9, 0x0002, 0x4003, 0x2e0c, 0x2d00, 0x0002, 0x8c96, 0x8c96, - 0x8c98, 0x8c96, 0x8c98, 0x8c96, 0x8c96, 0x8c96, 0x8c96, 0x8c96, - 0x8c9e, 0x8c96, 0x8c9e, 0x8c96, 0x8c96, 0x8c96, 0x080c, 0x0d7d, - 0x4104, 0x20a9, 0x0002, 0x4002, 0x4003, 0x0028, 0x20a9, 0x0002, - 0x4003, 0x4104, 0x4003, 0x01de, 0x014e, 0x01ce, 0x013e, 0x015e, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x7014, 0x8001, 0x7016, - 0x710c, 0x2110, 0x00f1, 0x810c, 0x9188, 0x0003, 0x7308, 0x8210, - 0x9282, 0x000a, 0x1198, 0x7008, 0x2048, 0xa800, 0x9005, 0x0158, - 0x0006, 0x080c, 0x8d74, 0x009e, 0xa807, 0x0000, 0x2900, 0x700a, - 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x009e, - 0x0005, 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, 0x9100, 0x2008, - 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, 0x9005, 0x0158, 0x9092, - 0x000c, 0x0240, 0x900e, 0x8108, 0x9082, 0x000c, 0x1de0, 0x002e, - 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00, 0x90b8, 0x0008, 0x690c, - 0x6810, 0x2019, 0x0001, 0x2031, 0x8d1a, 0x9112, 0x0220, 0x0118, - 0x8318, 0x2208, 0x0cd0, 0x6808, 0x9005, 0x0108, 0x8318, 0x233a, - 0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, - 0x0967, 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, - 0x9082, 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, - 0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0x90b8, 0x0007, 0x00e6, 0x2071, - 0x1800, 0x7128, 0x6810, 0x2019, 0x0001, 0x910a, 0x0118, 0x0210, - 0x8318, 0x0cd8, 0x2031, 0x8d2d, 0x0870, 0x6c16, 0x00ee, 0x0005, - 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, 0x9080, 0x8dac, - 0x2005, 0x9005, 0x090c, 0x0d7d, 0x2004, 0x90a0, 0x000a, 0x080c, - 0x1053, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, - 0x080c, 0x1053, 0x0188, 0x7024, 0xa802, 0xa807, 0x0000, 0x2900, - 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, - 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2048, - 0xac00, 0x080c, 0x106c, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, - 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, 0x7026, 0xa803, 0x0000, - 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, - 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, 0x0096, 0x9e80, 0x0009, - 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x106c, - 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, 0x9005, 0x0138, - 0x2048, 0xa800, 0x0006, 0x080c, 0x106c, 0x000e, 0x0cb8, 0x9006, - 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, - 0x7026, 0x702e, 0x009e, 0x0005, 0x1a6c, 0x0000, 0x0000, 0x0000, - 0x1930, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, 0x0000, 0x0000, - 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, 0x00b6, 0x00a6, - 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x8ece, 0xa067, 0x0023, - 0x6010, 0x905d, 0x0904, 0x8ea3, 0xb814, 0xa06e, 0xb910, 0xa172, - 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834, 0xa082, 0xa07b, - 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, 0xc085, 0xa07a, 0x2858, - 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c, 0x0d7d, 0x2020, - 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, 0x000f, 0x91e0, - 0x1e62, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, 0x908a, 0x0036, - 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x8e10, 0x8e10, 0x8e12, - 0x8e10, 0x8e10, 0x8e10, 0x8e14, 0x8e10, 0x8e10, 0x8e10, 0x8e16, - 0x8e10, 0x8e10, 0x8e10, 0x8e18, 0x8e10, 0x8e10, 0x8e10, 0x8e1a, - 0x8e10, 0x8e10, 0x8e10, 0x8e1c, 0x8e10, 0x8e10, 0x8e10, 0x8e1e, - 0x080c, 0x0d7d, 0xa180, 0x04b8, 0xa190, 0x04a8, 0xa1a0, 0x0498, - 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, 0xa1e0, 0x0458, - 0x908a, 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x8e42, - 0x8e40, 0x8e40, 0x8e40, 0x8e40, 0x8e40, 0x8e44, 0x8e40, 0x8e40, - 0x8e40, 0x8e40, 0x8e40, 0x8e46, 0x8e40, 0x8e40, 0x8e40, 0x8e40, - 0x8e40, 0x8e48, 0x8e40, 0x8e40, 0x8e40, 0x8e40, 0x8e40, 0x8e4a, - 0x080c, 0x0d7d, 0xa180, 0x0038, 0xa198, 0x0028, 0xa1b0, 0x0018, - 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x8e66, 0x8e68, 0x8e6a, - 0x8e6c, 0x8e6e, 0x8e70, 0x8e72, 0x8e74, 0x8e76, 0x8e78, 0x8e7a, - 0x8e7c, 0x8e7e, 0x8e80, 0x8e82, 0x8e84, 0x8e86, 0x8e88, 0x8e8a, - 0x8e8c, 0x8e8e, 0x8e90, 0x8e92, 0x8e94, 0x8e96, 0x080c, 0x0d7d, - 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448, 0xb9d6, 0x0438, - 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408, 0xb9c6, 0x00f8, - 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8, 0xb9b6, 0x00b8, - 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088, 0xb9a6, 0x0078, - 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048, 0xb996, 0x0038, - 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008, 0xb986, 0x8631, - 0x8421, 0x0120, 0x080c, 0x1e38, 0x0804, 0x8dea, 0x00ae, 0x00be, - 0x00ce, 0x00ee, 0x0005, 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, - 0x00ff, 0x9006, 0x0804, 0x8dcc, 0x0006, 0x0016, 0x00b6, 0x6010, - 0x2058, 0xb810, 0x9005, 0x01b0, 0x2001, 0x1924, 0x2004, 0x9005, - 0x0188, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0xbba0, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4b09, - 0x004e, 0x003e, 0x00be, 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, - 0xa834, 0x910a, 0xa936, 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, - 0x0238, 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, 0x0cd8, - 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, 0x0300, - 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, 0xa001, - 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, 0x9005, 0x01b8, 0x2068, - 0x2079, 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, 0xb8ae, 0x0060, - 0x9106, 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, 0x0d7d, - 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, - 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, - 0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, - 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, - 0x1f04, 0x8f23, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, - 0x1d90, 0xb8ac, 0x9005, 0x01d0, 0x2060, 0x600c, 0xb8ae, 0x6003, - 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, 0x6014, - 0x2048, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, 0x0000, 0x904d, 0x090c, - 0x0d7d, 0x080c, 0x106c, 0x080c, 0x8ade, 0x0c18, 0x2071, 0x0300, - 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x009e, 0x00de, - 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, 0x0006, 0x0156, 0x080c, - 0x2614, 0x015e, 0x11b0, 0x080c, 0x65bf, 0x190c, 0x0d7d, 0x000e, - 0x001e, 0xb912, 0xb816, 0x080c, 0xab89, 0x0140, 0x2b00, 0x6012, - 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, 0xac7c, 0x00be, 0x00ce, - 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, 0x0016, - 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0x8f95, 0x8f95, 0x8f95, - 0x8f97, 0x8fe0, 0x8f95, 0x8f95, 0x8f95, 0x9043, 0x8f95, 0x907b, - 0x8f95, 0x8f95, 0x8f95, 0x8f95, 0x8f95, 0x080c, 0x0d7d, 0x9182, - 0x0040, 0x0002, 0x8faa, 0x8faa, 0x8faa, 0x8faa, 0x8faa, 0x8faa, - 0x8faa, 0x8faa, 0x8faa, 0x8fac, 0x8fbd, 0x8faa, 0x8faa, 0x8faa, - 0x8faa, 0x8fce, 0x080c, 0x0d7d, 0x0096, 0x6114, 0x2148, 0xa87b, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, - 0x6b7b, 0x080c, 0xabdf, 0x009e, 0x0005, 0x080c, 0x9621, 0x00d6, - 0x6114, 0x080c, 0xc832, 0x0130, 0x0096, 0x6114, 0x2148, 0x080c, - 0x6d7b, 0x009e, 0x00de, 0x080c, 0xabdf, 0x0005, 0x080c, 0x9621, - 0x080c, 0x31ef, 0x6114, 0x0096, 0x2148, 0x080c, 0xc832, 0x0120, - 0xa87b, 0x0029, 0x080c, 0x6d7b, 0x009e, 0x080c, 0xabdf, 0x0005, - 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, 0x0002, 0x8ffb, 0x8ffb, - 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffd, 0x8ffb, - 0x8ffb, 0x8ffb, 0x903f, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, 0x8ffb, - 0x8ffb, 0x9003, 0x8ffb, 0x080c, 0x0d7d, 0x6114, 0x2148, 0xa938, - 0x918e, 0xffff, 0x05e0, 0x00e6, 0x6114, 0x2148, 0x080c, 0x8db4, - 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6b13, 0x009e, 0xa8ab, 0x0000, - 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x8ee3, 0x00be, - 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8ae7, 0x00be, 0x01e0, - 0x2071, 0x193c, 0x080c, 0x8b2e, 0x01b8, 0x9086, 0x0001, 0x1128, - 0x2001, 0x1946, 0x2004, 0x9005, 0x1178, 0x0096, 0x080c, 0x103a, - 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, 0x080c, 0x8aa5, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8ade, 0x0cd0, 0x080c, - 0x90f7, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, 0x0002, 0x9057, - 0x9057, 0x9057, 0x9059, 0x9057, 0x9057, 0x9057, 0x9079, 0x9057, - 0x9057, 0x9057, 0x9057, 0x9057, 0x9057, 0x9057, 0x9057, 0x080c, - 0x0d7d, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa8ac, 0xa836, - 0xa8b0, 0xa83a, 0xa847, 0x0000, 0xa84b, 0x0000, 0xa884, 0x9092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, - 0x621a, 0x080c, 0x1bc7, 0x2009, 0x8030, 0x080c, 0x9247, 0x009e, - 0x0005, 0x080c, 0x0d7d, 0x080c, 0x9621, 0x6114, 0x2148, 0xa87b, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, - 0x6d7b, 0x080c, 0xabdf, 0x009e, 0x0005, 0x080c, 0xa888, 0x6144, - 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003, 0x6000, 0x908a, - 0x0016, 0x1a0c, 0x0d7d, 0x0096, 0x0023, 0x009e, 0x080c, 0xa8a4, - 0x0005, 0x90b1, 0x90b1, 0x90b1, 0x90b3, 0x90c4, 0x90b1, 0x90b1, - 0x90b1, 0x90b1, 0x90b1, 0x90b1, 0x90b1, 0x90b1, 0x90b1, 0x90b1, - 0x90b1, 0x080c, 0x0d7d, 0x080c, 0xaa1c, 0x6114, 0x2148, 0xa87b, - 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, - 0x6d7b, 0x080c, 0xabdf, 0x0005, 0x0491, 0x0005, 0x080c, 0xa888, - 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120, 0x6003, 0x0003, - 0x2009, 0x0003, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0096, 0x0033, - 0x009e, 0x0106, 0x080c, 0xa8a4, 0x010e, 0x0005, 0x90ee, 0x90ee, - 0x90ee, 0x90f0, 0x90f7, 0x90ee, 0x90ee, 0x90ee, 0x90ee, 0x90ee, - 0x90ee, 0x90ee, 0x90ee, 0x90ee, 0x90ee, 0x90ee, 0x080c, 0x0d7d, - 0x0036, 0x00e6, 0x080c, 0xaa1c, 0x00ee, 0x003e, 0x0005, 0x00f6, - 0x00e6, 0x601b, 0x0000, 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, - 0x00b6, 0x2058, 0x080c, 0x8ee3, 0x00be, 0x2071, 0x193c, 0x080c, - 0x8b2e, 0x0160, 0x2001, 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, - 0x2c78, 0x080c, 0x8aa5, 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, - 0x0000, 0xa8a8, 0x2048, 0x080c, 0x106c, 0x009e, 0xa8ab, 0x0000, - 0x080c, 0x8ade, 0x0c80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, - 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086, 0x818e, 0x1208, 0x9200, - 0x1f04, 0x913c, 0x8086, 0x818e, 0x004e, 0x003e, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, - 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d, 0x0228, 0x911a, 0x1220, - 0x1f04, 0x9153, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x9153, - 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, - 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, - 0x2091, 0x2800, 0x2079, 0x19e6, 0x012e, 0x00d6, 0x2069, 0x19e6, - 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, - 0x0200, 0x080c, 0xa67d, 0x04a9, 0x080c, 0xa668, 0x0491, 0x080c, - 0xa66b, 0x0479, 0x080c, 0xa66e, 0x0461, 0x080c, 0xa671, 0x0449, - 0x080c, 0xa674, 0x0431, 0x080c, 0xa677, 0x0419, 0x080c, 0xa67a, - 0x0401, 0x01de, 0x014e, 0x015e, 0x6857, 0x0000, 0x00f6, 0x2079, - 0x0380, 0x00f9, 0x7807, 0x0003, 0x7803, 0x0000, 0x7803, 0x0001, - 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe, 0x9085, 0x8000, 0x206a, - 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc, 0x682a, 0x00fe, 0x00de, - 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, - 0x0005, 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, - 0x0400, 0x7827, 0x0031, 0x782b, 0x1aee, 0x781f, 0xff00, 0x781b, - 0xff00, 0x2061, 0x1ae3, 0x602f, 0x19e6, 0x6033, 0x1800, 0x6037, - 0x1a02, 0x603b, 0x1e62, 0x603f, 0x1e72, 0x6042, 0x6047, 0x1ab9, - 0x00ce, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0001, 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, - 0x19e6, 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, - 0x0003, 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, - 0x6146, 0x2c08, 0x2001, 0x0012, 0x080c, 0xa879, 0x0005, 0x0016, - 0x2009, 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, - 0x0007, 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0xa879, - 0x0088, 0x00c6, 0x2061, 0x19e6, 0x602c, 0x8000, 0x602e, 0x600c, - 0x9005, 0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, 0x6112, - 0x610e, 0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, - 0x0007, 0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, 0x0000, - 0x2c08, 0x2061, 0x19e6, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, - 0x2102, 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, - 0x600f, 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xa879, 0x0005, - 0x6044, 0xd0dc, 0x0110, 0x080c, 0xa31a, 0x0005, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, - 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e6, 0x7648, - 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x92d3, 0x6010, - 0x2058, 0xb8a0, 0x9206, 0x1904, 0x92ce, 0x87ff, 0x0120, 0x605c, - 0x9106, 0x1904, 0x92ce, 0x704c, 0x9c06, 0x1178, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa0fa, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, - 0x7052, 0x706e, 0x003e, 0x2029, 0x0001, 0x0811, 0x7048, 0x9c36, - 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xc832, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, - 0x1588, 0x6004, 0x9086, 0x0040, 0x090c, 0xa31a, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xcb35, - 0x080c, 0xe631, 0x080c, 0x6d7b, 0x007e, 0x003e, 0x001e, 0x080c, - 0xca21, 0x080c, 0xac1a, 0x00ce, 0x0804, 0x926c, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x926c, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, - 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, - 0x0076, 0x080c, 0xe631, 0x080c, 0xe27c, 0x007e, 0x003e, 0x001e, - 0x08c0, 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, - 0x0036, 0x0076, 0x080c, 0x6d7b, 0x080c, 0xabdf, 0x007e, 0x003e, - 0x001e, 0x0848, 0x6020, 0x9086, 0x000a, 0x0904, 0x92b8, 0x0804, - 0x92b1, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, - 0x0126, 0x2091, 0x8000, 0x2079, 0x19e6, 0x7848, 0x9065, 0x0904, - 0x936d, 0x600c, 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, 0x11a0, - 0x0036, 0x2019, 0x0001, 0x080c, 0xa0fa, 0x783f, 0x0000, 0x901e, - 0x7b4e, 0x7b6a, 0x7b52, 0x7b6e, 0x003e, 0x000e, 0x9005, 0x1118, - 0x600c, 0x600f, 0x0000, 0x0006, 0x00e6, 0x2f70, 0x080c, 0x9250, - 0x00ee, 0x080c, 0xc832, 0x0548, 0x6014, 0x2048, 0x6020, 0x9086, - 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002, 0x1188, 0x6010, 0x9005, - 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6048, - 0x9005, 0x11c0, 0x2001, 0x1987, 0x2004, 0x604a, 0x0098, 0x6004, - 0x9086, 0x0040, 0x090c, 0xa31a, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6d6f, 0x080c, 0xca21, 0x6044, 0xc0fc, 0x6046, - 0x080c, 0xac1a, 0x000e, 0x0804, 0x9316, 0x7e4a, 0x7e46, 0x012e, - 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1118, 0x080c, 0xe27c, 0x0c38, 0x6020, 0x9086, - 0x0009, 0x1130, 0xab7a, 0x080c, 0x6d7b, 0x080c, 0xabdf, 0x0c10, - 0x6020, 0x9086, 0x000a, 0x0990, 0x0850, 0x0016, 0x0026, 0x0086, - 0x9046, 0x00a9, 0x080c, 0x947e, 0x008e, 0x002e, 0x001e, 0x0005, - 0x00f6, 0x0126, 0x2079, 0x19e6, 0x2091, 0x8000, 0x080c, 0x94c7, - 0x080c, 0x955b, 0x080c, 0x67ad, 0x012e, 0x00fe, 0x0005, 0x00b6, - 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7620, 0x2660, 0x2678, - 0x8cff, 0x0904, 0x9443, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, - 0x943e, 0x88ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x943e, 0x7030, - 0x9c06, 0x1570, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, - 0x86d5, 0x080c, 0x9e16, 0x68c3, 0x0000, 0x080c, 0xa31a, 0x7033, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, 0x080c, 0x2a29, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, - 0x7008, 0xc0ad, 0x700a, 0x6003, 0x0009, 0x630a, 0x0804, 0x943e, - 0x7020, 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, - 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, - 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, - 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, 0x6014, 0x2048, 0x080c, - 0xc832, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xca47, - 0x1118, 0x080c, 0xb5a6, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xcb35, 0x080c, 0xe631, - 0x080c, 0x6d7b, 0x008e, 0x003e, 0x001e, 0x080c, 0xca21, 0x080c, - 0xac1a, 0x080c, 0xa1f0, 0x00ce, 0x0804, 0x93b8, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x93b8, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xe631, 0x080c, - 0xe27c, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xb5a6, 0x6020, - 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, - 0x0904, 0x9424, 0x9086, 0x008b, 0x0904, 0x9424, 0x0840, 0x6020, - 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, - 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9437, 0x0006, 0x00f6, - 0x00e6, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, - 0x8000, 0x9280, 0x1000, 0x2004, 0x905d, 0x2079, 0x19e6, 0x9036, - 0x7828, 0x2060, 0x8cff, 0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, - 0xffff, 0x080c, 0xaa67, 0x01d8, 0x610c, 0x0016, 0x080c, 0x9f84, - 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, - 0x0036, 0x0086, 0x080c, 0xcb35, 0x080c, 0xe631, 0x080c, 0x6d7b, - 0x008e, 0x003e, 0x001e, 0x080c, 0xac1a, 0x00ce, 0x08d8, 0x2c30, - 0x600c, 0x2060, 0x08b8, 0x080c, 0x67ca, 0x012e, 0x001e, 0x006e, - 0x00ce, 0x00be, 0x009e, 0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, - 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, - 0x952e, 0x600c, 0x0006, 0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, - 0x7830, 0x9c06, 0x1588, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, - 0x080c, 0x86d5, 0x080c, 0x9e16, 0x68c3, 0x0000, 0x080c, 0xa31a, - 0x7833, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, 0x080c, 0x2a29, + 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01e8, 0x080c, + 0xa899, 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, 0x080c, + 0xa1c8, 0x080c, 0xa0b3, 0x901e, 0x080c, 0xa133, 0x080c, 0xa8b5, + 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2a49, 0x080c, 0x77ef, + 0x080c, 0x6044, 0x0804, 0x776b, 0x2001, 0x180c, 0x200c, 0xd1b4, + 0x1160, 0xc1b5, 0x2102, 0x080c, 0x734a, 0x2069, 0x0140, 0x2001, + 0x0080, 0x080c, 0x2a49, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, + 0x9005, 0x1118, 0x6808, 0x9005, 0x0190, 0x6028, 0x9084, 0xfdff, + 0x602a, 0x2011, 0x0200, 0x080c, 0x2a83, 0x2069, 0x198e, 0x7000, + 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x776b, 0x2011, + 0x1e00, 0x080c, 0x2a83, 0x2009, 0x1e00, 0x080c, 0x2a2f, 0x6024, + 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x7727, 0x0006, + 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x85a5, 0x00ee, 0x00de, + 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1a02, 0x7070, 0x00ee, + 0x9005, 0x19e8, 0x0400, 0x0026, 0x2011, 0x7362, 0x080c, 0x8651, + 0x2011, 0x7355, 0x080c, 0x875d, 0x002e, 0x2069, 0x0140, 0x60e3, + 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, + 0x2001, 0x196c, 0x2004, 0x080c, 0x26a4, 0x60e2, 0x2001, 0x180c, + 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, + 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xcf7d, + 0x1904, 0x77d9, 0x7130, 0xd184, 0x1170, 0x080c, 0x337c, 0x0138, + 0xc18d, 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, + 0xd08c, 0x0904, 0x77d9, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, + 0x0016, 0x2019, 0x000e, 0x080c, 0xe286, 0x0156, 0x00b6, 0x20a9, + 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, + 0x080c, 0x6644, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, + 0x080c, 0xe316, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8902, + 0x001e, 0x8108, 0x1f04, 0x77a2, 0x00be, 0x015e, 0x001e, 0xd1ac, + 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x31d4, + 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, + 0x6644, 0x1110, 0x080c, 0x605e, 0x8108, 0x1f04, 0x77cf, 0x00be, + 0x015e, 0x080c, 0x1b04, 0x080c, 0xa899, 0x080c, 0xab61, 0x080c, + 0xa8b5, 0x60e3, 0x0000, 0x080c, 0x6044, 0x080c, 0x741d, 0x00ee, + 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, + 0x197c, 0x2003, 0x0001, 0x0005, 0x2001, 0x197c, 0x2003, 0x0000, + 0x0005, 0x2001, 0x197b, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197b, + 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, + 0x0000, 0x080c, 0x1060, 0x090c, 0x0d7d, 0xa8ab, 0xdcb0, 0x2900, + 0x704e, 0x080c, 0x1060, 0x090c, 0x0d7d, 0xa8ab, 0xdcb0, 0x2900, + 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, + 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, + 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, + 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, + 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, + 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, + 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, + 0x18fa, 0x6807, 0x0001, 0x00de, 0x080c, 0x7de7, 0x9006, 0x00ee, + 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, + 0x7865, 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, + 0x0002, 0x787b, 0x787c, 0x78c8, 0x7923, 0x7a33, 0x7879, 0x7879, + 0x7a5d, 0x080c, 0x0d7d, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, + 0x2003, 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x7ec9, 0xd0a4, + 0x0578, 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1648, 0x1d04, + 0x7899, 0x2001, 0x1a05, 0x200c, 0x8109, 0x0510, 0x2091, 0x6000, + 0x2102, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, + 0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, + 0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x78b8, 0x7882, 0x78b8, + 0x78b6, 0x78b8, 0x78b8, 0x78b8, 0x78b8, 0x78b8, 0x080c, 0x7923, + 0x782c, 0xd09c, 0x090c, 0x7de7, 0x0005, 0x9082, 0x005a, 0x1218, + 0x2100, 0x003b, 0x0c10, 0x080c, 0x7959, 0x0c90, 0x00e3, 0x08e8, + 0x0005, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, + 0x7959, 0x797b, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, + 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, + 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7965, 0x7959, 0x7b4e, + 0x7959, 0x7959, 0x7959, 0x797b, 0x7959, 0x7965, 0x7b8f, 0x7bd0, + 0x7c17, 0x7c2b, 0x7959, 0x7959, 0x797b, 0x7965, 0x798f, 0x7959, + 0x7a07, 0x7cd6, 0x7cf1, 0x7959, 0x797b, 0x7959, 0x798f, 0x7959, + 0x7959, 0x79fd, 0x7cf1, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, + 0x7959, 0x7959, 0x7959, 0x7959, 0x79a3, 0x7959, 0x7959, 0x7959, + 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7959, 0x7e6d, 0x7959, + 0x7e17, 0x7959, 0x7e17, 0x7959, 0x79b8, 0x7959, 0x7959, 0x7959, + 0x7959, 0x7959, 0x7959, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, + 0x1198, 0x782c, 0x080c, 0x7e10, 0xd0a4, 0x0170, 0x7824, 0x2048, + 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, + 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7de7, 0x0005, 0x7959, + 0x7965, 0x7b3a, 0x7959, 0x7965, 0x7959, 0x7965, 0x7965, 0x7959, + 0x7965, 0x7b3a, 0x7965, 0x7965, 0x7965, 0x7965, 0x7965, 0x7959, + 0x7965, 0x7b3a, 0x7959, 0x7959, 0x7965, 0x7959, 0x7959, 0x7959, + 0x7965, 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, + 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, + 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, + 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6d9f, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, + 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7adc, 0x7007, 0x0003, + 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7adc, 0x0005, 0xa864, + 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, + 0x0804, 0x7af7, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, + 0x704b, 0x7af7, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, + 0x7961, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7b13, 0x7007, + 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7b13, 0x0005, + 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7961, + 0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x11a8, 0xa868, + 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x62d4, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, + 0x080c, 0x6d9f, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0d38, + 0x9186, 0x0064, 0x0d20, 0x9186, 0x007c, 0x0d08, 0x9186, 0x0028, + 0x09f0, 0x9186, 0x0038, 0x09d8, 0x9186, 0x0078, 0x09c0, 0x9186, + 0x005f, 0x09a8, 0x9186, 0x0056, 0x0990, 0xa897, 0x4005, 0xa89b, + 0x0001, 0x2001, 0x0030, 0x900e, 0x08a0, 0xa87c, 0x9084, 0x00c0, + 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7d08, 0x2900, + 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, + 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, + 0x7969, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7969, 0x82ff, 0x1138, + 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7a9a, 0x0018, 0x9280, + 0x7a90, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7a7b, 0x080c, + 0x1060, 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, + 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, + 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, + 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, + 0xa17a, 0x810b, 0xa17e, 0x080c, 0x113c, 0xa06c, 0x908e, 0x0100, + 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, + 0x2048, 0x080c, 0x1079, 0x7014, 0x2048, 0x0804, 0x7969, 0x7020, + 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, + 0x711a, 0x0804, 0x7a33, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, + 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7d08, 0x0804, 0x7adc, + 0x7a92, 0x7a96, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, + 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, + 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, + 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, + 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, + 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, + 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, + 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, + 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, + 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, + 0x1178, 0x080c, 0x60d6, 0x1108, 0x0005, 0x080c, 0x6fd3, 0x0126, + 0x2091, 0x8000, 0x080c, 0xcb68, 0x080c, 0x6d9f, 0x012e, 0x0ca0, + 0x080c, 0xcf7d, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, + 0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, + 0x0000, 0x080c, 0x6164, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6d9f, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, + 0x2001, 0x0000, 0x0c90, 0x2009, 0x1834, 0x210c, 0x81ff, 0x11d8, + 0xa888, 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, + 0x080c, 0x6236, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, 0x61b1, + 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, + 0x6d9f, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, + 0x0000, 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, + 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, + 0x2048, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, + 0x0001, 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, + 0x20a9, 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, + 0x9096, 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, 0x080c, 0x6644, + 0x11b8, 0x0066, 0xae80, 0x080c, 0x6754, 0x006e, 0x0088, 0x0046, + 0x2011, 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, + 0x6644, 0x1110, 0x080c, 0x6927, 0x8108, 0x1f04, 0x7b77, 0x00ce, + 0xa87c, 0xd084, 0x1120, 0x080c, 0x1079, 0x00be, 0x0005, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x00be, 0x0005, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6a8a, 0x0580, 0x2061, + 0x1a6e, 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, + 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, + 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, + 0x2001, 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, + 0x6006, 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, + 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x7dd1, 0x012e, + 0x0804, 0x7dcb, 0x012e, 0x0804, 0x7dc5, 0x012e, 0x0804, 0x7dc8, + 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6a8a, 0x05e0, + 0x2061, 0x1a6e, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, + 0x1530, 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, + 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, + 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, + 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, + 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, + 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, + 0x7dd1, 0x012e, 0x0804, 0x7dce, 0x012e, 0x0804, 0x7dcb, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1a6e, 0x6300, 0xd38c, + 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x7ddf, + 0x012e, 0x0804, 0x7dce, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x7007, 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a6e, + 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, + 0x05d8, 0xa88c, 0x9065, 0x0598, 0x2001, 0x1834, 0x2004, 0x9005, + 0x0118, 0x080c, 0xac2b, 0x0068, 0x6017, 0xf400, 0x6063, 0x0000, + 0xa97c, 0xd1a4, 0x0110, 0xa980, 0x6162, 0x2009, 0x0041, 0x080c, + 0xac8d, 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, + 0x900e, 0x2011, 0xfdff, 0x080c, 0x8902, 0x002e, 0xa87c, 0xd0c4, + 0x0148, 0x2061, 0x1a6e, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, + 0x0208, 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7dd1, 0x00ce, + 0x012e, 0x00be, 0x0804, 0x7dcb, 0xa984, 0x9186, 0x002e, 0x0d30, + 0x9186, 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, + 0x1130, 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, + 0x0020, 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, 0x080c, 0x6644, + 0x1968, 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, + 0x6007, 0x0024, 0x2001, 0x1985, 0x2004, 0x601a, 0x0804, 0x7c66, + 0xa88c, 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, + 0x2004, 0x9005, 0x0150, 0x080c, 0xac2b, 0x8eff, 0x0118, 0x2e60, + 0x080c, 0xac2b, 0x00ee, 0x0804, 0x7c66, 0x6024, 0xc0dc, 0xc0d5, + 0x6026, 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, + 0x003b, 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, 0x2009, + 0x8020, 0x080c, 0x9239, 0x00ee, 0x0804, 0x7c66, 0x2061, 0x1a6e, + 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x7ddf, 0x0126, 0x2091, + 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x7ddf, + 0x012e, 0xa883, 0x0016, 0x0804, 0x7dd8, 0xa883, 0x0007, 0x0804, + 0x7dd8, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, + 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x7961, 0x0040, 0x7007, + 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7d08, 0x0005, + 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, + 0x61d0, 0x81ff, 0x1904, 0x7d8a, 0x6130, 0xd194, 0x1904, 0x7db4, + 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x0a04, 0x7d7e, 0x6068, 0x9e02, + 0x1a04, 0x7d7e, 0x7120, 0x9186, 0x0006, 0x1904, 0x7d70, 0x7010, + 0x905d, 0x0904, 0x7d8a, 0xb800, 0xd0e4, 0x1904, 0x7dae, 0x2061, + 0x1a6e, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, + 0xd0dc, 0x1904, 0x7db7, 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, + 0x7014, 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7dba, + 0x080c, 0x56f5, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, + 0x080c, 0x87f2, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, + 0x9005, 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7dba, + 0x012e, 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, + 0x00be, 0x0804, 0x7dd8, 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, + 0xa974, 0x080c, 0x6644, 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, + 0x9186, 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, + 0x0478, 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, + 0x0035, 0x0430, 0x080c, 0x56f9, 0xd0fc, 0x01e8, 0xa878, 0x2070, + 0x9e82, 0x1ddc, 0x02c0, 0x6068, 0x9e02, 0x12a8, 0x7120, 0x9186, + 0x0006, 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, + 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x7d14, 0x7003, + 0x0002, 0x0804, 0x7d14, 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, + 0x012e, 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, + 0x0045, 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, + 0xde67, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, + 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, + 0x0010, 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x0005, 0x080c, + 0x1079, 0x0005, 0x00d6, 0x080c, 0x87e9, 0x00de, 0x0005, 0x00d6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, + 0x01d8, 0x908c, 0x0780, 0x190c, 0x7ec9, 0xd09c, 0x11a8, 0x2071, + 0x1800, 0x70c0, 0x90ea, 0x0020, 0x0278, 0x8001, 0x70c2, 0x702c, + 0x2048, 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, + 0x2900, 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, + 0x0006, 0x9084, 0x0780, 0x190c, 0x7ec9, 0x000e, 0x0005, 0xa898, + 0x9084, 0x0003, 0x05a8, 0x080c, 0xab9a, 0x05d8, 0x2900, 0x6016, + 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x1138, 0x6028, 0xc0fd, + 0x602a, 0x2001, 0x196a, 0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, + 0xa99c, 0x918c, 0xff00, 0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, + 0x2630, 0x1540, 0x00b6, 0x080c, 0x6644, 0x2b00, 0x00be, 0x1510, + 0x6012, 0x6023, 0x0001, 0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, + 0x9086, 0x0035, 0x0110, 0x2009, 0x0041, 0x080c, 0xac8d, 0x0005, + 0xa87b, 0x0101, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, + 0x0005, 0xa87b, 0x002c, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, + 0x012e, 0x0005, 0xa87b, 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6d9f, 0x012e, 0x080c, 0xabf0, 0x0005, 0x00d6, 0x00c6, 0x0036, + 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, + 0x1a04, 0x7eba, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, + 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, + 0x1108, 0x04b0, 0x2b10, 0x080c, 0xab9a, 0x1118, 0x080c, 0xac60, + 0x05a8, 0x6212, 0xa874, 0x0002, 0x7e98, 0x7e9d, 0x7ea0, 0x7ea6, + 0x2019, 0x0002, 0x080c, 0xe286, 0x0060, 0x080c, 0xe216, 0x0048, + 0x2019, 0x0002, 0xa980, 0x080c, 0xe235, 0x0018, 0xa980, 0x080c, + 0xe216, 0x080c, 0xabf0, 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6d9f, 0x012e, 0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00de, 0x0005, 0xa887, 0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, + 0xa887, 0x0005, 0x0c50, 0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, + 0x0c20, 0x2091, 0x8000, 0x0e04, 0x7ecb, 0x0006, 0x0016, 0x2001, + 0x8003, 0x0006, 0x0804, 0x0d86, 0x2001, 0x1834, 0x2004, 0x9005, + 0x0005, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, + 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, + 0x080c, 0x1622, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, + 0x781f, 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, 0x7f4c, + 0x68c0, 0x90aa, 0x0005, 0x0a04, 0x855d, 0x7d44, 0x7c40, 0xd59c, + 0x190c, 0x0d7d, 0x9584, 0x00f6, 0x1508, 0x9484, 0x7000, 0x0138, + 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, 0x8007, 0x04f0, 0x7000, + 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, 0x00b0, 0x9484, 0x0fff, + 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, + 0xe727, 0x080c, 0x8444, 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, + 0x1118, 0x080c, 0x84a0, 0x19c8, 0xd5a4, 0x0148, 0x0046, 0x0056, + 0x080c, 0x7f9c, 0x080c, 0x213e, 0x005e, 0x004e, 0x0020, 0x080c, + 0xe727, 0x7817, 0x0140, 0x080c, 0x74ec, 0x0168, 0x2001, 0x0111, + 0x2004, 0xd08c, 0x0140, 0x6893, 0x0000, 0x2001, 0x0110, 0x2003, + 0x0008, 0x2003, 0x0000, 0x0489, 0x0005, 0x0002, 0x7f59, 0x8266, + 0x7f56, 0x7f56, 0x7f56, 0x7f56, 0x7f56, 0x7f56, 0x7817, 0x0140, + 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, + 0x0fff, 0x6892, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, + 0x1118, 0x080c, 0x5756, 0x0070, 0x080c, 0x7fbc, 0x0058, 0x9286, + 0x3000, 0x1118, 0x080c, 0x81a3, 0x0028, 0x9286, 0x8000, 0x1110, + 0x080c, 0x837a, 0x7817, 0x0140, 0x0005, 0x2001, 0x1810, 0x2004, + 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, + 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x4b29, 0x003e, + 0x002e, 0x0005, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, + 0x2019, 0xfffe, 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, + 0x2079, 0x0200, 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, + 0x2004, 0xd08c, 0x0160, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, + 0x1130, 0x0026, 0x2011, 0x8048, 0x080c, 0x4b29, 0x002e, 0x00fe, + 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, + 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, + 0x8174, 0x9186, 0x0023, 0x15c0, 0x080c, 0x840f, 0x0904, 0x8174, + 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, + 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x8174, 0x7124, 0x610a, + 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xac8d, + 0x0804, 0x8174, 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, + 0x2009, 0x0015, 0x080c, 0xac8d, 0x0804, 0x8174, 0x908e, 0x0100, + 0x1904, 0x8174, 0x7034, 0x9005, 0x1904, 0x8174, 0x2009, 0x0016, + 0x080c, 0xac8d, 0x0804, 0x8174, 0x9186, 0x0022, 0x1904, 0x8174, + 0x7030, 0x908e, 0x0300, 0x1580, 0x68dc, 0xd0a4, 0x0528, 0xc0b5, + 0x68de, 0x7100, 0x918c, 0x00ff, 0x697e, 0x7004, 0x6882, 0x00f6, + 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, + 0x2008, 0x080c, 0x2679, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, + 0x080c, 0x2630, 0x695e, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, + 0x2071, 0x1800, 0x70b6, 0x00ee, 0x7034, 0x9005, 0x1904, 0x8174, + 0x2009, 0x0017, 0x0804, 0x8124, 0x908e, 0x0400, 0x1190, 0x7034, + 0x9005, 0x1904, 0x8174, 0x080c, 0x74ec, 0x0120, 0x2009, 0x001d, + 0x0804, 0x8124, 0x68dc, 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, + 0x8124, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x8174, + 0x2009, 0x0018, 0x0804, 0x8124, 0x908e, 0x2010, 0x1120, 0x2009, + 0x0019, 0x0804, 0x8124, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, + 0x0804, 0x8124, 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, + 0x8174, 0x2009, 0x001b, 0x0804, 0x8124, 0x908e, 0x5000, 0x1140, + 0x7034, 0x9005, 0x1904, 0x8174, 0x2009, 0x001c, 0x0804, 0x8124, + 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x8124, 0x908e, + 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8174, 0x2009, 0x0024, + 0x0804, 0x8124, 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, + 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, 0x8124, 0x080c, + 0xd68f, 0x1904, 0x8174, 0x0804, 0x8122, 0x908c, 0xff00, 0x918e, + 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x8124, 0x908e, 0x0f00, + 0x1120, 0x2009, 0x0020, 0x0804, 0x8124, 0x908e, 0x6104, 0x1530, + 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, + 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, + 0x2124, 0x080c, 0x4b29, 0x004e, 0x8108, 0x0f04, 0x80d8, 0x9186, + 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, + 0x202b, 0x0000, 0x2009, 0x0023, 0x0804, 0x8124, 0x908e, 0x6000, + 0x1120, 0x2009, 0x003f, 0x0804, 0x8124, 0x908e, 0x5400, 0x1138, + 0x080c, 0x850d, 0x1904, 0x8174, 0x2009, 0x0046, 0x04a8, 0x908e, + 0x5500, 0x1148, 0x080c, 0x8535, 0x1118, 0x2009, 0x0041, 0x0460, + 0x2009, 0x0042, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, + 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, + 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, + 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, + 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, + 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x2630, 0x1904, 0x8177, 0x080c, 0x65e3, + 0x1904, 0x8177, 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x74ec, + 0x01c0, 0x68dc, 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, + 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, 0x687c, 0x9606, 0x1148, + 0x6880, 0x9506, 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb886, + 0x0080, 0xb884, 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x687c, + 0x9606, 0x1138, 0x6880, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, + 0x0098, 0x080c, 0xab9a, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, + 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, + 0x0016, 0x001e, 0x080c, 0xac8d, 0x00ce, 0x00be, 0x0005, 0x001e, + 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, + 0x080c, 0x4b29, 0x080c, 0xac60, 0x0d90, 0x2b08, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, + 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, + 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, + 0x080c, 0x9240, 0x08a0, 0x080c, 0x3346, 0x1140, 0x7010, 0x9084, + 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, + 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, + 0x11e8, 0x080c, 0x840f, 0x0904, 0x81fe, 0x7124, 0x610a, 0x7030, + 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, + 0x080c, 0xac8d, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, + 0x1568, 0x2009, 0x0016, 0x080c, 0xac8d, 0x0440, 0x9186, 0x0032, + 0x1528, 0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2630, 0x11a8, + 0x080c, 0x65e3, 0x1190, 0xbe12, 0xbd16, 0x080c, 0xab9a, 0x0168, + 0x2b08, 0x6112, 0x080c, 0xccfe, 0x6023, 0x0004, 0x7120, 0x610a, + 0x001e, 0x080c, 0xac8d, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, + 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, + 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, + 0x1120, 0x2009, 0x007f, 0x0804, 0x8260, 0x9596, 0xfffe, 0x1120, + 0x2009, 0x007e, 0x0804, 0x8260, 0x9596, 0xfffc, 0x1118, 0x2009, + 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019, 0x1837, 0x231c, 0xd3ac, + 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, + 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, + 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, + 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, + 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, + 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, + 0x8235, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, + 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, 0x7000, 0x908c, + 0xff00, 0x810f, 0x9184, 0x000f, 0x0002, 0x827d, 0x827d, 0x827d, + 0x8421, 0x827d, 0x8280, 0x82a5, 0x832e, 0x827d, 0x827d, 0x827d, + 0x827d, 0x827d, 0x827d, 0x827d, 0x827d, 0x7817, 0x0140, 0x0005, + 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, 0x9c8c, 0x0003, + 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, 0x6868, 0x9c02, 0x1290, 0x7008, + 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1150, 0x700c, + 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, + 0xac8d, 0x7817, 0x0140, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, + 0x0fff, 0x0904, 0x830a, 0x7110, 0xd1bc, 0x1904, 0x830a, 0x7108, + 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15c8, + 0x81ff, 0x15b8, 0x9080, 0x3388, 0x200d, 0x918c, 0xff00, 0x810f, + 0x2001, 0x0080, 0x9106, 0x0904, 0x830a, 0x9182, 0x0801, 0x1a04, + 0x830a, 0x9190, 0x1000, 0x2204, 0x905d, 0x05e0, 0xbe12, 0xbd16, + 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, 0xff00, 0x9286, 0x0600, + 0x1190, 0x080c, 0xab9a, 0x0598, 0x2b08, 0x7028, 0x6052, 0x702c, + 0x604e, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, + 0x080c, 0xd8f8, 0x00f8, 0x080c, 0x6a8e, 0x1138, 0xb807, 0x0606, + 0x0c40, 0x190c, 0x8202, 0x11b0, 0x0880, 0x080c, 0xab9a, 0x2b08, + 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, + 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x9240, 0x7817, 0x0140, 0x00ce, 0x00be, 0x0005, 0x2001, + 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b29, + 0x080c, 0xac60, 0x0d78, 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, + 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, + 0x0041, 0x2009, 0xa022, 0x080c, 0x9239, 0x08e0, 0x00b6, 0x7110, + 0xd1bc, 0x05d0, 0x7020, 0x2060, 0x9c84, 0x0003, 0x15a8, 0x9c82, + 0x1ddc, 0x0690, 0x6868, 0x9c02, 0x1678, 0x9484, 0x0fff, 0x9082, + 0x000c, 0x0650, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, + 0x9106, 0x1510, 0x700c, 0xb914, 0x9106, 0x11f0, 0x7124, 0x610a, + 0x601c, 0xd0fc, 0x11c8, 0x2001, 0x0271, 0x2004, 0x9005, 0x1180, + 0x9484, 0x0fff, 0x9082, 0x000c, 0x0158, 0x0066, 0x2031, 0x0100, + 0xa001, 0xa001, 0x8631, 0x1de0, 0x006e, 0x601c, 0xd0fc, 0x1120, + 0x2009, 0x0045, 0x080c, 0xac8d, 0x7817, 0x0140, 0x00be, 0x0005, + 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, + 0x0001, 0x0005, 0x080c, 0x3346, 0x1168, 0x7010, 0x9084, 0xff00, + 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, + 0x1208, 0x000b, 0x0005, 0x8391, 0x8392, 0x8391, 0x8391, 0x83f1, + 0x8400, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, + 0x0904, 0x83ef, 0x700c, 0x7108, 0x080c, 0x2630, 0x1904, 0x83ef, + 0x080c, 0x65e3, 0x1904, 0x83ef, 0xbe12, 0xbd16, 0x7110, 0xd1bc, + 0x01d8, 0x080c, 0x6a8e, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, + 0x080c, 0x840f, 0x00ce, 0x05d8, 0x080c, 0xab9a, 0x2b08, 0x05b8, + 0x6112, 0x080c, 0xccfe, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, + 0x0088, 0x080c, 0xac8d, 0x0458, 0x080c, 0x6a8e, 0x0148, 0x9086, + 0x0004, 0x0130, 0x080c, 0x6a96, 0x0118, 0x9086, 0x0004, 0x1180, + 0x080c, 0xab9a, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xccfe, 0x6023, + 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xac8d, 0x0078, + 0x080c, 0xab9a, 0x2b08, 0x0158, 0x6112, 0x080c, 0xccfe, 0x6023, + 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xac8d, 0x00be, + 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x8370, + 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xac8d, 0x0005, + 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x8370, 0x1130, + 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0xac8d, 0x0005, 0x7020, + 0x2060, 0x9c84, 0x0003, 0x1158, 0x9c82, 0x1ddc, 0x0240, 0x2001, + 0x181a, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, + 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, + 0x0003, 0x11b0, 0x9c82, 0x1ddc, 0x0298, 0x6868, 0x9c02, 0x1280, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, + 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0xac8d, + 0x7817, 0x0140, 0x00be, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, + 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, + 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, + 0x9084, 0xf000, 0x9086, 0xc000, 0x05c0, 0x080c, 0xab9a, 0x05a8, + 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, + 0x080c, 0x2630, 0x1590, 0x080c, 0x65e3, 0x1578, 0xbe12, 0xbd16, + 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xccfe, 0x080c, 0x1047, + 0x0500, 0x2900, 0x6062, 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, + 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, + 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, + 0x0001, 0x6003, 0x0001, 0x080c, 0x9240, 0x00fe, 0x009e, 0x00ce, + 0x0005, 0x080c, 0xabf0, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, + 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, + 0x2000, 0x1904, 0x84f7, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, + 0x2004, 0x9005, 0x1904, 0x84f9, 0x7030, 0x908e, 0x0400, 0x0904, + 0x84f9, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, + 0x0300, 0x11d8, 0x2009, 0x1837, 0x210c, 0xd18c, 0x1590, 0xd1a4, + 0x1580, 0x080c, 0x6a4c, 0x0588, 0x68b0, 0x9084, 0x00ff, 0x7100, + 0x918c, 0x00ff, 0x9106, 0x1518, 0x6880, 0x69b0, 0x918c, 0xff00, + 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, + 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, + 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, + 0x840f, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, 0x0300, + 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001, 0x1837, 0x2004, 0x9084, + 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50, 0x0156, 0x0046, 0x0016, + 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x027a, 0x080c, 0xbbc1, + 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, + 0x027e, 0x080c, 0xbbc1, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, + 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, + 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, + 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0272, 0x080c, 0xbbc1, + 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, + 0x0276, 0x080c, 0xbbc1, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, + 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, 0x00f6, 0x2079, 0x0200, + 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, + 0x1800, 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, + 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, + 0xc084, 0x7036, 0x00ee, 0x0005, 0x2071, 0x1a02, 0x7003, 0x0003, + 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x1ddc, + 0x7007, 0x0000, 0x7026, 0x702b, 0x9e6f, 0x7032, 0x7037, 0x9eec, + 0x703f, 0xffff, 0x7042, 0x7047, 0x558c, 0x704a, 0x705b, 0x8724, + 0x080c, 0x1060, 0x090c, 0x0d7d, 0x2900, 0x703a, 0xa867, 0x0003, + 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x1a02, 0x1d04, + 0x8640, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1590, 0x2001, + 0x013c, 0x2004, 0x9005, 0x190c, 0x87ce, 0x2001, 0x1869, 0x2004, + 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d7d, 0x700f, 0x0361, 0x7007, + 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, 0x1800, 0x69ec, 0xd1e4, + 0x1138, 0xd1dc, 0x1118, 0x080c, 0x8792, 0x0010, 0x080c, 0x8769, + 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, + 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, + 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, + 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, + 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, + 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0x9f88, + 0x0010, 0x7034, 0x080f, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, + 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, + 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, + 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, + 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, + 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, + 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, + 0x7004, 0x0002, 0x8668, 0x8669, 0x8693, 0x00e6, 0x2071, 0x1a02, + 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a02, 0x701c, 0x9206, 0x1120, + 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0x1a02, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, + 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, 0x080c, 0x6644, 0x11a8, + 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, 0x0126, 0x2091, 0x8000, + 0x0066, 0xb8d0, 0x9005, 0x0138, 0x0026, 0xba3c, 0x0016, 0x080c, + 0x676f, 0x001e, 0x002e, 0x006e, 0x012e, 0x8108, 0x9182, 0x0800, + 0x1220, 0x8631, 0x0128, 0x7112, 0x0c00, 0x900e, 0x7007, 0x0002, + 0x7112, 0x00be, 0x0005, 0x2031, 0x0010, 0x7014, 0x2060, 0x0126, + 0x2091, 0x8000, 0x6048, 0x9005, 0x0128, 0x8001, 0x604a, 0x1110, + 0x080c, 0xcb7f, 0x6018, 0x9005, 0x0904, 0x86eb, 0x00f6, 0x2079, + 0x0300, 0x7918, 0xd1b4, 0x1904, 0x86fe, 0x781b, 0x2020, 0xa001, + 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, 0x0804, 0x86fe, 0x8001, + 0x601a, 0x0106, 0x781b, 0x2000, 0xa001, 0x7918, 0xd1ac, 0x1dd0, + 0x010e, 0x00fe, 0x1540, 0x6120, 0x9186, 0x0003, 0x0148, 0x9186, + 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, 0xd1c4, 0x1100, + 0x080c, 0xc865, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, + 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, + 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x080c, 0xcfb0, + 0x0110, 0x080c, 0xc546, 0x012e, 0x9c88, 0x001c, 0x7116, 0x2001, + 0x181a, 0x2004, 0x9102, 0x1228, 0x8631, 0x0138, 0x2160, 0x0804, + 0x8697, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x0005, 0x00fe, 0x0c58, + 0x00e6, 0x2071, 0x1a02, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0x1a0b, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x1a02, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x1a0e, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1a02, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, 0x8000, + 0x7056, 0x2001, 0x1a10, 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, + 0x7068, 0xa09a, 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, 0xa08e, + 0x080c, 0x113c, 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, + 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, + 0x85a5, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, + 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x1a02, 0x7172, + 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, + 0x1a02, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, + 0x0005, 0x2069, 0x1800, 0x69ec, 0xd1e4, 0x1518, 0x0026, 0xd1ec, + 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117, 0x9294, 0x00c1, + 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, 0x0007, 0x0110, + 0x69ee, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, 0x8107, 0x9106, + 0x9094, 0x00c1, 0x9184, 0xff3e, 0x9205, 0x68ee, 0x080c, 0x0f12, + 0x002e, 0x0005, 0x69e8, 0x9184, 0x003f, 0x05b8, 0x8109, 0x9184, + 0x003f, 0x01a8, 0x6a54, 0x6874, 0x9202, 0x0220, 0xd1bc, 0x0168, + 0xc1bc, 0x0018, 0xd1bc, 0x1148, 0xc1bd, 0x2110, 0x00e6, 0x2071, + 0x1800, 0x080c, 0x0f34, 0x00ee, 0x0400, 0x69ea, 0x00f0, 0x0026, + 0x8107, 0x9094, 0x0007, 0x0128, 0x8001, 0x8007, 0x9085, 0x0007, + 0x0050, 0x2010, 0x8004, 0x8004, 0x8004, 0x9084, 0x0007, 0x9205, + 0x8007, 0x9085, 0x0028, 0x9086, 0x0040, 0x2010, 0x00e6, 0x2071, + 0x1800, 0x080c, 0x0f34, 0x00ee, 0x002e, 0x0005, 0x0016, 0x00c6, + 0x2009, 0xfff4, 0x210d, 0x2061, 0x0100, 0x60f0, 0x9100, 0x60f3, + 0x0000, 0x2009, 0xfff4, 0x200f, 0x1220, 0x8108, 0x2105, 0x8000, + 0x200f, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x2061, 0x1a6e, 0x00ce, + 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a6e, + 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, + 0x00c6, 0x2061, 0x1a6e, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, + 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, + 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, + 0x88ac, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8885, 0x2009, 0x0006, + 0x080c, 0x88d9, 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, + 0xd0fc, 0x05e0, 0x908c, 0x2023, 0x1568, 0x87ff, 0x1558, 0xa9a8, + 0x81ff, 0x1540, 0x6124, 0x918c, 0x0500, 0x1520, 0x6100, 0x918e, + 0x0007, 0x1500, 0x2009, 0x1869, 0x210c, 0xd184, 0x11d8, 0x6003, + 0x0003, 0x6007, 0x0043, 0x6047, 0xb035, 0x080c, 0x1c28, 0xa87c, + 0xc0dd, 0xa87e, 0x600f, 0x0000, 0x00f6, 0x2079, 0x0380, 0x7818, + 0xd0bc, 0x1de8, 0x7833, 0x0013, 0x2c00, 0x7836, 0x781b, 0x8080, + 0x00fe, 0x0005, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, + 0x88d3, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, + 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, + 0x2009, 0x0043, 0x0804, 0xac8d, 0x0005, 0x87ff, 0x1de8, 0x2009, + 0x0042, 0x0804, 0xac8d, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, + 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, + 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, + 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x88d3, 0x908c, 0x2020, + 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x174b, + 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0xac8d, + 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, + 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, + 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, + 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0xac8d, 0x0005, 0x00b9, + 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0xac8d, 0x0cb0, + 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, + 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, + 0x0001, 0x0096, 0x080c, 0xc865, 0x0518, 0x6014, 0x2048, 0xa982, + 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, + 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a6e, 0x6200, 0xd28c, + 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x6bd4, + 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, 0x87f2, 0x007e, + 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a6e, 0x6000, 0x81ff, + 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, + 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, + 0x9085, 0x0001, 0x0005, 0x2071, 0x1923, 0x7003, 0x0006, 0x7007, + 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x080c, 0x1060, 0x090c, + 0x0d7d, 0xa867, 0x0006, 0xa86b, 0x0001, 0xa8ab, 0xdcb0, 0xa89f, + 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, 0x0005, 0x0096, 0x00e6, + 0x2071, 0x1923, 0x702c, 0x2048, 0x6a2c, 0x721e, 0x6b30, 0x7322, + 0x6834, 0x7026, 0xa896, 0x6838, 0x702a, 0xa89a, 0x6824, 0x7016, + 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148, 0x900e, + 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208, 0x8318, + 0xaa8e, 0xab92, 0x7010, 0xd084, 0x0178, 0xc084, 0x7007, 0x0001, + 0x700f, 0x0000, 0x0006, 0x2009, 0x181d, 0x2104, 0x9082, 0x0007, + 0x2009, 0x1b4d, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, 0x2001, + 0x003b, 0x080c, 0x1693, 0x9006, 0x2071, 0x193c, 0x7002, 0x7006, + 0x702a, 0x00ee, 0x009e, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, + 0x8000, 0x2071, 0x1800, 0x7154, 0x2001, 0x0008, 0x910a, 0x0638, + 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x898c, + 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877, 0x20a9, 0x0007, 0x00c6, + 0x080c, 0xab9a, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, + 0x0089, 0x0126, 0x2091, 0x8000, 0x080c, 0x8b15, 0x012e, 0x1f04, + 0x8998, 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, + 0x0001, 0x0cc8, 0x00e6, 0x00b6, 0x0096, 0x0086, 0x0056, 0x0046, + 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, + 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, + 0x080c, 0x1047, 0x090c, 0x0d7d, 0x2900, 0x6016, 0x2058, 0xac66, + 0x9006, 0xa802, 0xa806, 0xa86a, 0xa87a, 0xa8aa, 0xa887, 0x0005, + 0xa87f, 0x0020, 0x7008, 0xa89a, 0x7010, 0xa89e, 0xae8a, 0xa8af, + 0xffff, 0xa8b3, 0x0000, 0x8109, 0x0160, 0x080c, 0x1047, 0x090c, + 0x0d7d, 0xad66, 0x2b00, 0xa802, 0x2900, 0xb806, 0x2058, 0x8109, + 0x1da0, 0x002e, 0x004e, 0x005e, 0x008e, 0x009e, 0x00be, 0x00ee, + 0x0005, 0x2079, 0x0000, 0x2071, 0x1923, 0x7004, 0x004b, 0x700c, + 0x0002, 0x8a04, 0x89fd, 0x89fd, 0x0005, 0x8a0e, 0x8a6f, 0x8a6f, + 0x8a6f, 0x8a70, 0x8a81, 0x8a81, 0x700c, 0x0cba, 0x0126, 0x2091, + 0x8000, 0x78a0, 0x79a0, 0x9106, 0x0128, 0x78a0, 0x79a0, 0x9106, + 0x1904, 0x8a62, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x0130, 0x2011, + 0x0004, 0x2204, 0xc0c5, 0x2012, 0x0ca8, 0x012e, 0x7018, 0x910a, + 0x1130, 0x7030, 0x9005, 0x05a8, 0x080c, 0x8ab0, 0x0490, 0x1210, + 0x7114, 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, + 0x1888, 0x2014, 0x2001, 0x1935, 0x2004, 0x9100, 0x9202, 0x0e48, + 0x080c, 0x8bff, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, + 0x2048, 0xa873, 0x0001, 0xa976, 0x080c, 0x8d08, 0x2100, 0xa87e, + 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a20, + 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x115b, + 0x1de8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x0130, 0x2011, + 0x0004, 0x2204, 0xc0c5, 0x2012, 0x0ca8, 0x012e, 0x0005, 0x0005, + 0x700c, 0x0002, 0x8a75, 0x8a78, 0x8a77, 0x080c, 0x8a0c, 0x0005, + 0x8001, 0x700e, 0x0096, 0x702c, 0x2048, 0xa974, 0x009e, 0x0011, + 0x0ca0, 0x0005, 0x0096, 0x702c, 0x2048, 0x7018, 0x9100, 0x7214, + 0x921a, 0x1130, 0x701c, 0xa88e, 0x7020, 0xa892, 0x9006, 0x0068, + 0x0006, 0x080c, 0x8d08, 0x2100, 0xaa8c, 0x9210, 0xaa8e, 0x1220, + 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x2f08, 0x9188, + 0x0028, 0x200a, 0x701a, 0x0005, 0x00e6, 0x2071, 0x1923, 0x700c, + 0x0002, 0x8aae, 0x8aae, 0x8aac, 0x700f, 0x0001, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7030, 0x9005, 0x0508, 0x2078, 0x7814, + 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8b1e, 0x00be, + 0x01b0, 0x00e6, 0x2071, 0x193c, 0x080c, 0x8b65, 0x00ee, 0x0178, + 0x0096, 0x080c, 0x1060, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x04d1, + 0x0041, 0x2001, 0x1946, 0x2003, 0x0000, 0x012e, 0x08c8, 0x012e, + 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6, 0x2940, 0x2650, 0x2600, + 0x9005, 0x0180, 0xa864, 0x9084, 0x000f, 0x2068, 0x9d88, 0x1e7a, + 0x2165, 0x0056, 0x2029, 0x0000, 0x080c, 0x8c8d, 0x080c, 0x1e50, + 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f, 0x2004, 0xa88a, 0x00c6, + 0x2f60, 0x080c, 0x174b, 0x00ce, 0x781f, 0x0101, 0x7813, 0x0000, + 0x0126, 0x2091, 0x8000, 0x080c, 0x8b74, 0x012e, 0x008e, 0x00ce, + 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, 0x2078, 0x780c, 0x7032, + 0x2001, 0x1946, 0x2003, 0x0001, 0x0005, 0x00e6, 0x2071, 0x1923, + 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, 0x0005, 0x00d6, 0x00c6, + 0x0026, 0x9b80, 0x8de7, 0x2005, 0x906d, 0x090c, 0x0d7d, 0x9b80, + 0x8ddf, 0x2005, 0x9065, 0x090c, 0x0d7d, 0x6114, 0x2600, 0x9102, + 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085, 0x0001, 0x002e, 0x00ce, + 0x00de, 0x0005, 0x6804, 0xd094, 0x0148, 0x6854, 0xd084, 0x1178, + 0xc085, 0x6856, 0x2011, 0x8026, 0x080c, 0x4b29, 0x684c, 0x0096, + 0x904d, 0x090c, 0x0d7d, 0xa804, 0x8000, 0xa806, 0x009e, 0x9006, + 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, 0xc08d, 0x6856, 0x2011, + 0x8025, 0x080c, 0x4b29, 0x684c, 0x0096, 0x904d, 0x090c, 0x0d7d, + 0xa800, 0x8000, 0xa802, 0x009e, 0x0888, 0x7000, 0x2019, 0x0008, + 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, 0x9005, 0x0020, 0x0210, + 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, 0x7814, 0x9005, 0x090c, + 0x0d7d, 0x781c, 0x9084, 0x0101, 0x9086, 0x0101, 0x190c, 0x0d7d, + 0x2069, 0x193c, 0x6804, 0x9080, 0x193e, 0x2f08, 0x2102, 0x6904, + 0x8108, 0x9182, 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x193e, + 0x2003, 0x0000, 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, + 0x2048, 0xa8a8, 0x0096, 0x2048, 0x9005, 0x190c, 0x1079, 0x009e, + 0xa8ab, 0x0000, 0x080c, 0x0ff9, 0x080c, 0xabf0, 0x00ce, 0x009e, + 0x0005, 0x6020, 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, + 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, + 0x0178, 0x6010, 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, 0x8f1c, + 0x00be, 0x6013, 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, + 0x0005, 0x2009, 0x1927, 0x210c, 0xd194, 0x0005, 0x00e6, 0x2071, + 0x1923, 0x7110, 0xc194, 0xd19c, 0x1118, 0xc185, 0x7007, 0x0000, + 0x7112, 0x2001, 0x003b, 0x080c, 0x1693, 0x00ee, 0x0005, 0x0096, + 0x00d6, 0x9006, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, + 0x702a, 0x7026, 0x702f, 0x0000, 0x080c, 0x8d67, 0x0170, 0x080c, + 0x8d9c, 0x0158, 0x2900, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, + 0x701f, 0x000a, 0x00de, 0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, + 0x0096, 0x0086, 0x00d6, 0x00c6, 0x2071, 0x1930, 0x721c, 0x2100, + 0x9202, 0x1618, 0x080c, 0x8d9c, 0x090c, 0x0d7d, 0x7018, 0x9005, + 0x1160, 0x2900, 0x7002, 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, + 0xa806, 0xa802, 0x7012, 0x701e, 0x0038, 0x2040, 0xa806, 0x2900, + 0xa002, 0x701a, 0xa803, 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, + 0x9080, 0x000a, 0x701e, 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, + 0x008e, 0x009e, 0x00ee, 0x0005, 0x0096, 0x0156, 0x0136, 0x0146, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1930, 0x7300, 0x831f, + 0x831e, 0x831e, 0x9384, 0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, + 0x0003, 0x7104, 0x080c, 0x8d08, 0x810c, 0x2100, 0x9318, 0x8003, + 0x2228, 0x2021, 0x0078, 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, + 0x8004, 0x20a8, 0x23a0, 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, + 0x8d11, 0x2130, 0x7014, 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, + 0x701e, 0x7004, 0x9600, 0x2008, 0x9082, 0x000a, 0x1190, 0x7000, + 0x2048, 0xa800, 0x9005, 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, + 0x8bff, 0x002e, 0x7000, 0x2048, 0xa800, 0x7002, 0x7007, 0x0000, + 0x0008, 0x7106, 0x2500, 0x9212, 0x1904, 0x8c3e, 0x012e, 0x00ee, + 0x014e, 0x013e, 0x015e, 0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x9580, 0x8ddf, 0x2005, 0x9075, 0x090c, + 0x0d7d, 0x080c, 0x8ce3, 0x012e, 0x9580, 0x8ddb, 0x2005, 0x9075, + 0x090c, 0x0d7d, 0x0156, 0x0136, 0x01c6, 0x0146, 0x01d6, 0x831f, + 0x831e, 0x831e, 0x9384, 0x003f, 0x20e0, 0x9384, 0xffc0, 0x9100, + 0x2098, 0xa860, 0x20e8, 0xa95c, 0x2c05, 0x9100, 0x20a0, 0x20a9, + 0x0002, 0x4003, 0x2e0c, 0x2d00, 0x0002, 0x8ccd, 0x8ccd, 0x8ccf, + 0x8ccd, 0x8ccf, 0x8ccd, 0x8ccd, 0x8ccd, 0x8ccd, 0x8ccd, 0x8cd5, + 0x8ccd, 0x8cd5, 0x8ccd, 0x8ccd, 0x8ccd, 0x080c, 0x0d7d, 0x4104, + 0x20a9, 0x0002, 0x4002, 0x4003, 0x0028, 0x20a9, 0x0002, 0x4003, + 0x4104, 0x4003, 0x01de, 0x014e, 0x01ce, 0x013e, 0x015e, 0x00ee, + 0x002e, 0x001e, 0x0005, 0x0096, 0x7014, 0x8001, 0x7016, 0x710c, + 0x2110, 0x00f1, 0x810c, 0x9188, 0x0003, 0x7308, 0x8210, 0x9282, + 0x000a, 0x1198, 0x7008, 0x2048, 0xa800, 0x9005, 0x0158, 0x0006, + 0x080c, 0x8dab, 0x009e, 0xa807, 0x0000, 0x2900, 0x700a, 0x7010, + 0x8001, 0x7012, 0x700f, 0x0000, 0x0008, 0x720e, 0x009e, 0x0005, + 0x0006, 0x810b, 0x810b, 0x2100, 0x810b, 0x9100, 0x2008, 0x000e, + 0x0005, 0x0006, 0x0026, 0x2100, 0x9005, 0x0158, 0x9092, 0x000c, + 0x0240, 0x900e, 0x8108, 0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, + 0x0005, 0x900e, 0x0cd8, 0x2d00, 0x90b8, 0x0008, 0x690c, 0x6810, + 0x2019, 0x0001, 0x2031, 0x8d51, 0x9112, 0x0220, 0x0118, 0x8318, + 0x2208, 0x0cd0, 0x6808, 0x9005, 0x0108, 0x8318, 0x233a, 0x6804, + 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, + 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, + 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, + 0x0cd0, 0x6c1a, 0x2d00, 0x90b8, 0x0007, 0x00e6, 0x2071, 0x1800, + 0x7128, 0x6810, 0x2019, 0x0001, 0x910a, 0x0118, 0x0210, 0x8318, + 0x0cd8, 0x2031, 0x8d64, 0x0870, 0x6c16, 0x00ee, 0x0005, 0x0096, + 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, 0x9080, 0x8de3, 0x2005, + 0x9005, 0x090c, 0x0d7d, 0x2004, 0x90a0, 0x000a, 0x080c, 0x1060, + 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x080c, + 0x1060, 0x0188, 0x7024, 0xa802, 0xa807, 0x0000, 0x2900, 0x7026, + 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, 0x9085, 0x0001, 0x012e, + 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, 0x0dc8, 0x2048, 0xac00, + 0x080c, 0x1079, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x7024, + 0x2048, 0x9005, 0x0130, 0xa800, 0x7026, 0xa803, 0x0000, 0xa807, + 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024, 0xa802, + 0x2900, 0x7026, 0x012e, 0x0005, 0x0096, 0x9e80, 0x0009, 0x2004, + 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x1079, 0x000e, + 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, 0x9005, 0x0138, 0x2048, + 0xa800, 0x0006, 0x080c, 0x1079, 0x000e, 0x0cb8, 0x9006, 0x7002, + 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, 0x7022, 0x702a, 0x7026, + 0x702e, 0x009e, 0x0005, 0x1a6c, 0x0000, 0x0000, 0x0000, 0x1930, + 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, 0x0000, 0x0000, 0x1877, + 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, 0x00b6, 0x00a6, 0xa8a8, + 0x2040, 0x2071, 0x1877, 0x080c, 0x8f07, 0xa067, 0x0023, 0x6010, + 0x905d, 0x0904, 0x8edc, 0xb814, 0xa06e, 0xb910, 0xa172, 0xb9a0, + 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834, 0xa082, 0xa07b, 0x0000, + 0xa898, 0x9005, 0x0118, 0xa078, 0xc085, 0xa07a, 0x2858, 0x2031, + 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c, 0x0d7d, 0x2020, 0x2050, + 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, 0x000f, 0x91e0, 0x1e7a, + 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, 0x908a, 0x0036, 0x1a0c, + 0x0d7d, 0x9082, 0x001b, 0x0002, 0x8e47, 0x8e47, 0x8e49, 0x8e47, + 0x8e47, 0x8e47, 0x8e4b, 0x8e47, 0x8e47, 0x8e47, 0x8e4d, 0x8e47, + 0x8e47, 0x8e47, 0x8e4f, 0x8e47, 0x8e47, 0x8e47, 0x8e51, 0x8e47, + 0x8e47, 0x8e47, 0x8e53, 0x8e47, 0x8e47, 0x8e47, 0x8e55, 0x080c, + 0x0d7d, 0xa180, 0x04b8, 0xa190, 0x04a8, 0xa1a0, 0x0498, 0xa1b0, + 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, 0xa1e0, 0x0458, 0x908a, + 0x0034, 0x1a0c, 0x0d7d, 0x9082, 0x001b, 0x0002, 0x8e79, 0x8e77, + 0x8e77, 0x8e77, 0x8e77, 0x8e77, 0x8e7b, 0x8e77, 0x8e77, 0x8e77, + 0x8e77, 0x8e77, 0x8e7d, 0x8e77, 0x8e77, 0x8e77, 0x8e77, 0x8e77, + 0x8e7f, 0x8e77, 0x8e77, 0x8e77, 0x8e77, 0x8e77, 0x8e81, 0x080c, + 0x0d7d, 0xa180, 0x0038, 0xa198, 0x0028, 0xa1b0, 0x0018, 0xa1c8, + 0x0008, 0xa1e0, 0x2600, 0x0002, 0x8e9d, 0x8e9f, 0x8ea1, 0x8ea3, + 0x8ea5, 0x8ea7, 0x8ea9, 0x8eab, 0x8ead, 0x8eaf, 0x8eb1, 0x8eb3, + 0x8eb5, 0x8eb7, 0x8eb9, 0x8ebb, 0x8ebd, 0x8ebf, 0x8ec1, 0x8ec3, + 0x8ec5, 0x8ec7, 0x8ec9, 0x8ecb, 0x8ecd, 0x080c, 0x0d7d, 0xb9e2, + 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448, 0xb9d6, 0x0438, 0xb9d2, + 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408, 0xb9c6, 0x00f8, 0xb9c2, + 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8, 0xb9b6, 0x00b8, 0xb9b2, + 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088, 0xb9a6, 0x0078, 0xb9a2, + 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048, 0xb996, 0x0038, 0xb992, + 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008, 0xb986, 0x8631, 0x8421, + 0x0130, 0x080c, 0x1e50, 0x090c, 0x0d7d, 0x0804, 0x8e21, 0x00ae, + 0x00be, 0x00ce, 0x00ee, 0x0005, 0xa86c, 0xa06e, 0xa870, 0xa072, + 0xa077, 0x00ff, 0x9006, 0x0804, 0x8e03, 0x0006, 0x0016, 0x00b6, + 0x6010, 0x2058, 0xb810, 0x9005, 0x01b0, 0x2001, 0x1924, 0x2004, + 0x9005, 0x0188, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, + 0x0036, 0x0046, 0xbba0, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, + 0x4b29, 0x004e, 0x003e, 0x00be, 0x001e, 0x000e, 0x0005, 0x9016, + 0x710c, 0xa834, 0x910a, 0xa936, 0x7008, 0x9005, 0x0120, 0x8210, + 0x910a, 0x0238, 0x0130, 0x7010, 0x8210, 0x910a, 0x0210, 0x0108, + 0x0cd8, 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x2079, + 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, 0x781b, 0x0202, + 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, 0x9005, 0x01b8, + 0x2068, 0x2079, 0x0000, 0x2c08, 0x911e, 0x1118, 0x680c, 0xb8ae, + 0x0060, 0x9106, 0x0140, 0x2d00, 0x2078, 0x680c, 0x9005, 0x090c, + 0x0d7d, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, + 0x0300, 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, + 0x00d6, 0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, + 0x20a9, 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, + 0x0110, 0x1f04, 0x8f5c, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, + 0xd094, 0x1d90, 0xb8ac, 0x9005, 0x01d0, 0x2060, 0x600c, 0xb8ae, + 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, + 0x6014, 0x2048, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, 0x0000, 0x904d, + 0x090c, 0x0d7d, 0x080c, 0x1079, 0x080c, 0x8b15, 0x0c18, 0x2071, + 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, 0x00ce, 0x009e, + 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, 0x0006, 0x0156, + 0x080c, 0x2630, 0x015e, 0x11b0, 0x080c, 0x65e3, 0x190c, 0x0d7d, + 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, 0xab9a, 0x0140, 0x2b00, + 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, 0xac8d, 0x00be, + 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0x8fce, 0x8fce, + 0x8fce, 0x8fd0, 0x9019, 0x8fce, 0x8fce, 0x8fce, 0x907c, 0x8fce, + 0x90b4, 0x8fce, 0x8fce, 0x8fce, 0x8fce, 0x8fce, 0x080c, 0x0d7d, + 0x9182, 0x0040, 0x0002, 0x8fe3, 0x8fe3, 0x8fe3, 0x8fe3, 0x8fe3, + 0x8fe3, 0x8fe3, 0x8fe3, 0x8fe3, 0x8fe5, 0x8ff6, 0x8fe3, 0x8fe3, + 0x8fe3, 0x8fe3, 0x9007, 0x080c, 0x0d7d, 0x0096, 0x6114, 0x2148, + 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, + 0x080c, 0x6b9f, 0x080c, 0xabf0, 0x009e, 0x0005, 0x080c, 0x965a, + 0x00d6, 0x6114, 0x080c, 0xc865, 0x0130, 0x0096, 0x6114, 0x2148, + 0x080c, 0x6d9f, 0x009e, 0x00de, 0x080c, 0xabf0, 0x0005, 0x080c, + 0x965a, 0x080c, 0x320f, 0x6114, 0x0096, 0x2148, 0x080c, 0xc865, + 0x0120, 0xa87b, 0x0029, 0x080c, 0x6d9f, 0x009e, 0x080c, 0xabf0, + 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, 0x0002, 0x9034, + 0x9034, 0x9034, 0x9034, 0x9034, 0x9034, 0x9034, 0x9034, 0x9036, + 0x9034, 0x9034, 0x9034, 0x9078, 0x9034, 0x9034, 0x9034, 0x9034, + 0x9034, 0x9034, 0x903c, 0x9034, 0x080c, 0x0d7d, 0x6114, 0x2148, + 0xa938, 0x918e, 0xffff, 0x05e0, 0x00e6, 0x6114, 0x2148, 0x080c, + 0x8deb, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6b37, 0x009e, 0xa8ab, + 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x8f1c, + 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8b1e, 0x00be, + 0x01e0, 0x2071, 0x193c, 0x080c, 0x8b65, 0x01b8, 0x9086, 0x0001, + 0x1128, 0x2001, 0x1946, 0x2004, 0x9005, 0x1178, 0x0096, 0x080c, + 0x1047, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, 0x080c, + 0x8ad9, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8b15, 0x0cd0, + 0x080c, 0x9130, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, 0x0002, + 0x9090, 0x9090, 0x9090, 0x9092, 0x9090, 0x9090, 0x9090, 0x90b2, + 0x9090, 0x9090, 0x9090, 0x9090, 0x9090, 0x9090, 0x9090, 0x9090, + 0x080c, 0x0d7d, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa8ac, + 0xa836, 0xa8b0, 0xa83a, 0xa847, 0x0000, 0xa84b, 0x0000, 0xa884, + 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, + 0x9210, 0x621a, 0x080c, 0x1bdf, 0x2009, 0x8030, 0x080c, 0x9280, + 0x009e, 0x0005, 0x080c, 0x0d7d, 0x080c, 0x965a, 0x6114, 0x2148, + 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, + 0x080c, 0x6d9f, 0x080c, 0xabf0, 0x009e, 0x0005, 0x080c, 0xa899, + 0x6144, 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0096, 0x0023, 0x009e, 0x080c, + 0xa8b5, 0x0005, 0x90ea, 0x90ea, 0x90ea, 0x90ec, 0x90fd, 0x90ea, + 0x90ea, 0x90ea, 0x90ea, 0x90ea, 0x90ea, 0x90ea, 0x90ea, 0x90ea, + 0x90ea, 0x90ea, 0x080c, 0x0d7d, 0x080c, 0xaa2d, 0x6114, 0x2148, + 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, + 0x080c, 0x6d9f, 0x080c, 0xabf0, 0x0005, 0x0491, 0x0005, 0x080c, + 0xa899, 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120, 0x6003, + 0x0003, 0x2009, 0x0003, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0096, + 0x0033, 0x009e, 0x0106, 0x080c, 0xa8b5, 0x010e, 0x0005, 0x9127, + 0x9127, 0x9127, 0x9129, 0x9130, 0x9127, 0x9127, 0x9127, 0x9127, + 0x9127, 0x9127, 0x9127, 0x9127, 0x9127, 0x9127, 0x9127, 0x080c, + 0x0d7d, 0x0036, 0x00e6, 0x080c, 0xaa2d, 0x00ee, 0x003e, 0x0005, + 0x00f6, 0x00e6, 0x601b, 0x0000, 0x6014, 0x2048, 0x6010, 0x9005, + 0x0128, 0x00b6, 0x2058, 0x080c, 0x8f1c, 0x00be, 0x2071, 0x193c, + 0x080c, 0x8b65, 0x0160, 0x2001, 0x187f, 0x2004, 0xa88a, 0x2031, + 0x0000, 0x2c78, 0x080c, 0x8ad9, 0x00ee, 0x00fe, 0x0005, 0x0096, + 0xa88b, 0x0000, 0xa8a8, 0x2048, 0x080c, 0x1079, 0x009e, 0xa8ab, + 0x0000, 0x080c, 0x8b15, 0x0c80, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000, 0x0036, + 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086, 0x818e, 0x1208, + 0x9200, 0x1f04, 0x9175, 0x8086, 0x818e, 0x004e, 0x003e, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, + 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d, 0x0228, 0x911a, + 0x1220, 0x1f04, 0x918c, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, + 0x918c, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, + 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, + 0x0126, 0x2091, 0x2800, 0x2079, 0x19e6, 0x012e, 0x00d6, 0x2069, + 0x19e6, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, + 0x2069, 0x0200, 0x080c, 0xa68e, 0x04a9, 0x080c, 0xa679, 0x0491, + 0x080c, 0xa67c, 0x0479, 0x080c, 0xa67f, 0x0461, 0x080c, 0xa682, + 0x0449, 0x080c, 0xa685, 0x0431, 0x080c, 0xa688, 0x0419, 0x080c, + 0xa68b, 0x0401, 0x01de, 0x014e, 0x015e, 0x6857, 0x0000, 0x00f6, + 0x2079, 0x0380, 0x00f9, 0x7807, 0x0003, 0x7803, 0x0000, 0x7803, + 0x0001, 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe, 0x9085, 0x8000, + 0x206a, 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc, 0x682a, 0x00fe, + 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, + 0x4004, 0x0005, 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, + 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, 0x1aee, 0x781f, 0xff00, + 0x781b, 0xff00, 0x2061, 0x1ae3, 0x602f, 0x19e6, 0x6033, 0x1800, + 0x6037, 0x1a02, 0x603b, 0x1e7a, 0x603f, 0x1e8a, 0x6042, 0x6047, + 0x1ab9, 0x00ce, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0001, 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, + 0x2061, 0x19e6, 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, + 0x9080, 0x0003, 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, + 0x0cd8, 0x6146, 0x2c08, 0x2001, 0x0012, 0x080c, 0xa88a, 0x0005, + 0x0016, 0x2009, 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, + 0x9084, 0x0007, 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, + 0xa88a, 0x0088, 0x00c6, 0x2061, 0x19e6, 0x602c, 0x8000, 0x602e, + 0x600c, 0x9005, 0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, + 0x6112, 0x610e, 0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, + 0x9084, 0x0007, 0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, + 0x0000, 0x2c08, 0x2061, 0x19e6, 0x6044, 0x9005, 0x0130, 0x9080, + 0x0003, 0x2102, 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, + 0x6146, 0x600f, 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xa88a, + 0x0005, 0x6044, 0xd0dc, 0x0110, 0x080c, 0xa327, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, + 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e6, + 0x7648, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x930c, + 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x9307, 0x87ff, 0x0120, + 0x605c, 0x9106, 0x1904, 0x9307, 0x704c, 0x9c06, 0x1178, 0x0036, + 0x2019, 0x0001, 0x080c, 0xa133, 0x703f, 0x0000, 0x9006, 0x704e, + 0x706a, 0x7052, 0x706e, 0x003e, 0x2029, 0x0001, 0x0811, 0x7048, + 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xc865, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, + 0x0003, 0x1588, 0x6004, 0x9086, 0x0040, 0x090c, 0xa327, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0xcb68, 0x080c, 0xe66e, 0x080c, 0x6d9f, 0x007e, 0x003e, 0x001e, + 0x080c, 0xca54, 0x080c, 0xac2b, 0x00ce, 0x0804, 0x92a5, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x92a5, 0x012e, 0x000e, 0x001e, 0x002e, + 0x003e, 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0076, 0x080c, 0xe66e, 0x080c, 0xe2b9, 0x007e, 0x003e, + 0x001e, 0x08c0, 0x6020, 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, + 0x0016, 0x0036, 0x0076, 0x080c, 0x6d9f, 0x080c, 0xabf0, 0x007e, + 0x003e, 0x001e, 0x0848, 0x6020, 0x9086, 0x000a, 0x0904, 0x92f1, + 0x0804, 0x92ea, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, + 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, 0x19e6, 0x7848, 0x9065, + 0x0904, 0x93a6, 0x600c, 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, + 0x11a0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa133, 0x783f, 0x0000, + 0x901e, 0x7b4e, 0x7b6a, 0x7b52, 0x7b6e, 0x003e, 0x000e, 0x9005, + 0x1118, 0x600c, 0x600f, 0x0000, 0x0006, 0x00e6, 0x2f70, 0x080c, + 0x9289, 0x00ee, 0x080c, 0xc865, 0x0548, 0x6014, 0x2048, 0x6020, + 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002, 0x1188, 0x6010, + 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, + 0x6048, 0x9005, 0x11c0, 0x2001, 0x1987, 0x2004, 0x604a, 0x0098, + 0x6004, 0x9086, 0x0040, 0x090c, 0xa327, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0x6d93, 0x080c, 0xca54, 0x6044, 0xc0fc, + 0x6046, 0x080c, 0xac2b, 0x000e, 0x0804, 0x934f, 0x7e4a, 0x7e46, + 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, + 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xe2b9, 0x0c38, 0x6020, + 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x6d9f, 0x080c, 0xabf0, + 0x0c10, 0x6020, 0x9086, 0x000a, 0x0990, 0x0850, 0x0016, 0x0026, + 0x0086, 0x9046, 0x00a9, 0x080c, 0x94b7, 0x008e, 0x002e, 0x001e, + 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e6, 0x2091, 0x8000, 0x080c, + 0x9500, 0x080c, 0x9594, 0x080c, 0x67d1, 0x012e, 0x00fe, 0x0005, + 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7620, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x947c, 0x6010, 0x2058, 0xb8a0, 0x9206, + 0x1904, 0x9477, 0x88ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x9477, + 0x7030, 0x9c06, 0x1570, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, + 0x080c, 0x8709, 0x080c, 0x9e4f, 0x68c3, 0x0000, 0x080c, 0xa327, + 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, 0x2a49, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, - 0x0058, 0x080c, 0x6a02, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, - 0xc0ad, 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xc830, - 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xca47, 0x1118, - 0x080c, 0xb5a6, 0x0060, 0x080c, 0x6a02, 0x1168, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d7b, 0x080c, 0xca21, 0x080c, - 0xac1a, 0x080c, 0xa1f0, 0x000e, 0x0804, 0x94ce, 0x7e22, 0x7e1e, - 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xe27c, 0x0c50, 0x080c, 0xb5a6, 0x6020, - 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, - 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, - 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, - 0x008b, 0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, 0x0066, - 0x9036, 0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, 0x0006, - 0x3e08, 0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, 0x6043, - 0xffff, 0x080c, 0xaa67, 0x0180, 0x610c, 0x080c, 0x9f84, 0x6014, - 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d7b, - 0x080c, 0xac1a, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, - 0x00be, 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, - 0x080c, 0x6136, 0x11b0, 0x2071, 0x19e6, 0x7030, 0x9080, 0x0005, - 0x2004, 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19e6, - 0x7030, 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, - 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, - 0x6043, 0xffff, 0x080c, 0xaa67, 0x0178, 0x080c, 0x9f84, 0x6014, - 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xcb35, - 0x080c, 0x6d7b, 0x080c, 0xac1a, 0x00ce, 0x0005, 0x00b6, 0x00e6, - 0x00c6, 0x080c, 0xa888, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, - 0x2072, 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xa8a4, 0x00ce, - 0x00ee, 0x00be, 0x0005, 0x2071, 0x19e6, 0x7030, 0x9005, 0x0da0, - 0x9c06, 0x190c, 0x0d7d, 0x7036, 0x080c, 0x86d5, 0x7004, 0x9084, - 0x0007, 0x0002, 0x95f4, 0x95f6, 0x95fd, 0x9607, 0x9615, 0x95f4, - 0x9602, 0x95f2, 0x080c, 0x0d7d, 0x0428, 0x0005, 0x080c, 0xaa52, - 0x7007, 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, - 0x9f84, 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, - 0xaa3d, 0x0140, 0x080c, 0xaa52, 0x0128, 0x0066, 0x9036, 0x080c, - 0x9f84, 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xaa3d, 0x080c, - 0xa31a, 0x0000, 0x010e, 0x190c, 0xa8a4, 0x00ce, 0x00ee, 0x00be, - 0x0005, 0x00d6, 0x00c6, 0x080c, 0xa888, 0x0106, 0x6044, 0xd0fc, - 0x1130, 0x010e, 0x090c, 0xa8a4, 0x00ce, 0x00de, 0x0005, 0x2069, - 0x19e6, 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d7d, 0x6852, - 0x00e6, 0x2d70, 0x080c, 0x9250, 0x00ee, 0x080c, 0x86e2, 0x0016, - 0x2009, 0x0040, 0x080c, 0x21c1, 0x001e, 0x683c, 0x9084, 0x0003, - 0x0002, 0x964f, 0x9650, 0x966e, 0x964d, 0x080c, 0x0d7d, 0x0460, - 0x6868, 0x9086, 0x0001, 0x0190, 0x600c, 0x9015, 0x0160, 0x6a4a, - 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, 0x9006, 0x7042, 0x684e, - 0x683f, 0x0000, 0x00c8, 0x684a, 0x6846, 0x0ca0, 0x686b, 0x0000, - 0x6848, 0x9065, 0x0d78, 0x6003, 0x0002, 0x0c60, 0x9006, 0x686a, - 0x6852, 0x686e, 0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, 0x0000, - 0x0018, 0x684e, 0x684a, 0x6846, 0x684f, 0x0000, 0x010e, 0x190c, - 0xa8a4, 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, - 0x000b, 0x0005, 0x969a, 0x969d, 0x9b0b, 0x9b9a, 0x969d, 0x9b0b, - 0x9b9a, 0x969a, 0x969d, 0x969a, 0x969a, 0x969a, 0x969a, 0x969a, - 0x969a, 0x969a, 0x080c, 0x95c6, 0x0005, 0x00b6, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, - 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d7d, - 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, - 0x0040, 0x1a04, 0x9709, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x988e, - 0x98c9, 0x98f2, 0x999a, 0x99bc, 0x99c2, 0x99cf, 0x99d7, 0x99e3, - 0x99e9, 0x99fa, 0x99e9, 0x9a52, 0x99d7, 0x9a5e, 0x9a64, 0x99e3, - 0x9a64, 0x9a70, 0x9707, 0x9707, 0x9707, 0x9707, 0x9707, 0x9707, - 0x9707, 0x9707, 0x9707, 0x9707, 0x9707, 0x9fa5, 0x9fc8, 0x9fd9, - 0x9ff9, 0xa02b, 0x99cf, 0x9707, 0x99cf, 0x99e9, 0x9707, 0x98f2, - 0x999a, 0x9707, 0xa418, 0x99e9, 0x9707, 0xa434, 0x99e9, 0x9707, - 0x99e3, 0x9888, 0x972a, 0x9707, 0xa450, 0xa4bd, 0xa59d, 0x9707, - 0xa5aa, 0x99cc, 0xa5d5, 0x9707, 0xa035, 0xa5e1, 0x9707, 0x080c, - 0x0d7d, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xa681, 0xa733, - 0x9728, 0x9751, 0x97fd, 0x9808, 0x9728, 0x99cf, 0x9728, 0x984f, - 0x985b, 0x976c, 0x9728, 0x9787, 0x97bb, 0xaabd, 0xab02, 0x99e9, - 0x080c, 0x0d7d, 0x00d6, 0x0096, 0x080c, 0x9a83, 0x7003, 0x2414, - 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, 0x700e, - 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x9de6, - 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x080c, 0xab49, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x9a83, 0x7003, 0x0500, 0x7814, - 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, - 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, - 0x9de6, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9a83, - 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, - 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, - 0x60c3, 0x0010, 0x080c, 0x9de6, 0x009e, 0x00de, 0x0005, 0x00d6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9a83, 0x20e9, 0x0000, - 0x2001, 0x19a2, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, - 0x21a6, 0x080c, 0xd5be, 0x9006, 0x080c, 0x21a6, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0x9de6, 0x012e, - 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9ace, 0x20e9, 0x0000, 0x2001, 0x19a2, 0x2003, 0x0000, - 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x080c, 0xd5be, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, - 0x080c, 0x0fec, 0x080c, 0x9de6, 0x012e, 0x009e, 0x00de, 0x0005, - 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, - 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9a83, 0x7003, - 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0x9de6, - 0x00d6, 0x00e6, 0x080c, 0x9ace, 0x7814, 0x9084, 0xff00, 0x2073, - 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, 0x2073, - 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, 0x8d68, - 0x8e70, 0x1f04, 0x981e, 0x2069, 0x1801, 0x20a9, 0x0004, 0x2d76, - 0x8d68, 0x8e70, 0x1f04, 0x9827, 0x2069, 0x19b2, 0x9086, 0xdf00, - 0x0110, 0x2069, 0x19cc, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, - 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, - 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x9835, - 0x60c3, 0x004c, 0x080c, 0x9de6, 0x00ee, 0x00de, 0x0005, 0x080c, - 0x9a83, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, - 0x0008, 0x0804, 0x9de6, 0x00d6, 0x0026, 0x0016, 0x080c, 0x9ace, - 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, - 0x0001, 0x2011, 0x000c, 0x2069, 0x1923, 0x6810, 0xd084, 0x1148, - 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, 0x9290, - 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, - 0x710a, 0x62c2, 0x080c, 0x9de6, 0x001e, 0x002e, 0x00de, 0x0005, - 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, 0x9de6, 0x080c, 0x9a83, - 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, 0xd084, 0x0130, 0x6828, - 0x0016, 0x080c, 0x2647, 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, - 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, - 0xab49, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, - 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, 0x7036, 0x0030, 0x2001, - 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, - 0x9de6, 0x080c, 0x9a83, 0x7003, 0x0500, 0x080c, 0xab49, 0x1120, - 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x700a, - 0x2001, 0x1820, 0x2004, 0x700e, 0x0030, 0x2001, 0x1818, 0x2004, - 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, - 0x0804, 0x9de6, 0x080c, 0x9a83, 0x9006, 0x080c, 0x6a34, 0xb8a0, - 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, - 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, 0x9006, 0xa89a, 0xa8a6, - 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, 0x9086, 0x007e, 0x1904, - 0x9961, 0x00d6, 0x2069, 0x196b, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, 0x080c, - 0xab60, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, - 0x7026, 0x0090, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, - 0x74c8, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, - 0x080c, 0xab60, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, - 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, - 0x080c, 0xa668, 0x2069, 0x1973, 0x2071, 0x024e, 0x6800, 0xc0dd, - 0x7002, 0x080c, 0x56d9, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, - 0x04a8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0170, 0x0016, 0x2001, - 0x196c, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, - 0x080c, 0x2688, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196b, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0xa668, 0x20a1, - 0x024e, 0x20a9, 0x0008, 0x2099, 0x1973, 0x4003, 0x60c3, 0x0074, - 0x0804, 0x9de6, 0x080c, 0x9a83, 0x7003, 0x2010, 0x7007, 0x0014, - 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, - 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, - 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x9a33, 0x7026, - 0x60c3, 0x0014, 0x0804, 0x9de6, 0x080c, 0x9a83, 0x7003, 0x5000, - 0x0804, 0x990c, 0x080c, 0x9a83, 0x7003, 0x2110, 0x7007, 0x0014, - 0x60c3, 0x0014, 0x0804, 0x9de6, 0x080c, 0x9ac5, 0x0010, 0x080c, - 0x9ace, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0x9de6, 0x080c, - 0x9ace, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, - 0x0008, 0x0804, 0x9de6, 0x080c, 0x9ace, 0x7003, 0x0200, 0x0804, - 0x990c, 0x080c, 0x9ace, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, - 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0x9de6, 0x00d6, 0x080c, 0x9ace, 0x7003, 0x0210, 0x7007, - 0x0014, 0x700b, 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, - 0x9184, 0x0030, 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, - 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, - 0x0400, 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, - 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, - 0xd1a4, 0x0110, 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, - 0x1110, 0x9085, 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, - 0x0150, 0xc0c5, 0xbad4, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, - 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, - 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, - 0x0804, 0x9de6, 0x080c, 0x9ace, 0x7003, 0x0210, 0x7007, 0x0014, - 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0x9de6, 0x080c, 0x9ace, - 0x7003, 0x0200, 0x0804, 0x9892, 0x080c, 0x9ace, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x9de6, - 0x080c, 0x9ace, 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, - 0x0804, 0x9de6, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, - 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x2200, 0x2021, 0x0100, 0x080c, 0xa67d, 0xb810, 0x9305, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x9dda, - 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, - 0x002e, 0x0005, 0x0026, 0x080c, 0xa67d, 0x7003, 0x02ff, 0x7007, - 0xfffc, 0x00d6, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, - 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, - 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, - 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0xa67d, - 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, - 0x9005, 0x1140, 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, - 0xfffe, 0x0020, 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, - 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x9dda, 0x721a, - 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, - 0x080c, 0x9dda, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, - 0x024c, 0x002e, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, - 0x0d7d, 0x908a, 0x0092, 0x1a0c, 0x0d7d, 0x6110, 0x2158, 0xb984, - 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9b3c, 0x9b4b, 0x9b56, - 0x9b3a, 0x9b3a, 0x9b3a, 0x9b3c, 0x9b3a, 0x9b3a, 0x9b3a, 0x9b3a, - 0x9b3a, 0x9b3a, 0x080c, 0x0d7d, 0x0411, 0x60c3, 0x0000, 0x0026, - 0x080c, 0x2998, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, - 0x002e, 0x0804, 0x9de6, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, - 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0x9de6, 0x0479, 0x7003, - 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, 0x9de6, 0x0026, - 0x080c, 0xa67d, 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, - 0x0804, 0x9a9e, 0x0026, 0x080c, 0xa67d, 0xb810, 0x9085, 0x8400, + 0x0040, 0x7008, 0xc0ad, 0x700a, 0x6003, 0x0009, 0x630a, 0x0804, + 0x9477, 0x7020, 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, + 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, + 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, 0x6014, 0x2048, + 0x080c, 0xc865, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, + 0xca7a, 0x1118, 0x080c, 0xb5c6, 0x0098, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xcb68, 0x080c, + 0xe66e, 0x080c, 0x6d9f, 0x008e, 0x003e, 0x001e, 0x080c, 0xca54, + 0x080c, 0xac2b, 0x080c, 0xa1fd, 0x00ce, 0x0804, 0x93f1, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x93f1, 0x012e, 0x000e, 0x001e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, + 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xe66e, + 0x080c, 0xe2b9, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xb5c6, + 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, + 0x000e, 0x0904, 0x945d, 0x9086, 0x008b, 0x0904, 0x945d, 0x0840, + 0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, + 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9470, 0x0006, + 0x00f6, 0x00e6, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x0016, 0x0126, + 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, 0x905d, 0x2079, 0x19e6, + 0x9036, 0x7828, 0x2060, 0x8cff, 0x0538, 0x6010, 0x9b06, 0x1500, + 0x6043, 0xffff, 0x080c, 0xaa78, 0x01d8, 0x610c, 0x0016, 0x080c, + 0x9fbd, 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, + 0x0016, 0x0036, 0x0086, 0x080c, 0xcb68, 0x080c, 0xe66e, 0x080c, + 0x6d9f, 0x008e, 0x003e, 0x001e, 0x080c, 0xac2b, 0x00ce, 0x08d8, + 0x2c30, 0x600c, 0x2060, 0x08b8, 0x080c, 0x67ee, 0x012e, 0x001e, + 0x006e, 0x00ce, 0x00be, 0x009e, 0x00ee, 0x00fe, 0x000e, 0x0005, + 0x0096, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7820, 0x9065, + 0x0904, 0x9567, 0x600c, 0x0006, 0x6044, 0xc0fc, 0x6046, 0x600f, + 0x0000, 0x7830, 0x9c06, 0x1588, 0x2069, 0x0100, 0x6820, 0xd0a4, + 0x1508, 0x080c, 0x8709, 0x080c, 0x9e4f, 0x68c3, 0x0000, 0x080c, + 0xa327, 0x7833, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, + 0x2a49, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x0058, 0x080c, 0x6a26, 0x1538, 0x6003, 0x0009, 0x630a, + 0x7808, 0xc0ad, 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, + 0xc863, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xca7a, + 0x1118, 0x080c, 0xb5c6, 0x0060, 0x080c, 0x6a26, 0x1168, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d9f, 0x080c, 0xca54, + 0x080c, 0xac2b, 0x080c, 0xa1fd, 0x000e, 0x0804, 0x9507, 0x7e22, + 0x7e1e, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, + 0x9086, 0x0006, 0x1118, 0x080c, 0xe2b9, 0x0c50, 0x080c, 0xb5c6, + 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, + 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, + 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, + 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, + 0x0066, 0x9036, 0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, + 0x0006, 0x3e08, 0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, + 0x6043, 0xffff, 0x080c, 0xaa78, 0x0180, 0x610c, 0x080c, 0x9fbd, + 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0x6d9f, 0x080c, 0xac2b, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, + 0x00ce, 0x00be, 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, + 0x0066, 0x080c, 0x6156, 0x11b0, 0x2071, 0x19e6, 0x7030, 0x9080, + 0x0005, 0x2004, 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, + 0x19e6, 0x7030, 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, + 0x1108, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, + 0x2660, 0x6043, 0xffff, 0x080c, 0xaa78, 0x0178, 0x080c, 0x9fbd, + 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0xcb68, 0x080c, 0x6d9f, 0x080c, 0xac2b, 0x00ce, 0x0005, 0x00b6, + 0x00e6, 0x00c6, 0x080c, 0xa899, 0x0106, 0x2071, 0x0101, 0x2e04, + 0xc0c4, 0x2072, 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xa8b5, + 0x00ce, 0x00ee, 0x00be, 0x0005, 0x2071, 0x19e6, 0x7030, 0x9005, + 0x0da0, 0x9c06, 0x190c, 0x0d7d, 0x7036, 0x080c, 0x8709, 0x7004, + 0x9084, 0x0007, 0x0002, 0x962d, 0x962f, 0x9636, 0x9640, 0x964e, + 0x962d, 0x963b, 0x962b, 0x080c, 0x0d7d, 0x0428, 0x0005, 0x080c, + 0xaa63, 0x7007, 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, + 0x080c, 0x9fbd, 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, + 0x080c, 0xaa4e, 0x0140, 0x080c, 0xaa63, 0x0128, 0x0066, 0x9036, + 0x080c, 0x9fbd, 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xaa4e, + 0x080c, 0xa327, 0x0000, 0x010e, 0x190c, 0xa8b5, 0x00ce, 0x00ee, + 0x00be, 0x0005, 0x00d6, 0x00c6, 0x080c, 0xa899, 0x0106, 0x6044, + 0xd0fc, 0x1130, 0x010e, 0x090c, 0xa8b5, 0x00ce, 0x00de, 0x0005, + 0x2069, 0x19e6, 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d7d, + 0x6852, 0x00e6, 0x2d70, 0x080c, 0x9289, 0x00ee, 0x080c, 0x8716, + 0x0016, 0x2009, 0x0040, 0x080c, 0x21d9, 0x001e, 0x683c, 0x9084, + 0x0003, 0x0002, 0x9688, 0x9689, 0x96a7, 0x9686, 0x080c, 0x0d7d, + 0x0460, 0x6868, 0x9086, 0x0001, 0x0190, 0x600c, 0x9015, 0x0160, + 0x6a4a, 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, 0x9006, 0x7042, + 0x684e, 0x683f, 0x0000, 0x00c8, 0x684a, 0x6846, 0x0ca0, 0x686b, + 0x0000, 0x6848, 0x9065, 0x0d78, 0x6003, 0x0002, 0x0c60, 0x9006, + 0x686a, 0x6852, 0x686e, 0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, + 0x0000, 0x0018, 0x684e, 0x684a, 0x6846, 0x684f, 0x0000, 0x010e, + 0x190c, 0xa8b5, 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, + 0x000f, 0x000b, 0x0005, 0x96d3, 0x96d6, 0x9b44, 0x9bd3, 0x96d6, + 0x9b44, 0x9bd3, 0x96d3, 0x96d6, 0x96d3, 0x96d3, 0x96d3, 0x96d3, + 0x96d3, 0x96d3, 0x96d3, 0x080c, 0x95ff, 0x0005, 0x00b6, 0x0156, + 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, + 0x0d7d, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, + 0x908a, 0x0040, 0x1a04, 0x9742, 0x005b, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, + 0x98c7, 0x9902, 0x992b, 0x99d3, 0x99f5, 0x99fb, 0x9a08, 0x9a10, + 0x9a1c, 0x9a22, 0x9a33, 0x9a22, 0x9a8b, 0x9a10, 0x9a97, 0x9a9d, + 0x9a1c, 0x9a9d, 0x9aa9, 0x9740, 0x9740, 0x9740, 0x9740, 0x9740, + 0x9740, 0x9740, 0x9740, 0x9740, 0x9740, 0x9740, 0x9fde, 0xa001, + 0xa012, 0xa032, 0xa064, 0x9a08, 0x9740, 0x9a08, 0x9a22, 0x9740, + 0x992b, 0x99d3, 0x9740, 0xa425, 0x9a22, 0x9740, 0xa441, 0x9a22, + 0x9740, 0x9a1c, 0x98c1, 0x9763, 0x9740, 0xa45d, 0xa4ca, 0xa5ae, + 0x9740, 0xa5bb, 0x9a05, 0xa5e6, 0x9740, 0xa06e, 0xa5f2, 0x9740, + 0x080c, 0x0d7d, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xa692, + 0xa744, 0x9761, 0x978a, 0x9836, 0x9841, 0x9761, 0x9a08, 0x9761, + 0x9888, 0x9894, 0x97a5, 0x9761, 0x97c0, 0x97f4, 0xaace, 0xab13, + 0x9a22, 0x080c, 0x0d7d, 0x00d6, 0x0096, 0x080c, 0x9abc, 0x7003, + 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, + 0x700e, 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, + 0x9e1f, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, + 0x00be, 0x080c, 0xab5a, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, + 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9abc, 0x7003, 0x0500, + 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, + 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, + 0x080c, 0x9e1f, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, + 0x9abc, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, + 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, + 0x701e, 0x60c3, 0x0010, 0x080c, 0x9e1f, 0x009e, 0x00de, 0x0005, + 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9abc, 0x20e9, + 0x0000, 0x2001, 0x19a2, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, + 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x001b, 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x2001, 0x0001, + 0x080c, 0x21be, 0x080c, 0xd5f1, 0x9006, 0x080c, 0x21be, 0x001e, + 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0x9e1f, + 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9b07, 0x20e9, 0x0000, 0x2001, 0x19a2, 0x2003, + 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, + 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x001b, 0x2098, 0x2001, 0x19a2, 0x0016, 0x200c, 0x080c, 0xd5f1, + 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, + 0x2048, 0x080c, 0x0ff9, 0x080c, 0x9e1f, 0x012e, 0x009e, 0x00de, + 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, + 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9abc, + 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, + 0x9e1f, 0x00d6, 0x00e6, 0x080c, 0x9b07, 0x7814, 0x9084, 0xff00, + 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, + 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, + 0x8d68, 0x8e70, 0x1f04, 0x9857, 0x2069, 0x1801, 0x20a9, 0x0004, + 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9860, 0x2069, 0x19b2, 0x9086, + 0xdf00, 0x0110, 0x2069, 0x19cc, 0x20a9, 0x001a, 0x9e86, 0x0260, + 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, + 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, + 0x986e, 0x60c3, 0x004c, 0x080c, 0x9e1f, 0x00ee, 0x00de, 0x0005, + 0x080c, 0x9abc, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, + 0x60c3, 0x0008, 0x0804, 0x9e1f, 0x00d6, 0x0026, 0x0016, 0x080c, + 0x9b07, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, + 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, 0x1923, 0x6810, 0xd084, + 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, 0x8e70, 0x8108, + 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, + 0x7206, 0x710a, 0x62c2, 0x080c, 0x9e1f, 0x001e, 0x002e, 0x00de, + 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, 0x9e1f, 0x080c, + 0x9abc, 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, 0xd084, 0x0130, + 0x6828, 0x0016, 0x080c, 0x2663, 0x710e, 0x001e, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, + 0x080c, 0xab5a, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, + 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, 0x7036, 0x0030, + 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, + 0x0804, 0x9e1f, 0x080c, 0x9abc, 0x7003, 0x0500, 0x080c, 0xab5a, + 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, + 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, 0x0030, 0x2001, 0x1818, + 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, + 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, + 0x0010, 0x0804, 0x9e1f, 0x080c, 0x9abc, 0x9006, 0x080c, 0x6a58, + 0xb8a0, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, + 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, 0x9006, 0xa89a, + 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, 0x9086, 0x007e, + 0x1904, 0x999a, 0x00d6, 0x2069, 0x196b, 0x2001, 0x1837, 0x2004, + 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, + 0x080c, 0xab71, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, + 0x681c, 0x7026, 0x0090, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, + 0x080c, 0x74ec, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, + 0x7012, 0x080c, 0xab71, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, + 0x00d6, 0x080c, 0xa679, 0x2069, 0x1973, 0x2071, 0x024e, 0x6800, + 0xc0dd, 0x7002, 0x080c, 0x56f9, 0xd0e4, 0x0110, 0x680c, 0x700e, + 0x00de, 0x04a8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0170, 0x0016, + 0x2001, 0x196c, 0x200c, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, + 0x0000, 0x080c, 0x26a4, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, + 0x196b, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, + 0x20a9, 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0xa679, + 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, 0x1973, 0x4003, 0x60c3, + 0x0074, 0x0804, 0x9e1f, 0x080c, 0x9abc, 0x7003, 0x2010, 0x7007, + 0x0014, 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, + 0x1847, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, + 0x0110, 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x9a6c, + 0x7026, 0x60c3, 0x0014, 0x0804, 0x9e1f, 0x080c, 0x9abc, 0x7003, + 0x5000, 0x0804, 0x9945, 0x080c, 0x9abc, 0x7003, 0x2110, 0x7007, + 0x0014, 0x60c3, 0x0014, 0x0804, 0x9e1f, 0x080c, 0x9afe, 0x0010, + 0x080c, 0x9b07, 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0x9e1f, + 0x080c, 0x9b07, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, + 0x60c3, 0x0008, 0x0804, 0x9e1f, 0x080c, 0x9b07, 0x7003, 0x0200, + 0x0804, 0x9945, 0x080c, 0x9b07, 0x7003, 0x0100, 0x782c, 0x9005, + 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, + 0x0008, 0x0804, 0x9e1f, 0x00d6, 0x080c, 0x9b07, 0x7003, 0x0210, + 0x7007, 0x0014, 0x700b, 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, + 0xb99c, 0x9184, 0x0030, 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, + 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, + 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, + 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, + 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, + 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, + 0xd1e4, 0x0150, 0xc0c5, 0xbad4, 0xd28c, 0x1108, 0xc0cd, 0x9094, + 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, + 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, + 0x00de, 0x0804, 0x9e1f, 0x080c, 0x9b07, 0x7003, 0x0210, 0x7007, + 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0x9e1f, 0x080c, + 0x9b07, 0x7003, 0x0200, 0x0804, 0x98cb, 0x080c, 0x9b07, 0x7003, + 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, + 0x9e1f, 0x080c, 0x9b07, 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, + 0x0008, 0x0804, 0x9e1f, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, + 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, 0xa68e, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, - 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x9b00, 0x0026, 0x080c, - 0xa67d, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, 0x7012, - 0x0804, 0x9b00, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, - 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, - 0x0d7d, 0x908a, 0x0057, 0x1a0c, 0x0d7d, 0x7910, 0x2158, 0xb984, - 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x0005, 0x9bcf, 0x9bcf, 0x9bcf, 0x9bf5, - 0x9bcf, 0x9bcf, 0x9bcf, 0x9bcf, 0x9bcf, 0x9bcf, 0x9bcf, 0xa1cd, - 0xa1d5, 0xa1dd, 0xa1e5, 0x9bcf, 0x9bcf, 0x9bcf, 0xa1c5, 0x080c, - 0x0d7d, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, 0xd084, 0x0128, - 0x7a4e, 0x7b14, 0x7b52, 0x722e, 0x732a, 0x9294, 0x00ff, 0xba8e, - 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, - 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0829, - 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016, 0x7814, 0x9084, - 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x9c05, 0x9c05, 0x9c07, - 0x9c05, 0x9c05, 0x9c05, 0x9c21, 0x9c05, 0x080c, 0x0d7d, 0x7914, - 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, - 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, - 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, - 0x9de6, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, - 0x080c, 0xa67d, 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, - 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x9dda, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, - 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028, 0x0110, 0x737c, - 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, - 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, - 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, 0x0000, 0x616e, - 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, - 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848, - 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e, - 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128, 0x609f, 0x0000, - 0x2001, 0x0092, 0x0058, 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, - 0x2011, 0xffff, 0x080c, 0x2a63, 0x2001, 0x00b2, 0x2010, 0x900e, - 0x080c, 0x2a72, 0x2009, 0x07d0, 0x080c, 0x86da, 0x003e, 0x004e, - 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, - 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, - 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, 0x2028, - 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, 0x9094, - 0xff80, 0x1130, 0x9080, 0x3368, 0x2015, 0x9294, 0x00ff, 0x0020, - 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, 0x9582, - 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, 0x6062, - 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, - 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, 0xd0a4, - 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, - 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848, 0x608a, 0xa844, - 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e, 0xb86c, 0x60ce, - 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xba84, 0x629e, - 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x900e, 0x2011, - 0x0092, 0x080c, 0x2a72, 0x2009, 0x07d0, 0x080c, 0x86da, 0x003e, + 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, + 0x9e13, 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, + 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, 0xa68e, 0x7003, 0x02ff, + 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, + 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, + 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, + 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, + 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, + 0xa68e, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, + 0xb810, 0x9005, 0x1140, 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffe, 0x0020, 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, + 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x9e13, + 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, + 0x0005, 0x080c, 0x9e13, 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, + 0x2071, 0x024c, 0x002e, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, + 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, + 0x0a0c, 0x0d7d, 0x908a, 0x0092, 0x1a0c, 0x0d7d, 0x6110, 0x2158, + 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9b75, 0x9b84, + 0x9b8f, 0x9b73, 0x9b73, 0x9b73, 0x9b75, 0x9b73, 0x9b73, 0x9b73, + 0x9b73, 0x9b73, 0x9b73, 0x080c, 0x0d7d, 0x0411, 0x60c3, 0x0000, + 0x0026, 0x080c, 0x29b4, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, + 0x2012, 0x002e, 0x0804, 0x9e1f, 0x0431, 0x7808, 0x700a, 0x7814, + 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0x9e1f, 0x0479, + 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, 0x9e1f, + 0x0026, 0x080c, 0xa68e, 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, + 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, + 0x0009, 0x0804, 0x9ad7, 0x0026, 0x080c, 0xa68e, 0xb810, 0x9085, + 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, + 0x6880, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x9b39, 0x0026, + 0x080c, 0xa68e, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, + 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, + 0x7012, 0x0804, 0x9b39, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, + 0x0a0c, 0x0d7d, 0x908a, 0x0057, 0x1a0c, 0x0d7d, 0x7910, 0x2158, + 0xb984, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x9c08, 0x9c08, 0x9c08, + 0x9c2e, 0x9c08, 0x9c08, 0x9c08, 0x9c08, 0x9c08, 0x9c08, 0x9c08, + 0xa1da, 0xa1e2, 0xa1ea, 0xa1f2, 0x9c08, 0x9c08, 0x9c08, 0xa1d2, + 0x080c, 0x0d7d, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, 0xd084, + 0x0128, 0x7a4e, 0x7b14, 0x7b52, 0x722e, 0x732a, 0x9294, 0x00ff, + 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, + 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, + 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016, 0x7814, + 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x9c3e, 0x9c3e, + 0x9c40, 0x9c3e, 0x9c3e, 0x9c3e, 0x9c5a, 0x9c3e, 0x080c, 0x0d7d, + 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, + 0x00b9, 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, + 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, + 0x0804, 0x9e1f, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, + 0x0016, 0x080c, 0xa68e, 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, + 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, + 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x9e13, 0x721a, + 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, + 0x1800, 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028, 0x0110, + 0x737c, 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140, 0x2001, + 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, 0x2001, + 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, 0x0000, + 0x616e, 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c, 0x8000, + 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, + 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, + 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, + 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, + 0x0000, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128, 0x609f, + 0x0000, 0x2001, 0x0092, 0x0058, 0x6028, 0xc0bd, 0x602a, 0x609f, + 0x00ff, 0x2011, 0xffff, 0x080c, 0x2a83, 0x2001, 0x00b2, 0x2010, + 0x900e, 0x080c, 0x2a92, 0x2009, 0x07d0, 0x080c, 0x870e, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, - 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, - 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, - 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x0002, 0x9d65, 0x9d65, - 0x9d65, 0x9d65, 0x9d65, 0x9d65, 0x9d65, 0x9d65, 0x9d65, 0x9d65, - 0x9d67, 0x9d65, 0x9d65, 0x9d65, 0x9d65, 0x080c, 0x0d7d, 0xb884, - 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, 0xaf90, 0x9784, - 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, - 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, 0xaf94, 0x87ff, - 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, - 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, - 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, - 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, 0xa87c, 0xd0fc, - 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, - 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0xa848, 0x608a, - 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0xb86c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xa65d, 0x2009, 0x07d0, - 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x86da, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, - 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217, 0x0005, 0x00d6, - 0x2069, 0x19e6, 0x686b, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x00f1, 0x080c, 0x86cc, 0x0005, 0x0016, 0x2001, - 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, - 0x080c, 0x86cc, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, - 0x2001, 0x19e7, 0x2003, 0x0000, 0x2001, 0x19f2, 0x2003, 0x0000, - 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, 0x0009, - 0x080c, 0x2a72, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00c6, - 0x0006, 0x080c, 0xa888, 0x0106, 0x2061, 0x0100, 0x61a4, 0x60a7, - 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, 0x0008, 0x080c, - 0x2a72, 0x002e, 0x001e, 0x010e, 0x090c, 0xa8a4, 0x000e, 0xa001, - 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, - 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x74c8, - 0x1510, 0x2001, 0x1a0b, 0x2004, 0x9005, 0x1904, 0x9e95, 0x080c, - 0x7569, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101, 0x6844, 0xd084, - 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, - 0x090c, 0x0d7d, 0x6843, 0x0100, 0x080c, 0x86cc, 0x04b0, 0x00c6, - 0x2061, 0x19e6, 0x00f0, 0x6904, 0x9194, 0x4000, 0x0598, 0x080c, - 0x9e16, 0x080c, 0x2a39, 0x00c6, 0x2061, 0x19e6, 0x6134, 0x9192, - 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0xa888, 0x6130, 0x080c, - 0xa8a4, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x86cc, 0x080c, 0x9e09, - 0x00a0, 0x080c, 0xa888, 0x6130, 0x91e5, 0x0000, 0x0150, 0x080c, - 0xe727, 0x080c, 0x86d5, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, - 0xac7c, 0x080c, 0xa8a4, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, - 0x00ce, 0x0005, 0x2001, 0x1a0b, 0x2004, 0x9005, 0x1db0, 0x00c6, - 0x2061, 0x19e6, 0x6134, 0x9192, 0x0003, 0x1ad8, 0x8108, 0x6136, - 0x00ce, 0x080c, 0x86cc, 0x080c, 0x5edf, 0x2009, 0x1846, 0x2114, - 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, - 0x0026, 0x080c, 0x86e2, 0x080c, 0xa888, 0x2001, 0x0387, 0x2003, - 0x0202, 0x2071, 0x19e6, 0x714c, 0x81ff, 0x0904, 0x9f3d, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x74c8, 0x1510, 0x0036, 0x2019, - 0x0002, 0x080c, 0xa0fa, 0x003e, 0x714c, 0x2160, 0x080c, 0xe727, - 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, - 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, 0xac7c, - 0x2001, 0x0386, 0x2003, 0x5040, 0x080c, 0x7569, 0x0804, 0x9f3d, - 0x6904, 0xd1f4, 0x0904, 0x9f4a, 0x080c, 0x2a39, 0x00c6, 0x704c, - 0x9065, 0x090c, 0x0d7d, 0x6020, 0x00ce, 0x9086, 0x0006, 0x1518, - 0x61c8, 0x60c4, 0x9105, 0x11f8, 0x2009, 0x180c, 0x2104, 0xd0d4, - 0x01d0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, - 0x1560, 0x0010, 0xc0d4, 0x200a, 0x6014, 0x9084, 0xe7fd, 0x9085, - 0x0010, 0x6016, 0x704c, 0x2060, 0x080c, 0x9621, 0x2009, 0x0049, - 0x080c, 0xac7c, 0x00d0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa0fa, - 0x003e, 0x714c, 0x2160, 0x080c, 0xe727, 0x2009, 0x004a, 0x6220, - 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, - 0x004a, 0x6003, 0x0003, 0x080c, 0xac7c, 0x2001, 0x0387, 0x2003, - 0x0200, 0x080c, 0xa8a4, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, - 0x009e, 0x0005, 0xd1ec, 0x1904, 0x9ef4, 0x0804, 0x9ef6, 0x0026, - 0x00e6, 0x2071, 0x19e6, 0x706c, 0xd084, 0x01e8, 0xc084, 0x706e, - 0x714c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, - 0x928e, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, 0x0012, 0x080c, - 0x2a72, 0x0048, 0x928e, 0x0009, 0x0db0, 0x2009, 0x1984, 0x2011, - 0x0016, 0x080c, 0x2a72, 0x00ee, 0x002e, 0x0005, 0x9036, 0x2001, - 0x19f0, 0x2004, 0x9005, 0x0128, 0x9c06, 0x0128, 0x2c30, 0x600c, - 0x0cc8, 0x9085, 0x0001, 0x0005, 0x00f6, 0x2079, 0x19e6, 0x610c, - 0x9006, 0x600e, 0x6044, 0xc0fc, 0x6046, 0x86ff, 0x1140, 0x7824, - 0x9c06, 0x1118, 0x7826, 0x782a, 0x0050, 0x792a, 0x0040, 0x00c6, - 0x2660, 0x610e, 0x00ce, 0x7824, 0x9c06, 0x1108, 0x7e26, 0x080c, - 0xa1f0, 0x080c, 0xca21, 0x00fe, 0x0005, 0x080c, 0x9a83, 0x7003, - 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, 0x9086, - 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb810, - 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, 0x607c, 0x6180, 0x9084, - 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, 0x0804, 0x9de6, - 0x080c, 0x9a83, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, 0xb810, - 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, 0x0804, - 0x9de6, 0x0156, 0x080c, 0x9ace, 0x7003, 0x0200, 0x080c, 0x879a, - 0x20a9, 0x0006, 0x2011, 0xfff4, 0x2019, 0xfff5, 0x9ef0, 0x0002, - 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, - 0x9290, 0x0002, 0x1f04, 0x9fe8, 0x60c3, 0x001c, 0x015e, 0x0804, - 0x9de6, 0x0016, 0x0026, 0x080c, 0x9aaa, 0x080c, 0x9abc, 0x9e80, - 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, 0x2048, 0xa800, - 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x009e, - 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, - 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x9de6, 0x002e, 0x001e, - 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0xa668, 0x20a1, 0x0240, - 0x22a8, 0x4003, 0x0c68, 0x080c, 0x9a83, 0x7003, 0x6200, 0x7808, - 0x700e, 0x60c3, 0x0008, 0x0804, 0x9de6, 0x0016, 0x0026, 0x080c, - 0x9a83, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, 0x2048, - 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, - 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, - 0x080c, 0x9de6, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7010, 0x2060, 0x8cff, - 0x0188, 0x080c, 0xca47, 0x1110, 0x080c, 0xb5a6, 0x600c, 0x0006, - 0x080c, 0xccc3, 0x600f, 0x0000, 0x080c, 0xabdf, 0x080c, 0xa1f0, - 0x00ce, 0x0c68, 0x2c00, 0x7012, 0x700e, 0x012e, 0x000e, 0x00ce, - 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, - 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, - 0x2071, 0x19e6, 0x7030, 0x2060, 0x8cff, 0x0548, 0x080c, 0x9e16, - 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x86d5, 0x00c6, 0x2061, 0x0100, - 0x080c, 0xa7b9, 0x00ce, 0x20a9, 0x01f4, 0x04b1, 0x080c, 0x95c6, - 0x6044, 0xd0ac, 0x1128, 0x2001, 0x1987, 0x2004, 0x604a, 0x0020, - 0x2009, 0x0013, 0x080c, 0xac7c, 0x000e, 0x001e, 0x002e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, - 0x1800, 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, - 0x080c, 0x86d5, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, - 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x5e89, 0x080c, 0x861d, - 0x20a9, 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, - 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, 0x2a39, 0x0090, 0xd084, - 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0xa0dc, 0x7804, 0x9084, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, 0x080c, - 0x2a29, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, - 0x200c, 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, - 0x2071, 0x0380, 0x701c, 0x0006, 0x701f, 0x0202, 0x2071, 0x19e6, - 0x704c, 0x2060, 0x8cff, 0x0904, 0xa19f, 0x9386, 0x0002, 0x1128, - 0x6814, 0x9084, 0x0002, 0x0904, 0xa19f, 0x68af, 0x95f5, 0x6817, - 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, - 0x080c, 0x86e2, 0x080c, 0x1de5, 0x0046, 0x2009, 0x00a5, 0x080c, - 0x0e55, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, 0x0004, - 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, 0x00f6, - 0x2079, 0x0090, 0x2071, 0x19e6, 0x6814, 0x9084, 0x1984, 0x9085, - 0x0012, 0x6816, 0x782b, 0x0008, 0x7057, 0x0000, 0x00fe, 0x00ee, - 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, 0x0001, - 0x0016, 0x2009, 0x0040, 0x080c, 0x21c1, 0x001e, 0x2009, 0x0000, - 0x080c, 0x0e55, 0x004e, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, - 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, 0x2a39, 0x0090, - 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, 0xa16d, 0x7804, - 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, - 0x080c, 0x2a29, 0x6827, 0x4000, 0x6824, 0x83ff, 0x1180, 0x2009, - 0x0049, 0x6020, 0x9086, 0x0009, 0x0150, 0x080c, 0x9621, 0x6044, - 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, 0x080c, 0xac7c, 0x000e, - 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, 0x0200, 0x000e, 0x001e, - 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a06, - 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, - 0x19e6, 0x6a3e, 0x012e, 0x00de, 0x0005, 0x080c, 0x9bd1, 0x785c, - 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, 0x080c, 0x9bd1, 0x785c, - 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, 0x080c, 0x9bd1, 0x785c, - 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, 0x080c, 0x9bd1, 0x785c, - 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, 0x080c, 0x9bd1, 0x785c, - 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, 0x0020, 0x0804, 0x9de6, - 0x00e6, 0x2071, 0x19e6, 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, - 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7620, 0x2660, - 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0xa295, 0x8cff, 0x0904, - 0xa295, 0x6020, 0x9086, 0x0006, 0x1904, 0xa290, 0x88ff, 0x0138, - 0x2800, 0x9c06, 0x1904, 0xa290, 0x2039, 0x0000, 0x0050, 0x6010, - 0x9b06, 0x1904, 0xa290, 0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, - 0xa290, 0x7030, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, 0x86d5, - 0x080c, 0xa31a, 0x7033, 0x0000, 0x0428, 0x080c, 0x86d5, 0x6820, - 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x080c, 0xa31a, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, - 0x080c, 0x2a29, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x7020, 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, - 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, 0x6014, 0x0096, - 0x2048, 0x080c, 0xc830, 0x0110, 0x080c, 0xe27c, 0x009e, 0x080c, - 0xac1a, 0x080c, 0xa1f0, 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa20b, - 0x2c78, 0x600c, 0x2060, 0x0804, 0xa20b, 0x9006, 0x012e, 0x000e, - 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, - 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, - 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19e6, 0x7648, 0x2660, 0x2678, 0x8cff, 0x0904, 0xa309, - 0x6020, 0x9086, 0x0006, 0x1904, 0xa304, 0x87ff, 0x0128, 0x2700, - 0x9c06, 0x1904, 0xa304, 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, - 0x0118, 0x605c, 0x9106, 0x15c0, 0x704c, 0x9c06, 0x1168, 0x0036, - 0x2019, 0x0001, 0x080c, 0xa0fa, 0x703f, 0x0000, 0x9006, 0x704e, - 0x706a, 0x7052, 0x706e, 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c, - 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xc830, 0x0110, 0x080c, 0xe27c, 0x080c, 0xac1a, 0x87ff, - 0x1198, 0x00ce, 0x0804, 0xa2b5, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xa2b5, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, - 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e6, 0x9006, 0x7032, 0x700a, - 0x7004, 0x9086, 0x0003, 0x0158, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e6, 0x2c10, 0x7648, 0x2660, 0x2678, - 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110, - 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, - 0x0040, 0x090c, 0x95c6, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, - 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7610, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xa407, 0x6010, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x1904, 0xa402, 0x7030, 0x9c06, 0x1520, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xa3d9, 0x080c, 0x9e16, - 0x68c3, 0x0000, 0x080c, 0xa31a, 0x7033, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a29, 0x9006, 0x080c, 0x2a29, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, - 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xca36, - 0x1180, 0x080c, 0x321e, 0x080c, 0xca47, 0x1518, 0x080c, 0xb5a6, - 0x0400, 0x080c, 0xa31a, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, - 0x0898, 0x080c, 0xca47, 0x1118, 0x080c, 0xb5a6, 0x0090, 0x6014, - 0x2048, 0x080c, 0xc830, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d6f, 0x080c, - 0xca21, 0x080c, 0xccc3, 0x080c, 0xac1a, 0x080c, 0xa1f0, 0x00ce, - 0x0804, 0xa382, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa382, 0x012e, - 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, 0xe27c, 0x0c08, - 0x00d6, 0x080c, 0x9ace, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, - 0x0014, 0x20e1, 0x0001, 0x2099, 0x1988, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, - 0x080c, 0x9de6, 0x00de, 0x0005, 0x080c, 0x9ace, 0x700b, 0x0800, - 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, - 0x782c, 0x7026, 0x7860, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, - 0x7860, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, 0x0804, 0x9de6, - 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, - 0xcec9, 0x00de, 0x1904, 0xa4b5, 0x080c, 0x9a83, 0x7003, 0x1300, - 0x782c, 0x080c, 0xa5c0, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, - 0x7810, 0x2058, 0xbaa0, 0x080c, 0xab49, 0x11d8, 0x9286, 0x007e, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, - 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, - 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, - 0x00c0, 0xb884, 0x700e, 0x00a8, 0x080c, 0xab49, 0x1130, 0x7810, - 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f, - 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, - 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, - 0x00de, 0x080c, 0x9de6, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, - 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xa533, - 0x9186, 0x0005, 0x0904, 0xa51b, 0x9186, 0x0004, 0x05f0, 0x9186, - 0x0008, 0x0904, 0xa524, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, - 0x1700, 0x080c, 0xa59d, 0x0005, 0x080c, 0xa55e, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x6a44, 0xd2fc, 0x11f8, - 0x0002, 0xa4fc, 0xa507, 0xa4fe, 0xa507, 0xa503, 0xa4fc, 0xa4fc, - 0xa507, 0xa507, 0xa507, 0xa507, 0xa4fc, 0xa4fc, 0xa4fc, 0xa4fc, - 0xa4fc, 0xa507, 0xa4fc, 0xa507, 0x080c, 0x0d7d, 0x6824, 0xd0e4, - 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, - 0x7022, 0x6830, 0x7026, 0x0804, 0xa557, 0x080c, 0xa55e, 0x00d6, - 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, - 0x1108, 0x900e, 0x04e0, 0x080c, 0xa55e, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x2009, 0x4000, 0x0498, 0x04c9, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, - 0x1108, 0x900e, 0x0420, 0x0451, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x6814, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, 0xa838, - 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, 0x0011, 0x2004, - 0xd0fc, 0x1148, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, - 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, - 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0x9de6, 0x00b6, 0x0036, - 0x0046, 0x0056, 0x0066, 0x080c, 0x9ace, 0x9006, 0x7003, 0x0200, - 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, - 0xab49, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x181f, - 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, - 0x00de, 0x0028, 0x901e, 0xbc84, 0x2029, 0x0000, 0x6634, 0x782c, - 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, - 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, - 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, 0x080c, 0x9ace, 0x7003, - 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, - 0x0804, 0x9de6, 0x080c, 0x9a7a, 0x7003, 0x1400, 0x7838, 0x700a, - 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, - 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x9de6, - 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, - 0x2058, 0xb8d4, 0xd084, 0x0120, 0x7850, 0x702a, 0x784c, 0x702e, - 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x9ac5, 0x7003, - 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, - 0x9de6, 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, - 0x0026, 0x080c, 0x2998, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, - 0x2012, 0x002e, 0x080c, 0x9e09, 0x080c, 0x86cc, 0x0005, 0x0036, - 0x0096, 0x00d6, 0x00e6, 0x7860, 0x2048, 0xaa7c, 0x9296, 0x00c0, - 0x9294, 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, - 0x9194, 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, - 0x9384, 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, - 0x00d6, 0x2069, 0x0200, 0x080c, 0xa67d, 0x00de, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, - 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, - 0x003e, 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, - 0x01c0, 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, - 0x0180, 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, - 0x1140, 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x19b1, - 0x210c, 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, - 0x0036, 0x0026, 0x2110, 0x900e, 0x080c, 0x2a72, 0x002e, 0x0005, - 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, - 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, - 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, - 0x0005, 0x080c, 0x9a83, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, - 0x2048, 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, - 0x1138, 0x2001, 0x197b, 0x2004, 0x9086, 0xaaaa, 0x1904, 0xa722, - 0x7003, 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, - 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080, 0x700e, - 0xa998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, 0x1805, - 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, - 0xa6b3, 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xa6bd, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, - 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, 0xa668, - 0x00de, 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, 0x20a9, - 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x2009, - 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dc0, 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008, 0x20a9, - 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00ce, - 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, 0x1837, - 0x2004, 0x9084, 0x0028, 0x1168, 0x080c, 0x74c8, 0x0150, 0x6028, - 0xc0bd, 0x602a, 0x2009, 0x1804, 0x2011, 0x0029, 0x080c, 0x2a72, - 0x0010, 0x080c, 0x9de6, 0x080c, 0x86cc, 0x00de, 0x009e, 0x002e, - 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, 0x9085, - 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, 0x00ff, - 0x00ee, 0x0804, 0xa698, 0x080c, 0x9a83, 0x0016, 0x0026, 0x0096, - 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500, 0x00c6, - 0xa89c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, - 0x700a, 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff, 0x9105, - 0x700e, 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c, 0x9084, - 0x00ff, 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290, 0x0006, + 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, + 0x2028, 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, + 0x9094, 0xff80, 0x1130, 0x9080, 0x3388, 0x2015, 0x9294, 0x00ff, + 0x0020, 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, + 0x9582, 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, + 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, + 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, + 0xd0a4, 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, + 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, + 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848, 0x608a, + 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e, 0xb86c, + 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xba84, + 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x900e, + 0x2011, 0x0092, 0x080c, 0x2a92, 0x2009, 0x07d0, 0x080c, 0x870e, + 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, + 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, + 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, + 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x0002, 0x9d9e, + 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, + 0x9d9e, 0x9da0, 0x9d9e, 0x9d9e, 0x9d9e, 0x9d9e, 0x080c, 0x0d7d, + 0xb884, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, 0xaf90, + 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, + 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, 0xaf94, + 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, + 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, + 0x6077, 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, + 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, 0xa87c, + 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, + 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, 0x8000, + 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0xa848, + 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0xb86c, + 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xa66e, 0x2009, + 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, + 0x080c, 0x870e, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, + 0x009e, 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217, 0x0005, + 0x00d6, 0x2069, 0x19e6, 0x686b, 0x0001, 0x00de, 0x0005, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8700, 0x0005, 0x0016, + 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, + 0x0089, 0x080c, 0x8700, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, + 0x2102, 0x2001, 0x19e7, 0x2003, 0x0000, 0x2001, 0x19f2, 0x2003, + 0x0000, 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, + 0x0009, 0x080c, 0x2a92, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x080c, 0xa899, 0x0106, 0x2061, 0x0100, 0x61a4, + 0x60a7, 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, 0x0008, + 0x080c, 0x2a92, 0x002e, 0x001e, 0x010e, 0x090c, 0xa8b5, 0x000e, + 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, + 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, + 0x74ec, 0x1510, 0x2001, 0x1a0b, 0x2004, 0x9005, 0x1904, 0x9ece, + 0x080c, 0x7591, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101, 0x6844, + 0xd084, 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, + 0xd084, 0x090c, 0x0d7d, 0x6843, 0x0100, 0x080c, 0x8700, 0x04b0, + 0x00c6, 0x2061, 0x19e6, 0x00f0, 0x6904, 0x9194, 0x4000, 0x0598, + 0x080c, 0x9e4f, 0x080c, 0x2a59, 0x00c6, 0x2061, 0x19e6, 0x6134, + 0x9192, 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0xa899, 0x6130, + 0x080c, 0xa8b5, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x8700, 0x080c, + 0x9e42, 0x00a0, 0x080c, 0xa899, 0x6130, 0x91e5, 0x0000, 0x0150, + 0x080c, 0xe764, 0x080c, 0x8709, 0x6003, 0x0001, 0x2009, 0x0014, + 0x080c, 0xac8d, 0x080c, 0xa8b5, 0x00ce, 0x0000, 0x002e, 0x001e, + 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a0b, 0x2004, 0x9005, 0x1db0, + 0x00c6, 0x2061, 0x19e6, 0x6134, 0x9192, 0x0003, 0x1ad8, 0x8108, + 0x6136, 0x00ce, 0x080c, 0x8700, 0x080c, 0x5eff, 0x2009, 0x1846, + 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, 0x00e6, + 0x0016, 0x0026, 0x080c, 0x8716, 0x080c, 0xa899, 0x2001, 0x0387, + 0x2003, 0x0202, 0x2071, 0x19e6, 0x714c, 0x81ff, 0x0904, 0x9f76, + 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x74ec, 0x1510, 0x0036, + 0x2019, 0x0002, 0x080c, 0xa133, 0x003e, 0x714c, 0x2160, 0x080c, + 0xe764, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, + 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, + 0xac8d, 0x2001, 0x0386, 0x2003, 0x5040, 0x080c, 0x7591, 0x0804, + 0x9f76, 0x6904, 0xd1f4, 0x0904, 0x9f83, 0x080c, 0x2a59, 0x00c6, + 0x704c, 0x9065, 0x090c, 0x0d7d, 0x6020, 0x00ce, 0x9086, 0x0006, + 0x1518, 0x61c8, 0x60c4, 0x9105, 0x11f8, 0x2009, 0x180c, 0x2104, + 0xd0d4, 0x01d0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, + 0x0002, 0x1560, 0x0010, 0xc0d4, 0x200a, 0x6014, 0x9084, 0xe7fd, + 0x9085, 0x0010, 0x6016, 0x704c, 0x2060, 0x080c, 0x965a, 0x2009, + 0x0049, 0x080c, 0xac8d, 0x00d0, 0x0036, 0x2019, 0x0001, 0x080c, + 0xa133, 0x003e, 0x714c, 0x2160, 0x080c, 0xe764, 0x2009, 0x004a, + 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, + 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, 0xac8d, 0x2001, 0x0387, + 0x2003, 0x0200, 0x080c, 0xa8b5, 0x002e, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, 0x9f2d, 0x0804, 0x9f2f, + 0x0026, 0x00e6, 0x2071, 0x19e6, 0x706c, 0xd084, 0x01e8, 0xc084, + 0x706e, 0x714c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, 0x0008, + 0x2114, 0x928e, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, 0x0012, + 0x080c, 0x2a92, 0x0048, 0x928e, 0x0009, 0x0db0, 0x2009, 0x1984, + 0x2011, 0x0016, 0x080c, 0x2a92, 0x00ee, 0x002e, 0x0005, 0x9036, + 0x2001, 0x19f0, 0x2004, 0x9005, 0x0128, 0x9c06, 0x0128, 0x2c30, + 0x600c, 0x0cc8, 0x9085, 0x0001, 0x0005, 0x00f6, 0x2079, 0x19e6, + 0x610c, 0x9006, 0x600e, 0x6044, 0xc0fc, 0x6046, 0x86ff, 0x1140, + 0x7824, 0x9c06, 0x1118, 0x7826, 0x782a, 0x0050, 0x792a, 0x0040, + 0x00c6, 0x2660, 0x610e, 0x00ce, 0x7824, 0x9c06, 0x1108, 0x7e26, + 0x080c, 0xa1fd, 0x080c, 0xca54, 0x00fe, 0x0005, 0x080c, 0x9abc, + 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, + 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, 0x2058, + 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, 0x607c, 0x6180, + 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, 0x0804, + 0x9e1f, 0x080c, 0x9abc, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, + 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, + 0x0804, 0x9e1f, 0x0156, 0x080c, 0x9b07, 0x7003, 0x0200, 0x080c, + 0x87ce, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x9ef0, + 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, + 0x0002, 0x9290, 0x0002, 0x1f04, 0xa021, 0x60c3, 0x001c, 0x015e, + 0x0804, 0x9e1f, 0x0016, 0x0026, 0x080c, 0x9ae3, 0x080c, 0x9af5, + 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, 0x2048, + 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, + 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, + 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x9e1f, 0x002e, + 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, 0xa679, 0x20a1, + 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x9abc, 0x7003, 0x6200, + 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x9e1f, 0x0016, 0x0026, + 0x080c, 0x9abc, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, + 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, + 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, + 0x60c2, 0x080c, 0x9e1f, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7010, 0x2060, + 0x8cff, 0x0188, 0x080c, 0xca7a, 0x1110, 0x080c, 0xb5c6, 0x600c, + 0x0006, 0x080c, 0xccf6, 0x600f, 0x0000, 0x080c, 0xabf0, 0x080c, + 0xa1fd, 0x00ce, 0x0c68, 0x2c00, 0x7012, 0x700e, 0x012e, 0x000e, + 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, + 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0x19e6, 0x7030, 0x2060, 0x8cff, 0x0548, 0x080c, + 0x9e4f, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x8709, 0x00c6, 0x2061, + 0x0100, 0x080c, 0xa7ca, 0x00ce, 0x20a9, 0x01f4, 0x04b1, 0x080c, + 0x95ff, 0x6044, 0xd0ac, 0x1128, 0x2001, 0x1987, 0x2004, 0x604a, + 0x0020, 0x2009, 0x0013, 0x080c, 0xac8d, 0x000e, 0x001e, 0x002e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, + 0x2001, 0x1800, 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, + 0x0d60, 0x080c, 0x8709, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, + 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x5ea9, 0x080c, + 0x8651, 0x20a9, 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, + 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, 0x2a59, 0x0090, + 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0xa115, 0x7804, + 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, + 0x080c, 0x2a49, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, + 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, + 0x0140, 0x2071, 0x0380, 0x701c, 0x0006, 0x701f, 0x0202, 0x2071, + 0x19e6, 0x704c, 0x2060, 0x8cff, 0x0904, 0xa1ac, 0x9386, 0x0002, + 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0xa1ac, 0x68af, 0x95f5, + 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, + 0x0008, 0x080c, 0x8716, 0x080c, 0x1dfd, 0x2001, 0x0032, 0x6920, + 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, + 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, + 0x9084, 0x4000, 0x190c, 0x2a59, 0x0090, 0xd08c, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0xa17a, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, 0x2a49, 0x6827, + 0x4000, 0x6824, 0x83ff, 0x1180, 0x2009, 0x0049, 0x6020, 0x9086, + 0x0009, 0x0150, 0x080c, 0x965a, 0x6044, 0xd0ac, 0x1118, 0x6003, + 0x0002, 0x0010, 0x080c, 0xac8d, 0x000e, 0x2071, 0x0380, 0xd08c, + 0x1110, 0x701f, 0x0200, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a06, 0x012e, 0x00de, 0x0005, + 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e6, 0x6a3e, 0x012e, + 0x00de, 0x0005, 0x080c, 0x9c0a, 0x785c, 0x7032, 0x7042, 0x7047, + 0x1000, 0x00f8, 0x080c, 0x9c0a, 0x785c, 0x7032, 0x7042, 0x7047, + 0x4000, 0x00b8, 0x080c, 0x9c0a, 0x785c, 0x7032, 0x7042, 0x7047, + 0x2000, 0x0078, 0x080c, 0x9c0a, 0x785c, 0x7032, 0x7042, 0x7047, + 0x0400, 0x0038, 0x080c, 0x9c0a, 0x785c, 0x7032, 0x7042, 0x7047, + 0x0200, 0x60c3, 0x0020, 0x0804, 0x9e1f, 0x00e6, 0x2071, 0x19e6, + 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x19e6, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001, + 0x87ff, 0x0904, 0xa2a2, 0x8cff, 0x0904, 0xa2a2, 0x6020, 0x9086, + 0x0006, 0x1904, 0xa29d, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, + 0xa29d, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa29d, + 0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, 0xa29d, 0x7030, 0x9c06, + 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, + 0x0148, 0x6827, 0x0001, 0x080c, 0x8709, 0x080c, 0xa327, 0x7033, + 0x0000, 0x0428, 0x080c, 0x8709, 0x6820, 0xd0b4, 0x0110, 0x68a7, + 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0xa327, 0x7033, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, 0x2a49, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7020, + 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, + 0x1168, 0x600f, 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xc863, + 0x0110, 0x080c, 0xe2b9, 0x009e, 0x080c, 0xac2b, 0x080c, 0xa1fd, + 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa218, 0x2c78, 0x600c, 0x2060, + 0x0804, 0xa218, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, + 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, + 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7648, + 0x2660, 0x2678, 0x8cff, 0x0904, 0xa316, 0x6020, 0x9086, 0x0006, + 0x1904, 0xa311, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa311, + 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, 0x0118, 0x605c, 0x9106, + 0x15c0, 0x704c, 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, + 0xa133, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, + 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, + 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, + 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, 0x080c, 0xc863, 0x0110, + 0x080c, 0xe2b9, 0x080c, 0xac2b, 0x87ff, 0x1198, 0x00ce, 0x0804, + 0xa2c2, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa2c2, 0x9006, 0x012e, + 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, + 0x2071, 0x19e6, 0x9006, 0x7032, 0x700a, 0x7004, 0x9086, 0x0003, + 0x0158, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, + 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, + 0x19e6, 0x2c10, 0x7648, 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, + 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, + 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, + 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, 0x95ff, + 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, + 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x19e6, 0x7610, 0x2660, 0x2678, 0x8cff, + 0x0904, 0xa414, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, + 0x1904, 0xa40f, 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x0904, 0xa3e6, 0x080c, 0x9e4f, 0x68c3, 0x0000, 0x080c, + 0xa327, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, + 0x2a49, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, + 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, + 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x080c, 0xca69, 0x1180, 0x080c, 0x323e, + 0x080c, 0xca7a, 0x1518, 0x080c, 0xb5c6, 0x0400, 0x080c, 0xa327, + 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xca7a, + 0x1118, 0x080c, 0xb5c6, 0x0090, 0x6014, 0x2048, 0x080c, 0xc863, + 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0x6d93, 0x080c, 0xca54, 0x080c, 0xccf6, + 0x080c, 0xac2b, 0x080c, 0xa1fd, 0x00ce, 0x0804, 0xa38f, 0x2c78, + 0x600c, 0x2060, 0x0804, 0xa38f, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1d20, 0x080c, 0xe2b9, 0x0c08, 0x00d6, 0x080c, 0x9b07, + 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, + 0x2099, 0x1988, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, + 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, 0x080c, 0x9e1f, 0x00de, + 0x0005, 0x080c, 0x9b07, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, + 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7860, + 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, 0x7860, 0x9084, 0xff00, + 0x8007, 0x7006, 0x60c2, 0x0804, 0x9e1f, 0x00b6, 0x00d6, 0x0016, + 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, 0xcefc, 0x00de, 0x1904, + 0xa4c2, 0x080c, 0x9abc, 0x7003, 0x1300, 0x782c, 0x080c, 0xa5d1, + 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, + 0x080c, 0xab5a, 0x11d8, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, + 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, + 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, + 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, 0x00c0, 0xb884, 0x700e, + 0x00a8, 0x080c, 0xab5a, 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, + 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f, 0x2d04, 0x700a, 0x8d68, + 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, + 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x9e1f, + 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, + 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, + 0x01c0, 0x9186, 0x0003, 0x0904, 0xa541, 0x9186, 0x0005, 0x0904, + 0xa529, 0x9186, 0x0004, 0x05f0, 0x9186, 0x0008, 0x0904, 0xa532, + 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0xa5ae, + 0x0005, 0x080c, 0xa56f, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x6800, 0x6a44, 0xd2fc, 0x11f8, 0x0002, 0xa509, 0xa514, + 0xa50b, 0xa514, 0xa510, 0xa509, 0xa509, 0xa514, 0xa514, 0xa514, + 0xa514, 0xa509, 0xa509, 0xa509, 0xa509, 0xa509, 0xa514, 0xa509, + 0xa514, 0x080c, 0x0d7d, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, + 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, + 0x0804, 0xa568, 0x080c, 0xa56f, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x0804, + 0xa568, 0x080c, 0xa56f, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x04b0, 0x04e1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, + 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, + 0x0438, 0x0469, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x6924, + 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, + 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, 0x0011, + 0x2004, 0xd0fc, 0x1148, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, + 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, + 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0x9e1f, 0x00b6, + 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x9b07, 0x9006, 0x7003, + 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, + 0x080c, 0xab5a, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, + 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, + 0xbc14, 0x00de, 0x0028, 0x901e, 0xbc84, 0x2029, 0x0000, 0x6634, + 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, + 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, + 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, 0x080c, 0x9b07, + 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, + 0x0008, 0x0804, 0x9e1f, 0x080c, 0x9ab3, 0x7003, 0x1400, 0x7838, + 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, + 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, + 0x9e1f, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, + 0x00b6, 0x2058, 0xb8d4, 0xd084, 0x0120, 0x7850, 0x702a, 0x784c, + 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x9afe, + 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, + 0x0804, 0x9e1f, 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, + 0x9575, 0x0026, 0x080c, 0x29b4, 0x0228, 0x2011, 0x0101, 0x2204, + 0xc0c5, 0x2012, 0x002e, 0x080c, 0x9e42, 0x080c, 0x8700, 0x0005, + 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7860, 0x2048, 0xaa7c, 0x9296, + 0x00c0, 0x9294, 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, + 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, + 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, + 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, 0xa68e, 0x00de, 0x20e9, + 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, + 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, + 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, + 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, + 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, + 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, + 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, + 0x19b1, 0x210c, 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, + 0x60ab, 0x0036, 0x0026, 0x2110, 0x900e, 0x080c, 0x2a92, 0x002e, + 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, + 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, + 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, + 0x6912, 0x0005, 0x080c, 0x9abc, 0x0016, 0x0026, 0x0096, 0x00d6, + 0x7814, 0x2048, 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, + 0x0028, 0x1138, 0x2001, 0x197b, 0x2004, 0x9086, 0xaaaa, 0x1904, + 0xa733, 0x7003, 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084, + 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080, + 0x700e, 0xa998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, + 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, + 0x1f04, 0xa6c4, 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, + 0x8108, 0x8210, 0x1f04, 0xa6ce, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, + 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, + 0xa679, 0x00de, 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0x20a9, 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xa774, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, 0x2012, - 0x8108, 0x8210, 0x1f04, 0xa77e, 0x00d6, 0x0016, 0x2069, 0x0200, - 0x080c, 0xa668, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, 0x0002, - 0x2009, 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xa794, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, 0x1f04, - 0xa7a5, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x080c, 0x9de6, 0x080c, 0x86cc, 0x00de, 0x009e, 0x002e, 0x001e, - 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, - 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, - 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, - 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7610, 0x2660, 0x2678, - 0x8cff, 0x0904, 0xa865, 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0xa837, 0x080c, 0x9e16, 0x68c3, 0x0000, - 0x080c, 0xa31a, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a29, 0x9006, - 0x080c, 0x2a29, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, 0x7612, 0x700c, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700e, 0x0010, - 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xca36, 0x1180, 0x080c, - 0x321e, 0x080c, 0xca47, 0x1518, 0x080c, 0xb5a6, 0x0400, 0x080c, - 0xa31a, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, - 0xca47, 0x1118, 0x080c, 0xb5a6, 0x0090, 0x6014, 0x2048, 0x080c, - 0xc830, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d7b, 0x080c, 0xca21, 0x080c, - 0xccc3, 0x080c, 0xac1a, 0x080c, 0xa1f0, 0x00ce, 0x0804, 0xa7e8, - 0x2c78, 0x600c, 0x2060, 0x0804, 0xa7e8, 0x7013, 0x0000, 0x700f, - 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xe27c, - 0x08f0, 0x00f6, 0x0036, 0x2079, 0x0380, 0x7b18, 0xd3bc, 0x1de8, - 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x003e, 0x00fe, 0x0005, - 0x0016, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x1188, 0x2001, 0x0015, 0x0c29, 0x2009, 0x1000, 0x2001, 0x0382, - 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x0120, 0x8109, 0x1db0, - 0x080c, 0x0d7d, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, - 0x0007, 0x9086, 0x0003, 0x1120, 0x2001, 0x0380, 0x2003, 0x0001, - 0x0005, 0x0156, 0x0016, 0x0026, 0x00e6, 0x900e, 0x2071, 0x19e6, - 0x0469, 0x0106, 0x0190, 0x7004, 0x9086, 0x0003, 0x0148, 0x20a9, - 0x1000, 0x6044, 0xd0fc, 0x01d8, 0x1f04, 0xa8c1, 0x080c, 0x0d7d, - 0x080c, 0xa888, 0x6044, 0xd0fc, 0x0190, 0x7030, 0x9c06, 0x1148, - 0x080c, 0x95c6, 0x6044, 0xd0dc, 0x0150, 0xc0dc, 0x6046, 0x700a, - 0x7042, 0x704c, 0x9c06, 0x190c, 0x0d7d, 0x080c, 0x9621, 0x010e, - 0x1919, 0x00ee, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x0382, - 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x0005, 0x0126, 0x2091, - 0x2400, 0x7808, 0xd0a4, 0x190c, 0x0d76, 0xd09c, 0x0128, 0x7820, - 0x908c, 0xf000, 0x11b8, 0x0012, 0x012e, 0x0005, 0xa90e, 0xa94c, - 0xa973, 0xa9aa, 0xa9ba, 0xa9cb, 0xa9da, 0xa9e8, 0xaa15, 0xaa19, - 0xa90e, 0xa90e, 0xa90e, 0xa90e, 0xa90e, 0xa90e, 0x080c, 0x0d7d, - 0x012e, 0x0005, 0x2060, 0x6044, 0xd0bc, 0x0140, 0xc0bc, 0x6046, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0012, 0x012e, 0x0005, - 0xa933, 0xa935, 0xa933, 0xa93b, 0xa933, 0xa933, 0xa933, 0xa933, - 0xa933, 0xa935, 0xa933, 0xa935, 0xa933, 0xa935, 0xa933, 0xa933, - 0xa933, 0xa935, 0xa933, 0x080c, 0x0d7d, 0x2009, 0x0013, 0x080c, - 0xac7c, 0x012e, 0x0005, 0x6014, 0x2048, 0xa87c, 0xd0dc, 0x0130, - 0x080c, 0x88a3, 0x080c, 0xabdf, 0x012e, 0x0005, 0x2009, 0x0049, - 0x080c, 0xac7c, 0x012e, 0x0005, 0x080c, 0xa888, 0x2001, 0x1a0b, - 0x2003, 0x0000, 0x7030, 0x9065, 0x090c, 0x0d7d, 0x7034, 0x9092, - 0x00c8, 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, 0x0110, - 0x7007, 0x0000, 0x781f, 0x0808, 0x0040, 0x080c, 0xe727, 0x6003, - 0x0001, 0x2009, 0x0014, 0x080c, 0xac7c, 0x781f, 0x0100, 0x080c, - 0xa8a4, 0x012e, 0x0005, 0x080c, 0xa888, 0x714c, 0x81ff, 0x1128, - 0x2011, 0x1a0e, 0x2013, 0x0000, 0x0438, 0x2061, 0x0100, 0x7150, - 0x9192, 0x7530, 0x12f0, 0x8108, 0x7152, 0x714c, 0x9188, 0x0008, - 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, - 0x0012, 0x6016, 0x0088, 0x714c, 0x9188, 0x0008, 0x210c, 0x918e, - 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, - 0x0018, 0x706c, 0xc085, 0x706e, 0x781f, 0x0200, 0x080c, 0xa8a4, - 0x012e, 0x0005, 0x080c, 0xa888, 0x714c, 0x2160, 0x6003, 0x0003, - 0x2009, 0x004a, 0x080c, 0xac7c, 0x781f, 0x0200, 0x080c, 0xa8a4, - 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, 0x6003, - 0x0003, 0x080c, 0xa888, 0x080c, 0x1d6d, 0x781f, 0x0400, 0x080c, - 0xa8a4, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, - 0x080c, 0xa888, 0x080c, 0x1db5, 0x781f, 0x0400, 0x080c, 0xa8a4, - 0x012e, 0x0005, 0x7030, 0x9065, 0x0148, 0x6044, 0xc0bc, 0x6046, - 0x7104, 0x9186, 0x0003, 0x0110, 0x080c, 0x9685, 0x012e, 0x0005, - 0x00f6, 0x703c, 0x9086, 0x0002, 0x0528, 0x704c, 0x907d, 0x0510, - 0x7844, 0xc0bc, 0x7846, 0x7820, 0x9086, 0x0009, 0x0118, 0x080c, - 0x9d40, 0x00c0, 0x7828, 0xd0fc, 0x1118, 0x080c, 0x9cbf, 0x0090, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1130, 0x2001, 0x197b, - 0x2004, 0x9086, 0xaaaa, 0x1120, 0x2001, 0x0387, 0x2003, 0x1000, - 0x080c, 0x9c44, 0x00fe, 0x012e, 0x0005, 0x080c, 0x7569, 0x012e, - 0x0005, 0x080c, 0x0d7d, 0x0005, 0x00e6, 0x2071, 0x19e6, 0x6044, - 0xc0bc, 0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, 0x2019, - 0x0001, 0x080c, 0xa0fa, 0x704f, 0x0000, 0x2001, 0x0109, 0x2004, - 0xd08c, 0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, 0x703f, - 0x0000, 0x080c, 0xa331, 0x00ee, 0x0005, 0x0026, 0x7010, 0x9c06, - 0x1178, 0x080c, 0xa1f0, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, - 0x0120, 0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, 0x9006, - 0x002e, 0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, 0xa1f0, - 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, 0x600f, - 0x0000, 0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, 0x00d6, - 0x0036, 0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x01f8, 0x080c, 0x86d5, 0x080c, 0x9e16, 0x68c3, 0x0000, 0x080c, - 0xa31a, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2a29, 0x9006, 0x080c, 0x2a29, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, 0x0038, - 0x7808, 0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, 0x003e, - 0x00de, 0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, 0x0100, - 0x2001, 0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, 0x2091, - 0x2800, 0x0016, 0x0036, 0x080c, 0xa8ee, 0x003e, 0x001e, 0x012e, - 0x00ce, 0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, 0x8319, - 0x1d38, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0156, 0x080c, - 0x9ace, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, - 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, - 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, - 0x080c, 0x74c8, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6adc, 0xd29c, - 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, 0x879a, 0x20a9, - 0x0006, 0x2011, 0xfff4, 0x2019, 0xfff5, 0x2071, 0x0250, 0x2305, - 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0xaaef, 0x60c3, 0x0020, 0x080c, 0x9de6, 0x015e, - 0x00de, 0x0005, 0x0156, 0x080c, 0x9ace, 0x7a14, 0x82ff, 0x0168, - 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, - 0x001c, 0x700f, 0x0001, 0x2011, 0x19bc, 0x2204, 0x8007, 0x701a, - 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7022, 0x2001, 0x1820, - 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, - 0x9de6, 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, 0x000e, 0x0005, - 0x2011, 0x0003, 0x080c, 0xa1b1, 0x2011, 0x0002, 0x080c, 0xa1bb, - 0x080c, 0xa07a, 0x0036, 0x901e, 0x080c, 0xa0fa, 0x003e, 0x0005, - 0x080c, 0x3361, 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, 0x9085, - 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x6620, 0xb85c, 0xc0ac, - 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, 0x188d, 0x7000, - 0x9005, 0x0140, 0x2001, 0x0812, 0x2071, 0x1800, 0x7076, 0x707a, - 0x706b, 0xffd4, 0x2071, 0x1800, 0x7074, 0x7056, 0x705b, 0x1ddc, - 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, - 0x9582, 0x0010, 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, - 0x0148, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, - 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, - 0x7068, 0x9502, 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, - 0x0005, 0x705b, 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, - 0x1800, 0x7554, 0x9582, 0x0010, 0x0600, 0x7058, 0x2060, 0x6000, - 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, - 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, - 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1228, 0x755a, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, - 0x1ddc, 0x0a0c, 0x0d7d, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, - 0x0d7d, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, - 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x605e, 0x6062, 0x6026, - 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x604a, 0x602a, - 0x6046, 0x6042, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, - 0x9006, 0x600e, 0x6016, 0x601a, 0x6012, 0x6022, 0x6002, 0x601e, - 0x605e, 0x6062, 0x604a, 0x6046, 0x2061, 0x1800, 0x6054, 0x8000, - 0x6056, 0x0005, 0x0006, 0x6000, 0x9086, 0x0000, 0x01d0, 0x601c, - 0xd084, 0x190c, 0x1a77, 0x6023, 0x0007, 0x2001, 0x1985, 0x2004, - 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, - 0xe534, 0x604b, 0x0000, 0x6044, 0xd0fc, 0x1129, 0x9006, 0x6046, - 0x6016, 0x000e, 0x0005, 0x080c, 0xa888, 0x0106, 0x2001, 0x19f9, - 0x2004, 0x9c06, 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0xa0fa, - 0x003e, 0x080c, 0xa331, 0x010e, 0x090c, 0xa8a4, 0x0005, 0x00e6, - 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, - 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, - 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, - 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, - 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, - 0xac90, 0xac9a, 0xacb5, 0xacd0, 0xcfa4, 0xcfc1, 0xcfdc, 0xac90, - 0xac9a, 0x8f7c, 0xacec, 0xac90, 0xac90, 0xac90, 0xac90, 0xac90, - 0x9186, 0x0013, 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x95c6, - 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7d, - 0x0013, 0x006e, 0x0005, 0xacb3, 0xb412, 0xb5ed, 0xacb3, 0xb683, - 0xafb5, 0xacb3, 0xacb3, 0xb394, 0xbbed, 0xacb3, 0xacb3, 0xacb3, - 0xacb3, 0xacb3, 0xacb3, 0x080c, 0x0d7d, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0xacce, 0xc1f2, - 0xacce, 0xacce, 0xacce, 0xacce, 0xacce, 0xacce, 0xc197, 0xc375, - 0xacce, 0xc22f, 0xc2b3, 0xc22f, 0xc2b3, 0xacce, 0x080c, 0x0d7d, - 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7d, 0x6000, 0x0002, 0xacea, - 0xbc37, 0xbcce, 0xbe4e, 0xbebd, 0xacea, 0xacea, 0xacea, 0xbc06, - 0xc118, 0xc11b, 0xacea, 0xacea, 0xacea, 0xacea, 0xc14b, 0xacea, - 0xacea, 0xacea, 0x080c, 0x0d7d, 0x0066, 0x6000, 0x90b2, 0x0016, - 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0xad05, 0xad05, 0xad43, - 0xade2, 0xae62, 0xad05, 0xad05, 0xad05, 0xad07, 0xad05, 0xad05, - 0xad05, 0xad05, 0xad05, 0xad05, 0xad05, 0x080c, 0x0d7d, 0x9186, - 0x004c, 0x0560, 0x9186, 0x0003, 0x190c, 0x0d7d, 0x0096, 0x601c, - 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa87c, - 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa836, 0xa8b0, 0xa83a, - 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, - 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, 0x080c, - 0x1bc7, 0x2009, 0x8030, 0x080c, 0x9247, 0x0005, 0x6010, 0x00b6, - 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, 0xae84, 0x080c, 0xcf69, - 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, - 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, - 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, - 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, - 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, - 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, - 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, - 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, - 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0xadaa, 0xadaa, 0xada5, - 0xada8, 0xadaa, 0xada2, 0xad95, 0xad95, 0xad95, 0xad95, 0xad95, - 0xad95, 0xad95, 0xad95, 0xad95, 0xad95, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, - 0x080c, 0x0d7d, 0x080c, 0xb842, 0x0028, 0x080c, 0xb927, 0x0010, - 0x080c, 0xba1d, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, - 0x2c00, 0xa896, 0x000e, 0x080c, 0xaf42, 0x0530, 0xa804, 0xa80e, - 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, - 0xadd8, 0x2031, 0x0000, 0x2041, 0x12a3, 0x080c, 0xb103, 0x0160, - 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, - 0x009e, 0x00de, 0x0804, 0xabdf, 0x2001, 0x002c, 0x900e, 0x080c, - 0xafa8, 0x0c70, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, - 0x91b2, 0x0047, 0x0a0c, 0x0d7d, 0x91b2, 0x0050, 0x1a0c, 0x0d7d, - 0x9182, 0x0047, 0x0042, 0x080c, 0xaa9a, 0x0120, 0x9086, 0x0002, - 0x0904, 0xad43, 0x0005, 0xae04, 0xae04, 0xae06, 0xae38, 0xae04, - 0xae04, 0xae04, 0xae04, 0xae4b, 0x080c, 0x0d7d, 0x00d6, 0x0016, - 0x0096, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, - 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, - 0x0000, 0x900e, 0x080c, 0xafa8, 0x080c, 0xabdf, 0x00a8, 0x6003, - 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, - 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, - 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, - 0x080c, 0x9621, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xc832, - 0x0120, 0xa87b, 0x0006, 0x080c, 0x6d7b, 0x009e, 0x00de, 0x080c, - 0xabdf, 0x0804, 0x9684, 0x080c, 0x9621, 0x080c, 0x31ef, 0x080c, - 0xcf66, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xc832, 0x0120, - 0xa87b, 0x0029, 0x080c, 0x6d7b, 0x009e, 0x00de, 0x080c, 0xabdf, - 0x0804, 0x9684, 0x9182, 0x0047, 0x0002, 0xae72, 0xae74, 0xae72, - 0xae72, 0xae72, 0xae72, 0xae72, 0xae72, 0xae72, 0xae72, 0xae72, - 0xae72, 0xae74, 0x080c, 0x0d7d, 0x00d6, 0x0096, 0x601f, 0x0000, - 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, 0x6d7b, - 0x009e, 0x00de, 0x0804, 0xabdf, 0x0026, 0x0036, 0x0056, 0x0066, - 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x103a, 0x000e, 0x090c, - 0x0d7d, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, - 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, 0x7990, 0x9188, - 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, - 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, - 0x1228, 0x2011, 0x001f, 0x080c, 0xc3f8, 0x04c0, 0x2130, 0x2009, - 0x0034, 0x2011, 0x001f, 0x080c, 0xc3f8, 0x96b2, 0x0034, 0xb004, - 0x904d, 0x0110, 0x080c, 0x0fec, 0x080c, 0x103a, 0x01d0, 0x8528, - 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, - 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xc3f8, 0x00b8, 0x96b2, - 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, 0xc3f8, - 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, - 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, - 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x6d7b, 0x000e, 0x2048, - 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, - 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, 0x103a, - 0x000e, 0x090c, 0x0d7d, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, - 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, - 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, - 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, - 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, 0x6d7b, 0x009e, 0x00fe, - 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, - 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, - 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, - 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, - 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, 0x103a, 0x2900, 0x009e, - 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, - 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, - 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, - 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, - 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, - 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, - 0x2e98, 0x2310, 0x84ff, 0x0904, 0xaf57, 0x0804, 0xaf59, 0x9085, - 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, - 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, - 0x6d6f, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, - 0x080c, 0xabdf, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0d7d, 0x080c, - 0xabdf, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, - 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, - 0x0136, 0x9080, 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, - 0x3418, 0x8318, 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, - 0x1db8, 0x2011, 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, - 0x4003, 0x3418, 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, - 0xc832, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0x009e, 0x0804, 0xabdf, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, - 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, 0x00be, - 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xab32, 0x080c, 0xabdf, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, - 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xcf51, 0x0188, 0x6014, - 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, - 0x2009, 0x0022, 0x080c, 0xb3ea, 0x9006, 0x001e, 0x000e, 0x0005, - 0x9085, 0x0001, 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, - 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, - 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, - 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, - 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, - 0x0020, 0x4003, 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x080c, 0xabdf, 0x001e, 0x009e, 0x0005, 0x0096, - 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, - 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, - 0x9108, 0x810b, 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, - 0x080c, 0xc3f8, 0x080c, 0xc832, 0x0140, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xabdf, 0x001e, - 0x009e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, - 0x0110, 0x2009, 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d7d, - 0xa97a, 0x080c, 0x6d7b, 0x009e, 0x080c, 0xabdf, 0x001e, 0x0005, - 0x0016, 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, - 0x0010, 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, - 0x6014, 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, - 0xc3f8, 0x009e, 0x080c, 0xc832, 0x0148, 0xa804, 0x9005, 0x1158, - 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xabdf, - 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, - 0x0100, 0x1118, 0x080c, 0xb5a6, 0x00e0, 0xa034, 0x8007, 0x800c, - 0x8806, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x000c, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1289, 0x0019, - 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x103a, 0x000e, - 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, - 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, - 0x0086, 0x2940, 0x080c, 0x112f, 0x008e, 0x9085, 0x0001, 0x009e, - 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, - 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, - 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, 0x0000, - 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xcec9, 0x001e, 0x1158, - 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, - 0x9386, 0x0006, 0x0128, 0x080c, 0xabdf, 0x0020, 0x0039, 0x0010, - 0x080c, 0xb21f, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, - 0x2048, 0x9186, 0x0015, 0x0904, 0xb1fe, 0x918e, 0x0016, 0x1904, - 0xb21d, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, - 0x0300, 0x1904, 0xb1d8, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, - 0x0904, 0xb1ba, 0x0804, 0xb21b, 0x6808, 0x9086, 0xffff, 0x1904, - 0xb200, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, - 0xa940, 0x9105, 0x1904, 0xb200, 0x6824, 0xd0b4, 0x1904, 0xb200, - 0x080c, 0xca21, 0x6864, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, - 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x9148, - 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, - 0x00c6, 0x2d60, 0x080c, 0xc54b, 0x00ce, 0x0804, 0xb21b, 0x00c6, - 0xa868, 0xd0fc, 0x1118, 0x080c, 0x60b6, 0x0010, 0x080c, 0x64ba, - 0x00ce, 0x1904, 0xb200, 0x00c6, 0x2d60, 0x080c, 0xabdf, 0x00ce, - 0x0804, 0xb21b, 0x00c6, 0x080c, 0xac4f, 0x0198, 0x6017, 0x0000, - 0x6810, 0x6012, 0x080c, 0xcccb, 0x6023, 0x0003, 0x6904, 0x00c6, - 0x2d60, 0x080c, 0xabdf, 0x00ce, 0x080c, 0xac7c, 0x00ce, 0x0804, - 0xb21b, 0x2001, 0x1987, 0x2004, 0x684a, 0x00ce, 0x0804, 0xb21b, - 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, - 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, - 0xcf0b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, - 0x8020, 0x080c, 0x9200, 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00, - 0x1138, 0x2001, 0x1987, 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8, - 0x89ff, 0x090c, 0x0d7d, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, - 0xa87b, 0x0003, 0x080c, 0x6b91, 0x080c, 0xca21, 0x080c, 0xac1a, - 0x0026, 0x6010, 0x00b6, 0x2058, 0xba3c, 0x080c, 0x674b, 0x00be, - 0x002e, 0x00de, 0x00ce, 0x080c, 0xabdf, 0x009e, 0x0005, 0x9186, - 0x0015, 0x1128, 0x2001, 0x1987, 0x2004, 0x684a, 0x0068, 0x918e, - 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xe534, 0x080c, - 0x88a3, 0x080c, 0xabdf, 0x00ce, 0x080c, 0xabdf, 0x0005, 0x0026, - 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, - 0x1987, 0x2004, 0x684a, 0x0804, 0xb299, 0x00c6, 0x2d60, 0x080c, - 0xc423, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, - 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, - 0x9200, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, - 0x090c, 0x0d7d, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, - 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, - 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, - 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, - 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, - 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, - 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xcbb5, 0x080c, 0x9684, - 0x0010, 0x080c, 0xabdf, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1904, 0xb304, 0x700c, 0x6210, 0x00b6, - 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb304, 0x6038, 0x2068, - 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb304, - 0x9286, 0x0002, 0x0904, 0xb304, 0x9286, 0x0000, 0x05e8, 0x6808, - 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, - 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, - 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, - 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, - 0x2048, 0x080c, 0xc832, 0x090c, 0x0d7d, 0xa87b, 0x0003, 0x009e, - 0x080c, 0xcf0b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x9200, 0x00ce, 0x0030, 0x6038, 0x2070, - 0x2001, 0x1987, 0x2004, 0x704a, 0x080c, 0xabdf, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, - 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, - 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, - 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xbbb5, 0x002e, - 0x003e, 0x015e, 0x009e, 0x1904, 0xb373, 0x0096, 0x0156, 0x0036, - 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, - 0x080c, 0xbbb5, 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, - 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, - 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xafee, 0x0096, 0x2048, - 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1289, 0x080c, - 0xb103, 0x0130, 0x00fe, 0x009e, 0x080c, 0xabdf, 0x00be, 0x0005, - 0x080c, 0xb5a6, 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x31ef, 0x080c, - 0xcf66, 0x00fe, 0x00c6, 0x080c, 0xab89, 0x2f00, 0x6012, 0x6017, - 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, - 0x0007, 0x080c, 0x6570, 0x080c, 0x659c, 0x080c, 0x9207, 0x080c, - 0x9684, 0x00ce, 0x0804, 0xb346, 0x2100, 0x91b2, 0x0053, 0x1a0c, - 0x0d7d, 0x91b2, 0x0040, 0x1a04, 0xb3fc, 0x0002, 0xb3ea, 0xb3ea, - 0xb3e0, 0xb3ea, 0xb3ea, 0xb3ea, 0xb3de, 0xb3de, 0xb3de, 0xb3de, - 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, - 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, - 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3ea, 0xb3de, 0xb3ea, - 0xb3ea, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3e0, 0xb3de, - 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, - 0xb3ea, 0xb3ea, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, 0xb3de, - 0xb3de, 0xb3de, 0xb3de, 0xb3ea, 0xb3de, 0xb3de, 0x080c, 0x0d7d, - 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8d4, 0xc08c, 0xb8d6, 0x00be, - 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, - 0x080c, 0x9207, 0x0010, 0x080c, 0x9200, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9684, 0x012e, 0x0005, 0x2600, 0x0002, 0xb3ea, 0xb3ea, - 0xb410, 0xb3ea, 0xb3ea, 0xb410, 0xb410, 0xb410, 0xb410, 0xb3ea, - 0xb410, 0xb3ea, 0xb410, 0xb3ea, 0xb410, 0xb410, 0xb410, 0xb410, - 0x080c, 0x0d7d, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7d, 0x91b6, - 0x0013, 0x0904, 0xb4e7, 0x91b6, 0x0027, 0x1904, 0xb493, 0x080c, - 0x95c6, 0x6004, 0x080c, 0xca36, 0x01b0, 0x080c, 0xca47, 0x01a8, - 0x908e, 0x0021, 0x0904, 0xb490, 0x908e, 0x0022, 0x1130, 0x080c, - 0xb01a, 0x0904, 0xb48c, 0x0804, 0xb48d, 0x908e, 0x003d, 0x0904, - 0xb490, 0x0804, 0xb486, 0x080c, 0x321e, 0x2001, 0x0007, 0x080c, - 0x6570, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xb5a6, - 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, 0xc285, 0x080c, - 0x74c8, 0x1108, 0xc2ad, 0x2202, 0x080c, 0xa888, 0x0036, 0x0026, - 0x2019, 0x0028, 0x2110, 0x080c, 0xe640, 0x002e, 0x003e, 0x0016, - 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x938d, 0x0076, - 0x903e, 0x080c, 0x9256, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, - 0x2c08, 0x080c, 0xdffb, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, - 0xa8a4, 0x080c, 0xcf66, 0x0016, 0x080c, 0xccc3, 0x080c, 0xabdf, - 0x001e, 0x080c, 0x32f8, 0x080c, 0x9684, 0x0030, 0x080c, 0xccc3, - 0x080c, 0xabdf, 0x080c, 0x9684, 0x0005, 0x080c, 0xb5a6, 0x0cb0, - 0x080c, 0xb5e2, 0x0c98, 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, - 0x1140, 0x080c, 0xaa9a, 0x0d80, 0x9086, 0x0002, 0x0904, 0xb5ed, - 0x0c58, 0x9186, 0x0014, 0x1d40, 0x080c, 0x95c6, 0x6004, 0x908e, - 0x0022, 0x1118, 0x080c, 0xb01a, 0x09f8, 0x080c, 0x31ef, 0x080c, - 0xcf66, 0x080c, 0xca36, 0x1190, 0x080c, 0x321e, 0x6010, 0x00b6, - 0x2058, 0xb9a0, 0x00be, 0x080c, 0xb5a6, 0x9186, 0x007e, 0x1128, - 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0800, 0x080c, 0xca47, - 0x1120, 0x080c, 0xb5a6, 0x0804, 0xb486, 0x6004, 0x908e, 0x0032, - 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, - 0x3599, 0x00fe, 0x00ee, 0x0804, 0xb486, 0x6004, 0x908e, 0x0021, - 0x0d40, 0x908e, 0x0022, 0x090c, 0xb5a6, 0x0804, 0xb486, 0x90b2, - 0x0040, 0x1a04, 0xb586, 0x2008, 0x0002, 0xb52f, 0xb530, 0xb533, - 0xb536, 0xb539, 0xb53c, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, - 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, - 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, - 0xb52d, 0xb52d, 0xb52d, 0xb53f, 0xb548, 0xb52d, 0xb549, 0xb548, - 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb548, 0xb548, 0xb52d, - 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb52d, 0xb571, - 0xb548, 0xb52d, 0xb544, 0xb52d, 0xb52d, 0xb52d, 0xb545, 0xb52d, - 0xb52d, 0xb52d, 0xb548, 0xb56c, 0xb52d, 0x080c, 0x0d7d, 0x00c0, - 0x2001, 0x000b, 0x00e8, 0x2001, 0x0003, 0x00d0, 0x2001, 0x0005, - 0x00b8, 0x2001, 0x0001, 0x00a0, 0x2001, 0x0009, 0x0088, 0x6003, - 0x0005, 0x080c, 0x9684, 0x0058, 0x0018, 0x0010, 0x080c, 0x6570, - 0x04b8, 0x080c, 0xcf69, 0x6003, 0x0004, 0x080c, 0x9684, 0x0005, - 0x080c, 0x6570, 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, + 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, + 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008, + 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, + 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, + 0x1837, 0x2004, 0x9084, 0x0028, 0x1168, 0x080c, 0x74ec, 0x0150, + 0x6028, 0xc0bd, 0x602a, 0x2009, 0x1804, 0x2011, 0x0029, 0x080c, + 0x2a92, 0x0010, 0x080c, 0x9e1f, 0x080c, 0x8700, 0x00de, 0x009e, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, + 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, + 0x00ff, 0x00ee, 0x0804, 0xa6a9, 0x080c, 0x9abc, 0x0016, 0x0026, + 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500, + 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, + 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff, + 0x9105, 0x700e, 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c, + 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008, + 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290, + 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, + 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108, + 0x8210, 0x1f04, 0xa785, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, + 0x2012, 0x8108, 0x8210, 0x1f04, 0xa78f, 0x00d6, 0x0016, 0x2069, + 0x0200, 0x080c, 0xa679, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, + 0x0002, 0x2009, 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, + 0x8210, 0x1f04, 0xa7a5, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, + 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, + 0x1f04, 0xa7b6, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x080c, 0x9e1f, 0x080c, 0x8700, 0x00de, 0x009e, 0x002e, + 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, + 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, + 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, + 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, + 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e6, 0x7610, 0x2660, + 0x2678, 0x8cff, 0x0904, 0xa876, 0x7030, 0x9c06, 0x1520, 0x2069, + 0x0100, 0x68c0, 0x9005, 0x0904, 0xa848, 0x080c, 0x9e4f, 0x68c3, + 0x0000, 0x080c, 0xa327, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2a49, + 0x9006, 0x080c, 0x2a49, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, 0x7612, + 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700e, + 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xca69, 0x1180, + 0x080c, 0x323e, 0x080c, 0xca7a, 0x1518, 0x080c, 0xb5c6, 0x0400, + 0x080c, 0xa327, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, + 0x080c, 0xca7a, 0x1118, 0x080c, 0xb5c6, 0x0090, 0x6014, 0x2048, + 0x080c, 0xc863, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d9f, 0x080c, 0xca54, + 0x080c, 0xccf6, 0x080c, 0xac2b, 0x080c, 0xa1fd, 0x00ce, 0x0804, + 0xa7f9, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa7f9, 0x7013, 0x0000, + 0x700f, 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, + 0xe2b9, 0x08f0, 0x00f6, 0x0036, 0x2079, 0x0380, 0x7b18, 0xd3bc, + 0x1de8, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x003e, 0x00fe, + 0x0005, 0x0016, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, + 0x0001, 0x1188, 0x2001, 0x0015, 0x0c29, 0x2009, 0x1000, 0x2001, + 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x0120, 0x8109, + 0x1db0, 0x080c, 0x0d7d, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, + 0x9084, 0x0007, 0x9086, 0x0003, 0x1120, 0x2001, 0x0380, 0x2003, + 0x0001, 0x0005, 0x0156, 0x0016, 0x0026, 0x00e6, 0x900e, 0x2071, + 0x19e6, 0x0469, 0x0106, 0x0190, 0x7004, 0x9086, 0x0003, 0x0148, + 0x20a9, 0x1000, 0x6044, 0xd0fc, 0x01d8, 0x1f04, 0xa8d2, 0x080c, + 0x0d7d, 0x080c, 0xa899, 0x6044, 0xd0fc, 0x0190, 0x7030, 0x9c06, + 0x1148, 0x080c, 0x95ff, 0x6044, 0xd0dc, 0x0150, 0xc0dc, 0x6046, + 0x700a, 0x7042, 0x704c, 0x9c06, 0x190c, 0x0d7d, 0x080c, 0x965a, + 0x010e, 0x1919, 0x00ee, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, + 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x0005, 0x0126, + 0x2091, 0x2400, 0x7808, 0xd0a4, 0x190c, 0x0d76, 0xd09c, 0x0128, + 0x7820, 0x908c, 0xf000, 0x11b8, 0x0012, 0x012e, 0x0005, 0xa91f, + 0xa95d, 0xa984, 0xa9bb, 0xa9cb, 0xa9dc, 0xa9eb, 0xa9f9, 0xaa26, + 0xaa2a, 0xa91f, 0xa91f, 0xa91f, 0xa91f, 0xa91f, 0xa91f, 0x080c, + 0x0d7d, 0x012e, 0x0005, 0x2060, 0x6044, 0xd0bc, 0x0140, 0xc0bc, + 0x6046, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0012, 0x012e, + 0x0005, 0xa944, 0xa946, 0xa944, 0xa94c, 0xa944, 0xa944, 0xa944, + 0xa944, 0xa944, 0xa946, 0xa944, 0xa946, 0xa944, 0xa946, 0xa944, + 0xa944, 0xa944, 0xa946, 0xa944, 0x080c, 0x0d7d, 0x2009, 0x0013, + 0x080c, 0xac8d, 0x012e, 0x0005, 0x6014, 0x2048, 0xa87c, 0xd0dc, + 0x0130, 0x080c, 0x88d7, 0x080c, 0xabf0, 0x012e, 0x0005, 0x2009, + 0x0049, 0x080c, 0xac8d, 0x012e, 0x0005, 0x080c, 0xa899, 0x2001, + 0x1a0b, 0x2003, 0x0000, 0x7030, 0x9065, 0x090c, 0x0d7d, 0x7034, + 0x9092, 0x00c8, 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, + 0x0110, 0x7007, 0x0000, 0x781f, 0x0808, 0x0040, 0x080c, 0xe764, + 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, 0xac8d, 0x781f, 0x0100, + 0x080c, 0xa8b5, 0x012e, 0x0005, 0x080c, 0xa899, 0x714c, 0x81ff, + 0x1128, 0x2011, 0x1a0e, 0x2013, 0x0000, 0x0438, 0x2061, 0x0100, + 0x7150, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7152, 0x714c, 0x9188, + 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, + 0x9085, 0x0012, 0x6016, 0x0088, 0x714c, 0x9188, 0x0008, 0x210c, + 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, + 0x6016, 0x0018, 0x706c, 0xc085, 0x706e, 0x781f, 0x0200, 0x080c, + 0xa8b5, 0x012e, 0x0005, 0x080c, 0xa899, 0x714c, 0x2160, 0x6003, + 0x0003, 0x2009, 0x004a, 0x080c, 0xac8d, 0x781f, 0x0200, 0x080c, + 0xa8b5, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, + 0x6003, 0x0003, 0x080c, 0xa899, 0x080c, 0x1d85, 0x781f, 0x0400, + 0x080c, 0xa8b5, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, + 0x2060, 0x080c, 0xa899, 0x080c, 0x1dcd, 0x781f, 0x0400, 0x080c, + 0xa8b5, 0x012e, 0x0005, 0x7030, 0x9065, 0x0148, 0x6044, 0xc0bc, + 0x6046, 0x7104, 0x9186, 0x0003, 0x0110, 0x080c, 0x96be, 0x012e, + 0x0005, 0x00f6, 0x703c, 0x9086, 0x0002, 0x0528, 0x704c, 0x907d, + 0x0510, 0x7844, 0xc0bc, 0x7846, 0x7820, 0x9086, 0x0009, 0x0118, + 0x080c, 0x9d79, 0x00c0, 0x7828, 0xd0fc, 0x1118, 0x080c, 0x9cf8, + 0x0090, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1130, 0x2001, + 0x197b, 0x2004, 0x9086, 0xaaaa, 0x1120, 0x2001, 0x0387, 0x2003, + 0x1000, 0x080c, 0x9c7d, 0x00fe, 0x012e, 0x0005, 0x080c, 0x7591, + 0x012e, 0x0005, 0x080c, 0x0d7d, 0x0005, 0x00e6, 0x2071, 0x19e6, + 0x6044, 0xc0bc, 0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, + 0x2019, 0x0001, 0x080c, 0xa133, 0x704f, 0x0000, 0x2001, 0x0109, + 0x2004, 0xd08c, 0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, + 0x703f, 0x0000, 0x080c, 0xa33e, 0x00ee, 0x0005, 0x0026, 0x7010, + 0x9c06, 0x1178, 0x080c, 0xa1fd, 0x6044, 0xc0fc, 0x6046, 0x600c, + 0x9015, 0x0120, 0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, + 0x9006, 0x002e, 0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, + 0xa1fd, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, + 0x600f, 0x0000, 0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, + 0x00d6, 0x0036, 0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x01f8, 0x080c, 0x8709, 0x080c, 0x9e4f, 0x68c3, 0x0000, + 0x080c, 0xa327, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2a49, 0x9006, 0x080c, 0x2a49, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, + 0x0038, 0x7808, 0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, + 0x003e, 0x00de, 0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, + 0x0100, 0x2001, 0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, + 0x2091, 0x2800, 0x0016, 0x0036, 0x080c, 0xa8ff, 0x003e, 0x001e, + 0x012e, 0x00ce, 0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, + 0x8319, 0x1d38, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0156, + 0x080c, 0x9b07, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, + 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, + 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, + 0x0060, 0x080c, 0x74ec, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6adc, + 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x080c, 0x87ce, + 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, 0x2071, 0x0250, + 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, 0x9398, 0x0002, + 0x9290, 0x0002, 0x1f04, 0xab00, 0x60c3, 0x0020, 0x080c, 0x9e1f, + 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9b07, 0x7a14, 0x82ff, + 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, + 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, + 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19bc, 0x2204, 0x8007, + 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, + 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7022, 0x2001, + 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, + 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, + 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, + 0x0804, 0x9e1f, 0x0006, 0x2001, 0x1837, 0x2004, 0xd0ac, 0x000e, + 0x0005, 0x2011, 0x0003, 0x080c, 0xa1be, 0x2011, 0x0002, 0x080c, + 0xa1c8, 0x080c, 0xa0b3, 0x0036, 0x901e, 0x080c, 0xa133, 0x003e, + 0x0005, 0x080c, 0x3381, 0x0188, 0x0016, 0x00b6, 0x00c6, 0x7010, + 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, 0x6644, 0xb85c, + 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, 0x2071, 0x188d, + 0x7000, 0x9005, 0x0140, 0x2001, 0x0812, 0x2071, 0x1800, 0x7076, + 0x707a, 0x706b, 0xffd4, 0x2071, 0x1800, 0x7074, 0x7056, 0x705b, + 0x1ddc, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, + 0x7554, 0x9582, 0x0010, 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, + 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, + 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, + 0x001c, 0x7068, 0x9502, 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, + 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, + 0x2071, 0x1800, 0x7554, 0x9582, 0x0010, 0x0600, 0x7058, 0x2060, + 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068, 0x9c02, + 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1228, 0x755a, 0x9085, + 0x0001, 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc8, 0x9006, 0x0cc8, + 0x9c82, 0x1ddc, 0x0a0c, 0x0d7d, 0x2001, 0x181a, 0x2004, 0x9c02, + 0x1a0c, 0x0d7d, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, + 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x605e, 0x6062, + 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x604a, + 0x602a, 0x6046, 0x6042, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, + 0x0005, 0x9006, 0x600e, 0x6016, 0x601a, 0x6012, 0x6022, 0x6002, + 0x601e, 0x605e, 0x6062, 0x604a, 0x6046, 0x2061, 0x1800, 0x6054, + 0x8000, 0x6056, 0x0005, 0x0006, 0x6000, 0x9086, 0x0000, 0x01d0, + 0x601c, 0xd084, 0x190c, 0x1a94, 0x6023, 0x0007, 0x2001, 0x1985, + 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, + 0x080c, 0xe571, 0x604b, 0x0000, 0x6044, 0xd0fc, 0x1129, 0x9006, + 0x6046, 0x6016, 0x000e, 0x0005, 0x080c, 0xa899, 0x0106, 0x2001, + 0x19f9, 0x2004, 0x9c06, 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, + 0xa133, 0x003e, 0x080c, 0xa33e, 0x010e, 0x090c, 0xa8b5, 0x0005, + 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, + 0x0001, 0x0608, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, + 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, + 0x9502, 0x1230, 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x705b, 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, + 0x0002, 0xaca1, 0xacab, 0xacc6, 0xace1, 0xcfd7, 0xcff4, 0xd00f, + 0xaca1, 0xacab, 0x8fb5, 0xacfd, 0xaca1, 0xaca1, 0xaca1, 0xaca1, + 0xaca1, 0x9186, 0x0013, 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, + 0x95ff, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0d7d, 0x0013, 0x006e, 0x0005, 0xacc4, 0xb430, 0xb60d, 0xacc4, + 0xb6a3, 0xafc6, 0xacc4, 0xacc4, 0xb3b2, 0xbc0d, 0xacc4, 0xacc4, + 0xacc4, 0xacc4, 0xacc4, 0xacc4, 0x080c, 0x0d7d, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0xacdf, + 0xc215, 0xacdf, 0xacdf, 0xacdf, 0xacdf, 0xacdf, 0xacdf, 0xc1b7, + 0xc398, 0xacdf, 0xc252, 0xc2d6, 0xc252, 0xc2d6, 0xacdf, 0x080c, + 0x0d7d, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d7d, 0x6000, 0x0002, + 0xacfb, 0xbc57, 0xbcee, 0xbe6e, 0xbedd, 0xacfb, 0xacfb, 0xacfb, + 0xbc26, 0xc138, 0xc13b, 0xacfb, 0xacfb, 0xacfb, 0xacfb, 0xc16b, + 0xacfb, 0xacfb, 0xacfb, 0x080c, 0x0d7d, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0xad16, 0xad16, + 0xad54, 0xadf3, 0xae73, 0xad16, 0xad16, 0xad16, 0xad18, 0xad16, + 0xad16, 0xad16, 0xad16, 0xad16, 0xad16, 0xad16, 0x080c, 0x0d7d, + 0x9186, 0x004c, 0x0560, 0x9186, 0x0003, 0x190c, 0x0d7d, 0x0096, + 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, + 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa836, 0xa8b0, + 0xa83a, 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092, 0x199a, 0x0210, + 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, + 0x080c, 0x1bdf, 0x2009, 0x8030, 0x080c, 0x9280, 0x0005, 0x6010, + 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, 0xae95, 0x080c, + 0xcf9c, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, + 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, + 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, + 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, + 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, + 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, + 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, + 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, + 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0xadbb, 0xadbb, + 0xadb6, 0xadb9, 0xadbb, 0xadb3, 0xada6, 0xada6, 0xada6, 0xada6, + 0xada6, 0xada6, 0xada6, 0xada6, 0xada6, 0xada6, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, + 0x00de, 0x080c, 0x0d7d, 0x080c, 0xb862, 0x0028, 0x080c, 0xb947, + 0x0010, 0x080c, 0xba3d, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, + 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xaf53, 0x0530, 0xa804, + 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, + 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x12b0, 0x080c, 0xb114, + 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, + 0x00fe, 0x009e, 0x00de, 0x0804, 0xabf0, 0x2001, 0x002c, 0x900e, + 0x080c, 0xafb9, 0x0c70, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, + 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0d7d, 0x91b2, 0x0050, 0x1a0c, + 0x0d7d, 0x9182, 0x0047, 0x0042, 0x080c, 0xaaab, 0x0120, 0x9086, + 0x0002, 0x0904, 0xad54, 0x0005, 0xae15, 0xae15, 0xae17, 0xae49, + 0xae15, 0xae15, 0xae15, 0xae15, 0xae5c, 0x080c, 0x0d7d, 0x00d6, + 0x0016, 0x0096, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, + 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, + 0x2001, 0x0000, 0x900e, 0x080c, 0xafb9, 0x080c, 0xabf0, 0x00a8, + 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, + 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, + 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, + 0x0005, 0x080c, 0x965a, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, + 0xc865, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6d9f, 0x009e, 0x00de, + 0x080c, 0xabf0, 0x0804, 0x96bd, 0x080c, 0x965a, 0x080c, 0x320f, + 0x080c, 0xcf99, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xc865, + 0x0120, 0xa87b, 0x0029, 0x080c, 0x6d9f, 0x009e, 0x00de, 0x080c, + 0xabf0, 0x0804, 0x96bd, 0x9182, 0x0047, 0x0002, 0xae83, 0xae85, + 0xae83, 0xae83, 0xae83, 0xae83, 0xae83, 0xae83, 0xae83, 0xae83, + 0xae83, 0xae83, 0xae85, 0x080c, 0x0d7d, 0x00d6, 0x0096, 0x601f, + 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, + 0x6d9f, 0x009e, 0x00de, 0x0804, 0xabf0, 0x0026, 0x0036, 0x0056, + 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x1047, 0x000e, + 0x090c, 0x0d7d, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, + 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, 0x7990, + 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, + 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, + 0x0034, 0x1228, 0x2011, 0x001f, 0x080c, 0xc41b, 0x04c0, 0x2130, + 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xc41b, 0x96b2, 0x0034, + 0xb004, 0x904d, 0x0110, 0x080c, 0x0ff9, 0x080c, 0x1047, 0x01d0, + 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, + 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xc41b, 0x00b8, + 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, + 0xc41b, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, + 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, + 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, + 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x6d9f, 0x000e, + 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, + 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, + 0x1047, 0x000e, 0x090c, 0x0d7d, 0xa960, 0x21e8, 0xa95c, 0x9188, + 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, + 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, + 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, + 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, + 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, 0x6d9f, 0x009e, + 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, + 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, + 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, + 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, + 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, 0x1047, 0x2900, + 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, + 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, + 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, + 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, + 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, + 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xaf68, 0x0804, 0xaf6a, + 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, + 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, + 0x080c, 0x6d93, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, + 0x1118, 0x080c, 0xabf0, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0d7d, + 0x080c, 0xabf0, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, + 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, + 0x4003, 0x0136, 0x9080, 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, + 0x0001, 0x3418, 0x8318, 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, + 0x8211, 0x1db8, 0x2011, 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, + 0x2398, 0x4003, 0x3418, 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, + 0x080c, 0xc865, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, + 0x0103, 0x009e, 0x0804, 0xabf0, 0x0096, 0x00d6, 0x0036, 0x7330, + 0x9386, 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, + 0x00be, 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, + 0x0103, 0xab32, 0x080c, 0xabf0, 0x003e, 0x00de, 0x009e, 0x0005, + 0x0011, 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xcf84, 0x0188, + 0x6014, 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, + 0x0000, 0x2009, 0x0022, 0x080c, 0xb408, 0x9006, 0x001e, 0x000e, + 0x0005, 0x9085, 0x0001, 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, + 0x9e80, 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, + 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, + 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, + 0x000a, 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, + 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, + 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, + 0x2048, 0xa867, 0x0103, 0x080c, 0xabf0, 0x001e, 0x009e, 0x0005, + 0x0096, 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, + 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, + 0x0004, 0x9108, 0x810b, 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, + 0x2048, 0x080c, 0xc41b, 0x080c, 0xc865, 0x0140, 0x6014, 0x2048, + 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xabf0, + 0x001e, 0x009e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, + 0x0200, 0x0110, 0x2009, 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, + 0x0d7d, 0xa97a, 0x080c, 0x6d9f, 0x009e, 0x080c, 0xabf0, 0x001e, + 0x0005, 0x0016, 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, + 0x0004, 0x0010, 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, + 0x000c, 0x6014, 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, + 0x080c, 0xc41b, 0x009e, 0x080c, 0xc865, 0x0148, 0xa804, 0x9005, + 0x1158, 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, + 0xabf0, 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, + 0x9086, 0x0100, 0x1118, 0x080c, 0xb5c6, 0x00e0, 0xa034, 0x8007, + 0x800c, 0x8806, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x000c, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, + 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x1296, + 0x0019, 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x1047, + 0x000e, 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, + 0xae6a, 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, + 0xad9a, 0x0086, 0x2940, 0x080c, 0x113c, 0x008e, 0x9085, 0x0001, + 0x009e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, + 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, + 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, + 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xcefc, 0x001e, + 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, + 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0xabf0, 0x0020, 0x0039, + 0x0010, 0x080c, 0xb23d, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, + 0x6814, 0x2048, 0x9186, 0x0015, 0x0904, 0xb21c, 0x918e, 0x0016, + 0x1904, 0xb23b, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, + 0x9186, 0x0300, 0x1904, 0xb1f6, 0x89ff, 0x1138, 0x6800, 0x9086, + 0x000f, 0x0904, 0xb1d8, 0x0804, 0xb239, 0x6808, 0x9086, 0xffff, + 0x1904, 0xb21e, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, + 0xa83c, 0xa940, 0x9105, 0x1904, 0xb21e, 0x6824, 0xd084, 0x1904, + 0xb21e, 0xd0b4, 0x0158, 0x0016, 0x2001, 0x1985, 0x200c, 0x6018, + 0x9102, 0x9082, 0x0005, 0x001e, 0x1a04, 0xb21e, 0x080c, 0xca54, + 0x6864, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, + 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x9181, 0xa884, 0x920a, + 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, + 0x080c, 0xc56e, 0x00ce, 0x0804, 0xb239, 0x00c6, 0xa868, 0xd0fc, + 0x1118, 0x080c, 0x60d6, 0x0010, 0x080c, 0x64de, 0x00ce, 0x1904, + 0xb21e, 0x00c6, 0x2d60, 0x080c, 0xabf0, 0x00ce, 0x0804, 0xb239, + 0x00c6, 0x080c, 0xac60, 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, + 0x080c, 0xccfe, 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, + 0xabf0, 0x00ce, 0x080c, 0xac8d, 0x00ce, 0x0804, 0xb239, 0x2001, + 0x1987, 0x2004, 0x684a, 0x00ce, 0x0804, 0xb239, 0x7008, 0x9086, + 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, 0xc1bc, 0xb902, + 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, 0xcf3e, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, + 0x9239, 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, + 0x1987, 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8, 0x89ff, 0x090c, + 0x0d7d, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, 0xa87b, 0x0003, + 0x080c, 0x6bb5, 0x080c, 0xca54, 0x080c, 0xac2b, 0x0026, 0x6010, + 0x00b6, 0x2058, 0xba3c, 0x080c, 0x676f, 0x00be, 0x002e, 0x00de, + 0x00ce, 0x080c, 0xabf0, 0x009e, 0x0005, 0x9186, 0x0015, 0x1128, + 0x2001, 0x1987, 0x2004, 0x684a, 0x0068, 0x918e, 0x0016, 0x1160, + 0x00c6, 0x2d00, 0x2060, 0x080c, 0xe571, 0x080c, 0x88d7, 0x080c, + 0xabf0, 0x00ce, 0x080c, 0xabf0, 0x0005, 0x0026, 0x0036, 0x0046, + 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, 0x1987, 0x2004, + 0x684a, 0x0804, 0xb2b7, 0x00c6, 0x2d60, 0x080c, 0xc446, 0x00ce, + 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, + 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9239, 0x00ce, + 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, 0x090c, 0x0d7d, + 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, 0x0178, 0xa843, + 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, 0x2001, 0x0001, + 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, 0xa87c, 0xd0b4, + 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, 0xa838, 0xa934, + 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, 0x9306, 0x1118, + 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, + 0x0005, 0x6832, 0x080c, 0xcbe8, 0x080c, 0x96bd, 0x0010, 0x080c, + 0xabf0, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, + 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, + 0x9206, 0x1904, 0xb322, 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, + 0x00be, 0x9206, 0x1904, 0xb322, 0x6038, 0x2068, 0x6824, 0xc0dc, + 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb322, 0x9286, 0x0002, + 0x0904, 0xb322, 0x9286, 0x0000, 0x05e8, 0x6808, 0x633c, 0x9306, + 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, 0x918e, 0x0016, + 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01c0, + 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, 0x9186, 0x004e, + 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, 0x2048, 0x080c, + 0xc865, 0x090c, 0x0d7d, 0xa87b, 0x0003, 0x009e, 0x080c, 0xcf3e, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, + 0x080c, 0x9239, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, 0x1987, + 0x2004, 0x704a, 0x080c, 0xabf0, 0x002e, 0x00de, 0x00ee, 0x0005, + 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, 0x2058, 0x91b6, + 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, 0xbc02, 0x0460, + 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0010, 0x2019, + 0x000a, 0x20a9, 0x0004, 0x080c, 0xbbd5, 0x002e, 0x003e, 0x015e, + 0x009e, 0x1904, 0xb391, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, + 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, 0x080c, 0xbbd5, + 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, 0xba0a, 0x733c, + 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, + 0x009e, 0x00be, 0x0804, 0xafff, 0x0096, 0x2048, 0xaa12, 0xab16, + 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, + 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, + 0xada4, 0x2031, 0x0000, 0x2041, 0x1296, 0x080c, 0xb114, 0x0130, + 0x00fe, 0x009e, 0x080c, 0xabf0, 0x00be, 0x0005, 0x080c, 0xb5c6, + 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x320f, 0x080c, 0xcf99, 0x00fe, + 0x00c6, 0x080c, 0xab9a, 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, + 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, + 0x6594, 0x080c, 0x65c0, 0x080c, 0x9240, 0x080c, 0x96bd, 0x00ce, + 0x0804, 0xb364, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0d7d, 0x91b2, + 0x0040, 0x1a04, 0xb41a, 0x0002, 0xb408, 0xb408, 0xb3fe, 0xb408, + 0xb408, 0xb408, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb408, 0xb3fc, 0xb408, 0xb408, 0xb3fc, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fe, 0xb3fc, 0xb3fc, 0xb3fc, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb408, 0xb408, + 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, 0xb3fc, + 0xb3fc, 0xb408, 0xb3fc, 0xb3fc, 0x080c, 0x0d7d, 0x0066, 0x00b6, + 0x6610, 0x2658, 0xb8d4, 0xc08c, 0xb8d6, 0x00be, 0x006e, 0x0000, + 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, 0x9240, + 0x0010, 0x080c, 0x9239, 0x0126, 0x2091, 0x8000, 0x080c, 0x96bd, + 0x012e, 0x0005, 0x2600, 0x0002, 0xb408, 0xb408, 0xb42e, 0xb408, + 0xb408, 0xb42e, 0xb42e, 0xb42e, 0xb42e, 0xb408, 0xb42e, 0xb408, + 0xb42e, 0xb408, 0xb42e, 0xb42e, 0xb42e, 0xb42e, 0x080c, 0x0d7d, + 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7d, 0x91b6, 0x0013, 0x0904, + 0xb505, 0x91b6, 0x0027, 0x1904, 0xb4b1, 0x080c, 0x95ff, 0x6004, + 0x080c, 0xca69, 0x01b0, 0x080c, 0xca7a, 0x01a8, 0x908e, 0x0021, + 0x0904, 0xb4ae, 0x908e, 0x0022, 0x1130, 0x080c, 0xb02b, 0x0904, + 0xb4aa, 0x0804, 0xb4ab, 0x908e, 0x003d, 0x0904, 0xb4ae, 0x0804, + 0xb4a4, 0x080c, 0x323e, 0x2001, 0x0007, 0x080c, 0x6594, 0x6010, + 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xb5c6, 0x9186, 0x007e, + 0x1148, 0x2001, 0x1837, 0x2014, 0xc285, 0x080c, 0x74ec, 0x1108, + 0xc2ad, 0x2202, 0x080c, 0xa899, 0x0036, 0x0026, 0x2019, 0x0028, + 0x2110, 0x080c, 0xe67d, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, + 0x2110, 0x2019, 0x0028, 0x080c, 0x93c6, 0x0076, 0x903e, 0x080c, + 0x928f, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, + 0xe038, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xa8b5, 0x080c, + 0xcf99, 0x0016, 0x080c, 0xccf6, 0x080c, 0xabf0, 0x001e, 0x080c, + 0x3318, 0x080c, 0x96bd, 0x0030, 0x080c, 0xccf6, 0x080c, 0xabf0, + 0x080c, 0x96bd, 0x0005, 0x080c, 0xb5c6, 0x0cb0, 0x080c, 0xb602, + 0x0c98, 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, + 0xaaab, 0x0d80, 0x9086, 0x0002, 0x0904, 0xb60d, 0x0c58, 0x9186, + 0x0014, 0x1d40, 0x080c, 0x95ff, 0x6004, 0x908e, 0x0022, 0x1118, + 0x080c, 0xb02b, 0x09f8, 0x080c, 0x320f, 0x080c, 0xcf99, 0x080c, + 0xca69, 0x1190, 0x080c, 0x323e, 0x6010, 0x00b6, 0x2058, 0xb9a0, + 0x00be, 0x080c, 0xb5c6, 0x9186, 0x007e, 0x1128, 0x2001, 0x1837, + 0x200c, 0xc185, 0x2102, 0x0800, 0x080c, 0xca7a, 0x1120, 0x080c, + 0xb5c6, 0x0804, 0xb4a4, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, + 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x35b9, 0x00fe, + 0x00ee, 0x0804, 0xb4a4, 0x6004, 0x908e, 0x0021, 0x0d40, 0x908e, + 0x0022, 0x090c, 0xb5c6, 0x0804, 0xb4a4, 0x90b2, 0x0040, 0x1a04, + 0xb5a6, 0x2008, 0x0002, 0xb54d, 0xb54e, 0xb551, 0xb554, 0xb557, + 0xb55a, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, + 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, + 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, + 0xb54b, 0xb55d, 0xb568, 0xb54b, 0xb569, 0xb568, 0xb54b, 0xb54b, + 0xb54b, 0xb54b, 0xb54b, 0xb568, 0xb568, 0xb54b, 0xb54b, 0xb54b, + 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb54b, 0xb591, 0xb568, 0xb54b, + 0xb564, 0xb54b, 0xb54b, 0xb54b, 0xb565, 0xb54b, 0xb54b, 0xb54b, + 0xb568, 0xb58c, 0xb54b, 0x080c, 0x0d7d, 0x00d0, 0x2001, 0x000b, + 0x00f8, 0x2001, 0x0003, 0x00e0, 0x2001, 0x0005, 0x00c8, 0x2001, + 0x0001, 0x00b0, 0x2001, 0x0009, 0x0098, 0x6003, 0x0005, 0x080c, + 0xcf9c, 0x080c, 0x96bd, 0x0058, 0x0018, 0x0010, 0x080c, 0x6594, + 0x04b8, 0x080c, 0xcf9c, 0x6003, 0x0004, 0x080c, 0x96bd, 0x0005, + 0x080c, 0x6594, 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, 0x1985, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, - 0x003e, 0x080c, 0x9684, 0x0c18, 0x080c, 0xccc3, 0x080c, 0xabdf, + 0x003e, 0x080c, 0x96bd, 0x0c18, 0x080c, 0xccf6, 0x080c, 0xabf0, 0x08f0, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, - 0x3599, 0x00fe, 0x00ee, 0x080c, 0x95c6, 0x080c, 0xabdf, 0x0878, - 0x6003, 0x0002, 0x080c, 0xcf69, 0x0804, 0x9684, 0x2600, 0x2008, - 0x0002, 0xb59d, 0xb580, 0xb59b, 0xb580, 0xb580, 0xb59b, 0xb59b, - 0xb59b, 0xb59b, 0xb580, 0xb59b, 0xb580, 0xb59b, 0xb580, 0xb59b, - 0xb59b, 0xb59b, 0xb59b, 0x080c, 0x0d7d, 0x0096, 0x6014, 0x2048, - 0x080c, 0x6d7b, 0x009e, 0x080c, 0xabdf, 0x0005, 0x00e6, 0x0096, - 0x0026, 0x0016, 0x080c, 0xc832, 0x0568, 0x6014, 0x2048, 0xa864, + 0x35b9, 0x00fe, 0x00ee, 0x080c, 0x95ff, 0x080c, 0xabf0, 0x0878, + 0x6003, 0x0002, 0x080c, 0xcf9c, 0x0804, 0x96bd, 0x2600, 0x2008, + 0x0002, 0xb5bd, 0xb5a0, 0xb5bb, 0xb5a0, 0xb5a0, 0xb5bb, 0xb5bb, + 0xb5bb, 0xb5bb, 0xb5a0, 0xb5bb, 0xb5a0, 0xb5bb, 0xb5a0, 0xb5bb, + 0xb5bb, 0xb5bb, 0xb5bb, 0x080c, 0x0d7d, 0x0096, 0x6014, 0x2048, + 0x080c, 0x6d9f, 0x009e, 0x080c, 0xabf0, 0x0005, 0x00e6, 0x0096, + 0x0026, 0x0016, 0x080c, 0xc865, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, - 0x5476, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xce30, 0x0090, + 0x5496, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, + 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xce63, 0x0090, 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0d7d, 0x6604, - 0x96b6, 0x004d, 0x1120, 0x080c, 0xcd4f, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x0043, 0x1120, 0x080c, 0xcd98, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x004b, 0x1120, 0x080c, 0xcdc4, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x0033, 0x1120, 0x080c, 0xcce5, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x0028, 0x1120, 0x080c, 0xca85, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x0029, 0x1120, 0x080c, 0xcac6, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x001f, 0x1120, 0x080c, 0xafc2, 0x0804, 0xb672, 0x6604, - 0x96b6, 0x0000, 0x1118, 0x080c, 0xb30a, 0x04e0, 0x6604, 0x96b6, - 0x0022, 0x1118, 0x080c, 0xaffb, 0x04a8, 0x6604, 0x96b6, 0x0035, - 0x1118, 0x080c, 0xb121, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, - 0x080c, 0xb29f, 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, - 0xb033, 0x0400, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb06f, - 0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xb0b0, 0x0090, - 0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, 0xb09a, 0x0058, 0x91b6, + 0x96b6, 0x004d, 0x1120, 0x080c, 0xcd82, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x0043, 0x1120, 0x080c, 0xcdcb, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x004b, 0x1120, 0x080c, 0xcdf7, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x0033, 0x1120, 0x080c, 0xcd18, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x0028, 0x1120, 0x080c, 0xcab8, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x0029, 0x1120, 0x080c, 0xcaf9, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x001f, 0x1120, 0x080c, 0xafd3, 0x0804, 0xb692, 0x6604, + 0x96b6, 0x0000, 0x1118, 0x080c, 0xb328, 0x04e0, 0x6604, 0x96b6, + 0x0022, 0x1118, 0x080c, 0xb00c, 0x04a8, 0x6604, 0x96b6, 0x0035, + 0x1118, 0x080c, 0xb132, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, + 0x080c, 0xb2bd, 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, + 0xb044, 0x0400, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb080, + 0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xb0c1, 0x0090, + 0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, 0xb0ab, 0x0058, 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, - 0x0804, 0xb8ce, 0x00be, 0x0005, 0x080c, 0xac99, 0x0cd8, 0xb68f, - 0xb692, 0xb68f, 0xb6d9, 0xb68f, 0xb842, 0xb8db, 0xb68f, 0xb68f, - 0xb8a4, 0xb68f, 0xb8ba, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0xabdf, 0xa001, + 0x0804, 0xb8ee, 0x00be, 0x0005, 0x080c, 0xacaa, 0x0cd8, 0xb6af, + 0xb6b2, 0xb6af, 0xb6f9, 0xb6af, 0xb862, 0xb8fb, 0xb6af, 0xb6af, + 0xb8c4, 0xb6af, 0xb8da, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, + 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0xabf0, 0xa001, 0xa001, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, 0x0074, - 0x1540, 0x080c, 0xdfcc, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, + 0x1540, 0x080c, 0xe009, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, 0x00f9, - 0x00be, 0x2001, 0x0006, 0x080c, 0x6570, 0x080c, 0x321e, 0x080c, - 0xabdf, 0x0098, 0x2001, 0x000a, 0x080c, 0x6570, 0x080c, 0x321e, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9207, 0x080c, 0x9684, - 0x0020, 0x2001, 0x0001, 0x080c, 0xb812, 0x00ee, 0x0005, 0x00d6, - 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x655c, 0x2069, 0x1847, - 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x659c, 0x00de, + 0x00be, 0x2001, 0x0006, 0x080c, 0x6594, 0x080c, 0x323e, 0x080c, + 0xabf0, 0x0098, 0x2001, 0x000a, 0x080c, 0x6594, 0x080c, 0x323e, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, + 0x0020, 0x2001, 0x0001, 0x080c, 0xb832, 0x00ee, 0x0005, 0x00d6, + 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x6580, 0x2069, 0x1847, + 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x65c0, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204, 0x9086, - 0x0074, 0x1904, 0xb7e7, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, - 0x1120, 0x080c, 0xba28, 0x0804, 0xb74b, 0x080c, 0xba1d, 0x6010, + 0x0074, 0x1904, 0xb807, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, + 0x1120, 0x080c, 0xba48, 0x0804, 0xb76b, 0x080c, 0xba3d, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, - 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xce30, 0x0030, 0xa807, + 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xce63, 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, - 0x6570, 0x080c, 0x321e, 0x080c, 0xabdf, 0x0804, 0xb7ec, 0x080c, - 0xb7fa, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, + 0x6594, 0x080c, 0x323e, 0x080c, 0xabf0, 0x0804, 0xb80c, 0x080c, + 0xb81a, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x080c, 0xce30, 0x08f8, 0x080c, 0xb7f0, - 0x0160, 0x9006, 0x080c, 0x655c, 0x2001, 0x0004, 0x080c, 0x659c, - 0x2001, 0x0007, 0x080c, 0x6570, 0x08a0, 0x2001, 0x0004, 0x080c, - 0x6570, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x9207, 0x080c, - 0x9684, 0x0804, 0xb7ec, 0xb85c, 0xd0e4, 0x01d8, 0x080c, 0xcc5d, - 0x080c, 0x74c8, 0x0118, 0xd0dc, 0x1904, 0xb70d, 0x2011, 0x1837, + 0x900e, 0x2011, 0x4000, 0x080c, 0xce63, 0x08f8, 0x080c, 0xb810, + 0x0160, 0x9006, 0x080c, 0x6580, 0x2001, 0x0004, 0x080c, 0x65c0, + 0x2001, 0x0007, 0x080c, 0x6594, 0x08a0, 0x2001, 0x0004, 0x080c, + 0x6594, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x9240, 0x080c, + 0x96bd, 0x0804, 0xb80c, 0xb85c, 0xd0e4, 0x01d8, 0x080c, 0xcc90, + 0x080c, 0x74ec, 0x0118, 0xd0dc, 0x1904, 0xb72d, 0x2011, 0x1837, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x196c, 0x2004, 0x00f6, 0x2079, - 0x0100, 0x78e3, 0x0000, 0x080c, 0x2688, 0x78e2, 0x00fe, 0x0804, - 0xb70d, 0x080c, 0xcc9e, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, - 0x0006, 0x080c, 0xe15c, 0x000e, 0x1904, 0xb70d, 0xc0b5, 0x2012, - 0x2001, 0x0006, 0x080c, 0x6570, 0x9006, 0x080c, 0x655c, 0x00c6, + 0x0100, 0x78e3, 0x0000, 0x080c, 0x26a4, 0x78e2, 0x00fe, 0x0804, + 0xb72d, 0x080c, 0xccd1, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, + 0x0006, 0x080c, 0xe199, 0x000e, 0x1904, 0xb72d, 0xc0b5, 0x2012, + 0x2001, 0x0006, 0x080c, 0x6594, 0x9006, 0x080c, 0x6580, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, 0x7082, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, - 0x780e, 0x00fe, 0x080c, 0x265d, 0x00f6, 0x2100, 0x900e, 0x080c, - 0x2614, 0x795e, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, + 0x780e, 0x00fe, 0x080c, 0x2679, 0x00f6, 0x2100, 0x900e, 0x080c, + 0x2630, 0x795e, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, - 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x265d, 0x00f6, - 0x2079, 0x1800, 0x7982, 0x2100, 0x900e, 0x080c, 0x2614, 0x795e, - 0x00fe, 0x8108, 0x080c, 0x65bf, 0x2b00, 0x00ce, 0x1904, 0xb70d, + 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x2679, 0x00f6, + 0x2079, 0x1800, 0x7982, 0x2100, 0x900e, 0x080c, 0x2630, 0x795e, + 0x00fe, 0x8108, 0x080c, 0x65e3, 0x2b00, 0x00ce, 0x1904, 0xb72d, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, - 0x2001, 0x0002, 0x080c, 0x6570, 0x6023, 0x0001, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x9207, 0x080c, 0x9684, 0x0028, 0x080c, - 0xb5a6, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, + 0x2001, 0x0002, 0x080c, 0x6594, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0028, 0x080c, + 0xb5c6, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, - 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xe699, 0x0190, 0x2071, 0x0260, + 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xe6d6, 0x0190, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, 0x080c, - 0x6570, 0x080c, 0x56e9, 0x1120, 0x2001, 0x0007, 0x080c, 0x659c, + 0x6594, 0x080c, 0x5709, 0x1120, 0x2001, 0x0007, 0x080c, 0x65c0, 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, - 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4b09, 0x004e, - 0x003e, 0x080c, 0x321e, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, - 0x0804, 0xabdf, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, - 0x7090, 0x9086, 0x0014, 0x1904, 0xb89a, 0x080c, 0x56e9, 0x1170, + 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4b29, 0x004e, + 0x003e, 0x080c, 0x323e, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, + 0x0804, 0xabf0, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, + 0x7090, 0x9086, 0x0014, 0x1904, 0xb8ba, 0x080c, 0x5709, 0x1170, 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, - 0x2021, 0x0006, 0x080c, 0x4cc0, 0x004e, 0x003e, 0x00d6, 0x6010, - 0x2058, 0x080c, 0x66bb, 0x080c, 0xb6c7, 0x00de, 0x080c, 0xbaee, + 0x2021, 0x0006, 0x080c, 0x4ce0, 0x004e, 0x003e, 0x00d6, 0x6010, + 0x2058, 0x080c, 0x66df, 0x080c, 0xb6e7, 0x00de, 0x080c, 0xbb0e, 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, - 0x080c, 0x6570, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, + 0x080c, 0x6594, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xce30, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x4000, 0x080c, 0xce63, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, - 0x009e, 0x080c, 0x321e, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, - 0xabdf, 0x0028, 0x080c, 0xb5a6, 0x9006, 0x080c, 0xb812, 0x001e, + 0x009e, 0x080c, 0x323e, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, + 0xabf0, 0x0028, 0x080c, 0xb5c6, 0x9006, 0x080c, 0xb832, 0x001e, 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, - 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x6570, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9207, 0x0804, 0x9684, 0x2001, 0x0001, - 0x0804, 0xb812, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, - 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x6570, - 0x0804, 0xabdf, 0x2001, 0x0001, 0x0804, 0xb812, 0x0002, 0xb68f, - 0xb8e6, 0xb68f, 0xb927, 0xb68f, 0xb9d4, 0xb8db, 0xb68f, 0xb68f, - 0xb9e8, 0xb68f, 0xb9fa, 0x6604, 0x9686, 0x0003, 0x0904, 0xb842, - 0x96b6, 0x001e, 0x1110, 0x080c, 0xabdf, 0x0005, 0x00b6, 0x00d6, - 0x00c6, 0x080c, 0xba0c, 0x11a0, 0x9006, 0x080c, 0x655c, 0x080c, - 0x31ef, 0x080c, 0xcf66, 0x2001, 0x0002, 0x080c, 0x6570, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9207, 0x080c, 0x9684, 0x0418, + 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x6594, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x9240, 0x0804, 0x96bd, 0x2001, 0x0001, + 0x0804, 0xb832, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, + 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x6594, + 0x0804, 0xabf0, 0x2001, 0x0001, 0x0804, 0xb832, 0x0002, 0xb6af, + 0xb906, 0xb6af, 0xb947, 0xb6af, 0xb9f4, 0xb8fb, 0xb6af, 0xb6af, + 0xba08, 0xb6af, 0xba1a, 0x6604, 0x9686, 0x0003, 0x0904, 0xb862, + 0x96b6, 0x001e, 0x1110, 0x080c, 0xabf0, 0x0005, 0x00b6, 0x00d6, + 0x00c6, 0x080c, 0xba2c, 0x11a0, 0x9006, 0x080c, 0x6580, 0x080c, + 0x320f, 0x080c, 0xcf99, 0x2001, 0x0002, 0x080c, 0x6594, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0418, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0xb842, 0x601b, 0x000a, 0x0088, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x1900, 0x1108, 0x08a0, 0x080c, 0x31ef, 0x080c, 0xcf66, 0x2001, - 0x0001, 0x080c, 0xb812, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, - 0x00b6, 0x0026, 0x9016, 0x080c, 0xba1a, 0x00d6, 0x2069, 0x197b, + 0x1900, 0x1108, 0x08a0, 0x080c, 0x320f, 0x080c, 0xcf99, 0x2001, + 0x0001, 0x080c, 0xb832, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, + 0x00b6, 0x0026, 0x9016, 0x080c, 0xba3a, 0x00d6, 0x2069, 0x197b, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, - 0x00de, 0x0088, 0x9006, 0x080c, 0x655c, 0x2001, 0x0002, 0x080c, - 0x6570, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9207, 0x080c, - 0x9684, 0x0804, 0xb9a4, 0x080c, 0xc832, 0x01b0, 0x6014, 0x2048, + 0x00de, 0x0088, 0x9006, 0x080c, 0x6580, 0x2001, 0x0002, 0x080c, + 0x6594, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9240, 0x080c, + 0x96bd, 0x0804, 0xb9c4, 0x080c, 0xc865, 0x01b0, 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, - 0x0002, 0x080c, 0xce8a, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, + 0x0002, 0x080c, 0xcebd, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, - 0x9006, 0x0c38, 0x080c, 0xb5a6, 0x2009, 0x026e, 0x2134, 0x96b4, + 0x9006, 0x0c38, 0x080c, 0xb5c6, 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01c0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, 0x2001, 0x0004, - 0x080c, 0x6570, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, - 0x2001, 0x0001, 0x080c, 0xb812, 0x002e, 0x00be, 0x009e, 0x0005, - 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xc832, 0x0140, + 0x080c, 0x6594, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, + 0x2001, 0x0001, 0x080c, 0xb832, 0x002e, 0x00be, 0x009e, 0x0005, + 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xc865, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c40, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, - 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fb7, 0x00ee, - 0x0010, 0x080c, 0x31ef, 0x0860, 0x080c, 0xba1a, 0x1160, 0x2001, - 0x0004, 0x080c, 0x6570, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x9207, 0x0804, 0x9684, 0x080c, 0xb5a6, 0x9006, 0x0804, 0xb812, - 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x6570, 0x6003, 0x0001, - 0x6007, 0x0005, 0x080c, 0x9207, 0x0804, 0x9684, 0x2001, 0x0001, - 0x0804, 0xb812, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x6570, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9207, 0x0804, 0x9684, - 0x2001, 0x0001, 0x0804, 0xb812, 0x2009, 0x026e, 0x2104, 0x9086, + 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fd7, 0x00ee, + 0x0010, 0x080c, 0x320f, 0x0860, 0x080c, 0xba3a, 0x1160, 0x2001, + 0x0004, 0x080c, 0x6594, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, + 0x9240, 0x0804, 0x96bd, 0x080c, 0xb5c6, 0x9006, 0x0804, 0xb832, + 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x6594, 0x6003, 0x0001, + 0x6007, 0x0005, 0x080c, 0x9240, 0x0804, 0x96bd, 0x2001, 0x0001, + 0x0804, 0xb832, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x6594, + 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9240, 0x0804, 0x96bd, + 0x2001, 0x0001, 0x0804, 0xb832, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, - 0x6110, 0x2158, 0x080c, 0x662f, 0x001e, 0x00ce, 0x00be, 0x0005, + 0x6110, 0x2158, 0x080c, 0x6653, 0x001e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, - 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xbac0, - 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6a66, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xe2d9, 0x2001, + 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xbae0, + 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6a8a, + 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xe316, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x31b4, 0x00e6, 0x2071, 0x1800, 0x080c, 0x2fc0, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x32f8, - 0x8108, 0x1f04, 0xba5e, 0x015e, 0x00ce, 0x080c, 0xba1d, 0x2071, + 0x080c, 0x31d4, 0x00e6, 0x2071, 0x1800, 0x080c, 0x2fe0, 0x00ee, + 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x3318, + 0x8108, 0x1f04, 0xba7e, 0x015e, 0x00ce, 0x080c, 0xba3d, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1837, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, - 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x265d, 0x080c, - 0x74c8, 0x0170, 0x2071, 0x0260, 0x2069, 0x1981, 0x7048, 0x206a, - 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xcc5d, - 0x0040, 0x2001, 0x0006, 0x080c, 0x6570, 0x080c, 0x321e, 0x080c, - 0xabdf, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, + 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x2679, 0x080c, + 0x74ec, 0x0170, 0x2071, 0x0260, 0x2069, 0x1981, 0x7048, 0x206a, + 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xcc90, + 0x0040, 0x2001, 0x0006, 0x080c, 0x6594, 0x080c, 0x323e, 0x080c, + 0xabf0, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbb5, 0x1148, 0x2011, - 0x027a, 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xbbb5, 0x1100, + 0x0004, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbd5, 0x1148, 0x2011, + 0x027a, 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xbbd5, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, @@ -5782,80 +5786,80 @@ unsigned short risc_code01[] = { 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f2, 0x252c, 0x2021, 0x19f9, 0x2424, 0x2061, 0x1ddc, 0x2071, - 0x1800, 0x7254, 0x7074, 0x9202, 0x1a04, 0xbb81, 0x080c, 0x8b72, - 0x0904, 0xbb7a, 0x080c, 0xe30a, 0x0904, 0xbb7a, 0x6720, 0x9786, - 0x0007, 0x0904, 0xbb7a, 0x2500, 0x9c06, 0x0904, 0xbb7a, 0x2400, - 0x9c06, 0x0904, 0xbb7a, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, + 0x1800, 0x7254, 0x7074, 0x9202, 0x1a04, 0xbba1, 0x080c, 0x8ba9, + 0x0904, 0xbb9a, 0x080c, 0xe347, 0x0904, 0xbb9a, 0x6720, 0x9786, + 0x0007, 0x0904, 0xbb9a, 0x2500, 0x9c06, 0x0904, 0xbb9a, 0x2400, + 0x9c06, 0x0904, 0xbb9a, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, - 0x1a77, 0x9786, 0x000a, 0x0148, 0x080c, 0xca47, 0x1130, 0x00ce, - 0x080c, 0xb5a6, 0x080c, 0xac1a, 0x00e8, 0x6014, 0x2048, 0x080c, - 0xc832, 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, - 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fec, 0x009e, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d6f, 0x080c, 0xca21, 0x080c, - 0xac1a, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, - 0xbb21, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, - 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xe27c, + 0x1a94, 0x9786, 0x000a, 0x0148, 0x080c, 0xca7a, 0x1130, 0x00ce, + 0x080c, 0xb5c6, 0x080c, 0xac2b, 0x00e8, 0x6014, 0x2048, 0x080c, + 0xc865, 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, + 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0ff9, 0x009e, + 0xab7a, 0xa877, 0x0000, 0x080c, 0x6d93, 0x080c, 0xca54, 0x080c, + 0xac2b, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, + 0xbb41, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, + 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xe2b9, 0x0c30, 0x9786, 0x0009, 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, - 0x2009, 0x004c, 0x080c, 0xac7c, 0x08e0, 0x9786, 0x000a, 0x0938, + 0x2009, 0x004c, 0x080c, 0xac8d, 0x08e0, 0x9786, 0x000a, 0x0938, 0x0820, 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, - 0xbba1, 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, + 0xbbc1, 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, - 0x810f, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xbbdf, + 0x810f, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xbbff, 0x9006, 0x0005, 0x918d, 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, - 0x1a0c, 0x0d7d, 0x080c, 0xca36, 0x0120, 0x080c, 0xca47, 0x0158, - 0x0028, 0x080c, 0x321e, 0x080c, 0xca47, 0x0128, 0x080c, 0x95c6, - 0x080c, 0xabdf, 0x0005, 0x080c, 0xb5a6, 0x0cc0, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbc25, 0xbc25, - 0xbc25, 0xbc25, 0xbc25, 0xbc25, 0xbc25, 0xbc25, 0xbc25, 0xbc25, - 0xbc25, 0xbc27, 0xbc27, 0xbc27, 0xbc27, 0xbc25, 0xbc25, 0xbc25, - 0xbc27, 0xbc25, 0xbc25, 0xbc25, 0xbc25, 0x080c, 0x0d7d, 0x600b, + 0x1a0c, 0x0d7d, 0x080c, 0xca69, 0x0120, 0x080c, 0xca7a, 0x0158, + 0x0028, 0x080c, 0x323e, 0x080c, 0xca7a, 0x0128, 0x080c, 0x95ff, + 0x080c, 0xabf0, 0x0005, 0x080c, 0xb5c6, 0x0cc0, 0x9182, 0x0057, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbc45, 0xbc45, + 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, + 0xbc45, 0xbc47, 0xbc47, 0xbc47, 0xbc47, 0xbc45, 0xbc45, 0xbc45, + 0xbc47, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0x080c, 0x0d7d, 0x600b, 0xffff, 0x6003, 0x000f, 0x6106, 0x0126, 0x2091, 0x8000, 0x080c, - 0xcf69, 0x2009, 0x8000, 0x080c, 0x9200, 0x012e, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xbcac, 0x9186, - 0x0027, 0x1520, 0x080c, 0x95c6, 0x080c, 0x31ef, 0x080c, 0xcf66, - 0x0096, 0x6114, 0x2148, 0x080c, 0xc832, 0x0198, 0x080c, 0xca47, - 0x1118, 0x080c, 0xb5a6, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, - 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6d7b, 0x080c, - 0xca21, 0x009e, 0x080c, 0xabdf, 0x0804, 0x9684, 0x9186, 0x0014, + 0xcf9c, 0x2009, 0x8000, 0x080c, 0x9239, 0x012e, 0x0005, 0x9186, + 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xbccc, 0x9186, + 0x0027, 0x1520, 0x080c, 0x95ff, 0x080c, 0x320f, 0x080c, 0xcf99, + 0x0096, 0x6114, 0x2148, 0x080c, 0xc865, 0x0198, 0x080c, 0xca7a, + 0x1118, 0x080c, 0xb5c6, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, + 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6d9f, 0x080c, + 0xca54, 0x009e, 0x080c, 0xabf0, 0x0804, 0x96bd, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x0018, 0x080c, 0x0d7d, 0x0005, - 0x0002, 0xbc8a, 0xbc88, 0xbc88, 0xbc88, 0xbc88, 0xbc88, 0xbc88, - 0xbc88, 0xbc88, 0xbc88, 0xbc88, 0xbca3, 0xbca3, 0xbca3, 0xbca3, - 0xbc88, 0xbca3, 0xbc88, 0xbca3, 0xbc88, 0xbc88, 0xbc88, 0xbc88, - 0x080c, 0x0d7d, 0x080c, 0x95c6, 0x0096, 0x6114, 0x2148, 0x080c, - 0xc832, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6d7b, 0x080c, 0xca21, 0x009e, - 0x080c, 0xabdf, 0x0005, 0x080c, 0x95c6, 0x080c, 0xca47, 0x090c, - 0xb5a6, 0x080c, 0xabdf, 0x0005, 0x0002, 0xbcc6, 0xbcc4, 0xbcc4, - 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, - 0xbcc8, 0xbcc8, 0xbcc8, 0xbcc8, 0xbcc4, 0xbcca, 0xbcc4, 0xbcc8, - 0xbcc4, 0xbcc4, 0xbcc4, 0xbcc4, 0x080c, 0x0d7d, 0x080c, 0x0d7d, - 0x080c, 0x0d7d, 0x080c, 0xabdf, 0x0804, 0x9684, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbced, 0xbced, - 0xbced, 0xbced, 0xbced, 0xbd26, 0xbe15, 0xbced, 0xbe21, 0xbced, - 0xbced, 0xbced, 0xbced, 0xbced, 0xbced, 0xbced, 0xbced, 0xbced, - 0xbced, 0xbe21, 0xbcef, 0xbced, 0xbe1f, 0x080c, 0x0d7d, 0x00b6, + 0x0002, 0xbcaa, 0xbca8, 0xbca8, 0xbca8, 0xbca8, 0xbca8, 0xbca8, + 0xbca8, 0xbca8, 0xbca8, 0xbca8, 0xbcc3, 0xbcc3, 0xbcc3, 0xbcc3, + 0xbca8, 0xbcc3, 0xbca8, 0xbcc3, 0xbca8, 0xbca8, 0xbca8, 0xbca8, + 0x080c, 0x0d7d, 0x080c, 0x95ff, 0x0096, 0x6114, 0x2148, 0x080c, + 0xc865, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, + 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6d9f, 0x080c, 0xca54, 0x009e, + 0x080c, 0xabf0, 0x0005, 0x080c, 0x95ff, 0x080c, 0xca7a, 0x090c, + 0xb5c6, 0x080c, 0xabf0, 0x0005, 0x0002, 0xbce6, 0xbce4, 0xbce4, + 0xbce4, 0xbce4, 0xbce4, 0xbce4, 0xbce4, 0xbce4, 0xbce4, 0xbce4, + 0xbce8, 0xbce8, 0xbce8, 0xbce8, 0xbce4, 0xbcea, 0xbce4, 0xbce8, + 0xbce4, 0xbce4, 0xbce4, 0xbce4, 0x080c, 0x0d7d, 0x080c, 0x0d7d, + 0x080c, 0x0d7d, 0x080c, 0xabf0, 0x0804, 0x96bd, 0x9182, 0x0057, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbd0d, 0xbd0d, + 0xbd0d, 0xbd0d, 0xbd0d, 0xbd46, 0xbe35, 0xbd0d, 0xbe41, 0xbd0d, + 0xbd0d, 0xbd0d, 0xbd0d, 0xbd0d, 0xbd0d, 0xbd0d, 0xbd0d, 0xbd0d, + 0xbd0d, 0xbe41, 0xbd0f, 0xbd0d, 0xbe3f, 0x080c, 0x0d7d, 0x00b6, 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1508, 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbea6, 0x080c, 0x6b91, + 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbec6, 0x080c, 0x6bb5, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0xb8d0, - 0x9005, 0x0110, 0x080c, 0x674b, 0x080c, 0xabdf, 0x009e, 0x00be, + 0x9005, 0x0110, 0x080c, 0x676f, 0x080c, 0xabf0, 0x009e, 0x00be, 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, 0x9105, 0x09c0, - 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xcb7c, 0x0c80, 0x00b6, 0x0096, + 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xcbaf, 0x0c80, 0x00b6, 0x0096, 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, 0xb800, 0xd0bc, - 0x1904, 0xbe04, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbea6, 0x080c, - 0x6b91, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0xb8d0, 0x9005, 0x0110, 0x080c, 0x674b, 0x601c, 0xd0fc, 0x1148, - 0x7044, 0xd0e4, 0x1904, 0xbde8, 0x080c, 0xabdf, 0x009e, 0x00be, + 0x1904, 0xbe24, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, + 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbec6, 0x080c, + 0x6bb5, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, + 0xb8d0, 0x9005, 0x0110, 0x080c, 0x676f, 0x601c, 0xd0fc, 0x1148, + 0x7044, 0xd0e4, 0x1904, 0xbe08, 0x080c, 0xabf0, 0x009e, 0x00be, 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d7d, 0x968c, 0x0c00, - 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xbdec, 0x7348, + 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xbe0c, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, @@ -5863,54 +5867,54 @@ unsigned short risc_code01[] = { 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, - 0x0804, 0xbd32, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, + 0x0804, 0xbd52, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, - 0x0025, 0x080c, 0xc3f8, 0x003e, 0xd6cc, 0x0904, 0xbd47, 0x7154, - 0xa98a, 0x81ff, 0x0904, 0xbd47, 0x9192, 0x0021, 0x1278, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xc3f8, 0x2011, 0x0205, - 0x2013, 0x0000, 0x080c, 0xcef6, 0x0804, 0xbd47, 0xa868, 0xd0fc, + 0x0025, 0x080c, 0xc41b, 0x003e, 0xd6cc, 0x0904, 0xbd67, 0x7154, + 0xa98a, 0x81ff, 0x0904, 0xbd67, 0x9192, 0x0021, 0x1278, 0x8304, + 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xc41b, 0x2011, 0x0205, + 0x2013, 0x0000, 0x080c, 0xcf29, 0x0804, 0xbd67, 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, - 0xc397, 0x00ae, 0x080c, 0xcef6, 0x080c, 0xc3e8, 0x0804, 0xbd49, - 0x080c, 0xcb3f, 0x0804, 0xbd5e, 0xa87c, 0xd0ac, 0x0904, 0xbd6f, - 0xa880, 0xd0bc, 0x1904, 0xbd6f, 0x7348, 0xa838, 0x9306, 0x11c8, - 0x734c, 0xa834, 0x931e, 0x0904, 0xbd6f, 0xd6d4, 0x0190, 0xab38, - 0x9305, 0x0904, 0xbd6f, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xbd3a, - 0xa838, 0xa934, 0x9105, 0x0904, 0xbd3a, 0xa880, 0xd0bc, 0x1904, - 0xbd3a, 0x080c, 0xcb7c, 0x0804, 0xbd5e, 0x00f6, 0x2079, 0x026c, + 0xc3ba, 0x00ae, 0x080c, 0xcf29, 0x080c, 0xc40b, 0x0804, 0xbd69, + 0x080c, 0xcb72, 0x0804, 0xbd7e, 0xa87c, 0xd0ac, 0x0904, 0xbd8f, + 0xa880, 0xd0bc, 0x1904, 0xbd8f, 0x7348, 0xa838, 0x9306, 0x11c8, + 0x734c, 0xa834, 0x931e, 0x0904, 0xbd8f, 0xd6d4, 0x0190, 0xab38, + 0x9305, 0x0904, 0xbd8f, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xbd5a, + 0xa838, 0xa934, 0x9105, 0x0904, 0xbd5a, 0xa880, 0xd0bc, 0x1904, + 0xbd5a, 0x080c, 0xcbaf, 0x0804, 0xbd7e, 0x00f6, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe, 0x0021, 0x0005, 0x0011, 0x0005, 0x0005, 0x0096, 0x6003, 0x0002, 0x6007, 0x0043, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46, 0xab4a, 0xae36, 0xad3a, - 0x6044, 0xd0fc, 0x190c, 0xa8b1, 0x604b, 0x0000, 0x080c, 0x1c3d, - 0x1118, 0x6144, 0x080c, 0x922c, 0x009e, 0x0005, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbe6d, 0xbe6d, - 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, - 0xbe6f, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe6d, 0xbe80, 0xbe6d, 0xbe6d, - 0xbe6d, 0xbe6d, 0xbea4, 0xbe6d, 0xbe6d, 0x080c, 0x0d7d, 0x6004, - 0x9086, 0x0040, 0x1110, 0x080c, 0x95c6, 0x2019, 0x0001, 0x080c, - 0xa0fa, 0x6003, 0x0002, 0x080c, 0xcf6e, 0x080c, 0x9621, 0x0005, - 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x95c6, 0x2019, 0x0001, - 0x080c, 0xa0fa, 0x080c, 0x9621, 0x080c, 0x31ef, 0x080c, 0xcf66, - 0x0096, 0x6114, 0x2148, 0x080c, 0xc832, 0x0150, 0xa867, 0x0103, - 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, 0x6d7b, 0x080c, 0xca21, - 0x009e, 0x080c, 0xabdf, 0x0005, 0x080c, 0x0d7d, 0xa87b, 0x0015, + 0x6044, 0xd0fc, 0x190c, 0xa8c2, 0x604b, 0x0000, 0x080c, 0x1c55, + 0x1118, 0x6144, 0x080c, 0x9265, 0x009e, 0x0005, 0x9182, 0x0057, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbe8d, 0xbe8d, + 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, + 0xbe8f, 0xbe8d, 0xbe8d, 0xbe8d, 0xbe8d, 0xbea0, 0xbe8d, 0xbe8d, + 0xbe8d, 0xbe8d, 0xbec4, 0xbe8d, 0xbe8d, 0x080c, 0x0d7d, 0x6004, + 0x9086, 0x0040, 0x1110, 0x080c, 0x95ff, 0x2019, 0x0001, 0x080c, + 0xa133, 0x6003, 0x0002, 0x080c, 0xcfa1, 0x080c, 0x965a, 0x0005, + 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x95ff, 0x2019, 0x0001, + 0x080c, 0xa133, 0x080c, 0x965a, 0x080c, 0x320f, 0x080c, 0xcf99, + 0x0096, 0x6114, 0x2148, 0x080c, 0xc865, 0x0150, 0xa867, 0x0103, + 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, 0x6d9f, 0x080c, 0xca54, + 0x009e, 0x080c, 0xabf0, 0x0005, 0x080c, 0x0d7d, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a77, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, 0x9182, 0x0057, 0x1220, - 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbedc, 0xbedc, 0xbedc, - 0xbedc, 0xbedc, 0xbede, 0xbedc, 0xbedc, 0xbf9b, 0xbedc, 0xbedc, - 0xbedc, 0xbedc, 0xbedc, 0xbedc, 0xbedc, 0xbedc, 0xbedc, 0xbedc, - 0xc0d9, 0xbedc, 0xc0e3, 0xbedc, 0x080c, 0x0d7d, 0x601c, 0xd0bc, + 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xbefc, 0xbefc, 0xbefc, + 0xbefc, 0xbefc, 0xbefe, 0xbefc, 0xbefc, 0xbfbb, 0xbefc, 0xbefc, + 0xbefc, 0xbefc, 0xbefc, 0xbefc, 0xbefc, 0xbefc, 0xbefc, 0xbefc, + 0xc0f9, 0xbefc, 0xc103, 0xbefc, 0x080c, 0x0d7d, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120, 0xc084, 0x601e, 0x0804, - 0xbcce, 0x6114, 0x0096, 0x2148, 0xa87c, 0xc0e5, 0xa87e, 0x009e, + 0xbcee, 0x6114, 0x0096, 0x2148, 0xa87c, 0xc0e5, 0xa87e, 0x009e, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, - 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xbf94, + 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xbfb4, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, - 0xb08e, 0x9284, 0x0300, 0x0904, 0xbf94, 0x9686, 0x0100, 0x1130, - 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x103a, + 0xb08e, 0x9284, 0x0300, 0x0904, 0xbfb4, 0x9686, 0x0100, 0x1130, + 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x1047, 0x090c, 0x0d7d, 0x2900, 0xb07a, 0xb77c, 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, 0x968c, 0x0c00, 0x0120, @@ -5920,1288 +5924,1291 @@ unsigned short risc_code01[] = { 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, - 0x2011, 0x0025, 0x080c, 0xc3f8, 0x003e, 0xd6cc, 0x01e8, 0x7154, + 0x2011, 0x0025, 0x080c, 0xc41b, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, - 0x0018, 0x2011, 0x0029, 0x080c, 0xc3f8, 0x2011, 0x0205, 0x2013, + 0x0018, 0x2011, 0x0029, 0x080c, 0xc41b, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, - 0x0c68, 0x2950, 0x080c, 0xc397, 0x080c, 0x1a55, 0x009e, 0x00ee, + 0x0c68, 0x2950, 0x080c, 0xc3ba, 0x080c, 0x1a62, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1987, 0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, - 0xa87e, 0x6003, 0x0002, 0x080c, 0xcf77, 0x0904, 0xc0d4, 0x604b, + 0xa87e, 0x6003, 0x0002, 0x080c, 0xcfaa, 0x0904, 0xc0f4, 0x604b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, - 0xd1cc, 0x0904, 0xc099, 0xa978, 0xa868, 0xd0fc, 0x0904, 0xc05a, + 0xd1cc, 0x0904, 0xc0b9, 0xa978, 0xa868, 0xd0fc, 0x0904, 0xc07a, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, - 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xc028, 0x9086, 0x0028, - 0x1904, 0xc014, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, 0xc030, + 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xc048, 0x9086, 0x0028, + 0x1904, 0xc034, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, 0xc050, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c, 0xc0fc, 0x601e, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, - 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fec, 0x009e, - 0x080c, 0xcb7c, 0x0804, 0xc0d4, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xce19, 0x0118, 0xb174, 0xc1dc, 0xb176, + 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0ff9, 0x009e, + 0x080c, 0xcbaf, 0x0804, 0xc0f4, 0xd1dc, 0x0158, 0xa87b, 0x0015, + 0xb07b, 0x0015, 0x080c, 0xce4c, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbea6, + 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbec6, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xa87e, 0x080c, - 0xcef6, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fec, 0x001e, - 0x0804, 0xc0c6, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, + 0xcf29, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0ff9, 0x001e, + 0x0804, 0xc0e6, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, - 0x0015, 0x080c, 0xce19, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, + 0x0015, 0x080c, 0xce4c, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbea6, 0xa890, - 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0fec, - 0x009e, 0x080c, 0xcef6, 0xa974, 0x0016, 0x080c, 0xc3e8, 0x001e, + 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xbec6, 0xa890, + 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0ff9, + 0x009e, 0x080c, 0xcf29, 0xa974, 0x0016, 0x080c, 0xc40b, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, - 0x0148, 0xa87b, 0x0015, 0x080c, 0xce19, 0x0118, 0xa974, 0xc1dc, + 0x0148, 0xa87b, 0x0015, 0x080c, 0xce4c, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, - 0xbea6, 0xa974, 0x0016, 0x080c, 0x6b91, 0x001e, 0x6010, 0x00b6, - 0x2058, 0xb8d0, 0x0016, 0x9005, 0x190c, 0x674b, 0x001e, 0x00be, - 0xd1e4, 0x1120, 0x080c, 0xabdf, 0x009e, 0x0005, 0x080c, 0xcb3f, - 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, 0x080c, 0xcf77, 0x190c, - 0x1a63, 0x009e, 0x0005, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, + 0xbec6, 0xa974, 0x0016, 0x080c, 0x6bb5, 0x001e, 0x6010, 0x00b6, + 0x2058, 0xb8d0, 0x0016, 0x9005, 0x190c, 0x676f, 0x001e, 0x00be, + 0xd1e4, 0x1120, 0x080c, 0xabf0, 0x009e, 0x0005, 0x080c, 0xcb72, + 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, 0x080c, 0xcfaa, 0x190c, + 0x1a80, 0x009e, 0x0005, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x01e8, 0xa877, 0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, 0x00b6, 0x6010, 0x2058, 0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, - 0x6b91, 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, - 0x080c, 0x674b, 0x080c, 0xabdf, 0x00be, 0x009e, 0x0005, 0xa87c, + 0x6bb5, 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, + 0x080c, 0x676f, 0x080c, 0xabf0, 0x00be, 0x009e, 0x0005, 0xa87c, 0xc0dc, 0xa87e, 0x08f8, 0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, - 0xbea6, 0x0c28, 0xa880, 0xd0bc, 0x1dc8, 0x080c, 0xcb7c, 0x0c60, - 0x080c, 0x95c6, 0x0010, 0x080c, 0x9621, 0x601c, 0xd084, 0x0110, - 0x080c, 0x1a77, 0x080c, 0xc832, 0x01f0, 0x0096, 0x6114, 0x2148, - 0x080c, 0xca47, 0x1118, 0x080c, 0xb5a6, 0x00a0, 0xa867, 0x0103, + 0xbec6, 0x0c28, 0xa880, 0xd0bc, 0x1dc8, 0x080c, 0xcbaf, 0x0c60, + 0x080c, 0x95ff, 0x0010, 0x080c, 0x965a, 0x601c, 0xd084, 0x0110, + 0x080c, 0x1a94, 0x080c, 0xc865, 0x01f0, 0x0096, 0x6114, 0x2148, + 0x080c, 0xca7a, 0x1118, 0x080c, 0xb5c6, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, - 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xe631, 0xa877, 0x0000, - 0x080c, 0x6d7b, 0x009e, 0x0804, 0xac1a, 0xa87b, 0x0004, 0x0cb0, + 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xe66e, 0xa877, 0x0000, + 0x080c, 0x6d9f, 0x009e, 0x0804, 0xac2b, 0xa87b, 0x0004, 0x0cb0, 0xa87b, 0x0004, 0x0c98, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, - 0xc16c, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, - 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc16a, 0xc190, - 0xc16a, 0xc16a, 0x080c, 0x0d7d, 0x080c, 0x56dd, 0x01f8, 0x6014, + 0x0208, 0x000a, 0x0005, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, + 0xc18c, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, + 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc18a, 0xc1b0, + 0xc18a, 0xc18a, 0x080c, 0x0d7d, 0x080c, 0x56fd, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, - 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x6d7b, 0x009e, 0x0804, 0xabdf, - 0x080c, 0x56dd, 0x0dd8, 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, - 0x0085, 0x0002, 0xc1a9, 0xc1a7, 0xc1a7, 0xc1b5, 0xc1a7, 0xc1a7, - 0xc1a7, 0xc1a7, 0xc1a7, 0xc1a7, 0xc1a7, 0xc1a7, 0xc1a7, 0x080c, + 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x6d9f, 0x009e, 0x0804, 0xabf0, + 0x080c, 0x56fd, 0x0dd8, 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, + 0x0085, 0x0002, 0xc1c9, 0xc1c7, 0xc1c7, 0xc1d5, 0xc1c7, 0xc1c7, + 0xc1c7, 0xc1c7, 0xc1c7, 0xc1c7, 0xc1c7, 0xc1c7, 0xc1c7, 0x080c, 0x0d7d, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, - 0x8020, 0x080c, 0x9200, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, - 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xc820, + 0x8020, 0x080c, 0x9239, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, + 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xc853, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, 0x6d10, - 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xc423, 0x00ce, 0x0128, + 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xc446, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x9280, 0x0004, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, - 0x00c6, 0x2260, 0x080c, 0xcb7c, 0x00ce, 0x00ee, 0x00de, 0x005e, - 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, - 0x0a0c, 0x0d7d, 0x908a, 0x0092, 0x1a0c, 0x0d7d, 0x9082, 0x0085, - 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d7d, - 0x080c, 0x95c6, 0x0096, 0x6014, 0x2048, 0x080c, 0xc832, 0x0140, - 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6d7b, - 0x009e, 0x080c, 0xac1a, 0x0804, 0x9684, 0xc22a, 0xc22c, 0xc22c, - 0xc22a, 0xc22a, 0xc22a, 0xc22a, 0xc22a, 0xc22a, 0xc22a, 0xc22a, - 0xc22a, 0xc22a, 0x080c, 0x0d7d, 0x080c, 0xac1a, 0x0005, 0x9186, - 0x0013, 0x1130, 0x6004, 0x9082, 0x0085, 0x2008, 0x0804, 0xc27b, - 0x9186, 0x0027, 0x1558, 0x080c, 0x95c6, 0x080c, 0x31ef, 0x080c, - 0xcf66, 0x0096, 0x6014, 0x2048, 0x080c, 0xc832, 0x0150, 0xa867, - 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6d7b, 0x080c, - 0xca21, 0x009e, 0x080c, 0xabdf, 0x0005, 0x9186, 0x0089, 0x0118, - 0x9186, 0x008a, 0x1140, 0x080c, 0xaa9a, 0x0128, 0x9086, 0x000c, - 0x0904, 0xc2b3, 0x0000, 0x080c, 0xac99, 0x0c70, 0x9186, 0x0014, - 0x1d60, 0x080c, 0x95c6, 0x0096, 0x6014, 0x2048, 0x080c, 0xc832, - 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, 0xa880, - 0xc0ec, 0xa882, 0x0890, 0x0002, 0xc28b, 0xc289, 0xc289, 0xc289, - 0xc289, 0xc289, 0xc29f, 0xc289, 0xc289, 0xc289, 0xc289, 0xc289, - 0xc289, 0x080c, 0x0d7d, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1985, 0x0010, - 0x2001, 0x1986, 0x2004, 0x601a, 0x6003, 0x000c, 0x0005, 0x6034, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, - 0x1118, 0x2001, 0x1985, 0x0010, 0x2001, 0x1986, 0x2004, 0x601a, - 0x6003, 0x000e, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, - 0x0208, 0x0012, 0x0804, 0xac99, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, - 0xc2cb, 0xc318, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, 0xc2c9, - 0xc2c9, 0x080c, 0x0d7d, 0x0096, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x009e, 0x0804, 0xc32c, - 0x080c, 0xc832, 0x1118, 0x080c, 0xca21, 0x0068, 0x6014, 0x2048, - 0x080c, 0xcf7d, 0x1110, 0x080c, 0xca21, 0xa867, 0x0103, 0x080c, - 0xcf31, 0x080c, 0x6d7b, 0x00d6, 0x2c68, 0x080c, 0xab89, 0x01d0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, - 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, - 0x080c, 0xcccb, 0x695c, 0x615e, 0x6023, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9200, 0x2d60, 0x00de, 0x080c, 0xabdf, 0x009e, 0x0005, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x05a0, 0x6034, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, - 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, 0x2c68, 0x080c, 0xcec9, - 0x11f0, 0x080c, 0xab89, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, - 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, - 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x695c, - 0x615e, 0x080c, 0xcccb, 0x2009, 0x8020, 0x080c, 0x9200, 0x2d60, - 0x00de, 0x0804, 0xabdf, 0x0096, 0x6014, 0x2048, 0x080c, 0xc832, - 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, 0xa882, - 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, - 0xa87b, 0x0005, 0x080c, 0xcb3b, 0xa877, 0x0000, 0x080c, 0x6d7b, - 0x080c, 0xca21, 0x009e, 0x0804, 0xabdf, 0x0016, 0x0096, 0x6014, - 0x2048, 0x080c, 0xc832, 0x0140, 0xa867, 0x0103, 0xa87b, 0x0028, - 0xa877, 0x0000, 0x080c, 0x6d7b, 0x009e, 0x001e, 0x9186, 0x0013, - 0x0158, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, - 0xac99, 0x0020, 0x080c, 0x95c6, 0x080c, 0xac1a, 0x0005, 0x0056, - 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, - 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, - 0x0020, 0x2011, 0x0029, 0x080c, 0xc3f8, 0x96b2, 0x0020, 0xb004, - 0x904d, 0x0110, 0x080c, 0x0fec, 0x080c, 0x103a, 0x0520, 0x8528, - 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, - 0x1228, 0x2608, 0x2011, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, - 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, - 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, - 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, - 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, - 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, - 0x080c, 0x6d7b, 0x2a48, 0x0cb8, 0x080c, 0x6d7b, 0x00ae, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, - 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, - 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, - 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, - 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, - 0x0000, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, - 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, - 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xc475, 0xc475, 0xc470, - 0xc499, 0xc44d, 0xc470, 0xc44f, 0xc470, 0xc44d, 0x90c6, 0xc470, - 0xc470, 0xc470, 0xc44d, 0xc44d, 0xc44d, 0x080c, 0x0d7d, 0x6010, - 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, 0xc499, 0x0036, 0x6014, - 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019, 0x000c, - 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, 0x0010, 0x2019, 0x0010, - 0x080c, 0xde2a, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, - 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, - 0x6014, 0x2048, 0x080c, 0xc832, 0x01d0, 0x6043, 0xffff, 0xa864, - 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, - 0x900e, 0x2001, 0x0005, 0x080c, 0x6faf, 0x080c, 0xcb3b, 0x080c, - 0x6d6f, 0x080c, 0xac1a, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, - 0x0ce0, 0x080c, 0xa888, 0x080c, 0xcf8b, 0x6000, 0x908a, 0x0016, - 0x1a0c, 0x0d7d, 0x002b, 0x0106, 0x080c, 0xa8a4, 0x010e, 0x0005, - 0xc4b8, 0xc4e6, 0xc4ba, 0xc50d, 0xc4e1, 0xc4b8, 0xc470, 0xc475, - 0xc475, 0xc470, 0xc470, 0xc470, 0xc470, 0xc470, 0xc470, 0xc470, - 0x080c, 0x0d7d, 0x86ff, 0x1510, 0x6020, 0x9086, 0x0006, 0x01f0, - 0x0096, 0x6014, 0x2048, 0x080c, 0xc832, 0x0158, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fec, 0x009e, 0x080c, - 0xcb3b, 0x009e, 0x080c, 0xcf0b, 0x6007, 0x0085, 0x6003, 0x000b, - 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x91e2, 0x9085, 0x0001, - 0x0005, 0x0066, 0x080c, 0x1a77, 0x006e, 0x08a0, 0x00e6, 0x2071, - 0x19e6, 0x7030, 0x9c06, 0x1120, 0x080c, 0xa07a, 0x00ee, 0x0850, - 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, - 0x2049, 0x0001, 0x2c40, 0x080c, 0xa1fa, 0x009e, 0x008e, 0x0040, - 0x0066, 0x080c, 0x9f76, 0x190c, 0x0d7d, 0x080c, 0x9f84, 0x006e, - 0x00ee, 0x1904, 0xc4ba, 0x0804, 0xc470, 0x0036, 0x00e6, 0x2071, - 0x19e6, 0x704c, 0x9c06, 0x1138, 0x901e, 0x080c, 0xa0fa, 0x00ee, - 0x003e, 0x0804, 0xc4ba, 0x080c, 0xa331, 0x00ee, 0x003e, 0x1904, - 0xc4ba, 0x0804, 0xc470, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, - 0x001b, 0x006e, 0x00ce, 0x0005, 0xc543, 0xc612, 0xc779, 0xc54b, - 0xac1a, 0xc543, 0xde1c, 0xcf73, 0xc612, 0x908d, 0xc7f8, 0xc53c, - 0xc53c, 0xc53c, 0xc53c, 0xc53c, 0x080c, 0x0d7d, 0x080c, 0xca47, - 0x1110, 0x080c, 0xb5a6, 0x0005, 0x080c, 0x95c6, 0x0804, 0xabdf, - 0x601b, 0x0001, 0x0005, 0x080c, 0xc832, 0x0130, 0x6014, 0x0096, - 0x2048, 0x2c00, 0xa896, 0x009e, 0x080c, 0xa888, 0x080c, 0xcf8b, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0013, 0x0804, 0xa8a4, - 0xc570, 0xc572, 0xc59c, 0xc5b0, 0xc5dd, 0xc570, 0xc543, 0xc543, - 0xc543, 0xc5b7, 0xc5b7, 0xc570, 0xc570, 0xc570, 0xc570, 0xc5c1, - 0x080c, 0x0d7d, 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, - 0xa882, 0x009e, 0x2071, 0x19e6, 0x7030, 0x9c06, 0x01d0, 0x0066, - 0x080c, 0x9f76, 0x190c, 0x0d7d, 0x080c, 0x9f84, 0x006e, 0x080c, - 0xcf0b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, - 0x1986, 0x2004, 0x601a, 0x2009, 0x8020, 0x080c, 0x91e2, 0x00ee, - 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, - 0xc0b5, 0xa882, 0x009e, 0x080c, 0xcf0b, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x91e2, 0x0005, - 0x080c, 0xa888, 0x080c, 0xaa1c, 0x080c, 0xa8a4, 0x0c28, 0x0096, - 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x0005, 0x080c, 0x56dd, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, - 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, - 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, - 0x080c, 0x6d7b, 0x009e, 0x0804, 0xabdf, 0x6014, 0x0096, 0x904d, - 0x0560, 0xa97c, 0xd1e4, 0x1158, 0x611c, 0xd1fc, 0x0530, 0x6110, - 0x00b6, 0x2158, 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, - 0xa8a4, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, - 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, - 0x0037, 0x2c08, 0x080c, 0x1686, 0x6000, 0x9086, 0x0004, 0x1120, - 0x2009, 0x0048, 0x080c, 0xac7c, 0x0005, 0x009e, 0x080c, 0x1a77, - 0x0804, 0xc59c, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x000b, - 0x0005, 0xc629, 0xc548, 0xc62b, 0xc629, 0xc62b, 0xc62b, 0xc544, - 0xc629, 0xc53e, 0xc53e, 0xc629, 0xc629, 0xc629, 0xc629, 0xc629, - 0xc629, 0x080c, 0x0d7d, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, - 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0d7d, 0x00b6, 0x0013, - 0x00be, 0x0005, 0xc646, 0xc713, 0xc648, 0xc688, 0xc648, 0xc688, - 0xc648, 0xc656, 0xc646, 0xc688, 0xc646, 0xc677, 0x080c, 0x0d7d, - 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, - 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xc70f, 0x6004, 0x080c, - 0xca47, 0x0904, 0xc72c, 0x908e, 0x0004, 0x1110, 0x080c, 0x321e, - 0x908e, 0x0021, 0x0904, 0xc730, 0x908e, 0x0022, 0x0904, 0xc774, - 0x908e, 0x003d, 0x0904, 0xc730, 0x908e, 0x0039, 0x0904, 0xc734, - 0x908e, 0x0035, 0x0904, 0xc734, 0x908e, 0x001e, 0x0178, 0x908e, - 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x0110, 0x080c, 0x31ef, 0x080c, 0xb5a6, 0x0804, 0xac1a, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xc700, 0x9186, - 0x0002, 0x1904, 0xc6d5, 0x2001, 0x1837, 0x2004, 0xd08c, 0x11c8, - 0x080c, 0x74c8, 0x11b0, 0x080c, 0xcf51, 0x0138, 0x080c, 0x74eb, - 0x1120, 0x080c, 0x73d3, 0x0804, 0xc75d, 0x2001, 0x197c, 0x2003, - 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x73f9, 0x0804, - 0xc75d, 0x6010, 0x2058, 0x2001, 0x1837, 0x2004, 0xd0ac, 0x1904, - 0xc75d, 0xb8a0, 0x9084, 0xff80, 0x1904, 0xc75d, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, - 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, 0x080c, 0xab89, 0x0128, - 0x2b00, 0x6012, 0x6023, 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, - 0x908e, 0x0002, 0x11a0, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1170, 0x2009, 0x1837, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, - 0x1800, 0x080c, 0x5fb7, 0x00ee, 0x080c, 0xb5a6, 0x0030, 0x080c, - 0xb5a6, 0x080c, 0x31ef, 0x080c, 0xcf66, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x321e, 0x012e, 0x00ee, 0x080c, 0xac1a, 0x0005, - 0x2001, 0x0002, 0x080c, 0x6570, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x9207, 0x080c, 0x9684, 0x00de, 0x00ce, 0x0c80, 0x080c, - 0x321e, 0x0804, 0xc684, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, - 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, - 0xc6d5, 0x8001, 0xb842, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, - 0x9684, 0x00de, 0x00ce, 0x0898, 0x080c, 0xb5a6, 0x0804, 0xc686, - 0x080c, 0xb5e2, 0x0804, 0xc686, 0x00d6, 0x2c68, 0x6104, 0x080c, - 0xcec9, 0x00de, 0x0118, 0x080c, 0xabdf, 0x00f0, 0x6004, 0x8007, - 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, 0x2001, 0x1986, 0x2004, - 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, 0xc0b5, 0x6026, 0x2160, - 0x2009, 0x8020, 0x080c, 0x9200, 0x0005, 0x00de, 0x00ce, 0x080c, - 0xb5a6, 0x080c, 0x31ef, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x321e, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, - 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xb01a, 0x1904, 0xc72c, - 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0096, 0x00d6, - 0x001b, 0x00de, 0x009e, 0x0005, 0xc794, 0xc794, 0xc794, 0xc794, - 0xc794, 0xc794, 0xc794, 0xc794, 0xc794, 0xc543, 0xc794, 0xc548, - 0xc796, 0xc548, 0xc7a3, 0xc794, 0x080c, 0x0d7d, 0x6004, 0x9086, - 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, 0x2009, 0x8020, - 0x080c, 0x9200, 0x0005, 0x080c, 0xcf45, 0x0118, 0x080c, 0xcf58, - 0x0010, 0x080c, 0xcf66, 0x080c, 0xca21, 0x080c, 0xc832, 0x0570, - 0x080c, 0x31ef, 0x080c, 0xc832, 0x0168, 0x6014, 0x2048, 0xa867, - 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, - 0x080c, 0x6d7b, 0x2c68, 0x080c, 0xab89, 0x0150, 0x6810, 0x6012, - 0x080c, 0xcccb, 0x00c6, 0x2d60, 0x080c, 0xac1a, 0x00ce, 0x0008, - 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x080c, 0x9207, 0x080c, 0x9684, 0x00c8, 0x080c, 0xcf45, - 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, 0x080c, 0x31ef, 0x08d0, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x080c, 0x31ef, 0x0868, 0x080c, 0xac1a, 0x0005, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0002, 0xc80e, 0xc80e, - 0xc810, 0xc810, 0xc810, 0xc80e, 0xc80e, 0xac1a, 0xc80e, 0xc80e, - 0xc80e, 0xc80e, 0xc80e, 0xc80e, 0xc80e, 0xc80e, 0x080c, 0x0d7d, - 0x080c, 0xa888, 0x080c, 0xaa1c, 0x080c, 0xa8a4, 0x6114, 0x0096, - 0x2148, 0xa87b, 0x0006, 0x080c, 0x6d7b, 0x009e, 0x0804, 0xabdf, - 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001, 0x181a, - 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, - 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, - 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x10e5, 0x000e, - 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7354, 0x7074, 0x9302, - 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xcf51, 0x0180, 0x9286, - 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x31ef, - 0x080c, 0xcf66, 0x00c6, 0x080c, 0xac1a, 0x00ce, 0x0060, 0x080c, - 0xcc3d, 0x0148, 0x080c, 0xca47, 0x1110, 0x080c, 0xb5a6, 0x00c6, - 0x080c, 0xabdf, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, - 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, - 0x1b31, 0x6112, 0x080c, 0x31ef, 0x9006, 0x0010, 0x9085, 0x0001, - 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xab89, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, 0x56dd, - 0x0118, 0x080c, 0xc963, 0x0168, 0x080c, 0xcccb, 0x6023, 0x0003, - 0x2009, 0x004b, 0x080c, 0xac7c, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, - 0x080c, 0xac4f, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, 0x080c, - 0xcccb, 0x6023, 0x0003, 0x0016, 0x080c, 0xa888, 0x080c, 0x938d, - 0x0076, 0x903e, 0x080c, 0x9256, 0x2c08, 0x080c, 0xdffb, 0x007e, - 0x080c, 0xa8a4, 0x001e, 0xd184, 0x0128, 0x080c, 0xabdf, 0x9085, - 0x0001, 0x0070, 0x080c, 0x56dd, 0x0128, 0xd18c, 0x1170, 0x080c, - 0xc963, 0x0148, 0x2009, 0x004c, 0x080c, 0xac7c, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, - 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, - 0x0016, 0x080c, 0xab89, 0x2c78, 0x0590, 0x7e5e, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xc975, 0x9186, 0x004d, - 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, 0x197f, 0x200c, 0xd1fc, - 0x0168, 0x2f60, 0x080c, 0xabdf, 0x00d0, 0x2001, 0x197e, 0x200c, - 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xabdf, 0x0088, 0x2f60, 0x080c, - 0x56dd, 0x0138, 0xd18c, 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, - 0x7816, 0x001e, 0x0016, 0x080c, 0xac7c, 0x9085, 0x0001, 0x001e, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x080c, - 0xab89, 0x2c78, 0x0508, 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, - 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, 0x2001, 0x197d, 0x200c, - 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xabdf, 0x0060, 0x2f60, 0x080c, - 0x56dd, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, 0x2009, 0x0052, - 0x080c, 0xac7c, 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x4aa9, 0x00ce, 0x1120, - 0x080c, 0xabdf, 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, - 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, 0x0076, 0x0126, - 0x2091, 0x8000, 0x080c, 0xa888, 0x080c, 0x6802, 0x0158, 0x2001, - 0xc97c, 0x0006, 0x900e, 0x2400, 0x080c, 0x6faf, 0x080c, 0x6d7b, - 0x000e, 0x0807, 0x2418, 0x080c, 0x958c, 0xbaa0, 0x0086, 0x2041, - 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x93a7, 0x008e, 0x080c, - 0x9256, 0x2f08, 0x2648, 0x080c, 0xdffb, 0xb93c, 0x81ff, 0x090c, - 0x947e, 0x080c, 0xa8a4, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xab89, 0x0190, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xcccb, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, - 0x001f, 0x080c, 0xac7c, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xac4f, - 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xcccb, 0x6023, 0x0008, - 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x173e, 0x00fe, 0x2009, - 0x0021, 0x080c, 0xac7c, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, 0x0016, 0x2091, - 0x8000, 0x080c, 0xab89, 0x0198, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xcccb, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x0016, 0x080c, - 0xac7c, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xac4f, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xcccb, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x0000, 0x080c, 0xac7c, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830, 0x2009, 0x0049, - 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0118, - 0x8211, 0xba3e, 0x1140, 0xb8d0, 0x9005, 0x0128, 0xb888, 0x9005, - 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e, 0x0005, 0x0006, 0x0016, - 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, - 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, 0x904d, - 0x080c, 0xc832, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, 0x6020, - 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, 0xd0fc, - 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, 0x000e, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xac4f, 0x0198, - 0x2b08, 0x6112, 0x080c, 0xcccb, 0x6023, 0x0001, 0x2900, 0x6016, - 0x080c, 0x31ef, 0x2009, 0x0028, 0x080c, 0xac7c, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, - 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, - 0xb7fa, 0x00be, 0x080c, 0xba1d, 0x6003, 0x0001, 0x6007, 0x0029, - 0x080c, 0x9207, 0x080c, 0x9684, 0x0078, 0x6014, 0x0096, 0x2048, - 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xce8a, - 0x080c, 0xb5a6, 0x080c, 0xabdf, 0x0005, 0x0096, 0x6014, 0x904d, - 0x090c, 0x0d7d, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, - 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6d7b, 0x012e, 0x009e, 0x080c, 0xabdf, 0x0c30, 0x0096, 0x9186, - 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x6570, 0x00e8, 0x9186, - 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x11e0, - 0x6010, 0x00b6, 0x2058, 0x080c, 0x66bb, 0x00be, 0x080c, 0xbaee, - 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, 0x0160, - 0x2001, 0x0006, 0x080c, 0x6570, 0x6014, 0x2048, 0xa868, 0xd0fc, - 0x0170, 0x080c, 0xafee, 0x0048, 0x6014, 0x2048, 0xa868, 0xd0fc, - 0x0528, 0x080c, 0xb5a6, 0x080c, 0xabdf, 0x009e, 0x0005, 0x6014, - 0x6310, 0x2358, 0x904d, 0x090c, 0x0d7d, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6913, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6d7b, 0x012e, 0x080c, 0xabdf, 0x08f8, 0x6014, 0x904d, - 0x090c, 0x0d7d, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, - 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6d7b, 0x012e, 0x080c, 0xabdf, 0x0840, 0xa878, 0x9086, 0x0005, - 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x604b, - 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, - 0x8023, 0x080c, 0x9200, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, 0x6020, 0x9084, 0x000f, - 0x001b, 0x006e, 0x00ce, 0x0005, 0xc543, 0xcb6e, 0xcb6e, 0xcb71, - 0xe328, 0xe343, 0xe346, 0xc543, 0xc543, 0xc543, 0xc543, 0xc543, - 0xc543, 0xc543, 0xc543, 0xc543, 0x080c, 0x0d7d, 0xa001, 0xa001, - 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, - 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834, 0x2004, 0x9005, 0x1540, - 0x00f6, 0x2c78, 0x080c, 0xab89, 0x0508, 0x7810, 0x6012, 0x080c, - 0xcccb, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, - 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, - 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x795c, 0x615e, 0x2009, - 0x8020, 0x080c, 0x9200, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, - 0x2001, 0x1987, 0x2004, 0x604a, 0x0005, 0x0016, 0x0096, 0x6814, - 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e, 0xa87c, 0x1108, 0xd0e4, - 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, 0xa88f, - 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, 0x080c, - 0x0fec, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, 0x6803, 0x0002, - 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0, 0x681c, - 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085, 0x0c00, - 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0, 0x693c, - 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, 0x683a, - 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, 0x695c, - 0x615e, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x2009, - 0x8020, 0x080c, 0x9200, 0x009e, 0x001e, 0x0005, 0x6024, 0xd0d4, - 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, 0x0230, - 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, 0x633e, - 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, 0xa836, - 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024, 0xc0d4, - 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a, 0xa840, - 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016, 0x6004, - 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e, 0x0036, - 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, 0x0158, 0x908e, - 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, 0x0110, - 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x0036, 0x00e6, 0x2001, 0x1981, 0x200c, 0x8000, 0x2014, 0x2001, - 0x0032, 0x080c, 0x9148, 0x2001, 0x1985, 0x82ff, 0x1110, 0x2011, - 0x0014, 0x2202, 0x2001, 0x1983, 0x200c, 0x8000, 0x2014, 0x2071, - 0x196b, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x9148, 0x2001, - 0x1986, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1987, - 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, 0x080c, 0xa879, 0x2001, - 0x1a88, 0x2102, 0x2001, 0x0032, 0x080c, 0x1686, 0x080c, 0x6a4b, - 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x00e6, 0x2001, 0x1985, 0x2003, 0x0028, 0x2001, 0x1986, 0x2003, - 0x0014, 0x2071, 0x196b, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, - 0x1987, 0x2009, 0x001e, 0x2102, 0x2001, 0x0017, 0x080c, 0xa879, - 0x2001, 0x1a88, 0x2102, 0x2001, 0x0032, 0x080c, 0x1686, 0x00ee, - 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, 0x904d, 0x0110, 0x080c, - 0x106c, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xab89, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xac7c, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, 0x7090, 0x9086, 0x0018, - 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, - 0x9743, 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, - 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, - 0x080c, 0x323e, 0x080c, 0xafee, 0x0020, 0x080c, 0xb5a6, 0x080c, - 0xabdf, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, - 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xab89, - 0x0188, 0x2b08, 0x6112, 0x080c, 0xcccb, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x004d, 0x080c, 0xac7c, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x0016, 0x080c, 0xab89, 0x0180, 0x2b08, 0x6112, 0x080c, 0xcccb, - 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xac7c, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, - 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x199f, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, - 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, 0x080c, 0xd572, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, - 0x0103, 0x0010, 0x080c, 0xb5a6, 0x080c, 0xabdf, 0x00fe, 0x00ee, - 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, - 0x7090, 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, - 0x9743, 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, - 0x9206, 0x1110, 0x080c, 0x31ef, 0x080c, 0xafee, 0x0020, 0x080c, - 0xb5a6, 0x080c, 0xabdf, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, - 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, - 0x1800, 0x9186, 0x0015, 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, - 0x6014, 0x2048, 0x2c78, 0x080c, 0x9743, 0x05f0, 0x707c, 0xaacc, - 0x9206, 0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, 0x31ef, - 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x568d, - 0x001e, 0x0010, 0x080c, 0x5476, 0x080c, 0xc832, 0x0508, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xc832, - 0x01b8, 0x6014, 0x2048, 0x080c, 0x5476, 0x1d70, 0xa87b, 0x0030, - 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, - 0x8000, 0xa867, 0x0139, 0x080c, 0x6d7b, 0x012e, 0x080c, 0xabdf, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, - 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, - 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, - 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, - 0x00b6, 0x00d6, 0x0036, 0x080c, 0xc832, 0x0904, 0xce86, 0x0096, - 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, - 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, - 0x6913, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, - 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, - 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, - 0x0fb7, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, - 0x9080, 0x000a, 0x2098, 0x080c, 0x0fb7, 0x00ce, 0x0090, 0xaa96, - 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, - 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, - 0xa89e, 0x080c, 0x6d6f, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, - 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, - 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000, - 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x2614, 0x2118, - 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, - 0x2011, 0x8018, 0x080c, 0x4b09, 0x00a8, 0x9096, 0x0001, 0x1148, - 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, - 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, - 0x0008, 0x6a2c, 0x080c, 0xc820, 0x01f0, 0x2260, 0x6120, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, - 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, - 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, - 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, - 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, 0xa9a8, 0x918c, - 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xbea6, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, - 0x901e, 0x0499, 0x01e0, 0x080c, 0xc832, 0x01c8, 0x080c, 0xca21, - 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, 0xa87c, - 0x080c, 0xca47, 0x1118, 0x080c, 0xb5a6, 0x0040, 0xa867, 0x0103, - 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6d7b, 0x009e, 0x003e, - 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, - 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, - 0x080c, 0xcb3b, 0xa877, 0x0000, 0x0005, 0x2001, 0x1810, 0x2004, - 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0f4, 0x000e, - 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, 0x000e, 0x0005, - 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0007, 0x080c, 0x4cc0, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, - 0x0005, 0x2001, 0x1985, 0x2004, 0x601a, 0x0005, 0x2001, 0x1987, - 0x2004, 0x604a, 0x0005, 0x080c, 0xabdf, 0x0804, 0x9684, 0x611c, - 0xd1fc, 0xa97c, 0x1108, 0xd1e4, 0x0005, 0x601c, 0xd0fc, 0xa87c, - 0x1108, 0xd0e4, 0x0005, 0x601c, 0xd0fc, 0xc0fc, 0x601e, 0xa87c, - 0x1108, 0xd0e4, 0x0005, 0x6044, 0xd0fc, 0x1138, 0xd0bc, 0x0198, - 0xc0bc, 0x6046, 0x6003, 0x0002, 0x0070, 0xd0ac, 0x1160, 0xd0dc, - 0x1128, 0x908c, 0x000f, 0x9186, 0x0005, 0x1118, 0x6003, 0x0003, - 0x0010, 0x6003, 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0d7d, 0x001b, 0x006e, 0x00be, 0x0005, 0xcfbf, - 0xd6cd, 0xd81e, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbf, 0xcff6, - 0xd8a2, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbf, 0x080c, - 0x0d7d, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7d, 0x0013, - 0x006e, 0x0005, 0xcfda, 0xddb9, 0xcfda, 0xcfda, 0xcfda, 0xcfda, - 0xcfda, 0xcfda, 0xdd68, 0xde0b, 0xcfda, 0xe463, 0xe497, 0xe463, - 0xe497, 0xcfda, 0x080c, 0x0d7d, 0x6000, 0x9082, 0x0016, 0x1a0c, - 0x0d7d, 0x6000, 0x000a, 0x0005, 0xcff4, 0xda7e, 0xdb47, 0xdb69, - 0xdbe4, 0xcff4, 0xdcde, 0xdc6c, 0xd8ac, 0xdd40, 0xdd55, 0xcff4, - 0xcff4, 0xcff4, 0xcff4, 0xcff4, 0x080c, 0x0d7d, 0x91b2, 0x0053, - 0x1a0c, 0x0d7d, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xd443, 0x0002, - 0xd040, 0xd234, 0xd040, 0xd040, 0xd040, 0xd23d, 0xd040, 0xd040, - 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, - 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd042, - 0xd0a9, 0xd0b8, 0xd11c, 0xd147, 0xd1c0, 0xd21f, 0xd040, 0xd040, - 0xd240, 0xd040, 0xd040, 0xd255, 0xd262, 0xd040, 0xd040, 0xd040, - 0xd040, 0xd040, 0xd2e5, 0xd040, 0xd040, 0xd2f9, 0xd040, 0xd040, - 0xd2b4, 0xd040, 0xd040, 0xd040, 0xd311, 0xd040, 0xd040, 0xd040, - 0xd38e, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd40b, - 0x080c, 0x0d7d, 0x080c, 0x6a28, 0x1150, 0x2001, 0x1837, 0x2004, - 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, - 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xd22d, 0x080c, - 0x69c4, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, - 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0xa888, 0x080c, 0x938d, - 0x0076, 0x903e, 0x080c, 0x9256, 0x2c08, 0x080c, 0xdffb, 0x007e, - 0x001e, 0x080c, 0xa8a4, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x6610, 0x2658, 0x080c, 0x662f, 0xbe04, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, - 0x00be, 0x2c08, 0x080c, 0xe6c0, 0x002e, 0x001e, 0x1178, 0x080c, - 0xdf29, 0x1904, 0xd114, 0x080c, 0xdec5, 0x1120, 0x6007, 0x0008, - 0x0804, 0xd22d, 0x6007, 0x0009, 0x0804, 0xd22d, 0x080c, 0xe15c, - 0x0128, 0x080c, 0xdf29, 0x0d78, 0x0804, 0xd114, 0x6017, 0x1900, - 0x0c88, 0x080c, 0x3326, 0x1904, 0xd440, 0x6106, 0x080c, 0xde76, - 0x6007, 0x0006, 0x0804, 0xd22d, 0x6007, 0x0007, 0x0804, 0xd22d, - 0x080c, 0xe4d3, 0x1904, 0xd440, 0x080c, 0x3326, 0x1904, 0xd440, - 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, - 0x1220, 0x2001, 0x0001, 0x080c, 0x655c, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, - 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, - 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, - 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, - 0x00b0, 0x00ee, 0x080c, 0xdf91, 0x1190, 0x9686, 0x0006, 0x1140, - 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x323e, 0x002e, - 0x080c, 0x66bb, 0x6007, 0x000a, 0x00de, 0x0804, 0xd22d, 0x6007, - 0x000b, 0x00de, 0x0804, 0xd22d, 0x080c, 0x31ef, 0x080c, 0xcf66, - 0x6007, 0x0001, 0x0804, 0xd22d, 0x080c, 0xe4d3, 0x1904, 0xd440, - 0x080c, 0x3326, 0x1904, 0xd440, 0x2071, 0x0260, 0x7034, 0x90b4, - 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, - 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, - 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x323e, 0x002e, 0x6007, - 0x000c, 0x2001, 0x0001, 0x080c, 0xe6a0, 0x0804, 0xd22d, 0x080c, - 0x6a28, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, - 0x0008, 0x1110, 0x0804, 0xd04f, 0x080c, 0x69c4, 0x6610, 0x2658, - 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, 0x0026, - 0x2001, 0x0006, 0x080c, 0x659c, 0x002e, 0x0050, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd114, - 0x080c, 0xdf9e, 0x1120, 0x6007, 0x000e, 0x0804, 0xd22d, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31ef, 0x080c, 0xcf66, - 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, - 0x2009, 0x0029, 0x080c, 0xe2d9, 0x6010, 0x2058, 0xb800, 0xc0e5, - 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xd22d, 0x2001, - 0x0001, 0x080c, 0x655c, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xbba1, 0x003e, - 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, - 0x9682, 0x0004, 0x0a04, 0xd114, 0x9682, 0x0007, 0x0a04, 0xd170, - 0x0804, 0xd114, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd22d, - 0x080c, 0x6a28, 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x1110, 0x0804, 0xd04f, 0x080c, 0x69c4, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, 0x9086, 0x0001, 0x000e, - 0x0170, 0x9082, 0x0006, 0x0698, 0x0150, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd114, 0x080c, - 0xdfcc, 0x1130, 0x080c, 0xdec5, 0x1118, 0x6007, 0x0010, 0x04e8, - 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x31ef, 0x080c, - 0xcf66, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, - 0x0148, 0x2009, 0x0029, 0x080c, 0xe2d9, 0x6010, 0x2058, 0xb800, - 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, - 0xe15c, 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0978, - 0x0804, 0xd114, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, - 0x3326, 0x1904, 0xd440, 0x080c, 0xe4d3, 0x1904, 0xd440, 0x080c, - 0xd60d, 0x1904, 0xd114, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, - 0x9207, 0x080c, 0x9684, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9207, 0x080c, 0x9684, 0x0cb0, 0x6007, 0x0005, 0x0c68, - 0x080c, 0xe4d3, 0x1904, 0xd440, 0x080c, 0x3326, 0x1904, 0xd440, - 0x080c, 0xd60d, 0x1904, 0xd114, 0x6007, 0x0020, 0x6003, 0x0001, - 0x080c, 0x9207, 0x080c, 0x9684, 0x0005, 0x080c, 0x3326, 0x1904, - 0xd440, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, - 0x9684, 0x0005, 0x080c, 0xe4d3, 0x1904, 0xd440, 0x080c, 0x3326, - 0x1904, 0xd440, 0x080c, 0xd60d, 0x1904, 0xd114, 0x0016, 0x0026, - 0x00e6, 0x2071, 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, - 0x080c, 0xc820, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, - 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, - 0x2c08, 0x9006, 0x080c, 0xe2a3, 0x1180, 0x7244, 0x9286, 0xffff, - 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, - 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, - 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, 0xabdf, 0x2160, - 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, 0x9684, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x655c, - 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0276, 0x080c, 0xbba1, 0x003e, 0x002e, 0x001e, 0x015e, - 0x0120, 0x6007, 0x0031, 0x0804, 0xd22d, 0x080c, 0xb812, 0x080c, - 0x74c8, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x74e2, 0x1138, - 0x080c, 0x77cc, 0x080c, 0x6024, 0x080c, 0x73f9, 0x0010, 0x080c, - 0x749c, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x3326, 0x1904, - 0xd440, 0x080c, 0xd60d, 0x1904, 0xd114, 0x6106, 0x080c, 0xd629, - 0x1120, 0x6007, 0x002b, 0x0804, 0xd22d, 0x6007, 0x002c, 0x0804, - 0xd22d, 0x080c, 0xe4d3, 0x1904, 0xd440, 0x080c, 0x3326, 0x1904, - 0xd440, 0x080c, 0xd60d, 0x1904, 0xd114, 0x6106, 0x080c, 0xd62e, - 0x1120, 0x6007, 0x002e, 0x0804, 0xd22d, 0x6007, 0x002f, 0x0804, - 0xd22d, 0x080c, 0x3326, 0x1904, 0xd440, 0x00e6, 0x00d6, 0x00c6, - 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, - 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, - 0x00ee, 0x0804, 0xd234, 0x080c, 0x56d9, 0xd0e4, 0x0904, 0xd38b, - 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, - 0x080c, 0x6a66, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, - 0xb814, 0x9206, 0x0510, 0x080c, 0x6a62, 0x15b8, 0x2069, 0x1800, - 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578, 0x7210, 0x080c, - 0xc820, 0x0590, 0x080c, 0xd4f8, 0x0578, 0x080c, 0xe355, 0x0560, - 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, - 0x9200, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, - 0x0150, 0x080c, 0xc820, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, - 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, - 0xe2a3, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, - 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, - 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x3326, - 0x1904, 0xd440, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0006, 0x1904, 0xd234, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0x56d9, 0xd0e4, 0x0904, 0xd403, 0x2069, 0x1800, 0x2071, 0x026c, - 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xe2a3, 0x2c10, 0x00ce, - 0x05e8, 0x080c, 0xc820, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, - 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, 0xc423, 0x002e, - 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, - 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, - 0x2004, 0x9005, 0x0170, 0x080c, 0xd4f8, 0x0904, 0xd384, 0x0056, - 0x7510, 0x7614, 0x080c, 0xe36e, 0x005e, 0x00ce, 0x00de, 0x00ee, - 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x0c78, 0x6007, 0x003b, - 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9200, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, - 0x0000, 0x0804, 0xd35b, 0x00e6, 0x0026, 0x080c, 0x6a28, 0x0550, - 0x080c, 0x69c4, 0x080c, 0xe545, 0x1518, 0x2071, 0x1800, 0x70dc, - 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, 0x0100, 0x72b0, 0x9284, - 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, 0x7280, 0x9205, 0x7082, - 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6a66, 0x0120, 0x2011, - 0x1a08, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2fc0, 0x0010, - 0x080c, 0xe577, 0x002e, 0x00ee, 0x080c, 0xabdf, 0x0804, 0xd233, - 0x080c, 0xabdf, 0x0005, 0x2600, 0x0002, 0xd457, 0xd488, 0xd499, - 0xd457, 0xd457, 0xd459, 0xd4aa, 0xd457, 0xd457, 0xd457, 0xd476, - 0xd457, 0xd457, 0xd457, 0xd4b5, 0xd4c2, 0xd4f3, 0xd457, 0x080c, - 0x0d7d, 0x080c, 0xe4d3, 0x1d20, 0x080c, 0x3326, 0x1d08, 0x080c, - 0xd60d, 0x1148, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, - 0x080c, 0x9207, 0x0005, 0x080c, 0x31ef, 0x080c, 0xcf66, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x9207, 0x0005, 0x080c, 0xe4d3, - 0x1938, 0x080c, 0x3326, 0x1920, 0x080c, 0xd60d, 0x1d60, 0x703c, - 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9207, 0x0005, - 0x080c, 0x3326, 0x1904, 0xd440, 0x2009, 0x0041, 0x080c, 0xe580, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, 0x9684, - 0x0005, 0x080c, 0x3326, 0x1904, 0xd440, 0x2009, 0x0042, 0x080c, - 0xe580, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, - 0x9684, 0x0005, 0x080c, 0x3326, 0x1904, 0xd440, 0x2009, 0x0046, - 0x080c, 0xe580, 0x080c, 0xabdf, 0x0005, 0x080c, 0xd515, 0x0904, - 0xd440, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x9207, 0x080c, - 0x9684, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, - 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, - 0x19bc, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19bd, 0x2004, - 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xbbb5, - 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9207, - 0x080c, 0x9684, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, - 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, - 0x2058, 0xb8d4, 0xd084, 0x0150, 0x7128, 0x6050, 0x9106, 0x1120, - 0x712c, 0x604c, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, 0x0086, - 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x7090, 0x908a, 0x00f9, 0x16e8, 0x20e1, 0x0000, 0x2001, 0x199f, - 0x2003, 0x0000, 0x080c, 0x1053, 0x05a0, 0x2900, 0x6016, 0x7090, - 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, - 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, - 0x199f, 0x0016, 0x200c, 0x0471, 0x001e, 0x2940, 0x080c, 0x1053, - 0x01c0, 0x2900, 0xa006, 0x2100, 0x81ff, 0x0180, 0x0c18, 0xa832, - 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, - 0x199f, 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, - 0x0048, 0x2071, 0x1800, 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, - 0x0fec, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, - 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, - 0xffff, 0x11a8, 0x080c, 0x219a, 0x2099, 0x026c, 0x2001, 0x0014, - 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, - 0x22a8, 0x8108, 0x080c, 0x219a, 0x2099, 0x0260, 0x0ca8, 0x080c, - 0x219a, 0x2061, 0x199f, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, - 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, - 0x080c, 0x219a, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x199f, 0x2019, - 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, - 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x21b2, 0x20a1, - 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, - 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, - 0x21b2, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x21b2, 0x2061, 0x19a2, - 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, - 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, - 0x21b2, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a2, 0x2019, 0x0260, - 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, - 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, - 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, - 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, - 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, - 0x0005, 0x00d6, 0x080c, 0xd6a3, 0x00de, 0x0005, 0x00d6, 0x080c, - 0xd6b0, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, - 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, - 0xe6a0, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, - 0x00ff, 0x6824, 0x080c, 0x2614, 0x1148, 0x2001, 0x0001, 0x080c, - 0xe6a0, 0x2110, 0x900e, 0x080c, 0x323e, 0x0018, 0x9085, 0x0001, - 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xac4f, - 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2614, 0x1568, 0x080c, 0x65bf, 0x1550, 0xbe12, - 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xe4d3, - 0x11c8, 0x080c, 0x3326, 0x11b0, 0x080c, 0xd60d, 0x0500, 0x2001, - 0x0007, 0x080c, 0x6570, 0x2001, 0x0007, 0x080c, 0x659c, 0x6017, - 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9207, 0x0010, 0x080c, 0xabdf, 0x9085, 0x0001, 0x00ce, 0x00be, - 0x0005, 0x080c, 0xabdf, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, - 0xabdf, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, - 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, - 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, - 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, - 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162, 0x908e, - 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, - 0x1a0c, 0x0d7d, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, - 0x1a04, 0xd7f2, 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, - 0x190c, 0x0d7d, 0x2001, 0x0007, 0x080c, 0x659c, 0x080c, 0x95c6, - 0x080c, 0xac1a, 0x080c, 0x9684, 0x0005, 0xd72d, 0xd72f, 0xd72d, - 0xd72d, 0xd72d, 0xd72f, 0xd73c, 0xd7ef, 0xd78c, 0xd7ef, 0xd7a0, - 0xd7ef, 0xd73c, 0xd7ef, 0xd7e7, 0xd7ef, 0xd7e7, 0xd7ef, 0xd7ef, - 0xd72d, 0xd72d, 0xd72d, 0xd72d, 0xd72d, 0xd72d, 0xd72d, 0xd72d, - 0xd72d, 0xd72d, 0xd72d, 0xd72f, 0xd72d, 0xd7ef, 0xd72d, 0xd72d, - 0xd7ef, 0xd72d, 0xd7ec, 0xd7ef, 0xd72d, 0xd72d, 0xd72d, 0xd72d, - 0xd7ef, 0xd7ef, 0xd72d, 0xd7ef, 0xd7ef, 0xd72d, 0xd737, 0xd72d, - 0xd72d, 0xd72d, 0xd72d, 0xd7eb, 0xd7ef, 0xd72d, 0xd72d, 0xd7ef, - 0xd7ef, 0xd72d, 0xd72d, 0xd72d, 0xd72d, 0x080c, 0x0d7d, 0x080c, - 0xcf69, 0x6003, 0x0002, 0x080c, 0x9684, 0x0804, 0xd7f1, 0x9006, - 0x080c, 0x655c, 0x0804, 0xd7ef, 0x080c, 0x6a62, 0x1904, 0xd7ef, - 0x9006, 0x080c, 0x655c, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, - 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, - 0x0428, 0x6010, 0x2058, 0xb884, 0x9005, 0x1178, 0x080c, 0xcf51, - 0x1904, 0xd7ef, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0007, 0x080c, - 0x4cc0, 0x004e, 0x003e, 0x0804, 0xd7ef, 0x080c, 0x3357, 0x1904, - 0xd7ef, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, - 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001, 0x0002, - 0x080c, 0x6570, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x9207, 0x080c, 0x9684, 0x6110, 0x2158, 0x2009, 0x0001, - 0x080c, 0x862b, 0x0804, 0xd7f1, 0x6610, 0x2658, 0xbe04, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xd7ef, 0x9686, 0x0004, - 0x0904, 0xd7ef, 0x080c, 0x8eac, 0x2001, 0x0004, 0x0804, 0xd7ed, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, - 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4cc0, 0x004e, - 0x003e, 0x2001, 0x0006, 0x080c, 0xd80b, 0x6610, 0x2658, 0xbe04, - 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, - 0x2001, 0x0006, 0x080c, 0x659c, 0x9284, 0x00ff, 0x908e, 0x0007, - 0x1120, 0x2001, 0x0006, 0x080c, 0x6570, 0x080c, 0x6a62, 0x11f8, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, - 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, - 0x78aa, 0x00fe, 0x0804, 0xd776, 0x2001, 0x0004, 0x0030, 0x2001, - 0x0006, 0x0409, 0x0020, 0x0018, 0x0010, 0x080c, 0x659c, 0x080c, - 0xabdf, 0x0005, 0x2600, 0x0002, 0xd806, 0xd806, 0xd806, 0xd806, - 0xd806, 0xd808, 0xd806, 0xd808, 0xd806, 0xd806, 0xd808, 0xd806, - 0xd806, 0xd806, 0xd808, 0xd808, 0xd808, 0xd808, 0x080c, 0x0d7d, - 0x080c, 0xabdf, 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, - 0xb900, 0xd184, 0x0138, 0x080c, 0x6570, 0x9006, 0x080c, 0x655c, - 0x080c, 0x321e, 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, - 0xb804, 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0d7d, - 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, - 0x0d7d, 0x006b, 0x0005, 0xb68f, 0xb68f, 0xb68f, 0xb68f, 0xd8a0, - 0xb68f, 0xd88a, 0xd84b, 0xb68f, 0xb68f, 0xb68f, 0xb68f, 0xb68f, - 0xb68f, 0xb68f, 0xb68f, 0xd8a0, 0xb68f, 0xd88a, 0xd891, 0xb68f, - 0xb68f, 0xb68f, 0xb68f, 0x00f6, 0x080c, 0x6a62, 0x11d8, 0x080c, - 0xcf51, 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb884, 0x9005, 0x0190, - 0x9006, 0x080c, 0x655c, 0x2001, 0x0002, 0x080c, 0x6570, 0x6023, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9207, 0x080c, - 0x9684, 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x2614, 0x11b0, 0x080c, 0x6620, 0x0118, 0x080c, 0xabdf, 0x0080, - 0xb810, 0x0006, 0xb814, 0x0006, 0xb884, 0x0006, 0x080c, 0x603e, - 0x000e, 0xb886, 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0xabdf, - 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0xabdf, - 0x0005, 0x080c, 0xba1a, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x9207, 0x080c, 0x9684, 0x0010, 0x080c, 0xabdf, 0x0005, - 0x0804, 0xabdf, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d7d, 0x080c, - 0x95c6, 0x080c, 0xac1a, 0x0005, 0x9182, 0x0040, 0x0002, 0xd8c2, - 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c4, 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, - 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, 0xd8c2, - 0xd8c2, 0xd8c2, 0x080c, 0x0d7d, 0x0096, 0x00b6, 0x00d6, 0x00e6, - 0x00f6, 0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11b0, - 0x6007, 0x0044, 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, - 0xd92b, 0x080c, 0xe694, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, - 0x0001, 0x2011, 0x0200, 0x080c, 0x88ce, 0x0020, 0x9026, 0x080c, - 0xe518, 0x0c30, 0x080c, 0x103a, 0x090c, 0x0d7d, 0x6003, 0x0007, - 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, - 0x6008, 0xa8e2, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, - 0xa876, 0xa87f, 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, - 0x6d7b, 0x001e, 0x080c, 0xe694, 0x1904, 0xd98b, 0x9486, 0x2000, - 0x1130, 0x2019, 0x0017, 0x080c, 0xe249, 0x0804, 0xd98b, 0x9486, - 0x0200, 0x1120, 0x080c, 0xe1d9, 0x0804, 0xd98b, 0x9486, 0x0400, - 0x0120, 0x9486, 0x1000, 0x1904, 0xd98b, 0x2019, 0x0002, 0x080c, - 0xe1f8, 0x0804, 0xd98b, 0x2069, 0x1a6e, 0x6a00, 0xd284, 0x0904, - 0xd9f5, 0x9284, 0x0300, 0x1904, 0xd9ee, 0x6804, 0x9005, 0x0904, - 0xd9d6, 0x2d78, 0x6003, 0x0007, 0x080c, 0x1053, 0x0904, 0xd997, - 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, - 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, 0xd9f9, 0x9006, 0xa802, - 0xa867, 0x0116, 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, - 0x2058, 0xb8a0, 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, - 0xa9be, 0xb930, 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, - 0x9084, 0x0003, 0x9080, 0xd993, 0x2005, 0xa87e, 0x20a9, 0x000a, - 0x2001, 0x0270, 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, - 0x0080, 0x20e1, 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, - 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, - 0xa9ae, 0x080c, 0x6d7e, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, - 0x00be, 0x009e, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, - 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, 0x103a, 0x1904, 0xd940, - 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, - 0x080c, 0x9200, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, - 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, - 0x918c, 0xf700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, - 0x0043, 0x2009, 0xa025, 0x080c, 0x9200, 0x0828, 0x6868, 0x602e, - 0x686c, 0x6032, 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, - 0x2009, 0xa022, 0x080c, 0x9200, 0x0804, 0xd98b, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4b09, 0x6017, - 0xf300, 0x0010, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, - 0x2009, 0xa022, 0x080c, 0x9200, 0x0804, 0xd98b, 0x6017, 0xf500, - 0x0c98, 0x6017, 0xf600, 0x0804, 0xd9ab, 0x6017, 0xf200, 0x0804, - 0xd9ab, 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, - 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, 0xd993, 0x2005, 0xa87e, - 0x2928, 0x6010, 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, - 0xa88e, 0xb830, 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, - 0x0205, 0x2104, 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, - 0x0210, 0x2214, 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, - 0x0d7d, 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, 0xda75, 0x2041, 0x0001, - 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, - 0x931a, 0x0530, 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, - 0x0260, 0x2098, 0x0c68, 0x2950, 0x080c, 0x1053, 0x0170, 0x2900, - 0xb002, 0xa867, 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001b, 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, - 0x0118, 0x080c, 0x106c, 0x0cc8, 0x080c, 0x106c, 0x0804, 0xd997, - 0x2548, 0x8847, 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, - 0x0000, 0x080c, 0xe27c, 0x0804, 0xd98b, 0x8010, 0x0004, 0x801a, - 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, - 0x1160, 0x6004, 0x908a, 0x0057, 0x1a0c, 0x0d7d, 0x9082, 0x0040, - 0x0a0c, 0x0d7d, 0x2008, 0x0804, 0xdb00, 0x9186, 0x0051, 0x0108, - 0x0040, 0x080c, 0xaa9a, 0x01e8, 0x9086, 0x0002, 0x0904, 0xdb47, - 0x00c0, 0x9186, 0x0027, 0x0180, 0x9186, 0x0048, 0x0128, 0x9186, - 0x0014, 0x0150, 0x190c, 0x0d7d, 0x080c, 0xaa9a, 0x0150, 0x9086, - 0x0004, 0x0904, 0xdbe4, 0x0028, 0x6004, 0x9082, 0x0040, 0x2008, - 0x001a, 0x080c, 0xac99, 0x0005, 0xdac7, 0xdac9, 0xdac9, 0xdaf0, - 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, - 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0xdac7, 0x080c, - 0x0d7d, 0x080c, 0x95c6, 0x080c, 0x9684, 0x0036, 0x0096, 0x6014, - 0x904d, 0x01d8, 0x080c, 0xc832, 0x01c0, 0x6003, 0x0002, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, - 0x080c, 0xe27c, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, - 0x1986, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, - 0x0096, 0x080c, 0x95c6, 0x080c, 0x9684, 0x080c, 0xc832, 0x0120, - 0x6014, 0x2048, 0x080c, 0x106c, 0x080c, 0xac1a, 0x009e, 0x0005, - 0x0002, 0xdb14, 0xdb29, 0xdb16, 0xdb3e, 0xdb14, 0xdb14, 0xdb14, - 0xdb14, 0xdb14, 0xdb14, 0xdb14, 0xdb14, 0xdb14, 0xdb14, 0xdb14, - 0xdb14, 0xdb14, 0xdb14, 0xdb14, 0x080c, 0x0d7d, 0x0096, 0x6014, - 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, - 0x080c, 0xac7c, 0x0010, 0x6003, 0x0004, 0x080c, 0x9684, 0x009e, - 0x0005, 0x080c, 0xc832, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, - 0x009e, 0xd1ec, 0x1138, 0x080c, 0x88a3, 0x080c, 0xabdf, 0x080c, - 0x9684, 0x0005, 0x080c, 0xe4dc, 0x0db0, 0x0cc8, 0x6003, 0x0001, - 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9200, 0x0005, 0x9182, - 0x0040, 0x0002, 0xdb5d, 0xdb5f, 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, - 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, 0xdb5d, - 0xdb5d, 0xdb5d, 0xdb5d, 0xdb60, 0xdb5d, 0x080c, 0x0d7d, 0x0005, - 0x00d6, 0x080c, 0x88a3, 0x00de, 0x080c, 0xe534, 0x080c, 0xabdf, - 0x0005, 0x9182, 0x0040, 0x0002, 0xdb7f, 0xdb7f, 0xdb7f, 0xdb7f, - 0xdb7f, 0xdb7f, 0xdb7f, 0xdb7f, 0xdb7f, 0xdb81, 0xdbac, 0xdb7f, - 0xdb7f, 0xdb7f, 0xdb7f, 0xdbac, 0xdb7f, 0xdb7f, 0xdb7f, 0x080c, + 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, 0x7220, 0x080c, 0xc853, + 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, + 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xcbaf, 0x00ce, + 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, + 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7d, 0x908a, 0x0092, 0x1a0c, + 0x0d7d, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, + 0x0014, 0x190c, 0x0d7d, 0x080c, 0x95ff, 0x0096, 0x6014, 0x2048, + 0x080c, 0xc865, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, + 0x0029, 0x080c, 0x6d9f, 0x009e, 0x080c, 0xac2b, 0x0804, 0x96bd, + 0xc24d, 0xc24f, 0xc24f, 0xc24d, 0xc24d, 0xc24d, 0xc24d, 0xc24d, + 0xc24d, 0xc24d, 0xc24d, 0xc24d, 0xc24d, 0x080c, 0x0d7d, 0x080c, + 0xac2b, 0x0005, 0x9186, 0x0013, 0x1130, 0x6004, 0x9082, 0x0085, + 0x2008, 0x0804, 0xc29e, 0x9186, 0x0027, 0x1558, 0x080c, 0x95ff, + 0x080c, 0x320f, 0x080c, 0xcf99, 0x0096, 0x6014, 0x2048, 0x080c, + 0xc865, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, + 0x080c, 0x6d9f, 0x080c, 0xca54, 0x009e, 0x080c, 0xabf0, 0x0005, + 0x9186, 0x0089, 0x0118, 0x9186, 0x008a, 0x1140, 0x080c, 0xaaab, + 0x0128, 0x9086, 0x000c, 0x0904, 0xc2d6, 0x0000, 0x080c, 0xacaa, + 0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, 0x95ff, 0x0096, 0x6014, + 0x2048, 0x080c, 0xc865, 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000, + 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x0890, 0x0002, 0xc2ae, + 0xc2ac, 0xc2ac, 0xc2ac, 0xc2ac, 0xc2ac, 0xc2c2, 0xc2ac, 0xc2ac, + 0xc2ac, 0xc2ac, 0xc2ac, 0xc2ac, 0x080c, 0x0d7d, 0x6034, 0x908c, + 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, + 0x2001, 0x1985, 0x0010, 0x2001, 0x1986, 0x2004, 0x601a, 0x6003, + 0x000c, 0x0005, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, + 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1985, 0x0010, 0x2001, + 0x1986, 0x2004, 0x601a, 0x6003, 0x000e, 0x0005, 0x9182, 0x0092, + 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xacaa, 0xc2ec, + 0xc2ec, 0xc2ec, 0xc2ec, 0xc2ee, 0xc33b, 0xc2ec, 0xc2ec, 0xc2ec, + 0xc2ec, 0xc2ec, 0xc2ec, 0xc2ec, 0x080c, 0x0d7d, 0x0096, 0x6010, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, + 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, + 0x009e, 0x0804, 0xc34f, 0x080c, 0xc865, 0x1118, 0x080c, 0xca54, + 0x0068, 0x6014, 0x2048, 0x080c, 0xcfb0, 0x1110, 0x080c, 0xca54, + 0xa867, 0x0103, 0x080c, 0xcf64, 0x080c, 0x6d9f, 0x00d6, 0x2c68, + 0x080c, 0xab9a, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, + 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, + 0x613e, 0x6910, 0x6112, 0x080c, 0xccfe, 0x695c, 0x615e, 0x6023, + 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, 0x2d60, 0x00de, 0x080c, + 0xabf0, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, + 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, + 0x2c68, 0x080c, 0xcefc, 0x11f0, 0x080c, 0xab9a, 0x01d8, 0x6106, + 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, + 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, + 0x693c, 0x613e, 0x695c, 0x615e, 0x080c, 0xccfe, 0x2009, 0x8020, + 0x080c, 0x9239, 0x2d60, 0x00de, 0x0804, 0xabf0, 0x0096, 0x6014, + 0x2048, 0x080c, 0xc865, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, + 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, + 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xcb6e, 0xa877, + 0x0000, 0x080c, 0x6d9f, 0x080c, 0xca54, 0x009e, 0x0804, 0xabf0, + 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xc865, 0x0140, 0xa867, + 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6d9f, 0x009e, + 0x001e, 0x9186, 0x0013, 0x0158, 0x9186, 0x0014, 0x0130, 0x9186, + 0x0027, 0x0118, 0x080c, 0xacaa, 0x0020, 0x080c, 0x95ff, 0x080c, + 0xac2b, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, + 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, + 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xc41b, + 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x0ff9, 0x080c, + 0x1047, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, + 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, 0x001b, 0x0499, + 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, + 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, + 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, + 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, + 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, + 0x0130, 0xa807, 0x0000, 0x080c, 0x6d9f, 0x2a48, 0x0cb8, 0x080c, + 0x6d9f, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, + 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, + 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, + 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, + 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, + 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, 0x0066, 0x0126, + 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, + 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, + 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, + 0xc498, 0xc498, 0xc493, 0xc4bc, 0xc470, 0xc493, 0xc472, 0xc493, + 0xc470, 0x90ff, 0xc493, 0xc493, 0xc493, 0xc470, 0xc470, 0xc470, + 0x080c, 0x0d7d, 0x6010, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, + 0xc4bc, 0x0036, 0x6014, 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, + 0x0118, 0x2019, 0x000c, 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, + 0x0010, 0x2019, 0x0010, 0x080c, 0xde67, 0x6023, 0x0006, 0x6003, + 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, + 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, 0x080c, 0xc865, 0x01d0, + 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, + 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x6fd3, + 0x080c, 0xcb6e, 0x080c, 0x6d93, 0x080c, 0xac2b, 0x9085, 0x0001, + 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, 0xa899, 0x080c, 0xcfbe, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x002b, 0x0106, 0x080c, + 0xa8b5, 0x010e, 0x0005, 0xc4db, 0xc509, 0xc4dd, 0xc530, 0xc504, + 0xc4db, 0xc493, 0xc498, 0xc498, 0xc493, 0xc493, 0xc493, 0xc493, + 0xc493, 0xc493, 0xc493, 0x080c, 0x0d7d, 0x86ff, 0x1510, 0x6020, + 0x9086, 0x0006, 0x01f0, 0x0096, 0x6014, 0x2048, 0x080c, 0xc865, + 0x0158, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, + 0x0ff9, 0x009e, 0x080c, 0xcb6e, 0x009e, 0x080c, 0xcf3e, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, + 0x921b, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, 0x1a94, 0x006e, + 0x08a0, 0x00e6, 0x2071, 0x19e6, 0x7030, 0x9c06, 0x1120, 0x080c, + 0xa0b3, 0x00ee, 0x0850, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, + 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0xa207, + 0x009e, 0x008e, 0x0040, 0x0066, 0x080c, 0x9faf, 0x190c, 0x0d7d, + 0x080c, 0x9fbd, 0x006e, 0x00ee, 0x1904, 0xc4dd, 0x0804, 0xc493, + 0x0036, 0x00e6, 0x2071, 0x19e6, 0x704c, 0x9c06, 0x1138, 0x901e, + 0x080c, 0xa133, 0x00ee, 0x003e, 0x0804, 0xc4dd, 0x080c, 0xa33e, + 0x00ee, 0x003e, 0x1904, 0xc4dd, 0x0804, 0xc493, 0x00c6, 0x0066, + 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xc566, + 0xc635, 0xc79f, 0xc56e, 0xac2b, 0xc566, 0xde59, 0xcfa6, 0xc635, + 0x90c6, 0xc82b, 0xc55f, 0xc55f, 0xc55f, 0xc55f, 0xc55f, 0x080c, + 0x0d7d, 0x080c, 0xca7a, 0x1110, 0x080c, 0xb5c6, 0x0005, 0x080c, + 0x95ff, 0x0804, 0xabf0, 0x601b, 0x0001, 0x0005, 0x080c, 0xc865, + 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, 0x080c, + 0xa899, 0x080c, 0xcfbe, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, + 0x0013, 0x0804, 0xa8b5, 0xc593, 0xc595, 0xc5bf, 0xc5d3, 0xc600, + 0xc593, 0xc566, 0xc566, 0xc566, 0xc5da, 0xc5da, 0xc593, 0xc593, + 0xc593, 0xc593, 0xc5e4, 0x080c, 0x0d7d, 0x00e6, 0x6014, 0x0096, + 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e6, 0x7030, + 0x9c06, 0x01d0, 0x0066, 0x080c, 0x9faf, 0x190c, 0x0d7d, 0x080c, + 0x9fbd, 0x006e, 0x080c, 0xcf3e, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x2001, 0x1986, 0x2004, 0x601a, 0x2009, 0x8020, + 0x080c, 0x921b, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, + 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x080c, 0xcf3e, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, + 0x080c, 0x921b, 0x0005, 0x080c, 0xa899, 0x080c, 0xaa2d, 0x080c, + 0xa8b5, 0x0c28, 0x0096, 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, + 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x56fd, 0x01b8, 0x6014, + 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, + 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, + 0x4005, 0xa89b, 0x0004, 0x080c, 0x6d9f, 0x009e, 0x0804, 0xabf0, + 0x6014, 0x0096, 0x904d, 0x0560, 0xa97c, 0xd1e4, 0x1158, 0x611c, + 0xd1fc, 0x0530, 0x6110, 0x00b6, 0x2158, 0xb93c, 0x8109, 0x0208, + 0xb93e, 0x00be, 0x080c, 0xa8b5, 0x2001, 0x180f, 0x2004, 0xd0c4, + 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, + 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, 0x080c, 0x1693, 0x6000, + 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xac8d, 0x0005, + 0x009e, 0x080c, 0x1a94, 0x0804, 0xc5bf, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0d7d, 0x000b, 0x0005, 0xc64c, 0xc56b, 0xc64e, 0xc64c, + 0xc64e, 0xc64e, 0xc567, 0xc64c, 0xc561, 0xc561, 0xc64c, 0xc64c, + 0xc64c, 0xc64c, 0xc64c, 0xc64c, 0x080c, 0x0d7d, 0x6010, 0x00b6, + 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, + 0x0d7d, 0x00b6, 0x0013, 0x00be, 0x0005, 0xc669, 0xc736, 0xc66b, + 0xc6ab, 0xc66b, 0xc6ab, 0xc66b, 0xc679, 0xc669, 0xc6ab, 0xc669, + 0xc69a, 0x080c, 0x0d7d, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, + 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, + 0xc732, 0x6004, 0x080c, 0xca7a, 0x0904, 0xc74f, 0x908e, 0x0004, + 0x1110, 0x080c, 0x323e, 0x908e, 0x0021, 0x0904, 0xc753, 0x908e, + 0x0022, 0x0904, 0xc79a, 0x908e, 0x003d, 0x0904, 0xc753, 0x908e, + 0x0039, 0x0904, 0xc757, 0x908e, 0x0035, 0x0904, 0xc757, 0x908e, + 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, 0x320f, 0x080c, + 0xb5c6, 0x0804, 0xac2b, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, + 0x0904, 0xc723, 0x9186, 0x0002, 0x1904, 0xc6f8, 0x2001, 0x1837, + 0x2004, 0xd08c, 0x11c8, 0x080c, 0x74ec, 0x11b0, 0x080c, 0xcf84, + 0x0138, 0x080c, 0x750f, 0x1120, 0x080c, 0x73f7, 0x0804, 0xc783, + 0x2001, 0x197c, 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, + 0x080c, 0x741d, 0x0804, 0xc783, 0x6010, 0x2058, 0x2001, 0x1837, + 0x2004, 0xd0ac, 0x1904, 0xc783, 0xb8a0, 0x9084, 0xff80, 0x1904, + 0xc783, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, + 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, + 0x080c, 0xab9a, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, 0x0458, + 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010, 0x2058, + 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, 0x2104, 0xc085, + 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5fd7, 0x00ee, 0x080c, + 0xb5c6, 0x0030, 0x080c, 0xb5c6, 0x080c, 0x320f, 0x080c, 0xcf99, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x323e, 0x012e, 0x00ee, + 0x080c, 0xac2b, 0x0005, 0x2001, 0x0002, 0x080c, 0x6594, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x9240, 0x080c, 0x96bd, 0x00de, + 0x00ce, 0x0c80, 0x080c, 0x323e, 0x0804, 0xc6a7, 0x00c6, 0x00d6, + 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, + 0x00ff, 0x9005, 0x0904, 0xc6f8, 0x8001, 0xb842, 0x6003, 0x0001, + 0x080c, 0x9240, 0x080c, 0x96bd, 0x00de, 0x00ce, 0x0898, 0x080c, + 0xb5c6, 0x0804, 0xc6a9, 0x080c, 0xb602, 0x0804, 0xc6a9, 0x00d6, + 0x2c68, 0x6104, 0x080c, 0xcefc, 0x00de, 0x0118, 0x080c, 0xabf0, + 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, + 0x2001, 0x1986, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, + 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x2009, 0x8020, + 0x080c, 0x9239, 0x0005, 0x00de, 0x00ce, 0x080c, 0xb5c6, 0x080c, + 0x320f, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x323e, 0x6017, + 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, 0x012e, + 0x00ee, 0x0005, 0x080c, 0xb02b, 0x1904, 0xc74f, 0x0005, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0d7d, 0x0096, 0x00d6, 0x001b, 0x00de, + 0x009e, 0x0005, 0xc7ba, 0xc7ba, 0xc7ba, 0xc7ba, 0xc7ba, 0xc7ba, + 0xc7ba, 0xc7ba, 0xc7ba, 0xc566, 0xc7ba, 0xc56b, 0xc7bc, 0xc56b, + 0xc7d6, 0xc7ba, 0x080c, 0x0d7d, 0x6004, 0x9086, 0x008b, 0x01b0, + 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, 0x602c, + 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, 0x6003, + 0x000d, 0x2009, 0x8020, 0x080c, 0x9239, 0x0005, 0x080c, 0xcf78, + 0x0118, 0x080c, 0xcf8b, 0x0010, 0x080c, 0xcf99, 0x080c, 0xca54, + 0x080c, 0xc865, 0x0570, 0x080c, 0x320f, 0x080c, 0xc865, 0x0168, + 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, + 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6d9f, 0x2c68, 0x080c, 0xab9a, + 0x0150, 0x6810, 0x6012, 0x080c, 0xccfe, 0x00c6, 0x2d60, 0x080c, + 0xac2b, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, + 0x00c8, 0x080c, 0xcf78, 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, + 0x080c, 0x320f, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x320f, 0x0868, + 0x080c, 0xac2b, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d7d, + 0x0002, 0xc841, 0xc841, 0xc843, 0xc843, 0xc843, 0xc841, 0xc841, + 0xac2b, 0xc841, 0xc841, 0xc841, 0xc841, 0xc841, 0xc841, 0xc841, + 0xc841, 0x080c, 0x0d7d, 0x080c, 0xa899, 0x080c, 0xaa2d, 0x080c, + 0xa8b5, 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x6d9f, + 0x009e, 0x0804, 0xabf0, 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, + 0x0240, 0x2001, 0x181a, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, + 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, + 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, + 0x080c, 0x10f2, 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, + 0x7354, 0x7074, 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, + 0xcf84, 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, + 0x1148, 0x080c, 0x320f, 0x080c, 0xcf99, 0x00c6, 0x080c, 0xac2b, + 0x00ce, 0x0060, 0x080c, 0xcc70, 0x0148, 0x080c, 0xca7a, 0x1110, + 0x080c, 0xb5c6, 0x00c6, 0x080c, 0xabf0, 0x00ce, 0x9ce0, 0x001c, + 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, + 0x81ff, 0x0128, 0x2061, 0x1b31, 0x6112, 0x080c, 0x320f, 0x9006, + 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x080c, 0xab9a, 0x01b0, 0x665e, 0x2b00, + 0x6012, 0x080c, 0x56fd, 0x0118, 0x080c, 0xc996, 0x0168, 0x080c, + 0xccfe, 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0xac8d, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0xbaa0, 0x080c, 0xac60, 0x0580, 0x605f, 0x0000, + 0x2b00, 0x6012, 0x080c, 0xccfe, 0x6023, 0x0003, 0x0016, 0x080c, + 0xa899, 0x080c, 0x93c6, 0x0076, 0x903e, 0x080c, 0x928f, 0x2c08, + 0x080c, 0xe038, 0x007e, 0x080c, 0xa8b5, 0x001e, 0xd184, 0x0128, + 0x080c, 0xabf0, 0x9085, 0x0001, 0x0070, 0x080c, 0x56fd, 0x0128, + 0xd18c, 0x1170, 0x080c, 0xc996, 0x0148, 0x2009, 0x004c, 0x080c, + 0xac8d, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x2900, 0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, + 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, 0xab9a, 0x2c78, 0x0590, + 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, + 0xc9a8, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, + 0x197f, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xabf0, 0x00d0, + 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xabf0, + 0x0088, 0x2f60, 0x080c, 0x56fd, 0x0138, 0xd18c, 0x1118, 0x04f1, + 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xac8d, + 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, + 0x00c6, 0x0046, 0x080c, 0xab9a, 0x2c78, 0x0508, 0x7e5e, 0x2b00, + 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, + 0x2001, 0x197d, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xabf0, + 0x0060, 0x2f60, 0x080c, 0x56fd, 0x0120, 0xd18c, 0x1160, 0x0071, + 0x0130, 0x2009, 0x0052, 0x080c, 0xac8d, 0x9085, 0x0001, 0x004e, + 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, + 0x4ac9, 0x00ce, 0x1120, 0x080c, 0xabf0, 0x9006, 0x0005, 0xa867, + 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, + 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0xa899, 0x080c, + 0x6826, 0x0158, 0x2001, 0xc9af, 0x0006, 0x900e, 0x2400, 0x080c, + 0x6fd3, 0x080c, 0x6d9f, 0x000e, 0x0807, 0x2418, 0x080c, 0x95c5, + 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, + 0x93e0, 0x008e, 0x080c, 0x928f, 0x2f08, 0x2648, 0x080c, 0xe038, + 0xb93c, 0x81ff, 0x090c, 0x94b7, 0x080c, 0xa8b5, 0x012e, 0x007e, + 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xab9a, + 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xccfe, 0x6023, 0x0001, + 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0xac8d, 0x9085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x080c, 0xac60, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, + 0xccfe, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, + 0x174b, 0x00fe, 0x2009, 0x0021, 0x080c, 0xac8d, 0x9085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, + 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0xab9a, 0x0198, 0x660a, + 0x2b08, 0x6112, 0x080c, 0xccfe, 0x6023, 0x0001, 0x2900, 0x6016, + 0x001e, 0x0016, 0x080c, 0xac8d, 0x9085, 0x0001, 0x001e, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x080c, 0xac60, 0x0188, 0x2b08, 0x6112, 0x080c, 0xccfe, 0x6023, + 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xac8d, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, + 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, + 0xba3c, 0x82ff, 0x0118, 0x8211, 0xba3e, 0x1140, 0xb8d0, 0x9005, + 0x0128, 0xb888, 0x9005, 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e, + 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, + 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, + 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, + 0x01a8, 0x6014, 0x904d, 0x080c, 0xc865, 0x0180, 0xa864, 0x9086, + 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, + 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, + 0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x080c, 0xac60, 0x0198, 0x2b08, 0x6112, 0x080c, 0xccfe, 0x6023, + 0x0001, 0x2900, 0x6016, 0x080c, 0x320f, 0x2009, 0x0028, 0x080c, + 0xac8d, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x9186, 0x0015, 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, + 0x1178, 0x00b6, 0x080c, 0xb81a, 0x00be, 0x080c, 0xba3d, 0x6003, + 0x0001, 0x6007, 0x0029, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0078, + 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, + 0x0001, 0x080c, 0xcebd, 0x080c, 0xb5c6, 0x080c, 0xabf0, 0x0005, + 0x0096, 0x6014, 0x904d, 0x090c, 0x0d7d, 0xa87b, 0x0030, 0xa883, + 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x009e, 0x080c, 0xabf0, + 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, + 0x6594, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, + 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x66df, + 0x00be, 0x080c, 0xbb0e, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, + 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x6594, 0x6014, + 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xafff, 0x0048, 0x6014, + 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xb5c6, 0x080c, 0xabf0, + 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0d7d, + 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, + 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x080c, 0xabf0, + 0x08f8, 0x6014, 0x904d, 0x090c, 0x0d7d, 0xa87b, 0x0030, 0xa883, + 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x080c, 0xabf0, 0x0840, + 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, + 0xa882, 0x0005, 0x604b, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, + 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9239, 0x0005, 0x00c6, + 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, + 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xc566, + 0xcba1, 0xcba1, 0xcba4, 0xe365, 0xe380, 0xe383, 0xc566, 0xc566, + 0xc566, 0xc566, 0xc566, 0xc566, 0xc566, 0xc566, 0xc566, 0x080c, + 0x0d7d, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, + 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834, + 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, 0x080c, 0xab9a, 0x0508, + 0x7810, 0x6012, 0x080c, 0xccfe, 0x7820, 0x9086, 0x0003, 0x0128, + 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, + 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, + 0x795c, 0x615e, 0x2009, 0x8020, 0x080c, 0x9239, 0x2f60, 0x00fe, + 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1987, 0x2004, 0x604a, 0x0005, + 0x0016, 0x0096, 0x6814, 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e, + 0xa87c, 0x1108, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, + 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, + 0xa878, 0x2048, 0x080c, 0x0ff9, 0x6830, 0x6036, 0x908e, 0x0001, + 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, + 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, + 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, + 0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, + 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, + 0x6910, 0x6112, 0x695c, 0x615e, 0x6023, 0x0001, 0x6007, 0x0039, + 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, 0x009e, 0x001e, + 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, + 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, + 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, + 0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, + 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, + 0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, + 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, + 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, + 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, + 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1981, 0x200c, + 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x9181, 0x2001, 0x1985, + 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1983, 0x200c, + 0x8000, 0x2014, 0x2071, 0x196b, 0x711a, 0x721e, 0x2001, 0x0064, + 0x080c, 0x9181, 0x2001, 0x1986, 0x82ff, 0x1110, 0x2011, 0x0014, + 0x2202, 0x2001, 0x1987, 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, + 0x080c, 0xa88a, 0x2001, 0x1a88, 0x2102, 0x2001, 0x0032, 0x080c, + 0x1693, 0x080c, 0x6a6f, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, + 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1985, 0x2003, 0x0028, + 0x2001, 0x1986, 0x2003, 0x0014, 0x2071, 0x196b, 0x701b, 0x0000, + 0x701f, 0x07d0, 0x2001, 0x1987, 0x2009, 0x001e, 0x2102, 0x2001, + 0x0017, 0x080c, 0xa88a, 0x2001, 0x1a88, 0x2102, 0x2001, 0x0032, + 0x080c, 0x1693, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, + 0x904d, 0x0110, 0x080c, 0x1079, 0x009e, 0x0005, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x080c, 0xab9a, 0x0180, 0x2b08, 0x6112, + 0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, + 0xac8d, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, + 0x7090, 0x9086, 0x0018, 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, + 0x1160, 0x2c78, 0x080c, 0x977c, 0x01d8, 0x707c, 0xaa50, 0x9206, + 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, + 0xbaa0, 0x00be, 0x900e, 0x080c, 0x325e, 0x080c, 0xafff, 0x0020, + 0x080c, 0xb5c6, 0x080c, 0xabf0, 0x00fe, 0x00ee, 0x009e, 0x0005, + 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x080c, 0xab9a, 0x0188, 0x2b08, 0x6112, 0x080c, 0xccfe, + 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0xac8d, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0xab9a, 0x0180, 0x2b08, + 0x6112, 0x080c, 0xccfe, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, + 0x080c, 0xac8d, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, + 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, + 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, + 0x7190, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, + 0x0000, 0x2001, 0x199f, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, + 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, + 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, + 0x080c, 0xd5a5, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, + 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, 0xb5c6, 0x080c, + 0xabf0, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, + 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, + 0x9186, 0x0015, 0x11b8, 0x7090, 0x9086, 0x0004, 0x1198, 0x6014, + 0x2048, 0x2c78, 0x080c, 0x977c, 0x01a8, 0x707c, 0xaa74, 0x9206, + 0x1130, 0x7080, 0xaa78, 0x9206, 0x1110, 0x080c, 0x320f, 0x080c, + 0xafff, 0x0020, 0x080c, 0xb5c6, 0x080c, 0xabf0, 0x00fe, 0x00ee, + 0x009e, 0x0005, 0x7060, 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, + 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1550, 0x7090, + 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x977c, + 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080, 0xaad0, 0x9206, + 0x1160, 0x080c, 0x320f, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, + 0xc0fd, 0x080c, 0x56ad, 0x001e, 0x0010, 0x080c, 0x5496, 0x080c, + 0xc865, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, + 0x0080, 0x080c, 0xc865, 0x01b8, 0x6014, 0x2048, 0x080c, 0x5496, + 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, + 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6d9f, + 0x012e, 0x080c, 0xabf0, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, + 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, + 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, + 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, + 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036, 0x080c, 0xc865, + 0x0904, 0xceb9, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, + 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, + 0xd0f4, 0x1140, 0x080c, 0x6937, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, + 0x0006, 0x2098, 0x080c, 0x0fc4, 0x20a9, 0x0004, 0xa85c, 0x9080, + 0x0035, 0x20a0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fc4, + 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, + 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, + 0xb804, 0x9084, 0x00ff, 0xa89e, 0x080c, 0x6d93, 0x6017, 0x0000, + 0x009e, 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, + 0x00b6, 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, + 0x0260, 0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, + 0x080c, 0x2630, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, + 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4b29, 0x00a8, + 0x9096, 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, + 0xa8a6, 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, + 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, + 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xc853, 0x01f0, + 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, + 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, + 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, + 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, + 0x0cc8, 0xa974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, + 0x1160, 0xa9a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, + 0xa834, 0xa938, 0x9115, 0x190c, 0xbec6, 0x0005, 0x0036, 0x2019, + 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xc865, + 0x01c8, 0x080c, 0xca54, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, + 0x0096, 0x2048, 0xa87c, 0x080c, 0xca7a, 0x1118, 0x080c, 0xb5c6, + 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, + 0x6d9f, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, + 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, + 0x0020, 0xa87b, 0x0005, 0x080c, 0xcb6e, 0xa877, 0x0000, 0x0005, + 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, + 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, + 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, + 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, 0x4ce0, 0x004e, 0x003e, + 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1985, 0x2004, 0x601a, + 0x0005, 0x2001, 0x1987, 0x2004, 0x604a, 0x0005, 0x080c, 0xabf0, + 0x0804, 0x96bd, 0x611c, 0xd1fc, 0xa97c, 0x1108, 0xd1e4, 0x0005, + 0x601c, 0xd0fc, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x601c, 0xd0fc, + 0xc0fc, 0x601e, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x6044, 0xd0fc, + 0x1138, 0xd0bc, 0x0198, 0xc0bc, 0x6046, 0x6003, 0x0002, 0x0070, + 0xd0ac, 0x1160, 0xd0dc, 0x1128, 0x908c, 0x000f, 0x9186, 0x0005, + 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x0005, 0x00b6, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d7d, 0x001b, 0x006e, + 0x00be, 0x0005, 0xcff2, 0xd700, 0xd851, 0xcff2, 0xcff2, 0xcff2, + 0xcff2, 0xcff2, 0xd029, 0xd8d5, 0xcff2, 0xcff2, 0xcff2, 0xcff2, + 0xcff2, 0xcff2, 0x080c, 0x0d7d, 0x0066, 0x6000, 0x90b2, 0x0016, + 0x1a0c, 0x0d7d, 0x0013, 0x006e, 0x0005, 0xd00d, 0xddf6, 0xd00d, + 0xd00d, 0xd00d, 0xd00d, 0xd00d, 0xd00d, 0xdda5, 0xde48, 0xd00d, + 0xe4a0, 0xe4d4, 0xe4a0, 0xe4d4, 0xd00d, 0x080c, 0x0d7d, 0x6000, + 0x9082, 0x0016, 0x1a0c, 0x0d7d, 0x6000, 0x000a, 0x0005, 0xd027, + 0xdab2, 0xdb7d, 0xdba0, 0xdc1c, 0xd027, 0xdd17, 0xdca4, 0xd8df, + 0xdd7d, 0xdd92, 0xd027, 0xd027, 0xd027, 0xd027, 0xd027, 0x080c, + 0x0d7d, 0x91b2, 0x0053, 0x1a0c, 0x0d7d, 0x2100, 0x91b2, 0x0040, + 0x1a04, 0xd476, 0x0002, 0xd073, 0xd267, 0xd073, 0xd073, 0xd073, + 0xd270, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, + 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, + 0xd073, 0xd073, 0xd075, 0xd0dc, 0xd0eb, 0xd14f, 0xd17a, 0xd1f3, + 0xd252, 0xd073, 0xd073, 0xd273, 0xd073, 0xd073, 0xd288, 0xd295, + 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd318, 0xd073, 0xd073, + 0xd32c, 0xd073, 0xd073, 0xd2e7, 0xd073, 0xd073, 0xd073, 0xd344, + 0xd073, 0xd073, 0xd073, 0xd3c1, 0xd073, 0xd073, 0xd073, 0xd073, + 0xd073, 0xd073, 0xd43e, 0x080c, 0x0d7d, 0x080c, 0x6a4c, 0x1150, + 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, + 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, + 0x0804, 0xd260, 0x080c, 0x69e8, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, + 0xa899, 0x080c, 0x93c6, 0x0076, 0x903e, 0x080c, 0x928f, 0x2c08, + 0x080c, 0xe038, 0x007e, 0x001e, 0x080c, 0xa8b5, 0x001e, 0x002e, + 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6653, 0xbe04, + 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, + 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xe6fd, 0x002e, + 0x001e, 0x1178, 0x080c, 0xdf66, 0x1904, 0xd147, 0x080c, 0xdf02, + 0x1120, 0x6007, 0x0008, 0x0804, 0xd260, 0x6007, 0x0009, 0x0804, + 0xd260, 0x080c, 0xe199, 0x0128, 0x080c, 0xdf66, 0x0d78, 0x0804, + 0xd147, 0x6017, 0x1900, 0x0c88, 0x080c, 0x3346, 0x1904, 0xd473, + 0x6106, 0x080c, 0xdeb3, 0x6007, 0x0006, 0x0804, 0xd260, 0x6007, + 0x0007, 0x0804, 0xd260, 0x080c, 0xe510, 0x1904, 0xd473, 0x080c, + 0x3346, 0x1904, 0xd473, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, + 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6580, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, + 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, + 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, + 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, + 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, + 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, 0x080c, 0xdfce, 0x1190, + 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, + 0x080c, 0x325e, 0x002e, 0x080c, 0x66df, 0x6007, 0x000a, 0x00de, + 0x0804, 0xd260, 0x6007, 0x000b, 0x00de, 0x0804, 0xd260, 0x080c, + 0x320f, 0x080c, 0xcf99, 0x6007, 0x0001, 0x0804, 0xd260, 0x080c, + 0xe510, 0x1904, 0xd473, 0x080c, 0x3346, 0x1904, 0xd473, 0x2071, + 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, + 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, + 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, + 0x325e, 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xe6dd, + 0x0804, 0xd260, 0x080c, 0x6a4c, 0x1140, 0x2001, 0x1837, 0x2004, + 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd082, 0x080c, + 0x69e8, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, + 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x65c0, 0x002e, + 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, + 0x0006, 0x1904, 0xd147, 0x080c, 0xdfdb, 0x1120, 0x6007, 0x000e, + 0x0804, 0xd260, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, + 0x320f, 0x080c, 0xcf99, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, + 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xe316, 0x6010, + 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, + 0x0804, 0xd260, 0x2001, 0x0001, 0x080c, 0x6580, 0x0156, 0x0016, + 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, + 0x080c, 0xbbc1, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, + 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xd147, 0x9682, + 0x0007, 0x0a04, 0xd1a3, 0x0804, 0xd147, 0x6017, 0x1900, 0x6007, + 0x0009, 0x0804, 0xd260, 0x080c, 0x6a4c, 0x1140, 0x2001, 0x1837, + 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd082, + 0x080c, 0x69e8, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, + 0x9086, 0x0001, 0x000e, 0x0170, 0x9082, 0x0006, 0x0698, 0x0150, + 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, + 0x1904, 0xd147, 0x080c, 0xe009, 0x1130, 0x080c, 0xdf02, 0x1118, + 0x6007, 0x0010, 0x04e8, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, + 0x080c, 0x320f, 0x080c, 0xcf99, 0x004e, 0x0016, 0x9006, 0x2009, + 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xe316, + 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, + 0x0001, 0x00f0, 0x080c, 0xe199, 0x0140, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x0978, 0x0804, 0xd147, 0x6017, 0x1900, 0x6007, + 0x0009, 0x0070, 0x080c, 0x3346, 0x1904, 0xd473, 0x080c, 0xe510, + 0x1904, 0xd473, 0x080c, 0xd640, 0x1904, 0xd147, 0x6007, 0x0012, + 0x6003, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, 0x6007, + 0x0001, 0x6003, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0cb0, + 0x6007, 0x0005, 0x0c68, 0x080c, 0xe510, 0x1904, 0xd473, 0x080c, + 0x3346, 0x1904, 0xd473, 0x080c, 0xd640, 0x1904, 0xd147, 0x6007, + 0x0020, 0x6003, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, + 0x080c, 0x3346, 0x1904, 0xd473, 0x6007, 0x0023, 0x6003, 0x0001, + 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, 0x080c, 0xe510, 0x1904, + 0xd473, 0x080c, 0x3346, 0x1904, 0xd473, 0x080c, 0xd640, 0x1904, + 0xd147, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, 0x9286, + 0xffff, 0x0180, 0x2c08, 0x080c, 0xc853, 0x01b0, 0x2260, 0x7240, + 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, + 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xe2e0, 0x1180, + 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, + 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, + 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, + 0x080c, 0xabf0, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, + 0x9240, 0x080c, 0x96bd, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, + 0x0001, 0x080c, 0x6580, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xbbc1, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xd260, + 0x080c, 0xb832, 0x080c, 0x74ec, 0x1190, 0x0006, 0x0026, 0x0036, + 0x080c, 0x7506, 0x1138, 0x080c, 0x77ef, 0x080c, 0x6044, 0x080c, + 0x741d, 0x0010, 0x080c, 0x74c0, 0x003e, 0x002e, 0x000e, 0x0005, + 0x080c, 0x3346, 0x1904, 0xd473, 0x080c, 0xd640, 0x1904, 0xd147, + 0x6106, 0x080c, 0xd65c, 0x1120, 0x6007, 0x002b, 0x0804, 0xd260, + 0x6007, 0x002c, 0x0804, 0xd260, 0x080c, 0xe510, 0x1904, 0xd473, + 0x080c, 0x3346, 0x1904, 0xd473, 0x080c, 0xd640, 0x1904, 0xd147, + 0x6106, 0x080c, 0xd661, 0x1120, 0x6007, 0x002e, 0x0804, 0xd260, + 0x6007, 0x002f, 0x0804, 0xd260, 0x080c, 0x3346, 0x1904, 0xd473, + 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, + 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, + 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xd267, 0x080c, 0x56f9, + 0xd0e4, 0x0904, 0xd3be, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, + 0x603e, 0x7108, 0x720c, 0x080c, 0x6a8a, 0x0140, 0x6010, 0x2058, + 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, 0x6a86, + 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, + 0x1578, 0x7210, 0x080c, 0xc853, 0x0590, 0x080c, 0xd52b, 0x0578, + 0x080c, 0xe392, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, + 0x2009, 0x8020, 0x080c, 0x9239, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xc853, 0x01c0, 0x9280, + 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, + 0x9085, 0x0001, 0x080c, 0xe2e0, 0x2c10, 0x2160, 0x0140, 0x0890, + 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, + 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, + 0x0868, 0x080c, 0x3346, 0x1904, 0xd473, 0x6010, 0x2058, 0xb804, + 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xd267, 0x00e6, + 0x00d6, 0x00c6, 0x080c, 0x56f9, 0xd0e4, 0x0904, 0xd436, 0x2069, + 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, + 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, + 0xe2e0, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xc853, 0x05d0, 0x7108, + 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, + 0x080c, 0xc446, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, + 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, + 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, 0xd52b, + 0x0904, 0xd3b7, 0x0056, 0x7510, 0x7614, 0x080c, 0xe3ab, 0x005e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, + 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, + 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, + 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, 0x0c10, 0x6007, 0x003b, + 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xd38e, 0x00e6, 0x0026, + 0x080c, 0x6a4c, 0x0550, 0x080c, 0x69e8, 0x080c, 0xe582, 0x1518, + 0x2071, 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, + 0x0100, 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, + 0x7280, 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, + 0x6a8a, 0x0120, 0x2011, 0x1a08, 0x2013, 0x07d0, 0xd0ac, 0x1128, + 0x080c, 0x2fe0, 0x0010, 0x080c, 0xe5b4, 0x002e, 0x00ee, 0x080c, + 0xabf0, 0x0804, 0xd266, 0x080c, 0xabf0, 0x0005, 0x2600, 0x0002, + 0xd48a, 0xd4bb, 0xd4cc, 0xd48a, 0xd48a, 0xd48c, 0xd4dd, 0xd48a, + 0xd48a, 0xd48a, 0xd4a9, 0xd48a, 0xd48a, 0xd48a, 0xd4e8, 0xd4f5, + 0xd526, 0xd48a, 0x080c, 0x0d7d, 0x080c, 0xe510, 0x1d20, 0x080c, + 0x3346, 0x1d08, 0x080c, 0xd640, 0x1148, 0x7038, 0x6016, 0x6007, + 0x0045, 0x6003, 0x0001, 0x080c, 0x9240, 0x0005, 0x080c, 0x320f, + 0x080c, 0xcf99, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9240, + 0x0005, 0x080c, 0xe510, 0x1938, 0x080c, 0x3346, 0x1920, 0x080c, + 0xd640, 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, + 0x080c, 0x9240, 0x0005, 0x080c, 0x3346, 0x1904, 0xd473, 0x2009, + 0x0041, 0x080c, 0xe5bd, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, + 0x9240, 0x080c, 0x96bd, 0x0005, 0x080c, 0x3346, 0x1904, 0xd473, + 0x2009, 0x0042, 0x080c, 0xe5bd, 0x6007, 0x0047, 0x6003, 0x0001, + 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, 0x080c, 0x3346, 0x1904, + 0xd473, 0x2009, 0x0046, 0x080c, 0xe5bd, 0x080c, 0xabf0, 0x0005, + 0x080c, 0xd548, 0x0904, 0xd473, 0x6007, 0x004e, 0x6003, 0x0001, + 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, 0x6007, 0x004f, 0x6017, + 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, + 0x1160, 0x7140, 0x2001, 0x19bc, 0x2004, 0x9106, 0x11b0, 0x7144, + 0x2001, 0x19bd, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, + 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, + 0x000a, 0x080c, 0xbbd5, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, + 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0005, 0x6007, 0x0050, + 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, + 0x00c6, 0x2260, 0x6010, 0x2058, 0xb8d4, 0xd084, 0x0150, 0x7128, + 0x6050, 0x9106, 0x1120, 0x712c, 0x604c, 0x9106, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, + 0x0016, 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1800, 0x7090, 0x908a, 0x00f9, 0x16e8, 0x20e1, + 0x0000, 0x2001, 0x199f, 0x2003, 0x0000, 0x080c, 0x1060, 0x05a0, + 0x2900, 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, + 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x001b, 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, 0x0471, 0x001e, + 0x2940, 0x080c, 0x1060, 0x01c0, 0x2900, 0xa006, 0x2100, 0x81ff, + 0x0180, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x001b, 0x20a0, 0x2001, 0x199f, 0x0016, 0x200c, 0x00b1, 0x001e, + 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x7093, 0x0000, + 0x6014, 0x2048, 0x080c, 0x0ff9, 0x9006, 0x012e, 0x01de, 0x01ce, + 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x918c, 0xffff, 0x11a8, 0x080c, 0x21b2, 0x2099, + 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, + 0x00f8, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x21b2, 0x2099, + 0x0260, 0x0ca8, 0x080c, 0x21b2, 0x2061, 0x199f, 0x6004, 0x2098, + 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, + 0x4003, 0x22a8, 0x8108, 0x080c, 0x21b2, 0x2099, 0x0260, 0x0ca8, + 0x2061, 0x199f, 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, + 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, + 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, + 0x080c, 0x21ca, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, + 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, + 0x22a8, 0x8108, 0x080c, 0x21ca, 0x20a1, 0x0240, 0x0c98, 0x080c, + 0x21ca, 0x2061, 0x19a2, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, + 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, + 0x22a8, 0x8108, 0x080c, 0x21ca, 0x20a1, 0x0240, 0x0c98, 0x2061, + 0x19a2, 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, + 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, + 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, + 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, + 0x0001, 0x006e, 0x00be, 0x0005, 0x00d6, 0x080c, 0xd6d6, 0x00de, + 0x0005, 0x00d6, 0x080c, 0xd6e3, 0x1520, 0x680c, 0x908c, 0xff00, + 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, + 0x0130, 0x9006, 0x080c, 0xe6dd, 0x2009, 0x0001, 0x0078, 0xd1ec, + 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x2630, 0x1148, + 0x2001, 0x0001, 0x080c, 0xe6dd, 0x2110, 0x900e, 0x080c, 0x325e, + 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, + 0x00c6, 0x080c, 0xac60, 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2630, 0x1568, 0x080c, + 0x65e3, 0x1550, 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, + 0x6012, 0x080c, 0xe510, 0x11c8, 0x080c, 0x3346, 0x11b0, 0x080c, + 0xd640, 0x0500, 0x2001, 0x0007, 0x080c, 0x6594, 0x2001, 0x0007, + 0x080c, 0x65c0, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x9240, 0x0010, 0x080c, 0xabf0, 0x9085, + 0x0001, 0x00ce, 0x00be, 0x0005, 0x080c, 0xabf0, 0x00ce, 0x002e, + 0x001e, 0x0ca8, 0x080c, 0xabf0, 0x9006, 0x0c98, 0x2069, 0x026d, + 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, + 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, + 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, + 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, + 0x910d, 0x6162, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, + 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0d7d, 0x91b6, 0x0013, 0x1130, + 0x2008, 0x91b2, 0x0040, 0x1a04, 0xd825, 0x0092, 0x91b6, 0x0027, + 0x0120, 0x91b6, 0x0014, 0x190c, 0x0d7d, 0x2001, 0x0007, 0x080c, + 0x65c0, 0x080c, 0x95ff, 0x080c, 0xac2b, 0x080c, 0x96bd, 0x0005, + 0xd760, 0xd762, 0xd760, 0xd760, 0xd760, 0xd762, 0xd76f, 0xd822, + 0xd7bf, 0xd822, 0xd7d3, 0xd822, 0xd76f, 0xd822, 0xd81a, 0xd822, + 0xd81a, 0xd822, 0xd822, 0xd760, 0xd760, 0xd760, 0xd760, 0xd760, + 0xd760, 0xd760, 0xd760, 0xd760, 0xd760, 0xd760, 0xd762, 0xd760, + 0xd822, 0xd760, 0xd760, 0xd822, 0xd760, 0xd81f, 0xd822, 0xd760, + 0xd760, 0xd760, 0xd760, 0xd822, 0xd822, 0xd760, 0xd822, 0xd822, + 0xd760, 0xd76a, 0xd760, 0xd760, 0xd760, 0xd760, 0xd81e, 0xd822, + 0xd760, 0xd760, 0xd822, 0xd822, 0xd760, 0xd760, 0xd760, 0xd760, + 0x080c, 0x0d7d, 0x080c, 0xcf9c, 0x6003, 0x0002, 0x080c, 0x96bd, + 0x0804, 0xd824, 0x9006, 0x080c, 0x6580, 0x0804, 0xd822, 0x080c, + 0x6a86, 0x1904, 0xd822, 0x9006, 0x080c, 0x6580, 0x6010, 0x2058, + 0xb810, 0x9086, 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, + 0x8000, 0x78aa, 0x00fe, 0x0428, 0x6010, 0x2058, 0xb884, 0x9005, + 0x1178, 0x080c, 0xcf84, 0x1904, 0xd822, 0x0036, 0x0046, 0xbba0, + 0x2021, 0x0007, 0x080c, 0x4ce0, 0x004e, 0x003e, 0x0804, 0xd822, + 0x080c, 0x3377, 0x1904, 0xd822, 0x2001, 0x1800, 0x2004, 0x9086, + 0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, + 0x00fe, 0x2001, 0x0002, 0x080c, 0x6594, 0x6023, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x9240, 0x080c, 0x96bd, 0x6110, + 0x2158, 0x2009, 0x0001, 0x080c, 0x865f, 0x0804, 0xd824, 0x6610, + 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, + 0xd822, 0x9686, 0x0004, 0x0904, 0xd822, 0x080c, 0x8ee5, 0x2001, + 0x0004, 0x0804, 0xd820, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, + 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, + 0x080c, 0x4ce0, 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xd83e, + 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, + 0x0006, 0x006e, 0x0168, 0x2001, 0x0006, 0x080c, 0x65c0, 0x9284, + 0x00ff, 0x908e, 0x0007, 0x1120, 0x2001, 0x0006, 0x080c, 0x6594, + 0x080c, 0x6a86, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01d0, + 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, 0x2079, + 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xd7a9, 0x2001, + 0x0004, 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, 0x0018, 0x0010, + 0x080c, 0x65c0, 0x080c, 0xabf0, 0x0005, 0x2600, 0x0002, 0xd839, + 0xd839, 0xd839, 0xd839, 0xd839, 0xd83b, 0xd839, 0xd83b, 0xd839, + 0xd839, 0xd83b, 0xd839, 0xd839, 0xd839, 0xd83b, 0xd83b, 0xd83b, + 0xd83b, 0x080c, 0x0d7d, 0x080c, 0xabf0, 0x0005, 0x0016, 0x00b6, + 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, 0x6594, + 0x9006, 0x080c, 0x6580, 0x080c, 0x323e, 0x00de, 0x00be, 0x001e, + 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, 0x90b2, + 0x000c, 0x1a0c, 0x0d7d, 0x91b6, 0x0015, 0x1110, 0x003b, 0x0028, + 0x91b6, 0x0016, 0x190c, 0x0d7d, 0x006b, 0x0005, 0xb6af, 0xb6af, + 0xb6af, 0xb6af, 0xd8d3, 0xb6af, 0xd8bd, 0xd87e, 0xb6af, 0xb6af, + 0xb6af, 0xb6af, 0xb6af, 0xb6af, 0xb6af, 0xb6af, 0xd8d3, 0xb6af, + 0xd8bd, 0xd8c4, 0xb6af, 0xb6af, 0xb6af, 0xb6af, 0x00f6, 0x080c, + 0x6a86, 0x11d8, 0x080c, 0xcf84, 0x11c0, 0x6010, 0x905d, 0x01a8, + 0xb884, 0x9005, 0x0190, 0x9006, 0x080c, 0x6580, 0x2001, 0x0002, + 0x080c, 0x6594, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x9240, 0x080c, 0x96bd, 0x00f0, 0x2011, 0x0263, 0x2204, + 0x8211, 0x220c, 0x080c, 0x2630, 0x11b0, 0x080c, 0x6644, 0x0118, + 0x080c, 0xabf0, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, 0xb884, + 0x0006, 0x080c, 0x605e, 0x000e, 0xb886, 0x000e, 0xb816, 0x000e, + 0xb812, 0x080c, 0xabf0, 0x00fe, 0x0005, 0x6604, 0x96b6, 0x001e, + 0x1110, 0x080c, 0xabf0, 0x0005, 0x080c, 0xba3a, 0x1148, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x9240, 0x080c, 0x96bd, 0x0010, + 0x080c, 0xabf0, 0x0005, 0x0804, 0xabf0, 0x6004, 0x908a, 0x0053, + 0x1a0c, 0x0d7d, 0x080c, 0x95ff, 0x080c, 0xac2b, 0x0005, 0x9182, + 0x0040, 0x0002, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f8, 0xd8f6, + 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, + 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0xd8f6, 0x080c, 0x0d7d, + 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, + 0x2258, 0xb8bc, 0x9005, 0x11b0, 0x6007, 0x0044, 0x2071, 0x0260, + 0x7444, 0x94a4, 0xff00, 0x0904, 0xd95f, 0x080c, 0xe6d1, 0x1170, + 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, + 0x8902, 0x0020, 0x9026, 0x080c, 0xe555, 0x0c30, 0x080c, 0x1047, + 0x090c, 0x0d7d, 0x6003, 0x0007, 0xa867, 0x010d, 0x9006, 0xa802, + 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, 0x6010, 0x2058, + 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, 0x0000, 0xa883, + 0x0000, 0xa887, 0x0036, 0x080c, 0x6d9f, 0x001e, 0x080c, 0xe6d1, + 0x1904, 0xd9bf, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, + 0xe286, 0x0804, 0xd9bf, 0x9486, 0x0200, 0x1120, 0x080c, 0xe216, + 0x0804, 0xd9bf, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, 0x1904, + 0xd9bf, 0x2019, 0x0002, 0x080c, 0xe235, 0x0804, 0xd9bf, 0x2069, + 0x1a6e, 0x6a00, 0xd284, 0x0904, 0xda29, 0x9284, 0x0300, 0x1904, + 0xda22, 0x6804, 0x9005, 0x0904, 0xda0a, 0x2d78, 0x6003, 0x0007, + 0x080c, 0x1060, 0x0904, 0xd9cb, 0x7800, 0xd08c, 0x1118, 0x7804, + 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, 0xd084, + 0x1904, 0xda2d, 0x9006, 0xa802, 0xa867, 0x0116, 0xa86a, 0x6008, + 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa9b6, + 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, 0xa9c2, 0xb934, + 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, 0xd9c7, + 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, 0xaa5c, 0x9290, + 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0xab60, + 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, + 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, 0x6da2, 0x002e, + 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, 0x0000, + 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, 0x0120, + 0x080c, 0x1047, 0x1904, 0xd974, 0x6017, 0xf100, 0x6003, 0x0001, + 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9239, 0x0c00, 0x2069, + 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, + 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, 0x6116, + 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x2009, 0xa025, 0x080c, + 0x9239, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0xf200, + 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9239, + 0x0804, 0xd9bf, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x4b29, 0x6017, 0xf300, 0x0010, 0x6017, 0xf100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9239, + 0x0804, 0xd9bf, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, 0x0804, + 0xd9df, 0x6017, 0xf200, 0x0804, 0xd9df, 0xa867, 0x0146, 0xa86b, + 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, 0x0003, + 0x9080, 0xd9c7, 0x2005, 0xa87e, 0x2928, 0x6010, 0x2058, 0xb8a0, + 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, 0xa892, 0xb834, + 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, 0x9085, 0x0080, + 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, 0x9294, 0x0fff, + 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d7d, 0x8210, 0x821c, 0x2001, + 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029, 0x20a0, + 0x2011, 0xdaa9, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, 0x9322, + 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, 0xd7fc, + 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, 0x2950, + 0x080c, 0x1060, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, 0xa86b, + 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x8840, + 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x1079, 0x0cc8, + 0x080c, 0x1079, 0x0804, 0xd9cb, 0x2548, 0x8847, 0x9885, 0x0046, + 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xe2b9, 0x0804, + 0xd9bf, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, + 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0057, + 0x1a0c, 0x0d7d, 0x9082, 0x0040, 0x0a0c, 0x0d7d, 0x2008, 0x0804, + 0xdb35, 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, 0xaaab, 0x01e8, + 0x9086, 0x0002, 0x0904, 0xdb7d, 0x00c0, 0x9186, 0x0027, 0x0180, + 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, 0x190c, 0x0d7d, + 0x080c, 0xaaab, 0x0150, 0x9086, 0x0004, 0x0904, 0xdc1c, 0x0028, + 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xacaa, 0x0005, + 0xdafc, 0xdafe, 0xdafe, 0xdb25, 0xdafc, 0xdafc, 0xdafc, 0xdafc, + 0xdafc, 0xdafc, 0xdafc, 0xdafc, 0xdafc, 0xdafc, 0xdafc, 0xdafc, + 0xdafc, 0xdafc, 0xdafc, 0xdafc, 0x080c, 0x0d7d, 0x080c, 0x95ff, + 0x080c, 0x96bd, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, + 0xc865, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, + 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xe2b9, 0x6017, + 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1986, 0x2004, 0x601a, + 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, 0x95ff, + 0x080c, 0x96bd, 0x080c, 0xc865, 0x0120, 0x6014, 0x2048, 0x080c, + 0x1079, 0x080c, 0xac2b, 0x009e, 0x0005, 0x0002, 0xdb4a, 0xdb5f, + 0xdb4c, 0xdb74, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, + 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, 0xdb4a, + 0xdb4a, 0xdb4a, 0x080c, 0x0d7d, 0x0096, 0x6014, 0x2048, 0xa87c, + 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0xac8d, + 0x0010, 0x6003, 0x0004, 0x080c, 0x96bd, 0x009e, 0x0005, 0x080c, + 0xc865, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, + 0x1138, 0x080c, 0x88d7, 0x080c, 0xabf0, 0x080c, 0x96bd, 0x0005, + 0x080c, 0xe519, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007, 0x0041, + 0x2009, 0xa022, 0x080c, 0x9239, 0x0005, 0x9182, 0x0040, 0x0002, + 0xdb94, 0xdb96, 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, + 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, 0xdb94, + 0xdb94, 0xdb97, 0xdb94, 0xdb94, 0x080c, 0x0d7d, 0x0005, 0x00d6, + 0x080c, 0x88d7, 0x00de, 0x080c, 0xe571, 0x080c, 0xabf0, 0x0005, + 0x9182, 0x0040, 0x0002, 0xdbb7, 0xdbb7, 0xdbb7, 0xdbb7, 0xdbb7, + 0xdbb7, 0xdbb7, 0xdbb7, 0xdbb7, 0xdbb9, 0xdbe4, 0xdbb7, 0xdbb7, + 0xdbb7, 0xdbb7, 0xdbe4, 0xdbb7, 0xdbb7, 0xdbb7, 0xdbb7, 0x080c, 0x0d7d, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x908c, 0x0003, 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168, 0x2009, - 0x0041, 0x009e, 0x0804, 0xdc6c, 0x6003, 0x0007, 0x601b, 0x0000, - 0x080c, 0x88a3, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, 0xd1ec, - 0x1130, 0x080c, 0x88a3, 0x080c, 0xabdf, 0x009e, 0x0005, 0x080c, - 0xe4dc, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, - 0x2102, 0x0036, 0x080c, 0x9621, 0x080c, 0x9684, 0x6014, 0x0096, + 0x0041, 0x009e, 0x0804, 0xdca4, 0x6003, 0x0007, 0x601b, 0x0000, + 0x080c, 0x88d7, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, 0xd1ec, + 0x1130, 0x080c, 0x88d7, 0x080c, 0xabf0, 0x009e, 0x0005, 0x080c, + 0xe519, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, + 0x2102, 0x0036, 0x080c, 0x965a, 0x080c, 0x96bd, 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, - 0x0080, 0x2019, 0x0004, 0x080c, 0xe27c, 0x6018, 0x9005, 0x1128, + 0x0080, 0x2019, 0x0004, 0x080c, 0xe2b9, 0x6018, 0x9005, 0x1128, 0x2001, 0x1986, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, - 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xdbfb, - 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfd, - 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, 0xdbfb, - 0xdbfb, 0xdbfb, 0xdc48, 0x080c, 0x0d7d, 0x6014, 0x0096, 0x2048, + 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xdc33, + 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc35, + 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, 0xdc33, + 0xdc33, 0xdc33, 0xdc80, 0x080c, 0x0d7d, 0x6014, 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, - 0x009e, 0x0804, 0xdc6c, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, - 0x88a3, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, + 0x009e, 0x0804, 0xdca4, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, + 0x88d7, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x00e9, - 0x080c, 0x88a5, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, - 0x6024, 0xd0f4, 0x0128, 0x080c, 0x167d, 0x1904, 0xdbfd, 0x0005, + 0x080c, 0x88d9, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, + 0x6024, 0xd0f4, 0x0128, 0x080c, 0x168a, 0x1904, 0xdc35, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, - 0x080c, 0x167d, 0x1904, 0xdbfd, 0x0005, 0xd2fc, 0x0140, 0x8002, + 0x080c, 0x168a, 0x1904, 0xdc35, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d7d, 0x6024, - 0xd0dc, 0x090c, 0x0d7d, 0x0005, 0xdc8f, 0xdc9b, 0xdca7, 0xdcb3, - 0xdc8f, 0xdc8f, 0xdc8f, 0xdc8f, 0xdc96, 0xdc91, 0xdc91, 0xdc8f, - 0xdc8f, 0xdc8f, 0xdc8f, 0xdc91, 0xdc8f, 0xdc91, 0xdc8f, 0x080c, - 0x0d7d, 0x6024, 0xd0dc, 0x090c, 0x0d7d, 0x0005, 0x6014, 0x9005, - 0x190c, 0x0d7d, 0x0005, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, - 0x8000, 0x2009, 0xa022, 0x080c, 0x91e2, 0x012e, 0x0005, 0x6003, - 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa001, 0x080c, - 0x9200, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x080c, 0x1c10, - 0x0126, 0x2091, 0x8000, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, - 0x0188, 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x6024, 0xd0cc, - 0x1148, 0xd0c4, 0x1138, 0xa8a8, 0x9005, 0x1120, 0x6144, 0x918d, - 0xb035, 0x0018, 0x6144, 0x918d, 0xa035, 0x009e, 0x080c, 0x9247, - 0x012e, 0x0005, 0x6144, 0x918d, 0xa032, 0x0cb8, 0x0126, 0x2091, - 0x8000, 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, - 0x012e, 0x0005, 0xdcfa, 0xdcfc, 0xdd11, 0xdd2b, 0xdcfa, 0xdcfa, - 0xdcfa, 0xdcfa, 0xdcfa, 0xdcfa, 0xdcfa, 0xdcfa, 0xdcfa, 0xdcfa, - 0xdcfa, 0xdcfa, 0x080c, 0x0d7d, 0x6014, 0x2048, 0xa87c, 0xd0fc, - 0x0510, 0x909c, 0x0003, 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x9200, - 0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x2009, 0xa001, - 0x080c, 0x9200, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, - 0x080c, 0xe27c, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, - 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, - 0x080c, 0x1c10, 0x6144, 0x918d, 0xa035, 0x080c, 0x9247, 0x0005, - 0x080c, 0x95c6, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, - 0xe631, 0x0036, 0x2019, 0x0029, 0x080c, 0xe27c, 0x003e, 0x009e, - 0x080c, 0xac1a, 0x080c, 0x9684, 0x0005, 0x080c, 0x9621, 0x6114, - 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xe631, 0x0036, 0x2019, - 0x0029, 0x080c, 0xe27c, 0x003e, 0x009e, 0x080c, 0xac1a, 0x0005, - 0x9182, 0x0085, 0x0002, 0xdd7a, 0xdd78, 0xdd78, 0xdd86, 0xdd78, - 0xdd78, 0xdd78, 0xdd78, 0xdd78, 0xdd78, 0xdd78, 0xdd78, 0xdd78, - 0x080c, 0x0d7d, 0x6003, 0x000b, 0x6106, 0x0126, 0x2091, 0x8000, - 0x2009, 0x8020, 0x080c, 0x9200, 0x012e, 0x0005, 0x0026, 0x00e6, - 0x080c, 0xe4d3, 0x0118, 0x080c, 0xabdf, 0x0440, 0x2071, 0x0260, - 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, - 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, - 0xaf0a, 0x7220, 0x080c, 0xe112, 0x0118, 0x6007, 0x0086, 0x0040, - 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x00ee, 0x002e, - 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, - 0x0d7d, 0x908a, 0x0092, 0x1a0c, 0x0d7d, 0x9082, 0x0085, 0x00a2, - 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0xac99, - 0x0050, 0x2001, 0x0007, 0x080c, 0x659c, 0x080c, 0x95c6, 0x080c, - 0xac1a, 0x080c, 0x9684, 0x0005, 0xdde9, 0xddeb, 0xddeb, 0xdde9, - 0xdde9, 0xdde9, 0xdde9, 0xdde9, 0xdde9, 0xdde9, 0xdde9, 0xdde9, - 0xdde9, 0x080c, 0x0d7d, 0x080c, 0xac1a, 0x080c, 0x9684, 0x0005, - 0x9182, 0x0085, 0x0a0c, 0x0d7d, 0x9182, 0x0092, 0x1a0c, 0x0d7d, - 0x9182, 0x0085, 0x0002, 0xde08, 0xde08, 0xde08, 0xde0a, 0xde08, - 0xde08, 0xde08, 0xde08, 0xde08, 0xde08, 0xde08, 0xde08, 0xde08, - 0x080c, 0x0d7d, 0x0005, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, - 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xac99, 0x0020, 0x080c, - 0x95c6, 0x080c, 0xac1a, 0x0005, 0x0036, 0x080c, 0xe534, 0x604b, - 0x0000, 0x2019, 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, - 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, 0x2001, 0x0382, - 0x2004, 0x9084, 0x0007, 0x0006, 0x9086, 0x0003, 0x0110, 0x080c, - 0xa888, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0xa1fa, 0x009e, - 0x008e, 0x1558, 0x0076, 0x2c38, 0x080c, 0xa2a5, 0x007e, 0x1528, - 0x6000, 0x9086, 0x0000, 0x0508, 0x6020, 0x9086, 0x0007, 0x01e8, - 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xe534, 0x080c, 0xcf69, - 0x080c, 0x1a77, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xc832, - 0x0110, 0x080c, 0xe27c, 0x009e, 0x9006, 0x6046, 0x6016, 0x080c, - 0xe534, 0x6023, 0x0007, 0x080c, 0xcf69, 0x000e, 0x9086, 0x0003, - 0x0110, 0x080c, 0xa8a4, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, - 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, - 0x2614, 0x15e8, 0x0016, 0x00c6, 0x080c, 0x6620, 0x15b0, 0x001e, - 0x00c6, 0x2160, 0x080c, 0xcf66, 0x00ce, 0x002e, 0x0026, 0x0016, - 0x080c, 0xa888, 0x2019, 0x0029, 0x080c, 0xa372, 0x080c, 0x938d, - 0x0076, 0x903e, 0x080c, 0x9256, 0x007e, 0x001e, 0x0076, 0x903e, - 0x080c, 0xdffb, 0x007e, 0x080c, 0xa8a4, 0x0026, 0xba04, 0x9294, - 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, - 0xbaa0, 0x080c, 0x32ba, 0x002e, 0xbc84, 0x001e, 0x080c, 0x603e, - 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, - 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, - 0x0016, 0x2009, 0x1824, 0x2104, 0x9086, 0x0074, 0x1904, 0xdf1e, - 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, - 0x8000, 0x0904, 0xdf1b, 0x2001, 0x197b, 0x2004, 0x9005, 0x1140, - 0x6010, 0x2058, 0xb884, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, - 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xe699, 0x0118, 0x6978, - 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, - 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, - 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, - 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, - 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, - 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, - 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, - 0x0005, 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, - 0xbb04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, - 0x0168, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, - 0x0004, 0x0120, 0x080c, 0x662f, 0x0804, 0xdf8a, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbb5, - 0x009e, 0x15c8, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xbbb5, 0x009e, 0x1568, 0x0046, 0x0016, - 0xbaa0, 0x2220, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, - 0x2009, 0x0029, 0x080c, 0xe2d9, 0xb800, 0xc0e5, 0xb802, 0x080c, - 0xa888, 0x2019, 0x0029, 0x080c, 0x938d, 0x0076, 0x2039, 0x0000, - 0x080c, 0x9256, 0x2c08, 0x080c, 0xdffb, 0x007e, 0x080c, 0xa8a4, - 0x2001, 0x0007, 0x080c, 0x659c, 0x2001, 0x0007, 0x080c, 0x6570, - 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, 0x00ce, - 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, 0x0118, - 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00f6, - 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, 0x7834, - 0x080c, 0x2614, 0x11d0, 0x080c, 0x6620, 0x11b8, 0x2011, 0x0270, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbb5, - 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xbbb5, 0x009e, 0x015e, 0x003e, 0x002e, - 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, 0x0026, - 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x2614, 0x11d0, 0x080c, 0x6620, 0x11b8, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbb5, 0x009e, - 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, - 0x0006, 0x080c, 0xbbb5, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, - 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x080c, 0xa8e6, - 0x0106, 0x190c, 0xa888, 0x2740, 0x2029, 0x19f2, 0x252c, 0x2021, - 0x19f9, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, - 0x81ff, 0x0150, 0x0006, 0x9186, 0x1b31, 0x000e, 0x0128, 0x8001, - 0x9602, 0x1a04, 0xe0a0, 0x0018, 0x9606, 0x0904, 0xe0a0, 0x080c, - 0x8b72, 0x0904, 0xe097, 0x2100, 0x9c06, 0x0904, 0xe097, 0x080c, - 0xe31a, 0x1904, 0xe097, 0x080c, 0xe6b6, 0x0904, 0xe097, 0x080c, - 0xe30a, 0x0904, 0xe097, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, - 0x3357, 0x0904, 0xe0e2, 0x6004, 0x9086, 0x0000, 0x1904, 0xe0e2, - 0x9786, 0x0004, 0x0904, 0xe0e2, 0x9786, 0x0007, 0x0904, 0xe097, - 0x2500, 0x9c06, 0x0904, 0xe097, 0x2400, 0x9c06, 0x0904, 0xe097, - 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, 0x0096, 0x6043, 0xffff, - 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a77, 0x001e, - 0x9786, 0x000a, 0x0148, 0x080c, 0xca47, 0x1130, 0x080c, 0xb5a6, - 0x009e, 0x080c, 0xac1a, 0x0418, 0x6014, 0x2048, 0x080c, 0xc832, - 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, 0x0103, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fec, 0x009e, 0xab7a, - 0xa877, 0x0000, 0x080c, 0xe631, 0x0016, 0x080c, 0xcb35, 0x080c, - 0x6d6f, 0x001e, 0x080c, 0xca21, 0x009e, 0x080c, 0xac1a, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe014, - 0x010e, 0x190c, 0xa8a4, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, - 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, - 0x9386, 0x0005, 0x0128, 0x080c, 0xe631, 0x080c, 0xe27c, 0x08e0, - 0x009e, 0x08e8, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, - 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x9621, 0x0096, - 0x6114, 0x2148, 0x080c, 0xc832, 0x0118, 0x6010, 0x080c, 0x6d7b, - 0x009e, 0x00c6, 0x080c, 0xabdf, 0x00ce, 0x0036, 0x080c, 0x9684, - 0x003e, 0x009e, 0x0804, 0xe097, 0x9786, 0x000a, 0x0904, 0xe07e, - 0x0804, 0xe07c, 0x81ff, 0x0904, 0xe097, 0x9180, 0x0001, 0x2004, - 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, - 0x1904, 0xe097, 0x6000, 0x9086, 0x0002, 0x1904, 0xe097, 0x080c, - 0xca36, 0x0138, 0x080c, 0xca47, 0x1904, 0xe097, 0x080c, 0xb5a6, - 0x0038, 0x080c, 0x321e, 0x080c, 0xca47, 0x1110, 0x080c, 0xb5a6, - 0x080c, 0xac1a, 0x0804, 0xe097, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, - 0x080c, 0xe2a3, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, - 0x00ee, 0x00ce, 0x0005, 0xe131, 0xe131, 0xe131, 0xe131, 0xe131, - 0xe131, 0xe133, 0xe131, 0xe131, 0xe131, 0xe131, 0xac1a, 0xac1a, - 0xe131, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, - 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xe2d9, - 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, 0xde2a, 0x003e, 0x9085, - 0x0001, 0x0005, 0x0096, 0x080c, 0xc832, 0x0140, 0x6014, 0x904d, - 0x080c, 0xc430, 0x687b, 0x0005, 0x080c, 0x6d7b, 0x009e, 0x080c, - 0xac1a, 0x9085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x655c, - 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0276, 0x080c, 0xbba1, 0x003e, 0x002e, 0x001e, 0x015e, - 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, - 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1ddc, 0x2079, - 0x0001, 0x8fff, 0x0904, 0xe1cc, 0x2071, 0x1800, 0x7654, 0x7074, - 0x8001, 0x9602, 0x1a04, 0xe1cc, 0x88ff, 0x0120, 0x2800, 0x9c06, - 0x1590, 0x2078, 0x080c, 0xe30a, 0x0570, 0x2400, 0x9c06, 0x0558, - 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, - 0x1140, 0x6010, 0x9b06, 0x11f8, 0x85ff, 0x0118, 0x605c, 0x9106, - 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xe534, 0x080c, - 0xcf69, 0x080c, 0x1a77, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, - 0xc832, 0x0120, 0x0046, 0x080c, 0xe27c, 0x004e, 0x009e, 0x080c, - 0xac1a, 0x88ff, 0x1198, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, - 0x9c02, 0x1210, 0x0804, 0xe181, 0x9006, 0x012e, 0x00be, 0x006e, - 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, - 0x0ca0, 0x080c, 0xa888, 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, - 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, - 0x904e, 0x080c, 0xa1fa, 0x009e, 0x008e, 0x903e, 0x080c, 0xa2a5, - 0x080c, 0xe172, 0x005e, 0x007e, 0x00be, 0x080c, 0xa8a4, 0x0005, - 0x080c, 0xa888, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, - 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, - 0x6620, 0x1190, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, - 0x0096, 0x904e, 0x080c, 0xa1fa, 0x009e, 0x008e, 0x903e, 0x080c, - 0xa2a5, 0x080c, 0xe172, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xe205, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, - 0xa8a4, 0x0005, 0x080c, 0xa888, 0x00b6, 0x0076, 0x0056, 0x6210, - 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0xa1fa, 0x009e, 0x008e, 0x903e, 0x080c, 0xa2a5, - 0x2c20, 0x080c, 0xe172, 0x005e, 0x007e, 0x00be, 0x080c, 0xa8a4, - 0x0005, 0x080c, 0xa888, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, - 0x6620, 0x11a0, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xe518, 0x004e, 0x0096, 0x904e, 0x080c, 0xa1fa, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa2a5, 0x080c, 0xe172, 0x003e, 0x001e, - 0x8108, 0x1f04, 0xe255, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, - 0x00be, 0x080c, 0xa8a4, 0x0005, 0x0016, 0x00f6, 0x080c, 0xc830, - 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, - 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, 0x6d7b, 0x2f48, - 0x0cb0, 0xab82, 0x080c, 0x6d7b, 0x00fe, 0x001e, 0x0005, 0xa800, - 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6d7b, 0x2f48, 0x0cb8, - 0x080c, 0x6d7b, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1ddc, - 0x9005, 0x1138, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, - 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, - 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, - 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x001c, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, - 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, - 0x0c30, 0x0096, 0x0006, 0x080c, 0x103a, 0x000e, 0x090c, 0x0d7d, - 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xc820, - 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0017, 0x2004, 0x002e, - 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, - 0xa87f, 0x0000, 0x2001, 0x198d, 0x2004, 0xa882, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d7b, 0x012e, - 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, - 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, - 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, - 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0005, 0x2001, 0x1986, 0x2004, 0x601a, 0x2009, 0x8020, 0x080c, - 0x9200, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, - 0x0158, 0xd0cc, 0x0118, 0x080c, 0xcb7c, 0x0030, 0x080c, 0xe534, - 0x080c, 0x88a3, 0x080c, 0xabdf, 0x0005, 0x9280, 0x0008, 0x2004, - 0x9084, 0x000f, 0x0002, 0xe369, 0xe369, 0xe369, 0xe36b, 0xe369, - 0xe36b, 0xe36b, 0xe369, 0xe36b, 0xe369, 0xe369, 0xe369, 0xe369, - 0xe369, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, - 0x2004, 0x9084, 0x000f, 0x0002, 0xe382, 0xe382, 0xe382, 0xe382, - 0xe382, 0xe382, 0xe38f, 0xe382, 0xe382, 0xe382, 0xe382, 0xe382, - 0xe382, 0xe382, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x0005, 0x0096, - 0x00c6, 0x2260, 0x080c, 0xe534, 0x604b, 0x0000, 0x6024, 0xc0f4, - 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, - 0x0007, 0x1904, 0xe3e8, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, - 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9200, 0x00c6, 0x2d60, 0x6100, - 0x9186, 0x0002, 0x1904, 0xe45f, 0x6014, 0x9005, 0x1138, 0x6000, - 0x9086, 0x0007, 0x190c, 0x0d7d, 0x0804, 0xe45f, 0x2048, 0x080c, - 0xc832, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, - 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, - 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, - 0x080c, 0xdc6c, 0x0804, 0xe45f, 0x2009, 0x0041, 0x0804, 0xe459, - 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, - 0x00de, 0x009e, 0x0804, 0xe382, 0xd0b4, 0x0128, 0xd0fc, 0x090c, - 0x0d7d, 0x0804, 0xe3a3, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, - 0x8020, 0x080c, 0x9200, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, - 0x0120, 0x9186, 0x0004, 0x1904, 0xe45f, 0x6814, 0x2048, 0xa97c, - 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, - 0x2c78, 0x080c, 0x173e, 0x00fe, 0x2009, 0x0042, 0x04d0, 0x0036, - 0x080c, 0x103a, 0x090c, 0x0d7d, 0xa867, 0x010d, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, - 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, - 0x2058, 0xb8a0, 0x00be, 0x2004, 0x635c, 0xab7a, 0xa876, 0x9006, - 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6d7b, - 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xde2a, 0x2d00, 0x600a, - 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x634a, 0x003e, - 0x0038, 0x604b, 0x0000, 0x6003, 0x0007, 0x080c, 0xdc6c, 0x00ce, - 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, - 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, 0x95c6, - 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, 0xe27c, - 0x009e, 0x003e, 0x080c, 0x9684, 0x0005, 0x9186, 0x0014, 0x0d70, - 0x080c, 0xac99, 0x0005, 0xe492, 0xe490, 0xe490, 0xe490, 0xe490, - 0xe490, 0xe492, 0xe490, 0xe490, 0xe490, 0xe490, 0xe490, 0xe490, - 0x080c, 0x0d7d, 0x6003, 0x000c, 0x080c, 0x9684, 0x0005, 0x9182, - 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x001a, 0x080c, 0xac99, - 0x0005, 0xe4ae, 0xe4ae, 0xe4ae, 0xe4ae, 0xe4b0, 0xe4d0, 0xe4ae, - 0xe4ae, 0xe4ae, 0xe4ae, 0xe4ae, 0xe4ae, 0xe4ae, 0x080c, 0x0d7d, - 0x00d6, 0x2c68, 0x080c, 0xab89, 0x01b0, 0x6003, 0x0001, 0x6007, - 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, 0x6023, 0x0004, 0x2009, - 0x8020, 0x080c, 0x9200, 0x2d60, 0x080c, 0xabdf, 0x00de, 0x0005, - 0x080c, 0xabdf, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, - 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, - 0x2001, 0x1987, 0x2004, 0x604a, 0x2009, 0x1867, 0x210c, 0xd1f4, - 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, - 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, 0x1987, 0x200c, 0x2001, - 0x1985, 0x2004, 0x9100, 0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, - 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, - 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, - 0x0016, 0x00c6, 0x00e6, 0x615c, 0xb8bc, 0x2060, 0x8cff, 0x0180, - 0x84ff, 0x1118, 0x605c, 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, - 0x88a3, 0x080c, 0xabdf, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, - 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, - 0xb8bc, 0x2068, 0x9005, 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, - 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, - 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, - 0x9636, 0x1508, 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, - 0x11d0, 0x2011, 0x0270, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, - 0x2019, 0x000a, 0x080c, 0xbbb5, 0x009e, 0x1168, 0x2011, 0x0274, - 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, - 0xbbb5, 0x009e, 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x5fb7, 0x080c, 0x2fc0, 0x00ee, 0x0005, - 0x0096, 0x0026, 0x080c, 0x103a, 0x090c, 0x0d7d, 0xa85c, 0x9080, - 0x001a, 0x20a0, 0x20a9, 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, - 0x9186, 0x0046, 0x1118, 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, - 0x9186, 0x0041, 0x0110, 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, - 0x7240, 0x9294, 0xff00, 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, - 0x1168, 0x7038, 0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, - 0xaa9e, 0x723c, 0x9294, 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, - 0x00ff, 0x7244, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, - 0x00ff, 0xaaa2, 0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, - 0x9e90, 0x001a, 0x2204, 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, - 0xa8aa, 0x8210, 0x2204, 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, - 0xa8b2, 0x8210, 0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, - 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, - 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, - 0x0205, 0x2013, 0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, - 0xa8b6, 0x8210, 0x2204, 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, - 0x0001, 0x2011, 0x0260, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, - 0x8007, 0xa8c2, 0x9186, 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, - 0x2011, 0x026a, 0x0146, 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, - 0x0008, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, - 0x8007, 0x4004, 0x8210, 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, - 0x2011, 0x0205, 0x2013, 0x0000, 0x002e, 0x080c, 0x6d7b, 0x009e, - 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, - 0x0108, 0x0011, 0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f2, 0x252c, 0x2021, - 0x19f9, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, - 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, - 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, - 0xe30a, 0x01b8, 0x080c, 0xe31a, 0x11a0, 0x6000, 0x9086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x1a77, 0x001e, 0x080c, 0xca36, 0x1110, - 0x080c, 0x321e, 0x080c, 0xca47, 0x1110, 0x080c, 0xb5a6, 0x080c, - 0xac1a, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, - 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, - 0x0005, 0x0006, 0x2001, 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, - 0x0006, 0x0036, 0x0046, 0x080c, 0xcf51, 0x0168, 0x2019, 0xffff, - 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0004, 0x080c, 0x4cc0, 0x004e, 0x003e, 0x000e, 0x6004, 0x9086, - 0x0001, 0x1128, 0x080c, 0xa372, 0x080c, 0xac1a, 0x9006, 0x0005, - 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, - 0x7454, 0x7074, 0x8001, 0x9402, 0x12b8, 0x2100, 0x9c06, 0x0148, - 0x6000, 0x9086, 0x0000, 0x0128, 0x6010, 0x2058, 0xb8a0, 0x9206, - 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, - 0x0c60, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be, 0x00ce, - 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, - 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, - 0x0118, 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, - 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, - 0x0005, 0x0118, 0x2071, 0xfffe, 0x0089, 0x001e, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, - 0xfff6, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, - 0x2077, 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, - 0x2071, 0xfff4, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff8, - 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, - 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, - 0x8000, 0x9d27 + 0xd0dc, 0x090c, 0x0d7d, 0x0005, 0xdcc8, 0xdcd4, 0xdce0, 0xdcec, + 0xdcc8, 0xdcc8, 0xdcc8, 0xdcc8, 0xdccf, 0xdcca, 0xdcca, 0xdcc8, + 0xdcc8, 0xdcc8, 0xdcc8, 0xdcca, 0xdcc8, 0xdcca, 0xdcc8, 0xdccf, + 0x080c, 0x0d7d, 0x6024, 0xd0dc, 0x090c, 0x0d7d, 0x0005, 0x6014, + 0x9005, 0x190c, 0x0d7d, 0x0005, 0x6003, 0x0001, 0x6106, 0x0126, + 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x921b, 0x012e, 0x0005, + 0x6003, 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa001, + 0x080c, 0x9239, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x080c, + 0x1c28, 0x0126, 0x2091, 0x8000, 0x6014, 0x0096, 0x2048, 0xa87c, + 0xd0fc, 0x0188, 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x6024, + 0xd0cc, 0x1148, 0xd0c4, 0x1138, 0xa8a8, 0x9005, 0x1120, 0x6144, + 0x918d, 0xb035, 0x0018, 0x6144, 0x918d, 0xa035, 0x009e, 0x080c, + 0x9280, 0x012e, 0x0005, 0x6144, 0x918d, 0xa032, 0x0cb8, 0x0126, + 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, + 0x003e, 0x012e, 0x0005, 0xdd37, 0xdd39, 0xdd4e, 0xdd68, 0xdd37, + 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, + 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0xdd37, 0x080c, + 0x0d7d, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0510, 0x909c, 0x0003, + 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, + 0x8000, 0x2009, 0xa022, 0x080c, 0x9239, 0x0470, 0x6014, 0x2048, + 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, + 0x6003, 0x0001, 0x6106, 0x2009, 0xa001, 0x080c, 0x9239, 0x00e0, + 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xe2b9, 0x00a0, + 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, + 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x080c, 0x1c28, 0x6144, + 0x918d, 0xa035, 0x080c, 0x9280, 0x0005, 0x080c, 0x95ff, 0x6114, + 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xe66e, 0x0036, 0x2019, + 0x0029, 0x080c, 0xe2b9, 0x003e, 0x009e, 0x080c, 0xac2b, 0x080c, + 0x96bd, 0x0005, 0x080c, 0x965a, 0x6114, 0x81ff, 0x0158, 0x0096, + 0x2148, 0x080c, 0xe66e, 0x0036, 0x2019, 0x0029, 0x080c, 0xe2b9, + 0x003e, 0x009e, 0x080c, 0xac2b, 0x0005, 0x9182, 0x0085, 0x0002, + 0xddb7, 0xddb5, 0xddb5, 0xddc3, 0xddb5, 0xddb5, 0xddb5, 0xddb5, + 0xddb5, 0xddb5, 0xddb5, 0xddb5, 0xddb5, 0x080c, 0x0d7d, 0x6003, + 0x000b, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, + 0x9239, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xe510, 0x0118, + 0x080c, 0xabf0, 0x0440, 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, + 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, + 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xaf1b, 0x7220, 0x080c, + 0xe14f, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, + 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x2009, + 0x8020, 0x080c, 0x9239, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, + 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d7d, 0x908a, 0x0092, + 0x1a0c, 0x0d7d, 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, + 0x9186, 0x0014, 0x0118, 0x080c, 0xacaa, 0x0050, 0x2001, 0x0007, + 0x080c, 0x65c0, 0x080c, 0x95ff, 0x080c, 0xac2b, 0x080c, 0x96bd, + 0x0005, 0xde26, 0xde28, 0xde28, 0xde26, 0xde26, 0xde26, 0xde26, + 0xde26, 0xde26, 0xde26, 0xde26, 0xde26, 0xde26, 0x080c, 0x0d7d, + 0x080c, 0xac2b, 0x080c, 0x96bd, 0x0005, 0x9182, 0x0085, 0x0a0c, + 0x0d7d, 0x9182, 0x0092, 0x1a0c, 0x0d7d, 0x9182, 0x0085, 0x0002, + 0xde45, 0xde45, 0xde45, 0xde47, 0xde45, 0xde45, 0xde45, 0xde45, + 0xde45, 0xde45, 0xde45, 0xde45, 0xde45, 0x080c, 0x0d7d, 0x0005, + 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, + 0x0118, 0x080c, 0xacaa, 0x0020, 0x080c, 0x95ff, 0x080c, 0xac2b, + 0x0005, 0x0036, 0x080c, 0xe571, 0x604b, 0x0000, 0x2019, 0x000b, + 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, + 0x0036, 0x2091, 0x8000, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x0006, 0x9086, 0x0003, 0x0110, 0x080c, 0xa899, 0x0086, 0x2c40, + 0x0096, 0x904e, 0x080c, 0xa207, 0x009e, 0x008e, 0x1558, 0x0076, + 0x2c38, 0x080c, 0xa2b2, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, + 0x0508, 0x6020, 0x9086, 0x0007, 0x01e8, 0x0096, 0x601c, 0xd084, + 0x0140, 0x080c, 0xe571, 0x080c, 0xcf9c, 0x080c, 0x1a94, 0x6023, + 0x0007, 0x6014, 0x2048, 0x080c, 0xc865, 0x0110, 0x080c, 0xe2b9, + 0x009e, 0x9006, 0x6046, 0x6016, 0x080c, 0xe571, 0x6023, 0x0007, + 0x080c, 0xcf9c, 0x000e, 0x9086, 0x0003, 0x0110, 0x080c, 0xa8b5, + 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, + 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, 0x2630, 0x15e8, 0x0016, + 0x00c6, 0x080c, 0x6644, 0x15b0, 0x001e, 0x00c6, 0x2160, 0x080c, + 0xcf99, 0x00ce, 0x002e, 0x0026, 0x0016, 0x080c, 0xa899, 0x2019, + 0x0029, 0x080c, 0xa37f, 0x080c, 0x93c6, 0x0076, 0x903e, 0x080c, + 0x928f, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, 0xe038, 0x007e, + 0x080c, 0xa8b5, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, + 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, 0x32da, + 0x002e, 0xbc84, 0x001e, 0x080c, 0x605e, 0xbe12, 0xbd16, 0xbc86, + 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, + 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, + 0x2104, 0x9086, 0x0074, 0x1904, 0xdf5b, 0x2069, 0x0260, 0x6944, + 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, 0xdf58, + 0x2001, 0x197b, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb884, + 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, + 0x0648, 0x080c, 0xe6d6, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, + 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, + 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, + 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, + 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, + 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, + 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, + 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, + 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, + 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, + 0x6653, 0x0804, 0xdfc7, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, + 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbd5, 0x009e, 0x15c8, 0x2011, + 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, + 0xbbd5, 0x009e, 0x1568, 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, + 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, + 0xe316, 0xb800, 0xc0e5, 0xb802, 0x080c, 0xa899, 0x2019, 0x0029, + 0x080c, 0x93c6, 0x0076, 0x2039, 0x0000, 0x080c, 0x928f, 0x2c08, + 0x080c, 0xe038, 0x007e, 0x080c, 0xa8b5, 0x2001, 0x0007, 0x080c, + 0x65c0, 0x2001, 0x0007, 0x080c, 0x6594, 0x001e, 0x004e, 0x9006, + 0x015e, 0x003e, 0x002e, 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, + 0x026e, 0x6800, 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, + 0x9006, 0x00de, 0x0005, 0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, + 0x0156, 0x2079, 0x026c, 0x7930, 0x7834, 0x080c, 0x2630, 0x11d0, + 0x080c, 0x6644, 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, + 0x2b48, 0x2019, 0x000a, 0x080c, 0xbbd5, 0x009e, 0x1158, 0x2011, + 0x0274, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, + 0xbbd5, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, + 0x0005, 0x00b6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2630, 0x11d0, 0x080c, + 0x6644, 0x11b8, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, + 0x2019, 0x000a, 0x080c, 0xbbd5, 0x009e, 0x1158, 0x2011, 0x027a, + 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xbbd5, + 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, + 0x0126, 0x2091, 0x8000, 0x080c, 0xa8f7, 0x0106, 0x190c, 0xa899, + 0x2740, 0x2029, 0x19f2, 0x252c, 0x2021, 0x19f9, 0x2424, 0x2061, + 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, + 0x9186, 0x1b31, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xe0dd, + 0x0018, 0x9606, 0x0904, 0xe0dd, 0x080c, 0x8ba9, 0x0904, 0xe0d4, + 0x2100, 0x9c06, 0x0904, 0xe0d4, 0x080c, 0xe357, 0x1904, 0xe0d4, + 0x080c, 0xe6f3, 0x0904, 0xe0d4, 0x080c, 0xe347, 0x0904, 0xe0d4, + 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x3377, 0x0904, 0xe11f, + 0x6004, 0x9086, 0x0000, 0x1904, 0xe11f, 0x9786, 0x0004, 0x0904, + 0xe11f, 0x9786, 0x0007, 0x0904, 0xe0d4, 0x2500, 0x9c06, 0x0904, + 0xe0d4, 0x2400, 0x9c06, 0x0904, 0xe0d4, 0x88ff, 0x0118, 0x605c, + 0x9906, 0x15d0, 0x0096, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, + 0x1120, 0x0016, 0x080c, 0x1a94, 0x001e, 0x9786, 0x000a, 0x0148, + 0x080c, 0xca7a, 0x1130, 0x080c, 0xb5c6, 0x009e, 0x080c, 0xac2b, + 0x0418, 0x6014, 0x2048, 0x080c, 0xc865, 0x01d8, 0x9786, 0x0003, + 0x1588, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, + 0x2048, 0x080c, 0x0ff9, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, + 0xe66e, 0x0016, 0x080c, 0xcb68, 0x080c, 0x6d93, 0x001e, 0x080c, + 0xca54, 0x009e, 0x080c, 0xac2b, 0x9ce0, 0x001c, 0x2001, 0x181a, + 0x2004, 0x9c02, 0x1210, 0x0804, 0xe051, 0x010e, 0x190c, 0xa8b5, + 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, + 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, + 0x080c, 0xe66e, 0x080c, 0xe2b9, 0x08e0, 0x009e, 0x08e8, 0x9786, + 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, 0x9086, + 0x0003, 0x11a0, 0x080c, 0x965a, 0x0096, 0x6114, 0x2148, 0x080c, + 0xc865, 0x0118, 0x6010, 0x080c, 0x6d9f, 0x009e, 0x00c6, 0x080c, + 0xabf0, 0x00ce, 0x0036, 0x080c, 0x96bd, 0x003e, 0x009e, 0x0804, + 0xe0d4, 0x9786, 0x000a, 0x0904, 0xe0bb, 0x0804, 0xe0b9, 0x81ff, + 0x0904, 0xe0d4, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, + 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904, 0xe0d4, 0x6000, + 0x9086, 0x0002, 0x1904, 0xe0d4, 0x080c, 0xca69, 0x0138, 0x080c, + 0xca7a, 0x1904, 0xe0d4, 0x080c, 0xb5c6, 0x0038, 0x080c, 0x323e, + 0x080c, 0xca7a, 0x1110, 0x080c, 0xb5c6, 0x080c, 0xac2b, 0x0804, + 0xe0d4, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, + 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, 0xe2e0, 0x001e, + 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, + 0xe16e, 0xe16e, 0xe16e, 0xe16e, 0xe16e, 0xe16e, 0xe170, 0xe16e, + 0xe16e, 0xe16e, 0xe16e, 0xac2b, 0xac2b, 0xe16e, 0x9006, 0x0005, + 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, + 0x2c00, 0x2009, 0x0020, 0x080c, 0xe316, 0x001e, 0x004e, 0x2019, + 0x0002, 0x080c, 0xde67, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, + 0x080c, 0xc865, 0x0140, 0x6014, 0x904d, 0x080c, 0xc453, 0x687b, + 0x0005, 0x080c, 0x6d9f, 0x009e, 0x080c, 0xac2b, 0x9085, 0x0001, + 0x0005, 0x2001, 0x0001, 0x080c, 0x6580, 0x0156, 0x0016, 0x0026, + 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, + 0xbbc1, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, + 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, + 0x8000, 0x2740, 0x2061, 0x1ddc, 0x2079, 0x0001, 0x8fff, 0x0904, + 0xe209, 0x2071, 0x1800, 0x7654, 0x7074, 0x8001, 0x9602, 0x1a04, + 0xe209, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, + 0xe347, 0x0570, 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, + 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, 0x9b06, + 0x11f8, 0x85ff, 0x0118, 0x605c, 0x9106, 0x11d0, 0x0096, 0x601c, + 0xd084, 0x0140, 0x080c, 0xe571, 0x080c, 0xcf9c, 0x080c, 0x1a94, + 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xc865, 0x0120, 0x0046, + 0x080c, 0xe2b9, 0x004e, 0x009e, 0x080c, 0xac2b, 0x88ff, 0x1198, + 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, + 0xe1be, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, + 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0xa899, + 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, + 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa207, + 0x009e, 0x008e, 0x903e, 0x080c, 0xa2b2, 0x080c, 0xe1af, 0x005e, + 0x007e, 0x00be, 0x080c, 0xa8b5, 0x0005, 0x080c, 0xa899, 0x00b6, + 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x6644, 0x1190, 0x0056, + 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, + 0xa207, 0x009e, 0x008e, 0x903e, 0x080c, 0xa2b2, 0x080c, 0xe1af, + 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xe242, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xa8b5, 0x0005, 0x080c, + 0xa899, 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, + 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, 0xa207, + 0x009e, 0x008e, 0x903e, 0x080c, 0xa2b2, 0x2c20, 0x080c, 0xe1af, + 0x005e, 0x007e, 0x00be, 0x080c, 0xa8b5, 0x0005, 0x080c, 0xa899, + 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, 0x6644, 0x11a0, 0x0086, + 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xe555, 0x004e, + 0x0096, 0x904e, 0x080c, 0xa207, 0x009e, 0x008e, 0x903e, 0x080c, + 0xa2b2, 0x080c, 0xe1af, 0x003e, 0x001e, 0x8108, 0x1f04, 0xe292, + 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xa8b5, + 0x0005, 0x0016, 0x00f6, 0x080c, 0xc863, 0x0198, 0xa864, 0x9084, + 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, + 0x0000, 0xab82, 0x080c, 0x6d9f, 0x2f48, 0x0cb0, 0xab82, 0x080c, + 0x6d9f, 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, + 0x0000, 0x080c, 0x6d9f, 0x2f48, 0x0cb8, 0x080c, 0x6d9f, 0x0c88, + 0x00e6, 0x0046, 0x0036, 0x2061, 0x1ddc, 0x9005, 0x1138, 0x2071, + 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, 0x12f8, 0x2100, 0x9c06, + 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, 0x6008, 0x9206, 0x1150, + 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, 0x91a0, 0x0004, 0x2424, + 0x9406, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, + 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, + 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, 0x0006, + 0x080c, 0x1047, 0x000e, 0x090c, 0x0d7d, 0xaae2, 0xa867, 0x010d, + 0xa88e, 0x0026, 0x2010, 0x080c, 0xc853, 0x2001, 0x0000, 0x0120, + 0x2200, 0x9080, 0x0017, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, + 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, + 0x198d, 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x6d9f, 0x012e, 0x009e, 0x0005, 0x6700, + 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, + 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, + 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, + 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, + 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1986, + 0x2004, 0x601a, 0x2009, 0x8020, 0x080c, 0x9239, 0x001e, 0x0005, + 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, + 0x080c, 0xcbaf, 0x0030, 0x080c, 0xe571, 0x080c, 0x88d7, 0x080c, + 0xabf0, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, + 0xe3a6, 0xe3a6, 0xe3a6, 0xe3a8, 0xe3a6, 0xe3a8, 0xe3a8, 0xe3a6, + 0xe3a8, 0xe3a6, 0xe3a6, 0xe3a6, 0xe3a6, 0xe3a6, 0x9006, 0x0005, + 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, + 0x0002, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3cc, + 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0xe3bf, 0x6007, + 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, + 0x8020, 0x080c, 0x9239, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, + 0xe571, 0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, + 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xe425, + 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, + 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, + 0x080c, 0x9239, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, + 0xe49c, 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, + 0x0d7d, 0x0804, 0xe49c, 0x2048, 0x080c, 0xc865, 0x1130, 0x0028, + 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, + 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, + 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xdca4, 0x0804, + 0xe49c, 0x2009, 0x0041, 0x0804, 0xe496, 0x9186, 0x0005, 0x15a0, + 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, + 0xe3bf, 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d7d, 0x0804, 0xe3e0, + 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9239, + 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, + 0x1904, 0xe49c, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, + 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x174b, + 0x00fe, 0x2009, 0x0042, 0x04d0, 0x0036, 0x080c, 0x1047, 0x090c, + 0x0d7d, 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, + 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, + 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, + 0x2004, 0x635c, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, + 0xae96, 0xa89f, 0x0001, 0x080c, 0x6d9f, 0x2019, 0x0045, 0x6008, + 0x2068, 0x080c, 0xde67, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, + 0x0007, 0x901e, 0x631a, 0x634a, 0x003e, 0x0038, 0x604b, 0x0000, + 0x6003, 0x0007, 0x080c, 0xdca4, 0x00ce, 0x00de, 0x009e, 0x0005, + 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, + 0x9186, 0x0027, 0x1178, 0x080c, 0x95ff, 0x0036, 0x0096, 0x6014, + 0x2048, 0x2019, 0x0004, 0x080c, 0xe2b9, 0x009e, 0x003e, 0x080c, + 0x96bd, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xacaa, 0x0005, + 0xe4cf, 0xe4cd, 0xe4cd, 0xe4cd, 0xe4cd, 0xe4cd, 0xe4cf, 0xe4cd, + 0xe4cd, 0xe4cd, 0xe4cd, 0xe4cd, 0xe4cd, 0x080c, 0x0d7d, 0x6003, + 0x000c, 0x080c, 0x96bd, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, + 0x0085, 0x0208, 0x001a, 0x080c, 0xacaa, 0x0005, 0xe4eb, 0xe4eb, + 0xe4eb, 0xe4eb, 0xe4ed, 0xe50d, 0xe4eb, 0xe4eb, 0xe4eb, 0xe4eb, + 0xe4eb, 0xe4eb, 0xe4eb, 0x080c, 0x0d7d, 0x00d6, 0x2c68, 0x080c, + 0xab9a, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, + 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, + 0x6910, 0x6112, 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x9239, + 0x2d60, 0x080c, 0xabf0, 0x00de, 0x0005, 0x080c, 0xabf0, 0x0005, + 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, + 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, + 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1987, 0x2004, + 0x604a, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, + 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, + 0x00d8, 0x2001, 0x1987, 0x200c, 0x2001, 0x1985, 0x2004, 0x9100, + 0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, + 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, + 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, + 0x615c, 0xb8bc, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x605c, + 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x88d7, 0x080c, 0xabf0, + 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, + 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x2068, 0x9005, + 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, + 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, + 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x1508, 0x8318, + 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, + 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, + 0xbbd5, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, + 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xbbd5, 0x009e, 0x1100, + 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x5fd7, 0x080c, 0x2fe0, 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, + 0x1047, 0x090c, 0x0d7d, 0xa85c, 0x9080, 0x001a, 0x20a0, 0x20a9, + 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, 0x1118, + 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, 0x0110, + 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, + 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, + 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, 0x9294, + 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, + 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, 0x9186, + 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, + 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, 0x2204, + 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, 0x9186, + 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, 0x8210, + 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, 0x8210, + 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, + 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, + 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, + 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x9186, + 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, 0x0146, + 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, 0x8210, + 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, 0x2013, + 0x0000, 0x002e, 0x080c, 0x6d9f, 0x009e, 0x0005, 0x00e6, 0x6010, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, + 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, + 0x8000, 0x2029, 0x19f2, 0x252c, 0x2021, 0x19f9, 0x2424, 0x2061, + 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, + 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, + 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xe347, 0x01b8, 0x080c, + 0xe357, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, + 0x1a94, 0x001e, 0x080c, 0xca69, 0x1110, 0x080c, 0x323e, 0x080c, + 0xca7a, 0x1110, 0x080c, 0xb5c6, 0x080c, 0xac2b, 0x9ce0, 0x001c, + 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, + 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, + 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, + 0x080c, 0xcf84, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, + 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4ce0, + 0x004e, 0x003e, 0x000e, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, + 0xa37f, 0x080c, 0xac2b, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, + 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, + 0x9402, 0x12b8, 0x2100, 0x9c06, 0x0148, 0x6000, 0x9086, 0x0000, + 0x0128, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x0140, 0x9ce0, 0x001c, + 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c60, 0x9085, 0x0001, + 0x0008, 0x9006, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x0126, + 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, + 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000, + 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, + 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, + 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, + 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, 0x0021, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70, + 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, 0xffec, 0x0c99, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, 0x00ee, 0x0005, + 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7014, + 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0001, 0x0002, + 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, + 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x97f5 }; #ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_length01 = 0xdf52; +unsigned short fw2322ipx_length01 = 0xdf8f; #else -unsigned short risc_code_length01 = 0xdf52; +unsigned short risc_code_length01 = 0xdf8f; #endif /* @@ -7689,7 +7696,7 @@ unsigned short xseqipx_code01[] = { 0x0002, 0x1f43, 0x001b, 0x1261, 0x0001, 0xff88, 0x0000, 0x0002, 0x0003, 0x0263, 0x0001, 0xff88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x8266, 0x0000, 0xb0ff, - 0x0011, 0x16a0, 0x0000, 0xff16, 0x000b, 0x24e2, 0x0002, 0xb100, + 0x0011, 0x16a0, 0x0000, 0xff16, 0x001b, 0x226d, 0x0002, 0xb100, 0x0013, 0x026e, 0x0010, 0xb1ff, 0x0001, 0x17a0, 0x0010, 0xff17, 0x0013, 0x022c, 0x0000, 0x16ff, 0x0001, 0x18a0, 0x0010, 0xff00, 0x000b, 0x2278, 0x0002, 0x1700, 0x0003, 0x12cb, 0x0013, 0x0279, @@ -8073,6 +8080,6 @@ unsigned short xseqipx_code01[] = { 0x000b, 0x885c, 0x0012, 0x1027, 0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8864, 0x0015, 0x00b8, 0x0000, 0x0007, 0x0003, 0x4867, - 0x0000, 0xb838, 0x0017, 0x4000, 0xa317, 0x2238 + 0x0000, 0xb838, 0x0017, 0x4000, 0xa307, 0x24ad }; unsigned short xseqipx_code_length01 = 0x10d6; diff --git a/drivers/scsi/qla2xxx/ql6312.c b/drivers/scsi/qla2xxx/ql6312.c index 6c0720da8..c6b08a6e2 100644 --- a/drivers/scsi/qla2xxx/ql6312.c +++ b/drivers/scsi/qla2xxx/ql6312.c @@ -87,3 +87,4 @@ module_exit(qla6312_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP6312 FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql6312_fw.c b/drivers/scsi/qla2xxx/ql6312_fw.c index 407bfa9f5..717b1f3d5 100644 --- a/drivers/scsi/qla2xxx/ql6312_fw.c +++ b/drivers/scsi/qla2xxx/ql6312_fw.c @@ -18,25 +18,25 @@ *************************************************************************/ /* - * Firmware Version 3.02.30 (07:52 Jun 16, 2004) + * Firmware Version 3.03.02 (16:50 Aug 10, 2004) */ #ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_version = 3*1024+2; +unsigned short fw2300flx_version = 3*1024+3; #else -unsigned short risc_code_version = 3*1024+2; +unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2300flx_version_str[] = {3, 2,30}; +unsigned char fw2300flx_version_str[] = {3, 3, 2}; #else -unsigned char firmware_version[] = {3, 2,30}; +unsigned char firmware_version[] = {3, 3, 2}; #endif #ifdef UNIQUE_FW_NAME -#define fw2300flx_VERSION_STRING "3.02.30" +#define fw2300flx_VERSION_STRING "3.03.02" #else -#define FW_VERSION_STRING "3.02.30" +#define FW_VERSION_STRING "3.03.02" #endif #ifdef UNIQUE_FW_NAME @@ -50,12 +50,12 @@ unsigned short fw2300flx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xd5bb, 0x0000, 0x0003, 0x0002, 0x001e, + 0x0470, 0x0000, 0x0000, 0xd5d4, 0x0000, 0x0003, 0x0003, 0x0002, 0x0317, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3032, 0x2e33, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x332e, 0x3033, 0x2e30, 0x3220, 0x2020, 0x2020, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, @@ -64,171 +64,171 @@ unsigned short risc_code01[] = { 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1bff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2b50, 0x2051, 0x1800, 0x2a70, 0x20e1, + 0x7883, 0x0004, 0x2089, 0x2b5b, 0x2051, 0x1800, 0x2a70, 0x20e1, 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e2f, 0x2029, 0x2480, 0x2031, 0xffff, 0x2039, 0x2450, 0x2021, 0x0050, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x0cc0, 0x9084, 0x0fff, 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, 0x4104, 0x8001, 0x1de0, 0x756a, 0x766e, 0x7766, 0x7472, 0x7476, - 0x00e6, 0x2071, 0x1a97, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x716c, + 0x00e6, 0x2071, 0x1a9f, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x716c, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x716c, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x0f03, 0x080c, - 0x5ce8, 0x080c, 0x9dd8, 0x080c, 0x10ba, 0x080c, 0x129f, 0x080c, - 0x1a55, 0x080c, 0x0d46, 0x080c, 0x103f, 0x080c, 0x323a, 0x080c, - 0x7293, 0x080c, 0x6626, 0x080c, 0x7f5c, 0x080c, 0x230c, 0x080c, - 0x8289, 0x080c, 0x791c, 0x080c, 0x2149, 0x080c, 0x227d, 0x080c, - 0x2301, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x091d, 0x7880, + 0x5cf3, 0x080c, 0x9dc5, 0x080c, 0x10ba, 0x080c, 0x129f, 0x080c, + 0x1a60, 0x080c, 0x0d46, 0x080c, 0x103f, 0x080c, 0x3245, 0x080c, + 0x72a0, 0x080c, 0x6635, 0x080c, 0x7f7a, 0x080c, 0x2317, 0x080c, + 0x82a7, 0x080c, 0x792a, 0x080c, 0x2154, 0x080c, 0x2288, 0x080c, + 0x230c, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x091d, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0911, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2071, 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, 0x1168, 0x080c, - 0x49ae, 0x080c, 0x3261, 0x080c, 0x7304, 0x080c, 0x6ad6, 0x080c, - 0x7f85, 0x080c, 0x2aba, 0x0c68, 0x000b, 0x0c88, 0x0940, 0x0941, + 0x49b9, 0x080c, 0x326c, 0x080c, 0x7311, 0x080c, 0x6ae5, 0x080c, + 0x7fa3, 0x080c, 0x2ac5, 0x0c68, 0x000b, 0x0c88, 0x0940, 0x0941, 0x0ad8, 0x093e, 0x0b8f, 0x0d45, 0x0d45, 0x0d45, 0x080c, 0x0db4, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, 0x0001, - 0x1904, 0x0aab, 0x080c, 0x0e71, 0x080c, 0x6f9b, 0x0150, 0x080c, - 0x6fbe, 0x15a0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, - 0x0468, 0x080c, 0x6ecd, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aab, - 0x7094, 0x9086, 0x0028, 0x1904, 0x0aab, 0x080c, 0x7f54, 0x080c, - 0x7f46, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, - 0xffff, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x6e1c, 0x080c, - 0x8021, 0x2011, 0x6e0f, 0x080c, 0x80f5, 0x2011, 0x5b43, 0x080c, - 0x8021, 0x2011, 0x8030, 0x901e, 0x7392, 0x04d0, 0x080c, 0x53f0, - 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, 0x0aab, 0x2011, 0x5b43, - 0x080c, 0x8021, 0x2011, 0x6e1c, 0x080c, 0x8021, 0x2011, 0x6e0f, - 0x080c, 0x80f5, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, - 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, 0x1976, 0x2004, 0x9005, - 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, 0x5c90, 0x00ce, 0x0804, - 0x0aab, 0x780f, 0x006b, 0x7a28, 0x080c, 0x6fa3, 0x0118, 0x9295, + 0x1904, 0x0aab, 0x080c, 0x0e71, 0x080c, 0x6faa, 0x0150, 0x080c, + 0x6fcd, 0x15a0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, 0x782a, + 0x0468, 0x080c, 0x6edc, 0x7000, 0x9086, 0x0001, 0x1904, 0x0aab, + 0x7094, 0x9086, 0x0028, 0x1904, 0x0aab, 0x080c, 0x7f72, 0x080c, + 0x7f64, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, + 0xffff, 0x7a28, 0x9295, 0x5e2f, 0x7a2a, 0x2011, 0x6e2b, 0x080c, + 0x803f, 0x2011, 0x6e1e, 0x080c, 0x8113, 0x2011, 0x5b4e, 0x080c, + 0x803f, 0x2011, 0x8030, 0x901e, 0x7392, 0x04d0, 0x080c, 0x53fb, + 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, 0x0aab, 0x2011, 0x5b4e, + 0x080c, 0x803f, 0x2011, 0x6e2b, 0x080c, 0x803f, 0x2011, 0x6e1e, + 0x080c, 0x8113, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, + 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, 0x197e, 0x2004, 0x9005, + 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, 0x5c9b, 0x00ce, 0x0804, + 0x0aab, 0x780f, 0x006b, 0x7a28, 0x080c, 0x6fb2, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, 0x7a2a, 0x2011, 0x8010, 0x73d4, - 0x2001, 0x1977, 0x2003, 0x0001, 0x080c, 0x2980, 0x080c, 0x48e9, + 0x2001, 0x197f, 0x2003, 0x0001, 0x080c, 0x298b, 0x080c, 0x48f4, 0x7244, 0xc284, 0x7246, 0x2001, 0x180c, 0x200c, 0xc1ac, 0xc1cc, - 0x2102, 0x080c, 0x9640, 0x2011, 0x0004, 0x080c, 0xbb3c, 0x080c, - 0x646a, 0x080c, 0x6f9b, 0x1120, 0x080c, 0x29c4, 0x02e0, 0x0400, - 0x080c, 0x5c97, 0x0140, 0x7093, 0x0001, 0x70cf, 0x0000, 0x080c, - 0x55bd, 0x0804, 0x0aab, 0x080c, 0x538f, 0xd094, 0x0188, 0x2011, - 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x5393, 0xd0d4, 0x1118, - 0x080c, 0x29c4, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x0088, - 0x080c, 0x5393, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x0040, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6563, - 0x0008, 0x2012, 0x080c, 0x6529, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707b, 0x0000, 0x080c, 0x6f9b, 0x1130, 0x70ac, 0x9005, - 0x1168, 0x080c, 0xbf7d, 0x0050, 0x080c, 0xbf7d, 0x70d8, 0xd09c, - 0x1128, 0x70ac, 0x9005, 0x0110, 0x080c, 0x5c6d, 0x70e3, 0x0000, - 0x70df, 0x0000, 0x70a3, 0x0000, 0x080c, 0x29cc, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72d8, 0x080c, 0x6f9b, 0x1178, - 0x9016, 0x0016, 0x2009, 0x0002, 0x2019, 0x193d, 0x211a, 0x001e, + 0x2102, 0x080c, 0x9650, 0x2011, 0x0004, 0x080c, 0xbb4b, 0x080c, + 0x6479, 0x080c, 0x6faa, 0x1120, 0x080c, 0x29cf, 0x02e0, 0x0400, + 0x080c, 0x5ca2, 0x0140, 0x7093, 0x0001, 0x70cf, 0x0000, 0x080c, + 0x55c8, 0x0804, 0x0aab, 0x080c, 0x539a, 0xd094, 0x0188, 0x2011, + 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x539e, 0xd0d4, 0x1118, + 0x080c, 0x29cf, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x0088, + 0x080c, 0x539e, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, + 0x0040, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6572, + 0x0008, 0x2012, 0x080c, 0x6538, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, + 0x00a8, 0x707b, 0x0000, 0x080c, 0x6faa, 0x1130, 0x70ac, 0x9005, + 0x1168, 0x080c, 0xbf8c, 0x0050, 0x080c, 0xbf8c, 0x70d8, 0xd09c, + 0x1128, 0x70ac, 0x9005, 0x0110, 0x080c, 0x5c78, 0x70e3, 0x0000, + 0x70df, 0x0000, 0x70a3, 0x0000, 0x080c, 0x29d7, 0x0228, 0x2011, + 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72d8, 0x080c, 0x6faa, 0x1178, + 0x9016, 0x0016, 0x2009, 0x0002, 0x2019, 0x1945, 0x211a, 0x001e, 0x705b, 0xffff, 0x705f, 0x00ef, 0x707f, 0x0000, 0x0020, 0x2019, - 0x193d, 0x201b, 0x0000, 0x2079, 0x1853, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72da, 0x080c, 0x6f9b, 0x0118, 0x9296, 0x0004, 0x0548, - 0x2011, 0x0001, 0x080c, 0xbb3c, 0x70a7, 0x0000, 0x70ab, 0xffff, + 0x1945, 0x201b, 0x0000, 0x2079, 0x185b, 0x7804, 0xd0ac, 0x0108, + 0xc295, 0x72da, 0x080c, 0x6faa, 0x0118, 0x9296, 0x0004, 0x0548, + 0x2011, 0x0001, 0x080c, 0xbb4b, 0x70a7, 0x0000, 0x70ab, 0xffff, 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, - 0x0003, 0x782a, 0x00fe, 0x080c, 0x2dbd, 0x2011, 0x0005, 0x080c, - 0x9772, 0x080c, 0x896d, 0x080c, 0x6f9b, 0x0148, 0x00c6, 0x2061, + 0x0003, 0x782a, 0x00fe, 0x080c, 0x2dc8, 0x2011, 0x0005, 0x080c, + 0x975b, 0x080c, 0x898b, 0x080c, 0x6faa, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, 0x70a7, 0x0000, 0x70ab, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, - 0x00fe, 0x2011, 0x0005, 0x080c, 0x9772, 0x080c, 0x896d, 0x080c, - 0x6f9b, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, + 0x00fe, 0x2011, 0x0005, 0x080c, 0x975b, 0x080c, 0x898b, 0x080c, + 0x6faa, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, - 0x080c, 0x6f9b, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, - 0x080c, 0x6f9b, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, + 0x080c, 0x6faa, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, + 0x080c, 0x6faa, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, - 0x090c, 0x30d7, 0x8108, 0x1f04, 0x0abf, 0x707b, 0x0000, 0x707c, + 0x090c, 0x30e2, 0x8108, 0x1f04, 0x0abf, 0x707b, 0x0000, 0x707c, 0x9084, 0x00ff, 0x707e, 0x70af, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, - 0x0b8c, 0x70a8, 0x9086, 0xffff, 0x0130, 0x080c, 0x2dbd, 0x080c, - 0x896d, 0x0804, 0x0b8c, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0540, + 0x0b8c, 0x70a8, 0x9086, 0xffff, 0x0130, 0x080c, 0x2dc8, 0x080c, + 0x898b, 0x0804, 0x0b8c, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, - 0xd08c, 0x01f0, 0x70dc, 0x9086, 0xffff, 0x01b0, 0x080c, 0x2f48, - 0x080c, 0x896d, 0x70d8, 0xd094, 0x1904, 0x0b8c, 0x2011, 0x0001, - 0x080c, 0xc22c, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2f82, - 0x080c, 0x896d, 0x0804, 0x0b8c, 0x70e0, 0x9005, 0x1904, 0x0b8c, + 0xd08c, 0x01f0, 0x70dc, 0x9086, 0xffff, 0x01b0, 0x080c, 0x2f53, + 0x080c, 0x898b, 0x70d8, 0xd094, 0x1904, 0x0b8c, 0x2011, 0x0001, + 0x080c, 0xc23b, 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2f8d, + 0x080c, 0x898b, 0x0804, 0x0b8c, 0x70e0, 0x9005, 0x1904, 0x0b8c, 0x70a4, 0x9005, 0x1904, 0x0b8c, 0x70d8, 0xd0a4, 0x0118, 0xd0b4, - 0x0904, 0x0b8c, 0x080c, 0x6529, 0x1904, 0x0b8c, 0x080c, 0x657c, - 0x1904, 0x0b8c, 0x080c, 0x6563, 0x01c0, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x6247, 0x1118, 0xb800, 0xd0ec, + 0x0904, 0x0b8c, 0x080c, 0x6538, 0x1904, 0x0b8c, 0x080c, 0x658b, + 0x1904, 0x0b8c, 0x080c, 0x6572, 0x01c0, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x6256, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b32, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b8c, 0x0006, 0x2001, 0x0103, - 0x2003, 0x006b, 0x000e, 0x2011, 0x1983, 0x080c, 0x0f73, 0x2011, - 0x199d, 0x080c, 0x0f73, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, - 0x70ab, 0xffff, 0x080c, 0x0e53, 0x9006, 0x080c, 0x260e, 0x0036, - 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4a86, 0x004e, - 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x6fbe, 0x0150, 0x080c, - 0x6f9b, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, - 0x782a, 0x00fe, 0x2001, 0x19b8, 0x2004, 0x9086, 0x0005, 0x1120, - 0x2011, 0x0000, 0x080c, 0x9772, 0x2011, 0x0000, 0x080c, 0x977c, - 0x080c, 0x896d, 0x080c, 0x8a4a, 0x012e, 0x00be, 0x0005, 0x0016, + 0x2003, 0x006b, 0x000e, 0x2011, 0x198b, 0x080c, 0x0f73, 0x2011, + 0x19a5, 0x080c, 0x0f73, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, + 0x70ab, 0xffff, 0x080c, 0x0e53, 0x9006, 0x080c, 0x2619, 0x0036, + 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4a91, 0x004e, + 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x6fcd, 0x0150, 0x080c, + 0x6faa, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, + 0x782a, 0x00fe, 0x2001, 0x19c0, 0x2004, 0x9086, 0x0005, 0x1120, + 0x2011, 0x0000, 0x080c, 0x975b, 0x2011, 0x0000, 0x080c, 0x9765, + 0x080c, 0x898b, 0x080c, 0x8a68, 0x012e, 0x00be, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, - 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x5c56, 0x7940, + 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x5c61, 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, - 0xd1ac, 0x1904, 0x0c1c, 0x2001, 0x1977, 0x2004, 0x9005, 0x1518, - 0x080c, 0x2a47, 0x1148, 0x2001, 0x0001, 0x080c, 0x29af, 0x2001, - 0x0001, 0x080c, 0x2992, 0x00b8, 0x080c, 0x2a4f, 0x1138, 0x9006, - 0x080c, 0x29af, 0x9006, 0x080c, 0x2992, 0x0068, 0x080c, 0x2a57, - 0x1d50, 0x2001, 0x1968, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, - 0x27a9, 0x0804, 0x0cfc, 0x080c, 0x6fac, 0x0148, 0x080c, 0x6fbe, - 0x1118, 0x080c, 0x728e, 0x0050, 0x080c, 0x6fa3, 0x0dd0, 0x080c, - 0x7289, 0x080c, 0x727f, 0x080c, 0x6ecd, 0x0058, 0x080c, 0x6f9b, - 0x0140, 0x2009, 0x00f8, 0x080c, 0x5c56, 0x7843, 0x0090, 0x7843, - 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x6f9b, + 0xd1ac, 0x1904, 0x0c1c, 0x2001, 0x197f, 0x2004, 0x9005, 0x1518, + 0x080c, 0x2a52, 0x1148, 0x2001, 0x0001, 0x080c, 0x29ba, 0x2001, + 0x0001, 0x080c, 0x299d, 0x00b8, 0x080c, 0x2a5a, 0x1138, 0x9006, + 0x080c, 0x29ba, 0x9006, 0x080c, 0x299d, 0x0068, 0x080c, 0x2a62, + 0x1d50, 0x2001, 0x1970, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, + 0x27b4, 0x0804, 0x0cfc, 0x080c, 0x6fbb, 0x0148, 0x080c, 0x6fcd, + 0x1118, 0x080c, 0x729b, 0x0050, 0x080c, 0x6fb2, 0x0dd0, 0x080c, + 0x7296, 0x080c, 0x728c, 0x080c, 0x6edc, 0x0058, 0x080c, 0x6faa, + 0x0140, 0x2009, 0x00f8, 0x080c, 0x5c61, 0x7843, 0x0090, 0x7843, + 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x6faa, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d01, 0x1f04, 0x0bfb, 0x0070, - 0x7824, 0x080c, 0x6fb5, 0x0118, 0xd0ac, 0x1904, 0x0d01, 0x9084, + 0x7824, 0x080c, 0x6fc4, 0x0118, 0xd0ac, 0x1904, 0x0d01, 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d01, 0x2001, 0x0001, - 0x080c, 0x260e, 0x0804, 0x0d14, 0x2001, 0x1977, 0x2004, 0x9005, - 0x1518, 0x080c, 0x2a47, 0x1148, 0x2001, 0x0001, 0x080c, 0x29af, - 0x2001, 0x0001, 0x080c, 0x2992, 0x00b8, 0x080c, 0x2a4f, 0x1138, - 0x9006, 0x080c, 0x29af, 0x9006, 0x080c, 0x2992, 0x0068, 0x080c, - 0x2a57, 0x1d50, 0x2001, 0x1968, 0x2004, 0xd0fc, 0x0108, 0x0020, - 0x080c, 0x27a9, 0x0804, 0x0cfc, 0x7850, 0x9085, 0x0040, 0x7852, - 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2a5f, 0x9085, + 0x080c, 0x2619, 0x0804, 0x0d14, 0x2001, 0x197f, 0x2004, 0x9005, + 0x1518, 0x080c, 0x2a52, 0x1148, 0x2001, 0x0001, 0x080c, 0x29ba, + 0x2001, 0x0001, 0x080c, 0x299d, 0x00b8, 0x080c, 0x2a5a, 0x1138, + 0x9006, 0x080c, 0x29ba, 0x9006, 0x080c, 0x299d, 0x0068, 0x080c, + 0x2a62, 0x1d50, 0x2001, 0x1970, 0x2004, 0xd0fc, 0x0108, 0x0020, + 0x080c, 0x27b4, 0x0804, 0x0cfc, 0x7850, 0x9085, 0x0040, 0x7852, + 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2a6a, 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c55, 0x080c, - 0x80d5, 0x1f04, 0x0c55, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, - 0x7852, 0x793a, 0x080c, 0x6fac, 0x0148, 0x080c, 0x6fbe, 0x1118, - 0x080c, 0x728e, 0x0050, 0x080c, 0x6fa3, 0x0dd0, 0x080c, 0x7289, - 0x080c, 0x727f, 0x080c, 0x6ecd, 0x0020, 0x2009, 0x00f8, 0x080c, - 0x5c56, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c7b, 0x7850, 0x9085, - 0x1400, 0x7852, 0x080c, 0x6f9b, 0x0120, 0x7843, 0x0090, 0x7843, - 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x80d5, 0x7820, - 0xd09c, 0x1588, 0x080c, 0x6f9b, 0x0904, 0x0ce1, 0x7824, 0xd0ac, - 0x1904, 0x0d01, 0x080c, 0x6fbe, 0x1530, 0x0046, 0x2021, 0x0320, - 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2a5f, 0x7824, + 0x80f3, 0x1f04, 0x0c55, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, + 0x7852, 0x793a, 0x080c, 0x6fbb, 0x0148, 0x080c, 0x6fcd, 0x1118, + 0x080c, 0x729b, 0x0050, 0x080c, 0x6fb2, 0x0dd0, 0x080c, 0x7296, + 0x080c, 0x728c, 0x080c, 0x6edc, 0x0020, 0x2009, 0x00f8, 0x080c, + 0x5c61, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c7b, 0x7850, 0x9085, + 0x1400, 0x7852, 0x080c, 0x6faa, 0x0120, 0x7843, 0x0090, 0x7843, + 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x80f3, 0x7820, + 0xd09c, 0x1588, 0x080c, 0x6faa, 0x0904, 0x0ce1, 0x7824, 0xd0ac, + 0x1904, 0x0d01, 0x080c, 0x6fcd, 0x1530, 0x0046, 0x2021, 0x0320, + 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2a6a, 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0d22, 0x8421, 0x1158, - 0x1d04, 0x0cbc, 0x080c, 0x80d5, 0x080c, 0x7289, 0x080c, 0x727f, + 0x1d04, 0x0cbc, 0x080c, 0x80f3, 0x080c, 0x7296, 0x080c, 0x728c, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1940, 0x1d04, 0x0cc9, 0x080c, - 0x80d5, 0x2009, 0x196b, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, + 0x80f3, 0x2009, 0x1973, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, 0x080c, - 0x2a40, 0x7924, 0x080c, 0x2a5f, 0xd19c, 0x0110, 0x080c, 0x2980, - 0x00d8, 0x080c, 0x6fac, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, - 0x6f73, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2a5f, - 0x7824, 0x080c, 0x6fb5, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, - 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x260e, + 0x2a4b, 0x7924, 0x080c, 0x2a6a, 0xd19c, 0x0110, 0x080c, 0x298b, + 0x00d8, 0x080c, 0x6fbb, 0x1140, 0x94a2, 0x03e8, 0x1128, 0x080c, + 0x6f82, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, 0x2a6a, + 0x7824, 0x080c, 0x6fc4, 0x0110, 0xd0ac, 0x1158, 0x9084, 0x1800, + 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x2619, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, 0x782a, - 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x1977, 0x2003, 0x0000, + 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x197f, 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, 0x80d5, 0x015e, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, 0x80f3, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x001e, - 0x000e, 0x0005, 0x00e6, 0x2071, 0x1894, 0x7004, 0x9086, 0x0001, - 0x1110, 0x080c, 0x3261, 0x00ee, 0x0005, 0x0005, 0x2a70, 0x2061, - 0x197b, 0x2063, 0x0003, 0x6007, 0x0002, 0x600b, 0x001e, 0x600f, - 0x0317, 0x2001, 0x194c, 0x900e, 0x2102, 0x7192, 0x2001, 0x0100, + 0x000e, 0x0005, 0x00e6, 0x2071, 0x189c, 0x7004, 0x9086, 0x0001, + 0x1110, 0x080c, 0x326c, 0x00ee, 0x0005, 0x0005, 0x2a70, 0x2061, + 0x1983, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0002, 0x600f, + 0x0317, 0x2001, 0x1954, 0x900e, 0x2102, 0x7192, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705b, 0xffff, 0x0008, 0x715a, - 0x7063, 0xffff, 0x717a, 0x717e, 0x080c, 0xbf7d, 0x70e7, 0x00c0, - 0x2061, 0x193c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, + 0x7063, 0xffff, 0x717a, 0x717e, 0x080c, 0xbf8c, 0x70e7, 0x00c0, + 0x2061, 0x1944, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, 0x601f, 0x07d0, - 0x2061, 0x1944, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, - 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, 0x1959, + 0x2061, 0x194c, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, + 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, 0x1961, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, - 0x2001, 0x182b, 0x2102, 0x0005, 0x9016, 0x080c, 0x6247, 0x1178, + 0x2001, 0x182b, 0x2102, 0x0005, 0x9016, 0x080c, 0x6256, 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, 0x2079, @@ -236,18 +236,18 @@ unsigned short risc_code01[] = { 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, 0x00d6, - 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x1a71, 0x7a08, 0x226a, - 0x2069, 0x1a72, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, 0x782c, - 0x2019, 0x1a7f, 0x201a, 0x2019, 0x1a82, 0x9016, 0x7808, 0xd09c, - 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x1a97, 0x0108, - 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x1a80, - 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x1a51, + 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x1a79, 0x7a08, 0x226a, + 0x2069, 0x1a7a, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, 0x782c, + 0x2019, 0x1a87, 0x201a, 0x2019, 0x1a8a, 0x9016, 0x7808, 0xd09c, + 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x1a9f, 0x0108, + 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, 0x1a88, + 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, 0x1a59, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0e03, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x0180, 0x2001, 0x19e9, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, + 0x0180, 0x2001, 0x19f1, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, - 0x1001, 0x080c, 0x539e, 0x1108, 0x0099, 0x0cd8, 0x0005, 0x918c, + 0x1001, 0x080c, 0x53a9, 0x1108, 0x0099, 0x0cd8, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x2800, 0x0010, 0x918d, 0x2000, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, 0x0ecb, 0x20a9, 0x0900, @@ -258,9 +258,9 @@ unsigned short risc_code01[] = { 0x70eb, 0x0000, 0x1128, 0x70eb, 0x0fa0, 0x080c, 0x0edd, 0x002e, 0x0005, 0x0026, 0x080c, 0x0ed8, 0x0128, 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, 0x0edd, 0x002e, 0x0005, - 0x0026, 0x70eb, 0x0000, 0x080c, 0x0ed8, 0x1148, 0x080c, 0x2a57, + 0x0026, 0x70eb, 0x0000, 0x080c, 0x0ed8, 0x1148, 0x080c, 0x2a62, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, 0x8282, 0x0040, 0x080c, - 0x2a57, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, + 0x2a62, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, 0x0edd, 0x002e, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1800, 0xd0b4, 0x70e4, 0x1110, 0xc0e4, 0x0048, 0x0006, 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x70eb, 0x0000, 0xc0e5, 0x0079, 0x000e, 0x00ee, @@ -275,11 +275,11 @@ unsigned short risc_code01[] = { 0x1f04, 0x0eec, 0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, - 0x1883, 0x600b, 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, + 0x188b, 0x600b, 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, - 0x0400, 0x0c98, 0x000e, 0x200f, 0x2001, 0x1893, 0x928a, 0x000e, + 0x0400, 0x0c98, 0x000e, 0x200f, 0x2001, 0x189b, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, @@ -301,7 +301,7 @@ unsigned short risc_code01[] = { 0x0158, 0x8210, 0x9906, 0x090c, 0x0db4, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0db4, 0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1906, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, + 0x8000, 0x2071, 0x190e, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0db4, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, 0x70be, 0x702c, 0x2048, 0x9085, @@ -313,36 +313,36 @@ unsigned short risc_code01[] = { 0x8000, 0x0016, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x080c, 0x7f46, 0x012e, 0x00ee, 0x0005, 0x2071, + 0x8000, 0x70be, 0x080c, 0x7f64, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, - 0x0440, 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x1883, + 0x0440, 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188b, 0x7000, 0x9005, 0x11a0, 0x2001, 0x0492, 0xa802, 0x2048, 0x2009, 0x2480, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, - 0x1883, 0x7104, 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, + 0x188b, 0x7104, 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74ba, 0x74be, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, 0x9982, 0x0492, 0x0288, 0x9982, - 0x0800, 0x1270, 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x1883, + 0x0800, 0x1270, 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x188b, 0x7010, 0x9902, 0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, - 0x9006, 0x0cd8, 0x00e6, 0x2071, 0x19e8, 0x7007, 0x0000, 0x9006, + 0x9006, 0x0cd8, 0x00e6, 0x2071, 0x19f0, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x10ce, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, - 0x00e6, 0xa06f, 0x0000, 0x2071, 0x19e8, 0x701c, 0x9088, 0x19f2, + 0x00e6, 0xa06f, 0x0000, 0x2071, 0x19f0, 0x701c, 0x9088, 0x19fa, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, 0x0db4, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, - 0x2071, 0x19e8, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, + 0x2071, 0x19f0, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1117, 0x1115, 0x1115, 0x1115, 0x128e, 0x128e, 0x128e, 0x128e, 0x080c, 0x0db4, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, - 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x19f2, 0x2004, + 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x19fa, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868, 0x009e, @@ -355,8 +355,8 @@ unsigned short risc_code01[] = { 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x2009, - 0x19e8, 0x2104, 0xc095, 0x200a, 0x080c, 0x10f4, 0x0005, 0x0016, - 0x00e6, 0x2071, 0x19e8, 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, + 0x19f0, 0x2104, 0xc095, 0x200a, 0x080c, 0x10f4, 0x0005, 0x0016, + 0x00e6, 0x2071, 0x19f0, 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, 0x190c, 0x0dad, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1105, 0x11ad, 0x11e1, 0x0db4, 0x0db4, 0x129a, 0x0db4, 0x918c, 0x0700, 0x1550, @@ -371,39 +371,39 @@ unsigned short risc_code01[] = { 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x0096, - 0x00d6, 0x7008, 0x2048, 0x2001, 0x18af, 0x2004, 0x9906, 0x1128, + 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b7, 0x2004, 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x10f4, 0x0005, 0x00de, 0x009e, 0x080c, 0x10f4, 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0db4, 0xa06c, 0x908e, 0x0100, 0x0130, - 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, 0x6884, + 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, 0x6893, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x101d, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0db4, 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x10d5, 0x00e8, 0xa97c, - 0xa894, 0x0016, 0x0006, 0x080c, 0x6884, 0x000e, 0x001e, 0xd1fc, - 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0x9e42, 0x00ce, + 0xa894, 0x0016, 0x0006, 0x080c, 0x6893, 0x000e, 0x001e, 0xd1fc, + 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0x9e2f, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, 0x101d, 0x7007, 0x0000, 0x080c, 0x10f4, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x7007, 0x0000, 0x080c, 0x1105, 0x0005, 0x0126, - 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x1a32, 0x7003, 0x0000, + 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x1a3a, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b, 0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, - 0x0000, 0x20a9, 0x0254, 0x2061, 0xd904, 0x2c0d, 0x7912, 0xe104, + 0x0000, 0x20a9, 0x0254, 0x2061, 0xd91d, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, 0x1f04, 0x12b5, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, - 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, 0x2001, 0x1a33, 0x2003, + 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, 0x2001, 0x1a3b, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, - 0x782b, 0x1a51, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, - 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a51, 0x602f, + 0x782b, 0x1a59, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, + 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a59, 0x602f, 0x1cd0, 0x2001, 0x1819, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, - 0x1f28, 0x2001, 0x313a, 0xd0fc, 0x190c, 0x0db4, 0x2001, 0x0003, - 0x2004, 0xd0d4, 0x1118, 0x783f, 0x313a, 0x0020, 0x9084, 0xc000, - 0x783f, 0xb13a, 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, + 0x1f33, 0x2001, 0x3145, 0xd0fc, 0x190c, 0x0db4, 0x2001, 0x0003, + 0x2004, 0xd0d4, 0x1118, 0x783f, 0x3145, 0x0020, 0x9084, 0xc000, + 0x783f, 0xb145, 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, 0x9184, 0x0070, 0x190c, 0x0dad, 0xd19c, 0x0158, 0x7820, 0x908c, 0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0db4, 0x0023, 0x012e, 0x0005, 0x012e, 0x0005, 0x1347, 0x1347, 0x135e, 0x1363, 0x1367, @@ -411,18 +411,18 @@ unsigned short risc_code01[] = { 0x149d, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x136e, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x1347, 0x134b, 0x1349, 0x080c, - 0x0db4, 0x080c, 0x0dad, 0x080c, 0x14a4, 0x2009, 0x1a4a, 0x2104, - 0x8000, 0x200a, 0x080c, 0x79f0, 0x080c, 0x195a, 0x0005, 0x2009, - 0x0048, 0x2060, 0x080c, 0x9ebc, 0x012e, 0x0005, 0x7004, 0xc085, + 0x0db4, 0x080c, 0x0dad, 0x080c, 0x14a4, 0x2009, 0x1a52, 0x2104, + 0x8000, 0x200a, 0x080c, 0x79fe, 0x080c, 0x196a, 0x0005, 0x2009, + 0x0048, 0x2060, 0x080c, 0x9ea9, 0x012e, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, 0x14a4, 0x080c, 0x15e0, 0x0005, 0x080c, 0x0db4, 0x080c, 0x14a4, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, - 0x0048, 0x080c, 0x9ebc, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, + 0x0048, 0x080c, 0x9ea9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x14a9, 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, 0x14a4, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0x9ebc, 0x0005, 0x080c, 0x14a4, + 0x009e, 0x2009, 0x0048, 0x080c, 0x9ea9, 0x0005, 0x080c, 0x14a4, 0x080c, 0x0db4, 0x080c, 0x14a4, 0x080c, 0x1421, 0x7827, 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, 0x782b, 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, @@ -431,13 +431,13 @@ unsigned short risc_code01[] = { 0x0050, 0x2003, 0x0020, 0x0490, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x143a, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, 0x0db4, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, - 0x080c, 0x79f0, 0x080c, 0x195a, 0x080c, 0xbb2c, 0x0158, 0xa9ac, + 0x080c, 0x79fe, 0x080c, 0x196a, 0x080c, 0xbb3b, 0x0158, 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xb75d, 0x0005, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xbf16, 0x2029, 0x00c8, + 0xc0bd, 0xa882, 0x080c, 0xb75c, 0x0005, 0x6010, 0x00b6, 0x2058, + 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xbf25, 0x2029, 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, - 0x080c, 0xd8ad, 0xd5a4, 0x1118, 0x080c, 0x14a9, 0x0005, 0x080c, - 0x79f0, 0x080c, 0x195a, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, + 0x080c, 0xd8c6, 0xd5a4, 0x1118, 0x080c, 0x14a9, 0x0005, 0x080c, + 0x79fe, 0x080c, 0x196a, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x151a, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, @@ -454,7 +454,7 @@ unsigned short risc_code01[] = { 0x0401, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x12c5, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0069, 0x0ca8, 0x0031, 0x2060, 0x2009, - 0x0053, 0x080c, 0x9ebc, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, + 0x0053, 0x080c, 0x9ea9, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, 0x1421, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, @@ -462,7 +462,7 @@ unsigned short risc_code01[] = { 0x810c, 0x810c, 0x080c, 0x150c, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, - 0x08c0, 0x080c, 0x79f0, 0x080c, 0x195a, 0x0090, 0x7827, 0x0015, + 0x08c0, 0x080c, 0x79fe, 0x080c, 0x196a, 0x0090, 0x7827, 0x0015, 0x782b, 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, @@ -478,18 +478,18 @@ unsigned short risc_code01[] = { 0x0030, 0x0904, 0x1593, 0x9284, 0x0048, 0x9086, 0x0008, 0x1904, 0x1593, 0x2001, 0x0109, 0x2004, 0xd08c, 0x01f0, 0x0006, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x0126, 0x2091, 0x2800, 0x00f6, - 0x0026, 0x0016, 0x2009, 0x1a4c, 0x2104, 0x8000, 0x0208, 0x200a, - 0x080c, 0x8393, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, + 0x0026, 0x0016, 0x2009, 0x1a54, 0x2104, 0x8000, 0x0208, 0x200a, + 0x080c, 0x83b1, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x000e, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x01d0, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x00f6, 0x0016, 0x2009, 0x1a4d, 0x2104, 0x8000, 0x0208, 0x200a, - 0x080c, 0x1d4c, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, + 0x00f6, 0x0016, 0x2009, 0x1a55, 0x2104, 0x8000, 0x0208, 0x200a, + 0x080c, 0x1d57, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x7818, 0xd0bc, 0x1904, 0x1543, 0x0005, 0x2001, 0x180c, 0x2004, 0xd0f4, 0x1528, 0x7a18, 0x9284, 0x0030, - 0x0508, 0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19c6, - 0x2004, 0x9005, 0x01b8, 0x2001, 0x1a35, 0x2004, 0x9086, 0x0000, - 0x0188, 0x2009, 0x1a4b, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x9431, 0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, + 0x0508, 0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19ce, + 0x2004, 0x9005, 0x01b8, 0x2001, 0x1a3d, 0x2004, 0x9086, 0x0000, + 0x0188, 0x2009, 0x1a53, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, + 0x9445, 0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, 0x0804, 0x1543, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x080c, 0x153c, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0db4, 0x7037, 0x0001, 0x7150, 0x7037, @@ -498,19 +498,19 @@ unsigned short risc_code01[] = { 0x701c, 0xd08c, 0x0904, 0x163f, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x163f, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x163f, 0x9c06, - 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, 0x7937, 0x012e, 0x7358, + 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, 0x7945, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x190c, 0xbef1, 0xab42, 0xac3e, 0x2001, - 0x1875, 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, + 0xb800, 0x00be, 0xd0bc, 0x190c, 0xbf00, 0xab42, 0xac3e, 0x2001, + 0x187d, 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, - 0xa837, 0xffff, 0x080c, 0x1f48, 0x1190, 0x080c, 0x17ed, 0x2a00, + 0xa837, 0xffff, 0x080c, 0x1f53, 0x1190, 0x080c, 0x17ed, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x14a9, 0x0005, 0x080c, 0x0db4, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, - 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1f28, 0x2165, 0x0002, 0x167e, + 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1f33, 0x2165, 0x0002, 0x167e, 0x16cb, 0x167e, 0x167e, 0x167e, 0x16ad, 0x167e, 0x1682, 0x1677, 0x16c2, 0x167e, 0x167e, 0x167e, 0x1787, 0x1696, 0x168c, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x16c2, 0x9085, 0x0001, @@ -518,10 +518,10 @@ unsigned short risc_code01[] = { 0xa83e, 0xa888, 0x0804, 0x16d2, 0xa87c, 0xd0bc, 0x0d78, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1721, 0xa87c, 0xd0bc, 0x0d28, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, - 0x0db4, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1f28, 0x2065, + 0x0db4, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1f33, 0x2065, 0xa888, 0xd19c, 0x1904, 0x1721, 0x0428, 0xa87c, 0xd0ac, 0x0970, 0xa804, 0x9045, 0x090c, 0x0db4, 0xa164, 0xa91a, 0x91ec, 0x000f, - 0x9d80, 0x1f28, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, + 0x9d80, 0x1f33, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x1721, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x167e, 0x9006, 0xa842, 0xa83e, 0x0804, 0x1721, 0xa87c, 0xd0ac, 0x0904, 0x167e, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x9082, @@ -549,7 +549,7 @@ unsigned short risc_code01[] = { 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c78, 0x0804, 0x167e, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, - 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1f23, 0xa813, 0x1f23, + 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1f2e, 0xa813, 0x1f2e, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, 0x0db4, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0db4, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, 0xaa32, @@ -558,7 +558,7 @@ unsigned short risc_code01[] = { 0xa916, 0x0128, 0x0078, 0x918a, 0x0002, 0xa916, 0x1158, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0db4, 0xa80e, 0xa064, - 0xa81a, 0x9084, 0x000f, 0x9080, 0x1f28, 0x2015, 0x82ff, 0x090c, + 0xa81a, 0x9084, 0x000f, 0x9080, 0x1f33, 0x2015, 0x82ff, 0x090c, 0x0db4, 0xaa12, 0x2205, 0xa80a, 0x0c10, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x18e2, 0x1844, 0x1844, 0x18e2, 0x18e2, 0x18dc, 0x18e2, 0x1844, 0x1893, 0x1893, 0x1893, 0x18e2, @@ -589,6311 +589,6314 @@ unsigned short risc_code01[] = { 0xa690, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, - 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1ee0, 0x1904, 0x17ed, + 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1eeb, 0x1904, 0x17ed, 0x900e, 0x0050, 0x080c, 0x0db4, 0xab2e, 0xaa32, 0xad1e, 0xac22, - 0xaf26, 0xae2a, 0x080c, 0x1ee0, 0x0005, 0x6014, 0x2048, 0x6118, + 0xaf26, 0xae2a, 0x080c, 0x1eeb, 0x0005, 0x6014, 0x2048, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, - 0xa986, 0x601b, 0x0002, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, + 0xa986, 0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, + 0x0150, 0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, + 0x080c, 0x9ea9, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, - 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0x9ebc, 0x0005, 0x0126, + 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0x9ea9, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x130c, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x130c, 0x00ce, - 0x2001, 0x0038, 0x080c, 0x19e7, 0x7930, 0x9186, 0x0040, 0x0160, + 0x2001, 0x0038, 0x080c, 0x19f2, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0db4, 0x2001, 0x001e, 0x8001, 0x1df0, - 0x8631, 0x1d40, 0x080c, 0x19f6, 0x000e, 0x6022, 0x012e, 0x0005, - 0x080c, 0x19e3, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, + 0x8631, 0x1d40, 0x080c, 0x1a01, 0x000e, 0x6022, 0x012e, 0x0005, + 0x080c, 0x19ee, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, - 0x0004, 0x00fe, 0x080c, 0x6f9b, 0x11b0, 0x2001, 0x0138, 0x2003, + 0x0004, 0x00fe, 0x080c, 0x6faa, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, - 0xa001, 0x8211, 0x1de0, 0x0081, 0x0066, 0x2031, 0x0000, 0x080c, - 0x704b, 0x006e, 0x0005, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, - 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, - 0x2a6b, 0x2009, 0x003c, 0x080c, 0x226a, 0x2001, 0x015d, 0x2003, - 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x7f46, 0x70a0, - 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, - 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x12c5, 0x7803, 0x0001, - 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, - 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x6f9b, 0x1108, - 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, - 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, - 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, - 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, - 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, - 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, 0x2c08, - 0x621c, 0x080c, 0x151a, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, - 0x15c5, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0005, - 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, - 0x0040, 0x0904, 0x1a54, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, - 0x080c, 0x0db4, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, - 0x2001, 0x0b10, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, - 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, - 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, - 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x19ed, - 0x9186, 0x0040, 0x190c, 0x0db4, 0x00d6, 0x2069, 0x0200, 0x692c, - 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, - 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, - 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, 0x0db4, - 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, - 0x2071, 0x1a35, 0x2079, 0x0090, 0x012e, 0x0005, 0x9280, 0x0005, - 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1ae9, 0xa964, 0x9184, - 0x0007, 0x0002, 0x1a72, 0x1ad4, 0x1a89, 0x1a89, 0x1a89, 0x1abc, - 0x1a9c, 0x1a8b, 0x918c, 0x00ff, 0x9186, 0x0008, 0x1170, 0xa87c, - 0xd0b4, 0x0904, 0x1d07, 0x9006, 0xa842, 0xa83e, 0xa988, 0x2900, - 0xa85a, 0xa813, 0x1f23, 0x0804, 0x1ae5, 0x9186, 0x0048, 0x0904, - 0x1ad4, 0x080c, 0x0db4, 0xa87c, 0xd0b4, 0x0904, 0x1d07, 0xa890, - 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, - 0xa84a, 0xa988, 0x0804, 0x1adc, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x001e, 0x1d38, 0xa87c, 0xd0b4, 0x0904, 0x1d07, 0xa890, 0xa842, - 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, - 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1f28, - 0x2005, 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, - 0x1540, 0xa87c, 0xd0b4, 0x0904, 0x1d07, 0xa804, 0xa85a, 0x2040, - 0xa064, 0x9084, 0x000f, 0x9080, 0x1f28, 0x2005, 0xa812, 0xa988, - 0x9006, 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1d07, - 0xa988, 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, - 0x000f, 0x9080, 0x1f28, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, - 0xa87e, 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, - 0x1d4c, 0x00e6, 0x2071, 0x1a35, 0x7000, 0x9005, 0x1904, 0x1b52, - 0x7206, 0x9280, 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, 0x782b, - 0x0004, 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, 0x00b6, - 0x2058, 0xb86c, 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, 0x0200, - 0x7803, 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, - 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0xa814, 0x2050, - 0xa858, 0x2040, 0xa810, 0x2060, 0xa064, 0x90ec, 0x000f, 0xa944, - 0x791a, 0x7116, 0xa848, 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, - 0x7004, 0xa940, 0xa838, 0x9106, 0x1500, 0xa93c, 0xa834, 0x9106, - 0x11e0, 0x0006, 0x0016, 0xa938, 0xa834, 0x9105, 0x0118, 0x001e, - 0x000e, 0x0098, 0x001e, 0x000e, 0x8aff, 0x01c8, 0x0126, 0x2091, - 0x8000, 0x2009, 0x0306, 0x200b, 0x0808, 0x00d9, 0x0108, 0x00c9, - 0x012e, 0x9006, 0x00ee, 0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, - 0xac34, 0x080c, 0x1f48, 0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, - 0x0001, 0x0c80, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, - 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, - 0x0904, 0x1d00, 0x700c, 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, - 0x0a04, 0x1cff, 0x9705, 0x0904, 0x1cff, 0x903e, 0x2730, 0xa880, - 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1c94, 0x1bd4, 0x1bd4, 0x1c94, - 0x1c94, 0x1c71, 0x1c94, 0x1bd4, 0x1c78, 0x1c23, 0x1c23, 0x1c94, - 0x1c94, 0x1c94, 0x1c6b, 0x1c23, 0xc0fc, 0xa882, 0xab2c, 0xaa30, - 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1c96, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1bc0, 0x1bbe, 0x1bbe, - 0x1bbe, 0x1bbe, 0x1bbe, 0x1bc4, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bbe, - 0x1bbe, 0x1bc8, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bcc, - 0x1bbe, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bbe, 0x1bd0, 0x080c, 0x0db4, - 0xa774, 0xa678, 0x0804, 0x1c96, 0xa78c, 0xa690, 0x0804, 0x1c96, - 0xa7a4, 0xa6a8, 0x0804, 0x1c96, 0xa7bc, 0xa6c0, 0x0804, 0x1c96, - 0xa7d4, 0xa6d8, 0x0804, 0x1c96, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0db4, 0x9082, 0x001b, 0x0002, 0x1bf7, 0x1bf7, 0x1bf9, 0x1bf7, - 0x1bf7, 0x1bf7, 0x1bff, 0x1bf7, 0x1bf7, 0x1bf7, 0x1c05, 0x1bf7, - 0x1bf7, 0x1bf7, 0x1c0b, 0x1bf7, 0x1bf7, 0x1bf7, 0x1c11, 0x1bf7, - 0x1bf7, 0x1bf7, 0x1c17, 0x1bf7, 0x1bf7, 0x1bf7, 0x1c1d, 0x080c, - 0x0db4, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, 0x1c96, 0xa584, - 0xa488, 0xa38c, 0xa290, 0x0804, 0x1c96, 0xa594, 0xa498, 0xa39c, - 0xa2a0, 0x0804, 0x1c96, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, - 0x1c96, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1c96, 0xa5c4, - 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1c96, 0xa5d4, 0xa4d8, 0xa3dc, - 0xa2e0, 0x0804, 0x1c96, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0db4, - 0x9082, 0x001b, 0x0002, 0x1c46, 0x1c44, 0x1c44, 0x1c44, 0x1c44, - 0x1c44, 0x1c4e, 0x1c44, 0x1c44, 0x1c44, 0x1c44, 0x1c44, 0x1c56, - 0x1c44, 0x1c44, 0x1c44, 0x1c44, 0x1c44, 0x1c5d, 0x1c44, 0x1c44, - 0x1c44, 0x1c44, 0x1c44, 0x1c64, 0x080c, 0x0db4, 0xa56c, 0xa470, - 0xa774, 0xa678, 0xa37c, 0xa280, 0x0804, 0x1c96, 0xa584, 0xa488, - 0xa78c, 0xa690, 0xa394, 0xa298, 0x0804, 0x1c96, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x04c8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0xa3c4, 0xa2c8, 0x0490, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0xa3dc, 0xa2e0, 0x0458, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x1518, 0x080c, 0x1ee0, 0x1904, 0x1b6f, 0x900e, 0x0804, 0x1d00, - 0xab64, 0x939c, 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, - 0x2060, 0x6004, 0x9086, 0x0043, 0x00ce, 0x0904, 0x1c23, 0xab9c, - 0x9016, 0xad8c, 0xac90, 0xaf94, 0xae98, 0x0040, 0x9386, 0x0008, - 0x0904, 0x1c23, 0x080c, 0x0db4, 0x080c, 0x0db4, 0x2009, 0x030f, - 0x2104, 0xd0fc, 0x0530, 0x0066, 0x2009, 0x0306, 0x2104, 0x9084, - 0x0030, 0x15c8, 0x2031, 0x1000, 0x200b, 0x4000, 0x2600, 0x9302, - 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, 0x9105, 0x0168, 0x2011, - 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, 0x9481, 0x0000, 0xa822, - 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, 0x0000, 0xa833, 0x0000, - 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, 0x7e0e, 0x782b, - 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, 0x9300, 0xa83e, 0xa840, - 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, 0x7010, 0x9201, 0x7012, - 0x080c, 0x1ee0, 0x0428, 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, - 0x9632, 0x7124, 0x7000, 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, - 0x2009, 0x0306, 0x2104, 0xd0b4, 0x1904, 0x1ca6, 0x200b, 0x4040, - 0x2009, 0x1a4e, 0x2104, 0x8000, 0x0a04, 0x1ca6, 0x200a, 0x0804, - 0x1ca6, 0xc18d, 0x7126, 0xd184, 0x1d58, 0x0804, 0x1ca6, 0x9006, - 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, - 0x0db4, 0x0026, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, - 0x7003, 0x0000, 0x7004, 0x0016, 0x080c, 0x1b62, 0x001e, 0x2060, - 0x6014, 0x2048, 0x080c, 0xbb2c, 0x0118, 0xa880, 0xc0bd, 0xa882, - 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, - 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, - 0x60c8, 0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, 0xb75d, 0x00ce, - 0x2001, 0x19c6, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, - 0x226a, 0x080c, 0x98eb, 0x2011, 0x0000, 0x080c, 0x977c, 0x080c, - 0x8a4a, 0x002e, 0x0804, 0x1e90, 0x0126, 0x2091, 0x2400, 0xa858, - 0x2040, 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1d09, - 0x7000, 0x0002, 0x1e90, 0x1d5e, 0x1dde, 0x1e8e, 0x8001, 0x7002, - 0x7027, 0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, 0x1dab, 0x080c, - 0x1b69, 0x0904, 0x1e90, 0x080c, 0x1b69, 0x0804, 0x1e90, 0x782b, - 0x0004, 0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, 0x8aff, 0x1518, - 0xa87c, 0xc0f5, 0xa87e, 0x00f8, 0x0026, 0x0036, 0xab3c, 0xaa40, - 0x0016, 0x7910, 0xa82c, 0x9100, 0xa82e, 0x7914, 0xa830, 0x9101, - 0xa832, 0x001e, 0x7810, 0x931a, 0x7814, 0x9213, 0x7800, 0xa81e, - 0x7804, 0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, 0x080c, 0x1efb, - 0xa880, 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, - 0xa812, 0x7003, 0x0000, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, - 0x0000, 0x0804, 0x1e90, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, - 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, - 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0db4, 0x7820, - 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, - 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, - 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, - 0x7003, 0x0000, 0x080c, 0x1b62, 0x0804, 0x1e90, 0x8001, 0x7002, - 0x7024, 0x8004, 0x7026, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, - 0x1d51, 0xd19c, 0x1904, 0x1e8c, 0x8aff, 0x0904, 0x1e90, 0x080c, - 0x1b69, 0x0804, 0x1e90, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, - 0x1efb, 0xdd9c, 0x1904, 0x1e4b, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0db4, 0x9082, 0x001b, 0x0002, 0x1e1f, 0x1e1f, 0x1e21, 0x1e1f, - 0x1e1f, 0x1e1f, 0x1e27, 0x1e1f, 0x1e1f, 0x1e1f, 0x1e2d, 0x1e1f, - 0x1e1f, 0x1e1f, 0x1e33, 0x1e1f, 0x1e1f, 0x1e1f, 0x1e39, 0x1e1f, - 0x1e1f, 0x1e1f, 0x1e3f, 0x1e1f, 0x1e1f, 0x1e1f, 0x1e45, 0x080c, - 0x0db4, 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1d80, 0xa08c, - 0x931a, 0xa090, 0x9213, 0x0804, 0x1d80, 0xa09c, 0x931a, 0xa0a0, - 0x9213, 0x0804, 0x1d80, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, - 0x1d80, 0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1d80, 0xa0cc, - 0x931a, 0xa0d0, 0x9213, 0x0804, 0x1d80, 0xa0dc, 0x931a, 0xa0e0, - 0x9213, 0x0804, 0x1d80, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0db4, - 0x9082, 0x001b, 0x0002, 0x1e6e, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e6c, - 0x1e6c, 0x1e74, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e7a, - 0x1e6c, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e6c, 0x1e80, 0x1e6c, 0x1e6c, - 0x1e6c, 0x1e6c, 0x1e6c, 0x1e86, 0x080c, 0x0db4, 0xa07c, 0x931a, - 0xa080, 0x9213, 0x0804, 0x1d80, 0xa094, 0x931a, 0xa098, 0x9213, - 0x0804, 0x1d80, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1d80, - 0xa0c4, 0x931a, 0xa0c8, 0x9213, 0x0804, 0x1d80, 0xa0dc, 0x931a, - 0xa0e0, 0x9213, 0x0804, 0x1d80, 0x0804, 0x1d7c, 0x080c, 0x0db4, - 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a35, 0x7000, 0x9086, - 0x0000, 0x0904, 0x1edb, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, - 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, - 0x080c, 0xd8f6, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0db4, - 0x0016, 0x2009, 0x0040, 0x080c, 0x226a, 0x001e, 0x2001, 0x020c, - 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1120, 0x2009, 0x0040, 0x080c, 0x226a, 0x782c, 0xd0fc, 0x09a8, - 0x080c, 0x1d4c, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, - 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x226a, 0x782b, - 0x0002, 0x7003, 0x0000, 0x080c, 0x1b62, 0x00ee, 0x00fe, 0x0005, - 0xa880, 0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, - 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, - 0x000f, 0x9080, 0x1f28, 0x2065, 0x8cff, 0x090c, 0x0db4, 0x8a51, - 0x0005, 0x2050, 0x0005, 0xa880, 0xd0fc, 0x11b8, 0x8a50, 0x8c61, - 0x2c05, 0x9005, 0x1190, 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, - 0x1108, 0x2900, 0x2040, 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, - 0x1f38, 0x2065, 0x8cff, 0x090c, 0x0db4, 0x0005, 0x0000, 0x001d, - 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, - 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, - 0x0000, 0x1f1b, 0x1f17, 0x0000, 0x0000, 0x1f25, 0x0000, 0x1f1b, - 0x1f22, 0x1f22, 0x1f1f, 0x0000, 0x0000, 0x0000, 0x1f25, 0x1f22, - 0x0000, 0x1f1d, 0x1f1d, 0x0000, 0x0000, 0x1f25, 0x0000, 0x1f1d, - 0x1f23, 0x1f23, 0x1f23, 0x0000, 0x0000, 0x0000, 0x1f25, 0x1f23, - 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, - 0x2127, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, - 0x0008, 0x1118, 0x2061, 0x1f23, 0x00d0, 0x9de0, 0x1f28, 0x9d86, - 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, - 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, - 0x0804, 0x2127, 0xa004, 0x9045, 0x0904, 0x2127, 0x08d8, 0x2c05, - 0x9005, 0x0904, 0x200f, 0xdd9c, 0x1904, 0x1fcb, 0x908a, 0x0036, - 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1fa0, 0x1fa0, 0x1fa2, - 0x1fa0, 0x1fa0, 0x1fa0, 0x1fa8, 0x1fa0, 0x1fa0, 0x1fa0, 0x1fae, - 0x1fa0, 0x1fa0, 0x1fa0, 0x1fb4, 0x1fa0, 0x1fa0, 0x1fa0, 0x1fba, - 0x1fa0, 0x1fa0, 0x1fa0, 0x1fc0, 0x1fa0, 0x1fa0, 0x1fa0, 0x1fc6, - 0x080c, 0x0db4, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x2005, - 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x2005, 0xa09c, 0x9422, - 0xa0a0, 0x931b, 0x0804, 0x2005, 0xa0ac, 0x9422, 0xa0b0, 0x931b, - 0x0804, 0x2005, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x2005, - 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x2005, 0xa0dc, 0x9422, - 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0db4, 0x9082, - 0x001b, 0x0002, 0x1fed, 0x1feb, 0x1feb, 0x1feb, 0x1feb, 0x1feb, - 0x1ff2, 0x1feb, 0x1feb, 0x1feb, 0x1feb, 0x1feb, 0x1ff7, 0x1feb, - 0x1feb, 0x1feb, 0x1feb, 0x1feb, 0x1ffc, 0x1feb, 0x1feb, 0x1feb, - 0x1feb, 0x1feb, 0x2001, 0x080c, 0x0db4, 0xa07c, 0x9422, 0xa080, - 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, - 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, - 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, 0x9405, - 0x0160, 0x8a51, 0x0904, 0x2127, 0x8c60, 0x0804, 0x1f77, 0xa004, - 0x9045, 0x0904, 0x2127, 0x0804, 0x1f52, 0x8a51, 0x0904, 0x2127, - 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x2127, - 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1f28, 0x2c05, 0x2060, 0xa880, - 0xc0fc, 0xa882, 0x0804, 0x211c, 0x2c05, 0x8422, 0x8420, 0x831a, - 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x20b9, 0x9082, - 0x001b, 0x0002, 0x2055, 0x2055, 0x2057, 0x2055, 0x2055, 0x2055, - 0x2065, 0x2055, 0x2055, 0x2055, 0x2073, 0x2055, 0x2055, 0x2055, - 0x2081, 0x2055, 0x2055, 0x2055, 0x208f, 0x2055, 0x2055, 0x2055, - 0x209d, 0x2055, 0x2055, 0x2055, 0x20ab, 0x080c, 0x0db4, 0xa17c, - 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa074, - 0x9420, 0xa078, 0x9319, 0x0804, 0x2117, 0xa18c, 0x2400, 0x9122, - 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa084, 0x9420, 0xa088, - 0x9319, 0x0804, 0x2117, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, - 0x911b, 0x0a0c, 0x0db4, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, - 0x2117, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, - 0x0db4, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x2117, 0xa1bc, - 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0b4, - 0x9420, 0xa0b8, 0x9319, 0x0804, 0x2117, 0xa1cc, 0x2400, 0x9122, - 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0c4, 0x9420, 0xa0c8, - 0x9319, 0x0804, 0x2117, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, - 0x911b, 0x0a0c, 0x0db4, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, - 0x2117, 0x9082, 0x001b, 0x0002, 0x20d7, 0x20d5, 0x20d5, 0x20d5, - 0x20d5, 0x20d5, 0x20e4, 0x20d5, 0x20d5, 0x20d5, 0x20d5, 0x20d5, - 0x20f1, 0x20d5, 0x20d5, 0x20d5, 0x20d5, 0x20d5, 0x20fe, 0x20d5, - 0x20d5, 0x20d5, 0x20d5, 0x20d5, 0x210b, 0x080c, 0x0db4, 0xa17c, - 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa06c, - 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, - 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa084, 0x9420, 0xa088, 0x9319, - 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, - 0x0db4, 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, - 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0b4, 0x9420, - 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, - 0x911b, 0x0a0c, 0x0db4, 0xa0cc, 0x9420, 0xa0d0, 0x9319, 0xac1e, - 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, 0xa812, - 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, - 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, - 0xd0bc, 0x190c, 0x0dad, 0x9084, 0x0007, 0x0002, 0x2148, 0x1d4c, - 0x2148, 0x213e, 0x2141, 0x2144, 0x2141, 0x2144, 0x080c, 0x1d4c, - 0x0005, 0x080c, 0x118f, 0x0005, 0x080c, 0x1d4c, 0x080c, 0x118f, - 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, - 0x2069, 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, - 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, - 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, - 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2267, 0x7900, 0xd1dc, - 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x218f, - 0x2187, 0x7937, 0x2187, 0x2189, 0x2189, 0x2189, 0x2189, 0x791d, - 0x2187, 0x218b, 0x2187, 0x2189, 0x2187, 0x2189, 0x2187, 0x080c, - 0x0db4, 0x0031, 0x0020, 0x080c, 0x791d, 0x080c, 0x7937, 0x0005, - 0x0006, 0x0016, 0x0026, 0x080c, 0xd8f6, 0x7930, 0x9184, 0x0003, - 0x01c0, 0x2001, 0x19c6, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, - 0x2004, 0x9005, 0x090c, 0x0db4, 0x00c6, 0x2001, 0x19c6, 0x2064, - 0x080c, 0xb75d, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x226a, - 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, - 0x080c, 0x6f9b, 0x1138, 0x080c, 0x727f, 0x080c, 0x5cda, 0x080c, - 0x6ecd, 0x0010, 0x080c, 0x5b99, 0x080c, 0x79e6, 0x0041, 0x0018, - 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, - 0x0036, 0x0046, 0x0056, 0x2071, 0x1a32, 0x080c, 0x195a, 0x005e, - 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, - 0x1800, 0x7128, 0x2001, 0x193f, 0x2102, 0x2001, 0x1947, 0x2102, - 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, - 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, - 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, - 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, - 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, - 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, - 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, - 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, - 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, - 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, - 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, - 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, - 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, - 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, - 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, - 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, - 0x080c, 0x0dad, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, - 0x2061, 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a65, - 0x080c, 0x2980, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, - 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, - 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, 0x196d, 0x2011, 0x196e, - 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, 0x29c4, 0x1238, 0x939d, - 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, - 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x29af, 0x9006, - 0x080c, 0x2992, 0x20a9, 0x0012, 0x1d04, 0x22bc, 0x2091, 0x6000, - 0x1f04, 0x22bc, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, - 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x269e, - 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x26ae, 0x60e7, 0x0000, - 0x61ea, 0x60e3, 0x0002, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x149f, 0x60bb, 0x0000, 0x20a9, - 0x0018, 0x60bf, 0x0000, 0x1f04, 0x22e9, 0x60bb, 0x0000, 0x60bf, - 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, - 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402f, 0x012e, - 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, 0x78c3, 0x0083, - 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, 0x1834, 0x2003, 0x0000, - 0x2001, 0x1833, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, - 0x0006, 0x0016, 0x0026, 0x6124, 0x9184, 0x5e2c, 0x1118, 0x9184, - 0x0007, 0x002a, 0x9195, 0x0004, 0x9284, 0x0007, 0x0002, 0x2349, - 0x232f, 0x2332, 0x2335, 0x233a, 0x233c, 0x2340, 0x2344, 0x080c, - 0x82c6, 0x00b8, 0x080c, 0x8393, 0x00a0, 0x080c, 0x8393, 0x080c, - 0x82c6, 0x0078, 0x0099, 0x0068, 0x080c, 0x82c6, 0x0079, 0x0048, - 0x080c, 0x8393, 0x0059, 0x0028, 0x080c, 0x8393, 0x080c, 0x82c6, - 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, - 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2597, 0xd1f4, 0x190c, - 0x0dad, 0x080c, 0x6f9b, 0x0904, 0x23a4, 0x080c, 0xc22c, 0x1120, - 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, 0x1800, 0x0550, - 0x080c, 0x6fbe, 0x0118, 0x080c, 0x6fac, 0x1520, 0x6027, 0x0020, - 0x6043, 0x0000, 0x080c, 0xc22c, 0x0168, 0x080c, 0x6fbe, 0x1150, - 0x2001, 0x1977, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x6e1c, - 0x0804, 0x259a, 0x70a0, 0x9005, 0x1150, 0x70a3, 0x0001, 0x00d6, - 0x2069, 0x0140, 0x080c, 0x6ff2, 0x00de, 0x1904, 0x259a, 0x080c, - 0x7289, 0x0428, 0x080c, 0x6fbe, 0x1590, 0x6024, 0x9084, 0x1800, - 0x1108, 0x0468, 0x080c, 0x7289, 0x080c, 0x727f, 0x080c, 0x5cda, - 0x080c, 0x6ecd, 0x0804, 0x2597, 0xd1ac, 0x1508, 0x6024, 0xd0dc, - 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7094, - 0x9086, 0x0028, 0x1110, 0x080c, 0x716e, 0x0804, 0x2597, 0x080c, - 0x7284, 0x0048, 0x2001, 0x194d, 0x2003, 0x0002, 0x0020, 0x080c, - 0x70d4, 0x0804, 0x2597, 0x080c, 0x7208, 0x0804, 0x2597, 0xd1ac, - 0x0904, 0x24b8, 0x080c, 0x6f9b, 0x11c0, 0x6027, 0x0020, 0x0006, - 0x0026, 0x0036, 0x080c, 0x6fb5, 0x1158, 0x080c, 0x727f, 0x080c, - 0x5cda, 0x080c, 0x6ecd, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, - 0x003e, 0x002e, 0x000e, 0x080c, 0x6f73, 0x0016, 0x0046, 0x00c6, - 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7038, 0xd084, - 0x0178, 0x9186, 0xf800, 0x1160, 0x7044, 0xd084, 0x1148, 0xc085, - 0x7046, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x48e9, 0x003e, - 0x080c, 0xc225, 0x1904, 0x2495, 0x9196, 0xff00, 0x05a8, 0x705c, - 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, 0x7130, - 0xd184, 0x1550, 0x080c, 0x3135, 0x0128, 0xc18d, 0x7132, 0x080c, - 0x6563, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, - 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x2495, - 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, - 0x2495, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, - 0x48e9, 0x003e, 0x0804, 0x2495, 0x7038, 0xd08c, 0x1140, 0x2001, - 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2495, 0xc1ad, 0x2102, 0x0036, - 0x73d4, 0x2011, 0x8013, 0x080c, 0x48e9, 0x003e, 0x7130, 0xc185, - 0x7132, 0x2011, 0x1854, 0x220c, 0x00f0, 0x0016, 0x2009, 0x0001, - 0x2011, 0x0100, 0x080c, 0x8218, 0x2019, 0x000e, 0x00c6, 0x2061, - 0x0000, 0x080c, 0xd4c7, 0x00ce, 0x9484, 0x00ff, 0x9080, 0x313a, - 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, - 0x080c, 0xd54b, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x2fa7, 0x001e, 0x0078, 0x0156, 0x00b6, - 0x20a9, 0x007f, 0x900e, 0x080c, 0x6247, 0x1110, 0x080c, 0x5cf4, - 0x8108, 0x1f04, 0x248b, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, - 0x9dc8, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, - 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x180c, 0x2214, 0xd29c, - 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, - 0x2003, 0x0001, 0x2001, 0x1825, 0x2003, 0x0000, 0x6027, 0x0020, - 0xd194, 0x0904, 0x2597, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2540, - 0x080c, 0x80a1, 0x080c, 0x93ad, 0x6027, 0x0004, 0x00f6, 0x2019, - 0x19c0, 0x2304, 0x907d, 0x0904, 0x250f, 0x7804, 0x9086, 0x0032, - 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, 0x782c, - 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, - 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, 0x080c, - 0x2b26, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, 0x080c, - 0x2a40, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, 0x080c, - 0x2b16, 0x9006, 0x080c, 0x2b16, 0x080c, 0x8861, 0x080c, 0x896d, - 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0x9e42, 0x009e, - 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, + 0xa001, 0x8211, 0x1de0, 0x0059, 0x0804, 0x705a, 0x0479, 0x0039, + 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, + 0x2071, 0x0200, 0x080c, 0x2a76, 0x2009, 0x003c, 0x080c, 0x2275, + 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, + 0x080c, 0x7f64, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, + 0x2001, 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, + 0x12c5, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, + 0x080c, 0x6faa, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, + 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, + 0x1160, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, + 0x2001, 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, + 0x2003, 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, + 0x8421, 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, + 0x601e, 0x0005, 0x2c08, 0x621c, 0x080c, 0x151a, 0x7930, 0x0005, + 0x2c08, 0x621c, 0x080c, 0x15c5, 0x7930, 0x0005, 0x8001, 0x1df0, + 0x0005, 0x2031, 0x0005, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, + 0x0038, 0x0c41, 0x9186, 0x0040, 0x0904, 0x1a5f, 0x2001, 0x001e, + 0x0c69, 0x8631, 0x1d80, 0x080c, 0x0db4, 0x781f, 0x0202, 0x2001, + 0x015d, 0x2003, 0x0000, 0x2001, 0x0b10, 0x0c01, 0x781c, 0xd084, + 0x0110, 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, + 0x0568, 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, + 0x0869, 0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, + 0x0030, 0x080c, 0x19f8, 0x9186, 0x0040, 0x190c, 0x0db4, 0x00d6, + 0x2069, 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, + 0x0130, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, + 0x9184, 0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, + 0x0007, 0x090c, 0x0db4, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, + 0x0126, 0x2091, 0x2400, 0x2071, 0x1a3d, 0x2079, 0x0090, 0x012e, + 0x0005, 0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, + 0x1af4, 0xa964, 0x9184, 0x0007, 0x0002, 0x1a7d, 0x1adf, 0x1a94, + 0x1a94, 0x1a94, 0x1ac7, 0x1aa7, 0x1a96, 0x918c, 0x00ff, 0x9186, + 0x0008, 0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1d12, 0x9006, 0xa842, + 0xa83e, 0xa988, 0x2900, 0xa85a, 0xa813, 0x1f2e, 0x0804, 0x1af0, + 0x9186, 0x0048, 0x0904, 0x1adf, 0x080c, 0x0db4, 0xa87c, 0xd0b4, + 0x0904, 0x1d12, 0xa890, 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, + 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa988, 0x0804, 0x1ae7, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x001e, 0x1d38, 0xa87c, 0xd0b4, 0x0904, + 0x1d12, 0xa890, 0xa842, 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, + 0xa846, 0xa8b0, 0xa84a, 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, + 0x000f, 0x9080, 0x1f33, 0x2005, 0xa812, 0xa988, 0x0448, 0x918c, + 0x00ff, 0x9186, 0x0015, 0x1540, 0xa87c, 0xd0b4, 0x0904, 0x1d12, + 0xa804, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1f33, + 0x2005, 0xa812, 0xa988, 0x9006, 0xa842, 0xa83e, 0x0088, 0xa87c, + 0xd0b4, 0x0904, 0x1d12, 0xa988, 0x9006, 0xa842, 0xa83e, 0x2900, + 0xa85a, 0xa864, 0x9084, 0x000f, 0x9080, 0x1f33, 0x2005, 0xa812, + 0xa916, 0xa87c, 0xc0dd, 0xa87e, 0x0005, 0x00f6, 0x2079, 0x0090, + 0x782c, 0xd0fc, 0x190c, 0x1d57, 0x00e6, 0x2071, 0x1a3d, 0x7000, + 0x9005, 0x1904, 0x1b5d, 0x7206, 0x9280, 0x0005, 0x204c, 0x9280, + 0x0004, 0x2004, 0x782b, 0x0004, 0x00f6, 0x2079, 0x0200, 0x7803, + 0x0040, 0x00fe, 0x00b6, 0x2058, 0xb86c, 0x7836, 0xb890, 0x00be, + 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0xa001, 0xa001, 0xa001, + 0xa001, 0xa001, 0xa001, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, + 0x00fe, 0xa814, 0x2050, 0xa858, 0x2040, 0xa810, 0x2060, 0xa064, + 0x90ec, 0x000f, 0xa944, 0x791a, 0x7116, 0xa848, 0x781e, 0x701a, + 0x9006, 0x700e, 0x7012, 0x7004, 0xa940, 0xa838, 0x9106, 0x1500, + 0xa93c, 0xa834, 0x9106, 0x11e0, 0x0006, 0x0016, 0xa938, 0xa834, + 0x9105, 0x0118, 0x001e, 0x000e, 0x0098, 0x001e, 0x000e, 0x8aff, + 0x01c8, 0x0126, 0x2091, 0x8000, 0x2009, 0x0306, 0x200b, 0x0808, + 0x00d9, 0x0108, 0x00c9, 0x012e, 0x9006, 0x00ee, 0x00fe, 0x0005, + 0x0036, 0x0046, 0xab38, 0xac34, 0x080c, 0x1f53, 0x004e, 0x003e, + 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, 0x2009, 0x0306, 0x200b, + 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, 0x0066, 0x0056, 0x0046, + 0x0036, 0x0026, 0x8aff, 0x0904, 0x1d0b, 0x700c, 0x7214, 0x923a, + 0x7010, 0x7218, 0x9203, 0x0a04, 0x1d0a, 0x9705, 0x0904, 0x1d0a, + 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1c9f, + 0x1bdf, 0x1bdf, 0x1c9f, 0x1c9f, 0x1c7c, 0x1c9f, 0x1bdf, 0x1c83, + 0x1c2e, 0x1c2e, 0x1c9f, 0x1c9f, 0x1c9f, 0x1c76, 0x1c2e, 0xc0fc, + 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1ca1, + 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, + 0x1bcb, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bcf, 0x1bc9, + 0x1bc9, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bd3, 0x1bc9, 0x1bc9, 0x1bc9, + 0x1bc9, 0x1bc9, 0x1bd7, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bc9, 0x1bc9, + 0x1bdb, 0x080c, 0x0db4, 0xa774, 0xa678, 0x0804, 0x1ca1, 0xa78c, + 0xa690, 0x0804, 0x1ca1, 0xa7a4, 0xa6a8, 0x0804, 0x1ca1, 0xa7bc, + 0xa6c0, 0x0804, 0x1ca1, 0xa7d4, 0xa6d8, 0x0804, 0x1ca1, 0x2c05, + 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1c02, + 0x1c02, 0x1c04, 0x1c02, 0x1c02, 0x1c02, 0x1c0a, 0x1c02, 0x1c02, + 0x1c02, 0x1c10, 0x1c02, 0x1c02, 0x1c02, 0x1c16, 0x1c02, 0x1c02, + 0x1c02, 0x1c1c, 0x1c02, 0x1c02, 0x1c02, 0x1c22, 0x1c02, 0x1c02, + 0x1c02, 0x1c28, 0x080c, 0x0db4, 0xa574, 0xa478, 0xa37c, 0xa280, + 0x0804, 0x1ca1, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x1ca1, + 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1ca1, 0xa5a4, 0xa4a8, + 0xa3ac, 0xa2b0, 0x0804, 0x1ca1, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, + 0x0804, 0x1ca1, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1ca1, + 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1ca1, 0x2c05, 0x908a, + 0x0034, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1c51, 0x1c4f, + 0x1c4f, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c59, 0x1c4f, 0x1c4f, 0x1c4f, + 0x1c4f, 0x1c4f, 0x1c61, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c4f, + 0x1c68, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c4f, 0x1c6f, 0x080c, + 0x0db4, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0804, + 0x1ca1, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0804, + 0x1ca1, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x04c8, + 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0490, 0xa5cc, + 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x0458, 0xa864, 0x9084, + 0x00ff, 0x9086, 0x001e, 0x1518, 0x080c, 0x1eeb, 0x1904, 0x1b7a, + 0x900e, 0x0804, 0x1d0b, 0xab64, 0x939c, 0x00ff, 0x9386, 0x0048, + 0x1180, 0x00c6, 0x7004, 0x2060, 0x6004, 0x9086, 0x0043, 0x00ce, + 0x0904, 0x1c2e, 0xab9c, 0x9016, 0xad8c, 0xac90, 0xaf94, 0xae98, + 0x0040, 0x9386, 0x0008, 0x0904, 0x1c2e, 0x080c, 0x0db4, 0x080c, + 0x0db4, 0x2009, 0x030f, 0x2104, 0xd0fc, 0x0530, 0x0066, 0x2009, + 0x0306, 0x2104, 0x9084, 0x0030, 0x15c8, 0x2031, 0x1000, 0x200b, + 0x4000, 0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, + 0x9105, 0x0168, 0x2011, 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, + 0x9481, 0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, + 0x0000, 0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, + 0x7f0a, 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, + 0x9300, 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, + 0x7010, 0x9201, 0x7012, 0x080c, 0x1eeb, 0x0428, 0x2031, 0x0080, + 0x9584, 0x007f, 0x0108, 0x9632, 0x7124, 0x7000, 0x9086, 0x0000, + 0x1198, 0xc185, 0x7126, 0x2009, 0x0306, 0x2104, 0xd0b4, 0x1904, + 0x1cb1, 0x200b, 0x4040, 0x2009, 0x1a56, 0x2104, 0x8000, 0x0a04, + 0x1cb1, 0x200a, 0x0804, 0x1cb1, 0xc18d, 0x7126, 0xd184, 0x1d58, + 0x0804, 0x1cb1, 0x9006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, + 0x007e, 0x0005, 0x080c, 0x0db4, 0x0026, 0x2001, 0x0105, 0x2003, + 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, 0x7004, 0x0016, 0x080c, + 0x1b6d, 0x001e, 0x2060, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0118, + 0xa880, 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, 0x1180, 0x2061, + 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, + 0x1dc0, 0x60c4, 0xa89a, 0x60c8, 0xa896, 0x7004, 0x2060, 0x00c6, + 0x080c, 0xb75c, 0x00ce, 0x2001, 0x19ce, 0x2004, 0x9c06, 0x1160, + 0x2009, 0x0040, 0x080c, 0x2275, 0x080c, 0x98d4, 0x2011, 0x0000, + 0x080c, 0x9765, 0x080c, 0x8a68, 0x002e, 0x0804, 0x1e9b, 0x0126, + 0x2091, 0x2400, 0xa858, 0x2040, 0x792c, 0x782b, 0x0002, 0x9184, + 0x0700, 0x1904, 0x1d14, 0x7000, 0x0002, 0x1e9b, 0x1d69, 0x1de9, + 0x1e99, 0x8001, 0x7002, 0x7027, 0x0000, 0xd19c, 0x1158, 0x8aff, + 0x0904, 0x1db6, 0x080c, 0x1b74, 0x0904, 0x1e9b, 0x080c, 0x1b74, + 0x0804, 0x1e9b, 0x782b, 0x0004, 0xd194, 0x0148, 0xa880, 0xc0fc, + 0xa882, 0x8aff, 0x1518, 0xa87c, 0xc0f5, 0xa87e, 0x00f8, 0x0026, + 0x0036, 0xab3c, 0xaa40, 0x0016, 0x7910, 0xa82c, 0x9100, 0xa82e, + 0x7914, 0xa830, 0x9101, 0xa832, 0x001e, 0x7810, 0x931a, 0x7814, + 0x9213, 0x7800, 0xa81e, 0x7804, 0xa822, 0xab3e, 0xaa42, 0x003e, + 0x002e, 0x080c, 0x1f06, 0xa880, 0xc0fd, 0xa882, 0x2a00, 0xa816, + 0x2800, 0xa85a, 0x2c00, 0xa812, 0x7003, 0x0000, 0x2009, 0x0306, + 0x200b, 0x4800, 0x7027, 0x0000, 0x0804, 0x1e9b, 0x00f6, 0x0026, + 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, + 0x1984, 0x9085, 0x0012, 0x7816, 0x0036, 0x2019, 0x1000, 0x8319, + 0x090c, 0x0db4, 0x7820, 0xd0bc, 0x1dd0, 0x003e, 0x79c8, 0x000e, + 0x9102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, + 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x002e, + 0x00fe, 0x782b, 0x0008, 0x7003, 0x0000, 0x080c, 0x1b6d, 0x0804, + 0x1e9b, 0x8001, 0x7002, 0x7024, 0x8004, 0x7026, 0xd194, 0x0170, + 0x782c, 0xd0fc, 0x1904, 0x1d5c, 0xd19c, 0x1904, 0x1e97, 0x8aff, + 0x0904, 0x1e9b, 0x080c, 0x1b74, 0x0804, 0x1e9b, 0x0026, 0x0036, + 0xab3c, 0xaa40, 0x080c, 0x1f06, 0xdd9c, 0x1904, 0x1e56, 0x2c05, + 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1e2a, + 0x1e2a, 0x1e2c, 0x1e2a, 0x1e2a, 0x1e2a, 0x1e32, 0x1e2a, 0x1e2a, + 0x1e2a, 0x1e38, 0x1e2a, 0x1e2a, 0x1e2a, 0x1e3e, 0x1e2a, 0x1e2a, + 0x1e2a, 0x1e44, 0x1e2a, 0x1e2a, 0x1e2a, 0x1e4a, 0x1e2a, 0x1e2a, + 0x1e2a, 0x1e50, 0x080c, 0x0db4, 0xa07c, 0x931a, 0xa080, 0x9213, + 0x0804, 0x1d8b, 0xa08c, 0x931a, 0xa090, 0x9213, 0x0804, 0x1d8b, + 0xa09c, 0x931a, 0xa0a0, 0x9213, 0x0804, 0x1d8b, 0xa0ac, 0x931a, + 0xa0b0, 0x9213, 0x0804, 0x1d8b, 0xa0bc, 0x931a, 0xa0c0, 0x9213, + 0x0804, 0x1d8b, 0xa0cc, 0x931a, 0xa0d0, 0x9213, 0x0804, 0x1d8b, + 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, 0x1d8b, 0x2c05, 0x908a, + 0x0034, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1e79, 0x1e77, + 0x1e77, 0x1e77, 0x1e77, 0x1e77, 0x1e7f, 0x1e77, 0x1e77, 0x1e77, + 0x1e77, 0x1e77, 0x1e85, 0x1e77, 0x1e77, 0x1e77, 0x1e77, 0x1e77, + 0x1e8b, 0x1e77, 0x1e77, 0x1e77, 0x1e77, 0x1e77, 0x1e91, 0x080c, + 0x0db4, 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1d8b, 0xa094, + 0x931a, 0xa098, 0x9213, 0x0804, 0x1d8b, 0xa0ac, 0x931a, 0xa0b0, + 0x9213, 0x0804, 0x1d8b, 0xa0c4, 0x931a, 0xa0c8, 0x9213, 0x0804, + 0x1d8b, 0xa0dc, 0x931a, 0xa0e0, 0x9213, 0x0804, 0x1d8b, 0x0804, + 0x1d87, 0x080c, 0x0db4, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071, + 0x1a3d, 0x7000, 0x9086, 0x0000, 0x0904, 0x1ee6, 0x2079, 0x0090, + 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, + 0x9184, 0x0003, 0x0188, 0x080c, 0xd90f, 0x2001, 0x0133, 0x2004, + 0x9005, 0x090c, 0x0db4, 0x0016, 0x2009, 0x0040, 0x080c, 0x2275, + 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, + 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x2275, + 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x1d57, 0x7000, 0x9086, 0x0000, + 0x1978, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, + 0x080c, 0x2275, 0x782b, 0x0002, 0x7003, 0x0000, 0x080c, 0x1b6d, + 0x00ee, 0x00fe, 0x0005, 0xa880, 0xd0fc, 0x11a8, 0x8c60, 0x2c05, + 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, + 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1f33, 0x2065, 0x8cff, + 0x090c, 0x0db4, 0x8a51, 0x0005, 0x2050, 0x0005, 0xa880, 0xd0fc, + 0x11b8, 0x8a50, 0x8c61, 0x2c05, 0x9005, 0x1190, 0x2800, 0x9906, + 0x0120, 0xa000, 0x9005, 0x1108, 0x2900, 0x2040, 0xa85a, 0xa064, + 0x9084, 0x000f, 0x9080, 0x1f43, 0x2065, 0x8cff, 0x090c, 0x0db4, + 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, + 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, + 0x0000, 0x0023, 0x0000, 0x0000, 0x1f26, 0x1f22, 0x0000, 0x0000, + 0x1f30, 0x0000, 0x1f26, 0x1f2d, 0x1f2d, 0x1f2a, 0x0000, 0x0000, + 0x0000, 0x1f30, 0x1f2d, 0x0000, 0x1f28, 0x1f28, 0x0000, 0x0000, + 0x1f30, 0x0000, 0x1f28, 0x1f2e, 0x1f2e, 0x1f2e, 0x0000, 0x0000, + 0x0000, 0x1f30, 0x1f2e, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, + 0xa888, 0x9055, 0x0904, 0x2132, 0x2940, 0xa064, 0x90ec, 0x000f, + 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x1f2e, 0x00d0, + 0x9de0, 0x1f33, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, + 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, + 0x9065, 0x1140, 0x0310, 0x0804, 0x2132, 0xa004, 0x9045, 0x0904, + 0x2132, 0x08d8, 0x2c05, 0x9005, 0x0904, 0x201a, 0xdd9c, 0x1904, + 0x1fd6, 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, + 0x1fab, 0x1fab, 0x1fad, 0x1fab, 0x1fab, 0x1fab, 0x1fb3, 0x1fab, + 0x1fab, 0x1fab, 0x1fb9, 0x1fab, 0x1fab, 0x1fab, 0x1fbf, 0x1fab, + 0x1fab, 0x1fab, 0x1fc5, 0x1fab, 0x1fab, 0x1fab, 0x1fcb, 0x1fab, + 0x1fab, 0x1fab, 0x1fd1, 0x080c, 0x0db4, 0xa07c, 0x9422, 0xa080, + 0x931b, 0x0804, 0x2010, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, + 0x2010, 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x2010, 0xa0ac, + 0x9422, 0xa0b0, 0x931b, 0x0804, 0x2010, 0xa0bc, 0x9422, 0xa0c0, + 0x931b, 0x0804, 0x2010, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, + 0x2010, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, + 0x1a0c, 0x0db4, 0x9082, 0x001b, 0x0002, 0x1ff8, 0x1ff6, 0x1ff6, + 0x1ff6, 0x1ff6, 0x1ff6, 0x1ffd, 0x1ff6, 0x1ff6, 0x1ff6, 0x1ff6, + 0x1ff6, 0x2002, 0x1ff6, 0x1ff6, 0x1ff6, 0x1ff6, 0x1ff6, 0x2007, + 0x1ff6, 0x1ff6, 0x1ff6, 0x1ff6, 0x1ff6, 0x200c, 0x080c, 0x0db4, + 0xa07c, 0x9422, 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, + 0x931b, 0x0070, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, + 0x9422, 0xa0c8, 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, + 0x0630, 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x2132, 0x8c60, + 0x0804, 0x1f82, 0xa004, 0x9045, 0x0904, 0x2132, 0x0804, 0x1f5d, + 0x8a51, 0x0904, 0x2132, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, + 0x9045, 0x0904, 0x2132, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1f33, + 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x2127, 0x2c05, + 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, + 0x1904, 0x20c4, 0x9082, 0x001b, 0x0002, 0x2060, 0x2060, 0x2062, + 0x2060, 0x2060, 0x2060, 0x2070, 0x2060, 0x2060, 0x2060, 0x207e, + 0x2060, 0x2060, 0x2060, 0x208c, 0x2060, 0x2060, 0x2060, 0x209a, + 0x2060, 0x2060, 0x2060, 0x20a8, 0x2060, 0x2060, 0x2060, 0x20b6, + 0x080c, 0x0db4, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, + 0x0a0c, 0x0db4, 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x2122, + 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0db4, + 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, 0x2122, 0xa19c, 0x2400, + 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa094, 0x9420, + 0xa098, 0x9319, 0x0804, 0x2122, 0xa1ac, 0x2400, 0x9122, 0xa1b0, + 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0a4, 0x9420, 0xa0a8, 0x9319, + 0x0804, 0x2122, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, + 0x0a0c, 0x0db4, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x2122, + 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0db4, + 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, 0x2122, 0xa1dc, 0x2400, + 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0d4, 0x9420, + 0xa0d8, 0x9319, 0x0804, 0x2122, 0x9082, 0x001b, 0x0002, 0x20e2, + 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20ef, 0x20e0, 0x20e0, + 0x20e0, 0x20e0, 0x20e0, 0x20fc, 0x20e0, 0x20e0, 0x20e0, 0x20e0, + 0x20e0, 0x2109, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x20e0, 0x2116, + 0x080c, 0x0db4, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, + 0x0a0c, 0x0db4, 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, + 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa084, + 0x9420, 0xa088, 0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, + 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa09c, 0x9420, 0xa0a0, 0x9319, + 0x00c8, 0xa1c4, 0x2400, 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, + 0x0db4, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, + 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0db4, 0xa0cc, 0x9420, + 0xa0d0, 0x9319, 0xac1e, 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, + 0xa85a, 0x2c00, 0xa812, 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, + 0x9006, 0x0028, 0x008e, 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, + 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0dad, 0x9084, 0x0007, + 0x0002, 0x2153, 0x1d57, 0x2153, 0x2149, 0x214c, 0x214f, 0x214c, + 0x214f, 0x080c, 0x1d57, 0x0005, 0x080c, 0x118f, 0x0005, 0x080c, + 0x1d57, 0x080c, 0x118f, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, + 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, 0x789b, + 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, + 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, + 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x2272, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, 0x9084, + 0x000e, 0x0002, 0x219a, 0x2192, 0x7945, 0x2192, 0x2194, 0x2194, + 0x2194, 0x2194, 0x792b, 0x2192, 0x2196, 0x2192, 0x2194, 0x2192, + 0x2194, 0x2192, 0x080c, 0x0db4, 0x0031, 0x0020, 0x080c, 0x792b, + 0x080c, 0x7945, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, 0xd90f, + 0x7930, 0x9184, 0x0003, 0x01c0, 0x2001, 0x19ce, 0x2004, 0x9005, + 0x0170, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0db4, 0x00c6, + 0x2001, 0x19ce, 0x2064, 0x080c, 0xb75c, 0x00ce, 0x00f8, 0x2009, + 0x0040, 0x080c, 0x2275, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, + 0x9286, 0x0003, 0x0160, 0x080c, 0x6faa, 0x1138, 0x080c, 0x728c, + 0x080c, 0x5ce5, 0x080c, 0x6edc, 0x0010, 0x080c, 0x5ba4, 0x080c, + 0x79f4, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, + 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a3a, + 0x080c, 0x196a, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, + 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, 0x2001, 0x1947, 0x2102, + 0x2001, 0x194f, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, + 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, + 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, + 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, 0x0488, 0x9182, 0x024c, + 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, 0x9400, 0x9400, 0x9420, + 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, 0x0006, 0x8403, 0x8003, + 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, 0x1230, 0x2011, 0x0005, + 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, 0x042c, 0x1228, 0x2011, + 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, 0x059c, 0x1228, 0x2011, + 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, 0x0002, 0x8423, 0x9482, + 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, 0x0110, 0x0208, 0x8321, + 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, 0x0005, 0x0006, 0x00d6, + 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x00de, + 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, 0x9005, 0x6810, 0x0110, + 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, 0x0005, 0x0006, 0x00d6, + 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, 0x910d, 0x6912, 0x00de, + 0x000e, 0x0005, 0x7938, 0x080c, 0x0dad, 0x00f6, 0x2079, 0x0200, + 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, + 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, + 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1800, 0x2009, + 0x0000, 0x080c, 0x2a70, 0x080c, 0x298b, 0x6054, 0x8004, 0x8004, + 0x8004, 0x8004, 0x9084, 0x000c, 0x6150, 0x918c, 0xfff3, 0x9105, + 0x6052, 0x6050, 0x9084, 0xb17f, 0x9085, 0x2000, 0x6052, 0x2009, + 0x1975, 0x2011, 0x1976, 0x6358, 0x939c, 0x38f0, 0x2320, 0x080c, + 0x29cf, 0x1238, 0x939d, 0x4003, 0x94a5, 0x8603, 0x230a, 0x2412, + 0x0030, 0x939d, 0x0203, 0x94a5, 0x8603, 0x230a, 0x2412, 0x9006, + 0x080c, 0x29ba, 0x9006, 0x080c, 0x299d, 0x20a9, 0x0012, 0x1d04, + 0x22c7, 0x2091, 0x6000, 0x1f04, 0x22c7, 0x602f, 0x0100, 0x602f, + 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6024, + 0x6026, 0x080c, 0x26a9, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, + 0x26b9, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0002, 0x604b, 0xf7f7, + 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x149f, + 0x60bb, 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x22f4, + 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, + 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, + 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, + 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, + 0x1834, 0x2003, 0x0000, 0x2001, 0x1833, 0x2003, 0x0001, 0x0005, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x9184, + 0x5e2c, 0x1118, 0x9184, 0x0007, 0x002a, 0x9195, 0x0004, 0x9284, + 0x0007, 0x0002, 0x2354, 0x233a, 0x233d, 0x2340, 0x2345, 0x2347, + 0x234b, 0x234f, 0x080c, 0x82e4, 0x00b8, 0x080c, 0x83b1, 0x00a0, + 0x080c, 0x83b1, 0x080c, 0x82e4, 0x0078, 0x0099, 0x0068, 0x080c, + 0x82e4, 0x0079, 0x0048, 0x080c, 0x83b1, 0x0059, 0x0028, 0x080c, + 0x83b1, 0x080c, 0x82e4, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, + 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, + 0x25a2, 0xd1f4, 0x190c, 0x0dad, 0x080c, 0x6faa, 0x0904, 0x23af, + 0x080c, 0xc23b, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, + 0x9084, 0x1800, 0x0550, 0x080c, 0x6fcd, 0x0118, 0x080c, 0x6fbb, + 0x1520, 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xc23b, 0x0168, + 0x080c, 0x6fcd, 0x1150, 0x2001, 0x197f, 0x2003, 0x0001, 0x6027, + 0x1800, 0x080c, 0x6e2b, 0x0804, 0x25a5, 0x70a0, 0x9005, 0x1150, + 0x70a3, 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x7001, 0x00de, + 0x1904, 0x25a5, 0x080c, 0x7296, 0x0428, 0x080c, 0x6fcd, 0x1590, + 0x6024, 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x7296, 0x080c, + 0x728c, 0x080c, 0x5ce5, 0x080c, 0x6edc, 0x0804, 0x25a2, 0xd1ac, + 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, + 0xd0cc, 0x0130, 0x7094, 0x9086, 0x0028, 0x1110, 0x080c, 0x717b, + 0x0804, 0x25a2, 0x080c, 0x7291, 0x0048, 0x2001, 0x1955, 0x2003, + 0x0002, 0x0020, 0x080c, 0x70e1, 0x0804, 0x25a2, 0x080c, 0x7215, + 0x0804, 0x25a2, 0xd1ac, 0x0904, 0x24c3, 0x080c, 0x6faa, 0x11c0, + 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x080c, 0x6fc4, 0x1158, + 0x080c, 0x728c, 0x080c, 0x5ce5, 0x080c, 0x6edc, 0x003e, 0x002e, + 0x000e, 0x00ae, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x6f82, + 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, + 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, + 0xff00, 0x7038, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7044, + 0xd084, 0x1148, 0xc085, 0x7046, 0x0036, 0x2418, 0x2011, 0x8016, + 0x080c, 0x48f4, 0x003e, 0x080c, 0xc234, 0x1904, 0x24a0, 0x9196, + 0xff00, 0x05a8, 0x705c, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, + 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x3140, 0x0128, + 0xc18d, 0x7132, 0x080c, 0x6572, 0x1510, 0x6240, 0x9294, 0x0010, + 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, + 0xd08c, 0x0904, 0x24a0, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, + 0x200c, 0xd1ac, 0x1904, 0x24a0, 0xc1ad, 0x2102, 0x0036, 0x73d4, + 0x2011, 0x8013, 0x080c, 0x48f4, 0x003e, 0x0804, 0x24a0, 0x7038, + 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x24a0, + 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x48f4, + 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x185c, 0x220c, 0x00f0, + 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8236, 0x2019, + 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xd4e0, 0x00ce, 0x9484, + 0x00ff, 0x9080, 0x3145, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, + 0x9006, 0x2009, 0x000e, 0x080c, 0xd564, 0x001e, 0xd1ac, 0x1148, + 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x2fb2, 0x001e, + 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6256, + 0x1110, 0x080c, 0x5cff, 0x8108, 0x1f04, 0x2496, 0x00be, 0x015e, + 0x00ce, 0x004e, 0x080c, 0x9db5, 0x60e3, 0x0000, 0x001e, 0x2001, + 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, + 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, + 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x1825, 0x2003, + 0x0000, 0x6027, 0x0020, 0xd194, 0x0904, 0x25a2, 0x0016, 0x6220, + 0xd2b4, 0x0904, 0x254b, 0x080c, 0x80bf, 0x080c, 0x93c7, 0x6027, + 0x0004, 0x00f6, 0x2019, 0x19c8, 0x2304, 0x907d, 0x0904, 0x251a, + 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, + 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, + 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, + 0x8001, 0x1df0, 0x080c, 0x2b31, 0x2001, 0x001e, 0x8001, 0x0240, + 0x20a9, 0x0009, 0x080c, 0x2a4b, 0x6904, 0xd1dc, 0x1140, 0x0cb0, + 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, 0x080c, + 0x887f, 0x080c, 0x898b, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, + 0x080c, 0x9e2f, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, + 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, + 0x4000, 0x0110, 0x080c, 0x2b31, 0x00de, 0x00c6, 0x2061, 0x19bf, + 0x6028, 0x080c, 0xc23b, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, + 0x909a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x93a3, + 0x0804, 0x25a1, 0x2061, 0x0100, 0x62c0, 0x080c, 0x9c3b, 0x2019, + 0x19c8, 0x2304, 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0x9ea9, + 0x00ce, 0x0804, 0x25a1, 0xd2bc, 0x0904, 0x258e, 0x080c, 0x80cc, + 0x6014, 0x9084, 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, - 0x2b26, 0x00de, 0x00c6, 0x2061, 0x19b7, 0x6028, 0x080c, 0xc22c, - 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, 0x1238, - 0x8000, 0x602a, 0x00ce, 0x080c, 0x9389, 0x0804, 0x2596, 0x2061, - 0x0100, 0x62c0, 0x080c, 0x9c4e, 0x2019, 0x19c0, 0x2304, 0x9065, - 0x0120, 0x2009, 0x0027, 0x080c, 0x9ebc, 0x00ce, 0x0804, 0x2596, - 0xd2bc, 0x0904, 0x2583, 0x080c, 0x80ae, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140, - 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2b26, 0x00de, 0x00c6, - 0x2061, 0x19b7, 0x6044, 0x080c, 0xc22c, 0x0120, 0x909a, 0x0003, - 0x1628, 0x0018, 0x909a, 0x00c8, 0x1608, 0x8000, 0x6046, 0x603c, - 0x00ce, 0x9005, 0x0558, 0x2009, 0x07d0, 0x080c, 0x80a6, 0x9080, - 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, 0x1984, - 0x918d, 0x0012, 0x6116, 0x00d0, 0x6114, 0x918c, 0x1984, 0x918d, - 0x0016, 0x6116, 0x0098, 0x6027, 0x0004, 0x0080, 0x0036, 0x2019, - 0x0001, 0x080c, 0x96d9, 0x003e, 0x2019, 0x19c6, 0x2304, 0x9065, - 0x0120, 0x2009, 0x004f, 0x080c, 0x9ebc, 0x00ce, 0x001e, 0xd19c, - 0x0904, 0x2609, 0x7038, 0xd0ac, 0x1904, 0x25de, 0x0016, 0x0156, - 0x6027, 0x0008, 0x6050, 0x9085, 0x0040, 0x6052, 0x6050, 0x9084, - 0xfbcf, 0x6052, 0x080c, 0x2a5f, 0x9085, 0x2000, 0x6052, 0x20a9, - 0x0012, 0x1d04, 0x25b1, 0x080c, 0x80d5, 0x1f04, 0x25b1, 0x6050, - 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x20a9, 0x0028, 0xa001, - 0x1f04, 0x25bf, 0x6150, 0x9185, 0x1400, 0x6052, 0x20a9, 0x0366, - 0x1d04, 0x25c8, 0x080c, 0x80d5, 0x6020, 0xd09c, 0x1130, 0x015e, - 0x6152, 0x001e, 0x6027, 0x0008, 0x04a0, 0x080c, 0x2a27, 0x1f04, - 0x25c8, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, - 0xc09c, 0x602a, 0x080c, 0x9dc8, 0x60e3, 0x0000, 0x080c, 0xd8d5, - 0x080c, 0xd8f0, 0x080c, 0x5393, 0xd0fc, 0x1138, 0x080c, 0xc225, - 0x1120, 0x9085, 0x0001, 0x080c, 0x6fe2, 0x9006, 0x080c, 0x2b16, - 0x2009, 0x0002, 0x080c, 0x2a65, 0x00e6, 0x2071, 0x1800, 0x7003, - 0x0004, 0x080c, 0x0e80, 0x00ee, 0x6027, 0x0008, 0x080c, 0x0b8f, - 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x71cc, 0x70ce, 0x9116, 0x0904, 0x265d, 0x81ff, 0x01a0, - 0x2009, 0x0000, 0x080c, 0x2a65, 0x2011, 0x8011, 0x2019, 0x010e, - 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, - 0x0000, 0x080c, 0x48e9, 0x0448, 0x2001, 0x1978, 0x200c, 0x81ff, - 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, - 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, 0x48e9, 0x080c, 0x0e80, - 0x080c, 0x5393, 0xd0fc, 0x1188, 0x080c, 0xc225, 0x1170, 0x00c6, - 0x080c, 0x26f9, 0x080c, 0x9640, 0x2061, 0x0100, 0x2019, 0x0028, - 0x2009, 0x0002, 0x080c, 0x2fa7, 0x00ce, 0x012e, 0x00fe, 0x00ee, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, - 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, 0x1836, 0x2214, 0xd2ac, - 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181e, 0x2204, 0x9106, 0x1190, - 0x2011, 0x181f, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, - 0x1148, 0x2011, 0x181f, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, - 0x9206, 0x1120, 0x2500, 0x080c, 0x7c40, 0x0048, 0x9584, 0x00ff, - 0x9080, 0x313a, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, - 0x9080, 0x313a, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, - 0x0140, 0x2001, 0x1817, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, - 0x6852, 0x6856, 0x1f04, 0x26a9, 0x00de, 0x0005, 0x0006, 0x00d6, - 0x0026, 0x2069, 0x0140, 0x2001, 0x1817, 0x2102, 0x8114, 0x8214, - 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, - 0x1128, 0x9184, 0x000f, 0x9080, 0xddaa, 0x2005, 0x6856, 0x8211, - 0x1f04, 0x26be, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, - 0x1800, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, - 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, - 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, - 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, - 0x26ee, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, - 0x0005, 0x080c, 0x538f, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, - 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xd54b, 0x004e, 0x0005, - 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, - 0x2765, 0x080c, 0x29c4, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, - 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, - 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, - 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, - 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, - 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, - 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, - 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, 0x8259, 0x928c, 0xff00, - 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, - 0x2009, 0x0138, 0x220a, 0x080c, 0x6f9b, 0x1118, 0x2009, 0x193d, - 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, - 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0dad, - 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, - 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, - 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, - 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, - 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, - 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, - 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1960, - 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0db4, 0x0033, 0x00ee, 0x002e, - 0x001e, 0x000e, 0x015e, 0x0005, 0x27c3, 0x27e1, 0x2805, 0x2807, - 0x2830, 0x2832, 0x2834, 0x2001, 0x0001, 0x080c, 0x260e, 0x080c, - 0x2a22, 0x2001, 0x1962, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, - 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, 0x29e0, 0x2001, 0x1960, - 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2835, 0x080c, 0x80b3, - 0x0005, 0x2009, 0x1965, 0x200b, 0x0000, 0x2001, 0x196a, 0x2003, - 0x0036, 0x2001, 0x1969, 0x2003, 0x002a, 0x2001, 0x1962, 0x2003, - 0x0001, 0x9006, 0x080c, 0x2992, 0x2001, 0xffff, 0x20a9, 0x0009, - 0x080c, 0x29e0, 0x2001, 0x1960, 0x2003, 0x0006, 0x2009, 0x001e, - 0x2011, 0x2835, 0x080c, 0x80b3, 0x0005, 0x080c, 0x0db4, 0x2001, - 0x196a, 0x2003, 0x0036, 0x2001, 0x1962, 0x2003, 0x0003, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2992, 0x2001, 0x1966, 0x2003, 0x0000, 0x2001, - 0xffff, 0x20a9, 0x0009, 0x080c, 0x29e0, 0x2001, 0x1960, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2835, 0x080c, 0x80b3, 0x0005, - 0x080c, 0x0db4, 0x080c, 0x0db4, 0x0005, 0x0006, 0x0016, 0x0026, - 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x2001, 0x1962, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0db4, 0x0043, - 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, - 0x2857, 0x2877, 0x28b7, 0x28e7, 0x290b, 0x291b, 0x291d, 0x080c, - 0x29d4, 0x11b0, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1968, - 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, - 0x0008, 0xc085, 0x200a, 0x2001, 0x1960, 0x2003, 0x0001, 0x0030, - 0x080c, 0x2941, 0x2001, 0xffff, 0x080c, 0x27d2, 0x0005, 0x080c, - 0x291f, 0x05e0, 0x2009, 0x1969, 0x2104, 0x8001, 0x200a, 0x080c, - 0x29d4, 0x1178, 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, 0x1968, 0x2104, 0xc085, - 0x200a, 0x2009, 0x1965, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, - 0x0118, 0x080c, 0x2927, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x29af, 0x2001, 0x1962, 0x2003, 0x0002, 0x0028, 0x2001, - 0x1960, 0x2003, 0x0003, 0x0010, 0x080c, 0x27f4, 0x0005, 0x080c, - 0x291f, 0x0560, 0x2009, 0x1969, 0x2104, 0x8001, 0x200a, 0x080c, - 0x29d4, 0x1168, 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x1960, - 0x2003, 0x0003, 0x2001, 0x1961, 0x2003, 0x0000, 0x00b8, 0x2009, - 0x1969, 0x2104, 0x9005, 0x1118, 0x080c, 0x2964, 0x0010, 0x080c, - 0x2934, 0x080c, 0x2927, 0x2009, 0x1965, 0x200b, 0x0000, 0x2001, - 0x1962, 0x2003, 0x0001, 0x080c, 0x27f4, 0x0000, 0x0005, 0x04b9, - 0x0508, 0x080c, 0x29d4, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, - 0x2009, 0x1966, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, - 0x0078, 0x2001, 0x196b, 0x2003, 0x000a, 0x2009, 0x1968, 0x2104, - 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, 0x1962, 0x2003, 0x0004, - 0x080c, 0x281f, 0x0005, 0x0099, 0x0168, 0x080c, 0x29d4, 0x1138, - 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, 0x280b, 0x0018, 0x0079, - 0x080c, 0x281f, 0x0005, 0x080c, 0x0db4, 0x080c, 0x0db4, 0x2009, - 0x196a, 0x2104, 0x8001, 0x200a, 0x090c, 0x2980, 0x0005, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x29af, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2992, - 0x0005, 0x2009, 0x1965, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, - 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x29af, 0x0005, 0x0086, 0x2001, 0x1968, 0x2004, - 0x9084, 0x7fff, 0x090c, 0x0db4, 0x2009, 0x1967, 0x2144, 0x8846, - 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, - 0x0db4, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, - 0x0006, 0x0156, 0x2001, 0x1960, 0x20a9, 0x0009, 0x2003, 0x0000, - 0x8000, 0x1f04, 0x2986, 0x2001, 0x1967, 0x2003, 0x8000, 0x015e, - 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, - 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x196d, - 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, - 0x783a, 0x2009, 0x196e, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, 0x7838, 0x9084, 0xfffa, - 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, 0x9084, 0xfffb, 0x9085, - 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, - 0x080c, 0x2a5f, 0xd09c, 0x1110, 0x1f04, 0x29d7, 0x015e, 0x0005, - 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x7850, 0x9085, 0x0040, - 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2a5f, 0x9085, - 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, - 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, - 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, - 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x2a0d, 0x080c, - 0x80d5, 0x1f04, 0x2a0d, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfbf, - 0x7852, 0x080c, 0x2a5f, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, - 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, 0x7852, 0x0005, 0x0006, - 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, - 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2a31, 0x0028, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x2a37, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x1d04, 0x2a40, 0x080c, 0x80d5, 0x1f04, 0x2a40, 0x0005, 0x0006, - 0x2001, 0x196c, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x2001, 0x196c, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, - 0x2001, 0x196c, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x1978, - 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, - 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, - 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, 0x200c, 0x918c, 0xff00, - 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, 0x1588, 0x2009, 0x00a2, - 0x080c, 0x0e2f, 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, - 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e, - 0x1db0, 0x9086, 0x0003, 0x11b8, 0x2304, 0x9402, 0x02a0, 0x1d60, - 0x8211, 0x1d68, 0x84ff, 0x0170, 0x2001, 0x0141, 0x200c, 0x918c, - 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x180c, 0x2104, 0xc0dd, - 0x200a, 0x0008, 0x0419, 0x2009, 0x0000, 0x080c, 0x0e2f, 0x004e, - 0x003e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd0dc, 0x01b0, 0x2001, - 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, 0x0141, 0x2004, 0x9084, - 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, 0x2091, 0x8000, 0x0016, - 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, 0x0005, 0x00c6, 0x2061, - 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, 0x2003, 0x0000, 0x6017, - 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, 0x6104, 0x918e, 0x0010, - 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, 0x0040, 0x04b9, 0x001e, - 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016, 0x2019, 0x0141, 0x6124, - 0x918c, 0x0028, 0x1120, 0x2304, 0x9084, 0x2800, 0x0dc0, 0x001e, - 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, 0x9385, 0x0009, 0x6016, - 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, 0x6016, 0x003e, 0x2001, - 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce, 0x0005, 0x0016, 0x0026, - 0x080c, 0x6fb5, 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, - 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, - 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, - 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, - 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, - 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, 0x1128, 0x080c, 0x6fb5, - 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, 0x0005, - 0x2dbc, 0x2dbc, 0x2be0, 0x2be0, 0x2bec, 0x2bec, 0x2bf8, 0x2bf8, - 0x2c06, 0x2c06, 0x2c12, 0x2c12, 0x2c20, 0x2c20, 0x2c2e, 0x2c2e, - 0x2c40, 0x2c40, 0x2c4c, 0x2c4c, 0x2c5a, 0x2c5a, 0x2c78, 0x2c78, - 0x2c98, 0x2c98, 0x2c68, 0x2c68, 0x2c88, 0x2c88, 0x2ca6, 0x2ca6, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2cb8, 0x2cb8, 0x2cc4, 0x2cc4, 0x2cd2, 0x2cd2, 0x2ce0, 0x2ce0, - 0x2cf0, 0x2cf0, 0x2cfe, 0x2cfe, 0x2d0e, 0x2d0e, 0x2d1e, 0x2d1e, - 0x2d30, 0x2d30, 0x2d3e, 0x2d3e, 0x2d4e, 0x2d4e, 0x2d70, 0x2d70, - 0x2d92, 0x2d92, 0x2d5e, 0x2d5e, 0x2d81, 0x2d81, 0x2da1, 0x2da1, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, 0x2c3e, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2315, 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x212d, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x212d, 0x080c, 0x2315, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2168, - 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2315, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x212d, 0x080c, 0x2168, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x212d, - 0x080c, 0x2315, 0x080c, 0x2168, 0x0804, 0x2db4, 0xa001, 0x0cf0, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x130c, 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2315, 0x080c, 0x130c, - 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x212d, 0x080c, 0x130c, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2315, 0x080c, 0x130c, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x212d, 0x080c, 0x2315, 0x080c, 0x130c, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x212d, 0x080c, 0x130c, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x130c, 0x080c, 0x2168, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x212d, - 0x080c, 0x2315, 0x080c, 0x130c, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2768, 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, 0x080c, 0x2315, - 0x0804, 0x2db4, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2768, 0x080c, 0x212d, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2768, 0x080c, 0x212d, 0x080c, 0x2315, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2768, 0x080c, 0x2168, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x2315, 0x080c, 0x2168, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x212d, 0x080c, 0x2168, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x212d, 0x080c, 0x2315, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2768, 0x080c, 0x130c, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x2315, 0x080c, 0x130c, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x212d, 0x080c, 0x130c, 0x0804, 0x2db4, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2768, - 0x080c, 0x2315, 0x080c, 0x130c, 0x080c, 0x2168, 0x0804, 0x2db4, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2768, 0x080c, 0x212d, 0x080c, 0x2315, 0x080c, 0x130c, - 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2768, 0x080c, 0x212d, 0x080c, 0x130c, 0x080c, - 0x2168, 0x0410, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2768, 0x080c, 0x130c, 0x080c, 0x2168, - 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2768, 0x080c, 0x212d, 0x080c, 0x2315, 0x080c, - 0x130c, 0x080c, 0x2168, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, - 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00b6, 0x00c6, 0x0026, - 0x0046, 0x9026, 0x080c, 0x6529, 0x1904, 0x2ec3, 0x72d8, 0x2001, - 0x194c, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, - 0xd2bc, 0x1904, 0x2ec3, 0x080c, 0x2ec8, 0x0804, 0x2ec3, 0xd2cc, - 0x1904, 0x2ec3, 0x080c, 0x6f9b, 0x1120, 0x70ab, 0xffff, 0x0804, - 0x2ec3, 0xd294, 0x0120, 0x70ab, 0xffff, 0x0804, 0x2ec3, 0x080c, - 0x3130, 0x0160, 0x080c, 0xc22c, 0x0128, 0x2001, 0x1817, 0x203c, - 0x0804, 0x2e55, 0x70ab, 0xffff, 0x0804, 0x2ec3, 0x2001, 0x1817, - 0x203c, 0x7290, 0xd284, 0x0904, 0x2e55, 0xd28c, 0x1904, 0x2e55, - 0x0036, 0x73a8, 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, - 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, - 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x05a8, 0x908e, 0x0000, - 0x0590, 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1588, 0x7290, - 0xc28d, 0x7292, 0x70ab, 0xffff, 0x003e, 0x0478, 0x0026, 0x2011, - 0x0010, 0x080c, 0x658f, 0x002e, 0x0118, 0x70ab, 0xffff, 0x0410, - 0x900e, 0x080c, 0x2665, 0x080c, 0x61e7, 0x11c0, 0x080c, 0x656b, - 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, 0x0138, 0x080c, - 0x6467, 0x0120, 0x080c, 0x2ee1, 0x0148, 0x0028, 0x080c, 0x3021, - 0x080c, 0x2f0d, 0x0118, 0x8318, 0x0804, 0x2e07, 0x73aa, 0x0010, - 0x70ab, 0xffff, 0x003e, 0x0804, 0x2ec3, 0x9780, 0x313a, 0x203d, - 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70a8, 0x9096, 0xffff, - 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, - 0x20a8, 0x0020, 0x70ab, 0xffff, 0x0804, 0x2ec3, 0x2700, 0x0156, - 0x0016, 0x9106, 0x0904, 0x2eb8, 0x0026, 0x2011, 0x0010, 0x080c, - 0x658f, 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x2ec0, 0xc484, - 0x080c, 0x6247, 0x0138, 0x080c, 0xc22c, 0x1590, 0x080c, 0x61e7, - 0x15b8, 0x0008, 0xc485, 0x080c, 0x656b, 0x1130, 0x7030, 0xd08c, - 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7290, 0xd28c, 0x0180, 0x080c, - 0x656b, 0x9082, 0x0006, 0x02e0, 0xd484, 0x1118, 0x080c, 0x620b, - 0x0028, 0x080c, 0x30ac, 0x01a0, 0x080c, 0x30d7, 0x0088, 0x080c, - 0x3021, 0x080c, 0xc22c, 0x1160, 0x080c, 0x2f0d, 0x0188, 0x0040, - 0x080c, 0xc22c, 0x1118, 0x080c, 0x30ac, 0x0110, 0x0451, 0x0140, - 0x001e, 0x8108, 0x015e, 0x1f04, 0x2e6e, 0x70ab, 0xffff, 0x0018, - 0x001e, 0x015e, 0x71aa, 0x004e, 0x002e, 0x00ce, 0x00be, 0x0005, - 0x00c6, 0x0016, 0x70ab, 0x0001, 0x2009, 0x007e, 0x080c, 0x61e7, - 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, 0x080c, 0x3021, 0x04a9, - 0x0128, 0x70d8, 0xc0bd, 0x70da, 0x080c, 0xbf7d, 0x001e, 0x00ce, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x1858, 0x2004, - 0x9084, 0x00ff, 0xb842, 0x080c, 0x9e8f, 0x01d0, 0x2b00, 0x6012, - 0x080c, 0xbfa6, 0x6023, 0x0001, 0x9006, 0x080c, 0x6184, 0x2001, - 0x0000, 0x080c, 0x6198, 0x0126, 0x2091, 0x8000, 0x70a4, 0x8000, - 0x70a6, 0x012e, 0x2009, 0x0004, 0x080c, 0x9ebc, 0x9085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x2001, 0x1858, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, - 0x9e8f, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, 0xb8a0, - 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1110, 0x080c, 0x2fdc, 0x080c, 0xbfa6, 0x6023, 0x0001, 0x9006, - 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, 0x0126, 0x2091, - 0x8000, 0x70a4, 0x8000, 0x70a6, 0x012e, 0x2009, 0x0002, 0x080c, - 0x9ebc, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, - 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, 0x080c, 0x61e7, 0x1140, - 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70df, 0xffff, - 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, - 0x080c, 0x9dec, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xbfa6, 0x6023, - 0x0001, 0x9006, 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, - 0x0126, 0x2091, 0x8000, 0x70e0, 0x8000, 0x70e2, 0x012e, 0x2009, - 0x0002, 0x080c, 0x9ebc, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, - 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2009, - 0x007f, 0x080c, 0x61e7, 0x11b8, 0xb813, 0x00ff, 0xb817, 0xfffd, - 0xb8bf, 0x0004, 0x080c, 0x9dec, 0x0170, 0x2b00, 0x6012, 0x6316, - 0x6023, 0x0001, 0x620a, 0x080c, 0xbfa6, 0x2009, 0x0022, 0x080c, - 0x9ebc, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, - 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, 0x21f0, 0x080c, 0x856f, - 0x080c, 0x84f9, 0x080c, 0x9c95, 0x080c, 0xad8a, 0x3e08, 0x2130, - 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, 0x007f, - 0x900e, 0x0016, 0x080c, 0x6247, 0x1140, 0x9686, 0x0002, 0x1118, - 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5cf4, 0x001e, 0x8108, 0x1f04, - 0x2fc1, 0x9686, 0x0001, 0x190c, 0x3104, 0x00be, 0x002e, 0x003e, - 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, 0x0036, - 0x0026, 0x0016, 0x00b6, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, - 0x0029, 0x080c, 0x8564, 0x0076, 0x2039, 0x0000, 0x080c, 0x8452, - 0x2c08, 0x080c, 0xd2bc, 0x007e, 0x001e, 0xba10, 0xbb14, 0xbcb0, - 0x080c, 0x5cf4, 0xba12, 0xbb16, 0xbcb2, 0x00be, 0x001e, 0x002e, - 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, - 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, - 0x1800, 0x70a4, 0x9005, 0x0110, 0x8001, 0x70a6, 0x000e, 0x00ee, - 0x0005, 0x2071, 0x1800, 0x70e0, 0x9005, 0x0dc0, 0x8001, 0x70e2, - 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, - 0x1118, 0x20a9, 0x0001, 0x0070, 0x080c, 0x538f, 0xd0c4, 0x0138, - 0x0030, 0x9006, 0x2020, 0x2009, 0x002d, 0x080c, 0xd54b, 0x20a9, - 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, 0x0904, 0x308b, 0x928e, - 0x007f, 0x0904, 0x308b, 0x928e, 0x0080, 0x05e8, 0x9288, 0x1000, - 0x210c, 0x81ff, 0x05c0, 0x8fff, 0x1148, 0x2001, 0x195e, 0x0006, - 0x2003, 0x0001, 0x04f1, 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, - 0x2158, 0x2001, 0x0001, 0x080c, 0x6535, 0x00ce, 0x00be, 0x2019, - 0x0029, 0x080c, 0x8564, 0x0076, 0x2039, 0x0000, 0x080c, 0x8452, - 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, - 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, - 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, - 0xd2bc, 0x001e, 0x007e, 0x002e, 0x8210, 0x1f04, 0x3042, 0x015e, - 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, 0x538f, 0xd0c4, 0x0140, - 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xd54b, - 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x7290, 0x82ff, 0x01e8, 0x080c, 0x6563, 0x11d0, 0x2100, 0x080c, - 0x2698, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, - 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, - 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, - 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, - 0x003e, 0x9180, 0x1000, 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, - 0x2061, 0x1a7f, 0x001e, 0x6112, 0x080c, 0x2fdc, 0x001e, 0x080c, - 0x620b, 0x012e, 0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, - 0x080c, 0x992c, 0x080c, 0xd803, 0x002e, 0x001e, 0x0005, 0x2001, - 0x1836, 0x2004, 0xd0cc, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x6f9b, - 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x6f9b, - 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, - 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x620b, - 0x8108, 0x1f04, 0x3115, 0x2061, 0x1800, 0x607b, 0x0000, 0x607c, - 0x9084, 0x00ff, 0x607e, 0x60af, 0x0000, 0x00be, 0x00ce, 0x0005, - 0x2001, 0x1875, 0x2004, 0xd0bc, 0x0005, 0x2011, 0x1854, 0x2214, - 0xd2ec, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, - 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, - 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, - 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, - 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, - 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, - 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, - 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, - 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, - 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, - 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, - 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, - 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, - 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, - 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, - 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, - 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, - 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, - 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, - 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, - 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, - 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, - 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, - 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, - 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, - 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, - 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x2b31, 0x00de, 0x00c6, 0x2061, 0x19bf, 0x6044, 0x080c, 0xc23b, + 0x0120, 0x909a, 0x0003, 0x1628, 0x0018, 0x909a, 0x00c8, 0x1608, + 0x8000, 0x6046, 0x603c, 0x00ce, 0x9005, 0x0558, 0x2009, 0x07d0, + 0x080c, 0x80c4, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, + 0x6114, 0x918c, 0x1984, 0x918d, 0x0012, 0x6116, 0x00d0, 0x6114, + 0x918c, 0x1984, 0x918d, 0x0016, 0x6116, 0x0098, 0x6027, 0x0004, + 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x96e9, 0x003e, 0x2019, + 0x19ce, 0x2304, 0x9065, 0x0120, 0x2009, 0x004f, 0x080c, 0x9ea9, + 0x00ce, 0x001e, 0xd19c, 0x0904, 0x2614, 0x7038, 0xd0ac, 0x1904, + 0x25e9, 0x0016, 0x0156, 0x6027, 0x0008, 0x6050, 0x9085, 0x0040, + 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2a6a, 0x9085, + 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x25bc, 0x080c, 0x80f3, + 0x1f04, 0x25bc, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, + 0x20a9, 0x0028, 0xa001, 0x1f04, 0x25ca, 0x6150, 0x9185, 0x1400, + 0x6052, 0x20a9, 0x0366, 0x1d04, 0x25d3, 0x080c, 0x80f3, 0x6020, + 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x04a0, + 0x080c, 0x2a32, 0x1f04, 0x25d3, 0x015e, 0x6152, 0x001e, 0x6027, + 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0x9db5, 0x60e3, + 0x0000, 0x080c, 0xd8ee, 0x080c, 0xd909, 0x080c, 0x539e, 0xd0fc, + 0x1138, 0x080c, 0xc234, 0x1120, 0x9085, 0x0001, 0x080c, 0x6ff1, + 0x9006, 0x080c, 0x2b21, 0x2009, 0x0002, 0x080c, 0x2a70, 0x00e6, + 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0e80, 0x00ee, 0x6027, + 0x0008, 0x080c, 0x0b8f, 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x1800, 0x71cc, 0x70ce, 0x9116, 0x0904, + 0x2668, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x2a70, 0x2011, + 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, + 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x48f4, 0x0448, 0x2001, + 0x1980, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, + 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, + 0x48f4, 0x080c, 0x0e80, 0x080c, 0x539e, 0xd0fc, 0x1188, 0x080c, + 0xc234, 0x1170, 0x00c6, 0x080c, 0x2704, 0x080c, 0x9650, 0x2061, + 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x2fb2, 0x00ce, + 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, + 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, + 0x1836, 0x2214, 0xd2ac, 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181e, + 0x2204, 0x9106, 0x1190, 0x2011, 0x181f, 0x2214, 0x9294, 0xff00, + 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, 0x181f, 0x2214, 0x9294, + 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, 0x2500, 0x080c, 0x7c4e, + 0x0048, 0x9584, 0x00ff, 0x9080, 0x3145, 0x200d, 0x918c, 0xff00, + 0x810f, 0x9006, 0x0005, 0x9080, 0x3145, 0x200d, 0x918c, 0x00ff, + 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1817, 0x2003, 0x00ef, + 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x26b4, 0x00de, + 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0x1817, + 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, + 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, 0xddc3, + 0x2005, 0x6856, 0x8211, 0x1f04, 0x26c9, 0x002e, 0x00de, 0x000e, + 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, 0x0110, 0xc09d, 0x0008, + 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, + 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, + 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, + 0x0404, 0x680e, 0x1f04, 0x26f9, 0x680f, 0x0000, 0x000e, 0x001e, + 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, 0x539a, 0xd0c4, 0x0150, + 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, + 0xd564, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, + 0x78c4, 0xd0dc, 0x0904, 0x2770, 0x080c, 0x29cf, 0x0660, 0x9084, + 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, + 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, + 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, + 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, + 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, + 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, + 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, + 0x8277, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, + 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, 0x6faa, + 0x1118, 0x2009, 0x1945, 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, + 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, + 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, + 0x0110, 0x080c, 0x0dad, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, + 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, + 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, + 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, + 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, + 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, + 0x00e6, 0x2001, 0x1968, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0db4, + 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, 0x27ce, + 0x27ec, 0x2810, 0x2812, 0x283b, 0x283d, 0x283f, 0x2001, 0x0001, + 0x080c, 0x2619, 0x080c, 0x2a2d, 0x2001, 0x196a, 0x2003, 0x0000, + 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, + 0x29eb, 0x2001, 0x1968, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, + 0x2840, 0x080c, 0x80d1, 0x0005, 0x2009, 0x196d, 0x200b, 0x0000, + 0x2001, 0x1972, 0x2003, 0x0036, 0x2001, 0x1971, 0x2003, 0x002a, + 0x2001, 0x196a, 0x2003, 0x0001, 0x9006, 0x080c, 0x299d, 0x2001, + 0xffff, 0x20a9, 0x0009, 0x080c, 0x29eb, 0x2001, 0x1968, 0x2003, + 0x0006, 0x2009, 0x001e, 0x2011, 0x2840, 0x080c, 0x80d1, 0x0005, + 0x080c, 0x0db4, 0x2001, 0x1972, 0x2003, 0x0036, 0x2001, 0x196a, + 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x299d, 0x2001, 0x196e, + 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x29eb, + 0x2001, 0x1968, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2840, + 0x080c, 0x80d1, 0x0005, 0x080c, 0x0db4, 0x080c, 0x0db4, 0x0005, + 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, + 0x8000, 0x2079, 0x0100, 0x2001, 0x196a, 0x2004, 0x908a, 0x0007, + 0x1a0c, 0x0db4, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, + 0x001e, 0x000e, 0x0005, 0x2862, 0x2882, 0x28c2, 0x28f2, 0x2916, + 0x2926, 0x2928, 0x080c, 0x29df, 0x11b0, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2009, 0x1970, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, + 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1968, + 0x2003, 0x0001, 0x0030, 0x080c, 0x294c, 0x2001, 0xffff, 0x080c, + 0x27dd, 0x0005, 0x080c, 0x292a, 0x05e0, 0x2009, 0x1971, 0x2104, + 0x8001, 0x200a, 0x080c, 0x29df, 0x1178, 0x7850, 0x9084, 0xefff, + 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, + 0x1970, 0x2104, 0xc085, 0x200a, 0x2009, 0x196d, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x2932, 0x00c0, 0x200b, + 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, + 0x0010, 0x2001, 0x0001, 0x080c, 0x29ba, 0x2001, 0x196a, 0x2003, + 0x0002, 0x0028, 0x2001, 0x1968, 0x2003, 0x0003, 0x0010, 0x080c, + 0x27ff, 0x0005, 0x080c, 0x292a, 0x0560, 0x2009, 0x1971, 0x2104, + 0x8001, 0x200a, 0x080c, 0x29df, 0x1168, 0x7850, 0x9084, 0xefff, + 0x7852, 0x2001, 0x1968, 0x2003, 0x0003, 0x2001, 0x1969, 0x2003, + 0x0000, 0x00b8, 0x2009, 0x1971, 0x2104, 0x9005, 0x1118, 0x080c, + 0x296f, 0x0010, 0x080c, 0x293f, 0x080c, 0x2932, 0x2009, 0x196d, + 0x200b, 0x0000, 0x2001, 0x196a, 0x2003, 0x0001, 0x080c, 0x27ff, + 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x29df, 0x11b8, 0x7850, + 0x9084, 0xefff, 0x7852, 0x2009, 0x196e, 0x2104, 0x8000, 0x200a, + 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x1973, 0x2003, 0x000a, + 0x2009, 0x1970, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, + 0x196a, 0x2003, 0x0004, 0x080c, 0x282a, 0x0005, 0x0099, 0x0168, + 0x080c, 0x29df, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, + 0x2816, 0x0018, 0x0079, 0x080c, 0x282a, 0x0005, 0x080c, 0x0db4, + 0x080c, 0x0db4, 0x2009, 0x1972, 0x2104, 0x8001, 0x200a, 0x090c, + 0x298b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ba, 0x0005, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, + 0x0001, 0x080c, 0x299d, 0x0005, 0x2009, 0x196d, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, + 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, + 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ba, 0x0005, 0x0086, + 0x2001, 0x1970, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0db4, 0x2009, + 0x196f, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, + 0xd084, 0x1120, 0x080c, 0x0db4, 0x9006, 0x0010, 0x2001, 0x0001, + 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1968, 0x20a9, + 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x2991, 0x2001, 0x196f, + 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, + 0x783a, 0x2009, 0x1975, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, + 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x1976, 0x210c, 0x795a, + 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, + 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, + 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, + 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, + 0x2001, 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, + 0x20a9, 0x0064, 0x7820, 0x080c, 0x2a6a, 0xd09c, 0x1110, 0x1f04, + 0x29e2, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, + 0x7850, 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, + 0x080c, 0x2a6a, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, + 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, + 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, + 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, + 0x1d04, 0x2a18, 0x080c, 0x80f3, 0x1f04, 0x2a18, 0x7850, 0x9085, + 0x0400, 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2a6a, 0x9085, 0x1000, + 0x7852, 0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, + 0x7852, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, + 0x000a, 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, + 0x2a3c, 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2a42, 0x00fe, + 0x015e, 0x000e, 0x0005, 0x1d04, 0x2a4b, 0x080c, 0x80f3, 0x1f04, + 0x2a4b, 0x0005, 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0000, + 0x000e, 0x0005, 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0001, + 0x000e, 0x0005, 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0002, + 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, + 0x0006, 0x2001, 0x1980, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, + 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, + 0xa001, 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, + 0x200c, 0x918c, 0xff00, 0x9186, 0x2000, 0x0118, 0x9186, 0x0100, + 0x1588, 0x2009, 0x00a2, 0x080c, 0x0e2f, 0x2019, 0x0160, 0x2324, + 0x2011, 0x0003, 0x2009, 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, + 0x918c, 0x0007, 0x910e, 0x1db0, 0x9086, 0x0003, 0x11b8, 0x2304, + 0x9402, 0x02a0, 0x1d60, 0x8211, 0x1d68, 0x84ff, 0x0170, 0x2001, + 0x0141, 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, + 0x180c, 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0419, 0x2009, 0x0000, + 0x080c, 0x0e2f, 0x004e, 0x003e, 0x0005, 0x2001, 0x180c, 0x2004, + 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, + 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, + 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, + 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, + 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, + 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, + 0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016, + 0x2019, 0x0141, 0x6124, 0x918c, 0x0028, 0x1120, 0x2304, 0x9084, + 0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, + 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, + 0x6016, 0x003e, 0x2001, 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce, + 0x0005, 0x0016, 0x0026, 0x080c, 0x6fc4, 0x0108, 0xc0bc, 0x2009, + 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, + 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, + 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, + 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, + 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, + 0x1128, 0x080c, 0x6fc4, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, + 0x001e, 0x000e, 0x0005, 0x2dc7, 0x2dc7, 0x2beb, 0x2beb, 0x2bf7, + 0x2bf7, 0x2c03, 0x2c03, 0x2c11, 0x2c11, 0x2c1d, 0x2c1d, 0x2c2b, + 0x2c2b, 0x2c39, 0x2c39, 0x2c4b, 0x2c4b, 0x2c57, 0x2c57, 0x2c65, + 0x2c65, 0x2c83, 0x2c83, 0x2ca3, 0x2ca3, 0x2c73, 0x2c73, 0x2c93, + 0x2c93, 0x2cb1, 0x2cb1, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2cc3, 0x2cc3, 0x2ccf, 0x2ccf, 0x2cdd, + 0x2cdd, 0x2ceb, 0x2ceb, 0x2cfb, 0x2cfb, 0x2d09, 0x2d09, 0x2d19, + 0x2d19, 0x2d29, 0x2d29, 0x2d3b, 0x2d3b, 0x2d49, 0x2d49, 0x2d59, + 0x2d59, 0x2d7b, 0x2d7b, 0x2d9d, 0x2d9d, 0x2d69, 0x2d69, 0x2d8c, + 0x2d8c, 0x2dac, 0x2dac, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, 0x2c49, + 0x2c49, 0x2c49, 0x2c49, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2320, 0x0804, 0x2dbf, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x2138, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2138, 0x080c, 0x2320, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2320, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2138, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2138, 0x080c, 0x2320, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x130c, 0x0804, 0x2dbf, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x2320, 0x080c, 0x130c, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2138, 0x080c, + 0x130c, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2320, 0x080c, 0x130c, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2138, 0x080c, 0x2320, 0x080c, + 0x130c, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2138, 0x080c, 0x130c, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x130c, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2138, 0x080c, 0x2320, 0x080c, 0x130c, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x0804, 0x2dbf, 0x0106, + 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, + 0x2773, 0x080c, 0x2320, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, + 0x2138, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, 0x080c, + 0x2320, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2320, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, 0x080c, 0x2173, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, 0x080c, 0x2320, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x130c, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2320, 0x080c, 0x130c, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, 0x080c, 0x130c, 0x0804, + 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x0156, 0x080c, 0x2773, 0x080c, 0x2320, 0x080c, 0x130c, 0x080c, + 0x2173, 0x0804, 0x2dbf, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, 0x080c, + 0x2320, 0x080c, 0x130c, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, + 0x080c, 0x130c, 0x080c, 0x2173, 0x0410, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, + 0x130c, 0x080c, 0x2173, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2773, 0x080c, 0x2138, + 0x080c, 0x2320, 0x080c, 0x130c, 0x080c, 0x2173, 0x0000, 0x015e, + 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, + 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6538, 0x1904, + 0x2ece, 0x72d8, 0x2001, 0x1954, 0x2004, 0x9005, 0x1110, 0xd29c, + 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2ece, 0x080c, 0x2ed3, + 0x0804, 0x2ece, 0xd2cc, 0x1904, 0x2ece, 0x080c, 0x6faa, 0x1120, + 0x70ab, 0xffff, 0x0804, 0x2ece, 0xd294, 0x0120, 0x70ab, 0xffff, + 0x0804, 0x2ece, 0x080c, 0x313b, 0x0160, 0x080c, 0xc23b, 0x0128, + 0x2001, 0x1817, 0x203c, 0x0804, 0x2e60, 0x70ab, 0xffff, 0x0804, + 0x2ece, 0x2001, 0x1817, 0x203c, 0x7290, 0xd284, 0x0904, 0x2e60, + 0xd28c, 0x1904, 0x2e60, 0x0036, 0x73a8, 0x938e, 0xffff, 0x1110, + 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001, + 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, + 0x05a8, 0x908e, 0x0000, 0x0590, 0x908e, 0x00ff, 0x1150, 0x7230, + 0xd284, 0x1588, 0x7290, 0xc28d, 0x7292, 0x70ab, 0xffff, 0x003e, + 0x0478, 0x0026, 0x2011, 0x0010, 0x080c, 0x659e, 0x002e, 0x0118, + 0x70ab, 0xffff, 0x0410, 0x900e, 0x080c, 0x2670, 0x080c, 0x61f6, + 0x11c0, 0x080c, 0x657a, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, + 0xd0bc, 0x0138, 0x080c, 0x6476, 0x0120, 0x080c, 0x2eec, 0x0148, + 0x0028, 0x080c, 0x302c, 0x080c, 0x2f18, 0x0118, 0x8318, 0x0804, + 0x2e12, 0x73aa, 0x0010, 0x70ab, 0xffff, 0x003e, 0x0804, 0x2ece, + 0x9780, 0x3145, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, + 0x70a8, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, + 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70ab, 0xffff, 0x0804, + 0x2ece, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x2ec3, 0x0026, + 0x2011, 0x0010, 0x080c, 0x659e, 0x002e, 0x0120, 0x2009, 0xffff, + 0x0804, 0x2ecb, 0xc484, 0x080c, 0x6256, 0x0138, 0x080c, 0xc23b, + 0x1590, 0x080c, 0x61f6, 0x15b8, 0x0008, 0xc485, 0x080c, 0x657a, + 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7290, + 0xd28c, 0x0180, 0x080c, 0x657a, 0x9082, 0x0006, 0x02e0, 0xd484, + 0x1118, 0x080c, 0x621a, 0x0028, 0x080c, 0x30b7, 0x01a0, 0x080c, + 0x30e2, 0x0088, 0x080c, 0x302c, 0x080c, 0xc23b, 0x1160, 0x080c, + 0x2f18, 0x0188, 0x0040, 0x080c, 0xc23b, 0x1118, 0x080c, 0x30b7, + 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2e79, + 0x70ab, 0xffff, 0x0018, 0x001e, 0x015e, 0x71aa, 0x004e, 0x002e, + 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70ab, 0x0001, 0x2009, + 0x007e, 0x080c, 0x61f6, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, + 0x080c, 0x302c, 0x04a9, 0x0128, 0x70d8, 0xc0bd, 0x70da, 0x080c, + 0xbf8c, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, + 0x2001, 0x1860, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0x9e7c, + 0x01d0, 0x2b00, 0x6012, 0x080c, 0xbfb5, 0x6023, 0x0001, 0x9006, + 0x080c, 0x6193, 0x2001, 0x0000, 0x080c, 0x61a7, 0x0126, 0x2091, + 0x8000, 0x70a4, 0x8000, 0x70a6, 0x012e, 0x2009, 0x0004, 0x080c, + 0x9ea9, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, + 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x1860, 0x2004, 0x9084, + 0x00ff, 0xb842, 0x080c, 0x9e7c, 0x0548, 0x2b00, 0x6012, 0xb800, + 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x2fe7, 0x080c, 0xbfb5, + 0x6023, 0x0001, 0x9006, 0x080c, 0x6193, 0x2001, 0x0002, 0x080c, + 0x61a7, 0x0126, 0x2091, 0x8000, 0x70a4, 0x8000, 0x70a6, 0x012e, + 0x2009, 0x0002, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x00ce, 0x00de, + 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, + 0x080c, 0x61f6, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, + 0x0110, 0x70df, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, + 0x0076, 0x00d6, 0x00c6, 0x080c, 0x9dd9, 0x01d0, 0x2b00, 0x6012, + 0x080c, 0xbfb5, 0x6023, 0x0001, 0x9006, 0x080c, 0x6193, 0x2001, + 0x0002, 0x080c, 0x61a7, 0x0126, 0x2091, 0x8000, 0x70e0, 0x8000, + 0x70e2, 0x012e, 0x2009, 0x0002, 0x080c, 0x9ea9, 0x9085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x61f6, 0x11b8, 0xb813, + 0x00ff, 0xb817, 0xfffd, 0xb8bf, 0x0004, 0x080c, 0x9dd9, 0x0170, + 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xbfb5, + 0x2009, 0x0022, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x012e, 0x00de, + 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, + 0x21f0, 0x080c, 0x858d, 0x080c, 0x8517, 0x080c, 0x9c82, 0x080c, + 0xad86, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, + 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6256, 0x1140, + 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5cff, + 0x001e, 0x8108, 0x1f04, 0x2fcc, 0x9686, 0x0001, 0x190c, 0x310f, + 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, + 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210, 0x2258, + 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x8582, 0x0076, 0x2039, + 0x0000, 0x080c, 0x8470, 0x2c08, 0x080c, 0xd2d5, 0x007e, 0x001e, + 0xba10, 0xbb14, 0xbcb0, 0x080c, 0x5cff, 0xba12, 0xbb16, 0xbcb2, + 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, + 0x0080, 0x0150, 0x2071, 0x1800, 0x70a4, 0x9005, 0x0110, 0x8001, + 0x70a6, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e0, 0x9005, + 0x0dc0, 0x8001, 0x70e2, 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, + 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, + 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0070, 0x080c, + 0x539a, 0xd0c4, 0x0138, 0x0030, 0x9006, 0x2020, 0x2009, 0x002d, + 0x080c, 0xd564, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, + 0x0904, 0x3096, 0x928e, 0x007f, 0x0904, 0x3096, 0x928e, 0x0080, + 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c0, 0x8fff, 0x1148, + 0x2001, 0x1966, 0x0006, 0x2003, 0x0001, 0x04f1, 0x000e, 0x2003, + 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, 0x6544, + 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x8582, 0x0076, 0x2039, + 0x0000, 0x080c, 0x8470, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, + 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, + 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, 0x00be, + 0x0016, 0x2c08, 0x080c, 0xd2d5, 0x001e, 0x007e, 0x002e, 0x8210, + 0x1f04, 0x304d, 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x080c, + 0x539a, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2220, 0x2009, + 0x0029, 0x080c, 0xd564, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, + 0x0026, 0x0036, 0x00c6, 0x7290, 0x82ff, 0x01e8, 0x080c, 0x6572, + 0x11d0, 0x2100, 0x080c, 0x26a3, 0x81ff, 0x01b8, 0x2019, 0x0001, + 0x8314, 0x92e0, 0x1c80, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, + 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, + 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0036, + 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000, 0x2004, 0x9065, + 0x0158, 0x0016, 0x00c6, 0x2061, 0x1a87, 0x001e, 0x6112, 0x080c, + 0x2fe7, 0x001e, 0x080c, 0x621a, 0x012e, 0x00ce, 0x001e, 0x0005, + 0x0016, 0x0026, 0x2110, 0x080c, 0x9915, 0x080c, 0xd81c, 0x002e, + 0x001e, 0x0005, 0x2001, 0x1836, 0x2004, 0xd0cc, 0x0005, 0x00c6, + 0x00b6, 0x080c, 0x6faa, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, + 0x0782, 0x080c, 0x6faa, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, + 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, 0x0110, 0xb800, + 0xd0bc, 0x090c, 0x621a, 0x8108, 0x1f04, 0x3120, 0x2061, 0x1800, + 0x607b, 0x0000, 0x607c, 0x9084, 0x00ff, 0x607e, 0x60af, 0x0000, + 0x00be, 0x00ce, 0x0005, 0x2001, 0x187d, 0x2004, 0xd0bc, 0x0005, + 0x2011, 0x185c, 0x2214, 0xd2ec, 0x0005, 0x7eef, 0x7de8, 0x7ce4, + 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, + 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, + 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, 0x80ba, + 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, 0x80ae, + 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, + 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, 0x6690, + 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, 0x607a, + 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, 0x806e, + 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, 0x5965, + 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, 0x5353, + 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, 0x4d49, + 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, 0x8036, + 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, 0x462c, + 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, 0x401f, + 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, 0x3a08, + 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, 0x3600, + 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, 0x8000, + 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, 0x8000, + 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, 0x2600, + 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, 0x2000, + 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, 0x1a00, + 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, 0x1300, + 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, 0x0d00, + 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, 0x0700, + 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, 0x0300, + 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x2071, 0x1894, 0x7003, 0x0002, 0x9006, 0x7016, - 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, 0x7046, 0x703b, 0x18b0, - 0x703f, 0x18b0, 0x7007, 0x0001, 0x080c, 0x1004, 0x090c, 0x0db4, - 0x2900, 0x706a, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1004, - 0x090c, 0x0db4, 0x2900, 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, - 0x0005, 0x2071, 0x1894, 0x7004, 0x0002, 0x3269, 0x326a, 0x327d, - 0x3291, 0x0005, 0x1004, 0x327a, 0x0e04, 0x327a, 0x2079, 0x0000, - 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, - 0x012e, 0x0468, 0x0005, 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, - 0x18ae, 0x2c4c, 0xa86c, 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, - 0x0904, 0x3365, 0x0005, 0x7018, 0x2048, 0x2061, 0x1800, 0x701c, - 0x0807, 0x7014, 0x2048, 0xa864, 0x9094, 0x00ff, 0x9296, 0x0029, - 0x1120, 0xaa78, 0xd2fc, 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, - 0x0005, 0x2079, 0x0000, 0x2061, 0x1800, 0x701c, 0x0807, 0x2061, - 0x1800, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, 0x2100, - 0x908a, 0x003f, 0x1a04, 0x3362, 0x61cc, 0x0804, 0x32f7, 0x3339, - 0x3371, 0x3362, 0x337b, 0x3385, 0x338b, 0x338f, 0x339f, 0x33a3, - 0x33b9, 0x33bf, 0x33c5, 0x33d0, 0x33db, 0x33ea, 0x33f9, 0x3407, - 0x341e, 0x3439, 0x3362, 0x34e2, 0x3520, 0x35c6, 0x35d7, 0x35fa, - 0x3362, 0x3362, 0x3362, 0x3632, 0x364e, 0x3657, 0x3686, 0x368c, - 0x3362, 0x36d2, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x36dd, - 0x36e6, 0x36ee, 0x36f0, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, - 0x3362, 0x371c, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x3739, - 0x3794, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x0002, - 0x37be, 0x37c1, 0x3820, 0x3839, 0x3869, 0x3b07, 0x3362, 0x4f68, - 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, 0x3362, - 0x33b9, 0x33bf, 0x4028, 0x53b3, 0x403e, 0x4ff7, 0x5048, 0x514b, - 0x3362, 0x51ad, 0x51e9, 0x521a, 0x531e, 0x5247, 0x529e, 0x3362, - 0x4042, 0x41e3, 0x41f9, 0x421e, 0x4283, 0x42f7, 0x4317, 0x438e, - 0x43ea, 0x4446, 0x4449, 0x446e, 0x450e, 0x4574, 0x457c, 0x46ae, - 0x4813, 0x4847, 0x4a91, 0x3362, 0x4aaf, 0x4b6b, 0x4c41, 0x3362, - 0x3362, 0x3362, 0x3362, 0x4ca7, 0x4cc2, 0x457c, 0x4f08, 0x714c, - 0x0000, 0x2021, 0x4000, 0x080c, 0x48c5, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x3343, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, - 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, - 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x1187, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, - 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, - 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, - 0x0850, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x48d2, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, - 0x7a8c, 0x7884, 0x7990, 0x0804, 0x48d5, 0x7984, 0x7888, 0x2114, - 0x200a, 0x0804, 0x3339, 0x7984, 0x2114, 0x0804, 0x3339, 0x20e1, - 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, - 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x3339, 0x7884, - 0x2060, 0x0804, 0x33ec, 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, - 0x001e, 0x789b, 0x0317, 0x7893, 0xffff, 0x2001, 0x1885, 0x2004, - 0x9005, 0x0118, 0x7896, 0x0804, 0x3339, 0x7897, 0x0001, 0x0804, - 0x3339, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x3375, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x337f, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x336e, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x3375, - 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x336e, 0x2138, 0x7d98, - 0x7c9c, 0x0804, 0x337f, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x336e, 0x21e8, 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, - 0x0804, 0x3339, 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, - 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, 0x0904, 0x3339, 0x0804, - 0x3368, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x336e, 0x21e0, - 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, 0x0804, 0x3339, 0x2069, - 0x1853, 0x7884, 0x7990, 0x911a, 0x1a04, 0x336e, 0x8019, 0x0904, - 0x336e, 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, - 0x685a, 0x685e, 0x080c, 0x72b0, 0x0804, 0x3339, 0x2069, 0x1853, - 0x7884, 0x7994, 0x911a, 0x1a04, 0x336e, 0x8019, 0x0904, 0x336e, - 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, - 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, 0x6669, 0x012e, 0x0804, - 0x3339, 0x902e, 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x336b, 0x7984, 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, - 0x20a1, 0x189c, 0x4101, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, - 0x0804, 0x336b, 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x080c, 0x48d2, 0x701f, 0x345d, 0x0005, 0xa864, 0x2008, 0x9084, - 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, - 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, - 0x336b, 0x810f, 0x918c, 0x00ff, 0x0904, 0x336b, 0x7112, 0x7010, - 0x8001, 0x0560, 0x7012, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, - 0x0804, 0x336b, 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, - 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, - 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x48d2, - 0x701f, 0x349b, 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, - 0x0120, 0x9096, 0x000a, 0x1904, 0x336b, 0x0888, 0x7014, 0x2048, - 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0029, - 0x1160, 0xc2fd, 0xaa7a, 0x080c, 0x5de6, 0x0150, 0x0126, 0x2091, - 0x8000, 0xa87a, 0xa982, 0x012e, 0x0050, 0x080c, 0x60fd, 0x1128, - 0x7007, 0x0003, 0x701f, 0x34c7, 0x0005, 0x080c, 0x6abf, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x189c, - 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, - 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, - 0x0804, 0x48d5, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, - 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, - 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, - 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, - 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x19e9, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, - 0x81ff, 0x1904, 0x336b, 0x7984, 0x080c, 0x6247, 0x1904, 0x336e, - 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x336e, 0x7c88, - 0x7d8c, 0x080c, 0x63aa, 0x080c, 0x6379, 0x0000, 0x1518, 0x2061, - 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, - 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, - 0x1a04, 0x336b, 0x0c30, 0x080c, 0xb75d, 0x012e, 0x0904, 0x336b, - 0x0804, 0x3339, 0x900e, 0x2001, 0x0005, 0x080c, 0x6abf, 0x0126, - 0x2091, 0x8000, 0x080c, 0xbe26, 0x080c, 0x6891, 0x012e, 0x0804, - 0x3339, 0x00a6, 0x2950, 0xb198, 0x080c, 0x6247, 0x1904, 0x35b3, - 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, - 0x080c, 0x63aa, 0x080c, 0x6379, 0x1520, 0x2061, 0x1cd0, 0x0126, - 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, - 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, - 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, 0x9c02, 0x2009, 0x000d, - 0x12b0, 0x0c28, 0x080c, 0xb75d, 0x012e, 0x2009, 0x0003, 0x0178, - 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x6abf, 0x0126, 0x2091, - 0x8000, 0x080c, 0xbe26, 0x080c, 0x6884, 0x012e, 0x0070, 0xb097, - 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, - 0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, - 0x336b, 0x080c, 0x48a0, 0x0904, 0x336e, 0x080c, 0x630e, 0x0904, - 0x336b, 0x080c, 0x63b0, 0x0904, 0x336b, 0x0804, 0x430e, 0x81ff, - 0x1904, 0x336b, 0x080c, 0x48bc, 0x0904, 0x336e, 0x080c, 0x643e, - 0x0904, 0x336b, 0x2019, 0x0005, 0x79a8, 0x080c, 0x63cb, 0x0904, - 0x336b, 0x7888, 0x908a, 0x1000, 0x1a04, 0x336e, 0x8003, 0x800b, - 0x810b, 0x9108, 0x080c, 0x802f, 0x7984, 0xd184, 0x1904, 0x3339, - 0x0804, 0x430e, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, - 0x0001, 0x0450, 0x2029, 0x07ff, 0x6458, 0x2400, 0x9506, 0x01f8, - 0x2508, 0x080c, 0x6247, 0x11d8, 0x080c, 0x643e, 0x1128, 0x2009, - 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, - 0x63cb, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, - 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x802f, 0x8529, - 0x1ae0, 0x012e, 0x0804, 0x3339, 0x012e, 0x0804, 0x336b, 0x012e, - 0x0804, 0x336e, 0x080c, 0x48a0, 0x0904, 0x336e, 0x080c, 0x630e, - 0x0904, 0x336b, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, - 0x8564, 0x0076, 0x903e, 0x080c, 0x8452, 0x900e, 0x080c, 0xd2bc, - 0x007e, 0x00ce, 0x080c, 0x63aa, 0x0804, 0x3339, 0x080c, 0x48a0, - 0x0904, 0x336e, 0x080c, 0x63aa, 0x2208, 0x0804, 0x3339, 0x0156, - 0x00d6, 0x00e6, 0x2069, 0x1906, 0x6810, 0x6914, 0x910a, 0x1208, - 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, - 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04, - 0x3668, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x3339, - 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1906, - 0x6910, 0x62b8, 0x0804, 0x3339, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x336b, 0x0126, 0x2091, 0x8000, 0x080c, 0x53a3, 0x0128, - 0x2009, 0x0007, 0x012e, 0x0804, 0x336b, 0x012e, 0x6158, 0x9190, - 0x313a, 0x2215, 0x9294, 0x00ff, 0x6378, 0x83ff, 0x0108, 0x627c, - 0x67d8, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, - 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, - 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, - 0x0068, 0x080c, 0x6f9b, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, - 0x0120, 0x2009, 0x0005, 0x0804, 0x336b, 0x9036, 0x7e9a, 0x7f9e, - 0x0804, 0x3339, 0x6148, 0x624c, 0x2019, 0x1956, 0x231c, 0x2001, - 0x1957, 0x2004, 0x789a, 0x0804, 0x3339, 0x0126, 0x2091, 0x8000, - 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x3339, 0x080c, 0x48bc, - 0x0904, 0x336e, 0xba44, 0xbb38, 0x0804, 0x3339, 0x080c, 0x0db4, - 0x080c, 0x48bc, 0x2110, 0x0904, 0x336e, 0xb804, 0x908c, 0x00ff, - 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, - 0x0009, 0x1904, 0x336b, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0x992c, 0x080c, 0x8564, 0x0076, 0x903e, - 0x080c, 0x8452, 0x900e, 0x080c, 0xd2bc, 0x007e, 0x00ce, 0xb807, - 0x0407, 0x012e, 0x0804, 0x3339, 0x6148, 0x624c, 0x7884, 0x604a, - 0x7b88, 0x634e, 0x2069, 0x1853, 0x831f, 0x9305, 0x6816, 0x788c, - 0x2069, 0x1956, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, - 0x2031, 0x07d0, 0x2069, 0x1957, 0x2d04, 0x266a, 0x789a, 0x0804, - 0x3339, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, 0x910e, - 0xd1b4, 0x190c, 0x0e9b, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, 0x2009, - 0x196d, 0x200a, 0x78ac, 0x2011, 0x196e, 0x2012, 0x2069, 0x0100, - 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, - 0x695a, 0x00de, 0x7888, 0x603e, 0x2011, 0x0114, 0x220c, 0x7888, - 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, 0x918c, 0xff7f, 0x2112, - 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, 0x190c, 0x0eb1, 0x6040, - 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, - 0x3339, 0x00f6, 0x2079, 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, - 0x9215, 0xa89c, 0x9084, 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, - 0x0140, 0x9215, 0x7a3a, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, - 0x9025, 0x0904, 0x336e, 0x788c, 0x902d, 0x0904, 0x336e, 0x900e, - 0x080c, 0x6247, 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, - 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x48bc, 0x0904, 0x336e, - 0x7888, 0x900d, 0x0904, 0x336e, 0x788c, 0x9005, 0x0904, 0x336e, - 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, 0x3339, 0x2011, 0xbc09, - 0x0010, 0x2011, 0xbc05, 0x080c, 0x53a3, 0x1904, 0x336b, 0x00c6, - 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, 0x1817, - 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, - 0x313a, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1817, 0x2004, 0x0026, - 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, - 0x0006, 0x080c, 0x9dec, 0x000e, 0x0510, 0x602e, 0x620a, 0x7984, - 0x00b6, 0x080c, 0x61ed, 0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, - 0x0001, 0x080c, 0x4889, 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, 0x3819, 0x2900, 0x6016, - 0x2009, 0x0032, 0x080c, 0x9ebc, 0x012e, 0x00ce, 0x0005, 0x012e, - 0x00ce, 0x0804, 0x336b, 0x00ce, 0x0804, 0x336e, 0x080c, 0x9e42, - 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, 0x336b, 0x0804, 0x3339, - 0x2061, 0x1a40, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, - 0x6104, 0x6208, 0x2061, 0x1800, 0x6350, 0x6070, 0x789a, 0x60bc, - 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, 0x3339, 0x900e, 0x2110, - 0x0c88, 0x81ff, 0x1904, 0x336b, 0x080c, 0x6f9b, 0x0904, 0x336b, - 0x0126, 0x2091, 0x8000, 0x6250, 0x6070, 0x9202, 0x0248, 0x9085, - 0x0001, 0x080c, 0x26ce, 0x080c, 0x55bd, 0x012e, 0x0804, 0x3339, - 0x012e, 0x0804, 0x336e, 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, - 0x1979, 0x2070, 0x2061, 0x1853, 0x6008, 0x2072, 0x900e, 0x2011, - 0x1400, 0x080c, 0x8259, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, - 0x400b, 0x0804, 0x333b, 0x7884, 0xd0fc, 0x0148, 0x2001, 0x002a, - 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, 0x0804, 0x336e, 0x2001, - 0x002a, 0x2004, 0x2069, 0x1853, 0x6908, 0x9102, 0x1230, 0x012e, - 0x0804, 0x336e, 0x012e, 0x0804, 0x336b, 0x080c, 0x9dc1, 0x0dd0, - 0x7884, 0xd0fc, 0x0904, 0x38e4, 0x00c6, 0x080c, 0x4889, 0x00ce, - 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, - 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, - 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, - 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, - 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, - 0x8004, 0xa816, 0x080c, 0x3a6a, 0x0928, 0x7014, 0x2048, 0xad2c, - 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, - 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x48d2, 0x701f, 0x39a7, - 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3853, 0x2001, - 0x196f, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, - 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, - 0x3ad9, 0x080c, 0x3a98, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, - 0x1a35, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x3e6c, 0x008e, 0x00ee, - 0x00fe, 0x080c, 0x3d99, 0x080c, 0x3c9e, 0x05b8, 0x2001, 0x020b, - 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x3ee0, 0x00f6, 0x2079, - 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, - 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, - 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, - 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, - 0x2001, 0x181f, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, - 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3ca8, 0x080c, - 0x3a93, 0x0058, 0x080c, 0x3a93, 0x080c, 0x3e04, 0x080c, 0x3d8f, - 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, - 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, - 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, - 0x129f, 0x2009, 0x0028, 0x080c, 0x226a, 0x2001, 0x0227, 0x200c, - 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x004e, 0x2001, 0x196f, 0x2004, 0x9005, 0x1118, 0x012e, - 0x0804, 0x3339, 0x012e, 0x2021, 0x400c, 0x0804, 0x333b, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, - 0x9005, 0x0904, 0x3a03, 0x2048, 0x1f04, 0x39b7, 0x7068, 0x2040, - 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, - 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, - 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x48d2, 0x701f, - 0x39a7, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, - 0x0006, 0x080c, 0x0f68, 0x000e, 0x080c, 0x48d5, 0x701f, 0x39a7, - 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, - 0x1118, 0x701f, 0x3a68, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, - 0xa86a, 0x2009, 0x007f, 0x080c, 0x61e7, 0x0110, 0x9006, 0x0030, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xbff5, 0x015e, 0x00de, - 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, - 0x0904, 0x336b, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, - 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3a3a, 0x7007, 0x0003, - 0x0804, 0x39f8, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, - 0x333b, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189c, 0x7003, + 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, 0x7042, + 0x7046, 0x703b, 0x18b8, 0x703f, 0x18b8, 0x7007, 0x0001, 0x080c, + 0x1004, 0x090c, 0x0db4, 0x2900, 0x706a, 0xa867, 0x0002, 0xa8ab, + 0xdcb0, 0x080c, 0x1004, 0x090c, 0x0db4, 0x2900, 0x706e, 0xa867, + 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189c, 0x7004, 0x0002, + 0x3274, 0x3275, 0x3288, 0x329c, 0x0005, 0x1004, 0x3285, 0x0e04, + 0x3285, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, + 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, 0x0ce8, + 0x2079, 0x0000, 0x2061, 0x18b6, 0x2c4c, 0xa86c, 0x908e, 0x0100, + 0x0128, 0x9086, 0x0200, 0x0904, 0x3370, 0x0005, 0x7018, 0x2048, + 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, 0x9094, + 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, 0x0005, + 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, 0x1800, + 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, 0x1210, + 0x61cc, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x336d, 0x61cc, + 0x0804, 0x3302, 0x3344, 0x337c, 0x336d, 0x3386, 0x3390, 0x3396, + 0x339a, 0x33aa, 0x33ae, 0x33c4, 0x33ca, 0x33d0, 0x33db, 0x33e6, + 0x33f5, 0x3404, 0x3412, 0x3429, 0x3444, 0x336d, 0x34ed, 0x352b, + 0x35d1, 0x35e2, 0x3605, 0x336d, 0x336d, 0x336d, 0x363d, 0x3659, + 0x3662, 0x3691, 0x3697, 0x336d, 0x36dd, 0x336d, 0x336d, 0x336d, + 0x336d, 0x336d, 0x36e8, 0x36f1, 0x36f9, 0x36fb, 0x336d, 0x336d, + 0x336d, 0x336d, 0x336d, 0x336d, 0x3727, 0x336d, 0x336d, 0x336d, + 0x336d, 0x336d, 0x3744, 0x379f, 0x336d, 0x336d, 0x336d, 0x336d, + 0x336d, 0x336d, 0x0002, 0x37c9, 0x37cc, 0x382b, 0x3844, 0x3874, + 0x3b12, 0x336d, 0x4f73, 0x336d, 0x336d, 0x336d, 0x336d, 0x336d, + 0x336d, 0x336d, 0x336d, 0x33c4, 0x33ca, 0x4033, 0x53be, 0x4049, + 0x5002, 0x5053, 0x5156, 0x336d, 0x51b8, 0x51f4, 0x5225, 0x5329, + 0x5252, 0x52a9, 0x336d, 0x404d, 0x41ee, 0x4204, 0x4229, 0x428e, + 0x4302, 0x4322, 0x4399, 0x43f5, 0x4451, 0x4454, 0x4479, 0x4519, + 0x457f, 0x4587, 0x46b9, 0x481e, 0x4852, 0x4a9c, 0x336d, 0x4aba, + 0x4b76, 0x4c4c, 0x336d, 0x336d, 0x336d, 0x336d, 0x4cb2, 0x4ccd, + 0x4587, 0x4f13, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, 0x48d0, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x334e, 0x0010, 0x012e, 0x0cc0, + 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, + 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x7007, 0x0001, 0x2091, + 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, + 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, + 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, 0x2520, + 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x48dd, 0x2039, 0x0001, + 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x48e0, + 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x3344, 0x7984, 0x2114, + 0x0804, 0x3344, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, + 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, 0x7a88, 0x7b8c, + 0x0804, 0x3344, 0x7884, 0x2060, 0x0804, 0x33f7, 0x2009, 0x0003, + 0x2011, 0x0003, 0x2019, 0x0002, 0x789b, 0x0317, 0x7893, 0xffff, + 0x2001, 0x188d, 0x2004, 0x9005, 0x0118, 0x7896, 0x0804, 0x3344, + 0x7897, 0x0001, 0x0804, 0x3344, 0x2039, 0x0001, 0x7d98, 0x7c9c, + 0x0804, 0x3380, 0x2039, 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x338a, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x3379, 0x2138, 0x7d98, + 0x7c9c, 0x0804, 0x3380, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, + 0x3379, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x338a, 0x79a0, 0x9182, + 0x0040, 0x0210, 0x0804, 0x3379, 0x21e8, 0x7984, 0x7888, 0x20a9, + 0x0001, 0x21a0, 0x4004, 0x0804, 0x3344, 0x2061, 0x0800, 0xe10c, + 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0x9005, + 0x0904, 0x3344, 0x0804, 0x3373, 0x79a0, 0x9182, 0x0040, 0x0210, + 0x0804, 0x3379, 0x21e0, 0x20a9, 0x0001, 0x7984, 0x2198, 0x4012, + 0x0804, 0x3344, 0x2069, 0x185b, 0x7884, 0x7990, 0x911a, 0x1a04, + 0x3379, 0x8019, 0x0904, 0x3379, 0x684a, 0x6942, 0x788c, 0x6852, + 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, 0x72bd, 0x0804, + 0x3344, 0x2069, 0x185b, 0x7884, 0x7994, 0x911a, 0x1a04, 0x3379, + 0x8019, 0x0904, 0x3379, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, + 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, 0x8000, 0x080c, + 0x6678, 0x012e, 0x0804, 0x3344, 0x902e, 0x2520, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3376, 0x7984, 0x7b88, 0x7a8c, 0x20a9, + 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a4, 0x4101, 0x080c, 0x4894, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3376, 0x2009, 0x0020, 0xa85c, + 0x9080, 0x0019, 0xaf60, 0x080c, 0x48dd, 0x701f, 0x3468, 0x0005, + 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, + 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, 0x0048, 0x0120, + 0x9096, 0x0029, 0x1904, 0x3376, 0x810f, 0x918c, 0x00ff, 0x0904, + 0x3376, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, 0x080c, 0x4894, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3376, 0x2009, 0x0020, 0x7068, + 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, + 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, + 0xaf60, 0x080c, 0x48dd, 0x701f, 0x34a6, 0x0005, 0xa864, 0x9084, + 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, 0x1904, 0x3376, + 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, + 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, 0x080c, 0x5df1, + 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x012e, 0x0050, + 0x080c, 0x610c, 0x1128, 0x7007, 0x0003, 0x701f, 0x34d2, 0x0005, + 0x080c, 0x6ace, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, + 0x0001, 0x2099, 0x18a4, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, + 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, + 0x0020, 0x012e, 0xaf60, 0x0804, 0x48e0, 0x2091, 0x8000, 0x7837, + 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, + 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, + 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, + 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, + 0x19f1, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, + 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, + 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3376, 0x7984, 0x080c, + 0x6256, 0x1904, 0x3379, 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x1a04, 0x3379, 0x7c88, 0x7d8c, 0x080c, 0x63b9, 0x080c, 0x6388, + 0x0000, 0x1518, 0x2061, 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, + 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, + 0x1118, 0xa870, 0x9506, 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, + 0x1819, 0x2004, 0x9c02, 0x1a04, 0x3376, 0x0c30, 0x080c, 0xb75c, + 0x012e, 0x0904, 0x3376, 0x0804, 0x3344, 0x900e, 0x2001, 0x0005, + 0x080c, 0x6ace, 0x0126, 0x2091, 0x8000, 0x080c, 0xbe35, 0x080c, + 0x68a0, 0x012e, 0x0804, 0x3344, 0x00a6, 0x2950, 0xb198, 0x080c, + 0x6256, 0x1904, 0x35be, 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, + 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x63b9, 0x080c, 0x6388, 0x1520, + 0x2061, 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, + 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, + 0x9506, 0x0158, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, + 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xb75c, 0x012e, + 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, + 0x6ace, 0x0126, 0x2091, 0x8000, 0x080c, 0xbe35, 0x080c, 0x6893, + 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, + 0xb097, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, + 0x0005, 0x81ff, 0x1904, 0x3376, 0x080c, 0x48ab, 0x0904, 0x3379, + 0x080c, 0x631d, 0x0904, 0x3376, 0x080c, 0x63bf, 0x0904, 0x3376, + 0x0804, 0x4319, 0x81ff, 0x1904, 0x3376, 0x080c, 0x48c7, 0x0904, + 0x3379, 0x080c, 0x644d, 0x0904, 0x3376, 0x2019, 0x0005, 0x79a8, + 0x080c, 0x63da, 0x0904, 0x3376, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x3379, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x804d, 0x7984, + 0xd184, 0x1904, 0x3344, 0x0804, 0x4319, 0x0126, 0x2091, 0x8000, + 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x07ff, 0x6458, + 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x6256, 0x11d8, 0x080c, + 0x644d, 0x1128, 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, 0x2019, + 0x0004, 0x900e, 0x080c, 0x63da, 0x1118, 0x2009, 0x0006, 0x0078, + 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, + 0x080c, 0x804d, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x3344, 0x012e, + 0x0804, 0x3376, 0x012e, 0x0804, 0x3379, 0x080c, 0x48ab, 0x0904, + 0x3379, 0x080c, 0x631d, 0x0904, 0x3376, 0xbaa0, 0x2019, 0x0005, + 0x00c6, 0x9066, 0x080c, 0x8582, 0x0076, 0x903e, 0x080c, 0x8470, + 0x900e, 0x080c, 0xd2d5, 0x007e, 0x00ce, 0x080c, 0x63b9, 0x0804, + 0x3344, 0x080c, 0x48ab, 0x0904, 0x3379, 0x080c, 0x63b9, 0x2208, + 0x0804, 0x3344, 0x0156, 0x00d6, 0x00e6, 0x2069, 0x190e, 0x6810, + 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, + 0x007e, 0x2069, 0x1000, 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, + 0x9210, 0x8d68, 0x1f04, 0x3673, 0x2300, 0x9218, 0x00ee, 0x00de, + 0x015e, 0x0804, 0x3344, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, + 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, + 0x0005, 0x2069, 0x190e, 0x6910, 0x62b8, 0x0804, 0x3344, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, 0x0126, 0x2091, 0x8000, + 0x080c, 0x53ae, 0x0128, 0x2009, 0x0007, 0x012e, 0x0804, 0x3376, + 0x012e, 0x6158, 0x9190, 0x3145, 0x2215, 0x9294, 0x00ff, 0x6378, + 0x83ff, 0x0108, 0x627c, 0x67d8, 0x97c4, 0x000a, 0x98c6, 0x000a, + 0x1118, 0x2031, 0x0001, 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, + 0x1118, 0x2031, 0x0003, 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, + 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, 0x6faa, 0x1118, 0x2031, + 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, 0x0804, 0x3376, + 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x3344, 0x6148, 0x624c, 0x2019, + 0x195e, 0x231c, 0x2001, 0x195f, 0x2004, 0x789a, 0x0804, 0x3344, + 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, + 0x3344, 0x080c, 0x48c7, 0x0904, 0x3379, 0xba44, 0xbb38, 0x0804, + 0x3344, 0x080c, 0x0db4, 0x080c, 0x48c7, 0x2110, 0x0904, 0x3379, + 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, + 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x3376, 0x0126, 0x2091, + 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x9915, 0x080c, + 0x8582, 0x0076, 0x903e, 0x080c, 0x8470, 0x900e, 0x080c, 0xd2d5, + 0x007e, 0x00ce, 0xb807, 0x0407, 0x012e, 0x0804, 0x3344, 0x6148, + 0x624c, 0x7884, 0x604a, 0x7b88, 0x634e, 0x2069, 0x185b, 0x831f, + 0x9305, 0x6816, 0x788c, 0x2069, 0x195e, 0x2d1c, 0x206a, 0x7e98, + 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x195f, 0x2d04, + 0x266a, 0x789a, 0x0804, 0x3344, 0x0126, 0x2091, 0x8000, 0x6138, + 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0e9b, 0xd0c4, 0x01a8, + 0x00d6, 0x78a8, 0x2009, 0x1975, 0x200a, 0x78ac, 0x2011, 0x1976, + 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, + 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0x603e, 0x2011, + 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, + 0x918c, 0xff7f, 0x2112, 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, + 0x190c, 0x0eb1, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, + 0x2012, 0x012e, 0x0804, 0x3344, 0x00f6, 0x2079, 0x1800, 0x7a38, + 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, 0x8002, + 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, 0x4000, + 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, + 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x3379, 0x788c, 0x902d, + 0x0904, 0x3379, 0x900e, 0x080c, 0x6256, 0x1120, 0xba44, 0xbb38, + 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, + 0x48c7, 0x0904, 0x3379, 0x7888, 0x900d, 0x0904, 0x3379, 0x788c, + 0x9005, 0x0904, 0x3379, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, + 0x3344, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x53ae, + 0x1904, 0x3376, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, + 0x1130, 0x2001, 0x1817, 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, + 0x007f, 0x16e0, 0x9188, 0x3145, 0x210d, 0x918c, 0x00ff, 0x2001, + 0x1817, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, + 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x9dd9, 0x000e, 0x0510, + 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x61fc, 0x2b08, 0x00be, + 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4894, 0x01d0, 0x9006, + 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, + 0x3824, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0x9ea9, 0x012e, + 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3376, 0x00ce, 0x0804, + 0x3379, 0x080c, 0x9e2f, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, + 0x3376, 0x0804, 0x3344, 0x2061, 0x1a48, 0x0126, 0x2091, 0x8000, + 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, 0x6350, + 0x6070, 0x789a, 0x60bc, 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, + 0x3344, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x3376, 0x080c, + 0x6faa, 0x0904, 0x3376, 0x0126, 0x2091, 0x8000, 0x6250, 0x6070, + 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x26d9, 0x080c, 0x55c8, + 0x012e, 0x0804, 0x3344, 0x012e, 0x0804, 0x3379, 0x0006, 0x0016, + 0x00c6, 0x00e6, 0x2001, 0x1981, 0x2070, 0x2061, 0x185b, 0x6008, + 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x8277, 0x7206, 0x00ee, + 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, + 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3346, 0x7884, 0xd0fc, + 0x0148, 0x2001, 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, + 0x0804, 0x3379, 0x2001, 0x002a, 0x2004, 0x2069, 0x185b, 0x6908, + 0x9102, 0x1230, 0x012e, 0x0804, 0x3379, 0x012e, 0x0804, 0x3376, + 0x080c, 0x9dae, 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x38ef, 0x00c6, + 0x080c, 0x4894, 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, + 0x7898, 0xa80e, 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, + 0x2001, 0x002f, 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, + 0x2001, 0x0031, 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, + 0x2001, 0x0035, 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, + 0x0003, 0x9084, 0x00fc, 0x8004, 0xa816, 0x080c, 0x3a75, 0x0928, + 0x7014, 0x2048, 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, - 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f68, 0x000e, - 0x080c, 0x48d5, 0x007e, 0x701f, 0x39a7, 0x7023, 0x0001, 0x0005, - 0x0804, 0x3339, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, - 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, - 0x080c, 0x4889, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, - 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, - 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, - 0x00fe, 0x000e, 0x0005, 0x2001, 0x196f, 0x2003, 0x0001, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x197a, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x1979, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x080c, 0x4889, 0xa813, 0x0019, 0xa817, 0x0001, + 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, + 0x48dd, 0x701f, 0x39b2, 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, + 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x080c, 0x385e, 0x2001, 0x1977, 0x2003, 0x0000, 0x2021, 0x000a, + 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, + 0x60bf, 0x0012, 0x080c, 0x3ae4, 0x080c, 0x3aa3, 0x00f6, 0x00e6, + 0x0086, 0x2940, 0x2071, 0x1a3d, 0x2079, 0x0090, 0x00d6, 0x2069, + 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, + 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, + 0x3e77, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3da4, 0x080c, 0x3ca9, + 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, + 0x3eeb, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, + 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, + 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, + 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, + 0x715c, 0x9106, 0x1190, 0x2001, 0x181f, 0x2004, 0x9106, 0x1168, + 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, + 0x080c, 0x3cb3, 0x080c, 0x3a9e, 0x0058, 0x080c, 0x3a9e, 0x080c, + 0x3e0f, 0x080c, 0x3d9a, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, + 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, + 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, + 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, + 0xfffd, 0x2102, 0x080c, 0x129f, 0x2009, 0x0028, 0x080c, 0x2275, + 0x2001, 0x0227, 0x200c, 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, 0x1977, 0x2004, + 0x9005, 0x1118, 0x012e, 0x0804, 0x3344, 0x012e, 0x2021, 0x400c, + 0x0804, 0x3346, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, + 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, + 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3a0e, 0x2048, 0x1f04, + 0x39c2, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, + 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, + 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, + 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, + 0x080c, 0x48dd, 0x701f, 0x39b2, 0x00b0, 0x8906, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, + 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f68, 0x000e, 0x080c, + 0x48e0, 0x701f, 0x39b2, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, + 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3a73, 0x0450, 0x7014, + 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, 0x080c, 0x61f6, + 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, + 0xc004, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, + 0x003e, 0x002e, 0x001e, 0x0904, 0x3376, 0x0016, 0x0026, 0x0036, + 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, + 0x3a45, 0x7007, 0x0003, 0x0804, 0x3a03, 0xa830, 0x9086, 0x0100, + 0x2021, 0x400c, 0x0904, 0x3346, 0x0076, 0xad10, 0xac0c, 0xab24, + 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, + 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, + 0x080c, 0x0f68, 0x000e, 0x080c, 0x48e0, 0x007e, 0x701f, 0x39b2, + 0x7023, 0x0001, 0x0005, 0x0804, 0x3344, 0x0156, 0x00c6, 0xa814, + 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, + 0x81ff, 0x0168, 0x0016, 0x080c, 0x4894, 0x001e, 0x0130, 0xa800, + 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, + 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, + 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, 0x2001, 0x1977, + 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, + 0x2001, 0x1982, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x1981, + 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, 0x4894, 0xa813, + 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, + 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, + 0x0100, 0x2001, 0x1981, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, + 0x2275, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, + 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x4894, 0x2940, + 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, + 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, + 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, + 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, + 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, + 0x2a62, 0x1130, 0x9006, 0x080c, 0x29ba, 0x9006, 0x080c, 0x299d, + 0x7884, 0x9084, 0x0007, 0x0002, 0x3b2f, 0x3b38, 0x3b41, 0x3b2c, + 0x3b2c, 0x3b2c, 0x3b2c, 0x3b2c, 0x012e, 0x0804, 0x3379, 0x2009, + 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3cfd, 0x00c0, + 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, 0x3cfd, + 0x0078, 0x080c, 0x6faa, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, + 0x3376, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x3346, + 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, + 0x080c, 0x385e, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, + 0x9006, 0x2068, 0x2060, 0x2058, 0x080c, 0x3fc6, 0x080c, 0x3f16, + 0x903e, 0x2720, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a3d, + 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, + 0x68d4, 0x780e, 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, + 0x3e77, 0x080c, 0x2a6a, 0x080c, 0x2a6a, 0x080c, 0x2a6a, 0x080c, + 0x2a6a, 0x080c, 0x3e77, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3da4, + 0x2009, 0x9c40, 0x8109, 0x11b0, 0x080c, 0x3cb3, 0x2001, 0x0004, + 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, + 0x3376, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, + 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, + 0x0201, 0x200c, 0x81ff, 0x0150, 0x080c, 0x3d82, 0x2d00, 0x9c05, + 0x9b05, 0x0120, 0x080c, 0x3cb3, 0x0804, 0x3c60, 0x080c, 0x3eeb, + 0x080c, 0x3e0f, 0x080c, 0x3d65, 0x080c, 0x3d9a, 0x00f6, 0x2079, + 0x0100, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3cb3, 0x00fe, + 0x0804, 0x3c60, 0x00fe, 0x080c, 0x3ca9, 0x1150, 0x8d68, 0x2001, + 0x0032, 0x2602, 0x2001, 0x0033, 0x2502, 0x080c, 0x3cb3, 0x0080, + 0x87ff, 0x0138, 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, + 0x0038, 0x2001, 0x1a3a, 0x2004, 0x9086, 0x0000, 0x1904, 0x3bb0, + 0x2001, 0x032f, 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, + 0x9605, 0x0904, 0x3c60, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, + 0x9b05, 0x1904, 0x3c60, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, + 0x0004, 0x7884, 0xd0ac, 0x1148, 0x2001, 0x1a3a, 0x2003, 0x0003, + 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, + 0x9005, 0x0108, 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, + 0x2275, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, + 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, + 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3c37, 0x00ce, 0x0030, + 0xa817, 0x0001, 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, + 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, + 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, + 0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3b6a, + 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, + 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, + 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, 0x129f, 0x7884, + 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, + 0x2275, 0x2001, 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, + 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, + 0x0010, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, + 0x1118, 0x012e, 0x0804, 0x3344, 0x012e, 0x2021, 0x400c, 0x0804, + 0x3346, 0x9085, 0x0001, 0x1d04, 0x3cb2, 0x2091, 0x6000, 0x8420, + 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, + 0x032a, 0x2003, 0x0004, 0x2001, 0x1a3a, 0x2003, 0x0000, 0x0071, + 0x2009, 0x0048, 0x080c, 0x2275, 0x2001, 0x0227, 0x2024, 0x2402, + 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, + 0x2071, 0x1a3d, 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, + 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, + 0x2009, 0x0040, 0x080c, 0x2275, 0x782c, 0xd0fc, 0x0d88, 0x080c, + 0x3eeb, 0x7000, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, + 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2275, 0x782b, 0x0002, + 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, + 0x2001, 0x1817, 0x200c, 0x7932, 0x7936, 0x080c, 0x26b9, 0x7850, + 0x9084, 0xfbff, 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, + 0x1df0, 0x9084, 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, + 0x1d04, 0x3d18, 0x2091, 0x6000, 0x1f04, 0x3d18, 0x7850, 0x9085, + 0x0400, 0x9084, 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, + 0x0003, 0x9086, 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, + 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, + 0xa001, 0x1f04, 0x3d38, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, + 0x61a8, 0x7854, 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, + 0x7827, 0x0048, 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, + 0x2019, 0x01f4, 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, + 0x080c, 0x2b21, 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, + 0x2b21, 0x7827, 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, + 0x00f6, 0x00e6, 0x2071, 0x1a3a, 0x2079, 0x0320, 0x2001, 0x0201, + 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, + 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, + 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, + 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, + 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, + 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, + 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, + 0x1982, 0x2004, 0x70e2, 0x080c, 0x3a94, 0x1188, 0x2001, 0x181f, + 0x2004, 0x2009, 0x181e, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, + 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, + 0x9085, 0x0002, 0x702e, 0x2009, 0x1817, 0x210c, 0x716e, 0x7063, + 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, + 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, + 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, + 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, + 0x7016, 0x080c, 0x3eeb, 0x00f6, 0x2071, 0x1a3a, 0x2079, 0x0320, + 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, + 0x6898, 0x780a, 0x00de, 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, + 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x3e77, + 0x2011, 0x0001, 0x080c, 0x3e77, 0x00fe, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0x1a3a, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, + 0x3e74, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x3e70, 0x7000, + 0x0002, 0x3e74, 0x3e25, 0x3e55, 0x3e70, 0xd1bc, 0x1170, 0xd1dc, + 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x3e77, 0x0904, + 0x3e74, 0x080c, 0x3e77, 0x0804, 0x3e74, 0x00f6, 0x2079, 0x0300, + 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, + 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3d82, + 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, + 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, + 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3e19, 0x2011, 0x0001, + 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, + 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, 0x0828, + 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0xa014, + 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, 0x2048, + 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a, 0x0007, + 0x1a0c, 0x0db4, 0x9398, 0x3ea5, 0x231d, 0x083f, 0x9080, 0x0004, + 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, 0x0035, + 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001, 0x0019, + 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x3ee2, 0x3ed9, 0x3ed0, + 0x3ec7, 0x3ebe, 0x3eb5, 0x3eac, 0xa964, 0x7902, 0xa968, 0x7906, + 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, 0xa978, + 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, 0x7902, + 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005, 0xa994, + 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, 0xa9a0, 0x7916, 0x0005, + 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0, 0x7916, + 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912, 0xa9c0, + 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, 0x7912, + 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, 0x1a3d, + 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2940, + 0x9026, 0x7000, 0x0002, 0x3f12, 0x3efe, 0x3f09, 0x8001, 0x7002, + 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x3e77, 0x190c, 0x3e77, + 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, + 0x080c, 0x3e77, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x1982, 0x2004, 0x601a, + 0x2061, 0x0100, 0x2001, 0x1981, 0x2004, 0x60ce, 0x6104, 0xc1ac, + 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, + 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4894, 0xa813, + 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, + 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x3f8e, 0x1d68, 0x2900, + 0xa85a, 0x00d0, 0x080c, 0x4894, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, - 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x1979, - 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x226a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, - 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x00e6, 0x080c, 0x4889, 0x2940, 0xa013, 0x0019, 0xa017, - 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, - 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, 0x2a57, 0x1130, 0x9006, - 0x080c, 0x29af, 0x9006, 0x080c, 0x2992, 0x7884, 0x9084, 0x0007, - 0x0002, 0x3b24, 0x3b2d, 0x3b36, 0x3b21, 0x3b21, 0x3b21, 0x3b21, - 0x3b21, 0x012e, 0x0804, 0x336e, 0x2009, 0x0114, 0x2104, 0x9085, - 0x0800, 0x200a, 0x080c, 0x3cf2, 0x00c0, 0x2009, 0x0114, 0x2104, - 0x9085, 0x4000, 0x200a, 0x080c, 0x3cf2, 0x0078, 0x080c, 0x6f9b, - 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x336b, 0x81ff, 0x0128, - 0x012e, 0x2021, 0x400b, 0x0804, 0x333b, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3853, 0x2009, - 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, - 0x2058, 0x080c, 0x3fbb, 0x080c, 0x3f0b, 0x903e, 0x2720, 0x00f6, - 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a35, 0x2079, 0x0090, 0x00d6, - 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x3e6c, 0x080c, 0x2a5f, - 0x080c, 0x2a5f, 0x080c, 0x2a5f, 0x080c, 0x2a5f, 0x080c, 0x3e6c, - 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3d99, 0x2009, 0x9c40, 0x8109, - 0x11b0, 0x080c, 0x3ca8, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, - 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x336b, 0x0cf8, 0x2001, - 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, - 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, - 0x0150, 0x080c, 0x3d77, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, - 0x3ca8, 0x0804, 0x3c55, 0x080c, 0x3ee0, 0x080c, 0x3e04, 0x080c, - 0x3d5a, 0x080c, 0x3d8f, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, - 0x0130, 0x8b58, 0x080c, 0x3ca8, 0x00fe, 0x0804, 0x3c55, 0x00fe, - 0x080c, 0x3c9e, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, - 0x0033, 0x2502, 0x080c, 0x3ca8, 0x0080, 0x87ff, 0x0138, 0x2001, - 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a32, - 0x2004, 0x9086, 0x0000, 0x1904, 0x3ba5, 0x2001, 0x032f, 0x2003, - 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3c55, - 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3c55, - 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, - 0x1148, 0x2001, 0x1a32, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, - 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, - 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x226a, 0x2900, 0xa85a, - 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, - 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, - 0x2004, 0x1f04, 0x3c2c, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, - 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, - 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, - 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3b5f, 0x001e, 0x00c6, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, - 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x129f, 0x7884, 0x9084, 0x0003, 0x9086, - 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x226a, 0x2001, 0x0227, - 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, 0x0000, - 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x00ce, 0x2d08, - 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, - 0x3339, 0x012e, 0x2021, 0x400c, 0x0804, 0x333b, 0x9085, 0x0001, - 0x1d04, 0x3ca7, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, - 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, 0x0004, - 0x2001, 0x1a32, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, 0x080c, - 0x226a, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, - 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a35, 0x7000, - 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, - 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, - 0x226a, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x3ee0, 0x7000, 0x9086, - 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, - 0x0040, 0x080c, 0x226a, 0x782b, 0x0002, 0x7003, 0x0000, 0x00ee, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1817, 0x200c, - 0x7932, 0x7936, 0x080c, 0x26ae, 0x7850, 0x9084, 0xfbff, 0x9085, - 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084, 0xffcf, - 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3d0d, 0x2091, - 0x6000, 0x1f04, 0x3d0d, 0x7850, 0x9085, 0x0400, 0x9084, 0xdfff, - 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, 0x9086, 0x0001, - 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7, 0x7843, - 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x3d2d, - 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xa001, - 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, - 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, - 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2b16, 0x7827, - 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2b16, 0x7827, 0x0048, - 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, - 0x1a32, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, - 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, - 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, - 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, 0x2009, - 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, 0x8c60, - 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, - 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, - 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0x197a, 0x2004, 0x70e2, - 0x080c, 0x3a89, 0x1188, 0x2001, 0x181f, 0x2004, 0x2009, 0x181e, - 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, - 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, - 0x2009, 0x1817, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e, - 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0x9080, - 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, - 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, - 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, 0x080c, 0x3ee0, - 0x00f6, 0x2071, 0x1a32, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, - 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, - 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, - 0x0004, 0x2011, 0x0011, 0x080c, 0x3e6c, 0x2011, 0x0001, 0x080c, - 0x3e6c, 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a32, - 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, 0x3e69, 0x782b, 0x0002, - 0x9026, 0xd19c, 0x1904, 0x3e65, 0x7000, 0x0002, 0x3e69, 0x3e1a, - 0x3e4a, 0x3e65, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, - 0x2011, 0x0001, 0x080c, 0x3e6c, 0x0904, 0x3e69, 0x080c, 0x3e6c, - 0x0804, 0x3e69, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, - 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, - 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3d77, 0x2009, 0x0001, 0x00f6, - 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, - 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, - 0xd0fc, 0x1904, 0x3e0e, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, - 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, - 0x0031, 0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, - 0x0036, 0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, - 0x911a, 0x831c, 0x831c, 0x938a, 0x0007, 0x1a0c, 0x0db4, 0x9398, - 0x3e9a, 0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, - 0x7102, 0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, - 0x2048, 0xa804, 0xa05a, 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, - 0x0001, 0x0005, 0x3ed7, 0x3ece, 0x3ec5, 0x3ebc, 0x3eb3, 0x3eaa, - 0x3ea1, 0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, - 0x7916, 0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, - 0xa980, 0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, - 0x7912, 0xa990, 0x7916, 0x0005, 0xa994, 0x7902, 0xa998, 0x7906, - 0xa99c, 0x7912, 0xa9a0, 0x7916, 0x0005, 0xa9a4, 0x7902, 0xa9a8, - 0x7906, 0xa9ac, 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, - 0xa9b8, 0x7906, 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, - 0x7902, 0xa9c8, 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, - 0x00f6, 0x00e6, 0x0086, 0x2071, 0x1a35, 0x2079, 0x0090, 0x792c, - 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2940, 0x9026, 0x7000, 0x0002, - 0x3f07, 0x3ef3, 0x3efe, 0x8001, 0x7002, 0xd19c, 0x1180, 0x2011, - 0x0001, 0x080c, 0x3e6c, 0x190c, 0x3e6c, 0x0048, 0x8001, 0x7002, - 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, 0x080c, 0x3e6c, 0x008e, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, - 0x0200, 0x2001, 0x197a, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, - 0x1979, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, - 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, - 0x002f, 0x201c, 0x080c, 0x4889, 0xa813, 0x0019, 0xaf16, 0x2900, - 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, - 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, - 0x009e, 0x080c, 0x3f83, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, - 0x4889, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, - 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, - 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, - 0xa872, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x1979, 0x2004, - 0x6036, 0x2009, 0x0040, 0x080c, 0x226a, 0x2001, 0x002a, 0x2004, - 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, - 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, - 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, - 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, - 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, - 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, - 0x0096, 0x2940, 0x0086, 0x080c, 0x4889, 0x008e, 0xa058, 0x00a6, - 0x2050, 0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, - 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, - 0x0528, 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, - 0x080c, 0x4889, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, - 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, - 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, - 0x080c, 0x3f83, 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4889, - 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, - 0x0030, 0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, - 0x002a, 0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, - 0xa072, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, - 0x2001, 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0xa017, 0x0000, - 0x2001, 0x1a32, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, - 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, - 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x20a9, 0x0013, 0x20a1, 0x1840, 0x20e9, - 0x0001, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, - 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, 0x3339, 0x7d98, 0x7c9c, - 0x0804, 0x343b, 0x080c, 0x6f9b, 0x190c, 0x5c9f, 0x2069, 0x1853, - 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, - 0x0001, 0x080c, 0x48d2, 0x701f, 0x4056, 0x0005, 0x080c, 0x539e, - 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, - 0x1853, 0x6800, 0x9005, 0x0904, 0x336e, 0x6804, 0xd094, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, - 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, - 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, - 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, - 0x007f, 0x1a04, 0x336e, 0x9288, 0x313a, 0x210d, 0x918c, 0x00ff, - 0x6162, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x336e, - 0x605a, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, - 0x0006, 0x2009, 0x1981, 0x9080, 0x27a1, 0x2005, 0x200a, 0x000e, - 0x2009, 0x1982, 0x9080, 0x27a5, 0x2005, 0x200a, 0x6808, 0x908a, - 0x0100, 0x0a04, 0x336e, 0x908a, 0x0841, 0x1a04, 0x336e, 0x9084, - 0x0007, 0x1904, 0x336e, 0x680c, 0x9005, 0x0904, 0x336e, 0x6810, - 0x9005, 0x0904, 0x336e, 0x6848, 0x6940, 0x910a, 0x1a04, 0x336e, - 0x8001, 0x0904, 0x336e, 0x684c, 0x6944, 0x910a, 0x1a04, 0x336e, - 0x8001, 0x0904, 0x336e, 0x2009, 0x1951, 0x200b, 0x0000, 0x2001, - 0x1875, 0x2004, 0xd0c4, 0x0140, 0x7884, 0x200a, 0x2009, 0x017f, - 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614a, - 0x8007, 0x9084, 0x00ff, 0x604e, 0x080c, 0x72b0, 0x080c, 0x6634, - 0x080c, 0x6669, 0x6808, 0x602a, 0x080c, 0x21dc, 0x2009, 0x0170, - 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, - 0x080c, 0x2708, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x41d3, - 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, - 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, - 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, - 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, - 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x1983, 0x20e9, 0x0001, - 0x4001, 0x20a9, 0x0004, 0x20a1, 0x199d, 0x20e9, 0x0001, 0x4001, - 0x080c, 0x812a, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, - 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, 0x918e, 0x0008, 0x1110, - 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, - 0x787b, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, - 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, - 0x0010, 0x6003, 0x0001, 0x1f04, 0x4142, 0x00ce, 0x00c6, 0x2061, - 0x196c, 0x2063, 0x0001, 0x9006, 0x080c, 0x29af, 0x9006, 0x080c, - 0x2992, 0x0000, 0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0e80, 0x00ee, - 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, - 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, 0x1128, 0x9294, - 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x194c, 0x6a80, 0x9294, - 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, 0x0118, 0x928e, - 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x277d, 0x2001, 0x193d, - 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, - 0x602f, 0x0000, 0x00ce, 0x080c, 0x6f9b, 0x0128, 0x080c, 0x4c9b, - 0x0110, 0x080c, 0x26ce, 0x60d0, 0x9005, 0x01c0, 0x6003, 0x0001, - 0x2009, 0x41bb, 0x00d0, 0x080c, 0x6f9b, 0x1168, 0x2011, 0x6e1c, - 0x080c, 0x8021, 0x2011, 0x6e0f, 0x080c, 0x80f5, 0x080c, 0x7284, - 0x080c, 0x6ecd, 0x0040, 0x080c, 0x5b99, 0x0028, 0x6003, 0x0004, - 0x2009, 0x41d3, 0x0010, 0x0804, 0x3339, 0x2001, 0x0170, 0x2004, - 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, - 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x336b, - 0x2069, 0x1853, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, - 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, - 0x48d5, 0x9006, 0x080c, 0x26ce, 0x81ff, 0x1904, 0x336b, 0x080c, - 0x6f9b, 0x11b0, 0x080c, 0x727f, 0x080c, 0x5cda, 0x080c, 0x3135, - 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xc22c, 0x0130, 0x080c, - 0x6fbe, 0x1118, 0x080c, 0x6f73, 0x0038, 0x080c, 0x6ecd, 0x0020, - 0x080c, 0x5c9f, 0x080c, 0x5b99, 0x0804, 0x3339, 0x81ff, 0x1904, - 0x336b, 0x080c, 0x6f9b, 0x1110, 0x0804, 0x336b, 0x6190, 0x81ff, - 0x01a8, 0x704f, 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, 0x2039, 0x0001, - 0x080c, 0x48d5, 0x701f, 0x3337, 0x012e, 0x0005, 0x704f, 0x0001, - 0x00d6, 0x2069, 0x1c80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, - 0x1c80, 0x2019, 0xffff, 0x4304, 0x6558, 0x9588, 0x313a, 0x210d, - 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, - 0x01a8, 0x080c, 0x6247, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, - 0x1c80, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1c80, - 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, - 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, - 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1c80, 0x2099, 0x1c80, 0x080c, - 0x5c2a, 0x0804, 0x422b, 0x080c, 0x48bc, 0x0904, 0x336e, 0x080c, - 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, 0x336b, 0x080c, 0x538f, - 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, 0x007f, - 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, 0x3130, 0x1148, 0xb800, - 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbcf5, 0x1120, - 0x2009, 0x0003, 0x0804, 0x336b, 0x7007, 0x0003, 0x701f, 0x42b9, - 0x0005, 0x080c, 0x48bc, 0x0904, 0x336e, 0x20a9, 0x002b, 0xb8b4, - 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, - 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8b4, - 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f68, 0x0070, - 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8b4, 0x20e0, - 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f68, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, - 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48d5, 0x81ff, - 0x1904, 0x336b, 0x080c, 0x48a0, 0x0904, 0x336e, 0x080c, 0x63b9, - 0x0904, 0x336b, 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, 0x0004, - 0x0804, 0x336b, 0xa974, 0xaa94, 0x0804, 0x3339, 0x080c, 0x5397, - 0x0904, 0x3339, 0x701f, 0x4303, 0x7007, 0x0003, 0x0005, 0x81ff, - 0x1904, 0x336b, 0x7888, 0x908a, 0x1000, 0x1a04, 0x336e, 0x080c, - 0x48bc, 0x0904, 0x336e, 0x080c, 0x656b, 0x0120, 0x080c, 0x6573, - 0x1904, 0x336e, 0x080c, 0x643e, 0x0904, 0x336b, 0x2019, 0x0004, - 0x900e, 0x080c, 0x63cb, 0x0904, 0x336b, 0x7984, 0x7a88, 0x04c9, - 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, 0x080c, 0x48ba, 0x01e0, - 0x080c, 0x656b, 0x0118, 0x080c, 0x6573, 0x11b0, 0x080c, 0x643e, - 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, - 0x63cb, 0x2009, 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x080c, 0x5397, + 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, + 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, 0x0100, + 0x2001, 0x1981, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2275, + 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, + 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, + 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, + 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, + 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, + 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, + 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, + 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, 0x4894, + 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, 0x00ae, + 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, + 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030, 0x2024, + 0x2001, 0x0031, 0x201c, 0x080c, 0x4894, 0x2940, 0xa813, 0x0019, + 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, + 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, + 0x9080, 0x0019, 0x009e, 0x080c, 0x3f8e, 0x1d68, 0x2900, 0xa85a, + 0x00d8, 0x080c, 0x4894, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, + 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, 0x0031, + 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa06e, + 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003, 0x0004, + 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, 0x0200, + 0x2102, 0xa017, 0x0000, 0x2001, 0x1a3a, 0x2003, 0x0003, 0x2001, + 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, + 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, + 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x001b, + 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x2009, 0x013c, + 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, + 0x3344, 0x7d98, 0x7c9c, 0x0804, 0x3446, 0x080c, 0x6faa, 0x190c, + 0x5caa, 0x2069, 0x185b, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x48dd, 0x701f, 0x4061, + 0x0005, 0x080c, 0x53a9, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, + 0x20d8, 0x21d0, 0x2069, 0x185b, 0x6800, 0x9005, 0x0904, 0x3379, + 0x6804, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, + 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, + 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, + 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, + 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x3379, 0x9288, 0x3145, + 0x210d, 0x918c, 0x00ff, 0x6162, 0xd0dc, 0x0130, 0x6828, 0x908a, + 0x007f, 0x1a04, 0x3379, 0x605a, 0x6888, 0x9084, 0x0030, 0x8004, + 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x1989, 0x9080, 0x27ac, + 0x2005, 0x200a, 0x000e, 0x2009, 0x198a, 0x9080, 0x27b0, 0x2005, + 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x3379, 0x908a, 0x0841, + 0x1a04, 0x3379, 0x9084, 0x0007, 0x1904, 0x3379, 0x680c, 0x9005, + 0x0904, 0x3379, 0x6810, 0x9005, 0x0904, 0x3379, 0x6848, 0x6940, + 0x910a, 0x1a04, 0x3379, 0x8001, 0x0904, 0x3379, 0x684c, 0x6944, + 0x910a, 0x1a04, 0x3379, 0x8001, 0x0904, 0x3379, 0x2009, 0x1959, + 0x200b, 0x0000, 0x2001, 0x187d, 0x2004, 0xd0c4, 0x0140, 0x7884, + 0x200a, 0x2009, 0x017f, 0x200a, 0x3b00, 0xc085, 0x20d8, 0x6814, + 0x908c, 0x00ff, 0x614a, 0x8007, 0x9084, 0x00ff, 0x604e, 0x080c, + 0x72bd, 0x080c, 0x6643, 0x080c, 0x6678, 0x6808, 0x602a, 0x080c, + 0x21e7, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x2713, 0x003e, 0x6000, 0x9086, + 0x0000, 0x1904, 0x41de, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, + 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, + 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, + 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, + 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, + 0x198b, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x19a5, + 0x20e9, 0x0001, 0x4001, 0x080c, 0x8148, 0x00c6, 0x900e, 0x20a9, + 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, 0x0100, 0x210c, + 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, 0x3e18, 0x12b0, + 0x3508, 0x8109, 0x080c, 0x7889, 0x6878, 0x6016, 0x6874, 0x2008, + 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, + 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x414d, + 0x00ce, 0x00c6, 0x2061, 0x1974, 0x2063, 0x0001, 0x9006, 0x080c, + 0x29ba, 0x9006, 0x080c, 0x299d, 0x0000, 0x00ce, 0x00e6, 0x2c70, + 0x080c, 0x0e80, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, + 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, + 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, + 0x1954, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, + 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, + 0x2788, 0x2001, 0x1945, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, + 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x6faa, + 0x0128, 0x080c, 0x4ca6, 0x0110, 0x080c, 0x26d9, 0x60d0, 0x9005, + 0x01c0, 0x6003, 0x0001, 0x2009, 0x41c6, 0x00d0, 0x080c, 0x6faa, + 0x1168, 0x2011, 0x6e2b, 0x080c, 0x803f, 0x2011, 0x6e1e, 0x080c, + 0x8113, 0x080c, 0x7291, 0x080c, 0x6edc, 0x0040, 0x080c, 0x5ba4, + 0x0028, 0x6003, 0x0004, 0x2009, 0x41de, 0x0010, 0x0804, 0x3344, + 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, + 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, 0x0817, 0x6000, 0x9086, + 0x0000, 0x0904, 0x3376, 0x2069, 0x185b, 0x7890, 0x6842, 0x7894, + 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x2039, 0x0001, 0x0804, 0x48e0, 0x9006, 0x080c, 0x26d9, 0x81ff, + 0x1904, 0x3376, 0x080c, 0x6faa, 0x11b0, 0x080c, 0x728c, 0x080c, + 0x5ce5, 0x080c, 0x3140, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, + 0xc23b, 0x0130, 0x080c, 0x6fcd, 0x1118, 0x080c, 0x6f82, 0x0038, + 0x080c, 0x6edc, 0x0020, 0x080c, 0x5caa, 0x080c, 0x5ba4, 0x0804, + 0x3344, 0x81ff, 0x1904, 0x3376, 0x080c, 0x6faa, 0x1110, 0x0804, + 0x3376, 0x6190, 0x81ff, 0x01a8, 0x704f, 0x0000, 0x2001, 0x1c80, + 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, + 0x8000, 0x2039, 0x0001, 0x080c, 0x48e0, 0x701f, 0x3342, 0x012e, + 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1c80, 0x20a9, 0x0040, + 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, 0xffff, 0x4304, 0x6558, + 0x9588, 0x3145, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, + 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x6256, 0x1190, 0xb814, + 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085, 0xff00, 0x8007, 0x201a, + 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, + 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, + 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1c80, + 0x2099, 0x1c80, 0x080c, 0x5c35, 0x0804, 0x4236, 0x080c, 0x48c7, + 0x0904, 0x3379, 0x080c, 0x4894, 0x1120, 0x2009, 0x0002, 0x0804, + 0x3376, 0x080c, 0x539a, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, + 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, + 0x313b, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, + 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, + 0x080c, 0xbd04, 0x1120, 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, + 0x0003, 0x701f, 0x42c4, 0x0005, 0x080c, 0x48c7, 0x0904, 0x3379, + 0x20a9, 0x002b, 0xb8b4, 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, + 0x0006, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, + 0x080c, 0x0f68, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, + 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, + 0x0f68, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x0804, 0x48e0, 0x81ff, 0x1904, 0x3376, 0x080c, 0x48ab, 0x0904, + 0x3379, 0x080c, 0x63c8, 0x0904, 0x3376, 0x0058, 0xa878, 0x9005, + 0x0120, 0x2009, 0x0004, 0x0804, 0x3376, 0xa974, 0xaa94, 0x0804, + 0x3344, 0x080c, 0x53a2, 0x0904, 0x3344, 0x701f, 0x430e, 0x7007, + 0x0003, 0x0005, 0x81ff, 0x1904, 0x3376, 0x7888, 0x908a, 0x1000, + 0x1a04, 0x3379, 0x080c, 0x48c7, 0x0904, 0x3379, 0x080c, 0x657a, + 0x0120, 0x080c, 0x6582, 0x1904, 0x3379, 0x080c, 0x644d, 0x0904, + 0x3376, 0x2019, 0x0004, 0x900e, 0x080c, 0x63da, 0x0904, 0x3376, + 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, + 0x080c, 0x48c5, 0x01e0, 0x080c, 0x657a, 0x0118, 0x080c, 0x6582, + 0x11b0, 0x080c, 0x644d, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, + 0x2019, 0x0004, 0x080c, 0x63da, 0x2009, 0x0003, 0x0120, 0xa998, + 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, + 0x4000, 0x080c, 0x53a2, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, + 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x6458, 0x2400, 0x9506, + 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x6256, + 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x804d, + 0x0005, 0x81ff, 0x1904, 0x3376, 0x798c, 0x2001, 0x1958, 0x918c, + 0x8000, 0x2102, 0x080c, 0x48ab, 0x0904, 0x3379, 0x080c, 0x657a, + 0x0120, 0x080c, 0x6582, 0x1904, 0x3379, 0x080c, 0x631d, 0x0904, + 0x3376, 0x080c, 0x63d1, 0x0904, 0x3376, 0x2001, 0x1958, 0x2004, + 0xd0fc, 0x1904, 0x3344, 0x0804, 0x4319, 0xa9a0, 0x2001, 0x1958, + 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x48b8, 0x01a0, 0x080c, + 0x657a, 0x0118, 0x080c, 0x6582, 0x1170, 0x080c, 0x631d, 0x2009, + 0x0002, 0x0128, 0x080c, 0x63d1, 0x1170, 0x2009, 0x0003, 0xa897, + 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1958, 0x2004, + 0xd0fc, 0x1128, 0x080c, 0x53a2, 0x0110, 0x9006, 0x0018, 0x900e, + 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x3376, + 0x798c, 0x2001, 0x1957, 0x918c, 0x8000, 0x2102, 0x080c, 0x48ab, + 0x0904, 0x3379, 0x080c, 0x657a, 0x0120, 0x080c, 0x6582, 0x1904, + 0x3379, 0x080c, 0x631d, 0x0904, 0x3376, 0x080c, 0x63bf, 0x0904, + 0x3376, 0x2001, 0x1957, 0x2004, 0xd0fc, 0x1904, 0x3344, 0x0804, + 0x4319, 0xa9a0, 0x2001, 0x1957, 0x918c, 0x8000, 0xc18d, 0x2102, + 0x080c, 0x48b8, 0x01a0, 0x080c, 0x657a, 0x0118, 0x080c, 0x6582, + 0x1170, 0x080c, 0x631d, 0x2009, 0x0002, 0x0128, 0x080c, 0x63bf, + 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, + 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, + 0x4000, 0x2001, 0x1957, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x53a2, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, - 0x2061, 0x1800, 0x6458, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, - 0x8529, 0x1ec8, 0x0005, 0x080c, 0x6247, 0x1138, 0x2200, 0x8003, - 0x800b, 0x810b, 0x9108, 0x080c, 0x802f, 0x0005, 0x81ff, 0x1904, - 0x336b, 0x798c, 0x2001, 0x1950, 0x918c, 0x8000, 0x2102, 0x080c, - 0x48a0, 0x0904, 0x336e, 0x080c, 0x656b, 0x0120, 0x080c, 0x6573, - 0x1904, 0x336e, 0x080c, 0x630e, 0x0904, 0x336b, 0x080c, 0x63c2, - 0x0904, 0x336b, 0x2001, 0x1950, 0x2004, 0xd0fc, 0x1904, 0x3339, - 0x0804, 0x430e, 0xa9a0, 0x2001, 0x1950, 0x918c, 0x8000, 0xc18d, - 0x2102, 0x080c, 0x48ad, 0x01a0, 0x080c, 0x656b, 0x0118, 0x080c, - 0x6573, 0x1170, 0x080c, 0x630e, 0x2009, 0x0002, 0x0128, 0x080c, - 0x63c2, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, - 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, - 0xa897, 0x4000, 0x2001, 0x1950, 0x2004, 0xd0fc, 0x1128, 0x080c, - 0x5397, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0000, 0x0005, 0x81ff, 0x1904, 0x336b, 0x798c, 0x2001, 0x194f, - 0x918c, 0x8000, 0x2102, 0x080c, 0x48a0, 0x0904, 0x336e, 0x080c, - 0x656b, 0x0120, 0x080c, 0x6573, 0x1904, 0x336e, 0x080c, 0x630e, - 0x0904, 0x336b, 0x080c, 0x63b0, 0x0904, 0x336b, 0x2001, 0x194f, - 0x2004, 0xd0fc, 0x1904, 0x3339, 0x0804, 0x430e, 0xa9a0, 0x2001, - 0x194f, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x48ad, 0x01a0, - 0x080c, 0x656b, 0x0118, 0x080c, 0x6573, 0x1170, 0x080c, 0x630e, - 0x2009, 0x0002, 0x0128, 0x080c, 0x63b0, 0x1170, 0x2009, 0x0003, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x194f, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5397, 0x0110, 0x9006, 0x0018, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x6100, 0x0804, - 0x3339, 0x080c, 0x48bc, 0x0904, 0x336e, 0x080c, 0x53a3, 0x1904, - 0x336b, 0x79a8, 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, - 0x8007, 0x789a, 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, - 0x8007, 0x789e, 0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, 0xba18, - 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, 0x3339, 0x78a8, 0x909c, - 0x0003, 0xd0b4, 0x1148, 0x939a, 0x0003, 0x1a04, 0x336b, 0x6258, - 0x7884, 0x9206, 0x1904, 0x44be, 0x2031, 0x1848, 0x2009, 0x013c, - 0x2136, 0x2001, 0x1840, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x0006, 0x78a8, 0x9084, 0x0080, 0x11c8, - 0x0006, 0x0036, 0x2001, 0x1a4e, 0x201c, 0x7b9a, 0x2003, 0x0000, - 0x2001, 0x1a4f, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a50, - 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, 0x000e, 0x0804, - 0x48d5, 0x000e, 0x2031, 0x0000, 0x2061, 0x18ae, 0x2c44, 0xa66a, - 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, - 0x10d5, 0x7007, 0x0002, 0x701f, 0x44de, 0x0005, 0x81ff, 0x1904, - 0x336b, 0x080c, 0x48bc, 0x0904, 0x336e, 0x080c, 0x656b, 0x1904, - 0x336b, 0x00c6, 0x080c, 0x4889, 0x00ce, 0x0904, 0x336b, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xbc9b, 0x0904, - 0x336b, 0x7007, 0x0003, 0x701f, 0x44f8, 0x0005, 0x080c, 0x4028, - 0x0006, 0x0036, 0x2001, 0x1a4e, 0x201c, 0x7b9a, 0x2003, 0x0000, - 0x2001, 0x1a4f, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a50, - 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, 0x000e, 0x0804, 0x3339, - 0xa830, 0x9086, 0x0100, 0x0904, 0x336b, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48d5, 0x9006, 0x080c, - 0x26ce, 0x78a8, 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, - 0x1904, 0x336b, 0x080c, 0x6f9b, 0x0110, 0x080c, 0x5c9f, 0x7888, - 0x908a, 0x1000, 0x1a04, 0x336e, 0x7984, 0x9186, 0x00ff, 0x0138, - 0x9182, 0x007f, 0x1a04, 0x336e, 0x2100, 0x080c, 0x2698, 0x0026, - 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, 0x19ca, 0x601b, 0x0000, - 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, 0x0000, 0x080c, 0x6f9b, - 0x1158, 0x080c, 0x727f, 0x080c, 0x5cda, 0x9085, 0x0001, 0x080c, - 0x6fe2, 0x080c, 0x6ecd, 0x00d0, 0x080c, 0x9dc8, 0x2061, 0x0100, - 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1969, 0x200b, 0x0000, - 0x2009, 0x002d, 0x2011, 0x5bc5, 0x080c, 0x80b3, 0x7984, 0x080c, - 0x6f9b, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x4371, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x3339, 0x7984, 0x080c, 0x61e7, 0x2b08, - 0x1904, 0x336e, 0x0804, 0x3339, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x336b, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, - 0x0005, 0x0804, 0x336b, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, - 0x0804, 0x336b, 0x7984, 0x9192, 0x0021, 0x1a04, 0x336e, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, - 0x7736, 0x080c, 0x48d2, 0x701f, 0x45ac, 0x7880, 0x9086, 0x006e, - 0x0110, 0x701f, 0x4e4d, 0x0005, 0x2009, 0x0080, 0x080c, 0x6247, - 0x1118, 0x080c, 0x656b, 0x0120, 0x2021, 0x400a, 0x0804, 0x333b, - 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, - 0xa884, 0x90be, 0x0100, 0x0904, 0x4645, 0x90be, 0x0112, 0x0904, - 0x4645, 0x90be, 0x0113, 0x0904, 0x4645, 0x90be, 0x0114, 0x0904, - 0x4645, 0x90be, 0x0117, 0x0904, 0x4645, 0x90be, 0x011a, 0x0904, - 0x4645, 0x90be, 0x011c, 0x0904, 0x4645, 0x90be, 0x0121, 0x0904, - 0x462c, 0x90be, 0x0131, 0x0904, 0x462c, 0x90be, 0x0171, 0x0904, - 0x4645, 0x90be, 0x0173, 0x0904, 0x4645, 0x90be, 0x01a1, 0x1128, - 0xa894, 0x8007, 0xa896, 0x0804, 0x4650, 0x90be, 0x0212, 0x0904, - 0x4639, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, - 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, - 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, - 0x00de, 0x0804, 0x336e, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, - 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x468e, 0x7028, - 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0001, 0x080c, 0x468e, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x469b, - 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x469b, 0x7028, 0x9080, 0x000c, - 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, - 0x00c6, 0x080c, 0x4889, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, - 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, - 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, - 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, - 0xa804, 0x2048, 0x080c, 0xbcb6, 0x1120, 0x2009, 0x0003, 0x0804, - 0x336b, 0x7007, 0x0003, 0x701f, 0x4685, 0x0005, 0x00ce, 0x009e, - 0x00de, 0x2009, 0x0002, 0x0804, 0x336b, 0xa820, 0x9086, 0x8001, - 0x1904, 0x3339, 0x2009, 0x0004, 0x0804, 0x336b, 0x0016, 0x0026, - 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, - 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, - 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, - 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x336b, 0x60d8, 0xd0ac, 0x1160, 0xd09c, - 0x0120, 0x2009, 0x0016, 0x0804, 0x336b, 0xd09c, 0x1120, 0x2009, - 0x0005, 0x0804, 0x336b, 0x7984, 0x78a8, 0x2040, 0x080c, 0x9dc1, - 0x1120, 0x9182, 0x007f, 0x0a04, 0x336e, 0x9186, 0x00ff, 0x0904, - 0x336e, 0x9182, 0x0800, 0x1a04, 0x336e, 0x7a8c, 0x7b88, 0x6078, - 0x9306, 0x1158, 0x607c, 0x924e, 0x0904, 0x336e, 0x080c, 0x9dc1, - 0x1120, 0x99cc, 0xff00, 0x0904, 0x336e, 0x0126, 0x2091, 0x8000, - 0x0026, 0x2011, 0x8008, 0x080c, 0x658f, 0x002e, 0x0140, 0x918d, - 0x8000, 0x080c, 0x65d9, 0x1118, 0x2001, 0x4009, 0x0458, 0x080c, - 0x47a3, 0x0560, 0x90c6, 0x4000, 0x1170, 0x00c6, 0x0006, 0x900e, - 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, - 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, - 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, - 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, - 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x333b, 0x2b00, 0x7026, - 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9e8f, 0x0904, - 0x4770, 0x2b00, 0x6012, 0x080c, 0xbfa6, 0x2e58, 0x00ee, 0x00e6, - 0x00c6, 0x080c, 0x4889, 0x00ce, 0x2b70, 0x1158, 0x080c, 0x9e42, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, - 0x336b, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, 0xa868, - 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x080c, 0x2fdc, 0x6023, - 0x0001, 0x9006, 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, - 0x2009, 0x0002, 0x080c, 0x9ebc, 0x78a8, 0xd094, 0x0138, 0x00ee, - 0x7024, 0x00e6, 0x2058, 0xb8bc, 0xc08d, 0xb8be, 0x9085, 0x0001, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x336b, 0x7007, 0x0003, 0x701f, 0x477f, 0x0005, 0xa830, - 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x333b, - 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, 0xba04, - 0x9294, 0x00ff, 0x0804, 0x52ec, 0x900e, 0xa868, 0xd0f4, 0x1904, - 0x3339, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x3339, 0x00e6, 0x00d6, 0x0096, 0x83ff, 0x0904, - 0x47eb, 0x902e, 0x080c, 0x9dc1, 0x0130, 0x9026, 0x20a9, 0x0800, - 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, - 0x107f, 0x2e04, 0x9005, 0x11b0, 0x2100, 0x9406, 0x15e8, 0x2428, - 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1528, 0x0030, 0x94ce, - 0x0080, 0x1130, 0x92ce, 0xfffc, 0x11f0, 0x93ce, 0x00ff, 0x11d8, - 0xc5fd, 0x0450, 0x2058, 0xbf10, 0x2700, 0x9306, 0x11b8, 0xbe14, - 0x2600, 0x9206, 0x1198, 0x2400, 0x9106, 0x1150, 0xd884, 0x0568, - 0xd894, 0x1558, 0x080c, 0x656b, 0x1540, 0x2001, 0x4000, 0x0430, - 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, - 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0948, 0x080c, 0x9dc1, - 0x1930, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x47b9, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x61e7, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x336b, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, 0x336b, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, - 0x336e, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x336e, - 0x2010, 0x2918, 0x080c, 0x2f82, 0x1120, 0x2009, 0x0003, 0x0804, - 0x336b, 0x7007, 0x0003, 0x701f, 0x483e, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1904, 0x3339, 0x2009, 0x0004, 0x0804, 0x336b, 0x7984, - 0x080c, 0x9dc1, 0x1120, 0x9182, 0x007f, 0x0a04, 0x336e, 0x9186, - 0x00ff, 0x0904, 0x336e, 0x9182, 0x0800, 0x1a04, 0x336e, 0x2001, - 0x9000, 0x080c, 0x5347, 0x1904, 0x336b, 0x0804, 0x3339, 0xa998, - 0x080c, 0x9dc1, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, - 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9000, 0x080c, 0x5347, - 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, 0x000a, - 0x0c48, 0x080c, 0x0feb, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, - 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, - 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, - 0x7984, 0x080c, 0x6247, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x6247, - 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, - 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x6247, - 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, - 0x0128, 0x2148, 0xa904, 0x080c, 0x101d, 0x0cc8, 0x7116, 0x711a, - 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, - 0x18ae, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x10d5, 0x7007, 0x0002, 0x701f, 0x3339, - 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, - 0x18a6, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4906, 0x7a36, 0x7833, - 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1187, 0x0804, 0x496c, 0x0016, 0x0086, - 0x0096, 0x00c6, 0x00e6, 0x2071, 0x1894, 0x7044, 0x9005, 0x1540, - 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x0feb, - 0x0904, 0x4964, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, - 0x9080, 0x1f28, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, - 0x2001, 0x18b0, 0x9c82, 0x18f0, 0x0210, 0x2061, 0x18b0, 0x2c00, - 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, - 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, - 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x2060, 0x001e, 0x8108, 0x2105, - 0x9005, 0xa146, 0x1520, 0x080c, 0x0feb, 0x1130, 0x8109, 0xa946, - 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, - 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, - 0x1f28, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, - 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, - 0x9082, 0x001b, 0x0002, 0x498e, 0x498e, 0x4990, 0x498e, 0x498e, - 0x498e, 0x4994, 0x498e, 0x498e, 0x498e, 0x4998, 0x498e, 0x498e, - 0x498e, 0x499c, 0x498e, 0x498e, 0x498e, 0x49a0, 0x498e, 0x498e, - 0x498e, 0x49a4, 0x498e, 0x498e, 0x498e, 0x49a9, 0x080c, 0x0db4, - 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, - 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, - 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, - 0x4967, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4967, 0x00e6, 0x2071, - 0x1894, 0x7048, 0x9005, 0x0904, 0x4a40, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x4a3f, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, - 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, - 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x2060, 0x001e, - 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4a42, 0xa804, 0x9005, - 0x090c, 0x0db4, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, - 0x0002, 0x9080, 0x1f28, 0x2005, 0xa04a, 0x0804, 0x4a42, 0x703c, - 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, - 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x87ff, 0x0118, - 0x2748, 0x080c, 0x101d, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, - 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x101d, 0x9006, 0x7042, - 0x7046, 0x703b, 0x18b0, 0x703f, 0x18b0, 0x0420, 0x7040, 0x9005, - 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, - 0x18f0, 0x0210, 0x2001, 0x18b0, 0x703e, 0x00a0, 0x9006, 0x703e, - 0x703a, 0x7044, 0x9005, 0x090c, 0x0db4, 0x2048, 0xa800, 0x9005, - 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1f28, 0x2005, - 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, - 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4a61, 0x4a61, - 0x4a63, 0x4a61, 0x4a61, 0x4a61, 0x4a68, 0x4a61, 0x4a61, 0x4a61, - 0x4a6d, 0x4a61, 0x4a61, 0x4a61, 0x4a72, 0x4a61, 0x4a61, 0x4a61, - 0x4a77, 0x4a61, 0x4a61, 0x4a61, 0x4a7c, 0x4a61, 0x4a61, 0x4a61, - 0x4a81, 0x080c, 0x0db4, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x49ed, - 0xaa84, 0xab88, 0xac8c, 0x0804, 0x49ed, 0xaa94, 0xab98, 0xac9c, - 0x0804, 0x49ed, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x49ed, 0xaab4, - 0xabb8, 0xacbc, 0x0804, 0x49ed, 0xaac4, 0xabc8, 0xaccc, 0x0804, - 0x49ed, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x49ed, 0x0026, 0x080c, - 0x538f, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x48e9, 0x002e, - 0x0005, 0x81ff, 0x1904, 0x336b, 0x0126, 0x2091, 0x8000, 0x6030, - 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x6f9b, 0x1158, 0x080c, - 0x727f, 0x080c, 0x5cda, 0x9085, 0x0001, 0x080c, 0x6fe2, 0x080c, - 0x6ecd, 0x0010, 0x080c, 0x5b99, 0x012e, 0x0804, 0x3339, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x336b, 0x080c, 0x53a3, 0x0120, - 0x2009, 0x0007, 0x0804, 0x336b, 0x080c, 0x6563, 0x0120, 0x2009, - 0x0008, 0x0804, 0x336b, 0x0026, 0x2011, 0x0010, 0x080c, 0x658f, - 0x002e, 0x0140, 0x7984, 0x080c, 0x65d9, 0x1120, 0x2009, 0x4009, - 0x0804, 0x336b, 0x7984, 0x080c, 0x61e7, 0x1904, 0x336e, 0x2b00, - 0x7026, 0x080c, 0x656b, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, - 0x900e, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x3339, 0x080c, 0x4889, 0x0904, 0x336b, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbd54, 0x0904, - 0x336b, 0x7888, 0xd094, 0x0118, 0xb8bc, 0xc08d, 0xb8be, 0x7007, - 0x0003, 0x701f, 0x4b50, 0x0005, 0x2061, 0x1800, 0x080c, 0x53a3, - 0x2009, 0x0007, 0x1578, 0x080c, 0x6563, 0x0118, 0x2009, 0x0008, - 0x0448, 0x080c, 0x3130, 0x0120, 0xa998, 0x080c, 0x61e7, 0x1530, - 0x080c, 0x48ba, 0x0518, 0x080c, 0x656b, 0xa89c, 0x1168, 0x9084, - 0x0005, 0x1150, 0x900e, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, - 0xbd54, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8bc, 0xc08d, 0xb8be, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, - 0xa830, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x333b, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x52ec, - 0x900e, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x3339, 0x080c, 0x53a3, 0x0120, 0x2009, 0x0007, - 0x0804, 0x336b, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, - 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, 0x336b, 0x900e, 0x2130, - 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, - 0x702a, 0x20a0, 0x080c, 0x6247, 0x1904, 0x4bee, 0x080c, 0x656b, - 0x0120, 0x080c, 0x6573, 0x1904, 0x4bee, 0x080c, 0x6563, 0x1130, - 0x080c, 0x6467, 0x1118, 0xd79c, 0x0904, 0x4bee, 0xd794, 0x1110, - 0xd784, 0x01a8, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, - 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, - 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x469b, 0x0048, 0x20a9, - 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x469b, - 0x4104, 0xd794, 0x0528, 0xb8b4, 0x20e0, 0xb8b8, 0x2060, 0x9c80, - 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, - 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, - 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x468e, - 0x9c80, 0x0026, 0x2098, 0xb8b4, 0x20e0, 0x20a9, 0x0002, 0x4003, - 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, - 0x9dc1, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, - 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, - 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4b8a, - 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x3339, 0x7033, 0x0001, - 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18ae, 0x2c44, - 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x10d5, 0x7007, 0x0002, 0x701f, - 0x4c2a, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, - 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18ae, 0x2c44, 0xa28c, - 0xa390, 0xa494, 0xa598, 0x0804, 0x4b8a, 0x7124, 0x810b, 0x0804, - 0x3339, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x336e, 0x9502, 0x0a04, - 0x336e, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x336e, 0x9502, - 0x0a04, 0x336e, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x336e, 0x9502, 0x0a04, 0x336e, 0x9284, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x336e, 0x9502, 0x0a04, 0x336e, 0x9384, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x336e, 0x9502, 0x0a04, 0x336e, 0x9384, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x336e, 0x9502, 0x0a04, 0x336e, - 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x336e, 0x9502, - 0x0a04, 0x336e, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x336e, - 0x9502, 0x0a04, 0x336e, 0x2061, 0x1959, 0x6102, 0x6206, 0x630a, - 0x640e, 0x0804, 0x3339, 0x0006, 0x080c, 0x538f, 0xd0cc, 0x000e, - 0x0005, 0x0006, 0x080c, 0x5393, 0xd0bc, 0x000e, 0x0005, 0x6170, - 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x3339, 0x83ff, - 0x1904, 0x336e, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x336e, 0x2019, - 0xffff, 0x6074, 0x9302, 0x9200, 0x0a04, 0x336e, 0x7986, 0x6272, - 0x0804, 0x3339, 0x080c, 0x53a3, 0x1904, 0x336b, 0x7c88, 0x7d84, - 0x7e98, 0x7f8c, 0x080c, 0x4889, 0x0904, 0x336b, 0x900e, 0x901e, - 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, - 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, - 0x656b, 0x0118, 0x080c, 0x6573, 0x1148, 0x20a9, 0x0001, 0xb814, + 0x0005, 0x6100, 0x0804, 0x3344, 0x080c, 0x48c7, 0x0904, 0x3379, + 0x080c, 0x53ae, 0x1904, 0x3376, 0x79a8, 0xd184, 0x1158, 0xb834, + 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, 0xba28, + 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, 0x789a, + 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, + 0x3344, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1158, 0xd0b4, 0x1148, + 0x939a, 0x0003, 0x1a04, 0x3376, 0x6258, 0x7884, 0x9206, 0x1904, + 0x44c9, 0x2031, 0x1848, 0x2009, 0x013c, 0x2136, 0x2001, 0x1840, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0006, 0x78a8, + 0x9084, 0x0080, 0x11c8, 0x0006, 0x0036, 0x2001, 0x1a56, 0x201c, + 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a57, 0x201c, 0x7b9e, 0x2003, + 0x0000, 0x2001, 0x1a58, 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, + 0x000e, 0x000e, 0x0804, 0x48e0, 0x000e, 0x2031, 0x0000, 0x2061, + 0x18b6, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, + 0xa496, 0xa59a, 0x080c, 0x10d5, 0x7007, 0x0002, 0x701f, 0x44e9, + 0x0005, 0x81ff, 0x1904, 0x3376, 0x080c, 0x48c7, 0x0904, 0x3379, + 0x080c, 0x657a, 0x1904, 0x3376, 0x00c6, 0x080c, 0x4894, 0x00ce, + 0x0904, 0x3376, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, + 0x080c, 0xbcaa, 0x0904, 0x3376, 0x7007, 0x0003, 0x701f, 0x4503, + 0x0005, 0x080c, 0x4033, 0x0006, 0x0036, 0x2001, 0x1a56, 0x201c, + 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a57, 0x201c, 0x7b9e, 0x2003, + 0x0000, 0x2001, 0x1a58, 0x201c, 0x7ba2, 0x2003, 0x0000, 0x003e, + 0x000e, 0x0804, 0x3344, 0xa830, 0x9086, 0x0100, 0x0904, 0x3376, + 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, + 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, + 0x48e0, 0x9006, 0x080c, 0x26d9, 0x78a8, 0x9084, 0x00ff, 0x9086, + 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3376, 0x080c, 0x6faa, 0x0110, + 0x080c, 0x5caa, 0x7888, 0x908a, 0x1000, 0x1a04, 0x3379, 0x7984, + 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, 0x3379, 0x2100, + 0x080c, 0x26a3, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2061, + 0x19d2, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, 0x0000, 0x6077, + 0x0000, 0x080c, 0x6faa, 0x1158, 0x080c, 0x728c, 0x080c, 0x5ce5, + 0x9085, 0x0001, 0x080c, 0x6ff1, 0x080c, 0x6edc, 0x00d0, 0x080c, + 0x9db5, 0x2061, 0x0100, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, + 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, + 0x1971, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5bd0, 0x080c, + 0x80d1, 0x7984, 0x080c, 0x6faa, 0x1110, 0x2009, 0x00ff, 0x7a88, + 0x080c, 0x437c, 0x012e, 0x00ce, 0x002e, 0x0804, 0x3344, 0x7984, + 0x080c, 0x61f6, 0x2b08, 0x1904, 0x3379, 0x0804, 0x3344, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, 0x60d8, 0xd0ac, 0x1130, + 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3376, 0x080c, 0x4894, + 0x1120, 0x2009, 0x0002, 0x0804, 0x3376, 0x7984, 0x9192, 0x0021, + 0x1a04, 0x3379, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, + 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x48dd, 0x701f, 0x45b7, + 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x4e58, 0x0005, 0x2009, + 0x0080, 0x080c, 0x6256, 0x1118, 0x080c, 0x657a, 0x0120, 0x2021, + 0x400a, 0x0804, 0x3346, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, + 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, 0x4650, + 0x90be, 0x0112, 0x0904, 0x4650, 0x90be, 0x0113, 0x0904, 0x4650, + 0x90be, 0x0114, 0x0904, 0x4650, 0x90be, 0x0117, 0x0904, 0x4650, + 0x90be, 0x011a, 0x0904, 0x4650, 0x90be, 0x011c, 0x0904, 0x4650, + 0x90be, 0x0121, 0x0904, 0x4637, 0x90be, 0x0131, 0x0904, 0x4637, + 0x90be, 0x0171, 0x0904, 0x4650, 0x90be, 0x0173, 0x0904, 0x4650, + 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, 0x465b, + 0x90be, 0x0212, 0x0904, 0x4644, 0x90be, 0x0213, 0x05e8, 0x90be, + 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, + 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, + 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x3379, 0x7028, 0x9080, + 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, + 0x080c, 0x4699, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, + 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4699, 0x00c8, 0x7028, + 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, + 0x0001, 0x080c, 0x46a6, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, + 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x46a6, + 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, + 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4894, 0x0550, 0xa868, + 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, + 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, + 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, + 0xa868, 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c, 0xbcc5, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, 0x701f, 0x4690, + 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, 0x3376, + 0xa820, 0x9086, 0x8001, 0x1904, 0x3344, 0x2009, 0x0004, 0x0804, + 0x3376, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, + 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, + 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, + 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, + 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, 0x60d8, + 0xd0ac, 0x1160, 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x3376, + 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3376, 0x7984, 0x78a8, + 0x2040, 0x080c, 0x9dae, 0x1120, 0x9182, 0x007f, 0x0a04, 0x3379, + 0x9186, 0x00ff, 0x0904, 0x3379, 0x9182, 0x0800, 0x1a04, 0x3379, + 0x7a8c, 0x7b88, 0x6078, 0x9306, 0x1158, 0x607c, 0x924e, 0x0904, + 0x3379, 0x080c, 0x9dae, 0x1120, 0x99cc, 0xff00, 0x0904, 0x3379, + 0x0126, 0x2091, 0x8000, 0x0026, 0x2011, 0x8008, 0x080c, 0x659e, + 0x002e, 0x0140, 0x918d, 0x8000, 0x080c, 0x65e8, 0x1118, 0x2001, + 0x4009, 0x0458, 0x080c, 0x47ae, 0x0560, 0x90c6, 0x4000, 0x1170, + 0x00c6, 0x0006, 0x900e, 0x080c, 0x6476, 0x1108, 0xc185, 0xb800, + 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, + 0x1110, 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, + 0x0060, 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, + 0x0020, 0x2001, 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, + 0x3346, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, + 0x080c, 0x9e7c, 0x0904, 0x477b, 0x2b00, 0x6012, 0x080c, 0xbfb5, + 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4894, 0x00ce, 0x2b70, + 0x1158, 0x080c, 0x9e2f, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, + 0x2009, 0x0002, 0x0804, 0x3376, 0x900e, 0xa966, 0xa96a, 0x2900, + 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, + 0x080c, 0x2fe7, 0x6023, 0x0001, 0x9006, 0x080c, 0x6193, 0x2001, + 0x0002, 0x080c, 0x61a7, 0x2009, 0x0002, 0x080c, 0x9ea9, 0x78a8, + 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8bc, 0xc08d, + 0xb8be, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, + 0x1120, 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, 0x701f, + 0x478a, 0x0005, 0xa830, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, + 0x4009, 0x0804, 0x3346, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, + 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, 0x0804, 0x52f7, 0x900e, + 0xa868, 0xd0f4, 0x1904, 0x3344, 0x080c, 0x6476, 0x1108, 0xc185, + 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3344, 0x00e6, 0x00d6, + 0x0096, 0x83ff, 0x0904, 0x47f6, 0x902e, 0x080c, 0x9dae, 0x0130, + 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, + 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b0, 0x2100, + 0x9406, 0x15e8, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, + 0x1528, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x11f0, + 0x93ce, 0x00ff, 0x11d8, 0xc5fd, 0x0450, 0x2058, 0xbf10, 0x2700, + 0x9306, 0x11b8, 0xbe14, 0x2600, 0x9206, 0x1198, 0x2400, 0x9106, + 0x1150, 0xd884, 0x0568, 0xd894, 0x1558, 0x080c, 0x657a, 0x1540, + 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, + 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, + 0x0948, 0x080c, 0x9dae, 0x1930, 0x2001, 0x4008, 0x0090, 0x8420, + 0x8e70, 0x1f04, 0x47c4, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, + 0x2001, 0x0001, 0x0030, 0x080c, 0x61f6, 0x1dd0, 0xbb12, 0xba16, + 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3376, 0x080c, 0x4894, 0x1120, 0x2009, + 0x0002, 0x0804, 0x3376, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, + 0x7884, 0x9005, 0x0904, 0x3379, 0x9096, 0x00ff, 0x0120, 0x9092, + 0x0004, 0x1a04, 0x3379, 0x2010, 0x2918, 0x080c, 0x2f8d, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, 0x701f, 0x4849, + 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x3344, 0x2009, 0x0004, + 0x0804, 0x3376, 0x7984, 0x080c, 0x9dae, 0x1120, 0x9182, 0x007f, + 0x0a04, 0x3379, 0x9186, 0x00ff, 0x0904, 0x3379, 0x9182, 0x0800, + 0x1a04, 0x3379, 0x2001, 0x9000, 0x080c, 0x5352, 0x1904, 0x3376, + 0x0804, 0x3344, 0xa998, 0x080c, 0x9dae, 0x1118, 0x9182, 0x007f, + 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, + 0x9000, 0x080c, 0x5352, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, + 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, + 0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x0feb, 0x0198, 0x9006, + 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, + 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, + 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6256, 0x1130, 0x7e88, + 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, + 0xa998, 0x080c, 0x6256, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, + 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, + 0x2608, 0x080c, 0x6256, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, + 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x101d, + 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, + 0x2031, 0x0000, 0x2061, 0x18b6, 0x2c44, 0xa66a, 0xa17a, 0xa772, + 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10d5, 0x7007, + 0x0002, 0x701f, 0x3344, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, + 0x2079, 0x0000, 0x2001, 0x18ae, 0x2004, 0x9005, 0x1190, 0x0e04, + 0x4911, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x0804, + 0x4977, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189c, + 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, + 0x2060, 0x080c, 0x0feb, 0x0904, 0x496f, 0xa84b, 0x0000, 0x2900, + 0x7046, 0x2001, 0x0002, 0x9080, 0x1f33, 0x2005, 0xa846, 0x0098, + 0x7038, 0x90e0, 0x0004, 0x2001, 0x18b8, 0x9c82, 0x18f8, 0x0210, + 0x2061, 0x18b8, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, + 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, + 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0db4, 0x2060, + 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x0feb, + 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, + 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, + 0x2001, 0x0002, 0x9080, 0x1f33, 0x2005, 0xa846, 0x0058, 0x2262, + 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, + 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4999, 0x4999, + 0x499b, 0x4999, 0x4999, 0x4999, 0x499f, 0x4999, 0x4999, 0x4999, + 0x49a3, 0x4999, 0x4999, 0x4999, 0x49a7, 0x4999, 0x4999, 0x4999, + 0x49ab, 0x4999, 0x4999, 0x4999, 0x49af, 0x4999, 0x4999, 0x4999, + 0x49b4, 0x080c, 0x0db4, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, + 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, + 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, + 0xa3ca, 0xa4ce, 0x0804, 0x4972, 0xa2d6, 0xa3da, 0xa4de, 0x0804, + 0x4972, 0x00e6, 0x2071, 0x189c, 0x7048, 0x9005, 0x0904, 0x4a4b, + 0x0126, 0x2091, 0x8000, 0x0e04, 0x4a4a, 0x00f6, 0x2079, 0x0000, + 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, + 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, + 0x0db4, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, + 0x4a4d, 0xa804, 0x9005, 0x090c, 0x0db4, 0x7042, 0x2938, 0x2040, + 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x1f33, 0x2005, 0xa04a, + 0x0804, 0x4a4d, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, + 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, + 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1187, 0x87ff, 0x0118, 0x2748, 0x080c, 0x101d, 0x7048, 0x8001, + 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, + 0x101d, 0x9006, 0x7042, 0x7046, 0x703b, 0x18b8, 0x703f, 0x18b8, + 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, + 0x9c80, 0x0004, 0x90fa, 0x18f8, 0x0210, 0x2001, 0x18b8, 0x703e, + 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0db4, + 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, + 0x9080, 0x1f33, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, + 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, + 0x0002, 0x4a6c, 0x4a6c, 0x4a6e, 0x4a6c, 0x4a6c, 0x4a6c, 0x4a73, + 0x4a6c, 0x4a6c, 0x4a6c, 0x4a78, 0x4a6c, 0x4a6c, 0x4a6c, 0x4a7d, + 0x4a6c, 0x4a6c, 0x4a6c, 0x4a82, 0x4a6c, 0x4a6c, 0x4a6c, 0x4a87, + 0x4a6c, 0x4a6c, 0x4a6c, 0x4a8c, 0x080c, 0x0db4, 0xaa74, 0xab78, + 0xac7c, 0x0804, 0x49f8, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x49f8, + 0xaa94, 0xab98, 0xac9c, 0x0804, 0x49f8, 0xaaa4, 0xaba8, 0xacac, + 0x0804, 0x49f8, 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x49f8, 0xaac4, + 0xabc8, 0xaccc, 0x0804, 0x49f8, 0xaad4, 0xabd8, 0xacdc, 0x0804, + 0x49f8, 0x0026, 0x080c, 0x539a, 0xd0c4, 0x0120, 0x2011, 0x8014, + 0x080c, 0x48f4, 0x002e, 0x0005, 0x81ff, 0x1904, 0x3376, 0x0126, + 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, + 0x6faa, 0x1158, 0x080c, 0x728c, 0x080c, 0x5ce5, 0x9085, 0x0001, + 0x080c, 0x6ff1, 0x080c, 0x6edc, 0x0010, 0x080c, 0x5ba4, 0x012e, + 0x0804, 0x3344, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, + 0x080c, 0x53ae, 0x0120, 0x2009, 0x0007, 0x0804, 0x3376, 0x080c, + 0x6572, 0x0120, 0x2009, 0x0008, 0x0804, 0x3376, 0x0026, 0x2011, + 0x0010, 0x080c, 0x659e, 0x002e, 0x0140, 0x7984, 0x080c, 0x65e8, + 0x1120, 0x2009, 0x4009, 0x0804, 0x3376, 0x7984, 0x080c, 0x61f6, + 0x1904, 0x3379, 0x2b00, 0x7026, 0x080c, 0x657a, 0x7888, 0x1170, + 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6476, 0x1108, 0xc185, + 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3344, 0x080c, 0x4894, + 0x0904, 0x3376, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, + 0x080c, 0xbd63, 0x0904, 0x3376, 0x7888, 0xd094, 0x0118, 0xb8bc, + 0xc08d, 0xb8be, 0x7007, 0x0003, 0x701f, 0x4b5b, 0x0005, 0x2061, + 0x1800, 0x080c, 0x53ae, 0x2009, 0x0007, 0x1578, 0x080c, 0x6572, + 0x0118, 0x2009, 0x0008, 0x0448, 0x080c, 0x313b, 0x0120, 0xa998, + 0x080c, 0x61f6, 0x1530, 0x080c, 0x48c5, 0x0518, 0x080c, 0x657a, + 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6476, + 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, + 0xc0fc, 0xa86a, 0x080c, 0xbd63, 0x11e0, 0xa89c, 0xd094, 0x0118, + 0xb8bc, 0xc08d, 0xb8be, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, + 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, + 0x0005, 0x9006, 0x0005, 0xa830, 0x2008, 0x918e, 0xdead, 0x1120, + 0x2021, 0x4009, 0x0804, 0x3346, 0x9086, 0x0100, 0x7024, 0x2058, + 0x1110, 0x0804, 0x52f7, 0x900e, 0x080c, 0x6476, 0x1108, 0xc185, + 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x3344, 0x080c, 0x53ae, + 0x0120, 0x2009, 0x0007, 0x0804, 0x3376, 0x7f84, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x080c, 0x4894, 0x1120, 0x2009, 0x0002, 0x0804, + 0x3376, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, + 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, 0x6256, 0x1904, + 0x4bf9, 0x080c, 0x657a, 0x0120, 0x080c, 0x6582, 0x1904, 0x4bf9, + 0x080c, 0x6572, 0x1130, 0x080c, 0x6476, 0x1118, 0xd79c, 0x0904, + 0x4bf9, 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8b4, 0x20e0, 0xb8b8, + 0x9080, 0x0006, 0x2098, 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, + 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, + 0x46a6, 0x0048, 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, + 0x20e0, 0x080c, 0x46a6, 0x4104, 0xd794, 0x0528, 0xb8b4, 0x20e0, + 0xb8b8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, + 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, + 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, + 0x20e0, 0x080c, 0x4699, 0x9c80, 0x0026, 0x2098, 0xb8b4, 0x20e0, + 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, + 0x0005, 0x8108, 0x080c, 0x9dae, 0x0118, 0x9186, 0x0800, 0x0040, + 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, + 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, + 0x0150, 0x0804, 0x4b95, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, + 0x3344, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, + 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, + 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10d5, + 0x7007, 0x0002, 0x701f, 0x4c35, 0x0005, 0x7030, 0x9005, 0x1180, + 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, + 0x18b6, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4b95, + 0x7124, 0x810b, 0x0804, 0x3344, 0x2029, 0x007e, 0x7984, 0x7a88, + 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, + 0x3379, 0x9502, 0x0a04, 0x3379, 0x9184, 0x00ff, 0x90e2, 0x0020, + 0x0a04, 0x3379, 0x9502, 0x0a04, 0x3379, 0x9284, 0xff00, 0x8007, + 0x90e2, 0x0020, 0x0a04, 0x3379, 0x9502, 0x0a04, 0x3379, 0x9284, + 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3379, 0x9502, 0x0a04, 0x3379, + 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x3379, 0x9502, + 0x0a04, 0x3379, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x3379, + 0x9502, 0x0a04, 0x3379, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x3379, 0x9502, 0x0a04, 0x3379, 0x9484, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x3379, 0x9502, 0x0a04, 0x3379, 0x2061, 0x1961, + 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x3344, 0x0006, 0x080c, + 0x539a, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, 0x539e, 0xd0bc, + 0x000e, 0x0005, 0x6170, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, + 0x0804, 0x3344, 0x83ff, 0x1904, 0x3379, 0x2001, 0xfff0, 0x9200, + 0x1a04, 0x3379, 0x2019, 0xffff, 0x6074, 0x9302, 0x9200, 0x0a04, + 0x3379, 0x7986, 0x6272, 0x0804, 0x3344, 0x080c, 0x53ae, 0x1904, + 0x3376, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x4894, 0x0904, + 0x3376, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, + 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, + 0x8bff, 0x0178, 0x080c, 0x657a, 0x0118, 0x080c, 0x6582, 0x1148, + 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, + 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, + 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, + 0x8277, 0x2208, 0x0804, 0x3344, 0x7033, 0x0001, 0x7122, 0x7024, + 0x9300, 0x7026, 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, 0xa37a, + 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, + 0x080c, 0x10d5, 0x7007, 0x0002, 0x701f, 0x4d27, 0x0005, 0x7030, + 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, + 0x2061, 0x18b6, 0x2c44, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, + 0x4ce5, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x8277, 0x2208, + 0x0804, 0x3344, 0x00f6, 0x00e6, 0x080c, 0x53ae, 0x2009, 0x0007, + 0x1904, 0x4dba, 0x2071, 0x189c, 0x745c, 0x84ff, 0x2009, 0x000e, + 0x1904, 0x4dba, 0xac9c, 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, + 0x1004, 0x2009, 0x0002, 0x0904, 0x4dba, 0x2900, 0x705e, 0x900e, + 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, + 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, + 0x657a, 0x0118, 0x080c, 0x6582, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, - 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, - 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x8259, 0x2208, 0x0804, - 0x3339, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, - 0x18ae, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, - 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x10d5, 0x7007, - 0x0002, 0x701f, 0x4d1c, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, - 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18ae, 0x2c44, - 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x4cda, 0x7224, 0x900e, - 0x2001, 0x0003, 0x080c, 0x8259, 0x2208, 0x0804, 0x3339, 0x00f6, - 0x00e6, 0x080c, 0x53a3, 0x2009, 0x0007, 0x1904, 0x4daf, 0x2071, - 0x1894, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x4daf, 0xac9c, - 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1004, 0x2009, 0x0002, - 0x0904, 0x4daf, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, - 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x656b, 0x0118, 0x080c, - 0x6573, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, - 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, - 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, - 0x0003, 0x080c, 0x8259, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, - 0x715c, 0x81ff, 0x090c, 0x0db4, 0x2148, 0x080c, 0x101d, 0x9006, - 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0x2061, 0x18af, 0x2c44, 0xa37a, 0x7058, - 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, - 0x4dbb, 0x000e, 0xa0a2, 0x080c, 0x10d5, 0x9006, 0x0048, 0x009e, - 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0db4, - 0x00e6, 0x2071, 0x1894, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, - 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, - 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, - 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x8259, - 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0db4, 0x2148, 0x080c, 0x101d, - 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6891, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, - 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x656b, - 0x0118, 0x080c, 0x6573, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, - 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, - 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, - 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, 0x0db4, - 0x2148, 0x080c, 0x101d, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, - 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, - 0x080c, 0x10d5, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, - 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, - 0x009e, 0x0804, 0x336e, 0xa884, 0xa988, 0x080c, 0x2665, 0x1518, - 0x080c, 0x61e7, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, - 0x4889, 0x01c8, 0x080c, 0x4889, 0x01b0, 0x009e, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, - 0xbcd6, 0x1120, 0x2009, 0x0003, 0x0804, 0x336b, 0x7007, 0x0003, - 0x701f, 0x4e88, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x336b, - 0x7124, 0x080c, 0x30d7, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, - 0x0004, 0x0804, 0x336b, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, - 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, - 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, - 0x20a9, 0x002a, 0x080c, 0x0f68, 0xaa6c, 0xab70, 0xac74, 0xad78, - 0x2061, 0x18ae, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, - 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, - 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x48d5, 0x97c6, 0x7200, - 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18ae, - 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x10d5, 0x7007, 0x0002, 0x701f, 0x4ee4, 0x0005, - 0x000e, 0x007e, 0x0804, 0x336e, 0x7020, 0x2048, 0xa804, 0x2048, - 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, - 0x002a, 0x080c, 0x0f68, 0x2100, 0x2238, 0x2061, 0x18ae, 0x2c44, - 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x48d5, - 0x81ff, 0x1904, 0x336b, 0x798c, 0x2001, 0x194e, 0x918c, 0x8000, - 0x2102, 0x080c, 0x48a0, 0x0904, 0x336e, 0x080c, 0x656b, 0x0120, - 0x080c, 0x6573, 0x1904, 0x336e, 0x080c, 0x630e, 0x0904, 0x336b, - 0x0126, 0x2091, 0x8000, 0x080c, 0x63d4, 0x012e, 0x0904, 0x336b, - 0x2001, 0x194e, 0x2004, 0xd0fc, 0x1904, 0x3339, 0x0804, 0x430e, - 0xa9a0, 0x2001, 0x194e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x48ad, 0x01a0, 0x080c, 0x656b, 0x0118, 0x080c, 0x6573, 0x1170, - 0x080c, 0x630e, 0x2009, 0x0002, 0x0128, 0x080c, 0x63d4, 0x1170, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x194e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5397, 0x0110, - 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x4283, 0x080c, 0x48bc, - 0x0904, 0x336e, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, - 0x336b, 0x080c, 0x656b, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, - 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, - 0x0028, 0x080c, 0x538f, 0xd0b4, 0x0904, 0x42bd, 0x7884, 0x908e, - 0x007e, 0x0904, 0x42bd, 0x908e, 0x007f, 0x0904, 0x42bd, 0x908e, - 0x0080, 0x0904, 0x42bd, 0xb800, 0xd08c, 0x1904, 0x42bd, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbcf5, 0x1120, 0x2009, - 0x0003, 0x0804, 0x336b, 0x7007, 0x0003, 0x701f, 0x4fb0, 0x0005, - 0x080c, 0x48bc, 0x0904, 0x336e, 0x0804, 0x42bd, 0x080c, 0x3130, - 0x0108, 0x0005, 0x2009, 0x1833, 0x210c, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x336b, 0x080c, 0x53a3, 0x0120, 0x2009, 0x0007, - 0x0804, 0x336b, 0x080c, 0x6563, 0x0120, 0x2009, 0x0008, 0x0804, - 0x336b, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x42bd, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbd54, 0x1120, - 0x2009, 0x0003, 0x0804, 0x336b, 0x7007, 0x0003, 0x701f, 0x4fe9, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, - 0x52ec, 0x080c, 0x48bc, 0x0904, 0x336e, 0x0804, 0x4f82, 0x81ff, - 0x2009, 0x0001, 0x1904, 0x336b, 0x080c, 0x53a3, 0x2009, 0x0007, - 0x1904, 0x336b, 0x080c, 0x6563, 0x0120, 0x2009, 0x0008, 0x0804, - 0x336b, 0x080c, 0x48bc, 0x0904, 0x336e, 0x080c, 0x656b, 0x2009, - 0x0009, 0x1904, 0x336b, 0x080c, 0x4889, 0x2009, 0x0002, 0x0904, - 0x336b, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, - 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, - 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x336e, - 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xbfa7, 0x2009, 0x0003, - 0x0904, 0x336b, 0x7007, 0x0003, 0x701f, 0x503f, 0x0005, 0xa830, - 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x336b, 0x0804, 0x3339, - 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x53a3, - 0x1188, 0x2009, 0x0014, 0x0804, 0x336b, 0xd2dc, 0x1568, 0x81ff, - 0x2009, 0x0001, 0x1904, 0x336b, 0x080c, 0x53a3, 0x2009, 0x0007, - 0x1904, 0x336b, 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, 0x536a, - 0x0804, 0x3339, 0xd2fc, 0x0158, 0x080c, 0x48bc, 0x0904, 0x336e, - 0x7984, 0x9284, 0x9000, 0x080c, 0x5347, 0x0804, 0x3339, 0x080c, - 0x48bc, 0x0904, 0x336e, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x5128, 0x080c, 0x4889, 0x2009, 0x0002, - 0x0904, 0x5128, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x48d2, 0x701f, 0x5099, - 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, 0x1120, - 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x336e, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x48bc, 0x1110, 0x0804, 0x336e, - 0x2009, 0x0043, 0x080c, 0xc00f, 0x2009, 0x0003, 0x0904, 0x5128, - 0x7007, 0x0003, 0x701f, 0x50bd, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x5128, 0x7984, 0x7aa8, 0x9284, 0x1000, - 0x080c, 0x5347, 0x0804, 0x3339, 0x00c6, 0xaab0, 0x9284, 0xc000, - 0x0140, 0xd2ec, 0x0168, 0x080c, 0x53a3, 0x1150, 0x2009, 0x0014, - 0x04f0, 0x2061, 0x1800, 0x080c, 0x53a3, 0x2009, 0x0007, 0x15b8, - 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, 0x536a, 0x0050, 0xd2fc, - 0x0178, 0x080c, 0x48ba, 0x0588, 0xa998, 0x9284, 0x9000, 0x080c, - 0x5347, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, - 0x080c, 0x48ba, 0x0510, 0x080c, 0x656b, 0x2009, 0x0009, 0x11b8, - 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, - 0x9084, 0xff00, 0x1190, 0x080c, 0x48ba, 0x1108, 0x0070, 0x2009, - 0x004b, 0x080c, 0xc00f, 0x2009, 0x0003, 0x0108, 0x0078, 0x0429, - 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, - 0x7aa8, 0xd2dc, 0x0904, 0x336b, 0x0016, 0x7984, 0x9284, 0x1000, - 0xc0fd, 0x080c, 0x5347, 0x001e, 0x1904, 0x336b, 0x0804, 0x3339, - 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0xaab0, 0xd2dc, 0x0150, - 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5347, 0x001e, - 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x336b, 0x080c, 0x53a3, 0x0120, 0x2009, 0x0007, 0x0804, 0x336b, - 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6247, 0x1904, 0x336e, - 0x9186, 0x007f, 0x0138, 0x080c, 0x656b, 0x0120, 0x2009, 0x0009, - 0x0804, 0x336b, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, - 0x336b, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, - 0x8007, 0xa80a, 0x080c, 0xbd0f, 0x1120, 0x2009, 0x0003, 0x0804, - 0x336b, 0x7007, 0x0003, 0x701f, 0x5186, 0x0005, 0xa808, 0x8007, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x336b, 0xa8e0, - 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, - 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48d5, 0x080c, 0x4889, 0x1120, - 0x2009, 0x0002, 0x0804, 0x336b, 0x7984, 0x9194, 0xff00, 0x918c, - 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x1983, 0x0040, 0x92c6, - 0x0001, 0x1118, 0x7023, 0x199d, 0x0010, 0x0804, 0x336e, 0x2009, - 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x080c, 0x48d2, 0x701f, 0x51d6, 0x0005, 0x2001, 0x182d, - 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, - 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, - 0x3339, 0x080c, 0x4889, 0x1120, 0x2009, 0x0002, 0x0804, 0x336b, - 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, - 0x2099, 0x1983, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x199d, - 0x0010, 0x0804, 0x336e, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, - 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, - 0x0804, 0x48d5, 0x7884, 0x908a, 0x1000, 0x1a04, 0x336e, 0x0126, - 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, - 0x19ca, 0x6142, 0x00ce, 0x012e, 0x0804, 0x3339, 0x00c6, 0x080c, - 0x6f9b, 0x1160, 0x080c, 0x727f, 0x080c, 0x5cda, 0x9085, 0x0001, - 0x080c, 0x6fe2, 0x080c, 0x6ecd, 0x080c, 0x0db4, 0x2061, 0x1800, - 0x6030, 0xc09d, 0x6032, 0x080c, 0x5b99, 0x00ce, 0x0005, 0x00c6, - 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x336b, 0x7884, - 0x9005, 0x0188, 0x7888, 0x2061, 0x196c, 0x2c0c, 0x2062, 0x080c, - 0x2a47, 0x01a0, 0x080c, 0x2a4f, 0x0188, 0x080c, 0x2a57, 0x0170, - 0x2162, 0x0804, 0x336e, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, - 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, - 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x0026, - 0x2011, 0x0003, 0x080c, 0x9772, 0x2011, 0x0002, 0x080c, 0x977c, - 0x002e, 0x080c, 0x9663, 0x0036, 0x901e, 0x080c, 0x96d9, 0x003e, - 0x60e3, 0x0000, 0x080c, 0xd8d5, 0x080c, 0xd8f0, 0x9085, 0x0001, - 0x080c, 0x6fe2, 0x9006, 0x080c, 0x2b16, 0x2001, 0x1800, 0x2003, - 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, 0x3339, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x336b, 0x080c, 0x53a3, 0x0120, 0x2009, - 0x0007, 0x0804, 0x336b, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, - 0x6247, 0x1904, 0x336e, 0x9186, 0x007f, 0x0138, 0x080c, 0x656b, - 0x0120, 0x2009, 0x0009, 0x0804, 0x336b, 0x080c, 0x4889, 0x1120, - 0x2009, 0x0002, 0x0804, 0x336b, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xbd12, 0x1120, 0x2009, 0x0003, 0x0804, 0x336b, - 0x7007, 0x0003, 0x701f, 0x52d5, 0x0005, 0xa830, 0x9086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x336b, 0xa8e0, 0xa866, 0xa834, - 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0xaf60, 0x0804, 0x48d5, 0xa898, 0x9086, 0x000d, 0x1904, - 0x336b, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x52f9, - 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, - 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0xa998, 0x7986, - 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x48c5, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x7007, 0x0001, - 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x2061, 0x19ca, 0x7984, 0x6152, 0x614e, 0x6057, - 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, 0x7888, - 0x6062, 0x788c, 0x605e, 0x2001, 0x19d8, 0x2044, 0x2001, 0x19df, - 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, - 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, 0x3339, 0x0126, - 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, 0x0006, - 0x080c, 0xbb79, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0160, 0x080c, 0x5cf4, 0x080c, 0x9dc1, 0x0110, - 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, - 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, - 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0180, - 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, 0x0080, - 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, 0x002e, - 0x001e, 0x8108, 0x1f04, 0x5372, 0x015e, 0x012e, 0x0005, 0x2001, - 0x1854, 0x2004, 0x0005, 0x2001, 0x1873, 0x2004, 0x0005, 0x0006, - 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, - 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, - 0x0005, 0x0016, 0x00e6, 0x2071, 0x1894, 0x7108, 0x910d, 0x710a, - 0x00ee, 0x001e, 0x0005, 0x79a4, 0x9182, 0x0081, 0x1a04, 0x336e, - 0x810c, 0x0016, 0x080c, 0x4889, 0x080c, 0x0ef3, 0x2100, 0x2238, - 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x48d2, 0x701f, - 0x53ca, 0x0005, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, - 0x79a4, 0x810c, 0x2061, 0x18ae, 0x2c44, 0xa770, 0xa074, 0x2071, - 0x1894, 0x080c, 0x48d5, 0x701f, 0x53de, 0x0005, 0x2061, 0x18ae, - 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0efb, 0x002e, - 0x001e, 0x080c, 0x0fa8, 0x9006, 0xa802, 0xa806, 0x0804, 0x3339, - 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, - 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x5599, 0x0068, - 0xd08c, 0x0118, 0x080c, 0x54a2, 0x0040, 0xd094, 0x0118, 0x080c, - 0x5472, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, - 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, - 0x0006, 0x7094, 0x9005, 0x000e, 0x0120, 0x7097, 0x0000, 0x708f, - 0x0000, 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, - 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, - 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, - 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, - 0x080c, 0x5c56, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, - 0x6042, 0x6043, 0x0000, 0x7083, 0x0000, 0x709f, 0x0001, 0x70c3, - 0x0000, 0x70db, 0x0000, 0x2009, 0x1c80, 0x200b, 0x0000, 0x7093, - 0x0000, 0x7087, 0x000f, 0x2009, 0x000f, 0x2011, 0x5b3c, 0x080c, - 0x80b3, 0x0005, 0x2001, 0x1875, 0x2004, 0xd08c, 0x0110, 0x705b, - 0xffff, 0x7084, 0x9005, 0x1528, 0x2011, 0x5b3c, 0x080c, 0x8021, - 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, - 0x6044, 0xd08c, 0x1168, 0x1f04, 0x5488, 0x6242, 0x7097, 0x0000, - 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, - 0x6242, 0x7097, 0x0000, 0x708b, 0x0000, 0x9006, 0x080c, 0x5cdf, - 0x0000, 0x0005, 0x7088, 0x908a, 0x0003, 0x1a0c, 0x0db4, 0x000b, - 0x0005, 0x54ac, 0x54fd, 0x5598, 0x00f6, 0x0016, 0x6900, 0x918c, - 0x0800, 0x708b, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, - 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, - 0x54bb, 0x080c, 0x0db4, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, - 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, - 0x080c, 0x5cbb, 0x2079, 0x1c00, 0x7833, 0x1101, 0x7837, 0x0000, - 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1c0e, - 0x20a9, 0x0004, 0x4003, 0x080c, 0x9c4a, 0x20e1, 0x0001, 0x2099, - 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, - 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x5b6d, 0x00fe, 0x9006, - 0x708e, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x708c, 0x708f, - 0x0000, 0x9025, 0x0904, 0x5575, 0x6020, 0xd0b4, 0x1904, 0x5573, - 0x719c, 0x81ff, 0x0904, 0x5561, 0x9486, 0x000c, 0x1904, 0x556e, - 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x5cb4, 0x2011, 0x0260, - 0x2019, 0x1c00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, - 0x1f04, 0x551a, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, - 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708b, 0x0002, - 0x7097, 0x0002, 0x2009, 0x07d0, 0x2011, 0x5b43, 0x080c, 0x80b3, - 0x080c, 0x5cbb, 0x04c0, 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7930, - 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, - 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x5cb4, 0x2011, - 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, - 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x5555, 0x0078, 0x709f, - 0x0000, 0x080c, 0x5cb4, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0001, 0x20a1, 0x1c00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, - 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, - 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x9c4a, 0x20e1, 0x0001, - 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, - 0x4003, 0x60c3, 0x000c, 0x2011, 0x19c1, 0x2013, 0x0000, 0x708f, - 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x93a4, 0x08d8, - 0x0005, 0x7094, 0x908a, 0x001d, 0x1a0c, 0x0db4, 0x000b, 0x0005, - 0x55ca, 0x55dd, 0x5606, 0x5626, 0x564c, 0x567b, 0x56a1, 0x56d9, - 0x56ff, 0x572d, 0x5768, 0x57a0, 0x57be, 0x57e9, 0x580b, 0x5826, - 0x5830, 0x5864, 0x588a, 0x58b9, 0x58df, 0x5917, 0x595b, 0x5998, - 0x59b9, 0x5a12, 0x5a34, 0x5a62, 0x5a62, 0x00c6, 0x2061, 0x1800, - 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, - 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, - 0x2061, 0x0100, 0x6043, 0x0002, 0x7097, 0x0001, 0x2009, 0x07d0, - 0x2011, 0x5b43, 0x080c, 0x80b3, 0x0005, 0x00f6, 0x708c, 0x9086, - 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x5cb4, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, - 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x2011, 0x5b43, 0x080c, 0x8021, 0x7097, 0x0010, 0x080c, - 0x5830, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, - 0x0003, 0x6043, 0x0004, 0x2011, 0x5b43, 0x080c, 0x8021, 0x080c, - 0x5c38, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, - 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x561b, - 0x60c3, 0x0014, 0x080c, 0x5b6d, 0x00fe, 0x0005, 0x00f6, 0x708c, - 0x9005, 0x0500, 0x2011, 0x5b43, 0x080c, 0x8021, 0x9086, 0x0014, - 0x11b8, 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, - 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, - 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0004, 0x0029, 0x0010, - 0x080c, 0x5c90, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0005, 0x080c, - 0x5c38, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, - 0x5cb4, 0x080c, 0x5c97, 0x1170, 0x7080, 0x9005, 0x1158, 0x7158, - 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5af0, 0x0168, - 0x080c, 0x5c6d, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5b6d, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, - 0x5b43, 0x080c, 0x8021, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cb4, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x7097, 0x0006, 0x0029, 0x0010, 0x080c, 0x5c90, 0x00fe, - 0x0005, 0x00f6, 0x7097, 0x0007, 0x080c, 0x5c38, 0x2079, 0x0240, - 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5cb4, 0x080c, 0x5c97, - 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, 0x0180, - 0x9180, 0x313a, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, - 0x080c, 0x5af0, 0x0180, 0x080c, 0x4ca1, 0x0110, 0x080c, 0x26ce, - 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b6d, 0x00fe, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b43, 0x080c, - 0x8021, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cb4, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, - 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, - 0x0008, 0x0029, 0x0010, 0x080c, 0x5c90, 0x00fe, 0x0005, 0x00f6, - 0x7097, 0x0009, 0x080c, 0x5c38, 0x2079, 0x0240, 0x7833, 0x1105, - 0x7837, 0x0100, 0x080c, 0x5c97, 0x1150, 0x7080, 0x9005, 0x1138, - 0x080c, 0x5a63, 0x1188, 0x9085, 0x0001, 0x080c, 0x26ce, 0x20a9, - 0x0008, 0x080c, 0x5cb4, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b6d, - 0x0010, 0x080c, 0x55bd, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, - 0x05a8, 0x2011, 0x5b43, 0x080c, 0x8021, 0x9086, 0x0014, 0x1560, - 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, - 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, + 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, + 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x8277, 0x2208, 0x009e, + 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c, 0x0db4, 0x2148, + 0x080c, 0x101d, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, + 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18b7, + 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, + 0xa696, 0xa79a, 0xa09f, 0x4dc6, 0x000e, 0xa0a2, 0x080c, 0x10d5, + 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, + 0x904d, 0x090c, 0x0db4, 0x00e6, 0x2071, 0x189c, 0xa06c, 0x908e, + 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, + 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, + 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, + 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, + 0x0003, 0x080c, 0x8277, 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0db4, + 0x2148, 0x080c, 0x101d, 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, + 0x2091, 0x8000, 0x080c, 0x68a0, 0x012e, 0xa09f, 0x0000, 0xa0a3, + 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, + 0x0178, 0x080c, 0x657a, 0x0118, 0x080c, 0x6582, 0x1148, 0xb814, + 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, + 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, + 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, + 0x81ff, 0x090c, 0x0db4, 0x2148, 0x080c, 0x101d, 0x9006, 0x705e, + 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, + 0x080c, 0x68a0, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, + 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, + 0xa592, 0xa696, 0xa79a, 0x080c, 0x10d5, 0x9006, 0x00ee, 0x0005, + 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, + 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x3379, 0xa884, 0xa988, + 0x080c, 0x2670, 0x1518, 0x080c, 0x61f6, 0x1500, 0x7126, 0xbe12, + 0xbd16, 0xae7c, 0x080c, 0x4894, 0x01c8, 0x080c, 0x4894, 0x01b0, + 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, + 0xa804, 0x2048, 0x080c, 0xbce5, 0x1120, 0x2009, 0x0003, 0x0804, + 0x3376, 0x7007, 0x0003, 0x701f, 0x4e93, 0x0005, 0x009e, 0x2009, + 0x0002, 0x0804, 0x3376, 0x7124, 0x080c, 0x30e2, 0xa820, 0x9086, + 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x3376, 0x2900, 0x7022, + 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, + 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, + 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f68, 0xaa6c, + 0xab70, 0xac74, 0xad78, 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, + 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, + 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, + 0x48e0, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, + 0x007e, 0x2061, 0x18b6, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, + 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10d5, 0x7007, 0x0002, + 0x701f, 0x4eef, 0x0005, 0x000e, 0x007e, 0x0804, 0x3379, 0x7020, + 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, + 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, + 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f68, 0x2100, 0x2238, + 0x2061, 0x18b6, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, + 0x002a, 0x0804, 0x48e0, 0x81ff, 0x1904, 0x3376, 0x798c, 0x2001, + 0x1956, 0x918c, 0x8000, 0x2102, 0x080c, 0x48ab, 0x0904, 0x3379, + 0x080c, 0x657a, 0x0120, 0x080c, 0x6582, 0x1904, 0x3379, 0x080c, + 0x631d, 0x0904, 0x3376, 0x0126, 0x2091, 0x8000, 0x080c, 0x63e3, + 0x012e, 0x0904, 0x3376, 0x2001, 0x1956, 0x2004, 0xd0fc, 0x1904, + 0x3344, 0x0804, 0x4319, 0xa9a0, 0x2001, 0x1956, 0x918c, 0x8000, + 0xc18d, 0x2102, 0x080c, 0x48b8, 0x01a0, 0x080c, 0x657a, 0x0118, + 0x080c, 0x6582, 0x1170, 0x080c, 0x631d, 0x2009, 0x0002, 0x0128, + 0x080c, 0x63e3, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, + 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, + 0x0005, 0xa897, 0x4000, 0x2001, 0x1956, 0x2004, 0xd0fc, 0x1128, + 0x080c, 0x53a2, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, + 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, + 0x428e, 0x080c, 0x48c7, 0x0904, 0x3379, 0x080c, 0x4894, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3376, 0x080c, 0x657a, 0x0130, 0x908e, + 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, + 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, 0x539a, 0xd0b4, 0x0904, + 0x42c8, 0x7884, 0x908e, 0x007e, 0x0904, 0x42c8, 0x908e, 0x007f, + 0x0904, 0x42c8, 0x908e, 0x0080, 0x0904, 0x42c8, 0xb800, 0xd08c, + 0x1904, 0x42c8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, + 0xbd04, 0x1120, 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, + 0x701f, 0x4fbb, 0x0005, 0x080c, 0x48c7, 0x0904, 0x3379, 0x0804, + 0x42c8, 0x080c, 0x313b, 0x0108, 0x0005, 0x2009, 0x1833, 0x210c, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, 0x080c, 0x53ae, + 0x0120, 0x2009, 0x0007, 0x0804, 0x3376, 0x080c, 0x6572, 0x0120, + 0x2009, 0x0008, 0x0804, 0x3376, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, + 0x1904, 0x42c8, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, + 0x080c, 0xbd63, 0x1120, 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, + 0x0003, 0x701f, 0x4ff4, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, + 0x2009, 0x0004, 0x0804, 0x52f7, 0x080c, 0x48c7, 0x0904, 0x3379, + 0x0804, 0x4f8d, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3376, 0x080c, + 0x53ae, 0x2009, 0x0007, 0x1904, 0x3376, 0x080c, 0x6572, 0x0120, + 0x2009, 0x0008, 0x0804, 0x3376, 0x080c, 0x48c7, 0x0904, 0x3379, + 0x080c, 0x657a, 0x2009, 0x0009, 0x1904, 0x3376, 0x080c, 0x4894, + 0x2009, 0x0002, 0x0904, 0x3376, 0x9006, 0xa866, 0xa832, 0xa868, + 0xc0fd, 0xa86a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, + 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, + 0x0100, 0x1904, 0x3379, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, + 0xbfb6, 0x2009, 0x0003, 0x0904, 0x3376, 0x7007, 0x0003, 0x701f, + 0x504a, 0x0005, 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, + 0x3376, 0x0804, 0x3344, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, + 0x01a0, 0x080c, 0x53ae, 0x1188, 0x2009, 0x0014, 0x0804, 0x3376, + 0xd2dc, 0x1568, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3376, 0x080c, + 0x53ae, 0x2009, 0x0007, 0x1904, 0x3376, 0xd2f4, 0x0130, 0x9284, + 0x5000, 0x080c, 0x5375, 0x0804, 0x3344, 0xd2fc, 0x0158, 0x080c, + 0x48c7, 0x0904, 0x3379, 0x7984, 0x9284, 0x9000, 0x080c, 0x5352, + 0x0804, 0x3344, 0x080c, 0x48c7, 0x0904, 0x3379, 0xb804, 0x9084, + 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x5133, 0x080c, + 0x4894, 0x2009, 0x0002, 0x0904, 0x5133, 0xa85c, 0x9080, 0x001b, + 0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, + 0x48dd, 0x701f, 0x50a4, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, + 0xa870, 0x9005, 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, + 0x3379, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x48c7, + 0x1110, 0x0804, 0x3379, 0x2009, 0x0043, 0x080c, 0xc01e, 0x2009, + 0x0003, 0x0904, 0x5133, 0x7007, 0x0003, 0x701f, 0x50c8, 0x0005, + 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x5133, 0x7984, + 0x7aa8, 0x9284, 0x1000, 0x080c, 0x5352, 0x0804, 0x3344, 0x00c6, + 0xaab0, 0x9284, 0xc000, 0x0140, 0xd2ec, 0x0168, 0x080c, 0x53ae, + 0x1150, 0x2009, 0x0014, 0x04f0, 0x2061, 0x1800, 0x080c, 0x53ae, + 0x2009, 0x0007, 0x15b8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, + 0x5375, 0x0050, 0xd2fc, 0x0178, 0x080c, 0x48c5, 0x0588, 0xa998, + 0x9284, 0x9000, 0x080c, 0x5352, 0xa87b, 0x0000, 0xa883, 0x0000, + 0xa897, 0x4000, 0x0438, 0x080c, 0x48c5, 0x0510, 0x080c, 0x657a, + 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, + 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, 0x48c5, + 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xc01e, 0x2009, 0x0003, + 0x0108, 0x0078, 0x0429, 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, + 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, + 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x3376, 0x0016, + 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5352, 0x001e, 0x1904, + 0x3376, 0x0804, 0x3344, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, + 0xaab0, 0xd2dc, 0x0150, 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x5352, 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x3376, 0x080c, 0x53ae, 0x0120, 0x2009, + 0x0007, 0x0804, 0x3376, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, + 0x6256, 0x1904, 0x3379, 0x9186, 0x007f, 0x0138, 0x080c, 0x657a, + 0x0120, 0x2009, 0x0009, 0x0804, 0x3376, 0x080c, 0x4894, 0x1120, + 0x2009, 0x0002, 0x0804, 0x3376, 0xa867, 0x0000, 0xa868, 0xc0fd, + 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a, 0x080c, 0xbd1e, 0x1120, + 0x2009, 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, 0x701f, 0x5191, + 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x3376, 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, + 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, + 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48e0, + 0x080c, 0x4894, 0x1120, 0x2009, 0x0002, 0x0804, 0x3376, 0x7984, + 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, + 0x198b, 0x0040, 0x92c6, 0x0001, 0x1118, 0x7023, 0x19a5, 0x0010, + 0x0804, 0x3379, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x48dd, 0x701f, 0x51e1, + 0x0005, 0x2001, 0x182d, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, + 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, + 0x0001, 0x4003, 0x0804, 0x3344, 0x080c, 0x4894, 0x1120, 0x2009, + 0x0002, 0x0804, 0x3376, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, + 0x8217, 0x82ff, 0x1118, 0x2099, 0x198b, 0x0040, 0x92c6, 0x0001, + 0x1118, 0x2099, 0x19a5, 0x0010, 0x0804, 0x3379, 0xa85c, 0x9080, + 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, + 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, + 0x9080, 0x0019, 0xaf60, 0x0804, 0x48e0, 0x7884, 0x908a, 0x1000, + 0x1a04, 0x3379, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, + 0x9108, 0x00c6, 0x2061, 0x19d2, 0x6142, 0x00ce, 0x012e, 0x0804, + 0x3344, 0x00c6, 0x080c, 0x6faa, 0x1160, 0x080c, 0x728c, 0x080c, + 0x5ce5, 0x9085, 0x0001, 0x080c, 0x6ff1, 0x080c, 0x6edc, 0x080c, + 0x0db4, 0x2061, 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5ba4, + 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, + 0x0904, 0x3376, 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x1974, + 0x2c0c, 0x2062, 0x080c, 0x2a52, 0x01a0, 0x080c, 0x2a5a, 0x0188, + 0x080c, 0x2a62, 0x0170, 0x2162, 0x0804, 0x3379, 0x2061, 0x0100, + 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, + 0x0000, 0x7884, 0x9086, 0x0002, 0x1548, 0x2061, 0x0100, 0x6028, + 0xc09c, 0x602a, 0x0026, 0x2011, 0x0003, 0x080c, 0x975b, 0x2011, + 0x0002, 0x080c, 0x9765, 0x002e, 0x080c, 0x9673, 0x0036, 0x901e, + 0x080c, 0x96e9, 0x003e, 0x60e3, 0x0000, 0x080c, 0xd8ee, 0x080c, + 0xd909, 0x9085, 0x0001, 0x080c, 0x6ff1, 0x9006, 0x080c, 0x2b21, + 0x2001, 0x1800, 0x2003, 0x0004, 0x6027, 0x0008, 0x00ce, 0x0804, + 0x3344, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3376, 0x080c, + 0x53ae, 0x0120, 0x2009, 0x0007, 0x0804, 0x3376, 0x7984, 0x7ea8, + 0x96b4, 0x00ff, 0x080c, 0x6256, 0x1904, 0x3379, 0x9186, 0x007f, + 0x0138, 0x080c, 0x657a, 0x0120, 0x2009, 0x0009, 0x0804, 0x3376, + 0x080c, 0x4894, 0x1120, 0x2009, 0x0002, 0x0804, 0x3376, 0xa867, + 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbd21, 0x1120, 0x2009, + 0x0003, 0x0804, 0x3376, 0x7007, 0x0003, 0x701f, 0x52e0, 0x0005, + 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3376, + 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x48e0, 0xa898, + 0x9086, 0x000d, 0x1904, 0x3376, 0x2021, 0x4005, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x5304, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, + 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, + 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, + 0x48d0, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1187, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x19d2, 0x7984, + 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, + 0x789c, 0x6066, 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x19e0, + 0x2044, 0x2001, 0x19e7, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, + 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, + 0x0804, 0x3344, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, + 0xc000, 0x0128, 0x0006, 0x080c, 0xbb88, 0x000e, 0x1198, 0xd0e4, + 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x5cff, + 0x080c, 0x9dae, 0x0110, 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, + 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, + 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, + 0x2004, 0x9005, 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, + 0x0150, 0x9186, 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, + 0x2200, 0x0801, 0x002e, 0x001e, 0x8108, 0x1f04, 0x537d, 0x015e, + 0x012e, 0x0005, 0x2001, 0x185c, 0x2004, 0x0005, 0x2001, 0x187b, + 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, + 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, + 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189c, + 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x9182, + 0x0081, 0x1a04, 0x3379, 0x810c, 0x0016, 0x080c, 0x4894, 0x080c, + 0x0ef3, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, + 0x080c, 0x48dd, 0x701f, 0x53d5, 0x0005, 0x2079, 0x0000, 0x7d94, + 0x7c98, 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b6, 0x2c44, + 0xa770, 0xa074, 0x2071, 0x189c, 0x080c, 0x48e0, 0x701f, 0x53e9, + 0x0005, 0x2061, 0x18b6, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, + 0x080c, 0x0efb, 0x002e, 0x001e, 0x080c, 0x0fa8, 0x9006, 0xa802, + 0xa806, 0x0804, 0x3344, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, + 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, + 0x0200, 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, + 0x080c, 0x55a4, 0x0068, 0xd08c, 0x0118, 0x080c, 0x54ad, 0x0040, + 0xd094, 0x0118, 0x080c, 0x547d, 0x0018, 0xd09c, 0x0108, 0x0099, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, + 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, + 0x612a, 0x001e, 0x0c68, 0x0006, 0x7094, 0x9005, 0x000e, 0x0120, + 0x7097, 0x0000, 0x708f, 0x0000, 0x624c, 0x9286, 0xf0f0, 0x1150, + 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, + 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, + 0x0128, 0x2009, 0x00f7, 0x080c, 0x5c61, 0x00f0, 0x6040, 0x9084, + 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7083, 0x0000, + 0x709f, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, 0x1c80, + 0x200b, 0x0000, 0x7093, 0x0000, 0x7087, 0x000f, 0x2009, 0x000f, + 0x2011, 0x5b47, 0x080c, 0x80d1, 0x0005, 0x2001, 0x187d, 0x2004, + 0xd08c, 0x0110, 0x705b, 0xffff, 0x7084, 0x9005, 0x1528, 0x2011, + 0x5b47, 0x080c, 0x803f, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, + 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x5493, + 0x6242, 0x7097, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, + 0x6042, 0x6242, 0x0048, 0x6242, 0x7097, 0x0000, 0x708b, 0x0000, + 0x9006, 0x080c, 0x5cea, 0x0000, 0x0005, 0x7088, 0x908a, 0x0003, + 0x1a0c, 0x0db4, 0x000b, 0x0005, 0x54b7, 0x5508, 0x55a3, 0x00f6, + 0x0016, 0x6900, 0x918c, 0x0800, 0x708b, 0x0001, 0x2001, 0x015d, + 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, + 0x00fc, 0x0120, 0x1f04, 0x54c6, 0x080c, 0x0db4, 0x68a0, 0x68a2, + 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, + 0x001e, 0x6837, 0x0020, 0x080c, 0x5cc6, 0x2079, 0x1c00, 0x7833, + 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, + 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0x9c37, + 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, + 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, + 0x5b78, 0x00fe, 0x9006, 0x708e, 0x6043, 0x0008, 0x6042, 0x0005, + 0x00f6, 0x708c, 0x708f, 0x0000, 0x9025, 0x0904, 0x5580, 0x6020, + 0xd0b4, 0x1904, 0x557e, 0x719c, 0x81ff, 0x0904, 0x556c, 0x9486, + 0x000c, 0x1904, 0x5579, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, + 0x5cbf, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304, 0x9106, + 0x11e8, 0x8210, 0x8318, 0x1f04, 0x5525, 0x6043, 0x0004, 0x2061, + 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, + 0x0006, 0x708b, 0x0002, 0x7097, 0x0002, 0x2009, 0x07d0, 0x2011, + 0x5b4e, 0x080c, 0x80d1, 0x080c, 0x5cc6, 0x04c0, 0x080c, 0x5cbf, + 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, + 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, + 0x080c, 0x5cbf, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, + 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, + 0x5560, 0x0078, 0x709f, 0x0000, 0x080c, 0x5cbf, 0x20e1, 0x0000, + 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9, 0x0014, + 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, + 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, + 0x9c37, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19c9, + 0x2013, 0x0000, 0x708f, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, + 0x080c, 0x93be, 0x08d8, 0x0005, 0x7094, 0x908a, 0x001d, 0x1a0c, + 0x0db4, 0x000b, 0x0005, 0x55d5, 0x55e8, 0x5611, 0x5631, 0x5657, + 0x5686, 0x56ac, 0x56e4, 0x570a, 0x5738, 0x5773, 0x57ab, 0x57c9, + 0x57f4, 0x5816, 0x5831, 0x583b, 0x586f, 0x5895, 0x58c4, 0x58ea, + 0x5922, 0x5966, 0x59a3, 0x59c4, 0x5a1d, 0x5a3f, 0x5a6d, 0x5a6d, + 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, + 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, + 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x7097, + 0x0001, 0x2009, 0x07d0, 0x2011, 0x5b4e, 0x080c, 0x80d1, 0x0005, + 0x00f6, 0x708c, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, + 0x11f0, 0x080c, 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, + 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x2011, 0x5b4e, 0x080c, 0x803f, + 0x7097, 0x0010, 0x080c, 0x583b, 0x0010, 0x708f, 0x0000, 0x00fe, + 0x0005, 0x00f6, 0x7097, 0x0003, 0x6043, 0x0004, 0x2011, 0x5b4e, + 0x080c, 0x803f, 0x080c, 0x5c43, 0x2079, 0x0240, 0x7833, 0x1102, + 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, + 0x8108, 0x1f04, 0x5626, 0x60c3, 0x0014, 0x080c, 0x5b78, 0x00fe, + 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b4e, 0x080c, + 0x803f, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cbf, 0x2079, 0x0260, + 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, - 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, - 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0000, 0x7097, - 0x000e, 0x080c, 0x580b, 0x0010, 0x080c, 0x5c90, 0x00fe, 0x0005, - 0x00f6, 0x7097, 0x000b, 0x2011, 0x1c0e, 0x20e9, 0x0001, 0x22a0, - 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x5c38, 0x2079, - 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5c97, 0x0118, - 0x2013, 0x0000, 0x0020, 0x705c, 0x9085, 0x0100, 0x2012, 0x20a9, - 0x0040, 0x2009, 0x024e, 0x2011, 0x1c0e, 0x220e, 0x8210, 0x8108, - 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, - 0x1f04, 0x578d, 0x60c3, 0x0084, 0x080c, 0x5b6d, 0x00fe, 0x0005, - 0x00f6, 0x708c, 0x9005, 0x01c0, 0x2011, 0x5b43, 0x080c, 0x8021, - 0x9086, 0x0084, 0x1178, 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x7097, 0x000c, - 0x0029, 0x0010, 0x080c, 0x5c90, 0x00fe, 0x0005, 0x00f6, 0x7097, - 0x000d, 0x080c, 0x5c38, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, - 0x0000, 0x080c, 0x5cb4, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, - 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, - 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, - 0x0260, 0x1f04, 0x57d1, 0x60c3, 0x0084, 0x080c, 0x5b6d, 0x00fe, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, 0x5b43, 0x080c, - 0x8021, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cb4, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7093, - 0x0001, 0x080c, 0x5c0a, 0x7097, 0x000e, 0x0029, 0x0010, 0x080c, - 0x5c90, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x5cdf, 0x7097, - 0x000f, 0x708f, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, - 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, - 0x07d0, 0x2011, 0x5b43, 0x080c, 0x8015, 0x0005, 0x708c, 0x9005, - 0x0130, 0x2011, 0x5b43, 0x080c, 0x8021, 0x7097, 0x0000, 0x0005, - 0x7097, 0x0011, 0x080c, 0x9c4a, 0x080c, 0x5cb4, 0x20e1, 0x0000, - 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x748c, 0x9480, - 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, - 0x080c, 0x5c97, 0x11a0, 0x7178, 0x81ff, 0x0188, 0x900e, 0x707c, - 0x9084, 0x00ff, 0x0160, 0x080c, 0x2665, 0x9186, 0x007e, 0x0138, - 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5af0, 0x60c3, - 0x0014, 0x080c, 0x5b6d, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, - 0x2011, 0x5b43, 0x080c, 0x8021, 0x9086, 0x0014, 0x11b8, 0x080c, - 0x5cb4, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, + 0x0004, 0x0029, 0x0010, 0x080c, 0x5c9b, 0x00fe, 0x0005, 0x00f6, + 0x7097, 0x0005, 0x080c, 0x5c43, 0x2079, 0x0240, 0x7833, 0x1103, + 0x7837, 0x0000, 0x080c, 0x5cbf, 0x080c, 0x5ca2, 0x1170, 0x7080, + 0x9005, 0x1158, 0x7158, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, + 0x080c, 0x5afb, 0x0168, 0x080c, 0x5c78, 0x20a9, 0x0008, 0x20e1, + 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, + 0x60c3, 0x0014, 0x080c, 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, + 0x9005, 0x0500, 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0014, + 0x11b8, 0x080c, 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, + 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, + 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0006, 0x0029, 0x0010, + 0x080c, 0x5c9b, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0007, 0x080c, + 0x5c43, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, + 0x5cbf, 0x080c, 0x5ca2, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, + 0x9186, 0xffff, 0x0180, 0x9180, 0x3145, 0x200d, 0x918c, 0xff00, + 0x810f, 0x2011, 0x0008, 0x080c, 0x5afb, 0x0180, 0x080c, 0x4cac, + 0x0110, 0x080c, 0x26d9, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, + 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x7097, 0x0012, 0x0029, 0x0010, 0x708f, 0x0000, - 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0013, 0x080c, 0x5c46, 0x2079, - 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5cb4, 0x080c, - 0x5c97, 0x1170, 0x7080, 0x9005, 0x1158, 0x7158, 0x9186, 0xffff, - 0x0138, 0x2011, 0x0008, 0x080c, 0x5af0, 0x0168, 0x080c, 0x5c6d, - 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b6d, 0x00fe, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b43, 0x080c, - 0x8021, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cb4, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, - 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, - 0x0014, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x7097, 0x0015, 0x080c, 0x5c46, 0x2079, 0x0240, 0x7833, 0x1104, - 0x7837, 0x0000, 0x080c, 0x5cb4, 0x080c, 0x5c97, 0x11b8, 0x7080, - 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, 0x0180, 0x9180, 0x313a, - 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5af0, - 0x0180, 0x080c, 0x4ca1, 0x0110, 0x080c, 0x26ce, 0x20a9, 0x0008, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b6d, 0x00fe, 0x0005, 0x00f6, - 0x708c, 0x9005, 0x05f0, 0x2011, 0x5b43, 0x080c, 0x8021, 0x9086, - 0x0014, 0x15a8, 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, - 0x1168, 0x9085, 0x0001, 0x080c, 0x5cdf, 0x7a38, 0xd2fc, 0x0128, - 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x0080, 0x9005, 0x11b8, + 0x70c3, 0x0001, 0x7097, 0x0008, 0x0029, 0x0010, 0x080c, 0x5c9b, + 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0009, 0x080c, 0x5c43, 0x2079, + 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x5ca2, 0x1150, + 0x7080, 0x9005, 0x1138, 0x080c, 0x5a6e, 0x1188, 0x9085, 0x0001, + 0x080c, 0x26d9, 0x20a9, 0x0008, 0x080c, 0x5cbf, 0x20e1, 0x0000, + 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, + 0x0014, 0x080c, 0x5b78, 0x0010, 0x080c, 0x55c8, 0x00fe, 0x0005, + 0x00f6, 0x708c, 0x9005, 0x05a8, 0x2011, 0x5b4e, 0x080c, 0x803f, + 0x9086, 0x0014, 0x1560, 0x080c, 0x5cbf, 0x2079, 0x0260, 0x7a30, + 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, + 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, + 0x70c3, 0x0001, 0x7097, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, - 0x9085, 0x0001, 0x080c, 0x5cdf, 0x7093, 0x0000, 0x7a38, 0xd2f4, - 0x0110, 0x70db, 0x0008, 0x7097, 0x0016, 0x0029, 0x0010, 0x708f, - 0x0000, 0x00fe, 0x0005, 0x080c, 0x9c4a, 0x080c, 0x5cb4, 0x20e1, - 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, - 0x024d, 0x2012, 0x2011, 0x026e, 0x7097, 0x0017, 0x080c, 0x5c97, - 0x1150, 0x7080, 0x9005, 0x1138, 0x080c, 0x5a63, 0x1188, 0x9085, - 0x0001, 0x080c, 0x26ce, 0x20a9, 0x0008, 0x080c, 0x5cb4, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5b6d, 0x0010, 0x080c, 0x55bd, 0x0005, - 0x00f6, 0x708c, 0x9005, 0x01d8, 0x2011, 0x5b43, 0x080c, 0x8021, - 0x9086, 0x0084, 0x1190, 0x080c, 0x5cb4, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, - 0x5cdf, 0x7097, 0x0018, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, - 0x0005, 0x00f6, 0x7097, 0x0019, 0x080c, 0x5c46, 0x2079, 0x0240, - 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5cb4, 0x2009, 0x026e, - 0x2039, 0x1c0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, - 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, - 0x59cc, 0x2039, 0x1c0e, 0x080c, 0x5c97, 0x11e8, 0x2728, 0x2514, - 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, - 0x9205, 0x202a, 0x705c, 0x2310, 0x8214, 0x92a0, 0x1c0e, 0x2414, - 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, - 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, - 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, - 0x2009, 0x0240, 0x1f04, 0x59ff, 0x60c3, 0x0084, 0x080c, 0x5b6d, - 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, 0x5b43, - 0x080c, 0x8021, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cb4, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, - 0x7093, 0x0001, 0x080c, 0x5c0a, 0x7097, 0x001a, 0x0029, 0x0010, - 0x708f, 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x5cdf, - 0x7097, 0x001b, 0x080c, 0x9c4a, 0x080c, 0x5cb4, 0x2011, 0x0260, - 0x2009, 0x0240, 0x748c, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, - 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, - 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, - 0x6816, 0x2011, 0x0260, 0x1f04, 0x5a4b, 0x60c3, 0x0084, 0x080c, - 0x5b6d, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1854, 0x252c, - 0x20a9, 0x0008, 0x2041, 0x1c0e, 0x20e9, 0x0001, 0x28a0, 0x080c, - 0x5cb4, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, - 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, - 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, - 0x1f04, 0x5a7d, 0x0804, 0x5aec, 0x82ff, 0x1160, 0xd5d4, 0x0120, - 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5aec, - 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, - 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, - 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5aa3, - 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5ab5, - 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, - 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5ac4, - 0x755a, 0x95c8, 0x313a, 0x292d, 0x95ac, 0x00ff, 0x757e, 0x6532, - 0x6536, 0x0016, 0x2508, 0x080c, 0x26ae, 0x001e, 0x60e7, 0x0000, - 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x7083, 0x0001, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, - 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, - 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, - 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, - 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, - 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, - 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, - 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715a, 0x91a0, - 0x313a, 0x242d, 0x95ac, 0x00ff, 0x757e, 0x6532, 0x6536, 0x0016, - 0x2508, 0x080c, 0x26ae, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7083, - 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7087, - 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, - 0x0140, 0x080c, 0x5bf9, 0x080c, 0x93ad, 0x7004, 0x9084, 0x4000, - 0x0110, 0x080c, 0x2b26, 0x0126, 0x2091, 0x8000, 0x2071, 0x1825, - 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, - 0x5c56, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, - 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, - 0x080c, 0x29cc, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, - 0x2011, 0x19c1, 0x2013, 0x0000, 0x708f, 0x0000, 0x012e, 0x60a3, - 0x0056, 0x60a7, 0x9575, 0x080c, 0x93a4, 0x6144, 0xd184, 0x0120, - 0x7194, 0x918d, 0x2000, 0x0018, 0x7188, 0x918d, 0x1000, 0x2011, - 0x1969, 0x2112, 0x2009, 0x07d0, 0x2011, 0x5b43, 0x080c, 0x80b3, - 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9dc8, 0x2009, 0x00f7, 0x080c, 0x5c56, 0x2061, 0x19ca, 0x900e, - 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, 0x1800, 0x6003, 0x0001, - 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1969, - 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x5bc5, 0x080c, 0x8015, - 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, - 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, 0x080c, 0x93ad, 0x2071, - 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2b26, 0x080c, - 0x6fa3, 0x0188, 0x080c, 0x6fbe, 0x1170, 0x080c, 0x7289, 0x0016, - 0x080c, 0x277d, 0x2001, 0x193d, 0x2102, 0x001e, 0x080c, 0x7284, - 0x080c, 0x6ecd, 0x0050, 0x2009, 0x0001, 0x080c, 0x2a65, 0x2001, - 0x0001, 0x080c, 0x260e, 0x080c, 0x5b99, 0x012e, 0x000e, 0x00ee, - 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, - 0x2011, 0x8017, 0x2001, 0x1969, 0x201c, 0x080c, 0x48e9, 0x003e, - 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1c80, - 0x080c, 0x5cb4, 0x20e9, 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, - 0x0020, 0x080c, 0x5cae, 0x2099, 0x0260, 0x20a1, 0x1c92, 0x0051, - 0x20a9, 0x000e, 0x080c, 0x5cb1, 0x2099, 0x0260, 0x20a1, 0x1cb2, - 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, - 0x2012, 0x8108, 0x8210, 0x1f04, 0x5c2e, 0x002e, 0x001e, 0x0005, - 0x080c, 0x9c4a, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x080c, 0x9c4a, - 0x080c, 0x5cb4, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, - 0x2061, 0x0100, 0x810f, 0x2001, 0x1833, 0x2004, 0x9005, 0x1138, - 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, - 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, - 0x6567, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xd54b, - 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, - 0x080c, 0x2fa7, 0x080c, 0xc22c, 0x0140, 0x0036, 0x2019, 0xffff, - 0x2021, 0x0007, 0x080c, 0x4a86, 0x003e, 0x004e, 0x001e, 0x0005, - 0x080c, 0x5b99, 0x7097, 0x0000, 0x708f, 0x0000, 0x0005, 0x0006, - 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, - 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0x918d, - 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x2009, 0x0001, - 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, 0x6814, 0x9084, 0xffc0, - 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, 0x0146, 0x01d6, 0x9006, - 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x4004, 0x2079, - 0x1c00, 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, 0x00ef, 0x7813, - 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, 0x014e, 0x015e, - 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, 0x0001, 0x0005, 0x2001, - 0x1976, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, - 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, - 0x1f04, 0x5cee, 0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, - 0x0146, 0x2069, 0x1853, 0x9006, 0xb802, 0xb8be, 0xb807, 0x0707, - 0xb80a, 0xb80e, 0xb812, 0x9198, 0x313a, 0x231d, 0x939c, 0x00ff, - 0xbb16, 0x0016, 0x0026, 0xb8b2, 0x080c, 0x9dc1, 0x1120, 0x9192, - 0x007e, 0x1208, 0xbbb2, 0x20a9, 0x0004, 0xb8b4, 0x20e8, 0xb9b8, - 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9198, - 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, 0xb83e, 0xb842, 0xb84e, - 0xb852, 0xb856, 0xb85a, 0xb85e, 0xb862, 0xb866, 0xb86a, 0xb86f, - 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, 0x0008, - 0xb896, 0xb89a, 0xb89e, 0xb8ae, 0xb9a2, 0x0096, 0xb8a4, 0x904d, - 0x0110, 0x080c, 0x101d, 0xb8a7, 0x0000, 0x009e, 0x9006, 0xb84a, - 0x6810, 0xb83a, 0x680c, 0xb846, 0x6814, 0x9084, 0x00ff, 0xb842, - 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, - 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, - 0x5dc4, 0x9182, 0x0800, 0x1a04, 0x5dc8, 0x2001, 0x180c, 0x2004, - 0x9084, 0x0003, 0x1904, 0x5dce, 0x9188, 0x1000, 0x2104, 0x905d, - 0x0518, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1508, 0xb8a4, - 0x900d, 0x1904, 0x5de0, 0xb850, 0x900d, 0x1148, 0xa802, 0x2900, - 0xb852, 0xb84e, 0x080c, 0x83f7, 0x9006, 0x012e, 0x0005, 0x00a6, - 0x2150, 0x2900, 0xb002, 0xa803, 0x0000, 0x00ae, 0xb852, 0x0c90, - 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e, 0x0498, - 0x9082, 0x0006, 0x1290, 0x080c, 0x9dc1, 0x1160, 0xb8a0, 0x9084, - 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0990, 0x2001, 0x0029, 0x2009, - 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, 0xd1fc, 0x0118, 0x2009, - 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, - 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x180c, - 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x905d, 0x09a8, - 0x080c, 0x656b, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, 0x5d77, - 0x080c, 0x63e3, 0x0904, 0x5d90, 0x0804, 0x5d7b, 0x00b6, 0x00e6, - 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, 0x5e61, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x5e39, 0xb8a0, 0x9086, - 0x007f, 0x0178, 0x080c, 0x6573, 0x0160, 0xa994, 0x81ff, 0x0130, - 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x656b, - 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, - 0x0026, 0x2010, 0x080c, 0xbb1a, 0x002e, 0x1120, 0x2001, 0x0008, - 0x0804, 0x5e63, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, - 0x0804, 0x5e63, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, - 0x080c, 0x9dec, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, - 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x9ebc, 0x9006, - 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, - 0x9dc1, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, - 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, - 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, - 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, - 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x2001, 0x002c, 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, - 0xa8e0, 0x9005, 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, - 0x9005, 0x1518, 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, - 0x1800, 0x9182, 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, - 0xaa98, 0xab94, 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, - 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, - 0x00be, 0x00fe, 0x0005, 0x5ef8, 0x5eb3, 0x5eca, 0x5ef8, 0x5ef8, - 0x5ef8, 0x5ef8, 0x5ef8, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, - 0x61e7, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x5f00, 0xb814, - 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x47a3, - 0x0150, 0x04b0, 0x080c, 0x6247, 0x1598, 0xb810, 0x9306, 0x1580, - 0xb814, 0x9206, 0x1568, 0x080c, 0x9dec, 0x0530, 0x2b00, 0x6012, - 0x080c, 0xbfa6, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, - 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x2fdc, 0x9006, 0x080c, - 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, 0x2001, 0x0200, 0xb86e, - 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0x9ebc, 0x9006, 0x0068, - 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, - 0x2001, 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, - 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, - 0x90c6, 0x0015, 0x0904, 0x60d5, 0x90c6, 0x0056, 0x0904, 0x60d9, - 0x90c6, 0x0066, 0x0904, 0x60dd, 0x90c6, 0x0067, 0x0904, 0x60e1, - 0x90c6, 0x0068, 0x0904, 0x60e5, 0x90c6, 0x0071, 0x0904, 0x60e9, - 0x90c6, 0x0074, 0x0904, 0x60ed, 0x90c6, 0x007c, 0x0904, 0x60f1, - 0x90c6, 0x007e, 0x0904, 0x60f5, 0x90c6, 0x0037, 0x0904, 0x60f9, - 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x60d0, - 0x9182, 0x0800, 0x1a04, 0x60d0, 0x080c, 0x6247, 0x1198, 0xb804, - 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, - 0x0148, 0x080c, 0x9dc1, 0x1904, 0x60b9, 0xb8a0, 0x9084, 0xff80, - 0x1904, 0x60b9, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, - 0x0904, 0x6019, 0x90c6, 0x0064, 0x0904, 0x6042, 0x2008, 0x0804, - 0x5fdc, 0xa998, 0xa8b0, 0x2040, 0x080c, 0x9dc1, 0x1120, 0x9182, - 0x007f, 0x0a04, 0x5fdc, 0x9186, 0x00ff, 0x0904, 0x5fdc, 0x9182, - 0x0800, 0x1a04, 0x5fdc, 0xaaa0, 0xab9c, 0x7878, 0x9306, 0x1188, - 0x787c, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, - 0x5fdc, 0x99cc, 0xff00, 0x009e, 0x1120, 0x2208, 0x2310, 0x0804, - 0x5fdc, 0x080c, 0x47a3, 0x0904, 0x5fe5, 0x900e, 0x9016, 0x90c6, - 0x4000, 0x1558, 0x0006, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, - 0x2098, 0x080c, 0x0f68, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0035, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, - 0x2098, 0x080c, 0x0f68, 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, - 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, - 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, - 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, - 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0470, 0x080c, 0x9dec, 0x1130, - 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c80, 0x2b00, 0x6012, - 0x080c, 0xbfa6, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, - 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2fdc, - 0x012e, 0x9006, 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, - 0x2009, 0x0002, 0x080c, 0x9ebc, 0xa8b0, 0xd094, 0x0118, 0xb8bc, - 0xc08d, 0xb8be, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, - 0x0005, 0x080c, 0x53a3, 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, - 0xaeb0, 0x080c, 0x6247, 0x1904, 0x5fd7, 0x9186, 0x007f, 0x0130, - 0x080c, 0x656b, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, - 0x0feb, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, - 0xa806, 0x080c, 0xbd12, 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x5fde, 0xa998, 0xaeb0, 0x080c, 0x6247, 0x1904, 0x5fd7, - 0x0096, 0x080c, 0x0feb, 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, - 0x6096, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, - 0xb8b4, 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, - 0xbbb8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f68, 0x009e, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, - 0x538f, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, - 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x656b, 0x0118, 0xa89b, - 0x0009, 0x0080, 0x080c, 0x53a3, 0x0118, 0xa89b, 0x0007, 0x0050, - 0x080c, 0xbcf5, 0x1904, 0x6012, 0x2009, 0x0003, 0x2001, 0x4005, - 0x0804, 0x5fde, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, - 0x2041, 0x122f, 0x080c, 0xa345, 0x1904, 0x6012, 0x2009, 0x0002, - 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x6013, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x6013, - 0x2001, 0x0029, 0x900e, 0x0804, 0x6013, 0x080c, 0x3569, 0x0804, - 0x6014, 0x080c, 0x50cc, 0x0804, 0x6014, 0x080c, 0x4339, 0x0804, - 0x6014, 0x080c, 0x43b2, 0x0804, 0x6014, 0x080c, 0x440e, 0x0804, - 0x6014, 0x080c, 0x485f, 0x0804, 0x6014, 0x080c, 0x4b04, 0x0804, - 0x6014, 0x080c, 0x4d37, 0x0804, 0x6014, 0x080c, 0x4f30, 0x0804, - 0x6014, 0x080c, 0x3779, 0x0804, 0x6014, 0x00b6, 0xa974, 0xae78, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182, 0x0800, 0x1268, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, 0x080c, 0x656b, 0x1148, - 0x00e9, 0x080c, 0x6372, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, - 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d88, 0x2001, - 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, - 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, 0x0126, 0x2091, - 0x8000, 0xb850, 0x900d, 0x0150, 0x2900, 0x0096, 0x2148, 0xa802, - 0x009e, 0xa803, 0x0000, 0xb852, 0x012e, 0x0005, 0x2900, 0xb852, - 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0xb84c, - 0x9005, 0x0170, 0x00e6, 0x2071, 0x19b7, 0x7004, 0x9086, 0x0002, - 0x0168, 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e, 0x012e, 0x0005, - 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x701c, 0x9b06, - 0x1d80, 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802, 0x2900, 0xb002, - 0x00ae, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0xb84c, - 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, - 0x012e, 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, - 0xb852, 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, - 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, - 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, - 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, - 0x6567, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, - 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, - 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0db4, 0x000e, - 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, - 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6563, 0x1138, 0x9284, 0x00ff, - 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, - 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, - 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, - 0x1000, 0x2204, 0x905d, 0x1180, 0x0096, 0x080c, 0x0feb, 0x2958, - 0x009e, 0x0160, 0x2b00, 0x2012, 0xb85c, 0xb8ba, 0xb860, 0xb8b6, - 0x9006, 0xb8a6, 0x080c, 0x5cf4, 0x9006, 0x0010, 0x9085, 0x0001, - 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, 0x8000, - 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, - 0x9190, 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, 0xb8a4, - 0x904d, 0x0110, 0x080c, 0x101d, 0x00d6, 0x00c6, 0xb8ac, 0x2060, - 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, 0xbb2c, - 0x0110, 0x080c, 0x0f9d, 0x080c, 0x9e42, 0x00ce, 0x0c88, 0x00ce, - 0x00de, 0x2b48, 0xb8b8, 0xb85e, 0xb8b4, 0xb862, 0x080c, 0x102d, - 0x00de, 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, - 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, - 0x2104, 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, - 0x0136, 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, - 0x080c, 0x6f9b, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, - 0x9dc1, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, - 0x1952, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, - 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, - 0x0001, 0x6886, 0x2069, 0x1800, 0x68b2, 0x7040, 0xb85e, 0x7048, - 0xb862, 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8b4, - 0x20e8, 0xb8b8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, - 0x2099, 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, - 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, - 0x7048, 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, - 0xb8a0, 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, - 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, - 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, - 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, - 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, - 0x0003, 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, - 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, - 0xb896, 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbbc, 0xc384, - 0xba00, 0x2009, 0x1873, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, - 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, - 0xd0cc, 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, - 0xbbbe, 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, - 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, - 0xaa04, 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, - 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, - 0x9080, 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, - 0x9086, 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0db4, 0x3c00, - 0x20e8, 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x0060, 0x080c, 0x0feb, 0x0170, 0x2900, - 0xb8a6, 0xa803, 0x0000, 0x080c, 0x6403, 0xa807, 0x0001, 0xae12, - 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, - 0x2091, 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, - 0x1150, 0x080c, 0x6412, 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, - 0x8001, 0xa806, 0x0020, 0x080c, 0x101d, 0xb8a7, 0x0000, 0x009e, - 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x83f7, 0x012e, - 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, - 0x8000, 0xb84c, 0x2048, 0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, - 0x83ff, 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, - 0x1118, 0xa870, 0x9506, 0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, - 0x080c, 0x97b1, 0xaa00, 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, - 0x00a6, 0x2150, 0xb202, 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, - 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, - 0x080c, 0x6467, 0x0128, 0x080c, 0xbbe9, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6467, 0x0128, 0x080c, 0xbb8e, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x6467, 0x0128, 0x080c, 0xbbe6, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x6467, 0x0128, 0x080c, 0xbbad, - 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6467, 0x0128, 0x080c, - 0xbc2a, 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, - 0x9085, 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, - 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, - 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, - 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, - 0x01ce, 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, - 0x01de, 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, + 0x7093, 0x0000, 0x7097, 0x000e, 0x080c, 0x5816, 0x0010, 0x080c, + 0x5c9b, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x000b, 0x2011, 0x1c0e, + 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, + 0x080c, 0x5c43, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, + 0x080c, 0x5ca2, 0x0118, 0x2013, 0x0000, 0x0020, 0x705c, 0x9085, + 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x1c0e, + 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, + 0x6812, 0x2009, 0x0240, 0x1f04, 0x5798, 0x60c3, 0x0084, 0x080c, + 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01c0, 0x2011, + 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0084, 0x1178, 0x080c, 0x5cbf, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, + 0x1120, 0x7097, 0x000c, 0x0029, 0x0010, 0x080c, 0x5c9b, 0x00fe, + 0x0005, 0x00f6, 0x7097, 0x000d, 0x080c, 0x5c43, 0x2079, 0x0240, + 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x5cbf, 0x20a9, 0x0040, + 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, + 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, + 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x57dc, 0x60c3, 0x0084, + 0x080c, 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, + 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0084, 0x1198, 0x080c, + 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, + 0x9005, 0x1140, 0x7093, 0x0001, 0x080c, 0x5c15, 0x7097, 0x000e, + 0x0029, 0x0010, 0x080c, 0x5c9b, 0x00fe, 0x0005, 0x918d, 0x0001, + 0x080c, 0x5cea, 0x7097, 0x000f, 0x708f, 0x0000, 0x2061, 0x0140, + 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, + 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5b4e, 0x080c, 0x8033, + 0x0005, 0x708c, 0x9005, 0x0130, 0x2011, 0x5b4e, 0x080c, 0x803f, + 0x7097, 0x0000, 0x0005, 0x7097, 0x0011, 0x080c, 0x9c37, 0x080c, + 0x5cbf, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x748c, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, + 0x8004, 0x20a8, 0x4003, 0x080c, 0x5ca2, 0x11a0, 0x7178, 0x81ff, + 0x0188, 0x900e, 0x707c, 0x9084, 0x00ff, 0x0160, 0x080c, 0x2670, + 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, + 0x080c, 0x5afb, 0x60c3, 0x0014, 0x080c, 0x5b78, 0x0005, 0x00f6, + 0x708c, 0x9005, 0x0500, 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, + 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0012, 0x0029, + 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0013, + 0x080c, 0x5c51, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, + 0x080c, 0x5cbf, 0x080c, 0x5ca2, 0x1170, 0x7080, 0x9005, 0x1158, + 0x7158, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5afb, + 0x0168, 0x080c, 0x5c78, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, + 0x080c, 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, + 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, + 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, + 0x70c3, 0x0001, 0x7097, 0x0014, 0x0029, 0x0010, 0x708f, 0x0000, + 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0015, 0x080c, 0x5c51, 0x2079, + 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5cbf, 0x080c, + 0x5ca2, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, + 0x0180, 0x9180, 0x3145, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, + 0x0008, 0x080c, 0x5afb, 0x0180, 0x080c, 0x4cac, 0x0110, 0x080c, + 0x26d9, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b78, + 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x05f0, 0x2011, 0x5b4e, + 0x080c, 0x803f, 0x9086, 0x0014, 0x15a8, 0x080c, 0x5cbf, 0x2079, + 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, + 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x5cea, + 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, + 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, + 0x1110, 0x70c3, 0x0001, 0x9085, 0x0001, 0x080c, 0x5cea, 0x7093, + 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, 0x7097, 0x0016, + 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x080c, 0x9c37, + 0x080c, 0x5cbf, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, + 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, + 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x7097, + 0x0017, 0x080c, 0x5ca2, 0x1150, 0x7080, 0x9005, 0x1138, 0x080c, + 0x5a6e, 0x1188, 0x9085, 0x0001, 0x080c, 0x26d9, 0x20a9, 0x0008, + 0x080c, 0x5cbf, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, + 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b78, 0x0010, + 0x080c, 0x55c8, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01d8, 0x2011, + 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0084, 0x1190, 0x080c, 0x5cbf, + 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, + 0x1138, 0x9006, 0x080c, 0x5cea, 0x7097, 0x0018, 0x0029, 0x0010, + 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0019, 0x080c, + 0x5c51, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, + 0x5cbf, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040, 0x213e, + 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, + 0x2009, 0x0260, 0x1f04, 0x59d7, 0x2039, 0x1c0e, 0x080c, 0x5ca2, + 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, + 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x705c, 0x2310, 0x8214, + 0x92a0, 0x1c0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, + 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, + 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, + 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5a0a, 0x60c3, + 0x0084, 0x080c, 0x5b78, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, + 0x01e0, 0x2011, 0x5b4e, 0x080c, 0x803f, 0x9086, 0x0084, 0x1198, + 0x080c, 0x5cbf, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, + 0x7834, 0x9005, 0x1140, 0x7093, 0x0001, 0x080c, 0x5c15, 0x7097, + 0x001a, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x9085, + 0x0001, 0x080c, 0x5cea, 0x7097, 0x001b, 0x080c, 0x9c37, 0x080c, + 0x5cbf, 0x2011, 0x0260, 0x2009, 0x0240, 0x748c, 0x9480, 0x0018, + 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, + 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, + 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5a56, + 0x60c3, 0x0084, 0x080c, 0x5b78, 0x0005, 0x0005, 0x0086, 0x0096, + 0x2029, 0x185c, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e, 0x20e9, + 0x0001, 0x28a0, 0x080c, 0x5cbf, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, + 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, + 0x8210, 0x0008, 0x8211, 0x1f04, 0x5a88, 0x0804, 0x5af7, 0x82ff, + 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, + 0x3fff, 0x0904, 0x5af7, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, + 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, + 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, + 0x8318, 0x1f04, 0x5aae, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, + 0x8425, 0x1f04, 0x5ac0, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, + 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, + 0x0010, 0x1f04, 0x5acf, 0x755a, 0x95c8, 0x3145, 0x292d, 0x95ac, + 0x00ff, 0x757e, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x26b9, + 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, + 0x7083, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, + 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, + 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, 0x0146, + 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x2011, + 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, 0x015e, + 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, 0x8420, + 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, + 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, + 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, + 0x203a, 0x715a, 0x91a0, 0x3145, 0x242d, 0x95ac, 0x00ff, 0x757e, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x26b9, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x7083, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, + 0x2071, 0x1800, 0x7087, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, + 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x5c04, 0x080c, 0x93c7, + 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2b31, 0x0126, 0x2091, + 0x8000, 0x2071, 0x1825, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, + 0x2009, 0x00f7, 0x080c, 0x5c61, 0x001e, 0x9094, 0x0010, 0x9285, + 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x29d7, 0x0228, 0x2011, 0x0101, + 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19c9, 0x2013, 0x0000, 0x708f, + 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x93be, + 0x6144, 0xd184, 0x0120, 0x7194, 0x918d, 0x2000, 0x0018, 0x7188, + 0x918d, 0x1000, 0x2011, 0x1971, 0x2112, 0x2009, 0x07d0, 0x2011, + 0x5b4e, 0x080c, 0x80d1, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x080c, 0x9db5, 0x2009, 0x00f7, 0x080c, 0x5c61, + 0x2061, 0x19d2, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, + 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, + 0x0010, 0x2009, 0x1971, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, + 0x5bd0, 0x080c, 0x8033, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, + 0x080c, 0x93c7, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, + 0x080c, 0x2b31, 0x080c, 0x6fb2, 0x0188, 0x080c, 0x6fcd, 0x1170, + 0x080c, 0x7296, 0x0016, 0x080c, 0x2788, 0x2001, 0x1945, 0x2102, + 0x001e, 0x080c, 0x7291, 0x080c, 0x6edc, 0x0050, 0x2009, 0x0001, + 0x080c, 0x2a70, 0x2001, 0x0001, 0x080c, 0x2619, 0x080c, 0x5ba4, + 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, + 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1971, 0x201c, + 0x080c, 0x48f4, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, + 0x0001, 0x20a1, 0x1c80, 0x080c, 0x5cbf, 0x20e9, 0x0000, 0x2099, + 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x5cb9, 0x2099, 0x0260, + 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x5cbc, 0x2099, + 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, + 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x5c39, + 0x002e, 0x001e, 0x0005, 0x080c, 0x9c37, 0x20e1, 0x0001, 0x2099, + 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, + 0x0005, 0x080c, 0x9c37, 0x080c, 0x5cbf, 0x20e1, 0x0000, 0x2099, + 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, + 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1833, + 0x2004, 0x9005, 0x1138, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, + 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, + 0x0016, 0x0046, 0x080c, 0x6576, 0x0158, 0x9006, 0x2020, 0x2009, + 0x002a, 0x080c, 0xd564, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, + 0x2019, 0x002a, 0x900e, 0x080c, 0x2fb2, 0x080c, 0xc23b, 0x0140, + 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4a91, 0x003e, + 0x004e, 0x001e, 0x0005, 0x080c, 0x5ba4, 0x7097, 0x0000, 0x708f, + 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, + 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, + 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, + 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, + 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, + 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, + 0x1c00, 0x4004, 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807, 0x00ef, + 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, + 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, + 0x0001, 0x0005, 0x2001, 0x197e, 0x0118, 0x2003, 0x0001, 0x0010, + 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, + 0x9006, 0x200a, 0x8108, 0x1f04, 0x5cf9, 0x015e, 0x0005, 0x00d6, + 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x185b, 0x9006, 0xb802, + 0xb8be, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x3145, + 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8b2, 0x080c, + 0x9dae, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbb2, 0x20a9, 0x0004, + 0xb8b4, 0x20e8, 0xb9b8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, + 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, + 0xb83e, 0xb842, 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e, 0xb862, + 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, + 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8ae, 0xb9a2, + 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x101d, 0xb8a7, 0x0000, + 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0x6814, + 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1a04, 0x5dcf, 0x9182, 0x0800, 0x1a04, 0x5dd3, + 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x5dd9, 0x9188, + 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff, 0x908e, + 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x5deb, 0xb850, 0x900d, + 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, 0x8415, 0x9006, + 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803, 0x0000, + 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, + 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0x9dae, + 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0990, + 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, + 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, + 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, + 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, + 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, + 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, + 0x2104, 0x905d, 0x09a8, 0x080c, 0x657a, 0x1990, 0xb800, 0xd0bc, + 0x0978, 0x0804, 0x5d82, 0x080c, 0x63f2, 0x0904, 0x5d9b, 0x0804, + 0x5d86, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, + 0x0800, 0x1a04, 0x5e6c, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, + 0x5e44, 0xb8a0, 0x9086, 0x007f, 0x0178, 0x080c, 0x6582, 0x0160, + 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, + 0x0118, 0x080c, 0x657a, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, + 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xbb29, 0x002e, + 0x1120, 0x2001, 0x0008, 0x0804, 0x5e6e, 0x6020, 0x9086, 0x000a, + 0x0120, 0x2001, 0x0008, 0x0804, 0x5e6e, 0x601a, 0x6003, 0x0008, + 0x2900, 0x6016, 0x0058, 0x080c, 0x9dd9, 0x05e8, 0x2b00, 0x6012, + 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, + 0x080c, 0x9ea9, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, + 0x0006, 0x1290, 0x080c, 0x9dae, 0x1160, 0xb8a0, 0x9084, 0xff80, + 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, + 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, + 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, + 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, 0x012e, + 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00f6, 0x00b6, + 0x0126, 0x2091, 0x8000, 0xa8e0, 0x9005, 0x1550, 0xa8dc, 0x9082, + 0x0101, 0x1630, 0xa8c8, 0x9005, 0x1518, 0xa8c4, 0x9082, 0x0101, + 0x12f8, 0xa974, 0x2079, 0x1800, 0x9182, 0x0800, 0x12e8, 0x7830, + 0x9084, 0x0003, 0x1130, 0xaa98, 0xab94, 0xa878, 0x9084, 0x0007, + 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, + 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, + 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, + 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x5f03, 0x5ebe, + 0x5ed5, 0x5f03, 0x5f03, 0x5f03, 0x5f03, 0x5f03, 0x2100, 0x9082, + 0x007e, 0x1278, 0x080c, 0x61f6, 0x0148, 0x9046, 0xb810, 0x9306, + 0x1904, 0x5f0b, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, + 0x0010, 0x080c, 0x47ae, 0x0150, 0x04b0, 0x080c, 0x6256, 0x1598, + 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0x9dd9, + 0x0530, 0x2b00, 0x6012, 0x080c, 0xbfb5, 0x2900, 0x6016, 0x600b, + 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, + 0x2fe7, 0x9006, 0x080c, 0x6193, 0x2001, 0x0002, 0x080c, 0x61a7, + 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, + 0x9ea9, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, + 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, 0x0000, + 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x0126, + 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x60e4, 0x90c6, + 0x0056, 0x0904, 0x60e8, 0x90c6, 0x0066, 0x0904, 0x60ec, 0x90c6, + 0x0067, 0x0904, 0x60f0, 0x90c6, 0x0068, 0x0904, 0x60f4, 0x90c6, + 0x0071, 0x0904, 0x60f8, 0x90c6, 0x0074, 0x0904, 0x60fc, 0x90c6, + 0x007c, 0x0904, 0x6100, 0x90c6, 0x007e, 0x0904, 0x6104, 0x90c6, + 0x0037, 0x0904, 0x6108, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, + 0x00ff, 0x0904, 0x60df, 0x9182, 0x0800, 0x1a04, 0x60df, 0x080c, + 0x6256, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, + 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0x9dae, 0x1904, 0x60c8, + 0xb8a0, 0x9084, 0xff80, 0x1904, 0x60c8, 0xa894, 0x90c6, 0x006f, + 0x0158, 0x90c6, 0x005e, 0x0904, 0x6028, 0x90c6, 0x0064, 0x0904, + 0x6051, 0x2008, 0x0804, 0x5feb, 0xa998, 0xa8b0, 0x2040, 0x080c, + 0x9dae, 0x1120, 0x9182, 0x007f, 0x0a04, 0x5feb, 0x9186, 0x00ff, + 0x0904, 0x5feb, 0x9182, 0x0800, 0x1a04, 0x5feb, 0xaaa0, 0xab9c, + 0x7878, 0x9306, 0x11a8, 0x787c, 0x0096, 0x924e, 0x1128, 0x2208, + 0x2310, 0x009e, 0x0804, 0x5feb, 0x080c, 0x9dae, 0x1140, 0x99cc, + 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x5feb, 0x009e, + 0x080c, 0x47ae, 0x0904, 0x5ff4, 0x900e, 0x9016, 0x90c6, 0x4000, + 0x1558, 0x0006, 0x080c, 0x6476, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, + 0x080c, 0x0f68, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0035, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, + 0x080c, 0x0f68, 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, + 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, + 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, + 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, + 0x2001, 0x0030, 0x900e, 0x0470, 0x080c, 0x9dd9, 0x1130, 0x2001, + 0x4005, 0x2009, 0x0003, 0x9016, 0x0c80, 0x2b00, 0x6012, 0x080c, + 0xbfb5, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, + 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2fe7, 0x012e, + 0x9006, 0x080c, 0x6193, 0x2001, 0x0002, 0x080c, 0x61a7, 0x2009, + 0x0002, 0x080c, 0x9ea9, 0xa8b0, 0xd094, 0x0118, 0xb8bc, 0xc08d, + 0xb8be, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, + 0x080c, 0x53ae, 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, + 0x080c, 0x6256, 0x1904, 0x5fe6, 0x9186, 0x007f, 0x0130, 0x080c, + 0x657a, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x0feb, + 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, + 0x080c, 0xbd21, 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, + 0x5fed, 0xa998, 0xaeb0, 0x080c, 0x6256, 0x1904, 0x5fe6, 0x0096, + 0x080c, 0x0feb, 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x60a5, + 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8b4, + 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, + 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbb8, + 0x9398, 0x0006, 0x2398, 0x080c, 0x0f68, 0x009e, 0xa87b, 0x0000, + 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x539a, + 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, + 0xa89b, 0x000c, 0x00b0, 0x080c, 0x657a, 0x0118, 0xa89b, 0x0009, + 0x0080, 0x080c, 0x53ae, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, + 0xbd04, 0x1904, 0x6021, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, + 0x5fed, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, + 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, + 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, + 0x122f, 0x080c, 0xa332, 0x1904, 0x6021, 0x2009, 0x0002, 0x08e8, + 0x2001, 0x0028, 0x900e, 0x0804, 0x6022, 0x2009, 0x180c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, 0x6022, 0x2001, + 0x0029, 0x900e, 0x0804, 0x6022, 0x080c, 0x3574, 0x0804, 0x6023, + 0x080c, 0x50d7, 0x0804, 0x6023, 0x080c, 0x4344, 0x0804, 0x6023, + 0x080c, 0x43bd, 0x0804, 0x6023, 0x080c, 0x4419, 0x0804, 0x6023, + 0x080c, 0x486a, 0x0804, 0x6023, 0x080c, 0x4b0f, 0x0804, 0x6023, + 0x080c, 0x4d42, 0x0804, 0x6023, 0x080c, 0x4f3b, 0x0804, 0x6023, + 0x080c, 0x3784, 0x0804, 0x6023, 0x00b6, 0xa974, 0xae78, 0x9684, + 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182, 0x0800, 0x1268, 0x9188, + 0x1000, 0x2104, 0x905d, 0x0140, 0x080c, 0x657a, 0x1148, 0x00e9, + 0x080c, 0x6381, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, + 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d88, 0x2001, 0x0029, + 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, + 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, + 0xb850, 0x900d, 0x0150, 0x2900, 0x0096, 0x2148, 0xa802, 0x009e, + 0xa803, 0x0000, 0xb852, 0x012e, 0x0005, 0x2900, 0xb852, 0xb84e, + 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0xb84c, 0x9005, + 0x0170, 0x00e6, 0x2071, 0x19bf, 0x7004, 0x9086, 0x0002, 0x0168, + 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e, 0x012e, 0x0005, 0x2900, + 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x701c, 0x9b06, 0x1d80, + 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802, 0x2900, 0xb002, 0x00ae, + 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0xb84c, 0x904d, + 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, 0x012e, + 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, + 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, 0x2091, + 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, 0x0008, + 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, + 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, + 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, 0x6576, + 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, + 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, 0x9086, + 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0db4, 0x000e, 0x00ce, + 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, + 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, 0xb89c, + 0xd0a4, 0x0150, 0x080c, 0x6572, 0x1138, 0x9284, 0x00ff, 0x9086, + 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, + 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, 0x0800, + 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, 0x1000, + 0x2204, 0x905d, 0x1180, 0x0096, 0x080c, 0x0feb, 0x2958, 0x009e, + 0x0160, 0x2b00, 0x2012, 0xb85c, 0xb8ba, 0xb860, 0xb8b6, 0x9006, + 0xb8a6, 0x080c, 0x5cff, 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, + 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, 0x8000, 0x0026, + 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, + 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, 0xb8a4, 0x904d, + 0x0110, 0x080c, 0x101d, 0x00d6, 0x00c6, 0xb8ac, 0x2060, 0x8cff, + 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0110, + 0x080c, 0x0f9d, 0x080c, 0x9e2f, 0x00ce, 0x0c88, 0x00ce, 0x00de, + 0x2b48, 0xb8b8, 0xb85e, 0xb8b4, 0xb862, 0x080c, 0x102d, 0x00de, + 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, + 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, + 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, + 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, + 0x6faa, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0x9dae, + 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x195a, + 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, + 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, + 0x6886, 0x2069, 0x1800, 0x68b2, 0x7040, 0xb85e, 0x7048, 0xb862, + 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8b4, 0x20e8, + 0xb8b8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, + 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, + 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, + 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, + 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, + 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, + 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, + 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, + 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, + 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, + 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, + 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbbc, 0xc384, 0xba00, + 0x2009, 0x187b, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, + 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, + 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbbe, + 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, + 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, + 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, + 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, + 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, + 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0db4, 0x3c00, 0x20e8, + 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, + 0x014e, 0x013e, 0x0060, 0x080c, 0x0feb, 0x0170, 0x2900, 0xb8a6, + 0xa803, 0x0000, 0x080c, 0x6412, 0xa807, 0x0001, 0xae12, 0x9085, + 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, + 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, + 0x080c, 0x6421, 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, + 0xa806, 0x0020, 0x080c, 0x101d, 0xb8a7, 0x0000, 0x009e, 0x012e, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x8415, 0x012e, 0x0005, + 0x901e, 0x0010, 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, + 0xb84c, 0x2048, 0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, 0x83ff, + 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, + 0xa870, 0x9506, 0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, 0x080c, + 0x979a, 0xaa00, 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, + 0x2150, 0xb202, 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, + 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, + 0x6476, 0x0128, 0x080c, 0xbbf8, 0x0010, 0x9085, 0x0001, 0x0005, + 0x080c, 0x6476, 0x0128, 0x080c, 0xbb9d, 0x0010, 0x9085, 0x0001, + 0x0005, 0x080c, 0x6476, 0x0128, 0x080c, 0xbbf5, 0x0010, 0x9085, + 0x0001, 0x0005, 0x080c, 0x6476, 0x0128, 0x080c, 0xbbbc, 0x0010, + 0x9085, 0x0001, 0x0005, 0x080c, 0x6476, 0x0128, 0x080c, 0xbc39, + 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, + 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, - 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, - 0x3300, 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, - 0x01de, 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, - 0x2091, 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x0feb, 0x0168, - 0x2900, 0xb8a6, 0x080c, 0x6403, 0xa803, 0x0001, 0xa807, 0x0000, - 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, - 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, - 0x080c, 0x101d, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, - 0xd0a4, 0x0005, 0x00b6, 0x00f6, 0x080c, 0x6f9b, 0x01b0, 0x71c0, - 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, - 0x1000, 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1853, 0x7804, - 0x00d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6247, - 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, - 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, - 0x1f04, 0x648d, 0x015e, 0x080c, 0x6529, 0x0120, 0x2001, 0x1955, - 0x200c, 0x0030, 0x2079, 0x1853, 0x7804, 0x0030, 0x2009, 0x07d0, - 0x2011, 0x64b7, 0x080c, 0x80b3, 0x00fe, 0x00be, 0x0005, 0x00b6, - 0x2011, 0x64b7, 0x080c, 0x8021, 0x080c, 0x6529, 0x01d8, 0x2001, - 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6567, - 0x0130, 0x2009, 0x07d0, 0x2011, 0x64b7, 0x080c, 0x80b3, 0x00e6, - 0x2071, 0x1800, 0x9006, 0x707a, 0x705c, 0x707e, 0x080c, 0x2dbd, - 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, - 0x080c, 0x6247, 0x1538, 0xb800, 0xd0ec, 0x0520, 0x0046, 0xbaa0, - 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, 0xd54b, 0xb800, 0xc0e5, - 0xc0ec, 0xb802, 0x080c, 0x6563, 0x2001, 0x0707, 0x1128, 0xb804, - 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, 0x2019, 0x0029, 0x080c, - 0x8564, 0x0076, 0x903e, 0x080c, 0x8452, 0x900e, 0x080c, 0xd2bc, - 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x64df, 0x00ce, 0x015e, - 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, - 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, - 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, - 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, - 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, - 0x0db4, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1836, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0x1953, 0x200c, 0x2011, 0x6559, 0x080c, 0x80b3, - 0x0005, 0x2011, 0x6559, 0x080c, 0x8021, 0x2011, 0x1836, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x080c, 0x538f, 0xd0ac, 0x0005, 0x080c, - 0x538f, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, - 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, - 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xc22c, - 0x0158, 0x70d8, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, - 0x905d, 0x0110, 0xb8bc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, - 0x0016, 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1817, 0x203c, - 0x9780, 0x313a, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, - 0x2008, 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, - 0x2100, 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, - 0xb89c, 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, - 0x9182, 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, - 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, - 0x0005, 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, - 0x0005, 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, - 0x9080, 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1817, - 0x203c, 0x9780, 0x313a, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, - 0x2020, 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, - 0x0178, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, - 0xd0a4, 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, - 0x8420, 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, - 0x007e, 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, - 0x00be, 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x2071, 0x1906, - 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, - 0x701e, 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1919, - 0x900e, 0x710a, 0x080c, 0x538f, 0xd0fc, 0x1140, 0x080c, 0x538f, - 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0400, 0x2001, 0x1873, - 0x200c, 0x9184, 0x0007, 0x9006, 0x0002, 0x663e, 0x663e, 0x663e, - 0x663e, 0x663e, 0x6655, 0x6663, 0x663e, 0x7003, 0x0003, 0x2009, - 0x1874, 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, - 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, - 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, - 0x2071, 0x1906, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, - 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, 0x72f1, 0x6a60, 0x9200, - 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, - 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, - 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, - 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, - 0x1906, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, - 0x00ee, 0x9006, 0x00ee, 0x0005, 0xa868, 0xd0fc, 0x11d8, 0x00e6, - 0x0026, 0x2001, 0x1919, 0x2004, 0x9005, 0x0904, 0x6896, 0xa87c, - 0xd0bc, 0x1904, 0x6896, 0xa978, 0xa874, 0x9105, 0x1904, 0x6896, - 0x2001, 0x1919, 0x2004, 0x0002, 0x6896, 0x66ef, 0x672b, 0x672b, - 0x6896, 0x672b, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, - 0x2009, 0x1919, 0x210c, 0x81ff, 0x0904, 0x6896, 0xa87c, 0xd0cc, - 0x0904, 0x6896, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, - 0x6896, 0x9186, 0x0003, 0x0904, 0x672b, 0x9186, 0x0005, 0x0904, - 0x672b, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, - 0x8020, 0xa853, 0x0016, 0x2071, 0x1906, 0x701c, 0x9005, 0x1904, - 0x6a4a, 0x0e04, 0x6a95, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, - 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2071, 0x1800, - 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, - 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f46, 0x002e, 0x00ee, - 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, - 0x2071, 0x1906, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x681a, - 0x782c, 0x908c, 0x0780, 0x190c, 0x6bbc, 0x8004, 0x8004, 0x8004, - 0x9084, 0x0003, 0x0002, 0x6749, 0x681a, 0x676e, 0x67b5, 0x080c, - 0x0db4, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1170, - 0x2071, 0x19ca, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, 0x2004, - 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f46, 0x0c10, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1580, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x182f, 0x210c, 0x918a, - 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7f46, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, 0x19f0, 0x2071, - 0x19ca, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, 0x2004, 0x8005, + 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, + 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, + 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, + 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, + 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, + 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, + 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, + 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, + 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x0feb, 0x0168, 0x2900, + 0xb8a6, 0x080c, 0x6412, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, + 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, + 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, + 0x101d, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, + 0x0005, 0x00b6, 0x00f6, 0x080c, 0x6faa, 0x01b0, 0x71c0, 0x81ff, + 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, + 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, + 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x185b, 0x7804, 0x00d0, + 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6256, 0x1168, + 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, + 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, + 0x649c, 0x015e, 0x080c, 0x6538, 0x0120, 0x2001, 0x195d, 0x200c, + 0x0030, 0x2079, 0x185b, 0x7804, 0x0030, 0x2009, 0x07d0, 0x2011, + 0x64c6, 0x080c, 0x80d1, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, + 0x64c6, 0x080c, 0x803f, 0x080c, 0x6538, 0x01d8, 0x2001, 0x107e, + 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6576, 0x0130, + 0x2009, 0x07d0, 0x2011, 0x64c6, 0x080c, 0x80d1, 0x00e6, 0x2071, + 0x1800, 0x9006, 0x707a, 0x705c, 0x707e, 0x080c, 0x2dc8, 0x00ee, + 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, + 0x6256, 0x1538, 0xb800, 0xd0ec, 0x0520, 0x0046, 0xbaa0, 0x2220, + 0x9006, 0x2009, 0x0029, 0x080c, 0xd564, 0xb800, 0xc0e5, 0xc0ec, + 0xb802, 0x080c, 0x6572, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, + 0x00ff, 0x9085, 0x0700, 0xb806, 0x2019, 0x0029, 0x080c, 0x8582, + 0x0076, 0x903e, 0x080c, 0x8470, 0x900e, 0x080c, 0xd2d5, 0x007e, + 0x004e, 0x001e, 0x8108, 0x1f04, 0x64ee, 0x00ce, 0x015e, 0x00be, + 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, 0x00be, + 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, 0x0005, + 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, 0x0005, + 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, + 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, + 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0db4, + 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, + 0x002e, 0x012e, 0x0005, 0x2011, 0x1836, 0x2204, 0xd0cc, 0x0138, + 0x2001, 0x195b, 0x200c, 0x2011, 0x6568, 0x080c, 0x80d1, 0x0005, + 0x2011, 0x6568, 0x080c, 0x803f, 0x2011, 0x1836, 0x2204, 0xc0cc, + 0x2012, 0x0005, 0x080c, 0x539a, 0xd0ac, 0x0005, 0x080c, 0x539a, + 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, + 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, + 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xc23b, 0x0158, + 0x70d8, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, + 0x0110, 0xb8bc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, + 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1817, 0x203c, 0x9780, + 0x3145, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, 0x2008, + 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, 0x2100, + 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, 0xb804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, 0xb89c, + 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, 0x9182, + 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, 0x00be, + 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, 0x0005, + 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, 0x0005, + 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, 0x9080, + 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1817, 0x203c, + 0x9780, 0x3145, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2020, + 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, 0x0178, + 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, 0xd0a4, + 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, 0x8420, + 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, 0x007e, + 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, 0x00be, + 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x2071, 0x190e, 0x7003, + 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, + 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1921, 0x900e, + 0x710a, 0x080c, 0x539a, 0xd0fc, 0x1140, 0x080c, 0x539a, 0x900e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x0400, 0x2001, 0x187b, 0x200c, + 0x9184, 0x0007, 0x9006, 0x0002, 0x664d, 0x664d, 0x664d, 0x664d, + 0x664d, 0x6664, 0x6672, 0x664d, 0x7003, 0x0003, 0x2009, 0x187c, + 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, + 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, 0x0005, + 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, + 0x190e, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, + 0x6844, 0x9005, 0x0158, 0x080c, 0x72fe, 0x6a60, 0x9200, 0x7002, + 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, + 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, + 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, + 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x190e, + 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, + 0x9006, 0x00ee, 0x0005, 0xa868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, + 0x2001, 0x1921, 0x2004, 0x9005, 0x0904, 0x68a5, 0xa87c, 0xd0bc, + 0x1904, 0x68a5, 0xa978, 0xa874, 0x9105, 0x1904, 0x68a5, 0x2001, + 0x1921, 0x2004, 0x0002, 0x68a5, 0x66fe, 0x673a, 0x673a, 0x68a5, + 0x673a, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, + 0x1921, 0x210c, 0x81ff, 0x0904, 0x68a5, 0xa87c, 0xd0cc, 0x0904, + 0x68a5, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x68a5, + 0x9186, 0x0003, 0x0904, 0x673a, 0x9186, 0x0005, 0x0904, 0x673a, + 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, + 0xa853, 0x0016, 0x2071, 0x190e, 0x701c, 0x9005, 0x1904, 0x6a59, + 0x0e04, 0x6aa4, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, + 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2071, 0x1800, 0x2011, + 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f64, 0x002e, 0x00ee, 0x0005, + 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, + 0x190e, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x6829, 0x782c, + 0x908c, 0x0780, 0x190c, 0x6bcb, 0x8004, 0x8004, 0x8004, 0x9084, + 0x0003, 0x0002, 0x6758, 0x6829, 0x677d, 0x67c4, 0x080c, 0x0db4, + 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1170, 0x2071, + 0x19d2, 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x7f46, 0x0800, 0x0096, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6bbc, 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6bbc, 0xd09c, 0x11a0, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1560, 0x2071, 0x19ca, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, - 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1170, 0x2071, - 0x19ca, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, 0x2004, 0x8005, - 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f46, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1904, 0x686f, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd09c, - 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, - 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6bbc, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6bbc, 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, - 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, 0x1d60, - 0x00ee, 0x2071, 0x19ca, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, - 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, - 0x7f46, 0x00ee, 0x0804, 0x682a, 0xa868, 0xd0fc, 0x1904, 0x68d2, - 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0f9d, 0x009e, - 0x0018, 0xa868, 0xd0fc, 0x15f0, 0x00e6, 0x0026, 0xa84f, 0x0000, - 0x00f6, 0x2079, 0x0050, 0x2071, 0x1800, 0x70e8, 0x8001, 0x01d0, - 0x1678, 0x2071, 0x1906, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, - 0x69c8, 0x782c, 0x908c, 0x0780, 0x190c, 0x6bbc, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0003, 0x0002, 0x68d3, 0x69c8, 0x68ee, 0x695b, - 0x080c, 0x0db4, 0x70eb, 0x0fa0, 0x71e4, 0x8107, 0x9106, 0x9094, - 0x00c0, 0x9184, 0xff3f, 0x9205, 0x70e6, 0x3b08, 0x3a00, 0x9104, - 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x0888, - 0x70ea, 0x0878, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, - 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, + 0x9200, 0x70be, 0x080c, 0x7f64, 0x0c10, 0x2071, 0x1800, 0x2900, + 0x7822, 0xa804, 0x900d, 0x1580, 0x7824, 0x00e6, 0x2071, 0x0040, + 0x712c, 0xd19c, 0x1148, 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, + 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, + 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7f64, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x19f0, 0x2071, 0x19d2, + 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x7f64, 0x0800, 0x0096, 0x00e6, 0x7824, 0x2048, + 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, + 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, + 0xd09c, 0x11a0, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1560, + 0x2071, 0x19d2, 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1170, 0x2071, 0x19d2, + 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f46, 0x0c60, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x694a, 0x7830, 0x8007, - 0x9084, 0x001f, 0x9082, 0x0001, 0x1220, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, - 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, - 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, - 0x8000, 0x70be, 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, - 0x6bbc, 0xd0a4, 0x19f0, 0x0e04, 0x6941, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2001, 0x1917, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2001, 0x1917, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, - 0x7f46, 0x0804, 0x6901, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, - 0x1d60, 0x00ee, 0x0e04, 0x699b, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, - 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x1187, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd09c, - 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f64, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, + 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, + 0x687e, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd09c, 0x1198, + 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, + 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6bcb, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, + 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x7f64, + 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x1d60, 0x00ee, + 0x2071, 0x19d2, 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, + 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f64, + 0x00ee, 0x0804, 0x6839, 0xa868, 0xd0fc, 0x1904, 0x68e1, 0x0096, + 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0f9d, 0x009e, 0x0018, + 0xa868, 0xd0fc, 0x15f0, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, + 0x2079, 0x0050, 0x2071, 0x1800, 0x70e8, 0x8001, 0x01d0, 0x1678, + 0x2071, 0x190e, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x69d7, + 0x782c, 0x908c, 0x0780, 0x190c, 0x6bcb, 0x8004, 0x8004, 0x8004, + 0x9084, 0x0003, 0x0002, 0x68e2, 0x69d7, 0x68fd, 0x696a, 0x080c, + 0x0db4, 0x70eb, 0x0fa0, 0x71e4, 0x8107, 0x9106, 0x9094, 0x00c0, + 0x9184, 0xff3f, 0x9205, 0x70e6, 0x3b08, 0x3a00, 0x9104, 0x918d, + 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x0888, 0x70ea, + 0x0878, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, + 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x7f46, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x9200, 0x70be, 0x080c, 0x7f64, 0x0c60, 0x2071, 0x1800, 0x2900, + 0x7822, 0xa804, 0x900d, 0x1904, 0x6959, 0x7830, 0x8007, 0x9084, + 0x001f, 0x9082, 0x0001, 0x1220, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, + 0x182f, 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, + 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, + 0xd0a4, 0x19f0, 0x0e04, 0x6950, 0x7838, 0x7938, 0x910e, 0x1de0, + 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, + 0x191f, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x1187, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2001, 0x191f, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f64, + 0x0804, 0x6910, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x1d60, + 0x00ee, 0x0e04, 0x69aa, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, + 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1187, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd09c, 0x1170, + 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x7f64, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6a44, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd09c, 0x11b0, 0x701c, 0x904d, + 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, + 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6bcb, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6bcb, 0xd0a4, 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x1d60, + 0x00ee, 0x0e04, 0x6a3d, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, + 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x1187, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, + 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f64, 0x00ee, 0x0804, + 0x69e7, 0x2071, 0x190e, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, + 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, + 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x6a84, 0x002e, 0x00ee, + 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, + 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, + 0x080c, 0x7f64, 0x0e04, 0x6a6e, 0x2071, 0x190e, 0x701c, 0x2048, + 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, + 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2071, 0x190e, 0x080c, + 0x6bb7, 0x002e, 0x00ee, 0x0005, 0x2071, 0x190e, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6a35, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd09c, 0x11b0, 0x701c, - 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, - 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, - 0x0780, 0x190c, 0x6bbc, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6bbc, 0xd0a4, 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, - 0x1d60, 0x00ee, 0x0e04, 0x6a2e, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, - 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x1187, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, - 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x7f46, 0x00ee, - 0x0804, 0x69d8, 0x2071, 0x1906, 0xa803, 0x0000, 0x2908, 0x7010, - 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, - 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x6a75, 0x002e, + 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, - 0x70be, 0x080c, 0x7f46, 0x0e04, 0x6a5f, 0x2071, 0x1906, 0x701c, - 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, - 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2071, 0x1906, - 0x080c, 0x6ba8, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1906, 0xa803, - 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x7f46, 0x002e, 0x00ee, 0x0005, 0x0006, - 0xa87c, 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, - 0x00ff, 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1906, - 0x7004, 0x0002, 0x6ae0, 0x6ae1, 0x6ba7, 0x6ae1, 0x0db4, 0x6ba7, - 0x0005, 0x2001, 0x1919, 0x2004, 0x0002, 0x6aeb, 0x6aeb, 0x6b40, - 0x6b41, 0x6aeb, 0x6b41, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6bc7, - 0x701c, 0x904d, 0x01e0, 0xa84c, 0x9005, 0x01d8, 0x0e04, 0x6b0f, - 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, - 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x1187, 0x2071, 0x1906, 0x080c, 0x6ba8, 0x012e, - 0x0470, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x6bbc, - 0xd09c, 0x2071, 0x1906, 0x1510, 0x2071, 0x1906, 0x700f, 0x0001, + 0x70be, 0x080c, 0x7f64, 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, + 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, + 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x190e, 0x7004, + 0x0002, 0x6aef, 0x6af0, 0x6bb6, 0x6af0, 0x0db4, 0x6bb6, 0x0005, + 0x2001, 0x1921, 0x2004, 0x0002, 0x6afa, 0x6afa, 0x6b4f, 0x6b50, + 0x6afa, 0x6b50, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6bd6, 0x701c, + 0x904d, 0x01e0, 0xa84c, 0x9005, 0x01d8, 0x0e04, 0x6b1e, 0xa94c, + 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, + 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x1187, 0x2071, 0x190e, 0x080c, 0x6bb7, 0x012e, 0x0470, + 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd09c, + 0x2071, 0x190e, 0x1510, 0x2071, 0x190e, 0x700f, 0x0001, 0xa964, + 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, + 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, + 0x00de, 0x2071, 0x190e, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, + 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, + 0x00d6, 0x2008, 0x2069, 0x19d2, 0x683c, 0x9005, 0x0760, 0x0158, + 0x9186, 0x0003, 0x0540, 0x2001, 0x1814, 0x2004, 0x2009, 0x1a9f, + 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, + 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x6b82, 0x2069, 0x0000, + 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2069, 0x19d2, + 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, + 0x6c37, 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, + 0x0780, 0x15c9, 0xd09c, 0x1500, 0x2071, 0x190e, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, - 0x6822, 0x00de, 0x2071, 0x1906, 0x701c, 0x2048, 0x7010, 0x8001, - 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, - 0x0005, 0x00d6, 0x2008, 0x2069, 0x19ca, 0x683c, 0x9005, 0x0760, - 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, 0x1814, 0x2004, 0x2009, - 0x1a97, 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, - 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x6b73, 0x2069, - 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1187, 0x2069, - 0x19ca, 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, - 0x1e0c, 0x6c28, 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, - 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500, 0x2071, 0x1906, 0x700f, - 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, - 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, - 0x0050, 0x6822, 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, - 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, - 0x0126, 0x2091, 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, - 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, - 0x101d, 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x6bbe, - 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0dbd, 0x0096, - 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, - 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, - 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x1187, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, - 0x0780, 0x1991, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, - 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x182f, - 0x210c, 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, - 0x19f0, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1187, 0x00ee, 0x00fe, 0x009e, 0x0005, - 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, + 0x6822, 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, + 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, + 0x2091, 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, + 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x101d, + 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x6bcd, 0x0006, + 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0dbd, 0x0096, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x1187, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, + 0x1991, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x182f, 0x210c, + 0x918a, 0x0040, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, 0x2048, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x19f0, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x1187, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6bbc, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x7f46, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bbc, 0xd0a4, - 0x1d70, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1919, 0x6808, - 0x690a, 0x2069, 0x19ca, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, - 0x2001, 0x191a, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x7094, 0x908a, 0x0029, 0x1a0c, 0x0db4, 0x9082, 0x001d, - 0x001b, 0x6027, 0x1e00, 0x0005, 0x6d50, 0x6cd6, 0x6cf2, 0x6d1c, - 0x6d3f, 0x6d7f, 0x6d91, 0x6cf2, 0x6d67, 0x6c91, 0x6cbf, 0x6c90, - 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, - 0x9005, 0x1518, 0x7097, 0x0028, 0x2069, 0x195f, 0x2d04, 0x7002, - 0x080c, 0x70d4, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7097, - 0x0028, 0x2069, 0x195f, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a32, 0x080c, - 0x195a, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, - 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, - 0x7097, 0x0028, 0x2069, 0x195f, 0x2d04, 0x7002, 0x080c, 0x716e, - 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, - 0x0090, 0x080c, 0x2b16, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, - 0x6dfe, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7097, - 0x0020, 0x080c, 0x6dfe, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, - 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2b16, 0x6124, 0xd1cc, - 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, - 0x080c, 0x1984, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, - 0x6fc7, 0x2001, 0x0080, 0x080c, 0x2b16, 0x7097, 0x0028, 0x0058, - 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, - 0x0010, 0x7097, 0x001f, 0x0005, 0x080c, 0x1984, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x6fc7, 0x2001, 0x0080, 0x080c, - 0x2b16, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, - 0x9184, 0x1e00, 0x1158, 0x7097, 0x0028, 0x0040, 0x7097, 0x001e, - 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, 0x2001, - 0x00a0, 0x080c, 0x2b16, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, - 0x080c, 0x1984, 0x7097, 0x001e, 0x0010, 0x7097, 0x001d, 0x0005, - 0x080c, 0x6e81, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x6dfe, 0x0016, - 0x080c, 0x1984, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7097, - 0x001e, 0x0020, 0x7097, 0x001f, 0x080c, 0x6dfe, 0x0005, 0x0006, - 0x2001, 0x00a0, 0x080c, 0x2b16, 0x000e, 0x6124, 0xd1d4, 0x1160, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, 0x001e, - 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x0021, 0x0005, 0x080c, - 0x6e81, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, - 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2b16, 0x000e, 0x6124, - 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, - 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, - 0x0010, 0x7097, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, - 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, - 0x8000, 0x080c, 0x6f9b, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, - 0x01b0, 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2a5f, 0x6024, - 0xd0cc, 0x0148, 0x2001, 0x00a0, 0x080c, 0x2b16, 0x080c, 0x727f, - 0x080c, 0x5cda, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x6fb5, 0x0150, 0x080c, 0x6fac, 0x1138, 0x2001, 0x0001, 0x080c, - 0x260e, 0x080c, 0x6f73, 0x00a0, 0x080c, 0x6e7e, 0x0178, 0x2001, - 0x0001, 0x080c, 0x260e, 0x7094, 0x9086, 0x001e, 0x0120, 0x7094, - 0x9086, 0x0022, 0x1118, 0x7097, 0x0025, 0x0010, 0x7097, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x6e0f, 0x080c, 0x80f5, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x6e0f, 0x080c, 0x80ec, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0x93ad, 0x2071, 0x1800, 0x080c, 0x6dac, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x93ad, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x9772, 0x2011, 0x0002, 0x080c, - 0x977c, 0x080c, 0x9663, 0x080c, 0x80a1, 0x0036, 0x901e, 0x080c, - 0x96d9, 0x003e, 0x60e3, 0x0000, 0x080c, 0xd8d5, 0x080c, 0xd8f0, - 0x2009, 0x0004, 0x080c, 0x2a65, 0x080c, 0x2980, 0x2001, 0x1800, - 0x2003, 0x0004, 0x6027, 0x0008, 0x2011, 0x6e0f, 0x080c, 0x80f5, - 0x080c, 0x6fb5, 0x0118, 0x9006, 0x080c, 0x2b16, 0x080c, 0x0b8f, - 0x2001, 0x0001, 0x080c, 0x260e, 0x012e, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, - 0x6e1c, 0x2071, 0x19ca, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, - 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, - 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, - 0x00c0, 0x080c, 0x2b16, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x6e8e, - 0x2091, 0x6000, 0x1f04, 0x6e8e, 0x015e, 0x00d6, 0x2069, 0x1800, - 0x6898, 0x8001, 0x0220, 0x0118, 0x689a, 0x00de, 0x0005, 0x689b, - 0x0014, 0x68e4, 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, - 0x080c, 0x8101, 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x728e, 0x2001, 0x193d, - 0x2003, 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, 0x26d9, - 0x9006, 0x080c, 0x2b16, 0x080c, 0x5b99, 0x6027, 0xffff, 0x602b, - 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x194d, - 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, - 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x6f63, 0x7097, - 0x0022, 0x0040, 0x7097, 0x0021, 0x0028, 0x7097, 0x0023, 0x0010, - 0x7097, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x26d9, 0x0026, 0x080c, 0x9dc8, 0x002e, 0x7000, 0x908e, - 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, - 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, - 0x012e, 0x015e, 0x080c, 0xc22c, 0x0118, 0x9006, 0x080c, 0x2b40, - 0x0804, 0x6f6f, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, - 0x2a5f, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2b16, - 0x1f04, 0x6f0d, 0x080c, 0x6ff2, 0x012e, 0x015e, 0x080c, 0x6fac, - 0x01a8, 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, - 0x6052, 0x080c, 0x6ff2, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, - 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x6ff2, 0x080c, 0xc22c, - 0x0118, 0x9006, 0x080c, 0x2b40, 0x0016, 0x0026, 0x7000, 0x908e, - 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, 0x6e1c, 0x080c, 0x80b3, - 0x002e, 0x001e, 0x080c, 0x7f3d, 0x7034, 0xc085, 0x7036, 0x2001, - 0x194d, 0x2003, 0x0004, 0x080c, 0x6c79, 0x080c, 0x6fac, 0x0138, - 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7284, 0x00ee, - 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x7f54, 0x080c, 0x7f46, - 0x080c, 0x728e, 0x2001, 0x193d, 0x2003, 0x0000, 0x9006, 0x7096, - 0x60e2, 0x6886, 0x080c, 0x26d9, 0x9006, 0x080c, 0x2b16, 0x6043, - 0x0090, 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, - 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x194c, 0x2004, 0x9086, - 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, 0x5393, 0x9084, 0x0030, - 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x5393, 0x9084, - 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x5393, - 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5393, 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, - 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, 0x0180, 0x0020, - 0x080c, 0x26f9, 0x900e, 0x0028, 0x080c, 0x6563, 0x1dc8, 0x2009, - 0x0002, 0x2019, 0x0028, 0x080c, 0x2fa7, 0x9006, 0x0019, 0x001e, - 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, - 0xc225, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, - 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, - 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, - 0x7007, 0x2091, 0x6000, 0x1f04, 0x7007, 0x602f, 0x0100, 0x602f, - 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, - 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, - 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, - 0x0001, 0x2001, 0x0001, 0x080c, 0x26d9, 0x2001, 0x00a0, 0x0006, - 0x080c, 0xc22c, 0x000e, 0x0130, 0x080c, 0x2b34, 0x9006, 0x080c, - 0x2b40, 0x0010, 0x080c, 0x2b16, 0x000e, 0x6052, 0x6050, 0x0006, - 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x29d4, 0x00fe, - 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c, 0xc1c5, - 0x2102, 0x0804, 0x70c6, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, - 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, - 0x080c, 0x2b16, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, 0x1d04, - 0x7074, 0x2091, 0x6000, 0x1f04, 0x7074, 0x2011, 0x0003, 0x080c, - 0x9772, 0x2011, 0x0002, 0x080c, 0x977c, 0x080c, 0x9663, 0x901e, - 0x080c, 0x96d9, 0x2001, 0x00a0, 0x080c, 0x2b16, 0x080c, 0x727f, - 0x080c, 0x5cda, 0x080c, 0xc22c, 0x0110, 0x080c, 0x0d22, 0x9085, - 0x0001, 0x0490, 0x86ff, 0x1110, 0x080c, 0x1984, 0x60e3, 0x0000, - 0x2001, 0x0002, 0x080c, 0x26d9, 0x60e2, 0x2001, 0x0080, 0x080c, - 0x2b16, 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, - 0x2a5f, 0x6024, 0x910c, 0x0138, 0x1d04, 0x70ab, 0x2091, 0x6000, - 0x1f04, 0x70ab, 0x0810, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b0, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xc22c, - 0x0110, 0x080c, 0x0d22, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, - 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, - 0x9086, 0x5540, 0x1128, 0x2069, 0x1a48, 0x2d04, 0x8000, 0x206a, - 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, - 0x1904, 0x7139, 0x2001, 0x0088, 0x080c, 0x2b16, 0x9006, 0x60e2, - 0x6886, 0x080c, 0x26d9, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, - 0x0400, 0x2069, 0x195f, 0x7000, 0x206a, 0x7097, 0x0026, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x711b, 0x2091, 0x6000, 0x1f04, - 0x711b, 0x0804, 0x7166, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, - 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2a5f, 0x6024, 0x910c, 0x0508, - 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x7127, 0x2091, 0x6000, 0x1f04, - 0x7127, 0x2011, 0x0003, 0x080c, 0x9772, 0x2011, 0x0002, 0x080c, - 0x977c, 0x080c, 0x9663, 0x901e, 0x080c, 0x96d9, 0x2001, 0x00a0, - 0x080c, 0x2b16, 0x080c, 0x727f, 0x080c, 0x5cda, 0x9085, 0x0001, - 0x00a8, 0x2001, 0x0080, 0x080c, 0x2b16, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x0002, 0x080c, 0x26d9, 0x60e2, 0x9006, 0x00ee, 0x00de, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, - 0x1800, 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, - 0x9772, 0x2011, 0x0002, 0x080c, 0x977c, 0x080c, 0x9663, 0x901e, - 0x080c, 0x96d9, 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2b16, - 0x080c, 0x727f, 0x080c, 0x5cda, 0x0804, 0x7200, 0x2001, 0x180c, - 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, 0x6e04, 0x2069, - 0x0140, 0x2001, 0x0080, 0x080c, 0x2b16, 0x60e3, 0x0000, 0x2069, - 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, - 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0x195f, 0x7000, - 0x206a, 0x7097, 0x0027, 0x7003, 0x0001, 0x0804, 0x7200, 0x6027, - 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2a5f, 0x6024, 0x910c, 0x01c8, - 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x71bf, 0x0006, 0x0016, 0x00c6, - 0x00d6, 0x00e6, 0x080c, 0x7f85, 0x00ee, 0x00de, 0x00ce, 0x001e, - 0x000e, 0x00e6, 0x2071, 0x19ca, 0x7018, 0x00ee, 0x9005, 0x19f8, - 0x01f8, 0x0026, 0x2011, 0x6e1c, 0x080c, 0x8021, 0x2011, 0x6e0f, - 0x080c, 0x80f5, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, - 0x080c, 0x26d9, 0x60e2, 0x2001, 0x180c, 0x200c, 0xc1b4, 0x2102, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x080c, 0xc225, 0x1904, 0x726d, 0x7130, - 0xd184, 0x1170, 0x080c, 0x3135, 0x0138, 0xc18d, 0x7132, 0x2011, - 0x1854, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x726d, - 0x2011, 0x1854, 0x220c, 0x0438, 0x0016, 0x2019, 0x000e, 0x080c, - 0xd4c7, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, - 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, 0x6247, 0x1170, 0x2120, - 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, 0xd54b, 0x2009, 0x0001, - 0x2011, 0x0100, 0x080c, 0x8218, 0x001e, 0x8108, 0x1f04, 0x7236, - 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, - 0x2019, 0x0004, 0x080c, 0x2fa7, 0x001e, 0x0078, 0x0156, 0x00b6, - 0x20a9, 0x007f, 0x900e, 0x080c, 0x6247, 0x1110, 0x080c, 0x5cf4, - 0x8108, 0x1f04, 0x7263, 0x00be, 0x015e, 0x080c, 0x1984, 0x080c, - 0x9dc8, 0x60e3, 0x0000, 0x080c, 0x5cda, 0x080c, 0x6ecd, 0x00ee, - 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, - 0x194d, 0x2003, 0x0001, 0x0005, 0x2001, 0x194d, 0x2003, 0x0000, - 0x0005, 0x2001, 0x194c, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x194c, - 0x2003, 0x0000, 0x0005, 0x2071, 0x18f0, 0x7003, 0x0000, 0x7007, - 0x0000, 0x080c, 0x1004, 0x090c, 0x0db4, 0xa8ab, 0xdcb0, 0x2900, - 0x704e, 0x080c, 0x1004, 0x090c, 0x0db4, 0xa8ab, 0xdcb0, 0x2900, - 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, - 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, - 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, - 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, - 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, - 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, - 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, - 0x18f0, 0x6807, 0x0001, 0x00de, 0x080c, 0x7880, 0x9006, 0x00ee, - 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, - 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, - 0x1f04, 0x72f5, 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18f0, - 0x7004, 0x0002, 0x7314, 0x7315, 0x734c, 0x73a7, 0x74e8, 0x7312, - 0x7312, 0x7512, 0x080c, 0x0db4, 0x0005, 0x2079, 0x0040, 0x782c, - 0x908c, 0x0780, 0x190c, 0x790c, 0xd0a4, 0x01f0, 0x7824, 0x2048, - 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, - 0x0608, 0x00b8, 0x2001, 0x1800, 0x200c, 0x9186, 0x0003, 0x1160, - 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, 0x0128, 0x9186, - 0x0003, 0x19e8, 0x080c, 0x73a7, 0x782c, 0xd09c, 0x090c, 0x7880, - 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, 0x0c18, 0x080c, - 0x73dd, 0x0c90, 0x00e3, 0x08f0, 0x0005, 0x73dd, 0x73dd, 0x73dd, - 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73ff, 0x73dd, 0x73dd, - 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, - 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, - 0x73dd, 0x73e9, 0x73dd, 0x75e7, 0x73dd, 0x73dd, 0x73dd, 0x73ff, - 0x73dd, 0x73e9, 0x7628, 0x7669, 0x76b0, 0x76c4, 0x73dd, 0x73dd, - 0x73ff, 0x73e9, 0x73dd, 0x73dd, 0x74bc, 0x776f, 0x778a, 0x73dd, - 0x73ff, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x74b2, 0x778a, 0x73dd, - 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, - 0x7413, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, - 0x73dd, 0x73dd, 0x78b0, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, - 0x7427, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x73dd, 0x2079, - 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x78a9, - 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, - 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, - 0x080c, 0x7880, 0x0005, 0x73dd, 0x73e9, 0x75d3, 0x73dd, 0x73e9, - 0x73dd, 0x73e9, 0x73e9, 0x73dd, 0x73e9, 0x75d3, 0x73e9, 0x73e9, - 0x73e9, 0x73e9, 0x73e9, 0x73dd, 0x73e9, 0x75d3, 0x73dd, 0x73dd, - 0x73e9, 0x73dd, 0x73dd, 0x73dd, 0x73e9, 0x00e6, 0x2071, 0x18f0, - 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, - 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, - 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, 0x00ff, 0x9105, 0xa86a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7591, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7591, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x75ac, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x75ac, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x73e5, 0x7007, - 0x0001, 0x2009, 0x1833, 0x210c, 0x81ff, 0x1904, 0x7489, 0xa994, - 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0, 0x0026, 0x2011, - 0x0010, 0x080c, 0x658f, 0x002e, 0x0578, 0x0016, 0xa998, 0x080c, - 0x65d9, 0x001e, 0x1548, 0x0400, 0x080c, 0x6f9b, 0x0140, 0xa897, - 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e, 0x0438, 0x0026, - 0x2011, 0x8008, 0x080c, 0x658f, 0x002e, 0x01b0, 0x0016, 0x0026, - 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000, 0x080c, 0x65d9, - 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, 0x4005, 0xa89b, 0x4009, - 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, 0x9084, 0x00ff, 0xa86a, - 0xa883, 0x0000, 0x080c, 0x5f09, 0x1108, 0x0005, 0x0126, 0x2091, - 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, 0x6891, 0x012e, - 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, 0x7437, 0x9186, 0x0064, - 0x0904, 0x7437, 0x9186, 0x007c, 0x0904, 0x7437, 0x9186, 0x0028, - 0x0904, 0x7437, 0x9186, 0x0038, 0x0904, 0x7437, 0x9186, 0x0078, - 0x0904, 0x7437, 0x9186, 0x005f, 0x0904, 0x7437, 0x9186, 0x0056, - 0x0904, 0x7437, 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, - 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, - 0x7007, 0x0001, 0x0804, 0x77a1, 0x2900, 0x7016, 0x701a, 0x20a9, - 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, 0x2098, 0x7050, - 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, 0x20a0, 0x4003, - 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x73ed, 0xaab4, 0x928a, - 0x0002, 0x1a04, 0x73ed, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, - 0x0118, 0x2001, 0x754f, 0x0018, 0x9280, 0x7545, 0x2005, 0x7056, - 0x7010, 0x9015, 0x0904, 0x7530, 0x080c, 0x1004, 0x1118, 0x7007, - 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, 0xe000, 0xa866, - 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, 0xa860, 0xa072, - 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, - 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, 0x810b, 0xa17e, - 0x080c, 0x10d5, 0xa06c, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, - 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, 0x080c, 0x101d, - 0x7014, 0x2048, 0x0804, 0x73ed, 0x7020, 0x2048, 0x7018, 0xa802, - 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x74e8, - 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, - 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x001e, 0x0904, 0x77a1, 0x0804, 0x7591, 0x7547, 0x754b, 0x0002, - 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, - 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, 0xaebc, 0xa804, - 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, 0xb0d2, 0xb0b4, - 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, 0xb0c6, 0xb0a8, - 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, 0xb0b2, 0xb09c, - 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, 0xb7a6, 0xb090, - 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, 0xb086, 0xb692, - 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, 0xb072, 0xb074, - 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, 0x006e, 0x007e, - 0x0005, 0x2009, 0x1833, 0x210c, 0x81ff, 0x1178, 0x080c, 0x5d56, - 0x1108, 0x0005, 0x080c, 0x6abf, 0x0126, 0x2091, 0x8000, 0x080c, - 0xbe20, 0x080c, 0x6891, 0x012e, 0x0ca0, 0x080c, 0xc225, 0x1d70, - 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1833, 0x210c, 0x81ff, - 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, - 0x0120, 0x080c, 0x5e6b, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, - 0x5de6, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, - 0x080c, 0x6891, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, - 0x2001, 0x0000, 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, 0xa906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, - 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x00b6, - 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, 0x0004, - 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, 0x20a9, - 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, 0x080c, - 0x6247, 0x11b8, 0x0066, 0xae80, 0x080c, 0x6357, 0x006e, 0x0088, - 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, - 0x080c, 0x6247, 0x1110, 0x080c, 0x6457, 0x8108, 0x1f04, 0x7610, - 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, 0x101d, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6567, 0x0580, - 0x2061, 0x1a40, 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, 0x00ff, - 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, - 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, 0x9005, - 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, 0x00ff, - 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, - 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x786a, - 0x012e, 0x0804, 0x7864, 0x012e, 0x0804, 0x785e, 0x012e, 0x0804, - 0x7861, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6567, - 0x05e0, 0x2061, 0x1a40, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, - 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, 0x918c, - 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, - 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0xa988, - 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, - 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, - 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, - 0x0804, 0x786a, 0x012e, 0x0804, 0x7867, 0x012e, 0x0804, 0x7864, - 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0x1a40, 0x6300, - 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, - 0x7878, 0x012e, 0x0804, 0x7867, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, - 0x1a40, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, - 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, 0x2001, 0x1833, 0x2004, - 0x9005, 0x0118, 0x080c, 0x9e72, 0x0068, 0x6017, 0xf400, 0x605b, - 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, 0x615a, 0x2009, 0x0041, - 0x080c, 0x9ebc, 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, - 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x8218, 0x002e, 0xa87c, - 0xd0c4, 0x0148, 0x2061, 0x1a40, 0x6000, 0xd08c, 0x1120, 0x6008, - 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x786a, - 0x00ce, 0x012e, 0x00be, 0x0804, 0x7864, 0xa984, 0x9186, 0x002e, - 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, 0x9186, - 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, 0x08b8, - 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, 0x080c, - 0x6247, 0x1968, 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, - 0x09b8, 0x6007, 0x0024, 0x2001, 0x1956, 0x2004, 0x601a, 0x0804, - 0x76ff, 0xa88c, 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, - 0x1833, 0x2004, 0x9005, 0x0150, 0x080c, 0x9e72, 0x8eff, 0x0118, - 0x2e60, 0x080c, 0x9e72, 0x00ee, 0x0804, 0x76ff, 0x6024, 0xc0dc, - 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, - 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, - 0x080c, 0x83da, 0x080c, 0x896d, 0x00ee, 0x0804, 0x76ff, 0x2061, - 0x1a40, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, 0x7878, 0x0126, - 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, - 0x7878, 0x012e, 0xa883, 0x0016, 0x0804, 0x7871, 0xa883, 0x0007, - 0x0804, 0x7871, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, - 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, 0x73e5, 0x0040, - 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x77a1, - 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, - 0x1800, 0x61cc, 0x81ff, 0x1904, 0x7823, 0x6130, 0xd194, 0x1904, - 0x784d, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x0a04, 0x7817, 0x6064, - 0x9e02, 0x1a04, 0x7817, 0x7120, 0x9186, 0x0006, 0x1904, 0x7809, - 0x7010, 0x905d, 0x0904, 0x7823, 0xb800, 0xd0e4, 0x1904, 0x7847, - 0x2061, 0x1a40, 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, - 0x7024, 0xd0dc, 0x1904, 0x7850, 0xa883, 0x0000, 0xa803, 0x0000, - 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, - 0x7853, 0x080c, 0x538f, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, - 0x2e60, 0x080c, 0x8138, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, - 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, - 0x7853, 0x012e, 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, - 0x0006, 0x00be, 0x0804, 0x7871, 0xd184, 0x0db8, 0xd1c4, 0x1190, - 0x00a0, 0xa974, 0x080c, 0x6247, 0x15d0, 0xb800, 0xd0e4, 0x15b8, - 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, - 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, - 0xa883, 0x0035, 0x0430, 0x080c, 0x5393, 0xd0fc, 0x01e8, 0xa878, - 0x2070, 0x9e82, 0x1cd0, 0x02c0, 0x6064, 0x9e02, 0x12a8, 0x7120, - 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, 0xd0bc, - 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x77ad, - 0x7003, 0x0002, 0x0804, 0x77ad, 0xa883, 0x0028, 0x0010, 0xa883, - 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, - 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, - 0x080c, 0xd106, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, 0x003e, - 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, - 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, 0x9105, - 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x0005, - 0x080c, 0x101d, 0x0005, 0x00d6, 0x080c, 0x812f, 0x00de, 0x0005, - 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, - 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, 0x790c, 0xd09c, 0x11a8, - 0x2071, 0x1800, 0x70bc, 0x90ea, 0x0040, 0x0278, 0x8001, 0x70be, - 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, 0x2071, - 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, 0x00de, - 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, 0x790c, 0x000e, 0x0005, - 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, - 0xaa74, 0x9282, 0x0004, 0x1a04, 0x78fd, 0xa97c, 0x9188, 0x1000, - 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, - 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, 0x9dec, - 0x1118, 0x080c, 0x9e8f, 0x05a8, 0x6212, 0xa874, 0x0002, 0x78db, - 0x78e0, 0x78e3, 0x78e9, 0x2019, 0x0002, 0x080c, 0xd4c7, 0x0060, - 0x080c, 0xd463, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, 0xd47e, - 0x0018, 0xa980, 0x080c, 0xd463, 0x080c, 0x9e42, 0xa887, 0x0000, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x00be, 0x001e, - 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, 0x0c80, - 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, 0x0004, - 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, 0x790e, - 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0dbd, 0x2001, - 0x1833, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, 0x0300, - 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, - 0x210c, 0xd1ec, 0x1120, 0x080c, 0x14a9, 0x00fe, 0x0005, 0x2001, - 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, 0x781c, - 0xd08c, 0x0904, 0x798e, 0x68bc, 0x90aa, 0x0005, 0x0a04, 0x7f3d, - 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1510, 0x9484, 0x7000, 0x0140, - 0x908a, 0x2000, 0x1260, 0x9584, 0x0700, 0x8007, 0x0804, 0x7995, - 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0da8, 0x00b0, 0x9484, - 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, - 0x080c, 0xd8ad, 0x080c, 0x7e82, 0x7817, 0x0140, 0x00a8, 0x9584, - 0x0076, 0x1118, 0x080c, 0x7ee0, 0x19c0, 0xd5a4, 0x0148, 0x0046, - 0x0056, 0x080c, 0x79f0, 0x080c, 0x21cf, 0x005e, 0x004e, 0x0020, - 0x080c, 0xd8ad, 0x7817, 0x0140, 0x080c, 0x6f9b, 0x0168, 0x2001, - 0x0111, 0x2004, 0xd08c, 0x0140, 0x688f, 0x0000, 0x2001, 0x0110, - 0x2003, 0x0008, 0x2003, 0x0000, 0x080c, 0x79d1, 0x2001, 0x19c0, - 0x2004, 0x9005, 0x090c, 0x896d, 0x0005, 0x0002, 0x79a7, 0x7ca4, - 0x799e, 0x799e, 0x799e, 0x799e, 0x799e, 0x799e, 0x7817, 0x0140, - 0x2001, 0x19c0, 0x2004, 0x9005, 0x090c, 0x896d, 0x0005, 0x7000, - 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x688e, - 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, - 0x53f0, 0x0070, 0x080c, 0x7a10, 0x0058, 0x9286, 0x3000, 0x1118, - 0x080c, 0x7bdf, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x7db2, - 0x7817, 0x0140, 0x2001, 0x19c0, 0x2004, 0x9005, 0x090c, 0x896d, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, - 0x2518, 0x080c, 0x48e9, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, - 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, - 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, - 0x080c, 0x48e9, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, - 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, - 0x0120, 0x9096, 0x0023, 0x1904, 0x7bb0, 0x9186, 0x0023, 0x15c0, - 0x080c, 0x7e47, 0x0904, 0x7bb0, 0x6120, 0x9186, 0x0001, 0x0150, - 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, - 0x1904, 0x7bb0, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, - 0x2009, 0x0015, 0x080c, 0x9ebc, 0x0804, 0x7bb0, 0x908e, 0x0214, - 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x9ebc, - 0x0804, 0x7bb0, 0x908e, 0x0100, 0x1904, 0x7bb0, 0x7034, 0x9005, - 0x1904, 0x7bb0, 0x2009, 0x0016, 0x080c, 0x9ebc, 0x0804, 0x7bb0, - 0x9186, 0x0022, 0x1904, 0x7bb0, 0x7030, 0x908e, 0x0300, 0x1580, - 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, - 0x697a, 0x7004, 0x687e, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, - 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26ae, 0x7932, - 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2665, 0x695a, 0x703c, - 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b2, 0x00ee, - 0x7034, 0x9005, 0x1904, 0x7bb0, 0x2009, 0x0017, 0x0804, 0x7b60, - 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x7bb0, 0x080c, - 0x6f9b, 0x0120, 0x2009, 0x001d, 0x0804, 0x7b60, 0x68d8, 0xc0a5, - 0x68da, 0x2009, 0x0030, 0x0804, 0x7b60, 0x908e, 0x0500, 0x1140, - 0x7034, 0x9005, 0x1904, 0x7bb0, 0x2009, 0x0018, 0x0804, 0x7b60, - 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x7b60, 0x908e, - 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x7b60, 0x908e, 0x5200, - 0x1140, 0x7034, 0x9005, 0x1904, 0x7bb0, 0x2009, 0x001b, 0x0804, - 0x7b60, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x7bb0, - 0x2009, 0x001c, 0x0804, 0x7b60, 0x908e, 0x1300, 0x1120, 0x2009, - 0x0034, 0x0804, 0x7b60, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, - 0x1904, 0x7bb0, 0x2009, 0x0024, 0x0804, 0x7b60, 0x908c, 0xff00, - 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, - 0xd09c, 0x0904, 0x7b60, 0x080c, 0xc8d7, 0x1904, 0x7bb0, 0x0804, - 0x7b5e, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, - 0x0804, 0x7b60, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, - 0x7b60, 0x908e, 0x6104, 0x1528, 0x2029, 0x0205, 0x2011, 0x026d, - 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, - 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x48e9, 0x004e, - 0x8108, 0x0f04, 0x7b2c, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, - 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, - 0x0478, 0x908e, 0x6000, 0x1118, 0x2009, 0x003f, 0x0448, 0x908e, - 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, - 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, - 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, - 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, - 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2665, - 0x1904, 0x7bb3, 0x080c, 0x61e7, 0x1904, 0x7bb3, 0xbe12, 0xbd16, - 0x001e, 0x0016, 0x080c, 0x6f9b, 0x01c0, 0x68d8, 0xd08c, 0x1148, - 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, - 0x0040, 0x6878, 0x9606, 0x1148, 0x687c, 0x9506, 0x9084, 0xff00, - 0x1120, 0x9584, 0x00ff, 0xb8b2, 0x0080, 0xb8b0, 0x9005, 0x1168, - 0x9186, 0x0046, 0x1150, 0x6878, 0x9606, 0x1138, 0x687c, 0x9506, - 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0x9dec, 0x01a8, - 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, - 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0x9ebc, - 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48e9, 0x080c, 0x9e8f, - 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, - 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, - 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x8422, 0x08a0, 0x080c, - 0x30ff, 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, - 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x7e47, 0x0904, - 0x7c3c, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, - 0x9005, 0x15d0, 0x2009, 0x0015, 0x080c, 0x9ebc, 0x04a8, 0x908e, - 0x0100, 0x1590, 0x7034, 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, - 0x9ebc, 0x0450, 0x9186, 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, - 0x1518, 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x2665, 0x11b8, 0x080c, 0x61e7, 0x11a0, 0xbe12, - 0xbd16, 0x080c, 0x9dec, 0x0178, 0x2b08, 0x6112, 0x080c, 0xbfa6, - 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x9ebc, 0x080c, - 0x896d, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, - 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, - 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, - 0x007f, 0x0804, 0x7c9e, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, - 0x0804, 0x7c9e, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, - 0x2011, 0x0000, 0x2019, 0x1836, 0x231c, 0xd3ac, 0x0130, 0x9026, - 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, - 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, - 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, - 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, - 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, - 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x7c73, 0x82ff, - 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, - 0x00ee, 0x004e, 0x00be, 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, - 0x9184, 0x000f, 0x0002, 0x7cbb, 0x7cbb, 0x7cbb, 0x7e59, 0x7cbb, - 0x7cc4, 0x7cef, 0x7d7d, 0x7cbb, 0x7cbb, 0x7cbb, 0x7cbb, 0x7cbb, - 0x7cbb, 0x7cbb, 0x7cbb, 0x7817, 0x0140, 0x2001, 0x19c0, 0x2004, - 0x9005, 0x090c, 0x896d, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, - 0x7120, 0x2160, 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, - 0x6864, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, - 0x610a, 0x2009, 0x0046, 0x080c, 0x9ebc, 0x7817, 0x0140, 0x2001, - 0x19c0, 0x2004, 0x9005, 0x090c, 0x896d, 0x00be, 0x0005, 0x00b6, - 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7d53, 0x7110, 0xd1bc, 0x1904, - 0x7d53, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x15b0, 0x81ff, 0x15a0, 0x9080, 0x313a, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x7d53, 0x080c, - 0x61e7, 0x1904, 0x7d53, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, - 0xba04, 0x9294, 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0x9dec, - 0x05e8, 0x2b08, 0x7028, 0x604a, 0x702c, 0x6046, 0x6112, 0x6023, - 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, - 0xcb35, 0x0408, 0x080c, 0x656b, 0x1138, 0xb807, 0x0606, 0x0c30, - 0x190c, 0x7c40, 0x11c0, 0x0898, 0x080c, 0x9dec, 0x2b08, 0x0198, - 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, - 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x8422, 0x080c, 0x896d, 0x7817, 0x0140, 0x2001, 0x19c0, 0x2004, - 0x9005, 0x090c, 0x896d, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48e9, 0x080c, - 0x9e8f, 0x0d48, 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6156, 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x83da, 0x080c, 0x896d, 0x08b0, 0x00b6, 0x7110, 0xd1bc, - 0x01e8, 0x7020, 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, - 0x02a8, 0x6864, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0045, 0x080c, 0x9ebc, 0x7817, 0x0140, - 0x2001, 0x19c0, 0x2004, 0x9005, 0x090c, 0x896d, 0x00be, 0x0005, - 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, - 0x0001, 0x0005, 0x080c, 0x30ff, 0x1168, 0x7010, 0x9084, 0xff00, - 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, - 0x1208, 0x000b, 0x0005, 0x7dc9, 0x7dca, 0x7dc9, 0x7dc9, 0x7e29, - 0x7e38, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, - 0x0904, 0x7e27, 0x700c, 0x7108, 0x080c, 0x2665, 0x1904, 0x7e27, - 0x080c, 0x61e7, 0x1904, 0x7e27, 0xbe12, 0xbd16, 0x7110, 0xd1bc, - 0x01d8, 0x080c, 0x656b, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, - 0x080c, 0x7e47, 0x00ce, 0x05d8, 0x080c, 0x9dec, 0x2b08, 0x05b8, - 0x6112, 0x080c, 0xbfa6, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, - 0x0088, 0x080c, 0x9ebc, 0x0458, 0x080c, 0x656b, 0x0148, 0x9086, - 0x0004, 0x0130, 0x080c, 0x6573, 0x0118, 0x9086, 0x0004, 0x1180, - 0x080c, 0x9dec, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xbfa6, 0x6023, - 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x9ebc, 0x0078, - 0x080c, 0x9dec, 0x2b08, 0x0158, 0x6112, 0x080c, 0xbfa6, 0x6023, - 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x9ebc, 0x00be, - 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x7da8, - 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x9ebc, 0x0005, - 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x7da8, 0x1130, - 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x9ebc, 0x0005, 0x7020, - 0x2060, 0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, - 0x1819, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, - 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, - 0x0007, 0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6864, 0x9c02, 0x1280, - 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, - 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0x9ebc, - 0x7817, 0x0140, 0x2001, 0x19c0, 0x2004, 0x9005, 0x090c, 0x896d, - 0x00be, 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, - 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, - 0x0009, 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, - 0x9086, 0xc000, 0x05d0, 0x080c, 0x9dec, 0x05b8, 0x0066, 0x00c6, - 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2665, - 0x15a0, 0x080c, 0x61e7, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, - 0x00ce, 0x6012, 0x080c, 0xbfa6, 0x080c, 0x0feb, 0x0510, 0x2900, - 0x605a, 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, - 0x20a9, 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, - 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, - 0x0001, 0x080c, 0x8422, 0x080c, 0x896d, 0x00fe, 0x009e, 0x00ce, - 0x0005, 0x080c, 0x9e42, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, - 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, - 0x2000, 0x1904, 0x7f37, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, - 0x2004, 0x9005, 0x1904, 0x7f39, 0x7030, 0x908e, 0x0400, 0x0904, - 0x7f39, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, - 0x0300, 0x11d8, 0x2009, 0x1836, 0x210c, 0xd18c, 0x1590, 0xd1a4, - 0x1580, 0x080c, 0x6529, 0x0558, 0x68ac, 0x9084, 0x00ff, 0x7100, - 0x918c, 0x00ff, 0x9106, 0x1518, 0x687c, 0x69ac, 0x918c, 0xff00, - 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, - 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, - 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, - 0x7e47, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x00f6, 0x2079, 0x0200, - 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, - 0x1800, 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, - 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, - 0xc084, 0x7036, 0x00ee, 0x0005, 0x2071, 0x19ca, 0x7003, 0x0003, - 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x1cd0, - 0x7007, 0x0000, 0x7026, 0x702b, 0x93c3, 0x7032, 0x7037, 0x9431, - 0x703f, 0xffff, 0x7042, 0x7047, 0x522e, 0x704a, 0x705b, 0x80bc, - 0x080c, 0x1004, 0x090c, 0x0db4, 0x2900, 0x703a, 0xa867, 0x0003, - 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19ca, 0x1d04, - 0x8010, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1510, 0x2001, - 0x1875, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, - 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0db4, 0x700f, - 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x8101, - 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, - 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, - 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, - 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, - 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, - 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0x953e, - 0x0010, 0x7034, 0x080f, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, - 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, - 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, - 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, - 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, - 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, - 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, - 0x7004, 0x0002, 0x8038, 0x8039, 0x8055, 0x00e6, 0x2071, 0x19ca, - 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x2071, 0x19ca, 0x701c, 0x9206, 0x1120, - 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x19ca, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, - 0x0005, 0x00b6, 0x7110, 0x080c, 0x6247, 0x1168, 0xb888, 0x8001, - 0x0250, 0xb88a, 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, - 0x896d, 0x001e, 0x012e, 0x8108, 0x9182, 0x0800, 0x0218, 0x900e, - 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x7014, 0x2060, 0x0126, - 0x2091, 0x8000, 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, - 0x080c, 0xbe37, 0x6018, 0x9005, 0x0528, 0x8001, 0x601a, 0x1510, - 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x11c8, 0x080c, - 0xbb2c, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, - 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, - 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, 0x0110, - 0x080c, 0xb828, 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x1819, - 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x19ca, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, - 0x0005, 0x2001, 0x19d3, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, - 0x19ca, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x19d6, - 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19ca, 0x711a, 0x721e, - 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, 0x8000, - 0x7056, 0x2001, 0x19d8, 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, - 0x7068, 0xa09a, 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, 0xa08e, - 0x080c, 0x10d5, 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, - 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, - 0x7f85, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x19ca, 0x7172, - 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, - 0x19ca, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, - 0x0005, 0x2069, 0x1800, 0x69e4, 0xd1e4, 0x1518, 0x0026, 0xd1ec, - 0x0140, 0x6a50, 0x6870, 0x9202, 0x0288, 0x8117, 0x9294, 0x00c0, - 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, 0x0007, 0x0110, - 0x69e6, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, 0x8107, 0x9106, - 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x68e6, 0x080c, 0x0ecb, - 0x002e, 0x0005, 0x00c6, 0x2061, 0x1a40, 0x00ce, 0x0005, 0x9184, - 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a40, 0x2060, 0x0005, - 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, - 0x1a40, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, - 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x81c2, 0xd0b4, - 0x1168, 0xd0bc, 0x1904, 0x819b, 0x2009, 0x0006, 0x080c, 0x81ef, - 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, - 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x81e9, 0x908c, - 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, - 0x1875, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, - 0x0804, 0x9ebc, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, - 0x9ebc, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, - 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, - 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, - 0x918e, 0x0003, 0x1904, 0x81e9, 0x908c, 0x2020, 0x918e, 0x2020, - 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x164a, 0x00fe, 0x007e, - 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x9ebc, 0x0005, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, - 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, - 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, - 0x2009, 0x0041, 0x080c, 0x9ebc, 0x0005, 0x00b9, 0x0ce8, 0x87ff, - 0x1dd8, 0x2009, 0x0043, 0x080c, 0x9ebc, 0x0cb0, 0x6110, 0x00b6, - 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, - 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, - 0x080c, 0xbb2c, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, - 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, - 0x1158, 0x00c6, 0x2061, 0x1a40, 0x6200, 0xd28c, 0x1120, 0x6204, - 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x66cb, 0x6014, 0x904d, - 0x0076, 0x2039, 0x0000, 0x190c, 0x8138, 0x007e, 0x009e, 0x0005, - 0x0156, 0x00c6, 0x2061, 0x1a40, 0x6000, 0x81ff, 0x0110, 0x9205, - 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, - 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, - 0x9006, 0x8004, 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, - 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, - 0x9200, 0x1f04, 0x823a, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, - 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, - 0x9005, 0x0510, 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, - 0x97be, 0x0008, 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, - 0x911a, 0x1220, 0x1f04, 0x8264, 0x0028, 0x911a, 0x2308, 0x8210, - 0x1f04, 0x8264, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, - 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, - 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19b7, 0x012e, 0x00d6, - 0x2069, 0x19b7, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, - 0x0000, 0x2069, 0x0200, 0x080c, 0x9c4a, 0x0401, 0x080c, 0x9c35, - 0x00e9, 0x080c, 0x9c38, 0x00d1, 0x080c, 0x9c3b, 0x00b9, 0x080c, - 0x9c3e, 0x00a1, 0x080c, 0x9c41, 0x0089, 0x080c, 0x9c44, 0x0071, - 0x080c, 0x9c47, 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, - 0x2d04, 0x9085, 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, - 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x6027, - 0x0001, 0x7804, 0x9084, 0x0007, 0x0002, 0x82d7, 0x82fb, 0x833a, - 0x82dd, 0x82fb, 0x82d7, 0x82d5, 0x82d5, 0x080c, 0x0db4, 0x080c, - 0x80a1, 0x080c, 0x896d, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x5b43, 0x080c, 0x8021, 0x7828, 0x9092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x5b83, 0x0c88, 0x62c0, - 0x080c, 0x9c4e, 0x080c, 0x5b43, 0x7807, 0x0003, 0x7827, 0x0000, - 0x782b, 0x0000, 0x0c28, 0x080c, 0x80a1, 0x6220, 0xd2a4, 0x0160, - 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0db4, 0x2009, 0x0013, - 0x080c, 0x9ebc, 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, - 0x0db4, 0x7828, 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, - 0x080c, 0x29cc, 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, - 0x090c, 0x0db4, 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, - 0x896d, 0x0c00, 0x080c, 0x9389, 0x08e8, 0x2011, 0x0130, 0x2214, - 0x080c, 0x9c4e, 0x080c, 0xd8ea, 0x2009, 0x0014, 0x080c, 0x9ebc, - 0x00ce, 0x0880, 0x2001, 0x19d3, 0x2003, 0x0000, 0x62c0, 0x82ff, - 0x1160, 0x782b, 0x0000, 0x7824, 0x9065, 0x090c, 0x0db4, 0x2009, - 0x0013, 0x080c, 0x9f0e, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, - 0x7824, 0x9005, 0x090c, 0x0db4, 0x7828, 0x9092, 0xc350, 0x1648, - 0x8000, 0x782a, 0x00de, 0x00ce, 0x00be, 0x080c, 0x29cc, 0x02f0, - 0x00b6, 0x00c6, 0x00d6, 0x781c, 0x905d, 0x090c, 0x0db4, 0xb800, - 0xc0dc, 0xb802, 0x7924, 0x2160, 0x080c, 0x9e42, 0xb93c, 0x81ff, - 0x090c, 0x0db4, 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, - 0x00de, 0x00ce, 0x00be, 0x080c, 0x896d, 0x0868, 0x080c, 0x9389, - 0x0850, 0x2011, 0x0130, 0x2214, 0x080c, 0x9c4e, 0x080c, 0xd8ea, - 0x7824, 0x9065, 0x2009, 0x0014, 0x080c, 0x9ebc, 0x00de, 0x00ce, - 0x00be, 0x0804, 0x834b, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, - 0x190c, 0x1d4c, 0x6024, 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, - 0x60c4, 0x9205, 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, - 0x080c, 0x9ebc, 0x00ce, 0x0005, 0x2011, 0x19d6, 0x2013, 0x0000, - 0x0cc8, 0x793c, 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, - 0x8108, 0x7946, 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, - 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, - 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, - 0x2160, 0x2009, 0x004a, 0x080c, 0x9ebc, 0x08a0, 0x7848, 0xc085, - 0x784a, 0x0880, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x600f, 0x0000, 0x2c08, 0x2061, 0x19b7, 0x6020, 0x8000, 0x6022, - 0x6010, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, - 0x00ce, 0x001e, 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, - 0x2069, 0x19b7, 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, - 0x9086, 0x0001, 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, 0x896d, - 0x00de, 0x0005, 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, - 0xb85b, 0x0000, 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, - 0x008e, 0x2069, 0x19b7, 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, - 0x681e, 0x08d8, 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x600f, 0x0000, 0x2c08, 0x2061, 0x19b7, 0x6020, 0x8000, 0x6022, - 0x6008, 0x9005, 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, - 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, - 0x600f, 0x0000, 0x2c08, 0x2061, 0x19b7, 0x6034, 0x9005, 0x0130, - 0x9080, 0x0003, 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, - 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, - 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, - 0x902e, 0x2071, 0x19b7, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, - 0x8cff, 0x0904, 0x84ce, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, - 0x84c9, 0x87ff, 0x0120, 0x6054, 0x9106, 0x1904, 0x84c9, 0x703c, - 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0x96d9, 0x7033, - 0x0000, 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, - 0x0001, 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, - 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, - 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, - 0x2678, 0x600f, 0x0000, 0x080c, 0xbb2c, 0x01f0, 0x6014, 0x2048, - 0x6020, 0x9086, 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, - 0x98db, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0076, 0x080c, 0xbe20, 0x080c, 0xd7f4, 0x080c, 0x6891, 0x007e, - 0x003e, 0x001e, 0x080c, 0xbd15, 0x080c, 0x9e72, 0x00ce, 0x0804, - 0x8468, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8468, 0x85ff, 0x0120, - 0x0036, 0x080c, 0x8a4a, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, - 0x003e, 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, - 0x0036, 0x0076, 0x080c, 0xd7f4, 0x080c, 0xd4f6, 0x007e, 0x003e, - 0x001e, 0x0890, 0x6020, 0x9086, 0x000a, 0x0904, 0x84b3, 0x0804, - 0x84ac, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, - 0x0126, 0x2091, 0x8000, 0x2079, 0x19b7, 0x7838, 0x9065, 0x0904, - 0x854e, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, - 0x0036, 0x2019, 0x0001, 0x080c, 0x96d9, 0x7833, 0x0000, 0x901e, - 0x7b3e, 0x7b42, 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xbb2c, 0x0548, - 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, - 0x0002, 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1958, - 0x2004, 0x6042, 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0x98db, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6884, 0x080c, - 0xbd15, 0x080c, 0x9e72, 0x000e, 0x0804, 0x8506, 0x7e3a, 0x7e36, - 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xd4f6, 0x0c50, 0x6020, - 0x9086, 0x000a, 0x09f8, 0x08b8, 0x0016, 0x0026, 0x0086, 0x9046, - 0x0099, 0x080c, 0x864d, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, - 0x0126, 0x2079, 0x19b7, 0x2091, 0x8000, 0x080c, 0x86e4, 0x080c, - 0x8772, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19b7, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8612, - 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x860d, 0x88ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x860d, 0x7024, 0x9c06, 0x1558, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x80a1, 0x080c, 0x93ad, - 0x68c3, 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2b16, 0x9006, 0x080c, 0x2b16, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, - 0x0804, 0x860d, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, - 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, 0x080c, 0xbb2c, - 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xbd32, 0x1118, - 0x080c, 0xa7d1, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, - 0x0016, 0x0036, 0x0086, 0x080c, 0xbe20, 0x080c, 0xd7f4, 0x080c, - 0x6891, 0x008e, 0x003e, 0x001e, 0x080c, 0xbd15, 0x080c, 0x9e72, - 0x080c, 0x97b1, 0x00ce, 0x0804, 0x858d, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x858d, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xd7f4, 0x080c, 0xd4f6, - 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xa7d1, 0x6020, 0x9086, - 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, - 0x85f3, 0x9086, 0x008b, 0x0904, 0x85f3, 0x0840, 0x6020, 0x9086, - 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, - 0x9086, 0x008b, 0x09b0, 0x0804, 0x8606, 0x00b6, 0x00a6, 0x0096, - 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, - 0x905d, 0x0904, 0x86dd, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, - 0x19b7, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a, 0x701c, 0x9b06, - 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0xb858, - 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110, 0x2900, 0xb05a, - 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4, 0xc0dc, 0xb802, - 0x080c, 0x617a, 0x0904, 0x86d9, 0x7624, 0x86ff, 0x0904, 0x86c8, - 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0560, 0x080c, 0x80a1, 0x080c, 0x93ad, 0x68c3, - 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b16, - 0x9006, 0x080c, 0x2b16, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x080c, 0x9e72, 0x00ce, 0x0048, 0x00de, - 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x8680, - 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0xbe20, 0x080c, 0xd7f4, 0x080c, 0x6891, 0x080c, 0x97b1, 0x0804, - 0x8680, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, - 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x8745, 0x600c, 0x0006, - 0x600f, 0x0000, 0x7824, 0x9c06, 0x1570, 0x2069, 0x0100, 0x6820, - 0xd0a4, 0x1508, 0x080c, 0x80a1, 0x080c, 0x93ad, 0x68c3, 0x0000, - 0x080c, 0x98db, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b16, 0x9006, - 0x080c, 0x2b16, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x0040, 0x080c, 0x6521, 0x1520, 0x6003, 0x0009, - 0x630a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xbb2a, 0x01b0, - 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xbd32, 0x1118, 0x080c, - 0xa7d1, 0x0060, 0x080c, 0x6521, 0x1168, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6891, 0x080c, 0xbd15, 0x080c, 0x9e72, - 0x080c, 0x97b1, 0x000e, 0x0804, 0x86eb, 0x7e16, 0x7e12, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1118, 0x080c, 0xd4f6, 0x0c50, 0x080c, 0xa7d1, 0x6020, 0x9086, - 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990, - 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, - 0x0d00, 0x0860, 0x0006, 0x0066, 0x0096, 0x00b6, 0x00c6, 0x00d6, - 0x7818, 0x905d, 0x0904, 0x87f2, 0xb854, 0x0006, 0x9006, 0xb856, - 0xb85a, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, 0x617a, 0x0904, - 0x87ef, 0x7e24, 0x86ff, 0x0904, 0x87e2, 0x9680, 0x0005, 0x2004, - 0x9906, 0x1904, 0x87e2, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x0904, 0x87d9, 0x080c, 0x80a1, 0x080c, 0x93ad, 0x68c3, 0x0000, - 0x080c, 0x98db, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b16, 0x9006, - 0x080c, 0x2b16, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, - 0xb800, 0xd0bc, 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1518, - 0x2009, 0x1958, 0x210c, 0x2102, 0x00f0, 0xb83c, 0x9005, 0x0110, - 0x8001, 0xb83e, 0x2660, 0x600f, 0x0000, 0x080c, 0x9e72, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x8785, 0x89ff, 0x0138, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0x6891, 0x080c, 0x97b1, 0x0804, 0x8785, 0x000e, - 0x0804, 0x8779, 0x781e, 0x781a, 0x00de, 0x00ce, 0x00be, 0x009e, - 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0xb800, - 0xd0dc, 0x01a0, 0xb84c, 0x904d, 0x0188, 0xa878, 0x9606, 0x1170, - 0x2071, 0x19b7, 0x7024, 0x9035, 0x0148, 0x9080, 0x0005, 0x2004, - 0x9906, 0x1120, 0xb800, 0xc0dc, 0xb802, 0x0029, 0x006e, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0x9005, - 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04b8, - 0x080c, 0x93ad, 0x78c3, 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, - 0x0036, 0x2079, 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2b16, 0x9006, 0x080c, 0x2b16, 0x2079, 0x0100, - 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x98db, 0x003e, - 0x080c, 0x617a, 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, - 0x2660, 0x080c, 0x9e42, 0x00ce, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0xbe20, 0x080c, 0x6891, 0x080c, 0x97b1, 0x00fe, - 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x2011, 0x0101, 0x2204, 0xc0c4, - 0x2012, 0x2001, 0x180c, 0x2014, 0xc2e4, 0x2202, 0x2071, 0x19b7, - 0x7004, 0x9084, 0x0007, 0x0002, 0x887e, 0x8882, 0x88a0, 0x88c9, - 0x8907, 0x887e, 0x8899, 0x887c, 0x080c, 0x0db4, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x7024, 0x9065, 0x0148, 0x7020, 0x8001, 0x7022, - 0x600c, 0x9015, 0x0158, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7216, 0x7212, - 0x0ca8, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, 0x9005, 0x0070, - 0x6010, 0x2058, 0x080c, 0x617a, 0xb800, 0xc0dc, 0xb802, 0x7007, - 0x0000, 0x7027, 0x0000, 0x7020, 0x8001, 0x7022, 0x1148, 0x2001, - 0x180c, 0x2014, 0xd2ec, 0x1180, 0x00ce, 0x00ee, 0x00be, 0x0005, - 0xb854, 0x9015, 0x0120, 0x721e, 0x080c, 0x896d, 0x0ca8, 0x7218, - 0x721e, 0x080c, 0x896d, 0x0c80, 0xc2ec, 0x2202, 0x080c, 0x8a4a, - 0x0c58, 0x7024, 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, 0x080c, - 0x97b1, 0x600c, 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, - 0x720e, 0x720a, 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, 0x97b1, - 0x600c, 0x9015, 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, - 0x7212, 0x00b8, 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, 0x2058, - 0x080c, 0x617a, 0xb800, 0xc0dc, 0xb802, 0x080c, 0x97b1, 0x701c, - 0x9065, 0x0138, 0xb854, 0x9015, 0x0110, 0x721e, 0x0010, 0x7218, - 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, - 0x9065, 0x0140, 0x080c, 0x97b1, 0x600c, 0x9015, 0x0158, 0x720e, - 0x600f, 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x720e, 0x720a, 0x0ca8, 0x00d6, 0x2069, 0x19b7, - 0x6830, 0x9084, 0x0003, 0x0002, 0x892a, 0x892c, 0x8950, 0x8928, - 0x080c, 0x0db4, 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, - 0x01b8, 0x683c, 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, - 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x19d6, - 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, - 0x6843, 0x0000, 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, 0x0c50, - 0x00c6, 0x9006, 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, 0x0160, - 0x600c, 0x9015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, - 0x0018, 0x683e, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0x2001, - 0x180c, 0x200c, 0xc1e5, 0x2102, 0x0005, 0x2001, 0x180c, 0x200c, - 0xd1ec, 0x0120, 0xc1ec, 0x2102, 0x080c, 0x8a4a, 0x2001, 0x19c3, - 0x2004, 0x9086, 0x0001, 0x0d58, 0x00d6, 0x2069, 0x19b7, 0x6804, - 0x9084, 0x0007, 0x0002, 0x898d, 0x8a32, 0x8a32, 0x8a32, 0x8a32, - 0x8a34, 0x8a32, 0x898b, 0x080c, 0x0db4, 0x6820, 0x9005, 0x1110, - 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0150, 0x6807, 0x0004, - 0x6826, 0x682b, 0x0000, 0x080c, 0x8aa5, 0x00ce, 0x00de, 0x0005, - 0x6814, 0x9065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, - 0x080c, 0x8aa5, 0x00ce, 0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, - 0x92dd, 0x0000, 0x0904, 0x8a1c, 0xb84c, 0x900d, 0x0118, 0xb888, - 0x9005, 0x01a0, 0xb854, 0x905d, 0x0120, 0x920e, 0x0904, 0x8a1c, - 0x0028, 0x6818, 0x920e, 0x0904, 0x8a1c, 0x2058, 0xb84c, 0x900d, - 0x0d88, 0xb888, 0x9005, 0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, - 0x9302, 0x1e40, 0x080c, 0x9e19, 0x0904, 0x8a1c, 0x8318, 0xbb3e, - 0x6116, 0x2b10, 0x6212, 0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, - 0x605e, 0xa883, 0x0000, 0xa884, 0x009e, 0x908a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, - 0x0096, 0x2148, 0xa964, 0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, - 0x0538, 0x00f6, 0x2c78, 0x2061, 0x0100, 0xbab0, 0x629a, 0x2069, - 0x0200, 0x2071, 0x0240, 0x080c, 0x8fdd, 0x2069, 0x19b7, 0xbb00, - 0xc3dd, 0xbb02, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, - 0x7823, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, - 0x00be, 0x00ce, 0x00de, 0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, - 0x6807, 0x0006, 0x2c18, 0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, - 0x0000, 0x080c, 0x617a, 0x080c, 0x9c6e, 0x00ee, 0x00be, 0x00ce, - 0x00de, 0x0005, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0138, - 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x8aa5, 0x00ce, - 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, 0x2202, 0x00de, - 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19b7, 0x6830, 0x9086, - 0x0000, 0x1548, 0x2001, 0x180c, 0x2014, 0xd2e4, 0x0130, 0xc2e4, - 0x2202, 0x080c, 0x897c, 0x2069, 0x19b7, 0x2001, 0x180c, 0x200c, - 0xd1c4, 0x11e0, 0x6838, 0x907d, 0x01b0, 0x6a04, 0x9296, 0x0000, - 0x1588, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, - 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1aea, 0x1178, - 0x012e, 0x080c, 0x920a, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, - 0x0066, 0x2031, 0x0001, 0x080c, 0x704b, 0x006e, 0x08d8, 0x012e, - 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, 0x0140, 0x6a3a, - 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c20, 0x683a, - 0x6836, 0x0cc0, 0x6a04, 0x9296, 0x0006, 0x1904, 0x8a42, 0x6a30, - 0x9296, 0x0000, 0x0930, 0x0804, 0x8a42, 0x6020, 0x9084, 0x000f, - 0x000b, 0x0005, 0x8ab9, 0x8abe, 0x8f17, 0x8fa6, 0x8abe, 0x8f17, - 0x8fa6, 0x8ab9, 0x8abe, 0x8ab9, 0x8ab9, 0x8ab9, 0x8ab9, 0x8ab9, - 0x8ab9, 0x080c, 0x8861, 0x080c, 0x896d, 0x0005, 0x00b6, 0x0156, - 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, - 0x0db4, 0x6110, 0x2158, 0xb9b0, 0x2c78, 0x2061, 0x0100, 0x619a, - 0x908a, 0x0040, 0x1a04, 0x8b2a, 0x005b, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, - 0x8ca1, 0x8cdc, 0x8d05, 0x8da8, 0x8dc9, 0x8dcf, 0x8ddc, 0x8de4, - 0x8df0, 0x8df6, 0x8e07, 0x8df6, 0x8e5e, 0x8de4, 0x8e6a, 0x8e70, - 0x8df0, 0x8e70, 0x8e7c, 0x8b28, 0x8b28, 0x8b28, 0x8b28, 0x8b28, - 0x8b28, 0x8b28, 0x8b28, 0x8b28, 0x8b28, 0x8b28, 0x9590, 0x95b3, - 0x95c4, 0x95e4, 0x9616, 0x8ddc, 0x8b28, 0x8ddc, 0x8df6, 0x8b28, - 0x8d05, 0x8da8, 0x8b28, 0x99d2, 0x8df6, 0x8b28, 0x99ee, 0x8df6, - 0x8b28, 0x8df0, 0x8c9b, 0x8b4b, 0x8b28, 0x9a0a, 0x9a77, 0x9b4e, - 0x8b28, 0x9b5b, 0x8dd9, 0x9b86, 0x8b28, 0x9620, 0x9bb3, 0x8b28, - 0x080c, 0x0db4, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x8b49, - 0x8b49, 0x8b49, 0x8b72, 0x8c1e, 0x8c29, 0x8b49, 0x8b49, 0x8b49, - 0x8c70, 0x8c7c, 0x8b8d, 0x8b49, 0x8ba8, 0x8bdc, 0x9d35, 0x9d7a, - 0x8df6, 0x080c, 0x0db4, 0x00d6, 0x0096, 0x080c, 0x8e8f, 0x7003, - 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, - 0x700e, 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, - 0x9381, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, - 0x00be, 0x080c, 0x9dc1, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x8e8f, 0x7003, 0x0500, - 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, - 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, - 0x080c, 0x9381, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, - 0x8e8f, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, - 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, - 0x701e, 0x60c3, 0x0010, 0x080c, 0x9381, 0x009e, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x8e8f, 0x20e9, - 0x0000, 0x2001, 0x1973, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x1973, 0x0016, 0x200c, 0x2001, 0x0001, - 0x080c, 0x224f, 0x080c, 0xc839, 0x9006, 0x080c, 0x224f, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0x9381, - 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x080c, 0x8eda, 0x20e9, 0x0000, 0x2001, 0x1973, 0x2003, - 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x1973, 0x0016, 0x200c, 0x080c, 0xc839, - 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, - 0x2048, 0x080c, 0x0f9d, 0x080c, 0x9381, 0x012e, 0x009e, 0x00de, - 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, - 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x8e8f, - 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, - 0x9381, 0x00d6, 0x00e6, 0x080c, 0x8eda, 0x7814, 0x9084, 0xff00, - 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, - 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, - 0x8d68, 0x8e70, 0x1f04, 0x8c3f, 0x2069, 0x1801, 0x20a9, 0x0004, - 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8c48, 0x2069, 0x1983, 0x9086, - 0xdf00, 0x0110, 0x2069, 0x199d, 0x20a9, 0x001a, 0x9e86, 0x0260, - 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, - 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, - 0x8c56, 0x60c3, 0x004c, 0x080c, 0x9381, 0x00ee, 0x00de, 0x0005, - 0x080c, 0x8e8f, 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, - 0x60c3, 0x0008, 0x0804, 0x9381, 0x00d6, 0x0026, 0x0016, 0x080c, - 0x8eda, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, - 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, 0x0800, 0x8e70, 0x2073, - 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0x9381, 0x001e, - 0x002e, 0x00de, 0x0005, 0x2001, 0x1817, 0x2004, 0x609a, 0x0804, - 0x9381, 0x080c, 0x8e8f, 0x7003, 0x5200, 0x2069, 0x1853, 0x6804, - 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x2698, 0x710e, 0x001e, + 0xd084, 0x190c, 0x1187, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, + 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x1187, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6bcb, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x7f64, 0x782c, 0x9094, 0x0780, 0x190c, 0x6bcb, 0xd0a4, 0x1d70, + 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1921, 0x6808, 0x690a, + 0x2069, 0x19d2, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, + 0x1922, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x7094, 0x908a, 0x0029, 0x1a0c, 0x0db4, 0x9082, 0x001d, 0x001b, + 0x6027, 0x1e00, 0x0005, 0x6d5f, 0x6ce5, 0x6d01, 0x6d2b, 0x6d4e, + 0x6d8e, 0x6da0, 0x6d01, 0x6d76, 0x6ca0, 0x6cce, 0x6c9f, 0x0005, + 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, + 0x1518, 0x7097, 0x0028, 0x2069, 0x1967, 0x2d04, 0x7002, 0x080c, + 0x70e1, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7097, 0x0028, + 0x2069, 0x1967, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, + 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a3a, 0x080c, 0x196a, + 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, + 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x7097, + 0x0028, 0x2069, 0x1967, 0x2d04, 0x7002, 0x080c, 0x717b, 0x6028, + 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, + 0x080c, 0x2b21, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x6e0d, + 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7097, 0x0020, + 0x080c, 0x6e0d, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, + 0x0005, 0x2001, 0x0088, 0x080c, 0x2b21, 0x6124, 0xd1cc, 0x11e8, + 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, + 0x198f, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x6fd6, + 0x2001, 0x0080, 0x080c, 0x2b21, 0x7097, 0x0028, 0x0058, 0x7097, + 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, 0x0010, + 0x7097, 0x001f, 0x0005, 0x080c, 0x198f, 0x60e3, 0x0001, 0x600c, + 0xc0b4, 0x600e, 0x080c, 0x6fd6, 0x2001, 0x0080, 0x080c, 0x2b21, + 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, + 0x1e00, 0x1158, 0x7097, 0x0028, 0x0040, 0x7097, 0x001e, 0x0028, + 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, 0x2001, 0x00a0, + 0x080c, 0x2b21, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, + 0x198f, 0x7097, 0x001e, 0x0010, 0x7097, 0x001d, 0x0005, 0x080c, + 0x6e90, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x6e0d, 0x0016, 0x080c, + 0x198f, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7097, 0x001e, + 0x0020, 0x7097, 0x001f, 0x080c, 0x6e0d, 0x0005, 0x0006, 0x2001, + 0x00a0, 0x080c, 0x2b21, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, 0x001e, 0x0028, + 0x7097, 0x001d, 0x0010, 0x7097, 0x0021, 0x0005, 0x080c, 0x6e90, + 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, + 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, + 0x0006, 0x2001, 0x0090, 0x080c, 0x2b21, 0x000e, 0x6124, 0xd1d4, + 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7097, + 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, 0x0010, + 0x7097, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, + 0x080c, 0x6faa, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, + 0xc1b4, 0x2102, 0x6027, 0x0200, 0x080c, 0x2a6a, 0x6024, 0xd0cc, + 0x0148, 0x2001, 0x00a0, 0x080c, 0x2b21, 0x080c, 0x728c, 0x080c, + 0x5ce5, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x6fc4, + 0x0150, 0x080c, 0x6fbb, 0x1138, 0x2001, 0x0001, 0x080c, 0x2619, + 0x080c, 0x6f82, 0x00a0, 0x080c, 0x6e8d, 0x0178, 0x2001, 0x0001, + 0x080c, 0x2619, 0x7094, 0x9086, 0x001e, 0x0120, 0x7094, 0x9086, + 0x0022, 0x1118, 0x7097, 0x0025, 0x0010, 0x7097, 0x0021, 0x012e, + 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x6e1e, + 0x080c, 0x8113, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, + 0x6e1e, 0x080c, 0x810a, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, + 0x0016, 0x080c, 0x93c7, 0x2071, 0x1800, 0x080c, 0x6dbb, 0x001e, + 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x0126, 0x080c, 0x93c7, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x080c, 0x975b, 0x2011, 0x0002, 0x080c, 0x9765, + 0x080c, 0x9673, 0x080c, 0x80bf, 0x0036, 0x901e, 0x080c, 0x96e9, + 0x003e, 0x60e3, 0x0000, 0x080c, 0xd8ee, 0x080c, 0xd909, 0x2009, + 0x0004, 0x080c, 0x2a70, 0x080c, 0x298b, 0x2001, 0x1800, 0x2003, + 0x0004, 0x6027, 0x0008, 0x2011, 0x6e1e, 0x080c, 0x8113, 0x080c, + 0x6fc4, 0x0118, 0x9006, 0x080c, 0x2b21, 0x080c, 0x0b8f, 0x2001, + 0x0001, 0x080c, 0x2619, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x6e2b, + 0x2071, 0x19d2, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, + 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, + 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, + 0x080c, 0x2b21, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x6e9d, 0x2091, + 0x6000, 0x1f04, 0x6e9d, 0x015e, 0x00d6, 0x2069, 0x1800, 0x6898, + 0x8001, 0x0220, 0x0118, 0x689a, 0x00de, 0x0005, 0x689b, 0x0014, + 0x68e4, 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, + 0x811f, 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1800, 0x080c, 0x729b, 0x2001, 0x1945, 0x2003, + 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, 0x26e4, 0x9006, + 0x080c, 0x2b21, 0x080c, 0x5ba4, 0x6027, 0xffff, 0x602b, 0x182f, + 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, + 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x1955, 0x200c, + 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, + 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x6f72, 0x7097, 0x0022, + 0x0040, 0x7097, 0x0021, 0x0028, 0x7097, 0x0023, 0x0010, 0x7097, + 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, + 0x26e4, 0x0026, 0x080c, 0x9db5, 0x002e, 0x7000, 0x908e, 0x0004, + 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, + 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, + 0x015e, 0x080c, 0xc23b, 0x0118, 0x9006, 0x080c, 0x2b4b, 0x0804, + 0x6f7e, 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a6a, + 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2b21, 0x1f04, + 0x6f1c, 0x080c, 0x7001, 0x012e, 0x015e, 0x080c, 0x6fbb, 0x01a8, + 0x6044, 0x9005, 0x0168, 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, + 0x080c, 0x7001, 0x9006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, + 0x6804, 0xd0d4, 0x1110, 0x080c, 0x7001, 0x080c, 0xc23b, 0x0118, + 0x9006, 0x080c, 0x2b4b, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, + 0x0130, 0x2009, 0x00c8, 0x2011, 0x6e2b, 0x080c, 0x80d1, 0x002e, + 0x001e, 0x080c, 0x7f5b, 0x7034, 0xc085, 0x7036, 0x2001, 0x1955, + 0x2003, 0x0004, 0x080c, 0x6c88, 0x080c, 0x6fbb, 0x0138, 0x6804, + 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7291, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x1800, 0x080c, 0x7f72, 0x080c, 0x7f64, 0x080c, + 0x729b, 0x2001, 0x1945, 0x2003, 0x0000, 0x9006, 0x7096, 0x60e2, + 0x6886, 0x080c, 0x26e4, 0x9006, 0x080c, 0x2b21, 0x6043, 0x0090, + 0x6043, 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0x1954, 0x2004, 0x9086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x080c, 0x539e, 0x9084, 0x0030, 0x9086, + 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x539e, 0x9084, 0x0030, + 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x539e, 0x9084, + 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, 0x539e, + 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, + 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, 0x0180, 0x0020, 0x080c, + 0x2704, 0x900e, 0x0028, 0x080c, 0x6572, 0x1dc8, 0x2009, 0x0002, + 0x2019, 0x0028, 0x080c, 0x2fb2, 0x9006, 0x0019, 0x001e, 0x003e, + 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, 0xc234, + 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, + 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, + 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, 0x9084, 0xfbff, + 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, 0x1d04, 0x7016, + 0x2091, 0x6000, 0x1f04, 0x7016, 0x602f, 0x0100, 0x602f, 0x0000, + 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x613a, 0x001e, + 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006, + 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, + 0x2001, 0x0001, 0x080c, 0x26e4, 0x2001, 0x00a0, 0x0006, 0x080c, + 0xc23b, 0x000e, 0x0130, 0x080c, 0x2b3f, 0x9006, 0x080c, 0x2b4b, + 0x0010, 0x080c, 0x2b21, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, + 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x29df, 0x00fe, 0x000e, + 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x6020, + 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c, 0xc1c5, 0x2102, + 0x0804, 0x70d3, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, 0x6028, + 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, 0x0090, 0x080c, + 0x2b21, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, 0x1d04, 0x7083, + 0x2091, 0x6000, 0x1f04, 0x7083, 0x2011, 0x0003, 0x080c, 0x975b, + 0x2011, 0x0002, 0x080c, 0x9765, 0x080c, 0x9673, 0x901e, 0x080c, + 0x96e9, 0x2001, 0x00a0, 0x080c, 0x2b21, 0x080c, 0x728c, 0x080c, + 0x5ce5, 0x080c, 0xc23b, 0x0110, 0x080c, 0x0d22, 0x9085, 0x0001, + 0x0480, 0x080c, 0x198f, 0x60e3, 0x0000, 0x2001, 0x0002, 0x080c, + 0x26e4, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2b21, 0x20a9, 0x0366, + 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2a6a, 0x6024, 0x910c, + 0x0138, 0x1d04, 0x70b8, 0x2091, 0x6000, 0x1f04, 0x70b8, 0x0820, + 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b0, 0x9005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x080c, 0xc23b, 0x0110, 0x080c, 0x0d22, + 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, 0x9086, 0x0003, 0x1168, + 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, 0x9086, 0x5540, 0x1128, + 0x2069, 0x1a50, 0x2d04, 0x8000, 0x206a, 0x2069, 0x0140, 0x6020, + 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x7146, 0x2001, + 0x0088, 0x080c, 0x2b21, 0x9006, 0x60e2, 0x6886, 0x080c, 0x26e4, + 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01c0, + 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, 0x0400, 0x2069, 0x1967, + 0x7000, 0x206a, 0x7097, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, + 0x1d04, 0x7128, 0x2091, 0x6000, 0x1f04, 0x7128, 0x0804, 0x7173, + 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, + 0x080c, 0x2a6a, 0x6024, 0x910c, 0x0508, 0x9084, 0x1a00, 0x11f0, + 0x1d04, 0x7134, 0x2091, 0x6000, 0x1f04, 0x7134, 0x2011, 0x0003, + 0x080c, 0x975b, 0x2011, 0x0002, 0x080c, 0x9765, 0x080c, 0x9673, + 0x901e, 0x080c, 0x96e9, 0x2001, 0x00a0, 0x080c, 0x2b21, 0x080c, + 0x728c, 0x080c, 0x5ce5, 0x9085, 0x0001, 0x00a8, 0x2001, 0x0080, + 0x080c, 0x2b21, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, 0x9005, + 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, 0x080c, + 0x26e4, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, + 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, + 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, + 0x00c0, 0x01c8, 0x2011, 0x0003, 0x080c, 0x975b, 0x2011, 0x0002, + 0x080c, 0x9765, 0x080c, 0x9673, 0x901e, 0x080c, 0x96e9, 0x2069, + 0x0140, 0x2001, 0x00a0, 0x080c, 0x2b21, 0x080c, 0x728c, 0x080c, + 0x5ce5, 0x0804, 0x720d, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, + 0xc1b5, 0x2102, 0x080c, 0x6e13, 0x2069, 0x0140, 0x2001, 0x0080, + 0x080c, 0x2b21, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, + 0x1118, 0x6808, 0x9005, 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, + 0x6027, 0x0200, 0x2069, 0x1967, 0x7000, 0x206a, 0x7097, 0x0027, + 0x7003, 0x0001, 0x0804, 0x720d, 0x6027, 0x1e00, 0x2009, 0x1e00, + 0x080c, 0x2a6a, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, + 0x1d04, 0x71cc, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, + 0x7fa3, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, + 0x19d2, 0x7070, 0x00ee, 0x9005, 0x19f8, 0x00f8, 0x0026, 0x2011, + 0x6e2b, 0x080c, 0x803f, 0x2011, 0x6e1e, 0x080c, 0x8113, 0x002e, + 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, + 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, 0x080c, 0x26e4, 0x60e2, + 0x2001, 0x180c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, + 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, + 0x080c, 0xc234, 0x1904, 0x727a, 0x7130, 0xd184, 0x1170, 0x080c, + 0x3140, 0x0138, 0xc18d, 0x7132, 0x2011, 0x185c, 0x2214, 0xd2ac, + 0x1120, 0x7030, 0xd08c, 0x0904, 0x727a, 0x2011, 0x185c, 0x220c, + 0x0438, 0x0016, 0x2019, 0x000e, 0x080c, 0xd4e0, 0x0156, 0x00b6, + 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, + 0x0188, 0x080c, 0x6256, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, + 0x000e, 0x080c, 0xd564, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, + 0x8236, 0x001e, 0x8108, 0x1f04, 0x7243, 0x00be, 0x015e, 0x001e, + 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, + 0x2fb2, 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, + 0x080c, 0x6256, 0x1110, 0x080c, 0x5cff, 0x8108, 0x1f04, 0x7270, + 0x00be, 0x015e, 0x080c, 0x198f, 0x080c, 0x9db5, 0x60e3, 0x0000, + 0x080c, 0x5ce5, 0x080c, 0x6edc, 0x00ee, 0x00ce, 0x004e, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x1955, 0x2003, 0x0001, + 0x0005, 0x2001, 0x1955, 0x2003, 0x0000, 0x0005, 0x2001, 0x1954, + 0x2003, 0xaaaa, 0x0005, 0x2001, 0x1954, 0x2003, 0x0000, 0x0005, + 0x2071, 0x18f8, 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1004, + 0x090c, 0x0db4, 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1004, + 0x090c, 0x0db4, 0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, + 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, + 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, + 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, + 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, + 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, + 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, + 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, + 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18f8, 0x6807, 0x0001, + 0x00de, 0x080c, 0x788e, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, + 0x20a9, 0x0006, 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, + 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x7302, 0x015e, + 0x0005, 0x2079, 0x0040, 0x2071, 0x18f8, 0x7004, 0x0002, 0x7321, + 0x7322, 0x735a, 0x73b5, 0x74f6, 0x731f, 0x731f, 0x7520, 0x080c, + 0x0db4, 0x0005, 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, + 0x791a, 0xd0a4, 0x01f8, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, + 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, + 0x1800, 0x200c, 0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x734a, + 0x7324, 0x734a, 0x7348, 0x734a, 0x734a, 0x734a, 0x734a, 0x734a, + 0x080c, 0x73b5, 0x782c, 0xd09c, 0x090c, 0x788e, 0x0005, 0x9082, + 0x005a, 0x1218, 0x2100, 0x003b, 0x0c10, 0x080c, 0x73eb, 0x0c90, + 0x00e3, 0x08e8, 0x0005, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x740d, 0x73eb, 0x73eb, 0x73eb, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73f7, + 0x73eb, 0x75f5, 0x73eb, 0x73eb, 0x73eb, 0x740d, 0x73eb, 0x73f7, + 0x7636, 0x7677, 0x76be, 0x76d2, 0x73eb, 0x73eb, 0x740d, 0x73f7, + 0x73eb, 0x73eb, 0x74ca, 0x777d, 0x7798, 0x73eb, 0x740d, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x74c0, 0x7798, 0x73eb, 0x73eb, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x7421, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, + 0x78be, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x7435, 0x73eb, + 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x73eb, 0x2079, 0x0040, 0x7004, + 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x78b7, 0xd0a4, 0x0170, + 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, + 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x788e, + 0x0005, 0x73eb, 0x73f7, 0x75e1, 0x73eb, 0x73f7, 0x73eb, 0x73f7, + 0x73f7, 0x73eb, 0x73f7, 0x75e1, 0x73f7, 0x73f7, 0x73f7, 0x73f7, + 0x73f7, 0x73eb, 0x73f7, 0x75e1, 0x73eb, 0x73eb, 0x73f7, 0x73eb, + 0x73eb, 0x73eb, 0x73f7, 0x00e6, 0x2071, 0x18f8, 0x2009, 0x0400, + 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, + 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, + 0x0001, 0xa868, 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a0, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, + 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x759f, + 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x759f, + 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x75ba, 0x7007, 0x0003, 0x7012, 0x2900, + 0x7016, 0x701a, 0x704b, 0x75ba, 0x0005, 0xa864, 0x8007, 0x9084, + 0x00ff, 0x9086, 0x0001, 0x1904, 0x73f3, 0x7007, 0x0001, 0x2009, + 0x1833, 0x210c, 0x81ff, 0x1904, 0x7497, 0xa994, 0x9186, 0x006f, + 0x0188, 0x9186, 0x0074, 0x15b0, 0x0026, 0x2011, 0x0010, 0x080c, + 0x659e, 0x002e, 0x0578, 0x0016, 0xa998, 0x080c, 0x65e8, 0x001e, + 0x1548, 0x0400, 0x080c, 0x6faa, 0x0140, 0xa897, 0x4005, 0xa89b, + 0x0016, 0x2001, 0x0030, 0x900e, 0x0438, 0x0026, 0x2011, 0x8008, + 0x080c, 0x659e, 0x002e, 0x01b0, 0x0016, 0x0026, 0x0036, 0xa998, + 0xaaa0, 0xab9c, 0x918d, 0x8000, 0x080c, 0x65e8, 0x003e, 0x002e, + 0x001e, 0x1140, 0xa897, 0x4005, 0xa89b, 0x4009, 0x2001, 0x0030, + 0x900e, 0x0050, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, + 0x080c, 0x5f14, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, + 0x0139, 0xa87a, 0xa982, 0x080c, 0x68a0, 0x012e, 0x0ca0, 0xa994, + 0x9186, 0x0071, 0x0904, 0x7445, 0x9186, 0x0064, 0x0904, 0x7445, + 0x9186, 0x007c, 0x0904, 0x7445, 0x9186, 0x0028, 0x0904, 0x7445, + 0x9186, 0x0038, 0x0904, 0x7445, 0x9186, 0x0078, 0x0904, 0x7445, + 0x9186, 0x005f, 0x0904, 0x7445, 0x9186, 0x0056, 0x0904, 0x7445, + 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, 0x0860, + 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, + 0x0804, 0x77af, 0x2900, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, + 0x20e0, 0xa85c, 0x9080, 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, + 0x20e8, 0xa05c, 0x9080, 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, + 0x9082, 0x0401, 0x1a04, 0x73fb, 0xaab4, 0x928a, 0x0002, 0x1a04, + 0x73fb, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, + 0x755d, 0x0018, 0x9280, 0x7553, 0x2005, 0x7056, 0x7010, 0x9015, + 0x0904, 0x753e, 0x080c, 0x1004, 0x1118, 0x7007, 0x0004, 0x0005, + 0x2900, 0x7022, 0x7054, 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, + 0xa95c, 0xe004, 0x9100, 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, + 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, + 0x0004, 0x0108, 0x9108, 0xa17a, 0x810b, 0xa17e, 0x080c, 0x10d5, + 0xa06c, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, + 0x0007, 0x0005, 0x7020, 0x2048, 0x080c, 0x101d, 0x7014, 0x2048, + 0x0804, 0x73fb, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, + 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x74f6, 0x7014, 0x2048, + 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, + 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, + 0x77af, 0x0804, 0x759f, 0x7555, 0x7559, 0x0002, 0x001d, 0x0007, + 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, + 0x0004, 0x0076, 0x0066, 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, + 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, + 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, + 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, + 0xb0a2, 0xb094, 0xb09e, 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, + 0xb096, 0xb088, 0xb08a, 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, + 0xb082, 0xb07c, 0xb07e, 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, + 0xb776, 0xb004, 0x9055, 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, + 0x1833, 0x210c, 0x81ff, 0x1178, 0x080c, 0x5d61, 0x1108, 0x0005, + 0x080c, 0x6ace, 0x0126, 0x2091, 0x8000, 0x080c, 0xbe2f, 0x080c, + 0x68a0, 0x012e, 0x0ca0, 0x080c, 0xc234, 0x1d70, 0x2001, 0x0028, + 0x900e, 0x0c70, 0x2009, 0x1833, 0x210c, 0x81ff, 0x11d8, 0xa888, + 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, + 0x5e76, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, 0x5df1, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x68a0, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, + 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, + 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, + 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, + 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, + 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, + 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, 0x080c, 0x6256, 0x11b8, + 0x0066, 0xae80, 0x080c, 0x6366, 0x006e, 0x0088, 0x0046, 0x2011, + 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6256, + 0x1110, 0x080c, 0x6466, 0x8108, 0x1f04, 0x761e, 0x00ce, 0xa87c, + 0xd084, 0x1120, 0x080c, 0x101d, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a0, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x080c, 0x6576, 0x0580, 0x2061, 0x1a48, + 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, + 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, + 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, + 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, + 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, + 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x7878, 0x012e, 0x0804, + 0x7872, 0x012e, 0x0804, 0x786c, 0x012e, 0x0804, 0x786f, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6576, 0x05e0, 0x2061, + 0x1a48, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, + 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, + 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, + 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, + 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, + 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, + 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x7878, + 0x012e, 0x0804, 0x7875, 0x012e, 0x0804, 0x7872, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x2061, 0x1a48, 0x6300, 0xd38c, 0x1120, + 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x7886, 0x012e, + 0x0804, 0x7875, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, + 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a48, 0x6000, + 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, + 0xa88c, 0x9065, 0x0598, 0x2001, 0x1833, 0x2004, 0x9005, 0x0118, + 0x080c, 0x9e5f, 0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, + 0xd1a4, 0x0110, 0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0x9ea9, + 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, + 0x2011, 0xfdff, 0x080c, 0x8236, 0x002e, 0xa87c, 0xd0c4, 0x0148, + 0x2061, 0x1a48, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, + 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7878, 0x00ce, 0x012e, + 0x00be, 0x0804, 0x7872, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, + 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, + 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, + 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, 0x080c, 0x6256, 0x1968, + 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, + 0x0024, 0x2001, 0x195e, 0x2004, 0x601a, 0x0804, 0x770d, 0xa88c, + 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, 0x1833, 0x2004, + 0x9005, 0x0150, 0x080c, 0x9e5f, 0x8eff, 0x0118, 0x2e60, 0x080c, + 0x9e5f, 0x00ee, 0x0804, 0x770d, 0x6024, 0xc0dc, 0xc0d5, 0x6026, + 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, + 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x83f8, + 0x080c, 0x898b, 0x00ee, 0x0804, 0x770d, 0x2061, 0x1a48, 0x6000, + 0xd084, 0x0190, 0xd08c, 0x1904, 0x7886, 0x0126, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x7886, 0x012e, + 0xa883, 0x0016, 0x0804, 0x787f, 0xa883, 0x0007, 0x0804, 0x787f, + 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, + 0x0001, 0x0069, 0x0005, 0x080c, 0x73f3, 0x0040, 0x7007, 0x0003, + 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x77af, 0x0005, 0x00b6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61cc, + 0x81ff, 0x1904, 0x7831, 0x6130, 0xd194, 0x1904, 0x785b, 0xa878, + 0x2070, 0x9e82, 0x1cd0, 0x0a04, 0x7825, 0x6064, 0x9e02, 0x1a04, + 0x7825, 0x7120, 0x9186, 0x0006, 0x1904, 0x7817, 0x7010, 0x905d, + 0x0904, 0x7831, 0xb800, 0xd0e4, 0x1904, 0x7855, 0x2061, 0x1a48, + 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, + 0x1904, 0x785e, 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, + 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7861, 0x080c, + 0x539a, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, + 0x8156, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, + 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7861, 0x012e, + 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, + 0x0804, 0x787f, 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, + 0x080c, 0x6256, 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, + 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, + 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, + 0x0430, 0x080c, 0x539e, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, + 0x1cd0, 0x02c0, 0x6064, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, + 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, + 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x77bb, 0x7003, 0x0002, + 0x0804, 0x77bb, 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, + 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, + 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xd11f, + 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, + 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, + 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, + 0x2091, 0x8000, 0x080c, 0x68a0, 0x012e, 0x0005, 0x080c, 0x101d, + 0x0005, 0x00d6, 0x080c, 0x814d, 0x00de, 0x0005, 0x00d6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, + 0x908c, 0x0780, 0x190c, 0x791a, 0xd09c, 0x11a8, 0x2071, 0x1800, + 0x70bc, 0x90ea, 0x0040, 0x0278, 0x8001, 0x70be, 0x702c, 0x2048, + 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, + 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, + 0x9084, 0x0780, 0x190c, 0x791a, 0x000e, 0x0005, 0x00d6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, + 0x0004, 0x1a04, 0x790b, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, + 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, + 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, 0x9dd9, 0x1118, 0x080c, + 0x9e7c, 0x05a8, 0x6212, 0xa874, 0x0002, 0x78e9, 0x78ee, 0x78f1, + 0x78f7, 0x2019, 0x0002, 0x080c, 0xd4e0, 0x0060, 0x080c, 0xd47c, + 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, 0xd497, 0x0018, 0xa980, + 0x080c, 0xd47c, 0x080c, 0x9e2f, 0xa887, 0x0000, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a0, 0x012e, 0x00be, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, 0x0c80, 0xa887, 0x0002, + 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, 0x0004, 0x0c38, 0xa887, + 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, 0x791c, 0x0006, 0x0016, + 0x2001, 0x8003, 0x0006, 0x0804, 0x0dbd, 0x2001, 0x1833, 0x2004, + 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, + 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, + 0x1120, 0x080c, 0x14a9, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, + 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, + 0x799c, 0x68bc, 0x90aa, 0x0005, 0x0a04, 0x7f5b, 0x7d44, 0x7c40, + 0x9584, 0x00f6, 0x1510, 0x9484, 0x7000, 0x0140, 0x908a, 0x2000, + 0x1260, 0x9584, 0x0700, 0x8007, 0x0804, 0x79a3, 0x7000, 0x9084, + 0xff00, 0x9086, 0x8100, 0x0da8, 0x00b0, 0x9484, 0x0fff, 0x1130, + 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, 0xd8c6, + 0x080c, 0x7e90, 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, + 0x080c, 0x7eee, 0x19c0, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, + 0x79fe, 0x080c, 0x21da, 0x005e, 0x004e, 0x0020, 0x080c, 0xd8c6, + 0x7817, 0x0140, 0x080c, 0x6faa, 0x0168, 0x2001, 0x0111, 0x2004, + 0xd08c, 0x0140, 0x688f, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, + 0x2003, 0x0000, 0x080c, 0x79df, 0x2001, 0x19c8, 0x2004, 0x9005, + 0x090c, 0x898b, 0x0005, 0x0002, 0x79b5, 0x7cb2, 0x79ac, 0x79ac, + 0x79ac, 0x79ac, 0x79ac, 0x79ac, 0x7817, 0x0140, 0x2001, 0x19c8, + 0x2004, 0x9005, 0x090c, 0x898b, 0x0005, 0x7000, 0x908c, 0xff00, + 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x688e, 0x9286, 0x2000, + 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x53fb, 0x0070, + 0x080c, 0x7a1e, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x7bed, + 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x7dc0, 0x7817, 0x0140, + 0x2001, 0x19c8, 0x2004, 0x9005, 0x090c, 0x898b, 0x0005, 0x2001, + 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, + 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, + 0x48f4, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, 0x0056, 0x00f6, + 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, 0x0036, 0x0046, + 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, 0x2019, 0xffff, + 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, 0x1800, 0x2004, + 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, 0x080c, 0x48f4, + 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, + 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, + 0x0023, 0x1904, 0x7bbe, 0x9186, 0x0023, 0x15c0, 0x080c, 0x7e55, + 0x0904, 0x7bbe, 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, + 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x7bbe, + 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, + 0x080c, 0x9ea9, 0x0804, 0x7bbe, 0x908e, 0x0214, 0x0118, 0x908e, + 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x9ea9, 0x0804, 0x7bbe, + 0x908e, 0x0100, 0x1904, 0x7bbe, 0x7034, 0x9005, 0x1904, 0x7bbe, + 0x2009, 0x0016, 0x080c, 0x9ea9, 0x0804, 0x7bbe, 0x9186, 0x0022, + 0x1904, 0x7bbe, 0x7030, 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, + 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, 0x697a, 0x7004, + 0x687e, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, + 0x00ff, 0x0016, 0x2008, 0x080c, 0x26b9, 0x7932, 0x7936, 0x001e, + 0x000e, 0x00fe, 0x080c, 0x2670, 0x695a, 0x703c, 0x00e6, 0x2071, + 0x0140, 0x7086, 0x2071, 0x1800, 0x70b2, 0x00ee, 0x7034, 0x9005, + 0x1904, 0x7bbe, 0x2009, 0x0017, 0x0804, 0x7b6e, 0x908e, 0x0400, + 0x1190, 0x7034, 0x9005, 0x1904, 0x7bbe, 0x080c, 0x6faa, 0x0120, + 0x2009, 0x001d, 0x0804, 0x7b6e, 0x68d8, 0xc0a5, 0x68da, 0x2009, + 0x0030, 0x0804, 0x7b6e, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, + 0x1904, 0x7bbe, 0x2009, 0x0018, 0x0804, 0x7b6e, 0x908e, 0x2010, + 0x1120, 0x2009, 0x0019, 0x0804, 0x7b6e, 0x908e, 0x2110, 0x1120, + 0x2009, 0x001a, 0x0804, 0x7b6e, 0x908e, 0x5200, 0x1140, 0x7034, + 0x9005, 0x1904, 0x7bbe, 0x2009, 0x001b, 0x0804, 0x7b6e, 0x908e, + 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x7bbe, 0x2009, 0x001c, + 0x0804, 0x7b6e, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, + 0x7b6e, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x7bbe, + 0x2009, 0x0024, 0x0804, 0x7b6e, 0x908c, 0xff00, 0x918e, 0x2400, + 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, + 0x7b6e, 0x080c, 0xc8e6, 0x1904, 0x7bbe, 0x0804, 0x7b6c, 0x908c, + 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x7b6e, + 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x7b6e, 0x908e, + 0x6104, 0x1528, 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, + 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, + 0x8108, 0x0046, 0x2124, 0x080c, 0x48f4, 0x004e, 0x8108, 0x0f04, + 0x7b3a, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, + 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, 0x0478, 0x908e, + 0x6000, 0x1118, 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, + 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, + 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, + 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, + 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, + 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2670, 0x1904, 0x7bc1, + 0x080c, 0x61f6, 0x1904, 0x7bc1, 0xbe12, 0xbd16, 0x001e, 0x0016, + 0x080c, 0x6faa, 0x01c0, 0x68d8, 0xd08c, 0x1148, 0x7000, 0x9084, + 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, 0x6878, + 0x9606, 0x1148, 0x687c, 0x9506, 0x9084, 0xff00, 0x1120, 0x9584, + 0x00ff, 0xb8b2, 0x0080, 0xb8b0, 0x9005, 0x1168, 0x9186, 0x0046, + 0x1150, 0x6878, 0x9606, 0x1138, 0x687c, 0x9506, 0x9084, 0xff00, + 0x1110, 0x001e, 0x0098, 0x080c, 0x9dd9, 0x01a8, 0x2b08, 0x6112, + 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, + 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0x9ea9, 0x00ce, 0x00be, + 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, + 0x2011, 0x8049, 0x080c, 0x48f4, 0x080c, 0x9e7c, 0x0d90, 0x2b08, + 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, + 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, + 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, + 0x6003, 0x0001, 0x080c, 0x8440, 0x08a0, 0x080c, 0x310a, 0x1140, + 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, + 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, + 0x9186, 0x0033, 0x11e8, 0x080c, 0x7e55, 0x0904, 0x7c4a, 0x7124, + 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d0, + 0x2009, 0x0015, 0x080c, 0x9ea9, 0x04a8, 0x908e, 0x0100, 0x1590, + 0x7034, 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0x9ea9, 0x0450, + 0x9186, 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, 0x2009, + 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, + 0x2670, 0x11b8, 0x080c, 0x61f6, 0x11a0, 0xbe12, 0xbd16, 0x080c, + 0x9dd9, 0x0178, 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0004, + 0x7120, 0x610a, 0x001e, 0x080c, 0x9ea9, 0x080c, 0x898b, 0x0010, + 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, + 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, + 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, + 0x7cac, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x7cac, + 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, + 0x2019, 0x1836, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, + 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, + 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, + 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, + 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, + 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, + 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x7c81, 0x82ff, 0x1118, 0x9085, + 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, + 0x00be, 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, + 0x0002, 0x7cc9, 0x7cc9, 0x7cc9, 0x7e67, 0x7cc9, 0x7cd2, 0x7cfd, + 0x7d8b, 0x7cc9, 0x7cc9, 0x7cc9, 0x7cc9, 0x7cc9, 0x7cc9, 0x7cc9, + 0x7cc9, 0x7817, 0x0140, 0x2001, 0x19c8, 0x2004, 0x9005, 0x090c, + 0x898b, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, + 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6864, 0x9c02, + 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, + 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, + 0x0046, 0x080c, 0x9ea9, 0x7817, 0x0140, 0x2001, 0x19c8, 0x2004, + 0x9005, 0x090c, 0x898b, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, + 0x0fff, 0x0904, 0x7d61, 0x7110, 0xd1bc, 0x1904, 0x7d61, 0x7108, + 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b0, + 0x81ff, 0x15a0, 0x9080, 0x3145, 0x200d, 0x918c, 0xff00, 0x810f, + 0x2001, 0x0080, 0x9106, 0x0904, 0x7d61, 0x080c, 0x61f6, 0x1904, + 0x7d61, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, 0x9294, + 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0x9dd9, 0x05e8, 0x2b08, + 0x7028, 0x604a, 0x702c, 0x6046, 0x6112, 0x6023, 0x0006, 0x7120, + 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xcb44, 0x0408, + 0x080c, 0x657a, 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, 0x7c4e, + 0x11c0, 0x0898, 0x080c, 0x9dd9, 0x2b08, 0x0198, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, + 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x8440, 0x080c, + 0x898b, 0x7817, 0x0140, 0x2001, 0x19c8, 0x2004, 0x9005, 0x090c, + 0x898b, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, + 0x0120, 0x2011, 0x8049, 0x080c, 0x48f4, 0x080c, 0x9e7c, 0x0d48, + 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, + 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x83f8, + 0x080c, 0x898b, 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7020, + 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, 0x6864, + 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, + 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, + 0x2009, 0x0045, 0x080c, 0x9ea9, 0x7817, 0x0140, 0x2001, 0x19c8, + 0x2004, 0x9005, 0x090c, 0x898b, 0x00be, 0x0005, 0x6120, 0x9186, + 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, + 0x080c, 0x310a, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, + 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, + 0x0005, 0x7dd7, 0x7dd8, 0x7dd7, 0x7dd7, 0x7e37, 0x7e46, 0x0005, + 0x00b6, 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x7e35, + 0x700c, 0x7108, 0x080c, 0x2670, 0x1904, 0x7e35, 0x080c, 0x61f6, + 0x1904, 0x7e35, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x01d8, 0x080c, + 0x657a, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, 0x7e55, + 0x00ce, 0x05d8, 0x080c, 0x9dd9, 0x2b08, 0x05b8, 0x6112, 0x080c, + 0xbfb5, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, + 0x9ea9, 0x0458, 0x080c, 0x657a, 0x0148, 0x9086, 0x0004, 0x0130, + 0x080c, 0x6582, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, 0x9dd9, + 0x2b08, 0x01d8, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0005, 0x7120, + 0x610a, 0x2009, 0x0088, 0x080c, 0x9ea9, 0x0078, 0x080c, 0x9dd9, + 0x2b08, 0x0158, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0004, 0x7120, + 0x610a, 0x2009, 0x0001, 0x080c, 0x9ea9, 0x00be, 0x0005, 0x7110, + 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x7db6, 0x1130, 0x7124, + 0x610a, 0x2009, 0x0089, 0x080c, 0x9ea9, 0x0005, 0x7110, 0xd1bc, + 0x0158, 0x0059, 0x0148, 0x080c, 0x7db6, 0x1130, 0x7124, 0x610a, + 0x2009, 0x008a, 0x080c, 0x9ea9, 0x0005, 0x7020, 0x2060, 0x9c84, + 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x1819, 0x2004, + 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, + 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007, 0x11b0, + 0x9c82, 0x1cd0, 0x0298, 0x6864, 0x9c02, 0x1280, 0x7008, 0x9084, + 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, + 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0x9ea9, 0x7817, 0x0140, + 0x2001, 0x19c8, 0x2004, 0x9005, 0x090c, 0x898b, 0x00be, 0x0005, + 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, + 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, + 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, + 0x05d0, 0x080c, 0x9dd9, 0x05b8, 0x0066, 0x00c6, 0x0046, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2670, 0x15a0, 0x080c, + 0x61f6, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, + 0x080c, 0xbfb5, 0x080c, 0x0feb, 0x0510, 0x2900, 0x605a, 0x9006, + 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, + 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, + 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, + 0x8440, 0x080c, 0x898b, 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, + 0x9e2f, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, + 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, + 0x7f45, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, + 0x1904, 0x7f47, 0x7030, 0x908e, 0x0400, 0x0904, 0x7f47, 0x908e, + 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, + 0x2009, 0x1836, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, + 0x6538, 0x0588, 0x68ac, 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, + 0x9106, 0x1518, 0x687c, 0x69ac, 0x918c, 0xff00, 0x9105, 0x7104, + 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, + 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, + 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x7e55, 0x0128, + 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, + 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, 0x0300, 0x0118, 0x908e, + 0x5200, 0x1d98, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, 0x9086, + 0x0008, 0x0d68, 0x0c50, 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, + 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, + 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, + 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, + 0x00ee, 0x0005, 0x2071, 0x19d2, 0x7003, 0x0003, 0x700f, 0x0361, + 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, 0x1cd0, 0x7007, 0x0000, + 0x7026, 0x702b, 0x93dd, 0x7032, 0x7037, 0x9445, 0x703f, 0xffff, + 0x7042, 0x7047, 0x5239, 0x704a, 0x705b, 0x80da, 0x080c, 0x1004, + 0x090c, 0x0db4, 0x2900, 0x703a, 0xa867, 0x0003, 0xa86f, 0x0100, + 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19d2, 0x1d04, 0x802e, 0x2091, + 0x6000, 0x700c, 0x8001, 0x700e, 0x1510, 0x2001, 0x187d, 0x2004, + 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, + 0x0001, 0x20d1, 0x0000, 0x080c, 0x0db4, 0x700f, 0x0361, 0x7007, + 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x811f, 0x7040, 0x900d, + 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, + 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, + 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, + 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, + 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, + 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0x954e, 0x0010, 0x7034, + 0x080f, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, + 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, + 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, + 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, + 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, + 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, + 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, + 0x8056, 0x8057, 0x8073, 0x00e6, 0x2071, 0x19d2, 0x7018, 0x9005, + 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, + 0x0006, 0x2071, 0x19d2, 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, + 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19d2, + 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, + 0x7110, 0x080c, 0x6256, 0x1168, 0xb888, 0x8001, 0x0250, 0xb88a, + 0x1140, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0x898b, 0x001e, + 0x012e, 0x8108, 0x9182, 0x0800, 0x0218, 0x900e, 0x7007, 0x0002, + 0x7112, 0x00be, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, + 0x6040, 0x9005, 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xbe46, + 0x6018, 0x9005, 0x0528, 0x8001, 0x601a, 0x1510, 0x6120, 0x9186, + 0x0003, 0x0118, 0x9186, 0x0006, 0x11c8, 0x080c, 0xbb3b, 0x01b0, + 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, + 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0xa87c, 0xd0e4, 0x0110, 0x080c, 0xb827, + 0x012e, 0x9c88, 0x0018, 0x7116, 0x2001, 0x1819, 0x2004, 0x9102, + 0x0220, 0x7017, 0x1cd0, 0x7007, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x19d2, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, + 0x19db, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19d2, 0x7132, + 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x19de, 0x2013, 0x0000, + 0x0005, 0x00e6, 0x2071, 0x19d2, 0x711a, 0x721e, 0x700b, 0x0009, + 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, 0x8000, 0x7056, 0x2001, + 0x19e0, 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, 0x7068, 0xa09a, + 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, 0xa08e, 0x080c, 0x10d5, + 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, 0x00a6, 0x00b6, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x7fa3, 0x015e, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, + 0x000e, 0x0005, 0x00e6, 0x2071, 0x19d2, 0x7172, 0x7276, 0x706f, + 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19d2, 0x7074, + 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x2069, + 0x1800, 0x69e4, 0xd1e4, 0x1518, 0x0026, 0xd1ec, 0x0140, 0x6a50, + 0x6870, 0x9202, 0x0288, 0x8117, 0x9294, 0x00c0, 0x0088, 0x9184, + 0x0007, 0x01a0, 0x8109, 0x9184, 0x0007, 0x0110, 0x69e6, 0x0070, + 0x8107, 0x9084, 0x0007, 0x910d, 0x8107, 0x9106, 0x9094, 0x00c0, + 0x9184, 0xff3f, 0x9205, 0x68e6, 0x080c, 0x0ecb, 0x002e, 0x0005, + 0x00c6, 0x2061, 0x1a48, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, + 0x8003, 0x8003, 0x9080, 0x1a48, 0x2060, 0x0005, 0xa884, 0x908a, + 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a48, 0x6014, + 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, + 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, + 0x00c0, 0x918e, 0x00c0, 0x0904, 0x81e0, 0xd0b4, 0x1168, 0xd0bc, + 0x1904, 0x81b9, 0x2009, 0x0006, 0x080c, 0x820d, 0x0005, 0x900e, + 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, 0x908c, 0x0003, + 0x0120, 0x918e, 0x0003, 0x1904, 0x8207, 0x908c, 0x2020, 0x918e, + 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x187d, 0x2104, + 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0x9ea9, + 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0x9ea9, 0x6110, + 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, + 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, + 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, + 0x1904, 0x8207, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, + 0x00f6, 0x2c78, 0x080c, 0x164a, 0x00fe, 0x007e, 0x87ff, 0x1120, + 0x2009, 0x0042, 0x080c, 0x9ea9, 0x0005, 0x6110, 0x00b6, 0x2158, + 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, + 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, + 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, + 0x080c, 0x9ea9, 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, + 0x0043, 0x080c, 0x9ea9, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, + 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, + 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xbb3b, + 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, + 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, + 0x2061, 0x1a48, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, + 0x6206, 0x00ce, 0x080c, 0x66da, 0x6014, 0x904d, 0x0076, 0x2039, + 0x0000, 0x190c, 0x8156, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, + 0x2061, 0x1a48, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, + 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, + 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, + 0x2019, 0x0100, 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, + 0x0020, 0x80f6, 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, + 0x8258, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, + 0x3e00, 0x81f6, 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, + 0x911a, 0x1600, 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, + 0x1110, 0x818d, 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, + 0x1f04, 0x8282, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x8282, + 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, + 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, + 0x2091, 0x2800, 0x2079, 0x19bf, 0x012e, 0x00d6, 0x2069, 0x19bf, + 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, + 0x0200, 0x080c, 0x9c37, 0x0401, 0x080c, 0x9c22, 0x00e9, 0x080c, + 0x9c25, 0x00d1, 0x080c, 0x9c28, 0x00b9, 0x080c, 0x9c2b, 0x00a1, + 0x080c, 0x9c2e, 0x0089, 0x080c, 0x9c31, 0x0071, 0x080c, 0x9c34, + 0x0059, 0x01de, 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, + 0x8001, 0x206a, 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, + 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, + 0x9084, 0x0007, 0x0002, 0x82f5, 0x8319, 0x8358, 0x82fb, 0x8319, + 0x82f5, 0x82f3, 0x82f3, 0x080c, 0x0db4, 0x080c, 0x80bf, 0x080c, + 0x898b, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, + 0x2011, 0x5b4e, 0x080c, 0x803f, 0x7828, 0x9092, 0x00c8, 0x1228, + 0x8000, 0x782a, 0x080c, 0x5b8e, 0x0c88, 0x62c0, 0x080c, 0x9c3b, + 0x080c, 0x5b4e, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, + 0x0c28, 0x080c, 0x80bf, 0x6220, 0xd2a4, 0x0160, 0x782b, 0x0000, + 0x7824, 0x9065, 0x090c, 0x0db4, 0x2009, 0x0013, 0x080c, 0x9ea9, + 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0db4, 0x7828, + 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, 0x29d7, + 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, 0x0db4, + 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x898b, 0x0c00, + 0x080c, 0x93a3, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, 0x9c3b, + 0x080c, 0xd903, 0x2009, 0x0014, 0x080c, 0x9ea9, 0x00ce, 0x0880, + 0x2001, 0x19db, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0x9065, 0x090c, 0x0db4, 0x2009, 0x0013, 0x080c, + 0x9efb, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, 0x9005, + 0x090c, 0x0db4, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, 0x782a, + 0x00de, 0x00ce, 0x00be, 0x080c, 0x29d7, 0x02f0, 0x00b6, 0x00c6, + 0x00d6, 0x781c, 0x905d, 0x090c, 0x0db4, 0xb800, 0xc0dc, 0xb802, + 0x7924, 0x2160, 0x080c, 0x9e2f, 0xb93c, 0x81ff, 0x090c, 0x0db4, + 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, + 0x00be, 0x080c, 0x898b, 0x0868, 0x080c, 0x93a3, 0x0850, 0x2011, + 0x0130, 0x2214, 0x080c, 0x9c3b, 0x080c, 0xd903, 0x7824, 0x9065, + 0x2009, 0x0014, 0x080c, 0x9ea9, 0x00de, 0x00ce, 0x00be, 0x0804, + 0x8369, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1d57, + 0x6024, 0x6027, 0x0002, 0xd0f4, 0x1580, 0x62c8, 0x60c4, 0x9205, + 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0x9ea9, + 0x00ce, 0x0005, 0x2011, 0x19de, 0x2013, 0x0000, 0x0cc8, 0x793c, + 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x12f0, 0x8108, 0x7946, + 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, + 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x6014, 0x9084, + 0x1984, 0x9085, 0x0016, 0x6016, 0x08d8, 0x793c, 0x2160, 0x2009, + 0x004a, 0x080c, 0x9ea9, 0x08a0, 0x7848, 0xc085, 0x784a, 0x0880, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19bf, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19bf, + 0xb800, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, + 0x1110, 0x2b00, 0x681e, 0x00de, 0x0804, 0x898b, 0x00de, 0x0005, + 0xc0d5, 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, + 0x0086, 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, + 0x19bf, 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19bf, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, + 0x0148, 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x19bf, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, + 0x2102, 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, + 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, + 0x19bf, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, + 0x84ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x84e7, 0x87ff, + 0x0120, 0x6054, 0x9106, 0x1904, 0x84e7, 0x703c, 0x9c06, 0x1178, + 0x0036, 0x2019, 0x0001, 0x080c, 0x96e9, 0x7033, 0x0000, 0x9006, + 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, + 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xbb3b, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, + 0x0003, 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0x98c4, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, + 0xbe2f, 0x080c, 0xd80d, 0x080c, 0x68a0, 0x007e, 0x003e, 0x001e, + 0x080c, 0xbd24, 0x080c, 0x9e5f, 0x00ce, 0x0804, 0x8486, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x8486, 0x85ff, 0x0120, 0x0036, 0x080c, + 0x8a68, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, + 0x080c, 0xd80d, 0x080c, 0xd50f, 0x007e, 0x003e, 0x001e, 0x0890, + 0x6020, 0x9086, 0x000a, 0x0904, 0x84d1, 0x0804, 0x84ca, 0x0006, + 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, + 0x8000, 0x2079, 0x19bf, 0x7838, 0x9065, 0x0904, 0x856c, 0x600c, + 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, + 0x0001, 0x080c, 0x96e9, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, + 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xbb3b, 0x0548, 0x6014, 0x2048, + 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, 0x1188, + 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, + 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1960, 0x2004, 0x6042, + 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0x98c4, 0xa867, 0x0103, + 0xab7a, 0xa877, 0x0000, 0x080c, 0x6893, 0x080c, 0xbd24, 0x080c, + 0x9e5f, 0x000e, 0x0804, 0x8524, 0x7e3a, 0x7e36, 0x012e, 0x00fe, + 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, + 0x0006, 0x1118, 0x080c, 0xd50f, 0x0c50, 0x6020, 0x9086, 0x000a, + 0x09f8, 0x08b8, 0x0016, 0x0026, 0x0086, 0x9046, 0x0099, 0x080c, + 0x866b, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, + 0x19bf, 0x2091, 0x8000, 0x080c, 0x8702, 0x080c, 0x8790, 0x012e, + 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, + 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x8630, 0x6010, 0x2058, + 0xb8a0, 0x9206, 0x1904, 0x862b, 0x88ff, 0x0120, 0x6054, 0x9106, + 0x1904, 0x862b, 0x7024, 0x9c06, 0x1558, 0x2069, 0x0100, 0x6820, + 0xd0a4, 0x1508, 0x080c, 0x80bf, 0x080c, 0x93c7, 0x68c3, 0x0000, + 0x080c, 0x98c4, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, + 0x080c, 0x2b21, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x0804, 0x862b, + 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, 0x7010, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, + 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, + 0x600f, 0x0000, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x01e8, 0x6020, + 0x9086, 0x0003, 0x1580, 0x080c, 0xbd41, 0x1118, 0x080c, 0xa7cd, + 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, + 0x0086, 0x080c, 0xbe2f, 0x080c, 0xd80d, 0x080c, 0x68a0, 0x008e, + 0x003e, 0x001e, 0x080c, 0xbd24, 0x080c, 0x9e5f, 0x080c, 0x979a, + 0x00ce, 0x0804, 0x85ab, 0x2c78, 0x600c, 0x2060, 0x0804, 0x85ab, + 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, + 0x0036, 0x0086, 0x080c, 0xd80d, 0x080c, 0xd50f, 0x008e, 0x003e, + 0x001e, 0x08d0, 0x080c, 0xa7cd, 0x6020, 0x9086, 0x0002, 0x1160, + 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x8611, 0x9086, + 0x008b, 0x0904, 0x8611, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920, + 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, + 0x09b0, 0x0804, 0x8624, 0x00b6, 0x00a6, 0x0096, 0x00c6, 0x0006, + 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, 0x905d, 0x0904, + 0x86fb, 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0x19bf, 0xbe54, + 0x7018, 0x9b06, 0x1108, 0x761a, 0x701c, 0x9b06, 0x1130, 0x86ff, + 0x1118, 0x7018, 0x701e, 0x0008, 0x761e, 0xb858, 0x904d, 0x0108, + 0xae56, 0x96d5, 0x0000, 0x0110, 0x2900, 0xb05a, 0xb857, 0x0000, + 0xb85b, 0x0000, 0xb800, 0xc0d4, 0xc0dc, 0xb802, 0x080c, 0x6189, + 0x0904, 0x86f7, 0x7624, 0x86ff, 0x0904, 0x86e6, 0x9680, 0x0005, + 0x2004, 0x9906, 0x15d8, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, + 0x0560, 0x080c, 0x80bf, 0x080c, 0x93c7, 0x68c3, 0x0000, 0x080c, + 0x98c4, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, + 0x2b21, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x00de, 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, + 0x2660, 0x080c, 0x9e5f, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, + 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x869e, 0x89ff, 0x0158, + 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xbe2f, 0x080c, + 0xd80d, 0x080c, 0x68a0, 0x080c, 0x979a, 0x0804, 0x869e, 0x006e, + 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x009e, 0x00ae, + 0x00be, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, + 0x7814, 0x9065, 0x0904, 0x8763, 0x600c, 0x0006, 0x600f, 0x0000, + 0x7824, 0x9c06, 0x1570, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, + 0x080c, 0x80bf, 0x080c, 0x93c7, 0x68c3, 0x0000, 0x080c, 0x98c4, + 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x0040, 0x080c, 0x6530, 0x1520, 0x6003, 0x0009, 0x630a, 0x2c30, + 0x00f8, 0x6014, 0x2048, 0x080c, 0xbb39, 0x01b0, 0x6020, 0x9086, + 0x0003, 0x1508, 0x080c, 0xbd41, 0x1118, 0x080c, 0xa7cd, 0x0060, + 0x080c, 0x6530, 0x1168, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, + 0x080c, 0x68a0, 0x080c, 0xbd24, 0x080c, 0x9e5f, 0x080c, 0x979a, + 0x000e, 0x0804, 0x8709, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, + 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, + 0xd50f, 0x0c50, 0x080c, 0xa7cd, 0x6020, 0x9086, 0x0002, 0x1150, + 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990, 0x9086, 0x008b, + 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0860, + 0x0006, 0x0066, 0x0096, 0x00b6, 0x00c6, 0x00d6, 0x7818, 0x905d, + 0x0904, 0x8810, 0xb854, 0x0006, 0x9006, 0xb856, 0xb85a, 0xb800, + 0xc0d4, 0xc0dc, 0xb802, 0x080c, 0x6189, 0x0904, 0x880d, 0x7e24, + 0x86ff, 0x0904, 0x8800, 0x9680, 0x0005, 0x2004, 0x9906, 0x1904, + 0x8800, 0x00d6, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x87f7, + 0x080c, 0x80bf, 0x080c, 0x93c7, 0x68c3, 0x0000, 0x080c, 0x98c4, + 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, + 0x00de, 0x00c6, 0x3e08, 0x918e, 0x0002, 0x1168, 0xb800, 0xd0bc, + 0x0150, 0x9680, 0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, 0x1960, + 0x210c, 0x2102, 0x00f0, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, + 0x2660, 0x600f, 0x0000, 0x080c, 0x9e5f, 0x00ce, 0x0048, 0x00de, + 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x87a3, + 0x89ff, 0x0138, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0x68a0, 0x080c, 0x979a, 0x0804, 0x87a3, 0x000e, 0x0804, 0x8797, + 0x781e, 0x781a, 0x00de, 0x00ce, 0x00be, 0x009e, 0x006e, 0x000e, + 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0xb800, 0xd0dc, 0x01a0, + 0xb84c, 0x904d, 0x0188, 0xa878, 0x9606, 0x1170, 0x2071, 0x19bf, + 0x7024, 0x9035, 0x0148, 0x9080, 0x0005, 0x2004, 0x9906, 0x1120, + 0xb800, 0xc0dc, 0xb802, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, + 0x0005, 0x00f6, 0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, + 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0x93c7, + 0x78c3, 0x0000, 0x080c, 0x98c4, 0x7027, 0x0000, 0x0036, 0x2079, + 0x0140, 0x7b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2b21, 0x9006, 0x080c, 0x2b21, 0x2079, 0x0100, 0x7824, 0xd084, + 0x0110, 0x7827, 0x0001, 0x080c, 0x98c4, 0x003e, 0x080c, 0x6189, + 0x00c6, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, + 0x9e2f, 0x00ce, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, + 0xbe2f, 0x080c, 0x68a0, 0x080c, 0x979a, 0x00fe, 0x0005, 0x00b6, + 0x00e6, 0x00c6, 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x2001, + 0x180c, 0x2014, 0xc2e4, 0x2202, 0x2071, 0x19bf, 0x7004, 0x9084, + 0x0007, 0x0002, 0x889c, 0x88a0, 0x88be, 0x88e7, 0x8925, 0x889c, + 0x88b7, 0x889a, 0x080c, 0x0db4, 0x00ce, 0x00ee, 0x00be, 0x0005, + 0x7024, 0x9065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, + 0x0158, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, + 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7216, 0x7212, 0x0ca8, 0x7007, + 0x0000, 0x7027, 0x0000, 0x7020, 0x9005, 0x0070, 0x6010, 0x2058, + 0x080c, 0x6189, 0xb800, 0xc0dc, 0xb802, 0x7007, 0x0000, 0x7027, + 0x0000, 0x7020, 0x8001, 0x7022, 0x1148, 0x2001, 0x180c, 0x2014, + 0xd2ec, 0x1180, 0x00ce, 0x00ee, 0x00be, 0x0005, 0xb854, 0x9015, + 0x0120, 0x721e, 0x080c, 0x898b, 0x0ca8, 0x7218, 0x721e, 0x080c, + 0x898b, 0x0c80, 0xc2ec, 0x2202, 0x080c, 0x8a68, 0x0c58, 0x7024, + 0x9065, 0x05b8, 0x700c, 0x9c06, 0x1160, 0x080c, 0x979a, 0x600c, + 0x9015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, + 0x0430, 0x7014, 0x9c06, 0x1160, 0x080c, 0x979a, 0x600c, 0x9015, + 0x0120, 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, + 0x6020, 0x9086, 0x0003, 0x1198, 0x6010, 0x2058, 0x080c, 0x6189, + 0xb800, 0xc0dc, 0xb802, 0x080c, 0x979a, 0x701c, 0x9065, 0x0138, + 0xb854, 0x9015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, + 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0140, + 0x080c, 0x979a, 0x600c, 0x9015, 0x0158, 0x720e, 0x600f, 0x0000, + 0x080c, 0x98c4, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, + 0x720e, 0x720a, 0x0ca8, 0x00d6, 0x2069, 0x19bf, 0x6830, 0x9084, + 0x0003, 0x0002, 0x8948, 0x894a, 0x896e, 0x8946, 0x080c, 0x0db4, + 0x00de, 0x0005, 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, + 0x9065, 0x0130, 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0x19de, 0x2013, 0x0000, + 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, + 0x6838, 0x9065, 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, + 0x6842, 0x6846, 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, + 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, + 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x200c, + 0xc1e5, 0x2102, 0x0005, 0x2001, 0x180c, 0x200c, 0xd1ec, 0x0120, + 0xc1ec, 0x2102, 0x080c, 0x8a68, 0x2001, 0x19cb, 0x2004, 0x9086, + 0x0001, 0x0d58, 0x00d6, 0x2069, 0x19bf, 0x6804, 0x9084, 0x0007, + 0x0002, 0x89ab, 0x8a50, 0x8a50, 0x8a50, 0x8a50, 0x8a52, 0x8a50, + 0x89a9, 0x080c, 0x0db4, 0x6820, 0x9005, 0x1110, 0x00de, 0x0005, + 0x00c6, 0x680c, 0x9065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, + 0x0000, 0x080c, 0x8abf, 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, + 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x8abf, + 0x00ce, 0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, 0x92dd, 0x0000, + 0x0904, 0x8a3a, 0xb84c, 0x900d, 0x0118, 0xb888, 0x9005, 0x01a0, + 0xb854, 0x905d, 0x0120, 0x920e, 0x0904, 0x8a3a, 0x0028, 0x6818, + 0x920e, 0x0904, 0x8a3a, 0x2058, 0xb84c, 0x900d, 0x0d88, 0xb888, + 0x9005, 0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, 0x9302, 0x1e40, + 0x080c, 0x9e06, 0x0904, 0x8a3a, 0x8318, 0xbb3e, 0x6116, 0x2b10, + 0x6212, 0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, 0x605e, 0xa883, + 0x0000, 0xa884, 0x009e, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, 0x0096, 0x2148, + 0xa964, 0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, + 0x2c78, 0x2061, 0x0100, 0xbab0, 0x629a, 0x2069, 0x0200, 0x2071, + 0x0240, 0x080c, 0x8ff7, 0x2069, 0x19bf, 0xbb00, 0xc3dd, 0xbb02, + 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, + 0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00be, 0x00ce, + 0x00de, 0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, 0x6807, 0x0006, + 0x2c18, 0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, 0x0000, 0x080c, + 0x6189, 0x080c, 0x9c5b, 0x00ee, 0x00be, 0x00ce, 0x00de, 0x0005, + 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x0138, 0x6807, 0x0004, + 0x6826, 0x682b, 0x0000, 0x080c, 0x8abf, 0x00ce, 0x00de, 0x0005, + 0x2001, 0x180c, 0x2014, 0xc2ed, 0x2202, 0x00de, 0x00fe, 0x0005, + 0x00f6, 0x00d6, 0x2069, 0x19bf, 0x6830, 0x9086, 0x0000, 0x1548, + 0x2001, 0x180c, 0x2014, 0xd2e4, 0x0130, 0xc2e4, 0x2202, 0x080c, + 0x899a, 0x2069, 0x19bf, 0x2001, 0x180c, 0x200c, 0xd1c4, 0x11e0, + 0x6838, 0x907d, 0x01b0, 0x6a04, 0x9296, 0x0000, 0x1568, 0x6833, + 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, + 0x2091, 0x2400, 0x002e, 0x080c, 0x1af5, 0x1158, 0x012e, 0x080c, + 0x9224, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x080c, 0x705a, + 0x08f8, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, + 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, + 0x0c40, 0x683a, 0x6836, 0x0cc0, 0x6a04, 0x9296, 0x0006, 0x1904, + 0x8a60, 0x6a30, 0x9296, 0x0000, 0x0950, 0x0804, 0x8a60, 0x6020, + 0x9084, 0x000f, 0x000b, 0x0005, 0x8ad3, 0x8ad8, 0x8f31, 0x8fc0, + 0x8ad8, 0x8f31, 0x8fc0, 0x8ad3, 0x8ad8, 0x8ad3, 0x8ad3, 0x8ad3, + 0x8ad3, 0x8ad3, 0x8ad3, 0x080c, 0x887f, 0x080c, 0x898b, 0x0005, + 0x00b6, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, + 0x0053, 0x1a0c, 0x0db4, 0x6110, 0x2158, 0xb9b0, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, 0x8b44, 0x005b, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, + 0x00be, 0x0005, 0x8cbb, 0x8cf6, 0x8d1f, 0x8dc2, 0x8de3, 0x8de9, + 0x8df6, 0x8dfe, 0x8e0a, 0x8e10, 0x8e21, 0x8e10, 0x8e78, 0x8dfe, + 0x8e84, 0x8e8a, 0x8e0a, 0x8e8a, 0x8e96, 0x8b42, 0x8b42, 0x8b42, + 0x8b42, 0x8b42, 0x8b42, 0x8b42, 0x8b42, 0x8b42, 0x8b42, 0x8b42, + 0x95a0, 0x95c3, 0x95d4, 0x95f4, 0x9626, 0x8df6, 0x8b42, 0x8df6, + 0x8e10, 0x8b42, 0x8d1f, 0x8dc2, 0x8b42, 0x99bb, 0x8e10, 0x8b42, + 0x99d7, 0x8e10, 0x8b42, 0x8e0a, 0x8cb5, 0x8b65, 0x8b42, 0x99f3, + 0x9a60, 0x9b3b, 0x8b42, 0x9b48, 0x8df3, 0x9b73, 0x8b42, 0x9630, + 0x9ba0, 0x8b42, 0x080c, 0x0db4, 0x2100, 0x005b, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, + 0x0005, 0x8b63, 0x8b63, 0x8b63, 0x8b8c, 0x8c38, 0x8c43, 0x8b63, + 0x8b63, 0x8b63, 0x8c8a, 0x8c96, 0x8ba7, 0x8b63, 0x8bc2, 0x8bf6, + 0x9d22, 0x9d67, 0x8e10, 0x080c, 0x0db4, 0x00d6, 0x0096, 0x080c, + 0x8ea9, 0x7003, 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, + 0x2048, 0xa83c, 0x700e, 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, + 0x0018, 0x080c, 0x939b, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, + 0x2058, 0xb8a0, 0x00be, 0x080c, 0x9dae, 0x1118, 0x9084, 0xff80, + 0x0110, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x8ea9, + 0x7003, 0x0500, 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, + 0xa87c, 0x7012, 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, + 0x60c3, 0x0010, 0x080c, 0x939b, 0x009e, 0x00de, 0x0005, 0x00d6, + 0x0096, 0x080c, 0x8ea9, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, + 0x700a, 0xa8d0, 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, + 0x701a, 0xa8e0, 0x701e, 0x60c3, 0x0010, 0x080c, 0x939b, 0x009e, + 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, + 0x8ea9, 0x20e9, 0x0000, 0x2001, 0x197b, 0x2003, 0x0000, 0x7814, + 0x2048, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, + 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x197b, 0x0016, 0x200c, + 0x2001, 0x0001, 0x080c, 0x225a, 0x080c, 0xc848, 0x9006, 0x080c, + 0x225a, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, + 0x080c, 0x939b, 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, + 0x0126, 0x2091, 0x8000, 0x080c, 0x8ef4, 0x20e9, 0x0000, 0x2001, + 0x197b, 0x2003, 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, + 0x0000, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, + 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x197b, 0x0016, 0x200c, + 0x080c, 0xc848, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, + 0x0051, 0x7814, 0x2048, 0x080c, 0x0f9d, 0x080c, 0x939b, 0x012e, + 0x009e, 0x00de, 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, + 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, + 0x080c, 0x8ea9, 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, + 0x0008, 0x0804, 0x939b, 0x00d6, 0x00e6, 0x080c, 0x8ef4, 0x7814, + 0x9084, 0xff00, 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, + 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, + 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8c59, 0x2069, 0x1801, + 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8c62, 0x2069, + 0x198b, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19a5, 0x20a9, 0x001a, + 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, + 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, + 0x8e70, 0x1f04, 0x8c70, 0x60c3, 0x004c, 0x080c, 0x939b, 0x00ee, + 0x00de, 0x0005, 0x080c, 0x8ea9, 0x7003, 0x6300, 0x7007, 0x0028, + 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x939b, 0x00d6, 0x0026, + 0x0016, 0x080c, 0x8ef4, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, + 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, 0x0800, + 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, + 0x939b, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1817, 0x2004, + 0x609a, 0x0804, 0x939b, 0x080c, 0x8ea9, 0x7003, 0x5200, 0x2069, + 0x185b, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26a3, + 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, + 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, + 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, 0x9dae, 0x1120, 0xb8a0, + 0x9082, 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7032, 0x2001, + 0x181f, 0x2004, 0x7036, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, + 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, 0x939b, 0x080c, 0x8ea9, + 0x7003, 0x0500, 0x080c, 0x9dae, 0x1120, 0xb8a0, 0x9082, 0x007f, + 0x0248, 0x2001, 0x181e, 0x2004, 0x700a, 0x2001, 0x181f, 0x2004, + 0x700e, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, - 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, - 0x0254, 0x4003, 0x080c, 0x9dc1, 0x1120, 0xb8a0, 0x9082, 0x007f, - 0x0248, 0x2001, 0x181e, 0x2004, 0x7032, 0x2001, 0x181f, 0x2004, - 0x7036, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x7036, - 0x60c3, 0x001c, 0x0804, 0x9381, 0x080c, 0x8e8f, 0x7003, 0x0500, - 0x080c, 0x9dc1, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, - 0x181e, 0x2004, 0x700a, 0x2001, 0x181f, 0x2004, 0x700e, 0x0030, - 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, - 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, - 0x4003, 0x60c3, 0x0010, 0x0804, 0x9381, 0x080c, 0x8e8f, 0x9006, - 0x080c, 0x6535, 0xb8a0, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, - 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, - 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, - 0x9086, 0x007e, 0x1904, 0x8d70, 0x00d6, 0x2069, 0x193c, 0x2001, - 0x1836, 0x2004, 0xd0a4, 0x0178, 0x6800, 0x700a, 0x6808, 0x9084, - 0x2000, 0x7012, 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, - 0x681c, 0x7026, 0x0080, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, - 0x080c, 0x6f9b, 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, - 0x7012, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, - 0x9c35, 0x2069, 0x1944, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, - 0x080c, 0x5393, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04a0, - 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0168, 0x0016, 0x2009, 0x0002, - 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x26d9, - 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x193c, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x080c, 0x9c35, 0x20a1, 0x024e, 0x20a9, - 0x0008, 0x2099, 0x1944, 0x4003, 0x60c3, 0x0074, 0x0804, 0x9381, - 0x080c, 0x8e8f, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, - 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1853, 0x7904, 0x00fe, - 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, 0x9085, - 0x0002, 0x00d6, 0x0804, 0x8e3f, 0x7026, 0x60c3, 0x0014, 0x0804, - 0x9381, 0x080c, 0x8e8f, 0x7003, 0x5000, 0x0804, 0x8d1f, 0x080c, - 0x8e8f, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, - 0x9381, 0x080c, 0x8ed1, 0x0010, 0x080c, 0x8eda, 0x7003, 0x0200, - 0x60c3, 0x0004, 0x0804, 0x9381, 0x080c, 0x8eda, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x9381, - 0x080c, 0x8eda, 0x7003, 0x0200, 0x0804, 0x8d1f, 0x080c, 0x8eda, - 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, - 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x9381, 0x00d6, - 0x080c, 0x8eda, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, - 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, 0x0190, - 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, - 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, - 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1853, 0x7904, - 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, - 0x2009, 0x1875, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, - 0x2009, 0x1873, 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbabc, 0xd28c, - 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, - 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, - 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x9381, 0x080c, 0x8eda, - 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, - 0x0804, 0x9381, 0x080c, 0x8eda, 0x7003, 0x0200, 0x0804, 0x8ca5, - 0x080c, 0x8eda, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, - 0x60c3, 0x0008, 0x0804, 0x9381, 0x080c, 0x8eda, 0x7003, 0x0100, - 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x9381, 0x0026, 0x00d6, - 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, - 0x9c4a, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x6878, 0x700a, 0x687c, 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, - 0x003e, 0x00de, 0x080c, 0x936f, 0x721a, 0x9f95, 0x0000, 0x7222, - 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, - 0x9c4a, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1800, - 0x6878, 0x700a, 0x687c, 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, - 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, - 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, - 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, - 0x2021, 0x0100, 0x080c, 0x9c4a, 0xb810, 0x9305, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, 0xb814, 0x9005, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6878, 0x700a, - 0x687c, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, - 0x00de, 0x080c, 0x936f, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x936f, 0x721a, 0x7a08, - 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db4, 0x908a, 0x0092, 0x1a0c, - 0x0db4, 0x6110, 0x2158, 0xb9b0, 0x2c78, 0x2061, 0x0100, 0x619a, - 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x0005, 0x8f48, 0x8f57, 0x8f62, 0x8f46, 0x8f46, 0x8f46, 0x8f48, - 0x8f46, 0x8f46, 0x8f46, 0x8f46, 0x8f46, 0x8f46, 0x080c, 0x0db4, - 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x29cc, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0x9381, 0x0431, - 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, - 0x0804, 0x9381, 0x0479, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, - 0x0004, 0x0804, 0x9381, 0x0026, 0x080c, 0x9c4a, 0xb810, 0x9085, - 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, - 0x687c, 0x700e, 0x7013, 0x0009, 0x0804, 0x8eaa, 0x0026, 0x080c, - 0x9c4a, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, 0x7012, - 0x0804, 0x8f0c, 0x0026, 0x080c, 0x9c4a, 0xb810, 0x9085, 0x8500, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, - 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8f0c, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, - 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0db4, 0x908a, 0x0054, 0x1a0c, - 0x0db4, 0x7910, 0x2158, 0xb9b0, 0x2061, 0x0100, 0x619a, 0x9082, - 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, - 0x8fdd, 0x9099, 0x906c, 0x91bb, 0x8fdb, 0x8fdb, 0x8fdb, 0x8fdb, - 0x8fdb, 0x8fdb, 0x8fdb, 0x978e, 0x9796, 0x979e, 0x97a6, 0x8fdb, - 0x9b92, 0x8fdb, 0x9786, 0x080c, 0x0db4, 0x0096, 0x780b, 0xffff, - 0x080c, 0x9048, 0x7914, 0x2148, 0xa978, 0x7956, 0xae64, 0x96b4, - 0x00ff, 0x9686, 0x0008, 0x1148, 0xa8b4, 0x7032, 0xa8b8, 0x7036, - 0xa8bc, 0x703a, 0xa8c0, 0x703e, 0x0008, 0x7132, 0xa97c, 0x9184, - 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0018, 0x9084, 0x0006, 0x8004, 0x2010, 0x785c, 0x9084, - 0x00ff, 0x8007, 0x9205, 0x7042, 0xd1ac, 0x0158, 0x7047, 0x0002, - 0x9686, 0x0008, 0x1118, 0x080c, 0x1789, 0x0010, 0x080c, 0x164a, - 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, 0x7047, 0x0000, - 0x9016, 0x2230, 0x0010, 0xaab0, 0xaeac, 0x726a, 0x766e, 0x20a9, - 0x0008, 0x20e9, 0x0000, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, - 0x2098, 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, 0x0018, 0x4003, - 0x6813, 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, 0x2001, 0x19d3, - 0x2003, 0x07d0, 0x2001, 0x19d2, 0x2003, 0x0009, 0x009e, 0x0005, - 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8bc, 0xd084, 0x0128, 0x7a46, - 0x7b14, 0x7b4a, 0x722e, 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, - 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, - 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, 0x0829, 0x2f10, - 0x7222, 0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, 0x0081, 0x7814, - 0x2048, 0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, 0x700a, 0xa8ac, - 0x700e, 0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, 0x9381, 0x6813, - 0x0008, 0xb810, 0x9085, 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, 0x0889, 0x080c, - 0x936f, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x9199, 0x7814, 0x2048, 0x080c, - 0xbb2a, 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, - 0x9006, 0x001b, 0x009e, 0x00de, 0x0005, 0x90b7, 0x9120, 0x9130, - 0x9156, 0x9162, 0x9173, 0x917b, 0x90b5, 0x080c, 0x0db4, 0x0016, - 0x0036, 0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, - 0xaba8, 0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, - 0x701e, 0x003e, 0x001e, 0x2001, 0x1981, 0x2004, 0x60c2, 0x0804, - 0x9381, 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, 0x0db4, 0xaba8, - 0x7824, 0xd0cc, 0x1904, 0x911d, 0x7316, 0xa898, 0x701a, 0xa894, - 0x701e, 0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, 0x0018, 0x9384, - 0x0300, 0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, 0xd3cc, 0x0110, - 0xa8a4, 0x9108, 0x6810, 0x9085, 0x0010, 0x6812, 0x2011, 0x0258, - 0x20e9, 0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x002c, 0x2098, 0x4003, 0x6810, 0x8000, 0x6812, - 0x2011, 0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, 0x6810, 0xc084, - 0x6812, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, - 0x61c2, 0x003e, 0x001e, 0x0804, 0x9381, 0xc3e5, 0x0804, 0x90dc, - 0x2011, 0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, 0x0110, 0x2011, - 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, - 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, - 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, - 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, - 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, - 0x700b, 0x2500, 0x60c3, 0x0032, 0x0804, 0x9381, 0x2011, 0x0028, - 0x7824, 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, 0x9381, - 0x0cd0, 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, - 0x7216, 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, - 0x0020, 0x0804, 0x9381, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, - 0xc2e5, 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, - 0x9384, 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, - 0x7216, 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, - 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, - 0x0818, 0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, 0x0700, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, - 0x7824, 0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, 0x936f, 0x721a, - 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, - 0x7013, 0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, - 0x0013, 0x001e, 0x0005, 0x91cb, 0x91cb, 0x91cd, 0x91cb, 0x91cb, - 0x91cb, 0x91e7, 0x91cb, 0x080c, 0x0db4, 0x7914, 0x918c, 0x08ff, - 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, 0x2069, 0x1853, - 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, - 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, 0x9381, 0x2009, - 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0x9c4a, - 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, 0x0888, 0x918d, - 0x0008, 0x7116, 0x080c, 0x936f, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, - 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, - 0xb8a0, 0x2028, 0xb910, 0xba14, 0x7378, 0x747c, 0x7820, 0x90be, - 0x0006, 0x0904, 0x92de, 0x90be, 0x000a, 0x1904, 0x929a, 0xb8b0, - 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, 0xaf90, 0x9784, - 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, - 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, 0xaf94, 0x87ff, - 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, - 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, - 0x0000, 0xb8b0, 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, - 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, 0xa87c, 0xd0fc, - 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, - 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0xa838, 0x608a, - 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x9c2f, 0x2009, 0x07d0, - 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x80a6, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, - 0x00be, 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, 0x931a, 0x9185, - 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0809, 0x6077, - 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x7814, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, - 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, 0xbab0, 0x629e, - 0x080c, 0x9c2f, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, - 0x0110, 0x2009, 0x1b58, 0x080c, 0x80a6, 0x003e, 0x004e, 0x005e, - 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7814, 0x2048, - 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, 0x9336, 0x9185, - 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0880, 0x6077, - 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, - 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, 0xa890, 0x608a, - 0xa88c, 0x608e, 0xa8b0, 0x60c6, 0xa8ac, 0x60ca, 0xa8ac, 0x7930, - 0x9108, 0x7932, 0xa8b0, 0x792c, 0x9109, 0x792e, 0xb86c, 0x60ce, - 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbab0, 0x629e, 0x080c, 0x9c0c, - 0x0804, 0x92ca, 0xb8bc, 0xd084, 0x0148, 0xb88c, 0x7814, 0x2048, - 0xb88c, 0x7846, 0xa836, 0x2900, 0xa83a, 0xb04a, 0x9185, 0x0600, - 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0829, 0x6077, 0x0000, - 0x60af, 0x9575, 0x60d7, 0x0000, 0x0804, 0x92ad, 0x9185, 0x0700, - 0x6062, 0x6266, 0x636a, 0x646e, 0x7824, 0xd0cc, 0x7826, 0x0118, - 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0xb88c, + 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0x939b, 0x080c, + 0x8ea9, 0x9006, 0x080c, 0x6544, 0xb8a0, 0x9086, 0x007e, 0x1130, + 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, + 0x904d, 0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, + 0x0300, 0xb8a0, 0x9086, 0x007e, 0x1904, 0x8d8a, 0x00d6, 0x2069, + 0x1944, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0178, 0x6800, 0x700a, + 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, 0x701f, 0x2710, + 0x6818, 0x7022, 0x681c, 0x7026, 0x0080, 0x6800, 0x700a, 0x6804, + 0x700e, 0x6808, 0x080c, 0x6faa, 0x1118, 0x9084, 0x37ff, 0x0010, + 0x9084, 0x3fff, 0x7012, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, + 0x00d6, 0x080c, 0x9c22, 0x2069, 0x194c, 0x2071, 0x024e, 0x6800, + 0xc0dd, 0x7002, 0x080c, 0x539e, 0xd0e4, 0x0110, 0x680c, 0x700e, + 0x00de, 0x04a0, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0168, 0x0016, + 0x2009, 0x0002, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, + 0x080c, 0x26e4, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x1944, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, + 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0x9c22, 0x20a1, + 0x024e, 0x20a9, 0x0008, 0x2099, 0x194c, 0x4003, 0x60c3, 0x0074, + 0x0804, 0x939b, 0x080c, 0x8ea9, 0x7003, 0x2010, 0x7007, 0x0014, + 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x185b, + 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, + 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x8e59, 0x7026, 0x60c3, + 0x0014, 0x0804, 0x939b, 0x080c, 0x8ea9, 0x7003, 0x5000, 0x0804, + 0x8d39, 0x080c, 0x8ea9, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, + 0x0014, 0x0804, 0x939b, 0x080c, 0x8eeb, 0x0010, 0x080c, 0x8ef4, + 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0x939b, 0x080c, 0x8ef4, + 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, + 0x0804, 0x939b, 0x080c, 0x8ef4, 0x7003, 0x0200, 0x0804, 0x8d39, + 0x080c, 0x8ef4, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, + 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x939b, 0x00d6, 0x080c, 0x8ef4, 0x7003, 0x0210, 0x7007, 0x0014, + 0x700b, 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, + 0x0030, 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, + 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, + 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, + 0x185b, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, + 0x9085, 0x0010, 0x2009, 0x187d, 0x210c, 0xd184, 0x1110, 0x9085, + 0x0002, 0x0026, 0x2009, 0x187b, 0x210c, 0xd1e4, 0x0150, 0xc0c5, + 0xbabc, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, + 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, + 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x939b, + 0x080c, 0x8ef4, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, + 0x60c3, 0x0014, 0x0804, 0x939b, 0x080c, 0x8ef4, 0x7003, 0x0200, + 0x0804, 0x8cbf, 0x080c, 0x8ef4, 0x7003, 0x0100, 0x700b, 0x0003, + 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x939b, 0x080c, 0x8ef4, + 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x939b, + 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, + 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, + 0x0100, 0x080c, 0x9c37, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, + 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x9485, 0x0029, + 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x9389, 0x721a, 0x9f95, + 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, + 0x0026, 0x080c, 0x9c37, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, + 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x00de, 0x7013, + 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, + 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, + 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x9c37, 0xb810, 0x9305, + 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, + 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, + 0x6878, 0x700a, 0x687c, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, + 0x004e, 0x003e, 0x00de, 0x080c, 0x9389, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x9389, + 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, + 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, + 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db4, 0x908a, + 0x0092, 0x1a0c, 0x0db4, 0x6110, 0x2158, 0xb9b0, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x00be, 0x0005, 0x8f62, 0x8f71, 0x8f7c, 0x8f60, 0x8f60, + 0x8f60, 0x8f62, 0x8f60, 0x8f60, 0x8f60, 0x8f60, 0x8f60, 0x8f60, + 0x080c, 0x0db4, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x29d7, + 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, + 0x939b, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, + 0x60c3, 0x000c, 0x0804, 0x939b, 0x0479, 0x7003, 0x0003, 0x7007, + 0x0300, 0x60c3, 0x0004, 0x0804, 0x939b, 0x0026, 0x080c, 0x9c37, + 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, + 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, 0x0009, 0x0804, 0x8ec4, + 0x0026, 0x080c, 0x9c37, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, + 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x2001, + 0x0099, 0x7012, 0x0804, 0x8f26, 0x0026, 0x080c, 0x9c37, 0xb810, + 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, + 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8f26, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, + 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0db4, 0x908a, + 0x0054, 0x1a0c, 0x0db4, 0x7910, 0x2158, 0xb9b0, 0x2061, 0x0100, + 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x0005, 0x8ff7, 0x90b3, 0x9086, 0x91d5, 0x8ff5, 0x8ff5, + 0x8ff5, 0x8ff5, 0x8ff5, 0x8ff5, 0x8ff5, 0x9777, 0x977f, 0x9787, + 0x978f, 0x8ff5, 0x9b7f, 0x8ff5, 0x976f, 0x080c, 0x0db4, 0x0096, + 0x780b, 0xffff, 0x080c, 0x9062, 0x7914, 0x2148, 0xa978, 0x7956, + 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, 0x1148, 0xa8b4, 0x7032, + 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, 0x703e, 0x0008, 0x7132, + 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, + 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006, 0x8004, 0x2010, + 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042, 0xd1ac, 0x0158, + 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, 0x080c, 0x1789, 0x0010, + 0x080c, 0x164a, 0x0050, 0xd1b4, 0x0118, 0x7047, 0x0001, 0x0028, + 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0xaab0, 0xaeac, 0x726a, + 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0xa860, 0x20e0, 0xa85c, + 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, 0x2069, 0x0200, 0x6813, + 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020, 0x6017, 0x0009, + 0x2001, 0x19db, 0x2003, 0x07d0, 0x2001, 0x19da, 0x2003, 0x0009, + 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8bc, 0xd084, + 0x0128, 0x7a46, 0x7b14, 0x7b4a, 0x722e, 0x732a, 0x9294, 0x00ff, + 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, + 0x7206, 0x2069, 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, + 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, + 0x0081, 0x7814, 0x2048, 0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, + 0x700a, 0xa8ac, 0x700e, 0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, + 0x939b, 0x6813, 0x0008, 0xb810, 0x9085, 0x0500, 0x7002, 0xb814, + 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, + 0x0889, 0x080c, 0x9389, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, + 0x2071, 0x024c, 0x0005, 0x00d6, 0x0096, 0x080c, 0x91b3, 0x7814, + 0x2048, 0x080c, 0xbb39, 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, + 0x0033, 0x0010, 0x9006, 0x001b, 0x009e, 0x00de, 0x0005, 0x90d1, + 0x913a, 0x914a, 0x9170, 0x917c, 0x918d, 0x9195, 0x90cf, 0x080c, + 0x0db4, 0x0016, 0x0036, 0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, + 0x0003, 0x1198, 0xaba8, 0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, + 0x701a, 0xa894, 0x701e, 0x003e, 0x001e, 0x2001, 0x1989, 0x2004, + 0x60c2, 0x0804, 0x939b, 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, + 0x0db4, 0xaba8, 0x7824, 0xd0cc, 0x1904, 0x9137, 0x7316, 0xa898, + 0x701a, 0xa894, 0x701e, 0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, + 0x0018, 0x9384, 0x0300, 0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, + 0xd3cc, 0x0110, 0xa8a4, 0x9108, 0x6810, 0x9085, 0x0010, 0x6812, + 0x2011, 0x0258, 0x20e9, 0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, + 0xa860, 0x20e0, 0xa85c, 0x9080, 0x002c, 0x2098, 0x4003, 0x6810, + 0x8000, 0x6812, 0x2011, 0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, + 0x6810, 0xc084, 0x6812, 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, + 0x0245, 0x201a, 0x61c2, 0x003e, 0x001e, 0x0804, 0x939b, 0xc3e5, + 0x0804, 0x90f6, 0x2011, 0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, + 0x0110, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, + 0x0ce8, 0xc2e5, 0x2011, 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, + 0x711e, 0x9105, 0x0108, 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, + 0xc2e5, 0x7216, 0x7027, 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, + 0x7047, 0x0500, 0x704f, 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, + 0x2071, 0x0240, 0x700b, 0x2500, 0x60c3, 0x0032, 0x0804, 0x939b, + 0x2011, 0x0028, 0x7824, 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, + 0x0804, 0x939b, 0x0cd0, 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, + 0x0108, 0xc2e5, 0x7216, 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, + 0x7036, 0x60c3, 0x0020, 0x0804, 0x939b, 0x2011, 0x0008, 0x7824, + 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, + 0xff00, 0x7816, 0x9384, 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, + 0x0108, 0xc2e5, 0x7216, 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, + 0x0006, 0x7824, 0xd0cc, 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, + 0x701e, 0x003e, 0x0818, 0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, + 0x0700, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, + 0x687c, 0x700e, 0x7824, 0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, + 0x9389, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, + 0x00de, 0x0005, 0x7013, 0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, + 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x91e5, 0x91e5, 0x91e7, + 0x91e5, 0x91e5, 0x91e5, 0x9201, 0x91e5, 0x080c, 0x0db4, 0x7914, + 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, + 0x2069, 0x185b, 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, + 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, + 0x939b, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, + 0x080c, 0x9c37, 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, + 0x7006, 0x2069, 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, + 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x9389, 0x721a, 0x7a08, + 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, + 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, + 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14, 0x7378, 0x747c, + 0x7820, 0x90be, 0x0006, 0x0904, 0x92f8, 0x90be, 0x000a, 0x1904, + 0x92b4, 0xb8b0, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, + 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, + 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, + 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, + 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, + 0x0129, 0x6077, 0x0000, 0xb8b0, 0x609e, 0x0050, 0x2039, 0x0029, + 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, + 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, + 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, + 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, + 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x9c1c, + 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, + 0x1b58, 0x080c, 0x80c4, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086, 0x0040, 0x0904, + 0x9334, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, - 0x2f00, 0x6086, 0x7808, 0x6082, 0xa838, 0x608a, 0xa834, 0x608e, - 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0xbab0, 0x629e, 0x7824, 0xd0cc, 0x0120, 0x080c, - 0x9c2f, 0x0804, 0x92ca, 0x080c, 0x9c0c, 0x0804, 0x92ca, 0x7a10, - 0x00b6, 0x2258, 0xba8c, 0x8210, 0x9294, 0x00ff, 0xba8e, 0x00be, - 0x8217, 0x0005, 0x00d6, 0x2069, 0x19b7, 0x6843, 0x0001, 0x00de, - 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8098, - 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, - 0x0600, 0x0128, 0x0089, 0x080c, 0x8098, 0x001e, 0x0005, 0xc1e5, - 0x2001, 0x180c, 0x2102, 0x2001, 0x19b8, 0x2003, 0x0000, 0x2001, - 0x19c0, 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, 0x9084, 0x1804, - 0x9085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, - 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, 0x9084, 0x1804, - 0x9085, 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, - 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x6f9b, 0x11e8, 0x2001, 0x19d3, - 0x2004, 0x9005, 0x1904, 0x9413, 0x0066, 0x2031, 0x0001, 0x080c, - 0x704b, 0x006e, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, - 0x6024, 0xd084, 0x090c, 0x0db4, 0x080c, 0x8098, 0x0460, 0x00c6, - 0x2061, 0x19b7, 0x00d0, 0x6904, 0x9194, 0x4000, 0x0548, 0x080c, - 0x93ad, 0x080c, 0x2b26, 0x00c6, 0x2061, 0x19b7, 0x6128, 0x9192, - 0x0008, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, - 0x080c, 0x8098, 0x080c, 0x93a4, 0x0070, 0x6124, 0x91e5, 0x0000, - 0x0140, 0x080c, 0xd8ea, 0x080c, 0x80a1, 0x2009, 0x0014, 0x080c, - 0x9ebc, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, - 0x2001, 0x19d3, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19b7, - 0x6128, 0x9192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, - 0x8098, 0x080c, 0x5b99, 0x2009, 0x1852, 0x2114, 0x8210, 0x220a, - 0x0c10, 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, - 0x80ae, 0x2071, 0x19b7, 0x713c, 0x81ff, 0x0904, 0x94a3, 0x2061, - 0x0100, 0x2069, 0x0140, 0x080c, 0x6f9b, 0x11b0, 0x0036, 0x2019, - 0x0002, 0x080c, 0x96d9, 0x003e, 0x713c, 0x2160, 0x080c, 0xd8ea, - 0x2009, 0x004a, 0x080c, 0x9ebc, 0x0066, 0x2031, 0x0001, 0x080c, - 0x704b, 0x006e, 0x0804, 0x94a3, 0x080c, 0x94af, 0x0904, 0x94a3, - 0x6904, 0xd1f4, 0x0904, 0x94aa, 0x080c, 0x2b26, 0x00c6, 0x703c, + 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2048, 0xa838, 0x608a, + 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, + 0xbab0, 0x629e, 0x080c, 0x9c1c, 0x2009, 0x07d0, 0x60c4, 0x9084, + 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x80c4, 0x003e, + 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, + 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0904, + 0x9350, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, + 0x0880, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, + 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, 0x7808, 0x6082, + 0xa890, 0x608a, 0xa88c, 0x608e, 0xa8b0, 0x60c6, 0xa8ac, 0x60ca, + 0xa8ac, 0x7930, 0x9108, 0x7932, 0xa8b0, 0x792c, 0x9109, 0x792e, + 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbab0, 0x629e, + 0x080c, 0x9bf9, 0x0804, 0x92e4, 0xb8bc, 0xd084, 0x0148, 0xb88c, + 0x7814, 0x2048, 0xb88c, 0x7846, 0xa836, 0x2900, 0xa83a, 0xb04a, + 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, 0x0829, + 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000, 0x0804, 0x92c7, + 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x7824, 0xd0cc, + 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073, 0x0898, 0x6077, + 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, + 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0xa838, 0x608a, + 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0xb86c, 0x60ce, + 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbab0, 0x629e, 0x7824, 0xd0cc, + 0x0120, 0x080c, 0x9c1c, 0x0804, 0x92e4, 0x080c, 0x9bf9, 0x0804, + 0x92e4, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210, 0x9294, 0x00ff, + 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069, 0x19bf, 0x6843, + 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, + 0x080c, 0x80b6, 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, + 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x80b6, 0x001e, + 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, 0x19c0, 0x2003, + 0x0000, 0x2001, 0x19c8, 0x2003, 0x0000, 0x0c88, 0x0006, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0016, + 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x6014, + 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, 0xa001, 0xa001, + 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, + 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x6faa, 0x11c0, + 0x2001, 0x19db, 0x2004, 0x9005, 0x15d0, 0x080c, 0x705a, 0x1160, + 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, 0x090c, + 0x0db4, 0x080c, 0x80b6, 0x0458, 0x00c6, 0x2061, 0x19bf, 0x00c8, + 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c, 0x2b31, 0x00c6, + 0x2061, 0x19bf, 0x6128, 0x9192, 0x0008, 0x1258, 0x8108, 0x612a, + 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x80b6, 0x080c, 0x93be, + 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, 0xd903, 0x080c, + 0x80bf, 0x2009, 0x0014, 0x080c, 0x9ea9, 0x00ce, 0x0000, 0x002e, + 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x19db, 0x2004, 0x9005, + 0x1db0, 0x00c6, 0x2061, 0x19bf, 0x6128, 0x9192, 0x0003, 0x1e08, + 0x8108, 0x612a, 0x00ce, 0x080c, 0x80b6, 0x080c, 0x5ba4, 0x2009, + 0x185a, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x0026, 0x080c, 0x80cc, 0x2071, 0x19bf, 0x713c, + 0x81ff, 0x0904, 0x94b3, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, + 0x6faa, 0x1190, 0x0036, 0x2019, 0x0002, 0x080c, 0x96e9, 0x003e, + 0x713c, 0x2160, 0x080c, 0xd903, 0x2009, 0x004a, 0x080c, 0x9ea9, + 0x080c, 0x705a, 0x0804, 0x94b3, 0x080c, 0x94bf, 0x0904, 0x94b3, + 0x6904, 0xd1f4, 0x0904, 0x94ba, 0x080c, 0x2b31, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0db4, 0x6020, 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, 0x2009, 0x180c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, - 0x1510, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, 0x2a79, + 0x1510, 0x0030, 0xc0d4, 0x200a, 0xd0cc, 0x0110, 0x080c, 0x2a84, 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x703c, 0x2060, - 0x2009, 0x0049, 0x080c, 0x9ebc, 0x0070, 0x0036, 0x2019, 0x0001, - 0x080c, 0x96d9, 0x003e, 0x713c, 0x2160, 0x080c, 0xd8ea, 0x2009, - 0x004a, 0x080c, 0x9ebc, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, - 0x009e, 0x0005, 0xd1ec, 0x1904, 0x9464, 0x0804, 0x9466, 0x00d6, + 0x2009, 0x0049, 0x080c, 0x9ea9, 0x0070, 0x0036, 0x2019, 0x0001, + 0x080c, 0x96e9, 0x003e, 0x713c, 0x2160, 0x080c, 0xd903, 0x2009, + 0x004a, 0x080c, 0x9ea9, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, + 0x009e, 0x0005, 0xd1ec, 0x1904, 0x9474, 0x0804, 0x9476, 0x00d6, 0x00c6, 0x0096, 0x703c, 0x9065, 0x090c, 0x0db4, 0x2001, 0x1836, - 0x2004, 0xd09c, 0x1904, 0x953b, 0x2001, 0x0306, 0x200c, 0x9184, - 0x0030, 0x0904, 0x953b, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904, - 0x953b, 0x2001, 0x020b, 0x2004, 0xd0fc, 0x0904, 0x953b, 0xd08c, - 0x0904, 0x953b, 0x2009, 0x1a4f, 0x2104, 0x8000, 0x0208, 0x200a, + 0x2004, 0xd09c, 0x1904, 0x954b, 0x2001, 0x0306, 0x200c, 0x9184, + 0x0030, 0x0904, 0x954b, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904, + 0x954b, 0x2001, 0x020b, 0x2004, 0xd0fc, 0x0904, 0x954b, 0xd08c, + 0x0904, 0x954b, 0x2009, 0x1a57, 0x2104, 0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, 0x0184, 0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, 0x9106, 0x1570, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, 0x2001, 0x009a, 0x2003, 0x0004, - 0x2001, 0x1a35, 0x2003, 0x0000, 0x2001, 0x1a3e, 0x2003, 0x0000, - 0x6a88, 0x698c, 0x2200, 0x9105, 0x1120, 0x2c10, 0x080c, 0x1a5e, + 0x2001, 0x1a3d, 0x2003, 0x0000, 0x2001, 0x1a46, 0x2003, 0x0000, + 0x6a88, 0x698c, 0x2200, 0x9105, 0x1120, 0x2c10, 0x080c, 0x1a69, 0x0040, 0x6014, 0x2048, 0xaa3a, 0xa936, 0x6ac4, 0x69c8, 0xa946, - 0xaa4a, 0x0126, 0x00c6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1aea, - 0x190c, 0x0db4, 0x012e, 0x0090, 0x2009, 0x1a50, 0x2104, 0x8000, + 0xaa4a, 0x0126, 0x00c6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1af5, + 0x190c, 0x0db4, 0x012e, 0x0090, 0x2009, 0x1a58, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8, 0x2011, 0x0020, 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4, 0x68c8, 0x9105, 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002, 0x7048, 0xc085, 0x704a, 0x0079, 0x7048, - 0xc084, 0x704a, 0x2009, 0x07d0, 0x080c, 0x80a6, 0x9006, 0x009e, + 0xc084, 0x704a, 0x2009, 0x07d0, 0x080c, 0x80c4, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0026, 0x00e6, - 0x2071, 0x19b7, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, 0x01a8, + 0x2071, 0x19bf, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, 0x9085, 0x0012, 0x7016, 0x0030, 0x7014, 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19b7, + 0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19bf, 0x7018, 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, 0x2058, 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, - 0x009e, 0x080c, 0x6379, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, + 0x009e, 0x080c, 0x6388, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, - 0x080c, 0x8e8f, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, + 0x080c, 0x8ea9, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, 0x6078, 0x617c, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, - 0x002c, 0x0804, 0x9381, 0x080c, 0x8e8f, 0x7003, 0x0f00, 0x7808, + 0x002c, 0x0804, 0x939b, 0x080c, 0x8ea9, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0x9381, 0x0156, 0x080c, 0x8eda, 0x7003, + 0x60c3, 0x0008, 0x0804, 0x939b, 0x0156, 0x080c, 0x8ef4, 0x7003, 0x0200, 0x2011, 0x1848, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, 0x1840, 0x2019, 0x1841, 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x95d5, 0x60c3, - 0x001c, 0x015e, 0x0804, 0x9381, 0x0016, 0x0026, 0x080c, 0x8eb6, - 0x080c, 0x8ec8, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, + 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x95e5, 0x60c3, + 0x001c, 0x015e, 0x0804, 0x939b, 0x0016, 0x0026, 0x080c, 0x8ed0, + 0x080c, 0x8ee2, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, - 0x9381, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, - 0x9c35, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x8e8f, - 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x9381, - 0x0016, 0x0026, 0x080c, 0x8e8f, 0x20e9, 0x0000, 0x20a1, 0x024c, + 0x939b, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, + 0x9c22, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x8ea9, + 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x939b, + 0x0016, 0x0026, 0x080c, 0x8ea9, 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x4003, 0x8003, 0x60c2, 0x080c, 0x9381, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, - 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xbd32, 0x1110, 0x080c, - 0xa7d1, 0x600c, 0x0006, 0x080c, 0xbf9e, 0x080c, 0x9e42, 0x080c, - 0x97b1, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, + 0x4003, 0x8003, 0x60c2, 0x080c, 0x939b, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, + 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xbd41, 0x1110, 0x080c, + 0xa7cd, 0x600c, 0x0006, 0x080c, 0xbfad, 0x080c, 0x9e2f, 0x080c, + 0x979a, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, - 0x0140, 0x2071, 0x19b7, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, - 0x93ad, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x80a1, 0x00c6, 0x2061, - 0x0100, 0x080c, 0x9c4e, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, - 0x0013, 0x080c, 0x9ebc, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, + 0x0140, 0x2071, 0x19bf, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, + 0x93c7, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x80bf, 0x00c6, 0x2061, + 0x0100, 0x080c, 0x9c3b, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, + 0x0013, 0x080c, 0x9ea9, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x80a1, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5b43, 0x080c, 0x8021, 0x20a9, + 0x80bf, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x2011, 0x5b4e, 0x080c, 0x803f, 0x20a9, 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2b26, 0x0090, 0xd084, 0x0118, - 0x6827, 0x0001, 0x0010, 0x1f04, 0x96bb, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2b16, 0x9006, 0x080c, 0x2b16, + 0x7804, 0x9084, 0x4000, 0x190c, 0x2b31, 0x0090, 0xd084, 0x0118, + 0x6827, 0x0001, 0x0010, 0x1f04, 0x96cb, 0x7804, 0x9084, 0x1000, + 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19b7, 0x703c, 0x2060, 0x8cff, 0x0904, 0x9767, 0x9386, 0x0002, - 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x9767, 0x68af, 0x95f5, + 0x19bf, 0x703c, 0x2060, 0x8cff, 0x0904, 0x9750, 0x9386, 0x0002, + 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x9750, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, - 0x0008, 0x080c, 0x80ae, 0x080c, 0x1e92, 0x0046, 0x2009, 0x00a5, - 0x080c, 0x0e2f, 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, - 0x0004, 0x11f8, 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, - 0x00f6, 0x2079, 0x0090, 0x2071, 0x1a35, 0x6814, 0x9084, 0x1984, - 0x9085, 0x0012, 0x6816, 0x782b, 0x0008, 0x7003, 0x0000, 0x00fe, - 0x00ee, 0x9386, 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, - 0x0001, 0x2001, 0x1951, 0x200c, 0x080c, 0x0e2f, 0x004e, 0x20a9, - 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, - 0x4000, 0x190c, 0x2b26, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, - 0x0010, 0x1f04, 0x9741, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2b16, 0x9006, 0x080c, 0x2b16, 0x6827, 0x4000, - 0x6824, 0x83ff, 0x1120, 0x2009, 0x0049, 0x080c, 0x9ebc, 0x000e, - 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, - 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19b7, - 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0x19b7, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, 0x9048, - 0x7854, 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, 0x080c, 0x9048, - 0x7854, 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, 0x080c, 0x9048, - 0x7854, 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, 0x080c, 0x9048, - 0x7854, 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, 0x080c, 0x9048, - 0x7854, 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, 0x0020, 0x0804, - 0x9381, 0x00e6, 0x2071, 0x19b7, 0x7020, 0x9005, 0x0110, 0x8001, - 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, 0x7614, - 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x9856, 0x8cff, - 0x0904, 0x9856, 0x6020, 0x9086, 0x0006, 0x1904, 0x9851, 0x88ff, - 0x0138, 0x2800, 0x9c06, 0x1904, 0x9851, 0x2039, 0x0000, 0x0050, - 0x6010, 0x9b06, 0x1904, 0x9851, 0x85ff, 0x0120, 0x6054, 0x9106, - 0x1904, 0x9851, 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, - 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, - 0x80a1, 0x080c, 0x98db, 0x7027, 0x0000, 0x0428, 0x080c, 0x80a1, - 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b16, - 0x9006, 0x080c, 0x2b16, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, - 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, - 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, 0x6014, - 0x0096, 0x2048, 0x080c, 0xbb2a, 0x0110, 0x080c, 0xd4f6, 0x009e, - 0x080c, 0x9e72, 0x080c, 0x97b1, 0x88ff, 0x1190, 0x00ce, 0x0804, - 0x97cc, 0x2c78, 0x600c, 0x2060, 0x0804, 0x97cc, 0x9006, 0x012e, - 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, - 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19b7, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, - 0x98ca, 0x6020, 0x9086, 0x0006, 0x1904, 0x98c5, 0x87ff, 0x0128, - 0x2700, 0x9c06, 0x1904, 0x98c5, 0x0040, 0x6010, 0x9b06, 0x15e8, - 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, - 0x0036, 0x2019, 0x0001, 0x080c, 0x96d9, 0x7033, 0x0000, 0x9006, - 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, - 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, - 0x2048, 0x080c, 0xbb2a, 0x0110, 0x080c, 0xd4f6, 0x080c, 0x9e72, - 0x87ff, 0x1198, 0x00ce, 0x0804, 0x9876, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x9876, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, - 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, - 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19b7, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, - 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, 0x2c10, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7038, - 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x6004, 0x9086, 0x0040, 0x090c, 0x8861, 0x9085, 0x0001, 0x0020, - 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19b7, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x99c1, 0x6010, - 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0x99bc, 0x7024, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x9993, - 0x080c, 0x93ad, 0x68c3, 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2b16, 0x9006, 0x080c, 0x2b16, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, - 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xbd21, 0x1180, 0x080c, 0x3005, 0x080c, 0xbd32, 0x1518, - 0x080c, 0xa7d1, 0x0400, 0x080c, 0x98db, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xbd32, 0x1118, 0x080c, 0xa7d1, - 0x0090, 0x6014, 0x2048, 0x080c, 0xbb2a, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6884, 0x080c, 0xbd15, 0x080c, 0xbf9e, 0x080c, 0x9e72, 0x080c, - 0x97b1, 0x00ce, 0x0804, 0x993c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x993c, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, - 0xd4f6, 0x0c08, 0x00d6, 0x080c, 0x8eda, 0x7003, 0x0200, 0x7007, - 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1959, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, - 0x7027, 0x7878, 0x080c, 0x9381, 0x00de, 0x0005, 0x080c, 0x8eda, - 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, - 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, 0x00ff, 0x9085, - 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, - 0x0804, 0x9381, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, - 0x0035, 0x080c, 0xc1a4, 0x00de, 0x1904, 0x9a6f, 0x080c, 0x8e8f, - 0x7003, 0x1300, 0x782c, 0x080c, 0x9b71, 0x2068, 0x6820, 0x9086, - 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0x9dc1, 0x11d8, - 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, - 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, - 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, - 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, - 0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, 0x080c, 0x9dc1, - 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, - 0x2069, 0x181e, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, - 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, - 0x000c, 0x001e, 0x00de, 0x080c, 0x9381, 0x00be, 0x0005, 0x781b, - 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, - 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, - 0x0904, 0x9ae9, 0x9186, 0x0005, 0x0904, 0x9ad2, 0x9186, 0x0004, - 0x05d8, 0x9186, 0x0008, 0x0904, 0x9ada, 0x7807, 0x0037, 0x782f, - 0x0003, 0x7817, 0x1700, 0x080c, 0x9b4e, 0x0005, 0x080c, 0x9b0f, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, - 0x9ab3, 0x9abe, 0x9ab5, 0x9abe, 0x9aba, 0x9ab3, 0x9ab3, 0x9abe, - 0x9abe, 0x9abe, 0x9abe, 0x9ab3, 0x9ab3, 0x9ab3, 0x9ab3, 0x9ab3, - 0x9abe, 0x9ab3, 0x9abe, 0x080c, 0x0db4, 0x6824, 0xd0e4, 0x0110, - 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, - 0x6830, 0x7026, 0x0804, 0x9b08, 0x080c, 0x9b0f, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, - 0x900e, 0x04b0, 0x04e1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, - 0x4000, 0x0470, 0x04a1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, - 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, - 0x00f8, 0x0429, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x0096, - 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, - 0x7022, 0x7226, 0x792c, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, - 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, - 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, 0x9381, 0x00b6, - 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x8eda, 0x9006, 0x7003, - 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, - 0x080c, 0x9dc1, 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, - 0x181e, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, - 0xbc14, 0x00de, 0x0028, 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, - 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, - 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, - 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, 0x080c, 0x8eda, - 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, - 0x0008, 0x0804, 0x9381, 0x080c, 0x8e86, 0x7003, 0x1400, 0x7838, - 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, - 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, - 0x9381, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, - 0x00b6, 0x2058, 0xb8bc, 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, - 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x8ed1, - 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, - 0x0804, 0x9381, 0x0021, 0x60c3, 0x0000, 0x0804, 0x9381, 0x00d6, - 0x080c, 0x9c4a, 0xb810, 0x9085, 0x0300, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, 0x0819, - 0x080c, 0x936f, 0x721a, 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, - 0x024c, 0x00de, 0x0005, 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, - 0x60a7, 0x9575, 0x0026, 0x080c, 0x29cc, 0x0228, 0x2011, 0x0101, - 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0x93a4, 0x080c, 0x8098, - 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7858, 0x2048, 0xaa7c, - 0x9296, 0x00c0, 0x9294, 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, - 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, - 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, - 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, 0x9c4a, 0x00de, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, - 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, - 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, - 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, - 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, - 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, - 0x2009, 0x1982, 0x210c, 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, - 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, - 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, - 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, - 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x00d6, 0x9290, - 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, - 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, - 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, - 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00d6, 0x0096, - 0x6014, 0x2048, 0xa878, 0x6056, 0x9006, 0xa836, 0xa83a, 0xa99c, - 0xa946, 0xa84a, 0x6023, 0x0003, 0x6007, 0x0040, 0x6003, 0x0003, - 0x600b, 0xffff, 0xa817, 0x0001, 0xa842, 0xa83e, 0x2900, 0xa85a, - 0xa813, 0x1f26, 0x080c, 0x843f, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8a4a, 0x012e, 0x009e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19b7, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9d21, 0x7024, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x9cf3, - 0x080c, 0x93ad, 0x68c3, 0x0000, 0x080c, 0x98db, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2b16, 0x9006, 0x080c, 0x2b16, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, - 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, + 0x0008, 0x080c, 0x80cc, 0x080c, 0x1e9d, 0x2001, 0x0032, 0x6920, + 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, + 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, + 0x9084, 0x4000, 0x190c, 0x2b31, 0x0090, 0xd08c, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0x972a, 0x7804, 0x9084, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, 0x6827, + 0x4000, 0x6824, 0x83ff, 0x1120, 0x2009, 0x0049, 0x080c, 0x9ea9, + 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, + 0x19bf, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, + 0x8000, 0x2069, 0x19bf, 0x6a32, 0x012e, 0x00de, 0x0005, 0x080c, + 0x9062, 0x7854, 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, 0x080c, + 0x9062, 0x7854, 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, 0x080c, + 0x9062, 0x7854, 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, 0x080c, + 0x9062, 0x7854, 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, 0x080c, + 0x9062, 0x7854, 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, 0x0020, + 0x0804, 0x939b, 0x00e6, 0x2071, 0x19bf, 0x7020, 0x9005, 0x0110, + 0x8001, 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, + 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x983f, + 0x8cff, 0x0904, 0x983f, 0x6020, 0x9086, 0x0006, 0x1904, 0x983a, + 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0x983a, 0x2039, 0x0000, + 0x0050, 0x6010, 0x9b06, 0x1904, 0x983a, 0x85ff, 0x0120, 0x6054, + 0x9106, 0x1904, 0x983a, 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, + 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, + 0x080c, 0x80bf, 0x080c, 0x98c4, 0x7027, 0x0000, 0x0428, 0x080c, + 0x80bf, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, + 0x68c3, 0x0000, 0x080c, 0x98c4, 0x7027, 0x0000, 0x0036, 0x2069, + 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2b21, 0x9006, 0x080c, 0x2b21, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, 0x660c, + 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, + 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, + 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, + 0x6014, 0x0096, 0x2048, 0x080c, 0xbb39, 0x0110, 0x080c, 0xd50f, + 0x009e, 0x080c, 0x9e5f, 0x080c, 0x979a, 0x88ff, 0x1190, 0x00ce, + 0x0804, 0x97b5, 0x2c78, 0x600c, 0x2060, 0x0804, 0x97b5, 0x9006, + 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, + 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x19bf, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x98b3, 0x6020, 0x9086, 0x0006, 0x1904, 0x98ae, 0x87ff, + 0x0128, 0x2700, 0x9c06, 0x1904, 0x98ae, 0x0040, 0x6010, 0x9b06, + 0x15e8, 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, + 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x96e9, 0x7033, 0x0000, + 0x9006, 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, + 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, + 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xbd21, 0x1180, 0x080c, 0x3005, 0x080c, 0xbd32, 0x1518, - 0x080c, 0xa7d1, 0x0400, 0x080c, 0x98db, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xbd32, 0x1118, 0x080c, 0xa7d1, - 0x0090, 0x6014, 0x2048, 0x080c, 0xbb2a, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6891, 0x080c, 0xbd15, 0x080c, 0xbf9e, 0x080c, 0x9e72, 0x080c, - 0x97b1, 0x00ce, 0x0804, 0x9ca4, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x9ca4, 0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x006e, 0x009e, - 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1d08, 0x080c, 0xd4f6, 0x08f0, 0x00d6, 0x0156, 0x080c, - 0x8eda, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, - 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, - 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, - 0x080c, 0x6f9b, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, - 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x2011, 0x1848, 0x63f0, - 0x2312, 0x20a9, 0x0006, 0x2011, 0x1840, 0x2019, 0x1841, 0x2071, - 0x0250, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0x9d69, 0x60c3, 0x0020, 0x080c, 0x9381, 0x015e, - 0x00de, 0x0005, 0x0156, 0x080c, 0x8eda, 0x7a14, 0x82ff, 0x0168, - 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, - 0x001c, 0x700f, 0x0001, 0x2011, 0x198d, 0x2204, 0x8007, 0x701a, - 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7022, 0x2001, 0x181f, - 0x2004, 0x7026, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, - 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, - 0x9381, 0x0006, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x000e, 0x0005, - 0x2011, 0x0003, 0x080c, 0x9772, 0x2011, 0x0002, 0x080c, 0x977c, - 0x080c, 0x9663, 0x0036, 0x901e, 0x080c, 0x96d9, 0x003e, 0x0005, - 0x2071, 0x1883, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976, 0x2071, - 0x1800, 0x7072, 0x7076, 0x7067, 0xffe0, 0x2071, 0x1800, 0x7070, - 0x7052, 0x7057, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, - 0x2091, 0x8000, 0x7550, 0x9582, 0x0010, 0x0608, 0x7054, 0x2060, + 0x6014, 0x2048, 0x080c, 0xbb39, 0x0110, 0x080c, 0xd50f, 0x080c, + 0x9e5f, 0x87ff, 0x1198, 0x00ce, 0x0804, 0x985f, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x985f, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, + 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, + 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19bf, 0x2001, + 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, + 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, + 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, 0x2c10, + 0x7638, 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, + 0x7038, 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, + 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, + 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, 0x887f, 0x9085, 0x0001, + 0x0020, 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, + 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, + 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2071, 0x19bf, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0x99aa, + 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0x99a5, + 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, + 0x997c, 0x080c, 0x93c7, 0x68c3, 0x0000, 0x080c, 0x98c4, 0x7027, + 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, + 0x2001, 0x0100, 0x080c, 0x2b21, 0x9006, 0x080c, 0x2b21, 0x2069, + 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, + 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, + 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, + 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, + 0x0000, 0x080c, 0xbd30, 0x1180, 0x080c, 0x3010, 0x080c, 0xbd41, + 0x1518, 0x080c, 0xa7cd, 0x0400, 0x080c, 0x98c4, 0x6824, 0xd084, + 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xbd41, 0x1118, 0x080c, + 0xa7cd, 0x0090, 0x6014, 0x2048, 0x080c, 0xbb39, 0x0168, 0x6020, + 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, + 0x080c, 0x6893, 0x080c, 0xbd24, 0x080c, 0xbfad, 0x080c, 0x9e5f, + 0x080c, 0x979a, 0x00ce, 0x0804, 0x9925, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x9925, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, + 0x080c, 0xd50f, 0x0c08, 0x00d6, 0x080c, 0x8ef4, 0x7003, 0x0200, + 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1961, + 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, + 0x0004, 0x7027, 0x7878, 0x080c, 0x939b, 0x00de, 0x0005, 0x080c, + 0x8ef4, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, + 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, 0x00ff, + 0x9085, 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, 0x7006, + 0x60c2, 0x0804, 0x939b, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, + 0x2009, 0x0035, 0x080c, 0xc1b3, 0x00de, 0x1904, 0x9a58, 0x080c, + 0x8ea9, 0x7003, 0x1300, 0x782c, 0x080c, 0x9b5e, 0x2068, 0x6820, + 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0x9dae, + 0x11d8, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, + 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, + 0x0458, 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, + 0x00ff, 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, + 0x700a, 0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, 0x080c, + 0x9dae, 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, + 0x00d6, 0x2069, 0x181e, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, + 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, + 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x939b, 0x00be, 0x0005, + 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, + 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, + 0x0003, 0x0904, 0x9ad3, 0x9186, 0x0005, 0x0904, 0x9abb, 0x9186, + 0x0004, 0x05d8, 0x9186, 0x0008, 0x0904, 0x9ac4, 0x7807, 0x0037, + 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0x9b3b, 0x0005, 0x080c, + 0x9afc, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, + 0x0002, 0x9a9c, 0x9aa7, 0x9a9e, 0x9aa7, 0x9aa3, 0x9a9c, 0x9a9c, + 0x9aa7, 0x9aa7, 0x9aa7, 0x9aa7, 0x9a9c, 0x9a9c, 0x9a9c, 0x9a9c, + 0x9a9c, 0x9aa7, 0x9a9c, 0x9aa7, 0x080c, 0x0db4, 0x6824, 0xd0e4, + 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, + 0x7022, 0x6830, 0x7026, 0x0804, 0x9af5, 0x080c, 0x9afc, 0x00d6, + 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, + 0x1108, 0x900e, 0x04d0, 0x080c, 0x9afc, 0x00d6, 0x0026, 0x792c, + 0x2168, 0x2009, 0x4000, 0x0488, 0x04b9, 0x00d6, 0x0026, 0x792c, + 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, + 0x1108, 0x900e, 0x0410, 0x0441, 0x00d6, 0x0026, 0x792c, 0x2168, + 0x6814, 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, 0xa834, + 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, + 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, + 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, + 0x002e, 0x00de, 0x0804, 0x939b, 0x00b6, 0x0036, 0x0046, 0x0056, + 0x0066, 0x080c, 0x8ef4, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, + 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0x9dae, 0x1118, + 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x181e, 0x2d2c, 0x8d68, + 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, + 0x901e, 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, + 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, + 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, + 0x003e, 0x00be, 0x0005, 0x080c, 0x8ef4, 0x7003, 0x0100, 0x782c, + 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0x939b, + 0x080c, 0x8ea0, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, + 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, + 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x939b, 0x00e6, 0x2071, + 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8bc, + 0xd084, 0x0120, 0x7848, 0x702a, 0x7844, 0x702e, 0x00be, 0x00fe, + 0x000e, 0x00ee, 0x0005, 0x080c, 0x8eeb, 0x7003, 0x0100, 0x782c, + 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x939b, 0x0021, + 0x60c3, 0x0000, 0x0804, 0x939b, 0x00d6, 0x080c, 0x9c37, 0xb810, + 0x9085, 0x0300, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, + 0x700a, 0x687c, 0x700e, 0x7013, 0x0819, 0x080c, 0x9389, 0x721a, + 0x2f10, 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, + 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, + 0x080c, 0x29d7, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, + 0x002e, 0x080c, 0x93be, 0x080c, 0x80b6, 0x0005, 0x0036, 0x0096, + 0x00d6, 0x00e6, 0x7858, 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, + 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, + 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, + 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, + 0x2069, 0x0200, 0x080c, 0x9c37, 0x00de, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, + 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, + 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, + 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, + 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, + 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, + 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x198a, 0x210c, + 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x6116, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, + 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, + 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, + 0x0008, 0x6912, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, + 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, + 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, + 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, + 0x0c60, 0x00de, 0x0005, 0x00d6, 0x0096, 0x6014, 0x2048, 0xa878, + 0x6056, 0x9006, 0xa836, 0xa83a, 0xa99c, 0xa946, 0xa84a, 0x6023, + 0x0003, 0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0xa817, + 0x0001, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa813, 0x1f31, 0x080c, + 0x845d, 0x0126, 0x2091, 0x8000, 0x080c, 0x8a68, 0x012e, 0x009e, + 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, + 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, 0x760c, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x9d0e, 0x7024, 0x9c06, 0x1520, 0x2069, + 0x0100, 0x68c0, 0x9005, 0x0904, 0x9ce0, 0x080c, 0x93c7, 0x68c3, + 0x0000, 0x080c, 0x98c4, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2b21, + 0x9006, 0x080c, 0x2b21, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, + 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, + 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xbd30, 0x1180, + 0x080c, 0x3010, 0x080c, 0xbd41, 0x1518, 0x080c, 0xa7cd, 0x0400, + 0x080c, 0x98c4, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, + 0x080c, 0xbd41, 0x1118, 0x080c, 0xa7cd, 0x0090, 0x6014, 0x2048, + 0x080c, 0xbb39, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x68a0, 0x080c, 0xbd24, + 0x080c, 0xbfad, 0x080c, 0x9e5f, 0x080c, 0x979a, 0x00ce, 0x0804, + 0x9c91, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9c91, 0x700f, 0x0000, + 0x700b, 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, + 0xd50f, 0x08f0, 0x00d6, 0x0156, 0x080c, 0x8ef4, 0x7a14, 0x82ff, + 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, + 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, + 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x6faa, 0x1110, + 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, + 0xc39d, 0x730e, 0x2011, 0x1848, 0x63f0, 0x2312, 0x20a9, 0x0006, + 0x2011, 0x1840, 0x2019, 0x1841, 0x2071, 0x0250, 0x2376, 0x8e70, + 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x9d56, + 0x60c3, 0x0020, 0x080c, 0x939b, 0x015e, 0x00de, 0x0005, 0x0156, + 0x080c, 0x8ef4, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, + 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, + 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, + 0x2011, 0x1995, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, + 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, + 0x181e, 0x2004, 0x7022, 0x2001, 0x181f, 0x2004, 0x7026, 0x0030, + 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, 0x939b, 0x0006, 0x2001, + 0x1836, 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, + 0x975b, 0x2011, 0x0002, 0x080c, 0x9765, 0x080c, 0x9673, 0x0036, + 0x901e, 0x080c, 0x96e9, 0x003e, 0x0005, 0x2071, 0x188b, 0x7000, + 0x9005, 0x0140, 0x2001, 0x0976, 0x2071, 0x1800, 0x7072, 0x7076, + 0x7067, 0xffe0, 0x2071, 0x1800, 0x7070, 0x7052, 0x7057, 0x1cd0, + 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7550, + 0x9582, 0x0010, 0x0608, 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, + 0x0148, 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, + 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, 0x0018, + 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, 0x0001, 0x012e, 0x00ee, + 0x0005, 0x7057, 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, + 0x1800, 0x7550, 0x9582, 0x0010, 0x0600, 0x7054, 0x2060, 0x6000, + 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1208, + 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, + 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1228, 0x7556, 0x9085, 0x0001, + 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, + 0x1cd0, 0x0a0c, 0x0db4, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1a0c, + 0x0db4, 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, + 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, 0x6056, 0x605a, 0x6026, + 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x6042, 0x2061, + 0x1800, 0x6050, 0x8000, 0x6052, 0x9086, 0x0001, 0x0108, 0x0005, + 0x0126, 0x2091, 0x8000, 0x080c, 0x898b, 0x012e, 0x0cc0, 0x0006, + 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, 0xd084, 0x190c, 0x191f, + 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, 0x195e, 0x2004, 0x0006, + 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xd7c1, + 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, + 0x2091, 0x8000, 0x7550, 0x9582, 0x0001, 0x0608, 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc0, 0x9006, - 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7550, 0x9582, 0x0010, 0x0600, - 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, - 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x7552, 0x9ca8, 0x0018, 0x7064, 0x9502, 0x1228, - 0x7556, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7057, 0x1cd0, 0x0cc8, - 0x9006, 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0db4, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1a0c, 0x0db4, 0x9006, 0x6006, 0x600a, 0x600e, - 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, - 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, - 0x603e, 0x6042, 0x2061, 0x1800, 0x6050, 0x8000, 0x6052, 0x9086, - 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x896d, - 0x012e, 0x0cc0, 0x0006, 0x6000, 0x9086, 0x0000, 0x01b0, 0x601c, - 0xd084, 0x190c, 0x190f, 0x6017, 0x0000, 0x6023, 0x0007, 0x2001, - 0x1956, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, - 0x601a, 0x080c, 0xd7a8, 0x6043, 0x0000, 0x000e, 0x0005, 0x00e6, - 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7550, 0x9582, 0x0001, - 0x0608, 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, - 0x0018, 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, 0x0018, 0x7064, 0x9502, - 0x1230, 0x7556, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7057, - 0x1cd0, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, - 0x9ecf, 0x9ed8, 0x9ef3, 0x9f0e, 0xc252, 0xc26f, 0xc28a, 0x9ecf, - 0x9ed8, 0x9ecf, 0x9f2a, 0x9ecf, 0x9ecf, 0x9ecf, 0x9ecf, 0x9186, - 0x0013, 0x1128, 0x080c, 0x8861, 0x080c, 0x896d, 0x0005, 0x0005, + 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0x9ebc, 0x9ec5, 0x9ee0, + 0x9efb, 0xc261, 0xc27e, 0xc299, 0x9ebc, 0x9ec5, 0x9ebc, 0x9f17, + 0x9ebc, 0x9ebc, 0x9ebc, 0x9ebc, 0x9186, 0x0013, 0x1128, 0x080c, + 0x887f, 0x080c, 0x898b, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, + 0x0016, 0x1a0c, 0x0db4, 0x0013, 0x006e, 0x0005, 0x9ede, 0xa644, + 0xa814, 0x9ede, 0xa8a2, 0xa1fa, 0x9ede, 0x9ede, 0xa5c6, 0xae46, + 0x9ede, 0x9ede, 0x9ede, 0x9ede, 0x9ede, 0x9ede, 0x080c, 0x0db4, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db4, 0x0013, 0x006e, - 0x0005, 0x9ef1, 0xa64a, 0xa818, 0x9ef1, 0xa8a6, 0xa20d, 0x9ef1, - 0x9ef1, 0xa5cc, 0xae4a, 0x9ef1, 0x9ef1, 0x9ef1, 0x9ef1, 0x9ef1, - 0x9ef1, 0x080c, 0x0db4, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, - 0x0db4, 0x0013, 0x006e, 0x0005, 0x9f0c, 0xb51e, 0x9f0c, 0x9f0c, - 0x9f0c, 0x9f0c, 0x9f0c, 0x9f0c, 0xb4c3, 0xb6a0, 0x9f0c, 0xb55f, - 0xb5de, 0xb55f, 0xb5de, 0x9f0c, 0x080c, 0x0db4, 0x6000, 0x9082, - 0x0016, 0x1a0c, 0x0db4, 0x6000, 0x0002, 0x9f28, 0xae91, 0xaf76, - 0xb0a6, 0xb251, 0x9f28, 0x9f28, 0x9f28, 0xae65, 0xb44f, 0xb452, - 0x9f28, 0x9f28, 0x9f28, 0x9f28, 0xb481, 0x9f28, 0x9f28, 0x9f28, - 0x080c, 0x0db4, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db4, - 0x0013, 0x006e, 0x0005, 0x9f43, 0x9f43, 0x9f86, 0xa025, 0xa0ba, - 0x9f43, 0x9f43, 0x9f43, 0x9f45, 0x9f43, 0x9f43, 0x9f43, 0x9f43, - 0x9f43, 0x9f43, 0x9f43, 0x080c, 0x0db4, 0x9186, 0x004c, 0x0588, - 0x9186, 0x0003, 0x190c, 0x0db4, 0x0096, 0x601c, 0xc0ed, 0x601e, - 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, - 0xc0b5, 0xa87e, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0x9006, 0xa836, - 0xa83a, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, 0x2c10, 0x080c, 0x1a5e, - 0x080c, 0x843f, 0x0126, 0x2091, 0x8000, 0x080c, 0x8a4a, 0x012e, - 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, - 0xa0dc, 0x080c, 0xc244, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, - 0x00f6, 0x2079, 0x1800, 0x7a8c, 0x6014, 0x2048, 0xa87c, 0xd0ec, - 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, - 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, - 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, - 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, - 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, - 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, - 0x9fed, 0x9fed, 0x9fe8, 0x9feb, 0x9fed, 0x9fe5, 0x9fd8, 0x9fd8, - 0x9fd8, 0x9fd8, 0x9fd8, 0x9fd8, 0x9fd8, 0x9fd8, 0x9fd8, 0x9fd8, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, - 0x00fe, 0x009e, 0x00de, 0x080c, 0x0db4, 0x080c, 0xaa89, 0x0028, - 0x080c, 0xabac, 0x0010, 0x080c, 0xac9b, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xa19a, - 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x1249, - 0x080c, 0xa345, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, - 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0x9e42, 0x2001, - 0x002c, 0x900e, 0x080c, 0xa200, 0x0c70, 0x91b6, 0x0015, 0x0170, - 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0db4, 0x91b2, - 0x0050, 0x1a0c, 0x0db4, 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, - 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x080c, 0x8393, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, - 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0x9f86, 0x0005, 0xa058, - 0xa058, 0xa05a, 0xa090, 0xa058, 0xa058, 0xa058, 0xa058, 0xa0a3, - 0x080c, 0x0db4, 0x00d6, 0x0016, 0x0096, 0x080c, 0x891d, 0x080c, - 0x8a4a, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, - 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, - 0x0000, 0x900e, 0x080c, 0xa200, 0x080c, 0x9e42, 0x00a8, 0x6003, - 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, - 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, - 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, - 0x080c, 0x891d, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xbb2c, - 0x0120, 0xa87b, 0x0006, 0x080c, 0x6891, 0x009e, 0x00de, 0x080c, - 0x9e42, 0x0804, 0x8a4a, 0x080c, 0x891d, 0x080c, 0x2fdc, 0x080c, - 0xc241, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xbb2c, 0x0120, - 0xa87b, 0x0029, 0x080c, 0x6891, 0x009e, 0x00de, 0x080c, 0x9e42, - 0x0804, 0x8a4a, 0x9182, 0x0047, 0x0002, 0xa0ca, 0xa0cc, 0xa0ca, - 0xa0ca, 0xa0ca, 0xa0ca, 0xa0ca, 0xa0ca, 0xa0ca, 0xa0ca, 0xa0ca, - 0xa0ca, 0xa0cc, 0x080c, 0x0db4, 0x00d6, 0x0096, 0x080c, 0x1511, - 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, 0x6891, - 0x009e, 0x00de, 0x0804, 0x9e42, 0x0026, 0x0036, 0x0056, 0x0066, - 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x0feb, 0x000e, 0x090c, - 0x0db4, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, - 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, 0x798c, 0x9188, - 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, - 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, - 0x1228, 0x2011, 0x001f, 0x080c, 0xb725, 0x04c0, 0x2130, 0x2009, - 0x0034, 0x2011, 0x001f, 0x080c, 0xb725, 0x96b2, 0x0034, 0xb004, - 0x904d, 0x0110, 0x080c, 0x0f9d, 0x080c, 0x0feb, 0x01d0, 0x8528, - 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, - 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xb725, 0x00b8, 0x96b2, - 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, 0xb725, - 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, - 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, - 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x6891, 0x000e, 0x2048, - 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, - 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, 0x0feb, - 0x000e, 0x090c, 0x0db4, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, - 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, - 0x1800, 0x798c, 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, - 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, - 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, - 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, 0x6891, 0x009e, 0x00fe, - 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, - 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, - 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, - 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, - 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, 0x0feb, 0x2900, 0x009e, - 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, - 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, - 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, - 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, - 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, - 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, - 0x2e98, 0x2310, 0x84ff, 0x0904, 0xa1af, 0x0804, 0xa1b1, 0x9085, - 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, - 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, - 0x6884, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, - 0x080c, 0x9e42, 0x0030, 0x91b6, 0x0016, 0x190c, 0x0db4, 0x080c, - 0x9e42, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, - 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, - 0x0136, 0x9080, 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, - 0x3418, 0x8318, 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, - 0x1db8, 0x2011, 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, - 0x4003, 0x3418, 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, - 0xbb2c, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0x009e, 0x0804, 0x9e42, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, - 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8bf, 0x0000, 0x00be, - 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xab32, 0x080c, 0x9e42, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, - 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xc22c, 0x0188, 0x6014, - 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, - 0x2009, 0x0022, 0x080c, 0xa622, 0x9006, 0x001e, 0x000e, 0x0005, - 0x9085, 0x0001, 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, - 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, - 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, - 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, - 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, - 0x0020, 0x4003, 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x080c, 0x9e42, 0x001e, 0x009e, 0x0005, 0x0096, - 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, - 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, - 0x9108, 0x810b, 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, - 0x080c, 0xb725, 0x080c, 0xbb2c, 0x0140, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0x9e42, 0x001e, - 0x009e, 0x0005, 0x0016, 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, - 0x2009, 0x0004, 0x0010, 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, - 0x2019, 0x000c, 0x6014, 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, - 0x2048, 0x080c, 0xb725, 0x009e, 0x080c, 0xbb2c, 0x0148, 0xa804, - 0x9005, 0x1158, 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, - 0x080c, 0x9e42, 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, - 0x8007, 0x9086, 0x0100, 0x1118, 0x080c, 0xa7d1, 0x00e0, 0xa034, - 0x8007, 0x800c, 0x8806, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x000c, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, - 0x4000, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, - 0x122f, 0x0019, 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, - 0x0feb, 0x000e, 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, - 0x0006, 0xae6a, 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, - 0xac96, 0xad9a, 0x0086, 0x2940, 0x080c, 0x10d5, 0x008e, 0x9085, - 0x0001, 0x009e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, - 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, - 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, - 0x6043, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xc1a4, - 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, - 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, 0x9e42, 0x0020, - 0x0039, 0x0010, 0x080c, 0xa457, 0x002e, 0x00de, 0x00ee, 0x0005, - 0x0096, 0x6814, 0x2048, 0x9186, 0x0015, 0x0904, 0xa43f, 0x918e, - 0x0016, 0x1904, 0xa455, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, - 0x0120, 0x9186, 0x0300, 0x1904, 0xa419, 0x89ff, 0x1138, 0x6800, - 0x9086, 0x000f, 0x0904, 0xa3fc, 0x0804, 0xa453, 0x6808, 0x9086, - 0xffff, 0x1904, 0xa441, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, - 0x1128, 0xa83c, 0xa940, 0x9105, 0x1904, 0xa441, 0x6824, 0xd0b4, - 0x1904, 0xa441, 0x080c, 0xbd15, 0x685c, 0xa882, 0xa87c, 0xc0dc, - 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, - 0x080c, 0x8259, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, - 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xb84f, 0x00ce, 0x0804, - 0xa453, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x5d56, 0x0010, - 0x080c, 0x60fd, 0x00ce, 0x1904, 0xa441, 0x00c6, 0x2d60, 0x080c, - 0x9e42, 0x00ce, 0x0804, 0xa453, 0x00c6, 0x080c, 0x9e8f, 0x0198, - 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xbfa6, 0x6023, 0x0003, - 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9e42, 0x00ce, 0x080c, 0x9ebc, - 0x00ce, 0x0804, 0xa453, 0x2001, 0x1958, 0x2004, 0x6842, 0x00ce, - 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, - 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, - 0x080c, 0xc1e6, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x080c, 0x83da, 0x080c, 0x896d, 0x00ce, 0x00e8, 0x700c, 0x9086, - 0x2a00, 0x1138, 0x2001, 0x1958, 0x2004, 0x6842, 0x00a0, 0x0479, - 0x00a0, 0x89ff, 0x090c, 0x0db4, 0x00c6, 0x00d6, 0x2d60, 0xa867, - 0x0103, 0xa87b, 0x0003, 0x080c, 0x66ac, 0x080c, 0xbd15, 0x080c, - 0x9e72, 0x00de, 0x00ce, 0x080c, 0x9e42, 0x009e, 0x0005, 0x9186, - 0x0015, 0x1128, 0x2001, 0x1958, 0x2004, 0x6842, 0x0068, 0x918e, - 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xd7a8, 0x080c, - 0x81ed, 0x080c, 0x9e42, 0x00ce, 0x080c, 0x9e42, 0x0005, 0x0026, - 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, - 0x1958, 0x2004, 0x6842, 0x0804, 0xa4d1, 0x00c6, 0x2d60, 0x080c, - 0xb750, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, - 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x83da, 0x080c, - 0x896d, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, - 0x090c, 0x0db4, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, - 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, - 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, - 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, - 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, - 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, - 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xbe9d, 0x080c, 0x896d, - 0x0010, 0x080c, 0x9e42, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1904, 0xa53c, 0x700c, 0x6210, 0x00b6, - 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xa53c, 0x6038, 0x2068, - 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xa53c, - 0x9286, 0x0002, 0x0904, 0xa53c, 0x9286, 0x0000, 0x05e8, 0x6808, - 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, - 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, - 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, - 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, - 0x2048, 0x080c, 0xbb2c, 0x090c, 0x0db4, 0xa87b, 0x0003, 0x009e, - 0x080c, 0xc1e6, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x080c, 0x83da, 0x080c, 0x896d, 0x00ce, 0x0030, 0x6038, 0x2070, - 0x2001, 0x1958, 0x2004, 0x7042, 0x080c, 0x9e42, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, - 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, - 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, - 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xae20, 0x002e, - 0x003e, 0x015e, 0x009e, 0x1904, 0xa5ab, 0x0096, 0x0156, 0x0036, - 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, - 0x080c, 0xae20, 0x002e, 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, - 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, - 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xa246, 0x0096, 0x2048, - 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x122f, 0x080c, - 0xa345, 0x0130, 0x00fe, 0x009e, 0x080c, 0x9e42, 0x00be, 0x0005, - 0x080c, 0xa7d1, 0x0cb8, 0x2b78, 0x00f6, 0x080c, 0x2fdc, 0x080c, - 0xc241, 0x00fe, 0x00c6, 0x080c, 0x9dec, 0x2f00, 0x6012, 0x6017, - 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, - 0x0007, 0x080c, 0x6198, 0x080c, 0x61c4, 0x080c, 0x8422, 0x080c, - 0x896d, 0x00ce, 0x0804, 0xa57e, 0x2100, 0x91b2, 0x0053, 0x1a0c, - 0x0db4, 0x91b2, 0x0040, 0x1a04, 0xa634, 0x0002, 0xa622, 0xa622, - 0xa618, 0xa622, 0xa622, 0xa622, 0xa616, 0xa616, 0xa616, 0xa616, - 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, - 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, - 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa622, 0xa616, 0xa622, - 0xa622, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa618, 0xa616, - 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, - 0xa622, 0xa622, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, 0xa616, - 0xa616, 0xa616, 0xa616, 0xa622, 0xa616, 0xa616, 0x080c, 0x0db4, - 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8bc, 0xc08c, 0xb8be, 0x00be, - 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, - 0x080c, 0x8422, 0x0010, 0x080c, 0x83da, 0x0126, 0x2091, 0x8000, - 0x080c, 0x896d, 0x012e, 0x0005, 0x2600, 0x0002, 0xa648, 0xa648, - 0xa648, 0xa622, 0xa622, 0xa648, 0xa648, 0xa648, 0xa648, 0xa622, - 0xa648, 0xa622, 0xa648, 0xa622, 0xa648, 0xa648, 0xa648, 0xa648, - 0x080c, 0x0db4, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0db4, 0x91b6, - 0x0013, 0x0904, 0xa70c, 0x91b6, 0x0027, 0x1904, 0xa6c7, 0x080c, - 0x8861, 0x6004, 0x080c, 0xbd21, 0x01b0, 0x080c, 0xbd32, 0x01a8, - 0x908e, 0x0021, 0x0904, 0xa6c4, 0x908e, 0x0022, 0x1130, 0x080c, - 0xa272, 0x0904, 0xa6c0, 0x0804, 0xa6c1, 0x908e, 0x003d, 0x0904, - 0xa6c4, 0x0804, 0xa6ba, 0x080c, 0x3005, 0x2001, 0x0007, 0x080c, - 0x6198, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xa7d1, - 0x9186, 0x007e, 0x1148, 0x2001, 0x1836, 0x2014, 0xc285, 0x080c, - 0x6f9b, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x0026, 0x2019, 0x0028, - 0x2110, 0x080c, 0xd803, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, - 0x2110, 0x2019, 0x0028, 0x080c, 0x8564, 0x0076, 0x903e, 0x080c, - 0x8452, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, - 0xd2bc, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0xc241, 0x0016, - 0x080c, 0xbf9e, 0x080c, 0x9e42, 0x001e, 0x080c, 0x30d7, 0x080c, - 0x896d, 0x0030, 0x080c, 0xbf9e, 0x080c, 0x9e42, 0x080c, 0x896d, - 0x0005, 0x080c, 0xa7d1, 0x0cb0, 0x080c, 0xa80d, 0x0c98, 0x9186, - 0x0014, 0x1db0, 0x080c, 0x8861, 0x6004, 0x908e, 0x0022, 0x1118, - 0x080c, 0xa272, 0x0d68, 0x080c, 0x2fdc, 0x080c, 0xc241, 0x080c, - 0xbd21, 0x1190, 0x080c, 0x3005, 0x6010, 0x00b6, 0x2058, 0xb9a0, - 0x00be, 0x080c, 0xa7d1, 0x9186, 0x007e, 0x1128, 0x2001, 0x1836, - 0x200c, 0xc185, 0x2102, 0x0870, 0x080c, 0xbd32, 0x1118, 0x080c, - 0xa7d1, 0x0840, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, - 0x2071, 0x1894, 0x2079, 0x0000, 0x080c, 0x336b, 0x00fe, 0x00ee, - 0x0804, 0xa6ba, 0x6004, 0x908e, 0x0021, 0x0d48, 0x908e, 0x0022, - 0x090c, 0xa7d1, 0x0804, 0xa6ba, 0x90b2, 0x0040, 0x1a04, 0xa7ba, - 0x2008, 0x0002, 0xa754, 0xa755, 0xa758, 0xa75b, 0xa75e, 0xa761, - 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, - 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, - 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, 0xa752, - 0xa764, 0xa76f, 0xa752, 0xa771, 0xa76f, 0xa752, 0xa752, 0xa752, - 0xa752, 0xa752, 0xa76f, 0xa76f, 0xa752, 0xa752, 0xa752, 0xa752, - 0xa752, 0xa752, 0xa752, 0xa752, 0xa7a1, 0xa76f, 0xa752, 0xa76b, - 0xa752, 0xa752, 0xa752, 0xa76c, 0xa752, 0xa752, 0xa752, 0xa76f, - 0xa798, 0xa752, 0x080c, 0x0db4, 0x00d0, 0x2001, 0x000b, 0x0410, - 0x2001, 0x0003, 0x00f8, 0x2001, 0x0005, 0x00e0, 0x2001, 0x0001, - 0x00c8, 0x2001, 0x0009, 0x00b0, 0x080c, 0x8861, 0x6003, 0x0005, - 0x080c, 0x896d, 0x0070, 0x0018, 0x0010, 0x080c, 0x6198, 0x0804, - 0xa7b2, 0x080c, 0x8861, 0x080c, 0xc244, 0x6003, 0x0004, 0x080c, - 0x896d, 0x0005, 0x080c, 0x6198, 0x080c, 0x8861, 0x6003, 0x0002, - 0x0036, 0x2019, 0x185e, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, - 0x1956, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x896d, 0x0c08, - 0x080c, 0x8861, 0x080c, 0xbf9e, 0x080c, 0x9e42, 0x080c, 0x896d, - 0x08c0, 0x00e6, 0x00f6, 0x2071, 0x1894, 0x2079, 0x0000, 0x080c, - 0x336b, 0x00fe, 0x00ee, 0x080c, 0x8861, 0x080c, 0x9e42, 0x080c, - 0x896d, 0x0838, 0x080c, 0x8861, 0x6003, 0x0002, 0x080c, 0xc244, - 0x0804, 0x896d, 0x2600, 0x2008, 0x0002, 0xa7cf, 0xa7cf, 0xa7cf, - 0xa7b2, 0xa7b2, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7b2, 0xa7cf, - 0xa7b2, 0xa7cf, 0xa7b2, 0xa7cf, 0xa7cf, 0xa7cf, 0xa7cf, 0x080c, - 0x0db4, 0x00e6, 0x0096, 0x0026, 0x0016, 0x080c, 0xbb2c, 0x0568, - 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, - 0x0056, 0x1148, 0x080c, 0x5138, 0x0130, 0x2001, 0x0000, 0x900e, - 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, - 0x080c, 0xc10b, 0x0090, 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, - 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, - 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, - 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, - 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, - 0x1a0c, 0x0db4, 0x6604, 0x96b6, 0x004d, 0x1120, 0x080c, 0xc02a, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, 0xc073, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, 0xc09f, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, 0xbfc0, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, 0xbd70, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, 0xbdb1, - 0x0804, 0xa895, 0x6604, 0x96b6, 0x001f, 0x1118, 0x080c, 0xa21a, - 0x04e0, 0x6604, 0x96b6, 0x0000, 0x1118, 0x080c, 0xa542, 0x04a8, - 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, 0xa253, 0x0470, 0x6604, - 0x96b6, 0x0035, 0x1118, 0x080c, 0xa363, 0x0438, 0x6604, 0x96b6, - 0x0039, 0x1118, 0x080c, 0xa4d7, 0x0400, 0x6604, 0x96b6, 0x003d, - 0x1118, 0x080c, 0xa28b, 0x00c8, 0x6604, 0x96b6, 0x0044, 0x1118, - 0x080c, 0xa2c7, 0x0090, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, - 0xa2f2, 0x0058, 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, - 0x0016, 0x1128, 0x00be, 0x0804, 0xab55, 0x00be, 0x0005, 0x080c, - 0x9ed7, 0x0cd8, 0xa8b2, 0xa8b5, 0xa8b2, 0xa8f9, 0xa8b2, 0xaa89, - 0xab62, 0xa8b2, 0xa8b2, 0xab2f, 0xa8b2, 0xab43, 0x0096, 0x080c, - 0x1511, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, - 0x0804, 0x9e42, 0xa001, 0xa001, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x708c, 0x9086, 0x0074, 0x1540, 0x080c, 0xd28d, 0x11b0, 0x6010, - 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, - 0xc0c5, 0xb802, 0x00e9, 0x00be, 0x2001, 0x0006, 0x080c, 0x6198, - 0x080c, 0x3005, 0x080c, 0x9e42, 0x0088, 0x2001, 0x000a, 0x080c, - 0x6198, 0x080c, 0x3005, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x8422, 0x080c, 0x896d, 0x0010, 0x080c, 0xaa74, 0x00ee, 0x0005, - 0x00d6, 0xb800, 0xd084, 0x0158, 0x9006, 0x080c, 0x6184, 0x2069, - 0x1853, 0x6804, 0x0020, 0x2001, 0x0006, 0x080c, 0x61c4, 0x00de, - 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1823, 0x2204, 0x9086, - 0x0074, 0x1904, 0xaa4b, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, - 0x1120, 0x080c, 0xaca6, 0x0804, 0xa9b0, 0x00d6, 0x080c, 0x6f9b, - 0x0198, 0x0026, 0x2011, 0x0010, 0x080c, 0x658f, 0x002e, 0x05c8, - 0x080c, 0x53a3, 0x1540, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x00f8, 0x0026, 0x2011, 0x8008, 0x080c, - 0x658f, 0x002e, 0x0530, 0x6014, 0x2048, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, - 0x080c, 0xc10b, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, - 0x3005, 0x080c, 0x9e42, 0x001e, 0x080c, 0x30d7, 0x00de, 0x0804, - 0xaa4e, 0x00de, 0x080c, 0xac9b, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, + 0x0005, 0x9ef9, 0xb51d, 0x9ef9, 0x9ef9, 0x9ef9, 0x9ef9, 0x9ef9, + 0x9ef9, 0xb4bf, 0xb69f, 0x9ef9, 0xb55e, 0xb5dd, 0xb55e, 0xb5dd, + 0x9ef9, 0x080c, 0x0db4, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0db4, + 0x6000, 0x0002, 0x9f15, 0xae8d, 0xaf72, 0xb0a2, 0xb24d, 0x9f15, + 0x9f15, 0x9f15, 0xae61, 0xb44b, 0xb44e, 0x9f15, 0x9f15, 0x9f15, + 0x9f15, 0xb47d, 0x9f15, 0x9f15, 0x9f15, 0x080c, 0x0db4, 0x0066, + 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db4, 0x0013, 0x006e, 0x0005, + 0x9f30, 0x9f30, 0x9f73, 0xa012, 0xa0a7, 0x9f30, 0x9f30, 0x9f30, + 0x9f32, 0x9f30, 0x9f30, 0x9f30, 0x9f30, 0x9f30, 0x9f30, 0x9f30, + 0x080c, 0x0db4, 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, + 0x0db4, 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, + 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, + 0xa846, 0xa8b0, 0xa84a, 0x9006, 0xa836, 0xa83a, 0xa884, 0x9092, + 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, + 0x621a, 0x009e, 0x2c10, 0x080c, 0x1a69, 0x080c, 0x845d, 0x0126, + 0x2091, 0x8000, 0x080c, 0x8a68, 0x012e, 0x0005, 0x6010, 0x00b6, + 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, 0xa0c9, 0x080c, 0xc253, + 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, + 0x7a8c, 0x6014, 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, + 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, + 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, + 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, + 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, + 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, + 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, + 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0x9fda, 0x9fda, 0x9fd5, + 0x9fd8, 0x9fda, 0x9fd2, 0x9fc5, 0x9fc5, 0x9fc5, 0x9fc5, 0x9fc5, + 0x9fc5, 0x9fc5, 0x9fc5, 0x9fc5, 0x9fc5, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, + 0x080c, 0x0db4, 0x080c, 0xaa85, 0x0028, 0x080c, 0xaba8, 0x0010, + 0x080c, 0xac97, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, + 0x2c00, 0xa896, 0x000e, 0x080c, 0xa187, 0x0530, 0xa804, 0xa80e, + 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, + 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, + 0xadd8, 0x2031, 0x0000, 0x2041, 0x1249, 0x080c, 0xa332, 0x0160, + 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, + 0x009e, 0x00de, 0x0804, 0x9e2f, 0x2001, 0x002c, 0x900e, 0x080c, + 0xa1ed, 0x0c70, 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, + 0x91b2, 0x0047, 0x0a0c, 0x0db4, 0x91b2, 0x0050, 0x1a0c, 0x0db4, + 0x9182, 0x0047, 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, + 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x83b1, + 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, + 0x1110, 0x0804, 0x9f73, 0x0005, 0xa045, 0xa045, 0xa047, 0xa07d, + 0xa045, 0xa045, 0xa045, 0xa045, 0xa090, 0x080c, 0x0db4, 0x00d6, + 0x0016, 0x0096, 0x080c, 0x893b, 0x080c, 0x8a68, 0x6003, 0x0004, + 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, + 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, + 0xa1ed, 0x080c, 0x9e2f, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, + 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, + 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, + 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, 0x080c, 0x893b, 0x00d6, + 0x0096, 0x6114, 0x2148, 0x080c, 0xbb3b, 0x0120, 0xa87b, 0x0006, + 0x080c, 0x68a0, 0x009e, 0x00de, 0x080c, 0x9e2f, 0x0804, 0x8a68, + 0x080c, 0x893b, 0x080c, 0x2fe7, 0x080c, 0xc250, 0x00d6, 0x0096, + 0x6114, 0x2148, 0x080c, 0xbb3b, 0x0120, 0xa87b, 0x0029, 0x080c, + 0x68a0, 0x009e, 0x00de, 0x080c, 0x9e2f, 0x0804, 0x8a68, 0x9182, + 0x0047, 0x0002, 0xa0b7, 0xa0b9, 0xa0b7, 0xa0b7, 0xa0b7, 0xa0b7, + 0xa0b7, 0xa0b7, 0xa0b7, 0xa0b7, 0xa0b7, 0xa0b7, 0xa0b9, 0x080c, + 0x0db4, 0x00d6, 0x0096, 0x080c, 0x1511, 0x6114, 0x2148, 0xa87b, + 0x0000, 0xa883, 0x0000, 0x080c, 0x68a0, 0x009e, 0x00de, 0x0804, + 0x9e2f, 0x0026, 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, + 0x0006, 0x080c, 0x0feb, 0x000e, 0x090c, 0x0db4, 0xa960, 0x21e8, + 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, + 0xa87a, 0x2079, 0x1800, 0x798c, 0x9188, 0x0018, 0x918c, 0x0fff, + 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, + 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, 0x2011, 0x001f, + 0x080c, 0xb724, 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, + 0x080c, 0xb724, 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, + 0x0f9d, 0x080c, 0x0feb, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, + 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, + 0x001b, 0x080c, 0xb724, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, + 0x2950, 0x2011, 0x001b, 0x080c, 0xb724, 0x0c18, 0x2001, 0x0205, + 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, + 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, + 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, + 0x0006, 0x080c, 0x68a0, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, + 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, + 0x00f6, 0x0096, 0x0006, 0x080c, 0x0feb, 0x000e, 0x090c, 0x0db4, + 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, + 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, 0x1800, 0x798c, 0x810c, + 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, + 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, + 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, + 0x0000, 0x080c, 0x68a0, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, + 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, + 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, + 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, + 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, + 0x0096, 0x080c, 0x0feb, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, + 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, + 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, + 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, + 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, + 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, + 0x0904, 0xa19c, 0x0804, 0xa19e, 0x9085, 0x0001, 0x7817, 0x0000, + 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, + 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, 0x6893, 0x009e, 0x003e, + 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0x9e2f, 0x0030, + 0x91b6, 0x0016, 0x190c, 0x0db4, 0x080c, 0x9e2f, 0x0005, 0x20a9, + 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, + 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, 0x0136, 0x9080, 0x001b, + 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, 0x23a0, + 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, 0x0006, + 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, 0x8318, + 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xbb3b, 0x0130, 0x6014, + 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, 0x9e2f, + 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, 0x6010, + 0x00b6, 0x2058, 0xb8bf, 0x0000, 0x00be, 0x6014, 0x9005, 0x0130, + 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, 0x9e2f, + 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, 0x0006, + 0x0016, 0x080c, 0xc23b, 0x0188, 0x6014, 0x9005, 0x1170, 0x600b, + 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, 0x080c, + 0xa61c, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, 0x0cd0, + 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, 0x0000, + 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, + 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, + 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, 0xa860, + 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, + 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, + 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0x080c, + 0x9e2f, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, 0x7030, + 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, + 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, 0x2011, + 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xb724, 0x080c, + 0xbb3b, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, 0xa8e2, + 0xa867, 0x0103, 0x080c, 0x9e2f, 0x001e, 0x009e, 0x0005, 0x0016, + 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, + 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, + 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xb724, + 0x009e, 0x080c, 0xbb3b, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, + 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0x9e2f, 0x009e, + 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, + 0x1118, 0x080c, 0xa7cd, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, + 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, + 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, + 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x122f, 0x0019, 0x0d08, + 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x0feb, 0x000e, 0x01b0, + 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, + 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, + 0x2940, 0x080c, 0x10d5, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, + 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, + 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, + 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, + 0x0016, 0x2009, 0x0035, 0x080c, 0xc1b3, 0x001e, 0x1158, 0x622c, + 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, + 0x0006, 0x0128, 0x080c, 0x9e2f, 0x0020, 0x0039, 0x0010, 0x080c, + 0xa451, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, + 0x9186, 0x0015, 0x0904, 0xa439, 0x918e, 0x0016, 0x1904, 0xa44f, + 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, + 0x1904, 0xa413, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, + 0xa3f6, 0x0804, 0xa44d, 0x6808, 0x9086, 0xffff, 0x1904, 0xa43b, + 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, + 0x9105, 0x1904, 0xa43b, 0x6824, 0xd084, 0x1904, 0xa43b, 0xd0b4, + 0x0158, 0x0016, 0x2001, 0x195e, 0x200c, 0x6018, 0x9102, 0x9082, + 0x0005, 0x001e, 0x1a04, 0xa43b, 0x080c, 0xbd24, 0x685c, 0xa882, + 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, + 0x2001, 0x000a, 0x080c, 0x8277, 0xa884, 0x920a, 0x0208, 0x8011, + 0xaa86, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xb84e, + 0x00ce, 0x0804, 0xa44d, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, + 0x5d61, 0x0010, 0x080c, 0x610c, 0x00ce, 0x1904, 0xa43b, 0x00c6, + 0x2d60, 0x080c, 0x9e2f, 0x00ce, 0x0804, 0xa44d, 0x00c6, 0x080c, + 0x9e7c, 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xbfb5, + 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9e2f, 0x00ce, + 0x080c, 0x9ea9, 0x00ce, 0x0804, 0xa44d, 0x2001, 0x1960, 0x2004, + 0x6842, 0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, + 0x00b6, 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, + 0xa87b, 0x0003, 0x080c, 0xc1f5, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x080c, 0x83f8, 0x080c, 0x898b, 0x00ce, 0x00e8, + 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, 0x1960, 0x2004, 0x6842, + 0x00a0, 0x0479, 0x00a0, 0x89ff, 0x090c, 0x0db4, 0x00c6, 0x00d6, + 0x2d60, 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x66bb, 0x080c, + 0xbd24, 0x080c, 0x9e5f, 0x00de, 0x00ce, 0x080c, 0x9e2f, 0x009e, + 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, 0x1960, 0x2004, 0x6842, + 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, + 0xd7c1, 0x080c, 0x820b, 0x080c, 0x9e2f, 0x00ce, 0x080c, 0x9e2f, + 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, + 0x0130, 0x2001, 0x1960, 0x2004, 0x6842, 0x0804, 0xa4cb, 0x00c6, + 0x2d60, 0x080c, 0xb74f, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, + 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, + 0x83f8, 0x080c, 0x898b, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, + 0x01a8, 0x89ff, 0x090c, 0x0db4, 0x6800, 0x9086, 0x0004, 0x1190, + 0xa87c, 0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, + 0xc0fc, 0xa882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, + 0x6832, 0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, + 0xd0f4, 0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, + 0x1d68, 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, + 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xbeac, + 0x080c, 0x898b, 0x0010, 0x080c, 0x9e2f, 0x004e, 0x003e, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, + 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xa536, 0x700c, + 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xa536, + 0x6038, 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, + 0x0904, 0xa536, 0x9286, 0x0002, 0x0904, 0xa536, 0x9286, 0x0000, + 0x05e8, 0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, + 0x0015, 0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, + 0x6104, 0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, + 0x004d, 0x0190, 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, + 0x6014, 0x0096, 0x2048, 0x080c, 0xbb3b, 0x090c, 0x0db4, 0xa87b, + 0x0003, 0x009e, 0x080c, 0xc1f5, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x080c, 0x83f8, 0x080c, 0x898b, 0x00ce, 0x0030, + 0x6038, 0x2070, 0x2001, 0x1960, 0x2004, 0x7042, 0x080c, 0x9e2f, + 0x002e, 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, + 0x2048, 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, + 0xbc00, 0xc48c, 0xbc02, 0x0460, 0x0096, 0x0156, 0x0036, 0x0026, + 0x2b48, 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, + 0xae1c, 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xa5a5, 0x0096, + 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, + 0x20a9, 0x0004, 0x080c, 0xae1c, 0x002e, 0x003e, 0x015e, 0x009e, + 0x15a0, 0x7238, 0xba0a, 0x733c, 0xbb0e, 0xbc00, 0xc48d, 0xbc02, + 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xa233, + 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, + 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, + 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, + 0x122f, 0x080c, 0xa332, 0x0130, 0x00fe, 0x009e, 0x080c, 0x9e2f, + 0x00be, 0x0005, 0x080c, 0xa7cd, 0x0cb8, 0x2b78, 0x00f6, 0x080c, + 0x2fe7, 0x080c, 0xc250, 0x00fe, 0x00c6, 0x080c, 0x9dd9, 0x2f00, + 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x2001, 0x0007, 0x080c, 0x61a7, 0x080c, 0x61d3, 0x080c, + 0x8440, 0x080c, 0x898b, 0x00ce, 0x0804, 0xa578, 0x2100, 0x91b2, + 0x0053, 0x1a0c, 0x0db4, 0x91b2, 0x0040, 0x1a04, 0xa62e, 0x0002, + 0xa61c, 0xa61c, 0xa612, 0xa61c, 0xa61c, 0xa61c, 0xa610, 0xa610, + 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, + 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, + 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa61c, + 0xa610, 0xa61c, 0xa61c, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, + 0xa612, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, + 0xa610, 0xa610, 0xa61c, 0xa61c, 0xa610, 0xa610, 0xa610, 0xa610, + 0xa610, 0xa610, 0xa610, 0xa610, 0xa610, 0xa61c, 0xa610, 0xa610, + 0x080c, 0x0db4, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8bc, 0xc08c, + 0xb8be, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, + 0x0032, 0x0118, 0x080c, 0x8440, 0x0010, 0x080c, 0x83f8, 0x0126, + 0x2091, 0x8000, 0x080c, 0x898b, 0x012e, 0x0005, 0x2600, 0x0002, + 0xa642, 0xa642, 0xa642, 0xa61c, 0xa61c, 0xa642, 0xa642, 0xa642, + 0xa642, 0xa61c, 0xa642, 0xa61c, 0xa642, 0xa61c, 0xa642, 0xa642, + 0xa642, 0xa642, 0x080c, 0x0db4, 0x6004, 0x90b2, 0x0053, 0x1a0c, + 0x0db4, 0x91b6, 0x0013, 0x0904, 0xa706, 0x91b6, 0x0027, 0x1904, + 0xa6c1, 0x080c, 0x887f, 0x6004, 0x080c, 0xbd30, 0x01b0, 0x080c, + 0xbd41, 0x01a8, 0x908e, 0x0021, 0x0904, 0xa6be, 0x908e, 0x0022, + 0x1130, 0x080c, 0xa25f, 0x0904, 0xa6ba, 0x0804, 0xa6bb, 0x908e, + 0x003d, 0x0904, 0xa6be, 0x0804, 0xa6b4, 0x080c, 0x3010, 0x2001, + 0x0007, 0x080c, 0x61a7, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, + 0x080c, 0xa7cd, 0x9186, 0x007e, 0x1148, 0x2001, 0x1836, 0x2014, + 0xc285, 0x080c, 0x6faa, 0x1108, 0xc2ad, 0x2202, 0x0036, 0x0026, + 0x2019, 0x0028, 0x2110, 0x080c, 0xd81c, 0x002e, 0x003e, 0x0016, + 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x8582, 0x0076, + 0x903e, 0x080c, 0x8470, 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, + 0x2c08, 0x080c, 0xd2d5, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, + 0xc250, 0x0016, 0x080c, 0xbfad, 0x080c, 0x9e2f, 0x001e, 0x080c, + 0x30e2, 0x080c, 0x898b, 0x0030, 0x080c, 0xbfad, 0x080c, 0x9e2f, + 0x080c, 0x898b, 0x0005, 0x080c, 0xa7cd, 0x0cb0, 0x080c, 0xa809, + 0x0c98, 0x9186, 0x0014, 0x1db0, 0x080c, 0x887f, 0x6004, 0x908e, + 0x0022, 0x1118, 0x080c, 0xa25f, 0x0d68, 0x080c, 0x2fe7, 0x080c, + 0xc250, 0x080c, 0xbd30, 0x1190, 0x080c, 0x3010, 0x6010, 0x00b6, + 0x2058, 0xb9a0, 0x00be, 0x080c, 0xa7cd, 0x9186, 0x007e, 0x1128, + 0x2001, 0x1836, 0x200c, 0xc185, 0x2102, 0x0870, 0x080c, 0xbd41, + 0x1118, 0x080c, 0xa7cd, 0x0840, 0x6004, 0x908e, 0x0032, 0x1160, + 0x00e6, 0x00f6, 0x2071, 0x189c, 0x2079, 0x0000, 0x080c, 0x3376, + 0x00fe, 0x00ee, 0x0804, 0xa6b4, 0x6004, 0x908e, 0x0021, 0x0d48, + 0x908e, 0x0022, 0x090c, 0xa7cd, 0x0804, 0xa6b4, 0x90b2, 0x0040, + 0x1a04, 0xa7b6, 0x2008, 0x0002, 0xa74e, 0xa74f, 0xa752, 0xa755, + 0xa758, 0xa75b, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, + 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, + 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, + 0xa74c, 0xa74c, 0xa75e, 0xa76b, 0xa74c, 0xa76d, 0xa76b, 0xa74c, + 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa76b, 0xa76b, 0xa74c, 0xa74c, + 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa74c, 0xa79d, 0xa76b, + 0xa74c, 0xa767, 0xa74c, 0xa74c, 0xa74c, 0xa768, 0xa74c, 0xa74c, + 0xa74c, 0xa76b, 0xa794, 0xa74c, 0x080c, 0x0db4, 0x00e0, 0x2001, + 0x000b, 0x0420, 0x2001, 0x0003, 0x0408, 0x2001, 0x0005, 0x00f0, + 0x2001, 0x0001, 0x00d8, 0x2001, 0x0009, 0x00c0, 0x080c, 0x887f, + 0x6003, 0x0005, 0x080c, 0xc253, 0x080c, 0x898b, 0x0070, 0x0018, + 0x0010, 0x080c, 0x61a7, 0x0804, 0xa7ae, 0x080c, 0x887f, 0x080c, + 0xc253, 0x6003, 0x0004, 0x080c, 0x898b, 0x0005, 0x080c, 0x61a7, + 0x080c, 0x887f, 0x6003, 0x0002, 0x0036, 0x2019, 0x1866, 0x2304, + 0x9084, 0xff00, 0x1120, 0x2001, 0x195e, 0x201c, 0x0040, 0x8007, + 0x909a, 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, + 0x003e, 0x080c, 0x898b, 0x0c08, 0x080c, 0x887f, 0x080c, 0xbfad, + 0x080c, 0x9e2f, 0x080c, 0x898b, 0x08c0, 0x00e6, 0x00f6, 0x2071, + 0x189c, 0x2079, 0x0000, 0x080c, 0x3376, 0x00fe, 0x00ee, 0x080c, + 0x887f, 0x080c, 0x9e2f, 0x080c, 0x898b, 0x0838, 0x080c, 0x887f, + 0x6003, 0x0002, 0x080c, 0xc253, 0x0804, 0x898b, 0x2600, 0x2008, + 0x0002, 0xa7cb, 0xa7cb, 0xa7cb, 0xa7ae, 0xa7ae, 0xa7cb, 0xa7cb, + 0xa7cb, 0xa7cb, 0xa7ae, 0xa7cb, 0xa7ae, 0xa7cb, 0xa7ae, 0xa7cb, + 0xa7cb, 0xa7cb, 0xa7cb, 0x080c, 0x0db4, 0x00e6, 0x0096, 0x0026, + 0x0016, 0x080c, 0xbb3b, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, + 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x5143, + 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, + 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xc11a, 0x0090, 0xa868, + 0xd0fc, 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, + 0x0168, 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, + 0x0100, 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, + 0x0cc0, 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, + 0xa823, 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, + 0x9084, 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0db4, 0x6604, 0x96b6, + 0x004d, 0x1120, 0x080c, 0xc039, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x0043, 0x1120, 0x080c, 0xc082, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x004b, 0x1120, 0x080c, 0xc0ae, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x0033, 0x1120, 0x080c, 0xbfcf, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x0028, 0x1120, 0x080c, 0xbd7f, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x0029, 0x1120, 0x080c, 0xbdc0, 0x0804, 0xa891, 0x6604, 0x96b6, + 0x001f, 0x1118, 0x080c, 0xa207, 0x04e0, 0x6604, 0x96b6, 0x0000, + 0x1118, 0x080c, 0xa53c, 0x04a8, 0x6604, 0x96b6, 0x0022, 0x1118, + 0x080c, 0xa240, 0x0470, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, + 0xa350, 0x0438, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xa4d1, + 0x0400, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xa278, 0x00c8, + 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xa2b4, 0x0090, 0x6604, + 0x96b6, 0x0049, 0x1118, 0x080c, 0xa2df, 0x0058, 0x91b6, 0x0015, + 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, + 0xab51, 0x00be, 0x0005, 0x080c, 0x9ec4, 0x0cd8, 0xa8ae, 0xa8b1, + 0xa8ae, 0xa8f5, 0xa8ae, 0xaa85, 0xab5e, 0xa8ae, 0xa8ae, 0xab2b, + 0xa8ae, 0xab3f, 0x0096, 0x080c, 0x1511, 0x6014, 0x2048, 0xa800, + 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0x9e2f, 0xa001, 0xa001, + 0x0005, 0x00e6, 0x2071, 0x1800, 0x708c, 0x9086, 0x0074, 0x1540, + 0x080c, 0xd2a6, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, + 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, 0x00e9, 0x00be, + 0x2001, 0x0006, 0x080c, 0x61a7, 0x080c, 0x3010, 0x080c, 0x9e2f, + 0x0088, 0x2001, 0x000a, 0x080c, 0x61a7, 0x080c, 0x3010, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x8440, 0x080c, 0x898b, 0x0010, + 0x080c, 0xaa70, 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0158, + 0x9006, 0x080c, 0x6193, 0x2069, 0x185b, 0x6804, 0x0020, 0x2001, + 0x0006, 0x080c, 0x61d3, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, + 0x2011, 0x1823, 0x2204, 0x9086, 0x0074, 0x1904, 0xaa47, 0x6010, + 0x2058, 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xaca2, 0x0804, + 0xa9ac, 0x00d6, 0x080c, 0x6faa, 0x0198, 0x0026, 0x2011, 0x0010, + 0x080c, 0x659e, 0x002e, 0x05c8, 0x080c, 0x53ae, 0x1540, 0x6014, + 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x00f8, + 0x0026, 0x2011, 0x8008, 0x080c, 0x659e, 0x002e, 0x0530, 0x6014, + 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, + 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, 0xc11a, 0x0040, 0x6014, + 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, + 0x2058, 0xb9a0, 0x0016, 0x080c, 0x3010, 0x080c, 0x9e2f, 0x001e, + 0x080c, 0x30e2, 0x00de, 0x0804, 0xaa4a, 0x00de, 0x080c, 0xac97, + 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, + 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc11a, 0x0030, + 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, + 0x080c, 0x61a7, 0x080c, 0x3010, 0x080c, 0x9e2f, 0x0804, 0xaa4a, + 0x080c, 0xaa58, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, + 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, + 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc11a, 0x08f8, 0x080c, + 0xaa4e, 0x0160, 0x9006, 0x080c, 0x6193, 0x2001, 0x0004, 0x080c, + 0x61d3, 0x2001, 0x0007, 0x080c, 0x61a7, 0x08a0, 0x2001, 0x0004, + 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x8440, + 0x080c, 0x898b, 0x0804, 0xaa4a, 0xb85c, 0xd0e4, 0x01d0, 0x080c, + 0xbf4f, 0x080c, 0x6faa, 0x0118, 0xd0dc, 0x1904, 0xa96e, 0x2011, + 0x1836, 0x2204, 0xc0ad, 0x2012, 0x2001, 0x0002, 0x00f6, 0x2079, + 0x0100, 0x78e3, 0x0000, 0x080c, 0x26e4, 0x78e2, 0x00fe, 0x0804, + 0xa96e, 0x080c, 0xbf8c, 0x2011, 0x1836, 0x2204, 0xc0a5, 0x2012, + 0x0006, 0x080c, 0xd3ff, 0x000e, 0x1904, 0xa96e, 0xc0b5, 0x2012, + 0x2001, 0x0006, 0x080c, 0x61a7, 0x9006, 0x080c, 0x6193, 0x00c6, + 0x2001, 0x180f, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, + 0x00e6, 0x2071, 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707a, + 0x7010, 0x78ea, 0x707e, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, + 0x780e, 0x00fe, 0x080c, 0x26b9, 0x00f6, 0x2100, 0x900e, 0x080c, + 0x2670, 0x795a, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, + 0x00c8, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, + 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26b9, 0x00f6, + 0x2079, 0x1800, 0x797e, 0x2100, 0x900e, 0x080c, 0x2670, 0x795a, + 0x00fe, 0x8108, 0x080c, 0x61f6, 0x2b00, 0x00ce, 0x1904, 0xa96e, + 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, + 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, + 0x2001, 0x0002, 0x080c, 0x61a7, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x8440, 0x080c, 0x898b, 0x0018, 0x080c, + 0xa7cd, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, + 0x2004, 0xd0a4, 0x0120, 0x2001, 0x185c, 0x2004, 0xd0ac, 0x0005, + 0x00e6, 0x080c, 0xd875, 0x0190, 0x2071, 0x0260, 0x7108, 0x720c, + 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, 0x2058, + 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, 0x0005, + 0x2030, 0x2001, 0x0007, 0x080c, 0x61a7, 0x080c, 0x53ae, 0x1120, + 0x2001, 0x0007, 0x080c, 0x61d3, 0x080c, 0x3010, 0x6020, 0x9086, + 0x000a, 0x1108, 0x0005, 0x0804, 0x9e2f, 0x00b6, 0x00e6, 0x0026, + 0x0016, 0x2071, 0x1800, 0x708c, 0x9086, 0x0014, 0x1904, 0xab22, + 0x00d6, 0x080c, 0x6faa, 0x0198, 0x0026, 0x2011, 0x0010, 0x080c, + 0x659e, 0x002e, 0x05c8, 0x080c, 0x53ae, 0x1540, 0x6014, 0x2048, + 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x00f8, 0x0026, + 0x2011, 0x8008, 0x080c, 0x659e, 0x002e, 0x0530, 0x6014, 0x2048, + 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, + 0x900e, 0x2011, 0x4009, 0x080c, 0xc11a, 0x0040, 0x6014, 0x2048, + 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, + 0xb9a0, 0x0016, 0x080c, 0x3010, 0x080c, 0x9e2f, 0x001e, 0x080c, + 0x30e2, 0x00de, 0x0804, 0xab26, 0x00de, 0x080c, 0x53ae, 0x1170, + 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, + 0x2021, 0x0006, 0x080c, 0x4a91, 0x004e, 0x003e, 0x00d6, 0x6010, + 0x2058, 0x080c, 0x62f1, 0x080c, 0xa8e4, 0x00de, 0x080c, 0xad68, + 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, + 0x080c, 0x61a7, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xc10b, 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, 0x6198, 0x080c, 0x3005, - 0x080c, 0x9e42, 0x0804, 0xaa4e, 0x080c, 0xaa5c, 0x6014, 0x9005, - 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, - 0x080c, 0xc10b, 0x08f8, 0x080c, 0xaa52, 0x0160, 0x9006, 0x080c, - 0x6184, 0x2001, 0x0004, 0x080c, 0x61c4, 0x2001, 0x0007, 0x080c, - 0x6198, 0x08a0, 0x2001, 0x0004, 0x080c, 0x6198, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x8422, 0x080c, 0x896d, 0x0804, 0xaa4e, - 0xb85c, 0xd0e4, 0x01d0, 0x080c, 0xbf40, 0x080c, 0x6f9b, 0x0118, - 0xd0dc, 0x1904, 0xa972, 0x2011, 0x1836, 0x2204, 0xc0ad, 0x2012, - 0x2001, 0x0002, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, - 0x26d9, 0x78e2, 0x00fe, 0x0804, 0xa972, 0x080c, 0xbf7d, 0x2011, - 0x1836, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xd3e6, 0x000e, - 0x1904, 0xa972, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x6198, - 0x9006, 0x080c, 0x6184, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, - 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, - 0x9084, 0x00ff, 0x78e6, 0x707a, 0x7010, 0x78ea, 0x707e, 0x908c, - 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26ae, - 0x00f6, 0x2100, 0x900e, 0x080c, 0x2665, 0x795a, 0x00fe, 0x9186, - 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, - 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, 0x780e, - 0x00fe, 0x080c, 0x26ae, 0x00f6, 0x2079, 0x1800, 0x797e, 0x2100, - 0x900e, 0x080c, 0x2665, 0x795a, 0x00fe, 0x8108, 0x080c, 0x61e7, - 0x2b00, 0x00ce, 0x1904, 0xa972, 0x6012, 0x2009, 0x180f, 0x210c, - 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, - 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, 0x0002, 0x080c, 0x6198, - 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8422, - 0x080c, 0x896d, 0x0018, 0x080c, 0xa7d1, 0x0431, 0x00de, 0x009e, - 0x00be, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, - 0x1854, 0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xd85c, 0x0190, - 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, - 0xff00, 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, - 0xb912, 0xba16, 0x00ee, 0x0005, 0x2030, 0x2001, 0x0007, 0x080c, - 0x6198, 0x080c, 0x53a3, 0x1120, 0x2001, 0x0007, 0x080c, 0x61c4, - 0x080c, 0x3005, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, - 0x9e42, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x708c, - 0x9086, 0x0014, 0x1904, 0xab26, 0x00d6, 0x080c, 0x6f9b, 0x0198, - 0x0026, 0x2011, 0x0010, 0x080c, 0x658f, 0x002e, 0x05c8, 0x080c, - 0x53a3, 0x1540, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0xdead, 0x00f8, 0x0026, 0x2011, 0x8008, 0x080c, 0x658f, - 0x002e, 0x0530, 0x6014, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, - 0xc10b, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x3005, - 0x080c, 0x9e42, 0x001e, 0x080c, 0x30d7, 0x00de, 0x0804, 0xab2a, - 0x00de, 0x080c, 0x53a3, 0x1170, 0x6014, 0x9005, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4a86, - 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, 0x62e2, 0x080c, - 0xa8e8, 0x00de, 0x080c, 0xad6c, 0x1588, 0x6010, 0x2058, 0xb890, - 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x6198, 0x0096, 0x6014, - 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xc10b, 0x0060, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0xa807, 0x0000, - 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, 0x3005, 0x6020, - 0x9086, 0x000a, 0x0138, 0x080c, 0x9e42, 0x0020, 0x080c, 0xa7d1, - 0x080c, 0xaa74, 0x001e, 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, - 0x1823, 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, - 0x6198, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x8422, 0x0804, - 0x896d, 0x0804, 0xaa74, 0x2030, 0x2011, 0x1823, 0x2204, 0x9086, - 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, - 0x6198, 0x0804, 0x9e42, 0x0804, 0xaa74, 0x0002, 0xa8b2, 0xab6d, - 0xa8b2, 0xabac, 0xa8b2, 0xac57, 0xab62, 0xa8b2, 0xa8b2, 0xac6a, - 0xa8b2, 0xac7a, 0x6604, 0x9686, 0x0003, 0x0904, 0xaa89, 0x96b6, - 0x001e, 0x1110, 0x080c, 0x9e42, 0x0005, 0x00b6, 0x00d6, 0x00c6, - 0x080c, 0xac8a, 0x11a0, 0x9006, 0x080c, 0x6184, 0x080c, 0x2fdc, - 0x080c, 0xc241, 0x2001, 0x0002, 0x080c, 0x6198, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x8422, 0x080c, 0x896d, 0x0408, 0x2009, - 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, - 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0xb842, 0x601b, 0x000a, - 0x0078, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x1900, - 0x1108, 0x08a0, 0x080c, 0x2fdc, 0x080c, 0xc241, 0x080c, 0xaa74, - 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, - 0x080c, 0xac98, 0x00d6, 0x2069, 0x194c, 0x2d04, 0x9005, 0x0168, - 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x181f, - 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, - 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x8422, 0x080c, 0x896d, 0x0804, 0xac27, - 0x080c, 0xbb2c, 0x01b0, 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, - 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, 0x0002, 0x080c, 0xc165, - 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, - 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, - 0xa7d1, 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, - 0x0510, 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x1118, 0x9686, 0x0009, 0x01b0, 0x9086, 0x1900, 0x1168, - 0x9686, 0x0009, 0x0180, 0x2001, 0x0004, 0x080c, 0x6198, 0x2001, - 0x0028, 0x601a, 0x6007, 0x0052, 0x0010, 0x080c, 0xaa74, 0x002e, - 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, - 0x080c, 0xbb2c, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, - 0xd0fc, 0x0108, 0x0c50, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, - 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, - 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, - 0x080c, 0x5c6d, 0x00ee, 0x0010, 0x080c, 0x2fdc, 0x0870, 0x080c, - 0xac98, 0x1160, 0x2001, 0x0004, 0x080c, 0x6198, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x8422, 0x0804, 0x896d, 0x080c, 0xa7d1, - 0x0804, 0xaa74, 0x0469, 0x1160, 0x2001, 0x0008, 0x080c, 0x6198, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x8422, 0x0804, 0x896d, - 0x0804, 0xaa74, 0x00e9, 0x1160, 0x2001, 0x000a, 0x080c, 0x6198, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x8422, 0x0804, 0x896d, - 0x0804, 0xaa74, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, - 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, 0x6110, 0x2158, - 0x080c, 0x6256, 0x001e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x00f6, - 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, 0x2009, 0x1836, - 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xad3e, 0x0560, 0x2009, - 0x1836, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6567, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xd54b, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2fa7, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x2dbd, 0x00ee, 0x00c6, 0x0156, - 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x30d7, 0x8108, 0x1f04, - 0xacdc, 0x015e, 0x00ce, 0x080c, 0xac9b, 0x2071, 0x0260, 0x2079, - 0x0200, 0x7817, 0x0001, 0x2001, 0x1836, 0x200c, 0xc1c5, 0x7018, - 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, - 0x7817, 0x0000, 0x2001, 0x1836, 0x2102, 0x2079, 0x0100, 0x2e04, - 0x9084, 0x00ff, 0x2069, 0x181e, 0x206a, 0x78e6, 0x0006, 0x8e70, - 0x2e04, 0x2069, 0x181f, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, - 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182b, 0x200a, 0x2200, - 0x9084, 0x00ff, 0x2008, 0x080c, 0x26ae, 0x080c, 0x6f9b, 0x0170, - 0x2071, 0x0260, 0x2069, 0x1952, 0x7048, 0x206a, 0x704c, 0x6806, - 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xbf40, 0x0040, 0x2001, - 0x0006, 0x080c, 0x6198, 0x080c, 0x3005, 0x080c, 0x9e42, 0x001e, - 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, - 0x0036, 0x00e6, 0x0156, 0x2019, 0x182b, 0x231c, 0x83ff, 0x01f0, - 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, - 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, - 0x2019, 0x000a, 0x080c, 0xae20, 0x1148, 0x2011, 0x027a, 0x20a9, - 0x0004, 0x2019, 0x0006, 0x080c, 0xae20, 0x1100, 0x015e, 0x00ee, - 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, - 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, - 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19c0, 0x252c, - 0x2021, 0x19c6, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7250, - 0x7070, 0x9202, 0x1a04, 0xadf8, 0x080c, 0xd57c, 0x0904, 0xadf1, - 0x6720, 0x9786, 0x0007, 0x0904, 0xadf1, 0x2500, 0x9c06, 0x0904, - 0xadf1, 0x2400, 0x9c06, 0x05e8, 0x3e08, 0x9186, 0x0002, 0x1148, - 0x6010, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x1580, 0x00c6, 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x190f, - 0x9786, 0x000a, 0x0148, 0x080c, 0xbd32, 0x1130, 0x00ce, 0x080c, - 0xa7d1, 0x080c, 0x9e72, 0x00e8, 0x6014, 0x2048, 0x080c, 0xbb2c, - 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0f9d, 0x009e, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6884, 0x080c, 0xbd15, 0x080c, 0x9e72, - 0x00ce, 0x9ce0, 0x0018, 0x7064, 0x9c02, 0x1210, 0x0804, 0xad9f, - 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, - 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, 0x080c, 0xd4f6, 0x0c30, - 0x9786, 0x000a, 0x0998, 0x0880, 0x220c, 0x2304, 0x9106, 0x1130, - 0x8210, 0x8318, 0x1f04, 0xae0c, 0x9006, 0x0005, 0x2304, 0x9102, - 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, 0x0005, - 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, - 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, 0x0001, - 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, 0x9006, - 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, 0x2001, - 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, 0x01ce, - 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0db4, 0x080c, - 0xbd21, 0x0120, 0x080c, 0xbd32, 0x0168, 0x0028, 0x080c, 0x3005, - 0x080c, 0xbd32, 0x0138, 0x080c, 0x8861, 0x080c, 0x9e42, 0x080c, - 0x896d, 0x0005, 0x080c, 0xa7d1, 0x0cb0, 0x9182, 0x0054, 0x1220, - 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xae81, 0xae81, 0xae81, - 0xae81, 0xae81, 0xae81, 0xae81, 0xae81, 0xae81, 0xae81, 0xae81, - 0xae83, 0xae83, 0xae83, 0xae83, 0xae81, 0xae81, 0xae81, 0xae83, - 0xae81, 0x080c, 0x0db4, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, - 0x080c, 0x83da, 0x0126, 0x2091, 0x8000, 0x080c, 0x896d, 0x012e, - 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, - 0xaf38, 0x9186, 0x0027, 0x1520, 0x080c, 0x8861, 0x080c, 0x2fdc, - 0x080c, 0xc241, 0x0096, 0x6114, 0x2148, 0x080c, 0xbb2c, 0x0198, - 0x080c, 0xbd32, 0x1118, 0x080c, 0xa7d1, 0x0068, 0xa867, 0x0103, - 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, - 0x6891, 0x080c, 0xbd15, 0x009e, 0x080c, 0x9e42, 0x0804, 0x896d, - 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x04a0, 0x9186, - 0x0046, 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, - 0x9186, 0x0048, 0x190c, 0x0db4, 0x2001, 0x0109, 0x2004, 0xd084, - 0x0508, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00f6, 0x00e6, 0x00c6, 0x2079, 0x19b7, 0x2071, 0x1800, 0x2061, - 0x0100, 0x080c, 0x82c6, 0x00ce, 0x00ee, 0x00fe, 0x003e, 0x002e, - 0x001e, 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, - 0x0804, 0xaf76, 0x0005, 0x0002, 0xaf12, 0xaf10, 0xaf10, 0xaf10, - 0xaf10, 0xaf10, 0xaf10, 0xaf10, 0xaf10, 0xaf10, 0xaf10, 0xaf2d, - 0xaf2d, 0xaf2d, 0xaf2d, 0xaf10, 0xaf2d, 0xaf10, 0xaf2d, 0xaf10, - 0x080c, 0x0db4, 0x080c, 0x8861, 0x0096, 0x6114, 0x2148, 0x080c, - 0xbb2c, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6891, 0x080c, 0xbd15, 0x009e, - 0x080c, 0x9e42, 0x080c, 0x896d, 0x0005, 0x080c, 0x8861, 0x080c, - 0xbd32, 0x090c, 0xa7d1, 0x080c, 0x9e42, 0x080c, 0x896d, 0x0005, - 0x0002, 0xaf4f, 0xaf4d, 0xaf4d, 0xaf4d, 0xaf4d, 0xaf4d, 0xaf4d, - 0xaf4d, 0xaf4d, 0xaf4d, 0xaf4d, 0xaf66, 0xaf66, 0xaf66, 0xaf66, - 0xaf4d, 0xaf70, 0xaf4d, 0xaf66, 0xaf4d, 0x080c, 0x0db4, 0x0096, - 0x080c, 0x8861, 0x6014, 0x2048, 0x2001, 0x1958, 0x2004, 0x6042, - 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c, 0x9085, 0x0400, - 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8, 0x080c, 0x8861, - 0x080c, 0xc244, 0x080c, 0xc249, 0x6003, 0x000f, 0x0804, 0x896d, - 0x080c, 0x8861, 0x080c, 0x9e42, 0x0804, 0x896d, 0x9182, 0x0054, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xaf92, 0xaf92, - 0xaf92, 0xaf92, 0xaf92, 0xaf94, 0xb071, 0xaf92, 0xb0a5, 0xaf92, - 0xaf92, 0xaf92, 0xaf92, 0xaf92, 0xaf92, 0xaf92, 0xaf92, 0xaf92, - 0xaf92, 0xb0a5, 0x080c, 0x0db4, 0x00b6, 0x0096, 0x6114, 0x2148, - 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010, 0x2058, 0xb800, - 0xd0bc, 0x1904, 0xb060, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb23a, - 0x080c, 0x66ac, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, - 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xb044, 0x080c, 0x9e42, 0x009e, - 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010, 0x2058, 0xb800, - 0xd0bc, 0x1904, 0xb048, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015, 0xa87c, 0xd0ac, - 0x0170, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, - 0x1118, 0x704c, 0x9206, 0x0118, 0xa992, 0xaa8e, 0xc6dc, 0x0038, - 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xa867, - 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, - 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, 0xaf9b, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xb725, 0x003e, - 0xd6cc, 0x0904, 0xafb0, 0x7154, 0xa98a, 0x81ff, 0x0904, 0xafb0, - 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, - 0x080c, 0xb725, 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xc1d1, - 0x0804, 0xafb0, 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, - 0x0c50, 0x00a6, 0x2950, 0x080c, 0xb6c4, 0x00ae, 0x080c, 0xc1d1, - 0x080c, 0xb715, 0x0804, 0xafb2, 0x080c, 0xbe2a, 0x0804, 0xafbf, - 0xa87c, 0xd0ac, 0x0904, 0xafcb, 0xa880, 0xd0bc, 0x1904, 0xafcb, - 0x7348, 0xa838, 0x9306, 0x11c8, 0x734c, 0xa834, 0x931e, 0x0904, - 0xafcb, 0xd6d4, 0x0190, 0xab38, 0x9305, 0x0904, 0xafcb, 0x0068, - 0xa87c, 0xd0ac, 0x0904, 0xafa3, 0xa838, 0xa934, 0x9105, 0x0904, - 0xafa3, 0xa880, 0xd0bc, 0x1904, 0xafa3, 0x080c, 0xbe64, 0x0804, - 0xafbf, 0x0096, 0x00f6, 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, - 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2048, 0xa87c, - 0xd0ac, 0x0140, 0x6003, 0x0002, 0x00fe, 0x009e, 0x0005, 0x2130, - 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, - 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac36, 0xab3a, 0xae46, - 0xad4a, 0x00fe, 0x6043, 0x0000, 0x2c10, 0x080c, 0x1a5e, 0x080c, - 0x843f, 0x080c, 0x8a4a, 0x009e, 0x0005, 0x0005, 0x9182, 0x0054, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb0c2, 0xb0c2, - 0xb0c2, 0xb0c2, 0xb0c2, 0xb0c4, 0xb15a, 0xb0c2, 0xb0c2, 0xb171, - 0xb1fd, 0xb0c2, 0xb0c2, 0xb0c2, 0xb0c2, 0xb212, 0xb0c2, 0xb0c2, - 0xb0c2, 0xb0c2, 0x080c, 0x0db4, 0x0076, 0x00a6, 0x00e6, 0x0096, - 0x2071, 0x0260, 0x6114, 0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, - 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, - 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xb155, 0x9694, - 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, - 0x9284, 0x0300, 0x0904, 0xb155, 0x080c, 0x0feb, 0x090c, 0x0db4, - 0x2900, 0xb07a, 0xb77c, 0xc7cd, 0xb77e, 0xa867, 0x0103, 0xb068, - 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, 0xae76, 0x968c, 0x0c00, - 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, - 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, - 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, - 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, - 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, - 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, - 0x0018, 0x2011, 0x0025, 0x080c, 0xb725, 0x003e, 0xd6cc, 0x01e8, - 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb725, 0x2011, 0x0205, - 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0xa98a, 0x0c68, 0x2950, 0x080c, 0xb6c4, 0x009e, 0x00ee, 0x00ae, - 0x007e, 0x0005, 0x00f6, 0x00a6, 0x6003, 0x0003, 0x2079, 0x026c, - 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6014, 0x2050, 0xb436, 0xb33a, - 0xb646, 0xb54a, 0x00ae, 0x00fe, 0x2c10, 0x080c, 0x1a5e, 0x0804, - 0x937a, 0x6003, 0x0002, 0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, - 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, - 0x00f6, 0x2c00, 0x2078, 0x080c, 0x164a, 0x00fe, 0x6003, 0x0004, - 0x0010, 0x6003, 0x0002, 0x009e, 0x080c, 0x8861, 0x080c, 0x896d, - 0x0096, 0x2001, 0x1958, 0x2004, 0x6042, 0x080c, 0x891d, 0x080c, - 0x8a4a, 0x6114, 0x2148, 0xa97c, 0xd1e4, 0x0904, 0xb1f8, 0xd1cc, - 0x05a8, 0xa978, 0xa868, 0xd0fc, 0x0538, 0x0016, 0xa87c, 0x0006, - 0xa880, 0x0006, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, - 0x810e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, - 0x9080, 0x0019, 0x2098, 0x0156, 0x20a9, 0x0020, 0x4003, 0x015e, - 0x000e, 0xa882, 0x000e, 0xa87e, 0x001e, 0xa874, 0x0006, 0x2148, - 0x080c, 0x0f9d, 0x001e, 0x0440, 0x0016, 0x080c, 0x0f9d, 0x009e, - 0xa974, 0x0016, 0x080c, 0xb715, 0x001e, 0x00f0, 0xa867, 0x0103, - 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, 0x0028, - 0x1118, 0xa87b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0xa87b, 0x0015, - 0x0038, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, - 0x0016, 0x080c, 0x66ac, 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9e42, - 0x009e, 0x0005, 0x080c, 0xbe2a, 0x0cd8, 0x6004, 0x9086, 0x0040, - 0x1120, 0x080c, 0x8861, 0x080c, 0x896d, 0x2019, 0x0001, 0x080c, - 0x96d9, 0x6003, 0x0002, 0x080c, 0xc249, 0x080c, 0x891d, 0x080c, - 0x8a4a, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x8861, - 0x080c, 0x896d, 0x2019, 0x0001, 0x080c, 0x96d9, 0x080c, 0x891d, - 0x080c, 0x2fdc, 0x080c, 0xc241, 0x0096, 0x6114, 0x2148, 0x080c, - 0xbb2c, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, - 0x080c, 0x6891, 0x080c, 0xbd15, 0x009e, 0x080c, 0x9e42, 0x080c, - 0x8a4a, 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, - 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, - 0x1a49, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, - 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xb26d, 0xb26d, 0xb26d, 0xb26d, 0xb26d, 0xb26f, 0xb26d, - 0xb26d, 0xb315, 0xb26d, 0xb26d, 0xb26d, 0xb26d, 0xb26d, 0xb26d, - 0xb26d, 0xb26d, 0xb26d, 0xb26d, 0xb446, 0x080c, 0x0db4, 0x0076, - 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, 0x7644, - 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, - 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, - 0x0904, 0xb30e, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, - 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xb30e, 0x9686, - 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, 0x0c38, - 0x080c, 0x0feb, 0x090c, 0x0db4, 0x2900, 0xb07a, 0xb77c, 0x97bd, - 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, - 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, 0x968c, - 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, - 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, - 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, 0x0118, - 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, - 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, - 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, - 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xb725, 0x003e, 0xd6cc, - 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, - 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb725, 0x2011, - 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, - 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xb6c4, 0x080c, 0x18ed, - 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1958, 0x2004, - 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x1118, - 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, 0x0904, - 0xb441, 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xb410, 0xa978, 0xa868, 0xd0fc, - 0x0904, 0xb3d1, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0x00a6, - 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xb39f, - 0x9086, 0x0028, 0x1904, 0xb38b, 0xa87b, 0x001c, 0xb07b, 0x001c, - 0x0804, 0xb3a7, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, 0x9205, - 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, 0x9206, - 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, 0x603a, - 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x6010, - 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x9006, 0xa876, - 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, 0xc0cc, - 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0f9d, 0x009e, 0x080c, - 0xbe64, 0x0804, 0xb441, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, - 0x0015, 0x080c, 0xc0f4, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, - 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb23a, 0xa87c, - 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, 0x8007, - 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, 0x2098, - 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xa87e, 0x080c, 0xc1d1, - 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0f9d, 0x001e, 0x0804, - 0xb43d, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, - 0x080c, 0xc0f4, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, - 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb23a, 0xa890, 0xb092, - 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0f9d, 0x009e, - 0x080c, 0xc1d1, 0xa974, 0x0016, 0x080c, 0xb715, 0x001e, 0x0468, - 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, - 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, - 0xa87b, 0x0015, 0x080c, 0xc0f4, 0x0118, 0xa974, 0xc1dc, 0xa976, - 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xb23a, - 0xa974, 0x0016, 0x080c, 0x66ac, 0x001e, 0xd1e4, 0x1120, 0x080c, - 0x9e42, 0x009e, 0x0005, 0x080c, 0xbe2a, 0x0cd8, 0x6114, 0x0096, - 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x18fb, 0x009e, 0x0005, 0x080c, - 0x8861, 0x0010, 0x080c, 0x891d, 0x080c, 0xbb2c, 0x01f0, 0x0096, - 0x6114, 0x2148, 0x080c, 0xbd32, 0x1118, 0x080c, 0xa7d1, 0x00a0, - 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, 0x11b8, 0xd184, - 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xd7f4, - 0xa877, 0x0000, 0x080c, 0x6891, 0x009e, 0x080c, 0x9e42, 0x080c, - 0x896d, 0x0804, 0x8a4a, 0xa87b, 0x0004, 0x0c90, 0xa87b, 0x0004, - 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49f, 0xb49d, - 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, - 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0xb49d, 0x080c, 0x0db4, 0x080c, - 0x5397, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, - 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, 0x0188, 0xa87b, - 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, 0x0103, 0xa976, - 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x6891, - 0x009e, 0x0804, 0x9e42, 0x9182, 0x0085, 0x0002, 0xb4d5, 0xb4d3, - 0xb4d3, 0xb4e1, 0xb4d3, 0xb4d3, 0xb4d3, 0xb4d3, 0xb4d3, 0xb4d3, - 0xb4d3, 0xb4d3, 0xb4d3, 0x080c, 0x0db4, 0x6003, 0x0001, 0x6106, - 0x080c, 0x83da, 0x0126, 0x2091, 0x8000, 0x080c, 0x896d, 0x012e, - 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, - 0x6216, 0x7220, 0x080c, 0xbb1a, 0x01a0, 0x2268, 0x6800, 0x9086, - 0x0000, 0x0178, 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, - 0x080c, 0xb750, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, - 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x83da, 0x080c, - 0x896d, 0x9280, 0x0004, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2260, 0x080c, 0xbe64, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, - 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db4, 0x908a, 0x0092, - 0x1a0c, 0x0db4, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, - 0x9186, 0x0014, 0x190c, 0x0db4, 0x080c, 0x8861, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbb2c, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6891, 0x009e, 0x080c, 0x9e72, 0x0804, - 0x896d, 0xb556, 0xb558, 0xb558, 0xb556, 0xb556, 0xb556, 0xb556, - 0xb556, 0xb556, 0xb556, 0xb556, 0xb556, 0xb556, 0x080c, 0x0db4, - 0x080c, 0x8861, 0x080c, 0x9e72, 0x080c, 0x896d, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, - 0x0027, 0x11f8, 0x080c, 0x8861, 0x080c, 0x2fdc, 0x080c, 0xc241, - 0x0096, 0x6014, 0x2048, 0x080c, 0xbb2c, 0x0150, 0xa867, 0x0103, - 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6891, 0x080c, 0xbd15, - 0x009e, 0x080c, 0x9e42, 0x080c, 0x896d, 0x0005, 0x080c, 0x9ed7, - 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x8861, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbb2c, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xb5ae, - 0xb5ac, 0xb5ac, 0xb5ac, 0xb5ac, 0xb5ac, 0xb5c6, 0xb5ac, 0xb5ac, - 0xb5ac, 0xb5ac, 0xb5ac, 0xb5ac, 0x080c, 0x0db4, 0x080c, 0x8861, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1956, 0x0010, 0x2001, 0x1957, 0x2004, - 0x601a, 0x6003, 0x000c, 0x080c, 0x896d, 0x0005, 0x080c, 0x8861, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1956, 0x0010, 0x2001, 0x1957, 0x2004, - 0x601a, 0x6003, 0x000e, 0x080c, 0x896d, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0x9ed7, 0xb5f4, - 0xb5f4, 0xb5f4, 0xb5f4, 0xb5f6, 0xb643, 0xb5f4, 0xb5f4, 0xb5f4, - 0xb5f4, 0xb5f4, 0xb5f4, 0xb5f4, 0x080c, 0x0db4, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xb657, 0x080c, 0xbb2c, 0x1118, 0x080c, 0xbd15, - 0x0068, 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xbd15, - 0xa867, 0x0103, 0x080c, 0xc20c, 0x080c, 0x6891, 0x00d6, 0x2c68, - 0x080c, 0x9dec, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xbfa6, 0x6954, 0x6156, 0x6023, - 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, 0x2d60, 0x00de, 0x080c, - 0x9e42, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, - 0x2c68, 0x080c, 0xc1a4, 0x11f0, 0x080c, 0x9dec, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xbfa6, 0x080c, 0x83da, - 0x080c, 0x896d, 0x2d60, 0x00de, 0x0804, 0x9e42, 0x0096, 0x6014, - 0x2048, 0x080c, 0xbb2c, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xbe26, 0xa877, - 0x0000, 0x080c, 0x6891, 0x080c, 0xbd15, 0x009e, 0x0804, 0x9e42, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xbb2c, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6891, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0x9ed7, 0x0030, 0x080c, 0x8861, 0x080c, - 0x9e72, 0x080c, 0x896d, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, - 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, - 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, - 0x080c, 0xb725, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0f9d, 0x080c, 0x0feb, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, - 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, - 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, - 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, - 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, - 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, - 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x6891, 0x2a48, - 0x0cb8, 0x080c, 0x6891, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, - 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, - 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, - 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, - 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, - 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, - 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, - 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, - 0x012e, 0x0005, 0xb78b, 0xb78b, 0xb786, 0xb7ad, 0xb779, 0xb786, - 0xb7ad, 0xb786, 0xb779, 0xb779, 0xb786, 0xb786, 0xb786, 0xb779, - 0xb779, 0x080c, 0x0db4, 0x0036, 0x2019, 0x0010, 0x080c, 0xd106, - 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, - 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11d8, 0x6014, 0x2048, - 0x080c, 0xbb2c, 0x01c0, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, - 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, - 0x6abf, 0x080c, 0xbe26, 0x080c, 0x6884, 0x080c, 0x9e72, 0x9085, - 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000, 0x908a, 0x0016, - 0x1a0c, 0x0db4, 0x0002, 0xb7c3, 0xb7f1, 0xb7c5, 0xb812, 0xb7ec, - 0xb7c3, 0xb786, 0xb78b, 0xb78b, 0xb786, 0xb786, 0xb786, 0xb786, - 0xb786, 0xb786, 0xb786, 0x080c, 0x0db4, 0x86ff, 0x1510, 0x6020, - 0x9086, 0x0006, 0x01f0, 0x0096, 0x6014, 0x2048, 0x080c, 0xbb2c, - 0x0158, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, - 0x0f9d, 0x009e, 0x080c, 0xbe26, 0x009e, 0x080c, 0xc1e6, 0x6007, - 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x83da, 0x080c, - 0x896d, 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, 0x190f, 0x006e, - 0x08a0, 0x00e6, 0x2071, 0x19b7, 0x7024, 0x9c06, 0x1120, 0x080c, - 0x9663, 0x00ee, 0x0850, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, - 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x97bb, - 0x009e, 0x008e, 0x0010, 0x080c, 0x9560, 0x00ee, 0x1904, 0xb7c5, - 0x0804, 0xb786, 0x0036, 0x00e6, 0x2071, 0x19b7, 0x703c, 0x9c06, - 0x1138, 0x901e, 0x080c, 0x96d9, 0x00ee, 0x003e, 0x0804, 0xb7c5, - 0x080c, 0x98eb, 0x00ee, 0x003e, 0x1904, 0xb7c5, 0x0804, 0xb786, - 0x00c6, 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xb845, - 0xb910, 0xba77, 0xb84f, 0x9e72, 0xb845, 0xd0f8, 0xc24e, 0xb910, - 0xb83e, 0xbaf6, 0xb83e, 0xb83e, 0xb83e, 0xb83e, 0x080c, 0x0db4, - 0x080c, 0xbd32, 0x1110, 0x080c, 0xa7d1, 0x0005, 0x080c, 0x8861, - 0x080c, 0x896d, 0x0804, 0x9e42, 0x601b, 0x0001, 0x0005, 0x080c, - 0xbb2c, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x0002, 0xb86e, 0xb870, - 0xb894, 0xb8a8, 0xb8ce, 0xb86e, 0xb845, 0xb845, 0xb845, 0xb8a8, - 0xb8a8, 0xb86e, 0xb86e, 0xb86e, 0xb86e, 0xb8b2, 0x080c, 0x0db4, - 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x2071, 0x19b7, 0x7024, 0x9c06, 0x01a0, 0x080c, 0x9560, 0x080c, - 0xc1e6, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, - 0x1957, 0x2004, 0x601a, 0x080c, 0x83da, 0x080c, 0x896d, 0x00ee, - 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, - 0xc0b5, 0xa882, 0x009e, 0x080c, 0xc1e6, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x080c, 0x83da, 0x080c, 0x896d, 0x0005, - 0x0096, 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, - 0x009e, 0x0005, 0x080c, 0x5397, 0x01b8, 0x6014, 0x0096, 0x904d, - 0x0190, 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, - 0x1150, 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, - 0x0004, 0x080c, 0x6891, 0x009e, 0x0804, 0x9e42, 0x6014, 0x0096, - 0x904d, 0x05c8, 0xa97c, 0xd1e4, 0x05b0, 0x2001, 0x180f, 0x2004, - 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, 0x800b, - 0x810b, 0x9108, 0x611a, 0x2001, 0x0030, 0x2c08, 0x080c, 0x151a, - 0x2001, 0x030c, 0x2004, 0x9086, 0x0041, 0x11a0, 0x6014, 0x0096, - 0x904d, 0x090c, 0x0db4, 0xa880, 0xd0f4, 0x1130, 0xc0f5, 0xa882, - 0x009e, 0x601b, 0x0002, 0x0070, 0x009e, 0x2001, 0x0037, 0x2c08, - 0x080c, 0x151a, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, - 0x080c, 0x9ebc, 0x0005, 0x009e, 0x080c, 0x190f, 0x0804, 0xb894, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x000b, 0x0005, 0xb927, - 0xb84c, 0xb929, 0xb927, 0xb929, 0xb929, 0xb846, 0xb927, 0xb840, - 0xb840, 0xb927, 0xb927, 0xb927, 0xb927, 0xb927, 0xb927, 0x080c, - 0x0db4, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, - 0x908a, 0x000c, 0x1a0c, 0x0db4, 0x00b6, 0x0013, 0x00be, 0x0005, - 0xb944, 0xba11, 0xb946, 0xb986, 0xb946, 0xb986, 0xb946, 0xb954, - 0xb944, 0xb986, 0xb944, 0xb975, 0x080c, 0x0db4, 0x6004, 0x908e, - 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, - 0x908e, 0x0052, 0x0904, 0xba0d, 0x6004, 0x080c, 0xbd32, 0x0904, - 0xba2a, 0x908e, 0x0004, 0x1110, 0x080c, 0x3005, 0x908e, 0x0021, - 0x0904, 0xba2e, 0x908e, 0x0022, 0x0904, 0xba72, 0x908e, 0x003d, - 0x0904, 0xba2e, 0x908e, 0x0039, 0x0904, 0xba32, 0x908e, 0x0035, - 0x0904, 0xba32, 0x908e, 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, - 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, - 0x080c, 0x2fdc, 0x080c, 0xa7d1, 0x0804, 0x9e72, 0x00c6, 0x00d6, - 0x6104, 0x9186, 0x0016, 0x0904, 0xb9fe, 0x9186, 0x0002, 0x1904, - 0xb9d3, 0x2001, 0x1836, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x6f9b, - 0x11b0, 0x080c, 0xc22c, 0x0138, 0x080c, 0x6fbe, 0x1120, 0x080c, - 0x6eab, 0x0804, 0xba5b, 0x2001, 0x194d, 0x2003, 0x0001, 0x2001, - 0x1800, 0x2003, 0x0001, 0x080c, 0x6ecd, 0x0804, 0xba5b, 0x6010, - 0x2058, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x1904, 0xba5b, 0xb8a0, - 0x9084, 0xff80, 0x1904, 0xba5b, 0xb840, 0x9084, 0x00ff, 0x9005, - 0x0190, 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, - 0x0398, 0x6043, 0x0000, 0x080c, 0x9dec, 0x0128, 0x2b00, 0x6012, - 0x6023, 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, - 0x11a0, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, - 0x1836, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x5c6d, 0x00ee, 0x080c, 0xa7d1, 0x0030, 0x080c, 0xa7d1, 0x080c, - 0x2fdc, 0x080c, 0xc241, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x3005, 0x012e, 0x00ee, 0x080c, 0x9e72, 0x0005, 0x2001, 0x0002, - 0x080c, 0x6198, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8422, - 0x080c, 0x896d, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3005, 0x0804, - 0xb982, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, - 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xb9d3, 0x8001, - 0xb842, 0x6003, 0x0001, 0x080c, 0x8422, 0x080c, 0x896d, 0x00de, - 0x00ce, 0x0898, 0x080c, 0xa7d1, 0x0804, 0xb984, 0x080c, 0xa80d, - 0x0804, 0xb984, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xc1a4, 0x00de, - 0x0118, 0x080c, 0x9e42, 0x00f0, 0x6004, 0x8007, 0x6134, 0x918c, - 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x603c, 0x600a, 0x2001, 0x1957, 0x2004, 0x601a, 0x602c, - 0x2c08, 0x2060, 0x6024, 0xc0b5, 0x6026, 0x2160, 0x080c, 0x83da, - 0x080c, 0x896d, 0x0005, 0x00de, 0x00ce, 0x080c, 0xa7d1, 0x080c, - 0x2fdc, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3005, 0x6017, - 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x080c, 0xa272, 0x1904, 0xba2a, 0x0005, 0x6000, - 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x0096, 0x00d6, 0x001b, 0x00de, - 0x009e, 0x0005, 0xba92, 0xba92, 0xba92, 0xba92, 0xba92, 0xba92, - 0xba92, 0xba92, 0xba92, 0xb845, 0xba92, 0xb84c, 0xba94, 0xb84c, - 0xbaa1, 0xba92, 0x080c, 0x0db4, 0x6004, 0x9086, 0x008b, 0x0148, - 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x83da, 0x080c, 0x896d, - 0x0005, 0x080c, 0xc220, 0x0118, 0x080c, 0xc233, 0x0010, 0x080c, - 0xc241, 0x080c, 0xbd15, 0x080c, 0xbb2c, 0x0570, 0x080c, 0x2fdc, - 0x080c, 0xbb2c, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, - 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6891, - 0x2c68, 0x080c, 0x9dec, 0x0150, 0x6810, 0x6012, 0x080c, 0xbfa6, - 0x00c6, 0x2d60, 0x080c, 0x9e72, 0x00ce, 0x0008, 0x2d60, 0x6017, - 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x8422, 0x080c, 0x896d, 0x00c8, 0x080c, 0xc220, 0x0138, 0x6034, - 0x9086, 0x4000, 0x1118, 0x080c, 0x2fdc, 0x08d0, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x080c, 0x2fdc, 0x0868, 0x080c, 0x9e72, 0x0005, 0x6000, 0x908a, - 0x0016, 0x1a0c, 0x0db4, 0x0002, 0xbb0c, 0xbb0c, 0xbb0e, 0xbb0e, - 0xbb0e, 0xbb0c, 0xbb0c, 0x9e72, 0xbb0c, 0xbb0c, 0xbb0c, 0xbb0c, - 0xbb0c, 0xbb0c, 0xbb0c, 0xbb0c, 0x080c, 0x0db4, 0x080c, 0x98eb, - 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x6891, 0x009e, - 0x0804, 0x9e42, 0x9284, 0x0007, 0x1158, 0x9282, 0x1cd0, 0x0240, - 0x2001, 0x1819, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, - 0x9006, 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, - 0x000e, 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, - 0x1096, 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7350, - 0x7070, 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xc22c, - 0x0180, 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, - 0x080c, 0x2fdc, 0x080c, 0xc241, 0x00c6, 0x080c, 0x9e72, 0x00ce, - 0x0060, 0x080c, 0xbf20, 0x0148, 0x080c, 0xbd32, 0x1110, 0x080c, - 0xa7d1, 0x00c6, 0x080c, 0x9e42, 0x00ce, 0x9ce0, 0x0018, 0x7064, - 0x9c02, 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, - 0x0128, 0x2061, 0x1a7f, 0x6112, 0x080c, 0x2fdc, 0x9006, 0x0010, - 0x9085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9dec, 0x01b0, 0x6656, 0x2b00, 0x6012, - 0x080c, 0x5397, 0x0118, 0x080c, 0xbc59, 0x0168, 0x080c, 0xbfa6, - 0x6023, 0x0003, 0x2009, 0x004b, 0x080c, 0x9ebc, 0x9085, 0x0001, + 0x4000, 0x080c, 0xc11a, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, + 0x009e, 0x080c, 0x3010, 0x6020, 0x9086, 0x000a, 0x0138, 0x080c, + 0x9e2f, 0x0020, 0x080c, 0xa7cd, 0x080c, 0xaa70, 0x001e, 0x002e, + 0x00ee, 0x00be, 0x0005, 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, + 0x1160, 0x2001, 0x0002, 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x8440, 0x0804, 0x898b, 0x0804, 0xaa70, 0x2030, + 0x2011, 0x1823, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, + 0x1120, 0x2001, 0x0007, 0x080c, 0x61a7, 0x0804, 0x9e2f, 0x0804, + 0xaa70, 0x0002, 0xa8ae, 0xab69, 0xa8ae, 0xaba8, 0xa8ae, 0xac53, + 0xab5e, 0xa8ae, 0xa8ae, 0xac66, 0xa8ae, 0xac76, 0x6604, 0x9686, + 0x0003, 0x0904, 0xaa85, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9e2f, + 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, 0xac86, 0x11a0, 0x9006, + 0x080c, 0x6193, 0x080c, 0x2fe7, 0x080c, 0xc250, 0x2001, 0x0002, + 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8440, + 0x080c, 0x898b, 0x0408, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, + 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0170, + 0x8001, 0xb842, 0x601b, 0x000a, 0x0078, 0x2009, 0x026f, 0x2104, + 0x9084, 0xff00, 0x9086, 0x1900, 0x1108, 0x08a0, 0x080c, 0x2fe7, + 0x080c, 0xc250, 0x080c, 0xaa70, 0x00ce, 0x00de, 0x00be, 0x0005, + 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xac94, 0x00d6, 0x2069, + 0x1954, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, + 0x007e, 0x1138, 0x2069, 0x181f, 0x2d04, 0x8000, 0x206a, 0x00de, + 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x6193, 0x2001, 0x0002, + 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8440, + 0x080c, 0x898b, 0x0804, 0xac23, 0x080c, 0xbb3b, 0x01b0, 0x6014, + 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, + 0x2001, 0x0002, 0x080c, 0xc174, 0x00b0, 0x6014, 0x2048, 0xa864, + 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, + 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, + 0x1110, 0x9006, 0x0c38, 0x080c, 0xa7cd, 0x2009, 0x026e, 0x2134, + 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0510, 0x9686, 0x000b, 0x01c8, + 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, + 0x01b0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0180, 0x2001, + 0x0004, 0x080c, 0x61a7, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, + 0x0010, 0x080c, 0xaa70, 0x002e, 0x00be, 0x009e, 0x0005, 0x9286, + 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0140, 0xa864, + 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c50, 0x6010, + 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, 0xb842, + 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, 0x007e, + 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c78, 0x00ee, 0x0010, + 0x080c, 0x2fe7, 0x0870, 0x080c, 0xac94, 0x1160, 0x2001, 0x0004, + 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x8440, + 0x0804, 0x898b, 0x080c, 0xa7cd, 0x0804, 0xaa70, 0x0469, 0x1160, + 0x2001, 0x0008, 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0005, + 0x080c, 0x8440, 0x0804, 0x898b, 0x0804, 0xaa70, 0x00e9, 0x1160, + 0x2001, 0x000a, 0x080c, 0x61a7, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x8440, 0x0804, 0x898b, 0x0804, 0xaa70, 0x2009, 0x026e, + 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, + 0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6265, 0x001e, 0x00ce, + 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, + 0x6010, 0x2058, 0x2009, 0x1836, 0x2104, 0x9085, 0x0003, 0x200a, + 0x080c, 0xad3a, 0x0560, 0x2009, 0x1836, 0x2104, 0xc0cd, 0x200a, + 0x080c, 0x6576, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, + 0xd564, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, + 0x2009, 0x0001, 0x080c, 0x2fb2, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x2dc8, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, + 0x080c, 0x30e2, 0x8108, 0x1f04, 0xacd8, 0x015e, 0x00ce, 0x080c, + 0xac97, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, + 0x1836, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, + 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1836, + 0x2102, 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, 0x2069, 0x181e, + 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0x181f, 0x206a, + 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, + 0x2009, 0x182b, 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, + 0x26b9, 0x080c, 0x6faa, 0x0170, 0x2071, 0x0260, 0x2069, 0x195a, + 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, + 0x080c, 0xbf4f, 0x0040, 0x2001, 0x0006, 0x080c, 0x61a7, 0x080c, + 0x3010, 0x080c, 0x9e2f, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, + 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, + 0x182b, 0x231c, 0x83ff, 0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, + 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1198, 0x2011, + 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019, 0x000a, 0x080c, 0xae1c, + 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, + 0xae1c, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, + 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, + 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, + 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, + 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2029, 0x19c8, 0x252c, 0x2021, 0x19ce, 0x2424, 0x2061, + 0x1cd0, 0x2071, 0x1800, 0x7250, 0x7070, 0x9202, 0x1a04, 0xadf4, + 0x080c, 0xd595, 0x0904, 0xaded, 0x6720, 0x9786, 0x0007, 0x0904, + 0xaded, 0x2500, 0x9c06, 0x0904, 0xaded, 0x2400, 0x9c06, 0x05e8, + 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000, 0x9086, + 0x0004, 0x1110, 0x080c, 0x191f, 0x9786, 0x000a, 0x0148, 0x080c, + 0xbd41, 0x1130, 0x00ce, 0x080c, 0xa7cd, 0x080c, 0x9e5f, 0x00e8, + 0x6014, 0x2048, 0x080c, 0xbb3b, 0x01a8, 0x9786, 0x0003, 0x1530, + 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, + 0x080c, 0x0f9d, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6893, + 0x080c, 0xbd24, 0x080c, 0x9e5f, 0x00ce, 0x9ce0, 0x0018, 0x7064, + 0x9c02, 0x1210, 0x0804, 0xad9b, 0x012e, 0x000e, 0x002e, 0x004e, + 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, + 0x1118, 0x080c, 0xd50f, 0x0c30, 0x9786, 0x000a, 0x0998, 0x0880, + 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xae08, + 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, + 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, + 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, + 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, + 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, + 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, + 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, + 0x0053, 0x1a0c, 0x0db4, 0x080c, 0xbd30, 0x0120, 0x080c, 0xbd41, + 0x0168, 0x0028, 0x080c, 0x3010, 0x080c, 0xbd41, 0x0138, 0x080c, + 0x887f, 0x080c, 0x9e2f, 0x080c, 0x898b, 0x0005, 0x080c, 0xa7cd, + 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, + 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7f, 0xae7f, 0xae7f, 0xae7f, + 0xae7d, 0xae7d, 0xae7d, 0xae7f, 0xae7d, 0x080c, 0x0db4, 0x600b, + 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, 0x83f8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x898b, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, + 0x6004, 0x9082, 0x0040, 0x0804, 0xaf34, 0x9186, 0x0027, 0x1520, + 0x080c, 0x887f, 0x080c, 0x2fe7, 0x080c, 0xc250, 0x0096, 0x6114, + 0x2148, 0x080c, 0xbb3b, 0x0198, 0x080c, 0xbd41, 0x1118, 0x080c, + 0xa7cd, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, + 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x68a0, 0x080c, 0xbd24, 0x009e, + 0x080c, 0x9e2f, 0x0804, 0x898b, 0x9186, 0x0014, 0x1120, 0x6004, + 0x9082, 0x0040, 0x04a0, 0x9186, 0x0046, 0x0150, 0x9186, 0x0045, + 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, 0x0048, 0x190c, 0x0db4, + 0x2001, 0x0109, 0x2004, 0xd084, 0x0508, 0x0126, 0x2091, 0x2800, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, 0x2079, + 0x19bf, 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x82e4, 0x00ce, + 0x00ee, 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, 0xa001, + 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, 0xaf72, 0x0005, 0x0002, + 0xaf0e, 0xaf0c, 0xaf0c, 0xaf0c, 0xaf0c, 0xaf0c, 0xaf0c, 0xaf0c, + 0xaf0c, 0xaf0c, 0xaf0c, 0xaf29, 0xaf29, 0xaf29, 0xaf29, 0xaf0c, + 0xaf29, 0xaf0c, 0xaf29, 0xaf0c, 0x080c, 0x0db4, 0x080c, 0x887f, + 0x0096, 0x6114, 0x2148, 0x080c, 0xbb3b, 0x0168, 0xa867, 0x0103, + 0xa87b, 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, + 0x68a0, 0x080c, 0xbd24, 0x009e, 0x080c, 0x9e2f, 0x080c, 0x898b, + 0x0005, 0x080c, 0x887f, 0x080c, 0xbd41, 0x090c, 0xa7cd, 0x080c, + 0x9e2f, 0x080c, 0x898b, 0x0005, 0x0002, 0xaf4b, 0xaf49, 0xaf49, + 0xaf49, 0xaf49, 0xaf49, 0xaf49, 0xaf49, 0xaf49, 0xaf49, 0xaf49, + 0xaf62, 0xaf62, 0xaf62, 0xaf62, 0xaf49, 0xaf6c, 0xaf49, 0xaf62, + 0xaf49, 0x080c, 0x0db4, 0x0096, 0x080c, 0x887f, 0x6014, 0x2048, + 0x2001, 0x1960, 0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, + 0x0004, 0xa87c, 0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, + 0x0002, 0x0cb8, 0x080c, 0x887f, 0x080c, 0xc253, 0x080c, 0xc258, + 0x6003, 0x000f, 0x0804, 0x898b, 0x080c, 0x887f, 0x080c, 0x9e2f, + 0x0804, 0x898b, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, + 0x000a, 0x0005, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf90, + 0xb06d, 0xaf8e, 0xb0a1, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, + 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, 0xaf8e, 0xb0a1, 0x080c, 0x0db4, + 0x00b6, 0x0096, 0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, + 0x1528, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xb05c, 0xa87b, + 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, + 0xa938, 0x9115, 0x190c, 0xb236, 0x080c, 0x66bb, 0x6210, 0x2258, + 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, + 0xb040, 0x080c, 0x9e2f, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, + 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xb044, 0x7348, + 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, + 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, + 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, + 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, + 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, + 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, + 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, + 0x0804, 0xaf97, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, + 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, + 0x0025, 0x080c, 0xb724, 0x003e, 0xd6cc, 0x0904, 0xafac, 0x7154, + 0xa98a, 0x81ff, 0x0904, 0xafac, 0x9192, 0x0021, 0x1278, 0x8304, + 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb724, 0x2011, 0x0205, + 0x2013, 0x0000, 0x080c, 0xc1e0, 0x0804, 0xafac, 0xa868, 0xd0fc, + 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, + 0xb6c3, 0x00ae, 0x080c, 0xc1e0, 0x080c, 0xb714, 0x0804, 0xafae, + 0x080c, 0xbe39, 0x0804, 0xafbb, 0xa87c, 0xd0ac, 0x0904, 0xafc7, + 0xa880, 0xd0bc, 0x1904, 0xafc7, 0x7348, 0xa838, 0x9306, 0x11c8, + 0x734c, 0xa834, 0x931e, 0x0904, 0xafc7, 0xd6d4, 0x0190, 0xab38, + 0x9305, 0x0904, 0xafc7, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xaf9f, + 0xa838, 0xa934, 0x9105, 0x0904, 0xaf9f, 0xa880, 0xd0bc, 0x1904, + 0xaf9f, 0x080c, 0xbe73, 0x0804, 0xafbb, 0x0096, 0x00f6, 0x6003, + 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, 0x6003, 0x0002, + 0x00fe, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, + 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, + 0x0e90, 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, 0x6043, 0x0000, + 0x2c10, 0x080c, 0x1a69, 0x080c, 0x845d, 0x080c, 0x8a68, 0x009e, + 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, + 0x000a, 0x0005, 0xb0be, 0xb0be, 0xb0be, 0xb0be, 0xb0be, 0xb0c0, + 0xb156, 0xb0be, 0xb0be, 0xb16d, 0xb1f9, 0xb0be, 0xb0be, 0xb0be, + 0xb0be, 0xb20e, 0xb0be, 0xb0be, 0xb0be, 0xb0be, 0x080c, 0x0db4, + 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, + 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, + 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, + 0x86ff, 0x0904, 0xb151, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, + 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xb151, + 0x080c, 0x0feb, 0x090c, 0x0db4, 0x2900, 0xb07a, 0xb77c, 0xc7cd, + 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, + 0xa872, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, + 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, + 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, + 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, + 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, + 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, + 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, + 0xb724, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, + 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, + 0x080c, 0xb724, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, + 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, + 0xb6c3, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x00f6, 0x00a6, + 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, + 0x6014, 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, 0x00ae, 0x00fe, + 0x2c10, 0x080c, 0x1a69, 0x0804, 0x9394, 0x6003, 0x0002, 0x6004, + 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c, 0xd0ac, + 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078, 0x080c, + 0x164a, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002, 0x009e, + 0x080c, 0x887f, 0x080c, 0x898b, 0x0096, 0x2001, 0x1960, 0x2004, + 0x6042, 0x080c, 0x893b, 0x080c, 0x8a68, 0x6114, 0x2148, 0xa97c, + 0xd1e4, 0x0904, 0xb1f4, 0xd1cc, 0x05a8, 0xa978, 0xa868, 0xd0fc, + 0x0538, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0xa860, 0x20e8, + 0xa85c, 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, 0x810f, 0x9184, + 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, 0x2098, 0x0156, + 0x20a9, 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, 0x000e, 0xa87e, + 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0f9d, 0x001e, 0x0440, + 0x0016, 0x080c, 0x0f9d, 0x009e, 0xa974, 0x0016, 0x080c, 0xb714, + 0x001e, 0x00f0, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, + 0x0002, 0x0180, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, + 0xd1dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0xa87b, + 0x0007, 0x0010, 0xa87b, 0x0000, 0x0016, 0x080c, 0x66bb, 0x001e, + 0xd1e4, 0x1120, 0x080c, 0x9e2f, 0x009e, 0x0005, 0x080c, 0xbe39, + 0x0cd8, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, 0x887f, 0x080c, + 0x898b, 0x2019, 0x0001, 0x080c, 0x96e9, 0x6003, 0x0002, 0x080c, + 0xc258, 0x080c, 0x893b, 0x080c, 0x8a68, 0x0005, 0x6004, 0x9086, + 0x0040, 0x1120, 0x080c, 0x887f, 0x080c, 0x898b, 0x2019, 0x0001, + 0x080c, 0x96e9, 0x080c, 0x893b, 0x080c, 0x2fe7, 0x080c, 0xc250, + 0x0096, 0x6114, 0x2148, 0x080c, 0xbb3b, 0x0150, 0xa867, 0x0103, + 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, 0x68a0, 0x080c, 0xbd24, + 0x009e, 0x080c, 0x9e2f, 0x080c, 0x8a68, 0x0005, 0xa87b, 0x0015, + 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, + 0x0000, 0x0006, 0x0016, 0x2009, 0x1a51, 0x2104, 0x8000, 0x200a, + 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, + 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb269, 0xb269, 0xb269, + 0xb269, 0xb269, 0xb26b, 0xb269, 0xb269, 0xb311, 0xb269, 0xb269, + 0xb269, 0xb269, 0xb269, 0xb269, 0xb269, 0xb269, 0xb269, 0xb269, + 0xb442, 0x080c, 0x0db4, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, + 0x0260, 0x6114, 0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, + 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, + 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xb30a, 0x9694, 0xff00, + 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, + 0x0300, 0x0904, 0xb30a, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, + 0x1118, 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x0feb, 0x090c, 0x0db4, + 0x2900, 0xb07a, 0xb77c, 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, + 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, + 0xf000, 0x9635, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, + 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, + 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, + 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, + 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, + 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, + 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, + 0x080c, 0xb724, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, + 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, + 0x0029, 0x080c, 0xb724, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, + 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, + 0x080c, 0xb6c3, 0x080c, 0x18ed, 0x009e, 0x00ee, 0x00ae, 0x007e, + 0x0005, 0x2001, 0x1960, 0x2004, 0x6042, 0x0096, 0x6114, 0x2148, + 0xa83c, 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, + 0x0002, 0xa97c, 0xd1e4, 0x0904, 0xb43d, 0x6043, 0x0000, 0x6010, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, + 0xb40c, 0xa978, 0xa868, 0xd0fc, 0x0904, 0xb3cd, 0x0016, 0xa87c, + 0x0006, 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, + 0x90b6, 0x0002, 0x0904, 0xb39b, 0x9086, 0x0028, 0x1904, 0xb387, + 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, 0xb3a3, 0x6024, 0xd0f4, + 0x11d0, 0xa838, 0xaa34, 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, + 0x1120, 0xa88c, 0xaa34, 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, + 0xa9ac, 0xa834, 0x9102, 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, + 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, + 0xb83e, 0x00be, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, + 0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, + 0x080c, 0x0f9d, 0x009e, 0x080c, 0xbe73, 0x0804, 0xb43d, 0xd1dc, + 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xc103, 0x0118, + 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, + 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, + 0x9115, 0x190c, 0xb236, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, + 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, + 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, + 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, + 0x000e, 0xa87e, 0x080c, 0xc1e0, 0x001e, 0xa874, 0x0006, 0x2148, + 0x080c, 0x0f9d, 0x001e, 0x0804, 0xb439, 0x0016, 0x00a6, 0x2150, + 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, + 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, + 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xc103, 0x0118, 0xb174, + 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, + 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, + 0x190c, 0xb236, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, + 0x00ae, 0x080c, 0x0f9d, 0x009e, 0x080c, 0xc1e0, 0xa974, 0x0016, + 0x080c, 0xb714, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, + 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, + 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xc103, + 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, + 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, + 0xa938, 0x9115, 0x190c, 0xb236, 0xa974, 0x0016, 0x080c, 0x66bb, + 0x001e, 0xd1e4, 0x1120, 0x080c, 0x9e2f, 0x009e, 0x0005, 0x080c, + 0xbe39, 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, + 0x190b, 0x009e, 0x0005, 0x080c, 0x887f, 0x0010, 0x080c, 0x893b, + 0x080c, 0xbb3b, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xbd41, + 0x1118, 0x080c, 0xa7cd, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, + 0x210c, 0xd18c, 0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, + 0x0029, 0x1110, 0x080c, 0xd80d, 0xa877, 0x0000, 0x080c, 0x68a0, + 0x009e, 0x080c, 0x9e2f, 0x080c, 0x898b, 0x0804, 0x8a68, 0xa87b, + 0x0004, 0x0c90, 0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, + 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb499, 0xb499, 0xb499, + 0xb499, 0xb499, 0xb49b, 0xb499, 0xb499, 0xb499, 0xb499, 0xb499, + 0xb499, 0xb499, 0xb499, 0xb499, 0xb499, 0xb499, 0xb499, 0xb499, + 0xb499, 0x080c, 0x0db4, 0x080c, 0x53a2, 0x01f8, 0x6014, 0x7144, + 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, + 0x0096, 0x904d, 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, + 0x0128, 0xa867, 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, + 0xa99a, 0xaa9e, 0x080c, 0x68a0, 0x009e, 0x0804, 0x9e2f, 0x9182, + 0x0085, 0x0002, 0xb4d1, 0xb4cf, 0xb4cf, 0xb4dd, 0xb4cf, 0xb4cf, + 0xb4cf, 0xb4cf, 0xb4cf, 0xb4cf, 0xb4cf, 0xb4cf, 0xb4cf, 0x080c, + 0x0db4, 0x6003, 0x0001, 0x6106, 0x080c, 0x83f8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x898b, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, + 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xbb29, + 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, 0x6d10, + 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xb74f, 0x00ce, 0x0128, + 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, + 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, 0x7220, 0x080c, 0xbb29, + 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, + 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xbe73, 0x00ce, + 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, + 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0db4, 0x908a, 0x0092, 0x1a0c, + 0x0db4, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, + 0x0014, 0x190c, 0x0db4, 0x080c, 0x887f, 0x0096, 0x6014, 0x2048, + 0x080c, 0xbb3b, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, + 0x0029, 0x080c, 0x68a0, 0x009e, 0x080c, 0x9e5f, 0x0804, 0x898b, + 0xb555, 0xb557, 0xb557, 0xb555, 0xb555, 0xb555, 0xb555, 0xb555, + 0xb555, 0xb555, 0xb555, 0xb555, 0xb555, 0x080c, 0x0db4, 0x080c, + 0x887f, 0x080c, 0x9e5f, 0x080c, 0x898b, 0x0005, 0x9186, 0x0013, + 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, 0x0027, + 0x11f8, 0x080c, 0x887f, 0x080c, 0x2fe7, 0x080c, 0xc250, 0x0096, + 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0150, 0xa867, 0x0103, 0xa877, + 0x0000, 0xa87b, 0x0029, 0x080c, 0x68a0, 0x080c, 0xbd24, 0x009e, + 0x080c, 0x9e2f, 0x080c, 0x898b, 0x0005, 0x080c, 0x9ec4, 0x0ce0, + 0x9186, 0x0014, 0x1dd0, 0x080c, 0x887f, 0x0096, 0x6014, 0x2048, + 0x080c, 0xbb3b, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, + 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xb5ad, 0xb5ab, + 0xb5ab, 0xb5ab, 0xb5ab, 0xb5ab, 0xb5c5, 0xb5ab, 0xb5ab, 0xb5ab, + 0xb5ab, 0xb5ab, 0xb5ab, 0x080c, 0x0db4, 0x080c, 0x887f, 0x6034, + 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, + 0x1118, 0x2001, 0x195e, 0x0010, 0x2001, 0x195f, 0x2004, 0x601a, + 0x6003, 0x000c, 0x080c, 0x898b, 0x0005, 0x080c, 0x887f, 0x6034, + 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, + 0x1118, 0x2001, 0x195e, 0x0010, 0x2001, 0x195f, 0x2004, 0x601a, + 0x6003, 0x000e, 0x080c, 0x898b, 0x0005, 0x9182, 0x0092, 0x1220, + 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0x9ec4, 0xb5f3, 0xb5f3, + 0xb5f3, 0xb5f3, 0xb5f5, 0xb642, 0xb5f3, 0xb5f3, 0xb5f3, 0xb5f3, + 0xb5f3, 0xb5f3, 0xb5f3, 0x080c, 0x0db4, 0x0096, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x009e, + 0x0804, 0xb656, 0x080c, 0xbb3b, 0x1118, 0x080c, 0xbd24, 0x0068, + 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xbd24, 0xa867, + 0x0103, 0x080c, 0xc21b, 0x080c, 0x68a0, 0x00d6, 0x2c68, 0x080c, + 0x9dd9, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, + 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, + 0x6910, 0x6112, 0x080c, 0xbfb5, 0x6954, 0x6156, 0x6023, 0x0001, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x2d60, 0x00de, 0x080c, 0x9e2f, + 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, + 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x0130, + 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, 0x2c68, + 0x080c, 0xc1b3, 0x11f0, 0x080c, 0x9dd9, 0x01d8, 0x6106, 0x6003, + 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, + 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, + 0x613e, 0x6954, 0x6156, 0x080c, 0xbfb5, 0x080c, 0x83f8, 0x080c, + 0x898b, 0x2d60, 0x00de, 0x0804, 0x9e2f, 0x0096, 0x6014, 0x2048, + 0x080c, 0xbb3b, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, + 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, + 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xbe35, 0xa877, 0x0000, + 0x080c, 0x68a0, 0x080c, 0xbd24, 0x009e, 0x0804, 0x9e2f, 0x0016, + 0x0096, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0140, 0xa867, 0x0103, + 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x68a0, 0x009e, 0x001e, + 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, + 0x0118, 0x080c, 0x9ec4, 0x0030, 0x080c, 0x887f, 0x080c, 0x9e5f, + 0x080c, 0x898b, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, + 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, + 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, + 0xb724, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x0f9d, + 0x080c, 0x0feb, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, + 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, 0x001b, + 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, + 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, + 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, + 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, + 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, + 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x68a0, 0x2a48, 0x0cb8, + 0x080c, 0x68a0, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, + 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, + 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, + 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, + 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, 0x0080, + 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, 0x0066, + 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, + 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, + 0x2031, 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, + 0x0005, 0xb78a, 0xb78a, 0xb785, 0xb7ac, 0xb778, 0xb785, 0xb7ac, + 0xb785, 0xb778, 0xb778, 0xb785, 0xb785, 0xb785, 0xb778, 0xb778, + 0x080c, 0x0db4, 0x0036, 0x2019, 0x0010, 0x080c, 0xd11f, 0x6023, + 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, + 0x0001, 0x0005, 0x0096, 0x86ff, 0x11d8, 0x6014, 0x2048, 0x080c, + 0xbb3b, 0x01c0, 0xa864, 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, + 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, 0x080c, 0x6ace, + 0x080c, 0xbe35, 0x080c, 0x6893, 0x080c, 0x9e5f, 0x9085, 0x0001, + 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000, 0x908a, 0x0016, 0x1a0c, + 0x0db4, 0x0002, 0xb7c2, 0xb7f0, 0xb7c4, 0xb811, 0xb7eb, 0xb7c2, + 0xb785, 0xb78a, 0xb78a, 0xb785, 0xb785, 0xb785, 0xb785, 0xb785, + 0xb785, 0xb785, 0x080c, 0x0db4, 0x86ff, 0x1510, 0x6020, 0x9086, + 0x0006, 0x01f0, 0x0096, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0158, + 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0f9d, + 0x009e, 0x080c, 0xbe35, 0x009e, 0x080c, 0xc1f5, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, 0x83f8, 0x080c, 0x898b, + 0x9085, 0x0001, 0x0005, 0x0066, 0x080c, 0x191f, 0x006e, 0x08a0, + 0x00e6, 0x2071, 0x19bf, 0x7024, 0x9c06, 0x1120, 0x080c, 0x9673, + 0x00ee, 0x0850, 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, + 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x97a4, 0x009e, + 0x008e, 0x0010, 0x080c, 0x9570, 0x00ee, 0x1904, 0xb7c4, 0x0804, + 0xb785, 0x0036, 0x00e6, 0x2071, 0x19bf, 0x703c, 0x9c06, 0x1138, + 0x901e, 0x080c, 0x96e9, 0x00ee, 0x003e, 0x0804, 0xb7c4, 0x080c, + 0x98d4, 0x00ee, 0x003e, 0x1904, 0xb7c4, 0x0804, 0xb785, 0x00c6, + 0x6020, 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xb844, 0xb90f, + 0xba79, 0xb84e, 0x9e5f, 0xb844, 0xd111, 0xc25d, 0xb90f, 0xb83d, + 0xbb05, 0xb83d, 0xb83d, 0xb83d, 0xb83d, 0x080c, 0x0db4, 0x080c, + 0xbd41, 0x1110, 0x080c, 0xa7cd, 0x0005, 0x080c, 0x887f, 0x080c, + 0x898b, 0x0804, 0x9e2f, 0x601b, 0x0001, 0x0005, 0x080c, 0xbb3b, + 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x0002, 0xb86d, 0xb86f, 0xb893, + 0xb8a7, 0xb8cd, 0xb86d, 0xb844, 0xb844, 0xb844, 0xb8a7, 0xb8a7, + 0xb86d, 0xb86d, 0xb86d, 0xb86d, 0xb8b1, 0x080c, 0x0db4, 0x00e6, + 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, + 0x19bf, 0x7024, 0x9c06, 0x01a0, 0x080c, 0x9570, 0x080c, 0xc1f5, + 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x195f, + 0x2004, 0x601a, 0x080c, 0x83f8, 0x080c, 0x898b, 0x00ee, 0x0005, + 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, + 0xa882, 0x009e, 0x080c, 0xc1f5, 0x6007, 0x0085, 0x6003, 0x000b, + 0x6023, 0x0002, 0x080c, 0x83f8, 0x080c, 0x898b, 0x0005, 0x0096, + 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, + 0x0005, 0x080c, 0x53a2, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, + 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, + 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, + 0x080c, 0x68a0, 0x009e, 0x0804, 0x9e2f, 0x6014, 0x0096, 0x904d, + 0x05c8, 0xa97c, 0xd1e4, 0x05b0, 0x2001, 0x180f, 0x2004, 0xd0c4, + 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, + 0x9108, 0x611a, 0x2001, 0x0030, 0x2c08, 0x080c, 0x151a, 0x2001, + 0x030c, 0x2004, 0x9086, 0x0041, 0x11a0, 0x6014, 0x0096, 0x904d, + 0x090c, 0x0db4, 0xa880, 0xd0f4, 0x1130, 0xc0f5, 0xa882, 0x009e, + 0x601b, 0x0002, 0x0070, 0x009e, 0x2001, 0x0037, 0x2c08, 0x080c, + 0x151a, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0x9ea9, 0x0005, 0x009e, 0x080c, 0x191f, 0x0804, 0xb893, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x000b, 0x0005, 0xb926, 0xb84b, + 0xb928, 0xb926, 0xb928, 0xb928, 0xb845, 0xb926, 0xb83f, 0xb83f, + 0xb926, 0xb926, 0xb926, 0xb926, 0xb926, 0xb926, 0x080c, 0x0db4, + 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, 0x908a, + 0x000c, 0x1a0c, 0x0db4, 0x00b6, 0x0013, 0x00be, 0x0005, 0xb943, + 0xba10, 0xb945, 0xb985, 0xb945, 0xb985, 0xb945, 0xb953, 0xb943, + 0xb985, 0xb943, 0xb974, 0x080c, 0x0db4, 0x6004, 0x908e, 0x0016, + 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, 0x908e, + 0x0052, 0x0904, 0xba0c, 0x6004, 0x080c, 0xbd41, 0x0904, 0xba29, + 0x908e, 0x0004, 0x1110, 0x080c, 0x3010, 0x908e, 0x0021, 0x0904, + 0xba2d, 0x908e, 0x0022, 0x0904, 0xba74, 0x908e, 0x003d, 0x0904, + 0xba2d, 0x908e, 0x0039, 0x0904, 0xba31, 0x908e, 0x0035, 0x0904, + 0xba31, 0x908e, 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, 0x6010, + 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, 0x080c, + 0x2fe7, 0x080c, 0xa7cd, 0x0804, 0x9e5f, 0x00c6, 0x00d6, 0x6104, + 0x9186, 0x0016, 0x0904, 0xb9fd, 0x9186, 0x0002, 0x1904, 0xb9d2, + 0x2001, 0x1836, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x6faa, 0x11b0, + 0x080c, 0xc23b, 0x0138, 0x080c, 0x6fcd, 0x1120, 0x080c, 0x6eba, + 0x0804, 0xba5d, 0x2001, 0x1955, 0x2003, 0x0001, 0x2001, 0x1800, + 0x2003, 0x0001, 0x080c, 0x6edc, 0x0804, 0xba5d, 0x6010, 0x2058, + 0x2001, 0x1836, 0x2004, 0xd0ac, 0x1904, 0xba5d, 0xb8a0, 0x9084, + 0xff80, 0x1904, 0xba5d, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, + 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, + 0x6043, 0x0000, 0x080c, 0x9dd9, 0x0128, 0x2b00, 0x6012, 0x6023, + 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, + 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1836, + 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c78, + 0x00ee, 0x080c, 0xa7cd, 0x0030, 0x080c, 0xa7cd, 0x080c, 0x2fe7, + 0x080c, 0xc250, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3010, + 0x012e, 0x00ee, 0x080c, 0x9e5f, 0x0005, 0x2001, 0x0002, 0x080c, + 0x61a7, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8440, 0x080c, + 0x898b, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3010, 0x0804, 0xb981, + 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, + 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xb9d2, 0x8001, 0xb842, + 0x6003, 0x0001, 0x080c, 0x8440, 0x080c, 0x898b, 0x00de, 0x00ce, + 0x0898, 0x080c, 0xa7cd, 0x0804, 0xb983, 0x080c, 0xa809, 0x0804, + 0xb983, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xc1b3, 0x00de, 0x0118, + 0x080c, 0x9e2f, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, + 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, + 0x603c, 0x600a, 0x2001, 0x195f, 0x2004, 0x601a, 0x602c, 0x2c08, + 0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x0005, 0x00de, 0x00ce, 0x080c, + 0xa7cd, 0x080c, 0x2fe7, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x3010, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, + 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xa25f, 0x1904, 0xba29, + 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0db4, 0x0096, 0x00d6, + 0x001b, 0x00de, 0x009e, 0x0005, 0xba94, 0xba94, 0xba94, 0xba94, + 0xba94, 0xba94, 0xba94, 0xba94, 0xba94, 0xb844, 0xba94, 0xb84b, + 0xba96, 0xb84b, 0xbab0, 0xba94, 0x080c, 0x0db4, 0x6004, 0x9086, + 0x008b, 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, + 0x1130, 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, + 0x008b, 0x6003, 0x000d, 0x080c, 0x83f8, 0x080c, 0x898b, 0x0005, + 0x080c, 0xc22f, 0x0118, 0x080c, 0xc242, 0x0010, 0x080c, 0xc250, + 0x080c, 0xbd24, 0x080c, 0xbb3b, 0x0570, 0x080c, 0x2fe7, 0x080c, + 0xbb3b, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, + 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x68a0, 0x2c68, + 0x080c, 0x9dd9, 0x0150, 0x6810, 0x6012, 0x080c, 0xbfb5, 0x00c6, + 0x2d60, 0x080c, 0x9e5f, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, + 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x8440, + 0x080c, 0x898b, 0x00c8, 0x080c, 0xc22f, 0x0138, 0x6034, 0x9086, + 0x4000, 0x1118, 0x080c, 0x2fe7, 0x08d0, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, + 0x2fe7, 0x0868, 0x080c, 0x9e5f, 0x0005, 0x6000, 0x908a, 0x0016, + 0x1a0c, 0x0db4, 0x0002, 0xbb1b, 0xbb1b, 0xbb1d, 0xbb1d, 0xbb1d, + 0xbb1b, 0xbb1b, 0x9e5f, 0xbb1b, 0xbb1b, 0xbb1b, 0xbb1b, 0xbb1b, + 0xbb1b, 0xbb1b, 0xbb1b, 0x080c, 0x0db4, 0x080c, 0x98d4, 0x6114, + 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x68a0, 0x009e, 0x0804, + 0x9e2f, 0x9284, 0x0007, 0x1158, 0x9282, 0x1cd0, 0x0240, 0x2001, + 0x1819, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, + 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, + 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x1096, + 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7350, 0x7070, + 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xc23b, 0x0180, + 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, + 0x2fe7, 0x080c, 0xc250, 0x00c6, 0x080c, 0x9e5f, 0x00ce, 0x0060, + 0x080c, 0xbf2f, 0x0148, 0x080c, 0xbd41, 0x1110, 0x080c, 0xa7cd, + 0x00c6, 0x080c, 0x9e2f, 0x00ce, 0x9ce0, 0x0018, 0x7064, 0x9c02, + 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, + 0x2061, 0x1a87, 0x6112, 0x080c, 0x2fe7, 0x9006, 0x0010, 0x9085, + 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9dd9, 0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, + 0x53a2, 0x0118, 0x080c, 0xbc68, 0x0168, 0x080c, 0xbfb5, 0x6023, + 0x0003, 0x2009, 0x004b, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0xbaa0, 0x080c, 0x9e7c, 0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, + 0x080c, 0xbfb5, 0x6023, 0x0003, 0x0016, 0x080c, 0x8582, 0x0076, + 0x903e, 0x080c, 0x8470, 0x2c08, 0x080c, 0xd2d5, 0x007e, 0x001e, + 0xd184, 0x0128, 0x080c, 0x9e2f, 0x9085, 0x0001, 0x0070, 0x080c, + 0x53a2, 0x0128, 0xd18c, 0x1170, 0x080c, 0xbc68, 0x0148, 0x2009, + 0x004c, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, + 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, 0x9dd9, + 0x2c78, 0x0590, 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, 0x2021, + 0x0005, 0x080c, 0xbc7a, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, + 0x0148, 0x2001, 0x1958, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, + 0x9e2f, 0x00d0, 0x2001, 0x1957, 0x200c, 0xd1fc, 0x0120, 0x2f60, + 0x080c, 0x9e2f, 0x0088, 0x2f60, 0x080c, 0x53a2, 0x0138, 0xd18c, + 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, + 0x080c, 0x9ea9, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, + 0x0005, 0x00f6, 0x00c6, 0x0046, 0x080c, 0x9dd9, 0x2c78, 0x0508, + 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, + 0x0489, 0x009e, 0x2001, 0x1956, 0x200c, 0xd1fc, 0x0120, 0x2f60, + 0x080c, 0x9e2f, 0x0060, 0x2f60, 0x080c, 0x53a2, 0x0120, 0xd18c, + 0x1160, 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0x9ea9, 0x9085, + 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, + 0x00c6, 0x080c, 0x4894, 0x00ce, 0x1120, 0x080c, 0x9e2f, 0x9006, + 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, + 0x0001, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, + 0x638a, 0x0158, 0x2001, 0xbc7f, 0x0006, 0x900e, 0x2400, 0x080c, + 0x6ace, 0x080c, 0x68a0, 0x000e, 0x0807, 0x2418, 0x080c, 0x8819, + 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, + 0x859a, 0x008e, 0x080c, 0x8470, 0x2f08, 0x2648, 0x080c, 0xd2d5, + 0xb93c, 0x81ff, 0x090c, 0x866b, 0x080c, 0x898b, 0x012e, 0x007e, + 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9dd9, + 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0001, + 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, - 0x8000, 0xbaa0, 0x080c, 0x9e8f, 0x0560, 0x6057, 0x0000, 0x2b00, - 0x6012, 0x080c, 0xbfa6, 0x6023, 0x0003, 0x0016, 0x080c, 0x8564, - 0x0076, 0x903e, 0x080c, 0x8452, 0x2c08, 0x080c, 0xd2bc, 0x007e, - 0x001e, 0xd184, 0x0128, 0x080c, 0x9e42, 0x9085, 0x0001, 0x0070, - 0x080c, 0x5397, 0x0128, 0xd18c, 0x1170, 0x080c, 0xbc59, 0x0148, - 0x2009, 0x004c, 0x080c, 0x9ebc, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, 0x2009, 0x004d, - 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, - 0x9dec, 0x2c78, 0x0590, 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, - 0x2021, 0x0005, 0x080c, 0xbc6b, 0x9186, 0x004d, 0x0118, 0x9186, - 0x004e, 0x0148, 0x2001, 0x1950, 0x200c, 0xd1fc, 0x0168, 0x2f60, - 0x080c, 0x9e42, 0x00d0, 0x2001, 0x194f, 0x200c, 0xd1fc, 0x0120, - 0x2f60, 0x080c, 0x9e42, 0x0088, 0x2f60, 0x080c, 0x5397, 0x0138, - 0xd18c, 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, - 0x0016, 0x080c, 0x9ebc, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, - 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x080c, 0x9dec, 0x2c78, - 0x0508, 0x7e56, 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, - 0x0004, 0x0489, 0x009e, 0x2001, 0x194e, 0x200c, 0xd1fc, 0x0120, - 0x2f60, 0x080c, 0x9e42, 0x0060, 0x2f60, 0x080c, 0x5397, 0x0120, - 0xd18c, 0x1160, 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0x9ebc, - 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, - 0x0c98, 0x00c6, 0x080c, 0x4889, 0x00ce, 0x1120, 0x080c, 0x9e42, - 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, - 0x9085, 0x0001, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, - 0x080c, 0x637b, 0x0158, 0x2001, 0xbc70, 0x0006, 0x900e, 0x2400, - 0x080c, 0x6abf, 0x080c, 0x6891, 0x000e, 0x0807, 0x2418, 0x080c, - 0x87fb, 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, - 0x080c, 0x857c, 0x008e, 0x080c, 0x8452, 0x2f08, 0x2648, 0x080c, - 0xd2bc, 0xb93c, 0x81ff, 0x090c, 0x864d, 0x080c, 0x896d, 0x012e, - 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9dec, 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xbfa6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0x9ebc, 0x9085, + 0x8000, 0x080c, 0x9e7c, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, + 0xbfb5, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, + 0x164a, 0x00fe, 0x2009, 0x0021, 0x080c, 0x9ea9, 0x9085, 0x0001, + 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, + 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0x9dd9, 0x0198, 0x660a, + 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0001, 0x2900, 0x6016, + 0x001e, 0x0016, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x001e, 0x012e, + 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x9e7c, 0x0188, 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, + 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0x9ea9, 0x9085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, + 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, + 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, 0x0005, + 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, + 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, + 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, + 0x6014, 0x904d, 0x080c, 0xbb3b, 0x0180, 0xa864, 0x9086, 0x0139, + 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, + 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, + 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x9e7c, 0x0198, 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, 0x0001, + 0x2900, 0x6016, 0x080c, 0x2fe7, 0x2009, 0x0028, 0x080c, 0x9ea9, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, + 0x0015, 0x11a8, 0x2011, 0x1823, 0x2204, 0x9086, 0x0074, 0x1178, + 0x00b6, 0x080c, 0xaa58, 0x00be, 0x080c, 0xac97, 0x6003, 0x0001, + 0x6007, 0x0029, 0x080c, 0x8440, 0x080c, 0x898b, 0x0078, 0x6014, + 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, + 0x080c, 0xc174, 0x080c, 0xa7cd, 0x080c, 0x9e2f, 0x0005, 0x0096, + 0x6014, 0x904d, 0x090c, 0x0db4, 0xa87b, 0x0030, 0xa883, 0x0000, + 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a0, 0x012e, 0x009e, 0x080c, 0x9e2f, 0x0c30, + 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x61a7, + 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1823, 0x2204, 0x9086, + 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x62f1, 0x00be, + 0x080c, 0xad68, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, + 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x61a7, 0x6014, 0x2048, + 0xa868, 0xd0fc, 0x0170, 0x080c, 0xa233, 0x0048, 0x6014, 0x2048, + 0xa868, 0xd0fc, 0x0528, 0x080c, 0xa7cd, 0x080c, 0x9e2f, 0x009e, + 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0db4, 0xa87b, + 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6476, + 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x68a0, 0x012e, 0x080c, 0x9e2f, 0x08f8, + 0x6014, 0x904d, 0x090c, 0x0db4, 0xa87b, 0x0030, 0xa883, 0x0000, + 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, + 0x8000, 0x080c, 0x68a0, 0x012e, 0x080c, 0x9e2f, 0x0840, 0xa878, + 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, + 0x0005, 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, + 0x0050, 0x080c, 0x83f8, 0x080c, 0x898b, 0x0005, 0x00c6, 0x6010, + 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0xb844, 0xbe65, 0xbe65, 0xbe68, + 0xd5b3, 0xd5ce, 0xd5d1, 0xb844, 0xb844, 0xb844, 0xb844, 0xb844, + 0xb844, 0xb844, 0xb844, 0x080c, 0x0db4, 0xa001, 0xa001, 0x0005, + 0x0096, 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, + 0x0010, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x0550, 0x2001, 0x1833, 0x2004, 0x9005, 0x1540, 0x00f6, + 0x2c78, 0x080c, 0x9dd9, 0x0508, 0x7810, 0x6012, 0x080c, 0xbfb5, + 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, + 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, + 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x83f8, + 0x080c, 0x898b, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, + 0x1960, 0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, + 0xa87c, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, + 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, + 0x2048, 0x080c, 0x0f9d, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, + 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, + 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, + 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, + 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, + 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, + 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, + 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, 0x009e, 0x001e, 0x0005, + 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, + 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, + 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, + 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, + 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, + 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, + 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, + 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, + 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, + 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, + 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x195a, 0x200c, 0x8000, + 0x2014, 0x2001, 0x0032, 0x080c, 0x8277, 0x2001, 0x195e, 0x82ff, + 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x195c, 0x200c, 0x8000, + 0x2014, 0x2071, 0x1944, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, + 0x8277, 0x2001, 0x195f, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, + 0x2001, 0x1960, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a68, 0x2102, + 0x2001, 0x0032, 0x080c, 0x151a, 0x080c, 0x655b, 0x00ee, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, + 0x195e, 0x2003, 0x0028, 0x2001, 0x195f, 0x2003, 0x0014, 0x2071, + 0x1944, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1960, 0x2009, + 0x001e, 0x2102, 0x2001, 0x1a68, 0x2102, 0x2001, 0x0032, 0x080c, + 0x151a, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, + 0x0110, 0x080c, 0x101d, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x080c, 0x9dd9, 0x0180, 0x2b08, 0x6112, 0x0ca9, + 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0x9ea9, + 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, + 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, 0x708c, + 0x9086, 0x0018, 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, + 0x2c78, 0x080c, 0x8b7e, 0x01d8, 0x7078, 0xaa50, 0x9206, 0x1160, + 0x707c, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, + 0x00be, 0x900e, 0x080c, 0x3030, 0x080c, 0xa233, 0x0020, 0x080c, + 0xa7cd, 0x080c, 0x9e2f, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, + 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x9dd9, 0x0188, 0x2b08, 0x6112, 0x080c, 0xbfb5, 0x6023, + 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0x9ea9, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9e8f, 0x01b8, 0x660a, 0x2b08, 0x6112, - 0x080c, 0xbfa6, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, - 0x080c, 0x164a, 0x00fe, 0x2009, 0x0021, 0x080c, 0x9ebc, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, - 0x00c6, 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0x9dec, 0x0198, - 0x660a, 0x2b08, 0x6112, 0x080c, 0xbfa6, 0x6023, 0x0001, 0x2900, - 0x6016, 0x001e, 0x0016, 0x080c, 0x9ebc, 0x9085, 0x0001, 0x001e, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9e8f, 0x0188, 0x2b08, 0x6112, 0x080c, 0xbfa6, - 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0x9ebc, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, - 0x0044, 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, - 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, - 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, - 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, - 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, - 0x01a8, 0x6014, 0x904d, 0x080c, 0xbb2c, 0x0180, 0xa864, 0x9086, - 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, - 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9e8f, 0x0198, 0x2b08, 0x6112, 0x080c, 0xbfa6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x080c, 0x2fdc, 0x2009, 0x0028, 0x080c, - 0x9ebc, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x9186, 0x0015, 0x11a8, 0x2011, 0x1823, 0x2204, 0x9086, 0x0074, - 0x1178, 0x00b6, 0x080c, 0xaa5c, 0x00be, 0x080c, 0xac9b, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x8422, 0x080c, 0x896d, 0x0078, - 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, - 0x0001, 0x080c, 0xc165, 0x080c, 0xa7d1, 0x080c, 0x9e42, 0x0005, - 0x0096, 0x6014, 0x904d, 0x090c, 0x0db4, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x009e, 0x080c, 0x9e42, - 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, - 0x6198, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1823, 0x2204, - 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x62e2, - 0x00be, 0x080c, 0xad6c, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, - 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x6198, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xa246, 0x0048, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xa7d1, 0x080c, 0x9e42, - 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0db4, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, - 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x080c, 0x9e42, - 0x08f8, 0x6014, 0x904d, 0x090c, 0x0db4, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6891, 0x012e, 0x080c, 0x9e42, 0x0840, - 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, - 0xa882, 0x0005, 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, - 0x6007, 0x0050, 0x080c, 0x83da, 0x080c, 0x896d, 0x0005, 0x00c6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, - 0x9084, 0x000f, 0x0013, 0x00ce, 0x0005, 0xb845, 0xbe56, 0xbe56, - 0xbe59, 0xd59a, 0xd5b5, 0xd5b8, 0xb845, 0xb845, 0xb845, 0xb845, - 0xb845, 0xb845, 0xb845, 0xb845, 0x080c, 0x0db4, 0xa001, 0xa001, - 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, - 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1833, 0x2004, 0x9005, 0x1540, - 0x00f6, 0x2c78, 0x080c, 0x9dec, 0x0508, 0x7810, 0x6012, 0x080c, - 0xbfa6, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, - 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, - 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, - 0x83da, 0x080c, 0x896d, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, - 0x2001, 0x1958, 0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, - 0x2048, 0xa87c, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, - 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, - 0xa878, 0x2048, 0x080c, 0x0f9d, 0x6830, 0x6036, 0x908e, 0x0001, - 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, - 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, - 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, - 0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, - 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, - 0x6910, 0x6112, 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, - 0x6003, 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, 0x009e, 0x001e, - 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, - 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, - 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, - 0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, - 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, - 0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, - 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, - 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, - 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, - 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, - 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1952, 0x200c, - 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x8259, 0x2001, 0x1956, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1954, 0x200c, - 0x8000, 0x2014, 0x2071, 0x193c, 0x711a, 0x721e, 0x2001, 0x0064, - 0x080c, 0x8259, 0x2001, 0x1957, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x1958, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a60, - 0x2102, 0x2001, 0x0032, 0x080c, 0x151a, 0x080c, 0x654c, 0x00ee, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, - 0x2001, 0x1956, 0x2003, 0x0028, 0x2001, 0x1957, 0x2003, 0x0014, - 0x2071, 0x193c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1958, - 0x2009, 0x001e, 0x2102, 0x2001, 0x1a60, 0x2102, 0x2001, 0x0032, - 0x080c, 0x151a, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, - 0x904d, 0x0110, 0x080c, 0x101d, 0x009e, 0x0005, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9dec, 0x0180, 0x2b08, 0x6112, - 0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, - 0x9ebc, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, - 0x708c, 0x9086, 0x0018, 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, - 0x1160, 0x2c78, 0x080c, 0x8b64, 0x01d8, 0x7078, 0xaa50, 0x9206, - 0x1160, 0x707c, 0xaa54, 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, - 0xbaa0, 0x00be, 0x900e, 0x080c, 0x3025, 0x080c, 0xa246, 0x0020, - 0x080c, 0xa7d1, 0x080c, 0x9e42, 0x00fe, 0x00ee, 0x009e, 0x0005, - 0x705c, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x9dec, 0x0188, 0x2b08, 0x6112, 0x080c, 0xbfa6, - 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, 0x080c, 0x9ebc, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0x9dec, 0x0180, 0x2b08, - 0x6112, 0x080c, 0xbfa6, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x080c, 0x9ebc, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, - 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, - 0x718c, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, - 0x0000, 0x2001, 0x1970, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, - 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x1970, 0x0016, 0x200c, - 0x080c, 0xc7ed, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, - 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, 0xa7d1, 0x080c, - 0x9e42, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, - 0x9186, 0x0015, 0x11b8, 0x708c, 0x9086, 0x0004, 0x1198, 0x6014, - 0x2048, 0x2c78, 0x080c, 0x8b64, 0x01a8, 0x7078, 0xaa74, 0x9206, - 0x1130, 0x707c, 0xaa78, 0x9206, 0x1110, 0x080c, 0x2fdc, 0x080c, - 0xa246, 0x0020, 0x080c, 0xa7d1, 0x080c, 0x9e42, 0x00fe, 0x00ee, - 0x009e, 0x0005, 0x705c, 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, - 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1550, 0x708c, - 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x8b64, - 0x05f0, 0x7078, 0xaacc, 0x9206, 0x1180, 0x707c, 0xaad0, 0x9206, - 0x1160, 0x080c, 0x2fdc, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, - 0xc0fd, 0x080c, 0x5347, 0x001e, 0x0010, 0x080c, 0x5138, 0x080c, - 0xbb2c, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x0080, 0x080c, 0xbb2c, 0x01b8, 0x6014, 0x2048, 0x080c, 0x5138, - 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, - 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x6891, - 0x012e, 0x080c, 0x9e42, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, - 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, - 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, - 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, - 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036, 0x080c, 0xbb2c, - 0x0904, 0xc161, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, - 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, - 0xd0f4, 0x1140, 0x080c, 0x6467, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, - 0x0006, 0x2098, 0x080c, 0x0f68, 0x20a9, 0x0004, 0xa85c, 0x9080, - 0x0035, 0x20a0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f68, - 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, - 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, - 0xb804, 0x9084, 0x00ff, 0xa89e, 0x080c, 0x6884, 0x6017, 0x0000, - 0x009e, 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, - 0x00b6, 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, - 0x0260, 0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, - 0x080c, 0x2665, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, - 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x48e9, 0x00a8, - 0x9096, 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, - 0xa8a6, 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, - 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, - 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, - 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xbb1a, 0x01f0, - 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, - 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, - 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, - 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, - 0x0cc8, 0xa974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, - 0x1160, 0xa9a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xb23a, 0x0005, 0x0036, 0x2019, - 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xbb2c, - 0x01c8, 0x080c, 0xbd15, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, - 0x0096, 0x2048, 0xa87c, 0x080c, 0xbd32, 0x1118, 0x080c, 0xa7d1, - 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, - 0x6891, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, - 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, - 0x0020, 0xa87b, 0x0005, 0x080c, 0xbe26, 0xa877, 0x0000, 0x0005, - 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, - 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, - 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, - 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, 0x4a86, 0x004e, 0x003e, - 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1956, 0x2004, 0x601a, - 0x0005, 0x2001, 0x1958, 0x2004, 0x6042, 0x0005, 0x080c, 0x9e42, - 0x0804, 0x896d, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, - 0x0db4, 0x001b, 0x006e, 0x00be, 0x0005, 0xc26d, 0xc94a, 0xcaa5, - 0xc26d, 0xc26d, 0xc26d, 0xc26d, 0xc26d, 0xc2a4, 0xcb29, 0xc26d, - 0xc26d, 0xc26d, 0xc26d, 0xc26d, 0xc26d, 0x080c, 0x0db4, 0x0066, - 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db4, 0x0013, 0x006e, 0x0005, - 0xc288, 0xd091, 0xc288, 0xc288, 0xc288, 0xc288, 0xc288, 0xc288, - 0xd03e, 0xd0e5, 0xc288, 0xd6d5, 0xd70b, 0xd6d5, 0xd70b, 0xc288, - 0x080c, 0x0db4, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0db4, 0x6000, - 0x000a, 0x0005, 0xc2a2, 0xcd06, 0xcdf6, 0xce18, 0xced7, 0xc2a2, - 0xcfb5, 0xcf5f, 0xcb35, 0xd014, 0xd029, 0xc2a2, 0xc2a2, 0xc2a2, - 0xc2a2, 0xc2a2, 0x080c, 0x0db4, 0x91b2, 0x0053, 0x1a0c, 0x0db4, - 0x2100, 0x91b2, 0x0040, 0x1a04, 0xc6eb, 0x0002, 0xc2ee, 0xc4dc, - 0xc2ee, 0xc2ee, 0xc2ee, 0xc4e5, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, - 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, - 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2f0, 0xc353, 0xc362, - 0xc3c6, 0xc3f1, 0xc469, 0xc4c7, 0xc2ee, 0xc2ee, 0xc4e8, 0xc2ee, - 0xc2ee, 0xc4fd, 0xc50a, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, - 0xc58d, 0xc2ee, 0xc2ee, 0xc5a1, 0xc2ee, 0xc2ee, 0xc55c, 0xc2ee, - 0xc2ee, 0xc2ee, 0xc5b9, 0xc2ee, 0xc2ee, 0xc2ee, 0xc636, 0xc2ee, - 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc2ee, 0xc6b3, 0x080c, 0x0db4, - 0x080c, 0x6529, 0x1150, 0x2001, 0x1836, 0x2004, 0xd0cc, 0x1128, - 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, - 0x0009, 0x6017, 0x0000, 0x0804, 0xc4d5, 0x080c, 0x6512, 0x00e6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, - 0x2019, 0x0029, 0x080c, 0x8564, 0x0076, 0x903e, 0x080c, 0x8452, - 0x2c08, 0x080c, 0xd2bc, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, - 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6256, 0xbe04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, - 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xd883, 0x002e, 0x001e, - 0x1178, 0x080c, 0xd1ef, 0x1904, 0xc3be, 0x080c, 0xd18b, 0x1120, - 0x6007, 0x0008, 0x0804, 0xc4d5, 0x6007, 0x0009, 0x0804, 0xc4d5, - 0x080c, 0xd3e6, 0x0128, 0x080c, 0xd1ef, 0x0d78, 0x0804, 0xc3be, - 0x6017, 0x1900, 0x0c88, 0x080c, 0x30ff, 0x1904, 0xc6e8, 0x6106, - 0x080c, 0xd140, 0x6007, 0x0006, 0x0804, 0xc4d5, 0x6007, 0x0007, - 0x0804, 0xc4d5, 0x080c, 0xd747, 0x1904, 0xc6e8, 0x080c, 0x30ff, - 0x1904, 0xc6e8, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, - 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6184, 0x96b4, - 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, - 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, - 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, - 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, 0x0014, - 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, - 0x602f, 0x0007, 0x00b0, 0x00ee, 0x080c, 0xd252, 0x1190, 0x9686, - 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, - 0x3025, 0x002e, 0x080c, 0x62e2, 0x6007, 0x000a, 0x00de, 0x0804, - 0xc4d5, 0x6007, 0x000b, 0x00de, 0x0804, 0xc4d5, 0x080c, 0x2fdc, - 0x080c, 0xc241, 0x6007, 0x0001, 0x0804, 0xc4d5, 0x080c, 0xd747, - 0x1904, 0xc6e8, 0x080c, 0x30ff, 0x1904, 0xc6e8, 0x2071, 0x0260, - 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, 0x7030, - 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, 0x0707, - 0x09e8, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3025, - 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xd863, 0x0804, - 0xc4d5, 0x080c, 0x6529, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, - 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xc2fd, 0x080c, 0x6512, - 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c0, - 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x61c4, 0x002e, 0x0050, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, - 0x1904, 0xc3be, 0x080c, 0xd25f, 0x1120, 0x6007, 0x000e, 0x0804, - 0xc4d5, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x2fdc, - 0x080c, 0xc241, 0x004e, 0x0016, 0x9006, 0x2009, 0x1854, 0x210c, - 0x0048, 0x2009, 0x0029, 0x080c, 0xd54b, 0x6010, 0x2058, 0xb800, - 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xc4d5, - 0x2001, 0x0001, 0x080c, 0x6184, 0x0156, 0x0016, 0x0026, 0x0036, - 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xae0c, - 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, - 0x8637, 0x9682, 0x0004, 0x0a04, 0xc3be, 0x9682, 0x0007, 0x0a04, - 0xc41a, 0x0804, 0xc3be, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, - 0xc4d5, 0x080c, 0x6529, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, - 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xc2fd, 0x080c, 0x6512, - 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, 0x9086, 0x0001, - 0x000e, 0x0170, 0x9082, 0x0006, 0x0690, 0x0150, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc3be, - 0x080c, 0xd28d, 0x1130, 0x080c, 0xd18b, 0x1118, 0x6007, 0x0010, - 0x04e0, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x2fdc, - 0x080c, 0xc241, 0x004e, 0x0016, 0x9006, 0x2009, 0x1854, 0x210c, - 0x0048, 0x2009, 0x0029, 0x080c, 0xd54b, 0x6010, 0x2058, 0xb800, - 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, - 0xd3e6, 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0980, - 0x0804, 0xc3be, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, - 0x30ff, 0x1904, 0xc6e8, 0x080c, 0xd747, 0x1904, 0xc6e8, 0x080c, - 0xc888, 0x1904, 0xc3be, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, - 0x8422, 0x080c, 0x896d, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x8422, 0x080c, 0x896d, 0x0cb0, 0x6007, 0x0005, 0x0c68, - 0x080c, 0xd747, 0x1904, 0xc6e8, 0x080c, 0x30ff, 0x1904, 0xc6e8, - 0x080c, 0xc888, 0x1904, 0xc3be, 0x6007, 0x0020, 0x6003, 0x0001, - 0x080c, 0x8422, 0x080c, 0x896d, 0x0005, 0x080c, 0x30ff, 0x1904, - 0xc6e8, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x8422, 0x080c, - 0x896d, 0x0005, 0x080c, 0xd747, 0x1904, 0xc6e8, 0x080c, 0x30ff, - 0x1904, 0xc6e8, 0x080c, 0xc888, 0x1904, 0xc3be, 0x0016, 0x0026, - 0x00e6, 0x2071, 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, - 0x080c, 0xbb1a, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, - 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, - 0x2c08, 0x9006, 0x080c, 0xd51d, 0x1180, 0x7244, 0x9286, 0xffff, - 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, - 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, - 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, 0x9e42, 0x2160, - 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x8422, 0x080c, 0x896d, - 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x6184, - 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, - 0x2011, 0x0276, 0x080c, 0xae0c, 0x003e, 0x002e, 0x001e, 0x015e, - 0x0120, 0x6007, 0x0031, 0x0804, 0xc4d5, 0x080c, 0xaa74, 0x080c, - 0x6f9b, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x6fb5, 0x1138, - 0x080c, 0x727f, 0x080c, 0x5cda, 0x080c, 0x6ecd, 0x0010, 0x080c, - 0x6f73, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x30ff, 0x1904, - 0xc6e8, 0x080c, 0xc888, 0x1904, 0xc3be, 0x6106, 0x080c, 0xc8a4, - 0x1120, 0x6007, 0x002b, 0x0804, 0xc4d5, 0x6007, 0x002c, 0x0804, - 0xc4d5, 0x080c, 0xd747, 0x1904, 0xc6e8, 0x080c, 0x30ff, 0x1904, - 0xc6e8, 0x080c, 0xc888, 0x1904, 0xc3be, 0x6106, 0x080c, 0xc8a9, - 0x1120, 0x6007, 0x002e, 0x0804, 0xc4d5, 0x6007, 0x002f, 0x0804, - 0xc4d5, 0x080c, 0x30ff, 0x1904, 0xc6e8, 0x00e6, 0x00d6, 0x00c6, - 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, - 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, - 0x00ee, 0x0804, 0xc4dc, 0x080c, 0x5393, 0xd0e4, 0x0904, 0xc633, - 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, - 0x080c, 0x6567, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, - 0xb814, 0x9206, 0x0510, 0x080c, 0x6563, 0x15b8, 0x2069, 0x1800, - 0x687c, 0x9206, 0x1590, 0x6878, 0x9106, 0x1578, 0x7210, 0x080c, - 0xbb1a, 0x0590, 0x080c, 0xc773, 0x0578, 0x080c, 0xd5c7, 0x0560, - 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x83da, 0x080c, - 0x896d, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, - 0x0150, 0x080c, 0xbb1a, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, - 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, - 0xd51d, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, - 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, - 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x30ff, - 0x1904, 0xc6e8, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, - 0x9086, 0x0006, 0x1904, 0xc4dc, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0x5393, 0xd0e4, 0x0904, 0xc6ab, 0x2069, 0x1800, 0x2071, 0x026c, - 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd51d, 0x2c10, 0x00ce, - 0x05e8, 0x080c, 0xbb1a, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, - 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, 0xb750, 0x002e, - 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, - 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, - 0x2004, 0x9005, 0x0170, 0x080c, 0xc773, 0x0904, 0xc62c, 0x0056, - 0x7510, 0x7614, 0x080c, 0xd5e0, 0x005e, 0x00ce, 0x00de, 0x00ee, - 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, - 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, 0x0c78, 0x6007, 0x003b, - 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x83da, - 0x080c, 0x896d, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, - 0x0000, 0x0804, 0xc603, 0x00e6, 0x0026, 0x080c, 0x6529, 0x0550, - 0x080c, 0x6512, 0x080c, 0xd7b9, 0x1518, 0x2071, 0x1800, 0x70d8, - 0x9085, 0x0003, 0x70da, 0x00f6, 0x2079, 0x0100, 0x72ac, 0x9284, - 0x00ff, 0x707a, 0x78e6, 0x9284, 0xff00, 0x727c, 0x9205, 0x707e, - 0x78ea, 0x00fe, 0x70e3, 0x0000, 0x080c, 0x6567, 0x0120, 0x2011, - 0x19d0, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2dbd, 0x0010, - 0x080c, 0xd7eb, 0x002e, 0x00ee, 0x080c, 0x9e42, 0x0804, 0xc4db, - 0x080c, 0x9e42, 0x0005, 0x2600, 0x0002, 0xc6ff, 0xc6ff, 0xc6ff, - 0xc6ff, 0xc6ff, 0xc701, 0xc6ff, 0xc6ff, 0xc6ff, 0xc6ff, 0xc71e, - 0xc6ff, 0xc6ff, 0xc6ff, 0xc730, 0xc73d, 0xc76e, 0xc6ff, 0x080c, - 0x0db4, 0x080c, 0xd747, 0x1d20, 0x080c, 0x30ff, 0x1d08, 0x080c, - 0xc888, 0x1148, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, - 0x080c, 0x8422, 0x0005, 0x080c, 0x2fdc, 0x080c, 0xc241, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x8422, 0x0005, 0x080c, 0xd747, - 0x1938, 0x080c, 0x30ff, 0x1920, 0x080c, 0xc888, 0x1d60, 0x703c, - 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x8422, 0x0005, - 0x080c, 0xc790, 0x0904, 0xc6e8, 0x6007, 0x004e, 0x6003, 0x0001, - 0x080c, 0x8422, 0x080c, 0x896d, 0x0005, 0x6007, 0x004f, 0x6017, - 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, - 0x1160, 0x7140, 0x2001, 0x198d, 0x2004, 0x9106, 0x11b0, 0x7144, - 0x2001, 0x198e, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, - 0x000a, 0x080c, 0xae20, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, - 0x0001, 0x080c, 0x8422, 0x080c, 0x896d, 0x0005, 0x6007, 0x0050, - 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, - 0x00c6, 0x2260, 0x6010, 0x2058, 0xb8bc, 0xd084, 0x0150, 0x7128, - 0x6048, 0x9106, 0x1120, 0x712c, 0x6044, 0x9106, 0x0110, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, - 0x0016, 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1800, 0x708c, 0x908a, 0x00f9, 0x16e8, 0x20e1, - 0x0000, 0x2001, 0x1970, 0x2003, 0x0000, 0x080c, 0x1004, 0x05a0, - 0x2900, 0x6016, 0x708c, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, - 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x2001, 0x1970, 0x0016, 0x200c, 0x0471, 0x001e, - 0x2940, 0x080c, 0x1004, 0x01c0, 0x2900, 0xa006, 0x2100, 0x81ff, - 0x0180, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x2001, 0x1970, 0x0016, 0x200c, 0x00b1, 0x001e, - 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x708f, 0x0000, - 0x6014, 0x2048, 0x080c, 0x0f9d, 0x9006, 0x012e, 0x01de, 0x01ce, - 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x918c, 0xffff, 0x11a8, 0x080c, 0x2243, 0x2099, - 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, - 0x00f8, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x2243, 0x2099, - 0x0260, 0x0ca8, 0x080c, 0x2243, 0x2061, 0x1970, 0x6004, 0x2098, - 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, - 0x4003, 0x22a8, 0x8108, 0x080c, 0x2243, 0x2099, 0x0260, 0x0ca8, - 0x2061, 0x1970, 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, - 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, - 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, - 0x080c, 0x225b, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, - 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, - 0x22a8, 0x8108, 0x080c, 0x225b, 0x20a1, 0x0240, 0x0c98, 0x080c, - 0x225b, 0x2061, 0x1973, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, - 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, - 0x22a8, 0x8108, 0x080c, 0x225b, 0x20a1, 0x0240, 0x0c98, 0x2061, - 0x1973, 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, - 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, + 0x2091, 0x8000, 0x0016, 0x080c, 0x9dd9, 0x0180, 0x2b08, 0x6112, + 0x080c, 0xbfb5, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, + 0x9ea9, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, + 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, + 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, 0x718c, + 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, + 0x2001, 0x1978, 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, + 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, + 0x9080, 0x001b, 0x20a0, 0x2001, 0x1978, 0x0016, 0x200c, 0x080c, + 0xc7fc, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, + 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, 0xa7cd, 0x080c, 0x9e2f, + 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, + 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, + 0x0015, 0x11b8, 0x708c, 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, + 0x2c78, 0x080c, 0x8b7e, 0x01a8, 0x7078, 0xaa74, 0x9206, 0x1130, + 0x707c, 0xaa78, 0x9206, 0x1110, 0x080c, 0x2fe7, 0x080c, 0xa233, + 0x0020, 0x080c, 0xa7cd, 0x080c, 0x9e2f, 0x00fe, 0x00ee, 0x009e, + 0x0005, 0x705c, 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, + 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1550, 0x708c, 0x9086, + 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, 0x080c, 0x8b7e, 0x05f0, + 0x7078, 0xaacc, 0x9206, 0x1180, 0x707c, 0xaad0, 0x9206, 0x1160, + 0x080c, 0x2fe7, 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, + 0x080c, 0x5352, 0x001e, 0x0010, 0x080c, 0x5143, 0x080c, 0xbb3b, + 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, + 0x080c, 0xbb3b, 0x01b8, 0x6014, 0x2048, 0x080c, 0x5143, 0x1d70, + 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, + 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0x080c, 0x68a0, 0x012e, + 0x080c, 0x9e2f, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, 0xaad0, + 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, + 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, + 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, + 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036, 0x080c, 0xbb3b, 0x0904, + 0xc170, 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, + 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, + 0x1140, 0x080c, 0x6476, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, + 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, + 0x2098, 0x080c, 0x0f68, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, + 0x20a0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f68, 0x00ce, + 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, + 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, + 0x9084, 0x00ff, 0xa89e, 0x080c, 0x6893, 0x6017, 0x0000, 0x009e, + 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, + 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, + 0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, + 0x2670, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, + 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x48f4, 0x00a8, 0x9096, + 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, + 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, + 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, + 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, + 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xbb29, 0x01f0, 0x2260, + 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, + 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, + 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, + 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, + 0xa974, 0xd1cc, 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, + 0xa9a8, 0x918c, 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0xa834, + 0xa938, 0x9115, 0x190c, 0xb236, 0x0005, 0x0036, 0x2019, 0x0001, + 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xbb3b, 0x01c8, + 0x080c, 0xbd24, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, + 0x2048, 0xa87c, 0x080c, 0xbd41, 0x1118, 0x080c, 0xa7cd, 0x0040, + 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x68a0, + 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, + 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, + 0xa87b, 0x0005, 0x080c, 0xbe35, 0xa877, 0x0000, 0x0005, 0x2001, + 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, + 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, + 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, + 0x00be, 0x2021, 0x0007, 0x080c, 0x4a91, 0x004e, 0x003e, 0x0005, + 0x0c51, 0x1d81, 0x0005, 0x2001, 0x195e, 0x2004, 0x601a, 0x0005, + 0x2001, 0x1960, 0x2004, 0x6042, 0x0005, 0x080c, 0x9e2f, 0x0804, + 0x898b, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0db4, + 0x001b, 0x006e, 0x00be, 0x0005, 0xc27c, 0xc959, 0xcab4, 0xc27c, + 0xc27c, 0xc27c, 0xc27c, 0xc27c, 0xc2b3, 0xcb38, 0xc27c, 0xc27c, + 0xc27c, 0xc27c, 0xc27c, 0xc27c, 0x080c, 0x0db4, 0x0066, 0x6000, + 0x90b2, 0x0016, 0x1a0c, 0x0db4, 0x0013, 0x006e, 0x0005, 0xc297, + 0xd0aa, 0xc297, 0xc297, 0xc297, 0xc297, 0xc297, 0xc297, 0xd057, + 0xd0fe, 0xc297, 0xd6ee, 0xd724, 0xd6ee, 0xd724, 0xc297, 0x080c, + 0x0db4, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0db4, 0x6000, 0x000a, + 0x0005, 0xc2b1, 0xcd16, 0xce08, 0xce2b, 0xceeb, 0xc2b1, 0xcfca, + 0xcf73, 0xcb44, 0xd02d, 0xd042, 0xc2b1, 0xc2b1, 0xc2b1, 0xc2b1, + 0xc2b1, 0x080c, 0x0db4, 0x91b2, 0x0053, 0x1a0c, 0x0db4, 0x2100, + 0x91b2, 0x0040, 0x1a04, 0xc6fa, 0x0002, 0xc2fd, 0xc4eb, 0xc2fd, + 0xc2fd, 0xc2fd, 0xc4f4, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, + 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, + 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2ff, 0xc362, 0xc371, 0xc3d5, + 0xc400, 0xc478, 0xc4d6, 0xc2fd, 0xc2fd, 0xc4f7, 0xc2fd, 0xc2fd, + 0xc50c, 0xc519, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc59c, + 0xc2fd, 0xc2fd, 0xc5b0, 0xc2fd, 0xc2fd, 0xc56b, 0xc2fd, 0xc2fd, + 0xc2fd, 0xc5c8, 0xc2fd, 0xc2fd, 0xc2fd, 0xc645, 0xc2fd, 0xc2fd, + 0xc2fd, 0xc2fd, 0xc2fd, 0xc2fd, 0xc6c2, 0x080c, 0x0db4, 0x080c, + 0x6538, 0x1150, 0x2001, 0x1836, 0x2004, 0xd0cc, 0x1128, 0x9084, + 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, 0x0009, + 0x6017, 0x0000, 0x0804, 0xc4e4, 0x080c, 0x6521, 0x00e6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, + 0x0029, 0x080c, 0x8582, 0x0076, 0x903e, 0x080c, 0x8470, 0x2c08, + 0x080c, 0xd2d5, 0x007e, 0x001e, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x6610, 0x2658, 0x080c, 0x6265, 0xbe04, 0x9684, 0x00ff, + 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, + 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xd89c, 0x002e, 0x001e, 0x1178, + 0x080c, 0xd208, 0x1904, 0xc3cd, 0x080c, 0xd1a4, 0x1120, 0x6007, + 0x0008, 0x0804, 0xc4e4, 0x6007, 0x0009, 0x0804, 0xc4e4, 0x080c, + 0xd3ff, 0x0128, 0x080c, 0xd208, 0x0d78, 0x0804, 0xc3cd, 0x6017, + 0x1900, 0x0c88, 0x080c, 0x310a, 0x1904, 0xc6f7, 0x6106, 0x080c, + 0xd159, 0x6007, 0x0006, 0x0804, 0xc4e4, 0x6007, 0x0007, 0x0804, + 0xc4e4, 0x080c, 0xd760, 0x1904, 0xc6f7, 0x080c, 0x310a, 0x1904, + 0xc6f7, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, + 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6193, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, + 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, + 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, + 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, + 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, + 0x0007, 0x00b0, 0x00ee, 0x080c, 0xd26b, 0x1190, 0x9686, 0x0006, + 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3030, + 0x002e, 0x080c, 0x62f1, 0x6007, 0x000a, 0x00de, 0x0804, 0xc4e4, + 0x6007, 0x000b, 0x00de, 0x0804, 0xc4e4, 0x080c, 0x2fe7, 0x080c, + 0xc250, 0x6007, 0x0001, 0x0804, 0xc4e4, 0x080c, 0xd760, 0x1904, + 0xc6f7, 0x080c, 0x310a, 0x1904, 0xc6f7, 0x2071, 0x0260, 0x7034, + 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, + 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, + 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3030, 0x002e, + 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xd87c, 0x0804, 0xc4e4, + 0x080c, 0x6538, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, + 0x9086, 0x0008, 0x1110, 0x0804, 0xc30c, 0x080c, 0x6521, 0x6610, + 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c0, 0x1138, + 0x0026, 0x2001, 0x0006, 0x080c, 0x61d3, 0x002e, 0x0050, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, + 0xc3cd, 0x080c, 0xd278, 0x1120, 0x6007, 0x000e, 0x0804, 0xc4e4, + 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x2fe7, 0x080c, + 0xc250, 0x004e, 0x0016, 0x9006, 0x2009, 0x185c, 0x210c, 0x0048, + 0x2009, 0x0029, 0x080c, 0xd564, 0x6010, 0x2058, 0xb800, 0xc0e5, + 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xc4e4, 0x2001, + 0x0001, 0x080c, 0x6193, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xae08, 0x003e, + 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, + 0x9682, 0x0004, 0x0a04, 0xc3cd, 0x9682, 0x0007, 0x0a04, 0xc429, + 0x0804, 0xc3cd, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xc4e4, + 0x080c, 0x6538, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, + 0x9086, 0x0008, 0x1110, 0x0804, 0xc30c, 0x080c, 0x6521, 0x6610, + 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, 0x9086, 0x0001, 0x000e, + 0x0170, 0x9082, 0x0006, 0x0690, 0x0150, 0x96b4, 0xff00, 0x8637, + 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc3cd, 0x080c, + 0xd2a6, 0x1130, 0x080c, 0xd1a4, 0x1118, 0x6007, 0x0010, 0x04e0, + 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x2fe7, 0x080c, + 0xc250, 0x004e, 0x0016, 0x9006, 0x2009, 0x185c, 0x210c, 0x0048, + 0x2009, 0x0029, 0x080c, 0xd564, 0x6010, 0x2058, 0xb800, 0xc0e5, + 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, 0xd3ff, + 0x0140, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0980, 0x0804, + 0xc3cd, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x310a, + 0x1904, 0xc6f7, 0x080c, 0xd760, 0x1904, 0xc6f7, 0x080c, 0xc897, + 0x1904, 0xc3cd, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x8440, + 0x080c, 0x898b, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x8440, 0x080c, 0x898b, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, + 0xd760, 0x1904, 0xc6f7, 0x080c, 0x310a, 0x1904, 0xc6f7, 0x080c, + 0xc897, 0x1904, 0xc3cd, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, + 0x8440, 0x080c, 0x898b, 0x0005, 0x080c, 0x310a, 0x1904, 0xc6f7, + 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x8440, 0x080c, 0x898b, + 0x0005, 0x080c, 0xd760, 0x1904, 0xc6f7, 0x080c, 0x310a, 0x1904, + 0xc6f7, 0x080c, 0xc897, 0x1904, 0xc3cd, 0x0016, 0x0026, 0x00e6, + 0x2071, 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, + 0xbb29, 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, + 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, + 0x9006, 0x080c, 0xd536, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, + 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, + 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, + 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, 0x9e2f, 0x2160, 0x6007, + 0x0025, 0x6003, 0x0001, 0x080c, 0x8440, 0x080c, 0x898b, 0x00ee, + 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x6193, 0x0156, + 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, + 0x0276, 0x080c, 0xae08, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, + 0x6007, 0x0031, 0x0804, 0xc4e4, 0x080c, 0xaa70, 0x080c, 0x6faa, + 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, 0x6fc4, 0x1138, 0x080c, + 0x728c, 0x080c, 0x5ce5, 0x080c, 0x6edc, 0x0010, 0x080c, 0x6f82, + 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, 0x310a, 0x1904, 0xc6f7, + 0x080c, 0xc897, 0x1904, 0xc3cd, 0x6106, 0x080c, 0xc8b3, 0x1120, + 0x6007, 0x002b, 0x0804, 0xc4e4, 0x6007, 0x002c, 0x0804, 0xc4e4, + 0x080c, 0xd760, 0x1904, 0xc6f7, 0x080c, 0x310a, 0x1904, 0xc6f7, + 0x080c, 0xc897, 0x1904, 0xc3cd, 0x6106, 0x080c, 0xc8b8, 0x1120, + 0x6007, 0x002e, 0x0804, 0xc4e4, 0x6007, 0x002f, 0x0804, 0xc4e4, + 0x080c, 0x310a, 0x1904, 0xc6f7, 0x00e6, 0x00d6, 0x00c6, 0x6010, + 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, + 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, + 0x0804, 0xc4eb, 0x080c, 0x539e, 0xd0e4, 0x0904, 0xc642, 0x2071, + 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, + 0x6576, 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, + 0x9206, 0x0510, 0x080c, 0x6572, 0x15b8, 0x2069, 0x1800, 0x687c, + 0x9206, 0x1590, 0x6878, 0x9106, 0x1578, 0x7210, 0x080c, 0xbb29, + 0x0590, 0x080c, 0xc782, 0x0578, 0x080c, 0xd5e0, 0x0560, 0x622e, + 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, + 0x080c, 0xbb29, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, + 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd536, + 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, + 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, + 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x310a, 0x1904, + 0xc6f7, 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, + 0x0006, 0x1904, 0xc4eb, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x539e, + 0xd0e4, 0x0904, 0xc6ba, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, + 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, + 0x2c08, 0x9085, 0x0001, 0x080c, 0xd536, 0x2c10, 0x00ce, 0x05e8, + 0x080c, 0xbb29, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, + 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, 0xb74f, 0x002e, 0x00ce, + 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, + 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, + 0x9005, 0x0170, 0x080c, 0xc782, 0x0904, 0xc63b, 0x0056, 0x7510, + 0x7614, 0x080c, 0xd5f9, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x0c78, 0x6007, 0x003b, 0x602f, + 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, 0x080c, 0x83f8, 0x080c, + 0x898b, 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, + 0x0804, 0xc612, 0x00e6, 0x0026, 0x080c, 0x6538, 0x0550, 0x080c, + 0x6521, 0x080c, 0xd7d2, 0x1518, 0x2071, 0x1800, 0x70d8, 0x9085, + 0x0003, 0x70da, 0x00f6, 0x2079, 0x0100, 0x72ac, 0x9284, 0x00ff, + 0x707a, 0x78e6, 0x9284, 0xff00, 0x727c, 0x9205, 0x707e, 0x78ea, + 0x00fe, 0x70e3, 0x0000, 0x080c, 0x6576, 0x0120, 0x2011, 0x19d8, + 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2dc8, 0x0010, 0x080c, + 0xd804, 0x002e, 0x00ee, 0x080c, 0x9e2f, 0x0804, 0xc4ea, 0x080c, + 0x9e2f, 0x0005, 0x2600, 0x0002, 0xc70e, 0xc70e, 0xc70e, 0xc70e, + 0xc70e, 0xc710, 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc72d, 0xc70e, + 0xc70e, 0xc70e, 0xc73f, 0xc74c, 0xc77d, 0xc70e, 0x080c, 0x0db4, + 0x080c, 0xd760, 0x1d20, 0x080c, 0x310a, 0x1d08, 0x080c, 0xc897, + 0x1148, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, + 0x8440, 0x0005, 0x080c, 0x2fe7, 0x080c, 0xc250, 0x6007, 0x0001, + 0x6003, 0x0001, 0x080c, 0x8440, 0x0005, 0x080c, 0xd760, 0x1938, + 0x080c, 0x310a, 0x1920, 0x080c, 0xc897, 0x1d60, 0x703c, 0x6016, + 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x8440, 0x0005, 0x080c, + 0xc79f, 0x0904, 0xc6f7, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, + 0x8440, 0x080c, 0x898b, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, + 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, + 0x7140, 0x2001, 0x1995, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, + 0x1996, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, + 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, + 0x080c, 0xae1c, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, + 0x080c, 0x8440, 0x080c, 0x898b, 0x0005, 0x6007, 0x0050, 0x703c, + 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, + 0x2260, 0x6010, 0x2058, 0xb8bc, 0xd084, 0x0150, 0x7128, 0x6048, + 0x9106, 0x1120, 0x712c, 0x6044, 0x9106, 0x0110, 0x9006, 0x0010, + 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, + 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, + 0x2071, 0x1800, 0x708c, 0x908a, 0x00f9, 0x16e8, 0x20e1, 0x0000, + 0x2001, 0x1978, 0x2003, 0x0000, 0x080c, 0x1004, 0x05a0, 0x2900, + 0x6016, 0x708c, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, + 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, + 0x20a0, 0x2001, 0x1978, 0x0016, 0x200c, 0x0471, 0x001e, 0x2940, + 0x080c, 0x1004, 0x01c0, 0x2900, 0xa006, 0x2100, 0x81ff, 0x0180, + 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, + 0x20a0, 0x2001, 0x1978, 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, + 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x708f, 0x0000, 0x6014, + 0x2048, 0x080c, 0x0f9d, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, + 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x918c, 0xffff, 0x11a8, 0x080c, 0x224e, 0x2099, 0x026c, + 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, + 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x224e, 0x2099, 0x0260, + 0x0ca8, 0x080c, 0x224e, 0x2061, 0x1978, 0x6004, 0x2098, 0x6008, + 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, + 0x22a8, 0x8108, 0x080c, 0x224e, 0x2099, 0x0260, 0x0ca8, 0x2061, + 0x1978, 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, + 0x2001, 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, - 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, - 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, - 0x0001, 0x006e, 0x00be, 0x0005, 0x00d6, 0x080c, 0xc920, 0x00de, - 0x0005, 0x00d6, 0x080c, 0xc92d, 0x1520, 0x680c, 0x908c, 0xff00, - 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, - 0x0130, 0x9006, 0x080c, 0xd863, 0x2009, 0x0001, 0x0078, 0xd1ec, - 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x2665, 0x1148, - 0x2001, 0x0001, 0x080c, 0xd863, 0x2110, 0x900e, 0x080c, 0x3025, - 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, - 0x00c6, 0x080c, 0x9e8f, 0x05a8, 0x0016, 0x0026, 0x00c6, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2665, 0x1578, 0x080c, - 0x61e7, 0x1560, 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, - 0x6012, 0x080c, 0xd747, 0x11d8, 0x080c, 0x30ff, 0x11c0, 0x080c, - 0xc888, 0x0510, 0x2001, 0x0007, 0x080c, 0x6198, 0x2001, 0x0007, - 0x080c, 0x61c4, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x8422, 0x080c, 0x896d, 0x0010, 0x080c, - 0x9e42, 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, 0x080c, 0x9e42, - 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, 0x9e42, 0x9006, 0x0c98, - 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, - 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, - 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, 0x6904, - 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, 0x6800, - 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e, 0x0014, 0x0110, 0x908e, - 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0db4, 0x91b6, - 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xca75, 0x0092, - 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0db4, 0x2001, - 0x0007, 0x080c, 0x61c4, 0x080c, 0x8861, 0x080c, 0x9e72, 0x080c, - 0x896d, 0x0005, 0xc9aa, 0xc9ac, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9ac, - 0xc9bb, 0xca6e, 0xca0d, 0xca6e, 0xca1f, 0xca6e, 0xc9bb, 0xca6e, - 0xca66, 0xca6e, 0xca66, 0xca6e, 0xca6e, 0xc9aa, 0xc9aa, 0xc9aa, - 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, - 0xc9ac, 0xc9aa, 0xca6e, 0xc9aa, 0xc9aa, 0xca6e, 0xc9aa, 0xca6b, - 0xca6e, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, 0xca6e, 0xca6e, 0xc9aa, - 0xca6e, 0xca6e, 0xc9aa, 0xc9b6, 0xc9aa, 0xc9aa, 0xc9aa, 0xc9aa, - 0xca6a, 0xca6e, 0xc9aa, 0xc9aa, 0xca6e, 0xca6e, 0xc9aa, 0xc9aa, - 0xc9aa, 0xc9aa, 0x080c, 0x0db4, 0x080c, 0x8861, 0x080c, 0xc244, - 0x6003, 0x0002, 0x080c, 0x896d, 0x0804, 0xca74, 0x9006, 0x080c, - 0x6184, 0x0804, 0xca6e, 0x080c, 0x6563, 0x1904, 0xca6e, 0x9006, - 0x080c, 0x6184, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, - 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x0428, - 0x6010, 0x2058, 0xb8b0, 0x9005, 0x1178, 0x080c, 0xc22c, 0x1904, - 0xca6e, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0007, 0x080c, 0x4a86, - 0x004e, 0x003e, 0x0804, 0xca6e, 0x080c, 0x3130, 0x1904, 0xca6e, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, - 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x2001, 0x0002, 0x080c, - 0x6198, 0x080c, 0x8861, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x8422, 0x080c, 0x896d, 0x6110, 0x2158, 0x2009, - 0x0001, 0x080c, 0x802f, 0x0804, 0xca74, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xca6e, 0x9686, - 0x0004, 0x0904, 0xca6e, 0x2001, 0x0004, 0x0804, 0xca6c, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, - 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4a86, 0x004e, 0x003e, - 0x2001, 0x0006, 0x080c, 0xca92, 0x6610, 0x2658, 0xbe04, 0x0066, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, - 0x0006, 0x080c, 0x61c4, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, - 0x2001, 0x0006, 0x080c, 0x6198, 0x080c, 0x6563, 0x11f8, 0x2001, - 0x1836, 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, - 0x00fe, 0x0804, 0xc9f5, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, - 0x0449, 0x0020, 0x0018, 0x0010, 0x080c, 0x61c4, 0x080c, 0x8861, - 0x080c, 0x9e42, 0x080c, 0x896d, 0x0005, 0x2600, 0x0002, 0xca89, - 0xca89, 0xca89, 0xca89, 0xca89, 0xca8b, 0xca89, 0xca89, 0xca89, - 0xca89, 0xca8b, 0xca89, 0xca89, 0xca89, 0xca8b, 0xca8b, 0xca8b, - 0xca8b, 0x080c, 0x0db4, 0x080c, 0x8861, 0x080c, 0x9e42, 0x080c, - 0x896d, 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, - 0xd184, 0x0138, 0x080c, 0x6198, 0x9006, 0x080c, 0x6184, 0x080c, - 0x3005, 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, - 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0db4, 0x91b6, - 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0db4, - 0x006b, 0x0005, 0xa8b2, 0xa8b2, 0xa8b2, 0xa8b2, 0xcb27, 0xa8b2, - 0xcb11, 0xcad2, 0xa8b2, 0xa8b2, 0xa8b2, 0xa8b2, 0xa8b2, 0xa8b2, - 0xa8b2, 0xa8b2, 0xcb27, 0xa8b2, 0xcb11, 0xcb18, 0xa8b2, 0xa8b2, - 0xa8b2, 0xa8b2, 0x00f6, 0x080c, 0x6563, 0x11d8, 0x080c, 0xc22c, - 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb8b0, 0x9005, 0x0190, 0x9006, - 0x080c, 0x6184, 0x2001, 0x0002, 0x080c, 0x6198, 0x6023, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x8422, 0x080c, 0x896d, - 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2665, - 0x11b0, 0x080c, 0x6247, 0x0118, 0x080c, 0x9e42, 0x0080, 0xb810, - 0x0006, 0xb814, 0x0006, 0xb8b0, 0x0006, 0x080c, 0x5cf4, 0x000e, - 0xb8b2, 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0x9e42, 0x00fe, - 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9e42, 0x0005, - 0x080c, 0xac98, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x8422, 0x080c, 0x896d, 0x0010, 0x080c, 0x9e42, 0x0005, 0x0804, - 0x9e42, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0db4, 0x080c, 0x8861, - 0x080c, 0x9e72, 0x080c, 0x896d, 0x0005, 0x9182, 0x0040, 0x0002, - 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4d, 0xcb4b, 0xcb4b, 0xcb4b, - 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, 0xcb4b, - 0xcb4b, 0xcb4b, 0xcb4b, 0x080c, 0x0db4, 0x0096, 0x00b6, 0x00d6, + 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, + 0x2266, 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, + 0x23a8, 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, + 0x8108, 0x080c, 0x2266, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x2266, + 0x2061, 0x197b, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, + 0x23a8, 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, + 0x8108, 0x080c, 0x2266, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x197b, + 0x2019, 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, + 0x0240, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, + 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, + 0x0066, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, + 0x0006, 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, + 0x9686, 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, + 0x006e, 0x00be, 0x0005, 0x00d6, 0x080c, 0xc92f, 0x00de, 0x0005, + 0x00d6, 0x080c, 0xc93c, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, + 0x9084, 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, + 0x9006, 0x080c, 0xd87c, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, + 0x6920, 0x918c, 0x00ff, 0x6824, 0x080c, 0x2670, 0x1148, 0x2001, + 0x0001, 0x080c, 0xd87c, 0x2110, 0x900e, 0x080c, 0x3030, 0x0018, + 0x9085, 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, + 0x080c, 0x9e7c, 0x05a8, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, + 0x2204, 0x8211, 0x220c, 0x080c, 0x2670, 0x1578, 0x080c, 0x61f6, + 0x1560, 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, + 0x080c, 0xd760, 0x11d8, 0x080c, 0x310a, 0x11c0, 0x080c, 0xc897, + 0x0510, 0x2001, 0x0007, 0x080c, 0x61a7, 0x2001, 0x0007, 0x080c, + 0x61d3, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x8440, 0x080c, 0x898b, 0x0010, 0x080c, 0x9e2f, + 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, 0x080c, 0x9e2f, 0x00ce, + 0x002e, 0x001e, 0x0ca8, 0x080c, 0x9e2f, 0x9006, 0x0c98, 0x2069, + 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, + 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, + 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, + 0x0018, 0x0118, 0x9186, 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, + 0x00ff, 0x910d, 0x615a, 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, + 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, 0x0db4, 0x91b6, 0x0013, + 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, 0xca84, 0x0092, 0x91b6, + 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, 0x0db4, 0x2001, 0x0007, + 0x080c, 0x61d3, 0x080c, 0x887f, 0x080c, 0x9e5f, 0x080c, 0x898b, + 0x0005, 0xc9b9, 0xc9bb, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9bb, 0xc9ca, + 0xca7d, 0xca1c, 0xca7d, 0xca2e, 0xca7d, 0xc9ca, 0xca7d, 0xca75, + 0xca7d, 0xca75, 0xca7d, 0xca7d, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, + 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9bb, + 0xc9b9, 0xca7d, 0xc9b9, 0xc9b9, 0xca7d, 0xc9b9, 0xca7a, 0xca7d, + 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xca7d, 0xca7d, 0xc9b9, 0xca7d, + 0xca7d, 0xc9b9, 0xc9c5, 0xc9b9, 0xc9b9, 0xc9b9, 0xc9b9, 0xca79, + 0xca7d, 0xc9b9, 0xc9b9, 0xca7d, 0xca7d, 0xc9b9, 0xc9b9, 0xc9b9, + 0xc9b9, 0x080c, 0x0db4, 0x080c, 0x887f, 0x080c, 0xc253, 0x6003, + 0x0002, 0x080c, 0x898b, 0x0804, 0xca83, 0x9006, 0x080c, 0x6193, + 0x0804, 0xca7d, 0x080c, 0x6572, 0x1904, 0xca7d, 0x9006, 0x080c, + 0x6193, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, 0x00f6, + 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x0428, 0x6010, + 0x2058, 0xb8b0, 0x9005, 0x1178, 0x080c, 0xc23b, 0x1904, 0xca7d, + 0x0036, 0x0046, 0xbba0, 0x2021, 0x0007, 0x080c, 0x4a91, 0x004e, + 0x003e, 0x0804, 0xca7d, 0x080c, 0x313b, 0x1904, 0xca7d, 0x2001, + 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, + 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x2001, 0x0002, 0x080c, 0x61a7, + 0x080c, 0x887f, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x8440, 0x080c, 0x898b, 0x6110, 0x2158, 0x2009, 0x0001, + 0x080c, 0x804d, 0x0804, 0xca83, 0x6610, 0x2658, 0xbe04, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xca7d, 0x9686, 0x0004, + 0x0904, 0xca7d, 0x2001, 0x0004, 0x0804, 0xca7b, 0x2001, 0x1800, + 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, + 0xbba0, 0x2021, 0x0006, 0x080c, 0x4a91, 0x004e, 0x003e, 0x2001, + 0x0006, 0x080c, 0xcaa1, 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, + 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, 0x0006, + 0x080c, 0x61d3, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, 0x2001, + 0x0006, 0x080c, 0x61a7, 0x080c, 0x6572, 0x11f8, 0x2001, 0x1836, + 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, + 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, + 0x0804, 0xca04, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, + 0x0020, 0x0018, 0x0010, 0x080c, 0x61d3, 0x080c, 0x887f, 0x080c, + 0x9e2f, 0x080c, 0x898b, 0x0005, 0x2600, 0x0002, 0xca98, 0xca98, + 0xca98, 0xca98, 0xca98, 0xca9a, 0xca98, 0xca98, 0xca98, 0xca98, + 0xca9a, 0xca98, 0xca98, 0xca98, 0xca9a, 0xca9a, 0xca9a, 0xca9a, + 0x080c, 0x0db4, 0x080c, 0x887f, 0x080c, 0x9e2f, 0x080c, 0x898b, + 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, + 0x0138, 0x080c, 0x61a7, 0x9006, 0x080c, 0x6193, 0x080c, 0x3010, + 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, + 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0db4, 0x91b6, 0x0015, + 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0db4, 0x006b, + 0x0005, 0xa8ae, 0xa8ae, 0xa8ae, 0xa8ae, 0xcb36, 0xa8ae, 0xcb20, + 0xcae1, 0xa8ae, 0xa8ae, 0xa8ae, 0xa8ae, 0xa8ae, 0xa8ae, 0xa8ae, + 0xa8ae, 0xcb36, 0xa8ae, 0xcb20, 0xcb27, 0xa8ae, 0xa8ae, 0xa8ae, + 0xa8ae, 0x00f6, 0x080c, 0x6572, 0x11d8, 0x080c, 0xc23b, 0x11c0, + 0x6010, 0x905d, 0x01a8, 0xb8b0, 0x9005, 0x0190, 0x9006, 0x080c, + 0x6193, 0x2001, 0x0002, 0x080c, 0x61a7, 0x6023, 0x0001, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x8440, 0x080c, 0x898b, 0x00f0, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2670, 0x11b0, + 0x080c, 0x6256, 0x0118, 0x080c, 0x9e2f, 0x0080, 0xb810, 0x0006, + 0xb814, 0x0006, 0xb8b0, 0x0006, 0x080c, 0x5cff, 0x000e, 0xb8b2, + 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0x9e2f, 0x00fe, 0x0005, + 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9e2f, 0x0005, 0x080c, + 0xac94, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x8440, + 0x080c, 0x898b, 0x0010, 0x080c, 0x9e2f, 0x0005, 0x0804, 0x9e2f, + 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0db4, 0x080c, 0x887f, 0x080c, + 0x9e5f, 0x080c, 0x898b, 0x0005, 0x9182, 0x0040, 0x0002, 0xcb5b, + 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5d, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, + 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, 0xcb5b, + 0xcb5b, 0xcb5b, 0xcb5b, 0x080c, 0x0db4, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, 0x6210, 0x2258, 0xb8ac, 0x9005, 0x11a8, 0x6106, 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, - 0xcbb3, 0x080c, 0xd857, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, - 0x0001, 0x2011, 0x0200, 0x080c, 0x8218, 0x0020, 0x9026, 0x080c, - 0xd78c, 0x0c38, 0x080c, 0x0feb, 0x090c, 0x0db4, 0x6003, 0x0007, + 0xcbc3, 0x080c, 0xd870, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, + 0x0001, 0x2011, 0x0200, 0x080c, 0x8236, 0x0020, 0x9026, 0x080c, + 0xd7a5, 0x0c38, 0x080c, 0x0feb, 0x090c, 0x0db4, 0x6003, 0x0007, 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, - 0x6891, 0x001e, 0x080c, 0xd857, 0x1904, 0xcc13, 0x9486, 0x2000, - 0x1130, 0x2019, 0x0017, 0x080c, 0xd4c7, 0x0804, 0xcc13, 0x9486, - 0x0200, 0x1120, 0x080c, 0xd463, 0x0804, 0xcc13, 0x9486, 0x0400, - 0x0120, 0x9486, 0x1000, 0x1904, 0xcc13, 0x2019, 0x0002, 0x080c, - 0xd47e, 0x0804, 0xcc13, 0x2069, 0x1a40, 0x6a00, 0xd284, 0x0904, - 0xcc7d, 0x9284, 0x0300, 0x1904, 0xcc76, 0x6804, 0x9005, 0x0904, - 0xcc5e, 0x2d78, 0x6003, 0x0007, 0x080c, 0x1004, 0x0904, 0xcc1f, + 0x68a0, 0x001e, 0x080c, 0xd870, 0x1904, 0xcc23, 0x9486, 0x2000, + 0x1130, 0x2019, 0x0017, 0x080c, 0xd4e0, 0x0804, 0xcc23, 0x9486, + 0x0200, 0x1120, 0x080c, 0xd47c, 0x0804, 0xcc23, 0x9486, 0x0400, + 0x0120, 0x9486, 0x1000, 0x1904, 0xcc23, 0x2019, 0x0002, 0x080c, + 0xd497, 0x0804, 0xcc23, 0x2069, 0x1a48, 0x6a00, 0xd284, 0x0904, + 0xcc8d, 0x9284, 0x0300, 0x1904, 0xcc86, 0x6804, 0x9005, 0x0904, + 0xcc6e, 0x2d78, 0x6003, 0x0007, 0x080c, 0x1004, 0x0904, 0xcc2f, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, - 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, 0xcc81, 0x9006, 0xa802, + 0x2001, 0x180f, 0x2004, 0xd084, 0x1904, 0xcc91, 0x9006, 0xa802, 0xa867, 0x0116, 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, - 0x9084, 0x0003, 0x9080, 0xcc1b, 0x2005, 0xa87e, 0x20a9, 0x000a, + 0x9084, 0x0003, 0x9080, 0xcc2b, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, - 0xa9ae, 0x080c, 0x6891, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, + 0xa9ae, 0x080c, 0x68a0, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, - 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, 0x0feb, 0x1904, 0xcbc8, - 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x83da, - 0x080c, 0x896d, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, + 0x1810, 0x2004, 0xd084, 0x0120, 0x080c, 0x0feb, 0x1904, 0xcbd8, + 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x83f8, + 0x080c, 0x898b, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, - 0x0043, 0x080c, 0x83da, 0x080c, 0x896d, 0x0828, 0x6868, 0x602e, + 0x0043, 0x080c, 0x83f8, 0x080c, 0x898b, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x83da, 0x080c, 0x896d, 0x0804, 0xcc13, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48e9, 0x6017, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x0804, 0xcc23, 0x2001, 0x180e, + 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48f4, 0x6017, 0xf300, 0x0010, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, - 0x080c, 0x83da, 0x080c, 0x896d, 0x0804, 0xcc13, 0x6017, 0xf500, - 0x0c98, 0x6017, 0xf600, 0x0804, 0xcc33, 0x6017, 0xf200, 0x0804, - 0xcc33, 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, - 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, 0xcc1b, 0x2005, 0xa87e, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x0804, 0xcc23, 0x6017, 0xf500, + 0x0c98, 0x6017, 0xf600, 0x0804, 0xcc43, 0x6017, 0xf200, 0x0804, + 0xcc43, 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, + 0xa87a, 0x7044, 0x9084, 0x0003, 0x9080, 0xcc2b, 0x2005, 0xa87e, 0x2928, 0x6010, 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0db4, 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, 0xccfd, 0x2041, 0x0001, + 0xa85c, 0x9080, 0x0029, 0x20a0, 0x2011, 0xcd0d, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, 0x2950, 0x080c, 0x1004, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, - 0x0118, 0x080c, 0x101d, 0x0cc8, 0x080c, 0x101d, 0x0804, 0xcc1f, + 0x0118, 0x080c, 0x101d, 0x0cc8, 0x080c, 0x101d, 0x0804, 0xcc2f, 0x2548, 0x8847, 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, - 0x0000, 0x080c, 0xd4f6, 0x0804, 0xcc13, 0x8010, 0x0004, 0x801a, + 0x0000, 0x080c, 0xd50f, 0x0804, 0xcc23, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0054, 0x1a0c, 0x0db4, 0x9082, 0x0040, - 0x0a0c, 0x0db4, 0x2008, 0x0804, 0xcdae, 0x9186, 0x0051, 0x0108, - 0x00c0, 0x2001, 0x0109, 0x2004, 0xd084, 0x0904, 0xcd5f, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x82c6, 0x002e, + 0x0a0c, 0x0db4, 0x2008, 0x0804, 0xcdbf, 0x9186, 0x0051, 0x0108, + 0x00c0, 0x2001, 0x0109, 0x2004, 0xd084, 0x0904, 0xcd6f, 0x0126, + 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x82e4, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0x9086, 0x0002, 0x1580, 0x0804, - 0xcdf6, 0x9186, 0x0027, 0x0530, 0x9186, 0x0048, 0x0128, 0x9186, + 0xce08, 0x9186, 0x0027, 0x0530, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0500, 0x190c, 0x0db4, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0, 0x00c6, 0x0126, 0x2091, 0x2800, 0x00c6, 0x2061, 0x0100, - 0x0006, 0x0016, 0x0026, 0x080c, 0x82c6, 0x002e, 0x001e, 0x000e, + 0x0006, 0x0016, 0x0026, 0x080c, 0x82e4, 0x002e, 0x001e, 0x000e, 0x00ce, 0x012e, 0x00ce, 0x6000, 0x9086, 0x0004, 0x190c, 0x0db4, - 0x0804, 0xced7, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, - 0x9ed7, 0x0005, 0xcd75, 0xcd77, 0xcd77, 0xcd9e, 0xcd75, 0xcd75, - 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0xcd75, - 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0xcd75, 0x080c, 0x0db4, 0x080c, - 0x8861, 0x080c, 0x896d, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, - 0x080c, 0xbb2c, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xd4f6, - 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1957, 0x2004, - 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, - 0x8861, 0x080c, 0x896d, 0x080c, 0xbb2c, 0x0120, 0x6014, 0x2048, - 0x080c, 0x101d, 0x080c, 0x9e72, 0x009e, 0x0005, 0x0002, 0xcdc2, - 0xcdd9, 0xcdc4, 0xcdf0, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, - 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, - 0xcdc2, 0xcdc2, 0x080c, 0x0db4, 0x0096, 0x080c, 0x8861, 0x6014, - 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, - 0x080c, 0x9ebc, 0x0010, 0x6003, 0x0004, 0x080c, 0x896d, 0x009e, - 0x0005, 0x080c, 0x8861, 0x080c, 0xbb2c, 0x0138, 0x6114, 0x0096, - 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, 0x080c, 0x81ed, 0x080c, - 0x9e42, 0x080c, 0x896d, 0x0005, 0x080c, 0xd750, 0x0db0, 0x0cc8, - 0x080c, 0x8861, 0x2009, 0x0041, 0x0804, 0xcf5f, 0x9182, 0x0040, - 0x0002, 0xce0c, 0xce0e, 0xce0c, 0xce0c, 0xce0c, 0xce0c, 0xce0c, - 0xce0c, 0xce0c, 0xce0c, 0xce0c, 0xce0c, 0xce0c, 0xce0c, 0xce0c, - 0xce0c, 0xce0c, 0xce0f, 0xce0c, 0x080c, 0x0db4, 0x0005, 0x00d6, - 0x080c, 0x81ed, 0x00de, 0x080c, 0xd7a8, 0x080c, 0x9e42, 0x0005, - 0x9182, 0x0040, 0x0002, 0xce2e, 0xce2e, 0xce2e, 0xce2e, 0xce2e, - 0xce2e, 0xce2e, 0xce2e, 0xce2e, 0xce30, 0xce9f, 0xce2e, 0xce2e, - 0xce2e, 0xce2e, 0xce9f, 0xce2e, 0xce2e, 0xce2e, 0x080c, 0x0db4, - 0x2001, 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, - 0x200c, 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xce9f, 0x2009, - 0x180c, 0x2104, 0xd0d4, 0x0904, 0xce9f, 0xc0d4, 0x200a, 0x2009, - 0x0105, 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, - 0x1873, 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x891d, - 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, - 0x918e, 0x0002, 0x0508, 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, - 0x080c, 0x8a4a, 0x2009, 0x0041, 0x009e, 0x0804, 0xcf5f, 0x080c, - 0x8a4a, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x81ed, 0x009e, - 0x0005, 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, - 0x011f, 0x2004, 0x603a, 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, - 0x2102, 0xd1cc, 0x0110, 0x080c, 0x2a79, 0x080c, 0x8a4a, 0x6014, - 0x2048, 0xa97c, 0xd1ec, 0x1130, 0x080c, 0x81ed, 0x080c, 0x9e42, - 0x009e, 0x0005, 0x080c, 0xd750, 0x0db8, 0x009e, 0x0005, 0x2001, - 0x180c, 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x891d, 0x080c, - 0x8a4a, 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, - 0x0140, 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, - 0x632e, 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xd4f6, - 0x6018, 0x9005, 0x1128, 0x2001, 0x1957, 0x2004, 0x8003, 0x601a, - 0x6017, 0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, - 0x0040, 0x0002, 0xceee, 0xceee, 0xceee, 0xceee, 0xceee, 0xceee, - 0xceee, 0xceee, 0xcef0, 0xceee, 0xceee, 0xceee, 0xceee, 0xceee, - 0xceee, 0xceee, 0xceee, 0xceee, 0xceee, 0xcf3b, 0x080c, 0x0db4, - 0x6014, 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, - 0x0128, 0x2009, 0x0041, 0x009e, 0x0804, 0xcf5f, 0x6003, 0x0007, - 0x601b, 0x0000, 0x080c, 0x81ed, 0x009e, 0x0005, 0x6124, 0xd1f4, - 0x1d58, 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, - 0x6030, 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, - 0x08d8, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, - 0x2009, 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, - 0x6003, 0x0006, 0x00e9, 0x080c, 0x81ef, 0x009e, 0x0005, 0x6003, - 0x0002, 0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x1511, - 0x1904, 0xcef0, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, - 0x009e, 0x9105, 0x1120, 0x080c, 0x1511, 0x1904, 0xcef0, 0x0005, - 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, - 0x0009, 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, - 0x0040, 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, - 0x190c, 0x0db4, 0x6024, 0xd0dc, 0x090c, 0x0db4, 0x0005, 0xcf82, - 0xcf8e, 0xcf9a, 0xcfa6, 0xcf82, 0xcf82, 0xcf82, 0xcf82, 0xcf89, - 0xcf84, 0xcf84, 0xcf82, 0xcf82, 0xcf82, 0xcf82, 0xcf84, 0xcf82, - 0xcf84, 0xcf82, 0x080c, 0x0db4, 0x6024, 0xd0dc, 0x090c, 0x0db4, - 0x0005, 0x6014, 0x9005, 0x190c, 0x0db4, 0x0005, 0x6003, 0x0001, - 0x6106, 0x080c, 0x83da, 0x0126, 0x2091, 0x8000, 0x080c, 0x896d, - 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x83da, 0x0126, - 0x2091, 0x8000, 0x080c, 0x896d, 0x012e, 0x0005, 0x6003, 0x0003, - 0x6106, 0x2c10, 0x080c, 0x1a5e, 0x0126, 0x2091, 0x8000, 0x080c, - 0x843f, 0x080c, 0x8a4a, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, - 0x0005, 0xcfd1, 0xcfd3, 0xcfe5, 0xcfff, 0xcfd1, 0xcfd1, 0xcfd1, - 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd1, - 0xcfd1, 0x080c, 0x0db4, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x01f8, - 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, - 0x080c, 0x83da, 0x080c, 0x896d, 0x0470, 0x6014, 0x2048, 0xa87c, - 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, - 0x0001, 0x6106, 0x080c, 0x83da, 0x080c, 0x896d, 0x00e0, 0x901e, - 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xd4f6, 0x00a0, 0x6014, - 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, - 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1a5e, 0x080c, - 0x843f, 0x080c, 0x8a4a, 0x0005, 0x080c, 0x8861, 0x6114, 0x81ff, - 0x0158, 0x0096, 0x2148, 0x080c, 0xd7f4, 0x0036, 0x2019, 0x0029, - 0x080c, 0xd4f6, 0x003e, 0x009e, 0x080c, 0x9e72, 0x080c, 0x896d, - 0x0005, 0x080c, 0x891d, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, - 0x080c, 0xd7f4, 0x0036, 0x2019, 0x0029, 0x080c, 0xd4f6, 0x003e, - 0x009e, 0x080c, 0x9e72, 0x080c, 0x8a4a, 0x0005, 0x9182, 0x0085, - 0x0002, 0xd050, 0xd04e, 0xd04e, 0xd05c, 0xd04e, 0xd04e, 0xd04e, - 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0x080c, 0x0db4, - 0x6003, 0x000b, 0x6106, 0x080c, 0x83da, 0x0126, 0x2091, 0x8000, - 0x080c, 0x896d, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, 0xd747, - 0x0118, 0x080c, 0x9e42, 0x0450, 0x2071, 0x0260, 0x7224, 0x6216, - 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, 0x2058, - 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xa162, 0x7220, - 0x080c, 0xd39c, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, - 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, - 0x080c, 0x83da, 0x080c, 0x896d, 0x080c, 0x8a4a, 0x00ee, 0x002e, - 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, - 0x0db4, 0x908a, 0x0092, 0x1a0c, 0x0db4, 0x9082, 0x0085, 0x00a2, - 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0x9ed7, - 0x0050, 0x2001, 0x0007, 0x080c, 0x61c4, 0x080c, 0x8861, 0x080c, - 0x9e72, 0x080c, 0x896d, 0x0005, 0xd0c1, 0xd0c3, 0xd0c3, 0xd0c1, - 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, - 0xd0c1, 0x080c, 0x0db4, 0x080c, 0x8861, 0x080c, 0x9e72, 0x080c, - 0x896d, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0db4, 0x9182, 0x0092, - 0x1a0c, 0x0db4, 0x9182, 0x0085, 0x0002, 0xd0e2, 0xd0e2, 0xd0e2, - 0xd0e4, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, - 0xd0e2, 0xd0e2, 0x080c, 0x0db4, 0x0005, 0x9186, 0x0013, 0x0148, - 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0x9ed7, - 0x0030, 0x080c, 0x8861, 0x080c, 0x9e72, 0x080c, 0x896d, 0x0005, - 0x0036, 0x080c, 0xd7a8, 0x6043, 0x0000, 0x2019, 0x000b, 0x0031, - 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, - 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0x97bb, - 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0x9866, 0x007e, - 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, - 0x01e0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xd7a8, 0x080c, - 0xc244, 0x080c, 0x190f, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, - 0xbb2c, 0x0110, 0x080c, 0xd4f6, 0x009e, 0x6017, 0x0000, 0x080c, - 0xd7a8, 0x6023, 0x0007, 0x080c, 0xc244, 0x003e, 0x012e, 0x0005, - 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, - 0x783c, 0x080c, 0x2665, 0x15c8, 0x0016, 0x00c6, 0x080c, 0x6247, - 0x1590, 0x001e, 0x00c6, 0x2160, 0x080c, 0xc241, 0x00ce, 0x002e, - 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x992c, 0x080c, 0x8564, - 0x0076, 0x903e, 0x080c, 0x8452, 0x007e, 0x001e, 0x0076, 0x903e, - 0x080c, 0xd2bc, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, - 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, - 0x3099, 0x002e, 0xbcb0, 0x001e, 0x080c, 0x5cf4, 0xbe12, 0xbd16, - 0xbcb2, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, - 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, - 0x1823, 0x2104, 0x9086, 0x0074, 0x1904, 0xd1e4, 0x2069, 0x0260, - 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, - 0xd1e1, 0x2001, 0x194c, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, - 0xb8b0, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, - 0x0001, 0x0648, 0x080c, 0xd85c, 0x0118, 0x6978, 0xd1fc, 0x11b8, - 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, - 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, - 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, - 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, - 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, - 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, - 0x0008, 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, - 0x00b6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, - 0x00ff, 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, - 0xff00, 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, - 0x080c, 0x6256, 0x0804, 0xd24b, 0x2011, 0x0276, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xae20, 0x009e, 0x15a0, - 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, - 0x080c, 0xae20, 0x009e, 0x1540, 0x0046, 0x0016, 0xbaa0, 0x2220, - 0x9006, 0x2009, 0x1854, 0x210c, 0x0038, 0x2009, 0x0029, 0x080c, - 0xd54b, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, 0x8564, - 0x0076, 0x2039, 0x0000, 0x080c, 0x8452, 0x2c08, 0x080c, 0xd2bc, - 0x007e, 0x2001, 0x0007, 0x080c, 0x61c4, 0x2001, 0x0007, 0x080c, - 0x6198, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, - 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, - 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, - 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, - 0x7834, 0x080c, 0x2665, 0x11d0, 0x080c, 0x6247, 0x11b8, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xae20, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xae20, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2665, 0x11d0, 0x080c, 0x6247, 0x11b8, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xae20, - 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xae20, 0x009e, 0x015e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2029, 0x19c0, 0x252c, 0x2021, 0x19c6, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7650, 0x7070, 0x81ff, 0x0150, 0x0006, 0x9186, - 0x1a7f, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xd355, 0x0018, - 0x9606, 0x0904, 0xd355, 0x2100, 0x9c06, 0x0904, 0xd34c, 0x080c, - 0xd58c, 0x1904, 0xd34c, 0x080c, 0xd879, 0x0904, 0xd34c, 0x080c, - 0xd57c, 0x0904, 0xd34c, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, - 0x3130, 0x0904, 0xd370, 0x6004, 0x9086, 0x0000, 0x1904, 0xd370, - 0x9786, 0x0004, 0x0904, 0xd370, 0x9786, 0x0007, 0x0904, 0xd34c, - 0x2500, 0x9c06, 0x0904, 0xd34c, 0x2400, 0x9c06, 0x05e8, 0x88ff, - 0x0118, 0x6054, 0x9906, 0x15c0, 0x0096, 0x6000, 0x9086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x190f, 0x001e, 0x9786, 0x000a, 0x0148, - 0x080c, 0xbd32, 0x1130, 0x080c, 0xa7d1, 0x009e, 0x080c, 0x9e72, - 0x0418, 0x6014, 0x2048, 0x080c, 0xbb2c, 0x01d8, 0x9786, 0x0003, - 0x1570, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, - 0x2048, 0x080c, 0x0f9d, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, - 0xd7f4, 0x0016, 0x080c, 0xbe20, 0x080c, 0x6884, 0x001e, 0x080c, - 0xbd15, 0x009e, 0x080c, 0x9e72, 0x9ce0, 0x0018, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1210, 0x0804, 0xd2d0, 0x012e, 0x002e, 0x004e, - 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, - 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xd7f4, 0x080c, - 0xd4f6, 0x08f8, 0x009e, 0x0c00, 0x9786, 0x000a, 0x0920, 0x0808, - 0x81ff, 0x09d0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0130, - 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1970, 0x6000, 0x9086, - 0x0002, 0x1950, 0x080c, 0xbd21, 0x0130, 0x080c, 0xbd32, 0x1920, - 0x080c, 0xa7d1, 0x0038, 0x080c, 0x3005, 0x080c, 0xbd32, 0x1110, - 0x080c, 0xa7d1, 0x080c, 0x9e72, 0x0804, 0xd34c, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, - 0x2170, 0x9006, 0x080c, 0xd51d, 0x001e, 0x0120, 0x6020, 0x9084, - 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xd3bb, 0xd3bb, 0xd3bb, - 0xd3bb, 0xd3bb, 0xd3bb, 0xd3bd, 0xd3bb, 0xd3bb, 0xd3bb, 0xd3bb, - 0x9e72, 0x9e72, 0xd3bb, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, - 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, - 0x080c, 0xd54b, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, 0xd106, - 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xbb2c, 0x0140, - 0x6014, 0x904d, 0x080c, 0xb75d, 0x687b, 0x0005, 0x080c, 0x6891, - 0x009e, 0x080c, 0x9e72, 0x9085, 0x0001, 0x0005, 0x2001, 0x0001, - 0x080c, 0x6184, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, - 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xae0c, 0x003e, 0x002e, - 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, - 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, - 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd456, 0x2071, 0x1800, - 0x7650, 0x7070, 0x8001, 0x9602, 0x1a04, 0xd456, 0x88ff, 0x0120, - 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xd57c, 0x0570, 0x2400, - 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, 0x0007, - 0x0520, 0x88ff, 0x1140, 0x6010, 0x9b06, 0x11f8, 0x85ff, 0x0118, - 0x6054, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, - 0xd7a8, 0x080c, 0xc244, 0x080c, 0x190f, 0x6023, 0x0007, 0x6014, - 0x2048, 0x080c, 0xbb2c, 0x0120, 0x0046, 0x080c, 0xd4f6, 0x004e, - 0x009e, 0x080c, 0x9e72, 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, - 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd40b, 0x9006, 0x012e, - 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x98c5, 0x0001, 0x0ca0, 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, - 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, - 0x904e, 0x080c, 0x97bb, 0x009e, 0x008e, 0x903e, 0x080c, 0x9866, - 0x080c, 0xd3fc, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, - 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, - 0x900e, 0x0016, 0x0036, 0x080c, 0x6247, 0x1190, 0x0056, 0x0086, - 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x97bb, - 0x009e, 0x008e, 0x903e, 0x080c, 0x9866, 0x080c, 0xd3fc, 0x005e, - 0x003e, 0x001e, 0x8108, 0x1f04, 0xd489, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076, 0x0056, 0x6210, - 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0x97bb, 0x009e, 0x008e, 0x903e, 0x080c, 0x9866, - 0x2c20, 0x080c, 0xd3fc, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, - 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x0800, - 0x900e, 0x0016, 0x0036, 0x080c, 0x6247, 0x11a0, 0x0086, 0x9046, - 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xd78c, 0x004e, 0x0096, - 0x904e, 0x080c, 0x97bb, 0x009e, 0x008e, 0x903e, 0x080c, 0x9866, - 0x080c, 0xd3fc, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd4d1, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x0016, 0x00f6, - 0x080c, 0xbb2a, 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, - 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, - 0x6891, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x6891, 0x00fe, 0x001e, - 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6891, - 0x2f48, 0x0cb8, 0x080c, 0x6891, 0x0c88, 0x00e6, 0x0046, 0x0036, - 0x2061, 0x1cd0, 0x9005, 0x1138, 0x2071, 0x1800, 0x7450, 0x7070, - 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, - 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, 0x6010, 0x91a0, 0x0004, - 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x1819, 0x2004, - 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, - 0x004e, 0x00ee, 0x0005, 0x0096, 0x0006, 0x080c, 0x0feb, 0x000e, - 0x090c, 0x0db4, 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, - 0x080c, 0xbb1a, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, - 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, - 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x195e, 0x2004, 0xa882, - 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6891, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, - 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, - 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, - 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, - 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, - 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0005, 0x2001, 0x1957, 0x2004, 0x601a, 0x080c, - 0x83da, 0x080c, 0x896d, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, - 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xbe64, 0x0030, - 0x080c, 0xd7a8, 0x080c, 0x81ed, 0x080c, 0x9e42, 0x0005, 0x9280, - 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd5db, 0xd5db, 0xd5db, - 0xd5dd, 0xd5db, 0xd5dd, 0xd5dd, 0xd5db, 0xd5dd, 0xd5db, 0xd5db, - 0xd5db, 0xd5db, 0xd5db, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, + 0x0804, 0xceeb, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, + 0x9ec4, 0x0005, 0xcd86, 0xcd88, 0xcd88, 0xcdaf, 0xcd86, 0xcd86, + 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, + 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0xcd86, 0x080c, 0x0db4, + 0x080c, 0x887f, 0x080c, 0x898b, 0x0036, 0x0096, 0x6014, 0x904d, + 0x01d8, 0x080c, 0xbb3b, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, + 0xd50f, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x195f, + 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, + 0x080c, 0x887f, 0x080c, 0x898b, 0x080c, 0xbb3b, 0x0120, 0x6014, + 0x2048, 0x080c, 0x101d, 0x080c, 0x9e5f, 0x009e, 0x0005, 0x0002, + 0xcdd4, 0xcdeb, 0xcdd6, 0xce02, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, + 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, + 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd4, 0x080c, 0x0db4, 0x0096, 0x080c, + 0x887f, 0x6014, 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, + 0x2009, 0x0043, 0x080c, 0x9ea9, 0x0010, 0x6003, 0x0004, 0x080c, + 0x898b, 0x009e, 0x0005, 0x080c, 0x887f, 0x080c, 0xbb3b, 0x0138, + 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, 0xd1ec, 0x1138, 0x080c, + 0x820b, 0x080c, 0x9e2f, 0x080c, 0x898b, 0x0005, 0x080c, 0xd769, + 0x0db0, 0x0cc8, 0x080c, 0x887f, 0x2009, 0x0041, 0x0804, 0xcf73, + 0x9182, 0x0040, 0x0002, 0xce1f, 0xce21, 0xce1f, 0xce1f, 0xce1f, + 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, + 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce22, 0xce1f, 0xce1f, 0x080c, + 0x0db4, 0x0005, 0x00d6, 0x080c, 0x820b, 0x00de, 0x080c, 0xd7c1, + 0x080c, 0x9e2f, 0x0005, 0x9182, 0x0040, 0x0002, 0xce42, 0xce42, + 0xce42, 0xce42, 0xce42, 0xce42, 0xce42, 0xce42, 0xce42, 0xce44, + 0xceb3, 0xce42, 0xce42, 0xce42, 0xce42, 0xceb3, 0xce42, 0xce42, + 0xce42, 0xce42, 0x080c, 0x0db4, 0x2001, 0x0105, 0x2004, 0x9084, + 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, 0x2001, 0x0131, 0x2004, + 0x9105, 0x1904, 0xceb3, 0x2009, 0x180c, 0x2104, 0xd0d4, 0x0904, + 0xceb3, 0xc0d4, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0xe7fd, + 0x9085, 0x0010, 0x200a, 0x2001, 0x187b, 0x2004, 0xd0e4, 0x1528, + 0x603b, 0x0000, 0x080c, 0x893b, 0x6014, 0x0096, 0x2048, 0xa87c, + 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, 0x0002, 0x0508, 0x2001, + 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, 0x8a68, 0x2009, 0x0041, + 0x009e, 0x0804, 0xcf73, 0x080c, 0x8a68, 0x6003, 0x0007, 0x601b, + 0x0000, 0x080c, 0x820b, 0x009e, 0x0005, 0x2001, 0x0100, 0x2004, + 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, 0x2004, 0x603a, 0x0890, + 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, 0xd1cc, 0x0110, 0x080c, + 0x2a84, 0x080c, 0x8a68, 0x6014, 0x2048, 0xa97c, 0xd1ec, 0x1130, + 0x080c, 0x820b, 0x080c, 0x9e2f, 0x009e, 0x0005, 0x080c, 0xd769, + 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, + 0x0036, 0x080c, 0x893b, 0x080c, 0x8a68, 0x6014, 0x0096, 0x2048, + 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0188, 0xa87c, + 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, 0x6330, 0x931a, + 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, 0x0080, + 0x2019, 0x0004, 0x080c, 0xd50f, 0x6018, 0x9005, 0x1128, 0x2001, + 0x195f, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, + 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xcf02, 0xcf02, + 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf04, 0xcf02, + 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf02, + 0xcf02, 0xcf4f, 0x080c, 0x0db4, 0x6014, 0x0096, 0x2048, 0xa834, + 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, + 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x009e, + 0x0804, 0xcf73, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x820b, + 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0xacac, + 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, + 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x00b6, 0x2158, + 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, 0x210c, 0xd19c, + 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, + 0x820d, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, 0x6024, + 0xd0f4, 0x0128, 0x080c, 0x1511, 0x1904, 0xcf04, 0x0005, 0x6014, + 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, 0x080c, + 0x1511, 0x1904, 0xcf04, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, + 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, + 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, + 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0db4, 0x6024, 0xd0dc, + 0x090c, 0x0db4, 0x0005, 0xcf97, 0xcfa3, 0xcfaf, 0xcfbb, 0xcf97, + 0xcf97, 0xcf97, 0xcf97, 0xcf9e, 0xcf99, 0xcf99, 0xcf97, 0xcf97, + 0xcf97, 0xcf97, 0xcf99, 0xcf97, 0xcf99, 0xcf97, 0xcf9e, 0x080c, + 0x0db4, 0x6024, 0xd0dc, 0x090c, 0x0db4, 0x0005, 0x6014, 0x9005, + 0x190c, 0x0db4, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x83f8, + 0x0126, 0x2091, 0x8000, 0x080c, 0x898b, 0x012e, 0x0005, 0x6003, + 0x0001, 0x6106, 0x080c, 0x83f8, 0x0126, 0x2091, 0x8000, 0x080c, + 0x898b, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, + 0x1a69, 0x0126, 0x2091, 0x8000, 0x080c, 0x845d, 0x080c, 0x8a68, + 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, + 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xcfea, 0xcfec, + 0xcffe, 0xd018, 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, + 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, 0xcfea, + 0xcfea, 0xcfea, 0x080c, 0x0db4, 0x6014, 0x2048, 0xa87c, 0xd0fc, + 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, 0x01d0, 0x6003, 0x0001, + 0x6106, 0x080c, 0x83f8, 0x080c, 0x898b, 0x0470, 0x6014, 0x2048, + 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, + 0x6003, 0x0001, 0x6106, 0x080c, 0x83f8, 0x080c, 0x898b, 0x00e0, + 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, 0xd50f, 0x00a0, + 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, + 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1a69, + 0x080c, 0x845d, 0x080c, 0x8a68, 0x0005, 0x080c, 0x887f, 0x6114, + 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xd80d, 0x0036, 0x2019, + 0x0029, 0x080c, 0xd50f, 0x003e, 0x009e, 0x080c, 0x9e5f, 0x080c, + 0x898b, 0x0005, 0x080c, 0x893b, 0x6114, 0x81ff, 0x0158, 0x0096, + 0x2148, 0x080c, 0xd80d, 0x0036, 0x2019, 0x0029, 0x080c, 0xd50f, + 0x003e, 0x009e, 0x080c, 0x9e5f, 0x080c, 0x8a68, 0x0005, 0x9182, + 0x0085, 0x0002, 0xd069, 0xd067, 0xd067, 0xd075, 0xd067, 0xd067, + 0xd067, 0xd067, 0xd067, 0xd067, 0xd067, 0xd067, 0xd067, 0x080c, + 0x0db4, 0x6003, 0x000b, 0x6106, 0x080c, 0x83f8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x898b, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, + 0xd760, 0x0118, 0x080c, 0x9e2f, 0x0450, 0x2071, 0x0260, 0x7224, + 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, + 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0xa14f, + 0x7220, 0x080c, 0xd3b5, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, + 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, + 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, 0x080c, 0x8a68, 0x00ee, + 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, + 0x0a0c, 0x0db4, 0x908a, 0x0092, 0x1a0c, 0x0db4, 0x9082, 0x0085, + 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, + 0x9ec4, 0x0050, 0x2001, 0x0007, 0x080c, 0x61d3, 0x080c, 0x887f, + 0x080c, 0x9e5f, 0x080c, 0x898b, 0x0005, 0xd0da, 0xd0dc, 0xd0dc, + 0xd0da, 0xd0da, 0xd0da, 0xd0da, 0xd0da, 0xd0da, 0xd0da, 0xd0da, + 0xd0da, 0xd0da, 0x080c, 0x0db4, 0x080c, 0x887f, 0x080c, 0x9e5f, + 0x080c, 0x898b, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0db4, 0x9182, + 0x0092, 0x1a0c, 0x0db4, 0x9182, 0x0085, 0x0002, 0xd0fb, 0xd0fb, + 0xd0fb, 0xd0fd, 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fb, + 0xd0fb, 0xd0fb, 0xd0fb, 0x080c, 0x0db4, 0x0005, 0x9186, 0x0013, + 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, + 0x9ec4, 0x0030, 0x080c, 0x887f, 0x080c, 0x9e5f, 0x080c, 0x898b, + 0x0005, 0x0036, 0x080c, 0xd7c1, 0x6043, 0x0000, 0x2019, 0x000b, + 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, + 0x0036, 0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, + 0x97a4, 0x009e, 0x008e, 0x1550, 0x0076, 0x2c38, 0x080c, 0x984f, + 0x007e, 0x1520, 0x6000, 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, + 0x0007, 0x01e0, 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xd7c1, + 0x080c, 0xc253, 0x080c, 0x191f, 0x6023, 0x0007, 0x6014, 0x2048, + 0x080c, 0xbb3b, 0x0110, 0x080c, 0xd50f, 0x009e, 0x6017, 0x0000, + 0x080c, 0xd7c1, 0x6023, 0x0007, 0x080c, 0xc253, 0x003e, 0x012e, + 0x0005, 0x00f6, 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, + 0x7938, 0x783c, 0x080c, 0x2670, 0x15c8, 0x0016, 0x00c6, 0x080c, + 0x6256, 0x1590, 0x001e, 0x00c6, 0x2160, 0x080c, 0xc250, 0x00ce, + 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x9915, 0x080c, + 0x8582, 0x0076, 0x903e, 0x080c, 0x8470, 0x007e, 0x001e, 0x0076, + 0x903e, 0x080c, 0xd2d5, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, + 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, + 0x080c, 0x30a4, 0x002e, 0xbcb0, 0x001e, 0x080c, 0x5cff, 0xbe12, + 0xbd16, 0xbcb2, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, + 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, + 0x2009, 0x1823, 0x2104, 0x9086, 0x0074, 0x1904, 0xd1fd, 0x2069, + 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, + 0x0904, 0xd1fa, 0x2001, 0x1954, 0x2004, 0x9005, 0x1140, 0x6010, + 0x2058, 0xb8b0, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, + 0x918a, 0x0001, 0x0648, 0x080c, 0xd875, 0x0118, 0x6978, 0xd1fc, + 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, + 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, + 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, + 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, + 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, + 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, + 0x0001, 0x0008, 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, + 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, + 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, + 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, + 0x0120, 0x080c, 0x6265, 0x0804, 0xd264, 0x2011, 0x0276, 0x20a9, + 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xae1c, 0x009e, + 0x15a0, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, + 0x0006, 0x080c, 0xae1c, 0x009e, 0x1540, 0x0046, 0x0016, 0xbaa0, + 0x2220, 0x9006, 0x2009, 0x185c, 0x210c, 0x0038, 0x2009, 0x0029, + 0x080c, 0xd564, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, + 0x8582, 0x0076, 0x2039, 0x0000, 0x080c, 0x8470, 0x2c08, 0x080c, + 0xd2d5, 0x007e, 0x2001, 0x0007, 0x080c, 0x61d3, 0x2001, 0x0007, + 0x080c, 0x61a7, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, + 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, + 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, + 0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, + 0x7930, 0x7834, 0x080c, 0x2670, 0x11d0, 0x080c, 0x6256, 0x11b8, + 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, + 0x080c, 0xae1c, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, + 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xae1c, 0x009e, 0x015e, + 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, + 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, + 0x220c, 0x080c, 0x2670, 0x11d0, 0x080c, 0x6256, 0x11b8, 0x2011, + 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, + 0xae1c, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, + 0x2b48, 0x2019, 0x0006, 0x080c, 0xae1c, 0x009e, 0x015e, 0x003e, + 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, + 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, + 0x2740, 0x2029, 0x19c8, 0x252c, 0x2021, 0x19ce, 0x2424, 0x2061, + 0x1cd0, 0x2071, 0x1800, 0x7650, 0x7070, 0x81ff, 0x0150, 0x0006, + 0x9186, 0x1a87, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xd36e, + 0x0018, 0x9606, 0x0904, 0xd36e, 0x2100, 0x9c06, 0x0904, 0xd365, + 0x080c, 0xd5a5, 0x1904, 0xd365, 0x080c, 0xd892, 0x0904, 0xd365, + 0x080c, 0xd595, 0x0904, 0xd365, 0x6720, 0x9786, 0x0001, 0x1148, + 0x080c, 0x313b, 0x0904, 0xd389, 0x6004, 0x9086, 0x0000, 0x1904, + 0xd389, 0x9786, 0x0004, 0x0904, 0xd389, 0x9786, 0x0007, 0x0904, + 0xd365, 0x2500, 0x9c06, 0x0904, 0xd365, 0x2400, 0x9c06, 0x05e8, + 0x88ff, 0x0118, 0x6054, 0x9906, 0x15c0, 0x0096, 0x6000, 0x9086, + 0x0004, 0x1120, 0x0016, 0x080c, 0x191f, 0x001e, 0x9786, 0x000a, + 0x0148, 0x080c, 0xbd41, 0x1130, 0x080c, 0xa7cd, 0x009e, 0x080c, + 0x9e5f, 0x0418, 0x6014, 0x2048, 0x080c, 0xbb3b, 0x01d8, 0x9786, + 0x0003, 0x1570, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, + 0xa878, 0x2048, 0x080c, 0x0f9d, 0x009e, 0xab7a, 0xa877, 0x0000, + 0x080c, 0xd80d, 0x0016, 0x080c, 0xbe2f, 0x080c, 0x6893, 0x001e, + 0x080c, 0xbd24, 0x009e, 0x080c, 0x9e5f, 0x9ce0, 0x0018, 0x2001, + 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd2e9, 0x012e, 0x002e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, + 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xd80d, + 0x080c, 0xd50f, 0x08f8, 0x009e, 0x0c00, 0x9786, 0x000a, 0x0920, + 0x0808, 0x81ff, 0x09d0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, + 0x0130, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1970, 0x6000, + 0x9086, 0x0002, 0x1950, 0x080c, 0xbd30, 0x0130, 0x080c, 0xbd41, + 0x1920, 0x080c, 0xa7cd, 0x0038, 0x080c, 0x3010, 0x080c, 0xbd41, + 0x1110, 0x080c, 0xa7cd, 0x080c, 0x9e5f, 0x0804, 0xd365, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, + 0x2c08, 0x2170, 0x9006, 0x080c, 0xd536, 0x001e, 0x0120, 0x6020, + 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xd3d4, 0xd3d4, + 0xd3d4, 0xd3d4, 0xd3d4, 0xd3d4, 0xd3d6, 0xd3d4, 0xd3d4, 0xd3d4, + 0xd3d4, 0x9e5f, 0x9e5f, 0xd3d4, 0x9006, 0x0005, 0x0036, 0x0046, + 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, + 0x0020, 0x080c, 0xd564, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, + 0xd11f, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xbb3b, + 0x0140, 0x6014, 0x904d, 0x080c, 0xb75c, 0x687b, 0x0005, 0x080c, + 0x68a0, 0x009e, 0x080c, 0x9e5f, 0x9085, 0x0001, 0x0005, 0x2001, + 0x0001, 0x080c, 0x6193, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xae08, 0x003e, + 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, + 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd46f, 0x2071, + 0x1800, 0x7650, 0x7070, 0x8001, 0x9602, 0x1a04, 0xd46f, 0x88ff, + 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xd595, 0x0570, + 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, + 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, 0x9b06, 0x11f8, 0x85ff, + 0x0118, 0x6054, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, + 0x080c, 0xd7c1, 0x080c, 0xc253, 0x080c, 0x191f, 0x6023, 0x0007, + 0x6014, 0x2048, 0x080c, 0xbb3b, 0x0120, 0x0046, 0x080c, 0xd50f, + 0x004e, 0x009e, 0x080c, 0x9e5f, 0x88ff, 0x1198, 0x9ce0, 0x0018, + 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd424, 0x9006, + 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x00b6, 0x0076, 0x0056, 0x0086, + 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6210, 0x2258, + 0x0096, 0x904e, 0x080c, 0x97a4, 0x009e, 0x008e, 0x903e, 0x080c, + 0x984f, 0x080c, 0xd415, 0x005e, 0x007e, 0x00be, 0x0005, 0x00b6, + 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x0036, 0x080c, 0x6256, 0x1190, 0x0056, + 0x0086, 0x9046, 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, + 0x97a4, 0x009e, 0x008e, 0x903e, 0x080c, 0x984f, 0x080c, 0xd415, + 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd4a2, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076, 0x0056, + 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, + 0x0096, 0x904e, 0x080c, 0x97a4, 0x009e, 0x008e, 0x903e, 0x080c, + 0x984f, 0x2c20, 0x080c, 0xd415, 0x005e, 0x007e, 0x00be, 0x0005, + 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, + 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, 0x6256, 0x11a0, 0x0086, + 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xd7a5, 0x004e, + 0x0096, 0x904e, 0x080c, 0x97a4, 0x009e, 0x008e, 0x903e, 0x080c, + 0x984f, 0x080c, 0xd415, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd4ea, + 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x0016, + 0x00f6, 0x080c, 0xbb39, 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, + 0x080c, 0x68a0, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x68a0, 0x00fe, + 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, + 0x68a0, 0x2f48, 0x0cb8, 0x080c, 0x68a0, 0x0c88, 0x00e6, 0x0046, + 0x0036, 0x2061, 0x1cd0, 0x9005, 0x1138, 0x2071, 0x1800, 0x7450, + 0x7070, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, + 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, 0x6010, 0x91a0, + 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x1819, + 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x0096, 0x0006, 0x080c, 0x0feb, + 0x000e, 0x090c, 0x0db4, 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, + 0x2010, 0x080c, 0xbb29, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, + 0x0015, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, + 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x1966, 0x2004, + 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x68a0, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, + 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, + 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, + 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, + 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, + 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x195f, 0x2004, 0x601a, + 0x080c, 0x83f8, 0x080c, 0x898b, 0x001e, 0x0005, 0xa001, 0xa001, + 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xbe73, + 0x0030, 0x080c, 0xd7c1, 0x080c, 0x820b, 0x080c, 0x9e2f, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd5f4, 0xd5f4, - 0xd5f4, 0xd5f4, 0xd5f4, 0xd5f4, 0xd601, 0xd5f4, 0xd5f4, 0xd5f4, - 0xd5f4, 0xd5f4, 0xd5f4, 0xd5f4, 0x6007, 0x003b, 0x602f, 0x0009, - 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, - 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xd7a8, 0x6043, 0x0000, - 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, - 0x2268, 0x9186, 0x0007, 0x1904, 0xd65a, 0x6814, 0x9005, 0x0138, - 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, - 0x003a, 0x6003, 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, 0x00c6, - 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xd6d1, 0x6014, 0x9005, - 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0db4, 0x0804, 0xd6d1, - 0x2048, 0x080c, 0xbb2c, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, - 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, - 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, - 0x2009, 0x0043, 0x080c, 0xcf5f, 0x0804, 0xd6d1, 0x2009, 0x0041, - 0x0804, 0xd6cb, 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, - 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xd5f4, 0xd0b4, 0x0128, - 0xd0fc, 0x090c, 0x0db4, 0x0804, 0xd615, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x83da, 0x080c, 0x896d, 0x00c6, 0x2d60, 0x6100, - 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xd6d1, 0x6814, - 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, - 0xa982, 0x00f6, 0x2c78, 0x080c, 0x164a, 0x00fe, 0x2009, 0x0042, - 0x04d0, 0x0036, 0x080c, 0x0feb, 0x090c, 0x0db4, 0xa867, 0x010d, - 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, - 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, - 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, 0xab7a, - 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, - 0x080c, 0x6891, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xd106, - 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, - 0x6342, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, - 0xcf5f, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, - 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, - 0x080c, 0x8861, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, - 0x080c, 0xd4f6, 0x009e, 0x003e, 0x080c, 0x896d, 0x0005, 0x9186, - 0x0014, 0x0d70, 0x080c, 0x9ed7, 0x0005, 0xd704, 0xd702, 0xd702, - 0xd702, 0xd702, 0xd702, 0xd704, 0xd702, 0xd702, 0xd702, 0xd702, - 0xd702, 0xd702, 0x080c, 0x0db4, 0x080c, 0x8861, 0x6003, 0x000c, - 0x080c, 0x896d, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, - 0x0208, 0x001a, 0x080c, 0x9ed7, 0x0005, 0xd722, 0xd722, 0xd722, - 0xd722, 0xd724, 0xd744, 0xd722, 0xd722, 0xd722, 0xd722, 0xd722, - 0xd722, 0xd722, 0x080c, 0x0db4, 0x00d6, 0x2c68, 0x080c, 0x9dec, - 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, - 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, - 0x6112, 0x6023, 0x0004, 0x080c, 0x83da, 0x080c, 0x896d, 0x2d60, - 0x080c, 0x9e42, 0x00de, 0x0005, 0x080c, 0x9e42, 0x0005, 0x00e6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, - 0x2009, 0x1873, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, - 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1958, 0x2004, 0x6042, - 0x2009, 0x1873, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1873, - 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, - 0x2001, 0x1958, 0x200c, 0x2001, 0x1956, 0x2004, 0x9100, 0x9080, - 0x000a, 0x6042, 0x6010, 0x00b6, 0x2058, 0xb8ac, 0x00be, 0x0008, - 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, - 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, - 0xb8ac, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, - 0x1138, 0x600c, 0x2072, 0x080c, 0x81ed, 0x080c, 0x9e42, 0x0010, - 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, - 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8ac, 0x2068, 0x9005, 0x0130, - 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, - 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182b, 0x2204, 0x9084, - 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x1508, 0x8318, 0x2334, - 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xae20, - 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, - 0x2048, 0x2019, 0x0006, 0x080c, 0xae20, 0x009e, 0x1100, 0x015e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c6d, - 0x080c, 0x2dbd, 0x00ee, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0xa880, - 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, - 0x19c0, 0x252c, 0x2021, 0x19c6, 0x2424, 0x2061, 0x1cd0, 0x2071, - 0x1800, 0x7650, 0x7070, 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, - 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, - 0x9c06, 0x01d0, 0x080c, 0xd57c, 0x01b8, 0x080c, 0xd58c, 0x11a0, - 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x190f, 0x001e, - 0x080c, 0xbd21, 0x1110, 0x080c, 0x3005, 0x080c, 0xbd32, 0x1110, - 0x080c, 0xa7d1, 0x080c, 0x9e72, 0x9ce0, 0x0018, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, - 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1836, 0x2004, - 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, 0xc22c, - 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, - 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4a86, 0x004e, 0x003e, - 0x000e, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x992c, 0x080c, - 0x9e72, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, - 0x1cd0, 0x2071, 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, 0x12b8, - 0x2100, 0x9c06, 0x0148, 0x6000, 0x9086, 0x0000, 0x0128, 0x6010, - 0x2058, 0xb8a0, 0x9206, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1220, 0x0c60, 0x9085, 0x0001, 0x0008, 0x9006, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, - 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7034, - 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, - 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, - 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0x184a, 0x0089, - 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, - 0x2091, 0x8000, 0x2071, 0x1842, 0x0021, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, - 0x2072, 0x0005, 0x00e6, 0x2071, 0x1840, 0x0c99, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1844, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, - 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7044, 0x8000, 0x7046, - 0x00ee, 0x000e, 0x012e, 0x0005, 0x0003, 0x000b, 0x04a6, 0x0000, - 0xc000, 0x0001, 0x8064, 0x0008, 0x0010, 0x0000, 0x8066, 0x0000, - 0x0101, 0x0008, 0x4407, 0x0003, 0x8060, 0x0000, 0x0400, 0x0000, - 0x580d, 0x000b, 0x798e, 0x0003, 0x50db, 0x000b, 0x4c0a, 0x0003, - 0xbac0, 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b, 0x15fe, 0x0008, - 0x340a, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffa0, 0x0001, - 0x2000, 0x0000, 0x1627, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, - 0x0000, 0x0007, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, 0x0000, - 0x0821, 0x0003, 0x4022, 0x0000, 0x0022, 0x000b, 0x4122, 0x0008, - 0x4447, 0x0002, 0x0e4f, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, - 0x122d, 0x000b, 0x0ca0, 0x0001, 0x122d, 0x000b, 0x9180, 0x0001, - 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x4430, 0x000b, 0x808c, 0x0008, - 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, 0x0000, - 0x8066, 0x0000, 0x0411, 0x0000, 0x4438, 0x0003, 0x03fe, 0x0000, - 0x43e0, 0x0001, 0x0e2a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, - 0x02e0, 0x0001, 0x0e2a, 0x000b, 0x9180, 0x0001, 0x0005, 0x0008, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0019, 0x0000, 0x4447, 0x000b, 0x0240, 0x0002, 0x0a27, 0x000b, - 0x00fe, 0x0000, 0x322a, 0x000b, 0x112a, 0x0000, 0x002e, 0x0008, - 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, - 0x0002, 0x0000, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0008, - 0x8066, 0x0000, 0x0011, 0x0008, 0x4458, 0x0003, 0x01fe, 0x0008, - 0x42e0, 0x0009, 0x0e1d, 0x0003, 0x00fe, 0x0000, 0x43e0, 0x0001, - 0x0e1d, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, 0x0008, - 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, 0x0008, - 0x446a, 0x000b, 0x808a, 0x0008, 0x0003, 0x0008, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0002, 0x0000, 0x5870, 0x000b, 0x8066, 0x0000, - 0x3679, 0x0000, 0x4473, 0x0003, 0x5874, 0x0003, 0x3efe, 0x0008, - 0x7f4f, 0x0002, 0x087a, 0x000b, 0x0d00, 0x0000, 0x0082, 0x0004, - 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, 0x1010, 0x0008, - 0x1efe, 0x0000, 0x300a, 0x000b, 0x00b8, 0x0004, 0x000a, 0x000b, - 0x00fe, 0x0000, 0x348a, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x0007, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x4489, 0x0003, - 0x03fe, 0x0000, 0x04d0, 0x0001, 0x0cb0, 0x0003, 0x82c0, 0x0001, - 0x1f00, 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000, 0x089f, 0x0003, - 0x14b0, 0x0003, 0x01fe, 0x0008, 0x0580, 0x0009, 0x7f06, 0x0000, - 0x02fe, 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0690, 0x0001, - 0x109f, 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008, - 0x08b0, 0x000b, 0x00fe, 0x0000, 0x34a6, 0x0003, 0x8072, 0x0000, - 0x1010, 0x0008, 0x3944, 0x0002, 0x08a1, 0x000b, 0x00aa, 0x000b, - 0x8072, 0x0000, 0x2020, 0x0008, 0x3945, 0x000a, 0x08a6, 0x0003, - 0x3946, 0x000a, 0x0cb7, 0x000b, 0x0000, 0x0007, 0x3943, 0x000a, - 0x08b7, 0x0003, 0x00aa, 0x000b, 0x00fe, 0x0000, 0x34b5, 0x000b, - 0x8072, 0x0000, 0x1000, 0x0000, 0x00b7, 0x000b, 0x8072, 0x0000, - 0x2000, 0x0000, 0x4000, 0x000f, 0x1c60, 0x0000, 0x1b62, 0x0000, - 0x8066, 0x0000, 0x0231, 0x0008, 0x44bc, 0x0003, 0x58bd, 0x0003, - 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0ccb, 0x0003, - 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, 0x0008, - 0x030a, 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000, 0x0d08, 0x0008, - 0x00cf, 0x000b, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, 0x0008, - 0x064a, 0x0000, 0x58cf, 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002, - 0x08d6, 0x000b, 0x8000, 0x0000, 0x0001, 0x0000, 0x0082, 0x0004, - 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, - 0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, 0x0003, 0x2b24, 0x0008, - 0x2b24, 0x0008, 0x58df, 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, - 0x1242, 0x0002, 0x092d, 0x000b, 0x3a45, 0x000a, 0x091c, 0x0003, - 0x8072, 0x0000, 0x1000, 0x0000, 0x3945, 0x000a, 0x08ec, 0x000b, - 0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, 0x000a, 0x7f3c, 0x0000, - 0x0917, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44f5, 0x000b, - 0x00fe, 0x0000, 0x3514, 0x000b, 0x1c60, 0x0000, 0x8062, 0x0008, - 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x44fd, 0x0003, - 0x00fe, 0x0000, 0x3204, 0x000b, 0x0038, 0x0000, 0x0060, 0x0008, - 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, - 0x4506, 0x0003, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, - 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x4510, 0x000b, 0x003a, 0x0008, - 0x1dfe, 0x0000, 0x00f1, 0x0003, 0x0036, 0x0008, 0x00b8, 0x0004, - 0x012d, 0x0003, 0x8074, 0x0000, 0x2000, 0x0000, 0x8072, 0x0000, - 0x2000, 0x0000, 0x012d, 0x0003, 0x3a44, 0x0002, 0x0a30, 0x000b, - 0x8074, 0x0000, 0x1000, 0x0000, 0x8072, 0x0000, 0x1000, 0x0000, - 0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3601, 0x0003, 0x26fe, 0x0008, - 0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, - 0x0d3f, 0x0003, 0x8074, 0x0000, 0x4040, 0x0008, 0x592d, 0x000b, - 0x50db, 0x000b, 0x3a46, 0x000a, 0x0d3f, 0x0003, 0x3a47, 0x0002, - 0x093a, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0x8000, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0182, 0x0003, - 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, 0x000a, - 0x0dfb, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, - 0x8066, 0x0000, 0x362a, 0x0000, 0x4544, 0x0003, 0x2000, 0x0000, - 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, - 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, - 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, - 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, - 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0052, 0x0000, - 0x455e, 0x000b, 0x92c0, 0x0009, 0x0780, 0x0008, 0x0e17, 0x0003, - 0x124b, 0x0002, 0x0967, 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x0a01, 0x0003, 0x3a46, 0x000a, 0x0d74, 0x0003, 0x5969, 0x000b, - 0x8054, 0x0008, 0x0004, 0x0000, 0x1243, 0x000a, 0x097e, 0x000b, - 0x8010, 0x0008, 0x000d, 0x0000, 0x01ef, 0x0004, 0x1810, 0x0000, - 0x01ef, 0x0004, 0x017e, 0x0003, 0x194d, 0x000a, 0x0978, 0x000b, - 0x1243, 0x000a, 0x0a0b, 0x0003, 0x5978, 0x000b, 0x8054, 0x0008, - 0x0004, 0x0000, 0x01e4, 0x000c, 0x1810, 0x0000, 0x01ef, 0x0004, - 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, - 0x0d30, 0x0000, 0x3a42, 0x0002, 0x0d88, 0x0003, 0x15fe, 0x0008, - 0x3451, 0x000b, 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, 0x0000, - 0x8010, 0x0008, 0x000c, 0x0008, 0x01ef, 0x0004, 0x000a, 0x000b, - 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d9e, 0x000b, 0x18fe, 0x0000, - 0x3ce0, 0x0009, 0x099b, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, - 0x099b, 0x0003, 0x01df, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, - 0x01dc, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x01dc, 0x000b, - 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0da3, 0x0003, 0x3c1e, 0x0008, - 0x01dc, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, 0x0dc1, 0x000b, - 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d9b, 0x000b, 0x8076, 0x0008, - 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x000d, 0x0000, - 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, 0x0008, - 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, 0x0000, - 0x8066, 0x0000, 0x0422, 0x0000, 0x45b8, 0x0003, 0x01e4, 0x000c, - 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, 0x0008, - 0x8072, 0x0000, 0xb000, 0x0000, 0x0182, 0x0003, 0xbbe0, 0x0009, - 0x0038, 0x0000, 0x0dd3, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, - 0x09d0, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d97, 0x000b, - 0x01df, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, 0x0000, - 0x8000, 0x0000, 0x0227, 0x0003, 0x8076, 0x0008, 0x0042, 0x0008, - 0x01dc, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0ddc, 0x000b, - 0x3a44, 0x0002, 0x0c0c, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, - 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, - 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, 0x0001, - 0x0007, 0x0000, 0x01e8, 0x0003, 0x1930, 0x000a, 0x7f00, 0x0000, - 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0x45ed, 0x0003, - 0x4000, 0x000f, 0x21ef, 0x0003, 0x0870, 0x0008, 0x4000, 0x000f, - 0xbac0, 0x0009, 0x0090, 0x0008, 0x09f8, 0x0003, 0x8074, 0x0000, - 0x0706, 0x0000, 0x01fa, 0x0003, 0x8074, 0x0000, 0x0703, 0x0000, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x0235, 0x0003, - 0x8010, 0x0008, 0x0008, 0x0000, 0x0235, 0x0003, 0x8010, 0x0008, - 0x0022, 0x0008, 0x0235, 0x0003, 0x01e4, 0x000c, 0x8010, 0x0008, - 0x0007, 0x0000, 0x01ef, 0x0004, 0x1810, 0x0000, 0x01ef, 0x0004, - 0x0241, 0x0003, 0x01e4, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, - 0x01ef, 0x0004, 0x1810, 0x0000, 0x01ef, 0x0004, 0x8074, 0x0000, - 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x000a, 0x000b, 0x8010, 0x0008, 0x0009, 0x0008, 0x0235, 0x0003, - 0x8010, 0x0008, 0x0005, 0x0008, 0x0235, 0x0003, 0x808c, 0x0008, - 0x0001, 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, 0x000a, - 0x085f, 0x0003, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x0d2a, 0x0008, - 0x0235, 0x0003, 0x8010, 0x0008, 0x0003, 0x0008, 0x0239, 0x0003, - 0x8010, 0x0008, 0x000b, 0x0000, 0x0239, 0x0003, 0x8010, 0x0008, - 0x0002, 0x0000, 0x0239, 0x0003, 0x3a47, 0x0002, 0x0d2d, 0x0003, - 0x8010, 0x0008, 0x0006, 0x0008, 0x0239, 0x0003, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x01ef, 0x0004, - 0x01f2, 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, 0x8010, 0x0008, - 0x000c, 0x0008, 0x01ef, 0x0004, 0x000a, 0x000b, 0x8074, 0x0000, - 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a4c, 0x0003, 0x8054, 0x0008, - 0x0019, 0x0000, 0x000a, 0x000b, 0x8054, 0x0008, 0x0009, 0x0008, - 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x022a, 0x000b, - 0x15b6, 0xf4ac, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, - 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, - 0x4000, 0x8000, 0x0a42 + 0xd5f4, 0xd5f6, 0xd5f4, 0xd5f6, 0xd5f6, 0xd5f4, 0xd5f6, 0xd5f4, + 0xd5f4, 0xd5f4, 0xd5f4, 0xd5f4, 0x9006, 0x0005, 0x9085, 0x0001, + 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd60d, + 0xd60d, 0xd60d, 0xd60d, 0xd60d, 0xd60d, 0xd61a, 0xd60d, 0xd60d, + 0xd60d, 0xd60d, 0xd60d, 0xd60d, 0xd60d, 0x6007, 0x003b, 0x602f, + 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x080c, 0x83f8, 0x080c, + 0x898b, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xd7c1, 0x6043, + 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, + 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xd673, 0x6814, 0x9005, + 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, + 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, + 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xd6ea, 0x6014, + 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0db4, 0x0804, + 0xd6ea, 0x2048, 0x080c, 0xbb3b, 0x1130, 0x0028, 0x2048, 0xa800, + 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, + 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, + 0xa882, 0x2009, 0x0043, 0x080c, 0xcf73, 0x0804, 0xd6ea, 0x2009, + 0x0041, 0x0804, 0xd6e4, 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, + 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xd60d, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x0db4, 0x0804, 0xd62e, 0x6007, 0x003a, + 0x6003, 0x0001, 0x080c, 0x83f8, 0x080c, 0x898b, 0x00c6, 0x2d60, + 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xd6ea, + 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, + 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x164a, 0x00fe, 0x2009, + 0x0042, 0x04d0, 0x0036, 0x080c, 0x0feb, 0x090c, 0x0db4, 0xa867, + 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, + 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, + 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, + 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, + 0x0001, 0x080c, 0x68a0, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xd11f, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, + 0x631a, 0x6342, 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, + 0x080c, 0xcf73, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, + 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, + 0x1178, 0x080c, 0x887f, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, + 0x0004, 0x080c, 0xd50f, 0x009e, 0x003e, 0x080c, 0x898b, 0x0005, + 0x9186, 0x0014, 0x0d70, 0x080c, 0x9ec4, 0x0005, 0xd71d, 0xd71b, + 0xd71b, 0xd71b, 0xd71b, 0xd71b, 0xd71d, 0xd71b, 0xd71b, 0xd71b, + 0xd71b, 0xd71b, 0xd71b, 0x080c, 0x0db4, 0x080c, 0x887f, 0x6003, + 0x000c, 0x080c, 0x898b, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, + 0x0085, 0x0208, 0x001a, 0x080c, 0x9ec4, 0x0005, 0xd73b, 0xd73b, + 0xd73b, 0xd73b, 0xd73d, 0xd75d, 0xd73b, 0xd73b, 0xd73b, 0xd73b, + 0xd73b, 0xd73b, 0xd73b, 0x080c, 0x0db4, 0x00d6, 0x2c68, 0x080c, + 0x9dd9, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, + 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, + 0x6910, 0x6112, 0x6023, 0x0004, 0x080c, 0x83f8, 0x080c, 0x898b, + 0x2d60, 0x080c, 0x9e2f, 0x00de, 0x0005, 0x080c, 0x9e2f, 0x0005, + 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, + 0x0005, 0x2009, 0x187b, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, + 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1960, 0x2004, + 0x6042, 0x2009, 0x187b, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, + 0x187b, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, + 0x00d8, 0x2001, 0x1960, 0x200c, 0x2001, 0x195e, 0x2004, 0x9100, + 0x9080, 0x000a, 0x6042, 0x6010, 0x00b6, 0x2058, 0xb8ac, 0x00be, + 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, + 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, + 0x6154, 0xb8ac, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, + 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x820b, 0x080c, 0x9e2f, + 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, + 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8ac, 0x2068, 0x9005, + 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, + 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182b, 0x2204, + 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x1508, 0x8318, + 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, + 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, + 0xae1c, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, + 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xae1c, 0x009e, 0x1100, + 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x5c78, 0x080c, 0x2dc8, 0x00ee, 0x0005, 0x00e6, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, + 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, + 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, + 0x2029, 0x19c8, 0x252c, 0x2021, 0x19ce, 0x2424, 0x2061, 0x1cd0, + 0x2071, 0x1800, 0x7650, 0x7070, 0x9606, 0x0578, 0x6720, 0x9786, + 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, + 0x2400, 0x9c06, 0x01d0, 0x080c, 0xd595, 0x01b8, 0x080c, 0xd5a5, + 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x191f, + 0x001e, 0x080c, 0xbd30, 0x1110, 0x080c, 0x3010, 0x080c, 0xbd41, + 0x1110, 0x080c, 0xa7cd, 0x080c, 0x9e5f, 0x9ce0, 0x0018, 0x2001, + 0x1819, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1836, + 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, + 0xc23b, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, + 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4a91, 0x004e, + 0x003e, 0x000e, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x9915, + 0x080c, 0x9e5f, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, 0x0046, + 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, + 0x12b8, 0x2100, 0x9c06, 0x0148, 0x6000, 0x9086, 0x0000, 0x0128, + 0x6010, 0x2058, 0xb8a0, 0x9206, 0x0140, 0x9ce0, 0x0018, 0x2001, + 0x1819, 0x2004, 0x9c02, 0x1220, 0x0c60, 0x9085, 0x0001, 0x0008, + 0x9006, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, + 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, + 0x7054, 0x8000, 0x7056, 0xd5b4, 0x0118, 0x7050, 0x8000, 0x7052, + 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, + 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0x184a, + 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, + 0x00e6, 0x2091, 0x8000, 0x2071, 0x1842, 0x0021, 0x00ee, 0x000e, + 0x012e, 0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, + 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0x1840, 0x0c99, 0x00ee, + 0x0005, 0x00e6, 0x2071, 0x1844, 0x0c69, 0x00ee, 0x0005, 0x0126, + 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7064, 0x8000, + 0x7066, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0003, 0x000b, 0x04a6, + 0x0000, 0xc000, 0x0001, 0x8064, 0x0008, 0x0010, 0x0000, 0x8066, + 0x0000, 0x0101, 0x0008, 0x4407, 0x0003, 0x8060, 0x0000, 0x0400, + 0x0000, 0x580d, 0x000b, 0x798e, 0x0003, 0x50db, 0x000b, 0x4c0a, + 0x0003, 0xbac0, 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b, 0x15fe, + 0x0008, 0x340a, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffa0, + 0x0001, 0x2000, 0x0000, 0x1627, 0x0003, 0x808c, 0x0008, 0x0001, + 0x0000, 0x0000, 0x0007, 0x4047, 0x000a, 0x808c, 0x0008, 0x0002, + 0x0000, 0x0821, 0x0003, 0x4022, 0x0000, 0x0022, 0x000b, 0x4122, + 0x0008, 0x4447, 0x0002, 0x0e4f, 0x000b, 0x0bfe, 0x0008, 0x11a0, + 0x0001, 0x122d, 0x000b, 0x0ca0, 0x0001, 0x122d, 0x000b, 0x9180, + 0x0001, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4430, 0x000b, 0x808c, + 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, + 0x0000, 0x8066, 0x0000, 0x0411, 0x0000, 0x4438, 0x0003, 0x03fe, + 0x0000, 0x43e0, 0x0001, 0x0e2a, 0x000b, 0xc2c0, 0x0009, 0x00ff, + 0x0008, 0x02e0, 0x0001, 0x0e2a, 0x000b, 0x9180, 0x0001, 0x0005, + 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, + 0x0000, 0x0019, 0x0000, 0x4447, 0x000b, 0x0240, 0x0002, 0x0a27, + 0x000b, 0x00fe, 0x0000, 0x322a, 0x000b, 0x112a, 0x0000, 0x002e, + 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, + 0x0008, 0x0002, 0x0000, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, + 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x4458, 0x0003, 0x01fe, + 0x0008, 0x42e0, 0x0009, 0x0e1d, 0x0003, 0x00fe, 0x0000, 0x43e0, + 0x0001, 0x0e1d, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, 0x1632, + 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, 0x8060, + 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x1e0a, + 0x0008, 0x446a, 0x000b, 0x808a, 0x0008, 0x0003, 0x0008, 0x1a60, + 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, 0x5870, 0x000b, 0x8066, + 0x0000, 0x3679, 0x0000, 0x4473, 0x0003, 0x5874, 0x0003, 0x3efe, + 0x0008, 0x7f4f, 0x0002, 0x087a, 0x000b, 0x0d00, 0x0000, 0x0082, + 0x0004, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, 0x1010, + 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, 0x00b8, 0x0004, 0x000a, + 0x000b, 0x00fe, 0x0000, 0x348a, 0x000b, 0x1a60, 0x0000, 0x8062, + 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x4489, + 0x0003, 0x03fe, 0x0000, 0x04d0, 0x0001, 0x0cb0, 0x0003, 0x82c0, + 0x0001, 0x1f00, 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000, 0x089f, + 0x0003, 0x14b0, 0x0003, 0x01fe, 0x0008, 0x0580, 0x0009, 0x7f06, + 0x0000, 0x02fe, 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0690, + 0x0001, 0x109f, 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, + 0x0008, 0x08b0, 0x000b, 0x00fe, 0x0000, 0x34a6, 0x0003, 0x8072, + 0x0000, 0x1010, 0x0008, 0x3944, 0x0002, 0x08a1, 0x000b, 0x00aa, + 0x000b, 0x8072, 0x0000, 0x2020, 0x0008, 0x3945, 0x000a, 0x08a6, + 0x0003, 0x3946, 0x000a, 0x0cb7, 0x000b, 0x0000, 0x0007, 0x3943, + 0x000a, 0x08b7, 0x0003, 0x00aa, 0x000b, 0x00fe, 0x0000, 0x34b5, + 0x000b, 0x8072, 0x0000, 0x1000, 0x0000, 0x00b7, 0x000b, 0x8072, + 0x0000, 0x2000, 0x0000, 0x4000, 0x000f, 0x1c60, 0x0000, 0x1b62, + 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x44bc, 0x0003, 0x58bd, + 0x0003, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, 0x0ccb, + 0x0003, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, + 0x0008, 0x030a, 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000, 0x0d08, + 0x0008, 0x00cf, 0x000b, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, + 0x0008, 0x064a, 0x0000, 0x58cf, 0x0003, 0x3efe, 0x0008, 0x7f4f, + 0x0002, 0x08d6, 0x000b, 0x8000, 0x0000, 0x0001, 0x0000, 0x0082, + 0x0004, 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, + 0x0008, 0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, 0x0003, 0x2b24, + 0x0008, 0x2b24, 0x0008, 0x58df, 0x000b, 0x8054, 0x0008, 0x0002, + 0x0000, 0x1242, 0x0002, 0x092d, 0x000b, 0x3a45, 0x000a, 0x091c, + 0x0003, 0x8072, 0x0000, 0x1000, 0x0000, 0x3945, 0x000a, 0x08ec, + 0x000b, 0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, 0x000a, 0x7f3c, + 0x0000, 0x0917, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x44f5, + 0x000b, 0x00fe, 0x0000, 0x3514, 0x000b, 0x1c60, 0x0000, 0x8062, + 0x0008, 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x44fd, + 0x0003, 0x00fe, 0x0000, 0x3204, 0x000b, 0x0038, 0x0000, 0x0060, + 0x0008, 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, + 0x0008, 0x4506, 0x0003, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, + 0x0008, 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, + 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4510, 0x000b, 0x003a, + 0x0008, 0x1dfe, 0x0000, 0x00f1, 0x0003, 0x0036, 0x0008, 0x00b8, + 0x0004, 0x012d, 0x0003, 0x8074, 0x0000, 0x2000, 0x0000, 0x8072, + 0x0000, 0x2000, 0x0000, 0x012d, 0x0003, 0x3a44, 0x0002, 0x0a30, + 0x000b, 0x8074, 0x0000, 0x1000, 0x0000, 0x8072, 0x0000, 0x1000, + 0x0000, 0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3601, 0x0003, 0x26fe, + 0x0008, 0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, 0x0008, 0x00d0, + 0x0009, 0x0d3f, 0x0003, 0x8074, 0x0000, 0x4040, 0x0008, 0x592d, + 0x000b, 0x50db, 0x000b, 0x3a46, 0x000a, 0x0d3f, 0x0003, 0x3a47, + 0x0002, 0x093a, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, + 0x0000, 0x8000, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0182, + 0x0003, 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, + 0x000a, 0x0dfb, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, + 0x0000, 0x8066, 0x0000, 0x362a, 0x0000, 0x4544, 0x0003, 0x2000, + 0x0000, 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, + 0x0000, 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, + 0x0000, 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, + 0x0000, 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, + 0x0000, 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x1a60, + 0x0000, 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0052, + 0x0000, 0x455e, 0x000b, 0x92c0, 0x0009, 0x0780, 0x0008, 0x0e17, + 0x0003, 0x124b, 0x0002, 0x0967, 0x0003, 0x2e4d, 0x0002, 0x2e4d, + 0x0002, 0x0a01, 0x0003, 0x3a46, 0x000a, 0x0d74, 0x0003, 0x5969, + 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x1243, 0x000a, 0x097e, + 0x000b, 0x8010, 0x0008, 0x000d, 0x0000, 0x01ef, 0x0004, 0x1810, + 0x0000, 0x01ef, 0x0004, 0x017e, 0x0003, 0x194d, 0x000a, 0x0978, + 0x000b, 0x1243, 0x000a, 0x0a0b, 0x0003, 0x5978, 0x000b, 0x8054, + 0x0008, 0x0004, 0x0000, 0x01e4, 0x000c, 0x1810, 0x0000, 0x01ef, + 0x0004, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, + 0x0008, 0x0d30, 0x0000, 0x3a42, 0x0002, 0x0d88, 0x0003, 0x15fe, + 0x0008, 0x3451, 0x000b, 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, + 0x0000, 0x8010, 0x0008, 0x000c, 0x0008, 0x01ef, 0x0004, 0x000a, + 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, 0x0d9e, 0x000b, 0x18fe, + 0x0000, 0x3ce0, 0x0009, 0x099b, 0x0003, 0x15fe, 0x0008, 0x3ce0, + 0x0009, 0x099b, 0x0003, 0x01df, 0x0004, 0x8076, 0x0008, 0x0040, + 0x0000, 0x01dc, 0x000b, 0x8076, 0x0008, 0x0041, 0x0008, 0x01dc, + 0x000b, 0xbbe0, 0x0009, 0x0032, 0x0000, 0x0da3, 0x0003, 0x3c1e, + 0x0008, 0x01dc, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, 0x0dc1, + 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0d9b, 0x000b, 0x8076, + 0x0008, 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, 0x000d, + 0x0000, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, 0x2706, + 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, 0x290a, + 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x45b8, 0x0003, 0x01e4, + 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, 0xf000, + 0x0008, 0x8072, 0x0000, 0xb000, 0x0000, 0x0182, 0x0003, 0xbbe0, + 0x0009, 0x0038, 0x0000, 0x0dd3, 0x000b, 0x18fe, 0x0000, 0x3ce0, + 0x0009, 0x09d0, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0d97, + 0x000b, 0x01df, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x8072, + 0x0000, 0x8000, 0x0000, 0x0227, 0x0003, 0x8076, 0x0008, 0x0042, + 0x0008, 0x01dc, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, 0x0ddc, + 0x000b, 0x3a44, 0x0002, 0x0c0c, 0x000b, 0x8072, 0x0000, 0x8000, + 0x0000, 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, 0x8000, + 0x0000, 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, 0xbc80, + 0x0001, 0x0007, 0x0000, 0x01e8, 0x0003, 0x1930, 0x000a, 0x7f00, + 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, 0x0400, + 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, 0x45ed, + 0x0003, 0x4000, 0x000f, 0x21ef, 0x0003, 0x0870, 0x0008, 0x4000, + 0x000f, 0xbac0, 0x0009, 0x0090, 0x0008, 0x09f8, 0x0003, 0x8074, + 0x0000, 0x0706, 0x0000, 0x01fa, 0x0003, 0x8074, 0x0000, 0x0703, + 0x0000, 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x0235, + 0x0003, 0x8010, 0x0008, 0x0008, 0x0000, 0x0235, 0x0003, 0x8010, + 0x0008, 0x0022, 0x0008, 0x0235, 0x0003, 0x01e4, 0x000c, 0x8010, + 0x0008, 0x0007, 0x0000, 0x01ef, 0x0004, 0x1810, 0x0000, 0x01ef, + 0x0004, 0x0241, 0x0003, 0x01e4, 0x000c, 0x8010, 0x0008, 0x001b, + 0x0008, 0x01ef, 0x0004, 0x1810, 0x0000, 0x01ef, 0x0004, 0x8074, + 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, + 0x0000, 0x000a, 0x000b, 0x8010, 0x0008, 0x0009, 0x0008, 0x0235, + 0x0003, 0x8010, 0x0008, 0x0005, 0x0008, 0x0235, 0x0003, 0x808c, + 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, 0x0004, 0x0000, 0x4143, + 0x000a, 0x085f, 0x0003, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x0d2a, + 0x0008, 0x0235, 0x0003, 0x8010, 0x0008, 0x0003, 0x0008, 0x0239, + 0x0003, 0x8010, 0x0008, 0x000b, 0x0000, 0x0239, 0x0003, 0x8010, + 0x0008, 0x0002, 0x0000, 0x0239, 0x0003, 0x3a47, 0x0002, 0x0d2d, + 0x0003, 0x8010, 0x0008, 0x0006, 0x0008, 0x0239, 0x0003, 0x8074, + 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x01ef, + 0x0004, 0x01f2, 0x0004, 0x3a40, 0x000a, 0x080a, 0x0003, 0x8010, + 0x0008, 0x000c, 0x0008, 0x01ef, 0x0004, 0x000a, 0x000b, 0x8074, + 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, + 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, 0x0a4c, 0x0003, 0x8054, + 0x0008, 0x0019, 0x0000, 0x000a, 0x000b, 0x8054, 0x0008, 0x0009, + 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x022a, + 0x000b, 0x15b6, 0xf4ac, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, + 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, + 0x2000, 0x4000, 0x8000, 0x2a9a }; #ifdef UNIQUE_FW_NAME -unsigned short fw2300flx_length01 = 0xd5bb; +unsigned short fw2300flx_length01 = 0xd5d4; #else -unsigned short risc_code_length01 = 0xd5bb; +unsigned short risc_code_length01 = 0xd5d4; #endif diff --git a/drivers/scsi/qla2xxx/ql6322.c b/drivers/scsi/qla2xxx/ql6322.c index ce651454d..75fb9b266 100644 --- a/drivers/scsi/qla2xxx/ql6322.c +++ b/drivers/scsi/qla2xxx/ql6322.c @@ -105,3 +105,4 @@ module_exit(qla6322_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic ISP6322 FC-SCSI Host Bus Adapter driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql6322_fw.c b/drivers/scsi/qla2xxx/ql6322_fw.c index de1cbcbe8..c2e6156c3 100644 --- a/drivers/scsi/qla2xxx/ql6322_fw.c +++ b/drivers/scsi/qla2xxx/ql6322_fw.c @@ -18,25 +18,25 @@ *************************************************************************/ /* - * Firmware Version 3.02.30 (07:56 Jun 16, 2004) + * Firmware Version 3.03.02 (16:54 Aug 10, 2004) */ #ifdef UNIQUE_FW_NAME -unsigned short fw2322flx_version = 3*1024+2; +unsigned short fw2322flx_version = 3*1024+3; #else -unsigned short risc_code_version = 3*1024+2; +unsigned short risc_code_version = 3*1024+3; #endif #ifdef UNIQUE_FW_NAME -unsigned char fw2322flx_version_str[] = {3, 2,30}; +unsigned char fw2322flx_version_str[] = {3, 3, 2}; #else -unsigned char firmware_version[] = {3, 2,30}; +unsigned char firmware_version[] = {3, 3, 2}; #endif #ifdef UNIQUE_FW_NAME -#define fw2322flx_VERSION_STRING "3.02.30" +#define fw2322flx_VERSION_STRING "3.03.02" #else -#define FW_VERSION_STRING "3.02.30" +#define FW_VERSION_STRING "3.03.02" #endif #ifdef UNIQUE_FW_NAME @@ -50,12 +50,12 @@ unsigned short fw2322flx_code01[] = { #else unsigned short risc_code01[] = { #endif - 0x0470, 0x0000, 0x0000, 0xce4c, 0x0000, 0x0003, 0x0002, 0x001e, + 0x0470, 0x0000, 0x0000, 0xce84, 0x0000, 0x0003, 0x0003, 0x0002, 0x0317, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3032, 0x2e33, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, + 0x332e, 0x3033, 0x2e30, 0x3220, 0x2020, 0x2020, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, @@ -64,161 +64,161 @@ unsigned short risc_code01[] = { 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1cff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x28ec, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e3d, 0x00f6, - 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x1f09, 0x1170, - 0x2079, 0x0300, 0x080c, 0x1f1f, 0x2061, 0xe000, 0x080c, 0x1f09, - 0x1128, 0x2079, 0x0380, 0x080c, 0x1f1f, 0x0060, 0x00fe, 0x7883, + 0x7883, 0x0004, 0x2089, 0x290c, 0x2051, 0x1800, 0x2a70, 0x20e1, + 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e4a, 0x00f6, + 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x1f21, 0x1170, + 0x2079, 0x0300, 0x080c, 0x1f37, 0x2061, 0xe000, 0x080c, 0x1f21, + 0x1128, 0x2079, 0x0380, 0x080c, 0x1f37, 0x0060, 0x00fe, 0x7883, 0x4010, 0x7837, 0x4010, 0x7833, 0x0010, 0x2091, 0x5000, 0x2091, 0x4080, 0x0cf8, 0x00fe, 0x2029, 0x26c0, 0x2031, 0xffff, 0x2039, 0x269c, 0x2021, 0x0050, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x0dc1, 0x9084, 0x0fff, 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, 0x4104, 0x8001, 0x1de0, 0x756a, - 0x766e, 0x7766, 0x7472, 0x7476, 0x00e6, 0x2071, 0x1b1d, 0x2472, + 0x766e, 0x7766, 0x7472, 0x7476, 0x00e6, 0x2071, 0x1b25, 0x2472, 0x00ee, 0x20a1, 0x1ddc, 0x716c, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x716c, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, - 0x1dd8, 0x080c, 0x0f3a, 0x080c, 0x5ce5, 0x080c, 0x9b70, 0x080c, - 0x10f1, 0x080c, 0x12e1, 0x080c, 0x1a67, 0x080c, 0x8422, 0x080c, - 0x0cf7, 0x080c, 0x1076, 0x080c, 0x327f, 0x080c, 0x73aa, 0x080c, - 0x6721, 0x080c, 0x8069, 0x080c, 0x20f6, 0x080c, 0x7a3e, 0x080c, - 0x1f38, 0x080c, 0x2076, 0x080c, 0x20eb, 0x2091, 0x3009, 0x7883, + 0x1dd8, 0x080c, 0x0f47, 0x080c, 0x5d05, 0x080c, 0x9b7c, 0x080c, + 0x10fe, 0x080c, 0x12ee, 0x080c, 0x1a7f, 0x080c, 0x8456, 0x080c, + 0x0cf7, 0x080c, 0x1083, 0x080c, 0x329f, 0x080c, 0x73cd, 0x080c, + 0x6745, 0x080c, 0x809d, 0x080c, 0x210e, 0x080c, 0x7a62, 0x080c, + 0x1f50, 0x080c, 0x208e, 0x080c, 0x2103, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, 0x0941, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, 0x0935, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11c9, 0x2071, 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, - 0x908e, 0x0003, 0x1158, 0x080c, 0x499f, 0x080c, 0x32a6, 0x080c, - 0x7412, 0x080c, 0x6bb9, 0x080c, 0x8092, 0x0c78, 0x000b, 0x0c98, + 0x11d6, 0x2071, 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, + 0x908e, 0x0003, 0x1158, 0x080c, 0x49bf, 0x080c, 0x32c6, 0x080c, + 0x7435, 0x080c, 0x6bdd, 0x080c, 0x80c6, 0x0c78, 0x000b, 0x0c98, 0x0962, 0x0963, 0x0afa, 0x0960, 0x0bab, 0x0cf6, 0x0cf6, 0x0cf6, 0x080c, 0x0d65, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, - 0x9086, 0x0001, 0x1904, 0x0acd, 0x080c, 0x0e8d, 0x080c, 0x7096, - 0x0150, 0x080c, 0x70b9, 0x15b0, 0x2079, 0x0100, 0x7828, 0x9085, - 0x1800, 0x782a, 0x0478, 0x080c, 0x6fc7, 0x7000, 0x9086, 0x0001, + 0x9086, 0x0001, 0x1904, 0x0acd, 0x080c, 0x0e9a, 0x080c, 0x70ba, + 0x0150, 0x080c, 0x70dd, 0x15b0, 0x2079, 0x0100, 0x7828, 0x9085, + 0x1800, 0x782a, 0x0478, 0x080c, 0x6feb, 0x7000, 0x9086, 0x0001, 0x1904, 0x0acd, 0x7094, 0x9086, 0x0028, 0x1904, 0x0acd, 0x080c, - 0x8061, 0x080c, 0x8053, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, - 0x0100, 0x2011, 0xffff, 0x080c, 0x288c, 0x7a28, 0x9295, 0x5e2c, - 0x7a2a, 0x2011, 0x6f0c, 0x080c, 0x8138, 0x2011, 0x6eff, 0x080c, - 0x823e, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x2011, 0x8030, 0x901e, - 0x7392, 0x04d0, 0x080c, 0x53e9, 0x2079, 0x0100, 0x7844, 0x9005, - 0x1904, 0x0acd, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x2011, 0x6f0c, - 0x080c, 0x8138, 0x2011, 0x6eff, 0x080c, 0x823e, 0x2001, 0x0265, + 0x8095, 0x080c, 0x8087, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, + 0x0100, 0x2011, 0xffff, 0x080c, 0x28ac, 0x7a28, 0x9295, 0x5e2c, + 0x7a2a, 0x2011, 0x6f30, 0x080c, 0x816c, 0x2011, 0x6f23, 0x080c, + 0x8272, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x2011, 0x8030, 0x901e, + 0x7392, 0x04d0, 0x080c, 0x5409, 0x2079, 0x0100, 0x7844, 0x9005, + 0x1904, 0x0acd, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x2011, 0x6f30, + 0x080c, 0x816c, 0x2011, 0x6f23, 0x080c, 0x8272, 0x2001, 0x0265, 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, - 0x2001, 0x1976, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, - 0x080c, 0x5c8d, 0x00ce, 0x0804, 0x0acd, 0x780f, 0x006b, 0x7a28, - 0x080c, 0x709e, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, - 0x7a2a, 0x2011, 0x8010, 0x73d4, 0x2001, 0x1977, 0x2003, 0x0001, - 0x080c, 0x2758, 0x080c, 0x48da, 0x7244, 0xc284, 0x7246, 0x2001, + 0x2001, 0x197e, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, + 0x080c, 0x5cad, 0x00ce, 0x0804, 0x0acd, 0x780f, 0x006b, 0x7a28, + 0x080c, 0x70c2, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, + 0x7a2a, 0x2011, 0x8010, 0x73d4, 0x2001, 0x197f, 0x2003, 0x0001, + 0x080c, 0x2774, 0x080c, 0x48fa, 0x7244, 0xc284, 0x7246, 0x2001, 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x2001, 0x0390, 0x2003, - 0x0400, 0x080c, 0x98bb, 0x080c, 0x91c4, 0x2011, 0x0004, 0x080c, - 0xb852, 0x080c, 0x98d7, 0x080c, 0x6561, 0x080c, 0x7096, 0x1120, - 0x080c, 0x27b9, 0x0600, 0x0420, 0x080c, 0x5c94, 0x0140, 0x7093, - 0x0001, 0x70cf, 0x0000, 0x080c, 0x55b6, 0x0804, 0x0acd, 0x080c, - 0x5388, 0xd094, 0x01a8, 0x2001, 0x0390, 0x2003, 0x0404, 0x2011, - 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x538c, 0xd0d4, 0x1118, - 0x080c, 0x27b9, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x0088, - 0x080c, 0x538c, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, - 0x0040, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x665e, - 0x0008, 0x2012, 0x080c, 0x6624, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707b, 0x0000, 0x080c, 0x7096, 0x1130, 0x70ac, 0x9005, - 0x1168, 0x080c, 0xbcae, 0x0050, 0x080c, 0xbcae, 0x70d8, 0xd09c, - 0x1128, 0x70ac, 0x9005, 0x0110, 0x080c, 0x5c6a, 0x70e3, 0x0000, - 0x70df, 0x0000, 0x70a3, 0x0000, 0x080c, 0x27c1, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72d8, 0x080c, 0x7096, 0x1178, - 0x9016, 0x0016, 0x2009, 0x0002, 0x2019, 0x193d, 0x211a, 0x001e, + 0x0400, 0x080c, 0x98c7, 0x080c, 0x91f8, 0x2011, 0x0004, 0x080c, + 0xb880, 0x080c, 0x98e3, 0x080c, 0x6585, 0x080c, 0x70ba, 0x1120, + 0x080c, 0x27d5, 0x0600, 0x0420, 0x080c, 0x5cb4, 0x0140, 0x7093, + 0x0001, 0x70cf, 0x0000, 0x080c, 0x55d6, 0x0804, 0x0acd, 0x080c, + 0x53a8, 0xd094, 0x01a8, 0x2001, 0x0390, 0x2003, 0x0404, 0x2011, + 0x180c, 0x2204, 0xc0cd, 0x2012, 0x080c, 0x53ac, 0xd0d4, 0x1118, + 0x080c, 0x27d5, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x0088, + 0x080c, 0x53ac, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, + 0x0040, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6682, + 0x0008, 0x2012, 0x080c, 0x6648, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, + 0x00a8, 0x707b, 0x0000, 0x080c, 0x70ba, 0x1130, 0x70ac, 0x9005, + 0x1168, 0x080c, 0xbcdc, 0x0050, 0x080c, 0xbcdc, 0x70d8, 0xd09c, + 0x1128, 0x70ac, 0x9005, 0x0110, 0x080c, 0x5c8a, 0x70e3, 0x0000, + 0x70df, 0x0000, 0x70a3, 0x0000, 0x080c, 0x27dd, 0x0228, 0x2011, + 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72d8, 0x080c, 0x70ba, 0x1178, + 0x9016, 0x0016, 0x2009, 0x0002, 0x2019, 0x1945, 0x211a, 0x001e, 0x705b, 0xffff, 0x705f, 0x00ef, 0x707f, 0x0000, 0x0020, 0x2019, - 0x193d, 0x201b, 0x0000, 0x2079, 0x1853, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72da, 0x080c, 0x7096, 0x0118, 0x9296, 0x0004, 0x0518, - 0x2011, 0x0001, 0x080c, 0xb852, 0x70a7, 0x0000, 0x70ab, 0xffff, - 0x7003, 0x0002, 0x00fe, 0x080c, 0x2de9, 0x080c, 0x98bb, 0x2011, - 0x0005, 0x080c, 0x931c, 0x080c, 0x98d7, 0x080c, 0x7096, 0x0148, + 0x1945, 0x201b, 0x0000, 0x2079, 0x185b, 0x7804, 0xd0ac, 0x0108, + 0xc295, 0x72da, 0x080c, 0x70ba, 0x0118, 0x9296, 0x0004, 0x0518, + 0x2011, 0x0001, 0x080c, 0xb880, 0x70a7, 0x0000, 0x70ab, 0xffff, + 0x7003, 0x0002, 0x00fe, 0x080c, 0x2e09, 0x080c, 0x98c7, 0x2011, + 0x0005, 0x080c, 0x9324, 0x080c, 0x98e3, 0x080c, 0x70ba, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x00e0, 0x70a7, 0x0000, 0x70ab, 0xffff, 0x7003, - 0x0002, 0x080c, 0x98bb, 0x2011, 0x0005, 0x080c, 0x931c, 0x080c, - 0x98d7, 0x080c, 0x7096, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, + 0x0002, 0x080c, 0x98c7, 0x2011, 0x0005, 0x080c, 0x9324, 0x080c, + 0x98e3, 0x080c, 0x70ba, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x2009, 0x0002, 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, - 0x00c6, 0x00b6, 0x080c, 0x7096, 0x1118, 0x20a9, 0x0800, 0x0010, - 0x20a9, 0x0782, 0x080c, 0x7096, 0x1110, 0x900e, 0x0010, 0x2009, + 0x00c6, 0x00b6, 0x080c, 0x70ba, 0x1118, 0x20a9, 0x0800, 0x0010, + 0x20a9, 0x0782, 0x080c, 0x70ba, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, - 0xb800, 0xd0bc, 0x090c, 0x3116, 0x8108, 0x1f04, 0x0ae1, 0x707b, + 0xb800, 0xd0bc, 0x090c, 0x3136, 0x8108, 0x1f04, 0x0ae1, 0x707b, 0x0000, 0x707c, 0x9084, 0x00ff, 0x707e, 0x70af, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0ba8, 0x70a8, 0x9086, 0xffff, 0x0120, 0x080c, - 0x2de9, 0x0804, 0x0ba8, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0520, + 0x2e09, 0x0804, 0x0ba8, 0x70d8, 0xd0ac, 0x1110, 0xd09c, 0x0520, 0xd084, 0x0510, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, - 0xd08c, 0x01d0, 0x70dc, 0x9086, 0xffff, 0x0190, 0x080c, 0x2f74, - 0x70d8, 0xd094, 0x1904, 0x0ba8, 0x2011, 0x0001, 0x080c, 0xbf61, - 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2fae, 0x0804, 0x0ba8, + 0xd08c, 0x01d0, 0x70dc, 0x9086, 0xffff, 0x0190, 0x080c, 0x2f94, + 0x70d8, 0xd094, 0x1904, 0x0ba8, 0x2011, 0x0001, 0x080c, 0xbf8f, + 0x0110, 0x2011, 0x0003, 0x901e, 0x080c, 0x2fce, 0x0804, 0x0ba8, 0x70e0, 0x9005, 0x1904, 0x0ba8, 0x70a4, 0x9005, 0x1904, 0x0ba8, - 0x70d8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0ba8, 0x080c, 0x6624, - 0x1904, 0x0ba8, 0x080c, 0x6677, 0x1904, 0x0ba8, 0x080c, 0x665e, + 0x70d8, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0ba8, 0x080c, 0x6648, + 0x1904, 0x0ba8, 0x080c, 0x669b, 0x1904, 0x0ba8, 0x080c, 0x6682, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, - 0x626b, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, + 0x628f, 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b4e, 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0ba8, 0x0006, 0x2001, 0x0103, 0x2003, 0x006b, 0x000e, 0x2011, - 0x1983, 0x080c, 0x0faa, 0x2011, 0x199d, 0x080c, 0x0faa, 0x7030, - 0xc08c, 0x7032, 0x7003, 0x0003, 0x70ab, 0xffff, 0x080c, 0x0e61, - 0x9006, 0x080c, 0x23e2, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, - 0x0006, 0x080c, 0x4a77, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x70b9, 0x0150, 0x080c, 0x7096, 0x7828, 0x0118, 0x9084, - 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x080c, 0x98bb, - 0x2001, 0x19b8, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, - 0x080c, 0x931c, 0x2011, 0x0000, 0x080c, 0x9326, 0x080c, 0x98d7, + 0x198b, 0x080c, 0x0fb7, 0x2011, 0x19a5, 0x080c, 0x0fb7, 0x7030, + 0xc08c, 0x7032, 0x7003, 0x0003, 0x70ab, 0xffff, 0x080c, 0x0e6e, + 0x9006, 0x080c, 0x23fe, 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, + 0x0006, 0x080c, 0x4a97, 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, + 0x080c, 0x70dd, 0x0150, 0x080c, 0x70ba, 0x7828, 0x0118, 0x9084, + 0xe1ff, 0x0010, 0x9084, 0xffdf, 0x782a, 0x00fe, 0x080c, 0x98c7, + 0x2001, 0x19c0, 0x2004, 0x9086, 0x0005, 0x1120, 0x2011, 0x0000, + 0x080c, 0x9324, 0x2011, 0x0000, 0x080c, 0x932e, 0x080c, 0x98e3, 0x012e, 0x00be, 0x0005, 0x0016, 0x0026, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x7904, 0x918c, 0xfffd, 0x7906, - 0x2009, 0x00f7, 0x080c, 0x5c53, 0x7940, 0x918c, 0x0010, 0x7942, - 0x7924, 0xd1b4, 0x0120, 0x2011, 0x0040, 0x080c, 0x288c, 0xd19c, - 0x0120, 0x2011, 0x0008, 0x080c, 0x288c, 0x0006, 0x0036, 0x0156, - 0x0000, 0x2001, 0x1977, 0x2004, 0x9005, 0x1518, 0x080c, 0x2820, - 0x1148, 0x2001, 0x0001, 0x080c, 0x2787, 0x2001, 0x0001, 0x080c, - 0x276a, 0x00b8, 0x080c, 0x2828, 0x1138, 0x9006, 0x080c, 0x2787, - 0x9006, 0x080c, 0x276a, 0x0068, 0x080c, 0x2830, 0x1d50, 0x2001, - 0x1968, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x2581, 0x0804, - 0x0ca9, 0x080c, 0x28af, 0x080c, 0x28e2, 0x20a9, 0x003a, 0x1d04, - 0x0bff, 0x080c, 0x821e, 0x1f04, 0x0bff, 0x080c, 0x70a7, 0x0148, - 0x080c, 0x70b9, 0x1118, 0x080c, 0x73a5, 0x0050, 0x080c, 0x709e, - 0x0dd0, 0x080c, 0x73a0, 0x080c, 0x7396, 0x080c, 0x6fc7, 0x0020, - 0x2009, 0x00f8, 0x080c, 0x5c53, 0x7850, 0xc0e5, 0x7852, 0x080c, - 0x7096, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, - 0x2019, 0xea60, 0x0d0c, 0x821e, 0x7820, 0xd09c, 0x15a0, 0x080c, - 0x7096, 0x0904, 0x0c8b, 0x7824, 0xd0ac, 0x1904, 0x0cae, 0x080c, - 0x70b9, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, - 0x2011, 0x1800, 0x080c, 0x288c, 0x080c, 0x2838, 0x7824, 0x9084, + 0x2009, 0x00f7, 0x080c, 0x5c73, 0x7940, 0x918c, 0x0010, 0x7942, + 0x7924, 0xd1b4, 0x0120, 0x2011, 0x0040, 0x080c, 0x28ac, 0xd19c, + 0x0120, 0x2011, 0x0008, 0x080c, 0x28ac, 0x0006, 0x0036, 0x0156, + 0x0000, 0x2001, 0x197f, 0x2004, 0x9005, 0x1518, 0x080c, 0x2840, + 0x1148, 0x2001, 0x0001, 0x080c, 0x27a3, 0x2001, 0x0001, 0x080c, + 0x2786, 0x00b8, 0x080c, 0x2848, 0x1138, 0x9006, 0x080c, 0x27a3, + 0x9006, 0x080c, 0x2786, 0x0068, 0x080c, 0x2850, 0x1d50, 0x2001, + 0x1970, 0x2004, 0xd0fc, 0x0108, 0x0020, 0x080c, 0x259d, 0x0804, + 0x0ca9, 0x080c, 0x28cf, 0x080c, 0x2902, 0x20a9, 0x003a, 0x1d04, + 0x0bff, 0x080c, 0x8252, 0x1f04, 0x0bff, 0x080c, 0x70cb, 0x0148, + 0x080c, 0x70dd, 0x1118, 0x080c, 0x73c8, 0x0050, 0x080c, 0x70c2, + 0x0dd0, 0x080c, 0x73c3, 0x080c, 0x73b9, 0x080c, 0x6feb, 0x0020, + 0x2009, 0x00f8, 0x080c, 0x5c73, 0x7850, 0xc0e5, 0x7852, 0x080c, + 0x70ba, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, + 0x2019, 0xea60, 0x0d0c, 0x8252, 0x7820, 0xd09c, 0x15a0, 0x080c, + 0x70ba, 0x0904, 0x0c8b, 0x7824, 0xd0ac, 0x1904, 0x0cae, 0x080c, + 0x70dd, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, + 0x2011, 0x1800, 0x080c, 0x28ac, 0x080c, 0x2858, 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0cd1, 0x8421, 0x1160, 0x1d04, - 0x0c5b, 0x080c, 0x821e, 0x080c, 0x73a0, 0x080c, 0x7396, 0x7003, + 0x0c5b, 0x080c, 0x8252, 0x080c, 0x73c3, 0x080c, 0x73b9, 0x7003, 0x0001, 0x0804, 0x0cae, 0x8319, 0x1928, 0x2001, 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0cd1, 0x1d04, 0x0c71, 0x080c, - 0x821e, 0x2009, 0x196b, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, - 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x288c, 0x20a9, - 0x0002, 0x080c, 0x2819, 0x7924, 0x080c, 0x2838, 0xd19c, 0x0110, - 0x080c, 0x2758, 0x00f0, 0x080c, 0x70a7, 0x1140, 0x94a2, 0x03e8, - 0x1128, 0x080c, 0x706a, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, - 0x080c, 0x288c, 0x080c, 0x2838, 0x7824, 0x080c, 0x70b0, 0x0110, + 0x8252, 0x2009, 0x1973, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, + 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x28ac, 0x20a9, + 0x0002, 0x080c, 0x2839, 0x7924, 0x080c, 0x2858, 0xd19c, 0x0110, + 0x080c, 0x2774, 0x00f0, 0x080c, 0x70cb, 0x1140, 0x94a2, 0x03e8, + 0x1128, 0x080c, 0x708e, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, + 0x080c, 0x28ac, 0x080c, 0x2858, 0x7824, 0x080c, 0x70d4, 0x0110, 0xd0ac, 0x1160, 0x9084, 0x1800, 0x0904, 0x0c63, 0x7003, 0x0001, - 0x0028, 0x2001, 0x0001, 0x080c, 0x23e2, 0x00a0, 0x7850, 0xc0e4, + 0x0028, 0x2001, 0x0001, 0x080c, 0x23fe, 0x00a0, 0x7850, 0xc0e4, 0x7852, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, - 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x288c, 0x7828, 0x9085, - 0x0028, 0x782a, 0x2001, 0x1977, 0x2003, 0x0000, 0x9006, 0x78f2, + 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x28ac, 0x7828, 0x9085, + 0x0028, 0x782a, 0x2001, 0x197f, 0x2003, 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x821e, 0x015e, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x8252, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x1894, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x32a6, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x197b, 0x2063, 0x0003, 0x6007, 0x0002, 0x600b, 0x001e, - 0x600f, 0x0317, 0x2001, 0x194c, 0x900e, 0x2102, 0x7192, 0x2001, + 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189c, 0x7004, 0x9086, + 0x0001, 0x1110, 0x080c, 0x32c6, 0x00ee, 0x0005, 0x0005, 0x2a70, + 0x2061, 0x1983, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0002, + 0x600f, 0x0317, 0x2001, 0x1954, 0x900e, 0x2102, 0x7192, 0x2001, 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705b, 0xffff, 0x0008, - 0x715a, 0x7063, 0xffff, 0x717a, 0x717e, 0x080c, 0xbcae, 0x70eb, - 0x00c0, 0x2061, 0x193c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, + 0x715a, 0x7063, 0xffff, 0x717a, 0x717e, 0x080c, 0xbcdc, 0x70eb, + 0x00c0, 0x2061, 0x1944, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x1944, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, + 0x07d0, 0x2061, 0x194c, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x1959, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182b, 0x2102, 0x0005, 0x9016, 0x080c, 0x626b, + 0x1961, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, + 0x2020, 0x2001, 0x182b, 0x2102, 0x0005, 0x9016, 0x080c, 0x628f, 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, @@ -226,456 +226,459 @@ unsigned short risc_code01[] = { 0x0d67, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, 0x7886, 0x3900, 0x789a, 0x7833, 0x0012, 0x2091, 0x5000, 0x0156, - 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x1af3, 0x7a08, - 0x226a, 0x2069, 0x1af4, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, - 0x782c, 0x2019, 0x1b01, 0x201a, 0x2019, 0x1b04, 0x9016, 0x7808, - 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x1b1d, + 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, 0x1afb, 0x7a08, + 0x226a, 0x2069, 0x1afc, 0x7a18, 0x226a, 0x8d68, 0x7a1c, 0x226a, + 0x782c, 0x2019, 0x1b09, 0x201a, 0x2019, 0x1b0c, 0x9016, 0x7808, + 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, 0x9386, 0x1b25, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, 0xdead, 0x2019, - 0x1b02, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, - 0x1a49, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, - 0x8318, 0x1f04, 0x0db4, 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, - 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x0180, 0x2001, 0x19f2, 0x2004, 0x9005, 0x0128, - 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, - 0x0002, 0x2003, 0x1001, 0x080c, 0x5397, 0x1170, 0x080c, 0x0efb, - 0x0110, 0x080c, 0x0e4e, 0x080c, 0x5397, 0x1130, 0x2071, 0x1800, - 0x2011, 0x8000, 0x080c, 0x0f0f, 0x0c70, 0x0005, 0x2001, 0x0382, - 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, - 0x080c, 0x98ac, 0x2079, 0x0380, 0x2069, 0x1ad3, 0x7818, 0x6802, - 0x781c, 0x6806, 0x7840, 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, - 0x2019, 0x1ade, 0x9016, 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, - 0x8210, 0x8318, 0x8210, 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, - 0x6a2a, 0x7830, 0x681a, 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, - 0x6826, 0x7803, 0x0000, 0x2069, 0x1a93, 0x901e, 0x20a9, 0x0020, - 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e28, 0x2069, - 0x1ab3, 0x2019, 0x00b0, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, - 0x8d68, 0x8318, 0x1f04, 0x0e35, 0x0005, 0x918c, 0x03ff, 0x2001, - 0x0003, 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, - 0x918d, 0x6400, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, - 0x2011, 0x0080, 0x080c, 0x0eed, 0x20a9, 0x0900, 0x080c, 0x0f23, - 0x2011, 0x0040, 0x080c, 0x0eed, 0x20a9, 0x0900, 0x080c, 0x0f23, - 0x0c78, 0x0026, 0x080c, 0x0efb, 0x1188, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, - 0x2011, 0x1b47, 0x080c, 0x0f0f, 0x002e, 0x0005, 0x2011, 0x010e, - 0x2214, 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, - 0x0010, 0x2011, 0x6840, 0xd0e4, 0x70ef, 0x0000, 0x1128, 0x70ef, - 0x0fa0, 0x080c, 0x0f00, 0x002e, 0x0005, 0x0026, 0x080c, 0x0efb, - 0x0148, 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, - 0x080c, 0x0f00, 0x002e, 0x0005, 0x0026, 0x70ef, 0x0000, 0x080c, - 0x0efb, 0x1130, 0x2011, 0x8040, 0x080c, 0x0f0f, 0x002e, 0x0005, - 0x080c, 0x2830, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, - 0x080c, 0x0f00, 0x002e, 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, - 0x1800, 0xd0b4, 0x70e8, 0x71e4, 0x1118, 0xc0e4, 0xc1f4, 0x0050, - 0x0006, 0x3b00, 0x9084, 0xff3e, 0x20d8, 0x000e, 0x70ef, 0x0000, - 0xc0e5, 0xc1f5, 0x0099, 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0x1800, 0xd0e4, 0x70e8, 0x1110, 0xc0dc, 0x0008, 0xc0dd, - 0x0016, 0x71e4, 0x0019, 0x001e, 0x00ee, 0x0005, 0x70ea, 0x71e6, - 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0eb3, 0x0e8d, 0x0e8d, - 0x0e61, 0x0e9c, 0x0e8d, 0x0e8d, 0x0e9c, 0xc284, 0x0016, 0x3b08, - 0x3a00, 0x9104, 0x918d, 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, - 0x20d0, 0x001e, 0x0005, 0x2001, 0x183a, 0x2004, 0xd0dc, 0x0005, - 0x9e86, 0x1800, 0x190c, 0x0d65, 0x70e8, 0xd0e4, 0x0108, 0xc2e5, - 0x72ea, 0xd0e4, 0x1118, 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, - 0x1800, 0x190c, 0x0d65, 0x70e4, 0xd0f4, 0x0108, 0xc2f5, 0x72e6, - 0xd0f4, 0x1140, 0x9284, 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, - 0x00c1, 0x0861, 0x0005, 0x1d04, 0x0f23, 0x2091, 0x6000, 0x1f04, - 0x0f23, 0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, - 0xffc0, 0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, - 0x000e, 0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, 0x1883, - 0x600b, 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, - 0x2009, 0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, - 0x5555, 0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, - 0x9306, 0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, - 0x0c98, 0x000e, 0x200f, 0x2001, 0x1893, 0x928a, 0x000e, 0x1638, - 0x928a, 0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, - 0x9006, 0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, - 0x6003, 0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, - 0x0001, 0x20e8, 0x21a0, 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, - 0x1da0, 0x002e, 0x009e, 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, - 0x000e, 0x08e8, 0x0016, 0x0026, 0x0096, 0x3348, 0x080c, 0x0f2a, - 0x2100, 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, - 0x3518, 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, - 0x003e, 0x0005, 0x20e9, 0x0001, 0x71b4, 0x81ff, 0x11c0, 0x9006, - 0x2009, 0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, - 0x2009, 0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, - 0x7078, 0x8007, 0x717c, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, - 0x000c, 0x23a0, 0x900e, 0x080c, 0x0d45, 0x2001, 0x0000, 0x810f, - 0x20a9, 0x0002, 0x4001, 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, - 0x0000, 0x0006, 0x080c, 0x1054, 0x009e, 0x0cb0, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x10cd, 0x090c, 0x0d65, 0x00ee, 0x0005, - 0x0086, 0x00e6, 0x0006, 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, - 0x00c9, 0x2071, 0x1800, 0x73bc, 0x702c, 0x9016, 0x9045, 0x0158, - 0x8210, 0x9906, 0x090c, 0x0d65, 0x2300, 0x9202, 0x0120, 0x1a0c, - 0x0d65, 0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, - 0x008e, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1906, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, - 0x9906, 0x090c, 0x0d65, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, - 0x008e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, - 0x70bc, 0x8001, 0x0270, 0x70be, 0x702c, 0x2048, 0x9085, 0x0001, - 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, - 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x70bc, 0x90ca, 0x0040, 0x0268, 0x8001, 0x70be, 0x702c, - 0x2048, 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, - 0x00ee, 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x0016, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, - 0xffc0, 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, - 0x70be, 0x080c, 0x8053, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9026, 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, - 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, - 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x1883, 0x7000, - 0x9005, 0x11a0, 0x2001, 0x049b, 0xa802, 0x2048, 0x2009, 0x26c0, - 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, - 0x0800, 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x1883, - 0x7104, 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, - 0x831b, 0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, - 0xa802, 0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, - 0x2848, 0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, - 0x2071, 0x1800, 0x74ba, 0x74be, 0x0005, 0x00e6, 0x0016, 0x9984, - 0xfc00, 0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, - 0x9982, 0x0440, 0x0278, 0x9982, 0x049b, 0x0288, 0x9982, 0x0800, - 0x1270, 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x1883, 0x7010, - 0x9902, 0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, - 0x0cd8, 0x00e6, 0x2071, 0x19f1, 0x7007, 0x0000, 0x9006, 0x701e, - 0x7022, 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, - 0x2071, 0x0080, 0x9006, 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, - 0x1f04, 0x1107, 0x702b, 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, - 0x7022, 0x1f04, 0x1110, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x19f1, 0x701c, - 0x9088, 0x19fb, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, - 0x9106, 0x090c, 0x0d65, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, - 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00e6, 0x2071, 0x19f1, 0x7004, 0x9005, 0x1128, 0x00f6, - 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, - 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1159, - 0x1157, 0x1157, 0x1157, 0x12d0, 0x12d0, 0x12d0, 0x12d0, 0x080c, - 0x0d65, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, - 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, - 0x19fb, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, - 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, - 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, - 0xa868, 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, - 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, - 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, - 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, - 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, - 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, - 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, - 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, - 0x0005, 0x2009, 0x19f1, 0x2104, 0xc095, 0x200a, 0x080c, 0x1136, - 0x0005, 0x0016, 0x00e6, 0x2071, 0x19f1, 0x00f6, 0x2079, 0x0080, - 0x792c, 0xd1bc, 0x190c, 0x0d5e, 0x782b, 0x0002, 0xd1fc, 0x0120, - 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, - 0x1147, 0x11ef, 0x1223, 0x0d65, 0x0d65, 0x12dc, 0x0d65, 0x918c, - 0x0700, 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, - 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, - 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, - 0x9005, 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x118c, - 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, - 0x0000, 0x080c, 0x1147, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, - 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, - 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11a1, 0x0005, - 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, - 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, - 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, - 0x0000, 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18af, 0x2004, - 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, - 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, - 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x1136, - 0x0005, 0x00de, 0x009e, 0x080c, 0x1136, 0x0005, 0xa8a8, 0xd08c, - 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0d65, 0xa06c, 0x908e, - 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, - 0x080c, 0x6985, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, - 0x1054, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d65, - 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, - 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, - 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x1117, - 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6985, 0x000e, - 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, - 0x9bda, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, - 0x080c, 0x1054, 0x7007, 0x0000, 0x080c, 0x1136, 0x00ae, 0x0005, - 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, - 0xc094, 0x7002, 0x012e, 0x0005, 0x7007, 0x0000, 0x080c, 0x1147, - 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, 0x1a3b, - 0x7003, 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, 0x0007, 0x7803, - 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, - 0x2001, 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, 0x0110, 0x7820, - 0x0cd8, 0x2001, 0x1a3c, 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, - 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, - 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, 0x1a49, 0x781f, 0xff00, - 0x781b, 0xff00, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, - 0x0303, 0x2061, 0x1a49, 0x602f, 0x1ddc, 0x2001, 0x1819, 0x2004, - 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1d04, 0x602b, 0x1a89, 0x6007, - 0x1a69, 0x2061, 0x1a69, 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, - 0x7908, 0x9184, 0x0070, 0x190c, 0x0d5e, 0xd19c, 0x05a0, 0x7820, - 0x908c, 0xf000, 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, - 0x6000, 0x9086, 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, - 0xa867, 0x0103, 0x080c, 0x67a7, 0x00b6, 0x6010, 0x2058, 0xba3c, - 0x8211, 0x0208, 0xba3e, 0xb8c0, 0x9005, 0x190c, 0x6396, 0x00be, - 0x6044, 0xd0fc, 0x190c, 0x98e4, 0x080c, 0x9c02, 0x7808, 0xd09c, - 0x19b0, 0x012e, 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d65, 0x002b, - 0x012e, 0x0005, 0x04b0, 0x012e, 0x0005, 0x1399, 0x13bf, 0x13ef, - 0x13f4, 0x13f8, 0x13fd, 0x1425, 0x1429, 0x1437, 0x143b, 0x1399, - 0x14c7, 0x14cb, 0x152e, 0x1399, 0x1399, 0x1399, 0x1399, 0x1399, - 0x1399, 0x1399, 0x1399, 0x1399, 0x1399, 0x1399, 0x1399, 0x1399, - 0x13ff, 0x1399, 0x13c7, 0x13ec, 0x13b3, 0x1399, 0x13d3, 0x139d, - 0x139b, 0x080c, 0x0d65, 0x080c, 0x0d5e, 0x080c, 0x1535, 0x2009, - 0x1a48, 0x2104, 0x8000, 0x200a, 0x080c, 0x7b01, 0x080c, 0x196c, - 0x0005, 0x6044, 0xd0fc, 0x190c, 0x98e4, 0x2009, 0x0055, 0x080c, - 0x9c76, 0x012e, 0x0005, 0x080c, 0x1535, 0x2060, 0x6044, 0xd0fc, - 0x190c, 0x98e4, 0x2009, 0x0055, 0x080c, 0x9c76, 0x0005, 0x2009, - 0x0048, 0x080c, 0x1535, 0x2060, 0x080c, 0x9c76, 0x0005, 0x2009, - 0x0054, 0x080c, 0x1535, 0x2060, 0x6044, 0xd0fc, 0x190c, 0x98e4, - 0x080c, 0x9c76, 0x0005, 0x080c, 0x1535, 0x2060, 0x0056, 0x0066, - 0x080c, 0x1535, 0x2028, 0x080c, 0x1535, 0x2030, 0x0036, 0x0046, - 0x2021, 0x0000, 0x2418, 0x2009, 0x0056, 0x080c, 0x9c76, 0x004e, - 0x003e, 0x006e, 0x005e, 0x0005, 0x080c, 0x1535, 0x0005, 0x7004, - 0xc085, 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, - 0x080c, 0x1535, 0x080c, 0x15f2, 0x0005, 0x080c, 0x0d65, 0x080c, - 0x1535, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, - 0x2009, 0x0048, 0x080c, 0x9c76, 0x2001, 0x015d, 0x2003, 0x0000, - 0x2009, 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, - 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x153a, - 0x2001, 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, - 0x0005, 0x080c, 0x1535, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, - 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, 0x9c76, 0x0005, 0x080c, - 0x1535, 0x080c, 0x0d65, 0x080c, 0x1535, 0x080c, 0x14b2, 0x7827, - 0x0018, 0x79ac, 0xd1dc, 0x0540, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0138, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0400, 0x7004, 0x9005, 0x1180, 0x78ab, 0x0004, 0x7827, - 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d65, 0x2001, 0x020d, - 0x2003, 0x0050, 0x2003, 0x0020, 0x0490, 0x78ab, 0x0004, 0x7803, - 0x0001, 0x080c, 0x14cb, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, - 0x090c, 0x0d65, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, - 0x01a8, 0x080c, 0x7b01, 0x080c, 0x196c, 0x080c, 0xb842, 0x0158, - 0xa9ac, 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, - 0xa880, 0xc0bd, 0xa882, 0x080c, 0xb440, 0x0005, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xbc43, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xd5e4, 0xd5a4, 0x1118, 0x080c, 0x153a, 0x0005, - 0x080c, 0x7b01, 0x080c, 0x196c, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x15ab, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0d65, - 0xd184, 0x1189, 0xd19c, 0x0158, 0xc19c, 0x7106, 0x2001, 0x020d, - 0x2003, 0x0050, 0x2003, 0x0020, 0x080c, 0x153a, 0x0005, 0x81ff, - 0x190c, 0x0d65, 0x0005, 0xc184, 0xd1b4, 0xc1b4, 0x7106, 0x0016, - 0x00e6, 0x15e0, 0x2071, 0x0200, 0x080c, 0x15e6, 0x6014, 0x9005, - 0x05a8, 0x0096, 0x2048, 0xa864, 0x009e, 0x9084, 0x00ff, 0x908e, - 0x0029, 0x0160, 0x908e, 0x0048, 0x1548, 0x601c, 0xd084, 0x11d8, - 0x00f6, 0x2c78, 0x080c, 0x165c, 0x00fe, 0x00a8, 0x00f6, 0x2c78, - 0x080c, 0x17a4, 0x00fe, 0x2009, 0x01f4, 0x8109, 0x0160, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, - 0x1110, 0x0401, 0x0040, 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, - 0x12f5, 0x7803, 0x0001, 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, - 0x2003, 0x0050, 0x2003, 0x0020, 0x0069, 0x0ca8, 0x0031, 0x2060, - 0x2009, 0x0053, 0x080c, 0x9c76, 0x0005, 0x7808, 0xd09c, 0x0de8, - 0x7820, 0x0005, 0x080c, 0x14b2, 0x00d6, 0x2069, 0x0200, 0x2009, - 0x01f4, 0x8109, 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, - 0x2003, 0x0000, 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, - 0x0180, 0x9182, 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, - 0x810c, 0x810c, 0x810c, 0x080c, 0x159d, 0x6827, 0x0001, 0x8109, - 0x1dd0, 0x04d9, 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, - 0x682c, 0xd0e4, 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, - 0x1130, 0x08c0, 0x080c, 0x7b01, 0x080c, 0x196c, 0x0090, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, - 0x020d, 0x2003, 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, - 0x0001, 0x00de, 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, - 0x0d30, 0x7827, 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, - 0x9085, 0x1800, 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, - 0x1de0, 0x0005, 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, - 0x9086, 0x0041, 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, - 0xd09c, 0x0140, 0x0016, 0x0026, 0x00c6, 0x080c, 0x1335, 0x00ce, - 0x002e, 0x001e, 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, - 0x8080, 0x0059, 0x1118, 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, - 0x3900, 0x8000, 0x2004, 0x080c, 0x0d65, 0x2009, 0xff00, 0x8109, - 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, 0x9085, 0x0001, 0x0005, - 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0c79, 0x1108, 0x0005, - 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d65, 0x7037, 0x0001, - 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, - 0x2060, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0c79, 0x6124, - 0xd1dc, 0x01f8, 0x701c, 0xd08c, 0x0904, 0x1651, 0x7017, 0x0000, - 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x1651, 0x2001, 0x0268, - 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, - 0x1651, 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, 0x7a59, - 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, 0xbc1e, 0xab42, - 0xac3e, 0x2001, 0x1875, 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, - 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, - 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, 0x1d24, 0x1190, 0x080c, - 0x17ff, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, - 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, - 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, - 0x153a, 0x0005, 0x080c, 0x0d65, 0x0016, 0x2009, 0x00a0, 0x8109, - 0xa001, 0xa001, 0xa001, 0x1dd8, 0x001e, 0x2cf0, 0x0126, 0x2091, - 0x2200, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, - 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1d04, 0x2165, - 0x0002, 0x1690, 0x16dd, 0x1690, 0x1690, 0x1690, 0x16bf, 0x1690, - 0x1694, 0x1689, 0x16d4, 0x1690, 0x1690, 0x1690, 0x1799, 0x16a8, - 0x169e, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x16d4, - 0x9085, 0x0001, 0x0804, 0x1790, 0xa87c, 0xd0bc, 0x0dc8, 0xa890, - 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x16e4, 0xa87c, 0xd0bc, - 0x0d78, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1733, - 0xa87c, 0xd0bc, 0x0d28, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, + 0x1b0a, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, 0x0000, 0x2069, + 0x1a51, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, + 0x8318, 0x1f04, 0x0db4, 0x2069, 0x1a71, 0x2019, 0x0050, 0x20a9, + 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dc1, + 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, 0x1800, 0x7803, + 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x0180, + 0x2001, 0x19fa, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, + 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, 0x1001, + 0x080c, 0x53b7, 0x1170, 0x080c, 0x0f08, 0x0110, 0x080c, 0x0e5b, + 0x080c, 0x53b7, 0x1130, 0x2071, 0x1800, 0x2011, 0x8000, 0x080c, + 0x0f1c, 0x0c70, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, 0x080c, 0x98b8, 0x2079, + 0x0380, 0x2069, 0x1adb, 0x7818, 0x6802, 0x781c, 0x6806, 0x7840, + 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, 0x2019, 0x1ae6, 0x9016, + 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, 0x8210, 0x8318, 0x8210, + 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, 0x6a2a, 0x7830, 0x681a, + 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, 0x6826, 0x7803, 0x0000, + 0x2069, 0x1a9b, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, + 0x8d68, 0x8318, 0x1f04, 0x0e35, 0x2069, 0x1abb, 0x2019, 0x00b0, + 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, + 0x0e42, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, + 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d, 0x6400, 0x2001, + 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, + 0x0efa, 0x20a9, 0x0900, 0x080c, 0x0f30, 0x2011, 0x0040, 0x080c, + 0x0efa, 0x20a9, 0x0900, 0x080c, 0x0f30, 0x0c78, 0x0026, 0x080c, + 0x0f08, 0x1188, 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, 0x9296, + 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, 0x2011, 0x1b47, 0x080c, + 0x0f1c, 0x002e, 0x0005, 0x2011, 0x010e, 0x2214, 0x9294, 0x0007, + 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, 0x2011, 0x6840, + 0xd0e4, 0x70ef, 0x0000, 0x1128, 0x70ef, 0x0fa0, 0x080c, 0x0f0d, + 0x002e, 0x0005, 0x0026, 0x080c, 0x0f08, 0x0148, 0xd0a4, 0x1138, + 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, 0x0f0d, 0x002e, + 0x0005, 0x0026, 0x70ef, 0x0000, 0x080c, 0x0f08, 0x1130, 0x2011, + 0x8040, 0x080c, 0x0f1c, 0x002e, 0x0005, 0x080c, 0x2850, 0x1118, + 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, 0x0f0d, 0x002e, + 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, 0x1800, 0xd0b4, 0x70e8, + 0x71e4, 0x1118, 0xc0e4, 0xc1f4, 0x0050, 0x0006, 0x3b00, 0x9084, + 0xff3e, 0x20d8, 0x000e, 0x70ef, 0x0000, 0xc0e5, 0xc1f5, 0x0099, + 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0xd0e4, + 0x70e8, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0016, 0x71e4, 0x0019, + 0x001e, 0x00ee, 0x0005, 0x70ea, 0x71e6, 0x7000, 0x9084, 0x0007, + 0x000b, 0x0005, 0x0ec0, 0x0e9a, 0x0e9a, 0x0e6e, 0x0ea9, 0x0e9a, + 0x0e9a, 0x0ea9, 0xc284, 0x0016, 0x3b08, 0x3a00, 0x9104, 0x918d, + 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, 0x20d0, 0x001e, 0x0005, + 0x2001, 0x183a, 0x2004, 0xd0dc, 0x0005, 0x9e86, 0x1800, 0x190c, + 0x0d65, 0x70e8, 0xd0e4, 0x0108, 0xc2e5, 0x72ea, 0xd0e4, 0x1118, + 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, 0x1800, 0x190c, 0x0d65, + 0x70e4, 0xd0f4, 0x0108, 0xc2f5, 0x72e6, 0xd0f4, 0x1140, 0x9284, + 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, 0x00c1, 0x0861, 0x0005, + 0x1d04, 0x0f30, 0x2091, 0x6000, 0x1f04, 0x0f30, 0x0005, 0x890e, + 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, + 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, + 0x0146, 0x0036, 0x0096, 0x2061, 0x188b, 0x600b, 0x0000, 0x600f, + 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, + 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, + 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, + 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, 0x000e, 0x200f, + 0x2001, 0x189b, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, + 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, + 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, + 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, 0x20e8, 0x21a0, + 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, 0x002e, 0x009e, + 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, 0x08e8, 0x0016, + 0x0026, 0x0096, 0x3348, 0x080c, 0x0f37, 0x2100, 0x9300, 0x2098, + 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, + 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, + 0x0001, 0x71b4, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, + 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, + 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x7078, 0x8007, 0x717c, + 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, + 0x080c, 0x0d45, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, + 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, + 0x1061, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x10da, 0x090c, 0x0d65, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, + 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, + 0x73bc, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, + 0x0d65, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0d65, 0xa000, 0x0c98, + 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, + 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x190e, 0x7010, + 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0d65, + 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, + 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70bc, 0x8001, 0x0270, + 0x70be, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, + 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70bc, 0x90ca, + 0x0040, 0x0268, 0x8001, 0x70be, 0x702c, 0x2048, 0xa800, 0x702e, + 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, + 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, + 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, + 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, + 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8087, + 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, + 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, + 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, + 0x0040, 0x0c90, 0x2071, 0x188b, 0x7000, 0x9005, 0x11a0, 0x2001, + 0x049b, 0xa802, 0x2048, 0x2009, 0x26c0, 0x8940, 0x2800, 0xa802, + 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, + 0x9188, 0x0040, 0x0c90, 0x2071, 0x188b, 0x7104, 0x7200, 0x82ff, + 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, + 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, + 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, + 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74ba, + 0x74be, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, + 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, + 0x9982, 0x049b, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, + 0x0800, 0x0250, 0x2071, 0x188b, 0x7010, 0x9902, 0x1228, 0x9085, + 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, + 0x19f9, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, + 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, + 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x1114, 0x702b, + 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022, 0x1f04, 0x111d, + 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, + 0xa06f, 0x0000, 0x2071, 0x19f9, 0x701c, 0x9088, 0x1a03, 0x280a, + 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, 0x090c, 0x0d65, + 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x00a9, 0x00fe, + 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, + 0x19f9, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, 0x0021, + 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, 0x0000, 0x1110, + 0x7007, 0x0006, 0x7000, 0x0002, 0x1166, 0x1164, 0x1164, 0x1164, + 0x12dd, 0x12dd, 0x12dd, 0x12dd, 0x080c, 0x0d65, 0x701c, 0x7120, + 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, 0xd1fc, 0x1110, + 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x1a03, 0x2004, 0x700a, + 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, 0x0026, 0xa88c, + 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, 0x780e, 0xa878, + 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868, 0x009e, 0xd084, + 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, + 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, + 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, 0x7812, 0x782b, + 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, + 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, 0x2098, 0x20e9, + 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, 0x2011, 0x0040, + 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x22a8, 0x4006, + 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, 0x782b, 0x0001, + 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x2009, 0x19f9, + 0x2104, 0xc095, 0x200a, 0x080c, 0x1143, 0x0005, 0x0016, 0x00e6, + 0x2071, 0x19f9, 0x00f6, 0x2079, 0x0080, 0x792c, 0xd1bc, 0x190c, + 0x0d5e, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, 0x0700, 0x7004, + 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1154, 0x11fc, 0x1230, + 0x0d65, 0x0d65, 0x12e9, 0x0d65, 0x918c, 0x0700, 0x1550, 0x0136, + 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, 0x20e1, 0x0000, + 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, 0x4005, 0x3400, + 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, 0x0578, 0x7800, + 0x7802, 0x7804, 0x7806, 0x080c, 0x1199, 0x0005, 0x7008, 0x0096, + 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x080c, 0x1154, + 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x0ca0, + 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180, 0x7800, 0x7802, + 0x7804, 0x7806, 0x080c, 0x11ae, 0x0005, 0x7008, 0x0096, 0x2048, + 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080, 0x0096, 0x7008, + 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808, 0xa896, 0x780c, + 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, 0x0096, 0x00d6, + 0x7008, 0x2048, 0x2001, 0x18b7, 0x2004, 0x9906, 0x1128, 0xa89c, + 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, 0x0096, 0x00d6, + 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, 0x2940, 0x080f, + 0x008e, 0x00de, 0x009e, 0x080c, 0x1143, 0x0005, 0x00de, 0x009e, + 0x080c, 0x1143, 0x0005, 0xa8a8, 0xd08c, 0x0005, 0x0096, 0xa0a0, + 0x904d, 0x090c, 0x0d65, 0xa06c, 0x908e, 0x0100, 0x0130, 0xa87b, + 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, 0x69a9, 0xa09f, + 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x1061, 0x009e, 0x0005, + 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d65, 0xa06c, 0x908e, 0x0100, + 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, 0xa80c, 0x2050, + 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, 0x8006, 0x8007, + 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xa076, 0xa172, + 0xb000, 0xa07a, 0x2810, 0x080c, 0x1124, 0x00e8, 0xa97c, 0xa894, + 0x0016, 0x0006, 0x080c, 0x69a9, 0x000e, 0x001e, 0xd1fc, 0x1138, + 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0x9be6, 0x00ce, 0x7008, + 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, 0x1061, 0x7007, + 0x0000, 0x080c, 0x1143, 0x00ae, 0x0005, 0x0126, 0x2091, 0x8000, + 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x012e, + 0x0005, 0x7007, 0x0000, 0x080c, 0x1154, 0x0005, 0x0126, 0x2091, + 0x2200, 0x2079, 0x0300, 0x2071, 0x1a43, 0x7003, 0x0000, 0x78bf, + 0x00f6, 0x0041, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, + 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x2001, 0x0165, 0x2003, + 0x4198, 0x7808, 0xd09c, 0x0110, 0x7820, 0x0cd8, 0x2001, 0x1a44, + 0x2003, 0x0000, 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, + 0x0002, 0x7807, 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, + 0x0031, 0x782b, 0x1a51, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, + 0x0200, 0x2004, 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a51, + 0x602f, 0x1ddc, 0x2001, 0x1819, 0x2004, 0x9082, 0x1ddc, 0x6032, + 0x603b, 0x1d1c, 0x602b, 0x1a91, 0x6007, 0x1a71, 0x2061, 0x1a71, + 0x00ce, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, 0x9184, 0x0070, + 0x190c, 0x0d5e, 0xd19c, 0x05a0, 0x7820, 0x908c, 0xf000, 0x0540, + 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, 0x6000, 0x9086, 0x0004, + 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, 0xa867, 0x0103, 0x080c, + 0x67cb, 0x00b6, 0x6010, 0x2058, 0xba3c, 0x8211, 0x0208, 0xba3e, + 0xb8c0, 0x9005, 0x190c, 0x63ba, 0x00be, 0x6044, 0xd0fc, 0x190c, + 0x98f0, 0x080c, 0x9c0e, 0x7808, 0xd09c, 0x19b0, 0x012e, 0x0005, + 0x908a, 0x0024, 0x1a0c, 0x0d65, 0x002b, 0x012e, 0x0005, 0x04b0, + 0x012e, 0x0005, 0x13a6, 0x13cc, 0x13fc, 0x1401, 0x1405, 0x140a, + 0x1432, 0x1436, 0x1444, 0x1448, 0x13a6, 0x14d4, 0x14d8, 0x153b, + 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x13a6, + 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x13a6, 0x140c, 0x13a6, 0x13d4, + 0x13f9, 0x13c0, 0x13a6, 0x13e0, 0x13aa, 0x13a8, 0x080c, 0x0d65, + 0x080c, 0x0d5e, 0x080c, 0x1542, 0x2009, 0x1a50, 0x2104, 0x8000, + 0x200a, 0x080c, 0x7b25, 0x080c, 0x1989, 0x0005, 0x6044, 0xd0fc, + 0x190c, 0x98f0, 0x2009, 0x0055, 0x080c, 0x9c82, 0x012e, 0x0005, + 0x080c, 0x1542, 0x2060, 0x6044, 0xd0fc, 0x190c, 0x98f0, 0x2009, + 0x0055, 0x080c, 0x9c82, 0x0005, 0x2009, 0x0048, 0x080c, 0x1542, + 0x2060, 0x080c, 0x9c82, 0x0005, 0x2009, 0x0054, 0x080c, 0x1542, + 0x2060, 0x6044, 0xd0fc, 0x190c, 0x98f0, 0x080c, 0x9c82, 0x0005, + 0x080c, 0x1542, 0x2060, 0x0056, 0x0066, 0x080c, 0x1542, 0x2028, + 0x080c, 0x1542, 0x2030, 0x0036, 0x0046, 0x2021, 0x0000, 0x2418, + 0x2009, 0x0056, 0x080c, 0x9c82, 0x004e, 0x003e, 0x006e, 0x005e, + 0x0005, 0x080c, 0x1542, 0x0005, 0x7004, 0xc085, 0xc0b5, 0x7006, + 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, 0x1542, 0x080c, + 0x15ff, 0x0005, 0x080c, 0x0d65, 0x080c, 0x1542, 0x2060, 0x6014, + 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, 0x0048, 0x080c, + 0x9c82, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, 0x03e8, 0x8109, + 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, 0x0218, + 0x2004, 0xd0ec, 0x1110, 0x080c, 0x1547, 0x2001, 0x0307, 0x2003, + 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, 0x080c, 0x1542, + 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, + 0x0048, 0x080c, 0x9c82, 0x0005, 0x080c, 0x1542, 0x080c, 0x0d65, + 0x080c, 0x1542, 0x080c, 0x14bf, 0x7827, 0x0018, 0x79ac, 0xd1dc, + 0x0540, 0x7827, 0x0015, 0x7828, 0x782b, 0x0000, 0x9065, 0x0138, + 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0400, 0x7004, + 0x9005, 0x1180, 0x78ab, 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, + 0xd1bc, 0x090c, 0x0d65, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x0490, 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x14d8, + 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, 0x0d65, 0x6014, + 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, 0x080c, 0x7b25, + 0x080c, 0x1989, 0x080c, 0xb870, 0x0158, 0xa9ac, 0xa936, 0xa9b0, + 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, 0xc0bd, 0xa882, + 0x080c, 0xb45e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x6024, 0x190c, 0xbc71, 0x2029, 0x00c8, 0x8529, 0x0128, + 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x7dbc, 0x080c, 0xd61c, + 0xd5a4, 0x1118, 0x080c, 0x1547, 0x0005, 0x080c, 0x7b25, 0x080c, + 0x1989, 0x0005, 0x781f, 0x0300, 0x7803, 0x0001, 0x0005, 0x0016, + 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, 0x7908, 0x918c, 0x0007, + 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, 0x080c, 0x15b8, 0x00fe, + 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, 0xc09d, 0x7006, 0x0005, + 0x7104, 0x9184, 0x0004, 0x190c, 0x0d65, 0xd184, 0x1189, 0xd19c, + 0x0158, 0xc19c, 0x7106, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x080c, 0x1547, 0x0005, 0x81ff, 0x190c, 0x0d65, 0x0005, + 0xc184, 0xd1b4, 0xc1b4, 0x7106, 0x0016, 0x00e6, 0x15e0, 0x2071, + 0x0200, 0x080c, 0x15f3, 0x6014, 0x9005, 0x05a8, 0x0096, 0x2048, + 0xa864, 0x009e, 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, + 0x0048, 0x1548, 0x601c, 0xd084, 0x11d8, 0x00f6, 0x2c78, 0x080c, + 0x1669, 0x00fe, 0x00a8, 0x00f6, 0x2c78, 0x080c, 0x17b1, 0x00fe, + 0x2009, 0x01f4, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, + 0x0dc8, 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x0401, 0x0040, + 0x2001, 0x020d, 0x2003, 0x0020, 0x080c, 0x1302, 0x7803, 0x0001, + 0x00ee, 0x001e, 0x0005, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, + 0x0020, 0x0069, 0x0ca8, 0x0031, 0x2060, 0x2009, 0x0053, 0x080c, + 0x9c82, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, 0x080c, + 0x14bf, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, 0x0510, + 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, 0x79bc, + 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, 0x0841, + 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, 0x810c, + 0x080c, 0x15aa, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, 0x6827, + 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, 0x1500, + 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, 0x080c, + 0x7b25, 0x080c, 0x1989, 0x0090, 0x7827, 0x0015, 0x782b, 0x0000, + 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, 0x0020, + 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, 0x0005, + 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, 0x0015, + 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, 0x6802, + 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, 0x2001, + 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, 0x0005, + 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, 0x0016, + 0x0026, 0x00c6, 0x080c, 0x1342, 0x00ce, 0x002e, 0x001e, 0x000e, + 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059, 0x1118, + 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, + 0x080c, 0x0d65, 0x2009, 0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, + 0x1dd8, 0x0005, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, + 0x781b, 0x8080, 0x0c79, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, + 0x2004, 0x080c, 0x0d65, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, + 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, 0x0005, 0x00e6, + 0x0016, 0x2071, 0x0200, 0x0c79, 0x6124, 0xd1dc, 0x01f8, 0x701c, + 0xd08c, 0x0904, 0x165e, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, + 0xd0bc, 0x0904, 0x165e, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, + 0x6038, 0x00ce, 0x918e, 0x0039, 0x1904, 0x165e, 0x9c06, 0x15f0, + 0x0126, 0x2091, 0x2600, 0x080c, 0x7a7d, 0x012e, 0x7358, 0x745c, + 0x6014, 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, + 0x00be, 0xd0bc, 0x190c, 0xbc4c, 0xab42, 0xac3e, 0x2001, 0x187d, + 0x2004, 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, + 0xffff, 0x080c, 0x1d3c, 0x1190, 0x080c, 0x180c, 0x2a00, 0xa816, + 0x0130, 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, + 0x0020, 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, + 0x7037, 0x0020, 0x001e, 0x00ee, 0x080c, 0x1547, 0x0005, 0x080c, + 0x0d65, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, 0xa001, + 0x1dd8, 0x001e, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, + 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, + 0x9d84, 0x000f, 0x9088, 0x1d1c, 0x2165, 0x0002, 0x169d, 0x16ea, + 0x169d, 0x169d, 0x169d, 0x16cc, 0x169d, 0x16a1, 0x1696, 0x16e1, + 0x169d, 0x169d, 0x169d, 0x17a6, 0x16b5, 0x16ab, 0xa964, 0x918c, + 0x00ff, 0x918e, 0x0048, 0x0904, 0x16e1, 0x9085, 0x0001, 0x0804, + 0x179d, 0xa87c, 0xd0bc, 0x0dc8, 0xa890, 0xa842, 0xa88c, 0xa83e, + 0xa888, 0x0804, 0x16f1, 0xa87c, 0xd0bc, 0x0d78, 0xa890, 0xa842, + 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1740, 0xa87c, 0xd0bc, 0x0d28, + 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, 0x090c, 0x0d65, + 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1d1c, 0x2065, 0xa888, + 0xd19c, 0x1904, 0x1740, 0x0428, 0xa87c, 0xd0ac, 0x0970, 0xa804, 0x9045, 0x090c, 0x0d65, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, - 0x1d04, 0x2065, 0xa888, 0xd19c, 0x1904, 0x1733, 0x0428, 0xa87c, - 0xd0ac, 0x0970, 0xa804, 0x9045, 0x090c, 0x0d65, 0xa164, 0xa91a, - 0x91ec, 0x000f, 0x9d80, 0x1d04, 0x2065, 0x9006, 0xa842, 0xa83e, - 0xd19c, 0x1904, 0x1733, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x1690, - 0x9006, 0xa842, 0xa83e, 0x0804, 0x1733, 0xa87c, 0xd0ac, 0x0904, - 0x1690, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0d65, 0x9082, 0x001b, 0x0002, 0x1707, 0x1707, 0x1709, 0x1707, - 0x1707, 0x1707, 0x170f, 0x1707, 0x1707, 0x1707, 0x1715, 0x1707, - 0x1707, 0x1707, 0x171b, 0x1707, 0x1707, 0x1707, 0x1721, 0x1707, - 0x1707, 0x1707, 0x1727, 0x1707, 0x1707, 0x1707, 0x172d, 0x080c, - 0x0d65, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, 0x1778, 0xa584, - 0xa488, 0xa38c, 0xa290, 0x0804, 0x1778, 0xa594, 0xa498, 0xa39c, - 0xa2a0, 0x0804, 0x1778, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, - 0x1778, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1778, 0xa5c4, - 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1778, 0xa5d4, 0xa4d8, 0xa3dc, - 0xa2e0, 0x0804, 0x1778, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d65, - 0x9082, 0x001b, 0x0002, 0x1756, 0x1754, 0x1754, 0x1754, 0x1754, - 0x1754, 0x175d, 0x1754, 0x1754, 0x1754, 0x1754, 0x1754, 0x1764, - 0x1754, 0x1754, 0x1754, 0x1754, 0x1754, 0x176b, 0x1754, 0x1754, - 0x1754, 0x1754, 0x1754, 0x1772, 0x080c, 0x0d65, 0xa56c, 0xa470, - 0xa774, 0xa678, 0xa37c, 0xa280, 0x00d8, 0xa584, 0xa488, 0xa78c, - 0xa690, 0xa394, 0xa298, 0x00a0, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, - 0xa3ac, 0xa2b0, 0x0068, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, - 0xa2c8, 0x0030, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60, - 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1158, - 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, - 0x00ce, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, 0xa812, - 0x0c78, 0x0804, 0x1690, 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, - 0xa001, 0xa001, 0x1dd8, 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, - 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1cff, - 0xa813, 0x1cff, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, - 0x090c, 0x0d65, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0d65, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, - 0xa836, 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, - 0x1120, 0x8109, 0xa916, 0x0128, 0x0078, 0x918a, 0x0002, 0xa916, - 0x1158, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, - 0x9006, 0x00ce, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0d65, - 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1d04, 0x2015, - 0x82ff, 0x090c, 0x0d65, 0xaa12, 0x2205, 0xa80a, 0x0c10, 0x903e, - 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x18f4, 0x1856, - 0x1856, 0x18f4, 0x18f4, 0x18ee, 0x18f4, 0x1856, 0x18a5, 0x18a5, - 0x18a5, 0x18f4, 0x18f4, 0x18f4, 0x18eb, 0x18a5, 0xc0fc, 0xa882, - 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x18f6, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1842, - 0x1840, 0x1840, 0x1840, 0x1840, 0x1840, 0x1846, 0x1840, 0x1840, - 0x1840, 0x1840, 0x1840, 0x184a, 0x1840, 0x1840, 0x1840, 0x1840, - 0x1840, 0x184e, 0x1840, 0x1840, 0x1840, 0x1840, 0x1840, 0x1852, - 0x080c, 0x0d65, 0xa774, 0xa678, 0x0804, 0x18f6, 0xa78c, 0xa690, - 0x0804, 0x18f6, 0xa7a4, 0xa6a8, 0x0804, 0x18f6, 0xa7bc, 0xa6c0, - 0x0804, 0x18f6, 0xa7d4, 0xa6d8, 0x0804, 0x18f6, 0x2c05, 0x908a, - 0x0036, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1879, 0x1879, - 0x187b, 0x1879, 0x1879, 0x1879, 0x1881, 0x1879, 0x1879, 0x1879, - 0x1887, 0x1879, 0x1879, 0x1879, 0x188d, 0x1879, 0x1879, 0x1879, - 0x1893, 0x1879, 0x1879, 0x1879, 0x1899, 0x1879, 0x1879, 0x1879, - 0x189f, 0x080c, 0x0d65, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, - 0x18f6, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x18f6, 0xa594, - 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x18f6, 0xa5a4, 0xa4a8, 0xa3ac, - 0xa2b0, 0x0804, 0x18f6, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, - 0x18f6, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x18f6, 0xa5d4, - 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x18f6, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x18c8, 0x18c6, 0x18c6, - 0x18c6, 0x18c6, 0x18c6, 0x18cf, 0x18c6, 0x18c6, 0x18c6, 0x18c6, - 0x18c6, 0x18d6, 0x18c6, 0x18c6, 0x18c6, 0x18c6, 0x18c6, 0x18dd, - 0x18c6, 0x18c6, 0x18c6, 0x18c6, 0x18c6, 0x18e4, 0x080c, 0x0d65, - 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0438, 0xa584, - 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1cda, - 0x1904, 0x17ff, 0x900e, 0x0050, 0x080c, 0x0d65, 0xab2e, 0xaa32, - 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, 0x1cda, 0x0005, 0x6014, - 0x2048, 0x6118, 0x810c, 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, - 0x0001, 0x0008, 0xa986, 0x601b, 0x0002, 0xa974, 0xd1dc, 0x1108, - 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, - 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, 0x0804, 0x9c76, - 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, - 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, - 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, - 0x7808, 0xd09c, 0x0120, 0x080c, 0x1335, 0x8631, 0x1db8, 0x00ce, - 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, - 0x1335, 0x00ce, 0x2001, 0x0038, 0x080c, 0x19f9, 0x7930, 0x9186, - 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0d65, 0x2001, 0x001e, - 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1a08, 0x000e, 0x6022, - 0x012e, 0x0005, 0x080c, 0x19f5, 0x7827, 0x0015, 0x7828, 0x9c06, - 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, - 0x0000, 0x78ab, 0x0004, 0x00fe, 0x080c, 0x7096, 0x11b0, 0x2001, - 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, - 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0081, 0x2001, 0x0386, - 0x2003, 0x2020, 0x080c, 0x7137, 0x0005, 0x0479, 0x0039, 0x2001, + 0x1d1c, 0x2065, 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x1740, + 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x169d, 0x9006, 0xa842, 0xa83e, + 0x0804, 0x1740, 0xa87c, 0xd0ac, 0x0904, 0x169d, 0x9006, 0xa842, + 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d65, 0x9082, 0x001b, + 0x0002, 0x1714, 0x1714, 0x1716, 0x1714, 0x1714, 0x1714, 0x171c, + 0x1714, 0x1714, 0x1714, 0x1722, 0x1714, 0x1714, 0x1714, 0x1728, + 0x1714, 0x1714, 0x1714, 0x172e, 0x1714, 0x1714, 0x1714, 0x1734, + 0x1714, 0x1714, 0x1714, 0x173a, 0x080c, 0x0d65, 0xa574, 0xa478, + 0xa37c, 0xa280, 0x0804, 0x1785, 0xa584, 0xa488, 0xa38c, 0xa290, + 0x0804, 0x1785, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1785, + 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1785, 0xa5b4, 0xa4b8, + 0xa3bc, 0xa2c0, 0x0804, 0x1785, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, + 0x0804, 0x1785, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1785, + 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, + 0x1763, 0x1761, 0x1761, 0x1761, 0x1761, 0x1761, 0x176a, 0x1761, + 0x1761, 0x1761, 0x1761, 0x1761, 0x1771, 0x1761, 0x1761, 0x1761, + 0x1761, 0x1761, 0x1778, 0x1761, 0x1761, 0x1761, 0x1761, 0x1761, + 0x177f, 0x080c, 0x0d65, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, + 0xa280, 0x00d8, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, + 0x00a0, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x0068, + 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0030, 0xa5cc, + 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0xab2e, 0xaa32, 0xad1e, + 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60, 0x2c1d, 0xa8ac, 0xaab0, + 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1158, 0x3e60, 0x601c, 0xc085, + 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x012e, 0x0005, + 0x2800, 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c78, 0x0804, 0x169d, + 0x0016, 0x2009, 0x00a0, 0x8109, 0xa001, 0xa001, 0xa001, 0x1dd8, + 0x001e, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x00c6, 0x3e60, 0x6014, + 0x2048, 0x2940, 0xa80e, 0x2061, 0x1d17, 0xa813, 0x1d17, 0x2c05, + 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, 0x0d65, 0x9006, + 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d65, 0xadcc, + 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, 0xaa32, 0xad1e, + 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0xa988, + 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1120, 0x8109, 0xa916, + 0x0128, 0x0078, 0x918a, 0x0002, 0xa916, 0x1158, 0x3e60, 0x601c, + 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x012e, + 0x0005, 0xa804, 0x9045, 0x090c, 0x0d65, 0xa80e, 0xa064, 0xa81a, + 0x9084, 0x000f, 0x9080, 0x1d1c, 0x2015, 0x82ff, 0x090c, 0x0d65, + 0xaa12, 0x2205, 0xa80a, 0x0c10, 0x903e, 0x2730, 0xa880, 0xd0fc, + 0x1190, 0x2d00, 0x0002, 0x1901, 0x1863, 0x1863, 0x1901, 0x1901, + 0x18fb, 0x1901, 0x1863, 0x18b2, 0x18b2, 0x18b2, 0x1901, 0x1901, + 0x1901, 0x18f8, 0x18b2, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, + 0xac20, 0xdd9c, 0x0904, 0x1903, 0x2c05, 0x908a, 0x0034, 0x1a0c, + 0x0d65, 0x9082, 0x001b, 0x0002, 0x184f, 0x184d, 0x184d, 0x184d, + 0x184d, 0x184d, 0x1853, 0x184d, 0x184d, 0x184d, 0x184d, 0x184d, + 0x1857, 0x184d, 0x184d, 0x184d, 0x184d, 0x184d, 0x185b, 0x184d, + 0x184d, 0x184d, 0x184d, 0x184d, 0x185f, 0x080c, 0x0d65, 0xa774, + 0xa678, 0x0804, 0x1903, 0xa78c, 0xa690, 0x0804, 0x1903, 0xa7a4, + 0xa6a8, 0x0804, 0x1903, 0xa7bc, 0xa6c0, 0x0804, 0x1903, 0xa7d4, + 0xa6d8, 0x0804, 0x1903, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0d65, + 0x9082, 0x001b, 0x0002, 0x1886, 0x1886, 0x1888, 0x1886, 0x1886, + 0x1886, 0x188e, 0x1886, 0x1886, 0x1886, 0x1894, 0x1886, 0x1886, + 0x1886, 0x189a, 0x1886, 0x1886, 0x1886, 0x18a0, 0x1886, 0x1886, + 0x1886, 0x18a6, 0x1886, 0x1886, 0x1886, 0x18ac, 0x080c, 0x0d65, + 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, 0x1903, 0xa584, 0xa488, + 0xa38c, 0xa290, 0x0804, 0x1903, 0xa594, 0xa498, 0xa39c, 0xa2a0, + 0x0804, 0x1903, 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1903, + 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, 0x1903, 0xa5c4, 0xa4c8, + 0xa3cc, 0xa2d0, 0x0804, 0x1903, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, + 0x0804, 0x1903, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0d65, 0x9082, + 0x001b, 0x0002, 0x18d5, 0x18d3, 0x18d3, 0x18d3, 0x18d3, 0x18d3, + 0x18dc, 0x18d3, 0x18d3, 0x18d3, 0x18d3, 0x18d3, 0x18e3, 0x18d3, + 0x18d3, 0x18d3, 0x18d3, 0x18d3, 0x18ea, 0x18d3, 0x18d3, 0x18d3, + 0x18d3, 0x18d3, 0x18f1, 0x080c, 0x0d65, 0xa56c, 0xa470, 0xa774, + 0xa678, 0xa37c, 0xa280, 0x0438, 0xa584, 0xa488, 0xa78c, 0xa690, + 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, + 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, + 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x0058, + 0x9d86, 0x000e, 0x1130, 0x080c, 0x1cf2, 0x1904, 0x180c, 0x900e, + 0x0050, 0x080c, 0x0d65, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, + 0xae2a, 0x080c, 0x1cf2, 0x0005, 0x6014, 0x2048, 0x6118, 0x810c, + 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, + 0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, + 0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, + 0x9c82, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, + 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, + 0x601e, 0x2009, 0x0048, 0x0804, 0x9c82, 0x0005, 0x0126, 0x00c6, + 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, + 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, + 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, + 0x080c, 0x1342, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, + 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1342, 0x00ce, 0x2001, + 0x0038, 0x080c, 0x1a11, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, + 0x0042, 0x190c, 0x0d65, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, + 0x1d40, 0x080c, 0x1a20, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, + 0x1a0d, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, + 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, + 0x00fe, 0x080c, 0x70ba, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, + 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, + 0x8211, 0x1de0, 0x0059, 0x0804, 0x715f, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, - 0x0200, 0x080c, 0x2844, 0x2009, 0x003c, 0x080c, 0x2063, 0x2001, + 0x0200, 0x080c, 0x2864, 0x2009, 0x003c, 0x080c, 0x207b, 0x2001, 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, - 0x8053, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, - 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x12f5, + 0x8087, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, + 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1302, 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, - 0x7096, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, + 0x70ba, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, - 0x0005, 0x2c08, 0x621c, 0x080c, 0x15ab, 0x7930, 0x0005, 0x2c08, - 0x621c, 0x080c, 0x15d8, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, + 0x0005, 0x2c08, 0x621c, 0x080c, 0x15b8, 0x7930, 0x0005, 0x2c08, + 0x621c, 0x080c, 0x15e5, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0005, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, - 0x0c41, 0x9186, 0x0040, 0x0904, 0x1a66, 0x2001, 0x001e, 0x0c69, + 0x0c41, 0x9186, 0x0040, 0x0904, 0x1a7e, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, 0x0d65, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0b10, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, - 0x080c, 0x19ff, 0x9186, 0x0040, 0x190c, 0x0d65, 0x00d6, 0x2069, + 0x080c, 0x1a17, 0x9186, 0x0040, 0x190c, 0x0d65, 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, 0x0d65, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, - 0x2091, 0x2400, 0x2079, 0x0380, 0x2001, 0x19b7, 0x2070, 0x012e, + 0x2091, 0x2400, 0x2079, 0x0380, 0x2001, 0x19bf, 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, - 0xa964, 0xa91a, 0x918c, 0x00ff, 0x9184, 0x000f, 0x0002, 0x1a9b, - 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a8f, - 0x1a9d, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x1a9b, 0x9086, - 0x0008, 0x1148, 0xa87c, 0xd0b4, 0x0904, 0x1c0d, 0x2011, 0x1cff, + 0xa964, 0xa91a, 0x918c, 0x00ff, 0x9184, 0x000f, 0x0002, 0x1ab3, + 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1aa7, + 0x1ab5, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x1ab3, 0x9086, + 0x0008, 0x1148, 0xa87c, 0xd0b4, 0x0904, 0x1c25, 0x2011, 0x1d17, 0x2205, 0xab88, 0x0068, 0x080c, 0x0d65, 0xa87c, 0xd0b4, 0x0904, - 0x1c0d, 0x9184, 0x000f, 0x9080, 0x1d04, 0x2015, 0x2205, 0xab88, + 0x1c25, 0x9184, 0x000f, 0x9080, 0x1d1c, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x9006, 0xa842, 0xa83e, 0x012e, 0x0005, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa88c, 0xa990, 0xaaac, 0xabb0, 0xaa36, 0xab3a, 0xa83e, 0xa942, 0xa846, 0xa94a, 0xa964, 0x918c, 0x00ff, 0x9186, 0x001e, - 0x0198, 0x2940, 0xa064, 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1d04, + 0x0198, 0x2940, 0xa064, 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1d1c, 0x2065, 0x2c05, 0x2808, 0x2c10, 0xab88, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x012e, 0x3e60, 0x0005, 0xa804, 0x2040, 0x0c58, 0x2cf0, 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa97c, 0x2950, - 0xd1dc, 0x1904, 0x1bd7, 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, + 0xd1dc, 0x1904, 0x1bef, 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, 0xa916, 0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, - 0x1d04, 0x2145, 0x0002, 0x1b0b, 0x1b19, 0x1b0b, 0x1b0b, 0x1b0b, - 0x1b0d, 0x1b0b, 0x1b0b, 0x1b6e, 0x1b6e, 0x1b0b, 0x1b0b, 0x1b0b, - 0x1b6c, 0x1b0b, 0x1b0b, 0x080c, 0x0d65, 0xa804, 0x2050, 0xb164, - 0xa91a, 0x9184, 0x000f, 0x9080, 0x1d04, 0x2045, 0xd19c, 0x1904, - 0x1b6e, 0x9036, 0x2638, 0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d65, - 0x9082, 0x001b, 0x0002, 0x1b3e, 0x1b3e, 0x1b40, 0x1b3e, 0x1b3e, - 0x1b3e, 0x1b46, 0x1b3e, 0x1b3e, 0x1b3e, 0x1b4c, 0x1b3e, 0x1b3e, - 0x1b3e, 0x1b52, 0x1b3e, 0x1b3e, 0x1b3e, 0x1b58, 0x1b3e, 0x1b3e, - 0x1b3e, 0x1b5e, 0x1b3e, 0x1b3e, 0x1b3e, 0x1b64, 0x080c, 0x0d65, - 0xb574, 0xb478, 0xb37c, 0xb280, 0x0804, 0x1bb3, 0xb584, 0xb488, - 0xb38c, 0xb290, 0x0804, 0x1bb3, 0xb594, 0xb498, 0xb39c, 0xb2a0, - 0x0804, 0x1bb3, 0xb5a4, 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1bb3, - 0xb5b4, 0xb4b8, 0xb3bc, 0xb2c0, 0x0804, 0x1bb3, 0xb5c4, 0xb4c8, - 0xb3cc, 0xb2d0, 0x0804, 0x1bb3, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, - 0x0804, 0x1bb3, 0x0804, 0x1bb3, 0x080c, 0x0d65, 0x2805, 0x908a, - 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1b91, 0x1b8f, - 0x1b8f, 0x1b8f, 0x1b8f, 0x1b8f, 0x1b98, 0x1b8f, 0x1b8f, 0x1b8f, - 0x1b8f, 0x1b8f, 0x1b9f, 0x1b8f, 0x1b8f, 0x1b8f, 0x1b8f, 0x1b8f, - 0x1ba6, 0x1b8f, 0x1b8f, 0x1b8f, 0x1b8f, 0x1b8f, 0x1bad, 0x080c, + 0x1d1c, 0x2145, 0x0002, 0x1b23, 0x1b31, 0x1b23, 0x1b23, 0x1b23, + 0x1b25, 0x1b23, 0x1b23, 0x1b86, 0x1b86, 0x1b23, 0x1b23, 0x1b23, + 0x1b84, 0x1b23, 0x1b23, 0x080c, 0x0d65, 0xa804, 0x2050, 0xb164, + 0xa91a, 0x9184, 0x000f, 0x9080, 0x1d1c, 0x2045, 0xd19c, 0x1904, + 0x1b86, 0x9036, 0x2638, 0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d65, + 0x9082, 0x001b, 0x0002, 0x1b56, 0x1b56, 0x1b58, 0x1b56, 0x1b56, + 0x1b56, 0x1b5e, 0x1b56, 0x1b56, 0x1b56, 0x1b64, 0x1b56, 0x1b56, + 0x1b56, 0x1b6a, 0x1b56, 0x1b56, 0x1b56, 0x1b70, 0x1b56, 0x1b56, + 0x1b56, 0x1b76, 0x1b56, 0x1b56, 0x1b56, 0x1b7c, 0x080c, 0x0d65, + 0xb574, 0xb478, 0xb37c, 0xb280, 0x0804, 0x1bcb, 0xb584, 0xb488, + 0xb38c, 0xb290, 0x0804, 0x1bcb, 0xb594, 0xb498, 0xb39c, 0xb2a0, + 0x0804, 0x1bcb, 0xb5a4, 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1bcb, + 0xb5b4, 0xb4b8, 0xb3bc, 0xb2c0, 0x0804, 0x1bcb, 0xb5c4, 0xb4c8, + 0xb3cc, 0xb2d0, 0x0804, 0x1bcb, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, + 0x0804, 0x1bcb, 0x0804, 0x1bcb, 0x080c, 0x0d65, 0x2805, 0x908a, + 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1ba9, 0x1ba7, + 0x1ba7, 0x1ba7, 0x1ba7, 0x1ba7, 0x1bb0, 0x1ba7, 0x1ba7, 0x1ba7, + 0x1ba7, 0x1ba7, 0x1bb7, 0x1ba7, 0x1ba7, 0x1ba7, 0x1ba7, 0x1ba7, + 0x1bbe, 0x1ba7, 0x1ba7, 0x1ba7, 0x1ba7, 0x1ba7, 0x1bc5, 0x080c, 0x0d65, 0xb56c, 0xb470, 0xb774, 0xb678, 0xb37c, 0xb280, 0x00d8, 0xb584, 0xb488, 0xb78c, 0xb690, 0xb394, 0xb298, 0x00a0, 0xb59c, 0xb4a0, 0xb7a4, 0xb6a8, 0xb3ac, 0xb2b0, 0x0068, 0xb5b4, 0xb4b8, @@ -683,100 +686,100 @@ unsigned short risc_code01[] = { 0xb6d8, 0xb3dc, 0xb2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8109, 0xa916, 0x1118, 0x9006, 0x012e, 0x0005, 0x8840, 0x2805, 0x9005, 0x1168, 0xb004, 0x9005, 0x090c, 0x0d65, - 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, 0x9080, 0x1d04, 0x2045, + 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, 0x9080, 0x1d1c, 0x2045, 0x2805, 0x2810, 0x2a08, 0xa80a, 0xa90e, 0xaa12, 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c, 0x0d65, 0xa93c, 0xaa40, 0xa844, 0x9106, 0x1118, 0xa848, 0x9206, 0x0508, 0x2958, 0xab48, 0xac44, 0x2940, - 0x080c, 0x1d24, 0x1998, 0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, + 0x080c, 0x1d3c, 0x1998, 0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, 0x1140, 0xa810, 0x2005, 0xa80a, 0x2a00, 0xa80e, 0x2009, 0x8015, 0x0070, 0x00c6, 0x3e60, 0x6044, 0xc0a4, 0x9085, 0x8005, 0x6046, - 0x00ce, 0x8319, 0xab16, 0x1904, 0x1bc0, 0x2009, 0x8005, 0x3e60, - 0x6044, 0x9105, 0x6046, 0x0804, 0x1bbd, 0x080c, 0x0d65, 0x00f6, + 0x00ce, 0x8319, 0xab16, 0x1904, 0x1bd8, 0x2009, 0x8005, 0x3e60, + 0x6044, 0x9105, 0x6046, 0x0804, 0x1bd5, 0x080c, 0x0d65, 0x00f6, 0x00e6, 0x0096, 0x00c6, 0x0026, 0x704c, 0x9c06, 0x190c, 0x0d65, 0x2079, 0x0090, 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, - 0x7057, 0x0000, 0x6014, 0x2048, 0x080c, 0xb842, 0x0118, 0xa880, + 0x7057, 0x0000, 0x6014, 0x2048, 0x080c, 0xb870, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, 0x9086, 0x0006, 0x1170, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, 0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, - 0xb440, 0x080c, 0x98bb, 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, - 0x0040, 0x080c, 0x2063, 0x080c, 0x949c, 0x2011, 0x0000, 0x080c, - 0x9326, 0x002e, 0x00ce, 0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, + 0xb45e, 0x080c, 0x98c7, 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, + 0x0040, 0x080c, 0x207b, 0x080c, 0x94a4, 0x2011, 0x0000, 0x080c, + 0x932e, 0x002e, 0x00ce, 0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0090, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d65, 0x7820, 0xd0bc, 0x1dd0, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, 0x2079, 0x0090, 0x782b, 0x0008, 0x7057, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x19b7, 0x7054, 0x9086, 0x0000, 0x0904, 0x1cd5, + 0x00e6, 0x2071, 0x19bf, 0x7054, 0x9086, 0x0000, 0x0904, 0x1ced, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, - 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xd62d, 0x2001, + 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, 0xd665, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0d65, 0x0016, 0x2009, 0x0040, - 0x080c, 0x2063, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, + 0x080c, 0x207b, 0x001e, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, - 0x080c, 0x2063, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x98d7, 0x782c, - 0xd0fc, 0x1de8, 0x080c, 0x98bb, 0x7054, 0x9086, 0x0000, 0x1950, + 0x080c, 0x207b, 0x782c, 0xd0fc, 0x09a8, 0x080c, 0x98e3, 0x782c, + 0xd0fc, 0x1de8, 0x080c, 0x98c7, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, - 0x2063, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, + 0x207b, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x0d65, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, - 0x9080, 0x1d04, 0x2065, 0x8cff, 0x090c, 0x0d65, 0x8a51, 0x0005, + 0x9080, 0x1d1c, 0x2065, 0x8cff, 0x090c, 0x0d65, 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000, 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, - 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x1cf7, 0x1cf3, 0x0000, - 0x0000, 0x1d01, 0x0000, 0x1cf7, 0x1cfe, 0x1cfe, 0x1cfb, 0x0000, - 0x0000, 0x0000, 0x1d01, 0x1cfe, 0x0000, 0x1cf9, 0x1cf9, 0x0000, - 0x0000, 0x1d01, 0x0000, 0x1cf9, 0x1cff, 0x1cff, 0x1cff, 0x0000, - 0x0000, 0x0000, 0x1d01, 0x1cff, 0x00c6, 0x00d6, 0x0086, 0xab42, - 0xac3e, 0xa888, 0x9055, 0x0904, 0x1f03, 0x2940, 0xa064, 0x90ec, - 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x1cff, - 0x00d0, 0x9de0, 0x1d04, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, + 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, 0x1d0f, 0x1d0b, 0x0000, + 0x0000, 0x1d19, 0x0000, 0x1d0f, 0x1d16, 0x1d16, 0x1d13, 0x0000, + 0x0000, 0x0000, 0x1d19, 0x1d16, 0x0000, 0x1d11, 0x1d11, 0x0000, + 0x0000, 0x1d19, 0x0000, 0x1d11, 0x1d17, 0x1d17, 0x1d17, 0x0000, + 0x0000, 0x0000, 0x1d19, 0x1d17, 0x00c6, 0x00d6, 0x0086, 0xab42, + 0xac3e, 0xa888, 0x9055, 0x0904, 0x1f1b, 0x2940, 0xa064, 0x90ec, + 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1118, 0x2061, 0x1d17, + 0x00d0, 0x9de0, 0x1d1c, 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, - 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, 0x1f03, 0xa004, 0x9045, - 0x0904, 0x1f03, 0x08d8, 0x2c05, 0x9005, 0x0904, 0x1deb, 0xdd9c, - 0x1904, 0x1da7, 0x908a, 0x0036, 0x1a0c, 0x0d65, 0x9082, 0x001b, - 0x0002, 0x1d7c, 0x1d7c, 0x1d7e, 0x1d7c, 0x1d7c, 0x1d7c, 0x1d84, - 0x1d7c, 0x1d7c, 0x1d7c, 0x1d8a, 0x1d7c, 0x1d7c, 0x1d7c, 0x1d90, - 0x1d7c, 0x1d7c, 0x1d7c, 0x1d96, 0x1d7c, 0x1d7c, 0x1d7c, 0x1d9c, - 0x1d7c, 0x1d7c, 0x1d7c, 0x1da2, 0x080c, 0x0d65, 0xa07c, 0x9422, - 0xa080, 0x931b, 0x0804, 0x1de1, 0xa08c, 0x9422, 0xa090, 0x931b, - 0x0804, 0x1de1, 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1de1, - 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, 0x1de1, 0xa0bc, 0x9422, - 0xa0c0, 0x931b, 0x0804, 0x1de1, 0xa0cc, 0x9422, 0xa0d0, 0x931b, - 0x0804, 0x1de1, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, - 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1dc9, 0x1dc7, - 0x1dc7, 0x1dc7, 0x1dc7, 0x1dc7, 0x1dce, 0x1dc7, 0x1dc7, 0x1dc7, - 0x1dc7, 0x1dc7, 0x1dd3, 0x1dc7, 0x1dc7, 0x1dc7, 0x1dc7, 0x1dc7, - 0x1dd8, 0x1dc7, 0x1dc7, 0x1dc7, 0x1dc7, 0x1dc7, 0x1ddd, 0x080c, + 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, 0x1f1b, 0xa004, 0x9045, + 0x0904, 0x1f1b, 0x08d8, 0x2c05, 0x9005, 0x0904, 0x1e03, 0xdd9c, + 0x1904, 0x1dbf, 0x908a, 0x0036, 0x1a0c, 0x0d65, 0x9082, 0x001b, + 0x0002, 0x1d94, 0x1d94, 0x1d96, 0x1d94, 0x1d94, 0x1d94, 0x1d9c, + 0x1d94, 0x1d94, 0x1d94, 0x1da2, 0x1d94, 0x1d94, 0x1d94, 0x1da8, + 0x1d94, 0x1d94, 0x1d94, 0x1dae, 0x1d94, 0x1d94, 0x1d94, 0x1db4, + 0x1d94, 0x1d94, 0x1d94, 0x1dba, 0x080c, 0x0d65, 0xa07c, 0x9422, + 0xa080, 0x931b, 0x0804, 0x1df9, 0xa08c, 0x9422, 0xa090, 0x931b, + 0x0804, 0x1df9, 0xa09c, 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1df9, + 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, 0x1df9, 0xa0bc, 0x9422, + 0xa0c0, 0x931b, 0x0804, 0x1df9, 0xa0cc, 0x9422, 0xa0d0, 0x931b, + 0x0804, 0x1df9, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, + 0x0034, 0x1a0c, 0x0d65, 0x9082, 0x001b, 0x0002, 0x1de1, 0x1ddf, + 0x1ddf, 0x1ddf, 0x1ddf, 0x1ddf, 0x1de6, 0x1ddf, 0x1ddf, 0x1ddf, + 0x1ddf, 0x1ddf, 0x1deb, 0x1ddf, 0x1ddf, 0x1ddf, 0x1ddf, 0x1ddf, + 0x1df0, 0x1ddf, 0x1ddf, 0x1ddf, 0x1ddf, 0x1ddf, 0x1df5, 0x080c, 0x0d65, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, - 0x931b, 0x0630, 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x1f03, - 0x8c60, 0x0804, 0x1d53, 0xa004, 0x9045, 0x0904, 0x1f03, 0x0804, - 0x1d2e, 0x8a51, 0x0904, 0x1f03, 0x8c60, 0x2c05, 0x9005, 0x1158, - 0xa004, 0x9045, 0x0904, 0x1f03, 0xa064, 0x90ec, 0x000f, 0x9de0, - 0x1d04, 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x1ef8, + 0x931b, 0x0630, 0x2300, 0x9405, 0x0160, 0x8a51, 0x0904, 0x1f1b, + 0x8c60, 0x0804, 0x1d6b, 0xa004, 0x9045, 0x0904, 0x1f1b, 0x0804, + 0x1d46, 0x8a51, 0x0904, 0x1f1b, 0x8c60, 0x2c05, 0x9005, 0x1158, + 0xa004, 0x9045, 0x0904, 0x1f1b, 0xa064, 0x90ec, 0x000f, 0x9de0, + 0x1d1c, 0x2c05, 0x2060, 0xa880, 0xc0fc, 0xa882, 0x0804, 0x1f10, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, - 0xdd9c, 0x1904, 0x1e95, 0x9082, 0x001b, 0x0002, 0x1e31, 0x1e31, - 0x1e33, 0x1e31, 0x1e31, 0x1e31, 0x1e41, 0x1e31, 0x1e31, 0x1e31, - 0x1e4f, 0x1e31, 0x1e31, 0x1e31, 0x1e5d, 0x1e31, 0x1e31, 0x1e31, - 0x1e6b, 0x1e31, 0x1e31, 0x1e31, 0x1e79, 0x1e31, 0x1e31, 0x1e31, - 0x1e87, 0x080c, 0x0d65, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, + 0xdd9c, 0x1904, 0x1ead, 0x9082, 0x001b, 0x0002, 0x1e49, 0x1e49, + 0x1e4b, 0x1e49, 0x1e49, 0x1e49, 0x1e59, 0x1e49, 0x1e49, 0x1e49, + 0x1e67, 0x1e49, 0x1e49, 0x1e49, 0x1e75, 0x1e49, 0x1e49, 0x1e49, + 0x1e83, 0x1e49, 0x1e49, 0x1e49, 0x1e91, 0x1e49, 0x1e49, 0x1e49, + 0x1e9f, 0x080c, 0x0d65, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, - 0x1ef3, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, - 0x0d65, 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, 0x1ef3, 0xa19c, + 0x1f0b, 0xa18c, 0x2400, 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, + 0x0d65, 0xa084, 0x9420, 0xa088, 0x9319, 0x0804, 0x1f0b, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa094, - 0x9420, 0xa098, 0x9319, 0x0804, 0x1ef3, 0xa1ac, 0x2400, 0x9122, + 0x9420, 0xa098, 0x9319, 0x0804, 0x1f0b, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa0a4, 0x9420, 0xa0a8, - 0x9319, 0x0804, 0x1ef3, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, + 0x9319, 0x0804, 0x1f0b, 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, - 0x1ef3, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, - 0x0d65, 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, 0x1ef3, 0xa1dc, + 0x1f0b, 0xa1cc, 0x2400, 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, + 0x0d65, 0xa0c4, 0x9420, 0xa0c8, 0x9319, 0x0804, 0x1f0b, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa0d4, - 0x9420, 0xa0d8, 0x9319, 0x0804, 0x1ef3, 0x9082, 0x001b, 0x0002, - 0x1eb3, 0x1eb1, 0x1eb1, 0x1eb1, 0x1eb1, 0x1eb1, 0x1ec0, 0x1eb1, - 0x1eb1, 0x1eb1, 0x1eb1, 0x1eb1, 0x1ecd, 0x1eb1, 0x1eb1, 0x1eb1, - 0x1eb1, 0x1eb1, 0x1eda, 0x1eb1, 0x1eb1, 0x1eb1, 0x1eb1, 0x1eb1, - 0x1ee7, 0x080c, 0x0d65, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, + 0x9420, 0xa0d8, 0x9319, 0x0804, 0x1f0b, 0x9082, 0x001b, 0x0002, + 0x1ecb, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ed8, 0x1ec9, + 0x1ec9, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ee5, 0x1ec9, 0x1ec9, 0x1ec9, + 0x1ec9, 0x1ec9, 0x1ef2, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ec9, 0x1ec9, + 0x1eff, 0x080c, 0x0d65, 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0d65, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, @@ -792,28 +795,28 @@ unsigned short risc_code01[] = { 0x1da8, 0x9284, 0x000f, 0x9405, 0x001e, 0x00ce, 0x0005, 0x7803, 0x0003, 0x780f, 0x0000, 0x6004, 0x7812, 0x2c04, 0x7816, 0x9ce0, 0x0002, 0x918a, 0x0002, 0x1db8, 0x0005, 0x2001, 0x0005, 0x2004, - 0xd0bc, 0x190c, 0x0d5e, 0xd094, 0x0110, 0x080c, 0x11d1, 0x0005, + 0xd0bc, 0x190c, 0x0d5e, 0xd094, 0x0110, 0x080c, 0x11de, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, - 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2060, 0x7900, 0xd1dc, 0x1118, - 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x1f7e, 0x1f76, - 0x7a59, 0x1f76, 0x1f78, 0x1f78, 0x1f78, 0x1f78, 0x7a3f, 0x1f76, - 0x1f7a, 0x1f76, 0x1f78, 0x1f76, 0x1f78, 0x1f76, 0x080c, 0x0d65, - 0x0031, 0x0020, 0x080c, 0x7a3f, 0x080c, 0x7a59, 0x0005, 0x0006, - 0x0016, 0x0026, 0x080c, 0xd62d, 0x7930, 0x9184, 0x0003, 0x0510, - 0x080c, 0x98bb, 0x2001, 0x19ca, 0x2004, 0x9005, 0x01a0, 0x2001, - 0x0133, 0x2004, 0x9005, 0x090c, 0x0d65, 0x00c6, 0x2001, 0x19ca, - 0x2064, 0x080c, 0x98d7, 0x080c, 0xb440, 0x2009, 0x0040, 0x080c, - 0x2063, 0x00ce, 0x0408, 0x2009, 0x0040, 0x080c, 0x2063, 0x080c, - 0x98d7, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, - 0x0160, 0x080c, 0x7096, 0x1138, 0x080c, 0x7396, 0x080c, 0x5cd7, - 0x080c, 0x6fc7, 0x0010, 0x080c, 0x5b92, 0x080c, 0x7af7, 0x0041, + 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2078, 0x7900, 0xd1dc, 0x1118, + 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x1f96, 0x1f8e, + 0x7a7d, 0x1f8e, 0x1f90, 0x1f90, 0x1f90, 0x1f90, 0x7a63, 0x1f8e, + 0x1f92, 0x1f8e, 0x1f90, 0x1f8e, 0x1f90, 0x1f8e, 0x080c, 0x0d65, + 0x0031, 0x0020, 0x080c, 0x7a63, 0x080c, 0x7a7d, 0x0005, 0x0006, + 0x0016, 0x0026, 0x080c, 0xd665, 0x7930, 0x9184, 0x0003, 0x0510, + 0x080c, 0x98c7, 0x2001, 0x19d2, 0x2004, 0x9005, 0x01a0, 0x2001, + 0x0133, 0x2004, 0x9005, 0x090c, 0x0d65, 0x00c6, 0x2001, 0x19d2, + 0x2064, 0x080c, 0x98e3, 0x080c, 0xb45e, 0x2009, 0x0040, 0x080c, + 0x207b, 0x00ce, 0x0408, 0x2009, 0x0040, 0x080c, 0x207b, 0x080c, + 0x98e3, 0x00d0, 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, + 0x0160, 0x080c, 0x70ba, 0x1138, 0x080c, 0x73b9, 0x080c, 0x5cf7, + 0x080c, 0x6feb, 0x0010, 0x080c, 0x5bb2, 0x080c, 0x7b1b, 0x0041, 0x0018, 0x9184, 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, - 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a3b, 0x080c, 0x196c, + 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a43, 0x080c, 0x1989, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, - 0x2071, 0x1800, 0x7128, 0x2001, 0x193f, 0x2102, 0x2001, 0x1947, + 0x2071, 0x1800, 0x7128, 0x2001, 0x1947, 0x2102, 0x2001, 0x194f, 0x2102, 0x2001, 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, @@ -834,17 +837,17 @@ unsigned short risc_code01[] = { 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, - 0x283e, 0x080c, 0x2758, 0x2001, 0x196d, 0x2003, 0x0000, 0x2001, - 0x196e, 0x2003, 0x0000, 0x080c, 0x28af, 0x9006, 0x080c, 0x2787, - 0x9006, 0x080c, 0x276a, 0x20a9, 0x0012, 0x1d04, 0x2095, 0x2091, - 0x6000, 0x1f04, 0x2095, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, - 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6224, 0x080c, 0x288c, - 0x080c, 0x2476, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x2486, + 0x285e, 0x080c, 0x2774, 0x2001, 0x1975, 0x2003, 0x0700, 0x2001, + 0x1976, 0x2003, 0x0700, 0x080c, 0x28cf, 0x9006, 0x080c, 0x27a3, + 0x9006, 0x080c, 0x2786, 0x20a9, 0x0012, 0x1d04, 0x20ad, 0x2091, + 0x6000, 0x1f04, 0x20ad, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, + 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, 0x6224, 0x080c, 0x28ac, + 0x080c, 0x2492, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x24a2, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0002, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x149f, 0x00c6, 0x2061, 0x0140, 0x608b, 0x000b, 0x608f, 0x10b8, 0x6093, 0x0000, 0x6097, 0x0198, 0x00ce, 0x6004, 0x9085, 0x8000, 0x6006, 0x60bb, - 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x20d3, 0x60bb, + 0x0000, 0x20a9, 0x0018, 0x60bf, 0x0000, 0x1f04, 0x20eb, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x60bf, 0x0320, 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, 0x602b, 0x402c, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, 0x0080, @@ -852,532 +855,533 @@ unsigned short risc_code01[] = { 0x2003, 0x0000, 0x2001, 0x1833, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x6028, 0x910c, 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x002a, 0x9195, 0x0004, - 0x9284, 0x0007, 0x0002, 0x211e, 0x211b, 0x211b, 0x211b, 0x211d, - 0x211b, 0x211b, 0x211b, 0x080c, 0x0d65, 0x0029, 0x002e, 0x001e, + 0x9284, 0x0007, 0x0002, 0x2136, 0x2133, 0x2133, 0x2133, 0x2135, + 0x2133, 0x2133, 0x2133, 0x080c, 0x0d65, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, - 0xd19c, 0x1904, 0x237d, 0xd1f4, 0x190c, 0x0d5e, 0x080c, 0x7096, - 0x0904, 0x217b, 0x080c, 0xbf61, 0x1120, 0x7000, 0x9086, 0x0003, - 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x70b9, 0x0118, - 0x080c, 0x70a7, 0x1530, 0x2011, 0x0020, 0x080c, 0x288c, 0x6043, - 0x0000, 0x080c, 0xbf61, 0x0168, 0x080c, 0x70b9, 0x1150, 0x2001, - 0x1977, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x6f0c, 0x0804, - 0x2380, 0x70a0, 0x9005, 0x1150, 0x70a3, 0x0001, 0x00d6, 0x2069, - 0x0140, 0x080c, 0x70ed, 0x00de, 0x1904, 0x2380, 0x080c, 0x73a0, - 0x0428, 0x080c, 0x70b9, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, - 0x0468, 0x080c, 0x73a0, 0x080c, 0x7396, 0x080c, 0x5cd7, 0x080c, - 0x6fc7, 0x0804, 0x237d, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, + 0xd19c, 0x1904, 0x2395, 0xd1f4, 0x190c, 0x0d5e, 0x080c, 0x70ba, + 0x0904, 0x2193, 0x080c, 0xbf8f, 0x1120, 0x7000, 0x9086, 0x0003, + 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x70dd, 0x0118, + 0x080c, 0x70cb, 0x1530, 0x2011, 0x0020, 0x080c, 0x28ac, 0x6043, + 0x0000, 0x080c, 0xbf8f, 0x0168, 0x080c, 0x70dd, 0x1150, 0x2001, + 0x197f, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x6f30, 0x0804, + 0x2398, 0x70a0, 0x9005, 0x1150, 0x70a3, 0x0001, 0x00d6, 0x2069, + 0x0140, 0x080c, 0x7111, 0x00de, 0x1904, 0x2398, 0x080c, 0x73c3, + 0x0428, 0x080c, 0x70dd, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, + 0x0468, 0x080c, 0x73c3, 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x080c, + 0x6feb, 0x0804, 0x2395, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7094, 0x9086, - 0x0028, 0x1110, 0x080c, 0x7279, 0x0804, 0x237d, 0x080c, 0x739b, - 0x0048, 0x2001, 0x194d, 0x2003, 0x0002, 0x0020, 0x080c, 0x71d7, - 0x0804, 0x237d, 0x080c, 0x731b, 0x0804, 0x237d, 0xd1ac, 0x0904, - 0x2297, 0x080c, 0x7096, 0x11d0, 0x2011, 0x0020, 0x080c, 0x288c, - 0x0006, 0x0026, 0x0036, 0x080c, 0x70b0, 0x1158, 0x080c, 0x7396, - 0x080c, 0x5cd7, 0x080c, 0x6fc7, 0x003e, 0x002e, 0x000e, 0x00ae, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x706a, 0x0016, 0x0046, + 0x0028, 0x1110, 0x080c, 0x729c, 0x0804, 0x2395, 0x080c, 0x73be, + 0x0048, 0x2001, 0x1955, 0x2003, 0x0002, 0x0020, 0x080c, 0x71fa, + 0x0804, 0x2395, 0x080c, 0x733e, 0x0804, 0x2395, 0xd1ac, 0x0904, + 0x22af, 0x080c, 0x70ba, 0x11d0, 0x2011, 0x0020, 0x080c, 0x28ac, + 0x0006, 0x0026, 0x0036, 0x080c, 0x70d4, 0x1158, 0x080c, 0x73b9, + 0x080c, 0x5cf7, 0x080c, 0x6feb, 0x003e, 0x002e, 0x000e, 0x00ae, + 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x708e, 0x0016, 0x0046, 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74d6, 0x948c, 0xff00, 0x7038, 0xd084, 0x0178, 0x9186, 0xf800, 0x1160, 0x7044, 0xd084, 0x1148, - 0xc085, 0x7046, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x48da, - 0x003e, 0x080c, 0xbf5a, 0x1904, 0x226e, 0x9196, 0xff00, 0x05a8, + 0xc085, 0x7046, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x48fa, + 0x003e, 0x080c, 0xbf88, 0x1904, 0x2286, 0x9196, 0xff00, 0x05a8, 0x705c, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, 0x9116, 0x0568, - 0x7130, 0xd184, 0x1550, 0x080c, 0x317a, 0x0128, 0xc18d, 0x7132, - 0x080c, 0x665e, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, + 0x7130, 0xd184, 0x1550, 0x080c, 0x319a, 0x0128, 0xc18d, 0x7132, + 0x080c, 0x6682, 0x1510, 0x6240, 0x9294, 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, - 0x226e, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, - 0x1904, 0x226e, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, - 0x080c, 0x48da, 0x003e, 0x0804, 0x226e, 0x7038, 0xd08c, 0x1140, - 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x226e, 0xc1ad, 0x2102, - 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x48da, 0x003e, 0x7130, - 0xc185, 0x7132, 0x2011, 0x1854, 0x220c, 0x00f0, 0x0016, 0x2009, - 0x0001, 0x2011, 0x0100, 0x080c, 0x83cd, 0x2019, 0x000e, 0x00c6, - 0x2061, 0x0000, 0x080c, 0xd1fc, 0x00ce, 0x9484, 0x00ff, 0x9080, - 0x317f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, - 0x000e, 0x080c, 0xd284, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, - 0x0002, 0x2019, 0x0004, 0x080c, 0x2fd3, 0x001e, 0x0078, 0x0156, - 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x626b, 0x1110, 0x080c, - 0x5cf1, 0x8108, 0x1f04, 0x2264, 0x00be, 0x015e, 0x00ce, 0x004e, - 0x080c, 0x98bb, 0x080c, 0x9b60, 0x080c, 0x98d7, 0x60e3, 0x0000, + 0x2286, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, + 0x1904, 0x2286, 0xc1ad, 0x2102, 0x0036, 0x73d4, 0x2011, 0x8013, + 0x080c, 0x48fa, 0x003e, 0x0804, 0x2286, 0x7038, 0xd08c, 0x1140, + 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2286, 0xc1ad, 0x2102, + 0x0036, 0x73d4, 0x2011, 0x8013, 0x080c, 0x48fa, 0x003e, 0x7130, + 0xc185, 0x7132, 0x2011, 0x185c, 0x220c, 0x00f0, 0x0016, 0x2009, + 0x0001, 0x2011, 0x0100, 0x080c, 0x8401, 0x2019, 0x000e, 0x00c6, + 0x2061, 0x0000, 0x080c, 0xd234, 0x00ce, 0x9484, 0x00ff, 0x9080, + 0x319f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2120, 0x9006, 0x2009, + 0x000e, 0x080c, 0xd2bc, 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, + 0x0002, 0x2019, 0x0004, 0x080c, 0x2ff3, 0x001e, 0x0078, 0x0156, + 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x628f, 0x1110, 0x080c, + 0x5d11, 0x8108, 0x1f04, 0x227c, 0x00be, 0x015e, 0x00ce, 0x004e, + 0x080c, 0x98c7, 0x080c, 0x9b6c, 0x080c, 0x98e3, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, 0xd19c, 0x11b0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, - 0x1825, 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x288c, 0xd194, - 0x0904, 0x237d, 0x0016, 0x080c, 0x98bb, 0x6220, 0xd2b4, 0x0904, - 0x2325, 0x080c, 0x81ea, 0x080c, 0x8f9c, 0x2011, 0x0004, 0x080c, - 0x288c, 0x00f6, 0x2019, 0x19c3, 0x2304, 0x907d, 0x0904, 0x22f2, + 0x1825, 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x28ac, 0xd194, + 0x0904, 0x2395, 0x0016, 0x080c, 0x98c7, 0x6220, 0xd2b4, 0x0904, + 0x233d, 0x080c, 0x821e, 0x080c, 0x8fd0, 0x2011, 0x0004, 0x080c, + 0x28ac, 0x00f6, 0x2019, 0x19cb, 0x2304, 0x907d, 0x0904, 0x230a, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, - 0x8001, 0x1df0, 0x080c, 0x2862, 0x2001, 0x001e, 0x8001, 0x0240, - 0x20a9, 0x0009, 0x080c, 0x2819, 0x6904, 0xd1dc, 0x1140, 0x0cb0, - 0x2001, 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x080c, - 0x885d, 0x080c, 0x98d7, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, - 0x080c, 0x9bda, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, + 0x8001, 0x1df0, 0x080c, 0x2882, 0x2001, 0x001e, 0x8001, 0x0240, + 0x20a9, 0x0009, 0x080c, 0x2839, 0x6904, 0xd1dc, 0x1140, 0x0cb0, + 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, 0x080c, 0x2872, 0x080c, + 0x8891, 0x080c, 0x98e3, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, + 0x080c, 0x9be6, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2862, 0x00de, 0x00c6, 0x2061, 0x19b7, - 0x6034, 0x080c, 0xbf61, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, - 0x909a, 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, 0x8f74, - 0x0804, 0x237a, 0x2061, 0x0100, 0x62c0, 0x080c, 0x97ec, 0x2019, - 0x19c3, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, 0x0027, - 0x080c, 0x9c76, 0x00ce, 0x0804, 0x237a, 0xd2bc, 0x05e0, 0x080c, - 0x81f7, 0x2011, 0x0004, 0x080c, 0x288c, 0x00d6, 0x2069, 0x0140, - 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2862, 0x00de, 0x00c6, - 0x2061, 0x19b7, 0x6050, 0x080c, 0xbf61, 0x0120, 0x909a, 0x0003, + 0x4000, 0x0110, 0x080c, 0x2882, 0x00de, 0x00c6, 0x2061, 0x19bf, + 0x6034, 0x080c, 0xbf8f, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, + 0x909a, 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, 0x8fa8, + 0x0804, 0x2392, 0x2061, 0x0100, 0x62c0, 0x080c, 0x97f8, 0x2019, + 0x19cb, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, 0x0027, + 0x080c, 0x9c82, 0x00ce, 0x0804, 0x2392, 0xd2bc, 0x05e0, 0x080c, + 0x822b, 0x2011, 0x0004, 0x080c, 0x28ac, 0x00d6, 0x2069, 0x0140, + 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2882, 0x00de, 0x00c6, + 0x2061, 0x19bf, 0x6050, 0x080c, 0xbf8f, 0x0120, 0x909a, 0x0003, 0x1638, 0x0018, 0x909a, 0x00c8, 0x1618, 0x8000, 0x6052, 0x604c, - 0x00ce, 0x9005, 0x0578, 0x2009, 0x07d0, 0x080c, 0x81ef, 0x9080, + 0x00ce, 0x9005, 0x0578, 0x2009, 0x07d0, 0x080c, 0x8223, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, - 0x0012, 0x080c, 0x289b, 0x00f0, 0x2009, 0x1984, 0x2011, 0x0016, - 0x080c, 0x289b, 0x00b8, 0x2011, 0x0004, 0x080c, 0x288c, 0x0090, - 0x0036, 0x2019, 0x0001, 0x080c, 0x9269, 0x003e, 0x2019, 0x19ca, + 0x0012, 0x080c, 0x28bb, 0x00f0, 0x2009, 0x1984, 0x2011, 0x0016, + 0x080c, 0x28bb, 0x00b8, 0x2011, 0x0004, 0x080c, 0x28ac, 0x0090, + 0x0036, 0x2019, 0x0001, 0x080c, 0x929d, 0x003e, 0x2019, 0x19d2, 0x2304, 0x9065, 0x0130, 0x2009, 0x004f, 0x6003, 0x0003, 0x080c, - 0x9c76, 0x00ce, 0x080c, 0x98d7, 0x001e, 0xd19c, 0x0904, 0x23db, - 0x7038, 0xd0ac, 0x1538, 0x0016, 0x0156, 0x2011, 0x0008, 0x080c, - 0x288c, 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367, 0x1f04, 0x23a8, - 0x1d04, 0x2390, 0x080c, 0x821e, 0x6020, 0xd09c, 0x1db8, 0x00f6, - 0x2079, 0x0100, 0x080c, 0x27c9, 0x00fe, 0x1d80, 0x6050, 0xc0e4, - 0x6052, 0x2011, 0x0008, 0x080c, 0x288c, 0x015e, 0x001e, 0x0498, - 0x015e, 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0x98bb, - 0x080c, 0x9b60, 0x080c, 0x98d7, 0x60e3, 0x0000, 0x080c, 0xd60c, - 0x080c, 0xd627, 0x080c, 0x538c, 0xd0fc, 0x1138, 0x080c, 0xbf5a, - 0x1120, 0x9085, 0x0001, 0x080c, 0x70dd, 0x9006, 0x080c, 0x2852, - 0x2009, 0x0002, 0x080c, 0x283e, 0x00e6, 0x2071, 0x1800, 0x7003, - 0x0004, 0x080c, 0x0e9c, 0x00ee, 0x2011, 0x0008, 0x080c, 0x288c, - 0x080c, 0x0bab, 0x001e, 0x918c, 0xffd0, 0x2110, 0x080c, 0x288c, - 0x00ae, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x71cc, 0x70ce, 0x9116, - 0x0904, 0x2435, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x283e, - 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, - 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x48da, 0x0468, - 0x2001, 0x1978, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, - 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, - 0x080c, 0x48da, 0x080c, 0x0e9c, 0x080c, 0x538c, 0xd0fc, 0x11a8, - 0x080c, 0xbf5a, 0x1190, 0x00c6, 0x080c, 0x24d1, 0x080c, 0x98bb, - 0x080c, 0x91c4, 0x080c, 0x98d7, 0x2061, 0x0100, 0x2019, 0x0028, - 0x2009, 0x0002, 0x080c, 0x2fd3, 0x00ce, 0x012e, 0x00fe, 0x00ee, - 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, - 0x2130, 0x9094, 0xff00, 0x11f0, 0x2011, 0x1836, 0x2214, 0xd2ac, - 0x11c8, 0x81ff, 0x01e8, 0x2011, 0x181e, 0x2204, 0x9106, 0x1190, - 0x2011, 0x181f, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, - 0x1148, 0x2011, 0x181f, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, - 0x9206, 0x1120, 0x2500, 0x080c, 0x7d4f, 0x0048, 0x9584, 0x00ff, - 0x9080, 0x317f, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, - 0x9080, 0x317f, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, - 0x0140, 0x2001, 0x1817, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, - 0x6852, 0x6856, 0x1f04, 0x2481, 0x00de, 0x0005, 0x0006, 0x00d6, - 0x0026, 0x2069, 0x0140, 0x2001, 0x1817, 0x2102, 0x8114, 0x8214, - 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, - 0x1128, 0x9184, 0x000f, 0x9080, 0xd63b, 0x2005, 0x6856, 0x8211, - 0x1f04, 0x2496, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, - 0x1800, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, - 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, - 0x6980, 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, - 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, - 0x24c6, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, - 0x0005, 0x080c, 0x5388, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, - 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0xd284, 0x004e, 0x0005, - 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, - 0x253d, 0x080c, 0x27b9, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, - 0x1120, 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, - 0x2011, 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, - 0x2009, 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, - 0x0002, 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, - 0x0078, 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, - 0x9084, 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, - 0x2300, 0x9080, 0x0020, 0x2018, 0x080c, 0x83fb, 0x928c, 0xff00, - 0x0110, 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, - 0x2009, 0x0138, 0x220a, 0x080c, 0x7096, 0x1118, 0x2009, 0x193d, - 0x220a, 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, - 0x200c, 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0d5e, - 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x0171, 0x2004, - 0xd0dc, 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, - 0x004c, 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, - 0x2001, 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, - 0x2001, 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, - 0x0005, 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, - 0x1800, 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1960, - 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d65, 0x0033, 0x00ee, 0x002e, - 0x001e, 0x000e, 0x015e, 0x0005, 0x259b, 0x25b9, 0x25dd, 0x25df, - 0x2608, 0x260a, 0x260c, 0x2001, 0x0001, 0x080c, 0x23e2, 0x080c, - 0x2803, 0x2001, 0x1962, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, - 0x782a, 0x9006, 0x20a9, 0x0009, 0x080c, 0x27d5, 0x2001, 0x1960, - 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x260d, 0x080c, 0x81fc, - 0x0005, 0x2009, 0x1965, 0x200b, 0x0000, 0x2001, 0x196a, 0x2003, - 0x0036, 0x2001, 0x1969, 0x2003, 0x002a, 0x2001, 0x1962, 0x2003, - 0x0001, 0x9006, 0x080c, 0x276a, 0x2001, 0xffff, 0x20a9, 0x0009, - 0x080c, 0x27d5, 0x2001, 0x1960, 0x2003, 0x0006, 0x2009, 0x001e, - 0x2011, 0x260d, 0x080c, 0x81fc, 0x0005, 0x080c, 0x0d65, 0x2001, - 0x196a, 0x2003, 0x0036, 0x2001, 0x1962, 0x2003, 0x0003, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x276a, 0x2001, 0x1966, 0x2003, 0x0000, 0x2001, - 0xffff, 0x20a9, 0x0009, 0x080c, 0x27d5, 0x2001, 0x1960, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x260d, 0x080c, 0x81fc, 0x0005, - 0x080c, 0x0d65, 0x080c, 0x0d65, 0x0005, 0x0006, 0x0016, 0x0026, - 0x00e6, 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x2001, 0x1962, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d65, 0x0043, - 0x012e, 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, - 0x262f, 0x264f, 0x268f, 0x26bf, 0x26e3, 0x26f3, 0x26f5, 0x080c, - 0x27c9, 0x11b0, 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x1968, - 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, 0x0110, 0xc08d, - 0x0008, 0xc085, 0x200a, 0x2001, 0x1960, 0x2003, 0x0001, 0x0030, - 0x080c, 0x2719, 0x2001, 0xffff, 0x080c, 0x25aa, 0x0005, 0x080c, - 0x26f7, 0x05e0, 0x2009, 0x1969, 0x2104, 0x8001, 0x200a, 0x080c, - 0x27c9, 0x1178, 0x7850, 0x9084, 0xefff, 0x7852, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0005, 0x0518, 0x2009, 0x1968, 0x2104, 0xc085, - 0x200a, 0x2009, 0x1965, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, - 0x0118, 0x080c, 0x26ff, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x2787, 0x2001, 0x1962, 0x2003, 0x0002, 0x0028, 0x2001, - 0x1960, 0x2003, 0x0003, 0x0010, 0x080c, 0x25cc, 0x0005, 0x080c, - 0x26f7, 0x0560, 0x2009, 0x1969, 0x2104, 0x8001, 0x200a, 0x080c, - 0x27c9, 0x1168, 0x7850, 0x9084, 0xefff, 0x7852, 0x2001, 0x1960, - 0x2003, 0x0003, 0x2001, 0x1961, 0x2003, 0x0000, 0x00b8, 0x2009, - 0x1969, 0x2104, 0x9005, 0x1118, 0x080c, 0x273c, 0x0010, 0x080c, - 0x270c, 0x080c, 0x26ff, 0x2009, 0x1965, 0x200b, 0x0000, 0x2001, - 0x1962, 0x2003, 0x0001, 0x080c, 0x25cc, 0x0000, 0x0005, 0x04b9, - 0x0508, 0x080c, 0x27c9, 0x11b8, 0x7850, 0x9084, 0xefff, 0x7852, - 0x2009, 0x1966, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, - 0x0078, 0x2001, 0x196b, 0x2003, 0x000a, 0x2009, 0x1968, 0x2104, - 0xc0fd, 0x200a, 0x0038, 0x0419, 0x2001, 0x1962, 0x2003, 0x0004, - 0x080c, 0x25f7, 0x0005, 0x0099, 0x0168, 0x080c, 0x27c9, 0x1138, - 0x7850, 0x9084, 0xefff, 0x7852, 0x080c, 0x25e3, 0x0018, 0x0079, - 0x080c, 0x25f7, 0x0005, 0x080c, 0x0d65, 0x080c, 0x0d65, 0x2009, - 0x196a, 0x2104, 0x8001, 0x200a, 0x090c, 0x2758, 0x0005, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2787, 0x0005, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x276a, - 0x0005, 0x2009, 0x1965, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, - 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x04d9, 0x7a38, - 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x2787, 0x0005, 0x0086, 0x2001, 0x1968, 0x2004, - 0x9084, 0x7fff, 0x090c, 0x0d65, 0x2009, 0x1967, 0x2144, 0x8846, - 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, 0x1120, 0x080c, - 0x0d65, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, 0x008e, 0x0005, - 0x0006, 0x0156, 0x2001, 0x1960, 0x20a9, 0x0009, 0x2003, 0x0000, - 0x8000, 0x1f04, 0x275e, 0x2001, 0x1967, 0x2003, 0x8000, 0x015e, - 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, - 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, 0x2009, 0x196d, - 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0006, - 0x783a, 0x2009, 0x196e, 0x210c, 0x795a, 0x00fe, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfffa, - 0x9085, 0x0004, 0x783a, 0x7850, 0x9084, 0xfff0, 0x7852, 0x00f8, - 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, 0x783a, 0x7850, 0x9084, - 0xfff0, 0x0016, 0x2009, 0x017f, 0x210c, 0x918e, 0x0005, 0x0140, - 0x2009, 0x0003, 0x210c, 0x918c, 0x0600, 0x918e, 0x0400, 0x0118, - 0x9085, 0x000a, 0x0010, 0x9085, 0x0000, 0x001e, 0x7852, 0x00fe, - 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, - 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, - 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, 0x080c, 0x2838, 0xd09c, - 0x1110, 0x1f04, 0x27cc, 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, - 0x2091, 0x8000, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, + 0x9c82, 0x00ce, 0x080c, 0x98e3, 0x001e, 0xd19c, 0x0904, 0x23f7, + 0x7038, 0xd0ac, 0x1558, 0x0016, 0x0156, 0x2011, 0x0008, 0x080c, + 0x28ac, 0x080c, 0x28cf, 0x080c, 0x2902, 0x6050, 0xc0e5, 0x6052, + 0x20a9, 0x0367, 0x1f04, 0x23c4, 0x1d04, 0x23ac, 0x080c, 0x8252, + 0x6020, 0xd09c, 0x1db8, 0x00f6, 0x2079, 0x0100, 0x080c, 0x27e5, + 0x00fe, 0x1d80, 0x6050, 0xc0e4, 0x6052, 0x2011, 0x0008, 0x080c, + 0x28ac, 0x015e, 0x001e, 0x0498, 0x015e, 0x001e, 0x0016, 0x6028, + 0xc09c, 0x602a, 0x080c, 0x98c7, 0x080c, 0x9b6c, 0x080c, 0x98e3, + 0x60e3, 0x0000, 0x080c, 0xd644, 0x080c, 0xd65f, 0x080c, 0x53ac, + 0xd0fc, 0x1138, 0x080c, 0xbf88, 0x1120, 0x9085, 0x0001, 0x080c, + 0x7101, 0x9006, 0x080c, 0x2872, 0x2009, 0x0002, 0x080c, 0x285e, + 0x00e6, 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ea9, 0x00ee, + 0x2011, 0x0008, 0x080c, 0x28ac, 0x080c, 0x0bab, 0x001e, 0x918c, + 0xffd0, 0x2110, 0x080c, 0x28ac, 0x00ae, 0x0005, 0x0006, 0x0016, + 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x1800, 0x71cc, 0x70ce, 0x9116, 0x0904, 0x2451, 0x81ff, 0x01a0, + 0x2009, 0x0000, 0x080c, 0x285e, 0x2011, 0x8011, 0x2019, 0x010e, + 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, + 0x0000, 0x080c, 0x48fa, 0x0468, 0x2001, 0x1980, 0x200c, 0x81ff, + 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, + 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, 0x48fa, 0x080c, 0x0ea9, + 0x080c, 0x53ac, 0xd0fc, 0x11a8, 0x080c, 0xbf88, 0x1190, 0x00c6, + 0x080c, 0x24ed, 0x080c, 0x98c7, 0x080c, 0x91f8, 0x080c, 0x98e3, + 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, 0x080c, 0x2ff3, + 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, + 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x11f0, + 0x2011, 0x1836, 0x2214, 0xd2ac, 0x11c8, 0x81ff, 0x01e8, 0x2011, + 0x181e, 0x2204, 0x9106, 0x1190, 0x2011, 0x181f, 0x2214, 0x9294, + 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, 0x181f, 0x2214, + 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, 0x2500, 0x080c, + 0x7d73, 0x0048, 0x9584, 0x00ff, 0x9080, 0x319f, 0x200d, 0x918c, + 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x319f, 0x200d, 0x918c, + 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, 0x1817, 0x2003, + 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, 0x1f04, 0x249d, + 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, + 0x1817, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, + 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, 0x000f, 0x9080, + 0xd673, 0x2005, 0x6856, 0x8211, 0x1f04, 0x24b2, 0x002e, 0x00de, + 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, 0x0110, 0xc09d, + 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, + 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, 0x0180, 0x9112, + 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, + 0x2001, 0x0404, 0x680e, 0x1f04, 0x24e2, 0x680f, 0x0000, 0x000e, + 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, 0x53a8, 0xd0c4, + 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, 0x2009, 0x002e, + 0x080c, 0xd2bc, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, + 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2559, 0x080c, 0x27d5, 0x0660, + 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, 0x4000, 0x900e, + 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, 0x900e, 0x0420, + 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, 0x00e8, 0x908e, + 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, 0x908e, 0x0200, + 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, 0x0100, 0x1548, + 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, 0x908e, 0x0300, + 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, 0x0020, 0x2018, + 0x080c, 0x842f, 0x928c, 0xff00, 0x0110, 0x2011, 0x00ff, 0x2200, + 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, 0x220a, 0x080c, + 0x70ba, 0x1118, 0x2009, 0x1945, 0x220a, 0x002e, 0x001e, 0x00fe, + 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, + 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0x9184, + 0x0003, 0x0110, 0x080c, 0x0d5e, 0x002e, 0x001e, 0x000e, 0x012e, + 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, 0x2001, 0x0170, + 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, 0x200c, 0x918c, + 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, 0x2004, 0x8007, + 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, 0x2004, 0x8007, + 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, 0x000c, 0x0018, + 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, 0x0006, 0x0016, + 0x0026, 0x00e6, 0x2001, 0x1968, 0x2004, 0x908a, 0x0007, 0x1a0c, + 0x0d65, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, 0x015e, 0x0005, + 0x25b7, 0x25d5, 0x25f9, 0x25fb, 0x2624, 0x2626, 0x2628, 0x2001, + 0x0001, 0x080c, 0x23fe, 0x080c, 0x2823, 0x2001, 0x196a, 0x2003, + 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, 0x20a9, 0x0009, + 0x080c, 0x27f1, 0x2001, 0x1968, 0x2003, 0x0006, 0x2009, 0x001e, + 0x2011, 0x2629, 0x080c, 0x8230, 0x0005, 0x2009, 0x196d, 0x200b, + 0x0000, 0x2001, 0x1972, 0x2003, 0x0036, 0x2001, 0x1971, 0x2003, + 0x002a, 0x2001, 0x196a, 0x2003, 0x0001, 0x9006, 0x080c, 0x2786, + 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x27f1, 0x2001, 0x1968, + 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2629, 0x080c, 0x8230, + 0x0005, 0x080c, 0x0d65, 0x2001, 0x1972, 0x2003, 0x0036, 0x2001, + 0x196a, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, + 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2786, 0x2001, + 0x196e, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, + 0x27f1, 0x2001, 0x1968, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, + 0x2629, 0x080c, 0x8230, 0x0005, 0x080c, 0x0d65, 0x080c, 0x0d65, + 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0156, 0x0126, + 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x196a, 0x2004, 0x908a, + 0x0007, 0x1a0c, 0x0d65, 0x0043, 0x012e, 0x015e, 0x00fe, 0x00ee, + 0x002e, 0x001e, 0x000e, 0x0005, 0x264b, 0x266b, 0x26ab, 0x26db, + 0x26ff, 0x270f, 0x2711, 0x080c, 0x27e5, 0x11b0, 0x7850, 0x9084, + 0xefff, 0x7852, 0x2009, 0x1970, 0x2104, 0x7a38, 0x9294, 0x0005, + 0x9296, 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, + 0x1968, 0x2003, 0x0001, 0x0030, 0x080c, 0x2735, 0x2001, 0xffff, + 0x080c, 0x25c6, 0x0005, 0x080c, 0x2713, 0x05e0, 0x2009, 0x1971, + 0x2104, 0x8001, 0x200a, 0x080c, 0x27e5, 0x1178, 0x7850, 0x9084, + 0xefff, 0x7852, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0518, + 0x2009, 0x1970, 0x2104, 0xc085, 0x200a, 0x2009, 0x196d, 0x2104, + 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, 0x271b, 0x00c0, + 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, 0x0004, 0x0110, + 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x27a3, 0x2001, 0x196a, + 0x2003, 0x0002, 0x0028, 0x2001, 0x1968, 0x2003, 0x0003, 0x0010, + 0x080c, 0x25e8, 0x0005, 0x080c, 0x2713, 0x0560, 0x2009, 0x1971, + 0x2104, 0x8001, 0x200a, 0x080c, 0x27e5, 0x1168, 0x7850, 0x9084, + 0xefff, 0x7852, 0x2001, 0x1968, 0x2003, 0x0003, 0x2001, 0x1969, + 0x2003, 0x0000, 0x00b8, 0x2009, 0x1971, 0x2104, 0x9005, 0x1118, + 0x080c, 0x2758, 0x0010, 0x080c, 0x2728, 0x080c, 0x271b, 0x2009, + 0x196d, 0x200b, 0x0000, 0x2001, 0x196a, 0x2003, 0x0001, 0x080c, + 0x25e8, 0x0000, 0x0005, 0x04b9, 0x0508, 0x080c, 0x27e5, 0x11b8, + 0x7850, 0x9084, 0xefff, 0x7852, 0x2009, 0x196e, 0x2104, 0x8000, + 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, 0x1973, 0x2003, + 0x000a, 0x2009, 0x1970, 0x2104, 0xc0fd, 0x200a, 0x0038, 0x0419, + 0x2001, 0x196a, 0x2003, 0x0004, 0x080c, 0x2613, 0x0005, 0x0099, + 0x0168, 0x080c, 0x27e5, 0x1138, 0x7850, 0x9084, 0xefff, 0x7852, + 0x080c, 0x25ff, 0x0018, 0x0079, 0x080c, 0x2613, 0x0005, 0x080c, + 0x0d65, 0x080c, 0x0d65, 0x2009, 0x1972, 0x2104, 0x8001, 0x200a, + 0x090c, 0x2774, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, + 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x27a3, 0x0005, + 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, + 0x2001, 0x0001, 0x080c, 0x2786, 0x0005, 0x2009, 0x196d, 0x2104, + 0x8000, 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, + 0x7a38, 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, + 0x2001, 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, + 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x27a3, 0x0005, + 0x0086, 0x2001, 0x1970, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d65, + 0x2009, 0x196f, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, + 0x1120, 0xd084, 0x1120, 0x080c, 0x0d65, 0x9006, 0x0010, 0x2001, + 0x0001, 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1968, + 0x20a9, 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x277a, 0x2001, + 0x196f, 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, + 0x0004, 0x783a, 0x2009, 0x1975, 0x210c, 0x795a, 0x0050, 0x7838, + 0x9084, 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x1976, 0x210c, + 0x795a, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, + 0x0158, 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x7850, + 0x9084, 0xfff0, 0x7852, 0x00f8, 0x7838, 0x9084, 0xfffb, 0x9085, + 0x0005, 0x783a, 0x7850, 0x9084, 0xfff0, 0x0016, 0x2009, 0x017f, + 0x210c, 0x918e, 0x0005, 0x0140, 0x2009, 0x0003, 0x210c, 0x918c, + 0x0600, 0x918e, 0x0400, 0x0118, 0x9085, 0x000a, 0x0010, 0x9085, + 0x0000, 0x001e, 0x7852, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, + 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, + 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, + 0x7820, 0x080c, 0x2858, 0xd09c, 0x1110, 0x1f04, 0x27e8, 0x015e, + 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x080c, 0x28cf, + 0x080c, 0x2902, 0x000e, 0x2008, 0x9186, 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, 0x9186, 0x0003, - 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x27f5, 0x080c, - 0x821e, 0x1f04, 0x27f5, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, - 0x001e, 0x012e, 0x0005, 0x080c, 0x28e2, 0x0005, 0x0006, 0x0156, + 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, 0x2815, 0x080c, + 0x8252, 0x1f04, 0x2815, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, + 0x001e, 0x012e, 0x0005, 0x080c, 0x2902, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, - 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2810, 0x00fe, 0x015e, 0x000e, - 0x0005, 0x1d04, 0x2819, 0x080c, 0x821e, 0x1f04, 0x2819, 0x0005, - 0x0006, 0x2001, 0x196c, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, - 0x0006, 0x2001, 0x196c, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, - 0x0006, 0x2001, 0x196c, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, + 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2830, 0x00fe, 0x015e, 0x000e, + 0x0005, 0x1d04, 0x2839, 0x080c, 0x8252, 0x1f04, 0x2839, 0x0005, + 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, + 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, + 0x0006, 0x2001, 0x1974, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, - 0x1978, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, + 0x1980, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, - 0x200a, 0x0005, 0x0016, 0x0026, 0x080c, 0x70b0, 0x0108, 0xc0bc, + 0x200a, 0x0005, 0x0016, 0x0026, 0x080c, 0x70d4, 0x0108, 0xc0bc, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, - 0x2104, 0x1128, 0x080c, 0x70b0, 0x0110, 0xc0bc, 0x0008, 0xc0bd, + 0x2104, 0x1128, 0x080c, 0x70d4, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, 0x001e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0101, 0x7844, 0xd084, 0x1de8, 0x2001, 0x0109, 0x2202, 0x7843, 0x0100, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0202, 0x7844, 0xd08c, 0x1de8, 0x2079, 0x0100, 0x7814, 0x9104, 0x9205, 0x7a16, 0x2079, 0x0380, 0x7843, 0x0200, 0x00fe, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, 0x9084, 0xfbff, - 0x9085, 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2819, 0x6050, + 0x9085, 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2839, 0x6050, 0x9085, 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, - 0x2819, 0x6054, 0xd0bc, 0x090c, 0x0d65, 0x20a9, 0x0005, 0x080c, - 0x2819, 0x6054, 0xd0ac, 0x090c, 0x0d65, 0x2009, 0x197f, 0x9084, + 0x2839, 0x6054, 0xd0bc, 0x090c, 0x0d65, 0x20a9, 0x0005, 0x080c, + 0x2839, 0x6054, 0xd0ac, 0x090c, 0x0d65, 0x2009, 0x1987, 0x9084, 0x7e00, 0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, 0x6050, 0xc0cd, - 0x6052, 0x00ce, 0x000e, 0x0005, 0x2de8, 0x2de8, 0x29ec, 0x29ec, - 0x29f8, 0x29f8, 0x2a04, 0x2a04, 0x2a12, 0x2a12, 0x2a1e, 0x2a1e, - 0x2a2c, 0x2a2c, 0x2a3a, 0x2a3a, 0x2a4c, 0x2a4c, 0x2a58, 0x2a58, - 0x2a66, 0x2a66, 0x2a84, 0x2a84, 0x2aa4, 0x2aa4, 0x2a74, 0x2a74, - 0x2a94, 0x2a94, 0x2ab2, 0x2ab2, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2ac4, 0x2ac4, 0x2ad0, 0x2ad0, - 0x2ade, 0x2ade, 0x2aec, 0x2aec, 0x2afc, 0x2afc, 0x2b0a, 0x2b0a, - 0x2b1a, 0x2b1a, 0x2b2a, 0x2b2a, 0x2b3c, 0x2b3c, 0x2b4a, 0x2b4a, - 0x2b5a, 0x2b5a, 0x2b7c, 0x2b7c, 0x2ba0, 0x2ba0, 0x2b6a, 0x2b6a, - 0x2b8e, 0x2b8e, 0x2bb0, 0x2bb0, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2bc4, 0x2bc4, 0x2bd0, 0x2bd0, - 0x2bde, 0x2bde, 0x2bec, 0x2bec, 0x2bfc, 0x2bfc, 0x2c0a, 0x2c0a, - 0x2c1a, 0x2c1a, 0x2c2a, 0x2c2a, 0x2c3c, 0x2c3c, 0x2c4a, 0x2c4a, - 0x2c5a, 0x2c5a, 0x2c6a, 0x2c6a, 0x2c7c, 0x2c7c, 0x2c8c, 0x2c8c, - 0x2c9e, 0x2c9e, 0x2cb0, 0x2cb0, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2cc4, 0x2cc4, 0x2cd2, 0x2cd2, - 0x2ce2, 0x2ce2, 0x2cf2, 0x2cf2, 0x2d04, 0x2d04, 0x2d14, 0x2d14, - 0x2d26, 0x2d26, 0x2d38, 0x2d38, 0x2d4c, 0x2d4c, 0x2d5c, 0x2d5c, - 0x2d6e, 0x2d6e, 0x2d80, 0x2d80, 0x2d94, 0x2d94, 0x2da5, 0x2da5, - 0x2db8, 0x2db8, 0x2dcb, 0x2dcb, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, - 0x2a4a, 0x2a4a, 0x2a4a, 0x2a4a, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ff, 0x0804, 0x2de0, + 0x6052, 0x00ce, 0x000e, 0x0005, 0x2e08, 0x2e08, 0x2a0c, 0x2a0c, + 0x2a18, 0x2a18, 0x2a24, 0x2a24, 0x2a32, 0x2a32, 0x2a3e, 0x2a3e, + 0x2a4c, 0x2a4c, 0x2a5a, 0x2a5a, 0x2a6c, 0x2a6c, 0x2a78, 0x2a78, + 0x2a86, 0x2a86, 0x2aa4, 0x2aa4, 0x2ac4, 0x2ac4, 0x2a94, 0x2a94, + 0x2ab4, 0x2ab4, 0x2ad2, 0x2ad2, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2ae4, 0x2ae4, 0x2af0, 0x2af0, + 0x2afe, 0x2afe, 0x2b0c, 0x2b0c, 0x2b1c, 0x2b1c, 0x2b2a, 0x2b2a, + 0x2b3a, 0x2b3a, 0x2b4a, 0x2b4a, 0x2b5c, 0x2b5c, 0x2b6a, 0x2b6a, + 0x2b7a, 0x2b7a, 0x2b9c, 0x2b9c, 0x2bc0, 0x2bc0, 0x2b8a, 0x2b8a, + 0x2bae, 0x2bae, 0x2bd0, 0x2bd0, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2be4, 0x2be4, 0x2bf0, 0x2bf0, + 0x2bfe, 0x2bfe, 0x2c0c, 0x2c0c, 0x2c1c, 0x2c1c, 0x2c2a, 0x2c2a, + 0x2c3a, 0x2c3a, 0x2c4a, 0x2c4a, 0x2c5c, 0x2c5c, 0x2c6a, 0x2c6a, + 0x2c7a, 0x2c7a, 0x2c8a, 0x2c8a, 0x2c9c, 0x2c9c, 0x2cac, 0x2cac, + 0x2cbe, 0x2cbe, 0x2cd0, 0x2cd0, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2ce4, 0x2ce4, 0x2cf2, 0x2cf2, + 0x2d02, 0x2d02, 0x2d12, 0x2d12, 0x2d24, 0x2d24, 0x2d34, 0x2d34, + 0x2d46, 0x2d46, 0x2d58, 0x2d58, 0x2d6c, 0x2d6c, 0x2d7c, 0x2d7c, + 0x2d8e, 0x2d8e, 0x2da0, 0x2da0, 0x2db4, 0x2db4, 0x2dc5, 0x2dc5, + 0x2dd8, 0x2dd8, 0x2deb, 0x2deb, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, + 0x2a6a, 0x2a6a, 0x2a6a, 0x2a6a, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x1f2d, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x20ff, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ff, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x20ff, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1335, 0x0804, 0x2de0, + 0x080c, 0x1f45, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x2117, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2117, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x2117, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ff, 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, - 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x20ff, - 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1335, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x0804, 0x2de0, + 0x080c, 0x2117, 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, + 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2117, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x2117, + 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1342, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x2117, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x20ff, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, - 0x080c, 0x1f2d, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, - 0x080c, 0x20ff, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x20ff, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x20ff, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, - 0x080c, 0x20ff, 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, - 0x080c, 0x1f2d, 0x080c, 0x1335, 0x080c, 0x1f57, 0x0804, 0x2de0, + 0x080c, 0x255c, 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, + 0x080c, 0x1f45, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, + 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x2117, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x2117, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x2117, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x2117, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, + 0x080c, 0x2117, 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, + 0x080c, 0x1f45, 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x1335, 0x080c, 0x1f57, 0x0804, 0x2de0, + 0x080c, 0x255c, 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x9921, 0x0804, 0x2de0, + 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x2117, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x992d, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x9921, 0x080c, 0x20ff, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, - 0x080c, 0x9921, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x9921, - 0x080c, 0x20ff, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x20ff, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x1f57, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x1335, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x080c, 0x1335, 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f2d, - 0x080c, 0x9921, 0x080c, 0x1335, 0x080c, 0x1f57, 0x0804, 0x2de0, + 0x080c, 0x992d, 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, + 0x080c, 0x992d, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x992d, + 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x2117, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x1f6f, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x2117, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x2117, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x1342, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x2117, + 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x992d, 0x080c, 0x2117, + 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x1f45, + 0x080c, 0x992d, 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x20ff, 0x080c, 0x1335, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x9921, - 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x9921, - 0x080c, 0x20ff, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x080c, 0x20ff, 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, - 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x1f57, 0x0804, 0x2de0, + 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x2117, 0x080c, 0x1342, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, 0x080c, 0x2117, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x992d, + 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, + 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x992d, + 0x080c, 0x2117, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x080c, 0x2117, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, + 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x080c, 0x1f57, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x080c, 0x20ff, 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, - 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x1335, 0x0804, 0x2de0, + 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x2117, + 0x080c, 0x1f6f, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x080c, 0x2117, 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, + 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, + 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x9921, 0x080c, 0x20ff, - 0x080c, 0x1335, 0x0804, 0x2de0, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x9921, - 0x080c, 0x1335, 0x080c, 0x1f57, 0x04d8, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, - 0x9921, 0x080c, 0x20ff, 0x080c, 0x1335, 0x080c, 0x1f57, 0x0440, + 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x992d, 0x080c, 0x2117, + 0x080c, 0x1342, 0x0804, 0x2e00, 0x0106, 0x0006, 0x0126, 0x01c6, + 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x992d, + 0x080c, 0x1342, 0x080c, 0x1f6f, 0x04d8, 0x0106, 0x0006, 0x0126, + 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, + 0x992d, 0x080c, 0x2117, 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0440, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, 0x1335, 0x080c, 0x9921, - 0x080c, 0x1f57, 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2540, 0x080c, 0x1f2d, 0x080c, - 0x9921, 0x080c, 0x20ff, 0x080c, 0x1335, 0x080c, 0x1f57, 0x0000, + 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, 0x1342, 0x080c, 0x992d, + 0x080c, 0x1f6f, 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, + 0x0136, 0x0146, 0x0156, 0x080c, 0x255c, 0x080c, 0x1f45, 0x080c, + 0x992d, 0x080c, 0x2117, 0x080c, 0x1342, 0x080c, 0x1f6f, 0x0000, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, - 0x000d, 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6624, - 0x1904, 0x2eef, 0x72d8, 0x2001, 0x194c, 0x2004, 0x9005, 0x1110, - 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2eef, 0x080c, - 0x2ef4, 0x0804, 0x2eef, 0xd2cc, 0x1904, 0x2eef, 0x080c, 0x7096, - 0x1120, 0x70ab, 0xffff, 0x0804, 0x2eef, 0xd294, 0x0120, 0x70ab, - 0xffff, 0x0804, 0x2eef, 0x080c, 0x3175, 0x0160, 0x080c, 0xbf61, - 0x0128, 0x2001, 0x1817, 0x203c, 0x0804, 0x2e81, 0x70ab, 0xffff, - 0x0804, 0x2eef, 0x2001, 0x1817, 0x203c, 0x7290, 0xd284, 0x0904, - 0x2e81, 0xd28c, 0x1904, 0x2e81, 0x0036, 0x73a8, 0x938e, 0xffff, + 0x000d, 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6648, + 0x1904, 0x2f0f, 0x72d8, 0x2001, 0x1954, 0x2004, 0x9005, 0x1110, + 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x2f0f, 0x080c, + 0x2f14, 0x0804, 0x2f0f, 0xd2cc, 0x1904, 0x2f0f, 0x080c, 0x70ba, + 0x1120, 0x70ab, 0xffff, 0x0804, 0x2f0f, 0xd294, 0x0120, 0x70ab, + 0xffff, 0x0804, 0x2f0f, 0x080c, 0x3195, 0x0160, 0x080c, 0xbf8f, + 0x0128, 0x2001, 0x1817, 0x203c, 0x0804, 0x2ea1, 0x70ab, 0xffff, + 0x0804, 0x2f0f, 0x2001, 0x1817, 0x203c, 0x7290, 0xd284, 0x0904, + 0x2ea1, 0xd28c, 0x1904, 0x2ea1, 0x0036, 0x73a8, 0x938e, 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x05a8, 0x908e, 0x0000, 0x0590, 0x908e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1588, 0x7290, 0xc28d, 0x7292, 0x70ab, 0xffff, - 0x003e, 0x0478, 0x0026, 0x2011, 0x0010, 0x080c, 0x668a, 0x002e, - 0x0118, 0x70ab, 0xffff, 0x0410, 0x900e, 0x080c, 0x243d, 0x080c, - 0x620b, 0x11c0, 0x080c, 0x6666, 0x1168, 0x7030, 0xd08c, 0x0130, - 0xb800, 0xd0bc, 0x0138, 0x080c, 0x655e, 0x0120, 0x080c, 0x2f0d, - 0x0148, 0x0028, 0x080c, 0x3059, 0x080c, 0x2f39, 0x0118, 0x8318, - 0x0804, 0x2e33, 0x73aa, 0x0010, 0x70ab, 0xffff, 0x003e, 0x0804, - 0x2eef, 0x9780, 0x317f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, + 0x003e, 0x0478, 0x0026, 0x2011, 0x0010, 0x080c, 0x66ae, 0x002e, + 0x0118, 0x70ab, 0xffff, 0x0410, 0x900e, 0x080c, 0x2459, 0x080c, + 0x622f, 0x11c0, 0x080c, 0x668a, 0x1168, 0x7030, 0xd08c, 0x0130, + 0xb800, 0xd0bc, 0x0138, 0x080c, 0x6582, 0x0120, 0x080c, 0x2f2d, + 0x0148, 0x0028, 0x080c, 0x3079, 0x080c, 0x2f59, 0x0118, 0x8318, + 0x0804, 0x2e53, 0x73aa, 0x0010, 0x70ab, 0xffff, 0x003e, 0x0804, + 0x2f0f, 0x9780, 0x319f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70a8, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70ab, 0xffff, - 0x0804, 0x2eef, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x2ee4, - 0x0026, 0x2011, 0x0010, 0x080c, 0x668a, 0x002e, 0x0120, 0x2009, - 0xffff, 0x0804, 0x2eec, 0xc484, 0x080c, 0x626b, 0x0138, 0x080c, - 0xbf61, 0x1590, 0x080c, 0x620b, 0x15b8, 0x0008, 0xc485, 0x080c, - 0x6666, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, - 0x7290, 0xd28c, 0x0180, 0x080c, 0x6666, 0x9082, 0x0006, 0x02e0, - 0xd484, 0x1118, 0x080c, 0x622f, 0x0028, 0x080c, 0x30eb, 0x01a0, - 0x080c, 0x3116, 0x0088, 0x080c, 0x3059, 0x080c, 0xbf61, 0x1160, - 0x080c, 0x2f39, 0x0188, 0x0040, 0x080c, 0xbf61, 0x1118, 0x080c, - 0x30eb, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, - 0x2e9a, 0x70ab, 0xffff, 0x0018, 0x001e, 0x015e, 0x71aa, 0x004e, + 0x0804, 0x2f0f, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x2f04, + 0x0026, 0x2011, 0x0010, 0x080c, 0x66ae, 0x002e, 0x0120, 0x2009, + 0xffff, 0x0804, 0x2f0c, 0xc484, 0x080c, 0x628f, 0x0138, 0x080c, + 0xbf8f, 0x1590, 0x080c, 0x622f, 0x15b8, 0x0008, 0xc485, 0x080c, + 0x668a, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, + 0x7290, 0xd28c, 0x0180, 0x080c, 0x668a, 0x9082, 0x0006, 0x02e0, + 0xd484, 0x1118, 0x080c, 0x6253, 0x0028, 0x080c, 0x310b, 0x01a0, + 0x080c, 0x3136, 0x0088, 0x080c, 0x3079, 0x080c, 0xbf8f, 0x1160, + 0x080c, 0x2f59, 0x0188, 0x0040, 0x080c, 0xbf8f, 0x1118, 0x080c, + 0x310b, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, + 0x2eba, 0x70ab, 0xffff, 0x0018, 0x001e, 0x015e, 0x71aa, 0x004e, 0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70ab, 0x0001, - 0x2009, 0x007e, 0x080c, 0x620b, 0x1168, 0xb813, 0x00ff, 0xb817, - 0xfffe, 0x080c, 0x3059, 0x04a9, 0x0128, 0x70d8, 0xc0bd, 0x70da, - 0x080c, 0xbcae, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x2001, 0x1858, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, - 0x9c49, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xbcdb, 0x6023, 0x0001, - 0x9006, 0x080c, 0x61a8, 0x2001, 0x0000, 0x080c, 0x61bc, 0x0126, + 0x2009, 0x007e, 0x080c, 0x622f, 0x1168, 0xb813, 0x00ff, 0xb817, + 0xfffe, 0x080c, 0x3079, 0x04a9, 0x0128, 0x70d8, 0xc0bd, 0x70da, + 0x080c, 0xbcdc, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, + 0x00c6, 0x2001, 0x1860, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, + 0x9c55, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xbd09, 0x6023, 0x0001, + 0x9006, 0x080c, 0x61cc, 0x2001, 0x0000, 0x080c, 0x61e0, 0x0126, 0x2091, 0x8000, 0x70a4, 0x8000, 0x70a6, 0x012e, 0x2009, 0x0004, - 0x080c, 0x9c76, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x1858, 0x2004, - 0x9084, 0x00ff, 0xb842, 0x080c, 0x9c49, 0x0548, 0x2b00, 0x6012, + 0x080c, 0x9c82, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x1860, 0x2004, + 0x9084, 0x00ff, 0xb842, 0x080c, 0x9c55, 0x0548, 0x2b00, 0x6012, 0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x300e, 0x080c, - 0xbcdb, 0x6023, 0x0001, 0x9006, 0x080c, 0x61a8, 0x2001, 0x0002, - 0x080c, 0x61bc, 0x0126, 0x2091, 0x8000, 0x70a4, 0x8000, 0x70a6, - 0x012e, 0x2009, 0x0002, 0x080c, 0x9c76, 0x9085, 0x0001, 0x00ce, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x302e, 0x080c, + 0xbd09, 0x6023, 0x0001, 0x9006, 0x080c, 0x61cc, 0x2001, 0x0002, + 0x080c, 0x61e0, 0x0126, 0x2091, 0x8000, 0x70a4, 0x8000, 0x70a6, + 0x012e, 0x2009, 0x0002, 0x080c, 0x9c82, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, - 0x0080, 0x080c, 0x620b, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, + 0x0080, 0x080c, 0x622f, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, 0x0110, 0x70df, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0x9b84, 0x01d0, 0x2b00, - 0x6012, 0x080c, 0xbcdb, 0x6023, 0x0001, 0x9006, 0x080c, 0x61a8, - 0x2001, 0x0002, 0x080c, 0x61bc, 0x0126, 0x2091, 0x8000, 0x70e0, - 0x8000, 0x70e2, 0x012e, 0x2009, 0x0002, 0x080c, 0x9c76, 0x9085, + 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0x9b90, 0x01d0, 0x2b00, + 0x6012, 0x080c, 0xbd09, 0x6023, 0x0001, 0x9006, 0x080c, 0x61cc, + 0x2001, 0x0002, 0x080c, 0x61e0, 0x0126, 0x2091, 0x8000, 0x70e0, + 0x8000, 0x70e2, 0x012e, 0x2009, 0x0002, 0x080c, 0x9c82, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x620b, 0x11b8, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8c7, 0x0004, 0x080c, 0x9b84, + 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x622f, 0x11b8, + 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8c7, 0x0004, 0x080c, 0x9b90, 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, - 0xbcdb, 0x2009, 0x0022, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, + 0xbd09, 0x2009, 0x0022, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, - 0x00b6, 0x21f0, 0x080c, 0x98bb, 0x0106, 0x080c, 0x862f, 0x080c, - 0x85aa, 0x080c, 0x980c, 0x080c, 0xab3a, 0x010e, 0x090c, 0x98d7, + 0x00b6, 0x21f0, 0x080c, 0x98c7, 0x0106, 0x080c, 0x8663, 0x080c, + 0x85de, 0x080c, 0x9818, 0x080c, 0xab55, 0x010e, 0x090c, 0x98e3, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x626b, 0x1140, 0x9686, - 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5cf1, 0x001e, - 0x8108, 0x1f04, 0x2ff3, 0x9686, 0x0001, 0x190c, 0x3149, 0x00be, + 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x628f, 0x1140, 0x9686, + 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x5d11, 0x001e, + 0x8108, 0x1f04, 0x3013, 0x9686, 0x0001, 0x190c, 0x3169, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, - 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0x98bb, 0x0106, - 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x8624, - 0x0076, 0x2039, 0x0000, 0x080c, 0x8509, 0x2c08, 0x080c, 0xcfd9, - 0x007e, 0x001e, 0x010e, 0x090c, 0x98d7, 0xba10, 0xbb14, 0xbc84, - 0x080c, 0x5cf1, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, + 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0x98c7, 0x0106, + 0x6210, 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x8658, + 0x0076, 0x2039, 0x0000, 0x080c, 0x853d, 0x2c08, 0x080c, 0xd011, + 0x007e, 0x001e, 0x010e, 0x090c, 0x98e3, 0xba10, 0xbb14, 0xbc84, + 0x080c, 0x5d11, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a4, 0x9005, 0x0110, 0x8001, 0x70a6, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e0, 0x9005, 0x0dc0, 0x8001, 0x70e2, 0x0ca8, 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x080c, - 0x98bb, 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0070, 0x080c, - 0x5388, 0xd0c4, 0x0138, 0x0030, 0x9006, 0x2020, 0x2009, 0x002d, - 0x080c, 0xd284, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, - 0x0904, 0x30c7, 0x928e, 0x007f, 0x0904, 0x30c7, 0x928e, 0x0080, + 0x98c7, 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0070, 0x080c, + 0x53a8, 0xd0c4, 0x0138, 0x0030, 0x9006, 0x2020, 0x2009, 0x002d, + 0x080c, 0xd2bc, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, + 0x0904, 0x30e7, 0x928e, 0x007f, 0x0904, 0x30e7, 0x928e, 0x0080, 0x05f0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150, - 0x2001, 0x195e, 0x0006, 0x2003, 0x0001, 0x080c, 0x30d8, 0x000e, + 0x2001, 0x1966, 0x0006, 0x2003, 0x0001, 0x080c, 0x30f8, 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, - 0x6630, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x8624, 0x0076, - 0x2039, 0x0000, 0x080c, 0x8509, 0x00b6, 0x00c6, 0x0026, 0x2158, + 0x6654, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x8658, 0x0076, + 0x2039, 0x0000, 0x080c, 0x853d, 0x00b6, 0x00c6, 0x0026, 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, - 0x00be, 0x0016, 0x2c08, 0x080c, 0xcfd9, 0x001e, 0x007e, 0x002e, - 0x8210, 0x1f04, 0x307d, 0x010e, 0x090c, 0x98d7, 0x015e, 0x001e, + 0x00be, 0x0016, 0x2c08, 0x080c, 0xd011, 0x001e, 0x007e, 0x002e, + 0x8210, 0x1f04, 0x309d, 0x010e, 0x090c, 0x98e3, 0x015e, 0x001e, 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0046, 0x0026, 0x0016, 0x080c, 0x5388, 0xd0c4, 0x0140, 0xd0a4, - 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xd284, 0x001e, + 0x0046, 0x0026, 0x0016, 0x080c, 0x53a8, 0xd0c4, 0x0140, 0xd0a4, + 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xd2bc, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7290, - 0x82ff, 0x01e8, 0x080c, 0x665e, 0x11d0, 0x2100, 0x080c, 0x2470, + 0x82ff, 0x01e8, 0x080c, 0x6682, 0x11d0, 0x2100, 0x080c, 0x248c, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x98bb, 0x0106, 0x0036, 0x2019, - 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0x98d7, 0x9180, 0x1000, - 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b01, 0x001e, - 0x6112, 0x080c, 0x300e, 0x001e, 0x080c, 0x622f, 0x012e, 0x00ce, - 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0x94dd, 0x080c, - 0xd53a, 0x002e, 0x001e, 0x0005, 0x2001, 0x1836, 0x2004, 0xd0cc, - 0x0005, 0x00c6, 0x00b6, 0x080c, 0x7096, 0x1118, 0x20a9, 0x0800, - 0x0010, 0x20a9, 0x0782, 0x080c, 0x7096, 0x1110, 0x900e, 0x0010, + 0x0126, 0x2091, 0x8000, 0x080c, 0x98c7, 0x0106, 0x0036, 0x2019, + 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0x98e3, 0x9180, 0x1000, + 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b09, 0x001e, + 0x6112, 0x080c, 0x302e, 0x001e, 0x080c, 0x6253, 0x012e, 0x00ce, + 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0x94e5, 0x080c, + 0xd572, 0x002e, 0x001e, 0x0005, 0x2001, 0x1836, 0x2004, 0xd0cc, + 0x0005, 0x00c6, 0x00b6, 0x080c, 0x70ba, 0x1118, 0x20a9, 0x0800, + 0x0010, 0x20a9, 0x0782, 0x080c, 0x70ba, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, - 0x0110, 0xb800, 0xd0bc, 0x090c, 0x622f, 0x8108, 0x1f04, 0x315a, + 0x0110, 0xb800, 0xd0bc, 0x090c, 0x6253, 0x8108, 0x1f04, 0x317a, 0x2061, 0x1800, 0x607b, 0x0000, 0x607c, 0x9084, 0x00ff, 0x607e, - 0x60af, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1875, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1854, 0x2214, 0xd2ec, 0x0005, 0x7eef, + 0x60af, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x187d, 0x2004, + 0xd0bc, 0x0005, 0x2011, 0x185c, 0x2214, 0xd2ec, 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, @@ -1410,360 +1414,360 @@ unsigned short risc_code01[] = { 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, - 0x1894, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, - 0x700e, 0x7042, 0x7046, 0x703b, 0x18b0, 0x703f, 0x18b0, 0x7007, - 0x0001, 0x080c, 0x103b, 0x090c, 0x0d65, 0x2900, 0x706a, 0xa867, - 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x103b, 0x090c, 0x0d65, 0x2900, - 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x1894, - 0x7004, 0x0002, 0x32ae, 0x32af, 0x32c2, 0x32d6, 0x0005, 0x1004, - 0x32bf, 0x0e04, 0x32bf, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, + 0x189c, 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, + 0x700e, 0x7042, 0x7046, 0x703b, 0x18b8, 0x703f, 0x18b8, 0x7007, + 0x0001, 0x080c, 0x1048, 0x090c, 0x0d65, 0x2900, 0x706a, 0xa867, + 0x0002, 0xa8ab, 0xdcb0, 0x080c, 0x1048, 0x090c, 0x0d65, 0x2900, + 0x706e, 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189c, + 0x7004, 0x0002, 0x32ce, 0x32cf, 0x32e2, 0x32f6, 0x0005, 0x1004, + 0x32df, 0x0e04, 0x32df, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, - 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18ae, 0x2c4c, 0xa86c, - 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x33aa, 0x0005, + 0x012e, 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b6, 0x2c4c, 0xa86c, + 0x908e, 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x33ca, 0x0005, 0x7018, 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, 0x1210, 0x61cc, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, - 0x33a7, 0x61cc, 0x0804, 0x333c, 0x337e, 0x33b6, 0x33a7, 0x33c0, - 0x33ca, 0x33d0, 0x33d4, 0x33e4, 0x33e8, 0x33fe, 0x3404, 0x340a, - 0x3415, 0x3420, 0x342f, 0x343e, 0x344c, 0x3463, 0x347e, 0x33a7, - 0x3527, 0x3565, 0x360a, 0x361b, 0x363e, 0x33a7, 0x33a7, 0x33a7, - 0x3676, 0x3696, 0x369f, 0x36cb, 0x36d1, 0x33a7, 0x3717, 0x33a7, - 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x3722, 0x372b, 0x3733, 0x3735, - 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x3765, 0x33a7, - 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x3782, 0x37dd, 0x33a7, 0x33a7, - 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x0002, 0x3807, 0x380a, 0x3869, - 0x3882, 0x38b2, 0x3b54, 0x33a7, 0x4f59, 0x33a7, 0x33a7, 0x33a7, - 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x33a7, 0x33fe, 0x3404, 0x4053, - 0x53ac, 0x4069, 0x4fe8, 0x5039, 0x513c, 0x33a7, 0x519e, 0x51da, - 0x520b, 0x5317, 0x5238, 0x5297, 0x33a7, 0x406d, 0x41fd, 0x4213, - 0x4238, 0x429d, 0x4311, 0x4331, 0x43a8, 0x4404, 0x4460, 0x4463, - 0x4488, 0x44fb, 0x4565, 0x456d, 0x469f, 0x4804, 0x4838, 0x4a82, - 0x33a7, 0x4aa0, 0x4b5c, 0x4c32, 0x33a7, 0x33a7, 0x33a7, 0x33a7, - 0x4c98, 0x4cb3, 0x456d, 0x4ef9, 0x714c, 0x0000, 0x2021, 0x4000, - 0x080c, 0x48b6, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3388, 0x0010, + 0x33c7, 0x61cc, 0x0804, 0x335c, 0x339e, 0x33d6, 0x33c7, 0x33e0, + 0x33ea, 0x33f0, 0x33f4, 0x3404, 0x3408, 0x341e, 0x3424, 0x342a, + 0x3435, 0x3440, 0x344f, 0x345e, 0x346c, 0x3483, 0x349e, 0x33c7, + 0x3547, 0x3585, 0x362a, 0x363b, 0x365e, 0x33c7, 0x33c7, 0x33c7, + 0x3696, 0x36b6, 0x36bf, 0x36eb, 0x36f1, 0x33c7, 0x3737, 0x33c7, + 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x3742, 0x374b, 0x3753, 0x3755, + 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x3785, 0x33c7, + 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x37a2, 0x37fd, 0x33c7, 0x33c7, + 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x0002, 0x3827, 0x382a, 0x3889, + 0x38a2, 0x38d2, 0x3b74, 0x33c7, 0x4f79, 0x33c7, 0x33c7, 0x33c7, + 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x33c7, 0x341e, 0x3424, 0x4073, + 0x53cc, 0x4089, 0x5008, 0x5059, 0x515c, 0x33c7, 0x51be, 0x51fa, + 0x522b, 0x5337, 0x5258, 0x52b7, 0x33c7, 0x408d, 0x421d, 0x4233, + 0x4258, 0x42bd, 0x4331, 0x4351, 0x43c8, 0x4424, 0x4480, 0x4483, + 0x44a8, 0x451b, 0x4585, 0x458d, 0x46bf, 0x4824, 0x4858, 0x4aa2, + 0x33c7, 0x4ac0, 0x4b7c, 0x4c52, 0x33c7, 0x33c7, 0x33c7, 0x33c7, + 0x4cb8, 0x4cd3, 0x458d, 0x4f19, 0x714c, 0x0000, 0x2021, 0x4000, + 0x080c, 0x48d6, 0x0126, 0x2091, 0x8000, 0x0e04, 0x33a8, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x7007, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, - 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x48c3, + 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x0804, 0x48e3, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, - 0x0804, 0x48c6, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x337e, - 0x7984, 0x2114, 0x0804, 0x337e, 0x20e1, 0x0000, 0x2099, 0x0021, + 0x0804, 0x48e6, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, 0x339e, + 0x7984, 0x2114, 0x0804, 0x339e, 0x20e1, 0x0000, 0x2099, 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, 0x7984, - 0x7a88, 0x7b8c, 0x0804, 0x337e, 0x7884, 0x2060, 0x0804, 0x3431, - 0x2009, 0x0003, 0x2011, 0x0002, 0x2019, 0x001e, 0x789b, 0x0317, - 0x7893, 0xffff, 0x2001, 0x1885, 0x2004, 0x9005, 0x0118, 0x7896, - 0x0804, 0x337e, 0x7897, 0x0001, 0x0804, 0x337e, 0x2039, 0x0001, - 0x7d98, 0x7c9c, 0x0804, 0x33ba, 0x2039, 0x0001, 0x7d98, 0x7c9c, - 0x0804, 0x33c4, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x33b3, - 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x33ba, 0x79a0, 0x9182, 0x0040, - 0x0210, 0x0804, 0x33b3, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x33c4, - 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x33b3, 0x21e8, 0x7984, - 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x337e, 0x2061, + 0x7a88, 0x7b8c, 0x0804, 0x339e, 0x7884, 0x2060, 0x0804, 0x3451, + 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0002, 0x789b, 0x0317, + 0x7893, 0xffff, 0x2001, 0x188d, 0x2004, 0x9005, 0x0118, 0x7896, + 0x0804, 0x339e, 0x7897, 0x0001, 0x0804, 0x339e, 0x2039, 0x0001, + 0x7d98, 0x7c9c, 0x0804, 0x33da, 0x2039, 0x0001, 0x7d98, 0x7c9c, + 0x0804, 0x33e4, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x33d3, + 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x33da, 0x79a0, 0x9182, 0x0040, + 0x0210, 0x0804, 0x33d3, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x33e4, + 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x33d3, 0x21e8, 0x7984, + 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x339e, 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, 0x1dd8, - 0x2010, 0x9005, 0x0904, 0x337e, 0x0804, 0x33ad, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x33b3, 0x21e0, 0x20a9, 0x0001, 0x7984, - 0x2198, 0x4012, 0x0804, 0x337e, 0x2069, 0x1853, 0x7884, 0x7990, - 0x911a, 0x1a04, 0x33b3, 0x8019, 0x0904, 0x33b3, 0x684a, 0x6942, + 0x2010, 0x9005, 0x0904, 0x339e, 0x0804, 0x33cd, 0x79a0, 0x9182, + 0x0040, 0x0210, 0x0804, 0x33d3, 0x21e0, 0x20a9, 0x0001, 0x7984, + 0x2198, 0x4012, 0x0804, 0x339e, 0x2069, 0x185b, 0x7884, 0x7990, + 0x911a, 0x1a04, 0x33d3, 0x8019, 0x0904, 0x33d3, 0x684a, 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, 0x080c, - 0x73c7, 0x0804, 0x337e, 0x2069, 0x1853, 0x7884, 0x7994, 0x911a, - 0x1a04, 0x33b3, 0x8019, 0x0904, 0x33b3, 0x684e, 0x6946, 0x788c, + 0x73ea, 0x0804, 0x339e, 0x2069, 0x185b, 0x7884, 0x7994, 0x911a, + 0x1a04, 0x33d3, 0x8019, 0x0904, 0x33d3, 0x684e, 0x6946, 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6764, 0x012e, 0x0804, 0x337e, 0x902e, 0x2520, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33b0, 0x7984, 0x7b88, - 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x189c, 0x4101, - 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, 0x2009, - 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x48c3, 0x701f, - 0x34a2, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, + 0x8000, 0x080c, 0x6788, 0x012e, 0x0804, 0x339e, 0x902e, 0x2520, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33d0, 0x7984, 0x7b88, + 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a4, 0x4101, + 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, 0x2009, + 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x48e3, 0x701f, + 0x34c2, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, 0x9096, - 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x33b0, 0x810f, 0x918c, - 0x00ff, 0x0904, 0x33b0, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, - 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, 0x2009, + 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x33d0, 0x810f, 0x918c, + 0x00ff, 0x0904, 0x33d0, 0x7112, 0x7010, 0x8001, 0x0560, 0x7012, + 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, - 0x9080, 0x0019, 0xaf60, 0x080c, 0x48c3, 0x701f, 0x34e0, 0x0005, + 0x9080, 0x0019, 0xaf60, 0x080c, 0x48e3, 0x701f, 0x3500, 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, 0x000a, - 0x1904, 0x33b0, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, + 0x1904, 0x33d0, 0x0888, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0029, 0x1160, 0xc2fd, 0xaa7a, - 0x080c, 0x5ddf, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, - 0x012e, 0x0050, 0x080c, 0x60f6, 0x1128, 0x7007, 0x0003, 0x701f, - 0x350c, 0x0005, 0x080c, 0x6ba2, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0005, 0x20e1, 0x0001, 0x2099, 0x189c, 0x400a, 0x2100, 0x9210, + 0x080c, 0x5dff, 0x0150, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, + 0x012e, 0x0050, 0x080c, 0x611a, 0x1128, 0x7007, 0x0003, 0x701f, + 0x352c, 0x0005, 0x080c, 0x6bc6, 0x0126, 0x2091, 0x8000, 0x20a9, + 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a4, 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, 0xa85c, 0x9080, - 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, 0x0804, 0x48c6, 0x2091, + 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, 0x0804, 0x48e6, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x0180, 0x2001, 0x19f2, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, + 0x0180, 0x2001, 0x19fa, 0x2004, 0x9005, 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, 0x2003, - 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x33b0, - 0x7984, 0x080c, 0x626b, 0x1904, 0x33b3, 0x7e98, 0x9684, 0x3fff, - 0x9082, 0x4000, 0x1a04, 0x33b3, 0x7c88, 0x7d8c, 0x080c, 0x64a1, - 0x080c, 0x642e, 0x1518, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, + 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, 0x81ff, 0x1904, 0x33d0, + 0x7984, 0x080c, 0x628f, 0x1904, 0x33d3, 0x7e98, 0x9684, 0x3fff, + 0x9082, 0x4000, 0x1a04, 0x33d3, 0x7c88, 0x7d8c, 0x080c, 0x64c5, + 0x080c, 0x6452, 0x1518, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150, 0x012e, 0x9ce0, 0x001c, - 0x2001, 0x1819, 0x2004, 0x9c02, 0x1a04, 0x33b0, 0x0c30, 0x080c, - 0xb440, 0x012e, 0x0904, 0x33b0, 0x0804, 0x337e, 0x900e, 0x2001, - 0x0005, 0x080c, 0x6ba2, 0x0126, 0x2091, 0x8000, 0x080c, 0xbb4b, - 0x080c, 0x6991, 0x012e, 0x0804, 0x337e, 0x00a6, 0x2950, 0xb198, - 0x080c, 0x626b, 0x1904, 0x35f7, 0xb6a4, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x64a1, 0x080c, 0x644b, + 0x2001, 0x1819, 0x2004, 0x9c02, 0x1a04, 0x33d0, 0x0c30, 0x080c, + 0xb45e, 0x012e, 0x0904, 0x33d0, 0x0804, 0x339e, 0x900e, 0x2001, + 0x0005, 0x080c, 0x6bc6, 0x0126, 0x2091, 0x8000, 0x080c, 0xbb79, + 0x080c, 0x69b5, 0x012e, 0x0804, 0x339e, 0x00a6, 0x2950, 0xb198, + 0x080c, 0x628f, 0x1904, 0x3617, 0xb6a4, 0x9684, 0x3fff, 0x9082, + 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, 0x64c5, 0x080c, 0x646f, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0, 0x001c, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xb440, + 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, 0x0c28, 0x080c, 0xb45e, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, 0x900e, 0x2001, 0x0005, - 0x080c, 0x6ba2, 0x0126, 0x2091, 0x8000, 0x080c, 0xbb4b, 0x080c, - 0x6985, 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, 0xb097, + 0x080c, 0x6bc6, 0x0126, 0x2091, 0x8000, 0x080c, 0xbb79, 0x080c, + 0x69a9, 0x012e, 0x0070, 0xb097, 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d, 0x0001, 0x2008, 0x2a48, - 0x00ae, 0x0005, 0x81ff, 0x1904, 0x33b0, 0x080c, 0x4891, 0x0904, - 0x33b3, 0x080c, 0x6332, 0x0904, 0x33b0, 0x080c, 0x64a7, 0x0904, - 0x33b0, 0x0804, 0x4328, 0x81ff, 0x1904, 0x33b0, 0x080c, 0x48ad, - 0x0904, 0x33b3, 0x080c, 0x6535, 0x0904, 0x33b0, 0x2019, 0x0005, - 0x79a8, 0x080c, 0x64c2, 0x0904, 0x33b0, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x33b3, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8146, - 0x7984, 0xd184, 0x1904, 0x337e, 0x0804, 0x4328, 0x0126, 0x2091, + 0x00ae, 0x0005, 0x81ff, 0x1904, 0x33d0, 0x080c, 0x48b1, 0x0904, + 0x33d3, 0x080c, 0x6356, 0x0904, 0x33d0, 0x080c, 0x64cb, 0x0904, + 0x33d0, 0x0804, 0x4348, 0x81ff, 0x1904, 0x33d0, 0x080c, 0x48cd, + 0x0904, 0x33d3, 0x080c, 0x6559, 0x0904, 0x33d0, 0x2019, 0x0005, + 0x79a8, 0x080c, 0x64e6, 0x0904, 0x33d0, 0x7888, 0x908a, 0x1000, + 0x1a04, 0x33d3, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x817a, + 0x7984, 0xd184, 0x1904, 0x339e, 0x0804, 0x4348, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x07ff, - 0x6458, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x626b, 0x11d8, - 0x080c, 0x6535, 0x1128, 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, - 0x2019, 0x0004, 0x900e, 0x080c, 0x64c2, 0x1118, 0x2009, 0x0006, + 0x6458, 0x2400, 0x9506, 0x01f8, 0x2508, 0x080c, 0x628f, 0x11d8, + 0x080c, 0x6559, 0x1128, 0x2009, 0x0002, 0x62bc, 0x2518, 0x00c0, + 0x2019, 0x0004, 0x900e, 0x080c, 0x64e6, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x8146, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x337e, - 0x012e, 0x0804, 0x33b0, 0x012e, 0x0804, 0x33b3, 0x080c, 0x4891, - 0x0904, 0x33b3, 0x080c, 0x6332, 0x0904, 0x33b0, 0x080c, 0x98bb, - 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x8624, 0x0076, - 0x903e, 0x080c, 0x8509, 0x900e, 0x080c, 0xcfd9, 0x007e, 0x00ce, - 0x080c, 0x98d7, 0x080c, 0x64a1, 0x0804, 0x337e, 0x080c, 0x4891, - 0x0904, 0x33b3, 0x080c, 0x64a1, 0x2208, 0x0804, 0x337e, 0x0156, - 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x1906, 0x6810, 0x6914, 0x910a, - 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x2071, 0x19b7, 0x7028, + 0x9108, 0x080c, 0x817a, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x339e, + 0x012e, 0x0804, 0x33d0, 0x012e, 0x0804, 0x33d3, 0x080c, 0x48b1, + 0x0904, 0x33d3, 0x080c, 0x6356, 0x0904, 0x33d0, 0x080c, 0x98c7, + 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, 0x8658, 0x0076, + 0x903e, 0x080c, 0x853d, 0x900e, 0x080c, 0xd011, 0x007e, 0x00ce, + 0x080c, 0x98e3, 0x080c, 0x64c5, 0x0804, 0x339e, 0x080c, 0x48b1, + 0x0904, 0x33d3, 0x080c, 0x64c5, 0x2208, 0x0804, 0x339e, 0x0156, + 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x190e, 0x6810, 0x6914, 0x910a, + 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, 0x2071, 0x19bf, 0x7028, 0x9065, 0x0118, 0x8210, 0x600c, 0x0cd8, 0x2300, 0x9218, 0x00ce, - 0x00ee, 0x00de, 0x015e, 0x0804, 0x337e, 0x00f6, 0x0016, 0x907d, + 0x00ee, 0x00de, 0x015e, 0x0804, 0x339e, 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, - 0x001e, 0x00fe, 0x0005, 0x2069, 0x1906, 0x6910, 0x62b8, 0x0804, - 0x337e, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33b0, 0x0126, - 0x2091, 0x8000, 0x080c, 0x539c, 0x0128, 0x2009, 0x0007, 0x012e, - 0x0804, 0x33b0, 0x012e, 0x6158, 0x9190, 0x317f, 0x2215, 0x9294, + 0x001e, 0x00fe, 0x0005, 0x2069, 0x190e, 0x6910, 0x62b8, 0x0804, + 0x339e, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33d0, 0x0126, + 0x2091, 0x8000, 0x080c, 0x53bc, 0x0128, 0x2009, 0x0007, 0x012e, + 0x0804, 0x33d0, 0x012e, 0x6158, 0x9190, 0x319f, 0x2215, 0x9294, 0x00ff, 0x6378, 0x83ff, 0x0108, 0x627c, 0x67d8, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, 0x00a8, 0x97c4, 0x0012, - 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, 0x7096, + 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, 0x0068, 0x080c, 0x70ba, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, 0x0120, 0x2009, 0x0005, - 0x0804, 0x33b0, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x337e, 0x6148, - 0x624c, 0x2019, 0x1956, 0x231c, 0x2001, 0x1957, 0x2004, 0x789a, - 0x0804, 0x337e, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, - 0x012e, 0x0804, 0x337e, 0x080c, 0x48ad, 0x0904, 0x33b3, 0xba44, - 0xbb38, 0x0804, 0x337e, 0x080c, 0x0d65, 0x080c, 0x48ad, 0x2110, - 0x0904, 0x33b3, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, - 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x33b0, + 0x0804, 0x33d0, 0x9036, 0x7e9a, 0x7f9e, 0x0804, 0x339e, 0x6148, + 0x624c, 0x2019, 0x195e, 0x231c, 0x2001, 0x195f, 0x2004, 0x789a, + 0x0804, 0x339e, 0x0126, 0x2091, 0x8000, 0x6138, 0x623c, 0x6340, + 0x012e, 0x0804, 0x339e, 0x080c, 0x48cd, 0x0904, 0x33d3, 0xba44, + 0xbb38, 0x0804, 0x339e, 0x080c, 0x0d65, 0x080c, 0x48cd, 0x2110, + 0x0904, 0x33d3, 0xb804, 0x908c, 0x00ff, 0x918e, 0x0006, 0x0140, + 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, 0x0009, 0x1904, 0x33d0, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, - 0x98bb, 0x080c, 0x94dd, 0x080c, 0x8624, 0x0076, 0x903e, 0x080c, - 0x8509, 0x900e, 0x080c, 0xcfd9, 0x007e, 0x00ce, 0x080c, 0x98d7, - 0xb807, 0x0407, 0x012e, 0x0804, 0x337e, 0x6148, 0x624c, 0x7884, - 0x604a, 0x7b88, 0x634e, 0x2069, 0x1853, 0x831f, 0x9305, 0x6816, - 0x788c, 0x2069, 0x1956, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, - 0x1210, 0x2031, 0x07d0, 0x2069, 0x1957, 0x2d04, 0x266a, 0x789a, - 0x0804, 0x337e, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, - 0x910e, 0xd1b4, 0x190c, 0x0eb4, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, - 0x2009, 0x196d, 0x200a, 0x78ac, 0x2011, 0x196e, 0x2012, 0x2069, + 0x98c7, 0x080c, 0x94e5, 0x080c, 0x8658, 0x0076, 0x903e, 0x080c, + 0x853d, 0x900e, 0x080c, 0xd011, 0x007e, 0x00ce, 0x080c, 0x98e3, + 0xb807, 0x0407, 0x012e, 0x0804, 0x339e, 0x6148, 0x624c, 0x7884, + 0x604a, 0x7b88, 0x634e, 0x2069, 0x185b, 0x831f, 0x9305, 0x6816, + 0x788c, 0x2069, 0x195e, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, + 0x1210, 0x2031, 0x07d0, 0x2069, 0x195f, 0x2d04, 0x266a, 0x789a, + 0x0804, 0x339e, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, + 0x910e, 0xd1b4, 0x190c, 0x0ec1, 0xd0c4, 0x01a8, 0x00d6, 0x78a8, + 0x2009, 0x1975, 0x200a, 0x78ac, 0x2011, 0x1976, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0x603e, 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040, 0x0010, 0x918c, 0xff7f, - 0x2112, 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, 0x190c, 0x0ecf, + 0x2112, 0x6140, 0x788c, 0x6042, 0x910e, 0xd1e4, 0x190c, 0x0edc, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, 0x0114, 0x2012, 0x012e, - 0x0804, 0x337e, 0x00f6, 0x2079, 0x1800, 0x7a38, 0xa898, 0x9084, + 0x0804, 0x339e, 0x00f6, 0x2079, 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, 0x7898, 0x9005, 0x01a8, - 0x7888, 0x9025, 0x0904, 0x33b3, 0x788c, 0x902d, 0x0904, 0x33b3, - 0x900e, 0x080c, 0x626b, 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, - 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x48ad, 0x0904, - 0x33b3, 0x7888, 0x900d, 0x0904, 0x33b3, 0x788c, 0x9005, 0x0904, - 0x33b3, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, 0x337e, 0x2011, - 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x539c, 0x1904, 0x33b0, + 0x7888, 0x9025, 0x0904, 0x33d3, 0x788c, 0x902d, 0x0904, 0x33d3, + 0x900e, 0x080c, 0x628f, 0x1120, 0xba44, 0xbb38, 0xbc46, 0xbd3a, + 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, 0x080c, 0x48cd, 0x0904, + 0x33d3, 0x7888, 0x900d, 0x0904, 0x33d3, 0x788c, 0x9005, 0x0904, + 0x33d3, 0xba44, 0xb946, 0xbb38, 0xb83a, 0x0804, 0x339e, 0x2011, + 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, 0x53bc, 0x1904, 0x33d0, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, 0x00ff, 0x1130, 0x2001, 0x1817, 0x2004, 0x9085, 0xff00, 0x0088, 0x9182, 0x007f, 0x16e0, - 0x9188, 0x317f, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1817, 0x2004, + 0x9188, 0x319f, 0x210d, 0x918c, 0x00ff, 0x2001, 0x1817, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, 0x9105, 0x0126, 0x2091, - 0x8000, 0x0006, 0x080c, 0x9b84, 0x000e, 0x0510, 0x602e, 0x620a, - 0x7984, 0x00b6, 0x080c, 0x6211, 0x2b08, 0x00be, 0x1500, 0x6112, - 0x6023, 0x0001, 0x080c, 0x487a, 0x01d0, 0x9006, 0xa866, 0x7007, - 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, 0x3862, 0x2900, - 0x6016, 0x2009, 0x0032, 0x080c, 0x9c76, 0x012e, 0x00ce, 0x0005, - 0x012e, 0x00ce, 0x0804, 0x33b0, 0x00ce, 0x0804, 0x33b3, 0x080c, - 0x9bda, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, 0x33b0, 0x0804, - 0x337e, 0x2061, 0x1a3e, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, + 0x8000, 0x0006, 0x080c, 0x9b90, 0x000e, 0x0510, 0x602e, 0x620a, + 0x7984, 0x00b6, 0x080c, 0x6235, 0x2b08, 0x00be, 0x1500, 0x6112, + 0x6023, 0x0001, 0x080c, 0x489a, 0x01d0, 0x9006, 0xa866, 0x7007, + 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x701f, 0x3882, 0x2900, + 0x6016, 0x2009, 0x0032, 0x080c, 0x9c82, 0x012e, 0x00ce, 0x0005, + 0x012e, 0x00ce, 0x0804, 0x33d0, 0x00ce, 0x0804, 0x33d3, 0x080c, + 0x9be6, 0x0cb0, 0xa830, 0x9086, 0x0100, 0x0904, 0x33d0, 0x0804, + 0x339e, 0x2061, 0x1a46, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, 0x6350, 0x6070, 0x789a, - 0x60bc, 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, 0x337e, 0x900e, - 0x2110, 0x0c88, 0x81ff, 0x1904, 0x33b0, 0x080c, 0x7096, 0x0904, - 0x33b0, 0x0126, 0x2091, 0x8000, 0x6250, 0x6070, 0x9202, 0x0248, - 0x9085, 0x0001, 0x080c, 0x24a6, 0x080c, 0x55b6, 0x012e, 0x0804, - 0x337e, 0x012e, 0x0804, 0x33b3, 0x0006, 0x0016, 0x00c6, 0x00e6, - 0x2001, 0x1979, 0x2070, 0x2061, 0x1853, 0x6008, 0x2072, 0x900e, - 0x2011, 0x1400, 0x080c, 0x83fb, 0x7206, 0x00ee, 0x00ce, 0x001e, + 0x60bc, 0x789e, 0x60b8, 0x78aa, 0x012e, 0x0804, 0x339e, 0x900e, + 0x2110, 0x0c88, 0x81ff, 0x1904, 0x33d0, 0x080c, 0x70ba, 0x0904, + 0x33d0, 0x0126, 0x2091, 0x8000, 0x6250, 0x6070, 0x9202, 0x0248, + 0x9085, 0x0001, 0x080c, 0x24c2, 0x080c, 0x55d6, 0x012e, 0x0804, + 0x339e, 0x012e, 0x0804, 0x33d3, 0x0006, 0x0016, 0x00c6, 0x00e6, + 0x2001, 0x1981, 0x2070, 0x2061, 0x185b, 0x6008, 0x2072, 0x900e, + 0x2011, 0x1400, 0x080c, 0x842f, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0128, 0x012e, - 0x2021, 0x400b, 0x0804, 0x3380, 0x7884, 0xd0fc, 0x0148, 0x2001, - 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, 0x0804, 0x33b3, - 0x2001, 0x002a, 0x2004, 0x2069, 0x1853, 0x6908, 0x9102, 0x1230, - 0x012e, 0x0804, 0x33b3, 0x012e, 0x0804, 0x33b0, 0x080c, 0x9b59, - 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x392d, 0x00c6, 0x080c, 0x487a, + 0x2021, 0x400b, 0x0804, 0x33a0, 0x7884, 0xd0fc, 0x0148, 0x2001, + 0x002a, 0x2004, 0x9082, 0x00e1, 0x0288, 0x012e, 0x0804, 0x33d3, + 0x2001, 0x002a, 0x2004, 0x2069, 0x185b, 0x6908, 0x9102, 0x1230, + 0x012e, 0x0804, 0x33d3, 0x012e, 0x0804, 0x33d0, 0x080c, 0x9b65, + 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x394d, 0x00c6, 0x080c, 0x489a, 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, - 0x00fc, 0x8004, 0xa816, 0x080c, 0x3ab7, 0x0928, 0x7014, 0x2048, + 0x00fc, 0x8004, 0xa816, 0x080c, 0x3ad7, 0x0928, 0x7014, 0x2048, 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x48c3, 0x701f, - 0x39f4, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, 0x98bb, 0x0046, + 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x48e3, 0x701f, + 0x3a14, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, 0x98c7, 0x0046, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x389c, 0x2001, 0x196f, 0x2003, 0x0000, 0x2021, 0x000a, + 0x080c, 0x38bc, 0x2001, 0x1977, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, - 0x60bf, 0x0012, 0x080c, 0x3b26, 0x080c, 0x3ae5, 0x00f6, 0x00e6, - 0x0086, 0x2940, 0x2071, 0x19b7, 0x2079, 0x0090, 0x00d6, 0x2069, + 0x60bf, 0x0012, 0x080c, 0x3b46, 0x080c, 0x3b05, 0x00f6, 0x00e6, + 0x0086, 0x2940, 0x2071, 0x19bf, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x3e97, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3dc4, 0x080c, 0x3cf1, + 0x3eb7, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x3de4, 0x080c, 0x3d11, 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, - 0x3f0b, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, + 0x3f2b, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, 0x2001, 0x181f, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, - 0x080c, 0x3cfb, 0x080c, 0x3ae0, 0x0058, 0x080c, 0x3ae0, 0x080c, - 0x3e2f, 0x080c, 0x3dba, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, + 0x080c, 0x3d1b, 0x080c, 0x3b00, 0x0058, 0x080c, 0x3b00, 0x080c, + 0x3e4f, 0x080c, 0x3dda, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x12e1, 0x2009, 0x0028, 0x080c, 0x2063, - 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0x98d7, 0x00fe, 0x00ee, + 0xfffd, 0x2102, 0x080c, 0x12ee, 0x2009, 0x0028, 0x080c, 0x207b, + 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0x98e3, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, - 0x196f, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x337e, 0x012e, - 0x2021, 0x400c, 0x0804, 0x3380, 0x0016, 0x0026, 0x0036, 0x0046, + 0x1977, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x339e, 0x012e, + 0x2021, 0x400c, 0x0804, 0x33a0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, - 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3a50, - 0x2048, 0x1f04, 0x3a04, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, + 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3a70, + 0x2048, 0x1f04, 0x3a24, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x001b, 0x080c, 0x48c3, 0x701f, 0x39f4, 0x00b0, 0x8906, + 0x9080, 0x001b, 0x080c, 0x48e3, 0x701f, 0x3a14, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f9f, - 0x000e, 0x080c, 0x48c6, 0x701f, 0x39f4, 0x015e, 0x00de, 0x009e, + 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fac, + 0x000e, 0x080c, 0x48e6, 0x701f, 0x3a14, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3ab5, + 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3ad5, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, - 0x080c, 0x620b, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, - 0xfffd, 0x080c, 0xbd2a, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x33b0, 0x0016, + 0x080c, 0x622f, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, + 0xfffd, 0x080c, 0xbd58, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x33d0, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x701f, 0x3a87, 0x7007, 0x0003, 0x0804, 0x3a45, 0xa830, - 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x3380, 0x0076, 0xad10, + 0x0156, 0x701f, 0x3aa7, 0x7007, 0x0003, 0x0804, 0x3a65, 0xa830, + 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x33a0, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, - 0x20a0, 0x0006, 0x080c, 0x0f9f, 0x000e, 0x080c, 0x48c6, 0x007e, - 0x701f, 0x39f4, 0x7023, 0x0001, 0x0005, 0x0804, 0x337e, 0x0156, + 0x20a0, 0x0006, 0x080c, 0x0fac, 0x000e, 0x080c, 0x48e6, 0x007e, + 0x701f, 0x3a14, 0x7023, 0x0001, 0x0005, 0x0804, 0x339e, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, - 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x487a, 0x001e, + 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x489a, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, - 0x2001, 0x196f, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0x197a, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0x1979, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, - 0x487a, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, + 0x2001, 0x1977, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, + 0x2061, 0x0200, 0x2001, 0x1982, 0x2004, 0x601a, 0x2061, 0x0100, + 0x2001, 0x1981, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, + 0x489a, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, - 0x0090, 0x2079, 0x0100, 0x2001, 0x1979, 0x2004, 0x6036, 0x2009, - 0x0040, 0x080c, 0x2063, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, + 0x0090, 0x2079, 0x0100, 0x2001, 0x1981, 0x2004, 0x6036, 0x2009, + 0x0040, 0x080c, 0x207b, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, - 0x487a, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, + 0x489a, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0148, 0x080c, 0x2830, 0x1130, 0x9006, 0x080c, 0x2787, 0x9006, - 0x080c, 0x276a, 0x7884, 0x9084, 0x0007, 0x0002, 0x3b71, 0x3b7a, - 0x3b83, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x012e, 0x0804, - 0x33b3, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, - 0x3d45, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, - 0x080c, 0x3d45, 0x0078, 0x080c, 0x7096, 0x1128, 0x012e, 0x2009, - 0x0016, 0x0804, 0x33b0, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, - 0x0804, 0x3380, 0x080c, 0x98bb, 0x0086, 0x0096, 0x00a6, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x389c, 0x2009, 0x0101, + 0x0148, 0x080c, 0x2850, 0x1130, 0x9006, 0x080c, 0x27a3, 0x9006, + 0x080c, 0x2786, 0x7884, 0x9084, 0x0007, 0x0002, 0x3b91, 0x3b9a, + 0x3ba3, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x012e, 0x0804, + 0x33d3, 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, + 0x3d65, 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, + 0x080c, 0x3d65, 0x0078, 0x080c, 0x70ba, 0x1128, 0x012e, 0x2009, + 0x0016, 0x0804, 0x33d0, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, + 0x0804, 0x33a0, 0x080c, 0x98c7, 0x0086, 0x0096, 0x00a6, 0x00b6, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x38bc, 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, 0x2058, - 0x080c, 0x3fe6, 0x080c, 0x3f36, 0x903e, 0x2720, 0x00f6, 0x00e6, - 0x0086, 0x2940, 0x2071, 0x19b7, 0x2079, 0x0090, 0x00d6, 0x2069, + 0x080c, 0x4006, 0x080c, 0x3f56, 0x903e, 0x2720, 0x00f6, 0x00e6, + 0x0086, 0x2940, 0x2071, 0x19bf, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, 0x780a, - 0x00de, 0x2011, 0x0001, 0x080c, 0x3e97, 0x080c, 0x2838, 0x080c, - 0x2838, 0x080c, 0x2838, 0x080c, 0x2838, 0x080c, 0x3e97, 0x008e, - 0x00ee, 0x00fe, 0x080c, 0x3dc4, 0x2009, 0x9c40, 0x8109, 0x11b0, - 0x080c, 0x3cfb, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, + 0x00de, 0x2011, 0x0001, 0x080c, 0x3eb7, 0x080c, 0x2858, 0x080c, + 0x2858, 0x080c, 0x2858, 0x080c, 0x2858, 0x080c, 0x3eb7, 0x008e, + 0x00ee, 0x00fe, 0x080c, 0x3de4, 0x2009, 0x9c40, 0x8109, 0x11b0, + 0x080c, 0x3d1b, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x2009, 0x0017, 0x080c, 0x33b0, 0x0cf8, 0x2001, 0x020b, + 0x008e, 0x2009, 0x0017, 0x080c, 0x33d0, 0x0cf8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0150, - 0x080c, 0x3da2, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, 0x3cfb, - 0x0804, 0x3ca4, 0x080c, 0x3f0b, 0x080c, 0x3e2f, 0x080c, 0x3d85, - 0x080c, 0x3dba, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, - 0x8b58, 0x080c, 0x3cfb, 0x00fe, 0x0804, 0x3ca4, 0x00fe, 0x080c, - 0x3cf1, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, - 0x2502, 0x080c, 0x3cfb, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, - 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a3b, 0x2004, - 0x9086, 0x0000, 0x1904, 0x3bf4, 0x2001, 0x032f, 0x2003, 0x00f6, - 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3ca4, 0x7884, - 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3ca4, 0xa013, + 0x080c, 0x3dc2, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, 0x3d1b, + 0x0804, 0x3cc4, 0x080c, 0x3f2b, 0x080c, 0x3e4f, 0x080c, 0x3da5, + 0x080c, 0x3dda, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, 0x0130, + 0x8b58, 0x080c, 0x3d1b, 0x00fe, 0x0804, 0x3cc4, 0x00fe, 0x080c, + 0x3d11, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, 0x0033, + 0x2502, 0x080c, 0x3d1b, 0x0080, 0x87ff, 0x0138, 0x2001, 0x0201, + 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a43, 0x2004, + 0x9086, 0x0000, 0x1904, 0x3c14, 0x2001, 0x032f, 0x2003, 0x00f6, + 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3cc4, 0x7884, + 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3cc4, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1148, - 0x2001, 0x1a3b, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, + 0x2001, 0x1a43, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, 0x2800, - 0xa05a, 0x2009, 0x0040, 0x080c, 0x2063, 0x2900, 0xa85a, 0xa813, + 0xa05a, 0x2009, 0x0040, 0x080c, 0x207b, 0x2900, 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, 0x2004, - 0x1f04, 0x3c7b, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, 0x9005, + 0x1f04, 0x3c9b, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0x00ce, 0x00fe, 0x0804, 0x3bae, 0x001e, 0x00c6, 0x2001, 0x032a, + 0x00ce, 0x00fe, 0x0804, 0x3bce, 0x001e, 0x00c6, 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, - 0x2102, 0x080c, 0x12e1, 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, - 0x01b0, 0x2009, 0x0028, 0x080c, 0x2063, 0x2001, 0x0227, 0x200c, - 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x28e2, 0x6052, 0x602f, + 0x2102, 0x080c, 0x12ee, 0x7884, 0x9084, 0x0003, 0x9086, 0x0002, + 0x01b0, 0x2009, 0x0028, 0x080c, 0x207b, 0x2001, 0x0227, 0x200c, + 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2902, 0x6052, 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x080c, - 0x98d7, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, + 0x98e3, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, - 0x1118, 0x012e, 0x0804, 0x337e, 0x012e, 0x2021, 0x400c, 0x0804, - 0x3380, 0x9085, 0x0001, 0x1d04, 0x3cfa, 0x2091, 0x6000, 0x8420, + 0x1118, 0x012e, 0x0804, 0x339e, 0x012e, 0x2021, 0x400c, 0x0804, + 0x33a0, 0x9085, 0x0001, 0x1d04, 0x3d1a, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2001, 0x1a3b, 0x2003, 0x0000, 0x0071, - 0x2009, 0x0048, 0x080c, 0x2063, 0x2001, 0x0227, 0x2024, 0x2402, + 0x032a, 0x2003, 0x0004, 0x2001, 0x1a43, 0x2003, 0x0000, 0x0071, + 0x2009, 0x0048, 0x080c, 0x207b, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, - 0x2071, 0x19b7, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, + 0x2071, 0x19bf, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x2063, 0x782c, 0xd0fc, 0x0d88, 0x080c, - 0x3f0b, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2063, 0x782b, 0x0002, + 0x2009, 0x0040, 0x080c, 0x207b, 0x782c, 0xd0fc, 0x0d88, 0x080c, + 0x3f2b, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, + 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x207b, 0x782b, 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x2001, 0x1817, 0x200c, 0x7932, 0x7936, 0x080c, 0x2486, 0x080c, - 0x28af, 0x080c, 0x28e2, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, + 0x2001, 0x1817, 0x200c, 0x7932, 0x7936, 0x080c, 0x24a2, 0x080c, + 0x28cf, 0x080c, 0x2902, 0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x7850, 0xc0e5, 0x7852, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x0110, 0x8319, 0x1dd8, 0x7850, 0xc0e4, 0x7852, 0x2011, 0x0048, - 0x080c, 0x288c, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, - 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2852, 0x2011, 0x0020, - 0x080c, 0x288c, 0x7843, 0x0000, 0x9006, 0x080c, 0x2852, 0x2011, - 0x0048, 0x080c, 0x288c, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, - 0x00f6, 0x00e6, 0x2071, 0x1a3b, 0x2079, 0x0320, 0x2001, 0x0201, + 0x080c, 0x28ac, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, 0xa001, + 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2872, 0x2011, 0x0020, + 0x080c, 0x28ac, 0x7843, 0x0000, 0x9006, 0x080c, 0x2872, 0x2011, + 0x0048, 0x080c, 0x28ac, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, + 0x00f6, 0x00e6, 0x2071, 0x1a43, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, @@ -1771,7 +1775,7 @@ unsigned short risc_code01[] = { 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, - 0x197a, 0x2004, 0x70e2, 0x080c, 0x3ad6, 0x1188, 0x2001, 0x181f, + 0x1982, 0x2004, 0x70e2, 0x080c, 0x3af6, 0x1188, 0x2001, 0x181f, 0x2004, 0x2009, 0x181e, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1817, 0x210c, 0x716e, 0x7063, @@ -1779,31 +1783,31 @@ unsigned short risc_code01[] = { 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, - 0x7016, 0x080c, 0x3f0b, 0x00f6, 0x2071, 0x1a3b, 0x2079, 0x0320, + 0x7016, 0x080c, 0x3f2b, 0x00f6, 0x2071, 0x1a43, 0x2079, 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, 0x00de, 0x2009, 0x03e8, 0x8109, 0x1df0, 0x792c, - 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x3e97, - 0x2011, 0x0001, 0x080c, 0x3e97, 0x00fe, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x1a3b, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, - 0x3e94, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x3e90, 0x7000, - 0x0002, 0x3e94, 0x3e45, 0x3e75, 0x3e90, 0xd1bc, 0x1170, 0xd1dc, - 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x3e97, 0x0904, - 0x3e94, 0x080c, 0x3e97, 0x0804, 0x3e94, 0x00f6, 0x2079, 0x0300, + 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, 0x3eb7, + 0x2011, 0x0001, 0x080c, 0x3eb7, 0x00fe, 0x00ee, 0x0005, 0x00f6, + 0x00e6, 0x2071, 0x1a43, 0x2079, 0x0320, 0x792c, 0xd1fc, 0x0904, + 0x3eb4, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x3eb0, 0x7000, + 0x0002, 0x3eb4, 0x3e65, 0x3e95, 0x3eb0, 0xd1bc, 0x1170, 0xd1dc, + 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x3eb7, 0x0904, + 0x3eb4, 0x080c, 0x3eb7, 0x0804, 0x3eb4, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, 0x7812, - 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3da2, + 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3dc2, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, 0x9184, - 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3e39, 0x2011, 0x0001, + 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x3e59, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a, 0x0007, - 0x1a0c, 0x0d65, 0x9398, 0x3ec5, 0x231d, 0x083f, 0x9080, 0x0004, + 0x1a0c, 0x0d65, 0x9398, 0x3ee5, 0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001, 0x0019, - 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x3f02, 0x3ef9, 0x3ef0, - 0x3ee7, 0x3ede, 0x3ed5, 0x3ecc, 0xa964, 0x7902, 0xa968, 0x7906, + 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x3f22, 0x3f19, 0x3f10, + 0x3f07, 0x3efe, 0x3ef5, 0x3eec, 0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005, 0xa994, @@ -1811,24 +1815,24 @@ unsigned short risc_code01[] = { 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, 0x7912, - 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, 0x19b7, + 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, 0x19bf, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, 0x2940, - 0x9026, 0x7054, 0x0002, 0x3f32, 0x3f1e, 0x3f29, 0x8001, 0x7056, - 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x3e97, 0x190c, 0x3e97, + 0x9026, 0x7054, 0x0002, 0x3f52, 0x3f3e, 0x3f49, 0x8001, 0x7056, + 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x3eb7, 0x190c, 0x3eb7, 0x0048, 0x8001, 0x7056, 0x782c, 0xd0fc, 0x1d38, 0x2011, 0x0001, - 0x080c, 0x3e97, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x197a, 0x2004, 0x601a, - 0x2061, 0x0100, 0x2001, 0x1979, 0x2004, 0x60ce, 0x6104, 0xc1ac, + 0x080c, 0x3eb7, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x1982, 0x2004, 0x601a, + 0x2061, 0x0100, 0x2001, 0x1981, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, 0x2001, - 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x487a, 0xa813, + 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x489a, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, - 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x3fae, 0x1d68, 0x2900, - 0xa85a, 0x00d0, 0x080c, 0x487a, 0xa813, 0x0019, 0xa817, 0x0001, + 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x3fce, 0x1d68, 0x2900, + 0xa85a, 0x00d0, 0x080c, 0x489a, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, 0x0100, - 0x2001, 0x1979, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2063, + 0x2001, 0x1981, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x207b, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, @@ -1836,654 +1840,654 @@ unsigned short risc_code01[] = { 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, 0x7304, - 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, 0x487a, + 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, 0x489a, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030, 0x2024, - 0x2001, 0x0031, 0x201c, 0x080c, 0x487a, 0x2940, 0xa813, 0x0019, + 0x2001, 0x0031, 0x201c, 0x080c, 0x489a, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, - 0x9080, 0x0019, 0x009e, 0x080c, 0x3fae, 0x1d68, 0x2900, 0xa85a, - 0x00d8, 0x080c, 0x487a, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, + 0x9080, 0x0019, 0x009e, 0x080c, 0x3fce, 0x1d68, 0x2900, 0xa85a, + 0x00d8, 0x080c, 0x489a, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, 0x0200, - 0x2102, 0xa017, 0x0000, 0x2001, 0x1a3b, 0x2003, 0x0003, 0x2001, + 0x2102, 0xa017, 0x0000, 0x2001, 0x1a43, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, 0x0002, - 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0013, + 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, 0x001b, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, 0x0804, - 0x337e, 0x7d98, 0x7c9c, 0x0804, 0x3480, 0x080c, 0x7096, 0x190c, - 0x5c9c, 0x2069, 0x1853, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x48c3, 0x701f, 0x4081, - 0x0005, 0x080c, 0x5397, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, - 0x20d8, 0x21d0, 0x2069, 0x1853, 0x6800, 0x9005, 0x0904, 0x33b3, + 0x339e, 0x7d98, 0x7c9c, 0x0804, 0x34a0, 0x080c, 0x70ba, 0x190c, + 0x5cbc, 0x2069, 0x185b, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, + 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x48e3, 0x701f, 0x40a1, + 0x0005, 0x080c, 0x53b7, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, + 0x20d8, 0x21d0, 0x2069, 0x185b, 0x6800, 0x9005, 0x0904, 0x33d3, 0x6804, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, - 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x33b3, 0x9288, 0x317f, + 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x33d3, 0x9288, 0x319f, 0x210d, 0x918c, 0x00ff, 0x6162, 0xd0dc, 0x0130, 0x6828, 0x908a, - 0x007f, 0x1a04, 0x33b3, 0x605a, 0x6888, 0x9084, 0x0030, 0x8004, - 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x1981, 0x9080, 0x2579, - 0x2005, 0x200a, 0x2008, 0x2001, 0x0018, 0x080c, 0x98ac, 0x2009, - 0x0390, 0x200b, 0x0400, 0x000e, 0x2009, 0x1982, 0x9080, 0x257d, - 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x33b3, 0x908a, - 0x0841, 0x1a04, 0x33b3, 0x9084, 0x0007, 0x1904, 0x33b3, 0x680c, - 0x9005, 0x0904, 0x33b3, 0x6810, 0x9005, 0x0904, 0x33b3, 0x6848, - 0x6940, 0x910a, 0x1a04, 0x33b3, 0x8001, 0x0904, 0x33b3, 0x684c, - 0x6944, 0x910a, 0x1a04, 0x33b3, 0x8001, 0x0904, 0x33b3, 0x6814, + 0x007f, 0x1a04, 0x33d3, 0x605a, 0x6888, 0x9084, 0x0030, 0x8004, + 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x1989, 0x9080, 0x2595, + 0x2005, 0x200a, 0x2008, 0x2001, 0x0018, 0x080c, 0x98b8, 0x2009, + 0x0390, 0x200b, 0x0400, 0x000e, 0x2009, 0x198a, 0x9080, 0x2599, + 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x33d3, 0x908a, + 0x0841, 0x1a04, 0x33d3, 0x9084, 0x0007, 0x1904, 0x33d3, 0x680c, + 0x9005, 0x0904, 0x33d3, 0x6810, 0x9005, 0x0904, 0x33d3, 0x6848, + 0x6940, 0x910a, 0x1a04, 0x33d3, 0x8001, 0x0904, 0x33d3, 0x684c, + 0x6944, 0x910a, 0x1a04, 0x33d3, 0x8001, 0x0904, 0x33d3, 0x6814, 0x908c, 0x00ff, 0x614a, 0x8007, 0x9084, 0x00ff, 0x604e, 0x080c, - 0x73c7, 0x080c, 0x672f, 0x080c, 0x6764, 0x6808, 0x602a, 0x080c, - 0x1fd5, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, - 0x0000, 0x0036, 0x6b08, 0x080c, 0x24e0, 0x003e, 0x6000, 0x9086, - 0x0000, 0x1904, 0x41ed, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, + 0x73ea, 0x080c, 0x6753, 0x080c, 0x6788, 0x6808, 0x602a, 0x080c, + 0x1fed, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, + 0x0000, 0x0036, 0x6b08, 0x080c, 0x24fc, 0x003e, 0x6000, 0x9086, + 0x0000, 0x1904, 0x420d, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, - 0x1983, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x199d, - 0x20e9, 0x0001, 0x4001, 0x080c, 0x82af, 0x00c6, 0x900e, 0x20a9, + 0x198b, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, 0x20a1, 0x19a5, + 0x20e9, 0x0001, 0x4001, 0x080c, 0x82e3, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, - 0x8109, 0x080c, 0x799d, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, + 0x8109, 0x080c, 0x79c1, 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, - 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x4165, 0x00ce, - 0x00c6, 0x2061, 0x196c, 0x2063, 0x0001, 0x9006, 0x080c, 0x2787, - 0x9006, 0x080c, 0x276a, 0x0000, 0x00ce, 0x00e6, 0x2c70, 0x080c, - 0x0e9c, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, + 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x4185, 0x00ce, + 0x00c6, 0x2061, 0x1974, 0x2063, 0x0001, 0x9006, 0x080c, 0x27a3, + 0x9006, 0x080c, 0x2786, 0x0000, 0x00ce, 0x00e6, 0x2c70, 0x080c, + 0x0ea9, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, 0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, - 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x194c, + 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x1954, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, - 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2555, - 0x2001, 0x193d, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, - 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x7096, 0x0128, - 0x080c, 0x4c8c, 0x0110, 0x080c, 0x24a6, 0x60d0, 0x9005, 0x01c0, - 0x6003, 0x0001, 0x2009, 0x41d5, 0x00d0, 0x080c, 0x7096, 0x1168, - 0x2011, 0x6f0c, 0x080c, 0x8138, 0x2011, 0x6eff, 0x080c, 0x823e, - 0x080c, 0x739b, 0x080c, 0x6fc7, 0x0040, 0x080c, 0x5b92, 0x0028, - 0x6003, 0x0004, 0x2009, 0x41ed, 0x0010, 0x0804, 0x337e, 0x2001, + 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2571, + 0x2001, 0x1945, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, + 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x70ba, 0x0128, + 0x080c, 0x4cac, 0x0110, 0x080c, 0x24c2, 0x60d0, 0x9005, 0x01c0, + 0x6003, 0x0001, 0x2009, 0x41f5, 0x00d0, 0x080c, 0x70ba, 0x1168, + 0x2011, 0x6f30, 0x080c, 0x816c, 0x2011, 0x6f23, 0x080c, 0x8272, + 0x080c, 0x73be, 0x080c, 0x6feb, 0x0040, 0x080c, 0x5bb2, 0x0028, + 0x6003, 0x0004, 0x2009, 0x420d, 0x0010, 0x0804, 0x339e, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, 0x1118, 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000, 0x9086, 0x0000, - 0x0904, 0x33b0, 0x2069, 0x1853, 0x7890, 0x6842, 0x7894, 0x6846, + 0x0904, 0x33d0, 0x2069, 0x185b, 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, - 0x0001, 0x0804, 0x48c6, 0x9006, 0x080c, 0x24a6, 0x81ff, 0x1904, - 0x33b0, 0x080c, 0x7096, 0x11b0, 0x080c, 0x7396, 0x080c, 0x5cd7, - 0x080c, 0x317a, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xbf61, - 0x0130, 0x080c, 0x70b9, 0x1118, 0x080c, 0x706a, 0x0038, 0x080c, - 0x6fc7, 0x0020, 0x080c, 0x5c9c, 0x080c, 0x5b92, 0x0804, 0x337e, - 0x81ff, 0x1904, 0x33b0, 0x080c, 0x7096, 0x1110, 0x0804, 0x33b0, + 0x0001, 0x0804, 0x48e6, 0x9006, 0x080c, 0x24c2, 0x81ff, 0x1904, + 0x33d0, 0x080c, 0x70ba, 0x11b0, 0x080c, 0x73b9, 0x080c, 0x5cf7, + 0x080c, 0x319a, 0x0118, 0x6130, 0xc18d, 0x6132, 0x080c, 0xbf8f, + 0x0130, 0x080c, 0x70dd, 0x1118, 0x080c, 0x708e, 0x0038, 0x080c, + 0x6feb, 0x0020, 0x080c, 0x5cbc, 0x080c, 0x5bb2, 0x0804, 0x339e, + 0x81ff, 0x1904, 0x33d0, 0x080c, 0x70ba, 0x1110, 0x0804, 0x33d0, 0x6190, 0x81ff, 0x01a8, 0x704f, 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0126, 0x2091, 0x8000, - 0x2039, 0x0001, 0x080c, 0x48c6, 0x701f, 0x337c, 0x012e, 0x0005, + 0x2039, 0x0001, 0x080c, 0x48e6, 0x701f, 0x339c, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, 0x6558, 0x9588, - 0x317f, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, - 0x2100, 0x9506, 0x01a8, 0x080c, 0x626b, 0x1190, 0xb814, 0x821c, + 0x319f, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, 0x2011, 0x0002, + 0x2100, 0x9506, 0x01a8, 0x080c, 0x628f, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1d80, 0x9085, 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1d80, 0x2324, 0x94a4, 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x1d80, 0x2099, - 0x1d80, 0x080c, 0x5c27, 0x0804, 0x4245, 0x080c, 0x48ad, 0x0904, - 0x33b3, 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, - 0x080c, 0x5388, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, 0x0538, - 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, 0x3175, + 0x1d80, 0x080c, 0x5c47, 0x0804, 0x4265, 0x080c, 0x48cd, 0x0904, + 0x33d3, 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, + 0x080c, 0x53a8, 0xd0b4, 0x0558, 0x7884, 0x908e, 0x007e, 0x0538, + 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, 0x080c, 0x3195, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, - 0xba11, 0x1120, 0x2009, 0x0003, 0x0804, 0x33b0, 0x7007, 0x0003, - 0x701f, 0x42d3, 0x0005, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x20a9, + 0xba3f, 0x1120, 0x2009, 0x0003, 0x0804, 0x33d0, 0x7007, 0x0003, + 0x701f, 0x42f3, 0x0005, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x20a9, 0x002b, 0xb8b4, 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, - 0x0f9f, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, 0x20a0, - 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0f9f, + 0x0fac, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x000a, 0x20a0, + 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fac, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, - 0x48c6, 0x81ff, 0x1904, 0x33b0, 0x080c, 0x4891, 0x0904, 0x33b3, - 0x080c, 0x64b0, 0x0904, 0x33b0, 0x0058, 0xa878, 0x9005, 0x0120, - 0x2009, 0x0004, 0x0804, 0x33b0, 0xa974, 0xaa94, 0x0804, 0x337e, - 0x080c, 0x5390, 0x0904, 0x337e, 0x701f, 0x431d, 0x7007, 0x0003, - 0x0005, 0x81ff, 0x1904, 0x33b0, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x33b3, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x080c, 0x6666, 0x0120, - 0x080c, 0x666e, 0x1904, 0x33b3, 0x080c, 0x6535, 0x0904, 0x33b0, - 0x2019, 0x0004, 0x900e, 0x080c, 0x64c2, 0x0904, 0x33b0, 0x7984, + 0x48e6, 0x81ff, 0x1904, 0x33d0, 0x080c, 0x48b1, 0x0904, 0x33d3, + 0x080c, 0x64d4, 0x0904, 0x33d0, 0x0058, 0xa878, 0x9005, 0x0120, + 0x2009, 0x0004, 0x0804, 0x33d0, 0xa974, 0xaa94, 0x0804, 0x339e, + 0x080c, 0x53b0, 0x0904, 0x339e, 0x701f, 0x433d, 0x7007, 0x0003, + 0x0005, 0x81ff, 0x1904, 0x33d0, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x33d3, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x080c, 0x668a, 0x0120, + 0x080c, 0x6692, 0x1904, 0x33d3, 0x080c, 0x6559, 0x0904, 0x33d0, + 0x2019, 0x0004, 0x900e, 0x080c, 0x64e6, 0x0904, 0x33d0, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, 0x12f8, 0x080c, - 0x48ab, 0x01e0, 0x080c, 0x6666, 0x0118, 0x080c, 0x666e, 0x11b0, - 0x080c, 0x6535, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, 0x2019, - 0x0004, 0x080c, 0x64c2, 0x2009, 0x0003, 0x0120, 0xa998, 0xaa9c, + 0x48cb, 0x01e0, 0x080c, 0x668a, 0x0118, 0x080c, 0x6692, 0x11b0, + 0x080c, 0x6559, 0x2009, 0x0002, 0x0168, 0x2009, 0x0002, 0x2019, + 0x0004, 0x080c, 0x64e6, 0x2009, 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x080c, 0x5390, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, + 0x080c, 0x53b0, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x6458, 0x2400, 0x9506, 0x0110, - 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x626b, 0x1138, - 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x8146, 0x0005, - 0x81ff, 0x1904, 0x33b0, 0x798c, 0x2001, 0x1950, 0x918c, 0x8000, - 0x2102, 0x080c, 0x4891, 0x0904, 0x33b3, 0x080c, 0x6666, 0x0120, - 0x080c, 0x666e, 0x1904, 0x33b3, 0x080c, 0x6332, 0x0904, 0x33b0, - 0x080c, 0x64b9, 0x0904, 0x33b0, 0x2001, 0x1950, 0x2004, 0xd0fc, - 0x1904, 0x337e, 0x0804, 0x4328, 0xa9a0, 0x2001, 0x1950, 0x918c, - 0x8000, 0xc18d, 0x2102, 0x080c, 0x489e, 0x01a0, 0x080c, 0x6666, - 0x0118, 0x080c, 0x666e, 0x1170, 0x080c, 0x6332, 0x2009, 0x0002, - 0x0128, 0x080c, 0x64b9, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, + 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x628f, 0x1138, + 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x817a, 0x0005, + 0x81ff, 0x1904, 0x33d0, 0x798c, 0x2001, 0x1958, 0x918c, 0x8000, + 0x2102, 0x080c, 0x48b1, 0x0904, 0x33d3, 0x080c, 0x668a, 0x0120, + 0x080c, 0x6692, 0x1904, 0x33d3, 0x080c, 0x6356, 0x0904, 0x33d0, + 0x080c, 0x64dd, 0x0904, 0x33d0, 0x2001, 0x1958, 0x2004, 0xd0fc, + 0x1904, 0x339e, 0x0804, 0x4348, 0xa9a0, 0x2001, 0x1958, 0x918c, + 0x8000, 0xc18d, 0x2102, 0x080c, 0x48be, 0x01a0, 0x080c, 0x668a, + 0x0118, 0x080c, 0x6692, 0x1170, 0x080c, 0x6356, 0x2009, 0x0002, + 0x0128, 0x080c, 0x64dd, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1950, 0x2004, 0xd0fc, - 0x1128, 0x080c, 0x5390, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x33b0, 0x798c, - 0x2001, 0x194f, 0x918c, 0x8000, 0x2102, 0x080c, 0x4891, 0x0904, - 0x33b3, 0x080c, 0x6666, 0x0120, 0x080c, 0x666e, 0x1904, 0x33b3, - 0x080c, 0x6332, 0x0904, 0x33b0, 0x080c, 0x64a7, 0x0904, 0x33b0, - 0x2001, 0x194f, 0x2004, 0xd0fc, 0x1904, 0x337e, 0x0804, 0x4328, - 0xa9a0, 0x2001, 0x194f, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x489e, 0x01a0, 0x080c, 0x6666, 0x0118, 0x080c, 0x666e, 0x1170, - 0x080c, 0x6332, 0x2009, 0x0002, 0x0128, 0x080c, 0x64a7, 0x1170, + 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1958, 0x2004, 0xd0fc, + 0x1128, 0x080c, 0x53b0, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, + 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, 0x33d0, 0x798c, + 0x2001, 0x1957, 0x918c, 0x8000, 0x2102, 0x080c, 0x48b1, 0x0904, + 0x33d3, 0x080c, 0x668a, 0x0120, 0x080c, 0x6692, 0x1904, 0x33d3, + 0x080c, 0x6356, 0x0904, 0x33d0, 0x080c, 0x64cb, 0x0904, 0x33d0, + 0x2001, 0x1957, 0x2004, 0xd0fc, 0x1904, 0x339e, 0x0804, 0x4348, + 0xa9a0, 0x2001, 0x1957, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, + 0x48be, 0x01a0, 0x080c, 0x668a, 0x0118, 0x080c, 0x6692, 0x1170, + 0x080c, 0x6356, 0x2009, 0x0002, 0x0128, 0x080c, 0x64cb, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x194f, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5390, 0x0110, + 0x2001, 0x1957, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x53b0, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x6100, 0x0804, 0x337e, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x080c, - 0x539c, 0x1904, 0x33b0, 0x79a8, 0xd184, 0x1158, 0xb834, 0x8007, + 0x6100, 0x0804, 0x339e, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x080c, + 0x53bc, 0x1904, 0x33d0, 0x79a8, 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, 0x789a, 0xbb1c, - 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, 0x337e, - 0x78a8, 0x909c, 0x0003, 0xd0b4, 0x1140, 0x939a, 0x0003, 0x1a04, - 0x33b0, 0x6258, 0x7884, 0x9206, 0x1560, 0x2031, 0x1848, 0x2009, - 0x013c, 0x2136, 0x2001, 0x1840, 0x2009, 0x000c, 0x7a8c, 0x7b88, + 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0200, 0x0804, 0x339e, + 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, 0x1140, 0x939a, + 0x0003, 0x1a04, 0x33d0, 0x6258, 0x7884, 0x9206, 0x1550, 0x2031, + 0x1848, 0x2009, 0x013c, 0x2136, 0x2001, 0x1840, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0006, 0x78a8, 0x9084, 0x0080, - 0x1118, 0x000e, 0x0804, 0x48c6, 0x000e, 0x2031, 0x0000, 0x2061, - 0x18ae, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x1117, 0x7007, 0x0002, 0x701f, 0x44e1, - 0x0005, 0x81ff, 0x1904, 0x33b0, 0x080c, 0x48ad, 0x0904, 0x33b3, - 0x080c, 0x6666, 0x1904, 0x33b0, 0x00c6, 0x080c, 0x487a, 0x00ce, - 0x0904, 0x33b0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, - 0x080c, 0xb9b7, 0x0904, 0x33b0, 0x7007, 0x0003, 0x701f, 0x44e5, - 0x0005, 0x080c, 0x4053, 0x0804, 0x337e, 0xa830, 0x9086, 0x0100, - 0x0904, 0x33b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, + 0x1118, 0x000e, 0x0804, 0x48e6, 0x000e, 0x2031, 0x0000, 0x2061, + 0x18b6, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, + 0xa496, 0xa59a, 0x080c, 0x1124, 0x7007, 0x0002, 0x701f, 0x4501, + 0x0005, 0x81ff, 0x1904, 0x33d0, 0x080c, 0x48cd, 0x0904, 0x33d3, + 0x080c, 0x668a, 0x1904, 0x33d0, 0x00c6, 0x080c, 0x489a, 0x00ce, + 0x0904, 0x33d0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, + 0x080c, 0xb9e5, 0x0904, 0x33d0, 0x7007, 0x0003, 0x701f, 0x4505, + 0x0005, 0x080c, 0x4073, 0x0804, 0x339e, 0xa830, 0x9086, 0x0100, + 0x0904, 0x33d0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x48c6, 0x9006, 0x080c, 0x24a6, 0x78a8, 0x9084, - 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x33b0, 0x080c, - 0x7096, 0x0110, 0x080c, 0x5c9c, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x33b3, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, - 0x33b3, 0x2100, 0x080c, 0x2470, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2061, 0x19d3, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, - 0x0000, 0x6077, 0x0000, 0x080c, 0x7096, 0x1158, 0x080c, 0x7396, - 0x080c, 0x5cd7, 0x9085, 0x0001, 0x080c, 0x70dd, 0x080c, 0x6fc7, - 0x00f0, 0x080c, 0x98bb, 0x080c, 0x9b60, 0x080c, 0x98d7, 0x2061, + 0x7d98, 0x0804, 0x48e6, 0x9006, 0x080c, 0x24c2, 0x78a8, 0x9084, + 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x33d0, 0x080c, + 0x70ba, 0x0110, 0x080c, 0x5cbc, 0x7888, 0x908a, 0x1000, 0x1a04, + 0x33d3, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, + 0x33d3, 0x2100, 0x080c, 0x248c, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2061, 0x19db, 0x601b, 0x0000, 0x601f, 0x0000, 0x6073, + 0x0000, 0x6077, 0x0000, 0x080c, 0x70ba, 0x1158, 0x080c, 0x73b9, + 0x080c, 0x5cf7, 0x9085, 0x0001, 0x080c, 0x7101, 0x080c, 0x6feb, + 0x00f0, 0x080c, 0x98c7, 0x080c, 0x9b6c, 0x080c, 0x98e3, 0x2061, 0x0100, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x810f, 0x9105, - 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1969, 0x200b, - 0x0000, 0x2009, 0x002d, 0x2011, 0x5bc2, 0x080c, 0x81fc, 0x7984, - 0x080c, 0x7096, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x438b, - 0x012e, 0x00ce, 0x002e, 0x0804, 0x337e, 0x7984, 0x080c, 0x620b, - 0x2b08, 0x1904, 0x33b3, 0x0804, 0x337e, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x33b0, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, - 0x2009, 0x0005, 0x0804, 0x33b0, 0x080c, 0x487a, 0x1120, 0x2009, - 0x0002, 0x0804, 0x33b0, 0x7984, 0x9192, 0x0021, 0x1a04, 0x33b3, + 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1971, 0x200b, + 0x0000, 0x2009, 0x002d, 0x2011, 0x5be2, 0x080c, 0x8230, 0x7984, + 0x080c, 0x70ba, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, 0x43ab, + 0x012e, 0x00ce, 0x002e, 0x0804, 0x339e, 0x7984, 0x080c, 0x622f, + 0x2b08, 0x1904, 0x33d3, 0x0804, 0x339e, 0x81ff, 0x0120, 0x2009, + 0x0001, 0x0804, 0x33d0, 0x60d8, 0xd0ac, 0x1130, 0xd09c, 0x1120, + 0x2009, 0x0005, 0x0804, 0x33d0, 0x080c, 0x489a, 0x1120, 0x2009, + 0x0002, 0x0804, 0x33d0, 0x7984, 0x9192, 0x0021, 0x1a04, 0x33d3, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, - 0xaf60, 0x7736, 0x080c, 0x48c3, 0x701f, 0x459d, 0x7880, 0x9086, - 0x006e, 0x0110, 0x701f, 0x4e3e, 0x0005, 0x2009, 0x0080, 0x080c, - 0x626b, 0x1118, 0x080c, 0x6666, 0x0120, 0x2021, 0x400a, 0x0804, - 0x3380, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, - 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, 0x4636, 0x90be, 0x0112, - 0x0904, 0x4636, 0x90be, 0x0113, 0x0904, 0x4636, 0x90be, 0x0114, - 0x0904, 0x4636, 0x90be, 0x0117, 0x0904, 0x4636, 0x90be, 0x011a, - 0x0904, 0x4636, 0x90be, 0x011c, 0x0904, 0x4636, 0x90be, 0x0121, - 0x0904, 0x461d, 0x90be, 0x0131, 0x0904, 0x461d, 0x90be, 0x0171, - 0x0904, 0x4636, 0x90be, 0x0173, 0x0904, 0x4636, 0x90be, 0x01a1, - 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, 0x4641, 0x90be, 0x0212, - 0x0904, 0x462a, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, + 0xaf60, 0x7736, 0x080c, 0x48e3, 0x701f, 0x45bd, 0x7880, 0x9086, + 0x006e, 0x0110, 0x701f, 0x4e5e, 0x0005, 0x2009, 0x0080, 0x080c, + 0x628f, 0x1118, 0x080c, 0x668a, 0x0120, 0x2021, 0x400a, 0x0804, + 0x33a0, 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, + 0xae7c, 0xa884, 0x90be, 0x0100, 0x0904, 0x4656, 0x90be, 0x0112, + 0x0904, 0x4656, 0x90be, 0x0113, 0x0904, 0x4656, 0x90be, 0x0114, + 0x0904, 0x4656, 0x90be, 0x0117, 0x0904, 0x4656, 0x90be, 0x011a, + 0x0904, 0x4656, 0x90be, 0x011c, 0x0904, 0x4656, 0x90be, 0x0121, + 0x0904, 0x463d, 0x90be, 0x0131, 0x0904, 0x463d, 0x90be, 0x0171, + 0x0904, 0x4656, 0x90be, 0x0173, 0x0904, 0x4656, 0x90be, 0x01a1, + 0x1128, 0xa894, 0x8007, 0xa896, 0x0804, 0x4661, 0x90be, 0x0212, + 0x0904, 0x464a, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, - 0x009e, 0x00de, 0x0804, 0x33b3, 0x7028, 0x9080, 0x0010, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x467f, + 0x009e, 0x00de, 0x0804, 0x33d3, 0x7028, 0x9080, 0x0010, 0x2098, + 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x469f, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0001, 0x080c, 0x467f, 0x00c8, 0x7028, 0x9080, 0x000c, + 0x20a9, 0x0001, 0x080c, 0x469f, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, - 0x468c, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x468c, 0x7028, 0x9080, + 0x46ac, 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, + 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x46ac, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, - 0x04f1, 0x00c6, 0x080c, 0x487a, 0x0550, 0xa868, 0xc0fd, 0xa86a, + 0x04f1, 0x00c6, 0x080c, 0x489a, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, - 0xa86a, 0xa804, 0x2048, 0x080c, 0xb9d2, 0x1120, 0x2009, 0x0003, - 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, 0x4676, 0x0005, 0x00ce, - 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, 0x33b0, 0xa820, 0x9086, - 0x8001, 0x1904, 0x337e, 0x2009, 0x0004, 0x0804, 0x33b0, 0x0016, + 0xa86a, 0xa804, 0x2048, 0x080c, 0xba00, 0x1120, 0x2009, 0x0003, + 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, 0x4696, 0x0005, 0x00ce, + 0x009e, 0x00de, 0x2009, 0x0002, 0x0804, 0x33d0, 0xa820, 0x9086, + 0x8001, 0x1904, 0x339e, 0x2009, 0x0004, 0x0804, 0x33d0, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x33b0, 0x60d8, 0xd0ac, 0x1160, - 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x33b0, 0xd09c, 0x1120, - 0x2009, 0x0005, 0x0804, 0x33b0, 0x7984, 0x78a8, 0x2040, 0x080c, - 0x9b59, 0x1120, 0x9182, 0x007f, 0x0a04, 0x33b3, 0x9186, 0x00ff, - 0x0904, 0x33b3, 0x9182, 0x0800, 0x1a04, 0x33b3, 0x7a8c, 0x7b88, - 0x6078, 0x9306, 0x1158, 0x607c, 0x924e, 0x0904, 0x33b3, 0x080c, - 0x9b59, 0x1120, 0x99cc, 0xff00, 0x0904, 0x33b3, 0x0126, 0x2091, - 0x8000, 0x0026, 0x2011, 0x8008, 0x080c, 0x668a, 0x002e, 0x0140, - 0x918d, 0x8000, 0x080c, 0x66d4, 0x1118, 0x2001, 0x4009, 0x0458, - 0x080c, 0x4794, 0x0560, 0x90c6, 0x4000, 0x1170, 0x00c6, 0x0006, - 0x900e, 0x080c, 0x655e, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, + 0x0120, 0x2009, 0x0001, 0x0804, 0x33d0, 0x60d8, 0xd0ac, 0x1160, + 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x33d0, 0xd09c, 0x1120, + 0x2009, 0x0005, 0x0804, 0x33d0, 0x7984, 0x78a8, 0x2040, 0x080c, + 0x9b65, 0x1120, 0x9182, 0x007f, 0x0a04, 0x33d3, 0x9186, 0x00ff, + 0x0904, 0x33d3, 0x9182, 0x0800, 0x1a04, 0x33d3, 0x7a8c, 0x7b88, + 0x6078, 0x9306, 0x1158, 0x607c, 0x924e, 0x0904, 0x33d3, 0x080c, + 0x9b65, 0x1120, 0x99cc, 0xff00, 0x0904, 0x33d3, 0x0126, 0x2091, + 0x8000, 0x0026, 0x2011, 0x8008, 0x080c, 0x66ae, 0x002e, 0x0140, + 0x918d, 0x8000, 0x080c, 0x66f8, 0x1118, 0x2001, 0x4009, 0x0458, + 0x080c, 0x47b4, 0x0560, 0x90c6, 0x4000, 0x1170, 0x00c6, 0x0006, + 0x900e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, - 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x3380, 0x2b00, - 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9c49, - 0x0904, 0x4761, 0x2b00, 0x6012, 0x080c, 0xbcdb, 0x2e58, 0x00ee, - 0x00e6, 0x00c6, 0x080c, 0x487a, 0x00ce, 0x2b70, 0x1158, 0x080c, - 0x9bda, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, - 0x0804, 0x33b0, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, - 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x080c, 0x300e, - 0x6023, 0x0001, 0x9006, 0x080c, 0x61a8, 0x2001, 0x0002, 0x080c, - 0x61bc, 0x2009, 0x0002, 0x080c, 0x9c76, 0x78a8, 0xd094, 0x0138, + 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x33a0, 0x2b00, + 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x9c55, + 0x0904, 0x4781, 0x2b00, 0x6012, 0x080c, 0xbd09, 0x2e58, 0x00ee, + 0x00e6, 0x00c6, 0x080c, 0x489a, 0x00ce, 0x2b70, 0x1158, 0x080c, + 0x9be6, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, + 0x0804, 0x33d0, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, + 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x080c, 0x302e, + 0x6023, 0x0001, 0x9006, 0x080c, 0x61cc, 0x2001, 0x0002, 0x080c, + 0x61e0, 0x2009, 0x0002, 0x080c, 0x9c82, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8c4, 0xc08d, 0xb8c6, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, - 0x0003, 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, 0x4770, 0x0005, + 0x0003, 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, 0x4790, 0x0005, 0xa830, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x3380, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, - 0xba04, 0x9294, 0x00ff, 0x0804, 0x52e5, 0x900e, 0xa868, 0xd0f4, - 0x1904, 0x337e, 0x080c, 0x655e, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x337e, 0x00e6, 0x00d6, 0x0096, 0x83ff, - 0x0904, 0x47dc, 0x902e, 0x080c, 0x9b59, 0x0130, 0x9026, 0x20a9, + 0x33a0, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, + 0xba04, 0x9294, 0x00ff, 0x0804, 0x5305, 0x900e, 0xa868, 0xd0f4, + 0x1904, 0x339e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x339e, 0x00e6, 0x00d6, 0x0096, 0x83ff, + 0x0904, 0x47fc, 0x902e, 0x080c, 0x9b65, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b0, 0x2100, 0x9406, 0x15e8, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1528, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x11f0, 0x93ce, 0x00ff, 0x11d8, 0xc5fd, 0x0450, 0x2058, 0xbf10, 0x2700, 0x9306, 0x11b8, 0xbe14, 0x2600, 0x9206, 0x1198, 0x2400, 0x9106, 0x1150, 0xd884, - 0x0568, 0xd894, 0x1558, 0x080c, 0x6666, 0x1540, 0x2001, 0x4000, + 0x0568, 0xd894, 0x1558, 0x080c, 0x668a, 0x1540, 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0948, 0x080c, - 0x9b59, 0x1930, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, - 0x47aa, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, - 0x0030, 0x080c, 0x620b, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, + 0x9b65, 0x1930, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, + 0x47ca, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, + 0x0030, 0x080c, 0x622f, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x33b0, 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, - 0x33b0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, - 0x0904, 0x33b3, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, - 0x33b3, 0x2010, 0x2918, 0x080c, 0x2fae, 0x1120, 0x2009, 0x0003, - 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, 0x482f, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1904, 0x337e, 0x2009, 0x0004, 0x0804, 0x33b0, - 0x7984, 0x080c, 0x9b59, 0x1120, 0x9182, 0x007f, 0x0a04, 0x33b3, - 0x9186, 0x00ff, 0x0904, 0x33b3, 0x9182, 0x0800, 0x1a04, 0x33b3, - 0x2001, 0x9000, 0x080c, 0x5340, 0x1904, 0x33b0, 0x0804, 0x337e, - 0xa998, 0x080c, 0x9b59, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, + 0x0804, 0x33d0, 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, + 0x33d0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, + 0x0904, 0x33d3, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, + 0x33d3, 0x2010, 0x2918, 0x080c, 0x2fce, 0x1120, 0x2009, 0x0003, + 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, 0x484f, 0x0005, 0xa830, + 0x9086, 0x0100, 0x1904, 0x339e, 0x2009, 0x0004, 0x0804, 0x33d0, + 0x7984, 0x080c, 0x9b65, 0x1120, 0x9182, 0x007f, 0x0a04, 0x33d3, + 0x9186, 0x00ff, 0x0904, 0x33d3, 0x9182, 0x0800, 0x1a04, 0x33d3, + 0x2001, 0x9000, 0x080c, 0x5360, 0x1904, 0x33d0, 0x0804, 0x339e, + 0xa998, 0x080c, 0x9b65, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9000, 0x080c, - 0x5340, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, + 0x5360, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, - 0x000a, 0x0c48, 0x080c, 0x1022, 0x0198, 0x9006, 0xa802, 0x7014, + 0x000a, 0x0c48, 0x080c, 0x102f, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, - 0x0005, 0x7984, 0x080c, 0x626b, 0x1130, 0x7e88, 0x9684, 0x3fff, + 0x0005, 0x7984, 0x080c, 0x628f, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, - 0x626b, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, + 0x628f, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, - 0x626b, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, - 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1054, 0x0cc8, 0x7116, + 0x628f, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, + 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1061, 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, - 0x2061, 0x18ae, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x1117, 0x7007, 0x0002, 0x701f, - 0x337e, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, - 0x2001, 0x18a6, 0x2004, 0x9005, 0x1190, 0x0e04, 0x48f7, 0x7a36, + 0x2061, 0x18b6, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, + 0xa392, 0xa496, 0xa59a, 0x080c, 0x1124, 0x7007, 0x0002, 0x701f, + 0x339e, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, + 0x2001, 0x18ae, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4917, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x0804, 0x495d, 0x0016, - 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x1894, 0x7044, 0x9005, + 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x0804, 0x497d, 0x0016, + 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189c, 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, - 0x1022, 0x0904, 0x4955, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, - 0x0002, 0x9080, 0x1d04, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, - 0x0004, 0x2001, 0x18b0, 0x9c82, 0x18f0, 0x0210, 0x2061, 0x18b0, + 0x102f, 0x0904, 0x4975, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, + 0x0002, 0x9080, 0x1d1c, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, + 0x0004, 0x2001, 0x18b8, 0x9c82, 0x18f8, 0x0210, 0x2061, 0x18b8, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d65, 0x2060, 0x001e, 0x8108, - 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x1022, 0x1130, 0x8109, + 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x102f, 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, - 0x9080, 0x1d04, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, + 0x9080, 0x1d1c, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, - 0x2c00, 0x9082, 0x001b, 0x0002, 0x497f, 0x497f, 0x4981, 0x497f, - 0x497f, 0x497f, 0x4985, 0x497f, 0x497f, 0x497f, 0x4989, 0x497f, - 0x497f, 0x497f, 0x498d, 0x497f, 0x497f, 0x497f, 0x4991, 0x497f, - 0x497f, 0x497f, 0x4995, 0x497f, 0x497f, 0x497f, 0x499a, 0x080c, + 0x2c00, 0x9082, 0x001b, 0x0002, 0x499f, 0x499f, 0x49a1, 0x499f, + 0x499f, 0x499f, 0x49a5, 0x499f, 0x499f, 0x499f, 0x49a9, 0x499f, + 0x499f, 0x499f, 0x49ad, 0x499f, 0x499f, 0x499f, 0x49b1, 0x499f, + 0x499f, 0x499f, 0x49b5, 0x499f, 0x499f, 0x499f, 0x49ba, 0x080c, 0x0d65, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, - 0x0804, 0x4958, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4958, 0x00e6, - 0x2071, 0x1894, 0x7048, 0x9005, 0x0904, 0x4a31, 0x0126, 0x2091, - 0x8000, 0x0e04, 0x4a30, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, + 0x0804, 0x4978, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4978, 0x00e6, + 0x2071, 0x189c, 0x7048, 0x9005, 0x0904, 0x4a51, 0x0126, 0x2091, + 0x8000, 0x0e04, 0x4a50, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d65, 0x2060, - 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4a33, 0xa804, + 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4a53, 0xa804, 0x9005, 0x090c, 0x0d65, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, - 0x2001, 0x0002, 0x9080, 0x1d04, 0x2005, 0xa04a, 0x0804, 0x4a33, + 0x2001, 0x0002, 0x9080, 0x1d1c, 0x2005, 0xa04a, 0x0804, 0x4a53, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x87ff, - 0x0118, 0x2748, 0x080c, 0x1054, 0x7048, 0x8001, 0x704a, 0x9005, - 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x1054, 0x9006, - 0x7042, 0x7046, 0x703b, 0x18b0, 0x703f, 0x18b0, 0x0420, 0x7040, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x87ff, + 0x0118, 0x2748, 0x080c, 0x1061, 0x7048, 0x8001, 0x704a, 0x9005, + 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x1061, 0x9006, + 0x7042, 0x7046, 0x703b, 0x18b8, 0x703f, 0x18b8, 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, - 0x90fa, 0x18f0, 0x0210, 0x2001, 0x18b0, 0x703e, 0x00a0, 0x9006, + 0x90fa, 0x18f8, 0x0210, 0x2001, 0x18b8, 0x703e, 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0d65, 0x2048, 0xa800, - 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1d04, + 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1d1c, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, - 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4a52, - 0x4a52, 0x4a54, 0x4a52, 0x4a52, 0x4a52, 0x4a59, 0x4a52, 0x4a52, - 0x4a52, 0x4a5e, 0x4a52, 0x4a52, 0x4a52, 0x4a63, 0x4a52, 0x4a52, - 0x4a52, 0x4a68, 0x4a52, 0x4a52, 0x4a52, 0x4a6d, 0x4a52, 0x4a52, - 0x4a52, 0x4a72, 0x080c, 0x0d65, 0xaa74, 0xab78, 0xac7c, 0x0804, - 0x49de, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x49de, 0xaa94, 0xab98, - 0xac9c, 0x0804, 0x49de, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x49de, - 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x49de, 0xaac4, 0xabc8, 0xaccc, - 0x0804, 0x49de, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x49de, 0x0026, - 0x080c, 0x5388, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x48da, - 0x002e, 0x0005, 0x81ff, 0x1904, 0x33b0, 0x0126, 0x2091, 0x8000, - 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x7096, 0x1158, - 0x080c, 0x7396, 0x080c, 0x5cd7, 0x9085, 0x0001, 0x080c, 0x70dd, - 0x080c, 0x6fc7, 0x0010, 0x080c, 0x5b92, 0x012e, 0x0804, 0x337e, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33b0, 0x080c, 0x539c, - 0x0120, 0x2009, 0x0007, 0x0804, 0x33b0, 0x080c, 0x665e, 0x0120, - 0x2009, 0x0008, 0x0804, 0x33b0, 0x0026, 0x2011, 0x0010, 0x080c, - 0x668a, 0x002e, 0x0140, 0x7984, 0x080c, 0x66d4, 0x1120, 0x2009, - 0x4009, 0x0804, 0x33b0, 0x7984, 0x080c, 0x620b, 0x1904, 0x33b3, - 0x2b00, 0x7026, 0x080c, 0x6666, 0x7888, 0x1170, 0x9084, 0x0005, - 0x1158, 0x900e, 0x080c, 0x655e, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x337e, 0x080c, 0x487a, 0x0904, 0x33b0, - 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xba79, - 0x0904, 0x33b0, 0x7888, 0xd094, 0x0118, 0xb8c4, 0xc08d, 0xb8c6, - 0x7007, 0x0003, 0x701f, 0x4b41, 0x0005, 0x2061, 0x1800, 0x080c, - 0x539c, 0x2009, 0x0007, 0x1578, 0x080c, 0x665e, 0x0118, 0x2009, - 0x0008, 0x0448, 0x080c, 0x3175, 0x0120, 0xa998, 0x080c, 0x620b, - 0x1530, 0x080c, 0x48ab, 0x0518, 0x080c, 0x6666, 0xa89c, 0x1168, - 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x655e, 0x1108, 0xc185, + 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4a72, + 0x4a72, 0x4a74, 0x4a72, 0x4a72, 0x4a72, 0x4a79, 0x4a72, 0x4a72, + 0x4a72, 0x4a7e, 0x4a72, 0x4a72, 0x4a72, 0x4a83, 0x4a72, 0x4a72, + 0x4a72, 0x4a88, 0x4a72, 0x4a72, 0x4a72, 0x4a8d, 0x4a72, 0x4a72, + 0x4a72, 0x4a92, 0x080c, 0x0d65, 0xaa74, 0xab78, 0xac7c, 0x0804, + 0x49fe, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x49fe, 0xaa94, 0xab98, + 0xac9c, 0x0804, 0x49fe, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x49fe, + 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x49fe, 0xaac4, 0xabc8, 0xaccc, + 0x0804, 0x49fe, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x49fe, 0x0026, + 0x080c, 0x53a8, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x48fa, + 0x002e, 0x0005, 0x81ff, 0x1904, 0x33d0, 0x0126, 0x2091, 0x8000, + 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x70ba, 0x1158, + 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x9085, 0x0001, 0x080c, 0x7101, + 0x080c, 0x6feb, 0x0010, 0x080c, 0x5bb2, 0x012e, 0x0804, 0x339e, + 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x33d0, 0x080c, 0x53bc, + 0x0120, 0x2009, 0x0007, 0x0804, 0x33d0, 0x080c, 0x6682, 0x0120, + 0x2009, 0x0008, 0x0804, 0x33d0, 0x0026, 0x2011, 0x0010, 0x080c, + 0x66ae, 0x002e, 0x0140, 0x7984, 0x080c, 0x66f8, 0x1120, 0x2009, + 0x4009, 0x0804, 0x33d0, 0x7984, 0x080c, 0x622f, 0x1904, 0x33d3, + 0x2b00, 0x7026, 0x080c, 0x668a, 0x7888, 0x1170, 0x9084, 0x0005, + 0x1158, 0x900e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x339e, 0x080c, 0x489a, 0x0904, 0x33d0, + 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbaa7, + 0x0904, 0x33d0, 0x7888, 0xd094, 0x0118, 0xb8c4, 0xc08d, 0xb8c6, + 0x7007, 0x0003, 0x701f, 0x4b61, 0x0005, 0x2061, 0x1800, 0x080c, + 0x53bc, 0x2009, 0x0007, 0x1578, 0x080c, 0x6682, 0x0118, 0x2009, + 0x0008, 0x0448, 0x080c, 0x3195, 0x0120, 0xa998, 0x080c, 0x622f, + 0x1530, 0x080c, 0x48cb, 0x0518, 0x080c, 0x668a, 0xa89c, 0x1168, + 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, - 0x080c, 0xba79, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8c4, 0xc08d, + 0x080c, 0xbaa7, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8c4, 0xc08d, 0xb8c6, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, 0xa830, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, - 0x0804, 0x3380, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, - 0x52e5, 0x900e, 0x080c, 0x655e, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x337e, 0x080c, 0x539c, 0x0120, 0x2009, - 0x0007, 0x0804, 0x33b0, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, 0x900e, + 0x0804, 0x33a0, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, + 0x5305, 0x900e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0x0804, 0x339e, 0x080c, 0x53bc, 0x0120, 0x2009, + 0x0007, 0x0804, 0x33d0, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, + 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, - 0x0005, 0x702a, 0x20a0, 0x080c, 0x626b, 0x1904, 0x4bdf, 0x080c, - 0x6666, 0x0120, 0x080c, 0x666e, 0x1904, 0x4bdf, 0x080c, 0x665e, - 0x1130, 0x080c, 0x655e, 0x1118, 0xd79c, 0x0904, 0x4bdf, 0xd794, + 0x0005, 0x702a, 0x20a0, 0x080c, 0x628f, 0x1904, 0x4bff, 0x080c, + 0x668a, 0x0120, 0x080c, 0x6692, 0x1904, 0x4bff, 0x080c, 0x6682, + 0x1130, 0x080c, 0x6582, 0x1118, 0xd79c, 0x0904, 0x4bff, 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x3400, 0xd794, 0x0160, 0x20a9, 0x0008, 0x4003, 0x2098, - 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x468c, 0x0048, + 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x46ac, 0x0048, 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, - 0x468c, 0x4104, 0xd794, 0x0528, 0xb8b4, 0x20e0, 0xb8b8, 0x2060, + 0x46ac, 0x4104, 0xd794, 0x0528, 0xb8b4, 0x20e0, 0xb8b8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, - 0x467f, 0x9c80, 0x0026, 0x2098, 0xb8b4, 0x20e0, 0x20a9, 0x0002, + 0x469f, 0x9c80, 0x0026, 0x2098, 0xb8b4, 0x20e0, 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, - 0x080c, 0x9b59, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, + 0x080c, 0x9b65, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, - 0x4b7b, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x337e, 0x7033, - 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18ae, + 0x4b9b, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x339e, 0x7033, + 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, - 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x1117, 0x7007, 0x0002, - 0x701f, 0x4c1b, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, - 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18ae, 0x2c44, - 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4b7b, 0x7124, 0x810b, - 0x0804, 0x337e, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, - 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33b3, 0x9502, - 0x0a04, 0x33b3, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x33b3, - 0x9502, 0x0a04, 0x33b3, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x33b3, 0x9502, 0x0a04, 0x33b3, 0x9284, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x33b3, 0x9502, 0x0a04, 0x33b3, 0x9384, 0xff00, - 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33b3, 0x9502, 0x0a04, 0x33b3, - 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x33b3, 0x9502, 0x0a04, - 0x33b3, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33b3, - 0x9502, 0x0a04, 0x33b3, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, - 0x33b3, 0x9502, 0x0a04, 0x33b3, 0x2061, 0x1959, 0x6102, 0x6206, - 0x630a, 0x640e, 0x0804, 0x337e, 0x0006, 0x080c, 0x5388, 0xd0cc, - 0x000e, 0x0005, 0x0006, 0x080c, 0x538c, 0xd0bc, 0x000e, 0x0005, - 0x6170, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x337e, - 0x83ff, 0x1904, 0x33b3, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x33b3, - 0x2019, 0xffff, 0x6074, 0x9302, 0x9200, 0x0a04, 0x33b3, 0x7986, - 0x6272, 0x0804, 0x337e, 0x080c, 0x539c, 0x1904, 0x33b0, 0x7c88, - 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x487a, 0x0904, 0x33b0, 0x900e, + 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x1124, 0x7007, 0x0002, + 0x701f, 0x4c3b, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, + 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b6, 0x2c44, + 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4b9b, 0x7124, 0x810b, + 0x0804, 0x339e, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, + 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33d3, 0x9502, + 0x0a04, 0x33d3, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x33d3, + 0x9502, 0x0a04, 0x33d3, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, + 0x0a04, 0x33d3, 0x9502, 0x0a04, 0x33d3, 0x9284, 0x00ff, 0x90e2, + 0x0020, 0x0a04, 0x33d3, 0x9502, 0x0a04, 0x33d3, 0x9384, 0xff00, + 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33d3, 0x9502, 0x0a04, 0x33d3, + 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x33d3, 0x9502, 0x0a04, + 0x33d3, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x33d3, + 0x9502, 0x0a04, 0x33d3, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, + 0x33d3, 0x9502, 0x0a04, 0x33d3, 0x2061, 0x1961, 0x6102, 0x6206, + 0x630a, 0x640e, 0x0804, 0x339e, 0x0006, 0x080c, 0x53a8, 0xd0cc, + 0x000e, 0x0005, 0x0006, 0x080c, 0x53ac, 0xd0bc, 0x000e, 0x0005, + 0x6170, 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x339e, + 0x83ff, 0x1904, 0x33d3, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x33d3, + 0x2019, 0xffff, 0x6074, 0x9302, 0x9200, 0x0a04, 0x33d3, 0x7986, + 0x6272, 0x0804, 0x339e, 0x080c, 0x53bc, 0x1904, 0x33d0, 0x7c88, + 0x7d84, 0x7e98, 0x7f8c, 0x080c, 0x489a, 0x0904, 0x33d0, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, - 0x080c, 0x6666, 0x0118, 0x080c, 0x666e, 0x1148, 0x20a9, 0x0001, + 0x080c, 0x668a, 0x0118, 0x080c, 0x6692, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, - 0x1148, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x83fb, 0x2208, - 0x0804, 0x337e, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, - 0x2061, 0x18ae, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, - 0x7034, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x1117, - 0x7007, 0x0002, 0x701f, 0x4d0d, 0x0005, 0x7030, 0x9005, 0x1178, - 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18ae, - 0x2c44, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x4ccb, 0x7224, - 0x900e, 0x2001, 0x0003, 0x080c, 0x83fb, 0x2208, 0x0804, 0x337e, - 0x00f6, 0x00e6, 0x080c, 0x539c, 0x2009, 0x0007, 0x1904, 0x4da0, - 0x2071, 0x1894, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x4da0, - 0xac9c, 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x103b, 0x2009, - 0x0002, 0x0904, 0x4da0, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, + 0x1148, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x842f, 0x2208, + 0x0804, 0x339e, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, + 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, + 0x7034, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x1124, + 0x7007, 0x0002, 0x701f, 0x4d2d, 0x0005, 0x7030, 0x9005, 0x1178, + 0x7120, 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b6, + 0x2c44, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x4ceb, 0x7224, + 0x900e, 0x2001, 0x0003, 0x080c, 0x842f, 0x2208, 0x0804, 0x339e, + 0x00f6, 0x00e6, 0x080c, 0x53bc, 0x2009, 0x0007, 0x1904, 0x4dc0, + 0x2071, 0x189c, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x4dc0, + 0xac9c, 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1048, 0x2009, + 0x0002, 0x0904, 0x4dc0, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, - 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6666, 0x0118, - 0x080c, 0x666e, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, + 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x668a, 0x0118, + 0x080c, 0x6692, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, - 0x2001, 0x0003, 0x080c, 0x83fb, 0x2208, 0x009e, 0xa897, 0x4000, - 0xa99a, 0x715c, 0x81ff, 0x090c, 0x0d65, 0x2148, 0x080c, 0x1054, + 0x2001, 0x0003, 0x080c, 0x842f, 0x2208, 0x009e, 0xa897, 0x4000, + 0xa99a, 0x715c, 0x81ff, 0x090c, 0x0d65, 0x2148, 0x080c, 0x1061, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, - 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18af, 0x2c44, 0xa37a, + 0x7152, 0x7054, 0x9300, 0x7056, 0x2061, 0x18b7, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, - 0xa09f, 0x4dac, 0x000e, 0xa0a2, 0x080c, 0x1117, 0x9006, 0x0048, + 0xa09f, 0x4dcc, 0x000e, 0xa0a2, 0x080c, 0x1124, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, - 0x0d65, 0x00e6, 0x2071, 0x1894, 0xa06c, 0x908e, 0x0100, 0x0138, + 0x0d65, 0x00e6, 0x2071, 0x189c, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, - 0x83fb, 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0d65, 0x2148, 0x080c, - 0x1054, 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6991, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, + 0x842f, 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0d65, 0x2148, 0x080c, + 0x1061, 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, + 0x080c, 0x69b5, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, - 0x6666, 0x0118, 0x080c, 0x666e, 0x1148, 0xb814, 0x20a9, 0x0001, + 0x668a, 0x0118, 0x080c, 0x6692, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, - 0x0d65, 0x2148, 0x080c, 0x1054, 0x9006, 0x705e, 0x918d, 0x0001, - 0x2008, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6991, + 0x0d65, 0x2148, 0x080c, 0x1061, 0x9006, 0x705e, 0x918d, 0x0001, + 0x2008, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x69b5, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, - 0xa79a, 0x080c, 0x1117, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, + 0xa79a, 0x080c, 0x1124, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, - 0x0118, 0x009e, 0x0804, 0x33b3, 0xa884, 0xa988, 0x080c, 0x243d, - 0x1518, 0x080c, 0x620b, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, - 0x080c, 0x487a, 0x01c8, 0x080c, 0x487a, 0x01b0, 0x009e, 0xa867, + 0x0118, 0x009e, 0x0804, 0x33d3, 0xa884, 0xa988, 0x080c, 0x2459, + 0x1518, 0x080c, 0x622f, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, + 0x080c, 0x489a, 0x01c8, 0x080c, 0x489a, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, - 0x080c, 0xb9f2, 0x1120, 0x2009, 0x0003, 0x0804, 0x33b0, 0x7007, - 0x0003, 0x701f, 0x4e79, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, - 0x33b0, 0x7124, 0x080c, 0x3116, 0xa820, 0x9086, 0x8001, 0x1120, - 0x2009, 0x0004, 0x0804, 0x33b0, 0x2900, 0x7022, 0xa804, 0x0096, + 0x080c, 0xba20, 0x1120, 0x2009, 0x0003, 0x0804, 0x33d0, 0x7007, + 0x0003, 0x701f, 0x4e99, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, + 0x33d0, 0x7124, 0x080c, 0x3136, 0xa820, 0x9086, 0x8001, 0x1120, + 0x2009, 0x0004, 0x0804, 0x33d0, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, - 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0f9f, 0xaa6c, 0xab70, 0xac74, - 0xad78, 0x2061, 0x18ae, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, + 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0fac, 0xaa6c, 0xab70, 0xac74, + 0xad78, 0x2061, 0x18b6, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, - 0x0600, 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x48c6, 0x97c6, + 0x0600, 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x48e6, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, - 0x18ae, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x1117, 0x7007, 0x0002, 0x701f, 0x4ed5, - 0x0005, 0x000e, 0x007e, 0x0804, 0x33b3, 0x7020, 0x2048, 0xa804, + 0x18b6, 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, + 0xa496, 0xa59a, 0x080c, 0x1124, 0x7007, 0x0002, 0x701f, 0x4ef5, + 0x0005, 0x000e, 0x007e, 0x0804, 0x33d3, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, - 0x20a9, 0x002a, 0x080c, 0x0f9f, 0x2100, 0x2238, 0x2061, 0x18ae, + 0x20a9, 0x002a, 0x080c, 0x0fac, 0x2100, 0x2238, 0x2061, 0x18b6, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, - 0x48c6, 0x81ff, 0x1904, 0x33b0, 0x798c, 0x2001, 0x194e, 0x918c, - 0x8000, 0x2102, 0x080c, 0x4891, 0x0904, 0x33b3, 0x080c, 0x6666, - 0x0120, 0x080c, 0x666e, 0x1904, 0x33b3, 0x080c, 0x6332, 0x0904, - 0x33b0, 0x0126, 0x2091, 0x8000, 0x080c, 0x64cb, 0x012e, 0x0904, - 0x33b0, 0x2001, 0x194e, 0x2004, 0xd0fc, 0x1904, 0x337e, 0x0804, - 0x4328, 0xa9a0, 0x2001, 0x194e, 0x918c, 0x8000, 0xc18d, 0x2102, - 0x080c, 0x489e, 0x01a0, 0x080c, 0x6666, 0x0118, 0x080c, 0x666e, - 0x1170, 0x080c, 0x6332, 0x2009, 0x0002, 0x0128, 0x080c, 0x64cb, + 0x48e6, 0x81ff, 0x1904, 0x33d0, 0x798c, 0x2001, 0x1956, 0x918c, + 0x8000, 0x2102, 0x080c, 0x48b1, 0x0904, 0x33d3, 0x080c, 0x668a, + 0x0120, 0x080c, 0x6692, 0x1904, 0x33d3, 0x080c, 0x6356, 0x0904, + 0x33d0, 0x0126, 0x2091, 0x8000, 0x080c, 0x64ef, 0x012e, 0x0904, + 0x33d0, 0x2001, 0x1956, 0x2004, 0xd0fc, 0x1904, 0x339e, 0x0804, + 0x4348, 0xa9a0, 0x2001, 0x1956, 0x918c, 0x8000, 0xc18d, 0x2102, + 0x080c, 0x48be, 0x01a0, 0x080c, 0x668a, 0x0118, 0x080c, 0x6692, + 0x1170, 0x080c, 0x6356, 0x2009, 0x0002, 0x0128, 0x080c, 0x64ef, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, - 0x4000, 0x2001, 0x194e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5390, + 0x4000, 0x2001, 0x1956, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x53b0, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x429d, 0x080c, - 0x48ad, 0x0904, 0x33b3, 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, - 0x0804, 0x33b0, 0x080c, 0x6666, 0x0130, 0x908e, 0x0004, 0x0118, + 0x0005, 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x42bd, 0x080c, + 0x48cd, 0x0904, 0x33d3, 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, + 0x0804, 0x33d0, 0x080c, 0x668a, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, - 0xb802, 0x0028, 0x080c, 0x5388, 0xd0b4, 0x0904, 0x42d7, 0x7884, - 0x908e, 0x007e, 0x0904, 0x42d7, 0x908e, 0x007f, 0x0904, 0x42d7, - 0x908e, 0x0080, 0x0904, 0x42d7, 0xb800, 0xd08c, 0x1904, 0x42d7, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xba11, 0x1120, - 0x2009, 0x0003, 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, 0x4fa1, - 0x0005, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x0804, 0x42d7, 0x080c, - 0x3175, 0x0108, 0x0005, 0x2009, 0x1833, 0x210c, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x33b0, 0x080c, 0x539c, 0x0120, 0x2009, - 0x0007, 0x0804, 0x33b0, 0x080c, 0x665e, 0x0120, 0x2009, 0x0008, - 0x0804, 0x33b0, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x42d7, - 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xba79, - 0x1120, 0x2009, 0x0003, 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, - 0x4fda, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, - 0x0804, 0x52e5, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x0804, 0x4f73, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x33b0, 0x080c, 0x539c, 0x2009, - 0x0007, 0x1904, 0x33b0, 0x080c, 0x665e, 0x0120, 0x2009, 0x0008, - 0x0804, 0x33b0, 0x080c, 0x48ad, 0x0904, 0x33b3, 0x080c, 0x6666, - 0x2009, 0x0009, 0x1904, 0x33b0, 0x080c, 0x487a, 0x2009, 0x0002, - 0x0904, 0x33b0, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, + 0xb802, 0x0028, 0x080c, 0x53a8, 0xd0b4, 0x0904, 0x42f7, 0x7884, + 0x908e, 0x007e, 0x0904, 0x42f7, 0x908e, 0x007f, 0x0904, 0x42f7, + 0x908e, 0x0080, 0x0904, 0x42f7, 0xb800, 0xd08c, 0x1904, 0x42f7, + 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xba3f, 0x1120, + 0x2009, 0x0003, 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, 0x4fc1, + 0x0005, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x0804, 0x42f7, 0x080c, + 0x3195, 0x0108, 0x0005, 0x2009, 0x1833, 0x210c, 0x81ff, 0x0120, + 0x2009, 0x0001, 0x0804, 0x33d0, 0x080c, 0x53bc, 0x0120, 0x2009, + 0x0007, 0x0804, 0x33d0, 0x080c, 0x6682, 0x0120, 0x2009, 0x0008, + 0x0804, 0x33d0, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x42f7, + 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xbaa7, + 0x1120, 0x2009, 0x0003, 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, + 0x4ffa, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, + 0x0804, 0x5305, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x0804, 0x4f93, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x33d0, 0x080c, 0x53bc, 0x2009, + 0x0007, 0x1904, 0x33d0, 0x080c, 0x6682, 0x0120, 0x2009, 0x0008, + 0x0804, 0x33d0, 0x080c, 0x48cd, 0x0904, 0x33d3, 0x080c, 0x668a, + 0x2009, 0x0009, 0x1904, 0x33d0, 0x080c, 0x489a, 0x2009, 0x0002, + 0x0904, 0x33d0, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0x9194, 0xff00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, - 0x33b3, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xbcdc, 0x2009, - 0x0003, 0x0904, 0x33b0, 0x7007, 0x0003, 0x701f, 0x5030, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x33b0, 0x0804, - 0x337e, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, - 0x539c, 0x1188, 0x2009, 0x0014, 0x0804, 0x33b0, 0xd2dc, 0x1568, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x33b0, 0x080c, 0x539c, 0x2009, - 0x0007, 0x1904, 0x33b0, 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, - 0x5363, 0x0804, 0x337e, 0xd2fc, 0x0158, 0x080c, 0x48ad, 0x0904, - 0x33b3, 0x7984, 0x9284, 0x9000, 0x080c, 0x5340, 0x0804, 0x337e, - 0x080c, 0x48ad, 0x0904, 0x33b3, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x2009, 0x0009, 0x1904, 0x5119, 0x080c, 0x487a, 0x2009, - 0x0002, 0x0904, 0x5119, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, - 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x48c3, 0x701f, - 0x508a, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, - 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x33b3, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x48ad, 0x1110, 0x0804, - 0x33b3, 0x2009, 0x0043, 0x080c, 0xbd44, 0x2009, 0x0003, 0x0904, - 0x5119, 0x7007, 0x0003, 0x701f, 0x50ae, 0x0005, 0xa830, 0x9086, - 0x0100, 0x2009, 0x0004, 0x0904, 0x5119, 0x7984, 0x7aa8, 0x9284, - 0x1000, 0x080c, 0x5340, 0x0804, 0x337e, 0x00c6, 0xaab0, 0x9284, - 0xc000, 0x0140, 0xd2ec, 0x0168, 0x080c, 0x539c, 0x1150, 0x2009, - 0x0014, 0x04f0, 0x2061, 0x1800, 0x080c, 0x539c, 0x2009, 0x0007, - 0x15b8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, 0x5363, 0x0050, - 0xd2fc, 0x0178, 0x080c, 0x48ab, 0x0588, 0xa998, 0x9284, 0x9000, - 0x080c, 0x5340, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, - 0x0438, 0x080c, 0x48ab, 0x0510, 0x080c, 0x6666, 0x2009, 0x0009, + 0x33d3, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xbd0a, 0x2009, + 0x0003, 0x0904, 0x33d0, 0x7007, 0x0003, 0x701f, 0x5050, 0x0005, + 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x33d0, 0x0804, + 0x339e, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, + 0x53bc, 0x1188, 0x2009, 0x0014, 0x0804, 0x33d0, 0xd2dc, 0x1568, + 0x81ff, 0x2009, 0x0001, 0x1904, 0x33d0, 0x080c, 0x53bc, 0x2009, + 0x0007, 0x1904, 0x33d0, 0xd2f4, 0x0130, 0x9284, 0x5000, 0x080c, + 0x5383, 0x0804, 0x339e, 0xd2fc, 0x0158, 0x080c, 0x48cd, 0x0904, + 0x33d3, 0x7984, 0x9284, 0x9000, 0x080c, 0x5360, 0x0804, 0x339e, + 0x080c, 0x48cd, 0x0904, 0x33d3, 0xb804, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x2009, 0x0009, 0x1904, 0x5139, 0x080c, 0x489a, 0x2009, + 0x0002, 0x0904, 0x5139, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, + 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x48e3, 0x701f, + 0x50aa, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, + 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x33d3, 0xa866, + 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x48cd, 0x1110, 0x0804, + 0x33d3, 0x2009, 0x0043, 0x080c, 0xbd72, 0x2009, 0x0003, 0x0904, + 0x5139, 0x7007, 0x0003, 0x701f, 0x50ce, 0x0005, 0xa830, 0x9086, + 0x0100, 0x2009, 0x0004, 0x0904, 0x5139, 0x7984, 0x7aa8, 0x9284, + 0x1000, 0x080c, 0x5360, 0x0804, 0x339e, 0x00c6, 0xaab0, 0x9284, + 0xc000, 0x0140, 0xd2ec, 0x0168, 0x080c, 0x53bc, 0x1150, 0x2009, + 0x0014, 0x04f0, 0x2061, 0x1800, 0x080c, 0x53bc, 0x2009, 0x0007, + 0x15b8, 0xd2f4, 0x0128, 0x9284, 0x5000, 0x080c, 0x5383, 0x0050, + 0xd2fc, 0x0178, 0x080c, 0x48cb, 0x0588, 0xa998, 0x9284, 0x9000, + 0x080c, 0x5360, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, + 0x0438, 0x080c, 0x48cb, 0x0510, 0x080c, 0x668a, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, - 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, 0x48ab, 0x1108, 0x0070, - 0x2009, 0x004b, 0x080c, 0xbd44, 0x2009, 0x0003, 0x0108, 0x0078, + 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, 0x48cb, 0x1108, 0x0070, + 0x2009, 0x004b, 0x080c, 0xbd72, 0x2009, 0x0003, 0x0108, 0x0078, 0x0429, 0x19c0, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, - 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x33b0, 0x0016, 0x7984, 0x9284, - 0x1000, 0xc0fd, 0x080c, 0x5340, 0x001e, 0x1904, 0x33b0, 0x0804, - 0x337e, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0xaab0, 0xd2dc, - 0x0150, 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5340, + 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x33d0, 0x0016, 0x7984, 0x9284, + 0x1000, 0xc0fd, 0x080c, 0x5360, 0x001e, 0x1904, 0x33d0, 0x0804, + 0x339e, 0x00f6, 0x2d78, 0x0011, 0x00fe, 0x0005, 0xaab0, 0xd2dc, + 0x0150, 0x0016, 0xa998, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5360, 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x33b0, 0x080c, 0x539c, 0x0120, 0x2009, 0x0007, 0x0804, - 0x33b0, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x626b, 0x1904, - 0x33b3, 0x9186, 0x007f, 0x0138, 0x080c, 0x6666, 0x0120, 0x2009, - 0x0009, 0x0804, 0x33b0, 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, - 0x0804, 0x33b0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, - 0x0100, 0x8007, 0xa80a, 0x080c, 0xba2b, 0x1120, 0x2009, 0x0003, - 0x0804, 0x33b0, 0x7007, 0x0003, 0x701f, 0x5177, 0x0005, 0xa808, - 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x33b0, + 0x0804, 0x33d0, 0x080c, 0x53bc, 0x0120, 0x2009, 0x0007, 0x0804, + 0x33d0, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x628f, 0x1904, + 0x33d3, 0x9186, 0x007f, 0x0138, 0x080c, 0x668a, 0x0120, 0x2009, + 0x0009, 0x0804, 0x33d0, 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, + 0x0804, 0x33d0, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, + 0x0100, 0x8007, 0xa80a, 0x080c, 0xba59, 0x1120, 0x2009, 0x0003, + 0x0804, 0x33d0, 0x7007, 0x0003, 0x701f, 0x5197, 0x0005, 0xa808, + 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x33d0, 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48c6, 0x080c, 0x487a, - 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, 0x7984, 0x9194, 0xff00, - 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x1983, 0x0040, - 0x92c6, 0x0001, 0x1118, 0x7023, 0x199d, 0x0010, 0x0804, 0x33b3, + 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x48e6, 0x080c, 0x489a, + 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, 0x7984, 0x9194, 0xff00, + 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x198b, 0x0040, + 0x92c6, 0x0001, 0x1118, 0x7023, 0x19a5, 0x0010, 0x0804, 0x33d3, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x48c3, 0x701f, 0x51c7, 0x0005, 0x2001, + 0x0019, 0xaf60, 0x080c, 0x48e3, 0x701f, 0x51e7, 0x0005, 0x2001, 0x182d, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, - 0x0804, 0x337e, 0x080c, 0x487a, 0x1120, 0x2009, 0x0002, 0x0804, - 0x33b0, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x1118, 0x2099, 0x1983, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, - 0x199d, 0x0010, 0x0804, 0x33b3, 0xa85c, 0x9080, 0x0019, 0x20a0, + 0x0804, 0x339e, 0x080c, 0x489a, 0x1120, 0x2009, 0x0002, 0x0804, + 0x33d0, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, + 0x1118, 0x2099, 0x198b, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, + 0x19a5, 0x0010, 0x0804, 0x33d3, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x0804, 0x48c6, 0x7884, 0x908a, 0x1000, 0x1a04, 0x33b3, + 0xaf60, 0x0804, 0x48e6, 0x7884, 0x908a, 0x1000, 0x1a04, 0x33d3, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, - 0x2061, 0x19d3, 0x6142, 0x00ce, 0x012e, 0x0804, 0x337e, 0x00c6, - 0x080c, 0x7096, 0x1160, 0x080c, 0x7396, 0x080c, 0x5cd7, 0x9085, - 0x0001, 0x080c, 0x70dd, 0x080c, 0x6fc7, 0x080c, 0x0d65, 0x2061, - 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5b92, 0x00ce, 0x0005, - 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x33b0, - 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x196c, 0x2c0c, 0x2062, - 0x080c, 0x2820, 0x01a0, 0x080c, 0x2828, 0x0188, 0x080c, 0x2830, - 0x0170, 0x2162, 0x0804, 0x33b3, 0x2061, 0x0100, 0x6038, 0x9086, + 0x2061, 0x19db, 0x6142, 0x00ce, 0x012e, 0x0804, 0x339e, 0x00c6, + 0x080c, 0x70ba, 0x1160, 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x9085, + 0x0001, 0x080c, 0x7101, 0x080c, 0x6feb, 0x080c, 0x0d65, 0x2061, + 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5bb2, 0x00ce, 0x0005, + 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x33d0, + 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x1974, 0x2c0c, 0x2062, + 0x080c, 0x2840, 0x01a0, 0x080c, 0x2848, 0x0188, 0x080c, 0x2850, + 0x0170, 0x2162, 0x0804, 0x33d3, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x1588, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, - 0x080c, 0x98bb, 0x0026, 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, - 0x0002, 0x080c, 0x9326, 0x002e, 0x080c, 0x91e9, 0x0036, 0x901e, - 0x080c, 0x9269, 0x003e, 0x080c, 0x98d7, 0x60e3, 0x0000, 0x080c, - 0xd60c, 0x080c, 0xd627, 0x9085, 0x0001, 0x080c, 0x70dd, 0x9006, - 0x080c, 0x2852, 0x2001, 0x1800, 0x2003, 0x0004, 0x0026, 0x2011, - 0x0008, 0x080c, 0x288c, 0x002e, 0x00ce, 0x0804, 0x337e, 0x81ff, - 0x0120, 0x2009, 0x0001, 0x0804, 0x33b0, 0x080c, 0x539c, 0x0120, - 0x2009, 0x0007, 0x0804, 0x33b0, 0x7984, 0x7ea8, 0x96b4, 0x00ff, - 0x080c, 0x626b, 0x1904, 0x33b3, 0x9186, 0x007f, 0x0138, 0x080c, - 0x6666, 0x0120, 0x2009, 0x0009, 0x0804, 0x33b0, 0x080c, 0x487a, - 0x1120, 0x2009, 0x0002, 0x0804, 0x33b0, 0xa867, 0x0000, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xba2e, 0x1120, 0x2009, 0x0003, 0x0804, - 0x33b0, 0x7007, 0x0003, 0x701f, 0x52ce, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x33b0, 0xa8e0, 0xa866, + 0x080c, 0x98c7, 0x0026, 0x2011, 0x0003, 0x080c, 0x9324, 0x2011, + 0x0002, 0x080c, 0x932e, 0x002e, 0x080c, 0x921d, 0x0036, 0x901e, + 0x080c, 0x929d, 0x003e, 0x080c, 0x98e3, 0x60e3, 0x0000, 0x080c, + 0xd644, 0x080c, 0xd65f, 0x9085, 0x0001, 0x080c, 0x7101, 0x9006, + 0x080c, 0x2872, 0x2001, 0x1800, 0x2003, 0x0004, 0x0026, 0x2011, + 0x0008, 0x080c, 0x28ac, 0x002e, 0x00ce, 0x0804, 0x339e, 0x81ff, + 0x0120, 0x2009, 0x0001, 0x0804, 0x33d0, 0x080c, 0x53bc, 0x0120, + 0x2009, 0x0007, 0x0804, 0x33d0, 0x7984, 0x7ea8, 0x96b4, 0x00ff, + 0x080c, 0x628f, 0x1904, 0x33d3, 0x9186, 0x007f, 0x0138, 0x080c, + 0x668a, 0x0120, 0x2009, 0x0009, 0x0804, 0x33d0, 0x080c, 0x489a, + 0x1120, 0x2009, 0x0002, 0x0804, 0x33d0, 0xa867, 0x0000, 0xa868, + 0xc0fd, 0xa86a, 0x080c, 0xba5c, 0x1120, 0x2009, 0x0003, 0x0804, + 0x33d0, 0x7007, 0x0003, 0x701f, 0x52ee, 0x0005, 0xa830, 0x9086, + 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x33d0, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x48c6, 0xa898, 0x9086, 0x000d, - 0x1904, 0x33b0, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x52f2, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, + 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x48e6, 0xa898, 0x9086, 0x000d, + 0x1904, 0x33d0, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, 0x0e04, + 0x5312, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, 0xa998, - 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x48b6, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x7007, + 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x48d6, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x2061, 0x19d3, 0x7984, 0x6152, 0x614e, + 0x2091, 0x8000, 0x00c6, 0x2061, 0x19db, 0x7984, 0x6152, 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7898, 0x606a, 0x789c, 0x6066, - 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x19e1, 0x2044, 0x2001, - 0x19e8, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, - 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, 0x337e, + 0x7888, 0x6062, 0x788c, 0x605e, 0x2001, 0x19e9, 0x2044, 0x2001, + 0x19f0, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, 0x0002, + 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, 0x339e, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, 0x0128, - 0x0006, 0x080c, 0xb88f, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, - 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x5cf1, 0x080c, 0x9b59, + 0x0006, 0x080c, 0xb8bd, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, + 0x1000, 0x2004, 0x905d, 0x0160, 0x080c, 0x5d11, 0x080c, 0x9b65, 0x0110, 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0180, 0x9186, 0x007e, 0x0168, 0x9186, 0x007f, 0x0150, 0x9186, 0x0080, 0x0138, 0x9186, 0x00ff, 0x0120, 0x0026, 0x2200, 0x0801, - 0x002e, 0x001e, 0x8108, 0x1f04, 0x536b, 0x015e, 0x012e, 0x0005, - 0x2001, 0x1854, 0x2004, 0x0005, 0x2001, 0x1873, 0x2004, 0x0005, + 0x002e, 0x001e, 0x8108, 0x1f04, 0x538b, 0x015e, 0x012e, 0x0005, + 0x2001, 0x185c, 0x2004, 0x0005, 0x2001, 0x187b, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1894, 0x7108, 0x910d, + 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189c, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x9182, 0x0081, 0x1a04, - 0x33b3, 0x810c, 0x0016, 0x080c, 0x487a, 0x080c, 0x0f2a, 0x2100, - 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x48c3, - 0x701f, 0x53c3, 0x0005, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, - 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18ae, 0x2c44, 0xa770, 0xa074, - 0x2071, 0x1894, 0x080c, 0x48c6, 0x701f, 0x53d7, 0x0005, 0x2061, - 0x18ae, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f32, - 0x002e, 0x001e, 0x080c, 0x0fdf, 0x9006, 0xa802, 0xa806, 0x0804, - 0x337e, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, + 0x33d3, 0x810c, 0x0016, 0x080c, 0x489a, 0x080c, 0x0f37, 0x2100, + 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, 0x48e3, + 0x701f, 0x53e3, 0x0005, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, + 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b6, 0x2c44, 0xa770, 0xa074, + 0x2071, 0x189c, 0x080c, 0x48e6, 0x701f, 0x53f7, 0x0005, 0x2061, + 0x18b6, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f3f, + 0x002e, 0x001e, 0x080c, 0x0fec, 0x9006, 0xa802, 0xa806, 0x0804, + 0x339e, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, - 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x5592, - 0x0068, 0xd08c, 0x0118, 0x080c, 0x549b, 0x0040, 0xd094, 0x0118, - 0x080c, 0x546b, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, + 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x55b2, + 0x0068, 0xd08c, 0x0118, 0x080c, 0x54bb, 0x0040, 0xd094, 0x0118, + 0x080c, 0x548b, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x0006, 0x7094, 0x9005, 0x000e, 0x0120, 0x7097, 0x0000, @@ -2491,215 +2495,215 @@ unsigned short risc_code01[] = { 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, - 0x00f7, 0x080c, 0x5c53, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, + 0x00f7, 0x080c, 0x5c73, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7083, 0x0000, 0x709f, 0x0001, 0x70c3, 0x0000, 0x70db, 0x0000, 0x2009, 0x1d80, 0x200b, 0x0000, - 0x7093, 0x0000, 0x7087, 0x000f, 0x2009, 0x000f, 0x2011, 0x5b35, - 0x080c, 0x81fc, 0x0005, 0x2001, 0x1875, 0x2004, 0xd08c, 0x0110, - 0x705b, 0xffff, 0x7084, 0x9005, 0x1528, 0x2011, 0x5b35, 0x080c, - 0x8138, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, - 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x5481, 0x6242, 0x7097, + 0x7093, 0x0000, 0x7087, 0x000f, 0x2009, 0x000f, 0x2011, 0x5b55, + 0x080c, 0x8230, 0x0005, 0x2001, 0x187d, 0x2004, 0xd08c, 0x0110, + 0x705b, 0xffff, 0x7084, 0x9005, 0x1528, 0x2011, 0x5b55, 0x080c, + 0x816c, 0x6040, 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, + 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x54a1, 0x6242, 0x7097, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x7097, 0x0000, 0x708b, 0x0000, 0x9006, 0x080c, - 0x5cdc, 0x0000, 0x0005, 0x7088, 0x908a, 0x0003, 0x1a0c, 0x0d65, - 0x000b, 0x0005, 0x54a5, 0x54f6, 0x5591, 0x00f6, 0x0016, 0x6900, + 0x5cfc, 0x0000, 0x0005, 0x7088, 0x908a, 0x0003, 0x1a0c, 0x0d65, + 0x000b, 0x0005, 0x54c5, 0x5516, 0x55b1, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708b, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, - 0x1f04, 0x54b4, 0x080c, 0x0d65, 0x68a0, 0x68a2, 0x689c, 0x689e, + 0x1f04, 0x54d4, 0x080c, 0x0d65, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, - 0x0020, 0x080c, 0x5cb8, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, + 0x0020, 0x080c, 0x5cd8, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, - 0x1d0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0x97e8, 0x20e1, 0x0001, + 0x1d0e, 0x20a9, 0x0004, 0x4003, 0x080c, 0x97f4, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, - 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x5b66, 0x00fe, + 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, 0x080c, 0x5b86, 0x00fe, 0x9006, 0x708e, 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x708c, - 0x708f, 0x0000, 0x9025, 0x0904, 0x556e, 0x6020, 0xd0b4, 0x1904, - 0x556c, 0x719c, 0x81ff, 0x0904, 0x555a, 0x9486, 0x000c, 0x1904, - 0x5567, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x5cb1, 0x2011, + 0x708f, 0x0000, 0x9025, 0x0904, 0x558e, 0x6020, 0xd0b4, 0x1904, + 0x558c, 0x719c, 0x81ff, 0x0904, 0x557a, 0x9486, 0x000c, 0x1904, + 0x5587, 0x9480, 0x0018, 0x8004, 0x20a8, 0x080c, 0x5cd1, 0x2011, 0x0260, 0x2019, 0x1d00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, - 0x8318, 0x1f04, 0x5513, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, + 0x8318, 0x1f04, 0x5533, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708b, - 0x0002, 0x7097, 0x0002, 0x2009, 0x07d0, 0x2011, 0x5b3c, 0x080c, - 0x81fc, 0x080c, 0x5cb8, 0x04c0, 0x080c, 0x5cb1, 0x2079, 0x0260, + 0x0002, 0x7097, 0x0002, 0x2009, 0x07d0, 0x2011, 0x5b5c, 0x080c, + 0x8230, 0x080c, 0x5cd8, 0x04c0, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, - 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x5cb1, + 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x5cd1, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, - 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x554e, 0x0078, - 0x709f, 0x0000, 0x080c, 0x5cb1, 0x20e1, 0x0000, 0x2099, 0x0260, + 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, 0x1f04, 0x556e, 0x0078, + 0x709f, 0x0000, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1d00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, - 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x97e8, 0x20e1, + 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x080c, 0x97f4, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19c4, 0x2013, 0x0000, - 0x708f, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8f8f, + 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, 0x19cc, 0x2013, 0x0000, + 0x708f, 0x0000, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8fc3, 0x08d8, 0x0005, 0x7094, 0x908a, 0x001d, 0x1a0c, 0x0d65, 0x000b, - 0x0005, 0x55c3, 0x55d6, 0x55ff, 0x561f, 0x5645, 0x5674, 0x569a, - 0x56d2, 0x56f8, 0x5726, 0x5761, 0x5799, 0x57b7, 0x57e2, 0x5804, - 0x581f, 0x5829, 0x585d, 0x5883, 0x58b2, 0x58d8, 0x5910, 0x5954, - 0x5991, 0x59b2, 0x5a0b, 0x5a2d, 0x5a5b, 0x5a5b, 0x00c6, 0x2061, + 0x0005, 0x55e3, 0x55f6, 0x561f, 0x563f, 0x5665, 0x5694, 0x56ba, + 0x56f2, 0x5718, 0x5746, 0x5781, 0x57b9, 0x57d7, 0x5802, 0x5824, + 0x583f, 0x5849, 0x587d, 0x58a3, 0x58d2, 0x58f8, 0x5930, 0x5974, + 0x59b1, 0x59d2, 0x5a2b, 0x5a4d, 0x5a7b, 0x5a7b, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, 0x7097, 0x0001, 0x2009, - 0x07d0, 0x2011, 0x5b3c, 0x080c, 0x81fc, 0x0005, 0x00f6, 0x708c, + 0x07d0, 0x2011, 0x5b5c, 0x080c, 0x8230, 0x0005, 0x00f6, 0x708c, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, - 0x5cb1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, + 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x7097, 0x0010, - 0x080c, 0x5829, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, - 0x7097, 0x0003, 0x6043, 0x0004, 0x2011, 0x5b3c, 0x080c, 0x8138, - 0x080c, 0x5c35, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, + 0x70c3, 0x0001, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x7097, 0x0010, + 0x080c, 0x5849, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x00f6, + 0x7097, 0x0003, 0x6043, 0x0004, 0x2011, 0x5b5c, 0x080c, 0x816c, + 0x080c, 0x5c55, 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, - 0x5614, 0x60c3, 0x0014, 0x080c, 0x5b66, 0x00fe, 0x0005, 0x00f6, - 0x708c, 0x9005, 0x0500, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x5cb1, 0x2079, 0x0260, 0x7a30, 0x9296, + 0x5634, 0x60c3, 0x0014, 0x080c, 0x5b86, 0x00fe, 0x0005, 0x00f6, + 0x708c, 0x9005, 0x0500, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x9086, + 0x0014, 0x11b8, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0004, 0x0029, - 0x0010, 0x080c, 0x5c8d, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0005, - 0x080c, 0x5c35, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, - 0x080c, 0x5cb1, 0x080c, 0x5c94, 0x1170, 0x7080, 0x9005, 0x1158, - 0x7158, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5ae9, - 0x0168, 0x080c, 0x5c6a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, + 0x0010, 0x080c, 0x5cad, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0005, + 0x080c, 0x5c55, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, + 0x080c, 0x5cd1, 0x080c, 0x5cb4, 0x1170, 0x7080, 0x9005, 0x1158, + 0x7158, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5b09, + 0x0168, 0x080c, 0x5c8a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, - 0x080c, 0x5b66, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, - 0x2011, 0x5b3c, 0x080c, 0x8138, 0x9086, 0x0014, 0x11b8, 0x080c, - 0x5cb1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, + 0x080c, 0x5b86, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, + 0x2011, 0x5b5c, 0x080c, 0x816c, 0x9086, 0x0014, 0x11b8, 0x080c, + 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, - 0x70c3, 0x0001, 0x7097, 0x0006, 0x0029, 0x0010, 0x080c, 0x5c8d, - 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0007, 0x080c, 0x5c35, 0x2079, - 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5cb1, 0x080c, - 0x5c94, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, - 0x0180, 0x9180, 0x317f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, - 0x0008, 0x080c, 0x5ae9, 0x0180, 0x080c, 0x4c92, 0x0110, 0x080c, - 0x24a6, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b66, - 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b3c, - 0x080c, 0x8138, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cb1, 0x2079, + 0x70c3, 0x0001, 0x7097, 0x0006, 0x0029, 0x0010, 0x080c, 0x5cad, + 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0007, 0x080c, 0x5c55, 0x2079, + 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x5cd1, 0x080c, + 0x5cb4, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, + 0x0180, 0x9180, 0x319f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, + 0x0008, 0x080c, 0x5b09, 0x0180, 0x080c, 0x4cb2, 0x0110, 0x080c, + 0x24c2, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b86, + 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b5c, + 0x080c, 0x816c, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, - 0x7097, 0x0008, 0x0029, 0x0010, 0x080c, 0x5c8d, 0x00fe, 0x0005, - 0x00f6, 0x7097, 0x0009, 0x080c, 0x5c35, 0x2079, 0x0240, 0x7833, - 0x1105, 0x7837, 0x0100, 0x080c, 0x5c94, 0x1150, 0x7080, 0x9005, - 0x1138, 0x080c, 0x5a5c, 0x1188, 0x9085, 0x0001, 0x080c, 0x24a6, - 0x20a9, 0x0008, 0x080c, 0x5cb1, 0x20e1, 0x0000, 0x2099, 0x026e, + 0x7097, 0x0008, 0x0029, 0x0010, 0x080c, 0x5cad, 0x00fe, 0x0005, + 0x00f6, 0x7097, 0x0009, 0x080c, 0x5c55, 0x2079, 0x0240, 0x7833, + 0x1105, 0x7837, 0x0100, 0x080c, 0x5cb4, 0x1150, 0x7080, 0x9005, + 0x1138, 0x080c, 0x5a7c, 0x1188, 0x9085, 0x0001, 0x080c, 0x24c2, + 0x20a9, 0x0008, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5b66, 0x0010, 0x080c, 0x55b6, 0x00fe, 0x0005, 0x00f6, 0x708c, - 0x9005, 0x05a8, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x9086, 0x0014, - 0x1560, 0x080c, 0x5cb1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, + 0x5b86, 0x0010, 0x080c, 0x55d6, 0x00fe, 0x0005, 0x00f6, 0x708c, + 0x9005, 0x05a8, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x9086, 0x0014, + 0x1560, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x000a, 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7093, 0x0000, - 0x7097, 0x000e, 0x080c, 0x5804, 0x0010, 0x080c, 0x5c8d, 0x00fe, + 0x7097, 0x000e, 0x080c, 0x5824, 0x0010, 0x080c, 0x5cad, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x000b, 0x2011, 0x1d0e, 0x20e9, 0x0001, - 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x5c35, - 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5c94, + 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x5c55, + 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5cb4, 0x0118, 0x2013, 0x0000, 0x0020, 0x705c, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, 0x1d0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x1f04, 0x5786, 0x60c3, 0x0084, 0x080c, 0x5b66, 0x00fe, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x01c0, 0x2011, 0x5b3c, 0x080c, - 0x8138, 0x9086, 0x0084, 0x1178, 0x080c, 0x5cb1, 0x2079, 0x0260, + 0x0240, 0x1f04, 0x57a6, 0x60c3, 0x0084, 0x080c, 0x5b86, 0x00fe, + 0x0005, 0x00f6, 0x708c, 0x9005, 0x01c0, 0x2011, 0x5b5c, 0x080c, + 0x816c, 0x9086, 0x0084, 0x1178, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x7097, - 0x000c, 0x0029, 0x0010, 0x080c, 0x5c8d, 0x00fe, 0x0005, 0x00f6, - 0x7097, 0x000d, 0x080c, 0x5c35, 0x2079, 0x0240, 0x7833, 0x1107, - 0x7837, 0x0000, 0x080c, 0x5cb1, 0x20a9, 0x0040, 0x2011, 0x026e, + 0x000c, 0x0029, 0x0010, 0x080c, 0x5cad, 0x00fe, 0x0005, 0x00f6, + 0x7097, 0x000d, 0x080c, 0x5c55, 0x2079, 0x0240, 0x7833, 0x1107, + 0x7837, 0x0000, 0x080c, 0x5cd1, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, - 0x2011, 0x0260, 0x1f04, 0x57ca, 0x60c3, 0x0084, 0x080c, 0x5b66, - 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, 0x5b3c, - 0x080c, 0x8138, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cb1, 0x2079, + 0x2011, 0x0260, 0x1f04, 0x57ea, 0x60c3, 0x0084, 0x080c, 0x5b86, + 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, 0x5b5c, + 0x080c, 0x816c, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, - 0x7093, 0x0001, 0x080c, 0x5c07, 0x7097, 0x000e, 0x0029, 0x0010, - 0x080c, 0x5c8d, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x5cdc, + 0x7093, 0x0001, 0x080c, 0x5c27, 0x7097, 0x000e, 0x0029, 0x0010, + 0x080c, 0x5cad, 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x5cfc, 0x7097, 0x000f, 0x708f, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, - 0x2009, 0x07d0, 0x2011, 0x5b3c, 0x080c, 0x812c, 0x0005, 0x708c, - 0x9005, 0x0130, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x7097, 0x0000, - 0x0005, 0x7097, 0x0011, 0x080c, 0x97e8, 0x080c, 0x5cb1, 0x20e1, + 0x2009, 0x07d0, 0x2011, 0x5b5c, 0x080c, 0x8160, 0x0005, 0x708c, + 0x9005, 0x0130, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x7097, 0x0000, + 0x0005, 0x7097, 0x0011, 0x080c, 0x97f4, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x748c, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, - 0x4003, 0x080c, 0x5c94, 0x11a0, 0x7178, 0x81ff, 0x0188, 0x900e, - 0x707c, 0x9084, 0x00ff, 0x0160, 0x080c, 0x243d, 0x9186, 0x007e, - 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5ae9, - 0x60c3, 0x0014, 0x080c, 0x5b66, 0x0005, 0x00f6, 0x708c, 0x9005, - 0x0500, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x5cb1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, + 0x4003, 0x080c, 0x5cb4, 0x11a0, 0x7178, 0x81ff, 0x0188, 0x900e, + 0x707c, 0x9084, 0x00ff, 0x0160, 0x080c, 0x2459, 0x9186, 0x007e, + 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5b09, + 0x60c3, 0x0014, 0x080c, 0x5b86, 0x0005, 0x00f6, 0x708c, 0x9005, + 0x0500, 0x2011, 0x5b5c, 0x080c, 0x816c, 0x9086, 0x0014, 0x11b8, + 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0012, 0x0029, 0x0010, 0x708f, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0013, 0x080c, 0x5c43, - 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5cb1, - 0x080c, 0x5c94, 0x1170, 0x7080, 0x9005, 0x1158, 0x7158, 0x9186, - 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5ae9, 0x0168, 0x080c, - 0x5c6a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b66, - 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b3c, - 0x080c, 0x8138, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cb1, 0x2079, + 0x0000, 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0013, 0x080c, 0x5c63, + 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x5cd1, + 0x080c, 0x5cb4, 0x1170, 0x7080, 0x9005, 0x1158, 0x7158, 0x9186, + 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5b09, 0x0168, 0x080c, + 0x5c8a, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, + 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b86, + 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x0500, 0x2011, 0x5b5c, + 0x080c, 0x816c, 0x9086, 0x0014, 0x11b8, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x7097, 0x0014, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x7097, 0x0015, 0x080c, 0x5c43, 0x2079, 0x0240, 0x7833, - 0x1104, 0x7837, 0x0000, 0x080c, 0x5cb1, 0x080c, 0x5c94, 0x11b8, + 0x00f6, 0x7097, 0x0015, 0x080c, 0x5c63, 0x2079, 0x0240, 0x7833, + 0x1104, 0x7837, 0x0000, 0x080c, 0x5cd1, 0x080c, 0x5cb4, 0x11b8, 0x7080, 0x9005, 0x11a0, 0x7160, 0x9186, 0xffff, 0x0180, 0x9180, - 0x317f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, - 0x5ae9, 0x0180, 0x080c, 0x4c92, 0x0110, 0x080c, 0x24a6, 0x20a9, + 0x319f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, + 0x5b09, 0x0180, 0x080c, 0x4cb2, 0x0110, 0x080c, 0x24c2, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b66, 0x00fe, 0x0005, - 0x00f6, 0x708c, 0x9005, 0x05f0, 0x2011, 0x5b3c, 0x080c, 0x8138, - 0x9086, 0x0014, 0x15a8, 0x080c, 0x5cb1, 0x2079, 0x0260, 0x7a30, + 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b86, 0x00fe, 0x0005, + 0x00f6, 0x708c, 0x9005, 0x05f0, 0x2011, 0x5b5c, 0x080c, 0x816c, + 0x9086, 0x0014, 0x15a8, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, - 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x5cdc, 0x7a38, 0xd2fc, + 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, 0x5cfc, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c0, 0x9005, 0x1110, 0x70c3, - 0x0001, 0x9085, 0x0001, 0x080c, 0x5cdc, 0x7093, 0x0000, 0x7a38, + 0x0001, 0x9085, 0x0001, 0x080c, 0x5cfc, 0x7093, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70db, 0x0008, 0x7097, 0x0016, 0x0029, 0x0010, - 0x708f, 0x0000, 0x00fe, 0x0005, 0x080c, 0x97e8, 0x080c, 0x5cb1, + 0x708f, 0x0000, 0x00fe, 0x0005, 0x080c, 0x97f4, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, 0x7097, 0x0017, 0x080c, - 0x5c94, 0x1150, 0x7080, 0x9005, 0x1138, 0x080c, 0x5a5c, 0x1188, - 0x9085, 0x0001, 0x080c, 0x24a6, 0x20a9, 0x0008, 0x080c, 0x5cb1, + 0x5cb4, 0x1150, 0x7080, 0x9005, 0x1138, 0x080c, 0x5a7c, 0x1188, + 0x9085, 0x0001, 0x080c, 0x24c2, 0x20a9, 0x0008, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b66, 0x0010, 0x080c, 0x55b6, - 0x0005, 0x00f6, 0x708c, 0x9005, 0x01d8, 0x2011, 0x5b3c, 0x080c, - 0x8138, 0x9086, 0x0084, 0x1190, 0x080c, 0x5cb1, 0x2079, 0x0260, + 0x4003, 0x60c3, 0x0014, 0x080c, 0x5b86, 0x0010, 0x080c, 0x55d6, + 0x0005, 0x00f6, 0x708c, 0x9005, 0x01d8, 0x2011, 0x5b5c, 0x080c, + 0x816c, 0x9086, 0x0084, 0x1190, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, - 0x080c, 0x5cdc, 0x7097, 0x0018, 0x0029, 0x0010, 0x708f, 0x0000, - 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0019, 0x080c, 0x5c43, 0x2079, - 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5cb1, 0x2009, + 0x080c, 0x5cfc, 0x7097, 0x0018, 0x0029, 0x0010, 0x708f, 0x0000, + 0x00fe, 0x0005, 0x00f6, 0x7097, 0x0019, 0x080c, 0x5c63, 0x2079, + 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x5cd1, 0x2009, 0x026e, 0x2039, 0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, - 0x1f04, 0x59c5, 0x2039, 0x1d0e, 0x080c, 0x5c94, 0x11e8, 0x2728, + 0x1f04, 0x59e5, 0x2039, 0x1d0e, 0x080c, 0x5cb4, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x705c, 0x2310, 0x8214, 0x92a0, 0x1d0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, - 0x6812, 0x2009, 0x0240, 0x1f04, 0x59f8, 0x60c3, 0x0084, 0x080c, - 0x5b66, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, - 0x5b3c, 0x080c, 0x8138, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cb1, + 0x6812, 0x2009, 0x0240, 0x1f04, 0x5a18, 0x60c3, 0x0084, 0x080c, + 0x5b86, 0x00fe, 0x0005, 0x00f6, 0x708c, 0x9005, 0x01e0, 0x2011, + 0x5b5c, 0x080c, 0x816c, 0x9086, 0x0084, 0x1198, 0x080c, 0x5cd1, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, - 0x1140, 0x7093, 0x0001, 0x080c, 0x5c07, 0x7097, 0x001a, 0x0029, + 0x1140, 0x7093, 0x0001, 0x080c, 0x5c27, 0x7097, 0x001a, 0x0029, 0x0010, 0x708f, 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, - 0x5cdc, 0x7097, 0x001b, 0x080c, 0x97e8, 0x080c, 0x5cb1, 0x2011, + 0x5cfc, 0x7097, 0x001b, 0x080c, 0x97f4, 0x080c, 0x5cd1, 0x2011, 0x0260, 0x2009, 0x0240, 0x748c, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, - 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5a44, 0x60c3, 0x0084, - 0x080c, 0x5b66, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1854, + 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5a64, 0x60c3, 0x0084, + 0x080c, 0x5b86, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x185c, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, - 0x080c, 0x5cb1, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, + 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, - 0x8211, 0x1f04, 0x5a76, 0x0804, 0x5ae5, 0x82ff, 0x1160, 0xd5d4, + 0x8211, 0x1f04, 0x5a96, 0x0804, 0x5b05, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, - 0x5ae5, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, + 0x5b05, 0x918d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, - 0x5a9c, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, - 0x5aae, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, + 0x5abc, 0x04d8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, + 0x5ace, 0x2328, 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, - 0x5abd, 0x755a, 0x95c8, 0x317f, 0x292d, 0x95ac, 0x00ff, 0x757e, - 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2486, 0x001e, 0x60e7, + 0x5add, 0x755a, 0x95c8, 0x319f, 0x292d, 0x95ac, 0x00ff, 0x757e, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x24a2, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, 0x201a, 0x7083, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, @@ -2710,52 +2714,52 @@ unsigned short risc_code01[] = { 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715a, - 0x91a0, 0x317f, 0x242d, 0x95ac, 0x00ff, 0x757e, 0x6532, 0x6536, - 0x0016, 0x2508, 0x080c, 0x2486, 0x001e, 0x60e7, 0x0000, 0x65ea, + 0x91a0, 0x319f, 0x242d, 0x95ac, 0x00ff, 0x757e, 0x6532, 0x6536, + 0x0016, 0x2508, 0x080c, 0x24a2, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7083, 0x0001, 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7087, 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, - 0x2071, 0x0140, 0x080c, 0x5bf6, 0x080c, 0x8f9c, 0x7004, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2862, 0x0126, 0x2091, 0x8000, 0x2071, + 0x2071, 0x0140, 0x080c, 0x5c16, 0x080c, 0x8fd0, 0x7004, 0x9084, + 0x4000, 0x0110, 0x080c, 0x2882, 0x0126, 0x2091, 0x8000, 0x2071, 0x1825, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, - 0x080c, 0x5c53, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, + 0x080c, 0x5c73, 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x080c, 0x27c1, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, - 0x2012, 0x2011, 0x19c4, 0x2013, 0x0000, 0x708f, 0x0000, 0x012e, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8f8f, 0x6144, 0xd184, + 0x8000, 0x080c, 0x27dd, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, + 0x2012, 0x2011, 0x19cc, 0x2013, 0x0000, 0x708f, 0x0000, 0x012e, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x8fc3, 0x6144, 0xd184, 0x0120, 0x7194, 0x918d, 0x2000, 0x0018, 0x7188, 0x918d, 0x1000, - 0x2011, 0x1969, 0x2112, 0x2009, 0x07d0, 0x2011, 0x5b3c, 0x080c, - 0x81fc, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x98bb, 0x080c, 0x9b60, 0x080c, 0x98d7, 0x2009, 0x00f7, - 0x080c, 0x5c53, 0x2061, 0x19d3, 0x900e, 0x611a, 0x611e, 0x6172, + 0x2011, 0x1971, 0x2112, 0x2009, 0x07d0, 0x2011, 0x5b5c, 0x080c, + 0x8230, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x98c7, 0x080c, 0x9b6c, 0x080c, 0x98e3, 0x2009, 0x00f7, + 0x080c, 0x5c73, 0x2061, 0x19db, 0x900e, 0x611a, 0x611e, 0x6172, 0x6176, 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2009, 0x1969, 0x200b, 0x0000, 0x2009, - 0x002d, 0x2011, 0x5bc2, 0x080c, 0x812c, 0x012e, 0x00ce, 0x002e, + 0x0090, 0x6043, 0x0010, 0x2009, 0x1971, 0x200b, 0x0000, 0x2009, + 0x002d, 0x2011, 0x5be2, 0x080c, 0x8160, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, - 0x2071, 0x0100, 0x080c, 0x8f9c, 0x2071, 0x0140, 0x7004, 0x9084, - 0x4000, 0x0110, 0x080c, 0x2862, 0x080c, 0x709e, 0x0188, 0x080c, - 0x70b9, 0x1170, 0x080c, 0x73a0, 0x0016, 0x080c, 0x2555, 0x2001, - 0x193d, 0x2102, 0x001e, 0x080c, 0x739b, 0x080c, 0x6fc7, 0x0050, - 0x2009, 0x0001, 0x080c, 0x283e, 0x2001, 0x0001, 0x080c, 0x23e2, - 0x080c, 0x5b92, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, + 0x2071, 0x0100, 0x080c, 0x8fd0, 0x2071, 0x0140, 0x7004, 0x9084, + 0x4000, 0x0110, 0x080c, 0x2882, 0x080c, 0x70c2, 0x0188, 0x080c, + 0x70dd, 0x1170, 0x080c, 0x73c3, 0x0016, 0x080c, 0x2571, 0x2001, + 0x1945, 0x2102, 0x001e, 0x080c, 0x73be, 0x080c, 0x6feb, 0x0050, + 0x2009, 0x0001, 0x080c, 0x285e, 0x2001, 0x0001, 0x080c, 0x23fe, + 0x080c, 0x5bb2, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, - 0x1969, 0x201c, 0x080c, 0x48da, 0x003e, 0x002e, 0x0005, 0x20a9, - 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x080c, 0x5cb1, 0x20e9, - 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x5cab, + 0x1971, 0x201c, 0x080c, 0x48fa, 0x003e, 0x002e, 0x0005, 0x20a9, + 0x0012, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x080c, 0x5cd1, 0x20e9, + 0x0000, 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x5ccb, 0x2099, 0x0260, 0x20a1, 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, - 0x5cae, 0x2099, 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, + 0x5cce, 0x2099, 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, - 0x1f04, 0x5c2b, 0x002e, 0x001e, 0x0005, 0x080c, 0x97e8, 0x20e1, + 0x1f04, 0x5c4b, 0x002e, 0x001e, 0x0005, 0x080c, 0x97f4, 0x20e1, 0x0001, 0x2099, 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, - 0x000c, 0x4003, 0x0005, 0x080c, 0x97e8, 0x080c, 0x5cb1, 0x20e1, + 0x000c, 0x4003, 0x0005, 0x080c, 0x97f4, 0x080c, 0x5cd1, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1833, 0x2004, 0x9005, 0x1138, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, - 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x6662, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xd284, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x2fd3, 0x080c, - 0xbf61, 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, - 0x4a77, 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5b92, 0x7097, + 0x00ce, 0x0005, 0x0016, 0x0046, 0x080c, 0x6686, 0x0158, 0x9006, + 0x2020, 0x2009, 0x002a, 0x080c, 0xd2bc, 0x2001, 0x180c, 0x200c, + 0xc195, 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x2ff3, 0x080c, + 0xbf8f, 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, + 0x4a97, 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5bb2, 0x7097, 0x0000, 0x708f, 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, @@ -2765,28 +2769,28 @@ unsigned short risc_code01[] = { 0x0001, 0x20a1, 0x1d00, 0x4004, 0x2079, 0x1d00, 0x7803, 0x2200, 0x7807, 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, - 0x1800, 0x2003, 0x0001, 0x0005, 0x2001, 0x1976, 0x0118, 0x2003, + 0x1800, 0x2003, 0x0001, 0x0005, 0x2001, 0x197e, 0x0118, 0x2003, 0x0001, 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, - 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x5ceb, 0x015e, - 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1853, + 0x2009, 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x5d0b, 0x015e, + 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x185b, 0x9006, 0xb802, 0xb8c6, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, - 0x9198, 0x317f, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, - 0xb886, 0x080c, 0x9b59, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, + 0x9198, 0x319f, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, + 0xb886, 0x080c, 0x9b65, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, 0x20a9, 0x0004, 0xb8b4, 0x20e8, 0xb9b8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, 0xb83e, 0xb842, 0xb8be, 0xb8c2, 0xb85e, 0xb862, 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8ae, 0xb9a2, - 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1054, 0xb8a7, 0x0000, + 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1061, 0xb8a7, 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, - 0x9082, 0x4000, 0x1a04, 0x5daf, 0x9182, 0x0800, 0x1a04, 0x5db3, - 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x5db9, 0x9188, + 0x9082, 0x4000, 0x1a04, 0x5dcf, 0x9182, 0x0800, 0x1a04, 0x5dd3, + 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x5dd9, 0x9188, 0x1000, 0x2104, 0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, 0x908e, - 0x0006, 0x1188, 0xb8a4, 0x900d, 0x1904, 0x5dcb, 0x080c, 0x6125, + 0x0006, 0x1188, 0xb8a4, 0x900d, 0x1904, 0x5deb, 0x080c, 0x6149, 0x9006, 0x012e, 0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, - 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0x9b59, + 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0x9b65, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0d10, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, @@ -2794,22 +2798,22 @@ unsigned short risc_code01[] = { 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, - 0x2104, 0x9065, 0x09a8, 0x080c, 0x6666, 0x1990, 0xb800, 0xd0bc, - 0x0978, 0x0804, 0x5d72, 0x080c, 0x64da, 0x0904, 0x5d7b, 0x0804, - 0x5d76, 0x00e6, 0x2071, 0x19b7, 0x7004, 0x9086, 0x0002, 0x1128, + 0x2104, 0x9065, 0x09a8, 0x080c, 0x668a, 0x1990, 0xb800, 0xd0bc, + 0x0978, 0x0804, 0x5d92, 0x080c, 0x64fe, 0x0904, 0x5d9b, 0x0804, + 0x5d96, 0x00e6, 0x2071, 0x19bf, 0x7004, 0x9086, 0x0002, 0x1128, 0x7030, 0x9080, 0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, - 0x5e5a, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x5e32, 0xb8a0, - 0x9086, 0x007f, 0x0178, 0x080c, 0x666e, 0x0160, 0xa994, 0x81ff, + 0x5e7a, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x5e52, 0xb8a0, + 0x9086, 0x007f, 0x0178, 0x080c, 0x6692, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, - 0x6666, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, - 0x2060, 0x0026, 0x2010, 0x080c, 0xb830, 0x002e, 0x1120, 0x2001, - 0x0008, 0x0804, 0x5e5c, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, - 0x0008, 0x0804, 0x5e5c, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, - 0x0058, 0x080c, 0x9b84, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, - 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x9c76, + 0x668a, 0x1598, 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, + 0x2060, 0x0026, 0x2010, 0x080c, 0xb85e, 0x002e, 0x1120, 0x2001, + 0x0008, 0x0804, 0x5e7c, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, + 0x0008, 0x0804, 0x5e7c, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, + 0x0058, 0x080c, 0x9b90, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, + 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0x9c82, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, - 0x080c, 0x9b59, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, + 0x080c, 0x9b65, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, @@ -2822,3596 +2826,3599 @@ unsigned short risc_code01[] = { 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, - 0x012e, 0x00be, 0x00fe, 0x0005, 0x5ef1, 0x5eac, 0x5ec3, 0x5ef1, - 0x5ef1, 0x5ef1, 0x5ef1, 0x5ef1, 0x2100, 0x9082, 0x007e, 0x1278, - 0x080c, 0x620b, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x5ef9, + 0x012e, 0x00be, 0x00fe, 0x0005, 0x5f11, 0x5ecc, 0x5ee3, 0x5f11, + 0x5f11, 0x5f11, 0x5f11, 0x5f11, 0x2100, 0x9082, 0x007e, 0x1278, + 0x080c, 0x622f, 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x5f19, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, - 0x4794, 0x0150, 0x04b0, 0x080c, 0x626b, 0x1598, 0xb810, 0x9306, - 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0x9b84, 0x0530, 0x2b00, - 0x6012, 0x080c, 0xbcdb, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, - 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x300e, 0x9006, - 0x080c, 0x61a8, 0x2001, 0x0002, 0x080c, 0x61bc, 0x2001, 0x0200, - 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0x9c76, 0x9006, + 0x47b4, 0x0150, 0x04b0, 0x080c, 0x628f, 0x1598, 0xb810, 0x9306, + 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, 0x9b90, 0x0530, 0x2b00, + 0x6012, 0x080c, 0xbd09, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, + 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, 0x080c, 0x302e, 0x9006, + 0x080c, 0x61cc, 0x2001, 0x0002, 0x080c, 0x61e0, 0x2001, 0x0200, + 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, 0x080c, 0x9c82, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0xa894, 0x90c6, 0x0015, 0x0904, 0x60ce, 0x90c6, 0x0056, 0x0904, - 0x60d2, 0x90c6, 0x0066, 0x0904, 0x60d6, 0x90c6, 0x0067, 0x0904, - 0x60da, 0x90c6, 0x0068, 0x0904, 0x60de, 0x90c6, 0x0071, 0x0904, - 0x60e2, 0x90c6, 0x0074, 0x0904, 0x60e6, 0x90c6, 0x007c, 0x0904, - 0x60ea, 0x90c6, 0x007e, 0x0904, 0x60ee, 0x90c6, 0x0037, 0x0904, - 0x60f2, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, - 0x60c9, 0x9182, 0x0800, 0x1a04, 0x60c9, 0x080c, 0x626b, 0x1198, + 0xa894, 0x90c6, 0x0015, 0x0904, 0x60f2, 0x90c6, 0x0056, 0x0904, + 0x60f6, 0x90c6, 0x0066, 0x0904, 0x60fa, 0x90c6, 0x0067, 0x0904, + 0x60fe, 0x90c6, 0x0068, 0x0904, 0x6102, 0x90c6, 0x0071, 0x0904, + 0x6106, 0x90c6, 0x0074, 0x0904, 0x610a, 0x90c6, 0x007c, 0x0904, + 0x610e, 0x90c6, 0x007e, 0x0904, 0x6112, 0x90c6, 0x0037, 0x0904, + 0x6116, 0x9016, 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, + 0x60ed, 0x9182, 0x0800, 0x1a04, 0x60ed, 0x080c, 0x628f, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, - 0x006f, 0x0148, 0x080c, 0x9b59, 0x1904, 0x60b2, 0xb8a0, 0x9084, - 0xff80, 0x1904, 0x60b2, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, - 0x005e, 0x0904, 0x6012, 0x90c6, 0x0064, 0x0904, 0x603b, 0x2008, - 0x0804, 0x5fd5, 0xa998, 0xa8b0, 0x2040, 0x080c, 0x9b59, 0x1120, - 0x9182, 0x007f, 0x0a04, 0x5fd5, 0x9186, 0x00ff, 0x0904, 0x5fd5, - 0x9182, 0x0800, 0x1a04, 0x5fd5, 0xaaa0, 0xab9c, 0x7878, 0x9306, - 0x1188, 0x787c, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, - 0x0804, 0x5fd5, 0x99cc, 0xff00, 0x009e, 0x1120, 0x2208, 0x2310, - 0x0804, 0x5fd5, 0x080c, 0x4794, 0x0904, 0x5fde, 0x900e, 0x9016, - 0x90c6, 0x4000, 0x1558, 0x0006, 0x080c, 0x655e, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, - 0x0006, 0x2098, 0x080c, 0x0f9f, 0x20a9, 0x0004, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0f9f, 0x000e, 0x00c8, 0x90c6, 0x4007, - 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, - 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, - 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, - 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0470, 0x080c, 0x9b84, - 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c80, 0x2b00, - 0x6012, 0x080c, 0xbcdb, 0x2900, 0x6016, 0x6023, 0x0001, 0xa868, - 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x300e, 0x012e, 0x9006, 0x080c, 0x61a8, 0x2001, 0x0002, 0x080c, - 0x61bc, 0x2009, 0x0002, 0x080c, 0x9c76, 0xa8b0, 0xd094, 0x0118, - 0xb8c4, 0xc08d, 0xb8c6, 0x9006, 0x9005, 0x012e, 0x00ee, 0x00fe, - 0x00be, 0x0005, 0x080c, 0x539c, 0x0118, 0x2009, 0x0007, 0x00f8, - 0xa998, 0xaeb0, 0x080c, 0x626b, 0x1904, 0x5fd0, 0x9186, 0x007f, - 0x0130, 0x080c, 0x6666, 0x0118, 0x2009, 0x0009, 0x0080, 0x0096, - 0x080c, 0x1022, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, 0x2900, - 0x009e, 0xa806, 0x080c, 0xba2e, 0x19b0, 0x2009, 0x0003, 0x2001, - 0x4005, 0x0804, 0x5fd7, 0xa998, 0xaeb0, 0x080c, 0x626b, 0x1904, - 0x5fd0, 0x0096, 0x080c, 0x1022, 0x1128, 0x009e, 0x2009, 0x0002, - 0x0804, 0x608f, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, 0x20a9, - 0x002b, 0xb8b4, 0x20e0, 0xb8b8, 0x2098, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, 0x0006, - 0x20a0, 0xbbb8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f9f, 0x009e, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, 0x1168, - 0x080c, 0x5388, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, 0xb800, - 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6666, 0x0118, - 0xa89b, 0x0009, 0x0080, 0x080c, 0x539c, 0x0118, 0xa89b, 0x0007, - 0x0050, 0x080c, 0xba11, 0x1904, 0x600b, 0x2009, 0x0003, 0x2001, - 0x4005, 0x0804, 0x5fd7, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa804, - 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, - 0x0000, 0x2041, 0x1271, 0x080c, 0xa0e7, 0x1904, 0x600b, 0x2009, - 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x600c, 0x2009, - 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, - 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, 0x0804, - 0x600c, 0x2001, 0x0029, 0x900e, 0x0804, 0x600c, 0x080c, 0x35ad, - 0x0804, 0x600d, 0x080c, 0x50bd, 0x0804, 0x600d, 0x080c, 0x4353, - 0x0804, 0x600d, 0x080c, 0x43cc, 0x0804, 0x600d, 0x080c, 0x4428, - 0x0804, 0x600d, 0x080c, 0x4850, 0x0804, 0x600d, 0x080c, 0x4af5, - 0x0804, 0x600d, 0x080c, 0x4d28, 0x0804, 0x600d, 0x080c, 0x4f21, - 0x0804, 0x600d, 0x080c, 0x37c2, 0x0804, 0x600d, 0x00b6, 0xa974, - 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1608, 0x9182, 0x0800, - 0x1258, 0x9188, 0x1000, 0x2104, 0x905d, 0x0130, 0x080c, 0x6666, - 0x1138, 0x00d9, 0x9006, 0x00b0, 0x2001, 0x0028, 0x900e, 0x0090, - 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, 0x0d98, 0x2001, 0x0029, - 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, - 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, 0xa877, 0x0000, 0xb8c0, - 0x9005, 0x1904, 0x619c, 0xb888, 0x9005, 0x1904, 0x619c, 0xb838, - 0xb93c, 0x9102, 0x1a04, 0x619c, 0x2b10, 0x080c, 0x9bb1, 0x0904, - 0x6198, 0x8108, 0xb93e, 0x6212, 0x2900, 0x6016, 0x6023, 0x0003, - 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, 0x605e, 0xa880, 0x9084, - 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, 0x05c0, 0xc0dd, - 0xa87e, 0xa888, 0x8001, 0x1568, 0x2001, 0x00f8, 0x8001, 0xa001, - 0xa001, 0xa001, 0x1dd8, 0xa816, 0xa864, 0x9094, 0x00f7, 0x9296, - 0x0011, 0x11f8, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, 0xaab0, - 0xa836, 0xaa3a, 0x2001, 0x000f, 0x8001, 0x1df0, 0x2001, 0x8004, - 0x6003, 0x0004, 0x6046, 0x00f6, 0x2079, 0x0380, 0x7818, 0xd0bc, - 0x1de8, 0x7833, 0x0010, 0x2c00, 0x7836, 0x781b, 0x8080, 0x00fe, - 0x0005, 0x080c, 0x165c, 0x601c, 0xc0bd, 0x601e, 0x0c38, 0x0006, - 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, - 0xd0b4, 0x190c, 0x1adf, 0x2001, 0x8004, 0x6003, 0x0002, 0x08d0, - 0x81ff, 0x1110, 0xb88b, 0x0001, 0x2908, 0xb8bc, 0xb9be, 0x9005, - 0x1110, 0xb9c2, 0x0020, 0x0096, 0x2048, 0xa902, 0x009e, 0x0005, - 0x00b6, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, - 0xba00, 0x9005, 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, - 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, - 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, - 0xb89c, 0xd0ac, 0x0158, 0x080c, 0x6662, 0x0140, 0x9284, 0xff00, - 0x8007, 0x9086, 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, - 0xff00, 0x9215, 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, - 0x82ff, 0x090c, 0x0d65, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, + 0x006f, 0x0148, 0x080c, 0x9b65, 0x1904, 0x60d6, 0xb8a0, 0x9084, + 0xff80, 0x1904, 0x60d6, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, + 0x005e, 0x0904, 0x6036, 0x90c6, 0x0064, 0x0904, 0x605f, 0x2008, + 0x0804, 0x5ff9, 0xa998, 0xa8b0, 0x2040, 0x080c, 0x9b65, 0x1120, + 0x9182, 0x007f, 0x0a04, 0x5ff9, 0x9186, 0x00ff, 0x0904, 0x5ff9, + 0x9182, 0x0800, 0x1a04, 0x5ff9, 0xaaa0, 0xab9c, 0x7878, 0x9306, + 0x11a8, 0x787c, 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, + 0x0804, 0x5ff9, 0x080c, 0x9b65, 0x1140, 0x99cc, 0xff00, 0x009e, + 0x1128, 0x2208, 0x2310, 0x0804, 0x5ff9, 0x009e, 0x080c, 0x47b4, + 0x0904, 0x6002, 0x900e, 0x9016, 0x90c6, 0x4000, 0x1558, 0x0006, + 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, + 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, + 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fac, + 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, + 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fac, + 0x000e, 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, + 0x4008, 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, + 0x0050, 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, + 0x0010, 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, + 0x900e, 0x0470, 0x080c, 0x9b90, 0x1130, 0x2001, 0x4005, 0x2009, + 0x0003, 0x9016, 0x0c80, 0x2b00, 0x6012, 0x080c, 0xbd09, 0x2900, + 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, + 0x0126, 0x2091, 0x8000, 0x080c, 0x302e, 0x012e, 0x9006, 0x080c, + 0x61cc, 0x2001, 0x0002, 0x080c, 0x61e0, 0x2009, 0x0002, 0x080c, + 0x9c82, 0xa8b0, 0xd094, 0x0118, 0xb8c4, 0xc08d, 0xb8c6, 0x9006, + 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x53bc, + 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x628f, + 0x1904, 0x5ff4, 0x9186, 0x007f, 0x0130, 0x080c, 0x668a, 0x0118, + 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x102f, 0x1120, 0x009e, + 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xba5c, + 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x5ffb, 0xa998, + 0xaeb0, 0x080c, 0x628f, 0x1904, 0x5ff4, 0x0096, 0x080c, 0x102f, + 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x60b3, 0x2900, 0x009e, + 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8b4, 0x20e0, 0xb8b8, + 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, + 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbb8, 0x9398, 0x0006, + 0x2398, 0x080c, 0x0fac, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, + 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x53a8, 0xd0b4, 0x1118, + 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, + 0x00b0, 0x080c, 0x668a, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, + 0x53bc, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xba3f, 0x1904, + 0x602f, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x5ffb, 0xa87b, + 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, + 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, + 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x127e, 0x080c, + 0xa0f3, 0x1904, 0x602f, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, + 0x900e, 0x0804, 0x6030, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, + 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, + 0x2001, 0x0029, 0x900e, 0x0804, 0x6030, 0x2001, 0x0029, 0x900e, + 0x0804, 0x6030, 0x080c, 0x35cd, 0x0804, 0x6031, 0x080c, 0x50dd, + 0x0804, 0x6031, 0x080c, 0x4373, 0x0804, 0x6031, 0x080c, 0x43ec, + 0x0804, 0x6031, 0x080c, 0x4448, 0x0804, 0x6031, 0x080c, 0x4870, + 0x0804, 0x6031, 0x080c, 0x4b15, 0x0804, 0x6031, 0x080c, 0x4d48, + 0x0804, 0x6031, 0x080c, 0x4f41, 0x0804, 0x6031, 0x080c, 0x37e2, + 0x0804, 0x6031, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, + 0x4000, 0x1608, 0x9182, 0x0800, 0x1258, 0x9188, 0x1000, 0x2104, + 0x905d, 0x0130, 0x080c, 0x668a, 0x1138, 0x00d9, 0x9006, 0x00b0, + 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, + 0xd1fc, 0x0d98, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, + 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, + 0x0005, 0xa877, 0x0000, 0xb8c0, 0x9005, 0x1904, 0x61c0, 0xb888, + 0x9005, 0x1904, 0x61c0, 0xb838, 0xb93c, 0x9102, 0x1a04, 0x61c0, + 0x2b10, 0x080c, 0x9bbd, 0x0904, 0x61bc, 0x8108, 0xb93e, 0x6212, + 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, + 0xa878, 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, + 0xa87c, 0xd0ac, 0x05c0, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1568, + 0x2001, 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0xa816, + 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x11f8, 0x9084, 0x00ff, + 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x000f, + 0x8001, 0x1df0, 0x2001, 0x8004, 0x6003, 0x0004, 0x6046, 0x00f6, + 0x2079, 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0010, 0x2c00, + 0x7836, 0x781b, 0x8080, 0x00fe, 0x0005, 0x080c, 0x1669, 0x601c, + 0xc0bd, 0x601e, 0x0c38, 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, + 0xa001, 0xa001, 0x1dd8, 0x000e, 0xd0b4, 0x190c, 0x1af7, 0x2001, + 0x8004, 0x6003, 0x0002, 0x08d0, 0x81ff, 0x1110, 0xb88b, 0x0001, + 0x2908, 0xb8bc, 0xb9be, 0x9005, 0x1110, 0xb9c2, 0x0020, 0x0096, + 0x2048, 0xa902, 0x009e, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x0026, + 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, 0x0110, 0xc285, + 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, - 0x0006, 0x9086, 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, - 0x665e, 0x1138, 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, - 0x0006, 0x000e, 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, - 0x012e, 0x00be, 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, - 0x0005, 0x00d6, 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1180, - 0x0096, 0x080c, 0x1022, 0x2958, 0x009e, 0x0160, 0x2b00, 0x2012, - 0xb85c, 0xb8ba, 0xb860, 0xb8b6, 0x9006, 0xb8a6, 0x080c, 0x5cf1, - 0x9006, 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0458, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, - 0x0518, 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1054, - 0x00d6, 0x00c6, 0xb8ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, - 0x6014, 0x2048, 0x080c, 0xb842, 0x0110, 0x080c, 0x0fd4, 0x080c, - 0x9bda, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x2b48, 0xb8b8, 0xb85e, - 0xb8b4, 0xb862, 0x080c, 0x1064, 0x00de, 0x9006, 0x002e, 0x012e, - 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, 0x9085, - 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, 0x9006, - 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, 0xb80a, - 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x7096, 0x1510, 0xb8a0, - 0x9086, 0x007e, 0x0120, 0x080c, 0x9b59, 0x11d8, 0x0078, 0x7040, - 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1952, 0x7048, 0x2062, 0x704c, - 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, 0x2069, - 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, 0x1800, - 0x68b2, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, 0x20e1, - 0x0000, 0x2099, 0x0276, 0xb8b4, 0x20e8, 0xb8b8, 0x9088, 0x000a, - 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, 0x0006, - 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, 0x0001, - 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, 0xb876, - 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, 0x1110, - 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, - 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, 0x02c1, - 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, 0x2009, - 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, - 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, - 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, - 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, 0x7054, - 0xb89e, 0x0036, 0xbbc4, 0xc384, 0xba00, 0x2009, 0x1873, 0x210c, - 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, - 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, 0x1108, - 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbc6, 0x003e, 0x00ee, 0x002e, - 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, - 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, 0x16c8, - 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, 0x908c, - 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, 0x2009, - 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, 0x8109, - 0x1dd0, 0x080c, 0x0d65, 0x3c00, 0x20e8, 0x3300, 0x8001, 0x20a0, - 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, 0x0060, - 0x080c, 0x1022, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, 0x080c, - 0x64fa, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, 0x009e, - 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, 0xb8a4, - 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x6509, 0x1158, - 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, 0x080c, - 0x1054, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096, 0x00c6, - 0xb888, 0x9005, 0x1904, 0x63ef, 0xb8c0, 0x904d, 0x0904, 0x63ef, - 0x080c, 0x9bb1, 0x0904, 0x63eb, 0x8210, 0xba3e, 0xa800, 0xb8c2, - 0x9005, 0x1108, 0xb8be, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, - 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, 0x605e, 0xa880, - 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, 0x01c8, - 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1568, 0xa816, 0xa864, 0x9094, - 0x00f7, 0x9296, 0x0011, 0x1530, 0x9084, 0x00ff, 0xc0bd, 0x601e, - 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x8004, 0x6003, 0x0004, - 0x0030, 0x080c, 0x1adf, 0x2001, 0x8004, 0x6003, 0x0002, 0x6046, - 0x2001, 0x0010, 0x2c08, 0x080c, 0x98ac, 0xb838, 0xba3c, 0x9202, - 0x0a04, 0x639c, 0x0020, 0x82ff, 0x1110, 0xb88b, 0x0001, 0x00ce, - 0x009e, 0x0005, 0x080c, 0x165c, 0x601c, 0xc0bd, 0x601e, 0x08e0, - 0x00b6, 0x0096, 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c, - 0x626b, 0x1158, 0xb8c0, 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04, - 0x63fe, 0x001e, 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, 0xb8c0, - 0x904d, 0x0188, 0xa800, 0xb8c2, 0x9005, 0x1108, 0xb8be, 0x9006, - 0xa802, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xbb45, - 0x080c, 0x6991, 0x0c60, 0x001e, 0x009e, 0x0005, 0x0086, 0x9046, - 0xb8c0, 0x904d, 0x01b0, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0128, 0x2940, 0xa800, 0x904d, 0x0160, 0x0ca8, 0xa800, 0x88ff, - 0x1128, 0xb8c2, 0x9005, 0x1118, 0xb8be, 0x0008, 0xa002, 0xa803, - 0x0000, 0x008e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x0126, - 0x2091, 0x8000, 0x00e6, 0x0096, 0x00c6, 0x0086, 0x0026, 0x2071, - 0x19b7, 0x9046, 0x7028, 0x9065, 0x01e8, 0x6014, 0x2068, 0x83ff, - 0x0120, 0x605c, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, - 0xa870, 0x9506, 0x0120, 0x2c40, 0x600c, 0x2060, 0x0c60, 0x600c, - 0x0006, 0x0066, 0x2830, 0x080c, 0x90f3, 0x006e, 0x000e, 0x83ff, - 0x0508, 0x0c08, 0x9046, 0xb8c0, 0x904d, 0x01e0, 0x83ff, 0x0120, - 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, - 0x9506, 0x0120, 0x2940, 0xa800, 0x2048, 0x0c70, 0xb8c0, 0xaa00, - 0x0026, 0x9906, 0x1110, 0xbac2, 0x0008, 0xa202, 0x000e, 0x83ff, - 0x0108, 0x0c10, 0x002e, 0x008e, 0x00ce, 0x009e, 0x00ee, 0x012e, - 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, - 0x655e, 0x0128, 0x080c, 0xb903, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x655e, 0x0128, 0x080c, 0xb8a4, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x655e, 0x0128, 0x080c, 0xb900, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x655e, 0x0128, 0x080c, 0xb8c3, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x655e, 0x0128, 0x080c, 0xb944, - 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, - 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, - 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, - 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, - 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, - 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, - 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, - 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, - 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, - 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, - 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, - 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, - 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x1022, 0x0168, 0x2900, - 0xb8a6, 0x080c, 0x64fa, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, - 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, - 0x1054, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, - 0x0005, 0x00b6, 0x00f6, 0x080c, 0x7096, 0x01b0, 0x71c0, 0x81ff, - 0x1198, 0x71d8, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, - 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1853, 0x7804, 0x00d0, - 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x626b, 0x1168, - 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, - 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, - 0x6584, 0x015e, 0x080c, 0x6624, 0x0120, 0x2001, 0x1955, 0x200c, - 0x0030, 0x2079, 0x1853, 0x7804, 0x0030, 0x2009, 0x07d0, 0x2011, - 0x65ae, 0x080c, 0x81fc, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, - 0x65ae, 0x080c, 0x8138, 0x080c, 0x6624, 0x01d8, 0x2001, 0x107e, - 0x2004, 0x2058, 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6662, 0x0130, - 0x2009, 0x07d0, 0x2011, 0x65ae, 0x080c, 0x81fc, 0x00e6, 0x2071, - 0x1800, 0x9006, 0x707a, 0x705c, 0x707e, 0x080c, 0x2de9, 0x00ee, - 0x04d0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, - 0x626b, 0x1558, 0xb800, 0xd0ec, 0x0540, 0x0046, 0xbaa0, 0x2220, - 0x9006, 0x2009, 0x0029, 0x080c, 0xd284, 0xb800, 0xc0e5, 0xc0ec, - 0xb802, 0x080c, 0x665e, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, - 0x00ff, 0x9085, 0x0700, 0xb806, 0x080c, 0x98bb, 0x2019, 0x0029, - 0x080c, 0x8624, 0x0076, 0x903e, 0x080c, 0x8509, 0x900e, 0x080c, - 0xcfd9, 0x007e, 0x004e, 0x080c, 0x98d7, 0x001e, 0x8108, 0x1f04, - 0x65d6, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, - 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, - 0xb800, 0x00be, 0xd0bc, 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, - 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, - 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, - 0x2204, 0x9b06, 0x190c, 0x0d65, 0x000e, 0xba00, 0x9005, 0x0110, - 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, - 0x1836, 0x2204, 0xd0cc, 0x0138, 0x2001, 0x1953, 0x200c, 0x2011, - 0x6654, 0x080c, 0x81fc, 0x0005, 0x2011, 0x6654, 0x080c, 0x8138, - 0x2011, 0x1836, 0x2204, 0xc0cc, 0x2012, 0x0005, 0x080c, 0x5388, - 0xd0ac, 0x0005, 0x080c, 0x5388, 0xd0a4, 0x0005, 0x0016, 0xb904, - 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, - 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, - 0x00f6, 0x080c, 0xbf61, 0x0158, 0x70d8, 0x9084, 0x0028, 0x0138, - 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, 0xb8c4, 0xd094, 0x00fe, - 0x00be, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x0076, 0x00b6, - 0x2001, 0x1817, 0x203c, 0x9780, 0x317f, 0x203d, 0x97bc, 0xff00, - 0x873f, 0x9006, 0x2018, 0x2008, 0x9284, 0x8000, 0x0110, 0x2019, - 0x0001, 0x9294, 0x7fff, 0x2100, 0x9706, 0x0190, 0x91a0, 0x1000, - 0x2404, 0x905d, 0x0168, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1138, 0x83ff, 0x0118, 0xb89c, 0xd0a4, 0x0110, 0x8211, 0x0158, - 0x8108, 0x83ff, 0x0120, 0x9182, 0x0800, 0x0e28, 0x0068, 0x9182, - 0x007e, 0x0e08, 0x0048, 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, - 0x9085, 0x0001, 0x000e, 0x0005, 0x00be, 0x007e, 0x004e, 0x003e, - 0x001e, 0x9006, 0x000e, 0x0005, 0x0046, 0x0056, 0x0076, 0x00b6, - 0x2100, 0x9084, 0x7fff, 0x9080, 0x1000, 0x2004, 0x905d, 0x0130, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0550, 0x9184, 0x8000, - 0x0580, 0x2001, 0x1817, 0x203c, 0x9780, 0x317f, 0x203d, 0x97bc, - 0xff00, 0x873f, 0x9006, 0x2020, 0x2400, 0x9706, 0x01a0, 0x94a8, - 0x1000, 0x2504, 0x905d, 0x0178, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x1148, 0xb89c, 0xd0a4, 0x0130, 0xb814, 0x9206, 0x1118, - 0xb810, 0x9306, 0x0128, 0x8420, 0x9482, 0x0800, 0x0e28, 0x0048, - 0x918c, 0x7fff, 0x00be, 0x007e, 0x005e, 0x004e, 0x9085, 0x0001, - 0x0005, 0x918c, 0x7fff, 0x00be, 0x007e, 0x005e, 0x004e, 0x9006, - 0x0005, 0x2071, 0x1906, 0x7003, 0x0001, 0x7007, 0x0000, 0x9006, - 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x0005, 0x0016, - 0x00e6, 0x2071, 0x1919, 0x900e, 0x710a, 0x080c, 0x5388, 0xd0fc, - 0x1140, 0x080c, 0x5388, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, - 0x0400, 0x2001, 0x1873, 0x200c, 0x9184, 0x0007, 0x9006, 0x0002, - 0x6739, 0x6739, 0x6739, 0x6739, 0x6739, 0x6750, 0x675e, 0x6739, - 0x7003, 0x0003, 0x2009, 0x1874, 0x210c, 0x9184, 0xff00, 0x8007, - 0x9005, 0x1110, 0x2001, 0x0002, 0x7006, 0x0018, 0x7003, 0x0005, - 0x0c88, 0x00ee, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0050, 0x684c, - 0x9005, 0x1150, 0x00e6, 0x2071, 0x1906, 0x7028, 0xc085, 0x702a, - 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, 0x9005, 0x0158, 0x080c, - 0x7408, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, 0x7006, 0x9006, - 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, 0x6868, 0x700a, - 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, 0x7016, 0x684c, - 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, 0x0019, 0x702b, - 0x0001, 0x00e6, 0x2071, 0x1906, 0x7028, 0xc084, 0x702a, 0x7007, - 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee, 0x0005, 0xa868, - 0xd0fc, 0x11d8, 0x00e6, 0x0026, 0x2001, 0x1919, 0x2004, 0x9005, - 0x0904, 0x6996, 0xa87c, 0xd0bc, 0x1904, 0x6996, 0xa978, 0xa874, - 0x9105, 0x1904, 0x6996, 0x2001, 0x1919, 0x2004, 0x0002, 0x6996, - 0x67ea, 0x6826, 0x6826, 0x6996, 0x6826, 0x0005, 0xa868, 0xd0fc, - 0x1500, 0x00e6, 0x0026, 0x2009, 0x1919, 0x210c, 0x81ff, 0x0904, - 0x6996, 0xa87c, 0xd0cc, 0x0904, 0x6996, 0xa880, 0x9084, 0x00ff, - 0x9086, 0x0001, 0x1904, 0x6996, 0x9186, 0x0003, 0x0904, 0x6826, - 0x9186, 0x0005, 0x0904, 0x6826, 0xa84f, 0x8021, 0xa853, 0x0017, - 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1906, - 0x701c, 0x9005, 0x1904, 0x6b2d, 0x0e04, 0x6b78, 0x2071, 0x0000, - 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, - 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11c9, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, - 0x1158, 0xa802, 0x2900, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, - 0x8053, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, - 0x00f6, 0x2079, 0x0050, 0x2071, 0x1906, 0xa803, 0x0000, 0x7010, - 0x9005, 0x1904, 0x691b, 0x782c, 0x908c, 0x0780, 0x190c, 0x6c9f, - 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6844, 0x691b, - 0x6869, 0x68b6, 0x080c, 0x0d65, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1170, 0x2071, 0x19d3, 0x703c, 0x9005, 0x1328, - 0x2001, 0x191a, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, - 0x0c10, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x15a8, - 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, - 0x182f, 0x210c, 0x918a, 0x0040, 0x0240, 0x7022, 0x2001, 0x1dc0, - 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8053, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, 0x19c8, 0x2071, - 0x19d3, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, 0x2004, 0x8005, + 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, 0x0158, 0x080c, + 0x6686, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, 0x0007, 0x1110, + 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, 0xba06, 0x0006, + 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, 0x0d65, 0x000e, + 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, + 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1168, + 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6682, 0x1138, 0x9284, 0x00ff, + 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0x9294, 0x00ff, + 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, 0x0005, 0x9182, + 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0026, 0x9190, + 0x1000, 0x2204, 0x905d, 0x1180, 0x0096, 0x080c, 0x102f, 0x2958, + 0x009e, 0x0160, 0x2b00, 0x2012, 0xb85c, 0xb8ba, 0xb860, 0xb8b6, + 0x9006, 0xb8a6, 0x080c, 0x5d11, 0x9006, 0x0010, 0x9085, 0x0001, + 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, 0x0126, 0x2091, 0x8000, + 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0458, 0x00d6, + 0x9190, 0x1000, 0x2204, 0x905d, 0x0518, 0x2013, 0x0000, 0xb8a4, + 0x904d, 0x0110, 0x080c, 0x1061, 0x00d6, 0x00c6, 0xb8ac, 0x2060, + 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, 0x2048, 0x080c, 0xb870, + 0x0110, 0x080c, 0x0fe1, 0x080c, 0x9be6, 0x00ce, 0x0c88, 0x00ce, + 0x00de, 0x2b48, 0xb8b8, 0xb85e, 0xb8b4, 0xb862, 0x080c, 0x1071, + 0x00de, 0x9006, 0x002e, 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, + 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, + 0x2104, 0x905d, 0x0dc0, 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, + 0x0136, 0x0146, 0x9006, 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, + 0x080c, 0x70ba, 0x1510, 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, + 0x9b65, 0x11d8, 0x0078, 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, + 0x195a, 0x7048, 0x2062, 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, + 0x600e, 0x00ce, 0x703c, 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, + 0x0001, 0x6886, 0x2069, 0x1800, 0x68b2, 0x7040, 0xb85e, 0x7048, + 0xb862, 0x704c, 0xb866, 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8b4, + 0x20e8, 0xb8b8, 0x9088, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, + 0x2099, 0x027a, 0x9088, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, + 0x2069, 0x0200, 0x6817, 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, + 0x7048, 0xb872, 0x7050, 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, + 0xb8a0, 0x9086, 0x007e, 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, + 0x1218, 0x2009, 0x0008, 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, + 0x0007, 0x00d0, 0x9182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, + 0x9182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, + 0x1218, 0x2009, 0x0004, 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, + 0x0003, 0x0010, 0x2009, 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, + 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, + 0xb896, 0x703c, 0xb89a, 0x7054, 0xb89e, 0x0036, 0xbbc4, 0xc384, + 0xba00, 0x2009, 0x187b, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, + 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, + 0xd0cc, 0x0128, 0xd38c, 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, + 0xbbc6, 0x003e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, + 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, + 0xaa04, 0x9282, 0x0010, 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, + 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, + 0x9080, 0x0004, 0x2098, 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, + 0x9086, 0xffff, 0x0120, 0x8109, 0x1dd0, 0x080c, 0x0d65, 0x3c00, + 0x20e8, 0x3300, 0x8001, 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, + 0x01ce, 0x014e, 0x013e, 0x0060, 0x080c, 0x102f, 0x0170, 0x2900, + 0xb8a6, 0xa803, 0x0000, 0x080c, 0x651e, 0xa807, 0x0001, 0xae12, + 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, + 0x2091, 0x8000, 0x0096, 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, + 0x1150, 0x080c, 0x652d, 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, + 0x8001, 0xa806, 0x0020, 0x080c, 0x1061, 0xb8a7, 0x0000, 0x009e, + 0x012e, 0x0005, 0x0096, 0x00c6, 0xb888, 0x9005, 0x1904, 0x6413, + 0xb8c0, 0x904d, 0x0904, 0x6413, 0x080c, 0x9bbd, 0x0904, 0x640f, + 0x8210, 0xba3e, 0xa800, 0xb8c2, 0x9005, 0x1108, 0xb8be, 0x2b00, + 0x6012, 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, + 0x0040, 0xa878, 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, + 0x0000, 0xa87c, 0xd0ac, 0x01c8, 0xc0dd, 0xa87e, 0xa888, 0x8001, + 0x1568, 0xa816, 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x1530, + 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, + 0x2001, 0x8004, 0x6003, 0x0004, 0x0030, 0x080c, 0x1af7, 0x2001, + 0x8004, 0x6003, 0x0002, 0x6046, 0x2001, 0x0010, 0x2c08, 0x080c, + 0x98b8, 0xb838, 0xba3c, 0x9202, 0x0a04, 0x63c0, 0x0020, 0x82ff, + 0x1110, 0xb88b, 0x0001, 0x00ce, 0x009e, 0x0005, 0x080c, 0x1669, + 0x601c, 0xc0bd, 0x601e, 0x08e0, 0x00b6, 0x0096, 0x0016, 0x20a9, + 0x0800, 0x900e, 0x0016, 0x080c, 0x628f, 0x1158, 0xb8c0, 0x904d, + 0x0140, 0x3e00, 0x9086, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1108, + 0x0041, 0x001e, 0x8108, 0x1f04, 0x6422, 0x001e, 0x00be, 0x009e, + 0x0005, 0x0096, 0x0016, 0xb8c0, 0x904d, 0x0188, 0xa800, 0xb8c2, + 0x9005, 0x1108, 0xb8be, 0x9006, 0xa802, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0xbb73, 0x080c, 0x69b5, 0x0c60, 0x001e, + 0x009e, 0x0005, 0x0086, 0x9046, 0xb8c0, 0x904d, 0x01b0, 0xa86c, + 0x9406, 0x1118, 0xa870, 0x9506, 0x0128, 0x2940, 0xa800, 0x904d, + 0x0160, 0x0ca8, 0xa800, 0x88ff, 0x1128, 0xb8c2, 0x9005, 0x1118, + 0xb8be, 0x0008, 0xa002, 0xa803, 0x0000, 0x008e, 0x0005, 0x901e, + 0x0010, 0x2019, 0x0001, 0x0126, 0x2091, 0x8000, 0x00e6, 0x0096, + 0x00c6, 0x0086, 0x0026, 0x2071, 0x19bf, 0x9046, 0x7028, 0x9065, + 0x01e8, 0x6014, 0x2068, 0x83ff, 0x0120, 0x605c, 0x9606, 0x0158, + 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0120, 0x2c40, + 0x600c, 0x2060, 0x0c60, 0x600c, 0x0006, 0x0066, 0x2830, 0x080c, + 0x9127, 0x006e, 0x000e, 0x83ff, 0x0508, 0x0c08, 0x9046, 0xb8c0, + 0x904d, 0x01e0, 0x83ff, 0x0120, 0xa878, 0x9606, 0x0158, 0x0030, + 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0120, 0x2940, 0xa800, + 0x2048, 0x0c70, 0xb8c0, 0xaa00, 0x0026, 0x9906, 0x1110, 0xbac2, + 0x0008, 0xa202, 0x000e, 0x83ff, 0x0108, 0x0c10, 0x002e, 0x008e, + 0x00ce, 0x009e, 0x00ee, 0x012e, 0x0005, 0x9016, 0x0489, 0x1110, + 0x2011, 0x0001, 0x0005, 0x080c, 0x6582, 0x0128, 0x080c, 0xb931, + 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6582, 0x0128, 0x080c, + 0xb8d2, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6582, 0x0128, + 0x080c, 0xb92e, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6582, + 0x0128, 0x080c, 0xb8f1, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, + 0x6582, 0x0128, 0x080c, 0xb972, 0x0010, 0x9085, 0x0001, 0x0005, + 0xb8a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, 0x0136, 0x01c6, + 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, + 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, + 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, + 0x0001, 0x0008, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0146, 0x01d6, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0004, 0x20a0, 0x20a9, 0x0010, + 0x2009, 0xffff, 0x4104, 0x01de, 0x014e, 0x0136, 0x01c6, 0xa800, + 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, + 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, + 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, + 0x0068, 0x0146, 0x01d6, 0x3300, 0x8001, 0x20a0, 0x3c00, 0x20e8, + 0x2001, 0xffff, 0x4004, 0x01de, 0x014e, 0x9006, 0x01ce, 0x013e, + 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, 0x1128, + 0x080c, 0x102f, 0x0168, 0x2900, 0xb8a6, 0x080c, 0x651e, 0xa803, + 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, + 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, 0x904d, + 0x0130, 0xb8a7, 0x0000, 0x080c, 0x1061, 0x9085, 0x0001, 0x012e, + 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, 0x00f6, 0x080c, + 0x70ba, 0x01b0, 0x71c0, 0x81ff, 0x1198, 0x71d8, 0xd19c, 0x0180, + 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d, 0x0148, 0xb804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, + 0x2079, 0x185b, 0x7804, 0x00d0, 0x0156, 0x20a9, 0x007f, 0x900e, + 0x0016, 0x080c, 0x628f, 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, + 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, + 0xb802, 0x001e, 0x8108, 0x1f04, 0x65a8, 0x015e, 0x080c, 0x6648, + 0x0120, 0x2001, 0x195d, 0x200c, 0x0030, 0x2079, 0x185b, 0x7804, + 0x0030, 0x2009, 0x07d0, 0x2011, 0x65d2, 0x080c, 0x8230, 0x00fe, + 0x00be, 0x0005, 0x00b6, 0x2011, 0x65d2, 0x080c, 0x816c, 0x080c, + 0x6648, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, + 0xb902, 0x080c, 0x6686, 0x0130, 0x2009, 0x07d0, 0x2011, 0x65d2, + 0x080c, 0x8230, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707a, 0x705c, + 0x707e, 0x080c, 0x2e09, 0x00ee, 0x04d0, 0x0156, 0x00c6, 0x20a9, + 0x007f, 0x900e, 0x0016, 0x080c, 0x628f, 0x1558, 0xb800, 0xd0ec, + 0x0540, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, + 0xd2bc, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6682, 0x2001, + 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, + 0x080c, 0x98c7, 0x2019, 0x0029, 0x080c, 0x8658, 0x0076, 0x903e, + 0x080c, 0x853d, 0x900e, 0x080c, 0xd011, 0x007e, 0x004e, 0x080c, + 0x98e3, 0x001e, 0x8108, 0x1f04, 0x65fa, 0x00ce, 0x015e, 0x00be, + 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, 0xb802, 0x00be, + 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, 0x0005, + 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, 0x0005, + 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, + 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, + 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0d65, + 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, + 0x002e, 0x012e, 0x0005, 0x2011, 0x1836, 0x2204, 0xd0cc, 0x0138, + 0x2001, 0x195b, 0x200c, 0x2011, 0x6678, 0x080c, 0x8230, 0x0005, + 0x2011, 0x6678, 0x080c, 0x816c, 0x2011, 0x1836, 0x2204, 0xc0cc, + 0x2012, 0x0005, 0x080c, 0x53a8, 0xd0ac, 0x0005, 0x080c, 0x53a8, + 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, + 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, + 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xbf8f, 0x0158, + 0x70d8, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, + 0x0110, 0xb8c4, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, + 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1817, 0x203c, 0x9780, + 0x319f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, 0x2008, + 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, 0x2100, + 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, 0xb804, + 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, 0xb89c, + 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, 0x9182, + 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, 0x00be, + 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, 0x0005, + 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, 0x0005, + 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, 0x9080, + 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, 0x9086, + 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1817, 0x203c, + 0x9780, 0x319f, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2020, + 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, 0x0178, + 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, 0xd0a4, + 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, 0x8420, + 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, 0x007e, + 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, 0x00be, + 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x2071, 0x190e, 0x7003, + 0x0001, 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, + 0x700a, 0x7046, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1921, 0x900e, + 0x710a, 0x080c, 0x53a8, 0xd0fc, 0x1140, 0x080c, 0x53a8, 0x900e, + 0xd09c, 0x0108, 0x8108, 0x7102, 0x0400, 0x2001, 0x187b, 0x200c, + 0x9184, 0x0007, 0x9006, 0x0002, 0x675d, 0x675d, 0x675d, 0x675d, + 0x675d, 0x6774, 0x6782, 0x675d, 0x7003, 0x0003, 0x2009, 0x187c, + 0x210c, 0x9184, 0xff00, 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, + 0x7006, 0x0018, 0x7003, 0x0005, 0x0c88, 0x00ee, 0x001e, 0x0005, + 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, + 0x190e, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, + 0x6844, 0x9005, 0x0158, 0x080c, 0x742b, 0x6a60, 0x9200, 0x7002, + 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, + 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, + 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, + 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x190e, + 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, + 0x9006, 0x00ee, 0x0005, 0xa868, 0xd0fc, 0x11d8, 0x00e6, 0x0026, + 0x2001, 0x1921, 0x2004, 0x9005, 0x0904, 0x69ba, 0xa87c, 0xd0bc, + 0x1904, 0x69ba, 0xa978, 0xa874, 0x9105, 0x1904, 0x69ba, 0x2001, + 0x1921, 0x2004, 0x0002, 0x69ba, 0x680e, 0x684a, 0x684a, 0x69ba, + 0x684a, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0x2009, + 0x1921, 0x210c, 0x81ff, 0x0904, 0x69ba, 0xa87c, 0xd0cc, 0x0904, + 0x69ba, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x69ba, + 0x9186, 0x0003, 0x0904, 0x684a, 0x9186, 0x0005, 0x0904, 0x684a, + 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, 0xa84f, 0x8020, + 0xa853, 0x0016, 0x2071, 0x190e, 0x701c, 0x9005, 0x1904, 0x6b51, + 0x0e04, 0x6b9c, 0x2071, 0x0000, 0xa84c, 0x7082, 0xa850, 0x7032, + 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x2071, 0x1800, 0x2011, + 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, 0x2900, 0x702e, + 0x70bc, 0x9200, 0x70be, 0x080c, 0x8087, 0x002e, 0x00ee, 0x0005, + 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, + 0x190e, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x693f, 0x782c, + 0x908c, 0x0780, 0x190c, 0x6cc3, 0x8004, 0x8004, 0x8004, 0x9084, + 0x0003, 0x0002, 0x6868, 0x693f, 0x688d, 0x68da, 0x080c, 0x0d65, + 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1170, 0x2071, + 0x19db, 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x8053, 0x0804, 0x6870, 0x0096, 0x00e6, - 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70bc, 0x8000, 0x70be, 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd09c, 0x11a0, 0x009e, 0x2900, 0x7822, 0xa804, - 0x900d, 0x1560, 0x2071, 0x19d3, 0x703c, 0x9005, 0x1328, 0x2001, - 0x191a, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1170, - 0x2071, 0x19d3, 0x703c, 0x9005, 0x1328, 0x2001, 0x191a, 0x2004, - 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1904, 0x6970, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, - 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, - 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, - 0x0780, 0x190c, 0x6c9f, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, - 0x1d60, 0x00ee, 0x2071, 0x19d3, 0x703c, 0x9005, 0x1328, 0x2001, - 0x191a, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, + 0x9200, 0x70be, 0x080c, 0x8087, 0x0c10, 0x2071, 0x1800, 0x2900, + 0x7822, 0xa804, 0x900d, 0x15a8, 0x7824, 0x00e6, 0x2071, 0x0040, + 0x712c, 0xd19c, 0x1170, 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, + 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, + 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, + 0x8000, 0x70be, 0x080c, 0x8087, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6cc3, 0xd0a4, 0x19c8, 0x2071, 0x19db, 0x703c, 0x9005, 0x1328, + 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8087, + 0x0804, 0x6894, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x8087, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x1d60, + 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, 0x11a0, + 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1560, 0x2071, 0x19db, + 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, + 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, + 0x2148, 0xa804, 0x900d, 0x1170, 0x2071, 0x19db, 0x703c, 0x9005, + 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x8087, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6994, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, 0x1198, 0x701c, 0x904d, + 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, + 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, + 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x01b0, + 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8087, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x19db, + 0x703c, 0x9005, 0x1328, 0x2001, 0x1922, 0x2004, 0x8005, 0x703e, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, + 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8087, 0x00ee, 0x0804, + 0x694f, 0xa868, 0xd0fc, 0x1560, 0x0096, 0xa804, 0xa807, 0x0000, + 0x904d, 0x190c, 0x0fe1, 0x009e, 0x0018, 0xa868, 0xd0fc, 0x1500, + 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, + 0x190e, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, 0x6acf, 0x782c, + 0x908c, 0x0780, 0x190c, 0x6cc3, 0x8004, 0x8004, 0x8004, 0x9084, + 0x0003, 0x0002, 0x69d9, 0x6acf, 0x69f4, 0x6a62, 0x080c, 0x0d65, + 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x8087, 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, + 0xa804, 0x900d, 0x1904, 0x6a51, 0x7830, 0xd0dc, 0x1120, 0x00fe, + 0x002e, 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, + 0xd19c, 0x1170, 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, 0x0240, + 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, + 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, + 0x70be, 0x080c, 0x8087, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, + 0xd0a4, 0x19c8, 0x0e04, 0x6a48, 0x7838, 0x7938, 0x910e, 0x1de0, + 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, + 0x191f, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, + 0x2004, 0xd084, 0x190c, 0x11d6, 0x00fe, 0x002e, 0x00ee, 0x0005, + 0x2001, 0x191f, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, + 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, + 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8087, + 0x0804, 0x6a03, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x8087, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x1d60, + 0x00ee, 0x0e04, 0x6aa2, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, + 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x11d6, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, 0x1170, + 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x8087, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, + 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, + 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x6b3c, 0x782c, + 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, 0x11b0, 0x701c, 0x904d, + 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, + 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, + 0x190c, 0x6cc3, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, + 0x6cc3, 0xd0a4, 0x05a8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, + 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, + 0x8087, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x1d60, + 0x00ee, 0x0e04, 0x6b35, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, + 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, + 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, + 0x11d6, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, + 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, + 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, + 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8087, 0x00ee, 0x0804, + 0x6adf, 0x2071, 0x190e, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, + 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, + 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x6b7c, 0x002e, 0x00ee, + 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, - 0x080c, 0x8053, 0x00ee, 0x0804, 0x692b, 0xa868, 0xd0fc, 0x1560, - 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x0fd4, 0x009e, - 0x0018, 0xa868, 0xd0fc, 0x1500, 0x00e6, 0x0026, 0xa84f, 0x0000, - 0x00f6, 0x2079, 0x0050, 0x2071, 0x1906, 0xa803, 0x0000, 0x7010, - 0x9005, 0x1904, 0x6aab, 0x782c, 0x908c, 0x0780, 0x190c, 0x6c9f, - 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x69b5, 0x6aab, - 0x69d0, 0x6a3e, 0x080c, 0x0d65, 0x0005, 0x2071, 0x1800, 0x2900, - 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, 0x0c60, - 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6a2d, - 0x7830, 0xd0dc, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7824, - 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x182f, - 0x210c, 0x918a, 0x0040, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, - 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8053, 0x782c, - 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, 0x19c8, 0x0e04, 0x6a24, - 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, - 0x6833, 0x0013, 0x00de, 0x2001, 0x1917, 0x200c, 0xc184, 0x2102, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1917, 0x200c, 0xc185, - 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, - 0x9200, 0x70be, 0x080c, 0x8053, 0x0804, 0x69df, 0x0096, 0x00e6, - 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70bc, 0x8000, 0x70be, 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6a7e, 0x7838, + 0x080c, 0x8087, 0x0e04, 0x6b66, 0x2071, 0x190e, 0x701c, 0x2048, + 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, + 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, + 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x2071, 0x190e, 0x080c, + 0x6caf, 0x002e, 0x00ee, 0x0005, 0x2071, 0x190e, 0xa803, 0x0000, + 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, + 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, + 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, + 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, + 0x70be, 0x080c, 0x8087, 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, + 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, + 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, + 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x190e, 0x7004, + 0x0002, 0x6be7, 0x6be8, 0x6cae, 0x6be8, 0x0d65, 0x6cae, 0x0005, + 0x2001, 0x1921, 0x2004, 0x0002, 0x6bf2, 0x6bf2, 0x6c47, 0x6c48, + 0x6bf2, 0x6c48, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6cce, 0x701c, + 0x904d, 0x01e0, 0xa84c, 0x9005, 0x01d8, 0x0e04, 0x6c16, 0xa94c, + 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, + 0xa870, 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x11d6, 0x2071, 0x190e, 0x080c, 0x6caf, 0x012e, 0x0470, + 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd09c, + 0x2071, 0x190e, 0x1510, 0x2071, 0x190e, 0x700f, 0x0001, 0xa964, + 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, + 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, + 0x00de, 0x2071, 0x190e, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, + 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, + 0x00d6, 0x2008, 0x2069, 0x19db, 0x683c, 0x9005, 0x0760, 0x0158, + 0x9186, 0x0003, 0x0540, 0x2001, 0x1814, 0x2004, 0x2009, 0x1b25, + 0x210c, 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, + 0x693c, 0x6838, 0x9106, 0x0190, 0x0e04, 0x6c7a, 0x2069, 0x0000, + 0x6837, 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, + 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x2069, 0x19db, + 0x683f, 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, + 0x6d34, 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, + 0x0780, 0x15c9, 0xd09c, 0x1500, 0x2071, 0x190e, 0x700f, 0x0001, + 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, + 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, + 0x6822, 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, + 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, + 0x2091, 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, + 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1061, + 0x0005, 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x6cc5, 0x0006, + 0x0016, 0x2001, 0x8004, 0x0006, 0x0804, 0x0d6e, 0x0096, 0x00f6, + 0x2079, 0x0050, 0x7044, 0xd084, 0x01c0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd09c, 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, - 0x900d, 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, - 0x7046, 0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, - 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, - 0x900d, 0x1904, 0x6b18, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, - 0xd09c, 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, - 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, - 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd09c, 0x0d50, - 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, 0x05a8, 0x00e6, - 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70bc, 0x8000, 0x70be, 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x6b11, 0x7838, - 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, - 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, - 0x080c, 0x8053, 0x00ee, 0x0804, 0x6abb, 0x2071, 0x1906, 0xa803, - 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, - 0x1e04, 0x6b58, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, 0x0e04, 0x6b42, - 0x2071, 0x1906, 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, - 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, - 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11c9, 0x2071, 0x1906, 0x080c, 0x6c8b, 0x002e, 0x00ee, 0x0005, - 0x2071, 0x1906, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, - 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, - 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70bc, 0x9200, 0x70be, 0x080c, 0x8053, 0x002e, - 0x00ee, 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103, 0x20a9, - 0x001c, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0, 0x9006, - 0x4004, 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a, 0xa982, - 0x0005, 0x2071, 0x1906, 0x7004, 0x0002, 0x6bc3, 0x6bc4, 0x6c8a, - 0x6bc4, 0x0d65, 0x6c8a, 0x0005, 0x2001, 0x1919, 0x2004, 0x0002, - 0x6bce, 0x6bce, 0x6c23, 0x6c24, 0x6bce, 0x6c24, 0x0126, 0x2091, - 0x8000, 0x1e0c, 0x6caa, 0x701c, 0x904d, 0x01e0, 0xa84c, 0x9005, - 0x01d8, 0x0e04, 0x6bf2, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, - 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x2071, 0x1906, - 0x080c, 0x6c8b, 0x012e, 0x0470, 0x2001, 0x005b, 0x2004, 0x9094, - 0x0780, 0x190c, 0x6c9f, 0xd09c, 0x2071, 0x1906, 0x1510, 0x2071, - 0x1906, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, - 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, - 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1906, 0x701c, - 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x19d3, - 0x683c, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, - 0x1814, 0x2004, 0x2009, 0x1b1d, 0x210c, 0x9102, 0x1500, 0x0126, - 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, - 0x0e04, 0x6c56, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, - 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11c9, 0x2069, 0x19d3, 0x683f, 0xffff, 0x012e, 0x00de, - 0x0126, 0x2091, 0x8000, 0x1e0c, 0x6d10, 0x701c, 0x904d, 0x0540, - 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500, - 0x2071, 0x1906, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, - 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, - 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2048, - 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, - 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x904d, - 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x080c, 0x1054, 0x0005, 0x012e, 0x0005, 0x2091, - 0x8000, 0x0e04, 0x6ca1, 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, - 0x0804, 0x0d6e, 0x0096, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, - 0x01c0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11c9, 0x00fe, 0x009e, - 0x0005, 0x782c, 0x9094, 0x0780, 0x1991, 0xd0a4, 0x0db8, 0x00e6, - 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1170, 0x2009, 0x182f, 0x210c, 0x918a, 0x0040, 0x0240, 0x7022, - 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, - 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x11c9, 0x00ee, 0x00fe, 0x009e, 0x0005, - 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, - 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, - 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11c9, 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, - 0x190c, 0x6c9f, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70bc, 0x8000, 0x70be, - 0x080c, 0x8053, 0x782c, 0x9094, 0x0780, 0x190c, 0x6c9f, 0xd0a4, - 0x1d70, 0x00d6, 0x2069, 0x0050, 0x693c, 0x2069, 0x1919, 0x6808, - 0x690a, 0x2069, 0x19d3, 0x9102, 0x1118, 0x683c, 0x9005, 0x1328, - 0x2001, 0x191a, 0x200c, 0x810d, 0x693e, 0x00de, 0x00ee, 0x00fe, - 0x0005, 0x7094, 0x908a, 0x0029, 0x1a0c, 0x0d65, 0x9082, 0x001d, - 0x003b, 0x0026, 0x2011, 0x1e00, 0x080c, 0x288c, 0x002e, 0x0005, - 0x6e3c, 0x6dc2, 0x6dde, 0x6e08, 0x6e2b, 0x6e6b, 0x6e7d, 0x6dde, - 0x6e53, 0x6d7d, 0x6dab, 0x6d7c, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x7097, 0x0028, - 0x2069, 0x195f, 0x2d04, 0x7002, 0x080c, 0x71d7, 0x6028, 0x9085, - 0x0600, 0x602a, 0x00b0, 0x7097, 0x0028, 0x2069, 0x195f, 0x2d04, - 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0x1a3b, 0x080c, 0x196c, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, - 0x1178, 0x6808, 0x9005, 0x1160, 0x7097, 0x0028, 0x2069, 0x195f, - 0x2d04, 0x7002, 0x080c, 0x7279, 0x6028, 0x9085, 0x0600, 0x602a, - 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2852, 0x000e, - 0x6124, 0xd1e4, 0x1190, 0x080c, 0x6eee, 0xd1d4, 0x1160, 0xd1dc, - 0x1138, 0xd1cc, 0x0150, 0x7097, 0x0020, 0x080c, 0x6eee, 0x0028, - 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, 0x2001, 0x0088, - 0x080c, 0x2852, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, - 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1996, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x70c2, 0x2001, 0x0080, 0x080c, - 0x2852, 0x7097, 0x0028, 0x0058, 0x7097, 0x001e, 0x0040, 0x7097, - 0x001d, 0x0028, 0x7097, 0x0020, 0x0010, 0x7097, 0x001f, 0x0005, - 0x080c, 0x1996, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, - 0x70c2, 0x2001, 0x0080, 0x080c, 0x2852, 0x6124, 0xd1d4, 0x1180, - 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x7097, - 0x0028, 0x0040, 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, - 0x7097, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, 0x2852, 0x6124, - 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1996, 0x7097, 0x001e, - 0x0010, 0x7097, 0x001d, 0x0005, 0x080c, 0x6f77, 0x6124, 0xd1dc, - 0x1188, 0x080c, 0x6eee, 0x0016, 0x080c, 0x1996, 0x001e, 0xd1d4, - 0x1128, 0xd1e4, 0x0138, 0x7097, 0x001e, 0x0020, 0x7097, 0x001f, - 0x080c, 0x6eee, 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2852, - 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0140, 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, - 0x7097, 0x0021, 0x0005, 0x080c, 0x6f77, 0x6124, 0xd1d4, 0x1150, - 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, 0x001e, 0x0028, 0x7097, - 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, - 0x080c, 0x2852, 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, - 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x7097, 0x001e, 0x0040, 0x7097, - 0x001d, 0x0028, 0x7097, 0x0020, 0x0010, 0x7097, 0x001f, 0x0005, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c, 0x7096, 0x11f8, - 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, - 0x2011, 0x0200, 0x080c, 0x288c, 0x002e, 0x080c, 0x2838, 0x6024, - 0xd0cc, 0x0148, 0x2001, 0x00a0, 0x080c, 0x2852, 0x080c, 0x7396, - 0x080c, 0x5cd7, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x70b0, 0x0150, 0x080c, 0x70a7, 0x1138, 0x2001, 0x0001, 0x080c, - 0x23e2, 0x080c, 0x706a, 0x00a0, 0x080c, 0x6f74, 0x0178, 0x2001, - 0x0001, 0x080c, 0x23e2, 0x7094, 0x9086, 0x001e, 0x0120, 0x7094, - 0x9086, 0x0022, 0x1118, 0x7097, 0x0025, 0x0010, 0x7097, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x6eff, 0x080c, 0x823e, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x6eff, 0x080c, 0x8235, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0x8f9c, 0x2071, 0x1800, 0x080c, 0x6e98, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x8f9c, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x080c, 0x98bb, 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, - 0x0002, 0x080c, 0x9326, 0x080c, 0x91e9, 0x080c, 0x81ea, 0x0036, - 0x901e, 0x080c, 0x9269, 0x003e, 0x080c, 0x98d7, 0x60e3, 0x0000, - 0x080c, 0xd60c, 0x080c, 0xd627, 0x2009, 0x0004, 0x080c, 0x283e, - 0x080c, 0x2758, 0x2001, 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, - 0x080c, 0x288c, 0x2011, 0x6eff, 0x080c, 0x823e, 0x080c, 0x70b0, - 0x0118, 0x9006, 0x080c, 0x2852, 0x080c, 0x0bab, 0x2001, 0x0001, - 0x080c, 0x23e2, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x6f0c, 0x2071, - 0x19d3, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, - 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, - 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, - 0x2852, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x6f84, 0x2091, 0x6000, - 0x1f04, 0x6f84, 0x015e, 0x00d6, 0x2069, 0x1800, 0x6898, 0x8001, - 0x0220, 0x0118, 0x689a, 0x00de, 0x0005, 0x689b, 0x0014, 0x68e8, - 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x824a, - 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x080c, 0x73a5, 0x2001, 0x193d, 0x2003, 0x0000, - 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, 0x24b1, 0x9006, 0x080c, - 0x2852, 0x080c, 0x5b92, 0x0026, 0x2011, 0xffff, 0x080c, 0x288c, - 0x002e, 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x2001, 0x194d, 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, - 0x0158, 0x9186, 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, - 0x705a, 0x7097, 0x0022, 0x0040, 0x7097, 0x0021, 0x0028, 0x7097, - 0x0023, 0x0010, 0x7097, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, - 0x2001, 0x0001, 0x080c, 0x24b1, 0x080c, 0x98bb, 0x0026, 0x080c, - 0x9b60, 0x002e, 0x080c, 0x98d7, 0x7000, 0x908e, 0x0004, 0x0118, - 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, - 0x080c, 0xbf61, 0x0118, 0x9006, 0x080c, 0x287c, 0x0804, 0x7066, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2838, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2852, 0x1f04, 0x700b, - 0x080c, 0x70ed, 0x012e, 0x015e, 0x080c, 0x70a7, 0x0170, 0x6044, - 0x9005, 0x0130, 0x080c, 0x70ed, 0x9006, 0x8001, 0x1df0, 0x0028, - 0x6804, 0xd0d4, 0x1110, 0x080c, 0x70ed, 0x080c, 0xbf61, 0x0118, - 0x9006, 0x080c, 0x287c, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, - 0x0130, 0x2009, 0x00c8, 0x2011, 0x6f0c, 0x080c, 0x81fc, 0x002e, - 0x001e, 0x080c, 0x804a, 0x7034, 0xc085, 0x7036, 0x2001, 0x194d, - 0x2003, 0x0004, 0x080c, 0x6d61, 0x080c, 0x70a7, 0x0138, 0x6804, - 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x739b, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1800, 0x080c, 0x8061, 0x080c, 0x8053, 0x080c, - 0x73a5, 0x2001, 0x193d, 0x2003, 0x0000, 0x9006, 0x7096, 0x60e2, - 0x6886, 0x080c, 0x24b1, 0x9006, 0x080c, 0x2852, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, 0x288c, 0x002e, - 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, - 0x194c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, - 0x538c, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x080c, 0x538c, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, - 0x0006, 0x080c, 0x538c, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, - 0x0005, 0x0006, 0x080c, 0x538c, 0x9084, 0x0030, 0x9086, 0x0020, - 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, - 0x0013, 0x0180, 0x0020, 0x080c, 0x24d1, 0x900e, 0x0028, 0x080c, - 0x665e, 0x1dc8, 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x2fd3, - 0x9006, 0x0019, 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, - 0x2e04, 0x0130, 0x080c, 0xbf5a, 0x1128, 0x9085, 0x0010, 0x0010, - 0x9084, 0xffef, 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, - 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, + 0x0013, 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, + 0x190c, 0x11d6, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, + 0x1991, 0xd0a4, 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, + 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x182f, 0x210c, + 0x918a, 0x0040, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, + 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8087, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, + 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, + 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, + 0x00ee, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, 0x7044, + 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, + 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, + 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11d6, 0x00fe, + 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x0db8, + 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, 0x2900, + 0x702e, 0x70bc, 0x8000, 0x70be, 0x080c, 0x8087, 0x782c, 0x9094, + 0x0780, 0x190c, 0x6cc3, 0xd0a4, 0x1d70, 0x00d6, 0x2069, 0x0050, + 0x693c, 0x2069, 0x1921, 0x6808, 0x690a, 0x2069, 0x19db, 0x9102, + 0x1118, 0x683c, 0x9005, 0x1328, 0x2001, 0x1922, 0x200c, 0x810d, + 0x693e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7094, 0x908a, 0x0029, + 0x1a0c, 0x0d65, 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00, + 0x080c, 0x28ac, 0x002e, 0x0005, 0x6e60, 0x6de6, 0x6e02, 0x6e2c, + 0x6e4f, 0x6e8f, 0x6ea1, 0x6e02, 0x6e77, 0x6da1, 0x6dcf, 0x6da0, + 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, + 0x9005, 0x1518, 0x7097, 0x0028, 0x2069, 0x1967, 0x2d04, 0x7002, + 0x080c, 0x71fa, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, 0x7097, + 0x0028, 0x2069, 0x1967, 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, + 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a43, 0x080c, + 0x1989, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, + 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, + 0x7097, 0x0028, 0x2069, 0x1967, 0x2d04, 0x7002, 0x080c, 0x729c, + 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, + 0x0090, 0x080c, 0x2872, 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, + 0x6f12, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x7097, + 0x0020, 0x080c, 0x6f12, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, + 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2872, 0x6124, 0xd1cc, + 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, + 0x080c, 0x19ae, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, + 0x70e6, 0x2001, 0x0080, 0x080c, 0x2872, 0x7097, 0x0028, 0x0058, + 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, + 0x0010, 0x7097, 0x001f, 0x0005, 0x080c, 0x19ae, 0x60e3, 0x0001, + 0x600c, 0xc0b4, 0x600e, 0x080c, 0x70e6, 0x2001, 0x0080, 0x080c, + 0x2872, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, + 0x9184, 0x1e00, 0x1158, 0x7097, 0x0028, 0x0040, 0x7097, 0x001e, + 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, 0x0005, 0x2001, + 0x00a0, 0x080c, 0x2872, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, + 0x080c, 0x19ae, 0x7097, 0x001e, 0x0010, 0x7097, 0x001d, 0x0005, + 0x080c, 0x6f9b, 0x6124, 0xd1dc, 0x1188, 0x080c, 0x6f12, 0x0016, + 0x080c, 0x19ae, 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x7097, + 0x001e, 0x0020, 0x7097, 0x001f, 0x080c, 0x6f12, 0x0005, 0x0006, + 0x2001, 0x00a0, 0x080c, 0x2872, 0x000e, 0x6124, 0xd1d4, 0x1160, + 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x7097, 0x001e, + 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x0021, 0x0005, 0x080c, + 0x6f9b, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, + 0x7097, 0x001e, 0x0028, 0x7097, 0x001d, 0x0010, 0x7097, 0x001f, + 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2872, 0x000e, 0x6124, + 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, + 0x7097, 0x001e, 0x0040, 0x7097, 0x001d, 0x0028, 0x7097, 0x0020, + 0x0010, 0x7097, 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, + 0x8000, 0x080c, 0x70ba, 0x11f8, 0x2001, 0x180c, 0x200c, 0xd1b4, + 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200, 0x080c, 0x28ac, + 0x002e, 0x080c, 0x2858, 0x6024, 0xd0cc, 0x0148, 0x2001, 0x00a0, + 0x080c, 0x2872, 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x0428, 0x6028, + 0xc0cd, 0x602a, 0x0408, 0x080c, 0x70d4, 0x0150, 0x080c, 0x70cb, + 0x1138, 0x2001, 0x0001, 0x080c, 0x23fe, 0x080c, 0x708e, 0x00a0, + 0x080c, 0x6f98, 0x0178, 0x2001, 0x0001, 0x080c, 0x23fe, 0x7094, + 0x9086, 0x001e, 0x0120, 0x7094, 0x9086, 0x0022, 0x1118, 0x7097, + 0x0025, 0x0010, 0x7097, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, + 0x001e, 0x0005, 0x0026, 0x2011, 0x6f23, 0x080c, 0x8272, 0x002e, + 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x6f23, 0x080c, 0x8269, + 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x8fd0, + 0x2071, 0x1800, 0x080c, 0x6ebc, 0x001e, 0x00fe, 0x00ee, 0x0005, + 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0126, + 0x080c, 0x8fd0, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, + 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c, 0x98c7, 0x2011, + 0x0003, 0x080c, 0x9324, 0x2011, 0x0002, 0x080c, 0x932e, 0x080c, + 0x921d, 0x080c, 0x821e, 0x0036, 0x901e, 0x080c, 0x929d, 0x003e, + 0x080c, 0x98e3, 0x60e3, 0x0000, 0x080c, 0xd644, 0x080c, 0xd65f, + 0x2009, 0x0004, 0x080c, 0x285e, 0x080c, 0x2774, 0x2001, 0x1800, + 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x28ac, 0x2011, 0x6f23, + 0x080c, 0x8272, 0x080c, 0x70d4, 0x0118, 0x9006, 0x080c, 0x2872, + 0x080c, 0x0bab, 0x2001, 0x0001, 0x080c, 0x23fe, 0x012e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0026, + 0x00e6, 0x2011, 0x6f30, 0x2071, 0x19db, 0x701c, 0x9206, 0x1118, + 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, 0x002e, 0x0005, + 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, 0x9086, 0x00c0, + 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2872, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x6fa8, 0x2091, 0x6000, 0x1f04, 0x6fa8, 0x015e, 0x00d6, + 0x2069, 0x1800, 0x6898, 0x8001, 0x0220, 0x0118, 0x689a, 0x00de, + 0x0005, 0x689b, 0x0014, 0x68e8, 0xd0dc, 0x0dc8, 0x6800, 0x9086, + 0x0001, 0x1da8, 0x080c, 0x827e, 0x0c90, 0x00c6, 0x00d6, 0x00e6, + 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x73c8, + 0x2001, 0x1945, 0x2003, 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, + 0x080c, 0x24cd, 0x9006, 0x080c, 0x2872, 0x080c, 0x5bb2, 0x0026, + 0x2011, 0xffff, 0x080c, 0x28ac, 0x002e, 0x602b, 0x182c, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, + 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x1955, 0x200c, 0x9186, + 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, + 0x9186, 0x0003, 0x0158, 0x0804, 0x707e, 0x7097, 0x0022, 0x0040, + 0x7097, 0x0021, 0x0028, 0x7097, 0x0023, 0x0010, 0x7097, 0x0024, + 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x24cd, + 0x080c, 0x98c7, 0x0026, 0x080c, 0x9b6c, 0x002e, 0x080c, 0x98e3, + 0x7000, 0x908e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, + 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, + 0xd0ac, 0x0150, 0x012e, 0x015e, 0x080c, 0xbf8f, 0x0118, 0x9006, + 0x080c, 0x289c, 0x0804, 0x708a, 0x6800, 0x9084, 0x00a1, 0xc0bd, + 0x6802, 0x080c, 0x2858, 0x6904, 0xd1d4, 0x1140, 0x2001, 0x0100, + 0x080c, 0x2872, 0x1f04, 0x702f, 0x080c, 0x7111, 0x012e, 0x015e, + 0x080c, 0x70cb, 0x0170, 0x6044, 0x9005, 0x0130, 0x080c, 0x7111, + 0x9006, 0x8001, 0x1df0, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, + 0x7111, 0x080c, 0xbf8f, 0x0118, 0x9006, 0x080c, 0x289c, 0x0016, + 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, 0x2011, + 0x6f30, 0x080c, 0x8230, 0x002e, 0x001e, 0x080c, 0x807e, 0x7034, + 0xc085, 0x7036, 0x2001, 0x1955, 0x2003, 0x0004, 0x080c, 0x6d85, + 0x080c, 0x70cb, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, 0x1100, + 0x080c, 0x73be, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, + 0x8095, 0x080c, 0x8087, 0x080c, 0x73c8, 0x2001, 0x1945, 0x2003, + 0x0000, 0x9006, 0x7096, 0x60e2, 0x6886, 0x080c, 0x24cd, 0x9006, + 0x080c, 0x2872, 0x6043, 0x0090, 0x6043, 0x0010, 0x0026, 0x2011, + 0xffff, 0x080c, 0x28ac, 0x002e, 0x602b, 0x182c, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x0006, 0x2001, 0x1954, 0x2004, 0x9086, 0xaaaa, + 0x000e, 0x0005, 0x0006, 0x080c, 0x53ac, 0x9084, 0x0030, 0x9086, + 0x0000, 0x000e, 0x0005, 0x0006, 0x080c, 0x53ac, 0x9084, 0x0030, + 0x9086, 0x0030, 0x000e, 0x0005, 0x0006, 0x080c, 0x53ac, 0x9084, + 0x0030, 0x9086, 0x0010, 0x000e, 0x0005, 0x0006, 0x080c, 0x53ac, + 0x9084, 0x0030, 0x9086, 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, + 0x2001, 0x180c, 0x2004, 0x908c, 0x0013, 0x0180, 0x0020, 0x080c, + 0x24ed, 0x900e, 0x0028, 0x080c, 0x6682, 0x1dc8, 0x2009, 0x0002, + 0x2019, 0x0028, 0x080c, 0x2ff3, 0x9006, 0x0019, 0x001e, 0x003e, + 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, 0xbf88, + 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, 0x00ee, + 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, + 0x0006, 0x6028, 0x0006, 0x080c, 0x28cf, 0x080c, 0x2902, 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x20a9, - 0x0002, 0x080c, 0x2819, 0x0026, 0x2011, 0x0040, 0x080c, 0x288c, + 0x0002, 0x080c, 0x2839, 0x0026, 0x2011, 0x0040, 0x080c, 0x28ac, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, - 0x24b1, 0x2001, 0x00a0, 0x0006, 0x080c, 0xbf61, 0x000e, 0x0130, - 0x080c, 0x2870, 0x9006, 0x080c, 0x287c, 0x0010, 0x080c, 0x2852, + 0x24cd, 0x2001, 0x00a0, 0x0006, 0x080c, 0xbf8f, 0x000e, 0x0130, + 0x080c, 0x2890, 0x9006, 0x080c, 0x289c, 0x0010, 0x080c, 0x2872, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, - 0x0100, 0x080c, 0x27c9, 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x9919, 0x0158, 0x2001, - 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c, 0x98ac, - 0x0804, 0x71c9, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, 0x6028, - 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x288c, 0x2001, - 0x0090, 0x080c, 0x2852, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1558, - 0x1d04, 0x7165, 0x2091, 0x6000, 0x1f04, 0x7165, 0x080c, 0x98bb, - 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, 0x0002, 0x080c, 0x9326, - 0x080c, 0x91e9, 0x901e, 0x080c, 0x9269, 0x2001, 0x0386, 0x2003, - 0x7000, 0x080c, 0x98d7, 0x2001, 0x00a0, 0x080c, 0x2852, 0x080c, - 0x7396, 0x080c, 0x5cd7, 0x080c, 0xbf61, 0x0110, 0x080c, 0x0cd1, - 0x9085, 0x0001, 0x04e0, 0x2001, 0x0386, 0x2004, 0xd0ac, 0x0110, - 0x080c, 0x1996, 0x60e3, 0x0000, 0x2001, 0x0002, 0x080c, 0x24b1, - 0x60e2, 0x2001, 0x0080, 0x080c, 0x2852, 0x20a9, 0x0366, 0x2011, - 0x1e00, 0x080c, 0x288c, 0x2009, 0x1e00, 0x080c, 0x2838, 0x6024, - 0x910c, 0x0140, 0x1d04, 0x71a7, 0x2091, 0x6000, 0x1f04, 0x71a7, - 0x0804, 0x716e, 0x2001, 0x0386, 0x2003, 0x7000, 0x6028, 0x9085, - 0x1e00, 0x602a, 0x70b0, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x080c, 0xbf61, 0x0110, 0x080c, 0x0cd1, 0x9006, 0x00ee, - 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, + 0x0100, 0x080c, 0x27e5, 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7000, 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, - 0x2004, 0x9084, 0x5540, 0x9086, 0x5540, 0x1128, 0x2069, 0x1a46, - 0x2d04, 0x8000, 0x206a, 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, - 0x0120, 0x6884, 0x9005, 0x1904, 0x7240, 0x2001, 0x0088, 0x080c, - 0x2852, 0x9006, 0x60e2, 0x6886, 0x080c, 0x24b1, 0x2069, 0x0200, - 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x01d0, 0x6028, 0x9084, - 0xfbff, 0x602a, 0x2011, 0x0400, 0x080c, 0x288c, 0x2069, 0x195f, - 0x7000, 0x206a, 0x7097, 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, - 0x1d04, 0x7220, 0x2091, 0x6000, 0x1f04, 0x7220, 0x0804, 0x7271, - 0x2069, 0x0140, 0x20a9, 0x0384, 0x2011, 0x1e00, 0x080c, 0x288c, - 0x2009, 0x1e00, 0x080c, 0x2838, 0x6024, 0x910c, 0x0528, 0x9084, - 0x1a00, 0x1510, 0x1d04, 0x722c, 0x2091, 0x6000, 0x1f04, 0x722c, - 0x080c, 0x98bb, 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, 0x0002, - 0x080c, 0x9326, 0x080c, 0x91e9, 0x901e, 0x080c, 0x9269, 0x080c, - 0x98d7, 0x2001, 0x00a0, 0x080c, 0x2852, 0x080c, 0x7396, 0x080c, - 0x5cd7, 0x9085, 0x0001, 0x00a8, 0x2001, 0x0080, 0x080c, 0x2852, - 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, - 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, 0x080c, 0x24b1, 0x60e2, - 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, - 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01e8, - 0x080c, 0x98bb, 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, 0x0002, - 0x080c, 0x9326, 0x080c, 0x91e9, 0x901e, 0x080c, 0x9269, 0x080c, - 0x98d7, 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2852, 0x080c, - 0x7396, 0x080c, 0x5cd7, 0x0804, 0x7313, 0x2001, 0x180c, 0x200c, - 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, 0x6ef4, 0x2069, 0x0140, - 0x2001, 0x0080, 0x080c, 0x2852, 0x60e3, 0x0000, 0x2069, 0x0200, - 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, 0x0190, 0x6028, 0x9084, - 0xfdff, 0x602a, 0x2011, 0x0200, 0x080c, 0x288c, 0x2069, 0x195f, - 0x7000, 0x206a, 0x7097, 0x0027, 0x7003, 0x0001, 0x0804, 0x7313, - 0x2011, 0x1e00, 0x080c, 0x288c, 0x2009, 0x1e00, 0x080c, 0x2838, - 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x72d0, - 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x8092, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19d3, 0x7018, - 0x00ee, 0x9005, 0x19e8, 0x01f8, 0x0026, 0x2011, 0x6f0c, 0x080c, - 0x8138, 0x2011, 0x6eff, 0x080c, 0x823e, 0x002e, 0x2069, 0x0140, - 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0x0002, 0x080c, 0x24b1, 0x60e2, 0x2001, 0x180c, - 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, - 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xbf5a, - 0x1904, 0x7380, 0x7130, 0xd184, 0x1170, 0x080c, 0x317a, 0x0138, - 0xc18d, 0x7132, 0x2011, 0x1854, 0x2214, 0xd2ac, 0x1120, 0x7030, - 0xd08c, 0x0904, 0x7380, 0x2011, 0x1854, 0x220c, 0x0438, 0x0016, - 0x2019, 0x000e, 0x080c, 0xd1fc, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x626b, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xd284, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x83cd, 0x001e, - 0x8108, 0x1f04, 0x7349, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x2fd3, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x626b, - 0x1110, 0x080c, 0x5cf1, 0x8108, 0x1f04, 0x7376, 0x00be, 0x015e, - 0x080c, 0x1996, 0x080c, 0x98bb, 0x080c, 0x9b60, 0x080c, 0x98d7, - 0x60e3, 0x0000, 0x080c, 0x5cd7, 0x080c, 0x6fc7, 0x00ee, 0x00ce, - 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x194d, - 0x2003, 0x0001, 0x0005, 0x2001, 0x194d, 0x2003, 0x0000, 0x0005, - 0x2001, 0x194c, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x194c, 0x2003, - 0x0000, 0x0005, 0x2071, 0x18f0, 0x7003, 0x0000, 0x7007, 0x0000, - 0x080c, 0x103b, 0x090c, 0x0d65, 0xa8ab, 0xdcb0, 0x2900, 0x704e, - 0x080c, 0x103b, 0x090c, 0x0d65, 0xa8ab, 0xdcb0, 0x2900, 0x7052, - 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, - 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, - 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, - 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, - 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, - 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18f0, - 0x6807, 0x0001, 0x00de, 0x080c, 0x79a2, 0x9006, 0x00ee, 0x0005, - 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, 0x740c, - 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18f0, 0x7004, 0x0002, - 0x7422, 0x7423, 0x746e, 0x74c9, 0x760a, 0x7420, 0x7420, 0x7634, - 0x080c, 0x0d65, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, 0x2003, - 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x7a2e, 0xd0a4, 0x0570, - 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1640, 0x1d04, 0x7440, - 0x2001, 0x19d6, 0x200c, 0x8109, 0x0508, 0x2091, 0x6000, 0x2102, + 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0x9925, 0x0158, 0x2001, + 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c, 0x98b8, + 0x0804, 0x71ec, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, 0x6028, + 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x28ac, 0x2001, + 0x0090, 0x080c, 0x2872, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1558, + 0x1d04, 0x718d, 0x2091, 0x6000, 0x1f04, 0x718d, 0x080c, 0x98c7, + 0x2011, 0x0003, 0x080c, 0x9324, 0x2011, 0x0002, 0x080c, 0x932e, + 0x080c, 0x921d, 0x901e, 0x080c, 0x929d, 0x2001, 0x0386, 0x2003, + 0x7000, 0x080c, 0x98e3, 0x2001, 0x00a0, 0x080c, 0x2872, 0x080c, + 0x73b9, 0x080c, 0x5cf7, 0x080c, 0xbf8f, 0x0110, 0x080c, 0x0cd1, + 0x9085, 0x0001, 0x04b8, 0x080c, 0x19ae, 0x60e3, 0x0000, 0x2001, + 0x0002, 0x080c, 0x24cd, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2872, + 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x28ac, 0x2009, 0x1e00, + 0x080c, 0x2858, 0x6024, 0x910c, 0x0140, 0x1d04, 0x71ca, 0x2091, + 0x6000, 0x1f04, 0x71ca, 0x0804, 0x7196, 0x2001, 0x0386, 0x2003, + 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b0, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xbf8f, 0x0110, 0x080c, + 0x0cd1, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, + 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, 0x9086, 0x0003, + 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, 0x9086, 0x5540, + 0x1128, 0x2069, 0x1a4e, 0x2d04, 0x8000, 0x206a, 0x2069, 0x0140, + 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, 0x1904, 0x7263, + 0x2001, 0x0088, 0x080c, 0x2872, 0x9006, 0x60e2, 0x6886, 0x080c, + 0x24cd, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, + 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011, 0x0400, 0x080c, + 0x28ac, 0x2069, 0x1967, 0x7000, 0x206a, 0x7097, 0x0026, 0x7003, + 0x0001, 0x20a9, 0x0002, 0x1d04, 0x7243, 0x2091, 0x6000, 0x1f04, + 0x7243, 0x0804, 0x7294, 0x2069, 0x0140, 0x20a9, 0x0384, 0x2011, + 0x1e00, 0x080c, 0x28ac, 0x2009, 0x1e00, 0x080c, 0x2858, 0x6024, + 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, 0x724f, 0x2091, + 0x6000, 0x1f04, 0x724f, 0x080c, 0x98c7, 0x2011, 0x0003, 0x080c, + 0x9324, 0x2011, 0x0002, 0x080c, 0x932e, 0x080c, 0x921d, 0x901e, + 0x080c, 0x929d, 0x080c, 0x98e3, 0x2001, 0x00a0, 0x080c, 0x2872, + 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x9085, 0x0001, 0x00a8, 0x2001, + 0x0080, 0x080c, 0x2872, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, + 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, + 0x080c, 0x24cd, 0x60e2, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x6020, + 0x9084, 0x00c0, 0x01e8, 0x080c, 0x98c7, 0x2011, 0x0003, 0x080c, + 0x9324, 0x2011, 0x0002, 0x080c, 0x932e, 0x080c, 0x921d, 0x901e, + 0x080c, 0x929d, 0x080c, 0x98e3, 0x2069, 0x0140, 0x2001, 0x00a0, + 0x080c, 0x2872, 0x080c, 0x73b9, 0x080c, 0x5cf7, 0x0804, 0x7336, + 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, + 0x6f18, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2872, 0x60e3, + 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, + 0x0190, 0x6028, 0x9084, 0xfdff, 0x602a, 0x2011, 0x0200, 0x080c, + 0x28ac, 0x2069, 0x1967, 0x7000, 0x206a, 0x7097, 0x0027, 0x7003, + 0x0001, 0x0804, 0x7336, 0x2011, 0x1e00, 0x080c, 0x28ac, 0x2009, + 0x1e00, 0x080c, 0x2858, 0x6024, 0x910c, 0x01c8, 0x9084, 0x1c00, + 0x11b0, 0x1d04, 0x72f3, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, + 0x080c, 0x80c6, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, + 0x2071, 0x19db, 0x7070, 0x00ee, 0x9005, 0x19e8, 0x00f8, 0x0026, + 0x2011, 0x6f30, 0x080c, 0x816c, 0x2011, 0x6f23, 0x080c, 0x8272, + 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000, 0x70b0, 0x9005, 0x1118, + 0x6887, 0x0001, 0x0008, 0x6886, 0x2001, 0x0002, 0x080c, 0x24cd, + 0x60e2, 0x2001, 0x180c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, + 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, + 0x0026, 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x1800, 0x080c, 0xbf88, 0x1904, 0x73a3, 0x7130, 0xd184, 0x1170, + 0x080c, 0x319a, 0x0138, 0xc18d, 0x7132, 0x2011, 0x185c, 0x2214, + 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x73a3, 0x2011, 0x185c, + 0x220c, 0x0438, 0x0016, 0x2019, 0x000e, 0x080c, 0xd234, 0x0156, + 0x00b6, 0x20a9, 0x007f, 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, + 0x0080, 0x0188, 0x080c, 0x628f, 0x1170, 0x2120, 0x9006, 0x0016, + 0x2009, 0x000e, 0x080c, 0xd2bc, 0x2009, 0x0001, 0x2011, 0x0100, + 0x080c, 0x8401, 0x001e, 0x8108, 0x1f04, 0x736c, 0x00be, 0x015e, + 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, + 0x080c, 0x2ff3, 0x001e, 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, + 0x900e, 0x080c, 0x628f, 0x1110, 0x080c, 0x5d11, 0x8108, 0x1f04, + 0x7399, 0x00be, 0x015e, 0x080c, 0x19ae, 0x080c, 0x98c7, 0x080c, + 0x9b6c, 0x080c, 0x98e3, 0x60e3, 0x0000, 0x080c, 0x5cf7, 0x080c, + 0x6feb, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, + 0x0005, 0x2001, 0x1955, 0x2003, 0x0001, 0x0005, 0x2001, 0x1955, + 0x2003, 0x0000, 0x0005, 0x2001, 0x1954, 0x2003, 0xaaaa, 0x0005, + 0x2001, 0x1954, 0x2003, 0x0000, 0x0005, 0x2071, 0x18f8, 0x7003, + 0x0000, 0x7007, 0x0000, 0x080c, 0x1048, 0x090c, 0x0d65, 0xa8ab, + 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1048, 0x090c, 0x0d65, 0xa8ab, + 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, + 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, + 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, + 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, + 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, + 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, + 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, + 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, + 0x00d6, 0x2069, 0x18f8, 0x6807, 0x0001, 0x00de, 0x080c, 0x79c6, + 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, + 0x818d, 0x1f04, 0x742f, 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, + 0x18f8, 0x7004, 0x0002, 0x7445, 0x7446, 0x7492, 0x74ed, 0x762e, + 0x7443, 0x7443, 0x7658, 0x080c, 0x0d65, 0x0005, 0x2079, 0x0040, + 0x2001, 0x1dc0, 0x2003, 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, + 0x7a52, 0xd0a4, 0x0578, 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, + 0x1648, 0x1d04, 0x7463, 0x2001, 0x19de, 0x200c, 0x8109, 0x0510, + 0x2091, 0x6000, 0x2102, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, + 0xa864, 0x9084, 0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, + 0x1800, 0x200c, 0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x7482, + 0x744c, 0x7482, 0x7480, 0x7482, 0x7482, 0x7482, 0x7482, 0x7482, + 0x080c, 0x74ed, 0x782c, 0xd09c, 0x090c, 0x79c6, 0x0005, 0x9082, + 0x005a, 0x1218, 0x2100, 0x003b, 0x0c10, 0x080c, 0x7523, 0x0c90, + 0x00e3, 0x08e8, 0x0005, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7545, 0x7523, 0x7523, 0x7523, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x752f, + 0x7523, 0x772d, 0x7523, 0x7523, 0x7523, 0x7545, 0x7523, 0x752f, + 0x776e, 0x77af, 0x77f6, 0x780a, 0x7523, 0x7523, 0x7545, 0x752f, + 0x7523, 0x7523, 0x7602, 0x78b5, 0x78d0, 0x7523, 0x7545, 0x7523, + 0x7523, 0x7523, 0x7523, 0x75f8, 0x78d0, 0x7523, 0x7523, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7559, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, + 0x79f6, 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x756d, 0x7523, + 0x7523, 0x7523, 0x7523, 0x7523, 0x7523, 0x2079, 0x0040, 0x7004, + 0x9086, 0x0003, 0x1198, 0x782c, 0x080c, 0x79ef, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, - 0x908a, 0x0040, 0x0608, 0x00b8, 0x2001, 0x1800, 0x200c, 0x9186, - 0x0003, 0x1160, 0x7104, 0x9186, 0x0004, 0x0140, 0x9186, 0x0007, - 0x0128, 0x9186, 0x0003, 0x1968, 0x080c, 0x74c9, 0x782c, 0xd09c, - 0x090c, 0x79a2, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, 0x003b, - 0x0c18, 0x080c, 0x74ff, 0x0c90, 0x00e3, 0x08f0, 0x0005, 0x74ff, - 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x7521, - 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x74ff, 0x74ff, 0x750b, 0x74ff, 0x7709, 0x74ff, 0x74ff, - 0x74ff, 0x7521, 0x74ff, 0x750b, 0x774a, 0x778b, 0x77d2, 0x77e6, - 0x74ff, 0x74ff, 0x7521, 0x750b, 0x74ff, 0x74ff, 0x75de, 0x7891, - 0x78ac, 0x74ff, 0x7521, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x75d4, - 0x78ac, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x74ff, 0x7535, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x79d2, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x74ff, 0x7549, 0x74ff, 0x74ff, 0x74ff, 0x74ff, 0x74ff, - 0x74ff, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, 0x782c, - 0x080c, 0x79cb, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, 0xa802, - 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, 0x002b, - 0x0c50, 0x00e9, 0x080c, 0x79a2, 0x0005, 0x74ff, 0x750b, 0x76f5, - 0x74ff, 0x750b, 0x74ff, 0x750b, 0x750b, 0x74ff, 0x750b, 0x76f5, - 0x750b, 0x750b, 0x750b, 0x750b, 0x750b, 0x74ff, 0x750b, 0x76f5, - 0x74ff, 0x74ff, 0x750b, 0x74ff, 0x74ff, 0x74ff, 0x750b, 0x00e6, - 0x2071, 0x18f0, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, 0x2009, - 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, 0x2009, - 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, 0x00ff, - 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6991, 0x012e, - 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, 0x1120, - 0x7007, 0x0001, 0x0804, 0x76b3, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x76b3, 0x0005, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x76ce, - 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x76ce, - 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, - 0x7507, 0x7007, 0x0001, 0x2009, 0x1833, 0x210c, 0x81ff, 0x1904, - 0x75ab, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x668a, 0x002e, 0x0578, 0x0016, - 0xa998, 0x080c, 0x66d4, 0x001e, 0x1548, 0x0400, 0x080c, 0x7096, - 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e, - 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x668a, 0x002e, 0x01b0, - 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000, - 0x080c, 0x66d4, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, 0x4005, - 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, 0x9084, - 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x5f02, 0x1108, 0x0005, - 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, - 0x6991, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, 0x7559, - 0x9186, 0x0064, 0x0904, 0x7559, 0x9186, 0x007c, 0x0904, 0x7559, - 0x9186, 0x0028, 0x0904, 0x7559, 0x9186, 0x0038, 0x0904, 0x7559, - 0x9186, 0x0078, 0x0904, 0x7559, 0x9186, 0x005f, 0x0904, 0x7559, - 0x9186, 0x0056, 0x0904, 0x7559, 0xa897, 0x4005, 0xa89b, 0x0001, - 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086, - 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x78c3, 0x2900, 0x7016, - 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, - 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, - 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x750f, - 0xaab4, 0x928a, 0x0002, 0x1a04, 0x750f, 0x82ff, 0x1138, 0xa8b8, - 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7671, 0x0018, 0x9280, 0x7667, - 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7652, 0x080c, 0x103b, - 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, - 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, - 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, - 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, - 0x810b, 0xa17e, 0x080c, 0x1117, 0xa06c, 0x908e, 0x0100, 0x0170, - 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, - 0x080c, 0x1054, 0x7014, 0x2048, 0x0804, 0x750f, 0x7020, 0x2048, - 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, - 0x0804, 0x760a, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, - 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x001e, 0x0904, 0x78c3, 0x0804, 0x76b3, 0x7669, - 0x766d, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, - 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, - 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, - 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, - 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, - 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, - 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, - 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, - 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, - 0x006e, 0x007e, 0x0005, 0x2009, 0x1833, 0x210c, 0x81ff, 0x1178, - 0x080c, 0x5d51, 0x1108, 0x0005, 0x080c, 0x6ba2, 0x0126, 0x2091, - 0x8000, 0x080c, 0xbb45, 0x080c, 0x6991, 0x012e, 0x0ca0, 0x080c, - 0xbf5a, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1833, - 0x210c, 0x81ff, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, 0x0000, - 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x5e64, 0x1138, 0x0005, 0x9006, - 0xa87a, 0x080c, 0x5ddf, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, - 0xa87a, 0xa982, 0x080c, 0x6991, 0x012e, 0x0cb0, 0x2001, 0x0028, - 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x7018, 0xa802, 0x2908, - 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, - 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, 0x080f, - 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, 0x00ff, - 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, 0x0190, - 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, 0x11d8, - 0xa974, 0x080c, 0x626b, 0x11b8, 0x0066, 0xae80, 0x080c, 0x637b, - 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, 0x2412, - 0x004e, 0x00c6, 0x080c, 0x626b, 0x1110, 0x080c, 0x654e, 0x8108, - 0x1f04, 0x7732, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, 0x1054, - 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6991, 0x012e, - 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, - 0x6662, 0x0580, 0x2061, 0x1a3e, 0x6100, 0xd184, 0x0178, 0xa888, - 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, 0x9005, - 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, 0x0001, - 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, 0xa888, - 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, 0x00ff, - 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, 0x012e, - 0x0804, 0x798c, 0x012e, 0x0804, 0x7986, 0x012e, 0x0804, 0x7980, - 0x012e, 0x0804, 0x7983, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x080c, 0x6662, 0x05e0, 0x2061, 0x1a3e, 0x6000, 0xd084, 0x05b8, - 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, 0x0170, - 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, 0x0620, - 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, 0x000c, - 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, 0x1120, - 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, 0x2100, - 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, 0x6206, - 0x630a, 0x012e, 0x0804, 0x798c, 0x012e, 0x0804, 0x7989, 0x012e, - 0x0804, 0x7986, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, - 0x1a3e, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, - 0x012e, 0x0804, 0x799a, 0x012e, 0x0804, 0x7989, 0x00b6, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, 0x0148, - 0x00c6, 0x2061, 0x1a3e, 0x6000, 0x9084, 0xfcff, 0x6002, 0x00ce, - 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, 0x2001, - 0x1833, 0x2004, 0x9005, 0x0118, 0x080c, 0x9c14, 0x0068, 0x6017, - 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, 0x6162, - 0x2009, 0x0041, 0x080c, 0x9c76, 0xa988, 0x918c, 0xff00, 0x9186, - 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, 0x83cd, - 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a3e, 0x6000, 0xd08c, - 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x00be, - 0x0804, 0x798c, 0x00ce, 0x012e, 0x00be, 0x0804, 0x7986, 0xa984, - 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, 0x0045, - 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, 0xc194, - 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, 0x1d10, - 0xa974, 0x080c, 0x626b, 0x1968, 0xb800, 0xc0e4, 0xb802, 0x0848, - 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1956, 0x2004, - 0x601a, 0x0804, 0x7821, 0xa88c, 0x9065, 0x0960, 0x00e6, 0xa890, - 0x9075, 0x2001, 0x1833, 0x2004, 0x9005, 0x0150, 0x080c, 0x9c14, - 0x8eff, 0x0118, 0x2e60, 0x080c, 0x9c14, 0x00ee, 0x0804, 0x7821, - 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0xa8a0, - 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, 0x6016, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, 0x00ee, 0x0804, - 0x7821, 0x2061, 0x1a3e, 0x6000, 0xd084, 0x0190, 0xd08c, 0x1904, - 0x799a, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, 0x6206, - 0x012e, 0x0804, 0x799a, 0x012e, 0xa883, 0x0016, 0x0804, 0x7993, - 0xa883, 0x0007, 0x0804, 0x7993, 0xa864, 0x8007, 0x9084, 0x00ff, - 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, 0x080c, - 0x7507, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x78c3, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x903e, 0x2061, 0x1800, 0x61cc, 0x81ff, 0x1904, 0x7945, 0x6130, - 0xd194, 0x1904, 0x796f, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x0a04, - 0x7939, 0x6064, 0x9e02, 0x1a04, 0x7939, 0x7120, 0x9186, 0x0006, - 0x1904, 0x792b, 0x7010, 0x905d, 0x0904, 0x7945, 0xb800, 0xd0e4, - 0x1904, 0x7969, 0x2061, 0x1a3e, 0x6100, 0x9184, 0x0301, 0x9086, - 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7972, 0xa883, 0x0000, - 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, 0xa87c, - 0xd0f4, 0x1904, 0x7975, 0x080c, 0x5388, 0xd09c, 0x1118, 0xa87c, - 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x82bd, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, 0xa87c, - 0xd0f4, 0x1904, 0x7975, 0x012e, 0x00ee, 0x00be, 0x0005, 0x012e, - 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7993, 0xd184, 0x0db8, - 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x626b, 0x15d0, 0xb800, - 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, 0x0002, - 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, 0xa883, - 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x538c, 0xd0fc, - 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x02c0, 0x6064, 0x9e02, - 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, 0x0170, - 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, 0x0007, - 0x1904, 0x78cf, 0x7003, 0x0002, 0x0804, 0x78cf, 0xa883, 0x0028, - 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, 0xa883, - 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, 0x0002, - 0x601b, 0x0014, 0x080c, 0xce09, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, - 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, 0x9084, - 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, 0x6991, - 0x012e, 0x0005, 0x080c, 0x1054, 0x0005, 0x00d6, 0x080c, 0x82b4, - 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, 0x7a2e, - 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70bc, 0x90ea, 0x0040, 0x0278, - 0x8001, 0x70be, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, 0xa802, - 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, 0x012e, - 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, 0x7a2e, - 0x000e, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, - 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x7a1f, 0xa97c, - 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, - 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, - 0x080c, 0x9b84, 0x1118, 0x080c, 0x9c49, 0x05a8, 0x6212, 0xa874, - 0x0002, 0x79fd, 0x7a02, 0x7a05, 0x7a0b, 0x2019, 0x0002, 0x080c, - 0xd1fc, 0x0060, 0x080c, 0xd18c, 0x0048, 0x2019, 0x0002, 0xa980, - 0x080c, 0xd1ab, 0x0018, 0xa980, 0x080c, 0xd18c, 0x080c, 0x9bda, - 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6991, 0x012e, - 0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, - 0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, - 0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, - 0x0e04, 0x7a30, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, - 0x0d6e, 0x2001, 0x1833, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, - 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, - 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x153a, 0x00fe, - 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, - 0x0005, 0x781c, 0xd08c, 0x0904, 0x7ab1, 0x68bc, 0x90aa, 0x0005, - 0x0a04, 0x804a, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d65, 0x9584, - 0x00f6, 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, - 0x9584, 0x0700, 0x8007, 0x04f0, 0x7000, 0x9084, 0xff00, 0x9086, - 0x8100, 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, - 0xff00, 0x9086, 0x8100, 0x11c0, 0x080c, 0xd5e4, 0x080c, 0x7f91, - 0x7817, 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x7fed, - 0x19c8, 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x7b01, 0x080c, - 0x1fc8, 0x005e, 0x004e, 0x0020, 0x080c, 0xd5e4, 0x7817, 0x0140, - 0x080c, 0x7096, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, - 0x688f, 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, - 0x0489, 0x0005, 0x0002, 0x7abe, 0x7db3, 0x7abb, 0x7abb, 0x7abb, - 0x7abb, 0x7abb, 0x7abb, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, - 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x688e, 0x9286, - 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x53e9, - 0x0070, 0x080c, 0x7b21, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, - 0x7cf0, 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x7ec7, 0x7817, - 0x0140, 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, - 0x8048, 0x2518, 0x080c, 0x48da, 0x003e, 0x002e, 0x0005, 0x0036, - 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, - 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, - 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, - 0x8048, 0x080c, 0x48da, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, - 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, - 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x7cc1, 0x9186, 0x0023, - 0x15c0, 0x080c, 0x7f5c, 0x0904, 0x7cc1, 0x6120, 0x9186, 0x0001, - 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, - 0x000a, 0x1904, 0x7cc1, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, - 0x1130, 0x2009, 0x0015, 0x080c, 0x9c76, 0x0804, 0x7cc1, 0x908e, - 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, - 0x9c76, 0x0804, 0x7cc1, 0x908e, 0x0100, 0x1904, 0x7cc1, 0x7034, - 0x9005, 0x1904, 0x7cc1, 0x2009, 0x0016, 0x080c, 0x9c76, 0x0804, - 0x7cc1, 0x9186, 0x0022, 0x1904, 0x7cc1, 0x7030, 0x908e, 0x0300, - 0x1580, 0x68d8, 0xd0a4, 0x0528, 0xc0b5, 0x68da, 0x7100, 0x918c, - 0x00ff, 0x697a, 0x7004, 0x687e, 0x00f6, 0x2079, 0x0100, 0x79e6, - 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x2486, - 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x243d, 0x695a, - 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b2, - 0x00ee, 0x7034, 0x9005, 0x1904, 0x7cc1, 0x2009, 0x0017, 0x0804, - 0x7c71, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x7cc1, - 0x080c, 0x7096, 0x0120, 0x2009, 0x001d, 0x0804, 0x7c71, 0x68d8, - 0xc0a5, 0x68da, 0x2009, 0x0030, 0x0804, 0x7c71, 0x908e, 0x0500, - 0x1140, 0x7034, 0x9005, 0x1904, 0x7cc1, 0x2009, 0x0018, 0x0804, - 0x7c71, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x7c71, - 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x7c71, 0x908e, - 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x7cc1, 0x2009, 0x001b, - 0x0804, 0x7c71, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, - 0x7cc1, 0x2009, 0x001c, 0x0804, 0x7c71, 0x908e, 0x1300, 0x1120, - 0x2009, 0x0034, 0x0804, 0x7c71, 0x908e, 0x1200, 0x1140, 0x7034, - 0x9005, 0x1904, 0x7cc1, 0x2009, 0x0024, 0x0804, 0x7c71, 0x908c, - 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, - 0x2004, 0xd09c, 0x0904, 0x7c71, 0x080c, 0xc63d, 0x1904, 0x7cc1, - 0x0804, 0x7c6f, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, - 0x002a, 0x0804, 0x7c71, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, - 0x0804, 0x7c71, 0x908e, 0x6104, 0x1528, 0x2029, 0x0205, 0x2011, - 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, - 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x48da, - 0x004e, 0x8108, 0x0f04, 0x7c3d, 0x9186, 0x0280, 0x1d88, 0x2504, - 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, - 0x0023, 0x0478, 0x908e, 0x6000, 0x1118, 0x2009, 0x003f, 0x0448, - 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, - 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, - 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, - 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, - 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, - 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x243d, 0x1904, 0x7cc4, 0x080c, 0x620b, 0x1904, 0x7cc4, 0xbe12, - 0xbd16, 0x001e, 0x0016, 0x080c, 0x7096, 0x01c0, 0x68d8, 0xd08c, - 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, - 0x1168, 0x0040, 0x6878, 0x9606, 0x1148, 0x687c, 0x9506, 0x9084, - 0xff00, 0x1120, 0x9584, 0x00ff, 0xb886, 0x0080, 0xb884, 0x9005, - 0x1168, 0x9186, 0x0046, 0x1150, 0x6878, 0x9606, 0x1138, 0x687c, - 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0x9b84, - 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, - 0x9c76, 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, - 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48da, 0x080c, - 0x9c49, 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, - 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, - 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, - 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x84ba, 0x08a0, - 0x080c, 0x3144, 0x1140, 0x7010, 0x9084, 0xff00, 0x8007, 0x908e, - 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, 0x0046, 0x7000, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, 0x080c, 0x7f5c, - 0x0904, 0x7d4b, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1140, - 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, 0x080c, 0x9c76, 0x0498, - 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, 0x1568, 0x2009, 0x0016, - 0x080c, 0x9c76, 0x0440, 0x9186, 0x0032, 0x1528, 0x7030, 0x908e, - 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x243d, 0x11a8, 0x080c, 0x620b, 0x1190, - 0xbe12, 0xbd16, 0x080c, 0x9b84, 0x0168, 0x2b08, 0x6112, 0x080c, - 0xbcdb, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x9c76, - 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, - 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, - 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, - 0x0804, 0x7dad, 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, - 0x7dad, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, - 0x0000, 0x2019, 0x1836, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, - 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, - 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, - 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, - 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, - 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, - 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x7d82, 0x82ff, 0x1118, - 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, - 0x004e, 0x00be, 0x0005, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, - 0x000f, 0x0002, 0x7dca, 0x7dca, 0x7dca, 0x7f6e, 0x7dca, 0x7dcd, - 0x7df2, 0x7e7b, 0x7dca, 0x7dca, 0x7dca, 0x7dca, 0x7dca, 0x7dca, - 0x7dca, 0x7dca, 0x7817, 0x0140, 0x0005, 0x00b6, 0x7110, 0xd1bc, - 0x01e8, 0x7120, 0x2160, 0x9c8c, 0x0003, 0x11c0, 0x9c8a, 0x1ddc, - 0x02a8, 0x6864, 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x9c76, 0x7817, 0x0140, - 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, 0x0fff, 0x0904, 0x7e57, - 0x7110, 0xd1bc, 0x1904, 0x7e57, 0x7108, 0x700c, 0x2028, 0x918c, - 0x00ff, 0x2130, 0x9094, 0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, - 0x317f, 0x200d, 0x918c, 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, - 0x0904, 0x7e57, 0x9182, 0x0801, 0x1a04, 0x7e57, 0x9190, 0x1000, - 0x2204, 0x905d, 0x05e0, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, - 0xba04, 0x9294, 0xff00, 0x9286, 0x0600, 0x1190, 0x080c, 0x9b84, - 0x0598, 0x2b08, 0x7028, 0x6052, 0x702c, 0x604e, 0x6112, 0x6023, - 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x080c, 0xc8a3, 0x00f8, - 0x080c, 0x6666, 0x1138, 0xb807, 0x0606, 0x0c40, 0x190c, 0x7d4f, - 0x11b0, 0x0880, 0x080c, 0x9b84, 0x2b08, 0x0188, 0x6112, 0x6023, - 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, - 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ba, 0x7817, - 0x0140, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x48da, 0x080c, 0x9c49, 0x0d78, - 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, - 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, - 0x080c, 0x84b3, 0x08e0, 0x00b6, 0x7110, 0xd1bc, 0x05d0, 0x7020, - 0x2060, 0x9c84, 0x0003, 0x15a8, 0x9c82, 0x1ddc, 0x0690, 0x6864, - 0x9c02, 0x1678, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0650, 0x7008, - 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1510, 0x700c, - 0xb914, 0x9106, 0x11f0, 0x7124, 0x610a, 0x601c, 0xd0fc, 0x11c8, - 0x2001, 0x0271, 0x2004, 0x9005, 0x1180, 0x9484, 0x0fff, 0x9082, - 0x000c, 0x0158, 0x0066, 0x2031, 0x0100, 0xa001, 0xa001, 0x8631, - 0x1de0, 0x006e, 0x601c, 0xd0fc, 0x1120, 0x2009, 0x0045, 0x080c, - 0x9c76, 0x7817, 0x0140, 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, - 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, - 0x3144, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, - 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, - 0x7ede, 0x7edf, 0x7ede, 0x7ede, 0x7f3e, 0x7f4d, 0x0005, 0x00b6, - 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x7f3c, 0x700c, - 0x7108, 0x080c, 0x243d, 0x1904, 0x7f3c, 0x080c, 0x620b, 0x1904, - 0x7f3c, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x01d8, 0x080c, 0x6666, - 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, 0x7f5c, 0x00ce, - 0x05d8, 0x080c, 0x9b84, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xbcdb, - 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x9c76, - 0x0458, 0x080c, 0x6666, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, - 0x666e, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, 0x9b84, 0x2b08, - 0x01d8, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0005, 0x7120, 0x610a, - 0x2009, 0x0088, 0x080c, 0x9c76, 0x0078, 0x080c, 0x9b84, 0x2b08, - 0x0158, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0004, 0x7120, 0x610a, - 0x2009, 0x0001, 0x080c, 0x9c76, 0x00be, 0x0005, 0x7110, 0xd1bc, - 0x0158, 0x00d1, 0x0148, 0x080c, 0x7ebd, 0x1130, 0x7124, 0x610a, - 0x2009, 0x0089, 0x080c, 0x9c76, 0x0005, 0x7110, 0xd1bc, 0x0158, - 0x0059, 0x0148, 0x080c, 0x7ebd, 0x1130, 0x7124, 0x610a, 0x2009, - 0x008a, 0x080c, 0x9c76, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0003, - 0x1158, 0x9c82, 0x1ddc, 0x0240, 0x2001, 0x1819, 0x2004, 0x9c02, - 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, - 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0003, 0x11b0, 0x9c82, - 0x1ddc, 0x0298, 0x6864, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, - 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, - 0x1120, 0x2009, 0x0051, 0x080c, 0x9c76, 0x7817, 0x0140, 0x00be, - 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, - 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, - 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, - 0xc000, 0x05c0, 0x080c, 0x9b84, 0x05a8, 0x0066, 0x00c6, 0x0046, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x243d, 0x1590, - 0x080c, 0x620b, 0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, - 0x6012, 0x080c, 0xbcdb, 0x080c, 0x1022, 0x0500, 0x2900, 0x6062, - 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, - 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, - 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, - 0x080c, 0x84ba, 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0x9bda, - 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, - 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x8044, - 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, - 0x8046, 0x7030, 0x908e, 0x0400, 0x0904, 0x8046, 0x908e, 0x6000, - 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, - 0x1836, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6624, - 0x0558, 0x68ac, 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, - 0x1518, 0x687c, 0x69ac, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, - 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, - 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, - 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x7f5c, 0x0128, 0x6004, - 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ce, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, - 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, - 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, - 0x0005, 0x2071, 0x19d3, 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, - 0x701a, 0x7072, 0x7012, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, - 0x702b, 0x8fbc, 0x7032, 0x7037, 0x9039, 0x703f, 0xffff, 0x7042, - 0x7047, 0x521f, 0x704a, 0x705b, 0x8205, 0x080c, 0x103b, 0x090c, - 0x0d65, 0x2900, 0x703a, 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, - 0xdcb0, 0x0005, 0x2071, 0x19d3, 0x1d04, 0x8127, 0x2091, 0x6000, - 0x700c, 0x8001, 0x700e, 0x1560, 0x2001, 0x1875, 0x2004, 0xd0c4, - 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, 0x20d1, 0x0001, - 0x20d1, 0x0000, 0x080c, 0x0d65, 0x700f, 0x0361, 0x7007, 0x0001, - 0x0126, 0x2091, 0x8000, 0x2069, 0x1800, 0x69e8, 0xd1e4, 0x1138, - 0xd1dc, 0x1118, 0x080c, 0x8273, 0x0010, 0x080c, 0x824a, 0x7040, - 0x900d, 0x0148, 0x8109, 0x7142, 0x1130, 0x7044, 0x080f, 0x0018, - 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, - 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, - 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, - 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, - 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, 0x090c, 0x90c1, 0x0010, - 0x7034, 0x080f, 0x703c, 0x9005, 0x0118, 0x0310, 0x8001, 0x703e, - 0x704c, 0x900d, 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, - 0x0009, 0x8109, 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, - 0x7018, 0x900d, 0x01d8, 0x0016, 0x7070, 0x900d, 0x0158, 0x706c, - 0x8001, 0x706e, 0x1138, 0x706f, 0x0009, 0x8109, 0x7172, 0x1110, - 0x7074, 0x080f, 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, - 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, - 0x0002, 0x814f, 0x8150, 0x817a, 0x00e6, 0x2071, 0x19d3, 0x7018, - 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, - 0x00e6, 0x0006, 0x2071, 0x19d3, 0x701c, 0x9206, 0x1120, 0x701a, - 0x701e, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x19d3, 0xb888, 0x9102, 0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, - 0x00b6, 0x2031, 0x0010, 0x7110, 0x080c, 0x626b, 0x11a8, 0xb888, - 0x8001, 0x0290, 0xb88a, 0x1180, 0x0126, 0x2091, 0x8000, 0x0066, - 0xb8c0, 0x9005, 0x0138, 0x0026, 0xba3c, 0x0016, 0x080c, 0x6396, - 0x001e, 0x002e, 0x006e, 0x012e, 0x8108, 0x9182, 0x0800, 0x1220, - 0x8631, 0x0128, 0x7112, 0x0c00, 0x900e, 0x7007, 0x0002, 0x7112, - 0x00be, 0x0005, 0x2031, 0x0010, 0x7014, 0x2060, 0x0126, 0x2091, - 0x8000, 0x6048, 0x9005, 0x0128, 0x8001, 0x604a, 0x1110, 0x080c, - 0xbb5c, 0x6018, 0x9005, 0x0904, 0x81cc, 0x00f6, 0x2079, 0x0300, - 0x7918, 0xd1b4, 0x1904, 0x81df, 0x781b, 0x2020, 0xa001, 0x7918, - 0xd1b4, 0x0120, 0x781b, 0x2000, 0x0804, 0x81df, 0x8001, 0x601a, - 0x0106, 0x781b, 0x2000, 0xa001, 0x7918, 0xd1ac, 0x1dd0, 0x010e, - 0x00fe, 0x1510, 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, - 0x11c8, 0x080c, 0xb842, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, - 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x080c, - 0xbf8d, 0x0110, 0x080c, 0xb533, 0x012e, 0x9c88, 0x001c, 0x7116, - 0x2001, 0x1819, 0x2004, 0x9102, 0x1228, 0x8631, 0x0138, 0x2160, - 0x0804, 0x817e, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x0005, 0x00fe, - 0x0c58, 0x00e6, 0x2071, 0x19d3, 0x7027, 0x07d0, 0x7023, 0x0009, - 0x00ee, 0x0005, 0x2001, 0x19dc, 0x2003, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x19d3, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, - 0x19df, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19d3, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, 0x7054, - 0x8000, 0x7056, 0x2001, 0x19e1, 0x2044, 0xa06c, 0x9086, 0x0000, - 0x0150, 0x7068, 0xa09a, 0x7064, 0xa096, 0x7060, 0xa092, 0x705c, - 0xa08e, 0x080c, 0x1117, 0x002e, 0x008e, 0x0005, 0x0006, 0x0016, - 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, - 0x080c, 0x8092, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x19d3, - 0x7172, 0x7276, 0x706f, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0x19d3, 0x7074, 0x9206, 0x1110, 0x7072, 0x7076, 0x000e, - 0x00ee, 0x0005, 0x2069, 0x1800, 0x69e8, 0xd1e4, 0x1518, 0x0026, - 0xd1ec, 0x0140, 0x6a50, 0x6870, 0x9202, 0x0288, 0x8117, 0x9294, - 0x00c1, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, 0x0007, - 0x0110, 0x69ea, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, 0x8107, - 0x9106, 0x9094, 0x00c1, 0x9184, 0xff3e, 0x9205, 0x68ea, 0x080c, - 0x0eed, 0x002e, 0x0005, 0x69e4, 0x9184, 0x003f, 0x05b8, 0x8109, - 0x9184, 0x003f, 0x01a8, 0x6a50, 0x6870, 0x9202, 0x0220, 0xd1bc, - 0x0168, 0xc1bc, 0x0018, 0xd1bc, 0x1148, 0xc1bd, 0x2110, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x0f0f, 0x00ee, 0x0400, 0x69e6, 0x00f0, - 0x0026, 0x8107, 0x9094, 0x0007, 0x0128, 0x8001, 0x8007, 0x9085, - 0x0007, 0x0050, 0x2010, 0x8004, 0x8004, 0x8004, 0x9084, 0x0007, - 0x9205, 0x8007, 0x9085, 0x0028, 0x9086, 0x0040, 0x2010, 0x00e6, - 0x2071, 0x1800, 0x080c, 0x0f0f, 0x00ee, 0x002e, 0x0005, 0x00c6, - 0x2061, 0x1a3e, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, - 0x8003, 0x9080, 0x1a3e, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, - 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a3e, 0x6014, 0x00ce, - 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, - 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, - 0x918e, 0x00c0, 0x0904, 0x8377, 0xd0b4, 0x1168, 0xd0bc, 0x1904, - 0x8350, 0x2009, 0x0006, 0x080c, 0x83a4, 0x0005, 0x900e, 0x0c60, - 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x05e0, 0x908c, 0x2023, 0x1568, - 0x87ff, 0x1558, 0xa9a8, 0x81ff, 0x1540, 0x6124, 0x918c, 0x0500, - 0x1520, 0x6100, 0x918e, 0x0007, 0x1500, 0x2009, 0x1875, 0x210c, - 0xd184, 0x11d8, 0x6003, 0x0003, 0x6007, 0x0043, 0x6047, 0xb035, - 0x080c, 0x1ab2, 0xa87c, 0xc0dd, 0xa87e, 0x600f, 0x0000, 0x00f6, - 0x2079, 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0013, 0x2c00, - 0x7836, 0x781b, 0x8080, 0x00fe, 0x0005, 0x908c, 0x0003, 0x0120, - 0x918e, 0x0003, 0x1904, 0x839e, 0x908c, 0x2020, 0x918e, 0x2020, - 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1875, 0x2104, 0xd084, - 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0x9c76, 0x0005, - 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, 0x9c76, 0x6110, 0x00b6, - 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, - 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, - 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, - 0x839e, 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, - 0x2c78, 0x080c, 0x165c, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, - 0x0042, 0x080c, 0x9c76, 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, - 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, - 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, - 0x9c76, 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, - 0x080c, 0x9c76, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, - 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xb842, 0x0518, - 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, - 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, - 0x1a3e, 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, - 0x00ce, 0x080c, 0x67c6, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, - 0x190c, 0x82bd, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, - 0x1a3e, 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, - 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, - 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086, - 0x818e, 0x1208, 0x9200, 0x1f04, 0x83ef, 0x8086, 0x818e, 0x004e, - 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, - 0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d, - 0x0228, 0x911a, 0x1220, 0x1f04, 0x8406, 0x0028, 0x911a, 0x2308, - 0x8210, 0x1f04, 0x8406, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, - 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, - 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19b7, 0x012e, - 0x00d6, 0x2069, 0x19b7, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, - 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0x97e8, 0x04a9, 0x080c, - 0x97d3, 0x0491, 0x080c, 0x97d6, 0x0479, 0x080c, 0x97d9, 0x0461, - 0x080c, 0x97dc, 0x0449, 0x080c, 0x97df, 0x0431, 0x080c, 0x97e2, - 0x0419, 0x080c, 0x97e5, 0x0401, 0x01de, 0x014e, 0x015e, 0x6857, - 0x0000, 0x00f6, 0x2079, 0x0380, 0x00f9, 0x7807, 0x0003, 0x7803, - 0x0000, 0x7803, 0x0001, 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe, - 0x9085, 0x8000, 0x206a, 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc, - 0x682a, 0x00fe, 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, - 0x2001, 0x0000, 0x4004, 0x0005, 0x00c6, 0x7803, 0x0000, 0x9006, - 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, 0x1abe, - 0x781f, 0xff00, 0x781b, 0xff00, 0x2061, 0x1ab3, 0x602f, 0x19b7, - 0x6033, 0x1800, 0x6037, 0x19d3, 0x603b, 0x1d04, 0x603f, 0x1d14, - 0x6042, 0x6047, 0x1a89, 0x00ce, 0x0005, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0001, 0x01b0, 0x00c6, 0x6146, 0x600f, - 0x0000, 0x2c08, 0x2061, 0x19b7, 0x602c, 0x8000, 0x602e, 0x601c, - 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, 0x611e, 0x00ce, 0x0005, - 0x6122, 0x611e, 0x0cd8, 0x6146, 0x2c08, 0x2001, 0x0012, 0x080c, - 0x98ac, 0x0005, 0x0016, 0x2009, 0x8020, 0x6146, 0x2c08, 0x2001, - 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, 0x1128, 0x2001, - 0x0019, 0x080c, 0x98ac, 0x0088, 0x00c6, 0x2061, 0x19b7, 0x602c, - 0x8000, 0x602e, 0x600c, 0x9005, 0x0128, 0x9080, 0x0003, 0x2102, - 0x610e, 0x0010, 0x6112, 0x610e, 0x00ce, 0x001e, 0x0005, 0x2001, - 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, 0x0198, 0x00c6, - 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19b7, 0x6044, 0x9005, - 0x0130, 0x9080, 0x0003, 0x2102, 0x6146, 0x00ce, 0x0005, 0x614a, - 0x6146, 0x0cd8, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2001, 0x0013, - 0x080c, 0x98ac, 0x0005, 0x6044, 0xd0dc, 0x0110, 0x080c, 0x9485, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, - 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, - 0x2071, 0x19b7, 0x7648, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, - 0x0904, 0x8586, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x8581, - 0x87ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x8581, 0x704c, 0x9c06, - 0x1178, 0x0036, 0x2019, 0x0001, 0x080c, 0x9269, 0x703f, 0x0000, - 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x003e, 0x2029, 0x0001, - 0x0811, 0x7048, 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, - 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, - 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, - 0x2678, 0x600f, 0x0000, 0x080c, 0xb842, 0x01f0, 0x6014, 0x2048, - 0x6020, 0x9086, 0x0003, 0x1588, 0x6004, 0x9086, 0x0040, 0x090c, - 0x9485, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0076, 0x080c, 0xbb45, 0x080c, 0xd52b, 0x080c, 0x6991, 0x007e, - 0x003e, 0x001e, 0x080c, 0xba31, 0x080c, 0x9c14, 0x00ce, 0x0804, - 0x851f, 0x2c78, 0x600c, 0x2060, 0x0804, 0x851f, 0x012e, 0x000e, - 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, 0x007e, 0x009e, 0x00be, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, 0xd52b, 0x080c, 0xd22f, - 0x007e, 0x003e, 0x001e, 0x08c0, 0x6020, 0x9086, 0x000a, 0x0918, - 0x0804, 0x8564, 0x0006, 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, - 0x9036, 0x0126, 0x2091, 0x8000, 0x2079, 0x19b7, 0x7848, 0x9065, - 0x0904, 0x860e, 0x600c, 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, - 0x11a0, 0x0036, 0x2019, 0x0001, 0x080c, 0x9269, 0x783f, 0x0000, - 0x901e, 0x7b4e, 0x7b6a, 0x7b52, 0x7b6e, 0x003e, 0x000e, 0x9005, - 0x1118, 0x600c, 0x600f, 0x0000, 0x0006, 0x00e6, 0x2f70, 0x080c, - 0x8503, 0x00ee, 0x080c, 0xb842, 0x0548, 0x6014, 0x2048, 0x6020, - 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002, 0x1188, 0x6010, - 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, - 0x6048, 0x9005, 0x11c0, 0x2001, 0x1958, 0x2004, 0x604a, 0x0098, - 0x6004, 0x9086, 0x0040, 0x090c, 0x9485, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6985, 0x080c, 0xba31, 0x6044, 0xc0fc, - 0x6046, 0x080c, 0x9c14, 0x000e, 0x0804, 0x85b7, 0x7e4a, 0x7e46, - 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xd22f, 0x0c38, 0x6020, - 0x9086, 0x000a, 0x09e0, 0x08a0, 0x0016, 0x0026, 0x0086, 0x9046, - 0x00a9, 0x080c, 0x8715, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, - 0x0126, 0x2079, 0x19b7, 0x2091, 0x8000, 0x080c, 0x875e, 0x080c, - 0x87f2, 0x080c, 0x63f8, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19b7, 0x7620, 0x2660, 0x2678, 0x8cff, - 0x0904, 0x86da, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x86d5, - 0x88ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x86d5, 0x7030, 0x9c06, - 0x1570, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, 0x81ea, - 0x080c, 0x8f9c, 0x68c3, 0x0000, 0x080c, 0x9485, 0x7033, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x7008, - 0xc0ad, 0x700a, 0x6003, 0x0009, 0x630a, 0x0804, 0x86d5, 0x7020, - 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, - 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6044, 0xc0fc, 0x6046, 0x6014, 0x2048, 0x080c, 0xb842, - 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, 0xba57, 0x1118, - 0x080c, 0xa581, 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, - 0x0016, 0x0036, 0x0086, 0x080c, 0xbb45, 0x080c, 0xd52b, 0x080c, - 0x6991, 0x008e, 0x003e, 0x001e, 0x080c, 0xba31, 0x080c, 0x9c14, - 0x080c, 0x935b, 0x00ce, 0x0804, 0x864f, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x864f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, - 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xd52b, 0x080c, 0xd22f, - 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xa581, 0x6020, 0x9086, - 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, - 0x86bb, 0x9086, 0x008b, 0x0904, 0x86bb, 0x0840, 0x6020, 0x9086, - 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, - 0x9086, 0x008b, 0x09b0, 0x0804, 0x86ce, 0x0006, 0x00f6, 0x00e6, - 0x0096, 0x00b6, 0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, 0x8000, - 0x9280, 0x1000, 0x2004, 0x905d, 0x2079, 0x19b7, 0x9036, 0x7828, - 0x2060, 0x8cff, 0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, 0xffff, - 0x080c, 0x9a77, 0x01d8, 0x610c, 0x0016, 0x080c, 0x90f3, 0x6014, - 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0086, 0x080c, 0xbb45, 0x080c, 0xd52b, 0x080c, 0x6991, 0x008e, - 0x003e, 0x001e, 0x080c, 0x9c14, 0x00ce, 0x08d8, 0x2c30, 0x600c, - 0x2060, 0x08b8, 0x080c, 0x6415, 0x012e, 0x001e, 0x006e, 0x00ce, - 0x00be, 0x009e, 0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, 0x87c5, - 0x600c, 0x0006, 0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, 0x7830, - 0x9c06, 0x1588, 0x2069, 0x0100, 0x6820, 0xd0a4, 0x1508, 0x080c, - 0x81ea, 0x080c, 0x8f9c, 0x68c3, 0x0000, 0x080c, 0x9485, 0x7833, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0058, - 0x080c, 0x661c, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, 0xc0ad, - 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xb840, 0x01b0, - 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xba57, 0x1118, 0x080c, - 0xa581, 0x0060, 0x080c, 0x661c, 0x1168, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x6991, 0x080c, 0xba31, 0x080c, 0x9c14, - 0x080c, 0x935b, 0x000e, 0x0804, 0x8765, 0x7e22, 0x7e1e, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1118, 0x080c, 0xd22f, 0x0c50, 0x080c, 0xa581, 0x6020, 0x9086, - 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990, - 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, - 0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x9036, - 0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, 0x0006, 0x3e08, - 0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, 0x6043, 0xffff, - 0x080c, 0x9a77, 0x0180, 0x610c, 0x080c, 0x90f3, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6991, 0x080c, - 0x9c14, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, 0x00be, - 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0x080c, - 0x5dd1, 0x11b0, 0x2071, 0x19b7, 0x7030, 0x9080, 0x0005, 0x2004, - 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19b7, 0x7030, - 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, 0x0029, - 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, 0x6043, - 0xffff, 0x080c, 0x9a77, 0x0178, 0x080c, 0x90f3, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xbb45, 0x080c, - 0x6991, 0x080c, 0x9c14, 0x00ce, 0x0005, 0x00b6, 0x00e6, 0x00c6, - 0x080c, 0x98bb, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, 0x2072, - 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0x98d7, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x2071, 0x19b7, 0x7030, 0x9005, 0x0da0, 0x9c06, - 0x190c, 0x0d65, 0x7036, 0x080c, 0x81ea, 0x7004, 0x9084, 0x0007, - 0x0002, 0x888b, 0x888d, 0x8894, 0x889e, 0x88ac, 0x888b, 0x8899, - 0x8889, 0x080c, 0x0d65, 0x0428, 0x0005, 0x080c, 0x9a62, 0x7007, - 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, 0x90f3, - 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, 0x9a4d, - 0x0140, 0x080c, 0x9a62, 0x0128, 0x0066, 0x9036, 0x080c, 0x90f3, - 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0x9a4d, 0x080c, 0x9485, - 0x0000, 0x010e, 0x190c, 0x98d7, 0x00ce, 0x00ee, 0x00be, 0x0005, - 0x00d6, 0x00c6, 0x080c, 0x98bb, 0x0106, 0x6044, 0xd0fc, 0x1130, - 0x010e, 0x090c, 0x98d7, 0x00ce, 0x00de, 0x0005, 0x2069, 0x19b7, - 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d65, 0x6852, 0x00e6, - 0x2d70, 0x080c, 0x8503, 0x00ee, 0x080c, 0x81f7, 0x0016, 0x2009, - 0x0040, 0x080c, 0x2063, 0x001e, 0x683c, 0x9084, 0x0003, 0x0002, - 0x88e6, 0x88e7, 0x8905, 0x88e4, 0x080c, 0x0d65, 0x0460, 0x6868, - 0x9086, 0x0001, 0x0190, 0x600c, 0x9015, 0x0160, 0x6a4a, 0x600f, - 0x0000, 0x6044, 0xc0fc, 0x6046, 0x9006, 0x7042, 0x684e, 0x683f, - 0x0000, 0x00c8, 0x684a, 0x6846, 0x0ca0, 0x686b, 0x0000, 0x6848, - 0x9065, 0x0d78, 0x6003, 0x0002, 0x0c60, 0x9006, 0x686a, 0x6852, - 0x686e, 0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, 0x0000, 0x0018, - 0x684e, 0x684a, 0x6846, 0x684f, 0x0000, 0x010e, 0x190c, 0x98d7, - 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, 0x000b, - 0x0005, 0x8931, 0x8934, 0x8d8d, 0x8e1c, 0x8934, 0x8d8d, 0x8e1c, - 0x8931, 0x8934, 0x8931, 0x8931, 0x8931, 0x8931, 0x8931, 0x8931, - 0x8931, 0x080c, 0x885d, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146, - 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d65, 0x6110, - 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, - 0x1a04, 0x89a0, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x8b17, 0x8b52, - 0x8b7b, 0x8c1e, 0x8c3f, 0x8c45, 0x8c52, 0x8c5a, 0x8c66, 0x8c6c, - 0x8c7d, 0x8c6c, 0x8cd4, 0x8c5a, 0x8ce0, 0x8ce6, 0x8c66, 0x8ce6, - 0x8cf2, 0x899e, 0x899e, 0x899e, 0x899e, 0x899e, 0x899e, 0x899e, - 0x899e, 0x899e, 0x899e, 0x899e, 0x9114, 0x9137, 0x9148, 0x9168, - 0x919a, 0x8c52, 0x899e, 0x8c52, 0x8c6c, 0x899e, 0x8b7b, 0x8c1e, - 0x899e, 0x9583, 0x8c6c, 0x899e, 0x959f, 0x8c6c, 0x899e, 0x8c66, - 0x8b11, 0x89c1, 0x899e, 0x95bb, 0x9628, 0x9708, 0x899e, 0x9715, - 0x8c4f, 0x9740, 0x899e, 0x91a4, 0x974c, 0x899e, 0x080c, 0x0d65, - 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x89bf, 0x89bf, 0x89bf, - 0x89e8, 0x8a94, 0x8a9f, 0x89bf, 0x89bf, 0x89bf, 0x8ae6, 0x8af2, - 0x8a03, 0x89bf, 0x8a1e, 0x8a52, 0x9acd, 0x9b12, 0x8c6c, 0x080c, - 0x0d65, 0x00d6, 0x0096, 0x080c, 0x8d05, 0x7003, 0x2414, 0x7007, - 0x0018, 0x700b, 0x0800, 0x7814, 0x2048, 0xa83c, 0x700e, 0xa850, - 0x7022, 0xa854, 0x7026, 0x60c3, 0x0018, 0x080c, 0x8f6c, 0x009e, - 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x080c, - 0x9b59, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, 0x0005, - 0x00d6, 0x0096, 0x080c, 0x8d05, 0x7003, 0x0500, 0x7814, 0x2048, - 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, 0x7016, - 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, 0x8f6c, - 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x8d05, 0x7003, - 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, 0xa8d4, - 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, 0x60c3, - 0x0010, 0x080c, 0x8f6c, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, - 0x0126, 0x2091, 0x8000, 0x080c, 0x8d05, 0x20e9, 0x0000, 0x2001, - 0x1973, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, 0x60c2, - 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, - 0x2001, 0x1973, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, 0x2048, - 0x080c, 0xc59f, 0x9006, 0x080c, 0x2048, 0x001e, 0xa804, 0x9005, - 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0x8f6c, 0x012e, 0x009e, + 0x908a, 0x001a, 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x79c6, + 0x0005, 0x7523, 0x752f, 0x7719, 0x7523, 0x752f, 0x7523, 0x752f, + 0x752f, 0x7523, 0x752f, 0x7719, 0x752f, 0x752f, 0x752f, 0x752f, + 0x752f, 0x7523, 0x752f, 0x7719, 0x7523, 0x7523, 0x752f, 0x7523, + 0x7523, 0x7523, 0x752f, 0x00e6, 0x2071, 0x18f8, 0x2009, 0x0400, + 0x0071, 0x00ee, 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, + 0x2000, 0x0029, 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, + 0x0001, 0xa868, 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, + 0x8000, 0x080c, 0x69b5, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, + 0x00ff, 0x0d08, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x76d7, + 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x76d7, + 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, + 0x7007, 0x0001, 0x0804, 0x76f2, 0x7007, 0x0003, 0x7012, 0x2900, + 0x7016, 0x701a, 0x704b, 0x76f2, 0x0005, 0xa864, 0x8007, 0x9084, + 0x00ff, 0x9086, 0x0001, 0x1904, 0x752b, 0x7007, 0x0001, 0x2009, + 0x1833, 0x210c, 0x81ff, 0x1904, 0x75cf, 0xa994, 0x9186, 0x006f, + 0x0188, 0x9186, 0x0074, 0x15b0, 0x0026, 0x2011, 0x0010, 0x080c, + 0x66ae, 0x002e, 0x0578, 0x0016, 0xa998, 0x080c, 0x66f8, 0x001e, + 0x1548, 0x0400, 0x080c, 0x70ba, 0x0140, 0xa897, 0x4005, 0xa89b, + 0x0016, 0x2001, 0x0030, 0x900e, 0x0438, 0x0026, 0x2011, 0x8008, + 0x080c, 0x66ae, 0x002e, 0x01b0, 0x0016, 0x0026, 0x0036, 0xa998, + 0xaaa0, 0xab9c, 0x918d, 0x8000, 0x080c, 0x66f8, 0x003e, 0x002e, + 0x001e, 0x1140, 0xa897, 0x4005, 0xa89b, 0x4009, 0x2001, 0x0030, + 0x900e, 0x0050, 0xa868, 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, + 0x080c, 0x5f22, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, + 0x0139, 0xa87a, 0xa982, 0x080c, 0x69b5, 0x012e, 0x0ca0, 0xa994, + 0x9186, 0x0071, 0x0904, 0x757d, 0x9186, 0x0064, 0x0904, 0x757d, + 0x9186, 0x007c, 0x0904, 0x757d, 0x9186, 0x0028, 0x0904, 0x757d, + 0x9186, 0x0038, 0x0904, 0x757d, 0x9186, 0x0078, 0x0904, 0x757d, + 0x9186, 0x005f, 0x0904, 0x757d, 0x9186, 0x0056, 0x0904, 0x757d, + 0xa897, 0x4005, 0xa89b, 0x0001, 0x2001, 0x0030, 0x900e, 0x0860, + 0xa87c, 0x9084, 0x00c0, 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, + 0x0804, 0x78e7, 0x2900, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, + 0x20e0, 0xa85c, 0x9080, 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, + 0x20e8, 0xa05c, 0x9080, 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, + 0x9082, 0x0401, 0x1a04, 0x7533, 0xaab4, 0x928a, 0x0002, 0x1a04, + 0x7533, 0x82ff, 0x1138, 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, + 0x7695, 0x0018, 0x9280, 0x768b, 0x2005, 0x7056, 0x7010, 0x9015, + 0x0904, 0x7676, 0x080c, 0x1048, 0x1118, 0x7007, 0x0004, 0x0005, + 0x2900, 0x7022, 0x7054, 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, + 0xa95c, 0xe004, 0x9100, 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, + 0x1210, 0x900e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, + 0x0004, 0x0108, 0x9108, 0xa17a, 0x810b, 0xa17e, 0x080c, 0x1124, + 0xa06c, 0x908e, 0x0100, 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, + 0x0007, 0x0005, 0x7020, 0x2048, 0x080c, 0x1061, 0x7014, 0x2048, + 0x0804, 0x7533, 0x7020, 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, + 0x2908, 0x2048, 0xa906, 0x711a, 0x0804, 0x762e, 0x7014, 0x2048, + 0x7007, 0x0001, 0xa8b4, 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, + 0x0108, 0x00b9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, + 0x78e7, 0x0804, 0x76d7, 0x768d, 0x7691, 0x0002, 0x001d, 0x0007, + 0x0004, 0x000a, 0x001b, 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, + 0x0004, 0x0076, 0x0066, 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, + 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, + 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, + 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, + 0xb0a2, 0xb094, 0xb09e, 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, + 0xb096, 0xb088, 0xb08a, 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, + 0xb082, 0xb07c, 0xb07e, 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, + 0xb776, 0xb004, 0x9055, 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, + 0x1833, 0x210c, 0x81ff, 0x1178, 0x080c, 0x5d71, 0x1108, 0x0005, + 0x080c, 0x6bc6, 0x0126, 0x2091, 0x8000, 0x080c, 0xbb73, 0x080c, + 0x69b5, 0x012e, 0x0ca0, 0x080c, 0xbf88, 0x1d70, 0x2001, 0x0028, + 0x900e, 0x0c70, 0x2009, 0x1833, 0x210c, 0x81ff, 0x11d8, 0xa888, + 0x9005, 0x01e0, 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, + 0x5e84, 0x1138, 0x0005, 0x9006, 0xa87a, 0x080c, 0x5dff, 0x1108, + 0x0005, 0x0126, 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x69b5, + 0x012e, 0x0cb0, 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, + 0x0c80, 0x7018, 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, + 0x8001, 0x7012, 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, + 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, + 0xa974, 0xa878, 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, + 0x0001, 0x9096, 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, + 0x0002, 0x0160, 0x9005, 0x11d8, 0xa974, 0x080c, 0x628f, 0x11b8, + 0x0066, 0xae80, 0x080c, 0x639f, 0x006e, 0x0088, 0x0046, 0x2011, + 0x180c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x628f, + 0x1110, 0x080c, 0x6572, 0x8108, 0x1f04, 0x7756, 0x00ce, 0xa87c, + 0xd084, 0x1120, 0x080c, 0x1061, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x080c, 0x69b5, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x080c, 0x6686, 0x0580, 0x2061, 0x1a46, + 0x6100, 0xd184, 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, + 0xd084, 0x0520, 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, + 0x0000, 0x00c8, 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, + 0x001e, 0x8000, 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, + 0xa888, 0x8007, 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, + 0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x79b0, 0x012e, 0x0804, + 0x79aa, 0x012e, 0x0804, 0x79a4, 0x012e, 0x0804, 0x79a7, 0x0126, + 0x2091, 0x8000, 0x7007, 0x0001, 0x080c, 0x6686, 0x05e0, 0x2061, + 0x1a46, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, + 0xac78, 0x9484, 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, + 0x1120, 0x2100, 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, + 0x9212, 0x02f0, 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, + 0x00ff, 0x9082, 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, + 0x9082, 0x0004, 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, + 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x79b0, + 0x012e, 0x0804, 0x79ad, 0x012e, 0x0804, 0x79aa, 0x0126, 0x2091, + 0x8000, 0x7007, 0x0001, 0x2061, 0x1a46, 0x6300, 0xd38c, 0x1120, + 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x79be, 0x012e, + 0x0804, 0x79ad, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, + 0x0001, 0xa87c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a46, 0x6000, + 0x9084, 0xfcff, 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, + 0xa88c, 0x9065, 0x0598, 0x2001, 0x1833, 0x2004, 0x9005, 0x0118, + 0x080c, 0x9c20, 0x0068, 0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, + 0xd1a4, 0x0110, 0xa980, 0x6162, 0x2009, 0x0041, 0x080c, 0x9c82, + 0xa988, 0x918c, 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, + 0x2011, 0xfdff, 0x080c, 0x8401, 0x002e, 0xa87c, 0xd0c4, 0x0148, + 0x2061, 0x1a46, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, + 0x600a, 0x00ce, 0x012e, 0x00be, 0x0804, 0x79b0, 0x00ce, 0x012e, + 0x00be, 0x0804, 0x79aa, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, + 0x002d, 0x0d18, 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, + 0x2001, 0x180c, 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, + 0x0158, 0x9186, 0x0029, 0x1d10, 0xa974, 0x080c, 0x628f, 0x1968, + 0xb800, 0xc0e4, 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, + 0x0024, 0x2001, 0x195e, 0x2004, 0x601a, 0x0804, 0x7845, 0xa88c, + 0x9065, 0x0960, 0x00e6, 0xa890, 0x9075, 0x2001, 0x1833, 0x2004, + 0x9005, 0x0150, 0x080c, 0x9c20, 0x8eff, 0x0118, 0x2e60, 0x080c, + 0x9c20, 0x00ee, 0x0804, 0x7845, 0x6024, 0xc0dc, 0xc0d5, 0x6026, + 0x2e60, 0x6007, 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, + 0xa8a4, 0x602e, 0xa8a8, 0x6016, 0x6003, 0x0001, 0x2009, 0x8020, + 0x080c, 0x84e7, 0x00ee, 0x0804, 0x7845, 0x2061, 0x1a46, 0x6000, + 0xd084, 0x0190, 0xd08c, 0x1904, 0x79be, 0x0126, 0x2091, 0x8000, + 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x79be, 0x012e, + 0xa883, 0x0016, 0x0804, 0x79b7, 0xa883, 0x0007, 0x0804, 0x79b7, + 0xa864, 0x8007, 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, + 0x0001, 0x0069, 0x0005, 0x080c, 0x752b, 0x0040, 0x7007, 0x0003, + 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x78e7, 0x0005, 0x00b6, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61cc, + 0x81ff, 0x1904, 0x7969, 0x6130, 0xd194, 0x1904, 0x7993, 0xa878, + 0x2070, 0x9e82, 0x1ddc, 0x0a04, 0x795d, 0x6064, 0x9e02, 0x1a04, + 0x795d, 0x7120, 0x9186, 0x0006, 0x1904, 0x794f, 0x7010, 0x905d, + 0x0904, 0x7969, 0xb800, 0xd0e4, 0x1904, 0x798d, 0x2061, 0x1a46, + 0x6100, 0x9184, 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, + 0x1904, 0x7996, 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, + 0x9005, 0x1198, 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7999, 0x080c, + 0x53a8, 0xd09c, 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, + 0x82f1, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, + 0x1de0, 0xa902, 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7999, 0x012e, + 0x00ee, 0x00be, 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, + 0x0804, 0x79b7, 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, + 0x080c, 0x628f, 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, + 0x0007, 0x1118, 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, + 0xa883, 0x000e, 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, + 0x0430, 0x080c, 0x53ac, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, + 0x1ddc, 0x02c0, 0x6064, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, + 0x1188, 0x7010, 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, + 0x0001, 0x7000, 0x9086, 0x0007, 0x1904, 0x78f3, 0x7003, 0x0002, + 0x0804, 0x78f3, 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, + 0x00ee, 0x00be, 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, + 0x0cb0, 0x2e60, 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xce41, + 0x012e, 0x00ee, 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, + 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, + 0x2009, 0x0001, 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, + 0x2091, 0x8000, 0x080c, 0x69b5, 0x012e, 0x0005, 0x080c, 0x1061, + 0x0005, 0x00d6, 0x080c, 0x82e8, 0x00de, 0x0005, 0x00d6, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, + 0x908c, 0x0780, 0x190c, 0x7a52, 0xd09c, 0x11a8, 0x2071, 0x1800, + 0x70bc, 0x90ea, 0x0040, 0x0278, 0x8001, 0x70be, 0x702c, 0x2048, + 0xa800, 0x702e, 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, + 0x7022, 0x702c, 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, + 0x9084, 0x0780, 0x190c, 0x7a52, 0x000e, 0x0005, 0x00d6, 0x00c6, + 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, 0x0001, 0xaa74, 0x9282, + 0x0004, 0x1a04, 0x7a43, 0xa97c, 0x9188, 0x1000, 0x2104, 0x905d, + 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, 0x9084, 0x00ff, 0x9084, + 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, 0x9b90, 0x1118, 0x080c, + 0x9c55, 0x05a8, 0x6212, 0xa874, 0x0002, 0x7a21, 0x7a26, 0x7a29, + 0x7a2f, 0x2019, 0x0002, 0x080c, 0xd234, 0x0060, 0x080c, 0xd1c4, + 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, 0xd1e3, 0x0018, 0xa980, + 0x080c, 0xd1c4, 0x080c, 0x9be6, 0xa887, 0x0000, 0x0126, 0x2091, + 0x8000, 0x080c, 0x69b5, 0x012e, 0x00be, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, 0x0c80, 0xa887, 0x0002, + 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, 0x0004, 0x0c38, 0xa887, + 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, 0x7a54, 0x0006, 0x0016, + 0x2001, 0x8003, 0x0006, 0x0804, 0x0d6e, 0x2001, 0x1833, 0x2004, + 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, 0x0300, 0x2001, 0x0200, + 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, 0x0218, 0x210c, 0xd1ec, + 0x1120, 0x080c, 0x1547, 0x00fe, 0x0005, 0x2001, 0x020d, 0x2003, + 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, 0x781c, 0xd08c, 0x0904, + 0x7ad5, 0x68bc, 0x90aa, 0x0005, 0x0a04, 0x807e, 0x7d44, 0x7c40, + 0xd59c, 0x190c, 0x0d65, 0x9584, 0x00f6, 0x1508, 0x9484, 0x7000, + 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, 0x0700, 0x8007, 0x04f0, + 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0db0, 0x00b0, 0x9484, + 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x11c0, + 0x080c, 0xd61c, 0x080c, 0x7fb5, 0x7817, 0x0140, 0x00a8, 0x9584, + 0x0076, 0x1118, 0x080c, 0x8011, 0x19c8, 0xd5a4, 0x0148, 0x0046, + 0x0056, 0x080c, 0x7b25, 0x080c, 0x1fe0, 0x005e, 0x004e, 0x0020, + 0x080c, 0xd61c, 0x7817, 0x0140, 0x080c, 0x70ba, 0x0168, 0x2001, + 0x0111, 0x2004, 0xd08c, 0x0140, 0x688f, 0x0000, 0x2001, 0x0110, + 0x2003, 0x0008, 0x2003, 0x0000, 0x0489, 0x0005, 0x0002, 0x7ae2, + 0x7dd7, 0x7adf, 0x7adf, 0x7adf, 0x7adf, 0x7adf, 0x7adf, 0x7817, + 0x0140, 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, + 0x9484, 0x0fff, 0x688e, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, + 0x0001, 0x1118, 0x080c, 0x5409, 0x0070, 0x080c, 0x7b45, 0x0058, + 0x9286, 0x3000, 0x1118, 0x080c, 0x7d14, 0x0028, 0x9286, 0x8000, + 0x1110, 0x080c, 0x7eeb, 0x7817, 0x0140, 0x0005, 0x2001, 0x1810, + 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, + 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, 0x2518, 0x080c, 0x48fa, + 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, + 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, + 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, + 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, 0x1800, 0x2004, 0x9086, + 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, 0x080c, 0x48fa, 0x002e, + 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, + 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, + 0x1904, 0x7ce5, 0x9186, 0x0023, 0x15c0, 0x080c, 0x7f80, 0x0904, + 0x7ce5, 0x6120, 0x9186, 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, + 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, 0x1904, 0x7ce5, 0x7124, + 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, + 0x9c82, 0x0804, 0x7ce5, 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, + 0x1130, 0x2009, 0x0015, 0x080c, 0x9c82, 0x0804, 0x7ce5, 0x908e, + 0x0100, 0x1904, 0x7ce5, 0x7034, 0x9005, 0x1904, 0x7ce5, 0x2009, + 0x0016, 0x080c, 0x9c82, 0x0804, 0x7ce5, 0x9186, 0x0022, 0x1904, + 0x7ce5, 0x7030, 0x908e, 0x0300, 0x1580, 0x68d8, 0xd0a4, 0x0528, + 0xc0b5, 0x68da, 0x7100, 0x918c, 0x00ff, 0x697a, 0x7004, 0x687e, + 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, + 0x0016, 0x2008, 0x080c, 0x24a2, 0x7932, 0x7936, 0x001e, 0x000e, + 0x00fe, 0x080c, 0x2459, 0x695a, 0x703c, 0x00e6, 0x2071, 0x0140, + 0x7086, 0x2071, 0x1800, 0x70b2, 0x00ee, 0x7034, 0x9005, 0x1904, + 0x7ce5, 0x2009, 0x0017, 0x0804, 0x7c95, 0x908e, 0x0400, 0x1190, + 0x7034, 0x9005, 0x1904, 0x7ce5, 0x080c, 0x70ba, 0x0120, 0x2009, + 0x001d, 0x0804, 0x7c95, 0x68d8, 0xc0a5, 0x68da, 0x2009, 0x0030, + 0x0804, 0x7c95, 0x908e, 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, + 0x7ce5, 0x2009, 0x0018, 0x0804, 0x7c95, 0x908e, 0x2010, 0x1120, + 0x2009, 0x0019, 0x0804, 0x7c95, 0x908e, 0x2110, 0x1120, 0x2009, + 0x001a, 0x0804, 0x7c95, 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, + 0x1904, 0x7ce5, 0x2009, 0x001b, 0x0804, 0x7c95, 0x908e, 0x5000, + 0x1140, 0x7034, 0x9005, 0x1904, 0x7ce5, 0x2009, 0x001c, 0x0804, + 0x7c95, 0x908e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x7c95, + 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, 0x1904, 0x7ce5, 0x2009, + 0x0024, 0x0804, 0x7c95, 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, + 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, 0xd09c, 0x0904, 0x7c95, + 0x080c, 0xc66b, 0x1904, 0x7ce5, 0x0804, 0x7c93, 0x908c, 0xff00, + 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, 0x0804, 0x7c95, 0x908e, + 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, 0x7c95, 0x908e, 0x6104, + 0x1528, 0x2029, 0x0205, 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, + 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, + 0x0046, 0x2124, 0x080c, 0x48fa, 0x004e, 0x8108, 0x0f04, 0x7c61, + 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, + 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, 0x0478, 0x908e, 0x6000, + 0x1118, 0x2009, 0x003f, 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, + 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, + 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, + 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, + 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, + 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, + 0x2204, 0x8211, 0x220c, 0x080c, 0x2459, 0x1904, 0x7ce8, 0x080c, + 0x622f, 0x1904, 0x7ce8, 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, + 0x70ba, 0x01c0, 0x68d8, 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, + 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, 0x0040, 0x6878, 0x9606, + 0x1148, 0x687c, 0x9506, 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, + 0xb886, 0x0080, 0xb884, 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, + 0x6878, 0x9606, 0x1138, 0x687c, 0x9506, 0x9084, 0xff00, 0x1110, + 0x001e, 0x0098, 0x080c, 0x9b90, 0x01a8, 0x2b08, 0x6112, 0x6023, + 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, + 0x000a, 0x0016, 0x001e, 0x080c, 0x9c82, 0x00ce, 0x00be, 0x0005, + 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, + 0x8049, 0x080c, 0x48fa, 0x080c, 0x9c55, 0x0d90, 0x2b08, 0x6112, + 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, + 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, + 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, + 0x0001, 0x080c, 0x84ee, 0x08a0, 0x080c, 0x3164, 0x1140, 0x7010, + 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, + 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0033, 0x11e8, 0x080c, 0x7f80, 0x0904, 0x7d6f, 0x7124, 0x610a, + 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, + 0x0015, 0x080c, 0x9c82, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, + 0x9005, 0x1568, 0x2009, 0x0016, 0x080c, 0x9c82, 0x0440, 0x9186, + 0x0032, 0x1528, 0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, + 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2459, + 0x11a8, 0x080c, 0x622f, 0x1190, 0xbe12, 0xbd16, 0x080c, 0x9b90, + 0x0168, 0x2b08, 0x6112, 0x080c, 0xbd09, 0x6023, 0x0004, 0x7120, + 0x610a, 0x001e, 0x080c, 0x9c82, 0x0010, 0x00ce, 0x001e, 0x004e, + 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, + 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, + 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x7dd1, 0x9596, 0xfffe, + 0x1120, 0x2009, 0x007e, 0x0804, 0x7dd1, 0x9596, 0xfffc, 0x1118, + 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019, 0x1836, 0x231c, + 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, + 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, + 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, + 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, + 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, + 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, + 0x1f04, 0x7da6, 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, + 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, 0x7000, + 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x0002, 0x7dee, 0x7dee, + 0x7dee, 0x7f92, 0x7dee, 0x7df1, 0x7e16, 0x7e9f, 0x7dee, 0x7dee, + 0x7dee, 0x7dee, 0x7dee, 0x7dee, 0x7dee, 0x7dee, 0x7817, 0x0140, + 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, 0x9c8c, + 0x0003, 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, 0x6864, 0x9c02, 0x1290, + 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1150, + 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x9c82, 0x7817, 0x0140, 0x00be, 0x0005, 0x00b6, 0x00c6, + 0x9484, 0x0fff, 0x0904, 0x7e7b, 0x7110, 0xd1bc, 0x1904, 0x7e7b, + 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, + 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x319f, 0x200d, 0x918c, 0xff00, + 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x7e7b, 0x9182, 0x0801, + 0x1a04, 0x7e7b, 0x9190, 0x1000, 0x2204, 0x905d, 0x05e0, 0xbe12, + 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, 0xff00, 0x9286, + 0x0600, 0x1190, 0x080c, 0x9b90, 0x0598, 0x2b08, 0x7028, 0x6052, + 0x702c, 0x604e, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, + 0x615e, 0x080c, 0xc8d2, 0x00f8, 0x080c, 0x668a, 0x1138, 0xb807, + 0x0606, 0x0c40, 0x190c, 0x7d73, 0x11b0, 0x0880, 0x080c, 0x9b90, + 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x9286, + 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, + 0x0001, 0x080c, 0x84ee, 0x7817, 0x0140, 0x00ce, 0x00be, 0x0005, + 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, + 0x48fa, 0x080c, 0x9c55, 0x0d78, 0x2b08, 0x6112, 0x6023, 0x0006, + 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, 0x6003, 0x0001, + 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x84e7, 0x08e0, 0x00b6, + 0x7110, 0xd1bc, 0x05d0, 0x7020, 0x2060, 0x9c84, 0x0003, 0x15a8, + 0x9c82, 0x1ddc, 0x0690, 0x6864, 0x9c02, 0x1678, 0x9484, 0x0fff, + 0x9082, 0x000c, 0x0650, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, + 0xb910, 0x9106, 0x1510, 0x700c, 0xb914, 0x9106, 0x11f0, 0x7124, + 0x610a, 0x601c, 0xd0fc, 0x11c8, 0x2001, 0x0271, 0x2004, 0x9005, + 0x1180, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0158, 0x0066, 0x2031, + 0x0100, 0xa001, 0xa001, 0x8631, 0x1de0, 0x006e, 0x601c, 0xd0fc, + 0x1120, 0x2009, 0x0045, 0x080c, 0x9c82, 0x7817, 0x0140, 0x00be, + 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, + 0x9085, 0x0001, 0x0005, 0x080c, 0x3164, 0x1168, 0x7010, 0x9084, + 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, + 0x0006, 0x1208, 0x000b, 0x0005, 0x7f02, 0x7f03, 0x7f02, 0x7f02, + 0x7f62, 0x7f71, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x0120, 0x702c, + 0xd084, 0x0904, 0x7f60, 0x700c, 0x7108, 0x080c, 0x2459, 0x1904, + 0x7f60, 0x080c, 0x622f, 0x1904, 0x7f60, 0xbe12, 0xbd16, 0x7110, + 0xd1bc, 0x01d8, 0x080c, 0x668a, 0x0118, 0x9086, 0x0004, 0x1588, + 0x00c6, 0x080c, 0x7f80, 0x00ce, 0x05d8, 0x080c, 0x9b90, 0x2b08, + 0x05b8, 0x6112, 0x080c, 0xbd09, 0x6023, 0x0002, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x9c82, 0x0458, 0x080c, 0x668a, 0x0148, + 0x9086, 0x0004, 0x0130, 0x080c, 0x6692, 0x0118, 0x9086, 0x0004, + 0x1180, 0x080c, 0x9b90, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xbd09, + 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x9c82, + 0x0078, 0x080c, 0x9b90, 0x2b08, 0x0158, 0x6112, 0x080c, 0xbd09, + 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x9c82, + 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, + 0x7ee1, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x9c82, + 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x7ee1, + 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x9c82, 0x0005, + 0x7020, 0x2060, 0x9c84, 0x0003, 0x1158, 0x9c82, 0x1ddc, 0x0240, + 0x2001, 0x1819, 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, + 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, + 0x9c84, 0x0003, 0x11b0, 0x9c82, 0x1ddc, 0x0298, 0x6864, 0x9c02, + 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, + 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, + 0x9c82, 0x7817, 0x0140, 0x00be, 0x0005, 0x2031, 0x0105, 0x0069, + 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029, + 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x0096, 0x00f6, + 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05c0, 0x080c, 0x9b90, + 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, 0x2204, 0x8211, + 0x220c, 0x080c, 0x2459, 0x1590, 0x080c, 0x622f, 0x1578, 0xbe12, + 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, 0xbd09, 0x080c, + 0x102f, 0x0500, 0x2900, 0x6062, 0x9006, 0xa802, 0xa866, 0xac6a, + 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860, 0x20e8, 0x20e1, + 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, 0x6007, 0x003e, + 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ee, 0x00fe, 0x009e, + 0x00ce, 0x0005, 0x080c, 0x9be6, 0x006e, 0x0cc0, 0x004e, 0x00ce, + 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, + 0x9086, 0x2000, 0x1904, 0x8068, 0x9186, 0x0022, 0x15f0, 0x2001, + 0x0111, 0x2004, 0x9005, 0x1904, 0x806a, 0x7030, 0x908e, 0x0400, + 0x0904, 0x806a, 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, + 0x908e, 0x0300, 0x11d8, 0x2009, 0x1836, 0x210c, 0xd18c, 0x1590, + 0xd1a4, 0x1580, 0x080c, 0x6648, 0x0588, 0x68ac, 0x9084, 0x00ff, + 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x687c, 0x69ac, 0x918c, + 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, + 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, + 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, + 0x080c, 0x7f80, 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, + 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, + 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001, 0x1836, 0x2004, + 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50, 0x00f6, 0x2079, + 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, + 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, + 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, + 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, 0x2071, 0x19db, 0x7003, + 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x7072, 0x7012, 0x7017, + 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, 0x8ff0, 0x7032, 0x7037, + 0x906d, 0x703f, 0xffff, 0x7042, 0x7047, 0x523f, 0x704a, 0x705b, + 0x8239, 0x080c, 0x1048, 0x090c, 0x0d65, 0x2900, 0x703a, 0xa867, + 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19db, + 0x1d04, 0x815b, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1560, + 0x2001, 0x187d, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, + 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d65, + 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, + 0x1800, 0x69e8, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, 0x82a7, + 0x0010, 0x080c, 0x827e, 0x7040, 0x900d, 0x0148, 0x8109, 0x7142, + 0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, + 0x900d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, + 0x8109, 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, + 0x1110, 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, + 0x702e, 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, + 0x007f, 0x090c, 0x90f5, 0x0010, 0x7034, 0x080f, 0x703c, 0x9005, + 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0x900d, 0x0168, 0x7048, + 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, 0x714e, 0x1120, + 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, + 0x7070, 0x900d, 0x0158, 0x706c, 0x8001, 0x706e, 0x1138, 0x706f, + 0x0009, 0x8109, 0x7172, 0x1110, 0x7074, 0x080f, 0x001e, 0x7008, + 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, + 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x8183, 0x8184, 0x81ae, + 0x00e6, 0x2071, 0x19db, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19db, + 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x7072, 0x7076, 0x000e, + 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19db, 0xb888, 0x9102, 0x0208, + 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, + 0x080c, 0x628f, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, + 0x0126, 0x2091, 0x8000, 0x0066, 0xb8c0, 0x9005, 0x0138, 0x0026, + 0xba3c, 0x0016, 0x080c, 0x63ba, 0x001e, 0x002e, 0x006e, 0x012e, + 0x8108, 0x9182, 0x0800, 0x1220, 0x8631, 0x0128, 0x7112, 0x0c00, + 0x900e, 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x2031, 0x0010, + 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6048, 0x9005, 0x0128, + 0x8001, 0x604a, 0x1110, 0x080c, 0xbb8a, 0x6018, 0x9005, 0x0904, + 0x8200, 0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, 0x8213, + 0x781b, 0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, + 0x0804, 0x8213, 0x8001, 0x601a, 0x0106, 0x781b, 0x2000, 0xa001, + 0x7918, 0xd1ac, 0x1dd0, 0x010e, 0x00fe, 0x1510, 0x6120, 0x9186, + 0x0003, 0x0118, 0x9186, 0x0006, 0x11c8, 0x080c, 0xb870, 0x01b0, + 0x6014, 0x2048, 0xa884, 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, + 0xa886, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, + 0x810b, 0x9108, 0x611a, 0x080c, 0xbfbb, 0x0110, 0x080c, 0xb551, + 0x012e, 0x9c88, 0x001c, 0x7116, 0x2001, 0x1819, 0x2004, 0x9102, + 0x1228, 0x8631, 0x0138, 0x2160, 0x0804, 0x81b2, 0x7017, 0x1ddc, + 0x7007, 0x0000, 0x0005, 0x00fe, 0x0c58, 0x00e6, 0x2071, 0x19db, + 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, 0x0005, 0x2001, 0x19e4, + 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19db, 0x7132, 0x702f, + 0x0009, 0x00ee, 0x0005, 0x2011, 0x19e7, 0x2013, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x19db, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x0086, 0x0026, 0x7054, 0x8000, 0x7056, 0x2001, 0x19e9, + 0x2044, 0xa06c, 0x9086, 0x0000, 0x0150, 0x7068, 0xa09a, 0x7064, + 0xa096, 0x7060, 0xa092, 0x705c, 0xa08e, 0x080c, 0x1124, 0x002e, + 0x008e, 0x0005, 0x0006, 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x080c, 0x80c6, 0x015e, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, + 0x0005, 0x00e6, 0x2071, 0x19db, 0x7172, 0x7276, 0x706f, 0x0009, + 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x19db, 0x7074, 0x9206, + 0x1110, 0x7072, 0x7076, 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, + 0x69e8, 0xd1e4, 0x1518, 0x0026, 0xd1ec, 0x0140, 0x6a50, 0x6870, + 0x9202, 0x0288, 0x8117, 0x9294, 0x00c1, 0x0088, 0x9184, 0x0007, + 0x01a0, 0x8109, 0x9184, 0x0007, 0x0110, 0x69ea, 0x0070, 0x8107, + 0x9084, 0x0007, 0x910d, 0x8107, 0x9106, 0x9094, 0x00c1, 0x9184, + 0xff3e, 0x9205, 0x68ea, 0x080c, 0x0efa, 0x002e, 0x0005, 0x69e4, + 0x9184, 0x003f, 0x05b8, 0x8109, 0x9184, 0x003f, 0x01a8, 0x6a50, + 0x6870, 0x9202, 0x0220, 0xd1bc, 0x0168, 0xc1bc, 0x0018, 0xd1bc, + 0x1148, 0xc1bd, 0x2110, 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f1c, + 0x00ee, 0x0400, 0x69e6, 0x00f0, 0x0026, 0x8107, 0x9094, 0x0007, + 0x0128, 0x8001, 0x8007, 0x9085, 0x0007, 0x0050, 0x2010, 0x8004, + 0x8004, 0x8004, 0x9084, 0x0007, 0x9205, 0x8007, 0x9085, 0x0028, + 0x9086, 0x0040, 0x2010, 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f1c, + 0x00ee, 0x002e, 0x0005, 0x00c6, 0x2061, 0x1a46, 0x00ce, 0x0005, + 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a46, 0x2060, + 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, + 0x2061, 0x1a46, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, + 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, + 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x83ab, + 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8384, 0x2009, 0x0006, 0x080c, + 0x83d8, 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, + 0x05e0, 0x908c, 0x2023, 0x1568, 0x87ff, 0x1558, 0xa9a8, 0x81ff, + 0x1540, 0x6124, 0x918c, 0x0500, 0x1520, 0x6100, 0x918e, 0x0007, + 0x1500, 0x2009, 0x187d, 0x210c, 0xd184, 0x11d8, 0x6003, 0x0003, + 0x6007, 0x0043, 0x6047, 0xb035, 0x080c, 0x1aca, 0xa87c, 0xc0dd, + 0xa87e, 0x600f, 0x0000, 0x00f6, 0x2079, 0x0380, 0x7818, 0xd0bc, + 0x1de8, 0x7833, 0x0013, 0x2c00, 0x7836, 0x781b, 0x8080, 0x00fe, + 0x0005, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x83d2, + 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, + 0x2009, 0x187d, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, + 0x0043, 0x0804, 0x9c82, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, + 0x0804, 0x9c82, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, + 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, + 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, + 0x0120, 0x918e, 0x0003, 0x1904, 0x83d2, 0x908c, 0x2020, 0x918e, + 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1669, 0x00fe, + 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x9c82, 0x0005, + 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, + 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, + 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, + 0x1120, 0x2009, 0x0041, 0x080c, 0x9c82, 0x0005, 0x00b9, 0x0ce8, + 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, 0x9c82, 0x0cb0, 0x6110, + 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, + 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, + 0x0096, 0x080c, 0xb870, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, + 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, + 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a46, 0x6200, 0xd28c, 0x1120, + 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x67ea, 0x6014, + 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, 0x82f1, 0x007e, 0x009e, + 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a46, 0x6000, 0x81ff, 0x0110, + 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, + 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, + 0x0001, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x0046, 0x20a9, + 0x0010, 0x9006, 0x8004, 0x8086, 0x818e, 0x1208, 0x9200, 0x1f04, + 0x8423, 0x8086, 0x818e, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, + 0x2091, 0x8000, 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x01c8, + 0x911a, 0x12b8, 0x8213, 0x818d, 0x0228, 0x911a, 0x1220, 0x1f04, + 0x843a, 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x843a, 0x0006, + 0x3200, 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, + 0x0005, 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, + 0x2800, 0x2079, 0x19bf, 0x012e, 0x00d6, 0x2069, 0x19bf, 0x6803, + 0x0005, 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, + 0x080c, 0x97f4, 0x04a9, 0x080c, 0x97df, 0x0491, 0x080c, 0x97e2, + 0x0479, 0x080c, 0x97e5, 0x0461, 0x080c, 0x97e8, 0x0449, 0x080c, + 0x97eb, 0x0431, 0x080c, 0x97ee, 0x0419, 0x080c, 0x97f1, 0x0401, + 0x01de, 0x014e, 0x015e, 0x6857, 0x0000, 0x00f6, 0x2079, 0x0380, + 0x00f9, 0x7807, 0x0003, 0x7803, 0x0000, 0x7803, 0x0001, 0x2069, + 0x0004, 0x2d04, 0x9084, 0xfffe, 0x9085, 0x8000, 0x206a, 0x2069, + 0x0100, 0x6828, 0x9084, 0xfffc, 0x682a, 0x00fe, 0x00de, 0x0005, + 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, + 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, 0x0400, + 0x7827, 0x0031, 0x782b, 0x1ac6, 0x781f, 0xff00, 0x781b, 0xff00, + 0x2061, 0x1abb, 0x602f, 0x19bf, 0x6033, 0x1800, 0x6037, 0x19db, + 0x603b, 0x1d1c, 0x603f, 0x1d2c, 0x6042, 0x6047, 0x1a91, 0x00ce, + 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, + 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19bf, + 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, 0x0003, + 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, 0x6146, + 0x2c08, 0x2001, 0x0012, 0x080c, 0x98b8, 0x0005, 0x0016, 0x2009, + 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0x98b8, 0x0088, + 0x00c6, 0x2061, 0x19bf, 0x602c, 0x8000, 0x602e, 0x600c, 0x9005, + 0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, 0x6112, 0x610e, + 0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, + 0x2061, 0x19bf, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, + 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, 0x600f, + 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0x98b8, 0x0005, 0x6044, + 0xd0dc, 0x0110, 0x080c, 0x948d, 0x0005, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, + 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19bf, 0x7648, 0x2660, + 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x85ba, 0x6010, 0x2058, + 0xb8a0, 0x9206, 0x1904, 0x85b5, 0x87ff, 0x0120, 0x605c, 0x9106, + 0x1904, 0x85b5, 0x704c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, + 0x080c, 0x929d, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, + 0x706e, 0x003e, 0x2029, 0x0001, 0x0811, 0x7048, 0x9c36, 0x1110, + 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, + 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, + 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, + 0xb870, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1588, + 0x6004, 0x9086, 0x0040, 0x090c, 0x948d, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xbb73, 0x080c, + 0xd563, 0x080c, 0x69b5, 0x007e, 0x003e, 0x001e, 0x080c, 0xba5f, + 0x080c, 0x9c20, 0x00ce, 0x0804, 0x8553, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x8553, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, + 0x006e, 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, + 0x080c, 0xd563, 0x080c, 0xd267, 0x007e, 0x003e, 0x001e, 0x08c0, + 0x6020, 0x9086, 0x000a, 0x0918, 0x0804, 0x8598, 0x0006, 0x0066, + 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, 0x8000, + 0x2079, 0x19bf, 0x7848, 0x9065, 0x0904, 0x8642, 0x600c, 0x0006, + 0x600f, 0x0000, 0x784c, 0x9c06, 0x11a0, 0x0036, 0x2019, 0x0001, + 0x080c, 0x929d, 0x783f, 0x0000, 0x901e, 0x7b4e, 0x7b6a, 0x7b52, + 0x7b6e, 0x003e, 0x000e, 0x9005, 0x1118, 0x600c, 0x600f, 0x0000, + 0x0006, 0x00e6, 0x2f70, 0x080c, 0x8537, 0x00ee, 0x080c, 0xb870, + 0x0548, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x15a8, 0x3e08, + 0x918e, 0x0002, 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, + 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6048, 0x9005, 0x11c0, 0x2001, + 0x1960, 0x2004, 0x604a, 0x0098, 0x6004, 0x9086, 0x0040, 0x090c, + 0x948d, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x69a9, + 0x080c, 0xba5f, 0x6044, 0xc0fc, 0x6046, 0x080c, 0x9c20, 0x000e, + 0x0804, 0x85eb, 0x7e4a, 0x7e46, 0x012e, 0x00fe, 0x00de, 0x00ce, + 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, + 0x080c, 0xd267, 0x0c38, 0x6020, 0x9086, 0x000a, 0x09e0, 0x08a0, + 0x0016, 0x0026, 0x0086, 0x9046, 0x00a9, 0x080c, 0x8749, 0x008e, + 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19bf, 0x2091, + 0x8000, 0x080c, 0x8792, 0x080c, 0x8826, 0x080c, 0x641c, 0x012e, + 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, + 0x7620, 0x2660, 0x2678, 0x8cff, 0x0904, 0x870e, 0x6010, 0x2058, + 0xb8a0, 0x9206, 0x1904, 0x8709, 0x88ff, 0x0120, 0x605c, 0x9106, + 0x1904, 0x8709, 0x7030, 0x9c06, 0x1570, 0x2069, 0x0100, 0x6820, + 0xd0a4, 0x1508, 0x080c, 0x821e, 0x080c, 0x8fd0, 0x68c3, 0x0000, + 0x080c, 0x948d, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, + 0x080c, 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x003e, 0x0040, 0x7008, 0xc0ad, 0x700a, 0x6003, 0x0009, + 0x630a, 0x0804, 0x8709, 0x7020, 0x9c36, 0x1110, 0x660c, 0x7622, + 0x701c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x701e, + 0x0010, 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, + 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, + 0x6014, 0x2048, 0x080c, 0xb870, 0x01e8, 0x6020, 0x9086, 0x0003, + 0x1580, 0x080c, 0xba85, 0x1118, 0x080c, 0xa59c, 0x0098, 0xa867, + 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, + 0xbb73, 0x080c, 0xd563, 0x080c, 0x69b5, 0x008e, 0x003e, 0x001e, + 0x080c, 0xba5f, 0x080c, 0x9c20, 0x080c, 0x9363, 0x00ce, 0x0804, + 0x8683, 0x2c78, 0x600c, 0x2060, 0x0804, 0x8683, 0x012e, 0x000e, + 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, + 0x080c, 0xd563, 0x080c, 0xd267, 0x008e, 0x003e, 0x001e, 0x08d0, + 0x080c, 0xa59c, 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x0904, 0x86ef, 0x9086, 0x008b, 0x0904, + 0x86ef, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, + 0x8702, 0x0006, 0x00f6, 0x00e6, 0x0096, 0x00b6, 0x00c6, 0x0066, + 0x0016, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, 0x2004, 0x905d, + 0x2079, 0x19bf, 0x9036, 0x7828, 0x2060, 0x8cff, 0x0538, 0x6010, + 0x9b06, 0x1500, 0x6043, 0xffff, 0x080c, 0x9a83, 0x01d8, 0x610c, + 0x0016, 0x080c, 0x9127, 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xbb73, 0x080c, + 0xd563, 0x080c, 0x69b5, 0x008e, 0x003e, 0x001e, 0x080c, 0x9c20, + 0x00ce, 0x08d8, 0x2c30, 0x600c, 0x2060, 0x08b8, 0x080c, 0x6439, + 0x012e, 0x001e, 0x006e, 0x00ce, 0x00be, 0x009e, 0x00ee, 0x00fe, + 0x000e, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x9036, + 0x7820, 0x9065, 0x0904, 0x87f9, 0x600c, 0x0006, 0x6044, 0xc0fc, + 0x6046, 0x600f, 0x0000, 0x7830, 0x9c06, 0x1588, 0x2069, 0x0100, + 0x6820, 0xd0a4, 0x1508, 0x080c, 0x821e, 0x080c, 0x8fd0, 0x68c3, + 0x0000, 0x080c, 0x948d, 0x7833, 0x0000, 0x0036, 0x2069, 0x0140, + 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2872, + 0x9006, 0x080c, 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, + 0x6827, 0x0001, 0x003e, 0x0058, 0x080c, 0x6640, 0x1538, 0x6003, + 0x0009, 0x630a, 0x7808, 0xc0ad, 0x780a, 0x2c30, 0x00f8, 0x6014, + 0x2048, 0x080c, 0xb86e, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, + 0x080c, 0xba85, 0x1118, 0x080c, 0xa59c, 0x0060, 0x080c, 0x6640, + 0x1168, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x69b5, + 0x080c, 0xba5f, 0x080c, 0x9c20, 0x080c, 0x9363, 0x000e, 0x0804, + 0x8799, 0x7e22, 0x7e1e, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xd267, 0x0c50, + 0x080c, 0xa59c, 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, + 0x9086, 0x0085, 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, + 0x6020, 0x9086, 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, + 0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0096, + 0x00b6, 0x00c6, 0x0066, 0x9036, 0x7828, 0x9065, 0x0510, 0x6010, + 0x2058, 0x600c, 0x0006, 0x3e08, 0x918e, 0x0002, 0x1118, 0xb800, + 0xd0bc, 0x11a8, 0x6043, 0xffff, 0x080c, 0x9a83, 0x0180, 0x610c, + 0x080c, 0x9127, 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, + 0x0000, 0x080c, 0x69b5, 0x080c, 0x9c20, 0x000e, 0x08f0, 0x2c30, + 0x0ce0, 0x006e, 0x00ce, 0x00be, 0x009e, 0x000e, 0x0005, 0x00e6, + 0x00d6, 0x0096, 0x0066, 0x080c, 0x5df1, 0x11b0, 0x2071, 0x19bf, + 0x7030, 0x9080, 0x0005, 0x2004, 0x904d, 0x0170, 0xa878, 0x9606, + 0x1158, 0x2071, 0x19bf, 0x7030, 0x9035, 0x0130, 0x9080, 0x0005, + 0x2004, 0x9906, 0x1108, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, + 0x0005, 0x00c6, 0x2660, 0x6043, 0xffff, 0x080c, 0x9a83, 0x0178, + 0x080c, 0x9127, 0x6014, 0x2048, 0xa867, 0x0103, 0xab7a, 0xa877, + 0x0000, 0x080c, 0xbb73, 0x080c, 0x69b5, 0x080c, 0x9c20, 0x00ce, + 0x0005, 0x00b6, 0x00e6, 0x00c6, 0x080c, 0x98c7, 0x0106, 0x2071, + 0x0101, 0x2e04, 0xc0c4, 0x2072, 0x6044, 0xd0fc, 0x1138, 0x010e, + 0x090c, 0x98e3, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x2071, 0x19bf, + 0x7030, 0x9005, 0x0da0, 0x9c06, 0x190c, 0x0d65, 0x7036, 0x080c, + 0x821e, 0x7004, 0x9084, 0x0007, 0x0002, 0x88bf, 0x88c1, 0x88c8, + 0x88d2, 0x88e0, 0x88bf, 0x88cd, 0x88bd, 0x080c, 0x0d65, 0x0428, + 0x0005, 0x080c, 0x9a6e, 0x7007, 0x0000, 0x7033, 0x0000, 0x00e8, + 0x0066, 0x9036, 0x080c, 0x9127, 0x006e, 0x7007, 0x0000, 0x7033, + 0x0000, 0x0098, 0x080c, 0x9a59, 0x0140, 0x080c, 0x9a6e, 0x0128, + 0x0066, 0x9036, 0x080c, 0x9127, 0x006e, 0x7033, 0x0000, 0x0028, + 0x080c, 0x9a59, 0x080c, 0x948d, 0x0000, 0x010e, 0x190c, 0x98e3, + 0x00ce, 0x00ee, 0x00be, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x98c7, + 0x0106, 0x6044, 0xd0fc, 0x1130, 0x010e, 0x090c, 0x98e3, 0x00ce, + 0x00de, 0x0005, 0x2069, 0x19bf, 0x684c, 0x9005, 0x0da8, 0x9c06, + 0x190c, 0x0d65, 0x6852, 0x00e6, 0x2d70, 0x080c, 0x8537, 0x00ee, + 0x080c, 0x822b, 0x0016, 0x2009, 0x0040, 0x080c, 0x207b, 0x001e, + 0x683c, 0x9084, 0x0003, 0x0002, 0x891a, 0x891b, 0x8939, 0x8918, + 0x080c, 0x0d65, 0x0460, 0x6868, 0x9086, 0x0001, 0x0190, 0x600c, + 0x9015, 0x0160, 0x6a4a, 0x600f, 0x0000, 0x6044, 0xc0fc, 0x6046, + 0x9006, 0x7042, 0x684e, 0x683f, 0x0000, 0x00c8, 0x684a, 0x6846, + 0x0ca0, 0x686b, 0x0000, 0x6848, 0x9065, 0x0d78, 0x6003, 0x0002, + 0x0c60, 0x9006, 0x686a, 0x6852, 0x686e, 0x600c, 0x9015, 0x0120, + 0x6a4a, 0x600f, 0x0000, 0x0018, 0x684e, 0x684a, 0x6846, 0x684f, + 0x0000, 0x010e, 0x190c, 0x98e3, 0x00ce, 0x00de, 0x0005, 0x0005, + 0x6020, 0x9084, 0x000f, 0x000b, 0x0005, 0x8965, 0x8968, 0x8dc1, + 0x8e50, 0x8968, 0x8dc1, 0x8e50, 0x8965, 0x8968, 0x8965, 0x8965, + 0x8965, 0x8965, 0x8965, 0x8965, 0x8965, 0x080c, 0x8891, 0x0005, + 0x00b6, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, + 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, + 0x0053, 0x1a0c, 0x0d65, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x908a, 0x0040, 0x1a04, 0x89d4, 0x005b, 0x00fe, + 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, + 0x00be, 0x0005, 0x8b4b, 0x8b86, 0x8baf, 0x8c52, 0x8c73, 0x8c79, + 0x8c86, 0x8c8e, 0x8c9a, 0x8ca0, 0x8cb1, 0x8ca0, 0x8d08, 0x8c8e, + 0x8d14, 0x8d1a, 0x8c9a, 0x8d1a, 0x8d26, 0x89d2, 0x89d2, 0x89d2, + 0x89d2, 0x89d2, 0x89d2, 0x89d2, 0x89d2, 0x89d2, 0x89d2, 0x89d2, + 0x9148, 0x916b, 0x917c, 0x919c, 0x91ce, 0x8c86, 0x89d2, 0x8c86, + 0x8ca0, 0x89d2, 0x8baf, 0x8c52, 0x89d2, 0x958b, 0x8ca0, 0x89d2, + 0x95a7, 0x8ca0, 0x89d2, 0x8c9a, 0x8b45, 0x89f5, 0x89d2, 0x95c3, + 0x9630, 0x9714, 0x89d2, 0x9721, 0x8c83, 0x974c, 0x89d2, 0x91d8, + 0x9758, 0x89d2, 0x080c, 0x0d65, 0x2100, 0x005b, 0x00fe, 0x00ee, + 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, + 0x0005, 0x89f3, 0x89f3, 0x89f3, 0x8a1c, 0x8ac8, 0x8ad3, 0x89f3, + 0x89f3, 0x89f3, 0x8b1a, 0x8b26, 0x8a37, 0x89f3, 0x8a52, 0x8a86, + 0x9ad9, 0x9b1e, 0x8ca0, 0x080c, 0x0d65, 0x00d6, 0x0096, 0x080c, + 0x8d39, 0x7003, 0x2414, 0x7007, 0x0018, 0x700b, 0x0800, 0x7814, + 0x2048, 0xa83c, 0x700e, 0xa850, 0x7022, 0xa854, 0x7026, 0x60c3, + 0x0018, 0x080c, 0x8fa0, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, + 0x2058, 0xb8a0, 0x00be, 0x080c, 0x9b65, 0x1118, 0x9084, 0xff80, + 0x0110, 0x9085, 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0x8d39, + 0x7003, 0x0500, 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, + 0xa87c, 0x7012, 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, + 0x60c3, 0x0010, 0x080c, 0x8fa0, 0x009e, 0x00de, 0x0005, 0x00d6, + 0x0096, 0x080c, 0x8d39, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, + 0x700a, 0xa8d0, 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, + 0x701a, 0xa8e0, 0x701e, 0x60c3, 0x0010, 0x080c, 0x8fa0, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8d50, 0x20e9, 0x0000, 0x2001, 0x1973, 0x2003, 0x0000, 0x7814, - 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, 0x60c2, - 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, - 0x2001, 0x1973, 0x0016, 0x200c, 0x080c, 0xc59f, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, 0x080c, - 0x0fd4, 0x080c, 0x8f6c, 0x012e, 0x009e, 0x00de, 0x0005, 0x60c0, - 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, 0x20a3, - 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x8d05, 0x7003, 0x7800, - 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x00d6, - 0x00e6, 0x080c, 0x8d50, 0x7814, 0x9084, 0xff00, 0x2073, 0x0200, - 0x8e70, 0x8e70, 0x9095, 0x0010, 0x2272, 0x8e70, 0x2073, 0x0034, - 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, - 0x1f04, 0x8ab5, 0x2069, 0x1801, 0x20a9, 0x0004, 0x2d76, 0x8d68, - 0x8e70, 0x1f04, 0x8abe, 0x2069, 0x1983, 0x9086, 0xdf00, 0x0110, - 0x2069, 0x199d, 0x20a9, 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, - 0x2061, 0x0200, 0x6010, 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, - 0x2d04, 0x8007, 0x2072, 0x8d68, 0x8e70, 0x1f04, 0x8acc, 0x60c3, - 0x004c, 0x080c, 0x8f6c, 0x00ee, 0x00de, 0x0005, 0x080c, 0x8d05, - 0x7003, 0x6300, 0x7007, 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, - 0x0804, 0x8f6c, 0x00d6, 0x0026, 0x0016, 0x080c, 0x8d50, 0x7003, - 0x0200, 0x7814, 0x700e, 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, - 0x2011, 0x000c, 0x2073, 0x0800, 0x8e70, 0x2073, 0x0000, 0x00ee, - 0x7206, 0x710a, 0x62c2, 0x080c, 0x8f6c, 0x001e, 0x002e, 0x00de, - 0x0005, 0x2001, 0x1817, 0x2004, 0x609a, 0x0804, 0x8f6c, 0x080c, - 0x8d05, 0x7003, 0x5200, 0x2069, 0x1853, 0x6804, 0xd084, 0x0130, - 0x6828, 0x0016, 0x080c, 0x2470, 0x710e, 0x001e, 0x20a9, 0x0004, - 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, - 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x0254, 0x4003, - 0x080c, 0x9b59, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, - 0x181e, 0x2004, 0x7032, 0x2001, 0x181f, 0x2004, 0x7036, 0x0030, - 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x001c, - 0x0804, 0x8f6c, 0x080c, 0x8d05, 0x7003, 0x0500, 0x080c, 0x9b59, - 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, - 0x700a, 0x2001, 0x181f, 0x2004, 0x700e, 0x0030, 0x2001, 0x1817, - 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x60c3, - 0x0010, 0x0804, 0x8f6c, 0x080c, 0x8d05, 0x9006, 0x080c, 0x6630, - 0xb8a0, 0x9086, 0x007e, 0x1130, 0x7003, 0x0400, 0x620c, 0xc2b4, - 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, 0x9006, 0xa89a, - 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, 0x9086, 0x007e, - 0x1904, 0x8be6, 0x00d6, 0x2069, 0x193c, 0x2001, 0x1836, 0x2004, - 0xd0a4, 0x0178, 0x6800, 0x700a, 0x6808, 0x9084, 0x2000, 0x7012, - 0x680c, 0x7016, 0x701f, 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, - 0x0080, 0x6800, 0x700a, 0x6804, 0x700e, 0x6808, 0x080c, 0x7096, - 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x680c, - 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, - 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0x97d3, 0x2069, - 0x1944, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, 0x538c, - 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04a0, 0x2001, 0x1836, - 0x2004, 0xd0a4, 0x0168, 0x0016, 0x2009, 0x0002, 0x60e0, 0x9106, - 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x24b1, 0x61e2, 0x001e, - 0x20e1, 0x0001, 0x2099, 0x193c, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1805, 0x20a1, - 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, - 0x4003, 0x080c, 0x97d3, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x2099, - 0x1944, 0x4003, 0x60c3, 0x0074, 0x0804, 0x8f6c, 0x080c, 0x8d05, - 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, 0x2000, - 0x9006, 0x00f6, 0x2079, 0x1853, 0x7904, 0x00fe, 0xd1ac, 0x1110, - 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, 0x9085, 0x0002, 0x00d6, - 0x0804, 0x8cb5, 0x7026, 0x60c3, 0x0014, 0x0804, 0x8f6c, 0x080c, - 0x8d05, 0x7003, 0x5000, 0x0804, 0x8b95, 0x080c, 0x8d05, 0x7003, - 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, 0x8f6c, 0x080c, - 0x8d47, 0x0010, 0x080c, 0x8d50, 0x7003, 0x0200, 0x60c3, 0x0004, - 0x0804, 0x8f6c, 0x080c, 0x8d50, 0x7003, 0x0100, 0x700b, 0x0003, - 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x080c, 0x8d50, - 0x7003, 0x0200, 0x0804, 0x8b95, 0x080c, 0x8d50, 0x7003, 0x0100, - 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, 0x0003, 0x7814, - 0x700e, 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x00d6, 0x080c, 0x8d50, - 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, 0xb894, 0x9086, - 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, 0x0190, 0xb998, 0x9184, - 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, 0x0058, 0x700f, - 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, 0x0700, 0x0010, - 0x700f, 0x0800, 0x00f6, 0x2079, 0x1853, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, 0x0010, 0x2009, 0x1875, - 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, 0x0026, 0x2009, 0x1873, - 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbac4, 0xd28c, 0x1108, 0xc0cd, - 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0x9094, - 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x7026, 0x60c3, - 0x0014, 0x00de, 0x0804, 0x8f6c, 0x080c, 0x8d50, 0x7003, 0x0210, - 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, 0x0014, 0x0804, 0x8f6c, - 0x080c, 0x8d50, 0x7003, 0x0200, 0x0804, 0x8b1b, 0x080c, 0x8d50, + 0x8d39, 0x20e9, 0x0000, 0x2001, 0x197b, 0x2003, 0x0000, 0x7814, + 0x2048, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, + 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x197b, 0x0016, 0x200c, + 0x2001, 0x0001, 0x080c, 0x2060, 0x080c, 0xc5cd, 0x9006, 0x080c, + 0x2060, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, + 0x080c, 0x8fa0, 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, + 0x0126, 0x2091, 0x8000, 0x080c, 0x8d84, 0x20e9, 0x0000, 0x2001, + 0x197b, 0x2003, 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, + 0x0000, 0xa814, 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, + 0xa85c, 0x9080, 0x001b, 0x2098, 0x2001, 0x197b, 0x0016, 0x200c, + 0x080c, 0xc5cd, 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, + 0x0051, 0x7814, 0x2048, 0x080c, 0x0fe1, 0x080c, 0x8fa0, 0x012e, + 0x009e, 0x00de, 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, + 0x0130, 0x9082, 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, + 0x080c, 0x8d39, 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, + 0x0008, 0x0804, 0x8fa0, 0x00d6, 0x00e6, 0x080c, 0x8d84, 0x7814, + 0x9084, 0xff00, 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9095, 0x0010, + 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, + 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8ae9, 0x2069, 0x1801, + 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x8af2, 0x2069, + 0x198b, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19a5, 0x20a9, 0x001a, + 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, + 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, + 0x8e70, 0x1f04, 0x8b00, 0x60c3, 0x004c, 0x080c, 0x8fa0, 0x00ee, + 0x00de, 0x0005, 0x080c, 0x8d39, 0x7003, 0x6300, 0x7007, 0x0028, + 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x8fa0, 0x00d6, 0x0026, + 0x0016, 0x080c, 0x8d84, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, + 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2073, 0x0800, + 0x8e70, 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, + 0x8fa0, 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1817, 0x2004, + 0x609a, 0x0804, 0x8fa0, 0x080c, 0x8d39, 0x7003, 0x5200, 0x2069, + 0x185b, 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x248c, + 0x710e, 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, + 0x20e9, 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, + 0x1801, 0x20a1, 0x0254, 0x4003, 0x080c, 0x9b65, 0x1120, 0xb8a0, + 0x9082, 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7032, 0x2001, + 0x181f, 0x2004, 0x7036, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, + 0x00ff, 0x7036, 0x60c3, 0x001c, 0x0804, 0x8fa0, 0x080c, 0x8d39, + 0x7003, 0x0500, 0x080c, 0x9b65, 0x1120, 0xb8a0, 0x9082, 0x007f, + 0x0248, 0x2001, 0x181e, 0x2004, 0x700a, 0x2001, 0x181f, 0x2004, + 0x700e, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, 0x700e, + 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, + 0x20a1, 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0x8fa0, 0x080c, + 0x8d39, 0x9006, 0x080c, 0x6654, 0xb8a0, 0x9086, 0x007e, 0x1130, + 0x7003, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, + 0x904d, 0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, + 0x0300, 0xb8a0, 0x9086, 0x007e, 0x1904, 0x8c1a, 0x00d6, 0x2069, + 0x1944, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0178, 0x6800, 0x700a, + 0x6808, 0x9084, 0x2000, 0x7012, 0x680c, 0x7016, 0x701f, 0x2710, + 0x6818, 0x7022, 0x681c, 0x7026, 0x0080, 0x6800, 0x700a, 0x6804, + 0x700e, 0x6808, 0x080c, 0x70ba, 0x1118, 0x9084, 0x37ff, 0x0010, + 0x9084, 0x3fff, 0x7012, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, + 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, + 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, + 0x00d6, 0x080c, 0x97df, 0x2069, 0x194c, 0x2071, 0x024e, 0x6800, + 0xc0dd, 0x7002, 0x080c, 0x53ac, 0xd0e4, 0x0110, 0x680c, 0x700e, + 0x00de, 0x04a0, 0x2001, 0x1836, 0x2004, 0xd0a4, 0x0168, 0x0016, + 0x2009, 0x0002, 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, + 0x080c, 0x24cd, 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x1944, + 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, + 0x0004, 0x2099, 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, + 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x080c, 0x97df, 0x20a1, + 0x024e, 0x20a9, 0x0008, 0x2099, 0x194c, 0x4003, 0x60c3, 0x0074, + 0x0804, 0x8fa0, 0x080c, 0x8d39, 0x7003, 0x2010, 0x7007, 0x0014, + 0x700b, 0x0800, 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x185b, + 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, 0x9085, + 0x0010, 0x9085, 0x0002, 0x00d6, 0x0804, 0x8ce9, 0x7026, 0x60c3, + 0x0014, 0x0804, 0x8fa0, 0x080c, 0x8d39, 0x7003, 0x5000, 0x0804, + 0x8bc9, 0x080c, 0x8d39, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, + 0x0014, 0x0804, 0x8fa0, 0x080c, 0x8d7b, 0x0010, 0x080c, 0x8d84, + 0x7003, 0x0200, 0x60c3, 0x0004, 0x0804, 0x8fa0, 0x080c, 0x8d84, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, - 0x0804, 0x8f6c, 0x080c, 0x8d50, 0x7003, 0x0100, 0x700b, 0x000b, - 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x0026, 0x00d6, 0x0036, 0x0046, - 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, - 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x080c, 0x97e8, 0xb810, - 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, - 0x687c, 0x700e, 0x9485, 0x0029, 0x7012, 0x004e, 0x003e, 0x00de, - 0x080c, 0x8f60, 0x721a, 0x9f95, 0x0000, 0x7222, 0x7027, 0xffff, - 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, 0x080c, 0x97e8, 0x7003, - 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, 0x1800, 0x6878, 0x700a, - 0x687c, 0x700e, 0x00de, 0x7013, 0x2029, 0x0c10, 0x7003, 0x0100, - 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f, 0x0000, 0x0005, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0040, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, - 0x080c, 0x97e8, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0xb810, 0x9005, 0x1140, 0xb814, 0x9005, 0x1128, 0x700b, - 0x00ff, 0x700f, 0xfffe, 0x0020, 0x6878, 0x700a, 0x687c, 0x700e, - 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, - 0x8f60, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, - 0x002e, 0x0005, 0x080c, 0x8f60, 0x721a, 0x7a08, 0x7222, 0x7814, - 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, 0x00b6, 0x00c6, 0x00d6, - 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, - 0x0085, 0x0a0c, 0x0d65, 0x908a, 0x0092, 0x1a0c, 0x0d65, 0x6110, - 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x9082, 0x0085, - 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x8dbe, - 0x8dcd, 0x8dd8, 0x8dbc, 0x8dbc, 0x8dbc, 0x8dbe, 0x8dbc, 0x8dbc, - 0x8dbc, 0x8dbc, 0x8dbc, 0x8dbc, 0x080c, 0x0d65, 0x0411, 0x60c3, - 0x0000, 0x0026, 0x080c, 0x27c1, 0x0228, 0x2011, 0x0101, 0x2204, - 0xc0c5, 0x2012, 0x002e, 0x0804, 0x8f6c, 0x0431, 0x7808, 0x700a, - 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, 0x000c, 0x0804, 0x8f6c, - 0x0479, 0x7003, 0x0003, 0x7007, 0x0300, 0x60c3, 0x0004, 0x0804, - 0x8f6c, 0x0026, 0x080c, 0x97e8, 0xb810, 0x9085, 0x8100, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, - 0x7013, 0x0009, 0x0804, 0x8d20, 0x0026, 0x080c, 0x97e8, 0xb810, - 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, - 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8d82, - 0x0026, 0x080c, 0x97e8, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, + 0x0804, 0x8fa0, 0x080c, 0x8d84, 0x7003, 0x0200, 0x0804, 0x8bc9, + 0x080c, 0x8d84, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, + 0x0010, 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x8fa0, 0x00d6, 0x080c, 0x8d84, 0x7003, 0x0210, 0x7007, 0x0014, + 0x700b, 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, + 0x0030, 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, + 0x700f, 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, + 0x0028, 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, + 0x185b, 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0x0010, + 0x9085, 0x0010, 0x2009, 0x187d, 0x210c, 0xd184, 0x1110, 0x9085, + 0x0002, 0x0026, 0x2009, 0x187b, 0x210c, 0xd1e4, 0x0150, 0xc0c5, + 0xbac4, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, + 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, + 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0x8fa0, + 0x080c, 0x8d84, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, + 0x60c3, 0x0014, 0x0804, 0x8fa0, 0x080c, 0x8d84, 0x7003, 0x0200, + 0x0804, 0x8b4f, 0x080c, 0x8d84, 0x7003, 0x0100, 0x700b, 0x0003, + 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0x8fa0, 0x080c, 0x8d84, + 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0x8fa0, + 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, + 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, + 0x0100, 0x080c, 0x97f4, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, + 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x9485, 0x0029, + 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0x8f94, 0x721a, 0x9f95, + 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, + 0x0026, 0x080c, 0x97f4, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, + 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x00de, 0x7013, + 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, + 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, + 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, + 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0x97f4, 0xb810, 0x9305, + 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, + 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, + 0x6878, 0x700a, 0x687c, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, + 0x004e, 0x003e, 0x00de, 0x080c, 0x8f94, 0x721a, 0x7a08, 0x7222, + 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0x8f94, + 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, + 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, + 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d65, 0x908a, + 0x0092, 0x1a0c, 0x0d65, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, + 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, + 0x00ce, 0x00be, 0x0005, 0x8df2, 0x8e01, 0x8e0c, 0x8df0, 0x8df0, + 0x8df0, 0x8df2, 0x8df0, 0x8df0, 0x8df0, 0x8df0, 0x8df0, 0x8df0, + 0x080c, 0x0d65, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x27dd, + 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, + 0x8fa0, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, + 0x60c3, 0x000c, 0x0804, 0x8fa0, 0x0479, 0x7003, 0x0003, 0x7007, + 0x0300, 0x60c3, 0x0004, 0x0804, 0x8fa0, 0x0026, 0x080c, 0x97f4, + 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, + 0x6878, 0x700a, 0x687c, 0x700e, 0x7013, 0x0009, 0x0804, 0x8d54, + 0x0026, 0x080c, 0x97f4, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, 0x700a, 0x687c, 0x700e, 0x2001, - 0x0099, 0x7012, 0x0804, 0x8d82, 0x00b6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2c78, 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, - 0x0040, 0x0a0c, 0x0d65, 0x908a, 0x0057, 0x1a0c, 0x0d65, 0x7910, - 0x2158, 0xb984, 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x0005, 0x8e51, 0x8e51, - 0x8e51, 0x8e77, 0x8e51, 0x8e51, 0x8e51, 0x8e51, 0x8e51, 0x8e51, - 0x8e51, 0x9338, 0x9340, 0x9348, 0x9350, 0x8e51, 0x8e51, 0x8e51, - 0x9330, 0x080c, 0x0d65, 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8c4, - 0xd084, 0x0128, 0x7a4e, 0x7b14, 0x7b52, 0x722e, 0x732a, 0x9294, - 0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, - 0xba14, 0x7206, 0x2069, 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, - 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016, - 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0x8e87, - 0x8e87, 0x8e89, 0x8e87, 0x8e87, 0x8e87, 0x8ea3, 0x8e87, 0x080c, - 0x0d65, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, - 0x0003, 0x00b9, 0x2069, 0x1853, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, - 0x0001, 0x0804, 0x8f6c, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, - 0x0cb0, 0x0016, 0x080c, 0x97e8, 0x001e, 0xb810, 0x9085, 0x0100, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a78, 0x720a, 0x6a7c, - 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0x8f60, - 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x0096, - 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14, - 0x7378, 0x747c, 0x7820, 0x0002, 0x8eeb, 0x8eeb, 0x8eeb, 0x8eeb, - 0x8eeb, 0x8eeb, 0x8eeb, 0x8eeb, 0x8eeb, 0x8eeb, 0x8eed, 0x8eeb, - 0x8eeb, 0x8eeb, 0x8eeb, 0x080c, 0x0d65, 0xb884, 0x609e, 0x7814, - 0x2048, 0xa87c, 0xd0fc, 0x0558, 0xaf90, 0x9784, 0xff00, 0x9105, - 0x6062, 0x873f, 0x9784, 0xff00, 0x0006, 0x7814, 0x2048, 0xa878, - 0xc0fc, 0x9005, 0x000e, 0x1160, 0xaf94, 0x87ff, 0x0198, 0x2039, - 0x0098, 0x9705, 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, 0x0038, - 0x9185, 0x2200, 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, 0xb884, - 0x609e, 0x0050, 0x2039, 0x0029, 0x9705, 0x6072, 0x0cc0, 0x9185, - 0x0200, 0x6062, 0x6073, 0x2029, 0xa87c, 0xd0fc, 0x0118, 0xaf94, - 0x87ff, 0x1120, 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, - 0x646e, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x607a, 0x607f, 0x0000, 0xa848, 0x608a, 0xa844, 0x608e, - 0xa838, 0x60c6, 0xa834, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0x080c, 0x97c8, 0x2009, 0x07d0, 0x60c4, 0x9084, - 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x81ef, 0x003e, - 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, - 0x7a40, 0x9294, 0x00ff, 0x8217, 0x0005, 0x00d6, 0x2069, 0x19b7, - 0x686b, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x00f1, 0x080c, 0x81e1, 0x0005, 0x0016, 0x2001, 0x180c, 0x200c, - 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, 0x81e1, - 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, 0x19b8, - 0x2003, 0x0000, 0x2001, 0x19c3, 0x2003, 0x0000, 0x0c88, 0x0006, - 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, 0x0009, 0x080c, 0x289b, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x080c, - 0x98bb, 0x0106, 0x2061, 0x0100, 0x61a4, 0x60a7, 0x95f5, 0x0016, - 0x0026, 0x2009, 0x1804, 0x2011, 0x0008, 0x080c, 0x289b, 0x002e, - 0x001e, 0x010e, 0x090c, 0x98d7, 0x000e, 0xa001, 0xa001, 0xa001, - 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, - 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x7096, 0x1510, 0x2001, - 0x19dc, 0x2004, 0x9005, 0x1904, 0x901b, 0x080c, 0x7137, 0x11a8, - 0x2069, 0x0380, 0x6843, 0x0101, 0x6844, 0xd084, 0x1de8, 0x2061, - 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, 0xd084, 0x090c, 0x0d65, - 0x6843, 0x0100, 0x080c, 0x81e1, 0x04b0, 0x00c6, 0x2061, 0x19b7, - 0x00f0, 0x6904, 0x9194, 0x4000, 0x0598, 0x080c, 0x8f9c, 0x080c, - 0x2862, 0x00c6, 0x2061, 0x19b7, 0x6134, 0x9192, 0x0008, 0x1278, - 0x8108, 0x6136, 0x080c, 0x98bb, 0x6130, 0x080c, 0x98d7, 0x00ce, - 0x81ff, 0x01c8, 0x080c, 0x81e1, 0x080c, 0x8f8f, 0x00a0, 0x080c, - 0x98bb, 0x6130, 0x91e5, 0x0000, 0x0150, 0x080c, 0xd621, 0x080c, - 0x81ea, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, 0x9c76, 0x080c, - 0x98d7, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, - 0x2001, 0x19dc, 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19b7, - 0x6134, 0x9192, 0x0003, 0x1ad8, 0x8108, 0x6136, 0x00ce, 0x080c, - 0x81e1, 0x080c, 0x5b92, 0x2009, 0x1852, 0x2114, 0x8210, 0x220a, - 0x0c10, 0x0096, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, - 0x81f7, 0x080c, 0x98bb, 0x2001, 0x0387, 0x2003, 0x0202, 0x2071, - 0x19b7, 0x714c, 0x81ff, 0x0904, 0x90af, 0x2061, 0x0100, 0x2069, - 0x0140, 0x080c, 0x7096, 0x11c0, 0x0036, 0x2019, 0x0002, 0x080c, - 0x9269, 0x003e, 0x714c, 0x2160, 0x080c, 0xd621, 0x2009, 0x004a, - 0x6003, 0x0003, 0x080c, 0x9c76, 0x2001, 0x0386, 0x2003, 0x5040, - 0x080c, 0x7137, 0x0804, 0x90af, 0x6904, 0xd1f4, 0x0904, 0x90bc, - 0x080c, 0x2862, 0x00c6, 0x704c, 0x9065, 0x090c, 0x0d65, 0x6020, - 0x00ce, 0x9086, 0x0006, 0x1518, 0x61c8, 0x60c4, 0x9105, 0x11f8, - 0x2009, 0x180c, 0x2104, 0xd0d4, 0x01d0, 0x6214, 0x9294, 0x1800, - 0x1128, 0x6224, 0x9294, 0x0002, 0x1510, 0x0010, 0xc0d4, 0x200a, - 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x704c, 0x2060, - 0x080c, 0x88b8, 0x2009, 0x0049, 0x080c, 0x9c76, 0x0080, 0x0036, - 0x2019, 0x0001, 0x080c, 0x9269, 0x003e, 0x714c, 0x2160, 0x080c, - 0xd621, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, 0x9c76, 0x2001, - 0x0387, 0x2003, 0x0200, 0x080c, 0x98d7, 0x002e, 0x001e, 0x00ee, - 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, 0x9070, 0x0804, - 0x9072, 0x0026, 0x00e6, 0x2071, 0x19b7, 0x706c, 0xd084, 0x01d0, - 0xc084, 0x706e, 0x714c, 0x81ff, 0x01a8, 0x2071, 0x0100, 0x9188, - 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x2009, 0x1984, 0x2011, - 0x0012, 0x080c, 0x289b, 0x0030, 0x2009, 0x1984, 0x2011, 0x0016, - 0x080c, 0x289b, 0x00ee, 0x002e, 0x0005, 0x9036, 0x2001, 0x19c1, - 0x2004, 0x9005, 0x0128, 0x9c06, 0x0128, 0x2c30, 0x600c, 0x0cc8, - 0x9085, 0x0001, 0x0005, 0x00f6, 0x2079, 0x19b7, 0x610c, 0x9006, - 0x600e, 0x6044, 0xc0fc, 0x6046, 0x86ff, 0x1140, 0x7824, 0x9c06, - 0x1118, 0x7826, 0x782a, 0x0050, 0x792a, 0x0040, 0x00c6, 0x2660, - 0x610e, 0x00ce, 0x7824, 0x9c06, 0x1108, 0x7e26, 0x080c, 0x935b, - 0x080c, 0xba31, 0x00fe, 0x0005, 0x080c, 0x8d05, 0x7003, 0x1200, - 0x7838, 0x7012, 0x783c, 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, - 0x1148, 0x7810, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb810, 0xb914, - 0x00be, 0x0020, 0x2061, 0x1800, 0x6078, 0x617c, 0x9084, 0x00ff, - 0x700a, 0x710e, 0x00ce, 0x60c3, 0x002c, 0x0804, 0x8f6c, 0x080c, - 0x8d05, 0x7003, 0x0f00, 0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, - 0x00ff, 0x700a, 0xb814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x8f6c, - 0x0156, 0x080c, 0x8d50, 0x7003, 0x0200, 0x2011, 0x1848, 0x63f0, - 0x2312, 0x20a9, 0x0006, 0x2011, 0x1840, 0x2019, 0x1841, 0x9ef0, - 0x0002, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0x9159, 0x60c3, 0x001c, 0x015e, 0x0804, 0x8f6c, - 0x0016, 0x0026, 0x080c, 0x8d2c, 0x080c, 0x8d3e, 0x9e80, 0x0004, - 0x20e9, 0x0000, 0x20a0, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x009e, 0x7808, - 0x9088, 0x0002, 0x21a8, 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, - 0x0004, 0x8003, 0x60c2, 0x080c, 0x8f6c, 0x002e, 0x001e, 0x0005, - 0x20a9, 0x0010, 0x4003, 0x080c, 0x97d3, 0x20a1, 0x0240, 0x22a8, - 0x4003, 0x0c68, 0x080c, 0x8d05, 0x7003, 0x6200, 0x7808, 0x700e, - 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x0016, 0x0026, 0x080c, 0x8d05, - 0x20e9, 0x0000, 0x20a1, 0x024c, 0x7814, 0x0096, 0x2048, 0xa800, - 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, - 0x7808, 0x9088, 0x0002, 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, - 0x8f6c, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19b7, 0x7010, 0x2060, 0x8cff, 0x0188, - 0x080c, 0xba57, 0x1110, 0x080c, 0xa581, 0x600c, 0x0006, 0x080c, - 0xbcd3, 0x600f, 0x0000, 0x080c, 0x9bda, 0x080c, 0x935b, 0x00ce, - 0x0c68, 0x2c00, 0x7012, 0x700e, 0x012e, 0x000e, 0x00ce, 0x00ee, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19b7, 0x7030, 0x2060, 0x8cff, 0x0548, 0x080c, 0x8f9c, 0x6ac0, - 0x68c3, 0x0000, 0x080c, 0x81ea, 0x00c6, 0x2061, 0x0100, 0x080c, - 0x97ec, 0x00ce, 0x20a9, 0x01f4, 0x04b1, 0x080c, 0x885d, 0x6044, - 0xd0ac, 0x1128, 0x2001, 0x1958, 0x2004, 0x604a, 0x0020, 0x2009, - 0x0013, 0x080c, 0x9c76, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, - 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x81ea, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5b3c, 0x080c, 0x8138, 0x20a9, - 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2862, 0x0090, 0xd084, 0x0118, - 0x6827, 0x0001, 0x0010, 0x1f04, 0x924b, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x0380, 0x701c, 0x0006, 0x701f, 0x0202, 0x2071, 0x19b7, 0x704c, - 0x2060, 0x8cff, 0x0904, 0x930a, 0x9386, 0x0002, 0x1128, 0x6814, - 0x9084, 0x0002, 0x0904, 0x930a, 0x68af, 0x95f5, 0x6817, 0x0010, - 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, 0x080c, - 0x81f7, 0x080c, 0x1c87, 0x0046, 0x2009, 0x00a5, 0x080c, 0x0e3d, - 0x2021, 0x0169, 0x2404, 0x9084, 0x000f, 0x9086, 0x0004, 0x11f8, - 0x68af, 0x95f5, 0x68c6, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, - 0x0090, 0x2071, 0x19b7, 0x6814, 0x9084, 0x1984, 0x9085, 0x0012, - 0x6816, 0x782b, 0x0008, 0x7057, 0x0000, 0x00fe, 0x00ee, 0x9386, - 0x0002, 0x1128, 0x7884, 0x9005, 0x1110, 0x7887, 0x0001, 0x0016, - 0x2009, 0x0040, 0x080c, 0x2063, 0x001e, 0x2009, 0x0000, 0x080c, - 0x0e3d, 0x004e, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, - 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, 0x2862, 0x0090, 0xd08c, - 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, 0x92dc, 0x7804, 0x9084, - 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, - 0x2852, 0x6827, 0x4000, 0x6824, 0x83ff, 0x1160, 0x2009, 0x0049, - 0x080c, 0x88b8, 0x6044, 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, - 0x080c, 0x9c76, 0x000e, 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, + 0x0099, 0x7012, 0x0804, 0x8db6, 0x0026, 0x080c, 0x97f4, 0xb810, + 0x9085, 0x8500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6878, + 0x700a, 0x687c, 0x700e, 0x2001, 0x0099, 0x7012, 0x0804, 0x8db6, + 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, 0x0200, + 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d65, 0x908a, + 0x0057, 0x1a0c, 0x0d65, 0x7910, 0x2158, 0xb984, 0x2061, 0x0100, + 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, + 0x00be, 0x0005, 0x8e85, 0x8e85, 0x8e85, 0x8eab, 0x8e85, 0x8e85, + 0x8e85, 0x8e85, 0x8e85, 0x8e85, 0x8e85, 0x9340, 0x9348, 0x9350, + 0x9358, 0x8e85, 0x8e85, 0x8e85, 0x9338, 0x080c, 0x0d65, 0x6813, + 0x0008, 0xba8c, 0x8210, 0xb8c4, 0xd084, 0x0128, 0x7a4e, 0x7b14, + 0x7b52, 0x722e, 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a, + 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800, + 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, + 0x7027, 0xffff, 0x0005, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, + 0x0013, 0x001e, 0x0005, 0x8ebb, 0x8ebb, 0x8ebd, 0x8ebb, 0x8ebb, + 0x8ebb, 0x8ed7, 0x8ebb, 0x080c, 0x0d65, 0x7914, 0x918c, 0x08ff, + 0x918d, 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, 0x2069, 0x185b, + 0x6804, 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, + 0x0010, 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, 0x8fa0, 0x2009, + 0x0003, 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0x97f4, + 0x001e, 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, + 0x1800, 0x6a78, 0x720a, 0x6a7c, 0x720e, 0x7013, 0x0888, 0x918d, + 0x0008, 0x7116, 0x080c, 0x8f94, 0x721a, 0x7a08, 0x7222, 0x2f10, + 0x7226, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, + 0xb8a0, 0x2028, 0xb910, 0xba14, 0x7378, 0x747c, 0x7820, 0x0002, + 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, + 0x8f1f, 0x8f1f, 0x8f21, 0x8f1f, 0x8f1f, 0x8f1f, 0x8f1f, 0x080c, + 0x0d65, 0xb884, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, + 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, + 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, + 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, + 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, + 0x0129, 0x6077, 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029, + 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, + 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, + 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, + 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, + 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, + 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0x97d4, + 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, + 0x1b58, 0x080c, 0x8223, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, + 0x00ee, 0x009e, 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217, + 0x0005, 0x00d6, 0x2069, 0x19bf, 0x686b, 0x0001, 0x00de, 0x0005, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8215, 0x0005, + 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, + 0x0128, 0x0089, 0x080c, 0x8215, 0x001e, 0x0005, 0xc1e5, 0x2001, + 0x180c, 0x2102, 0x2001, 0x19c0, 0x2003, 0x0000, 0x2001, 0x19cb, + 0x2003, 0x0000, 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804, + 0x2011, 0x0009, 0x080c, 0x28bb, 0x002e, 0x001e, 0x000e, 0x0005, + 0x0016, 0x00c6, 0x0006, 0x080c, 0x98c7, 0x0106, 0x2061, 0x0100, + 0x61a4, 0x60a7, 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, + 0x0008, 0x080c, 0x28bb, 0x002e, 0x001e, 0x010e, 0x090c, 0x98e3, + 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, + 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, + 0x080c, 0x70ba, 0x1510, 0x2001, 0x19e4, 0x2004, 0x9005, 0x1904, + 0x904f, 0x080c, 0x715f, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101, + 0x6844, 0xd084, 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, + 0x6024, 0xd084, 0x090c, 0x0d65, 0x6843, 0x0100, 0x080c, 0x8215, + 0x04b0, 0x00c6, 0x2061, 0x19bf, 0x00f0, 0x6904, 0x9194, 0x4000, + 0x0598, 0x080c, 0x8fd0, 0x080c, 0x2882, 0x00c6, 0x2061, 0x19bf, + 0x6134, 0x9192, 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0x98c7, + 0x6130, 0x080c, 0x98e3, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x8215, + 0x080c, 0x8fc3, 0x00a0, 0x080c, 0x98c7, 0x6130, 0x91e5, 0x0000, + 0x0150, 0x080c, 0xd659, 0x080c, 0x821e, 0x6003, 0x0001, 0x2009, + 0x0014, 0x080c, 0x9c82, 0x080c, 0x98e3, 0x00ce, 0x0000, 0x002e, + 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x19e4, 0x2004, 0x9005, + 0x1db0, 0x00c6, 0x2061, 0x19bf, 0x6134, 0x9192, 0x0003, 0x1ad8, + 0x8108, 0x6136, 0x00ce, 0x080c, 0x8215, 0x080c, 0x5bb2, 0x2009, + 0x185a, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, + 0x00e6, 0x0016, 0x0026, 0x080c, 0x822b, 0x080c, 0x98c7, 0x2001, + 0x0387, 0x2003, 0x0202, 0x2071, 0x19bf, 0x714c, 0x81ff, 0x0904, + 0x90e3, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x70ba, 0x11c0, + 0x0036, 0x2019, 0x0002, 0x080c, 0x929d, 0x003e, 0x714c, 0x2160, + 0x080c, 0xd659, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, 0x9c82, + 0x2001, 0x0386, 0x2003, 0x5040, 0x080c, 0x715f, 0x0804, 0x90e3, + 0x6904, 0xd1f4, 0x0904, 0x90f0, 0x080c, 0x2882, 0x00c6, 0x704c, + 0x9065, 0x090c, 0x0d65, 0x6020, 0x00ce, 0x9086, 0x0006, 0x1518, + 0x61c8, 0x60c4, 0x9105, 0x11f8, 0x2009, 0x180c, 0x2104, 0xd0d4, + 0x01d0, 0x6214, 0x9294, 0x1800, 0x1128, 0x6224, 0x9294, 0x0002, + 0x1510, 0x0010, 0xc0d4, 0x200a, 0x6014, 0x9084, 0xe7fd, 0x9085, + 0x0010, 0x6016, 0x704c, 0x2060, 0x080c, 0x88ec, 0x2009, 0x0049, + 0x080c, 0x9c82, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x929d, + 0x003e, 0x714c, 0x2160, 0x080c, 0xd659, 0x2009, 0x004a, 0x6003, + 0x0003, 0x080c, 0x9c82, 0x2001, 0x0387, 0x2003, 0x0200, 0x080c, + 0x98e3, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, + 0xd1ec, 0x1904, 0x90a4, 0x0804, 0x90a6, 0x0026, 0x00e6, 0x2071, + 0x19bf, 0x706c, 0xd084, 0x01d0, 0xc084, 0x706e, 0x714c, 0x81ff, + 0x01a8, 0x2071, 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, + 0x1138, 0x2009, 0x1984, 0x2011, 0x0012, 0x080c, 0x28bb, 0x0030, + 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x28bb, 0x00ee, 0x002e, + 0x0005, 0x9036, 0x2001, 0x19c9, 0x2004, 0x9005, 0x0128, 0x9c06, + 0x0128, 0x2c30, 0x600c, 0x0cc8, 0x9085, 0x0001, 0x0005, 0x00f6, + 0x2079, 0x19bf, 0x610c, 0x9006, 0x600e, 0x6044, 0xc0fc, 0x6046, + 0x86ff, 0x1140, 0x7824, 0x9c06, 0x1118, 0x7826, 0x782a, 0x0050, + 0x792a, 0x0040, 0x00c6, 0x2660, 0x610e, 0x00ce, 0x7824, 0x9c06, + 0x1108, 0x7e26, 0x080c, 0x9363, 0x080c, 0xba5f, 0x00fe, 0x0005, + 0x080c, 0x8d39, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, + 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, + 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, + 0x6078, 0x617c, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, + 0x002c, 0x0804, 0x8fa0, 0x080c, 0x8d39, 0x7003, 0x0f00, 0x7808, + 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, + 0x60c3, 0x0008, 0x0804, 0x8fa0, 0x0156, 0x080c, 0x8d84, 0x7003, + 0x0200, 0x2011, 0x1848, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, + 0x1840, 0x2019, 0x1841, 0x9ef0, 0x0002, 0x2376, 0x8e70, 0x2276, + 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x918d, 0x60c3, + 0x001c, 0x015e, 0x0804, 0x8fa0, 0x0016, 0x0026, 0x080c, 0x8d60, + 0x080c, 0x8d72, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, + 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, + 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, + 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, + 0x8fa0, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, + 0x97df, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0x8d39, + 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0x8fa0, + 0x0016, 0x0026, 0x080c, 0x8d39, 0x20e9, 0x0000, 0x20a1, 0x024c, + 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, + 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, + 0x4003, 0x8003, 0x60c2, 0x080c, 0x8fa0, 0x002e, 0x001e, 0x0005, + 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, + 0x7010, 0x2060, 0x8cff, 0x0188, 0x080c, 0xba85, 0x1110, 0x080c, + 0xa59c, 0x600c, 0x0006, 0x080c, 0xbd01, 0x600f, 0x0000, 0x080c, + 0x9be6, 0x080c, 0x9363, 0x00ce, 0x0c68, 0x2c00, 0x7012, 0x700e, + 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, + 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0x19bf, 0x7030, 0x2060, 0x8cff, + 0x0548, 0x080c, 0x8fd0, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x821e, + 0x00c6, 0x2061, 0x0100, 0x080c, 0x97f8, 0x00ce, 0x20a9, 0x01f4, + 0x04b1, 0x080c, 0x8891, 0x6044, 0xd0ac, 0x1128, 0x2001, 0x1960, + 0x2004, 0x604a, 0x0020, 0x2009, 0x0013, 0x080c, 0x9c82, 0x000e, + 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, + 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, 0x0001, 0x0d78, + 0x9096, 0x0004, 0x0d60, 0x080c, 0x821e, 0x6814, 0x9084, 0x0001, + 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, + 0x5b5c, 0x080c, 0x816c, 0x20a9, 0x01f4, 0x0009, 0x08c0, 0x6824, + 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, + 0x2882, 0x0090, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, + 0x927f, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, + 0x2872, 0x9006, 0x080c, 0x2872, 0x0005, 0x0126, 0x0156, 0x00f6, + 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, + 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102, 0x2069, + 0x0100, 0x2079, 0x0140, 0x2071, 0x0380, 0x701c, 0x0006, 0x701f, + 0x0202, 0x2071, 0x19bf, 0x704c, 0x2060, 0x8cff, 0x0904, 0x9312, + 0x9386, 0x0002, 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0x9312, + 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, + 0x69c6, 0x68cb, 0x0008, 0x080c, 0x822b, 0x080c, 0x1c9f, 0x2001, + 0x0032, 0x6920, 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, + 0x0008, 0x692e, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, + 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, 0x2882, 0x0090, 0xd08c, + 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, 0x92e4, 0x7804, 0x9084, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, 0x080c, + 0x2872, 0x6827, 0x4000, 0x6824, 0x83ff, 0x1160, 0x2009, 0x0049, + 0x080c, 0x88ec, 0x6044, 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, + 0x080c, 0x9c82, 0x000e, 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, 0x0200, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0x19b7, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0x19b7, 0x6a3e, 0x012e, 0x00de, 0x0005, - 0x080c, 0x8e53, 0x785c, 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, - 0x080c, 0x8e53, 0x785c, 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, - 0x080c, 0x8e53, 0x785c, 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, - 0x080c, 0x8e53, 0x785c, 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, - 0x080c, 0x8e53, 0x785c, 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, - 0x0020, 0x0804, 0x8f6c, 0x00e6, 0x2071, 0x19b7, 0x702c, 0x9005, + 0x2069, 0x19bf, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, + 0x2091, 0x8000, 0x2069, 0x19bf, 0x6a3e, 0x012e, 0x00de, 0x0005, + 0x080c, 0x8e87, 0x785c, 0x7032, 0x7042, 0x7047, 0x1000, 0x00f8, + 0x080c, 0x8e87, 0x785c, 0x7032, 0x7042, 0x7047, 0x4000, 0x00b8, + 0x080c, 0x8e87, 0x785c, 0x7032, 0x7042, 0x7047, 0x2000, 0x0078, + 0x080c, 0x8e87, 0x785c, 0x7032, 0x7042, 0x7047, 0x0400, 0x0038, + 0x080c, 0x8e87, 0x785c, 0x7032, 0x7042, 0x7047, 0x0200, 0x60c3, + 0x0020, 0x0804, 0x8fa0, 0x00e6, 0x2071, 0x19bf, 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19b7, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, - 0x9400, 0x8cff, 0x0904, 0x9400, 0x6020, 0x9086, 0x0006, 0x1904, - 0x93fb, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0x93fb, 0x2039, - 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0x93fb, 0x85ff, 0x0120, - 0x605c, 0x9106, 0x1904, 0x93fb, 0x7030, 0x9c06, 0x15b0, 0x2069, + 0x19bf, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, + 0x9408, 0x8cff, 0x0904, 0x9408, 0x6020, 0x9086, 0x0006, 0x1904, + 0x9403, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, 0x9403, 0x2039, + 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0x9403, 0x85ff, 0x0120, + 0x605c, 0x9106, 0x1904, 0x9403, 0x7030, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, - 0x0001, 0x080c, 0x81ea, 0x080c, 0x9485, 0x7033, 0x0000, 0x0428, - 0x080c, 0x81ea, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x080c, 0x9485, 0x7033, 0x0000, 0x0036, + 0x0001, 0x080c, 0x821e, 0x080c, 0x948d, 0x7033, 0x0000, 0x0428, + 0x080c, 0x821e, 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x080c, 0x948d, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, 0x0100, 0x6824, + 0x080c, 0x2872, 0x9006, 0x080c, 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7020, 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, - 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xb840, 0x0110, 0x080c, - 0xd22f, 0x009e, 0x080c, 0x9c14, 0x080c, 0x935b, 0x88ff, 0x1190, - 0x00ce, 0x0804, 0x9376, 0x2c78, 0x600c, 0x2060, 0x0804, 0x9376, + 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xb86e, 0x0110, 0x080c, + 0xd267, 0x009e, 0x080c, 0x9c20, 0x080c, 0x9363, 0x88ff, 0x1190, + 0x00ce, 0x0804, 0x937e, 0x2c78, 0x600c, 0x2060, 0x0804, 0x937e, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, 0x7648, 0x2660, 0x2678, - 0x8cff, 0x0904, 0x9474, 0x6020, 0x9086, 0x0006, 0x1904, 0x946f, - 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0x946f, 0x0040, 0x6010, + 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, 0x7648, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x947c, 0x6020, 0x9086, 0x0006, 0x1904, 0x9477, + 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0x9477, 0x0040, 0x6010, 0x9b06, 0x15e8, 0x85ff, 0x0118, 0x605c, 0x9106, 0x15c0, 0x704c, - 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x9269, 0x703f, + 0x9c06, 0x1168, 0x0036, 0x2019, 0x0001, 0x080c, 0x929d, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6014, 0x2048, 0x080c, 0xb840, 0x0110, 0x080c, 0xd22f, - 0x080c, 0x9c14, 0x87ff, 0x1198, 0x00ce, 0x0804, 0x9420, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x9420, 0x9006, 0x012e, 0x000e, 0x002e, + 0x0000, 0x6014, 0x2048, 0x080c, 0xb86e, 0x0110, 0x080c, 0xd267, + 0x080c, 0x9c20, 0x87ff, 0x1198, 0x00ce, 0x0804, 0x9428, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x9428, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, - 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19b7, + 0x0000, 0x00ce, 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19bf, 0x9006, 0x7032, 0x700a, 0x7004, 0x9086, 0x0003, 0x0158, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, 0x2c10, + 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19bf, 0x2c10, 0x7648, 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110, 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, 0x885d, 0x9085, 0x0001, + 0x0000, 0x6004, 0x9086, 0x0040, 0x090c, 0x8891, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19b7, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9572, - 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0x956d, + 0x2071, 0x19bf, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0x957a, + 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0x9575, 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, - 0x9544, 0x080c, 0x8f9c, 0x68c3, 0x0000, 0x080c, 0x9485, 0x7033, + 0x954c, 0x080c, 0x8fd0, 0x68c3, 0x0000, 0x080c, 0x948d, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, + 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, 0x080c, 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x080c, 0xba46, 0x1180, 0x080c, 0x303d, 0x080c, 0xba57, - 0x1518, 0x080c, 0xa581, 0x0400, 0x080c, 0x9485, 0x6824, 0xd084, - 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xba57, 0x1118, 0x080c, - 0xa581, 0x0090, 0x6014, 0x2048, 0x080c, 0xb840, 0x0168, 0x6020, + 0x0000, 0x080c, 0xba74, 0x1180, 0x080c, 0x305d, 0x080c, 0xba85, + 0x1518, 0x080c, 0xa59c, 0x0400, 0x080c, 0x948d, 0x6824, 0xd084, + 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xba85, 0x1118, 0x080c, + 0xa59c, 0x0090, 0x6014, 0x2048, 0x080c, 0xb86e, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, - 0x080c, 0x6985, 0x080c, 0xba31, 0x080c, 0xbcd3, 0x080c, 0x9c14, - 0x080c, 0x935b, 0x00ce, 0x0804, 0x94ed, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x94ed, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, + 0x080c, 0x69a9, 0x080c, 0xba5f, 0x080c, 0xbd01, 0x080c, 0x9c20, + 0x080c, 0x9363, 0x00ce, 0x0804, 0x94f5, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x94f5, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, - 0x080c, 0xd22f, 0x0c08, 0x00d6, 0x080c, 0x8d50, 0x7003, 0x0200, - 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1959, + 0x080c, 0xd267, 0x0c08, 0x00d6, 0x080c, 0x8d84, 0x7003, 0x0200, + 0x7007, 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1961, 0x20e9, 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, - 0x0004, 0x7027, 0x7878, 0x080c, 0x8f6c, 0x00de, 0x0005, 0x080c, - 0x8d50, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, + 0x0004, 0x7027, 0x7878, 0x080c, 0x8fa0, 0x00de, 0x0005, 0x080c, + 0x8d84, 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, 0x782c, 0x7026, 0x7860, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, 0x7860, 0x9084, 0xff00, 0x8007, 0x7006, - 0x60c2, 0x0804, 0x8f6c, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, - 0x2009, 0x0035, 0x080c, 0xbed9, 0x00de, 0x1904, 0x9620, 0x080c, - 0x8d05, 0x7003, 0x1300, 0x782c, 0x080c, 0x972b, 0x2068, 0x6820, - 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0x9b59, + 0x60c2, 0x0804, 0x8fa0, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, + 0x2009, 0x0035, 0x080c, 0xbf07, 0x00de, 0x1904, 0x9628, 0x080c, + 0x8d39, 0x7003, 0x1300, 0x782c, 0x080c, 0x9737, 0x2068, 0x6820, + 0x9086, 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0x9b65, 0x11d8, 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, 0x00c0, 0xb884, 0x700e, 0x00a8, 0x080c, - 0x9b59, 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, + 0x9b65, 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181e, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, - 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x8f6c, 0x00be, 0x0005, + 0x60c3, 0x000c, 0x001e, 0x00de, 0x080c, 0x8fa0, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, - 0x0003, 0x0904, 0x969e, 0x9186, 0x0005, 0x0904, 0x9686, 0x9186, - 0x0004, 0x05f0, 0x9186, 0x0008, 0x0904, 0x968f, 0x7807, 0x0037, - 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0x9708, 0x0005, 0x080c, - 0x96c9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, - 0x6a44, 0xd2fc, 0x11f8, 0x0002, 0x9667, 0x9672, 0x9669, 0x9672, - 0x966e, 0x9667, 0x9667, 0x9672, 0x9672, 0x9672, 0x9672, 0x9667, - 0x9667, 0x9667, 0x9667, 0x9667, 0x9672, 0x9667, 0x9672, 0x080c, + 0x0003, 0x0904, 0x96a7, 0x9186, 0x0005, 0x0904, 0x968f, 0x9186, + 0x0004, 0x05f0, 0x9186, 0x0008, 0x0904, 0x9698, 0x7807, 0x0037, + 0x782f, 0x0003, 0x7817, 0x1700, 0x080c, 0x9714, 0x0005, 0x080c, + 0x96d5, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, + 0x6a44, 0xd2fc, 0x11f8, 0x0002, 0x966f, 0x967a, 0x9671, 0x967a, + 0x9676, 0x966f, 0x966f, 0x967a, 0x967a, 0x967a, 0x967a, 0x966f, + 0x966f, 0x966f, 0x966f, 0x966f, 0x967a, 0x966f, 0x967a, 0x080c, 0x0d65, 0x6824, 0xd0e4, 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, - 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0x96c2, - 0x080c, 0x96c9, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, - 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x04e0, 0x080c, 0x96c9, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x0498, 0x04c9, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, - 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, 0x0420, 0x0451, 0x00d6, - 0x0026, 0x792c, 0x2168, 0x6814, 0x0096, 0x2048, 0xa9ac, 0xa834, - 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, - 0x9180, 0x0011, 0x2004, 0xd0fc, 0x1148, 0x9180, 0x0000, 0x2004, - 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, 0x4000, - 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, 0x0804, - 0x8f6c, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, 0x8d50, - 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, 0x7810, - 0x2058, 0xb8a0, 0x080c, 0x9b59, 0x1118, 0x9092, 0x007e, 0x0268, - 0x00d6, 0x2069, 0x181e, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, 0x1000, - 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, 0xbc84, 0x2029, - 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, 0x0003, - 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, 0x7416, - 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, 0x0005, - 0x080c, 0x8d50, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x700e, 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x080c, 0x8cfc, 0x7003, - 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, 0x7012, - 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, 0x60c3, - 0x0010, 0x0804, 0x8f6c, 0x00e6, 0x2071, 0x0240, 0x0006, 0x00f6, - 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8c4, 0xd084, 0x0120, 0x7850, - 0x702a, 0x784c, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, 0x0005, - 0x080c, 0x8d47, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0x8f6c, 0x00a9, 0x7914, 0x712a, 0x60c3, - 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x27c1, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0x8f8f, 0x080c, - 0x81e1, 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7860, 0x2048, - 0xaa7c, 0x9296, 0x00c0, 0x9294, 0xfffd, 0xaa7e, 0xaa80, 0x9294, - 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, 0x00ff, - 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, 0xa870, - 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, 0x97e8, - 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, 0x0035, - 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, 0x0037, - 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, 0x0096, - 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, 0x2001, - 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, 0xd0c4, - 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, 0xc1d5, - 0x2102, 0x2009, 0x1982, 0x210c, 0x009e, 0x918d, 0x0092, 0x0010, - 0x2009, 0x0096, 0x60ab, 0x0036, 0x0026, 0x2110, 0x900e, 0x080c, - 0x289b, 0x002e, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, - 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, - 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, - 0x2009, 0x0008, 0x6912, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, - 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, - 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, - 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, - 0x6812, 0x0c60, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, 0x19b7, - 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9898, 0x7030, 0x9c06, - 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x986a, 0x080c, - 0x8f9c, 0x68c3, 0x0000, 0x080c, 0x9485, 0x7033, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, - 0x660c, 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, - 0xba46, 0x1180, 0x080c, 0x303d, 0x080c, 0xba57, 0x1518, 0x080c, - 0xa581, 0x0400, 0x080c, 0x9485, 0x6824, 0xd084, 0x09b0, 0x6827, - 0x0001, 0x0898, 0x080c, 0xba57, 0x1118, 0x080c, 0xa581, 0x0090, - 0x6014, 0x2048, 0x080c, 0xb840, 0x0168, 0x6020, 0x9086, 0x0003, - 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6991, - 0x080c, 0xba31, 0x080c, 0xbcd3, 0x080c, 0x9c14, 0x080c, 0x935b, - 0x00ce, 0x0804, 0x981b, 0x2c78, 0x600c, 0x2060, 0x0804, 0x981b, - 0x7013, 0x0000, 0x700f, 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1d08, 0x080c, 0xd22f, 0x08f0, 0x00f6, 0x0036, 0x2079, 0x0380, - 0x7b18, 0xd3bc, 0x1de8, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, - 0x003e, 0x00fe, 0x0005, 0x0016, 0x2001, 0x0382, 0x2004, 0x9084, - 0x0007, 0x9086, 0x0001, 0x1188, 0x2001, 0x0015, 0x0c29, 0x2009, - 0x1000, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, - 0x0120, 0x8109, 0x1db0, 0x080c, 0x0d65, 0x001e, 0x0005, 0x2001, - 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x1120, 0x2001, - 0x0380, 0x2003, 0x0001, 0x0005, 0x0156, 0x0016, 0x0026, 0x00e6, - 0x900e, 0x2071, 0x19b7, 0x0469, 0x0106, 0x0190, 0x7004, 0x9086, - 0x0003, 0x0148, 0x20a9, 0x1000, 0x6044, 0xd0fc, 0x01d8, 0x1f04, - 0x98f4, 0x080c, 0x0d65, 0x080c, 0x98bb, 0x6044, 0xd0fc, 0x0190, - 0x7030, 0x9c06, 0x1148, 0x080c, 0x885d, 0x6044, 0xd0dc, 0x0150, - 0xc0dc, 0x6046, 0x700a, 0x7042, 0x704c, 0x9c06, 0x190c, 0x0d65, - 0x080c, 0x88b8, 0x010e, 0x1919, 0x00ee, 0x002e, 0x001e, 0x015e, - 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, - 0x0005, 0x0126, 0x2091, 0x2400, 0x7808, 0xd0a4, 0x190c, 0x0d5e, - 0xd09c, 0x0128, 0x7820, 0x908c, 0xf000, 0x11b8, 0x0012, 0x012e, - 0x0005, 0x9941, 0x997f, 0x99a6, 0x99d6, 0x99e6, 0x99f7, 0x9a06, - 0x9a14, 0x9a25, 0x9a29, 0x9941, 0x9941, 0x9941, 0x9941, 0x9941, - 0x9941, 0x080c, 0x0d65, 0x012e, 0x0005, 0x2060, 0x6044, 0xd0bc, - 0x0140, 0xc0bc, 0x6046, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, - 0x0012, 0x012e, 0x0005, 0x9966, 0x9968, 0x9966, 0x996e, 0x9966, - 0x9966, 0x9966, 0x9966, 0x9966, 0x9968, 0x9966, 0x9968, 0x9966, - 0x9968, 0x9966, 0x9966, 0x9966, 0x9968, 0x9966, 0x080c, 0x0d65, - 0x2009, 0x0013, 0x080c, 0x9c76, 0x012e, 0x0005, 0x6014, 0x2048, - 0xa87c, 0xd0dc, 0x0130, 0x080c, 0x83a2, 0x080c, 0x9bda, 0x012e, - 0x0005, 0x2009, 0x0049, 0x080c, 0x9c76, 0x012e, 0x0005, 0x080c, - 0x98bb, 0x2001, 0x19dc, 0x2003, 0x0000, 0x7030, 0x9065, 0x090c, - 0x0d65, 0x7034, 0x9092, 0x00c8, 0x1258, 0x8000, 0x7036, 0x7004, - 0x9086, 0x0003, 0x0110, 0x7007, 0x0000, 0x781f, 0x0808, 0x0040, - 0x080c, 0xd621, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, 0x9c76, - 0x781f, 0x0100, 0x080c, 0x98d7, 0x012e, 0x0005, 0x080c, 0x98bb, - 0x714c, 0x81ff, 0x1128, 0x2011, 0x19df, 0x2013, 0x0000, 0x0400, - 0x2061, 0x0100, 0x7150, 0x9192, 0x7530, 0x12b8, 0x8108, 0x7152, - 0x714c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0050, 0x6014, 0x9084, - 0x1984, 0x9085, 0x0016, 0x6016, 0x0018, 0x706c, 0xc085, 0x706e, - 0x781f, 0x0200, 0x080c, 0x98d7, 0x012e, 0x0005, 0x080c, 0x98bb, - 0x714c, 0x2160, 0x6003, 0x0003, 0x2009, 0x004a, 0x080c, 0x9c76, - 0x781f, 0x0200, 0x080c, 0x98d7, 0x012e, 0x0005, 0x7808, 0xd09c, - 0x0de8, 0x7820, 0x2060, 0x6003, 0x0003, 0x080c, 0x98bb, 0x080c, - 0x1c0f, 0x781f, 0x0400, 0x080c, 0x98d7, 0x012e, 0x0005, 0x7808, - 0xd09c, 0x0de8, 0x7820, 0x2060, 0x080c, 0x98bb, 0x080c, 0x1c57, - 0x781f, 0x0400, 0x080c, 0x98d7, 0x012e, 0x0005, 0x7030, 0x9065, - 0x0148, 0x6044, 0xc0bc, 0x6046, 0x7104, 0x9186, 0x0003, 0x0110, - 0x080c, 0x891c, 0x012e, 0x0005, 0x00f6, 0x703c, 0x9086, 0x0002, - 0x0148, 0x704c, 0x907d, 0x0130, 0x7844, 0xc0bc, 0x7846, 0x080c, - 0x8ec6, 0x0000, 0x00fe, 0x012e, 0x0005, 0x080c, 0x7137, 0x012e, - 0x0005, 0x080c, 0x0d65, 0x0005, 0x00e6, 0x2071, 0x19b7, 0x6044, - 0xc0bc, 0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, 0x2019, - 0x0001, 0x080c, 0x9269, 0x704f, 0x0000, 0x2001, 0x0109, 0x2004, - 0xd08c, 0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, 0x703f, - 0x0000, 0x080c, 0x949c, 0x00ee, 0x0005, 0x0026, 0x7010, 0x9c06, - 0x1178, 0x080c, 0x935b, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, - 0x0120, 0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, 0x9006, - 0x002e, 0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, 0x935b, - 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, 0x600f, - 0x0000, 0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, 0x00d6, - 0x0036, 0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, - 0x01f8, 0x080c, 0x81ea, 0x080c, 0x8f9c, 0x68c3, 0x0000, 0x080c, - 0x9485, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2852, 0x9006, 0x080c, 0x2852, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, 0x0038, - 0x7808, 0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, 0x003e, - 0x00de, 0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, 0x0100, - 0x2001, 0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, 0x2091, - 0x2800, 0x0016, 0x0036, 0x080c, 0x9921, 0x003e, 0x001e, 0x012e, - 0x00ce, 0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, 0x8319, - 0x1d38, 0x003e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0156, 0x080c, - 0x8d50, 0x7a14, 0x82ff, 0x0138, 0x7003, 0x0100, 0x700b, 0x0003, - 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, 0x7007, 0x0000, 0x2069, - 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, 0x1110, 0xc38d, 0x0060, - 0x080c, 0x7096, 0x1110, 0xc3ad, 0x0008, 0xc3a5, 0x6ad8, 0xd29c, - 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, 0x2011, 0x1848, 0x63f0, - 0x2312, 0x20a9, 0x0006, 0x2011, 0x1840, 0x2019, 0x1841, 0x2071, - 0x0250, 0x2376, 0x8e70, 0x2276, 0x8e70, 0x9398, 0x0002, 0x9290, - 0x0002, 0x1f04, 0x9b01, 0x60c3, 0x0020, 0x080c, 0x8f6c, 0x015e, - 0x00de, 0x0005, 0x0156, 0x080c, 0x8d50, 0x7a14, 0x82ff, 0x0168, - 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, 0x1238, 0x7003, 0x0100, - 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, 0x7003, 0x0200, 0x7007, - 0x001c, 0x700f, 0x0001, 0x2011, 0x198d, 0x2204, 0x8007, 0x701a, - 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181e, 0x2004, 0x7022, 0x2001, 0x181f, - 0x2004, 0x7026, 0x0030, 0x2001, 0x1817, 0x2004, 0x9084, 0x00ff, - 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, 0x001c, 0x015e, 0x0804, - 0x8f6c, 0x0006, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x000e, 0x0005, - 0x2011, 0x0003, 0x080c, 0x931c, 0x2011, 0x0002, 0x080c, 0x9326, - 0x080c, 0x91e9, 0x0036, 0x901e, 0x080c, 0x9269, 0x003e, 0x0005, - 0x2071, 0x1883, 0x7000, 0x9005, 0x0140, 0x2001, 0x0812, 0x2071, - 0x1800, 0x7072, 0x7076, 0x7067, 0xffd4, 0x2071, 0x1800, 0x7070, - 0x7052, 0x7057, 0x1ddc, 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, - 0x2091, 0x8000, 0x7550, 0x9582, 0x0010, 0x0608, 0x7054, 0x2060, - 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7064, 0x9c02, - 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, - 0x7552, 0x9ca8, 0x001c, 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, - 0x0001, 0x012e, 0x00ee, 0x0005, 0x7057, 0x1ddc, 0x0cc0, 0x9006, - 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7550, 0x9582, 0x0010, 0x0600, - 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, - 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x7552, 0x9ca8, 0x001c, 0x7064, 0x9502, 0x1228, - 0x7556, 0x9085, 0x0001, 0x00ee, 0x0005, 0x7057, 0x1ddc, 0x0cc8, - 0x9006, 0x0cc8, 0x9c82, 0x1ddc, 0x0a0c, 0x0d65, 0x2001, 0x1819, - 0x2004, 0x9c02, 0x1a0c, 0x0d65, 0x9006, 0x6006, 0x600a, 0x600e, - 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, 0x601e, - 0x605e, 0x6062, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, - 0x603e, 0x604a, 0x6046, 0x6042, 0x2061, 0x1800, 0x6050, 0x8000, - 0x6052, 0x0005, 0x9006, 0x600e, 0x6016, 0x601a, 0x6012, 0x6022, - 0x6002, 0x601e, 0x605e, 0x6062, 0x604a, 0x6046, 0x2061, 0x1800, - 0x6050, 0x8000, 0x6052, 0x0005, 0x0006, 0x6000, 0x9086, 0x0000, - 0x01d0, 0x601c, 0xd084, 0x190c, 0x1921, 0x6023, 0x0007, 0x2001, - 0x1956, 0x2004, 0x0006, 0x9082, 0x0051, 0x000e, 0x0208, 0x8004, - 0x601a, 0x080c, 0xd4df, 0x604b, 0x0000, 0x6044, 0xd0fc, 0x1129, - 0x9006, 0x6046, 0x6016, 0x000e, 0x0005, 0x080c, 0x98bb, 0x0106, - 0x2001, 0x19ca, 0x2004, 0x9c06, 0x1130, 0x0036, 0x2019, 0x0001, - 0x080c, 0x9269, 0x003e, 0x080c, 0x949c, 0x010e, 0x090c, 0x98d7, - 0x0005, 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7550, - 0x9582, 0x0001, 0x0608, 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, - 0x0148, 0x9ce0, 0x001c, 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, - 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, 0x001c, - 0x7064, 0x9502, 0x1230, 0x7556, 0x9085, 0x0001, 0x012e, 0x00ee, - 0x0005, 0x7057, 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x6020, 0x9084, - 0x000f, 0x0002, 0x9c8a, 0x9c94, 0x9caf, 0x9cca, 0xbfb4, 0xbfd1, - 0xbfec, 0x9c8a, 0x9c94, 0x9c8a, 0x9ce6, 0x9c8a, 0x9c8a, 0x9c8a, - 0x9c8a, 0x9c8a, 0x9186, 0x0013, 0x1130, 0x6044, 0xd0fc, 0x0110, - 0x080c, 0x885d, 0x0005, 0x0005, 0x0066, 0x6000, 0x90b2, 0x0016, - 0x1a0c, 0x0d65, 0x0013, 0x006e, 0x0005, 0x9cad, 0xa3f6, 0xa5c8, - 0x9cad, 0xa656, 0x9faf, 0x9cad, 0x9cad, 0xa378, 0xabfd, 0x9cad, - 0x9cad, 0x9cad, 0x9cad, 0x9cad, 0x9cad, 0x080c, 0x0d65, 0x0066, - 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x006e, 0x0005, - 0x9cc8, 0xb202, 0x9cc8, 0x9cc8, 0x9cc8, 0x9cc8, 0x9cc8, 0x9cc8, - 0xb1a7, 0xb385, 0x9cc8, 0xb23f, 0xb2c3, 0xb23f, 0xb2c3, 0x9cc8, - 0x080c, 0x0d65, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d65, 0x6000, - 0x0002, 0x9ce4, 0xac47, 0xacde, 0xae5e, 0xaecd, 0x9ce4, 0x9ce4, - 0x9ce4, 0xac16, 0xb128, 0xb12b, 0x9ce4, 0x9ce4, 0x9ce4, 0x9ce4, - 0xb15b, 0x9ce4, 0x9ce4, 0x9ce4, 0x080c, 0x0d65, 0x0066, 0x6000, - 0x90b2, 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x006e, 0x0005, 0x9cff, - 0x9cff, 0x9d3d, 0x9ddc, 0x9e5c, 0x9cff, 0x9cff, 0x9cff, 0x9d01, - 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x080c, - 0x0d65, 0x9186, 0x004c, 0x0560, 0x9186, 0x0003, 0x190c, 0x0d65, - 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, - 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa836, - 0xa8b0, 0xa83a, 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092, 0x199a, - 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, - 0x009e, 0x080c, 0x1a71, 0x2009, 0x8030, 0x080c, 0x84fa, 0x0005, - 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, 0x9e7e, - 0x080c, 0xbf79, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, 0x00f6, - 0x2079, 0x1800, 0x7a8c, 0x6014, 0x2048, 0xa87c, 0xd0ec, 0x1110, - 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, 0x1140, - 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, 0x0028, - 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, 0x0000, - 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, 0x1118, - 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, 0x2001, - 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, 0x9da4, - 0x9da4, 0x9d9f, 0x9da2, 0x9da4, 0x9d9c, 0x9d8f, 0x9d8f, 0x9d8f, - 0x9d8f, 0x9d8f, 0x9d8f, 0x9d8f, 0x9d8f, 0x9d8f, 0x9d8f, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, 0x00fe, - 0x009e, 0x00de, 0x080c, 0x0d65, 0x080c, 0xa839, 0x0028, 0x080c, - 0xa95c, 0x0010, 0x080c, 0xaa4b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0x9f3c, 0x0530, - 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0xaacc, - 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x128b, 0x080c, - 0xa0e7, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, 0x00de, - 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0x9bda, 0x2001, 0x002c, - 0x900e, 0x080c, 0x9fa2, 0x0c70, 0x91b6, 0x0015, 0x0170, 0x91b6, - 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0d65, 0x91b2, 0x0050, - 0x1a0c, 0x0d65, 0x9182, 0x0047, 0x0042, 0x080c, 0x9aaa, 0x0120, - 0x9086, 0x0002, 0x0904, 0x9d3d, 0x0005, 0x9dfe, 0x9dfe, 0x9e00, - 0x9e32, 0x9dfe, 0x9dfe, 0x9dfe, 0x9dfe, 0x9e45, 0x080c, 0x0d65, - 0x00d6, 0x0016, 0x0096, 0x6003, 0x0004, 0x6114, 0x2148, 0xa87c, - 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, 0x9005, - 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0x9fa2, 0x080c, 0x9bda, - 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, 0xa8ae, - 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, - 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, 0x001e, - 0x00de, 0x0005, 0x080c, 0x88b8, 0x00d6, 0x0096, 0x6114, 0x2148, - 0x080c, 0xb842, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6991, 0x009e, - 0x00de, 0x080c, 0x9bda, 0x0804, 0x891b, 0x080c, 0x88b8, 0x080c, - 0x300e, 0x080c, 0xbf76, 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, - 0xb842, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6991, 0x009e, 0x00de, - 0x080c, 0x9bda, 0x0804, 0x891b, 0x9182, 0x0047, 0x0002, 0x9e6c, - 0x9e6e, 0x9e6c, 0x9e6c, 0x9e6c, 0x9e6c, 0x9e6c, 0x9e6c, 0x9e6c, - 0x9e6c, 0x9e6c, 0x9e6c, 0x9e6e, 0x080c, 0x0d65, 0x00d6, 0x0096, - 0x080c, 0x15a2, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, 0x0000, - 0x080c, 0x6991, 0x009e, 0x00de, 0x0804, 0x9bda, 0x0026, 0x0036, - 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, 0x1022, - 0x000e, 0x090c, 0x0d65, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, - 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, 0x1800, - 0x798c, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, 0x2950, - 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, 0x0001, - 0x9182, 0x0034, 0x1228, 0x2011, 0x001f, 0x080c, 0xb408, 0x04c0, - 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xb408, 0x96b2, - 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x0fd4, 0x080c, 0x1022, - 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, - 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, 0xb408, - 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, - 0x080c, 0xb408, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, - 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, 0x0048, - 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, - 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x6991, - 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, 0x006e, - 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, 0x0006, - 0x080c, 0x1022, 0x000e, 0x090c, 0x0d65, 0xa960, 0x21e8, 0xa95c, - 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xaa66, - 0xa87a, 0x2079, 0x1800, 0x798c, 0x810c, 0x9188, 0x000c, 0x9182, - 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, 0xac76, - 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, 0x200c, - 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, 0x6991, - 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, 0x0096, - 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x001e, - 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, 0x000c, - 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, 0x2011, - 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, 0x1022, - 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, 0x2009, - 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, 0x2200, - 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, 0x2020, - 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, 0x83ff, - 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, 0x9085, - 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0x9f51, 0x0804, - 0x9f53, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, 0x00de, - 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, 0xa87a, - 0xa982, 0x080c, 0x6985, 0x009e, 0x003e, 0x00de, 0x0005, 0x91b6, - 0x0015, 0x1118, 0x080c, 0x9bda, 0x0030, 0x91b6, 0x0016, 0x190c, - 0x0d65, 0x080c, 0x9bda, 0x0005, 0x20a9, 0x000e, 0x20e1, 0x0000, - 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x20a0, - 0x009e, 0x4003, 0x0136, 0x9080, 0x001b, 0x20a0, 0x2011, 0x0006, - 0x20a9, 0x0001, 0x3418, 0x8318, 0x23a0, 0x4003, 0x3318, 0x8318, - 0x2398, 0x8211, 0x1db8, 0x2011, 0x0006, 0x013e, 0x20a0, 0x3318, - 0x8318, 0x2398, 0x4003, 0x3418, 0x8318, 0x23a0, 0x8211, 0x1db8, - 0x0096, 0x080c, 0xb842, 0x0130, 0x6014, 0x2048, 0xa807, 0x0000, - 0xa867, 0x0103, 0x009e, 0x0804, 0x9bda, 0x0096, 0x00d6, 0x0036, - 0x7330, 0x9386, 0x0200, 0x11a8, 0x6010, 0x00b6, 0x2058, 0xb8c7, - 0x0000, 0x00be, 0x6014, 0x9005, 0x0130, 0x2048, 0xa807, 0x0000, - 0xa867, 0x0103, 0xab32, 0x080c, 0x9bda, 0x003e, 0x00de, 0x009e, - 0x0005, 0x0011, 0x1d48, 0x0cc8, 0x0006, 0x0016, 0x080c, 0xbf61, - 0x0188, 0x6014, 0x9005, 0x1170, 0x600b, 0x0003, 0x601b, 0x0000, - 0x604b, 0x0000, 0x2009, 0x0022, 0x080c, 0xa3ce, 0x9006, 0x001e, - 0x000e, 0x0005, 0x9085, 0x0001, 0x0cd0, 0x0096, 0x0016, 0x20a9, - 0x0014, 0x9e80, 0x000c, 0x20e1, 0x0000, 0x2098, 0x6014, 0x2048, + 0x2009, 0x2000, 0x682c, 0x7022, 0x6830, 0x7026, 0x0804, 0x96ce, + 0x080c, 0x96d5, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, + 0x6a00, 0x9286, 0x0002, 0x1108, 0x900e, 0x0804, 0x96ce, 0x080c, + 0x96d5, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x04b0, + 0x04e1, 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, + 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, 0x900e, 0x0438, 0x0469, + 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, 0x6924, 0xc185, 0x6926, + 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, + 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, 0x0011, 0x2004, 0xd0fc, + 0x1148, 0x9180, 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, + 0x0004, 0x0118, 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, + 0x0018, 0x002e, 0x00de, 0x0804, 0x8fa0, 0x00b6, 0x0036, 0x0046, + 0x0056, 0x0066, 0x080c, 0x8d84, 0x9006, 0x7003, 0x0200, 0x7938, + 0x710a, 0x793c, 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0x9b65, + 0x1118, 0x9092, 0x007e, 0x0268, 0x00d6, 0x2069, 0x181e, 0x2d2c, + 0x8d68, 0x2d34, 0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, + 0x0028, 0x901e, 0xbc84, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, + 0x0008, 0x2004, 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, + 0x741e, 0x0020, 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, + 0x004e, 0x003e, 0x00be, 0x0005, 0x080c, 0x8d84, 0x7003, 0x0100, + 0x782c, 0x700a, 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, + 0x8fa0, 0x080c, 0x8d30, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, + 0x783c, 0x700e, 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, + 0x00ff, 0x8007, 0x701a, 0x60c3, 0x0010, 0x0804, 0x8fa0, 0x00e6, + 0x2071, 0x0240, 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, + 0xb8c4, 0xd084, 0x0120, 0x7850, 0x702a, 0x784c, 0x702e, 0x00be, + 0x00fe, 0x000e, 0x00ee, 0x0005, 0x080c, 0x8d7b, 0x7003, 0x0100, + 0x782c, 0x700a, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0x8fa0, + 0x00a9, 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, + 0x080c, 0x27dd, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, + 0x002e, 0x080c, 0x8fc3, 0x080c, 0x8215, 0x0005, 0x0036, 0x0096, + 0x00d6, 0x00e6, 0x7860, 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, + 0xfffd, 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, + 0x00ff, 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, + 0xff00, 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, + 0x2069, 0x0200, 0x080c, 0x97f4, 0x00de, 0x20e9, 0x0000, 0x20a1, + 0x0240, 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, + 0x2098, 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, + 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, + 0x0005, 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, + 0x9084, 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, + 0x7824, 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, + 0x2001, 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x198a, 0x210c, + 0x009e, 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, + 0x0026, 0x2110, 0x900e, 0x080c, 0x28bb, 0x002e, 0x0005, 0x2009, + 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, + 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, + 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, + 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, + 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, + 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, + 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, + 0x2091, 0x8000, 0x2071, 0x19bf, 0x7610, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x98a4, 0x7030, 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, + 0x9005, 0x0904, 0x9876, 0x080c, 0x8fd0, 0x68c3, 0x0000, 0x080c, + 0x948d, 0x7033, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, + 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, 0x080c, + 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, + 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, + 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, + 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, + 0x2678, 0x600f, 0x0000, 0x080c, 0xba74, 0x1180, 0x080c, 0x305d, + 0x080c, 0xba85, 0x1518, 0x080c, 0xa59c, 0x0400, 0x080c, 0x948d, + 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, 0xba85, + 0x1118, 0x080c, 0xa59c, 0x0090, 0x6014, 0x2048, 0x080c, 0xb86e, + 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, + 0xa877, 0x0000, 0x080c, 0x69b5, 0x080c, 0xba5f, 0x080c, 0xbd01, + 0x080c, 0x9c20, 0x080c, 0x9363, 0x00ce, 0x0804, 0x9827, 0x2c78, + 0x600c, 0x2060, 0x0804, 0x9827, 0x7013, 0x0000, 0x700f, 0x0000, + 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, + 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xd267, 0x08f0, + 0x00f6, 0x0036, 0x2079, 0x0380, 0x7b18, 0xd3bc, 0x1de8, 0x7832, + 0x7936, 0x7a3a, 0x781b, 0x8080, 0x003e, 0x00fe, 0x0005, 0x0016, + 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, 0x1188, + 0x2001, 0x0015, 0x0c29, 0x2009, 0x1000, 0x2001, 0x0382, 0x2004, + 0x9084, 0x0007, 0x9086, 0x0003, 0x0120, 0x8109, 0x1db0, 0x080c, + 0x0d65, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, + 0x9086, 0x0003, 0x1120, 0x2001, 0x0380, 0x2003, 0x0001, 0x0005, + 0x0156, 0x0016, 0x0026, 0x00e6, 0x900e, 0x2071, 0x19bf, 0x0469, + 0x0106, 0x0190, 0x7004, 0x9086, 0x0003, 0x0148, 0x20a9, 0x1000, + 0x6044, 0xd0fc, 0x01d8, 0x1f04, 0x9900, 0x080c, 0x0d65, 0x080c, + 0x98c7, 0x6044, 0xd0fc, 0x0190, 0x7030, 0x9c06, 0x1148, 0x080c, + 0x8891, 0x6044, 0xd0dc, 0x0150, 0xc0dc, 0x6046, 0x700a, 0x7042, + 0x704c, 0x9c06, 0x190c, 0x0d65, 0x080c, 0x88ec, 0x010e, 0x1919, + 0x00ee, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x0382, 0x2004, + 0x9084, 0x0007, 0x9086, 0x0003, 0x0005, 0x0126, 0x2091, 0x2400, + 0x7808, 0xd0a4, 0x190c, 0x0d5e, 0xd09c, 0x0128, 0x7820, 0x908c, + 0xf000, 0x11b8, 0x0012, 0x012e, 0x0005, 0x994d, 0x998b, 0x99b2, + 0x99e2, 0x99f2, 0x9a03, 0x9a12, 0x9a20, 0x9a31, 0x9a35, 0x994d, + 0x994d, 0x994d, 0x994d, 0x994d, 0x994d, 0x080c, 0x0d65, 0x012e, + 0x0005, 0x2060, 0x6044, 0xd0bc, 0x0140, 0xc0bc, 0x6046, 0x6000, + 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x0012, 0x012e, 0x0005, 0x9972, + 0x9974, 0x9972, 0x997a, 0x9972, 0x9972, 0x9972, 0x9972, 0x9972, + 0x9974, 0x9972, 0x9974, 0x9972, 0x9974, 0x9972, 0x9972, 0x9972, + 0x9974, 0x9972, 0x080c, 0x0d65, 0x2009, 0x0013, 0x080c, 0x9c82, + 0x012e, 0x0005, 0x6014, 0x2048, 0xa87c, 0xd0dc, 0x0130, 0x080c, + 0x83d6, 0x080c, 0x9be6, 0x012e, 0x0005, 0x2009, 0x0049, 0x080c, + 0x9c82, 0x012e, 0x0005, 0x080c, 0x98c7, 0x2001, 0x19e4, 0x2003, + 0x0000, 0x7030, 0x9065, 0x090c, 0x0d65, 0x7034, 0x9092, 0x00c8, + 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, 0x0110, 0x7007, + 0x0000, 0x781f, 0x0808, 0x0040, 0x080c, 0xd659, 0x6003, 0x0001, + 0x2009, 0x0014, 0x080c, 0x9c82, 0x781f, 0x0100, 0x080c, 0x98e3, + 0x012e, 0x0005, 0x080c, 0x98c7, 0x714c, 0x81ff, 0x1128, 0x2011, + 0x19e7, 0x2013, 0x0000, 0x0400, 0x2061, 0x0100, 0x7150, 0x9192, + 0x7530, 0x12b8, 0x8108, 0x7152, 0x714c, 0x9188, 0x0008, 0x210c, + 0x918e, 0x0006, 0x1138, 0x6014, 0x9084, 0x1984, 0x9085, 0x0012, + 0x6016, 0x0050, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x6016, + 0x0018, 0x706c, 0xc085, 0x706e, 0x781f, 0x0200, 0x080c, 0x98e3, + 0x012e, 0x0005, 0x080c, 0x98c7, 0x714c, 0x2160, 0x6003, 0x0003, + 0x2009, 0x004a, 0x080c, 0x9c82, 0x781f, 0x0200, 0x080c, 0x98e3, + 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, 0x6003, + 0x0003, 0x080c, 0x98c7, 0x080c, 0x1c27, 0x781f, 0x0400, 0x080c, + 0x98e3, 0x012e, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, + 0x080c, 0x98c7, 0x080c, 0x1c6f, 0x781f, 0x0400, 0x080c, 0x98e3, + 0x012e, 0x0005, 0x7030, 0x9065, 0x0148, 0x6044, 0xc0bc, 0x6046, + 0x7104, 0x9186, 0x0003, 0x0110, 0x080c, 0x8950, 0x012e, 0x0005, + 0x00f6, 0x703c, 0x9086, 0x0002, 0x0148, 0x704c, 0x907d, 0x0130, + 0x7844, 0xc0bc, 0x7846, 0x080c, 0x8efa, 0x0000, 0x00fe, 0x012e, + 0x0005, 0x080c, 0x715f, 0x012e, 0x0005, 0x080c, 0x0d65, 0x0005, + 0x00e6, 0x2071, 0x19bf, 0x6044, 0xc0bc, 0x6046, 0xd0fc, 0x01b8, + 0x704c, 0x9c06, 0x1190, 0x2019, 0x0001, 0x080c, 0x929d, 0x704f, + 0x0000, 0x2001, 0x0109, 0x2004, 0xd08c, 0x1138, 0x2001, 0x0108, + 0x2004, 0xd0bc, 0x1110, 0x703f, 0x0000, 0x080c, 0x94a4, 0x00ee, + 0x0005, 0x0026, 0x7010, 0x9c06, 0x1178, 0x080c, 0x9363, 0x6044, + 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7212, 0x600f, 0x0000, + 0x0010, 0x7212, 0x720e, 0x9006, 0x002e, 0x0005, 0x0026, 0x7020, + 0x9c06, 0x1178, 0x080c, 0x9363, 0x6044, 0xc0fc, 0x6046, 0x600c, + 0x9015, 0x0120, 0x7222, 0x600f, 0x0000, 0x0010, 0x7222, 0x721e, + 0x9006, 0x002e, 0x0005, 0x00d6, 0x0036, 0x7830, 0x9c06, 0x1558, + 0x2069, 0x0100, 0x68c0, 0x9005, 0x01f8, 0x080c, 0x821e, 0x080c, + 0x8fd0, 0x68c3, 0x0000, 0x080c, 0x948d, 0x2069, 0x0140, 0x6b04, + 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2872, 0x9006, + 0x080c, 0x2872, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, + 0x0001, 0x9085, 0x0001, 0x0038, 0x7808, 0xc0ad, 0x780a, 0x6003, + 0x0009, 0x630a, 0x9006, 0x003e, 0x00de, 0x0005, 0x0016, 0x0026, + 0x0036, 0x6100, 0x2019, 0x0100, 0x2001, 0x0382, 0x2004, 0xd09c, + 0x0190, 0x00c6, 0x0126, 0x2091, 0x2800, 0x0016, 0x0036, 0x080c, + 0x992d, 0x003e, 0x001e, 0x012e, 0x00ce, 0x6200, 0x2200, 0x9106, + 0x0d58, 0x2200, 0x0010, 0x8319, 0x1d38, 0x003e, 0x002e, 0x001e, + 0x0005, 0x00d6, 0x0156, 0x080c, 0x8d84, 0x7a14, 0x82ff, 0x0138, + 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, + 0x0200, 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, + 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x70ba, 0x1110, 0xc3ad, + 0x0008, 0xc3a5, 0x6ad8, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, + 0x730e, 0x2011, 0x1848, 0x63f0, 0x2312, 0x20a9, 0x0006, 0x2011, + 0x1840, 0x2019, 0x1841, 0x2071, 0x0250, 0x2376, 0x8e70, 0x2276, + 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0x9b0d, 0x60c3, + 0x0020, 0x080c, 0x8fa0, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, + 0x8d84, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, + 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, + 0x0488, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, + 0x1995, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, + 0x0421, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181e, + 0x2004, 0x7022, 0x2001, 0x181f, 0x2004, 0x7026, 0x0030, 0x2001, + 0x1817, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, + 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, + 0x60c3, 0x001c, 0x015e, 0x0804, 0x8fa0, 0x0006, 0x2001, 0x1836, + 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0x9324, + 0x2011, 0x0002, 0x080c, 0x932e, 0x080c, 0x921d, 0x0036, 0x901e, + 0x080c, 0x929d, 0x003e, 0x0005, 0x2071, 0x188b, 0x7000, 0x9005, + 0x0140, 0x2001, 0x0812, 0x2071, 0x1800, 0x7072, 0x7076, 0x7067, + 0xffd4, 0x2071, 0x1800, 0x7070, 0x7052, 0x7057, 0x1ddc, 0x0005, + 0x00e6, 0x0126, 0x2071, 0x1800, 0x2091, 0x8000, 0x7550, 0x9582, + 0x0010, 0x0608, 0x7054, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, + 0x9ce0, 0x001c, 0x7064, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, + 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, 0x001c, 0x7064, + 0x9502, 0x1230, 0x7556, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, + 0x7057, 0x1ddc, 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, + 0x7550, 0x9582, 0x0010, 0x0600, 0x7054, 0x2060, 0x6000, 0x9086, + 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7064, 0x9c02, 0x1208, 0x0cb0, + 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7552, 0x9ca8, + 0x001c, 0x7064, 0x9502, 0x1228, 0x7556, 0x9085, 0x0001, 0x00ee, + 0x0005, 0x7057, 0x1ddc, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1ddc, + 0x0a0c, 0x0d65, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1a0c, 0x0d65, + 0x9006, 0x6006, 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, + 0x0000, 0x6003, 0x0000, 0x601e, 0x605e, 0x6062, 0x6026, 0x602a, + 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x604a, 0x6046, 0x6042, + 0x2061, 0x1800, 0x6050, 0x8000, 0x6052, 0x0005, 0x9006, 0x600e, + 0x6016, 0x601a, 0x6012, 0x6022, 0x6002, 0x601e, 0x605e, 0x6062, + 0x604a, 0x6046, 0x2061, 0x1800, 0x6050, 0x8000, 0x6052, 0x0005, + 0x0006, 0x6000, 0x9086, 0x0000, 0x01d0, 0x601c, 0xd084, 0x190c, + 0x193e, 0x6023, 0x0007, 0x2001, 0x195e, 0x2004, 0x0006, 0x9082, + 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xd517, 0x604b, + 0x0000, 0x6044, 0xd0fc, 0x1129, 0x9006, 0x6046, 0x6016, 0x000e, + 0x0005, 0x080c, 0x98c7, 0x0106, 0x2001, 0x19d2, 0x2004, 0x9c06, + 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0x929d, 0x003e, 0x080c, + 0x94a4, 0x010e, 0x090c, 0x98e3, 0x0005, 0x00e6, 0x0126, 0x2071, + 0x1800, 0x2091, 0x8000, 0x7550, 0x9582, 0x0001, 0x0608, 0x7054, + 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7064, + 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, + 0x8529, 0x7552, 0x9ca8, 0x001c, 0x7064, 0x9502, 0x1230, 0x7556, + 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x7057, 0x1ddc, 0x0cc0, + 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0x9c96, 0x9ca0, + 0x9cbb, 0x9cd6, 0xbfe2, 0xbfff, 0xc01a, 0x9c96, 0x9ca0, 0x9c96, + 0x9cf2, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9c96, 0x9186, 0x0013, + 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x8891, 0x0005, 0x0005, + 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x006e, + 0x0005, 0x9cb9, 0xa40f, 0xa5e3, 0x9cb9, 0xa671, 0x9fbb, 0x9cb9, + 0x9cb9, 0xa391, 0xac18, 0x9cb9, 0x9cb9, 0x9cb9, 0x9cb9, 0x9cb9, + 0x9cb9, 0x080c, 0x0d65, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0d65, 0x0013, 0x006e, 0x0005, 0x9cd4, 0xb220, 0x9cd4, 0x9cd4, + 0x9cd4, 0x9cd4, 0x9cd4, 0x9cd4, 0xb1c2, 0xb3a3, 0x9cd4, 0xb25d, + 0xb2e1, 0xb25d, 0xb2e1, 0x9cd4, 0x080c, 0x0d65, 0x6000, 0x9082, + 0x0016, 0x1a0c, 0x0d65, 0x6000, 0x0002, 0x9cf0, 0xac62, 0xacf9, + 0xae79, 0xaee8, 0x9cf0, 0x9cf0, 0x9cf0, 0xac31, 0xb143, 0xb146, + 0x9cf0, 0x9cf0, 0x9cf0, 0x9cf0, 0xb176, 0x9cf0, 0x9cf0, 0x9cf0, + 0x080c, 0x0d65, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d65, + 0x0013, 0x006e, 0x0005, 0x9d0b, 0x9d0b, 0x9d49, 0x9de8, 0x9e68, + 0x9d0b, 0x9d0b, 0x9d0b, 0x9d0d, 0x9d0b, 0x9d0b, 0x9d0b, 0x9d0b, + 0x9d0b, 0x9d0b, 0x9d0b, 0x080c, 0x0d65, 0x9186, 0x004c, 0x0560, + 0x9186, 0x0003, 0x190c, 0x0d65, 0x0096, 0x601c, 0xc0ed, 0x601e, + 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, + 0xc0b5, 0xa87e, 0xa8ac, 0xa836, 0xa8b0, 0xa83a, 0x9006, 0xa846, + 0xa84a, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, + 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, 0x080c, 0x1a89, 0x2009, + 0x8030, 0x080c, 0x852e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, + 0x00be, 0x2c00, 0x080c, 0x9e8a, 0x080c, 0xbfa7, 0x6003, 0x0007, + 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, 0x7a8c, 0x6014, + 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, + 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, + 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, + 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, + 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, + 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, + 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, + 0x8423, 0x9405, 0x0002, 0x9db0, 0x9db0, 0x9dab, 0x9dae, 0x9db0, + 0x9da8, 0x9d9b, 0x9d9b, 0x9d9b, 0x9d9b, 0x9d9b, 0x9d9b, 0x9d9b, + 0x9d9b, 0x9d9b, 0x9d9b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, + 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0d65, + 0x080c, 0xa854, 0x0028, 0x080c, 0xa977, 0x0010, 0x080c, 0xaa66, + 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, + 0x000e, 0x080c, 0x9f48, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, + 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, + 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, + 0x0000, 0x2041, 0x1298, 0x080c, 0xa0f3, 0x0160, 0x000e, 0x9005, + 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, + 0x0804, 0x9be6, 0x2001, 0x002c, 0x900e, 0x080c, 0x9fae, 0x0c70, + 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, + 0x0a0c, 0x0d65, 0x91b2, 0x0050, 0x1a0c, 0x0d65, 0x9182, 0x0047, + 0x0042, 0x080c, 0x9ab6, 0x0120, 0x9086, 0x0002, 0x0904, 0x9d49, + 0x0005, 0x9e0a, 0x9e0a, 0x9e0c, 0x9e3e, 0x9e0a, 0x9e0a, 0x9e0a, + 0x9e0a, 0x9e51, 0x080c, 0x0d65, 0x00d6, 0x0016, 0x0096, 0x6003, + 0x0004, 0x6114, 0x2148, 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, + 0x9005, 0x1158, 0xa894, 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, + 0x080c, 0x9fae, 0x080c, 0x9be6, 0x00a8, 0x6003, 0x0002, 0xa8a4, + 0xa9a8, 0x9105, 0x1178, 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, + 0xa88c, 0xa88a, 0xa8a4, 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, + 0xa8cb, 0x0000, 0x009e, 0x001e, 0x00de, 0x0005, 0x080c, 0x88ec, + 0x00d6, 0x0096, 0x6114, 0x2148, 0x080c, 0xb870, 0x0120, 0xa87b, + 0x0006, 0x080c, 0x69b5, 0x009e, 0x00de, 0x080c, 0x9be6, 0x0804, + 0x894f, 0x080c, 0x88ec, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x00d6, + 0x0096, 0x6114, 0x2148, 0x080c, 0xb870, 0x0120, 0xa87b, 0x0029, + 0x080c, 0x69b5, 0x009e, 0x00de, 0x080c, 0x9be6, 0x0804, 0x894f, + 0x9182, 0x0047, 0x0002, 0x9e78, 0x9e7a, 0x9e78, 0x9e78, 0x9e78, + 0x9e78, 0x9e78, 0x9e78, 0x9e78, 0x9e78, 0x9e78, 0x9e78, 0x9e7a, + 0x080c, 0x0d65, 0x00d6, 0x0096, 0x080c, 0x15af, 0x6114, 0x2148, + 0xa87b, 0x0000, 0xa883, 0x0000, 0x080c, 0x69b5, 0x009e, 0x00de, + 0x0804, 0x9be6, 0x0026, 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, + 0x00f6, 0x0006, 0x080c, 0x102f, 0x000e, 0x090c, 0x0d65, 0xa960, + 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, + 0x4104, 0xa87a, 0x2079, 0x1800, 0x798c, 0x9188, 0x0018, 0x918c, + 0x0fff, 0xa972, 0xac76, 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, + 0x0000, 0x901e, 0x2029, 0x0001, 0x9182, 0x0034, 0x1228, 0x2011, + 0x001f, 0x080c, 0xb426, 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, + 0x001f, 0x080c, 0xb426, 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, + 0x080c, 0x0fe1, 0x080c, 0x102f, 0x01d0, 0x8528, 0xa867, 0x0110, + 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, + 0x2011, 0x001b, 0x080c, 0xb426, 0x00b8, 0x96b2, 0x003c, 0x2009, + 0x003c, 0x2950, 0x2011, 0x001b, 0x080c, 0xb426, 0x0c18, 0x2001, + 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, + 0xb070, 0xc0fd, 0xb072, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, + 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, + 0x0000, 0x0006, 0x080c, 0x69b5, 0x000e, 0x2048, 0x9005, 0x1db0, + 0x00fe, 0x00ae, 0x009e, 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, + 0x00d6, 0x00f6, 0x0096, 0x0006, 0x080c, 0x102f, 0x000e, 0x090c, + 0x0d65, 0xa960, 0x21e8, 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, + 0x20a9, 0x0020, 0x4104, 0xaa66, 0xa87a, 0x2079, 0x1800, 0x798c, + 0x810c, 0x9188, 0x000c, 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, + 0x21a8, 0x810b, 0xa972, 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, + 0x20a0, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, + 0x2003, 0x0000, 0x080c, 0x69b5, 0x009e, 0x00fe, 0x00de, 0x0005, + 0x0016, 0x00d6, 0x00f6, 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, + 0x918d, 0x0080, 0x2102, 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, + 0xd0ec, 0x0118, 0x9e80, 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, + 0x9282, 0x0020, 0x0218, 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, + 0x1170, 0x0096, 0x080c, 0x102f, 0x2900, 0x009e, 0x05c0, 0xa806, + 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, + 0x908e, 0x0260, 0x0140, 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, + 0x2010, 0x2100, 0x9318, 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, + 0x2410, 0x9318, 0x9006, 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, + 0x20e1, 0x0000, 0x4003, 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, + 0x1130, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, + 0x84ff, 0x0904, 0x9f5d, 0x0804, 0x9f5f, 0x9085, 0x0001, 0x7817, + 0x0000, 0x009e, 0x00fe, 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, + 0x0096, 0x6314, 0x2348, 0xa87a, 0xa982, 0x080c, 0x69a9, 0x009e, + 0x003e, 0x00de, 0x0005, 0x91b6, 0x0015, 0x1118, 0x080c, 0x9be6, + 0x0030, 0x91b6, 0x0016, 0x190c, 0x0d65, 0x080c, 0x9be6, 0x0005, + 0x20a9, 0x000e, 0x20e1, 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, + 0xa860, 0x20e8, 0xa85c, 0x20a0, 0x009e, 0x4003, 0x0136, 0x9080, + 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, + 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, + 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, + 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xb870, 0x0130, + 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, + 0x9be6, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, + 0x6010, 0x00b6, 0x2058, 0xb8c7, 0x0000, 0x00be, 0x6014, 0x9005, + 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, + 0x9be6, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, + 0x0006, 0x0016, 0x080c, 0xbf8f, 0x0188, 0x6014, 0x9005, 0x1170, + 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, 0x2009, 0x0022, + 0x080c, 0xa3e7, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, + 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, + 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, + 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, - 0x0205, 0x2003, 0x0001, 0x2099, 0x0260, 0x20a9, 0x0016, 0x4003, - 0x20a9, 0x000a, 0xa804, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0002, 0x2099, - 0x0260, 0x20a9, 0x0020, 0x4003, 0x2003, 0x0000, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0x080c, 0x9bda, 0x001e, 0x009e, - 0x0005, 0x0096, 0x0016, 0x900e, 0x7030, 0x9086, 0x0100, 0x0140, - 0x7038, 0x9084, 0x00ff, 0x800c, 0x703c, 0x9084, 0x00ff, 0x8004, - 0x9080, 0x0004, 0x9108, 0x810b, 0x2011, 0x0002, 0x2019, 0x000c, - 0x6014, 0x2048, 0x080c, 0xb408, 0x080c, 0xb842, 0x0140, 0x6014, - 0x2048, 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, - 0x9bda, 0x001e, 0x009e, 0x0005, 0x0016, 0x0096, 0x7030, 0x9086, - 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, 0x800c, 0x810b, - 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, 0xa804, 0x0096, - 0x9005, 0x0108, 0x2048, 0x080c, 0xb408, 0x009e, 0x080c, 0xb842, - 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, 0xa864, 0xa8e2, - 0xa867, 0x0103, 0x080c, 0x9bda, 0x009e, 0x001e, 0x0005, 0x0086, - 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, 0x080c, 0xa581, - 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, - 0x0000, 0x2041, 0x1271, 0x0019, 0x0d08, 0x008e, 0x0898, 0x0096, - 0x0006, 0x080c, 0x1022, 0x000e, 0x01b0, 0xa8ab, 0x0dcb, 0xa876, - 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, 0xa97a, 0xaf72, - 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, 0x080c, 0x1117, - 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, 0x00d6, 0x0026, - 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, - 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, - 0x9206, 0x11e0, 0x604b, 0x0000, 0x2c68, 0x0016, 0x2009, 0x0035, - 0x080c, 0xbed9, 0x001e, 0x1158, 0x622c, 0x2268, 0x2071, 0x026c, - 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, 0x0128, 0x080c, - 0x9bda, 0x0020, 0x0039, 0x0010, 0x080c, 0xa203, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, 0x0015, 0x0904, - 0xa1e2, 0x918e, 0x0016, 0x1904, 0xa201, 0x700c, 0x908c, 0xff00, - 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, 0xa1bc, 0x89ff, - 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xa19e, 0x0804, 0xa1ff, - 0x6808, 0x9086, 0xffff, 0x1904, 0xa1e4, 0xa87c, 0x9084, 0x0060, - 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, 0x1904, 0xa1e4, - 0x6824, 0xd0b4, 0x1904, 0xa1e4, 0x080c, 0xba31, 0x6864, 0xa882, - 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, - 0x2001, 0x000a, 0x080c, 0x83fb, 0xa884, 0x920a, 0x0208, 0x8011, - 0xaa86, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xb55b, - 0x00ce, 0x0804, 0xa1ff, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, - 0x5d51, 0x0010, 0x080c, 0x60f6, 0x00ce, 0x1904, 0xa1e4, 0x00c6, - 0x2d60, 0x080c, 0x9bda, 0x00ce, 0x0804, 0xa1ff, 0x00c6, 0x080c, - 0x9c49, 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xbcdb, - 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9bda, 0x00ce, - 0x080c, 0x9c76, 0x00ce, 0x0804, 0xa1ff, 0x2001, 0x1958, 0x2004, - 0x684a, 0x00ce, 0x0804, 0xa1ff, 0x7008, 0x9086, 0x000b, 0x11c8, - 0x6010, 0x00b6, 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, - 0x2d60, 0xa87b, 0x0003, 0x080c, 0xbf1b, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x84b3, 0x00ce, - 0x0430, 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, 0x1958, 0x2004, - 0x684a, 0x00e8, 0x04c1, 0x00e8, 0x89ff, 0x090c, 0x0d65, 0x00c6, - 0x00d6, 0x2d60, 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x67a7, - 0x080c, 0xba31, 0x080c, 0x9c14, 0x0026, 0x6010, 0x00b6, 0x2058, - 0xba3c, 0x080c, 0x6396, 0x00be, 0x002e, 0x00de, 0x00ce, 0x080c, - 0x9bda, 0x009e, 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, 0x1958, - 0x2004, 0x684a, 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, - 0x2060, 0x080c, 0xd4df, 0x080c, 0x83a2, 0x080c, 0x9bda, 0x00ce, - 0x080c, 0x9bda, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, - 0xabac, 0xd2f4, 0x0130, 0x2001, 0x1958, 0x2004, 0x684a, 0x0804, - 0xa27d, 0x00c6, 0x2d60, 0x080c, 0xb433, 0x00ce, 0x6804, 0x9086, - 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, - 0x0050, 0x2009, 0x8023, 0x080c, 0x84b3, 0x00ce, 0x04f0, 0x6800, - 0x9086, 0x000f, 0x01a8, 0x89ff, 0x090c, 0x0d65, 0x6800, 0x9086, - 0x0004, 0x1190, 0xa87c, 0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, - 0x0fff, 0xa880, 0xc0fc, 0xa882, 0x2001, 0x0001, 0x6832, 0x0400, - 0x2001, 0x0007, 0x6832, 0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, - 0x0db8, 0x6824, 0xd0f4, 0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, - 0x0c20, 0xd2ec, 0x1d68, 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, - 0x0d38, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, - 0x080c, 0xbbc5, 0x080c, 0x891b, 0x0010, 0x080c, 0x9bda, 0x004e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, - 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, - 0xa2e8, 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, - 0x1904, 0xa2e8, 0x6038, 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, - 0x9286, 0x0007, 0x0904, 0xa2e8, 0x9286, 0x0002, 0x0904, 0xa2e8, - 0x9286, 0x0000, 0x05e8, 0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, - 0x026c, 0x9186, 0x0015, 0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, - 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, - 0x01a8, 0x9186, 0x004d, 0x0190, 0x9186, 0x004e, 0x0178, 0x9186, - 0x0052, 0x0160, 0x6014, 0x0096, 0x2048, 0x080c, 0xb842, 0x090c, - 0x0d65, 0xa87b, 0x0003, 0x009e, 0x080c, 0xbf1b, 0x6007, 0x0085, - 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x84b3, - 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, 0x1958, 0x2004, 0x704a, - 0x080c, 0x9bda, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, - 0x00f6, 0x6014, 0x2048, 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, - 0xba08, 0xbb0c, 0xbc00, 0xc48c, 0xbc02, 0x0460, 0x0096, 0x0156, - 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, - 0x0004, 0x080c, 0xabd3, 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, - 0xa357, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, - 0x2019, 0x0006, 0x20a9, 0x0004, 0x080c, 0xabd3, 0x002e, 0x003e, - 0x015e, 0x009e, 0x15a0, 0x7238, 0xba0a, 0x733c, 0xbb0e, 0xbc00, - 0xc48d, 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, - 0x0804, 0x9fe8, 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, - 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, - 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, - 0x0000, 0x2041, 0x1271, 0x080c, 0xa0e7, 0x0130, 0x00fe, 0x009e, - 0x080c, 0x9bda, 0x00be, 0x0005, 0x080c, 0xa581, 0x0cb8, 0x2b78, - 0x00f6, 0x080c, 0x300e, 0x080c, 0xbf76, 0x00fe, 0x00c6, 0x080c, - 0x9b84, 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, - 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x61bc, 0x080c, - 0x61e8, 0x080c, 0x84ba, 0x080c, 0x891b, 0x00ce, 0x0804, 0xa32a, - 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0d65, 0x91b2, 0x0040, 0x1a04, - 0xa3e0, 0x0002, 0xa3ce, 0xa3ce, 0xa3c4, 0xa3ce, 0xa3ce, 0xa3ce, - 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3ce, 0xa3c2, 0xa3ce, 0xa3ce, 0xa3c2, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3c2, 0xa3c4, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3ce, 0xa3ce, 0xa3c2, 0xa3c2, - 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3c2, 0xa3ce, - 0xa3c2, 0xa3c2, 0x080c, 0x0d65, 0x0066, 0x00b6, 0x6610, 0x2658, - 0xb8c4, 0xc08c, 0xb8c6, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, - 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, 0x84ba, 0x0010, 0x080c, - 0x84b3, 0x0126, 0x2091, 0x8000, 0x080c, 0x891b, 0x012e, 0x0005, - 0x2600, 0x0002, 0xa3f4, 0xa3f4, 0xa3f4, 0xa3ce, 0xa3ce, 0xa3f4, - 0xa3f4, 0xa3f4, 0xa3f4, 0xa3ce, 0xa3f4, 0xa3ce, 0xa3f4, 0xa3ce, - 0xa3f4, 0xa3f4, 0xa3f4, 0xa3f4, 0x080c, 0x0d65, 0x6004, 0x90b2, - 0x0053, 0x1a0c, 0x0d65, 0x91b6, 0x0013, 0x0904, 0xa4cb, 0x91b6, - 0x0027, 0x1904, 0xa477, 0x080c, 0x885d, 0x6004, 0x080c, 0xba46, - 0x01b0, 0x080c, 0xba57, 0x01a8, 0x908e, 0x0021, 0x0904, 0xa474, - 0x908e, 0x0022, 0x1130, 0x080c, 0xa014, 0x0904, 0xa470, 0x0804, - 0xa471, 0x908e, 0x003d, 0x0904, 0xa474, 0x0804, 0xa46a, 0x080c, - 0x303d, 0x2001, 0x0007, 0x080c, 0x61bc, 0x6010, 0x00b6, 0x2058, - 0xb9a0, 0x00be, 0x080c, 0xa581, 0x9186, 0x007e, 0x1148, 0x2001, - 0x1836, 0x2014, 0xc285, 0x080c, 0x7096, 0x1108, 0xc2ad, 0x2202, - 0x080c, 0x98bb, 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, - 0xd53a, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, - 0x0028, 0x080c, 0x8624, 0x0076, 0x903e, 0x080c, 0x8509, 0x6010, - 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, 0xcfd9, 0x007e, - 0x003e, 0x002e, 0x001e, 0x080c, 0x98d7, 0x080c, 0xbf76, 0x0016, - 0x080c, 0xbcd3, 0x080c, 0x9bda, 0x001e, 0x080c, 0x3116, 0x080c, - 0x891b, 0x0030, 0x080c, 0xbcd3, 0x080c, 0x9bda, 0x080c, 0x891b, - 0x0005, 0x080c, 0xa581, 0x0cb0, 0x080c, 0xa5bd, 0x0c98, 0x9186, - 0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, 0x9aaa, 0x0d80, - 0x9086, 0x0002, 0x0904, 0xa5c8, 0x0c58, 0x9186, 0x0014, 0x1d40, - 0x080c, 0x885d, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xa014, - 0x09f8, 0x080c, 0x300e, 0x080c, 0xbf76, 0x080c, 0xba46, 0x1190, - 0x080c, 0x303d, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, - 0xa581, 0x9186, 0x007e, 0x1128, 0x2001, 0x1836, 0x200c, 0xc185, - 0x2102, 0x0800, 0x080c, 0xba57, 0x1120, 0x080c, 0xa581, 0x0804, - 0xa46a, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, - 0x1894, 0x2079, 0x0000, 0x080c, 0x33b0, 0x00fe, 0x00ee, 0x0804, - 0xa46a, 0x6004, 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, - 0xa581, 0x0804, 0xa46a, 0x90b2, 0x0040, 0x1a04, 0xa56a, 0x2008, - 0x0002, 0xa513, 0xa514, 0xa517, 0xa51a, 0xa51d, 0xa520, 0xa511, - 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, - 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, - 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, 0xa523, - 0xa52c, 0xa511, 0xa52d, 0xa52c, 0xa511, 0xa511, 0xa511, 0xa511, - 0xa511, 0xa52c, 0xa52c, 0xa511, 0xa511, 0xa511, 0xa511, 0xa511, - 0xa511, 0xa511, 0xa511, 0xa555, 0xa52c, 0xa511, 0xa528, 0xa511, - 0xa511, 0xa511, 0xa529, 0xa511, 0xa511, 0xa511, 0xa52c, 0xa550, - 0xa511, 0x080c, 0x0d65, 0x00c0, 0x2001, 0x000b, 0x00e8, 0x2001, - 0x0003, 0x00d0, 0x2001, 0x0005, 0x00b8, 0x2001, 0x0001, 0x00a0, - 0x2001, 0x0009, 0x0088, 0x6003, 0x0005, 0x080c, 0x891b, 0x0058, - 0x0018, 0x0010, 0x080c, 0x61bc, 0x04b8, 0x080c, 0xbf79, 0x6003, - 0x0004, 0x080c, 0x891b, 0x0005, 0x080c, 0x61bc, 0x6003, 0x0002, - 0x0036, 0x2019, 0x185e, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, - 0x1956, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x891b, 0x0c18, - 0x080c, 0xbcd3, 0x080c, 0x9bda, 0x08f0, 0x00e6, 0x00f6, 0x2071, - 0x1894, 0x2079, 0x0000, 0x080c, 0x33b0, 0x00fe, 0x00ee, 0x080c, - 0x885d, 0x080c, 0x9bda, 0x0878, 0x6003, 0x0002, 0x080c, 0xbf79, - 0x0804, 0x891b, 0x2600, 0x2008, 0x0002, 0xa57f, 0xa57f, 0xa57f, - 0xa564, 0xa564, 0xa57f, 0xa57f, 0xa57f, 0xa57f, 0xa564, 0xa57f, - 0xa564, 0xa57f, 0xa564, 0xa57f, 0xa57f, 0xa57f, 0xa57f, 0x080c, - 0x0d65, 0x00e6, 0x0096, 0x0026, 0x0016, 0x080c, 0xb842, 0x0568, - 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, - 0x0056, 0x1148, 0x080c, 0x5129, 0x0130, 0x2001, 0x0000, 0x900e, - 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, - 0x080c, 0xbe40, 0x0090, 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, - 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, - 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, - 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, - 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, - 0x1a0c, 0x0d65, 0x6604, 0x96b6, 0x004d, 0x1120, 0x080c, 0xbd5f, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x0043, 0x1120, 0x080c, 0xbda8, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x004b, 0x1120, 0x080c, 0xbdd4, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x0033, 0x1120, 0x080c, 0xbcf5, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x0028, 0x1120, 0x080c, 0xba95, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x0029, 0x1120, 0x080c, 0xbad6, - 0x0804, 0xa645, 0x6604, 0x96b6, 0x001f, 0x1118, 0x080c, 0x9fbc, - 0x04e0, 0x6604, 0x96b6, 0x0000, 0x1118, 0x080c, 0xa2ee, 0x04a8, - 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, 0x9ff5, 0x0470, 0x6604, - 0x96b6, 0x0035, 0x1118, 0x080c, 0xa105, 0x0438, 0x6604, 0x96b6, - 0x0039, 0x1118, 0x080c, 0xa283, 0x0400, 0x6604, 0x96b6, 0x003d, - 0x1118, 0x080c, 0xa02d, 0x00c8, 0x6604, 0x96b6, 0x0044, 0x1118, - 0x080c, 0xa069, 0x0090, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, - 0xa094, 0x0058, 0x91b6, 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, - 0x0016, 0x1128, 0x00be, 0x0804, 0xa905, 0x00be, 0x0005, 0x080c, - 0x9c93, 0x0cd8, 0xa662, 0xa665, 0xa662, 0xa6a9, 0xa662, 0xa839, - 0xa912, 0xa662, 0xa662, 0xa8df, 0xa662, 0xa8f3, 0x0096, 0x080c, - 0x15a2, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, - 0x0804, 0x9bda, 0xa001, 0xa001, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x708c, 0x9086, 0x0074, 0x1540, 0x080c, 0xcfaa, 0x11b0, 0x6010, - 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, - 0xc0c5, 0xb802, 0x00e9, 0x00be, 0x2001, 0x0006, 0x080c, 0x61bc, - 0x080c, 0x303d, 0x080c, 0x9bda, 0x0088, 0x2001, 0x000a, 0x080c, - 0x61bc, 0x080c, 0x303d, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x84ba, 0x080c, 0x891b, 0x0010, 0x080c, 0xa824, 0x00ee, 0x0005, - 0x00d6, 0xb800, 0xd084, 0x0158, 0x9006, 0x080c, 0x61a8, 0x2069, - 0x1853, 0x6804, 0x0020, 0x2001, 0x0006, 0x080c, 0x61e8, 0x00de, - 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1823, 0x2204, 0x9086, - 0x0074, 0x1904, 0xa7fb, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x007e, - 0x1120, 0x080c, 0xaa56, 0x0804, 0xa760, 0x00d6, 0x080c, 0x7096, - 0x0198, 0x0026, 0x2011, 0x0010, 0x080c, 0x668a, 0x002e, 0x05c8, - 0x080c, 0x539c, 0x1540, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x00f8, 0x0026, 0x2011, 0x8008, 0x080c, - 0x668a, 0x002e, 0x0530, 0x6014, 0x2048, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, - 0x080c, 0xbe40, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, - 0x303d, 0x080c, 0x9bda, 0x001e, 0x080c, 0x3116, 0x00de, 0x0804, - 0xa7fe, 0x00de, 0x080c, 0xaa4b, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xbe40, 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, 0x61bc, 0x080c, 0x303d, - 0x080c, 0x9bda, 0x0804, 0xa7fe, 0x080c, 0xa80c, 0x6014, 0x9005, - 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, - 0x080c, 0xbe40, 0x08f8, 0x080c, 0xa802, 0x0160, 0x9006, 0x080c, - 0x61a8, 0x2001, 0x0004, 0x080c, 0x61e8, 0x2001, 0x0007, 0x080c, - 0x61bc, 0x08a0, 0x2001, 0x0004, 0x080c, 0x61bc, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x84ba, 0x080c, 0x891b, 0x0804, 0xa7fe, - 0xb85c, 0xd0e4, 0x01d0, 0x080c, 0xbc6d, 0x080c, 0x7096, 0x0118, - 0xd0dc, 0x1904, 0xa722, 0x2011, 0x1836, 0x2204, 0xc0ad, 0x2012, - 0x2001, 0x0002, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, - 0x24b1, 0x78e2, 0x00fe, 0x0804, 0xa722, 0x080c, 0xbcae, 0x2011, - 0x1836, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xd10f, 0x000e, - 0x1904, 0xa722, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x61bc, - 0x9006, 0x080c, 0x61a8, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, - 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, - 0x9084, 0x00ff, 0x78e6, 0x707a, 0x7010, 0x78ea, 0x707e, 0x908c, - 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x2486, - 0x00f6, 0x2100, 0x900e, 0x080c, 0x243d, 0x795a, 0x00fe, 0x9186, - 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, 0x2009, 0x00ef, 0x00f6, - 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x780c, 0xc0b5, 0x780e, - 0x00fe, 0x080c, 0x2486, 0x00f6, 0x2079, 0x1800, 0x797e, 0x2100, - 0x900e, 0x080c, 0x243d, 0x795a, 0x00fe, 0x8108, 0x080c, 0x620b, - 0x2b00, 0x00ce, 0x1904, 0xa722, 0x6012, 0x2009, 0x180f, 0x210c, - 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, - 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, 0x0002, 0x080c, 0x61bc, - 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x84ba, - 0x080c, 0x891b, 0x0018, 0x080c, 0xa581, 0x0431, 0x00de, 0x009e, - 0x00be, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, - 0x1854, 0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xd593, 0x0190, - 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, - 0xff00, 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, - 0xb912, 0xba16, 0x00ee, 0x0005, 0x2030, 0x2001, 0x0007, 0x080c, - 0x61bc, 0x080c, 0x539c, 0x1120, 0x2001, 0x0007, 0x080c, 0x61e8, - 0x080c, 0x303d, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, - 0x9bda, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x708c, - 0x9086, 0x0014, 0x1904, 0xa8d6, 0x00d6, 0x080c, 0x7096, 0x0198, - 0x0026, 0x2011, 0x0010, 0x080c, 0x668a, 0x002e, 0x05c8, 0x080c, - 0x539c, 0x1540, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0xdead, 0x00f8, 0x0026, 0x2011, 0x8008, 0x080c, 0x668a, - 0x002e, 0x0530, 0x6014, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, - 0xbe40, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, - 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x303d, - 0x080c, 0x9bda, 0x001e, 0x080c, 0x3116, 0x00de, 0x0804, 0xa8da, - 0x00de, 0x080c, 0x539c, 0x1170, 0x6014, 0x9005, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4a77, - 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, 0x6306, 0x080c, - 0xa698, 0x00de, 0x080c, 0xab1c, 0x1588, 0x6010, 0x2058, 0xb890, - 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x61bc, 0x0096, 0x6014, - 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xbe40, 0x0060, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, 0xa807, 0x0000, - 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, 0x303d, 0x6020, - 0x9086, 0x000a, 0x0138, 0x080c, 0x9bda, 0x0020, 0x080c, 0xa581, - 0x080c, 0xa824, 0x001e, 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, - 0x1823, 0x2204, 0x9086, 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, - 0x61bc, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x84ba, 0x0804, - 0x891b, 0x0804, 0xa824, 0x2030, 0x2011, 0x1823, 0x2204, 0x9086, - 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, - 0x61bc, 0x0804, 0x9bda, 0x0804, 0xa824, 0x0002, 0xa662, 0xa91d, - 0xa662, 0xa95c, 0xa662, 0xaa07, 0xa912, 0xa662, 0xa662, 0xaa1a, - 0xa662, 0xaa2a, 0x6604, 0x9686, 0x0003, 0x0904, 0xa839, 0x96b6, - 0x001e, 0x1110, 0x080c, 0x9bda, 0x0005, 0x00b6, 0x00d6, 0x00c6, - 0x080c, 0xaa3a, 0x11a0, 0x9006, 0x080c, 0x61a8, 0x080c, 0x300e, - 0x080c, 0xbf76, 0x2001, 0x0002, 0x080c, 0x61bc, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x84ba, 0x080c, 0x891b, 0x0408, 0x2009, - 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, - 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, 0xb842, 0x601b, 0x000a, - 0x0078, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x1900, - 0x1108, 0x08a0, 0x080c, 0x300e, 0x080c, 0xbf76, 0x080c, 0xa824, - 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, - 0x080c, 0xaa48, 0x00d6, 0x2069, 0x194c, 0x2d04, 0x9005, 0x0168, - 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x2069, 0x181f, - 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, - 0x080c, 0x61a8, 0x2001, 0x0002, 0x080c, 0x61bc, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x84ba, 0x080c, 0x891b, 0x0804, 0xa9d7, - 0x080c, 0xb842, 0x01b0, 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, - 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, 0x0002, 0x080c, 0xbe9a, - 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, - 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, - 0xa581, 0x2009, 0x026e, 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, - 0x0510, 0x9686, 0x000b, 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x1118, 0x9686, 0x0009, 0x01b0, 0x9086, 0x1900, 0x1168, - 0x9686, 0x0009, 0x0180, 0x2001, 0x0004, 0x080c, 0x61bc, 0x2001, - 0x0028, 0x601a, 0x6007, 0x0052, 0x0010, 0x080c, 0xa824, 0x002e, - 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, - 0x080c, 0xb842, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, - 0xd0fc, 0x0108, 0x0c50, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, - 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, - 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, - 0x080c, 0x5c6a, 0x00ee, 0x0010, 0x080c, 0x300e, 0x0870, 0x080c, - 0xaa48, 0x1160, 0x2001, 0x0004, 0x080c, 0x61bc, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x84ba, 0x0804, 0x891b, 0x080c, 0xa581, - 0x0804, 0xa824, 0x0469, 0x1160, 0x2001, 0x0008, 0x080c, 0x61bc, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x84ba, 0x0804, 0x891b, - 0x0804, 0xa824, 0x00e9, 0x1160, 0x2001, 0x000a, 0x080c, 0x61bc, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x84ba, 0x0804, 0x891b, - 0x0804, 0xa824, 0x2009, 0x026e, 0x2104, 0x9086, 0x0003, 0x1138, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, 0x2a00, 0x0005, - 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, 0x6110, 0x2158, - 0x080c, 0x627a, 0x001e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x00f6, - 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, 0x2009, 0x1836, - 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xaaee, 0x0560, 0x2009, - 0x1836, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6662, 0x0158, 0x9006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xd284, 0x2001, 0x180c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, 0x2fd3, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x2de9, 0x00ee, 0x00c6, 0x0156, - 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x3116, 0x8108, 0x1f04, - 0xaa8c, 0x015e, 0x00ce, 0x080c, 0xaa4b, 0x2071, 0x0260, 0x2079, - 0x0200, 0x7817, 0x0001, 0x2001, 0x1836, 0x200c, 0xc1c5, 0x7018, - 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, 0x1108, 0xc1c4, - 0x7817, 0x0000, 0x2001, 0x1836, 0x2102, 0x2079, 0x0100, 0x2e04, - 0x9084, 0x00ff, 0x2069, 0x181e, 0x206a, 0x78e6, 0x0006, 0x8e70, - 0x2e04, 0x2069, 0x181f, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, - 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182b, 0x200a, 0x2200, - 0x9084, 0x00ff, 0x2008, 0x080c, 0x2486, 0x080c, 0x7096, 0x0170, - 0x2071, 0x0260, 0x2069, 0x1952, 0x7048, 0x206a, 0x704c, 0x6806, - 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xbc6d, 0x0040, 0x2001, - 0x0006, 0x080c, 0x61bc, 0x080c, 0x303d, 0x080c, 0x9bda, 0x001e, - 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, - 0x0036, 0x00e6, 0x0156, 0x2019, 0x182b, 0x231c, 0x83ff, 0x01f0, - 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, - 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, - 0x2019, 0x000a, 0x080c, 0xabd3, 0x1148, 0x2011, 0x027a, 0x20a9, - 0x0004, 0x2019, 0x0006, 0x080c, 0xabd3, 0x1100, 0x015e, 0x00ee, - 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, - 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, - 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19c3, 0x252c, - 0x2021, 0x19ca, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7250, - 0x7070, 0x9202, 0x1a04, 0xabab, 0x080c, 0xd2b5, 0x0904, 0xaba4, - 0x6720, 0x9786, 0x0007, 0x0904, 0xaba4, 0x2500, 0x9c06, 0x0904, - 0xaba4, 0x2400, 0x9c06, 0x0904, 0xaba4, 0x3e08, 0x9186, 0x0002, - 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, - 0x1110, 0x080c, 0x1921, 0x9786, 0x000a, 0x0148, 0x080c, 0xba57, - 0x1130, 0x00ce, 0x080c, 0xa581, 0x080c, 0x9c14, 0x00e8, 0x6014, - 0x2048, 0x080c, 0xb842, 0x01a8, 0x9786, 0x0003, 0x1530, 0xa867, - 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, - 0x0fd4, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6985, 0x080c, - 0xba31, 0x080c, 0x9c14, 0x00ce, 0x9ce0, 0x001c, 0x7064, 0x9c02, - 0x1210, 0x0804, 0xab4f, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, - 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1118, - 0x080c, 0xd22f, 0x0c30, 0x9786, 0x000a, 0x0998, 0x0880, 0x220c, - 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xabbf, 0x9006, - 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, - 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, - 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, - 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, - 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, - 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, - 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, 0x6004, 0x908a, 0x0053, - 0x1a0c, 0x0d65, 0x080c, 0xba46, 0x0120, 0x080c, 0xba57, 0x0158, - 0x0028, 0x080c, 0x303d, 0x080c, 0xba57, 0x0128, 0x080c, 0x885d, - 0x080c, 0x9bda, 0x0005, 0x080c, 0xa581, 0x0cc0, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xac35, 0xac35, - 0xac35, 0xac35, 0xac35, 0xac35, 0xac35, 0xac35, 0xac35, 0xac35, - 0xac35, 0xac37, 0xac37, 0xac37, 0xac37, 0xac35, 0xac35, 0xac35, - 0xac37, 0xac35, 0xac35, 0xac35, 0xac35, 0x080c, 0x0d65, 0x600b, - 0xffff, 0x6003, 0x000f, 0x6106, 0x0126, 0x2091, 0x8000, 0x080c, - 0xbf79, 0x2009, 0x8000, 0x080c, 0x84b3, 0x012e, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xacbc, 0x9186, - 0x0027, 0x1520, 0x080c, 0x885d, 0x080c, 0x300e, 0x080c, 0xbf76, - 0x0096, 0x6114, 0x2148, 0x080c, 0xb842, 0x0198, 0x080c, 0xba57, - 0x1118, 0x080c, 0xa581, 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, - 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6991, 0x080c, - 0xba31, 0x009e, 0x080c, 0x9bda, 0x0804, 0x891b, 0x9186, 0x0014, - 0x1120, 0x6004, 0x9082, 0x0040, 0x0018, 0x080c, 0x0d65, 0x0005, - 0x0002, 0xac9a, 0xac98, 0xac98, 0xac98, 0xac98, 0xac98, 0xac98, - 0xac98, 0xac98, 0xac98, 0xac98, 0xacb3, 0xacb3, 0xacb3, 0xacb3, - 0xac98, 0xacb3, 0xac98, 0xacb3, 0xac98, 0xac98, 0xac98, 0xac98, - 0x080c, 0x0d65, 0x080c, 0x885d, 0x0096, 0x6114, 0x2148, 0x080c, - 0xb842, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6991, 0x080c, 0xba31, 0x009e, - 0x080c, 0x9bda, 0x0005, 0x080c, 0x885d, 0x080c, 0xba57, 0x090c, - 0xa581, 0x080c, 0x9bda, 0x0005, 0x0002, 0xacd6, 0xacd4, 0xacd4, - 0xacd4, 0xacd4, 0xacd4, 0xacd4, 0xacd4, 0xacd4, 0xacd4, 0xacd4, - 0xacd8, 0xacd8, 0xacd8, 0xacd8, 0xacd4, 0xacda, 0xacd4, 0xacd8, - 0xacd4, 0xacd4, 0xacd4, 0xacd4, 0x080c, 0x0d65, 0x080c, 0x0d65, - 0x080c, 0x0d65, 0x080c, 0x9bda, 0x0804, 0x891b, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xacfd, 0xacfd, - 0xacfd, 0xacfd, 0xacfd, 0xad36, 0xae25, 0xacfd, 0xae31, 0xacfd, - 0xacfd, 0xacfd, 0xacfd, 0xacfd, 0xacfd, 0xacfd, 0xacfd, 0xacfd, - 0xacfd, 0xae31, 0xacff, 0xacfd, 0xae2f, 0x080c, 0x0d65, 0x00b6, - 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1508, - 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xaeb6, 0x080c, 0x67a7, - 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0xb8c0, - 0x9005, 0x0110, 0x080c, 0x6396, 0x080c, 0x9bda, 0x009e, 0x00be, - 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, 0x9105, 0x09c0, - 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xbb8c, 0x0c80, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, - 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, 0xb800, 0xd0bc, - 0x1904, 0xae14, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xaeb6, 0x080c, - 0x67a7, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0xb8c0, 0x9005, 0x0110, 0x080c, 0x6396, 0x601c, 0xd0fc, 0x1148, - 0x7044, 0xd0e4, 0x1904, 0xadf8, 0x080c, 0x9bda, 0x009e, 0x00be, - 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d65, 0x968c, 0x0c00, - 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xadfc, 0x7348, - 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, - 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, - 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, - 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, - 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, - 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, - 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, - 0x0804, 0xad42, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, - 0x0025, 0x080c, 0xb408, 0x003e, 0xd6cc, 0x0904, 0xad57, 0x7154, - 0xa98a, 0x81ff, 0x0904, 0xad57, 0x9192, 0x0021, 0x1278, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb408, 0x2011, 0x0205, - 0x2013, 0x0000, 0x080c, 0xbf06, 0x0804, 0xad57, 0xa868, 0xd0fc, - 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, - 0xb3a7, 0x00ae, 0x080c, 0xbf06, 0x080c, 0xb3f8, 0x0804, 0xad59, - 0x080c, 0xbb4f, 0x0804, 0xad6e, 0xa87c, 0xd0ac, 0x0904, 0xad7f, - 0xa880, 0xd0bc, 0x1904, 0xad7f, 0x7348, 0xa838, 0x9306, 0x11c8, - 0x734c, 0xa834, 0x931e, 0x0904, 0xad7f, 0xd6d4, 0x0190, 0xab38, - 0x9305, 0x0904, 0xad7f, 0x0068, 0xa87c, 0xd0ac, 0x0904, 0xad4a, - 0xa838, 0xa934, 0x9105, 0x0904, 0xad4a, 0xa880, 0xd0bc, 0x1904, - 0xad4a, 0x080c, 0xbb8c, 0x0804, 0xad6e, 0x00f6, 0x2079, 0x026c, - 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe, 0x0021, 0x0005, 0x0011, - 0x0005, 0x0005, 0x0096, 0x6003, 0x0002, 0x6007, 0x0043, 0x6014, - 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e, 0x0005, 0x2130, 0x2228, - 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, - 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46, 0xab4a, 0xae36, 0xad3a, - 0x6044, 0xd0fc, 0x190c, 0x98e4, 0x604b, 0x0000, 0x080c, 0x1adf, - 0x1118, 0x6144, 0x080c, 0x84df, 0x009e, 0x0005, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xae7d, 0xae7d, - 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae7d, - 0xae7f, 0xae7d, 0xae7d, 0xae7d, 0xae7d, 0xae90, 0xae7d, 0xae7d, - 0xae7d, 0xae7d, 0xaeb4, 0xae7d, 0xae7d, 0x080c, 0x0d65, 0x6004, - 0x9086, 0x0040, 0x1110, 0x080c, 0x885d, 0x2019, 0x0001, 0x080c, - 0x9269, 0x6003, 0x0002, 0x080c, 0xbf7e, 0x080c, 0x88b8, 0x0005, - 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x885d, 0x2019, 0x0001, - 0x080c, 0x9269, 0x080c, 0x88b8, 0x080c, 0x300e, 0x080c, 0xbf76, - 0x0096, 0x6114, 0x2148, 0x080c, 0xb842, 0x0150, 0xa867, 0x0103, - 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, 0x6991, 0x080c, 0xba31, - 0x009e, 0x080c, 0x9bda, 0x0005, 0x080c, 0x0d65, 0xa87b, 0x0015, - 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, - 0x0000, 0x0006, 0x0016, 0x2009, 0x1a47, 0x2104, 0x8000, 0x200a, - 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, 0x9182, 0x0057, 0x1220, - 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xaeec, 0xaeec, 0xaeec, - 0xaeec, 0xaeec, 0xaeee, 0xaeec, 0xaeec, 0xafab, 0xaeec, 0xaeec, - 0xaeec, 0xaeec, 0xaeec, 0xaeec, 0xaeec, 0xaeec, 0xaeec, 0xaeec, - 0xb0e9, 0xaeec, 0xb0f3, 0xaeec, 0x080c, 0x0d65, 0x601c, 0xd0bc, - 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120, 0xc084, 0x601e, 0x0804, - 0xacde, 0x6114, 0x0096, 0x2148, 0xa87c, 0xc0e5, 0xa87e, 0x009e, - 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, - 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, 0xb676, 0x96b4, - 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, 0x00b6, 0x2258, 0xba3c, - 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x86ff, 0x0904, 0xafa4, - 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, 0x7048, 0xb092, 0x704c, - 0xb08e, 0x9284, 0x0300, 0x0904, 0xafa4, 0x9686, 0x0100, 0x1130, - 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, 0x0c38, 0x080c, 0x1022, - 0x090c, 0x0d65, 0x2900, 0xb07a, 0xb77c, 0x97bd, 0x0200, 0xb77e, - 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, 0xb070, 0xa872, - 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, 0x968c, 0x0c00, 0x0120, - 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, - 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, - 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, - 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, - 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, - 0x2011, 0x0025, 0x080c, 0xb408, 0x003e, 0xd6cc, 0x01e8, 0x7154, - 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, - 0x0018, 0x2011, 0x0029, 0x080c, 0xb408, 0x2011, 0x0205, 0x2013, - 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, - 0x0c68, 0x2950, 0x080c, 0xb3a7, 0x080c, 0x18ff, 0x009e, 0x00ee, - 0x00ae, 0x007e, 0x0005, 0x2001, 0x1958, 0x2004, 0x604a, 0x0096, - 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x1118, 0xa87c, 0xc0dc, - 0xa87e, 0x6003, 0x0002, 0x080c, 0xbf87, 0x0904, 0xb0e4, 0x604b, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1500, - 0xd1cc, 0x0904, 0xb0a9, 0xa978, 0xa868, 0xd0fc, 0x0904, 0xb06a, - 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0x00a6, 0x2150, 0xb174, - 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, 0xb038, 0x9086, 0x0028, - 0x1904, 0xb024, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x0804, 0xb040, - 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, 0x9205, 0x09c8, 0xa838, - 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, 0x9206, 0x0988, 0x6024, - 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, 0x603a, 0xa9b0, 0xa838, - 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x6010, 0x00b6, 0x2058, - 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c, 0xc0fc, 0x601e, 0x9006, - 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, - 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fd4, 0x009e, - 0x080c, 0xbb8c, 0x0804, 0xb0e4, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xbe29, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xaeb6, - 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, - 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, - 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xa87e, 0x080c, - 0xbf06, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fd4, 0x001e, - 0x0804, 0xb0d6, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, - 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, 0x001c, - 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, 0xb07b, - 0x0015, 0x080c, 0xbe29, 0x0118, 0xb174, 0xc1dc, 0xb176, 0x0078, - 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xaeb6, 0xa890, - 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, 0x0fd4, - 0x009e, 0x080c, 0xbf06, 0xa974, 0x0016, 0x080c, 0xb3f8, 0x001e, - 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, - 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, 0xd1dc, - 0x0148, 0xa87b, 0x0015, 0x080c, 0xbe29, 0x0118, 0xa974, 0xc1dc, - 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, 0xa87b, + 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, + 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, + 0x080c, 0x9be6, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, + 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, + 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, + 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xb426, + 0x080c, 0xb870, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, + 0xa8e2, 0xa867, 0x0103, 0x080c, 0x9be6, 0x001e, 0x009e, 0x0005, + 0x0016, 0x0096, 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, + 0x0010, 0x7034, 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, + 0x6014, 0x2048, 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, + 0xb426, 0x009e, 0x080c, 0xb870, 0x0148, 0xa804, 0x9005, 0x1158, + 0xa807, 0x0000, 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0x9be6, + 0x009e, 0x001e, 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, + 0x0100, 0x1118, 0x080c, 0xa59c, 0x00e0, 0xa034, 0x8007, 0x800c, + 0x8806, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, + 0x000c, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, + 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x127e, 0x0019, + 0x0d08, 0x008e, 0x0898, 0x0096, 0x0006, 0x080c, 0x102f, 0x000e, + 0x01b0, 0xa8ab, 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, + 0x2800, 0xa89e, 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, + 0x0086, 0x2940, 0x080c, 0x1124, 0x008e, 0x9085, 0x0001, 0x009e, + 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, + 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, + 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, 0x0000, + 0x2c68, 0x0016, 0x2009, 0x0035, 0x080c, 0xbf07, 0x001e, 0x1158, + 0x622c, 0x2268, 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, + 0x9386, 0x0006, 0x0128, 0x080c, 0x9be6, 0x0020, 0x0039, 0x0010, + 0x080c, 0xa21c, 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, + 0x2048, 0x9186, 0x0015, 0x0904, 0xa1fb, 0x918e, 0x0016, 0x1904, + 0xa21a, 0x700c, 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, + 0x0300, 0x1904, 0xa1d5, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, + 0x0904, 0xa1b7, 0x0804, 0xa218, 0x6808, 0x9086, 0xffff, 0x1904, + 0xa1fd, 0xa87c, 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, + 0xa940, 0x9105, 0x1904, 0xa1fd, 0x6824, 0xd084, 0x1904, 0xa1fd, + 0xd0b4, 0x0158, 0x0016, 0x2001, 0x195e, 0x200c, 0x6018, 0x9102, + 0x9082, 0x0005, 0x001e, 0x1a04, 0xa1fd, 0x080c, 0xba5f, 0x6864, + 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, + 0x6a18, 0x2001, 0x000a, 0x080c, 0x842f, 0xa884, 0x920a, 0x0208, + 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, + 0xb579, 0x00ce, 0x0804, 0xa218, 0x00c6, 0xa868, 0xd0fc, 0x1118, + 0x080c, 0x5d71, 0x0010, 0x080c, 0x611a, 0x00ce, 0x1904, 0xa1fd, + 0x00c6, 0x2d60, 0x080c, 0x9be6, 0x00ce, 0x0804, 0xa218, 0x00c6, + 0x080c, 0x9c55, 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, + 0xbd09, 0x6023, 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0x9be6, + 0x00ce, 0x080c, 0x9c82, 0x00ce, 0x0804, 0xa218, 0x2001, 0x1960, + 0x2004, 0x684a, 0x00ce, 0x0804, 0xa218, 0x7008, 0x9086, 0x000b, + 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, + 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, 0xbf49, 0x6007, 0x0085, + 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x84e7, + 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00, 0x1138, 0x2001, 0x1960, + 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8, 0x89ff, 0x090c, 0x0d65, + 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, + 0x67cb, 0x080c, 0xba5f, 0x080c, 0x9c20, 0x0026, 0x6010, 0x00b6, + 0x2058, 0xba3c, 0x080c, 0x63ba, 0x00be, 0x002e, 0x00de, 0x00ce, + 0x080c, 0x9be6, 0x009e, 0x0005, 0x9186, 0x0015, 0x1128, 0x2001, + 0x1960, 0x2004, 0x684a, 0x0068, 0x918e, 0x0016, 0x1160, 0x00c6, + 0x2d00, 0x2060, 0x080c, 0xd517, 0x080c, 0x83d6, 0x080c, 0x9be6, + 0x00ce, 0x080c, 0x9be6, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, + 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, 0x1960, 0x2004, 0x684a, + 0x0804, 0xa296, 0x00c6, 0x2d60, 0x080c, 0xb451, 0x00ce, 0x6804, + 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, + 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x84e7, 0x00ce, 0x04f0, + 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, 0x090c, 0x0d65, 0x6800, + 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, 0x0178, 0xa843, 0x0fff, + 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, 0x2001, 0x0001, 0x6832, + 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, 0xa87c, 0xd0b4, 0x1150, + 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, 0xa838, 0xa934, 0x9105, + 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, 0x9306, 0x1118, 0x7020, + 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, 0x683a, 0x2001, 0x0005, + 0x6832, 0x080c, 0xbbf3, 0x080c, 0x894f, 0x0010, 0x080c, 0x9be6, + 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x7008, + 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, 0xba10, 0x00be, 0x9206, + 0x1904, 0xa301, 0x700c, 0x6210, 0x00b6, 0x2258, 0xba14, 0x00be, + 0x9206, 0x1904, 0xa301, 0x6038, 0x2068, 0x6824, 0xc0dc, 0x6826, + 0x6a20, 0x9286, 0x0007, 0x0904, 0xa301, 0x9286, 0x0002, 0x0904, + 0xa301, 0x9286, 0x0000, 0x05e8, 0x6808, 0x633c, 0x9306, 0x15c8, + 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, 0x918e, 0x0016, 0x1100, + 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, 0x004b, 0x01c0, 0x9186, + 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, 0x9186, 0x004e, 0x0178, + 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, 0x2048, 0x080c, 0xb870, + 0x090c, 0x0d65, 0xa87b, 0x0003, 0x009e, 0x080c, 0xbf49, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, + 0x84e7, 0x00ce, 0x0030, 0x6038, 0x2070, 0x2001, 0x1960, 0x2004, + 0x704a, 0x080c, 0x9be6, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00b6, + 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, 0x2058, 0x91b6, 0x0015, + 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, 0xbc02, 0x0460, 0x0096, + 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0010, 0x2019, 0x000a, + 0x20a9, 0x0004, 0x080c, 0xabee, 0x002e, 0x003e, 0x015e, 0x009e, + 0x1904, 0xa370, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, + 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, 0x080c, 0xabee, 0x002e, + 0x003e, 0x015e, 0x009e, 0x15a0, 0x7238, 0xba0a, 0x733c, 0xbb0e, + 0xbc00, 0xc48d, 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, + 0x00be, 0x0804, 0x9ff4, 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, + 0x009e, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, + 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, + 0x2031, 0x0000, 0x2041, 0x127e, 0x080c, 0xa0f3, 0x0130, 0x00fe, + 0x009e, 0x080c, 0x9be6, 0x00be, 0x0005, 0x080c, 0xa59c, 0x0cb8, + 0x2b78, 0x00f6, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x00fe, 0x00c6, + 0x080c, 0x9b90, 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, + 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x61e0, + 0x080c, 0x620c, 0x080c, 0x84ee, 0x080c, 0x894f, 0x00ce, 0x0804, + 0xa343, 0x2100, 0x91b2, 0x0053, 0x1a0c, 0x0d65, 0x91b2, 0x0040, + 0x1a04, 0xa3f9, 0x0002, 0xa3e7, 0xa3e7, 0xa3dd, 0xa3e7, 0xa3e7, + 0xa3e7, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3e7, 0xa3db, 0xa3e7, 0xa3e7, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3db, 0xa3dd, 0xa3db, 0xa3db, 0xa3db, 0xa3db, + 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3e7, 0xa3e7, 0xa3db, + 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, 0xa3db, + 0xa3e7, 0xa3db, 0xa3db, 0x080c, 0x0d65, 0x0066, 0x00b6, 0x6610, + 0x2658, 0xb8c4, 0xc08c, 0xb8c6, 0x00be, 0x006e, 0x0000, 0x6003, + 0x0001, 0x6106, 0x9186, 0x0032, 0x0118, 0x080c, 0x84ee, 0x0010, + 0x080c, 0x84e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x894f, 0x012e, + 0x0005, 0x2600, 0x0002, 0xa40d, 0xa40d, 0xa40d, 0xa3e7, 0xa3e7, + 0xa40d, 0xa40d, 0xa40d, 0xa40d, 0xa3e7, 0xa40d, 0xa3e7, 0xa40d, + 0xa3e7, 0xa40d, 0xa40d, 0xa40d, 0xa40d, 0x080c, 0x0d65, 0x6004, + 0x90b2, 0x0053, 0x1a0c, 0x0d65, 0x91b6, 0x0013, 0x0904, 0xa4e4, + 0x91b6, 0x0027, 0x1904, 0xa490, 0x080c, 0x8891, 0x6004, 0x080c, + 0xba74, 0x01b0, 0x080c, 0xba85, 0x01a8, 0x908e, 0x0021, 0x0904, + 0xa48d, 0x908e, 0x0022, 0x1130, 0x080c, 0xa020, 0x0904, 0xa489, + 0x0804, 0xa48a, 0x908e, 0x003d, 0x0904, 0xa48d, 0x0804, 0xa483, + 0x080c, 0x305d, 0x2001, 0x0007, 0x080c, 0x61e0, 0x6010, 0x00b6, + 0x2058, 0xb9a0, 0x00be, 0x080c, 0xa59c, 0x9186, 0x007e, 0x1148, + 0x2001, 0x1836, 0x2014, 0xc285, 0x080c, 0x70ba, 0x1108, 0xc2ad, + 0x2202, 0x080c, 0x98c7, 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, + 0x080c, 0xd572, 0x002e, 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, + 0x2019, 0x0028, 0x080c, 0x8658, 0x0076, 0x903e, 0x080c, 0x853d, + 0x6010, 0x00b6, 0x905d, 0x0100, 0x00be, 0x2c08, 0x080c, 0xd011, + 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x98e3, 0x080c, 0xbfa4, + 0x0016, 0x080c, 0xbd01, 0x080c, 0x9be6, 0x001e, 0x080c, 0x3136, + 0x080c, 0x894f, 0x0030, 0x080c, 0xbd01, 0x080c, 0x9be6, 0x080c, + 0x894f, 0x0005, 0x080c, 0xa59c, 0x0cb0, 0x080c, 0xa5d8, 0x0c98, + 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, 0x9ab6, + 0x0d80, 0x9086, 0x0002, 0x0904, 0xa5e3, 0x0c58, 0x9186, 0x0014, + 0x1d40, 0x080c, 0x8891, 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, + 0xa020, 0x09f8, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x080c, 0xba74, + 0x1190, 0x080c, 0x305d, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, + 0x080c, 0xa59c, 0x9186, 0x007e, 0x1128, 0x2001, 0x1836, 0x200c, + 0xc185, 0x2102, 0x0800, 0x080c, 0xba85, 0x1120, 0x080c, 0xa59c, + 0x0804, 0xa483, 0x6004, 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, + 0x2071, 0x189c, 0x2079, 0x0000, 0x080c, 0x33d0, 0x00fe, 0x00ee, + 0x0804, 0xa483, 0x6004, 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, + 0x090c, 0xa59c, 0x0804, 0xa483, 0x90b2, 0x0040, 0x1a04, 0xa585, + 0x2008, 0x0002, 0xa52c, 0xa52d, 0xa530, 0xa533, 0xa536, 0xa539, + 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, + 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, + 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa52a, + 0xa53c, 0xa547, 0xa52a, 0xa548, 0xa547, 0xa52a, 0xa52a, 0xa52a, + 0xa52a, 0xa52a, 0xa547, 0xa547, 0xa52a, 0xa52a, 0xa52a, 0xa52a, + 0xa52a, 0xa52a, 0xa52a, 0xa52a, 0xa570, 0xa547, 0xa52a, 0xa543, + 0xa52a, 0xa52a, 0xa52a, 0xa544, 0xa52a, 0xa52a, 0xa52a, 0xa547, + 0xa56b, 0xa52a, 0x080c, 0x0d65, 0x00d0, 0x2001, 0x000b, 0x00f8, + 0x2001, 0x0003, 0x00e0, 0x2001, 0x0005, 0x00c8, 0x2001, 0x0001, + 0x00b0, 0x2001, 0x0009, 0x0098, 0x6003, 0x0005, 0x080c, 0xbfa7, + 0x080c, 0x894f, 0x0058, 0x0018, 0x0010, 0x080c, 0x61e0, 0x04b8, + 0x080c, 0xbfa7, 0x6003, 0x0004, 0x080c, 0x894f, 0x0005, 0x080c, + 0x61e0, 0x6003, 0x0002, 0x0036, 0x2019, 0x1866, 0x2304, 0x9084, + 0xff00, 0x1120, 0x2001, 0x195e, 0x201c, 0x0040, 0x8007, 0x909a, + 0x0004, 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, + 0x080c, 0x894f, 0x0c18, 0x080c, 0xbd01, 0x080c, 0x9be6, 0x08f0, + 0x00e6, 0x00f6, 0x2071, 0x189c, 0x2079, 0x0000, 0x080c, 0x33d0, + 0x00fe, 0x00ee, 0x080c, 0x8891, 0x080c, 0x9be6, 0x0878, 0x6003, + 0x0002, 0x080c, 0xbfa7, 0x0804, 0x894f, 0x2600, 0x2008, 0x0002, + 0xa59a, 0xa59a, 0xa59a, 0xa57f, 0xa57f, 0xa59a, 0xa59a, 0xa59a, + 0xa59a, 0xa57f, 0xa59a, 0xa57f, 0xa59a, 0xa57f, 0xa59a, 0xa59a, + 0xa59a, 0xa59a, 0x080c, 0x0d65, 0x00e6, 0x0096, 0x0026, 0x0016, + 0x080c, 0xb870, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, + 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x5149, 0x0130, + 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, + 0x900e, 0x2011, 0x4005, 0x080c, 0xbe6e, 0x0090, 0xa868, 0xd0fc, + 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, + 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, + 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, + 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, + 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, + 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0d65, 0x6604, 0x96b6, 0x004d, + 0x1120, 0x080c, 0xbd8d, 0x0804, 0xa660, 0x6604, 0x96b6, 0x0043, + 0x1120, 0x080c, 0xbdd6, 0x0804, 0xa660, 0x6604, 0x96b6, 0x004b, + 0x1120, 0x080c, 0xbe02, 0x0804, 0xa660, 0x6604, 0x96b6, 0x0033, + 0x1120, 0x080c, 0xbd23, 0x0804, 0xa660, 0x6604, 0x96b6, 0x0028, + 0x1120, 0x080c, 0xbac3, 0x0804, 0xa660, 0x6604, 0x96b6, 0x0029, + 0x1120, 0x080c, 0xbb04, 0x0804, 0xa660, 0x6604, 0x96b6, 0x001f, + 0x1118, 0x080c, 0x9fc8, 0x04e0, 0x6604, 0x96b6, 0x0000, 0x1118, + 0x080c, 0xa307, 0x04a8, 0x6604, 0x96b6, 0x0022, 0x1118, 0x080c, + 0xa001, 0x0470, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, 0xa111, + 0x0438, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xa29c, 0x0400, + 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xa039, 0x00c8, 0x6604, + 0x96b6, 0x0044, 0x1118, 0x080c, 0xa075, 0x0090, 0x6604, 0x96b6, + 0x0049, 0x1118, 0x080c, 0xa0a0, 0x0058, 0x91b6, 0x0015, 0x1110, + 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xa920, + 0x00be, 0x0005, 0x080c, 0x9c9f, 0x0cd8, 0xa67d, 0xa680, 0xa67d, + 0xa6c4, 0xa67d, 0xa854, 0xa92d, 0xa67d, 0xa67d, 0xa8fa, 0xa67d, + 0xa90e, 0x0096, 0x080c, 0x15af, 0x6014, 0x2048, 0xa800, 0x2048, + 0xa867, 0x0103, 0x009e, 0x0804, 0x9be6, 0xa001, 0xa001, 0x0005, + 0x00e6, 0x2071, 0x1800, 0x708c, 0x9086, 0x0074, 0x1540, 0x080c, + 0xcfe2, 0x11b0, 0x6010, 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, + 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, 0x00e9, 0x00be, 0x2001, + 0x0006, 0x080c, 0x61e0, 0x080c, 0x305d, 0x080c, 0x9be6, 0x0088, + 0x2001, 0x000a, 0x080c, 0x61e0, 0x080c, 0x305d, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, 0x0010, 0x080c, + 0xa83f, 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0158, 0x9006, + 0x080c, 0x61cc, 0x2069, 0x185b, 0x6804, 0x0020, 0x2001, 0x0006, + 0x080c, 0x620c, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, + 0x1823, 0x2204, 0x9086, 0x0074, 0x1904, 0xa816, 0x6010, 0x2058, + 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xaa71, 0x0804, 0xa77b, + 0x00d6, 0x080c, 0x70ba, 0x0198, 0x0026, 0x2011, 0x0010, 0x080c, + 0x66ae, 0x002e, 0x05c8, 0x080c, 0x53bc, 0x1540, 0x6014, 0x2048, + 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x00f8, 0x0026, + 0x2011, 0x8008, 0x080c, 0x66ae, 0x002e, 0x0530, 0x6014, 0x2048, + 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, + 0x900e, 0x2011, 0x4009, 0x080c, 0xbe6e, 0x0040, 0x6014, 0x2048, + 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, + 0xb9a0, 0x0016, 0x080c, 0x305d, 0x080c, 0x9be6, 0x001e, 0x080c, + 0x3136, 0x00de, 0x0804, 0xa819, 0x00de, 0x080c, 0xaa66, 0x6010, + 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, + 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, + 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xbe6e, 0x0030, 0xa807, + 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, + 0x61e0, 0x080c, 0x305d, 0x080c, 0x9be6, 0x0804, 0xa819, 0x080c, + 0xa827, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, + 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, + 0x900e, 0x2011, 0x4000, 0x080c, 0xbe6e, 0x08f8, 0x080c, 0xa81d, + 0x0160, 0x9006, 0x080c, 0x61cc, 0x2001, 0x0004, 0x080c, 0x620c, + 0x2001, 0x0007, 0x080c, 0x61e0, 0x08a0, 0x2001, 0x0004, 0x080c, + 0x61e0, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x84ee, 0x080c, + 0x894f, 0x0804, 0xa819, 0xb85c, 0xd0e4, 0x01d0, 0x080c, 0xbc9b, + 0x080c, 0x70ba, 0x0118, 0xd0dc, 0x1904, 0xa73d, 0x2011, 0x1836, + 0x2204, 0xc0ad, 0x2012, 0x2001, 0x0002, 0x00f6, 0x2079, 0x0100, + 0x78e3, 0x0000, 0x080c, 0x24cd, 0x78e2, 0x00fe, 0x0804, 0xa73d, + 0x080c, 0xbcdc, 0x2011, 0x1836, 0x2204, 0xc0a5, 0x2012, 0x0006, + 0x080c, 0xd147, 0x000e, 0x1904, 0xa73d, 0xc0b5, 0x2012, 0x2001, + 0x0006, 0x080c, 0x61e0, 0x9006, 0x080c, 0x61cc, 0x00c6, 0x2001, + 0x180f, 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, + 0x2071, 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707a, 0x7010, + 0x78ea, 0x707e, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, + 0x00fe, 0x080c, 0x24a2, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2459, + 0x795a, 0x00fe, 0x9186, 0x0081, 0x01d8, 0x2009, 0x0081, 0x00c8, + 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, + 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x24a2, 0x00f6, 0x2079, + 0x1800, 0x797e, 0x2100, 0x900e, 0x080c, 0x2459, 0x795a, 0x00fe, + 0x8108, 0x080c, 0x622f, 0x2b00, 0x00ce, 0x1904, 0xa73d, 0x6012, + 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, + 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, + 0x0002, 0x080c, 0x61e0, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x84ee, 0x080c, 0x894f, 0x0018, 0x080c, 0xa59c, + 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, 0x1810, 0x2004, + 0xd0a4, 0x0120, 0x2001, 0x185c, 0x2004, 0xd0ac, 0x0005, 0x00e6, + 0x080c, 0xd5cb, 0x0190, 0x2071, 0x0260, 0x7108, 0x720c, 0x918c, + 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, 0x2058, 0xb8a0, + 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, 0x0005, 0x2030, + 0x2001, 0x0007, 0x080c, 0x61e0, 0x080c, 0x53bc, 0x1120, 0x2001, + 0x0007, 0x080c, 0x620c, 0x080c, 0x305d, 0x6020, 0x9086, 0x000a, + 0x1108, 0x0005, 0x0804, 0x9be6, 0x00b6, 0x00e6, 0x0026, 0x0016, + 0x2071, 0x1800, 0x708c, 0x9086, 0x0014, 0x1904, 0xa8f1, 0x00d6, + 0x080c, 0x70ba, 0x0198, 0x0026, 0x2011, 0x0010, 0x080c, 0x66ae, + 0x002e, 0x05c8, 0x080c, 0x53bc, 0x1540, 0x6014, 0x2048, 0xa807, + 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x00f8, 0x0026, 0x2011, + 0x8008, 0x080c, 0x66ae, 0x002e, 0x0530, 0x6014, 0x2048, 0xa864, + 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, + 0x2011, 0x4009, 0x080c, 0xbe6e, 0x0040, 0x6014, 0x2048, 0xa807, + 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, + 0x0016, 0x080c, 0x305d, 0x080c, 0x9be6, 0x001e, 0x080c, 0x3136, + 0x00de, 0x0804, 0xa8f5, 0x00de, 0x080c, 0x53bc, 0x1170, 0x6014, + 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, + 0x0006, 0x080c, 0x4a97, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, + 0x080c, 0x632a, 0x080c, 0xa6b3, 0x00de, 0x080c, 0xab37, 0x1588, + 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, + 0x61e0, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, + 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, + 0x080c, 0xbe6e, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, + 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, + 0x080c, 0x305d, 0x6020, 0x9086, 0x000a, 0x0138, 0x080c, 0x9be6, + 0x0020, 0x080c, 0xa59c, 0x080c, 0xa83f, 0x001e, 0x002e, 0x00ee, + 0x00be, 0x0005, 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, 0x1160, + 0x2001, 0x0002, 0x080c, 0x61e0, 0x6003, 0x0001, 0x6007, 0x0001, + 0x080c, 0x84ee, 0x0804, 0x894f, 0x0804, 0xa83f, 0x2030, 0x2011, + 0x1823, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, 0x000b, 0x1120, + 0x2001, 0x0007, 0x080c, 0x61e0, 0x0804, 0x9be6, 0x0804, 0xa83f, + 0x0002, 0xa67d, 0xa938, 0xa67d, 0xa977, 0xa67d, 0xaa22, 0xa92d, + 0xa67d, 0xa67d, 0xaa35, 0xa67d, 0xaa45, 0x6604, 0x9686, 0x0003, + 0x0904, 0xa854, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9be6, 0x0005, + 0x00b6, 0x00d6, 0x00c6, 0x080c, 0xaa55, 0x11a0, 0x9006, 0x080c, + 0x61cc, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x2001, 0x0002, 0x080c, + 0x61e0, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x84ee, 0x080c, + 0x894f, 0x0408, 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, + 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0170, 0x8001, + 0xb842, 0x601b, 0x000a, 0x0078, 0x2009, 0x026f, 0x2104, 0x9084, + 0xff00, 0x9086, 0x1900, 0x1108, 0x08a0, 0x080c, 0x302e, 0x080c, + 0xbfa4, 0x080c, 0xa83f, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, + 0x00b6, 0x0026, 0x9016, 0x080c, 0xaa63, 0x00d6, 0x2069, 0x1954, + 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, + 0x1138, 0x2069, 0x181f, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, + 0x00de, 0x0088, 0x9006, 0x080c, 0x61cc, 0x2001, 0x0002, 0x080c, + 0x61e0, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x84ee, 0x080c, + 0x894f, 0x0804, 0xa9f2, 0x080c, 0xb870, 0x01b0, 0x6014, 0x2048, + 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, + 0x0002, 0x080c, 0xbec8, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, + 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, + 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, + 0x9006, 0x0c38, 0x080c, 0xa59c, 0x2009, 0x026e, 0x2134, 0x96b4, + 0x00ff, 0x9686, 0x0005, 0x0510, 0x9686, 0x000b, 0x01c8, 0x2009, + 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01b0, + 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0180, 0x2001, 0x0004, + 0x080c, 0x61e0, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0010, + 0x080c, 0xa83f, 0x002e, 0x00be, 0x009e, 0x0005, 0x9286, 0x0139, + 0x0160, 0x6014, 0x2048, 0x080c, 0xb870, 0x0140, 0xa864, 0x9086, + 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c50, 0x6010, 0x2058, + 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, 0xb842, 0x601b, + 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, 0x007e, 0x1138, + 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c8a, 0x00ee, 0x0010, 0x080c, + 0x302e, 0x0870, 0x080c, 0xaa63, 0x1160, 0x2001, 0x0004, 0x080c, + 0x61e0, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x84ee, 0x0804, + 0x894f, 0x080c, 0xa59c, 0x0804, 0xa83f, 0x0469, 0x1160, 0x2001, + 0x0008, 0x080c, 0x61e0, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, + 0x84ee, 0x0804, 0x894f, 0x0804, 0xa83f, 0x00e9, 0x1160, 0x2001, + 0x000a, 0x080c, 0x61e0, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, + 0x84ee, 0x0804, 0x894f, 0x0804, 0xa83f, 0x2009, 0x026e, 0x2104, + 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, + 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, + 0x0016, 0x6110, 0x2158, 0x080c, 0x629e, 0x001e, 0x00ce, 0x00be, + 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, + 0x2058, 0x2009, 0x1836, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, + 0xab09, 0x0560, 0x2009, 0x1836, 0x2104, 0xc0cd, 0x200a, 0x080c, + 0x6686, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xd2bc, + 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, + 0x0001, 0x080c, 0x2ff3, 0x00e6, 0x2071, 0x1800, 0x080c, 0x2e09, + 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, + 0x3136, 0x8108, 0x1f04, 0xaaa7, 0x015e, 0x00ce, 0x080c, 0xaa66, + 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1836, + 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, + 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1836, 0x2102, + 0x2079, 0x0100, 0x2e04, 0x9084, 0x00ff, 0x2069, 0x181e, 0x206a, + 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0x181f, 0x206a, 0x78ea, + 0x7832, 0x7836, 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, + 0x182b, 0x200a, 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x24a2, + 0x080c, 0x70ba, 0x0170, 0x2071, 0x0260, 0x2069, 0x195a, 0x7048, + 0x206a, 0x704c, 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, + 0xbc9b, 0x0040, 0x2001, 0x0006, 0x080c, 0x61e0, 0x080c, 0x305d, + 0x080c, 0x9be6, 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, + 0x0005, 0x0096, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x182b, + 0x231c, 0x83ff, 0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, + 0x7004, 0x9084, 0xff00, 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, + 0x20a9, 0x0004, 0x2b48, 0x2019, 0x000a, 0x080c, 0xabee, 0x1148, + 0x2011, 0x027a, 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xabee, + 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, + 0x2071, 0x0260, 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, + 0x0800, 0x1188, 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, + 0x0100, 0x1138, 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, + 0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, + 0x2029, 0x19cb, 0x252c, 0x2021, 0x19d2, 0x2424, 0x2061, 0x1ddc, + 0x2071, 0x1800, 0x7250, 0x7070, 0x9202, 0x1a04, 0xabc6, 0x080c, + 0xd2ed, 0x0904, 0xabbf, 0x6720, 0x9786, 0x0007, 0x0904, 0xabbf, + 0x2500, 0x9c06, 0x0904, 0xabbf, 0x2400, 0x9c06, 0x0904, 0xabbf, + 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff, + 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x193e, 0x9786, 0x000a, + 0x0148, 0x080c, 0xba85, 0x1130, 0x00ce, 0x080c, 0xa59c, 0x080c, + 0x9c20, 0x00e8, 0x6014, 0x2048, 0x080c, 0xb870, 0x01a8, 0x9786, + 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, + 0xa878, 0x2048, 0x080c, 0x0fe1, 0x009e, 0xab7a, 0xa877, 0x0000, + 0x080c, 0x69a9, 0x080c, 0xba5f, 0x080c, 0x9c20, 0x00ce, 0x9ce0, + 0x001c, 0x7064, 0x9c02, 0x1210, 0x0804, 0xab6a, 0x012e, 0x000e, + 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, + 0x9786, 0x0006, 0x1118, 0x080c, 0xd267, 0x0c30, 0x9786, 0x000a, + 0x0998, 0x0880, 0x220c, 0x2304, 0x9106, 0x1130, 0x8210, 0x8318, + 0x1f04, 0xabda, 0x9006, 0x0005, 0x2304, 0x9102, 0x0218, 0x2001, + 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, 0x0005, 0x0136, 0x01c6, + 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, 0x003f, 0x21e0, 0x9084, + 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, 0x0001, 0x220c, 0x4002, + 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, 0x9006, 0x001e, 0x01ce, + 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, 0x2001, 0x0001, 0x0010, + 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, 0x01ce, 0x013e, 0x0005, + 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d65, 0x080c, 0xba74, 0x0120, + 0x080c, 0xba85, 0x0158, 0x0028, 0x080c, 0x305d, 0x080c, 0xba85, + 0x0128, 0x080c, 0x8891, 0x080c, 0x9be6, 0x0005, 0x080c, 0xa59c, + 0x0cc0, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xac50, 0xac50, 0xac50, 0xac50, 0xac50, 0xac50, 0xac50, + 0xac50, 0xac50, 0xac50, 0xac50, 0xac52, 0xac52, 0xac52, 0xac52, + 0xac50, 0xac50, 0xac50, 0xac52, 0xac50, 0xac50, 0xac50, 0xac50, + 0x080c, 0x0d65, 0x600b, 0xffff, 0x6003, 0x000f, 0x6106, 0x0126, + 0x2091, 0x8000, 0x080c, 0xbfa7, 0x2009, 0x8000, 0x080c, 0x84e7, + 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, + 0x0804, 0xacd7, 0x9186, 0x0027, 0x1520, 0x080c, 0x8891, 0x080c, + 0x302e, 0x080c, 0xbfa4, 0x0096, 0x6114, 0x2148, 0x080c, 0xb870, + 0x0198, 0x080c, 0xba85, 0x1118, 0x080c, 0xa59c, 0x0068, 0xa867, + 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, + 0x080c, 0x69b5, 0x080c, 0xba5f, 0x009e, 0x080c, 0x9be6, 0x0804, + 0x894f, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x0018, + 0x080c, 0x0d65, 0x0005, 0x0002, 0xacb5, 0xacb3, 0xacb3, 0xacb3, + 0xacb3, 0xacb3, 0xacb3, 0xacb3, 0xacb3, 0xacb3, 0xacb3, 0xacce, + 0xacce, 0xacce, 0xacce, 0xacb3, 0xacce, 0xacb3, 0xacce, 0xacb3, + 0xacb3, 0xacb3, 0xacb3, 0x080c, 0x0d65, 0x080c, 0x8891, 0x0096, + 0x6114, 0x2148, 0x080c, 0xb870, 0x0168, 0xa867, 0x0103, 0xa87b, + 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x69b5, + 0x080c, 0xba5f, 0x009e, 0x080c, 0x9be6, 0x0005, 0x080c, 0x8891, + 0x080c, 0xba85, 0x090c, 0xa59c, 0x080c, 0x9be6, 0x0005, 0x0002, + 0xacf1, 0xacef, 0xacef, 0xacef, 0xacef, 0xacef, 0xacef, 0xacef, + 0xacef, 0xacef, 0xacef, 0xacf3, 0xacf3, 0xacf3, 0xacf3, 0xacef, + 0xacf5, 0xacef, 0xacf3, 0xacef, 0xacef, 0xacef, 0xacef, 0x080c, + 0x0d65, 0x080c, 0x0d65, 0x080c, 0x0d65, 0x080c, 0x9be6, 0x0804, + 0x894f, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xad18, 0xad18, 0xad18, 0xad18, 0xad18, 0xad51, 0xae40, + 0xad18, 0xae4c, 0xad18, 0xad18, 0xad18, 0xad18, 0xad18, 0xad18, + 0xad18, 0xad18, 0xad18, 0xad18, 0xae4c, 0xad1a, 0xad18, 0xae4a, + 0x080c, 0x0d65, 0x00b6, 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, + 0xb800, 0xd0bc, 0x1508, 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, - 0xaeb6, 0xa974, 0x0016, 0x080c, 0x67a7, 0x001e, 0x6010, 0x00b6, - 0x2058, 0xb8c0, 0x0016, 0x9005, 0x190c, 0x6396, 0x001e, 0x00be, - 0xd1e4, 0x1120, 0x080c, 0x9bda, 0x009e, 0x0005, 0x080c, 0xbb4f, - 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, 0x080c, 0xbf87, 0x190c, - 0x190d, 0x009e, 0x0005, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, - 0x9105, 0x01e8, 0xa877, 0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, - 0x00b6, 0x6010, 0x2058, 0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, - 0x67a7, 0xba3c, 0x8211, 0x0208, 0xba3e, 0xb8c0, 0x9005, 0x0110, - 0x080c, 0x6396, 0x080c, 0x9bda, 0x00be, 0x009e, 0x0005, 0xa87c, - 0xc0dc, 0xa87e, 0x08f8, 0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, - 0xaeb6, 0x0c28, 0xa880, 0xd0bc, 0x1dc8, 0x080c, 0xbb8c, 0x0c60, - 0x080c, 0x885d, 0x0010, 0x080c, 0x88b8, 0x601c, 0xd084, 0x0110, - 0x080c, 0x1921, 0x080c, 0xb842, 0x01f0, 0x0096, 0x6114, 0x2148, - 0x080c, 0xba57, 0x1118, 0x080c, 0xa581, 0x00a0, 0xa867, 0x0103, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, - 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, 0xd52b, 0xa877, 0x0000, - 0x080c, 0x6991, 0x009e, 0x0804, 0x9c14, 0xa87b, 0x0004, 0x0cb0, - 0xa87b, 0x0004, 0x0c98, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, - 0xb17c, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, - 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb17a, 0xb1a0, - 0xb17a, 0xb17a, 0x080c, 0x0d65, 0x080c, 0x5390, 0x01f8, 0x6014, - 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, - 0x00ff, 0x0096, 0x904d, 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, - 0x0139, 0x0128, 0xa867, 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, - 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x6991, 0x009e, 0x0804, 0x9bda, - 0x080c, 0x5390, 0x0dd8, 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, - 0x0085, 0x0002, 0xb1b9, 0xb1b7, 0xb1b7, 0xb1c5, 0xb1b7, 0xb1b7, - 0xb1b7, 0xb1b7, 0xb1b7, 0xb1b7, 0xb1b7, 0xb1b7, 0xb1b7, 0x080c, - 0x0d65, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, - 0x8020, 0x080c, 0x84b3, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, - 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xb830, - 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, 0x0178, 0x6010, 0x6d10, - 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0xb433, 0x00ce, 0x0128, - 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, 0x9280, 0x0004, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, - 0x00c6, 0x2260, 0x080c, 0xbb8c, 0x00ce, 0x00ee, 0x00de, 0x005e, - 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, - 0x0a0c, 0x0d65, 0x908a, 0x0092, 0x1a0c, 0x0d65, 0x9082, 0x0085, - 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d65, - 0x080c, 0x885d, 0x0096, 0x6014, 0x2048, 0x080c, 0xb842, 0x0140, - 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6991, - 0x009e, 0x080c, 0x9c14, 0x0804, 0x891b, 0xb23a, 0xb23c, 0xb23c, - 0xb23a, 0xb23a, 0xb23a, 0xb23a, 0xb23a, 0xb23a, 0xb23a, 0xb23a, - 0xb23a, 0xb23a, 0x080c, 0x0d65, 0x080c, 0x9c14, 0x0005, 0x9186, - 0x0013, 0x1130, 0x6004, 0x9082, 0x0085, 0x2008, 0x0804, 0xb28b, - 0x9186, 0x0027, 0x1558, 0x080c, 0x885d, 0x080c, 0x300e, 0x080c, - 0xbf76, 0x0096, 0x6014, 0x2048, 0x080c, 0xb842, 0x0150, 0xa867, - 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6991, 0x080c, - 0xba31, 0x009e, 0x080c, 0x9bda, 0x0005, 0x9186, 0x0089, 0x0118, - 0x9186, 0x008a, 0x1140, 0x080c, 0x9aaa, 0x0128, 0x9086, 0x000c, - 0x0904, 0xb2c3, 0x0000, 0x080c, 0x9c93, 0x0c70, 0x9186, 0x0014, - 0x1d60, 0x080c, 0x885d, 0x0096, 0x6014, 0x2048, 0x080c, 0xb842, - 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, 0xa880, - 0xc0ec, 0xa882, 0x0890, 0x0002, 0xb29b, 0xb299, 0xb299, 0xb299, - 0xb299, 0xb299, 0xb2af, 0xb299, 0xb299, 0xb299, 0xb299, 0xb299, - 0xb299, 0x080c, 0x0d65, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1956, 0x0010, - 0x2001, 0x1957, 0x2004, 0x601a, 0x6003, 0x000c, 0x0005, 0x6034, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, - 0x1118, 0x2001, 0x1956, 0x0010, 0x2001, 0x1957, 0x2004, 0x601a, - 0x6003, 0x000e, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, - 0x0208, 0x0012, 0x0804, 0x9c93, 0xb2d9, 0xb2d9, 0xb2d9, 0xb2d9, - 0xb2db, 0xb328, 0xb2d9, 0xb2d9, 0xb2d9, 0xb2d9, 0xb2d9, 0xb2d9, - 0xb2d9, 0x080c, 0x0d65, 0x0096, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x009e, 0x0804, 0xb33c, - 0x080c, 0xb842, 0x1118, 0x080c, 0xba31, 0x0068, 0x6014, 0x2048, - 0x080c, 0xbf8d, 0x1110, 0x080c, 0xba31, 0xa867, 0x0103, 0x080c, - 0xbf41, 0x080c, 0x6991, 0x00d6, 0x2c68, 0x080c, 0x9b84, 0x01d0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, - 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, - 0x080c, 0xbcdb, 0x695c, 0x615e, 0x6023, 0x0001, 0x2009, 0x8020, - 0x080c, 0x84b3, 0x2d60, 0x00de, 0x080c, 0x9bda, 0x009e, 0x0005, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x05a0, 0x6034, - 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, - 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, 0x2c68, 0x080c, 0xbed9, - 0x11f0, 0x080c, 0x9b84, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, - 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, - 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x695c, - 0x615e, 0x080c, 0xbcdb, 0x2009, 0x8020, 0x080c, 0x84b3, 0x2d60, - 0x00de, 0x0804, 0x9bda, 0x0096, 0x6014, 0x2048, 0x080c, 0xb842, - 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, 0xa882, - 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, - 0xa87b, 0x0005, 0x080c, 0xbb4b, 0xa877, 0x0000, 0x080c, 0x6991, - 0x080c, 0xba31, 0x009e, 0x0804, 0x9bda, 0x0016, 0x0096, 0x6014, - 0x2048, 0x080c, 0xb842, 0x0140, 0xa867, 0x0103, 0xa87b, 0x0028, - 0xa877, 0x0000, 0x080c, 0x6991, 0x009e, 0x001e, 0x9186, 0x0013, - 0x0158, 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, - 0x9c93, 0x0020, 0x080c, 0x885d, 0x080c, 0x9c14, 0x0005, 0x0056, - 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, - 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, - 0x0020, 0x2011, 0x0029, 0x080c, 0xb408, 0x96b2, 0x0020, 0xb004, - 0x904d, 0x0110, 0x080c, 0x0fd4, 0x080c, 0x1022, 0x0520, 0x8528, - 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, - 0x1228, 0x2608, 0x2011, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, - 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, - 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, - 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, - 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, - 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, - 0x080c, 0x6991, 0x2a48, 0x0cb8, 0x080c, 0x6991, 0x00ae, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, - 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, - 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, - 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, - 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, - 0x0000, 0x00fe, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, - 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, - 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xb485, 0xb485, 0xb480, - 0xb4a9, 0xb45d, 0xb480, 0xb45f, 0xb480, 0xb45d, 0xb45d, 0xb480, - 0xb480, 0xb480, 0xb45d, 0xb45d, 0xb45d, 0x080c, 0x0d65, 0x6010, - 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, 0xb4a9, 0x0036, 0x6014, - 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019, 0x000c, - 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, 0x0010, 0x2019, 0x0010, - 0x080c, 0xce09, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, - 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, - 0x6014, 0x2048, 0x080c, 0xb842, 0x01d0, 0x6043, 0xffff, 0xa864, - 0x9086, 0x0139, 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, - 0x900e, 0x2001, 0x0005, 0x080c, 0x6ba2, 0x080c, 0xbb4b, 0x080c, - 0x6985, 0x080c, 0x9c14, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, - 0x0ce0, 0x080c, 0x98bb, 0x080c, 0xbf9b, 0x6000, 0x908a, 0x0016, - 0x1a0c, 0x0d65, 0x002b, 0x0106, 0x080c, 0x98d7, 0x010e, 0x0005, - 0xb4c8, 0xb4f6, 0xb4ca, 0xb51d, 0xb4f1, 0xb4c8, 0xb480, 0xb485, - 0xb485, 0xb480, 0xb480, 0xb480, 0xb480, 0xb480, 0xb480, 0xb480, - 0x080c, 0x0d65, 0x86ff, 0x1510, 0x6020, 0x9086, 0x0006, 0x01f0, - 0x0096, 0x6014, 0x2048, 0x080c, 0xb842, 0x0158, 0xa87c, 0xd0cc, - 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fd4, 0x009e, 0x080c, - 0xbb4b, 0x009e, 0x080c, 0xbf1b, 0x6007, 0x0085, 0x6003, 0x000b, - 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x8495, 0x9085, 0x0001, - 0x0005, 0x0066, 0x080c, 0x1921, 0x006e, 0x08a0, 0x00e6, 0x2071, - 0x19b7, 0x7030, 0x9c06, 0x1120, 0x080c, 0x91e9, 0x00ee, 0x0850, - 0x6020, 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, - 0x2049, 0x0001, 0x2c40, 0x080c, 0x9365, 0x009e, 0x008e, 0x0040, - 0x0066, 0x080c, 0x90e5, 0x190c, 0x0d65, 0x080c, 0x90f3, 0x006e, - 0x00ee, 0x1904, 0xb4ca, 0x0804, 0xb480, 0x0036, 0x00e6, 0x2071, - 0x19b7, 0x704c, 0x9c06, 0x1138, 0x901e, 0x080c, 0x9269, 0x00ee, - 0x003e, 0x0804, 0xb4ca, 0x080c, 0x949c, 0x00ee, 0x003e, 0x1904, - 0xb4ca, 0x0804, 0xb480, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, - 0x001b, 0x006e, 0x00ce, 0x0005, 0xb553, 0xb622, 0xb789, 0xb55b, - 0x9c14, 0xb553, 0xcdfb, 0xbf83, 0xb622, 0xb54c, 0xb808, 0xb54c, - 0xb54c, 0xb54c, 0xb54c, 0xb54c, 0x080c, 0x0d65, 0x080c, 0xba57, - 0x1110, 0x080c, 0xa581, 0x0005, 0x080c, 0x885d, 0x0804, 0x9bda, - 0x601b, 0x0001, 0x0005, 0x080c, 0xb842, 0x0130, 0x6014, 0x0096, - 0x2048, 0x2c00, 0xa896, 0x009e, 0x080c, 0x98bb, 0x080c, 0xbf9b, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x0804, 0x98d7, - 0xb580, 0xb582, 0xb5ac, 0xb5c0, 0xb5ed, 0xb580, 0xb553, 0xb553, - 0xb553, 0xb5c7, 0xb5c7, 0xb580, 0xb580, 0xb580, 0xb580, 0xb5d1, - 0x080c, 0x0d65, 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, - 0xa882, 0x009e, 0x2071, 0x19b7, 0x7030, 0x9c06, 0x01d0, 0x0066, - 0x080c, 0x90e5, 0x190c, 0x0d65, 0x080c, 0x90f3, 0x006e, 0x080c, - 0xbf1b, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, - 0x1957, 0x2004, 0x601a, 0x2009, 0x8020, 0x080c, 0x8495, 0x00ee, - 0x0005, 0x601b, 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, - 0xc0b5, 0xa882, 0x009e, 0x080c, 0xbf1b, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x2009, 0x8020, 0x080c, 0x8495, 0x0005, - 0x080c, 0x98bb, 0x080c, 0x9a2c, 0x080c, 0x98d7, 0x0c28, 0x0096, - 0x601b, 0x0001, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x0005, 0x080c, 0x5390, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, - 0xa864, 0xa867, 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, - 0xa867, 0x0139, 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, - 0x080c, 0x6991, 0x009e, 0x0804, 0x9bda, 0x6014, 0x0096, 0x904d, - 0x0560, 0xa97c, 0xd1e4, 0x1158, 0x611c, 0xd1fc, 0x0530, 0x6110, - 0x00b6, 0x2158, 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, - 0x98d7, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, - 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, - 0x0037, 0x2c08, 0x080c, 0x15ab, 0x6000, 0x9086, 0x0004, 0x1120, - 0x2009, 0x0048, 0x080c, 0x9c76, 0x0005, 0x009e, 0x080c, 0x1921, - 0x0804, 0xb5ac, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x000b, - 0x0005, 0xb639, 0xb558, 0xb63b, 0xb639, 0xb63b, 0xb63b, 0xb554, - 0xb639, 0xb54e, 0xb54e, 0xb639, 0xb639, 0xb639, 0xb639, 0xb639, - 0xb639, 0x080c, 0x0d65, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, - 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0d65, 0x00b6, 0x0013, - 0x00be, 0x0005, 0xb656, 0xb723, 0xb658, 0xb698, 0xb658, 0xb698, - 0xb658, 0xb666, 0xb656, 0xb698, 0xb656, 0xb687, 0x080c, 0x0d65, - 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, - 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xb71f, 0x6004, 0x080c, - 0xba57, 0x0904, 0xb73c, 0x908e, 0x0004, 0x1110, 0x080c, 0x303d, - 0x908e, 0x0021, 0x0904, 0xb740, 0x908e, 0x0022, 0x0904, 0xb784, - 0x908e, 0x003d, 0x0904, 0xb740, 0x908e, 0x0039, 0x0904, 0xb744, - 0x908e, 0x0035, 0x0904, 0xb744, 0x908e, 0x001e, 0x0178, 0x908e, - 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x0110, 0x080c, 0x300e, 0x080c, 0xa581, 0x0804, 0x9c14, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xb710, 0x9186, - 0x0002, 0x1904, 0xb6e5, 0x2001, 0x1836, 0x2004, 0xd08c, 0x11c8, - 0x080c, 0x7096, 0x11b0, 0x080c, 0xbf61, 0x0138, 0x080c, 0x70b9, - 0x1120, 0x080c, 0x6fa1, 0x0804, 0xb76d, 0x2001, 0x194d, 0x2003, - 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x6fc7, 0x0804, - 0xb76d, 0x6010, 0x2058, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x1904, - 0xb76d, 0xb8a0, 0x9084, 0xff80, 0x1904, 0xb76d, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0190, 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, - 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, 0x080c, 0x9b84, 0x0128, - 0x2b00, 0x6012, 0x6023, 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, - 0x908e, 0x0002, 0x11a0, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1170, 0x2009, 0x1836, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, - 0x1800, 0x080c, 0x5c6a, 0x00ee, 0x080c, 0xa581, 0x0030, 0x080c, - 0xa581, 0x080c, 0x300e, 0x080c, 0xbf76, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x303d, 0x012e, 0x00ee, 0x080c, 0x9c14, 0x0005, - 0x2001, 0x0002, 0x080c, 0x61bc, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x84ba, 0x080c, 0x891b, 0x00de, 0x00ce, 0x0c80, 0x080c, - 0x303d, 0x0804, 0xb694, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, - 0x0d38, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, - 0xb6e5, 0x8001, 0xb842, 0x6003, 0x0001, 0x080c, 0x84ba, 0x080c, - 0x891b, 0x00de, 0x00ce, 0x0898, 0x080c, 0xa581, 0x0804, 0xb696, - 0x080c, 0xa5bd, 0x0804, 0xb696, 0x00d6, 0x2c68, 0x6104, 0x080c, - 0xbed9, 0x00de, 0x0118, 0x080c, 0x9bda, 0x00f0, 0x6004, 0x8007, - 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x603c, 0x600a, 0x2001, 0x1957, 0x2004, - 0x601a, 0x602c, 0x2c08, 0x2060, 0x6024, 0xc0b5, 0x6026, 0x2160, - 0x2009, 0x8020, 0x080c, 0x84b3, 0x0005, 0x00de, 0x00ce, 0x080c, - 0xa581, 0x080c, 0x300e, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x303d, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, - 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xa014, 0x1904, 0xb73c, - 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x0096, 0x00d6, - 0x001b, 0x00de, 0x009e, 0x0005, 0xb7a4, 0xb7a4, 0xb7a4, 0xb7a4, - 0xb7a4, 0xb7a4, 0xb7a4, 0xb7a4, 0xb7a4, 0xb553, 0xb7a4, 0xb558, - 0xb7a6, 0xb558, 0xb7b3, 0xb7a4, 0x080c, 0x0d65, 0x6004, 0x9086, - 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, 0x2009, 0x8020, - 0x080c, 0x84b3, 0x0005, 0x080c, 0xbf55, 0x0118, 0x080c, 0xbf68, - 0x0010, 0x080c, 0xbf76, 0x080c, 0xba31, 0x080c, 0xb842, 0x0570, - 0x080c, 0x300e, 0x080c, 0xb842, 0x0168, 0x6014, 0x2048, 0xa867, - 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, - 0x080c, 0x6991, 0x2c68, 0x080c, 0x9b84, 0x0150, 0x6810, 0x6012, - 0x080c, 0xbcdb, 0x00c6, 0x2d60, 0x080c, 0x9c14, 0x00ce, 0x0008, - 0x2d60, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x080c, 0x84ba, 0x080c, 0x891b, 0x00c8, 0x080c, 0xbf55, - 0x0138, 0x6034, 0x9086, 0x4000, 0x1118, 0x080c, 0x300e, 0x08d0, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x080c, 0x300e, 0x0868, 0x080c, 0x9c14, 0x0005, - 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x0002, 0xb81e, 0xb81e, - 0xb820, 0xb820, 0xb820, 0xb81e, 0xb81e, 0x9c14, 0xb81e, 0xb81e, - 0xb81e, 0xb81e, 0xb81e, 0xb81e, 0xb81e, 0xb81e, 0x080c, 0x0d65, - 0x080c, 0x98bb, 0x080c, 0x9a2c, 0x080c, 0x98d7, 0x6114, 0x0096, - 0x2148, 0xa87b, 0x0006, 0x080c, 0x6991, 0x009e, 0x0804, 0x9bda, - 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001, 0x1819, - 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, - 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, - 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x10cd, 0x000e, - 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7350, 0x7070, 0x9302, - 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xbf61, 0x0180, 0x9286, - 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x300e, - 0x080c, 0xbf76, 0x00c6, 0x080c, 0x9c14, 0x00ce, 0x0060, 0x080c, - 0xbc4d, 0x0148, 0x080c, 0xba57, 0x1110, 0x080c, 0xa581, 0x00c6, - 0x080c, 0x9bda, 0x00ce, 0x9ce0, 0x001c, 0x7064, 0x9c02, 0x1208, - 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, - 0x1b01, 0x6112, 0x080c, 0x300e, 0x9006, 0x0010, 0x9085, 0x0001, - 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9b84, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, 0x5390, - 0x0118, 0x080c, 0xb973, 0x0168, 0x080c, 0xbcdb, 0x6023, 0x0003, - 0x2009, 0x004b, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, - 0x080c, 0x9c49, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, 0x080c, - 0xbcdb, 0x6023, 0x0003, 0x0016, 0x080c, 0x98bb, 0x080c, 0x8624, - 0x0076, 0x903e, 0x080c, 0x8509, 0x2c08, 0x080c, 0xcfd9, 0x007e, - 0x080c, 0x98d7, 0x001e, 0xd184, 0x0128, 0x080c, 0x9bda, 0x9085, - 0x0001, 0x0070, 0x080c, 0x5390, 0x0128, 0xd18c, 0x1170, 0x080c, - 0xb973, 0x0148, 0x2009, 0x004c, 0x080c, 0x9c76, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, - 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, - 0x0016, 0x080c, 0x9b84, 0x2c78, 0x0590, 0x7e5e, 0x2b00, 0x7812, - 0x7823, 0x0003, 0x2021, 0x0005, 0x080c, 0xb985, 0x9186, 0x004d, - 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, 0x1950, 0x200c, 0xd1fc, - 0x0168, 0x2f60, 0x080c, 0x9bda, 0x00d0, 0x2001, 0x194f, 0x200c, - 0xd1fc, 0x0120, 0x2f60, 0x080c, 0x9bda, 0x0088, 0x2f60, 0x080c, - 0x5390, 0x0138, 0xd18c, 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, - 0x7816, 0x001e, 0x0016, 0x080c, 0x9c76, 0x9085, 0x0001, 0x001e, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x080c, - 0x9b84, 0x2c78, 0x0508, 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, - 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, 0x2001, 0x194e, 0x200c, - 0xd1fc, 0x0120, 0x2f60, 0x080c, 0x9bda, 0x0060, 0x2f60, 0x080c, - 0x5390, 0x0120, 0xd18c, 0x1160, 0x0071, 0x0130, 0x2009, 0x0052, - 0x080c, 0x9c76, 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, 0x487a, 0x00ce, 0x1120, - 0x080c, 0x9bda, 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, - 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, 0x0096, 0x0076, 0x0126, - 0x2091, 0x8000, 0x080c, 0x98bb, 0x080c, 0x644d, 0x0158, 0x2001, - 0xb98c, 0x0006, 0x900e, 0x2400, 0x080c, 0x6ba2, 0x080c, 0x6991, - 0x000e, 0x0807, 0x2418, 0x080c, 0x8823, 0xbaa0, 0x0086, 0x2041, - 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x863e, 0x008e, 0x080c, - 0x8509, 0x2f08, 0x2648, 0x080c, 0xcfd9, 0xb93c, 0x81ff, 0x090c, - 0x8715, 0x080c, 0x98d7, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9b84, 0x0190, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, - 0x001f, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c49, - 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0008, - 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x165c, 0x00fe, 0x2009, - 0x0021, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, 0x0016, 0x2091, - 0x8000, 0x080c, 0x9b84, 0x0198, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xbcdb, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x0016, 0x080c, - 0x9c76, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c49, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x0000, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830, 0x2009, 0x0049, - 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0118, - 0x8211, 0xba3e, 0x1140, 0xb8c0, 0x9005, 0x0128, 0xb888, 0x9005, - 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e, 0x0005, 0x0006, 0x0016, - 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, - 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, 0x904d, - 0x080c, 0xb842, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, 0x6020, - 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, 0xd0fc, - 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, 0x000e, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c49, 0x0198, - 0x2b08, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0001, 0x2900, 0x6016, - 0x080c, 0x300e, 0x2009, 0x0028, 0x080c, 0x9c76, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, - 0x2011, 0x1823, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, - 0xa80c, 0x00be, 0x080c, 0xaa4b, 0x6003, 0x0001, 0x6007, 0x0029, - 0x080c, 0x84ba, 0x080c, 0x891b, 0x0078, 0x6014, 0x0096, 0x2048, - 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xbe9a, - 0x080c, 0xa581, 0x080c, 0x9bda, 0x0005, 0x0096, 0x6014, 0x904d, - 0x090c, 0x0d65, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, - 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6991, 0x012e, 0x009e, 0x080c, 0x9bda, 0x0c30, 0x0096, 0x9186, - 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x61bc, 0x00e8, 0x9186, - 0x0015, 0x1510, 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, 0x11e0, - 0x6010, 0x00b6, 0x2058, 0x080c, 0x6306, 0x00be, 0x080c, 0xab1c, - 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, 0x0160, - 0x2001, 0x0006, 0x080c, 0x61bc, 0x6014, 0x2048, 0xa868, 0xd0fc, - 0x0170, 0x080c, 0x9fe8, 0x0048, 0x6014, 0x2048, 0xa868, 0xd0fc, - 0x0528, 0x080c, 0xa581, 0x080c, 0x9bda, 0x009e, 0x0005, 0x6014, - 0x6310, 0x2358, 0x904d, 0x090c, 0x0d65, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x655e, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6991, 0x012e, 0x080c, 0x9bda, 0x08f8, 0x6014, 0x904d, - 0x090c, 0x0d65, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, - 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6991, 0x012e, 0x080c, 0x9bda, 0x0840, 0xa878, 0x9086, 0x0005, - 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x604b, - 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, - 0x8023, 0x080c, 0x84b3, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, 0x6020, 0x9084, 0x000f, - 0x001b, 0x006e, 0x00ce, 0x0005, 0xb553, 0xbb7e, 0xbb7e, 0xbb81, - 0xd2d3, 0xd2ee, 0xd2f1, 0xb553, 0xb553, 0xb553, 0xb553, 0xb553, - 0xb553, 0xb553, 0xb553, 0xb553, 0x080c, 0x0d65, 0xa001, 0xa001, - 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, - 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1833, 0x2004, 0x9005, 0x1540, - 0x00f6, 0x2c78, 0x080c, 0x9b84, 0x0508, 0x7810, 0x6012, 0x080c, - 0xbcdb, 0x7820, 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, - 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, - 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x795c, 0x615e, 0x2009, - 0x8020, 0x080c, 0x84b3, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, - 0x2001, 0x1958, 0x2004, 0x604a, 0x0005, 0x0016, 0x0096, 0x6814, - 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e, 0xa87c, 0x1108, 0xd0e4, - 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, 0xa88f, - 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, 0x080c, - 0x0fd4, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, 0x6803, 0x0002, - 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0, 0x681c, - 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085, 0x0c00, - 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0, 0x693c, - 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, 0x683a, - 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, 0x695c, - 0x615e, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x2009, - 0x8020, 0x080c, 0x84b3, 0x009e, 0x001e, 0x0005, 0x6024, 0xd0d4, - 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, 0x0230, - 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, 0x633e, - 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, 0xa836, - 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024, 0xc0d4, - 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a, 0xa840, - 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016, 0x6004, - 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e, 0x0036, - 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, 0x0158, 0x908e, - 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, 0x0110, - 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x0036, 0x00e6, 0x2001, 0x1952, 0x200c, 0x8000, 0x2014, 0x2001, - 0x0032, 0x080c, 0x83fb, 0x2001, 0x1956, 0x82ff, 0x1110, 0x2011, - 0x0014, 0x2202, 0x2001, 0x1954, 0x200c, 0x8000, 0x2014, 0x2071, - 0x193c, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x83fb, 0x2001, - 0x1957, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1958, - 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, 0x080c, 0x98ac, 0x2001, - 0x1a58, 0x2102, 0x2001, 0x0032, 0x080c, 0x15ab, 0x080c, 0x6647, - 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x00e6, 0x2001, 0x1956, 0x2003, 0x0028, 0x2001, 0x1957, 0x2003, - 0x0014, 0x2071, 0x193c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, - 0x1958, 0x2009, 0x001e, 0x2102, 0x2001, 0x0017, 0x080c, 0x98ac, - 0x2001, 0x1a58, 0x2102, 0x2001, 0x0032, 0x080c, 0x15ab, 0x00ee, - 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, 0x904d, 0x0110, 0x080c, - 0x1054, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9b84, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0x9c76, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x1500, 0x708c, 0x9086, 0x0018, - 0x11e0, 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, - 0x89da, 0x01d8, 0x7078, 0xaa50, 0x9206, 0x1160, 0x707c, 0xaa54, - 0x9206, 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, - 0x080c, 0x305d, 0x080c, 0x9fe8, 0x0020, 0x080c, 0xa581, 0x080c, - 0x9bda, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, 0xaa54, 0x9206, - 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9b84, - 0x0188, 0x2b08, 0x6112, 0x080c, 0xbcdb, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x004d, 0x080c, 0x9c76, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x0016, 0x080c, 0x9b84, 0x0180, 0x2b08, 0x6112, 0x080c, 0xbcdb, - 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0x9c76, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x1568, 0x718c, 0x6014, 0x2048, - 0xa814, 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x1970, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, - 0x8007, 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x20a0, 0x2001, 0x1970, 0x0016, 0x200c, 0x080c, 0xc553, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, - 0x0103, 0x0010, 0x080c, 0xa581, 0x080c, 0x9bda, 0x00fe, 0x00ee, - 0x009e, 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, - 0x708c, 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, - 0x89da, 0x01a8, 0x7078, 0xaa74, 0x9206, 0x1130, 0x707c, 0xaa78, - 0x9206, 0x1110, 0x080c, 0x300e, 0x080c, 0x9fe8, 0x0020, 0x080c, - 0xa581, 0x080c, 0x9bda, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, - 0xaa78, 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, - 0x1800, 0x9186, 0x0015, 0x1550, 0x708c, 0x9086, 0x0004, 0x1530, - 0x6014, 0x2048, 0x2c78, 0x080c, 0x89da, 0x05f0, 0x7078, 0xaacc, - 0x9206, 0x1180, 0x707c, 0xaad0, 0x9206, 0x1160, 0x080c, 0x300e, - 0x0016, 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5340, - 0x001e, 0x0010, 0x080c, 0x5129, 0x080c, 0xb842, 0x0508, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xb842, - 0x01b8, 0x6014, 0x2048, 0x080c, 0x5129, 0x1d70, 0xa87b, 0x0030, - 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, - 0x8000, 0xa867, 0x0139, 0x080c, 0x6991, 0x012e, 0x080c, 0x9bda, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, 0xaad0, 0x9206, 0x0930, - 0x0888, 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, - 0x2100, 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, - 0x0120, 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, - 0x00b6, 0x00d6, 0x0036, 0x080c, 0xb842, 0x0904, 0xbe96, 0x0096, - 0x6314, 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, - 0x00c6, 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, - 0x655e, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, - 0xa99a, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, - 0x20a0, 0xb8b4, 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, - 0x0f9f, 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8b8, - 0x9080, 0x000a, 0x2098, 0x080c, 0x0f9f, 0x00ce, 0x0090, 0xaa96, - 0x3918, 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, - 0xa89b, 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, - 0xa89e, 0x080c, 0x6985, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, - 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, - 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000, - 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x243d, 0x2118, - 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, - 0x2011, 0x8018, 0x080c, 0x48da, 0x00a8, 0x9096, 0x0001, 0x1148, - 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, - 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, - 0x0008, 0x6a2c, 0x080c, 0xb830, 0x01f0, 0x2260, 0x6120, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, - 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, - 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, - 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, - 0x0188, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1160, 0xa9a8, 0x918c, - 0x0f00, 0x810f, 0x918e, 0x0001, 0x1128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xaeb6, 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, - 0x901e, 0x0499, 0x01e0, 0x080c, 0xb842, 0x01c8, 0x080c, 0xba31, - 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, 0xa87c, - 0x080c, 0xba57, 0x1118, 0x080c, 0xa581, 0x0040, 0xa867, 0x0103, - 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6991, 0x009e, 0x003e, - 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, + 0xaed1, 0x080c, 0x67cb, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, + 0x8211, 0xba3e, 0xb8c0, 0x9005, 0x0110, 0x080c, 0x63ba, 0x080c, + 0x9be6, 0x009e, 0x00be, 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, + 0xa934, 0x9105, 0x09c0, 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xbbba, + 0x0c80, 0x00b6, 0x0096, 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, + 0x7644, 0x0008, 0x9036, 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, + 0x2058, 0xb800, 0xd0bc, 0x1904, 0xae2f, 0xa87b, 0x0000, 0xa867, + 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, + 0x190c, 0xaed1, 0x080c, 0x67cb, 0x6210, 0x2258, 0xba3c, 0x82ff, + 0x0110, 0x8211, 0xba3e, 0xb8c0, 0x9005, 0x0110, 0x080c, 0x63ba, + 0x601c, 0xd0fc, 0x1148, 0x7044, 0xd0e4, 0x1904, 0xae13, 0x080c, + 0x9be6, 0x009e, 0x00be, 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, + 0x0d65, 0x968c, 0x0c00, 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, + 0x1904, 0xae17, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, + 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, + 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, + 0xa938, 0xaa34, 0x2100, 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, + 0x704c, 0x9206, 0x0118, 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, + 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, + 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, + 0x9005, 0x1118, 0xc6c4, 0x0804, 0xad5d, 0x735c, 0xab86, 0x83ff, + 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, + 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xb426, 0x003e, 0xd6cc, + 0x0904, 0xad72, 0x7154, 0xa98a, 0x81ff, 0x0904, 0xad72, 0x9192, + 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, + 0xb426, 0x2011, 0x0205, 0x2013, 0x0000, 0x080c, 0xbf34, 0x0804, + 0xad72, 0xa868, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, + 0x00a6, 0x2950, 0x080c, 0xb3c5, 0x00ae, 0x080c, 0xbf34, 0x080c, + 0xb416, 0x0804, 0xad74, 0x080c, 0xbb7d, 0x0804, 0xad89, 0xa87c, + 0xd0ac, 0x0904, 0xad9a, 0xa880, 0xd0bc, 0x1904, 0xad9a, 0x7348, + 0xa838, 0x9306, 0x11c8, 0x734c, 0xa834, 0x931e, 0x0904, 0xad9a, + 0xd6d4, 0x0190, 0xab38, 0x9305, 0x0904, 0xad9a, 0x0068, 0xa87c, + 0xd0ac, 0x0904, 0xad65, 0xa838, 0xa934, 0x9105, 0x0904, 0xad65, + 0xa880, 0xd0bc, 0x1904, 0xad65, 0x080c, 0xbbba, 0x0804, 0xad89, + 0x00f6, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe, + 0x0021, 0x0005, 0x0011, 0x0005, 0x0005, 0x0096, 0x6003, 0x0002, + 0x6007, 0x0043, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e, + 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, + 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46, + 0xab4a, 0xae36, 0xad3a, 0x6044, 0xd0fc, 0x190c, 0x98f0, 0x604b, + 0x0000, 0x080c, 0x1af7, 0x1118, 0x6144, 0x080c, 0x8513, 0x009e, + 0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, + 0x0005, 0xae98, 0xae98, 0xae98, 0xae98, 0xae98, 0xae98, 0xae98, + 0xae98, 0xae98, 0xae98, 0xae9a, 0xae98, 0xae98, 0xae98, 0xae98, + 0xaeab, 0xae98, 0xae98, 0xae98, 0xae98, 0xaecf, 0xae98, 0xae98, + 0x080c, 0x0d65, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x8891, + 0x2019, 0x0001, 0x080c, 0x929d, 0x6003, 0x0002, 0x080c, 0xbfac, + 0x080c, 0x88ec, 0x0005, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, + 0x8891, 0x2019, 0x0001, 0x080c, 0x929d, 0x080c, 0x88ec, 0x080c, + 0x302e, 0x080c, 0xbfa4, 0x0096, 0x6114, 0x2148, 0x080c, 0xb870, + 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, + 0x69b5, 0x080c, 0xba5f, 0x009e, 0x080c, 0x9be6, 0x0005, 0x080c, + 0x0d65, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, + 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a4f, + 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, + 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, + 0xaf07, 0xaf07, 0xaf07, 0xaf07, 0xaf07, 0xaf09, 0xaf07, 0xaf07, + 0xafc6, 0xaf07, 0xaf07, 0xaf07, 0xaf07, 0xaf07, 0xaf07, 0xaf07, + 0xaf07, 0xaf07, 0xaf07, 0xb104, 0xaf07, 0xb10e, 0xaf07, 0x080c, + 0x0d65, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120, + 0xc084, 0x601e, 0x0804, 0xacf9, 0x6114, 0x0096, 0x2148, 0xa87c, + 0xc0e5, 0xa87e, 0x009e, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, + 0x0260, 0x6114, 0x2150, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, + 0x9036, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, + 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, + 0x86ff, 0x0904, 0xafbf, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, + 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xafbf, + 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, + 0x0c38, 0x080c, 0x102f, 0x090c, 0x0d65, 0x2900, 0xb07a, 0xb77c, + 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, + 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, + 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, + 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, + 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, + 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, + 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, + 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, + 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xb426, 0x003e, + 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, + 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xb426, + 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, + 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xb3c5, 0x080c, + 0x190c, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1960, + 0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, + 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0x080c, 0xbfb5, + 0x0904, 0xb0ff, 0x604b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, + 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xb0c4, 0xa978, 0xa868, + 0xd0fc, 0x0904, 0xb085, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, + 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, + 0xb053, 0x9086, 0x0028, 0x1904, 0xb03f, 0xa87b, 0x001c, 0xb07b, + 0x001c, 0x0804, 0xb05b, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, + 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, + 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, + 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, + 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c, + 0xc0fc, 0x601e, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, + 0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, + 0x080c, 0x0fe1, 0x009e, 0x080c, 0xbbba, 0x0804, 0xb0ff, 0xd1dc, + 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xbe57, 0x0118, + 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, + 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, + 0x9115, 0x190c, 0xaed1, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, + 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, + 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, + 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, + 0x000e, 0xa87e, 0x080c, 0xbf34, 0x001e, 0xa874, 0x0006, 0x2148, + 0x080c, 0x0fe1, 0x001e, 0x0804, 0xb0f1, 0x0016, 0x00a6, 0x2150, + 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, + 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, + 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xbe57, 0x0118, 0xb174, + 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, + 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, + 0x190c, 0xaed1, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, + 0x00ae, 0x080c, 0x0fe1, 0x009e, 0x080c, 0xbf34, 0xa974, 0x0016, + 0x080c, 0xb416, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, + 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, + 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xbe57, + 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, + 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, + 0xa938, 0x9115, 0x190c, 0xaed1, 0xa974, 0x0016, 0x080c, 0x67cb, + 0x001e, 0x6010, 0x00b6, 0x2058, 0xb8c0, 0x0016, 0x9005, 0x190c, + 0x63ba, 0x001e, 0x00be, 0xd1e4, 0x1120, 0x080c, 0x9be6, 0x009e, + 0x0005, 0x080c, 0xbb7d, 0x0cd8, 0x6114, 0x0096, 0x2148, 0xa97c, + 0x080c, 0xbfb5, 0x190c, 0x192a, 0x009e, 0x0005, 0x0096, 0x6114, + 0x2148, 0xa83c, 0xa940, 0x9105, 0x01e8, 0xa877, 0x0000, 0xa87b, + 0x0000, 0xa867, 0x0103, 0x00b6, 0x6010, 0x2058, 0xa834, 0xa938, + 0x9115, 0x11a0, 0x080c, 0x67cb, 0xba3c, 0x8211, 0x0208, 0xba3e, + 0xb8c0, 0x9005, 0x0110, 0x080c, 0x63ba, 0x080c, 0x9be6, 0x00be, + 0x009e, 0x0005, 0xa87c, 0xc0dc, 0xa87e, 0x08f8, 0xb800, 0xd0bc, + 0x1120, 0xa834, 0x080c, 0xaed1, 0x0c28, 0xa880, 0xd0bc, 0x1dc8, + 0x080c, 0xbbba, 0x0c60, 0x080c, 0x8891, 0x0010, 0x080c, 0x88ec, + 0x601c, 0xd084, 0x0110, 0x080c, 0x193e, 0x080c, 0xb870, 0x01f0, + 0x0096, 0x6114, 0x2148, 0x080c, 0xba85, 0x1118, 0x080c, 0xa59c, + 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, 0x1198, + 0xd184, 0x1170, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, 0x080c, + 0xd563, 0xa877, 0x0000, 0x080c, 0x69b5, 0x009e, 0x0804, 0x9c20, + 0xa87b, 0x0004, 0x0cb0, 0xa87b, 0x0004, 0x0c98, 0x9182, 0x0057, + 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xb195, 0xb195, + 0xb195, 0xb195, 0xb195, 0xb197, 0xb195, 0xb195, 0xb195, 0xb195, + 0xb195, 0xb195, 0xb195, 0xb195, 0xb195, 0xb195, 0xb195, 0xb195, + 0xb195, 0xb195, 0xb1bb, 0xb195, 0xb195, 0x080c, 0x0d65, 0x080c, + 0x53b0, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, 0x9016, 0xd1c4, + 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, 0x0188, 0xa87b, + 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, 0x0103, 0xa976, + 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, 0x080c, 0x69b5, + 0x009e, 0x0804, 0x9be6, 0x080c, 0x53b0, 0x0dd8, 0x6014, 0x900e, + 0x9016, 0x0c10, 0x9182, 0x0085, 0x0002, 0xb1d4, 0xb1d2, 0xb1d2, + 0xb1e0, 0xb1d2, 0xb1d2, 0xb1d2, 0xb1d2, 0xb1d2, 0xb1d2, 0xb1d2, + 0xb1d2, 0xb1d2, 0x080c, 0x0d65, 0x6003, 0x0001, 0x6106, 0x0126, + 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x84e7, 0x012e, 0x0005, + 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, 0x7224, 0x6216, + 0x7220, 0x080c, 0xb85e, 0x01a0, 0x2268, 0x6800, 0x9086, 0x0000, + 0x0178, 0x6010, 0x6d10, 0x952e, 0x1158, 0x00c6, 0x2d60, 0x080c, + 0xb451, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, 0x0010, + 0x6007, 0x0087, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, + 0x7220, 0x080c, 0xb85e, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, + 0x00be, 0xd0bc, 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, + 0x080c, 0xbbba, 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, + 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d65, + 0x908a, 0x0092, 0x1a0c, 0x0d65, 0x9082, 0x0085, 0x00e2, 0x9186, + 0x0027, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d65, 0x080c, 0x8891, + 0x0096, 0x6014, 0x2048, 0x080c, 0xb870, 0x0140, 0xa867, 0x0103, + 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x69b5, 0x009e, 0x080c, + 0x9c20, 0x0804, 0x894f, 0xb258, 0xb25a, 0xb25a, 0xb258, 0xb258, + 0xb258, 0xb258, 0xb258, 0xb258, 0xb258, 0xb258, 0xb258, 0xb258, + 0x080c, 0x0d65, 0x080c, 0x9c20, 0x0005, 0x9186, 0x0013, 0x1130, + 0x6004, 0x9082, 0x0085, 0x2008, 0x0804, 0xb2a9, 0x9186, 0x0027, + 0x1558, 0x080c, 0x8891, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x0096, + 0x6014, 0x2048, 0x080c, 0xb870, 0x0150, 0xa867, 0x0103, 0xa877, + 0x0000, 0xa87b, 0x0029, 0x080c, 0x69b5, 0x080c, 0xba5f, 0x009e, + 0x080c, 0x9be6, 0x0005, 0x9186, 0x0089, 0x0118, 0x9186, 0x008a, + 0x1140, 0x080c, 0x9ab6, 0x0128, 0x9086, 0x000c, 0x0904, 0xb2e1, + 0x0000, 0x080c, 0x9c9f, 0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, + 0x8891, 0x0096, 0x6014, 0x2048, 0x080c, 0xb870, 0x0d00, 0xa867, + 0x0103, 0xa877, 0x0000, 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, + 0x0890, 0x0002, 0xb2b9, 0xb2b7, 0xb2b7, 0xb2b7, 0xb2b7, 0xb2b7, + 0xb2cd, 0xb2b7, 0xb2b7, 0xb2b7, 0xb2b7, 0xb2b7, 0xb2b7, 0x080c, + 0x0d65, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, + 0x9186, 0x0035, 0x1118, 0x2001, 0x195e, 0x0010, 0x2001, 0x195f, + 0x2004, 0x601a, 0x6003, 0x000c, 0x0005, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, + 0x195e, 0x0010, 0x2001, 0x195f, 0x2004, 0x601a, 0x6003, 0x000e, + 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, + 0x0804, 0x9c9f, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f9, 0xb346, + 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0xb2f7, 0x080c, + 0x0d65, 0x0096, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, + 0x0168, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, + 0x9186, 0x0035, 0x1118, 0x009e, 0x0804, 0xb35a, 0x080c, 0xb870, + 0x1118, 0x080c, 0xba5f, 0x0068, 0x6014, 0x2048, 0x080c, 0xbfbb, + 0x1110, 0x080c, 0xba5f, 0xa867, 0x0103, 0x080c, 0xbf6f, 0x080c, + 0x69b5, 0x00d6, 0x2c68, 0x080c, 0x9b90, 0x01d0, 0x6003, 0x0001, + 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, + 0x2009, 0x026f, 0x210c, 0x613e, 0x6910, 0x6112, 0x080c, 0xbd09, + 0x695c, 0x615e, 0x6023, 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, + 0x2d60, 0x00de, 0x080c, 0x9be6, 0x009e, 0x0005, 0x6010, 0x00b6, + 0x2058, 0xb800, 0x00be, 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, + 0x810f, 0x9186, 0x0035, 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, + 0x0039, 0x1538, 0x00d6, 0x2c68, 0x080c, 0xbf07, 0x11f0, 0x080c, + 0x9b90, 0x01d8, 0x6106, 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, + 0x6112, 0x692c, 0x612e, 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, + 0x6136, 0x6938, 0x613a, 0x693c, 0x613e, 0x695c, 0x615e, 0x080c, + 0xbd09, 0x2009, 0x8020, 0x080c, 0x84e7, 0x2d60, 0x00de, 0x0804, + 0x9be6, 0x0096, 0x6014, 0x2048, 0x080c, 0xb870, 0x01c8, 0xa867, + 0x0103, 0xa880, 0xd0b4, 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, - 0x080c, 0xbb4b, 0xa877, 0x0000, 0x0005, 0x2001, 0x1810, 0x2004, - 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0f4, 0x000e, - 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, 0x000e, 0x0005, - 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, - 0x0007, 0x080c, 0x4a77, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, - 0x0005, 0x2001, 0x1956, 0x2004, 0x601a, 0x0005, 0x2001, 0x1958, - 0x2004, 0x604a, 0x0005, 0x080c, 0x9bda, 0x0804, 0x891b, 0x611c, - 0xd1fc, 0xa97c, 0x1108, 0xd1e4, 0x0005, 0x601c, 0xd0fc, 0xa87c, - 0x1108, 0xd0e4, 0x0005, 0x601c, 0xd0fc, 0xc0fc, 0x601e, 0xa87c, - 0x1108, 0xd0e4, 0x0005, 0x6044, 0xd0fc, 0x1138, 0xd0bc, 0x0198, - 0xc0bc, 0x6046, 0x6003, 0x0002, 0x0070, 0xd0ac, 0x1160, 0xd0dc, - 0x1128, 0x908c, 0x000f, 0x9186, 0x0005, 0x1118, 0x6003, 0x0003, - 0x0010, 0x6003, 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, - 0x0016, 0x1a0c, 0x0d65, 0x001b, 0x006e, 0x00be, 0x0005, 0xbfcf, - 0xc6ae, 0xc7fd, 0xbfcf, 0xbfcf, 0xbfcf, 0xbfcf, 0xbfcf, 0xc006, - 0xc881, 0xbfcf, 0xbfcf, 0xbfcf, 0xbfcf, 0xbfcf, 0xbfcf, 0x080c, - 0x0d65, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d65, 0x0013, - 0x006e, 0x0005, 0xbfea, 0xcd98, 0xbfea, 0xbfea, 0xbfea, 0xbfea, - 0xbfea, 0xbfea, 0xcd47, 0xcdea, 0xbfea, 0xd40e, 0xd442, 0xd40e, - 0xd442, 0xbfea, 0x080c, 0x0d65, 0x6000, 0x9082, 0x0016, 0x1a0c, - 0x0d65, 0x6000, 0x000a, 0x0005, 0xc004, 0xca5d, 0xcb26, 0xcb48, - 0xcbc3, 0xc004, 0xccbd, 0xcc4b, 0xc88b, 0xcd1f, 0xcd34, 0xc004, - 0xc004, 0xc004, 0xc004, 0xc004, 0x080c, 0x0d65, 0x91b2, 0x0053, - 0x1a0c, 0x0d65, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xc451, 0x0002, - 0xc050, 0xc242, 0xc050, 0xc050, 0xc050, 0xc24b, 0xc050, 0xc050, - 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, - 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc052, - 0xc0b9, 0xc0c8, 0xc12c, 0xc157, 0xc1cf, 0xc22d, 0xc050, 0xc050, - 0xc24e, 0xc050, 0xc050, 0xc263, 0xc270, 0xc050, 0xc050, 0xc050, - 0xc050, 0xc050, 0xc2f3, 0xc050, 0xc050, 0xc307, 0xc050, 0xc050, - 0xc2c2, 0xc050, 0xc050, 0xc050, 0xc31f, 0xc050, 0xc050, 0xc050, - 0xc39c, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc050, 0xc419, - 0x080c, 0x0d65, 0x080c, 0x6624, 0x1150, 0x2001, 0x1836, 0x2004, - 0xd0cc, 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, - 0x0009, 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xc23b, 0x080c, - 0x660d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, - 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x98bb, 0x080c, 0x8624, - 0x0076, 0x903e, 0x080c, 0x8509, 0x2c08, 0x080c, 0xcfd9, 0x007e, - 0x001e, 0x080c, 0x98d7, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x6610, 0x2658, 0x080c, 0x627a, 0xbe04, 0x9684, 0x00ff, 0x9082, - 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, - 0x00be, 0x2c08, 0x080c, 0xd5ba, 0x002e, 0x001e, 0x1178, 0x080c, - 0xcf08, 0x1904, 0xc124, 0x080c, 0xcea4, 0x1120, 0x6007, 0x0008, - 0x0804, 0xc23b, 0x6007, 0x0009, 0x0804, 0xc23b, 0x080c, 0xd10f, - 0x0128, 0x080c, 0xcf08, 0x0d78, 0x0804, 0xc124, 0x6017, 0x1900, - 0x0c88, 0x080c, 0x3144, 0x1904, 0xc44e, 0x6106, 0x080c, 0xce55, - 0x6007, 0x0006, 0x0804, 0xc23b, 0x6007, 0x0007, 0x0804, 0xc23b, - 0x080c, 0xd47e, 0x1904, 0xc44e, 0x080c, 0x3144, 0x1904, 0xc44e, - 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, - 0x1220, 0x2001, 0x0001, 0x080c, 0x61a8, 0x96b4, 0xff00, 0x8637, - 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, - 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, - 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, - 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, - 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, - 0x00b0, 0x00ee, 0x080c, 0xcf6f, 0x1190, 0x9686, 0x0006, 0x1140, - 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x305d, 0x002e, - 0x080c, 0x6306, 0x6007, 0x000a, 0x00de, 0x0804, 0xc23b, 0x6007, - 0x000b, 0x00de, 0x0804, 0xc23b, 0x080c, 0x300e, 0x080c, 0xbf76, - 0x6007, 0x0001, 0x0804, 0xc23b, 0x080c, 0xd47e, 0x1904, 0xc44e, - 0x080c, 0x3144, 0x1904, 0xc44e, 0x2071, 0x0260, 0x7034, 0x90b4, - 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, - 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, - 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, 0x305d, 0x002e, 0x6007, - 0x000c, 0x2001, 0x0001, 0x080c, 0xd59a, 0x0804, 0xc23b, 0x080c, - 0x6624, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, 0x9086, - 0x0008, 0x1110, 0x0804, 0xc05f, 0x080c, 0x660d, 0x6610, 0x2658, - 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x06c0, 0x1138, 0x0026, - 0x2001, 0x0006, 0x080c, 0x61e8, 0x002e, 0x0050, 0x96b4, 0xff00, - 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc124, - 0x080c, 0xcf7c, 0x1120, 0x6007, 0x000e, 0x0804, 0xc23b, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x300e, 0x080c, 0xbf76, - 0x004e, 0x0016, 0x9006, 0x2009, 0x1854, 0x210c, 0x0048, 0x2009, - 0x0029, 0x080c, 0xd284, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, - 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, 0xc23b, 0x2001, 0x0001, - 0x080c, 0x61a8, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, - 0x2019, 0x1805, 0x2011, 0x0270, 0x080c, 0xabbf, 0x003e, 0x002e, - 0x001e, 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, - 0x0004, 0x0a04, 0xc124, 0x9682, 0x0007, 0x0a04, 0xc180, 0x0804, - 0xc124, 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xc23b, 0x080c, - 0x6624, 0x1140, 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, 0x9086, - 0x0008, 0x1110, 0x0804, 0xc05f, 0x080c, 0x660d, 0x6610, 0x2658, - 0xbe04, 0x9684, 0x00ff, 0x0006, 0x9086, 0x0001, 0x000e, 0x0170, - 0x9082, 0x0006, 0x0690, 0x0150, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc124, 0x080c, 0xcfaa, - 0x1130, 0x080c, 0xcea4, 0x1118, 0x6007, 0x0010, 0x04e0, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x300e, 0x080c, 0xbf76, - 0x004e, 0x0016, 0x9006, 0x2009, 0x1854, 0x210c, 0x0048, 0x2009, - 0x0029, 0x080c, 0xd284, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, - 0x001e, 0x004e, 0x6007, 0x0001, 0x00f0, 0x080c, 0xd10f, 0x0140, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0980, 0x0804, 0xc124, - 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x3144, 0x1904, - 0xc44e, 0x080c, 0xd47e, 0x1904, 0xc44e, 0x080c, 0xc5ee, 0x1904, - 0xc124, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x84ba, 0x080c, - 0x891b, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ba, - 0x080c, 0x891b, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xd47e, - 0x1904, 0xc44e, 0x080c, 0x3144, 0x1904, 0xc44e, 0x080c, 0xc5ee, - 0x1904, 0xc124, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x84ba, - 0x080c, 0x891b, 0x0005, 0x080c, 0x3144, 0x1904, 0xc44e, 0x6007, - 0x0023, 0x6003, 0x0001, 0x080c, 0x84ba, 0x080c, 0x891b, 0x0005, - 0x080c, 0xd47e, 0x1904, 0xc44e, 0x080c, 0x3144, 0x1904, 0xc44e, - 0x080c, 0xc5ee, 0x1904, 0xc124, 0x0016, 0x0026, 0x00e6, 0x2071, - 0x0260, 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xb830, - 0x01b0, 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, - 0x0004, 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, - 0x080c, 0xd256, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, - 0x6007, 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, - 0x6007, 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, - 0x9086, 0x0024, 0x1110, 0x080c, 0x9bda, 0x2160, 0x6007, 0x0025, - 0x6003, 0x0001, 0x080c, 0x84ba, 0x080c, 0x891b, 0x00ee, 0x002e, - 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x61a8, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, - 0x080c, 0xabbf, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, - 0x0031, 0x0804, 0xc23b, 0x080c, 0xa824, 0x080c, 0x7096, 0x1190, - 0x0006, 0x0026, 0x0036, 0x080c, 0x70b0, 0x1138, 0x080c, 0x7396, - 0x080c, 0x5cd7, 0x080c, 0x6fc7, 0x0010, 0x080c, 0x706a, 0x003e, - 0x002e, 0x000e, 0x0005, 0x080c, 0x3144, 0x1904, 0xc44e, 0x080c, - 0xc5ee, 0x1904, 0xc124, 0x6106, 0x080c, 0xc60a, 0x1120, 0x6007, - 0x002b, 0x0804, 0xc23b, 0x6007, 0x002c, 0x0804, 0xc23b, 0x080c, - 0xd47e, 0x1904, 0xc44e, 0x080c, 0x3144, 0x1904, 0xc44e, 0x080c, - 0xc5ee, 0x1904, 0xc124, 0x6106, 0x080c, 0xc60f, 0x1120, 0x6007, - 0x002e, 0x0804, 0xc23b, 0x6007, 0x002f, 0x0804, 0xc23b, 0x080c, - 0x3144, 0x1904, 0xc44e, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, - 0xb904, 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, - 0x8007, 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, - 0xc242, 0x080c, 0x538c, 0xd0e4, 0x0904, 0xc399, 0x2071, 0x026c, - 0x7010, 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x6662, - 0x0140, 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, - 0x0510, 0x080c, 0x665e, 0x15b8, 0x2069, 0x1800, 0x687c, 0x9206, - 0x1590, 0x6878, 0x9106, 0x1578, 0x7210, 0x080c, 0xb830, 0x0590, - 0x080c, 0xc4d9, 0x0578, 0x080c, 0xd300, 0x0560, 0x622e, 0x6007, - 0x0036, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, - 0xb830, 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, - 0x08e0, 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xd256, 0x2c10, - 0x2160, 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, - 0x1500, 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, - 0x0880, 0x6007, 0x0012, 0x0868, 0x080c, 0x3144, 0x1904, 0xc44e, - 0x6010, 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, - 0x1904, 0xc242, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x538c, 0xd0e4, - 0x0904, 0xc411, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, - 0x720c, 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, - 0x9085, 0x0001, 0x080c, 0xd256, 0x2c10, 0x00ce, 0x05e8, 0x080c, - 0xb830, 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, - 0x00c6, 0x0026, 0x2260, 0x080c, 0xb433, 0x002e, 0x00ce, 0x7118, - 0x918c, 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, - 0x0118, 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, - 0x0170, 0x080c, 0xc4d9, 0x0904, 0xc392, 0x0056, 0x7510, 0x7614, - 0x080c, 0xd319, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, - 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, - 0x8020, 0x080c, 0x84b3, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, - 0x6017, 0x0300, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, - 0x0c10, 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, - 0xc369, 0x00e6, 0x0026, 0x080c, 0x6624, 0x0550, 0x080c, 0x660d, - 0x080c, 0xd4f0, 0x1518, 0x2071, 0x1800, 0x70d8, 0x9085, 0x0003, - 0x70da, 0x00f6, 0x2079, 0x0100, 0x72ac, 0x9284, 0x00ff, 0x707a, - 0x78e6, 0x9284, 0xff00, 0x727c, 0x9205, 0x707e, 0x78ea, 0x00fe, - 0x70e3, 0x0000, 0x080c, 0x6662, 0x0120, 0x2011, 0x19d9, 0x2013, - 0x07d0, 0xd0ac, 0x1128, 0x080c, 0x2de9, 0x0010, 0x080c, 0xd522, - 0x002e, 0x00ee, 0x080c, 0x9bda, 0x0804, 0xc241, 0x080c, 0x9bda, - 0x0005, 0x2600, 0x0002, 0xc465, 0xc465, 0xc465, 0xc465, 0xc465, - 0xc467, 0xc465, 0xc465, 0xc465, 0xc465, 0xc484, 0xc465, 0xc465, - 0xc465, 0xc496, 0xc4a3, 0xc4d4, 0xc465, 0x080c, 0x0d65, 0x080c, - 0xd47e, 0x1d20, 0x080c, 0x3144, 0x1d08, 0x080c, 0xc5ee, 0x1148, - 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x84ba, - 0x0005, 0x080c, 0x300e, 0x080c, 0xbf76, 0x6007, 0x0001, 0x6003, - 0x0001, 0x080c, 0x84ba, 0x0005, 0x080c, 0xd47e, 0x1938, 0x080c, - 0x3144, 0x1920, 0x080c, 0xc5ee, 0x1d60, 0x703c, 0x6016, 0x6007, - 0x004a, 0x6003, 0x0001, 0x080c, 0x84ba, 0x0005, 0x080c, 0xc4f6, - 0x0904, 0xc44e, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x84ba, - 0x080c, 0x891b, 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, - 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, - 0x2001, 0x198d, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x198e, - 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, - 0xabd3, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, - 0x84ba, 0x080c, 0x891b, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, - 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, - 0x6010, 0x2058, 0xb8c4, 0xd084, 0x0150, 0x7128, 0x6050, 0x9106, - 0x1120, 0x712c, 0x604c, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, - 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, - 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x708c, 0x908a, 0x00f9, 0x16e8, 0x20e1, 0x0000, 0x2001, - 0x1970, 0x2003, 0x0000, 0x080c, 0x103b, 0x05a0, 0x2900, 0x6016, - 0x708c, 0x8004, 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, - 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, - 0x2001, 0x1970, 0x0016, 0x200c, 0x0471, 0x001e, 0x2940, 0x080c, - 0x103b, 0x01c0, 0x2900, 0xa006, 0x2100, 0x81ff, 0x0180, 0x0c18, - 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, - 0x2001, 0x1970, 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, - 0x0001, 0x0048, 0x2071, 0x1800, 0x708f, 0x0000, 0x6014, 0x2048, - 0x080c, 0x0fd4, 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, - 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x918c, 0xffff, 0x11a8, 0x080c, 0x203c, 0x2099, 0x026c, 0x2001, - 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, - 0x4003, 0x22a8, 0x8108, 0x080c, 0x203c, 0x2099, 0x0260, 0x0ca8, - 0x080c, 0x203c, 0x2061, 0x1970, 0x6004, 0x2098, 0x6008, 0x3518, - 0x9312, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, - 0x8108, 0x080c, 0x203c, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x1970, - 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, - 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, - 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x2054, - 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, - 0x080c, 0x2054, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x2054, 0x2061, - 0x1973, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, - 0x080c, 0x2054, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x1973, 0x2019, - 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, - 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, - 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, - 0x00be, 0x0005, 0x00d6, 0x080c, 0xc684, 0x00de, 0x0005, 0x00d6, - 0x080c, 0xc691, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, - 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, - 0x080c, 0xd59a, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, - 0x918c, 0x00ff, 0x6824, 0x080c, 0x243d, 0x1148, 0x2001, 0x0001, - 0x080c, 0xd59a, 0x2110, 0x900e, 0x080c, 0x305d, 0x0018, 0x9085, - 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, - 0x9c49, 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x243d, 0x1568, 0x080c, 0x620b, 0x1550, - 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, - 0xd47e, 0x11c8, 0x080c, 0x3144, 0x11b0, 0x080c, 0xc5ee, 0x0500, - 0x2001, 0x0007, 0x080c, 0x61bc, 0x2001, 0x0007, 0x080c, 0x61e8, - 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x84ba, 0x0010, 0x080c, 0x9bda, 0x9085, 0x0001, 0x00ce, - 0x00be, 0x0005, 0x080c, 0x9bda, 0x00ce, 0x002e, 0x001e, 0x0ca8, - 0x080c, 0x9bda, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, - 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, - 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, - 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, - 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162, - 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, - 0x0053, 0x1a0c, 0x0d65, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, - 0x0040, 0x1a04, 0xc7d1, 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, - 0x0014, 0x190c, 0x0d65, 0x2001, 0x0007, 0x080c, 0x61e8, 0x080c, - 0x885d, 0x080c, 0x9c14, 0x080c, 0x891b, 0x0005, 0xc70e, 0xc710, - 0xc70e, 0xc70e, 0xc70e, 0xc710, 0xc71d, 0xc7ce, 0xc76d, 0xc7ce, - 0xc77f, 0xc7ce, 0xc71d, 0xc7ce, 0xc7c6, 0xc7ce, 0xc7c6, 0xc7ce, - 0xc7ce, 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc70e, - 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc710, 0xc70e, 0xc7ce, 0xc70e, - 0xc70e, 0xc7ce, 0xc70e, 0xc7cb, 0xc7ce, 0xc70e, 0xc70e, 0xc70e, - 0xc70e, 0xc7ce, 0xc7ce, 0xc70e, 0xc7ce, 0xc7ce, 0xc70e, 0xc718, - 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0xc7ca, 0xc7ce, 0xc70e, 0xc70e, - 0xc7ce, 0xc7ce, 0xc70e, 0xc70e, 0xc70e, 0xc70e, 0x080c, 0x0d65, - 0x080c, 0xbf79, 0x6003, 0x0002, 0x080c, 0x891b, 0x0804, 0xc7d0, - 0x9006, 0x080c, 0x61a8, 0x0804, 0xc7ce, 0x080c, 0x665e, 0x1904, - 0xc7ce, 0x9006, 0x080c, 0x61a8, 0x6010, 0x2058, 0xb810, 0x9086, - 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, - 0x00fe, 0x0428, 0x6010, 0x2058, 0xb884, 0x9005, 0x1178, 0x080c, - 0xbf61, 0x1904, 0xc7ce, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0007, - 0x080c, 0x4a77, 0x004e, 0x003e, 0x0804, 0xc7ce, 0x080c, 0x3175, - 0x1904, 0xc7ce, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, - 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x2001, - 0x0002, 0x080c, 0x61bc, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x84ba, 0x080c, 0x891b, 0x6110, 0x2158, 0x2009, - 0x0001, 0x080c, 0x8146, 0x0804, 0xc7d0, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0904, 0xc7ce, 0x9686, - 0x0004, 0x0904, 0xc7ce, 0x2001, 0x0004, 0x0804, 0xc7cc, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, - 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4a77, 0x004e, 0x003e, - 0x2001, 0x0006, 0x080c, 0xc7ea, 0x6610, 0x2658, 0xbe04, 0x0066, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, - 0x0006, 0x080c, 0x61e8, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, - 0x2001, 0x0006, 0x080c, 0x61bc, 0x080c, 0x665e, 0x11f8, 0x2001, - 0x1836, 0x2004, 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x01a0, 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, - 0x00fe, 0x0804, 0xc757, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, - 0x0409, 0x0020, 0x0018, 0x0010, 0x080c, 0x61e8, 0x080c, 0x9bda, - 0x0005, 0x2600, 0x0002, 0xc7e5, 0xc7e5, 0xc7e5, 0xc7e5, 0xc7e5, - 0xc7e7, 0xc7e5, 0xc7e5, 0xc7e5, 0xc7e5, 0xc7e7, 0xc7e5, 0xc7e5, - 0xc7e5, 0xc7e7, 0xc7e7, 0xc7e7, 0xc7e7, 0x080c, 0x0d65, 0x080c, - 0x9bda, 0x0005, 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, - 0xd184, 0x0138, 0x080c, 0x61bc, 0x9006, 0x080c, 0x61a8, 0x080c, - 0x303d, 0x00de, 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, - 0x9084, 0xff00, 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0d65, 0x91b6, - 0x0015, 0x1110, 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d65, - 0x006b, 0x0005, 0xa662, 0xa662, 0xa662, 0xa662, 0xc87f, 0xa662, - 0xc869, 0xc82a, 0xa662, 0xa662, 0xa662, 0xa662, 0xa662, 0xa662, - 0xa662, 0xa662, 0xc87f, 0xa662, 0xc869, 0xc870, 0xa662, 0xa662, - 0xa662, 0xa662, 0x00f6, 0x080c, 0x665e, 0x11d8, 0x080c, 0xbf61, - 0x11c0, 0x6010, 0x905d, 0x01a8, 0xb884, 0x9005, 0x0190, 0x9006, - 0x080c, 0x61a8, 0x2001, 0x0002, 0x080c, 0x61bc, 0x6023, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x84ba, 0x080c, 0x891b, - 0x00f0, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x243d, - 0x11b0, 0x080c, 0x626b, 0x0118, 0x080c, 0x9bda, 0x0080, 0xb810, - 0x0006, 0xb814, 0x0006, 0xb884, 0x0006, 0x080c, 0x5cf1, 0x000e, - 0xb886, 0x000e, 0xb816, 0x000e, 0xb812, 0x080c, 0x9bda, 0x00fe, - 0x0005, 0x6604, 0x96b6, 0x001e, 0x1110, 0x080c, 0x9bda, 0x0005, - 0x080c, 0xaa48, 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x84ba, 0x080c, 0x891b, 0x0010, 0x080c, 0x9bda, 0x0005, 0x0804, - 0x9bda, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d65, 0x080c, 0x885d, - 0x080c, 0x9c14, 0x0005, 0x9182, 0x0040, 0x0002, 0xc8a1, 0xc8a1, - 0xc8a1, 0xc8a1, 0xc8a3, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, - 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, 0xc8a1, - 0xc8a1, 0x080c, 0x0d65, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, - 0x0046, 0x0026, 0x6210, 0x2258, 0xb8ac, 0x9005, 0x11b0, 0x6007, - 0x0044, 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xc90a, - 0x080c, 0xd58e, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, - 0x2011, 0x0200, 0x080c, 0x83cd, 0x0020, 0x9026, 0x080c, 0xd4c3, - 0x0c30, 0x080c, 0x1022, 0x090c, 0x0d65, 0x6003, 0x0007, 0xa867, - 0x010d, 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, - 0xa8e2, 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, - 0xa87f, 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x6991, - 0x001e, 0x080c, 0xd58e, 0x1904, 0xc96a, 0x9486, 0x2000, 0x1130, - 0x2019, 0x0017, 0x080c, 0xd1fc, 0x0804, 0xc96a, 0x9486, 0x0200, - 0x1120, 0x080c, 0xd18c, 0x0804, 0xc96a, 0x9486, 0x0400, 0x0120, - 0x9486, 0x1000, 0x1904, 0xc96a, 0x2019, 0x0002, 0x080c, 0xd1ab, - 0x0804, 0xc96a, 0x2069, 0x1a3e, 0x6a00, 0xd284, 0x0904, 0xc9d4, - 0x9284, 0x0300, 0x1904, 0xc9cd, 0x6804, 0x9005, 0x0904, 0xc9b5, - 0x2d78, 0x6003, 0x0007, 0x080c, 0x103b, 0x0904, 0xc976, 0x7800, - 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, - 0x180f, 0x2004, 0xd084, 0x1904, 0xc9d8, 0x9006, 0xa802, 0xa867, - 0x0116, 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, - 0xb8a0, 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, - 0xb930, 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, - 0x0003, 0x9080, 0xc972, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, - 0x0270, 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, - 0x20e1, 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, - 0x0000, 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, - 0x080c, 0x6994, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, - 0x009e, 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, - 0x2004, 0xd084, 0x0120, 0x080c, 0x1022, 0x1904, 0xc91f, 0x6017, - 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x84b3, 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, - 0x1200, 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, - 0xf700, 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, - 0x2009, 0xa025, 0x080c, 0x84b3, 0x0828, 0x6868, 0x602e, 0x686c, - 0x6032, 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, - 0xa022, 0x080c, 0x84b3, 0x0804, 0xc96a, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x48da, 0x6017, 0xf300, - 0x0010, 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, - 0xa022, 0x080c, 0x84b3, 0x0804, 0xc96a, 0x6017, 0xf500, 0x0c98, - 0x6017, 0xf600, 0x0804, 0xc98a, 0x6017, 0xf200, 0x0804, 0xc98a, - 0xa867, 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, - 0x7044, 0x9084, 0x0003, 0x9080, 0xc972, 0x2005, 0xa87e, 0x2928, - 0x6010, 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, - 0xb830, 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, - 0x2104, 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, - 0x2214, 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d65, - 0x8210, 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0029, 0x20a0, 0x2011, 0xca54, 0x2041, 0x0001, 0x223d, - 0x9784, 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, - 0x0530, 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, - 0x2098, 0x0c68, 0x2950, 0x080c, 0x103b, 0x0170, 0x2900, 0xb002, - 0xa867, 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x001b, 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, - 0x080c, 0x1054, 0x0cc8, 0x080c, 0x1054, 0x0804, 0xc976, 0x2548, - 0x8847, 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, - 0x080c, 0xd22f, 0x0804, 0xc96a, 0x8010, 0x0004, 0x801a, 0x0006, - 0x8018, 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0057, 0x1a0c, 0x0d65, 0x9082, 0x0040, 0x0a0c, - 0x0d65, 0x2008, 0x0804, 0xcadf, 0x9186, 0x0051, 0x0108, 0x0040, - 0x080c, 0x9aaa, 0x01e8, 0x9086, 0x0002, 0x0904, 0xcb26, 0x00c0, - 0x9186, 0x0027, 0x0180, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, - 0x0150, 0x190c, 0x0d65, 0x080c, 0x9aaa, 0x0150, 0x9086, 0x0004, - 0x0904, 0xcbc3, 0x0028, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, - 0x080c, 0x9c93, 0x0005, 0xcaa6, 0xcaa8, 0xcaa8, 0xcacf, 0xcaa6, - 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, - 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0xcaa6, 0x080c, 0x0d65, - 0x080c, 0x885d, 0x080c, 0x891b, 0x0036, 0x0096, 0x6014, 0x904d, - 0x01d8, 0x080c, 0xb842, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, + 0x080c, 0xbb79, 0xa877, 0x0000, 0x080c, 0x69b5, 0x080c, 0xba5f, + 0x009e, 0x0804, 0x9be6, 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, + 0xb870, 0x0140, 0xa867, 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, + 0x080c, 0x69b5, 0x009e, 0x001e, 0x9186, 0x0013, 0x0158, 0x9186, + 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0x9c9f, 0x0020, + 0x080c, 0x8891, 0x080c, 0x9c20, 0x0005, 0x0056, 0x0066, 0x0096, + 0x00a6, 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, + 0x0100, 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, + 0x0029, 0x080c, 0xb426, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, + 0x080c, 0x0fe1, 0x080c, 0x102f, 0x0520, 0x8528, 0xa867, 0x0110, + 0xa86b, 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, + 0x2011, 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, + 0x2950, 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, + 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, + 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, + 0x0003, 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, + 0x0158, 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x69b5, + 0x2a48, 0x0cb8, 0x080c, 0x69b5, 0x00ae, 0x0005, 0x00f6, 0x2079, + 0x0200, 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, + 0x810c, 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, + 0x20e1, 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, + 0x0020, 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, + 0x9085, 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, + 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, + 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, + 0x006e, 0x012e, 0x0005, 0xb4a3, 0xb4a3, 0xb49e, 0xb4c7, 0xb47b, + 0xb49e, 0xb47d, 0xb49e, 0xb47b, 0xb47b, 0xb49e, 0xb49e, 0xb49e, + 0xb47b, 0xb47b, 0xb47b, 0x080c, 0x0d65, 0x6010, 0x9080, 0x0000, + 0x2004, 0xd0bc, 0x190c, 0xb4c7, 0x0036, 0x6014, 0x0096, 0x2048, + 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019, 0x000c, 0x0038, 0xd094, + 0x0118, 0x2019, 0x000d, 0x0010, 0x2019, 0x0010, 0x080c, 0xce41, + 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x9006, 0x0005, + 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, + 0x080c, 0xb870, 0x01d0, 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, + 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, + 0x0005, 0x080c, 0x6bc6, 0x080c, 0xbb79, 0x080c, 0x69a9, 0x080c, + 0x9c20, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, + 0x98c7, 0x080c, 0xbfc9, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, + 0x002b, 0x0106, 0x080c, 0x98e3, 0x010e, 0x0005, 0xb4e6, 0xb514, + 0xb4e8, 0xb53b, 0xb50f, 0xb4e6, 0xb49e, 0xb4a3, 0xb4a3, 0xb49e, + 0xb49e, 0xb49e, 0xb49e, 0xb49e, 0xb49e, 0xb49e, 0x080c, 0x0d65, + 0x86ff, 0x1510, 0x6020, 0x9086, 0x0006, 0x01f0, 0x0096, 0x6014, + 0x2048, 0x080c, 0xb870, 0x0158, 0xa87c, 0xd0cc, 0x0130, 0x0096, + 0xa878, 0x2048, 0x080c, 0x0fe1, 0x009e, 0x080c, 0xbb79, 0x009e, + 0x080c, 0xbf49, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, + 0x2009, 0x8020, 0x080c, 0x84c9, 0x9085, 0x0001, 0x0005, 0x0066, + 0x080c, 0x193e, 0x006e, 0x08a0, 0x00e6, 0x2071, 0x19bf, 0x7030, + 0x9c06, 0x1120, 0x080c, 0x921d, 0x00ee, 0x0850, 0x6020, 0x9084, + 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, + 0x2c40, 0x080c, 0x936d, 0x009e, 0x008e, 0x0040, 0x0066, 0x080c, + 0x9119, 0x190c, 0x0d65, 0x080c, 0x9127, 0x006e, 0x00ee, 0x1904, + 0xb4e8, 0x0804, 0xb49e, 0x0036, 0x00e6, 0x2071, 0x19bf, 0x704c, + 0x9c06, 0x1138, 0x901e, 0x080c, 0x929d, 0x00ee, 0x003e, 0x0804, + 0xb4e8, 0x080c, 0x94a4, 0x00ee, 0x003e, 0x1904, 0xb4e8, 0x0804, + 0xb49e, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, + 0x00ce, 0x0005, 0xb571, 0xb640, 0xb7aa, 0xb579, 0x9c20, 0xb571, + 0xce33, 0xbfb1, 0xb640, 0xb56a, 0xb836, 0xb56a, 0xb56a, 0xb56a, + 0xb56a, 0xb56a, 0x080c, 0x0d65, 0x080c, 0xba85, 0x1110, 0x080c, + 0xa59c, 0x0005, 0x080c, 0x8891, 0x0804, 0x9be6, 0x601b, 0x0001, + 0x0005, 0x080c, 0xb870, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, + 0xa896, 0x009e, 0x080c, 0x98c7, 0x080c, 0xbfc9, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x0804, 0x98e3, 0xb59e, 0xb5a0, + 0xb5ca, 0xb5de, 0xb60b, 0xb59e, 0xb571, 0xb571, 0xb571, 0xb5e5, + 0xb5e5, 0xb59e, 0xb59e, 0xb59e, 0xb59e, 0xb5ef, 0x080c, 0x0d65, + 0x00e6, 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, + 0x2071, 0x19bf, 0x7030, 0x9c06, 0x01d0, 0x0066, 0x080c, 0x9119, + 0x190c, 0x0d65, 0x080c, 0x9127, 0x006e, 0x080c, 0xbf49, 0x6007, + 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x195f, 0x2004, + 0x601a, 0x2009, 0x8020, 0x080c, 0x84c9, 0x00ee, 0x0005, 0x601b, + 0x0001, 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, + 0x009e, 0x080c, 0xbf49, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x2009, 0x8020, 0x080c, 0x84c9, 0x0005, 0x080c, 0x98c7, + 0x080c, 0x9a38, 0x080c, 0x98e3, 0x0c28, 0x0096, 0x601b, 0x0001, + 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, + 0x53b0, 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, + 0x0103, 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, + 0xa87b, 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x69b5, + 0x009e, 0x0804, 0x9be6, 0x6014, 0x0096, 0x904d, 0x0560, 0xa97c, + 0xd1e4, 0x1158, 0x611c, 0xd1fc, 0x0530, 0x6110, 0x00b6, 0x2158, + 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, 0x98e3, 0x2001, + 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, 0x009e, + 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0037, 0x2c08, + 0x080c, 0x15b8, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, + 0x080c, 0x9c82, 0x0005, 0x009e, 0x080c, 0x193e, 0x0804, 0xb5ca, + 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x000b, 0x0005, 0xb657, + 0xb576, 0xb659, 0xb657, 0xb659, 0xb659, 0xb572, 0xb657, 0xb56c, + 0xb56c, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0xb657, 0x080c, + 0x0d65, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, 0x00ff, 0x00be, + 0x908a, 0x000c, 0x1a0c, 0x0d65, 0x00b6, 0x0013, 0x00be, 0x0005, + 0xb674, 0xb741, 0xb676, 0xb6b6, 0xb676, 0xb6b6, 0xb676, 0xb684, + 0xb674, 0xb6b6, 0xb674, 0xb6a5, 0x080c, 0x0d65, 0x6004, 0x908e, + 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, 0x0002, 0x0590, + 0x908e, 0x0052, 0x0904, 0xb73d, 0x6004, 0x080c, 0xba85, 0x0904, + 0xb75a, 0x908e, 0x0004, 0x1110, 0x080c, 0x305d, 0x908e, 0x0021, + 0x0904, 0xb75e, 0x908e, 0x0022, 0x0904, 0xb7a5, 0x908e, 0x003d, + 0x0904, 0xb75e, 0x908e, 0x0039, 0x0904, 0xb762, 0x908e, 0x0035, + 0x0904, 0xb762, 0x908e, 0x001e, 0x0178, 0x908e, 0x0001, 0x1140, + 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x0110, + 0x080c, 0x302e, 0x080c, 0xa59c, 0x0804, 0x9c20, 0x00c6, 0x00d6, + 0x6104, 0x9186, 0x0016, 0x0904, 0xb72e, 0x9186, 0x0002, 0x1904, + 0xb703, 0x2001, 0x1836, 0x2004, 0xd08c, 0x11c8, 0x080c, 0x70ba, + 0x11b0, 0x080c, 0xbf8f, 0x0138, 0x080c, 0x70dd, 0x1120, 0x080c, + 0x6fc5, 0x0804, 0xb78e, 0x2001, 0x1955, 0x2003, 0x0001, 0x2001, + 0x1800, 0x2003, 0x0001, 0x080c, 0x6feb, 0x0804, 0xb78e, 0x6010, + 0x2058, 0x2001, 0x1836, 0x2004, 0xd0ac, 0x1904, 0xb78e, 0xb8a0, + 0x9084, 0xff80, 0x1904, 0xb78e, 0xb840, 0x9084, 0x00ff, 0x9005, + 0x0190, 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, + 0x0398, 0x604b, 0x0000, 0x080c, 0x9b90, 0x0128, 0x2b00, 0x6012, + 0x6023, 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, + 0x11a0, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, + 0x1836, 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, + 0x5c8a, 0x00ee, 0x080c, 0xa59c, 0x0030, 0x080c, 0xa59c, 0x080c, + 0x302e, 0x080c, 0xbfa4, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, + 0x305d, 0x012e, 0x00ee, 0x080c, 0x9c20, 0x0005, 0x2001, 0x0002, + 0x080c, 0x61e0, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x84ee, + 0x080c, 0x894f, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x305d, 0x0804, + 0xb6b2, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, + 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xb703, 0x8001, + 0xb842, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, 0x00de, + 0x00ce, 0x0898, 0x080c, 0xa59c, 0x0804, 0xb6b4, 0x080c, 0xa5d8, + 0x0804, 0xb6b4, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xbf07, 0x00de, + 0x0118, 0x080c, 0x9be6, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, + 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, + 0x0002, 0x603c, 0x600a, 0x2001, 0x195f, 0x2004, 0x601a, 0x602c, + 0x2c08, 0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, + 0x2160, 0x2009, 0x8020, 0x080c, 0x84e7, 0x0005, 0x00de, 0x00ce, + 0x080c, 0xa59c, 0x080c, 0x302e, 0x00e6, 0x0126, 0x2091, 0x8000, + 0x080c, 0x305d, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, + 0x604b, 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xa020, 0x1904, + 0xb75a, 0x0005, 0x6000, 0x908a, 0x0016, 0x1a0c, 0x0d65, 0x0096, + 0x00d6, 0x001b, 0x00de, 0x009e, 0x0005, 0xb7c5, 0xb7c5, 0xb7c5, + 0xb7c5, 0xb7c5, 0xb7c5, 0xb7c5, 0xb7c5, 0xb7c5, 0xb571, 0xb7c5, + 0xb576, 0xb7c7, 0xb576, 0xb7e1, 0xb7c5, 0x080c, 0x0d65, 0x6004, + 0x9086, 0x008b, 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, + 0x0035, 0x1130, 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, + 0x6007, 0x008b, 0x6003, 0x000d, 0x2009, 0x8020, 0x080c, 0x84e7, + 0x0005, 0x080c, 0xbf83, 0x0118, 0x080c, 0xbf96, 0x0010, 0x080c, + 0xbfa4, 0x080c, 0xba5f, 0x080c, 0xb870, 0x0570, 0x080c, 0x302e, + 0x080c, 0xb870, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, + 0x0006, 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x69b5, + 0x2c68, 0x080c, 0x9b90, 0x0150, 0x6810, 0x6012, 0x080c, 0xbd09, + 0x00c6, 0x2d60, 0x080c, 0x9c20, 0x00ce, 0x0008, 0x2d60, 0x6017, + 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x84ee, 0x080c, 0x894f, 0x00c8, 0x080c, 0xbf83, 0x0138, 0x6034, + 0x9086, 0x4000, 0x1118, 0x080c, 0x302e, 0x08d0, 0x6034, 0x908c, + 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, + 0x080c, 0x302e, 0x0868, 0x080c, 0x9c20, 0x0005, 0x6000, 0x908a, + 0x0016, 0x1a0c, 0x0d65, 0x0002, 0xb84c, 0xb84c, 0xb84e, 0xb84e, + 0xb84e, 0xb84c, 0xb84c, 0x9c20, 0xb84c, 0xb84c, 0xb84c, 0xb84c, + 0xb84c, 0xb84c, 0xb84c, 0xb84c, 0x080c, 0x0d65, 0x080c, 0x98c7, + 0x080c, 0x9a38, 0x080c, 0x98e3, 0x6114, 0x0096, 0x2148, 0xa87b, + 0x0006, 0x080c, 0x69b5, 0x009e, 0x0804, 0x9be6, 0x9284, 0x0003, + 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001, 0x1819, 0x2004, 0x9202, + 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, + 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, + 0x9086, 0xf000, 0x0110, 0x080c, 0x10da, 0x000e, 0x009e, 0x0005, + 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, + 0x1ddc, 0x2071, 0x1800, 0x7350, 0x7070, 0x9302, 0x1640, 0x6020, + 0x9206, 0x11f8, 0x080c, 0xbf8f, 0x0180, 0x9286, 0x0001, 0x1168, + 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x302e, 0x080c, 0xbfa4, + 0x00c6, 0x080c, 0x9c20, 0x00ce, 0x0060, 0x080c, 0xbc7b, 0x0148, + 0x080c, 0xba85, 0x1110, 0x080c, 0xa59c, 0x00c6, 0x080c, 0x9be6, + 0x00ce, 0x9ce0, 0x001c, 0x7064, 0x9c02, 0x1208, 0x08a0, 0x012e, + 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, + 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, 0x1b09, 0x6112, + 0x080c, 0x302e, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, + 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9b90, + 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, 0x53b0, 0x0118, 0x080c, + 0xb9a1, 0x0168, 0x080c, 0xbd09, 0x6023, 0x0003, 0x2009, 0x004b, + 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0x9c55, + 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, 0x080c, 0xbd09, 0x6023, + 0x0003, 0x0016, 0x080c, 0x98c7, 0x080c, 0x8658, 0x0076, 0x903e, + 0x080c, 0x853d, 0x2c08, 0x080c, 0xd011, 0x007e, 0x080c, 0x98e3, + 0x001e, 0xd184, 0x0128, 0x080c, 0x9be6, 0x9085, 0x0001, 0x0070, + 0x080c, 0x53b0, 0x0128, 0xd18c, 0x1170, 0x080c, 0xb9a1, 0x0148, + 0x2009, 0x004c, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, 0x0c90, 0x2009, 0x004d, + 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, 0x0046, 0x0016, 0x080c, + 0x9b90, 0x2c78, 0x0590, 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, + 0x2021, 0x0005, 0x080c, 0xb9b3, 0x9186, 0x004d, 0x0118, 0x9186, + 0x004e, 0x0148, 0x2001, 0x1958, 0x200c, 0xd1fc, 0x0168, 0x2f60, + 0x080c, 0x9be6, 0x00d0, 0x2001, 0x1957, 0x200c, 0xd1fc, 0x0120, + 0x2f60, 0x080c, 0x9be6, 0x0088, 0x2f60, 0x080c, 0x53b0, 0x0138, + 0xd18c, 0x1118, 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, + 0x0016, 0x080c, 0x9c82, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, + 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x080c, 0x9b90, 0x2c78, + 0x0508, 0x7e5e, 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, + 0x0004, 0x0489, 0x009e, 0x2001, 0x1956, 0x200c, 0xd1fc, 0x0120, + 0x2f60, 0x080c, 0x9be6, 0x0060, 0x2f60, 0x080c, 0x53b0, 0x0120, + 0xd18c, 0x1160, 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0x9c82, + 0x9085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, + 0x0c98, 0x00c6, 0x080c, 0x489a, 0x00ce, 0x1120, 0x080c, 0x9be6, + 0x9006, 0x0005, 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, + 0x9085, 0x0001, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, + 0x080c, 0x98c7, 0x080c, 0x6471, 0x0158, 0x2001, 0xb9ba, 0x0006, + 0x900e, 0x2400, 0x080c, 0x6bc6, 0x080c, 0x69b5, 0x000e, 0x0807, + 0x2418, 0x080c, 0x8857, 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, + 0x0001, 0x2608, 0x080c, 0x8672, 0x008e, 0x080c, 0x853d, 0x2f08, + 0x2648, 0x080c, 0xd011, 0xb93c, 0x81ff, 0x090c, 0x8749, 0x080c, + 0x98e3, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x080c, 0x9b90, 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, + 0xbd09, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, + 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9c55, 0x01b8, 0x660a, + 0x2b08, 0x6112, 0x080c, 0xbd09, 0x6023, 0x0008, 0x2900, 0x6016, + 0x00f6, 0x2c78, 0x080c, 0x1669, 0x00fe, 0x2009, 0x0021, 0x080c, + 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, + 0x2009, 0x003d, 0x00c6, 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, + 0x9b90, 0x0198, 0x660a, 0x2b08, 0x6112, 0x080c, 0xbd09, 0x6023, + 0x0001, 0x2900, 0x6016, 0x001e, 0x0016, 0x080c, 0x9c82, 0x9085, + 0x0001, 0x001e, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x9c55, 0x0188, 0x2b08, 0x6112, + 0x080c, 0xbd09, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, + 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, + 0x0cd8, 0x2009, 0x0044, 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, + 0x00b6, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0118, 0x8211, 0xba3e, + 0x1140, 0xb8c0, 0x9005, 0x0128, 0xb888, 0x9005, 0x1110, 0xb88b, + 0x0001, 0x00be, 0x002e, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, + 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, + 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, + 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, 0x904d, 0x080c, 0xb870, + 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, + 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, + 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x080c, 0x9c55, 0x0198, 0x2b08, 0x6112, + 0x080c, 0xbd09, 0x6023, 0x0001, 0x2900, 0x6016, 0x080c, 0x302e, + 0x2009, 0x0028, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, 0x11a8, 0x2011, 0x1823, + 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, 0x080c, 0xa827, 0x00be, + 0x080c, 0xaa66, 0x6003, 0x0001, 0x6007, 0x0029, 0x080c, 0x84ee, + 0x080c, 0x894f, 0x0078, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, + 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, 0xbec8, 0x080c, 0xa59c, + 0x080c, 0x9be6, 0x0005, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d65, + 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, + 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x69b5, 0x012e, + 0x009e, 0x080c, 0x9be6, 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, + 0x2001, 0x0004, 0x080c, 0x61e0, 0x00e8, 0x9186, 0x0015, 0x1510, + 0x2011, 0x1823, 0x2204, 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, + 0x2058, 0x080c, 0x632a, 0x00be, 0x080c, 0xab37, 0x1198, 0x6010, + 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, + 0x080c, 0x61e0, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, + 0x9ff4, 0x0048, 0x6014, 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, + 0xa59c, 0x080c, 0x9be6, 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, + 0x904d, 0x090c, 0x0d65, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, + 0x4000, 0x900e, 0x080c, 0x6582, 0x1108, 0xc185, 0xb800, 0xd0bc, + 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, 0x8000, 0x080c, 0x69b5, + 0x012e, 0x080c, 0x9be6, 0x08f8, 0x6014, 0x904d, 0x090c, 0x0d65, + 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, + 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, 0x080c, 0x69b5, 0x012e, + 0x080c, 0x9be6, 0x0840, 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, + 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, 0x604b, 0x0000, 0x6017, + 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, + 0x84e7, 0x0005, 0x00c6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x0130, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, + 0x00ce, 0x0005, 0xb571, 0xbbac, 0xbbac, 0xbbaf, 0xd30b, 0xd326, + 0xd329, 0xb571, 0xb571, 0xb571, 0xb571, 0xb571, 0xb571, 0xb571, + 0xb571, 0xb571, 0x080c, 0x0d65, 0xa001, 0xa001, 0x0005, 0x0096, + 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, + 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, + 0x0550, 0x2001, 0x1833, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, + 0x080c, 0x9b90, 0x0508, 0x7810, 0x6012, 0x080c, 0xbd09, 0x7820, + 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, + 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, + 0x0035, 0x6003, 0x0001, 0x795c, 0x615e, 0x2009, 0x8020, 0x080c, + 0x84e7, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1960, + 0x2004, 0x604a, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, 0x681c, + 0xd0fc, 0xc0fc, 0x681e, 0xa87c, 0x1108, 0xd0e4, 0x0180, 0xc0e4, + 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, + 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, 0x080c, 0x0fe1, 0x6830, + 0x6036, 0x908e, 0x0001, 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, + 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, + 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, + 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, + 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, + 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, 0x695c, 0x615e, 0x6023, + 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, + 0x84e7, 0x009e, 0x001e, 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, + 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, + 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, + 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, + 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, + 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, + 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, + 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, + 0x0037, 0x0170, 0x908e, 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, + 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, + 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, + 0x2001, 0x195a, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, + 0x842f, 0x2001, 0x195e, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, + 0x2001, 0x195c, 0x200c, 0x8000, 0x2014, 0x2071, 0x1944, 0x711a, + 0x721e, 0x2001, 0x0064, 0x080c, 0x842f, 0x2001, 0x195f, 0x82ff, + 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1960, 0x9288, 0x000a, + 0x2102, 0x2001, 0x0017, 0x080c, 0x98b8, 0x2001, 0x1a60, 0x2102, + 0x2001, 0x0032, 0x080c, 0x15b8, 0x080c, 0x666b, 0x00ee, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, + 0x195e, 0x2003, 0x0028, 0x2001, 0x195f, 0x2003, 0x0014, 0x2071, + 0x1944, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1960, 0x2009, + 0x001e, 0x2102, 0x2001, 0x0017, 0x080c, 0x98b8, 0x2001, 0x1a60, + 0x2102, 0x2001, 0x0032, 0x080c, 0x15b8, 0x00ee, 0x001e, 0x000e, + 0x0005, 0x0096, 0x6060, 0x904d, 0x0110, 0x080c, 0x1061, 0x009e, + 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9b90, + 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, + 0x2009, 0x0033, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, + 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, + 0x9186, 0x0015, 0x1500, 0x708c, 0x9086, 0x0018, 0x11e0, 0x6014, + 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x8a0e, 0x01d8, + 0x7078, 0xaa50, 0x9206, 0x1160, 0x707c, 0xaa54, 0x9206, 0x1140, + 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, 0x307d, + 0x080c, 0x9ff4, 0x0020, 0x080c, 0xa59c, 0x080c, 0x9be6, 0x00fe, + 0x00ee, 0x009e, 0x0005, 0x705c, 0xaa54, 0x9206, 0x0d48, 0x0c80, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0x9b90, 0x0188, 0x2b08, + 0x6112, 0x080c, 0xbd09, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, + 0x004d, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, + 0x9b90, 0x0180, 0x2b08, 0x6112, 0x080c, 0xbd09, 0x6023, 0x0001, + 0x2900, 0x6016, 0x001e, 0x080c, 0x9c82, 0x9085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, + 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, + 0x9186, 0x0015, 0x1568, 0x718c, 0x6014, 0x2048, 0xa814, 0x8003, + 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x1978, 0x2003, 0x0000, + 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, + 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, + 0x1978, 0x0016, 0x200c, 0x080c, 0xc581, 0x001e, 0xa804, 0x9005, + 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, + 0x080c, 0xa59c, 0x080c, 0x9be6, 0x00fe, 0x00ee, 0x009e, 0x006e, + 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, + 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x708c, 0x9086, + 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x8a0e, 0x01a8, + 0x7078, 0xaa74, 0x9206, 0x1130, 0x707c, 0xaa78, 0x9206, 0x1110, + 0x080c, 0x302e, 0x080c, 0x9ff4, 0x0020, 0x080c, 0xa59c, 0x080c, + 0x9be6, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x705c, 0xaa78, 0x9206, + 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, + 0x0015, 0x1550, 0x708c, 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, + 0x2c78, 0x080c, 0x8a0e, 0x05f0, 0x7078, 0xaacc, 0x9206, 0x1180, + 0x707c, 0xaad0, 0x9206, 0x1160, 0x080c, 0x302e, 0x0016, 0xa998, + 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5360, 0x001e, 0x0010, + 0x080c, 0x5149, 0x080c, 0xb870, 0x0508, 0xa87b, 0x0000, 0xa883, + 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xb870, 0x01b8, 0x6014, + 0x2048, 0x080c, 0x5149, 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, + 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, + 0x0139, 0x080c, 0x69b5, 0x012e, 0x080c, 0x9be6, 0x00fe, 0x00ee, + 0x009e, 0x0005, 0x705c, 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, + 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, + 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, + 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, + 0x0036, 0x080c, 0xb870, 0x0904, 0xbec4, 0x0096, 0x6314, 0x2348, + 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, + 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6582, 0x1108, + 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, + 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8b4, + 0x20e0, 0xb8b8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fac, 0x20a9, + 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8b8, 0x9080, 0x000a, + 0x2098, 0x080c, 0x0fac, 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, + 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, + 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, 0x080c, + 0x69a9, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, 0x00be, 0x0005, + 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, 0x6214, 0x2248, + 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000, 0x11a0, 0xb814, + 0x9084, 0x00ff, 0x900e, 0x080c, 0x2459, 0x2118, 0x831f, 0x939c, + 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, 0x2011, 0x8018, + 0x080c, 0x48fa, 0x00a8, 0x9096, 0x0001, 0x1148, 0x89ff, 0x0180, + 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x0048, 0x9096, + 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, + 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, 0x0005, 0x00c6, + 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, 0x0008, 0x6a2c, + 0x080c, 0xb85e, 0x01f0, 0x2260, 0x6120, 0x9186, 0x0003, 0x0118, + 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, 0x683c, 0x9206, + 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, 0x6008, 0x693c, + 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, 0x002e, 0x00ce, + 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, 0x0188, 0x918c, + 0x00ff, 0x918e, 0x0002, 0x1160, 0xa9a8, 0x918c, 0x0f00, 0x810f, + 0x918e, 0x0001, 0x1128, 0xa834, 0xa938, 0x9115, 0x190c, 0xaed1, + 0x0005, 0x0036, 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, + 0x01e0, 0x080c, 0xb870, 0x01c8, 0x080c, 0xba5f, 0x6037, 0x4000, + 0x6014, 0x6017, 0x0000, 0x0096, 0x2048, 0xa87c, 0x080c, 0xba85, + 0x1118, 0x080c, 0xa59c, 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, + 0x83ff, 0x1129, 0x080c, 0x69b5, 0x009e, 0x003e, 0x0005, 0xa880, + 0xd0b4, 0x0128, 0xa87b, 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, + 0x0118, 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xbb79, + 0xa877, 0x0000, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, + 0x0006, 0x2001, 0x1810, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, + 0x2001, 0x1810, 0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, + 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, + 0x4a97, 0x004e, 0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, + 0x195e, 0x2004, 0x601a, 0x0005, 0x2001, 0x1960, 0x2004, 0x604a, + 0x0005, 0x080c, 0x9be6, 0x0804, 0x894f, 0x611c, 0xd1fc, 0xa97c, + 0x1108, 0xd1e4, 0x0005, 0x601c, 0xd0fc, 0xa87c, 0x1108, 0xd0e4, + 0x0005, 0x601c, 0xd0fc, 0xc0fc, 0x601e, 0xa87c, 0x1108, 0xd0e4, + 0x0005, 0x6044, 0xd0fc, 0x1138, 0xd0bc, 0x0198, 0xc0bc, 0x6046, + 0x6003, 0x0002, 0x0070, 0xd0ac, 0x1160, 0xd0dc, 0x1128, 0x908c, + 0x000f, 0x9186, 0x0005, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, + 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0016, 0x1a0c, + 0x0d65, 0x001b, 0x006e, 0x00be, 0x0005, 0xbffd, 0xc6dc, 0xc82b, + 0xbffd, 0xbffd, 0xbffd, 0xbffd, 0xbffd, 0xc034, 0xc8af, 0xbffd, + 0xbffd, 0xbffd, 0xbffd, 0xbffd, 0xbffd, 0x080c, 0x0d65, 0x0066, + 0x6000, 0x90b2, 0x0016, 0x1a0c, 0x0d65, 0x0013, 0x006e, 0x0005, + 0xc018, 0xcdd0, 0xc018, 0xc018, 0xc018, 0xc018, 0xc018, 0xc018, + 0xcd7f, 0xce22, 0xc018, 0xd446, 0xd47a, 0xd446, 0xd47a, 0xc018, + 0x080c, 0x0d65, 0x6000, 0x9082, 0x0016, 0x1a0c, 0x0d65, 0x6000, + 0x000a, 0x0005, 0xc032, 0xca8c, 0xcb57, 0xcb7a, 0xcbf6, 0xc032, + 0xccf1, 0xcc7e, 0xc8b9, 0xcd57, 0xcd6c, 0xc032, 0xc032, 0xc032, + 0xc032, 0xc032, 0x080c, 0x0d65, 0x91b2, 0x0053, 0x1a0c, 0x0d65, + 0x2100, 0x91b2, 0x0040, 0x1a04, 0xc47f, 0x0002, 0xc07e, 0xc270, + 0xc07e, 0xc07e, 0xc07e, 0xc279, 0xc07e, 0xc07e, 0xc07e, 0xc07e, + 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, + 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc080, 0xc0e7, 0xc0f6, + 0xc15a, 0xc185, 0xc1fd, 0xc25b, 0xc07e, 0xc07e, 0xc27c, 0xc07e, + 0xc07e, 0xc291, 0xc29e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, + 0xc321, 0xc07e, 0xc07e, 0xc335, 0xc07e, 0xc07e, 0xc2f0, 0xc07e, + 0xc07e, 0xc07e, 0xc34d, 0xc07e, 0xc07e, 0xc07e, 0xc3ca, 0xc07e, + 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc07e, 0xc447, 0x080c, 0x0d65, + 0x080c, 0x6648, 0x1150, 0x2001, 0x1836, 0x2004, 0xd0cc, 0x1128, + 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, + 0x0009, 0x6017, 0x0000, 0x0804, 0xc269, 0x080c, 0x6631, 0x00e6, + 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, + 0x2019, 0x0029, 0x080c, 0x98c7, 0x080c, 0x8658, 0x0076, 0x903e, + 0x080c, 0x853d, 0x2c08, 0x080c, 0xd011, 0x007e, 0x001e, 0x080c, + 0x98e3, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, + 0x080c, 0x629e, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, + 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, + 0x080c, 0xd5f2, 0x002e, 0x001e, 0x1178, 0x080c, 0xcf40, 0x1904, + 0xc152, 0x080c, 0xcedc, 0x1120, 0x6007, 0x0008, 0x0804, 0xc269, + 0x6007, 0x0009, 0x0804, 0xc269, 0x080c, 0xd147, 0x0128, 0x080c, + 0xcf40, 0x0d78, 0x0804, 0xc152, 0x6017, 0x1900, 0x0c88, 0x080c, + 0x3164, 0x1904, 0xc47c, 0x6106, 0x080c, 0xce8d, 0x6007, 0x0006, + 0x0804, 0xc269, 0x6007, 0x0007, 0x0804, 0xc269, 0x080c, 0xd4b6, + 0x1904, 0xc47c, 0x080c, 0x3164, 0x1904, 0xc47c, 0x00d6, 0x6610, + 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, + 0x0001, 0x080c, 0x61cc, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, + 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, + 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, + 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, + 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, + 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, + 0x080c, 0xcfa7, 0x1190, 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, + 0x2258, 0xbaa0, 0x900e, 0x080c, 0x307d, 0x002e, 0x080c, 0x632a, + 0x6007, 0x000a, 0x00de, 0x0804, 0xc269, 0x6007, 0x000b, 0x00de, + 0x0804, 0xc269, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x6007, 0x0001, + 0x0804, 0xc269, 0x080c, 0xd4b6, 0x1904, 0xc47c, 0x080c, 0x3164, + 0x1904, 0xc47c, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, + 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, + 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, + 0xbaa0, 0x900e, 0x080c, 0x307d, 0x002e, 0x6007, 0x000c, 0x2001, + 0x0001, 0x080c, 0xd5d2, 0x0804, 0xc269, 0x080c, 0x6648, 0x1140, + 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, + 0x0804, 0xc08d, 0x080c, 0x6631, 0x6610, 0x2658, 0xbe04, 0x9684, + 0x00ff, 0x9082, 0x0006, 0x06c0, 0x1138, 0x0026, 0x2001, 0x0006, + 0x080c, 0x620c, 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, + 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xc152, 0x080c, 0xcfb4, + 0x1120, 0x6007, 0x000e, 0x0804, 0xc269, 0x0046, 0x6410, 0x2458, + 0xbca0, 0x0046, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x004e, 0x0016, + 0x9006, 0x2009, 0x185c, 0x210c, 0x0048, 0x2009, 0x0029, 0x080c, + 0xd2bc, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, + 0x6007, 0x0001, 0x0804, 0xc269, 0x2001, 0x0001, 0x080c, 0x61cc, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, + 0x2011, 0x0270, 0x080c, 0xabda, 0x003e, 0x002e, 0x001e, 0x015e, + 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, + 0xc152, 0x9682, 0x0007, 0x0a04, 0xc1ae, 0x0804, 0xc152, 0x6017, + 0x1900, 0x6007, 0x0009, 0x0804, 0xc269, 0x080c, 0x6648, 0x1140, + 0x2001, 0x1836, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, + 0x0804, 0xc08d, 0x080c, 0x6631, 0x6610, 0x2658, 0xbe04, 0x9684, + 0x00ff, 0x0006, 0x9086, 0x0001, 0x000e, 0x0170, 0x9082, 0x0006, + 0x0690, 0x0150, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, + 0x9686, 0x0006, 0x1904, 0xc152, 0x080c, 0xcfe2, 0x1130, 0x080c, + 0xcedc, 0x1118, 0x6007, 0x0010, 0x04e0, 0x0046, 0x6410, 0x2458, + 0xbca0, 0x0046, 0x080c, 0x302e, 0x080c, 0xbfa4, 0x004e, 0x0016, + 0x9006, 0x2009, 0x185c, 0x210c, 0x0048, 0x2009, 0x0029, 0x080c, + 0xd2bc, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, + 0x6007, 0x0001, 0x00f0, 0x080c, 0xd147, 0x0140, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0980, 0x0804, 0xc152, 0x6017, 0x1900, + 0x6007, 0x0009, 0x0070, 0x080c, 0x3164, 0x1904, 0xc47c, 0x080c, + 0xd4b6, 0x1904, 0xc47c, 0x080c, 0xc61c, 0x1904, 0xc152, 0x6007, + 0x0012, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, 0x0005, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, + 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, 0xd4b6, 0x1904, 0xc47c, + 0x080c, 0x3164, 0x1904, 0xc47c, 0x080c, 0xc61c, 0x1904, 0xc152, + 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, + 0x0005, 0x080c, 0x3164, 0x1904, 0xc47c, 0x6007, 0x0023, 0x6003, + 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, 0x0005, 0x080c, 0xd4b6, + 0x1904, 0xc47c, 0x080c, 0x3164, 0x1904, 0xc47c, 0x080c, 0xc61c, + 0x1904, 0xc152, 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x7244, + 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xb85e, 0x01b0, 0x2260, + 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, + 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xd28e, + 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, + 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, + 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, + 0x1110, 0x080c, 0x9be6, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, + 0x080c, 0x84ee, 0x080c, 0x894f, 0x00ee, 0x002e, 0x001e, 0x0005, + 0x2001, 0x0001, 0x080c, 0x61cc, 0x0156, 0x0016, 0x0026, 0x0036, + 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xabda, + 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, + 0xc269, 0x080c, 0xa83f, 0x080c, 0x70ba, 0x1190, 0x0006, 0x0026, + 0x0036, 0x080c, 0x70d4, 0x1138, 0x080c, 0x73b9, 0x080c, 0x5cf7, + 0x080c, 0x6feb, 0x0010, 0x080c, 0x708e, 0x003e, 0x002e, 0x000e, + 0x0005, 0x080c, 0x3164, 0x1904, 0xc47c, 0x080c, 0xc61c, 0x1904, + 0xc152, 0x6106, 0x080c, 0xc638, 0x1120, 0x6007, 0x002b, 0x0804, + 0xc269, 0x6007, 0x002c, 0x0804, 0xc269, 0x080c, 0xd4b6, 0x1904, + 0xc47c, 0x080c, 0x3164, 0x1904, 0xc47c, 0x080c, 0xc61c, 0x1904, + 0xc152, 0x6106, 0x080c, 0xc63d, 0x1120, 0x6007, 0x002e, 0x0804, + 0xc269, 0x6007, 0x002f, 0x0804, 0xc269, 0x080c, 0x3164, 0x1904, + 0xc47c, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, + 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, + 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xc270, 0x080c, + 0x53ac, 0xd0e4, 0x0904, 0xc3c7, 0x2071, 0x026c, 0x7010, 0x603a, + 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x6686, 0x0140, 0x6010, + 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, + 0x6682, 0x15b8, 0x2069, 0x1800, 0x687c, 0x9206, 0x1590, 0x6878, + 0x9106, 0x1578, 0x7210, 0x080c, 0xb85e, 0x0590, 0x080c, 0xc507, + 0x0578, 0x080c, 0xd338, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, + 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, 0x00ce, 0x00de, 0x00ee, + 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xb85e, 0x01c0, + 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, + 0x2c08, 0x9085, 0x0001, 0x080c, 0xd28e, 0x2c10, 0x2160, 0x0140, + 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, + 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, + 0x0012, 0x0868, 0x080c, 0x3164, 0x1904, 0xc47c, 0x6010, 0x2058, + 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xc270, + 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x53ac, 0xd0e4, 0x0904, 0xc43f, + 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, + 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, + 0x080c, 0xd28e, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xb85e, 0x05d0, + 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, + 0x2260, 0x080c, 0xb451, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, + 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, + 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, + 0xc507, 0x0904, 0xc3c0, 0x0056, 0x7510, 0x7614, 0x080c, 0xd351, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, + 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, + 0x84e7, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, + 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, 0x0c10, 0x6007, + 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xc397, 0x00e6, + 0x0026, 0x080c, 0x6648, 0x0550, 0x080c, 0x6631, 0x080c, 0xd528, + 0x1518, 0x2071, 0x1800, 0x70d8, 0x9085, 0x0003, 0x70da, 0x00f6, + 0x2079, 0x0100, 0x72ac, 0x9284, 0x00ff, 0x707a, 0x78e6, 0x9284, + 0xff00, 0x727c, 0x9205, 0x707e, 0x78ea, 0x00fe, 0x70e3, 0x0000, + 0x080c, 0x6686, 0x0120, 0x2011, 0x19e1, 0x2013, 0x07d0, 0xd0ac, + 0x1128, 0x080c, 0x2e09, 0x0010, 0x080c, 0xd55a, 0x002e, 0x00ee, + 0x080c, 0x9be6, 0x0804, 0xc26f, 0x080c, 0x9be6, 0x0005, 0x2600, + 0x0002, 0xc493, 0xc493, 0xc493, 0xc493, 0xc493, 0xc495, 0xc493, + 0xc493, 0xc493, 0xc493, 0xc4b2, 0xc493, 0xc493, 0xc493, 0xc4c4, + 0xc4d1, 0xc502, 0xc493, 0x080c, 0x0d65, 0x080c, 0xd4b6, 0x1d20, + 0x080c, 0x3164, 0x1d08, 0x080c, 0xc61c, 0x1148, 0x7038, 0x6016, + 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x84ee, 0x0005, 0x080c, + 0x302e, 0x080c, 0xbfa4, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, + 0x84ee, 0x0005, 0x080c, 0xd4b6, 0x1938, 0x080c, 0x3164, 0x1920, + 0x080c, 0xc61c, 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, + 0x0001, 0x080c, 0x84ee, 0x0005, 0x080c, 0xc524, 0x0904, 0xc47c, + 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, 0x894f, + 0x0005, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, 0x00ff, + 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, 0x1995, + 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x1996, 0x2004, 0x9106, + 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, 0x0004, + 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xabee, 0x009e, + 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ee, 0x080c, + 0x894f, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, 0x0016, + 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, 0x2058, + 0xb8c4, 0xd084, 0x0150, 0x7128, 0x6050, 0x9106, 0x1120, 0x712c, + 0x604c, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, + 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, 0x0086, 0x00e6, + 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x708c, + 0x908a, 0x00f9, 0x16e8, 0x20e1, 0x0000, 0x2001, 0x1978, 0x2003, + 0x0000, 0x080c, 0x1048, 0x05a0, 0x2900, 0x6016, 0x708c, 0x8004, + 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x1978, + 0x0016, 0x200c, 0x0471, 0x001e, 0x2940, 0x080c, 0x1048, 0x01c0, + 0x2900, 0xa006, 0x2100, 0x81ff, 0x0180, 0x0c18, 0xa832, 0x20a8, + 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x1978, + 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, + 0x2071, 0x1800, 0x708f, 0x0000, 0x6014, 0x2048, 0x080c, 0x0fe1, + 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, + 0x11a8, 0x080c, 0x2054, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, + 0x9312, 0x1218, 0x23a8, 0x4003, 0x00f8, 0x20a8, 0x4003, 0x22a8, + 0x8108, 0x080c, 0x2054, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x2054, + 0x2061, 0x1978, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x1218, + 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, + 0x2054, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x1978, 0x2019, 0x0280, + 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, + 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, + 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, + 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x206c, 0x20a1, 0x024c, + 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, + 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x206c, + 0x20a1, 0x0240, 0x0c98, 0x080c, 0x206c, 0x2061, 0x197b, 0x6004, + 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, + 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x206c, + 0x20a1, 0x0240, 0x0c98, 0x2061, 0x197b, 0x2019, 0x0260, 0x3400, + 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, + 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, + 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, 0x2658, + 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, + 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, + 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, 0x0005, + 0x00d6, 0x080c, 0xc6b2, 0x00de, 0x0005, 0x00d6, 0x080c, 0xc6bf, + 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, + 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xd5d2, + 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, + 0x6824, 0x080c, 0x2459, 0x1148, 0x2001, 0x0001, 0x080c, 0xd5d2, + 0x2110, 0x900e, 0x080c, 0x307d, 0x0018, 0x9085, 0x0001, 0x0008, + 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0x9c55, 0x0598, + 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, + 0x080c, 0x2459, 0x1568, 0x080c, 0x622f, 0x1550, 0xbe12, 0xbd16, + 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xd4b6, 0x11c8, + 0x080c, 0x3164, 0x11b0, 0x080c, 0xc61c, 0x0500, 0x2001, 0x0007, + 0x080c, 0x61e0, 0x2001, 0x0007, 0x080c, 0x620c, 0x6017, 0x0000, + 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x84ee, + 0x0010, 0x080c, 0x9be6, 0x9085, 0x0001, 0x00ce, 0x00be, 0x0005, + 0x080c, 0x9be6, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, 0x9be6, + 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, 0x1228, + 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, 0x6017, + 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, 0x0800, + 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, 0x1158, + 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162, 0x908e, 0x0014, + 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, 0x1a0c, + 0x0d65, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, 0x1a04, + 0xc7ff, 0x0092, 0x91b6, 0x0027, 0x0120, 0x91b6, 0x0014, 0x190c, + 0x0d65, 0x2001, 0x0007, 0x080c, 0x620c, 0x080c, 0x8891, 0x080c, + 0x9c20, 0x080c, 0x894f, 0x0005, 0xc73c, 0xc73e, 0xc73c, 0xc73c, + 0xc73c, 0xc73e, 0xc74b, 0xc7fc, 0xc79b, 0xc7fc, 0xc7ad, 0xc7fc, + 0xc74b, 0xc7fc, 0xc7f4, 0xc7fc, 0xc7f4, 0xc7fc, 0xc7fc, 0xc73c, + 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0xc73c, + 0xc73c, 0xc73c, 0xc73e, 0xc73c, 0xc7fc, 0xc73c, 0xc73c, 0xc7fc, + 0xc73c, 0xc7f9, 0xc7fc, 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0xc7fc, + 0xc7fc, 0xc73c, 0xc7fc, 0xc7fc, 0xc73c, 0xc746, 0xc73c, 0xc73c, + 0xc73c, 0xc73c, 0xc7f8, 0xc7fc, 0xc73c, 0xc73c, 0xc7fc, 0xc7fc, + 0xc73c, 0xc73c, 0xc73c, 0xc73c, 0x080c, 0x0d65, 0x080c, 0xbfa7, + 0x6003, 0x0002, 0x080c, 0x894f, 0x0804, 0xc7fe, 0x9006, 0x080c, + 0x61cc, 0x0804, 0xc7fc, 0x080c, 0x6682, 0x1904, 0xc7fc, 0x9006, + 0x080c, 0x61cc, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, + 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x0428, + 0x6010, 0x2058, 0xb884, 0x9005, 0x1178, 0x080c, 0xbf8f, 0x1904, + 0xc7fc, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0007, 0x080c, 0x4a97, + 0x004e, 0x003e, 0x0804, 0xc7fc, 0x080c, 0x3195, 0x1904, 0xc7fc, + 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, 0x00f6, 0x2079, + 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x2001, 0x0002, 0x080c, + 0x61e0, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x84ee, 0x080c, 0x894f, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, + 0x817a, 0x0804, 0xc7fe, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x0904, 0xc7fc, 0x9686, 0x0004, 0x0904, + 0xc7fc, 0x2001, 0x0004, 0x0804, 0xc7fa, 0x2001, 0x1800, 0x2004, + 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, + 0x2021, 0x0006, 0x080c, 0x4a97, 0x004e, 0x003e, 0x2001, 0x0006, + 0x080c, 0xc818, 0x6610, 0x2658, 0xbe04, 0x0066, 0x96b4, 0xff00, + 0x8637, 0x9686, 0x0006, 0x006e, 0x0168, 0x2001, 0x0006, 0x080c, + 0x620c, 0x9284, 0x00ff, 0x908e, 0x0007, 0x1120, 0x2001, 0x0006, + 0x080c, 0x61e0, 0x080c, 0x6682, 0x11f8, 0x2001, 0x1836, 0x2004, + 0xd0a4, 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, + 0x00f6, 0x2079, 0x1800, 0x78a4, 0x8000, 0x78a6, 0x00fe, 0x0804, + 0xc785, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, + 0x0018, 0x0010, 0x080c, 0x620c, 0x080c, 0x9be6, 0x0005, 0x2600, + 0x0002, 0xc813, 0xc813, 0xc813, 0xc813, 0xc813, 0xc815, 0xc813, + 0xc813, 0xc813, 0xc813, 0xc815, 0xc813, 0xc813, 0xc813, 0xc815, + 0xc815, 0xc815, 0xc815, 0x080c, 0x0d65, 0x080c, 0x9be6, 0x0005, + 0x0016, 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, + 0x080c, 0x61e0, 0x9006, 0x080c, 0x61cc, 0x080c, 0x305d, 0x00de, + 0x00be, 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, + 0x8007, 0x90b2, 0x000c, 0x1a0c, 0x0d65, 0x91b6, 0x0015, 0x1110, + 0x003b, 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d65, 0x006b, 0x0005, + 0xa67d, 0xa67d, 0xa67d, 0xa67d, 0xc8ad, 0xa67d, 0xc897, 0xc858, + 0xa67d, 0xa67d, 0xa67d, 0xa67d, 0xa67d, 0xa67d, 0xa67d, 0xa67d, + 0xc8ad, 0xa67d, 0xc897, 0xc89e, 0xa67d, 0xa67d, 0xa67d, 0xa67d, + 0x00f6, 0x080c, 0x6682, 0x11d8, 0x080c, 0xbf8f, 0x11c0, 0x6010, + 0x905d, 0x01a8, 0xb884, 0x9005, 0x0190, 0x9006, 0x080c, 0x61cc, + 0x2001, 0x0002, 0x080c, 0x61e0, 0x6023, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x080c, 0x84ee, 0x080c, 0x894f, 0x00f0, 0x2011, + 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2459, 0x11b0, 0x080c, + 0x628f, 0x0118, 0x080c, 0x9be6, 0x0080, 0xb810, 0x0006, 0xb814, + 0x0006, 0xb884, 0x0006, 0x080c, 0x5d11, 0x000e, 0xb886, 0x000e, + 0xb816, 0x000e, 0xb812, 0x080c, 0x9be6, 0x00fe, 0x0005, 0x6604, + 0x96b6, 0x001e, 0x1110, 0x080c, 0x9be6, 0x0005, 0x080c, 0xaa63, + 0x1148, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x84ee, 0x080c, + 0x894f, 0x0010, 0x080c, 0x9be6, 0x0005, 0x0804, 0x9be6, 0x6004, + 0x908a, 0x0053, 0x1a0c, 0x0d65, 0x080c, 0x8891, 0x080c, 0x9c20, + 0x0005, 0x9182, 0x0040, 0x0002, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, + 0xc8d2, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, + 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, 0xc8d0, + 0x080c, 0x0d65, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, + 0x0026, 0x6210, 0x2258, 0xb8ac, 0x9005, 0x11b0, 0x6007, 0x0044, + 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xc939, 0x080c, + 0xd5c6, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, + 0x0200, 0x080c, 0x8401, 0x0020, 0x9026, 0x080c, 0xd4fb, 0x0c30, + 0x080c, 0x102f, 0x090c, 0x0d65, 0x6003, 0x0007, 0xa867, 0x010d, + 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, + 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, + 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x69b5, 0x001e, + 0x080c, 0xd5c6, 0x1904, 0xc999, 0x9486, 0x2000, 0x1130, 0x2019, + 0x0017, 0x080c, 0xd234, 0x0804, 0xc999, 0x9486, 0x0200, 0x1120, + 0x080c, 0xd1c4, 0x0804, 0xc999, 0x9486, 0x0400, 0x0120, 0x9486, + 0x1000, 0x1904, 0xc999, 0x2019, 0x0002, 0x080c, 0xd1e3, 0x0804, + 0xc999, 0x2069, 0x1a46, 0x6a00, 0xd284, 0x0904, 0xca03, 0x9284, + 0x0300, 0x1904, 0xc9fc, 0x6804, 0x9005, 0x0904, 0xc9e4, 0x2d78, + 0x6003, 0x0007, 0x080c, 0x1048, 0x0904, 0xc9a5, 0x7800, 0xd08c, + 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, + 0x2004, 0xd084, 0x1904, 0xca07, 0x9006, 0xa802, 0xa867, 0x0116, + 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, + 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, + 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, + 0x9080, 0xc9a1, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, + 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, + 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, + 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, + 0x69b8, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, + 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, + 0xd084, 0x0120, 0x080c, 0x102f, 0x1904, 0xc94e, 0x6017, 0xf100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x84e7, + 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, + 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, + 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x2009, + 0xa025, 0x080c, 0x84e7, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, + 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, + 0x080c, 0x84e7, 0x0804, 0xc999, 0x2001, 0x180e, 0x2004, 0xd0ec, + 0x0120, 0x2011, 0x8049, 0x080c, 0x48fa, 0x6017, 0xf300, 0x0010, + 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, + 0x080c, 0x84e7, 0x0804, 0xc999, 0x6017, 0xf500, 0x0c98, 0x6017, + 0xf600, 0x0804, 0xc9b9, 0x6017, 0xf200, 0x0804, 0xc9b9, 0xa867, + 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, + 0x9084, 0x0003, 0x9080, 0xc9a1, 0x2005, 0xa87e, 0x2928, 0x6010, + 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, + 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, + 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, + 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d65, 0x8210, + 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, + 0x0029, 0x20a0, 0x2011, 0xca83, 0x2041, 0x0001, 0x223d, 0x9784, + 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, + 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, + 0x0c68, 0x2950, 0x080c, 0x1048, 0x0170, 0x2900, 0xb002, 0xa867, + 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, + 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, + 0x1061, 0x0cc8, 0x080c, 0x1061, 0x0804, 0xc9a5, 0x2548, 0x8847, + 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, + 0xd267, 0x0804, 0xc999, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, + 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, + 0x908a, 0x0057, 0x1a0c, 0x0d65, 0x9082, 0x0040, 0x0a0c, 0x0d65, + 0x2008, 0x0804, 0xcb0f, 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, + 0x9ab6, 0x01e8, 0x9086, 0x0002, 0x0904, 0xcb57, 0x00c0, 0x9186, + 0x0027, 0x0180, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, + 0x190c, 0x0d65, 0x080c, 0x9ab6, 0x0150, 0x9086, 0x0004, 0x0904, + 0xcbf6, 0x0028, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, + 0x9c9f, 0x0005, 0xcad6, 0xcad8, 0xcad8, 0xcaff, 0xcad6, 0xcad6, + 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, + 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0xcad6, 0x080c, 0x0d65, + 0x080c, 0x8891, 0x080c, 0x894f, 0x0036, 0x0096, 0x6014, 0x904d, + 0x01d8, 0x080c, 0xb870, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, - 0xd22f, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1957, + 0xd267, 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x195f, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, - 0x080c, 0x885d, 0x080c, 0x891b, 0x080c, 0xb842, 0x0120, 0x6014, - 0x2048, 0x080c, 0x1054, 0x080c, 0x9c14, 0x009e, 0x0005, 0x0002, - 0xcaf3, 0xcb08, 0xcaf5, 0xcb1d, 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, - 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, 0xcaf3, - 0xcaf3, 0xcaf3, 0xcaf3, 0x080c, 0x0d65, 0x0096, 0x6014, 0x2048, - 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0x9c76, 0x0010, 0x6003, 0x0004, 0x080c, 0x891b, 0x009e, 0x0005, - 0x080c, 0xb842, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, - 0xd1ec, 0x1138, 0x080c, 0x83a2, 0x080c, 0x9bda, 0x080c, 0x891b, - 0x0005, 0x080c, 0xd487, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007, - 0x0041, 0x2009, 0xa022, 0x080c, 0x84b3, 0x0005, 0x9182, 0x0040, - 0x0002, 0xcb3c, 0xcb3e, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, - 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, 0xcb3c, - 0xcb3c, 0xcb3c, 0xcb3f, 0xcb3c, 0x080c, 0x0d65, 0x0005, 0x00d6, - 0x080c, 0x83a2, 0x00de, 0x080c, 0xd4df, 0x080c, 0x9bda, 0x0005, - 0x9182, 0x0040, 0x0002, 0xcb5e, 0xcb5e, 0xcb5e, 0xcb5e, 0xcb5e, - 0xcb5e, 0xcb5e, 0xcb5e, 0xcb5e, 0xcb60, 0xcb8b, 0xcb5e, 0xcb5e, - 0xcb5e, 0xcb5e, 0xcb8b, 0xcb5e, 0xcb5e, 0xcb5e, 0x080c, 0x0d65, - 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x908c, 0x0003, - 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168, 0x2009, 0x0041, - 0x009e, 0x0804, 0xcc4b, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, - 0x83a2, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, 0xd1ec, 0x1130, - 0x080c, 0x83a2, 0x080c, 0x9bda, 0x009e, 0x0005, 0x080c, 0xd487, - 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0x0036, 0x080c, 0x88b8, 0x080c, 0x891b, 0x6014, 0x0096, 0x2048, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0188, 0xa87c, - 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, 0x6330, 0x931a, - 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, 0x0002, 0x0080, - 0x2019, 0x0004, 0x080c, 0xd22f, 0x6018, 0x9005, 0x1128, 0x2001, - 0x1957, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, 0x6003, 0x0007, - 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, 0xcbda, 0xcbda, - 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbdc, 0xcbda, - 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, 0xcbda, - 0xcbda, 0xcc27, 0x080c, 0x0d65, 0x6014, 0x0096, 0x2048, 0xa834, - 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1190, - 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, 0x0041, 0x009e, - 0x0804, 0xcc4b, 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x83a2, - 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, 0x0046, 0xacac, - 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, 0x6432, 0x602c, - 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, 0x210c, 0xd19c, - 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x00e9, 0x080c, - 0x83a4, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, 0x0005, 0x6024, - 0xd0f4, 0x0128, 0x080c, 0x15a2, 0x1904, 0xcbdc, 0x0005, 0x6014, - 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, 0x1120, 0x080c, - 0x15a2, 0x1904, 0xcbdc, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, - 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, - 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, 0x0062, 0x9186, - 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d65, 0x6024, 0xd0dc, - 0x090c, 0x0d65, 0x0005, 0xcc6e, 0xcc7a, 0xcc86, 0xcc92, 0xcc6e, - 0xcc6e, 0xcc6e, 0xcc6e, 0xcc75, 0xcc70, 0xcc70, 0xcc6e, 0xcc6e, - 0xcc6e, 0xcc6e, 0xcc70, 0xcc6e, 0xcc70, 0xcc6e, 0x080c, 0x0d65, - 0x6024, 0xd0dc, 0x090c, 0x0d65, 0x0005, 0x6014, 0x9005, 0x190c, - 0x0d65, 0x0005, 0x6003, 0x0001, 0x6106, 0x0126, 0x2091, 0x8000, - 0x2009, 0xa022, 0x080c, 0x8495, 0x012e, 0x0005, 0x6003, 0x0004, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa001, 0x080c, 0x84b3, - 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x080c, 0x1ab2, 0x0126, - 0x2091, 0x8000, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, - 0x9084, 0x0003, 0x9086, 0x0002, 0x01a0, 0x6024, 0xd0cc, 0x1148, - 0xd0c4, 0x1138, 0xa8a8, 0x9005, 0x1120, 0x6144, 0x918d, 0xb035, - 0x0018, 0x6144, 0x918d, 0xa035, 0x009e, 0x080c, 0x84fa, 0x012e, - 0x0005, 0x6144, 0x918d, 0xa032, 0x0cb8, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, - 0x0005, 0xccd9, 0xccdb, 0xccf0, 0xcd0a, 0xccd9, 0xccd9, 0xccd9, - 0xccd9, 0xccd9, 0xccd9, 0xccd9, 0xccd9, 0xccd9, 0xccd9, 0xccd9, - 0xccd9, 0x080c, 0x0d65, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0510, + 0x080c, 0x8891, 0x080c, 0x894f, 0x080c, 0xb870, 0x0120, 0x6014, + 0x2048, 0x080c, 0x1061, 0x080c, 0x9c20, 0x009e, 0x0005, 0x0002, + 0xcb24, 0xcb39, 0xcb26, 0xcb4e, 0xcb24, 0xcb24, 0xcb24, 0xcb24, + 0xcb24, 0xcb24, 0xcb24, 0xcb24, 0xcb24, 0xcb24, 0xcb24, 0xcb24, + 0xcb24, 0xcb24, 0xcb24, 0xcb24, 0x080c, 0x0d65, 0x0096, 0x6014, + 0x2048, 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, + 0x080c, 0x9c82, 0x0010, 0x6003, 0x0004, 0x080c, 0x894f, 0x009e, + 0x0005, 0x080c, 0xb870, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, + 0x009e, 0xd1ec, 0x1138, 0x080c, 0x83d6, 0x080c, 0x9be6, 0x080c, + 0x894f, 0x0005, 0x080c, 0xd4bf, 0x0db0, 0x0cc8, 0x6003, 0x0001, + 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x84e7, 0x0005, 0x9182, + 0x0040, 0x0002, 0xcb6e, 0xcb70, 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, + 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, 0xcb6e, + 0xcb6e, 0xcb6e, 0xcb6e, 0xcb71, 0xcb6e, 0xcb6e, 0x080c, 0x0d65, + 0x0005, 0x00d6, 0x080c, 0x83d6, 0x00de, 0x080c, 0xd517, 0x080c, + 0x9be6, 0x0005, 0x9182, 0x0040, 0x0002, 0xcb91, 0xcb91, 0xcb91, + 0xcb91, 0xcb91, 0xcb91, 0xcb91, 0xcb91, 0xcb91, 0xcb93, 0xcbbe, + 0xcb91, 0xcb91, 0xcb91, 0xcb91, 0xcbbe, 0xcb91, 0xcb91, 0xcb91, + 0xcb91, 0x080c, 0x0d65, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, + 0x0168, 0x908c, 0x0003, 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, + 0x1168, 0x2009, 0x0041, 0x009e, 0x0804, 0xcc7e, 0x6003, 0x0007, + 0x601b, 0x0000, 0x080c, 0x83d6, 0x009e, 0x0005, 0x6014, 0x2048, + 0xa97c, 0xd1ec, 0x1130, 0x080c, 0x83d6, 0x080c, 0x9be6, 0x009e, + 0x0005, 0x080c, 0xd4bf, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, + 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x88ec, 0x080c, 0x894f, + 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, + 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, + 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, + 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xd267, 0x6018, + 0x9005, 0x1128, 0x2001, 0x195f, 0x2004, 0x8003, 0x601a, 0x6017, + 0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, + 0x0002, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, + 0xcc0d, 0xcc0f, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, + 0xcc0d, 0xcc0d, 0xcc0d, 0xcc0d, 0xcc5a, 0x080c, 0x0d65, 0x6014, + 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, + 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, + 0x2009, 0x0041, 0x009e, 0x0804, 0xcc7e, 0x6003, 0x0007, 0x601b, + 0x0000, 0x080c, 0x83d6, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, + 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, + 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, + 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, + 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, + 0x0006, 0x00e9, 0x080c, 0x83d8, 0x009e, 0x0005, 0x6003, 0x0002, + 0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x15af, 0x1904, + 0xcc0f, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, + 0x9105, 0x1120, 0x080c, 0x15af, 0x1904, 0xcc0f, 0x0005, 0xd2fc, + 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, + 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, + 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, + 0x0d65, 0x6024, 0xd0dc, 0x090c, 0x0d65, 0x0005, 0xcca2, 0xccae, + 0xccba, 0xccc6, 0xcca2, 0xcca2, 0xcca2, 0xcca2, 0xcca9, 0xcca4, + 0xcca4, 0xcca2, 0xcca2, 0xcca2, 0xcca2, 0xcca4, 0xcca2, 0xcca4, + 0xcca2, 0xcca9, 0x080c, 0x0d65, 0x6024, 0xd0dc, 0x090c, 0x0d65, + 0x0005, 0x6014, 0x9005, 0x190c, 0x0d65, 0x0005, 0x6003, 0x0001, + 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x84c9, + 0x012e, 0x0005, 0x6003, 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, + 0x2009, 0xa001, 0x080c, 0x84e7, 0x012e, 0x0005, 0x6003, 0x0003, + 0x6106, 0x080c, 0x1aca, 0x0126, 0x2091, 0x8000, 0x6014, 0x0096, + 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x9084, 0x0003, 0x9086, 0x0002, + 0x01a0, 0x6024, 0xd0cc, 0x1148, 0xd0c4, 0x1138, 0xa8a8, 0x9005, + 0x1120, 0x6144, 0x918d, 0xb035, 0x0018, 0x6144, 0x918d, 0xa035, + 0x009e, 0x080c, 0x852e, 0x012e, 0x0005, 0x6144, 0x918d, 0xa032, + 0x0cb8, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, 0x0040, + 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xcd11, 0xcd13, 0xcd28, + 0xcd42, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, + 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, 0xcd11, + 0xcd11, 0x080c, 0x0d65, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0510, 0x909c, 0x0003, 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001, 0x6106, - 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x84b3, 0x0470, + 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x84e7, 0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x2009, 0xa001, 0x080c, - 0x84b3, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, - 0xd22f, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, + 0x84e7, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, 0x080c, + 0xd267, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, 0x080c, - 0x1ab2, 0x6144, 0x918d, 0xa035, 0x080c, 0x84fa, 0x0005, 0x080c, - 0x885d, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xd52b, - 0x0036, 0x2019, 0x0029, 0x080c, 0xd22f, 0x003e, 0x009e, 0x080c, - 0x9c14, 0x080c, 0x891b, 0x0005, 0x080c, 0x88b8, 0x6114, 0x81ff, - 0x0158, 0x0096, 0x2148, 0x080c, 0xd52b, 0x0036, 0x2019, 0x0029, - 0x080c, 0xd22f, 0x003e, 0x009e, 0x080c, 0x9c14, 0x0005, 0x9182, - 0x0085, 0x0002, 0xcd59, 0xcd57, 0xcd57, 0xcd65, 0xcd57, 0xcd57, - 0xcd57, 0xcd57, 0xcd57, 0xcd57, 0xcd57, 0xcd57, 0xcd57, 0x080c, + 0x1aca, 0x6144, 0x918d, 0xa035, 0x080c, 0x852e, 0x0005, 0x080c, + 0x8891, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xd563, + 0x0036, 0x2019, 0x0029, 0x080c, 0xd267, 0x003e, 0x009e, 0x080c, + 0x9c20, 0x080c, 0x894f, 0x0005, 0x080c, 0x88ec, 0x6114, 0x81ff, + 0x0158, 0x0096, 0x2148, 0x080c, 0xd563, 0x0036, 0x2019, 0x0029, + 0x080c, 0xd267, 0x003e, 0x009e, 0x080c, 0x9c20, 0x0005, 0x9182, + 0x0085, 0x0002, 0xcd91, 0xcd8f, 0xcd8f, 0xcd9d, 0xcd8f, 0xcd8f, + 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8f, 0x080c, 0x0d65, 0x6003, 0x000b, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, - 0x8020, 0x080c, 0x84b3, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, - 0xd47e, 0x0118, 0x080c, 0x9bda, 0x0440, 0x2071, 0x0260, 0x7224, + 0x8020, 0x080c, 0x84e7, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, + 0xd4b6, 0x0118, 0x080c, 0x9be6, 0x0440, 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, 0x0150, 0x6010, 0x00b6, - 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0x9f04, - 0x7220, 0x080c, 0xd0c5, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, + 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, 0x014e, 0x080c, 0x9f10, + 0x7220, 0x080c, 0xd0fd, 0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, 0x6007, 0x0086, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, 0x00ee, 0x002e, 0x0005, + 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d65, 0x908a, 0x0092, 0x1a0c, 0x0d65, 0x9082, 0x0085, 0x00a2, 0x9186, - 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0x9c93, 0x0050, - 0x2001, 0x0007, 0x080c, 0x61e8, 0x080c, 0x885d, 0x080c, 0x9c14, - 0x080c, 0x891b, 0x0005, 0xcdc8, 0xcdca, 0xcdca, 0xcdc8, 0xcdc8, - 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc8, - 0x080c, 0x0d65, 0x080c, 0x9c14, 0x080c, 0x891b, 0x0005, 0x9182, + 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, 0x080c, 0x9c9f, 0x0050, + 0x2001, 0x0007, 0x080c, 0x620c, 0x080c, 0x8891, 0x080c, 0x9c20, + 0x080c, 0x894f, 0x0005, 0xce00, 0xce02, 0xce02, 0xce00, 0xce00, + 0xce00, 0xce00, 0xce00, 0xce00, 0xce00, 0xce00, 0xce00, 0xce00, + 0x080c, 0x0d65, 0x080c, 0x9c20, 0x080c, 0x894f, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d65, 0x9182, 0x0092, 0x1a0c, 0x0d65, 0x9182, - 0x0085, 0x0002, 0xcde7, 0xcde7, 0xcde7, 0xcde9, 0xcde7, 0xcde7, - 0xcde7, 0xcde7, 0xcde7, 0xcde7, 0xcde7, 0xcde7, 0xcde7, 0x080c, + 0x0085, 0x0002, 0xce1f, 0xce1f, 0xce1f, 0xce21, 0xce1f, 0xce1f, + 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0xce1f, 0x080c, 0x0d65, 0x0005, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, - 0x9186, 0x0027, 0x0118, 0x080c, 0x9c93, 0x0020, 0x080c, 0x885d, - 0x080c, 0x9c14, 0x0005, 0x0036, 0x080c, 0xd4df, 0x604b, 0x0000, + 0x9186, 0x0027, 0x0118, 0x080c, 0x9c9f, 0x0020, 0x080c, 0x8891, + 0x080c, 0x9c20, 0x0005, 0x0036, 0x080c, 0xd517, 0x604b, 0x0000, 0x2019, 0x000b, 0x0031, 0x6023, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x0006, 0x9086, 0x0003, 0x0110, 0x080c, 0x98bb, - 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0x9365, 0x009e, 0x008e, - 0x1558, 0x0076, 0x2c38, 0x080c, 0x9410, 0x007e, 0x1528, 0x6000, + 0x9084, 0x0007, 0x0006, 0x9086, 0x0003, 0x0110, 0x080c, 0x98c7, + 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0x936d, 0x009e, 0x008e, + 0x1558, 0x0076, 0x2c38, 0x080c, 0x9418, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, 0x0508, 0x6020, 0x9086, 0x0007, 0x01e8, 0x0096, - 0x601c, 0xd084, 0x0140, 0x080c, 0xd4df, 0x080c, 0xbf79, 0x080c, - 0x1921, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xb842, 0x0110, - 0x080c, 0xd22f, 0x009e, 0x9006, 0x6046, 0x6016, 0x080c, 0xd4df, - 0x6023, 0x0007, 0x080c, 0xbf79, 0x000e, 0x9086, 0x0003, 0x0110, - 0x080c, 0x98d7, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x00b6, - 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, 0x243d, - 0x15e8, 0x0016, 0x00c6, 0x080c, 0x626b, 0x15b0, 0x001e, 0x00c6, - 0x2160, 0x080c, 0xbf76, 0x00ce, 0x002e, 0x0026, 0x0016, 0x080c, - 0x98bb, 0x2019, 0x0029, 0x080c, 0x94dd, 0x080c, 0x8624, 0x0076, - 0x903e, 0x080c, 0x8509, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, - 0xcfd9, 0x007e, 0x080c, 0x98d7, 0x0026, 0xba04, 0x9294, 0xff00, + 0x601c, 0xd084, 0x0140, 0x080c, 0xd517, 0x080c, 0xbfa7, 0x080c, + 0x193e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xb870, 0x0110, + 0x080c, 0xd267, 0x009e, 0x9006, 0x6046, 0x6016, 0x080c, 0xd517, + 0x6023, 0x0007, 0x080c, 0xbfa7, 0x000e, 0x9086, 0x0003, 0x0110, + 0x080c, 0x98e3, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x00b6, + 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, 0x2459, + 0x15e8, 0x0016, 0x00c6, 0x080c, 0x628f, 0x15b0, 0x001e, 0x00c6, + 0x2160, 0x080c, 0xbfa4, 0x00ce, 0x002e, 0x0026, 0x0016, 0x080c, + 0x98c7, 0x2019, 0x0029, 0x080c, 0x94e5, 0x080c, 0x8658, 0x0076, + 0x903e, 0x080c, 0x853d, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, + 0xd011, 0x007e, 0x080c, 0x98e3, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, - 0x080c, 0x30d8, 0x002e, 0xbc84, 0x001e, 0x080c, 0x5cf1, 0xbe12, + 0x080c, 0x30f8, 0x002e, 0xbc84, 0x001e, 0x080c, 0x5d11, 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, - 0x2009, 0x1823, 0x2104, 0x9086, 0x0074, 0x1904, 0xcefd, 0x2069, + 0x2009, 0x1823, 0x2104, 0x9086, 0x0074, 0x1904, 0xcf35, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, - 0x0904, 0xcefa, 0x2001, 0x194c, 0x2004, 0x9005, 0x1140, 0x6010, + 0x0904, 0xcf32, 0x2001, 0x1954, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb884, 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, - 0x918a, 0x0001, 0x0648, 0x080c, 0xd593, 0x0118, 0x6978, 0xd1fc, + 0x918a, 0x0001, 0x0648, 0x080c, 0xd5cb, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, @@ -6422,225 +6429,225 @@ unsigned short risc_code01[] = { 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, - 0x0120, 0x080c, 0x627a, 0x0804, 0xcf68, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xabd3, 0x009e, + 0x0120, 0x080c, 0x629e, 0x0804, 0xcfa0, 0x2011, 0x0276, 0x20a9, + 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xabee, 0x009e, 0x15c0, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, - 0x0006, 0x080c, 0xabd3, 0x009e, 0x1560, 0x0046, 0x0016, 0xbaa0, - 0x2220, 0x9006, 0x2009, 0x1854, 0x210c, 0x0038, 0x2009, 0x0029, - 0x080c, 0xd284, 0xb800, 0xc0e5, 0xb802, 0x080c, 0x98bb, 0x2019, - 0x0029, 0x080c, 0x8624, 0x0076, 0x2039, 0x0000, 0x080c, 0x8509, - 0x2c08, 0x080c, 0xcfd9, 0x007e, 0x080c, 0x98d7, 0x2001, 0x0007, - 0x080c, 0x61e8, 0x2001, 0x0007, 0x080c, 0x61bc, 0x001e, 0x004e, + 0x0006, 0x080c, 0xabee, 0x009e, 0x1560, 0x0046, 0x0016, 0xbaa0, + 0x2220, 0x9006, 0x2009, 0x185c, 0x210c, 0x0038, 0x2009, 0x0029, + 0x080c, 0xd2bc, 0xb800, 0xc0e5, 0xb802, 0x080c, 0x98c7, 0x2019, + 0x0029, 0x080c, 0x8658, 0x0076, 0x2039, 0x0000, 0x080c, 0x853d, + 0x2c08, 0x080c, 0xd011, 0x007e, 0x080c, 0x98e3, 0x2001, 0x0007, + 0x080c, 0x620c, 0x2001, 0x0007, 0x080c, 0x61e0, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00f6, 0x0016, 0x0026, - 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, 0x7834, 0x080c, 0x243d, - 0x11d0, 0x080c, 0x626b, 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xabd3, 0x009e, 0x1158, + 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, 0x7834, 0x080c, 0x2459, + 0x11d0, 0x080c, 0x628f, 0x11b8, 0x2011, 0x0270, 0x20a9, 0x0004, + 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xabee, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, - 0x080c, 0xabd3, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, + 0x080c, 0xabee, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x243d, 0x11d0, - 0x080c, 0x626b, 0x11b8, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xabd3, 0x009e, 0x1158, 0x2011, + 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2459, 0x11d0, + 0x080c, 0x628f, 0x11b8, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, + 0x2b48, 0x2019, 0x000a, 0x080c, 0xabee, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, - 0xabd3, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, + 0xabee, 0x009e, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, - 0x0026, 0x0126, 0x2091, 0x8000, 0x080c, 0x9919, 0x0106, 0x190c, - 0x98bb, 0x2740, 0x2029, 0x19c3, 0x252c, 0x2021, 0x19ca, 0x2424, + 0x0026, 0x0126, 0x2091, 0x8000, 0x080c, 0x9925, 0x0106, 0x190c, + 0x98c7, 0x2740, 0x2029, 0x19cb, 0x252c, 0x2021, 0x19d2, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7650, 0x7070, 0x81ff, 0x0150, - 0x0006, 0x9186, 0x1b01, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, - 0xd07a, 0x0018, 0x9606, 0x0904, 0xd07a, 0x2100, 0x9c06, 0x0904, - 0xd071, 0x080c, 0xd2c5, 0x1904, 0xd071, 0x080c, 0xd5b0, 0x0904, - 0xd071, 0x080c, 0xd2b5, 0x0904, 0xd071, 0x6720, 0x9786, 0x0001, - 0x1148, 0x080c, 0x3175, 0x0904, 0xd099, 0x6004, 0x9086, 0x0000, - 0x1904, 0xd099, 0x9786, 0x0004, 0x0904, 0xd099, 0x9786, 0x0007, - 0x0904, 0xd071, 0x2500, 0x9c06, 0x0904, 0xd071, 0x2400, 0x9c06, - 0x0904, 0xd071, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, 0x0096, + 0x0006, 0x9186, 0x1b09, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, + 0xd0b2, 0x0018, 0x9606, 0x0904, 0xd0b2, 0x2100, 0x9c06, 0x0904, + 0xd0a9, 0x080c, 0xd2fd, 0x1904, 0xd0a9, 0x080c, 0xd5e8, 0x0904, + 0xd0a9, 0x080c, 0xd2ed, 0x0904, 0xd0a9, 0x6720, 0x9786, 0x0001, + 0x1148, 0x080c, 0x3195, 0x0904, 0xd0d1, 0x6004, 0x9086, 0x0000, + 0x1904, 0xd0d1, 0x9786, 0x0004, 0x0904, 0xd0d1, 0x9786, 0x0007, + 0x0904, 0xd0a9, 0x2500, 0x9c06, 0x0904, 0xd0a9, 0x2400, 0x9c06, + 0x0904, 0xd0a9, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, 0x0096, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x1921, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xba57, 0x1130, - 0x080c, 0xa581, 0x009e, 0x080c, 0x9c14, 0x0418, 0x6014, 0x2048, - 0x080c, 0xb842, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, 0x0103, - 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fd4, - 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd52b, 0x0016, 0x080c, - 0xbb45, 0x080c, 0x6985, 0x001e, 0x080c, 0xba31, 0x009e, 0x080c, - 0x9c14, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, - 0x0804, 0xcff2, 0x010e, 0x190c, 0x98d7, 0x012e, 0x002e, 0x004e, + 0x193e, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xba85, 0x1130, + 0x080c, 0xa59c, 0x009e, 0x080c, 0x9c20, 0x0418, 0x6014, 0x2048, + 0x080c, 0xb870, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, 0x0103, + 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fe1, + 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd563, 0x0016, 0x080c, + 0xbb73, 0x080c, 0x69a9, 0x001e, 0x080c, 0xba5f, 0x009e, 0x080c, + 0x9c20, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, + 0x0804, 0xd02a, 0x010e, 0x190c, 0x98e3, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, - 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xd52b, 0x080c, - 0xd22f, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x000a, 0x0908, 0x0804, - 0xd056, 0x81ff, 0x09b0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, + 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xd563, 0x080c, + 0xd267, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x000a, 0x0908, 0x0804, + 0xd08e, 0x81ff, 0x09b0, 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0130, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1950, 0x6000, - 0x9086, 0x0002, 0x1930, 0x080c, 0xba46, 0x0130, 0x080c, 0xba57, - 0x1900, 0x080c, 0xa581, 0x0038, 0x080c, 0x303d, 0x080c, 0xba57, - 0x1110, 0x080c, 0xa581, 0x080c, 0x9c14, 0x0804, 0xd071, 0xa864, + 0x9086, 0x0002, 0x1930, 0x080c, 0xba74, 0x0130, 0x080c, 0xba85, + 0x1900, 0x080c, 0xa59c, 0x0038, 0x080c, 0x305d, 0x080c, 0xba85, + 0x1110, 0x080c, 0xa59c, 0x080c, 0x9c20, 0x0804, 0xd0a9, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, - 0x2c08, 0x2170, 0x9006, 0x080c, 0xd256, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xd0e4, 0xd0e4, - 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e6, 0xd0e4, 0xd0e4, 0xd0e4, - 0xd0e4, 0x9c14, 0x9c14, 0xd0e4, 0x9006, 0x0005, 0x0036, 0x0046, + 0x2c08, 0x2170, 0x9006, 0x080c, 0xd28e, 0x001e, 0x0120, 0x6020, + 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xd11c, 0xd11c, + 0xd11c, 0xd11c, 0xd11c, 0xd11c, 0xd11e, 0xd11c, 0xd11c, 0xd11c, + 0xd11c, 0x9c20, 0x9c20, 0xd11c, 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, - 0x0020, 0x080c, 0xd284, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, - 0xce09, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xb842, - 0x0140, 0x6014, 0x904d, 0x080c, 0xb440, 0x687b, 0x0005, 0x080c, - 0x6991, 0x009e, 0x080c, 0x9c14, 0x9085, 0x0001, 0x0005, 0x2001, - 0x0001, 0x080c, 0x61a8, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xabbf, 0x003e, + 0x0020, 0x080c, 0xd2bc, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, + 0xce41, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xb870, + 0x0140, 0x6014, 0x904d, 0x080c, 0xb45e, 0x687b, 0x0005, 0x080c, + 0x69b5, 0x009e, 0x080c, 0x9c20, 0x9085, 0x0001, 0x0005, 0x2001, + 0x0001, 0x080c, 0x61cc, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, + 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xabda, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2061, 0x1ddc, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd17f, 0x2071, - 0x1800, 0x7650, 0x7070, 0x8001, 0x9602, 0x1a04, 0xd17f, 0x88ff, - 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xd2b5, 0x0570, + 0x2061, 0x1ddc, 0x2079, 0x0001, 0x8fff, 0x0904, 0xd1b7, 0x2071, + 0x1800, 0x7650, 0x7070, 0x8001, 0x9602, 0x1a04, 0xd1b7, 0x88ff, + 0x0120, 0x2800, 0x9c06, 0x1590, 0x2078, 0x080c, 0xd2ed, 0x0570, 0x2400, 0x9c06, 0x0558, 0x6720, 0x9786, 0x0006, 0x1538, 0x9786, 0x0007, 0x0520, 0x88ff, 0x1140, 0x6010, 0x9b06, 0x11f8, 0x85ff, 0x0118, 0x605c, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, - 0x080c, 0xd4df, 0x080c, 0xbf79, 0x080c, 0x1921, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xb842, 0x0120, 0x0046, 0x080c, 0xd22f, - 0x004e, 0x009e, 0x080c, 0x9c14, 0x88ff, 0x1198, 0x9ce0, 0x001c, - 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd134, 0x9006, + 0x080c, 0xd517, 0x080c, 0xbfa7, 0x080c, 0x193e, 0x6023, 0x0007, + 0x6014, 0x2048, 0x080c, 0xb870, 0x0120, 0x0046, 0x080c, 0xd267, + 0x004e, 0x009e, 0x080c, 0x9c20, 0x88ff, 0x1198, 0x9ce0, 0x001c, + 0x2001, 0x1819, 0x2004, 0x9c02, 0x1210, 0x0804, 0xd16c, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0x98bb, 0x00b6, 0x0076, + 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0x98c7, 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, - 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0x9365, 0x009e, 0x008e, - 0x903e, 0x080c, 0x9410, 0x080c, 0xd125, 0x005e, 0x007e, 0x00be, - 0x080c, 0x98d7, 0x0005, 0x080c, 0x98bb, 0x00b6, 0x0046, 0x0056, + 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0x936d, 0x009e, 0x008e, + 0x903e, 0x080c, 0x9418, 0x080c, 0xd15d, 0x005e, 0x007e, 0x00be, + 0x080c, 0x98e3, 0x0005, 0x080c, 0x98c7, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x0036, 0x080c, 0x626b, 0x1190, 0x0056, 0x0086, 0x9046, - 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x9365, 0x009e, - 0x008e, 0x903e, 0x080c, 0x9410, 0x080c, 0xd125, 0x005e, 0x003e, - 0x001e, 0x8108, 0x1f04, 0xd1b8, 0x015e, 0x00ce, 0x007e, 0x005e, - 0x004e, 0x00be, 0x080c, 0x98d7, 0x0005, 0x080c, 0x98bb, 0x00b6, + 0x0016, 0x0036, 0x080c, 0x628f, 0x1190, 0x0056, 0x0086, 0x9046, + 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0x936d, 0x009e, + 0x008e, 0x903e, 0x080c, 0x9418, 0x080c, 0xd15d, 0x005e, 0x003e, + 0x001e, 0x8108, 0x1f04, 0xd1f0, 0x015e, 0x00ce, 0x007e, 0x005e, + 0x004e, 0x00be, 0x080c, 0x98e3, 0x0005, 0x080c, 0x98c7, 0x00b6, 0x0076, 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, - 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, 0x9365, 0x009e, 0x008e, - 0x903e, 0x080c, 0x9410, 0x2c20, 0x080c, 0xd125, 0x005e, 0x007e, - 0x00be, 0x080c, 0x98d7, 0x0005, 0x080c, 0x98bb, 0x00b6, 0x0046, + 0x2019, 0x0048, 0x0096, 0x904e, 0x080c, 0x936d, 0x009e, 0x008e, + 0x903e, 0x080c, 0x9418, 0x2c20, 0x080c, 0xd15d, 0x005e, 0x007e, + 0x00be, 0x080c, 0x98e3, 0x0005, 0x080c, 0x98c7, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, - 0x0016, 0x0036, 0x080c, 0x626b, 0x11a0, 0x0086, 0x9046, 0x2828, - 0x0046, 0x2021, 0x0001, 0x080c, 0xd4c3, 0x004e, 0x0096, 0x904e, - 0x080c, 0x9365, 0x009e, 0x008e, 0x903e, 0x080c, 0x9410, 0x080c, - 0xd125, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd208, 0x015e, 0x00ce, - 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0x98d7, 0x0005, 0x0016, - 0x00f6, 0x080c, 0xb840, 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, + 0x0016, 0x0036, 0x080c, 0x628f, 0x11a0, 0x0086, 0x9046, 0x2828, + 0x0046, 0x2021, 0x0001, 0x080c, 0xd4fb, 0x004e, 0x0096, 0x904e, + 0x080c, 0x936d, 0x009e, 0x008e, 0x903e, 0x080c, 0x9418, 0x080c, + 0xd15d, 0x003e, 0x001e, 0x8108, 0x1f04, 0xd240, 0x015e, 0x00ce, + 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0x98e3, 0x0005, 0x0016, + 0x00f6, 0x080c, 0xb86e, 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, - 0x080c, 0x6991, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x6991, 0x00fe, + 0x080c, 0x69b5, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x69b5, 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, - 0x6991, 0x2f48, 0x0cb8, 0x080c, 0x6991, 0x0c88, 0x00e6, 0x0046, + 0x69b5, 0x2f48, 0x0cb8, 0x080c, 0x69b5, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1ddc, 0x9005, 0x1138, 0x2071, 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000, 0x0148, 0x6008, 0x9206, 0x1130, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, - 0x003e, 0x004e, 0x00ee, 0x0005, 0x0096, 0x0006, 0x080c, 0x1022, + 0x003e, 0x004e, 0x00ee, 0x0005, 0x0096, 0x0006, 0x080c, 0x102f, 0x000e, 0x090c, 0x0d65, 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, - 0x2010, 0x080c, 0xb830, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, + 0x2010, 0x080c, 0xb85e, 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0017, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, - 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x195e, 0x2004, + 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x1966, 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6991, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, + 0x080c, 0x69b5, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, - 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1957, 0x2004, 0x601a, - 0x2009, 0x8020, 0x080c, 0x84b3, 0x001e, 0x0005, 0xa001, 0xa001, - 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xbb8c, - 0x0030, 0x080c, 0xd4df, 0x080c, 0x83a2, 0x080c, 0x9bda, 0x0005, - 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd314, 0xd314, - 0xd314, 0xd316, 0xd314, 0xd316, 0xd316, 0xd314, 0xd316, 0xd314, - 0xd314, 0xd314, 0xd314, 0xd314, 0x9006, 0x0005, 0x9085, 0x0001, - 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd32d, - 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd33a, 0xd32d, 0xd32d, - 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0x6007, 0x003b, 0x602f, + 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x195f, 0x2004, 0x601a, + 0x2009, 0x8020, 0x080c, 0x84e7, 0x001e, 0x0005, 0xa001, 0xa001, + 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0xbbba, + 0x0030, 0x080c, 0xd517, 0x080c, 0x83d6, 0x080c, 0x9be6, 0x0005, + 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd34c, 0xd34c, + 0xd34c, 0xd34e, 0xd34c, 0xd34e, 0xd34e, 0xd34c, 0xd34e, 0xd34c, + 0xd34c, 0xd34c, 0xd34c, 0xd34c, 0x9006, 0x0005, 0x9085, 0x0001, + 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xd365, + 0xd365, 0xd365, 0xd365, 0xd365, 0xd365, 0xd372, 0xd365, 0xd365, + 0xd365, 0xd365, 0xd365, 0xd365, 0xd365, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, - 0x84b3, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xd4df, 0x604b, + 0x84e7, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xd517, 0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, - 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xd393, 0x6814, 0x9005, + 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xd3cb, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, - 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, - 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xd40a, 0x6014, + 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, + 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xd442, 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d65, 0x0804, - 0xd40a, 0x2048, 0x080c, 0xb842, 0x1130, 0x0028, 0x2048, 0xa800, + 0xd442, 0x2048, 0x080c, 0xb870, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, - 0xa882, 0x2009, 0x0043, 0x080c, 0xcc4b, 0x0804, 0xd40a, 0x2009, - 0x0041, 0x0804, 0xd404, 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, - 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xd32d, 0xd0b4, - 0x0128, 0xd0fc, 0x090c, 0x0d65, 0x0804, 0xd34e, 0x6007, 0x003a, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84b3, 0x00c6, 0x2d60, - 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xd40a, + 0xa882, 0x2009, 0x0043, 0x080c, 0xcc7e, 0x0804, 0xd442, 0x2009, + 0x0041, 0x0804, 0xd43c, 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, + 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xd365, 0xd0b4, + 0x0128, 0xd0fc, 0x090c, 0x0d65, 0x0804, 0xd386, 0x6007, 0x003a, + 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x84e7, 0x00c6, 0x2d60, + 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, 0xd442, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, - 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x165c, 0x00fe, 0x2009, - 0x0042, 0x04d0, 0x0036, 0x080c, 0x1022, 0x090c, 0x0d65, 0xa867, + 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x1669, 0x00fe, 0x2009, + 0x0042, 0x04d0, 0x0036, 0x080c, 0x102f, 0x090c, 0x0d65, 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004, 0x635c, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, - 0x0001, 0x080c, 0x6991, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, - 0xce09, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, + 0x0001, 0x080c, 0x69b5, 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, + 0xce41, 0x2d00, 0x600a, 0x6023, 0x0006, 0x6003, 0x0007, 0x901e, 0x631a, 0x634a, 0x003e, 0x0038, 0x604b, 0x0000, 0x6003, 0x0007, - 0x080c, 0xcc4b, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, + 0x080c, 0xcc7e, 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, - 0x1178, 0x080c, 0x885d, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, - 0x0004, 0x080c, 0xd22f, 0x009e, 0x003e, 0x080c, 0x891b, 0x0005, - 0x9186, 0x0014, 0x0d70, 0x080c, 0x9c93, 0x0005, 0xd43d, 0xd43b, - 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43d, 0xd43b, 0xd43b, 0xd43b, - 0xd43b, 0xd43b, 0xd43b, 0x080c, 0x0d65, 0x6003, 0x000c, 0x080c, - 0x891b, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, - 0x001a, 0x080c, 0x9c93, 0x0005, 0xd459, 0xd459, 0xd459, 0xd459, - 0xd45b, 0xd47b, 0xd459, 0xd459, 0xd459, 0xd459, 0xd459, 0xd459, - 0xd459, 0x080c, 0x0d65, 0x00d6, 0x2c68, 0x080c, 0x9b84, 0x01b0, + 0x1178, 0x080c, 0x8891, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, + 0x0004, 0x080c, 0xd267, 0x009e, 0x003e, 0x080c, 0x894f, 0x0005, + 0x9186, 0x0014, 0x0d70, 0x080c, 0x9c9f, 0x0005, 0xd475, 0xd473, + 0xd473, 0xd473, 0xd473, 0xd473, 0xd475, 0xd473, 0xd473, 0xd473, + 0xd473, 0xd473, 0xd473, 0x080c, 0x0d65, 0x6003, 0x000c, 0x080c, + 0x894f, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, + 0x001a, 0x080c, 0x9c9f, 0x0005, 0xd491, 0xd491, 0xd491, 0xd491, + 0xd493, 0xd4b3, 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, + 0xd491, 0x080c, 0x0d65, 0x00d6, 0x2c68, 0x080c, 0x9b90, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, - 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x84b3, 0x2d60, 0x080c, - 0x9bda, 0x00de, 0x0005, 0x080c, 0x9bda, 0x0005, 0x00e6, 0x6010, + 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x84e7, 0x2d60, 0x080c, + 0x9be6, 0x00de, 0x0005, 0x080c, 0x9be6, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, - 0x1873, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, - 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1958, 0x2004, 0x604a, 0x2009, - 0x1873, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1873, 0x210c, + 0x187b, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, + 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1960, 0x2004, 0x604a, 0x2009, + 0x187b, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x187b, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, - 0x1958, 0x200c, 0x2001, 0x1956, 0x2004, 0x9100, 0x9080, 0x000a, + 0x1960, 0x200c, 0x2001, 0x195e, 0x2004, 0x9100, 0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, 0x2058, 0xb8ac, 0x00be, 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x615c, 0xb8ac, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x605c, 0x9106, 0x1138, - 0x600c, 0x2072, 0x080c, 0x83a2, 0x080c, 0x9bda, 0x0010, 0x9cf0, + 0x600c, 0x2072, 0x080c, 0x83d6, 0x080c, 0x9be6, 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8ac, 0x2068, 0x9005, 0x0130, 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182b, 0x2204, 0x9084, 0x00ff, 0x2019, 0x026e, 0x2334, 0x9636, 0x1508, 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9, 0x0004, - 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xabd3, 0x009e, + 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xabee, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, - 0x2019, 0x0006, 0x080c, 0xabd3, 0x009e, 0x1100, 0x015e, 0x003e, - 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c6a, 0x080c, - 0x2de9, 0x00ee, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, + 0x2019, 0x0006, 0x080c, 0xabee, 0x009e, 0x1100, 0x015e, 0x003e, + 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x5c8a, 0x080c, + 0x2e09, 0x00ee, 0x0005, 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0056, - 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x19c3, - 0x252c, 0x2021, 0x19ca, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, + 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0x19cb, + 0x252c, 0x2021, 0x19d2, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7650, 0x7070, 0x9606, 0x0578, 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, 0x2400, 0x9c06, - 0x01d0, 0x080c, 0xd2b5, 0x01b8, 0x080c, 0xd2c5, 0x11a0, 0x6000, - 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1921, 0x001e, 0x080c, - 0xba46, 0x1110, 0x080c, 0x303d, 0x080c, 0xba57, 0x1110, 0x080c, - 0xa581, 0x080c, 0x9c14, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, + 0x01d0, 0x080c, 0xd2ed, 0x01b8, 0x080c, 0xd2fd, 0x11a0, 0x6000, + 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x193e, 0x001e, 0x080c, + 0xba74, 0x1110, 0x080c, 0x305d, 0x080c, 0xba85, 0x1110, 0x080c, + 0xa59c, 0x080c, 0x9c20, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1836, 0x2004, 0xd09c, - 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, 0xbf61, 0x0168, + 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, 0xbf8f, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, 0x2058, 0xbba0, - 0x00be, 0x2021, 0x0004, 0x080c, 0x4a77, 0x004e, 0x003e, 0x000e, - 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x94dd, 0x080c, 0x9c14, + 0x00be, 0x2021, 0x0004, 0x080c, 0x4a97, 0x004e, 0x003e, 0x000e, + 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, 0x94e5, 0x080c, 0x9c20, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7450, 0x7070, 0x8001, 0x9402, 0x12b8, 0x2100, 0x9c06, 0x0148, 0x6000, 0x9086, 0x0000, 0x0128, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x1819, 0x2004, 0x9c02, 0x1220, 0x0c60, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, - 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7034, 0x8000, - 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, + 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, 0x0118, 0x7054, 0x8000, + 0x7056, 0xd5b4, 0x0118, 0x7050, 0x8000, 0x7052, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, 0x184a, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, @@ -6648,15 +6655,15 @@ unsigned short risc_code01[] = { 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, 0x00e6, 0x2071, 0x1840, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1844, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, - 0x2091, 0x8000, 0x2071, 0x1840, 0x7044, 0x8000, 0x7046, 0x00ee, + 0x2091, 0x8000, 0x2071, 0x1840, 0x7064, 0x8000, 0x7066, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, - 0x2000, 0x4000, 0x8000, 0x9407 + 0x2000, 0x4000, 0x8000, 0x8c0a }; #ifdef UNIQUE_FW_NAME -unsigned short fw2322flx_length01 = 0xce4c; +unsigned short fw2322flx_length01 = 0xce84; #else -unsigned short risc_code_length01 = 0xce4c; +unsigned short risc_code_length01 = 0xce84; #endif /* @@ -7054,7 +7061,7 @@ unsigned short xseqflx_code01[] = { 0x0000, 0x0002, 0x0002, 0x1f43, 0x000b, 0x1256, 0x0001, 0xff88, 0x0000, 0x0002, 0x0013, 0x0258, 0x0001, 0xff88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x825b, - 0x0000, 0xb0ff, 0x0011, 0x16a0, 0x0000, 0xff16, 0x000b, 0x24e2, + 0x0000, 0xb0ff, 0x0011, 0x16a0, 0x0000, 0xff16, 0x001b, 0x2262, 0x0002, 0xb100, 0x0003, 0x0263, 0x0010, 0xb1ff, 0x0001, 0x17a0, 0x0010, 0xff17, 0x0003, 0x0221, 0x0000, 0x16ff, 0x0001, 0x18a0, 0x0010, 0xff00, 0x001b, 0x226d, 0x0002, 0x1700, 0x0013, 0x12c0, @@ -7421,6 +7428,6 @@ unsigned short xseqflx_code01[] = { 0x000b, 0x880c, 0x0012, 0x1027, 0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x8814, 0x0015, 0x00b8, 0x0000, 0x0007, 0x0013, 0x4817, - 0x0000, 0xb838, 0x0017, 0x4000, 0xa5a5, 0x1ab5 + 0x0000, 0xb838, 0x0017, 0x4000, 0xa595, 0x1d35 }; unsigned short xseqflx_code_length01 = 0x1036; diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 23f43ec5e..dcc33daa5 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -36,13 +36,12 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) uint16_t mb0, mb2; uint32_t stat; - device_reg_t *reg; - uint16_t *dmp_reg; + device_reg_t __iomem *reg = ha->iobase; + uint16_t __iomem *dmp_reg; unsigned long flags; struct qla2300_fw_dump *fw; uint32_t dump_size, data_ram_cnt; - reg = ha->iobase; risc_address = data_ram_cnt = 0; mb0 = mb2 = 0; flags = 0; @@ -86,89 +85,90 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } } else { + RD_REG_WORD(®->hccr); /* PCI Posting. */ udelay(10); } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t *)(reg + 0); + dmp_reg = (uint16_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x10); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) fw->risc_host_reg[cnt] = RD_REG_WORD(dmp_reg++); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x40); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40); for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x40); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++) fw->resp_dma_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x50); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0xA0); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2800); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2A00); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2C00); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2E00); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++); @@ -221,6 +221,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, @@ -231,11 +232,13 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); } udelay(5); } @@ -277,6 +280,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, @@ -287,11 +291,13 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); } udelay(5); } @@ -334,6 +340,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } else if (stat == 0x10 || stat == 0x11) { set_bit(MBX_INTERRUPT, @@ -344,11 +351,13 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } /* clear this intr; it wasn't a mailbox intr */ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); } udelay(5); } @@ -578,13 +587,11 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) uint32_t cnt, timer; uint16_t risc_address; uint16_t mb0, mb2; - - device_reg_t *reg; - uint16_t *dmp_reg; + device_reg_t __iomem *reg = ha->iobase; + uint16_t __iomem *dmp_reg; unsigned long flags; struct qla2100_fw_dump *fw; - reg = ha->iobase; risc_address = 0; mb0 = mb2 = 0; flags = 0; @@ -624,79 +631,79 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t *)(reg + 0); + dmp_reg = (uint16_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x10); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); for (cnt = 0; cnt < ha->mbx_count; cnt++) { if (cnt == 8) { - dmp_reg = (uint16_t *)((uint8_t *)reg + 0xe0); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xe0); } fw->mailbox_reg[cnt] = RD_REG_WORD(dmp_reg++); } - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x20); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20); for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) fw->dma_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0xA0); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) fw->risc_gp0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2100); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) fw->risc_gp1_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) fw->risc_gp2_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2300); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) fw->risc_gp3_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) fw->risc_gp4_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2500); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) fw->risc_gp5_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) fw->risc_gp6_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->pcr, 0x2700); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) fw->risc_gp7_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) fw->frame_buf_hdw_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) fw->fpm_b0_reg[cnt] = RD_REG_WORD(dmp_reg++); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t *)((uint8_t *)reg + 0x80); + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) fw->fpm_b1_reg[cnt] = RD_REG_WORD(dmp_reg++); @@ -731,6 +738,7 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->mctr, 0xf1); else WRT_REG_WORD(®->mctr, 0xf2); + RD_REG_WORD(®->mctr); /* PCI Posting. */ /* Release RISC. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); @@ -761,9 +769,11 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); break; } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); } udelay(5); } @@ -974,9 +984,7 @@ qla_uprintf(char **uiter, char *fmt, ...) void qla2x00_dump_regs(scsi_qla_host_t *ha) { - device_reg_t *reg; - - reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; printk("Mailbox registers:\n"); printk("scsi(%ld): mbox 0 0x%04x \n", diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 96de77053..6c94b8667 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -232,6 +234,7 @@ /* ISP request and response entry counts (37-65535) */ #define REQUEST_ENTRY_CNT_2100 128 /* Number of request entries. */ #define REQUEST_ENTRY_CNT_2200 2048 /* Number of request entries. */ +#define REQUEST_ENTRY_CNT_2XXX_EXT_MEM 4096 /* Number of request entries. */ #define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/ @@ -2028,6 +2031,16 @@ struct qla_board_info { struct qla_fw_info *fw_info; }; +/* Return data from MBC_GET_ID_LIST call. */ +struct gid_list_info { + uint8_t al_pa; + uint8_t area; + uint8_t domain; + uint8_t loop_id_2100; /* ISP2100/ISP2200 -- 4 bytes. */ + uint16_t loop_id; /* ISP23XX -- 6 bytes. */ +}; +#define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES) + /* * Linux Host Adapter structure */ @@ -2113,11 +2126,9 @@ typedef struct scsi_qla_host { spinlock_t hardware_lock ____cacheline_aligned; - device_reg_t *iobase; /* Base I/O address */ + device_reg_t __iomem *iobase; /* Base I/O address */ unsigned long pio_address; unsigned long pio_length; - void * mmio_address; - unsigned long mmio_length; #define MIN_IOBASE_LEN 0x100 /* ISP ring lock, rings, and indexes */ @@ -2239,8 +2250,6 @@ typedef struct scsi_qla_host { struct io_descriptor io_descriptors[MAX_IO_DESCRIPTORS]; uint16_t iodesc_signature; - port_database_t *iodesc_pd; - dma_addr_t iodesc_pd_dma; /* OS target queue pointers. */ os_tgt_t *otgt[MAX_FIBRE_DEVICES]; @@ -2275,10 +2284,22 @@ typedef struct scsi_qla_host { uint32_t timer_active; struct timer_list timer; - /* Firmware Initialization Control Block data */ - dma_addr_t init_cb_dma; /* Physical address. */ + dma_addr_t gid_list_dma; + struct gid_list_info *gid_list; + + dma_addr_t rlc_rsp_dma; + rpt_lun_cmd_rsp_t *rlc_rsp; + + /* Small DMA pool allocations -- maximum 256 bytes in length. */ +#define DMA_POOL_SIZE 256 + struct dma_pool *s_dma_pool; + + dma_addr_t init_cb_dma; init_cb_t *init_cb; - + + dma_addr_t iodesc_pd_dma; + port_database_t *iodesc_pd; + /* These are used by mailbox operations. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 1b54cde88..ef5abaaf8 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -246,7 +246,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); /* * Global Function Prototypes in qla_isr.c source file. */ -extern irqreturn_t qla2x00_intr_handler(int, void *, struct pt_regs *); +extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *); +extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *); extern void qla2x00_process_response_queue(struct scsi_qla_host *); /* diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e31b5fe3e..aa6e8103d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -37,6 +37,7 @@ static int qla2x00_pci_config(scsi_qla_host_t *); static int qla2x00_isp_firmware(scsi_qla_host_t *); static void qla2x00_reset_chip(scsi_qla_host_t *); static int qla2x00_chip_diag(scsi_qla_host_t *); +static void qla2x00_resize_request_q(scsi_qla_host_t *); static int qla2x00_setup_chip(scsi_qla_host_t *); static void qla2x00_init_response_q_entries(scsi_qla_host_t *); static int qla2x00_init_rings(scsi_qla_host_t *); @@ -50,8 +51,7 @@ static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); static void qla2x00_lun_discovery(scsi_qla_host_t *, fc_port_t *); static int qla2x00_rpt_lun_discovery(scsi_qla_host_t *, fc_port_t *, inq_cmd_rsp_t *, dma_addr_t); -static int qla2x00_report_lun(scsi_qla_host_t *, fc_port_t *, - rpt_lun_cmd_rsp_t *, dma_addr_t); +static int qla2x00_report_lun(scsi_qla_host_t *, fc_port_t *); static fc_lun_t *qla2x00_cfg_lun(scsi_qla_host_t *, fc_port_t *, uint16_t, inq_cmd_rsp_t *, dma_addr_t); static fc_lun_t * qla2x00_add_lun(fc_port_t *, uint16_t); @@ -217,7 +217,9 @@ check_fw_ready_again: rval = QLA_FUNCTION_FAILED; if (ha->mem_err) restart_risc = 1; - } + } else if (ha->device_flags & DFLG_NO_CABLE) + /* If no cable, then all is good. */ + rval = QLA_SUCCESS; } } while (restart_risc && retry--); @@ -306,6 +308,7 @@ qla2x00_pci_config(scsi_qla_host_t *ha) /* Select FPM registers. */ WRT_REG_WORD(&ha->iobase->ctrl_status, 0x20); + RD_REG_WORD(&ha->iobase->ctrl_status); /* Get the fb rev level */ ha->fb_rev = RD_FB_CMD_REG(ha, ha->iobase); @@ -315,6 +318,7 @@ qla2x00_pci_config(scsi_qla_host_t *ha) /* Deselect FPM registers. */ WRT_REG_WORD(&ha->iobase->ctrl_status, 0x0); + RD_REG_WORD(&ha->iobase->ctrl_status); /* Release RISC module. */ WRT_REG_WORD(&ha->iobase->hccr, HCCR_RELEASE_RISC); @@ -381,7 +385,7 @@ static void qla2x00_reset_chip(scsi_qla_host_t *ha) { unsigned long flags = 0; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; uint32_t cnt; unsigned long mbx_flags = 0; uint16_t cmd; @@ -408,25 +412,32 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) udelay(100); } } else { + RD_REG_WORD(®->hccr); /* PCI Posting. */ udelay(10); } /* Select FPM registers. */ WRT_REG_WORD(®->ctrl_status, 0x20); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* FPM Soft Reset. */ WRT_REG_WORD(®->fpm_diag_config, 0x100); + RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */ /* Toggle Fpm Reset. */ - if (!IS_QLA2200(ha)) + if (!IS_QLA2200(ha)) { WRT_REG_WORD(®->fpm_diag_config, 0x0); + RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */ + } /* Select frame buffer registers. */ WRT_REG_WORD(®->ctrl_status, 0x10); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* Reset frame buffer FIFOs. */ if (IS_QLA2200(ha)) { WRT_FB_CMD_REG(ha, reg, 0xa000); + RD_FB_CMD_REG(ha, reg); /* PCI Posting. */ } else { WRT_FB_CMD_REG(ha, reg, 0x00fc); @@ -440,12 +451,15 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) /* Select RISC module registers. */ WRT_REG_WORD(®->ctrl_status, 0); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ /* Release RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); @@ -478,7 +492,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) /* Release RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); - RD_REG_WORD(®->hccr); /* PCI Posting. */ + RD_REG_WORD(®->hccr); /* PCI Posting. */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { @@ -507,8 +521,10 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) pci_write_config_word(ha->pdev, PCI_COMMAND, cmd); /* Disable RISC pause on FPM parity error. */ - if (!IS_QLA2100(ha)) + if (!IS_QLA2100(ha)) { WRT_REG_WORD(®->hccr, HCCR_DISABLE_PARITY_PAUSE); + RD_REG_WORD(®->hccr); /* PCI Posting. */ + } spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -523,7 +539,7 @@ static int qla2x00_chip_diag(scsi_qla_host_t *ha) { int rval; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; unsigned long flags = 0; uint16_t data; uint32_t cnt; @@ -539,6 +555,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) /* Reset ISP chip. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + /* * We need to have a delay here since the card will not respond while * in reset causing an MCA on some architectures. @@ -637,6 +654,59 @@ chip_diag_failed: return (rval); } +/** + * qla2x00_resize_request_q() - Resize request queue given available ISP memory. + * @ha: HA context + * + * Returns 0 on success. + */ +static void +qla2x00_resize_request_q(scsi_qla_host_t *ha) +{ + int rval; + uint16_t fw_iocb_cnt = 0; + uint16_t request_q_length = REQUEST_ENTRY_CNT_2XXX_EXT_MEM; + dma_addr_t request_dma; + request_t *request_ring; + + /* Valid only on recent ISPs. */ + if (IS_QLA2100(ha) || IS_QLA2200(ha)) + return; + + /* Retrieve IOCB counts available to the firmware. */ + rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); + if (rval) + return; + /* No point in continuing if current settings are sufficient. */ + if (fw_iocb_cnt < 1024) + return; + if (ha->request_q_length >= request_q_length) + return; + + /* Attempt to claim larger area for request queue. */ + request_ring = dma_alloc_coherent(&ha->pdev->dev, + (request_q_length + 1) * sizeof(request_t), &request_dma, + GFP_KERNEL); + if (request_ring == NULL) + return; + + /* Resize successful, report extensions. */ + qla_printk(KERN_INFO, ha, "Extended memory detected (%d KB)...\n", + (ha->fw_memory_size + 1) / 1024); + qla_printk(KERN_INFO, ha, "Resizing request queue depth " + "(%d -> %d)...\n", ha->request_q_length, request_q_length); + + /* Clear old allocations. */ + dma_free_coherent(&ha->pdev->dev, + (ha->request_q_length + 1) * sizeof(request_t), ha->request_ring, + ha->request_dma); + + /* Begin using larger queue. */ + ha->request_q_length = request_q_length; + ha->request_ring = request_ring; + ha->request_dma = request_dma; +} + /** * qla2x00_setup_chip() - Load and start RISC firmware. * @ha: HA context @@ -734,9 +804,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_minor_version, &ha->fw_subminor_version, &ha->fw_attributes, &ha->fw_memory_size); + qla2x00_resize_request_q(ha); } - } - else { + } else { DEBUG2(printk(KERN_INFO "scsi(%ld): ISP Firmware failed checksum.\n", ha->host_no)); @@ -783,7 +853,6 @@ qla2x00_init_response_q_entries(scsi_qla_host_t *ha) static void qla2x00_update_fw_options(scsi_qla_host_t *ha) { - /* Setup seriallink options */ uint16_t swing, emphasis; memset(ha->fw_options, 0, sizeof(ha->fw_options)); @@ -807,7 +876,6 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3); emphasis >>= 3; ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3; - /* 2G settings */ swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5); swing >>= 5; @@ -818,7 +886,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) /* Return command IOCBs without waiting for an ABTS to complete. */ ha->fw_options[3] |= BIT_13; - /* Update Serial Link options. */ + /* Update firmware options. */ qla2x00_set_fw_options(ha, ha->fw_options); } @@ -837,13 +905,13 @@ qla2x00_init_rings(scsi_qla_host_t *ha) int rval; unsigned long flags = 0; int cnt; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; spin_lock_irqsave(&ha->hardware_lock, flags); /* Clear outstanding commands array. */ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) - ha->outstanding_cmds[cnt] = 0; + ha->outstanding_cmds[cnt] = NULL; ha->current_outstanding_cmd = 0; @@ -858,6 +926,16 @@ qla2x00_init_rings(scsi_qla_host_t *ha) ha->response_ring_ptr = ha->response_ring; ha->rsp_ring_index = 0; + /* Setup ring parameters in initialization control block. */ + ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); + ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); + ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length); + ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length); + ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); + ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); + ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); + ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); + /* Initialize response queue entries */ qla2x00_init_response_q_entries(ha); @@ -865,19 +943,19 @@ qla2x00_init_rings(scsi_qla_host_t *ha) WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0); WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0); - RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); + RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); + /* Update any ISP specific firmware options before initialization. */ + qla2x00_update_fw_options(ha); + DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); rval = qla2x00_init_firmware(ha, sizeof(init_cb_t)); if (rval) { DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", ha->host_no)); } else { - /* Update any ISP specific firmware options. */ - qla2x00_update_fw_options(ha); - DEBUG3(printk("scsi(%ld): Init firmware -- success.\n", ha->host_no)); } @@ -969,8 +1047,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) break; /* Delay for a while */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 2); + msleep(500); DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", ha->host_no, fw_state, jiffies)); @@ -1115,14 +1192,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) init_cb_t *icb = ha->init_cb; nvram_t *nv = (nvram_t *)ha->request_ring; uint16_t *wptr = (uint16_t *)ha->request_ring; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; uint8_t timer_mode; rval = QLA_SUCCESS; - if (ha->flags.init_done) - return (rval); - /* Determine NVRAM starting address. */ ha->nvram_base = 0; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) @@ -1405,18 +1479,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ha->binding_type = BIND_BY_PORT_NAME; } - /* - * Setup ring parameters in initialization control block - */ - icb->request_q_outpointer = __constant_cpu_to_le16(0); - icb->response_q_inpointer = __constant_cpu_to_le16(0); - icb->request_q_length = cpu_to_le16(ha->request_q_length); - icb->response_q_length = cpu_to_le16(ha->response_q_length); - icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); - icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); - icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); - icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); - icb->lun_enables = __constant_cpu_to_le16(0); icb->command_resource_count = 0; icb->immediate_notify_resource_count = 0; @@ -1640,50 +1702,28 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) uint16_t index; uint16_t entries; - struct dev_id { - uint8_t al_pa; - uint8_t area; - uint8_t domain; - uint8_t loop_id_2100; /* ISP2100/ISP2200 -- 4 bytes. */ - uint16_t loop_id; /* ISP23XX -- 6 bytes. */ - } *id_list; -#define MAX_ID_LIST_SIZE (sizeof(struct dev_id) * MAX_FIBRE_DEVICES) - dma_addr_t id_list_dma; char *id_iter; uint16_t loop_id; uint8_t domain, area, al_pa; found_devs = 0; new_fcport = NULL; - entries = MAX_FIBRE_DEVICES; - id_list = pci_alloc_consistent(ha->pdev, MAX_ID_LIST_SIZE, - &id_list_dma); - if (id_list == NULL) { - DEBUG2(printk("scsi(%ld): Failed to allocate memory, No local " - "loop\n", ha->host_no)); - - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - port_list"); - - ha->mem_err++; - return (QLA_MEMORY_ALLOC_FAILED); - } - memset(id_list, 0, MAX_ID_LIST_SIZE); DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", ha->host_no)); DEBUG3(qla2x00_get_fcal_position_map(ha, NULL)); /* Get list of logged in devices. */ - rval = qla2x00_get_id_list(ha, id_list, id_list_dma, &entries); - if (rval != QLA_SUCCESS) { + memset(ha->gid_list, 0, GID_LIST_SIZE); + rval = qla2x00_get_id_list(ha, ha->gid_list, ha->gid_list_dma, + &entries); + if (rval != QLA_SUCCESS) goto cleanup_allocation; - } DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n", ha->host_no, entries)); - DEBUG3(qla2x00_dump_buffer((uint8_t *)id_list, - entries * sizeof(struct dev_id))); + DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list, + entries * sizeof(struct gid_list_info))); /* Allocate temporary fcport for any new fcports discovered. */ new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); @@ -1711,18 +1751,18 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) } /* Add devices to port list. */ - id_iter = (char *)id_list; + id_iter = (char *)ha->gid_list; for (index = 0; index < entries; index++) { - domain = ((struct dev_id *)id_iter)->domain; - area = ((struct dev_id *)id_iter)->area; - al_pa = ((struct dev_id *)id_iter)->al_pa; + domain = ((struct gid_list_info *)id_iter)->domain; + area = ((struct gid_list_info *)id_iter)->area; + al_pa = ((struct gid_list_info *)id_iter)->al_pa; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - loop_id = - (uint16_t)((struct dev_id *)id_iter)->loop_id_2100; + loop_id = (uint16_t) + ((struct gid_list_info *)id_iter)->loop_id_2100; id_iter += 4; } else { - loop_id = - le16_to_cpu(((struct dev_id *)id_iter)->loop_id); + loop_id = le16_to_cpu( + ((struct gid_list_info *)id_iter)->loop_id); id_iter += 6; } @@ -1793,8 +1833,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) } cleanup_allocation: - pci_free_consistent(ha->pdev, MAX_ID_LIST_SIZE, id_list, id_list_dma); - if (new_fcport) kfree(new_fcport); @@ -1902,7 +1940,7 @@ qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport) dma_addr_t inq_dma; uint16_t lun; - inq = pci_alloc_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), &inq_dma); + inq = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &inq_dma); if (inq == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - INQ\n"); @@ -1918,7 +1956,7 @@ qla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport) } } - pci_free_consistent(ha->pdev, sizeof(inq_cmd_rsp_t), inq, inq_dma); + dma_pool_free(ha->s_dma_pool, inq, inq_dma); } /* @@ -1942,8 +1980,6 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, int rval; uint32_t len, cnt; uint16_t lun; - rpt_lun_cmd_rsp_t *rlc; - dma_addr_t rlc_dma; /* Assume a failed status */ rval = QLA_FUNCTION_FAILED; @@ -1952,30 +1988,19 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, if ((fcport->flags & FCF_RLC_SUPPORT) == 0) return (rval); - rlc = pci_alloc_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), - &rlc_dma); - if (rlc == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - RLC"); - return QLA_MEMORY_ALLOC_FAILED; - } - - rval = qla2x00_report_lun(ha, fcport, rlc, rlc_dma); - if (rval != QLA_SUCCESS) { - pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), rlc, - rlc_dma); + rval = qla2x00_report_lun(ha, fcport); + if (rval != QLA_SUCCESS) return (rval); - } /* Always add a fc_lun_t structure for lun 0 -- mid-layer requirement */ qla2x00_add_lun(fcport, 0); /* Configure LUN list. */ - len = be32_to_cpu(rlc->list.hdr.len); + len = be32_to_cpu(ha->rlc_rsp->list.hdr.len); len /= 8; for (cnt = 0; cnt < len; cnt++) { - lun = CHAR_TO_SHORT(rlc->list.lst[cnt].lsb, - rlc->list.lst[cnt].msb.b); + lun = CHAR_TO_SHORT(ha->rlc_rsp->list.lst[cnt].lsb, + ha->rlc_rsp->list.lst[cnt].msb.b); DEBUG3(printk("scsi(%ld): RLC lun = (%d)\n", ha->host_no, lun)); @@ -1986,8 +2011,6 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, } atomic_set(&fcport->state, FCS_ONLINE); - pci_free_consistent(ha->pdev, sizeof(rpt_lun_cmd_rsp_t), rlc, rlc_dma); - return (rval); } @@ -1998,8 +2021,6 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, * Input: * ha: adapter state pointer. * fcport: FC port structure pointer. - * mem: pointer to dma memory object for report LUN IOCB - * packet. * * Returns: * qla2x00 local function return status code. @@ -2008,15 +2029,18 @@ qla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport, * Kernel context. */ static int -qla2x00_report_lun(scsi_qla_host_t *ha, - fc_port_t *fcport, rpt_lun_cmd_rsp_t *rlc, dma_addr_t rlc_dma) +qla2x00_report_lun(scsi_qla_host_t *ha, fc_port_t *fcport) { int rval; uint16_t retries; uint16_t comp_status; uint16_t scsi_status; + rpt_lun_cmd_rsp_t *rlc; + dma_addr_t rlc_dma; rval = QLA_FUNCTION_FAILED; + rlc = ha->rlc_rsp; + rlc_dma = ha->rlc_rsp_dma; for (retries = 3; retries; retries--) { memset(rlc, 0, sizeof(rpt_lun_cmd_rsp_t)); @@ -4133,7 +4157,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { sp = ha->outstanding_cmds[cnt]; if (sp) { - ha->outstanding_cmds[cnt] = 0; + ha->outstanding_cmds[cnt] = NULL; if (ha->actthreads) ha->actthreads--; sp->lun_queue->out_cnt--; @@ -4247,7 +4271,7 @@ static int qla2x00_restart_isp(scsi_qla_host_t *ha) { uint8_t status = 0; - device_reg_t *reg; + device_reg_t __iomem *reg = ha->iobase; unsigned long flags = 0; uint32_t wait_time; @@ -4261,9 +4285,13 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) } reg = ha->iobase; + spin_lock_irqsave(&ha->hardware_lock, flags); + /* Disable SRAM, Instruction RAM and GP RAM parity. */ WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x0)); + RD_REG_WORD(®->hccr); /* PCI Posting. */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); status = qla2x00_setup_chip(ha); @@ -4279,6 +4307,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) /* SRAM, Instruction RAM and GP RAM parity */ WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x7)); + RD_REG_WORD(®->hccr); /* PCI Posting. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -4327,13 +4356,16 @@ static void qla2x00_reset_adapter(scsi_qla_host_t *ha) { unsigned long flags = 0; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; ha->flags.online = 0; qla2x00_disable_intrs(ha); + /* Reset RISC processor. */ spin_lock_irqsave(&ha->hardware_lock, flags); WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); + RD_REG_WORD(®->hccr); /* PCI Posting. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); } diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 9bd7757b9..07c11330f 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -18,7 +18,7 @@ */ -static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t *); +static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *); /* * qla2x00_debounce_register * Debounce register. @@ -30,7 +30,7 @@ static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t *); * register value. */ static __inline__ uint16_t -qla2x00_debounce_register(volatile uint16_t *addr) +qla2x00_debounce_register(volatile uint16_t __iomem *addr) { volatile uint16_t first; volatile uint16_t second; @@ -117,7 +117,10 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *); static inline void qla2x00_poll(scsi_qla_host_t *ha) { - qla2x00_intr_handler(0, ha, NULL); + if (IS_QLA2100(ha) || IS_QLA2200(ha)) + qla2100_intr_handler(0, ha, NULL); + else + qla2300_intr_handler(0, ha, NULL); } @@ -128,10 +131,9 @@ static inline void qla2x00_enable_intrs(scsi_qla_host_t *ha) { unsigned long flags = 0; - device_reg_t *reg; + device_reg_t __iomem *reg = ha->iobase; spin_lock_irqsave(&ha->hardware_lock, flags); - reg = ha->iobase; ha->interrupts_on = 1; /* enable risc and host interrupts */ WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); @@ -144,10 +146,9 @@ static inline void qla2x00_disable_intrs(scsi_qla_host_t *ha) { unsigned long flags = 0; - device_reg_t *reg; + device_reg_t __iomem *reg = ha->iobase; spin_lock_irqsave(&ha->hardware_lock, flags); - reg = ha->iobase; ha->interrupts_on = 0; /* disable risc and host interrupts */ WRT_REG_WORD(®->ictrl, 0); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 710a88d67..ed3f9413a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -22,6 +22,8 @@ #include #include +#include + static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd); static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *); static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *); @@ -336,14 +338,15 @@ qla2x00_start_scsi(srb_t *sp) uint16_t cnt; uint16_t req_cnt; uint16_t tot_dsds; - device_reg_t *reg; + device_reg_t __iomem *reg; + char tag[2]; /* Setup device pointers. */ ret = 0; fclun = sp->lun_queue->fclun; ha = fclun->fcport->ha; - cmd = sp->cmd; reg = ha->iobase; + cmd = sp->cmd; /* Send marker if required */ if (ha->marker_needed != 0) { @@ -416,13 +419,13 @@ qla2x00_start_scsi(srb_t *sp) /* Update tagged queuing modifier */ cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); - if (cmd->device->tagged_supported) { - switch (cmd->tag) { - case HEAD_OF_QUEUE_TAG: + if (scsi_populate_tag_msg(cmd, tag)) { + switch (tag[0]) { + case MSG_HEAD_TAG: cmd_pkt->control_flags = __constant_cpu_to_le16(CF_HEAD_TAG); break; - case ORDERED_QUEUE_TAG: + case MSG_ORDERED_TAG: cmd_pkt->control_flags = __constant_cpu_to_le16(CF_ORDERED_TAG); break; @@ -544,7 +547,7 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, request_t * qla2x00_req_pkt(scsi_qla_host_t *ha) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; request_t *pkt = NULL; uint16_t cnt; uint32_t *dword_ptr; @@ -613,7 +616,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) request_t * qla2x00_ms_req_pkt(scsi_qla_host_t *ha, srb_t *sp) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; request_t *pkt = NULL; uint16_t cnt, i, index; uint32_t *dword_ptr; @@ -703,7 +706,7 @@ qla2x00_ms_req_pkt(scsi_qla_host_t *ha, srb_t *sp) void qla2x00_isp_cmd(scsi_qla_host_t *ha) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; DEBUG5(printk("%s(): IOCB data:\n", __func__)); DEBUG5(qla2x00_dump_buffer( diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f9284fd87..5dbbc5197 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -30,7 +30,7 @@ static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *); /** - * qla2x00_intr_handler() - Process interrupts for the ISP. + * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: * @dev_id: SCSI driver HA context * @regs: @@ -40,20 +40,14 @@ static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *); * Returns handled flag. */ irqreturn_t -qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { scsi_qla_host_t *ha; - device_reg_t *reg; + device_reg_t __iomem *reg; + int status; + unsigned long flags; + unsigned long iter; uint32_t mbx; - int status = 0; - unsigned long flags = 0; - unsigned long mbx_flags = 0; - unsigned long intr_iter; - uint32_t stat; - uint16_t hccr; - - /* Don't loop forever, interrupt are OFF */ - intr_iter = 50; ha = (scsi_qla_host_t *) dev_id; if (!ha) { @@ -63,107 +57,40 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) } reg = ha->iobase; + status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); - - for (;;) { - /* Relax CPU! */ - if (!(intr_iter--)) + for (iter = 50; iter--; ) { + if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) break; - if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) - break; - - if (RD_REG_WORD(®->semaphore) & BIT_0) { - WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); - RD_REG_WORD(®->hccr); - - /* Get mailbox data. */ - mbx = RD_MAILBOX_REG(ha, reg, 0); - if (mbx > 0x3fff && mbx < 0x8000) { - qla2x00_mbx_completion(ha, - (uint16_t)mbx); - status |= MBX_INTERRUPT; - } else if (mbx > 0x7fff && mbx < 0xc000) { - qla2x00_async_event(ha, mbx); - } else { - /*EMPTY*/ - DEBUG2(printk("scsi(%ld): Unrecognized " - "interrupt type (%d)\n", - ha->host_no, mbx)); - } - /* Release mailbox registers. */ - WRT_REG_WORD(®->semaphore, 0); - /* Workaround for ISP2100 chip. */ - if (IS_QLA2100(ha)) - RD_REG_WORD(®->semaphore); - } else { - qla2x00_process_response_queue(ha); - - WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); - RD_REG_WORD(®->hccr); - } - } else /* IS_QLA23XX(ha) */ { - stat = RD_REG_DWORD(®->u.isp2300.host_status); - if (stat & HSR_RISC_PAUSED) { - hccr = RD_REG_WORD(®->hccr); - if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) - qla_printk(KERN_INFO, ha, - "Parity error -- HCCR=%x.\n", hccr); - else - qla_printk(KERN_INFO, ha, - "RISC paused -- HCCR=%x\n", hccr); - - /* - * Issue a "HARD" reset in order for the RISC - * interrupt bit to be cleared. Schedule a big - * hammmer to get out of the RISC PAUSED state. - */ - WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); - RD_REG_WORD(®->hccr); - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - break; - } else if ((stat & HSR_RISC_INT) == 0) - break; + if (RD_REG_WORD(®->semaphore) & BIT_0) { + WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD(®->hccr); - mbx = MSW(stat); - switch (stat & 0xff) { - case 0x13: - qla2x00_process_response_queue(ha); - break; - case 0x1: - case 0x2: - case 0x10: - case 0x11: + /* Get mailbox data. */ + mbx = RD_MAILBOX_REG(ha, reg, 0); + if (mbx > 0x3fff && mbx < 0x8000) { qla2x00_mbx_completion(ha, (uint16_t)mbx); status |= MBX_INTERRUPT; - - /* Release mailbox registers. */ - WRT_REG_WORD(®->semaphore, 0); - break; - case 0x12: - qla2x00_async_event(ha, mbx); - break; - case 0x15: - mbx = mbx << 16 | MBA_CMPLT_1_16BIT; - qla2x00_async_event(ha, mbx); - break; - case 0x16: - mbx = mbx << 16 | MBA_SCSI_COMPLETION; + } else if (mbx > 0x7fff && mbx < 0xc000) { qla2x00_async_event(ha, mbx); - break; - default: + } else { + /*EMPTY*/ DEBUG2(printk("scsi(%ld): Unrecognized " "interrupt type (%d)\n", - ha->host_no, stat & 0xff)); - break; + ha->host_no, mbx)); } + /* Release mailbox registers. */ + WRT_REG_WORD(®->semaphore, 0); + RD_REG_WORD(®->semaphore); + } else { + qla2x00_process_response_queue(ha); + WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); - RD_REG_WORD_RELAXED(®->hccr); + RD_REG_WORD(®->hccr); } } - spin_unlock_irqrestore(&ha->hardware_lock, flags); qla2x00_next(ha); @@ -172,48 +99,130 @@ qla2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { + spin_lock_irqsave(&ha->mbx_reg_lock, flags); - /* There was a mailbox completion */ - DEBUG3(printk("%s(%ld): Going to get mbx reg lock.\n", - __func__, ha->host_no)); + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + up(&ha->mbx_intr_sem); - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); + spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); + } - if (ha->mcp == NULL) { - DEBUG3(printk("%s(%ld): Error mbx pointer.\n", - __func__, ha->host_no)); - } else { - DEBUG3(printk("%s(%ld): Going to set mbx intr flags. " - "cmd=%x.\n", - __func__, ha->host_no, ha->mcp->mb[0])); - } - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + if (!list_empty(&ha->done_queue)) + qla2x00_done(ha); - DEBUG3(printk("%s(%ld): Going to wake up mbx function for " - "completion.\n", - __func__, ha->host_no)); + return (IRQ_HANDLED); +} - up(&ha->mbx_intr_sem); +/** + * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. + * @irq: + * @dev_id: SCSI driver HA context + * @regs: + * + * Called by system whenever the host adapter generates an interrupt. + * + * Returns handled flag. + */ +irqreturn_t +qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + scsi_qla_host_t *ha; + device_reg_t __iomem *reg; + int status; + unsigned long flags; + unsigned long iter; + uint32_t stat; + uint32_t mbx; + uint16_t hccr; - DEBUG3(printk("%s(%ld): Going to release mbx reg lock.\n", - __func__, ha->host_no)); + ha = (scsi_qla_host_t *) dev_id; + if (!ha) { + printk(KERN_INFO + "%s(): NULL host pointer\n", __func__); + return (IRQ_NONE); + } + + reg = ha->iobase; + status = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (iter = 50; iter--; ) { + stat = RD_REG_DWORD(®->u.isp2300.host_status); + if (stat & HSR_RISC_PAUSED) { + hccr = RD_REG_WORD(®->hccr); + if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) + qla_printk(KERN_INFO, ha, + "Parity error -- HCCR=%x.\n", hccr); + else + qla_printk(KERN_INFO, ha, + "RISC paused -- HCCR=%x\n", hccr); + + /* + * Issue a "HARD" reset in order for the RISC + * interrupt bit to be cleared. Schedule a big + * hammmer to get out of the RISC PAUSED state. + */ + WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + } else if ((stat & HSR_RISC_INT) == 0) + break; - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); + mbx = MSW(stat); + switch (stat & 0xff) { + case 0x13: + qla2x00_process_response_queue(ha); + break; + case 0x1: + case 0x2: + case 0x10: + case 0x11: + qla2x00_mbx_completion(ha, (uint16_t)mbx); + status |= MBX_INTERRUPT; + + /* Release mailbox registers. */ + WRT_REG_WORD(®->semaphore, 0); + break; + case 0x12: + qla2x00_async_event(ha, mbx); + break; + case 0x15: + mbx = mbx << 16 | MBA_CMPLT_1_16BIT; + qla2x00_async_event(ha, mbx); + break; + case 0x16: + mbx = mbx << 16 | MBA_SCSI_COMPLETION; + qla2x00_async_event(ha, mbx); + break; + default: + DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " + "(%d)\n", + ha->host_no, stat & 0xff)); + break; + } + WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); + RD_REG_WORD_RELAXED(®->hccr); } + spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!list_empty(&ha->done_queue)) - qla2x00_done(ha); + qla2x00_next(ha); + ha->last_irq_cpu = smp_processor_id(); + ha->total_isr_cnt++; + + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + (status & MBX_INTERRUPT) && ha->flags.mbox_int) { + spin_lock_irqsave(&ha->mbx_reg_lock, flags); - /* Wakeup the DPC routine */ - if ((!ha->flags.mbox_busy && - (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || - test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || - test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) && - ha->dpc_wait && !ha->dpc_active) { + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + up(&ha->mbx_intr_sem); - up(ha->dpc_wait); + spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } + if (!list_empty(&ha->done_queue)) + qla2x00_done(ha); + return (IRQ_HANDLED); } @@ -226,17 +235,17 @@ static void qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) { uint16_t cnt; - uint16_t *wptr; - device_reg_t *reg = ha->iobase; + uint16_t __iomem *wptr; + device_reg_t __iomem *reg = ha->iobase; /* Load return mailbox registers. */ ha->flags.mbox_int = 1; ha->mailbox_out[0] = mb0; - wptr = (uint16_t *)MAILBOX_REG(ha, reg, 1); + wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1); for (cnt = 1; cnt < ha->mbx_count; cnt++) { if (IS_QLA2200(ha) && cnt == 8) - wptr = (uint16_t *)MAILBOX_REG(ha, reg, 8); + wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); if (cnt == 4 || cnt == 5) ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr); else @@ -268,7 +277,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) uint16_t handle_cnt; uint16_t cnt; uint32_t handles[5]; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; uint32_t rscn_entry, host_pid; uint8_t rscn_queue_index; @@ -574,7 +583,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx) } /* - * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET + * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET * event etc. earlier indicating loop is down) then process * it. Otherwise ignore it and Wait for RSCN to come in. */ @@ -715,7 +724,7 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index) void qla2x00_process_response_queue(struct scsi_qla_host *ha) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; sts_entry_t *pkt; uint16_t handle_cnt; uint16_t cnt; @@ -969,7 +978,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) sizeof(cp->sense_buffer)) sense_sz = le16_to_cpu(pkt->req_sense_length); else - sense_sz = sizeof(cp->sense_buffer) - 1; + sense_sz = sizeof(cp->sense_buffer); CMD_ACTUAL_SNSLEN(cp) = sense_sz; sp->request_sense_length = sense_sz; @@ -1039,7 +1048,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt) sizeof(cp->sense_buffer)) sense_sz = le16_to_cpu(pkt->req_sense_length); else - sense_sz = sizeof(cp->sense_buffer) - 1; + sense_sz = sizeof(cp->sense_buffer); CMD_ACTUAL_SNSLEN(cp) = sense_sz; sp->request_sense_length = sense_sz; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index eadc3d4d2..db3854123 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -58,12 +58,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) { int rval; unsigned long flags = 0; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; struct timer_list tmp_intr_timer; uint8_t abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); uint8_t io_lock_on = ha->flags.init_done; uint16_t command; - uint16_t *iptr, *optr; + uint16_t *iptr; + uint16_t __iomem *optr; uint32_t cnt; uint32_t mboxes; unsigned long mbx_flags = 0; @@ -101,7 +102,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) spin_lock_irqsave(&ha->hardware_lock, flags); /* Load mailbox registers. */ - optr = (uint16_t *)MAILBOX_REG(ha, reg, 0); + optr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 0); iptr = mcp->mb; command = mcp->mb[0]; @@ -109,7 +110,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) for (cnt = 0; cnt < ha->mbx_count; cnt++) { if (IS_QLA2200(ha) && cnt == 8) - optr = (uint16_t *)MAILBOX_REG(ha, reg, 8); + optr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); if (mboxes & BIT_0) WRT_REG_WORD(optr, *iptr); @@ -209,6 +210,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) /* Check whether we timed out */ if (ha->flags.mbox_int) { + uint16_t *iptr2; DEBUG3_11(printk("qla2x00_mailbox_cmd: cmd %x completed.\n", command);) @@ -223,15 +225,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) } /* Load return mailbox registers. */ - optr = mcp->mb; + iptr2 = mcp->mb; iptr = (uint16_t *)&ha->mailbox_out[0]; mboxes = mcp->in_mb; for (cnt = 0; cnt < ha->mbx_count; cnt++) { if (mboxes & BIT_0) - *optr = *iptr; + *iptr2 = *iptr; mboxes >>= 1; - optr++; + iptr2++; iptr++; } } else { @@ -1403,7 +1405,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) DEBUG11(printk("qla2x00_get_port_database(%ld): entered.\n", ha->host_no);) - pd = pci_alloc_consistent(ha->pdev, PORT_DATABASE_SIZE, &pd_dma); + pd = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pd_dma); if (pd == NULL) { DEBUG2_3_11(printk("qla2x00_get_port_database(%ld): **** " "Mem Alloc Failed ****", ha->host_no);) @@ -1464,7 +1466,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) fcport->port_type = FCT_TARGET; gpd_error_out: - pci_free_consistent(ha->pdev, PORT_DATABASE_SIZE, pd, pd_dma); + dma_pool_free(ha->s_dma_pool, pd, pd_dma); if (rval != QLA_SUCCESS) { /*EMPTY*/ @@ -1617,14 +1619,12 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; link_stat_t *stat_buf; - dma_addr_t phys_address = 0; - + dma_addr_t stat_buf_dma; DEBUG11(printk("qla2x00_get_link_status(%ld): entered.\n", ha->host_no);) - stat_buf = pci_alloc_consistent(ha->pdev, sizeof(link_stat_t), - &phys_address); + stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma); if (stat_buf == NULL) { DEBUG2_3_11(printk("qla2x00_get_link_status(%ld): Failed to " "allocate memory.\n", ha->host_no)); @@ -1641,10 +1641,10 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, } else { mcp->mb[1] = loop_id << 8; } - mcp->mb[2] = MSW(phys_address); - mcp->mb[3] = LSW(phys_address); - mcp->mb[6] = MSW(MSD(phys_address)); - mcp->mb[7] = LSW(MSD(phys_address)); + mcp->mb[2] = MSW(stat_buf_dma); + mcp->mb[3] = LSW(stat_buf_dma); + mcp->mb[6] = MSW(MSD(stat_buf_dma)); + mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->in_mb = MBX_0; mcp->tov = 30; @@ -1688,8 +1688,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, rval = BIT_1; } - pci_free_consistent(ha->pdev, sizeof(link_stat_t), stat_buf, - phys_address); + dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma); return rval; } @@ -2409,7 +2408,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) char *pmap; dma_addr_t pmap_dma; - pmap = pci_alloc_consistent(ha->pdev, FCAL_MAP_SIZE, &pmap_dma); + pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma); if (pmap == NULL) { DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", __func__, ha->host_no)); @@ -2438,7 +2437,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) if (pos_map) memcpy(pos_map, pmap, FCAL_MAP_SIZE); } - pci_free_consistent(ha->pdev, FCAL_MAP_SIZE, pmap, pmap_dma); + dma_pool_free(ha->s_dma_pool, pmap, pmap_dma); if (rval != QLA_SUCCESS) { DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index dd5aaba4e..143305bef 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -235,67 +236,6 @@ static __inline__ void sp_get(struct scsi_qla_host * ha, srb_t *sp); static __inline__ void qla2x00_delete_from_done_queue(scsi_qla_host_t *, srb_t *); -/************************************************************************** -* sp_put -* -* Description: -* Decrement reference count and call the callback if we're the last -* owner of the specified sp. Will get the host_lock before calling -* the callback. -* -* Input: -* ha - pointer to the scsi_qla_host_t where the callback is to occur. -* sp - pointer to srb_t structure to use. -* -* Returns: -* -**************************************************************************/ -static inline void -sp_put(struct scsi_qla_host * ha, srb_t *sp) -{ - if (atomic_read(&sp->ref_count) == 0) { - qla_printk(KERN_INFO, ha, - "%s(): **** SP->ref_count not zero\n", - __func__); - DEBUG2(BUG();) - - return; - } - - if (!atomic_dec_and_test(&sp->ref_count)) { - return; - } - - qla2x00_callback(ha, sp->cmd); -} - -/************************************************************************** -* sp_get -* -* Description: -* Increment reference count of the specified sp. -* -* Input: -* sp - pointer to srb_t structure to use. -* -* Returns: -* -**************************************************************************/ -static inline void -sp_get(struct scsi_qla_host * ha, srb_t *sp) -{ - atomic_inc(&sp->ref_count); - - if (atomic_read(&sp->ref_count) > 2) { - qla_printk(KERN_INFO, ha, - "%s(): **** SP->ref_count greater than two\n", - __func__); - DEBUG2(BUG();) - - return; - } -} - /* * qla2x00_callback * Returns the completed SCSI command to LINUX. @@ -366,6 +306,67 @@ qla2x00_callback(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) (*(cmd)->scsi_done)(cmd); } +/************************************************************************** +* sp_put +* +* Description: +* Decrement reference count and call the callback if we're the last +* owner of the specified sp. Will get the host_lock before calling +* the callback. +* +* Input: +* ha - pointer to the scsi_qla_host_t where the callback is to occur. +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_put(struct scsi_qla_host * ha, srb_t *sp) +{ + if (atomic_read(&sp->ref_count) == 0) { + qla_printk(KERN_INFO, ha, + "%s(): **** SP->ref_count not zero\n", + __func__); + DEBUG2(BUG();) + + return; + } + + if (!atomic_dec_and_test(&sp->ref_count)) { + return; + } + + qla2x00_callback(ha, sp->cmd); +} + +/************************************************************************** +* sp_get +* +* Description: +* Increment reference count of the specified sp. +* +* Input: +* sp - pointer to srb_t structure to use. +* +* Returns: +* +**************************************************************************/ +static inline void +sp_get(struct scsi_qla_host * ha, srb_t *sp) +{ + atomic_inc(&sp->ref_count); + + if (atomic_read(&sp->ref_count) > 2) { + qla_printk(KERN_INFO, ha, + "%s(): **** SP->ref_count greater than two\n", + __func__); + DEBUG2(BUG();) + + return; + } +} + static inline void qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp) { @@ -753,7 +754,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) cmd->host_scribble = (unsigned char *)handle; /* Bookkeeping information */ - sp->r_start = jiffies; /* time the request was recieved */ + sp->r_start = jiffies; /* time the request was received */ sp->u_start = 0; /* Setup device queue pointers. */ @@ -844,11 +845,9 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)) was_empty = add_to_pending_queue(ha, sp); if ((IS_QLA2100(ha) || IS_QLA2200(ha)) && ha->flags.online) { - unsigned long flags; - device_reg_t *reg; - reg = ha->iobase; - if (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) { + unsigned long flags; + spin_lock_irqsave(&ha->hardware_lock, flags); qla2x00_process_response_queue(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -969,8 +968,7 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) || ha->dpc_active) && time_before(jiffies, wait_online)) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + msleep(1000); } if (ha->flags.online) return_status = QLA_SUCCESS; @@ -1011,8 +1009,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) atomic_read(&ha->loop_state) == LOOP_DOWN) || test_bit(CFG_ACTIVE, &ha->cfg_flags) || atomic_read(&ha->loop_state) != LOOP_READY) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + msleep(1000); if (time_after_eq(jiffies, loop_timeout)) { return_status = QLA_FUNCTION_FAILED; break; @@ -1583,14 +1580,10 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) if (rval == FAILED) goto out; - /* - * Blocking Call. It goes to sleep waiting for cmd to get to done q - * - * XXX(hch): really? We're under host_lock here.. - */ /* Waiting for our command in done_queue to be returned to OS.*/ - if (!qla2x00_eh_wait_for_pending_commands(ha)) - rval = FAILED; + if (cmd->device->host->eh_active) + if (!qla2x00_eh_wait_for_pending_commands(ha)) + rval = FAILED; out: qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, @@ -1663,7 +1656,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) goto out; /* Waiting for our command in done_queue to be returned to OS.*/ - if (qla2x00_eh_wait_for_pending_commands(ha)) + if (!qla2x00_eh_wait_for_pending_commands(ha)) rval = FAILED; out: @@ -1784,7 +1777,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev) ql2xmaxqdepth = queue_depth; - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + scsi_activate_tcq(sdev, queue_depth); qla_printk(KERN_INFO, ha, "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue " @@ -1819,28 +1812,27 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) * assist in setting the proper dma mask. */ if (sizeof(dma_addr_t) > 4) { - /* Update our PCI device dma_mask for full 64 bits */ - if (pci_set_dma_mask(ha->pdev, 0xffffffffffffffffULL) == 0) { + if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) { ha->flags.enable_64bit_addressing = 1; ha->calc_request_entries = qla2x00_calc_iocbs_64; ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_64; if (pci_set_consistent_dma_mask(ha->pdev, - 0xffffffffffffffffULL)) { + DMA_64BIT_MASK)) { qla_printk(KERN_DEBUG, ha, "Failed to set 64 bit PCI consistent mask; " "using 32 bit.\n"); pci_set_consistent_dma_mask(ha->pdev, - 0xffffffffULL); + DMA_32BIT_MASK); } } else { qla_printk(KERN_DEBUG, ha, "Failed to set 64 bit PCI DMA mask, falling back " "to 32 bit MASK.\n"); - pci_set_dma_mask(ha->pdev, 0xffffffff); + pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); } } else { - pci_set_dma_mask(ha->pdev, 0xffffffff); + pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK); } } @@ -1896,15 +1888,13 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) ha->pio_address = pio; ha->pio_length = pio_len; - ha->mmio_address = ioremap(mmio, MIN_IOBASE_LEN); - if (!ha->mmio_address) { + ha->iobase = ioremap(mmio, MIN_IOBASE_LEN); + if (!ha->iobase) { qla_printk(KERN_ERR, ha, "cannot remap MMIO (%s), aborting\n", ha->pdev->slot_name); goto iospace_error_exit; } - ha->mmio_length = mmio_len; - ha->iobase = (device_reg_t *) ha->mmio_address; return (0); @@ -1918,7 +1908,7 @@ iospace_error_exit: int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) { int ret; - device_reg_t *reg; + device_reg_t __iomem *reg; struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; @@ -1934,7 +1924,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) if (host == NULL) { printk(KERN_WARNING "qla2xxx: Couldn't allocate host from scsi layer!\n"); - return -1; + goto probe_disable_device; } /* Clear our data area */ @@ -2068,8 +2058,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) host->unique_id = ha->instance; host->max_id = ha->max_targets; - if (request_irq(host->irq, qla2x00_intr_handler, SA_INTERRUPT|SA_SHIRQ, - ha->brd_info->drv_name, ha)) { + if (IS_QLA2100(ha) || IS_QLA2200(ha)) + ret = request_irq(host->irq, qla2100_intr_handler, + SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); + else + ret = request_irq(host->irq, qla2300_intr_handler, + SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); + if (ret != 0) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", host->irq); @@ -2120,8 +2115,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) qla2x00_check_fabric_devices(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + msleep(10); } pci_set_drvdata(pdev, ha); @@ -2158,6 +2152,9 @@ probe_failed: scsi_host_put(host); +probe_disable_device: + pci_disable_device(pdev); + return -1; } EXPORT_SYMBOL_GPL(qla2x00_probe_one); @@ -2224,12 +2221,11 @@ qla2x00_free_device(scsi_qla_host_t *ha) free_irq(ha->pdev->irq, ha); /* release io space registers */ + if (ha->iobase) + iounmap(ha->iobase); pci_release_regions(ha->pdev); -#if MEMORY_MAPPED_IO - if (ha->mmio_address) - iounmap(ha->mmio_address); -#endif + pci_disable_device(ha->pdev); } @@ -2815,6 +2811,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *ha) { + char name[16]; uint8_t status = 1; int retry= 10; @@ -2825,57 +2822,105 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) * bug where available mem is not allocated until after a * little delay and a retry. */ - ha->request_ring = pci_alloc_consistent(ha->pdev, - ((ha->request_q_length + 1) * (sizeof(request_t))), - &ha->request_dma); + ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, + (ha->request_q_length + 1) * sizeof(request_t), + &ha->request_dma, GFP_KERNEL); if (ha->request_ring == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - request_ring\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } - ha->response_ring = pci_alloc_consistent(ha->pdev, - ((ha->response_q_length + 1) * (sizeof(response_t))), - &ha->response_dma); + ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, + (ha->response_q_length + 1) * sizeof(response_t), + &ha->response_dma, GFP_KERNEL); if (ha->response_ring == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - response_ring\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); + + continue; + } + + ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, + &ha->gid_list_dma, GFP_KERNEL); + if (ha->gid_list == NULL) { + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - gid_list\n"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + + ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev, + sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL); + if (ha->rlc_rsp == NULL) { + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - rlc"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + + snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no); + ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, + DMA_POOL_SIZE, 8, 0); + if (ha->s_dma_pool == NULL) { + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - s_dma_pool\n"); + + qla2x00_mem_free(ha); + msleep(100); continue; } /* get consistent memory allocated for init control block */ - ha->init_cb = pci_alloc_consistent(ha->pdev, - sizeof(init_cb_t), &ha->init_cb_dma); + ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->init_cb_dma); if (ha->init_cb == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - init_cb\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } memset(ha->init_cb, 0, sizeof(init_cb_t)); + /* Get consistent memory allocated for Get Port Database cmd */ + ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->iodesc_pd_dma); + if (ha->iodesc_pd == NULL) { + /* error */ + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - iodesc_pd\n"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); + /* Allocate ioctl related memory. */ if (qla2x00_alloc_ioctl_mem(ha)) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ioctl_mem\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } @@ -2886,8 +2931,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) "qla2x00_allocate_sp_pool()\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } @@ -2895,32 +2939,31 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) /* Allocate memory for SNS commands */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) { /* Get consistent memory allocated for SNS commands */ - ha->sns_cmd = pci_alloc_consistent(ha->pdev, - sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma); + ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, + GFP_KERNEL); if (ha->sns_cmd == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - sns_cmd\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt)); } else { /* Get consistent memory allocated for MS IOCB */ - ha->ms_iocb = pci_alloc_consistent(ha->pdev, - sizeof(ms_iocb_entry_t), &ha->ms_iocb_dma); + ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, + &ha->ms_iocb_dma); if (ha->ms_iocb == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ms_iocb\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } @@ -2930,38 +2973,22 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) * Get consistent memory allocated for CT SNS * commands */ - ha->ct_sns = pci_alloc_consistent(ha->pdev, - sizeof(struct ct_sns_pkt), &ha->ct_sns_dma); + ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, + sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, + GFP_KERNEL); if (ha->ct_sns == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ct_sns\n"); qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); continue; } memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); } - /* Get consistent memory allocated for Get Port Database cmd */ - ha->iodesc_pd = pci_alloc_consistent(ha->pdev, - PORT_DATABASE_SIZE, &ha->iodesc_pd_dma); - if (ha->iodesc_pd == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - iodesc_pd\n"); - - qla2x00_mem_free(ha); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - - continue; - } - memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); - /* Done all allocations without any error. */ status = 0; @@ -3016,52 +3043,67 @@ qla2x00_mem_free(scsi_qla_host_t *ha) /* free sp pool */ qla2x00_free_sp_pool(ha); - if (ha->iodesc_pd) { - pci_free_consistent(ha->pdev, PORT_DATABASE_SIZE, - ha->iodesc_pd, ha->iodesc_pd_dma); - } + if (ha->sns_cmd) + dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), + ha->sns_cmd, ha->sns_cmd_dma); - if (ha->sns_cmd) { - pci_free_consistent(ha->pdev, - sizeof(struct sns_cmd_pkt), ha->sns_cmd, ha->sns_cmd_dma); - } + if (ha->ct_sns) + dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), + ha->ct_sns, ha->ct_sns_dma); - if (ha->ct_sns) { - pci_free_consistent(ha->pdev, - sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma); - } - if (ha->ms_iocb) { - pci_free_consistent(ha->pdev, - sizeof(ms_iocb_entry_t), ha->ms_iocb, ha->ms_iocb_dma); - } + if (ha->ms_iocb) + dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); - if (ha->init_cb) { - pci_free_consistent(ha->pdev, - sizeof(init_cb_t), ha->init_cb, ha->init_cb_dma); - } + if (ha->iodesc_pd) + dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma); - if (ha->request_ring) { - pci_free_consistent(ha->pdev, - ((ha->request_q_length + 1) * (sizeof(request_t))), - ha->request_ring, ha->request_dma); - } + if (ha->init_cb) + dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); + + if (ha->s_dma_pool) + dma_pool_destroy(ha->s_dma_pool); + + if (ha->rlc_rsp) + dma_free_coherent(&ha->pdev->dev, + sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp, + ha->rlc_rsp_dma); + + if (ha->gid_list) + dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, + ha->gid_list_dma); - if (ha->response_ring) { - pci_free_consistent(ha->pdev, - ((ha->response_q_length + 1) * (sizeof(response_t))), + if (ha->response_ring) + dma_free_coherent(&ha->pdev->dev, + (ha->response_q_length + 1) * sizeof(response_t), ha->response_ring, ha->response_dma); - } - ha->iodesc_pd = NULL; - ha->iodesc_pd_dma = 0; + if (ha->request_ring) + dma_free_coherent(&ha->pdev->dev, + (ha->request_q_length + 1) * sizeof(request_t), + ha->request_ring, ha->request_dma); + + ha->sns_cmd = NULL; + ha->sns_cmd_dma = 0; ha->ct_sns = NULL; + ha->ct_sns_dma = 0; ha->ms_iocb = NULL; - + ha->ms_iocb_dma = 0; + ha->iodesc_pd = NULL; + ha->iodesc_pd_dma = 0; ha->init_cb = NULL; - ha->request_ring = NULL; - ha->request_dma = 0; + ha->init_cb_dma = 0; + + ha->s_dma_pool = NULL; + + ha->rlc_rsp = NULL; + ha->rlc_rsp_dma = 0; + ha->gid_list = NULL; + ha->gid_list_dma = 0; + ha->response_ring = NULL; ha->response_dma = 0; + ha->request_ring = NULL; + ha->request_dma = 0; list_for_each_safe(fcpl, fcptemp, &ha->fcports) { fcport = list_entry(fcpl, fc_port_t, list); @@ -3080,16 +3122,15 @@ qla2x00_mem_free(scsi_qla_host_t *ha) } INIT_LIST_HEAD(&ha->fcports); - if (ha->fw_dump) { + if (ha->fw_dump) free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - ha->fw_dump = NULL; - } - if (ha->fw_dump_buffer) { + if (ha->fw_dump_buffer) vfree(ha->fw_dump_buffer); - ha->fw_dump_reading = 0; - ha->fw_dump_buffer = NULL; - } + + ha->fw_dump = NULL; + ha->fw_dump_reading = 0; + ha->fw_dump_buffer = NULL; } /* @@ -3187,9 +3228,6 @@ qla2x00_do_dpc(void *data) if (ha->dpc_should_die) break; - if (!list_empty(&ha->done_queue)) - qla2x00_done(ha); - DEBUG3(printk("qla2x00: DPC handler waking up\n")); /* Initialization not yet finished. Don't do anything yet. */ @@ -3200,6 +3238,9 @@ qla2x00_do_dpc(void *data) ha->dpc_active = 1; + if (!list_empty(&ha->done_queue)) + qla2x00_done(ha); + /* Process commands in retry queue */ if (test_and_clear_bit(PORT_RESTART_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): DPC checking retry_q. " @@ -3590,7 +3631,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha) { srb_t *sp; - sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); + sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC); if (sp) atomic_set(&sp->ref_count, 1); return (sp); @@ -4403,61 +4444,64 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) } static void -qla2xxx_get_port_id(struct scsi_device *sdev) +qla2xxx_get_port_id(struct scsi_target *starget) { - scsi_qla_host_t *ha = to_qla_host(sdev->host); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + scsi_qla_host_t *ha = to_qla_host(shost); struct fc_port *fc; list_for_each_entry(fc, &ha->fcports, list) { - if (fc->os_target_id == sdev->id) { - fc_port_id(sdev) = fc->d_id.b.domain << 16 | + if (fc->os_target_id == starget->id) { + fc_starget_port_id(starget) = fc->d_id.b.domain << 16 | fc->d_id.b.area << 8 | fc->d_id.b.al_pa; return; } } - fc_port_id(sdev) = -1; + fc_starget_port_id(starget) = -1; } static void -qla2xxx_get_port_name(struct scsi_device *sdev) +qla2xxx_get_port_name(struct scsi_target *starget) { - scsi_qla_host_t *ha = to_qla_host(sdev->host); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + scsi_qla_host_t *ha = to_qla_host(shost); struct fc_port *fc; list_for_each_entry(fc, &ha->fcports, list) { - if (fc->os_target_id == sdev->id) { - fc_port_name(sdev) = + if (fc->os_target_id == starget->id) { + fc_starget_port_name(starget) = __be64_to_cpu(*(uint64_t *)fc->port_name); return; } } - fc_port_name(sdev) = -1; + fc_starget_port_name(starget) = -1; } static void -qla2xxx_get_node_name(struct scsi_device *sdev) +qla2xxx_get_node_name(struct scsi_target *starget) { - scsi_qla_host_t *ha = to_qla_host(sdev->host); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + scsi_qla_host_t *ha = to_qla_host(shost); struct fc_port *fc; list_for_each_entry(fc, &ha->fcports, list) { - if (fc->os_target_id == sdev->id) { - fc_node_name(sdev) = + if (fc->os_target_id == starget->id) { + fc_starget_node_name(starget) = __be64_to_cpu(*(uint64_t *)fc->node_name); return; } } - fc_node_name(sdev) = -1; + fc_starget_node_name(starget) = -1; } static struct fc_function_template qla2xxx_transport_functions = { - .get_port_id = qla2xxx_get_port_id, - .show_port_id = 1, - .get_port_name = qla2xxx_get_port_name, - .show_port_name = 1, - .get_node_name = qla2xxx_get_node_name, - .show_node_name = 1, + .get_starget_port_id = qla2xxx_get_port_id, + .show_starget_port_id = 1, + .get_starget_port_name = qla2xxx_get_port_name, + .show_starget_port_name = 1, + .get_starget_node_name = qla2xxx_get_node_name, + .show_starget_node_name = 1, }; /** @@ -4517,3 +4561,4 @@ module_exit(qla2x00_module_exit); MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c index f2050f9dd..87d0cea8d 100644 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ b/drivers/scsi/qla2xxx/qla_rscn.c @@ -47,8 +47,6 @@ /* Local Prototypes. */ static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t); static inline uint16_t qla2x00_handle_to_idx(uint32_t); -static inline uint16_t qla2x00_handle_to_iter(uint32_t); -static inline uint16_t qla2x00_handle_to_type(uint32_t); static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *); static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *, uint32_t); @@ -129,30 +127,6 @@ qla2x00_handle_to_idx(uint32_t handle) return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK)); } -/** - * qla2x00_handle_to_type() - Retrive the descriptor type for a given handle. - * @handle: descriptor handle - * - * Returns the descriptor type specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_type(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_TYPE_SHIFT) & HDL_TYPE_MASK)); -} - -/** - * qla2x00_handle_to_iter() - Retrive the rolling signature for a given handle. - * @handle: descriptor handle - * - * Returns the signature specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_iter(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_ITER_SHIFT) & HDL_ITER_MASK)); -} - /** * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. * @iodesc: io descriptor @@ -241,6 +215,20 @@ qla2x00_free_iodesc(struct io_descriptor *iodesc) iodesc->signature = 0; } +/** + * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. + * @iodesc: io descriptor + */ +static inline void +qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc) +{ + if (iodesc->timer.function != NULL) { + del_timer_sync(&iodesc->timer); + iodesc->timer.data = (unsigned long) NULL; + iodesc->timer.function = NULL; + } +} + /** * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors. * @ha: HA context @@ -311,20 +299,6 @@ qla2x00_add_iodesc_timer(struct io_descriptor *iodesc) add_timer(&iodesc->timer); } -/** - * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. - * @iodesc: io descriptor - */ -static inline void -qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc) -{ - if (iodesc->timer.function != NULL) { - del_timer_sync(&iodesc->timer); - iodesc->timer.data = (unsigned long) NULL; - iodesc->timer.function = NULL; - } -} - /** * IO descriptor support routines. **/ @@ -374,10 +348,9 @@ static inline struct mbx_entry * qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle) { uint16_t cnt; - device_reg_t *reg; + device_reg_t __iomem *reg = ha->iobase; struct mbx_entry *mbxentry; - reg = ha->iobase; mbxentry = NULL; if (ha->req_q_cnt < 3) { diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 5196a746d..203c23dfa 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -39,9 +39,7 @@ void qla2x00_lock_nvram_access(scsi_qla_host_t *ha) { uint16_t data; - device_reg_t *reg; - - reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) { data = RD_REG_WORD(®->nvram); @@ -52,12 +50,14 @@ qla2x00_lock_nvram_access(scsi_qla_host_t *ha) /* Lock resource */ WRT_REG_WORD(®->u.isp2300.host_semaphore, 0x1); + RD_REG_WORD(®->u.isp2300.host_semaphore); udelay(5); data = RD_REG_WORD(®->u.isp2300.host_semaphore); while ((data & BIT_0) == 0) { /* Lock failed */ udelay(100); WRT_REG_WORD(®->u.isp2300.host_semaphore, 0x1); + RD_REG_WORD(®->u.isp2300.host_semaphore); udelay(5); data = RD_REG_WORD(®->u.isp2300.host_semaphore); } @@ -71,12 +71,12 @@ qla2x00_lock_nvram_access(scsi_qla_host_t *ha) void qla2x00_unlock_nvram_access(scsi_qla_host_t *ha) { - device_reg_t *reg; - - reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) + if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) { WRT_REG_WORD(®->u.isp2300.host_semaphore, 0); + RD_REG_WORD(®->u.isp2300.host_semaphore); + } } /** @@ -112,7 +112,7 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data) int count; uint16_t word; uint32_t nv_cmd; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; qla2x00_nv_write(ha, NVR_DATA_OUT); qla2x00_nv_write(ha, 0); @@ -197,7 +197,7 @@ static uint16_t qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd) { uint8_t cnt; - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; uint16_t data = 0; uint16_t reg_data; @@ -239,7 +239,7 @@ qla2x00_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd) void qla2x00_nv_deselect(scsi_qla_host_t *ha) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; WRT_REG_WORD(®->nvram, NVR_DESELECT); NVRAM_DELAY(); @@ -254,7 +254,7 @@ qla2x00_nv_deselect(scsi_qla_host_t *ha) void qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data) { - device_reg_t *reg = ha->iobase; + device_reg_t __iomem *reg = ha->iobase; WRT_REG_WORD(®->nvram, data | NVR_SELECT); NVRAM_DELAY(); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 1dc4c9594..69081270f 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -19,9 +19,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.00.00b14-k" +#define QLA2XXX_VERSION "8.00.00b21-k" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 0 #define QLA_DRIVER_PATCH_VER 0 -#define QLA_DRIVER_BETA_VER 14 +#define QLA_DRIVER_BETA_VER 21 diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index ef1fdfdc3..3a192e3c9 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -815,9 +815,11 @@ int isp2x00_detect(Scsi_Host_Template * tmpt) some time before recognizing it is attached to a fabric */ #if ISP2x00_FABRIC - for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) { - barrier(); - cpu_relax(); + if (hosts) { + for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) { + barrier(); + cpu_relax(); + } } #endif diff --git a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c index 55c6c4b08..b1d45102d 100644 --- a/drivers/scsi/qlogicfc_asm.c +++ b/drivers/scsi/qlogicfc_asm.c @@ -19,10 +19,10 @@ * Firmware Version 1.19.16 (10:36 Nov 02, 2000) */ -unsigned short risc_code_addr01 = 0x1000 ; +static unsigned short risc_code_addr01 = 0x1000 ; -unsigned short risc_code_length2100 = 0x9260; -unsigned short risc_code2100[] = { +static unsigned short risc_code_length2100 = 0x9260; +static unsigned short risc_code2100[] = { 0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010, 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, @@ -4729,8 +4729,8 @@ unsigned short risc_code2100[] = { * Firmware Version 2.01.27 (11:07 Dec 18, 2000) */ -unsigned short risc_code_length2200 = 0x9cbf; -unsigned short risc_code2200[] = { +static unsigned short risc_code_length2200 = 0x9cbf; +static unsigned short risc_code2200[] = { 0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b, 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c index 1be526c1c..aa80193ce 100644 --- a/drivers/scsi/qlogicisp.c +++ b/drivers/scsi/qlogicisp.c @@ -564,7 +564,7 @@ struct isp_queue_entry { }; struct isp1020_hostdata { - u_long memaddr; + void __iomem *memaddr; u_char revision; struct host_param host_param; struct dev_param dev_param[MAX_TARGETS]; @@ -714,7 +714,7 @@ int isp1020_detect(Scsi_Host_Template *tmpt) continue; fail_uninit: - iounmap((void *)hostdata->memaddr); + iounmap(hostdata->memaddr); release_region(host->io_port, 0xff); fail_and_unregister: if (hostdata->res_cpu) @@ -747,7 +747,7 @@ int isp1020_release(struct Scsi_Host *host) isp_outw(0x0, host, PCI_INTF_CTL); free_irq(host->irq, host); - iounmap((void *)hostdata->memaddr); + iounmap(hostdata->memaddr); release_region(host->io_port, 0xff); @@ -769,7 +769,7 @@ const char *isp1020_info(struct Scsi_Host *host) "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d %s base 0x%lx", hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, (hostdata->memaddr ? "MEM" : "I/O"), - (hostdata->memaddr ? hostdata->memaddr : host->io_port)); + (hostdata->memaddr ? (unsigned long)hostdata->memaddr : host->io_port)); LEAVE("isp1020_info"); @@ -1410,18 +1410,17 @@ static int isp1020_init(struct Scsi_Host *sh) if ((command & PCI_COMMAND_MEMORY) && ((mem_flags & 1) == 0)) { - mem_base = (u_long) ioremap(mem_base, PAGE_SIZE); - if (!mem_base) { + hostdata->memaddr = ioremap(mem_base, PAGE_SIZE); + if (!hostdata->memaddr) { printk("qlogicisp : i/o remapping failed.\n"); goto out_release; } - hostdata->memaddr = mem_base; } else { if (command & PCI_COMMAND_IO && (io_flags & 3) != 1) { printk("qlogicisp : i/o mapping is disabled\n"); goto out_release; } - hostdata->memaddr = 0; /* zero to signify no i/o mapping */ + hostdata->memaddr = NULL; /* zero to signify no i/o mapping */ mem_base = 0; } @@ -1470,7 +1469,7 @@ static int isp1020_init(struct Scsi_Host *sh) return 0; out_unmap: - iounmap((void *)hostdata->memaddr); + iounmap(hostdata->memaddr); out_release: release_region(sh->io_port, 0xff); return 1; diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index c49ca7f2f..91aaf50c7 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -987,7 +987,7 @@ const char *qlogicpti_info(struct Scsi_Host *host) static char buf[80]; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %lx", + sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p", __irq_itoa(qpti->qhost->irq), qpti->qregs); return buf; } diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index a40ff75ca..6cd1c0771 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h @@ -335,7 +335,7 @@ struct scsi_cmnd; /* Software state for the driver. */ struct qlogicpti { /* These are the hot elements in the cache, so they come first. */ - unsigned long qregs; /* Adapter registers */ + void __iomem *qregs; /* Adapter registers */ struct pti_queue_entry *res_cpu; /* Ptr to RESPONSE bufs (CPU) */ struct pti_queue_entry *req_cpu; /* Ptr to REQUEST bufs (CPU) */ @@ -370,7 +370,7 @@ struct qlogicpti { struct host_param host_param; struct dev_param dev_param[MAX_TARGETS]; - unsigned long sreg; + void __iomem *sreg; #define SREG_TPOWER 0x80 /* State of termpwr */ #define SREG_FUSE 0x40 /* State of on board fuse */ #define SREG_PDISAB 0x20 /* Disable state for power on */ diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 29248d608..a21105cb7 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -20,6 +20,10 @@ * If you do not delete the provisions above, a recipient may use your * version of this file under either the OSL or the GPL. * + * 0.03 + * - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using + * mmio_base, which is only set for the CK804/MCP04 case. + * * 0.02 * - Added support for CK804 SATA controller. * @@ -40,13 +44,12 @@ #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "0.02" +#define DRV_VERSION "0.5" #define NV_PORTS 2 #define NV_PIO_MASK 0x1f +#define NV_MWDMA_MASK 0x07 #define NV_UDMA_MASK 0x7f -#define NV_PORT0_BMDMA_REG_OFFSET 0x00 -#define NV_PORT1_BMDMA_REG_OFFSET 0x08 #define NV_PORT0_SCR_REG_OFFSET 0x00 #define NV_PORT1_SCR_REG_OFFSET 0x40 @@ -177,11 +180,12 @@ static struct pci_driver nv_pci_driver = { static Scsi_Host_Template nv_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, @@ -194,13 +198,14 @@ static Scsi_Host_Template nv_sht = { static struct ata_port_operations nv_ops = { .port_disable = ata_port_disable, - .tf_load = ata_tf_load_pio, - .tf_read = ata_tf_read_pio, - .exec_command = ata_exec_command_pio, - .check_status = ata_check_status_pio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_pio, - .bmdma_start = ata_bmdma_start_pio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -213,10 +218,31 @@ static struct ata_port_operations nv_ops = { .host_stop = nv_host_stop, }; +/* FIXME: The hardware provides the necessary SATA PHY controls + * to support ATA_FLAG_SATA_RESET. However, it is currently + * necessary to disable that flag, to solve misdetection problems. + * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. + * + * This problem really needs to be investigated further. But in the + * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. + */ +static struct ata_port_info nv_port_info = { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | + /* ATA_FLAG_SATA_RESET | */ + ATA_FLAG_SRST | + ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_ops, +}; + MODULE_AUTHOR("NVIDIA"); MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); +MODULE_VERSION(DRV_VERSION); irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs) { @@ -293,7 +319,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; struct nv_host *host; - struct ata_probe_ent *probe_ent = NULL; + struct ata_port_info *ppi; + struct ata_probe_ent *probe_ent; int rc; if (!printed_version++) @@ -301,11 +328,11 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = pci_enable_device(pdev); if (rc) - return rc; + goto err_out; rc = pci_request_regions(pdev, DRV_NAME); if (rc) - goto err_out; + goto err_out_disable; rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -314,53 +341,19 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); - if (!probe_ent) { - rc = -ENOMEM; + rc = -ENOMEM; + + ppi = &nv_port_info; + probe_ent = ata_pci_init_native_mode(pdev, &ppi); + if (!probe_ent) goto err_out_regions; - } host = kmalloc(sizeof(struct nv_host), GFP_KERNEL); - if (!host) { - rc = -ENOMEM; + if (!host) goto err_out_free_ent; - } host->host_desc = &nv_device_tbl[ent->driver_data]; - memset(probe_ent, 0, sizeof(*probe_ent)); - INIT_LIST_HEAD(&probe_ent->node); - - probe_ent->pdev = pdev; - probe_ent->sht = &nv_sht; - probe_ent->host_flags = ATA_FLAG_SATA | - ATA_FLAG_SATA_RESET | - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY; - - probe_ent->port_ops = &nv_ops; - probe_ent->n_ports = NV_PORTS; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - probe_ent->pio_mask = NV_PIO_MASK; - probe_ent->udma_mask = NV_UDMA_MASK; - - probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); - ata_std_ports(&probe_ent->port[0]); - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[0].bmdma_addr = - pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET; - - probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); - ata_std_ports(&probe_ent->port[1]); - probe_ent->port[1].altstatus_addr = - probe_ent->port[1].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[1].bmdma_addr = - pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET; - probe_ent->private_data = host; if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) { @@ -368,8 +361,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5), pci_resource_len(pdev, 5)); - if (probe_ent->mmio_base == NULL) - goto err_out_free_ent; + if (probe_ent->mmio_base == NULL) { + rc = -EIO; + goto err_out_free_host; + } base = (unsigned long)probe_ent->mmio_base; @@ -387,26 +382,30 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); + rc = ata_device_add(probe_ent); + if (rc != NV_PORTS) + goto err_out_iounmap; + // Enable hotplug event interrupts. if (host->host_desc->enable_hotplug) host->host_desc->enable_hotplug(probe_ent); - rc = ata_device_add(probe_ent); - if (rc != NV_PORTS) - goto err_out_free_ent; - kfree(probe_ent); return 0; +err_out_iounmap: + if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) + iounmap(probe_ent->mmio_base); +err_out_free_host: + kfree(host); err_out_free_ent: kfree(probe_ent); - err_out_regions: pci_release_regions(pdev); - -err_out: +err_out_disable: pci_disable_device(pdev); +err_out: return rc; } @@ -415,33 +414,33 @@ static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) u8 intr_mask; outb(NV_INT_STATUS_HOTPLUG, - (unsigned long)probe_ent->mmio_base + NV_INT_STATUS); + probe_ent->port[0].scr_addr + NV_INT_STATUS); - intr_mask = inb((unsigned long)probe_ent->mmio_base + NV_INT_ENABLE); + intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE); intr_mask |= NV_INT_ENABLE_HOTPLUG; - outb(intr_mask, (unsigned long)probe_ent->mmio_base + NV_INT_ENABLE); + outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE); } static void nv_disable_hotplug(struct ata_host_set *host_set) { u8 intr_mask; - intr_mask = inb((unsigned long)host_set->mmio_base + NV_INT_ENABLE); + intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - outb(intr_mask, (unsigned long)host_set->mmio_base + NV_INT_ENABLE); + outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); } static void nv_check_hotplug(struct ata_host_set *host_set) { u8 intr_status; - intr_status = inb((unsigned long)host_set->mmio_base + NV_INT_STATUS); + intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); // Clear interrupt status. - outb(0xff, (unsigned long)host_set->mmio_base + NV_INT_STATUS); + outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); if (intr_status & NV_INT_STATUS_HOTPLUG) { if (intr_status & NV_INT_STATUS_PDEV_ADDED) @@ -464,12 +463,13 @@ static void nv_check_hotplug(struct ata_host_set *host_set) static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) { + struct pci_dev *pdev = to_pci_dev(probe_ent->dev); u8 intr_mask; u8 regval; - pci_read_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, ®val); + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, regval); + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); @@ -481,6 +481,7 @@ static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) { + struct pci_dev *pdev = to_pci_dev(host_set->dev); u8 intr_mask; u8 regval; @@ -490,9 +491,9 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); - pci_read_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, ®val); + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, regval); + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); } static void nv_check_hotplug_ck804(struct ata_host_set *host_set) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index a2eefb6bc..4b95f70aa 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -40,7 +40,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "1.00" +#define DRV_VERSION "1.01" enum { @@ -73,8 +73,7 @@ struct pdc_port_priv { static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc_dma_start(struct ata_queued_cmd *qc); +static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void pdc_eng_timeout(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); @@ -83,14 +82,13 @@ static void pdc_phy_reset(struct ata_port *ap); static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, int have_err); static void pdc_irq_clear(struct ata_port *ap); static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_sata_sht = { +static Scsi_Host_Template pdc_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -106,12 +104,13 @@ static Scsi_Host_Template pdc_sata_sht = { .bios_param = ata_std_bios_param, }; -static struct ata_port_operations pdc_sata_ops = { +static struct ata_port_operations pdc_ata_ops = { .port_disable = ata_port_disable, .tf_load = pdc_tf_load_mmio, - .tf_read = ata_tf_read_mmio, - .check_status = ata_check_status_mmio, + .tf_read = ata_tf_read, + .check_status = ata_check_status, .exec_command = pdc_exec_command_mmio, + .dev_select = ata_std_dev_select, .phy_reset = pdc_phy_reset, .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, @@ -127,26 +126,28 @@ static struct ata_port_operations pdc_sata_ops = { static struct ata_port_info pdc_port_info[] = { /* board_2037x */ { - .sht = &pdc_sata_sht, + .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_sata_ops, + .port_ops = &pdc_ata_ops, }, /* board_20319 */ { - .sht = &pdc_sata_sht, + .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_sata_ops, + .port_ops = &pdc_ata_ops, }, }; -static struct pci_device_id pdc_sata_pci_tbl[] = { +static struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -163,17 +164,17 @@ static struct pci_device_id pdc_sata_pci_tbl[] = { }; -static struct pci_driver pdc_sata_pci_driver = { +static struct pci_driver pdc_ata_pci_driver = { .name = DRV_NAME, - .id_table = pdc_sata_pci_tbl, - .probe = pdc_sata_init_one, + .id_table = pdc_ata_pci_tbl, + .probe = pdc_ata_init_one, .remove = ata_pci_remove_one, }; static int pdc_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp; int rc; @@ -188,7 +189,7 @@ static int pdc_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); if (!pp->pkt) { rc = -ENOMEM; goto err_out_kfree; @@ -208,11 +209,11 @@ err_out: static void pdc_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp = ap->private_data; ap->private_data = NULL; - pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma); kfree(pp); ata_port_stop(ap); } @@ -269,26 +270,26 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) VPRINTK("ENTER\n"); - ata_qc_prep(qc); - - i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, qc->dev->devno, pp->pkt); + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + ata_qc_prep(qc); + /* fall through */ - if (qc->tf.flags & ATA_TFLAG_LBA48) - i = pdc_prep_lba48(&qc->tf, pp->pkt, i); - else - i = pdc_prep_lba28(&qc->tf, pp->pkt, i); + case ATA_PROT_NODATA: + i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma, + qc->dev->devno, pp->pkt); - pdc_pkt_footer(&qc->tf, pp->pkt, i); -} + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, pp->pkt, i); + else + i = pdc_prep_lba28(&qc->tf, pp->pkt, i); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, - int have_err) -{ - u8 err_bit = have_err ? ATA_ERR : 0; + pdc_pkt_footer(&qc->tf, pp->pkt, i); + break; - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap) | err_bit); + default: + break; + } } static void pdc_eng_timeout(struct ata_port *ap) @@ -315,17 +316,9 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: - printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); - break; - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); + printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); break; default: @@ -358,13 +351,8 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap, switch (qc->tf.protocol) { case ATA_PROT_DMA: - pdc_dma_complete(ap, qc, have_err); - handled = 1; - break; - - case ATA_PROT_NODATA: /* command completion, but no data xfer */ - status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); + case ATA_PROT_NODATA: + status = ata_wait_idle(ap); if (have_err) status |= ATA_ERR; ata_qc_complete(qc, status); @@ -440,7 +428,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r return IRQ_RETVAL(handled); } -static inline void pdc_dma_start(struct ata_queued_cmd *qc) +static inline void pdc_packet_start(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct pdc_port_priv *pp = ap->private_data; @@ -462,7 +450,8 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { case ATA_PROT_DMA: - pdc_dma_start(qc); + case ATA_PROT_NODATA: + pdc_packet_start(qc); return 0; case ATA_PROT_ATAPI_DMA: @@ -478,19 +467,21 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA); - ata_tf_load_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - WARN_ON (tf->protocol == ATA_PROT_DMA); - ata_exec_command_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_exec_command(ap, tf); } -static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) +static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = base; port->data_addr = base; @@ -539,8 +530,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) writel(tmp, mmio + PDC_TBG_MODE); readl(mmio + PDC_TBG_MODE); /* flush */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10) + 1); + msleep(10); /* adjust slew rate control register. */ tmp = readl(mmio + PDC_SLEW_CTL); @@ -549,7 +539,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) writel(tmp, mmio + PDC_SLEW_CTL); } -static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; struct ata_probe_ent *probe_ent = NULL; @@ -587,7 +577,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 3), @@ -601,6 +591,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask; probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; probe_ent->port_ops = pdc_port_info[board_idx].port_ops; @@ -608,8 +599,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * probe_ent->irq_flags = SA_SHIRQ; probe_ent->mmio_base = mmio_base; - pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); - pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); + pdc_ata_setup_port(&probe_ent->port[0], base + 0x200); + pdc_ata_setup_port(&probe_ent->port[1], base + 0x280); probe_ent->port[0].scr_addr = base + 0x400; probe_ent->port[1].scr_addr = base + 0x500; @@ -619,8 +610,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * case board_20319: probe_ent->n_ports = 4; - pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); - pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); + pdc_ata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_ata_setup_port(&probe_ent->port[3], base + 0x380); probe_ent->port[2].scr_addr = base + 0x600; probe_ent->port[3].scr_addr = base + 0x700; @@ -654,22 +645,23 @@ err_out: } -static int __init pdc_sata_init(void) +static int __init pdc_ata_init(void) { - return pci_module_init(&pdc_sata_pci_driver); + return pci_module_init(&pdc_ata_pci_driver); } -static void __exit pdc_sata_exit(void) +static void __exit pdc_ata_exit(void) { - pci_unregister_driver(&pdc_sata_pci_driver); + pci_unregister_driver(&pdc_ata_pci_driver); } MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver"); MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); +MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl); +MODULE_VERSION(DRV_VERSION); -module_init(pdc_sata_init); -module_exit(pdc_sata_exit); +module_init(pdc_ata_init); +module_exit(pdc_ata_exit); diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 72a89d1be..80e75bd5a 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -6,7 +6,7 @@ * on emails. * * Copyright 2003 Red Hat, Inc. - * Copyright 2003 Benjamin Herrenschmidt + * Copyright 2003 Benjamin Herrenschmidt * * The contents of this file are subject to the Open * Software License version 1.1 that can be found at @@ -38,7 +38,7 @@ #include #define DRV_NAME "sata_sil" -#define DRV_VERSION "0.54" +#define DRV_VERSION "0.8" enum { sil_3112 = 0, @@ -87,6 +87,7 @@ struct sil_drivelist { { "ST380023AS", SIL_QUIRK_MOD15WRITE }, { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, { "ST3160023AS", SIL_QUIRK_MOD15WRITE }, + { "ST3120026AS", SIL_QUIRK_MOD15WRITE }, { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, @@ -106,6 +107,7 @@ static struct pci_driver sil_pci_driver = { static Scsi_Host_Template sil_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -124,14 +126,15 @@ static Scsi_Host_Template sil_sht = { static struct ata_port_operations sil_ops = { .port_disable = ata_port_disable, .dev_config = sil_dev_config, - .tf_load = ata_tf_load_mmio, - .tf_read = ata_tf_read_mmio, - .check_status = ata_check_status_mmio, - .exec_command = ata_exec_command_mmio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, .post_set_mode = sil_post_set_mode, - .bmdma_setup = ata_bmdma_setup_mmio, - .bmdma_start = ata_bmdma_start_mmio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -149,7 +152,8 @@ static struct ata_port_info sil_port_info[] = { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, /* sil_3114 */ @@ -157,7 +161,8 @@ static struct ata_port_info sil_port_info[] = { .sht = &sil_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, @@ -185,6 +190,7 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil_pci_tbl); +MODULE_VERSION(DRV_VERSION); static void sil_post_set_mode (struct ata_port *ap) { @@ -283,7 +289,7 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) const char *s; unsigned int len; - ata_dev_id_string(dev, model_num, ATA_ID_PROD_OFS, + ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); s = &model_num[0]; len = strnlen(s, sizeof(model_num)); @@ -358,11 +364,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) memset(probe_ent, 0, sizeof(*probe_ent)); INIT_LIST_HEAD(&probe_ent->node); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; probe_ent->sht = sil_port_info[ent->driver_data].sht; probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2; probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask; + probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask; probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask; probe_ent->irq = pdev->irq; probe_ent->irq_flags = SA_SHIRQ; diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 88b7a02ea..d48e437c9 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -38,7 +38,7 @@ #include #define DRV_NAME "sata_sis" -#define DRV_VERSION "0.10" +#define DRV_VERSION "0.5" enum { sis_180 = 0, @@ -76,6 +76,7 @@ static struct pci_driver sis_pci_driver = { static Scsi_Host_Template sis_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -93,13 +94,14 @@ static Scsi_Host_Template sis_sht = { static struct ata_port_operations sis_ops = { .port_disable = ata_port_disable, - .tf_load = ata_tf_load_pio, - .tf_read = ata_tf_read_pio, - .check_status = ata_check_status_pio, - .exec_command = ata_exec_command_pio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_pio, - .bmdma_start = ata_bmdma_start_pio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -111,11 +113,22 @@ static struct ata_port_operations sis_ops = { .port_stop = ata_port_stop, }; +static struct ata_port_info sis_port_info = { + .sht = &sis_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | + ATA_FLAG_NO_LEGACY, + .pio_mask = 0x1f, + .mwdma_mask = 0x7, + .udma_mask = 0x7f, + .port_ops = &sis_ops, +}; + MODULE_AUTHOR("Uwe Koziolek"); MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sis_pci_tbl); +MODULE_VERSION(DRV_VERSION); static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) { @@ -128,22 +141,24 @@ static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); u32 val; if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ return 0xffffffff; - pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val); + pci_read_config_dword(pdev, cfg_addr, &val); return val; } static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ return; - pci_write_config_dword(ap->host_set->pdev, cfg_addr, val); + pci_write_config_dword(pdev, cfg_addr, val); } static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) @@ -184,6 +199,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_probe_ent *probe_ent = NULL; int rc; u32 genctl; + struct ata_port_info *ppi; rc = pci_enable_device(pdev); if (rc) @@ -200,20 +216,13 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + ppi = &sis_port_info; + probe_ent = ata_pci_init_native_mode(pdev, &ppi); if (!probe_ent) { rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; - INIT_LIST_HEAD(&probe_ent->node); - - probe_ent->sht = &sis_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY; - /* check and see if the SCRs are in IO space or PCI cfg space */ pci_read_config_dword(pdev, SIS_GENCTL, &genctl); if ((genctl & GENCTL_IOMAPPED_SCR) == 0) @@ -230,31 +239,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->host_flags |= SIS_FLAG_CFGSCR; } - probe_ent->pio_mask = 0x03; - probe_ent->udma_mask = 0x7f; - probe_ent->port_ops = &sis_ops; - - probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); - ata_std_ports(&probe_ent->port[0]); - probe_ent->port[0].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); - if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) + if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) { probe_ent->port[0].scr_addr = pci_resource_start(pdev, SIS_SCR_PCI_BAR); - - probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); - ata_std_ports(&probe_ent->port[1]); - probe_ent->port[1].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; - if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) probe_ent->port[1].scr_addr = pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64; - - probe_ent->n_ports = 2; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; + } pci_set_master(pdev); pci_enable_intx(pdev); @@ -284,6 +274,6 @@ static void __exit sis_exit(void) pci_unregister_driver(&sis_pci_driver); } - module_init(sis_init); module_exit(sis_exit); + diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 398f24f27..eca3eeb9e 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -49,7 +49,7 @@ #endif /* CONFIG_PPC_OF */ #define DRV_NAME "sata_svw" -#define DRV_VERSION "1.04" +#define DRV_VERSION "1.05" /* Taskfile registers offsets */ #define K2_SATA_TF_CMD_OFFSET 0x00 @@ -148,7 +148,73 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) } } +/** + * k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO) + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u8 dmactl; + void *mmio = (void *) ap->ioaddr.bmdma_addr; + /* load PRD table addr. */ + mb(); /* make sure PRD table writes are visible to controller */ + writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); + + /* specify data direction, triple-check start bit is clear */ + dmactl = readb(mmio + ATA_DMA_CMD); + dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); + if (!rw) + dmactl |= ATA_DMA_WR; + writeb(dmactl, mmio + ATA_DMA_CMD); + + /* issue r/w command if this is not a ATA DMA command*/ + if (qc->tf.protocol != ATA_PROT_DMA) + ap->ops->exec_command(ap, &qc->tf); +} + +/** + * k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO) + * @qc: Info associated with this ATA transaction. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ + +void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void *mmio = (void *) ap->ioaddr.bmdma_addr; + u8 dmactl; + + /* start host DMA transaction */ + dmactl = readb(mmio + ATA_DMA_CMD); + writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); + /* There is a race condition in certain SATA controllers that can + be seen when the r/w command is given to the controller before the + host DMA is started. On a Read command, the controller would initiate + the command to the drive even before it sees the DMA start. When there + are very fast drives connected to the controller, or when the data request + hits in the drive cache, there is the possibility that the drive returns a part + or all of the requested data to the controller before the DMA start is issued. + In this case, the controller would become confused as to what to do with the data. + In the worst case when all the data is returned back to the controller, the + controller could hang. In other cases it could return partial data returning + in data corruption. This problem has been seen in PPC systems and can also appear + on an system with very fast disks, where the SATA controller is sitting behind a + number of bridges, and hence there is significant latency between the r/w command + and the start command. */ + /* issue r/w command if the access is to ATA*/ + if (qc->tf.protocol == ATA_PROT_DMA) + ap->ops->exec_command(ap, &qc->tf); +} + static u8 k2_stat_check_status(struct ata_port *ap) { return readl((void *) ap->ioaddr.status_addr); @@ -179,7 +245,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, return 0; /* Find the OF node for the PCI device proper */ - np = pci_device_to_OF_node(ap->host_set->pdev); + np = pci_device_to_OF_node(to_pci_dev(ap->host_set->dev)); if (np == NULL) return 0; @@ -205,6 +271,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, static Scsi_Host_Template k2_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -229,10 +296,11 @@ static struct ata_port_operations k2_sata_ops = { .tf_load = k2_sata_tf_load, .tf_read = k2_sata_tf_read, .check_status = k2_stat_check_status, - .exec_command = ata_exec_command_mmio, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_mmio, - .bmdma_start = ata_bmdma_start_mmio, + .bmdma_setup = k2_bmdma_setup_mmio, + .bmdma_start = k2_bmdma_start_mmio, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -308,7 +376,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 5), @@ -343,6 +411,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e * if we don't fill these */ probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x7; probe_ent->udma_mask = 0x7f; /* We have 4 ports per PCI function */ @@ -371,6 +440,8 @@ err_out: static struct pci_device_id k2_sata_pci_tbl[] = { { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { } }; @@ -388,6 +459,7 @@ static int __init k2_sata_init(void) return pci_module_init(&k2_sata_pci_driver); } + static void __exit k2_sata_exit(void) { pci_unregister_driver(&k2_sata_pci_driver); @@ -398,6 +470,7 @@ MODULE_AUTHOR("Benjamin Herrenschmidt"); MODULE_DESCRIPTION("low-level driver for K2 SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl); +MODULE_VERSION(DRV_VERSION); module_init(k2_sata_init); module_exit(k2_sata_exit); diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index b54fd87e3..20a01253b 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -40,7 +40,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_sx4" -#define DRV_VERSION "0.50" +#define DRV_VERSION "0.7" enum { @@ -146,8 +146,6 @@ struct pdc_host_priv { static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static void pdc20621_dma_setup(struct ata_queued_cmd *qc); -static void pdc20621_dma_start(struct ata_queued_cmd *qc); static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs); static void pdc_eng_timeout(struct ata_port *ap); static void pdc_20621_phy_reset (struct ata_port *ap); @@ -157,8 +155,6 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf); static void pdc20621_host_stop(struct ata_host_set *host_set); -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, int have_err); static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe); static int pdc20621_detect_dimm(struct ata_probe_ent *pe); static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, @@ -172,11 +168,13 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, u32 offset, u32 size); static void pdc20621_irq_clear(struct ata_port *ap); +static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); static Scsi_Host_Template pdc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -195,14 +193,13 @@ static Scsi_Host_Template pdc_sata_sht = { static struct ata_port_operations pdc_20621_ops = { .port_disable = ata_port_disable, .tf_load = pdc_tf_load_mmio, - .tf_read = ata_tf_read_mmio, - .check_status = ata_check_status_mmio, + .tf_read = ata_tf_read, + .check_status = ata_check_status, .exec_command = pdc_exec_command_mmio, + .dev_select = ata_std_dev_select, .phy_reset = pdc_20621_phy_reset, - .bmdma_setup = pdc20621_dma_setup, - .bmdma_start = pdc20621_dma_start, .qc_prep = pdc20621_qc_prep, - .qc_issue = ata_qc_issue_prot, + .qc_issue = pdc20621_qc_issue_prot, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, .irq_clear = pdc20621_irq_clear, @@ -217,7 +214,8 @@ static struct ata_port_info pdc_port_info[] = { .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO, - .pio_mask = 0x03, /* pio3-4 */ + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_20621_ops, }, @@ -250,7 +248,7 @@ static void pdc20621_host_stop(struct ata_host_set *host_set) static int pdc_port_start(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp; int rc; @@ -265,7 +263,7 @@ static int pdc_port_start(struct ata_port *ap) } memset(pp, 0, sizeof(*pp)); - pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); + pp->pkt = dma_alloc_coherent(dev, 128, &pp->pkt_dma, GFP_KERNEL); if (!pp->pkt) { rc = -ENOMEM; goto err_out_kfree; @@ -285,11 +283,11 @@ err_out: static void pdc_port_stop(struct ata_port *ap) { - struct pci_dev *pdev = ap->host_set->pdev; + struct device *dev = ap->host_set->dev; struct pdc_port_priv *pp = ap->private_data; ap->private_data = NULL; - pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma); + dma_free_coherent(dev, 128, pp->pkt, pp->pkt_dma); kfree(pp); ata_port_stop(ap); } @@ -377,7 +375,10 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf, /* dimm dma S/G, and next-pkt */ dw = i >> 2; - buf32[dw] = cpu_to_le32(dimm_sg); + if (tf->protocol == ATA_PROT_NODATA) + buf32[dw] = 0; + else + buf32[dw] = cpu_to_le32(dimm_sg); buf32[dw + 1] = 0; i += 8; @@ -437,7 +438,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, buf32[dw + 3]); } -static void pdc20621_qc_prep(struct ata_queued_cmd *qc) +static void pdc20621_dma_prep(struct ata_queued_cmd *qc) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; @@ -449,8 +450,7 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc) unsigned int i, last, idx, total_len = 0, sgt_len; u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ]; - if (!(qc->flags & ATA_QCFLAG_DMAMAP)) - return; + assert(qc->flags & ATA_QCFLAG_DMAMAP); VPRINTK("ata%u: ENTER\n", ap->id); @@ -501,6 +501,56 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc) VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); } +static void pdc20621_nodata_prep(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct pdc_port_priv *pp = ap->private_data; + void *mmio = ap->host_set->mmio_base; + struct pdc_host_priv *hpriv = ap->host_set->private_data; + void *dimm_mmio = hpriv->dimm_mmio; + unsigned int portno = ap->port_no; + unsigned int i; + + VPRINTK("ata%u: ENTER\n", ap->id); + + /* hard-code chip #0 */ + mmio += PDC_CHIP0_OFS; + + i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno); + + if (qc->tf.flags & ATA_TFLAG_LBA48) + i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i); + else + i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i); + + pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i); + + /* copy three S/G tables and two packets to DIMM MMIO window */ + memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP), + &pp->dimm_buf, PDC_DIMM_HEADER_SZ); + + /* force host FIFO dump */ + writel(0x00000001, mmio + PDC_20621_GENERAL_CTL); + + readl(dimm_mmio); /* MMIO PCI posting flush */ + + VPRINTK("ata pkt buf ofs %u, mmio copied\n", i); +} + +static void pdc20621_qc_prep(struct ata_queued_cmd *qc) +{ + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + pdc20621_dma_prep(qc); + break; + case ATA_PROT_NODATA: + pdc20621_nodata_prep(qc); + break; + default: + break; + } +} + static void __pdc20621_push_hdma(struct ata_queued_cmd *qc, unsigned int seq, u32 pkt_ofs) @@ -576,13 +626,7 @@ static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { } #endif /* ATA_VERBOSE_DEBUG */ -static void pdc20621_dma_setup(struct ata_queued_cmd *qc) -{ - /* nothing for now. later, we will call standard - * code in libata-core for ATAPI here */ -} - -static void pdc20621_dma_start(struct ata_queued_cmd *qc) +static void pdc20621_packet_start(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ata_host_set *host_set = ap->host_set; @@ -590,24 +634,21 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) void *mmio = host_set->mmio_base; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); u8 seq = (u8) (port_no + 1); - unsigned int doing_hdma = 0, port_ofs; + unsigned int port_ofs; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; VPRINTK("ata%u: ENTER\n", ap->id); + wmb(); /* flush PRD, pkt writes */ + port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no); /* if writing, we (1) DMA to DIMM, then (2) do ATA command */ - if (rw) { - doing_hdma = 1; + if (rw && qc->tf.protocol == ATA_PROT_DMA) { seq += 4; - } - - wmb(); /* flush PRD, pkt writes */ - if (doing_hdma) { pdc20621_dump_hdma(qc); pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT); VPRINTK("queued ofs 0x%x (%u), seq %u\n", @@ -628,6 +669,25 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) } } +static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) +{ + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_NODATA: + pdc20621_packet_start(qc); + return 0; + + case ATA_PROT_ATAPI_DMA: + BUG(); + break; + + default: + break; + } + + return ata_qc_issue_prot(qc); +} + static inline unsigned int pdc20621_host_intr( struct ata_port *ap, struct ata_queued_cmd *qc, unsigned int doing_hdma, @@ -648,7 +708,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, if (doing_hdma) { VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); + /* get drive status; clear intr; complete txn */ + ata_qc_complete(qc, ata_wait_idle(ap)); pdc20621_pop_hdma(qc); } @@ -685,7 +746,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, else { VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); - pdc_dma_complete(ap, qc, 0); + /* get drive status; clear intr; complete txn */ + ata_qc_complete(qc, ata_wait_idle(ap)); pdc20621_pop_hdma(qc); } handled = 1; @@ -779,16 +841,6 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re return IRQ_RETVAL(handled); } -static inline void pdc_dma_complete (struct ata_port *ap, - struct ata_queued_cmd *qc, - int have_err) -{ - u8 err_bit = have_err ? ATA_ERR : 0; - - /* get drive status; clear intr; complete txn */ - ata_qc_complete(qc, ata_wait_idle(ap) | err_bit); -} - static void pdc_eng_timeout(struct ata_port *ap) { u8 drv_stat; @@ -813,17 +865,9 @@ static void pdc_eng_timeout(struct ata_port *ap) switch (qc->tf.protocol) { case ATA_PROT_DMA: - printk(KERN_ERR "ata%u: DMA timeout\n", ap->id); - ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); - break; - case ATA_PROT_NODATA: - drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); - - ata_qc_complete(qc, drv_stat); + printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR); break; default: @@ -842,15 +886,17 @@ out: static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_tf_load_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { - if (tf->protocol != ATA_PROT_DMA) - ata_exec_command_mmio(ap, tf); + WARN_ON (tf->protocol == ATA_PROT_DMA || + tf->protocol == ATA_PROT_NODATA); + ata_exec_command(ap, tf); } @@ -1144,8 +1190,7 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe) error = 0; break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((i * 100) * HZ / 1000 + 1); + msleep(i*100); } return error; } @@ -1178,8 +1223,7 @@ static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe) readl(mmio + PDC_TIME_CONTROL); /* Wait 3 seconds */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3 * HZ); + msleep(3000); /* When timer is enabled, counter is decreased every internal @@ -1353,7 +1397,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 3), @@ -1384,6 +1428,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * probe_ent->sht = pdc_port_info[board_idx].sht; probe_ent->host_flags = pdc_port_info[board_idx].host_flags; probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask; probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; probe_ent->port_ops = pdc_port_info[board_idx].port_ops; @@ -1394,21 +1439,11 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * probe_ent->private_data = hpriv; base += PDC_CHIP0_OFS; + probe_ent->n_ports = 4; pdc_sata_setup_port(&probe_ent->port[0], base + 0x200); pdc_sata_setup_port(&probe_ent->port[1], base + 0x280); - - /* notice 4-port boards */ - switch (board_idx) { - case board_20621: - probe_ent->n_ports = 4; - - pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); - pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); - break; - default: - BUG(); - break; - } + pdc_sata_setup_port(&probe_ent->port[2], base + 0x300); + pdc_sata_setup_port(&probe_ent->port[3], base + 0x380); pci_set_master(pdev); @@ -1457,6 +1492,7 @@ MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Promise SATA low-level driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl); +MODULE_VERSION(DRV_VERSION); module_init(pdc_sata_init); module_exit(pdc_sata_exit); diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 1becb3691..c45b1ee00 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -32,7 +32,7 @@ #include #define DRV_NAME "sata_uli" -#define DRV_VERSION "0.11" +#define DRV_VERSION "0.2" enum { uli_5289 = 0, @@ -150,18 +150,20 @@ static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); u32 val; - pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val); + pci_read_config_dword(pdev, cfg_addr, &val); return val; } static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) { + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); - pci_write_config_dword(ap->host_set->pdev, cfg_addr, val); + pci_write_config_dword(pdev, cfg_addr, val); } static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg) diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 993edfc99..5e3d5a600 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -38,7 +38,7 @@ #include #define DRV_NAME "sata_via" -#define DRV_VERSION "0.20" +#define DRV_VERSION "1.0" enum { via_sata = 0, @@ -81,6 +81,7 @@ static struct pci_driver svia_pci_driver = { static Scsi_Host_Template svia_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -99,15 +100,16 @@ static Scsi_Host_Template svia_sht = { static struct ata_port_operations svia_sata_ops = { .port_disable = ata_port_disable, - .tf_load = ata_tf_load_pio, - .tf_read = ata_tf_read_pio, - .check_status = ata_check_status_pio, - .exec_command = ata_exec_command_pio, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_pio, - .bmdma_start = ata_bmdma_start_pio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -123,10 +125,20 @@ static struct ata_port_operations svia_sata_ops = { .port_stop = ata_port_stop, }; +static struct ata_port_info svia_port_info = { + .sht = &svia_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = 0x7f, + .port_ops = &svia_sata_ops, +}; + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, svia_pci_tbl); +MODULE_VERSION(DRV_VERSION); static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg) { @@ -156,6 +168,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; unsigned int i; int rc; + struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; u8 tmp8; @@ -196,41 +209,17 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + ppi = &svia_port_info; + probe_ent = ata_pci_init_native_mode(pdev, &ppi); if (!probe_ent) { printk(KERN_ERR DRV_NAME "(%s): out of memory\n", pci_name(pdev)); rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); - INIT_LIST_HEAD(&probe_ent->node); - probe_ent->pdev = pdev; - probe_ent->sht = &svia_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY; - probe_ent->port_ops = &svia_sata_ops; - probe_ent->n_ports = 2; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; - probe_ent->pio_mask = 0x1f; - probe_ent->udma_mask = 0x7f; - - probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); - ata_std_ports(&probe_ent->port[0]); - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); + probe_ent->port[0].scr_addr = svia_scr_addr(pci_resource_start(pdev, 5), 0); - - probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); - ata_std_ports(&probe_ent->port[1]); - probe_ent->port[1].altstatus_addr = - probe_ent->port[1].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; probe_ent->port[1].scr_addr = svia_scr_addr(pci_resource_start(pdev, 5), 1); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index d63a339cc..26c822f1e 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -26,7 +26,7 @@ #include #define DRV_NAME "sata_vsc" -#define DRV_VERSION "0.01" +#define DRV_VERSION "1.0" /* Interrupt register offsets (from chip base address) */ #define VSC_SATA_INT_STAT_OFFSET 0x00 @@ -190,6 +190,7 @@ irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *reg static Scsi_Host_Template vsc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, @@ -210,11 +211,12 @@ static struct ata_port_operations vsc_sata_ops = { .port_disable = ata_port_disable, .tf_load = vsc_sata_tf_load, .tf_read = vsc_sata_tf_read, - .exec_command = ata_exec_command_mmio, - .check_status = ata_check_status_mmio, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup_mmio, - .bmdma_start = ata_bmdma_start_mmio, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -291,7 +293,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d goto err_out_regions; } memset(probe_ent, 0, sizeof(*probe_ent)); - probe_ent->pdev = pdev; + probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); mmio_base = ioremap(pci_resource_start(pdev, 0), @@ -320,6 +322,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d * if we don't fill these */ probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x07; probe_ent->udma_mask = 0x7f; /* We have 4 ports per PCI function */ @@ -330,6 +333,14 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d pci_set_master(pdev); + /* + * Config offset 0x98 is "Extended Control and Status Register 0" + * Default value is (1 << 28). All bits except bit 28 are reserved in + * DPA mode. If bit 28 is set, LED 0 reflects all ports' activity. + * If bit 28 is clear, each port has its own LED. + */ + pci_write_config_dword(pdev, 0x98, 0); + /* FIXME: check ata_device_add return value */ ata_device_add(probe_ent); kfree(probe_ent); @@ -382,6 +393,7 @@ MODULE_AUTHOR("Jeremy Higdon"); MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl); +MODULE_VERSION(DRV_VERSION); module_init(vsc_sata_init); module_exit(vsc_sata_exit); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 17dce6657..855a682ab 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -244,7 +244,13 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, */ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask) { - struct scsi_cmnd *cmd = __scsi_get_command(dev->host, gfp_mask); + struct scsi_cmnd *cmd; + + /* Bail if we can't get a reference to the device */ + if (!get_device(&dev->sdev_gendev)) + return NULL; + + cmd = __scsi_get_command(dev->host, gfp_mask); if (likely(cmd != NULL)) { unsigned long flags; @@ -258,7 +264,8 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask) spin_lock_irqsave(&dev->list_lock, flags); list_add_tail(&cmd->list, &dev->cmd_list); spin_unlock_irqrestore(&dev->list_lock, flags); - } + } else + put_device(&dev->sdev_gendev); return cmd; } @@ -276,7 +283,8 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int gfp_mask) */ void scsi_put_command(struct scsi_cmnd *cmd) { - struct Scsi_Host *shost = cmd->device->host; + struct scsi_device *sdev = cmd->device; + struct Scsi_Host *shost = sdev->host; unsigned long flags; /* serious error if the command hasn't come from a device list */ @@ -294,6 +302,8 @@ void scsi_put_command(struct scsi_cmnd *cmd) if (likely(cmd != NULL)) kmem_cache_free(shost->cmd_pool->slab, cmd); + + put_device(&sdev->sdev_gendev); } /* @@ -518,6 +528,26 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) /* return 0 (because the command has been processed) */ goto out; } + + /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */ + if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) { + /* + * in SDEV_BLOCK, the command is just put back on the device + * queue. The suspend state has already blocked the queue so + * future requests should not occur until the device + * transitions out of the suspend state. + */ + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); + + SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n")); + + /* + * NOTE: rtn is still zero here because we don't need the + * queue to be plugged on return (it's already stopped) + */ + goto out; + } + /* Assign a unique nonzero serial_number. */ /* XXX(hch): this is racy */ if (++serial_number == 0) @@ -897,15 +927,16 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) */ if (tags <= 0) return; - /* - * Limit max queue depth on a single lun to 256 for now. Remember, - * we allocate a struct scsi_command for each of these and keep it - * around forever. Too deep of a depth just wastes memory. - */ - if (tags > 256) - return; spin_lock_irqsave(&device_request_lock, flags); + spin_lock(sdev->request_queue->queue_lock); + + /* Check to see if the queue is managed by the block layer + * if it is, and we fail to adjust the depth, exit */ + if (blk_queue_tagged(sdev->request_queue) && + blk_queue_resize_tags(sdev->request_queue, tags) != 0) + goto out; + sdev->queue_depth = tags; switch (tagged) { case MSG_ORDERED_TAG: @@ -926,6 +957,8 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->queue_depth = tags; break; } + out: + spin_unlock(sdev->request_queue->queue_lock); spin_unlock_irqrestore(&device_request_lock, flags); } @@ -1030,6 +1063,7 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost, /* skip devices that we can't get a reference to */ if (!scsi_device_get(next)) break; + next = NULL; list = list->next; } spin_unlock_irqrestore(shost->host_lock, flags); @@ -1100,8 +1134,8 @@ EXPORT_SYMBOL(scsi_device_lookup); /** * scsi_device_cancel - cancel outstanding IO to this device - * @sdev: pointer to struct scsi_device - * @data: pointer to cancel value. + * @sdev: Pointer to struct scsi_device + * @recovery: Boolean instructing function to recover device or not. * **/ int scsi_device_cancel(struct scsi_device *sdev, int recovery) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index b9509840a..829c44550 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -55,8 +55,8 @@ #include "scsi_logging.h" #include "scsi_debug.h" -#define SCSI_DEBUG_VERSION "1.73" -static const char * scsi_debug_version_date = "20040518"; +#define SCSI_DEBUG_VERSION "1.74" +static const char * scsi_debug_version_date = "20040829"; /* Additional Sense Code (ASC) used */ #define NO_ADDED_SENSE 0x0 @@ -82,8 +82,9 @@ static const char * scsi_debug_version_date = "20040518"; #define DEF_EVERY_NTH 0 #define DEF_NUM_PARTS 0 #define DEF_OPTS 0 -#define DEF_SCSI_LEVEL 3 +#define DEF_SCSI_LEVEL 4 /* SPC-2 */ #define DEF_PTYPE 0 +#define DEF_D_SENSE 0 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -114,6 +115,7 @@ static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */ static int scsi_debug_opts = DEF_OPTS; static int scsi_debug_scsi_level = DEF_SCSI_LEVEL; static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */ +static int scsi_debug_dsense = DEF_D_SENSE; static int scsi_debug_cmnd_count = 0; @@ -277,7 +279,7 @@ static int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) { unsigned char *cmd = (unsigned char *) SCpnt->cmnd; - int block, upper_blk, num; + int block, upper_blk, num, k; unsigned char *buff; int errsts = 0; int target = SCpnt->device->id; @@ -305,7 +307,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) bufflen = SDEBUG_SENSE_LEN; } - + if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { + printk(KERN_INFO "scsi_debug: cmd "); + for (k = 0, num = SCpnt->cmd_len; k < num; ++k) + printk("%02x ", (int)cmd[k]); + printk("\n"); + } if(target == sdebug_driver_template.this_id) { printk(KERN_INFO "scsi_debug: initiator's id used as " "target!\n"); @@ -331,14 +338,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) } switch (*cmd) { - case INQUIRY: /* mandatory */ + case INQUIRY: /* mandatory, ignore unit attention */ errsts = resp_inquiry(cmd, target, buff, bufflen, devip); break; - case REQUEST_SENSE: /* mandatory */ - /* Since this driver indicates autosense by placing the - * sense buffer in the scsi_cmnd structure in the response - * (when SAM_STAT_CHECK_CONDITION is set), the mid level - * shouldn't need to call REQUEST_SENSE */ + case REQUEST_SENSE: /* mandatory, ignore unit attention */ if (devip) { sbuff = devip->sense_buff; memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? @@ -349,20 +352,24 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) buff[0] = 0x70; } break; + case REZERO_UNIT: /* actually this is REWIND for SSC */ case START_STOP: errsts = check_reset(SCpnt, devip); + memset(buff, 0, bufflen); break; case ALLOW_MEDIUM_REMOVAL: if ((errsts = check_reset(SCpnt, devip))) break; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk("\tMedium removal %s\n", - cmd[4] ? "inhibited" : "enabled"); + printk(KERN_INFO "scsi_debug: Medium removal %s\n", + cmd[4] ? "inhibited" : "enabled"); break; case SEND_DIAGNOSTIC: /* mandatory */ + errsts = check_reset(SCpnt, devip); memset(buff, 0, bufflen); break; case TEST_UNIT_READY: /* mandatory */ + errsts = check_reset(SCpnt, devip); memset(buff, 0, bufflen); break; case RESERVE: @@ -429,7 +436,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) errsts = check_condition_result; } break; - case REPORT_LUNS: + case REPORT_LUNS: /* mandatory, ignore unit attention */ errsts = resp_report_luns(cmd, buff, bufflen, devip); break; case WRITE_16: @@ -469,14 +476,20 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) break; case MODE_SENSE: case MODE_SENSE_10: + if ((errsts = check_reset(SCpnt, devip))) + break; errsts = resp_mode_sense(cmd, target, buff, bufflen, devip); break; case SYNCHRONIZE_CACHE: + errsts = check_reset(SCpnt, devip); memset(buff, 0, bufflen); break; default: + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " + "supported\n", *cmd); if ((errsts = check_reset(SCpnt, devip))) - break; + break; /* Unit attention takes precedence */ mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0, 18); errsts = check_condition_result; break; @@ -496,6 +509,9 @@ static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) { if (devip->reset) { + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + printk(KERN_INFO "scsi_debug: Reporting Unit " + "attention: power on reset\n"); devip->reset = 0; mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0, 18); return check_condition_result; @@ -503,7 +519,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) return 0; } -#define SDEBUG_LONG_INQ_SZ 58 +#define SDEBUG_LONG_INQ_SZ 96 #define SDEBUG_MAX_INQ_ARR_SZ 128 static const char * vendor_id = "Linux "; @@ -593,11 +609,21 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, /* drops through here for a standard inquiry */ arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */ arr[2] = scsi_debug_scsi_level; + arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; + arr[6] = 0x1; /* claim: ADDR16 */ arr[7] = 0x3a; /* claim: WBUS16, SYNC, LINKED + CMDQUE */ memcpy(&arr[8], vendor_id, 8); memcpy(&arr[16], product_id, 16); memcpy(&arr[32], product_rev, 4); + /* version descriptors (2 bytes each) follow */ + arr[58] = 0x0; arr[59] = 0x40; /* SAM-2 */ + arr[60] = 0x2; arr[61] = 0x60; /* SPC-2 */ + if (scsi_debug_ptype == 0) { + arr[62] = 0x1; arr[63] = 0x80; /* SBC */ + } else if (scsi_debug_ptype == 1) { + arr[62] = 0x2; arr[63] = 0x00; /* SSC */ + } memcpy(buff, arr, min_len); return 0; } @@ -660,6 +686,8 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target) unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; + if (scsi_debug_dsense) + ctrl_m_pg[2] |= 0x4; memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg)); if (1 == pcontrol) memset(p + 2, 0, sizeof(ctrl_m_pg) - 2); @@ -683,7 +711,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, struct sdebug_dev_info * devip) { unsigned char dbd; - int pcontrol, pcode; + int pcontrol, pcode, subpcode; unsigned char dev_spec; int alloc_len, msense_6, offset, len; unsigned char * ap; @@ -695,11 +723,9 @@ static int resp_mode_sense(unsigned char * cmd, int target, dbd = cmd[1] & 0x8; pcontrol = (cmd[2] & 0xc0) >> 6; pcode = cmd[2] & 0x3f; + subpcode = cmd[3]; msense_6 = (MODE_SENSE == cmd[0]); alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); - /* printk(KERN_INFO "msense: dbd=%d pcontrol=%d pcode=%d " - "msense_6=%d alloc_len=%d\n", dbd, pcontrol, pcode, " - "msense_6, alloc_len); */ if (bufflen < alloc_len) printk(KERN_INFO "scsi_debug: mode_sense: bufflen=%d " "< alloc_length=%d\n", bufflen, alloc_len); @@ -720,6 +746,11 @@ static int resp_mode_sense(unsigned char * cmd, int target, } ap = arr + offset; + if (0 != subpcode) { /* TODO: Control Extension page */ + mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + 0, 18); + return check_condition_result; + } switch (pcode) { case 0x1: /* Read-Write error recovery page, direct access */ len = resp_err_recov_pg(ap, pcontrol, target); @@ -1023,13 +1054,23 @@ static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, sbuff = devip->sense_buff; memset(sbuff, 0, SDEBUG_SENSE_LEN); - if (inbandLen > SDEBUG_SENSE_LEN) - inbandLen = SDEBUG_SENSE_LEN; - sbuff[0] = 0x70; - sbuff[2] = key; - sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0; - sbuff[12] = asc; - sbuff[13] = asq; + if (scsi_debug_dsense) { + sbuff[0] = 0x72; /* descriptor, current */ + sbuff[1] = key; + sbuff[2] = asc; + sbuff[3] = asq; + } else { + if (inbandLen > SDEBUG_SENSE_LEN) + inbandLen = SDEBUG_SENSE_LEN; + sbuff[0] = 0x70; /* fixed, current */ + sbuff[2] = key; + sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0; + sbuff[12] = asc; + sbuff[13] = asq; + } + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " + "[0x%x,0x%x,0x%x]\n", key, asc, asq); } static int scsi_debug_abort(struct scsi_cmnd * SCpnt) @@ -1230,17 +1271,11 @@ static int schedule_resp(struct scsi_cmnd * cmnd, struct sdebug_dev_info * devip, done_funct_t done, int scsi_result, int delta_jiff) { - int k, num; - if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) { - printk(KERN_INFO "scsi_debug: cmd "); - for (k = 0, num = cmnd->cmd_len; k < num; ++k) - printk("%02x ", (int)cmnd->cmnd[k]); - printk("\n"); if (scsi_result) { struct scsi_device * sdp = cmnd->device; - printk(KERN_INFO "scsi_debug: ... <%u %u %u %u> " + printk(KERN_INFO "scsi_debug: <%u %u %u %u> " "non-zero result=0x%x\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun, scsi_result); } @@ -1296,6 +1331,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, module_param_named(add_host, scsi_debug_add_host, int, 0); /* perm=0644 */ module_param_named(delay, scsi_debug_delay, int, 0); /* perm=0644 */ module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, 0); +module_param_named(dsense, scsi_debug_dsense, int, 0); module_param_named(every_nth, scsi_debug_every_nth, int, 0); module_param_named(max_luns, scsi_debug_max_luns, int, 0); module_param_named(num_parts, scsi_debug_num_parts, int, 0); @@ -1312,13 +1348,14 @@ MODULE_VERSION(SCSI_DEBUG_VERSION); MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs"); +MODULE_PARM_DESC(dsense, "use descriptor sense format(def: fixed)"); MODULE_PARM_DESC(every_nth, "timeout every nth command(def=100)"); MODULE_PARM_DESC(max_luns, "number of SCSI LUNs per target to simulate"); MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate"); MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->..."); MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); -MODULE_PARM_DESC(scsi_level, "SCSI level to simulate"); +MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=4[SPC-2])"); static char sdebug_info[256]; @@ -1452,6 +1489,24 @@ static ssize_t sdebug_ptype_store(struct device_driver * ddp, } DRIVER_ATTR(ptype, S_IRUGO | S_IWUSR, sdebug_ptype_show, sdebug_ptype_store); +static ssize_t sdebug_dsense_show(struct device_driver * ddp, char * buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dsense); +} +static ssize_t sdebug_dsense_store(struct device_driver * ddp, + const char * buf, size_t count) +{ + int n; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + scsi_debug_dsense = n; + return count; + } + return -EINVAL; +} +DRIVER_ATTR(dsense, S_IRUGO | S_IWUSR, sdebug_dsense_show, + sdebug_dsense_store); + static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 0153b7747..4347594a6 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -83,6 +83,7 @@ static struct { {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN}, {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN}, {"SONY", "CD-ROM CDU-8012", NULL, BLIST_NOLUN}, + {"SONY", "SDT-5000", "3.17", BLIST_SELECT_NO_ATN}, {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN}, /* locks up */ {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN}, /* locks up */ /* @@ -115,13 +116,15 @@ static struct { /* * Other types of devices that have special flags. + * Note that all USB devices should have the BLIST_INQUIRY_36 flag. */ + {"3PARdata", "VV", NULL, BLIST_REPORTLUN2}, {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN}, - {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN}, + {"BELKIN", "USB 2 HS-CF", "1.95", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, - {"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN}, + {"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ @@ -142,9 +145,9 @@ static struct { {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN}, - {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN}, - {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN}, + {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36}, + {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36}, + {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, @@ -153,6 +156,7 @@ static struct { {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, {"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD}, {"HP", "C1557A", NULL, BLIST_FORCELUN}, + {"HP", "C3323-300", "4269", BLIST_NOTQ}, {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, @@ -179,10 +183,13 @@ static struct { {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN}, + {"SEAGATE", "ST34555N", "0930", BLIST_NOTQ}, /* Chokes on tagged INQUIRY */ + {"SEAGATE", "ST3390N", "9546", BLIST_NOTQ}, {"SGI", "RAID3", "*", BLIST_SPARSELUN}, {"SGI", "RAID5", "*", BLIST_SPARSELUN}, {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, - {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN}, + {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, + {"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36}, {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ {"SUN", "T300", "*", BLIST_SPARSELUN}, @@ -190,7 +197,10 @@ static struct { {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, - {"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN}, + {"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36}, + {"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN}, + {"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN}, + {"WangDAT", "Model 1300", "02.4", BLIST_SELECT_NO_ATN}, {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, @@ -510,7 +520,7 @@ void scsi_exit_devinfo(void) * Add command line @dev_list entries, then add * scsi_static_device_list entries to the scsi device info list. **/ -int scsi_init_devinfo(void) +int __init scsi_init_devinfo(void) { #ifdef CONFIG_SCSI_PROC_FS struct proc_dir_entry *p; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 288f2fde9..e9841638b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -42,8 +42,8 @@ * These should *probably* be handled by the host itself. * Since it is allowed to sleep, it probably should. */ -#define BUS_RESET_SETTLE_TIME (10*HZ) -#define HOST_RESET_SETTLE_TIME (10*HZ) +#define BUS_RESET_SETTLE_TIME (10) +#define HOST_RESET_SETTLE_TIME (10) /* called with shost->host_lock held */ void scsi_eh_wakeup(struct Scsi_Host *shost) @@ -643,15 +643,13 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, * Notes: * This has the unfortunate side effect that if a shost adapter does * not automatically request sense information, that we end up shutting - * it down before we request it. All shosts should be doing this - * anyways, so for now all I have to say is tough noogies if you end up - * in here. On second thought, this is probably a good idea. We - * *really* want to give authors an incentive to automatically request - * this. + * it down before we request it. * - * In 2.5 this capability will be going away. + * All drivers should request sense information internally these days, + * so for now all I have to say is tough noogies if you end up in here. * - * Really? --hch + * XXX: Long term this code should go away, but that needs an audit of + * all LLDDs first. **/ static int scsi_eh_get_sense(struct list_head *work_q, struct list_head *done_q) @@ -1044,7 +1042,7 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) if (rtn == SUCCESS) { if (!scmd->device->host->hostt->skip_settle_delay) - scsi_sleep(BUS_RESET_SETTLE_TIME); + ssleep(BUS_RESET_SETTLE_TIME); spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); spin_unlock_irqrestore(scmd->device->host->host_lock, flags); @@ -1076,7 +1074,7 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) if (rtn == SUCCESS) { if (!scmd->device->host->hostt->skip_settle_delay) - scsi_sleep(HOST_RESET_SETTLE_TIME); + ssleep(HOST_RESET_SETTLE_TIME); spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); spin_unlock_irqrestore(scmd->device->host->host_lock, flags); @@ -1215,43 +1213,6 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, return; } -/** - * scsi_sleep_done - timer function for scsi_sleep - * @sem: semphore to signal - * - **/ -static void scsi_sleep_done(unsigned long data) -{ - struct semaphore *sem = (struct semaphore *)data; - - if (sem) - up(sem); -} - -/** - * scsi_sleep - sleep for specified timeout - * @timeout: timeout value - * - **/ -void scsi_sleep(int timeout) -{ - DECLARE_MUTEX_LOCKED(sem); - struct timer_list timer; - - init_timer(&timer); - timer.data = (unsigned long)&sem; - timer.expires = jiffies + timeout; - timer.function = (void (*)(unsigned long))scsi_sleep_done; - - SCSI_LOG_ERROR_RECOVERY(5, printk("sleeping for timer tics %d\n", - timeout)); - - add_timer(&timer); - - down(&sem); - del_timer(&timer); -} - /** * scsi_decide_disposition - Disposition a cmd on return from LLD. * @scmd: SCSI cmd to examine. @@ -1639,8 +1600,6 @@ int scsi_error_handler(void *data) int rtn; DECLARE_MUTEX_LOCKED(sem); - lock_kernel(); - /* * Flush resources */ @@ -1652,8 +1611,6 @@ int scsi_error_handler(void *data) shost->eh_wait = &sem; shost->ehandler = current; - unlock_kernel(); - /* * Wake up the thread that created us. */ @@ -1886,3 +1843,79 @@ scsi_reset_provider(struct scsi_device *dev, int flag) scsi_next_command(scmd); return rtn; } + +/** + * scsi_normalize_sense - normalize main elements from either fixed or + * descriptor sense data format into a common format. + * + * @sense_buffer: byte array containing sense data returned by device + * @sb_len: number of valid bytes in sense_buffer + * @sshdr: pointer to instance of structure that common + * elements are written to. + * + * Notes: + * The "main elements" from sense data are: response_code, sense_key, + * asc, ascq and additional_length (only for descriptor format). + * + * Typically this function can be called after a device has + * responded to a SCSI command with the CHECK_CONDITION status. + * + * Return value: + * 1 if valid sense data information found, else 0; + **/ +int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, + struct scsi_sense_hdr *sshdr) +{ + if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) + return 0; + + memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); + + sshdr->response_code = (sense_buffer[0] & 0x7f); + if (sshdr->response_code >= 0x72) { + /* + * descriptor format + */ + if (sb_len > 1) + sshdr->sense_key = (sense_buffer[1] & 0xf); + if (sb_len > 2) + sshdr->asc = sense_buffer[2]; + if (sb_len > 3) + sshdr->ascq = sense_buffer[3]; + if (sb_len > 7) + sshdr->additional_length = sense_buffer[7]; + } else { + /* + * fixed format + */ + if (sb_len > 2) + sshdr->sense_key = (sense_buffer[2] & 0xf); + if (sb_len > 7) { + sb_len = (sb_len < (sense_buffer[7] + 8)) ? + sb_len : (sense_buffer[7] + 8); + if (sb_len > 12) + sshdr->asc = sense_buffer[12]; + if (sb_len > 13) + sshdr->ascq = sense_buffer[13]; + } + } + + return 1; +} +EXPORT_SYMBOL(scsi_normalize_sense); + +int scsi_request_normalize_sense(struct scsi_request *sreq, + struct scsi_sense_hdr *sshdr) +{ + return scsi_normalize_sense(sreq->sr_sense_buffer, + sizeof(sreq->sr_sense_buffer), sshdr); +} +EXPORT_SYMBOL(scsi_request_normalize_sense); + +int scsi_command_normalize_sense(struct scsi_cmnd *cmd, + struct scsi_sense_hdr *sshdr) +{ + return scsi_normalize_sense(cmd->sense_buffer, + sizeof(cmd->sense_buffer), sshdr); +} +EXPORT_SYMBOL(scsi_command_normalize_sense); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index bc5869b10..d459bb7a0 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "scsi_logging.h" @@ -391,6 +392,21 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; + /* Check for deprecated ioctls ... all the ioctls which don't + * follow the new unique numbering scheme are deprecated */ + switch (cmd) { + case SCSI_IOCTL_SEND_COMMAND: + case SCSI_IOCTL_TEST_UNIT_READY: + case SCSI_IOCTL_BENCHMARK_COMMAND: + case SCSI_IOCTL_SYNC: + case SCSI_IOCTL_START_UNIT: + case SCSI_IOCTL_STOP_UNIT: + printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); + break; + default: + break; + } + switch (cmd) { case SCSI_IOCTL_GET_IDLUN: if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) @@ -417,12 +433,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) case SCSI_IOCTL_DOORUNLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); case SCSI_IOCTL_TEST_UNIT_READY: - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = 0; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; - scsi_cmd[4] = 0; - return ioctl_internal_command(sdev, scsi_cmd, - IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); + return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, + NORMAL_RETRIES); case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = 0; @@ -445,3 +457,51 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) } return -EINVAL; } + +/* + * the scsi_nonblock_ioctl() function is designed for ioctls which may + * be executed even if the device is in recovery. + */ +int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, + void __user *arg, struct file *filp) +{ + int val, result; + + /* The first set of iocts may be executed even if we're doing + * error processing, as long as the device was opened + * non-blocking */ + if (filp && filp->f_flags & O_NONBLOCK) { + if (test_bit(SHOST_RECOVERY, + &sdev->host->shost_state)) + return -ENODEV; + } else if (!scsi_block_when_processing_errors(sdev)) + return -ENODEV; + + switch (cmd) { + case SG_SCSI_RESET: + result = get_user(val, (int __user *)arg); + if (result) + return result; + if (val == SG_SCSI_RESET_NOTHING) + return 0; + switch (val) { + case SG_SCSI_RESET_DEVICE: + val = SCSI_TRY_RESET_DEVICE; + break; + case SG_SCSI_RESET_BUS: + val = SCSI_TRY_RESET_BUS; + break; + case SG_SCSI_RESET_HOST: + val = SCSI_TRY_RESET_HOST; + break; + default: + return -EINVAL; + } + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return (scsi_reset_provider(sdev, val) == + SUCCESS) ? 0 : -EIO; + } + return -ENODEV; +} +EXPORT_SYMBOL(scsi_nonblockable_ioctl); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e30d3f2bf..ceee6c283 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -365,7 +366,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) unsigned long flags; spin_lock_irqsave(shost->host_lock, flags); - current_sdev->sdev_target->starget_sdev_user = NULL; + scsi_target(current_sdev)->starget_sdev_user = NULL; spin_unlock_irqrestore(shost->host_lock, flags); /* @@ -377,7 +378,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) blk_run_queue(current_sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); - if (current_sdev->sdev_target->starget_sdev_user) + if (scsi_target(current_sdev)->starget_sdev_user) goto out; list_for_each_entry_safe(sdev, tmp, ¤t_sdev->same_target_siblings, same_target_siblings) { @@ -692,6 +693,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, request_queue_t *q = cmd->device->request_queue; struct request *req = cmd->request; int clear_errors = 1; + struct scsi_sense_hdr sshdr; /* * Free up any indirection buffers we allocated for DMA purposes. @@ -711,11 +713,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, } if (blk_pc_request(req)) { /* SG_IO ioctl from block level */ - req->errors = (driver_byte(result) & DRIVER_SENSE) ? - (CHECK_CONDITION << 1) : (result & 0xff); + req->errors = result; if (result) { clear_errors = 0; - if (cmd->sense_buffer[0] & 0x70) { + if (scsi_command_normalize_sense(cmd, &sshdr)) { + /* + * SG_IO wants to know about deferred errors + */ int len = 8 + cmd->sense_buffer[7]; if (len > SCSI_SENSE_BUFFERSIZE) @@ -724,7 +728,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, req->sense_len = len; } } else - req->data_len -= cmd->bufflen; + req->data_len = cmd->resid; } /* @@ -774,17 +778,17 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, * can choose a block to remap, etc. */ if (driver_byte(result) != 0) { - if ((cmd->sense_buffer[0] & 0x7f) == 0x70) { + if (scsi_command_normalize_sense(cmd, &sshdr) && + !scsi_sense_is_deferred(&sshdr)) { /* * If the device is in the process of becoming ready, * retry. */ - if (cmd->sense_buffer[12] == 0x04 && - cmd->sense_buffer[13] == 0x01) { + if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) { scsi_requeue_command(q, cmd); return; } - if ((cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { + if (sshdr.sense_key == UNIT_ATTENTION) { if (cmd->device->removable) { /* detected disc change. set a bit * and quietly refuse further access. @@ -813,7 +817,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, * failed, we may have read past the end of the disk. */ - switch (cmd->sense_buffer[2]) { + /* + * XXX: Following is probably broken since deferred errors + * fall through [dpg 20040827] + */ + switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd->device->use_10_for_rw && (cmd->cmnd[0] == READ_10 || @@ -835,8 +843,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, req->rq_disk ? req->rq_disk->disk_name : ""); cmd = scsi_end_request(cmd, 0, this_count, 1); return; - break; - case MEDIUM_ERROR: case VOLUME_OVERFLOW: printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ", cmd->device->host->host_no, (int) cmd->device->channel, @@ -954,6 +960,22 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_KILL; } +static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct scsi_device *sdev = q->queuedata; + struct scsi_driver *drv; + + if (sdev->sdev_state != SDEV_RUNNING) + return -ENXIO; + + drv = *(struct scsi_driver **) disk->private_data; + if (drv->issue_flush) + return drv->issue_flush(&sdev->sdev_gendev, error_sector); + + return -EOPNOTSUPP; +} + static int scsi_prep_fn(struct request_queue *q, struct request *req) { struct scsi_device *sdev = q->queuedata; @@ -1008,7 +1030,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { if(unlikely(specials_only)) { - if(specials_only == SDEV_QUIESCE) + if(specials_only == SDEV_QUIESCE || + specials_only == SDEV_BLOCK) return BLKPREP_DEFER; printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", @@ -1231,10 +1254,10 @@ static void scsi_request_fn(struct request_queue *q) if (!scsi_host_queue_ready(q, shost, sdev)) goto not_ready; if (sdev->single_lun) { - if (sdev->sdev_target->starget_sdev_user && - sdev->sdev_target->starget_sdev_user != sdev) + if (scsi_target(sdev)->starget_sdev_user && + scsi_target(sdev)->starget_sdev_user != sdev) goto not_ready; - sdev->sdev_target->starget_sdev_user = sdev; + scsi_target(sdev)->starget_sdev_user = sdev; } shost->host_busy++; @@ -1304,19 +1327,22 @@ static void scsi_request_fn(struct request_queue *q) u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) { struct device *host_dev; + u64 bounce_limit = 0xffffffff; if (shost->unchecked_isa_dma) return BLK_BOUNCE_ISA; - - host_dev = scsi_get_device(shost); - if (PCI_DMA_BUS_IS_PHYS && host_dev && host_dev->dma_mask) - return *host_dev->dma_mask; - /* * Platforms with virtual-DMA translation * hardware have no practical limit. */ - return BLK_BOUNCE_ANY; + if (!PCI_DMA_BUS_IS_PHYS) + return BLK_BOUNCE_ANY; + + host_dev = scsi_get_device(shost); + if (host_dev && host_dev->dma_mask) + bounce_limit = *host_dev->dma_mask; + + return bounce_limit; } struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) @@ -1335,7 +1361,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); - + blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); + if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; @@ -1479,8 +1506,7 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, } sreq->sr_cmd_len = 0; - sreq->sr_sense_buffer[0] = 0; - sreq->sr_sense_buffer[2] = 0; + memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); sreq->sr_data_direction = DMA_FROM_DEVICE; memset(buffer, 0, len); @@ -1491,14 +1517,21 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, * ILLEGAL REQUEST sense return identifies the actual command * byte as the problem. MODE_SENSE commands can return * ILLEGAL REQUEST if the code page isn't supported */ - if (use_10_for_ms && ! scsi_status_is_good(sreq->sr_result) && - (driver_byte(sreq->sr_result) & DRIVER_SENSE) && - sreq->sr_sense_buffer[2] == ILLEGAL_REQUEST && - (sreq->sr_sense_buffer[4] & 0x40) == 0x40 && - sreq->sr_sense_buffer[5] == 0 && - sreq->sr_sense_buffer[6] == 0 ) { - sreq->sr_device->use_10_for_ms = 0; - goto retry; + + if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) && + (driver_byte(sreq->sr_result) & DRIVER_SENSE)) { + struct scsi_sense_hdr sshdr; + + if (scsi_request_normalize_sense(sreq, &sshdr)) { + if ((sshdr.sense_key == ILLEGAL_REQUEST) && + (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { + /* + * Invalid command operation code + */ + sreq->sr_device->use_10_for_ms = 0; + goto retry; + } + } } if(scsi_status_is_good(sreq->sr_result)) { @@ -1555,6 +1588,35 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, return ret; } +int +scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) +{ + struct scsi_request *sreq; + char cmd[] = { + TEST_UNIT_READY, 0, 0, 0, 0, 0, + }; + int result; + + sreq = scsi_allocate_request(sdev, GFP_KERNEL); + if (!sreq) + return -ENOMEM; + + sreq->sr_data_direction = DMA_NONE; + scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); + + if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && + ((sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION || + (sreq->sr_sense_buffer[2] & 0x0f) == NOT_READY) && + sdev->removable) { + sdev->changed = 1; + sreq->sr_result = 0; + } + result = sreq->sr_result; + scsi_release_request(sreq); + return result; +} +EXPORT_SYMBOL(scsi_test_unit_ready); + /** * scsi_device_set_state - Take the given device through the device * state model. @@ -1584,6 +1646,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) case SDEV_CREATED: case SDEV_OFFLINE: case SDEV_QUIESCE: + case SDEV_BLOCK: break; default: goto illegal; @@ -1611,11 +1674,22 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) } break; + case SDEV_BLOCK: + switch (oldstate) { + case SDEV_CREATED: + case SDEV_RUNNING: + break; + default: + goto illegal; + } + break; + case SDEV_CANCEL: switch (oldstate) { case SDEV_CREATED: case SDEV_RUNNING: case SDEV_OFFLINE: + case SDEV_BLOCK: break; default: goto illegal; @@ -1669,7 +1743,7 @@ scsi_device_quiesce(struct scsi_device *sdev) scsi_run_queue(sdev->request_queue); while (sdev->device_busy) { - schedule_timeout(HZ/5); + msleep_interruptible(200); scsi_run_queue(sdev->request_queue); } return 0; @@ -1694,3 +1768,111 @@ scsi_device_resume(struct scsi_device *sdev) } EXPORT_SYMBOL(scsi_device_resume); +static int +device_quiesce_fn(struct device *dev, void *data) +{ + scsi_device_quiesce(to_scsi_device(dev)); + return 0; +} + +void +scsi_target_quiesce(struct scsi_target *starget) +{ + device_for_each_child(&starget->dev, NULL, device_quiesce_fn); +} +EXPORT_SYMBOL(scsi_target_quiesce); + +static int +device_resume_fn(struct device *dev, void *data) +{ + scsi_device_resume(to_scsi_device(dev)); + return 0; +} + +void +scsi_target_resume(struct scsi_target *starget) +{ + device_for_each_child(&starget->dev, NULL, device_resume_fn); +} +EXPORT_SYMBOL(scsi_target_resume); + +/** + * scsi_internal_device_block - internal function to put a device + * temporarily into the SDEV_BLOCK state + * @sdev: device to block + * + * Block request made by scsi lld's to temporarily stop all + * scsi commands on the specified device. Called from interrupt + * or normal process context. + * + * Returns zero if successful or error if not + * + * Notes: + * This routine transitions the device to the SDEV_BLOCK state + * (which must be a legal transition). When the device is in this + * state, all commands are deferred until the scsi lld reenables + * the device with scsi_device_unblock or device_block_tmo fires. + * This routine assumes the host_lock is held on entry. + **/ +int +scsi_internal_device_block(struct scsi_device *sdev) +{ + request_queue_t *q = sdev->request_queue; + unsigned long flags; + int err = 0; + + err = scsi_device_set_state(sdev, SDEV_BLOCK); + if (err) + return err; + + /* + * The device has transitioned to SDEV_BLOCK. Stop the + * block layer from calling the midlayer with this device's + * request queue. + */ + spin_lock_irqsave(q->queue_lock, flags); + blk_stop_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(scsi_internal_device_block); + +/** + * scsi_internal_device_unblock - resume a device after a block request + * @sdev: device to resume + * + * Called by scsi lld's or the midlayer to restart the device queue + * for the previously suspended scsi device. Called from interrupt or + * normal process context. + * + * Returns zero if successful or error if not. + * + * Notes: + * This routine transitions the device to the SDEV_RUNNING state + * (which must be a legal transition) allowing the midlayer to + * goose the queue for this device. This routine assumes the + * host_lock is held upon entry. + **/ +int +scsi_internal_device_unblock(struct scsi_device *sdev) +{ + request_queue_t *q = sdev->request_queue; + int err; + unsigned long flags; + + /* + * Try to transition the scsi device to SDEV_RUNNING + * and goose the device queue if successful. + */ + err = scsi_device_set_state(sdev, SDEV_RUNNING); + if (err) + return err; + + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(scsi_internal_device_unblock); diff --git a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c index d835a505b..489175833 100644 --- a/drivers/scsi/scsi_module.c +++ b/drivers/scsi/scsi_module.c @@ -11,7 +11,6 @@ #include #include -#include "scsi.h" #include diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 4dfb3db63..adedf7366 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -58,16 +58,6 @@ struct Scsi_Host; */ #define SCAN_WILD_CARD ~0 -/* - * scsi_target: representation of a scsi target, for now, this is only - * used for single_lun devices. If no one has active IO to the target, - * starget_sdev_user is NULL, else it points to the active sdev. - */ -struct scsi_target { - struct scsi_device *starget_sdev_user; - unsigned int starget_refcnt; -}; - /* hosts.c */ extern int scsi_init_hosts(void); extern void scsi_exit_hosts(void); @@ -96,7 +86,7 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) /* scsi_devinfo.c */ extern int scsi_get_device_flags(struct scsi_device *sdev, unsigned char *vendor, unsigned char *model); -extern int scsi_init_devinfo(void); +extern int __init scsi_init_devinfo(void); extern void scsi_exit_devinfo(void); /* scsi_error.c */ @@ -156,9 +146,20 @@ extern int scsi_sysfs_add_sdev(struct scsi_device *); extern int scsi_sysfs_add_host(struct Scsi_Host *); extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); +extern int scsi_sysfs_device_initialize(struct scsi_device *); +extern int scsi_sysfs_target_initialize(struct scsi_device *); extern struct scsi_transport_template blank_transport_template; extern struct class sdev_class; extern struct bus_type scsi_bus_type; +/* + * internal scsi timeout functions: for use by mid-layer and transport + * classes. + */ + +#define SCSI_DEVICE_BLOCK_MAX_TIMEOUT (HZ*60) +extern int scsi_internal_device_block(struct scsi_device *sdev); +extern int scsi_internal_device_unblock(struct scsi_device *sdev); + #endif /* _SCSI_PRIV_H */ diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 166cb9ab3..f6b9f893c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -200,12 +200,14 @@ static void print_inquiry(unsigned char *inq_result) * scsi_Device pointer, or NULL on failure. **/ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, - uint channel, uint id, uint lun) + uint channel, uint id, uint lun, void *hostdata) { - struct scsi_device *sdev, *device; + struct scsi_device *sdev; unsigned long flags; + int display_failure_msg = 1, ret; - sdev = kmalloc(sizeof(*sdev) + shost->transportt->size, GFP_ATOMIC); + sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, + GFP_ATOMIC); if (!sdev) goto out; @@ -224,6 +226,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, INIT_LIST_HEAD(&sdev->starved_entry); spin_lock_init(&sdev->list_lock); + /* usually NULL and set by ->slave_alloc instead */ + sdev->hostdata = hostdata; /* if the device needs this changing, it may do so in the * slave_configure function */ @@ -250,71 +254,39 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); if (shost->hostt->slave_alloc) { - if (shost->hostt->slave_alloc(sdev)) + ret = shost->hostt->slave_alloc(sdev); + if (ret) { + /* + * if LLDD reports slave not present, don't clutter + * console with alloc failure messages + */ + if (ret == -ENXIO) + display_failure_msg = 0; goto out_free_queue; + } } - if (shost->transportt->setup) { - if (shost->transportt->setup(sdev)) + if (shost->transportt->device_setup) { + if (shost->transportt->device_setup(sdev)) goto out_cleanup_slave; } - if (get_device(&sdev->host->shost_gendev)) { - - device_initialize(&sdev->sdev_gendev); - sdev->sdev_gendev.parent = &sdev->host->shost_gendev; - sdev->sdev_gendev.bus = &scsi_bus_type; - sdev->sdev_gendev.release = scsi_device_dev_release; - sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", - sdev->host->host_no, sdev->channel, sdev->id, - sdev->lun); - - class_device_initialize(&sdev->sdev_classdev); - sdev->sdev_classdev.dev = &sdev->sdev_gendev; - sdev->sdev_classdev.class = &sdev_class; - snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, - "%d:%d:%d:%d", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); - - class_device_initialize(&sdev->transport_classdev); - sdev->transport_classdev.dev = &sdev->sdev_gendev; - sdev->transport_classdev.class = sdev->host->transportt->class; - snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE, - "%d:%d:%d:%d", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); - } else - goto out_cleanup_transport; + if (scsi_sysfs_device_initialize(sdev) != 0) + goto out_cleanup_slave; - /* - * If there are any same target siblings, add this to the - * sibling list - */ - spin_lock_irqsave(shost->host_lock, flags); - list_for_each_entry(device, &shost->__devices, siblings) { - if (device->id == sdev->id && - device->channel == sdev->channel) { - list_add_tail(&sdev->same_target_siblings, - &device->same_target_siblings); - sdev->scsi_level = device->scsi_level; - break; - } - } - /* - * If there wasn't another lun already configured at this - * target, then default this device to SCSI_2 until we - * know better - */ - if (!sdev->scsi_level) - sdev->scsi_level = SCSI_2; + /* NOTE: this target initialisation code depends critically on + * lun scanning being sequential. */ + if (scsi_sysfs_target_initialize(sdev)) + goto out_remove_siblings; - list_add_tail(&sdev->siblings, &shost->__devices); - spin_unlock_irqrestore(shost->host_lock, flags); return sdev; -out_cleanup_transport: - if (shost->transportt->cleanup) - shost->transportt->cleanup(sdev); +out_remove_siblings: + spin_lock_irqsave(shost->host_lock, flags); + list_del(&sdev->siblings); + list_del(&sdev->same_target_siblings); + spin_unlock_irqrestore(shost->host_lock, flags); out_cleanup_slave: if (shost->hostt->slave_destroy) shost->hostt->slave_destroy(sdev); @@ -323,7 +295,8 @@ out_free_queue: out_free_dev: kfree(sdev); out: - printk(ALLOC_FAILURE_MSG, __FUNCTION__); + if (display_failure_msg) + printk(ALLOC_FAILURE_MSG, __FUNCTION__); return NULL; } @@ -346,104 +319,113 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, { struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ unsigned char scsi_cmd[MAX_COMMAND_SIZE]; - int possible_inq_resp_len; - int count = 0; + int first_inquiry_len, try_inquiry_len, next_inquiry_len; + int response_len = 0; + int pass, count; *bflags = 0; - repeat_inquiry: - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY to host %d" - " channel %d id %d lun %d\n", sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun)); - - memset(scsi_cmd, 0, 6); - scsi_cmd[0] = INQUIRY; - scsi_cmd[4] = 36; /* issue conservative alloc_length */ - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; - memset(inq_result, 0, 36); - scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, 36, - HZ/2 + HZ*scsi_inq_timeout, 3); + /* Perform up to 3 passes. The first pass uses a conservative + * transfer length of 36 unless sdev->inquiry_len specifies a + * different value. */ + first_inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; + try_inquiry_len = first_inquiry_len; + pass = 1; + + next_pass: + SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY pass %d " + "to host %d channel %d id %d lun %d, length %d\n", + pass, sdev->host->host_no, sdev->channel, + sdev->id, sdev->lun, try_inquiry_len)); + + /* Each pass gets up to three chances to ignore Unit Attention */ + for (count = 0; count < 3; ++count) { + memset(scsi_cmd, 0, 6); + scsi_cmd[0] = INQUIRY; + scsi_cmd[4] = (unsigned char) try_inquiry_len; + sreq->sr_cmd_len = 0; + sreq->sr_data_direction = DMA_FROM_DEVICE; - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 1st INQUIRY %s with" - " code 0x%x\n", sreq->sr_result ? - "failed" : "successful", sreq->sr_result)); - ++count; + memset(inq_result, 0, try_inquiry_len); + scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, + try_inquiry_len, + HZ/2 + HZ*scsi_inq_timeout, 3); + + SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " + "with code 0x%x\n", + sreq->sr_result ? "failed" : "successful", + sreq->sr_result)); + + if (sreq->sr_result) { - if (sreq->sr_result) { - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) != 0 && - (sreq->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION && - (sreq->sr_sense_buffer[12] == 0x28 || - sreq->sr_sense_buffer[12] == 0x29) && - sreq->sr_sense_buffer[13] == 0) { /* not-ready to ready transition or power-on - good */ /* dpg: bogus? INQUIRY never returns UNIT_ATTENTION */ - /* Supposedly, but many buggy devices do so anyway */ - if (count < 3) - goto repeat_inquiry; + /* Supposedly, but many buggy devices do so anyway. */ + if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && + (sreq->sr_sense_buffer[2] & 0xf) == + UNIT_ATTENTION && + (sreq->sr_sense_buffer[12] == 0x28 || + sreq->sr_sense_buffer[12] == 0x29) && + sreq->sr_sense_buffer[13] == 0) + continue; } - /* - * assume no peripheral if any other sort of error - */ - return; + break; } - /* - * Get any flags for this device. - * - * XXX add a bflags to Scsi_Device, and replace the corresponding - * bit fields in Scsi_Device, so bflags need not be passed as an - * argument. - */ - *bflags |= scsi_get_device_flags(sdev, &inq_result[8], &inq_result[16]); + if (sreq->sr_result == 0) { + response_len = (unsigned char) inq_result[4] + 5; + if (response_len > 255) + response_len = first_inquiry_len; /* sanity */ - possible_inq_resp_len = (unsigned char) inq_result[4] + 5; - if (BLIST_INQUIRY_36 & *bflags) - possible_inq_resp_len = 36; - else if (BLIST_INQUIRY_58 & *bflags) - possible_inq_resp_len = 58; - else if (possible_inq_resp_len > 255) - possible_inq_resp_len = 36; /* sanity */ - - if (possible_inq_resp_len > 36) { /* do additional INQUIRY */ - memset(scsi_cmd, 0, 6); - scsi_cmd[0] = INQUIRY; - scsi_cmd[4] = (unsigned char) possible_inq_resp_len; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; /* - * re-zero inq_result just to be safe. + * Get any flags for this device. + * + * XXX add a bflags to Scsi_Device, and replace the + * corresponding bit fields in Scsi_Device, so bflags + * need not be passed as an argument. */ - memset(inq_result, 0, possible_inq_resp_len); - scsi_wait_req(sreq, (void *) scsi_cmd, - (void *) inq_result, - possible_inq_resp_len, (1+scsi_inq_timeout)*(HZ/2), 3); - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 2nd INQUIRY" - " %s with code 0x%x\n", sreq->sr_result ? - "failed" : "successful", sreq->sr_result)); - if (sreq->sr_result) { - /* if the longer inquiry has failed, flag the device - * as only accepting 36 byte inquiries and retry the - * 36 byte inquiry */ - printk(KERN_INFO "scsi scan: %d byte inquiry failed" - " with code %d. Consider BLIST_INQUIRY_36 for" - " this device\n", possible_inq_resp_len, - sreq->sr_result); - *bflags = BLIST_INQUIRY_36; - goto repeat_inquiry; + *bflags = scsi_get_device_flags(sdev, &inq_result[8], + &inq_result[16]); + + /* When the first pass succeeds we gain information about + * what larger transfer lengths might work. */ + if (pass == 1) { + if (BLIST_INQUIRY_36 & *bflags) + next_inquiry_len = 36; + else if (BLIST_INQUIRY_58 & *bflags) + next_inquiry_len = 58; + else if (sdev->inquiry_len) + next_inquiry_len = sdev->inquiry_len; + else + next_inquiry_len = response_len; + + /* If more data is available perform the second pass */ + if (next_inquiry_len > try_inquiry_len) { + try_inquiry_len = next_inquiry_len; + pass = 2; + goto next_pass; + } } - /* - * The INQUIRY can change, this means the length can change. - */ - possible_inq_resp_len = (unsigned char) inq_result[4] + 5; - if (BLIST_INQUIRY_58 & *bflags) - possible_inq_resp_len = 58; - else if (possible_inq_resp_len > 255) - possible_inq_resp_len = 36; /* sanity */ + } else if (pass == 2) { + printk(KERN_INFO "scsi scan: %d byte inquiry failed. " + "Consider BLIST_INQUIRY_36 for this device\n", + try_inquiry_len); + + /* If this pass failed, the third pass goes back and transfers + * the same amount as we successfully got in the first pass. */ + try_inquiry_len = first_inquiry_len; + pass = 3; + goto next_pass; } - sdev->inquiry_len = possible_inq_resp_len; + /* If the last transfer attempt got an error, assume the + * peripheral doesn't exist or is dead. */ + if (sreq->sr_result) + return; + + /* Don't report any more data than the device says is valid */ + sdev->inquiry_len = min(try_inquiry_len, response_len); /* * XXX Abort if the response length is less than 36? If less than @@ -498,10 +480,6 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, **/ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) { - struct scsi_device *sdev_sibling; - struct scsi_target *starget; - unsigned long flags; - /* * XXX do not save the inquiry, since it can change underneath us, * save just vendor/model/rev. @@ -531,7 +509,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) */ inq_result[0] = TYPE_ROM; inq_result[1] |= 0x80; /* removable */ - } + } else if (*bflags & BLIST_NO_ULD_ATTACH) + sdev->no_uld_attach = 1; switch (sdev->type = (inq_result[0] & 0x1f)) { case TYPE_TAPE: @@ -603,6 +582,13 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if ((*bflags & BLIST_BORKEN) == 0) sdev->borken = 0; + /* + * Apparently some really broken devices (contrary to the SCSI + * standards) need to be selected without asserting ATN + */ + if (*bflags & BLIST_SELECT_NO_ATN) + sdev->select_no_atn = 1; + /* * Some devices may not want to have a start command automatically * issued when a device is added. @@ -610,40 +596,9 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if (*bflags & BLIST_NOSTARTONADD) sdev->no_start_on_add = 1; - /* - * If we need to allow I/O to only one of the luns attached to - * this target id at a time set single_lun, and allocate or modify - * sdev_target. - */ - if (*bflags & BLIST_SINGLELUN) { + if (*bflags & BLIST_SINGLELUN) sdev->single_lun = 1; - spin_lock_irqsave(sdev->host->host_lock, flags); - starget = NULL; - /* - * Search for an existing target for this sdev. - */ - list_for_each_entry(sdev_sibling, &sdev->same_target_siblings, - same_target_siblings) { - if (sdev_sibling->sdev_target != NULL) { - starget = sdev_sibling->sdev_target; - break; - } - } - if (!starget) { - starget = kmalloc(sizeof(*starget), GFP_ATOMIC); - if (!starget) { - printk(ALLOC_FAILURE_MSG, __FUNCTION__); - spin_unlock_irqrestore(sdev->host->host_lock, - flags); - return SCSI_SCAN_NO_RESPONSE; - } - starget->starget_refcnt = 0; - starget->starget_sdev_user = NULL; - } - starget->starget_refcnt++; - sdev->sdev_target = starget; - spin_unlock_irqrestore(sdev->host->host_lock, flags); - } + sdev->use_10_for_rw = 1; @@ -666,7 +621,10 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) if (*bflags & BLIST_NOT_LOCKABLE) sdev->lockable = 0; - if(sdev->host->hostt->slave_configure) + if (sdev->host->transportt->device_configure) + sdev->host->transportt->device_configure(sdev); + + if (sdev->host->hostt->slave_configure) sdev->host->hostt->slave_configure(sdev); /* @@ -697,7 +655,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) **/ static int scsi_probe_and_add_lun(struct Scsi_Host *host, uint channel, uint id, uint lun, int *bflagsp, - struct scsi_device **sdevp, int rescan) + struct scsi_device **sdevp, int rescan, void *hostdata) { struct scsi_device *sdev; struct scsi_request *sreq; @@ -726,7 +684,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, } } - sdev = scsi_alloc_sdev(host, channel, id, lun); + sdev = scsi_alloc_sdev(host, channel, id, lun, hostdata); if (!sdev) goto out; sreq = scsi_allocate_request(sdev, GFP_ATOMIC); @@ -783,8 +741,6 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, } else { if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } out: @@ -874,7 +830,7 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel, */ for (lun = 1; lun < max_dev_lun; ++lun) if ((scsi_probe_and_add_lun(shost, channel, id, lun, - NULL, NULL, rescan) != SCSI_SCAN_LUN_PRESENT) && + NULL, NULL, rescan, NULL) != SCSI_SCAN_LUN_PRESENT) && !sparse_lun) return; } @@ -1085,7 +1041,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, int res; res = scsi_probe_and_add_lun(sdev->host, sdev->channel, - sdev->id, lun, NULL, NULL, rescan); + sdev->id, lun, NULL, NULL, rescan, NULL); if (res == SCSI_SCAN_NO_RESPONSE) { /* * Got some results, but now none, abort. @@ -1111,14 +1067,15 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, return 0; } -struct scsi_device *scsi_add_device(struct Scsi_Host *shost, - uint channel, uint id, uint lun) +struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, + uint id, uint lun, void *hostdata) { struct scsi_device *sdev; int res; down(&shost->scan_mutex); - res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1); + res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, + &sdev, 1, hostdata); if (res != SCSI_SCAN_LUN_PRESENT) sdev = ERR_PTR(-ENODEV); up(&shost->scan_mutex); @@ -1178,7 +1135,7 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, * Scan for a specific host/chan/id/lun. */ scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL, - rescan); + rescan, NULL); return; } @@ -1187,7 +1144,7 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, * would not configure LUN 0 until all LUNs are scanned. */ res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev, - rescan); + rescan, NULL); if (res == SCSI_SCAN_LUN_PRESENT) { if (scsi_report_lun_scan(sdev, bflags, rescan) != 0) /* @@ -1316,7 +1273,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) { struct scsi_device *sdev; - sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0); + sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0, NULL); if (sdev) { sdev->borken = 0; } @@ -1342,7 +1299,5 @@ void scsi_free_host_dev(struct scsi_device *sdev) if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); } diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c index 9da2db4ee..37231932e 100644 --- a/drivers/scsi/scsi_syms.c +++ b/drivers/scsi/scsi_syms.c @@ -69,11 +69,9 @@ EXPORT_SYMBOL(scsi_track_queue_full); EXPORT_SYMBOL(scsi_get_host_dev); EXPORT_SYMBOL(scsi_free_host_dev); -EXPORT_SYMBOL(scsi_sleep); - EXPORT_SYMBOL(scsi_io_completion); -EXPORT_SYMBOL(scsi_add_device); +EXPORT_SYMBOL(__scsi_add_device); EXPORT_SYMBOL(scsi_remove_device); EXPORT_SYMBOL(scsi_device_cancel); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a8855d324..79e47aacf 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -30,6 +30,7 @@ static struct { { SDEV_DEL, "deleted" }, { SDEV_QUIESCE, "quiesce" }, { SDEV_OFFLINE, "offline" }, + { SDEV_BLOCK, "blocked" }, }; const char *scsi_device_state_name(enum scsi_device_state state) @@ -153,25 +154,36 @@ void scsi_device_dev_release(struct device *dev) struct scsi_device *sdev; struct device *parent; unsigned long flags; + int delete; parent = dev->parent; sdev = to_scsi_device(dev); spin_lock_irqsave(sdev->host->host_lock, flags); + /* If we're the last LUN on the target, destroy the target */ + delete = list_empty(&sdev->same_target_siblings); list_del(&sdev->siblings); list_del(&sdev->same_target_siblings); list_del(&sdev->starved_entry); - if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0) - kfree(sdev->sdev_target); spin_unlock_irqrestore(sdev->host->host_lock, flags); + if (delete) { + struct scsi_target *starget = to_scsi_target(parent); + if (!starget->create) { + device_del(parent); + if (starget->transport_classdev.class) + class_device_unregister(&starget->transport_classdev); + } + put_device(parent); + } if (sdev->request_queue) scsi_free_queue(sdev->request_queue); kfree(sdev->inquiry); kfree(sdev); - put_device(parent); + if (parent) + put_device(parent); } struct class sdev_class = { @@ -183,6 +195,8 @@ struct class sdev_class = { static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) { struct scsi_device *sdp = to_scsi_device(dev); + if (sdp->no_uld_attach) + return 0; return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } @@ -430,6 +444,14 @@ static int attr_add(struct device *dev, struct device_attribute *attr) return device_create_file(dev, attr); } +static void scsi_target_dev_release(struct device *dev) +{ + struct scsi_target *starget = to_scsi_target(dev); + struct device *parent = dev->parent; + kfree(starget); + put_device(parent); +} + /** * scsi_sysfs_add_sdev - add scsi device to sysfs * @sdev: scsi_device to add @@ -440,13 +462,55 @@ static int attr_add(struct device *dev, struct device_attribute *attr) int scsi_sysfs_add_sdev(struct scsi_device *sdev) { struct class_device_attribute **attrs; - int error, i; + struct scsi_target *starget = sdev->sdev_target; + struct Scsi_Host *shost = sdev->host; + int error, i, create; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + create = starget->create; + starget->create = 0; + spin_unlock_irqrestore(shost->host_lock, flags); + + if (create) { + error = device_add(&starget->dev); + if (error) { + printk(KERN_ERR "Target device_add failed\n"); + return error; + } + if (starget->transport_classdev.class) { + int i; + struct class_device_attribute **attrs = + sdev->host->transportt->target_attrs; + + error = class_device_add(&starget->transport_classdev); + if (error) { + dev_printk(KERN_ERR, &starget->dev, + "Target transport add failed\n"); + return error; + } + + /* take a reference for the transport_classdev; this + * is released by the transport_class .release */ + get_device(&starget->dev); + for (i = 0; attrs[i]; i++) { + error = class_device_create_file(&starget->transport_classdev, + attrs[i]); + if (error) { + dev_printk(KERN_ERR, &starget->dev, + "Target transport attr add failed\n"); + return error; + } + } + } + } if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) return error; error = device_add(&sdev->sdev_gendev); if (error) { + put_device(sdev->sdev_gendev.parent); printk(KERN_INFO "error 1\n"); return error; } @@ -459,7 +523,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) /* take a reference for the sdev_classdev; this is * released by the sdev_class .release */ get_device(&sdev->sdev_gendev); - if (sdev->transport_classdev.class) { error = class_device_add(&sdev->transport_classdev); if (error) @@ -494,7 +557,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) } if (sdev->transport_classdev.class) { - attrs = sdev->host->transportt->attrs; + attrs = sdev->host->transportt->device_attrs; for (i = 0; attrs[i]; i++) { error = class_device_create_file(&sdev->transport_classdev, attrs[i]); @@ -525,8 +588,11 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) **/ void scsi_remove_device(struct scsi_device *sdev) { + struct Scsi_Host *shost = sdev->host; + + down(&shost->scan_mutex); if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) - return; + goto out; class_device_unregister(&sdev->sdev_classdev); if (sdev->transport_classdev.class) @@ -535,9 +601,10 @@ void scsi_remove_device(struct scsi_device *sdev) scsi_device_set_state(sdev, SDEV_DEL); if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); - if (sdev->host->transportt->cleanup) - sdev->host->transportt->cleanup(sdev); put_device(&sdev->sdev_gendev); + +out: + up(&shost->scan_mutex); } int scsi_register_driver(struct device_driver *drv) @@ -620,6 +687,121 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost) } } + class_device_initialize(&shost->transport_classdev); + shost->transport_classdev.class = shost->transportt->host_class; + shost->transport_classdev.dev = &shost->shost_gendev; + snprintf(shost->transport_classdev.class_id, BUS_ID_SIZE, + "host%d", shost->host_no); + + if (shost->transport_classdev.class) { + struct class_device_attribute **attrs = + shost->transportt->host_attrs; + error = class_device_add(&shost->transport_classdev); + if (error) + return error; + /* take a reference for the transport_classdev; this + * is released by the transport_class .release */ + get_device(&shost->shost_gendev); + for (i = 0; attrs[i]; i++) { + error = class_device_create_file(&shost->transport_classdev, + attrs[i]); + if (error) + return error; + } + } + + return 0; +} + +int scsi_sysfs_device_initialize(struct scsi_device *sdev) +{ + device_initialize(&sdev->sdev_gendev); + sdev->sdev_gendev.bus = &scsi_bus_type; + sdev->sdev_gendev.release = scsi_device_dev_release; + sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", + sdev->host->host_no, sdev->channel, sdev->id, + sdev->lun); + + class_device_initialize(&sdev->sdev_classdev); + sdev->sdev_classdev.dev = &sdev->sdev_gendev; + sdev->sdev_classdev.class = &sdev_class; + snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + + class_device_initialize(&sdev->transport_classdev); + sdev->transport_classdev.dev = &sdev->sdev_gendev; + sdev->transport_classdev.class = sdev->host->transportt->device_class; + snprintf(sdev->transport_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + return 0; +} + +int scsi_sysfs_target_initialize(struct scsi_device *sdev) +{ + struct scsi_target *starget = NULL; + struct Scsi_Host *shost = sdev->host; + struct scsi_device *device; + struct device *dev = NULL; + unsigned long flags; + int create = 0; + + spin_lock_irqsave(shost->host_lock, flags); + /* + * Search for an existing target for this sdev. + */ + list_for_each_entry(device, &shost->__devices, siblings) { + if (device->id == sdev->id && + device->channel == sdev->channel) { + list_add_tail(&sdev->same_target_siblings, + &device->same_target_siblings); + sdev->scsi_level = device->scsi_level; + starget = device->sdev_target; + break; + } + } + + if (!starget) { + const int size = sizeof(*starget) + + shost->transportt->target_size; + starget = kmalloc(size, GFP_ATOMIC); + if (!starget) { + printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); + spin_unlock_irqrestore(shost->host_lock, + flags); + return -ENOMEM; + } + memset(starget, 0, size); + dev = &starget->dev; + device_initialize(dev); + dev->parent = get_device(&shost->shost_gendev); + dev->release = scsi_target_dev_release; + sprintf(dev->bus_id, "target%d:%d:%d", + shost->host_no, sdev->channel, sdev->id); + class_device_initialize(&starget->transport_classdev); + starget->transport_classdev.dev = &starget->dev; + starget->transport_classdev.class = shost->transportt->target_class; + snprintf(starget->transport_classdev.class_id, BUS_ID_SIZE, + "target%d:%d:%d", + shost->host_no, sdev->channel, sdev->id); + starget->id = sdev->id; + starget->channel = sdev->channel; + create = starget->create = 1; + /* + * If there wasn't another lun already configured at + * this target, then default this device to SCSI_2 + * until we know better + */ + sdev->scsi_level = SCSI_2; + } + get_device(&starget->dev); + sdev->sdev_gendev.parent = &starget->dev; + sdev->sdev_target = starget; + list_add_tail(&sdev->siblings, &shost->__devices); + spin_unlock_irqrestore(shost->host_lock, flags); + if (create && shost->transportt->target_setup) + shost->transportt->target_setup(starget); return 0; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 3480d4941..40b415c00 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -23,23 +23,31 @@ #include #include #include +#include "scsi_priv.h" #define FC_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a) static void transport_class_release(struct class_device *class_dev); +static void host_class_release(struct class_device *class_dev); -#define FC_NUM_ATTRS 3 /* increase this if you add attributes */ -#define FC_OTHER_ATTRS 0 /* increase this if you add "always on" - * attributes */ +#define FC_STARGET_NUM_ATTRS 4 /* increase this if you add attributes */ +#define FC_STARGET_OTHER_ATTRS 0 /* increase this if you add "always on" + * attributes */ +#define FC_HOST_NUM_ATTRS 1 struct fc_internal { struct scsi_transport_template t; struct fc_function_template *f; /* The actual attributes */ - struct class_device_attribute private_attrs[FC_NUM_ATTRS]; + struct class_device_attribute private_starget_attrs[ + FC_STARGET_NUM_ATTRS]; /* The array of null terminated pointers to attributes * needed by scsi_sysfs.c */ - struct class_device_attribute *attrs[FC_NUM_ATTRS + FC_OTHER_ATTRS + 1]; + struct class_device_attribute *starget_attrs[ + FC_STARGET_NUM_ATTRS + FC_STARGET_OTHER_ATTRS + 1]; + + struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS]; + struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1]; }; #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) @@ -49,101 +57,211 @@ struct class fc_transport_class = { .release = transport_class_release, }; +struct class fc_host_class = { + .name = "fc_host", + .release = host_class_release, +}; + static __init int fc_transport_init(void) { + int error = class_register(&fc_host_class); + if (error) + return error; return class_register(&fc_transport_class); } static void __exit fc_transport_exit(void) { class_unregister(&fc_transport_class); + class_unregister(&fc_host_class); } -static int fc_setup_transport_attrs(struct scsi_device *sdev) +static int fc_setup_starget_transport_attrs(struct scsi_target *starget) { - /* I'm not sure what values are invalid. We should pick some invalid - * values for the defaults */ - fc_node_name(sdev) = -1; - fc_port_name(sdev) = -1; - fc_port_id(sdev) = -1; + /* + * Set default values easily detected by the midlayer as + * failure cases. The scsi lldd is responsible for initializing + * all transport attributes to valid values per target. + */ + fc_starget_node_name(starget) = -1; + fc_starget_port_name(starget) = -1; + fc_starget_port_id(starget) = -1; + fc_starget_dev_loss_tmo(starget) = -1; + init_timer(&fc_starget_dev_loss_timer(starget)); + return 0; +} +static int fc_setup_host_transport_attrs(struct Scsi_Host *shost) +{ + /* + * Set default values easily detected by the midlayer as + * failure cases. The scsi lldd is responsible for initializing + * all transport attributes to valid values per host. + */ + fc_host_link_down_tmo(shost) = -1; + init_timer(&fc_host_link_down_timer(shost)); return 0; } static void transport_class_release(struct class_device *class_dev) { - struct scsi_device *sdev = transport_class_to_sdev(class_dev); - put_device(&sdev->sdev_gendev); + struct scsi_target *starget = transport_class_to_starget(class_dev); + put_device(&starget->dev); } -#define fc_transport_show_function(field, format_string, cast) \ - \ +static void host_class_release(struct class_device *class_dev) +{ + struct Scsi_Host *shost = transport_class_to_shost(class_dev); + put_device(&shost->shost_gendev); +} + + +/* + * Remote Port Attribute Management + */ + +#define fc_starget_show_function(field, format_string, cast) \ static ssize_t \ -show_fc_transport_##field (struct class_device *cdev, char *buf) \ +show_fc_starget_##field (struct class_device *cdev, char *buf) \ { \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ - struct fc_transport_attrs *tp; \ - struct fc_internal *i = to_fc_internal(sdev->host->transportt); \ - tp = (struct fc_transport_attrs *)&sdev->transport_data; \ - if (i->f->get_##field) \ - i->f->get_##field(sdev); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ + struct fc_starget_attrs *tp; \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + tp = (struct fc_starget_attrs *)&starget->starget_data; \ + if (i->f->get_starget_##field) \ + i->f->get_starget_##field(starget); \ return snprintf(buf, 20, format_string, cast tp->field); \ } -#define fc_transport_store_function(field, format_string) \ +#define fc_starget_store_function(field, format_string) \ static ssize_t \ -store_fc_transport_##field(struct class_device *cdev, const char *buf, \ +store_fc_starget_##field(struct class_device *cdev, const char *buf, \ size_t count) \ { \ int val; \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ - struct fc_internal *i = to_fc_internal(sdev->host->transportt); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ \ val = simple_strtoul(buf, NULL, 0); \ - i->f->set_##field(sdev, val); \ + i->f->set_starget_##field(starget, val); \ return count; \ } -#define fc_transport_rd_attr(field, format_string) \ - fc_transport_show_function(field, format_string, ) \ +#define fc_starget_rd_attr(field, format_string) \ + fc_starget_show_function(field, format_string, ) \ static CLASS_DEVICE_ATTR(field, S_IRUGO, \ - show_fc_transport_##field, NULL) + show_fc_starget_##field, NULL) -#define fc_transport_rd_attr_cast(field, format_string, cast) \ - fc_transport_show_function(field, format_string, (cast)) \ -static CLASS_DEVICE_ATTR( field, S_IRUGO, \ - show_fc_transport_##field, NULL) +#define fc_starget_rd_attr_cast(field, format_string, cast) \ + fc_starget_show_function(field, format_string, (cast)) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO, \ + show_fc_starget_##field, NULL) -#define fc_transport_rw_attr(field, format_string) \ - fc_transport_show_function(field, format_string, ) \ - fc_transport_store_function(field, format_string) \ +#define fc_starget_rw_attr(field, format_string) \ + fc_starget_show_function(field, format_string, ) \ + fc_starget_store_function(field, format_string) \ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \ - show_fc_transport_##field, \ - store_fc_transport_##field) - -/* the FiberChannel Tranport Attributes: */ -fc_transport_rd_attr_cast(node_name, "0x%llx\n", unsigned long long); -fc_transport_rd_attr_cast(port_name, "0x%llx\n", unsigned long long); -fc_transport_rd_attr(port_id, "0x%06x\n"); - -#define SETUP_ATTRIBUTE_RD(field) \ - i->private_attrs[count] = class_device_attr_##field; \ - i->private_attrs[count].attr.mode = S_IRUGO; \ - i->private_attrs[count].store = NULL; \ - i->attrs[count] = &i->private_attrs[count]; \ - if (i->f->show_##field) \ + show_fc_starget_##field, \ + store_fc_starget_##field) + +#define SETUP_STARGET_ATTRIBUTE_RD(field) \ + i->private_starget_attrs[count] = class_device_attr_##field; \ + i->private_starget_attrs[count].attr.mode = S_IRUGO; \ + i->private_starget_attrs[count].store = NULL; \ + i->starget_attrs[count] = &i->private_starget_attrs[count]; \ + if (i->f->show_starget_##field) \ + count++ + +#define SETUP_STARGET_ATTRIBUTE_RW(field) \ + i->private_starget_attrs[count] = class_device_attr_##field; \ + if (!i->f->set_starget_##field) { \ + i->private_starget_attrs[count].attr.mode = S_IRUGO; \ + i->private_starget_attrs[count].store = NULL; \ + } \ + i->starget_attrs[count] = &i->private_starget_attrs[count]; \ + if (i->f->show_starget_##field) \ + count++ + +/* The FC Tranport Remote Port (Target) Attributes: */ +fc_starget_rd_attr_cast(node_name, "0x%llx\n", unsigned long long); +fc_starget_rd_attr_cast(port_name, "0x%llx\n", unsigned long long); +fc_starget_rd_attr(port_id, "0x%06x\n"); +fc_starget_rw_attr(dev_loss_tmo, "%d\n"); + + +/* + * Host Attribute Management + */ + +#define fc_host_show_function(field, format_string, cast) \ +static ssize_t \ +show_fc_host_##field (struct class_device *cdev, char *buf) \ +{ \ + struct Scsi_Host *shost = transport_class_to_shost(cdev); \ + struct fc_host_attrs *tp; \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + tp = (struct fc_host_attrs *)shost->shost_data; \ + if (i->f->get_host_##field) \ + i->f->get_host_##field(shost); \ + return snprintf(buf, 20, format_string, cast tp->field); \ +} + +#define fc_host_store_function(field, format_string) \ +static ssize_t \ +store_fc_host_##field(struct class_device *cdev, const char *buf, \ + size_t count) \ +{ \ + int val; \ + struct Scsi_Host *shost = transport_class_to_shost(cdev); \ + struct fc_internal *i = to_fc_internal(shost->transportt); \ + \ + val = simple_strtoul(buf, NULL, 0); \ + i->f->set_host_##field(shost, val); \ + return count; \ +} + +#define fc_host_rd_attr(field, format_string) \ + fc_host_show_function(field, format_string, ) \ +static CLASS_DEVICE_ATTR(host_##field, S_IRUGO, \ + show_fc_host_##field, NULL) + +#define fc_host_rd_attr_cast(field, format_string, cast) \ + fc_host_show_function(field, format_string, (cast)) \ +static CLASS_DEVICE_ATTR(host_##field, S_IRUGO, \ + show_fc_host_##field, NULL) + +#define fc_host_rw_attr(field, format_string) \ + fc_host_show_function(field, format_string, ) \ + fc_host_store_function(field, format_string) \ +static CLASS_DEVICE_ATTR(host_##field, S_IRUGO | S_IWUSR, \ + show_fc_host_##field, \ + store_fc_host_##field) + +#define SETUP_HOST_ATTRIBUTE_RD(field) \ + i->private_host_attrs[count] = class_device_attr_host_##field; \ + i->private_host_attrs[count].attr.mode = S_IRUGO; \ + i->private_host_attrs[count].store = NULL; \ + i->host_attrs[count] = &i->private_host_attrs[count]; \ + if (i->f->show_host_##field) \ count++ -#define SETUP_ATTRIBUTE_RW(field) \ - i->private_attrs[count] = class_device_attr_##field; \ - if (!i->f->set_##field) { \ - i->private_attrs[count].attr.mode = S_IRUGO; \ - i->private_attrs[count].store = NULL; \ - } \ - i->attrs[count] = &i->private_attrs[count]; \ - if (i->f->show_##field) \ +#define SETUP_HOST_ATTRIBUTE_RW(field) \ + i->private_host_attrs[count] = class_device_attr_host_##field; \ + if (!i->f->set_host_##field) { \ + i->private_host_attrs[count].attr.mode = S_IRUGO; \ + i->private_host_attrs[count].store = NULL; \ + } \ + i->host_attrs[count] = &i->private_host_attrs[count]; \ + if (i->f->show_host_##field) \ count++ +/* The FC Tranport Host Attributes: */ +fc_host_rw_attr(link_down_tmo, "%d\n"); + + + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -156,21 +274,43 @@ fc_attach_transport(struct fc_function_template *ft) memset(i, 0, sizeof(struct fc_internal)); - i->t.attrs = &i->attrs[0]; - i->t.class = &fc_transport_class; - i->t.setup = &fc_setup_transport_attrs; - i->t.size = sizeof(struct fc_transport_attrs); + i->t.target_attrs = &i->starget_attrs[0]; + i->t.target_class = &fc_transport_class; + i->t.target_setup = &fc_setup_starget_transport_attrs; + i->t.target_size = sizeof(struct fc_starget_attrs); + + i->t.host_attrs = &i->host_attrs[0]; + i->t.host_class = &fc_host_class; + i->t.host_setup = &fc_setup_host_transport_attrs; + i->t.host_size = sizeof(struct fc_host_attrs); i->f = ft; - SETUP_ATTRIBUTE_RD(port_id); - SETUP_ATTRIBUTE_RD(port_name); - SETUP_ATTRIBUTE_RD(node_name); + + /* + * setup remote port (target) attributes + */ + SETUP_STARGET_ATTRIBUTE_RD(port_id); + SETUP_STARGET_ATTRIBUTE_RD(port_name); + SETUP_STARGET_ATTRIBUTE_RD(node_name); + SETUP_STARGET_ATTRIBUTE_RW(dev_loss_tmo); + + BUG_ON(count > FC_STARGET_NUM_ATTRS); + + /* Setup the always-on attributes here */ + + i->starget_attrs[count] = NULL; + - BUG_ON(count > FC_NUM_ATTRS); + /* setup host attributes */ + count=0; + SETUP_HOST_ATTRIBUTE_RW(link_down_tmo); + + BUG_ON(count > FC_HOST_NUM_ATTRS); /* Setup the always-on attributes here */ - i->attrs[count] = NULL; + i->host_attrs[count] = NULL; + return &i->t; } @@ -185,6 +325,204 @@ void fc_release_transport(struct scsi_transport_template *t) EXPORT_SYMBOL(fc_release_transport); + +/** + * fc_device_block - called by target functions to block a scsi device + * @dev: scsi device + * @data: unused + **/ +static int fc_device_block(struct device *dev, void *data) +{ + scsi_internal_device_block(to_scsi_device(dev)); + return 0; +} + +/** + * fc_device_unblock - called by target functions to unblock a scsi device + * @dev: scsi device + * @data: unused + **/ +static int fc_device_unblock(struct device *dev, void *data) +{ + scsi_internal_device_unblock(to_scsi_device(dev)); + return 0; +} + +/** + * fc_timeout_blocked_tgt - Timeout handler for blocked scsi targets + * that fail to recover in the alloted time. + * @data: scsi target that failed to reappear in the alloted time. + **/ +static void fc_timeout_blocked_tgt(unsigned long data) +{ + struct scsi_target *starget = (struct scsi_target *)data; + + dev_printk(KERN_ERR, &starget->dev, + "blocked target time out: target resuming\n"); + + /* + * set the device going again ... if the scsi lld didn't + * unblock this device, then IO errors will probably + * result if the host still isn't ready. + */ + device_for_each_child(&starget->dev, NULL, fc_device_unblock); +} + +/** + * fc_target_block - block a target by temporarily putting all its scsi devices + * into the SDEV_BLOCK state. + * @starget: scsi target managed by this fc scsi lldd. + * + * scsi lldd's with a FC transport call this routine to temporarily stop all + * scsi commands to all devices managed by this scsi target. Called + * from interrupt or normal process context. + * + * Returns zero if successful or error if not + * + * Notes: + * The timeout and timer types are extracted from the fc transport + * attributes from the caller's target pointer. This routine assumes no + * locks are held on entry. + **/ +int +fc_target_block(struct scsi_target *starget) +{ + int timeout = fc_starget_dev_loss_tmo(starget); + struct timer_list *timer = &fc_starget_dev_loss_timer(starget); + + if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) + return -EINVAL; + + device_for_each_child(&starget->dev, NULL, fc_device_block); + + /* The scsi lld blocks this target for the timeout period only. */ + timer->data = (unsigned long)starget; + timer->expires = jiffies + timeout * HZ; + timer->function = fc_timeout_blocked_tgt; + add_timer(timer); + + return 0; +} +EXPORT_SYMBOL(fc_target_block); + +/** + * fc_target_unblock - unblock a target following a fc_target_block request. + * @starget: scsi target managed by this fc scsi lldd. + * + * scsi lld's with a FC transport call this routine to restart IO to all + * devices associated with the caller's scsi target following a fc_target_block + * request. Called from interrupt or normal process context. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +void +fc_target_unblock(struct scsi_target *starget) +{ + /* + * Stop the target timer first. Take no action on the del_timer + * failure as the state machine state change will validate the + * transaction. + */ + del_timer_sync(&fc_starget_dev_loss_timer(starget)); + + device_for_each_child(&starget->dev, NULL, fc_device_unblock); +} +EXPORT_SYMBOL(fc_target_unblock); + +/** + * fc_timeout_blocked_host - Timeout handler for blocked scsi hosts + * that fail to recover in the alloted time. + * @data: scsi host that failed to recover its devices in the alloted + * time. + **/ +static void fc_timeout_blocked_host(unsigned long data) +{ + struct Scsi_Host *shost = (struct Scsi_Host *)data; + struct scsi_device *sdev; + + dev_printk(KERN_ERR, &shost->shost_gendev, + "blocked host time out: host resuming\n"); + + shost_for_each_device(sdev, shost) { + /* + * set the device going again ... if the scsi lld didn't + * unblock this device, then IO errors will probably + * result if the host still isn't ready. + */ + scsi_internal_device_unblock(sdev); + } +} + +/** + * fc_host_block - block all scsi devices managed by the calling host temporarily + * by putting each device in the SDEV_BLOCK state. + * @shost: scsi host pointer that contains all scsi device siblings. + * + * scsi lld's with a FC transport call this routine to temporarily stop all + * scsi commands to all devices managed by this host. Called + * from interrupt or normal process context. + * + * Returns zero if successful or error if not + * + * Notes: + * The timeout and timer types are extracted from the fc transport + * attributes from the caller's host pointer. This routine assumes no + * locks are held on entry. + **/ +int +fc_host_block(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + int timeout = fc_host_link_down_tmo(shost); + struct timer_list *timer = &fc_host_link_down_timer(shost); + + if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) + return -EINVAL; + + shost_for_each_device(sdev, shost) { + scsi_internal_device_block(sdev); + } + + /* The scsi lld blocks this host for the timeout period only. */ + timer->data = (unsigned long)shost; + timer->expires = jiffies + timeout * HZ; + timer->function = fc_timeout_blocked_host; + add_timer(timer); + + return 0; +} +EXPORT_SYMBOL(fc_host_block); + +/** + * fc_host_unblock - unblock all devices managed by this host following a + * fc_host_block request. + * @shost: scsi host containing all scsi device siblings to unblock. + * + * scsi lld's with a FC transport call this routine to restart IO to all scsi + * devices managed by the specified scsi host following an fc_host_block + * request. Called from interrupt or normal process context. + * + * Notes: + * This routine assumes no locks are held on entry. + **/ +void +fc_host_unblock(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + + /* + * Stop the host timer first. Take no action on the del_timer + * failure as the state machine state change will validate the + * transaction. + */ + del_timer_sync(&fc_host_link_down_timer(shost)); + shost_for_each_device(sdev, shost) { + scsi_internal_device_unblock(sdev); + } +} +EXPORT_SYMBOL(fc_host_unblock); + MODULE_AUTHOR("Martin Hicks"); MODULE_DESCRIPTION("FC Transport Attributes"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 9c41eefb9..f01133b4c 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -27,25 +27,28 @@ #include #include #include +#include "scsi_priv.h" #include #include #include #include #include -#define SPI_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a) +#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a) static void transport_class_release(struct class_device *class_dev); +static void host_class_release(struct class_device *class_dev); #define SPI_NUM_ATTRS 10 /* increase this if you add attributes */ #define SPI_OTHER_ATTRS 1 /* Increase this if you add "always * on" attributes */ +#define SPI_HOST_ATTRS 1 #define SPI_MAX_ECHO_BUFFER_SIZE 4096 /* Private data accessors (keep these out of the header file) */ -#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dv_pending) -#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->transport_data)->dv_sem) +#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) +#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) struct spi_internal { struct scsi_transport_template t; @@ -55,6 +58,8 @@ struct spi_internal { /* The array of null terminated pointers to attributes * needed by scsi_sysfs.c */ struct class_device_attribute *attrs[SPI_NUM_ATTRS + SPI_OTHER_ATTRS + 1]; + struct class_device_attribute private_host_attrs[SPI_HOST_ATTRS]; + struct class_device_attribute *host_attrs[SPI_HOST_ATTRS + 1]; }; #define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t) @@ -80,43 +85,117 @@ static const char *const ppr_to_ns[] = { * by 4 */ #define SPI_STATIC_PPR 0x0c +static struct { + enum spi_signal_type value; + char *name; +} signal_types[] = { + { SPI_SIGNAL_UNKNOWN, "unknown" }, + { SPI_SIGNAL_SE, "SE" }, + { SPI_SIGNAL_LVD, "LVD" }, + { SPI_SIGNAL_HVD, "HVD" }, +}; + +static inline const char *spi_signal_to_string(enum spi_signal_type type) +{ + int i; + + for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + if (type == signal_types[i].value) + return signal_types[i].name; + } + return NULL; +} +static inline enum spi_signal_type spi_signal_to_value(const char *name) +{ + int i, len; + + for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + len = strlen(signal_types[i].name); + if (strncmp(name, signal_types[i].name, len) == 0 && + (name[len] == '\n' || name[len] == '\0')) + return signal_types[i].value; + } + return SPI_SIGNAL_UNKNOWN; +} + + struct class spi_transport_class = { .name = "spi_transport", .release = transport_class_release, }; +struct class spi_host_class = { + .name = "spi_host", + .release = host_class_release, +}; + static __init int spi_transport_init(void) { + int error = class_register(&spi_host_class); + if (error) + return error; return class_register(&spi_transport_class); } static void __exit spi_transport_exit(void) { class_unregister(&spi_transport_class); + class_unregister(&spi_host_class); +} + +static int spi_setup_host_attrs(struct Scsi_Host *shost) +{ + spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; + + return 0; +} + +static int spi_configure_device(struct scsi_device *sdev) +{ + struct scsi_target *starget = sdev->sdev_target; + + /* Populate the target capability fields with the values + * gleaned from the device inquiry */ + + spi_support_sync(starget) = scsi_device_sync(sdev); + spi_support_wide(starget) = scsi_device_wide(sdev); + spi_support_dt(starget) = scsi_device_dt(sdev); + spi_support_dt_only(starget) = scsi_device_dt_only(sdev); + spi_support_ius(starget) = scsi_device_ius(sdev); + spi_support_qas(starget) = scsi_device_qas(sdev); + + return 0; } -static int spi_setup_transport_attrs(struct scsi_device *sdev) +static int spi_setup_transport_attrs(struct scsi_target *starget) { - spi_period(sdev) = -1; /* illegal value */ - spi_offset(sdev) = 0; /* async */ - spi_width(sdev) = 0; /* narrow */ - spi_iu(sdev) = 0; /* no IU */ - spi_dt(sdev) = 0; /* ST */ - spi_qas(sdev) = 0; - spi_wr_flow(sdev) = 0; - spi_rd_strm(sdev) = 0; - spi_rti(sdev) = 0; - spi_pcomp_en(sdev) = 0; - spi_dv_pending(sdev) = 0; - init_MUTEX(&spi_dv_sem(sdev)); + spi_period(starget) = -1; /* illegal value */ + spi_offset(starget) = 0; /* async */ + spi_width(starget) = 0; /* narrow */ + spi_iu(starget) = 0; /* no IU */ + spi_dt(starget) = 0; /* ST */ + spi_qas(starget) = 0; + spi_wr_flow(starget) = 0; + spi_rd_strm(starget) = 0; + spi_rti(starget) = 0; + spi_pcomp_en(starget) = 0; + spi_dv_pending(starget) = 0; + spi_initial_dv(starget) = 0; + init_MUTEX(&spi_dv_sem(starget)); return 0; } static void transport_class_release(struct class_device *class_dev) { - struct scsi_device *sdev = transport_class_to_sdev(class_dev); - put_device(&sdev->sdev_gendev); + struct scsi_target *starget = transport_class_to_starget(class_dev); + put_device(&starget->dev); +} + +static void host_class_release(struct class_device *class_dev) +{ + struct Scsi_Host *shost = transport_class_to_shost(class_dev); + put_device(&shost->shost_gendev); } #define spi_transport_show_function(field, format_string) \ @@ -124,12 +203,13 @@ static void transport_class_release(struct class_device *class_dev) static ssize_t \ show_spi_transport_##field(struct class_device *cdev, char *buf) \ { \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ struct spi_transport_attrs *tp; \ - struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ - tp = (struct spi_transport_attrs *)&sdev->transport_data; \ + struct spi_internal *i = to_spi_internal(shost->transportt); \ + tp = (struct spi_transport_attrs *)&starget->starget_data; \ if (i->f->get_##field) \ - i->f->get_##field(sdev); \ + i->f->get_##field(starget); \ return snprintf(buf, 20, format_string, tp->field); \ } @@ -139,11 +219,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \ size_t count) \ { \ int val; \ - struct scsi_device *sdev = transport_class_to_sdev(cdev); \ - struct spi_internal *i = to_spi_internal(sdev->host->transportt); \ + struct scsi_target *starget = transport_class_to_starget(cdev); \ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \ + struct spi_internal *i = to_spi_internal(shost->transportt); \ \ val = simple_strtoul(buf, NULL, 0); \ - i->f->set_##field(sdev, val); \ + i->f->set_##field(starget, val); \ return count; \ } @@ -168,8 +249,13 @@ spi_transport_rd_attr(pcomp_en, "%d\n"); static ssize_t store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct scsi_target *starget = transport_class_to_starget(cdev); + /* FIXME: we're relying on an awful lot of device internals + * here. We really need a function to get the first available + * child */ + struct device *dev = container_of(starget->dev.children.next, struct device, node); + struct scsi_device *sdev = to_scsi_device(dev); spi_dv_device(sdev); return count; } @@ -180,15 +266,16 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct spi_transport_attrs *tp; const char *str; - struct spi_internal *i = to_spi_internal(sdev->host->transportt); + struct spi_internal *i = to_spi_internal(shost->transportt); - tp = (struct spi_transport_attrs *)&sdev->transport_data; + tp = (struct spi_transport_attrs *)&starget->starget_data; if (i->f->get_period) - i->f->get_period(sdev); + i->f->get_period(starget); switch(tp->period) { @@ -212,8 +299,9 @@ static ssize_t store_spi_transport_period(struct class_device *cdev, const char *buf, size_t count) { - struct scsi_device *sdev = transport_class_to_sdev(cdev); - struct spi_internal *i = to_spi_internal(sdev->host->transportt); + struct scsi_target *starget = transport_class_to_starget(cdev); + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct spi_internal *i = to_spi_internal(shost->transportt); int j, period = -1; for (j = 0; j < SPI_STATIC_PPR; j++) { @@ -246,7 +334,7 @@ store_spi_transport_period(struct class_device *cdev, const char *buf, if (period > 0xff) period = 0xff; - i->f->set_period(sdev, period); + i->f->set_period(starget, period); return count; } @@ -255,9 +343,35 @@ static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, show_spi_transport_period, store_spi_transport_period); +static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct spi_internal *i = to_spi_internal(shost->transportt); + + if (i->f->get_signalling) + i->f->get_signalling(shost); + + return sprintf(buf, "%s\n", spi_signal_to_string(spi_signalling(shost))); +} +static ssize_t store_spi_host_signalling(struct class_device *cdev, + const char *buf, size_t count) +{ + struct Scsi_Host *shost = transport_class_to_shost(cdev); + struct spi_internal *i = to_spi_internal(shost->transportt); + enum spi_signal_type type = spi_signal_to_value(buf); + + if (type != SPI_SIGNAL_UNKNOWN) + i->f->set_signalling(shost, type); + + return count; +} +static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR, + show_spi_host_signalling, + store_spi_host_signalling); + #define DV_SET(x, y) \ if(i->f->set_##x) \ - i->f->set_##x(sdev, y) + i->f->set_##x(sdev->sdev_target, y) #define DV_LOOPS 3 #define DV_TIMEOUT (10*HZ) @@ -325,7 +439,7 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, DV_TIMEOUT, DV_RETRIES); if(sreq->sr_result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); - SPI_PRINTK(sdev, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); return 0; } @@ -401,8 +515,8 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, /* OK, retrain, fallback */ if (i->f->get_period) - i->f->get_period(sdev); - newperiod = spi_period(sdev); + i->f->get_period(sdev->sdev_target); + newperiod = spi_period(sdev->sdev_target); period = newperiod > period ? newperiod : period; if (period < 0x0d) period++; @@ -411,11 +525,11 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, if (unlikely(period > 0xff || period == prevperiod)) { /* Total failure; set to async and return */ - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n"); DV_SET(offset, 0); return 0; } - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation detected failure, dropping back\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n"); DV_SET(period, period); prevperiod = period; } @@ -486,20 +600,20 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) DV_SET(width, 0); if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) { - SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); /* FIXME: should probably offline the device here? */ return; } /* test width */ if (i->f->set_width && sdev->wdtr) { - i->f->set_width(sdev, 1); + i->f->set_width(sdev->sdev_target, 1); if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer + len, DV_LOOPS)) { - SPI_PRINTK(sdev, KERN_ERR, "Wide Transfers Fail\n"); - i->f->set_width(sdev, 0); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n"); + i->f->set_width(sdev->sdev_target, 0); } } @@ -520,12 +634,16 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) /* OK, now we have our initial speed set by the read only inquiry * test, now try an echo buffer test (if the device allows it) */ - if ((len = spi_dv_device_get_echo_buffer(sreq, buffer)) == 0) { - SPI_PRINTK(sdev, KERN_INFO, "Domain Validation skipping write tests\n"); + len = 0; + if (sdev->ppr) + len = spi_dv_device_get_echo_buffer(sreq, buffer); + + if (len == 0) { + SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n"); return; } if (len > SPI_MAX_ECHO_BUFFER_SIZE) { - SPI_PRINTK(sdev, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); + SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE); len = SPI_MAX_ECHO_BUFFER_SIZE; } @@ -547,6 +665,7 @@ void spi_dv_device(struct scsi_device *sdev) { struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); + struct scsi_target *starget = sdev->sdev_target; u8 *buffer; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; @@ -563,22 +682,28 @@ spi_dv_device(struct scsi_device *sdev) memset(buffer, 0, len); + /* We need to verify that the actual device will quiesce; the + * later target quiesce is just a nice to have */ if (unlikely(scsi_device_quiesce(sdev))) goto out_free; - spi_dv_pending(sdev) = 1; - down(&spi_dv_sem(sdev)); + scsi_target_quiesce(starget); + + spi_dv_pending(starget) = 1; + down(&spi_dv_sem(starget)); - SPI_PRINTK(sdev, KERN_INFO, "Beginning Domain Validation\n"); + SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); spi_dv_device_internal(sreq, buffer); - SPI_PRINTK(sdev, KERN_INFO, "Ending Domain Validation\n"); + SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); + + up(&spi_dv_sem(starget)); + spi_dv_pending(starget) = 0; - up(&spi_dv_sem(sdev)); - spi_dv_pending(sdev) = 0; + scsi_target_resume(starget); - scsi_device_resume(sdev); + spi_initial_dv(starget) = 1; out_free: kfree(buffer); @@ -602,7 +727,7 @@ spi_dv_device_work_wrapper(void *data) kfree(wqw); spi_dv_device(sdev); - spi_dv_pending(sdev) = 0; + spi_dv_pending(sdev->sdev_target) = 0; scsi_device_put(sdev); } @@ -625,15 +750,15 @@ spi_schedule_dv_device(struct scsi_device *sdev) if (unlikely(!wqw)) return; - if (unlikely(spi_dv_pending(sdev))) { + if (unlikely(spi_dv_pending(sdev->sdev_target))) { kfree(wqw); return; } /* Set pending early (dv_device doesn't check it, only sets it) */ - spi_dv_pending(sdev) = 1; + spi_dv_pending(sdev->sdev_target) = 1; if (unlikely(scsi_device_get(sdev))) { kfree(wqw); - spi_dv_pending(sdev) = 0; + spi_dv_pending(sdev->sdev_target) = 0; return; } @@ -654,6 +779,15 @@ EXPORT_SYMBOL(spi_schedule_dv_device); if (i->f->show_##field) \ count++ +#define SETUP_HOST_ATTRIBUTE(field) \ + i->private_host_attrs[count] = class_device_attr_##field; \ + if (!i->f->set_##field) { \ + i->private_host_attrs[count].attr.mode = S_IRUGO; \ + i->private_host_attrs[count].store = NULL; \ + } \ + i->host_attrs[count] = &i->private_host_attrs[count]; \ + count++ + struct scsi_transport_template * spi_attach_transport(struct spi_function_template *ft) { @@ -666,10 +800,15 @@ spi_attach_transport(struct spi_function_template *ft) memset(i, 0, sizeof(struct spi_internal)); - i->t.attrs = &i->attrs[0]; - i->t.class = &spi_transport_class; - i->t.setup = &spi_setup_transport_attrs; - i->t.size = sizeof(struct spi_transport_attrs); + i->t.target_attrs = &i->attrs[0]; + i->t.target_class = &spi_transport_class; + i->t.target_setup = &spi_setup_transport_attrs; + i->t.device_configure = &spi_configure_device; + i->t.target_size = sizeof(struct spi_transport_attrs); + i->t.host_attrs = &i->host_attrs[0]; + i->t.host_class = &spi_host_class; + i->t.host_setup = &spi_setup_host_attrs; + i->t.host_size = sizeof(struct spi_host_attrs); i->f = ft; SETUP_ATTRIBUTE(period); @@ -691,6 +830,13 @@ spi_attach_transport(struct spi_function_template *ft) i->attrs[count] = NULL; + count = 0; + SETUP_HOST_ATTRIBUTE(signalling); + + BUG_ON(count > SPI_HOST_ATTRS); + + i->host_attrs[count] = NULL; + return &i->t; } EXPORT_SYMBOL(spi_attach_transport); diff --git a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c index 920a1b717..f7630f8dd 100644 --- a/drivers/scsi/scsicam.c +++ b/drivers/scsi/scsicam.c @@ -29,10 +29,11 @@ unsigned char *scsi_bios_ptable(struct block_device *dev) unsigned char *res = kmalloc(66, GFP_KERNEL); if (res) { struct block_device *bdev = dev->bd_contains; - struct buffer_head *bh = __bread(bdev, 0, block_size(bdev)); - if (bh) { - memcpy(res, bh->b_data + 0x1be, 66); - brelse(bh); + Sector sect; + void *data = read_dev_sector(bdev, 0, §); + if (data) { + memcpy(res, data + 0x1be, 66); + put_dev_sector(sect); } else { kfree(res); res = NULL; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8fd459060..0d10f1067 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -42,11 +42,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -62,12 +64,18 @@ #include "scsi_logging.h" - /* - * Remaining dev_t-handling stuff + * More than enough for everybody ;) The huge number of majors + * is a leftover from 16bit dev_t days, we don't really need that + * much numberspace. */ #define SD_MAJORS 16 -#define SD_DISKS 32768 /* anything between 256 and 262144 */ + +/* + * This is limited by the naming scheme enforced in sd_probe, + * add another character to it if you really need more disks. + */ +#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) /* * Time out in seconds for disks and Magneto-opticals (which are slower). @@ -96,8 +104,7 @@ struct scsi_disk { unsigned RCD : 1; /* state of disk RCD bit, unused */ }; - -static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG]; +static DEFINE_IDR(sd_index_idr); static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED; /* This semaphore is used to mediate the 0->1 reference get in the @@ -113,6 +120,7 @@ static int sd_remove(struct device *); static void sd_shutdown(struct device *dev); static void sd_rescan(struct device *); static int sd_init_command(struct scsi_cmnd *); +static int sd_issue_flush(struct device *, sector_t *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, struct scsi_request *SRpnt, unsigned char *buffer); @@ -126,9 +134,11 @@ static struct scsi_driver sd_template = { }, .rescan = sd_rescan, .init_command = sd_init_command, + .issue_flush = sd_issue_flush, }; -/* Device no to disk mapping: +/* + * Device no to disk mapping: * * major disc2 disc p1 * |............|.............|....|....| <- dev_t @@ -141,7 +151,6 @@ static struct scsi_driver sd_template = { * As we stay compatible with our numbering scheme, we can reuse * the well-know SCSI majors 8, 65--71, 136--143. */ - static int sd_major(int major_idx) { switch (major_idx) { @@ -157,14 +166,6 @@ static int sd_major(int major_idx) } } -static unsigned int make_sd_dev(unsigned int sd_nr, unsigned int part) -{ - return (part & 0xf) | ((sd_nr & 0xf) << 4) | - (sd_major((sd_nr & 0xf0) >> 4) << 20) | (sd_nr & 0xfff00); -} - -/* reverse mapping dev -> (sd_nr, part) not currently needed */ - #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kref) static inline struct scsi_disk *scsi_disk(struct gendisk *disk) @@ -180,16 +181,14 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) if (disk->private_data == NULL) goto out; sdkp = scsi_disk(disk); - if (!kref_get(&sdkp->kref)) - goto out_sdkp; + kref_get(&sdkp->kref); if (scsi_device_get(sdkp->device)) goto out_put; up(&sd_ref_sem); return sdkp; out_put: - kref_put(&sdkp->kref); - out_sdkp: + kref_put(&sdkp->kref, scsi_disk_release); sdkp = NULL; out: up(&sd_ref_sem); @@ -199,8 +198,8 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) static void scsi_disk_put(struct scsi_disk *sdkp) { down(&sd_ref_sem); + kref_put(&sdkp->kref, scsi_disk_release); scsi_device_put(sdkp->device); - kref_put(&sdkp->kref); up(&sd_ref_sem); } @@ -575,8 +574,9 @@ static int sd_ioctl(struct inode * inode, struct file * filp, * may try and take the device offline, in which case all further * access to the device is prohibited. */ - if (!scsi_block_when_processing_errors(sdp)) - return -ENODEV; + error = scsi_nonblockable_ioctl(sdp, cmd, p, filp); + if (!scsi_block_when_processing_errors(sdp) || !error) + return error; if (cmd == HDIO_GETGEO) { if (!arg) @@ -648,7 +648,7 @@ static int sd_media_changed(struct gendisk *disk) */ retval = -ENODEV; if (scsi_block_when_processing_errors(sdp)) - retval = scsi_ioctl(sdp, SCSI_IOCTL_TEST_UNIT_READY, NULL); + retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES); /* * Unable to test, unit probably not ready. This usually @@ -676,6 +676,62 @@ not_present: return 1; } +static int sd_sync_cache(struct scsi_device *sdp) +{ + struct scsi_request *sreq; + int retries, res; + + if (!scsi_device_online(sdp)) + return -ENODEV; + + sreq = scsi_allocate_request(sdp, GFP_KERNEL); + if (!sreq) { + printk("FAILED\n No memory for request\n"); + return -ENOMEM; + } + + sreq->sr_data_direction = DMA_NONE; + for (retries = 3; retries > 0; --retries) { + unsigned char cmd[10] = { 0 }; + + cmd[0] = SYNCHRONIZE_CACHE; + /* + * Leave the rest of the command zero to indicate + * flush everything. + */ + scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); + if (sreq->sr_result == 0) + break; + } + + res = sreq->sr_result; + if (res) { + printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + "host = %d, driver = %02x\n ", + status_byte(res), msg_byte(res), + host_byte(res), driver_byte(res)); + if (driver_byte(res) & DRIVER_SENSE) + scsi_print_req_sense("sd", sreq); + } + + scsi_release_request(sreq); + return res; +} + +static int sd_issue_flush(struct device *dev, sector_t *error_sector) +{ + struct scsi_device *sdp = to_scsi_device(dev); + struct scsi_disk *sdkp = dev_get_drvdata(dev); + + if (!sdkp) + return -ENODEV; + + if (!sdkp->WCE) + return 0; + + return sd_sync_cache(sdp); +} + static void sd_rescan(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); @@ -889,7 +945,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, * Issue command to spin up drive when not ready */ } else if (SRpnt->sr_sense_buffer[2] == NOT_READY) { - unsigned long time1; if (!spintime) { printk(KERN_NOTICE "%s: Spinning up disk...", diskname); @@ -908,12 +963,8 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, spintime_value = jiffies; } spintime = 1; - time1 = HZ; /* Wait 1 second for next try */ - do { - current->state = TASK_UNINTERRUPTIBLE; - time1 = schedule_timeout(time1); - } while(time1); + msleep(1000); printk("."); } else { /* we don't understand the sense code, so it's @@ -1053,6 +1104,11 @@ repeat: (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; } + /* Some devices return the total number of sectors, not the + * highest sector number. Make the necessary adjustment. */ + if (sdp->fix_capacity) + --sdkp->capacity; + got_data: if (sector_size == 0) { sector_size = 512; @@ -1074,6 +1130,13 @@ got_data: * For this reason, we leave the thing in the table. */ sdkp->capacity = 0; + /* + * set a bogus sector size so the normal read/write + * logic in the block layer will eventually refuse any + * request on this device without tripping over power + * of two sector size assumptions + */ + sector_size = 512; } { /* @@ -1347,7 +1410,7 @@ static int sd_probe(struct device *dev) struct scsi_disk *sdkp; struct gendisk *gd; u32 index; - int error, devno; + int error; error = -ENODEV; if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)) @@ -1362,27 +1425,23 @@ static int sd_probe(struct device *dev) goto out; memset (sdkp, 0, sizeof(*sdkp)); - kref_init(&sdkp->kref, scsi_disk_release); - - /* Note: We can accomodate 64 partitions, but the genhd code - * assumes partitions allocate consecutive minors, which they don't. - * So for now stay with max 16 partitions and leave two spare bits. - * Later, we may change the genhd code and the alloc_disk() call - * and the ->minors assignment here. KG, 2004-02-10 - */ + kref_init(&sdkp->kref); + gd = alloc_disk(16); if (!gd) goto out_free; + if (!idr_pre_get(&sd_index_idr, GFP_KERNEL)) + goto out_put; + spin_lock(&sd_index_lock); - index = find_first_zero_bit(sd_index_bits, SD_DISKS); - if (index == SD_DISKS) { - spin_unlock(&sd_index_lock); + error = idr_get_new(&sd_index_idr, NULL, &index); + spin_unlock(&sd_index_lock); + + if (index >= SD_MAX_DISKS) error = -EBUSY; + if (error) goto out_put; - } - __set_bit(index, sd_index_bits); - spin_unlock(&sd_index_lock); sdkp->device = sdp; sdkp->driver = &sd_template; @@ -1397,15 +1456,14 @@ static int sd_probe(struct device *dev) sdp->timeout = SD_MOD_TIMEOUT; } - devno = make_sd_dev(index, 0); - gd->major = MAJOR(devno); - gd->first_minor = MINOR(devno); + gd->major = sd_major((index & 0xf0) >> 4); + gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); gd->minors = 16; gd->fops = &sd_fops; if (index < 26) { sprintf(gd->disk_name, "sd%c", 'a' + index % 26); - } else if (index < (26*27)) { + } else if (index < (26 + 1) * 26) { sprintf(gd->disk_name, "sd%c%c", 'a' + index / 26 - 1,'a' + index % 26); } else { @@ -1464,7 +1522,7 @@ static int sd_remove(struct device *dev) del_gendisk(sdkp->disk); sd_shutdown(dev); down(&sd_ref_sem); - kref_put(&sdkp->kref); + kref_put(&sdkp->kref, scsi_disk_release); up(&sd_ref_sem); return 0; @@ -1485,7 +1543,7 @@ static void scsi_disk_release(struct kref *kref) struct gendisk *disk = sdkp->disk; spin_lock(&sd_index_lock); - clear_bit(sdkp->index, sd_index_bits); + idr_remove(&sd_index_idr, sdkp->index); spin_unlock(&sd_index_lock); disk->private_data = NULL; @@ -1503,52 +1561,17 @@ static void scsi_disk_release(struct kref *kref) static void sd_shutdown(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - struct scsi_disk *sdkp; - struct scsi_request *sreq; - int retries, res; + struct scsi_disk *sdkp = dev_get_drvdata(dev); - sdkp = dev_get_drvdata(dev); if (!sdkp) - return; /* this can happen */ + return; /* this can happen */ - if (!scsi_device_online(sdp) || !sdkp->WCE) + if (!sdkp->WCE) return; - printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", + printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n", sdkp->disk->disk_name); - - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk("FAILED\n No memory for request\n"); - return; - } - - sreq->sr_data_direction = DMA_NONE; - for (retries = 3; retries > 0; --retries) { - unsigned char cmd[10] = { 0 }; - - cmd[0] = SYNCHRONIZE_CACHE; - /* - * Leave the rest of the command zero to indicate - * flush everything. - */ - scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); - if (sreq->sr_result == 0) - break; - } - - res = sreq->sr_result; - if (res) { - printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " - "host = %d, driver = %02x\n ", - status_byte(res), msg_byte(res), - host_byte(res), driver_byte(res)); - if (driver_byte(res) & DRIVER_SENSE) - scsi_print_req_sense("sd", sreq); - } - - scsi_release_request(sreq); - printk("\n"); + sd_sync_cache(sdp); } /** diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index 43102408d..b362ff281 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -237,13 +237,13 @@ static unsigned int base_address = 0; /* Where the card ROM starts, used to calculate memory mapped register location. */ -static unsigned long st0x_cr_sr; /* control register write, status +static void __iomem *st0x_cr_sr; /* control register write, status register read. 256 bytes in length. Read is status of SCSI BUS, as per STAT masks. */ -static unsigned long st0x_dr; /* data register, read write 256 +static void __iomem *st0x_dr; /* data register, read write 256 bytes in length. */ static volatile int st0x_aborted = 0; /* set when we are aborted, ie by a @@ -254,17 +254,17 @@ static unsigned char controller_type = 0; /* set to SEAGATE for ST0x boards */ static int irq = IRQ; -MODULE_PARM (base_address, "i"); -MODULE_PARM (controller_type, "b"); -MODULE_PARM (irq, "i"); +module_param(base_address, uint, 0); +module_param(controller_type, byte, 0); +module_param(irq, int, 0); MODULE_LICENSE("GPL"); #define retcode(result) (((result) << 16) | (message << 8) | status) -#define STATUS ((u8) isa_readb(st0x_cr_sr)) -#define DATA ((u8) isa_readb(st0x_dr)) -#define WRITE_CONTROL(d) { isa_writeb((d), st0x_cr_sr); } -#define WRITE_DATA(d) { isa_writeb((d), st0x_dr); } +#define STATUS ((u8) readb(st0x_cr_sr)) +#define DATA ((u8) readb(st0x_dr)) +#define WRITE_CONTROL(d) { writeb((d), st0x_cr_sr); } +#define WRITE_DATA(d) { writeb((d), st0x_dr); } #ifndef OVERRIDE static unsigned int seagate_bases[] = { @@ -420,6 +420,7 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) { struct Scsi_Host *instance; int i, j; + unsigned long cr, dr; tpnt->proc_name = "seagate"; /* @@ -454,12 +455,18 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) * space for the on-board RAM instead. */ - for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) - for (j = 0; !base_address && j < NUM_SIGNATURES; ++j) - if (isa_check_signature(seagate_bases[i] + signatures[j].offset, signatures[j].signature, signatures[j].length)) { + for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) { + void __iomem *p = ioremap(seagate_bases[i], 0x2000); + if (!p) + continue; + for (j = 0; j < NUM_SIGNATURES; ++j) + if (check_signature(p + signatures[j].offset, signatures[j].signature, signatures[j].length)) { base_address = seagate_bases[i]; controller_type = signatures[j].type; + break; } + iounmap(p); + } #endif /* OVERRIDE */ } /* (! controller_type) */ @@ -471,11 +478,13 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) return 0; } - st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); - st0x_dr = st0x_cr_sr + 0x200; + cr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00); + dr = cr + 0x200; + st0x_cr_sr = ioremap(cr, 0x100); + st0x_dr = ioremap(dr, 0x100); DANY("%s detected. Base address = %x, cr = %x, dr = %x\n", - tpnt->name, base_address, st0x_cr_sr, st0x_dr); + tpnt->name, base_address, cr, dr); /* * At all times, we will use IRQ 5. Should also check for IRQ3 @@ -1140,7 +1149,7 @@ connect_loop: #endif "loop 1b;" /* output */ : - /* input */ :"D" (phys_to_virt (st0x_dr)), + /* input */ :"D" (st0x_dr), "S" (data), "c" (SCint->transfersize) @@ -1148,19 +1157,7 @@ connect_loop: : "eax", "ecx", "esi"); #else /* SEAGATE_USE_ASM */ - { -#ifdef FAST32 - unsigned int *iop = phys_to_virt (st0x_dr); - const unsigned int *dp =(unsigned int *) data; - int xferlen = transfersize >> 2; -#else - unsigned char *iop = phys_to_virt (st0x_dr); - const unsigned char *dp = data; - int xferlen = transfersize; -#endif - for (; xferlen; --xferlen) - *iop = *dp++; - } + memcpy_toio(st0x_dr, data, transfersize); #endif /* SEAGATE_USE_ASM */ /* SJT: End */ len -= transfersize; @@ -1212,10 +1209,8 @@ connect_loop: "=D" (__dummy_2) /* input */ : "0" (data), "1" (len), - "2" (phys_to_virt - (st0x_cr_sr)), - "3" (phys_to_virt - (st0x_dr)) + "2" (st0x_cr_sr), + "3" (st0x_dr) /* clobbered */ : "eax"); #else /* SEAGATE_USE_ASM */ @@ -1292,7 +1287,7 @@ connect_loop: #endif "loop 1b\n\t" /* output */ : - /* input */ :"S" (phys_to_virt (st0x_dr)), + /* input */ :"S" (st0x_dr), "D" (data), "c" (SCint->transfersize) @@ -1300,22 +1295,7 @@ connect_loop: : "eax", "ecx", "edi"); #else /* SEAGATE_USE_ASM */ - { -#ifdef FAST32 - const unsigned int *iop = - phys_to_virt (st0x_dr); - unsigned int *dp = - (unsigned int *) data; - int xferlen = len >> 2; -#else - const unsigned char *iop = - phys_to_virt (st0x_dr); - unsigned char *dp = data; - int xferlen = len; -#endif - for (; xferlen; --xferlen) - *dp++ = *iop; - } + memcpy_fromio(data, st0x_dr, len); #endif /* SEAGATE_USE_ASM */ /* SJT: End */ len -= transfersize; @@ -1381,10 +1361,8 @@ connect_loop: "=b" (__dummy_4) /* input */ : "0" (data), "1" (len), - "2" (phys_to_virt - (st0x_cr_sr)), - "3" (phys_to_virt - (st0x_dr)) + "2" (st0x_cr_sr), + "3" (st0x_dr) /* clobbered */ : "eax"); #else /* SEAGATE_USE_ASM */ diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7b0665d8b..7fb610d88 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -47,8 +47,9 @@ static int sg_version_num = 30531; /* 2 digits for each component */ #include #include #include - #include +#include + #include "scsi.h" #include #include @@ -205,8 +206,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); -static int sg_ms_to_jif(unsigned int msecs); -static inline unsigned sg_jif_to_ms(int jifs); static int sg_allow_access(unsigned char opcode, char dev_type); static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); static Sg_device *sg_get_dev(int dev); @@ -564,6 +563,20 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) hp->usr_ptr = NULL; if (__copy_from_user(cmnd, buf, cmd_size)) return -EFAULT; + /* + * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV, + * but is is possible that the app intended SG_DXFER_TO_DEV, because there + * is a non-zero input_size, so emit a warning. + */ + if (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV) + if (printk_ratelimit()) + printk(KERN_WARNING + "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--" + "guessing data in;\n" KERN_WARNING " " + "program %s not setting count and/or reply_len properly\n", + old_hdr.reply_len - (int)SZ_SG_HEADER, + input_size, (unsigned int) cmnd[0], + current->comm); k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking); return (k < 0) ? k : count; } @@ -577,6 +590,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, sg_io_hdr_t *hp; unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)]; int timeout; + unsigned long ul_timeout; if (count < SZ_SG_IO_HDR) return -EINVAL; @@ -611,7 +625,8 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, return -EBUSY; /* reserve buffer already being used */ } } - timeout = sg_ms_to_jif(srp->header.timeout); + ul_timeout = msecs_to_jiffies(srp->header.timeout); + timeout = (ul_timeout < INT_MAX) ? ul_timeout : INT_MAX; if ((!hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof (cmnd))) { sg_remove_request(sfp, srp); return -EMSGSIZE; @@ -719,17 +734,16 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, return 0; } -static inline unsigned -sg_jif_to_ms(int jifs) +static int +sg_srp_done(Sg_request *srp, Sg_fd *sfp) { - if (jifs <= 0) - return 0U; - else { - unsigned int j = (unsigned int) jifs; - return (j < - (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * - 1000); - } + unsigned long iflags; + int done; + + read_lock_irqsave(&sfp->rq_list_lock, iflags); + done = srp->done; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return done; } static int @@ -771,7 +785,7 @@ sg_ioctl(struct inode *inode, struct file *filp, while (1) { result = 0; /* following macro to beat race condition */ __wait_event_interruptible(sfp->read_wait, - (sdp->detached || sfp->closed || srp->done), + (sdp->detached || sfp->closed || sg_srp_done(srp, sfp)), result); if (sdp->detached) return -ENODEV; @@ -782,7 +796,9 @@ sg_ioctl(struct inode *inode, struct file *filp, srp->orphan = 1; return result; /* -ERESTARTSYS because signal hit process */ } + write_lock_irqsave(&sfp->rq_list_lock, iflags); srp->done = 2; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp); return (result < 0) ? result : 0; } @@ -941,7 +957,7 @@ sg_ioctl(struct inode *inode, struct file *filp, srp->header.driver_status; rinfo[val].duration = srp->done ? srp->header.duration : - sg_jif_to_ms( + jiffies_to_msecs( jiffies - srp->header.duration); rinfo[val].orphan = srp->orphan; rinfo[val].sg_io_owned = srp->sg_io_owned; @@ -1225,6 +1241,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt) Sg_device *sdp = NULL; Sg_fd *sfp; Sg_request *srp = NULL; + unsigned long iflags; if (SCpnt && (SRpnt = SCpnt->sc_request)) srp = (Sg_request *) SRpnt->upper_private_data; @@ -1263,7 +1280,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt) srp->header.resid = SCpnt->resid; /* N.B. unit of duration changes here from jiffies to millisecs */ srp->header.duration = - sg_jif_to_ms(jiffies - (int) srp->header.duration); + jiffies_to_msecs(jiffies - srp->header.duration); if (0 != SRpnt->sr_result) { memcpy(srp->sense_b, SRpnt->sr_sense_buffer, sizeof (srp->sense_b)); @@ -1313,8 +1330,10 @@ sg_cmd_done(Scsi_Cmnd * SCpnt) if (sfp && srp) { /* Now wake up any sg_read() that is waiting for this packet. */ kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); + write_lock_irqsave(&sfp->rq_list_lock, iflags); srp->done = 1; wake_up_interruptible(&sfp->read_wait); + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); } } @@ -1508,7 +1527,7 @@ sg_remove(struct class_device *cl_dev) tsfp = sfp->nextfp; for (srp = sfp->headrp; srp; srp = tsrp) { tsrp = srp->nextrp; - if (sfp->closed || (0 == srp->done)) + if (sfp->closed || (0 == sg_srp_done(srp, sfp))) sg_finish_rem_req(srp); } if (sfp->closed) { @@ -1547,7 +1566,7 @@ sg_remove(struct class_device *cl_dev) } if (delay) - scsi_sleep(2); /* dirty detach so delay device destruction */ + msleep(10); /* dirty detach so delay device destruction */ } /* Set 'perm' (4th argument) to 0 to disable module_param's definition @@ -2421,7 +2440,7 @@ sg_add_sfp(Sg_device * sdp, int dev) return NULL; memset(sfp, 0, sizeof (Sg_fd)); init_waitqueue_head(&sfp->read_wait); - sfp->rq_list_lock = RW_LOCK_UNLOCKED; + rwlock_init(&sfp->rq_list_lock); sfp->timeout = SG_DEFAULT_TIMEOUT; sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER; @@ -2490,7 +2509,7 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) for (srp = sfp->headrp; srp; srp = tsrp) { tsrp = srp->nextrp; - if (srp->done) + if (sg_srp_done(srp, sfp)) sg_finish_rem_req(srp); else ++dirty; @@ -2587,17 +2606,6 @@ sg_page_free(char *buff, int size) free_pages((unsigned long) buff, order); } -static int -sg_ms_to_jif(unsigned int msecs) -{ - if ((UINT_MAX / 2U) < msecs) - return INT_MAX; /* special case, set largest possible */ - else - return ((int) msecs < - (INT_MAX / 1000)) ? (((int) msecs * HZ) / 1000) - : (((int) msecs / 1000) * HZ); -} - static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE, INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12, MODE_SENSE, MODE_SENSE_10, LOG_SENSE @@ -2960,7 +2968,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) { seq_printf(s, " FD(%d): timeout=%dms bufflen=%d " "(res)sgat=%d low_dma=%d\n", k + 1, - sg_jif_to_ms(fp->timeout), + jiffies_to_msecs(fp->timeout), fp->reserve.bufflen, (int) fp->reserve.k_use_sg, (int) fp->low_dma); @@ -2996,8 +3004,8 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) seq_printf(s, " dur=%d", hp->duration); else seq_printf(s, " t_o/elap=%d/%d", - new_interface ? hp->timeout : sg_jif_to_ms(fp->timeout), - sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0)); + new_interface ? hp->timeout : jiffies_to_msecs(fp->timeout), + jiffies_to_msecs(hp->duration ? (jiffies - hp->duration) : 0)); seq_printf(s, "ms sgat=%d op=0x%02x\n", usg, (int) srp->data.cmd_opcode); } diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index f73bf835d..3e684c2ad 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include "53c700.h" @@ -124,28 +127,16 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, NCR_700_set_io_mapped(hostdata); /* and register the chip */ - if((host = NCR_700_detect(&sim710_driver_template, hostdata)) == NULL) { + if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev, irq, + scsi_id)) == NULL) { printk(KERN_ERR "sim710: No host detected; card configuration problem?\n"); goto out_release; } - host->irq = irq; - host->this_id = scsi_id; - - if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "sim710", host)) { - printk(KERN_ERR "sim710: irq problem with %d, detaching\n", - irq); - goto out_unregister; - } - - scsi_add_host(host, dev); /* XXX handle failure */ scsi_scan_host(host); - hostdata->dev = dev; return 0; - out_unregister: - scsi_host_put(host); out_release: release_region(host->base, 64); out_free: diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index b80aa283c..dc9d740da 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -140,15 +140,13 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) if (disk->private_data == NULL) goto out; cd = scsi_cd(disk); - if (!kref_get(&cd->kref)) - goto out_null; + kref_get(&cd->kref); if (scsi_device_get(cd->device)) goto out_put; goto out; out_put: - kref_put(&cd->kref); - out_null: + kref_put(&cd->kref, sr_kref_release); cd = NULL; out: up(&sr_ref_sem); @@ -158,8 +156,8 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) static inline void scsi_cd_put(struct scsi_cd *cd) { down(&sr_ref_sem); + kref_put(&cd->kref, sr_kref_release); scsi_device_put(cd->device); - kref_put(&cd->kref); up(&sr_ref_sem); } @@ -183,7 +181,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot) return -EINVAL; } - retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, NULL); + retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES); if (retval) { /* Unable to test, unit probably not ready. This usually * means there is no disc in the drive. Mark as changed, @@ -379,6 +377,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) return 0; SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = DMA_TO_DEVICE; + cd->cdi.media_written = 1; } else if (rq_data_dir(SCpnt->request) == READ) { SCpnt->cmnd[0] = READ_10; SCpnt->sc_data_direction = DMA_FROM_DEVICE; @@ -576,7 +575,7 @@ static int sr_probe(struct device *dev) goto fail; memset(cd, 0, sizeof(*cd)); - kref_init(&cd->kref, sr_kref_release); + kref_init(&cd->kref); disk = alloc_disk(1); if (!disk) @@ -877,10 +876,10 @@ static void get_capabilities(struct scsi_cd *cd) cd->cdi.mask |= CDC_CLOSE_TRAY; */ /* - * if DVD-RAM of MRW-W, we are randomly writeable + * if DVD-RAM, MRW-W or CD-RW, we are randomly writable */ - if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) != - (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) { + if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) != + (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) { cd->device->writeable = 1; } @@ -937,7 +936,7 @@ static int sr_remove(struct device *dev) del_gendisk(cd->disk); down(&sr_ref_sem); - kref_put(&cd->kref); + kref_put(&cd->kref, sr_kref_release); up(&sr_ref_sem); return 0; diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 7d24b57c2..462b79167 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -131,7 +132,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); if (retries++ < 10) { /* sleep 2 sec and try again */ - scsi_sleep(2 * HZ); + ssleep(2); goto retry; } else { /* 20 secs are enough? */ @@ -548,5 +549,17 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { Scsi_CD *cd = cdi->handle; + int ret; + + ret = scsi_nonblockable_ioctl(cd->device, cmd, + (void __user *)arg, NULL); + /* + * ENODEV means that we didn't recognise the ioctl, or that we + * cannot execute it in the current device state. In either + * case fall through to scsi_ioctl, which will return ENDOEV again + * if it doesn't recognise the ioctl + */ + if (ret != -ENODEV) + return ret; return scsi_ioctl(cd->device, cmd, (void __user *)arg); } diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 5fa0153da..64a9b4c62 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20040403"; +static char *verstr = "20041025"; #include @@ -40,6 +40,16 @@ static char *verstr = "20040403"; #include #include +#include +#include +#include +#include +#include +#include +#include +#include + + /* The driver prints some debugging information on the console if DEBUG is defined and non-zero. */ #define DEBUG 0 @@ -56,13 +66,6 @@ static char *verstr = "20040403"; #define DEBC(a) #endif - -#include "scsi.h" -#include - -#include -#include - #define ST_KILOBYTE 1024 #include "st_options.h" @@ -71,8 +74,8 @@ static char *verstr = "20040403"; static int buffer_kbs; static int max_sg_segs; static int try_direct_io = TRY_DIRECT_IO; -static int try_rdio = TRUE; -static int try_wdio = TRUE; +static int try_rdio = 1; +static int try_wdio = 1; static int st_dev_max; static int st_nr_dev; @@ -169,17 +172,17 @@ static rwlock_t st_dev_arr_lock = RW_LOCK_UNLOCKED; static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE; static int st_max_sg_segs = ST_MAX_SG; -static Scsi_Tape **scsi_tapes = NULL; +static struct scsi_tape **scsi_tapes = NULL; static int modes_defined; -static ST_buffer *new_tape_buffer(int, int, int); -static int enlarge_buffer(ST_buffer *, int, int); -static void normalize_buffer(ST_buffer *); -static int append_to_buffer(const char __user *, ST_buffer *, int); -static int from_buffer(ST_buffer *, char __user *, int); -static void move_buffer_data(ST_buffer *, int); -static void buf_to_sg(ST_buffer *, unsigned int); +static struct st_buffer *new_tape_buffer(int, int, int); +static int enlarge_buffer(struct st_buffer *, int, int); +static void normalize_buffer(struct st_buffer *); +static int append_to_buffer(const char __user *, struct st_buffer *, int); +static int from_buffer(struct st_buffer *, char __user *, int); +static void move_buffer_data(struct st_buffer *, int); +static void buf_to_sg(struct st_buffer *, unsigned int); static int st_map_user_pages(struct scatterlist *, const unsigned int, unsigned long, size_t, int, unsigned long); @@ -193,7 +196,7 @@ static int st_init_command(struct scsi_cmnd *); static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); -static void do_create_class_files(Scsi_Tape *, int, int); +static void do_create_class_files(struct scsi_tape *, int, int); static struct scsi_driver st_template = { .owner = THIS_MODULE, @@ -205,12 +208,12 @@ static struct scsi_driver st_template = { .init_command = st_init_command, }; -static int st_compression(Scsi_Tape *, int); +static int st_compression(struct scsi_tape *, int); -static int find_partition(Scsi_Tape *); -static int switch_partition(Scsi_Tape *); +static int find_partition(struct scsi_tape *); +static int switch_partition(struct scsi_tape *); -static int st_int_ioctl(Scsi_Tape *, unsigned int, unsigned long); +static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long); #include "osst_detect.h" @@ -237,7 +240,7 @@ static struct st_reject_data reject_list[] = { /* If the device signature is on the list of incompatible drives, the function returns a pointer to the name of the correct driver (if known) */ -static char * st_incompatible(Scsi_Device* SDp) +static char * st_incompatible(struct scsi_device* SDp) { struct st_reject_data *rp; @@ -254,13 +257,13 @@ static char * st_incompatible(Scsi_Device* SDp) } -static inline char *tape_name(Scsi_Tape *tape) +static inline char *tape_name(struct scsi_tape *tape) { return tape->disk->disk_name; } /* Convert the result to success code */ -static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt) +static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt) { int result = SRpnt->sr_result; unsigned char *sense = SRpnt->sr_sense_buffer, scode; @@ -287,7 +290,7 @@ static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt) SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5], SRpnt->sr_bufflen); if (driver_byte(result) & DRIVER_SENSE) - print_req_sense("st", SRpnt); + scsi_print_req_sense("st", SRpnt); } else ) /* end DEB */ if (!(driver_byte(result) & DRIVER_SENSE) || ((sense[0] & 0x70) == 0x70 && @@ -300,7 +303,7 @@ static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt) SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ if (driver_byte(result) & DRIVER_SENSE) { printk(KERN_WARNING "%s: Error with sense data: ", name); - print_req_sense("st", SRpnt); + scsi_print_req_sense("st", SRpnt); } else printk(KERN_WARNING "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", @@ -351,11 +354,11 @@ static int st_chk_result(Scsi_Tape *STp, Scsi_Request * SRpnt) /* Wakeup from interrupt */ -static void st_sleep_done(Scsi_Cmnd * SCpnt) +static void st_sleep_done(struct scsi_cmnd * SCpnt) { int remainder; - Scsi_Tape *STp = container_of(SCpnt->request->rq_disk->private_data, - Scsi_Tape, driver); + struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data, + struct scsi_tape, driver); if ((STp->buffer)->writing && (SCpnt->sense_buffer[0] & 0x70) == 0x70 && @@ -385,9 +388,9 @@ static void st_sleep_done(Scsi_Cmnd * SCpnt) /* Do the scsi command. Waits until command performed if do_wait is true. Otherwise write_behind_check() is used to check that the command has finished. */ -static Scsi_Request * - st_do_scsi(Scsi_Request * SRpnt, Scsi_Tape * STp, unsigned char *cmd, int bytes, - int direction, int timeout, int retries, int do_wait) +static struct scsi_request * +st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd, + int bytes, int direction, int timeout, int retries, int do_wait) { unsigned char *bp; @@ -432,10 +435,10 @@ static Scsi_Request * /* Handle the write-behind checking (downs the semaphore) */ -static void write_behind_check(Scsi_Tape * STp) +static void write_behind_check(struct scsi_tape * STp) { - ST_buffer *STbuffer; - ST_partstat *STps; + struct st_buffer *STbuffer; + struct st_partstat *STps; STbuffer = STp->buffer; @@ -468,9 +471,9 @@ static void write_behind_check(Scsi_Tape * STp) /* Step over EOF if it has been inadvertently crossed (ioctl not used because it messes up the block number). */ -static int cross_eof(Scsi_Tape * STp, int forward) +static int cross_eof(struct scsi_tape * STp, int forward) { - Scsi_Request *SRpnt; + struct scsi_request *SRpnt; unsigned char cmd[MAX_COMMAND_SIZE]; cmd[0] = SPACE; @@ -485,8 +488,8 @@ static int cross_eof(Scsi_Tape * STp, int forward) DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", tape_name(STp), forward ? "forward" : "backward")); - SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->device->timeout, MAX_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, + STp->device->timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -502,13 +505,13 @@ static int cross_eof(Scsi_Tape * STp, int forward) /* Flush the write buffer (never need to write if variable blocksize). */ -static int flush_write_buffer(Scsi_Tape * STp) +static int flush_write_buffer(struct scsi_tape * STp) { int offset, transfer, blks; int result; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; - ST_partstat *STps; + struct scsi_request *SRpnt; + struct st_partstat *STps; if ((STp->buffer)->writing) { write_behind_check(STp); @@ -543,8 +546,8 @@ static int flush_write_buffer(Scsi_Tape * STp) cmd[3] = blks >> 8; cmd[4] = blks; - SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->device->timeout, MAX_WRITE_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, cmd, transfer, DMA_TO_DEVICE, + STp->device->timeout, MAX_WRITE_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -577,11 +580,11 @@ static int flush_write_buffer(Scsi_Tape * STp) /* Flush the tape buffer. The tape will be positioned correctly unless seek_next is true. */ -static int flush_buffer(Scsi_Tape *STp, int seek_next) +static int flush_buffer(struct scsi_tape *STp, int seek_next) { int backspace, result; - ST_buffer *STbuffer; - ST_partstat *STps; + struct st_buffer *STbuffer; + struct st_partstat *STps; STbuffer = STp->buffer; @@ -610,7 +613,7 @@ static int flush_buffer(Scsi_Tape *STp, int seek_next) result = 0; if (!seek_next) { if (STps->eof == ST_FM_HIT) { - result = cross_eof(STp, FALSE); /* Back over the EOF hit */ + result = cross_eof(STp, 0); /* Back over the EOF hit */ if (!result) STps->eof = ST_NOEOF; else { @@ -632,9 +635,9 @@ static int flush_buffer(Scsi_Tape *STp, int seek_next) } /* Set the mode parameters */ -static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm) +static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) { - int set_it = FALSE; + int set_it = 0; unsigned long arg; char *name = tape_name(STp); @@ -642,7 +645,7 @@ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm) STm->default_density >= 0 && STm->default_density != STp->density) { arg = STm->default_density; - set_it = TRUE; + set_it = 1; } else arg = STp->density; arg <<= MT_ST_DENSITY_SHIFT; @@ -650,7 +653,7 @@ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm) STm->default_blksize >= 0 && STm->default_blksize != STp->block_size) { arg |= STm->default_blksize; - set_it = TRUE; + set_it = 1; } else arg |= STp->block_size; if (set_it && @@ -665,8 +668,8 @@ static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm) } -/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */ -static int do_door_lock(Scsi_Tape * STp, int do_lock) +/* Lock or unlock the drive door. Don't use when scsi_request allocated. */ +static int do_door_lock(struct scsi_tape * STp, int do_lock) { int retval, cmd; DEB(char *name = tape_name(STp);) @@ -687,10 +690,10 @@ static int do_door_lock(Scsi_Tape * STp, int do_lock) /* Set the internal state after reset */ -static void reset_state(Scsi_Tape *STp) +static void reset_state(struct scsi_tape *STp) { int i; - ST_partstat *STps; + struct st_partstat *STps; STp->pos_unknown = 0; for (i = 0; i < ST_NBR_PARTITIONS; i++) { @@ -698,7 +701,7 @@ static void reset_state(Scsi_Tape *STp) STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; - STps->last_block_valid = FALSE; + STps->last_block_valid = 0; STps->drv_block = -1; STps->drv_file = -1; } @@ -719,20 +722,20 @@ static void reset_state(Scsi_Tape *STp) #define MAX_ATTENTIONS 10 -static int test_ready(Scsi_Tape *STp, int do_wait) +static int test_ready(struct scsi_tape *STp, int do_wait) { int attentions, waits, max_wait, scode; - int retval = CHKRES_READY, new_session = FALSE; + int retval = CHKRES_READY, new_session = 0; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt = NULL; + struct scsi_request *SRpnt = NULL; max_wait = do_wait ? ST_BLOCK_SECONDS : 0; for (attentions=waits=0; ; ) { memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, - STp->long_timeout, MAX_READY_RETRIES, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, + STp->long_timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -744,7 +747,7 @@ static int test_ready(Scsi_Tape *STp, int do_wait) scode = (SRpnt->sr_sense_buffer[2] & 0x0f); if (scode == UNIT_ATTENTION) { /* New media? */ - new_session = TRUE; + new_session = 1; if (attentions < MAX_ATTENTIONS) { attentions++; continue; @@ -794,14 +797,14 @@ static int test_ready(Scsi_Tape *STp, int do_wait) 0 drive ready 1 drive not ready (possibly no tape) */ -static int check_tape(Scsi_Tape *STp, struct file *filp) +static int check_tape(struct scsi_tape *STp, struct file *filp) { - int i, retval, new_session = FALSE, do_wait; + int i, retval, new_session = 0, do_wait; unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning; unsigned short st_flags = filp->f_flags; - Scsi_Request *SRpnt = NULL; - ST_mode *STm; - ST_partstat *STps; + struct scsi_request *SRpnt = NULL; + struct st_modedef *STm; + struct st_partstat *STps; char *name = tape_name(STp); struct inode *inode = filp->f_dentry->d_inode; int mode = TAPE_MODE(inode); @@ -811,7 +814,7 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) if (mode != STp->current_mode) { DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n", name, STp->current_mode, mode)); - new_session = TRUE; + new_session = 1; STp->current_mode = mode; } STm = &(STp->modes[STp->current_mode]); @@ -836,11 +839,11 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; - STps->last_block_valid = FALSE; + STps->last_block_valid = 0; STps->drv_block = 0; STps->drv_file = 0; } - new_session = TRUE; + new_session = 1; } else { STp->cleaning_req |= saved_cleaning; @@ -867,8 +870,8 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = READ_BLOCK_LIMITS; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout, - MAX_READY_RETRIES, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE, + STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; goto err_out; @@ -894,8 +897,8 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) cmd[0] = MODE_SENSE; cmd[4] = 12; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout, - MAX_READY_RETRIES, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE, + STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) { retval = (STp->buffer)->syscall_result; goto err_out; @@ -928,7 +931,7 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) } scsi_release_request(SRpnt); SRpnt = NULL; - STp->inited = TRUE; + STp->inited = 1; if (STp->block_size > 0) (STp->buffer)->buffer_blocks = @@ -970,8 +973,8 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) } if (new_session) { /* Change the drive parameters for the new mode */ - STp->density_changed = STp->blksize_changed = FALSE; - STp->compression_changed = FALSE; + STp->density_changed = STp->blksize_changed = 0; + STp->compression_changed = 0; if (!(STm->defaults_for_writes) && (retval = set_mode_densblk(STp, STm)) < 0) goto err_out; @@ -996,8 +999,8 @@ static int check_tape(Scsi_Tape *STp, struct file *filp) static int st_open(struct inode *inode, struct file *filp) { int i, retval = (-EIO); - Scsi_Tape *STp; - ST_partstat *STps; + struct scsi_tape *STp; + struct st_partstat *STps; int dev = TAPE_NR(inode); char *name; @@ -1076,10 +1079,10 @@ static int st_flush(struct file *filp) { int result = 0, result2; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; - Scsi_Tape *STp = filp->private_data; - ST_mode *STm = &(STp->modes[STp->current_mode]); - ST_partstat *STps = &(STp->ps[STp->partition]); + struct scsi_request *SRpnt; + struct scsi_tape *STp = filp->private_data; + struct st_modedef *STm = &(STp->modes[STp->current_mode]); + struct st_partstat *STps = &(STp->ps[STp->partition]); char *name = tape_name(STp); if (file_count(filp) > 1) @@ -1106,8 +1109,8 @@ static int st_flush(struct file *filp) if (STps->rw == ST_WRITING && !STp->pos_unknown) { - DEBC(printk(ST_DEB_MSG "%s: File length %ld bytes.\n", - name, (long) (filp->f_pos)); + DEBC(printk(ST_DEB_MSG "%s: File length %lld bytes.\n", + name, (long long)filp->f_pos); printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n", name, STp->nbr_waits, STp->nbr_finished); ) @@ -1116,8 +1119,8 @@ static int st_flush(struct file *filp) cmd[0] = WRITE_FILEMARKS; cmd[4] = 1 + STp->two_fm; - SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->device->timeout, MAX_WRITE_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, + STp->device->timeout, MAX_WRITE_RETRIES, 1); if (!SRpnt) { result = (STp->buffer)->syscall_result; goto out; @@ -1143,7 +1146,7 @@ static int st_flush(struct file *filp) STps->drv_file++; STps->drv_block = 0; if (STp->two_fm) - cross_eof(STp, FALSE); + cross_eof(STp, 0); STps->eof = ST_FM; } @@ -1155,7 +1158,7 @@ static int st_flush(struct file *filp) if (STp->can_bsr) result = flush_buffer(STp, 0); else if (STps->eof == ST_FM_HIT) { - result = cross_eof(STp, FALSE); + result = cross_eof(STp, 0); if (result) { if (STps->drv_file >= 0) STps->drv_file++; @@ -1165,7 +1168,7 @@ static int st_flush(struct file *filp) STps->eof = ST_NOEOF; } } else if ((STps->eof == ST_NOEOF && - !(result = cross_eof(STp, TRUE))) || + !(result = cross_eof(STp, 1))) || STps->eof == ST_FM_HIT) { if (STps->drv_file >= 0) STps->drv_file++; @@ -1189,7 +1192,7 @@ static int st_flush(struct file *filp) static int st_release(struct inode *inode, struct file *filp) { int result = 0; - Scsi_Tape *STp = filp->private_data; + struct scsi_tape *STp = filp->private_data; if (STp->door_locked == ST_LOCKED_AUTO) do_door_lock(STp, 0); @@ -1204,7 +1207,7 @@ static int st_release(struct inode *inode, struct file *filp) } /* The checks common to both reading and writing */ -static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count) +static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count) { ssize_t retval = 0; @@ -1271,10 +1274,11 @@ static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count) } -static int setup_buffering(Scsi_Tape *STp, const char __user *buf, size_t count, int is_read) +static int setup_buffering(struct scsi_tape *STp, const char __user *buf, + size_t count, int is_read) { int i, bufsize, retval = 0; - ST_buffer *STbp = STp->buffer; + struct st_buffer *STbp = STp->buffer; if (is_read) i = STp->try_dio && try_rdio; @@ -1290,7 +1294,7 @@ static int setup_buffering(Scsi_Tape *STp, const char __user *buf, size_t count, STbp->buffer_bytes = 0; /* can be used as transfer counter */ } else - STbp->do_dio = FALSE; /* fall back to buffering with any error */ + STbp->do_dio = 0; /* fall back to buffering with any error */ STbp->sg_segs = STbp->do_dio; STbp->frp_sg_current = 0; DEB( @@ -1303,7 +1307,7 @@ static int setup_buffering(Scsi_Tape *STp, const char __user *buf, size_t count, } ) } else - STbp->do_dio = FALSE; + STbp->do_dio = 0; DEB( STp->nbr_requests++; ) if (!STbp->do_dio) { @@ -1329,13 +1333,13 @@ static int setup_buffering(Scsi_Tape *STp, const char __user *buf, size_t count, /* Can be called more than once after each setup_buffer() */ -static void release_buffering(Scsi_Tape *STp) +static void release_buffering(struct scsi_tape *STp) { - ST_buffer *STbp; + struct st_buffer *STbp; STbp = STp->buffer; if (STbp->do_dio) { - sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, FALSE); + sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, 0); STbp->do_dio = 0; } } @@ -1352,11 +1356,11 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) int async_write; unsigned char cmd[MAX_COMMAND_SIZE]; const char __user *b_point; - Scsi_Request *SRpnt = NULL; - Scsi_Tape *STp = filp->private_data; - ST_mode *STm; - ST_partstat *STps; - ST_buffer *STbp; + struct scsi_request *SRpnt = NULL; + struct scsi_tape *STp = filp->private_data; + struct st_modedef *STm; + struct st_partstat *STps; + struct st_buffer *STbp; char *name = tape_name(STp); if (down_interruptible(&STp->lock)) @@ -1438,7 +1442,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) goto out; } - retval = setup_buffering(STp, buf, count, FALSE); + retval = setup_buffering(STp, buf, count, 0); if (retval) goto out; @@ -1482,7 +1486,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STp->block_size != 0 && STm->do_buffer_writes && !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK && STbp->buffer_bytes < STbp->buffer_size) { - STp->dirty = TRUE; + STp->dirty = 1; /* Don't write a buffer that is not full enough. */ if (!async_write && count == 0) break; @@ -1503,7 +1507,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) cmd[3] = blks >> 8; cmd[4] = blks; - SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, + SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, DMA_TO_DEVICE, STp->device->timeout, MAX_WRITE_RETRIES, !async_write); if (!SRpnt) { retval = STbp->syscall_result; @@ -1559,7 +1563,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 && (scode == NO_SENSE || scode == RECOVERED_ERROR)) { move_buffer_data(STp->buffer, transfer - undone); - retry_eot = TRUE; + retry_eot = 1; if (STps->drv_block >= 0) { STps->drv_block += (transfer - undone) / STp->block_size; @@ -1630,14 +1634,15 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) Does release user buffer mapping if it is set. */ -static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) +static long read_tape(struct scsi_tape *STp, long count, + struct scsi_request ** aSRpnt) { int transfer, blks, bytes; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; - ST_mode *STm; - ST_partstat *STps; - ST_buffer *STbp; + struct scsi_request *SRpnt; + struct st_modedef *STm; + struct st_partstat *STps; + struct st_buffer *STbp; int retval = 0; char *name = tape_name(STp); @@ -1673,8 +1678,8 @@ static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt) cmd[4] = blks; SRpnt = *aSRpnt; - SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ, - STp->device->timeout, MAX_RETRIES, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE, + STp->device->timeout, MAX_RETRIES, 1); release_buffering(STp); *aSRpnt = SRpnt; if (!SRpnt) @@ -1818,11 +1823,11 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) ssize_t retval = 0; ssize_t i, transfer; int special, do_dio = 0; - Scsi_Request *SRpnt = NULL; - Scsi_Tape *STp = filp->private_data; - ST_mode *STm; - ST_partstat *STps; - ST_buffer *STbp = STp->buffer; + struct scsi_request *SRpnt = NULL; + struct scsi_tape *STp = filp->private_data; + struct st_modedef *STm; + struct st_partstat *STps; + struct st_buffer *STbp = STp->buffer; DEB( char *name = tape_name(STp); ) if (down_interruptible(&STp->lock)) @@ -1852,7 +1857,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) STps->eof, STbp->buffer_bytes); ) /* end DEB */ - retval = setup_buffering(STp, buf, count, TRUE); + retval = setup_buffering(STp, buf, count, 1); if (retval) goto out; do_dio = STbp->do_dio; @@ -1960,7 +1965,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) DEB( /* Set the driver options */ -static void st_log_options(Scsi_Tape * STp, ST_mode * STm, char *name) +static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name) { if (debugging) { printk(KERN_INFO @@ -1983,20 +1988,20 @@ static void st_log_options(Scsi_Tape * STp, ST_mode * STm, char *name) ) -static int st_set_options(Scsi_Tape *STp, long options) +static int st_set_options(struct scsi_tape *STp, long options) { int value; long code; - ST_mode *STm; + struct st_modedef *STm; char *name = tape_name(STp); struct cdev *cd0, *cd1; STm = &(STp->modes[STp->current_mode]); if (!STm->defined) { cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1]; - memcpy(STm, &(STp->modes[0]), sizeof(ST_mode)); + memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef)); STm->cdevs[0] = cd0; STm->cdevs[1] = cd1; - modes_defined = TRUE; + modes_defined = 1; DEBC(printk(ST_DEB_MSG "%s: Initialized mode %d definition from mode 0\n", name, STp->current_mode)); @@ -2065,7 +2070,7 @@ static int st_set_options(Scsi_Tape *STp, long options) DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", name, STm->default_blksize)); if (STp->ready == ST_READY) { - STp->blksize_changed = FALSE; + STp->blksize_changed = 0; set_mode_densblk(STp, STm); } } @@ -2104,7 +2109,7 @@ static int st_set_options(Scsi_Tape *STp, long options) DEBC( printk(KERN_INFO "%s: Density default set to %x\n", name, STm->default_density)); if (STp->ready == ST_READY) { - STp->density_changed = FALSE; + STp->density_changed = 0; set_mode_densblk(STp, STm); } } @@ -2137,7 +2142,7 @@ static int st_set_options(Scsi_Tape *STp, long options) DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", name, (value & 1))); if (STp->ready == ST_READY) { - STp->compression_changed = FALSE; + STp->compression_changed = 0; st_compression(STp, (STm->default_compression == ST_YES)); } } @@ -2171,10 +2176,10 @@ static int st_set_options(Scsi_Tape *STp, long options) /* Read a mode page into the tape buffer. The block descriptors are included if incl_block_descs is true. The page control is ored to the page number parameter, if necessary. */ -static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs) +static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs) { unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt = NULL; + struct scsi_request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SENSE; @@ -2183,8 +2188,8 @@ static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs) cmd[2] = page; cmd[4] = 255; - SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, - STp->device->timeout, 0, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, + STp->device->timeout, 0, 1); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2196,11 +2201,11 @@ static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs) /* Send the mode page in the tape buffer to the drive. Assumes that the mode data in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */ -static int write_mode_page(Scsi_Tape *STp, int page, int slow) +static int write_mode_page(struct scsi_tape *STp, int page, int slow) { int pgo; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt = NULL; + struct scsi_request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; @@ -2214,8 +2219,8 @@ static int write_mode_page(Scsi_Tape *STp, int page, int slow) (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP; (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; - SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, - (slow ? STp->long_timeout : STp->device->timeout), 0, TRUE); + SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, + (slow ? STp->long_timeout : STp->device->timeout), 0, 1); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2242,7 +2247,7 @@ static int write_mode_page(Scsi_Tape *STp, int page, int slow) work without this (suggestion from Michael Schaefer ). Including block descriptors should not cause any harm to other drives. */ -static int st_compression(Scsi_Tape * STp, int state) +static int st_compression(struct scsi_tape * STp, int state) { int retval; int mpoffs; /* Offset to mode page start */ @@ -2253,7 +2258,7 @@ static int st_compression(Scsi_Tape * STp, int state) return (-EIO); /* Read the current page contents */ - retval = read_mode_page(STp, COMPRESSION_PAGE, FALSE); + retval = read_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n", name)); @@ -2282,7 +2287,7 @@ static int st_compression(Scsi_Tape * STp, int state) b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */ } - retval = write_mode_page(STp, COMPRESSION_PAGE, FALSE); + retval = write_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name)); return (-EIO); @@ -2290,19 +2295,19 @@ static int st_compression(Scsi_Tape * STp, int state) DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n", name, state)); - STp->compression_changed = TRUE; + STp->compression_changed = 1; return 0; } /* 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) +static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code) { int retval = (-EIO), timeout; DEB( char *name = tape_name(STp); ) unsigned char cmd[MAX_COMMAND_SIZE]; - ST_partstat *STps; - Scsi_Request *SRpnt; + struct st_partstat *STps; + struct scsi_request *SRpnt; if (STp->ready != ST_READY && !load_code) { if (STp->ready == ST_NO_TAPE) @@ -2339,8 +2344,8 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code) printk(ST_DEB_MSG "%s: Loading tape.\n", name); ); - SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - timeout, MAX_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, + timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2370,17 +2375,17 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code) /* Internal ioctl function */ -static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) +static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg) { int timeout; long ltmp; int ioctl_result; - int chg_eof = TRUE; + int chg_eof = 1; unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; - ST_partstat *STps; + struct scsi_request *SRpnt; + struct st_partstat *STps; int fileno, blkno, at_sm, undone; - int datalen = 0, direction = SCSI_DATA_NONE; + int datalen = 0, direction = DMA_NONE; char *name = tape_name(STp); WARN_ON(STp->buffer->do_dio != 0); @@ -2399,7 +2404,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) memset(cmd, 0, MAX_COMMAND_SIZE); switch (cmd_in) { case MTFSFM: - chg_eof = FALSE; /* Changed from the FSF after this */ + chg_eof = 0; /* Changed from the FSF after this */ case MTFSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2414,7 +2419,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) at_sm &= (arg == 0); break; case MTBSFM: - chg_eof = FALSE; /* Changed from the FSF after this */ + chg_eof = 0; /* Changed from the FSF after this */ case MTBSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2583,7 +2588,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) case MTSETDENSITY: /* Set tape density */ case MTSETDRVBUFFER: /* Set drive buffering */ case SET_DENS_AND_BLK: /* Set density and block size */ - chg_eof = FALSE; + chg_eof = 0; if (STp->dirty || (STp->buffer)->buffer_bytes != 0) return (-EIO); /* Not allowed if data in buffer */ if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) && @@ -2598,7 +2603,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) if ((STp->use_pf & USE_PF)) cmd[1] = MODE_SELECT_PAGE_FORMAT; cmd[4] = datalen = 12; - direction = SCSI_DATA_WRITE; + direction = DMA_TO_DEVICE; memset((STp->buffer)->b_data, 0, 12); if (cmd_in == MTSETDRVBUFFER) @@ -2609,7 +2614,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) (STp->buffer)->b_data[3] = 8; /* block descriptor length */ if (cmd_in == MTSETDENSITY) { (STp->buffer)->b_data[4] = arg; - STp->density_changed = TRUE; /* At least we tried ;-) */ + STp->density_changed = 1; /* At least we tried ;-) */ } else if (cmd_in == SET_DENS_AND_BLK) (STp->buffer)->b_data[4] = arg >> 24; else @@ -2617,7 +2622,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { ltmp = arg & MT_ST_BLKSIZE_MASK; if (cmd_in == MTSETBLK) - STp->blksize_changed = TRUE; /* At least we tried ;-) */ + STp->blksize_changed = 1; /* At least we tried ;-) */ } else ltmp = STp->block_size; (STp->buffer)->b_data[9] = (ltmp >> 16); @@ -2646,7 +2651,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) } SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction, - timeout, MAX_RETRIES, TRUE); + timeout, MAX_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2784,12 +2789,12 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg) /* Get the tape position. If bt == 2, arg points into a kernel space mt_loc structure. */ -static int get_location(Scsi_Tape *STp, unsigned int *block, int *partition, +static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition, int logical) { int result; unsigned char scmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; + struct scsi_request *SRpnt; DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) @@ -2804,8 +2809,8 @@ static int get_location(Scsi_Tape *STp, unsigned int *block, int *partition, if (!logical && !STp->scsi2_logical) scmd[1] = 1; } - SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->device->timeout, - MAX_READY_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE, + STp->device->timeout, MAX_READY_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2844,15 +2849,15 @@ static int get_location(Scsi_Tape *STp, unsigned int *block, int *partition, /* Set the tape block and partition. Negative partition means that only the block should be set in vendor specific way. */ -static int set_location(Scsi_Tape *STp, unsigned int block, int partition, +static int set_location(struct scsi_tape *STp, unsigned int block, int partition, int logical) { - ST_partstat *STps; + struct st_partstat *STps; int result, p; unsigned int blk; int timeout; unsigned char scmd[MAX_COMMAND_SIZE]; - Scsi_Request *SRpnt; + struct scsi_request *SRpnt; DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) @@ -2871,9 +2876,9 @@ static int set_location(Scsi_Tape *STp, unsigned int block, int partition, return (-EINVAL); if (partition != STp->partition) { if (get_location(STp, &blk, &p, 1)) - STps->last_block_valid = FALSE; + STps->last_block_valid = 0; else { - STps->last_block_valid = TRUE; + STps->last_block_valid = 1; STps->last_block_visited = blk; DEBC(printk(ST_DEB_MSG "%s: Visited block %d for partition %d saved.\n", @@ -2909,8 +2914,8 @@ static int set_location(Scsi_Tape *STp, unsigned int block, int partition, timeout = STp->device->timeout; } - SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE, - timeout, MAX_READY_RETRIES, TRUE); + SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE, + timeout, MAX_READY_RETRIES, 1); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2947,7 +2952,7 @@ static int set_location(Scsi_Tape *STp, unsigned int block, int partition, /* Find the current partition number for the drive status. Called from open and returns either partition number of negative error code. */ -static int find_partition(Scsi_Tape *STp) +static int find_partition(struct scsi_tape *STp) { int i, partition; unsigned int block; @@ -2961,9 +2966,9 @@ static int find_partition(Scsi_Tape *STp) /* Change the partition if necessary */ -static int switch_partition(Scsi_Tape *STp) +static int switch_partition(struct scsi_tape *STp) { - ST_partstat *STps; + struct st_partstat *STps; if (STp->partition == STp->new_partition) return 0; @@ -2989,7 +2994,7 @@ static int switch_partition(Scsi_Tape *STp) /* Get the number of partitions on the tape. As a side effect reads the mode page into the tape buffer. */ -static int nbr_partitions(Scsi_Tape *STp) +static int nbr_partitions(struct scsi_tape *STp) { int result; DEB( char *name = tape_name(STp); ) @@ -2997,7 +3002,7 @@ static int nbr_partitions(Scsi_Tape *STp) if (STp->ready != ST_READY) return (-EIO); - result = read_mode_page(STp, PART_PAGE, TRUE); + result = read_mode_page(STp, PART_PAGE, 1); if (result) { DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n", @@ -3032,14 +3037,14 @@ static int nbr_partitions(Scsi_Tape *STp) is acceptable also to some other old drives and enforced if the first partition size field is used for the first additional partition size. */ -static int partition_tape(Scsi_Tape *STp, int size) +static int partition_tape(struct scsi_tape *STp, int size) { char *name = tape_name(STp); int result; int pgo, psd_cnt, psdo; unsigned char *bp; - result = read_mode_page(STp, PART_PAGE, FALSE); + result = read_mode_page(STp, PART_PAGE, 0); if (result) { DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name)); return result; @@ -3082,7 +3087,7 @@ static int partition_tape(Scsi_Tape *STp, int size) bp[pgo + PP_OFF_RESERVED] = 0; bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB; - result = write_mode_page(STp, PART_PAGE, TRUE); + result = write_mode_page(STp, PART_PAGE, 1); if (result) { printk(KERN_INFO "%s: Partitioning of tape failed.\n", name); result = (-EIO); @@ -3100,9 +3105,9 @@ static int st_ioctl(struct inode *inode, struct file *file, int i, cmd_nr, cmd_type, bt; int retval = 0; unsigned int blk; - Scsi_Tape *STp = file->private_data; - ST_mode *STm; - ST_partstat *STps; + struct scsi_tape *STp = file->private_data; + struct st_modedef *STm; + struct st_partstat *STps; char *name = tape_name(STp); void __user *p = (void __user *)arg; @@ -3125,10 +3130,11 @@ static int st_ioctl(struct inode *inode, struct file *file, * may try and take the device offline, in which case all further * access to the device is prohibited. */ - if (!scsi_block_when_processing_errors(STp->device)) { - retval = (-ENXIO); + retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, file); + if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV) goto out; - } + retval = 0; + cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); @@ -3259,7 +3265,7 @@ static int st_ioctl(struct inode *inode, struct file *file, for (i = 0; i < ST_NBR_PARTITIONS; i++) { STp->ps[i].rw = ST_IDLE; STp->ps[i].at_sm = 0; - STp->ps[i].last_block_valid = FALSE; + STp->ps[i].last_block_valid = 0; } STp->partition = STp->new_partition = 0; STp->nbr_partitions = 1; /* Bad guess ?-) */ @@ -3308,7 +3314,7 @@ static int st_ioctl(struct inode *inode, struct file *file, goto out; } - if ((i = flush_buffer(STp, FALSE)) < 0) { + if ((i = flush_buffer(STp, 0)) < 0) { retval = i; goto out; } @@ -3423,18 +3429,18 @@ static int st_ioctl(struct inode *inode, struct file *file, /* Try to allocate a new tape buffer. Calling function must not hold dev_arr_lock. */ -static ST_buffer * +static struct st_buffer * new_tape_buffer(int from_initialization, int need_dma, int max_sg) { int i, priority, got = 0, segs = 0; - ST_buffer *tb; + struct st_buffer *tb; if (from_initialization) priority = GFP_ATOMIC; else priority = GFP_KERNEL; - i = sizeof(ST_buffer) + (max_sg - 1) * sizeof(struct scatterlist) + + i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) + max_sg * sizeof(struct st_buf_fragment); tb = kmalloc(i, priority); if (!tb) { @@ -3448,7 +3454,7 @@ static ST_buffer * tb->b_data = page_address(tb->sg[0].page); tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); - tb->in_use = TRUE; + tb->in_use = 1; tb->dma = need_dma; tb->buffer_size = got; @@ -3457,12 +3463,12 @@ static ST_buffer * /* Try to allocate enough space in the tape buffer */ -static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) +static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma) { int segs, nbr, max_segs, b_size, priority, order, got; if (new_size <= STbuffer->buffer_size) - return TRUE; + return 1; if (STbuffer->buffer_size <= PAGE_SIZE) normalize_buffer(STbuffer); /* Avoid extra segment */ @@ -3470,7 +3476,7 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) max_segs = STbuffer->use_sg; nbr = max_segs - STbuffer->frp_segs; if (nbr <= 0) - return FALSE; + return 0; priority = GFP_KERNEL | __GFP_NOWARN; if (need_dma) @@ -3491,7 +3497,7 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) } DEB(STbuffer->buffer_size = got); normalize_buffer(STbuffer); - return FALSE; + return 0; } STbuffer->frp[segs].length = b_size; STbuffer->frp_segs += 1; @@ -3501,12 +3507,12 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) } STbuffer->b_data = page_address(STbuffer->frp[0].page); - return TRUE; + return 1; } /* Release the extra buffer */ -static void normalize_buffer(ST_buffer * STbuffer) +static void normalize_buffer(struct st_buffer * STbuffer) { int i, order; @@ -3522,7 +3528,7 @@ static void normalize_buffer(ST_buffer * STbuffer) /* Move data from the user buffer to the tape buffer. Returns zero (success) or negative error code. */ -static int append_to_buffer(const char __user *ubp, ST_buffer * st_bp, int do_count) +static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count) { int i, cnt, res, offset; @@ -3553,7 +3559,7 @@ static int append_to_buffer(const char __user *ubp, ST_buffer * st_bp, int do_co /* Move data from the tape buffer to the user buffer. Returns zero (success) or negative error code. */ -static int from_buffer(ST_buffer * st_bp, char __user *ubp, int do_count) +static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count) { int i, cnt, res, offset; @@ -3584,7 +3590,7 @@ static int from_buffer(ST_buffer * st_bp, char __user *ubp, int do_count) /* Move data towards start of buffer */ -static void move_buffer_data(ST_buffer * st_bp, int offset) +static void move_buffer_data(struct st_buffer * st_bp, int offset) { int src_seg, dst_seg, src_offset = 0, dst_offset; int count, total; @@ -3622,7 +3628,7 @@ static void move_buffer_data(ST_buffer * st_bp, int offset) /* Fill the s/g list up to the length required for this transfer */ -static void buf_to_sg(ST_buffer *STbp, unsigned int length) +static void buf_to_sg(struct st_buffer *STbp, unsigned int length) { int i; unsigned int count; @@ -3720,10 +3726,10 @@ static int st_probe(struct device *dev) struct scsi_device *SDp = to_scsi_device(dev); struct gendisk *disk = NULL; struct cdev *cdev = NULL; - Scsi_Tape *tpnt = NULL; - ST_mode *STm; - ST_partstat *STps; - ST_buffer *buffer; + struct scsi_tape *tpnt = NULL; + struct st_modedef *STm; + struct st_partstat *STps; + struct st_buffer *buffer; int i, j, mode, dev_num, error; char *stp; u64 bounce_limit; @@ -3741,9 +3747,10 @@ static int st_probe(struct device *dev) i = SDp->host->sg_tablesize; if (st_max_sg_segs < i) i = st_max_sg_segs; - buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); + buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { - printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); + printk(KERN_ERR + "st: Can't allocate new tape buffer. Device not attached.\n"); goto out; } @@ -3755,7 +3762,7 @@ static int st_probe(struct device *dev) write_lock(&st_dev_arr_lock); if (st_nr_dev >= st_dev_max) { - Scsi_Tape **tmp_da; + struct scsi_tape **tmp_da; int tmp_dev_max; tmp_dev_max = max(st_nr_dev * 2, 8); @@ -3768,17 +3775,17 @@ static int st_probe(struct device *dev) goto out_put_disk; } - tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC); + tmp_da = kmalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC); if (tmp_da == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't extend device array.\n"); goto out_put_disk; } - memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *)); + memset(tmp_da, 0, tmp_dev_max * sizeof(struct scsi_tape *)); if (scsi_tapes != NULL) { memcpy(tmp_da, scsi_tapes, - st_dev_max * sizeof(Scsi_Tape *)); + st_dev_max * sizeof(struct scsi_tape *)); kfree(scsi_tapes); } scsi_tapes = tmp_da; @@ -3792,13 +3799,13 @@ static int st_probe(struct device *dev) if (i >= st_dev_max) panic("scsi_devices corrupt (st)"); - tpnt = kmalloc(sizeof(Scsi_Tape), GFP_ATOMIC); + tpnt = kmalloc(sizeof(struct scsi_tape), GFP_ATOMIC); if (tpnt == NULL) { write_unlock(&st_dev_arr_lock); printk(KERN_ERR "st: Can't allocate device descriptor.\n"); goto out_put_disk; } - memset(tpnt, 0, sizeof(Scsi_Tape)); + memset(tpnt, 0, sizeof(struct scsi_tape)); tpnt->disk = disk; sprintf(disk->disk_name, "st%d", i); disk->private_data = &tpnt->driver; @@ -3844,7 +3851,7 @@ static int st_probe(struct device *dev) for (i = 0; i < ST_NBR_MODES; i++) { STm = &(tpnt->modes[i]); - STm->defined = FALSE; + STm->defined = 0; STm->sysv = ST_SYSV; STm->defaults_for_writes = 0; STm->do_async_writes = ST_ASYNC_WRITES; @@ -3860,16 +3867,16 @@ static int st_probe(struct device *dev) STps->rw = ST_IDLE; STps->eof = ST_NOEOF; STps->at_sm = 0; - STps->last_block_valid = FALSE; + STps->last_block_valid = 0; STps->drv_block = (-1); STps->drv_file = (-1); } tpnt->current_mode = 0; - tpnt->modes[0].defined = TRUE; + tpnt->modes[0].defined = 1; tpnt->density_changed = tpnt->compression_changed = - tpnt->blksize_changed = FALSE; + tpnt->blksize_changed = 0; init_MUTEX(&tpnt->lock); st_nr_dev++; @@ -3961,8 +3968,8 @@ out: static int st_remove(struct device *dev) { - Scsi_Device *SDp = to_scsi_device(dev); - Scsi_Tape *tpnt; + struct scsi_device *SDp = to_scsi_device(dev); + struct scsi_tape *tpnt; int i, j, mode; write_lock(&st_dev_arr_lock); @@ -4136,7 +4143,7 @@ static void do_remove_driverfs_files(void) /* The sysfs simple class interface */ static ssize_t st_defined_show(struct class_device *class_dev, char *buf) { - ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); ssize_t l = 0; l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined); @@ -4147,7 +4154,7 @@ CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL); static ssize_t st_defblk_show(struct class_device *class_dev, char *buf) { - ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); ssize_t l = 0; l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize); @@ -4158,7 +4165,7 @@ CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL); static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf) { - ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); ssize_t l = 0; char *fmt; @@ -4171,7 +4178,7 @@ CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL); static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) { - ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); ssize_t l = 0; l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1); @@ -4180,7 +4187,7 @@ static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); -static void do_create_class_files(Scsi_Tape *STp, int dev_num, int mode) +static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) { int i, rew, error; char name[10]; @@ -4253,7 +4260,7 @@ static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pag return nr_pages; out_unmap: - sgl_unmap_user_pages(sgl, nr_pages, FALSE); + sgl_unmap_user_pages(sgl, nr_pages, 0); return 0; } diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 56ca7a785..0e6dd5d68 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -2,13 +2,11 @@ #ifndef _ST_H #define _ST_H -#ifndef _SCSI_H -#include "scsi.h" -#endif #include + /* The tape buffer descriptor. */ -typedef struct { +struct st_buffer { unsigned char in_use; unsigned char dma; /* DMA-able buffer */ unsigned char do_dio; /* direct i/o set up? */ @@ -19,7 +17,7 @@ typedef struct { int writing; int midlevel_result; int syscall_result; - Scsi_Request *last_SRpnt; + struct scsi_request *last_SRpnt; unsigned char *b_data; unsigned short use_sg; /* zero or max number of s/g segments for this adapter */ unsigned short sg_segs; /* number of segments in s/g list */ @@ -28,7 +26,7 @@ typedef struct { unsigned int frp_sg_current; /* driver buffer length currently in s/g list */ struct st_buf_fragment *frp; /* the allocated buffer fragment list */ struct scatterlist sg[1]; /* MUST BE last item */ -} ST_buffer; +}; /* The tape buffer fragment descriptor */ struct st_buf_fragment { @@ -37,7 +35,7 @@ struct st_buf_fragment { }; /* The tape mode definition */ -typedef struct { +struct st_modedef { unsigned char defined; unsigned char sysv; /* SYS V semantics? */ unsigned char do_async_writes; @@ -48,7 +46,7 @@ typedef struct { short default_density; /* Forced density, -1 = no value */ int default_blksize; /* Forced blocksize, -1 = no value */ struct cdev *cdevs[2]; /* Auto-rewind and non-rewind devices */ -} ST_mode; +}; /* Number of modes can be changed by changing ST_NBR_MODE_BITS. The maximum number of modes is 16 (ST_NBR_MODE_BITS 4) */ @@ -61,7 +59,7 @@ typedef struct { #define ST_MAX_TAPE_ENTRIES (ST_MAX_TAPES << (ST_NBR_MODE_BITS + 1)) /* The status related to each partition */ -typedef struct { +struct st_partstat { unsigned char rw; unsigned char eof; unsigned char at_sm; @@ -69,17 +67,17 @@ typedef struct { u32 last_block_visited; int drv_block; /* The block where the drive head is */ int drv_file; -} ST_partstat; +}; #define ST_NBR_PARTITIONS 4 /* The tape drive descriptor */ -typedef struct { +struct scsi_tape { struct scsi_driver *driver; - Scsi_Device *device; + struct scsi_device *device; struct semaphore lock; /* For serialization */ struct completion wait; /* For SCSI commands */ - ST_buffer *buffer; + struct st_buffer *buffer; /* Drive characteristics */ unsigned char omit_blklims; @@ -105,14 +103,14 @@ typedef struct { unsigned long max_pfn; /* the maximum page number reachable by the HBA */ /* Mode characteristics */ - ST_mode modes[ST_NBR_MODES]; + struct st_modedef modes[ST_NBR_MODES]; int current_mode; /* Status variables */ int partition; int new_partition; int nbr_partitions; /* zero until partition support enabled */ - ST_partstat ps[ST_NBR_PARTITIONS]; + struct st_partstat ps[ST_NBR_PARTITIONS]; unsigned char dirty; unsigned char ready; unsigned char write_prot; @@ -146,7 +144,7 @@ typedef struct { unsigned char last_sense[16]; #endif struct gendisk *disk; -} Scsi_Tape; +}; /* Bit masks for use_pf */ #define USE_PF 1 diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index f1070c80a..e3ea99f23 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -107,17 +107,17 @@ static inline unsigned char sun3scsi_read(int reg); static inline void sun3scsi_write(int reg, int value); static int setup_can_queue = -1; -MODULE_PARM(setup_can_queue, "i"); +module_param(setup_can_queue, int, 0); static int setup_cmd_per_lun = -1; -MODULE_PARM(setup_cmd_per_lun, "i"); +module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; -MODULE_PARM(setup_sg_tablesize, "i"); +module_param(setup_sg_tablesize, int, 0); #ifdef SUPPORT_TAGS static int setup_use_tagged_queuing = -1; -MODULE_PARM(setup_use_tagged_queuing, "i"); +module_param(setup_use_tagged_queuing, int, 0); #endif static int setup_hostid = -1; -MODULE_PARM(setup_hostid, "i"); +module_param(setup_hostid, int, 0); static Scsi_Cmnd *sun3_dma_setup_done = NULL; diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index 4cf3e2e7d..9acb5ddeb 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -72,17 +72,17 @@ static inline unsigned char sun3scsi_read(int reg); static inline void sun3scsi_write(int reg, int value); static int setup_can_queue = -1; -MODULE_PARM(setup_can_queue, "i"); +module_param(setup_can_queue, int, 0); static int setup_cmd_per_lun = -1; -MODULE_PARM(setup_cmd_per_lun, "i"); +module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; -MODULE_PARM(setup_sg_tablesize, "i"); +module_param(setup_sg_tablesize, int, 0); #ifdef SUPPORT_TAGS static int setup_use_tagged_queuing = -1; -MODULE_PARM(setup_use_tagged_queuing, "i"); +module_param(setup_use_tagged_queuing, int, 0); #endif static int setup_hostid = -1; -MODULE_PARM(setup_hostid, "i"); +module_param(setup_hostid, int, 0); static Scsi_Cmnd *sun3_dma_setup_done = NULL; diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index f2b934cd9..5d1dc0e8b 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -370,7 +370,7 @@ static int sun3x_esp_release(struct Scsi_Host *instance) } static Scsi_Host_Template driver_template = { - .proc_name = "esp", + .proc_name = "sun3x_esp", .proc_info = &esp_proc_info, .name = "Sun ESP 100/100a/200", .detect = sun3x_esp_detect, diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index de5cc5912..f43ebddf4 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -852,10 +852,10 @@ static int sym53c416_bios_param(struct scsi_device *sdev, MODULE_AUTHOR("Lieven Willems"); MODULE_LICENSE("GPL"); -MODULE_PARM(sym53c416, "1-2i"); -MODULE_PARM(sym53c416_1, "1-2i"); -MODULE_PARM(sym53c416_2, "1-2i"); -MODULE_PARM(sym53c416_3, "1-2i"); +module_param_array(sym53c416, uint, NULL, 0); +module_param_array(sym53c416_1, uint, NULL, 0); +module_param_array(sym53c416_2, uint, NULL, 0); +module_param_array(sym53c416_3, uint, NULL, 0); #endif diff --git a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h index fc81e413e..6bc75a391 100644 --- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h +++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM53C8XX_H @@ -81,7 +68,6 @@ */ #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 @@ -142,9 +128,7 @@ struct sym_driver_setup { u_char scsi_bus_check; u_char host_id; - u_char reverse_probe; u_char verbose; - u_short debug; u_char settle_delay; u_char use_nvram; u_long excludes[8]; @@ -158,6 +142,7 @@ struct sym_driver_setup { #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 boot_verbose sym_driver_setup.verbose /* Always enable parity. */ #define SYM_SETUP_PCI_PARITY 1 @@ -176,54 +161,13 @@ struct sym_driver_setup { .irq_mode = 0, \ .scsi_bus_check = 1, \ .host_id = 7, \ - .reverse_probe = 0, \ .verbose = 0, \ - .debug = 0, \ .settle_delay = 3, \ .use_nvram = 1, \ } -/* - * Boot fail safe setup. - * - * Override initial setup from boot command line: - * sym53c8xx=safe:y - */ -#define SYM_LINUX_DRIVER_SAFE_SETUP { \ - .max_tag = 0, \ - .burst_order = 0, \ - .scsi_led = 0, \ - .scsi_diff = 1, \ - .irq_mode = 0, \ - .scsi_bus_check = 2, \ - .host_id = 7, \ - .reverse_probe = 0, \ - .verbose = 2, \ - .debug = 0, \ - .settle_delay = 10, \ - .use_nvram = 1, \ -} - -/* - * 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 +extern unsigned int sym_debug_flags; #define DEBUG_FLAGS sym_debug_flags -#endif -#define boot_verbose sym_driver_setup.verbose #endif /* SYM53C8XX_H */ diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h index e54790812..b0f58e725 100644 --- a/drivers/scsi/sym53c8xx_2/sym_conf.h +++ b/drivers/scsi/sym53c8xx_2/sym_conf.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_CONF_H diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h index 1241104b6..2e1d89f5d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_defs.h +++ b/drivers/scsi/sym53c8xx_2/sym_defs.h @@ -22,61 +22,46 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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 */ #ifndef SYM_DEFS_H #define SYM_DEFS_H -/* - * Vendor. - */ -#define PCI_VENDOR_NCR 0x1000 +#define SYM_VERSION "2.1.18m" +#define SYM_DRIVER_NAME "sym-" SYM_VERSION /* * 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_33 0x20 -#define PCI_ID_LSI53C1010_66 0x21 -#define PCI_ID_LSI53C1510D 0xa +#define PCI_ID_SYM53C810 PCI_DEVICE_ID_NCR_53C810 +#define PCI_ID_SYM53C810AP PCI_DEVICE_ID_LSI_53C810AP +#define PCI_ID_SYM53C815 PCI_DEVICE_ID_NCR_53C815 +#define PCI_ID_SYM53C820 PCI_DEVICE_ID_NCR_53C820 +#define PCI_ID_SYM53C825 PCI_DEVICE_ID_NCR_53C825 +#define PCI_ID_SYM53C860 PCI_DEVICE_ID_NCR_53C860 +#define PCI_ID_SYM53C875 PCI_DEVICE_ID_NCR_53C875 +#define PCI_ID_SYM53C875_2 PCI_DEVICE_ID_NCR_53C875J +#define PCI_ID_SYM53C885 PCI_DEVICE_ID_NCR_53C885 +#define PCI_ID_SYM53C895 PCI_DEVICE_ID_NCR_53C895 +#define PCI_ID_SYM53C896 PCI_DEVICE_ID_NCR_53C896 +#define PCI_ID_SYM53C895A PCI_DEVICE_ID_LSI_53C895A +#define PCI_ID_SYM53C875A PCI_DEVICE_ID_LSI_53C875A +#define PCI_ID_LSI53C1010_33 PCI_DEVICE_ID_LSI_53C1010_33 +#define PCI_ID_LSI53C1010_66 PCI_DEVICE_ID_LSI_53C1010_66 +#define PCI_ID_LSI53C1510D PCI_DEVICE_ID_LSI_53C1510 /* * SYM53C8XX device features descriptor. @@ -773,33 +758,32 @@ struct sym_tblsel { * 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_COMPLETE COMMAND_COMPLETE +#define M_EXTENDED EXTENDED_MESSAGE +#define M_SAVE_DP SAVE_POINTERS +#define M_RESTORE_DP RESTORE_POINTERS +#define M_DISCONNECT DISCONNECT +#define M_ID_ERROR INITIATOR_ERROR +#define M_ABORT ABORT +#define M_REJECT MESSAGE_REJECT +#define M_NOOP NOP +#define M_PARITY MSG_PARITY_ERROR +#define M_LCOMPLETE LINKED_CMD_COMPLETE +#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE +#define M_RESET BUS_DEVICE_RESET #define M_ABORT_TAG (0x0d) #define M_CLEAR_QUEUE (0x0e) -#define M_INIT_REC (0x0f) -#define M_REL_REC (0x10) +#define M_INIT_REC INITIATE_RECOVERY +#define M_REL_REC RELEASE_RECOVERY #define M_TERMINATE (0x11) -#define M_SIMPLE_TAG (0x20) -#define M_HEAD_TAG (0x21) -#define M_ORDERED_TAG (0x22) +#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG +#define M_HEAD_TAG HEAD_OF_QUEUE_TAG +#define M_ORDERED_TAG ORDERED_QUEUE_TAG #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_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER +#define M_X_SYNC_REQ EXTENDED_SDTR +#define M_X_WIDE_REQ EXTENDED_WDTR #define M_X_PPR_REQ (0x04) /* @@ -814,15 +798,15 @@ struct sym_tblsel { * 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_GOOD SAM_STAT_GOOD +#define S_CHECK_COND SAM_STAT_CHECK_CONDITION +#define S_COND_MET SAM_STAT_CONDITION_MET +#define S_BUSY SAM_STAT_BUSY +#define S_INT SAM_STAT_INTERMEDIATE +#define S_INT_COND_MET SAM_STAT_INTERMEDIATE_CONDITION_MET +#define S_CONFLICT SAM_STAT_RESERVATION_CONFLICT +#define S_TERMINATED SAM_STAT_COMMAND_TERMINATED +#define S_QUEUE_FULL SAM_STAT_TASK_SET_FULL #define S_ILLEGAL (0xff) #endif /* defined SYM_DEFS_H */ diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index 0c9eb07a1..c30d5cd65 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifdef __FreeBSD__ @@ -411,7 +398,6 @@ void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len) if (opcode == 0) { printf ("%s: ERROR0 IN SCRIPT at %d.\n", sym_name(np), (int) (cur-start)); - MDELAY (10000); ++cur; continue; }; @@ -455,7 +441,6 @@ void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len) 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 diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h index 59333f42b..43f6810a4 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_FW_H diff --git a/drivers/scsi/sym53c8xx_2/sym_fw1.h b/drivers/scsi/sym53c8xx_2/sym_fw1.h index afb3309b9..cdd92d82f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw1.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw1.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ /* diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h index 025f266a8..7ea7151f5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw2.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ /* diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 22238315d..4c64761be 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -3,6 +3,7 @@ * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier + * Copyright (c) 2003-2004 Matthew Wilcox * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier @@ -22,39 +23,25 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ -#define SYM_GLUE_C - #include #include #include #include +#include #include #include #include @@ -68,6 +55,77 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" +struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP; +unsigned int sym_debug_flags = 0; + +static char *excl_string; +static char *safe_string; +module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0); +module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0); +module_param_named(burst, sym_driver_setup.burst_order, byte, 0); +module_param_named(led, sym_driver_setup.scsi_led, byte, 0); +module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0); +module_param_named(irqm, sym_driver_setup.irq_mode, byte, 0); +module_param_named(buschk, sym_driver_setup.scsi_bus_check, byte, 0); +module_param_named(hostid, sym_driver_setup.host_id, byte, 0); +module_param_named(verb, sym_driver_setup.verbose, byte, 0); +module_param_named(debug, sym_debug_flags, uint, 0); +module_param_named(settle, sym_driver_setup.settle_delay, byte, 0); +module_param_named(nvram, sym_driver_setup.use_nvram, byte, 0); +module_param_named(excl, excl_string, charp, 0); +module_param_named(safe, safe_string, charp, 0); + +MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default"); +MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN"); +MODULE_PARM_DESC(burst, "Maximum burst. 0 to disable, 255 to read from registers"); +MODULE_PARM_DESC(led, "Set to 1 to enable LED support"); +MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3"); +MODULE_PARM_DESC(irqm, "0 for open drain, 1 to leave alone, 2 for totem pole"); +MODULE_PARM_DESC(buschk, "0 to not check, 1 for detach on error, 2 for warn on error"); +MODULE_PARM_DESC(hostid, "The SCSI ID to use for the host adapters"); +MODULE_PARM_DESC(verb, "0 for minimal verbosity, 1 for normal, 2 for excessive"); +MODULE_PARM_DESC(debug, "Set bits to enable debugging"); +MODULE_PARM_DESC(settle, "Settle delay in seconds. Default 3"); +MODULE_PARM_DESC(nvram, "Option currently not used"); +MODULE_PARM_DESC(excl, "List ioport addresses here to prevent controllers from being attached"); +MODULE_PARM_DESC(safe, "Set other settings to a \"safe mode\""); + +MODULE_LICENSE("GPL"); +MODULE_VERSION(SYM_VERSION); +MODULE_AUTHOR("Matthew Wilcox "); +MODULE_DESCRIPTION("NCR, Symbios and LSI 8xx and 1010 PCI SCSI adapters"); + +static void sym2_setup_params(void) +{ + char *p = excl_string; + int xi = 0; + + while (p && (xi < 8)) { + char *next_p; + int val = (int) simple_strtoul(p, &next_p, 0); + sym_driver_setup.excludes[xi++] = val; + p = next_p; + } + + if (safe_string) { + if (*safe_string == 'y') { + sym_driver_setup.max_tag = 0; + sym_driver_setup.burst_order = 0; + sym_driver_setup.scsi_led = 0; + sym_driver_setup.scsi_diff = 1; + sym_driver_setup.irq_mode = 0; + sym_driver_setup.scsi_bus_check = 2; + sym_driver_setup.host_id = 7; + sym_driver_setup.verbose = 2; + sym_driver_setup.settle_delay = 10; + sym_driver_setup.use_nvram = 1; + } else if (*safe_string != 'n') { + printk(KERN_WARNING NAME53C8XX "Ignoring parameter %s" + " passed to safe option", safe_string); + } + } +} + static int __devinit pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) { @@ -142,19 +200,12 @@ m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m) return b; } -/* - * Driver host data structure. - */ -struct host_data { - struct sym_hcb *ncb; -}; - /* * 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 completion done; struct timer_list timer; void (*old_done)(struct scsi_cmnd *); int to_do; @@ -165,7 +216,6 @@ struct sym_eh_wait { * 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 */ dma_addr_t data_mapping; u_char data_mapped; struct sym_eh_wait *eh_wait; @@ -220,53 +270,17 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) return use_sg; } -static void __sync_scsi_data_for_cpu(struct pci_dev *pdev, struct scsi_cmnd *cmd) -{ - int dma_dir = cmd->sc_data_direction; - - switch(SYM_UCMD_PTR(cmd)->data_mapped) { - case 2: - pci_dma_sync_sg_for_cpu(pdev, cmd->buffer, cmd->use_sg, dma_dir); - break; - case 1: - pci_dma_sync_single_for_cpu(pdev, SYM_UCMD_PTR(cmd)->data_mapping, - cmd->request_bufflen, dma_dir); - break; - } -} - -static void __sync_scsi_data_for_device(struct pci_dev *pdev, struct scsi_cmnd *cmd) -{ - int dma_dir = cmd->sc_data_direction; - - switch(SYM_UCMD_PTR(cmd)->data_mapped) { - case 2: - pci_dma_sync_sg_for_device(pdev, cmd->buffer, cmd->use_sg, dma_dir); - break; - case 1: - pci_dma_sync_single_for_device(pdev, SYM_UCMD_PTR(cmd)->data_mapping, - cmd->request_bufflen, dma_dir); - break; - } -} - #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_for_cpu(np, cmd) \ - __sync_scsi_data_for_cpu(np->s.device, cmd) -#define sync_scsi_data_for_device(np, cmd) \ - __sync_scsi_data_for_device(np->s.device, cmd) - /* * Complete a pending CAM CCB. */ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb) { - sym_remque(&SYM_UCMD_PTR(ccb)->link_cmdq); unmap_scsi_data(np, ccb); ccb->scsi_done(ccb); } @@ -416,27 +430,6 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) } -/* - * Called on successfull INQUIRY response. - */ -void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid) -{ - int retv; - - if (!cmd || cmd->use_sg) - return; - - sync_scsi_data_for_cpu(np, cmd); - retv = __sym_sniff_inquiry(np, cmd->device->id, cmd->device->lun, - (u_char *) cmd->request_buffer, - cmd->request_bufflen - resid); - sync_scsi_data_for_device(np, cmd); - if (retv < 0) - return; - else if (retv) - sym_update_trans_settings(np, &np->target[cmd->device->id]); -} - /* * Build the scatter/gather array for an I/O. */ @@ -636,7 +629,6 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct switch (cp->cdb_buf[0]) { case 0x0A: case 0x2A: case 0xAA: panic("XXXXXXXXXXXXX WRITE NOT YET ALLOWED XXXXXXXXXXXXXX\n"); - MDELAY(10000); break; default: break; @@ -724,30 +716,6 @@ void sym_log_bus_error(struct sym_hcb *np) } } - -/* - * Requeue awaiting commands. - */ -static void sym_requeue_awaiting_cmds(struct sym_hcb *np) -{ - struct scsi_cmnd *cmd; - struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd); - SYM_QUEHEAD tmp_cmdq; - int sts; - - sym_que_move(&np->s.wait_cmdq, &tmp_cmdq); - - while ((ucp = (struct sym_ucmd *) 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); - } - } -} - /* * queuecommand method. Entered with the host adapter lock held and * interrupts disabled. @@ -775,18 +743,12 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, } } - 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; - } + if (np->s.settle_time_valid) + return SCSI_MLQUEUE_HOST_BUSY; - 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: + if (sts) + return SCSI_MLQUEUE_HOST_BUSY; return 0; } @@ -801,15 +763,7 @@ static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); spin_lock_irqsave(np->s.host->host_lock, flags); - sym_interrupt(np); - - /* - * push queue walk-through to tasklet - */ - if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid) - sym_requeue_awaiting_cmds(np); - spin_unlock_irqrestore(np->s.host->host_lock, flags); if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n"); @@ -826,12 +780,7 @@ static void sym53c8xx_timer(unsigned long npref) unsigned long flags; spin_lock_irqsave(np->s.host->host_lock, flags); - sym_timer(np); - - if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid) - sym_requeue_awaiting_cmds(np); - spin_unlock_irqrestore(np->s.host->host_lock, flags); } @@ -873,7 +822,7 @@ static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out) /* Wake up the eh thread if it wants to sleep */ if (ep->to_do == SYM_EH_DO_WAIT) - up(&ep->sem); + complete(&ep->done); } /* @@ -909,14 +858,6 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) 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) { struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); @@ -933,7 +874,7 @@ prepare: case SYM_EH_DO_IGNORE: break; case SYM_EH_DO_WAIT: - init_MUTEX_LOCKED(&ep->sem); + init_completion(&ep->done); /* fall through */ case SYM_EH_DO_COMPLETE: ep->old_done = cmd->scsi_done; @@ -984,7 +925,7 @@ prepare: ep->timed_out = 1; /* Be pessimistic for once :) */ add_timer(&ep->timer); spin_unlock_irq(np->s.host->host_lock); - down(&ep->sem); + wait_for_completion(&ep->done); spin_lock_irq(np->s.host->host_lock); if (ep->timed_out) sts = -2; @@ -1048,7 +989,6 @@ static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_shor } } -#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT /* * Linux select queue depths function */ @@ -1101,9 +1041,6 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun) } 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. @@ -1118,12 +1055,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device) 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); + tp->sdev = device; /* * Allocate the LCB if not yet. @@ -1163,7 +1095,8 @@ static int sym53c8xx_slave_configure(struct scsi_device *device) lp->s.scdev_depth = depth_to_use; sym_tune_dev_queuing(np, device->id, device->lun, reqtags); - spi_dv_device(device); + if (!spi_initial_dv(device->sdev_target)) + spi_dv_device(device); return 0; } @@ -1243,7 +1176,7 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc) 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.options = PPR_OPT_MASK; tp->tinfo.goal.width = 1; tp->tinfo.goal.period = uc->data; tp->tinfo.goal.offset = np->maxoffs_dt; @@ -1810,12 +1743,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, if (sym_reset_scsi_bus(np, 0)) goto reset_failed; - /* - * Initialize some queue headers. - */ - sym_que_init(&np->s.wait_cmdq); - sym_que_init(&np->s.busy_cmdq); - /* * Start the SCRIPTS. */ @@ -1907,178 +1834,14 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp) } #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; /* command line passed by insmod */ -MODULE_PARM(sym53c8xx, "s"); -#endif - -#define OPT_MAX_TAG 1 -#define OPT_BURST_ORDER 2 -#define OPT_SCSI_LED 3 -#define OPT_SCSI_DIFF 4 -#define OPT_IRQ_MODE 5 -#define OPT_SCSI_BUS_CHECK 6 -#define OPT_HOST_ID 7 -#define OPT_REVERSE_PROBE 8 -#define OPT_VERBOSE 9 -#define OPT_DEBUG 10 -#define OPT_SETTLE_DELAY 11 -#define OPT_USE_NVRAM 12 -#define OPT_EXCLUDE 13 -#define OPT_SAFE_SETUP 14 - -static char setup_token[] __initdata = - "tags:" "burst:" - "led:" "diff:" - "irqm:" "buschk:" - "hostid:" "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; - unsigned 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(BURST_ORDER, burst_order) - __SIMPLE_OPTION(SCSI_LED, scsi_led) - __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(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; -} - -#ifndef MODULE -__setup("sym53c8xx=", sym53c8xx_setup); -#endif - -/* - * Read and check the PCI configuration for any detected NCR - * boards and save data for attaching after all boards have - * been detected. - */ -static int __devinit -sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) +static int __devinit sym_check_supported(struct sym_device *device) { struct sym_pci_chip *chip; - u_long base, base_2; - u_long base_c, base_2_c, io_port; - int i; - u_short device_id, status_reg; + struct pci_dev *pdev = device->pdev; u_char revision; - - /* Choose some short name for this device */ - sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - - device_id = pdev->device; - - io_port = pdev->resource[0].start; - - base_c = pdev->resource[1].start; - i = pci_get_base_address(pdev, 1, &base); - - base_2_c = pdev->resource[i].start; - pci_get_base_address(pdev, i, &base_2); - - base &= PCI_BASE_ADDRESS_MEM_MASK; - base_2 &= PCI_BASE_ADDRESS_MEM_MASK; - - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + unsigned long io_port = device->s.io_port; + unsigned long base = device->s.base; + int i; /* * If user excluded this chip, do not initialize it. @@ -2086,19 +1849,10 @@ sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) if (io_port) { for (i = 0 ; i < 8 ; i++) { if (sym_driver_setup.excludes[i] == io_port) - return -1; + return -ENODEV; } } - /* - * 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. * XXX: can this still happen with Linux 2.6's PCI layer? @@ -2107,66 +1861,84 @@ sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) if (!io_port) { printf_info("%s: IO base address disabled.\n", sym_name(device)); - return -1; + return -ENODEV; } #else if (!base) { printf_info("%s: MMIO base address disabled.\n", sym_name(device)); - return -1; + return -ENODEV; } #endif /* - * Ignore Symbios chips controlled by various RAID controllers. - * These controllers set value 0x52414944 at RAM end - 16. + * Check if the chip is supported. Then copy the chip description + * to our device structure so we can make it match the actual device + * and options. */ -#if defined(__i386__) - if (base_2_c) { - unsigned int ram_size, ram_val; - void *ram_ptr; - - if (chip->features & FE_RAM8K) - ram_size = 8192; - else - ram_size = 4096; - - ram_ptr = ioremap(base_2_c, ram_size); - if (ram_ptr) { - ram_val = readl_raw(ram_ptr + ram_size - 16); - iounmap(ram_ptr); - if (ram_val == 0x52414944) { - printf_info("%s: not initializing, " - "driven by RAID controller.\n", - sym_name(device)); - return -1; - } - } + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + chip = sym_lookup_pci_chip_table(pdev->device, revision); + if (!chip) { + printf_info("%s: device not supported\n", sym_name(device)); + return -ENODEV; } -#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. - */ memcpy(&device->chip, chip, sizeof(device->chip)); device->chip.revision_id = revision; + return 0; +} + +/* + * Ignore Symbios chips controlled by various RAID controllers. + * These controllers set value 0x52414944 at RAM end - 16. + */ +static int __devinit sym_check_raid(struct sym_device *device) +{ + unsigned long base_2_c = device->s.base_2_c; + unsigned int ram_size, ram_val; + void __iomem *ram_ptr; + + if (!base_2_c) + return 0; + + if (device->chip.features & FE_RAM8K) + ram_size = 8192; + else + ram_size = 4096; + + ram_ptr = ioremap(base_2_c, ram_size); + if (!ram_ptr) + return 0; + + ram_val = readl(ram_ptr + ram_size - 16); + iounmap(ram_ptr); + if (ram_val != 0x52414944) + return 0; + + printf_info("%s: not initializing, driven by RAID controller.\n", + sym_name(device)); + return -ENODEV; +} + +static int __devinit sym_set_workarounds(struct sym_device *device) +{ + struct sym_pci_chip *chip = &device->chip; + struct pci_dev *pdev = device->pdev; + u_short status_reg; + /* - * 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) { + if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && chip->revision_id < 0x4) { chip->features |= (FE_WRIE | FE_CLSE); } /* If the chip can do Memory Write Invalidate, enable it */ if (chip->features & FE_WRIE) { if (pci_set_mwi(pdev)) - return -1; + return -ENODEV; } /* @@ -2192,20 +1964,39 @@ sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) } } - /* - * Initialise device structure with items required by sym_attach. - */ - device->pdev = 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 = pdev->irq; - return 0; } +/* + * Read and check the PCI configuration for any detected NCR + * boards and save data for attaching after all boards have + * been detected. + */ +static void __devinit +sym_init_device(struct pci_dev *pdev, struct sym_device *device) +{ + unsigned long base, base_2; + int i; + + device->host_id = SYM_SETUP_HOST_ID; + device->pdev = pdev; + device->s.irq = pdev->irq; + + /* Choose some short name for this device */ + sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + device->s.io_port = pdev->resource[0].start; + + device->s.base_c = pdev->resource[1].start; + i = pci_get_base_address(pdev, 1, &base); + device->s.base = base & PCI_BASE_ADDRESS_MEM_MASK; + + device->s.base_2_c = pdev->resource[i].start; + pci_get_base_address(pdev, i, &base_2); + device->s.base_2 = base_2 & PCI_BASE_ADDRESS_MEM_MASK; +} + /* * The NCR PQS and PDS cards are constructed as a DEC bridge * behind which sits a proprietary NCR memory controller and @@ -2222,9 +2013,9 @@ sym53c8xx_pci_init(struct pci_dev *pdev, struct sym_device *device) void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev) { int slot; + u8 tmp; for (slot = 0; slot < 256; slot++) { - u8 tmp; struct pci_dev *memc = pci_get_slot(pdev->bus, slot); if (!memc || memc->vendor != 0x101a || memc->device == 0x0009) { @@ -2232,28 +2023,26 @@ void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev) continue; } - /* - * We set these bits in the memory controller once per 875. - * This isn't a problem in practice. - */ - /* bit 1: allow individual 875 configuration */ pci_read_config_byte(memc, 0x44, &tmp); - tmp |= 0x2; - pci_write_config_byte(memc, 0x44, tmp); + if ((tmp & 0x2) == 0) { + tmp |= 0x2; + pci_write_config_byte(memc, 0x44, tmp); + } /* bit 2: drive individual 875 interrupts to the bus */ pci_read_config_byte(memc, 0x45, &tmp); - tmp |= 0x4; - pci_write_config_byte(memc, 0x45, tmp); - - pci_read_config_byte(pdev, 0x84, &tmp); - sym_dev->host_id = tmp; + if ((tmp & 0x4) == 0) { + tmp |= 0x4; + pci_write_config_byte(memc, 0x45, tmp); + } pci_dev_put(memc); - break; } + + pci_read_config_byte(pdev, 0x84, &tmp); + sym_dev->host_id = tmp; } /* @@ -2282,8 +2071,6 @@ static int sym_detach(struct sym_hcb *np) return 1; } -MODULE_LICENSE("Dual BSD/GPL"); - /* * Driver host template. */ @@ -2318,15 +2105,21 @@ static int __devinit sym2_probe(struct pci_dev *pdev, memset(&nvram, 0, sizeof(nvram)); if (pci_enable_device(pdev)) - return -ENODEV; + goto leave; pci_set_master(pdev); if (pci_request_regions(pdev, NAME53C8XX)) goto disable; - sym_dev.host_id = SYM_SETUP_HOST_ID; - if (sym53c8xx_pci_init(pdev, &sym_dev)) + sym_init_device(pdev, &sym_dev); + if (sym_check_supported(&sym_dev)) + goto free; + + if (sym_check_raid(&sym_dev)) + goto leave; /* Don't disable the device */ + + if (sym_set_workarounds(&sym_dev)) goto free; sym_config_pqs(pdev, &sym_dev); @@ -2351,6 +2144,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev, pci_release_regions(pdev); disable: pci_disable_device(pdev); + leave: return -ENODEV; } @@ -2370,104 +2164,156 @@ static void __devexit sym2_remove(struct pci_dev *pdev) attach_count--; } -static void sym2_get_offset(struct scsi_device *sdev) +static void sym2_get_signalling(struct Scsi_Host *shost) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + enum spi_signal_type type; - spi_offset(sdev) = tp->tinfo.curr.offset; + switch (np->scsi_mode) { + case SMODE_SE: + type = SPI_SIGNAL_SE; + break; + case SMODE_LVD: + type = SPI_SIGNAL_LVD; + break; + case SMODE_HVD: + type = SPI_SIGNAL_HVD; + break; + default: + type = SPI_SIGNAL_UNKNOWN; + break; + } + spi_signalling(shost) = type; } -static void sym2_set_offset(struct scsi_device *sdev, int offset) +static void sym2_get_offset(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + spi_offset(starget) = tp->tinfo.curr.offset; +} + +static void sym2_set_offset(struct scsi_target *starget, int offset) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - if (tp->tinfo.curr.options & PPR_OPT_DT) { - if (offset > np->maxoffs_dt) - offset = np->maxoffs_dt; - } else { - if (offset > np->maxoffs) - offset = np->maxoffs; - } tp->tinfo.goal.offset = offset; } -static void sym2_get_period(struct scsi_device *sdev) +static void sym2_get_period(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_period(sdev) = tp->tinfo.curr.period; + spi_period(starget) = tp->tinfo.curr.period; } -static void sym2_set_period(struct scsi_device *sdev, int period) +static void sym2_set_period(struct scsi_target *starget, int period) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - if (period <= 9 && np->minsync_dt) { - if (period < np->minsync_dt) - period = np->minsync_dt; - tp->tinfo.goal.options = PPR_OPT_DT; - tp->tinfo.goal.period = period; - if (!tp->tinfo.curr.offset || - tp->tinfo.curr.offset > np->maxoffs_dt) - tp->tinfo.goal.offset = np->maxoffs_dt; - } else { - if (period < np->minsync) - period = np->minsync; - tp->tinfo.goal.options = 0; - tp->tinfo.goal.period = period; - if (!tp->tinfo.curr.offset || - tp->tinfo.curr.offset > np->maxoffs) - tp->tinfo.goal.offset = np->maxoffs; - } + /* have to have DT for these transfers */ + if (period <= np->minsync) + tp->tinfo.goal.options |= PPR_OPT_DT; + + tp->tinfo.goal.period = period; } -static void sym2_get_width(struct scsi_device *sdev) +static void sym2_get_width(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_width(sdev) = tp->tinfo.curr.width ? 1 : 0; + spi_width(starget) = tp->tinfo.curr.width ? 1 : 0; } -static void sym2_set_width(struct scsi_device *sdev, int width) +static void sym2_set_width(struct scsi_target *starget, int width) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + /* It is illegal to have DT set on narrow transfers. If DT is + * clear, we must also clear IU and QAS. */ + if (width == 0) + tp->tinfo.goal.options &= ~PPR_OPT_MASK; tp->tinfo.goal.width = width; } -static void sym2_get_dt(struct scsi_device *sdev) +static void sym2_get_dt(struct scsi_target *starget) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - spi_dt(sdev) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0; + spi_dt(starget) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0; } -static void sym2_set_dt(struct scsi_device *sdev, int dt) +static void sym2_set_dt(struct scsi_target *starget, int dt) { - struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; - struct sym_tcb *tp = &np->target[sdev->id]; + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; - if (!dt) { - /* if clearing DT, then we may need to reduce the - * period and the offset */ - if (tp->tinfo.curr.period < np->minsync) - tp->tinfo.goal.period = np->minsync; - if (tp->tinfo.curr.offset > np->maxoffs) - tp->tinfo.goal.offset = np->maxoffs; - tp->tinfo.goal.options &= ~PPR_OPT_DT; - } else { + /* We must clear QAS and IU if DT is clear */ + if (dt) tp->tinfo.goal.options |= PPR_OPT_DT; - } + else + tp->tinfo.goal.options &= ~PPR_OPT_MASK; +} + +static void sym2_get_iu(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + spi_iu(starget) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0; +} + +static void sym2_set_iu(struct scsi_target *starget, int iu) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + if (iu) + tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT; + else + tp->tinfo.goal.options &= ~PPR_OPT_IU; +} + +static void sym2_get_qas(struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + spi_qas(starget) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0; } - + +static void sym2_set_qas(struct scsi_target *starget, int qas) +{ + struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; + struct sym_tcb *tp = &np->target[starget->id]; + + if (qas) + tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT; + else + tp->tinfo.goal.options &= ~PPR_OPT_QAS; +} + static struct spi_function_template sym2_transport_functions = { .set_offset = sym2_set_offset, @@ -2482,6 +2328,13 @@ static struct spi_function_template sym2_transport_functions = { .get_dt = sym2_get_dt, .set_dt = sym2_set_dt, .show_dt = 1, + .get_iu = sym2_get_iu, + .set_iu = sym2_set_iu, + .show_iu = 1, + .get_qas = sym2_get_qas, + .set_qas = sym2_set_qas, + .show_qas = 1, + .get_signalling = sym2_get_signalling, }; static struct pci_device_id sym2_id_table[] __devinitdata = { @@ -2533,12 +2386,17 @@ static struct pci_driver sym2_driver = { static int __init sym2_init(void) { + int error; + + sym2_setup_params(); sym2_transport_template = spi_attach_transport(&sym2_transport_functions); if (!sym2_transport_template) return -ENODEV; - pci_register_driver(&sym2_driver); - return 0; + error = pci_module_init(&sym2_driver); + if (error) + spi_release_transport(sym2_transport_template); + return error; } static void __exit sym2_exit(void) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 60d48b750..df1b9af12 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_GLUE_H @@ -89,8 +76,6 @@ #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 @@ -108,10 +93,9 @@ #define printf(args...) printk(args) /* - * Insert a delay in micro-seconds and milli-seconds. + * Insert a delay in micro-seconds */ #define sym_udelay(us) udelay(us) -#define sym_mdelay(ms) mdelay(ms) /* * A 'read barrier' flushes any data that have been prefetched @@ -289,32 +273,32 @@ typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */ * 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)) +#define INB_OFF(o) readb(np->s.mmio_va + sym_offb(o)) +#define OUTB_OFF(o, val) writeb((val), 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 INW_OFF(o) readw_l2b(np->s.mmio_va + sym_offw(o)) +#define INL_OFF(o) readl_l2b(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)) +#define OUTW_OFF(o, val) writew_b2l((val), np->s.mmio_va + sym_offw(o)) +#define OUTL_OFF(o, val) writel_b2l((val), 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 INW_OFF(o) readw_b2l(np->s.mmio_va + sym_offw(o)) +#define INL_OFF(o) readl_b2l(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)) +#define OUTW_OFF(o, val) writew_l2b((val), np->s.mmio_va + sym_offw(o)) +#define OUTL_OFF(o, val) writel_l2b((val), 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 INW_OFF(o) readw_raw(np->s.mmio_va + sym_offw(o)) +#define INL_OFF(o) readl_raw(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)) +#define OUTW_OFF(o, val) writew_raw((val), np->s.mmio_va + sym_offw(o)) +#define OUTL_OFF(o, val) writel_raw((val), np->s.mmio_va + (o)) #endif @@ -391,15 +375,12 @@ struct sym_shcb { struct Scsi_Host *host; - void * mmio_va; /* MMIO kernel virtual address */ - void * ram_va; /* RAM kernel virtual address */ + void __iomem * mmio_va; /* MMIO kernel virtual address */ + void __iomem * ram_va; /* RAM kernel virtual address */ u_long io_port; /* IO port address cookie */ 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 */ @@ -424,7 +405,7 @@ struct sym_slot { int irq; /* port and address fields to fit INB, OUTB macros */ u_long io_port; - void * mmio_va; + void __iomem * mmio_va; char inst_name[16]; }; @@ -439,6 +420,13 @@ struct sym_device { u_char host_id; }; +/* + * Driver host data structure. + */ +struct host_data { + struct sym_hcb *ncb; +}; + /* * The driver definitions (sym_hipd.h) must know about a * couple of things related to the memory allocator. diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 25a27f998..383f48b10 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -3,6 +3,7 @@ * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier + * Copyright (c) 2003-2004 Matthew Wilcox * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier @@ -22,37 +23,20 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ - -#define SYM_VERSION "2.1.18j" -#define SYM_DRIVER_NAME "sym-" SYM_VERSION - #include "sym_glue.h" #include "sym_nvram.h" @@ -303,7 +287,6 @@ int sym_reset_scsi_bus(hcb_p np, int enab_int) } out: OUTB (nc_scntl1, 0); - /* MDELAY(100); */ return retv; } @@ -1042,28 +1025,11 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *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); - /* - * Some single-ended devices may crash on receiving a - * PPR negotiation attempt. Only try PPR if we're in - * LVD mode. - */ - if (np->features & FE_ULTRA3) { - tp->tinfo.user.options |= PPR_OPT_DT; - tp->tinfo.user.period = np->minsync_dt; - tp->tinfo.user.offset = np->maxoffs_dt; - tp->tinfo.user.spi_version = 3; - } - if (!tp->usrtags) tp->usrflags &= ~SYM_TAGS_ENABLED; } @@ -1497,6 +1463,56 @@ static void sym_update_dmap_regs(hcb_p np) } #endif +static void sym_check_goals(struct scsi_device *sdev) +{ + struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb; + struct sym_trans *st = &np->target[sdev->id].tinfo.goal; + + /* here we enforce all the fiddly SPI rules */ + + if (!scsi_device_wide(sdev)) + st->width = 0; + + if (!scsi_device_sync(sdev)) { + st->options = 0; + st->period = 0; + st->offset = 0; + return; + } + + if (scsi_device_dt(sdev)) { + if (scsi_device_dt_only(sdev)) + st->options |= PPR_OPT_DT; + + if (st->offset == 0) + st->options &= ~PPR_OPT_DT; + } else { + st->options &= ~PPR_OPT_DT; + } + + if (!(np->features & FE_ULTRA3)) + st->options &= ~PPR_OPT_DT; + + if (st->options & PPR_OPT_DT) { + /* all DT transfers must be wide */ + st->width = 1; + if (st->offset > np->maxoffs_dt) + st->offset = np->maxoffs_dt; + if (st->period < np->minsync_dt) + st->period = np->minsync_dt; + if (st->period > np->maxsync_dt) + st->period = np->maxsync_dt; + } else { + st->options &= ~PPR_OPT_MASK; + if (st->offset > np->maxoffs) + st->offset = np->maxoffs; + if (st->period < np->minsync) + st->period = np->minsync; + if (st->period > np->maxsync) + st->period = np->maxsync; + } +} + /* * Prepare the next negotiation message if needed. * @@ -1508,6 +1524,10 @@ 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; + struct scsi_device *sdev = tp->sdev; + + if (likely(sdev)) + sym_check_goals(sdev); /* * Early C1010 chips need a work-around for DT @@ -1518,19 +1538,21 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr) /* * negotiate using PPR ? */ - if (tp->tinfo.goal.options & PPR_OPT_MASK) + if (scsi_device_dt(sdev)) { 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; + } else { + /* + * negotiate wide transfers ? + */ + 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: @@ -1554,7 +1576,7 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr) msgptr[msglen++] = 0; msgptr[msglen++] = tp->tinfo.goal.offset; msgptr[msglen++] = tp->tinfo.goal.width; - msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_DT; + msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK; break; }; @@ -1921,7 +1943,7 @@ void sym_start_up (hcb_p np, int reason) if (np->features & (FE_ULTRA2|FE_ULTRA3)) { OUTONW (nc_sien, SBMC); if (reason == 0) { - MDELAY(100); + mdelay(100); INW (nc_sist); } np->scsi_mode = INB (nc_stest4) & SMODE; @@ -1988,7 +2010,7 @@ void sym_start_up (hcb_p np, int reason) /* * 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, +static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs, u_char per, u_char wide, u_char div, u_char fak) { SYM_QUEHEAD *qp; @@ -2039,7 +2061,7 @@ static void sym_settrans(hcb_p np, int target, u_char dt, u_char ofs, */ if (np->features & FE_C10) { uval = uval & ~(U3EN|AIPCKEN); - if (dt) { + if (opts) { assert(np->features & FE_U3EN); uval |= U3EN; } @@ -2142,17 +2164,17 @@ sym_setsync(hcb_p np, int target, * Let everything be aware of the changes. */ static void -sym_setpprot(hcb_p np, int target, u_char dt, u_char ofs, +sym_setpprot(hcb_p np, int target, u_char opts, 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); + sym_settrans(np, target, opts, 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; + tp->tinfo.goal.options = tp->tinfo.curr.options = opts; sym_xpt_async_nego_ppr(np, target); } @@ -2713,7 +2735,7 @@ unexpected_phase: 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; + np->msgout[0] = IDENTIFY(0, cp->lun); nxtdsp = SCRIPTB_BA (np, ident_break_atn); } else @@ -3142,10 +3164,7 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp) * requesting sense data. */ - /* - * identify message - */ - cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun; + cp->scsi_smsg2[0] = IDENTIFY(0, cp->lun); msglen = 1; /* @@ -3504,8 +3523,8 @@ static void sym_sir_task_recovery(hcb_p np, int num) */ 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; + lp->to_clear = 0; /* We don't expect to fail here */ + np->abrt_msg[0] = IDENTIFY(0, lun); np->abrt_msg[1] = M_ABORT; np->abrt_tbl.size = 2; break; @@ -3546,7 +3565,7 @@ static void sym_sir_task_recovery(hcb_p np, int num) * We have some task to abort. * Set the IDENTIFY(lun) */ - np->abrt_msg[0] = M_IDENTIFY | cp->lun; + np->abrt_msg[0] = IDENTIFY(0, cp->lun); /* * If we want to abort an untagged command, we @@ -3557,8 +3576,7 @@ static void sym_sir_task_recovery(hcb_p np, int num) if (cp->tag == NO_TAG) { np->abrt_msg[1] = M_ABORT; np->abrt_tbl.size = 2; - } - else { + } else { np->abrt_msg[1] = cp->scsi_smsg[1]; np->abrt_msg[2] = cp->scsi_smsg[2]; np->abrt_msg[3] = M_ABORT_TAG; @@ -3999,7 +4017,6 @@ int sym_compute_residual(hcb_p np, ccb_p cp) 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) { @@ -4019,19 +4036,11 @@ sym_sync_nego_check(hcb_p np, int req, int target) 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;} - } } /* @@ -4127,20 +4136,17 @@ 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; + unsigned char fak, div; + int dt, chg = 0; + + unsigned char per = np->msgin[3]; + unsigned char ofs = np->msgin[5]; + unsigned char wide = np->msgin[6]; + unsigned char opts = np->msgin[7] & PPR_OPT_MASK; 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. @@ -4150,40 +4156,29 @@ sym_ppr_nego_check(hcb_p np, int req, int target) 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;} - } + opts = 0; if (!(np->features & FE_U3EN)) /* Broken U3EN bit not supported */ - dt &= ~PPR_OPT_DT; + opts = 0; - if (dt != (np->msgin[7] & PPR_OPT_MASK)) chg = 1; + if (opts != (np->msgin[7] & PPR_OPT_MASK)) + chg = 1; + + dt = opts & PPR_OPT_DT; 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;} + unsigned char maxoffs = dt ? np->maxoffs_dt : np->maxoffs; + if (ofs > maxoffs) { + chg = 1; + ofs = maxoffs; } } 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;} + unsigned char minsync = dt ? np->minsync_dt : np->minsync; + if (per < np->minsync_dt) { + chg = 1; + per = minsync; } } @@ -4204,7 +4199,7 @@ sym_ppr_nego_check(hcb_p np, int req, int target) /* * Apply new values. */ - sym_setpprot (np, target, dt, ofs, per, wide, div, fak); + sym_setpprot(np, target, opts, ofs, per, wide, div, fak); /* * It was an answer. We are done. @@ -4222,7 +4217,7 @@ sym_ppr_nego_check(hcb_p np, int req, int target) np->msgout[4] = 0; np->msgout[5] = ofs; np->msgout[6] = wide; - np->msgout[7] = dt; + np->msgout[7] = opts; if (DEBUG_FLAGS & DEBUG_NEGO) { sym_print_nego_msg(np, target, "ppr msgout", np->msgout); @@ -4238,7 +4233,7 @@ reject_it: * If it is a device response that should result in * ST, we may want to try a legacy negotiation later. */ - if (!req && !dt) { + if (!req && !opts) { tp->tinfo.goal.options = 0; tp->tinfo.goal.width = wide; tp->tinfo.goal.period = per; @@ -4286,7 +4281,6 @@ reject_it: 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) { @@ -4306,10 +4300,6 @@ sym_wide_nego_check(hcb_p np, int req, int target) 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); @@ -5276,8 +5266,9 @@ 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_char *msgptr; u_int msglen; + int can_disconnect; /* * Keep track of the IO in our CCB. @@ -5285,25 +5276,21 @@ int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp) cp->cam_ccb = (cam_ccb_p) csio; /* - * Retreive the target descriptor. + * Retrieve the target descriptor. */ tp = &np->target[cp->target]; /* - * Retreive the lun descriptor. + * Retrieve 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; + can_disconnect = (cp->tag != NO_TAG) || + (lp && (lp->curr_flags & SYM_DISC_ENABLED)); msgptr = cp->scsi_smsg; msglen = 0; - msgptr[msglen++] = idmsg; + msgptr[msglen++] = IDENTIFY(can_disconnect, cp->lun); /* * Build the tag message if present. @@ -5510,7 +5497,6 @@ void sym_complete_error (hcb_p np, ccb_p cp) 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); } /* @@ -5738,15 +5724,8 @@ if (resid) /* * 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; /* @@ -5772,13 +5751,6 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw) */ 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. diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index aa246dd0f..4d3b98953 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_HIPD_H @@ -69,11 +56,6 @@ * When this option is set, the driver will use a queue per * device and handle QUEUE FULL status requeuing internally. * - * 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. @@ -82,7 +64,6 @@ #if 0 #define SYM_OPT_HANDLE_DIR_UNKNOWN #define SYM_OPT_HANDLE_DEVICE_QUEUEING -#define SYM_OPT_SNIFF_INQUIRY #define SYM_OPT_LIMIT_COMMAND_REORDERING #endif @@ -364,7 +345,6 @@ struct sym_trans { 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 @@ -465,18 +445,7 @@ struct sym_tcb { */ 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 - + struct scsi_device *sdev; }; /* @@ -1139,12 +1108,7 @@ 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. @@ -1168,26 +1132,6 @@ void sym_clock(hcb_p np); 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. * @@ -1388,7 +1332,6 @@ u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m); #define PRINT_ADDR sym_print_addr #define PRINT_TARGET sym_print_target #define PRINT_LUN sym_print_lun -#define MDELAY sym_mdelay #define UDELAY sym_udelay #endif /* SYM_HIPD_H */ diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c index c0df21ca2..567a6dd31 100644 --- a/drivers/scsi/sym53c8xx_2/sym_malloc.c +++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifdef __FreeBSD__ diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c index ee2a7b28a..f27f52e65 100644 --- a/drivers/scsi/sym53c8xx_2/sym_misc.c +++ b/drivers/scsi/sym53c8xx_2/sym_misc.c @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifdef __FreeBSD__ @@ -203,10 +190,12 @@ void sym_announce_transfer_rate(hcb_p np, int target) mb10 = (f10 + period/2) / period; } printf_info ( - "%s:%d: %s %sSCSI %d.%d MB/s %s (%d.%d ns, offset %d)\n", + "%s:%d: %s %sSCSI %d.%d MB/s %s%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", + (__tcurr.options & PPR_OPT_IU) ? " IU" : "", + (__tcurr.options & PPR_OPT_QAS) ? " QAS" : "", period/10, period%10, __tcurr.offset); } else @@ -216,121 +205,3 @@ void sym_announce_transfer_rate(hcb_p np, int target) #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) -{ - memcpy(&tp->tinfo.goal, &tp->tinfo.user, 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) - 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 --git a/drivers/scsi/sym53c8xx_2/sym_misc.h b/drivers/scsi/sym53c8xx_2/sym_misc.h index 4568f0c22..0433d5d0c 100644 --- a/drivers/scsi/sym53c8xx_2/sym_misc.h +++ b/drivers/scsi/sym53c8xx_2/sym_misc.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_MISC_H diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c index 2bb4b3f3e..f3621324a 100644 --- a/drivers/scsi/sym53c8xx_2/sym_nvram.c +++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c @@ -22,42 +22,24 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sym_glue.h" #include "sym_nvram.h" -/* - * Some poor and bogus sync table that refers to Tekram NVRAM layout. - */ -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 @@ -100,8 +82,6 @@ sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram) struct sym_tcb *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; @@ -121,15 +101,6 @@ sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram) { struct sym_tcb *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; diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h index ff3a8bf02..a6bd02afb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_nvram.h +++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h @@ -22,32 +22,19 @@ * *----------------------------------------------------------------------------- * - * 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. + * 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. * - * 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 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. * - * 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. + * 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 */ #ifndef SYM_NVRAM_H diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h index 640802075..7ca14db34 100644 --- a/drivers/scsi/sym53c8xx_comm.h +++ b/drivers/scsi/sym53c8xx_comm.h @@ -54,57 +54,6 @@ ******************************************************************************* */ -/* -** This file contains definitions and code that the -** sym53c8xx and ncr53c8xx drivers should share. -** The sharing will be achieved in a further version -** of the driver bundle. For now, only the ncr53c8xx -** driver includes this file. -*/ - -/*========================================================== -** -** Hmmm... What complex some PCI-HOST bridges actually -** are, despite the fact that the PCI specifications -** are looking so smart and simple! ;-) -** -**========================================================== -*/ - -/*========================================================== -** -** Miscallaneous defines. -** -**========================================================== -*/ - -#define u_char unsigned char -#define u_long unsigned long - -#ifndef bzero -#define bzero(d, n) memset((d), 0, (n)) -#endif - -/*========================================================== -** -** assert () -** -**========================================================== -** -** modified copy from 386bsd:/usr/include/sys/assert.h -** -**---------------------------------------------------------- -*/ - -#define assert(expression) { \ - if (!(expression)) { \ - (void)panic( \ - "assertion \"%s\" failed: file \"%s\", line %d\n", \ - #expression, \ - __FILE__, __LINE__); \ - } \ -} - /*========================================================== ** ** Debugging tags @@ -137,170 +86,22 @@ static int ncr_debug = SCSI_NCR_DEBUG_FLAGS; #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS #endif -/*========================================================== -** -** A la VMS/CAM-3 queue management. -** Implemented from linux list management. -** -**========================================================== -*/ - -typedef struct xpt_quehead { - struct xpt_quehead *flink; /* Forward pointer */ - struct xpt_quehead *blink; /* Backward pointer */ -} XPT_QUEHEAD; - -#define xpt_que_init(ptr) do { \ - (ptr)->flink = (ptr); (ptr)->blink = (ptr); \ -} while (0) - -static inline void __xpt_que_add(struct xpt_quehead * new, - struct xpt_quehead * blink, - struct xpt_quehead * flink) +static inline struct list_head *ncr_list_pop(struct list_head *head) { - flink->blink = new; - new->flink = flink; - new->blink = blink; - blink->flink = new; -} - -static inline void __xpt_que_del(struct xpt_quehead * blink, - struct xpt_quehead * flink) -{ - flink->blink = blink; - blink->flink = flink; -} + if (!list_empty(head)) { + struct list_head *elem = head->next; -static inline int xpt_que_empty(struct xpt_quehead *head) -{ - return head->flink == head; -} - -static inline void xpt_que_splice(struct xpt_quehead *list, - struct xpt_quehead *head) -{ - struct xpt_quehead *first = list->flink; - - if (first != list) { - struct xpt_quehead *last = list->blink; - struct xpt_quehead *at = head->flink; - - first->blink = head; - head->flink = first; - - last->flink = at; - at->blink = last; + list_del(elem); + return elem; } -} - -#define xpt_que_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - - -#define xpt_insque(new, pos) __xpt_que_add(new, pos, (pos)->flink) - -#define xpt_remque(el) __xpt_que_del((el)->blink, (el)->flink) -#define xpt_insque_head(new, head) __xpt_que_add(new, head, (head)->flink) - -static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head) -{ - struct xpt_quehead *elem = head->flink; - - if (elem != head) - __xpt_que_del(head, elem->flink); - else - elem = NULL; - return elem; + return NULL; } -#define xpt_insque_tail(new, head) __xpt_que_add(new, (head)->blink, head) - -static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head) -{ - struct xpt_quehead *elem = head->blink; - - if (elem != head) - __xpt_que_del(elem->blink, head); - else - elem = 0; - return elem; -} - - -/*========================================================== -** -** SMP threading. -** -** Assuming that SMP systems are generally high end -** systems and may use several SCSI adapters, we are -** using one lock per controller instead of some global -** one. For the moment (linux-2.1.95), driver's entry -** points are called with the 'io_request_lock' lock -** held, so: -** - We are uselessly loosing a couple of micro-seconds -** to lock the controller data structure. -** - But the driver is not broken by design for SMP and -** so can be more resistant to bugs or bad changes in -** the IO sub-system code. -** - A small advantage could be that the interrupt code -** is grained as wished (e.g.: by controller). -** -**========================================================== -*/ - -spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED; -#define NCR_LOCK_DRIVER(flags) spin_lock_irqsave(&DRIVER_SMP_LOCK, flags) -#define NCR_UNLOCK_DRIVER(flags) \ - spin_unlock_irqrestore(&DRIVER_SMP_LOCK, flags) - -#define NCR_INIT_LOCK_NCB(np) spin_lock_init(&np->smp_lock) -#define NCR_LOCK_NCB(np, flags) spin_lock_irqsave(&np->smp_lock, flags) -#define NCR_UNLOCK_NCB(np, flags) spin_unlock_irqrestore(&np->smp_lock, flags) - -#define NCR_LOCK_SCSI_DONE(host, flags) \ - spin_lock_irqsave((host)->host_lock, flags) -#define NCR_UNLOCK_SCSI_DONE(host, flags) \ - spin_unlock_irqrestore(((host)->host_lock), flags) - -/*========================================================== -** -** Memory mapped IO -** -** Since linux-2.1, we must use ioremap() to map the io -** memory space and iounmap() to unmap it. This allows -** portability. Linux 1.3.X and 2.0.X allow to remap -** physical pages addresses greater than the highest -** physical memory address to kernel virtual pages with -** vremap() / vfree(). That was not portable but worked -** with i386 architecture. -** -**========================================================== -*/ - #ifdef __sparc__ #include #endif -#define memcpy_to_pci(a, b, c) memcpy_toio((a), (b), (c)) - -/*========================================================== -** -** Insert a delay in micro-seconds and milli-seconds. -** -** Under Linux, udelay() is restricted to delay < -** 1 milli-second. In fact, it generally works for up -** to 1 second delay. Since 2.1.105, the mdelay() function -** is provided for delays in milli-seconds. -** Under 2.0 kernels, udelay() is an inline function -** that is very inaccurate on Pentium processors. -** -**========================================================== -*/ - -#define UDELAY udelay -#define MDELAY mdelay - /*========================================================== ** ** Simple power of two buddy-like allocator. @@ -319,8 +120,6 @@ spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED; **========================================================== */ -#define __GetFreePages(flags, order) __get_free_pages(flags, order) - #define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */ #if PAGE_SIZE >= 8192 #define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum */ @@ -356,10 +155,6 @@ typedef struct m_pool { /* Memory pool of a given kind */ m_bush_t bush; m_addr_t (*getp)(struct m_pool *); void (*freep)(struct m_pool *, m_addr_t); -#define M_GETP() mp->getp(mp) -#define M_FREEP(p) mp->freep(mp, p) -#define GetPages() __GetFreePages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER) -#define FreePages(p) free_pages(p, MEMO_PAGE_ORDER) int nump; m_vtob_s *(vtob[VTOB_HASH_SIZE]); struct m_pool *next; @@ -385,7 +180,7 @@ static void *___m_alloc(m_pool_s *mp, int size) j = i; while (!h[j].next) { if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) { - h[j].next = (m_link_s *) M_GETP(); + h[j].next = (m_link_s *)mp->getp(mp); if (h[j].next) h[j].next->next = NULL; break; @@ -434,7 +229,7 @@ static void ___m_free(m_pool_s *mp, void *ptr, int size) while (1) { #ifdef MEMO_FREE_UNUSED if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) { - M_FREEP(a); + mp->freep(mp, a); break; } #endif @@ -455,6 +250,8 @@ static void ___m_free(m_pool_s *mp, void *ptr, int size) } } +static spinlock_t ncr53c8xx_lock = SPIN_LOCK_UNLOCKED; + static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags) { void *p; @@ -465,7 +262,7 @@ static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags) printk ("new %-10s[%4d] @%p.\n", name, size, p); if (p) - bzero(p, size); + memset(p, 0, size); else if (uflags & MEMO_WARN) printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size); @@ -491,7 +288,7 @@ static void __m_free(m_pool_s *mp, void *ptr, int size, char *name) static m_addr_t ___mp0_getp(m_pool_s *mp) { - m_addr_t m = GetPages(); + m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER); if (m) ++mp->nump; return m; @@ -499,7 +296,7 @@ static m_addr_t ___mp0_getp(m_pool_s *mp) static void ___mp0_freep(m_pool_s *mp, m_addr_t m) { - FreePages(m); + free_pages(m, MEMO_PAGE_ORDER); --mp->nump; } @@ -569,7 +366,7 @@ static m_pool_s *___cre_dma_pool(m_bush_t bush) m_pool_s *mp; mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL"); if (mp) { - bzero(mp, sizeof(*mp)); + memset(mp, 0, sizeof(*mp)); mp->bush = bush; mp->getp = ___dma_getp; mp->freep = ___dma_freep; @@ -597,7 +394,7 @@ static void *__m_calloc_dma(m_bush_t bush, int size, char *name) struct m_pool *mp; void *m = NULL; - NCR_LOCK_DRIVER(flags); + spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (!mp) mp = ___cre_dma_pool(bush); @@ -605,7 +402,7 @@ static void *__m_calloc_dma(m_bush_t bush, int size, char *name) m = __m_calloc(mp, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); - NCR_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&ncr53c8xx_lock, flags); return m; } @@ -615,13 +412,13 @@ static void __m_free_dma(m_bush_t bush, void *m, int size, char *name) u_long flags; struct m_pool *mp; - NCR_LOCK_DRIVER(flags); + spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (mp) __m_free(mp, m, size, name); if (mp && !mp->nump) ___del_dma_pool(mp); - NCR_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&ncr53c8xx_lock, flags); } static m_addr_t __vtobus(m_bush_t bush, void *m) @@ -632,14 +429,14 @@ static m_addr_t __vtobus(m_bush_t bush, void *m) m_vtob_s *vp = NULL; m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK; - NCR_LOCK_DRIVER(flags); + spin_lock_irqsave(&ncr53c8xx_lock, flags); mp = ___get_dma_pool(bush); if (mp) { vp = mp->vtob[hc]; while (vp && (m_addr_t) vp->vaddr != a) vp = vp->next; } - NCR_UNLOCK_DRIVER(flags); + spin_unlock_irqrestore(&ncr53c8xx_lock, flags); return vp ? vp->baddr + (((m_addr_t) m) - a) : 0; } @@ -658,100 +455,59 @@ static m_addr_t __vtobus(m_bush_t bush, void *m) #define __data_mapped SCp.phase #define __data_mapping SCp.have_data_in -static void __unmap_scsi_data(struct device *dev, Scsi_Cmnd *cmd) +static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd) { - enum dma_data_direction dma_dir = - (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); - switch(cmd->__data_mapped) { case 2: - dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, dma_dir); + dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, + cmd->sc_data_direction); break; case 1: dma_unmap_single(dev, cmd->__data_mapping, - cmd->request_bufflen, dma_dir); + cmd->request_bufflen, + cmd->sc_data_direction); break; } cmd->__data_mapped = 0; } -static u_long __map_scsi_single_data(struct device *dev, Scsi_Cmnd *cmd) +static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd) { dma_addr_t mapping; - enum dma_data_direction dma_dir = - (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); - if (cmd->request_bufflen == 0) return 0; mapping = dma_map_single(dev, cmd->request_buffer, - cmd->request_bufflen, dma_dir); + cmd->request_bufflen, + cmd->sc_data_direction); cmd->__data_mapped = 1; cmd->__data_mapping = mapping; return mapping; } -static int __map_scsi_sg_data(struct device *dev, Scsi_Cmnd *cmd) +static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) { int use_sg; - enum dma_data_direction dma_dir = - (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); if (cmd->use_sg == 0) return 0; - use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, dma_dir); + use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, + cmd->sc_data_direction); cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; return use_sg; } -static void __sync_scsi_data_for_cpu(struct device *dev, Scsi_Cmnd *cmd) -{ - enum dma_data_direction dma_dir = - (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); - - switch(cmd->__data_mapped) { - case 2: - dma_sync_sg_for_cpu(dev, cmd->buffer, cmd->use_sg, dma_dir); - break; - case 1: - dma_sync_single_for_cpu(dev, cmd->__data_mapping, - cmd->request_bufflen, dma_dir); - break; - } -} - -static void __sync_scsi_data_for_device(struct device *dev, Scsi_Cmnd *cmd) -{ - enum dma_data_direction dma_dir = - (enum dma_data_direction)scsi_to_pci_dma_dir(cmd->sc_data_direction); - - switch(cmd->__data_mapped) { - case 2: - dma_sync_sg_for_device(dev, cmd->buffer, cmd->use_sg, dma_dir); - break; - case 1: - dma_sync_single_for_device(dev, cmd->__data_mapping, - cmd->request_bufflen, dma_dir); - break; - } -} - -#define scsi_sg_dma_address(sc) sg_dma_address(sc) -#define scsi_sg_dma_len(sc) sg_dma_len(sc) - #define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd) #define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd) #define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd) #define sync_scsi_data_for_cpu(np, cmd) __sync_scsi_data_for_cpu(np->dev, cmd) #define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd) -#define scsi_data_direction(cmd) (cmd->sc_data_direction) - /*========================================================== ** ** Driver setup. @@ -774,58 +530,6 @@ static struct ncr_driver_setup #define bootverbose (np->verbose) -/*=================================================================== -** -** Utility routines that protperly return data through /proc FS. -** -**=================================================================== -*/ -#ifdef SCSI_NCR_USER_INFO_SUPPORT - -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; -} - -#endif - /*=================================================================== ** ** Driver setup from the boot command line diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h index 28881d052..c1d1e959f 100644 --- a/drivers/scsi/sym53c8xx_defs.h +++ b/drivers/scsi/sym53c8xx_defs.h @@ -66,19 +66,12 @@ #include -/* These options are not tunable from 'make config' */ -#define SCSI_NCR_PROC_INFO_SUPPORT - /* ** If you want a driver as small as possible, donnot define the ** following options. */ #define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT #define SCSI_NCR_DEBUG_INFO_SUPPORT -#ifdef SCSI_NCR_PROC_INFO_SUPPORT -# define SCSI_NCR_USER_COMMAND_SUPPORT -# define SCSI_NCR_USER_INFO_SUPPORT -#endif /* ** To disable integrity checking, do not define the @@ -422,42 +415,42 @@ * MEMORY mapped IO input / output */ -#define INB_OFF(o) readb_raw((char *)np->reg + ncr_offb(o)) -#define OUTB_OFF(o, val) writeb_raw((val), (char *)np->reg + ncr_offb(o)) +#define INB_OFF(o) readb_raw((char __iomem *)np->reg + ncr_offb(o)) +#define OUTB_OFF(o, val) writeb_raw((val), (char __iomem *)np->reg + ncr_offb(o)) #if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) -#define INW_OFF(o) readw_l2b((char *)np->reg + ncr_offw(o)) -#define INL_OFF(o) readl_l2b((char *)np->reg + (o)) +#define INW_OFF(o) readw_l2b((char __iomem *)np->reg + ncr_offw(o)) +#define INL_OFF(o) readl_l2b((char __iomem *)np->reg + (o)) -#define OUTW_OFF(o, val) writew_b2l((val), (char *)np->reg + ncr_offw(o)) -#define OUTL_OFF(o, val) writel_b2l((val), (char *)np->reg + (o)) +#define OUTW_OFF(o, val) writew_b2l((val), (char __iomem *)np->reg + ncr_offw(o)) +#define OUTL_OFF(o, val) writel_b2l((val), (char __iomem *)np->reg + (o)) #elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) -#define INW_OFF(o) readw_b2l((char *)np->reg + ncr_offw(o)) -#define INL_OFF(o) readl_b2l((char *)np->reg + (o)) +#define INW_OFF(o) readw_b2l((char __iomem *)np->reg + ncr_offw(o)) +#define INL_OFF(o) readl_b2l((char __iomem *)np->reg + (o)) -#define OUTW_OFF(o, val) writew_l2b((val), (char *)np->reg + ncr_offw(o)) -#define OUTL_OFF(o, val) writel_l2b((val), (char *)np->reg + (o)) +#define OUTW_OFF(o, val) writew_l2b((val), (char __iomem *)np->reg + ncr_offw(o)) +#define OUTL_OFF(o, val) writel_l2b((val), (char __iomem *)np->reg + (o)) #else #ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS /* Only 8 or 32 bit transfers allowed */ -#define INW_OFF(o) (readb((char *)np->reg + ncr_offw(o)) << 8 | readb((char *)np->reg + ncr_offw(o) + 1)) +#define INW_OFF(o) (readb((char __iomem *)np->reg + ncr_offw(o)) << 8 | readb((char __iomem *)np->reg + ncr_offw(o) + 1)) #else -#define INW_OFF(o) readw_raw((char *)np->reg + ncr_offw(o)) +#define INW_OFF(o) readw_raw((char __iomem *)np->reg + ncr_offw(o)) #endif -#define INL_OFF(o) readl_raw((char *)np->reg + (o)) +#define INL_OFF(o) readl_raw((char __iomem *)np->reg + (o)) #ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS /* Only 8 or 32 bit transfers allowed */ -#define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char *)np->reg + ncr_offw(o)); writeb((char)(val), (char *)np->reg + ncr_offw(o) + 1); } while (0) +#define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char __iomem *)np->reg + ncr_offw(o)); writeb((char)(val), (char __iomem *)np->reg + ncr_offw(o) + 1); } while (0) #else -#define OUTW_OFF(o, val) writew_raw((val), (char *)np->reg + ncr_offw(o)) +#define OUTW_OFF(o, val) writew_raw((val), (char __iomem *)np->reg + ncr_offw(o)) #endif -#define OUTL_OFF(o, val) writel_raw((val), (char *)np->reg + (o)) +#define OUTL_OFF(o, val) writel_raw((val), (char __iomem *)np->reg + (o)) #endif diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 7ef1b8c92..6dc289767 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -199,6 +199,7 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ static int current_override = 0, current_base = 0; struct Scsi_Host *instance; unsigned long base; + void __iomem *p; int sig, count; tpnt->proc_name = "t128"; @@ -206,26 +207,34 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ for (count = 0; current_override < NO_OVERRIDES; ++current_override) { base = 0; + p = NULL; - if (overrides[current_override].address) + if (overrides[current_override].address) { base = overrides[current_override].address; - else + p = ioremap(bases[current_base].address, 0x2000); + if (!p) + base = 0; + } else for (; !base && (current_base < NO_BASES); ++current_base) { #if (TDEBUG & TDEBUG_INIT) printk("scsi-t128 : probing address %08x\n", bases[current_base].address); #endif + if (bases[current_base].noauto) + continue; + p = ioremap(bases[current_base].address, 0x2000); + if (!p) + continue; for (sig = 0; sig < NO_SIGNATURES; ++sig) - if (!bases[current_base].noauto && - isa_check_signature(bases[current_base].address + - signatures[sig].offset, + if (check_signature(p + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { base = bases[current_base].address; #if (TDEBUG & TDEBUG_INIT) printk("scsi-t128 : detected board.\n"); #endif - break; + goto found; } + iounmap(p); } #if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) @@ -235,11 +244,13 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ if (!base) break; +found: instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); if(instance == NULL) break; instance->base = base; + ((struct NCR5380_hostdata *)instance->hostdata)->base = p; NCR5380_init(instance, 0); @@ -282,11 +293,15 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ static int t128_release(struct Scsi_Host *shost) { + NCR5380_local_declare(); + NCR5380_setup(shost); if (shost->irq) free_irq(shost->irq, NULL); + NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); + iounmap(base); return 0; } @@ -334,28 +349,30 @@ int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len) { - unsigned long reg = instance->base + T_DATA_REG_OFFSET; + NCR5380_local_declare(); + void __iomem *reg; unsigned char *d = dst; register int i = len; + NCR5380_setup(instance); + reg = base + T_DATA_REG_OFFSET; #if 0 for (; i; --i) { - while (!(isa_readb(instance->base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); + while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); #else - while (!(isa_readb(instance->base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); + while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); for (; i; --i) { #endif - *d++ = isa_readb(reg); + *d++ = readb(reg); } - if (isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) { + if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { unsigned char tmp; - unsigned long foo; - foo = instance->base + T_CONTROL_REG_OFFSET; - tmp = isa_readb(foo); - isa_writeb(tmp | T_CR_CT, foo); - isa_writeb(tmp, foo); + void __iomem *foo = base + T_CONTROL_REG_OFFSET; + tmp = readb(foo); + writeb(tmp | T_CR_CT, foo); + writeb(tmp, foo); printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", instance->host_no); return -1; @@ -378,27 +395,30 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, int len) { - unsigned long reg = instance->base + T_DATA_REG_OFFSET; + NCR5380_local_declare(); + void __iomem *reg; unsigned char *s = src; register int i = len; + NCR5380_setup(instance); + reg = base + T_DATA_REG_OFFSET; + #if 0 for (; i; --i) { - while (!(isa_readb(instance->base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); + while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); #else - while (!(isa_readb(instance->base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); + while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); for (; i; --i) { #endif - isa_writeb(*s++, reg); + writeb(*s++, reg); } - if (isa_readb(instance->base + T_STATUS_REG_OFFSET) & T_ST_TIM) { + if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { unsigned char tmp; - unsigned long foo; - foo = instance->base + T_CONTROL_REG_OFFSET; - tmp = isa_readb(foo); - isa_writeb(tmp | T_CR_CT, foo); - isa_writeb(tmp, foo); + void __iomem *foo = base + T_CONTROL_REG_OFFSET; + tmp = readb(foo); + writeb(tmp | T_CR_CT, foo); + writeb(tmp, foo); printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", instance->host_no); return -1; diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 0f8286cd4..161ba53d9 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -111,28 +111,28 @@ static int t128_device_reset(Scsi_Cmnd *); #ifndef HOSTS_C #define NCR5380_implementation_fields \ - unsigned long base + void __iomem *base #define NCR5380_local_declare() \ - unsigned long base + void __iomem *base #define NCR5380_setup(instance) \ - base = (instance)->base + base = ((struct NCR5380_hostdata *)(instance->hostdata))->base #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) #if !(TDEBUG & TDEBUG_TRANSFER) -#define NCR5380_read(reg) isa_readb(T128_address(reg)) -#define NCR5380_write(reg, value) isa_writeb((value),(T128_address(reg))) +#define NCR5380_read(reg) readb(T128_address(reg)) +#define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #else #define NCR5380_read(reg) \ (((unsigned char) printk("scsi%d : read register %d at address %08x\n"\ - , instance->hostno, (reg), T128_address(reg))), isa_readb(T128_address(reg))) + , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) #define NCR5380_write(reg, value) { \ printk("scsi%d : write %02x to register %d at address %08x\n", \ instance->hostno, (value), (reg), T128_address(reg)); \ - isa_writeb((value), (T128_address(reg))); \ + writeb((value), (T128_address(reg))); \ } #endif diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 1b324b800..ee9df02ef 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -179,9 +179,6 @@ * suggested by CH. * ***********************************************************************/ -/* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ -#define DC390_IRQ SA_SHIRQ /* | SA_INTERRUPT */ - /* DEBUG options */ //#define DC390_DEBUG0 //#define DC390_DEBUG1 @@ -240,35 +237,22 @@ #include #include -#if 0 #include #include #include -#else -#include "scsi.h" -#endif #include #include +#include -#include "dc390.h" - -#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI +#define DC390_BANNER "Tekram DC390/AM53C974" +#define DC390_VERSION "2.1d 2004-05-27" - static struct pci_device_id tmscsim_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD53C974, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); +#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI #include "tmscsim.h" -static u8 dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ); + static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus); static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus); static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus); @@ -288,31 +272,18 @@ static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB ); static void dc390_Disconnect( struct dc390_acb* pACB ); static void dc390_Reselect( struct dc390_acb* pACB ); static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ); -static void dc390_DoingSRB_Done( struct dc390_acb* pACB, struct scsi_cmnd * cmd); static void dc390_ScsiRstDetect( struct dc390_acb* pACB ); -static void dc390_ResetSCSIBus( struct dc390_acb* pACB ); -static void __inline__ dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ); -static void __inline__ dc390_InvalidCmd( struct dc390_acb* pACB ); -static void __inline__ dc390_EnableMsgOut_Abort (struct dc390_acb*, struct dc390_srb*); -static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *); - -static int dc390_initAdapter(struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index ); -static void dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB); - -static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, - off_t offset, int length, int inout); +static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*); +static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB); +static void dc390_ResetDevParam(struct dc390_acb* pACB); -static struct dc390_acb* dc390_pACB_start= NULL; -static struct dc390_acb* dc390_pACB_current = NULL; -static unsigned long dc390_lastabortedpid = 0; static u32 dc390_laststatus = 0; static u8 dc390_adapterCnt = 0; /* Startup values, to be overriden on the commandline */ static int tmscsim[] = {-2, -2, -2, -2, -2, -2}; -static int tmscsim_paramnum = ARRAY_SIZE(tmscsim); -module_param_array(tmscsim, int, tmscsim_paramnum, 0); +module_param_array(tmscsim, int, NULL, 0); MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); @@ -369,242 +340,10 @@ static char* dc390_p1_str[] = { }; #endif -/* Devices erroneously pretending to be able to do TagQ */ -static u8 dc390_baddevname1[2][28] ={ - "SEAGATE ST3390N 9546", - "HP C3323-300 4269"}; -#define BADDEVCNT 2 - -static char* dc390_adapname = "DC390"; static u8 dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; static u8 dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; -/*********************************************************************** - * Functions for access to DC390 EEPROM - * and some to emulate it - * - **********************************************************************/ - - -static void __devinit dc390_EnDisableCE(u8 mode, struct pci_dev *pdev, u8 *regval) -{ - u8 bval; - - bval = 0; - if(mode == ENABLE_CE) - *regval = 0xc0; - else - *regval = 0x80; - pci_write_config_byte(pdev, *regval, bval); - if(mode == DISABLE_CE) - pci_write_config_byte(pdev, *regval, bval); - udelay(160); -} - - -/* Override EEprom values with explicitly set values */ -static void __devinit dc390_EEprom_Override (u8 index) -{ - u8 *ptr = (u8 *) dc390_eepromBuf[index]; - u8 id; - - /* Adapter Settings */ - if (tmscsim[0] != -2) - ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */ - if (tmscsim[3] != -2) - ptr[EE_MODE2] = (u8)tmscsim[3]; - if (tmscsim[5] != -2) - ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */ - if (tmscsim[4] != -2) - ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */ - - /* Device Settings */ - for (id = 0; id < MAX_SCSI_ID; id++) - { - if (tmscsim[2] != -2) - ptr[id<<2] = (u8)tmscsim[2]; /* EE_MODE1 */ - if (tmscsim[1] != -2) - ptr[(id<<2) + 1] = (u8)tmscsim[1]; /* EE_Speed */ - } -} - -/* Handle "-1" case */ -static void __devinit dc390_check_for_safe_settings (void) -{ - if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */ - { - tmscsim[0] = 7; tmscsim[1] = 4; - tmscsim[2] = 0x09; tmscsim[3] = 0x0f; - tmscsim[4] = 2; tmscsim[5] = 10; - printk (KERN_INFO "DC390: Using safe settings.\n"); - } -} - - -static int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, - PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ - | SYNC_NEGO_ | TAG_QUEUEING_, - MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION - /* | NO_SEEK */ -# ifdef CONFIG_SCSI_MULTI_LUN - | LUN_CHECK -# endif - , 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ }; - -/* Copy defaults over set values where missing */ -static void __devinit dc390_fill_with_defaults (void) -{ - int i; - PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\ - tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5])); - for (i = 0; i < 6; i++) - { - if (tmscsim[i] < 0 || tmscsim[i] > 255) - tmscsim[i] = tmscsim_def[i]; - } - /* Sanity checks */ - if (tmscsim[0] > 7) tmscsim[0] = 7; - if (tmscsim[1] > 7) tmscsim[1] = 4; - if (tmscsim[4] > 5) tmscsim[4] = 4; - if (tmscsim[5] > 180) tmscsim[5] = 180; -} - -#ifndef MODULE -/* Override defaults on cmdline: - * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) - */ -static int __init dc390_setup (char *str) -{ - int ints[8]; - int i, im; - (void)get_options (str, ARRAY_SIZE(ints), ints); - im = ints[0]; - if (im > 6) - { - printk (KERN_NOTICE "DC390: ignore extra params!\n"); - im = 6; - } - for (i = 0; i < im; i++) - tmscsim[i] = ints[i+1]; - /* dc390_checkparams (); */ - return 1; -} - -__setup("tmscsim=", dc390_setup); -#endif - -static void __devinit dc390_EEpromOutDI(struct pci_dev *pdev, u8 *regval, u8 Carry) -{ - u8 bval; - - bval = 0; - if(Carry) - { - bval = 0x40; - *regval = 0x80; - pci_write_config_byte(pdev, *regval, bval); - } - udelay(160); - bval |= 0x80; - pci_write_config_byte(pdev, *regval, bval); - udelay(160); - bval = 0; - pci_write_config_byte(pdev, *regval, bval); - udelay(160); -} - - -static u8 __devinit dc390_EEpromInDO(struct pci_dev *pdev) -{ - u8 bval; - - pci_write_config_byte(pdev, 0x80, 0x80); - udelay(160); - pci_write_config_byte(pdev, 0x80, 0x40); - udelay(160); - pci_read_config_byte(pdev, 0x00, &bval); - if(bval == 0x22) - return(1); - else - return(0); -} - - -static u16 __devinit dc390_EEpromGetData1(struct pci_dev *pdev) -{ - u8 i; - u8 carryFlag; - u16 wval; - - wval = 0; - for(i=0; i<16; i++) - { - wval <<= 1; - carryFlag = dc390_EEpromInDO(pdev); - wval |= carryFlag; - } - return(wval); -} - - -static void __devinit dc390_Prepare(struct pci_dev *pdev, u8 *regval, u8 EEpromCmd) -{ - u8 i,j; - u8 carryFlag; - - carryFlag = 1; - j = 0x80; - for(i=0; i<9; i++) - { - dc390_EEpromOutDI(pdev, regval, carryFlag); - carryFlag = (EEpromCmd & j) ? 1 : 0; - j >>= 1; - } -} - - -static void __devinit dc390_ReadEEprom(struct pci_dev *pdev, u16 *ptr) -{ - u8 regval,cmd; - u8 i; - - cmd = EEPROM_READ; - for(i=0; i<0x40; i++) - { - dc390_EnDisableCE(ENABLE_CE, pdev, ®val); - dc390_Prepare(pdev, ®val, cmd++); - *ptr++ = dc390_EEpromGetData1(pdev); - dc390_EnDisableCE(DISABLE_CE, pdev, ®val); - } -} - - -static void __devinit dc390_interpret_delay (u8 index) -{ - char interpd [] = {1,3,5,10,16,30,60,120}; - dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]]; -} - -static u8 __devinit dc390_CheckEEpromCheckSum(struct pci_dev *pdev, u8 index) -{ - u8 i; - char EEbuf[128]; - u16 wval, *ptr = (u16 *)EEbuf; - - dc390_ReadEEprom(pdev, ptr); - memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID); - memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], - &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID); - dc390_interpret_delay (index); - - wval = 0; - for(i=0; i<0x40; i++, ptr++) - wval += *ptr; - return (wval == 0x1234 ? 0 : 1); -} - - /*********************************************************************** * Functions for the management of the internal structures * (DCBs, SRBs, Queueing) @@ -612,52 +351,18 @@ static u8 __devinit dc390_CheckEEpromCheckSum(struct pci_dev *pdev, u8 index) **********************************************************************/ static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) { - struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return 0; + struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL; while (pDCB->TargetID != id || pDCB->TargetLUN != lun) { pDCB = pDCB->pNextDCB; if (pDCB == pACB->pLinkDCB) - { - DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n", - pDCB, id, pACB->DCBmap[id])); - return 0; - } + return NULL; } DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \ pDCB, pDCB->TargetID, pDCB->TargetLUN)); return pDCB; } -/* Queueing philosphy: - * There are a couple of lists: - * - Query: Contains the Scsi Commands not yet turned into SRBs (per ACB) - * (Note: For new EH, it is unnecessary!) - * - Waiting: Contains a list of SRBs not yet sent (per DCB) - * - Free: List of free SRB slots - * - * If there are no waiting commands for the DCB, the new one is sent to the bus - * otherwise the oldest one is taken from the Waiting list and the new one is - * queued to the Waiting List - * - * Lists are managed using two pointers and eventually a counter - */ - -/* Return next free SRB */ -static __inline__ struct dc390_srb* dc390_Free_get ( struct dc390_acb* pACB ) -{ - struct dc390_srb* pSRB; - - pSRB = pACB->pFreeSRB; - DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB)); - if( pSRB ) - { - pACB->pFreeSRB = pSRB->pNextSRB; - pSRB->pNextSRB = NULL; - } - - return( pSRB ); -} - /* Insert SRB oin top of free list */ static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB) { @@ -666,34 +371,6 @@ static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_s pACB->pFreeSRB = pSRB; } - -/* Inserts a SRB to the top of the Waiting list */ -static __inline__ void dc390_Waiting_insert ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) -{ - DEBUG0(printk ("DC390: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid)); - pSRB->pNextSRB = pDCB->pWaitingSRB; - if (!pDCB->pWaitingSRB) - pDCB->pWaitLast = pSRB; - pDCB->pWaitingSRB = pSRB; - pDCB->WaitSRBCnt++; -} - - -/* Queue SRB to waiting list */ -static __inline__ void dc390_Waiting_append ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB) -{ - DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid)); - if( pDCB->pWaitingSRB ) - pDCB->pWaitLast->pNextSRB = pSRB; - else - pDCB->pWaitingSRB = pSRB; - - pDCB->pWaitLast = pSRB; - pSRB->pNextSRB = NULL; - pDCB->WaitSRBCnt++; - pDCB->pDCBACB->CmdInQ++; -} - static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { pDCB->GoingSRBCnt++; @@ -728,132 +405,6 @@ static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_ pDCB->GoingSRBCnt--; } -/* Moves SRB from Going list to the top of Waiting list */ -static void dc390_Going_to_Waiting ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) -{ - DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid)); - /* Remove SRB from Going */ - dc390_Going_remove (pDCB, pSRB); - /* Insert on top of Waiting */ - dc390_Waiting_insert (pDCB, pSRB); - /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */ -} - -/* Moves first SRB from Waiting list to Going list */ -static __inline__ void dc390_Waiting_to_Going ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) -{ - /* Remove from waiting list */ - DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB)); - pDCB->pWaitingSRB = pSRB->pNextSRB; - if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL; - pDCB->WaitSRBCnt--; - dc390_Going_append (pDCB, pSRB); -} - -static void DC390_waiting_timed_out (unsigned long ptr); -/* Sets the timer to wake us up */ -static void dc390_waiting_timer (struct dc390_acb* pACB, unsigned long to) -{ - if (timer_pending (&pACB->Waiting_Timer)) return; - init_timer (&pACB->Waiting_Timer); - pACB->Waiting_Timer.function = DC390_waiting_timed_out; - pACB->Waiting_Timer.data = (unsigned long)pACB; - if (time_before (jiffies + to, pACB->pScsiHost->last_reset)) - pACB->Waiting_Timer.expires = pACB->pScsiHost->last_reset + 1; - else - pACB->Waiting_Timer.expires = jiffies + to + 1; - add_timer (&pACB->Waiting_Timer); -} - - -/* Send the next command from the waiting list to the bus */ -static void dc390_Waiting_process ( struct dc390_acb* pACB ) -{ - struct dc390_dcb *ptr, *ptr1; - struct dc390_srb *pSRB; - - if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) - return; - if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); - ptr = pACB->pDCBRunRobin; - if( !ptr ) - { - ptr = pACB->pLinkDCB; - pACB->pDCBRunRobin = ptr; - } - ptr1 = ptr; - if (!ptr1) return; - do - { - pACB->pDCBRunRobin = ptr1->pNextDCB; - if( !( pSRB = ptr1->pWaitingSRB ) || - ( ptr1->MaxCommand <= ptr1->GoingSRBCnt )) - ptr1 = ptr1->pNextDCB; - else - { - /* Try to send to the bus */ - if( !dc390_StartSCSI(pACB, ptr1, pSRB) ) - dc390_Waiting_to_Going (ptr1, pSRB); - else - dc390_waiting_timer (pACB, HZ/5); - break; - } - } while (ptr1 != ptr); - return; -} - -/* Wake up waiting queue */ -static void DC390_waiting_timed_out (unsigned long ptr) -{ - struct dc390_acb* pACB = (struct dc390_acb*)ptr; - unsigned long iflags; - DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n")); - spin_lock_irqsave(pACB->pScsiHost->host_lock, iflags); - dc390_Waiting_process (pACB); - spin_unlock_irqrestore(pACB->pScsiHost->host_lock, iflags); -} - -/*********************************************************************** - * Function: static void dc390_SendSRB (struct dc390_acb* pACB, struct dc390_srb* pSRB) - * - * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB) - * - ***********************************************************************/ - -static void dc390_SendSRB( struct dc390_acb* pACB, struct dc390_srb* pSRB ) -{ - struct dc390_dcb* pDCB; - - pDCB = pSRB->pSRBDCB; - if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || - (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) - { - dc390_Waiting_append (pDCB, pSRB); - dc390_Waiting_process (pACB); - return; - } - -#if 0 - if( pDCB->pWaitingSRB ) - { - dc390_Waiting_append (pDCB, pSRB); -/* pSRB = GetWaitingSRB(pDCB); */ /* non-existent */ - pSRB = pDCB->pWaitingSRB; - /* Remove from waiting list */ - pDCB->pWaitingSRB = pSRB->pNextSRB; - pSRB->pNextSRB = NULL; - if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL; - } -#endif - - if (!dc390_StartSCSI(pACB, pDCB, pSRB)) - dc390_Going_append (pDCB, pSRB); - else { - dc390_Waiting_insert (pDCB, pSRB); - dc390_waiting_timer (pACB, HZ/5); - } -} - static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length) { memset(sg, 0, sizeof(struct scatterlist)); @@ -929,493 +480,1437 @@ static void dc390_pci_unmap (struct dc390_srb* pSRB) } } - -/*********************************************************************** - * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, struct dc390_dcb* pDCB, - * struct dc390_srb* pSRB) - * - * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd - * - ***********************************************************************/ - -static void dc390_BuildSRB (struct scsi_cmnd *pcmd, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +static void __inline__ +dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { - pSRB->pSRBDCB = pDCB; - pSRB->pcmd = pcmd; - //pSRB->ScsiCmdLen = pcmd->cmd_len; - //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len); - - pSRB->SGIndex = 0; - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; - pSRB->MsgCnt = 0; - if( pDCB->DevType != TYPE_TAPE ) - pSRB->RetryCnt = 1; - else - pSRB->RetryCnt = 0; - pSRB->SRBStatus = 0; - pSRB->SRBFlag = 0; - pSRB->SRBState = 0; - pSRB->TotalXferredLen = 0; - pSRB->SGBusAddr = 0; - pSRB->SGToBeXferLen = 0; - pSRB->ScsiPhase = 0; - pSRB->EndMessage = 0; - pSRB->TagNumber = 255; - /* KG: deferred PCI mapping to dc390_StartSCSI */ + if (pSRB->TagNumber != SCSI_NO_TAG) { + pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */ + pSRB->TagNumber = SCSI_NO_TAG; + } } -/*********************************************************************** - * Function : static int DC390_queue_command (struct scsi_cmnd *cmd, - * void (*done)(struct scsi_cmnd *)) - * - * Purpose : enqueues a SCSI command - * - * Inputs : cmd - SCSI command, done - callback function called on - * completion, with a pointer to the command descriptor. - * - * Returns : (depending on kernel version) - * 2.0.x: always return 0 - * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x - * TO BE DONE: - * new model: return 0 if successful, or must not be re-queued - * return 1 if command cannot be queued (queue full) - * command will be inserted in midlevel queue then ... - * - ***********************************************************************/ -static int DC390_queue_command(struct scsi_cmnd *cmd, - void (* done)(struct scsi_cmnd *)) +static int +dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) { - struct dc390_dcb* pDCB = (struct dc390_dcb*) cmd->device->hostdata; - struct dc390_srb* pSRB; - struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; - - DEBUG0(/* if(pACB->scan_devices) */ \ - printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\ - cmd->cmnd[0],cmd->device->id,cmd->device->lun,cmd->pid, cmd->buffer)); - - /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY - * commands and alloc a DCB for the device if not yet there. DCB will - * be removed in dc390_SRBdone if SEL_TIMEOUT */ - if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) { - printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; + struct scsi_cmnd *scmd = pSRB->pcmd; + struct scsi_device *sdev = scmd->device; + u8 cmd, disc_allowed, try_sync_nego; + char tag[2]; + + pSRB->ScsiPhase = SCSI_NOP0; + + if (pACB->Connected) + { + // Should not happen normally + printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n", + pSRB->SRBState, pSRB->SRBFlag); + pSRB->SRBState = SRB_READY; + pACB->SelConn++; + return 1; + } + if (time_before (jiffies, pACB->pScsiHost->last_reset)) + { + DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n")); + return 1; } + /* KG: Moved pci mapping here */ + dc390_pci_map(pSRB); + /* TODO: error handling */ + DC390_write8 (Scsi_Dest_ID, pDCB->TargetID); + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg1, pDCB->CtrlR1); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); /* Flush FIFO */ + DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\ + scmd->cmnd[0], pDCB->SyncMode)); + + /* Don't disconnect on AUTO_REQSENSE, cause it might be an + * Contingent Allegiance Condition (6.6), where no tags should be used. + * All other have to be allowed to disconnect to prevent Incorrect + * Initiator Connection (6.8.2/6.5.2) */ + /* Changed KG, 99/06/06 */ + if (! (pSRB->SRBFlag & AUTO_REQSENSE)) + disc_allowed = pDCB->DevMode & EN_DISCONNECT_; + else + disc_allowed = 0; - /* Should it be: BUG_ON(!pDCB); ? */ + if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr && + (((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) && + !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY)) + try_sync_nego = 1; + else + try_sync_nego = 0; - if (!pDCB) - { /* should never happen */ - printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; + pSRB->MsgCnt = 0; + cmd = SEL_W_ATN; + DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN)); + /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */ + if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && scsi_populate_tag_msg(scmd, tag)) { + DC390_write8(ScsiFifo, tag[0]); + pDCB->TagMask |= 1 << tag[1]; + pSRB->TagNumber = tag[1]; + DC390_write8(ScsiFifo, tag[1]); + DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->pid, pSRB, tag[1])); + cmd = SEL_W_ATN3; + } else { + /* No TagQ */ +//no_tag: + DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->pid, pSRB)); } - pACB->Cmds++; - cmd->scsi_done = done; - cmd->result = 0; - - pSRB = dc390_Free_get(pACB); - if (!pSRB) - goto requeue; - - dc390_BuildSRB(cmd, pDCB, pSRB); - if (pDCB->pWaitingSRB) { - dc390_Waiting_append(pDCB, pSRB); - dc390_Waiting_process(pACB); - } else - dc390_SendSRB(pACB, pSRB); - - DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid)); - return(0); - - requeue: - return 1; - fail: - cmd->result = DID_BAD_TARGET << 16; - done(cmd); + pSRB->SRBState = SRB_START_; + + if (try_sync_nego) + { + u8 Sync_Off = pDCB->SyncOffset; + DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN)); + pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE; + pSRB->MsgOutBuf[1] = 3; + pSRB->MsgOutBuf[2] = EXTENDED_SDTR; + pSRB->MsgOutBuf[3] = pDCB->NegoPeriod; + if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET; + pSRB->MsgOutBuf[4] = Sync_Off; + pSRB->MsgCnt = 5; + //pSRB->SRBState = SRB_MSGOUT_; + pSRB->SRBState |= DO_SYNC_NEGO; + cmd = SEL_W_ATN_STOP; + } + + /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ + if (cmd != SEL_W_ATN_STOP) + { + if( pSRB->SRBFlag & AUTO_REQSENSE ) + { + DC390_write8 (ScsiFifo, REQUEST_SENSE); + DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, sizeof(scmd->sense_buffer)); + DC390_write8 (ScsiFifo, 0); + DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n")); + } + else /* write cmnd to bus */ + { + u8 *ptr; u8 i; + ptr = (u8 *)scmd->cmnd; + for (i = 0; i < scmd->cmd_len; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + } + } + DEBUG0(if (pACB->pActiveDCB) \ + printk (KERN_WARNING "DC390: ActiveDCB != 0\n")); + DEBUG0(if (pDCB->pActiveSRB) \ + printk (KERN_WARNING "DC390: ActiveSRB != 0\n")); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + if (DC390_read8 (Scsi_Status) & INTERRUPT) + { + dc390_freetag (pDCB, pSRB); + DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n", + scmd->pid, scmd->device->id, scmd->device->lun)); + pSRB->SRBState = SRB_READY; + //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->SelLost++; + return 1; + } + DC390_write8 (ScsiCmd, cmd); + pACB->pActiveDCB = pDCB; + pDCB->pActiveSRB = pSRB; + pACB->Connected = 1; + pSRB->ScsiPhase = SCSI_NOP1; return 0; } -/* We ignore mapping problems, as we expect everybody to respect - * valid partition tables. Waiting for complaints ;-) */ - -#ifdef CONFIG_SCSI_DC390T_TRADMAP -/* - * The next function, partsize(), is copied from scsicam.c. - * - * This is ugly code duplication, but I didn't find another way to solve it: - * We want to respect the partition table and if it fails, we apply the - * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do - * the job, because we don't know, whether the values returned are from - * the part. table or determined by setsize(). Unfortunately the setsize() - * values differ from the ones chosen by the DC390 BIOS. - * - * Looking forward to seeing suggestions for a better solution! KG, 98/10/14 - */ -#include +//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ +#define DMA_INT 0 -/* - * Function : static int partsize(unsigned char *buf, unsigned long - * capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs); - * - * Purpose : to determine the BIOS mapping used to create the partition - * table, storing the results in *cyls, *hds, and *secs - * - * Returns : -1 on failure, 0 on success. - * - */ +#if DMA_INT +/* This is similar to AM53C974.c ... */ +static u8 +dc390_dma_intr (struct dc390_acb* pACB) +{ + struct dc390_srb* pSRB; + u8 dstate; + DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev); + + DEBUG0(pci_read_config_word(pdev, PCI_STATUS, &pstate)); + DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\ + { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \ + pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));}); -static int partsize(unsigned char *buf, unsigned long capacity, - unsigned int *cyls, unsigned int *hds, unsigned int *secs) { - struct partition *p, *largest = NULL; - int i, largest_cyl; - int cyl, ext_cyl, end_head, end_cyl, end_sector; - unsigned int logical_end, physical_end, ext_physical_end; - + dstate = DC390_read8 (DMA_Status); - if (*(unsigned short *) (buf+64) == 0xAA55) { - for (largest_cyl = -1, p = (struct partition *) buf, - i = 0; i < 4; ++i, ++p) { - if (!p->sys_ind) - continue; - cyl = p->cyl + ((p->sector & 0xc0) << 2); - if (cyl > largest_cyl) { - largest_cyl = cyl; - largest = p; - } - } + if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate; + else pSRB = pACB->pActiveDCB->pActiveSRB; + + if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT)) + { + printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate); + return dstate; } - - if (largest) { - end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2); - end_head = largest->end_head; - end_sector = largest->end_sector & 0x3f; - - physical_end = end_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - - /* This is the actual _sector_ number at the end */ - logical_end = get_unaligned(&largest->start_sect) - + get_unaligned(&largest->nr_sects); - - /* This is for >1023 cylinders */ - ext_cyl= (logical_end-(end_head * end_sector + end_sector)) - /(end_head + 1) / end_sector; - ext_physical_end = ext_cyl * (end_head + 1) * end_sector + - end_head * end_sector + end_sector; - - if ((logical_end == physical_end) || - (end_cyl==1023 && ext_physical_end==logical_end)) { - *secs = end_sector; - *hds = end_head + 1; - *cyls = capacity / ((end_head + 1) * end_sector); - return 0; - } + if (dstate & DMA_XFER_DONE) + { + u32 residual, xferCnt; int ctr = 6000000; + if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION)) + { + do + { + DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n")); + dstate = DC390_read8 (DMA_Status); + residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 | + DC390_read8 (CtcReg_High) << 16; + residual += DC390_read8 (Current_Fifo) & 0x1f; + } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr); + if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + /* residual = ... */ + } + else + residual = 0; + + /* ??? */ + + xferCnt = pSRB->SGToBeXferLen - residual; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = residual; +# ifdef DC390_DEBUG0 + printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n", + (unsigned int)residual, (unsigned int)xferCnt); +# endif + + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } - return -1; + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; + return dstate; } +#endif -/*********************************************************************** - * Function: - * DC390_bios_param - * - * Description: - * Return the disk geometry for the given SCSI device. - * Respect the partition table, otherwise try own heuristic - * - * Note: - * In contrary to other externally callable funcs (DC390_), we don't lock - ***********************************************************************/ -static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) -{ - int heads, sectors, cylinders; - struct dc390_acb* pACB = (struct dc390_acb*) sdev->host->hostdata; - int ret_code = -1; - int size = capacity; - unsigned char *buf; - if ((buf = scsi_bios_ptable(bdev))) +static void __inline__ +dc390_InvalidCmd(struct dc390_acb* pACB) +{ + if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT)) + DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); +} + + +static irqreturn_t __inline__ +DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct dc390_acb *pACB = (struct dc390_acb*)dev_id; + struct dc390_dcb *pDCB; + struct dc390_srb *pSRB; + u8 sstatus=0; + u8 phase; + void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *); + u8 istate, istatus; +#if DMA_INT + u8 dstatus; +#endif + + sstatus = DC390_read8 (Scsi_Status); + if( !(sstatus & INTERRUPT) ) + return IRQ_NONE; + + DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus)); + +#if DMA_INT + spin_lock_irq(pACB->pScsiHost->host_lock); + dstatus = dc390_dma_intr (pACB); + spin_unlock_irq(pACB->pScsiHost->host_lock); + + DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus)); + if (! (dstatus & SCSI_INTERRUPT)) + { + DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); + return IRQ_NONE; + } +#else + //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); + //dstatus = DC390_read8 (DMA_Status); + //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); +#endif + + spin_lock_irq(pACB->pScsiHost->host_lock); + + istate = DC390_read8 (Intern_State); + istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ + + DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus)); + dc390_laststatus &= ~0x00ffffff; + dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus; + + if (sstatus & ILLEGAL_OP_ERR) + { + printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus); + dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); + } + + else if (istatus & INVALID_CMD) { - /* try to infer mapping from partition table */ - ret_code = partsize (buf, (unsigned long) size, (unsigned int *) geom + 2, - (unsigned int *) geom + 0, (unsigned int *) geom + 1); - kfree (buf); + printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus); + dc390_InvalidCmd( pACB ); + goto unlock; + } + + if (istatus & SCSI_RESET) + { + dc390_ScsiRstDetect( pACB ); + goto unlock; + } + + if (istatus & DISCONNECTED) + { + dc390_Disconnect( pACB ); + goto unlock; + } + + if (istatus & RESELECTED) + { + dc390_Reselect( pACB ); + goto unlock; + } + + else if (istatus & (SELECTED | SEL_ATTENTION)) + { + printk (KERN_ERR "DC390: Target mode not supported!\n"); + goto unlock; + } + + if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) ) + { + pDCB = pACB->pActiveDCB; + if (!pDCB) + { + printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n"); + goto unlock; + } + pSRB = pDCB->pActiveSRB; + if( pDCB->DCBFlag & ABORT_DEV_ ) + dc390_EnableMsgOut_Abort (pACB, pSRB); + + phase = pSRB->ScsiPhase; + DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus)); + stateV = (void *) dc390_phase0[phase]; + ( *stateV )( pACB, pSRB, &sstatus ); + + pSRB->ScsiPhase = sstatus & 7; + phase = (u8) sstatus & 7; + DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus)); + stateV = (void *) dc390_phase1[phase]; + ( *stateV )( pACB, pSRB, &sstatus ); + } + + unlock: + spin_unlock_irq(pACB->pScsiHost->host_lock); + return IRQ_HANDLED; +} + +static irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) +{ + irqreturn_t ret; + DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq)); + /* Locking is done in DC390_Interrupt */ + ret = DC390_Interrupt(irq, dev_id, regs); + DEBUG1(printk (".. IRQ returned\n")); + return ret; +} + +static void +dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + u8 sstatus; + struct scatterlist *psgl; + u32 ResidCnt, xferCnt; + u8 dstate = 0; + + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + unsigned long timeout = jiffies + HZ; + + /* Function called from the ISR with the host_lock held and interrupts disabled */ + if (pSRB->SGToBeXferLen) + while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) { + spin_unlock_irq(pACB->pScsiHost->host_lock); + udelay(50); + spin_lock_irq(pACB->pScsiHost->host_lock); + } + if (!time_before(jiffies, timeout)) + printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", + DC390_read32 (DMA_Wk_ByteCntr)); + dc390_laststatus &= ~0xff000000; + dc390_laststatus |= dstate << 24; + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + } + else + pSRB->SGToBeXferLen = 0; + } + else + { + ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f; + ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16; + ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; + ResidCnt += (u32) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + } } - if (ret_code == -1) + if ((*psstatus & 7) != SCSI_DATA_OUT) { - heads = 64; - sectors = 32; - cylinders = size / (heads * sectors); + DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + } +} + +static void +dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + u8 sstatus, residual, bval; + struct scatterlist *psgl; + u32 ResidCnt, i; + unsigned long xferCnt; + u8 *ptr; - if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR)) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) { - heads = 255; - sectors = 63; - cylinders = size / (heads * sectors); + int dstate = 0; + unsigned long timeout = jiffies + HZ; + + /* Function called from the ISR with the host_lock held and interrupts disabled */ + if (pSRB->SGToBeXferLen) + while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) { + spin_unlock_irq(pACB->pScsiHost->host_lock); + udelay(50); + spin_lock_irq(pACB->pScsiHost->host_lock); + } + if (!time_before(jiffies, timeout)) { + printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", + DC390_read32 (DMA_Wk_ByteCntr)); + printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate); + } + dc390_laststatus &= ~0xff000000; + dc390_laststatus |= dstate << 24; + DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \ + + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \ + + ((unsigned long) DC390_read8 (CtcReg_Low))); + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen)); + + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + } + else + pSRB->SGToBeXferLen = 0; } + else /* phase changed */ + { + residual = 0; + bval = DC390_read8 (Current_Fifo); + while( bval & 0x1f ) + { + DEBUG1(printk (KERN_DEBUG "Check for residuals,")); + if( (bval & 0x1f) == 1 ) + { + for(i=0; i < 0x100; i++) + { + bval = DC390_read8 (Current_Fifo); + if( !(bval & 0x1f) ) + goto din_1; + else if( i == 0x0ff ) + { + residual = 1; /* ;1 residual byte */ + goto din_1; + } + } + } + else + bval = DC390_read8 (Current_Fifo); + } +din_1: + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD); + for (i = 0xa000; i; i--) + { + bval = DC390_read8 (DMA_Status); + if (bval & BLAST_COMPLETE) + break; + } + /* It seems a DMA Blast abort isn't that bad ... */ + if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); + //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; + + DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval)); + ResidCnt = (u32) DC390_read8 (CtcReg_High); + ResidCnt <<= 8; + ResidCnt |= (u32) DC390_read8 (CtcReg_Mid); + ResidCnt <<= 8; + ResidCnt |= (u32) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + + if( residual ) + { + bval = DC390_read8 (ScsiFifo); /* get one residual byte */ + ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr ); + *ptr = bval; + pSRB->SGBusAddr++; xferCnt++; + pSRB->TotalXferredLen++; + pSRB->SGToBeXferLen--; + } + DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ + pSRB->TotalXferredLen, pSRB->SGToBeXferLen)); - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; + } } + if ((*psstatus & 7) != SCSI_DATA_IN) + { + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + } +} - return (0); +static void +dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ } -#else -static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) + +static void +dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + + pSRB->TargetStatus = DC390_read8 (ScsiFifo); + //udelay (1); + pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */ + + *psstatus = SCSI_NOP0; + pSRB->SRBState = SRB_COMPLETED; + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); +} + +static void +dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) ) + *psstatus = SCSI_NOP0; + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); +} + + +static void __inline__ +dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB) +{ + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); + dc390_SetXferRate (pACB, pDCB); +} + + +#ifdef DC390_DEBUG0 +static void +dc390_printMsg (u8 *MsgBuf, u8 len) { - return scsicam_bios_param (bdev, capacity, geom); + int i; + printk (" %02x", MsgBuf[0]); + for (i = 1; i < len; i++) + printk (" %02x", MsgBuf[i]); + printk ("\n"); } #endif -static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD) + +/* reject_msg */ +static void __inline__ +dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB) { - struct pci_dev *pdev; - u16 pstat; + pSRB->MsgOutBuf[0] = MESSAGE_REJECT; + pSRB->MsgCnt = 1; + DC390_ENABLE_MSGOUT; + DEBUG0 (printk (KERN_INFO "DC390: Reject message\n")); +} - if (!pDCB) pDCB = pACB->pActiveDCB; - if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB; +/* abort command */ +static void +dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB ) +{ + pSRB->MsgOutBuf[0] = ABORT; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; +} - if (pSRB) +static struct dc390_srb* +dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag) +{ + struct dc390_srb* pSRB = pDCB->pGoingSRB; + + if (pSRB) { - printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n", - pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState, - pSRB->ScsiPhase); - printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus); + struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag); + pSRB = (struct dc390_srb *)scmd->host_scribble; + + if (pDCB->DCBFlag & ABORT_DEV_) + { + pSRB->SRBState = SRB_ABORT_SENT; + dc390_EnableMsgOut_Abort( pACB, pSRB ); + } + + if (!(pSRB->SRBState & SRB_DISCONNECT)) + goto mingx0; + + pDCB->pActiveSRB = pSRB; + pSRB->SRBState = SRB_DATA_XFER; } - printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus); - printk ("DC390: Register dump: SCSI block:\n"); - printk ("DC390: XferCnt Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n"); - printk ("DC390: %06x %02x %02x %02x", - DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16), - DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State)); - printk (" %02x %02x %02x %02x %02x %02x\n", - DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1), - DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4)); - DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); - if (DC390_read8(Current_Fifo) & 0x1f) - { - printk ("DC390: FIFO:"); - while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo)); - printk ("\n"); - } - printk ("DC390: Register dump: DMA engine:\n"); - printk ("DC390: Cmd STrCnt SBusA WrkBC WrkAC Stat SBusCtrl\n"); - printk ("DC390: %02x %08x %08x %08x %08x %02x %08x\n", - DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr), - DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr), - DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl)); - DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); + else + { + mingx0: + pSRB = pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = ABORT_TAG; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + } + return pSRB; +} - pdev = pACB->pdev; - pci_read_config_word(pdev, PCI_STATUS, &pstat); - printk ("DC390: Register dump: PCI Status: %04x\n", pstat); - printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n"); + +/* set async transfer mode */ +static void +dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB) +{ + struct dc390_dcb* pDCB = pSRB->pSRBDCB; + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID); + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 &= 0x3f; + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ + dc390_reprog (pACB, pDCB); } +/* set sync transfer mode */ +static void +dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB) +{ + u8 bval; + u16 wval, wval1; + struct dc390_dcb* pDCB = pSRB->pSRBDCB; + u8 oldsyncperiod = pDCB->SyncPeriod; + u8 oldsyncoffset = pDCB->SyncOffset; + + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + { + printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", + pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]); + + /* reject */ + //dc390_MsgIn_reject (pACB, pSRB); + //return dc390_MsgIn_set_async (pACB, pSRB); + + /* Reply with corrected SDTR Message */ + if (pSRB->MsgInBuf[4] > 15) + { + printk (KERN_INFO "DC390: Lower Sync Offset to 15\n"); + pSRB->MsgInBuf[4] = 15; + } + if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod) + { + printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); + pSRB->MsgInBuf[3] = pDCB->NegoPeriod; + } + memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); + pSRB->MsgCnt = 5; + DC390_ENABLE_MSGOUT; + } -/*********************************************************************** - * Function : int DC390_abort (struct scsi_cmnd *cmd) - * - * Purpose : Abort an errant SCSI command - * - * Inputs : cmd - command to abort - * - * Returns : 0 on success, -1 on failure. - * - * Status: Buggy ! - ***********************************************************************/ + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; + pDCB->SyncOffset &= 0x0f0; + pDCB->SyncOffset |= pSRB->MsgInBuf[4]; + pDCB->NegoPeriod = pSRB->MsgInBuf[3]; + + wval = (u16) pSRB->MsgInBuf[3]; + wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */ + if( (wval1 * 25) != wval) wval1++; + bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */ -static int DC390_abort (struct scsi_cmnd *cmd) + pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */ + if (pACB->glitch_cfg != NS_TO_GLITCH(0)) + pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1)); + else + pDCB->CtrlR4 |= NS_TO_GLITCH(0); + if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */ + + if (wval1 >= 8) + { + wval1--; /* Timing computation differs by 1 from FAST_SCSI */ + bval = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ + } + + pDCB->CtrlR3 = bval; + pDCB->SyncPeriod = (u8)wval1; + + if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0) + { + if (! (bval & FAST_SCSI)) wval1++; + printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, + 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f); + } + + dc390_reprog (pACB, pDCB); +} + + +/* handle RESTORE_PTR */ +/* I presume, this command is already mapped, so, have to remap. */ +static void +dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) { - struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata; - struct dc390_srb *pSRB, *psrb; - u32 count, i; - int status; - //unsigned long sbac; - struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata; + struct scsi_cmnd *pcmd = pSRB->pcmd; + struct scatterlist *psgl; + pSRB->TotalXferredLen = 0; + pSRB->SGIndex = 0; + if (pcmd->use_sg) { + pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; + psgl = pSRB->pSegmentList; + //dc390_pci_sync(pSRB); + + while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr) + { + pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl); + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + } + else + pSRB->SGToBeXferLen = 0; + } + pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", + pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); + + } else if(pcmd->request_buffer) { + //dc390_pci_sync(pSRB); + + sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr; + pSRB->SGcount = 1; + pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx; + } else { + pSRB->SGcount = 0; + printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n"); + } - printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", - cmd->pid, cmd->device->id, cmd->device->lun); + pSRB->TotalXferredLen = pSRB->Saved_Ptr; +} - if( !pDCB ) goto NOT_RUN; - /* Added 98/07/02 KG */ - /* - pSRB = pDCB->pActiveSRB; - if (pSRB && pSRB->pcmd == cmd ) - goto ON_GOING; - */ - - pSRB = pDCB->pWaitingSRB; - if( !pSRB ) - goto ON_GOING; +/* According to the docs, the AM53C974 reads the message and + * generates a Successful Operation IRQ before asserting ACK for + * the last byte (how does it know whether it's the last ?) */ +/* The old code handled it in another way, indicating, that on + * every message byte an IRQ is generated and every byte has to + * be manually ACKed. Hmmm ? (KG, 98/11/28) */ +/* The old implementation was correct. Sigh! */ + +/* Check if the message is complete */ +static u8 __inline__ +dc390_MsgIn_complete (u8 *msgbuf, u32 len) +{ + if (*msgbuf == EXTENDED_MESSAGE) + { + if (len < 2) return 0; + if (len < msgbuf[1] + 2) return 0; + } + else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages + if (len < 2) return 0; + return 1; +} + - /* Now scan Waiting queue */ - if( pSRB->pcmd == cmd ) + +/* read and eval received messages */ +static void +dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + struct dc390_dcb* pDCB = pACB->pActiveDCB; + + /* Read the msg */ + + pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo); + //pSRB->SRBState = 0; + + /* Msg complete ? */ + if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen)) + { + DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen)); + /* Now eval the msg */ + switch (pSRB->MsgInBuf[0]) + { + case DISCONNECT: + pSRB->SRBState = SRB_DISCONNECT; break; + + case SIMPLE_QUEUE_TAG: + case HEAD_OF_QUEUE_TAG: + case ORDERED_QUEUE_TAG: + pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]); + break; + + case MESSAGE_REJECT: + DC390_write8 (ScsiCmd, RESET_ATN_CMD); + pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + if( pSRB->SRBState & DO_SYNC_NEGO) + dc390_MsgIn_set_async (pACB, pSRB); + break; + + case EXTENDED_MESSAGE: + /* reject every extended msg but SDTR */ + if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR) + dc390_MsgIn_reject (pACB, pSRB); + else + { + if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0) + dc390_MsgIn_set_async (pACB, pSRB); + else + dc390_MsgIn_set_sync (pACB, pSRB); + } + + // nothing has to be done + case COMMAND_COMPLETE: break; + + // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the + // scsi command. Thanks, Gerard, for pointing it out. + case SAVE_POINTERS: + pSRB->Saved_Ptr = pSRB->TotalXferredLen; + break; + // The device might want to restart transfer with a RESTORE + case RESTORE_POINTERS: + DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n")); + dc390_restore_ptr (pACB, pSRB); + break; + + // reject unknown messages + default: dc390_MsgIn_reject (pACB, pSRB); + } + + /* Clear counter and MsgIn state */ + pSRB->SRBState &= ~SRB_MSGIN; + pACB->MsgLen = 0; + } + + *psstatus = SCSI_NOP0; + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); +} + + +static void +dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) +{ + struct scatterlist *psgl; + unsigned long lval; + struct dc390_dcb* pDCB = pACB->pActiveDCB; + + if (pSRB == pACB->pTmpSRB) { - pDCB->pWaitingSRB = pSRB->pNextSRB; - goto IN_WAIT; + if (pDCB) + printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN); + else + printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n"); + + /* Try to recover - some broken disks react badly to tagged INQUIRY */ + if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) { + pSRB = pDCB->pGoingSRB; + pDCB->pActiveSRB = pSRB; + } else { + pSRB->pSRBDCB = pDCB; + dc390_EnableMsgOut_Abort(pACB, pSRB); + if (pDCB) + pDCB->DCBFlag |= ABORT_DEV; + return; + } } - else + + if( pSRB->SGIndex < pSRB->SGcount ) { - psrb = pSRB; - if( !(psrb->pNextSRB) ) - goto ON_GOING; - while( psrb->pNextSRB->pcmd != cmd ) + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */); + if( !pSRB->SGToBeXferLen ) { - psrb = psrb->pNextSRB; - if( !(psrb->pNextSRB) || psrb == pSRB) - goto ON_GOING; + psgl = pSRB->pSegmentList; + pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); + pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.")); } - pSRB = psrb->pNextSRB; - psrb->pNextSRB = pSRB->pNextSRB; - if( pSRB == pDCB->pWaitLast ) - pDCB->pWaitLast = psrb; -IN_WAIT: - dc390_Free_insert (pACB, pSRB); - pDCB->WaitSRBCnt--; - INIT_LIST_HEAD((struct list_head*)&cmd->SCp); - status = SCSI_ABORT_SUCCESS; - goto ABO_X; + lval = pSRB->SGToBeXferLen; + DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr)); + DC390_write8 (CtcReg_Low, (u8) lval); + lval >>= 8; + DC390_write8 (CtcReg_Mid, (u8) lval); + lval >>= 8; + DC390_write8 (CtcReg_High, (u8) lval); + + DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen); + DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr); + + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ + pSRB->SRBState = SRB_DATA_XFER; + + DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); + + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT)); + //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status))); + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT)); + } + else /* xfer pad */ + { + if( pSRB->SGcount ) + { + pSRB->AdaptStatus = H_OVER_UNDER_RUN; + pSRB->SRBStatus |= OVER_RUN; + DEBUG0(printk (KERN_WARNING " DC390: Overrun -")); + } + DEBUG0(printk (KERN_WARNING " Clear transfer pad \n")); + DC390_write8 (CtcReg_Low, 0); + DC390_write8 (CtcReg_Mid, 0); + DC390_write8 (CtcReg_High, 0); + + pSRB->SRBState |= SRB_XFERPAD; + DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE); +/* + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT; + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); +*/ } +} + + +static void +dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION); +} + +static void +dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION); +} - /* SRB has already been sent ! */ -ON_GOING: - /* abort() is too stupid for already sent commands at the moment. - * If it's called we are in trouble anyway, so let's dump some info - * into the syslog at least. (KG, 98/08/20,99/06/20) */ - dc390_dumpinfo (pACB, pDCB, pSRB); - pSRB = pDCB->pGoingSRB; - pDCB->DCBFlag |= ABORT_DEV_; - /* Now for the hard part: The command is currently processed */ - for( count = pDCB->GoingSRBCnt, i=0; iSRBFlag & AUTO_REQSENSE) ) + { + cnt = (u8) pSRB->pcmd->cmd_len; + ptr = (u8 *) pSRB->pcmd->cmnd; + for(i=0; i < cnt; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + } + else { - if( pSRB->pcmd != cmd ) - pSRB = pSRB->pNextSRB; + DC390_write8 (ScsiFifo, REQUEST_SENSE); + pDCB = pACB->pActiveDCB; + DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); + DC390_write8 (ScsiFifo, 0); + DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n")); + } + pSRB->SRBState = SRB_COMMAND; + DC390_write8 (ScsiCmd, INFO_XFER_CMD); +} + +static void +dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pSRB->SRBState = SRB_STATUS; + DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); +} + +static void +dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + u8 bval, i, cnt; + u8 *ptr; + struct dc390_dcb* pDCB; + + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pDCB = pACB->pActiveDCB; + if( !(pSRB->SRBState & SRB_MSGOUT) ) + { + cnt = pSRB->MsgCnt; + if( cnt ) + { + ptr = (u8 *) pSRB->MsgOutBuf; + for(i=0; i < cnt; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + pSRB->MsgCnt = 0; + if( (pDCB->DCBFlag & ABORT_DEV_) && + (pSRB->MsgOutBuf[0] == ABORT) ) + pSRB->SRBState = SRB_ABORT_SENT; + } else { - if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) + bval = ABORT; /* ??? MSG_NOP */ + if( (pSRB->pcmd->cmnd[0] == INQUIRY ) || + (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) { - status = SCSI_ABORT_BUSY; - printk ("DC390: Abort current command (pid %li, SRB %p)\n", - cmd->pid, pSRB); - goto ABO_X; + if( pDCB->SyncMode & SYNC_ENABLE ) + goto mop1; } - else + DC390_write8 (ScsiFifo, bval); + } + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + } + else + { +mop1: + printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN); + DC390_write8 (ScsiFifo, EXTENDED_MESSAGE); + DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */ + DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */ + DC390_write8 (ScsiFifo, pDCB->NegoPeriod); + if (pDCB->SyncOffset & 0x0f) + DC390_write8 (ScsiFifo, pDCB->SyncOffset); + else + DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET); + pSRB->SRBState |= DO_SYNC_NEGO; + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + } +} + +static void +dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + if( !(pSRB->SRBState & SRB_MSGIN) ) + { + pSRB->SRBState &= ~SRB_DISCONNECT; + pSRB->SRBState |= SRB_MSGIN; + } + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); +} + +static void +dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ +} + +static void +dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +{ +} + + +static void +dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB ) +{ + u8 bval, i, cnt; + struct dc390_dcb* ptr; + + if( !(pDCB->TargetLUN) ) + { + if( !pACB->scan_devices ) + { + ptr = pACB->pLinkDCB; + cnt = pACB->DCBCnt; + bval = pDCB->TargetID; + for(i=0; iTargetID == bval ) + { + ptr->SyncPeriod = pDCB->SyncPeriod; + ptr->SyncOffset = pDCB->SyncOffset; + ptr->CtrlR3 = pDCB->CtrlR3; + ptr->CtrlR4 = pDCB->CtrlR4; + ptr->SyncMode = pDCB->SyncMode; + } + ptr = ptr->pNextDCB; } } } + return; +} -NOT_RUN: - status = SCSI_ABORT_NOT_RUNNING; -ABO_X: - cmd->result = DID_ABORT << 16; - printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status); -#if 0 - if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */ +static void +dc390_Disconnect( struct dc390_acb* pACB ) +{ + struct dc390_dcb *pDCB; + struct dc390_srb *pSRB, *psrb; + u8 i, cnt; + + DEBUG0(printk(KERN_INFO "DISC,")); + + if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n"); + pACB->Connected = 0; + pDCB = pACB->pActiveDCB; + if (!pDCB) + { + DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\ + pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel)); + mdelay(400); + DC390_read8 (INT_Status); /* Reset Pending INT */ + DC390_write8 (ScsiCmd, EN_SEL_RESEL); + return; + } + DC390_write8 (ScsiCmd, EN_SEL_RESEL); + pSRB = pDCB->pActiveSRB; + pACB->pActiveDCB = NULL; + pSRB->ScsiPhase = SCSI_NOP0; + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + pSRB->SRBState = 0; + else if( pSRB->SRBState & SRB_ABORT_SENT ) + { + pDCB->TagMask = 0; + pDCB->DCBFlag = 0; + cnt = pDCB->GoingSRBCnt; + pDCB->GoingSRBCnt = 0; + pSRB = pDCB->pGoingSRB; + for( i=0; i < cnt; i++) { - /* Let's do something to help the bus getting clean again */ - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); - DC390_write8 (ScsiCmd, DMA_COMMAND); - //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); - //DC390_write8 (ScsiCmd, RESET_ATN_CMD); - DC390_write8 (ScsiCmd, NOP_CMD); - //udelay (10000); - //DC390_read8 (INT_Status); - //DC390_write8 (ScsiCmd, EN_SEL_RESEL); + psrb = pSRB->pNextSRB; + dc390_Free_insert (pACB, pSRB); + pSRB = psrb; } - sbac = DC390_read32 (DMA_ScsiBusCtrl); - if (sbac & SCSI_BUSY) - { /* clear BSY, SEL and ATN */ - printk (KERN_WARNING "DC390: Reset SCSI device: "); - //DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES); - //udelay (250); - //sbac = DC390_read32 (DMA_ScsiBusCtrl); - //printk ("%08lx ", sbac); - //DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM)); - //udelay (100); - //sbac = DC390_read32 (DMA_ScsiBusCtrl); - //printk ("%08lx ", sbac); - DC390_write8 (ScsiCmd, RST_DEVICE_CMD); - udelay (250); - DC390_write8 (ScsiCmd, NOP_CMD); - sbac = DC390_read32 (DMA_ScsiBusCtrl); - printk ("%08lx\n", sbac); + pDCB->pGoingSRB = NULL; } -#endif - dc390_lastabortedpid = cmd->pid; - //do_DC390_Interrupt (pACB->IRQLevel, 0, 0); -#ifndef USE_NEW_EH - if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd); -#endif - return( status ); + else + { + if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || + !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) + { /* Selection time out */ + pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; + goto disc1; + } + else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED)) + { +disc1: + dc390_freetag (pDCB, pSRB); + pDCB->pActiveSRB = NULL; + pSRB->SRBState = SRB_FREE; + dc390_SRBdone( pACB, pDCB, pSRB); + } + } + pACB->MsgLen = 0; } -static void dc390_ResetDevParam( struct dc390_acb* pACB ) +static void +dc390_Reselect( struct dc390_acb* pACB ) { - struct dc390_dcb *pDCB, *pdcb; + struct dc390_dcb* pDCB; + struct dc390_srb* pSRB; + u8 id, lun; + + DEBUG0(printk(KERN_INFO "RSEL,")); + pACB->Connected = 1; + pDCB = pACB->pActiveDCB; + if( pDCB ) + { /* Arbitration lost but Reselection won */ + DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n")); + pSRB = pDCB->pActiveSRB; + if( !( pACB->scan_devices ) ) + { + struct scsi_cmnd *pcmd = pSRB->pcmd; + pcmd->resid = pcmd->request_bufflen; + SET_RES_DID(pcmd->result, DID_SOFT_ERROR); + dc390_Going_remove(pDCB, pSRB); + dc390_Free_insert(pACB, pSRB); + pcmd->scsi_done (pcmd); + DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB)); + } + } + /* Get ID */ + lun = DC390_read8 (ScsiFifo); + DEBUG0(printk ("Dev %02x,", lun)); + if (!(lun & (1 << pACB->pScsiHost->this_id))) + printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun); + else + lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ + id = 0; while (lun >>= 1) id++; + /* Get LUN */ + lun = DC390_read8 (ScsiFifo); + if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n"); + lun &= 7; + DEBUG0(printk ("(%02i-%i),", id, lun)); + pDCB = dc390_findDCB (pACB, id, lun); + if (!pDCB) + { + printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n", + id, lun); + return; + } + pACB->pActiveDCB = pDCB; + /* TagQ: We expect a message soon, so never mind the exact SRB */ + if( pDCB->SyncMode & EN_TAG_QUEUEING ) + { + pSRB = pACB->pTmpSRB; + pDCB->pActiveSRB = pSRB; + } + else + { + pSRB = pDCB->pActiveSRB; + if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) + { + pSRB= pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n", + id, lun); + pDCB->pActiveSRB = pSRB; + dc390_EnableMsgOut_Abort ( pACB, pSRB ); + } + else + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n", + id, lun); + dc390_EnableMsgOut_Abort( pACB, pSRB ); + } + else + pSRB->SRBState = SRB_DATA_XFER; + } + } - pDCB = pACB->pLinkDCB; - if (! pDCB) return; - pdcb = pDCB; - do + DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber)); + pSRB->ScsiPhase = SCSI_NOP0; + DC390_write8 (Scsi_Dest_ID, pDCB->TargetID); + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg1, pDCB->CtrlR1); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */ + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */ +} + +static int __inline__ +dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +{ + struct scsi_cmnd *pcmd; + + pcmd = pSRB->pcmd; + + REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\ + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN)); + + pSRB->SRBFlag |= AUTO_REQSENSE; + pSRB->SavedSGCount = pcmd->use_sg; + pSRB->SavedTotXLen = pSRB->TotalXferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ + + /* We are called from SRBdone, original PCI mapping has been removed + * already, new one is set up from StartSCSI */ + pSRB->SGIndex = 0; + + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + return dc390_StartSCSI(pACB, pDCB, pSRB); +} + + +static void +dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) +{ + u8 status; + struct scsi_cmnd *pcmd; + + pcmd = pSRB->pcmd; + /* KG: Moved pci_unmap here */ + dc390_pci_unmap(pSRB); + + status = pSRB->TargetStatus; + + DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ + pSRB, pcmd->pid)); + if(pSRB->SRBFlag & AUTO_REQSENSE) + { /* Last command was a Request Sense */ + pSRB->SRBFlag &= ~AUTO_REQSENSE; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = CHECK_CONDITION << 1; + + //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status); + if (status == (CHECK_CONDITION << 1)) + pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0); + else /* Retry */ + { + if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */) + { + /* Don't retry on TEST_UNIT_READY */ + pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION); + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\ + (u32) pcmd->result, (u32) pSRB->TotalXferredLen)); + } else { + SET_RES_DRV(pcmd->result, DRIVER_SENSE); + pcmd->use_sg = pSRB->SavedSGCount; + //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + pSRB->TotalXferredLen = 0; + SET_RES_DID(pcmd->result, DID_SOFT_ERROR); + } + } + goto cmd_done; + } + if( status ) { - pDCB->SyncMode &= ~SYNC_NEGO_DONE; - pDCB->SyncPeriod = 0; - pDCB->SyncOffset = 0; - pDCB->TagMask = 0; - pDCB->CtrlR3 = FAST_CLK; - pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK; - pDCB->CtrlR4 |= pACB->glitch_cfg; - pDCB = pDCB->pNextDCB; + if( status_byte(status) == CHECK_CONDITION ) + { + if (dc390_RequestSense(pACB, pDCB, pSRB)) { + SET_RES_DID(pcmd->result, DID_ERROR); + goto cmd_done; + } + return; + } + else if( status_byte(status) == QUEUE_FULL ) + { + scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); + pcmd->use_sg = pSRB->SavedSGCount; + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + pSRB->TotalXferredLen = 0; + SET_RES_DID(pcmd->result, DID_SOFT_ERROR); + } + else if(status == SCSI_STAT_SEL_TIMEOUT) + { + pSRB->AdaptStatus = H_SEL_TIMEOUT; + pSRB->TargetStatus = 0; + pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0); + /* Devices are removed below ... */ + } + else if (status_byte(status) == BUSY && + (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) && + pACB->scan_devices) + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = status; + pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0); + } + else + { /* Another error */ + pSRB->TotalXferredLen = 0; + SET_RES_DID(pcmd->result, DID_SOFT_ERROR); + goto cmd_done; + } + } + else + { /* Target status == 0 */ + status = pSRB->AdaptStatus; + if(status & H_OVER_UNDER_RUN) + { + pSRB->TargetStatus = 0; + SET_RES_DID(pcmd->result,DID_OK); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + } + else if( pSRB->SRBStatus & PARITY_ERROR) + { + //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0); + SET_RES_DID(pcmd->result,DID_PARITY); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + } + else /* No error */ + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + SET_RES_DID(pcmd->result,DID_OK); + } } - while( pdcb != pDCB ); - pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT); +cmd_done: + pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; + + dc390_Going_remove (pDCB, pSRB); + /* Add to free list */ + dc390_Free_insert (pACB, pSRB); + + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); + pcmd->scsi_done (pcmd); + + return; } -#if 0 -/* Moves all SRBs from Going to Waiting for all DCBs */ -static void dc390_RecoverSRB( struct dc390_acb* pACB ) + +/* Remove all SRBs from Going list and inform midlevel */ +static void +dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd) { struct dc390_dcb *pDCB, *pdcb; struct dc390_srb *psrb, *psrb2; - u32 cnt, i; + int i; + struct scsi_cmnd *pcmd; pDCB = pACB->pLinkDCB; - if( !pDCB ) return; pdcb = pDCB; + if (! pdcb) return; do { - cnt = pdcb->GoingSRBCnt; psrb = pdcb->pGoingSRB; - for (i=0; iGoingSRBCnt; i++) { - psrb2 = psrb; - psrb = psrb->pNextSRB; -/* dc390_RewaitSRB( pDCB, psrb ); */ - if( pdcb->pWaitingSRB ) - { - psrb2->pNextSRB = pdcb->pWaitingSRB; - pdcb->pWaitingSRB = psrb2; - } - else - { - pdcb->pWaitingSRB = psrb2; - pdcb->pWaitLast = psrb2; - psrb2->pNextSRB = NULL; - } + psrb2 = psrb->pNextSRB; + pcmd = psrb->pcmd; + dc390_Free_insert (pACB, psrb); + psrb = psrb2; } pdcb->GoingSRBCnt = 0; pdcb->pGoingSRB = NULL; @@ -1423,278 +1918,231 @@ static void dc390_RecoverSRB( struct dc390_acb* pACB ) pdcb = pdcb->pNextDCB; } while( pdcb != pDCB ); } -#endif -/*********************************************************************** - * Function : int DC390_reset (struct scsi_cmnd *cmd, ...) - * - * Purpose : perform a hard reset on the SCSI bus - * - * Inputs : cmd - command which caused the SCSI RESET - * resetFlags - how hard to try - * - * Returns : 0 on success. - ***********************************************************************/ -static int DC390_reset (struct scsi_cmnd *cmd) +static void +dc390_ResetSCSIBus( struct dc390_acb* pACB ) { - u8 bval; - struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; + //DC390_write8 (ScsiCmd, RST_DEVICE_CMD); + //udelay (250); + //DC390_write8 (ScsiCmd, NOP_CMD); - printk(KERN_INFO "DC390: RESET ... "); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD); + pACB->Connected = 0; - if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); - bval = DC390_read8 (CtrlReg1); - bval |= DIS_INT_ON_SCSI_RST; - DC390_write8 (CtrlReg1, bval); /* disable IRQ on bus reset */ + return; +} - pACB->ACBFlag |= RESET_DEV; - dc390_ResetSCSIBus( pACB ); +static void +dc390_ScsiRstDetect( struct dc390_acb* pACB ) +{ + printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus); + //DEBUG0(printk(KERN_INFO "RST_DETECT,")); - dc390_ResetDevParam( pACB ); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + /* Unlock before ? */ + /* delay half a second */ udelay (1000); - pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 - + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); - DC390_read8 (INT_Status); /* Reset Pending INT */ + pACB->pScsiHost->last_reset = jiffies + 5*HZ/2 + + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; + pACB->Connected = 0; - dc390_DoingSRB_Done( pACB, cmd ); - /* dc390_RecoverSRB (pACB); */ - pACB->pActiveDCB = NULL; + if( pACB->ACBFlag & RESET_DEV ) + pACB->ACBFlag |= RESET_DONE; + else + { /* Reset was issued by sb else */ + pACB->ACBFlag |= RESET_DETECT; + + dc390_ResetDevParam( pACB ); + dc390_DoingSRB_Done( pACB, NULL); + //dc390_RecoverSRB( pACB ); + pACB->pActiveDCB = NULL; + pACB->ACBFlag = 0; + } + return; +} + +static int DC390_queuecommand(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) +{ + struct scsi_device *sdev = cmd->device; + struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata; + struct dc390_dcb *dcb = sdev->hostdata; + struct dc390_srb *srb; + + if (sdev->queue_depth <= dcb->GoingSRBCnt) + goto device_busy; + if (acb->pActiveDCB) + goto host_busy; + if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV)) + goto host_busy; + + srb = acb->pFreeSRB; + if (unlikely(srb == NULL)) + goto host_busy; + + cmd->scsi_done = done; + cmd->result = 0; + acb->Cmds++; + + acb->pFreeSRB = srb->pNextSRB; + srb->pNextSRB = NULL; + + srb->pSRBDCB = dcb; + srb->pcmd = cmd; + cmd->host_scribble = (char *)srb; + + srb->SGIndex = 0; + srb->AdaptStatus = 0; + srb->TargetStatus = 0; + srb->MsgCnt = 0; + + srb->SRBStatus = 0; + srb->SRBFlag = 0; + srb->SRBState = 0; + srb->TotalXferredLen = 0; + srb->SGBusAddr = 0; + srb->SGToBeXferLen = 0; + srb->ScsiPhase = 0; + srb->EndMessage = 0; + srb->TagNumber = SCSI_NO_TAG; + + if (dc390_StartSCSI(acb, dcb, srb)) { + dc390_Free_insert(acb, srb); + goto host_busy; + } + + dc390_Going_append(dcb, srb); + + return 0; + + host_busy: + return SCSI_MLQUEUE_HOST_BUSY; + + device_busy: + return SCSI_MLQUEUE_DEVICE_BUSY; +} - pACB->ACBFlag = 0; - bval = DC390_read8 (CtrlReg1); - bval &= ~DIS_INT_ON_SCSI_RST; - DC390_write8 (CtrlReg1, bval); /* re-enable interrupt */ +static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) +{ + struct pci_dev *pdev; + u16 pstat; + + if (!pDCB) pDCB = pACB->pActiveDCB; + if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB; - dc390_Waiting_process( pACB ); + if (pSRB) + { + printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n", + pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState, + pSRB->ScsiPhase); + printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus); + } + printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus); + printk ("DC390: Register dump: SCSI block:\n"); + printk ("DC390: XferCnt Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n"); + printk ("DC390: %06x %02x %02x %02x", + DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16), + DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State)); + printk (" %02x %02x %02x %02x %02x %02x\n", + DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1), + DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4)); + DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); + if (DC390_read8(Current_Fifo) & 0x1f) + { + printk ("DC390: FIFO:"); + while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo)); + printk ("\n"); + } + printk ("DC390: Register dump: DMA engine:\n"); + printk ("DC390: Cmd STrCnt SBusA WrkBC WrkAC Stat SBusCtrl\n"); + printk ("DC390: %02x %08x %08x %08x %08x %02x %08x\n", + DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr), + DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr), + DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl)); + DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); - printk("done\n"); - return( SCSI_RESET_SUCCESS ); + pdev = pACB->pdev; + pci_read_config_word(pdev, PCI_STATUS, &pstat); + printk ("DC390: Register dump: PCI Status: %04x\n", pstat); + printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n"); } -#include "scsiiom.c" - -/*********************************************************************** - * Function : static void dc390_updateDCB() - * - * Purpose : Set the configuration dependent DCB parameters - ***********************************************************************/ -static void dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB) +static int DC390_abort(struct scsi_cmnd *cmd) { - pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/; - if (pDCB->DevMode & TAG_QUEUEING_) { - //if (pDCB->SyncMode & EN_TAG_QUEUEING) pDCB->MaxCommand = pACB->TagMaxNum; - } else { - pDCB->SyncMode &= ~EN_TAG_QUEUEING; - pDCB->MaxCommand = 1; - } - - if( pDCB->DevMode & SYNC_NEGO_ ) - pDCB->SyncMode |= SYNC_ENABLE; - else { - pDCB->SyncMode &= ~(SYNC_NEGO_DONE | SYNC_ENABLE); - pDCB->SyncOffset &= ~0x0f; - } + struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata; + struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata; - //if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; + printk("DC390: Abort command (pid %li, Device %02i-%02i)\n", + cmd->pid, cmd->device->id, cmd->device->lun); - pDCB->CtrlR1 = pACB->pScsiHost->this_id; - if( pDCB->DevMode & PARITY_CHK_ ) - pDCB->CtrlR1 |= PARITY_ERR_REPO; -} + /* abort() is too stupid for already sent commands at the moment. + * If it's called we are in trouble anyway, so let's dump some info + * into the syslog at least. (KG, 98/08/20,99/06/20) */ + dc390_dumpinfo(pACB, pDCB, NULL); -/*********************************************************************** - * Function : static void dc390_initSRB() - * - * Purpose : initialize the internal structures for a given SRB - * - * Inputs : psrb - pointer to this scsi request block structure - ***********************************************************************/ + pDCB->DCBFlag |= ABORT_DEV_; + printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid); -static void __inline__ dc390_initSRB( struct dc390_srb* psrb ) -{ - /* psrb->PhysSRB = virt_to_phys( psrb ); */ + return FAILED; } -static void dc390_linkSRB( struct dc390_acb* pACB ) +static void dc390_ResetDevParam( struct dc390_acb* pACB ) { - u32 count, i; + struct dc390_dcb *pDCB, *pdcb; - count = pACB->SRBCount; - for( i=0; ipLinkDCB; + if (! pDCB) return; + pdcb = pDCB; + do { - if( i != count-1 ) - pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; - else - pACB->SRB_array[i].pNextSRB = NULL; - dc390_initSRB( &pACB->SRB_array[i] ); + pDCB->SyncMode &= ~SYNC_NEGO_DONE; + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->TagMask = 0; + pDCB->CtrlR3 = FAST_CLK; + pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK; + pDCB->CtrlR4 |= pACB->glitch_cfg; + pDCB = pDCB->pNextDCB; } -} - - -/*********************************************************************** - * Function : static void dc390_initACB () - * - * Purpose : initialize the internal structures for a given SCSI host - * - * Inputs : psh - pointer to this host adapter's structure - * io_port, Irq, index: Resources and adapter index - ***********************************************************************/ - -static void __devinit dc390_initACB (struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index) -{ - struct dc390_acb* pACB; - u8 i; - - psh->can_queue = MAX_CMD_QUEUE; - psh->cmd_per_lun = MAX_CMD_PER_LUN; - psh->this_id = (int) dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; - psh->io_port = io_port; - psh->n_io_port = 0x80; - psh->irq = Irq; - psh->base = io_port; - psh->unique_id = io_port; - psh->dma_channel = -1; - psh->last_reset = jiffies; - - pACB = (struct dc390_acb*) psh->hostdata; - - pACB->pScsiHost = psh; - pACB->IOPortBase = (u16) io_port; - pACB->IRQLevel = Irq; - - DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \ - index, psh->this_id, (int)io_port, Irq)); - - psh->max_id = 8; - - if( psh->max_id - 1 == dc390_eepromBuf[index][EE_ADAPT_SCSI_ID] ) - psh->max_id--; - psh->max_lun = 1; - if( dc390_eepromBuf[index][EE_MODE2] & LUN_CHECK ) - psh->max_lun = 8; + while( pdcb != pDCB ); + pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT); - pACB->pLinkDCB = NULL; - pACB->pDCBRunRobin = NULL; - pACB->pActiveDCB = NULL; - pACB->pFreeSRB = pACB->SRB_array; - pACB->SRBCount = MAX_SRB_CNT; - pACB->AdapterIndex = index; - pACB->status = 0; - pACB->DCBCnt = 0; - pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM]; - pACB->ACBFlag = 0; - pACB->scan_devices = 1; - pACB->MsgLen = 0; - pACB->Ignore_IRQ = 0; - pACB->Gmode2 = dc390_eepromBuf[index][EE_MODE2]; - dc390_linkSRB( pACB ); - pACB->pTmpSRB = &pACB->TmpSRB; - dc390_initSRB( pACB->pTmpSRB ); - for(i=0; iDCBmap[i] = 0; - pACB->sel_timeout = SEL_TIMEOUT; - pACB->glitch_cfg = EATER_25NS; - pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0; - pACB->SelLost = pACB->SelConn = 0; - init_timer (&pACB->Waiting_Timer); } - -/*********************************************************************** - * Function : static int dc390_initAdapter () - * - * Purpose : initialize the SCSI chip ctrl registers - * - * Inputs : psh - pointer to this host adapter's structure - * io_port, Irq, index: Resources - * - * Outputs: 0 on success, -1 on error - ***********************************************************************/ - -static int __devinit dc390_initAdapter (struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index) +static int DC390_bus_reset (struct scsi_cmnd *cmd) { - struct dc390_acb *pACB, *pACB2; - u8 dstate; - int i; - - pACB = (struct dc390_acb*) psh->hostdata; - - if (request_region (io_port, psh->n_io_port, "tmscsim") == NULL) { - printk(KERN_ERR "DC390: register IO ports error!\n"); - return( -1 ); - } - - DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */ - - if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", pACB) )) - { - printk(KERN_ERR "DC390: register IRQ error!\n"); - release_region (io_port, psh->n_io_port); - return( -1 ); - } + struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; + u8 bval; - if( !dc390_pACB_start ) - { - pACB2 = NULL; - dc390_pACB_start = pACB; - dc390_pACB_current = pACB; - pACB->pNextACB = NULL; - } - else - { - pACB2 = dc390_pACB_current; - dc390_pACB_current->pNextACB = pACB; - dc390_pACB_current = pACB; - pACB->pNextACB = NULL; - } + bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST; + DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */ - DC390_write8 (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id); /* Disable SCSI bus reset interrupt */ + pACB->ACBFlag |= RESET_DEV; + dc390_ResetSCSIBus(pACB); - if (pACB->Gmode2 & RST_SCSI_BUS) - { - dc390_ResetSCSIBus( pACB ); - udelay (1000); - pACB->pScsiHost->last_reset = jiffies + HZ/2 - + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; - /* - for( i=0; i<(500 + 1000*dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); i++ ) - udelay(1000); - */ - } - pACB->ACBFlag = 0; - DC390_read8 (INT_Status); /* Reset Pending INT */ + dc390_ResetDevParam(pACB); + udelay(1000); + pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 + + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; - DC390_write8 (Scsi_TimeOut, SEL_TIMEOUT); /* 250ms selection timeout */ - DC390_write8 (Clk_Factor, CLK_FREQ_40MHZ); /* Conversion factor = 0 , 40MHz clock */ - DC390_write8 (ScsiCmd, NOP_CMD); /* NOP cmd - clear command register */ - DC390_write8 (CtrlReg2, EN_FEATURE+EN_SCSI2_CMD); /* Enable Feature and SCSI-2 */ - DC390_write8 (CtrlReg3, FAST_CLK); /* fast clock */ - DC390_write8 (CtrlReg4, pACB->glitch_cfg | /* glitch eater */ - (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0); /* Negation */ - DC390_write8 (CtcReg_High, 0); /* Clear Transfer Count High: ID */ - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); - DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); - dstate = DC390_read8 (DMA_Status); - DC390_write8 (DMA_Status, dstate); /* clear */ + DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); + DC390_read8(INT_Status); /* Reset Pending INT */ - return(0); -} + dc390_DoingSRB_Done(pACB, cmd); + pACB->pActiveDCB = NULL; + pACB->ACBFlag = 0; -static void __devinit dc390_set_pci_cfg (struct pci_dev *pdev) -{ - u16 cmd; + bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST; + DC390_write8(CtrlReg1, bval); /* re-enable interrupt */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); + return SUCCESS; } /** @@ -1706,7 +2154,7 @@ static void __devinit dc390_set_pci_cfg (struct pci_dev *pdev) static int dc390_slave_alloc(struct scsi_device *scsi_device) { struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata; - struct dc390_dcb *pDCB, *pDCB2 = 0; + struct dc390_dcb *pDCB, *pDCB2 = NULL; uint id = scsi_device->id; uint lun = scsi_device->lun; @@ -1728,7 +2176,6 @@ static int dc390_slave_alloc(struct scsi_device *scsi_device) pDCB->pDCBACB = pACB; pDCB->TargetID = id; pDCB->TargetLUN = lun; - pDCB->MaxCommand = 1; /* * Some values are for all LUNs: Copy them @@ -1736,14 +2183,13 @@ static int dc390_slave_alloc(struct scsi_device *scsi_device) */ if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) { pDCB->DevMode = pDCB2->DevMode; - pDCB->SyncMode = pDCB2->SyncMode; + pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE; pDCB->SyncPeriod = pDCB2->SyncPeriod; pDCB->SyncOffset = pDCB2->SyncOffset; pDCB->NegoPeriod = pDCB2->NegoPeriod; pDCB->CtrlR3 = pDCB2->CtrlR3; pDCB->CtrlR4 = pDCB2->CtrlR4; - pDCB->Inquiry7 = pDCB2->Inquiry7; } else { u8 index = pACB->AdapterIndex; PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2]; @@ -1757,8 +2203,16 @@ static int dc390_slave_alloc(struct scsi_device *scsi_device) pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK; } - pACB->DCBmap[id] |= (1 << lun); - dc390_updateDCB(pACB, pDCB); + if (pDCB->DevMode & SYNC_NEGO_) + pDCB->SyncMode |= SYNC_ENABLE; + else { + pDCB->SyncMode = 0; + pDCB->SyncOffset &= ~0x0f; + } + + pDCB->CtrlR1 = pACB->pScsiHost->this_id; + if (pDCB->DevMode & PARITY_CHK_) + pDCB->CtrlR1 |= PARITY_ERR_REPO; pACB->scan_devices = 1; scsi_device->hostdata = pDCB; @@ -1781,8 +2235,6 @@ static void dc390_slave_destroy(struct scsi_device *scsi_device) BUG_ON(pDCB->GoingSRBCnt > 1); - pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN); - if (pDCB == pACB->pLinkDCB) { if (pACB->pLastDCB == pDCB) { pDCB->pNextDCB = NULL; @@ -1808,103 +2260,347 @@ static void dc390_slave_destroy(struct scsi_device *scsi_device) pACB->DCBCnt--; } -static int dc390_slave_configure(struct scsi_device *scsi_device) +static int dc390_slave_configure(struct scsi_device *sdev) { - struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata; - pACB->scan_devices = 0; + struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata; + struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata; + + acb->scan_devices = 0; + if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) { + dcb->SyncMode |= EN_TAG_QUEUEING; + scsi_activate_tcq(sdev, acb->TagMaxNum); + } + return 0; } static struct scsi_host_template driver_template = { .module = THIS_MODULE, .proc_name = "tmscsim", - .proc_info = DC390_proc_info, .name = DC390_BANNER " V" DC390_VERSION, .slave_alloc = dc390_slave_alloc, .slave_configure = dc390_slave_configure, .slave_destroy = dc390_slave_destroy, - .queuecommand = DC390_queue_command, + .queuecommand = DC390_queuecommand, .eh_abort_handler = DC390_abort, - .eh_bus_reset_handler = DC390_reset, - .bios_param = DC390_bios_param, - .can_queue = 42, + .eh_bus_reset_handler = DC390_bus_reset, + .can_queue = 1, .this_id = 7, .sg_tablesize = SG_ALL, - .cmd_per_lun = 16, + .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, }; -static int __devinit dc390_init_one(struct pci_dev *dev, - const struct pci_device_id *id) +/*********************************************************************** + * Functions for access to DC390 EEPROM + * and some to emulate it + * + **********************************************************************/ + +static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd) { - struct Scsi_Host *scsi_host; - unsigned long io_port; - u8 irq; - struct dc390_acb* pACB; - int ret = -ENOMEM; + u8 carryFlag = 1, j = 0x80, bval; + int i; + + for (i = 0; i < 9; i++) { + if (carryFlag) { + pci_write_config_byte(pdev, 0x80, 0x40); + bval = 0xc0; + } else + bval = 0x80; + + udelay(160); + pci_write_config_byte(pdev, 0x80, bval); + udelay(160); + pci_write_config_byte(pdev, 0x80, 0); + udelay(160); + + carryFlag = (cmd & j) ? 1 : 0; + j >>= 1; + } +} + +static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev) +{ + int i; + u16 wval = 0; + u8 bval; + + for (i = 0; i < 16; i++) { + wval <<= 1; + + pci_write_config_byte(pdev, 0x80, 0x80); + udelay(160); + pci_write_config_byte(pdev, 0x80, 0x40); + udelay(160); + pci_read_config_byte(pdev, 0x00, &bval); + + if (bval == 0x22) + wval |= 1; + } + + return wval; +} + +static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr) +{ + u8 cmd = EEPROM_READ, i; + + for (i = 0; i < 0x40; i++) { + pci_write_config_byte(pdev, 0xc0, 0); + udelay(160); + + dc390_eeprom_prepare_read(pdev, cmd++); + *ptr++ = dc390_eeprom_get_data(pdev); + + pci_write_config_byte(pdev, 0x80, 0); + pci_write_config_byte(pdev, 0x80, 0); + udelay(160); + } +} - if (pci_enable_device(dev)) - return -ENODEV; +/* Override EEprom values with explicitly set values */ +static void __devinit dc390_eeprom_override(u8 index) +{ + u8 *ptr = (u8 *) dc390_eepromBuf[index], id; + + /* Adapter Settings */ + if (tmscsim[0] != -2) + ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */ + if (tmscsim[3] != -2) + ptr[EE_MODE2] = (u8)tmscsim[3]; + if (tmscsim[5] != -2) + ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */ + if (tmscsim[4] != -2) + ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */ + + /* Device Settings */ + for (id = 0; id < MAX_SCSI_ID; id++) { + if (tmscsim[2] != -2) + ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */ + if (tmscsim[1] != -2) + ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */ + } +} + +static int __devinitdata tmscsim_def[] = { + 7, + 0 /* 10MHz */, + PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_, + MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK, + 3 /* 16 Tags per LUN */, + 1 /* s delay after Reset */, +}; + +/* Copy defaults over set values where missing */ +static void __devinit dc390_fill_with_defaults (void) +{ + int i; + + for (i = 0; i < 6; i++) { + if (tmscsim[i] < 0 || tmscsim[i] > 255) + tmscsim[i] = tmscsim_def[i]; + } + + /* Sanity checks */ + if (tmscsim[0] > 7) + tmscsim[0] = 7; + if (tmscsim[1] > 7) + tmscsim[1] = 4; + if (tmscsim[4] > 5) + tmscsim[4] = 4; + if (tmscsim[5] > 180) + tmscsim[5] = 180; +} + +static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index) +{ + u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120}; + u8 EEbuf[128]; + u16 *ptr = (u16 *)EEbuf, wval = 0; + int i; - io_port = pci_resource_start(dev, 0); - irq = dev->irq; + dc390_read_eeprom(pdev, ptr); + memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID); + memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], + &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID); - /* allocate scsi host information (includes out adapter) */ - scsi_host = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb)); - if (!scsi_host) - goto nomem; + dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]]; - pACB = (struct dc390_acb*) scsi_host->hostdata; + for (i = 0; i < 0x40; i++, ptr++) + wval += *ptr; - if (dc390_CheckEEpromCheckSum (dev, dc390_adapterCnt)) { + /* no Tekram EEprom found */ + if (wval != 0x1234) { int speed; - dc390_adapname = "AM53C974"; + printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n"); - dc390_check_for_safe_settings(); + + /* + * XXX(hch): bogus, because we might have tekram and + * non-tekram hbas in a single machine. + */ dc390_fill_with_defaults(); - dc390_EEprom_Override(dc390_adapterCnt); + speed = dc390_clock_speed[tmscsim[1]]; - printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz)," - " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", - tmscsim[0], tmscsim[1], speed/10, speed%10, + printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), " + "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", + tmscsim[0], tmscsim[1], speed / 10, speed % 10, (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]); - } else { - dc390_check_for_safe_settings(); - dc390_EEprom_Override(dc390_adapterCnt); } +} + +static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index) +{ + struct Scsi_Host *shost = pACB->pScsiHost; + u8 dstate; + + /* Disable SCSI bus reset interrupt */ + DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id); + + if (pACB->Gmode2 & RST_SCSI_BUS) { + dc390_ResetSCSIBus(pACB); + udelay(1000); + shost->last_reset = jiffies + HZ/2 + + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; + } + + pACB->ACBFlag = 0; + + /* Reset Pending INT */ + DC390_read8(INT_Status); + + /* 250ms selection timeout */ + DC390_write8(Scsi_TimeOut, SEL_TIMEOUT); + + /* Conversion factor = 0 , 40MHz clock */ + DC390_write8(Clk_Factor, CLK_FREQ_40MHZ); + + /* NOP cmd - clear command register */ + DC390_write8(ScsiCmd, NOP_CMD); + + /* Enable Feature and SCSI-2 */ + DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD); + + /* Fast clock */ + DC390_write8(CtrlReg3, FAST_CLK); + + /* Negation */ + DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */ + (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? + NEGATE_REQACKDATA : 0); + + /* Clear Transfer Count High: ID */ + DC390_write8(CtcReg_High, 0); + DC390_write8(DMA_Cmd, DMA_IDLE_CMD); + DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); + DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); + + dstate = DC390_read8(DMA_Status); + DC390_write8(DMA_Status, dstate); +} + +static int __devinit dc390_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct dc390_acb *pACB; + struct Scsi_Host *shost; + unsigned long io_port; + int error = -ENODEV, i; + + if (pci_enable_device(pdev)) + goto out; - DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (u32) scsi_host, dc390_adapterCnt)); + pci_set_master(pdev); - dc390_initACB(scsi_host, io_port, irq, dc390_adapterCnt); + error = -ENOMEM; + shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb)); + if (!shost) + goto out_disable_device; - pACB->pdev = dev; + pACB = (struct dc390_acb *)shost->hostdata; + memset(pACB, 0, sizeof(struct dc390_acb)); - if (dc390_initAdapter(scsi_host, io_port, irq, dc390_adapterCnt)) { - scsi_unregister(scsi_host); - ret = -EBUSY; - goto busy; + dc390_check_eeprom(pdev, dc390_adapterCnt); + dc390_eeprom_override(dc390_adapterCnt); + + io_port = pci_resource_start(pdev, 0); + + shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID]; + shost->io_port = io_port; + shost->n_io_port = 0x80; + shost->irq = pdev->irq; + shost->base = io_port; + shost->unique_id = io_port; + shost->last_reset = jiffies; + + pACB->pScsiHost = shost; + pACB->IOPortBase = (u16) io_port; + pACB->IRQLevel = pdev->irq; + + shost->max_id = 8; + + if (shost->max_id - 1 == + dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID]) + shost->max_id--; + + if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK) + shost->max_lun = 8; + else + shost->max_lun = 1; + + pACB->pFreeSRB = pACB->SRB_array; + pACB->SRBCount = MAX_SRB_CNT; + pACB->AdapterIndex = dc390_adapterCnt; + pACB->TagMaxNum = + 2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM]; + pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2]; + + for (i = 0; i < pACB->SRBCount-1; i++) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL; + pACB->pTmpSRB = &pACB->TmpSRB; + + pACB->sel_timeout = SEL_TIMEOUT; + pACB->glitch_cfg = EATER_25NS; + pACB->pdev = pdev; + + if (!request_region(io_port, shost->n_io_port, "tmscsim")) { + printk(KERN_ERR "DC390: register IO ports error!\n"); + goto out_host_put; } - pci_set_master(dev); - dc390_set_pci_cfg(dev); - dc390_adapterCnt++; + /* Reset Pending INT */ + DC390_read8_(INT_Status, io_port); - /* get the scsi mid level to scan for new devices on the bus */ - if (scsi_add_host(scsi_host, &dev->dev)) { - ret = -ENODEV; - goto nodev; + if (request_irq(pdev->irq, do_DC390_Interrupt, SA_SHIRQ, + "tmscsim", pACB)) { + printk(KERN_ERR "DC390: register IRQ error!\n"); + goto out_release_region; } - pci_set_drvdata(dev, scsi_host); - scsi_scan_host(scsi_host); + dc390_init_hw(pACB, dc390_adapterCnt); + + dc390_adapterCnt++; + + pci_set_drvdata(pdev, shost); + + error = scsi_add_host(shost, &pdev->dev); + if (error) + goto out_free_irq; + scsi_scan_host(shost); return 0; -nodev: -busy: - scsi_host_put(scsi_host); -nomem: - pci_disable_device(dev); - return ret; + out_free_irq: + free_irq(pdev->irq, pACB); + out_release_region: + release_region(io_port, shost->n_io_port); + out_host_put: + scsi_host_put(shost); + out_disable_device: + pci_disable_device(pdev); + out: + return error; } /** @@ -1929,8 +2625,6 @@ static void __devexit dc390_remove_one(struct pci_dev *dev) dc390_ResetSCSIBus(pACB); spin_unlock_irqrestore(scsi_host->host_lock, iflags); - del_timer_sync(&pACB->Waiting_Timer); - free_irq(scsi_host->irq, pACB); release_region(scsi_host->io_port, scsi_host->n_io_port); @@ -1939,161 +2633,32 @@ static void __devexit dc390_remove_one(struct pci_dev *dev) pci_set_drvdata(dev, NULL); } -/******************************************************************** - * Function: DC390_proc_info(char* buffer, char **start, - * off_t offset, int length, int hostno, int inout) - * - * Purpose: return SCSI Adapter/Device Info - * - * Input: buffer: Pointer to a buffer where to write info - * start : - * offset: - * hostno: Host adapter index - * inout : Read (=0) or set(!=0) info - * - * Output: buffer: contains info - * length; length of info in buffer - * - * return value: length - * - ********************************************************************/ - -#undef SPRINTF -#define SPRINTF(args...) pos += sprintf(pos, ## args) - -#define YESNO(YN) \ - if (YN) SPRINTF(" Yes "); \ - else SPRINTF(" No ") - - -static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, - off_t offset, int length, int inout) -{ - int dev, spd, spd1; - char *pos = buffer; - struct dc390_acb* pACB; - struct dc390_dcb* pDCB; - - pACB = dc390_pACB_start; - - while(pACB != (struct dc390_acb*)-1) - { - if (shpnt == pACB->pScsiHost) - break; - pACB = pACB->pNextACB; - } - - if (pACB == (struct dc390_acb*)-1) return(-ESRCH); - - if(inout) /* Has data been written to the file ? */ - return -ENOSYS; - - SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, "); - SPRINTF("Driver Version %s\n", DC390_VERSION); - - SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); - SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex); - SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase); - SPRINTF("IRQ %02i\n", pACB->IRQLevel); - - SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun); - SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", - shpnt->this_id, (pACB->sel_timeout*164)/100, - dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); - - SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n", - pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12); - - SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n", - pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB); - SPRINTF(" Lost arbitrations %i, Sel. connected %i, Connected: %s\n", - pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No"); - - SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt); - SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n", - pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], - pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]); - - SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n"); - - pDCB = pACB->pLinkDCB; - for (dev = 0; dev < pACB->DCBCnt; dev++) - { - SPRINTF("%02i %02i %02i ", dev, pDCB->TargetID, pDCB->TargetLUN); - YESNO(pDCB->DevMode & PARITY_CHK_); - YESNO(pDCB->SyncMode & SYNC_NEGO_DONE); - YESNO(pDCB->DevMode & EN_DISCONNECT_); - YESNO(pDCB->DevMode & SEND_START_); - YESNO(pDCB->SyncMode & EN_TAG_QUEUEING); - if (pDCB->SyncOffset & 0x0f) - { - int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++; - SPRINTF(" %03i ns ", (pDCB->NegoPeriod) << 2); - spd = 40/(sp); spd1 = 40%(sp); - spd1 = (spd1 * 10 + sp/2) / (sp); - SPRINTF(" %2i.%1i M %02i", spd, spd1, (pDCB->SyncOffset & 0x0f)); - } - else SPRINTF(" (%03i ns) ", (pDCB->NegoPeriod) << 2); - /* Add more info ...*/ - SPRINTF (" %02i\n", pDCB->MaxCommand); - pDCB = pDCB->pNextDCB; - } - if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n"); - else SPRINTF ("\n"); - pDCB = pACB->pLinkDCB; - - for (dev = 0; dev < pACB->DCBCnt; dev++) - { - struct dc390_srb* pSRB; - if (pDCB->WaitSRBCnt) - SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN, - pDCB->WaitSRBCnt); - for (pSRB = pDCB->pWaitingSRB; pSRB; pSRB = pSRB->pNextSRB) - SPRINTF(" %li", pSRB->pcmd->pid); - if (pDCB->GoingSRBCnt) - SPRINTF ("\nDCB (%02i-%i): Going : %i:", pDCB->TargetID, pDCB->TargetLUN, - pDCB->GoingSRBCnt); - for (pSRB = pDCB->pGoingSRB; pSRB; pSRB = pSRB->pNextSRB) -#if 0 //def DC390_DEBUGTRACE - SPRINTF(" %s\n ", pSRB->debugtrace); -#else - SPRINTF(" %li", pSRB->pcmd->pid); -#endif - if (pDCB->WaitSRBCnt || pDCB->GoingSRBCnt) SPRINTF ("\n"); - pDCB = pDCB->pNextDCB; - } - -#ifdef DC390_DEBUGDCB - SPRINTF ("DCB list for ACB %p:\n", pACB); - pDCB = pACB->pLinkDCB; - SPRINTF ("%p", pDCB); - for (dev = 0; dev < pACB->DCBCnt; dev++, pDCB=pDCB->pNextDCB) - SPRINTF ("->%p", pDCB->pNextDCB); - SPRINTF("\n"); -#endif - - *start = buffer + offset; - - if (pos - buffer < offset) - return 0; - else if (pos - buffer - offset < length) - return pos - buffer - offset; - else - return length; -} - -#undef YESNO -#undef SPRINTF +static struct pci_device_id tmscsim_pci_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { } +}; +MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); static struct pci_driver dc390_driver = { .name = "tmscsim", .id_table = tmscsim_pci_tbl, - .probe = dc390_init_one, + .probe = dc390_probe_one, .remove = __devexit_p(dc390_remove_one), }; static int __init dc390_module_init(void) { + if (tmscsim[0] == -1 || tmscsim[0] > 15) { + tmscsim[0] = 7; + tmscsim[1] = 4; + tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_; + tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION; + tmscsim[4] = 2; + tmscsim[5] = 10; + printk (KERN_INFO "DC390: Using safe settings.\n"); + } + return pci_module_init(&dc390_driver); } @@ -2104,3 +2669,25 @@ static void __exit dc390_module_exit(void) module_init(dc390_module_init); module_exit(dc390_module_exit); + +#ifndef MODULE +static int __init dc390_setup (char *str) +{ + int ints[8],i, im; + + get_options(str, ARRAY_SIZE(ints), ints); + im = ints[0]; + + if (im > 6) { + printk (KERN_NOTICE "DC390: ignore extra params!\n"); + im = 6; + } + + for (i = 0; i < im; i++) + tmscsim[i] = ints[i+1]; + /* dc390_checkparams (); */ + return 1; +} + +__setup("tmscsim=", dc390_setup); +#endif diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h index 62e9f8791..d4495272f 100644 --- a/drivers/scsi/tmscsim.h +++ b/drivers/scsi/tmscsim.h @@ -15,10 +15,8 @@ #define MAX_ADAPTER_NUM 4 #define MAX_SG_LIST_BUF 16 /* Not used */ -#define MAX_CMD_PER_LUN 32 -#define MAX_CMD_QUEUE MAX_CMD_PER_LUN+MAX_CMD_PER_LUN/2+1 #define MAX_SCSI_ID 8 -#define MAX_SRB_CNT MAX_CMD_QUEUE+1 /* Max number of started commands */ +#define MAX_SRB_CNT 50 /* Max number of started commands */ #define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ @@ -44,17 +42,15 @@ struct dc390_dcb *pSRBDCB; struct scsi_cmnd *pcmd; struct scatterlist *pSegmentList; -/* 0x10: */ struct scatterlist Segmentx; /* make a one entry of S/G list table */ -/* 0x1c: */ unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A*/ unsigned long SGToBeXferLen; /*; to be xfer length */ unsigned long TotalXferredLen; unsigned long SavedTotXLen; +unsigned long Saved_Ptr; u32 SRBState; -/* 0x30: */ u8 SRBStatus; u8 SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ /*; b4-settimeout,b5-Residual valid */ @@ -62,24 +58,18 @@ u8 AdaptStatus; u8 TargetStatus; u8 ScsiPhase; -u8 TagNumber; +s8 TagNumber; u8 SGIndex; u8 SGcount; -/* 0x38: */ u8 MsgCnt; u8 EndMessage; -u8 RetryCnt; u8 SavedSGCount; -unsigned long Saved_Ptr; - -/* 0x40: */ u8 MsgInBuf[6]; u8 MsgOutBuf[6]; //u8 IORBFlag; /*;81h-Reset, 2-retry */ -/* 0x4c: */ }; @@ -93,20 +83,12 @@ struct dc390_dcb struct dc390_dcb *pNextDCB; struct dc390_acb *pDCBACB; -/* 0x08: */ /* Queued SRBs */ -struct dc390_srb *pWaitingSRB; -struct dc390_srb *pWaitLast; struct dc390_srb *pGoingSRB; struct dc390_srb *pGoingLast; struct dc390_srb *pActiveSRB; -u8 WaitSRBCnt; /* Not used */ u8 GoingSRBCnt; -u8 DevType; -u8 MaxCommand; - -/* 0x20: */ u32 TagMask; u8 TargetID; /*; SCSI Target ID (SCSI Only) */ @@ -117,18 +99,11 @@ u8 DCBFlag; u8 CtrlR1; u8 CtrlR3; u8 CtrlR4; -u8 Inquiry7; -/* 0x2c: */ u8 SyncMode; /*; 0:async mode */ u8 NegoPeriod; /*;for nego. */ u8 SyncPeriod; /*;for reg. */ u8 SyncOffset; /*;for reg. and nego.(low nibble) */ - -/* 0x30:*/ -//u8 InqDataBuf[8]; -//u8 CapacityBuf[8]; -///* 0x40: */ }; @@ -140,7 +115,6 @@ u8 SyncOffset; /*;for reg. and nego.(low nibble) */ struct dc390_acb { struct Scsi_Host *pScsiHost; -struct dc390_acb *pNextACB; u16 IOPortBase; u8 IRQLevel; u8 status; @@ -163,7 +137,6 @@ struct dc390_srb *pFreeSRB; struct dc390_srb *pTmpSRB; u8 msgin123[4]; -u8 DCBmap[MAX_SCSI_ID]; u8 Connected; u8 pad; @@ -183,8 +156,6 @@ u32 SelLost; u32 SelConn; u32 CmdInQ; u32 CmdOutOfSRB; - -struct timer_list Waiting_Timer; struct dc390_srb TmpSRB; struct dc390_srb SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ @@ -311,11 +282,11 @@ struct dc390_srb SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ #define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)) #define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1) -#define SET_RES_TARGET(who,tgt) { who &= ~RES_TARGET; who |= (int)(tgt); } -#define SET_RES_TARGET_LNX(who,tgt) { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } -#define SET_RES_MSG(who,msg) { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } -#define SET_RES_DID(who,did) { who &= ~RES_DID; who |= (int)(did) << 16; } -#define SET_RES_DRV(who,drv) { who &= ~RES_DRV; who |= (int)(drv) << 24; } +#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0) +#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0) +#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0) +#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0) +#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0) /*;---Sync_Mode */ #define SYNC_DISABLE 0 @@ -348,64 +319,6 @@ typedef struct { dma_addr_t saved_dma_handle; } dc390_cmd_scp_t; -/* -** Inquiry Data format -*/ - -typedef struct _SCSIInqData { /* INQUIRY */ - - u8 DevType; /* Periph Qualifier & Periph Dev Type*/ - u8 RMB_TypeMod; /* rem media bit & Dev Type Modifier */ - u8 Vers; /* ISO, ECMA, & ANSI versions */ - u8 RDF; /* AEN, TRMIOP, & response data format*/ - u8 AddLen; /* length of additional data */ - u8 Res1; /* reserved */ - u8 Res2; /* reserved */ - u8 Flags; /* RelADr,Wbus32,Wbus16,Sync,etc. */ - u8 VendorID[8]; /* Vendor Identification */ - u8 ProductID[16]; /* Product Identification */ - u8 ProductRev[4]; /* Product Revision */ - - -} SCSI_INQDATA, *PSCSI_INQDATA; - - -/* Inquiry byte 0 masks */ - - -#define SCSI_DEVTYPE 0x1F /* Peripheral Device Type */ -#define SCSI_PERIPHQUAL 0xE0 /* Peripheral Qualifier */ -#define TYPE_NODEV SCSI_DEVTYPE /* Unknown or no device type */ - - -/* Inquiry byte 1 mask */ - -#define SCSI_REMOVABLE_MEDIA 0x80 /* Removable Media bit (1=removable) */ - - -/* Peripheral Device Type definitions */ -/* see include/scsi/scsi.h for the rest */ - -#ifndef TYPE_PRINTER -# define TYPE_PRINTER 0x02 /* Printer device */ -#endif -#ifndef TYPE_COMM -# define TYPE_COMM 0x09 /* Communications device */ -#endif - -/* -** Inquiry flag definitions (Inq data byte 7) -*/ - -#define SCSI_INQ_RELADR 0x80 /* device supports relative addressing*/ -#define SCSI_INQ_WBUS32 0x40 /* device supports 32 bit data xfers */ -#define SCSI_INQ_WBUS16 0x20 /* device supports 16 bit data xfers */ -#define SCSI_INQ_SYNC 0x10 /* device supports synchronous xfer */ -#define SCSI_INQ_LINKED 0x08 /* device supports linked commands */ -#define SCSI_INQ_CMDQUEUE 0x02 /* device supports command queueing */ -#define SCSI_INQ_SFTRE 0x01 /* device supports soft resets */ - - /* ;========================================================== ; EEPROM byte offset diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index b2f69d7a8..2889f402d 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -421,22 +421,26 @@ #include #include #include -#include -#include "scsi.h" -#include #include #include -static int u14_34f_detect(Scsi_Host_Template *); +#include +#include +#include +#include +#include +#include + +static int u14_34f_detect(struct scsi_host_template *); static int u14_34f_release(struct Scsi_Host *); -static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int u14_34f_eh_abort(Scsi_Cmnd *); -static int u14_34f_eh_host_reset(Scsi_Cmnd *); +static int u14_34f_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); +static int u14_34f_eh_abort(struct scsi_cmnd *); +static int u14_34f_eh_host_reset(struct scsi_cmnd *); static int u14_34f_bios_param(struct scsi_device *, struct block_device *, sector_t, int *); -static int u14_34f_slave_configure(Scsi_Device *); +static int u14_34f_slave_configure(struct scsi_device *); -static Scsi_Host_Template driver_template = { +static struct scsi_host_template driver_template = { .name = "UltraStor 14F/34F rev. 8.10.00 ", .detect = u14_34f_detect, .release = u14_34f_release, @@ -575,7 +579,7 @@ struct mscp { unsigned int sense_addr PACKED; /* Additional fields begin here. */ - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; unsigned int cpp_index; /* cp index */ /* All the cp structure is zero filled by queuecommand except the @@ -634,7 +638,7 @@ static unsigned long io_port[] = { #define DEV2H(x) le32_to_cpu(x) static irqreturn_t do_interrupt_handler(int, void *, struct pt_regs *); -static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); +static void flush_dev(struct scsi_device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; static int setup_done = FALSE; static int link_statistics; @@ -682,7 +686,7 @@ MODULE_DESCRIPTION("UltraStor 14F/34F SCSI Driver"); #endif -static int u14_34f_slave_configure(Scsi_Device *dev) { +static int u14_34f_slave_configure(struct scsi_device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; @@ -794,7 +798,7 @@ static int board_inquiry(unsigned int j) { } static int port_detect \ - (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { + (unsigned long port_base, unsigned int j, struct scsi_host_template *tpnt) { unsigned char irq, dma_channel, subversion, i; unsigned char in_byte; char *bus_type, dma_name[16]; @@ -1080,7 +1084,7 @@ static int option_setup(char *str) { return 1; } -static int u14_34f_detect(Scsi_Host_Template *tpnt) { +static int u14_34f_detect(struct scsi_host_template *tpnt) { unsigned int j = 0, k; tpnt->proc_name = "u14-34f"; @@ -1113,10 +1117,10 @@ static void map_dma(unsigned int i, unsigned int j) { unsigned int k, count, pci_dir; struct scatterlist *sgpnt; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (SCpnt->sense_buffer) cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer, @@ -1156,10 +1160,10 @@ static void map_dma(unsigned int i, unsigned int j) { static void unmap_dma(unsigned int i, unsigned int j) { unsigned int pci_dir; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (DEV2H(cpp->sense_addr)) pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr), @@ -1178,10 +1182,10 @@ static void unmap_dma(unsigned int i, unsigned int j) { static void sync_dma(unsigned int i, unsigned int j) { unsigned int pci_dir; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction); + pci_dir = SCpnt->sc_data_direction; if (DEV2H(cpp->sense_addr)) pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr), @@ -1214,24 +1218,24 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) { }; struct mscp *cpp; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt; - if (SCpnt->sc_data_direction == SCSI_DATA_READ) { + if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { cpp->xdir = DTD_IN; return; } - else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) { + else if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { cpp->xdir = DTD_OUT; return; } - else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) { + else if (SCpnt->sc_data_direction == DMA_NONE) { cpp->xdir = DTD_NONE; return; } - if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN) + if (SCpnt->sc_data_direction != DMA_BIDIRECTIONAL) panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j)); cpp->xdir = DTD_IN; @@ -1251,7 +1255,7 @@ static void scsi_to_dev_dir(unsigned int i, unsigned int j) { } -static int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { +static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { unsigned int i, j, k; struct mscp *cpp; @@ -1332,7 +1336,7 @@ static int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { return 0; } -static int u14_34f_eh_abort(Scsi_Cmnd *SCarg) { +static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; @@ -1406,10 +1410,10 @@ static int u14_34f_eh_abort(Scsi_Cmnd *SCarg) { panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -static int u14_34f_eh_host_reset(Scsi_Cmnd *SCarg) { +static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", @@ -1589,7 +1593,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, static int reorder(unsigned int j, unsigned long cursec, unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; struct mscp *cpp; unsigned int k, n; unsigned int rev = FALSE, s = TRUE, r = TRUE; @@ -1685,9 +1689,9 @@ static int reorder(unsigned int j, unsigned long cursec, return overlap; } -static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, +static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned int j, unsigned int ihdlr) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; struct mscp *cpp; unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES]; @@ -1725,7 +1729,7 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, } static irqreturn_t ihdlr(int irq, unsigned int j) { - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg, ret; struct mscp *spp, *cpp; diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index cb0a05d56..3d0a0f2f7 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -137,9 +137,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 6bb37d329..5754445fb 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -154,7 +154,7 @@ MODULE_LICENSE("GPL"); static char *setup_args[] = { "", "", "", "", "", "", "", "", "" }; static char *setup_strings; -MODULE_PARM(setup_strings, "s"); +module_param(setup_strings, charp, 0); static void wd33c93_execute(struct Scsi_Host *instance); diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index 193e40c18..bf4a758e2 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -190,7 +190,6 @@ #include -#define ANY2SCSI_INLINE /* undef this to use old macros */ #undef WD7000_DEBUG /* general debug */ #ifdef WD7000_DEBUG #define dprintk printk @@ -590,7 +589,7 @@ typedef union icb { #ifdef MODULE static char *wd7000; -MODULE_PARM(wd7000, "s"); +module_param(wd7000, charp, 0); #endif /* @@ -726,55 +725,17 @@ static int __init wd7000_setup(char *str) __setup("wd7000=", wd7000_setup); -#ifdef ANY2SCSI_INLINE -/* - * Since they're used a lot, I've redone the following from the macros - * formerly in wd7000.h, hopefully to speed them up by getting rid of - * all the shifting (it may not matter; GCC might have done as well anyway). - * - * xany2scsi and xscsi2int were not being used, and are no longer defined. - * (They were simply 4-byte versions of these routines). - */ -typedef union { /* let's cheat... */ - int i; - unchar u[sizeof(int)]; /* the sizeof(int) makes it more portable */ -} i_u; - - static inline void any2scsi(unchar * scsi, int any) { - *scsi++ = ((i_u) any).u[2]; - *scsi++ = ((i_u) any).u[1]; - *scsi++ = ((i_u) any).u[0]; + *scsi++ = (unsigned)any >> 16; + *scsi++ = (unsigned)any >> 8; + *scsi++ = any; } - static inline int scsi2int(unchar * scsi) { - i_u result; - - result.i = 0; /* clears unused bytes */ - result.u[2] = *scsi++; - result.u[1] = *scsi++; - result.u[0] = *scsi++; - - return (result.i); + return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2]; } -#else -/* - * These are the old ones - I've just moved them here... - */ -#undef any2scsi -#define any2scsi(up, p) (up)[0] = (((unsigned long) (p)) >> 16); \ - (up)[1] = ((unsigned long) (p)) >> 8; \ - (up)[2] = ((unsigned long) (p)); - -#undef scsi2int -#define scsi2int(up) ( (((unsigned long) *(up)) << 16) + \ - (((unsigned long) (up)[1]) << 8) + \ - ((unsigned long) (up)[2]) ) -#endif - static inline void wd7000_enable_intr(Adapter * host) { @@ -1468,16 +1429,16 @@ static int wd7000_detect(struct scsi_host_template *tpnt) break; if (i == pass) { - void *biosaddr = ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, + void __iomem *biosaddr = ioremap(wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, signatures[sig_ptr].len); - short bios_match = 0; + short bios_match = 1; if (biosaddr) - bios_match = memcmp((char *) biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); + bios_match = check_signature(biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); iounmap(biosaddr); - if (!bios_match) + if (bios_match) goto bios_matched; } } @@ -1512,8 +1473,7 @@ static int wd7000_detect(struct scsi_host_template *tpnt) * ASC reset... */ outb(ASC_RES, iobase + ASC_CONTROL); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100); + msleep(10); outb(0, iobase + ASC_CONTROL); if (WAIT(iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 9b946fd6d..c2afeb777 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -190,7 +190,12 @@ static struct parisc_driver zalon_driver = { static int __init zalon7xx_init(void) { - return register_parisc_driver(&zalon_driver); + int ret = ncr53c8xx_init(); + if (!ret) + ret = register_parisc_driver(&zalon_driver); + if (ret) + ncr53c8xx_exit(); + return ret; } static void __exit zalon7xx_exit(void) diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 511a40b0f..759addd51 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -13,12 +13,14 @@ #include #include #include +#include +#include #include #include -#include #include #include +#include #include #include @@ -90,22 +92,21 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; - unsigned int status, ch, rxs, max_count = 256; + unsigned int status, ch, flag, rxs, max_count = 256; status = *CSR_UARTFLG; while (!(status & 0x10) && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - goto out; - } + if (tty->low_latency) + tty_flip_buffer_push(tty); + /* + * If this failed then we will throw away the + * bytes but must do so to clear interrupts + */ } ch = *CSR_UARTDR; - - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; port->icount.rx++; rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ; @@ -120,15 +121,13 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r rxs &= port->read_status_mask; if (rxs & RXSTAT_PARITY) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (rxs & RXSTAT_FRAME) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if ((rxs & port->ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); } if ((rxs & RXSTAT_OVERRUN) && tty->flip.count < TTY_FLIPBUF_SIZE) { @@ -137,9 +136,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r * immediately, and doesn't affect the current * character. */ - *tty->flip.char_buf_ptr++ = 0; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - tty->flip.count++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } status = *CSR_UARTFLG; } diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 5c499be24..36f2fb04c 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -34,12 +34,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -435,10 +436,7 @@ static void do_softint(void *private) return; #if 0 if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } #endif } @@ -760,7 +758,7 @@ static void rs_flush_chars(struct tty_struct *tty) extern void console_printn(const char * b, int count); -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, total = 0; @@ -782,15 +780,7 @@ static int rs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - up(&tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); @@ -858,10 +848,7 @@ static void rs_flush_buffer(struct tty_struct *tty) cli(); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; sti(); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -1011,7 +998,7 @@ static void send_break( struct m68k_serial * info, int duration) unsigned long flags; if (!info->port) return; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); save_flags(flags); cli(); #ifdef USE_INTS @@ -1185,11 +1172,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; info->tty = 0; +#warning "This is not and has never been valid so fix it" +#if 0 if (tty->ldisc.num != ldiscs[N_TTY].num) { if (tty->ldisc.close) (tty->ldisc.close)(tty); @@ -1198,10 +1187,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp) if (tty->ldisc.open) (tty->ldisc.open)(tty); } +#endif if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 64e296ad3..f148022b6 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -700,12 +700,8 @@ static void do_softint(void *private_) if (!tty) return; - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) + tty_wakeup(tty); } @@ -1051,7 +1047,7 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch) } -static int rs_360_write(struct tty_struct * tty, int from_user, +static int rs_360_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -1083,16 +1079,8 @@ static int rs_360_write(struct tty_struct * tty, int from_user, break; } - if (from_user) { - if (copy_from_user((void *)bdp->buf, buf, c)) { - if (!ret) - ret = -EFAULT; - break; - } - } else { - /* memcpy(__va(bdp->buf), buf, c); */ - memcpy((void *)bdp->buf, buf, c); - } + /* memcpy(__va(bdp->buf), buf, c); */ + memcpy((void *)bdp->buf, buf, c); bdp->length = c; bdp->status |= BD_SC_READY; @@ -1152,10 +1140,7 @@ static void rs_360_flush_buffer(struct tty_struct *tty) /* There is nothing to "flush", whatever we gave the CPM * is on its way out. */ - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); info->flags &= ~TX_WAKEUP; } @@ -1411,7 +1396,7 @@ static void end_break(ser_info_t *info) */ static void send_break(ser_info_t *info, int duration) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); #ifdef SERIAL_DEBUG_SEND_BREAK printk("rs_send_break(%d) jiff=%lu...", duration, jiffies); #endif @@ -1716,15 +1701,13 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; info->tty = 0; if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -1777,9 +1760,8 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...", lsr, jiffies); #endif - current->state = TASK_INTERRUPTIBLE; /* current->counter = 0; make us low-priority */ - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && ((orig_jiffies + timeout) < jiffies)) @@ -2592,7 +2574,7 @@ int rs_360_init(void) state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - printk(KERN_INFO "ttyS%02d at irq 0x%02x is an %s\n", + printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n", i, (unsigned int)(state->irq), (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC"); diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 4906b5751..31dd922e2 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -20,27 +20,29 @@ * membase is an 'ioremapped' cookie. */ #include + +#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include -#include #include #include #include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include #include -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include #include "8250.h" /* @@ -130,6 +132,7 @@ struct uart_8250_port { struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ unsigned int capabilities; /* port capabilities */ + unsigned int tx_loadsz; /* transmit fifo load size */ unsigned short rev; unsigned char acr; unsigned char ier; @@ -156,23 +159,109 @@ static struct irq_info irq_lists[NR_IRQS]; /* * Here we define the default xmit fifo size used for each type of UART. */ -static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "Cirrus", 1, 0 }, - { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, - { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, - { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "Startech", 1, 0 }, - { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, - { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, - { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "NS16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO | UART_NATSEMI }, - { "XScale", 32, UART_CLEAR_FIFO | UART_USE_FIFO }, +static const struct serial8250_config uart_config[] = { + [PORT_UNKNOWN] = { + .name = "unknown", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_8250] = { + .name = "8250", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16450] = { + .name = "16450", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550] = { + .name = "16550", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550A] = { + .name = "16550A", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, + [PORT_CIRRUS] = { + .name = "Cirrus", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16650] = { + .name = "ST16650", + .fifo_size = 1, + .tx_loadsz = 1, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16650V2] = { + .name = "ST16650V2", + .fifo_size = 32, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_00, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16750] = { + .name = "TI16750", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | + UART_FCR7_64BYTE, + .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE, + }, + [PORT_STARTECH] = { + .name = "Startech", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16C950] = { + .name = "16C950/954", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, + [PORT_16654] = { + .name = "ST16654", + .fifo_size = 64, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | + UART_FCR_T_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_16850] = { + .name = "XR16850", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + }, + [PORT_RSA] = { + .name = "RSA", + .fifo_size = 2048, + .tx_loadsz = 2048, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11, + .flags = UART_CAP_FIFO, + }, + [PORT_NS16550A] = { + .name = "NS16550A", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_NATSEMI, + }, + [PORT_XSCALE] = { + .name = "XScale", + .fifo_size = 32, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO, + }, }; static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) @@ -187,6 +276,9 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) case UPIO_MEM: return readb(up->port.membase + offset); + case UPIO_MEM32: + return readl(up->port.membase + offset); + default: return inb(up->port.iobase + offset); } @@ -207,6 +299,10 @@ serial_out(struct uart_8250_port *up, int offset, int value) writeb(value, up->port.membase + offset); break; + case UPIO_MEM32: + writel(value, up->port.membase + offset); + break; + default: outb(value, up->port.iobase + offset); } @@ -243,6 +339,41 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) return value; } +/* + * FIFO support. + */ +static inline void serial8250_clear_fifos(struct uart_8250_port *p) +{ + if (p->capabilities & UART_CAP_FIFO) { + serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_outp(p, UART_FCR, 0); + } +} + +/* + * IER sleep support. UARTs which have EFRs need the "extended + * capability" bit enabled. Note that on XR16C850s, we need to + * reset LCR to write to IER. + */ +static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep) +{ + if (p->capabilities & UART_CAP_SLEEP) { + if (p->capabilities & UART_CAP_EFR) { + serial_outp(p, UART_LCR, 0xBF); + serial_outp(p, UART_EFR, UART_EFR_ECB); + serial_outp(p, UART_LCR, 0); + } + serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); + if (p->capabilities & UART_CAP_EFR) { + serial_outp(p, UART_LCR, 0xBF); + serial_outp(p, UART_EFR, 0); + serial_outp(p, UART_LCR, 0); + } + } +} + #ifdef CONFIG_SERIAL_8250_RSA /* * Attempts to turn on the RSA FIFO. Returns zero on failure. @@ -361,6 +492,11 @@ static void autoconfig_has_efr(struct uart_8250_port *up) { unsigned char id1, id2, id3, rev, saved_dll, saved_dlm; + /* + * Everything with an EFR has SLEEP + */ + up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; + /* * First we check to see if it's an Oxford Semiconductor UART. * @@ -471,6 +607,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) unsigned char status1, status2; up->port.type = PORT_16550A; + up->capabilities |= UART_CAP_FIFO; /* * Check for presence of the EFR when DLAB is set. @@ -482,6 +619,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (serial_in(up, UART_EFR) != 0) { DEBUG_AUTOCONF("EFRv1 "); up->port.type = PORT_16650; + up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP; } else { DEBUG_AUTOCONF("Motorola 8xxx DUART "); } @@ -534,6 +672,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) #endif up->port.type = PORT_NS16550A; + up->capabilities |= UART_NATSEMI; return; } } @@ -557,6 +696,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (status1 == 6 && status2 == 7) { up->port.type = PORT_16750; + up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP; return; } } @@ -587,6 +727,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) spin_lock_irqsave(&up->port.lock, flags); // save_flags(flags); cli(); + up->capabilities = 0; + if (!(up->port.flags & UPF_BUGGY_UART)) { /* * Do a simple existence test first; if we fail this, @@ -697,8 +839,16 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) #endif serial_outp(up, UART_LCR, save_lcr); - up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; + if (up->capabilities != uart_config[up->port.type].flags) { + printk(KERN_WARNING + "ttyS%d: detected caps %08x should be %08x\n", + up->port.line, up->capabilities, + uart_config[up->port.type].flags); + } + + up->port.fifosize = uart_config[up->port.type].fifo_size; up->capabilities = uart_config[up->port.type].flags; + up->tx_loadsz = uart_config[up->port.type].tx_loadsz; if (up->port.type == PORT_UNKNOWN) goto out; @@ -711,10 +861,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_outp(up, UART_RSA_FRR, 0); #endif serial_outp(up, UART_MCR, save_mcr); - serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(up, UART_FCR, 0); + serial8250_clear_fifos(up); (void)serial_in(up, UART_RX); serial_outp(up, UART_IER, 0); @@ -781,6 +928,12 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) up->ier &= ~UART_IER_THRI; serial_out(up, UART_IER, up->ier); } + + /* + * We only do this from uart_stop - if we run out of + * characters to send, we don't want to prevent the + * FIFO from emptying. + */ if (up->port.type == PORT_16C950 && tty_stop) { up->acr |= UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); @@ -825,27 +978,40 @@ static _INLINE_ void receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; - unsigned char ch; + unsigned char ch, lsr = *status; int max_count = 256; + char flag; do { + /* The following is not allowed by the tty layer and + unsafe. It should be fixed ASAP */ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set + if(tty->low_latency) + tty_flip_buffer_push(tty); + /* If this failed then we will throw away the + bytes but must do so to clear interrupts */ } ch = serial_inp(up, UART_RX); - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; - if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE))) { +#ifdef CONFIG_SERIAL_8250_CONSOLE + /* + * Recover the break flag from console xmit + */ + if (up->port.line == up->port.cons->index) { + lsr |= up->lsr_break_flag; + up->lsr_break_flag = 0; + } +#endif + + if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE))) { /* * For statistics only */ - if (*status & UART_LSR_BI) { - *status &= ~(UART_LSR_FE | UART_LSR_PE); + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; /* * We do the SysRQ and SAK checking @@ -855,56 +1021,45 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) */ if (uart_handle_break(&up->port)) goto ignore_char; - } else if (*status & UART_LSR_PE) + } else if (lsr & UART_LSR_PE) up->port.icount.parity++; - else if (*status & UART_LSR_FE) + else if (lsr & UART_LSR_FE) up->port.icount.frame++; - if (*status & UART_LSR_OE) + if (lsr & UART_LSR_OE) up->port.icount.overrun++; /* * Mask off conditions which should be ingored. */ - *status &= up->port.read_status_mask; + lsr &= up->port.read_status_mask; -#ifdef CONFIG_SERIAL_8250_CONSOLE - if (up->port.line == up->port.cons->index) { - /* Recover the break flag from console xmit */ - *status |= up->lsr_break_flag; - up->lsr_break_flag = 0; - } -#endif - if (*status & UART_LSR_BI) { + if (lsr & UART_LSR_BI) { DEBUG_INTR("handling break...."); - *tty->flip.flag_buf_ptr = TTY_BREAK; - } else if (*status & UART_LSR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (*status & UART_LSR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_BREAK; + } else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((*status & up->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + if ((lsr & up->port.ignore_status_mask) == 0) { + tty_insert_flip_char(tty, ch, flag); } - if ((*status & UART_LSR_OE) && + if ((lsr & UART_LSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character. */ - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: - *status = serial_inp(up, UART_LSR); - } while ((*status & UART_LSR_DR) && (max_count-- > 0)); + lsr = serial_inp(up, UART_LSR); + } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); tty_flip_buffer_push(tty); + *status = lsr; } static _INLINE_ void transmit_chars(struct uart_8250_port *up) @@ -923,7 +1078,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) return; } - count = up->port.fifosize; + count = up->tx_loadsz; do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -997,7 +1152,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r { struct irq_info *i = dev_id; struct list_head *l, *end = NULL; - int pass_counter = 0; + int pass_counter = 0, handled = 0; DEBUG_INTR("serial8250_interrupt(%d)...", irq); @@ -1016,6 +1171,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r serial8250_handle_port(up, regs); spin_unlock(&up->port.lock); + handled = 1; + end = NULL; } else if (end == NULL) end = l; @@ -1033,8 +1190,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r spin_unlock(&i->lock); DEBUG_INTR("end.\n"); - /* FIXME! Was it really ours? */ - return IRQ_HANDLED; + + return IRQ_RETVAL(handled); } /* @@ -1227,12 +1384,7 @@ static int serial8250_startup(struct uart_port *port) * Clear the FIFO buffers and disable them. * (they will be reeanbled in set_termios()) */ - if (up->capabilities & UART_CLEAR_FIFO) { - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); - } + serial8250_clear_fifos(up); /* * Clear the interrupt registers. @@ -1253,6 +1405,23 @@ static int serial8250_startup(struct uart_port *port) return -ENODEV; } + /* + * For a XR16C850, we need to set the trigger levels + */ + if (up->port.type == PORT_16850) { + unsigned char fctr; + + serial_outp(up, UART_LCR, 0xbf); + + fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); + serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); + serial_outp(up, UART_TRG, UART_TRG_96); + serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_outp(up, UART_TRG, UART_TRG_96); + + serial_outp(up, UART_LCR, 0); + } + /* * If the "interrupt" for this port doesn't correspond with any * hardware interrupt, we use a timer-based system. The original @@ -1345,10 +1514,7 @@ static void serial8250_shutdown(struct uart_port *port) * Disable break condition and FIFOs */ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_FCR, 0); + serial8250_clear_fifos(up); #ifdef CONFIG_SERIAL_8250_RSA /* @@ -1440,28 +1606,25 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, up->rev == 0x5201) quot ++; - if (up->capabilities & UART_USE_FIFO) { + if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { if (baud < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; -#ifdef CONFIG_SERIAL_8250_RSA - else if (up->port.type == PORT_RSA) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; -#endif else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + fcr = uart_config[up->port.type].fcr; } /* - * TI16C750: hardware flow control and 64 byte FIFOs. When AFE is - * enabled, RTS will be deasserted when the receive FIFO contains - * more characters than the trigger, or the MCR RTS bit is cleared. + * MCR-based auto flow control. When AFE is enabled, RTS will be + * deasserted when the receive FIFO contains more characters than + * the trigger, or the MCR RTS bit is cleared. In the case where + * the remote UART is not using CTS auto flow control, we must + * have sufficient FIFO entries for the latency of the remote + * UART to respond. IOW, at least 32 bytes of FIFO. */ - if (up->port.type == PORT_16750) { + if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) { up->mcr &= ~UART_MCR_AFE; if (termios->c_cflag & CRTSCTS) up->mcr |= UART_MCR_AFE; - - fcr |= UART_FCR7_64BYTE; } /* @@ -1514,10 +1677,18 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, serial_out(up, UART_IER, up->ier); - if (up->capabilities & UART_STARTECH) { + if (up->capabilities & UART_CAP_EFR) { + unsigned char efr = 0; + /* + * TI16C752/Startech hardware flow control. FIXME: + * - TI16C752 requires control thresholds to be set. + * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled. + */ + if (termios->c_cflag & CRTSCTS) + efr |= UART_EFR_CTS; + serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, - termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0); + serial_outp(up, UART_EFR, efr); } if (up->capabilities & UART_NATSEMI) { @@ -1554,215 +1725,139 @@ static void serial8250_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct uart_8250_port *up = (struct uart_8250_port *)port; - if (state) { - /* sleep */ - if (up->capabilities & UART_STARTECH) { - /* Arrange to enter sleep mode */ - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_IER, UART_IERX_SLEEP); - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, 0); - serial_outp(up, UART_LCR, 0); - } - if (up->port.type == PORT_16750) { - /* Arrange to enter sleep mode */ - serial_outp(up, UART_IER, UART_IERX_SLEEP); - } - - if (up->pm) - up->pm(port, state, oldstate); - } else { - /* wake */ - if (up->capabilities & UART_STARTECH) { - /* Wake up UART */ - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, UART_EFR_ECB); - /* - * Turn off LCR == 0xBF so we actually set the IER - * register on the XR16C850 - */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_IER, 0); - /* - * Now reset LCR so we can turn off the ECB bit - */ - serial_outp(up, UART_LCR, 0xBF); - serial_outp(up, UART_EFR, 0); - /* - * For a XR16C850, we need to set the trigger levels - */ - if (up->port.type == PORT_16850) { - unsigned char fctr; - - fctr = serial_inp(up, UART_FCTR) & - ~(UART_FCTR_RX | UART_FCTR_TX); - serial_outp(up, UART_FCTR, fctr | - UART_FCTR_TRGD | - UART_FCTR_RX); - serial_outp(up, UART_TRG, UART_TRG_96); - serial_outp(up, UART_FCTR, fctr | - UART_FCTR_TRGD | - UART_FCTR_TX); - serial_outp(up, UART_TRG, UART_TRG_96); - } - serial_outp(up, UART_LCR, 0); - } + struct uart_8250_port *p = (struct uart_8250_port *)port; - if (up->port.type == PORT_16750) { - /* Wake up UART */ - serial_outp(up, UART_IER, 0); - } + serial8250_set_sleep(p, state != 0); - if (up->pm) - up->pm(port, state, oldstate); - } + if (p->pm) + p->pm(port, state, oldstate); } /* - * Resource handling. This is complicated by the fact that resources - * depend on the port type. Maybe we should be claiming the standard - * 8250 ports, and then trying to get other resources as necessary? + * Resource handling. */ -static int -serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res) +static int serial8250_request_std_resource(struct uart_8250_port *up) { unsigned int size = 8 << up->port.regshift; int ret = 0; switch (up->port.iotype) { case UPIO_MEM: - if (up->port.mapbase) { - *res = request_mem_region(up->port.mapbase, size, "serial"); - if (!*res) - ret = -EBUSY; + if (!up->port.mapbase) + break; + + if (!request_mem_region(up->port.mapbase, size, "serial")) { + ret = -EBUSY; + break; + } + + if (up->port.flags & UPF_IOREMAP) { + up->port.membase = ioremap(up->port.mapbase, size); + if (!up->port.membase) { + release_mem_region(up->port.mapbase, size); + ret = -ENOMEM; + } } break; case UPIO_HUB6: case UPIO_PORT: - *res = request_region(up->port.iobase, size, "serial"); - if (!*res) + if (!request_region(up->port.iobase, size, "serial")) ret = -EBUSY; break; } return ret; } -static int -serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res) +static void serial8250_release_std_resource(struct uart_8250_port *up) { unsigned int size = 8 << up->port.regshift; - unsigned long start; - int ret = 0; switch (up->port.iotype) { case UPIO_MEM: - if (up->port.mapbase) { - start = up->port.mapbase; - start += UART_RSA_BASE << up->port.regshift; - *res = request_mem_region(start, size, "serial-rsa"); - if (!*res) - ret = -EBUSY; + if (!up->port.mapbase) + break; + + if (up->port.flags & UPF_IOREMAP) { + iounmap(up->port.membase); + up->port.membase = NULL; } + + release_mem_region(up->port.mapbase, size); break; case UPIO_HUB6: case UPIO_PORT: - start = up->port.iobase; - start += UART_RSA_BASE << up->port.regshift; - *res = request_region(start, size, "serial-rsa"); - if (!*res) - ret = -EBUSY; + release_region(up->port.iobase, size); break; } - - return ret; } -static void serial8250_release_port(struct uart_port *port) +static int serial8250_request_rsa_resource(struct uart_8250_port *up) { - struct uart_8250_port *up = (struct uart_8250_port *)port; - unsigned long start, offset = 0, size = 0; - - if (up->port.type == PORT_RSA) { - offset = UART_RSA_BASE << up->port.regshift; - size = 8; - } - - size <<= up->port.regshift; + unsigned long start = UART_RSA_BASE << up->port.regshift; + unsigned int size = 8 << up->port.regshift; + int ret = 0; switch (up->port.iotype) { case UPIO_MEM: - if (up->port.mapbase) { - /* - * Unmap the area. - */ - iounmap(up->port.membase); - up->port.membase = NULL; - - start = up->port.mapbase; - - if (size) - release_mem_region(start + offset, size); - release_mem_region(start, 8 << up->port.regshift); - } + ret = -EINVAL; break; case UPIO_HUB6: case UPIO_PORT: - start = up->port.iobase; + start += up->port.iobase; + if (!request_region(start, size, "serial-rsa")) + ret = -EBUSY; + break; + } - if (size) - release_region(start + offset, size); - release_region(start + offset, 8 << up->port.regshift); + return ret; +} + +static void serial8250_release_rsa_resource(struct uart_8250_port *up) +{ + unsigned long offset = UART_RSA_BASE << up->port.regshift; + unsigned int size = 8 << up->port.regshift; + + switch (up->port.iotype) { + case UPIO_MEM: break; - default: + case UPIO_HUB6: + case UPIO_PORT: + release_region(up->port.iobase + offset, size); break; } } +static void serial8250_release_port(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + serial8250_release_std_resource(up); + if (up->port.type == PORT_RSA) + serial8250_release_rsa_resource(up); +} + static int serial8250_request_port(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res = NULL, *res_rsa = NULL; int ret = 0; - if (up->port.type == PORT_RSA) { - ret = serial8250_request_rsa_resource(up, &res_rsa); + ret = serial8250_request_std_resource(up); + if (ret == 0 && up->port.type == PORT_RSA) { + ret = serial8250_request_rsa_resource(up); if (ret < 0) - return ret; + serial8250_release_std_resource(up); } - ret = serial8250_request_std_resource(up, &res); - - /* - * If we have a mapbase, then request that as well. - */ - if (ret == 0 && up->port.flags & UPF_IOREMAP) { - int size = res->end - res->start + 1; - - up->port.membase = ioremap(up->port.mapbase, size); - if (!up->port.membase) - ret = -ENOMEM; - } - - if (ret < 0) { - if (res_rsa) - release_resource(res_rsa); - if (res) - release_resource(res); - } return ret; } static void serial8250_config_port(struct uart_port *port, int flags) { struct uart_8250_port *up = (struct uart_8250_port *)port; - struct resource *res_std = NULL, *res_rsa = NULL; int probeflags = PROBE_ANY; int ret; @@ -1778,11 +1873,11 @@ static void serial8250_config_port(struct uart_port *port, int flags) * Find the region that we can probe for. This in turn * tells us whether we can probe for the type of port. */ - ret = serial8250_request_std_resource(up, &res_std); + ret = serial8250_request_std_resource(up); if (ret < 0) return; - ret = serial8250_request_rsa_resource(up, &res_rsa); + ret = serial8250_request_rsa_resource(up); if (ret < 0) probeflags &= ~PROBE_RSA; @@ -1791,14 +1886,10 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); - /* - * If the port wasn't an RSA port, release the resource. - */ - if (up->port.type != PORT_RSA && res_rsa) - release_resource(res_rsa); - - if (up->port.type == PORT_UNKNOWN && res_std) - release_resource(res_std); + if (up->port.type != PORT_RSA && probeflags & PROBE_RSA) + serial8250_release_rsa_resource(up); + if (up->port.type == PORT_UNKNOWN) + serial8250_release_std_resource(up); } static int @@ -1806,7 +1897,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) { if (ser->irq >= NR_IRQS || ser->irq < 0 || ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || - ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS || + ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS || ser->type == PORT_STARTECH) return -EINVAL; return 0; @@ -1854,6 +1945,24 @@ static void __init serial8250_isa_init_ports(void) return; first = 0; + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; + + up->port.line = i; + spin_lock_init(&up->port.lock); + + init_timer(&up->timer); + up->timer.function = serial8250_timeout; + + /* + * ALPHA_KLUDGE_MCR needs to be killed. + */ + up->mcr_mask = ~ALPHA_KLUDGE_MCR; + up->mcr_force = ALPHA_KLUDGE_MCR; + + up->port.ops = &serial8250_pops; + } + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port); i++, up++) { up->port.iobase = old_serial_port[i].port; @@ -1864,13 +1973,13 @@ static void __init serial8250_isa_init_ports(void) up->port.membase = old_serial_port[i].iomem_base; up->port.iotype = old_serial_port[i].io_type; up->port.regshift = old_serial_port[i].iomem_reg_shift; - up->port.ops = &serial8250_pops; if (share_irqs) up->port.flags |= UPF_SHARE_IRQ; } } -static void __init serial8250_register_ports(struct uart_driver *drv) +static void __init +serial8250_register_ports(struct uart_driver *drv, struct device *dev) { int i; @@ -1879,17 +1988,7 @@ static void __init serial8250_register_ports(struct uart_driver *drv) for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; - up->port.line = i; - up->port.ops = &serial8250_pops; - init_timer(&up->timer); - up->timer.function = serial8250_timeout; - - /* - * ALPHA_KLUDGE_MCR needs to be killed. - */ - up->mcr_mask = ~ALPHA_KLUDGE_MCR; - up->mcr_force = ALPHA_KLUDGE_MCR; - + up->port.dev = dev; uart_add_one_port(drv, &up->port); } } @@ -1974,7 +2073,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial_out(up, UART_IER, ier); } -static int __init serial8250_console_setup(struct console *co, char *options) +static int serial8250_console_setup(struct console *co, char *options) { struct uart_port *port; int baud = 9600; @@ -1990,14 +2089,9 @@ static int __init serial8250_console_setup(struct console *co, char *options) if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; - if (!port->ops) + if (!port->iobase && !port->membase) return -ENODEV; - /* - * Temporary fix. - */ - spin_lock_init(&port->lock); - if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -2031,6 +2125,41 @@ static int __init serial8250_late_console_init(void) } late_initcall(serial8250_late_console_init); +static int __init find_port(struct uart_port *p) +{ + int line; + struct uart_port *port; + + for (line = 0; line < UART_NR; line++) { + port = &serial8250_ports[line].port; + if (p->iotype == port->iotype && + p->iobase == port->iobase && + p->membase == port->membase) + return line; + } + return -ENODEV; +} + +int __init serial8250_start_console(struct uart_port *port, char *options) +{ + int line; + + line = find_port(port); + if (line < 0) + return -ENODEV; + + add_preferred_console("ttyS", line, options); + printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", + line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port", + port->iotype == UPIO_MEM ? (unsigned long) port->mapbase : + (unsigned long) port->iobase, options); + if (!(serial8250_console.flags & CON_ENABLED)) { + serial8250_console.flags &= ~CON_PRINTBUFFER; + register_console(&serial8250_console); + } + return line; +} + #define SERIAL8250_CONSOLE &serial8250_console #else #define SERIAL8250_CONSOLE NULL @@ -2047,120 +2176,267 @@ static struct uart_driver serial8250_reg = { .cons = SERIAL8250_CONSOLE, }; -/* - * register_serial and unregister_serial allows for 16x50 serial ports to be - * configured at run-time, to support PCMCIA modems. - */ - -static int __register_serial(struct serial_struct *req, int line) +int __init early_serial_setup(struct uart_port *port) { - struct uart_port port; - - port.iobase = req->port; - port.membase = req->iomem_base; - port.irq = req->irq; - port.uartclk = req->baud_base * 16; - port.fifosize = req->xmit_fifo_size; - port.regshift = req->iomem_reg_shift; - port.iotype = req->io_type; - port.flags = req->flags | UPF_BOOT_AUTOCONF; - port.mapbase = req->iomap_base; - port.line = line; - - if (share_irqs) - port.flags |= UPF_SHARE_IRQ; - - if (HIGH_BITS_OFFSET) - port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET; - - /* - * If a clock rate wasn't specified by the low level - * driver, then default to the standard clock rate. - */ - if (port.uartclk == 0) - port.uartclk = BASE_BAUD * 16; + if (port->line >= ARRAY_SIZE(serial8250_ports)) + return -ENODEV; - return uart_register_port(&serial8250_reg, &port); + serial8250_isa_init_ports(); + serial8250_ports[port->line].port = *port; + serial8250_ports[port->line].port.ops = &serial8250_pops; + return 0; } /** - * register_serial - configure a 16x50 serial port at runtime - * @req: request structure - * - * Configure the serial port specified by the request. If the - * port exists and is in use an error is returned. If the port - * is not currently in the table it is added. + * serial8250_suspend_port - suspend one serial port + * @line: serial line number + * @level: the level of port suspension, as per uart_suspend_port * - * The port is then probed and if necessary the IRQ is autodetected - * If this fails an error is returned. + * Suspend one serial port. + */ +void serial8250_suspend_port(int line) +{ + uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); +} + +/** + * serial8250_resume_port - resume one serial port + * @line: serial line number + * @level: the level of port resumption, as per uart_resume_port * - * On success the port is ready to use and the line number is returned. + * Resume one serial port. */ -int register_serial(struct serial_struct *req) +void serial8250_resume_port(int line) { - return __register_serial(req, -1); + uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); } -int __init early_serial_setup(struct uart_port *port) +/* + * Register a set of serial devices attached to a platform device. The + * list is terminated with a zero flags entry, which means we expect + * all entries to have at least UPF_BOOT_AUTOCONF set. + */ +static int __devinit serial8250_probe(struct device *dev) { - if (port->line >= ARRAY_SIZE(serial8250_ports)) - return -ENODEV; + struct plat_serial8250_port *p = dev->platform_data; + struct uart_port port; - serial8250_isa_init_ports(); - serial8250_ports[port->line].port = *port; - serial8250_ports[port->line].port.ops = &serial8250_pops; + memset(&port, 0, sizeof(struct uart_port)); + + for (; p && p->flags != 0; p++) { + port.iobase = p->iobase; + port.membase = p->membase; + port.irq = p->irq; + port.uartclk = p->uartclk; + port.regshift = p->regshift; + port.iotype = p->iotype; + port.flags = p->flags; + port.mapbase = p->mapbase; + port.dev = dev; + if (share_irqs) + port.flags |= UPF_SHARE_IRQ; + serial8250_register_port(&port); + } return 0; } -/** - * unregister_serial - remove a 16x50 serial port at runtime - * @line: serial line number - * - * Remove one serial port. This may be called from interrupt - * context. +/* + * Remove serial ports registered against a platform device. */ -void unregister_serial(int line) +static int __devexit serial8250_remove(struct device *dev) { - uart_unregister_port(&serial8250_reg, line); + int i; + + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; + + if (up->port.dev == dev) + serial8250_unregister_port(i); + } + return 0; } -/* - * This is for ISAPNP only. - */ -void serial8250_get_irq_map(unsigned int *map) +static int serial8250_suspend(struct device *dev, u32 state, u32 level) { int i; + if (level != SUSPEND_DISABLE) + return 0; + + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == dev) + uart_suspend_port(&serial8250_reg, &up->port); + } + + return 0; +} + +static int serial8250_resume(struct device *dev, u32 level) +{ + int i; + + if (level != RESUME_ENABLE) + return 0; + for (i = 0; i < UART_NR; i++) { - if (serial8250_ports[i].port.type != PORT_UNKNOWN && - serial8250_ports[i].port.irq < 16) - *map |= 1 << serial8250_ports[i].port.irq; + struct uart_8250_port *up = &serial8250_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == dev) + uart_resume_port(&serial8250_reg, &up->port); } + + return 0; +} + +static struct device_driver serial8250_isa_driver = { + .name = "serial8250", + .bus = &platform_bus_type, + .probe = serial8250_probe, + .remove = __devexit_p(serial8250_remove), + .suspend = serial8250_suspend, + .resume = serial8250_resume, +}; + +/* + * This "device" covers _all_ ISA 8250-compatible serial devices listed + * in the table in include/asm/serial.h + */ +static struct platform_device *serial8250_isa_devs; + +/* + * serial8250_register_port and serial8250_unregister_port allows for + * 16x50 serial ports to be configured at run-time, to support PCMCIA + * modems and PCI multiport cards. + */ +static DECLARE_MUTEX(serial_sem); + +/* + * Are the two ports equivalent? + */ +static int uart_match_port(struct uart_port *port1, struct uart_port *port2) +{ + if (port1->iotype != port2->iotype) + return 0; + + switch (port1->iotype) { + case UPIO_PORT: + return (port1->iobase == port2->iobase); + case UPIO_HUB6: + return (port1->iobase == port2->iobase) && + (port1->hub6 == port2->hub6); + case UPIO_MEM: + return (port1->membase == port2->membase); + } + return 0; +} + +static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) +{ + int i; + + /* + * First, find a port entry which matches. + */ + for (i = 0; i < UART_NR; i++) + if (uart_match_port(&serial8250_ports[i].port, port)) + return &serial8250_ports[i]; + + /* + * We didn't find a matching entry, so look for the first + * free entry. We look for one which hasn't been previously + * used (indicated by zero iobase). + */ + for (i = 0; i < UART_NR; i++) + if (serial8250_ports[i].port.type == PORT_UNKNOWN && + serial8250_ports[i].port.iobase == 0) + return &serial8250_ports[i]; + + /* + * That also failed. Last resort is to find any entry which + * doesn't have a real port associated with it. + */ + for (i = 0; i < UART_NR; i++) + if (serial8250_ports[i].port.type == PORT_UNKNOWN) + return &serial8250_ports[i]; + + return NULL; } /** - * serial8250_suspend_port - suspend one serial port - * @line: serial line number - * @level: the level of port suspension, as per uart_suspend_port + * serial8250_register_port - register a serial port + * @port: serial port template * - * Suspend one serial port. + * Configure the serial port specified by the request. If the + * port exists and is in use, it is hung up and unregistered + * first. + * + * The port is then probed and if necessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. */ -void serial8250_suspend_port(int line) +int serial8250_register_port(struct uart_port *port) { - uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); + struct uart_8250_port *uart; + int ret = -ENOSPC; + + if (port->uartclk == 0) + return -EINVAL; + + down(&serial_sem); + + uart = serial8250_find_match_or_unused(port); + if (uart) { + uart_remove_one_port(&serial8250_reg, &uart->port); + + uart->port.iobase = port->iobase; + uart->port.membase = port->membase; + uart->port.irq = port->irq; + uart->port.uartclk = port->uartclk; + uart->port.fifosize = port->fifosize; + uart->port.regshift = port->regshift; + uart->port.iotype = port->iotype; + uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; + uart->port.mapbase = port->mapbase; + if (port->dev) + uart->port.dev = port->dev; + + ret = uart_add_one_port(&serial8250_reg, &uart->port); + if (ret == 0) + ret = uart->port.line; + } + up(&serial_sem); + + return ret; } +EXPORT_SYMBOL(serial8250_register_port); /** - * serial8250_resume_port - resume one serial port - * @line: serial line number - * @level: the level of port resumption, as per uart_resume_port + * serial8250_unregister_port - remove a 16x50 serial port at runtime + * @line: serial line number * - * Resume one serial port. + * Remove one serial port. This may not be called from interrupt + * context. We hand the port back to the our control. */ -void serial8250_resume_port(int line) +void serial8250_unregister_port(int line) { - uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); + struct uart_8250_port *uart = &serial8250_ports[line]; + + down(&serial_sem); + uart_remove_one_port(&serial8250_reg, &uart->port); + if (serial8250_isa_devs) { + uart->port.flags &= ~UPF_BOOT_AUTOCONF; + uart->port.type = PORT_UNKNOWN; + uart->port.dev = &serial8250_isa_devs->dev; + uart_add_one_port(&serial8250_reg, &uart->port); + } else { + uart->port.dev = NULL; + } + up(&serial_sem); } +EXPORT_SYMBOL(serial8250_unregister_port); static int __init serial8250_init(void) { @@ -2174,18 +2450,42 @@ static int __init serial8250_init(void) spin_lock_init(&irq_lists[i].lock); ret = uart_register_driver(&serial8250_reg); - if (ret >= 0) - serial8250_register_ports(&serial8250_reg); + if (ret) + goto out; + serial8250_isa_devs = platform_device_register_simple("serial8250", + -1, NULL, 0); + if (IS_ERR(serial8250_isa_devs)) { + ret = PTR_ERR(serial8250_isa_devs); + goto unreg; + } + + serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); + + ret = driver_register(&serial8250_isa_driver); + if (ret == 0) + goto out; + + platform_device_unregister(serial8250_isa_devs); + unreg: + uart_unregister_driver(&serial8250_reg); + out: return ret; } static void __exit serial8250_exit(void) { - int i; + struct platform_device *isa_dev = serial8250_isa_devs; - for (i = 0; i < UART_NR; i++) - uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port); + /* + * This tells serial8250_unregister_port() not to re-register + * the ports (thereby making serial8250_isa_driver permanently + * in use.) + */ + serial8250_isa_devs = NULL; + + driver_unregister(&serial8250_isa_driver); + platform_device_unregister(isa_dev); uart_unregister_driver(&serial8250_reg); } @@ -2193,9 +2493,6 @@ static void __exit serial8250_exit(void) module_init(serial8250_init); module_exit(serial8250_exit); -EXPORT_SYMBOL(register_serial); -EXPORT_SYMBOL(unregister_serial); -EXPORT_SYMBOL(serial8250_get_irq_map); EXPORT_SYMBOL(serial8250_suspend_port); EXPORT_SYMBOL(serial8250_resume_port); @@ -2207,7 +2504,80 @@ MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" " (unsafe)"); #ifdef CONFIG_SERIAL_8250_RSA -module_param_array(probe_rsa, ulong, probe_rsa_count, 0444); +module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); #endif MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); + +/** + * register_serial - configure a 16x50 serial port at runtime + * @req: request structure + * + * Configure the serial port specified by the request. If the + * port exists and is in use an error is returned. If the port + * is not currently in the table it is added. + * + * The port is then probed and if necessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. + */ +int register_serial(struct serial_struct *req) +{ + struct uart_port port; + + port.iobase = req->port; + port.membase = req->iomem_base; + port.irq = req->irq; + port.uartclk = req->baud_base * 16; + port.fifosize = req->xmit_fifo_size; + port.regshift = req->iomem_reg_shift; + port.iotype = req->io_type; + port.flags = req->flags | UPF_BOOT_AUTOCONF; + port.mapbase = req->iomap_base; + port.dev = NULL; + + if (share_irqs) + port.flags |= UPF_SHARE_IRQ; + + if (HIGH_BITS_OFFSET) + port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET; + + /* + * If a clock rate wasn't specified by the low level driver, then + * default to the standard clock rate. This should be 115200 (*16) + * and should not depend on the architecture's BASE_BAUD definition. + * However, since this API will be deprecated, it's probably a + * better idea to convert the drivers to use the new API + * (serial8250_register_port and serial8250_unregister_port). + */ + if (port.uartclk == 0) { + printk(KERN_WARNING + "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n", + port.iobase, port.mapbase, port.membase, port.irq); + printk(KERN_WARNING "Serial: see %s:%d for more information\n", + __FILE__, __LINE__); + dump_stack(); + + /* + * Fix it up for now, but this is only a temporary measure. + */ + port.uartclk = BASE_BAUD * 16; + } + + return serial8250_register_port(&port); +} +EXPORT_SYMBOL(register_serial); + +/** + * unregister_serial - remove a 16x50 serial port at runtime + * @line: serial line number + * + * Remove one serial port. This may not be called from interrupt + * context. We hand the port back to our local PM control. + */ +void unregister_serial(int line) +{ + serial8250_unregister_port(line); +} +EXPORT_SYMBOL(unregister_serial); diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index da0ad9b3d..b4cb2fbaa 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -17,7 +17,8 @@ #include -void serial8250_get_irq_map(unsigned int *map); +int serial8250_register_port(struct uart_port *); +void serial8250_unregister_port(int line); void serial8250_suspend_port(int line); void serial8250_resume_port(int line); @@ -33,6 +34,22 @@ struct old_serial_port { unsigned short iomem_reg_shift; }; +/* + * This replaces serial_uart_config in include/linux/serial.h + */ +struct serial8250_config { + const char *name; + unsigned short fifo_size; + unsigned short tx_loadsz; + unsigned char fcr; + unsigned int flags; +}; + +#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */ +#define UART_CAP_EFR (1 << 9) /* UART has EFR */ +#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ +#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ + #undef SERIAL_DEBUG_PCI #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) @@ -55,3 +72,14 @@ struct old_serial_port { #else #define SERIAL8250_SHARE_IRQS 0 #endif + +#if defined(__alpha__) && !defined(CONFIG_PCI) +/* + * Digital did something really horribly wrong with the OUT1 and OUT2 + * lines on at least some ALPHA's. The failure mode is that if either + * is cleared, the machine locks up with endless interrupts. + */ +#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1) +#else +#define ALPHA_KLUDGE_MCR 0 +#endif diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c index 2e69f6c53..32af3650e 100644 --- a/drivers/serial/8250_acorn.c +++ b/drivers/serial/8250_acorn.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -22,11 +21,13 @@ #include #include +#include "8250.h" + #define MAX_PORTS 3 struct serial_card_type { unsigned int num_ports; - unsigned int baud_base; + unsigned int uartclk; unsigned int type; unsigned int offset[MAX_PORTS]; }; @@ -36,31 +37,15 @@ struct serial_card_info { int ports[MAX_PORTS]; }; -static inline int -serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base) -{ - struct serial_struct req; - - memset(&req, 0, sizeof(req)); - req.irq = irq; - req.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ; - req.baud_base = baud_base; - req.io_type = UPIO_MEM; - req.iomem_base = vaddr; - req.iomem_reg_shift = 2; - req.iomap_base = baddr; - - return register_serial(&req); -} - static int __devinit serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) { struct serial_card_info *info; struct serial_card_type *type = id->data; + struct uart_port port; unsigned long bus_addr; - unsigned char *virt_addr; - unsigned int port; + unsigned char __iomem *virt_addr; + unsigned int i; info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL); if (!info) @@ -69,21 +54,28 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) memset(info, 0, sizeof(struct serial_card_info)); info->num_ports = type->num_ports; - ecard_set_drvdata(ec, info); - - bus_addr = ec->resource[type->type].start; - virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1); + bus_addr = ecard_resource_start(ec, type->type); + virt_addr = ioremap(bus_addr, ecard_resource_len(ec, type->type)); if (!virt_addr) { kfree(info); return -ENOMEM; } - for (port = 0; port < info->num_ports; port ++) { - unsigned long baddr = bus_addr + type->offset[port]; - unsigned char *vaddr = virt_addr + type->offset[port]; + ecard_set_drvdata(ec, info); + + memset(&port, 0, sizeof(struct uart_port)); + port.irq = ec->irq; + port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + port.uartclk = type->uartclk; + port.iotype = UPIO_MEM; + port.regshift = 2; + port.dev = &ec->dev; + + for (i = 0; i < info->num_ports; i ++) { + port.membase = virt_addr + type->offset[i]; + port.mapbase = bus_addr + type->offset[i]; - info->ports[port] = serial_register_onedev(baddr, vaddr, - ec->irq, type->baud_base); + info->ports[i] = serial8250_register_port(&port); } return 0; @@ -98,21 +90,21 @@ static void __devexit serial_card_remove(struct expansion_card *ec) for (i = 0; i < info->num_ports; i++) if (info->ports[i] > 0) - unregister_serial(info->ports[i]); + serial8250_unregister_port(info->ports[i]); kfree(info); } static struct serial_card_type atomwide_type = { .num_ports = 3, - .baud_base = 7372800 / 16, + .uartclk = 7372800, .type = ECARD_RES_IOCSLOW, .offset = { 0x2800, 0x2400, 0x2000 }, }; static struct serial_card_type serport_type = { .num_ports = 2, - .baud_base = 3686400 / 16, + .uartclk = 3686400, .type = ECARD_RES_IOCSLOW, .offset = { 0x2000, 0x2020 }, }; @@ -128,7 +120,7 @@ static struct ecard_driver serial_card_driver = { .remove = __devexit_p(serial_card_remove), .id_table = serial_cids, .drv = { - .name = "8250_acorn", + .name = "8250_acorn", }, }; diff --git a/drivers/serial/8250_acpi.c b/drivers/serial/8250_acpi.c index ec25d59a1..6b9ead288 100644 --- a/drivers/serial/8250_acpi.c +++ b/drivers/serial/8250_acpi.c @@ -12,81 +12,71 @@ #include #include #include -#include -#include #include #include #include -#include + +#include "8250.h" struct serial_private { int line; - void *iomem_base; }; -static acpi_status acpi_serial_mmio(struct serial_struct *req, +static acpi_status acpi_serial_mmio(struct uart_port *port, struct acpi_resource_address64 *addr) { - unsigned long size; - - size = addr->max_address_range - addr->min_address_range + 1; - req->iomap_base = addr->min_address_range; - req->iomem_base = ioremap(req->iomap_base, size); - if (!req->iomem_base) { - printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n", - __FUNCTION__, req->iomap_base, req->iomap_base + size); - return AE_ERROR; - } - req->io_type = SERIAL_IO_MEM; + port->mapbase = addr->min_address_range; + port->iotype = UPIO_MEM; + port->flags |= UPF_IOREMAP; return AE_OK; } -static acpi_status acpi_serial_port(struct serial_struct *req, +static acpi_status acpi_serial_port(struct uart_port *port, struct acpi_resource_io *io) { if (io->range_length) { - req->port = io->min_base_address; - req->io_type = SERIAL_IO_PORT; + port->iobase = io->min_base_address; + port->iotype = UPIO_PORT; } else printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__); return AE_OK; } -static acpi_status acpi_serial_ext_irq(struct serial_struct *req, +static acpi_status acpi_serial_ext_irq(struct uart_port *port, struct acpi_resource_ext_irq *ext_irq) { if (ext_irq->number_of_interrupts > 0) - req->irq = acpi_register_gsi(ext_irq->interrupts[0], - ext_irq->edge_level, ext_irq->active_high_low); + port->irq = acpi_register_gsi(ext_irq->interrupts[0], + ext_irq->edge_level, ext_irq->active_high_low); return AE_OK; } -static acpi_status acpi_serial_irq(struct serial_struct *req, +static acpi_status acpi_serial_irq(struct uart_port *port, struct acpi_resource_irq *irq) { if (irq->number_of_interrupts > 0) - req->irq = acpi_register_gsi(irq->interrupts[0], - irq->edge_level, irq->active_high_low); + port->irq = acpi_register_gsi(irq->interrupts[0], + irq->edge_level, irq->active_high_low); return AE_OK; } static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data) { - struct serial_struct *serial_req = (struct serial_struct *) data; + struct uart_port *port = (struct uart_port *) data; struct acpi_resource_address64 addr; acpi_status status; status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) - return acpi_serial_mmio(serial_req, &addr); + return acpi_serial_mmio(port, &addr); else if (res->id == ACPI_RSTYPE_IO) - return acpi_serial_port(serial_req, &res->data.io); + return acpi_serial_port(port, &res->data.io); else if (res->id == ACPI_RSTYPE_EXT_IRQ) - return acpi_serial_ext_irq(serial_req, &res->data.extended_irq); + return acpi_serial_ext_irq(port, &res->data.extended_irq); else if (res->id == ACPI_RSTYPE_IRQ) - return acpi_serial_irq(serial_req, &res->data.irq); + return acpi_serial_irq(port, &res->data.irq); return AE_OK; } @@ -94,10 +84,13 @@ static int acpi_serial_add(struct acpi_device *device) { struct serial_private *priv; acpi_status status; - struct serial_struct serial_req; + struct uart_port port; int result; - memset(&serial_req, 0, sizeof(serial_req)); + memset(&port, 0, sizeof(struct uart_port)); + + port.uartclk = 1843200; + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL); if (!priv) { @@ -107,25 +100,20 @@ static int acpi_serial_add(struct acpi_device *device) memset(priv, 0, sizeof(*priv)); status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, - acpi_serial_resource, &serial_req); + acpi_serial_resource, &port); if (ACPI_FAILURE(status)) { result = -ENODEV; goto fail; } - if (serial_req.iomem_base) - priv->iomem_base = serial_req.iomem_base; - else if (!serial_req.port) { + if (!port.mapbase && !port.iobase) { printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n", __FUNCTION__, device->pnp.bus_id); result = -ENODEV; goto fail; } - serial_req.baud_base = BASE_BAUD; - serial_req.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; - - priv->line = register_serial(&serial_req); + priv->line = serial8250_register_port(&port); if (priv->line < 0) { printk(KERN_WARNING "Couldn't register serial port %s: %d\n", device->pnp.bus_id, priv->line); @@ -137,8 +125,6 @@ static int acpi_serial_add(struct acpi_device *device) return 0; fail: - if (serial_req.iomem_base) - iounmap(serial_req.iomem_base); kfree(priv); return result; @@ -152,9 +138,7 @@ static int acpi_serial_remove(struct acpi_device *device, int type) return -EINVAL; priv = acpi_driver_data(device); - unregister_serial(priv->line); - if (priv->iomem_base) - iounmap(priv->iomem_base); + serial8250_unregister_port(priv->line); kfree(priv); return 0; diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 97482bed7..a95bde861 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -22,37 +22,18 @@ #include #include #include -#include +#include /* for LASI_BASE_BAUD */ -static void setup_parisc_serial(struct serial_struct *serial, - unsigned long address, int irq, int line) -{ - memset(serial, 0, sizeof(struct serial_struct)); - - /* autoconfig() sets state->type. This sets info->type */ - serial->type = PORT_16550A; - - serial->line = line; - serial->iomap_base = address; - serial->iomem_base = ioremap(address, 0x8); - - serial->irq = irq; - serial->io_type = SERIAL_IO_MEM; /* define access method */ - serial->flags = 0; - serial->xmit_fifo_size = 16; - serial->custom_divisor = 0; - serial->baud_base = LASI_BASE_BAUD; -} +#include "8250.h" static int __init serial_init_chip(struct parisc_device *dev) { static int serial_line_nr; + struct uart_port port; unsigned long address; int err; - struct serial_struct *serial; - if (!dev->irq) { /* We find some unattached serial ports by walking native * busses. These should be silently ignored. Otherwise, @@ -66,21 +47,23 @@ serial_init_chip(struct parisc_device *dev) return -ENODEV; } - serial = kmalloc(sizeof(*serial), GFP_KERNEL); - if (!serial) - return -ENOMEM; - address = dev->hpa; if (dev->id.sversion != 0x8d) { address += 0x800; } - setup_parisc_serial(serial, address, dev->irq, serial_line_nr++); - err = register_serial(serial); + memset(&port, 0, sizeof(struct uart_port)); + port.mapbase = address; + port.irq = dev->irq; + port.iotype = UPIO_MEM; + port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; + port.uartclk = LASI_BASE_BAUD * 16; + port.dev = &dev->dev; + + err = serial8250_register_port(&port); if (err < 0) { - printk(KERN_WARNING "register_serial returned error %d\n", err); - kfree(serial); - return -ENODEV; + printk(KERN_WARNING "serial8250_register_port returned error %d\n", err); + return err; } return 0; diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 34b367778..11ed84047 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -22,11 +22,10 @@ #include #include #include -#include #include #include +#include -#include #include #include @@ -75,7 +74,7 @@ struct pci_serial_quirk { u32 subdevice; int (*init)(struct pci_dev *dev); int (*setup)(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx); + struct uart_port *port, int idx); void (*exit)(struct pci_dev *dev); }; @@ -83,7 +82,7 @@ struct pci_serial_quirk { struct serial_private { unsigned int nr; - void *remapped_bar[PCI_NUM_BAR_RESOURCES]; + void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES]; struct pci_serial_quirk *quirk; int line[0]; }; @@ -100,34 +99,32 @@ static void moan_device(const char *str, struct pci_dev *dev) } static int -setup_port(struct pci_dev *dev, struct serial_struct *req, +setup_port(struct pci_dev *dev, struct uart_port *port, int bar, int offset, int regshift) { struct serial_private *priv = pci_get_drvdata(dev); - unsigned long port, len; + unsigned long base, len; if (bar >= PCI_NUM_BAR_RESOURCES) return -EINVAL; if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { - port = pci_resource_start(dev, bar); + base = pci_resource_start(dev, bar); len = pci_resource_len(dev, bar); if (!priv->remapped_bar[bar]) - priv->remapped_bar[bar] = ioremap(port, len); + priv->remapped_bar[bar] = ioremap(base, len); if (!priv->remapped_bar[bar]) return -ENOMEM; - req->io_type = UPIO_MEM; - req->iomap_base = port + offset; - req->iomem_base = priv->remapped_bar[bar] + offset; - req->iomem_reg_shift = regshift; + port->iotype = UPIO_MEM; + port->mapbase = base + offset; + port->membase = priv->remapped_bar[bar] + offset; + port->regshift = regshift; } else { - port = pci_resource_start(dev, bar) + offset; - req->io_type = UPIO_PORT; - req->port = port; - if (HIGH_BITS_OFFSET) - req->port_high = port >> HIGH_BITS_OFFSET; + base = pci_resource_start(dev, bar) + offset; + port->iotype = UPIO_PORT; + port->iobase = base; } return 0; } @@ -138,7 +135,7 @@ setup_port(struct pci_dev *dev, struct serial_struct *req, */ static int afavlab_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -150,7 +147,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board, offset += (idx - 4) * board->uart_offset; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } /* @@ -191,7 +188,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev) */ static int pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int offset = board->first_offset; unsigned int bar = FL_GET_BASE(board->flags); @@ -213,7 +210,7 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, offset += idx * board->uart_offset; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } /* @@ -243,7 +240,8 @@ static int __devinit pci_inteli960ni_init(struct pci_dev *dev) */ static int __devinit pci_plx9050_init(struct pci_dev *dev) { - u8 *p, irq_config; + u8 irq_config; + void __iomem *p; if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) { moan_device("no memory in bar 0", dev); @@ -272,12 +270,12 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; - writel(irq_config, (unsigned long)p + 0x4c); + writel(irq_config, p + 0x4c); /* * Read the register back to ensure that it took effect. */ - readl((unsigned long)p + 0x4c); + readl(p + 0x4c); iounmap(p); return 0; @@ -285,7 +283,7 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) static void __devexit pci_plx9050_exit(struct pci_dev *dev) { - u8 *p; + u8 __iomem *p; if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) return; @@ -308,7 +306,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ static int sbs_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -323,7 +321,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, } else /* we have only 8 ports on PMC-OCTALPRO */ return 1; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } /* @@ -338,7 +336,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, static int __devinit sbs_init(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); @@ -362,7 +360,7 @@ static int __devinit sbs_init(struct pci_dev *dev) static void __devexit sbs_exit(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); if (p != NULL) { @@ -397,7 +395,8 @@ static void __devexit sbs_exit(struct pci_dev *dev) static int pci_siig10x_init(struct pci_dev *dev) { - u16 data, *p; + u16 data; + void __iomem *p; switch (dev->device & 0xfff8) { case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ @@ -415,8 +414,8 @@ static int pci_siig10x_init(struct pci_dev *dev) if (p == NULL) return -ENOMEM; - writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); - readw((unsigned long)p + 0x28); + writew(readw(p + 0x28) & data, p + 0x28); + readw(p + 0x28); iounmap(p); return 0; } @@ -520,7 +519,7 @@ static int __devinit pci_timedia_init(struct pci_dev *dev) */ static int pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int bar = 0, offset = board->first_offset; @@ -545,7 +544,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, bar = idx - 2; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } /* @@ -553,7 +552,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, */ static int titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -569,7 +568,7 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, offset = (idx - 2) * board->uart_offset; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } static int __devinit pci_xircom_init(struct pci_dev *dev) @@ -580,7 +579,7 @@ static int __devinit pci_xircom_init(struct pci_dev *dev) static int pci_default_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset, maxnr; @@ -596,7 +595,7 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) return 1; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(dev, port, bar, offset, board->reg_shift); } /* This should be in linux/pci_ids.h */ @@ -1027,6 +1026,7 @@ enum pci_board_num_t { pbn_b1_bt_2_921600, + pbn_b1_1_1382400, pbn_b1_2_1382400, pbn_b1_4_1382400, pbn_b1_8_1382400, @@ -1068,6 +1068,9 @@ enum pci_board_num_t { pbn_computone_6, pbn_computone_8, pbn_sbsxrsio, + pbn_exar_XR17C152, + pbn_exar_XR17C154, + pbn_exar_XR17C158, }; /* @@ -1251,6 +1254,12 @@ static struct pci_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b1_1_1382400] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 1382400, + .uart_offset = 8, + }, [pbn_b1_2_1382400] = { .flags = FL_BASE1, .num_ports = 2, @@ -1488,7 +1497,30 @@ static struct pci_board pci_boards[] __devinitdata = { .base_baud = 460800, .uart_offset = 256, .reg_shift = 4, - } + }, + /* + * Exar Corp. XR17C15[248] Dual/Quad/Octal UART + * Only basic 16550A support. + * XR17C15[24] are not tested, but they should work. + */ + [pbn_exar_XR17C152] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_exar_XR17C154] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_exar_XR17C158] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x200, + }, }; /* @@ -1582,7 +1614,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) struct serial_private *priv; struct pci_board *board, tmp; struct pci_serial_quirk *quirk; - struct serial_struct serial_req; int rc, nr_ports, i; if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { @@ -1662,19 +1693,22 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) pci_set_drvdata(dev, priv); for (i = 0; i < nr_ports; i++) { - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | - UPF_SHARE_IRQ; - serial_req.baud_base = board->base_baud; - serial_req.irq = get_pci_irq(dev, board, i); - if (quirk->setup(dev, board, &serial_req, i)) + struct uart_port serial_port; + memset(&serial_port, 0, sizeof(struct uart_port)); + + serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | + UPF_SHARE_IRQ; + serial_port.uartclk = board->base_baud * 16; + serial_port.irq = get_pci_irq(dev, board, i); + serial_port.dev = &dev->dev; + if (quirk->setup(dev, board, &serial_port, i)) break; #ifdef SERIAL_DEBUG_PCI printk("Setup PCI port: port %x, irq %d, type %d\n", - serial_req.port, serial_req.irq, serial_req.io_type); + serial_port.iobase, serial_port.irq, serial_port.iotype); #endif - priv->line[i] = register_serial(&serial_req); + priv->line[i] = serial8250_register_port(&serial_port); if (priv->line[i] < 0) { printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); break; @@ -1704,7 +1738,7 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev) int i; for (i = 0; i < priv->nr; i++) - unregister_serial(priv->line[i]); + serial8250_unregister_port(priv->line[i]); for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { if (priv->remapped_bar[i]) @@ -2081,6 +2115,20 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_460800 }, + /* + * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + + /* + * Dell Remote Access Card III - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + /* * RAStel 2 port modem, gerg@moreton.com.au */ @@ -2147,6 +2195,22 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_8_115200 }, + /* + * Exar Corp. XR17C15[248] Dual/Quad/Octal UART + */ + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C152 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C154 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C158 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index efa91660a..a7af0b01c 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -21,14 +21,10 @@ #include #include #include -#include -#include -#include #include +#include -#include #include -#include #include "8250.h" @@ -49,7 +45,7 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Actiontec ISA PNP 56K X2 Fax Modem */ { "AEI1240", 0 }, /* Rockwell 56K ACF II Fax+Data+Voice Modem */ - { "AKY1021", SPCI_FL_NO_SHIRQ }, + { "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ }, /* AZT3005 PnP SOUND DEVICE */ { "AZT4001", 0 }, /* Best Data Products Inc. Smart One 336F PnP Modem */ @@ -293,6 +289,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "USR0006", 0 }, /* U.S. Robotics 33.6K Voice EXT PnP */ { "USR0007", 0 }, + /* U.S. Robotics Courier V.Everything INT PnP */ + { "USR0009", 0 }, /* U.S. Robotics 33.6K Voice INT PnP */ { "USR2002", 0 }, /* U.S. Robotics 56K Voice INT PnP */ @@ -396,26 +394,29 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) static int __devinit serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) { - struct serial_struct serial_req; + struct uart_port port; int ret, line, flags = dev_id->driver_data; + if (flags & UNKNOWN_DEV) { ret = serial_pnp_guess_board(dev, &flags); if (ret < 0) return ret; } - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.irq = pnp_irq(dev,0); - serial_req.port = pnp_port_start(dev, 0); - if (HIGH_BITS_OFFSET) - serial_req.port = pnp_port_start(dev, 0) >> HIGH_BITS_OFFSET; + + memset(&port, 0, sizeof(struct uart_port)); + port.irq = pnp_irq(dev,0); + port.iobase = pnp_port_start(dev, 0); + #ifdef SERIAL_DEBUG_PNP printk("Setup PNP port: port %x, irq %d, type %d\n", - serial_req.port, serial_req.irq, serial_req.io_type); + port.iobase, port.irq, port.iotype); #endif - serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE; - serial_req.baud_base = 115200; - line = register_serial(&serial_req); + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + port.uartclk = 1843200; + port.dev = &dev->dev; + + line = serial8250_register_port(&port); if (line >= 0) pnp_set_drvdata(dev, (void *)(line + 1)); @@ -427,7 +428,7 @@ static void __devexit serial_pnp_remove(struct pnp_dev * dev) { int line = (int)pnp_get_drvdata(dev); if (line) - unregister_serial(line - 1); + serial8250_unregister_port(line - 1); } static struct pnp_driver serial_pnp_driver = { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 74a0b9cad..bf196291d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -10,7 +10,7 @@ menu "Serial drivers" # The new 8250/16550 serial drivers config SERIAL_8250 tristate "8250/16550 and compatible serial support" - depends on (BROKEN || !SPARC64) + depends on (BROKEN || !(SPARC64 || SPARC32)) select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard @@ -386,6 +386,29 @@ config SERIAL_SA1100_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_IMX + bool "IMX serial port support" + depends on ARM && ARCH_IMX + select SERIAL_CORE + help + If you have a machine based on a Motorola IMX CPU you + can enable its onboard serial port by enabling this option. + +config SERIAL_IMX_CONSOLE + bool "Console on IMX serial port" + depends on SERIAL_IMX + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Motorola IMX + CPU you can make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + config SERIAL_SUNCORE bool depends on SPARC32 || SPARC64 @@ -450,7 +473,7 @@ config SERIAL_MUX_CONSOLE config PDC_CONSOLE bool "PDC software console support" - depends on PARISC && !SERIAL_MUX + depends on PARISC && !SERIAL_MUX && VT default n help Saying Y here will enable the software based PDC console to be @@ -682,6 +705,7 @@ config SERIAL_SGI_L1_CONSOLE bool "SGI Altix L1 serial console support" depends on IA64_GENERIC || IA64_SGI_SN2 select SERIAL_CORE + select SERIAL_CORE_CONSOLE help If you have an SGI Altix and you would like to use the system controller serial port as your console (you want this!), @@ -714,4 +738,45 @@ config SERIAL_MPC52xx_CONSOLE_BAUD This value is only used if the bootloader doesn't pass in the console baudrate +config SERIAL_ICOM + tristate "IBM Multiport Serial Adapter" + depends on PPC_ISERIES || PPC_PSERIES + select SERIAL_CORE + help + This driver is for a family of multiport serial adapters + including 2 port RVX, 2 port internal modem, 4 port internal + modem and a split 1 port RVX and 1 port internal modem. + + This driver can also be built as a module. If so, the module + will be called icom. + +config SERIAL_M32R_SIO + bool "M32R SIO I/F" + depends on M32R + default y + select SERIAL_CORE + help + Say Y here if you want to use the M32R serial controller. + +config SERIAL_M32R_SIO_CONSOLE + bool "use SIO console" + depends on SERIAL_M32R_SIO=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you want to support a serial console. + + If you use an M3T-M32700UT or an OPSPUT platform, + please say also y for SERIAL_M32R_PLDSIO. + +config SERIAL_M32R_PLDSIO + bool "M32R SIO I/F on a PLD" + depends on SERIAL_M32R_SIO=y + default n + help + Say Y here if you want to use the M32R serial controller + on a PLD (Programmable Logic Device). + + If you use an M3T-M32700UT or an OPSPUT platform, + please say Y. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index dbe2e5f76..ee8d8de3c 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -9,12 +9,14 @@ serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o +serial-8250-$(CONFIG_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o @@ -40,4 +42,8 @@ obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o obj-$(CONFIG_SERIAL_BAST_SIO) += bast_sio.o obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o obj-$(CONFIG_SERIAL_CPM) += cpm_uart/ +obj-$(CONFIG_SERIAL_IMX) += imx.o obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o +obj-$(CONFIG_SERIAL_ICOM) += icom.o +obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o +obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o \ No newline at end of file diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index b88c00b37..ac57fdc87 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -32,25 +32,25 @@ * and hooked into this driver. */ #include + +#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include #include +#include +#include +#include +#include #include #include #include - -#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - #include #define UART_NR 2 @@ -149,22 +149,22 @@ pl010_rx_chars(struct uart_port *port) #endif { struct tty_struct *tty = port->info->tty; - unsigned int status, ch, rsr, max_count = 256; + unsigned int status, ch, flag, rsr, max_count = 256; status = UART_GET_FR(port); while (UART_RX_DATA(status) && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - return; - } + if (tty->low_latency) + tty_flip_buffer_push(tty); + /* + * If this failed then we will throw away the + * bytes but must do so to clear interrupts. + */ } ch = UART_GET_CHAR(port); + flag = TTY_NORMAL; - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; port->icount.rx++; /* @@ -188,20 +188,18 @@ pl010_rx_chars(struct uart_port *port) rsr &= port->read_status_mask; if (rsr & UART01x_RSR_BE) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (rsr & UART01x_RSR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (rsr & UART01x_RSR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; if ((rsr & port->ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); } if ((rsr & UART01x_RSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { @@ -210,9 +208,7 @@ pl010_rx_chars(struct uart_port *port) * immediately, and doesn't affect the current * character */ - *tty->flip.char_buf_ptr++ = 0; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - tty->flip.count++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: status = UART_GET_FR(port); @@ -714,6 +710,24 @@ static struct console amba_console = { .data = &amba_reg, }; +static int __init amba_console_init(void) +{ + /* + * All port initializations are done statically + */ + register_console(&amba_console); + return 0; +} +console_initcall(amba_console_init); + +static int __init amba_late_console_init(void) +{ + if (!(amba_console.flags & CON_ENABLED)) + register_console(&amba_console); + return 0; +} +late_initcall(amba_late_console_init); + #define AMBA_CONSOLE &amba_console #else #define AMBA_CONSOLE NULL diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index c91f6b149..ff658a830 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -32,26 +32,26 @@ * and hooked into this driver. */ #include + +#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include #include +#include +#include +#include +#include #include #include #include #include - -#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - #include #define UART_NR 14 @@ -115,22 +115,21 @@ pl011_rx_chars(struct uart_amba_port *uap) #endif { struct tty_struct *tty = uap->port.info->tty; - unsigned int status, ch, rsr, max_count = 256; + unsigned int status, ch, flag, rsr, max_count = 256; status = readw(uap->port.membase + UART01x_FR); while ((status & UART01x_FR_RXFE) == 0 && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - return; - } + if (tty->low_latency) + tty_flip_buffer_push(tty); + /* + * If this failed then we will throw away the + * bytes but must do so to clear interrupts + */ } ch = readw(uap->port.membase + UART01x_DR); - - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; uap->port.icount.rx++; /* @@ -154,20 +153,18 @@ pl011_rx_chars(struct uart_amba_port *uap) rsr &= uap->port.read_status_mask; if (rsr & UART01x_RSR_BE) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (rsr & UART01x_RSR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (rsr & UART01x_RSR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&uap->port, ch, regs)) goto ignore_char; if ((rsr & uap->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); } if ((rsr & UART01x_RSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { @@ -176,9 +173,7 @@ pl011_rx_chars(struct uart_amba_port *uap) * immediately, and doesn't affect the current * character */ - *tty->flip.char_buf_ptr++ = 0; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - tty->flip.count++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: status = readw(uap->port.membase + UART01x_FR); @@ -696,7 +691,6 @@ static int __init pl011_console_setup(struct console *co, char *options) int bits = 8; int parity = 'n'; int flow = 'n'; - int ret; /* * Check whether an invalid uart number has been specified, and @@ -746,7 +740,7 @@ static struct uart_driver amba_reg = { static int pl011_probe(struct amba_device *dev, void *id) { struct uart_amba_port *uap; - void *base; + void __iomem *base; int i, ret; for (i = 0; i < ARRAY_SIZE(amba_ports); i++) diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index f1c524aca..1db28380b 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -1313,20 +1313,6 @@ void unregister_serial(int line) uart_unregister_port(&serial8250_reg, line); } -/* - * This is for ISAPNP only. - */ -void serial8250_get_irq_map(unsigned int *map) -{ - int i; - - for (i = 0; i < UART_NR; i++) { - if (serial8250_ports[i].port.type != PORT_UNKNOWN && - serial8250_ports[i].port.irq < 16) - *map |= 1 << serial8250_ports[i].port.irq; - } -} - /** * serial8250_suspend_port - suspend one serial port * @line: serial line number @@ -1382,7 +1368,6 @@ module_exit(serial8250_exit); EXPORT_SYMBOL(register_serial); EXPORT_SYMBOL(unregister_serial); -EXPORT_SYMBOL(serial8250_get_irq_map); EXPORT_SYMBOL(serial8250_suspend_port); EXPORT_SYMBOL(serial8250_resume_port); diff --git a/drivers/serial/bast_sio.c b/drivers/serial/bast_sio.c index 698514d16..2b48fab6f 100644 --- a/drivers/serial/bast_sio.c +++ b/drivers/serial/bast_sio.c @@ -1,3 +1,19 @@ +/* linux/drivers/serial/bast_sio.c + * + * Copyright (c) 2004 Simtec Electronics + * Ben Dooks + * + * http://www.simtec.co.uk/products/EB2410ITX/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 23-Sep-2004 BJD Added copyright header + * 23-Sep-2004 BJD Added serial port remove code +*/ + #include #include #include @@ -20,10 +36,6 @@ static int __init serial_bast_register(unsigned long port, unsigned int irq) { struct serial_struct serial_req; -#if 0 - printk("BAST: SuperIO serial (%08lx,%d)\n", port, irq); -#endif - serial_req.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ; serial_req.baud_base = BASE_BAUD; serial_req.irq = irq; @@ -37,11 +49,13 @@ static int __init serial_bast_register(unsigned long port, unsigned int irq) #define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO) +static int port[2] = { -1, -1 }; + static int __init serial_bast_init(void) { if (machine_is_bast()) { - serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1); - serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2); + port[0] = serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1); + port[1] = serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2); } return 0; @@ -49,7 +63,10 @@ static int __init serial_bast_init(void) static void __exit serial_bast_exit(void) { - /* todo -> remove both our ports */ + if (port[0] != -1) + unregister_serial(port[0]); + if (port[1] != -1) + unregister_serial(port[1]); } diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 4aaef99d1..16592fae4 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -26,26 +26,26 @@ * */ #include + +#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include #include #include +#include +#include +#include +#include #include #include #include - -#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - #include #define UART_NR 2 @@ -123,9 +123,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re goto ignore_char; error_return: - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flg); ignore_char: status = clps_readl(SYSFLG(port)); } @@ -158,11 +156,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; + tty_insert_flip_char(tty, ch, flg); ch = 0; flg = TTY_OVERRUN; } diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 598704e7e..5f6187baa 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -17,13 +17,8 @@ #include "cpm_uart_cpm1.h" #endif -#ifndef CONFIG_SERIAL_8250 -#define SERIAL_CPM_MAJOR TTY_MAJOR -#define SERIAL_CPM_MINOR 64 -#else #define SERIAL_CPM_MAJOR 204 -#define SERIAL_CPM_MINOR 42 -#endif +#define SERIAL_CPM_MINOR 46 #define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC) #define IS_DISCARDING(pinfo) (pinfo->flags & FLAG_DISCARDING) @@ -70,6 +65,8 @@ struct uart_cpm_port { /* helpers */ int baud; int bits; + /* Keep track of 'odd' SMC2 wirings */ + int is_portb; }; extern int cpm_uart_port_map[UART_NR]; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 34f4c6737..73306b9d9 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -743,6 +743,18 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE; pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE; +/* + * In case SMC1 is being relocated... + */ +#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH) + up->smc_rbptr = pinfo->smcup->smc_rbase; + up->smc_tbptr = pinfo->smcup->smc_tbase; + up->smc_rstate = 0; + up->smc_tstate = 0; + up->smc_brkcr = 1; /* number of break chars */ + up->smc_brkec = 0; +#endif + /* Set up the uart parameters in the * parameter ram. */ @@ -872,6 +884,9 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = smc2_lineif, +#ifdef CONFIG_SERIAL_CPM_ALT_SMC2 + .is_portb = 1, +#endif }, [UART_SCC1] = { .port = { diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index a9ab04731..de26cf7b0 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -82,10 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) void smc1_lineif(struct uart_cpm_port *pinfo) { volatile cpm8xx_t *cp = cpmp; - - cp->cp_pbpar |= 0x000000c0; - cp->cp_pbdir &= ~0x000000c0; - cp->cp_pbodr &= ~0x000000c0; + unsigned int iobits = 0x000000c0; + + if (!pinfo->is_portb) { + cp->cp_pbpar |= iobits; + cp->cp_pbdir &= ~iobits; + cp->cp_pbodr &= ~iobits; + } else { + ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; + } pinfo->brg = 1; } @@ -194,8 +201,16 @@ int cpm_uart_init_portdesc(void) cpm_uart_nr = 0; #ifdef CONFIG_SERIAL_CPM_SMC1 cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0]; +/* + * Is SMC1 being relocated? + */ +# ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH + cpm_uart_ports[UART_SMC1].smcup = + (smc_uart_t *) & cpmp->cp_dparam[0x3C0]; +# else cpm_uart_ports[UART_SMC1].smcup = (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC1]; +# endif cpm_uart_ports[UART_SMC1].port.mapbase = (unsigned long)&cpmp->cp_smc[0]; cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX); diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 293d17234..97824eeea 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -28,12 +28,13 @@ #include #include -#include #include #include #include -#include +#include +#include #include +#include #include #include @@ -186,7 +187,7 @@ static inline void dz_receive_chars(struct dz_port *dport) struct uart_icount *icount; int ignore = 0; unsigned short status, tmp; - unsigned char ch; + unsigned char ch, flag; /* this code is going to be a problem... the call to tty_flip_buffer is going to need @@ -201,6 +202,7 @@ static inline void dz_receive_chars(struct dz_port *dport) ch = UCHAR(status); /* grab the char */ + flag = TTY_NORMAL; #if 0 if (info->is_console) { @@ -217,8 +219,6 @@ static inline void dz_receive_chars(struct dz_port *dport) if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = 0; icount->rx++; /* keep track of the statistics */ @@ -243,12 +243,12 @@ static inline void dz_receive_chars(struct dz_port *dport) tmp = status & dport->port.read_status_mask; if (tmp & DZ_PERR) { - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; #ifdef DEBUG_DZ debug_console("PERR\n", 5); #endif } else if (tmp & DZ_FERR) { - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; #ifdef DEBUG_DZ debug_console("FERR\n", 5); #endif @@ -257,17 +257,12 @@ static inline void dz_receive_chars(struct dz_port *dport) #ifdef DEBUG_DZ debug_console("OERR\n", 5); #endif - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } + tty_insert_flip_char(tty, ch, flag); + ch = 0; + flag = TTY_OVERRUN; } } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); ignore_char: } while (status & DZ_DVAL); diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index c15c8a0aa..63b647fcc 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -54,13 +54,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include "icom.h" @@ -140,12 +140,6 @@ static inline void trace(struct icom_port *, char *, unsigned long) {}; static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {}; #endif -static void msleep(unsigned long msecs) -{ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(MSECS_TO_JIFFIES(msecs)); -} - static void free_port_memory(struct icom_port *icom_port) { struct pci_dev *dev = icom_port->adapter->pci_dev; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index dfed45204..d8875ae2c 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -34,13 +34,14 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -424,11 +425,7 @@ static void mcfrs_offintr(void *private) tty = info->tty; if (!tty) return; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } @@ -739,7 +736,7 @@ static void mcfrs_flush_chars(struct tty_struct *tty) local_irq_restore(flags); } -static int mcfrs_write(struct tty_struct * tty, int from_user, +static int mcfrs_write(struct tty_struct * tty, const unsigned char *buf, int count) { volatile unsigned char *uartp; @@ -748,8 +745,8 @@ static int mcfrs_write(struct tty_struct * tty, int from_user, int c, total = 0; #if 0 - printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", - __FILE__, __LINE__, (int)tty, from_user, (int)buf, count); + printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n", + __FILE__, __LINE__, (int)tty, (int)buf, count); #endif if (serial_paranoia_check(info, tty->name, "mcfrs_write")) @@ -768,19 +765,7 @@ static int mcfrs_write(struct tty_struct * tty, int from_user, if (c <= 0) break; - if (from_user) { - down(&mcfrs_tmp_buf_sem); - if (copy_from_user(mcfrs_tmp_buf, buf, c)) - return -EFAULT; - - local_irq_disable(); - c = min(c, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1, - ((int)SERIAL_XMIT_SIZE) - info->xmit_head)); - local_irq_restore(flags); - memcpy(info->xmit_buf + info->xmit_head, mcfrs_tmp_buf, c); - up(&mcfrs_tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); local_irq_disable(); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); @@ -835,10 +820,7 @@ static void mcfrs_flush_buffer(struct tty_struct *tty) info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; local_irq_restore(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -997,7 +979,7 @@ static void send_break( struct mcf_serial * info, int duration) if (!info->addr) return; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); uartp = info->addr; local_irq_save(flags); @@ -1232,11 +1214,12 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); + tty->closing = 0; info->event = 0; info->tty = 0; +#if 0 if (tty->ldisc.num != ldiscs[N_TTY].num) { if (tty->ldisc.close) (tty->ldisc.close)(tty); @@ -1245,10 +1228,10 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp) if (tty->ldisc.open) (tty->ldisc.open)(tty); } +#endif if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -1313,8 +1296,7 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout) fifo_cnt++; if (fifo_cnt == 0) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 72586594b..34e149048 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -29,6 +29,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * 2004-08-06 Harald Welte + * - Enable BREAK interrupt + * - Add support for sysreq + * * TODO: - Add DMA support * - Defer port shutdown to a few seconds after close * - maybe put something right into uap->clk_divisor @@ -36,6 +40,7 @@ #undef DEBUG #undef DEBUG_HARD +#undef USE_CTRL_O_SYSRQ #include #include @@ -53,17 +58,22 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include #include #include +#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include @@ -259,8 +269,27 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, } ch &= uap->parity_mask; - if (ch == 0 && uap->prev_status & BRK_ABRT) - r1 |= BRK_ABRT; + if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) { + uap->flags &= ~PMACZILOG_FLAG_BREAK; + } + +#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_SERIAL_CORE_CONSOLE) +#ifdef USE_CTRL_O_SYSRQ + /* Handle the SysRq ^O Hack */ + if (ch == '\x0f') { + uap->port.sysrq = jiffies + HZ*5; + goto next_char; + } +#endif /* USE_CTRL_O_SYSRQ */ + if (uap->port.sysrq) { + int swallow; + spin_unlock(&uap->port.lock); + swallow = uart_handle_sysrq_char(&uap->port, ch, regs); + spin_lock(&uap->port.lock); + if (swallow) + goto next_char; + } +#endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ /* A real serial line, record the character and status. */ if (drop) @@ -276,10 +305,8 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) { - pmz_debug("pmz: do handle break !\n"); + if (uart_handle_break(&uap->port)) goto next_char; - } } else if (r1 & PAR_ERR) uap->port.icount.parity++; @@ -295,10 +322,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, else if (r1 & CRC_ERR) *tty->flip.flag_buf_ptr = TTY_FRAME; } - if (uart_handle_sysrq_char(&uap->port, ch, regs)) { - pmz_debug("pmz: sysrq swallowed the char\n"); - goto next_char; - } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->port.ignore_status_mask) == 0) { @@ -364,6 +387,9 @@ static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs) wake_up_interruptible(&uap->port.info->delta_msr_wait); } + if (status & BRK_ABRT) + uap->flags |= PMACZILOG_FLAG_BREAK; + uap->prev_status = status; } @@ -872,8 +898,8 @@ static int __pmz_startup(struct uart_pmac_port *uap) uap->curregs[R13] = 0; uap->curregs[R14] = BRENAB; - /* Clear handshaking */ - uap->curregs[R15] = 0; + /* Clear handshaking, enable BREAK interrupts */ + uap->curregs[R15] = BRKIE; /* Master interrupt enable */ uap->curregs[R9] |= NV | MIE; @@ -949,8 +975,7 @@ static int pmz_startup(struct uart_port *port) */ if (pwr_delay != 0) { pmz_debug("pmz: delaying %d ms\n", pwr_delay); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((pwr_delay * HZ)/1000); + msleep(pwr_delay); } /* IrDA reset is done now */ @@ -1309,6 +1334,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, /* Load registers to the chip */ pmz_maybe_update_regs(uap); } + uart_update_timeout(port, termios->c_cflag, baud); + pmz_debug("pmz: set_termios() done.\n"); } @@ -1412,7 +1439,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) uap->port.mapbase = np->addrs[0].address; uap->port.membase = ioremap(uap->port.mapbase, 0x1000); - uap->control_reg = (volatile u8 *)uap->port.membase; + uap->control_reg = uap->port.membase; uap->data_reg = uap->control_reg + 0x10; /* @@ -1423,16 +1450,14 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) uap->flags |= PMACZILOG_FLAG_HAS_DMA; #endif if (ZS_HAS_DMA(uap)) { - uap->tx_dma_regs = (volatile struct dbdma_regs *) - ioremap(np->addrs[np->n_addrs - 2].address, 0x1000); + uap->tx_dma_regs = ioremap(np->addrs[np->n_addrs - 2].address, 0x1000); if (uap->tx_dma_regs == NULL) { uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - uap->rx_dma_regs = (volatile struct dbdma_regs *) - ioremap(np->addrs[np->n_addrs - 1].address, 0x1000); + uap->rx_dma_regs = ioremap(np->addrs[np->n_addrs - 1].address, 0x1000); if (uap->rx_dma_regs == NULL) { - iounmap((void *)uap->tx_dma_regs); + iounmap(uap->tx_dma_regs); uap->tx_dma_regs = NULL; uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; @@ -1509,9 +1534,9 @@ static void pmz_dispose_port(struct uart_pmac_port *uap) struct device_node *np; np = uap->node; - iounmap((void *)uap->rx_dma_regs); - iounmap((void *)uap->tx_dma_regs); - iounmap((void *)uap->control_reg); + iounmap(uap->rx_dma_regs); + iounmap(uap->tx_dma_regs); + iounmap(uap->control_reg); uap->node = NULL; of_node_put(np); memset(uap, 0, sizeof(struct uart_pmac_port)); @@ -1576,7 +1601,7 @@ static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) return 0; } - if (pm_state == mdev->ofdev.dev.power_state || pm_state < 2) + if (pm_state == mdev->ofdev.dev.power.power_state || pm_state < 2) return 0; pmz_debug("suspend, switching to state %d\n", pm_state); @@ -1620,7 +1645,7 @@ static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) pmz_debug("suspend, switching complete\n"); - mdev->ofdev.dev.power_state = pm_state; + mdev->ofdev.dev.power.power_state = pm_state; return 0; } @@ -1636,7 +1661,7 @@ static int pmz_resume(struct macio_dev *mdev) if (uap == NULL) return 0; - if (mdev->ofdev.dev.power_state == 0) + if (mdev->ofdev.dev.power.power_state == 0) return 0; pmz_debug("resume, switching to state 0\n"); @@ -1684,13 +1709,12 @@ static int pmz_resume(struct macio_dev *mdev) */ if (pwr_delay != 0) { pmz_debug("pmz: delaying %d ms\n", pwr_delay); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((pwr_delay * HZ)/1000); + msleep(pwr_delay); } pmz_debug("resume, switching complete\n"); - mdev->ofdev.dev.power_state = 0; + mdev->ofdev.dev.power.power_state = 0; return 0; } diff --git a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h index 63bb9716c..c03f9bfac 100644 --- a/drivers/serial/pmac_zilog.h +++ b/drivers/serial/pmac_zilog.h @@ -47,17 +47,18 @@ struct uart_pmac_port { #define PMACZILOG_FLAG_IS_OPEN 0x00002000 #define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000 #define PMACZILOG_FLAG_IS_EXTCLK 0x00008000 +#define PMACZILOG_FLAG_BREAK 0x00010000 unsigned char parity_mask; unsigned char prev_status; - volatile u8 *control_reg; - volatile u8 *data_reg; + volatile u8 __iomem *control_reg; + volatile u8 __iomem *data_reg; unsigned int tx_dma_irq; unsigned int rx_dma_irq; - volatile struct dbdma_regs *tx_dma_regs; - volatile struct dbdma_regs *rx_dma_regs; + volatile struct dbdma_regs __iomem *tx_dma_regs; + volatile struct dbdma_regs __iomem *rx_dma_regs; struct termios termios_cache; }; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index cb6b4f3ec..68b25b2c2 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -25,8 +25,12 @@ */ #include + +#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include #include @@ -36,16 +40,14 @@ #include #include #include +#include +#include +#include #include #include #include - -#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include +#include struct uart_pxa_port { @@ -101,25 +103,20 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) { struct tty_struct *tty = up->port.info->tty; - unsigned char ch; + unsigned int ch, flag; int max_count = 256; do { if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + if (tty->low_latency) + tty_flip_buffer_push(tty); /* - * FIXME: Deadlock can happen here if we're a - * low-latency port. We're holding the per-port - * spinlock, and we call flush_to_ldisc-> - * n_tty_receive_buf->n_tty_receive_char-> - * opost->uart_put_char. + * If this failed then we will throw away the + * bytes but must do so to clear interrupts */ - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set } ch = serial_in(up, UART_RX); - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | @@ -158,18 +155,16 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) } #endif if (*status & UART_LSR_BI) { - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; } else if (*status & UART_LSR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (*status & UART_LSR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; if ((*status & up->port.ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flag); } if ((*status & UART_LSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { @@ -178,10 +173,7 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) * immediately, and doesn't affect the current * character. */ - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } ignore_char: *status = serial_in(up, UART_LSR); diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 22a02bd69..c2fa9b43a 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1,7 +1,7 @@ /* - * linux/drivers/char/s3c2410.c + * linux/drivers/serial/s3c2410.c * - * Driver for onboard UARTs on the Samsung S3C2410 + * Driver for onboard UARTs on the Samsung S3C24XX * * Based on drivers/char/serial.c and drivers/char/21285.c * @@ -9,56 +9,153 @@ * * Changelog: * - */ + * 22-Jul-2004 BJD Finished off device rewrite + * + * 21-Jul-2004 BJD Thanks to for pointing out + * problems with baud rate and loss of IR settings. Update + * to add configuration via platform_device structure + * + * 28-Sep-2004 BJD Re-write for the following items + * - S3C2410 and S3C2440 serial support + * - Power Management support + * - Fix console via IrDA devices + * - SysReq (Herbert Pötzl) + * - Break character handling (Herbert Pötzl) + * - spin-lock initialisation (Dimitry Andric) + * - added clock control + * - updated init code to use platform_device info +*/ + +/* Hote on 2410 error handling + * + * The s3c2410 manual has a love/hate affair with the contents of the + * UERSTAT register in the UART blocks, and keeps marking some of the + * error bits as reserved. Having checked with the s3c2410x01, + * it copes with BREAKs properly, so I am happy to ignore the RESERVED + * feature from the latter versions of the manual. + * + * If it becomes aparrent that latter versions of the 2410 remove these + * bits, then action will have to be taken to differentiate the versions + * and change the policy on BREAK + * + * BJD, 04-Nov-2004 +*/ + #include + +#if defined(CONFIG_SERIAL_S3C2410_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include #include +#include #include +#include +#include #include #include +#include #include #include #include +#include + #include +#include #include +/* structures */ + +struct s3c24xx_uart_info { + char *name; + unsigned int type; + unsigned int fifosize; + unsigned long rx_fifomask; + unsigned long rx_fifoshift; + unsigned long rx_fifofull; + unsigned long tx_fifomask; + unsigned long tx_fifoshift; + unsigned long tx_fifofull; + + /* clock source control */ + + int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); + int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); +}; + +struct s3c24xx_uart_port { + unsigned char rx_claimed; + unsigned char tx_claimed; + + struct s3c24xx_uart_info *info; + struct s3c24xx_uart_clksrc *clksrc; + struct clk *clk; + struct clk *baudclk; + struct uart_port port; +}; + + +/* configuration defines */ + #if 0 -#include -#define dbg(x...) llprintk(x) +#if 1 +/* send debug to the low-level output routines */ + +extern void printascii(const char *); + +static void +s3c24xx_serial_dbg(const char *fmt, ...) +{ + va_list va; + char buff[256]; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + printascii(buff); +} + +#define dbg(x...) s3c24xx_serial_dbg(x) + #else -#define dbg(x...) +#define dbg(x...) printk(KERN_DEBUG "s3c24xx: "); +#endif +#else /* no debug */ +#define dbg(x...) do {} while(0) #endif -#define SERIAL_S3C2410_NAME "ttySAC" -#define SERIAL_S3C2410_MAJOR 204 -#define SERIAL_S3C2410_MINOR 64 +/* UART name and device definitions */ + +#define S3C24XX_SERIAL_NAME "ttySAC" +#define S3C24XX_SERIAL_DEVFS "tts/" +#define S3C24XX_SERIAL_MAJOR 204 +#define S3C24XX_SERIAL_MINOR 64 + + +/* conversion functions */ + +#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) +#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data) /* we can support 3 uarts, but not always use them */ #define NR_PORTS (3) -static const char serial_s3c2410_name[] = "Samsung S3C2410 UART"; - /* port irq numbers */ #define TX_IRQ(port) ((port)->irq + 1) #define RX_IRQ(port) ((port)->irq) -#define tx_enabled(port) ((port)->unused[0]) -#define rx_enabled(port) ((port)->unused[1]) - -/* flag to ignore all characters comming in */ -#define RXSTAT_DUMMY_READ (0x10000000) +/* register access controls */ -/* access functions */ - -#define portaddr(port, reg) ((void *)((port)->membase + (reg))) +#define portaddr(port, reg) ((port)->membase + (reg)) #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) @@ -69,107 +166,234 @@ static const char serial_s3c2410_name[] = "Samsung S3C2410 UART"; #define wr_regl(port, reg, val) \ do { __raw_writel(val, portaddr(port, reg)); } while(0) +/* macros to change one thing to another */ + +#define tx_enabled(port) ((port)->unused[0]) +#define rx_enabled(port) ((port)->unused[1]) + +/* flag to ignore all characters comming in */ +#define RXSTAT_DUMMY_READ (0x10000000) + +static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port) +{ + return container_of(port, struct s3c24xx_uart_port, port); +} + +/* translate a port to the device name */ + +static inline char *s3c24xx_serial_portname(struct uart_port *port) +{ + return to_platform_device(port->dev)->name; +} + +static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) +{ + return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); +} + +static void s3c24xx_serial_rx_enable(struct uart_port *port) +{ + unsigned long flags; + unsigned int ucon, ufcon; + int count = 10000; + + spin_lock_irqsave(&port->lock, flags); + + while (--count && !s3c24xx_serial_txempty_nofifo(port)) + udelay(100); + + ufcon = rd_regl(port, S3C2410_UFCON); + ufcon |= S3C2410_UFCON_RESETRX; + wr_regl(port, S3C2410_UFCON, ufcon); + + ucon = rd_regl(port, S3C2410_UCON); + ucon |= S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + rx_enabled(port) = 1; + spin_unlock_irqrestore(&port->lock, flags); +} + +static void s3c24xx_serial_rx_disable(struct uart_port *port) +{ + unsigned long flags; + unsigned int ucon; + spin_lock_irqsave(&port->lock, flags); + ucon = rd_regl(port, S3C2410_UCON); + ucon &= ~S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); -/* code */ + rx_enabled(port) = 0; + spin_unlock_irqrestore(&port->lock, flags); +} static void -serial_s3c2410_stop_tx(struct uart_port *port, unsigned int tty_stop) +s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop) { if (tx_enabled(port)) { disable_irq(TX_IRQ(port)); tx_enabled(port) = 0; + if (port->flags & UPF_CONS_FLOW) + s3c24xx_serial_rx_enable(port); } } static void -serial_s3c2410_start_tx(struct uart_port *port, unsigned int tty_start) +s3c24xx_serial_start_tx(struct uart_port *port, unsigned int tty_start) { if (!tx_enabled(port)) { + if (port->flags & UPF_CONS_FLOW) + s3c24xx_serial_rx_disable(port); + enable_irq(TX_IRQ(port)); tx_enabled(port) = 1; } } -static void serial_s3c2410_stop_rx(struct uart_port *port) + +static void s3c24xx_serial_stop_rx(struct uart_port *port) { if (rx_enabled(port)) { - dbg("serial_s3c2410_stop_rx: port=%p\n", port); + dbg("s3c24xx_serial_stop_rx: port=%p\n", port); disable_irq(RX_IRQ(port)); rx_enabled(port) = 0; } } -static void serial_s3c2410_enable_ms(struct uart_port *port) +static void s3c24xx_serial_enable_ms(struct uart_port *port) +{ +} + +static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) +{ + return to_ourport(port)->info; +} + +static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) +{ + if (port->dev == NULL) + return NULL; + + return (struct s3c2410_uartcfg *)port->dev->platform_data; +} + +static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, + unsigned long ufstat) { + struct s3c24xx_uart_info *info = ourport->info; + + if (ufstat & info->rx_fifofull) + return info->fifosize; + + return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; } + /* ? - where has parity gone?? */ #define S3C2410_UERSTAT_PARITY (0x1000) static irqreturn_t -serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs) +s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) { - struct uart_port *port = dev_id; + struct s3c24xx_uart_port *ourport = dev_id; + struct uart_port *port = &ourport->port; struct tty_struct *tty = port->info->tty; - unsigned int ufcon, ch, rxs, ufstat; - int max_count = 256; + unsigned int ufcon, ch, flag, ufstat, uerstat; + int max_count = 64; while (max_count-- > 0) { ufcon = rd_regl(port, S3C2410_UFCON); ufstat = rd_regl(port, S3C2410_UFSTAT); - if (S3C2410_UFCON_RXC(ufstat) == 0) + if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) break; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void *)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - goto out; - } + if (tty->low_latency) + tty_flip_buffer_push(tty); + + /* + * If this failed then we will throw away the + * bytes but must do so to clear interrupts + */ } + uerstat = rd_regl(port, S3C2410_UERSTAT); ch = rd_regb(port, S3C2410_URXH); - *tty->flip.char_buf_ptr = ch; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + if (port->flags & UPF_CONS_FLOW) { + int txe = s3c24xx_serial_txempty_nofifo(port); + + if (rx_enabled(port)) { + if (!txe) { + rx_enabled(port) = 0; + continue; + } + } else { + if (txe) { + ufcon |= S3C2410_UFCON_RESETRX; + wr_regl(port, S3C2410_UFCON, ufcon); + rx_enabled(port) = 1; + goto out; + } + continue; + } + } + + /* insert the character into the buffer */ + + flag = TTY_NORMAL; port->icount.rx++; - rxs = rd_regb(port, S3C2410_UERSTAT) | RXSTAT_DUMMY_READ; + if (uerstat & S3C2410_UERSTAT_ANY) { + dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", + ch, uerstat); + + /* check for break */ + if (uerstat & S3C2410_UERSTAT_BREAK) { + dbg("break!\n"); + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } - if (rxs & S3C2410_UERSTAT_ANY) { - if (rxs & S3C2410_UERSTAT_FRAME) + if (uerstat & S3C2410_UERSTAT_FRAME) port->icount.frame++; - if (rxs & S3C2410_UERSTAT_OVERRUN) + if (uerstat & S3C2410_UERSTAT_OVERRUN) port->icount.overrun++; - rxs &= port->read_status_mask; + uerstat &= port->read_status_mask; - if (rxs & S3C2410_UERSTAT_PARITY) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (rxs & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN)) - *tty->flip.flag_buf_ptr = TTY_FRAME; + if (uerstat & S3C2410_UERSTAT_BREAK) + flag = TTY_BREAK; + else if (uerstat & S3C2410_UERSTAT_PARITY) + flag = TTY_PARITY; + else if (uerstat & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN)) + flag = TTY_FRAME; } - if ((rxs & port->ignore_status_mask) == 0) { - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; + + if ((uerstat & port->ignore_status_mask) == 0) { + tty_insert_flip_char(tty, ch, flag); } - if ((rxs & S3C2410_UERSTAT_OVERRUN) && + if ((uerstat & S3C2410_UERSTAT_OVERRUN) && tty->flip.count < TTY_FLIPBUF_SIZE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character. */ - *tty->flip.char_buf_ptr++ = 0; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - tty->flip.count++; + + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } + + ignore_char: + continue; } tty_flip_buffer_push(tty); @@ -177,10 +401,10 @@ serial_s3c2410_rx_chars(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -static irqreturn_t -serial_s3c2410_tx_chars(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *regs) { - struct uart_port *port = (struct uart_port *)dev_id; + struct s3c24xx_uart_port *ourport = id; + struct uart_port *port = &ourport->port; struct circ_buf *xmit = &port->info->xmit; int count = 256; @@ -196,14 +420,14 @@ serial_s3c2410_tx_chars(int irq, void *dev_id, struct pt_regs *regs) */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - serial_s3c2410_stop_tx(port, 0); + s3c24xx_serial_stop_tx(port, 0); goto out; } /* try and drain the buffer... */ while (!uart_circ_empty(xmit) && count-- > 0) { - if (rd_regl(port, S3C2410_UFSTAT) & S3C2410_UFSTAT_TXFULL) + if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) break; wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); @@ -215,22 +439,31 @@ serial_s3c2410_tx_chars(int irq, void *dev_id, struct pt_regs *regs) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - serial_s3c2410_stop_tx(port, 0); + s3c24xx_serial_stop_tx(port, 0); out: return IRQ_HANDLED; } -static unsigned int -serial_s3c2410_tx_empty(struct uart_port *port) +static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) { - unsigned int ufcon = rd_regl(port, S3C2410_UFCON); - return (S3C2410_UFCON_TXC(ufcon) != 0) ? 0 : TIOCSER_TEMT; + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); + unsigned long ufcon = rd_regl(port, S3C2410_UFCON); + + if (ufcon & S3C2410_UFCON_FIFOMODE) { + if ((ufstat & info->tx_fifomask) != 0 || + (ufstat & info->tx_fifofull)) + return 0; + + return 1; + } + + return s3c24xx_serial_txempty_nofifo(port); } /* no modem control lines */ -static unsigned int -serial_s3c2410_get_mctrl(struct uart_port *port) +static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) { unsigned int umstat = rd_regb(port,S3C2410_UMSTAT); @@ -240,13 +473,12 @@ serial_s3c2410_get_mctrl(struct uart_port *port) return TIOCM_CAR | TIOCM_DSR; } -static void -serial_s3c2410_set_mctrl(struct uart_port *port, unsigned int mctrl) +static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) { /* todo - possibly remove AFC and do manual CTS */ } -static void serial_s3c2410_break_ctl(struct uart_port *port, int break_state) +static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) { unsigned long flags; unsigned int ucon; @@ -265,46 +497,250 @@ static void serial_s3c2410_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&port->lock, flags); } -static int serial_s3c2410_startup(struct uart_port *port) +static void s3c24xx_serial_shutdown(struct uart_port *port) +{ + struct s3c24xx_uart_port *ourport = to_ourport(port); + + if (ourport->tx_claimed) { + free_irq(TX_IRQ(port), ourport); + tx_enabled(port) = 0; + ourport->tx_claimed = 0; + } + + if (ourport->rx_claimed) { + free_irq(RX_IRQ(port), ourport); + ourport->rx_claimed = 0; + rx_enabled(port) = 0; + } +} + + +static int s3c24xx_serial_startup(struct uart_port *port) { + struct s3c24xx_uart_port *ourport = to_ourport(port); + unsigned long flags; int ret; - tx_enabled(port) = 1; - rx_enabled(port) = 1; + dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n", + port->mapbase, port->membase); + + local_irq_save(flags); - dbg("serial_s3c2410_startup: port=%p (%p)\n", - port, port->mapbase); + rx_enabled(port) = 1; - ret = request_irq(RX_IRQ(port), serial_s3c2410_rx_chars, 0, - serial_s3c2410_name, port); + ret = request_irq(RX_IRQ(port), + s3c24xx_serial_rx_chars, 0, + s3c24xx_serial_portname(port), ourport); - if (ret != 0) + if (ret != 0) { + printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port)); return ret; + } + + ourport->rx_claimed = 1; + + dbg("requesting tx irq...\n"); - ret = request_irq(TX_IRQ(port), serial_s3c2410_tx_chars, 0, - serial_s3c2410_name, port); + tx_enabled(port) = 1; + + ret = request_irq(TX_IRQ(port), + s3c24xx_serial_tx_chars, 0, + s3c24xx_serial_portname(port), ourport); if (ret) { - free_irq(RX_IRQ(port), port); - return ret; + printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port)); + goto err; } + ourport->tx_claimed = 1; + + dbg("s3c24xx_serial_startup ok\n"); + /* the port reset code should have done the correct * register setup for the port controls */ + local_irq_restore(flags); + return ret; + + err: + s3c24xx_serial_shutdown(port); + local_irq_restore(flags); return ret; } -static void serial_s3c2410_shutdown(struct uart_port *port) +/* power power management control */ + +static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, + unsigned int old) { - free_irq(TX_IRQ(port), port); - free_irq(RX_IRQ(port), port); + struct s3c24xx_uart_port *ourport = to_ourport(port); + + switch (level) { + case 3: + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) + clk_disable(ourport->baudclk); + + clk_disable(ourport->clk); + break; + + case 0: + clk_enable(ourport->clk); + + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) + clk_enable(ourport->baudclk); + + break; + default: + printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level); + } } -static void -serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +/* baud rate calculation + * + * The UARTs on the S3C2410/S3C2440 can take their clocks from a number + * of different sources, including the peripheral clock ("pclk") and an + * external clock ("uclk"). The S3C2440 also adds the core clock ("fclk") + * with a programmable extra divisor. + * + * The following code goes through the clock sources, and calculates the + * baud clocks (and the resultant actual baud rates) and then tries to + * pick the closest one and select that. + * + * NOTES: + * 1) there is no current code to properly select/deselect FCLK on + * the s3c2440, so only specify FCLK or non-FCLK in the clock + * sources for the UART + * +*/ + + +#define MAX_CLKS (8) + +static struct s3c24xx_uart_clksrc tmp_clksrc = { + .name = "pclk", + .min_baud = 0, + .max_baud = 0, + .divisor = 1, +}; + +static inline int +s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + return (info->get_clksrc)(port, c); +} + +static inline int +s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) +{ + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + + return (info->set_clksrc)(port, c); +} + +struct baud_calc { + struct s3c24xx_uart_clksrc *clksrc; + unsigned int calc; + unsigned int quot; + struct clk *src; +}; + +static int s3c24xx_serial_calcbaud(struct baud_calc *calc, + struct uart_port *port, + struct s3c24xx_uart_clksrc *clksrc, + unsigned int baud) +{ + unsigned long rate; + + calc->src = clk_get(port->dev, clksrc->name); + if (calc->src == NULL || IS_ERR(calc->src)) + return 0; + + rate = clk_get_rate(calc->src); + + calc->clksrc = clksrc; + calc->quot = (rate + (8 * baud)) / (16 * baud); + calc->calc = (rate / (calc->quot * 16)); + + calc->quot--; + return 1; +} + +static unsigned int s3c24xx_serial_getclk(struct uart_port *port, + struct s3c24xx_uart_clksrc **clksrc, + struct clk **clk, + unsigned int baud) +{ + struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); + struct s3c24xx_uart_clksrc *clkp; + struct baud_calc res[MAX_CLKS]; + struct baud_calc *resptr, *best, *sptr; + int i; + + clkp = cfg->clocks; + best = NULL; + + if (cfg->clocks_size < 2) { + if (cfg->clocks_size == 0) + clkp = &tmp_clksrc; + + s3c24xx_serial_calcbaud(res, port, clkp, baud); + best = res; + resptr = best + 1; + } else { + resptr = res; + + for (i = 0; i < cfg->clocks_size; i++, clkp++) { + if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud)) + resptr++; + } + } + + /* ok, we now need to select the best clock we found */ + + if (!best) { + unsigned int deviation = (1<<30)|((1<<30)-1); + int calc_deviation; + + for (sptr = res; sptr < resptr; sptr++) { + printk(KERN_DEBUG + "found clk %p (%s) quot %d, calc %d\n", + sptr->clksrc, sptr->clksrc->name, + sptr->quot, sptr->calc); + + calc_deviation = baud - sptr->calc; + if (calc_deviation < 0) + calc_deviation = -calc_deviation; + + if (calc_deviation < deviation) { + best = sptr; + deviation = calc_deviation; + } + } + + printk(KERN_DEBUG "best %p (deviation %d)\n", best, deviation); + } + + printk(KERN_DEBUG "selected clock %p (%s) quot %d, calc %d\n", + best->clksrc, best->clksrc->name, best->quot, best->calc); + + /* store results to pass back */ + + *clksrc = best->clksrc; + *clk = best->src; + + return best->quot; +} + +static void s3c24xx_serial_set_termios(struct uart_port *port, + struct termios *termios, + struct termios *old) { + struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); + struct s3c24xx_uart_port *ourport = to_ourport(port); + struct s3c24xx_uart_clksrc *clksrc; + struct clk *clk; unsigned long flags; unsigned int baud, quot; unsigned int ulcon; @@ -315,16 +751,34 @@ serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios, termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR); termios->c_cflag |= CLOCAL; - /* - * We don't support BREAK character recognition. - */ - termios->c_iflag &= ~(IGNBRK | BRKINT); - /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); + + baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); + + if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) + quot = port->custom_divisor; + else + quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); + + /* check to see if we need to change clock source */ + + if (ourport->clksrc != clksrc || ourport->baudclk != clk) { + s3c24xx_serial_setsource(port, clksrc); + + if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { + clk_disable(ourport->baudclk); + clk_unuse(ourport->baudclk); + ourport->baudclk = NULL; + } + + clk_use(clk); + clk_enable(clk); + + ourport->clksrc = clksrc; + ourport->baudclk = clk; + } switch (termios->c_cflag & CSIZE) { case CS5: @@ -346,6 +800,9 @@ serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios, break; } + /* preserve original lcon IR settings */ + ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); + if (termios->c_cflag & CSTOPB) ulcon |= S3C2410_LCON_STOPB; @@ -358,18 +815,12 @@ serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios, ulcon |= S3C2410_LCON_PNONE; } - /* - if (port->fifosize) - enable_fifo() - */ - spin_lock_irqsave(&port->lock, flags); - dbg("setting ulcon to %08x\n", ulcon); - //dbg("\n"); + dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); - /* set the ulcon register */ wr_regl(port, S3C2410_ULCON, ulcon); + wr_regl(port, S3C2410_UBRDIV, quot); dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", rd_regl(port, S3C2410_ULCON), @@ -406,113 +857,151 @@ serial_s3c2410_set_termios(struct uart_port *port, struct termios *termios, spin_unlock_irqrestore(&port->lock, flags); } -static const char *serial_s3c2410_type(struct uart_port *port) +static const char *s3c24xx_serial_type(struct uart_port *port) { - return port->type == PORT_S3C2410 ? "S3C2410" : NULL; + switch (port->type) { + case PORT_S3C2410: + return "S3C2410"; + case PORT_S3C2440: + return "S3C2440"; + default: + return NULL; + } } #define MAP_SIZE (0x100) -static void -serial_s3c2410_release_port(struct uart_port *port) +static void s3c24xx_serial_release_port(struct uart_port *port) { release_mem_region(port->mapbase, MAP_SIZE); } -static int -serial_s3c2410_request_port(struct uart_port *port) +static int s3c24xx_serial_request_port(struct uart_port *port) { - return request_mem_region(port->mapbase, MAP_SIZE, serial_s3c2410_name) - != NULL ? 0 : -EBUSY; + char *name = s3c24xx_serial_portname(port); + return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; } -static void -serial_s3c2410_config_port(struct uart_port *port, int flags) +static void s3c24xx_serial_config_port(struct uart_port *port, int flags) { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + if (flags & UART_CONFIG_TYPE && - serial_s3c2410_request_port(port) == 0) - port->type = PORT_S3C2410; + s3c24xx_serial_request_port(port) == 0) + port->type = info->type; } /* * verify the new serial_struct (for TIOCSSERIAL). */ static int -serial_s3c2410_verify_port(struct uart_port *port, struct serial_struct *ser) +s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) { - int ret = 0; + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); - if (ser->type != PORT_UNKNOWN && ser->type != PORT_S3C2410) - ret = -EINVAL; + if (ser->type != PORT_UNKNOWN && ser->type != info->type) + return -EINVAL; - return ret; + return 0; } -static struct uart_ops serial_s3c2410_ops = { - .tx_empty = serial_s3c2410_tx_empty, - .get_mctrl = serial_s3c2410_get_mctrl, - .set_mctrl = serial_s3c2410_set_mctrl, - .stop_tx = serial_s3c2410_stop_tx, - .start_tx = serial_s3c2410_start_tx, - .stop_rx = serial_s3c2410_stop_rx, - .enable_ms = serial_s3c2410_enable_ms, - .break_ctl = serial_s3c2410_break_ctl, - .startup = serial_s3c2410_startup, - .shutdown = serial_s3c2410_shutdown, - .set_termios = serial_s3c2410_set_termios, - .type = serial_s3c2410_type, - .release_port = serial_s3c2410_release_port, - .request_port = serial_s3c2410_request_port, - .config_port = serial_s3c2410_config_port, - .verify_port = serial_s3c2410_verify_port, + +#ifdef CONFIG_SERIAL_S3C2410_CONSOLE + +static struct console s3c24xx_serial_console; + +#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console +#else +#define S3C24XX_SERIAL_CONSOLE NULL +#endif + +static struct uart_ops s3c24xx_serial_ops = { + .pm = s3c24xx_serial_pm, + .tx_empty = s3c24xx_serial_tx_empty, + .get_mctrl = s3c24xx_serial_get_mctrl, + .set_mctrl = s3c24xx_serial_set_mctrl, + .stop_tx = s3c24xx_serial_stop_tx, + .start_tx = s3c24xx_serial_start_tx, + .stop_rx = s3c24xx_serial_stop_rx, + .enable_ms = s3c24xx_serial_enable_ms, + .break_ctl = s3c24xx_serial_break_ctl, + .startup = s3c24xx_serial_startup, + .shutdown = s3c24xx_serial_shutdown, + .set_termios = s3c24xx_serial_set_termios, + .type = s3c24xx_serial_type, + .release_port = s3c24xx_serial_release_port, + .request_port = s3c24xx_serial_request_port, + .config_port = s3c24xx_serial_config_port, + .verify_port = s3c24xx_serial_verify_port, +}; + + +static struct uart_driver s3c24xx_uart_drv = { + .owner = THIS_MODULE, + .dev_name = "s3c2410_serial", + .nr = 3, + .cons = S3C24XX_SERIAL_CONSOLE, + .driver_name = S3C24XX_SERIAL_NAME, + .devfs_name = S3C24XX_SERIAL_DEVFS, + .major = S3C24XX_SERIAL_MAJOR, + .minor = S3C24XX_SERIAL_MINOR, }; -static struct uart_port serial_s3c2410_ports[NR_PORTS] = { - { - .membase = 0, - .mapbase = 0, - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX0, - .uartclk = 0, - .fifosize = 16, - .ops = &serial_s3c2410_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, +static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = { + [0] = { + .port = { + .lock = SPIN_LOCK_UNLOCKED, + .membase = 0, + .mapbase = 0, + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX0, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 0, + } + }, + [1] = { + .port = { + .lock = SPIN_LOCK_UNLOCKED, + .membase = 0, + .mapbase = 0, + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX1, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 1, + } }, - { - .membase = 0, - .mapbase = 0, - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX1, - .uartclk = 0, - .fifosize = 16, - .ops = &serial_s3c2410_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - } #if NR_PORTS > 2 - , - { - .membase = 0, - .mapbase = 0, - .iotype = UPIO_MEM, - .irq = IRQ_S3CUART_RX2, - .uartclk = 0, - .fifosize = 16, - .ops = &serial_s3c2410_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 2, + + [2] = { + .port = { + .lock = SPIN_LOCK_UNLOCKED, + .membase = 0, + .mapbase = 0, + .iotype = UPIO_MEM, + .irq = IRQ_S3CUART_RX2, + .uartclk = 0, + .fifosize = 16, + .ops = &s3c24xx_serial_ops, + .flags = UPF_BOOT_AUTOCONF, + .line = 2, + } } #endif }; -static int -serial_s3c2410_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) + +static int s3c24xx_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) { /* ensure registers are setup */ - dbg("serial_s3c2410_resetport: port=%p (%08x), cfg=%p\n", + dbg("s3c24xx_serial_resetport: port=%p (%08lx), cfg=%p\n", port, port->mapbase, cfg); wr_regl(port, S3C2410_UCON, cfg->ucon); @@ -526,105 +1015,431 @@ serial_s3c2410_resetport(struct uart_port *port, return 0; } -/* serial_s3c2410_init_ports +/* s3c24xx_serial_init_port * - * initialise the serial ports from the machine provided initialisation - * data. -*/ + * initialise a single serial port from the platform device given + */ -static int serial_s3c2410_init_ports(void) +static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, + struct s3c24xx_uart_info *info, + struct platform_device *platdev) { - struct uart_port *ptr = serial_s3c2410_ports; - struct s3c2410_uartcfg *cfg = s3c2410_uartcfgs; - static int inited = 0; - int i; + struct uart_port *port = &ourport->port; + struct s3c2410_uartcfg *cfg; + struct resource *res; + + dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev); + + if (platdev == NULL) + return -ENODEV; + + cfg = s3c24xx_dev_to_cfg(&platdev->dev); - if (inited) + if (port->mapbase != 0) return 0; - inited = 1; - dbg("serial_s3c2410_init_ports: initialising ports...\n"); + if (cfg->hwport > 3) + return -EINVAL; - for (i = 0; i < NR_PORTS; i++, ptr++, cfg++) { + /* setup info for port */ + port->dev = &platdev->dev; + ourport->info = info; - if (cfg->hwport > 3) - continue; + /* copy the info in from provided structure */ + ourport->port.fifosize = info->fifosize; - dbg("serial_s3c2410_init_ports: port %d (hw %d)...\n", - i, cfg->hwport); + dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport); - if (cfg->clock != NULL) - ptr->uartclk = *cfg->clock; + port->uartclk = 1; - switch (cfg->hwport) { - case 0: - ptr->mapbase = S3C2410_PA_UART0; - ptr->membase = (char *)S3C2410_VA_UART0; - ptr->irq = IRQ_S3CUART_RX0; - break; + if (cfg->uart_flags & UPF_CONS_FLOW) { + dbg("s3c24xx_serial_init_port: enabling flow control\n"); + port->flags |= UPF_CONS_FLOW; + } - case 1: - ptr->mapbase = S3C2410_PA_UART1; - ptr->membase = (char *)S3C2410_VA_UART1; - ptr->irq = IRQ_S3CUART_RX1; - break; + /* sort our the physical and virtual addresses for each UART */ - case 2: - ptr->mapbase = S3C2410_PA_UART2; - ptr->membase = (char *)S3C2410_VA_UART2; - ptr->irq = IRQ_S3CUART_RX2; - break; - } + res = platform_get_resource(platdev, IORESOURCE_MEM, 0); + if (res == NULL) { + printk(KERN_ERR "failed to find memory resource for uart\n"); + return -EINVAL; + } + + dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); + + port->mapbase = res->start; + port->membase = (void __iomem *)(res->start - S3C2410_PA_UART); + port->membase += S3C2410_VA_UART; + port->irq = platform_get_irq(platdev, 0); + + ourport->clk = clk_get(&platdev->dev, "uart"); + + if (ourport->clk != NULL && !IS_ERR(ourport->clk)) + clk_use(ourport->clk); + + dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n", + port->mapbase, port->membase, port->irq, port->uartclk); + + /* reset the fifos (and setup the uart) */ + s3c24xx_serial_resetport(port, cfg); + return 0; +} + +/* Device driver serial port probe */ + +static int probe_index = 0; + +int s3c24xx_serial_probe(struct device *_dev, + struct s3c24xx_uart_info *info) +{ + struct s3c24xx_uart_port *ourport; + struct platform_device *dev = to_platform_device(_dev); + int ret; + + dbg("s3c24xx_serial_probe(%p, %p) %d\n", _dev, info, probe_index); + + ourport = &s3c24xx_serial_ports[probe_index]; + probe_index++; + + dbg("%s: initialising port %p...\n", __FUNCTION__, ourport); + + ret = s3c24xx_serial_init_port(ourport, info, dev); + if (ret < 0) + goto probe_err; + + dbg("%s: adding port\n", __FUNCTION__); + uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); + dev_set_drvdata(_dev, &ourport->port); + + return 0; + + probe_err: + return ret; +} + +int s3c24xx_serial_remove(struct device *_dev) +{ + struct uart_port *port = s3c24xx_dev_to_port(_dev); + + if (port) + uart_remove_one_port(&s3c24xx_uart_drv, port); + + return 0; +} + +/* UART power management code */ + +#ifdef CONFIG_PM + +int s3c24xx_serial_suspend(struct device *dev, u32 state, u32 level) +{ + struct uart_port *port = s3c24xx_dev_to_port(dev); + + if (port && level == SUSPEND_DISABLE) + uart_suspend_port(&s3c24xx_uart_drv, port); + + return 0; +} + +int s3c24xx_serial_resume(struct device *dev, u32 level) +{ + struct uart_port *port = s3c24xx_dev_to_port(dev); + struct s3c24xx_uart_port *ourport = to_ourport(port); + + if (port && level == RESUME_ENABLE) { + clk_enable(ourport->clk); + s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); + clk_disable(ourport->clk); + + uart_resume_port(&s3c24xx_uart_drv, port); + } + + return 0; +} + +#else +#define s3c24xx_serial_suspend NULL +#define s3c24xx_serial_resume NULL +#endif + +int s3c24xx_serial_init(struct device_driver *drv, + struct s3c24xx_uart_info *info) +{ + dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); + return driver_register(drv); +} + + +/* now comes the code to initialise either the s3c2410 or s3c2440 serial + * port information +*/ + +/* cpu specific variations on the serial port support */ + +#ifdef CONFIG_CPU_S3C2410 + +static int s3c2410_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2410_UCON_UCLK; + else + ucon &= ~S3C2410_UCON_UCLK; + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + +static int s3c2410_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + clk->divisor = 1; + clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk"; + + return 0; +} + +static struct s3c24xx_uart_info s3c2410_uart_inf = { + .name = "Samsung S3C2410 UART", + .type = PORT_S3C2410, + .fifosize = 16, + .rx_fifomask = S3C2410_UFSTAT_RXMASK, + .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2410_UFSTAT_RXFULL, + .tx_fifofull = S3C2410_UFSTAT_TXFULL, + .tx_fifomask = S3C2410_UFSTAT_TXMASK, + .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, + .get_clksrc = s3c2410_serial_getsource, + .set_clksrc = s3c2410_serial_setsource, +}; + +/* device management */ + +static int s3c2410_serial_probe(struct device *dev) +{ + return s3c24xx_serial_probe(dev, &s3c2410_uart_inf); +} + +static struct device_driver s3c2410_serial_drv = { + .name = "s3c2410-uart", + .bus = &platform_bus_type, + .probe = s3c2410_serial_probe, + .remove = s3c24xx_serial_remove, + .suspend = s3c24xx_serial_suspend, + .resume = s3c24xx_serial_resume, +}; + +static inline int s3c2410_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2410_serial_drv, &s3c2410_uart_inf); +} + +static inline void s3c2410_serial_exit(void) +{ + driver_unregister(&s3c2410_serial_drv); +} + +#define s3c2410_uart_inf_at &s3c2410_uart_inf +#else + +static inline int s3c2410_serial_init(void) +{ + return 0; +} + +static inline void s3c2410_serial_exit(void) +{ +} + +#define s3c2410_uart_inf_at NULL + +#endif /* CONFIG_CPU_S3C2410 */ + +#ifdef CONFIG_CPU_S3C2440 + +static int s3c2440_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + // todo - proper fclk<>nonfclk switch // + + ucon &= ~S3C2440_UCON_CLKMASK; + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2440_UCON_UCLK; + else if (strcmp(clk->name, "pclk") == 0) + ucon |= S3C2440_UCON_PCLK; + else if (strcmp(clk->name, "fclk") == 0) + ucon |= S3C2440_UCON_FCLK; + else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c2440_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + switch (ucon & S3C2440_UCON_CLKMASK) { + case S3C2440_UCON_UCLK: + clk->divisor = 1; + clk->name = "uclk"; + break; + + case S3C2440_UCON_PCLK: + case S3C2440_UCON_PCLK2: + clk->divisor = 1; + clk->name = "pclk"; + break; + + case S3C2440_UCON_FCLK: + clk->divisor = 7; /* todo - work out divisor */ + clk->name = "fclk"; + break; + } + + return 0; +} + + +static struct s3c24xx_uart_info s3c2440_uart_inf = { + .name = "Samsung S3C2440 UART", + .type = PORT_S3C2440, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c2440_serial_getsource, + .set_clksrc = s3c2440_serial_setsource +}; + +/* device management */ + +static int s3c2440_serial_probe(struct device *dev) +{ + dbg("s3c2440_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); +} + +static struct device_driver s3c2440_serial_drv = { + .name = "s3c2440-uart", + .bus = &platform_bus_type, + .probe = s3c2440_serial_probe, + .remove = s3c24xx_serial_remove, + .suspend = s3c24xx_serial_suspend, + .resume = s3c24xx_serial_resume, +}; + + +static inline int s3c2440_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf); +} + +static inline void s3c2440_serial_exit(void) +{ + driver_unregister(&s3c2440_serial_drv); +} + +#define s3c2440_uart_inf_at &s3c2440_uart_inf +#else + +static inline int s3c2440_serial_init(void) +{ + return 0; +} + +static inline void s3c2440_serial_exit(void) +{ +} - if (ptr->mapbase == 0) - continue; +#define s3c2440_uart_inf_at NULL +#endif /* CONFIG_CPU_S3C2440 */ - /* reset the fifos (and setup the uart */ - serial_s3c2410_resetport(ptr, cfg); +/* module initialisation code */ + +static int __init s3c24xx_serial_modinit(void) +{ + int ret; + + ret = uart_register_driver(&s3c24xx_uart_drv); + if (ret < 0) { + printk(KERN_ERR "failed to register UART driver\n"); + return -1; } + s3c2410_serial_init(); + s3c2440_serial_init(); + return 0; } +static void __exit s3c24xx_serial_modexit(void) +{ + s3c2410_serial_exit(); + s3c2440_serial_exit(); + + uart_unregister_driver(&s3c24xx_uart_drv); +} + + +module_init(s3c24xx_serial_modinit); +module_exit(s3c24xx_serial_modexit); + +/* Console code */ + #ifdef CONFIG_SERIAL_S3C2410_CONSOLE static struct uart_port *cons_uart; static int -serial_s3c2410_console_txrdy(struct uart_port *port, unsigned int ufcon) +s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned long ufstat, utrstat; if (ufcon & S3C2410_UFCON_FIFOMODE) { /* fifo mode - check ammount of data in fifo registers... */ ufstat = rd_regl(port, S3C2410_UFSTAT); - - return S3C2410_UFCON_TXC(ufstat) < 12; + return (ufstat & info->tx_fifofull) ? 0 : 1; } /* in non-fifo mode, we go and use the tx buffer empty */ utrstat = rd_regl(port, S3C2410_UTRSTAT); - - return (utrstat & S3C2410_UTRSTAT_TXFE) ? 1 : 0; + return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; } static void -serial_s3c2410_console_write(struct console *co, const char *s, +s3c24xx_serial_console_write(struct console *co, const char *s, unsigned int count) { int i; unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); for (i = 0; i < count; i++) { - while (!serial_s3c2410_console_txrdy(cons_uart, ufcon)) + while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) barrier(); wr_regb(cons_uart, S3C2410_UTXH, s[i]); if (s[i] == '\n') { - while (!serial_s3c2410_console_txrdy(cons_uart, ufcon)) + while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) barrier(); wr_regb(cons_uart, S3C2410_UTXH, '\r'); @@ -633,17 +1448,21 @@ serial_s3c2410_console_write(struct console *co, const char *s, } static void __init -serial_s3c2410_get_options(struct uart_port *port, int *baud, +s3c24xx_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { - - unsigned int ulcon, ucon, ubrdiv; + struct s3c24xx_uart_clksrc clksrc; + struct clk *clk; + unsigned int ulcon; + unsigned int ucon; + unsigned int ubrdiv; + unsigned long rate; ulcon = rd_regl(port, S3C2410_ULCON); ucon = rd_regl(port, S3C2410_UCON); ubrdiv = rd_regl(port, S3C2410_UBRDIV); - dbg("serial_s3c2410_get_options: port=%p\n" + dbg("s3c24xx_serial_get_options: port=%p\n" "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", port, ulcon, ucon, ubrdiv); @@ -675,21 +1494,53 @@ serial_s3c2410_get_options(struct uart_port *port, int *baud, *parity = 'o'; break; - default: case S3C2410_LCON_PNONE: - /* nothing */ + default: + *parity = 'n'; } /* now calculate the baud rate */ - *baud = port->uartclk / ( 16 * (ubrdiv + 1)); + s3c24xx_serial_getsource(port, &clksrc); + + clk = clk_get(port->dev, clksrc.name); + if (!IS_ERR(clk) && clk != NULL) + rate = clk_get_rate(clk); + else + rate = 1; + + + *baud = rate / ( 16 * (ubrdiv + 1)); dbg("calculated baud %d\n", *baud); } } +/* s3c24xx_serial_init_ports + * + * initialise the serial ports from the machine provided initialisation + * data. +*/ + +static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) +{ + struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; + struct platform_device **platdev_ptr; + int i; + + dbg("s3c24xx_serial_init_ports: initialising ports...\n"); + + platdev_ptr = s3c24xx_uart_devs; + + for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) { + s3c24xx_serial_init_port(ptr, info, *platdev_ptr); + } + + return 0; +} + static int __init -serial_s3c2410_console_setup(struct console *co, char *options) +s3c24xx_serial_console_setup(struct console *co, char *options) { struct uart_port *port; int baud = 9600; @@ -697,23 +1548,26 @@ serial_s3c2410_console_setup(struct console *co, char *options) int parity = 'n'; int flow = 'n'; + dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", + co, co->index, options); + /* is this a valid port */ if (co->index == -1 || co->index >= NR_PORTS) co->index = 0; - port = &serial_s3c2410_ports[co->index]; + port = &s3c24xx_serial_ports[co->index].port; /* is the port configured? */ if (port->mapbase == 0x0) { co->index = 0; - port = &serial_s3c2410_ports[co->index]; + port = &s3c24xx_serial_ports[co->index].port; } cons_uart = port; - dbg("serial_s3c2410_console_setup: port=%p (%d)\n", port, co->index); + dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); /* * Check whether an invalid uart number has been specified, and @@ -723,138 +1577,68 @@ serial_s3c2410_console_setup(struct console *co, char *options) if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else - serial_s3c2410_get_options(port, &baud, &parity, &bits); + s3c24xx_serial_get_options(port, &baud, &parity, &bits); + + dbg("s3c24xx_serial_console_setup: baud %d\n", baud); return uart_set_options(port, co, baud, parity, bits, flow); } -static struct uart_driver s3c2410_uart_drv; +/* s3c24xx_serial_initconsole + * + * initialise the console from one of the uart drivers +*/ -static struct console serial_s3c2410_console = +static struct console s3c24xx_serial_console = { - .name = SERIAL_S3C2410_NAME, - .write = serial_s3c2410_console_write, + .name = S3C24XX_SERIAL_NAME, .device = uart_console_device, - .setup = serial_s3c2410_console_setup, .flags = CON_PRINTBUFFER, .index = -1, - .data = &s3c2410_uart_drv, + .write = s3c24xx_serial_console_write, + .setup = s3c24xx_serial_console_setup }; -static int __init s3c2410_console_init(void) -{ - dbg("s3c2410_console_init:\n"); - - serial_s3c2410_init_ports(); - register_console(&serial_s3c2410_console); - return 0; -} -console_initcall(s3c2410_console_init); - -#define SERIAL_S3C2410_CONSOLE &serial_s3c2410_console -#else -#define SERIAL_S3C2410_CONSOLE NULL -#endif -static struct uart_driver s3c2410_uart_drv = { - .owner = THIS_MODULE, - .driver_name = SERIAL_S3C2410_NAME, - .dev_name = SERIAL_S3C2410_NAME, - .major = SERIAL_S3C2410_MAJOR, - .minor = SERIAL_S3C2410_MINOR, - .nr = 3, - .cons = SERIAL_S3C2410_CONSOLE, -}; - -/* device driver */ - -static int s3c2410_serial_probe(struct device *_dev); -static int s3c2410_serial_remove(struct device *_dev); - -static struct device_driver s3c2410_serial_drv = { - .name = "s3c2410-uart", - .bus = &platform_bus_type, - .probe = s3c2410_serial_probe, - .remove = s3c2410_serial_remove, - .suspend = NULL, - .resume = NULL, -}; - -#define s3c2410_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) - -static int s3c2410_serial_probe(struct device *_dev) +static int s3c24xx_serial_initconsole(void) { - struct platform_device *dev = to_platform_device(_dev); - struct resource *res = dev->resource; - int i; - - dbg("s3c2410_serial_probe: dev=%p, _dev=%p, res=%p\n", _dev, dev, res); - - for (i = 0; i < dev->num_resources; i++, res++) - if (res->flags & IORESOURCE_MEM) - break; + struct s3c24xx_uart_info *info; + struct platform_device *dev = s3c24xx_uart_devs[0]; - if (i < dev->num_resources) { - struct uart_port *ptr = serial_s3c2410_ports; + dbg("s3c24xx_serial_initconsole\n"); - for (i = 0; i < NR_PORTS; i++, ptr++) { - dbg("s3c2410_serial_probe: ptr=%p (%08x, %08x)\n", - ptr, ptr->mapbase, ptr->membase); + /* select driver based on the cpu */ - if (ptr->mapbase != res->start) - continue; - - dbg("s3c2410_serial_probe: got device %p: port=%p\n", - _dev, ptr); - - uart_add_one_port(&s3c2410_uart_drv, ptr); - dev_set_drvdata(_dev, ptr); - break; - } + if (dev == NULL) { + printk(KERN_ERR "s3c24xx: no devices for console init\n"); + return 0; } - return 0; -} + if (strcmp(dev->name, "s3c2410-uart") == 0) { + info = s3c2410_uart_inf_at; + } else if (strcmp(dev->name, "s3c2440-uart") == 0) { + info = s3c2440_uart_inf_at; + } else { + printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name); + return 0; + } -static int s3c2410_serial_remove(struct device *_dev) -{ - struct uart_port *port = s3c2410_dev_to_port(_dev); + if (info == NULL) { + printk(KERN_ERR "s3c24xx: no driver for console\n"); + return 0; + } - if (port) - uart_remove_one_port(&s3c2410_uart_drv, port); + s3c24xx_serial_console.data = &s3c24xx_uart_drv; + s3c24xx_serial_init_ports(info); + register_console(&s3c24xx_serial_console); return 0; } +console_initcall(s3c24xx_serial_initconsole); - -static int __init serial_s3c2410_init(void) -{ - int ret; - - printk(KERN_INFO "S3C2410X Serial, (c) 2003 Simtec Electronics\n"); - - ret = uart_register_driver(&s3c2410_uart_drv); - if (ret != 0) - return ret; - - ret = driver_register(&s3c2410_serial_drv); - if (ret) { - uart_unregister_driver(&s3c2410_uart_drv); - } - - return ret; -} - -static void __exit serial_s3c2410_exit(void) -{ - driver_unregister(&s3c2410_serial_drv); - uart_unregister_driver(&s3c2410_uart_drv); -} - -module_init(serial_s3c2410_init); -module_exit(serial_s3c2410_exit); +#endif /* CONFIG_SERIAL_S3C2410_CONSOLE */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("Samsung S3C2410X (S3C2410) Serial driver"); +MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver"); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index b60c5b604..91d208755 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -25,26 +25,27 @@ * */ #include + +#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include #include +#include +#include +#include +#include #include #include #include #include -#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_SA1100_MAJOR 204 #define MINOR_START 5 @@ -220,9 +221,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) goto ignore_char; error_return: - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | UTSR0_TO_SM(UART_GET_UTSR0(sport)); @@ -257,11 +256,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) * overrun does *not* affect the character * we read from the FIFO */ - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; + tty_insert_flip_char(tty, ch, flg); ch = 0; flg = TTY_OVERRUN; } diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 24ef1cbf5..5ed45a7cb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -32,6 +32,7 @@ #include #include #include /* for serial_state and serial_icounter_struct */ +#include #include #include @@ -107,15 +108,7 @@ static void uart_start(struct tty_struct *tty) static void uart_tasklet_action(unsigned long data) { struct uart_state *state = (struct uart_state *)data; - struct tty_struct *tty; - - tty = state->info->tty; - if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - tty->ldisc.write_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } + tty_wakeup(state->info->tty); } static inline void @@ -170,8 +163,6 @@ static int uart_startup(struct uart_state *state, int init_hw) return -ENOMEM; info->xmit.buf = (unsigned char *) page; - info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE; - init_MUTEX(&info->tmpbuf_sem); uart_circ_clear(&info->xmit); } @@ -246,7 +237,6 @@ static void uart_shutdown(struct uart_state *state) if (info->xmit.buf) { free_page((unsigned long)info->xmit.buf); info->xmit.buf = NULL; - info->tmpbuf = NULL; } /* @@ -403,7 +393,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; else - quot = port->uartclk / (16 * baud); + quot = (port->uartclk + (8 * baud)) / (16 * baud); return quot; } @@ -458,53 +448,30 @@ __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) spin_unlock_irqrestore(&port->lock, flags); } -static inline int -__uart_user_write(struct uart_port *port, struct circ_buf *circ, - const unsigned char __user *buf, int count) +static void uart_put_char(struct tty_struct *tty, unsigned char ch) { - unsigned long flags; - int c, ret = 0; - - if (down_interruptible(&port->info->tmpbuf_sem)) - return -EINTR; - - while (1) { - int c1; - c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; + struct uart_state *state = tty->driver_data; - c -= copy_from_user(port->info->tmpbuf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&port->lock, flags); - c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(circ->buf + circ->head, port->info->tmpbuf, c); - circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); - spin_unlock_irqrestore(&port->lock, flags); - buf += c; - count -= c; - ret += c; - } - up(&port->info->tmpbuf_sem); + __uart_put_char(state->port, &state->info->xmit, ch); +} - return ret; +static void uart_flush_chars(struct tty_struct *tty) +{ + uart_start(tty); } -static inline int -__uart_kern_write(struct uart_port *port, struct circ_buf *circ, - const unsigned char *buf, int count) +static int +uart_write(struct tty_struct *tty, const unsigned char * buf, int count) { + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + struct circ_buf *circ = &state->info->xmit; unsigned long flags; int c, ret = 0; + if (!circ->buf) + return 0; + spin_lock_irqsave(&port->lock, flags); while (1) { c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); @@ -520,38 +487,6 @@ __uart_kern_write(struct uart_port *port, struct circ_buf *circ, } spin_unlock_irqrestore(&port->lock, flags); - return ret; -} - -static void uart_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct uart_state *state = tty->driver_data; - - __uart_put_char(state->port, &state->info->xmit, ch); -} - -static void uart_flush_chars(struct tty_struct *tty) -{ - uart_start(tty); -} - -static int -uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, - int count) -{ - struct uart_state *state = tty->driver_data; - int ret; - - if (!state->info->xmit.buf) - return 0; - - if (from_user) - ret = __uart_user_write(state->port, &state->info->xmit, - (const unsigned char __user *)buf, count); - else - ret = __uart_kern_write(state->port, &state->info->xmit, - buf, count); - uart_start(tty); return ret; } @@ -581,10 +516,7 @@ static void uart_flush_buffer(struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); uart_circ_clear(&state->info->xmit); spin_unlock_irqrestore(&port->lock, flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -652,8 +584,10 @@ static int uart_get_info(struct uart_state *state, tmp.flags = port->flags; tmp.xmit_fifo_size = port->fifosize; tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; + tmp.close_delay = state->close_delay / 10; + tmp.closing_wait = state->closing_wait == USF_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + state->closing_wait / 10; tmp.custom_divisor = port->custom_divisor; tmp.hub6 = port->hub6; tmp.io_type = port->iotype; @@ -671,8 +605,8 @@ static int uart_set_info(struct uart_state *state, struct serial_struct new_serial; struct uart_port *port = state->port; unsigned long new_port; - unsigned int change_irq, change_port, old_flags; - unsigned int old_custom_divisor; + unsigned int change_irq, change_port, old_flags, closing_wait; + unsigned int old_custom_divisor, close_delay; int retval = 0; if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) @@ -683,6 +617,9 @@ static int uart_set_info(struct uart_state *state, new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; new_serial.irq = irq_canonicalize(new_serial.irq); + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + USF_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; /* * This semaphore protects state->count. It is also @@ -714,8 +651,8 @@ static int uart_set_info(struct uart_state *state, retval = -EPERM; if (change_irq || change_port || (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.closing_wait != state->closing_wait) || + (close_delay != state->close_delay) || + (closing_wait != state->closing_wait) || (new_serial.xmit_fifo_size != port->fifosize) || (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) goto exit; @@ -819,8 +756,8 @@ static int uart_set_info(struct uart_state *state, port->flags = (port->flags & ~UPF_CHANGE_MASK) | (new_serial.flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; + state->close_delay = close_delay; + state->closing_wait = closing_wait; port->fifosize = new_serial.xmit_fifo_size; if (state->info->tty) state->info->tty->low_latency = @@ -1216,7 +1153,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) { struct uart_state *state = tty->driver_data; struct uart_port *port; - + BUG_ON(!kernel_locked()); if (!state || !state->port) @@ -1239,12 +1176,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * one, we've got real problems, since it means the * serial port won't be shutdown. */ - printk("uart_close: bad serial port count; tty->count is 1, " + printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, " "state->count is %d\n", state->count); state->count = 1; } if (--state->count < 0) { - printk("rs_close: bad serial port count for %s: %d\n", + printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n", tty->name, state->count); state->count = 0; } @@ -1259,7 +1196,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->closing = 1; if (state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, state->closing_wait); + tty_wait_until_sent(tty, msecs_to_jiffies(state->closing_wait)); /* * At this point, we stop accepting input. To do this, we @@ -1280,16 +1217,15 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uart_shutdown(state); uart_flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + + tty_ldisc_flush(tty); + tty->closing = 0; state->info->tty = NULL; if (state->info->blocked_open) { - if (state->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(state->close_delay); - } + if (state->close_delay) + msleep_interruptible(state->close_delay); } else if (!uart_console(port)) { uart_change_pm(state, 3); } @@ -1353,8 +1289,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) * we wait. */ while (!port->ops->tx_empty(port)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + msleep_interruptible(jiffies_to_msecs(char_time)); if (signal_pending(current)) break; if (time_after(jiffies, expire)) @@ -1911,10 +1846,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) * Wait for the transmitter to empty. */ while (!ops->tx_empty(port)) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10*HZ/1000); + msleep(10); } - set_current_state(TASK_RUNNING); ops->shutdown(port); } @@ -1978,6 +1911,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6); break; case UPIO_MEM: + case UPIO_MEM32: printk("MMIO 0x%lx", port->mapbase); break; } @@ -2152,8 +2086,8 @@ int uart_register_driver(struct uart_driver *drv) for (i = 0; i < drv->nr; i++) { struct uart_state *state = drv->state + i; - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; + state->close_delay = 500; /* .5 seconds */ + state->closing_wait = 30000; /* 30 seconds */ init_MUTEX(&state->sem); } @@ -2234,6 +2168,15 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) */ tty_register_device(drv->tty_driver, port->line, port->dev); + /* + * If this driver supports console, and it hasn't been + * successfully registered yet, try to re-register it. + * It may be that the port was not available. + */ + if (port->type != PORT_UNKNOWN && + port->cons && !(port->cons->flags & CON_ENABLED)) + register_console(port->cons); + out: up(&port_sem); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index c3e6eb244..6be72e5a2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -40,8 +40,6 @@ #include #include #include -#include -#include #include #include #include @@ -59,7 +57,7 @@ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); +module_param(pc_debug, int, 0644); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; #else @@ -81,7 +79,7 @@ static int do_sound = 1; static int buggy_uart; module_param(irq_mask, uint, 0444); -module_param_array(irq_list, int, irq_list_count, 0444); +module_param_array(irq_list, int, &irq_list_count, 0444); module_param(do_sound, int, 0444); module_param(buggy_uart, int, 0444); @@ -148,7 +146,7 @@ static void serial_remove(dev_link_t *link) */ if (info->link.state & DEV_CONFIG) { for (i = 0; i < info->ndev; i++) - unregister_serial(info->line[i]); + serial8250_unregister_port(info->line[i]); info->link.dev = NULL; @@ -304,21 +302,22 @@ static void serial_detach(dev_link_t * link) /*====================================================================*/ -static int setup_serial(struct serial_info * info, ioaddr_t port, int irq) +static int setup_serial(struct serial_info * info, ioaddr_t iobase, int irq) { - struct serial_struct serial; + struct uart_port port; int line; - memset(&serial, 0, sizeof (serial)); - serial.port = port; - serial.irq = irq; - serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ; + memset(&port, 0, sizeof (struct uart_port)); + port.iobase = iobase; + port.irq = irq; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; + port.uartclk = 1843200; if (buggy_uart) - serial.flags |= UPF_BUGGY_UART; - line = register_serial(&serial); + port.flags |= UPF_BUGGY_UART; + line = serial8250_register_port(&port); if (line < 0) { - printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," - " irq %d failed\n", (u_long) serial.port, serial.irq); + printk(KERN_NOTICE "serial_cs: serial8250_register_port() at " + "0x%04lx, irq %d failed\n", (u_long)iobase, irq); return -EINVAL; } @@ -363,9 +362,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse) /*====================================================================*/ -static int simple_config(dev_link_t * link) +static int simple_config(dev_link_t *link) { static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + static int size_table[2] = { 8, 16 }; client_handle_t handle = link->handle; struct serial_info *info = link->priv; tuple_t tuple; @@ -374,6 +374,7 @@ static int simple_config(dev_link_t * link) cistpl_cftable_entry_t *cf = &parse.cftable_entry; config_info_t config; int i, j, try; + int s; /* If the card is already configured, look up the port and irq */ i = pcmcia_get_configuration_info(handle, &config); @@ -399,29 +400,30 @@ static int simple_config(dev_link_t * link) tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ - for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if (i != CS_SUCCESS) - goto next_entry; - if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; - if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && - (cf->io.win[0].base != 0)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = (try == 0) ? - 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); - if (i == CS_SUCCESS) - goto found_port; + for (s = 0; s < 2; s++) { + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) + goto next_entry; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) && + (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = pcmcia_request_io(link->handle, &link->io); + if (i == CS_SUCCESS) + goto found_port; + } +next_entry: + i = next_tuple(handle, &tuple, &parse); } - next_entry: - i = next_tuple(handle, &tuple, &parse); } } - /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index d863368e4..4ce3a41f1 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -28,25 +28,24 @@ */ #include + +#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include +#include +#include +#include +#include #include #include -#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include - -#include - #define DEV_MAJOR 204 #define DEV_MINOR 16 #define DEV_NR 3 @@ -60,6 +59,15 @@ #define UART_REG_SIZE 32 +#define UART_R_DATA (0x00) +#define UART_R_FCON (0x04) +#define UART_R_BRCON (0x08) +#define UART_R_CON (0x0c) +#define UART_R_STATUS (0x10) +#define UART_R_RAWISR (0x14) +#define UART_R_INTEN (0x18) +#define UART_R_ISR (0x1c) + #define UARTEN (0x01) /* UART enable */ #define SIRDIS (0x02) /* Serial IR disable (UART1 only) */ @@ -138,21 +146,20 @@ lh7a40xuart_rx_chars (struct uart_port* port) { struct tty_struct* tty = port->info->tty; int cbRxMax = 256; /* (Gross) limit on receive */ - unsigned int data; /* Received data and status */ + unsigned int data, flag;/* Received data and status */ while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.work.func((void*)tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - return; - } + if (tty->low_latency) + tty_flip_buffer_push(tty); + /* + * If this failed then we will throw away the + * bytes but must do so to clear interrupts + */ } data = UR (port, UART_R_DATA); - - *tty->flip.char_buf_ptr = (unsigned char) data; - *tty->flip.flag_buf_ptr = TTY_NORMAL; + flag = TTY_NORMAL; ++port->icount.rx; if (data & RxError) { /* Quick check, short-circuit */ @@ -173,20 +180,18 @@ lh7a40xuart_rx_chars (struct uart_port* port) data &= port->read_status_mask | 0xff; if (data & RxBreak) - *tty->flip.flag_buf_ptr = TTY_BREAK; + flag = TTY_BREAK; else if (data & RxParityError) - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; else if (data & RxFramingError) - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) continue; if ((data & port->ignore_status_mask) == 0) { - ++tty->flip.flag_buf_ptr; - ++tty->flip.char_buf_ptr; - ++tty->flip.count; + tty_insert_flip_char(tty, data, flag); } if ((data & RxOverrunError) && tty->flip.count < TTY_FLIPBUF_SIZE) { @@ -195,9 +200,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) * immediately, and doesn't affect the current * character */ - *tty->flip.char_buf_ptr++ = 0; - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - ++tty->flip.count; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } } tty_flip_buffer_push (tty); diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index a6639f467..ad5b776d7 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -3,7 +3,7 @@ * * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) * - * Copyright (C) 2002, 2003 Paul Mundt + * Copyright (C) 2002, 2003, 2004 Paul Mundt * * based off of the old drivers/char/sh-sci.c by: * @@ -18,7 +18,8 @@ * for more details. */ -#define DEBUG +#undef DEBUG + #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_CPU_FREQ #include @@ -50,7 +52,6 @@ #include #include #include -#include #include @@ -332,7 +333,7 @@ static void sci_init_pins_sci(struct uart_port *port, unsigned int cflag) #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) #if defined(CONFIG_CPU_SH3) -/* For SH7707, SH7709, SH7709A, SH7729, SH7300*/ +/* For SH7705, SH7707, SH7709, SH7709A, SH7729, SH7300*/ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) { unsigned int fcr_val = 0; @@ -798,7 +799,7 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void * if ((phase == CPUFREQ_POSTCHANGE) || (phase == CPUFREQ_RESUMECHANGE)){ for (i = 0; i < SCI_NPORTS; i++) { - struct uart_port *port = &sci_ports[i]; + struct uart_port *port = &sci_ports[i].port; /* * Update the uartclk per-port if frequency has @@ -1139,6 +1140,35 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .irqs = SCI_IRQS, .init_pins = sci_init_pins_sci, }, +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) + { + .port = { + .membase = (void *)SCIF0, + .mapbase = SCIF0, + .iotype = SERIAL_IO_MEM, + .irq = 55, + .ops = &sci_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .type = PORT_SCIF, + .irqs = SH3_IRDA_IRQS, + .init_pins = sci_init_pins_scif, + }, + { + .port = { + .membase = (void *)SCIF2, + .mapbase = SCIF2, + .iotype = SERIAL_IO_MEM, + .irq = 59, + .ops = &sci_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, + }, + .type = PORT_SCIF, + .irqs = SH3_SCIF_IRQS, + .init_pins = sci_init_pins_scif, + } #elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) { .port = { @@ -1197,6 +1227,21 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .irqs = SH7300_SCIF0_IRQS, .init_pins = sci_init_pins_scif, }, +#elif defined(CONFIG_CPU_SUBTYPE_SH73180) + { + .port = { + .membase = (void *)0xffe00000, + .mapbase = 0xffe00000, + .iotype = SERIAL_IO_MEM, + .irq = 25, + .ops = &sci_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .type = PORT_SCIF, + .irqs = SH73180_SCIF_IRQS, + .init_pins = sci_init_pins_scif, + }, #elif defined(CONFIG_SH_RTS7751R2D) { .port = { @@ -1284,6 +1329,21 @@ static struct sci_port sci_ports[SCI_NPORTS] = { .irqs = SH7760_SCIF2_IRQS, .init_pins = sci_init_pins_scif, }, +#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) + { + .port = { + .membase = (void *)0xffe80000, + .mapbase = 0xffe80000, + .iotype = SERIAL_IO_MEM, + .irq = 43, + .ops = &sci_uart_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .type = PORT_SCIF, + .irqs = SH4_SCIF_IRQS, + .init_pins = sci_init_pins_scif, + }, #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) { .port = { @@ -1551,7 +1611,7 @@ static struct console kgdb_console = { /* Register the KGDB console so we get messages (d'oh!) */ static int __init kgdb_console_init(void) { - register_console(&kgdb_console); + register_console(&kgdb_console); return 0; } diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index bf248f18a..2892169ef 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -38,6 +38,7 @@ #define SH7760_SCIF1_IRQS { 72, 73, 75, 74 } #define SH7760_SCIF2_IRQS { 76, 77, 79, 78 } #define SH7300_SCIF0_IRQS {80, 80, 80, 80 } +#define SH73180_SCIF_IRQS {80, 81, 83, 82 } #define H8300H_SCI_IRQS0 {52, 53, 54, 0 } #define H8300H_SCI_IRQS1 {56, 57, 58, 0 } #define H8300H_SCI_IRQS2 {60, 61, 62, 0 } @@ -57,6 +58,21 @@ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_AND_SCIF +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) +# define SCIF0 0xA4400000 +# define SCIF2 0xA4410000 +# define SCSMR_Ir 0xA44A0000 +# define IRDA_SCIF SCIF0 +# define SCI_NPORTS 2 +# define SCPCR 0xA4000116 +# define SCPDR 0xA4000136 + +/* Set the clock source, + * SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input + * SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output + */ +# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 +# define SCIF_ONLY #elif defined(CONFIG_SH_RTS7751R2D) # define SCI_NPORTS 1 # define SCSPTR1 0xffe0001c /* 8 bit SCI */ @@ -87,6 +103,19 @@ # define SCPDR 0xA4050136 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH73180) +# define SCI_NPORTS 1 +# define SCPDR 0xA4050138 /* 16 bit SCIF */ +# define SCSPTR2 SCPDR +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) +# define SCI_NPORTS 1 +# define SCSPTR2 0xffe80020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) # define SCI_NPORTS 2 # define SCSPTR1 0xffe00020 /* 16 bit SCIF */ @@ -152,16 +181,16 @@ #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) /* SCxSR SCIF */ -#define SCIF_ER 0x0080 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_TEND 0x0040 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_TDFE 0x0020 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_BRK 0x0010 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_FER 0x0008 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_PER 0x0004 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_RDF 0x0002 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#define SCIF_DR 0x0001 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_ER 0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TEND 0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TDFE 0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_BRK 0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_FER 0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_PER 0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ -#if defined(CONFIG_CPU_SUBTYPE_SH7300) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) #define SCIF_ORER 0x0200 #define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) #define SCIF_RFDC_MASK 0x007f @@ -190,7 +219,7 @@ # define SCxSR_ERRORS(port) SCIF_ERRORS # define SCxSR_RDxF(port) SCIF_RDF # define SCxSR_TDxE(port) SCIF_TDFE -#if defined(CONFIG_CPU_SUBTYPE_SH7300) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCxSR_ORER(port) SCIF_ORER #else # define SCxSR_ORER(port) 0x0000 @@ -198,12 +227,13 @@ # define SCxSR_FER(port) SCIF_FER # define SCxSR_PER(port) SCIF_PER # define SCxSR_BRK(port) SCIF_BRK -#if defined(CONFIG_CPU_SUBTYPE_SH7300) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCxSR_RDxF_CLEAR(port) (sci_in(port,SCxSR)&0xfffc) # define SCxSR_ERROR_CLEAR(port) (sci_in(port,SCxSR)&0xfd73) # define SCxSR_TDxE_CLEAR(port) (sci_in(port,SCxSR)&0xffdf) # define SCxSR_BREAK_CLEAR(port) (sci_in(port,SCxSR)&0xffe3) #else +/* SH7705 can also use this, clearing is same between 7705 and 7709 and 7300 */ # define SCxSR_RDxF_CLEAR(port) 0x00fc # define SCxSR_ERROR_CLEAR(port) 0x0073 # define SCxSR_TDxE_CLEAR(port) 0x00df @@ -307,7 +337,7 @@ struct sci_port { } #ifdef CONFIG_CPU_SH3 -#if defined(CONFIG_CPU_SUBTYPE_SH7300) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) #define SCIF_FNS(name, scif_offset, scif_size) \ CPU_SCIF_FNS(name, scif_offset, scif_size) #else @@ -333,7 +363,7 @@ struct sci_port { CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) +#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) SCIF_FNS(SCSCR, 0x08, 16) @@ -422,7 +452,18 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == SCIF0) + return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ + if (port->mapbase == SCIF2) + return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ + return 1; +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ + defined(CONFIG_CPU_SUBTYPE_SH7751) || \ + defined(CONFIG_CPU_SUBTYPE_SH4_202) static inline int sci_rxd_in(struct uart_port *port) { #ifndef SCIF_ONLY @@ -452,6 +493,11 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */ return 1; } +#elif defined(CONFIG_CPU_SUBTYPE_SH73180) +static inline int sci_rxd_in(struct uart_port *port) +{ + return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */ +} #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) static inline int sci_rxd_in(struct uart_port *port) { @@ -510,6 +556,8 @@ static inline int sci_rxd_in(struct uart_port *port) #if defined(CONFIG_CPU_SUBTYPE_SH7300) #define SCBRR_VALUE(bps) ((PCLK+16*bps)/(16*bps)-1) +#elif defined(CONFIG_CPU_SUBTYPE_SH7705) +#define SCBRR_VALUE(bps) (((PCLK*2)+16*bps)/(32*bps)-1) #elif !defined(__H8300H__) && !defined(__H8300S__) #define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1) #else diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 98b96c546..92e69e24d 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -50,8 +50,8 @@ #include #include +#include #include -#include #include /* number of characters we can transmit to the SAL console at a time */ @@ -70,16 +70,22 @@ /* To use dynamic numbers only and not use the assigned major and minor, * define the following.. */ -/* #define USE_DYNAMIC_MINOR 1 */ /* use dynamic minor number */ -#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */ + /* #define USE_DYNAMIC_MINOR 1 *//* use dynamic minor number */ +#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */ /* Device name we're using */ #define DEVICE_NAME "ttySG" -#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */ +#define DEVICE_NAME_DYNAMIC "ttySG0" /* need full name for misc_register */ /* The major/minor we are using, ignored for USE_DYNAMIC_MINOR */ #define DEVICE_MAJOR 204 #define DEVICE_MINOR 40 +#ifdef CONFIG_MAGIC_SYSRQ +static char sysrq_serial_str[] = "\eSYS"; +static char *sysrq_serial_ptr = sysrq_serial_str; +static unsigned long sysrq_requested; +#endif /* CONFIG_MAGIC_SYSRQ */ + /* * Port definition - this kinda drives it all */ @@ -100,9 +106,8 @@ struct sn_cons_port { static struct sn_cons_port sal_console_port; /* Only used if USE_DYNAMIC_MINOR is set to 1 */ -static struct miscdevice misc; /* used with misc_register for dynamic */ +static struct miscdevice misc; /* used with misc_register for dynamic */ -extern u64 master_node_bedrock_address; extern void early_sn_setup(void); #undef DEBUG @@ -118,9 +123,6 @@ static int snt_hw_puts_raw(const char *, int); static int snt_hw_puts_buffered(const char *, int); static int snt_poll_getc(void); static int snt_poll_input_pending(void); -static int snt_sim_puts(const char *, int); -static int snt_sim_getc(void); -static int snt_sim_input_pending(void); static int snt_intr_getc(void); static int snt_intr_input_pending(void); static void sn_transmit_chars(struct sn_cons_port *, int); @@ -134,14 +136,6 @@ static struct sn_sal_ops poll_ops = { .sal_input_pending = snt_poll_input_pending }; -/* A table for the simulator */ -static struct sn_sal_ops sim_ops = { - .sal_puts_raw = snt_sim_puts, - .sal_puts = snt_sim_puts, - .sal_getc = snt_sim_getc, - .sal_input_pending = snt_sim_input_pending -}; - /* A table for interrupts enabled */ static struct sn_sal_ops intr_ops = { .sal_puts_raw = snt_hw_puts_raw, @@ -162,15 +156,13 @@ static struct sn_sal_ops intr_ops = { * output is buffered and sent to the SAL asynchronously (either by * timer callback or by UART interrupt) */ - /* routines for running the console in polling mode */ /** * snt_poll_getc - Get a character from the console in polling mode * */ -static int -snt_poll_getc(void) +static int snt_poll_getc(void) { int ch; @@ -182,8 +174,7 @@ snt_poll_getc(void) * snt_poll_input_pending - Check if any input is waiting - polling mode. * */ -static int -snt_poll_input_pending(void) +static int snt_poll_input_pending(void) { int status, input; @@ -191,64 +182,13 @@ snt_poll_input_pending(void) return !status && input; } -/* routines for running the console on the simulator */ - -/** - * snt_sim_puts - send to the console, used in simulator mode - * @str: String to send - * @count: length of string - * - */ -static int -snt_sim_puts(const char *str, int count) -{ - int counter = count; - -#ifdef FLAG_DIRECT_CONSOLE_WRITES - /* This is an easy way to pre-pend the output to know whether the output - * was done via sal or directly */ - writeb('[', master_node_bedrock_address + (UART_TX << 3)); - writeb('+', master_node_bedrock_address + (UART_TX << 3)); - writeb(']', master_node_bedrock_address + (UART_TX << 3)); - writeb(' ', master_node_bedrock_address + (UART_TX << 3)); -#endif /* FLAG_DIRECT_CONSOLE_WRITES */ - while (counter > 0) { - writeb(*str, master_node_bedrock_address + (UART_TX << 3)); - counter--; - str++; - } - return count; -} - -/** - * snt_sim_getc - Get character from console in simulator mode - * - */ -static int -snt_sim_getc(void) -{ - return readb(master_node_bedrock_address + (UART_RX << 3)); -} - -/** - * snt_sim_input_pending - Check if there is input pending in simulator mode - * - */ -static int -snt_sim_input_pending(void) -{ - return readb(master_node_bedrock_address + - (UART_LSR << 3)) & UART_LSR_DR; -} - /* routines for an interrupt driven console (normal) */ /** * snt_intr_getc - Get a character from the console, interrupt mode * */ -static int -snt_intr_getc(void) +static int snt_intr_getc(void) { return ia64_sn_console_readc(); } @@ -257,8 +197,7 @@ snt_intr_getc(void) * snt_intr_input_pending - Check if input is pending, interrupt mode * */ -static int -snt_intr_input_pending(void) +static int snt_intr_input_pending(void) { return ia64_sn_console_intr_status() & SAL_CONSOLE_INTR_RECV; } @@ -271,8 +210,7 @@ snt_intr_input_pending(void) * @len: Length * */ -static int -snt_hw_puts_raw(const char *s, int len) +static int snt_hw_puts_raw(const char *s, int len) { /* this will call the PROM and not return until this is done */ return ia64_sn_console_putb(s, len); @@ -284,8 +222,7 @@ snt_hw_puts_raw(const char *s, int len) * @len: Length * */ -static int -snt_hw_puts_buffered(const char *s, int len) +static int snt_hw_puts_buffered(const char *s, int len) { /* queue data to the PROM */ return ia64_sn_console_xmit_chars((char *)s, len); @@ -303,8 +240,7 @@ snt_hw_puts_buffered(const char *s, int len) * @port: Port to operate with (we ignore since we only have one port) * */ -static const char * -snp_type(struct uart_port *port) +static const char *snp_type(struct uart_port *port) { return ("SGI SN L1"); } @@ -314,8 +250,7 @@ snp_type(struct uart_port *port) * @port: Port to operate on (we ignore since we only have one port) * */ -static unsigned int -snp_tx_empty(struct uart_port *port) +static unsigned int snp_tx_empty(struct uart_port *port) { return 1; } @@ -326,8 +261,7 @@ snp_tx_empty(struct uart_port *port) * @tty_stop: Set to 1 if called via uart_stop * */ -static void -snp_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void snp_stop_tx(struct uart_port *port, unsigned int tty_stop) { } @@ -336,8 +270,7 @@ snp_stop_tx(struct uart_port *port, unsigned int tty_stop) * @port: Port to operate on - we ignore - no-op function * */ -static void -snp_release_port(struct uart_port *port) +static void snp_release_port(struct uart_port *port) { } @@ -346,8 +279,7 @@ snp_release_port(struct uart_port *port) * @port: Port to operate on - we ignore - no-op function * */ -static void -snp_enable_ms(struct uart_port *port) +static void snp_enable_ms(struct uart_port *port) { } @@ -356,8 +288,7 @@ snp_enable_ms(struct uart_port *port) * @port: Port to shut down - we ignore * */ -static void -snp_shutdown(struct uart_port *port) +static void snp_shutdown(struct uart_port *port) { } @@ -367,8 +298,7 @@ snp_shutdown(struct uart_port *port) * @mctrl: Lines to set/unset - we ignore * */ -static void -snp_set_mctrl(struct uart_port *port, unsigned int mctrl) +static void snp_set_mctrl(struct uart_port *port, unsigned int mctrl) { } @@ -377,8 +307,7 @@ snp_set_mctrl(struct uart_port *port, unsigned int mctrl) * @port: port to operate on - we only have one port so we ignore this * */ -static unsigned int -snp_get_mctrl(struct uart_port *port) +static unsigned int snp_get_mctrl(struct uart_port *port) { return TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS; } @@ -388,8 +317,7 @@ snp_get_mctrl(struct uart_port *port) * @port: Port to operate on - we ignore * */ -static void -snp_stop_rx(struct uart_port *port) +static void snp_stop_rx(struct uart_port *port) { } @@ -399,11 +327,11 @@ snp_stop_rx(struct uart_port *port) * @tty_stop: Set to 1 if called via uart_start * */ -static void -snp_start_tx(struct uart_port *port, unsigned int tty_stop) +static void snp_start_tx(struct uart_port *port, unsigned int tty_stop) { if (sal_console_port.sc_ops->sal_wakeup_transmit) - sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, TRANSMIT_BUFFERED); + sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, + TRANSMIT_BUFFERED); } @@ -413,8 +341,7 @@ snp_start_tx(struct uart_port *port, unsigned int tty_stop) * @break_state: Break state * */ -static void -snp_break_ctl(struct uart_port *port, int break_state) +static void snp_break_ctl(struct uart_port *port, int break_state) { } @@ -423,8 +350,7 @@ snp_break_ctl(struct uart_port *port, int break_state) * @port: Port to operate on * */ -static int -snp_startup(struct uart_port *port) +static int snp_startup(struct uart_port *port) { return 0; } @@ -447,8 +373,7 @@ snp_set_termios(struct uart_port *port, struct termios *termios, * @port: port to operate on * */ -static int -snp_request_port(struct uart_port *port) +static int snp_request_port(struct uart_port *port) { return 0; } @@ -459,8 +384,7 @@ snp_request_port(struct uart_port *port) * @flags: flags used for port setup * */ -static void -snp_config_port(struct uart_port *port, int flags) +static void snp_config_port(struct uart_port *port, int flags) { } @@ -498,22 +422,17 @@ static struct uart_ops sn_console_ops = { * itself may be broken. * */ -static int -sn_debug_printf(const char *fmt, ...) +static int sn_debug_printf(const char *fmt, ...) { static char printk_buf[1024]; int printed_len; va_list args; va_start(args, fmt); - printed_len = vsnprintf(printk_buf, sizeof (printk_buf), fmt, args); + printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); if (!sal_console_port.sc_ops) { - if (IS_RUNNING_ON_SIMULATOR()) - sal_console_port.sc_ops = &sim_ops; - else - sal_console_port.sc_ops = &poll_ops; - + sal_console_port.sc_ops = &poll_ops; early_sn_setup(); } sal_console_port.sc_ops->sal_puts_raw(printk_buf, printed_len); @@ -521,24 +440,25 @@ sn_debug_printf(const char *fmt, ...) va_end(args); return printed_len; } -#endif /* DEBUG */ +#endif /* DEBUG */ /* * Interrupt handling routines. */ - /** * sn_receive_chars - Grab characters, pass them to tty layer * @port: Port to operate on * @regs: Saved registers (needed by uart_handle_sysrq_char) + * @flags: irq flags * * Note: If we're not registered with the serial core infrastructure yet, * we don't try to send characters to it... * */ static void -sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs) +sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs, + unsigned long flags) { int ch; struct tty_struct *tty; @@ -569,10 +489,34 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs) "obtaining data from the console (0x%0x)\n", ch); break; } -#if defined(CONFIG_SERIAL_SGI_L1_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - if (uart_handle_sysrq_char(&port->sc_port, ch, regs)) - continue; -#endif /* CONFIG_SERIAL_SGI_L1_CONSOLE && CONFIG_MAGIC_SYSRQ */ +#ifdef CONFIG_MAGIC_SYSRQ + if (sysrq_requested) { + unsigned long sysrq_timeout = sysrq_requested + HZ*5; + + sysrq_requested = 0; + if (ch && time_before(jiffies, sysrq_timeout)) { + spin_unlock_irqrestore(&port->sc_port.lock, flags); + handle_sysrq(ch, regs, NULL); + spin_lock_irqsave(&port->sc_port.lock, flags); + /* ignore actual sysrq command char */ + continue; + } + } + if (ch == *sysrq_serial_ptr) { + if (!(*++sysrq_serial_ptr)) { + sysrq_requested = jiffies; + sysrq_serial_ptr = sysrq_serial_str; + } + /* + * ignore the whole sysrq string except for the + * leading escape + */ + if (ch != '\e') + continue; + } + else + sysrq_serial_ptr = sysrq_serial_str; +#endif /* CONFIG_MAGIC_SYSRQ */ /* record the character to pass up to the tty layer */ if (tty) { @@ -583,8 +527,6 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs) if (tty->flip.count == TTY_FLIPBUF_SIZE) break; } - else { - } port->sc_port.icount.rx++; } @@ -604,8 +546,7 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs) * ignore them until we register with the serial core stuffs. * */ -static void -sn_transmit_chars(struct sn_cons_port *port, int raw) +static void sn_transmit_chars(struct sn_cons_port *port, int raw) { int xmit_count, tail, head, loops, ii; int result; @@ -620,8 +561,7 @@ sn_transmit_chars(struct sn_cons_port *port, int raw) if (port->sc_port.info) { /* We're initilized, using serial core infrastructure */ xmit = &port->sc_port.info->xmit; - } - else { + } else { /* Probably sn_sal_switch_to_asynch has been run but serial core isn't * initilized yet. Just return. Writes are going through * sn_sal_console_write (due to register_console) at this time. @@ -673,7 +613,7 @@ sn_transmit_chars(struct sn_cons_port *port, int raw) uart_write_wakeup(&port->sc_port); if (uart_circ_empty(xmit)) - snp_stop_tx(&port->sc_port, 0); /* no-op for us */ + snp_stop_tx(&port->sc_port, 0); /* no-op for us */ } /** @@ -683,10 +623,9 @@ sn_transmit_chars(struct sn_cons_port *port, int raw) * @regs: Saved registers, used by sn_receive_chars for uart_handle_sysrq_char * */ -static irqreturn_t -sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct sn_cons_port *port = (struct sn_cons_port *) dev_id; + struct sn_cons_port *port = (struct sn_cons_port *)dev_id; unsigned long flags; int status = ia64_sn_console_intr_status(); @@ -695,7 +634,7 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_lock_irqsave(&port->sc_port.lock, flags); if (status & SAL_CONSOLE_INTR_RECV) { - sn_receive_chars(port, regs); + sn_receive_chars(port, regs, flags); } if (status & SAL_CONSOLE_INTR_XMIT) { sn_transmit_chars(port, TRANSMIT_BUFFERED); @@ -711,10 +650,10 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs) * returns the console irq if interrupt is successfully registered, else 0 * */ -static int -sn_sal_connect_interrupt(struct sn_cons_port *port) +static int sn_sal_connect_interrupt(struct sn_cons_port *port) { - if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, SA_INTERRUPT, + if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, + SA_INTERRUPT | SA_SHIRQ, "SAL console driver", port) >= 0) { return SGI_UART_VECTOR; } @@ -732,10 +671,9 @@ sn_sal_connect_interrupt(struct sn_cons_port *port) * Obviously not used in interrupt mode * */ -static void -sn_sal_timer_poll(unsigned long data) +static void sn_sal_timer_poll(unsigned long data) { - struct sn_cons_port *port = (struct sn_cons_port *) data; + struct sn_cons_port *port = (struct sn_cons_port *)data; unsigned long flags; if (!port) @@ -743,7 +681,7 @@ sn_sal_timer_poll(unsigned long data) if (!port->sc_port.irq) { spin_lock_irqsave(&port->sc_port.lock, flags); - sn_receive_chars(port, NULL); + sn_receive_chars(port, NULL, flags); sn_transmit_chars(port, TRANSMIT_RAW); spin_unlock_irqrestore(&port->sc_port.lock, flags); mod_timer(&port->sc_timer, @@ -765,8 +703,7 @@ sn_sal_timer_poll(unsigned long data) * if we didn't already come through here via sn_sal_serial_console_init. * */ -static void __init -sn_sal_switch_to_asynch(struct sn_cons_port *port) +static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port) { unsigned long flags; @@ -781,12 +718,8 @@ sn_sal_switch_to_asynch(struct sn_cons_port *port) spin_lock_irqsave(&port->sc_port.lock, flags); /* early_printk invocation may have done this for us */ - if (!port->sc_ops) { - if (IS_RUNNING_ON_SIMULATOR()) - port->sc_ops = &sim_ops; - else - port->sc_ops = &poll_ops; - } + if (!port->sc_ops) + port->sc_ops = &poll_ops; /* we can't turn on the console interrupt (as request_irq * calls kmalloc, which isn't set up yet), so we rely on a @@ -795,7 +728,7 @@ sn_sal_switch_to_asynch(struct sn_cons_port *port) */ init_timer(&port->sc_timer); port->sc_timer.function = sn_sal_timer_poll; - port->sc_timer.data = (unsigned long) port; + port->sc_timer.data = (unsigned long)port; if (IS_RUNNING_ON_SIMULATOR()) port->sc_interrupt_timeout = 6; @@ -822,8 +755,7 @@ sn_sal_switch_to_asynch(struct sn_cons_port *port) * We attempt to switch to interrupt mode here by calling * sn_sal_connect_interrupt. If that works out, we enable receive interrupts. */ -static void __init -sn_sal_switch_to_interrupts(struct sn_cons_port *port) +static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) { int irq; unsigned long flags; @@ -851,7 +783,6 @@ sn_sal_switch_to_interrupts(struct sn_cons_port *port) * Kernel console definitions */ -#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE static void sn_sal_console_write(struct console *, const char *, unsigned); static int __init sn_sal_console_setup(struct console *, char *); extern struct uart_driver sal_console_uart; @@ -862,22 +793,19 @@ static struct console sal_console = { .write = sn_sal_console_write, .device = uart_console_device, .setup = sn_sal_console_setup, - .index = -1, /* unspecified */ + .index = -1, /* unspecified */ .data = &sal_console_uart, }; #define SAL_CONSOLE &sal_console -#else -#define SAL_CONSOLE 0 -#endif /* CONFIG_SERIAL_SGI_L1_CONSOLE */ static struct uart_driver sal_console_uart = { .owner = THIS_MODULE, .driver_name = "sn_console", .dev_name = DEVICE_NAME, - .major = 0, /* major/minor set at registration time per USE_DYNAMIC_MINOR */ + .major = 0, /* major/minor set at registration time per USE_DYNAMIC_MINOR */ .minor = 0, - .nr = 1, /* one port */ + .nr = 1, /* one port */ .cons = SAL_CONSOLE, }; @@ -890,38 +818,38 @@ static struct uart_driver sal_console_uart = { * core and try to enable interrupt driven mode. * */ -static int __init -sn_sal_module_init(void) +static int __init sn_sal_module_init(void) { int retval; - printk(KERN_INFO "sn_console: Console driver init\n"); - if (!ia64_platform_is("sn2")) return -ENODEV; + printk(KERN_INFO "sn_console: Console driver init\n"); + if (USE_DYNAMIC_MINOR == 1) { misc.minor = MISC_DYNAMIC_MINOR; misc.name = DEVICE_NAME_DYNAMIC; retval = misc_register(&misc); if (retval != 0) { - printk("Failed to register console device using misc_register.\n"); + printk + ("Failed to register console device using misc_register.\n"); return -ENODEV; } sal_console_uart.major = MISC_MAJOR; sal_console_uart.minor = misc.minor; - } - else { + } else { sal_console_uart.major = DEVICE_MAJOR; sal_console_uart.minor = DEVICE_MINOR; } /* We register the driver and the port before switching to interrupts - * or async above so the proper uart structures are populated */ + * or async above so the proper uart structures are populated */ if (uart_register_driver(&sal_console_uart) < 0) { - printk("ERROR sn_sal_module_init failed uart_register_driver, line %d\n", - __LINE__); + printk + ("ERROR sn_sal_module_init failed uart_register_driver, line %d\n", + __LINE__); return -ENODEV; } @@ -957,8 +885,7 @@ sn_sal_module_init(void) * sn_sal_module_exit - When we're unloaded, remove the driver/port * */ -static void __exit -sn_sal_module_exit(void) +static void __exit sn_sal_module_exit(void) { del_timer_sync(&sal_console_port.sc_timer); uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port); @@ -969,8 +896,6 @@ sn_sal_module_exit(void) module_init(sn_sal_module_init); module_exit(sn_sal_module_exit); -#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE - /** * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required * @puts_raw : puts function to do the writing @@ -982,7 +907,8 @@ module_exit(sn_sal_module_exit); * */ -static void puts_raw_fixed(int (*puts_raw) (const char *s, int len), const char *s, int count) +static void puts_raw_fixed(int (*puts_raw) (const char *s, int len), + const char *s, int count) { const char *s1; @@ -1030,7 +956,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) if (port->sc_port.info) { /* somebody really wants this output, might be an - * oops, kdb, panic, etc. make sure they get it. */ + * oops, kdb, panic, etc. make sure they get it. */ #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) if (spin_is_locked(&port->sc_port.lock)) { int lhead = port->sc_port.info->xmit.head; @@ -1038,29 +964,39 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) int counter, got_lock = 0; /* - * We attempt to determine if someone has died with the - * lock. We wait ~20 secs after the head and tail ptrs - * stop moving and assume the lock holder is not functional - * and plow ahead. If the lock is freed within the time out - * period we re-get the lock and go ahead normally. We also - * remember if we have plowed ahead so that we don't have + * We attempt to determine if someone has died with the + * lock. We wait ~20 secs after the head and tail ptrs + * stop moving and assume the lock holder is not functional + * and plow ahead. If the lock is freed within the time out + * period we re-get the lock and go ahead normally. We also + * remember if we have plowed ahead so that we don't have * to wait out the time out period again - the asumption - * is that we will time out again. - */ + * is that we will time out again. + */ for (counter = 0; counter < 150; mdelay(125), counter++) { - if (!spin_is_locked(&port->sc_port.lock) || stole_lock) { + if (!spin_is_locked(&port->sc_port.lock) + || stole_lock) { if (!stole_lock) { - spin_lock_irqsave(&port->sc_port.lock, flags); + spin_lock_irqsave(&port-> + sc_port.lock, + flags); got_lock = 1; } break; - } - else { + } else { /* still locked */ - if ((lhead != port->sc_port.info->xmit.head) || (ltail != port->sc_port.info->xmit.tail)) { - lhead = port->sc_port.info->xmit.head; - ltail = port->sc_port.info->xmit.tail; + if ((lhead != + port->sc_port.info->xmit.head) + || (ltail != + port->sc_port.info->xmit. + tail)) { + lhead = + port->sc_port.info->xmit. + head; + ltail = + port->sc_port.info->xmit. + tail; counter = 0; } } @@ -1068,16 +1004,15 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) /* flush anything in the serial core xmit buffer, raw */ sn_transmit_chars(port, 1); if (got_lock) { - spin_unlock_irqrestore(&port->sc_port.lock, flags); + spin_unlock_irqrestore(&port->sc_port.lock, + flags); stole_lock = 0; - } - else { + } else { /* fell thru */ stole_lock = 1; } puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); - } - else { + } else { stole_lock = 0; #endif spin_lock_irqsave(&port->sc_port.lock, flags); @@ -1085,7 +1020,9 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) spin_unlock_irqrestore(&port->sc_port.lock, flags); puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) } +#endif } else { /* Not yet registered with serial core - simple case */ @@ -1106,8 +1043,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) * here so providing it is easier. * */ -static int __init -sn_sal_console_setup(struct console *co, char *options) +static int __init sn_sal_console_setup(struct console *co, char *options) { return 0; } @@ -1135,7 +1071,7 @@ static struct console sal_console_early __initdata = { .name = "sn_sal", .write = sn_sal_console_write_early, .flags = CON_PRINTBUFFER, - .index = -1, + .index = -1, }; /** @@ -1147,24 +1083,18 @@ static struct console sal_console_early __initdata = { * sn_sal_serial_console_init is called, this console is unregistered * and a new one registered. */ -int __init -sn_serial_console_early_setup(void) +int __init sn_serial_console_early_setup(void) { if (!ia64_platform_is("sn2")) return -1; - if (IS_RUNNING_ON_SIMULATOR()) - sal_console_port.sc_ops = &sim_ops; - else - sal_console_port.sc_ops = &poll_ops; - - early_sn_setup(); /* Find SAL entry points */ + sal_console_port.sc_ops = &poll_ops; + early_sn_setup(); /* Find SAL entry points */ register_console(&sal_console_early); return 0; } - /** * sn_sal_serial_console_init - Early console output - set up for register * @@ -1177,12 +1107,11 @@ sn_serial_console_early_setup(void) * it here doesn't hurt anything. * */ -static int __init -sn_sal_serial_console_init(void) +static int __init sn_sal_serial_console_init(void) { if (ia64_platform_is("sn2")) { sn_sal_switch_to_asynch(&sal_console_port); - DPRINTF ("sn_sal_serial_console_init : register console\n"); + DPRINTF("sn_sal_serial_console_init : register console\n"); register_console(&sal_console); unregister_console(&sal_console_early); } @@ -1190,5 +1119,3 @@ sn_sal_serial_console_init(void) } console_initcall(sn_sal_serial_console_init); - -#endif /* CONFIG_SERIAL_SGI_L1_CONSOLE */ diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 494df5557..8caaf2e5e 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -51,7 +51,7 @@ struct uart_sunsab_port { struct uart_port port; /* Generic UART port */ - union sab82532_async_regs *regs; /* Chip registers */ + union sab82532_async_regs __iomem *regs; /* Chip registers */ unsigned long irqflags; /* IRQ state flags */ int dsr; /* Current DSR state */ unsigned int cec_timeout; /* Chip poll timeout... */ @@ -143,6 +143,11 @@ receive_chars(struct uart_sunsab_port *up, writeb(SAB82532_CMDR_RMC, &up->regs->w.cmdr); } + /* Count may be zero for BRK, so we check for it here */ + if ((stat->sreg.isr1 & SAB82532_ISR1_BRK) && + (up->port.line == up->port.cons->index)) + saw_console_brk = 1; + for (i = 0; i < count; i++) { unsigned char ch = buf[i]; @@ -172,8 +177,6 @@ receive_chars(struct uart_sunsab_port *up, stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR | SAB82532_ISR0_FERR); up->port.icount.brk++; - if (up->port.line == up->port.cons->index) - saw_console_brk = 1; /* * We do the SysRQ and SAK checking * here because otherwise the break @@ -325,8 +328,9 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs) tty = NULL; if (status.stat) { - if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | - SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) + if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | + SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || + (status.sreg.isr1 & SAB82532_ISR1_BRK)) tty = receive_chars(up, &status, regs); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & SAB82532_ISR1_CSC)) @@ -352,8 +356,10 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id, struct pt_regs *regs) tty = NULL; if (status.stat) { - if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | - SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) + if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME | + SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) || + (status.sreg.isr1 & SAB82532_ISR1_BRK)) + tty = receive_chars(up, &status, regs); if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) || (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC))) @@ -768,25 +774,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0), &up->regs->rw.ccr2); - if (cflag & CRTSCTS) { - writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_RTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FCTS, - &up->regs->rw.mode); - up->interrupt_mask1 &= ~SAB82532_IMR1_CSC; - writeb(up->interrupt_mask1, &up->regs->w.imr1); - } else { - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS, - &up->regs->rw.mode); - writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FCTS, - &up->regs->rw.mode); - up->interrupt_mask1 |= SAB82532_IMR1_CSC; - writeb(up->interrupt_mask1, &up->regs->w.imr1); - } writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode); } @@ -940,6 +927,7 @@ static int sunsab_console_setup(struct console *con, char *options) writeb(up->interrupt_mask1, &up->regs->w.imr1); sunsab_convert_to_sab(up, con->cflag, 0, baud); + sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); spin_unlock_irqrestore(&up->port.lock, flags); @@ -1143,14 +1131,14 @@ static int __init sunsab_init(void) sunserial_current_minor += num_channels; + sunsab_console_init(); + for (i = 0; i < num_channels; i++) { struct uart_sunsab_port *up = &sunsab_ports[i]; uart_add_one_port(&sunsab_reg, &up->port); } - sunsab_console_init(); - return 0; } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 02586518a..9fe592232 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -95,10 +95,9 @@ struct uart_sunsu_port { enum su_type su_type; unsigned int type_probed; /* XXX Stupid */ int port_node; - unsigned int irq; #ifdef CONFIG_SERIO - struct serio serio; + struct serio *serio; int serio_open; #endif }; @@ -520,7 +519,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg /* Stop-A is handled by drivers/char/keyboard.c now. */ if (up->su_type == SU_PORT_KBD) { #ifdef CONFIG_SERIO - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(up->serio, ch, 0, regs); #endif } else if (up->su_type == SU_PORT_MS) { int ret = suncore_mouse_baud_detection(ch, is_break); @@ -534,7 +533,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg case 0: #ifdef CONFIG_SERIO - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(up->serio, ch, 0, regs); #endif break; }; @@ -684,14 +683,14 @@ static int sunsu_startup(struct uart_port *port) } if (up->su_type != SU_PORT_PORT) { - retval = request_irq(up->irq, sunsu_kbd_ms_interrupt, + retval = request_irq(up->port.irq, sunsu_kbd_ms_interrupt, SA_SHIRQ, su_typev[up->su_type], up); } else { - retval = request_irq(up->irq, sunsu_serial_interrupt, + retval = request_irq(up->port.irq, sunsu_serial_interrupt, SA_SHIRQ, su_typev[up->su_type], up); } if (retval) { - printk("su: Cannot register IRQ %d\n", up->irq); + printk("su: Cannot register IRQ %d\n", up->port.irq); return retval; } @@ -779,7 +778,7 @@ static void sunsu_shutdown(struct uart_port *port) */ (void) serial_in(up, UART_RX); - free_irq(up->irq, up); + free_irq(up->port.irq, up); } static void @@ -994,7 +993,7 @@ static spinlock_t sunsu_serio_lock = SPIN_LOCK_UNLOCKED; static int sunsu_serio_write(struct serio *serio, unsigned char ch) { - struct uart_sunsu_port *up = serio->driver; + struct uart_sunsu_port *up = serio->port_data; unsigned long flags; int lsr; @@ -1014,7 +1013,7 @@ static int sunsu_serio_write(struct serio *serio, unsigned char ch) static int sunsu_serio_open(struct serio *serio) { - struct uart_sunsu_port *up = serio->driver; + struct uart_sunsu_port *up = serio->port_data; unsigned long flags; int ret; @@ -1031,7 +1030,7 @@ static int sunsu_serio_open(struct serio *serio) static void sunsu_serio_close(struct serio *serio) { - struct uart_sunsu_port *up = serio->driver; + struct uart_sunsu_port *up = serio->port_data; unsigned long flags; spin_lock_irqsave(&sunsu_serio_lock, flags); @@ -1078,7 +1077,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) * This is correct on both architectures. */ up->port.mapbase = dev->resource[0].start; - up->irq = dev->irqs[0]; + up->port.irq = dev->irqs[0]; goto ebus_done; } } @@ -1091,7 +1090,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) /* Same on sparc64. Cool architecure... */ up->port.membase = (char *) isa_dev->resource.start; up->port.mapbase = isa_dev->resource.start; - up->irq = isa_dev->irq; + up->port.irq = isa_dev->irq; goto ebus_done; } } @@ -1133,7 +1132,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) /* * There is no intr property on MrCoffee, so hardwire it. */ - up->irq = IRQ_4M(13); + up->port.irq = IRQ_4M(13); #endif ebus_done: @@ -1284,54 +1283,58 @@ static struct uart_driver sunsu_reg = { .major = TTY_MAJOR, }; -static int __init sunsu_kbd_ms_init(void) +static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel) { - struct uart_sunsu_port *up; - int i; + struct serio *serio; - for (i = 0, up = sunsu_ports; i < 2; i++, up++) { - up->port.line = i; - up->port.type = PORT_UNKNOWN; - up->port.uartclk = (SU_BASE_BAUD * 16); + up->port.line = channel; + up->port.type = PORT_UNKNOWN; + up->port.uartclk = (SU_BASE_BAUD * 16); - if (up->su_type == SU_PORT_KBD) - up->cflag = B1200 | CS8 | CLOCAL | CREAD; - else - up->cflag = B4800 | CS8 | CLOCAL | CREAD; + if (up->su_type == SU_PORT_KBD) + up->cflag = B1200 | CS8 | CLOCAL | CREAD; + else + up->cflag = B4800 | CS8 | CLOCAL | CREAD; - sunsu_autoconfig(up); - if (up->port.type == PORT_UNKNOWN) - continue; + sunsu_autoconfig(up); + if (up->port.type == PORT_UNKNOWN) + return -1; - printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n", - i, - up->port.membase, __irq_itoa(up->irq), - sunsu_type(&up->port)); + printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n", + channel, + up->port.membase, __irq_itoa(up->port.irq), + sunsu_type(&up->port)); #ifdef CONFIG_SERIO - memset(&up->serio, 0, sizeof(up->serio)); + up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(*serio)); - up->serio.driver = up; + serio->port_data = up; - up->serio.type = SERIO_RS232; + serio->type = SERIO_RS232; if (up->su_type == SU_PORT_KBD) { - up->serio.type |= SERIO_SUNKBD; - up->serio.name = "sukbd"; + serio->type |= SERIO_SUNKBD; + strlcpy(serio->name, "sukbd", sizeof(serio->name)); } else { - up->serio.type |= (SERIO_SUN | (1 << 16)); - up->serio.name = "sums"; + serio->type |= (SERIO_SUN | (1 << 16)); + strlcpy(serio->name, "sums", sizeof(serio->name)); } - up->serio.phys = (i == 0 ? "su/serio0" : "su/serio1"); + strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"), + sizeof(serio->phys)); - up->serio.write = sunsu_serio_write; - up->serio.open = sunsu_serio_open; - up->serio.close = sunsu_serio_close; + serio->write = sunsu_serio_write; + serio->open = sunsu_serio_open; + serio->close = sunsu_serio_close; - serio_register_port(&up->serio); + serio_register_port(serio); + } else { + printk(KERN_WARNING "su%d: not enough memory for serio port\n", + channel); + } #endif - sunsu_startup(&up->port); - } + sunsu_startup(&up->port); return 0; } @@ -1529,6 +1532,7 @@ static int __init sunsu_serial_init(void) if (ret < 0) return ret; + sunsu_serial_console_init(); for (i = 0; i < UART_NR; i++) { struct uart_sunsu_port *up = &sunsu_ports[i]; @@ -1680,10 +1684,12 @@ static int __init sunsu_probe(void) if (scan.msx != -1 && scan.kbx != -1) { sunsu_ports[0].su_type = SU_PORT_MS; sunsu_ports[0].port_node = scan.msnode; + sunsu_kbd_ms_init(&sunsu_ports[0], 0); + sunsu_ports[1].su_type = SU_PORT_KBD; sunsu_ports[1].port_node = scan.kbnode; + sunsu_kbd_ms_init(&sunsu_ports[1], 1); - sunsu_kbd_ms_init(); return 0; } @@ -1699,7 +1705,6 @@ static int __init sunsu_probe(void) * Console must be initiated after the generic initialization. */ sunsu_serial_init(); - sunsu_serial_console_init(); return 0; } @@ -1715,7 +1720,10 @@ static void __exit sunsu_exit(void) if (up->su_type == SU_PORT_MS || up->su_type == SU_PORT_KBD) { #ifdef CONFIG_SERIO - serio_unregister_port(&up->serio); + if (up->serio) { + serio_unregister_port(up->serio); + up->serio = NULL; + } #endif } else if (up->port.type != PORT_UNKNOWN) { uart_remove_one_port(&sunsu_reg, &up->port); diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index b38c02593..09add5f1e 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -107,12 +107,12 @@ struct uart_sunzilog_port { unsigned char prev_status; #ifdef CONFIG_SERIO - struct serio serio; + struct serio *serio; int serio_open; #endif }; -#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase)) +#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase)) #define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT)) #define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB) @@ -133,7 +133,7 @@ struct uart_sunzilog_port { * The port lock must be held and local IRQs must be disabled * when {read,write}_zsreg is invoked. */ -static unsigned char read_zsreg(struct zilog_channel *channel, +static unsigned char read_zsreg(struct zilog_channel __iomem *channel, unsigned char reg) { unsigned char retval; @@ -146,7 +146,7 @@ static unsigned char read_zsreg(struct zilog_channel *channel, return retval; } -static void write_zsreg(struct zilog_channel *channel, +static void write_zsreg(struct zilog_channel __iomem *channel, unsigned char reg, unsigned char value) { sbus_writeb(reg, &channel->control); @@ -155,7 +155,7 @@ static void write_zsreg(struct zilog_channel *channel, ZSDELAY(); } -static void sunzilog_clear_fifo(struct zilog_channel *channel) +static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) { int i; @@ -182,7 +182,7 @@ static void sunzilog_clear_fifo(struct zilog_channel *channel) /* This function must only be called when the TX is not busy. The UART * port lock must be held and local interrupts disabled. */ -static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) +static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) { int i; @@ -258,7 +258,7 @@ static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) * The UART port lock must be held and local interrupts disabled. */ static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up, - struct zilog_channel *channel) + struct zilog_channel __iomem *channel) { if (!ZS_REGS_HELD(up)) { if (ZS_TX_ACTIVE(up)) { @@ -291,7 +291,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, /* Stop-A is handled by drivers/char/keyboard.c now. */ #ifdef CONFIG_SERIO if (up->serio_open) - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(up->serio, ch, 0, regs); #endif } else if (ZS_IS_MOUSE(up)) { int ret = suncore_mouse_baud_detection(ch, is_break); @@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, case 0: #ifdef CONFIG_SERIO if (up->serio_open) - serio_interrupt(&up->serio, ch, 0, regs); + serio_interrupt(up->serio, ch, 0, regs); #endif break; }; @@ -315,7 +315,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, static struct tty_struct * sunzilog_receive_chars(struct uart_sunzilog_port *up, - struct zilog_channel *channel, + struct zilog_channel __iomem *channel, struct pt_regs *regs) { struct tty_struct *tty; @@ -419,7 +419,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, } static void sunzilog_status_handle(struct uart_sunzilog_port *up, - struct zilog_channel *channel, + struct zilog_channel __iomem *channel, struct pt_regs *regs) { unsigned char status; @@ -471,7 +471,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up, } static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, - struct zilog_channel *channel) + struct zilog_channel __iomem *channel) { struct circ_buf *xmit; @@ -548,7 +548,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg struct uart_sunzilog_port *up = dev_id; while (up) { - struct zilog_channel *channel + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); struct tty_struct *tty; unsigned char r3; @@ -609,7 +609,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg */ static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port) { - struct zilog_channel *channel; + struct zilog_channel __iomem *channel; unsigned long flags; unsigned char status; @@ -662,7 +662,7 @@ static unsigned int sunzilog_get_mctrl(struct uart_port *port) static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char set_bits, clear_bits; set_bits = clear_bits = 0; @@ -694,7 +694,7 @@ static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop) static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char status; up->flags |= SUNZILOG_FLAG_TX_ACTIVE; @@ -736,7 +736,7 @@ static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start) static void sunzilog_stop_rx(struct uart_port *port) { struct uart_sunzilog_port *up = UART_ZILOG(port); - struct zilog_channel *channel; + struct zilog_channel __iomem *channel; if (ZS_IS_CONS(up)) return; @@ -752,7 +752,7 @@ static void sunzilog_stop_rx(struct uart_port *port) static void sunzilog_enable_ms(struct uart_port *port) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char new_reg; new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); @@ -768,7 +768,7 @@ static void sunzilog_enable_ms(struct uart_port *port) static void sunzilog_break_ctl(struct uart_port *port, int break_state) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char set_bits, clear_bits, new_reg; unsigned long flags; @@ -794,7 +794,7 @@ static void sunzilog_break_ctl(struct uart_port *port, int break_state) static void __sunzilog_startup(struct uart_sunzilog_port *up) { - struct zilog_channel *channel; + struct zilog_channel __iomem *channel; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); up->prev_status = sbus_readb(&channel->control); @@ -849,7 +849,7 @@ static int sunzilog_startup(struct uart_port *port) static void sunzilog_shutdown(struct uart_port *port) { struct uart_sunzilog_port *up = UART_ZILOG(port); - struct zilog_channel *channel; + struct zilog_channel __iomem *channel; unsigned long flags; if (ZS_IS_CONS(up)) @@ -974,6 +974,8 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios, sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); + uart_update_timeout(port, termios->c_cflag, baud); + spin_unlock_irqrestore(&up->port.lock, flags); } @@ -1025,7 +1027,7 @@ static struct uart_ops sunzilog_pops = { }; static struct uart_sunzilog_port *sunzilog_port_table; -static struct zilog_layout **sunzilog_chip_regs; +static struct zilog_layout __iomem **sunzilog_chip_regs; static struct uart_sunzilog_port *sunzilog_irq_chain; static int zilog_irq = -1; @@ -1051,10 +1053,10 @@ static void * __init alloc_one_table(unsigned long size) static void __init sunzilog_alloc_tables(void) { - sunzilog_port_table = (struct uart_sunzilog_port *) + sunzilog_port_table = alloc_one_table(NUM_CHANNELS * sizeof(struct uart_sunzilog_port)); - sunzilog_chip_regs = (struct zilog_layout **) - alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout *)); + sunzilog_chip_regs = + alloc_one_table(NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *)); if (sunzilog_port_table == NULL || sunzilog_chip_regs == NULL) { prom_printf("SunZilog: Cannot allocate tables.\n"); @@ -1067,7 +1069,7 @@ static void __init sunzilog_alloc_tables(void) /* We used to attempt to use the address property of the Zilog device node * but that totally is not necessary on sparc64. */ -static struct zilog_layout * __init get_zs_sun4u(int chip, int zsnode) +static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode) { unsigned long mapped_addr; unsigned int sun4u_ino; @@ -1131,7 +1133,7 @@ static struct zilog_layout * __init get_zs_sun4u(int chip, int zsnode) } } - return (struct zilog_layout *) mapped_addr; + return (struct zilog_layout __iomem *) mapped_addr; } #else /* CONFIG_SPARC64 */ @@ -1139,10 +1141,10 @@ static struct zilog_layout * __init get_zs_sun4u(int chip, int zsnode) * XXX The sun4d case is utterly screwed: it tries to re-walk the tree * (for the 3rd time) in order to find bootbus and cpu. Streamline it. */ -static struct zilog_layout * __init get_zs_sun4cmd(int chip, int node) +static struct zilog_layout __iomem * __init get_zs_sun4cmd(int chip, int node) { struct linux_prom_irqs irq_info[2]; - unsigned long mapped_addr = 0; + void __iomem *mapped_addr = NULL; int zsnode, cpunode, bbnode; struct linux_prom_registers zsreg[4]; struct resource res; @@ -1228,12 +1230,12 @@ static struct zilog_layout * __init get_zs_sun4cmd(int chip, int node) prom_halt(); } - return (struct zilog_layout *) mapped_addr; + return (struct zilog_layout __iomem *) mapped_addr; } #endif /* !(CONFIG_SPARC64) */ /* Get the address of the registers for SunZilog instance CHIP. */ -static struct zilog_layout * __init get_zs(int chip, int node) +static struct zilog_layout __iomem * __init get_zs(int chip, int node) { if (chip < 0 || chip >= NUM_SUNZILOG) { prom_printf("SunZilog: Illegal chip number %d in get_zs.\n", chip); @@ -1259,7 +1261,7 @@ static struct zilog_layout * __init get_zs(int chip, int node) zilog_irq = 12; res.end = (res.start + (8 - 1)); res.flags = IORESOURCE_IO; - return (struct zilog_layout *) sbus_ioremap(&res, 0, 8, "SunZilog"); + return sbus_ioremap(&res, 0, 8, "SunZilog"); } return get_zs_sun4cmd(chip, node); @@ -1268,7 +1270,7 @@ static struct zilog_layout * __init get_zs(int chip, int node) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ -static void sunzilog_put_char(struct zilog_channel *channel, unsigned char ch) +static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch) { int loops = ZS_PUT_CHAR_MAX_DELAY; @@ -1295,7 +1297,7 @@ static spinlock_t sunzilog_serio_lock = SPIN_LOCK_UNLOCKED; static int sunzilog_serio_write(struct serio *serio, unsigned char ch) { - struct uart_sunzilog_port *up = serio->driver; + struct uart_sunzilog_port *up = serio->port_data; unsigned long flags; spin_lock_irqsave(&sunzilog_serio_lock, flags); @@ -1309,7 +1311,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch) static int sunzilog_serio_open(struct serio *serio) { - struct uart_sunzilog_port *up = serio->driver; + struct uart_sunzilog_port *up = serio->port_data; unsigned long flags; int ret; @@ -1326,7 +1328,7 @@ static int sunzilog_serio_open(struct serio *serio) static void sunzilog_serio_close(struct serio *serio) { - struct uart_sunzilog_port *up = serio->driver; + struct uart_sunzilog_port *up = serio->port_data; unsigned long flags; spin_lock_irqsave(&sunzilog_serio_lock, flags); @@ -1483,7 +1485,7 @@ static void __init sunzilog_scan(struct zs_probe_scan *t, int node) static void __init sunzilog_prepare(void) { struct uart_sunzilog_port *up; - struct zilog_layout *rp; + struct zilog_layout __iomem *rp; int channel, chip; /* @@ -1499,8 +1501,8 @@ static void __init sunzilog_prepare(void) for (chip = 0; chip < NUM_SUNZILOG; chip++) { rp = sunzilog_chip_regs[chip]; - up[(chip * 2) + 0].port.membase = (char *) &rp->channelA; - up[(chip * 2) + 1].port.membase = (char *) &rp->channelB; + up[(chip * 2) + 0].port.membase = (void __iomem *)&rp->channelA; + up[(chip * 2) + 1].port.membase = (void __iomem *)&rp->channelB; /* Channel A */ up[(chip * 2) + 0].port.iotype = SERIAL_IO_MEM; @@ -1545,33 +1547,44 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe up->curregs[R15] = BRKIE; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); sunzilog_convert_to_zs(up, up->cflag, 0, brg); + sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); + __sunzilog_startup(up); +} #ifdef CONFIG_SERIO - memset(&up->serio, 0, sizeof(up->serio)); +static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel) +{ + struct serio *serio; - up->serio.driver = up; + up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + if (serio) { + memset(serio, 0, sizeof(*serio)); - up->serio.type = SERIO_RS232; - if (channel == KEYBOARD_LINE) { - up->serio.type |= SERIO_SUNKBD; - up->serio.name = "zskbd"; - } else { - up->serio.type |= (SERIO_SUN | (1 << 16)); - up->serio.name = "zsms"; - } - up->serio.phys = (channel == KEYBOARD_LINE ? - "zs/serio0" : "zs/serio1"); + serio->port_data = up; - up->serio.write = sunzilog_serio_write; - up->serio.open = sunzilog_serio_open; - up->serio.close = sunzilog_serio_close; + serio->type = SERIO_RS232; + if (channel == KEYBOARD_LINE) { + serio->type |= SERIO_SUNKBD; + strlcpy(serio->name, "zskbd", sizeof(serio->name)); + } else { + serio->type |= (SERIO_SUN | (1 << 16)); + strlcpy(serio->name, "zsms", sizeof(serio->name)); + } + strlcpy(serio->phys, + (channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"), + sizeof(serio->phys)); - serio_register_port(&up->serio); -#endif + serio->write = sunzilog_serio_write; + serio->open = sunzilog_serio_open; + serio->close = sunzilog_serio_close; - sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); - __sunzilog_startup(up); + serio_register_port(serio); + } else { + printk(KERN_WARNING "zs%d: not enough memory for serio port\n", + channel); + } } +#endif static void __init sunzilog_init_hw(void) { @@ -1579,7 +1592,7 @@ static void __init sunzilog_init_hw(void) for (i = 0; i < NUM_CHANNELS; i++) { struct uart_sunzilog_port *up = &sunzilog_port_table[i]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; int baud, brg; @@ -1615,10 +1628,15 @@ static void __init sunzilog_init_hw(void) } spin_unlock_irqrestore(&up->port.lock, flags); + +#ifdef CONFIG_SERIO + if (i == KEYBOARD_LINE || i == MOUSE_LINE) + sunzilog_register_serio(up, i); +#endif } } -static struct zilog_layout * __init get_zs(int chip, int node); +static struct zilog_layout __iomem * __init get_zs(int chip, int node); static void __init sunzilog_scan_probe(struct zs_probe_scan *t, int node) { @@ -1672,6 +1690,7 @@ static int __init sunzilog_ports_init(void) ret = uart_register_driver(&sunzilog_reg); if (ret == 0) { + sunzilog_console_init(); for (i = 0; i < NUM_CHANNELS; i++) { struct uart_sunzilog_port *up = &sunzilog_port_table[i]; @@ -1720,7 +1739,6 @@ static int __init sunzilog_init(void) sunzilog_alloc_tables(); sunzilog_ports_init(); - sunzilog_console_init(); return 0; } @@ -1732,10 +1750,15 @@ static void __exit sunzilog_exit(void) for (i = 0; i < NUM_CHANNELS; i++) { struct uart_sunzilog_port *up = &sunzilog_port_table[i]; - if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) - continue; - - uart_remove_one_port(&sunzilog_reg, &up->port); + if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) { +#ifdef CONFIG_SERIO + if (up->serio) { + serio_unregister_port(up->serio); + up->serio = NULL; + } +#endif + } else + uart_remove_one_port(&sunzilog_reg, &up->port); } uart_unregister_driver(&sunzilog_reg); diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c index caaa89a8d..186f1300c 100644 --- a/drivers/serial/uart00.c +++ b/drivers/serial/uart00.c @@ -27,23 +27,25 @@ * */ #include + +#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include -#include #include #include -#include #include #include +#include +#include +#include +#include #include #include #include -#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include #include #define UART00_TYPE (volatile unsigned int*) #include @@ -132,9 +134,8 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs) goto ignore_char; error_return: - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; + tty_insert_flip_char(tty, ch, flg); + ignore_char: status = UART_GET_RSR(port); } @@ -174,11 +175,7 @@ uart00_rx_chars(struct uart_port *port, struct pt_regs *regs) * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; + tty_insert_flip_char(tty, ch, flg); ch = 0; flg = TTY_OVERRUN; } diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 7391ae649..a8c4d1163 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_CONSOLE #include #endif @@ -63,7 +64,6 @@ #include #include #include -#include #include #include #include @@ -211,10 +211,6 @@ static void probe_sccs(void); static void change_speed(struct dec_serial *info); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the copy_from_user blocks while swapping in a page, @@ -683,10 +679,7 @@ static void do_softint(void *private_) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } } @@ -706,7 +699,7 @@ int zs_startup(struct dec_serial * info) save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%02d (irq %d)...", info->line, info->irq); + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); #endif /* @@ -934,7 +927,7 @@ static void rs_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int rs_write(struct tty_struct * tty, int from_user, +static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, total = 0; @@ -950,20 +943,12 @@ static int rs_write(struct tty_struct * tty, int from_user, save_flags(flags); while (1) { cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) break; - if (from_user) { - down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - up(&tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); @@ -1010,10 +995,7 @@ static void rs_flush_buffer(struct tty_struct *tty) cli(); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; sti(); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); + tty_wakeup(tty); } /* @@ -1356,7 +1338,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttyS%02d, count = %d\n", info->line, info->count); + printk("rs_close ttyS%d, count = %d\n", info->line, info->count); #endif if ((tty->count == 1) && (info->count != 1)) { /* @@ -1371,7 +1353,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) info->count = 1; } if (--info->count < 0) { - printk("rs_close: bad serial port count for ttyS%02d: %d\n", + printk("rs_close: bad serial port count for ttyS%d: %d\n", info->line, info->count); info->count = 0; } @@ -1407,8 +1389,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); tty->closing = 0; info->event = 0; info->tty = 0; @@ -1446,7 +1427,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) if (char_time == 0) char_time = 1; if (timeout) - char_time = MIN(char_time, timeout); + char_time = min_t(unsigned long, char_time, timeout); while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(char_time); @@ -1531,7 +1512,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, retval = 0; add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttyS%02d, count = %d\n", + printk("block_til_ready before block: ttyS%d, count = %d\n", info->line, info->count); #endif cli(); @@ -1565,7 +1546,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, break; } #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttyS%02d, count = %d\n", + printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif schedule(); @@ -1576,7 +1557,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, info->count++; info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttyS%02d, count = %d\n", + printk("block_til_ready after blocking: ttyS%d, count = %d\n", info->line, info->count); #endif if (retval) @@ -1742,14 +1723,10 @@ static void __init probe_sccs(void) * We're called early and memory managment isn't up, yet. * Thus check_region would fail. */ - if (check_region((unsigned long) + if (!request_region((unsigned long) zs_channels[n_channels].control, - ZS_CHAN_IO_SIZE) < 0) { + ZS_CHAN_IO_SIZE, "SCC")) panic("SCC I/O region is not free"); - } - request_region((unsigned long) - zs_channels[n_channels].control, - ZS_CHAN_IO_SIZE, "SCC"); #endif zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; zs_soft[n_channels].irq = zs_parms->irq; @@ -1896,7 +1873,7 @@ int __init zs_init(void) info->tqueue.data = info; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - printk("ttyS%02d at 0x%08x (irq = %d)", info->line, + printk("ttyS%d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); tty_register_device(serial_driver, info->line, NULL); diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 1d0a2e1a7..59a6515e7 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -7718,6 +7718,23 @@ static void __exit ixj_exit(void) cleanup(); } +static IXJ *new_ixj(unsigned long port) +{ + IXJ *res; + if (!request_region(port, 16, "ixj DSP")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port); + return NULL; + } + res = ixj_alloc(); + if (!res) { + release_region(port, 16); + printk(KERN_INFO "ixj: out of memory\n"); + return NULL; + } + res->DSPbase = port; + return res; +} + int __init ixj_probe_isapnp(int *cnt) { int probe = 0; @@ -7750,15 +7767,9 @@ int __init ixj_probe_isapnp(int *cnt) return -ENODEV; } - result = check_region(pnp_port_start(dev, 0), 16); - if (result) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0)); + j = new_ixj(pnp_port_start(dev, 0)); + if (!j) break; - } - - j = ixj_alloc(); - j->DSPbase = pnp_port_start(dev,0); - request_region(j->DSPbase, 16, "ixj DSP"); if (func != 0x110) j->XILINXbase = pnp_port_start(dev, 1); /* get real port */ @@ -7806,22 +7817,15 @@ int __init ixj_probe_isapnp(int *cnt) int __init ixj_probe_isa(int *cnt) { - int i, result, probe; + int i, probe; /* Use passed parameters for older kernels without PnP */ for (i = 0; i < IXJMAX; i++) { if (dspio[i]) { - IXJ *j; + IXJ *j = new_ixj(dspio[i]); - if ((result = check_region(ixj[*cnt].DSPbase, 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[*cnt].DSPbase); + if (!j) break; - } - - j = ixj_alloc(); - - j->DSPbase = dspio[i]; - request_region(j->DSPbase, 16, "ixj DSP"); j->XILINXbase = xio[i]; j->cardtype = 0; @@ -7840,7 +7844,6 @@ int __init ixj_probe_pci(int *cnt) struct pci_dev *pci = NULL; int i, probe = 0; IXJ *j = NULL; - int result; for (i = 0; i < IXJMAX - *cnt; i++) { pci = pci_find_device(0x15E2, 0x0500, pci); @@ -7849,20 +7852,12 @@ int __init ixj_probe_pci(int *cnt) if (pci_enable_device(pci)) break; - if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address\n"); + j = new_ixj(pci_resource_start(pci, 0)); + if (!j) break; - } - /* Grab a device slot */ - j = ixj_alloc(); - if(j == NULL) - break; - - j->DSPbase = pci_resource_start(pci, 0); j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); j->XILINXbase = j->DSPbase + 0x10; - request_region(j->DSPbase, 16, "ixj DSP"); j->cardtype = QTI_PHONEJACK_PCI; j->board = *cnt; probe = ixj_selfprobe(j); diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index ad23b28e6..143818a56 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -1188,12 +1188,12 @@ typedef struct { unsigned int cid_rec_codec; unsigned int cid_rec_volume; unsigned char cid_rec_flag; - char rec_mode; + signed char rec_mode; unsigned int play_codec; unsigned int cid_play_codec; unsigned int cid_play_volume; unsigned char cid_play_flag; - char play_mode; + signed char play_mode; IXJ_FLAGS flags; unsigned long busyflags; unsigned int rec_frame_size; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 09027693c..f216f6a6d 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -23,7 +23,7 @@ #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); +module_param(pc_debug, int, 0644); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #else #define DEBUG(n, args...) diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 0e805e4f3..e22a84223 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -7,7 +7,7 @@ menu "USB support" # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB tristate "Support for Host-side USB" - depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404 + depends on USB_ARCH_HAS_HCD ---help--- Universal Serial Bus (USB) is a specification for a serial bus subsystem which offers higher speeds and more features than the @@ -91,6 +91,8 @@ source "drivers/usb/serial/Kconfig" source "drivers/usb/misc/Kconfig" +source "drivers/usb/atm/Kconfig" + source "drivers/usb/gadget/Kconfig" endmenu diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index e3787f35c..9e63dfde0 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += host/ obj-$(CONFIG_USB_OHCI_HCD) += host/ obj-$(CONFIG_USB_UHCI_HCD) += host/ obj-$(CONFIG_USB_SL811HS) += host/ +obj-$(CONFIG_ETRAX_USB_HOST) += host/ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_AUDIO) += class/ @@ -37,6 +38,7 @@ obj-$(CONFIG_USB_KONICAWC) += media/ obj-$(CONFIG_USB_OV511) += media/ obj-$(CONFIG_USB_PWC) += media/ obj-$(CONFIG_USB_SE401) += media/ +obj-$(CONFIG_USB_SN9C102) += media/ obj-$(CONFIG_USB_STV680) += media/ obj-$(CONFIG_USB_VICAM) += media/ obj-$(CONFIG_USB_W9968CF) += media/ @@ -62,8 +64,10 @@ obj-$(CONFIG_USB_LCD) += misc/ obj-$(CONFIG_USB_LED) += misc/ obj-$(CONFIG_USB_LEGOTOWER) += misc/ obj-$(CONFIG_USB_RIO500) += misc/ -obj-$(CONFIG_USB_SPEEDTOUCH) += misc/ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ + +obj-$(CONFIG_USB_ATM) += atm/ +obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c06a3c1b0..f17e576d1 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -816,6 +816,9 @@ static void speedtch_usb_disconnect(struct usb_interface *intf) return; } +/*QQ need to handle disconnects on interface #2 while uploading firmware */ +/*QQ and what about interface #1? */ + if (instance->int_urb) { struct urb *int_urb = instance->int_urb; instance->int_urb = NULL; diff --git a/drivers/usb/atm/usb_atm.c b/drivers/usb/atm/usb_atm.c index 9180dda04..d1e271e00 100644 --- a/drivers/usb/atm/usb_atm.c +++ b/drivers/usb/atm/usb_atm.c @@ -111,7 +111,7 @@ static int udsl_print_packet(const unsigned char *data, int len); #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands " #define DRIVER_VERSION "1.8" -#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION +#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; @@ -311,6 +311,15 @@ static void udsl_extract_cells(struct udsl_instance_data *instance, ** encode ** *************/ +static inline void udsl_fill_cell_header(unsigned char *target, struct atm_vcc *vcc) +{ + target[0] = vcc->vpi >> 4; + target[1] = (vcc->vpi << 4) | (vcc->vci >> 12); + target[2] = vcc->vci >> 4; + target[3] = vcc->vci << 4; + target[4] = 0xec; +} + static const unsigned char zeros[ATM_CELL_PAYLOAD]; static void udsl_groom_skb(struct atm_vcc *vcc, struct sk_buff *skb) @@ -320,11 +329,6 @@ static void udsl_groom_skb(struct atm_vcc *vcc, struct sk_buff *skb) u32 crc; ctrl->atm_data.vcc = vcc; - ctrl->cell_header[0] = vcc->vpi >> 4; - ctrl->cell_header[1] = (vcc->vpi << 4) | (vcc->vci >> 12); - ctrl->cell_header[2] = vcc->vci >> 4; - ctrl->cell_header[3] = vcc->vci << 4; - ctrl->cell_header[4] = 0xec; ctrl->num_cells = UDSL_NUM_CELLS(skb->len); ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; @@ -366,7 +370,7 @@ static unsigned int udsl_write_cells(struct udsl_instance_data *instance, ne = min(howmany, ctrl->num_entire); for (i = 0; i < ne; i++) { - memcpy(target, ctrl->cell_header, ATM_CELL_HEADER); + udsl_fill_cell_header(target, ctrl->atm_data.vcc); target += ATM_CELL_HEADER; memcpy(target, skb->data, ATM_CELL_PAYLOAD); target += ATM_CELL_PAYLOAD; @@ -382,11 +386,7 @@ static unsigned int udsl_write_cells(struct udsl_instance_data *instance, if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) goto out; - if (instance->snd_padding) { - memset(target, 0, instance->snd_padding); - target += instance->snd_padding; - } - memcpy(target, ctrl->cell_header, ATM_CELL_HEADER); + udsl_fill_cell_header(target, ctrl->atm_data.vcc); target += ATM_CELL_HEADER; memcpy(target, skb->data, skb->len); target += skb->len; @@ -400,7 +400,11 @@ static unsigned int udsl_write_cells(struct udsl_instance_data *instance, goto out; } - memcpy(target, ctrl->cell_header, ATM_CELL_HEADER); + if (instance->snd_padding) { + memset(target, 0, instance->snd_padding); + target += instance->snd_padding; + } + udsl_fill_cell_header(target, ctrl->atm_data.vcc); target += ATM_CELL_HEADER; memset(target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; diff --git a/drivers/usb/atm/usb_atm.h b/drivers/usb/atm/usb_atm.h index 188e91710..219763cc3 100644 --- a/drivers/usb/atm/usb_atm.h +++ b/drivers/usb/atm/usb_atm.h @@ -91,7 +91,6 @@ struct udsl_control { unsigned int num_cells; unsigned int num_entire; unsigned int pdu_padding; - unsigned char cell_header[ATM_CELL_HEADER]; unsigned char aal5_trailer[ATM_AAL5_TRAILER]; }; diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 3d49e9d8c..0561d0234 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -9,7 +9,8 @@ config USB_AUDIO depends on USB && SOUND help Say Y here if you want to connect USB audio equipment such as - speakers to your computer's USB port. + speakers to your computer's USB port. You only need this if you use + the OSS sound driver; ALSA has its own option for usb audio support. To compile this driver as a module, choose M here: the module will be called audio. diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c index 42f60fa37..675b5ffa3 100644 --- a/drivers/usb/class/audio.c +++ b/drivers/usb/class/audio.c @@ -509,7 +509,10 @@ static int dmabuf_mmap(struct vm_area_struct *vma, struct dmabuf *db, unsigned l return -EINVAL; db->mapped = 1; for(nr = 0; nr < size; nr++) { - if (remap_page_range(vma, start, virt_to_phys(db->sgbuf[nr]), PAGE_SIZE, prot)) + unsigned long pfn; + + pfn = virt_to_phys(db->sgbuf[nr]) >> PAGE_SHIFT; + if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, prot)) return -EAGAIN; start += PAGE_SIZE; } @@ -635,13 +638,13 @@ static void usbin_stop(struct usb_audiodev *as) spin_unlock_irqrestore(&as->lock, flags); if (notkilled && signal_pending(current)) { if (i & FLG_URB0RUNNING) - usb_unlink_urb(u->durb[0].urb); + usb_kill_urb(u->durb[0].urb); if (i & FLG_URB1RUNNING) - usb_unlink_urb(u->durb[1].urb); + usb_kill_urb(u->durb[1].urb); if (i & FLG_SYNC0RUNNING) - usb_unlink_urb(u->surb[0].urb); + usb_kill_urb(u->surb[0].urb); if (i & FLG_SYNC1RUNNING) - usb_unlink_urb(u->surb[1].urb); + usb_kill_urb(u->surb[1].urb); notkilled = 0; } } @@ -1114,13 +1117,13 @@ static void usbout_stop(struct usb_audiodev *as) spin_unlock_irqrestore(&as->lock, flags); if (notkilled && signal_pending(current)) { if (i & FLG_URB0RUNNING) - usb_unlink_urb(u->durb[0].urb); + usb_kill_urb(u->durb[0].urb); if (i & FLG_URB1RUNNING) - usb_unlink_urb(u->durb[1].urb); + usb_kill_urb(u->durb[1].urb); if (i & FLG_SYNC0RUNNING) - usb_unlink_urb(u->surb[0].urb); + usb_kill_urb(u->surb[0].urb); if (i & FLG_SYNC1RUNNING) - usb_unlink_urb(u->surb[1].urb); + usb_kill_urb(u->surb[1].urb); notkilled = 0; } } @@ -1949,15 +1952,12 @@ static inline int prog_dmabuf_out(struct usb_audiodev *as) static int usb_audio_open_mixdev(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); - struct list_head *devs, *mdevs; struct usb_mixerdev *ms; struct usb_audio_state *s; down(&open_sem); - for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) { - s = list_entry(devs, struct usb_audio_state, audiodev); - for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) { - ms = list_entry(mdevs, struct usb_mixerdev, list); + list_for_each_entry(s, &audiodevs, audiodev) { + list_for_each_entry(ms, &s->mixerlist, list) { if (ms->dev_mixer == minor) goto mixer_found; } @@ -2634,16 +2634,13 @@ static int usb_audio_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); DECLARE_WAITQUEUE(wait, current); - struct list_head *devs, *adevs; struct usb_audiodev *as; struct usb_audio_state *s; for (;;) { down(&open_sem); - for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) { - s = list_entry(devs, struct usb_audio_state, audiodev); - for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) { - as = list_entry(adevs, struct usb_audiodev, list); + list_for_each_entry(s, &audiodevs, audiodev) { + list_for_each_entry(as, &s->audiolist, list) { if (!((as->dev_audio ^ minor) & ~0xf)) goto device_found; } @@ -3122,12 +3119,18 @@ static void prepmixch(struct consmixstate *state) { struct usb_device *dev = state->s->usbdev; struct mixerchannel *ch; - unsigned char buf[2]; + unsigned char *buf; __s16 v1; unsigned int v2, v3; if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES) return; + buf = kmalloc(sizeof(*buf) * 2, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "prepmixch: out of memory\n") ; + return; + } + ch = &state->mixch[state->nrmixch-1]; switch (ch->selector) { case 0: /* mixer unit request */ @@ -3239,13 +3242,16 @@ static void prepmixch(struct consmixstate *state) default: goto err; } - return; + freebuf: + kfree(buf); + return; err: printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector); if (state->nrmixch) state->nrmixch--; + goto freebuf; } @@ -3809,7 +3815,6 @@ static int usb_audio_probe(struct usb_interface *intf, static void usb_audio_disconnect(struct usb_interface *intf) { struct usb_audio_state *s = usb_get_intfdata (intf); - struct list_head *list; struct usb_audiodev *as; struct usb_mixerdev *ms; @@ -3831,8 +3836,7 @@ static void usb_audio_disconnect(struct usb_interface *intf) usb_set_intfdata (intf, NULL); /* deregister all audio and mixer devices, so no new processes can open this device */ - for(list = s->audiolist.next; list != &s->audiolist; list = list->next) { - as = list_entry(list, struct usb_audiodev, list); + list_for_each_entry(as, &s->audiolist, list) { usbin_disc(as); usbout_disc(as); wake_up(&as->usbin.dma.wait); @@ -3843,8 +3847,7 @@ static void usb_audio_disconnect(struct usb_interface *intf) } as->dev_audio = -1; } - for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) { - ms = list_entry(list, struct usb_mixerdev, list); + list_for_each_entry(ms, &s->mixerlist, list) { if (ms->dev_mixer >= 0) { unregister_sound_mixer(ms->dev_mixer); printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer); diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c index 2e8f5200c..6585faa28 100644 --- a/drivers/usb/class/bluetty.c +++ b/drivers/usb/class/bluetty.c @@ -207,7 +207,7 @@ struct usb_bluetooth { /* local function prototypes */ static int bluetooth_open (struct tty_struct *tty, struct file *filp); static void bluetooth_close (struct tty_struct *tty, struct file *filp); -static int bluetooth_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static int bluetooth_write (struct tty_struct *tty, const unsigned char *buf, int count); static int bluetooth_write_room (struct tty_struct *tty); static int bluetooth_chars_in_buffer (struct tty_struct *tty); static void bluetooth_throttle (struct tty_struct *tty); @@ -426,14 +426,14 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp) bluetooth->open_count = 0; /* shutdown any in-flight urbs that we know about */ - usb_unlink_urb (bluetooth->read_urb); - usb_unlink_urb (bluetooth->interrupt_in_urb); + usb_kill_urb (bluetooth->read_urb); + usb_kill_urb (bluetooth->interrupt_in_urb); } up(&bluetooth->lock); } -static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int bluetooth_write (struct tty_struct * tty, const unsigned char *buf, int count) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); struct urb *urb = NULL; @@ -471,21 +471,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign printk ("\n"); #endif - if (from_user) { - temp_buffer = kmalloc (count, GFP_KERNEL); - if (temp_buffer == NULL) { - err ("%s - out of memory.", __FUNCTION__); - retval = -ENOMEM; - goto exit; - } - if (copy_from_user (temp_buffer, (void __user *)buf, count)) { - retval = -EFAULT; - goto exit; - } - current_buffer = temp_buffer; - } else { - current_buffer = buf; - } + current_buffer = buf; switch (*current_buffer) { /* First byte indicates the type of packet */ @@ -705,7 +691,7 @@ void btusb_disable_bulk_read(struct tty_struct *tty){ } if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length)) - usb_unlink_urb(bluetooth->read_urb); + usb_kill_urb(bluetooth->read_urb); } #endif @@ -988,21 +974,13 @@ static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs static void bluetooth_softint(void *private) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__); - struct tty_struct *tty; dbg("%s", __FUNCTION__); - if (!bluetooth) { + if (!bluetooth) return; - } - - tty = bluetooth->tty; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - dbg("%s - write wakeup call.", __FUNCTION__); - (tty->ldisc.write_wakeup)(tty); - } - wake_up_interruptible(&tty->write_wait); + tty_wakeup(bluetooth->tty); } @@ -1187,14 +1165,14 @@ static void usb_bluetooth_disconnect(struct usb_interface *intf) bluetooth->open_count = 0; if (bluetooth->read_urb) { - usb_unlink_urb (bluetooth->read_urb); + usb_kill_urb (bluetooth->read_urb); usb_free_urb (bluetooth->read_urb); } if (bluetooth->bulk_in_buffer) kfree (bluetooth->bulk_in_buffer); if (bluetooth->interrupt_in_urb) { - usb_unlink_urb (bluetooth->interrupt_in_urb); + usb_kill_urb (bluetooth->interrupt_in_urb); usb_free_urb (bluetooth->interrupt_in_urb); } if (bluetooth->interrupt_in_buffer) @@ -1204,7 +1182,7 @@ static void usb_bluetooth_disconnect(struct usb_interface *intf) for (i = 0; i < NUM_CONTROL_URBS; ++i) { if (bluetooth->control_urb_pool[i]) { - usb_unlink_urb (bluetooth->control_urb_pool[i]); + usb_kill_urb (bluetooth->control_urb_pool[i]); if (bluetooth->control_urb_pool[i]->transfer_buffer) kfree (bluetooth->control_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->control_urb_pool[i]); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3fae8a6e4..cf7fcf829 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -142,7 +142,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs) case ACM_IRQ_LINE_STATE: - newctrl = le16_to_cpu(get_unaligned((__u16 *) data)); + newctrl = le16_to_cpu(get_unaligned((__le16 *) data)); if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { dbg("calling hangup"); @@ -248,16 +248,11 @@ out: static void acm_softint(void *private) { struct acm *acm = private; - struct tty_struct *tty = acm->tty; dbg("Entering acm_softint.\n"); if (!ACM_READY(acm)) return; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - - wake_up_interruptible(&tty->write_wait); + tty_wakeup(acm->tty); } /* @@ -306,9 +301,9 @@ done: return 0; full_bailout: - usb_unlink_urb(acm->readurb); + usb_kill_urb(acm->readurb); bail_out_and_unlink: - usb_unlink_urb(acm->ctrlurb); + usb_kill_urb(acm->ctrlurb); bail_out: up(&open_sem); return -EIO; @@ -325,9 +320,9 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) if (!--acm->used) { if (acm->dev) { acm_set_control(acm, acm->ctrlout = 0); - usb_unlink_urb(acm->ctrlurb); - usb_unlink_urb(acm->writeurb); - usb_unlink_urb(acm->readurb); + usb_kill_urb(acm->ctrlurb); + usb_kill_urb(acm->writeurb); + usb_kill_urb(acm->readurb); } else { tty_unregister_device(acm_tty_driver, acm->minor); acm_table[acm->minor] = NULL; @@ -340,11 +335,11 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) up(&open_sem); } -static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct acm *acm = tty->driver_data; int stat; - dbg("Entering acm_tty_write to write %d bytes from %s space,\n", count, from_user ? "user" : "kernel"); + dbg("Entering acm_tty_write to write %d bytes,\n", count); if (!ACM_READY(acm)) return -EINVAL; @@ -355,19 +350,15 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c count = (count > acm->writesize) ? acm->writesize : count; - dbg("Get %d bytes from %s space...", count, from_user ? "user" : "kernel"); - if (from_user) { - if (copy_from_user(acm->write_buffer, (void __user *)buf, count)) - return -EFAULT; - } else - memcpy(acm->write_buffer, buf, count); + dbg("Get %d bytes...", count); + memcpy(acm->write_buffer, buf, count); dbg(" Successfully copied.\n"); acm->writeurb->transfer_buffer_length = count; acm->writeurb->dev = acm->dev; acm->ready_for_write = 0; - stat = usb_submit_urb(acm->writeurb, GFP_NOIO); + stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC); if (stat < 0) { dbg("usb_submit_urb(write bulk) failed"); acm->ready_for_write = 1; @@ -547,6 +538,17 @@ static int acm_probe (struct usb_interface *intf, return -EINVAL; } + if (!buflen) { + if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { + dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint"); + buflen = intf->cur_altsetting->endpoint->extralen; + buffer = intf->cur_altsetting->endpoint->extra; + } else { + err("Zero length descriptor references"); + return -EINVAL; + } + } + while (buflen > 0) { if (buffer [1] != USB_DT_CS_INTERFACE) { err("skipping garbage"); @@ -563,6 +565,8 @@ static int acm_probe (struct usb_interface *intf, break; case CDC_COUNTRY_TYPE: /* maybe somehow export */ break; /* for now we ignore it */ + case CDC_HEADER_TYPE: /* maybe check version */ + break; /* for now we ignore it */ case CDC_AC_MANAGEMENT_TYPE: ac_management_function = buffer[3]; break; @@ -574,7 +578,7 @@ static int acm_probe (struct usb_interface *intf, break; default: - err("Ignoring extra header"); + err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]); break; } next_desc: @@ -583,19 +587,25 @@ next_desc: } if (!union_header) { - dev_dbg(&intf->dev,"No union descriptor, giving up\n"); - return -ENODEV; - } - - control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); - data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); - if (!control_interface || !data_interface) { - dev_dbg(&intf->dev,"no interfaces\n"); - return -ENODEV; + if (call_interface_num > 0) { + dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n"); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); + control_interface = intf; + } else { + dev_dbg(&intf->dev,"No union descriptor, giving up\n"); + return -ENODEV; + } + } else { + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); + if (!control_interface || !data_interface) { + dev_dbg(&intf->dev,"no interfaces\n"); + return -ENODEV; + } } - if (data_interface_num != call_interface_num) - dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported."); + if (data_interface_num != call_interface_num) + dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported."); if (usb_interface_claimed(data_interface)) { /* valid in this context */ dev_dbg(&intf->dev,"The data interface isn't available\n"); @@ -636,7 +646,7 @@ next_desc: dbg("interfaces are valid"); for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); - if (acm_table[minor]) { + if (minor == ACM_TTY_MINORS) { err("no more free acm devices"); return -ENODEV; } @@ -761,9 +771,9 @@ static void acm_disconnect(struct usb_interface *intf) acm->dev = NULL; usb_set_intfdata (intf, NULL); - usb_unlink_urb(acm->ctrlurb); - usb_unlink_urb(acm->readurb); - usb_unlink_urb(acm->writeurb); + usb_kill_urb(acm->ctrlurb); + usb_kill_urb(acm->readurb); + usb_kill_urb(acm->writeurb); flush_scheduled_work(); /* wait for acm_softint */ diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index bf72f278b..da945b367 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -70,7 +70,7 @@ */ struct acm_line { - __u32 speed; + __le32 speed; __u8 stopbits; __u8 parity; __u8 databits; @@ -117,6 +117,7 @@ struct union_desc { } __attribute__ ((packed)); /* class specific descriptor types */ +#define CDC_HEADER_TYPE 0x00 #define CDC_CALL_MANAGEMENT_TYPE 0x01 #define CDC_AC_MANAGEMENT_TYPE 0x02 #define CDC_UNION_TYPE 0x06 diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c index 6a6dbac49..1dc952e9b 100644 --- a/drivers/usb/class/usb-midi.c +++ b/drivers/usb/class/usb-midi.c @@ -55,39 +55,39 @@ /* ------------------------------------------------------------------------- */ static int singlebyte = 0; -MODULE_PARM(singlebyte,"i"); +module_param(singlebyte, int, 0); MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet"); static int maxdevices = 4; -MODULE_PARM(maxdevices,"i"); +module_param(maxdevices, int, 0); MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device"); static int uvendor = -1; -MODULE_PARM(uvendor,"i"); +module_param(uvendor, int, 0); MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface"); static int uproduct = -1; -MODULE_PARM(uproduct,"i"); +module_param(uproduct, int, 0); MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface"); static int uinterface = -1; -MODULE_PARM(uinterface,"i"); +module_param(uinterface, int, 0); MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface"); static int ualt = -1; -MODULE_PARM(ualt,"i"); +module_param(ualt, int, 0); MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface"); static int umin = -1; -MODULE_PARM(umin,"i"); +module_param(umin, int, 0); MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface"); static int umout = -1; -MODULE_PARM(umout,"i"); +module_param(umout, int, 0); MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface"); static int ucable = -1; -MODULE_PARM(ucable,"i"); +module_param(ucable, int, 0); MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface"); /** Note -- the usb_string() returns only Latin-1 characters. @@ -95,7 +95,7 @@ MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface") * unicode16LE-to-JIS routine is needed to wrap around usb_get_string(). **/ static unsigned short ulangid = 0x0409; /** 0x0411 for Japanese **/ -MODULE_PARM(ulangid,"h"); +module_param(ulangid, ushort, 0); MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices"); MODULE_AUTHOR("NAGANO Daisuke "); @@ -805,7 +805,6 @@ static int usb_midi_open(struct inode *inode, struct file *file) { int minor = iminor(inode); DECLARE_WAITQUEUE(wait, current); - struct list_head *devs, *mdevs; struct usb_midi_state *s; struct usb_mididev *m; unsigned long flags; @@ -817,10 +816,8 @@ static int usb_midi_open(struct inode *inode, struct file *file) for(;;) { down(&open_sem); - for (devs = mididevs.next; devs != &mididevs; devs = devs->next) { - s = list_entry(devs, struct usb_midi_state, mididev); - for (mdevs = s->midiDevList.next; mdevs != &s->midiDevList; mdevs = mdevs->next) { - m = list_entry(mdevs, struct usb_mididev, list); + list_for_each_entry(s, &mididevs, mididev) { + list_for_each_entry(m, &s->midiDevList, list) { if ( !((m->dev_midi ^ minor) & ~0xf) ) goto device_found; } @@ -939,7 +936,7 @@ static int usb_midi_release(struct inode *inode, struct file *file) if ( m->open_mode & FMODE_WRITE ) { m->open_mode &= ~FMODE_WRITE; - usb_unlink_urb( m->mout.ep->urb ); + usb_kill_urb( m->mout.ep->urb ); } if ( m->open_mode & FMODE_READ ) { @@ -951,7 +948,7 @@ static int usb_midi_release(struct inode *inode, struct file *file) if ( m->min.ep->readers == 0 && m->min.ep->urbSubmitted ) { m->min.ep->urbSubmitted = 0; - usb_unlink_urb(m->min.ep->urb); + usb_kill_urb(m->min.ep->urb); } spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); } @@ -1042,7 +1039,7 @@ static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, in static int remove_midi_in_endpoint( struct midi_in_endpoint *min ) { - usb_unlink_urb( min->urb ); + usb_kill_urb( min->urb ); usb_free_urb( min->urb ); kfree( min->recvBuf ); kfree( min ); @@ -1102,7 +1099,7 @@ static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d, static int remove_midi_out_endpoint( struct midi_out_endpoint *mout ) { - usb_unlink_urb( mout->urb ); + usb_kill_urb( mout->urb ); usb_free_urb( mout->urb ); kfree( mout->buf ); kfree( mout ); @@ -1994,7 +1991,6 @@ static int usb_midi_probe(struct usb_interface *intf, static void usb_midi_disconnect(struct usb_interface *intf) { struct usb_midi_state *s = usb_get_intfdata (intf); - struct list_head *list; struct usb_mididev *m; if ( !s ) @@ -2012,8 +2008,7 @@ static void usb_midi_disconnect(struct usb_interface *intf) s->usbdev = NULL; usb_set_intfdata (intf, NULL); - for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) { - m = list_entry(list, struct usb_mididev, list); + list_for_each_entry(m, &s->midiDevList, list) { wake_up(&(m->min.ep->wait)); wake_up(&(m->mout.ep->wait)); if ( m->dev_midi >= 0 ) { diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index b6da40067..3bde7c622 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -221,7 +221,8 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol); static int usblp_cache_device_id_string(struct usblp *usblp); /* forward reference to make our lives easier */ -extern struct usb_driver usblp_driver; +static struct usb_driver usblp_driver; +static DECLARE_MUTEX(usblp_sem); /* locks the existence of usblp's */ /* * Functions for usblp control messages. @@ -343,7 +344,7 @@ static int usblp_open(struct inode *inode, struct file *file) if (minor < 0) return -ENODEV; - lock_kernel(); + down (&usblp_sem); retval = -ENODEV; intf = usb_find_interface(&usblp_driver, minor); @@ -389,7 +390,7 @@ static int usblp_open(struct inode *inode, struct file *file) } } out: - unlock_kernel(); + up (&usblp_sem); return retval; } @@ -397,10 +398,6 @@ static void usblp_cleanup (struct usblp *usblp) { info("usblp%d: removed", usblp->minor); - usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, - usblp->writebuf, usblp->writeurb->transfer_dma); - usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, - usblp->readbuf, usblp->readurb->transfer_dma); kfree (usblp->device_id_string); kfree (usblp->statusbuf); usb_free_urb(usblp->writeurb); @@ -410,22 +407,22 @@ static void usblp_cleanup (struct usblp *usblp) static void usblp_unlink_urbs(struct usblp *usblp) { - usb_unlink_urb(usblp->writeurb); + usb_kill_urb(usblp->writeurb); if (usblp->bidir) - usb_unlink_urb(usblp->readurb); + usb_kill_urb(usblp->readurb); } static int usblp_release(struct inode *inode, struct file *file) { struct usblp *usblp = file->private_data; - down (&usblp->sem); + down (&usblp_sem); usblp->used = 0; if (usblp->present) { usblp_unlink_urbs(usblp); - up(&usblp->sem); } else /* finish cleanup from disconnect */ usblp_cleanup (usblp); + up (&usblp_sem); return 0; } @@ -1129,7 +1126,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp) /* First two bytes are length in big-endian. * They count themselves, and we copy them into * the user's buffer. */ - length = be16_to_cpu(*((u16 *)usblp->device_id_string)); + length = be16_to_cpu(*((__be16 *)usblp->device_id_string)); if (length < 2) length = 2; else if (length >= USBLP_DEVICE_ID_SIZE) @@ -1153,18 +1150,21 @@ static void usblp_disconnect(struct usb_interface *intf) BUG (); } + down (&usblp_sem); down (&usblp->sem); - lock_kernel(); usblp->present = 0; usb_set_intfdata (intf, NULL); usblp_unlink_urbs(usblp); + usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, + usblp->writebuf, usblp->writeurb->transfer_dma); + usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, + usblp->readbuf, usblp->readurb->transfer_dma); + up (&usblp->sem); if (!usblp->used) usblp_cleanup (usblp); - else /* cleanup later, on release */ - up (&usblp->sem); - unlock_kernel(); + up (&usblp_sem); } static struct usb_device_id usblp_ids [] = { @@ -1208,6 +1208,6 @@ module_exit(usblp_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_PARM(proto_bias, "i"); +module_param(proto_bias, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(proto_bias, "Favourite protocol number"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 050b078e3..1a9ff6184 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -60,3 +60,40 @@ config USB_DYNAMIC_MINORS If you are unsure about this, say N here. +config USB_SUSPEND + bool "USB suspend/resume (EXPERIMENTAL)" + depends on USB && PM && EXPERIMENTAL + help + If you say Y here, you can use driver calls or the sysfs + "power/state" file to suspend or resume individual USB + peripherals. There are many related features, such as + remote wakeup and driver-specific suspend processing, that + may not yet work as expected. + + If you are unsure about this, say N here. + + +config USB_OTG + bool + depends on USB && EXPERIMENTAL + select USB_SUSPEND + default n + + +config USB_OTG_WHITELIST + bool "Rely on OTG Targeted Peripherals List" + depends on USB_OTG + default y + help + If you say Y here, the "otg_whitelist.h" file will be used as a + product whitelist, so USB peripherals not listed there will be + rejected during enumeration. This behavior is required by the + USB OTG specification for all devices not on your product's + "Targeted Peripherals List". + + Otherwise, peripherals not listed there will only generate a + warning and enumeration will continue. That's more like what + normal Linux-USB hosts do (other than the warning), and is + convenient for many stages of product development. + + diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index ae7ec7405..33c51714f 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -106,7 +106,7 @@ skip_to_next_endpoint_or_interface_descriptor: return buffer - buffer0 + i; } -static void usb_release_interface_cache(struct kref *ref) +void usb_release_interface_cache(struct kref *ref) { struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); int j; @@ -356,7 +356,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx, if (!intfc) return -ENOMEM; memset(intfc, 0, len); - kref_init(&intfc->ref, usb_release_interface_cache); + kref_init(&intfc->ref); } /* Skip over any Class Specific or Vendor Specific descriptors; @@ -422,7 +422,8 @@ void usb_destroy_configuration(struct usb_device *dev) for (i = 0; i < cf->desc.bNumInterfaces; i++) { if (cf->intf_cache[i]) - kref_put(&cf->intf_cache[i]->ref); + kref_put(&cf->intf_cache[i]->ref, + usb_release_interface_cache); } } kfree(dev->config); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 5541363b6..50009ed51 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -149,7 +149,7 @@ static const struct class_info clas_info[] = /*****************************************************************/ -void usbdevfs_conn_disc_event(void) +void usbfs_conn_disc_event(void) { conndiscevcnt++; wake_up(&deviceconndiscwq); @@ -283,9 +283,8 @@ static char *usb_dump_interface( /* TBD: * 0. TBDs - * 1. marking active config and ifaces (code lists all, but should mark + * 1. marking active interface altsettings (code lists all, but should mark * which ones are active, if any) - * 2. add status to each endpoint line */ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active) @@ -452,7 +451,7 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de * nbytes - the maximum number of bytes to write * skip_bytes - the number of bytes to skip before writing anything * file_offset - the offset into the devices file on completion - * The caller must own the usbdev->serialize semaphore. + * The caller must own the device lock. */ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) @@ -570,7 +569,6 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct list_head *buslist; struct usb_bus *bus; ssize_t ret, total_written = 0; loff_t skip_bytes = *ppos; @@ -582,18 +580,15 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - /* enumerate busses */ down (&usb_bus_list_lock); - for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { - /* print devices for this bus */ - bus = list_entry(buslist, struct usb_bus, bus_list); - + /* print devices for all busses */ + list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ if (!bus->root_hub) continue; - down(&bus->root_hub->serialize); + usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); - up(&bus->root_hub->serialize); + usb_unlock_device(bus->root_hub); if (ret < 0) { up(&usb_bus_list_lock); return ret; @@ -683,7 +678,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig) return ret; } -struct file_operations usbdevfs_devices_fops = { +struct file_operations usbfs_devices_fops = { .llseek = usb_device_lseek, .read = usb_device_read, .poll = usb_device_poll, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6f969a4da..ff47c18a0 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -21,7 +21,7 @@ * * $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $ * - * This file implements the usbdevfs/x/y files, where + * This file implements the usbfs/x/y files, where * x is the bus number and y the device number. * * It allows user space programs/"drivers" to communicate directly @@ -72,6 +72,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic"); } while (0) +#define MAX_USBFS_BUFFER_SIZE 16384 + static inline int connected (struct usb_device *dev) { return dev->state != USB_STATE_NOTATTACHED; @@ -111,7 +113,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l int i; pos = *ppos; - down(&dev->serialize); + usb_lock_device(dev); if (!connected(dev)) { ret = -ENODEV; goto err; @@ -173,7 +175,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l } err: - up(&dev->serialize); + usb_unlock_device(dev); return ret; } @@ -284,9 +286,10 @@ static void destroy_async (struct dev_state *ps, struct list_head *list) while (!list_empty(list)) { as = list_entry(list->next, struct async, asynclist); list_del_init(&as->asynclist); + + /* drop the spinlock so the completion handler can run */ spin_unlock_irqrestore(&ps->lock, flags); - /* usb_unlink_urb calls the completion handler with status == -ENOENT */ - usb_unlink_urb(as->urb); + usb_kill_urb(as->urb); spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); @@ -351,7 +354,7 @@ static void driver_disconnect(struct usb_interface *intf) destroy_async_on_interface(ps, ifnum); } -struct usb_driver usbdevfs_driver = { +struct usb_driver usbfs_driver = { .owner = THIS_MODULE, .name = "usbfs", .probe = driver_probe, @@ -376,7 +379,7 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum) if (!intf) err = -ENOENT; else - err = usb_driver_claim_interface(&usbdevfs_driver, intf, ps); + err = usb_driver_claim_interface(&usbfs_driver, intf, ps); up_write(&usb_bus_type.subsys.rwsem); if (err == 0) set_bit(ifnum, &ps->ifclaimed); @@ -399,7 +402,7 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) if (!intf) err = -ENOENT; else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { - usb_driver_release_interface(&usbdevfs_driver, intf); + usb_driver_release_interface(&usbfs_driver, intf); err = 0; } up_write(&usb_bus_type.subsys.rwsem); @@ -408,6 +411,8 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) static int checkintf(struct dev_state *ps, unsigned int ifnum) { + if (ps->dev->state != USB_STATE_CONFIGURED) + return -EHOSTUNREACH; if (ifnum >= 8*sizeof(ps->ifclaimed)) return -EINVAL; if (test_bit(ifnum, &ps->ifclaimed)) @@ -447,6 +452,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig { int ret = 0; + if (ps->dev->state != USB_STATE_CONFIGURED) + return -EHOSTUNREACH; if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) return 0; @@ -514,16 +521,15 @@ static int usbdev_release(struct inode *inode, struct file *file) struct usb_device *dev = ps->dev; unsigned int ifnum; - down(&dev->serialize); + usb_lock_device(dev); list_del_init(&ps->list); - - if (connected(dev)) { - for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); ifnum++) - if (test_bit(ifnum, &ps->ifclaimed)) - releaseintf(ps, ifnum); - destroy_all_async(ps); + for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed); + ifnum++) { + if (test_bit(ifnum, &ps->ifclaimed)) + releaseintf(ps, ifnum); } - up(&dev->serialize); + destroy_all_async(ps); + usb_unlock_device(dev); usb_put_dev(dev); ps->dev = NULL; kfree(ps); @@ -555,8 +561,10 @@ static int proc_control(struct dev_state *ps, void __user *arg) snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + usb_unlock_device(dev); i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); + usb_lock_device(dev); if ((i > 0) && ctrl.wLength) { if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); @@ -584,11 +592,13 @@ static int proc_control(struct dev_state *ps, void __user *arg) printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } + usb_unlock_device(dev); i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); + usb_lock_device(dev); } free_page((unsigned long)tbuf); - if (i<0) { + if (i<0 && i != -EPIPE) { dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " "failed cmd %s rqt %u rq %u len %u ret %d\n", current->comm, ctrl.bRequestType, ctrl.bRequest, @@ -619,6 +629,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) return -EINVAL; len1 = bulk.len; + if (len1 > MAX_USBFS_BUFFER_SIZE) + return -EINVAL; if (!(tbuf = kmalloc(len1, GFP_KERNEL))) return -ENOMEM; tmo = (bulk.timeout * HZ + 999) / 1000; @@ -627,7 +639,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) kfree(tbuf); return -EINVAL; } + usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); + usb_lock_device(dev); if (!i && len2) { if (copy_to_user(bulk.data, tbuf, len2)) { kfree(tbuf); @@ -641,7 +655,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) return -EFAULT; } } + usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); + usb_lock_device(dev); } kfree(tbuf); if (i < 0) { @@ -722,7 +738,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg) static int proc_resetdevice(struct dev_state *ps) { - return __usb_reset_device(ps->dev); + return usb_reset_device(ps->dev); } @@ -849,7 +865,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) case USBDEVFS_URB_TYPE_BULK: uurb.number_of_packets = 0; - if (uurb.buffer_length > 16384) + if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) return -EFAULT; @@ -891,7 +907,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) interval = 1 << min (15, ep_desc->bInterval - 1); else interval = ep_desc->bInterval; - if (uurb.buffer_length > 16384) + if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) return -EFAULT; @@ -964,7 +980,7 @@ static int proc_unlinkurb(struct dev_state *ps, void __user *arg) as = async_getpending(ps, arg); if (!as) return -EINVAL; - usb_unlink_urb(as->urb); + usb_kill_urb(as->urb); return 0; } @@ -1006,15 +1022,15 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) int ret; add_wait_queue(&ps->wait, &wait); - while (connected(dev)) { + for (;;) { __set_current_state(TASK_INTERRUPTIBLE); if ((as = async_getcompleted(ps))) break; if (signal_pending(current)) break; - up(&dev->serialize); + usb_unlock_device(dev); schedule(); - down(&dev->serialize); + usb_lock_device(dev); } remove_wait_queue(&ps->wait, &wait); set_current_state(TASK_RUNNING); @@ -1118,7 +1134,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) } if (ps->dev->state != USB_STATE_CONFIGURED) - retval = -ENODEV; + retval = -EHOSTUNREACH; else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno))) retval = -EINVAL; else switch (ctrl.ioctl_code) { @@ -1137,7 +1153,11 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) /* let kernel drivers try to (re)bind to the interface */ case USBDEVFS_CONNECT: + usb_unlock_device(ps->dev); + usb_lock_all_devices(); bus_rescan_devices(intf->dev.bus); + usb_unlock_all_devices(); + usb_lock_device(ps->dev); break; /* talk directly to the interface's driver */ @@ -1180,9 +1200,9 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd if (!(file->f_mode & FMODE_WRITE)) return -EPERM; - down(&dev->serialize); + usb_lock_device(dev); if (!connected(dev)) { - up(&dev->serialize); + usb_unlock_device(dev); return -ENODEV; } @@ -1282,7 +1302,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ret = proc_ioctl(ps, p); break; } - up(&dev->serialize); + usb_unlock_device(dev); if (ret >= 0) inode->i_atime = CURRENT_TIME; return ret; @@ -1302,7 +1322,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai return mask; } -struct file_operations usbdevfs_device_file_operations = { +struct file_operations usbfs_device_file_operations = { .llseek = usbdev_lseek, .read = usbdev_read, .poll = usbdev_poll, diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index e7a7ba513..0a273a8fe 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -38,14 +38,6 @@ /*-------------------------------------------------------------------------*/ -static void hcd_pci_release(struct usb_bus *bus) -{ - struct usb_hcd *hcd = bus->hcpriv; - - if (hcd) - hcd->driver->hcd_free(hcd); -} - /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -65,7 +57,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) { struct hc_driver *driver; unsigned long resource, len; - void *base; + void __iomem *base; struct usb_hcd *hcd; int retval, region; char buf [8], *bufp = buf; @@ -78,12 +70,15 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) if (pci_enable_device (dev) < 0) return -ENODEV; + dev->current_state = 0; + dev->dev.power.power_state = 0; if (!dev->irq) { dev_err (&dev->dev, "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", pci_name(dev)); - return -ENODEV; + retval = -ENODEV; + goto done; } if (driver->flags & HCD_MEMORY) { // EHCI, OHCI @@ -92,7 +87,8 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) len = pci_resource_len (dev, 0); if (!request_mem_region (resource, len, driver->description)) { dev_dbg (&dev->dev, "controller already in use\n"); - return -EBUSY; + retval = -EBUSY; + goto done; } base = ioremap_nocache (resource, len); if (base == NULL) { @@ -102,7 +98,7 @@ clean_1: release_mem_region (resource, len); dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval); - return retval; + goto done; } } else { // UHCI @@ -119,9 +115,10 @@ clean_1: } if (region == PCI_ROM_RESOURCE) { dev_dbg (&dev->dev, "no i/o regions available\n"); - return -EBUSY; + retval = -EBUSY; + goto done; } - base = (void *) resource; + base = (void __iomem *) resource; } // driver->reset(), later on, will transfer device from @@ -139,7 +136,7 @@ clean_2: release_region (resource, len); dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval); - return retval; + goto done; } } // hcd zeroed everything @@ -160,7 +157,7 @@ clean_2: if ((retval = hcd_buffer_create (hcd)) != 0) { clean_3: - driver->hcd_free (hcd); + kfree (hcd); goto clean_2; } @@ -188,14 +185,14 @@ clean_3: } hcd->irq = dev->irq; - dev_info (hcd->self.controller, "irq %s, %s %p\n", bufp, + dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp, (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", - base); + resource); usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; + hcd->self.release = &usb_hcd_release; hcd->self.hcpriv = (void *) hcd; - hcd->self.release = &hcd_pci_release; init_timer (&hcd->rh_timer); INIT_LIST_HEAD (&hcd->dev_list); @@ -207,6 +204,9 @@ clean_3: usb_hcd_pci_remove (dev); } +done: + if (retval != 0) + pci_disable_device (dev); return retval; } EXPORT_SYMBOL (usb_hcd_pci_probe); @@ -260,12 +260,26 @@ void usb_hcd_pci_remove (struct pci_dev *dev) } usb_deregister_bus (&hcd->self); + + pci_disable_device(dev); } EXPORT_SYMBOL (usb_hcd_pci_remove); #ifdef CONFIG_PM +static char __attribute_used__ *pci_state(u32 state) +{ + switch (state) { + case 0: return "D0"; + case 1: return "D1"; + case 2: return "D2"; + case 3: return "D3hot"; + case 4: return "D3cold"; + } + return NULL; +} + /** * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD * @dev: USB Host Controller being suspended @@ -286,45 +300,82 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) * PM-sensitive HCDs may already have done this. */ has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); - if (has_pci_pm) - dev_dbg(hcd->self.controller, "suspend D%d --> D%d\n", - dev->current_state, state); + if (state > 4) + state = 4; switch (hcd->state) { - case USB_STATE_HALT: - dev_dbg (hcd->self.controller, "halted; hcd not suspended\n"); - break; - case HCD_STATE_SUSPENDED: - dev_dbg (hcd->self.controller, "hcd already suspended\n"); - break; - default: + + /* entry if root hub wasn't yet suspended ... from sysfs, + * without autosuspend, or if USB_SUSPEND isn't configured. + */ + case USB_STATE_RUNNING: + hcd->state = USB_STATE_QUIESCING; retval = hcd->driver->suspend (hcd, state); - if (retval) + if (retval) { dev_dbg (hcd->self.controller, "suspend fail, retval %d\n", retval); - else { - hcd->state = HCD_STATE_SUSPENDED; - pci_save_state (dev, hcd->pci_state); + break; + } + hcd->state = HCD_STATE_SUSPENDED; + /* FALLTHROUGH */ + + /* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the + * controller and/or root hub will already have been suspended, + * but it won't be ready for a PCI resume call. + * + * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will + * have been called, otherwise root hub timers still run ... + */ + case HCD_STATE_SUSPENDED: + if (state <= dev->current_state) + break; + + /* no DMA or IRQs except in D0 */ + if (!dev->current_state) { + pci_save_state (dev); + pci_disable_device (dev); + free_irq (hcd->irq, hcd); + } + + if (!has_pci_pm) { + dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n"); + break; + } + + /* POLICY: ignore D1/D2/D3hot differences; + * we know D3hot will always work. + */ + retval = pci_set_power_state (dev, state); + if (retval < 0 && state < 3) { + retval = pci_set_power_state (dev, 3); + if (retval == 0) + state = 3; + } + if (retval == 0) { + dev_dbg (hcd->self.controller, "--> PCI %s\n", + pci_state(dev->current_state)); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, state, hcd->remote_wakeup); pci_enable_wake (dev, 4, hcd->remote_wakeup); #endif - /* no DMA or IRQs except in D0 */ - pci_disable_device (dev); - free_irq (hcd->irq, hcd); - - if (has_pci_pm) - retval = pci_set_power_state (dev, state); - dev->dev.power.power_state = state; - if (retval < 0) { - dev_dbg (&dev->dev, - "PCI suspend fail, %d\n", - retval); - (void) usb_hcd_pci_resume (dev); - } + } else if (retval < 0) { + dev_dbg (&dev->dev, "PCI %s suspend fail, %d\n", + pci_state(state), retval); + (void) usb_hcd_pci_resume (dev); + break; } + break; + default: + dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n", + hcd->state); + retval = -EINVAL; + break; } + + /* update power_state **ONLY** to make sysfs happier */ + if (retval == 0) + dev->dev.power.power_state = state; return retval; } EXPORT_SYMBOL (usb_hcd_pci_suspend); @@ -342,16 +393,18 @@ int usb_hcd_pci_resume (struct pci_dev *dev) int has_pci_pm; hcd = pci_get_drvdata(dev); - has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); - if (has_pci_pm) - dev_dbg(hcd->self.controller, "resume from state D%d\n", - dev->current_state); - if (hcd->state != HCD_STATE_SUSPENDED) { dev_dbg (hcd->self.controller, "can't resume, not suspended!\n"); - return -EL3HLT; + return 0; } + has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); + + /* D3cold resume isn't usually reported this way... */ + dev_dbg(hcd->self.controller, "resume from PCI %s%s\n", + pci_state(dev->current_state), + has_pci_pm ? "" : " (legacy)"); + hcd->state = USB_STATE_RESUMING; if (has_pci_pm) @@ -364,8 +417,8 @@ int usb_hcd_pci_resume (struct pci_dev *dev) "can't restore IRQ after resume!\n"); return retval; } - pci_set_master (dev); - pci_restore_state (dev, hcd->pci_state); + hcd->saw_irq = 0; + pci_restore_state (dev); #ifdef CONFIG_USB_SUSPEND pci_enable_wake (dev, dev->current_state, 0); pci_enable_wake (dev, 4, 0); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index cd2268ad1..dc67f3ddf 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -435,8 +435,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) /* non-generic request */ if (HCD_IS_SUSPENDED (hcd->state)) urb->status = -EAGAIN; - else if (!HCD_IS_RUNNING (hcd->state)) - urb->status = -ENODEV; else urb->status = hcd->driver->hub_control (hcd, typeReq, wValue, wIndex, @@ -445,13 +443,16 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) error: /* "protocol stall" on error */ urb->status = -EPIPE; - dev_dbg (hcd->self.controller, "unsupported hub control message (maxchild %d)\n", - urb->dev->maxchild); } if (urb->status) { urb->actual_length = 0; - dev_dbg (hcd->self.controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n", - typeReq, wValue, wIndex, wLength, urb->status); + if (urb->status != -EPIPE) { + dev_dbg (hcd->self.controller, + "CTRL: TypeReq=0x%x val=0x%x " + "idx=0x%x len=%d ==> %d\n", + typeReq, wValue, wIndex, + wLength, urb->status); + } } if (bufp) { if (urb->transfer_buffer_length < len) @@ -478,6 +479,11 @@ error: /* * Root Hub interrupt transfers are synthesized with a timer. * Completions are called in_interrupt() but not in_irq(). + * + * Note: some root hubs (including common UHCI based designs) can't + * correctly issue port change IRQs. They're the ones that _need_ a + * timer; most other root hubs don't. Some systems could save a + * lot of battery power by eliminating these root hub timer IRQs. */ static void rh_report_status (unsigned long ptr); @@ -487,10 +493,7 @@ static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) int len = 1 + (urb->dev->maxchild / 8); /* rh_timer protected by hcd_data_lock */ - if (hcd->rh_timer.data - || urb->status != -EINPROGRESS - || urb->transfer_buffer_length < len - || !HCD_IS_RUNNING (hcd->state)) { + if (hcd->rh_timer.data || urb->transfer_buffer_length < len) { dev_dbg (hcd->self.controller, "not queuing rh status urb, stat %d\n", urb->status); @@ -529,19 +532,19 @@ static void rh_report_status (unsigned long ptr) return; } - if (!HCD_IS_SUSPENDED (hcd->state)) - length = hcd->driver->hub_status_data ( - hcd, urb->transfer_buffer); - /* complete the status urb, or retrigger the timer */ spin_lock (&hcd_data_lock); - if (length > 0) { - hcd->rh_timer.data = 0; - urb->actual_length = length; - urb->status = 0; - urb->hcpriv = NULL; - } else - mod_timer (&hcd->rh_timer, jiffies + HZ/4); + if (urb->dev->state == USB_STATE_CONFIGURED) { + length = hcd->driver->hub_status_data ( + hcd, urb->transfer_buffer); + if (length > 0) { + hcd->rh_timer.data = 0; + urb->actual_length = length; + urb->status = 0; + urb->hcpriv = NULL; + } else + mod_timer (&hcd->rh_timer, jiffies + HZ/4); + } spin_unlock (&hcd_data_lock); spin_unlock (&urb->lock); @@ -572,18 +575,34 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) /*-------------------------------------------------------------------------*/ -int usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) +static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) { unsigned long flags; /* note: always a synchronous unlink */ - del_timer_sync (&hcd->rh_timer); - hcd->rh_timer.data = 0; + if ((unsigned long) urb == hcd->rh_timer.data) { + del_timer_sync (&hcd->rh_timer); + hcd->rh_timer.data = 0; + + local_irq_save (flags); + urb->hcpriv = NULL; + usb_hcd_giveback_urb (hcd, urb, NULL); + local_irq_restore (flags); + + } else if (usb_pipeendpoint(urb->pipe) == 0) { + spin_lock_irq(&urb->lock); /* from usb_kill_urb */ + ++urb->reject; + spin_unlock_irq(&urb->lock); + + wait_event(usb_kill_urb_queue, + atomic_read(&urb->use_count) == 0); + + spin_lock_irq(&urb->lock); + --urb->reject; + spin_unlock_irq(&urb->lock); + } else + return -EINVAL; - local_irq_save (flags); - urb->hcpriv = NULL; - usb_hcd_giveback_urb (hcd, urb, NULL); - local_irq_restore (flags); return 0; } @@ -708,6 +727,7 @@ int usb_register_bus(struct usb_bus *bus) bus->busnum = busnum; } else { printk (KERN_ERR "%s: too many buses\n", usbcore_name); + up(&usb_bus_list_lock); return -E2BIG; } @@ -790,14 +810,16 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64; retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { + usb_dev->bus->root_hub = NULL; + up (&usb_bus_list_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", usb_dev->dev.bus_id, retval); return (retval < 0) ? retval : -EMSGSIZE; } - down (&usb_dev->serialize); + usb_lock_device (usb_dev); retval = usb_new_device (usb_dev); - up (&usb_dev->serialize); + usb_unlock_device (usb_dev); if (retval) { usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", @@ -1083,13 +1105,17 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) spin_lock_irqsave (&hcd_data_lock, flags); if (unlikely (urb->reject)) status = -EPERM; - else if (HCD_IS_RUNNING (hcd->state) && - hcd->state != USB_STATE_QUIESCING) { + else switch (hcd->state) { + case USB_STATE_RUNNING: + case USB_STATE_RESUMING: usb_get_dev (urb->dev); list_add_tail (&urb->urb_list, &dev->urb_list); status = 0; - } else + break; + default: status = -ESHUTDOWN; + break; + } spin_unlock_irqrestore (&hcd_data_lock, flags); if (status) { INIT_LIST_HEAD (&urb->urb_list); @@ -1172,8 +1198,8 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) { int value; - if (urb == (struct urb *) hcd->rh_timer.data) - value = usb_rh_status_dequeue (hcd, urb); + if (urb->dev == hcd->self.root_hub) + value = usb_rh_urb_dequeue (hcd, urb); else { /* The only reason an HCD might fail this call is if @@ -1261,7 +1287,7 @@ static int hcd_unlink_urb (struct urb *urb, int status) * never get completion IRQs ... maybe even the ones we need to * finish unlinking the initial failed usb_set_address(). */ - if (!hcd->saw_irq) { + if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { dev_warn (hcd->self.controller, "Unlink after no-IRQ? " "Different ACPI or APIC settings may help." "\n"); @@ -1311,13 +1337,10 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) rescan: /* (re)block new requests, as best we can */ - if (endpoint & USB_DIR_IN) { - usb_endpoint_halt (udev, epnum, 0); + if (endpoint & USB_DIR_IN) udev->epmaxpacketin [epnum] = 0; - } else { - usb_endpoint_halt (udev, epnum, 1); + else udev->epmaxpacketout [epnum] = 0; - } /* then kill any current requests */ spin_lock (&hcd_data_lock); @@ -1407,6 +1430,45 @@ static int hcd_hub_resume (struct usb_bus *bus) /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_USB_OTG + +/** + * usb_bus_start_enum - start immediate enumeration (for OTG) + * @bus: the bus (must use hcd framework) + * @port: 1-based number of port; usually bus->otg_port + * Context: in_interrupt() + * + * Starts enumeration, with an immediate reset followed later by + * khubd identifying and possibly configuring the device. + * This is needed by OTG controller drivers, where it helps meet + * HNP protocol timing requirements for starting a port reset. + */ +int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num) +{ + struct usb_hcd *hcd; + int status = -EOPNOTSUPP; + + /* NOTE: since HNP can't start by grabbing the bus's address0_sem, + * boards with root hubs hooked up to internal devices (instead of + * just the OTG port) may need more attention to resetting... + */ + hcd = container_of (bus, struct usb_hcd, self); + if (port_num && hcd->driver->start_port_reset) + status = hcd->driver->start_port_reset(hcd, port_num); + + /* run khubd shortly after (first) root port reset finishes; + * it may issue others, until at least 50 msecs have passed. + */ + if (status == 0) + mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10)); + return status; +} +EXPORT_SYMBOL (usb_bus_start_enum); + +#endif + +/*-------------------------------------------------------------------------*/ + /* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup. * we're guaranteed that the device is fully quiesced. also, that each * endpoint has been hcd_endpoint_disabled. @@ -1534,13 +1596,12 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) struct usb_hcd *hcd = __hcd; int start = hcd->state; - if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ + if (start == USB_STATE_HALT) return IRQ_NONE; - - hcd->saw_irq = 1; if (hcd->driver->irq (hcd, r) == IRQ_NONE) return IRQ_NONE; + hcd->saw_irq = 1; if (hcd->state != start && hcd->state == USB_STATE_HALT) usb_hc_died (hcd); return IRQ_HANDLED; @@ -1549,22 +1610,6 @@ EXPORT_SYMBOL (usb_hcd_irq); /*-------------------------------------------------------------------------*/ -static void hcd_panic (void *_hcd) -{ - struct usb_hcd *hcd = _hcd; - struct usb_device *hub = hcd->self.root_hub; - unsigned i; - - /* hc's root hub is removed later removed in hcd->stop() */ - down (&hub->serialize); - usb_set_device_state(hub, USB_STATE_NOTATTACHED); - for (i = 0; i < hub->maxchild; i++) { - if (hub->children [i]) - usb_disconnect (&hub->children [i]); - } - up (&hub->serialize); -} - /** * usb_hc_died - report abnormal shutdown of a host controller (bus glue) * @hcd: pointer to the HCD representing the controller @@ -1577,9 +1622,19 @@ void usb_hc_died (struct usb_hcd *hcd) { dev_err (hcd->self.controller, "HC died; cleaning up\n"); - /* clean up old urbs and devices; needs a task context */ - INIT_WORK (&hcd->work, hcd_panic, hcd); - (void) schedule_work (&hcd->work); + /* make khubd clean up old urbs and devices */ + usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED); + mod_timer(&hcd->rh_timer, jiffies); } EXPORT_SYMBOL (usb_hc_died); +/*-------------------------------------------------------------------------*/ + +void usb_hcd_release(struct usb_bus *bus) +{ + struct usb_hcd *hcd; + + hcd = container_of (bus, struct usb_hcd, self); + kfree(hcd); +} +EXPORT_SYMBOL (usb_hcd_release); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 89b6fc2e3..12a2b9f80 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -67,7 +67,6 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ struct timer_list rh_timer; /* drives root hub */ struct list_head dev_list; /* devices on this bus */ - struct work_struct work; /* * hardware info/state @@ -77,11 +76,10 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ unsigned can_wakeup:1; /* hw supports wakeup? */ unsigned remote_wakeup:1;/* sw should use wakeup? */ int irq; /* irq allocated */ - void *regs; /* device memory/io */ + void __iomem *regs; /* device memory/io */ #ifdef CONFIG_PCI int region; /* pci region for regs */ - u32 pci_state [16]; /* for PM state save */ #endif #define HCD_BUFFER_POOLS 4 @@ -193,8 +191,13 @@ struct hc_driver { int (*get_frame_number) (struct usb_hcd *hcd); /* memory lifecycle */ + /* Note: The absence of hcd_free reflects a temporary situation; + * in the near future hcd_alloc will disappear as well and all + * allocations/deallocations will be handled by usbcore. For the + * moment, drivers are required to return a pointer that the core + * can pass to kfree, i.e., the struct usb_hcd must be the _first_ + * member of a larger driver-specific structure. */ struct usb_hcd *(*hcd_alloc) (void); - void (*hcd_free) (struct usb_hcd *hcd); /* manage i/o requests, device state */ int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb, @@ -212,11 +215,11 @@ struct hc_driver { char *buf, u16 wLength); int (*hub_suspend)(struct usb_hcd *); int (*hub_resume)(struct usb_hcd *); + int (*start_port_reset)(struct usb_hcd *, unsigned port_num); }; extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); extern void usb_bus_init (struct usb_bus *bus); -extern int usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb); #ifdef CONFIG_PCI struct pci_dev; @@ -362,6 +365,11 @@ static inline int hcd_register_root (struct usb_device *usb_dev, return usb_register_root_hub (usb_dev, hcd->self.controller); } +extern void usb_hcd_release (struct usb_bus *); + +extern void usb_set_device_state(struct usb_device *udev, + enum usb_device_state new_state); + /*-------------------------------------------------------------------------*/ /* exported only within usbcore */ @@ -376,8 +384,6 @@ extern void usb_bus_put (struct usb_bus *bus); extern int usb_find_interface_driver (struct usb_device *dev, struct usb_interface *interface); -#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) - #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) /* diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b13fe4040..161c52f2e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -36,15 +36,18 @@ #include "hcd.h" #include "hub.h" -/* Protect all struct usb_device state members */ +/* Protect struct usb_device->state and ->children members + * Note: Both are also protected by ->serialize, except that ->state can + * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED; -/* Wakes up khubd */ +/* khubd's worklist and its lock */ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; - static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ +/* Wakes up khubd */ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); + static pid_t khubd_pid = 0; /* PID of khubd */ static DECLARE_COMPLETION(khubd_exited); @@ -53,6 +56,31 @@ static int blinkenlights = 0; module_param (blinkenlights, bool, S_IRUGO); MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); +/* + * As of 2.6.10 we introduce a new USB device initialization scheme which + * closely resembles the way Windows works. Hopefully it will be compatible + * with a wider range of devices than the old scheme. However some previously + * working devices may start giving rise to "device not accepting address" + * errors; if that happens the user can try the old scheme by adjusting the + * following module parameters. + * + * For maximum flexibility there are two boolean parameters to control the + * hub driver's behavior. On the first initialization attempt, if the + * "old_scheme_first" parameter is set then the old scheme will be used, + * otherwise the new scheme is used. If that fails and "use_both_schemes" + * is set, then the driver will make another attempt, using the other scheme. + */ +static int old_scheme_first = 0; +module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(old_scheme_first, + "start with the old device initialization scheme"); + +static int use_both_schemes = 0; +module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(use_both_schemes, + "try the other device initialization scheme if the " + "first one fails"); + #ifdef DEBUG static inline char *portspeed (int portstatus) @@ -75,9 +103,17 @@ static inline struct device *hubdev (struct usb_device *hdev) /* USB 2.0 spec Section 11.24.4.5 */ static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) { - return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT); + int i, ret; + + for (i = 0; i < 3; i++) { + ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, + USB_DT_HUB << 8, 0, data, size, + HZ * USB_CTRL_GET_TIMEOUT); + if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) + return ret; + } + return -EINVAL; } /* @@ -143,7 +179,7 @@ static void led_work (void *__hub) unsigned changed = 0; int cursor = -1; - if (hdev->state != USB_STATE_CONFIGURED) + if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing) return; for (i = 0; i < hub->descriptor->bNbrPorts; i++) { @@ -226,6 +262,19 @@ static int get_port_status(struct usb_device *hdev, int port, data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); } +static void kick_khubd(struct usb_hub *hub) +{ + unsigned long flags; + + spin_lock_irqsave(&hub_event_lock, flags); + if (list_empty(&hub->event_list)) { + list_add_tail(&hub->event_list, &hub_event_list); + wake_up(&khubd_wait); + } + spin_unlock_irqrestore(&hub_event_lock, flags); +} + + /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb, struct pt_regs *regs) { @@ -261,14 +310,12 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) hub->nerrors = 0; /* Something happened, let khubd figure it out */ - spin_lock(&hub_event_lock); - if (list_empty(&hub->event_list)) { - list_add_tail(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock(&hub_event_lock); + kick_khubd(hub); resubmit: + if (hub->quiescing) + return; + if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 && status != -ENODEV && status != -EPERM) dev_err (&hub->intf->dev, "resubmit --> %d\n", status); @@ -381,6 +428,33 @@ static void hub_power_on(struct usb_hub *hub) msleep(hub->descriptor->bPwrOn2PwrGood * 2); } +static void hub_quiesce(struct usb_hub *hub) +{ + /* stop khubd and related activity */ + hub->quiescing = 1; + usb_kill_urb(hub->urb); + if (hub->has_indicators) + cancel_delayed_work(&hub->leds); + if (hub->has_indicators || hub->tt.hub) + flush_scheduled_work(); +} + +static void hub_activate(struct usb_hub *hub) +{ + int status; + + hub->quiescing = 0; + status = usb_submit_urb(hub->urb, GFP_NOIO); + if (status < 0) + dev_err(&hub->intf->dev, "activate --> %d\n", status); + if (hub->has_indicators && blinkenlights) + schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); + + /* scan all ports ASAP */ + hub->event_bits[0] = ~0; + kick_khubd(hub); +} + static int hub_hub_status(struct usb_hub *hub, u16 *status, u16 *change) { @@ -576,7 +650,7 @@ static int hub_configure(struct usb_hub *hub, dev_dbg(hub_dev, "%sover-current condition exists\n", (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); - /* Start the interrupt endpoint */ + /* set up the interrupt endpoint */ pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); @@ -594,24 +668,14 @@ static int hub_configure(struct usb_hub *hub, hub, endpoint->bInterval); hub->urb->transfer_dma = hub->buffer_dma; hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - ret = usb_submit_urb(hub->urb, GFP_KERNEL); - if (ret) { - message = "couldn't submit status urb"; - goto fail; - } - /* Wake up khubd */ - wake_up(&khubd_wait); - - /* maybe start cycling the hub leds */ - if (hub->has_indicators && blinkenlights) { - set_port_led(hdev, 1, HUB_LED_GREEN); + /* maybe cycle the hub leds */ + if (hub->has_indicators && blinkenlights) hub->indicator [0] = INDICATOR_CYCLE; - schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); - } hub_power_on(hub); - + hub->change_bits[0] = ~0; + hub_activate(hub); return 0; fail: @@ -637,22 +701,14 @@ static void hub_disconnect(struct usb_interface *intf) usb_set_intfdata (intf, NULL); - if (hub->urb) { - usb_kill_urb(hub->urb); - usb_free_urb(hub->urb); - hub->urb = NULL; - } + hub_quiesce(hub); + usb_free_urb(hub->urb); + hub->urb = NULL; spin_lock_irq(&hub_event_lock); list_del_init(&hub->event_list); spin_unlock_irq(&hub_event_lock); - /* assuming we used keventd, it must quiesce too */ - if (hub->has_indicators) - cancel_delayed_work (&hub->leds); - if (hub->has_indicators || hub->tt.hub) - flush_scheduled_work (); - if (hub->descriptor) { kfree(hub->descriptor); hub->descriptor = NULL; @@ -772,54 +828,74 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) } } -static int hub_reset(struct usb_hub *hub) +/* caller has locked the hub device */ +static void hub_pre_reset(struct usb_device *hdev) { - struct usb_device *hdev = hub->hdev; + struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]); int i; - /* Disconnect any attached devices */ - for (i = 0; i < hub->descriptor->bNbrPorts; i++) { + for (i = 0; i < hdev->maxchild; ++i) { if (hdev->children[i]) usb_disconnect(&hdev->children[i]); } + hub_quiesce(hub); +} - /* Attempt to reset the hub */ - if (hub->urb) - usb_kill_urb(hub->urb); - else - return -1; - - if (usb_reset_device(hdev)) - return -1; - - hub->urb->dev = hdev; - if (usb_submit_urb(hub->urb, GFP_KERNEL)) - return -1; +/* caller has locked the hub device */ +static void hub_post_reset(struct usb_device *hdev) +{ + struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]); + hub_activate(hub); hub_power_on(hub); - - return 0; } -/* FIXME! This routine should be subsumed into hub_reset */ -static void hub_start_disconnect(struct usb_device *hdev) + +/* grab device/port lock, returning index of that port (zero based). + * protects the upstream link used by this device from concurrent + * tree operations like suspend, resume, reset, and disconnect, which + * apply to everything downstream of a given port. + */ +static int locktree(struct usb_device *udev) { - struct usb_device *parent = hdev->parent; - int i; + int t; + struct usb_device *hdev; - /* Find the device pointer to disconnect */ - if (parent) { - for (i = 0; i < parent->maxchild; i++) { - if (parent->children[i] == hdev) { - usb_disconnect(&parent->children[i]); - return; - } - } + if (!udev) + return -ENODEV; + + /* root hub is always the first lock in the series */ + hdev = udev->parent; + if (!hdev) { + usb_lock_device(udev); + return 0; } - dev_err(&hdev->dev, "cannot disconnect hub!\n"); -} + /* on the path from root to us, lock everything from + * top down, dropping parent locks when not needed + */ + t = locktree(hdev); + if (t < 0) + return t; + for (t = 0; t < hdev->maxchild; t++) { + if (hdev->children[t] == udev) { + /* everything is fail-fast once disconnect + * processing starts + */ + if (udev->state == USB_STATE_NOTATTACHED) + break; + /* when everyone grabs locks top->bottom, + * non-overlapping work may be concurrent + */ + down(&udev->serialize); + up(&hdev->serialize); + return t; + } + } + usb_unlock_device(hdev); + return -ENODEV; +} static void recursively_mark_NOTATTACHED(struct usb_device *udev) { @@ -833,21 +909,24 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev) } /** - * usb_set_device_state - change a device's current state (usbcore-internal) + * usb_set_device_state - change a device's current state (usbcore, hcds) * @udev: pointer to device whose state should be changed * @new_state: new state value to be stored * - * udev->state is _not_ protected by the udev->serialize semaphore. This + * udev->state is _not_ fully protected by the device lock. Although + * most transitions are made only while holding the lock, the state can + * can change to USB_STATE_NOTATTACHED at almost any time. This * is so that devices can be marked as disconnected as soon as possible, - * without having to wait for the semaphore to be released. Instead, - * changes to the state must be protected by the device_state_lock spinlock. + * without having to wait for any semaphores to be released. As a result, + * all changes to any device's state must be protected by the + * device_state_lock spinlock. * * Once a device has been added to the device tree, all changes to its state * should be made using this routine. The state should _not_ be set directly. * * If udev->state is already USB_STATE_NOTATTACHED then no change is made. * Otherwise udev->state is set to new_state, and if new_state is - * USB_STATE_NOTATTACHED then all of udev's descendant's states are also set + * USB_STATE_NOTATTACHED then all of udev's descendants' states are also set * to USB_STATE_NOTATTACHED. */ void usb_set_device_state(struct usb_device *udev, @@ -864,6 +943,7 @@ void usb_set_device_state(struct usb_device *udev, recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); } +EXPORT_SYMBOL(usb_set_device_state); static void choose_address(struct usb_device *udev) @@ -900,8 +980,9 @@ static void release_address(struct usb_device *udev) * @pdev: pointer to device being disconnected * Context: !in_interrupt () * - * Something got disconnected. Get rid of it, and all of its children. - * If *pdev is a normal device then the parent hub should be locked. + * Something got disconnected. Get rid of it and all of its children. + * + * If *pdev is a normal device then the parent hub must already be locked. * If *pdev is a root hub then this routine will acquire the * usb_bus_list_lock on behalf of the caller. * @@ -921,14 +1002,17 @@ void usb_disconnect(struct usb_device **pdev) } /* mark the device as inactive, so any further urb submissions for - * this device will fail. + * this device (and any of its children) will fail immediately. + * this quiesces everyting except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); /* lock the bus list on behalf of HCDs unregistering their root hubs */ - if (!udev->parent) + if (!udev->parent) { down(&usb_bus_list_lock); - down(&udev->serialize); + usb_lock_device(udev); + } else + down(&udev->serialize); dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); @@ -940,6 +1024,7 @@ void usb_disconnect(struct usb_device **pdev) /* deallocate hcd/hardware state ... nuking all pending urbs and * cleaning up all state associated with the current configuration + * so that the hardware is now fully quiesced. */ usb_disable_device(udev, 0); @@ -957,9 +1042,11 @@ void usb_disconnect(struct usb_device **pdev) *pdev = NULL; spin_unlock_irq(&device_state_lock); - up(&udev->serialize); - if (!udev->parent) + if (!udev->parent) { + usb_unlock_device(udev); up(&usb_bus_list_lock); + } else + up(&udev->serialize); device_unregister(&udev->dev); } @@ -982,11 +1069,19 @@ static int choose_configuration(struct usb_device *udev) ->altsetting->desc; if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) continue; - /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ + /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS. + * MSFT needs this to be the first config; never use + * it as the default unless Linux has host-side RNDIS. + * A second config would ideally be CDC-Ethernet, but + * may instead be the "vendor specific" CDC subset + * long used by ARM Linux for sa1100 or pxa255. + */ if (desc->bInterfaceClass == USB_CLASS_COMM && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff) + && desc->bInterfaceProtocol == 0xff) { + c = udev->config[1].desc.bConfigurationValue; continue; + } c = udev->config[i].desc.bConfigurationValue; break; } @@ -1016,6 +1111,10 @@ static inline void show_string(struct usb_device *udev, char *id, int index) {} #endif +#ifdef CONFIG_USB_OTG +#include "otg_whitelist.h" +#endif + /** * usb_new_device - perform initial device setup (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) @@ -1065,6 +1164,79 @@ int usb_new_device(struct usb_device *udev) show_string(udev, "SerialNumber", udev->descriptor.iSerialNumber); +#ifdef CONFIG_USB_OTG + /* + * OTG-aware devices on OTG-capable root hubs may be able to use SRP, + * to wake us after we've powered off VBUS; and HNP, switching roles + * "host" to "peripheral". The OTG descriptor helps figure this out. + */ + if (!udev->bus->is_b_host + && udev->config + && udev->parent == udev->bus->root_hub) { + struct usb_otg_descriptor *desc = 0; + struct usb_bus *bus = udev->bus; + + /* descriptor may appear anywhere in config */ + if (__usb_get_extra_descriptor (udev->rawdescriptors[0], + udev->config[0].desc.wTotalLength, + USB_DT_OTG, (void **) &desc) == 0) { + if (desc->bmAttributes & USB_OTG_HNP) { + unsigned port; + struct usb_device *root = udev->parent; + + for (port = 0; port < root->maxchild; port++) { + if (root->children[port] == udev) + break; + } + port++; + + dev_info(&udev->dev, + "Dual-Role OTG device on %sHNP port\n", + (port == bus->otg_port) + ? "" : "non-"); + + /* enable HNP before suspend, it's simpler */ + if (port == bus->otg_port) + bus->b_hnp_enable = 1; + err = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, 0, + bus->b_hnp_enable + ? USB_DEVICE_B_HNP_ENABLE + : USB_DEVICE_A_ALT_HNP_SUPPORT, + 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); + if (err < 0) { + /* OTG MESSAGE: report errors here, + * customize to match your product. + */ + dev_info(&udev->dev, + "can't set HNP mode; %d\n", + err); + bus->b_hnp_enable = 0; + } + } + } + } + + if (!is_targeted(udev)) { + + /* Maybe it can talk to us, though we can't talk to it. + * (Includes HNP test device.) + */ + if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { + static int __usb_suspend_device (struct usb_device *, + int port, u32 state); + err = __usb_suspend_device(udev, + udev->bus->otg_port - 1, + PM_SUSPEND_MEM); + if (err < 0) + dev_dbg(&udev->dev, "HNP fail, %d\n", err); + } + err = -ENODEV; + goto fail; + } +#endif + /* put device-specific files into sysfs */ err = device_add (&udev->dev); if (err) { @@ -1127,7 +1299,8 @@ static int hub_port_status(struct usb_device *hdev, int port, #define PORT_RESET_TRIES 5 #define SET_ADDRESS_TRIES 2 #define GET_DESCRIPTOR_TRIES 2 -#define SET_CONFIG_TRIES 2 +#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) +#define USE_NEW_SCHEME(i) ((i) / 2 == old_scheme_first) #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ #define HUB_SHORT_RESET_TIME 10 @@ -1200,9 +1373,13 @@ static int hub_port_reset(struct usb_device *hdev, int port, status = hub_port_wait_reset(hdev, port, udev, delay); /* return on disconnect or reset */ - if (status == -ENOTCONN || status == 0) { + switch (status) { + case 0: + case -ENOTCONN: + case -ENODEV: clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_RESET); + /* FIXME need disconnect() for NOTATTACHED device */ usb_set_device_state(udev, status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); @@ -1226,9 +1403,10 @@ static int hub_port_disable(struct usb_device *hdev, int port) { int ret; - if (hdev->children[port]) + if (hdev->children[port]) { usb_set_device_state(hdev->children[port], USB_STATE_NOTATTACHED); + } ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE); if (ret) dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n", @@ -1237,9 +1415,530 @@ static int hub_port_disable(struct usb_device *hdev, int port) return ret; } +/* + * Disable a port and mark a logical connnect-change event, so that some + * time later khubd will disconnect() any existing usb_device on the port + * and will re-enumerate if there actually is a device attached. + */ +static void hub_port_logical_disconnect(struct usb_device *hdev, int port) +{ + struct usb_hub *hub; + + dev_dbg(hubdev(hdev), "logical disconnect on port %d\n", port + 1); + hub_port_disable(hdev, port); + + /* FIXME let caller ask to power down the port: + * - some devices won't enumerate without a VBUS power cycle + * - SRP saves power that way + * - usb_suspend_device(dev,PM_SUSPEND_DISK) + * That's easy if this hub can switch power per-port, and + * khubd reactivates the port later (timer, SRP, etc). + * Powerdown must be optional, because of reset/DFU. + */ + + hub = usb_get_intfdata(hdev->actconfig->interface[0]); + set_bit(port, hub->change_bits); + kick_khubd(hub); +} + + #ifdef CONFIG_USB_SUSPEND - /* no USB_SUSPEND yet! */ +/* + * Selective port suspend reduces power; most suspended devices draw + * less than 500 uA. It's also used in OTG, along with remote wakeup. + * All devices below the suspended port are also suspended. + * + * Devices leave suspend state when the host wakes them up. Some devices + * also support "remote wakeup", where the device can activate the USB + * tree above them to deliver data, such as a keypress or packet. In + * some cases, this wakes the USB host. + */ +static int hub_port_suspend(struct usb_device *hdev, int port) +{ + int status; + struct usb_device *udev; + + udev = hdev->children[port]; + // dev_dbg(hubdev(hdev), "suspend port %d\n", port + 1); + + /* enable remote wakeup when appropriate; this lets the device + * wake up the upstream hub (including maybe the root hub). + * + * NOTE: OTG devices may issue remote wakeup (or SRP) even when + * we don't explicitly enable it here. + */ + if (udev->actconfig + // && FIXME (remote wakeup enabled on this bus) + // ... currently assuming it's always appropriate + && (udev->actconfig->desc.bmAttributes + & USB_CONFIG_ATT_WAKEUP) != 0) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + if (status) + dev_dbg(&udev->dev, + "won't remote wakeup, status %d\n", + status); + } + + /* see 7.1.7.6 */ + status = set_port_feature(hdev, port + 1, USB_PORT_FEAT_SUSPEND); + if (status) { + dev_dbg(hubdev(hdev), + "can't suspend port %d, status %d\n", + port + 1, status); + /* paranoia: "should not happen" */ + (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* device has up to 10 msec to fully suspend */ + dev_dbg(&udev->dev, "usb suspend\n"); + udev->state = USB_STATE_SUSPENDED; + msleep(10); + } + return status; +} + +/* + * Devices on USB hub ports have only one "suspend" state, corresponding + * to ACPI D2 (PM_SUSPEND_MEM), "may cause the device to lose some context". + * State transitions include: + * + * - suspend, resume ... when the VBUS power link stays live + * - suspend, disconnect ... VBUS lost + * + * Once VBUS drop breaks the circuit, the port it's using has to go through + * normal re-enumeration procedures, starting with enabling VBUS power. + * Other than re-initializing the hub (plug/unplug, except for root hubs), + * Linux (2.6) currently has NO mechanisms to initiate that: no khubd + * timer, no SRP, no requests through sysfs. + */ +int __usb_suspend_device (struct usb_device *udev, int port, u32 state) +{ + int status; + + /* caller owns the udev device lock */ + if (port < 0) + return port; + + if (udev->state == USB_STATE_SUSPENDED + || udev->state == USB_STATE_NOTATTACHED) { + return 0; + } + + /* suspend interface drivers; if this is a hub, it + * suspends the child devices + */ + if (udev->actconfig) { + int i; + + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_driver *driver; + + intf = udev->actconfig->interface[i]; + if (state <= intf->dev.power.power_state) + continue; + if (!intf->dev.driver) + continue; + driver = to_usb_driver(intf->dev.driver); + + if (driver->suspend) { + status = driver->suspend(intf, state); + if (intf->dev.power.power_state != state + || status) + dev_err(&intf->dev, + "suspend %d fail, code %d\n", + state, status); + } + + /* only drivers with suspend() can ever resume(); + * and after power loss, even they won't. + * bus_rescan_devices() can rebind drivers later. + * + * FIXME the PM core self-deadlocks when unbinding + * drivers during suspend/resume ... everything grabs + * dpm_sem (not a spinlock, ugh). we want to unbind, + * since we know every driver's probe/disconnect works + * even for drivers that can't suspend. + */ + if (!driver->suspend || state > PM_SUSPEND_MEM) { +#if 1 + dev_warn(&intf->dev, "resume is unsafe!\n"); +#else + down_write(&usb_bus_type.rwsem); + device_release_driver(&intf->dev); + up_write(&usb_bus_type.rwsem); +#endif + } + } + } + + /* + * FIXME this needs port power off call paths too, to help force + * USB into the "generic" PM model. At least for devices on + * ports that aren't using ganged switching (usually root hubs). + * + * NOTE: SRP-capable links should adopt more aggressive poweroff + * policies (when HNP doesn't apply) once we have mechanisms to + * turn power back on! (Likely not before 2.7...) + */ + if (state > PM_SUSPEND_MEM) { + dev_warn(&udev->dev, "no poweroff yet, suspending instead\n"); + } + + /* "global suspend" of the HC-to-USB interface (root hub), or + * "selective suspend" of just one hub-device link. + */ + if (!udev->parent) { + struct usb_bus *bus = udev->bus; + if (bus && bus->op->hub_suspend) { + status = bus->op->hub_suspend (bus); + if (status == 0) + usb_set_device_state(udev, + USB_STATE_SUSPENDED); + } else + status = -EOPNOTSUPP; + } else + status = hub_port_suspend(udev->parent, port); + + return status; +} +EXPORT_SYMBOL(__usb_suspend_device); + +/** + * usb_suspend_device - suspend a usb device + * @udev: device that's no longer in active use + * @state: PM_SUSPEND_MEM to suspend + * Context: must be able to sleep; device not locked + * + * Suspends a USB device that isn't in active use, conserving power. + * Devices may wake out of a suspend, if anything important happens, + * using the remote wakeup mechanism. They may also be taken out of + * suspend by the host, using usb_resume_device(). It's also routine + * to disconnect devices while they are suspended. + * + * Suspending OTG devices may trigger HNP, if that's been enabled + * between a pair of dual-role devices. That will change roles, such + * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral. + * + * Returns 0 on success, else negative errno. + */ +int usb_suspend_device(struct usb_device *udev, u32 state) +{ + int port, status; + + port = locktree(udev); + if (port < 0) + return port; + + status = __usb_suspend_device(udev, port, state); + usb_unlock_device(udev); + return status; +} + +/* + * hardware resume signaling is finished, either because of selective + * resume (by host) or remote wakeup (by device) ... now see what changed + * in the tree that's rooted at this device. + */ +static int finish_port_resume(struct usb_device *udev) +{ + int status; + u16 devstatus; + + /* caller owns the udev device lock */ + dev_dbg(&udev->dev, "usb resume\n"); + + /* usb ch9 identifies four variants of SUSPENDED, based on what + * state the device resumes to. Linux currently won't see the + * first two on the host side; they'd be inside hub_port_init() + * during many timeouts, but khubd can't suspend until later. + */ + udev->state = udev->actconfig + ? USB_STATE_CONFIGURED + : USB_STATE_ADDRESS; + + /* 10.5.4.5 says be sure devices in the tree are still there. + * For now let's assume the device didn't go crazy on resume, + * and device drivers will know about any resume quirks. + */ + status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); + if (status < 0) + dev_dbg(&udev->dev, + "gone after usb resume? status %d\n", + status); + else if (udev->actconfig) { + unsigned i; + + le16_to_cpus(&devstatus); + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + if (status) { + dev_dbg(&udev->dev, "disable remote " + "wakeup, status %d\n", status); + status = 0; + } + } + + /* resume interface drivers; if this is a hub, it + * resumes the child devices + */ + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_driver *driver; + + intf = udev->actconfig->interface[i]; + if (intf->dev.power.power_state == PM_SUSPEND_ON) + continue; + if (!intf->dev.driver) { + /* FIXME maybe force to alt 0 */ + continue; + } + driver = to_usb_driver(intf->dev.driver); + + /* bus_rescan_devices() may rebind drivers */ + if (!driver->resume) + continue; + + /* can we do better than just logging errors? */ + status = driver->resume(intf); + if (intf->dev.power.power_state != PM_SUSPEND_ON + || status) + dev_dbg(&intf->dev, + "resume fail, state %d code %d\n", + intf->dev.power.power_state, status); + } + status = 0; + + } else if (udev->devnum <= 0) { + dev_dbg(&udev->dev, "bogus resume!\n"); + status = -EINVAL; + } + return status; +} + +static int +hub_port_resume(struct usb_device *hdev, int port) +{ + int status; + struct usb_device *udev; + + udev = hdev->children[port]; + // dev_dbg(hubdev(hdev), "resume port %d\n", port + 1); + + /* see 7.1.7.7; affects power usage, but not budgeting */ + status = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_SUSPEND); + if (status) { + dev_dbg(&hdev->actconfig->interface[0]->dev, + "can't resume port %d, status %d\n", + port + 1, status); + } else { + u16 devstatus; + u16 portchange; + + /* drive resume for at least 20 msec */ + dev_dbg(&udev->dev, "RESUME\n"); + msleep(25); + +#define LIVE_FLAGS ( USB_PORT_STAT_POWER \ + | USB_PORT_STAT_ENABLE \ + | USB_PORT_STAT_CONNECTION) + + /* Virtual root hubs can trigger on GET_PORT_STATUS to + * stop resume signaling. Then finish the resume + * sequence. + */ + devstatus = portchange = 0; + status = hub_port_status(hdev, port, + &devstatus, &portchange); + if (status < 0 + || (devstatus & LIVE_FLAGS) != LIVE_FLAGS + || (devstatus & USB_PORT_STAT_SUSPEND) != 0 + ) { + dev_dbg(&hdev->actconfig->interface[0]->dev, + "port %d status %04x.%04x after resume, %d\n", + port + 1, portchange, devstatus, status); + } else { + /* TRSMRCY = 10 msec */ + msleep(10); + status = finish_port_resume(udev); + } + } + if (status < 0) + hub_port_logical_disconnect(hdev, port); + + return status; +} + +static int hub_resume (struct usb_interface *intf); + +/** + * usb_resume_device - re-activate a suspended usb device + * @udev: device to re-activate + * Context: must be able to sleep; device not locked + * + * This will re-activate the suspended device, increasing power usage + * while letting drivers communicate again with its endpoints. + * USB resume explicitly guarantees that the power session between + * the host and the device is the same as it was when the device + * suspended. + * + * Returns 0 on success, else negative errno. + */ +int usb_resume_device(struct usb_device *udev) +{ + int port, status; + + port = locktree(udev); + if (port < 0) + return port; + + /* "global resume" of the HC-to-USB interface (root hub), or + * selective resume of one hub-to-device port + */ + if (!udev->parent) { + struct usb_bus *bus = udev->bus; + if (bus && bus->op->hub_resume) { + status = bus->op->hub_resume (bus); + } else + status = -EOPNOTSUPP; + if (status == 0) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_set_device_state (udev, USB_STATE_CONFIGURED); + status = hub_resume (udev + ->actconfig->interface[0]); + } + } else if (udev->state == USB_STATE_SUSPENDED) { + // NOTE this fails if parent is also suspended... + status = hub_port_resume(udev->parent, port); + } else { + status = 0; + } + if (status < 0) { + dev_dbg(&udev->dev, "can't resume, status %d\n", + status); + } + + usb_unlock_device(udev); + + /* rebind drivers that had no suspend() */ + if (status == 0) { + usb_lock_all_devices(); + bus_rescan_devices(&usb_bus_type); + usb_unlock_all_devices(); + } + return status; +} + +static int remote_wakeup(struct usb_device *udev) +{ + int status = 0; + + /* don't repeat RESUME sequence if this device + * was already woken up by some other task + */ + down(&udev->serialize); + if (udev->state == USB_STATE_SUSPENDED) { + dev_dbg(&udev->dev, "RESUME (wakeup)\n"); + /* TRSMRCY = 10 msec */ + msleep(10); + status = finish_port_resume(udev); + } + up(&udev->serialize); + return status; +} + +static int hub_suspend(struct usb_interface *intf, u32 state) +{ + struct usb_hub *hub = usb_get_intfdata (intf); + struct usb_device *hdev = hub->hdev; + unsigned port; + int status; + + /* stop khubd and related activity */ + hub_quiesce(hub); + + /* then suspend every port */ + for (port = 0; port < hdev->maxchild; port++) { + struct usb_device *udev; + + udev = hdev->children [port]; + if (!udev) + continue; + down(&udev->serialize); + status = __usb_suspend_device(udev, port, state); + up(&udev->serialize); + if (status < 0) + dev_dbg(&intf->dev, "suspend port %d --> %d\n", + port, status); + } + + intf->dev.power.power_state = state; + return 0; +} + +static int hub_resume(struct usb_interface *intf) +{ + struct usb_device *hdev = interface_to_usbdev(intf); + struct usb_hub *hub = usb_get_intfdata (intf); + unsigned port; + int status; + + if (intf->dev.power.power_state == PM_SUSPEND_ON) + return 0; + + for (port = 0; port < hdev->maxchild; port++) { + struct usb_device *udev; + u16 portstat, portchange; + + udev = hdev->children [port]; + status = hub_port_status(hdev, port, &portstat, &portchange); + if (status == 0) { + if (portchange & USB_PORT_STAT_C_SUSPEND) { + clear_port_feature(hdev, port + 1, + USB_PORT_FEAT_C_SUSPEND); + portchange &= ~USB_PORT_STAT_C_SUSPEND; + } + + /* let khubd handle disconnects etc */ + if (portchange) + continue; + } + + if (!udev || status < 0) + continue; + down (&udev->serialize); + if (portstat & USB_PORT_STAT_SUSPEND) + status = hub_port_resume(hdev, port); + else { + status = finish_port_resume(udev); + if (status < 0) { + dev_dbg(&intf->dev, "resume port %d --> %d\n", + port + 1, status); + hub_port_logical_disconnect(hdev, port); + } + } + up(&udev->serialize); + } + intf->dev.power.power_state = PM_SUSPEND_ON; + + hub_activate(hub); + return 0; +} #else /* !CONFIG_USB_SUSPEND */ @@ -1325,20 +2024,30 @@ static int hub_port_debounce(struct usb_device *hdev, int port) return portstatus; } +#define usb_sndaddr0pipe() (PIPE_CONTROL << 30) +#define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) + static int hub_set_address(struct usb_device *udev) { int retval; if (udev->devnum == 0) return -EINVAL; - if (udev->state != USB_STATE_DEFAULT && - udev->state != USB_STATE_ADDRESS) + if (udev->state == USB_STATE_ADDRESS) + return 0; + if (udev->state != USB_STATE_DEFAULT) return -EINVAL; - retval = usb_control_msg(udev, (PIPE_CONTROL << 30) /* Address 0 */, + retval = usb_control_msg(udev, usb_sndaddr0pipe(), USB_REQ_SET_ADDRESS, 0, udev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - if (retval == 0) + if (retval == 0) { + int m = udev->epmaxpacketin[0]; + usb_set_device_state(udev, USB_STATE_ADDRESS); + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT); + udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = m; + } return retval; } @@ -1352,7 +2061,8 @@ static int hub_set_address(struct usb_device *udev) * pointers, it's not necessary to lock the device. */ static int -hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) +hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port, + int retry_counter) { static DECLARE_MUTEX(usb_address0_sem); @@ -1387,6 +2097,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } + oldspeed = udev->speed; /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. @@ -1396,22 +2107,22 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) i = 64; break; case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ - /* to determine the ep0 maxpacket size, read the first 8 - * bytes from the device descriptor to get bMaxPacketSize0; - * then correct our initial (small) guess. + /* to determine the ep0 maxpacket size, try to read + * the device descriptor to get bMaxPacketSize0 and + * then correct our initial guess. */ - // FALLTHROUGH + i = 64; + break; case USB_SPEED_LOW: /* fixed at 8 */ i = 8; break; default: goto fail; } - udev->epmaxpacketin [0] = i; - udev->epmaxpacketout[0] = i; + udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i; dev_info (&udev->dev, - "%s %s speed USB device using address %d\n", + "%s %s speed USB device using %s and address %d\n", (udev->config) ? "reset" : "new", ({ char *speed; switch (udev->speed) { case USB_SPEED_LOW: speed = "low"; break; @@ -1419,6 +2130,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) case USB_SPEED_HIGH: speed = "high"; break; default: speed = "?"; break; }; speed;}), + udev->bus->controller->driver->name, udev->devnum); /* Set up TT records, if needed */ @@ -1439,11 +2151,59 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) * this area, and this is how Linux has done it for ages. * Change it cautiously. * - * NOTE: Windows gets the descriptor first, seemingly to help - * work around device bugs like "can't use addresses with bit 3 - * set in certain configurations". Yes, really. + * NOTE: If USE_NEW_SCHEME() is true we will start by issuing + * a 64-byte GET_DESCRIPTOR request. This is what Windows does, + * so it may help with some non-standards-compliant devices. + * Otherwise we start with SET_ADDRESS and then try to read the + * first 8 bytes of the device descriptor to get the ep0 maxpacket + * value. */ - for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) { + for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { + if (USE_NEW_SCHEME(retry_counter)) { + struct usb_device_descriptor *buf; + +#define GET_DESCRIPTOR_BUFSIZE 64 + buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); + if (!buf) { + retval = -ENOMEM; + continue; + } + buf->bMaxPacketSize0 = 0; + + /* Use a short timeout the first time through, + * so that recalcitrant full-speed devices with + * 8- or 16-byte ep0-maxpackets won't slow things + * down tremendously by NAKing the unexpectedly + * early status stage. + */ + j = usb_control_msg(udev, usb_rcvaddr0pipe(), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + USB_DT_DEVICE << 8, 0, + buf, GET_DESCRIPTOR_BUFSIZE, + (i ? HZ * USB_CTRL_GET_TIMEOUT : HZ)); + udev->descriptor.bMaxPacketSize0 = + buf->bMaxPacketSize0; + kfree(buf); + + retval = hub_port_reset(hdev, port, udev, delay); + if (retval < 0) /* error or disconnect */ + goto fail; + if (oldspeed != udev->speed) { + dev_dbg(&udev->dev, + "device reset changed speed!\n"); + retval = -ENODEV; + goto fail; + } + if (udev->descriptor.bMaxPacketSize0 == 0) { + dev_err(&udev->dev, "device descriptor " + "read/%s, error %d\n", + "64", j); + retval = -EMSGSIZE; + continue; + } +#undef GET_DESCRIPTOR_BUFSIZE + } + for (j = 0; j < SET_ADDRESS_TRIES; ++j) { retval = hub_set_address(udev); if (retval >= 0) @@ -1462,27 +2222,31 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) * - read ep0 maxpacket even for high and low speed, */ msleep(10); + if (USE_NEW_SCHEME(retry_counter)) + break; + retval = usb_get_device_descriptor(udev, 8); - if (retval >= 8) + if (retval < 8) { + dev_err(&udev->dev, "device descriptor " + "read/%s, error %d\n", + "8", retval); + if (retval >= 0) + retval = -EMSGSIZE; + } else { + retval = 0; break; - msleep(100); + } } - if (retval != 8) { - dev_err(&udev->dev, "device descriptor read/%s, error %d\n", - "8", retval); - if (retval >= 0) - retval = -EMSGSIZE; + if (retval) goto fail; - } - if (udev->speed == USB_SPEED_FULL - && (udev->epmaxpacketin [0] - != udev->descriptor.bMaxPacketSize0)) { + + /* Should we verify that the value is valid? */ + i = udev->descriptor.bMaxPacketSize0; + if (udev->epmaxpacketin[0] != i) { + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); usb_disable_endpoint(udev, 0 + USB_DIR_IN); usb_disable_endpoint(udev, 0 + USB_DIR_OUT); - usb_endpoint_running(udev, 0, 1); - usb_endpoint_running(udev, 0, 0); - udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0; - udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0; + udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i; } retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); @@ -1574,6 +2338,7 @@ hub_power_remaining (struct usb_hub *hub) * a port enable-change occurs (often caused by EMI); * usb_reset_device() encounters changed descriptors (as from * a firmware download) + * caller already locked the hub */ static void hub_port_connect_change(struct usb_hub *hub, int port, u16 portstatus, u16 portchange) @@ -1596,6 +2361,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port, usb_disconnect(&hdev->children[port]); clear_bit(port, hub->change_bits); +#ifdef CONFIG_USB_OTG + /* during HNP, don't repeat the debounce */ + if (hdev->bus->is_b_host) + portchange &= ~USB_PORT_STAT_C_CONNECTION; +#endif + if (portchange & USB_PORT_STAT_C_CONNECTION) { status = hub_port_debounce(hdev, port); if (status < 0) { @@ -1621,6 +2392,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port, return; } +#ifdef CONFIG_USB_SUSPEND + /* If something is connected, but the port is suspended, wake it up.. */ + if (portstatus & USB_PORT_STAT_SUSPEND) { + status = hub_port_resume(hdev, port); + if (status < 0) + dev_dbg(hub_dev, "can't clear suspend on port %d; %d\n", port+1, status); + } +#endif + for (i = 0; i < SET_CONFIG_TRIES; i++) { struct usb_device *udev; @@ -1645,7 +2425,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port, } /* reset and get descriptor */ - status = hub_port_init(hdev, udev, port); + status = hub_port_init(hdev, udev, port, i); if (status < 0) goto loop; @@ -1778,9 +2558,18 @@ static void hub_events(void) usb_get_dev(hdev); spin_unlock_irq(&hub_event_lock); + dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", + hdev->state, hub->descriptor + ? hub->descriptor->bNbrPorts + : 0, + /* NOTE: expects max 15 ports... */ + (u16) hub->change_bits[0], + (u16) hub->event_bits[0]); + /* Lock the device, then check to see if we were * disconnected while waiting for the lock to succeed. */ - down(&hdev->serialize); + if (locktree(hdev) < 0) + break; if (hdev->state != USB_STATE_CONFIGURED || !hdev->actconfig || hub != usb_get_intfdata( @@ -1791,10 +2580,10 @@ static void hub_events(void) dev_dbg (hub_dev, "resetting for error %d\n", hub->error); - if (hub_reset(hub)) { + ret = usb_reset_device(hdev); + if (ret) { dev_dbg (hub_dev, - "can't reset; disconnecting\n"); - hub_start_disconnect(hdev); + "error resetting hub: %d\n", ret); goto loop; } @@ -1850,15 +2639,17 @@ static void hub_events(void) if (portchange & USB_PORT_STAT_C_SUSPEND) { clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_SUSPEND); - if (hdev->children[i]) + if (hdev->children[i]) { ret = remote_wakeup(hdev->children[i]); - else + if (ret < 0) + connect_change = 1; + } else { ret = -ENODEV; + hub_port_disable(hdev, i); + } dev_dbg (hub_dev, "resume on port %d, status %d\n", i + 1, ret); - if (ret < 0) - ret = hub_port_disable(hdev, i); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { @@ -1902,7 +2693,7 @@ static void hub_events(void) } loop: - up(&hdev->serialize); + usb_unlock_device(hdev); usb_put_dev(hdev); } /* end while (1) */ @@ -2034,7 +2825,7 @@ static int config_descriptors_changed(struct usb_device *udev) } /** - * usb_reset_devce - perform a USB port reset to reinitialize a device + * usb_reset_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) * * WARNING - don't reset any device unless drivers for all of its @@ -2055,13 +2846,15 @@ static int config_descriptors_changed(struct usb_device *udev) * * The caller must own the device lock. For example, it's safe to use * this from a driver probe() routine after downloading new firmware. + * For calls that might not occur during probe(), drivers should lock + * the device using usb_lock_device_for_reset(). */ -int __usb_reset_device(struct usb_device *udev) +int usb_reset_device(struct usb_device *udev) { struct usb_device *parent = udev->parent; struct usb_device_descriptor descriptor = udev->descriptor; - int i, ret, port = -1; - struct usb_hub *hub; + int i, ret = 0, port = -1; + int udev_is_a_hub = 0; if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED) { @@ -2070,13 +2863,9 @@ int __usb_reset_device(struct usb_device *udev) return -EINVAL; } - /* FIXME: This should be legal for regular hubs. Root hubs may - * have special requirements. */ - if (udev->maxchild) { - /* this requires hub- or hcd-specific logic; - * see hub_reset() and OHCI hc_restart() - */ - dev_dbg(&udev->dev, "%s for hub!\n", __FUNCTION__); + if (!parent) { + /* this requires hcd-specific logic; see OHCI hc_restart() */ + dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__); return -EISDIR; } @@ -2092,7 +2881,24 @@ int __usb_reset_device(struct usb_device *udev) return -ENOENT; } - ret = hub_port_init(parent, udev, port); + /* If we're resetting an active hub, take some special actions */ + if (udev->actconfig && + udev->actconfig->interface[0]->dev.driver == + &hub_driver.driver) { + udev_is_a_hub = 1; + hub_pre_reset(udev); + } + + for (i = 0; i < SET_CONFIG_TRIES; ++i) { + + /* ep0 maxpacket size may change; let the HCD know about it. + * Other endpoints will be handled by re-enumeration. */ + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT); + ret = hub_port_init(parent, udev, port, i); + if (ret >= 0) + break; + } if (ret < 0) goto re_enumerate; @@ -2105,7 +2911,7 @@ int __usb_reset_device(struct usb_device *udev) } if (!udev->actconfig) - return 0; + goto done; ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, @@ -2123,7 +2929,7 @@ int __usb_reset_device(struct usb_device *udev) struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle and halt status even + /* set_interface resets host side toggle even * for altsetting zero. the interface may have no driver. */ desc = &intf->cur_altsetting->desc; @@ -2139,32 +2945,12 @@ int __usb_reset_device(struct usb_device *udev) } } +done: + if (udev_is_a_hub) + hub_post_reset(udev); return 0; re_enumerate: - hub_port_disable(parent, port); - - hub = usb_get_intfdata(parent->actconfig->interface[0]); - set_bit(port, hub->change_bits); - - spin_lock_irq(&hub_event_lock); - if (list_empty(&hub->event_list)) { - list_add_tail(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock_irq(&hub_event_lock); - + hub_port_logical_disconnect(parent, port); return -ENODEV; } -EXPORT_SYMBOL(__usb_reset_device); - -int usb_reset_device(struct usb_device *udev) -{ - int r; - - down(&udev->serialize); - r = __usb_reset_device(udev); - up(&udev->serialize); - - return r; -} diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 9e81738fd..7ace2d24d 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -60,8 +60,8 @@ * See USB 2.0 spec Table 11-19 and Table 11-20 */ struct usb_port_status { - __u16 wPortStatus; - __u16 wPortChange; + __le16 wPortStatus; + __le16 wPortChange; } __attribute__ ((packed)); /* @@ -103,8 +103,8 @@ struct usb_port_status { #define HUB_CHAR_PORTIND 0x0080 /* D7 */ struct usb_hub_status { - __u16 wHubStatus; - __u16 wHubChange; + __le16 wHubStatus; + __le16 wHubChange; } __attribute__ ((packed)); /* @@ -190,8 +190,8 @@ struct usb_hub { struct usb_device *hdev; struct urb *urb; /* for interrupt polling pipe */ - /* buffer for urb ... 1 bit each for hub and children, rounded up */ - char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; + /* buffer for urb ... with extra space in case of babble */ + char (*buffer)[8]; dma_addr_t buffer_dma; /* DMA address for buffer */ union { struct usb_hub_status hub; @@ -214,6 +214,8 @@ struct usb_hub { u8 power_budget; /* in 2mA units; or zero */ + unsigned quiescing:1; + unsigned has_indicators:1; enum hub_led_mode indicator[USB_MAXCHILDREN]; struct work_struct leds; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index d73c3ad45..58e3e9151 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -4,7 +4,7 @@ * inode.c -- Inode/Dentry functions for the USB device file system. * * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Copyright (C) 2001,2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.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 @@ -40,17 +40,15 @@ #include #include #include +#include "usb.h" static struct super_operations usbfs_ops; static struct file_operations default_file_operations; static struct inode_operations usbfs_dir_inode_operations; -static struct vfsmount *usbdevfs_mount; static struct vfsmount *usbfs_mount; -static int usbdevfs_mount_count; /* = 0 */ static int usbfs_mount_count; /* = 0 */ static int ignore_mount = 0; -static struct dentry *devices_usbdevfs_dentry; static struct dentry *devices_usbfs_dentry; static int num_buses; /* = 0 */ @@ -240,9 +238,6 @@ static int remount(struct super_block *sb, int *flags, char *data) if (usbfs_mount && usbfs_mount->mnt_sb) update_sb(usbfs_mount->mnt_sb); - if (usbdevfs_mount && usbdevfs_mount->mnt_sb) - update_sb(usbdevfs_mount->mnt_sb); - return 0; } @@ -345,30 +340,13 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry) return 0; } -static void d_unhash(struct dentry *dentry) -{ - dget(dentry); - spin_lock(&dcache_lock); - switch (atomic_read(&dentry->d_count)) { - default: - spin_unlock(&dcache_lock); - shrink_dcache_parent(dentry); - spin_lock(&dcache_lock); - if (atomic_read(&dentry->d_count) != 2) - break; - case 2: - __d_drop(dentry); - } - spin_unlock(&dcache_lock); -} - static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) { int error = -ENOTEMPTY; struct inode * inode = dentry->d_inode; down(&inode->i_sem); - d_unhash(dentry); + dentry_unhash(dentry); if (usbfs_empty(dentry)) { dentry->d_inode->i_nlink -= 2; dput(dentry); @@ -578,28 +556,12 @@ static void fs_remove_file (struct dentry *dentry) /* --------------------------------------------------------------------- */ - - -/* - * The usbdevfs name is now deprecated (as of 2.5.1). - * It will be removed when the 2.7.x development cycle is started. - * You have been warned :) - */ -static struct file_system_type usbdevice_fs_type; - static struct super_block *usb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return get_sb_single(fs_type, flags, data, usbfs_fill_super); } -static struct file_system_type usbdevice_fs_type = { - .owner = THIS_MODULE, - .name = "usbdevfs", - .get_sb = usb_get_sb, - .kill_sb = kill_litter_super, -}; - static struct file_system_type usb_fs_type = { .owner = THIS_MODULE, .name = "usbfs", @@ -620,16 +582,10 @@ static int create_special_files (void) ignore_mount = 1; /* create the devices special file */ - retval = simple_pin_fs("usbdevfs", &usbdevfs_mount, &usbdevfs_mount_count); - if (retval) { - err ("Unable to get usbdevfs mount"); - goto exit; - } - retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count); if (retval) { err ("Unable to get usbfs mount"); - goto error_clean_usbdevfs_mount; + goto exit; } ignore_mount = 0; @@ -637,7 +593,7 @@ static int create_special_files (void) parent = usbfs_mount->mnt_sb->s_root; devices_usbfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, - NULL, &usbdevfs_devices_fops, + NULL, &usbfs_devices_fops, listuid, listgid); if (devices_usbfs_dentry == NULL) { err ("Unable to create devices usbfs file"); @@ -645,42 +601,19 @@ static int create_special_files (void) goto error_clean_mounts; } - parent = usbdevfs_mount->mnt_sb->s_root; - devices_usbdevfs_dentry = fs_create_file ("devices", - listmode | S_IFREG, parent, - NULL, &usbdevfs_devices_fops, - listuid, listgid); - if (devices_usbdevfs_dentry == NULL) { - err ("Unable to create devices usbfs file"); - retval = -ENODEV; - goto error_remove_file; - } - goto exit; -error_remove_file: - fs_remove_file (devices_usbfs_dentry); - devices_usbfs_dentry = NULL; - error_clean_mounts: simple_release_fs(&usbfs_mount, &usbfs_mount_count); - -error_clean_usbdevfs_mount: - simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count); - exit: return retval; } static void remove_special_files (void) { - if (devices_usbdevfs_dentry) - fs_remove_file (devices_usbdevfs_dentry); if (devices_usbfs_dentry) fs_remove_file (devices_usbfs_dentry); - devices_usbdevfs_dentry = NULL; devices_usbfs_dentry = NULL; - simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count); simple_release_fs(&usbfs_mount, &usbfs_mount_count); } @@ -688,11 +621,6 @@ void usbfs_update_special (void) { struct inode *inode; - if (devices_usbdevfs_dentry) { - inode = devices_usbdevfs_dentry->d_inode; - if (inode) - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - } if (devices_usbfs_dentry) { inode = devices_usbfs_dentry->d_inode; if (inode) @@ -724,29 +652,16 @@ void usbfs_add_bus(struct usb_bus *bus) return; } - parent = usbdevfs_mount->mnt_sb->s_root; - bus->usbdevfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, - bus, NULL, busuid, busgid); - if (bus->usbdevfs_dentry == NULL) { - err ("error creating usbdevfs bus entry"); - return; - } - usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } - void usbfs_remove_bus(struct usb_bus *bus) { if (bus->usbfs_dentry) { fs_remove_file (bus->usbfs_dentry); bus->usbfs_dentry = NULL; } - if (bus->usbdevfs_dentry) { - fs_remove_file (bus->usbdevfs_dentry); - bus->usbdevfs_dentry = NULL; - } --num_buses; if (num_buses <= 0) { @@ -755,7 +670,7 @@ void usbfs_remove_bus(struct usb_bus *bus) } usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } void usbfs_add_device(struct usb_device *dev) @@ -767,20 +682,12 @@ void usbfs_add_device(struct usb_device *dev) sprintf (name, "%03d", dev->devnum); dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, dev->bus->usbfs_dentry, dev, - &usbdevfs_device_file_operations, + &usbfs_device_file_operations, devuid, devgid); if (dev->usbfs_dentry == NULL) { err ("error creating usbfs device entry"); return; } - dev->usbdevfs_dentry = fs_create_file (name, devmode | S_IFREG, - dev->bus->usbdevfs_dentry, dev, - &usbdevfs_device_file_operations, - devuid, devgid); - if (dev->usbdevfs_dentry == NULL) { - err ("error creating usbdevfs device entry"); - return; - } /* Set the size of the device's file to be * equal to the size of the device descriptors. */ @@ -788,15 +695,13 @@ void usbfs_add_device(struct usb_device *dev) for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { struct usb_config_descriptor *config = (struct usb_config_descriptor *)dev->rawdescriptors[i]; - i_size += le16_to_cpu (config->wTotalLength); + i_size += le16_to_cpu ((__force __le16)config->wTotalLength); } if (dev->usbfs_dentry->d_inode) dev->usbfs_dentry->d_inode->i_size = i_size; - if (dev->usbdevfs_dentry->d_inode) - dev->usbdevfs_dentry->d_inode->i_size = i_size; usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } void usbfs_remove_device(struct usb_device *dev) @@ -808,12 +713,9 @@ void usbfs_remove_device(struct usb_device *dev) fs_remove_file (dev->usbfs_dentry); dev->usbfs_dentry = NULL; } - if (dev->usbdevfs_dentry) { - fs_remove_file (dev->usbdevfs_dentry); - dev->usbdevfs_dentry = NULL; - } while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); + wake_up_all(&ds->wait); list_del_init(&ds->list); if (ds->discsignr) { sinfo.si_signo = SIGPIPE; @@ -824,51 +726,38 @@ void usbfs_remove_device(struct usb_device *dev) } } usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } /* --------------------------------------------------------------------- */ -#ifdef CONFIG_PROC_FS static struct proc_dir_entry *usbdir = NULL; -#endif int __init usbfs_init(void) { int retval; - retval = usb_register(&usbdevfs_driver); + retval = usb_register(&usbfs_driver); if (retval) return retval; retval = register_filesystem(&usb_fs_type); if (retval) { - usb_deregister(&usbdevfs_driver); - return retval; - } - retval = register_filesystem(&usbdevice_fs_type); - if (retval) { - unregister_filesystem(&usb_fs_type); - usb_deregister(&usbdevfs_driver); + usb_deregister(&usbfs_driver); return retval; } -#ifdef CONFIG_PROC_FS - /* create mount point for usbdevfs */ + /* create mount point for usbfs */ usbdir = proc_mkdir("usb", proc_bus); -#endif return 0; } void usbfs_cleanup(void) { - usb_deregister(&usbdevfs_driver); + usb_deregister(&usbfs_driver); unregister_filesystem(&usb_fs_type); - unregister_filesystem(&usbdevice_fs_type); -#ifdef CONFIG_PROC_FS if (usbdir) remove_proc_entry("usb", proc_bus); -#endif } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e0eacc28a..d7d784e18 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include "hcd.h" /* for usbcore internals */ @@ -32,10 +34,6 @@ static void timeout_kill(unsigned long data) { struct urb *urb = (struct urb *) data; - dev_warn(&urb->dev->dev, "%s timeout on ep%d%s\n", - usb_pipecontrol(urb->pipe) ? "control" : "bulk", - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out"); usb_unlink_urb(urb); } @@ -66,8 +64,14 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) wait_for_completion(&done); status = urb->status; /* note: HCDs return ETIMEDOUT for other reasons too */ - if (status == -ECONNRESET) + if (status == -ECONNRESET) { + dev_warn(&urb->dev->dev, + "%s timed out on ep%d%s\n", + current->comm, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out"); status = -ETIMEDOUT; + } if (timeout > 0) del_timer_sync(&timer); } @@ -239,16 +243,18 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) // BUG (); } - if (urb->status && urb->status != -ECONNRESET) { + if (io->status == 0 && urb->status && urb->status != -ECONNRESET) { int i, found, status; io->status = urb->status; /* the previous urbs, and this one, completed already. * unlink pending urbs so they won't rx/tx bad data. + * careful: unlink can sometimes be synchronous... */ + spin_unlock (&io->lock); for (i = 0, found = 0; i < io->entries; i++) { - if (!io->urbs [i]) + if (!io->urbs [i] || !io->urbs [i]->dev) continue; if (found) { status = usb_unlink_urb (io->urbs [i]); @@ -259,6 +265,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) } else if (urb == io->urbs [i]) found = 1; } + spin_lock (&io->lock); } urb->dev = NULL; @@ -337,7 +344,7 @@ int usb_sg_init ( if (io->entries <= 0) return io->entries; - io->count = 0; + io->count = io->entries; io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); if (!io->urbs) goto nomem; @@ -347,7 +354,7 @@ int usb_sg_init ( if (usb_pipein (pipe)) urb_flags |= URB_SHORT_NOT_OK; - for (i = 0; i < io->entries; i++, io->count = i) { + for (i = 0; i < io->entries; i++) { unsigned len; io->urbs [i] = usb_alloc_urb (0, mem_flags); @@ -477,24 +484,19 @@ void usb_sg_wait (struct usb_sg_request *io) /* fail any uncompleted urbs */ default: - spin_lock_irq (&io->lock); - io->count -= entries - i; - if (io->status == -EINPROGRESS) - io->status = retval; - if (io->count == 0) - complete (&io->complete); - spin_unlock_irq (&io->lock); - - io->urbs[i]->dev = NULL; + io->urbs [i]->dev = NULL; io->urbs [i]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } spin_lock_irq (&io->lock); - if (retval && io->status == -ECONNRESET) + if (retval && (io->status == 0 || io->status == -ECONNRESET)) io->status = retval; } + io->count -= entries - i; + if (io->count == 0) + complete (&io->complete); spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. @@ -525,6 +527,7 @@ void usb_sg_cancel (struct usb_sg_request *io) int i; io->status = -ECONNRESET; + spin_unlock (&io->lock); for (i = 0; i < io->entries; i++) { int retval; @@ -535,6 +538,7 @@ void usb_sg_cancel (struct usb_sg_request *io) dev_warn (&io->dev->dev, "%s, unlink --> %d\n", __FUNCTION__, retval); } + spin_lock (&io->lock); } spin_unlock_irqrestore (&io->lock, flags); } @@ -552,8 +556,7 @@ void usb_sg_cancel (struct usb_sg_request *io) * * Gets a USB descriptor. Convenience functions exist to simplify * getting some types of descriptors. Use - * usb_get_device_descriptor() for USB_DT_DEVICE (not exported), - * and usb_get_string() or usb_string() for USB_DT_STRING. + * usb_get_string() or usb_string() for USB_DT_STRING. * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG) * are part of the device structure. * In addition to a number of USB-standard descriptors, some @@ -577,8 +580,13 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (type << 8) + index, 0, buf, size, HZ * USB_CTRL_GET_TIMEOUT); - if (!(result == 0 || result == -EPIPE)) - break; + if (result == 0 || result == -EPIPE) + continue; + if (result > 1 && ((u8 *)buf)[1] != type) { + result = -EPROTO; + continue; + } + break; } return result; } @@ -623,6 +631,20 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, return result; } +static void usb_try_string_workarounds(unsigned char *buf, int *length) +{ + int newlength, oldlength = *length; + + for (newlength = 2; newlength + 1 < oldlength; newlength += 2) + if (!isprint(buf[newlength]) || buf[newlength + 1]) + break; + + if (newlength > 2) { + buf[0] = newlength; + *length = newlength; + } +} + static int usb_string_sub(struct usb_device *dev, unsigned int langid, unsigned int index, unsigned char *buf) { @@ -634,19 +656,26 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid, /* If that failed try to read the descriptor length, then * ask for just that many bytes */ - if (rc < 0) { + if (rc < 2) { rc = usb_get_string(dev, langid, index, buf, 2); if (rc == 2) rc = usb_get_string(dev, langid, index, buf, buf[0]); } - if (rc >= 0) { + if (rc >= 2) { + if (!buf[0] && !buf[1]) + usb_try_string_workarounds(buf, &rc); + /* There might be extra junk at the end of the descriptor */ if (buf[0] < rc) rc = buf[0]; - if (rc < 2) - rc = -EINVAL; + + rc = rc - (rc & 1); /* force a multiple of two */ } + + if (rc < 2) + rc = (rc < 0 ? rc : -EINVAL); + return rc; } @@ -680,6 +709,8 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) int err; unsigned int u, idx; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; if (size <= 0 || !buf || !index) return -EINVAL; buf[0] = 0; @@ -724,13 +755,16 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) buf[idx] = 0; err = idx; + if (tbuf[1] != USB_DT_STRING) + dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf); + errout: kfree(tbuf); return err; } -/** - * usb_get_device_descriptor - (re)reads the device descriptor +/* + * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) * @dev: the device whose device descriptor is being updated * @size: how much of the descriptor to read * Context: !in_interrupt () @@ -797,9 +831,19 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) */ int usb_get_status(struct usb_device *dev, int type, int target, void *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, - HZ * USB_CTRL_GET_TIMEOUT); + int ret; + u16 *status = kmalloc(sizeof(*status), GFP_KERNEL); + + if (!status) + return -ENOMEM; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status, + sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT); + + *(u16 *)data = *status; + kfree(status); + return ret; } /** @@ -854,9 +898,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe) * the copy in usb-storage, for as long as we need two copies. */ - /* toggle was reset by the clear, then ep was reactivated */ + /* toggle was reset by the clear */ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); - usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); return 0; } @@ -870,9 +913,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe) * Deallocates hcd/hardware state for this endpoint ... and nukes all * pending urbs. * - * If the HCD hasn't registered a disable() function, this marks the - * endpoint as halted and sets its maxpacket size to 0 to prevent - * further submissions. + * If the HCD hasn't registered a disable() function, this sets the + * endpoint's maxpacket size to 0 to prevent further submissions. */ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) { @@ -881,13 +923,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) else { unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; - if (usb_endpoint_out(epaddr)) { - usb_endpoint_halt(dev, epnum, 1); + if (usb_endpoint_out(epaddr)) dev->epmaxpacketout[epnum] = 0; - } else { - usb_endpoint_halt(dev, epnum, 0); + else dev->epmaxpacketin[epnum] = 0; - } } } @@ -930,7 +969,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) usb_disable_endpoint(dev, i + USB_DIR_IN); } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) @@ -966,9 +1004,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) * @dev: the device whose interface is being enabled * @epd: pointer to the endpoint descriptor * - * Marks the endpoint as running, resets its toggle, and stores - * its maxpacket value. For control endpoints, both the input - * and output sides are handled. + * Resets the endpoint toggle and stores its maxpacket value. + * For control endpoints, both the input and output sides are handled. */ void usb_enable_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *epd) @@ -980,12 +1017,10 @@ void usb_enable_endpoint(struct usb_device *dev, USB_ENDPOINT_XFER_CONTROL); if (usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 1); usb_settoggle(dev, epnum, 1, 0); dev->epmaxpacketout[epnum] = maxsize; } if (!usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 0); usb_settoggle(dev, epnum, 0, 0); dev->epmaxpacketin[epnum] = maxsize; } @@ -1048,6 +1083,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) int ret; int manual = 0; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + iface = usb_ifnum_to_if(dev, interface); if (!iface) { dev_dbg(&dev->dev, "selecting invalid interface %d\n", @@ -1138,6 +1176,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * use usb_set_interface() on the interfaces it claims. Resetting the whole * configuration would affect other drivers' interfaces. * + * The caller must own the device lock. + * * Returns zero on success, else a negative error code. */ int usb_reset_configuration(struct usb_device *dev) @@ -1145,9 +1185,12 @@ int usb_reset_configuration(struct usb_device *dev) int i, retval; struct usb_host_config *config; - /* caller must own dev->serialize (config won't change) - * and the usb bus readlock (so driver bindings are stable); - * so calls during probe() are fine + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + + /* caller must have locked the device and must own + * the usb bus readlock (so driver bindings are stable); + * calls during probe() are fine */ for (i = 1; i < 16; ++i) { @@ -1166,7 +1209,6 @@ int usb_reset_configuration(struct usb_device *dev) } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* re-init hc/hcd interface/endpoint state */ for (i = 0; i < config->desc.bNumInterfaces; i++) { @@ -1195,7 +1237,7 @@ static void release_interface(struct device *dev) struct usb_interface_cache *intfc = altsetting_to_usb_interface_cache(intf->altsetting); - kref_put(&intfc->ref); + kref_put(&intfc->ref, usb_release_interface_cache); kfree(intf); } @@ -1203,7 +1245,7 @@ static void release_interface(struct device *dev) * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated * @configuration: the configuration being chosen. - * Context: !in_interrupt(), caller holds dev->serialize + * Context: !in_interrupt(), caller owns the device lock * * This is used to enable non-default device modes. Not all devices * use this kind of configurability; many devices only have one @@ -1224,8 +1266,8 @@ static void release_interface(struct device *dev) * usb_set_interface(). * * This call is synchronous. The calling context must be able to sleep, - * and must not hold the driver model lock for USB; usb device driver - * probe() methods may not use this routine. + * must own the device lock, and must not hold the driver model's USB + * bus rwsem; usb device driver probe() methods cannot use this routine. * * Returns zero on success, or else the status code returned by the * underlying call that failed. On succesful completion, each interface @@ -1240,8 +1282,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) struct usb_interface **new_interfaces = NULL; int n, nintf; - /* dev->serialize guards all config changes */ - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (dev->config[i].desc.bConfigurationValue == configuration) { cp = &dev->config[i]; @@ -1258,6 +1298,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp && configuration == 0) dev_warn(&dev->dev, "config 0 descriptor??\n"); + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + /* Allocate memory for new interfaces before doing anything else, * so that if we run out then nothing will have changed. */ n = nintf = 0; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 78c5ca2f1..bae974d58 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -27,11 +27,13 @@ static ssize_t show_##field (struct device *dev, char *buf) \ { \ struct usb_device *udev; \ + struct usb_host_config *actconfig; \ \ udev = to_usb_device (dev); \ - if (udev->actconfig) \ + actconfig = udev->actconfig; \ + if (actconfig) \ return sprintf (buf, format_string, \ - udev->actconfig->desc.field * multiplier); \ + actconfig->desc.field * multiplier); \ else \ return 0; \ } \ @@ -44,6 +46,28 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n") usb_actconfig_attr (bmAttributes, 1, "%2x\n") usb_actconfig_attr (bMaxPower, 2, "%3dmA\n") +#define usb_actconfig_str(name, field) \ +static ssize_t show_##name(struct device *dev, char *buf) \ +{ \ + struct usb_device *udev; \ + struct usb_host_config *actconfig; \ + int len; \ + \ + udev = to_usb_device (dev); \ + actconfig = udev->actconfig; \ + if (!actconfig) \ + return 0; \ + len = usb_string(udev, actconfig->desc.field, buf, PAGE_SIZE); \ + if (len < 0) \ + return 0; \ + buf[len] = '\n'; \ + buf[len+1] = 0; \ + return len+1; \ +} \ +static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); + +usb_actconfig_str (configuration, iConfiguration) + /* configuration value is always present, and r/w */ usb_actconfig_show(bConfigurationValue, 1, "%u\n"); @@ -55,9 +79,9 @@ set_bConfigurationValue (struct device *dev, const char *buf, size_t count) if (sscanf (buf, "%u", &config) != 1 || config > 255) return -EINVAL; - down(&udev->serialize); + usb_lock_device(udev); value = usb_set_configuration (udev, config); - up(&udev->serialize); + usb_unlock_device(udev); return (value < 0) ? value : count; } @@ -198,6 +222,7 @@ void usb_create_sysfs_dev_files (struct usb_device *udev) device_create_file (dev, &dev_attr_product); if (udev->descriptor.iSerialNumber) device_create_file (dev, &dev_attr_serial); + device_create_file (dev, &dev_attr_configuration); } void usb_remove_sysfs_dev_files (struct usb_device *udev) @@ -212,6 +237,7 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev) device_remove_file(dev, &dev_attr_product); if (udev->descriptor.iSerialNumber) device_remove_file(dev, &dev_attr_serial); + device_remove_file (dev, &dev_attr_configuration); } /* Interface fields */ @@ -231,7 +257,26 @@ usb_intf_attr (bNumEndpoints, "%02x\n") usb_intf_attr (bInterfaceClass, "%02x\n") usb_intf_attr (bInterfaceSubClass, "%02x\n") usb_intf_attr (bInterfaceProtocol, "%02x\n") -usb_intf_attr (iInterface, "%02x\n") + +#define usb_intf_str(name, field) \ +static ssize_t show_##name(struct device *dev, char *buf) \ +{ \ + struct usb_interface *intf; \ + struct usb_device *udev; \ + int len; \ + \ + intf = to_usb_interface (dev); \ + udev = interface_to_usbdev (intf); \ + len = usb_string(udev, intf->cur_altsetting->desc.field, buf, PAGE_SIZE);\ + if (len < 0) \ + return 0; \ + buf[len] = '\n'; \ + buf[len+1] = 0; \ + return len+1; \ +} \ +static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); + +usb_intf_str (interface, iInterface); static struct attribute *intf_attrs[] = { &dev_attr_bInterfaceNumber.attr, @@ -240,7 +285,6 @@ static struct attribute *intf_attrs[] = { &dev_attr_bInterfaceClass.attr, &dev_attr_bInterfaceSubClass.attr, &dev_attr_bInterfaceProtocol.attr, - &dev_attr_iInterface.attr, NULL, }; static struct attribute_group intf_attr_grp = { @@ -250,9 +294,17 @@ static struct attribute_group intf_attr_grp = { void usb_create_sysfs_intf_files (struct usb_interface *intf) { sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); + + if (intf->cur_altsetting->desc.iInterface) + device_create_file(&intf->dev, &dev_attr_interface); + } void usb_remove_sysfs_intf_files (struct usb_interface *intf) { sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); + + if (intf->cur_altsetting->desc.iInterface) + device_remove_file(&intf->dev, &dev_attr_interface); + } diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 777f34ea6..29367e626 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -39,7 +39,7 @@ void usb_init_urb(struct urb *urb) { if (urb) { memset(urb, 0, sizeof(*urb)); - kref_init(&urb->kref, urb_destroy); + kref_init(&urb->kref); spin_lock_init(&urb->lock); } } @@ -88,7 +88,7 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags) void usb_free_urb(struct urb *urb) { if (urb) - kref_put(&urb->kref); + kref_put(&urb->kref, urb_destroy); } /** @@ -256,13 +256,6 @@ int usb_submit_urb(struct urb *urb, int mem_flags) if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) return -ENODEV; - /* (actually HCDs may need to duplicate this, endpoint might yet - * stall due to queued bulk/intr transactions that complete after - * we check) - */ - if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out)) - return -EPIPE; - /* FIXME there should be a sharable lock protecting us against * config/altsetting changes and disconnects, kicking in here. * (here == before maxpacket, and eventually endpoint type, @@ -271,11 +264,10 @@ int usb_submit_urb(struct urb *urb, int mem_flags) max = usb_maxpacket (dev, pipe, is_out); if (max <= 0) { - dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)", - __FUNCTION__, - usb_pipeendpoint (pipe), is_out ? "OUT" : "IN", - dev->bus->bus_name, dev->devpath, - max); + dev_dbg(&dev->dev, + "bogus endpoint ep%d%s in %s (bad maxpacket %d)", + usb_pipeendpoint (pipe), is_out ? "out" : "in", + __FUNCTION__, max); return -EMSGSIZE; } @@ -458,6 +450,13 @@ int usb_unlink_urb(struct urb *urb) if (!urb) return -EINVAL; if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { +#ifdef CONFIG_DEBUG_KERNEL + if (printk_ratelimit()) { + printk(KERN_NOTICE "usb_unlink_urb() is deprecated for " + "synchronous unlinks. Use usb_kill_urb() instead.\n"); + WARN_ON(1); + } +#endif usb_kill_urb(urb); return 0; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 324e16caf..00f6caf6d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,9 @@ const char *usbcore_name = "usbcore"; int nousb; /* Disable USB when built into kernel image */ /* Not honored on modular build */ +DECLARE_RWSEM(usb_all_devices_rwsem); +EXPORT_SYMBOL(usb_all_devices_rwsem); + static int generic_probe (struct device *dev) { @@ -73,6 +77,7 @@ static int generic_remove (struct device *dev) } static struct device_driver usb_generic_driver = { + .owner = THIS_MODULE, .name = "usb", .bus = &usb_bus_type, .probe = generic_probe, @@ -93,11 +98,17 @@ int usb_probe_interface(struct device *dev) if (!driver->probe) return error; + /* FIXME we'd much prefer to just resume it ... */ + if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; id = usb_match_id (intf, driver->id_table); if (id) { dev_dbg (dev, "%s - got id\n", __FUNCTION__); + intf->condition = USB_INTERFACE_BINDING; error = driver->probe (intf, id); + intf->condition = error ? USB_INTERFACE_UNBOUND : + USB_INTERFACE_BOUND; } return error; @@ -109,6 +120,8 @@ int usb_unbind_interface(struct device *dev) struct usb_interface *intf = to_usb_interface(dev); struct usb_driver *driver = to_usb_driver(intf->dev.driver); + intf->condition = USB_INTERFACE_UNBINDING; + /* release all urbs for this interface */ usb_disable_interface(interface_to_usbdev(intf), intf); @@ -120,6 +133,7 @@ int usb_unbind_interface(struct device *dev) intf->altsetting[0].desc.bInterfaceNumber, 0); usb_set_intfdata(intf, NULL); + intf->condition = USB_INTERFACE_UNBOUND; return 0; } @@ -148,8 +162,11 @@ int usb_register(struct usb_driver *new_driver) new_driver->driver.bus = &usb_bus_type; new_driver->driver.probe = usb_probe_interface; new_driver->driver.remove = usb_unbind_interface; + new_driver->driver.owner = new_driver->owner; + usb_lock_all_devices(); retval = driver_register(&new_driver->driver); + usb_unlock_all_devices(); if (!retval) { pr_info("%s: registered new driver %s\n", @@ -178,7 +195,9 @@ void usb_deregister(struct usb_driver *driver) { pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); + usb_lock_all_devices(); driver_unregister (&driver->driver); + usb_unlock_all_devices(); usbfs_update_special(); } @@ -200,7 +219,7 @@ void usb_deregister(struct usb_driver *driver) * alternate settings available for this interfaces. * * Don't call this function unless you are bound to one of the interfaces - * on this device or you own the dev->serialize semaphore! + * on this device or you have locked the device! */ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) { @@ -233,7 +252,7 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) * drivers avoid such mistakes. * * Don't call this function unless you are bound to the intf interface - * or you own the device's ->serialize semaphore! + * or you have locked the device! */ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, unsigned int altnum) @@ -301,11 +320,12 @@ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) * way to bind to an interface is to return the private data from * the driver's probe() method. * - * Callers must own the driver model's usb bus writelock. So driver - * probe() entries don't need extra locking, but other call contexts - * may need to explicitly claim that lock. + * Callers must own the device lock and the driver model's usb_bus_type.subsys + * writelock. So driver probe() entries don't need extra locking, + * but other call contexts may need to explicitly claim those locks. */ -int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) +int usb_driver_claim_interface(struct usb_driver *driver, + struct usb_interface *iface, void* priv) { struct device *dev = &iface->dev; @@ -314,6 +334,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface * dev->driver = &driver->driver; usb_set_intfdata(iface, priv); + iface->condition = USB_INTERFACE_BOUND; /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() @@ -334,8 +355,8 @@ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface * * also causes the driver disconnect() method to be called. * * This call is synchronous, and may not be used in an interrupt context. - * Callers must own the usb_device serialize semaphore and the driver model's - * usb bus writelock. So driver disconnect() entries don't need extra locking, + * Callers must own the device lock and the driver model's usb_bus_type.subsys + * writelock. So driver disconnect() entries don't need extra locking, * but other call contexts may need to explicitly claim those locks. */ void usb_driver_release_interface(struct usb_driver *driver, @@ -353,6 +374,7 @@ void usb_driver_release_interface(struct usb_driver *driver, dev->driver = NULL; usb_set_intfdata(iface, NULL); + iface->condition = USB_INTERFACE_UNBOUND; } /** @@ -530,9 +552,7 @@ static int usb_device_match (struct device *dev, struct device_driver *drv) return 0; intf = to_usb_interface(dev); - usb_drv = to_usb_driver(drv); - id = usb_drv->id_table; id = usb_match_id (intf, usb_drv->id_table); if (id) @@ -562,7 +582,6 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, { struct usb_interface *intf; struct usb_device *usb_dev; - char *scratch; int i = 0; int length = 0; @@ -589,8 +608,6 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, return -ENODEV; } - scratch = buffer; - #ifdef CONFIG_USB_DEVICEFS /* If this is available, userspace programs can directly read * all the device descriptors we don't tell them about. Or @@ -598,37 +615,30 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, * * FIXME reduce hardwired intelligence here */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum); - if ((buffer_size - length <= 0) || (i >= num_envp)) + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "DEVICE=/proc/bus/usb/%03d/%03d", + usb_dev->bus->busnum, usb_dev->devnum)) return -ENOMEM; - ++length; - scratch += length; #endif /* per-device configurations are common */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x", - usb_dev->descriptor.idVendor, - usb_dev->descriptor.idProduct, - usb_dev->descriptor.bcdDevice); - if ((buffer_size - length <= 0) || (i >= num_envp)) + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PRODUCT=%x/%x/%x", + usb_dev->descriptor.idVendor, + usb_dev->descriptor.idProduct, + usb_dev->descriptor.bcdDevice)) return -ENOMEM; - ++length; - scratch += length; /* class-based driver binding models */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "TYPE=%d/%d/%d", + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - ++length; - scratch += length; if (usb_dev->descriptor.bDeviceClass == 0) { struct usb_host_interface *alt = intf->cur_altsetting; @@ -637,19 +647,16 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp, * agents are called for all interfaces, and can use * $DEVPATH/bInterfaceNumber if necessary. */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "INTERFACE=%d/%d/%d", - alt->desc.bInterfaceClass, - alt->desc.bInterfaceSubClass, - alt->desc.bInterfaceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "INTERFACE=%d/%d/%d", + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol)) return -ENOMEM; - ++length; - scratch += length; - } - envp[i++] = NULL; + + envp[i] = NULL; return 0; } @@ -757,7 +764,11 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port) init_MUTEX(&dev->serialize); if (dev->bus->op->allocate) - dev->bus->op->allocate(dev); + if (dev->bus->op->allocate(dev)) { + usb_bus_put(bus); + kfree(dev); + return NULL; + } return dev; } @@ -828,6 +839,160 @@ void usb_put_intf(struct usb_interface *intf) put_device(&intf->dev); } + +/* USB device locking + * + * Although locking USB devices should be straightforward, it is + * complicated by the way the driver-model core works. When a new USB + * driver is registered or unregistered, the core will automatically + * probe or disconnect all matching interfaces on all USB devices while + * holding the USB subsystem writelock. There's no good way for us to + * tell which devices will be used or to lock them beforehand; our only + * option is to effectively lock all the USB devices. + * + * We do that by using a private rw-semaphore, usb_all_devices_rwsem. + * When locking an individual device you must first acquire the rwsem's + * readlock. When a driver is registered or unregistered the writelock + * must be held. These actions are encapsulated in the subroutines + * below, so all a driver needs to do is call usb_lock_device() and + * usb_unlock_device(). + * + * Complications arise when several devices are to be locked at the same + * time. Only hub-aware drivers that are part of usbcore ever have to + * do this; nobody else needs to worry about it. The problem is that + * usb_lock_device() must not be called to lock a second device since it + * would acquire the rwsem's readlock reentrantly, leading to deadlock if + * another thread was waiting for the writelock. The solution is simple: + * + * When locking more than one device, call usb_lock_device() + * to lock the first one. Lock the others by calling + * down(&udev->serialize) directly. + * + * When unlocking multiple devices, use up(&udev->serialize) + * to unlock all but the last one. Unlock the last one by + * calling usb_unlock_device(). + * + * When locking both a device and its parent, always lock the + * the parent first. + */ + +/** + * usb_lock_device - acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Use this routine when you don't hold any other device locks; + * to acquire nested inner locks call down(&udev->serialize) directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_lock_device(struct usb_device *udev) +{ + down_read(&usb_all_devices_rwsem); + down(&udev->serialize); +} + +/** + * usb_trylock_device - attempt to acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Don't use this routine if you already hold a device lock; + * use down_trylock(&udev->serialize) instead. + * This is necessary for proper interaction with usb_lock_all_devices(). + * + * Returns 1 if successful, 0 if contention. + */ +int usb_trylock_device(struct usb_device *udev) +{ + if (!down_read_trylock(&usb_all_devices_rwsem)) + return 0; + if (down_trylock(&udev->serialize)) { + up_read(&usb_all_devices_rwsem); + return 0; + } + return 1; +} + +/** + * usb_lock_device_for_reset - cautiously acquire the lock for a + * usb device structure + * @udev: device that's being locked + * @iface: interface bound to the driver making the request (optional) + * + * Attempts to acquire the device lock, but fails if the device is + * NOTATTACHED or SUSPENDED, or if iface is specified and the interface + * is neither BINDING nor BOUND. Rather than sleeping to wait for the + * lock, the routine polls repeatedly. This is to prevent deadlock with + * disconnect; in some drivers (such as usb-storage) the disconnect() + * callback will block waiting for a device reset to complete. + * + * Returns a negative error code for failure, otherwise 1 or 0 to indicate + * that the device will or will not have to be unlocked. (0 can be + * returned when an interface is given and is BINDING, because in that + * case the driver already owns the device lock.) + */ +int usb_lock_device_for_reset(struct usb_device *udev, + struct usb_interface *iface) +{ + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (udev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + if (iface) { + switch (iface->condition) { + case USB_INTERFACE_BINDING: + return 0; + case USB_INTERFACE_BOUND: + break; + default: + return -EINTR; + } + } + + while (!usb_trylock_device(udev)) { + msleep(15); + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (udev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + if (iface && iface->condition != USB_INTERFACE_BOUND) + return -EINTR; + } + return 1; +} + +/** + * usb_unlock_device - release the lock for a usb device structure + * @udev: device that's being unlocked + * + * Use this routine when releasing the only device lock you hold; + * to release inner nested locks call up(&udev->serialize) directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_unlock_device(struct usb_device *udev) +{ + up(&udev->serialize); + up_read(&usb_all_devices_rwsem); +} + +/** + * usb_lock_all_devices - acquire the lock for all usb device structures + * + * This is necessary when registering a new driver or probing a bus, + * since the driver-model core may try to use any usb_device. + */ +void usb_lock_all_devices(void) +{ + down_write(&usb_all_devices_rwsem); +} + +/** + * usb_unlock_all_devices - release the lock for all usb device structures + */ +void usb_unlock_all_devices(void) +{ + up_write(&usb_all_devices_rwsem); +} + + static struct usb_device *match_device(struct usb_device *dev, u16 vendor_id, u16 product_id) { @@ -849,8 +1014,10 @@ static struct usb_device *match_device(struct usb_device *dev, /* look through all of the children of this device */ for (child = 0; child < dev->maxchild; ++child) { if (dev->children[child]) { + down(&dev->children[child]->serialize); ret_dev = match_device(dev->children[child], vendor_id, product_id); + up(&dev->children[child]->serialize); if (ret_dev) goto exit; } @@ -885,7 +1052,9 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) bus = container_of(buslist, struct usb_bus, bus_list); if (!bus->root_hub) continue; + usb_lock_device(bus->root_hub); dev = match_device(bus->root_hub, vendor_id, product_id); + usb_unlock_device(bus->root_hub); if (dev) goto exit; } @@ -1236,6 +1405,10 @@ static int usb_generic_suspend(struct device *dev, u32 state) intf = to_usb_interface(dev); driver = to_usb_driver(dev->driver); + /* there's only one USB suspend state */ + if (intf->dev.power.power_state) + return 0; + if (driver->suspend) return driver->suspend(intf, state); return 0; @@ -1371,6 +1544,11 @@ EXPORT_SYMBOL(usb_put_dev); EXPORT_SYMBOL(usb_get_dev); EXPORT_SYMBOL(usb_hub_tt_clear_buffer); +EXPORT_SYMBOL(usb_lock_device); +EXPORT_SYMBOL(usb_trylock_device); +EXPORT_SYMBOL(usb_lock_device_for_reset); +EXPORT_SYMBOL(usb_unlock_device); + EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_driver_release_interface); EXPORT_SYMBOL(usb_match_id); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7d978af3a..4035ff925 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -10,6 +10,7 @@ extern int usb_unbind_interface (struct device *dev); extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface (struct usb_device *dev, struct usb_interface *intf); +extern void usb_release_interface_cache(struct kref *ref); extern void usb_disable_device (struct usb_device *dev, int skip_ep0); extern void usb_enable_endpoint (struct usb_device *dev, @@ -21,8 +22,29 @@ extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); extern int usb_set_configuration(struct usb_device *dev, int configuration); -extern void usb_set_device_state(struct usb_device *udev, - enum usb_device_state new_state); +extern void usb_lock_all_devices(void); +extern void usb_unlock_all_devices(void); /* for labeling diagnostics */ extern const char *usbcore_name; + +/* usbfs stuff */ +extern struct usb_driver usbfs_driver; +extern struct file_operations usbfs_devices_fops; +extern struct file_operations usbfs_device_file_operations; +extern void usbfs_conn_disc_event(void); + +struct dev_state { + struct list_head list; /* state list */ + struct usb_device *dev; + struct file *file; + spinlock_t lock; /* protects the async urb lists */ + struct list_head async_pending; + struct list_head async_completed; + wait_queue_head_t wait; /* wake up if a request completed */ + unsigned int discsignr; + struct task_struct *disctask; + void __user *disccontext; + unsigned long ifclaimed; +}; + diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 9189fb0da..c6e0693ed 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -39,6 +39,17 @@ config USB_GADGET If in doubt, say "N" and don't enable these drivers; most people don't have this kind of hardware (except maybe inside Linux PDAs). +config USB_GADGET_DEBUG_FILES + boolean "Debugging information files" + depends on USB_GADGET && PROC_FS + help + Some of the drivers in the "gadget" framework can expose + debugging information in files such as /proc/driver/udc + (for a peripheral controller). The information in these + files may help when you're troubleshooting or bringing up a + driver on a new board. Enable these files by choosing "Y" + here. If in doubt, or to conserve kernel memory, say "N". + # # USB Peripheral Controller Support # @@ -135,6 +146,18 @@ config USB_SA1100 depends on USB_GADGET_SA1100 default USB_GADGET +config USB_GADGET_LH7A40X + boolean "LH7A40X" + depends on ARCH_LH7A40X + help + This driver provides USB Device Controller driver for LH7A40x + +config USB_LH7A40X + tristate + depends on USB_GADGET_LH7A40X + default USB_GADGET + + config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" depends on USB && EXPERIMENTAL @@ -163,6 +186,37 @@ config USB_DUMMY_HCD depends on USB_GADGET_DUMMY_HCD default USB_GADGET +config USB_GADGET_OMAP + boolean "OMAP USB Device Controller" + depends on ARCH_OMAP + select ISP1301_OMAP if MACH_OMAP_H2 + help + Many Texas Instruments OMAP processors have flexible full + speed USB device controllers, with support for up to 30 + endpoints (plus endpoint zero). This driver supports the + controller in the OMAP 1611, and should work with controllers + in other OMAP processors too, given minor tweaks. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "omap_udc" and force all + gadget drivers to also be dynamically linked. + +config USB_OMAP + tristate + depends on USB_GADGET_OMAP + default USB_GADGET + +config USB_OTG + boolean "OTG Support" + depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD + help + The most notable feature of USB OTG is support for a + "Dual-Role" device, which can act as either a device + or a host. The initial role choice can be changed + later, when two dual-role devices talk to each other. + + Select this only if your OMAP board has a Mini-AB connector. + endchoice config USB_GADGET_DUALSPEED @@ -275,7 +329,7 @@ config USB_GADGETFS dynamically linked module called "gadgetfs". config USB_FILE_STORAGE - tristate "File-backed Storage Gadget (DEVELOPMENT)" + tristate "File-backed Storage Gadget" # we don't support the SA1100 because of its limitations depends on USB_GADGET_SA1100 = n help @@ -288,7 +342,7 @@ config USB_FILE_STORAGE dynamically linked module called "g_file_storage". config USB_FILE_STORAGE_TEST - bool "File-backed Storage Gadget test version" + bool "File-backed Storage Gadget testing version" depends on USB_FILE_STORAGE default n help diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 645d15cf5..d5fd04d88 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,13 +5,15 @@ obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o +obj-$(CONFIG_USB_OMAP) += omap_udc.o +obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o # # USB gadget drivers # g_zero-objs := zero.o usbstring.o config.o epautoconf.o g_ether-objs := ether.o usbstring.o config.o epautoconf.o -g_serial-objs := serial.o usbstring.o +g_serial-objs := serial.o usbstring.o config.o epautoconf.o gadgetfs-objs := inode.o g_file_storage-objs := file_storage.o usbstring.o config.o \ epautoconf.o diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 4c1b157cf..c283dbf3e 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -65,7 +65,7 @@ #define DRIVER_DESC "USB Host+Gadget Emulator" -#define DRIVER_VERSION "14 Mar 2004" +#define DRIVER_VERSION "29 Oct 2004" static const char driver_name [] = "dummy_hcd"; static const char driver_desc [] = "USB Host+Gadget Emulator"; @@ -95,6 +95,17 @@ struct dummy_request { struct usb_request req; }; +static inline struct dummy_ep *usb_ep_to_dummy_ep (struct usb_ep *_ep) +{ + return container_of (_ep, struct dummy_ep, ep); +} + +static inline struct dummy_request *usb_request_to_dummy_request + (struct usb_request *_req) +{ + return container_of (_req, struct dummy_request, req); +} + /*-------------------------------------------------------------------------*/ /* @@ -133,6 +144,7 @@ static const char *const ep_name [] = { #define FIFO_SIZE 64 struct dummy { + struct usb_hcd hcd; /* must come first! */ spinlock_t lock; /* @@ -149,37 +161,49 @@ struct dummy { /* * MASTER/HOST side support */ - struct usb_hcd hcd; - struct platform_device pdev; struct timer_list timer; u32 port_status; - int started; - struct completion released; + unsigned started:1; unsigned resuming:1; unsigned long re_timeout; struct usb_device *udev; }; -static struct dummy *the_controller; +static inline struct dummy *hcd_to_dummy (struct usb_hcd *hcd) +{ + return container_of(hcd, struct dummy, hcd); +} + +static inline struct device *dummy_dev (struct dummy *dum) +{ + return dum->hcd.self.controller; +} static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) { return container_of (ep->gadget, struct dummy, gadget); } +static inline struct dummy *gadget_to_dummy (struct usb_gadget *gadget) +{ + return container_of (gadget, struct dummy, gadget); +} + static inline struct dummy *gadget_dev_to_dummy (struct device *dev) { return container_of (dev, struct dummy, gadget.dev); } +static struct dummy *the_controller; + +/*-------------------------------------------------------------------------*/ + /* * This "hardware" may look a bit odd in diagnostics since it's got both * host and device sides; and it binds different drivers to each side. */ -#define hardware (&the_controller->pdev.dev) - -/*-------------------------------------------------------------------------*/ +static struct platform_device the_pdev; static struct device_driver dummy_driver = { .name = (char *) driver_name, @@ -195,8 +219,8 @@ static struct device_driver dummy_driver = { * drivers would do real i/o using dma, fifos, irqs, timers, etc. */ -#define is_enabled() \ - (the_controller->port_status & USB_PORT_STAT_ENABLE) +#define is_enabled(dum) \ + (dum->port_status & USB_PORT_STAT_ENABLE) static int dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) @@ -206,10 +230,12 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) unsigned max; int retval; - ep = container_of (_ep, struct dummy_ep, ep); + ep = usb_ep_to_dummy_ep (_ep); if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT) - if (!the_controller->driver || !is_enabled ()) + return -EINVAL; + dum = ep_to_dummy (ep); + if (!dum->driver || !is_enabled (dum)) return -ESHUTDOWN; max = desc->wMaxPacketSize & 0x3ff; @@ -221,7 +247,6 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) * have some extra sanity checks. (there could be more though, * especially for "ep9out" style fixed function ones.) */ - dum = container_of (ep->gadget, struct dummy, gadget); retval = -EINVAL; switch (desc->bmAttributes & 0x03) { case USB_ENDPOINT_XFER_BULK: @@ -290,7 +315,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) _ep->maxpacket = max; ep->desc = desc; - dev_dbg (hardware, "enabled %s (ep%d%s-%s) maxpacket %d\n", + dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", _ep->name, desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", @@ -334,7 +359,7 @@ static int dummy_disable (struct usb_ep *_ep) unsigned long flags; int retval; - ep = container_of (_ep, struct dummy_ep, ep); + ep = usb_ep_to_dummy_ep (_ep); if (!_ep || !ep->desc || _ep->name == ep0name) return -EINVAL; dum = ep_to_dummy (ep); @@ -345,7 +370,7 @@ static int dummy_disable (struct usb_ep *_ep) nuke (dum, ep); spin_unlock_irqrestore (&dum->lock, flags); - dev_dbg (hardware, "disabled %s\n", _ep->name); + dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name); return retval; } @@ -355,9 +380,9 @@ dummy_alloc_request (struct usb_ep *_ep, int mem_flags) struct dummy_ep *ep; struct dummy_request *req; - ep = container_of (_ep, struct dummy_ep, ep); if (!_ep) return 0; + ep = usb_ep_to_dummy_ep (_ep); req = kmalloc (sizeof *req, mem_flags); if (!req) @@ -373,11 +398,11 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req) struct dummy_ep *ep; struct dummy_request *req; - ep = container_of (_ep, struct dummy_ep, ep); + ep = usb_ep_to_dummy_ep (_ep); if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) return; - req = container_of (_req, struct dummy_request, req); + req = usb_request_to_dummy_request (_req); WARN_ON (!list_empty (&req->queue)); kfree (req); } @@ -389,9 +414,14 @@ dummy_alloc_buffer ( dma_addr_t *dma, int mem_flags ) { - char *retval; + char *retval; + struct dummy_ep *ep; + struct dummy *dum; + + ep = usb_ep_to_dummy_ep (_ep); + dum = ep_to_dummy (ep); - if (!the_controller->driver) + if (!dum->driver) return 0; retval = kmalloc (bytes, mem_flags); *dma = (dma_addr_t) retval; @@ -412,9 +442,6 @@ dummy_free_buffer ( static void fifo_complete (struct usb_ep *ep, struct usb_request *req) { -#if 0 - dev_dbg (hardware, "fifo_complete: %d\n", req->status); -#endif } static int @@ -425,21 +452,20 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags) struct dummy *dum; unsigned long flags; - req = container_of (_req, struct dummy_request, req); + req = usb_request_to_dummy_request (_req); if (!_req || !list_empty (&req->queue) || !_req->complete) return -EINVAL; - ep = container_of (_ep, struct dummy_ep, ep); + ep = usb_ep_to_dummy_ep (_ep); if (!_ep || (!ep->desc && _ep->name != ep0name)) return -EINVAL; - if (!the_controller->driver || !is_enabled ()) + dum = ep_to_dummy (ep); + if (!dum->driver || !is_enabled (dum)) return -ESHUTDOWN; - dum = container_of (ep->gadget, struct dummy, gadget); - #if 0 - dev_dbg (hardware, "ep %p queue req %p to %s, len %d buf %p\n", + dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", ep, _req, _ep->name, _req->length, _req->buf); #endif @@ -482,13 +508,13 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) unsigned long flags; struct dummy_request *req = 0; - if (!the_controller->driver) - return -ESHUTDOWN; - if (!_ep || !_req) return retval; - ep = container_of (_ep, struct dummy_ep, ep); - dum = container_of (ep->gadget, struct dummy, gadget); + ep = usb_ep_to_dummy_ep (_ep); + dum = ep_to_dummy (ep); + + if (!dum->driver) + return -ESHUTDOWN; spin_lock_irqsave (&dum->lock, flags); list_for_each_entry (req, &ep->queue, queue) { @@ -502,9 +528,9 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) spin_unlock_irqrestore (&dum->lock, flags); if (retval == 0) { - dev_dbg (hardware, "dequeued req %p from %s, len %d buf %p\n", + dev_dbg (dummy_dev(dum), + "dequeued req %p from %s, len %d buf %p\n", req, _ep->name, _req->length, _req->buf); - _req->complete (_ep, _req); } return retval; @@ -514,12 +540,14 @@ static int dummy_set_halt (struct usb_ep *_ep, int value) { struct dummy_ep *ep; + struct dummy *dum; if (!_ep) return -EINVAL; - if (!the_controller->driver) + ep = usb_ep_to_dummy_ep (_ep); + dum = ep_to_dummy (ep); + if (!dum->driver) return -ESHUTDOWN; - ep = container_of (_ep, struct dummy_ep, ep); if (!value) ep->halted = 0; else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && @@ -563,7 +591,7 @@ static int dummy_wakeup (struct usb_gadget *_gadget) { struct dummy *dum; - dum = container_of (_gadget, struct dummy, gadget); + dum = gadget_to_dummy (_gadget); if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0 || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))) return -EINVAL; @@ -578,7 +606,7 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) { struct dummy *dum; - dum = container_of (_gadget, struct dummy, gadget); + dum = gadget_to_dummy (_gadget); if (value) dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED); else @@ -596,14 +624,13 @@ static const struct usb_gadget_ops dummy_ops = { /* "function" sysfs attribute */ static ssize_t -show_function (struct device *_dev, char *buf) +show_function (struct device *dev, char *buf) { - struct dummy *dum = the_controller; + struct dummy *dum = gadget_dev_to_dummy (dev); - if (!dum->driver->function - || strlen (dum->driver->function) > PAGE_SIZE) + if (!dum->driver || !dum->driver->function) return 0; - return snprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); + return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); } DEVICE_ATTR (function, S_IRUGO, show_function, NULL); @@ -626,17 +653,11 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL); static void dummy_udc_release (struct device *dev) { - struct dummy *dum = gadget_dev_to_dummy (dev); - - complete (&dum->released); } static void -dummy_hc_release (struct device *dev) +dummy_pdev_release (struct device *dev) { - struct dummy *dum = dev_get_drvdata (dev); - - complete (&dum->released); } static int @@ -645,7 +666,7 @@ dummy_register_udc (struct dummy *dum) int rc; strcpy (dum->gadget.dev.bus_id, "udc"); - dum->gadget.dev.parent = &dum->pdev.dev; + dum->gadget.dev.parent = dummy_dev(dum); dum->gadget.dev.release = dummy_udc_release; rc = device_register (&dum->gadget.dev); @@ -658,9 +679,7 @@ static void dummy_unregister_udc (struct dummy *dum) { device_remove_file (&dum->gadget.dev, &dev_attr_function); - init_completion (&dum->released); device_unregister (&dum->gadget.dev); - wait_for_completion (&dum->released); } int @@ -712,7 +731,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) dum->driver = driver; dum->gadget.dev.driver = &driver->driver; - dev_dbg (hardware, "binding gadget driver '%s'\n", driver->driver.name); + dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n", + driver->driver.name); if ((retval = driver->bind (&dum->gadget)) != 0) { dum->driver = 0; dum->gadget.dev.driver = 0; @@ -720,7 +740,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) } // FIXME: Check these calls for errors and re-order - driver->driver.bus = dum->pdev.dev.bus; + driver->driver.bus = dum->gadget.dev.parent->bus; driver_register (&driver->driver); device_bind_driver (&dum->gadget.dev); @@ -766,12 +786,13 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (!driver || driver != dum->driver) return -EINVAL; - dev_dbg (hardware, "unregister gadget driver '%s'\n", + dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n", driver->driver.name); spin_lock_irqsave (&dum->lock, flags); stop_activity (dum, driver); - dum->port_status &= ~USB_PORT_STAT_CONNECTION; + dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | + USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); dum->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); spin_unlock_irqrestore (&dum->lock, flags); @@ -816,17 +837,17 @@ static int dummy_urb_enqueue ( struct dummy *dum; unsigned long flags; - /* patch to usb_sg_init() is in 2.5.60 */ - BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); + if (!urb->transfer_buffer && urb->transfer_buffer_length) + return -EINVAL; - dum = container_of (hcd, struct dummy, hcd); + dum = hcd_to_dummy (hcd); spin_lock_irqsave (&dum->lock, flags); if (!dum->udev) { dum->udev = urb->dev; usb_get_dev (dum->udev); } else if (unlikely (dum->udev != urb->dev)) - dev_err (hardware, "usb_device address has changed!\n"); + dev_err (dummy_dev(dum), "usb_device address has changed!\n"); urb->hcpriv = dum; if (usb_pipetype (urb->pipe) == PIPE_CONTROL) @@ -1052,7 +1073,7 @@ static void dummy_timer (unsigned long _dum) total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/; break; default: - dev_err (hardware, "bogus device speed\n"); + dev_err (dummy_dev(dum), "bogus device speed\n"); return; } @@ -1062,7 +1083,8 @@ static void dummy_timer (unsigned long _dum) spin_lock_irqsave (&dum->lock, flags); if (!dum->udev) { - dev_err (hardware, "timer fired with no URBs pending?\n"); + dev_err (dummy_dev(dum), + "timer fired with no URBs pending?\n"); spin_unlock_irqrestore (&dum->lock, flags); return; } @@ -1103,10 +1125,10 @@ restart: ep = find_endpoint(dum, address); if (!ep) { /* set_configuration() disagreement */ - dev_err (hardware, + dev_dbg (dummy_dev(dum), "no ep configured for urb %p\n", urb); - maybe_set_status (urb, -ETIMEDOUT); + maybe_set_status (urb, -EPROTO); goto return_urb; } @@ -1119,7 +1141,7 @@ restart: } if (ep->halted && !ep->setup_stage) { /* NOTE: must not be iso! */ - dev_dbg (hardware, "ep %s halted, urb %p\n", + dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n", ep->ep.name, urb); maybe_set_status (urb, -EPIPE); goto return_urb; @@ -1145,7 +1167,8 @@ restart: list_for_each_entry (req, &ep->queue, queue) { list_del_init (&req->queue); req->req.status = -EOVERFLOW; - dev_dbg (hardware, "stale req = %p\n", req); + dev_dbg (dummy_dev(dum), "stale req = %p\n", + req); spin_unlock (&dum->lock); req->req.complete (&ep->ep, &req->req); @@ -1167,7 +1190,7 @@ restart: break; dum->address = setup.wValue; maybe_set_status (urb, 0); - dev_dbg (hardware, "set_address = %d\n", + dev_dbg (dummy_dev(dum), "set_address = %d\n", setup.wValue); value = 0; break; @@ -1283,7 +1306,7 @@ restart: if (value < 0) { if (value != -EOPNOTSUPP) - dev_dbg (hardware, + dev_dbg (dummy_dev(dum), "setup --> %d\n", value); maybe_set_status (urb, -EPIPE); @@ -1363,14 +1386,14 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf) unsigned long flags; int retval; - dum = container_of (hcd, struct dummy, hcd); + dum = hcd_to_dummy (hcd); spin_lock_irqsave (&dum->lock, flags); if (!(dum->port_status & PORT_C_MASK)) retval = 0; else { *buf = (1 << 1); - dev_dbg (hardware, "port status 0x%08x has changes\n", + dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n", dum->port_status); retval = 1; } @@ -1402,7 +1425,7 @@ static int dummy_hub_control ( int retval = 0; unsigned long flags; - dum = container_of (hcd, struct dummy, hcd); + dum = hcd_to_dummy (hcd); spin_lock_irqsave (&dum->lock, flags); switch (typeReq) { case ClearHubFeature: @@ -1410,9 +1433,12 @@ static int dummy_hub_control ( case ClearPortFeature: switch (wValue) { case USB_PORT_FEAT_SUSPEND: - /* 20msec resume signaling */ - dum->resuming = 1; - dum->re_timeout = jiffies + ((HZ * 20)/1000); + if (dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) { + /* 20msec resume signaling */ + dum->resuming = 1; + dum->re_timeout = jiffies + + msecs_to_jiffies(20); + } break; case USB_PORT_FEAT_POWER: dum->port_status = 0; @@ -1441,7 +1467,7 @@ static int dummy_hub_control ( dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND); dum->resuming = 0; dum->re_timeout = 0; - if (dum->driver->resume) { + if (dum->driver && dum->driver->resume) { spin_unlock (&dum->lock); dum->driver->resume (&dum->gadget); spin_lock (&dum->lock); @@ -1482,11 +1508,15 @@ static int dummy_hub_control ( case SetPortFeature: switch (wValue) { case USB_PORT_FEAT_SUSPEND: - dum->port_status |= (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); + if ((dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) + == 0) { + dum->port_status |= + (1 << USB_PORT_FEAT_SUSPEND); + if (dum->driver && dum->driver->suspend) { + spin_unlock (&dum->lock); + dum->driver->suspend (&dum->gadget); + spin_lock (&dum->lock); + } } break; case USB_PORT_FEAT_RESET: @@ -1496,14 +1526,15 @@ static int dummy_hub_control ( | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); + dev_dbg (dummy_dev(dum), + "disconnect\n"); stop_activity (dum, dum->driver); } /* FIXME test that code path! */ } /* 50msec reset signaling */ - dum->re_timeout = jiffies + ((HZ * 50)/1000); + dum->re_timeout = jiffies + msecs_to_jiffies(50); /* FALLTHROUGH */ default: dum->port_status |= (1 << wValue); @@ -1511,7 +1542,7 @@ static int dummy_hub_control ( break; default: - dev_dbg (hardware, + dev_dbg (dummy_dev(dum), "hub control req%04x v%04x i%04x l%d\n", typeReq, wValue, wIndex, wLength); @@ -1531,20 +1562,12 @@ static struct usb_hcd *dummy_alloc (void) dum = kmalloc (sizeof *dum, SLAB_KERNEL); if (dum == NULL) - return 0; + return NULL; + the_controller = dum; memset (dum, 0, sizeof *dum); return &dum->hcd; } -static void dummy_free (struct usb_hcd *hcd) -{ - struct dummy *dum; - - dum = container_of (hcd, struct dummy, hcd); - WARN_ON (dum->driver != 0); - kfree (dum); -} - /*-------------------------------------------------------------------------*/ static inline ssize_t @@ -1576,7 +1599,8 @@ show_urb (char *buf, size_t size, struct urb *urb) static ssize_t show_urbs (struct device *dev, char *buf) { - struct dummy *dum = dev_get_drvdata(dev); + struct usb_hcd *hcd = dev_get_drvdata (dev); + struct dummy *dum = hcd_to_dummy (hcd); struct urb *urb; size_t size = 0; unsigned long flags; @@ -1599,17 +1623,13 @@ show_urbs (struct device *dev, char *buf) } static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); - -static const struct hc_driver dummy_hcd; - static int dummy_start (struct usb_hcd *hcd) { struct dummy *dum; - struct usb_bus *bus; struct usb_device *root; int retval; - dum = container_of (hcd, struct dummy, hcd); + dum = hcd_to_dummy (hcd); /* * MASTER side init ... we emulate a root hub that'll only ever @@ -1618,121 +1638,56 @@ static int dummy_start (struct usb_hcd *hcd) */ spin_lock_init (&dum->lock); - retval = driver_register (&dummy_driver); - if (retval < 0) - return retval; - - dum->pdev.name = "hc"; - dum->pdev.dev.driver = &dummy_driver; - dev_set_drvdata(&dum->pdev.dev, dum); - dum->pdev.dev.release = dummy_hc_release; - retval = platform_device_register (&dum->pdev); - if (retval < 0) { - driver_unregister (&dummy_driver); - return retval; - } - dev_info (&dum->pdev.dev, "%s, driver " DRIVER_VERSION "\n", - driver_desc); - - hcd->self.controller = &dum->pdev.dev; - - /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ - device_create_file (hcd->self.controller, &dev_attr_urbs); - init_timer (&dum->timer); dum->timer.function = dummy_timer; dum->timer.data = (unsigned long) dum; - /* root hub will appear as another device */ - dum->hcd.driver = (struct hc_driver *) &dummy_hcd; - dum->hcd.description = dummy_hcd.description; - dum->hcd.product_desc = "Dummy host controller"; - - bus = hcd_to_bus (&dum->hcd); - bus->bus_name = dum->pdev.dev.bus_id; - usb_bus_init (bus); - bus->op = &usb_hcd_operations; - bus->hcpriv = &dum->hcd; - - /* FIXME don't require the pci-based buffer/alloc impls; - * the "generic dma" implementation still requires them, - * it's not very generic yet. - */ - if ((retval = hcd_buffer_create (&dum->hcd)) != 0) { -clean0: - init_completion (&dum->released); - platform_device_unregister (&dum->pdev); - wait_for_completion (&dum->released); - driver_unregister (&dummy_driver); - return retval; - } - - INIT_LIST_HEAD (&hcd->dev_list); - usb_register_bus (bus); - - root = usb_alloc_dev (0, bus, 0); - if (!root) { - retval = -ENOMEM; -clean1: - hcd_buffer_destroy (&dum->hcd); - usb_deregister_bus (bus); - goto clean0; - } + root = usb_alloc_dev (0, &hcd->self, 0); + if (!root) + return -ENOMEM; /* root hub enters addressed state... */ - dum->hcd.state = USB_STATE_RUNNING; + hcd->state = USB_STATE_RUNNING; root->speed = USB_SPEED_HIGH; /* ...then configured, so khubd sees us. */ - if ((retval = hcd_register_root (root, &dum->hcd)) != 0) { + if ((retval = hcd_register_root (root, hcd)) != 0) { usb_put_dev (root); -clean2: - dum->hcd.state = USB_STATE_QUIESCING; - goto clean1; +clean: + hcd->state = USB_STATE_QUIESCING; + return retval; } /* only show a low-power port: just 8mA */ hub_set_power_budget (root, 8); - dum->started = 1; - if ((retval = dummy_register_udc (dum)) != 0) { - dum->started = 0; - usb_disconnect (&bus->root_hub); - goto clean2; + usb_disconnect (&hcd->self.root_hub); + goto clean; } + + /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ + device_create_file (dummy_dev(dum), &dev_attr_urbs); + + dum->started = 1; return 0; } static void dummy_stop (struct usb_hcd *hcd) { struct dummy *dum; - struct usb_bus *bus; - dum = container_of (hcd, struct dummy, hcd); + dum = hcd_to_dummy (hcd); if (!dum->started) return; dum->started = 0; + device_remove_file (dummy_dev(dum), &dev_attr_urbs); + usb_gadget_unregister_driver (dum->driver); dummy_unregister_udc (dum); - bus = hcd_to_bus (&dum->hcd); - hcd->state = USB_STATE_QUIESCING; - dev_dbg (hardware, "remove root hub\n"); - usb_disconnect (&bus->root_hub); - - hcd_buffer_destroy (&dum->hcd); - usb_deregister_bus (bus); - - dev_info (hardware, "stopped\n"); - - device_remove_file (hcd->self.controller, &dev_attr_urbs); - init_completion (&dum->released); - platform_device_unregister (&dum->pdev); - wait_for_completion (&dum->released); - - driver_unregister (&dummy_driver); + dev_info (dummy_dev(dum), "stopped\n"); } /*-------------------------------------------------------------------------*/ @@ -1750,7 +1705,6 @@ static const struct hc_driver dummy_hcd = { .stop = dummy_stop, .hcd_alloc = dummy_alloc, - .hcd_free = dummy_free, .urb_enqueue = dummy_urb_enqueue, .urb_dequeue = dummy_urb_dequeue, @@ -1761,34 +1715,128 @@ static const struct hc_driver dummy_hcd = { .hub_control = dummy_hub_control, }; -/*-------------------------------------------------------------------------*/ +static void dummy_remove (struct device *dev); -static int __init init (void) +static int dummy_probe (struct device *dev) { struct usb_hcd *hcd; - int value; + struct dummy *dum; + int retval; - if (usb_disabled ()) - return -ENODEV; - if ((hcd = dummy_alloc ()) == 0) + dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); + + hcd = dummy_alloc (); + if (hcd == NULL) { + dev_dbg (dev, "hcd_alloc failed\n"); return -ENOMEM; + } - the_controller = container_of (hcd, struct dummy, hcd); - value = dummy_start (hcd); + dev_set_drvdata (dev, hcd); + dum = hcd_to_dummy (hcd); - if (value != 0) { - dummy_free (hcd); - the_controller = 0; + hcd->driver = (struct hc_driver *) &dummy_hcd; + hcd->description = dummy_hcd.description; + hcd->self.controller = dev; + + /* FIXME don't require the pci-based buffer/alloc impls; + * the "generic dma" implementation still requires them, + * it's not very generic yet. + */ + retval = hcd_buffer_create (hcd); + if (retval != 0) { + dev_dbg (dev, "pool alloc failed\n"); + goto err1; } - return value; + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.release = &usb_hcd_release; + hcd->self.hcpriv = hcd; + hcd->self.bus_name = dev->bus_id; + hcd->product_desc = "Dummy host controller"; + + INIT_LIST_HEAD (&hcd->dev_list); + + usb_register_bus (&hcd->self); + + if ((retval = dummy_start (hcd)) < 0) + dummy_remove (dev); + return retval; + +err1: + kfree (hcd); + dev_set_drvdata (dev, NULL); + return retval; +} + +static void dummy_remove (struct device *dev) +{ + struct usb_hcd *hcd; + struct dummy *dum; + + hcd = dev_get_drvdata (dev); + dum = hcd_to_dummy (hcd); + + hcd->state = USB_STATE_QUIESCING; + + dev_dbg (dev, "roothub graceful disconnect\n"); + usb_disconnect (&hcd->self.root_hub); + + hcd->driver->stop (hcd); + hcd->state = USB_STATE_HALT; + + hcd_buffer_destroy (hcd); + + dev_set_drvdata (dev, NULL); + usb_deregister_bus (&hcd->self); + the_controller = NULL; +} + +/*-------------------------------------------------------------------------*/ + +static int dummy_pdev_detect (void) +{ + int retval; + + retval = driver_register (&dummy_driver); + if (retval < 0) + return retval; + + the_pdev.name = "hc"; + the_pdev.dev.driver = &dummy_driver; + the_pdev.dev.release = dummy_pdev_release; + + retval = platform_device_register (&the_pdev); + if (retval < 0) + driver_unregister (&dummy_driver); + return retval; +} + +static void dummy_pdev_remove (void) +{ + platform_device_unregister (&the_pdev); + driver_unregister (&dummy_driver); +} + +/*-------------------------------------------------------------------------*/ + +static int __init init (void) +{ + int retval; + + if (usb_disabled ()) + return -ENODEV; + if ((retval = dummy_pdev_detect ()) != 0) + return retval; + if ((retval = dummy_probe (&the_pdev.dev)) != 0) + dummy_pdev_remove (); + return retval; } module_init (init); static void __exit cleanup (void) { - dummy_stop (&the_controller->hcd); - dummy_free (&the_controller->hcd); - the_controller = 0; + dummy_remove (&the_pdev.dev); + dummy_pdev_remove (); } module_exit (cleanup); - diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 174afd47b..d15c26965 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -63,6 +63,7 @@ /* * Ethernet gadget driver -- with CDC and non-CDC options + * Builds on hardware support for a full duplex link. * * CDC Ethernet is the standard USB solution for sending Ethernet frames * using USB. Real hardware tends to use the same framing protocol but look @@ -83,7 +84,7 @@ */ #define DRIVER_DESC "Ethernet Gadget" -#define DRIVER_VERSION "St Patrick's Day 2004" +#define DRIVER_VERSION "Equinox 2004" static const char shortname [] = "ether"; static const char driver_desc [] = DRIVER_DESC; @@ -222,6 +223,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_LH7A40X +#define DEV_CONFIG_CDC +#endif + #ifdef CONFIG_USB_GADGET_MQ11XX #define DEV_CONFIG_CDC #endif @@ -230,6 +235,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_N9604 +#define DEV_CONFIG_CDC +#endif + +#ifdef CONFIG_USB_GADGET_PXA27X +#define DEV_CONFIG_CDC +#endif + /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. @@ -382,7 +395,7 @@ eth_config = { .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = STRING_CDC, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, + .bMaxPower = 50, }; #ifdef CONFIG_USB_ETH_RNDIS @@ -396,7 +409,7 @@ rndis_config = { .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE, .iConfiguration = STRING_RNDIS, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, + .bMaxPower = 50, }; #endif @@ -847,7 +860,7 @@ static inline void __init hs_subset_descriptors(void) /* descriptors that are built on-demand */ -static char manufacturer [40]; +static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; #ifdef DEV_CONFIG_CDC @@ -855,7 +868,7 @@ static char product_desc [40] = DRIVER_DESC; static char ethaddr [2 * ETH_ALEN + 1]; #endif -/* static strings, in iso 8859/1 */ +/* static strings, in UTF-8 */ static struct usb_string strings [] = { { STRING_MANUFACTURER, manufacturer, }, { STRING_PRODUCT, product_desc, }, @@ -897,9 +910,9 @@ config_buf (enum usb_device_speed speed, if (type == USB_DT_OTHER_SPEED_CONFIG) hs = !hs; -#define which_fn(t) (hs ? & hs_ ## t ## _function : & fs_ ## t ## _function) +#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function) #else -#define which_fn(t) (& fs_ ## t ## _function) +#define which_fn(t) (fs_ ## t ## _function) #endif if (index >= device_desc.bNumConfigurations) @@ -911,14 +924,12 @@ config_buf (enum usb_device_speed speed, */ if (device_desc.bNumConfigurations == 2 && index == 0) { config = &rndis_config; - function = (const struct usb_descriptor_header **) - which_fn (rndis); + function = which_fn (rndis); } else #endif { config = ð_config; - function = (const struct usb_descriptor_header **) - which_fn (eth); + function = which_fn (eth); } /* for now, don't advertise srp-only devices */ @@ -1195,13 +1206,20 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) result = -EINVAL; /* FALL THROUGH */ case 0: - return result; + break; } - if (result) - eth_reset_config (dev); - else { + if (result) { + if (number) + eth_reset_config (dev); + usb_gadget_vbus_draw(dev->gadget, + dev->gadget->is_otg ? 8 : 100); + } else { char *speed; + unsigned power; + + power = 2 * eth_config.bMaxPower; + usb_gadget_vbus_draw(dev->gadget, power); switch (gadget->speed) { case USB_SPEED_FULL: speed = "full"; break; @@ -1212,8 +1230,8 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) } dev->config = number; - INFO (dev, "%s speed config #%d: %s, using %s\n", - speed, number, driver_desc, + INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", + speed, number, power, driver_desc, dev->rndis ? "RNDIS" : (dev->cdc @@ -1372,8 +1390,9 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req) { if (req->status || req->actual != req->length) - DEBUG (dev, "rndis response complete --> %d, %d/%d\n", - req->status, req->actual, req->length); + DEBUG ((struct eth_dev *) ep->driver_data, + "rndis response complete --> %d, %d/%d\n", + req->status, req->actual, req->length); /* done sending after CDC_GET_ENCAPSULATED_RESPONSE */ } @@ -1667,7 +1686,7 @@ eth_disconnect (struct usb_gadget *gadget) static int eth_change_mtu (struct net_device *net, int new_mtu) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); // FIXME if rndis, don't change while link's live @@ -1682,58 +1701,29 @@ static int eth_change_mtu (struct net_device *net, int new_mtu) static struct net_device_stats *eth_get_stats (struct net_device *net) { - return &((struct eth_dev *) net->priv)->stats; + return &((struct eth_dev *)netdev_priv(net))->stats; } -static int eth_ethtool_ioctl (struct net_device *net, void __user *useraddr) +static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) { - struct eth_dev *dev = (struct eth_dev *) net->priv; - u32 cmd; - - if (get_user (cmd, (u32 __user *)useraddr)) - return -EFAULT; - switch (cmd) { - - case ETHTOOL_GDRVINFO: { /* get driver info */ - struct ethtool_drvinfo info; - - memset (&info, 0, sizeof info); - info.cmd = ETHTOOL_GDRVINFO; - strlcpy (info.driver, shortname, sizeof info.driver); - strlcpy (info.version, DRIVER_VERSION, sizeof info.version); - strlcpy (info.fw_version, dev->gadget->name, - sizeof info.fw_version); - strlcpy (info.bus_info, dev->gadget->dev.bus_id, - sizeof info.bus_info); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - case ETHTOOL_GLINK: { /* get link status */ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = (dev->gadget->speed != USB_SPEED_UNKNOWN); - if (copy_to_user (useraddr, &edata, sizeof (edata))) - return -EFAULT; - return 0; - } - - } - /* Note that the ethtool user space code requires EOPNOTSUPP */ - return -EOPNOTSUPP; + struct eth_dev *dev = netdev_priv(net); + strlcpy(p->driver, shortname, sizeof p->driver); + strlcpy(p->version, DRIVER_VERSION, sizeof p->version); + strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); + strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info); } -static int eth_ioctl (struct net_device *net, struct ifreq *rq, int cmd) +static u32 eth_get_link(struct net_device *net) { - switch (cmd) { - case SIOCETHTOOL: - return eth_ethtool_ioctl(net, rq->ifr_data); - default: - return -EOPNOTSUPP; - } + struct eth_dev *dev = netdev_priv(net); + return dev->gadget->speed != USB_SPEED_UNKNOWN; } +static struct ethtool_ops ops = { + .get_drvinfo = eth_get_drvinfo, + .get_link = eth_get_link +}; + static void defer_kevent (struct eth_dev *dev, int flag) { if (test_and_set_bit (flag, &dev->todo)) @@ -1994,7 +1984,7 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req) static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); int length = skb->len; int retval; struct usb_request *req = NULL; @@ -2095,11 +2085,13 @@ static void rndis_send_media_state (struct eth_dev *dev, int connect) } } -static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) +static void +rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) { if (req->status || req->actual != req->length) - DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n", - req->status, req->actual, req->length); + DEBUG ((struct eth_dev *) ep->driver_data, + "rndis control ack complete --> %d, %d/%d\n", + req->status, req->actual, req->length); usb_ep_free_buffer(ep, req->buf, req->dma, 8); usb_ep_free_request(ep, req); @@ -2107,7 +2099,7 @@ static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *r static int rndis_control_ack (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); u32 length; struct usb_request *resp; @@ -2174,7 +2166,7 @@ static void eth_start (struct eth_dev *dev, int gfp_flags) static int eth_open (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); DEBUG (dev, "%s\n", __FUNCTION__); if (netif_carrier_ok (dev->net)) @@ -2184,7 +2176,7 @@ static int eth_open (struct net_device *net) static int eth_stop (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); VDEBUG (dev, "%s\n", __FUNCTION__); netif_stop_queue (net); @@ -2195,7 +2187,7 @@ static int eth_stop (struct net_device *net) ); /* ensure there are no more active requests */ - if (dev->gadget->speed != USB_SPEED_UNKNOWN) { + if (dev->config) { usb_ep_disable (dev->in_ep); usb_ep_disable (dev->out_ep); if (netif_carrier_ok (dev->net)) { @@ -2329,6 +2321,12 @@ eth_bind (struct usb_gadget *gadget) device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207); } else if (gadget_is_omap (gadget)) { device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208); + } else if (gadget_is_lh7a40x(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209); + } else if (gadget_is_n9604(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210); + } else if (gadget_is_pxa27x(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); } else { /* can't assume CDC works. don't want to default to * anything less functional on CDC-capable hardware, @@ -2461,15 +2459,17 @@ autoconf_fail: if (gadget->is_otg) { otg_descriptor.bmAttributes |= USB_OTG_HNP, eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + eth_config.bMaxPower = 4; #ifdef CONFIG_USB_ETH_RNDIS rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + rndis_config.bMaxPower = 4; #endif } net = alloc_etherdev (sizeof *dev); if (!net) return status; - dev = net->priv; + dev = netdev_priv(net); spin_lock_init (&dev->lock); INIT_WORK (&dev->work, eth_work, dev); INIT_LIST_HEAD (&dev->tx_reqs); @@ -2513,7 +2513,7 @@ autoconf_fail: net->stop = eth_stop; // watchdog_timeo, tx_timeout ... // set_multicast_list - net->do_ioctl = eth_ioctl; + SET_ETHTOOL_OPS(net, &ops); /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 9b978911e..84d1f39cb 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -46,17 +46,16 @@ * * Backing storage is provided by a regular file or a block device, specified * by the "file" module parameter. Access can be limited to read-only by - * setting the optional "ro" module parameter. + * setting the optional "ro" module parameter. The gadget will indicate that + * it has removable media if the optional "removable" module parameter is set. * * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected * by the optional "transport" module parameter. It also supports the * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by - * the optional "protocol" module parameter. For testing purposes the - * gadget will indicate that it has removable media if the optional - * "removable" module parameter is set. In addition, the default Vendor ID, - * Product ID, and release number can be overridden. + * the optional "protocol" module parameter. In addition, the default + * Vendor ID, Product ID, and release number can be overridden. * * There is support for multiple logical units (LUNs), each of which has * its own backing file. The number of LUNs can be set using the optional @@ -79,13 +78,13 @@ * the files or block devices used for * backing storage * ro=b[,b...] Default false, booleans for read-only access + * removable Default false, boolean for removable media * luns=N Default N = number of filenames, number of * LUNs to support * transport=XXX Default BBB, transport name (CB, CBI, or BBB) * protocol=YYY Default SCSI, protocol name (RBC, 8020 or * ATAPI, QIC, UFI, 8070, or SCSI; * also 1 - 6) - * removable Default false, boolean for removable media * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID * release=0xRRRR Override the USB release number (bcdDevice) @@ -97,16 +96,16 @@ * boolean to permit the driver to halt * bulk endpoints * - * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro" - * options are available; default values are used for everything else. + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", + * "removable", and "luns" options are available; default values are used + * for everything else. * * The pathnames of the backing files and the ro settings are available in * the attribute files "file" and "ro" in the lun subdirectory of the - * gadget's sysfs directory. If CONFIG_USB_FILE_STORAGE_TEST and the - * "removable" option are both set, writing to these files will simulate - * ejecting/loading the medium (writing an empty line means eject) and - * adjusting a write-enable tab. Changes to the ro setting are not allowed - * when the medium is loaded. + * gadget's sysfs directory. If the "removable" option is set, writing to + * these files will simulate ejecting/loading the medium (writing an empty + * line means eject) and adjusting a write-enable tab. Changes to the ro + * setting are not allowed when the medium is loaded. * * This gadget driver is heavily based on "Gadget Zero" by David Brownell. */ @@ -178,7 +177,10 @@ * Bulk-only specification requires a stall. In such cases the driver * will halt the endpoint and set a flag indicating that it should clear * the halt in software during the next device reset. Hopefully this - * will permit everything to work correctly. + * will permit everything to work correctly. Furthermore, although the + * specification allows the bulk-out endpoint to halt when the host sends + * too much data, implementing this would cause an unavoidable race. + * The driver will always use the "no-stall" approach for OUT transfers. * * One subtle point concerns sending status-stage responses for ep0 * requests. Some of these requests, such as device reset, can involve @@ -215,6 +217,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +235,7 @@ #include #include #include +#include #include #include #include @@ -246,7 +250,7 @@ #define DRIVER_DESC "File-backed Storage Gadget" #define DRIVER_NAME "g_file_storage" -#define DRIVER_VERSION "21 March 2004" +#define DRIVER_VERSION "20 October 2004" static const char longname[] = DRIVER_DESC; static const char shortname[] = DRIVER_NAME; @@ -365,20 +369,23 @@ static struct { }; -module_param_array(file, charp, mod_data.num_filenames, S_IRUGO); +module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO); MODULE_PARM_DESC(file, "names of backing files or devices"); -module_param_array(ro, bool, mod_data.num_ros, S_IRUGO); +module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO); MODULE_PARM_DESC(ro, "true to force read-only"); +module_param_named(luns, mod_data.nluns, uint, S_IRUGO); +MODULE_PARM_DESC(luns, "number of LUNs"); + +module_param_named(removable, mod_data.removable, bool, S_IRUGO); +MODULE_PARM_DESC(removable, "true to simulate removable media"); + -/* In the non-TEST version, only the file and ro module parameters +/* In the non-TEST version, only the module parameters listed above * are available. */ #ifdef CONFIG_USB_FILE_STORAGE_TEST -module_param_named(luns, mod_data.nluns, uint, S_IRUGO); -MODULE_PARM_DESC(luns, "number of LUNs"); - module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); @@ -386,9 +393,6 @@ module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " "8070, or SCSI)"); -module_param_named(removable, mod_data.removable, bool, S_IRUGO); -MODULE_PARM_DESC(removable, "true to simulate removable media"); - module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); MODULE_PARM_DESC(vendor, "USB Vendor ID"); @@ -426,9 +430,9 @@ MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); /* Command Block Wrapper */ struct bulk_cb_wrap { - u32 Signature; // Contains 'USBC' + __le32 Signature; // Contains 'USBC' u32 Tag; // Unique per command id - u32 DataTransferLength; // Size of the data + __le32 DataTransferLength; // Size of the data u8 Flags; // Direction in bit 7 u8 Lun; // LUN (normally 0) u8 Length; // Of the CDB, <= MAX_COMMAND_SIZE @@ -441,9 +445,9 @@ struct bulk_cb_wrap { /* Command Status Wrapper */ struct bulk_cs_wrap { - u32 Signature; // Should = 'USBS' + __le32 Signature; // Should = 'USBS' u32 Tag; // Same as original command - u32 Residue; // Amount not transferred + __le32 Residue; // Amount not transferred u8 Status; // See below }; @@ -525,11 +529,6 @@ struct interrupt_data { * parts of the driver that aren't used in the non-TEST version. Even gcc * can recognize when a test of a constant expression yields a dead code * path. - * - * Also, in the non-TEST version, open_backing_file() is only used during - * initialization and the sysfs attribute store_xxx routines aren't used - * at all. We will define NORMALLY_INIT to mark them as __init so they - * don't occupy kernel code space unnecessarily. */ #ifdef CONFIG_USB_FILE_STORAGE_TEST @@ -537,16 +536,12 @@ struct interrupt_data { #define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK) #define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI) #define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI) -#define backing_file_is_open(curlun) ((curlun)->filp != NULL) -#define NORMALLY_INIT #else #define transport_is_bbb() 1 #define transport_is_cbi() 0 #define protocol_is_scsi() 1 -#define backing_file_is_open(curlun) 1 -#define NORMALLY_INIT __init #endif /* CONFIG_USB_FILE_STORAGE_TEST */ @@ -567,6 +562,8 @@ struct lun { struct device dev; }; +#define backing_file_is_open(curlun) ((curlun)->filp != NULL) + static inline struct lun *dev_to_lun(struct device *dev) { return container_of(dev, struct lun, dev); @@ -659,6 +656,7 @@ struct fsg_dev { unsigned long atomic_bitflags; #define REGISTERED 0 #define CLEAR_BULK_HALTS 1 +#define SUSPENDED 2 struct usb_ep *bulk_in; struct usb_ep *bulk_out; @@ -870,6 +868,14 @@ config_desc = { .bMaxPower = 1, // self-powered }; +static struct usb_otg_descriptor +otg_desc = { + .bLength = sizeof(otg_desc), + .bDescriptorType = USB_DT_OTG, + + .bmAttributes = USB_OTG_SRP, +}; + /* There is only one interface. */ static struct usb_interface_descriptor @@ -918,12 +924,14 @@ fs_intr_in_desc = { }; static const struct usb_descriptor_header *fs_function[] = { + (struct usb_descriptor_header *) &otg_desc, (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &fs_bulk_in_desc, (struct usb_descriptor_header *) &fs_bulk_out_desc, (struct usb_descriptor_header *) &fs_intr_in_desc, NULL, }; +#define FS_FUNCTION_PRE_EP_ENTRIES 2 #ifdef CONFIG_USB_GADGET_DUALSPEED @@ -980,12 +988,14 @@ hs_intr_in_desc = { }; static const struct usb_descriptor_header *hs_function[] = { + (struct usb_descriptor_header *) &otg_desc, (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &hs_bulk_in_desc, (struct usb_descriptor_header *) &hs_bulk_out_desc, (struct usb_descriptor_header *) &hs_intr_in_desc, NULL, }; +#define HS_FUNCTION_PRE_EP_ENTRIES 2 /* Maxpacket and other transfer characteristics vary by speed. */ #define ep_desc(g,fs,hs) (((g)->speed==USB_SPEED_HIGH) ? (hs) : (fs)) @@ -1000,7 +1010,7 @@ static const struct usb_descriptor_header *hs_function[] = { /* The CBI specification limits the serial string to 12 uppercase hexadecimal * characters. */ -static char manufacturer[40]; +static char manufacturer[50]; static char serial[13]; /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ @@ -1022,9 +1032,12 @@ static struct usb_gadget_strings stringtab = { * and with code managing interfaces and their altsettings. They must * also handle different speeds and other-speed requests. */ -static int populate_config_buf(enum usb_device_speed speed, +static int populate_config_buf(struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index) { +#ifdef CONFIG_USB_GADGET_DUALSPEED + enum usb_device_speed speed = gadget->speed; +#endif int len; const struct usb_descriptor_header **function; @@ -1040,9 +1053,11 @@ static int populate_config_buf(enum usb_device_speed speed, #endif function = fs_function; + /* for now, don't advertise srp-only devices */ + if (!gadget->is_otg) + function++; + len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); - if (len < 0) - return len; ((struct usb_config_descriptor *) buf)->bDescriptorType = type; return len; } @@ -1172,9 +1187,10 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) wakeup_thread(fsg); } + +#ifdef CONFIG_USB_FILE_STORAGE_TEST static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) { -#ifdef CONFIG_USB_FILE_STORAGE_TEST struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; @@ -1190,17 +1206,21 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) bh->state = BUF_STATE_EMPTY; spin_unlock(&fsg->lock); wakeup_thread(fsg); -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ } +#else +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) +{} +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ + /*-------------------------------------------------------------------------*/ /* Ep0 class-specific handlers. These always run in_irq. */ +#ifdef CONFIG_USB_FILE_STORAGE_TEST static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) { -#ifdef CONFIG_USB_FILE_STORAGE_TEST struct usb_request *req = fsg->ep0req; static u8 cbi_reset_cmnd[6] = { SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; @@ -1238,9 +1258,13 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) spin_unlock(&fsg->lock); wakeup_thread(fsg); -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ } +#else +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{} +#endif /* CONFIG_USB_FILE_STORAGE_TEST */ + static int class_setup_req(struct fsg_dev *fsg, const struct usb_ctrlrequest *ctrl) @@ -1363,7 +1387,7 @@ static int standard_setup_req(struct fsg_dev *fsg, #ifdef CONFIG_USB_GADGET_DUALSPEED get_config: #endif - value = populate_config_buf(fsg->gadget->speed, + value = populate_config_buf(fsg->gadget, req->buf, ctrl->wValue >> 8, ctrl->wValue & 0xff); @@ -1465,8 +1489,8 @@ static int fsg_setup(struct usb_gadget *gadget, /* Respond with data/status or defer until later? */ if (rc >= 0 && rc != DELAYED_STATUS) { fsg->ep0req->length = rc; - fsg->ep0req->zero = rc < ctrl->wLength - && (rc % gadget->ep0->maxpacket) == 0; + fsg->ep0req->zero = (rc < ctrl->wLength && + (rc % gadget->ep0->maxpacket) == 0); fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out"); rc = ep0_queue(fsg); @@ -1520,6 +1544,8 @@ static int sleep_thread(struct fsg_dev *fsg) rc = wait_event_interruptible(fsg->thread_wqh, fsg->thread_wakeup_needed); fsg->thread_wakeup_needed = 0; + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); return (rc ? -EINTR : 0); } @@ -2277,8 +2303,7 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg) } /* Wait for a short time and then try again */ - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(HZ / 10) != 0) + if (msleep_interruptible(100) != 0) return -EINTR; rc = usb_ep_set_halt(fsg->bulk_in); } @@ -2443,14 +2468,19 @@ static int finish_reply(struct fsg_dev *fsg) rc = -EINTR; } - /* We haven't processed all the incoming data. If we are - * allowed to stall, halt the bulk-out endpoint and cancel - * any outstanding requests. */ + /* We haven't processed all the incoming data. Even though + * we may be allowed to stall, doing so would cause a race. + * The controller may already have ACK'ed all the remaining + * bulk-out packets, in which case the host wouldn't see a + * STALL. Not realizing the endpoint was halted, it wouldn't + * clear the halt -- leading to problems later on. */ +#if 0 else if (mod_data.can_stall) { fsg_set_halt(fsg, fsg->bulk_out); raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); rc = -EINTR; } +#endif /* We can't stall. Read in the excess data and throw it * all away. */ @@ -2513,7 +2543,7 @@ static int send_status(struct fsg_dev *fsg) } else if (mod_data.transport_type == USB_PR_CB) { - /* Control-Bulk transport has no status stage! */ + /* Control-Bulk transport has no status phase! */ return 0; } else { // USB_PR_CBI @@ -2603,8 +2633,10 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, fsg->residue = fsg->usb_amount_left = fsg->data_size; /* Conflicting data directions is a phase error */ - if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) - goto phase_error; + if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) { + fsg->phase_error = 1; + return -EINVAL; + } /* Verify the length of the command itself */ if (cmnd_size != fsg->cmnd_size) { @@ -2613,8 +2645,10 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, * with cbw->Length == 12 (it should be 6). */ if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12) cmnd_size = fsg->cmnd_size; - else - goto phase_error; + else { + fsg->phase_error = 1; + return -EINVAL; + } } /* Check that the LUN values are oonsistent */ @@ -2674,10 +2708,6 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, } return 0; - -phase_error: - fsg->phase_error = 1; - return -EINVAL; } @@ -3424,8 +3454,7 @@ static int fsg_main_thread(void *fsg_) /* If the next two routines are called while the gadget is registered, * the caller must own fsg->filesem for writing. */ -static int NORMALLY_INIT open_backing_file(struct lun *curlun, - const char *filename) +static int open_backing_file(struct lun *curlun, const char *filename) { int ro; struct file *filp = NULL; @@ -3550,8 +3579,7 @@ static ssize_t show_file(struct device *dev, char *buf) } -ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf, - size_t count) +static ssize_t store_ro(struct device *dev, const char *buf, size_t count) { ssize_t rc = count; struct lun *curlun = dev_to_lun(dev); @@ -3575,8 +3603,7 @@ ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf, return rc; } -ssize_t NORMALLY_INIT store_file(struct device *dev, const char *buf, - size_t count) +static ssize_t store_file(struct device *dev, const char *buf, size_t count) { struct lun *curlun = dev_to_lun(dev); struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); @@ -3692,26 +3719,32 @@ static int __init check_parameters(struct fsg_dev *fsg) if (mod_data.release == 0xffff) { // Parameter wasn't set if (gadget_is_net2280(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0301); + mod_data.release = 0x0301; else if (gadget_is_dummy(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0302); + mod_data.release = 0x0302; else if (gadget_is_pxa(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0303); + mod_data.release = 0x0303; else if (gadget_is_sh(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0304); + mod_data.release = 0x0304; /* The sa1100 controller is not supported */ else if (gadget_is_goku(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0306); + mod_data.release = 0x0306; else if (gadget_is_mq11xx(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0307); + mod_data.release = 0x0307; else if (gadget_is_omap(fsg->gadget)) - mod_data.release = __constant_cpu_to_le16(0x0308); + mod_data.release = 0x0308; + else if (gadget_is_lh7a40x(fsg->gadget)) + mod_data.release = 0x0309; + else if (gadget_is_n9604(fsg->gadget)) + mod_data.release = 0x0310; + else if (gadget_is_pxa27x(fsg->gadget)) + mod_data.release = 0x0311; else { WARN(fsg, "controller '%s' not recognized\n", fsg->gadget->name); - mod_data.release = __constant_cpu_to_le16(0x0399); + mod_data.release = 0x0399; } } @@ -3805,9 +3838,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) goto out; } - /* Create the LUNs and open their backing files. We can't register - * the LUN devices until the gadget itself is registered, which - * doesn't happen until after fsg_bind() returns. */ + /* Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. */ fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL); if (!fsg->luns) { rc = -ENOMEM; @@ -3825,6 +3857,15 @@ static int __init fsg_bind(struct usb_gadget *gadget) snprintf(curlun->dev.bus_id, BUS_ID_SIZE, "%s-lun%d", gadget->dev.bus_id, i); + if ((rc = device_register(&curlun->dev)) != 0) + INFO(fsg, "failed to register LUN%d: %d\n", i, rc); + else { + curlun->registered = 1; + curlun->dev.release = lun_release; + device_create_file(&curlun->dev, &dev_attr_ro); + device_create_file(&curlun->dev, &dev_attr_file); + } + if (file[i] && *file[i]) { if ((rc = open_backing_file(curlun, file[i])) != 0) goto out; @@ -3867,10 +3908,10 @@ static int __init fsg_bind(struct usb_gadget *gadget) intf_desc.bNumEndpoints = i; intf_desc.bInterfaceSubClass = mod_data.protocol_type; intf_desc.bInterfaceProtocol = mod_data.transport_type; - fs_function[i+1] = NULL; + fs_function[i + FS_FUNCTION_PRE_EP_ENTRIES] = NULL; #ifdef CONFIG_USB_GADGET_DUALSPEED - hs_function[i+1] = NULL; + hs_function[i + HS_FUNCTION_PRE_EP_ENTRIES] = NULL; /* Assume ep0 uses the same maxpacket value for both speeds */ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; @@ -3881,6 +3922,11 @@ static int __init fsg_bind(struct usb_gadget *gadget) hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress; #endif + if (gadget->is_otg) { + otg_desc.bmAttributes |= USB_OTG_HNP, + config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + rc = -ENOMEM; /* Allocate the request and buffer for endpoint 0 */ @@ -3972,6 +4018,25 @@ out: } +/*-------------------------------------------------------------------------*/ + +static void fsg_suspend(struct usb_gadget *gadget) +{ + struct fsg_dev *fsg = get_gadget_data(gadget); + + DBG(fsg, "suspend\n"); + set_bit(SUSPENDED, &fsg->atomic_bitflags); +} + +static void fsg_resume(struct usb_gadget *gadget) +{ + struct fsg_dev *fsg = get_gadget_data(gadget); + + DBG(fsg, "resume\n"); + clear_bit(SUSPENDED, &fsg->atomic_bitflags); +} + + /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver fsg_driver = { @@ -3985,6 +4050,8 @@ static struct usb_gadget_driver fsg_driver = { .unbind = fsg_unbind, .disconnect = fsg_disconnect, .setup = fsg_setup, + .suspend = fsg_suspend, + .resume = fsg_resume, .driver = { .name = (char *) shortname, @@ -4024,8 +4091,6 @@ static int __init fsg_init(void) { int rc; struct fsg_dev *fsg; - int i; - struct lun *curlun; if ((rc = fsg_alloc()) != 0) return rc; @@ -4036,19 +4101,6 @@ static int __init fsg_init(void) } set_bit(REGISTERED, &fsg->atomic_bitflags); - /* Register the LUN devices and their attribute files */ - for (i = 0; i < fsg->nluns; ++i) { - curlun = &fsg->luns[i]; - if ((rc = device_register(&curlun->dev)) != 0) - INFO(fsg, "failed to register LUN%d: %d\n", i, rc); - else { - curlun->registered = 1; - curlun->dev.release = lun_release; - device_create_file(&curlun->dev, &dev_attr_ro); - device_create_file(&curlun->dev, &dev_attr_file); - } - } - /* Tell the thread to start working */ complete(&fsg->thread_notifier); return 0; diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 3093bceb9..e893de9fb 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -44,6 +44,12 @@ #define gadget_is_sa1100(g) 0 #endif +#ifdef CONFIG_USB_GADGET_LH7A40X +#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name) +#else +#define gadget_is_lh7a40x(g) 0 +#endif + #ifdef CONFIG_USB_GADGET_MQ11XX #define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name) #else @@ -56,6 +62,18 @@ #define gadget_is_omap(g) 0 #endif +#ifdef CONFIG_USB_GADGET_N9604 +#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name) +#else +#define gadget_is_n9604(g) 0 +#endif + +#ifdef CONFIG_USB_GADGET_PXA27X +#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name) +#else +#define gadget_is_pxa27x(g) 0 +#endif + // CONFIG_USB_GADGET_AT91RM9200 // CONFIG_USB_GADGET_SX2 // CONFIG_USB_GADGET_AU1X00 diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 61ce5b2ee..005db7cca 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -90,7 +90,7 @@ module_param(use_dma, uint, S_IRUGO); static void nuke(struct goku_ep *, int status); static inline void -command(struct goku_udc_regs *regs, int command, unsigned epnum) +command(struct goku_udc_regs __iomem *regs, int command, unsigned epnum) { writel(COMMAND_EP(epnum) | command, ®s->Command); udelay(300); @@ -161,8 +161,8 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) /* ep1 and ep2 can do double buffering and/or dma */ if (ep->num < 3) { - struct goku_udc_regs *regs = ep->dev->regs; - u32 tmp; + struct goku_udc_regs __iomem *regs = ep->dev->regs; + u32 tmp; /* double buffer except (for now) with pio in */ tmp = ((ep->dma || !ep->is_in) @@ -191,7 +191,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) return 0; } -static void ep_reset(struct goku_udc_regs *regs, struct goku_ep *ep) +static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep) { struct goku_udc *dev = ep->dev; @@ -209,16 +209,16 @@ static void ep_reset(struct goku_udc_regs *regs, struct goku_ep *ep) writel(dev->int_enable, ®s->int_enable); readl(®s->int_enable); if (ep->num < 3) { - struct goku_udc_regs *regs = ep->dev->regs; - u32 tmp; + struct goku_udc_regs __iomem *r = ep->dev->regs; + u32 tmp; - tmp = readl(®s->EPxSingle); + tmp = readl(&r->EPxSingle); tmp &= ~(0x11 << ep->num); - writel(tmp, ®s->EPxSingle); + writel(tmp, &r->EPxSingle); - tmp = readl(®s->EPxBCS); + tmp = readl(&r->EPxBCS); tmp &= ~(0x11 << ep->num); - writel(tmp, ®s->EPxBCS); + writel(tmp, &r->EPxBCS); } /* reset dma in case we're still using it */ if (ep->dma) { @@ -237,7 +237,7 @@ static void ep_reset(struct goku_udc_regs *regs, struct goku_ep *ep) } ep->ep.maxpacket = MAX_FIFO_SIZE; - ep->desc = 0; + ep->desc = NULL; ep->stopped = 1; ep->irqs = 0; ep->dma = 0; @@ -274,10 +274,10 @@ goku_alloc_request(struct usb_ep *_ep, int gfp_flags) struct goku_request *req; if (!_ep) - return 0; + return NULL; req = kmalloc(sizeof *req, gfp_flags); if (!req) - return 0; + return NULL; memset(req, 0, sizeof *req); req->req.dma = DMA_ADDR_INVALID; @@ -334,7 +334,7 @@ goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, ep = container_of(_ep, struct goku_ep, ep); if (!_ep) - return 0; + return NULL; *dma = DMA_ADDR_INVALID; #if defined(USE_KMALLOC) @@ -413,7 +413,7 @@ done(struct goku_ep *ep, struct goku_request *req, int status) /*-------------------------------------------------------------------------*/ static inline int -write_packet(u32 *fifo, u8 *buf, struct goku_request *req, unsigned max) +write_packet(u32 __iomem *fifo, u8 *buf, struct goku_request *req, unsigned max) { unsigned length, count; @@ -488,10 +488,10 @@ static int write_fifo(struct goku_ep *ep, struct goku_request *req) static int read_fifo(struct goku_ep *ep, struct goku_request *req) { - struct goku_udc_regs *regs; - u32 size, set; - u8 *buf; - unsigned bufferspace, is_short, dbuff; + struct goku_udc_regs __iomem *regs; + u32 size, set; + u8 *buf; + unsigned bufferspace, is_short, dbuff; regs = ep->dev->regs; top: @@ -581,7 +581,8 @@ top: } static inline void -pio_irq_enable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum) +pio_irq_enable(struct goku_udc *dev, + struct goku_udc_regs __iomem *regs, int epnum) { dev->int_enable |= INT_EPxDATASET (epnum); writel(dev->int_enable, ®s->int_enable); @@ -589,7 +590,8 @@ pio_irq_enable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum) } static inline void -pio_irq_disable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum) +pio_irq_disable(struct goku_udc *dev, + struct goku_udc_regs __iomem *regs, int epnum) { dev->int_enable &= ~INT_EPxDATASET (epnum); writel(dev->int_enable, ®s->int_enable); @@ -613,10 +615,10 @@ pio_advance(struct goku_ep *ep) // return: 0 = q running, 1 = q stopped, negative = errno static int start_dma(struct goku_ep *ep, struct goku_request *req) { - struct goku_udc_regs *regs = ep->dev->regs; - u32 master; - u32 start = req->req.dma; - u32 end = start + req->req.length - 1; + struct goku_udc_regs __iomem *regs = ep->dev->regs; + u32 master; + u32 start = req->req.dma; + u32 end = start + req->req.length - 1; master = readl(®s->dma_master) & MST_RW_BITS; @@ -668,9 +670,9 @@ static int start_dma(struct goku_ep *ep, struct goku_request *req) static void dma_advance(struct goku_udc *dev, struct goku_ep *ep) { - struct goku_request *req; - struct goku_udc_regs *regs = ep->dev->regs; - u32 master; + struct goku_request *req; + struct goku_udc_regs __iomem *regs = ep->dev->regs; + u32 master; master = readl(®s->dma_master); @@ -716,9 +718,9 @@ stop: static void abort_dma(struct goku_ep *ep, int status) { - struct goku_udc_regs *regs = ep->dev->regs; - struct goku_request *req; - u32 curr, master; + struct goku_udc_regs __iomem *regs = ep->dev->regs; + struct goku_request *req; + u32 curr, master; /* NAK future host requests, hoping the implicit delay lets the * dma engine finish reading (or writing) its latest packet and @@ -848,7 +850,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) if (unlikely(status != 0)) { if (status > 0) status = 0; - req = 0; + req = NULL; } } /* else pio or dma irq handler advances the queue. */ @@ -927,7 +929,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req) } else if (!list_empty(&req->queue)) done(ep, req, -ECONNRESET); else - req = 0; + req = NULL; spin_unlock_irqrestore(&dev->lock, flags); return req ? 0 : -EOPNOTSUPP; @@ -984,7 +986,8 @@ static int goku_set_halt(struct usb_ep *_ep, int value) retval = -EAGAIN; else if (ep->is_in && value /* data in (either) packet buffer? */ - && (ep->dev->regs->DataSet & DATASET_AB(ep->num))) + && (readl(&ep->dev->regs->DataSet) + & DATASET_AB(ep->num))) retval = -EAGAIN; else if (!value) goku_clear_halt(ep); @@ -1000,9 +1003,9 @@ static int goku_set_halt(struct usb_ep *_ep, int value) static int goku_fifo_status(struct usb_ep *_ep) { - struct goku_ep *ep; - struct goku_udc_regs *regs; - u32 size; + struct goku_ep *ep; + struct goku_udc_regs __iomem *regs; + u32 size; if (!_ep) return -ENODEV; @@ -1022,9 +1025,9 @@ static int goku_fifo_status(struct usb_ep *_ep) static void goku_fifo_flush(struct usb_ep *_ep) { - struct goku_ep *ep; - struct goku_udc_regs *regs; - u32 size; + struct goku_ep *ep; + struct goku_udc_regs __iomem *regs; + u32 size; if (!_ep) return; @@ -1092,13 +1095,7 @@ static inline char *dmastr(void) return "(dma IN)"; } -/* if we're trying to save space, don't bother with this proc file */ - -#if defined(CONFIG_PROC_FS) && !defined(CONFIG_EMBEDDED) -# define UDC_PROC_FILE -#endif - -#ifdef UDC_PROC_FILE +#ifdef CONFIG_USB_GADGET_DEBUG_FILES static const char proc_node_name [] = "driver/udc"; @@ -1147,14 +1144,14 @@ static int udc_proc_read(char *buffer, char **start, off_t off, int count, int *eof, void *_dev) { - char *buf = buffer; - struct goku_udc *dev = _dev; - struct goku_udc_regs *regs = dev->regs; - char *next = buf; - unsigned size = count; - unsigned long flags; - int i, t, is_usb_connected; - u32 tmp; + char *buf = buffer; + struct goku_udc *dev = _dev; + struct goku_udc_regs __iomem *regs = dev->regs; + char *next = buf; + unsigned size = count; + unsigned long flags; + int i, t, is_usb_connected; + u32 tmp; if (off != 0) return 0; @@ -1312,7 +1309,7 @@ done: return count - size; } -#endif /* UDC_PROC_FILE */ +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ /*-------------------------------------------------------------------------*/ @@ -1342,17 +1339,17 @@ static void udc_reinit (struct goku_udc *dev) ep->dev = dev; INIT_LIST_HEAD (&ep->queue); - ep_reset(0, ep); + ep_reset(NULL, ep); } - dev->ep[0].reg_mode = 0; + dev->ep[0].reg_mode = NULL; dev->ep[0].ep.maxpacket = MAX_EP0_SIZE; list_del_init (&dev->ep[0].ep.ep_list); } static void udc_reset(struct goku_udc *dev) { - struct goku_udc_regs *regs = dev->regs; + struct goku_udc_regs __iomem *regs = dev->regs; writel(0, ®s->power_detect); writel(0, ®s->int_enable); @@ -1369,8 +1366,8 @@ static void udc_reset(struct goku_udc *dev) static void ep0_start(struct goku_udc *dev) { - struct goku_udc_regs *regs = dev->regs; - unsigned i; + struct goku_udc_regs __iomem *regs = dev->regs; + unsigned i; VDBG(dev, "%s\n", __FUNCTION__); @@ -1447,15 +1444,15 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return -EBUSY; /* hook up the driver */ - driver->driver.bus = 0; + driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; retval = driver->bind(&dev->gadget); if (retval) { DBG(dev, "bind to driver %s --> error %d\n", driver->driver.name, retval); - dev->driver = 0; - dev->gadget.dev.driver = 0; + dev->driver = NULL; + dev->gadget.dev.driver = NULL; return retval; } @@ -1477,7 +1474,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver) DBG (dev, "%s\n", __FUNCTION__); if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = 0; + driver = NULL; /* disconnect gadget driver after quiesceing hw and the driver */ udc_reset (dev); @@ -1504,7 +1501,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) return -EINVAL; spin_lock_irqsave(&dev->lock, flags); - dev->driver = 0; + dev->driver = NULL; stop_activity(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); @@ -1520,9 +1517,9 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); static void ep0_setup(struct goku_udc *dev) { - struct goku_udc_regs *regs = dev->regs; - struct usb_ctrlrequest ctrl; - int tmp; + struct goku_udc_regs __iomem *regs = dev->regs; + struct usb_ctrlrequest ctrl; + int tmp; /* read SETUP packet and enter DATA stage */ ctrl.bRequestType = readl(®s->bRequestType); @@ -1629,11 +1626,11 @@ stall: static irqreturn_t goku_irq(int irq, void *_dev, struct pt_regs *r) { - struct goku_udc *dev = _dev; - struct goku_udc_regs *regs = dev->regs; - struct goku_ep *ep; - u32 stat, handled = 0; - unsigned i, rescans = 5; + struct goku_udc *dev = _dev; + struct goku_udc_regs __iomem *regs = dev->regs; + struct goku_ep *ep; + u32 stat, handled = 0; + unsigned i, rescans = 5; spin_lock(&dev->lock); @@ -1651,7 +1648,7 @@ rescan: stat = 0; handled = 1; // FIXME have a neater way to prevent re-enumeration - dev->driver = 0; + dev->driver = NULL; goto done; } if (stat & INT_PWRDETECT) { @@ -1815,7 +1812,7 @@ static void goku_remove(struct pci_dev *pdev) usb_gadget_unregister_driver(dev->driver); } -#ifdef UDC_PROC_FILE +#ifdef CONFIG_USB_GADGET_DEBUG_FILES remove_proc_entry(proc_node_name, NULL); #endif if (dev->regs) @@ -1831,9 +1828,9 @@ static void goku_remove(struct pci_dev *pdev) pci_disable_device(pdev); device_unregister(&dev->gadget.dev); - pci_set_drvdata(pdev, 0); - dev->regs = 0; - the_controller = 0; + pci_set_drvdata(pdev, NULL); + dev->regs = NULL; + the_controller = NULL; INFO(dev, "unbind\n"); } @@ -1844,9 +1841,9 @@ static void goku_remove(struct pci_dev *pdev) static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct goku_udc *dev = 0; + struct goku_udc *dev = NULL; unsigned long resource, len; - void *base = 0; + void __iomem *base = NULL; int retval; char buf [8], *bufp; @@ -1906,7 +1903,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) retval = -EFAULT; goto done; } - dev->regs = (struct goku_udc_regs *) base; + dev->regs = (struct goku_udc_regs __iomem *) base; pci_set_drvdata(pdev, dev); INFO(dev, "%s\n", driver_desc); @@ -1933,7 +1930,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); -#ifdef UDC_PROC_FILE +#ifdef CONFIG_USB_GADGET_DEBUG_FILES create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); #endif @@ -1976,7 +1973,7 @@ static struct pci_driver goku_pci_driver = { static int __init init (void) { - return pci_module_init (&goku_pci_driver); + return pci_register_driver (&goku_pci_driver); } module_init (init); diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index 64e83163a..ea8c8e58c 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -216,9 +216,9 @@ struct goku_ep { struct list_head queue; const struct usb_endpoint_descriptor *desc; - u32 *reg_fifo; - u32 *reg_mode; - u32 *reg_status; + u32 __iomem *reg_fifo; + u32 __iomem *reg_mode; + u32 __iomem *reg_status; }; struct goku_request { @@ -253,7 +253,7 @@ struct goku_udc { /* pci state used to access those endpoints */ struct pci_dev *pdev; - struct goku_udc_regs *regs; + struct goku_udc_regs __iomem *regs; u32 int_enable; /* statistics... */ diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index c746ecbe1..638b7eaf1 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1,7 +1,7 @@ /* * inode.c -- user mode filesystem api for usb gadget controllers * - * Copyright (C) 2003 David Brownell + * Copyright (C) 2003-2004 David Brownell * Copyright (C) 2003 Agilent Technologies * * This program is free software; you can redistribute it and/or modify @@ -71,7 +71,7 @@ */ #define DRIVER_DESC "USB Gadget filesystem" -#define DRIVER_VERSION "18 Nov 2003" +#define DRIVER_VERSION "24 Aug 2004" static const char driver_desc [] = DRIVER_DESC; static const char shortname [] = "gadgetfs"; @@ -229,37 +229,12 @@ static void put_ep (struct ep_data *data) /*----------------------------------------------------------------------*/ /* most "how to use the hardware" policy choices are in userspace: - * mapping endpoint roles the driver needs to the capabilities that - * the usb controller exposes. + * mapping endpoint roles (which the driver needs) to the capabilities + * which the usb controller has. most of those capabilities are exposed + * implicitly, starting with the driver name and then endpoint names. */ -#ifdef CONFIG_USB_GADGET_DUMMY_HCD -/* act (mostly) like a net2280 */ -#define CONFIG_USB_GADGET_NET2280 -#endif - -#ifdef CONFIG_USB_GADGET_NET2280 -#define CHIP "net2280" -#define HIGHSPEED -#endif - -#ifdef CONFIG_USB_GADGET_PXA2XX -#define CHIP "pxa2xx_udc" -/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */ -#warning works best with pxa255 or newer -#endif - -#ifdef CONFIG_USB_GADGET_GOKU -#define CHIP "goku_udc" -#endif - -#ifdef CONFIG_USB_GADGET_OMAP -#define CHIP "omap_udc" -#endif - -#ifdef CONFIG_USB_GADGET_SA1100 -#define CHIP "sa1100" -#endif +static const char *CHIP; /*----------------------------------------------------------------------*/ @@ -558,7 +533,7 @@ struct kiocb_priv { static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) { - struct kiocb_priv *priv = (void *) &iocb->private; + struct kiocb_priv *priv = iocb->private; struct ep_data *epdata; int value; @@ -577,10 +552,10 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) return value; } -static long ep_aio_read_retry(struct kiocb *iocb) +static ssize_t ep_aio_read_retry(struct kiocb *iocb) { - struct kiocb_priv *priv = (void *) &iocb->private; - int status = priv->actual; + struct kiocb_priv *priv = iocb->private; + ssize_t status = priv->actual; /* we "retry" to get the right mm context for this: */ status = copy_to_user(priv->ubuf, priv->buf, priv->actual); @@ -589,6 +564,7 @@ static long ep_aio_read_retry(struct kiocb *iocb) else status = priv->actual; kfree(priv->buf); + kfree(priv); aio_put_req(iocb); return status; } @@ -596,7 +572,7 @@ static long ep_aio_read_retry(struct kiocb *iocb) static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) { struct kiocb *iocb = req->context; - struct kiocb_priv *priv = (void *) &iocb->private; + struct kiocb_priv *priv = iocb->private; struct ep_data *epdata = priv->epdata; /* lock against disconnect (and ideally, cancel) */ @@ -607,6 +583,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) || unlikely(0 == req->actual) || unlikely(kiocbIsCancelled(iocb))) { kfree(req->buf); + kfree(priv); + iocb->private = NULL; /* aio_complete() reports bytes-transferred _and_ faults */ if (unlikely(kiocbIsCancelled(iocb))) aio_put_req(iocb); @@ -631,17 +609,33 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) } static ssize_t -ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) +ep_aio_rwtail( + struct kiocb *iocb, + char *buf, + size_t len, + struct ep_data *epdata, + char __user *ubuf +) { struct kiocb_priv *priv = (void *) &iocb->private; struct usb_request *req; ssize_t value; - value = get_ready_ep(iocb->ki_filp->f_flags, epdata); - if (unlikely(value < 0)) { + priv = kmalloc(sizeof *priv, GFP_KERNEL); + if (!priv) { + value = -ENOMEM; +fail: kfree(buf); return value; } + iocb->private = priv; + priv->ubuf = ubuf; + + value = get_ready_ep(iocb->ki_filp->f_flags, epdata); + if (unlikely(value < 0)) { + kfree(priv); + goto fail; + } iocb->ki_cancel = ep_aio_cancel; get_ep(epdata); @@ -671,9 +665,10 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) up(&epdata->lock); - if (unlikely(value)) + if (unlikely(value)) { + kfree(priv); put_ep(epdata); - else + } else value = -EIOCBQUEUED; return value; } @@ -681,7 +676,6 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) static ssize_t ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o) { - struct kiocb_priv *priv = (void *) &iocb->private; struct ep_data *epdata = iocb->ki_filp->private_data; char *buf; @@ -691,8 +685,7 @@ ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o) if (unlikely(!buf)) return -ENOMEM; iocb->ki_retry = ep_aio_read_retry; - priv->ubuf = ubuf; - return ep_aio_rwtail(iocb, buf, len, epdata); + return ep_aio_rwtail(iocb, buf, len, epdata, ubuf); } static ssize_t @@ -710,7 +703,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) kfree(buf); return -EFAULT; } - return ep_aio_rwtail(iocb, buf, len, epdata); + return ep_aio_rwtail(iocb, buf, len, epdata, NULL); } /*----------------------------------------------------------------------*/ @@ -718,6 +711,8 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) /* used after endpoint configuration */ static struct file_operations ep_io_operations = { .owner = THIS_MODULE, + .llseek = no_llseek, + .read = ep_read, .write = ep_write, .ioctl = ep_ioctl, @@ -874,6 +869,8 @@ ep_open (struct inode *inode, struct file *fd) /* used before endpoint configuration */ static struct file_operations ep_config_operations = { .owner = THIS_MODULE, + .llseek = no_llseek, + .open = ep_open, .write = ep_config, .release = ep_release, @@ -980,6 +977,18 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) retval = usb_ep_queue (ep, req, GFP_ATOMIC); dev->state = STATE_CONNECTED; + /* assume that was SET_CONFIGURATION */ + if (dev->current_config) { + unsigned power; +#ifdef HIGHSPEED + if (dev->gadget->speed == USB_SPEED_HIGH) + power = dev->hs_config->bMaxPower; + else +#endif + power = dev->config->bMaxPower; + usb_gadget_vbus_draw(dev->gadget, 2 * power); + } + } else { /* collect OUT data */ if ((fd->f_flags & O_NONBLOCK) != 0 && !dev->setup_out_ready) { @@ -1230,6 +1239,8 @@ static int dev_ioctl (struct inode *inode, struct file *fd, /* used after device configuration */ static struct file_operations ep0_io_operations = { .owner = THIS_MODULE, + .llseek = no_llseek, + .read = ep0_read, .write = ep0_write, .fasync = ep0_fasync, @@ -1406,19 +1417,25 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) if (0 == (u8) ctrl->wValue) { value = 0; dev->current_config = 0; + usb_gadget_vbus_draw(gadget, 8 /* mA */ ); // user mode expected to disable endpoints } else { - u8 config; + u8 config, power; #ifdef HIGHSPEED - if (gadget->speed == USB_SPEED_HIGH) + if (gadget->speed == USB_SPEED_HIGH) { config = dev->hs_config->bConfigurationValue; - else + power = dev->hs_config->bMaxPower; + } else #endif + { config = dev->config->bConfigurationValue; + power = dev->config->bMaxPower; + } if (config == (u8) ctrl->wValue) { value = 0; dev->current_config = config; + usb_gadget_vbus_draw(gadget, 2 * power); } } @@ -1636,8 +1653,8 @@ gadgetfs_bind (struct usb_gadget *gadget) if (!dev) return -ESRCH; if (0 != strcmp (CHIP, gadget->name)) { - printk (KERN_ERR "%s expected " CHIP " controller not %s\n", - shortname, gadget->name); + printk (KERN_ERR "%s expected %s controller not %s\n", + shortname, CHIP, gadget->name); return -ENODEV; } @@ -1727,6 +1744,26 @@ static struct usb_gadget_driver gadgetfs_driver = { /*----------------------------------------------------------------------*/ +static void gadgetfs_nop(struct usb_gadget *arg) { } + +static int gadgetfs_probe (struct usb_gadget *gadget) +{ + CHIP = gadget->name; + return -EISNAM; +} + +static struct usb_gadget_driver probe_driver = { + .speed = USB_SPEED_HIGH, + .bind = gadgetfs_probe, + .unbind = gadgetfs_nop, + .setup = (void *)gadgetfs_nop, + .disconnect = gadgetfs_nop, + .driver = { + .name = "nop", + }, +}; + + /* DEVICE INITIALIZATION * * fd = open ("/dev/gadget/$CHIP", O_RDWR) @@ -1763,6 +1800,7 @@ static int is_valid_config (struct usb_config_descriptor *config) && config->bConfigurationValue != 0 && (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0 && (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0; + /* FIXME if gadget->is_otg, _must_ include an otg descriptor */ /* FIXME check lengths: walk to end */ } @@ -1881,6 +1919,8 @@ dev_open (struct inode *inode, struct file *fd) static struct file_operations dev_init_operations = { .owner = THIS_MODULE, + .llseek = no_llseek, + .open = dev_open, .write = dev_config, .fasync = ep0_fasync, @@ -1941,12 +1981,8 @@ gadgetfs_create_file (struct super_block *sb, char const *name, { struct dentry *dentry; struct inode *inode; - struct qstr qname; - qname.name = name; - qname.len = strlen (name); - qname.hash = full_name_hash (qname.name, qname.len); - dentry = d_alloc (sb->s_root, &qname); + dentry = d_alloc_name(sb->s_root, name); if (!dentry) return NULL; @@ -1976,6 +2012,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) if (the_device) return -ESRCH; + /* fake probe to determine $CHIP */ + (void) usb_gadget_register_driver (&probe_driver); + if (!CHIP) + return -ENODEV; + /* superblock */ sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 772627e97..0def9f70e 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -54,7 +54,6 @@ static const char ep0name[] = "ep0-control"; /* Local definintions. */ -#define UDC_PROC_FILE #ifndef NO_STATES static char *state_names[] = { @@ -192,7 +191,7 @@ static __inline__ void usb_clear(u32 val, u32 port) */ #define is_usb_connected() get_portc_pdr(2) -#ifdef UDC_PROC_FILE +#ifdef CONFIG_USB_GADGET_DEBUG_FILES static const char proc_node_name[] = "driver/udc"; @@ -248,12 +247,12 @@ udc_proc_read(char *page, char **start, off_t off, int count, #define create_proc_files() create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev) #define remove_proc_files() remove_proc_entry(proc_node_name, NULL) -#else /* !UDC_PROC_FILE */ +#else /* !CONFIG_USB_GADGET_DEBUG_FILES */ #define create_proc_files() do {} while (0) #define remove_proc_files() do {} while (0) -#endif /* UDC_PROC_FILE */ +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ /* * udc_disable - disable USB device controller diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 880b1f799..d2997ef3c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -7,13 +7,9 @@ * * CODE STATUS HIGHLIGHTS * - * Used with a gadget driver like "zero.c" this enumerates fine to Windows - * or Linux hosts; handles disconnect, reconnect, and reset, for full or - * high speed operation; and passes USB-IF "chapter 9" tests. - * - * Handles standard stress loads from the Linux "usbtest" driver, with - * either DMA (default) or PIO (use_dma=n) used for ep-{a,b,c,d}. Testing - * with "ttcp" (and the "ether.c" driver) behaves nicely too. + * This driver should work well with most "gadget" drivers, including + * the File Storage, Serial, and Ethernet/RNDIS gadget drivers + * as well as Gadget Zero and Gadgetfs. * * DMA is enabled by default. Drivers using transfer queues might use * DMA chaining to remove IRQ latencies between transfers. (Except when @@ -80,7 +76,6 @@ #define EP_DONTUSE 13 /* nonzero */ #define USE_RDK_LEDS /* GPIO pins control three LEDs */ -#define USE_SYSFS_DEBUG_FILES static const char driver_name [] = "net2280"; @@ -121,7 +116,7 @@ module_param (fifo_mode, ushort, 0644); #define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") -#if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG) +#if defined(CONFIG_USB_GADGET_DEBUG_FILES) || defined (DEBUG) static char *type_string (u8 bmAttributes) { switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) { @@ -257,7 +252,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) return 0; } -static int handshake (u32 *ptr, u32 mask, u32 done, int usec) +static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; @@ -276,7 +271,7 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec) static struct usb_ep_ops net2280_ep_ops; -static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep) +static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) { u32 tmp; @@ -307,14 +302,16 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep) /* init to our chosen defaults, notably so that we NAK OUT * packets until the driver queues a read (+note erratum 0112) */ - writel ( (1 << SET_NAK_OUT_PACKETS_MODE) + tmp = (1 << SET_NAK_OUT_PACKETS_MODE) | (1 << SET_NAK_OUT_PACKETS) | (1 << CLEAR_EP_HIDE_STATUS_PHASE) - | (1 << CLEAR_INTERRUPT_MODE) - | (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) - | (1 << CLEAR_ENDPOINT_TOGGLE) - | (1 << CLEAR_ENDPOINT_HALT) - , &ep->regs->ep_rsp); + | (1 << CLEAR_INTERRUPT_MODE); + + if (ep->num != 0) { + tmp |= (1 << CLEAR_ENDPOINT_TOGGLE) + | (1 << CLEAR_ENDPOINT_HALT); + } + writel (tmp, &ep->regs->ep_rsp); /* scrub most status bits, and flush any fifo state */ writel ( (1 << TIMEOUT) @@ -517,7 +514,7 @@ net2280_free_buffer ( static void write_fifo (struct net2280_ep *ep, struct usb_request *req) { - struct net2280_ep_regs *regs = ep->regs; + struct net2280_ep_regs __iomem *regs = ep->regs; u8 *buf; u32 tmp; unsigned count, total; @@ -577,7 +574,8 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req) */ static void out_flush (struct net2280_ep *ep) { - u32 *statp, tmp; + u32 __iomem *statp; + u32 tmp; ASSERT_OUT_NAKING (ep); @@ -610,7 +608,7 @@ static void out_flush (struct net2280_ep *ep) static int read_fifo (struct net2280_ep *ep, struct net2280_request *req) { - struct net2280_ep_regs *regs = ep->regs; + struct net2280_ep_regs __iomem *regs = ep->regs; u8 *buf = req->req.buf + req->req.actual; unsigned count, tmp, is_short; unsigned cleanup = 0, prevent = 0; @@ -678,7 +676,7 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req) } if (count) { tmp = readl (®s->ep_data); - cpu_to_le32s (&tmp); + /* LE conversion is implicit here: */ do { *buf++ = (u8) tmp; tmp >>= 8; @@ -719,7 +717,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE); /* td->dmadesc = previously set by caller */ - td->dmaaddr = cpu_to_le32p (&req->req.dma); + td->dmaaddr = cpu_to_le32 (req->req.dma); /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */ wmb (); @@ -737,12 +735,12 @@ static const u32 dmactl_default = /* erratum 0116 workaround part 2 (no AUTOSTART) */ | (1 << DMA_ENABLE); -static inline void spin_stop_dma (struct net2280_dma_regs *dma) +static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma) { handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50); } -static inline void stop_dma (struct net2280_dma_regs *dma) +static inline void stop_dma (struct net2280_dma_regs __iomem *dma) { writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl); spin_stop_dma (dma); @@ -750,7 +748,7 @@ static inline void stop_dma (struct net2280_dma_regs *dma) static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) { - struct net2280_dma_regs *dma = ep->dma; + struct net2280_dma_regs __iomem *dma = ep->dma; writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION), &dma->dmacount); @@ -771,7 +769,7 @@ static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) static void start_dma (struct net2280_ep *ep, struct net2280_request *req) { u32 tmp; - struct net2280_dma_regs *dma = ep->dma; + struct net2280_dma_regs __iomem *dma = ep->dma; /* FIXME can't use DMA for ZLPs */ @@ -1419,15 +1417,44 @@ static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value) return 0; } +static int net2280_pullup(struct usb_gadget *_gadget, int is_on) +{ + struct net2280 *dev; + u32 tmp; + unsigned long flags; + + if (!_gadget) + return -ENODEV; + dev = container_of (_gadget, struct net2280, gadget); + + spin_lock_irqsave (&dev->lock, flags); + tmp = readl (&dev->usb->usbctl); + dev->softconnect = (is_on != 0); + if (is_on) + tmp |= (1 << USB_DETECT_ENABLE); + else + tmp &= ~(1 << USB_DETECT_ENABLE); + writel (tmp, &dev->usb->usbctl); + spin_unlock_irqrestore (&dev->lock, flags); + + return 0; +} + static const struct usb_gadget_ops net2280_ops = { .get_frame = net2280_get_frame, .wakeup = net2280_wakeup, .set_selfpowered = net2280_set_selfpowered, + .pullup = net2280_pullup, }; /*-------------------------------------------------------------------------*/ -#ifdef USE_SYSFS_DEBUG_FILES +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +/* FIXME move these into procfs, and use seq_file. + * Sysfs _still_ doesn't behave for arbitrarily sized files, + * and also doesn't help products using this with 2.4 kernels. + */ /* "function" sysfs attribute */ static ssize_t @@ -1680,8 +1707,10 @@ show_queues (struct device *_dev, char *buf) td = req->td; t = scnprintf (next, size, "\t td %08x " " count %08x buf %08x desc %08x\n", - req->td_dma, td->dmacount, - td->dmaaddr, td->dmadesc); + (u32) req->td_dma, + le32_to_cpu (td->dmacount), + le32_to_cpu (td->dmaaddr), + le32_to_cpu (td->dmadesc)); if (t <= 0 || t > size) goto done; size -= t; @@ -1807,8 +1836,6 @@ static void usb_reset (struct net2280 *dev) { u32 tmp; - /* force immediate bus disconnect, and synch through pci */ - writel (0, &dev->usb->usbctl); dev->gadget.speed = USB_SPEED_UNKNOWN; (void) readl (&dev->usb->usbctl); @@ -1902,10 +1929,8 @@ static void ep0_start (struct net2280 *dev) , &dev->usb->stdrsp); writel ( (1 << USB_ROOT_PORT_WAKEUP_ENABLE) | (1 << SELF_POWERED_USB_DEVICE) - /* erratum 0102 workaround */ - | ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY | (1 << REMOTE_WAKEUP_SUPPORT) - | (1 << USB_DETECT_ENABLE) + | (dev->softconnect << USB_DETECT_ENABLE) | (1 << SELF_POWERED_STATUS) , &dev->usb->usbctl); @@ -1957,6 +1982,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) dev->ep [i].irqs = 0; /* hook up the driver ... */ + dev->softconnect = 1; driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; @@ -2028,6 +2054,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) stop_activity (dev, driver); spin_unlock_irqrestore (&dev->lock, flags); + net2280_pullup (&dev->gadget, 0); + driver->unbind (&dev->gadget); dev->gadget.dev.driver = NULL; dev->driver = NULL; @@ -2492,15 +2520,23 @@ next_endpoints: static void handle_stat1_irqs (struct net2280 *dev, u32 stat) { struct net2280_ep *ep; - u32 tmp, num, scratch; + u32 tmp, num, mask, scratch; /* after disconnect there's nothing else to do! */ tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT); + mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED); + + /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set. + * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and + * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT + * only indicates a change in the reset state). + */ if (stat & tmp) { writel (tmp, &dev->regs->irqstat1); - if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0 - || (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0 - ) && dev->gadget.speed != USB_SPEED_UNKNOWN) { + if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && + ((readl (&dev->usb->usbstat) & mask) == 0)) + || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) + ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) { DEBUG (dev, "disconnect %s\n", dev->driver->driver.name); stop_activity (dev, dev->driver); @@ -2525,8 +2561,6 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) { if (dev->driver->suspend) dev->driver->suspend (&dev->gadget); - /* we use SUSPEND_IMMEDIATELY */ - stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT); } else { if (dev->driver->resume) dev->driver->resume (&dev->gadget); @@ -2553,7 +2587,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) stat &= ~DMA_INTERRUPTS; scratch >>= 9; for (num = 0; scratch; num++) { - struct net2280_dma_regs *dma; + struct net2280_dma_regs __iomem *dma; tmp = 1 << num; if ((tmp & scratch) == 0) @@ -2722,7 +2756,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) { struct net2280 *dev; unsigned long resource, len; - void *base = NULL; + void __iomem *base = NULL; int retval, i; char buf [8], *bufp; @@ -2780,14 +2814,15 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) retval = -EFAULT; goto done; } - dev->regs = (struct net2280_regs *) base; - dev->usb = (struct net2280_usb_regs *) (base + 0x0080); - dev->pci = (struct net2280_pci_regs *) (base + 0x0100); - dev->dma = (struct net2280_dma_regs *) (base + 0x0180); - dev->dep = (struct net2280_dep_regs *) (base + 0x0200); - dev->epregs = (struct net2280_ep_regs *) (base + 0x0300); + dev->regs = (struct net2280_regs __iomem *) base; + dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080); + dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100); + dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180); + dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200); + dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300); /* put into initial config, link up all endpoints */ + writel (0, &dev->usb->usbctl); usb_reset (dev); usb_reinit (dev); @@ -2812,6 +2847,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->got_irq = 1; /* DMA setup */ + /* NOTE: we know only the 32 LSBs of dma addresses may be nonzero */ dev->requests = pci_pool_create ("requests", pdev, sizeof (struct net2280_dma), 0 /* no alignment requirements */, @@ -2907,7 +2943,7 @@ static int __init init (void) { if (!use_dma) use_dma_chaining = 0; - return pci_module_init (&net2280_pci_driver); + return pci_register_driver (&net2280_pci_driver); } module_init (init); diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index ec9d6f7e7..fff4509cf 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -446,7 +446,7 @@ struct net2280_ep_regs { /* [11.9] */ */ static inline u32 -get_idx_reg (struct net2280_regs *regs, u32 index) +get_idx_reg (struct net2280_regs __iomem *regs, u32 index) { writel (index, ®s->idxaddr); /* NOTE: synchs device/cpu memory views */ @@ -454,7 +454,7 @@ get_idx_reg (struct net2280_regs *regs, u32 index) } static inline void -set_idx_reg (struct net2280_regs *regs, u32 index, u32 value) +set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value) { writel (index, ®s->idxaddr); writel (value, ®s->idxdata); @@ -495,10 +495,10 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value) * use struct net2280_dma_regs bitfields */ struct net2280_dma { - u32 dmacount; - u32 dmaaddr; /* the buffer */ - u32 dmadesc; /* next dma descriptor */ - u32 _reserved; + __le32 dmacount; + __le32 dmaaddr; /* the buffer */ + __le32 dmadesc; /* next dma descriptor */ + __le32 _reserved; } __attribute__ ((aligned (16))); /*-------------------------------------------------------------------------*/ @@ -507,8 +507,8 @@ struct net2280_dma { struct net2280_ep { struct usb_ep ep; - struct net2280_ep_regs *regs; - struct net2280_dma_regs *dma; + struct net2280_ep_regs __iomem *regs; + struct net2280_dma_regs __iomem *dma; struct net2280_dma *dummy; dma_addr_t td_dma; /* of dummy */ struct net2280 *dev; @@ -539,7 +539,7 @@ static inline void allow_status (struct net2280_ep *ep) /* count (<= 4) bytes in the next fifo write will be valid */ static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count) { - writeb (count, 2 + (u8 *) &ep->regs->ep_cfg); + writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg); } struct net2280_request { @@ -559,18 +559,19 @@ struct net2280 { struct usb_gadget_driver *driver; unsigned enabled : 1, protocol_stall : 1, + softconnect : 1, got_irq : 1, region : 1; u16 chiprev; /* pci state used to access those endpoints */ struct pci_dev *pdev; - struct net2280_regs *regs; - struct net2280_usb_regs *usb; - struct net2280_pci_regs *pci; - struct net2280_dma_regs *dma; - struct net2280_dep_regs *dep; - struct net2280_ep_regs *epregs; + struct net2280_regs __iomem *regs; + struct net2280_usb_regs __iomem *usb; + struct net2280_pci_regs __iomem *pci; + struct net2280_dma_regs __iomem *dma; + struct net2280_dep_regs __iomem *dep; + struct net2280_ep_regs __iomem *epregs; struct pci_pool *requests; // statistics... diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index e40089d79..98dfa4c85 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -59,15 +59,14 @@ #undef USB_TRACE -/* OUT-dma seems to be behaving */ +/* bulk DMA seems to be behaving for both IN and OUT */ #define USE_DMA /* ISO too */ #define USE_ISO - #define DRIVER_DESC "OMAP UDC driver" -#define DRIVER_VERSION "24 August 2004" +#define DRIVER_VERSION "4 October 2004" #define DMA_ADDR_INVALID (~(dma_addr_t)0) @@ -104,7 +103,6 @@ static unsigned fifo_mode = 0; module_param (fifo_mode, uint, 0); MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)"); - #ifdef USE_DMA static unsigned use_dma = 1; @@ -224,18 +222,17 @@ static int omap_ep_enable(struct usb_ep *_ep, list_add(&ep->iso, &udc->iso); /* maybe assign a DMA channel to this endpoint */ - if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && !(ep->bEndpointAddress & USB_DIR_IN)) - /* FIXME ISO can dma, but prefers first channel. - * IN can dma, but lacks debugging. - */ + if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK) + /* FIXME ISO can dma, but prefers first channel */ dma_channel_claim(ep, 0); /* PIO OUT may RX packets */ if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC && !ep->has_dma - && !(ep->bEndpointAddress & USB_DIR_IN)) + && !(ep->bEndpointAddress & USB_DIR_IN)) { UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } spin_unlock_irqrestore(&udc->lock, flags); VDBG("%s enabled\n", _ep->name); @@ -262,6 +259,7 @@ static int omap_ep_disable(struct usb_ep *_ep) ep->has_dma = 0; UDC_CTRL_REG = UDC_SET_HALT; list_del_init(&ep->iso); + del_timer(&ep->timer); spin_unlock_irqrestore(&ep->udc->lock, flags); @@ -498,17 +496,22 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) u16 ep_stat = UDC_STAT_FLG_REG; is_last = 0; - if (ep_stat & FIFO_UNREADABLE) + if (ep_stat & FIFO_EMPTY) { + if (!ep->double_buf) + break; + ep->fnf = 1; + } + if (ep_stat & UDC_EP_HALTED) break; - if (ep_stat & (UDC_NON_ISO_FIFO_FULL|UDC_ISO_FIFO_FULL)) + if (ep_stat & FIFO_FULL) avail = ep->ep.maxpacket; - else + else { avail = UDC_RXFSTAT_REG; + ep->fnf = ep->double_buf; + } count = read_packet(buf, req, avail); - // FIXME double buffered PIO OUT wasn't behaving... - /* partial packet reads may not be errors */ if (count < ep->ep.maxpacket) { is_last = 1; @@ -526,26 +529,56 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) if (!ep->bEndpointAddress) break; - if (!ep->double_buf) { - UDC_CTRL_REG = UDC_SET_FIFO_EN; - if (!is_last) - break; - } - - if (is_last) { + if (is_last) done(ep, req, 0); - if (list_empty(&ep->queue) || !ep->double_buf) - break; - req = container_of(ep->queue.next, - struct omap_req, queue); - is_last = 0; - } + break; } return is_last; } /*-------------------------------------------------------------------------*/ +static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) +{ + dma_addr_t end; + + /* IN-DMA needs this on fault/cancel paths, so 15xx misreports + * the last transfer's bytecount by more than a FIFO's worth. + */ + if (cpu_is_omap15xx()) + return 0; + + end = omap_readw(OMAP_DMA_CSAC(ep->lch)); + if (end == ep->dma_counter) + return 0; + + end |= start & (0xffff << 16); + if (end < start) + end += 0x10000; + return end - start; +} + +#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ + ? OMAP_DMA_CSAC(x) /* really: CPC */ \ + : OMAP_DMA_CDAC(x)) + +static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) +{ + dma_addr_t end; + + end = omap_readw(DMA_DEST_LAST(ep->lch)); + if (end == ep->dma_counter) + return 0; + + end |= start & (0xffff << 16); + if (cpu_is_omap15xx()) + end++; + if (end < start) + end += 0x10000; + return end - start; +} + + /* Each USB transfer request using DMA maps to one or more DMA transfers. * When DMA completion isn't request completion, the UDC continues with * the next DMA transfer for that USB transfer. @@ -555,26 +588,29 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) { u16 txdma_ctrl; unsigned length = req->req.length - req->req.actual; + const int sync_mode = cpu_is_omap15xx() + ? OMAP_DMA_SYNC_FRAME + : OMAP_DMA_SYNC_ELEMENT; /* measure length in either bytes or packets */ - if (length <= (UDC_TXN_TSC + 1)) { + if ((cpu_is_omap16xx() && length <= (UDC_TXN_TSC + 1)) + || (cpu_is_omap15xx() && length < ep->maxpacket)) { txdma_ctrl = UDC_TXN_EOT | length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, - length, 1, OMAP_DMA_SYNC_ELEMENT); + length, 1, sync_mode); } else { - length = max(length / ep->maxpacket, + length = min(length / ep->maxpacket, (unsigned) UDC_TXN_TSC + 1); txdma_ctrl = length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, - ep->ep.maxpacket, length, - OMAP_DMA_SYNC_ELEMENT); + ep->ep.maxpacket, length, sync_mode); length *= ep->maxpacket; } - omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); omap_start_dma(ep->lch); + ep->dma_counter = omap_readw(OMAP_DMA_CSAC(ep->lch)); UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; req->dma_bytes = length; @@ -592,14 +628,9 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status) && req->dma_bytes != 0 && (req->req.actual % ep->maxpacket) == 0) return; - } else { - u32 last; - - // FIXME this surely isn't #bytes transferred - last = (omap_readw(OMAP_DMA_CSSA_U(ep->lch)) << 16) - | omap_readw(OMAP_DMA_CSSA_L(ep->lch)); - req->req.actual = last - req->req.dma; - } + } else + req->req.actual += dma_src_len(ep, req->req.dma + + req->req.actual); /* tx completion */ omap_stop_dma(ep->lch); @@ -624,6 +655,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) OMAP_DMA_SYNC_ELEMENT); omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); + ep->dma_counter = omap_readw(DMA_DEST_LAST(ep->lch)); UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); @@ -638,15 +670,13 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status) { u16 count; - /* FIXME must be a better way to see how much dma - * happened, even when it never got going... - */ - count = omap_readw(OMAP_DMA_CDAC(ep->lch)); - count -= 0xffff & (req->req.dma + req->req.actual); + if (status == 0) + ep->dma_counter = (u16) (req->req.dma + req->req.actual); + count = dma_dest_len(ep, req->req.dma + req->req.actual); count += req->req.actual; if (count <= req->req.length) req->req.actual = count; - + if (count != req->dma_bytes || status) omap_stop_dma(ep->lch); @@ -705,7 +735,9 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src) if (irq_src & UDC_RXN_CNT) { ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)]; - DBG("%s, RX_CNT irq?\n", ep->ep.name); + ep->irqs++; + /* omap15xx does this unasked... */ + VDBG("%s, RX_CNT irq?\n", ep->ep.name); UDC_IRQ_SRC_REG = UDC_RXN_CNT; } } @@ -778,7 +810,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ); /* channel type P: hw synch (fifo) */ - omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch)); + if (!cpu_is_omap15xx()) + omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch)); } just_restart: @@ -803,6 +836,10 @@ just_restart: use_ep(ep, UDC_EP_SEL); (is_in ? write_fifo : read_fifo)(ep, req); deselect_ep(); + if (!is_in) { + UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } /* IN: 6 wait states before it'll tx */ } } @@ -833,24 +870,21 @@ static void dma_channel_release(struct omap_ep *ep) UDC_TXDMA_CFG_REG &= ~mask; if (req) { - if (active) - udelay(50); finish_in_dma(ep, req, -ECONNRESET); - if (UDC_TXDMA_CFG_REG & mask) - WARN("%s, SPIN abort TX dma\n", ep->ep.name); - } - /* host may empty the fifo (or not...) */ + /* clear FIFO; hosts probably won't empty it */ + use_ep(ep, UDC_EP_SEL); + UDC_CTRL_REG = UDC_CLR_EP; + deselect_ep(); + } while (UDC_TXDMA_CFG_REG & mask) udelay(10); - } else { UDC_RXDMA_CFG_REG &= ~mask; /* dma empties the fifo */ - while (active && (UDC_RXDMA_CFG_REG & mask)) + while (UDC_RXDMA_CFG_REG & mask) udelay(10); - omap_stop_dma(ep->lch); if (req) finish_out_dma(ep, req, -ECONNRESET); } @@ -997,6 +1031,10 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) req = 0; deselect_ep(); + if (!is_in) { + UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } /* IN: 6 wait states before it'll tx */ } } @@ -1034,7 +1072,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) { int channel = ep->dma_channel; - /* releasing the dma completion cancels the request, + /* releasing the channel cancels the request, * reclaiming the channel restarts the queue */ dma_channel_release(ep); @@ -1104,8 +1142,10 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) use_ep(ep, 0); UDC_CTRL_REG = UDC_RESET_EP; ep->ackwait = 0; - if (!(ep->bEndpointAddress & USB_DIR_IN)) + if (!(ep->bEndpointAddress & USB_DIR_IN)) { UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } } } done: @@ -1200,7 +1240,8 @@ static void pullup_enable(struct omap_udc *udc) { UDC_SYSCON1_REG |= UDC_PULLUP_EN; #ifndef CONFIG_USB_OTG - OTG_CTRL_REG |= OTG_BSESSVLD; + if (!cpu_is_omap15xx()) + OTG_CTRL_REG |= OTG_BSESSVLD; #endif UDC_IRQ_EN_REG = UDC_DS_CHG_IE; } @@ -1208,7 +1249,8 @@ static void pullup_enable(struct omap_udc *udc) static void pullup_disable(struct omap_udc *udc) { #ifndef CONFIG_USB_OTG - OTG_CTRL_REG &= ~OTG_BSESSVLD; + if (!cpu_is_omap15xx()) + OTG_CTRL_REG &= ~OTG_BSESSVLD; #endif UDC_IRQ_EN_REG = UDC_DS_CHG_IE; UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; @@ -1216,7 +1258,7 @@ static void pullup_disable(struct omap_udc *udc) /* * Called by whatever detects VBUS sessions: external transceiver - * driver, or maybe GPIO0 VBUS IRQ. + * driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock. */ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) { @@ -1227,6 +1269,13 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) spin_lock_irqsave(&udc->lock, flags); VDBG("VBUS %s\n", is_active ? "on" : "off"); udc->vbus_active = (is_active != 0); + if (cpu_is_omap15xx()) { + /* "software" detect, ignored if !VBUS_MODE_1510 */ + if (is_active) + FUNC_MUX_CTRL_0_REG |= VBUS_CTRL_1510; + else + FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510; + } if (can_pullup(udc)) pullup_enable(udc); else @@ -1340,8 +1389,15 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) /* Clear any pending requests and then scrub any rx/tx state * before starting to handle the SETUP request. */ - if (irq_src & UDC_SETUP) + if (irq_src & UDC_SETUP) { + u16 ack = irq_src & (UDC_EP0_TX|UDC_EP0_RX); + nuke(ep0, 0); + if (ack) { + UDC_IRQ_SRC_REG = ack; + irq_src = UDC_SETUP; + } + } /* IN/OUT packets mean we're in the DATA or STATUS stage. * This driver uses only uses protocol stalls (ep0 never halts), @@ -1506,8 +1562,10 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) use_ep(ep, 0); UDC_CTRL_REG = UDC_RESET_EP; ep->ackwait = 0; - if (!(ep->bEndpointAddress & USB_DIR_IN)) + if (!(ep->bEndpointAddress & USB_DIR_IN)) { UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } } VDBG("%s halt cleared by host\n", ep->name); goto ep0out_status_stage; @@ -1688,7 +1746,7 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) } change &= ~UDC_SUS; } - if (change & OTG_FLAGS) { + if (!cpu_is_omap15xx() && (change & OTG_FLAGS)) { update_otg(udc); change &= ~OTG_FLAGS; } @@ -1741,6 +1799,39 @@ omap_udc_irq(int irq, void *_udc, struct pt_regs *r) return status; } +/* workaround for seemingly-lost IRQs for RX ACKs... */ +#define PIO_OUT_TIMEOUT (jiffies + HZ/3) +#define HALF_FULL(f) (!((f)&(UDC_NON_ISO_FIFO_FULL|UDC_NON_ISO_FIFO_EMPTY))) + +static void pio_out_timer(unsigned long _ep) +{ + struct omap_ep *ep = (void *) _ep; + unsigned long flags; + u16 stat_flg; + + spin_lock_irqsave(&ep->udc->lock, flags); + if (!list_empty(&ep->queue) && ep->ackwait) { + use_ep(ep, 0); + stat_flg = UDC_STAT_FLG_REG; + + if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN) + || (ep->double_buf && HALF_FULL(stat_flg)))) { + struct omap_req *req; + + VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg); + req = container_of(ep->queue.next, + struct omap_req, queue); + UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL; + (void) read_fifo(ep, req); + UDC_EP_NUM_REG = ep->bEndpointAddress; + UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } + } + mod_timer(&ep->timer, PIO_OUT_TIMEOUT); + spin_unlock_irqrestore(&ep->udc->lock, flags); +} + static irqreturn_t omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r) { @@ -1764,38 +1855,56 @@ omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r) ep = &udc->ep[epnum]; ep->irqs++; - if (!list_empty(&ep->queue)) { - UDC_EP_NUM_REG = epnum | UDC_EP_SEL; - if ((UDC_STAT_FLG_REG & UDC_ACK)) { + UDC_EP_NUM_REG = epnum | UDC_EP_SEL; + ep->fnf = 0; + if ((UDC_STAT_FLG_REG & UDC_ACK)) { + ep->ackwait--; + if (!list_empty(&ep->queue)) { int stat; req = container_of(ep->queue.next, struct omap_req, queue); stat = read_fifo(ep, req); - // FIXME double buffered PIO OUT should work + if (!ep->double_buf) + ep->fnf = 1; } - UDC_EP_NUM_REG = epnum; } + /* min 6 clock delay before clearing EP_SEL ... */ + epn_stat = UDC_EPN_STAT_REG; + epn_stat = UDC_EPN_STAT_REG; + UDC_EP_NUM_REG = epnum; + + /* enabling fifo _after_ clearing ACK, contrary to docs, + * reduces lossage; timer still needed though (sigh). + */ + if (ep->fnf) { + UDC_CTRL_REG = UDC_SET_FIFO_EN; + ep->ackwait = 1 + ep->double_buf; + } + mod_timer(&ep->timer, PIO_OUT_TIMEOUT); } /* then IN transfers */ - if (irq_src & UDC_EPN_TX) { + else if (irq_src & UDC_EPN_TX) { epnum = epn_stat & 0x0f; UDC_IRQ_SRC_REG = UDC_EPN_TX; status = IRQ_HANDLED; ep = &udc->ep[16 + epnum]; ep->irqs++; - ep->ackwait = 0; - if (!list_empty(&ep->queue)) { - UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL; - if ((UDC_STAT_FLG_REG & UDC_ACK)) { + UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL; + if ((UDC_STAT_FLG_REG & UDC_ACK)) { + ep->ackwait = 0; + if (!list_empty(&ep->queue)) { req = container_of(ep->queue.next, struct omap_req, queue); (void) write_fifo(ep, req); } - UDC_EP_NUM_REG = epnum | UDC_EP_DIR; - /* 6 wait states before it'll tx */ } + /* min 6 clock delay before clearing EP_SEL ... */ + epn_stat = UDC_EPN_STAT_REG; + epn_stat = UDC_EPN_STAT_REG; + UDC_EP_NUM_REG = epnum | UDC_EP_DIR; + /* then 6 clocks before it'd tx */ } spin_unlock_irqrestore(&udc->lock, flags); @@ -1937,6 +2046,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) pullup_disable (udc); } + if (machine_is_omap_innovator()) + omap_vbus_session(&udc->gadget, 1); + done: return status; } @@ -1952,6 +2064,9 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (!driver || driver != udc->driver) return -EINVAL; + if (machine_is_omap_innovator()) + omap_vbus_session(&udc->gadget, 0); + if (udc->transceiver) (void) otg_set_peripheral(udc->transceiver, 0); else @@ -1974,7 +2089,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_OMAP_PROC +#ifdef CONFIG_USB_GADGET_DEBUG_FILES #include @@ -2000,8 +2115,16 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) stat_flg = UDC_STAT_FLG_REG; seq_printf(s, - "\n%s %sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n", - ep->name, buf, ep->irqs, stat_flg, + "\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n", + ep->name, buf, + ep->double_buf ? "dbuf " : "", + ({char *s; switch(ep->ackwait){ + case 0: s = ""; break; + case 1: s = "(ackw) "; break; + case 2: s = "(ackw2) "; break; + default: s = "(?) "; break; + } s;}), + ep->irqs, stat_flg, (stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "", (stat_flg & UDC_MISS_IN) ? "miss_in " : "", (stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "", @@ -2019,10 +2142,19 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep) if (list_empty (&ep->queue)) seq_printf(s, "\t(queue empty)\n"); else - list_for_each_entry (req, &ep->queue, queue) + list_for_each_entry (req, &ep->queue, queue) { + unsigned length = req->req.actual; + + if (use_dma && buf[0]) { + length += ((ep->bEndpointAddress & USB_DIR_IN) + ? dma_src_len : dma_dest_len) + (ep, req->req.dma + length); + buf[0] = 0; + } seq_printf(s, "\treq %p len %d/%d buf %p\n", - &req->req, req->req.actual, + &req->req, length, req->req.length, req->req.buf); + } } static char *trx_mode(unsigned m) @@ -2036,34 +2168,14 @@ static char *trx_mode(unsigned m) } } -static int proc_udc_show(struct seq_file *s, void *_) +static int proc_otg_show(struct seq_file *s) { u32 tmp; - struct omap_ep *ep; - unsigned long flags; - - spin_lock_irqsave(&udc->lock, flags); - seq_printf(s, "%s, version: " DRIVER_VERSION -#ifdef USE_ISO - " (iso)" -#endif - "%s\n", - driver_desc, - use_dma ? " (dma)" : ""); - - tmp = UDC_REV_REG & 0xff; - seq_printf(s, - "UDC rev %d.%d, OTG rev %d.%d, fifo mode %d, gadget %s\n" - "hmc %d, transceiver %08x %s\n", + tmp = OTG_REV_REG; + seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %08x\n", tmp >> 4, tmp & 0xf, - OTG_REV_REG >> 4, OTG_REV_REG & 0xf, - fifo_mode, - udc->driver ? udc->driver->driver.name : "(none)", - HMC, USB_TRANSCEIVER_CTRL_REG, - udc->transceiver ? udc->transceiver->label : ""); - - /* OTG controller registers */ + USB_TRANSCEIVER_CTRL_REG); tmp = OTG_SYSCON_1_REG; seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," FOURBITS "\n", tmp, @@ -2117,6 +2229,41 @@ static int proc_udc_show(struct seq_file *s, void *_) seq_printf(s, "otg_outctrl %04x" "\n", tmp); tmp = OTG_TEST_REG; seq_printf(s, "otg_test %04x" "\n", tmp); +} + +static int proc_udc_show(struct seq_file *s, void *_) +{ + u32 tmp; + struct omap_ep *ep; + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + + seq_printf(s, "%s, version: " DRIVER_VERSION +#ifdef USE_ISO + " (iso)" +#endif + "%s\n", + driver_desc, + use_dma ? " (dma)" : ""); + + tmp = UDC_REV_REG & 0xff; + seq_printf(s, + "UDC rev %d.%d, fifo mode %d, gadget %s\n" + "hmc %d, transceiver %s\n", + tmp >> 4, tmp & 0xf, + fifo_mode, + udc->driver ? udc->driver->driver.name : "(none)", + HMC, + udc->transceiver ? udc->transceiver->label : "(none)"); + seq_printf(s, "ULPD control %04x req %04x status %04x\n", + __REG16(ULPD_CLOCK_CTRL), + __REG16(ULPD_SOFT_REQ), + __REG16(ULPD_STATUS_REQ)); + + /* OTG controller registers */ + if (!cpu_is_omap15xx()) + proc_otg_show(s); tmp = UDC_SYSCON1_REG; seq_printf(s, "\nsyscon1 %04x" EIGHTBITS "\n", tmp, @@ -2292,10 +2439,10 @@ omap_ep_setup(char *name, u8 addr, u8 type, epn_rxtx |= UDC_EPN_RX_ISO; dbuf = 1; } else { - /* pio-out could potentially double-buffer, - * as can (should!) DMA-IN + /* double-buffering "not supported" on 15xx, + * and ignored for PIO-IN on 16xx */ - if (!use_dma || (addr & USB_DIR_IN)) + if (!use_dma || cpu_is_omap15xx()) dbuf = 0; switch (maxp) { @@ -2307,6 +2454,9 @@ omap_ep_setup(char *name, u8 addr, u8 type, } if (dbuf && addr) epn_rxtx |= UDC_EPN_RX_DB; + init_timer(&ep->timer); + ep->timer.function = pio_out_timer; + ep->timer.data = (unsigned long) ep; } if (addr) epn_rxtx |= UDC_EPN_RX_VALID; @@ -2496,41 +2646,63 @@ static int __init omap_udc_probe(struct device *dev) return -EBUSY; } - INFO("OMAP UDC rev %d.%d, OTG rev %d.%d, %s receptacle\n", + INFO("OMAP UDC rev %d.%d%s\n", UDC_REV_REG >> 4, UDC_REV_REG & 0xf, - OTG_REV_REG >> 4, OTG_REV_REG & 0xf, - config->otg ? "Mini-AB" : "B/Mini-B"); + config->otg ? ", Mini-AB" : ""); /* use the mode given to us by board init code */ - hmc = HMC; - switch (hmc) { - case 3: - case 11: - case 19: - case 25: - xceiv = otg_get_transceiver(); - if (!xceiv) { - DBG("external transceiver not registered!\n"); - goto cleanup0; + if (cpu_is_omap15xx()) { + hmc = HMC_1510; + type = "(unknown)"; + + if (machine_is_omap_innovator()) { + /* just set up software VBUS detect, and then + * later rig it so we always report VBUS. + * FIXME without really sensing VBUS, we can't + * know when to turn PULLUP_EN on/off; and that + * means we always "need" the 48MHz clock. + */ + u32 tmp = FUNC_MUX_CTRL_0_REG; + + FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510; + tmp |= VBUS_MODE_1510; + tmp &= ~VBUS_CTRL_1510; + FUNC_MUX_CTRL_0_REG = tmp; } - type = xceiv->label; - break; - case 0: /* POWERUP DEFAULT == 0 */ - case 4: - case 12: - case 20: - type = "INTEGRATED"; - break; - case 21: /* internal loopback */ - type = "(loopback)"; - break; - case 14: /* transceiverless */ - type = "(none)"; - break; + } else { + hmc = HMC_1610; + switch (hmc) { + case 3: + case 11: + case 16: + case 19: + case 25: + xceiv = otg_get_transceiver(); + if (!xceiv) { + DBG("external transceiver not registered!\n"); + if (config->otg) + goto cleanup0; + type = "(unknown external)"; + } else + type = xceiv->label; + break; + case 0: /* POWERUP DEFAULT == 0 */ + case 4: + case 12: + case 20: + type = "INTEGRATED"; + break; + case 21: /* internal loopback */ + type = "(loopback)"; + break; + case 14: /* transceiverless */ + type = "(none)"; + break; - default: - ERR("unrecognized UDC HMC mode %d\n", hmc); - return -ENODEV; + default: + ERR("unrecognized UDC HMC mode %d\n", hmc); + return -ENODEV; + } } INFO("hmc mode %d, transceiver %s\n", hmc, type); @@ -2542,7 +2714,9 @@ static int __init omap_udc_probe(struct device *dev) xceiv = 0; // "udc" is now valid pullup_disable(udc); +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) udc->gadget.is_otg = (config->otg != 0); +#endif /* USB general purpose IRQ: ep0, state changes, dma, etc */ status = request_irq(odev->resource[1].start, omap_udc_irq, @@ -2671,14 +2845,11 @@ static struct device_driver udc_driver = { static int __init udc_init(void) { - /* should work on many OMAP systems with at most minor changes, - * but the 1510 doesn't have an OTG controller. - */ - if (cpu_is_omap1510()) { - DBG("no OMAP1510 support yet\n"); - return -ENODEV; - } - INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc, + INFO("%s, version: " DRIVER_VERSION +#ifdef USE_ISO + " (iso)" +#endif + "%s\n", driver_desc, use_dma ? " (dma)" : ""); return driver_register(&udc_driver); } diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index bd5420cd0..c9e685416 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -146,11 +146,14 @@ struct omap_ep { u8 bmAttributes; unsigned double_buf:1; unsigned stopped:1; - unsigned ackwait:1; + unsigned fnf:1; unsigned has_dma:1; + u8 ackwait; u8 dma_channel; + u16 dma_counter; int lch; struct omap_udc *udc; + struct timer_list timer; }; struct omap_udc { @@ -168,7 +171,6 @@ struct omap_udc { unsigned ep0_set_config:1; unsigned ep0_reset_config:1; unsigned ep0_setup:1; - unsigned hmc:6; struct completion *done; }; @@ -193,7 +195,14 @@ struct omap_udc { /*-------------------------------------------------------------------------*/ -// #define HMC_1510 ((MOD_CONF_CTRL_0_REG >> 1) & 0x3f) +#define MOD_CONF_CTRL_0_REG __REG32(MOD_CONF_CTRL_0) +#define VBUS_W2FC_1510 (1 << 17) /* 0 gpio0, 1 dvdd2 pin */ + +#define FUNC_MUX_CTRL_0_REG __REG32(FUNC_MUX_CTRL_0) +#define VBUS_CTRL_1510 (1 << 19) /* 1 connected (software) */ +#define VBUS_MODE_1510 (1 << 18) /* 0 hardware, 1 software */ + +#define HMC_1510 ((MOD_CONF_CTRL_0_REG >> 1) & 0x3f) #define HMC_1610 (OTG_SYSCON_2_REG & 0x3f) -#define HMC HMC_1610 +#define HMC (cpu_is_omap15xx() ? HMC_1510 : HMC_1610) diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 63e538a57..710f7a435 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -91,10 +92,6 @@ static const char ep0name [] = "ep0"; // #define USE_OUT_DMA // #define DISABLE_TEST_MODE -#ifdef CONFIG_PROC_FS -#define UDC_PROC_FILE -#endif - #ifdef CONFIG_ARCH_IXP4XX #undef USE_DMA @@ -108,15 +105,9 @@ static const char ep0name [] = "ep0"; #include "pxa2xx_udc.h" -#ifdef CONFIG_EMBEDDED -/* few strings, and little code to use them */ -#undef DEBUG -#undef UDC_PROC_FILE -#endif - #ifdef USE_DMA static int use_dma = 1; -MODULE_PARM (use_dma, "i"); +module_param(use_dma, bool, 0); MODULE_PARM_DESC (use_dma, "true to use dma"); static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r); @@ -146,7 +137,7 @@ static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req); * ... so mode = 3 (or 7, 15, etc) does it for both */ static ushort fifo_mode = 0; -MODULE_PARM (fifo_mode, "h"); +module_param(fifo_mode, ushort, 0); MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode"); #endif @@ -1211,7 +1202,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = { /*-------------------------------------------------------------------------*/ -#ifdef UDC_PROC_FILE +#ifdef CONFIG_USB_GADGET_DEBUG_FILES static const char proc_node_name [] = "driver/udc"; @@ -1367,11 +1358,12 @@ done: #define remove_proc_files() \ remove_proc_entry(proc_node_name, NULL) -#else /* !UDC_PROC_FILE */ +#else /* !CONFIG_USB_GADGET_DEBUG_FILES */ + #define create_proc_files() do {} while (0) #define remove_proc_files() do {} while (0) -#endif /* UDC_PROC_FILE */ +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ /* "function" sysfs attribute */ static ssize_t @@ -1508,7 +1500,7 @@ static void udc_enable (struct pxa2xx_udc *dev) /* caller must be able to sleep in order to cope * with startup transients. */ - schedule_timeout(HZ/10); + msleep(100); /* enable suspend/resume and reset irqs */ udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 1cd445a01..c3d064b09 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -70,8 +70,6 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging"); #define RNDIS_MAX_CONFIGS 1 -static struct proc_dir_entry *rndis_connect_dir; -static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; @@ -123,7 +121,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); length = 4; /* Bogus question! - * Hardware must be ready to recieve high level protocols. + * Hardware must be ready to receive high level protocols. * BTW: * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! @@ -1275,7 +1273,9 @@ int rndis_rm_hdr (u8 *buf, u32 *length) return 0; } -int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, void *data) { char *out = page; @@ -1320,7 +1320,7 @@ int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, return len; } -int rndis_proc_write (struct file *file, const char __user *buffer, +static int rndis_proc_write (struct file *file, const char __user *buffer, unsigned long count, void *data) { rndis_params *p = data; @@ -1365,43 +1365,40 @@ int rndis_proc_write (struct file *file, const char __user *buffer, return count; } +#define NAME_TEMPLATE "driver/rndis-%03d" + +static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; + +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ + + int __init rndis_init (void) { u8 i; - char name [4]; - /* FIXME this should probably be /proc/driver/rndis, - * and only if debugging is enabled - */ - - if (!(rndis_connect_dir = proc_mkdir ("rndis", NULL))) { - printk (KERN_ERR "%s: couldn't create /proc/rndis entry", - __FUNCTION__); - return -EIO; - } - for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - sprintf (name, "%03d", i); +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + char name [20]; + + sprintf (name, NAME_TEMPLATE, i); if (!(rndis_connect_state [i] - = create_proc_entry (name, 0660, - rndis_connect_dir))) + = create_proc_entry (name, 0660, NULL))) { DEBUG ("%s :remove entries", __FUNCTION__); - for (i--; i > 0; i--) { - sprintf (name, "%03d", i); - remove_proc_entry (name, rndis_connect_dir); + while (i) { + sprintf (name, NAME_TEMPLATE, --i); + remove_proc_entry (name, NULL); } DEBUG ("\n"); - - remove_proc_entry ("000", rndis_connect_dir); - remove_proc_entry ("rndis", NULL); return -EIO; } + rndis_connect_state [i]->nlink = 1; rndis_connect_state [i]->write_proc = rndis_proc_write; rndis_connect_state [i]->read_proc = rndis_proc_read; rndis_connect_state [i]->data = (void *) (rndis_per_dev_params + i); +#endif rndis_per_dev_params [i].confignr = i; rndis_per_dev_params [i].used = 0; rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED; @@ -1415,14 +1412,14 @@ int __init rndis_init (void) void rndis_exit (void) { +#ifdef CONFIG_USB_GADGET_DEBUG_FILES u8 i; - char name [4]; + char name [20]; for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - sprintf (name, "%03d", i); - remove_proc_entry (name, rndis_connect_dir); + sprintf (name, NAME_TEMPLATE, i); + remove_proc_entry (name, NULL); } - remove_proc_entry ("rndis", NULL); - return; +#endif } diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ebfc22b2a..15c2c02aa 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -48,6 +48,8 @@ #include #include +#include "gadget_chips.h" + /* Wait Cond */ @@ -121,10 +123,84 @@ do { \ }) +/* CDC-ACM Defines and Structures */ + +#define USB_CDC_SUBCLASS_ACM 2 + +#define USB_CDC_CTRL_PROTO_NONE 0 +#define USB_CDC_CTRL_PROTO_AT 1 +#define USB_CDC_CTRL_PROTO_VENDOR 0xff + +#define USB_CDC_SUBTYPE_HEADER 0 +#define USB_CDC_SUBTYPE_CALL_MGMT 1 +#define USB_CDC_SUBTYPE_ACM 2 +#define USB_CDC_SUBTYPE_UNION 6 + +#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 +#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 + +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 + +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + +/* Header Functional Descriptor from CDC spec 5.2.3.1 */ +struct usb_cdc_header_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + u16 bcdCDC; +} __attribute__ ((packed)); + +/* Call Management Descriptor from CDC spec 5.2.3.3 */ +struct usb_cdc_call_mgmt_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + u8 bmCapabilities; + u8 bDataInterface; +} __attribute__ ((packed)); + +/* Abstract Control Management Descriptor from CDC spec 5.2.3.4 */ +struct usb_cdc_acm_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + u8 bmCapabilities; +} __attribute__ ((packed)); + +/* Union Functional Descriptor from CDC spec 5.2.3.8 */ +struct usb_cdc_union_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + u8 bMasterInterface0; + u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +/* Line Coding Structure from CDC spec 6.2.13 */ +struct usb_cdc_line_coding { + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; +} __attribute__ ((packed)); + + /* Defines */ -#define GS_VERSION_STR "v0.1" -#define GS_VERSION_NUM 0x0001 +#define GS_VERSION_STR "v2.0" +#define GS_VERSION_NUM 0x0200 #define GS_LONG_NAME "Gadget Serial" #define GS_SHORT_NAME "g_serial" @@ -136,13 +212,13 @@ do { \ #define GS_NUM_CONFIGS 1 #define GS_NO_CONFIG_ID 0 -#define GS_BULK_CONFIG_ID 2 +#define GS_BULK_CONFIG_ID 1 +#define GS_ACM_CONFIG_ID 2 -#define GS_NUM_INTERFACES 1 -#define GS_INTERFACE_ID 0 -#define GS_ALT_INTERFACE_ID 0 - -#define GS_NUM_ENDPOINTS 2 +#define GS_MAX_NUM_INTERFACES 2 +#define GS_BULK_INTERFACE_ID 0 +#define GS_CONTROL_INTERFACE_ID 0 +#define GS_DATA_INTERFACE_ID 1 #define GS_MAX_DESC_LEN 256 @@ -154,9 +230,23 @@ do { \ #define GS_CLOSE_TIMEOUT 15 +#define GS_DEFAULT_USE_ACM 0 + +#define GS_DEFAULT_DTE_RATE 9600 +#define GS_DEFAULT_DATA_BITS 8 +#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY +#define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS + +/* select highspeed/fullspeed, hiding highspeed if not configured */ +#ifdef CONFIG_USB_GADGET_DUALSPEED +#define GS_SPEED_SELECT(is_hs,hs,fs) ((is_hs) ? (hs) : (fs)) +#else +#define GS_SPEED_SELECT(is_hs,hs,fs) (fs) +#endif /* CONFIG_USB_GADGET_DUALSPEED */ + /* debug settings */ -#if G_SERIAL_DEBUG -static int debug = G_SERIAL_DEBUG; +#ifdef GS_DEBUG +static int debug = 1; #define gs_debug(format, arg...) \ do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0) @@ -170,175 +260,19 @@ static int debug = G_SERIAL_DEBUG; #define gs_debug_level(level, format, arg...) \ do { } while(0) -#endif /* G_SERIAL_DEBUG */ - - -/* USB Controllers */ - -/* - * NetChip 2280, PCI based. - * - * This has half a dozen configurable endpoints, four with dedicated - * DMA channels to manage their FIFOs. It supports high speed. - * Those endpoints can be arranged in any desired configuration. - */ -#ifdef CONFIG_USB_GADGET_NET2280 -#define CHIP "net2280" -#define EP0_MAXPACKET 64 -static const char EP_OUT_NAME[] = "ep-a"; -#define EP_OUT_NUM 2 -static const char EP_IN_NAME[] = "ep-b"; -#define EP_IN_NUM 2 -#define HIGHSPEED -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER - -extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode); - -static inline void hw_optimize(struct usb_gadget *gadget) -{ - /* we can have bigger ep-a/ep-b fifos (2KB each, 4 packets - * for highspeed bulk) because we're not using ep-c/ep-d. - */ - net2280_set_fifo_mode (gadget, 1); -} -#endif - - -/* - * Dummy_hcd, software-based loopback controller. - * - * This imitates the abilities of the NetChip 2280, so we will use - * the same configuration. - */ -#ifdef CONFIG_USB_GADGET_DUMMY_HCD -#define CHIP "dummy" -#define EP0_MAXPACKET 64 -static const char EP_OUT_NAME[] = "ep-a"; -#define EP_OUT_NUM 2 -static const char EP_IN_NAME[] = "ep-b"; -#define EP_IN_NUM 2 -#define HIGHSPEED -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER - -/* no hw optimizations to apply */ -#define hw_optimize(g) do {} while (0) -#endif - - -/* - * PXA-2xx UDC: widely used in second gen Linux-capable PDAs. - * - * This has fifteen fixed-function full speed endpoints, and it - * can support all USB transfer types. - * - * These supports three or four configurations, with fixed numbers. - * The hardware interprets SET_INTERFACE, net effect is that you - * can't use altsettings or reset the interfaces independently. - * So stick to a single interface. - */ -#ifdef CONFIG_USB_GADGET_PXA2XX -#define CHIP "pxa2xx" -#define EP0_MAXPACKET 16 -static const char EP_OUT_NAME[] = "ep2out-bulk"; -#define EP_OUT_NUM 2 -static const char EP_IN_NAME[] = "ep1in-bulk"; -#define EP_IN_NUM 1 -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER - -/* no hw optimizations to apply */ -#define hw_optimize(g) do {} while (0) -#endif - -#ifdef CONFIG_USB_GADGET_OMAP -#define CHIP "omap" -#define EP0_MAXPACKET 64 -static const char EP_OUT_NAME [] = "ep2out-bulk"; -#define EP_OUT_NUM 2 -static const char EP_IN_NAME [] = "ep1in-bulk"; -#define EP_IN_NUM 1 -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER -/* supports remote wakeup, but this driver doesn't */ - -/* no hw optimizations to apply */ -#define hw_optimize(g) do {} while (0) -#endif - - -/* - * SA-1100 UDC: widely used in first gen Linux-capable PDAs. - * - * This has only two fixed function endpoints, which can only - * be used for bulk (or interrupt) transfers. (Plus control.) - * - * Since it can't flush its TX fifos without disabling the UDC, - * the current configuration or altsettings can't change except - * in special situations. So this is a case of "choose it right - * during enumeration" ... - */ -#ifdef CONFIG_USB_GADGET_SA1100 -#define CHIP "sa1100" -#define EP0_MAXPACKET 8 -static const char EP_OUT_NAME[] = "ep1out-bulk"; -#define EP_OUT_NUM 1 -static const char EP_IN_NAME [] = "ep2in-bulk"; -#define EP_IN_NUM 2 -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER - -/* no hw optimizations to apply */ -#define hw_optimize(g) do {} while (0) -#endif - - -/* - * Toshiba TC86C001 ("Goku-S") UDC - * - * This has three semi-configurable full speed bulk/interrupt endpoints. - */ -#ifdef CONFIG_USB_GADGET_GOKU -#define CHIP "goku" -#define DRIVER_VERSION_NUM 0x0116 -#define EP0_MAXPACKET 8 -static const char EP_OUT_NAME [] = "ep1-bulk"; -#define EP_OUT_NUM 1 -static const char EP_IN_NAME [] = "ep2-bulk"; -#define EP_IN_NUM 2 -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER - -/* no hw optimizations to apply */ -#define hw_optimize(g) do {} while (0) -#endif - -/* - * USB Controller Defaults - */ -#ifndef EP0_MAXPACKET -#error Configure some USB peripheral controller for g_serial! -#endif - -#ifndef SELFPOWER -/* default: say we rely on bus power */ -#define SELFPOWER 0 -/* else value must be USB_CONFIG_ATT_SELFPOWER */ -#endif - -#ifndef MAX_USB_POWER -/* any hub supports this steady state bus power consumption */ -#define MAX_USB_POWER 100 /* mA */ -#endif - -#ifndef WAKEUP -/* default: this driver won't do remote wakeup */ -#define WAKEUP 0 -/* else value must be USB_CONFIG_ATT_WAKEUP */ -#endif +#endif /* GS_DEBUG */ /* Thanks to NetChip Technologies for donating this product ID. * * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! * Instead: allocate your own, using normal USB-IF procedures. */ -#define GS_VENDOR_ID 0x0525 /* NetChip */ -#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */ +#define GS_VENDOR_ID 0x0525 /* NetChip */ +#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */ +#define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */ + +#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ +#define GS_NOTIFY_MAXPACKET 8 /* Structures */ @@ -369,6 +303,7 @@ struct gs_port { int port_in_use; /* open/close in progress */ wait_queue_head_t port_write_wait;/* waiting to write */ struct gs_buf *port_write_buf; + struct usb_cdc_line_coding port_line_coding; }; /* the device structure holds info for the USB device */ @@ -376,8 +311,15 @@ struct gs_dev { struct usb_gadget *dev_gadget; /* gadget device pointer */ spinlock_t dev_lock; /* lock for set/reset config */ int dev_config; /* configuration number */ + struct usb_ep *dev_notify_ep; /* address of notify endpoint */ struct usb_ep *dev_in_ep; /* address of in endpoint */ struct usb_ep *dev_out_ep; /* address of out endpoint */ + struct usb_endpoint_descriptor /* desciptor of notify ep */ + *dev_notify_ep_desc; + struct usb_endpoint_descriptor /* descriptor of in endpoint */ + *dev_in_ep_desc; + struct usb_endpoint_descriptor /* descriptor of out endpoint */ + *dev_out_ep_desc; struct usb_request *dev_ctrl_req; /* control request */ struct list_head dev_req_list; /* list of write requests */ int dev_sched_port; /* round robin port scheduled */ @@ -394,7 +336,7 @@ static void __exit gs_module_exit(void); /* tty driver */ static int gs_open(struct tty_struct *tty, struct file *file); static void gs_close(struct tty_struct *tty, struct file *file); -static int gs_write(struct tty_struct *tty, int from_user, +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count); static void gs_put_char(struct tty_struct *tty, unsigned char ch); static void gs_flush_chars(struct tty_struct *tty); @@ -420,12 +362,16 @@ static int gs_bind(struct usb_gadget *gadget); static void gs_unbind(struct usb_gadget *gadget); static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl); +static int gs_setup_standard(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl); +static int gs_setup_class(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl); static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req); static void gs_disconnect(struct usb_gadget *gadget); static int gs_set_config(struct gs_dev *dev, unsigned config); static void gs_reset_config(struct gs_dev *dev); -static int gs_build_config_desc(u8 *buf, enum usb_device_speed speed, - u8 type, unsigned int index); +static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, + u8 type, unsigned int index, int is_otg); static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int kmalloc_flags); @@ -449,11 +395,18 @@ static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count); +/* external functions */ +extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode); + /* Globals */ static struct gs_dev *gs_device; +static const char *EP_IN_NAME; +static const char *EP_OUT_NAME; +static const char *EP_NOTIFY_NAME; + static struct semaphore gs_open_close_sem[GS_NUM_PORTS]; static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; @@ -461,8 +414,8 @@ static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; -static unsigned char gs_tmp_buf[GS_TMP_BUF_SIZE]; -static struct semaphore gs_tmp_buf_sem; +static unsigned int use_acm = GS_DEFAULT_USE_ACM; + /* tty driver struct */ static struct tty_operations gs_tty_ops = { @@ -483,11 +436,11 @@ static struct tty_driver *gs_tty_driver; /* gadget driver struct */ static struct usb_gadget_driver gs_gadget_driver = { -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, #else .speed = USB_SPEED_FULL, -#endif +#endif /* CONFIG_USB_GADGET_DUALSPEED */ .function = GS_LONG_NAME, .bind = gs_bind, .unbind = gs_unbind, @@ -507,14 +460,21 @@ static struct usb_gadget_driver gs_gadget_driver = { #define GS_MANUFACTURER_STR_ID 1 #define GS_PRODUCT_STR_ID 2 #define GS_SERIAL_STR_ID 3 -#define GS_CONFIG_STR_ID 4 +#define GS_BULK_CONFIG_STR_ID 4 +#define GS_ACM_CONFIG_STR_ID 5 +#define GS_CONTROL_STR_ID 6 +#define GS_DATA_STR_ID 7 -/* static strings, in iso 8859/1 */ +/* static strings, in UTF-8 */ +static char manufacturer[50]; static struct usb_string gs_strings[] = { - { GS_MANUFACTURER_STR_ID, UTS_SYSNAME " " UTS_RELEASE " with " CHIP }, + { GS_MANUFACTURER_STR_ID, manufacturer }, { GS_PRODUCT_STR_ID, GS_LONG_NAME }, { GS_SERIAL_STR_ID, "0" }, - { GS_CONFIG_STR_ID, "Bulk" }, + { GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" }, + { GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" }, + { GS_CONTROL_STR_ID, "Gadget Serial Control" }, + { GS_DATA_STR_ID, "Gadget Serial Data" }, { } /* end of list */ }; @@ -523,83 +483,211 @@ static struct usb_gadget_strings gs_string_table = { .strings = gs_strings, }; -static const struct usb_device_descriptor gs_device_desc = { +static struct usb_device_descriptor gs_device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16(0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .bMaxPacketSize0 = EP0_MAXPACKET, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID), .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID), - .bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM), .iManufacturer = GS_MANUFACTURER_STR_ID, .iProduct = GS_PRODUCT_STR_ID, .iSerialNumber = GS_SERIAL_STR_ID, .bNumConfigurations = GS_NUM_CONFIGS, }; -static const struct usb_config_descriptor gs_config_desc = { +static struct usb_otg_descriptor gs_otg_descriptor = { + .bLength = sizeof(gs_otg_descriptor), + .bDescriptorType = USB_DT_OTG, + .bmAttributes = USB_OTG_SRP, +}; + +static struct usb_config_descriptor gs_bulk_config_desc = { .bLength = USB_DT_CONFIG_SIZE, .bDescriptorType = USB_DT_CONFIG, - /* .wTotalLength set by gs_build_config_desc */ - .bNumInterfaces = GS_NUM_INTERFACES, + /* .wTotalLength computed dynamically */ + .bNumInterfaces = 1, .bConfigurationValue = GS_BULK_CONFIG_ID, - .iConfiguration = GS_CONFIG_STR_ID, - .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, - .bMaxPower = (MAX_USB_POWER + 1) / 2, + .iConfiguration = GS_BULK_CONFIG_STR_ID, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, }; -static const struct usb_interface_descriptor gs_interface_desc = { +static struct usb_config_descriptor gs_acm_config_desc = { + .bLength = USB_DT_CONFIG_SIZE, + .bDescriptorType = USB_DT_CONFIG, + /* .wTotalLength computed dynamically */ + .bNumInterfaces = 2, + .bConfigurationValue = GS_ACM_CONFIG_ID, + .iConfiguration = GS_ACM_CONFIG_STR_ID, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, +}; + +static const struct usb_interface_descriptor gs_bulk_interface_desc = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bNumEndpoints = GS_NUM_ENDPOINTS, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .iInterface = GS_CONFIG_STR_ID, + .bInterfaceNumber = GS_BULK_INTERFACE_ID, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = GS_DATA_STR_ID, }; -static const struct usb_endpoint_descriptor gs_fullspeed_in_desc = { +static const struct usb_interface_descriptor gs_control_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = GS_CONTROL_INTERFACE_ID, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_CTRL_PROTO_AT, + .iInterface = GS_CONTROL_STR_ID, +}; + +static const struct usb_interface_descriptor gs_data_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = GS_DATA_INTERFACE_ID, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = GS_DATA_STR_ID, +}; + +static const struct usb_cdc_header_desc gs_header_desc = { + .bLength = sizeof(gs_header_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_SUBTYPE_HEADER, + .bcdCDC = __constant_cpu_to_le16(0x0110), +}; + +static const struct usb_cdc_call_mgmt_desc gs_call_mgmt_descriptor = { + .bLength = sizeof(gs_call_mgmt_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_SUBTYPE_CALL_MGMT, + .bmCapabilities = 0, + .bDataInterface = 1, /* index of data interface */ +}; + +static struct usb_cdc_acm_desc gs_acm_descriptor = { + .bLength = sizeof(gs_acm_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_SUBTYPE_ACM, + .bmCapabilities = 0, +}; + +static const struct usb_cdc_union_desc gs_union_desc = { + .bLength = sizeof(gs_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_SUBTYPE_UNION, + .bMasterInterface0 = 0, /* index of control interface */ + .bSlaveInterface0 = 1, /* index of data interface */ +}; + +static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, +}; + +static struct usb_endpoint_descriptor gs_fullspeed_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), }; -static const struct usb_endpoint_descriptor gs_fullspeed_out_desc = { +static struct usb_endpoint_descriptor gs_fullspeed_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_OUT_NUM | USB_DIR_OUT, + .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(64), }; -static const struct usb_endpoint_descriptor gs_highspeed_in_desc = { +static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = { + (struct usb_descriptor_header *) &gs_otg_descriptor, + (struct usb_descriptor_header *) &gs_bulk_interface_desc, + (struct usb_descriptor_header *) &gs_fullspeed_in_desc, + (struct usb_descriptor_header *) &gs_fullspeed_out_desc, + NULL, +}; + +static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = { + (struct usb_descriptor_header *) &gs_otg_descriptor, + (struct usb_descriptor_header *) &gs_control_interface_desc, + (struct usb_descriptor_header *) &gs_header_desc, + (struct usb_descriptor_header *) &gs_call_mgmt_descriptor, + (struct usb_descriptor_header *) &gs_acm_descriptor, + (struct usb_descriptor_header *) &gs_union_desc, + (struct usb_descriptor_header *) &gs_fullspeed_notify_desc, + (struct usb_descriptor_header *) &gs_data_interface_desc, + (struct usb_descriptor_header *) &gs_fullspeed_in_desc, + (struct usb_descriptor_header *) &gs_fullspeed_out_desc, + NULL, +}; + +#ifdef CONFIG_USB_GADGET_DUALSPEED +static struct usb_endpoint_descriptor gs_highspeed_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, +}; + +static struct usb_endpoint_descriptor gs_highspeed_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = __constant_cpu_to_le16(512), }; -static const struct usb_endpoint_descriptor gs_highspeed_out_desc = { +static struct usb_endpoint_descriptor gs_highspeed_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_OUT_NUM | USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = __constant_cpu_to_le16(512), }; -#ifdef HIGHSPEED -static const struct usb_qualifier_descriptor gs_qualifier_desc = { +static struct usb_qualifier_descriptor gs_qualifier_desc = { .bLength = sizeof(struct usb_qualifier_descriptor), .bDescriptorType = USB_DT_DEVICE_QUALIFIER, .bcdUSB = __constant_cpu_to_le16 (0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, /* assumes ep0 uses the same value for both speeds ... */ - .bMaxPacketSize0 = EP0_MAXPACKET, .bNumConfigurations = GS_NUM_CONFIGS, }; -#endif + +static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = { + (struct usb_descriptor_header *) &gs_otg_descriptor, + (struct usb_descriptor_header *) &gs_bulk_interface_desc, + (struct usb_descriptor_header *) &gs_highspeed_in_desc, + (struct usb_descriptor_header *) &gs_highspeed_out_desc, + NULL, +}; + +static const struct usb_descriptor_header *gs_acm_highspeed_function[] = { + (struct usb_descriptor_header *) &gs_otg_descriptor, + (struct usb_descriptor_header *) &gs_control_interface_desc, + (struct usb_descriptor_header *) &gs_header_desc, + (struct usb_descriptor_header *) &gs_call_mgmt_descriptor, + (struct usb_descriptor_header *) &gs_acm_descriptor, + (struct usb_descriptor_header *) &gs_union_desc, + (struct usb_descriptor_header *) &gs_highspeed_notify_desc, + (struct usb_descriptor_header *) &gs_data_interface_desc, + (struct usb_descriptor_header *) &gs_highspeed_in_desc, + (struct usb_descriptor_header *) &gs_highspeed_out_desc, + NULL, +}; + +#endif /* CONFIG_USB_GADGET_DUALSPEED */ /* Module */ @@ -607,20 +695,23 @@ MODULE_DESCRIPTION(GS_LONG_NAME); MODULE_AUTHOR("Al Borchers"); MODULE_LICENSE("GPL"); -#if G_SERIAL_DEBUG -MODULE_PARM(debug, "i"); +#ifdef GS_DEBUG +module_param(debug, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); #endif -MODULE_PARM(read_q_size, "i"); +module_param(read_q_size, uint, S_IRUGO); MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); -MODULE_PARM(write_q_size, "i"); +module_param(write_q_size, uint, S_IRUGO); MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32"); -MODULE_PARM(write_buf_size, "i"); +module_param(write_buf_size, uint, S_IRUGO); MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192"); +module_param(use_acm, uint, S_IRUGO); +MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no"); + module_init(gs_module_init); module_exit(gs_module_exit); @@ -659,8 +750,6 @@ static int __init gs_module_init(void) for (i=0; i < GS_NUM_PORTS; i++) sema_init(&gs_open_close_sem[i], 1); - sema_init(&gs_tmp_buf_sem, 1); - retval = tty_register_driver(gs_tty_driver); if (retval) { usb_gadget_unregister_driver(&gs_gadget_driver); @@ -700,13 +789,12 @@ static int gs_open(struct tty_struct *tty, struct file *file) struct gs_dev *dev; struct gs_buf *buf; struct semaphore *sem; + int ret; port_num = tty->index; gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file); - tty->driver_data = NULL; - if (port_num < 0 || port_num >= GS_NUM_PORTS) { printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n", port_num, tty, file); @@ -735,9 +823,8 @@ static int gs_open(struct tty_struct *tty, struct file *file) printk(KERN_ERR "gs_open: (%d,%p,%p) device is not connected\n", port_num, tty, file); - spin_unlock_irqrestore(&dev->dev_lock, flags); - up(sem); - return -ENODEV; + ret = -ENODEV; + goto exit_unlock_dev; } port = dev->dev_port[port_num]; @@ -745,9 +832,8 @@ static int gs_open(struct tty_struct *tty, struct file *file) if (port == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n", port_num, tty, file); - spin_unlock_irqrestore(&dev->dev_lock, flags); - up(sem); - return -ENODEV; + ret = -ENODEV; + goto exit_unlock_dev; } spin_lock(&port->port_lock); @@ -756,20 +842,20 @@ static int gs_open(struct tty_struct *tty, struct file *file) if (port->port_dev == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n", port_num, tty, file); - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return -EIO; + ret = -EIO; + goto exit_unlock_port; } if (port->port_open_count > 0) { ++port->port_open_count; - spin_unlock_irqrestore(&port->port_lock, flags); gs_debug("gs_open: (%d,%p,%p) already open\n", port_num, tty, file); - up(sem); - return 0; + ret = 0; + goto exit_unlock_port; } + tty->driver_data = NULL; + /* mark port as in use, we can drop port lock and sleep if necessary */ port->port_in_use = 1; @@ -785,18 +871,16 @@ static int gs_open(struct tty_struct *tty, struct file *file) "gs_open: (%d,%p,%p) port disconnected (2)\n", port_num, tty, file); port->port_in_use = 0; - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return -EIO; + ret = -EIO; + goto exit_unlock_port; } if ((port->port_write_buf=buf) == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n", port_num, tty, file); port->port_in_use = 0; - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return -ENOMEM; + ret = -ENOMEM; + goto exit_unlock_port; } } @@ -808,9 +892,8 @@ static int gs_open(struct tty_struct *tty, struct file *file) printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n", port_num, tty, file); port->port_in_use = 0; - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return -EIO; + ret = -EIO; + goto exit_unlock_port; } tty->driver_data = port; @@ -818,12 +901,20 @@ static int gs_open(struct tty_struct *tty, struct file *file) port->port_open_count = 1; port->port_in_use = 0; + gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file); + + ret = 0; + +exit_unlock_port: spin_unlock_irqrestore(&port->port_lock, flags); up(sem); + return ret; - gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file); +exit_unlock_dev: + spin_unlock_irqrestore(&dev->dev_lock, flags); + up(sem); + return ret; - return 0; } /* @@ -851,24 +942,18 @@ static void gs_close(struct tty_struct *tty, struct file *file) printk(KERN_ERR "gs_close: (%d,%p,%p) port is already closed\n", port->port_num, tty, file); - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return; + goto exit; } - if (port->port_open_count > 0) { + if (port->port_open_count > 1) { --port->port_open_count; - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return; + goto exit; } /* free disconnected port on final close */ if (port->port_dev == NULL) { kfree(port); - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return; + goto exit; } /* mark port as closed but in use, we can drop port lock */ @@ -889,9 +974,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) /* (might have happened during the above sleep) */ if (port->port_dev == NULL) { kfree(port); - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - return; + goto exit; } gs_buf_clear(port->port_write_buf); @@ -900,20 +983,22 @@ static void gs_close(struct tty_struct *tty, struct file *file) port->port_tty = NULL; port->port_in_use = 0; - spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); - gs_debug("gs_close: (%d,%p,%p) completed\n", port->port_num, tty, file); + +exit: + spin_unlock_irqrestore(&port->port_lock, flags); + up(sem); } /* * gs_write */ -static int gs_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) { unsigned long flags; struct gs_port *port = tty->driver_data; + int ret; if (port == NULL) { printk(KERN_ERR "gs_write: NULL port pointer\n"); @@ -926,54 +1011,36 @@ static int gs_write(struct tty_struct *tty, int from_user, const unsigned char * if (count == 0) return 0; - /* copy from user into tmp buffer, get tmp_buf semaphore */ - if (from_user) { - if (count > GS_TMP_BUF_SIZE) - count = GS_TMP_BUF_SIZE; - down(&gs_tmp_buf_sem); - if (copy_from_user(gs_tmp_buf, buf, count) != 0) { - up(&gs_tmp_buf_sem); - printk(KERN_ERR - "gs_write: (%d,%p) cannot copy from user space\n", - port->port_num, tty); - return -EFAULT; - } - buf = gs_tmp_buf; - } - spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); - return -EIO; + ret = -EIO; + goto exit; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_write: (%d,%p) port is closed\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); - return -EBADF; + ret = -EBADF; + goto exit; } count = gs_buf_put(port->port_write_buf, buf, count); spin_unlock_irqrestore(&port->port_lock, flags); - if (from_user) - up(&gs_tmp_buf_sem); - gs_send(gs_device); gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty, count); return count; + +exit: + spin_unlock_irqrestore(&port->port_lock, flags); + return ret; } /* @@ -996,19 +1063,18 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch) if (port->port_dev == NULL) { printk(KERN_ERR "gs_put_char: (%d,%p) port is not connected\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - return; + goto exit; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - return; + goto exit; } gs_buf_put(port->port_write_buf, &ch, 1); +exit: spin_unlock_irqrestore(&port->port_lock, flags); } @@ -1033,20 +1099,23 @@ static void gs_flush_chars(struct tty_struct *tty) printk(KERN_ERR "gs_flush_chars: (%d,%p) port is not connected\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - return; + goto exit; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n", port->port_num, tty); - spin_unlock_irqrestore(&port->port_lock, flags); - return; + goto exit; } spin_unlock_irqrestore(&port->port_lock, flags); gs_send(gs_device); + + return; + +exit: + spin_unlock_irqrestore(&port->port_lock, flags); } /* @@ -1243,17 +1312,16 @@ static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size) if (len < size) size = len; - if (size == 0) { - spin_unlock(&port->port_lock); - return 0; - } + if (size == 0) + goto exit; size = gs_buf_get(port->port_write_buf, packet, size); - wake_up_interruptible(&port->port_tty->write_wait); + if (port->port_tty) + wake_up_interruptible(&port->port_tty->write_wait); +exit: spin_unlock(&port->port_lock); - return size; } @@ -1274,6 +1342,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size) { unsigned int len; struct gs_port *port; + int ret; /* TEMPORARY -- only port 0 is supported right now */ port = dev->dev_port[0]; @@ -1286,18 +1355,25 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size) spin_lock(&port->port_lock); + if (port->port_open_count == 0) { + printk(KERN_ERR "gs_recv_packet: port=%d, port is closed\n", + port->port_num); + ret = -EIO; + goto exit; + } + if (port->port_tty == NULL) { printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n", port->port_num); - spin_unlock(&port->port_lock); - return -EIO; + ret = -EIO; + goto exit; } if (port->port_tty->magic != TTY_MAGIC) { printk(KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n", port->port_num); - spin_unlock(&port->port_lock); - return -EIO; + ret = -EIO; + goto exit; } len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count); @@ -1312,9 +1388,11 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size) wake_up_interruptible(&port->port_tty->read_wait); } - spin_unlock(&port->port_lock); + ret = 0; - return 0; +exit: + spin_unlock(&port->port_lock); + return ret; } /* @@ -1416,18 +1494,116 @@ requeue: static int gs_bind(struct usb_gadget *gadget) { int ret; + struct usb_ep *ep; struct gs_dev *dev; + /* device specific */ + if (gadget_is_net2280(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0001); + } else if (gadget_is_pxa(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0002); + } else if (gadget_is_sh(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0003); + /* sh doesn't support multiple interfaces or configs */ + use_acm = 0; + } else if (gadget_is_sa1100(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0004); + /* sa1100 doesn't support necessary endpoints */ + use_acm = 0; + } else if (gadget_is_goku(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0005); + } else if (gadget_is_mq11xx(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0006); + } else if (gadget_is_omap(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0007); + } else if (gadget_is_lh7a40x(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0008); + } else if (gadget_is_n9604(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0009); + } else if (gadget_is_pxa27x(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0011); + } else { + printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n", + gadget->name); + /* unrecognized, but safe unless bulk is REALLY quirky */ + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); + } + + usb_ep_autoconfig_reset(gadget); + + ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); + if (!ep) + goto autoconf_fail; + EP_IN_NAME = ep->name; + ep->driver_data = ep; /* claim the endpoint */ + + ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); + if (!ep) + goto autoconf_fail; + EP_OUT_NAME = ep->name; + ep->driver_data = ep; /* claim the endpoint */ + + if (use_acm) { + ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); + if (!ep) { + printk(KERN_ERR "gs_bind: cannot run ACM on %s\n", gadget->name); + goto autoconf_fail; + } + gs_device_desc.idProduct = __constant_cpu_to_le16( + GS_CDC_PRODUCT_ID), + EP_NOTIFY_NAME = ep->name; + ep->driver_data = ep; /* claim the endpoint */ + } + + gs_device_desc.bDeviceClass = use_acm + ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; + gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; + +#ifdef CONFIG_USB_GADGET_DUALSPEED + gs_qualifier_desc.bDeviceClass = use_acm + ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC; + /* assume ep0 uses the same packet size for both speeds */ + gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0; + /* assume endpoints are dual-speed */ + gs_highspeed_notify_desc.bEndpointAddress = + gs_fullspeed_notify_desc.bEndpointAddress; + gs_highspeed_in_desc.bEndpointAddress = + gs_fullspeed_in_desc.bEndpointAddress; + gs_highspeed_out_desc.bEndpointAddress = + gs_fullspeed_out_desc.bEndpointAddress; +#endif /* CONFIG_USB_GADGET_DUALSPEED */ + + usb_gadget_set_selfpowered(gadget); + + if (gadget->is_otg) { + gs_otg_descriptor.bmAttributes |= USB_OTG_HNP, + gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL); if (dev == NULL) return -ENOMEM; - set_gadget_data(gadget, dev); + snprintf(manufacturer, sizeof(manufacturer), + UTS_SYSNAME " " UTS_RELEASE " with %s", gadget->name); memset(dev, 0, sizeof(struct gs_dev)); dev->dev_gadget = gadget; spin_lock_init(&dev->dev_lock); INIT_LIST_HEAD(&dev->dev_req_list); + set_gadget_data(gadget, dev); if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) { printk(KERN_ERR "gs_bind: cannot allocate ports\n"); @@ -1450,6 +1626,10 @@ static int gs_bind(struct usb_gadget *gadget) GS_LONG_NAME, GS_VERSION_STR); return 0; + +autoconf_fail: + printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name); + return -ENODEV; } /* @@ -1466,8 +1646,10 @@ static void gs_unbind(struct usb_gadget *gadget) /* read/write requests already freed, only control request remains */ if (dev != NULL) { - if (dev->dev_ctrl_req != NULL) + if (dev->dev_ctrl_req != NULL) { gs_free_req(gadget->ep0, dev->dev_ctrl_req); + dev->dev_ctrl_req = NULL; + } gs_free_ports(dev); kfree(dev); set_gadget_data(gadget, NULL); @@ -1486,10 +1668,51 @@ static void gs_unbind(struct usb_gadget *gadget) * Returns the size of the data sent to the host, or a negative * error number. */ -static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +static int gs_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + int ret = -EOPNOTSUPP; + struct gs_dev *dev = get_gadget_data(gadget); + struct usb_request *req = dev->dev_ctrl_req; + + switch (ctrl->bRequestType & USB_TYPE_MASK) { + case USB_TYPE_STANDARD: + ret = gs_setup_standard(gadget,ctrl); + break; + + case USB_TYPE_CLASS: + ret = gs_setup_class(gadget,ctrl); + break; + + default: + printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", + ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, + ctrl->wIndex, ctrl->wLength); + break; + } + + /* respond with data transfer before status phase? */ + if (ret >= 0) { + req->length = ret; + req->zero = ret < ctrl->wLength + && (ret % gadget->ep0->maxpacket) == 0; + ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + if (ret < 0) { + printk(KERN_ERR "gs_setup: cannot queue response, ret=%d\n", + ret); + req->status = 0; + gs_setup_complete(gadget->ep0, req); + } + } + + /* device either stalls (ret < 0) or reports success */ + return ret; +} + +static int gs_setup_standard(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) { int ret = -EOPNOTSUPP; - unsigned int sv_config; struct gs_dev *dev = get_gadget_data(gadget); struct usb_request *req = dev->dev_ctrl_req; @@ -1505,18 +1728,24 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr memcpy(req->buf, &gs_device_desc, ret); break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: + if (!gadget->is_dualspeed) + break; ret = min(ctrl->wLength, (u16)sizeof(struct usb_qualifier_descriptor)); memcpy(req->buf, &gs_qualifier_desc, ret); break; case USB_DT_OTHER_SPEED_CONFIG: -#endif /* HIGHSPEED */ + if (!gadget->is_dualspeed) + break; + /* fall through */ +#endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: - ret = gs_build_config_desc(req->buf, gadget->speed, - ctrl->wValue >> 8, ctrl->wValue & 0xff); + ret = gs_build_config_buf(req->buf, gadget->speed, + ctrl->wValue >> 8, ctrl->wValue & 0xff, + gadget->is_otg); if (ret >= 0) ret = min(ctrl->wLength, (u16)ret); break; @@ -1547,59 +1776,106 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr break; case USB_REQ_SET_INTERFACE: - if (ctrl->bRequestType != USB_RECIP_INTERFACE) + if (ctrl->bRequestType != USB_RECIP_INTERFACE + || !dev->dev_config || ctrl->wIndex >= GS_MAX_NUM_INTERFACES) break; - spin_lock(&dev->dev_lock); if (dev->dev_config == GS_BULK_CONFIG_ID - && ctrl->wIndex == GS_INTERFACE_ID - && ctrl->wValue == GS_ALT_INTERFACE_ID) { - sv_config = dev->dev_config; - /* since there is only one interface, setting the */ - /* interface is equivalent to setting the config */ - gs_reset_config(dev); - gs_set_config(dev, sv_config); - ret = 0; + && ctrl->wIndex != GS_BULK_INTERFACE_ID) + break; + /* no alternate interface settings */ + if (ctrl->wValue != 0) + break; + spin_lock(&dev->dev_lock); + /* PXA hardware partially handles SET_INTERFACE; + * we need to kluge around that interference. */ + if (gadget_is_pxa(gadget)) { + ret = gs_set_config(dev, use_acm ? + GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID); + goto set_interface_done; } + if (dev->dev_config != GS_BULK_CONFIG_ID + && ctrl->wIndex == GS_CONTROL_INTERFACE_ID) { + if (dev->dev_notify_ep) { + usb_ep_disable(dev->dev_notify_ep); + usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc); + } + } else { + usb_ep_disable(dev->dev_in_ep); + usb_ep_disable(dev->dev_out_ep); + usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc); + usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc); + } + ret = 0; +set_interface_done: spin_unlock(&dev->dev_lock); break; case USB_REQ_GET_INTERFACE: - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) + if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) + || dev->dev_config == GS_NO_CONFIG_ID) break; - if (dev->dev_config == GS_NO_CONFIG_ID) - break; - if (ctrl->wIndex != GS_INTERFACE_ID) { + if (ctrl->wIndex >= GS_MAX_NUM_INTERFACES + || (dev->dev_config == GS_BULK_CONFIG_ID + && ctrl->wIndex != GS_BULK_INTERFACE_ID)) { ret = -EDOM; break; } - *(u8 *)req->buf = GS_ALT_INTERFACE_ID; + /* no alternate interface settings */ + *(u8 *)req->buf = 0; ret = min(ctrl->wLength, (u16)1); break; default: - printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", + printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, ctrl->wLength); break; - } - /* respond with data transfer before status phase? */ - if (ret >= 0) { - req->length = ret; - req->zero = ret < ctrl->wLength - && (ret % gadget->ep0->maxpacket) == 0; - ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (ret < 0) { - printk(KERN_ERR - "gs_setup: cannot queue response, ret=%d\n", - ret); - req->status = 0; - gs_setup_complete(gadget->ep0, req); + return ret; +} + +static int gs_setup_class(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + int ret = -EOPNOTSUPP; + struct gs_dev *dev = get_gadget_data(gadget); + struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ + struct usb_request *req = dev->dev_ctrl_req; + + switch (ctrl->bRequest) { + case USB_CDC_REQ_SET_LINE_CODING: + ret = min(ctrl->wLength, + (u16)sizeof(struct usb_cdc_line_coding)); + if (port) { + spin_lock(&port->port_lock); + memcpy(&port->port_line_coding, req->buf, ret); + spin_unlock(&port->port_lock); + } + break; + + case USB_CDC_REQ_GET_LINE_CODING: + port = dev->dev_port[0]; /* ACM only has one port */ + ret = min(ctrl->wLength, + (u16)sizeof(struct usb_cdc_line_coding)); + if (port) { + spin_lock(&port->port_lock); + memcpy(req->buf, &port->port_line_coding, ret); + spin_unlock(&port->port_lock); } + break; + + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + ret = 0; + break; + + default: + printk(KERN_ERR "gs_setup: unknown class request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", + ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, + ctrl->wIndex, ctrl->wLength); + break; } - /* device either stalls (ret < 0) or reports success */ return ret; } @@ -1658,6 +1934,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) int ret = 0; struct usb_gadget *gadget = dev->dev_gadget; struct usb_ep *ep; + struct usb_endpoint_descriptor *ep_desc; struct usb_request *req; struct gs_req_entry *req_entry; @@ -1671,53 +1948,90 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) gs_reset_config(dev); - if (config == GS_NO_CONFIG_ID) + switch (config) { + case GS_NO_CONFIG_ID: return 0; - - if (config != GS_BULK_CONFIG_ID) + case GS_BULK_CONFIG_ID: + if (use_acm) + return -EINVAL; + /* device specific optimizations */ + if (gadget_is_net2280(gadget)) + net2280_set_fifo_mode(gadget, 1); + break; + case GS_ACM_CONFIG_ID: + if (!use_acm) + return -EINVAL; + /* device specific optimizations */ + if (gadget_is_net2280(gadget)) + net2280_set_fifo_mode(gadget, 1); + break; + default: return -EINVAL; + } - hw_optimize(gadget); + dev->dev_config = config; gadget_for_each_ep(ep, gadget) { - if (strcmp(ep->name, EP_IN_NAME) == 0) { - ret = usb_ep_enable(ep, - gadget->speed == USB_SPEED_HIGH ? - &gs_highspeed_in_desc : &gs_fullspeed_in_desc); + if (EP_NOTIFY_NAME + && strcmp(ep->name, EP_NOTIFY_NAME) == 0) { + ep_desc = GS_SPEED_SELECT( + gadget->speed == USB_SPEED_HIGH, + &gs_highspeed_notify_desc, + &gs_fullspeed_notify_desc); + ret = usb_ep_enable(ep,ep_desc); + if (ret == 0) { + ep->driver_data = dev; + dev->dev_notify_ep = ep; + dev->dev_notify_ep_desc = ep_desc; + } else { + printk(KERN_ERR "gs_set_config: cannot enable notify endpoint %s, ret=%d\n", + ep->name, ret); + goto exit_reset_config; + } + } + + else if (strcmp(ep->name, EP_IN_NAME) == 0) { + ep_desc = GS_SPEED_SELECT( + gadget->speed == USB_SPEED_HIGH, + &gs_highspeed_in_desc, + &gs_fullspeed_in_desc); + ret = usb_ep_enable(ep,ep_desc); if (ret == 0) { ep->driver_data = dev; dev->dev_in_ep = ep; + dev->dev_in_ep_desc = ep_desc; } else { printk(KERN_ERR "gs_set_config: cannot enable in endpoint %s, ret=%d\n", ep->name, ret); - gs_reset_config(dev); - return ret; + goto exit_reset_config; } } else if (strcmp(ep->name, EP_OUT_NAME) == 0) { - ret = usb_ep_enable(ep, - gadget->speed == USB_SPEED_HIGH ? - &gs_highspeed_out_desc : + ep_desc = GS_SPEED_SELECT( + gadget->speed == USB_SPEED_HIGH, + &gs_highspeed_out_desc, &gs_fullspeed_out_desc); + ret = usb_ep_enable(ep,ep_desc); if (ret == 0) { ep->driver_data = dev; dev->dev_out_ep = ep; + dev->dev_out_ep_desc = ep_desc; } else { printk(KERN_ERR "gs_set_config: cannot enable out endpoint %s, ret=%d\n", ep->name, ret); - gs_reset_config(dev); - return ret; + goto exit_reset_config; } } } - if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL) { - gs_reset_config(dev); + if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL + || (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) { printk(KERN_ERR "gs_set_config: cannot find endpoints\n"); - return -ENODEV; + ret = -ENODEV; + goto exit_reset_config; } /* allocate and queue read requests */ @@ -1730,10 +2044,9 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) ret); } } else { - gs_reset_config(dev); - printk(KERN_ERR - "gs_set_config: cannot allocate read requests\n"); - return -ENOMEM; + printk(KERN_ERR "gs_set_config: cannot allocate read requests\n"); + ret = -ENOMEM; + goto exit_reset_config; } } @@ -1744,20 +2057,22 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) req_entry->re_req->complete = gs_write_complete; list_add(&req_entry->re_entry, &dev->dev_req_list); } else { - gs_reset_config(dev); - printk(KERN_ERR - "gs_set_config: cannot allocate write requests\n"); - return -ENOMEM; + printk(KERN_ERR "gs_set_config: cannot allocate write requests\n"); + ret = -ENOMEM; + goto exit_reset_config; } } - dev->dev_config = config; - - printk(KERN_INFO "gs_set_config: %s configured for %s speed\n", + printk(KERN_INFO "gs_set_config: %s configured, %s speed %s config\n", GS_LONG_NAME, - gadget->speed == USB_SPEED_HIGH ? "high" : "full"); + gadget->speed == USB_SPEED_HIGH ? "high" : "full", + config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM"); return 0; + +exit_reset_config: + gs_reset_config(dev); + return ret; } /* @@ -1794,6 +2109,10 @@ static void gs_reset_config(struct gs_dev *dev) /* disable endpoints, forcing completion of pending i/o; */ /* completion handlers free their requests in this case */ + if (dev->dev_notify_ep) { + usb_ep_disable(dev->dev_notify_ep); + dev->dev_notify_ep = NULL; + } if (dev->dev_in_ep) { usb_ep_disable(dev->dev_in_ep); dev->dev_in_ep = NULL; @@ -1805,41 +2124,48 @@ static void gs_reset_config(struct gs_dev *dev) } /* - * gs_build_config_desc + * gs_build_config_buf * - * Builds a config descriptor in the given buffer and returns the + * Builds the config descriptors in the given buffer and returns the * length, or a negative error number. */ -static int gs_build_config_desc(u8 *buf, enum usb_device_speed speed, u8 type, unsigned int index) +static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, + u8 type, unsigned int index, int is_otg) { + int len; int high_speed; - int len = USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE - + GS_NUM_ENDPOINTS * USB_DT_ENDPOINT_SIZE; + const struct usb_config_descriptor *config_desc; + const struct usb_descriptor_header **function; - /* only one config */ - if (index != 0) + if (index >= gs_device_desc.bNumConfigurations) return -EINVAL; - memcpy(buf, &gs_config_desc, USB_DT_CONFIG_SIZE); - ((struct usb_config_descriptor *)buf)->bDescriptorType = type; - ((struct usb_config_descriptor *)buf)->wTotalLength = __constant_cpu_to_le16(len); - buf += USB_DT_CONFIG_SIZE; - - memcpy(buf, &gs_interface_desc, USB_DT_INTERFACE_SIZE); - buf += USB_DT_INTERFACE_SIZE; - /* other speed switches high and full speed */ high_speed = (speed == USB_SPEED_HIGH); if (type == USB_DT_OTHER_SPEED_CONFIG) high_speed = !high_speed; - memcpy(buf, - high_speed ? &gs_highspeed_in_desc : &gs_fullspeed_in_desc, - USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; - memcpy(buf, - high_speed ? &gs_highspeed_out_desc : &gs_fullspeed_out_desc, - USB_DT_ENDPOINT_SIZE); + if (use_acm) { + config_desc = &gs_acm_config_desc; + function = GS_SPEED_SELECT(high_speed, + gs_acm_highspeed_function, + gs_acm_fullspeed_function); + } else { + config_desc = &gs_bulk_config_desc; + function = GS_SPEED_SELECT(high_speed, + gs_bulk_highspeed_function, + gs_bulk_fullspeed_function); + } + + /* for now, don't advertise srp-only devices */ + if (!is_otg) + function++; + + len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function); + if (len < 0) + return len; + + ((struct usb_config_descriptor *)buf)->bDescriptorType = type; return len; } @@ -1861,8 +2187,7 @@ static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int if (req != NULL) { req->length = len; - req->buf = usb_ep_alloc_buffer(ep, len, &req->dma, - kmalloc_flags); + req->buf = kmalloc(len, kmalloc_flags); if (req->buf == NULL) { usb_ep_free_request(ep, req); return NULL; @@ -1880,9 +2205,7 @@ static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int static void gs_free_req(struct usb_ep *ep, struct usb_request *req) { if (ep != NULL && req != NULL) { - if (req->buf != NULL) - usb_ep_free_buffer(ep, req->buf, req->dma, - req->length); + kfree(req->buf); usb_ep_free_request(ep, req); } } @@ -1949,6 +2272,10 @@ static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags) memset(port, 0, sizeof(struct gs_port)); port->port_dev = dev; port->port_num = i; + port->port_line_coding.dwDTERate = GS_DEFAULT_DTE_RATE; + port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT; + port->port_line_coding.bParityType = GS_DEFAULT_PARITY; + port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS; spin_lock_init(&port->port_lock); init_waitqueue_head(&port->port_write_wait); @@ -1991,8 +2318,10 @@ static void gs_free_ports(struct gs_dev *dev) if (port->port_open_count > 0 || port->port_in_use) { port->port_dev = NULL; wake_up_interruptible(&port->port_write_wait); - wake_up_interruptible(&port->port_tty->read_wait); - wake_up_interruptible(&port->port_tty->write_wait); + if (port->port_tty) { + wake_up_interruptible(&port->port_tty->read_wait); + wake_up_interruptible(&port->port_tty->write_wait); + } } else { kfree(port); } diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 4fa5e1c8f..c439eb07f 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -396,10 +396,10 @@ static const struct usb_descriptor_header *hs_loopback_function [] = { #endif /* !CONFIG_USB_GADGET_DUALSPEED */ -static char manufacturer [40]; +static char manufacturer [50]; static char serial [40]; -/* static strings, in iso 8859/1 */ +/* static strings, in UTF-8 */ static struct usb_string strings [] = { { STRING_MANUFACTURER, manufacturer, }, { STRING_PRODUCT, longname, }, @@ -960,7 +960,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) case USB_DT_STRING: /* wIndex == language code. * this driver only handles one language, you can - * add others even if they don't use iso8859/1 + * add string tables for other languages, using + * any UTF-8 characters */ value = usb_gadget_get_string (&stringtab, ctrl->wValue & 0xff, req->buf); @@ -1185,6 +1186,12 @@ autoconf_fail: device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207); } else if (gadget_is_omap (gadget)) { device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208); + } else if (gadget_is_lh7a40x(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209); + } else if (gadget_is_n9604(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210); + } else if (gadget_is_pxa27x(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); } else { /* gadget zero is so simple (for now, no altsettings) that * it SHOULD NOT have problems with bulk-capable hardware. @@ -1236,6 +1243,12 @@ autoconf_fail: loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } + if (gadget->is_otg) { + otg_descriptor.bmAttributes |= USB_OTG_HNP, + source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + usb_gadget_set_selfpowered (gadget); init_timer (&dev->resume); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 946898ac4..256787e33 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -1,3 +1,21 @@ +# Host-side USB depends on having a host controller +# NOTE: dummy_hcd is always an option, but it's ignored here ... +# NOTE: SL-811 option should be board-specific ... +config USB_ARCH_HAS_HCD + boolean + default y if USB_ARCH_HAS_OHCI + default y if ARM # SL-811 + default PCI + +# many non-PCI hcds implement OHCI +config USB_ARCH_HAS_OHCI + boolean + default y if SA1111 + default y if ARCH_OMAP + default y if ARCH_LH7A404 + default y if PXA27x + default PCI + # # USB Host Controller Drivers # @@ -6,7 +24,7 @@ comment "USB Host Controller Drivers" config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB + depends on USB && PCI ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. @@ -51,7 +69,8 @@ config USB_EHCI_ROOT_HUB_TT config USB_OHCI_HCD tristate "OHCI HCD support" - depends on USB + depends on USB && USB_ARCH_HAS_OHCI + select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing USB 1.1 host controller hardware. It does more in hardware than Intel's @@ -67,7 +86,7 @@ config USB_OHCI_HCD config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" - depends on USB + depends on USB && PCI ---help--- The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB @@ -81,14 +100,16 @@ config USB_UHCI_HCD To compile this driver as a module, choose M here: the module will be called uhci-hcd. -config USB_SL811HS - tristate "SL811HS support" - depends on ARM && USB +config USB_SL811_HCD + tristate "SL811HS HCD support" + depends on USB + default N help - Say Y here if you have a SL811HS USB host controller in your system. - - If you do not know what this is, please say N. + The SL811HS is a single-port USB controller that supports either + host side or peripheral side roles. Enable this option if your + board has this chip, and you want to use it as a host controller. + If unsure, say N. To compile this driver as a module, choose M here: the - module will be called hc_sl811. + module will be called sl811-hcd. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index b1146b80c..a574ca06c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -6,5 +6,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o - -obj-$(CONFIG_USB_SL811HS) += hc_sl811.o +obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o +obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index ad32ba159..b83e753c4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -119,16 +119,16 @@ static void __attribute__((__unused__)) dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) { ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, - cpu_to_le32p (&qtd->hw_next), - cpu_to_le32p (&qtd->hw_alt_next), - cpu_to_le32p (&qtd->hw_token), - cpu_to_le32p (&qtd->hw_buf [0])); + le32_to_cpup (&qtd->hw_next), + le32_to_cpup (&qtd->hw_alt_next), + le32_to_cpup (&qtd->hw_token), + le32_to_cpup (&qtd->hw_buf [0])); if (qtd->hw_buf [1]) ehci_dbg (ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", - cpu_to_le32p (&qtd->hw_buf [1]), - cpu_to_le32p (&qtd->hw_buf [2]), - cpu_to_le32p (&qtd->hw_buf [3]), - cpu_to_le32p (&qtd->hw_buf [4])); + le32_to_cpup (&qtd->hw_buf [1]), + le32_to_cpup (&qtd->hw_buf [2]), + le32_to_cpup (&qtd->hw_buf [3]), + le32_to_cpup (&qtd->hw_buf [4])); } static void __attribute__((__unused__)) @@ -185,7 +185,7 @@ dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) } static int __attribute__((__unused__)) -dbg_status_buf (char *buf, unsigned len, char *label, u32 status) +dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) { return scnprintf (buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", @@ -204,7 +204,7 @@ dbg_status_buf (char *buf, unsigned len, char *label, u32 status) } static int __attribute__((__unused__)) -dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) +dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) { return scnprintf (buf, len, "%s%sintrenable %02x%s%s%s%s%s%s", @@ -221,7 +221,8 @@ dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) static const char *const fls_strings [] = { "1024", "512", "256", "??" }; -static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command) +static int +dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) { return scnprintf (buf, len, "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", @@ -240,7 +241,7 @@ static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command) } static int -dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) +dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) { char *sig; @@ -276,19 +277,19 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {} static inline int __attribute__((__unused__)) -dbg_status_buf (char *buf, unsigned len, char *label, u32 status) +dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) { return 0; } static inline int __attribute__((__unused__)) -dbg_command_buf (char *buf, unsigned len, char *label, u32 command) +dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) { return 0; } static inline int __attribute__((__unused__)) -dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) +dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) { return 0; } static inline int __attribute__((__unused__)) -dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) +dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) { return 0; } #endif /* DEBUG */ @@ -331,14 +332,14 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { } default: tmp = '?'; break; \ }; tmp; }) -static inline char token_mark (u32 token) +static inline char token_mark (__le32 token) { - token = le32_to_cpu (token); - if (token & QTD_STS_ACTIVE) + __u32 v = le32_to_cpu (token); + if (v & QTD_STS_ACTIVE) return '*'; - if (token & QTD_STS_HALT) + if (v & QTD_STS_HALT) return '-'; - if (!IS_SHORT_READ (token)) + if (!IS_SHORT_READ (v)) return ' '; /* tries to advance through hw_alt_next */ return '/'; @@ -371,25 +372,25 @@ static void qh_lines ( mark = '.'; /* use hw_qtd_next */ /* else alt_next points to some other qtd */ } - scratch = cpu_to_le32p (&qh->hw_info1); - hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0; + scratch = le32_to_cpup (&qh->hw_info1); + hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0; temp = scnprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", qh, scratch & 0x007f, speed_char (scratch), (scratch >> 8) & 0x000f, - scratch, cpu_to_le32p (&qh->hw_info2), - cpu_to_le32p (&qh->hw_token), mark, + scratch, le32_to_cpup (&qh->hw_info2), + le32_to_cpup (&qh->hw_token), mark, (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token) ? "data1" : "data0", - (cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f); + (le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f); size -= temp; next += temp; /* hc may be modifying the list as we read it ... */ list_for_each (entry, &qh->qtd_list) { td = list_entry (entry, struct ehci_qtd, qtd_list); - scratch = cpu_to_le32p (&td->hw_token); + scratch = le32_to_cpup (&td->hw_token); mark = ' '; if (hw_curr == td->qtd_dma) mark = '*'; @@ -488,7 +489,8 @@ show_periodic (struct class_device *class_dev, char *buf) union ehci_shadow p, *seen; unsigned temp, size, seen_count; char *next; - unsigned i, tag; + unsigned i; + __le32 tag; if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) return 0; @@ -541,7 +543,7 @@ show_periodic (struct class_device *class_dev, char *buf) } /* show more info the first time around */ if (temp == seen_count && p.ptr) { - u32 scratch = cpu_to_le32p ( + u32 scratch = le32_to_cpup ( &p.qh->hw_info1); struct ehci_qtd *qtd; char *type = ""; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d3bb7b508..0b8d4dc21 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -97,7 +97,7 @@ * 2001-June Works with usb-storage and NEC EHCI on 2.4 */ -#define DRIVER_VERSION "2004-May-10" +#define DRIVER_VERSION "26 Oct 2004" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -155,7 +155,7 @@ MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); * before driver shutdown. But it also seems to be caused by bugs in cardbus * bridge shutdown: shutting down the bridge before the devices using it. */ -static int handshake (u32 *ptr, u32 mask, u32 done, int usec) +static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; @@ -172,13 +172,6 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec) return -ETIMEDOUT; } -/* - * hc states include: unknown, halted, ready, running - * transitional states are messy just now - * trying to avoid "running" unless urbs are active - * a "ready" hc can be finishing prefetched work - */ - /* force HC to halt state from unknown (EHCI spec section 2.3) */ static int ehci_halt (struct ehci_hcd *ehci) { @@ -207,7 +200,7 @@ static int ehci_reset (struct ehci_hcd *ehci) } /* idle the controller (from running) */ -static void ehci_ready (struct ehci_hcd *ehci) +static void ehci_quiesce (struct ehci_hcd *ehci) { u32 temp; @@ -217,11 +210,8 @@ static void ehci_ready (struct ehci_hcd *ehci) #endif /* wait for any schedule enables/disables to take effect */ - temp = 0; - if (ehci->async->qh_next.qh) - temp = STS_ASS; - if (ehci->next_uframe != -1) - temp |= STS_PSS; + temp = readl (&ehci->regs->command) << 10; + temp &= STS_ASS | STS_PSS; if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125) != 0) { ehci->hcd.state = USB_STATE_HALT; @@ -289,7 +279,7 @@ static void ehci_watchdog (unsigned long param) static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) { if (cap & (1 << 16)) { - int msec = 500; + int msec = 5000; struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller); /* request handoff to OS */ @@ -305,7 +295,10 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) if (cap & (1 << 16)) { ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", where, cap); - return 1; + // some BIOS versions seem buggy... + // return 1; + ehci_warn (ehci, "continuing after BIOS bug...\n"); + return 0; } ehci_dbg (ehci, "BIOS handoff succeeded\n"); } @@ -337,17 +330,25 @@ static int ehci_hc_reset (struct usb_hcd *hcd) spin_lock_init (&ehci->lock); - ehci->caps = (struct ehci_caps *) hcd->regs; - ehci->regs = (struct ehci_regs *) (hcd->regs + - HC_LENGTH (readl (&ehci->caps->hc_capbase))); + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); dbg_hcs_params (ehci, "reset"); dbg_hcc_params (ehci, "reset"); #ifdef CONFIG_PCI /* EHCI 0.96 and later may have "extended capabilities" */ - if (hcd->self.controller->bus == &pci_bus_type) + if (hcd->self.controller->bus == &pci_bus_type) { + struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller); + + /* AMD8111 EHCI doesn't work, according to AMD errata */ + if ((pdev->vendor == PCI_VENDOR_ID_AMD) + && (pdev->device == 0x7463)) { + ehci_info (ehci, "ignoring AMD8111 (errata)\n"); + return -EIO; + } + temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); - else + } else temp = 0; while (temp && count--) { u32 cap; @@ -360,10 +361,6 @@ static int ehci_hc_reset (struct usb_hcd *hcd) if (bios_handoff (ehci, temp, cap) != 0) return -EOPNOTSUPP; break; - case 0x0a: /* appendix C */ - ehci_dbg (ehci, "debug registers, BAR %d offset %d\n", - (cap >> 29) & 0x07, (cap >> 16) & 0x0fff); - break; case 0: /* illegal reserved capability */ ehci_warn (ehci, "illegal capability!\n"); cap = 0; @@ -382,6 +379,14 @@ static int ehci_hc_reset (struct usb_hcd *hcd) /* cache this readonly data; minimize PCI reads */ ehci->hcs_params = readl (&ehci->caps->hcs_params); + /* at least the Genesys GL880S needs fixup here */ + temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); + temp &= 0x0f; + if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { + temp |= (ehci->hcs_params & ~0xf); + ehci->hcs_params = temp; + } + /* force HC to halt state */ return ehci_halt (ehci); } @@ -395,17 +400,22 @@ static int ehci_start (struct usb_hcd *hcd) int retval; u32 hcc_params; u8 sbrn = 0; - - init_timer (&ehci->watchdog); - ehci->watchdog.function = ehci_watchdog; - ehci->watchdog.data = (unsigned long) ehci; + int first; + + /* skip some things on restart paths */ + first = (ehci->watchdog.data == 0); + if (first) { + init_timer (&ehci->watchdog); + ehci->watchdog.function = ehci_watchdog; + ehci->watchdog.data = (unsigned long) ehci; + } /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; - if ((retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0) + if (first && (retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ @@ -416,6 +426,7 @@ static int ehci_start (struct usb_hcd *hcd) ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params); ehci->reclaim = NULL; + ehci->reclaim_ready = 0; ehci->next_uframe = -1; /* controller state: unknown --> reset */ @@ -462,13 +473,15 @@ static int ehci_start (struct usb_hcd *hcd) * its dummy is used in hw_alt_next of many tds, to prevent the qh * from automatically advancing to the next td after short reads. */ - ehci->async->qh_next.qh = NULL; - ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); - ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); - ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); - ehci->async->hw_qtd_next = EHCI_LIST_END; - ehci->async->qh_state = QH_STATE_LINKED; - ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma); + if (first) { + ehci->async->qh_next.qh = NULL; + ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); + ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); + ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); + ehci->async->hw_qtd_next = EHCI_LIST_END; + ehci->async->qh_state = QH_STATE_LINKED; + ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma); + } writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); /* @@ -520,12 +533,14 @@ static int ehci_start (struct usb_hcd *hcd) /* wire up the root hub */ bus = hcd_to_bus (hcd); - udev = usb_alloc_dev (NULL, bus, 0); + udev = first ? usb_alloc_dev (NULL, bus, 0) : bus->root_hub; if (!udev) { done2: ehci_mem_cleanup (ehci); return -ENOMEM; } + udev->speed = USB_SPEED_HIGH; + udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED; /* * Start, enabling full USB 2.0 functionality ... usb 1.1 devices @@ -533,8 +548,10 @@ done2: * involved with the root hub. (Except where one is integrated, * and there's no companion controller unless maybe for USB OTG.) */ - ehci->reboot_notifier.notifier_call = ehci_reboot; - register_reboot_notifier (&ehci->reboot_notifier); + if (first) { + ehci->reboot_notifier.notifier_call = ehci_reboot; + register_reboot_notifier (&ehci->reboot_notifier); + } ehci->hcd.state = USB_STATE_RUNNING; writel (FLAG_CF, &ehci->regs->configured_flag); @@ -542,21 +559,23 @@ done2: temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, - "USB %x.%x enabled, EHCI %x.%02x, driver %s\n", + "USB %x.%x %s, EHCI %x.%02x, driver %s\n", ((sbrn & 0xf0)>>4), (sbrn & 0x0f), + first ? "initialized" : "restarted", temp >> 8, temp & 0xff, DRIVER_VERSION); /* * From here on, khubd concurrently accesses the root * hub; drivers will be talking to enumerated devices. + * (On restart paths, khubd already knows about the root + * hub and could find work as soon as we wrote FLAG_CF.) * * Before this point the HC was idle/ready. After, khubd * and device drivers may start it running. */ - udev->speed = USB_SPEED_HIGH; - if (hcd_register_root (udev, hcd) != 0) { + if (first && hcd_register_root (udev, hcd) != 0) { if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); + ehci_quiesce (ehci); ehci_reset (ehci); usb_put_dev (udev); retval = -ENODEV; @@ -565,7 +584,8 @@ done2: writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ - create_debug_files (ehci); + if (first) + create_debug_files (ehci); return 0; } @@ -579,24 +599,23 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_dbg (ehci, "stop\n"); - /* no more interrupts ... */ - if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); - if (in_interrupt ()) { /* must not happen!! */ - ehci_err (ehci, "stopped in_interrupt!\n"); - return; - } - del_timer_sync (&ehci->watchdog); - /* Turn off port power on all root hub ports. */ rh_ports = HCS_N_PORTS (ehci->hcs_params); - for (port = 1; port <= rh_ports; port++) { - ehci_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, + for (port = 1; port <= rh_ports; port++) + (void) ehci_hub_control(hcd, + ClearPortFeature, USB_PORT_FEAT_POWER, port, NULL, 0); - } + + /* no more interrupts ... */ + del_timer_sync (&ehci->watchdog); + + spin_lock_irq(&ehci->lock); + if (HCD_IS_RUNNING (ehci->hcd.state)) + ehci_quiesce (ehci); ehci_reset (ehci); writel (0, &ehci->regs->intr_enable); + spin_unlock_irq(&ehci->lock); /* let companion controllers work when we aren't */ writel (0, &ehci->regs->configured_flag); @@ -634,7 +653,8 @@ static int ehci_get_frame (struct usb_hcd *hcd) /* suspend/resume, section 4.3 */ -/* These routines rely on PCI to handle powerdown and wakeup, and +/* These routines rely on the bus (pci, platform, etc) + * to handle powerdown and wakeup, and currently also on * transceivers that don't need any software attention to set up * the right sort of wakeup. */ @@ -643,17 +663,19 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - while (time_before (jiffies, ehci->next_statechange)) + if (time_before (jiffies, ehci->next_statechange)) msleep (100); #ifdef CONFIG_USB_SUSPEND (void) usb_suspend_device (hcd->self.root_hub, state); #else - /* FIXME lock root hub */ + usb_lock_device (hcd->self.root_hub); (void) ehci_hub_suspend (hcd); + usb_unlock_device (hcd->self.root_hub); #endif // save (PCI) FLADJ in case of Vaux power loss + // ... we'd only use it to handle clock skew return 0; } @@ -661,21 +683,67 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) static int ehci_resume (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int retval; + unsigned port; + struct usb_device *root = hcd->self.root_hub; + int retval = -EINVAL; + int powerup = 0; // maybe restore (PCI) FLADJ - while (time_before (jiffies, ehci->next_statechange)) + if (time_before (jiffies, ehci->next_statechange)) msleep (100); -#ifdef CONFIG_USB_SUSPEND - retval = usb_resume_device (hcd->self.root_hub); -#else - /* FIXME lock root hub */ - retval = ehci_hub_resume (hcd); -#endif - if (retval == 0) - hcd->self.controller->power.power_state = 0; + /* If any port is suspended, we know we can/must resume the HC. */ + for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { + u32 status; + port--; + status = readl (&ehci->regs->port_status [port]); + if (status & PORT_SUSPEND) { + down (&hcd->self.root_hub->serialize); + retval = ehci_hub_resume (hcd); + up (&hcd->self.root_hub->serialize); + break; + } + if ((status & PORT_POWER) == 0) + powerup = 1; + if (!root->children [port]) + continue; + dbg_port (ehci, __FUNCTION__, port + 1, status); + usb_set_device_state (root->children[port], + USB_STATE_NOTATTACHED); + } + + /* Else reset, to cope with power loss or flush-to-storage + * style "resume" having activated BIOS during reboot. + */ + if (port == 0) { + (void) ehci_halt (ehci); + (void) ehci_reset (ehci); + (void) ehci_hc_reset (hcd); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq (&ehci->lock); + if (ehci->reclaim) + ehci->reclaim_ready = 1; + ehci_work (ehci, NULL); + spin_unlock_irq (&ehci->lock); + + /* restart; khubd will disconnect devices */ + retval = ehci_start (hcd); + + /* here we "know" root ports should always stay powered; + * but some controllers may lost all power. + */ + if (powerup) { + ehci_dbg (ehci, "...powerup ports...\n"); + for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) + (void) ehci_hub_control(hcd, + SetPortFeature, USB_PORT_FEAT_POWER, + port--, NULL, 0); + msleep(20); + } + } + return retval; } @@ -692,15 +760,25 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) timer_action_done (ehci, TIMER_IO_WATCHDOG); if (ehci->reclaim_ready) end_unlink_async (ehci, regs); + + /* another CPU may drop ehci->lock during a schedule scan while + * it reports urb completions. this flag guards against bogus + * attempts at re-entrant schedule scanning. + */ + if (ehci->scanning) + return; + ehci->scanning = 1; scan_async (ehci, regs); if (ehci->next_uframe != -1) scan_periodic (ehci, regs); + ehci->scanning = 0; /* the IO watchdog guards against hardware or driver bugs that * misplace IRQs, and should let us run completely without IRQs. * such lossage has been observed on both VT6202 and VT8235. */ - if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0)) + if (HCD_IS_RUNNING (ehci->hcd.state) && (ehci->async->qh_next.ptr != 0 + || ehci->periodic_sched != 0)) timer_action (ehci, TIMER_IO_WATCHDOG); } @@ -846,6 +924,30 @@ static int ehci_urb_enqueue ( } } +static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + /* if we need to use IAA and it's busy, defer */ + if (qh->qh_state == QH_STATE_LINKED + && ehci->reclaim + && HCD_IS_RUNNING (ehci->hcd.state)) { + struct ehci_qh *last; + + for (last = ehci->reclaim; + last->reclaim; + last = last->reclaim) + continue; + qh->qh_state = QH_STATE_UNLINK_WAIT; + last->reclaim = qh; + + /* bypass IAA if the hc can't care */ + } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim) + end_unlink_async (ehci, NULL); + + /* something else might have unlinked the qh by now */ + if (qh->qh_state == QH_STATE_LINKED) + start_unlink_async (ehci, qh); +} + /* remove from hardware lists * completions normally happen asynchronously */ @@ -864,28 +966,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) qh = (struct ehci_qh *) urb->hcpriv; if (!qh) break; - - /* if we need to use IAA and it's busy, defer */ - if (qh->qh_state == QH_STATE_LINKED - && ehci->reclaim - && HCD_IS_RUNNING (ehci->hcd.state) - ) { - struct ehci_qh *last; - - for (last = ehci->reclaim; - last->reclaim; - last = last->reclaim) - continue; - qh->qh_state = QH_STATE_UNLINK_WAIT; - last->reclaim = qh; - - /* bypass IAA if the hc can't care */ - } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim) - end_unlink_async (ehci, NULL); - - /* something else might have unlinked the qh by now */ - if (qh->qh_state == QH_STATE_LINKED) - start_unlink_async (ehci, qh); + unlink_async (ehci, qh); break; case PIPE_INTERRUPT: @@ -938,7 +1019,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) struct ehci_hcd *ehci = hcd_to_ehci (hcd); int epnum; unsigned long flags; - struct ehci_qh *qh; + struct ehci_qh *qh, *tmp; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ @@ -964,6 +1045,16 @@ rescan: if (!HCD_IS_RUNNING (ehci->hcd.state)) qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { + case QH_STATE_LINKED: + for (tmp = ehci->async->qh_next.qh; + tmp && tmp != qh; + tmp = tmp->qh_next.qh) + continue; + /* periodic qh self-unlinks on empty */ + if (!tmp) + goto nogood; + unlink_async (ehci, qh); + /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ idle_timeout: spin_unlock_irqrestore (&ehci->lock, flags); @@ -977,6 +1068,7 @@ idle_timeout: } /* else FALL THROUGH */ default: +nogood: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. */ @@ -1017,7 +1109,6 @@ static const struct hc_driver ehci_driver = { * memory lifecycle (except per-request) */ .hcd_alloc = ehci_hcd_alloc, - .hcd_free = ehci_hcd_free, /* * managing i/o requests and associated device resources @@ -1089,7 +1180,7 @@ static int __init init (void) sizeof (struct ehci_qh), sizeof (struct ehci_qtd), sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); - return pci_module_init (&ehci_pci_driver); + return pci_register_driver (&ehci_pci_driver); } module_init (init); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 452c73ede..6affe7d37 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -33,22 +33,29 @@ static int ehci_hub_suspend (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct usb_device *root = hcd_to_bus (&ehci->hcd)->root_hub; int port; - int status = 0; - if (root->dev.power.power_state != 0) - return 0; if (time_before (jiffies, ehci->next_statechange)) - return -EAGAIN; + msleep(5); port = HCS_N_PORTS (ehci->hcs_params); spin_lock_irq (&ehci->lock); + /* stop schedules, clean any completed work */ + if (HCD_IS_RUNNING(hcd->state)) { + ehci_quiesce (ehci); + ehci->hcd.state = USB_STATE_QUIESCING; + } + ehci->command = readl (&ehci->regs->command); + if (ehci->reclaim) + ehci->reclaim_ready = 1; + ehci_work(ehci, NULL); + /* suspend any active/unsuspended ports, maybe allow wakeup */ while (port--) { - u32 t1 = readl (&ehci->regs->port_status [port]); - u32 t2 = t1; + u32 __iomem *reg = &ehci->regs->port_status [port]; + u32 t1 = readl (reg); + u32 t2 = t1; if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) t2 |= PORT_SUSPEND; @@ -60,48 +67,45 @@ static int ehci_hub_suspend (struct usb_hcd *hcd) if (t1 != t2) { ehci_vdbg (ehci, "port %d, %08x -> %08x\n", port + 1, t1, t2); - writel (t2, &ehci->regs->port_status [port]); + writel (t2, reg); } } - /* stop schedules, then turn off HC and clean any completed work */ - if (hcd->state == USB_STATE_RUNNING) - ehci_ready (ehci); - ehci->command = readl (&ehci->regs->command); - writel (ehci->command & ~CMD_RUN, &ehci->regs->command); - if (ehci->reclaim) - ehci->reclaim_ready = 1; - ehci_work(ehci, NULL); - (void) handshake (&ehci->regs->status, STS_HALT, STS_HALT, 2000); + /* turn off now-idle HC */ + ehci_halt (ehci); + ehci->hcd.state = HCD_STATE_SUSPENDED; - root->dev.power.power_state = 3; ehci->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irq (&ehci->lock); - return status; + return 0; } -/* caller owns root->serialize, and should reset/reinit on error */ +/* caller has locked the root hub, and should reset/reinit on error */ static int ehci_hub_resume (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct usb_device *root = hcd_to_bus (&ehci->hcd)->root_hub; u32 temp; int i; + int intr_enable; - if (!root->dev.power.power_state) - return 0; if (time_before (jiffies, ehci->next_statechange)) - return -EAGAIN; + msleep(5); + spin_lock_irq (&ehci->lock); /* re-init operational registers in case we lost power */ if (readl (&ehci->regs->intr_enable) == 0) { - writel (INTR_MASK, &ehci->regs->intr_enable); + /* at least some APM implementations will try to deliver + * IRQs right away, so delay them until we're ready. + */ + intr_enable = 1; writel (0, &ehci->regs->segment); writel (ehci->periodic_dma, &ehci->regs->frame_list); writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); - /* FIXME will this work even (pci) vAUX was lost? */ - } + } else + intr_enable = 0; + ehci_dbg(ehci, "resume root hub%s\n", + intr_enable ? " after power loss" : ""); /* restore CMD_RUN, framelist size, and irq threshold */ writel (ehci->command, &ehci->regs->command); @@ -118,7 +122,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd) writel (temp, &ehci->regs->port_status [i]); } i = HCS_N_PORTS (ehci->hcs_params); - msleep (20); + mdelay (20); while (i--) { temp = readl (&ehci->regs->port_status [i]); if ((temp & PORT_SUSPEND) == 0) @@ -135,19 +139,26 @@ static int ehci_hub_resume (struct usb_hcd *hcd) temp |= CMD_ASE; if (ehci->periodic_sched) temp |= CMD_PSE; - if (temp) - writel (ehci->command | temp, &ehci->regs->command); + if (temp) { + ehci->command |= temp; + writel (ehci->command, &ehci->regs->command); + } - root->dev.power.power_state = 0; ehci->next_statechange = jiffies + msecs_to_jiffies(5); ehci->hcd.state = USB_STATE_RUNNING; + + /* Now we can safely re-enable irqs */ + if (intr_enable) + writel (INTR_MASK, &ehci->regs->intr_enable); + + spin_unlock_irq (&ehci->lock); return 0; } #else -#define ehci_hub_suspend 0 -#define ehci_hub_resume 0 +#define ehci_hub_suspend NULL +#define ehci_hub_resume NULL #endif /* CONFIG_PM */ @@ -200,6 +211,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) int ports, i, retval = 1; unsigned long flags; + /* if !USB_SUSPEND, root hub timers won't get shut down ... */ + if (!HCD_IS_RUNNING(ehci->hcd.state)) + return 0; + /* init status to no-changes */ buf [0] = 0; ports = HCS_N_PORTS (ehci->hcs_params); @@ -236,6 +251,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) status = STS_PCD; } } + /* FIXME autosuspend idle root hubs */ spin_unlock_irqrestore (&ehci->lock, flags); return status ? retval : 0; } @@ -265,9 +281,12 @@ ehci_hub_descriptor ( temp = 0x0008; /* per-port overcurrent reporting */ if (HCS_PPC (ehci->hcs_params)) temp |= 0x0001; /* per-port power control */ +#if 0 +// re-enable when we support USB_PORT_FEAT_INDICATOR below. if (HCS_INDICATOR (ehci->hcs_params)) temp |= 0x0080; /* per-port indicators (LEDs) */ - desc->wHubCharacteristics = cpu_to_le16 (temp); +#endif + desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp); } /*-------------------------------------------------------------------------*/ @@ -455,7 +474,7 @@ static int ehci_hub_control ( #endif dbg_port (ehci, "GetStatus", wIndex + 1, temp); // we "know" this alignment is good, caller used kmalloc()... - *((u32 *) buf) = cpu_to_le32 (status); + *((__le32 *) buf) = cpu_to_le32 (status); break; case SetHubFeature: switch (wValue) { diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 31f311d53..e81f61c05 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -50,11 +50,6 @@ static struct usb_hcd *ehci_hcd_alloc (void) return NULL; } -static void ehci_hcd_free (struct usb_hcd *hcd) -{ - kfree (hcd_to_ehci (hcd)); -} - /*-------------------------------------------------------------------------*/ /* Allocate the key transfer structures from the previously allocated pool */ @@ -114,7 +109,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags) return qh; memset (qh, 0, sizeof *qh); - kref_init(&qh->kref, qh_destroy); + kref_init(&qh->kref); qh->ehci = ehci; qh->qh_dma = dma; // INIT_LIST_HEAD (&qh->qh_list); @@ -139,7 +134,7 @@ static inline struct ehci_qh *qh_get (struct ehci_qh *qh) static inline void qh_put (struct ehci_qh *qh) { - kref_put(&qh->kref); + kref_put(&qh->kref, qh_destroy); } /*-------------------------------------------------------------------------*/ @@ -235,9 +230,9 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags) } /* Hardware periodic table */ - ehci->periodic = (u32 *) + ehci->periodic = (__le32 *) dma_alloc_coherent (ehci->hcd.self.controller, - ehci->periodic_size * sizeof (u32), + ehci->periodic_size * sizeof(__le32), &ehci->periodic_dma, 0); if (ehci->periodic == 0) { goto fail; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index be39e7aba..69107cc87 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -83,19 +83,59 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, /*-------------------------------------------------------------------------*/ -/* update halted (but potentially linked) qh */ - static inline void qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) { + /* writes to an active overlay are unsafe */ + BUG_ON(qh->qh_state != QH_STATE_IDLE); + qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma); qh->hw_alt_next = EHCI_LIST_END; + /* Except for control endpoints, we make hardware maintain data + * toggle (like OHCI) ... here (re)initialize the toggle in the QH, + * and set the pseudo-toggle in udev. Only usb_clear_halt() will + * ever clear it. + */ + if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) { + unsigned is_out, epnum; + + is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); + epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; + if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { + qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); + usb_settoggle (qh->dev, epnum, is_out, 1); + } + } + /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb (); qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); } +/* if it weren't for a common silicon quirk (writing the dummy into the qh + * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault + * recovery (including urb dequeue) would need software changes to a QH... + */ +static void +qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + struct ehci_qtd *qtd; + + if (list_empty (&qh->qtd_list)) + qtd = qh->dummy; + else { + qtd = list_entry (qh->qtd_list.next, + struct ehci_qtd, qtd_list); + /* first qtd may already be partially processed */ + if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current) + qtd = NULL; + } + + if (qtd) + qh_update (ehci, qh, qtd); +} + /*-------------------------------------------------------------------------*/ static void qtd_copy_status ( @@ -153,17 +193,9 @@ static void qtd_copy_status ( usb_pipein (urb->pipe) ? "in" : "out", token, urb->status); - /* stall indicates some recovery action is needed */ - if (urb->status == -EPIPE) { - int pipe = urb->pipe; - - if (!usb_pipecontrol (pipe)) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (pipe), - usb_pipeout (pipe)); - /* if async CSPLIT failed, try cleaning out the TT buffer */ - } else if (urb->dev->tt && !usb_pipeint (urb->pipe) + if (urb->status != -EPIPE + && urb->dev->tt && !usb_pipeint (urb->pipe) && ((token & QTD_STS_MMF) != 0 || QTD_CERR(token) == 0) && (!ehci_is_ARC(ehci) @@ -183,6 +215,8 @@ static void qtd_copy_status ( static void ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs) +__releases(ehci->lock) +__acquires(ehci->lock) { if (likely (urb->hcpriv != 0)) { struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; @@ -232,6 +266,11 @@ ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs) spin_lock (&ehci->lock); } +static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); + +static void intr_deschedule (struct ehci_hcd *ehci, + struct ehci_qh *qh, int wait); +static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); /* * Process and free completed qtds for a qh, returning URBs to drivers. @@ -315,6 +354,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs) } else { stopped = 1; + if (unlikely (!HCD_IS_RUNNING (ehci->hcd.state))) + urb->status = -ESHUTDOWN; + /* ignore active urbs unless some previous qtd * for the urb faulted (including short read) or * its urb was canceled. we may patch qh or qtds. @@ -372,21 +414,27 @@ halt: /* restore original state; caller must unlink or relink */ qh->qh_state = state; - /* update qh after fault cleanup */ - if (unlikely (stopped != 0) - /* some EHCI 0.95 impls will overlay dummy qtds */ - || qh->hw_qtd_next == EHCI_LIST_END) { - if (list_empty (&qh->qtd_list)) - end = qh->dummy; - else { - end = list_entry (qh->qtd_list.next, - struct ehci_qtd, qtd_list); - /* first qtd may already be partially processed */ - if (cpu_to_le32 (end->qtd_dma) == qh->hw_current) - end = NULL; + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); + break; + case QH_STATE_LINKED: + /* should be rare for periodic transfers, + * except maybe high bandwidth ... + */ + if (qh->period) { + intr_deschedule (ehci, qh, 1); + (void) qh_schedule (ehci, qh); + } else + start_unlink_async (ehci, qh); + break; + /* otherwise, unlink already started */ } - if (end) - qh_update (ehci, qh, end); } return count; @@ -560,21 +608,6 @@ cleanup: /*-------------------------------------------------------------------------*/ -/* - * Hardware maintains data toggle (like OHCI) ... here we (re)initialize - * the hardware data toggle in the QH, and set the pseudo-toggle in udev - * so we can see if usb_clear_halt() was called. NOP for control, since - * we set up qh->hw_info1 to always use the QTD toggle bits. - */ -static inline void -clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh) -{ - vdbg ("clear toggle, dev %d ep 0x%x-%s", - udev->devnum, ep, is_out ? "out" : "in"); - qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); - usb_settoggle (udev, ep, is_out, 1); -} - // Would be best to create all qh's from config descriptors, // when each interface/altsetting is established. Unlink // any previous qh and cancel its urbs first; endpoints are @@ -654,11 +687,11 @@ qh_make ( qh->period = urb->interval; } - - /* support for tt scheduling */ - qh->dev = usb_get_dev (urb->dev); } + /* support for tt scheduling, and access to toggles */ + qh->dev = usb_get_dev (urb->dev); + /* using TT? */ switch (urb->dev->speed) { case USB_SPEED_LOW: @@ -718,8 +751,8 @@ done: qh->qh_state = QH_STATE_IDLE; qh->hw_info1 = cpu_to_le32 (info1); qh->hw_info2 = cpu_to_le32 (info2); - qh_update (ehci, qh, qh->dummy); usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); + qh_refresh (ehci, qh); return qh; } @@ -729,7 +762,7 @@ done: static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { - u32 dma = QH_NEXT (qh->qh_dma); + __le32 dma = QH_NEXT (qh->qh_dma); struct ehci_qh *head; /* (re)start the async schedule? */ @@ -748,7 +781,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) } } - qh->hw_token &= ~HALT_BIT; + /* clear halt and/or toggle; and maybe recover from silicon quirk */ + if (qh->qh_state == QH_STATE_IDLE) + qh_refresh (ehci, qh); /* splice right after start */ qh->qh_next = head->qh_next; @@ -764,7 +799,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -#define QH_ADDR_MASK __constant_le32_to_cpu(0x7f) +#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) /* * For control/bulk/interrupt, return QH with these TDs appended. @@ -823,32 +858,13 @@ static struct ehci_qh *qh_append_tds ( qh->hw_info1 &= ~QH_ADDR_MASK; } - /* usb_clear_halt() means qh data toggle gets reset */ - if (unlikely (!usb_gettoggle (urb->dev, - (epnum & 0x0f), !(epnum & 0x10))) - && !usb_pipecontrol (urb->pipe)) { - /* "never happens": drivers do stall cleanup right */ - if (qh->qh_state != QH_STATE_IDLE - && !list_empty (&qh->qtd_list) - && qh->qh_state != QH_STATE_COMPLETING) - ehci_warn (ehci, "clear toggle dev%d " - "ep%d%s: not idle\n", - usb_pipedevice (urb->pipe), - epnum & 0x0f, - usb_pipein (urb->pipe) - ? "in" : "out"); - /* else we know this overlay write is safe */ - clear_toggle (urb->dev, - epnum & 0x0f, !(epnum & 0x10), qh); - } - /* just one way to queue requests: swap with the dummy qtd. - * only hc or qh_completions() usually modify the overlay. + * only hc or qh_refresh() ever modify the overlay. */ if (likely (qtd != 0)) { struct ehci_qtd *dummy; dma_addr_t dma; - u32 token; + __le32 token; /* to avoid racing the HC, use the dummy td instead of * the first td of our list (becomes new dummy). both @@ -939,8 +955,6 @@ submit_async ( /* the async qh for the qtds being reclaimed are now unlinked from the HC */ -static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); - static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) { struct ehci_qh *qh = ehci->reclaim; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 10df2665e..74bdd5bfc 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -44,7 +44,7 @@ static int ehci_get_frame (struct usb_hcd *hcd); * @tag: hardware tag for type of this record */ static union ehci_shadow * -periodic_next_shadow (union ehci_shadow *periodic, int tag) +periodic_next_shadow (union ehci_shadow *periodic, __le32 tag) { switch (tag) { case Q_TYPE_QH: @@ -64,7 +64,7 @@ periodic_next_shadow (union ehci_shadow *periodic, int tag) static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) { union ehci_shadow *prev_p = &ehci->pshadow [frame]; - u32 *hw_p = &ehci->periodic [frame]; + __le32 *hw_p = &ehci->periodic [frame]; union ehci_shadow here = *prev_p; union ehci_shadow *next_p; @@ -98,7 +98,7 @@ static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) static unsigned short periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) { - u32 *hw_p = &ehci->periodic [frame]; + __le32 *hw_p = &ehci->periodic [frame]; union ehci_shadow *q = &ehci->pshadow [frame]; unsigned usecs = 0; @@ -196,7 +196,7 @@ static int tt_no_collision ( */ for (; frame < ehci->periodic_size; frame += period) { union ehci_shadow here; - u32 type; + __le32 type; here = ehci->pshadow [frame]; type = Q_NEXT_TYPE (ehci->periodic [frame]); @@ -325,7 +325,7 @@ static void intr_deschedule ( status = disable_periodic (ehci); else { status = 0; - vdbg ("periodic schedule still enabled"); + ehci_vdbg (ehci, "periodic schedule still enabled\n"); } /* @@ -342,7 +342,7 @@ static void intr_deschedule ( * the race is very short. then if qh also isn't * rescheduled soon, it won't matter. otherwise... */ - vdbg ("intr_deschedule..."); + ehci_vdbg (ehci, "intr_deschedule...\n"); } } else qh->hw_next = EHCI_LIST_END; @@ -353,8 +353,8 @@ static void intr_deschedule ( hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= (qh->usecs + qh->c_usecs) / qh->period; - dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d", - qh, qh->period, frame, + ehci_dbg (ehci, "descheduled qh%d/%p frame=%d count=%d, urbs=%d\n", + qh->period, qh, frame, atomic_read (&qh->kref.refcount), ehci->periodic_sched); } @@ -403,7 +403,7 @@ static int check_intr_schedule ( unsigned frame, unsigned uframe, const struct ehci_qh *qh, - u32 *c_maskp + __le32 *c_maskp ) { int retval = -ENOSPC; @@ -412,7 +412,7 @@ static int check_intr_schedule ( goto done; if (!qh->c_usecs) { retval = 0; - *c_maskp = cpu_to_le32 (0); + *c_maskp = 0; goto done; } @@ -447,9 +447,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) { int status; unsigned uframe; - u32 c_mask; + __le32 c_mask; unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + qh_refresh(ehci, qh); qh->hw_next = EHCI_LIST_END; frame = qh->start; @@ -486,13 +487,14 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff); qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask; } else - dbg ("reused previous qh %p schedule", qh); + ehci_dbg (ehci, "reused qh %p schedule\n", qh); /* stuff into the periodic schedule */ qh->qh_state = QH_STATE_LINKED; - dbg ("scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)", - qh, qh->usecs, qh->c_usecs, - qh->period, frame, uframe, qh->gap_uf); + ehci_dbg(ehci, + "scheduled qh%d/%p usecs %d/%d starting %d.%d (gap %d)\n", + qh->period, qh, qh->usecs, qh->c_usecs, + frame, uframe, qh->gap_uf); do { if (unlikely (ehci->pshadow [frame].ptr != 0)) { @@ -907,6 +909,7 @@ itd_urb_transaction ( if (unlikely (0 == itd)) { iso_sched_free (stream, sched); + spin_unlock_irqrestore (&ehci->lock, flags); return -ENOMEM; } memset (itd, 0, sizeof *itd); @@ -1008,8 +1011,7 @@ sitd_slot_ok ( uframe += period_uframes; } while (uframe < mod); - stream->splits = stream->raw_mask << (uframe & 7); - cpu_to_le32s (&stream->splits); + stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7)); return 1; } @@ -1812,7 +1814,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs) for (;;) { union ehci_shadow q, *q_p; - u32 type, *hw_p; + __le32 type, *hw_p; unsigned uframes; /* don't scan past the live uframe */ @@ -1836,7 +1838,9 @@ restart: while (q.ptr != 0) { unsigned uf; union ehci_shadow temp; + int live; + live = HCD_IS_RUNNING (ehci->hcd.state); switch (type) { case Q_TYPE_QH: /* handle any completions */ @@ -1861,7 +1865,7 @@ restart: case Q_TYPE_ITD: /* skip itds for later in the frame */ rmb (); - for (uf = uframes; uf < 8; uf++) { + for (uf = live ? uframes : 8; uf < 8; uf++) { if (0 == (q.itd->hw_transaction [uf] & ITD_ACTIVE)) continue; @@ -1885,7 +1889,8 @@ restart: q = *q_p; break; case Q_TYPE_SITD: - if (q.sitd->hw_results & SITD_ACTIVE) { + if ((q.sitd->hw_results & SITD_ACTIVE) + && live) { q_p = &q.sitd->sitd_next; hw_p = &q.sitd->hw_next; type = Q_NEXT_TYPE (q.sitd->hw_next); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index ed4d00291..2e2cb6eba 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -47,17 +47,25 @@ struct ehci_stats { #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ struct ehci_hcd { /* one per controller */ + + /* glue to PCI and HCD framework */ + struct usb_hcd hcd; /* must come first! */ + struct ehci_caps __iomem *caps; + struct ehci_regs __iomem *regs; + __u32 hcs_params; /* cached register copy */ + spinlock_t lock; /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - int reclaim_ready : 1; + unsigned reclaim_ready : 1; + unsigned scanning : 1; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ unsigned periodic_size; - u32 *periodic; /* hw periodic table */ + __le32 *periodic; /* hw periodic table */ dma_addr_t periodic_dma; unsigned i_thresh; /* uframes HC might cache */ @@ -68,12 +76,6 @@ struct ehci_hcd { /* one per controller */ /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; - /* glue to PCI and HCD framework */ - struct usb_hcd hcd; - struct ehci_caps *caps; - struct ehci_regs *regs; - u32 hcs_params; /* cached register copy */ - /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ struct dma_pool *qtd_pool; /* one or more per qh */ @@ -272,9 +274,9 @@ struct ehci_regs { */ struct ehci_qtd { /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.5.1 */ - u32 hw_alt_next; /* see EHCI 3.5.2 */ - u32 hw_token; /* see EHCI 3.5.3 */ + __le32 hw_next; /* see EHCI 3.5.1 */ + __le32 hw_alt_next; /* see EHCI 3.5.2 */ + __le32 hw_token; /* see EHCI 3.5.3 */ #define QTD_TOGGLE (1 << 31) /* data toggle */ #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) #define QTD_IOC (1 << 15) /* interrupt on complete */ @@ -288,8 +290,8 @@ struct ehci_qtd { #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ #define QTD_STS_STS (1 << 1) /* split transaction state */ #define QTD_STS_PING (1 << 0) /* issue PING? */ - u32 hw_buf [5]; /* see EHCI 3.5.4 */ - u32 hw_buf_hi [5]; /* Appendix B */ + __le32 hw_buf [5]; /* see EHCI 3.5.4 */ + __le32 hw_buf_hi [5]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t qtd_dma; /* qtd address */ @@ -349,18 +351,18 @@ union ehci_shadow { struct ehci_qh { /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.6.1 */ - u32 hw_info1; /* see EHCI 3.6.2 */ + __le32 hw_next; /* see EHCI 3.6.1 */ + __le32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 - u32 hw_info2; /* see EHCI 3.6.2 */ - u32 hw_current; /* qtd list - see EHCI 3.6.4 */ + __le32 hw_info2; /* see EHCI 3.6.2 */ + __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ /* qtd overlay (hardware parts of a struct ehci_qtd) */ - u32 hw_qtd_next; - u32 hw_alt_next; - u32 hw_token; - u32 hw_buf [5]; - u32 hw_buf_hi [5]; + __le32 hw_qtd_next; + __le32 hw_alt_next; + __le32 hw_token; + __le32 hw_buf [5]; + __le32 hw_buf_hi [5]; /* the rest is HCD-private */ dma_addr_t qh_dma; /* address of qh */ @@ -396,7 +398,7 @@ struct ehci_qh { struct ehci_iso_packet { /* These will be copied to iTD when scheduling */ u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ - u32 transaction; /* itd->hw_transaction[i] |= */ + __le32 transaction; /* itd->hw_transaction[i] |= */ u8 cross; /* buf crosses pages */ /* for full speed OUT splits */ u16 buf1; @@ -418,8 +420,8 @@ struct ehci_iso_sched { */ struct ehci_iso_stream { /* first two fields match QH, but info1 == 0 */ - u32 hw_next; - u32 hw_info1; + __le32 hw_next; + __le32 hw_info1; u32 refcount; u8 bEndpointAddress; @@ -433,7 +435,7 @@ struct ehci_iso_stream { unsigned long start; /* jiffies */ unsigned long rescheduled; int next_uframe; - u32 splits; + __le32 splits; /* the rest is derived from the endpoint descriptor, * trusting urb->interval == f(epdesc->bInterval) and @@ -446,12 +448,12 @@ struct ehci_iso_stream { unsigned bandwidth; /* This is used to initialize iTD's hw_bufp fields */ - u32 buf0; - u32 buf1; - u32 buf2; + __le32 buf0; + __le32 buf1; + __le32 buf2; /* this is used to initialize sITD's tt info */ - u32 address; + __le32 address; }; /*-------------------------------------------------------------------------*/ @@ -464,8 +466,8 @@ struct ehci_iso_stream { */ struct ehci_itd { /* first part defined by EHCI spec */ - u32 hw_next; /* see EHCI 3.3.1 */ - u32 hw_transaction [8]; /* see EHCI 3.3.2 */ + __le32 hw_next; /* see EHCI 3.3.1 */ + __le32 hw_transaction [8]; /* see EHCI 3.3.2 */ #define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ #define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ #define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ @@ -475,8 +477,8 @@ struct ehci_itd { #define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) - u32 hw_bufp [7]; /* see EHCI 3.3.3 */ - u32 hw_bufp_hi [7]; /* Appendix B */ + __le32 hw_bufp [7]; /* see EHCI 3.3.3 */ + __le32 hw_bufp_hi [7]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t itd_dma; /* for this itd */ @@ -503,11 +505,11 @@ struct ehci_itd { */ struct ehci_sitd { /* first part defined by EHCI spec */ - u32 hw_next; + __le32 hw_next; /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - u32 hw_fullspeed_ep; /* EHCI table 3-9 */ - u32 hw_uframe; /* EHCI table 3-10 */ - u32 hw_results; /* EHCI table 3-11 */ + __le32 hw_fullspeed_ep; /* EHCI table 3-9 */ + __le32 hw_uframe; /* EHCI table 3-10 */ + __le32 hw_results; /* EHCI table 3-11 */ #define SITD_IOC (1 << 31) /* interrupt on completion */ #define SITD_PAGE (1 << 30) /* buffer 0/1 */ #define SITD_LENGTH(x) (0x3ff & ((x)>>16)) @@ -521,9 +523,9 @@ struct ehci_sitd { #define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE) - u32 hw_buf [2]; /* EHCI table 3-12 */ - u32 hw_backpointer; /* EHCI table 3-13 */ - u32 hw_buf_hi [2]; /* Appendix B */ + __le32 hw_buf [2]; /* EHCI table 3-12 */ + __le32 hw_backpointer; /* EHCI table 3-13 */ + __le32 hw_buf_hi [2]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t sitd_dma; @@ -548,8 +550,8 @@ struct ehci_sitd { * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. */ struct ehci_fstn { - u32 hw_next; /* any periodic q entry */ - u32 hw_prev; /* qh or EHCI_LIST_END */ + __le32 hw_next; /* any periodic q entry */ + __le32 hw_prev; /* qh or EHCI_LIST_END */ /* the rest is HCD-private */ dma_addr_t fstn_dma; diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 54daaacdc..653bfce0c 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -131,16 +131,16 @@ static char *hcfs2string (int state) static void ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) { - struct ohci_regs *regs = controller->regs; + struct ohci_regs __iomem *regs = controller->regs; u32 temp; - temp = ohci_readl (®s->revision) & 0xff; + temp = ohci_readl (controller, ®s->revision) & 0xff; ohci_dbg_sw (controller, next, size, "OHCI %d.%d, %s legacy support registers\n", 0x03 & (temp >> 4), (temp & 0x0f), (temp & 0x10) ? "with" : "NO"); - temp = ohci_readl (®s->control); + temp = ohci_readl (controller, ®s->control); ohci_dbg_sw (controller, next, size, "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp, @@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) temp & OHCI_CTRL_CBSR ); - temp = ohci_readl (®s->cmdstatus); + temp = ohci_readl (controller, ®s->cmdstatus); ohci_dbg_sw (controller, next, size, "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, (temp & OHCI_SOC) >> 16, @@ -166,26 +166,33 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ); ohci_dump_intr_mask (controller, "intrstatus", - ohci_readl (®s->intrstatus), next, size); + ohci_readl (controller, ®s->intrstatus), + next, size); ohci_dump_intr_mask (controller, "intrenable", - ohci_readl (®s->intrenable), next, size); + ohci_readl (controller, ®s->intrenable), + next, size); // intrdisable always same as intrenable maybe_print_eds (controller, "ed_periodcurrent", - ohci_readl (®s->ed_periodcurrent), next, size); + ohci_readl (controller, ®s->ed_periodcurrent), + next, size); maybe_print_eds (controller, "ed_controlhead", - ohci_readl (®s->ed_controlhead), next, size); + ohci_readl (controller, ®s->ed_controlhead), + next, size); maybe_print_eds (controller, "ed_controlcurrent", - ohci_readl (®s->ed_controlcurrent), next, size); + ohci_readl (controller, ®s->ed_controlcurrent), + next, size); maybe_print_eds (controller, "ed_bulkhead", - ohci_readl (®s->ed_bulkhead), next, size); + ohci_readl (controller, ®s->ed_bulkhead), + next, size); maybe_print_eds (controller, "ed_bulkcurrent", - ohci_readl (®s->ed_bulkcurrent), next, size); + ohci_readl (controller, ®s->ed_bulkcurrent), + next, size); maybe_print_eds (controller, "donehead", - ohci_readl (®s->donehead), next, size); + ohci_readl (controller, ®s->donehead), next, size); } #define dbg_port_sw(hc,num,value,next,size) \ @@ -269,7 +276,7 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) ohci_dump_status (controller, NULL, NULL); if (controller->hcca) ohci_dbg (controller, - "hcca frame #%04x\n", OHCI_FRAME_NO(controller->hcca)); + "hcca frame #%04x\n", ohci_frame_no(controller)); ohci_dump_roothub (controller, 1, NULL, NULL); } @@ -279,13 +286,13 @@ static const char data1 [] = "DATA1"; static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, const struct td *td) { - u32 tmp = le32_to_cpup (&td->hwINFO); + u32 tmp = hc32_to_cpup (ohci, &td->hwINFO); ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n", label, td, (tmp & TD_DONE) ? " (DONE)" : "", td->urb, td->index, - le32_to_cpup (&td->hwNextTD)); + hc32_to_cpup (ohci, &td->hwNextTD)); if ((tmp & TD_ISO) == 0) { const char *toggle, *pid; u32 cbp, be; @@ -306,8 +313,8 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, TD_CC_GET(tmp), /* EC, */ toggle, (tmp & TD_DI) >> 21, pid, (tmp & TD_R) ? "R" : ""); - cbp = le32_to_cpup (&td->hwCBP); - be = le32_to_cpup (&td->hwBE); + cbp = hc32_to_cpup (ohci, &td->hwCBP); + be = hc32_to_cpup (ohci, &td->hwBE); ohci_dbg (ohci, " cbp %08x be %08x (len %d)\n", cbp, be, cbp ? (be + 1 - cbp) : 0); } else { @@ -318,10 +325,10 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, (tmp & TD_DI) >> 21, tmp & 0x0000ffff); ohci_dbg (ohci, " bp0 %08x be %08x\n", - le32_to_cpup (&td->hwCBP) & ~0x0fff, - le32_to_cpup (&td->hwBE)); + hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff, + hc32_to_cpup (ohci, &td->hwBE)); for (i = 0; i < MAXPSW; i++) { - u16 psw = le16_to_cpup (&td->hwPSW [i]); + u16 psw = hc16_to_cpup (ohci, &td->hwPSW [i]); int cc = (psw >> 12) & 0x0f; ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i, psw, cc, @@ -336,33 +343,34 @@ static void __attribute__((unused)) ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, const struct ed *ed, int verbose) { - u32 tmp = ed->hwINFO; + u32 tmp = hc32_to_cpu (ohci, ed->hwINFO); char *type = ""; ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n", label, ed, ed->state, edstring (ed->type), - le32_to_cpup (&ed->hwNextED)); + hc32_to_cpup (ohci, &ed->hwNextED)); switch (tmp & (ED_IN|ED_OUT)) { case ED_OUT: type = "-OUT"; break; case ED_IN: type = "-IN"; break; /* else from TDs ... control */ } ohci_dbg (ohci, - " info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", le32_to_cpu (tmp), - 0x03ff & (le32_to_cpu (tmp) >> 16), + " info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", tmp, + 0x03ff & (tmp >> 16), (tmp & ED_DEQUEUE) ? " DQ" : "", (tmp & ED_ISO) ? " ISO" : "", (tmp & ED_SKIP) ? " SKIP" : "", (tmp & ED_LOWSPEED) ? " LOW" : "", - 0x000f & (le32_to_cpu (tmp) >> 7), + 0x000f & (tmp >> 7), type, - 0x007f & le32_to_cpu (tmp)); + 0x007f & tmp); + tmp = hc32_to_cpup (ohci, &ed->hwHeadP); ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s\n", - tmp = le32_to_cpup (&ed->hwHeadP), - (ed->hwHeadP & ED_C) ? data1 : data0, - (ed->hwHeadP & ED_H) ? " HALT" : "", - le32_to_cpup (&ed->hwTailP), + tmp, + (tmp & ED_C) ? data1 : data0, + (tmp & ED_H) ? " HALT" : "", + hc32_to_cpup (ohci, &ed->hwTailP), verbose ? "" : " (not listing)"); if (verbose) { struct list_head *tmp; @@ -394,13 +402,6 @@ static inline void remove_debug_files (struct ohci_hcd *bus) { } #else -static inline struct ohci_hcd *dev_to_ohci (struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata (dev); - - return hcd_to_ohci (hcd); -} - static ssize_t show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) { @@ -415,23 +416,23 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) /* dump a snapshot of the bulk or control schedule */ while (ed) { - u32 info = ed->hwINFO; - u32 scratch = cpu_to_le32p (&ed->hwINFO); - struct list_head *entry; - struct td *td; + u32 info = hc32_to_cpu (ohci, ed->hwINFO); + u32 headp = hc32_to_cpu (ohci, ed->hwHeadP); + struct list_head *entry; + struct td *td; temp = scnprintf (buf, size, "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s", ed, (info & ED_LOWSPEED) ? 'l' : 'f', - scratch & 0x7f, - (scratch >> 7) & 0xf, + info & 0x7f, + (info >> 7) & 0xf, (info & ED_IN) ? "in" : "out", - 0x03ff & (scratch >> 16), - scratch, + 0x03ff & (info >> 16), + info, (info & ED_SKIP) ? " s" : "", - (ed->hwHeadP & ED_H) ? " H" : "", - (ed->hwHeadP & ED_C) ? data1 : data0); + (headp & ED_H) ? " H" : "", + (headp & ED_C) ? data1 : data0); size -= temp; buf += temp; @@ -439,21 +440,21 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) u32 cbp, be; td = list_entry (entry, struct td, td_list); - scratch = cpu_to_le32p (&td->hwINFO); - cbp = le32_to_cpup (&td->hwCBP); - be = le32_to_cpup (&td->hwBE); + info = hc32_to_cpup (ohci, &td->hwINFO); + cbp = hc32_to_cpup (ohci, &td->hwCBP); + be = hc32_to_cpup (ohci, &td->hwBE); temp = scnprintf (buf, size, "\n\ttd %p %s %d cc=%x urb %p (%08x)", td, ({ char *pid; - switch (scratch & TD_DP) { + switch (info & TD_DP) { case TD_DP_SETUP: pid = "setup"; break; case TD_DP_IN: pid = "in"; break; case TD_DP_OUT: pid = "out"; break; default: pid = "(?)"; break; } pid;}), cbp ? (be + 1 - cbp) : 0, - TD_CC_GET (scratch), td->urb, scratch); + TD_CC_GET (info), td->urb, info); size -= temp; buf += temp; } @@ -541,8 +542,7 @@ show_periodic (struct class_device *class_dev, char *buf) /* show more info the first time around */ if (temp == seen_count) { - u32 info = ed->hwINFO; - u32 scratch = cpu_to_le32p (&ed->hwINFO); + u32 info = hc32_to_cpu (ohci, ed->hwINFO); struct list_head *entry; unsigned qlen = 0; @@ -554,15 +554,17 @@ show_periodic (struct class_device *class_dev, char *buf) " (%cs dev%d ep%d%s-%s qlen %u" " max %d %08x%s%s)", (info & ED_LOWSPEED) ? 'l' : 'f', - scratch & 0x7f, - (scratch >> 7) & 0xf, + info & 0x7f, + (info >> 7) & 0xf, (info & ED_IN) ? "in" : "out", (info & ED_ISO) ? "iso" : "int", qlen, - 0x03ff & (scratch >> 16), - scratch, + 0x03ff & (info >> 16), + info, (info & ED_SKIP) ? " K" : "", - (ed->hwHeadP & ED_H) ? " H" : ""); + (ed->hwHeadP & + cpu_to_hc32(ohci, ED_H)) ? + " H" : ""); size -= temp; next += temp; @@ -599,7 +601,7 @@ show_registers (struct class_device *class_dev, char *buf) struct usb_bus *bus; struct usb_hcd *hcd; struct ohci_hcd *ohci; - struct ohci_regs *regs; + struct ohci_regs __iomem *regs; unsigned long flags; unsigned temp, size; char *next; @@ -634,31 +636,31 @@ show_registers (struct class_device *class_dev, char *buf) /* hcca */ if (ohci->hcca) ohci_dbg_sw (ohci, &next, &size, - "hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca)); + "hcca frame 0x%04x\n", ohci_frame_no(ohci)); /* other registers mostly affect frame timings */ - rdata = ohci_readl (®s->fminterval); + rdata = ohci_readl (ohci, ®s->fminterval); temp = scnprintf (next, size, "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", - rdata, (rdata >> 31) ? " FIT" : "", + rdata, (rdata >> 31) ? "FIT " : "", (rdata >> 16) & 0xefff, rdata & 0xffff); size -= temp; next += temp; - rdata = ohci_readl (®s->fmremaining); + rdata = ohci_readl (ohci, ®s->fmremaining); temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", - rdata, (rdata >> 31) ? " FRT" : "", + rdata, (rdata >> 31) ? "FRT " : "", rdata & 0x3fff); size -= temp; next += temp; - rdata = ohci_readl (®s->periodicstart); + rdata = ohci_readl (ohci, ®s->periodicstart); temp = scnprintf (next, size, "periodicstart 0x%04x\n", rdata & 0x3fff); size -= temp; next += temp; - rdata = ohci_readl (®s->lsthresh); + rdata = ohci_readl (ohci, ®s->lsthresh); temp = scnprintf (next, size, "lsthresh 0x%04x\n", rdata & 0x3fff); size -= temp; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d13e98e35..a4d998570 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -2,7 +2,7 @@ * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2000-2004 David Brownell * * [ Initialisation is based on Linus' ] * [ uhci code and gregs ohci fragments ] @@ -97,6 +97,7 @@ #include #include /* for in_interrupt () */ #include +#include #include "../core/hcd.h" #include #include /* needed by ohci-mem.c when no PCI */ @@ -108,7 +109,7 @@ #include -#define DRIVER_VERSION "2004 Feb 02" +#define DRIVER_VERSION "2004 Nov 08" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -121,12 +122,26 @@ #define OHCI_INTR_INIT \ (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH) +#ifdef __hppa__ +/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +#define IR_DISABLE +#endif + +#ifdef CONFIG_ARCH_OMAP +/* OMAP doesn't support IR (no SMM; not needed) */ +#define IR_DISABLE +#endif + /*-------------------------------------------------------------------------*/ static const char hcd_name [] = "ohci_hcd"; #include "ohci.h" +static void ohci_dump (struct ohci_hcd *ohci, int verbose); +static int ohci_init (struct ohci_hcd *ohci); +static void ohci_stop (struct usb_hcd *hcd); + #include "ohci-hub.c" #include "ohci-dbg.c" #include "ohci-mem.c" @@ -138,6 +153,11 @@ static int power_switching = 0; module_param (power_switching, bool, 0); MODULE_PARM_DESC (power_switching, "true (not default) to switch port power"); +/* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */ +static int no_handshake = 0; +module_param (no_handshake, bool, 0); +MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake"); + /*-------------------------------------------------------------------------*/ /* @@ -240,7 +260,7 @@ static int ohci_urb_enqueue ( if (retval < 0) goto fail0; if (ed->type == PIPE_ISOCHRONOUS) { - u16 frame = OHCI_FRAME_NO(ohci->hcca); + u16 frame = ohci_frame_no(ohci); /* delay a few frames before the first TD */ frame += max_t (u16, 8, ed->interval); @@ -383,34 +403,35 @@ static int ohci_get_frame (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - return OHCI_FRAME_NO(ohci->hcca); + return ohci_frame_no(ohci); +} + +static void ohci_usb_reset (struct ohci_hcd *ohci) +{ + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + ohci->hc_control &= OHCI_CTRL_RWC; + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); } /*-------------------------------------------------------------------------* * HC functions *-------------------------------------------------------------------------*/ -/* reset the HC and BUS */ +/* init memory, and kick BIOS/SMM off */ -static int hc_reset (struct ohci_hcd *ohci) +static int ohci_init (struct ohci_hcd *ohci) { u32 temp; + int ret; - /* boot firmware should have set this up (5.1.1.3.1) */ - if (!ohci->fminterval) { - temp = ohci_readl (&ohci->regs->fminterval); - if (temp & 0x3fff0000) - ohci->fminterval = temp; - else - ohci->fminterval = DEFAULT_FMINTERVAL; - /* also: power/overcurrent flags in roothub.a */ - } + disable (ohci); + ohci->regs = ohci->hcd.regs; + ohci->next_statechange = jiffies; - /* SMM owns the HC? not for long! - * On PA-RISC, PDC can leave IR set incorrectly; ignore it there. - */ -#ifndef __hppa__ - if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { +#ifndef IR_DISABLE + /* SMM owns the HC? not for long! */ + if (!no_handshake && ohci_readl (ohci, + &ohci->regs->control) & OHCI_CTRL_IR) { ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); /* this timeout is arbitrary. we make it long, so systems @@ -419,50 +440,123 @@ static int hc_reset (struct ohci_hcd *ohci) */ temp = 500; /* arbitrary: five seconds */ - writel (OHCI_INTR_OC, &ohci->regs->intrenable); - writel (OHCI_OCR, &ohci->regs->cmdstatus); - while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { + ohci_writel (ohci, OHCI_INTR_OC, &ohci->regs->intrenable); + ohci_writel (ohci, OHCI_OCR, &ohci->regs->cmdstatus); + while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) { msleep (10); if (--temp == 0) { ohci_err (ohci, "USB HC TakeOver failed!\n"); - return -1; + return -EBUSY; } } + ohci_usb_reset (ohci); } #endif /* Disable HC interrupts */ - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + // flush the writes + (void) ohci_readl (ohci, &ohci->regs->control); - ohci_dbg (ohci, "reset, control = 0x%x\n", - ohci_readl (&ohci->regs->control)); + if (ohci->hcca) + return 0; - /* Reset USB (needed by some controllers); RemoteWakeupConnected + ohci->hcca = dma_alloc_coherent (ohci->hcd.self.controller, + sizeof *ohci->hcca, &ohci->hcca_dma, 0); + if (!ohci->hcca) + return -ENOMEM; + + if ((ret = ohci_mem_init (ohci)) < 0) + ohci_stop (&ohci->hcd); + + return ret; + +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * resets USB and controller + * enable interrupts + * connect the virtual root hub + */ +static int ohci_run (struct ohci_hcd *ohci) +{ + u32 mask, temp; + struct usb_device *udev; + struct usb_bus *bus; + int first = ohci->fminterval == 0; + + disable (ohci); + + /* boot firmware should have set this up (5.1.1.3.1) */ + if (first) { + + temp = ohci_readl (ohci, &ohci->regs->fminterval); + ohci->fminterval = temp & 0x3fff; + if (ohci->fminterval != FI) + ohci_dbg (ohci, "fminterval delta %d\n", + ohci->fminterval - FI); + ohci->fminterval |= FSMP (ohci->fminterval) << 16; + /* also: power/overcurrent flags in roothub.a */ + } + + /* Reset USB nearly "by the book". RemoteWakeupConnected * saved if boot firmware (BIOS/SMM/...) told us it's connected * (for OHCI integrated on mainboard, it normally is) */ - ohci->hc_control = ohci_readl (&ohci->regs->control); - ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ - if (ohci->hc_control) + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + ohci->hc_control); + + if (ohci->hc_control & OHCI_CTRL_RWC + && !(ohci->flags & OHCI_QUIRK_AMD756)) ohci->hcd.can_wakeup = 1; - writel (ohci->hc_control, &ohci->regs->control); + + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + temp = 0; + break; + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESUME; + temp = 10 /* msec wait */; + break; + // case OHCI_USB_RESET: + default: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESET; + temp = 50 /* msec wait */; + break; + } + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + // flush the writes + (void) ohci_readl (ohci, &ohci->regs->control); + msleep(temp); if (power_switching) { unsigned ports = roothub_a (ohci) & RH_A_NDP; /* power down each port */ for (temp = 0; temp < ports; temp++) - writel (RH_PS_LSDA, + ohci_writel (ohci, RH_PS_LSDA, &ohci->regs->roothub.portstatus [temp]); } - // flush those pci writes - (void) ohci_readl (&ohci->regs->control); - msleep (50); + // flush those writes + (void) ohci_readl (ohci, &ohci->regs->control); + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + /* 2msec timelimit here means no irqs/preempt */ + spin_lock_irq (&ohci->lock); + +retry: /* HC Reset requires max 10 us delay */ - writel (OHCI_HCR, &ohci->regs->cmdstatus); + ohci_writel (ohci, OHCI_HCR, &ohci->regs->cmdstatus); temp = 30; /* ... allow extra time */ - while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + while ((ohci_readl (ohci, &ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--temp == 0) { + spin_unlock_irq (&ohci->lock); ohci_err (ohci, "USB HC reset timed out!\n"); return -1; } @@ -475,102 +569,103 @@ static int hc_reset (struct ohci_hcd *ohci) * ... but some hardware won't init fmInterval "by the book" * (SiS, OPTi ...), so reset again instead. SiS doesn't need * this if we write fmInterval after we're OPERATIONAL. + * Unclear about ALi, ServerWorks, and others ... this could + * easily be a longstanding bug in chip init on Linux. */ - writel (ohci->hc_control, &ohci->regs->control); - // flush those pci writes - (void) ohci_readl (&ohci->regs->control); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub - */ -static int hc_start (struct ohci_hcd *ohci) -{ - u32 mask, tmp; - struct usb_device *udev; - struct usb_bus *bus; - - disable (ohci); + if (ohci->flags & OHCI_QUIRK_INITRESET) { + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + // flush those writes + (void) ohci_readl (ohci, &ohci->regs->control); + } + ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval); /* Tell the controller where the control and bulk lists are * The lists are empty now. */ - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); + ohci_writel (ohci, 0, &ohci->regs->ed_controlhead); + ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead); /* a reset clears this */ - writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); + ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca); periodic_reinit (ohci); /* some OHCI implementations are finicky about how they init. * bogus values here mean not even enumeration could work. */ - if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 - || !ohci_readl (&ohci->regs->periodicstart)) { - ohci_err (ohci, "init err\n"); + if ((ohci_readl (ohci, &ohci->regs->fminterval) & 0x3fff0000) == 0 + || !ohci_readl (ohci, &ohci->regs->periodicstart)) { + if (!(ohci->flags & OHCI_QUIRK_INITRESET)) { + ohci->flags |= OHCI_QUIRK_INITRESET; + ohci_dbg (ohci, "enabling initreset quirk\n"); + goto retry; + } + spin_unlock_irq (&ohci->lock); + ohci_err (ohci, "init err (%08x %04x)\n", + ohci_readl (ohci, &ohci->regs->fminterval), + ohci_readl (ohci, &ohci->regs->periodicstart)); return -EOVERFLOW; } /* start controller operations */ ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); ohci->hcd.state = USB_STATE_RUNNING; /* wake on ConnectStatusChange, matching external hubs */ - writel (RH_HS_DRWE, &ohci->regs->roothub.status); + ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); /* Choose the interrupts we care about now, others later on demand */ mask = OHCI_INTR_INIT; - writel (mask, &ohci->regs->intrstatus); - writel (mask, &ohci->regs->intrenable); + ohci_writel (ohci, mask, &ohci->regs->intrstatus); + ohci_writel (ohci, mask, &ohci->regs->intrenable); /* handle root hub init quirks ... */ - tmp = roothub_a (ohci); - tmp &= ~(RH_A_PSM | RH_A_OCPM); + temp = roothub_a (ohci); + temp &= ~(RH_A_PSM | RH_A_OCPM); if (ohci->flags & OHCI_QUIRK_SUPERIO) { /* NSC 87560 and maybe others */ - tmp |= RH_A_NOCP; - tmp &= ~(RH_A_POTPGT | RH_A_NPS); + temp |= RH_A_NOCP; + temp &= ~(RH_A_POTPGT | RH_A_NPS); } else if (power_switching) { /* act like most external hubs: use per-port power * switching and overcurrent reporting. */ - tmp &= ~(RH_A_NPS | RH_A_NOCP); - tmp |= RH_A_PSM | RH_A_OCPM; + temp &= ~(RH_A_NPS | RH_A_NOCP); + temp |= RH_A_PSM | RH_A_OCPM; } else { /* hub power always on; required for AMD-756 and some * Mac platforms. ganged overcurrent reporting, if any. */ - tmp |= RH_A_NPS; + temp |= RH_A_NPS; } - writel (tmp, &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); - writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b); - // flush those pci writes - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, temp, &ohci->regs->roothub.a); + ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status); + ohci_writel (ohci, power_switching ? RH_B_PPCM : 0, + &ohci->regs->roothub.b); + // flush those writes + (void) ohci_readl (ohci, &ohci->regs->control); + + spin_unlock_irq (&ohci->lock); // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((roothub_a (ohci) >> 23) & 0x1fe); bus = hcd_to_bus (&ohci->hcd); + ohci->hcd.state = USB_STATE_RUNNING; + + ohci_dump (ohci, 1); - if (bus->root_hub) { - ohci->hcd.state = USB_STATE_RUNNING; + udev = hcd_to_bus (&ohci->hcd)->root_hub; + if (udev) { return 0; } /* connect the virtual root hub */ udev = usb_alloc_dev (NULL, bus, 0); - ohci->hcd.state = USB_STATE_RUNNING; if (!udev) { disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); return -ENOMEM; } @@ -579,10 +674,13 @@ static int hc_start (struct ohci_hcd *ohci) usb_put_dev (udev); disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); return -ENODEV; } + if (ohci->power_budget) + hub_set_power_budget(udev, ohci->power_budget); + create_debug_files (ohci); return 0; } @@ -593,23 +691,24 @@ static int hc_start (struct ohci_hcd *ohci) static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct ohci_regs *regs = ohci->regs; + struct ohci_regs __iomem *regs = ohci->regs; int ints; /* we can eliminate a (slow) ohci_readl() if _only_ WDH caused this irq */ if ((ohci->hcca->done_head != 0) - && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { + && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) + & 0x01)) { ints = OHCI_INTR_WDH; /* cardbus/... hardware gone before remove() */ - } else if ((ints = ohci_readl (®s->intrstatus)) == ~(u32)0) { + } else if ((ints = ohci_readl (ohci, ®s->intrstatus)) == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); return IRQ_HANDLED; /* interrupt for some other device? */ - } else if ((ints &= ohci_readl (®s->intrenable)) == 0) { + } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { return IRQ_NONE; } @@ -619,7 +718,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) // e.g. due to PCI Master/Target Abort ohci_dump (ohci, 1); - hc_reset (ohci); + ohci_usb_reset (ohci); } if (ints & OHCI_INTR_RD) { @@ -629,12 +728,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) if (ints & OHCI_INTR_WDH) { if (HCD_IS_RUNNING(hcd->state)) - writel (OHCI_INTR_WDH, ®s->intrdisable); + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable); spin_lock (&ohci->lock); dl_done_list (ohci, ptregs); spin_unlock (&ohci->lock); if (HCD_IS_RUNNING(hcd->state)) - writel (OHCI_INTR_WDH, ®s->intrenable); + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); } /* could track INTR_SO to reduce available PCI/... bandwidth */ @@ -644,18 +743,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) */ spin_lock (&ohci->lock); if (ohci->ed_rm_list) - finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), - ptregs); + finish_unlinks (ohci, ohci_frame_no(ohci), ptregs); if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list && HCD_IS_RUNNING(ohci->hcd.state)) - writel (OHCI_INTR_SF, ®s->intrdisable); + ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); spin_unlock (&ohci->lock); if (HCD_IS_RUNNING(ohci->hcd.state)) { - writel (ints, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); - // flush those pci writes - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, ints, ®s->intrstatus); + ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); + // flush those writes + (void) ohci_readl (ohci, &ohci->regs->control); } return IRQ_HANDLED; @@ -673,10 +771,9 @@ static void ohci_stop (struct usb_hcd *hcd) ohci_dump (ohci, 1); flush_scheduled_work(); - if (HCD_IS_RUNNING(ohci->hcd.state)) - hc_reset (ohci); - else - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + ohci_usb_reset (ohci); + ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); remove_debug_files (ohci); ohci_mem_cleanup (ohci); @@ -693,25 +790,14 @@ static void ohci_stop (struct usb_hcd *hcd) /* must not be called from interrupt context */ -#ifdef CONFIG_PM - -static void mark_children_gone (struct usb_device *dev) -{ - unsigned i; - - for (i = 0; i < dev->maxchild; i++) { - if (dev->children [i] == 0) - continue; - dev->children [i]->state = USB_STATE_NOTATTACHED; - mark_children_gone (dev->children [i]); - } -} +#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) -static int hc_restart (struct ohci_hcd *ohci) +static int ohci_restart (struct ohci_hcd *ohci) { int temp; int i; struct urb_priv *priv; + struct usb_device *root = ohci->hcd.self.root_hub; /* mark any devices gone, so they do nothing till khubd disconnects. * recycle any "live" eds/tds (and urbs) right away. @@ -720,7 +806,11 @@ static int hc_restart (struct ohci_hcd *ohci) */ spin_lock_irq(&ohci->lock); disable (ohci); - mark_children_gone (ohci->hcd.self.root_hub); + for (i = 0; i < root->maxchild; i++) { + if (root->children [i]) + usb_set_device_state (root->children[i], + USB_STATE_NOTATTACHED); + } if (!list_empty (&ohci->pending)) ohci_dbg(ohci, "abort schedule...\n"); list_for_each_entry (priv, &ohci->pending, pending) { @@ -730,7 +820,7 @@ static int hc_restart (struct ohci_hcd *ohci) switch (ed->state) { case ED_OPER: ed->state = ED_UNLINK; - ed->hwINFO |= ED_DEQUEUE; + ed->hwINFO |= cpu_to_hc32(ohci, ED_DEQUEUE); ed_deschedule (ohci, ed); ed->ed_next = ohci->ed_rm_list; @@ -764,7 +854,7 @@ static int hc_restart (struct ohci_hcd *ohci) ohci->ed_controltail = NULL; ohci->ed_bulktail = NULL; - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + if ((temp = ohci_run (ohci)) < 0) { ohci_err (ohci, "can't restart, %d\n", temp); return temp; } else { @@ -774,12 +864,9 @@ static int hc_restart (struct ohci_hcd *ohci) */ i = roothub_a (ohci) & RH_A_NDP; while (i--) - writel (RH_PS_PSS, + ohci_writel (ohci, RH_PS_PSS, &ohci->regs->roothub.portstatus [temp]); - ohci->hcd.self.root_hub->dev.power.power_state = 0; - ohci->hcd.state = USB_STATE_RUNNING; ohci_dbg (ohci, "restart complete\n"); - ohci_dump (ohci, 1); } return 0; } @@ -809,10 +896,25 @@ MODULE_LICENSE ("GPL"); #include "ohci-lh7a404.c" #endif +#ifdef CONFIG_PXA27x +#include "ohci-pxa27x.c" +#endif + #if !(defined(CONFIG_PCI) \ || defined(CONFIG_SA1111) \ || defined(CONFIG_ARCH_OMAP) \ || defined (CONFIG_ARCH_LH7A404) \ + || defined (CONFIG_PXA27x) \ ) #error "missing bus glue for ohci-hcd" #endif + +#if !defined(HAVE_HNP) && defined(CONFIG_USB_OTG) + +#warning non-OTG configuration, too many HCDs + +static void start_hnp(struct ohci_hcd *ohci) +{ + /* "can't happen" */ +} +#endif diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index f6263bf9b..8f40bfa42 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -2,7 +2,7 @@ * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2000-2004 David Brownell * * This file is licenced under GPL */ @@ -11,34 +11,8 @@ /* * OHCI Root Hub ... the nonsharable stuff - * - * Registers don't need cpu_to_le32, that happens transparently */ -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define read_roothub(hc, register, mask) ({ \ - u32 temp = ohci_readl (&hc->regs->roothub.register); \ - if (temp == -1) \ - disable (hc); \ - else if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = ohci_readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a (struct ohci_hcd *hc) - { return read_roothub (hc, a, 0xfc0fe000); } -static inline u32 roothub_b (struct ohci_hcd *hc) - { return ohci_readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci_hcd *hc) - { return ohci_readl (&hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci_hcd *hc, int i) - { return read_roothub (hc, portstatus [i], 0xffe0fce0); } - -/*-------------------------------------------------------------------------*/ - #define dbg_port(hc,label,num,value) \ ohci_dbg (hc, \ "%s roothub.portstatus [%d] " \ @@ -69,36 +43,32 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i) static void dl_done_list (struct ohci_hcd *, struct pt_regs *); static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); +static int ohci_restart (struct ohci_hcd *ohci); static int ohci_hub_suspend (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct usb_device *root = hcd_to_bus (&ohci->hcd)->root_hub; int status = 0; + unsigned long flags; - if (root->dev.power.power_state != 0) - return 0; - if (time_before (jiffies, ohci->next_statechange)) - return -EAGAIN; - - spin_lock_irq (&ohci->lock); + spin_lock_irqsave (&ohci->lock, flags); - ohci->hc_control = ohci_readl (&ohci->regs->control); + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_RESUME: ohci_dbg (ohci, "resume/suspend?\n"); ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control |= OHCI_USB_RESET; - writel (ohci->hc_control, &ohci->regs->control); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); /* FALL THROUGH */ case OHCI_USB_RESET: status = -EBUSY; ohci_dbg (ohci, "needs reinit!\n"); goto done; case OHCI_USB_SUSPEND: - ohci_dbg (ohci, "already suspended?\n"); - goto succeed; + ohci_dbg (ohci, "already suspended\n"); + goto done; } ohci_dbg (ohci, "suspend root hub\n"); @@ -108,9 +78,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) int limit; ohci->hc_control &= ~OHCI_SCHED_ENABLES; - writel (ohci->hc_control, &ohci->regs->control); - ohci->hc_control = ohci_readl (&ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus); /* sched disables take effect on the next frame, * then the last WDH could take 6+ msec @@ -120,15 +90,17 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) while (limit > 0) { udelay (250); limit =- 250; - if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + if (ohci_readl (ohci, &ohci->regs->intrstatus) + & OHCI_INTR_SF) break; } dl_done_list (ohci, NULL); mdelay (7); } dl_done_list (ohci, NULL); - finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), NULL); - writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); + finish_unlinks (ohci, ohci_frame_no(ohci), NULL); + ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus), + &ohci->regs->intrstatus); /* maybe resume can wake root hub */ if (ohci->hcd.remote_wakeup) @@ -139,19 +111,16 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) /* Suspend hub */ ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control |= OHCI_USB_SUSPEND; - writel (ohci->hc_control, &ohci->regs->control); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); /* no resumes until devices finish suspending */ ohci->next_statechange = jiffies + msecs_to_jiffies (5); -succeed: - /* it's not USB_STATE_SUSPENDED unless access to this - * hub from the non-usb side (PCI, SOC, etc) stopped - */ - root->dev.power.power_state = 3; done: - spin_unlock_irq (&ohci->lock); + if (status == 0) + ohci->hcd.state = HCD_STATE_SUSPENDED; + spin_unlock_irqrestore (&ohci->lock, flags); return status; } @@ -163,29 +132,36 @@ static inline struct ed *find_head (struct ed *ed) return ed; } -static int hc_restart (struct ohci_hcd *ohci); - -/* caller owns root->serialize */ +/* caller has locked the root hub */ static int ohci_hub_resume (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct usb_device *root = hcd_to_bus (&ohci->hcd)->root_hub; u32 temp, enables; int status = -EINPROGRESS; - if (!root->dev.power.power_state) - return 0; if (time_before (jiffies, ohci->next_statechange)) - return -EAGAIN; + msleep(5); spin_lock_irq (&ohci->lock); - ohci->hc_control = ohci_readl (&ohci->regs->control); - switch (ohci->hc_control & OHCI_CTRL_HCFS) { + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); + + if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { + /* this can happen after suspend-to-disk */ + if (hcd->state == USB_STATE_RESUMING) { + ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", + ohci->hc_control); + status = -EBUSY; + /* this happens when pmcore resumes HC then root */ + } else { + ohci_dbg (ohci, "duplicate resume\n"); + status = 0; + } + } else switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_SUSPEND: ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); ohci->hc_control |= OHCI_USB_RESUME; - writel (ohci->hc_control, &ohci->regs->control); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); ohci_dbg (ohci, "resume root hub\n"); break; case OHCI_USB_RESUME: @@ -194,7 +170,6 @@ static int ohci_hub_resume (struct usb_hcd *hcd) break; case OHCI_USB_OPER: ohci_dbg (ohci, "odd resume\n"); - root->dev.power.power_state = 0; status = 0; break; default: /* RESET, we lost power */ @@ -202,27 +177,31 @@ static int ohci_hub_resume (struct usb_hcd *hcd) status = -EBUSY; } spin_unlock_irq (&ohci->lock); - if (status == -EBUSY) - return hc_restart (ohci); + if (status == -EBUSY) { + (void) ohci_init (ohci); + return ohci_restart (ohci); + } if (status != -EINPROGRESS) return status; temp = roothub_a (ohci) & RH_A_NDP; enables = 0; while (temp--) { - u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]); + u32 stat = ohci_readl (ohci, + &ohci->regs->roothub.portstatus [temp]); /* force global, not selective, resume */ if (!(stat & RH_PS_PSS)) continue; - writel (RH_PS_POCI, &ohci->regs->roothub.portstatus [temp]); + ohci_writel (ohci, RH_PS_POCI, + &ohci->regs->roothub.portstatus [temp]); } /* Some controllers (lucent) need extra-long delays */ ohci->hcd.state = USB_STATE_RESUMING; mdelay (20 /* usb 11.5.1.10 */ + 15); - temp = ohci_readl (&ohci->regs->control); + temp = ohci_readl (ohci, &ohci->regs->control); temp &= OHCI_CTRL_HCFS; if (temp != OHCI_USB_RESUME) { ohci_err (ohci, "controller won't resume\n"); @@ -230,36 +209,36 @@ static int ohci_hub_resume (struct usb_hcd *hcd) } /* disable old schedule state, reinit from scratch */ - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_controlcurrent); - writel (0, &ohci->regs->ed_bulkhead); - writel (0, &ohci->regs->ed_bulkcurrent); - writel (0, &ohci->regs->ed_periodcurrent); - writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); + ohci_writel (ohci, 0, &ohci->regs->ed_controlhead); + ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent); + ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead); + ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent); + ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent); + ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca); periodic_reinit (ohci); /* interrupts might have been disabled */ - writel (OHCI_INTR_INIT, &ohci->regs->intrenable); + ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable); if (ohci->ed_rm_list) - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus); + ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable); + ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus), + &ohci->regs->intrstatus); /* Then re-enable operations */ - writel (OHCI_USB_OPER, &ohci->regs->control); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); msleep (3); temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; if (ohci->hcd.can_wakeup) temp |= OHCI_CTRL_RWC; ohci->hc_control = temp; - writel (temp, &ohci->regs->control); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, temp, &ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); /* TRSMRCY */ msleep (10); - root->dev.power.power_state = 0; /* keep it alive for ~5x suspend + resume costs */ ohci->next_statechange = jiffies + msecs_to_jiffies (250); @@ -269,13 +248,14 @@ static int ohci_hub_resume (struct usb_hcd *hcd) temp = 0; if (!ohci->ed_rm_list) { if (ohci->ed_controltail) { - writel (find_head (ohci->ed_controltail)->dma, - &ohci->regs->ed_controlhead); + ohci_writel (ohci, + find_head (ohci->ed_controltail)->dma, + &ohci->regs->ed_controlhead); enables |= OHCI_CTRL_CLE; temp |= OHCI_CLF; } if (ohci->ed_bulktail) { - writel (find_head (ohci->ed_bulktail)->dma, + ohci_writel (ohci, find_head (ohci->ed_bulktail)->dma, &ohci->regs->ed_bulkhead); enables |= OHCI_CTRL_BLE; temp |= OHCI_BLF; @@ -287,10 +267,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd) if (enables) { ohci_dbg (ohci, "restarting schedules ... %08x\n", enables); ohci->hc_control |= enables; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); if (temp) - writel (status, &ohci->regs->cmdstatus); - (void) ohci_readl (&ohci->regs->control); + ohci_writel (ohci, temp, &ohci->regs->cmdstatus); + (void) ohci_readl (ohci, &ohci->regs->control); } ohci->hcd.state = USB_STATE_RUNNING; @@ -301,9 +281,9 @@ static void ohci_rh_resume (void *_hcd) { struct usb_hcd *hcd = _hcd; - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); (void) ohci_hub_resume (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); } #else @@ -325,16 +305,26 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; - int can_suspend = 1; + int can_suspend = hcd->can_wakeup; + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); + + /* handle autosuspended root: finish resuming before + * letting khubd or root hub timer see state changes. + */ + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER + || !HCD_IS_RUNNING(ohci->hcd.state)) { + can_suspend = 0; + goto done; + } ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { - if (!HCD_IS_RUNNING(ohci->hcd.state)) - return -ESHUTDOWN; - ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", - ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP); + ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, + ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ - return 0; + goto done; } /* init status */ @@ -370,10 +360,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) continue; can_suspend = 0; } +done: + spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work + * NOTE: if we can do this, we don't need a root hub timer! */ if (can_suspend && !changed @@ -381,12 +374,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER - && down_trylock (&hcd->self.root_hub->serialize) == 0 + && time_after (jiffies, ohci->next_statechange) + && usb_trylock_device (hcd->self.root_hub) ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (&ohci->hcd); ohci->hcd.state = USB_STATE_RUNNING; - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); } #endif @@ -421,7 +415,7 @@ ohci_hub_descriptor ( temp |= 0x0010; else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */ temp |= 0x0008; - desc->wHubCharacteristics = cpu_to_le16 (temp); + desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp); /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ rh = roothub_b (ohci); @@ -435,6 +429,89 @@ ohci_hub_descriptor ( /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_USB_OTG + +static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + u32 status; + + if (!port) + return -EINVAL; + port--; + + /* start port reset before HNP protocol times out */ + status = ohci_readl(ohci, &ohci->regs->roothub.portstatus [port]); + if (!(status & RH_PS_CCS)) + return -ENODEV; + + /* khubd will finish the reset later */ + ohci_writel(ohci, RH_PS_PRS, &ohci->regs->roothub.portstatus [port]); + return 0; +} + +static void start_hnp(struct ohci_hcd *ohci); + +#else + +#define ohci_start_port_reset NULL + +#endif + +/*-------------------------------------------------------------------------*/ + + +/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling, + * not necessarily continuous ... to guard against resume signaling. + * The short timeout is safe for non-root hubs, and is backward-compatible + * with earlier Linux hosts. + */ +#ifdef CONFIG_USB_SUSPEND +#define PORT_RESET_MSEC 50 +#else +#define PORT_RESET_MSEC 10 +#endif + +/* this timer value might be vendor-specific ... */ +#define PORT_RESET_HW_MSEC 10 + +/* wrap-aware logic morphed from */ +#define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0) + +/* called from some task, normally khubd */ +static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) +{ + __hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port]; + u32 temp; + u16 now = ohci_readl(ohci, &ohci->regs->fmnumber); + u16 reset_done = now + PORT_RESET_MSEC; + + /* build a "continuous enough" reset signal, with up to + * 3msec gap between pulses. scheduler HZ==100 must work; + * this might need to be deadline-scheduled. + */ + do { + /* spin until any current reset finishes */ + for (;;) { + temp = ohci_readl (ohci, portstat); + if (!(temp & RH_PS_PRS)) + break; + udelay (500); + } + + if (!(temp & RH_PS_CCS)) + break; + if (temp & RH_PS_PRSC) + ohci_writel (ohci, RH_PS_PRSC, portstat); + + /* start the next reset, sleep till it's probably done */ + ohci_writel (ohci, RH_PS_PRS, portstat); + msleep(PORT_RESET_HW_MSEC); + now = ohci_readl(ohci, &ohci->regs->fmnumber); + } while (tick_before(now, reset_done)); + /* caller synchronizes using PRSC */ +} + static int ohci_hub_control ( struct usb_hcd *hcd, u16 typeReq, @@ -452,7 +529,8 @@ static int ohci_hub_control ( case ClearHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: - writel (RH_HS_OCIC, &ohci->regs->roothub.status); + ohci_writel (ohci, RH_HS_OCIC, + &ohci->regs->roothub.status); case C_HUB_LOCAL_POWER: break; default: @@ -495,22 +573,23 @@ static int ohci_hub_control ( default: goto error; } - writel (temp, &ohci->regs->roothub.portstatus [wIndex]); - // ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); + ohci_writel (ohci, temp, + &ohci->regs->roothub.portstatus [wIndex]); + // ohci_readl (ohci, &ohci->regs->roothub.portstatus [wIndex]); break; case GetHubDescriptor: ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); break; case GetHubStatus: temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE); - *(u32 *) buf = cpu_to_le32 (temp); + *(__le32 *) buf = cpu_to_le32 (temp); break; case GetPortStatus: if (!wIndex || wIndex > ports) goto error; wIndex--; temp = roothub_portstatus (ohci, wIndex); - *(u32 *) buf = cpu_to_le32 (temp); + *(__le32 *) buf = cpu_to_le32 (temp); #ifndef OHCI_VERBOSE_DEBUG if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ @@ -533,18 +612,21 @@ static int ohci_hub_control ( wIndex--; switch (wValue) { case USB_PORT_FEAT_SUSPEND: - writel (RH_PS_PSS, +#ifdef CONFIG_USB_OTG + if (ohci->hcd.self.otg_port == (wIndex + 1) + && ohci->hcd.self.b_hnp_enable) + start_hnp(ohci); + else +#endif + ohci_writel (ohci, RH_PS_PSS, &ohci->regs->roothub.portstatus [wIndex]); break; case USB_PORT_FEAT_POWER: - writel (RH_PS_PPS, + ohci_writel (ohci, RH_PS_PPS, &ohci->regs->roothub.portstatus [wIndex]); break; case USB_PORT_FEAT_RESET: - temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); - if (temp & RH_PS_CCS) - writel (RH_PS_PRS, - &ohci->regs->roothub.portstatus [wIndex]); + root_port_reset (ohci, wIndex); break; default: goto error; diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 4e11a8eae..a787c8f88 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -146,6 +146,7 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver, usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; + hcd->self.release = &usb_hcd_release; hcd->self.hcpriv = (void *) hcd; hcd->self.bus_name = "lh7a404"; hcd->product_desc = "LH7A404 OHCI"; @@ -165,9 +166,8 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver, err2: hcd_buffer_destroy (hcd); - if (hcd) - driver->hcd_free(hcd); err1: + kfree(hcd); lh7a404_stop_hc(dev); release_mem_region(dev->resource[0].start, dev->resource[0].end @@ -191,8 +191,6 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver, */ void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev) { - void *base; - pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state); if (in_interrupt ()) @@ -211,9 +209,6 @@ void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev) usb_deregister_bus (&hcd->self); - base = hcd->regs; - hcd->driver->hcd_free (hcd); - lh7a404_stop_hc(dev); release_mem_region(dev->resource[0].start, dev->resource[0].end @@ -229,38 +224,14 @@ ohci_lh7a404_start (struct usb_hcd *hcd) int ret; ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci); - - ohci->hcca = dma_alloc_coherent (hcd->self.controller, - sizeof *ohci->hcca, &ohci->hcca_dma, 0); - if (!ohci->hcca) - return -ENOMEM; - - ohci_dbg (ohci, "ohci_lh7a404_start, ohci->hcca:%p", - ohci->hcca); - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); + if ((ret = ohci_init(ohci)) < 0) return ret; - } - ohci->regs = hcd->regs; - if (hc_reset (ohci) < 0) { - ohci_stop (hcd); - return -ENODEV; - } - - if (hc_start (ohci) < 0) { + if ((ret = ohci_run (ohci)) < 0) { err ("can't start %s", ohci->hcd.self.bus_name); ohci_stop (hcd); - return -EBUSY; + return ret; } - create_debug_files (ohci); - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif /*DEBUG*/ return 0; } @@ -289,7 +260,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { * memory lifecycle (except per-request) */ .hcd_alloc = ohci_hcd_alloc, - .hcd_free = ohci_hcd_free, /* * managing i/o requests and associated device resources diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index 13419364f..705825bff 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -40,11 +40,6 @@ static struct usb_hcd *ohci_hcd_alloc (void) return NULL; } -static void ohci_hcd_free (struct usb_hcd *hcd) -{ - kfree (hcd_to_ohci (hcd)); -} - /*-------------------------------------------------------------------------*/ static int ohci_mem_init (struct ohci_hcd *ohci) @@ -104,7 +99,7 @@ td_alloc (struct ohci_hcd *hc, int mem_flags) if (td) { /* in case hc fetches it, make it look dead */ memset (td, 0, sizeof *td); - td->hwNextTD = cpu_to_le32 (dma); + td->hwNextTD = cpu_to_hc32 (hc, dma); td->td_dma = dma; /* hashed in td_fill */ } @@ -120,7 +115,7 @@ td_free (struct ohci_hcd *hc, struct td *td) prev = &(*prev)->td_hash; if (*prev) *prev = td->td_hash; - else if ((td->hwINFO & TD_DONE) != 0) + else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0) ohci_dbg (hc, "no hash for td %p\n", td); dma_pool_free (hc->td_cache, td, td->td_dma); } diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 1e5fc5d93..e3f2f2a35 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -2,27 +2,30 @@ * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2000-2004 David Brownell * (C) Copyright 2002 Hewlett-Packard Company * * OMAP Bus Glue * * Written by Christopher Hoover - * Based on fragments of previous driver by Rusell King et al. + * Based on fragments of previous driver by Russell King et al. * * Modified for OMAP from ohci-sa1111.c by Tony Lindgren * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc. * * This file is licenced under the GPL. */ - + #include #include +#include -#include #include #include #include +#include +#include +#include #include "ohci-omap.h" @@ -33,123 +36,40 @@ extern int usb_disabled(void); extern int ocpi_enable(void); -/* - * Use the first port only by default. Override with hmc_mode option. - * - * NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports - * 1 & 2, so only port 0 will work. To use the OHCI on the first port, use - * the Innovator USB client cable with a client-to-client connector and modify - * either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should - * be the red lead in the cable. - * - * To mount USB hard disk as root, see the patch for do_mounts.c that tries - * remounting the root, and use root=0801 if your root is on sda1. Does not - * work with devfs. - */ -static int default_hmc_mode = 16; -static int hmc_mode = 1234; - -/* - * Set the USB host pin multiplexing and the selected HMC mode - */ -static int omap_usb_set_hmc_mode(int hmc_mode) -{ - unsigned int val; - - switch (hmc_mode) { - case 0: - /* 0: function, 1: disabled, 2: disabled */ - omap_cfg_reg(W4_USB_PUEN); - omap_cfg_reg(R18_1510_USB_GPIO0); - break; - case 4: - /* 0: function 1: host 2: host */ - omap_cfg_reg(usb1_speed); - omap_cfg_reg(usb1_susp); - omap_cfg_reg(usb1_seo); - omap_cfg_reg(usb1_txen); - omap_cfg_reg(usb1_txd); - omap_cfg_reg(usb1_vp); - omap_cfg_reg(usb1_vm); - omap_cfg_reg(usb1_rcv); - omap_cfg_reg(usb2_susp); - omap_cfg_reg(usb2_seo); - omap_cfg_reg(usb2_txen); - omap_cfg_reg(usb2_txd); - omap_cfg_reg(usb2_vp); - omap_cfg_reg(usb2_vm); - omap_cfg_reg(usb2_rcv); - break; - case 16: - /* 0: host, 1: disabled, 2: disabled */ - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(Y5_USB0_RCV); - omap_cfg_reg(R9_USB0_VM); - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W5_USB0_SE0); - break; - default: - printk("Unknown USB host configuration: %i\n", hmc_mode); - return -ENODEV; - } - - /* Write the selected HMC mode */ - val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR; - val |= (hmc_mode << 1); - writel(val, MOD_CONF_CTRL_0); - - return 0; -} - /* * OHCI clock initialization for OMAP-1510 and 1610 */ static int omap_ohci_clock_power(int on) { if (on) { - if (cpu_is_omap_1510()) { - /* Use DPLL, not APLL */ - writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH, - ULPD_APLL_CTRL_REG); - - /* Enable DPLL */ - writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE, - ULPD_DPLL_CTRL_REG); - - /* Software request for USB 48MHz clock */ - writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ, - ULPD_SOFT_REQ_REG); + /* for 1510, 48MHz DPLL is set up in usb init */ - while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK)); - } - - if (cpu_is_omap_1610()) { + if (cpu_is_omap16xx()) { /* Enable OHCI */ - writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ, - ULPD_SOFT_REQ_REG); + omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ, + ULPD_SOFT_REQ); /* USB host clock request if not using OTG */ - writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ, - ULPD_SOFT_REQ_REG); + omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ, + ULPD_SOFT_REQ); - writel(readl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ, - ULPD_STATUS_REQ_REG); + omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ, + ULPD_STATUS_REQ); } /* Enable 48MHz clock to USB */ - writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN, - ULPD_CLOCK_CTRL_REG); + omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN, + ULPD_CLOCK_CTRL); - writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK), + omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK), ARM_IDLECT2); - writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN, + omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN, MOD_CONF_CTRL_0); } else { /* Disable 48MHz clock to USB */ - writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN, - ULPD_CLOCK_CTRL_REG); + omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN, + ULPD_CLOCK_CTRL); /* FIXME: The DPLL stays on for now */ } @@ -163,13 +83,21 @@ static int omap_ohci_clock_power(int on) static int omap_ohci_transceiver_power(int on) { if (on) { - if (omap_is_innovator()) - writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20, - OMAP1510_FPGA_HOST_CTRL); + if (machine_is_omap_innovator() && cpu_is_omap1510()) + fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) + | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), + INNOVATOR_FPGA_CAM_USB_CONTROL); + else if (machine_is_omap_osk()) { + /* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */ + } } else { - if (omap_is_innovator()) - writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20, - OMAP1510_FPGA_HOST_CTRL); + if (machine_is_omap_innovator() && cpu_is_omap1510()) + fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) + & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), + INNOVATOR_FPGA_CAM_USB_CONTROL); + else if (machine_is_omap_osk()) { + /* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */ + } } return 0; @@ -181,10 +109,10 @@ static int omap_ohci_transceiver_power(int on) static int omap_1510_local_bus_power(int on) { if (on) { - writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL); + omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL); udelay(200); } else { - writel(0, OMAP1510_LB_MMU_CTL); + omap_writel(0, OMAP1510_LB_MMU_CTL); } return 0; @@ -193,8 +121,8 @@ static int omap_1510_local_bus_power(int on) /* * OMAP-1510 specific Local Bus initialization * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE. - * See also arch/mach-omap/memory.h for __virt_to_bus() and - * __bus_to_virt() which need to match with the physical + * See also arch/mach-omap/memory.h for __virt_to_dma() and + * __dma_to_virt() which need to match with the physical * Local Bus address below. */ static int omap_1510_local_bus_init(void) @@ -202,125 +130,115 @@ static int omap_1510_local_bus_init(void) unsigned int tlb; unsigned long lbaddr, physaddr; - writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, + omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, OMAP1510_LB_CLOCK_DIV); /* Configure the Local Bus MMU table */ for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) { lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET; physaddr = tlb * 0x00100000 + PHYS_OFFSET; - writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); - writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, + omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H); + omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, OMAP1510_LB_MMU_CAM_L); - writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); - writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); - writel(tlb << 4, OMAP1510_LB_MMU_LCK); - writel(0x1, OMAP1510_LB_MMU_LD_TLB); + omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H); + omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L); + omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK); + omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB); } /* Enable the walking table */ - writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL); + omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL); udelay(200); return 0; } -/* - * OMAP-1610 specific hardware initialization - * - * Intended to configure OMAP-1610 USB host and OTG ports depending on - * the HMC mode selected. - * - * FIXME: Currently only supports alternate ping group 2 mode, should - * be easy to modify for other configurations once there is some - * hardware to test with. - */ -static int omap_1610_usb_init(int mode) -{ - u_int val = 0; - - /* Configure the OMAP transceiver settings */ - val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/ - val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */ +#ifdef CONFIG_USB_OTG - //val |= (1 << 3); /* Isolate integrated transceiver from port 0 */ - val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */ - val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */ +static void start_hnp(struct ohci_hcd *ohci) +{ + const unsigned port = ohci->hcd.self.otg_port - 1; + unsigned long flags; - writel(val, USB_TRANSCEIVER_CTRL); + otg_start_hnp(ohci->transceiver); - /* Set the USB0_TRX_MODE */ - val = 0; - val &= ~OTG_IDLE_EN; - val &= ~DEV_IDLE_EN; - val &= ~(7 << 16); /* Clear USB0_TRX_MODE */ - val |= (3 << 16); /* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */ - writel(val, OTG_SYSCON_1); + local_irq_save(flags); + ohci->transceiver->state = OTG_STATE_A_SUSPEND; + writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]); + OTG_CTRL_REG &= ~OTG_A_BUSREQ; + local_irq_restore(flags); +} - /* - * Control via OTG, see TRM p 15-163 - */ - val = 0; - //val |= 1; /* REVISIT: Enable OTG = 1 */ +#endif - /* Control via OTG */ - val &= ~HMC_PADEN; - val &= ~OTG_PADEN; - val |= UHOST_EN; +/*-------------------------------------------------------------------------*/ - val &= ~0x3f; /* Clear HMC mode */ - val |= mode; /* Set HMC mode */ - val &= ~(7 << 16); /* Clear ASE0_BRST */ - val |= (4 << 16); /* Must be 4 */ - val |= USBX_SYNCHRO; /* Must be set */ - val |= SRP_VBUS; - writel(val, OTG_SYSCON_2); +static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) +{ + struct omap_usb_config *config = pdev->dev.platform_data; + int need_transceiver = (config->otg != 0); - /* Enable OTG idle */ - //writel(readl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1); + dev_dbg(&pdev->dev, "starting USB Controller\n"); - return 0; -} + if (config->otg) { + ohci->hcd.self.otg_port = config->otg; + /* default/minimum OTG power budget: 8 mA */ + ohci->power_budget = 8; + } -/*-------------------------------------------------------------------------*/ + /* boards can use OTG transceivers in non-OTG modes */ + need_transceiver = need_transceiver + || machine_is_omap_h2(); -static void omap_start_hc(struct omap_dev *dev) -{ - printk(KERN_DEBUG __FILE__ - ": starting OMAP OHCI USB Controller\n"); + if (cpu_is_omap16xx()) + ocpi_enable(); - /* - * Set the HMC mode for the USB ports - */ -#if 0 - /* See note about the Innovator wiring above */ - if (omap_is_innovator()) - hmc_mode = 4; /* 0: function 1: host 2: host */ +#ifdef CONFIG_ARCH_OMAP_OTG + if (need_transceiver) { + ohci->transceiver = otg_get_transceiver(); + if (ohci->transceiver) { + int status = otg_set_host(ohci->transceiver, + &ohci->hcd.self); + dev_dbg(&pdev->dev, "init %s transceiver, status %d\n", + ohci->transceiver->label, status); + if (status) { + if (ohci->transceiver) + put_device(ohci->transceiver->dev); + return status; + } + } else { + dev_err(&pdev->dev, "can't find transceiver\n"); + return -ENODEV; + } + } #endif - if (cpu_is_omap_1610()) - ocpi_enable(); - - omap_usb_set_hmc_mode(hmc_mode); + if (machine_is_omap_osk()) { + omap_request_gpio(9); + omap_set_gpio_direction(9, 1); + omap_set_gpio_dataout(9, 1); + } omap_ohci_clock_power(1); + omap_ohci_transceiver_power(1); - if (cpu_is_omap_1510()) { + if (cpu_is_omap1510()) { omap_1510_local_bus_power(1); omap_1510_local_bus_init(); } - if (cpu_is_omap_1610()) - omap_1610_usb_init(hmc_mode); + /* board init will have already handled HMC and mux setup. + * any external transceiver should already be initialized + * too, so all configured ports use the right signaling now. + */ - //omap_enable_device(dev); + return 0; } -static void omap_stop_hc(struct omap_dev *dev) +static void omap_stop_hc(struct platform_device *pdev) { - printk(KERN_DEBUG __FILE__ - ": stopping OMAP OHCI USB Controller\n"); + dev_dbg(&pdev->dev, "stopping USB Controller\n"); /* * FIXME: Put the USB host controller into reset. @@ -336,16 +254,7 @@ static void omap_stop_hc(struct omap_dev *dev) /*-------------------------------------------------------------------------*/ -static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r) -{ - struct usb_hcd *hcd = __hcd; - - return usb_hcd_irq(irq, hcd, r); -} - -/*-------------------------------------------------------------------------*/ - -void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *); +void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -358,59 +267,72 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *); * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. - * - * Store this function in the HCD's struct pci_driver as probe(). */ int usb_hcd_omap_probe (const struct hc_driver *driver, - struct usb_hcd **hcd_out, - struct omap_dev *dev) + struct platform_device *pdev) { int retval; struct usb_hcd *hcd = 0; + struct ohci_hcd *ohci; - if (!request_mem_region(dev->res.start, - dev->res.end - dev->res.start + 1, hcd_name)) { - dbg("request_mem_region failed"); - return -EBUSY; + if (pdev->num_resources != 2) { + printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", + pdev->num_resources); + return -ENODEV; } - omap_start_hc(dev); + if (pdev->resource[0].flags != IORESOURCE_MEM + || pdev->resource[1].flags != IORESOURCE_IRQ) { + printk(KERN_ERR "hcd probe: invalid resource type\n"); + return -ENODEV; + } + + if (!request_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) { + dev_dbg(&pdev->dev, "request_mem_region failed\n"); + return -EBUSY; + } hcd = driver->hcd_alloc (); if (hcd == NULL){ - dbg ("hcd_alloc failed"); + dev_dbg(&pdev->dev, "hcd_alloc failed\n"); retval = -ENOMEM; goto err1; } + dev_set_drvdata(&pdev->dev, hcd); + ohci = hcd_to_ohci(hcd); hcd->driver = (struct hc_driver *) driver; hcd->description = driver->description; - hcd->irq = dev->irq[0]; - hcd->regs = dev->mapbase; - hcd->self.controller = &dev->dev; + hcd->irq = pdev->resource[1].start; + hcd->regs = (void *)pdev->resource[0].start; + hcd->self.controller = &pdev->dev; + + retval = omap_start_hc(ohci, pdev); + if (retval < 0) + goto err1; retval = hcd_buffer_create (hcd); if (retval != 0) { - dbg ("pool alloc fail"); + dev_dbg(&pdev->dev, "pool alloc fail\n"); goto err1; } - retval = request_irq (hcd->irq, - usb_hcd_omap_hcim_irq, + retval = request_irq (hcd->irq, usb_hcd_irq, SA_INTERRUPT, hcd->description, hcd); if (retval != 0) { - dbg("request_irq failed"); + dev_dbg(&pdev->dev, "request_irq failed\n"); retval = -EBUSY; goto err2; } - info ("%s (OMAP) at 0x%p, irq %d\n", - hcd->description, hcd->regs, hcd->irq); + dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; + hcd->self.release = &usb_hcd_release; hcd->self.hcpriv = (void *) hcd; - hcd->self.bus_name = "omap"; + hcd->self.bus_name = pdev->dev.bus_id; hcd->product_desc = "OMAP OHCI"; INIT_LIST_HEAD (&hcd->dev_list); @@ -418,22 +340,22 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, if ((retval = driver->start (hcd)) < 0) { - usb_hcd_omap_remove(hcd, dev); + usb_hcd_omap_remove(hcd, pdev); return retval; } - *hcd_out = hcd; return 0; err2: hcd_buffer_destroy (hcd); - if (hcd) - driver->hcd_free(hcd); err1: - omap_stop_hc(dev); + kfree(hcd); + omap_stop_hc(pdev); - release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); + release_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1); + dev_set_drvdata(&pdev->dev, 0); return retval; } @@ -451,34 +373,33 @@ int usb_hcd_omap_probe (const struct hc_driver *driver, * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev) +void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) { - void *base; - - info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); + dev_info(&pdev->dev, "remove: state %x\n", hcd->state); if (in_interrupt ()) BUG (); hcd->state = USB_STATE_QUIESCING; - dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); + dev_dbg(&pdev->dev, "roothub graceful disconnect\n"); usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd); hcd_buffer_destroy (hcd); hcd->state = USB_STATE_HALT; + if (machine_is_omap_osk()) + omap_free_gpio(9); + free_irq (hcd->irq, hcd); usb_deregister_bus (&hcd->self); - base = hcd->regs; - hcd->driver->hcd_free (hcd); - - omap_stop_hc(dev); + omap_stop_hc(pdev); - release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); + release_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1); } /*-------------------------------------------------------------------------*/ @@ -486,35 +407,22 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev) static int __devinit ohci_omap_start (struct usb_hcd *hcd) { + struct omap_usb_config *config; struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - ohci->hcca = dma_alloc_consistent (hcd->self.controller, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); + if ((ret = ohci_init(ohci)) < 0) return ret; - } - ohci->regs = hcd->regs; - if (hc_reset (ohci) < 0) { - ohci_stop (hcd); - return -ENODEV; - } - if (hc_start (ohci) < 0) { + config = hcd->self.controller->platform_data; + if (config->otg || config->rwc) + writel(OHCI_CTRL_RWC, &ohci->regs->control); + + if ((ret = ohci_run (ohci)) < 0) { err ("can't start %s", ohci->hcd.self.bus_name); ohci_stop (hcd); - return -EBUSY; + return ret; } - create_debug_files (ohci); - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif return 0; } @@ -533,17 +441,12 @@ static const struct hc_driver ohci_omap_hc_driver = { * basic lifecycle operations */ .start = ohci_omap_start, -#ifdef CONFIG_PM - /* suspend: ohci_omap_suspend, -- tbd */ - /* resume: ohci_omap_resume, -- tbd */ -#endif .stop = ohci_stop, /* * memory lifecycle (except per-request) */ .hcd_alloc = ohci_hcd_alloc, - .hcd_free = ohci_hcd_free, /* * managing i/o requests and associated device resources @@ -566,104 +469,130 @@ static const struct hc_driver ohci_omap_hc_driver = { .hub_suspend = ohci_hub_suspend, .hub_resume = ohci_hub_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ -static int ohci_hcd_omap_drv_probe(struct omap_dev *dev) +static int ohci_hcd_omap_drv_probe(struct device *dev) { - struct usb_hcd *hcd = NULL; - int ret; + return usb_hcd_omap_probe(&ohci_omap_hc_driver, + to_platform_device(dev)); +} - if (usb_disabled()) - return -ENODEV; +static int ohci_hcd_omap_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + usb_hcd_omap_remove(hcd, pdev); + if (ohci->transceiver) { + (void) otg_set_host(ohci->transceiver, 0); + put_device(ohci->transceiver->dev); + } + dev_set_drvdata(dev, NULL); + + return 0; +} + +/*-------------------------------------------------------------------------*/ - ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev); +#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) - if (ret == 0) - omap_set_drvdata(dev, hcd); +/* states match PCI usage, always suspending the root hub except that + * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset). + */ - return ret; +static int ohci_omap_suspend(struct device *dev, u32 state, u32 level) +{ + struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); + int status = -EINVAL; + + if (state <= dev->power.power_state) + return 0; + + dev_dbg(dev, "suspend to %d\n", state); + down(&ohci->hcd.self.root_hub->serialize); + status = ohci_hub_suspend(&ohci->hcd); + if (status == 0) { + if (state >= 4) { + /* power off + reset */ + OTG_SYSCON_2_REG &= ~UHOST_EN; + ohci->hcd.self.root_hub->state = USB_STATE_SUSPENDED; + state = 4; + } + ohci->hcd.state = HCD_STATE_SUSPENDED; + dev->power.power_state = state; + } + up(&ohci->hcd.self.root_hub->serialize); + return status; } -static int ohci_hcd_omap_drv_remove(struct omap_dev *dev) +static int ohci_omap_resume(struct device *dev, u32 level) { - struct usb_hcd *hcd = omap_get_drvdata(dev); + struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); + int status = 0; - usb_hcd_omap_remove(hcd, dev); + switch (dev->power.power_state) { + case 0: + break; + case 4: + if (time_before(jiffies, ohci->next_statechange)) + msleep(5); + ohci->next_statechange = jiffies; + OTG_SYSCON_2_REG |= UHOST_EN; + /* FALLTHROUGH */ + default: + dev_dbg(dev, "resume from %d\n", dev->power.power_state); +#ifdef CONFIG_USB_SUSPEND + /* get extra cleanup even if remote wakeup isn't in use */ + status = usb_resume_device(ohci->hcd.self.root_hub); +#else + down(&ohci->hcd.self.root_hub->serialize); + status = ohci_hub_resume(&ohci->hcd); + up(&ohci->hcd.self.root_hub->serialize); +#endif + if (status == 0) + dev->power.power_state = 0; + break; + } + return status; +} - omap_set_drvdata(dev, NULL); +#endif - return 0; -} +/*-------------------------------------------------------------------------*/ /* * Driver definition to register with the OMAP bus */ -static struct omap_driver ohci_hcd_omap_driver = { - .drv = { - .name = OMAP_OHCI_NAME, - }, - .devid = OMAP_OCP_DEVID_USB, - .busid = OMAP_BUS_OCP, - .clocks = 0, +static struct device_driver ohci_hcd_omap_driver = { + .name = "ohci", + .bus = &platform_bus_type, .probe = ohci_hcd_omap_drv_probe, .remove = ohci_hcd_omap_drv_remove, -}; - -/* Any dma_mask must be set for OHCI to work */ -static u64 omap_dmamask = 0xffffffffUL; - -/* - * Device definition to match the driver above - */ -static struct omap_dev ohci_hcd_omap_device = { - .name = OMAP_OHCI_NAME, - .devid = OMAP_OCP_DEVID_USB, - .busid = OMAP_BUS_OCP, - .mapbase = (void *)OMAP_OHCI_BASE, - .dma_mask = &omap_dmamask, /* Needed only for OHCI */ - .res = { - .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + OMAP_OHCI_SIZE, - }, - .irq = { - INT_USB_HHC_1, - }, +#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) + .suspend = ohci_omap_suspend, + .resume = ohci_omap_resume, +#endif }; static int __init ohci_hcd_omap_init (void) { - int ret; - - dbg (DRIVER_INFO " (OMAP)"); - dbg ("block sizes: ed %d td %d\n", - sizeof (struct ed), sizeof (struct td)); - - if (hmc_mode < 0 || hmc_mode > 25) - hmc_mode = default_hmc_mode; - - /* Register the driver with OMAP bus */ - ret = omap_driver_register(&ohci_hcd_omap_driver); - if (ret != 0) + printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name); + if (usb_disabled()) return -ENODEV; - /* Register the device with OMAP bus */ - ret = omap_device_register(&ohci_hcd_omap_device); - if (ret != 0) { - omap_driver_unregister(&ohci_hcd_omap_driver); - return -ENODEV; - } + pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof (struct ed), sizeof (struct td)); - return ret; + return driver_register(&ohci_hcd_omap_driver); } -MODULE_PARM(hmc_mode, "hmc_mode"); - static void __exit ohci_hcd_omap_cleanup (void) { - omap_device_unregister(&ohci_hcd_omap_device); - omap_driver_unregister(&ohci_hcd_omap_driver); + driver_unregister(&ohci_hcd_omap_driver); } module_init (ohci_hcd_omap_init); diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index dc8bc13bf..89624afec 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -35,9 +35,7 @@ ohci_pci_reset (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - ohci->regs = hcd->regs; - ohci->next_statechange = jiffies; - return hc_reset (ohci); + return ohci_init (ohci); } static int __devinit @@ -46,11 +44,6 @@ ohci_pci_start (struct usb_hcd *hcd) struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - ohci->hcca = dma_alloc_coherent (hcd->self.controller, - sizeof *ohci->hcca, &ohci->hcca_dma, 0); - if (!ohci->hcca) - return -ENOMEM; - if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { struct pci_dev *pdev = to_pci_dev(hcd->self.controller); @@ -61,6 +54,7 @@ ohci_pci_start (struct usb_hcd *hcd) && pdev->device == 0x740c) { ohci->flags = OHCI_QUIRK_AMD756; ohci_info (ohci, "AMD756 erratum 4 workaround\n"); + // also somewhat erratum 10 (suspend/resume issues) } /* FIXME for some of the early AMD 760 southbridges, OHCI @@ -92,25 +86,16 @@ ohci_pci_start (struct usb_hcd *hcd) ohci_info (ohci, "Using NSC SuperIO setup\n"); } } - - } - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); - return ret; } - if (hc_start (ohci) < 0) { + /* NOTE: there may have already been a first reset, to + * keep bios/smm irqs from making trouble + */ + if ((ret = ohci_run (ohci)) < 0) { ohci_err (ohci, "can't start\n"); ohci_stop (hcd); - return -EBUSY; + return ret; } - create_debug_files (ohci); - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif return 0; } @@ -121,25 +106,22 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) struct ohci_hcd *ohci = hcd_to_ohci (hcd); /* suspend root hub, hoping it keeps power during suspend */ - while (time_before (jiffies, ohci->next_statechange)) + if (time_before (jiffies, ohci->next_statechange)) msleep (100); #ifdef CONFIG_USB_SUSPEND (void) usb_suspend_device (hcd->self.root_hub, state); #else - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); (void) ohci_hub_suspend (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); #endif /* let things settle down a bit */ msleep (100); #ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq ((to_pci_dev(hcd->self.controller))->irq); - - { + if (_machine == _MACH_Pmac) { struct device_node *of_node; /* Disable USB PAD & cell clock */ @@ -147,7 +129,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) if (of_node) pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); } -#endif +#endif /* CONFIG_PMAC_PBOOK */ return 0; } @@ -158,7 +140,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) int retval = 0; #ifdef CONFIG_PMAC_PBOOK - { + if (_machine == _MACH_Pmac) { struct device_node *of_node; /* Re-enable USB PAD & cell clock */ @@ -166,27 +148,20 @@ static int ohci_pci_resume (struct usb_hcd *hcd) if (of_node) pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); } -#endif +#endif /* CONFIG_PMAC_PBOOK */ /* resume root hub */ - while (time_before (jiffies, ohci->next_statechange)) + if (time_before (jiffies, ohci->next_statechange)) msleep (100); #ifdef CONFIG_USB_SUSPEND /* get extra cleanup even if remote wakeup isn't in use */ retval = usb_resume_device (hcd->self.root_hub); #else - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); retval = ohci_hub_resume (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); #endif - if (retval == 0) { - hcd->self.controller->power.power_state = 0; -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (to_pci_dev(hcd->self.controller)->irq); -#endif - } return retval; } @@ -219,7 +194,6 @@ static const struct hc_driver ohci_pci_hc_driver = { * memory lifecycle (except per-request) */ .hcd_alloc = ohci_hcd_alloc, - .hcd_free = ohci_hcd_free, /* * managing i/o requests and associated device resources @@ -242,6 +216,7 @@ static const struct hc_driver ohci_pci_hc_driver = { .hub_suspend = ohci_hub_suspend, .hub_resume = ohci_hub_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ @@ -276,9 +251,9 @@ static int __init ohci_hcd_pci_init (void) if (usb_disabled()) return -ENODEV; - printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, + pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); - return pci_module_init (&ohci_pci_driver); + return pci_register_driver (&ohci_pci_driver); } module_init (ohci_hcd_pci_init); diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 74c829f92..466184846 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -35,6 +35,8 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) */ static void finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) +__releases(ohci->lock) +__acquires(ohci->lock) { // ASSERT (urb->hcpriv != 0); @@ -78,7 +80,7 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0 && hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) { ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE); - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); } } @@ -131,12 +133,12 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) unsigned i; ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & ED_ISO) ? "iso " : "", + (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "", ed, ed->branch, ed->load, ed->interval); for (i = ed->branch; i < NUM_INTS; i += ed->interval) { struct ed **prev = &ohci->periodic [i]; - u32 *prev_p = &ohci->hcca->int_table [i]; + __hc32 *prev_p = &ohci->hcca->int_table [i]; struct ed *here = *prev; /* sorting each branch by period (slow before fast) @@ -156,7 +158,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) ed->hwNextED = *prev_p; wmb (); *prev = ed; - *prev_p = cpu_to_le32p (&ed->dma); + *prev_p = cpu_to_hc32(ohci, ed->dma); wmb(); } ohci->load [i] += ed->load; @@ -193,17 +195,20 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) case PIPE_CONTROL: if (ohci->ed_controltail == NULL) { WARN_ON (ohci->hc_control & OHCI_CTRL_CLE); - writel (ed->dma, &ohci->regs->ed_controlhead); + ohci_writel (ohci, ed->dma, + &ohci->regs->ed_controlhead); } else { ohci->ed_controltail->ed_next = ed; - ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); + ohci->ed_controltail->hwNextED = cpu_to_hc32 (ohci, + ed->dma); } ed->ed_prev = ohci->ed_controltail; if (!ohci->ed_controltail && !ohci->ed_rm_list) { wmb(); ohci->hc_control |= OHCI_CTRL_CLE; - writel (0, &ohci->regs->ed_controlcurrent); - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, 0, &ohci->regs->ed_controlcurrent); + ohci_writel (ohci, ohci->hc_control, + &ohci->regs->control); } ohci->ed_controltail = ed; break; @@ -211,17 +216,19 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) case PIPE_BULK: if (ohci->ed_bulktail == NULL) { WARN_ON (ohci->hc_control & OHCI_CTRL_BLE); - writel (ed->dma, &ohci->regs->ed_bulkhead); + ohci_writel (ohci, ed->dma, &ohci->regs->ed_bulkhead); } else { ohci->ed_bulktail->ed_next = ed; - ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); + ohci->ed_bulktail->hwNextED = cpu_to_hc32 (ohci, + ed->dma); } ed->ed_prev = ohci->ed_bulktail; if (!ohci->ed_bulktail && !ohci->ed_rm_list) { wmb(); ohci->hc_control |= OHCI_CTRL_BLE; - writel (0, &ohci->regs->ed_bulkcurrent); - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, 0, &ohci->regs->ed_bulkcurrent); + ohci_writel (ohci, ohci->hc_control, + &ohci->regs->control); } ohci->ed_bulktail = ed; break; @@ -257,7 +264,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) for (i = ed->branch; i < NUM_INTS; i += ed->interval) { struct ed *temp; struct ed **prev = &ohci->periodic [i]; - u32 *prev_p = &ohci->hcca->int_table [i]; + __hc32 *prev_p = &ohci->hcca->int_table [i]; while (*prev && (temp = *prev) != ed) { prev_p = &temp->hwNextED; @@ -272,7 +279,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval; ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & ED_ISO) ? "iso " : "", + (ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "", ed, ed->branch, ed->load, ed->interval); } @@ -300,7 +307,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) */ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) { - ed->hwINFO |= ED_SKIP; + ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); wmb (); ed->state = ED_UNLINK; @@ -320,10 +327,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, + &ohci->regs->control); // a ohci_readl() later syncs CLE with the HC } else - writel (le32_to_cpup (&ed->hwNextED), + ohci_writel (ohci, + hc32_to_cpup (ohci, &ed->hwNextED), &ohci->regs->ed_controlhead); } else { ed->ed_prev->ed_next = ed->ed_next; @@ -344,10 +353,12 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, + &ohci->regs->control); // a ohci_readl() later syncs BLE with the HC } else - writel (le32_to_cpup (&ed->hwNextED), + ohci_writel (ohci, + hc32_to_cpup (ohci, &ed->hwNextED), &ohci->regs->ed_bulkhead); } else { ed->ed_prev->ed_next = ed->ed_next; @@ -416,7 +427,7 @@ static struct ed *ed_get ( goto done; } ed->dummy = td; - ed->hwTailP = cpu_to_le32 (td->td_dma); + ed->hwTailP = cpu_to_hc32 (ohci, td->td_dma); ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ ed->state = ED_IDLE; ed->type = type; @@ -431,7 +442,6 @@ static struct ed *ed_get ( info = usb_pipedevice (pipe); info |= (ep >> 1) << 7; info |= usb_maxpacket (udev, pipe, is_out) << 16; - info = cpu_to_le32 (info); if (udev->speed == USB_SPEED_LOW) info |= ED_LOWSPEED; /* only control transfers store pids in tds */ @@ -451,7 +461,7 @@ static struct ed *ed_get ( / 1000; } } - ed->hwINFO = info; + ed->hwINFO = cpu_to_hc32(ohci, info); } done: @@ -469,7 +479,7 @@ done: */ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) { - ed->hwINFO |= ED_DEQUEUE; + ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE); ed_deschedule (ohci, ed); /* rm_list is just singly linked, for simplicity */ @@ -478,17 +488,17 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) ohci->ed_rm_list = ed; /* enable SOF interrupt */ - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); + ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrstatus); + ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable); // flush those writes, and get latest HCCA contents - (void) ohci_readl (&ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); /* SF interrupt might get delayed; record the frame counter value that * indicates when the HC isn't looking at it, so concurrent unlinks * behave. frame_no wraps every 2^16 msec, and changes right before * SF is triggered. */ - ed->tick = OHCI_FRAME_NO(ohci->hcca) + 1; + ed->tick = ohci_frame_no(ohci) + 1; } @@ -540,19 +550,19 @@ td_fill (struct ohci_hcd *ohci, u32 info, if (!len) data = 0; - td->hwINFO = cpu_to_le32 (info); + td->hwINFO = cpu_to_hc32 (ohci, info); if (is_iso) { - td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); - td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); + td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000); + td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000); td->ed->last_iso = info & 0xffff; } else { - td->hwCBP = cpu_to_le32 (data); + td->hwCBP = cpu_to_hc32 (ohci, data); } if (data) - td->hwBE = cpu_to_le32 (data + len - 1); + td->hwBE = cpu_to_hc32 (ohci, data + len - 1); else td->hwBE = 0; - td->hwNextTD = cpu_to_le32 (td_pt->td_dma); + td->hwNextTD = cpu_to_hc32 (ohci, td_pt->td_dma); /* append to queue */ list_add_tail (&td->td_list, &td->ed->td_list); @@ -593,7 +603,7 @@ static void td_submit_urb ( if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out, 1); - urb_priv->ed->hwHeadP &= ~ED_C; + urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C); } urb_priv->td_cnt = 0; @@ -642,7 +652,7 @@ static void td_submit_urb ( /* maybe kickstart bulk list */ if (urb_priv->ed->type == PIPE_BULK) { wmb (); - writel (OHCI_BLF, &ohci->regs->cmdstatus); + ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus); } break; @@ -664,7 +674,7 @@ static void td_submit_urb ( td_fill (ohci, info, data, 0, urb, cnt++); /* maybe kickstart control list */ wmb (); - writel (OHCI_CLF, &ohci->regs->cmdstatus); + ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus); break; /* ISO has no retransmit, so no toggle; and it uses special TDs. @@ -693,7 +703,7 @@ static void td_submit_urb ( if (periodic) { wmb (); ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); } // ASSERT (urb_priv->length == cnt); @@ -708,14 +718,14 @@ static void td_submit_urb ( */ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) { - u32 tdINFO = le32_to_cpup (&td->hwINFO); + u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO); int cc = 0; list_del (&td->td_list); /* ISO ... drivers see per-TD length/status */ if (tdINFO & TD_ISO) { - u16 tdPSW = le16_to_cpu (td->hwPSW [0]); + u16 tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]); int dlen = 0; /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ @@ -747,16 +757,10 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) */ } else { int type = usb_pipetype (urb->pipe); - u32 tdBE = le32_to_cpup (&td->hwBE); + u32 tdBE = hc32_to_cpup (ohci, &td->hwBE); cc = TD_CC_GET (tdINFO); - /* control endpoints only have soft stalls */ - if (type != PIPE_CONTROL && cc == TD_CC_STALL) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)); - /* update packet status if needed (short is normally ok) */ if (cc == TD_DATAUNDERRUN && !(urb->transfer_flags & URB_SHORT_NOT_OK)) @@ -774,7 +778,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) urb->actual_length += tdBE - td->data_dma + 1; else urb->actual_length += - le32_to_cpup (&td->hwCBP) + hc32_to_cpup (ohci, &td->hwCBP) - td->data_dma; } @@ -795,14 +799,14 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) struct urb *urb = td->urb; struct ed *ed = td->ed; struct list_head *tmp = td->td_list.next; - u32 toggle = ed->hwHeadP & ED_C; + __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C); /* clear ed halt; this is the td that caused it, but keep it inactive * until its urb->complete() has a chance to clean up. */ - ed->hwINFO |= ED_SKIP; + ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); wmb (); - ed->hwHeadP &= ~ED_H; + ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H); /* put any later tds from this urb onto the donelist, after 'td', * order won't matter here: no errors, and nothing was transferred. @@ -810,7 +814,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) */ while (tmp != &ed->td_list) { struct td *next; - u32 info; + __hc32 info; next = list_entry (tmp, struct td, td_list); tmp = next->td_list.next; @@ -826,8 +830,8 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) * and clear ED_SKIP. */ info = next->hwINFO; - info |= cpu_to_le32 (TD_DONE); - info &= ~cpu_to_le32 (TD_CC); + info |= cpu_to_hc32 (ohci, TD_DONE); + info &= ~cpu_to_hc32 (ohci, TD_CC); next->hwINFO = info; next->next_dl_td = rev; @@ -855,7 +859,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) urb, urb->dev->devpath, usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", - le32_to_cpu (td->hwINFO), + hc32_to_cpu (ohci, td->hwINFO), cc, cc_to_error [cc]); } @@ -871,7 +875,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) struct td *td_rev = NULL; struct td *td = NULL; - td_dma = le32_to_cpup (&ohci->hcca->done_head); + td_dma = hc32_to_cpup (ohci, &ohci->hcca->done_head); ohci->hcca->done_head = 0; wmb(); @@ -887,28 +891,26 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) break; } - td->hwINFO |= cpu_to_le32 (TD_DONE); - cc = TD_CC_GET (le32_to_cpup (&td->hwINFO)); + td->hwINFO |= cpu_to_hc32 (ohci, TD_DONE); + cc = TD_CC_GET (hc32_to_cpup (ohci, &td->hwINFO)); /* Non-iso endpoints can halt on error; un-halt, * and dequeue any other TDs from this urb. * No other TD could have caused the halt. */ - if (cc != TD_CC_NOERROR && (td->ed->hwHeadP & ED_H)) + if (cc != TD_CC_NOERROR + && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H))) td_rev = ed_halted (ohci, td, cc, td_rev); td->next_dl_td = td_rev; td_rev = td; - td_dma = le32_to_cpup (&td->hwNextTD); + td_dma = hc32_to_cpup (ohci, &td->hwNextTD); } return td_rev; } /*-------------------------------------------------------------------------*/ -/* wrap-aware logic stolen from */ -#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) - /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) @@ -919,7 +921,7 @@ rescan_all: for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) { struct list_head *entry, *tmp; int completed, modified; - u32 *prev; + __hc32 *prev; /* only take off EDs that the HC isn't using, accounting for * frame counter wraps and EDs with partially retired TDs @@ -937,7 +939,8 @@ skip_ed: td = list_entry (ed->td_list.next, struct td, td_list); - head = cpu_to_le32 (ed->hwHeadP) & TD_MASK; + head = hc32_to_cpu (ohci, ed->hwHeadP) & + TD_MASK; /* INTR_WDH may need to clean up first */ if (td->td_dma != head) @@ -968,7 +971,7 @@ rescan_this: struct td *td; struct urb *urb; urb_priv_t *urb_priv; - u32 savebits; + __hc32 savebits; td = list_entry (entry, struct td, td_list); urb = td->urb; @@ -980,7 +983,7 @@ rescan_this: } /* patch pointer hc uses */ - savebits = *prev & ~cpu_to_le32 (TD_MASK); + savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK); *prev = td->hwNextTD | savebits; /* HC may have partly processed this TD */ @@ -998,10 +1001,10 @@ rescan_this: /* ED's now officially unlinked, hc doesn't see */ ed->state = ED_IDLE; - ed->hwHeadP &= ~ED_H; + ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); ed->hwNextED = 0; wmb (); - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); + ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE); /* but if there's work queued, reschedule */ if (!list_empty (&ed->td_list)) { @@ -1023,24 +1026,27 @@ rescan_this: command |= OHCI_CLF; if (!(ohci->hc_control & OHCI_CTRL_CLE)) { control |= OHCI_CTRL_CLE; - writel (0, &ohci->regs->ed_controlcurrent); + ohci_writel (ohci, 0, + &ohci->regs->ed_controlcurrent); } } if (ohci->ed_bulktail) { command |= OHCI_BLF; if (!(ohci->hc_control & OHCI_CTRL_BLE)) { control |= OHCI_CTRL_BLE; - writel (0, &ohci->regs->ed_bulkcurrent); + ohci_writel (ohci, 0, + &ohci->regs->ed_bulkcurrent); } } /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ if (control) { ohci->hc_control |= control; - writel (ohci->hc_control, &ohci->regs->control); + ohci_writel (ohci, ohci->hc_control, + &ohci->regs->control); } if (command) - writel (command, &ohci->regs->cmdstatus); + ohci_writel (ohci, command, &ohci->regs->cmdstatus); } } @@ -1080,18 +1086,19 @@ dl_done_list (struct ohci_hcd *ohci, struct pt_regs *regs) start_ed_unlink (ohci, ed); /* ... reenabling halted EDs only after fault cleanup */ - } else if ((ed->hwINFO & (ED_SKIP | ED_DEQUEUE)) == ED_SKIP) { + } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE)) + == cpu_to_hc32 (ohci, ED_SKIP)) { td = list_entry (ed->td_list.next, struct td, td_list); - if (!(td->hwINFO & TD_DONE)) { - ed->hwINFO &= ~ED_SKIP; + if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) { + ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP); /* ... hc may need waking-up */ switch (ed->type) { case PIPE_CONTROL: - writel (OHCI_CLF, + ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus); break; case PIPE_BULK: - writel (OHCI_BLF, + ohci_writel (ohci, OHCI_BLF, &ohci->regs->cmdstatus); break; } diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index c3cd76aba..5bb7fe44a 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -194,6 +194,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; + hcd->self.release = &usb_hcd_release; hcd->self.hcpriv = (void *) hcd; hcd->self.bus_name = "sa1111"; hcd->product_desc = "SA-1111 OHCI"; @@ -213,9 +214,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, err2: hcd_buffer_destroy (hcd); - if (hcd) - driver->hcd_free(hcd); err1: + kfree(hcd); sa1111_stop_hc(dev); release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); return retval; @@ -237,8 +237,6 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, */ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) { - void *base; - info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); if (in_interrupt ()) @@ -257,9 +255,6 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) usb_deregister_bus (&hcd->self); - base = hcd->regs; - hcd->driver->hcd_free (hcd); - sa1111_stop_hc(dev); release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); } @@ -272,33 +267,14 @@ ohci_sa1111_start (struct usb_hcd *hcd) struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - ohci->hcca = dma_alloc_coherent (hcd->self.controller, - sizeof *ohci->hcca, &ohci->hcca_dma, 0); - if (!ohci->hcca) - return -ENOMEM; - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); + if ((ret = ohci_init(ohci)) < 0) return ret; - } - ohci->regs = hcd->regs; - - if (hc_reset (ohci) < 0) { - ohci_stop (hcd); - return -ENODEV; - } - if (hc_start (ohci) < 0) { + if ((ret = ohci_run (ohci)) < 0) { err ("can't start %s", ohci->hcd.self.bus_name); ohci_stop (hcd); - return -EBUSY; + return ret; } - create_debug_files (ohci); - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif return 0; } @@ -327,7 +303,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = { * memory lifecycle (except per-request) */ .hcd_alloc = ohci_hcd_alloc, - .hcd_free = ohci_hcd_free, /* * managing i/o requests and associated device resources diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 5f0384417..9c3843025 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -6,6 +6,14 @@ * * This file is licenced under the GPL. */ + +/* + * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to + * __leXX (normally) or __beXX (given OHCI_BIG_ENDIAN), depending on the + * host controller implementation. + */ +typedef __u32 __bitwise __hc32; +typedef __u16 __bitwise __hc16; /* * OHCI Endpoint Descriptor (ED) ... holds TD queue @@ -15,21 +23,21 @@ * both EHCI and UHCI call similar structures a "QH". */ struct ed { - /* first fields are hardware-specified, le32 */ - __u32 hwINFO; /* endpoint config bitmap */ + /* first fields are hardware-specified */ + __hc32 hwINFO; /* endpoint config bitmap */ /* info bits defined by hcd */ -#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27) +#define ED_DEQUEUE (1 << 27) /* info bits defined by the hardware */ -#define ED_ISO __constant_cpu_to_le32(1 << 15) -#define ED_SKIP __constant_cpu_to_le32(1 << 14) -#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13) -#define ED_OUT __constant_cpu_to_le32(0x01 << 11) -#define ED_IN __constant_cpu_to_le32(0x02 << 11) - __u32 hwTailP; /* tail of TD list */ - __u32 hwHeadP; /* head of TD list (hc r/w) */ -#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */ -#define ED_H __constant_cpu_to_le32(0x01) /* halted */ - __u32 hwNextED; /* next ED in list */ +#define ED_ISO (1 << 15) +#define ED_SKIP (1 << 14) +#define ED_LOWSPEED (1 << 13) +#define ED_OUT (0x01 << 11) +#define ED_IN (0x02 << 11) + __hc32 hwTailP; /* tail of TD list */ + __hc32 hwHeadP; /* head of TD list (hc r/w) */ +#define ED_C (0x02) /* toggle carry */ +#define ED_H (0x01) /* halted */ + __hc32 hwNextED; /* next ED in list */ /* rest are purely for the driver's use */ dma_addr_t dma; /* addr of ED */ @@ -42,7 +50,6 @@ struct ed { /* create --> IDLE --> OPER --> ... --> IDLE --> destroy * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... - * some special cases : OPER --> IDLE ... */ u8 state; /* ED_{IDLE,UNLINK,OPER} */ #define ED_IDLE 0x00 /* NOT linked to HC */ @@ -70,8 +77,8 @@ struct ed { * and 4.3.2 (iso) */ struct td { - /* first fields are hardware-specified, le32 */ - __u32 hwINFO; /* transfer info bitmask */ + /* first fields are hardware-specified */ + __hc32 hwINFO; /* transfer info bitmask */ /* hwINFO bits for both general and iso tds: */ #define TD_CC 0xf0000000 /* condition code */ @@ -100,13 +107,13 @@ struct td { /* (no hwINFO #defines yet for iso tds) */ - __u32 hwCBP; /* Current Buffer Pointer (or 0) */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ + __hc32 hwCBP; /* Current Buffer Pointer (or 0) */ + __hc32 hwNextTD; /* Next TD Pointer */ + __hc32 hwBE; /* Memory Buffer End Pointer */ /* PSW is only for ISO */ #define MAXPSW 1 /* hardware allows 8 */ - __u16 hwPSW [MAXPSW]; + __hc16 hwPSW [MAXPSW]; /* rest are purely for the driver's use */ __u8 index; @@ -171,20 +178,20 @@ static const int cc_to_error [16] = { */ struct ohci_hcca { #define NUM_INTS 32 - __u32 int_table [NUM_INTS]; /* periodic schedule */ + __hc32 int_table [NUM_INTS]; /* periodic schedule */ /* * OHCI defines u16 frame_no, followed by u16 zero pad. * Since some processors can't do 16 bit bus accesses, * portable access must be a 32 bit byteswapped access. */ - u32 frame_no; /* current frame number */ -#define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no)) - __u32 done_head; /* info returned for an interrupt */ + __hc32 frame_no; /* current frame number */ + __hc32 done_head; /* info returned for an interrupt */ u8 reserved_for_hc [116]; u8 what [4]; /* spec only identifies 252 bytes :) */ } __attribute__ ((aligned(256))); +#define ohci_frame_no(ohci) ((u16)hc32_to_cpup(ohci,&(ohci)->hcca->frame_no)) /* * This is the structure of the OHCI controller's memory mapped I/O region. @@ -193,36 +200,36 @@ struct ohci_hcca { */ struct ohci_regs { /* control and status registers (section 7.1) */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; + __hc32 revision; + __hc32 control; + __hc32 cmdstatus; + __hc32 intrstatus; + __hc32 intrenable; + __hc32 intrdisable; /* memory pointers (section 7.2) */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; + __hc32 hcca; + __hc32 ed_periodcurrent; + __hc32 ed_controlhead; + __hc32 ed_controlcurrent; + __hc32 ed_bulkhead; + __hc32 ed_bulkcurrent; + __hc32 donehead; /* frame counters (section 7.3) */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; + __hc32 fminterval; + __hc32 fmremaining; + __hc32 fmnumber; + __hc32 periodicstart; + __hc32 lsthresh; /* Root hub ports (section 7.4) */ struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; + __hc32 a; + __hc32 b; + __hc32 status; #define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */ - __u32 portstatus [MAX_ROOT_PORTS]; + __hc32 portstatus [MAX_ROOT_PORTS]; } roothub; /* and optional "legacy support" registers (appendix B) at 0x0100 */ @@ -338,12 +345,17 @@ typedef struct urb_priv { */ struct ohci_hcd { + /* + * framework state + */ + struct usb_hcd hcd; /* must come first! */ + spinlock_t lock; /* * I/O memory used to communicate with the HC (dma-consistent) */ - struct ohci_regs *regs; + struct ohci_regs __iomem *regs; /* * main memory used to communicate with the HC (dma-consistent). @@ -359,6 +371,13 @@ struct ohci_hcd { struct ed *ed_controltail; /* last in ctrl list */ struct ed *periodic [NUM_INTS]; /* shadow int_table */ + /* + * OTG controllers and transceivers need software interaction; + * other external transceivers should be software-transparent + */ + struct otg_transceiver *transceiver; + unsigned power_budget; + /* * memory management for queue data structures */ @@ -380,36 +399,16 @@ struct ohci_hcd { unsigned long flags; /* for HC bugs */ #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ +#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ +#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */ // there are also chip quirks/bugs in init logic - /* - * framework state - */ - struct usb_hcd hcd; }; #define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd) /*-------------------------------------------------------------------------*/ -static inline void disable (struct ohci_hcd *ohci) -{ - ohci->hcd.state = USB_STATE_HALT; -} - -#define FI 0x2edf /* 12000 bits per frame (-1) */ -#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI) -#define LSTHRESH 0x628 /* lowspeed bit threshold */ - -static inline void periodic_reinit (struct ohci_hcd *ohci) -{ - writel (ohci->fminterval, &ohci->regs->fminterval); - writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart); - writel (LSTHRESH, &ohci->regs->lsthresh); -} - -/*-------------------------------------------------------------------------*/ - #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ @@ -429,22 +428,164 @@ static inline void periodic_reinit (struct ohci_hcd *ohci) # define ohci_vdbg(ohci, fmt, args...) do { } while (0) #endif +/*-------------------------------------------------------------------------*/ + +/* + * While most USB host controllers implement their registers and + * in-memory communication descriptors in little-endian format, + * a minority (notably the IBM STB04XXX and the Motorola MPC5200 + * processors) implement them in big endian format. + * + * This attempts to support either format at compile time without a + * runtime penalty, or both formats with the additional overhead + * of checking a flag bit. + */ + +#ifdef CONFIG_USB_OHCI_BIG_ENDIAN + +#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN +#define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */ +#else +#define big_endian(ohci) 1 /* only big endian */ +#endif + +/* + * Big-endian read/write functions are arch-specific. + * Other arches can be added if/when they're needed. + */ +#if defined(CONFIG_PPC) +#define readl_be(addr) in_be32((__force unsigned *)addr) +#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) +#endif + +static inline unsigned int ohci_readl (const struct ohci_hcd *ohci, + __hc32 __iomem * regs) +{ + return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs); +} + +static inline void ohci_writel (const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) +{ + big_endian(ohci) ? writel_be (val, regs) : + writel (val, (__force u32 *)regs); +} + +#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */ + +#define big_endian(ohci) 0 /* only little endian */ + #ifdef CONFIG_ARCH_LH7A404 /* Marc Singer: at the time this code was written, the LH7A404 * had a problem reading the USB host registers. This * implementation of the ohci_readl function performs the read * twice as a work-around. */ -static inline unsigned int ohci_readl (void* regs) +static inline unsigned int +ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs) { - *(volatile unsigned int*) regs; - return *(volatile unsigned int*) regs; + *(volatile __force unsigned int*) regs; + return *(volatile __force unsigned int*) regs; } #else /* Standard version of ohci_readl uses standard, platform * specific implementation. */ -static inline unsigned int ohci_readl (void* regs) +static inline unsigned int +ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs) { - return readl (regs); + return readl(regs); } #endif + +static inline void ohci_writel (const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) +{ + writel (val, regs); +} + +#endif /* !CONFIG_USB_OHCI_BIG_ENDIAN */ + +/*-------------------------------------------------------------------------*/ + +/* cpu to ohci */ +static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x) +{ + return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x); +} + +static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x) +{ + return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x); +} + +static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x) +{ + return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x); +} + +static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x) +{ + return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x); +} + +/* ohci to cpu */ +static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x) +{ + return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x); +} + +static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x) +{ + return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x); +} + +static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x) +{ + return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x); +} + +static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) +{ + return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x); +} + +/*-------------------------------------------------------------------------*/ + +static inline void disable (struct ohci_hcd *ohci) +{ + ohci->hcd.state = USB_STATE_HALT; +} + +#define FI 0x2edf /* 12000 bits per frame (-1) */ +#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) +#define LSTHRESH 0x628 /* lowspeed bit threshold */ + +static inline void periodic_reinit (struct ohci_hcd *ohci) +{ + u32 fi = ohci->fminterval & 0x0ffff; + + ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff, + &ohci->regs->periodicstart); +} + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define read_roothub(hc, register, mask) ({ \ + u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \ + if (temp == -1) \ + disable (hc); \ + else if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = ohci_readl (hc, &hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci_hcd *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci_hcd *hc) + { return ohci_readl (hc, &hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci_hcd *hc) + { return ohci_readl (hc, &hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci_hcd *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index a0721d060..baf744441 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -34,17 +34,6 @@ static inline void lprintk(char *buf) } } -static inline int uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (qh == uhci->skelqh[i]) - return 1; - - return 0; -} - static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) { char *out = buf; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index bf8ab3cd7..614403bbf 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -51,8 +51,8 @@ #include #include #include +#include -#include #include #include #include @@ -82,7 +82,7 @@ static int debug = 1; #else static int debug = 0; #endif -MODULE_PARM(debug, "i"); +module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level"); static char *errbuf; #define ERRBUF_LEN (32 * 1024) @@ -92,7 +92,7 @@ static char *errbuf; static kmem_cache_t *uhci_up_cachep; /* urb_priv */ -static int uhci_get_current_frame_number(struct uhci_hcd *uhci); +static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci); static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); @@ -174,7 +174,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status, */ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) { - framenum %= UHCI_NUMFRAMES; + framenum &= (UHCI_NUMFRAMES - 1); td->frame = framenum; @@ -230,42 +230,22 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) } /* - * Inserts a td into qh list at the top. + * Inserts a td list into qh. */ -static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 breadth) +static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth) { - struct list_head *tmp, *head; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td, *ptd; - - if (list_empty(&urbp->td_list)) - return; - - head = &urbp->td_list; - tmp = head->next; + struct uhci_td *td; + u32 *plink; /* Ordering isn't important here yet since the QH hasn't been */ - /* inserted into the schedule yet */ - td = list_entry(tmp, struct uhci_td, list); - - /* Add the first TD to the QH element pointer */ - qh->element = cpu_to_le32(td->dma_handle) | breadth; - - ptd = td; - - /* Then link the rest of the TD's */ - tmp = tmp->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - ptd->link = cpu_to_le32(td->dma_handle) | breadth; - - ptd = td; + /* inserted into the schedule yet */ + plink = &qh->element; + list_for_each_entry(td, &urbp->td_list, list) { + *plink = cpu_to_le32(td->dma_handle) | breadth; + plink = &td->link; } - - ptd->link = UHCI_PTR_TERM; + *plink = UHCI_PTR_TERM; } static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) @@ -330,7 +310,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *tmp; + struct urb_priv *turbp; struct uhci_qh *lqh; /* Grab the last QH */ @@ -358,12 +338,8 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct */ lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; if (lqh->urbp) { - list_for_each (tmp, &lqh->urbp->queue_list) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - + list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list) turbp->qh->link = lqh->link; - } } list_add_tail(&urbp->qh->list, &skelqh->list); @@ -376,7 +352,7 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { struct uhci_qh *pqh; - u32 newlink; + __le32 newlink; unsigned int age; if (!qh) @@ -405,18 +381,11 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) pqh = list_entry(qh->list.prev, struct uhci_qh, list); pqh->link = newlink; if (pqh->urbp) { - struct list_head *head, *tmp; - - head = &pqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; + struct urb_priv *turbp; + list_for_each_entry(turbp, &pqh->urbp->queue_list, + queue_list) turbp->qh->link = newlink; - } } wmb(); @@ -447,21 +416,14 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - - head = &urbp->td_list; - tmp = head->next; - while (head != tmp) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; + struct uhci_td *td; + list_for_each_entry(td, &urbp->td_list, list) { if (toggle) td->token |= cpu_to_le32(TD_TOKEN_TOGGLE); else td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE); - toggle ^= 1; } @@ -473,30 +435,19 @@ static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb) { struct urb_priv *eurbp, *urbp, *furbp, *lurbp; - struct list_head *tmp; struct uhci_td *lltd; eurbp = eurb->hcpriv; urbp = urb->hcpriv; /* Find the first URB in the queue */ + furbp = eurbp; if (eurbp->queued) { - struct list_head *head = &eurbp->queue_list; - - tmp = head->next; - while (tmp != head) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - if (!turbp->queued) + list_for_each_entry(furbp, &eurbp->queue_list, queue_list) + if (!furbp->queued) break; + } - tmp = tmp->next; - } - } else - tmp = &eurbp->queue_list; - - furbp = list_entry(tmp, struct urb_priv, queue_list); lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); @@ -522,9 +473,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) { - struct urb_priv *urbp, *nurbp; - struct list_head *head, *tmp; - struct urb_priv *purbp; + struct urb_priv *urbp, *nurbp, *purbp, *turbp; struct uhci_td *pltd; unsigned int toggle; @@ -556,14 +505,7 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) toggle = uhci_toggle(td_token(pltd)) ^ 1; } - head = &urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp; - - turbp = list_entry(tmp, struct urb_priv, queue_list); - tmp = tmp->next; - + list_for_each_entry(turbp, &urbp->queue_list, queue_list) { if (!turbp->queued) break; toggle = uhci_fixup_toggle(turbp->urb, toggle); @@ -637,7 +579,7 @@ static void uhci_remove_td_from_urb(struct uhci_td *td) static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) { - struct list_head *head, *tmp; + struct uhci_td *td, *tmp; struct urb_priv *urbp; unsigned int age; @@ -660,13 +602,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) if (list_empty(&uhci->td_remove_list)) uhci_set_next_interrupt(uhci); - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - + list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { uhci_remove_td_from_urb(td); uhci_remove_td(uhci, td); list_add(&td->remove_list, &uhci->td_remove_list); @@ -829,8 +765,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); - /* Low-speed transfers get a different queue, and won't hog the bus */ - if (urb->dev->speed == USB_SPEED_LOW) + /* Low-speed transfers get a different queue, and won't hog the bus. + * Also, some devices enumerate better without FSBR; the easiest way + * to do that is to put URBs on the low-speed queue while the device + * is in the DEFAULT state. */ + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->state == USB_STATE_DEFAULT) skelqh = uhci->skel_ls_control_qh; else { skelqh = uhci->skel_fs_control_qh; @@ -1083,7 +1023,6 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb */ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) { - struct list_head *tmp, *head; struct urb_priv *urbp = urb->hcpriv; struct uhci_td *td; unsigned int status = 0; @@ -1091,13 +1030,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) urb->actual_length = 0; - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - + list_for_each_entry(td, &urbp->td_list, list) { status = uhci_status_bits(td_status(td)); if (status & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -1120,10 +1053,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) td_error: ret = uhci_map_status(status, uhci_packetout(td_token(td))); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td))); err: /* @@ -1180,17 +1109,12 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) { struct urb *last_urb = NULL; - struct list_head *tmp, *head; + struct urb_priv *up; int ret = 0; - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); + list_for_each_entry(up, &uhci->urb_list, urb_list) { struct urb *u = up->urb; - tmp = tmp->next; - /* look for pending URB's with identical pipe handle */ if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS) && (u != urb)) { @@ -1221,15 +1145,14 @@ static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) limits = isochronous_find_limits(uhci, urb, &start, &end); if (urb->transfer_flags & URB_ISO_ASAP) { - if (limits) { - int curframe; - - curframe = uhci_get_current_frame_number(uhci) % UHCI_NUMFRAMES; - urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES; - } else + if (limits) + urb->start_frame = + (uhci_get_current_frame_number(uhci) + + 10) & (UHCI_NUMFRAMES - 1); + else urb->start_frame = end; } else { - urb->start_frame %= UHCI_NUMFRAMES; + urb->start_frame &= (UHCI_NUMFRAMES - 1); /* FIXME: Sanity check */ } @@ -1276,7 +1199,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) { - struct list_head *tmp, *head; + struct uhci_td *td; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; int status; int i, ret = 0; @@ -1284,14 +1207,9 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) urb->actual_length = 0; i = 0; - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); + list_for_each_entry(td, &urbp->td_list, list) { int actlength; - tmp = tmp->next; - if (td_status(td) & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -1315,20 +1233,15 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) { - struct list_head *tmp, *head; + struct urb_priv *up; /* We don't match Isoc transfers since they are special */ if (usb_pipeisoc(urb->pipe)) return NULL; - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); + list_for_each_entry(up, &uhci->urb_list, urb_list) { struct urb *u = up->urb; - tmp = tmp->next; - if (u->dev == urb->dev && u->status == -EINPROGRESS) { /* For control, ignore the direction */ if (usb_pipecontrol(urb->pipe) && @@ -1344,7 +1257,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) { - int ret = -EINVAL; + int ret; struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb *eurb; @@ -1352,7 +1265,8 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) spin_lock_irqsave(&uhci->schedule_lock, flags); - if (urb->status != -EINPROGRESS) /* URB already unlinked! */ + ret = urb->status; + if (ret != -EINPROGRESS) /* URB already unlinked! */ goto out; eurb = uhci_find_urb_ep(uhci, urb); @@ -1478,9 +1392,10 @@ out: static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) { - struct list_head *head, *tmp; + struct list_head *head; + struct uhci_td *td; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int prevactive = 1; + int prevactive = 0; uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ @@ -1488,25 +1403,28 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) * Now we need to find out what the last successful toggle was * so we can update the local data toggle for the next transfer * - * There's 3 way's the last successful completed TD is found: + * There are 2 ways the last successful completed TD is found: * * 1) The TD is NOT active and the actual length < expected length * 2) The TD is NOT active and it's the last TD in the chain + * + * and a third way the first uncompleted TD is found: + * * 3) The TD is active and the previous TD is NOT active * * Control and Isochronous ignore the toggle, so this is safe * for all types + * + * FIXME: The toggle fixups won't be 100% reliable until we + * change over to using a single queue for each endpoint and + * stop the queue before unlinking. */ head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - + list_for_each_entry(td, head, list) { if (!(td_status(td) & TD_CTRL_ACTIVE) && - (uhci_actual_length(td_status(td)) < uhci_expected_length(td_token(td)) || - tmp == head)) + (uhci_actual_length(td_status(td)) < + uhci_expected_length(td_token(td)) || + td->list.next == head)) usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), uhci_packetout(td_token(td)), uhci_toggle(td_token(td)) ^ 1); @@ -1559,7 +1477,8 @@ done: static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; + struct list_head *head; + struct uhci_td *td; int count = 0; uhci_dec_fsbr(uhci, urb); @@ -1573,18 +1492,14 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) */ head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - + list_for_each_entry(td, head, list) { /* * Make sure we don't do the last one (since it'll have the * TERM bit set) as well as we skip every so many TD's to * make sure it doesn't hog the bandwidth */ - if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1)) + if (td->list.next != head && (count % DEPTH_INTERVAL) == + (DEPTH_INTERVAL - 1)) td->link |= UHCI_PTR_DEPTH; count++; @@ -1598,7 +1513,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) * * returns the current frame number for a USB bus/controller. */ -static int uhci_get_current_frame_number(struct uhci_hcd *uhci) +static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci) { return inw(uhci->io_addr + USBFRNUM); } @@ -1609,12 +1524,10 @@ static void stall_callback(unsigned long ptr) { struct usb_hcd *hcd = (struct usb_hcd *)ptr; struct uhci_hcd *uhci = hcd_to_uhci(hcd); - struct list_head list, *tmp, *head; + struct urb_priv *up; unsigned long flags; int called_uhci_finish_completion = 0; - INIT_LIST_HEAD(&list); - spin_lock_irqsave(&uhci->schedule_lock, flags); if (!list_empty(&uhci->urb_remove_list) && uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) { @@ -1623,27 +1536,15 @@ static void stall_callback(unsigned long ptr) called_uhci_finish_completion = 1; } - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); + list_for_each_entry(up, &uhci->urb_list, urb_list) { struct urb *u = up->urb; - tmp = tmp->next; - spin_lock(&u->lock); /* Check if the FSBR timed out */ if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) uhci_fsbr_timeout(uhci, u); - /* Check if the URB timed out */ - if (u->timeout && u->status == -EINPROGRESS && - time_after_eq(jiffies, up->inserttime + u->timeout)) { - u->status = -ETIMEDOUT; - list_move_tail(&up->urb_list, &list); - } - spin_unlock(&u->lock); } spin_unlock_irqrestore(&uhci->schedule_lock, flags); @@ -1652,17 +1553,6 @@ static void stall_callback(unsigned long ptr) if (called_uhci_finish_completion) wake_up_all(&uhci->waitqh); - head = &list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); - struct urb *u = up->urb; - - tmp = tmp->next; - - uhci_urb_dequeue(hcd, u); - } - /* Really disable FSBR */ if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { uhci->fsbrtimeout = 0; @@ -1671,6 +1561,8 @@ static void stall_callback(unsigned long ptr) /* Poll for and perform state transitions */ hc_state_transitions(uhci); + if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) + uhci_check_resume(uhci); init_stall_timer(hcd); } @@ -1690,15 +1582,9 @@ static int init_stall_timer(struct usb_hcd *hcd) static void uhci_free_pending_qhs(struct uhci_hcd *uhci) { - struct list_head *tmp, *head; - - head = &uhci->qh_remove_list; - tmp = head->next; - while (tmp != head) { - struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list); - - tmp = tmp->next; + struct uhci_qh *qh, *tmp; + list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) { list_del_init(&qh->remove_list); uhci_free_qh(uhci, qh); @@ -1707,22 +1593,19 @@ static void uhci_free_pending_qhs(struct uhci_hcd *uhci) static void uhci_free_pending_tds(struct uhci_hcd *uhci) { - struct list_head *tmp, *head; - - head = &uhci->td_remove_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, remove_list); - - tmp = tmp->next; + struct uhci_td *td, *tmp; + list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) { list_del_init(&td->remove_list); uhci_free_td(uhci, td); } } -static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) +static void +uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) +__releases(uhci->schedule_lock) +__acquires(uhci->schedule_lock) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); @@ -1736,19 +1619,13 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - struct list_head *tmp, *head; + struct urb_priv *urbp, *tmp; - head = &uhci->complete_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); + list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) { struct urb *urb = urbp->urb; list_del_init(&urbp->urb_list); uhci_finish_urb(hcd, urb, regs); - - head = &uhci->complete_list; - tmp = head->next; } } @@ -1764,7 +1641,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long io_addr = uhci->io_addr; unsigned short status; - struct list_head *tmp, *head; + struct urb_priv *urbp, *tmp; unsigned int age; /* @@ -1811,15 +1688,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) else uhci_set_next_interrupt(uhci); - /* Walk the list of pending URB's to see which ones completed */ - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); + /* Walk the list of pending URBs to see which ones completed + * (must be _safe because uhci_transfer_result() dequeues URBs) */ + list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { struct urb *urb = urbp->urb; - tmp = tmp->next; - /* Checks the status and does all of the magic necessary */ uhci_transfer_result(uhci, urb); } @@ -1981,10 +1854,10 @@ static void hc_state_transitions(struct uhci_hcd *uhci) } } -static void start_hc(struct uhci_hcd *uhci) +static int start_hc(struct uhci_hcd *uhci) { unsigned long io_addr = uhci->io_addr; - int timeout = 1000; + int timeout = 10; /* * Reset the HC - this will force us to get a @@ -1994,10 +1867,11 @@ static void start_hc(struct uhci_hcd *uhci) */ outw(USBCMD_HCRESET, io_addr + USBCMD); while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { - if (!--timeout) { + if (--timeout < 0) { dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); - break; + return -ETIMEDOUT; } + msleep(1); } /* Turn on PIRQ and all interrupts */ @@ -2016,6 +1890,7 @@ static void start_hc(struct uhci_hcd *uhci) outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); uhci->hcd.state = USB_STATE_RUNNING; + return 0; } /* @@ -2258,7 +2133,8 @@ static int uhci_start(struct usb_hcd *hcd) irq = 7; /* Only place we don't use the frame list routines */ - uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle); + uhci->fl->frame[i] = UHCI_PTR_QH | + cpu_to_le32(uhci->skelqh[irq]->dma_handle); } /* @@ -2266,7 +2142,8 @@ static int uhci_start(struct usb_hcd *hcd) * the memory writes above before the I/O transfers in start_hc(). */ mb(); - start_hc(uhci); + if ((retval = start_hc(uhci)) != 0) + goto err_alloc_skelqh; init_stall_timer(hcd); @@ -2372,6 +2249,7 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state) static int uhci_resume(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + int rc; pci_set_master(to_pci_dev(uhci_dev(uhci))); @@ -2394,7 +2272,8 @@ static int uhci_resume(struct usb_hcd *hcd) USBLEGSUP_DEFAULT); } else { reset_hc(uhci); - start_hc(uhci); + if ((rc = start_hc(uhci)) != 0) + return rc; } uhci->hcd.state = USB_STATE_RUNNING; return 0; @@ -2414,11 +2293,6 @@ static struct usb_hcd *uhci_hcd_alloc(void) return &uhci->hcd; } -static void uhci_hcd_free(struct usb_hcd *hcd) -{ - kfree(hcd_to_uhci(hcd)); -} - /* Are there any URBs for a particular device/endpoint on a given list? */ static int urbs_for_ep_list(struct list_head *head, struct hcd_dev *hdev, int ep) @@ -2483,7 +2357,6 @@ static const struct hc_driver uhci_driver = { .stop = uhci_stop, .hcd_alloc = uhci_hcd_alloc, - .hcd_free = uhci_hcd_free, .urb_enqueue = uhci_urb_enqueue, .urb_dequeue = uhci_urb_dequeue, @@ -2543,7 +2416,7 @@ static int __init uhci_hcd_init(void) if (!uhci_up_cachep) goto up_failed; - retval = pci_module_init(&uhci_pci_driver); + retval = pci_register_driver(&uhci_pci_driver); if (retval) goto init_failed; diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index b4bf3b6ca..e8fc0d64e 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -80,7 +80,7 @@ #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ struct uhci_frame_list { - u32 frame[UHCI_NUMFRAMES]; + __le32 frame[UHCI_NUMFRAMES]; void *frame_cpu[UHCI_NUMFRAMES]; @@ -105,8 +105,8 @@ struct urb_priv; */ struct uhci_qh { /* Hardware fields */ - u32 link; /* Next queue */ - u32 element; /* Queue element pointer */ + __le32 link; /* Next queue */ + __le32 element; /* Queue element pointer */ /* Software fields */ dma_addr_t dma_handle; @@ -185,10 +185,10 @@ struct uhci_qh { */ struct uhci_td { /* Hardware fields */ - u32 link; - u32 status; - u32 token; - u32 buffer; + __le32 link; + __le32 status; + __le32 token; + __le32 buffer; /* Software fields */ dma_addr_t dma_handle; @@ -324,7 +324,7 @@ enum uhci_state { * a subset of what the full implementation needs. */ struct uhci_hcd { - struct usb_hcd hcd; + struct usb_hcd hcd; /* must come first! */ #ifdef CONFIG_PROC_FS /* procfs */ @@ -352,6 +352,12 @@ struct uhci_hcd { int resume_detect; /* Need a Global Resume */ unsigned int saved_framenumber; /* Save during PM suspend */ + /* Support for port suspend/resume */ + unsigned long port_c_suspend; /* Bit-arrays of ports */ + unsigned long suspended_ports; + unsigned long resuming_ports; + unsigned long resume_timeout; /* Time to stop signalling */ + /* Main list of URB's currently controlled by this HC */ struct list_head urb_list; /* P: uhci->schedule_lock */ @@ -385,12 +391,12 @@ struct urb_priv { struct uhci_qh *qh; /* QH for this URB */ struct list_head td_list; /* P: urb->lock */ - int fsbr : 1; /* URB turned on FSBR */ - int fsbr_timeout : 1; /* URB timed out on FSBR */ - int queued : 1; /* QH was queued (not linked in) */ - int short_control_packet : 1; /* If we get a short packet during */ - /* a control transfer, retrigger */ - /* the status phase */ + unsigned fsbr : 1; /* URB turned on FSBR */ + unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ + unsigned queued : 1; /* QH was queued (not linked in) */ + unsigned short_control_packet : 1; /* If we get a short packet during */ + /* a control transfer, retrigger */ + /* the status phase */ unsigned long inserttime; /* In jiffies */ unsigned long fsbrtime; /* In jiffies */ diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 2dde38163..1feccf2f0 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -36,14 +36,16 @@ static __u8 root_hub_hub_des[] = static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long io_addr = uhci->io_addr; - int i; + int port; *buf = 0; - for (i = 0; i < uhci->rh_numports; i++) { - if (inw(io_addr + USBPORTSC1 + i * 2) & RWC_BITS) - *buf |= (1 << (i + 1)); + for (port = 0; port < uhci->rh_numports; ++port) { + if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) || + test_bit(port, &uhci->port_c_suspend)) + *buf |= (1 << (port + 1)); } + if (*buf && uhci->state == UHCI_SUSPENDED) + uhci->resume_detect = 1; return !!*buf; } @@ -62,31 +64,73 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) status &= ~(RWC_BITS|WZ_BITS); \ outw(status, port_addr) +/* UHCI controllers don't automatically stop resume signalling after 20 msec, + * so we have to poll and check timeouts in order to take care of it. + * FIXME: Synchronize access to these fields by a spinlock. + */ +static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, + unsigned long port_addr) +{ + int status; + + if (test_bit(port, &uhci->suspended_ports)) { + CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); + clear_bit(port, &uhci->suspended_ports); + clear_bit(port, &uhci->resuming_ports); + set_bit(port, &uhci->port_c_suspend); + + /* The controller won't actually turn off the RD bit until + * it has had a chance to send a low-speed EOP sequence, + * which takes 3 bit times (= 2 microseconds). We'll delay + * slightly longer for good luck. */ + udelay(4); + } +} + +static void uhci_check_resume(struct uhci_hcd *uhci) +{ + unsigned int port; + unsigned long port_addr; + + for (port = 0; port < uhci->rh_numports; ++port) { + port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; + if (unlikely(inw(port_addr) & USBPORTSC_RD)) { + if (!test_bit(port, &uhci->resuming_ports)) { + + /* Port received a wakeup request */ + set_bit(port, &uhci->resuming_ports); + uhci->resume_timeout = jiffies + + msecs_to_jiffies(20); + } else if (time_after_eq(jiffies, + uhci->resume_timeout)) { + uhci_finish_suspend(uhci, port, port_addr); + } + } + } +} /* size of returned buffer is part of USB spec */ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int status, retval = 0, len = 0; - unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * (wIndex-1); - __u16 wPortChange, wPortStatus; + int status, lstatus, retval = 0, len = 0; + unsigned int port = wIndex - 1; + unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; + u16 wPortChange, wPortStatus; switch (typeReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ case GetHubStatus: - *(__u32 *)buf = cpu_to_le32(0); + *(__le32 *)buf = cpu_to_le32(0); OK(4); /* hub power */ case GetPortStatus: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; + + if (uhci->resuming_ports) + uhci_check_resume(uhci); + status = inw(port_addr); /* Intel controllers report the OverCurrent bit active on. @@ -97,37 +141,46 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, PCI_VENDOR_ID_VIA) status ^= USBPORTSC_OC; - /* UHCI doesn't support C_SUSPEND and C_RESET (always false) */ - wPortChange = 0; + /* UHCI doesn't support C_RESET (always false) */ + wPortChange = lstatus = 0; if (status & USBPORTSC_CSC) - wPortChange |= 1 << (USB_PORT_FEAT_C_CONNECTION - 16); + wPortChange |= USB_PORT_STAT_C_CONNECTION; if (status & USBPORTSC_PEC) - wPortChange |= 1 << (USB_PORT_FEAT_C_ENABLE - 16); + wPortChange |= USB_PORT_STAT_C_ENABLE; if (status & USBPORTSC_OCC) - wPortChange |= 1 << (USB_PORT_FEAT_C_OVER_CURRENT - 16); + wPortChange |= USB_PORT_STAT_C_OVERCURRENT; + + if (test_bit(port, &uhci->port_c_suspend)) { + wPortChange |= USB_PORT_STAT_C_SUSPEND; + lstatus |= 1; + } + if (test_bit(port, &uhci->suspended_ports)) + lstatus |= 2; + if (test_bit(port, &uhci->resuming_ports)) + lstatus |= 4; /* UHCI has no power switching (always on) */ - wPortStatus = 1 << USB_PORT_FEAT_POWER; + wPortStatus = USB_PORT_STAT_POWER; if (status & USBPORTSC_CCS) - wPortStatus |= 1 << USB_PORT_FEAT_CONNECTION; + wPortStatus |= USB_PORT_STAT_CONNECTION; if (status & USBPORTSC_PE) { - wPortStatus |= 1 << USB_PORT_FEAT_ENABLE; + wPortStatus |= USB_PORT_STAT_ENABLE; if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) - wPortStatus |= 1 << USB_PORT_FEAT_SUSPEND; + wPortStatus |= USB_PORT_STAT_SUSPEND; } if (status & USBPORTSC_OC) - wPortStatus |= 1 << USB_PORT_FEAT_OVER_CURRENT; + wPortStatus |= USB_PORT_STAT_OVERCURRENT; if (status & USBPORTSC_PR) - wPortStatus |= 1 << USB_PORT_FEAT_RESET; + wPortStatus |= USB_PORT_STAT_RESET; if (status & USBPORTSC_LSDA) - wPortStatus |= 1 << USB_PORT_FEAT_LOWSPEED; + wPortStatus |= USB_PORT_STAT_LOW_SPEED; if (wPortChange) - dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n", - wIndex, status); + dev_dbg(uhci_dev(uhci), "port %d portsc %04x,%02x\n", + wIndex, status, lstatus); - *(__u16 *)buf = cpu_to_le16(wPortStatus); - *(__u16 *)(buf + 2) = cpu_to_le16(wPortChange); + *(__le16 *)buf = cpu_to_le16(wPortStatus); + *(__le16 *)(buf + 2) = cpu_to_le16(wPortChange); OK(4); case SetHubFeature: /* We don't implement these */ case ClearHubFeature: @@ -140,11 +193,12 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } break; case SetPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; switch (wValue) { case USB_PORT_FEAT_SUSPEND: + set_bit(port, &uhci->suspended_ports); SET_RH_PORTSTAT(USBPORTSC_SUSP); OK(0); case USB_PORT_FEAT_RESET: @@ -152,6 +206,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, mdelay(50); /* USB v1.1 7.1.7.3 */ CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); + + /* Reset terminates Resume signalling */ + uhci_finish_suspend(uhci, port, port_addr); SET_RH_PORTSTAT(USBPORTSC_PE); mdelay(10); CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC); @@ -164,21 +221,38 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } break; case ClearPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; switch (wValue) { case USB_PORT_FEAT_ENABLE: CLR_RH_PORTSTAT(USBPORTSC_PE); + + /* Disable terminates Resume signalling */ + uhci_finish_suspend(uhci, port, port_addr); OK(0); case USB_PORT_FEAT_C_ENABLE: CLR_RH_PORTSTAT(USBPORTSC_PEC); OK(0); case USB_PORT_FEAT_SUSPEND: - CLR_RH_PORTSTAT(USBPORTSC_SUSP); + if (test_bit(port, &uhci->suspended_ports) && + !test_and_set_bit(port, + &uhci->resuming_ports)) { + uhci->resume_timeout = jiffies + + msecs_to_jiffies(20); + SET_RH_PORTSTAT(USBPORTSC_RD); + + /* The controller won't allow RD to be set + * if the port is disabled. When this happens + * just skip the Resume signalling. + */ + if (!(inw(port_addr) & USBPORTSC_RD)) + uhci_finish_suspend(uhci, port, + port_addr); + } OK(0); case USB_PORT_FEAT_C_SUSPEND: - /* this driver won't report these */ + clear_bit(port, &uhci->port_c_suspend); OK(0); case USB_PORT_FEAT_POWER: /* UHCI has no power switching */ diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig index 0b0f80e4f..b541b67d2 100644 --- a/drivers/usb/image/Kconfig +++ b/drivers/usb/image/Kconfig @@ -30,11 +30,12 @@ config USB_MICROTEK This driver can be compiled as a module, called microtek. config USB_HPUSBSCSI - tristate "HP53xx USB scanner support (EXPERIMENTAL)" - depends on USB && SCSI && EXPERIMENTAL + tristate "HP53xx USB scanner support" + depends on USB && SCSI help Say Y here if you want support for the HP 53xx series of scanners - and the Minolta Scan Dual. This driver is experimental. + and the Minolta Scan Dual. The scanner will be accessible as a SCSI device. + Please note that recent versions of SANE use usbfs, not this driver. This can be compiled as a module, called hpusbscsi. diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c index dabc3666a..47a864b29 100644 --- a/drivers/usb/image/hpusbscsi.c +++ b/drivers/usb/image/hpusbscsi.c @@ -106,7 +106,7 @@ hpusbscsi_usb_probe(struct usb_interface *intf, /* In host->hostdata we store a pointer to desc */ new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new)); if (!new->host) - goto out_unlink_controlurb; + goto out_kill_controlurb; new->host->hostdata[0] = (unsigned long)new; scsi_add_host(new->host, &intf->dev); /* XXX handle failure */ @@ -118,8 +118,8 @@ hpusbscsi_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, new); return 0; - out_unlink_controlurb: - usb_unlink_urb(new->controlurb); + out_kill_controlurb: + usb_kill_urb(new->controlurb); out_free_controlurb: usb_free_urb(new->controlurb); out_free_dataurb: @@ -137,7 +137,7 @@ hpusbscsi_usb_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); scsi_remove_host(desc->host); - usb_unlink_urb(desc->controlurb); + usb_kill_urb(desc->controlurb); scsi_host_put(desc->host); usb_free_urb(desc->controlurb); @@ -280,8 +280,8 @@ static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb) struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]); printk(KERN_DEBUG"Requested is canceled.\n"); - usb_unlink_urb(hpusbscsi->dataurb); - usb_unlink_urb(hpusbscsi->controlurb); + usb_kill_urb(hpusbscsi->dataurb); + usb_kill_urb(hpusbscsi->controlurb); hpusbscsi->state = HP_STATE_FREE; return SCSI_ABORT_PENDING; diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index f401557f0..66bb13307 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -317,7 +317,6 @@ static int mdc800_usb_waitForIRQ (int mode, int msec) mdc800->camera_request_ready=1+mode; add_wait_queue(&mdc800->irq_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); timeout = msec*HZ/1000; while (!mdc800->irq_woken && timeout) { @@ -325,7 +324,6 @@ static int mdc800_usb_waitForIRQ (int mode, int msec) timeout = schedule_timeout (timeout); } remove_wait_queue(&mdc800->irq_wait, &wait); - set_current_state(TASK_RUNNING); mdc800->irq_woken = 0; if (mdc800->camera_request_ready>0) @@ -543,9 +541,9 @@ static void mdc800_usb_disconnect (struct usb_interface *intf) mdc800->state=NOT_CONNECTED; - usb_unlink_urb (mdc800->irq_urb); - usb_unlink_urb (mdc800->write_urb); - usb_unlink_urb (mdc800->download_urb); + usb_kill_urb(mdc800->irq_urb); + usb_kill_urb(mdc800->write_urb); + usb_kill_urb(mdc800->download_urb); mdc800->dev = NULL; usb_set_intfdata(intf, NULL); @@ -649,9 +647,9 @@ static int mdc800_device_release (struct inode* inode, struct file *file) down (&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { - usb_unlink_urb (mdc800->irq_urb); - usb_unlink_urb (mdc800->write_urb); - usb_unlink_urb (mdc800->download_urb); + usb_kill_urb(mdc800->irq_urb); + usb_kill_urb(mdc800->write_urb); + usb_kill_urb(mdc800->download_urb); mdc800->open=0; } else @@ -725,7 +723,6 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); } - set_current_state(TASK_RUNNING); remove_wait_queue(&mdc800->download_wait, &wait); mdc800->downloaded = 0; if (mdc800->download_urb->status != 0) @@ -851,12 +848,11 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout (timeout); } - set_current_state(TASK_RUNNING); remove_wait_queue(&mdc800->write_wait, &wait); mdc800->written = 0; if (mdc800->state == WORKING) { - usb_unlink_urb (mdc800->write_urb); + usb_kill_urb(mdc800->write_urb); up (&mdc800->io_lock); return -EIO; } diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 230efaf7b..2a18c3562 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -214,8 +214,8 @@ static struct usb_driver mts_usb_driver = { #ifdef MTS_DO_DEBUG static inline void mts_debug_dump(struct mts_desc* desc) { - MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n", - (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0], + MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n", + (int)desc, (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0] ); MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n", @@ -324,7 +324,7 @@ static inline void mts_urb_abort(struct mts_desc* desc) { MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); - usb_unlink_urb( desc->urb ); + usb_kill_urb( desc->urb ); } static int mts_scsi_abort (Scsi_Cmnd *srb) @@ -341,12 +341,18 @@ static int mts_scsi_abort (Scsi_Cmnd *srb) static int mts_scsi_host_reset (Scsi_Cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); + int result, rc; MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); - usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */ - return 0; /* RANT why here 0 and not SUCCESS */ + rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); + if (rc < 0) + return FAILED; + result = usb_reset_device(desc->usb_dev);; + if (rc) + usb_unlock_device(desc->usb_dev); + return result ? FAILED : SUCCESS; } static @@ -777,6 +783,7 @@ static int mts_usb_probe(struct usb_interface *intf, goto out_kfree; new_desc->usb_dev = dev; + new_desc->usb_intf = intf; init_MUTEX(&new_desc->lock); /* endpoints */ @@ -822,10 +829,10 @@ static void mts_usb_disconnect (struct usb_interface *intf) usb_set_intfdata(intf, NULL); + usb_kill_urb(desc->urb); scsi_remove_host(desc->host); - usb_unlink_urb(desc->urb); - scsi_host_put(desc->host); + scsi_host_put(desc->host); usb_free_urb(desc->urb); kfree(desc); } diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h index 206994ddc..3271deb8c 100644 --- a/drivers/usb/image/microtek.h +++ b/drivers/usb/image/microtek.h @@ -31,6 +31,7 @@ struct mts_desc { struct mts_desc *prev; struct usb_device *usb_dev; + struct usb_interface *usb_intf; /* Endpoint addresses */ u8 ep_out; diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index dc2f8f06c..7916f807b 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -1,7 +1,7 @@ # # USB Input driver configuration # -comment "USB Human Interface Devices (HID)" +comment "USB Input Devices" depends on USB config USB_HID @@ -12,7 +12,8 @@ config USB_HID mice, joysticks, graphic tablets, or any other HID based devices to your computer via USB. You also need to select HID Input layer support (below) if you want to use keyboards, mice, joysticks and - the like. + the like ... as well as Uninterruptible Power Supply (UPS) and + monitor control devices. You can't use this driver and the HIDBP (Boot Protocol) keyboard and mouse drivers at the same time. More information is available: @@ -24,7 +25,7 @@ config USB_HID module will be called usbhid. comment "Input core support is needed for USB HID input layer or HIDBP support" - depends on USB && INPUT=n + depends on USB_HID && INPUT=n config USB_HIDINPUT bool "HID input layer support" @@ -32,8 +33,7 @@ config USB_HIDINPUT depends on INPUT && USB_HID help Say Y here if you want to use a USB keyboard, mouse or joystick, - or any other HID input device. You also need "Input core support", - (CONFIG_INPUT), which you select under "Input device support", above. + or any other HID input device. If unsure, say Y. @@ -87,7 +87,6 @@ config USB_HIDDEV This module supports these devices separately using a separate event interface on /dev/usb/hiddevX (char 180:96 to 180:111). - This driver requires CONFIG_USB_HID. If unsure, say Y. @@ -201,6 +200,9 @@ config USB_EGALAX The driver has been tested on a Xenarc 700TSV monitor with eGalax touchscreen. + Have a look at http://linux.chapter7.ch/touchkit/ for + a usage description and the required user-space stuff. + To compile this driver as a module, choose M here: the module will be called touchkitusb. diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index b0261f8a6..67a5b70a6 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -494,9 +494,9 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) } else { input_regs(inputdev, regs); - x = le16_to_cpu(get_unaligned((__u16 *) (data + 1))); - y = le16_to_cpu(get_unaligned((__u16 *) (data + 3))); - z = le16_to_cpu(get_unaligned((__u16 *) (data + 6))); + x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); + y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); + z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); p = (data[5] & 0x01) != 0 ? 1 : 0; dv = (data[5] & 0x02) != 0 ? 1 : 0; @@ -573,8 +573,8 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; } else { input_regs(inputdev, regs); - x = le16_to_cpu(get_unaligned((__u16 *) (data + 1))); - y = le16_to_cpu(get_unaligned((__u16 *) (data + 3))); + x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); + y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); jitterable = data[5] & 0x1c; @@ -632,7 +632,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; macro = data[3]; - z = le16_to_cpu(get_unaligned((__u16 *) (data + 4))); + z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); if (dv != 0) { input_regs(inputdev, regs); @@ -729,7 +729,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs) * hat switches (which just so happen to be the macroKeys.) */ else if (data[0] == 6) { - macro = le16_to_cpu(get_unaligned((__u16 *) (data + 1))); + macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); input_regs(inputdev, regs); if (macro > 0) { @@ -837,7 +837,7 @@ static void aiptek_close(struct input_dev *inputdev) struct aiptek *aiptek = inputdev->private; if (--aiptek->openCount == 0) { - usb_unlink_urb(aiptek->urb); + usb_kill_urb(aiptek->urb); } } @@ -930,7 +930,7 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data) buf[0], buf[1], buf[2]); ret = -EIO; } else { - ret = le16_to_cpu(get_unaligned((__u16 *) (buf + 1))); + ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1))); } kfree(buf); return ret; @@ -2258,7 +2258,7 @@ static void aiptek_disconnect(struct usb_interface *intf) if (aiptek != NULL) { /* Free & unhook everything from the system. */ - usb_unlink_urb(aiptek->urb); + usb_kill_urb(aiptek->urb); input_unregister_device(&aiptek->inputdev); aiptek_delete_files(&intf->dev); usb_free_urb(aiptek->urb); @@ -2289,9 +2289,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(programmableDelay, "i"); +module_param(programmableDelay, int, 0); MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); -MODULE_PARM(jitterDelay, "i"); +module_param(jitterDelay, int, 0); MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); module_init(aiptek_init); diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index c1f1c1d20..f491d76a8 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -102,6 +102,7 @@ #define ATI_REMOTE_VENDOR_ID 0x0bc7 #define ATI_REMOTE_PRODUCT_ID 0x004 #define LOLA_REMOTE_PRODUCT_ID 0x002 +#define MEDION_REMOTE_PRODUCT_ID 0x006 #define DRIVER_VERSION "2.2.1" #define DRIVER_AUTHOR "Torrey Hoffman " @@ -112,11 +113,11 @@ #define ATI_INPUTNUM 1 /* Which input device to register as */ static unsigned long channel_mask = 0; -module_param(channel_mask, ulong, 444); +module_param(channel_mask, ulong, 0444); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug = 0; -module_param(debug, int, 444); +module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) @@ -126,6 +127,7 @@ MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); static struct usb_device_id ati_remote_table[] = { { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, {} /* Terminating entry */ }; @@ -418,13 +420,14 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne while (timeout && (ati_remote->out_urb->status == -EINPROGRESS) && !(ati_remote->send_flags & SEND_FLAG_COMPLETE)) { + set_current_state(TASK_INTERRUPTIBLE); timeout = schedule_timeout(timeout); rmb(); } set_current_state(TASK_RUNNING); remove_wait_queue(&ati_remote->wait, &wait); - usb_unlink_urb(ati_remote->out_urb); + usb_kill_urb(ati_remote->out_urb); return retval; } @@ -624,10 +627,10 @@ static void ati_remote_delete(struct ati_remote *ati_remote) if (!ati_remote) return; if (ati_remote->irq_urb) - usb_unlink_urb(ati_remote->irq_urb); + usb_kill_urb(ati_remote->irq_urb); if (ati_remote->out_urb) - usb_unlink_urb(ati_remote->out_urb); + usb_kill_urb(ati_remote->out_urb); input_unregister_device(&ati_remote->idev); @@ -729,7 +732,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de /* See if the offered device matches what we can accept */ if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) || ( (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID) && - (udev->descriptor.idProduct != LOLA_REMOTE_PRODUCT_ID) )) + (udev->descriptor.idProduct != LOLA_REMOTE_PRODUCT_ID) && + (udev->descriptor.idProduct != MEDION_REMOTE_PRODUCT_ID) )) return -ENODEV; /* Allocate and clear an ati_remote struct */ diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 79082d918..b8b69e074 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -94,7 +94,8 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + values * sizeof(unsigned)); - report->field[report->maxfield++] = field; + field->index = report->maxfield++; + report->field[field->index] = field; field->usage = (struct hid_usage *)(field + 1); field->value = (unsigned *)(field->usage + usages); field->report = report; @@ -219,17 +220,13 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); return -1; } - usages = parser->local.usage_index; + + if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count))) + return 0; /* Ignore padding fields */ offset = report->size; report->size += parser->global.report_size * parser->global.report_count; - if (usages < parser->global.report_count) - usages = parser->global.report_count; - - if (usages == 0) - return 0; /* ignore padding fields */ - if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) return 0; @@ -609,16 +606,16 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) case 2: if ((end - start) < 2) return NULL; - item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start)); - start = (__u8 *)((__u16 *)start + 1); + item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); + start = (__u8 *)((__le16 *)start + 1); return start; case 3: item->size++; if ((end - start) < 4) return NULL; - item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start)); - start = (__u8 *)((__u32 *)start + 1); + item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start)); + start = (__u8 *)((__le32 *)start + 1); return start; } @@ -760,15 +757,15 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) { report += (offset >> 5) << 2; offset &= 31; - return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1); + return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); } static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) { report += (offset >> 5) << 2; offset &= 31; - put_unaligned((get_unaligned((__u64*)report) + put_unaligned((get_unaligned((__le64*)report) & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset))) - | cpu_to_le64((__u64)value << offset), (__u64*)report); + | cpu_to_le64((__u64)value << offset), (__le64*)report); } /* @@ -923,20 +920,23 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs) int status; switch (urb->status) { - case 0: /* success */ - hid_input_report(HID_INPUT_REPORT, urb, regs); - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dbg("nonzero status in input irq %d", urb->status); + case 0: /* success */ + hid_input_report(HID_INPUT_REPORT, urb, regs); + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + case -EPERM: + return; + case -ETIMEDOUT: /* NAK */ + break; + default: /* error */ + warn("input irq status %d received", urb->status); } - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, SLAB_ATOMIC); if (status) - err ("can't resubmit intr, %s-%s/input%d, status %d", + err("can't resubmit intr, %s-%s/input%d, status %d", hid->dev->bus->bus_name, hid->dev->devpath, hid->ifnum, status); } @@ -1137,23 +1137,31 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs) struct hid_device *hid = urb->context; unsigned long flags; - if (urb->status) - warn("output irq status %d received", urb->status); + switch (urb->status) { + case 0: /* success */ + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + break; + default: /* error */ + warn("output irq status %d received", urb->status); + } spin_lock_irqsave(&hid->outlock, flags); hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); if (hid->outhead != hid->outtail) { - hid_submit_out(hid); + if (hid_submit_out(hid)) { + clear_bit(HID_OUT_RUNNING, &hid->iofl);; + wake_up(&hid->wait); + } spin_unlock_irqrestore(&hid->outlock, flags); return; } clear_bit(HID_OUT_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->outlock, flags); - wake_up(&hid->wait); } @@ -1166,26 +1174,34 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs) struct hid_device *hid = urb->context; unsigned long flags; - if (urb->status) - warn("ctrl urb status %d received", urb->status); - spin_lock_irqsave(&hid->ctrllock, flags); - if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); + switch (urb->status) { + case 0: /* success */ + if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) + hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + case -EPIPE: /* report not available */ + break; + default: /* error */ + warn("ctrl urb status %d received", urb->status); + } hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); if (hid->ctrlhead != hid->ctrltail) { - hid_submit_ctrl(hid); + if (hid_submit_ctrl(hid)) { + clear_bit(HID_CTRL_RUNNING, &hid->iofl); + wake_up(&hid->wait); + } spin_unlock_irqrestore(&hid->ctrllock, flags); return; } clear_bit(HID_CTRL_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->ctrllock, flags); - wake_up(&hid->wait); } @@ -1211,7 +1227,8 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign hid->outhead = head; if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl)) - hid_submit_out(hid); + if (hid_submit_out(hid)) + clear_bit(HID_OUT_RUNNING, &hid->iofl); spin_unlock_irqrestore(&hid->outlock, flags); return; @@ -1230,7 +1247,8 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign hid->ctrlhead = head; if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl)) - hid_submit_ctrl(hid); + if (hid_submit_ctrl(hid)) + clear_bit(HID_CTRL_RUNNING, &hid->iofl); spin_unlock_irqrestore(&hid->ctrllock, flags); } @@ -1244,8 +1262,10 @@ int hid_wait_io(struct hid_device *hid) add_wait_queue(&hid->wait, &wait); while (timeout && (test_bit(HID_CTRL_RUNNING, &hid->iofl) || - test_bit(HID_OUT_RUNNING, &hid->iofl))) + test_bit(HID_OUT_RUNNING, &hid->iofl))) { + set_current_state(TASK_UNINTERRUPTIBLE); timeout = schedule_timeout(timeout); + } set_current_state(TASK_RUNNING); remove_wait_queue(&hid->wait, &wait); @@ -1282,7 +1302,7 @@ int hid_open(struct hid_device *hid) void hid_close(struct hid_device *hid) { if (!--hid->open) - usb_unlink_urb(hid->urbin); + usb_kill_urb(hid->urbin); } /* @@ -1334,9 +1354,9 @@ void hid_init_reports(struct hid_device *hid) while (ret) { err |= ret; if (test_bit(HID_CTRL_RUNNING, &hid->iofl)) - usb_unlink_urb(hid->urbctrl); + usb_kill_urb(hid->urbctrl); if (test_bit(HID_OUT_RUNNING, &hid->iofl)) - usb_unlink_urb(hid->urbout); + usb_kill_urb(hid->urbout); ret = hid_wait_io(hid); } @@ -1412,6 +1432,7 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_CYPRESS 0x04b4 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 +#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 #define USB_VENDOR_ID_BERKSHIRE 0x0c98 #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 @@ -1439,6 +1460,15 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 +#define USB_VENDOR_ID_CODEMERCS 0x07c0 +#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500 +#define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501 +#define USB_DEVICE_ID_CODEMERCS_IOW48 0x1502 +#define USB_DEVICE_ID_CODEMERCS_IOW28 0x1503 + +#define USB_VENDOR_ID_DELORME 0x1163 +#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 + static struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1453,20 +1483,20 @@ static struct hid_blacklist { { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE }, @@ -1511,6 +1541,7 @@ static struct hid_blacklist { { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_BACK }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA }, + { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, @@ -1521,6 +1552,13 @@ static struct hid_blacklist { { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, + + { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, + { 0, 0 } }; @@ -1619,11 +1657,17 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) struct usb_endpoint_descriptor *endpoint; int pipe; + int interval; endpoint = &interface->endpoint[n].desc; if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ continue; + /* handle potential highspeed HID correctly */ + interval = endpoint->bInterval; + if (dev->speed == USB_SPEED_HIGH) + interval = 1 << (interval - 1); + if (endpoint->bEndpointAddress & USB_DIR_IN) { int len; @@ -1636,9 +1680,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (len > HID_BUFFER_SIZE) len = HID_BUFFER_SIZE; usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len, - hid_irq_in, hid, endpoint->bInterval); + hid_irq_in, hid, interval); hid->urbin->transfer_dma = hid->inbuf_dma; - hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); } else { if (hid->urbout) continue; @@ -1646,9 +1690,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) goto fail; pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0, - hid_irq_out, hid, 1); + hid_irq_out, hid, interval); hid->urbout->transfer_dma = hid->outbuf_dma; - hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); } } @@ -1659,8 +1703,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) init_waitqueue_head(&hid->wait); - hid->outlock = SPIN_LOCK_UNLOCKED; - hid->ctrllock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&hid->outlock); + spin_lock_init(&hid->ctrllock); hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; @@ -1698,8 +1742,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) hid->ctrlbuf, 1, hid_ctrl, hid); hid->urbctrl->setup_dma = hid->cr_dma; hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; - hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP - | URB_NO_SETUP_DMA_MAP); + hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK); return hid; @@ -1725,9 +1768,9 @@ static void hid_disconnect(struct usb_interface *intf) return; usb_set_intfdata(intf, NULL); - usb_unlink_urb(hid->urbin); - usb_unlink_urb(hid->urbout); - usb_unlink_urb(hid->urbctrl); + usb_kill_urb(hid->urbin); + usb_kill_urb(hid->urbout); + usb_kill_urb(hid->urbctrl); if (hid->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hid); @@ -1799,6 +1842,30 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id return 0; } +static int hid_suspend(struct usb_interface *intf, u32 state) +{ + struct hid_device *hid = usb_get_intfdata (intf); + + usb_kill_urb(hid->urbin); + intf->dev.power.power_state = state; + dev_dbg(&intf->dev, "suspend\n"); + return 0; +} + +static int hid_resume(struct usb_interface *intf) +{ + struct hid_device *hid = usb_get_intfdata (intf); + int status; + + intf->dev.power.power_state = PM_SUSPEND_ON; + if (hid->open) + status = usb_submit_urb(hid->urbin, GFP_NOIO); + else + status = 0; + dev_dbg(&intf->dev, "resume status %d\n", status); + return status; +} + static struct usb_device_id hid_usb_ids [] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, .bInterfaceClass = USB_INTERFACE_CLASS_HID }, @@ -1812,6 +1879,8 @@ static struct usb_driver hid_driver = { .name = "usbhid", .probe = hid_probe, .disconnect = hid_disconnect, + .suspend = hid_suspend, + .resume = hid_resume, .id_table = hid_usb_ids, }; @@ -1835,8 +1904,8 @@ hiddev_init_fail: static void __exit hid_exit(void) { - hiddev_exit(); usb_deregister(&hid_driver); + hiddev_exit(); } module_init(hid_init); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index ff319d9ad..44e466d19 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -223,16 +223,6 @@ static int hiddev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } -/* - * De-allocate a hiddev structure - */ -static struct usb_class_driver hiddev_class; -static void hiddev_cleanup(struct hiddev *hiddev) -{ - hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; - usb_deregister_dev(hiddev->hid->intf, &hiddev_class); - kfree(hiddev); -} /* * release file op @@ -253,7 +243,7 @@ static int hiddev_release(struct inode * inode, struct file * file) if (list->hiddev->exist) hid_close(list->hiddev->hid); else - hiddev_cleanup(list->hiddev); + kfree(list->hiddev); } kfree(list); @@ -636,16 +626,19 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd goto inval; field = report->field[uref->field_index]; - if (uref->usage_index >= field->maxusage) - goto inval; - if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { - if (uref_multi->num_values >= HID_MAX_USAGES || - uref->usage_index >= field->maxusage || - (uref->usage_index + uref_multi->num_values) >= field->maxusage) + if (cmd == HIDIOCGCOLLECTIONINDEX) { + if (uref->usage_index >= field->maxusage) goto inval; + } else if (uref->usage_index >= field->report_count) + goto inval; + + else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && + (uref_multi->num_values >= HID_MAX_MULTI_USAGES || + uref->usage_index + uref_multi->num_values >= field->report_count || + uref->usage_index + uref_multi->num_values < uref->usage_index)) + goto inval; } - } switch (cmd) { case HIDIOCGUSAGE: @@ -795,17 +788,21 @@ int hiddev_connect(struct hid_device *hid) * This is where hid.c calls us to disconnect a hiddev device from the * corresponding hid device (usually because the usb device has disconnected) */ +static struct usb_class_driver hiddev_class; void hiddev_disconnect(struct hid_device *hid) { struct hiddev *hiddev = hid->hiddev; hiddev->exist = 0; + hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; + usb_deregister_dev(hiddev->hid->intf, &hiddev_class); + if (hiddev->open) { hid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); } else { - hiddev_cleanup(hiddev); + kfree(hiddev); } } diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index 43af4031f..2e4c0d246 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -26,10 +26,9 @@ MODULE_LICENSE(DRIVER_LICENSE); #define USB_VENDOR_ID_KBGEAR 0x084e -static int kb_pressure_click = 0x10; -MODULE_PARM (kb_pressure_click,"i"); -MODULE_PARM_DESC(kb_pressure_click, - "pressure threshold for clicks"); +static int kb_pressure_click = 0x10; +module_param(kb_pressure_click, int, 0); +MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); struct kbtab { signed char *data; @@ -67,8 +66,8 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1])); - kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3])); + kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1])); + kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3])); kbtab->pressure = (data[5]); @@ -123,7 +122,7 @@ static void kbtab_close(struct input_dev *dev) struct kbtab *kbtab = dev->private; if (!--kbtab->open) - usb_unlink_urb(kbtab->irq); + usb_kill_urb(kbtab->irq); } static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -206,7 +205,7 @@ static void kbtab_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (kbtab) { - usb_unlink_urb(kbtab->irq); + usb_kill_urb(kbtab->irq); input_unregister_device(&kbtab->dev); usb_free_urb(kbtab->irq); usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index ae5713876..9dcfd7e2f 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -155,7 +155,7 @@ static void mtouchusb_close (struct input_dev *input) struct mtouch_usb *mtouch = input->private; if (!--mtouch->open) - usb_unlink_urb (mtouch->irq); + usb_kill_urb (mtouch->irq); } static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) @@ -320,7 +320,7 @@ static void mtouchusb_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (mtouch) { dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); - usb_unlink_urb(mtouch->irq); + usb_kill_urb(mtouch->irq); input_unregister_device(&mtouch->input); usb_free_urb(mtouch->irq); mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index a38b0db8d..d1ea1f056 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c @@ -56,7 +56,7 @@ static void hid_pid_exit(struct hid_device* hid) struct hid_ff_pid *private = hid->ff_private; if (private->urbffout) { - usb_unlink_urb(private->urbffout); + usb_kill_urb(private->urbffout); usb_free_urb(private->urbffout); } } diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 0ba1bcbfb..01384f523 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -349,7 +349,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i return -ENOMEM; } - pm->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&pm->lock); init_input_dev(&pm->input); /* get a handle to the interrupt data pipe */ @@ -417,7 +417,7 @@ static void powermate_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (pm) { pm->requires_update = 0; - usb_unlink_urb(pm->irq); + usb_kill_urb(pm->irq); input_unregister_device(&pm->input); usb_free_urb(pm->irq); usb_free_urb(pm->config); diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 4917b042e..65dd5be4e 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -59,6 +59,10 @@ #define DRIVER_AUTHOR "Daniel Ritz " #define DRIVER_DESC "eGalax TouchKit USB HID Touchscreen Driver" +static int swap_xy; +module_param(swap_xy, bool, 0644); +MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); + struct touchkit_usb { unsigned char *data; dma_addr_t data_dma; @@ -80,6 +84,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs) { struct touchkit_usb *touchkit = urb->context; int retval; + int x, y; switch (urb->status) { case 0: @@ -103,13 +108,19 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs) goto exit; } + if (swap_xy) { + y = TOUCHKIT_GET_X(touchkit->data); + x = TOUCHKIT_GET_Y(touchkit->data); + } else { + x = TOUCHKIT_GET_X(touchkit->data); + y = TOUCHKIT_GET_Y(touchkit->data); + } + input_regs(&touchkit->input, regs); input_report_key(&touchkit->input, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(touchkit->data)); - input_report_abs(&touchkit->input, ABS_X, - TOUCHKIT_GET_X(touchkit->data)); - input_report_abs(&touchkit->input, ABS_Y, - TOUCHKIT_GET_Y(touchkit->data)); + input_report_abs(&touchkit->input, ABS_X, x); + input_report_abs(&touchkit->input, ABS_Y, y); input_sync(&touchkit->input); exit: @@ -141,7 +152,7 @@ static void touchkit_close(struct input_dev *input) struct touchkit_usb *touchkit = input->private; if (!--touchkit->open) - usb_unlink_urb(touchkit->irq); + usb_kill_urb(touchkit->irq); } static int touchkit_alloc_buffers(struct usb_device *udev, @@ -276,7 +287,7 @@ static void touchkit_disconnect(struct usb_interface *intf) dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); usb_set_intfdata(intf, NULL); input_unregister_device(&touchkit->input); - usb_unlink_urb(touchkit->irq); + usb_kill_urb(touchkit->irq); usb_free_urb(touchkit->irq); touchkit_free_buffers(interface_to_usbdev(intf), touchkit); kfree(touchkit); diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 0c51b1eb8..1700f405b 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -196,7 +196,7 @@ static void usb_kbd_close(struct input_dev *dev) struct usb_kbd *kbd = dev->private; if (!--kbd->open) - usb_unlink_urb(kbd->irq); + usb_kill_urb(kbd->irq); } static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) @@ -343,7 +343,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (kbd) { - usb_unlink_urb(kbd->irq); + usb_kill_urb(kbd->irq); input_unregister_device(&kbd->dev); usb_kbd_free_mem(interface_to_usbdev(intf), kbd); kfree(kbd); diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 5bf27306e..8c7381b74 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -118,7 +118,7 @@ static void usb_mouse_close(struct input_dev *dev) struct usb_mouse *mouse = dev->private; if (!--mouse->open) - usb_unlink_urb(mouse->irq); + usb_kill_urb(mouse->irq); } static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) @@ -223,7 +223,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (mouse) { - usb_unlink_urb(mouse->irq); + usb_kill_urb(mouse->irq); input_unregister_device(&mouse->dev); usb_free_urb(mouse->irq); usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index c66001351..471d1bf68 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -285,8 +285,8 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) input_regs(dev, regs); input_report_key(dev, BTN_TOOL_PEN, 1); - input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((u16 *) &data[1]))); - input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((u16 *) &data[3]))); + input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1]))); + input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3]))); input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); @@ -329,8 +329,8 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) if (data[0] != 2) dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - x = le16_to_cpu(*(u16 *) &data[2]); - y = le16_to_cpu(*(u16 *) &data[4]); + x = le16_to_cpu(*(__le16 *) &data[2]); + y = le16_to_cpu(*(__le16 *) &data[4]); input_regs(dev, regs); @@ -367,7 +367,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) input_report_abs(dev, ABS_Y, y); } - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(u16 *) &data[6])); + input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); input_report_key(dev, BTN_STYLUS, data[1] & 0x02); input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); @@ -456,8 +456,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - input_report_abs(dev, ABS_X, be16_to_cpu(*(u16 *) &data[2])); - input_report_abs(dev, ABS_Y, be16_to_cpu(*(u16 *) &data[4])); + input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); + input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); input_report_abs(dev, ABS_DISTANCE, data[9]); if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */ @@ -608,7 +608,7 @@ static void wacom_close(struct input_dev *dev) struct wacom *wacom = dev->private; if (!--wacom->open) - usb_unlink_urb(wacom->irq); + usb_kill_urb(wacom->irq); } static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -729,7 +729,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (wacom) { - usb_unlink_urb(wacom->irq); + usb_kill_urb(wacom->irq); input_unregister_device(&wacom->dev); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma); diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index 1956eb06b..c5fa87edb 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -214,7 +214,7 @@ static void xpad_close (struct input_dev *dev) struct usb_xpad *xpad = dev->private; if (!--xpad->open_count) - usb_unlink_urb(xpad->irq_in); + usb_kill_urb(xpad->irq_in); } static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -325,7 +325,7 @@ static void xpad_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (xpad) { - usb_unlink_urb(xpad->irq_in); + usb_kill_urb(xpad->irq_in); input_unregister_device(&xpad->dev); usb_free_urb(xpad->irq_in); usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig index 6dac4dc14..678e5fcbe 100644 --- a/drivers/usb/media/Kconfig +++ b/drivers/usb/media/Kconfig @@ -106,46 +106,6 @@ config USB_OV511 To compile this driver as a module, choose M here: the module will be called ov511. -config USB_PWC - tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV - ---help--- - Say Y or M here if you want to use one of these Philips & OEM - webcams: - * Philips PCA645, PCA646 - * Philips PCVC675, PCVC680, PCVC690 - * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 - * Askey VC010 - * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' - and 'Orbit'/'Sphere' - * Samsung MPC-C10, MPC-C30 - * Creative Webcam 5, Pro Ex - * SOTEC Afina Eye - * Visionite VCS-UC300, VCS-UM100 - - The PCA635, PCVC665 and PCVC720/20 are not supported by this driver - and never will be, but the 665 and 720/20 are supported by other - drivers. - - This driver has an optional plugin (called PWCX), which is - distributed as a binary module only. It contains code that allow you - to use higher resolutions and framerates but may not be distributed - as source. But even without this plugin you can these cams for most - applications. - - See for more information and - installation instructions. - - The built-in microphone is enabled by selecting USB Audio support. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at . - - To compile this driver as a module, choose M here: the - module will be called pwc. - config USB_SE401 tristate "USB SE401 Camera support" depends on USB && VIDEO_DEV @@ -163,11 +123,11 @@ config USB_SE401 module will be called se401. config USB_SN9C102 - tristate "USB SN9C10[12] PC Camera Controller support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL + tristate "USB SN9C10x PC Camera Controller support" + depends on USB && VIDEO_DEV ---help--- - Say Y here if you want support for cameras based on SN9C101 and - SN9C102 PC Camera Controllers. + Say Y here if you want support for cameras based on SONiX SN9C101, + SN9C102 or SN9C103 PC Camera Controllers. See for more informations. diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile index 059764cd4..9f0a31eb6 100644 --- a/drivers/usb/media/Makefile +++ b/drivers/usb/media/Makefile @@ -2,15 +2,13 @@ # Makefile for USB Media drivers # -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o -sn9c102-objs := sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o +sn9c102-objs := sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o sn9c102_pas202bcb.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o obj-$(CONFIG_USB_OV511) += ov511.o -obj-$(CONFIG_USB_PWC) += pwc.o obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_SN9C102) += sn9c102.o obj-$(CONFIG_USB_STV680) += stv680.o diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c index 01f77cbc4..73f826d7d 100644 --- a/drivers/usb/media/dabusb.c +++ b/drivers/usb/media/dabusb.c @@ -61,7 +61,7 @@ static dabusb_t dabusb[NRDABUSB]; static int buffers = 256; -extern struct usb_driver dabusb_driver; +static struct usb_driver dabusb_driver; /*-------------------------------------------------------------------*/ @@ -109,16 +109,13 @@ static void dump_urb (struct urb *urb) static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) { unsigned long flags; - struct list_head *p; pbuff_t b; dbg("dabusb_cancel_queue"); spin_lock_irqsave (&s->lock, flags); - for (p = q->next; p != q; p = p->next) { - b = list_entry (p, buff_t, buff_list); - + list_for_each_entry(b, q, buff_list) { #ifdef DEBUG dump_urb(b->purb); #endif @@ -598,7 +595,7 @@ static int dabusb_open (struct inode *inode, struct file *file) if (file->f_flags & O_NONBLOCK) { return -EBUSY; } - schedule_timeout (HZ / 2); + msleep_interruptible(500); if (signal_pending (current)) { return -EAGAIN; @@ -868,7 +865,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE("GPL"); -MODULE_PARM (buffers, "i"); +module_param(buffers, int, 0); MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); module_init (dabusb_init); diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c index f6b18a218..7503f5b96 100644 --- a/drivers/usb/media/dsbr100.c +++ b/drivers/usb/media/dsbr100.c @@ -107,7 +107,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file); static int usb_dsbr100_close(struct inode *inode, struct file *file); static int radio_nr = -1; -MODULE_PARM(radio_nr, "i"); +module_param(radio_nr, int, 0); /* Data for one (physical) device */ typedef struct { diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c index 2740aeb0f..277d65b38 100644 --- a/drivers/usb/media/ibmcam.c +++ b/drivers/usb/media/ibmcam.c @@ -124,38 +124,38 @@ static int init_model2_yb = -1; /* Settings for camera model 3 */ static int init_model3_input = 0; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -MODULE_PARM(flags, "i"); +module_param(flags, int, 0); MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames"); -MODULE_PARM(framerate, "i"); +module_param(framerate, int, 0); MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -MODULE_PARM(lighting, "i"); +module_param(lighting, int, 0); MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); -MODULE_PARM(sharpness, "i"); +module_param(sharpness, int, 0); MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); -MODULE_PARM(size, "i"); +module_param(size, int, 0); MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)"); -MODULE_PARM(init_brightness, "i"); +module_param(init_brightness, int, 0); MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -MODULE_PARM(init_contrast, "i"); +module_param(init_contrast, int, 0); MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -MODULE_PARM(init_color, "i"); +module_param(init_color, int, 0); MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -MODULE_PARM(init_hue, "i"); +module_param(init_hue, int, 0); MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -MODULE_PARM(hue_correction, "i"); +module_param(hue_correction, int, 0); MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); -MODULE_PARM(init_model2_rg2, "i"); +module_param(init_model2_rg2, int, 0); MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); -MODULE_PARM(init_model2_sat, "i"); +module_param(init_model2_sat, int, 0); MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); -MODULE_PARM(init_model2_yb, "i"); +module_param(init_model2_yb, int, 0); MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); /* 01.01.08 - Added for RCA video in support -LO */ -MODULE_PARM(init_model3_input, "i"); +module_param(init_model3_input, int, 0); MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA"); MODULE_AUTHOR ("Dmitri"); diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c index 5fc52c5d3..aca3093c2 100644 --- a/drivers/usb/media/konicawc.c +++ b/drivers/usb/media/konicawc.c @@ -68,7 +68,7 @@ static const int debug = 0; /* Some default values for initial camera settings, can be set by modprobe */ -static enum frame_sizes size; +static int size; static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ static int brightness = MAX_BRIGHTNESS/2; static int contrast = MAX_CONTRAST/2; @@ -362,8 +362,8 @@ static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs) else if (!urb->status && !cam->last_data_urb->status) len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); - resubmit_urb(uvd, urb); resubmit_urb(uvd, cam->last_data_urb); + resubmit_urb(uvd, urb); cam->last_data_urb = NULL; uvd->stats.urb_length = len; uvd->stats.data_count += len; @@ -474,13 +474,8 @@ static void konicawc_stop_data(struct uvd *uvd) /* Unschedule all of the iso td's */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { - j = usb_unlink_urb(uvd->sbuf[i].urb); - if (j < 0) - err("usb_unlink_urb() error %d.", j); - - j = usb_unlink_urb(cam->sts_urb[i]); - if (j < 0) - err("usb_unlink_urb() error %d.", j); + usb_kill_urb(uvd->sbuf[i].urb); + usb_kill_urb(cam->sts_urb[i]); } if (!uvd->remove_pending) { @@ -928,23 +923,23 @@ MODULE_DEVICE_TABLE(usb, id_table); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Simon Evans "); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_PARM(speed, "i"); +module_param(speed, int, 0); MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); -MODULE_PARM(size, "i"); +module_param(size, int, 0); MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); -MODULE_PARM(brightness, "i"); +module_param(brightness, int, 0); MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); -MODULE_PARM(contrast, "i"); +module_param(contrast, int, 0); MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); -MODULE_PARM(saturation, "i"); +module_param(saturation, int, 0); MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); -MODULE_PARM(sharpness, "i"); +module_param(sharpness, int, 0); MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); -MODULE_PARM(whitebal, "i"); +module_param(whitebal, int, 0); MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); #ifdef CONFIG_USB_DEBUG -MODULE_PARM(debug, "i"); +module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); #endif diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c index 529a2de54..8bd791d1d 100644 --- a/drivers/usb/media/ov511.c +++ b/drivers/usb/media/ov511.c @@ -119,78 +119,79 @@ static int remove_zeros; static int mirror; static int ov518_color; -MODULE_PARM(autobright, "i"); +module_param(autobright, int, 0); MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness"); -MODULE_PARM(autogain, "i"); +module_param(autogain, int, 0); MODULE_PARM_DESC(autogain, "Sensor automatically changes gain"); -MODULE_PARM(autoexp, "i"); +module_param(autoexp, int, 0); MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure"); -MODULE_PARM(debug, "i"); +module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max"); -MODULE_PARM(snapshot, "i"); +module_param(snapshot, int, 0); MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); -MODULE_PARM(cams, "i"); +module_param(cams, int, 0); MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); -MODULE_PARM(compress, "i"); +module_param(compress, int, 0); MODULE_PARM_DESC(compress, "Turn on compression"); -MODULE_PARM(testpat, "i"); +module_param(testpat, int, 0); MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)"); -MODULE_PARM(dumppix, "i"); +module_param(dumppix, int, 0); MODULE_PARM_DESC(dumppix, "Dump raw pixel data"); -MODULE_PARM(led, "i"); +module_param(led, int, 0); MODULE_PARM_DESC(led, "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)"); -MODULE_PARM(dump_bridge, "i"); +module_param(dump_bridge, int, 0); MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers"); -MODULE_PARM(dump_sensor, "i"); +module_param(dump_sensor, int, 0); MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers"); -MODULE_PARM(printph, "i"); +module_param(printph, int, 0); MODULE_PARM_DESC(printph, "Print frame start/end headers"); -MODULE_PARM(phy, "i"); +module_param(phy, int, 0); MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)"); -MODULE_PARM(phuv, "i"); +module_param(phuv, int, 0); MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)"); -MODULE_PARM(pvy, "i"); +module_param(pvy, int, 0); MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)"); -MODULE_PARM(pvuv, "i"); +module_param(pvuv, int, 0); MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)"); -MODULE_PARM(qhy, "i"); +module_param(qhy, int, 0); MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)"); -MODULE_PARM(qhuv, "i"); +module_param(qhuv, int, 0); MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)"); -MODULE_PARM(qvy, "i"); +module_param(qvy, int, 0); MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)"); -MODULE_PARM(qvuv, "i"); +module_param(qvuv, int, 0); MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)"); -MODULE_PARM(lightfreq, "i"); +module_param(lightfreq, int, 0); MODULE_PARM_DESC(lightfreq, "Light frequency. Set to 50 or 60 Hz, or zero for default settings"); -MODULE_PARM(bandingfilter, "i"); +module_param(bandingfilter, int, 0); MODULE_PARM_DESC(bandingfilter, "Enable banding filter (to reduce effects of fluorescent lighting)"); -MODULE_PARM(clockdiv, "i"); +module_param(clockdiv, int, 0); MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value"); -MODULE_PARM(packetsize, "i"); +module_param(packetsize, int, 0); MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size"); -MODULE_PARM(framedrop, "i"); +module_param(framedrop, int, 0); MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting"); -MODULE_PARM(fastset, "i"); +module_param(fastset, int, 0); MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately"); -MODULE_PARM(force_palette, "i"); +module_param(force_palette, int, 0); MODULE_PARM_DESC(force_palette, "Force the palette to a specific value"); -MODULE_PARM(backlight, "i"); +module_param(backlight, int, 0); MODULE_PARM_DESC(backlight, "For objects that are lit from behind"); -MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i"); +static int num_uv; +module_param_array(unit_video, int, &num_uv, 0); MODULE_PARM_DESC(unit_video, "Force use of specific minor number(s). 0 is not allowed."); -MODULE_PARM(remove_zeros, "i"); +module_param(remove_zeros, int, 0); MODULE_PARM_DESC(remove_zeros, "Remove zero-padding from uncompressed incoming data"); -MODULE_PARM(mirror, "i"); +module_param(mirror, int, 0); MODULE_PARM_DESC(mirror, "Reverse image horizontally"); -MODULE_PARM(ov518_color, "i"); +module_param(ov518_color, int, 0); MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)"); MODULE_AUTHOR(DRIVER_AUTHOR); @@ -323,21 +324,6 @@ static struct symbolic_list urb_errlist[] = { /********************************************************************** * Memory management **********************************************************************/ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long -kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - static void * rvmalloc(unsigned long size) { @@ -472,7 +458,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n) down(&ov->cbuf_lock); - *((u32 *)ov->cbuf) = __cpu_to_le32(val); + *((__le32 *)ov->cbuf) = __cpu_to_le32(val); rc = usb_control_msg(ov->dev, usb_sndctrlpipe(ov->dev, 0), @@ -1169,7 +1155,7 @@ init_ov_sensor(struct usb_ov511 *ov) return -EIO; /* Wait for it to initialize */ - schedule_timeout(1 + 150 * HZ / 1000); + msleep(150); for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) { if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) && @@ -1182,7 +1168,7 @@ init_ov_sensor(struct usb_ov511 *ov) if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO; /* Wait for it to initialize */ - schedule_timeout(1 + 150 * HZ / 1000); + msleep(150); /* Dummy read to sync I2C */ if (i2c_r(ov, 0x00) < 0) return -EIO; @@ -3829,7 +3815,7 @@ ov51x_unlink_isoc(struct usb_ov511 *ov) /* Unschedule all of the iso td's */ for (n = OV511_NUMSBUF - 1; n >= 0; n--) { if (ov->sbuf[n].urb) { - usb_unlink_urb(ov->sbuf[n].urb); + usb_kill_urb(ov->sbuf[n].urb); usb_free_urb(ov->sbuf[n].urb); ov->sbuf[n].urb = NULL; } @@ -4770,9 +4756,8 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma) pos = (unsigned long)ov->fbuf; while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, - PAGE_SHARED)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { up(&ov->lock); return -EAGAIN; } @@ -4947,7 +4932,7 @@ ov7xx0_configure(struct usb_ov511 *ov) return -1; /* Wait for it to initialize */ - schedule_timeout(1 + 150 * HZ / 1000); + msleep(150); i = 0; success = 0; diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index 260bbd98b..ae4b3576e 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -53,9 +53,9 @@ MODULE_DEVICE_TABLE(usb, device_table); MODULE_AUTHOR("Jeroen Vreeken "); MODULE_DESCRIPTION("SE401 USB Camera Driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(flickerless, "i"); +module_param(flickerless, int, 0); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); -MODULE_PARM(video_nr, "i"); +module_param(video_nr, int, 0); static struct usb_driver se401_driver; @@ -65,20 +65,6 @@ static struct usb_driver se401_driver; * Memory management * **********************************************************************/ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - static void *rvmalloc(unsigned long size) { void *mem; @@ -514,7 +500,7 @@ static int se401_stop_stream(struct usb_se401 *se401) se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); for (i=0; iurb[i]) { - usb_unlink_urb(se401->urb[i]); + usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i]=NULL; kfree(se401->sbuf[i].data); @@ -883,7 +869,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) se401->dev = NULL; for (i=0; iurb[i]) { - usb_unlink_urb(se401->urb[i]); + usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i] = NULL; kfree(se401->sbuf[i].data); @@ -892,7 +878,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) kfree(se401->scratch[i].data); } if (se401->inturb) { - usb_unlink_urb(se401->inturb); + usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); } info("%s disconnected", se401->camera_name); @@ -1182,8 +1168,8 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) } pos = (unsigned long)se401->fbuf; while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { up(&se401->lock); return -EAGAIN; } diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h index fc9cb47e6..a58ff2e9e 100644 --- a/drivers/usb/media/sn9c102.h +++ b/drivers/usb/media/sn9c102.h @@ -1,5 +1,5 @@ /*************************************************************************** - * V4L2 driver for SN9C10[12] PC Camera Controllers * + * V4L2 driver for SN9C10x PC Camera Controllers * * * * Copyright (C) 2004 by Luca Risolia * * * @@ -27,10 +27,12 @@ #include #include #include +#include #include #include #include #include +#include #include "sn9c102_sensor.h" @@ -39,23 +41,31 @@ #define SN9C102_DEBUG #define SN9C102_DEBUG_LEVEL 2 #define SN9C102_MAX_DEVICES 64 +#define SN9C102_PRESERVE_IMGSCALE 0 #define SN9C102_MAX_FRAMES 32 #define SN9C102_URBS 2 #define SN9C102_ISO_PACKETS 7 #define SN9C102_ALTERNATE_SETTING 8 -#define SN9C102_CTRL_TIMEOUT 10*HZ +#define SN9C102_URB_TIMEOUT msecs_to_jiffies(3) +#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(100) /*****************************************************************************/ -#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10[12] PC Camera Controllers" +#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" #define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.01-beta" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) +#define SN9C102_MODULE_VERSION "1:1.19" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 19) -SN9C102_ID_TABLE; -SN9C102_SENSOR_TABLE; +enum sn9c102_bridge { + BRIDGE_SN9C101 = 0x01, + BRIDGE_SN9C102 = 0x02, + BRIDGE_SN9C103 = 0x04, +}; + +SN9C102_ID_TABLE +SN9C102_SENSOR_TABLE enum sn9c102_frame_state { F_UNUSED, @@ -92,7 +102,7 @@ enum sn9c102_stream_state { }; struct sn9c102_sysfs_attr { - u8 reg, val, i2c_reg, i2c_val; + u8 reg, i2c_reg; }; static DECLARE_MUTEX(sn9c102_sysfs_lock); @@ -103,6 +113,7 @@ struct sn9c102_device { struct video_device* v4ldev; + enum sn9c102_bridge bridge; struct sn9c102_sensor* sensor; struct usb_device* usbdev; @@ -112,11 +123,13 @@ struct sn9c102_device { struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; struct list_head inqueue, outqueue; - u32 frame_count, nbuffers; + u32 frame_count, nbuffers, nreadbuffers; enum sn9c102_io_method io; enum sn9c102_stream_state stream; + struct v4l2_jpegcompression compression; + struct sn9c102_sysfs_attr sysfs; u16 reg[32]; diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index bcd9fbd3b..e4c44fa87 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -1,5 +1,5 @@ /*************************************************************************** - * V4L2 driver for SN9C10[12] PC Camera Controllers * + * V4L2 driver for SN9C10x PC Camera Controllers * * * * Copyright (C) 2004 by Luca Risolia * * * @@ -28,9 +28,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -52,8 +52,7 @@ MODULE_VERSION(SN9C102_MODULE_VERSION); MODULE_LICENSE(SN9C102_MODULE_LICENSE); static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; -static unsigned int nv; -module_param_array(video_nr, short, nv, 0444); +module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, "\n<-1|n[,...]> Specify V4L2 minor mode number." "\n -1 = use next available (default)" @@ -83,7 +82,7 @@ MODULE_PARM_DESC(debug, /*****************************************************************************/ -typedef char sn9c102_sof_header_t[7]; +typedef char sn9c102_sof_header_t[12]; typedef char sn9c102_eof_header_t[4]; static sn9c102_sof_header_t sn9c102_sof_header[] = { @@ -91,8 +90,6 @@ static sn9c102_sof_header_t sn9c102_sof_header[] = { {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, }; -/* Number of random bytes that complete the SOF above headers */ -#define SN9C102_SOFLEN 5 static sn9c102_eof_header_t sn9c102_eof_header[] = { {0x00, 0x00, 0x00, 0x00}, @@ -103,17 +100,6 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = { /*****************************************************************************/ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long)page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); - ret = __pa(kva); - return ret; -} - - static void* rvmalloc(size_t size) { void* mem; @@ -170,15 +156,15 @@ static u32 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count) cam->nbuffers = count; while (cam->nbuffers > 0) { - if ((buff = rvmalloc(cam->nbuffers * imagesize))) + if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize)))) break; cam->nbuffers--; } for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*imagesize; + cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*imagesize; + cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); cam->frame[i].buf.length = imagesize; cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cam->frame[i].buf.sequence = 0; @@ -237,9 +223,6 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) u8* buff = cam->control_buffer; int res; - if (index == 0x18) - value = (value & 0xcf) | (cam->reg[0x18] & 0x30); - *buff = value; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, @@ -392,7 +375,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, data[4] = data3; data[5] = data4; data[6] = data5; - data[7] = 0x10; + data[7] = 0x14; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); if (res < 0) @@ -404,7 +387,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, if (err) DBG(3, "I2C write failed for %s image sensor", sensor->name) - PDBGG("I2C write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " + PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", n, data0, data1, data2, data3, data4, data5) @@ -441,26 +424,32 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) /*****************************************************************************/ -static void* sn9c102_find_sof_header(void* mem, size_t len) +static void* +sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) { - size_t soflen=sizeof(sn9c102_sof_header_t), SOFLEN=SN9C102_SOFLEN, i; + size_t soflen = sizeof(sn9c102_sof_header_t), i; u8 j, n = sizeof(sn9c102_sof_header) / soflen; - for (i = 0; (len >= soflen+SOFLEN) && (i <= len-soflen-SOFLEN); i++) + for (i = 0; (len >= soflen) && (i <= len - soflen); i++) for (j = 0; j < n; j++) - if (!memcmp(mem + i, sn9c102_sof_header[j], soflen)) + /* It's enough to compare 7 bytes */ + if (!memcmp(mem + i, sn9c102_sof_header[j], 7)) /* Skips the header */ - return mem + i + soflen + SOFLEN; + return mem + i + soflen; return NULL; } -static void* sn9c102_find_eof_header(void* mem, size_t len) +static void* +sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) { size_t eoflen = sizeof(sn9c102_eof_header_t), i; unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; + if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + return NULL; /* EOF header does not exist in compressed data */ + for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) for (j = 0; j < n; j++) if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) @@ -517,15 +506,17 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs) PDBGG("Isochrnous frame: length %u, #%u i", len, i) - /* NOTE: It is probably correct to assume that SOF and EOF + /* + NOTE: It is probably correct to assume that SOF and EOF headers do not occur between two consecutive packets, but who knows..Whatever is the truth, this assumption - doesn't introduce bugs. */ + doesn't introduce bugs. + */ redo: - sof = sn9c102_find_sof_header(pos, len); + sof = sn9c102_find_sof_header(cam, pos, len); if (!sof) { - eof = sn9c102_find_eof_header(pos, len); + eof = sn9c102_find_eof_header(cam, pos, len); if ((*f)->state == F_GRABBING) { end_of_frame: img = len; @@ -553,7 +544,9 @@ end_of_frame: (*f)->buf.bytesused += img; - if ((*f)->buf.bytesused == (*f)->buf.length) { + if ((*f)->buf.bytesused == (*f)->buf.length || + (cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X && eof)) { u32 b = (*f)->buf.bytesused; (*f)->state = F_DONE; (*f)->buf.sequence= ++cam->frame_count; @@ -606,14 +599,20 @@ start_of_frame: goto redo; } else if ((*f)->state == F_GRABBING) { - eof = sn9c102_find_eof_header(pos, len); + eof = sn9c102_find_eof_header(cam, pos, len); if (eof && eof < sof) goto end_of_frame; /* (1) */ else { - DBG(3, "SOF before expected EOF after %lu " - "bytes of image data", - (unsigned long)((*f)->buf.bytesused)) - goto start_of_frame; + if (cam->sensor->pix_format.pixelformat == + V4L2_PIX_FMT_SN9C10X) { + eof = sof-sizeof(sn9c102_sof_header_t); + goto end_of_frame; + } else { + DBG(3, "SOF before expected EOF after " + "%lu bytes of image data", + (unsigned long)((*f)->buf.bytesused)) + goto start_of_frame; + } } } } @@ -635,7 +634,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) struct usb_device *udev = cam->usbdev; struct urb* urb; const unsigned int wMaxPacketSize[] = {0, 128, 256, 384, 512, - 680, 800, 900, 1023}; + 680, 800, 900, 1023}; const unsigned int psz = wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; s8 i, j; int err = 0; @@ -737,6 +736,29 @@ static int sn9c102_stop_transfer(struct sn9c102_device* cam) return err; } + +int sn9c102_stream_interrupt(struct sn9c102_device* cam) +{ + int err = 0; + + cam->stream = STREAM_INTERRUPT; + err = wait_event_timeout(cam->wait_stream, + (cam->stream == STREAM_OFF) || + (cam->state & DEV_DISCONNECTED), + SN9C102_URB_TIMEOUT); + if (err) { + cam->state |= DEV_MISCONFIGURED; + DBG(1, "The camera is misconfigured. To use " + "it, close and open /dev/video%d " + "again.", cam->v4ldev->minor) + return err; + } + if (cam->state & DEV_DISCONNECTED) + return -ENODEV; + + return 0; +} + /*****************************************************************************/ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) @@ -764,9 +786,11 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) return (u8)val; } -/* NOTE 1: being inside one of the following methods implies that the v4l +/* + NOTE 1: being inside one of the following methods implies that the v4l device exists for sure (see kobjects and reference counters) - NOTE 2: buffers are PAGE_SIZE long */ + NOTE 2: buffers are PAGE_SIZE long +*/ static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf) { @@ -964,6 +988,11 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf) return -ENODEV; } + if (cam->sensor->slave_read_id == SN9C102_I2C_SLAVEID_UNAVAILABLE) { + up(&sn9c102_sysfs_lock); + return -ENOSYS; + } + if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { up(&sn9c102_sysfs_lock); return -EIO; @@ -1019,17 +1048,63 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) static ssize_t -sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len) +sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) { + struct sn9c102_device* cam; + enum sn9c102_bridge bridge; ssize_t res = 0; u8 value; ssize_t count; + if (down_interruptible(&sn9c102_sysfs_lock)) + return -ERESTARTSYS; + + cam = video_get_drvdata(to_video_device(cd)); + if (!cam) { + up(&sn9c102_sysfs_lock); + return -ENODEV; + } + + bridge = cam->bridge; + + up(&sn9c102_sysfs_lock); + value = sn9c102_strtou8(buf, len, &count); if (!count) return -EINVAL; - if ((res = sn9c102_store_reg(cd, "0x10", 4)) >= 0) + switch (bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + if (value > 0x0f) + return -EINVAL; + if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + break; + case BRIDGE_SN9C103: + if (value > 0x7f) + return -EINVAL; + if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) + res = sn9c102_store_val(cd, buf, len); + break; + } + + return res; +} + + +static ssize_t +sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) +{ + ssize_t res = 0; + u8 value; + ssize_t count; + + value = sn9c102_strtou8(buf, len, &count); + if (!count || value > 0x7f) + return -EINVAL; + + if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0) res = sn9c102_store_val(cd, buf, len); return res; @@ -1037,17 +1112,17 @@ sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len) static ssize_t -sn9c102_store_green(struct class_device* cd, const char* buf, size_t len) +sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) { ssize_t res = 0; u8 value; ssize_t count; value = sn9c102_strtou8(buf, len, &count); - if (!count || value > 0x0f) + if (!count || value > 0x7f) return -EINVAL; - if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0) + if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0) res = sn9c102_store_val(cd, buf, len); return res; @@ -1062,8 +1137,9 @@ static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static CLASS_DEVICE_ATTR(redblue, S_IWUGO, NULL, sn9c102_store_redblue); static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green); +static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue); +static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red); static void sn9c102_create_sysfs(struct sn9c102_device* cam) @@ -1072,9 +1148,14 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) video_device_create_file(v4ldev, &class_device_attr_reg); video_device_create_file(v4ldev, &class_device_attr_val); - video_device_create_file(v4ldev, &class_device_attr_redblue); - video_device_create_file(v4ldev, &class_device_attr_green); - if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) { + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) + video_device_create_file(v4ldev, &class_device_attr_green); + else if (cam->bridge == BRIDGE_SN9C103) { + video_device_create_file(v4ldev, &class_device_attr_blue); + video_device_create_file(v4ldev, &class_device_attr_red); + } + if (cam->sensor->slave_write_id != SN9C102_I2C_SLAVEID_UNAVAILABLE || + cam->sensor->slave_read_id != SN9C102_I2C_SLAVEID_UNAVAILABLE) { video_device_create_file(v4ldev, &class_device_attr_i2c_reg); video_device_create_file(v4ldev, &class_device_attr_i2c_val); } @@ -1082,6 +1163,35 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) /*****************************************************************************/ +static int +sn9c102_set_format(struct sn9c102_device* cam, struct v4l2_pix_format* fmt) +{ + int err = 0; + + if (fmt->pixelformat == V4L2_PIX_FMT_SN9C10X) + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); + else + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); + + return err ? -EIO : 0; +} + + +static int +sn9c102_set_compression(struct sn9c102_device* cam, + struct v4l2_jpegcompression* compression) +{ + int err = 0; + + if (compression->quality == 0) + err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); + else if (compression->quality == 1) + err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); + + return err ? -EIO : 0; +} + + static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) { u8 r = 0; @@ -1111,31 +1221,18 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), v_start = (u8)(rect->top - s->cropcap.bounds.top), h_size = (u8)(rect->width / 16), - v_size = (u8)(rect->height / 16), - ae_strx = 0x00, - ae_stry = 0x00, - ae_endx = h_size / 2, - ae_endy = v_size / 2; + v_size = (u8)(rect->height / 16); int err = 0; - /* These are a sort of stroboscopic signal for some sensors */ - err += sn9c102_write_reg(cam, h_size, 0x1a); - err += sn9c102_write_reg(cam, v_size, 0x1b); - err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); err += sn9c102_write_reg(cam, h_size, 0x15); err += sn9c102_write_reg(cam, v_size, 0x16); - err += sn9c102_write_reg(cam, ae_strx, 0x1c); - err += sn9c102_write_reg(cam, ae_stry, 0x1d); - err += sn9c102_write_reg(cam, ae_endx, 0x1e); - err += sn9c102_write_reg(cam, ae_endy, 0x1f); if (err) return -EIO; PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " - "%u %u %u %u %u %u", h_start, v_start, h_size, v_size, ho_size, - vo_size) + "%u %u %u %u", h_start, v_start, h_size, v_size) return 0; } @@ -1172,6 +1269,20 @@ static int sn9c102_init(struct sn9c102_device* cam) } } + if (!(cam->state & DEV_INITIALIZED)) + cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; + else + err += sn9c102_set_compression(cam, &cam->compression); + err += sn9c102_set_format(cam, &s->pix_format); + if (err) + return err; + + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) + DBG(3, "Compressed video format is active, quality %d", + cam->compression.quality) + else + DBG(3, "Uncompressed video format is active") + if (s->set_crop) if ((err = s->set_crop(cam, rect))) { DBG(3, "set_crop() failed") @@ -1187,9 +1298,12 @@ static int sn9c102_init(struct sn9c102_device* cam) ctrl.value = qctrl[i].default_value; err = s->set_ctrl(cam, &ctrl); if (err) { - DBG(3, "Set control failed") + DBG(3, "Set %s control failed", + s->qctrl[i].name) return err; } + DBG(3, "Image sensor supports '%s' control", + s->qctrl[i].name) } } @@ -1198,6 +1312,7 @@ static int sn9c102_init(struct sn9c102_device* cam) spin_lock_init(&cam->queue_lock); init_waitqueue_head(&cam->wait_frame); init_waitqueue_head(&cam->wait_stream); + cam->nreadbuffers = 2; memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); memcpy(&(s->_rect), &(s->cropcap.defrect), sizeof(struct v4l2_rect)); @@ -1229,7 +1344,10 @@ static int sn9c102_open(struct inode* inode, struct file* filp) struct sn9c102_device* cam; int err = 0; - /* This the only safe way to prevent race conditions with disconnect */ + /* + This is the only safe way to prevent race conditions with + disconnect + */ if (!down_read_trylock(&sn9c102_disconnect)) return -ERESTARTSYS; @@ -1352,7 +1470,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) } if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, 2)) { + if (!sn9c102_request_buffers(cam, cam->nreadbuffers)) { DBG(1, "read() failed, not enough memory") up(&cam->fileop_sem); return -ENOMEM; @@ -1396,8 +1514,8 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) sn9c102_queue_unusedframes(cam); - if (count > f->buf.length) - count = f->buf.length; + if (count > f->buf.bytesused) + count = f->buf.bytesused; if (copy_to_user(buf, f->bufmem, count)) { up(&cam->fileop_sem); @@ -1518,11 +1636,15 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) return -EINVAL; } + /* VM_IO is eventually going to replace PageReserved altogether */ + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + pos = (unsigned long)cam->frame[i].bufmem; while (size > 0) { /* size is page-aligned */ - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, - vma->vm_page_prot)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, + vma->vm_page_prot)) { up(&cam->fileop_sem); return -EAGAIN; } @@ -1532,8 +1654,6 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) } vma->vm_ops = &sn9c102_vm_ops; - vma->vm_flags &= ~VM_IO; /* not I/O memory */ - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ vma->vm_private_data = &cam->frame[i]; sn9c102_vm_open(vma); @@ -1558,11 +1678,14 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, .version = SN9C102_MODULE_VERSION_CODE, .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, + V4L2_CAP_STREAMING, }; strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - strlcpy(cap.bus_info, cam->dev.bus_id, sizeof(cap.bus_info)); + if (usb_make_path(cam->usbdev, cap.bus_info, + sizeof(cap.bus_info)) < 0) + strlcpy(cap.bus_info, cam->dev.bus_id, + sizeof(cap.bus_info)); if (copy_to_user(arg, &cap, sizeof(cap))) return -EFAULT; @@ -1657,16 +1780,24 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; - if ((err = s->set_ctrl(cam, &ctrl))) - return err; - n = sizeof(s->qctrl) / sizeof(s->qctrl[0]); for (i = 0; i < n; i++) if (ctrl.id == s->qctrl[i].id) { - s->_qctrl[i].default_value = ctrl.value; + if (ctrl.value < s->qctrl[i].minimum || + ctrl.value > s->qctrl[i].maximum) + return -ERANGE; + ctrl.value -= ctrl.value % s->qctrl[i].step; break; } + if ((err = s->set_ctrl(cam, &ctrl))) + return err; + + s->_qctrl[i].default_value = ctrl.value; + + PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", + (unsigned long)ctrl.id, (unsigned long)ctrl.value) + return 0; } @@ -1727,6 +1858,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } + /* Preserve R,G or B origin */ + rect->left = (s->_rect.left & 1L) ? + rect->left | 1L : rect->left & ~1L; + rect->top = (s->_rect.top & 1L) ? + rect->top | 1L : rect->top & ~1L; + if (rect->width < 16) rect->width = 16; if (rect->height < 16) @@ -1747,30 +1884,19 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, rect->width &= ~15L; rect->height &= ~15L; - { /* calculate the scaling factor */ + if (SN9C102_PRESERVE_IMGSCALE) { + /* Calculate the actual scaling factor */ u32 a, b; a = rect->width * rect->height; b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 : - ((a / b) > 4 ? 4 : (a / b)))) : 1; - } + scale = b ? (u8)((a / b) < 4 ? 1 : + ((a / b) < 16 ? 2 : 4)) : 1; + } else + scale = 1; - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } if (copy_to_user(arg, &crop, sizeof(crop))) { cam->stream = stream; @@ -1789,7 +1915,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, DBG(1, "VIDIOC_S_CROP failed because of hardware " "problems. To use the camera, close and open " "/dev/video%d again.", cam->v4ldev->minor) - return err; + return -EIO; } s->pix_format.width = rect->width/scale; @@ -1811,20 +1937,23 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, case VIDIOC_ENUM_FMT: { - struct sn9c102_sensor* s = cam->sensor; struct v4l2_fmtdesc fmtd; if (copy_from_user(&fmtd, arg, sizeof(fmtd))) return -EFAULT; - if (fmtd.index != 0) + if (fmtd.index == 0) { + strcpy(fmtd.description, "bayer rgb"); + fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; + } else if (fmtd.index == 1) { + strcpy(fmtd.description, "compressed"); + fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; + fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; + } else return -EINVAL; - memset(&fmtd, 0, sizeof(fmtd)); - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = s->pix_format.pixelformat; + memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); if (copy_to_user(arg, &fmtd, sizeof(fmtd))) return -EFAULT; @@ -1843,8 +1972,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - pfmt->bytesperline = (pfmt->width * pfmt->priv) / 8; - pfmt->sizeimage = pfmt->height * pfmt->bytesperline; + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) + ? 0 : (pfmt->width * pfmt->priv) / 8; + pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); pfmt->field = V4L2_FIELD_NONE; memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); @@ -1879,12 +2009,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, memcpy(&rect, &(s->_rect), sizeof(rect)); - { /* calculate the scaling factor */ + { /* calculate the actual scaling factor */ u32 a, b; a = rect.width * rect.height; b = pix->width * pix->height; - scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 : - ((a / b) > 4 ? 4 : (a / b)))) : 1; + scale = b ? (u8)((a / b) < 4 ? 1 : + ((a / b) < 16 ? 2 : 4)) : 1; } rect.width = scale * pix->width; @@ -1895,25 +2025,39 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (rect.height < 16) rect.height = 16; if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left+bounds->width - rect.left; + rect.width = bounds->left + bounds->width - rect.left; if (rect.height > bounds->top + bounds->height - rect.top) rect.height = bounds->top + bounds->height - rect.top; rect.width &= ~15L; rect.height &= ~15L; + { /* adjust the scaling factor */ + u32 a, b; + a = rect.width * rect.height; + b = pix->width * pix->height; + scale = b ? (u8)((a / b) < 4 ? 1 : + ((a / b) < 16 ? 2 : 4)) : 1; + } + pix->width = rect.width / scale; pix->height = rect.height / scale; - pix->pixelformat = pfmt->pixelformat; + if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) + pix->pixelformat = pfmt->pixelformat; pix->priv = pfmt->priv; /* bpp */ pix->colorspace = pfmt->colorspace; - pix->bytesperline = (pix->width * pix->priv) / 8; - pix->sizeimage = pix->height * pix->bytesperline; + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) + ? 0 : (pix->width * pix->priv) / 8; + pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); pix->field = V4L2_FIELD_NONE; - if (cmd == VIDIOC_TRY_FMT) + if (cmd == VIDIOC_TRY_FMT) { + if (copy_to_user(arg, &format, sizeof(format))) + return -EFAULT; return 0; + } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { @@ -1922,22 +2066,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } if (copy_to_user(arg, &format, sizeof(format))) { cam->stream = stream; @@ -1946,7 +2077,8 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, sn9c102_release_buffers(cam); - err = sn9c102_set_crop(cam, &rect); + err += sn9c102_set_format(cam, pix); + err += sn9c102_set_crop(cam, &rect); if (s->set_crop) err += s->set_crop(cam, &rect); err += sn9c102_set_scale(cam, scale); @@ -1956,7 +2088,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, DBG(1, "VIDIOC_S_FMT failed because of hardware " "problems. To use the camera, close and open " "/dev/video%d again.", cam->v4ldev->minor) - return err; + return -EIO; } memcpy(pfmt, pix, sizeof(*pix)); @@ -1975,6 +2107,47 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return 0; } + case VIDIOC_G_JPEGCOMP: + { + if (copy_to_user(arg, &cam->compression, + sizeof(cam->compression))) + return -EFAULT; + + return 0; + } + + case VIDIOC_S_JPEGCOMP: + { + struct v4l2_jpegcompression jc; + const enum sn9c102_stream_state stream = cam->stream; + int err = 0; + + if (copy_from_user(&jc, arg, sizeof(jc))) + return -EFAULT; + + if (jc.quality != 0 && jc.quality != 1) + return -EINVAL; + + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) + return err; + + err += sn9c102_set_compression(cam, &jc); + if (err) { /* atomic, no rollback in ioctl() */ + cam->state |= DEV_MISCONFIGURED; + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " + "problems. To use the camera, close and open " + "/dev/video%d again.", cam->v4ldev->minor) + return -EIO; + } + + cam->compression.quality = jc.quality; + + cam->stream = stream; + + return 0; + } + case VIDIOC_REQBUFS: { struct v4l2_requestbuffers rb; @@ -2001,22 +2174,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return -EINVAL; } - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } sn9c102_empty_framequeues(cam); @@ -2119,7 +2279,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, spin_lock_irqsave(&cam->queue_lock, lock_flags); f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); - list_del(&cam->outqueue); + list_del(cam->outqueue.next); spin_unlock_irqrestore(&cam->queue_lock, lock_flags); f->state = F_UNUSED; @@ -2166,22 +2326,9 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (cam->stream == STREAM_ON) { - cam->stream = STREAM_INTERRUPT; - err = wait_event_interruptible - ( cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED) ); - if (err) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "The camera is misconfigured. To use " - "it, close and open /dev/video%d " - "again.", cam->v4ldev->minor) + if (cam->stream == STREAM_ON) + if ((err = sn9c102_stream_interrupt(cam))) return err; - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - } sn9c102_empty_framequeues(cam); @@ -2190,13 +2337,56 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp, return 0; } + case VIDIOC_G_PARM: + { + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + return 0; + } + + case VIDIOC_S_PARM: + { + struct v4l2_streamparm sp; + + if (copy_from_user(&sp, arg, sizeof(sp))) + return -EFAULT; + + if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + sp.parm.capture.extendedmode = 0; + + if (sp.parm.capture.readbuffers == 0) + sp.parm.capture.readbuffers = cam->nreadbuffers; + + if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) + sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; + + if (copy_to_user(arg, &sp, sizeof(sp))) + return -EFAULT; + + cam->nreadbuffers = sp.parm.capture.readbuffers; + + return 0; + } + case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_QUERYSTD: case VIDIOC_ENUMSTD: case VIDIOC_QUERYMENU: - case VIDIOC_G_PARM: - case VIDIOC_S_PARM: return -EINVAL; default: @@ -2291,16 +2481,28 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) r = sn9c102_read_reg(cam, 0x00); if (r < 0 || r != 0x10) { - DBG(1, "Sorry, this is not a SN9C10[12] based camera " + DBG(1, "Sorry, this is not a SN9C10x based camera " "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct) err = -ENODEV; goto fail; } - DBG(2, "SN9C10[12] PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)", - sn9c102_id_table[i].idVendor, sn9c102_id_table[i].idProduct) + cam->bridge = (sn9c102_id_table[i].idProduct & 0xffc0) == 0x6080 ? + BRIDGE_SN9C103 : BRIDGE_SN9C102; + switch (cam->bridge) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + DBG(2, "SN9C10[12] PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor, + sn9c102_id_table[i].idProduct) + break; + case BRIDGE_SN9C103: + DBG(2, "SN9C103 PC Camera Controller detected " + "(vid/pid 0x%04X/0x%04X)", sn9c102_id_table[i].idVendor, + sn9c102_id_table[i].idProduct) + break; + } for (i = 0; sn9c102_sensor_table[i]; i++) { err = sn9c102_sensor_table[i](cam); @@ -2323,7 +2525,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->state |= DEV_MISCONFIGURED; } - strcpy(cam->v4ldev->name, "SN9C10[12] PC Camera"); + strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); cam->v4ldev->owner = THIS_MODULE; cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; cam->v4ldev->hardware = VID_HARDWARE_SN9C102; diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c index 34bdfcf8e..54942d607 100644 --- a/drivers/usb/media/sn9c102_pas106b.c +++ b/drivers/usb/media/sn9c102_pas106b.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Driver for PAS106B image sensor connected to the SN9C10[12] PC Camera * + * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Luca Risolia * @@ -38,15 +38,9 @@ static int pas106b_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x09, 0x18); err += sn9c102_i2c_write(cam, 0x02, 0x0c); - err += sn9c102_i2c_write(cam, 0x03, 0x12); - err += sn9c102_i2c_write(cam, 0x04, 0x05); - err += sn9c102_i2c_write(cam, 0x05, 0x22); - err += sn9c102_i2c_write(cam, 0x06, 0xac); - err += sn9c102_i2c_write(cam, 0x07, 0x00); - err += sn9c102_i2c_write(cam, 0x08, 0x01); - err += sn9c102_i2c_write(cam, 0x0a, 0x00); - err += sn9c102_i2c_write(cam, 0x0b, 0x00); - err += sn9c102_i2c_write(cam, 0x0d, 0x00); + err += sn9c102_i2c_write(cam, 0x05, 0x5a); + err += sn9c102_i2c_write(cam, 0x06, 0x88); + err += sn9c102_i2c_write(cam, 0x07, 0x80); err += sn9c102_i2c_write(cam, 0x10, 0x06); err += sn9c102_i2c_write(cam, 0x11, 0x06); err += sn9c102_i2c_write(cam, 0x12, 0x00); @@ -63,12 +57,50 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x03), + r2 = sn9c102_i2c_read(cam, 0x04); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 4) | (r2 & 0x0f); + } + return 0; case V4L2_CID_RED_BALANCE: - return (ctrl->value = sn9c102_i2c_read(cam, 0x0c))<0 ? -EIO:0; + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; case V4L2_CID_BLUE_BALANCE: - return (ctrl->value = sn9c102_i2c_read(cam, 0x09))<0 ? -EIO:0; - case V4L2_CID_BRIGHTNESS: - return (ctrl->value = sn9c102_i2c_read(cam, 0x0e))<0 ? -EIO:0; + if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case V4L2_CID_GAIN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0) + return -EIO; + ctrl->value &= 0x1f; + return 0; + case V4L2_CID_CONTRAST: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0) + return -EIO; + ctrl->value &= 0x07; + return 0; + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0) + return -EIO; + ctrl->value = (ctrl->value & 0x1f) << 1; + return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) + return -EIO; + ctrl->value &= 0xf8; + return 0; + case SN9C102_V4L2_CID_DAC_SIGN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) + return -EIO; + ctrl->value &= 0x01; + return 0; default: return -EINVAL; } @@ -81,21 +113,42 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam, int err = 0; switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); + err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); + break; case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value & 0x1f); + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); break; case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x1f); + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); + break; + case V4L2_CID_GAIN: + err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); + break; + case V4L2_CID_CONTRAST: + err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); + err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); break; - case V4L2_CID_BRIGHTNESS: - err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f); + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); + break; + case SN9C102_V4L2_CID_DAC_SIGN: + { + int r; + err += (r = sn9c102_i2c_read(cam, 0x07)) < 0 ? r : 0; + err += sn9c102_i2c_write(cam, 0x07, r | ctrl->value); + } break; default: return -EINVAL; } err += sn9c102_i2c_write(cam, 0x13, 0x01); - return err; + return err ? -EIO : 0; } @@ -123,6 +176,36 @@ static struct sn9c102_sensor pas106b = { .slave_write_id = 0x40, .init = &pas106b_init, .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x125, + .maximum = 0xfff, + .step = 0x01, + .default_value = 0x140, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0d, + .flags = 0, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "contrast", + .minimum = 0x00, + .maximum = 0x07, + .step = 0x01, + .default_value = 0x00, /* 0x00~0x03 have same effect */ + .flags = 0, + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -130,7 +213,7 @@ static struct sn9c102_sensor pas106b = { .minimum = 0x00, .maximum = 0x1f, .step = 0x01, - .default_value = 0x03, + .default_value = 0x04, .flags = 0, }, { @@ -140,17 +223,37 @@ static struct sn9c102_sensor pas106b = { .minimum = 0x00, .maximum = 0x1f, .step = 0x01, + .default_value = 0x06, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_GREEN_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green balance", + .minimum = 0x00, + .maximum = 0x3e, + .step = 0x02, .default_value = 0x02, .flags = 0, }, { - .id = V4L2_CID_BRIGHTNESS, + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", + .name = "DAC magnitude", .minimum = 0x00, .maximum = 0x1f, .step = 0x01, - .default_value = 0x06, + .default_value = 0x01, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_SIGN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "DAC sign", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, .flags = 0, }, }, @@ -185,11 +288,13 @@ int sn9c102_probe_pas106b(struct sn9c102_device* cam) int r0 = 0, r1 = 0, err = 0; unsigned int pid = 0; - /* Minimal initialization to enable the I2C communication - NOTE: do NOT change the values! */ + /* + Minimal initialization to enable the I2C communication + NOTE: do NOT change the values! + */ err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ - err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 48 MHz */ + err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ if (err) return -EIO; diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c index 26944eaf8..3e2fd5a6f 100644 --- a/drivers/usb/media/sn9c102_pas202bcb.c +++ b/drivers/usb/media/sn9c102_pas202bcb.c @@ -1,11 +1,14 @@ /*************************************************************************** - * Driver for PAS202BCB image sensor connected to the SN9C10[12] PC Camera * + * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * * Controllers * * * * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * * * * http://cadu.homelinux.com:8080/ * * * + * DAC Magnitude, DAC sign, exposure and green gain controls added by * + * Luca Risolia * + * * * 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 * @@ -36,18 +39,15 @@ static int pas202bcb_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x00, 0x11); err += sn9c102_write_reg(cam, 0x00, 0x14); err += sn9c102_write_reg(cam, 0x20, 0x17); - err += sn9c102_write_reg(cam, 0x20, 0x19); + err += sn9c102_write_reg(cam, 0x30, 0x19); err += sn9c102_write_reg(cam, 0x09, 0x18); - err += sn9c102_i2c_write(cam, 0x02, 0x0c); + err += sn9c102_i2c_write(cam, 0x02, 0x14); err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x04, 0x07); - err += sn9c102_i2c_write(cam, 0x05, 0x25); err += sn9c102_i2c_write(cam, 0x0d, 0x2c); err += sn9c102_i2c_write(cam, 0x0e, 0x01); err += sn9c102_i2c_write(cam, 0x0f, 0xa9); - err += sn9c102_i2c_write(cam, 0x08, 0x01); - err += sn9c102_i2c_write(cam, 0x0b, 0x01); + err += sn9c102_i2c_write(cam, 0x10, 0x08); err += sn9c102_i2c_write(cam, 0x13, 0x63); err += sn9c102_i2c_write(cam, 0x15, 0x70); err += sn9c102_i2c_write(cam, 0x11, 0x01); @@ -62,6 +62,15 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + { + int r1 = sn9c102_i2c_read(cam, 0x04), + r2 = sn9c102_i2c_read(cam, 0x05); + if (r1 < 0 || r2 < 0) + return -EIO; + ctrl->value = (r1 << 6) | (r2 & 0x3f); + } + return 0; case V4L2_CID_RED_BALANCE: if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) return -EIO; @@ -77,11 +86,20 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam, return -EIO; ctrl->value &= 0x1f; return 0; - case V4L2_CID_BRIGHTNESS: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0) + case SN9C102_V4L2_CID_GREEN_BALANCE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) return -EIO; ctrl->value &= 0x0f; return 0; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) + return -EIO; + return 0; + case SN9C102_V4L2_CID_DAC_SIGN: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0b)) < 0) + return -EIO; + ctrl->value &= 0x01; + return 0; default: return -EINVAL; } @@ -94,24 +112,38 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam, int err = 0; switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); + err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); + break; case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x0f); + err += sn9c102_i2c_write(cam, 0x09, ctrl->value); break; case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x07, ctrl->value & 0x0f); + err += sn9c102_i2c_write(cam, 0x07, ctrl->value); break; case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x1f); + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); + break; + case SN9C102_V4L2_CID_GREEN_BALANCE: + err += sn9c102_i2c_write(cam, 0x08, ctrl->value); + break; + case SN9C102_V4L2_CID_DAC_MAGNITUDE: + err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); break; - case V4L2_CID_BRIGHTNESS: - err += sn9c102_i2c_write(cam, 0x06, 0x0f-(ctrl->value & 0x0f)); + case SN9C102_V4L2_CID_DAC_SIGN: + { + int r; + err += (r = sn9c102_i2c_read(cam, 0x0b)) < 0 ? r : 0; + err += sn9c102_i2c_write(cam, 0x0b, r | ctrl->value); + } break; default: return -EINVAL; } err += sn9c102_i2c_write(cam, 0x11, 0x01); - return err; + return err ? -EIO : 0; } @@ -140,6 +172,26 @@ static struct sn9c102_sensor pas202bcb = { .slave_write_id = 0x40, .init = &pas202bcb_init, .qctrl = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x01e5, + .maximum = 0x3fff, + .step = 0x01, + .default_value = 0x01e5, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0x1f, + .step = 0x01, + .default_value = 0x0c, + .flags = 0, + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -161,23 +213,33 @@ static struct sn9c102_sensor pas202bcb = { .flags = 0, }, { - .id = V4L2_CID_GAIN, + .id = SN9C102_V4L2_CID_GREEN_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", + .name = "green balance", .minimum = 0x00, - .maximum = 0x1f, + .maximum = 0x0f, .step = 0x01, - .default_value = 0x0c, + .default_value = 0x00, .flags = 0, }, { - .id = V4L2_CID_BRIGHTNESS, + .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", + .name = "DAC magnitude", .minimum = 0x00, - .maximum = 0x0f, + .maximum = 0xff, .step = 0x01, - .default_value = 0x0f, + .default_value = 0x04, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_DAC_SIGN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "DAC sign", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x01, .flags = 0, }, }, @@ -217,7 +279,7 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) * NOTE: do NOT change the values! */ err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ - err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ + err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ if (err) return -EIO; diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h index 54a3499b5..ebafc2809 100644 --- a/drivers/usb/media/sn9c102_sensor.h +++ b/drivers/usb/media/sn9c102_sensor.h @@ -1,5 +1,5 @@ /*************************************************************************** - * API for image sensors connected to the SN9C10[12] PC Camera Controllers * + * API for image sensors connected to the SN9C10x PC Camera Controllers * * * * Copyright (C) 2004 by Luca Risolia * * * @@ -33,7 +33,8 @@ struct sn9c102_sensor; /*****************************************************************************/ -/* OVERVIEW. +/* + OVERVIEW. This is a small interface that allows you to add support for any CCD/CMOS image sensors connected to the SN9C10X bridges. The entire API is documented below. In the most general case, to support a sensor there are three steps @@ -48,26 +49,33 @@ struct sn9c102_sensor; "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do NOT need to touch the source code of the core module for the things to work properly, unless you find bugs or flaws in it. Finally, do not forget to - read the V4L2 API for completeness. */ + read the V4L2 API for completeness. +*/ /*****************************************************************************/ - -/* Probing functions: on success, you must attach the sensor to the camera + +/* + Probing functions: on success, you must attach the sensor to the camera by calling sn9c102_attach_sensor() provided below. To enable the I2C communication, you might need to perform a really basic initialization of the SN9C10X chip by using the write function declared ahead. - Functions must return 0 on success, the appropriate error otherwise. */ + Functions must return 0 on success, the appropriate error otherwise. +*/ extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); +extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); -/* Add the above entries to this table. Be sure to add the entry in the right +/* + Add the above entries to this table. Be sure to add the entry in the right place, since, on failure, the next probing routine is called according to - the order of the list below, from top to bottom */ + the order of the list below, from top to bottom. +*/ #define SN9C102_SENSOR_TABLE \ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ - &sn9c102_probe_pas106b, /* strong detection based on SENSOR vid/pid */\ + &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ + &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ NULL, \ @@ -81,28 +89,56 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, /* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/ #define SN9C102_ID_TABLE \ static const struct usb_device_id sn9c102_id_table[] = { \ - { USB_DEVICE(0xc45, 0x6001), }, \ - { USB_DEVICE(0xc45, 0x6005), }, /* TAS5110C1B */ \ - { USB_DEVICE(0xc45, 0x6009), }, /* PAS106B */ \ - { USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */ \ - { USB_DEVICE(0xc45, 0x6024), }, \ - { USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B Maybe also TAS5110C1B */\ - { USB_DEVICE(0xc45, 0x6028), }, /* Maybe PAS202B */ \ - { USB_DEVICE(0xc45, 0x6029), }, \ - { USB_DEVICE(0xc45, 0x602a), }, /* Maybe HV7131[D|E1] */ \ - { USB_DEVICE(0xc45, 0x602c), }, /* Maybe OV7620 */ \ - { USB_DEVICE(0xc45, 0x6030), }, /* Maybe MI03 */ \ - { USB_DEVICE(0xc45, 0x8001), }, \ + { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x6024), }, \ + { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ + { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131[D|E1] */ \ + { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ + { USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */ \ + { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ + { USB_DEVICE(0x0c45, 0x6080), }, \ + { USB_DEVICE(0x0c45, 0x6082), }, /* MI0343 and MI0360 */ \ + { USB_DEVICE(0x0c45, 0x6083), }, /* HV7131[D|E1] */ \ + { USB_DEVICE(0x0c45, 0x6088), }, \ + { USB_DEVICE(0x0c45, 0x608a), }, \ + { USB_DEVICE(0x0c45, 0x608b), }, \ + { USB_DEVICE(0x0c45, 0x608c), }, /* HV7131x */ \ + { USB_DEVICE(0x0c45, 0x608e), }, /* CIS-VF10 */ \ + { USB_DEVICE(0x0c45, 0x608f), }, /* OV7630 */ \ + { USB_DEVICE(0x0c45, 0x60a0), }, \ + { USB_DEVICE(0x0c45, 0x60a2), }, \ + { USB_DEVICE(0x0c45, 0x60a3), }, \ + { USB_DEVICE(0x0c45, 0x60a8), }, /* PAS106B */ \ + { USB_DEVICE(0x0c45, 0x60aa), }, /* TAS5130D1B */ \ + { USB_DEVICE(0x0c45, 0x60ab), }, /* TAS5110C1B */ \ + { USB_DEVICE(0x0c45, 0x60ac), }, \ + { USB_DEVICE(0x0c45, 0x60ae), }, \ + { USB_DEVICE(0x0c45, 0x60af), }, /* PAS202BCB */ \ + { USB_DEVICE(0x0c45, 0x60b0), }, \ + { USB_DEVICE(0x0c45, 0x60b2), }, \ + { USB_DEVICE(0x0c45, 0x60b3), }, \ + { USB_DEVICE(0x0c45, 0x60b8), }, \ + { USB_DEVICE(0x0c45, 0x60ba), }, \ + { USB_DEVICE(0x0c45, 0x60bb), }, \ + { USB_DEVICE(0x0c45, 0x60bc), }, \ + { USB_DEVICE(0x0c45, 0x60be), }, \ { } \ }; /*****************************************************************************/ -/* Read/write routines: they always return -1 on error, 0 or the read value +/* + Read/write routines: they always return -1 on error, 0 or the read value otherwise. NOTE that a real read operation is not supported by the SN9C10X chip for some of its registers. To work around this problem, a pseudo-read call is provided instead: it returns the last successfully written value - on the register (0 if it has never been written), the usual -1 on error. */ + on the register (0 if it has never been written), the usual -1 on error. +*/ /* The "try" I2C I/O versions are used when probing the sensor */ extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, @@ -110,10 +146,12 @@ extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, u8 address); -/* This must be used if and only if the sensor doesn't implement the standard - I2C protocol, like the TASC sensors. There a number of good reasons why you - must use the single-byte versions of this function: do not abuse. It writes - n bytes, from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip) */ +/* + This must be used if and only if the sensor doesn't implement the standard + I2C protocol. There a number of good reasons why you must use the + single-byte versions of this function: do not abuse. It writes n bytes, + from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip). +*/ extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, @@ -127,12 +165,14 @@ extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); -/* NOTE: there are no debugging functions here. To uniform the output you must +/* + NOTE: there are no debugging functions here. To uniform the output you must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, already included here, the argument being the struct device 'dev' of the sensor structure. Do NOT use these macros before the sensor is attached or the kernel will crash! However you should not need to notify the user about - common errors or other messages, since this is done by the master module. */ + common errors or other messages, since this is done by the master module. +*/ /*****************************************************************************/ @@ -146,28 +186,36 @@ enum sn9c102_i2c_interface { SN9C102_I2C_3WIRES, }; +#define SN9C102_I2C_SLAVEID_FICTITIOUS 0xff +#define SN9C102_I2C_SLAVEID_UNAVAILABLE 0x00 + struct sn9c102_sensor { char name[32], /* sensor name */ maintainer[64]; /* name of the mantainer */ - /* These sensor capabilities must be provided if the SN9C10X controller + /* + These sensor capabilities must be provided if the SN9C10X controller needs to communicate through the sensor serial interface by using - at least one of the i2c functions available */ + at least one of the i2c functions available. + */ enum sn9c102_i2c_frequency frequency; enum sn9c102_i2c_interface interface; - /* These identifiers must be provided if the image sensor implements - the standard I2C protocol. TASC sensors don't, although they have a - serial interface: so this is a case where the "raw" I2C version - could be helpful. */ + /* + These identifiers must be provided if the image sensor implements + the standard I2C protocol. + */ u8 slave_read_id, slave_write_id; /* reg. 0x09 */ - /* NOTE: Where not noted,most of the functions below are not mandatory. + /* + NOTE: Where not noted,most of the functions below are not mandatory. Set to null if you do not implement them. If implemented, - they must return 0 on success, the proper error otherwise. */ + they must return 0 on success, the proper error otherwise. + */ int (*init)(struct sn9c102_device* cam); - /* This function is called after the sensor has been attached. + /* + This function is called after the sensor has been attached. It should be used to initialize the sensor only, but may also configure part of the SN9C10X chip if necessary. You don't need to setup picture settings like brightness, contrast, etc.. here, if @@ -177,23 +225,30 @@ struct sn9c102_sensor { specified in the v4l2_queryctrl list of supported controls; Same suggestions apply for other settings, _if_ the corresponding methods are present; if not, the initialization must configure the - sensor according to the default configuration structures below. */ + sensor according to the default configuration structures below. + */ struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE]; - /* Optional list of default controls, defined as indicated in the - V4L2 API. Menu type controls are not handled by this interface. */ + /* + Optional list of default controls, defined as indicated in the + V4L2 API. Menu type controls are not handled by this interface. + */ int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl); int (*set_ctrl)(struct sn9c102_device* cam, const struct v4l2_control* ctrl); - /* You must implement at least the set_ctrl method if you have defined + /* + You must implement at least the set_ctrl method if you have defined the list above. The returned value must follow the V4L2 specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER are not supported by this driver, so do not implement them. Also, - passed values are NOT checked to see if they are out of bounds. */ + you don't have to check whether the passed values are out of bounds, + given that this is done by the core module. + */ struct v4l2_cropcap cropcap; - /* Think the image sensor as a grid of R,G,B monochromatic pixels + /* + Think the image sensor as a grid of R,G,B monochromatic pixels disposed according to a particular Bayer pattern, which describes the complete array of pixels, from (0,0) to (xmax, ymax). We will use this coordinate system from now on. It is assumed the sensor @@ -221,11 +276,13 @@ struct sn9c102_sensor { NOTE: once you have defined the bounds of the active window (struct cropcap.bounds) you must not change them.anymore. Only 'bounds' and 'defrect' fields are mandatory, other fields - will be ignored. */ + will be ignored. + */ int (*set_crop)(struct sn9c102_device* cam, const struct v4l2_rect* rect); - /* To be called on VIDIOC_C_SETCROP. The core module always calls a + /* + To be called on VIDIOC_C_SETCROP. The core module always calls a default routine which configures the appropriate SN9C10X regs (also scaling), but you may need to override/adjust specific stuff. 'rect' contains width and height values that are multiple of 16: in @@ -235,36 +292,56 @@ struct sn9c102_sensor { NOTE: in case, you must program the SN9C10X chip to get rid of blank pixels or blank lines at the _start_ of each line or frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12,0x13) (having set H_SIZE and, + real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, V_SIZE you don't have to care about blank pixels or blank - lines at the end of each line or frame). */ + lines at the end of each line or frame). + */ struct v4l2_pix_format pix_format; - /* What you have to define here are: initial 'width' and 'height' of - the target rectangle, the bayer 'pixelformat' and 'priv' which we'll - be used to indicate the number of bits per pixel, 8 or 9. - Nothing more. + /* + What you have to define here are: 1) initial 'width' and 'height' of + the target rectangle 2) the initial 'pixelformat', which can be + either V4L2_PIX_FMT_SN9C10X (for compressed video) or + V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the + number of bits per pixel for uncompressed video, 8 or 9 (despite the + current value of 'pixelformat'). NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 of cropcap.defrect.width and cropcap.defrect.height. I suggest 1/1. - NOTE 2: as said above, you have to program the SN9C10X chip to get + NOTE 2: The initial compression quality is defined by the first bit + of reg 0x17 during the initialization of the image sensor. + NOTE 3: as said above, you have to program the SN9C10X chip to get rid of any blank pixels, so that the output of the sensor - matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */ + matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). + */ const struct device* dev; - /* This is the argument for dev_err(), dev_info() and dev_warn(). It + /* + This is the argument for dev_err(), dev_info() and dev_warn(). It is used for debugging purposes. You must not access the struct - before the sensor is attached. */ + before the sensor is attached. + */ const struct usb_device* usbdev; - /* Points to the usb_device struct after the sensor is attached. - Do not touch unless you know what you are doing. */ + /* + Points to the usb_device struct after the sensor is attached. + Do not touch unless you know what you are doing. + */ - /* Do NOT write to the data below, it's READ ONLY. It is used by the + /* + Do NOT write to the data below, it's READ ONLY. It is used by the core module to store successfully updated values of the above - settings, for rollbacks..etc..in case of errors during atomic I/O */ + settings, for rollbacks..etc..in case of errors during atomic I/O + */ struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE]; struct v4l2_rect _rect; }; +/*****************************************************************************/ + +/* Private ioctl's for control settings supported by some image sensors */ +#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE +#define SN9C102_V4L2_CID_DAC_SIGN V4L2_CID_PRIVATE_BASE + 1 +#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 2 + #endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c index d67470013..03153cae2 100644 --- a/drivers/usb/media/sn9c102_tas5110c1b.c +++ b/drivers/usb/media/sn9c102_tas5110c1b.c @@ -1,6 +1,6 @@ /*************************************************************************** - * Driver for TAS5110C1B image sensor connected to the SN9C10[12] PC * - * Camera Controllers * + * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * + * Controllers * * * * Copyright (C) 2004 by Luca Risolia * * * @@ -24,6 +24,8 @@ static struct sn9c102_sensor tas5110c1b; +static struct v4l2_control tas5110c1b_gain; + static int tas5110c1b_init(struct sn9c102_device* cam) { @@ -33,15 +35,50 @@ static int tas5110c1b_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x44, 0x01); err += sn9c102_write_reg(cam, 0x00, 0x10); err += sn9c102_write_reg(cam, 0x00, 0x11); - err += sn9c102_write_reg(cam, 0x00, 0x14); + err += sn9c102_write_reg(cam, 0x0a, 0x14); err += sn9c102_write_reg(cam, 0x60, 0x17); err += sn9c102_write_reg(cam, 0x06, 0x18); - err += sn9c102_write_reg(cam, 0xcb, 0x19); + err += sn9c102_write_reg(cam, 0xfb, 0x19); + + err += sn9c102_i2c_write(cam, 0xc0, 0x80); return err; } +static int tas5110c1b_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_GAIN: + ctrl->value = tas5110c1b_gain.value; + break; + default: + return -EINVAL; + } + + return 0; +} + + +static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value))) + tas5110c1b_gain.value = ctrl->value; + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + static int tas5110c1b_set_crop(struct sn9c102_device* cam, const struct v4l2_rect* rect) { @@ -53,6 +90,11 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam, err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); + /* Don't change ! */ + err += sn9c102_write_reg(cam, 0x14, 0x1a); + err += sn9c102_write_reg(cam, 0x0a, 0x1b); + err += sn9c102_write_reg(cam, 0xfb, 0x19); + return err; } @@ -60,7 +102,24 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam, static struct sn9c102_sensor tas5110c1b = { .name = "TAS5110C1B", .maintainer = "Luca Risolia ", + .frequency = SN9C102_I2C_100KHZ, + .interface = SN9C102_I2C_3WIRES, + .slave_read_id = SN9C102_I2C_SLAVEID_UNAVAILABLE, + .slave_write_id = SN9C102_I2C_SLAVEID_FICTITIOUS, .init = &tas5110c1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x01, + .default_value = 0x40, + .flags = 0, + }, + }, + .set_ctrl = &tas5110c1b_set_ctrl, .cropcap = { .bounds = { .left = 0, @@ -75,6 +134,7 @@ static struct sn9c102_sensor tas5110c1b = { .height = 288, }, }, + .get_ctrl = &tas5110c1b_get_ctrl, .set_crop = &tas5110c1b_set_crop, .pix_format = { .width = 352, @@ -90,8 +150,10 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) /* This sensor has no identifiers, so let's attach it anyway */ sn9c102_attach_sensor(cam, &tas5110c1b); - /* At the moment, only devices whose PID is 0x6005 have this sensor */ - if (tas5110c1b.usbdev->descriptor.idProduct != 0x6005) + /* Sensor detection is based on USB pid/vid */ + if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 && + tas5110c1b.usbdev->descriptor.idProduct != 0x6005 && + tas5110c1b.usbdev->descriptor.idProduct != 0x60ab) return -ENODEV; return 0; diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c index 5f1b0f9a6..36b00d12a 100644 --- a/drivers/usb/media/sn9c102_tas5130d1b.c +++ b/drivers/usb/media/sn9c102_tas5130d1b.c @@ -1,6 +1,6 @@ /*************************************************************************** - * Driver for TAS5130D1B image sensor connected to the SN9C10[12] PC * - * Camera Controllers * + * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * + * Controllers * * * * Copyright (C) 2004 by Luca Risolia * * * @@ -24,6 +24,8 @@ static struct sn9c102_sensor tas5130d1b; +static struct v4l2_control tas5130d1b_gain, tas5130d1b_exposure; + static int tas5130d1b_init(struct sn9c102_device* cam) { @@ -37,38 +39,67 @@ static int tas5130d1b_init(struct sn9c102_device* cam) err += sn9c102_write_reg(cam, 0x00, 0x14); err += sn9c102_write_reg(cam, 0x60, 0x17); err += sn9c102_write_reg(cam, 0x07, 0x18); - err += sn9c102_write_reg(cam, 0x33, 0x19); - - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40, - 0x47, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20, - 0xa9, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0, - 0x49, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20, - 0x6c, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0, - 0x08, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x20, - 0x00, 0, 0); - - err += sn9c102_write_reg(cam, 0x63, 0x19); return err; } +static int tas5130d1b_get_ctrl(struct sn9c102_device* cam, + struct v4l2_control* ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_GAIN: + ctrl->value = tas5130d1b_gain.value; + break; + case V4L2_CID_EXPOSURE: + ctrl->value = tas5130d1b_exposure.value; + break; + default: + return -EINVAL; + } + + return 0; +} + + +static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, + const struct v4l2_control* ctrl) +{ + int err = 0; + + switch (ctrl->id) { + case V4L2_CID_GAIN: + if (!(err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value))) + tas5130d1b_gain.value = ctrl->value; + break; + case V4L2_CID_EXPOSURE: + if (!(err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value))) + tas5130d1b_exposure.value = ctrl->value; + break; + default: + return -EINVAL; + } + + return err ? -EIO : 0; +} + + static int tas5130d1b_set_crop(struct sn9c102_device* cam, const struct v4l2_rect* rect) { struct sn9c102_sensor* s = &tas5130d1b; - int err = 0; u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; + int err = 0; err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); + /* Do NOT change! */ + err += sn9c102_write_reg(cam, 0x1f, 0x1a); + err += sn9c102_write_reg(cam, 0x1a, 0x1b); + err += sn9c102_write_reg(cam, 0xf3, 0x19); + return err; } @@ -78,7 +109,33 @@ static struct sn9c102_sensor tas5130d1b = { .maintainer = "Luca Risolia ", .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_3WIRES, + .slave_read_id = SN9C102_I2C_SLAVEID_UNAVAILABLE, + .slave_write_id = SN9C102_I2C_SLAVEID_FICTITIOUS, .init = &tas5130d1b_init, + .qctrl = { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "global gain", + .minimum = 0x00, + .maximum = 0xf6, + .step = 0x02, + .default_value = 0x00, + .flags = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0x47, + .step = 0x01, + .default_value = 0x00, + .flags = 0, + }, + }, + .get_ctrl = &tas5130d1b_get_ctrl, + .set_ctrl = &tas5130d1b_set_ctrl, .cropcap = { .bounds = { .left = 0, @@ -108,13 +165,10 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) /* This sensor has no identifiers, so let's attach it anyway */ sn9c102_attach_sensor(cam, &tas5130d1b); - /* At the moment, only devices whose PID is 0x6025 have this sensor */ - if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025) + /* Sensor detection is based on USB pid/vid */ + if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025 && + tas5130d1b.usbdev->descriptor.idProduct != 0x60aa) return -ENODEV; - dev_info(tas5130d1b.dev, "TAS5130D1B detected, but the support for it " - "is disabled at the moment - needs further " - "testing -\n"); - - return -ENODEV; + return 0; } diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index af460298a..b8e798345 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c @@ -93,11 +93,11 @@ static unsigned int debug = 0; MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE ("GPL"); -MODULE_PARM (debug, "i"); +module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC (debug, "Debug enabled or not"); -MODULE_PARM (swapRGB_on, "i"); +module_param(swapRGB_on, int, 0); MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never"); -MODULE_PARM (video_nr, "i"); +module_param(video_nr, int, 0); /******************************************************************** * @@ -118,20 +118,6 @@ MODULE_PARM (video_nr, "i"); * * And the STV0680 driver - Kevin ********************************************************************/ - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -static inline unsigned long kvirt_to_pa (unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - static void *rvmalloc (unsigned long size) { void *mem; @@ -512,12 +498,6 @@ exit: /**************************************************************************** * sysfs ***************************************************************************/ -static inline struct usb_stv *cd_to_stv(struct class_device *cd) -{ - struct video_device *vdev = to_video_device(cd); - return video_get_drvdata(vdev); -} - #define stv680_file(name, variable, field) \ static ssize_t show_##name(struct class_device *class_dev, char *buf) \ { \ @@ -704,7 +684,6 @@ static int stv680_start_stream (struct usb_stv *stv680) usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), stv680->sbuf[i].data, stv680->rawbufsize, stv680_video_irq, stv680); - urb->timeout = PENCAM_TIMEOUT * 2; stv680->urb[i] = urb; err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); if (err) @@ -726,7 +705,7 @@ static int stv680_stop_stream (struct usb_stv *stv680) for (i = 0; i < STV680_NUMSBUF; i++) if (stv680->urb[i]) { - usb_unlink_urb (stv680->urb[i]); + usb_kill_urb (stv680->urb[i]); usb_free_urb (stv680->urb[i]); stv680->urb[i] = NULL; kfree (stv680->sbuf[i].data); @@ -1292,8 +1271,8 @@ static int stv680_mmap (struct file *file, struct vm_area_struct *vma) } pos = (unsigned long) stv680->fbuf; while (size > 0) { - page = kvirt_to_pa (pos); - if (remap_page_range (vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { up (&stv680->lock); return -EAGAIN; } @@ -1458,7 +1437,7 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680) for (i = 0; i < STV680_NUMSBUF; i++) if (stv680->urb[i]) { - usb_unlink_urb (stv680->urb[i]); + usb_kill_urb (stv680->urb[i]); usb_free_urb (stv680->urb[i]); stv680->urb[i] = NULL; kfree (stv680->sbuf[i].data); diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c index cbaf7d804..84f38839c 100644 --- a/drivers/usb/media/ultracam.c +++ b/drivers/usb/media/ultracam.c @@ -60,9 +60,9 @@ static int init_color = 128; static int init_hue = 128; static int hue_correction = 128; -MODULE_PARM(debug, "i"); +module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -MODULE_PARM(flags, "i"); +module_param(flags, int, 0); MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, " "1=B/W, " @@ -71,18 +71,18 @@ MODULE_PARM_DESC(flags, "4=test pattern, " "5=separate frames, " "6=clean frames"); -MODULE_PARM(framerate, "i"); +module_param(framerate, int, 0); MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -MODULE_PARM(init_brightness, "i"); +module_param(init_brightness, int, 0); MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -MODULE_PARM(init_contrast, "i"); +module_param(init_contrast, int, 0); MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -MODULE_PARM(init_color, "i"); +module_param(init_color, int, 0); MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -MODULE_PARM(init_hue, "i"); +module_param(init_hue, int, 0); MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -MODULE_PARM(hue_correction, "i"); +module_param(hue_correction, int, 0); MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); /* diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c index d46b136c9..543d465e7 100644 --- a/drivers/usb/media/usbvideo.c +++ b/drivers/usb/media/usbvideo.c @@ -34,7 +34,7 @@ #endif static int video_nr = -1; -MODULE_PARM(video_nr, "i"); +module_param(video_nr, int, 0); /* * Local prototypes. @@ -60,21 +60,6 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, /*******************************/ /* Memory management functions */ /*******************************/ - -/* - * Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ -unsigned long usbvideo_kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - static void *usbvideo_rvmalloc(unsigned long size) { void *mem; @@ -519,72 +504,6 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) } } -/* - * usbvideo_DrawLine() - * - * A standard implementation of Bresenham's line drawing algorithm. - * This procedure is provided primarily for debugging or demo - * purposes. - */ -void usbvideo_DrawLine( - struct usbvideo_frame *frame, - int x1, int y1, - int x2, int y2, - unsigned char cr, unsigned char cg, unsigned char cb) -{ - int i, dx, dy, np, d; - int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2; - - if ((dx = x2 - x1) < 0) - dx = -dx; - if ((dy = y2 - y1) < 0) - dy = -dy; - if (dx >= dy) { - np = dx + 1; - d = (2 * dy) - dx; - dinc1 = dy << 1; - dinc2 = (dy - dx) << 1; - xinc1 = 1; - xinc2 = 1; - yinc1 = 0; - yinc2 = 1; - } else { - np = dy + 1; - d = (2 * dx) - dy; - dinc1 = dx << 1; - dinc2 = (dx - dy) << 1; - xinc1 = 0; - xinc2 = 1; - yinc1 = 1; - yinc2 = 1; - } - /* Make sure x and y move in the right directions */ - if (x1 > x2) { - xinc1 = -xinc1; - xinc2 = -xinc2; - } - if (y1 > y2) { - yinc1 = -yinc1; - yinc2 = -yinc2; - } - for (i=0, x=x1, y=y1; i < np; i++) { - if (frame->palette == VIDEO_PALETTE_RGB24) { -/* TODO */ RGB24_PUTPIXEL(frame, x, y, cr, cg, cb); - } - if (d < 0) { - d += dinc1; - x += xinc1; - y += yinc1; - } else { - d += dinc2; - x += xinc2; - y += yinc2; - } - } -} - -EXPORT_SYMBOL(usbvideo_DrawLine); - /* * usbvideo_TestPattern() * @@ -673,6 +592,8 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) EXPORT_SYMBOL(usbvideo_TestPattern); + +#ifdef DEBUG /* * usbvideo_HexDump() * @@ -702,16 +623,7 @@ void usbvideo_HexDump(const unsigned char *data, int len) EXPORT_SYMBOL(usbvideo_HexDump); -/* Debugging aid */ -void usbvideo_SayAndWait(const char *what) -{ - wait_queue_head_t wq; - init_waitqueue_head(&wq); - info("Say: %s", what); - interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */ -} - -EXPORT_SYMBOL(usbvideo_SayAndWait); +#endif /* ******************************************************************** */ @@ -1168,8 +1080,8 @@ static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) pos = (unsigned long) uvd->fbuf; while (size > 0) { - page = usbvideo_kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; @@ -1910,9 +1822,7 @@ static void usbvideo_StopDataPump(struct uvd *uvd) /* Unschedule all of the iso td's */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { - j = usb_unlink_urb(uvd->sbuf[i].urb); - if (j < 0) - err("%s: usb_unlink_urb() error %d.", __FUNCTION__, j); + usb_kill_urb(uvd->sbuf[i].urb); } if (uvd->debug > 1) info("%s: streaming=0", __FUNCTION__); diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 1e416c1de..411608f1b 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -351,16 +351,6 @@ static unsigned char setup5[] = { 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00 }; -static unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - /* rvmalloc / rvfree copied from usbvideo.c * * Not sure why these are not yet non-statics which I can reference through @@ -1055,8 +1045,8 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma) pos = (unsigned long)cam->framebuf; while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 36fbe800f..6604a30d5 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -111,30 +111,30 @@ module_param(ovmod_load, bool, 0644); module_param(vppmod_load, bool, 0444); #endif module_param(simcams, ushort, 0644); -module_param_array(video_nr, short, param_nv[0], 0444); -module_param_array(packet_size, uint, param_nv[1], 0444); -module_param_array(max_buffers, ushort, param_nv[2], 0444); -module_param_array(double_buffer, bool, param_nv[3], 0444); -module_param_array(clamping, bool, param_nv[4], 0444); -module_param_array(filter_type, ushort, param_nv[5], 0444); -module_param_array(largeview, bool, param_nv[6], 0444); -module_param_array(decompression, ushort, param_nv[7], 0444); -module_param_array(upscaling, bool, param_nv[8], 0444); -module_param_array(force_palette, ushort, param_nv[9], 0444); -module_param_array(force_rgb, ushort, param_nv[10], 0444); -module_param_array(autobright, bool, param_nv[11], 0444); -module_param_array(autoexp, bool, param_nv[12], 0444); -module_param_array(lightfreq, ushort, param_nv[13], 0444); -module_param_array(bandingfilter, bool, param_nv[14], 0444); -module_param_array(clockdiv, short, param_nv[15], 0444); -module_param_array(backlight, bool, param_nv[16], 0444); -module_param_array(mirror, bool, param_nv[17], 0444); -module_param_array(monochrome, bool, param_nv[18], 0444); -module_param_array(brightness, uint, param_nv[19], 0444); -module_param_array(hue, uint, param_nv[20], 0444); -module_param_array(colour, uint, param_nv[21], 0444); -module_param_array(contrast, uint, param_nv[22], 0444); -module_param_array(whiteness, uint, param_nv[23], 0444); +module_param_array(video_nr, short, ¶m_nv[0], 0444); +module_param_array(packet_size, uint, ¶m_nv[1], 0444); +module_param_array(max_buffers, ushort, ¶m_nv[2], 0444); +module_param_array(double_buffer, bool, ¶m_nv[3], 0444); +module_param_array(clamping, bool, ¶m_nv[4], 0444); +module_param_array(filter_type, ushort, ¶m_nv[5], 0444); +module_param_array(largeview, bool, ¶m_nv[6], 0444); +module_param_array(decompression, ushort, ¶m_nv[7], 0444); +module_param_array(upscaling, bool, ¶m_nv[8], 0444); +module_param_array(force_palette, ushort, ¶m_nv[9], 0444); +module_param_array(force_rgb, ushort, ¶m_nv[10], 0444); +module_param_array(autobright, bool, ¶m_nv[11], 0444); +module_param_array(autoexp, bool, ¶m_nv[12], 0444); +module_param_array(lightfreq, ushort, ¶m_nv[13], 0444); +module_param_array(bandingfilter, bool, ¶m_nv[14], 0444); +module_param_array(clockdiv, short, ¶m_nv[15], 0444); +module_param_array(backlight, bool, ¶m_nv[16], 0444); +module_param_array(mirror, bool, ¶m_nv[17], 0444); +module_param_array(monochrome, bool, ¶m_nv[18], 0444); +module_param_array(brightness, uint, ¶m_nv[19], 0444); +module_param_array(hue, uint, ¶m_nv[20], 0444); +module_param_array(colour, uint, ¶m_nv[21], 0444); +module_param_array(contrast, uint, ¶m_nv[22], 0444); +module_param_array(whiteness, uint, ¶m_nv[23], 0444); #ifdef W9968CF_DEBUG module_param(debug, ushort, 0644); module_param(specific_debug, bool, 0644); @@ -457,7 +457,6 @@ static int w9968cf_i2c_control(struct i2c_adapter*, unsigned int cmd, unsigned long arg); /* Memory management */ -static inline unsigned long kvirt_to_pa(unsigned long adr); static void* rvmalloc(unsigned long size); static void rvfree(void *mem, unsigned long size); static void w9968cf_deallocate_memory(struct w9968cf_device*); @@ -611,20 +610,6 @@ static struct w9968cf_symbolic_list urb_errlist[] = { /**************************************************************************** * Memory management functions * ****************************************************************************/ - -/* Here we want the physical address of the memory. - This is used when initializing the contents of the area. */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - - static void* rvmalloc(unsigned long size) { void* mem; @@ -2919,9 +2904,9 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma) return -EINVAL; while (vsize > 0) { - page = kvirt_to_pa(pos) + vma->vm_pgoff; - if (remap_page_range(vma, start, page, PAGE_SIZE, - vma->vm_page_prot)) + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page + vma->vm_pgoff, + PAGE_SIZE, vma->vm_page_prot)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h index e910f26de..988125ab3 100644 --- a/drivers/usb/media/w9968cf.h +++ b/drivers/usb/media/w9968cf.h @@ -135,7 +135,7 @@ static const struct w9968cf_format w9968cf_formatlist[] = { #define W9968CF_MODULE_NAME "V4L driver for W996[87]CF JPEG USB " \ "Dual Mode Camera Chip" -#define W9968CF_MODULE_VERSION "1:1.32-basic" +#define W9968CF_MODULE_VERSION "1:1.33-basic" #define W9968CF_MODULE_AUTHOR "(C) 2002-2004 Luca Risolia" #define W9968CF_AUTHOR_EMAIL "" #define W9968CF_MODULE_LICENSE "GPL" diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8c958af4a..a3dd6f03e 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -121,17 +121,15 @@ config USB_CYTHERM To compile this driver as a module, choose M here: the module will be called cytherm. -config USB_SPEEDTOUCH - tristate "Alcatel Speedtouch USB support" - depends on USB && ATM - select CRC32 +config USB_PHIDGETKIT + tristate "USB PhidgetKit support" + depends on USB help - Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330 - modem. In order to use your modem you will need to install some user - space tools, see for details. + Say Y here if you want to connect a PhidgetKit USB device from + Phidgets Inc. To compile this driver as a module, choose M here: the - module will be called speedtch. + module will be called phidgetkit. config USB_PHIDGETSERVO tristate "USB PhidgetServo support" diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index d641a470e..4936caf5f 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -10,9 +10,9 @@ obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o +obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o +obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o -obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TIGL) += tiglusb.o obj-$(CONFIG_USB_USS720) += uss720.o -obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 310c5a96c..94842c34a 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -269,7 +269,7 @@ typedef struct /* Forwards */ static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs); static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp); -extern struct usb_driver auerswald_driver; +static struct usb_driver auerswald_driver; /*-------------------------------------------------------------------*/ @@ -516,7 +516,7 @@ static void auerchain_unlink_all (pauerchain_t acp) urbp = acep->urbp; urbp->transfer_flags &= ~URB_ASYNC_UNLINK; dbg ("unlink active urb"); - usb_unlink_urb (urbp); + usb_kill_urb (urbp); } } @@ -1037,7 +1037,8 @@ static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs) /* now extract the information */ channelid = cp->intbufp[2]; - bytecount = le16_to_cpup (&cp->intbufp[3]); + bytecount = (unsigned char)cp->intbufp[3]; + bytecount |= (unsigned char)cp->intbufp[4] << 8; /* check the channel id */ if (channelid >= AUH_TYPESIZE) { @@ -1170,22 +1171,16 @@ intoend: endpoint. This function returns 0 if successful or an error code. NOTE: no mutex please! */ -static int auerswald_int_release (pauerswald_t cp) +static void auerswald_int_release (pauerswald_t cp) { - int ret = 0; dbg ("auerswald_int_release"); /* stop the int endpoint */ - if (cp->inturbp) { - ret = usb_unlink_urb (cp->inturbp); - if (ret) - dbg ("nonzero int unlink result received: %d", ret); - } + if (cp->inturbp) + usb_kill_urb (cp->inturbp); /* deallocate memory */ auerswald_int_free (cp); - - return ret; } /* --------------------------------------------------------------------- */ @@ -1930,7 +1925,7 @@ static int auerswald_probe (struct usb_interface *intf, struct usb_device *usbdev = interface_to_usbdev(intf); pauerswald_t cp = NULL; unsigned int u = 0; - char *pbuf; + __le16 *pbuf; int ret; dbg ("probe: vendor id 0x%x, device id 0x%x", @@ -1976,8 +1971,7 @@ static int auerswald_probe (struct usb_interface *intf, dbg ("Version is %X", cp->version); /* allow some time to settle the device */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/3); + msleep(334); /* Try to get a suitable textual description of the device */ /* Device name:*/ @@ -2003,7 +1997,7 @@ static int auerswald_probe (struct usb_interface *intf, info("device is a %s", cp->dev_desc); /* get the maximum allowed control transfer length */ - pbuf = (char *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ + pbuf = (__le16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ if (!pbuf) { err( "out of memory"); goto pfail; diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index cd7b548b9..e83e91148 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -71,6 +71,8 @@ * - make device locking interruptible * 2004-04-30 - 0.95 Juergen Stuber * - check for valid udev on resubmitting and unlinking urbs + * 2004-08-03 - 0.96 Juergen Stuber + * - move reset into open to clean out spurious data */ #include @@ -98,12 +100,12 @@ /* Version Information */ -#define DRIVER_VERSION "v0.95" +#define DRIVER_VERSION "v0.96" #define DRIVER_AUTHOR "Juergen Stuber " #define DRIVER_DESC "LEGO USB Tower Driver" /* Module parameters */ -MODULE_PARM(debug, "i"); +module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); /* The defaults are chosen to work with the latest versions of leJOS and NQC. @@ -113,8 +115,8 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); * In this case read_buffer_size should exceed the maximal packet length * (417 for datalog uploads), and packet_timeout should be set. */ -static size_t read_buffer_size = 480; -MODULE_PARM(read_buffer_size, "i"); +static int read_buffer_size = 480; +module_param(read_buffer_size, int, 0); MODULE_PARM_DESC(read_buffer_size, "Read buffer size"); /* Some legacy software likes to send packets in one piece. @@ -123,8 +125,8 @@ MODULE_PARM_DESC(read_buffer_size, "Read buffer size"); * A problem with long writes is that the following read may time out * if the software is not prepared to wait long enough. */ -static size_t write_buffer_size = 480; -MODULE_PARM(write_buffer_size, "i"); +static int write_buffer_size = 480; +module_param(write_buffer_size, int, 0); MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); /* Some legacy software expects reads to contain whole LASM packets. @@ -138,7 +140,7 @@ MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); * Set it to 0 to disable. */ static int packet_timeout = 50; -MODULE_PARM(packet_timeout, "i"); +module_param(packet_timeout, int, 0); MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms"); /* Some legacy software expects blocking reads to time out. @@ -146,7 +148,7 @@ MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms"); * Set it to 0 to disable. */ static int read_timeout = 200; -MODULE_PARM(read_timeout, "i"); +module_param(read_timeout, int, 0); MODULE_PARM_DESC(read_timeout, "Read timeout in ms"); /* As of kernel version 2.6.4 ehci-hcd uses an @@ -159,11 +161,11 @@ MODULE_PARM_DESC(read_timeout, "Read timeout in ms"); * or set to 0 to use the standard interval from the endpoint descriptors. */ static int interrupt_in_interval = 2; -MODULE_PARM(interrupt_in_interval, "i"); +module_param(interrupt_in_interval, int, 0); MODULE_PARM_DESC(interrupt_in_interval, "Interrupt in interval in ms"); static int interrupt_out_interval = 8; -MODULE_PARM(interrupt_out_interval, "i"); +module_param(interrupt_out_interval, int, 0); MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms"); /* Define these values to match your device */ @@ -175,18 +177,18 @@ MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms"); #define LEGO_USB_TOWER_REQUEST_GET_VERSION 0xFD struct tower_reset_reply { - __u16 size; /* little-endian */ + __le16 size; /* little-endian */ __u8 err_code; __u8 spare; } __attribute__ ((packed)); struct tower_get_version_reply { - __u16 size; /* little-endian */ + __le16 size; /* little-endian */ __u8 err_code; __u8 spare; __u8 major; __u8 minor; - __u16 build_no; /* little-endian */ + __le16 build_no; /* little-endian */ } __attribute__ ((packed)); @@ -341,6 +343,8 @@ static int tower_open (struct inode *inode, struct file *file) int subminor; int retval = 0; struct usb_interface *interface; + struct tower_reset_reply reset_reply; + int result; dbg(2, "%s: enter", __FUNCTION__); @@ -378,6 +382,22 @@ static int tower_open (struct inode *inode, struct file *file) } dev->open_count = 1; + /* reset the tower */ + result = usb_control_msg (dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + LEGO_USB_TOWER_REQUEST_RESET, + USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + 0, + 0, + &reset_reply, + sizeof(reset_reply), + HZ); + if (result < 0) { + err("LEGO USB Tower reset control request failed"); + retval = result; + goto unlock_exit; + } + /* initialize in direction */ dev->read_buffer_length = 0; dev->read_packet_length = 0; @@ -485,12 +505,12 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) dev->interrupt_in_running = 0; mb(); if (dev->interrupt_in_urb != NULL && dev->udev) { - usb_unlink_urb (dev->interrupt_in_urb); + usb_kill_urb (dev->interrupt_in_urb); } } if (dev->interrupt_out_busy) { if (dev->interrupt_out_urb != NULL && dev->udev) { - usb_unlink_urb (dev->interrupt_out_urb); + usb_kill_urb (dev->interrupt_out_urb); } } @@ -694,7 +714,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t } /* write the data into interrupt_out_buffer from userspace */ - bytes_to_write = min(count, write_buffer_size); + bytes_to_write = min_t(int, count, write_buffer_size); dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write); if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { @@ -828,7 +848,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device struct lego_usb_tower *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor* endpoint; - struct tower_reset_reply reset_reply; struct tower_get_version_reply get_version_reply; int i; int retval = -ENOMEM; @@ -951,22 +970,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device /* let the user know what node this device is now attached to */ info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor); - /* reset the tower */ - result = usb_control_msg (udev, - usb_rcvctrlpipe(udev, 0), - LEGO_USB_TOWER_REQUEST_RESET, - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, - &reset_reply, - sizeof(reset_reply), - HZ); - if (result < 0) { - err("LEGO USB Tower reset control request failed"); - retval = result; - goto error; - } - /* get the firmware version and log it */ result = usb_control_msg (udev, usb_rcvctrlpipe(udev, 0), diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index b89b53401..8cca7e747 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c @@ -12,8 +12,6 @@ * controllers available at: http://www.phidgets.com/ * * Note that the driver takes input as: degrees.minutes - * -23 < degrees < 203 - * 0 < minutes < 59 * * CAUTION: Generally you should use 0 < degrees < 180 as anything else * is probably beyond the range of your servo and may damage it. @@ -21,6 +19,10 @@ * Jun 16, 2004: Sean Young * - cleanups * - was using memory after kfree() + * Aug 8, 2004: Sean Young + * - set the highest angle as high as the hardware allows, there are + * some odd servos out there + * */ #include @@ -87,6 +89,9 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, int retval; unsigned char *buffer; + if (degrees < -23 || degrees > 362) + return -EINVAL; + buffer = kmalloc(6, GFP_KERNEL); if (!buffer) { dev_err(&servo->udev->dev, "%s - out of memory\n", @@ -157,6 +162,9 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, int retval; unsigned char *buffer; + if (degrees < -23 || degrees > 278) + return -EINVAL; + buffer = kmalloc(2, GFP_KERNEL); if (!buffer) { dev_err(&servo->udev->dev, "%s - out of memory\n", @@ -212,10 +220,8 @@ static ssize_t set_servo##value (struct device *dev, \ return -EINVAL; \ } \ \ - if (degrees < -23 || degrees > (180 + 23) || \ - minutes < 0 || minutes > 59) { \ + if (minutes < 0 || minutes > 59) \ return -EINVAL; \ - } \ \ if (servo->type & SERVO_VERSION_30) \ retval = change_position_v30 (servo, value, degrees, \ diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index e90a334f7..6a6e3de91 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -170,13 +170,11 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", - le32_to_cpu(result)); + err("Error executing ioctrl. code = %d", result); retries = 0; } else { - dbg("Executed ioctl. Result = %d (data=%04x)", - le32_to_cpu(result), - le32_to_cpu(*((long *) buffer))); + dbg("Executed ioctl. Result = %d (data=%02x)", + result, buffer[0]); if (copy_to_user(rio_cmd.buffer, buffer, rio_cmd.length)) { free_page((unsigned long) buffer); @@ -239,12 +237,10 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, if (result == -ETIMEDOUT) retries--; else if (result < 0) { - err("Error executing ioctrl. code = %d", - le32_to_cpu(result)); + err("Error executing ioctrl. code = %d", result); retries = 0; } else { - dbg("Executed ioctl. Result = %d", - le32_to_cpu(result)); + dbg("Executed ioctl. Result = %d", result); retries = 0; } diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c index cdf5919f8..4a5d2b002 100644 --- a/drivers/usb/misc/tiglusb.c +++ b/drivers/usb/misc/tiglusb.c @@ -4,7 +4,7 @@ * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org). * * Copyright (C) 2001-2004: - * Romain Lievin + * Romain Lievin * Julien BLACHE * under the terms of the GNU General Public License. * @@ -14,7 +14,7 @@ * and the website at: http://lpg.ticalc.org/prj_usb/ * for more info. * - * History : + * History: * 1.0x, Romain & Julien: initial submit. * 1.03, Greg Kroah: modifications. * 1.04, Julien: clean-up & fixes; Romain: 2.4 backport. @@ -22,6 +22,7 @@ * 1.06, Romain: synched with 2.5, version/firmware changed (confusing). * 1.07, Romain: fixed bad use of usb_clear_halt (invalid argument); * timeout argument checked in ioctl + clean-up. + * 1.08, Romain: added support of USB port embedded on some TI's handhelds. */ #include @@ -41,7 +42,7 @@ /* * Version Information */ -#define DRIVER_VERSION "1.07" +#define DRIVER_VERSION "1.08" #define DRIVER_AUTHOR "Romain Lievin & Julien Blache " #define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver" #define DRIVER_LICENSE "GPL" @@ -115,7 +116,7 @@ tiglusb_open (struct inode *inode, struct file *filp) return -EBUSY; } - schedule_timeout (HZ / 2); + msleep_interruptible(500); if (signal_pending (current)) { return -EAGAIN; @@ -177,11 +178,11 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos) if (!s->dev) return -EIO; - buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL); + buffer = kmalloc (s->max_ps, GFP_KERNEL); if (!buffer) return -ENOMEM; - bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count; + bytes_to_read = (count >= s->max_ps) ? s->max_ps : count; pipe = usb_rcvbulkpipe (s->dev, 1); result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read, @@ -234,11 +235,11 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * if (!s->dev) return -EIO; - buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL); + buffer = kmalloc (s->max_ps, GFP_KERNEL); if (!buffer) return -ENOMEM; - bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count; + bytes_to_write = (count >= s->max_ps) ? s->max_ps : count; if (copy_from_user (buffer, buf, bytes_to_write)) { ret = -EFAULT; goto out; @@ -308,6 +309,15 @@ tiglusb_ioctl (struct inode *inode, struct file *filp, if (clear_pipes (s->dev)) ret = -EIO; break; + case IOCTL_TIUSB_GET_MAXPS: + if (copy_to_user((int __user *) arg, &s->max_ps, sizeof(int))) + return -EFAULT; + break; + case IOCTL_TIUSB_GET_DEVID: + if (copy_to_user((int __user *) arg, &s->dev->descriptor.idProduct, + sizeof(int))) + return -EFAULT; + break; default: ret = -ENOTTY; break; @@ -340,6 +350,9 @@ tiglusb_probe (struct usb_interface *intf, int minor = -1; int i, err = 0; ptiglusb_t s; + struct usb_host_config *conf; + struct usb_host_interface *ifdata = NULL; + int max_ps; dbg ("probing vendor id 0x%x, device id 0x%x", dev->descriptor.idVendor, dev->descriptor.idProduct); @@ -354,19 +367,31 @@ tiglusb_probe (struct usb_interface *intf, goto out; } - if ((dev->descriptor.idProduct != 0xe001) - && (dev->descriptor.idVendor != 0x451)) { + if (dev->descriptor.idVendor != 0x451) { err = -ENODEV; goto out; } - // NOTE: it's already in this config, this shouldn't be needed. - // is this working around some hardware bug? - if (usb_reset_configuration (dev) < 0) { - err ("tiglusb_probe: reset_configuration failed"); - err = -ENODEV; - goto out; - } + if ((dev->descriptor.idProduct != 0xe001) && + (dev->descriptor.idProduct != 0xe004) && + (dev->descriptor.idProduct != 0xe008)) { + err = -ENODEV; + goto out; + } + + /* + * TI introduced some new handhelds with embedded USB port. + * Port advertises same config as SilverLink cable but with a + * different maximum packet size (64 rather than 32). + */ + + conf = dev->actconfig; + ifdata = conf->interface[0]->cur_altsetting; + max_ps = ifdata->endpoint[0].desc.wMaxPacketSize; + + info("max packet size of %d/%d bytes\n", + ifdata->endpoint[0].desc.wMaxPacketSize, + ifdata->endpoint[1].desc.wMaxPacketSize); /* * Find a tiglusb struct @@ -389,6 +414,7 @@ tiglusb_probe (struct usb_interface *intf, down (&s->mutex); s->remove_pending = 0; s->dev = dev; + s->max_ps = max_ps; up (&s->mutex); dbg ("bound to interface"); @@ -560,7 +586,7 @@ MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE (DRIVER_LICENSE); -MODULE_PARM (timeout, "i"); +module_param(timeout, int, 0); MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)"); /* --------------------------------------------------------------------- */ diff --git a/drivers/usb/misc/tiglusb.h b/drivers/usb/misc/tiglusb.h index 627a3728d..0c90cb290 100644 --- a/drivers/usb/misc/tiglusb.h +++ b/drivers/usb/misc/tiglusb.h @@ -17,12 +17,6 @@ */ #define MAXTIGL 16 -/* - * Max. packetsize for IN and OUT pipes - */ -#define BULK_RCV_MAX 32 -#define BULK_SND_MAX 32 - /* * The driver context... */ @@ -42,6 +36,8 @@ typedef struct driver_state_t state; /* started/stopped */ int opened; /* tru if open */ int remove_pending; + + int max_ps; /* max packet size */ } tiglusb_t, *ptiglusb_t; #endif diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8ee1b05ea..d630edfac 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1054,8 +1054,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size); if (!urb) return -ENOMEM; - if (async) - urb->transfer_flags |= URB_ASYNC_UNLINK; + urb->transfer_flags |= URB_ASYNC_UNLINK; urb->context = &completion; urb->complete = unlink1_callback; @@ -1074,17 +1073,20 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) * hcd states and code paths, even with little other system load. */ msleep (jiffies % (2 * INTERRUPT_RATE)); + if (async) { retry: - retval = usb_unlink_urb (urb); - if (retval == -EBUSY || retval == -EIDRM) { - /* we can't unlink urbs while they're completing. - * or if they've completed, and we haven't resubmitted. - * "normal" drivers would prevent resubmission, but - * since we're testing unlink paths, we can't. - */ - dev_dbg (&dev->intf->dev, "unlink retry\n"); - goto retry; - } + retval = usb_unlink_urb (urb); + if (retval == -EBUSY || retval == -EIDRM) { + /* we can't unlink urbs while they're completing. + * or if they've completed, and we haven't resubmitted. + * "normal" drivers would prevent resubmission, but + * since we're testing unlink paths, we can't. + */ + dev_dbg (&dev->intf->dev, "unlink retry\n"); + goto retry; + } + } else + usb_kill_urb (urb); if (!(retval == 0 || retval == -EINPROGRESS)) { dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval); return retval; @@ -1095,9 +1097,10 @@ retry: simple_free_urb (urb); if (async) - return (retval != -ECONNRESET) ? -ECONNRESET : 0; + return (retval == -ECONNRESET) ? 0 : retval - 1000; else - return (retval != -ENOENT) ? -ENOENT : 0; + return (retval == -ENOENT || retval == -EPERM) ? + 0 : retval - 2000; } static int unlink_simple (struct usbtest_dev *dev, int pipe, int len) @@ -1352,7 +1355,7 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) "iso test, %lu errors\n", ctx->errors); complete (&ctx->done); - } else + } done: spin_unlock(&ctx->lock); } @@ -1454,8 +1457,10 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, status = usb_submit_urb (urbs [i], SLAB_ATOMIC); if (status < 0) { ERROR (dev, "submit iso[%d], error %d\n", i, status); - if (i == 0) + if (i == 0) { + spin_unlock_irq (&context.lock); goto fail; + } simple_free_urb (urbs [i]); context.pending--; diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 0bc5ccc24..8b22320d5 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -44,6 +44,7 @@ #include #include #include +#include /* * Version Information @@ -159,8 +160,7 @@ static int change_mode(struct parport *pp, int m) if (time_after_eq (jiffies, expire)) /* The FIFO is stuck. */ return -EBUSY; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((HZ + 99) / 100); + msleep_interruptible(10); if (signal_pending (current)) break; } diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 5d5881db6..d64409e85 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -1,15 +1,15 @@ # # USB Network devices configuration # -comment "USB Network adaptors" - depends on USB - -comment "Networking support is needed for USB Networking device support" +comment "Networking support is needed for USB Network Adapter support" depends on USB && !NET +menu "USB Network Adapters" + depends on USB && NET + config USB_CATC tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)" - depends on USB && NET && EXPERIMENTAL + depends on EXPERIMENTAL select CRC32 ---help--- Say Y if you want to use one of the following 10Mbps USB Ethernet @@ -29,7 +29,6 @@ config USB_CATC config USB_KAWETH tristate "USB KLSI KL5USB101-based ethernet device support" - depends on USB && NET ---help--- Say Y here if you want to use one of the following 10Mbps only USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: @@ -69,7 +68,6 @@ config USB_KAWETH config USB_PEGASUS tristate "USB Pegasus/Pegasus-II based ethernet device support" - depends on USB && NET select MII ---help--- Say Y here if you know you have Pegasus or Pegasus-II based adapter. @@ -85,7 +83,7 @@ config USB_PEGASUS config USB_RTL8150 tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)" - depends on USB && NET && EXPERIMENTAL + depends on EXPERIMENTAL help Say Y here if you have RTL8150 based usb-ethernet adapter. Send me any comments you may have. @@ -96,7 +94,6 @@ config USB_RTL8150 config USB_USBNET tristate "Multi-purpose USB Networking Framework" - depends on USB && NET ---help--- This driver supports several kinds of network links over USB, with "minidrivers" built around a common network driver core @@ -185,6 +182,14 @@ config USB_PL2301 Choose this option if you're using a host-to-host cable with one of these chips. +config USB_KC2190 + boolean "KT Technology KC2190 based cables (InstaNet)" + default y + depends on USB_USBNET && EXPERIMENTAL + help + Choose this option if you're using a host-to-host cable + with one of these chips. + comment "Intelligent USB Devices/Gadgets" depends on USB_USBNET @@ -198,6 +203,9 @@ config USB_ARMLINUX such as the SA-11x0 and PXA-25x UDCs, or the tftp capabilities in some PXA versions of the "blob" boot loader. + Linux-based "Gumstix" PXA-25x based systems use this protocol + to talk with other Linux systems. + Although the ROMs shipped with Sharp Zaurus products use a different link level framing protocol, you can have them use this simpler protocol by installing a different kernel. @@ -258,17 +266,20 @@ config USB_AX8817X select MII default y help - This option adds support for ASIX AX88172 based USB 2.0 10/100 Ethernet devices. This driver should work with at least the following devices: * Aten UC210T * ASIX AX88172 + * Billionton Systems, USB2AR + * Buffalo LUA-U2-KTX + * Corega FEther USB2-TX * D-Link DUB-E100 * Hawking UF200 * Linksys USB200M * Netgear FA120 + * Sitecom LN-029 * Intellinet USB 2.0 Ethernet * ST Lab USB 2.0 Ethernet * TrendNet TU2-ET100 @@ -276,4 +287,4 @@ config USB_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. - +endmenu diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index de9bf863e..c825ef78c 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #undef DEBUG @@ -242,7 +242,7 @@ static void catc_rx_done(struct urb *urb, struct pt_regs *regs) do { if(!catc->is_f5u011) { - pkt_len = le16_to_cpup((u16*)pkt_start); + pkt_len = le16_to_cpup((__le16*)pkt_start); if (pkt_len > urb->actual_length) { catc->stats.rx_length_errors++; catc->stats.rx_errors++; @@ -303,7 +303,7 @@ static void catc_irq_done(struct urb *urb, struct pt_regs *regs) else if (data[1] & 0x20) linksts = LinkBad; } else { - hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff); + hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff); if (data[0] == 0x90) linksts = LinkGood; else if (data[0] == 0xA0) @@ -411,7 +411,7 @@ static void catc_tx_done(struct urb *urb, struct pt_regs *regs) static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); unsigned long flags; char *tx_buf; @@ -442,7 +442,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) static void catc_tx_timeout(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); warn("Transmit timed out."); catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; @@ -604,7 +604,7 @@ static void catc_stats_timer(unsigned long data) static struct net_device_stats *catc_get_stats(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); return &catc->stats; } @@ -622,7 +622,7 @@ static void catc_multicast(unsigned char *addr, u8 *multicast) static void catc_set_multicast_list(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); struct dev_mc_list *mc; u8 broadcast[6]; u8 rx = RxEnable | RxPolarity | RxMultiCast; @@ -664,74 +664,38 @@ static void catc_set_multicast_list(struct net_device *netdev) } } -/* - * ioctl's - */ -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct catc *catc = dev->priv; - u32 cmd; - - if (get_user(cmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (cmd) { - /* get driver info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path (catc->usbdev, info.bus_info, sizeof info.bus_info); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: - if (catc->is_f5u011) { - struct ethtool_cmd ecmd = { ETHTOOL_GSET, - SUPPORTED_10baseT_Half | SUPPORTED_TP, - ADVERTISED_10baseT_Half | ADVERTISED_TP, - SPEED_10, - DUPLEX_HALF, - PORT_TP, - 0, - XCVR_INTERNAL, - AUTONEG_DISABLE, - 1, - 1 - }; - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } else { - return -EOPNOTSUPP; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = netif_carrier_ok(dev); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; + struct catc *catc = netdev_priv(dev); + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info); } -static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); - default: - return -EOPNOTSUPP; - } + struct catc *catc = netdev_priv(dev); + if (!catc->is_f5u011) + return -EOPNOTSUPP; + + cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; + cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; + cmd->speed = SPEED_10; + cmd->duplex = DUPLEX_HALF; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = catc_get_drvinfo, + .get_settings = catc_get_settings, + .get_link = ethtool_op_get_link +}; /* * Open, close. @@ -739,7 +703,7 @@ static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int catc_open(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); int status; catc->irq_urb->dev = catc->usbdev; @@ -758,17 +722,17 @@ static int catc_open(struct net_device *netdev) static int catc_stop(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); netif_stop_queue(netdev); if (!catc->is_f5u011) del_timer_sync(&catc->timer); - usb_unlink_urb(catc->rx_urb); - usb_unlink_urb(catc->tx_urb); - usb_unlink_urb(catc->irq_urb); - usb_unlink_urb(catc->ctrl_urb); + usb_kill_urb(catc->rx_urb); + usb_kill_urb(catc->tx_urb); + usb_kill_urb(catc->irq_urb); + usb_kill_urb(catc->ctrl_urb); return 0; } @@ -791,17 +755,11 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id return -EIO; } - catc = kmalloc(sizeof(struct catc), GFP_KERNEL); - if (!catc) + netdev = alloc_etherdev(sizeof(struct catc)); + if (!netdev) return -ENOMEM; - memset(catc, 0, sizeof(struct catc)); - - netdev = alloc_etherdev(0); - if (!netdev) { - kfree(catc); - return -EIO; - } + catc = netdev_priv(netdev); netdev->open = catc_open; netdev->hard_start_xmit = catc_hard_start_xmit; @@ -810,14 +768,13 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id netdev->tx_timeout = catc_tx_timeout; netdev->watchdog_timeo = TX_TIMEOUT; netdev->set_multicast_list = catc_set_multicast_list; - netdev->do_ioctl = catc_ioctl; - netdev->priv = catc; + SET_ETHTOOL_OPS(netdev, &ops); catc->usbdev = usbdev; catc->netdev = netdev; - catc->tx_lock = SPIN_LOCK_UNLOCKED; - catc->ctrl_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&catc->tx_lock); + spin_lock_init(&catc->ctrl_lock); init_timer(&catc->timer); catc->timer.data = (long) catc; @@ -839,7 +796,6 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id if (catc->irq_urb) usb_free_urb(catc->irq_urb); free_netdev(netdev); - kfree(catc); return -ENOMEM; } @@ -944,7 +900,6 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); free_netdev(netdev); - kfree(catc); return -EIO; } return 0; @@ -962,7 +917,6 @@ static void catc_disconnect(struct usb_interface *intf) usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); free_netdev(catc->netdev); - kfree(catc); } } diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 6eb637a80..1d16b0c57 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -203,7 +203,7 @@ struct kaweth_ethernet_configuration __u8 reserved2; eth_addr_t hw_addr; __u32 statistics_mask; - __u16 segment_size; + __le16 segment_size; __u16 max_multicast_filters; __u8 reserved3; } __attribute__ ((packed)); @@ -246,7 +246,7 @@ struct kaweth_device struct kaweth_ethernet_configuration configuration; struct net_device_stats stats; -} __attribute__ ((packed)); +}; /**************************************************************** @@ -588,7 +588,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) int count = urb->actual_length; int count2 = urb->transfer_buffer_length; - __u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf); + __u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf); struct sk_buff *skb; @@ -651,7 +651,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) ****************************************************************/ static int kaweth_open(struct net_device *net) { - struct kaweth_device *kaweth = (struct kaweth_device *)net->priv; + struct kaweth_device *kaweth = netdev_priv(net); int res; kaweth_dbg("Opening network device."); @@ -668,13 +668,13 @@ static int kaweth_open(struct net_device *net) INTBUFFERSIZE, int_callback, kaweth, - HZ/4); + 250); /* overriding the descriptor */ kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle; kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); if (res) { - usb_unlink_urb(kaweth->rx_urb); + usb_kill_urb(kaweth->rx_urb); return -EIO; } @@ -689,58 +689,36 @@ static int kaweth_open(struct net_device *net) ****************************************************************/ static int kaweth_close(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); netif_stop_queue(net); kaweth->status |= KAWETH_STATUS_CLOSING; - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); + usb_kill_urb(kaweth->irq_urb); + usb_kill_urb(kaweth->rx_urb); flush_scheduled_work(); /* a scheduled work may have resubmitted, we hit them again */ - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); + usb_kill_urb(kaweth->irq_urb); + usb_kill_urb(kaweth->rx_urb); kaweth->status &= ~KAWETH_STATUS_CLOSING; return 0; } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strlcpy(info.driver, driver_name, sizeof(info.driver)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - return -EOPNOTSUPP; + strlcpy(info->driver, driver_name, sizeof(info->driver)); } -/**************************************************************** - * kaweth_ioctl - ****************************************************************/ -static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(net, rq->ifr_data); - } - return -EOPNOTSUPP; -} +static struct ethtool_ops ops = { + .get_drvinfo = kaweth_get_drvinfo +}; /**************************************************************** * kaweth_usb_transmit_complete @@ -751,7 +729,8 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs) struct sk_buff *skb = kaweth->tx_skb; if (unlikely(urb->status != 0)) - kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status); + if (urb->status != -ENOENT) + kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status); netif_wake_queue(kaweth->net); dev_kfree_skb_irq(skb); @@ -762,8 +741,8 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs) ****************************************************************/ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) { - struct kaweth_device *kaweth = net->priv; - u16 *private_header; + struct kaweth_device *kaweth = netdev_priv(net); + __le16 *private_header; int res; @@ -794,7 +773,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) } } - private_header = (u16 *)__skb_push(skb, 2); + private_header = (__le16 *)__skb_push(skb, 2); *private_header = cpu_to_le16(skb->len-2); kaweth->tx_skb = skb; @@ -833,7 +812,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) ****************************************************************/ static void kaweth_set_rx_mode(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED | KAWETH_PACKET_FILTER_BROADCAST | @@ -890,7 +869,8 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) ****************************************************************/ static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) { - return &((struct kaweth_device *)dev->priv)->stats; + struct kaweth_device *kaweth = netdev_priv(dev); + return &kaweth->stats; } /**************************************************************** @@ -898,7 +878,7 @@ static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) ****************************************************************/ static void kaweth_tx_timeout(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); kaweth_warn("%s: Tx timed out. Resetting.", net->name); kaweth->stats.tx_errors++; @@ -933,12 +913,14 @@ static int kaweth_probe( (int)dev->descriptor.bLength, (int)dev->descriptor.bDescriptorType); - if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) + netdev = alloc_etherdev(sizeof(*kaweth)); + if (!netdev) return -ENOMEM; - memset(kaweth, 0, sizeof(struct kaweth_device)); - + kaweth = netdev_priv(netdev); kaweth->dev = dev; + kaweth->net = netdev; + spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); @@ -963,9 +945,7 @@ static int kaweth_probe( 100, 2)) < 0) { kaweth_err("Error downloading firmware (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + goto err_fw; } if ((result = kaweth_download_firmware(kaweth, @@ -974,9 +954,7 @@ static int kaweth_probe( 100, 3)) < 0) { kaweth_err("Error downloading firmware fix (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + goto err_fw; } if ((result = kaweth_download_firmware(kaweth, @@ -985,9 +963,8 @@ static int kaweth_probe( 126, 2)) < 0) { kaweth_err("Error downloading trigger code (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + goto err_fw; + } if ((result = kaweth_download_firmware(kaweth, @@ -996,23 +973,20 @@ static int kaweth_probe( 126, 3)) < 0) { kaweth_err("Error downloading trigger code fix (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + goto err_fw; } if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { kaweth_err("Error triggering firmware (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + goto err_fw; } /* Device will now disappear for a moment... */ kaweth_info("Firmware loaded. I'll be back..."); +err_fw: free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); + free_netdev(netdev); return -EIO; } @@ -1020,8 +994,7 @@ static int kaweth_probe( if(result < 0) { kaweth_err("Error reading configuration (%d), no net device created", result); - kfree(kaweth); - return -EIO; + goto err_free_netdev; } kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); @@ -1039,18 +1012,17 @@ static int kaweth_probe( &bcast_addr, sizeof(bcast_addr))) { kaweth_err("Firmware not functioning properly, no net device created"); - kfree(kaweth); - return -EIO; + goto err_free_netdev; } if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { kaweth_dbg("Error setting URB size"); - goto err_no_netdev; + goto err_free_netdev; } if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { kaweth_err("Error setting SOFS wait"); - goto err_no_netdev; + goto err_free_netdev; } result = kaweth_set_receive_filter(kaweth, @@ -1060,20 +1032,14 @@ static int kaweth_probe( if(result < 0) { kaweth_err("Error setting receive filter"); - kfree(kaweth); - return -EIO; + goto err_free_netdev; } kaweth_dbg("Initializing net device."); - if (!(netdev = alloc_etherdev(0))) { - kfree(kaweth); - return -ENOMEM; - } - kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) - goto err_no_urb; + goto err_free_netdev; kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->rx_urb) goto err_only_tx; @@ -1094,26 +1060,23 @@ static int kaweth_probe( if (!kaweth->rx_buf) goto err_all_but_rxbuf; - kaweth->net = netdev; - memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr)); - memcpy(kaweth->net->dev_addr, - &kaweth->configuration.hw_addr, + memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr)); + memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr, sizeof(kaweth->configuration.hw_addr)); - kaweth->net->priv = kaweth; - kaweth->net->open = kaweth_open; - kaweth->net->stop = kaweth_close; + netdev->open = kaweth_open; + netdev->stop = kaweth_close; - kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT; - kaweth->net->tx_timeout = kaweth_tx_timeout; + netdev->watchdog_timeo = KAWETH_TX_TIMEOUT; + netdev->tx_timeout = kaweth_tx_timeout; - kaweth->net->do_ioctl = kaweth_ioctl; - kaweth->net->hard_start_xmit = kaweth_start_xmit; - kaweth->net->set_multicast_list = kaweth_set_rx_mode; - kaweth->net->get_stats = kaweth_netdev_stats; - kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); + netdev->hard_start_xmit = kaweth_start_xmit; + netdev->set_multicast_list = kaweth_set_rx_mode; + netdev->get_stats = kaweth_netdev_stats; + netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size); + SET_ETHTOOL_OPS(netdev, &ops); - memset(&kaweth->stats, 0, sizeof(kaweth->stats)); + /* kaweth is zeroed as part of alloc_netdev */ INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); @@ -1150,10 +1113,9 @@ err_tx_and_rx: usb_free_urb(kaweth->rx_urb); err_only_tx: usb_free_urb(kaweth->tx_urb); -err_no_urb: +err_free_netdev: free_netdev(netdev); -err_no_netdev: - kfree(kaweth); + return -EIO; } @@ -1163,6 +1125,7 @@ err_no_netdev: static void kaweth_disconnect(struct usb_interface *intf) { struct kaweth_device *kaweth = usb_get_intfdata(intf); + struct net_device *netdev; kaweth_info("Unregistering"); @@ -1171,40 +1134,23 @@ static void kaweth_disconnect(struct usb_interface *intf) kaweth_warn("unregistering non-existant device"); return; } - + netdev = kaweth->net; kaweth->removed = 1; - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); - - /* we need to wait for the urb to be cancelled, if it is active */ - spin_lock(&kaweth->device_lock); - if (usb_unlink_urb(kaweth->tx_urb) == -EINPROGRESS) { - spin_unlock(&kaweth->device_lock); - wait_event(kaweth->term_wait, kaweth->end); - } else { - spin_unlock(&kaweth->device_lock); - } - - if(kaweth->net) { - if(kaweth->net->flags & IFF_UP) { - kaweth_dbg("Closing net device"); - dev_close(kaweth->net); - } + usb_kill_urb(kaweth->irq_urb); + usb_kill_urb(kaweth->rx_urb); + usb_kill_urb(kaweth->tx_urb); - kaweth_dbg("Unregistering net device"); - unregister_netdev(kaweth->net); - free_netdev(kaweth->net); - } + kaweth_dbg("Unregistering net device"); + unregister_netdev(netdev); usb_free_urb(kaweth->rx_urb); usb_free_urb(kaweth->tx_urb); usb_free_urb(kaweth->irq_urb); - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); - kfree(kaweth); + free_netdev(netdev); } @@ -1250,19 +1196,17 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) return status; } - set_current_state(TASK_UNINTERRUPTIBLE); while (timeout && !awd.done) { - timeout = schedule_timeout(timeout); set_current_state(TASK_UNINTERRUPTIBLE); + timeout = schedule_timeout(timeout); } - set_current_state(TASK_RUNNING); remove_wait_queue(&awd.wqh, &wait); if (!timeout) { // timeout kaweth_warn("usb_control/bulk_msg: timeout"); - usb_unlink_urb(urb); // remove urb safely + usb_kill_urb(urb); // remove urb safely status = -ETIMEDOUT; } else { diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index f4f1071a3..3f644d68d 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -78,8 +78,8 @@ static struct usb_device_id pegasus_ids[] = { MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_PARM(loopback, "i"); -MODULE_PARM(mii_mode, "i"); +module_param(loopback, bool, 0); +module_param(mii_mode, bool, 0); MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); @@ -286,7 +286,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) { int i; __u8 data[4] = { phy, 0, 0, indx }; - __u16 regdi; + __le16 regdi; set_register(pegasus, PhyCtrl, 0); set_registers(pegasus, PhyAddr, sizeof (data), data); @@ -308,7 +308,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) static int mdio_read(struct net_device *dev, int phy_id, int loc) { - pegasus_t *pegasus = (pegasus_t *) dev->priv; + pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); int res; read_mii_word(pegasus, phy_id, loc, (u16 *) & res); @@ -322,7 +322,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) *(data + 1) = cpu_to_le16p(®d); set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, 4, data); + set_registers(pegasus, PhyAddr, sizeof(data), data); set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); for (i = 0; i < REG_TIMEOUT; i++) { get_registers(pegasus, PhyCtrl, 1, data); @@ -338,7 +338,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) { - pegasus_t *pegasus = (pegasus_t *) dev->priv; + pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); write_mii_word(pegasus, phy_id, loc, val); } @@ -347,7 +347,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) { int i; __u8 tmp; - __u16 retdatai; + __le16 retdatai; set_register(pegasus, EpromCtrl, 0); set_register(pegasus, EpromOffset, index); @@ -388,8 +388,8 @@ static inline void disable_eprom_write(pegasus_t * pegasus) static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) { - int i, tmp; - __u8 d[4] = { 0x3f, 0, 0, EPROM_WRITE }; + int i; + __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; set_registers(pegasus, EpromOffset, 4, d); enable_eprom_write(pegasus); @@ -417,7 +417,7 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id) for (i = 0; i < 3; i++) { read_eprom_word(pegasus, i, &w16); - ((__u16 *) id)[i] = cpu_to_le16p(&w16); + ((__le16 *) id)[i] = cpu_to_le16p(&w16); } } @@ -471,7 +471,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) { __u16 linkpart; __u8 data[4]; - pegasus_t *pegasus = dev->priv; + pegasus_t *pegasus = netdev_priv(dev); read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); data[0] = 0xc9; @@ -581,7 +581,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) if (!count) goto goon; - rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4)); + rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4)); if (rx_status & 0x000e0000) { dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000); pegasus->stats.rx_errors++; @@ -594,7 +594,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goto goon; } if (pegasus->chip == 0x8513) { - pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer); + pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer); pkt_len &= 0x0fff; pegasus->rx_skb->data += 2; } else { @@ -754,11 +754,7 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) static void pegasus_tx_timeout(struct net_device *net) { - pegasus_t *pegasus = net->priv; - - if (!pegasus) - return; - + pegasus_t *pegasus = netdev_priv(net); warn("%s: Tx timed out.", net->name); pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(pegasus->tx_urb); @@ -767,14 +763,14 @@ static void pegasus_tx_timeout(struct net_device *net) static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3; int res; __u16 l16 = skb->len; netif_stop_queue(net); - ((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); + ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); memcpy(pegasus->tx_buff + 2, skb->data, skb->len); usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, usb_sndbulkpipe(pegasus->usb, 2), @@ -804,7 +800,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) { - return &((pegasus_t *) dev->priv)->stats; + return &((pegasus_t *) netdev_priv(dev))->stats; } static inline void disable_net_traffic(pegasus_t * pegasus) @@ -832,10 +828,9 @@ static inline void get_interrupt_interval(pegasus_t * pegasus) static void set_carrier(struct net_device *net) { - pegasus_t *pegasus; + pegasus_t *pegasus = netdev_priv(net); short tmp; - pegasus = net->priv; read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp); if (tmp & BMSR_LSTATUS) netif_carrier_on(net); @@ -854,10 +849,10 @@ static void free_all_urbs(pegasus_t * pegasus) static void unlink_all_urbs(pegasus_t * pegasus) { - usb_unlink_urb(pegasus->intr_urb); - usb_unlink_urb(pegasus->tx_urb); - usb_unlink_urb(pegasus->rx_urb); - usb_unlink_urb(pegasus->ctrl_urb); + usb_kill_urb(pegasus->intr_urb); + usb_kill_urb(pegasus->tx_urb); + usb_kill_urb(pegasus->rx_urb); + usb_kill_urb(pegasus->ctrl_urb); } static int alloc_urbs(pegasus_t * pegasus) @@ -890,7 +885,7 @@ static int alloc_urbs(pegasus_t * pegasus) static int pegasus_open(struct net_device *net) { - pegasus_t *pegasus = (pegasus_t *) net->priv; + pegasus_t *pegasus = netdev_priv(net); int res; if (pegasus->rx_skb == NULL) @@ -920,8 +915,8 @@ static int pegasus_open(struct net_device *net) if ((res = enable_net_traffic(net, pegasus->usb))) { err("can't enable_net_traffic() - %d", res); res = -EIO; - usb_unlink_urb(pegasus->rx_urb); - usb_unlink_urb(pegasus->intr_urb); + usb_kill_urb(pegasus->rx_urb); + usb_kill_urb(pegasus->intr_urb); free_skb_pool(pegasus); goto exit; } @@ -933,7 +928,7 @@ exit: static int pegasus_close(struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); pegasus->flags &= ~PEGASUS_RUNNING; netif_stop_queue(net); @@ -944,177 +939,124 @@ static int pegasus_close(struct net_device *net) return 0; } + +void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + pegasus_t *pegasus = netdev_priv(dev); + strncpy(info->driver, driver_name, sizeof (info->driver) - 1); + strncpy(info->version, DRIVER_VERSION, sizeof (info->version) - 1); + usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info)); +} + #ifdef CONFIG_MII -static int pegasus_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + pegasus_t *pegasus = netdev_priv(dev); + mii_ethtool_gset(&pegasus->mii, ecmd); + return 0; +} +static int pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + pegasus_t *pegasus = netdev_priv(dev); + return mii_ethtool_sset(&pegasus->mii, ecmd); +} - u32 ethcmd; - pegasus_t *pegasus = dev->priv; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - /* get driver-specific version/etc. info */ - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info; - memset (&info, 0, sizeof (info)); - info.cmd = ETHTOOL_GDRVINFO; - strncpy(info.driver, driver_name, - sizeof (info.driver) - 1); - strncpy(info.version, DRIVER_VERSION, - sizeof (info.version) - 1); - usb_make_path(pegasus->usb, info.bus_info, - sizeof (info.bus_info)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } +static int pegasus_nway_reset(struct net_device *dev) +{ + pegasus_t *pegasus = netdev_priv(dev); + return mii_nway_restart(&pegasus->mii); +} - /* get settings */ - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - mii_ethtool_gset(&pegasus->mii, &ecmd); - if (copy_to_user(useraddr, &ecmd, sizeof (ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET:{ - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof (ecmd))) - return -EFAULT; - r = mii_ethtool_sset(&pegasus->mii, &ecmd); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST:{ - return mii_nway_restart(&pegasus->mii); - } +static u32 pegasus_get_link(struct net_device *dev) +{ + pegasus_t *pegasus = netdev_priv(dev); + return mii_link_ok(&pegasus->mii); +} - /* get link status */ - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = mii_link_ok(&pegasus->mii); - if (copy_to_user(useraddr, &edata, sizeof (edata))) - return -EFAULT; - return 0; - } - /* get message-level */ - case ETHTOOL_GMSGLVL:{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - /* edata.data = pegasus->msg_enable; FIXME */ - 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; - /* sp->msg_enable = edata.data; FIXME */ - return 0; - } +static u32 pegasus_get_msglevel(struct net_device *dev) +{ + /* + * pegasus_t *pegasus = netdev_priv(dev); + * return pegasus->msg_enable; FIXME + */ + return 0; +} - } +static void pegasus_set_msglevel(struct net_device *dev, u32 v) +{ + /* + * pegasus_t *pegasus = netdev_priv(dev); + * pegasus->msg_enable = edata.data; FIXME + */ +} - return -EOPNOTSUPP; +static struct ethtool_ops ops = { + .get_drvinfo = pegasus_get_drvinfo, + .get_settings = pegasus_get_settings, + .set_settings = pegasus_set_settings, + .nway_reset = pegasus_nway_reset, + .get_link = pegasus_get_link, + .get_msglevel = pegasus_get_msglevel, + .set_msglevel = pegasus_set_msglevel, +}; -} #else -static int pegasus_ethtool_ioctl(struct net_device *net, void __user *uaddr) -{ - pegasus_t *pegasus; - int cmd; - pegasus = net->priv; - if (get_user(cmd, (int __user *) uaddr)) - return -EFAULT; - switch (cmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info; - memset (&info, 0, sizeof (info)); - info.cmd = ETHTOOL_GDRVINFO; - strncpy(info.driver, driver_name, - sizeof (info.driver) - 1); - strncpy(info.version, DRIVER_VERSION, - sizeof (info.version) - 1); - usb_make_path(pegasus->usb, info.bus_info, - sizeof (info.bus_info)); - if (copy_to_user(uaddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd; - short lpa, bmcr; - u8 port; - - memset(&ecmd, 0, sizeof (ecmd)); - ecmd.supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | SUPPORTED_MII); - get_registers(pegasus, Reg7b, 1, &port); - if (port == 0) - ecmd.port = PORT_MII; - else - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = pegasus->phy; - read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr); - read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = lpa & (LPA_100HALF | LPA_100FULL) ? - SPEED_100 : SPEED_10; - if (ecmd.speed == SPEED_100) - ecmd.duplex = lpa & LPA_100FULL ? - DUPLEX_FULL : DUPLEX_HALF; - else - ecmd.duplex = lpa & LPA_10FULL ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = bmcr & BMCR_SPEED100 ? - SPEED_100 : SPEED_10; - ecmd.duplex = bmcr & BMCR_FULLDPLX ? - DUPLEX_FULL : DUPLEX_HALF; - } - if (copy_to_user(uaddr, &ecmd, sizeof (ecmd))) - return -EFAULT; - - return 0; - } - case ETHTOOL_SSET:{ - return -EOPNOTSUPP; - } - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = netif_carrier_ok(net); - if (copy_to_user(uaddr, &edata, sizeof (edata))) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; +static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + pegasus_t *pegasus = netdev_priv(dev); + short lpa, bmcr; + u8 port; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + get_registers(pegasus, Reg7b, 1, &port); + if (port == 0) + ecmd->port = PORT_MII; + else + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = pegasus->phy; + read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr); + read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->speed = lpa & (LPA_100HALF | LPA_100FULL) ? + SPEED_100 : SPEED_10; + if (ecmd->speed == SPEED_100) + ecmd->duplex = lpa & LPA_100FULL ? + DUPLEX_FULL : DUPLEX_HALF; + else + ecmd->duplex = lpa & LPA_10FULL ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->speed = bmcr & BMCR_SPEED100 ? + SPEED_100 : SPEED_10; + ecmd->duplex = bmcr & BMCR_FULLDPLX ? + DUPLEX_FULL : DUPLEX_HALF; } + return 0; } + +static struct ethtool_ops ops = { + .get_drvinfo = pegasus_get_drvinfo, + .get_settings = pegasus_get_settings, + .get_link = ethtool_op_get_link, +}; #endif + static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { __u16 *data = (__u16 *) & rq->ifr_ifru; - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); int res; switch (cmd) { - case SIOCETHTOOL: - res = pegasus_ethtool_ioctl(net, rq->ifr_data); - break; case SIOCDEVPRIVATE: data[0] = pegasus->phy; case SIOCDEVPRIVATE + 1: @@ -1135,7 +1077,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) static void pegasus_set_multicast(struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); if (net->flags & IFF_PROMISC) { pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; @@ -1172,7 +1114,7 @@ static __u8 mii_phy_probe(pegasus_t * pegasus) static inline void setup_pegasus_II(pegasus_t * pegasus) { - u16 data = 0xa5; + __u8 data = 0xa5; set_register(pegasus, Reg1d, 0); set_register(pegasus, Reg7b, 1); @@ -1211,11 +1153,13 @@ static int pegasus_probe(struct usb_interface *intf, int res = -ENOMEM; usb_get_dev(dev); - if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) { + net = alloc_etherdev(sizeof(struct pegasus)); + if (!net) { err("out of memory allocating device structure"); goto out; } + pegasus = netdev_priv(net); memset(pegasus, 0, sizeof (struct pegasus)); pegasus->dev_index = dev_index; init_waitqueue_head(&pegasus->ctrl_wait); @@ -1223,16 +1167,11 @@ static int pegasus_probe(struct usb_interface *intf, if (!alloc_urbs(pegasus)) goto out1; - net = alloc_etherdev(0); - if (!net) - goto out2; - tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); pegasus->usb = dev; pegasus->net = net; SET_MODULE_OWNER(net); - net->priv = pegasus; net->open = pegasus_open; net->stop = pegasus_close; net->watchdog_timeo = PEGASUS_TX_TIMEOUT; @@ -1242,6 +1181,7 @@ static int pegasus_probe(struct usb_interface *intf, net->set_multicast_list = pegasus_set_multicast; net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; + SET_ETHTOOL_OPS(net, &ops); pegasus->mii.dev = net; pegasus->mii.mdio_read = mdio_read; pegasus->mii.mdio_write = mdio_write; @@ -1254,7 +1194,7 @@ static int pegasus_probe(struct usb_interface *intf, if (reset_mac(pegasus)) { err("can't reset MAC"); res = -EIO; - goto out3; + goto out2; } set_ethernet_addr(pegasus); fill_skb_pool(pegasus); @@ -1271,19 +1211,17 @@ static int pegasus_probe(struct usb_interface *intf, SET_NETDEV_DEV(net, &intf->dev); res = register_netdev(net); if (res) - goto out4; + goto out3; printk("%s: %s\n", net->name, usb_dev_id[dev_index].name); return 0; -out4: +out3: usb_set_intfdata(intf, NULL); free_skb_pool(pegasus); -out3: - free_netdev(net); out2: free_all_urbs(pegasus); out1: - kfree(pegasus); + free_netdev(net); out: usb_put_dev(dev); return res; @@ -1307,7 +1245,6 @@ static void pegasus_disconnect(struct usb_interface *intf) if (pegasus->rx_skb) dev_kfree_skb(pegasus->rx_skb); free_netdev(pegasus->net); - kfree(pegasus); } static struct usb_driver pegasus_driver = { diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index d9d09e984..2ecba5158 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -20,7 +20,7 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.6.1 (2004/03/13)" +#define DRIVER_VERSION "v0.6.2 (2004/08/27)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" @@ -160,7 +160,7 @@ struct rtl8150 { spinlock_t rx_pool_lock; struct usb_ctrlrequest dr; int intr_interval; - u16 rx_creg; + __le16 rx_creg; u8 *intr_buff; u8 phy; }; @@ -265,7 +265,7 @@ static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) if (i < MII_TIMEOUT) { get_registers(dev, PHYDAT, 2, data); - *reg = le16_to_cpup(data); + *reg = data[0] | (data[1] << 8); return 0; } else return 1; @@ -304,15 +304,12 @@ static inline void set_ethernet_addr(rtl8150_t * dev) static int rtl8150_set_mac_address(struct net_device *netdev, void *p) { struct sockaddr *addr = p; - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int i; if (netif_running(netdev)) return -EBUSY; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); dbg("%s: Setting MAC address to ", netdev->name); for (i = 0; i < 5; i++) @@ -392,10 +389,10 @@ static void free_all_urbs(rtl8150_t * dev) static void unlink_all_urbs(rtl8150_t * dev) { - usb_unlink_urb(dev->rx_urb); - usb_unlink_urb(dev->tx_urb); - usb_unlink_urb(dev->intr_urb); - usb_unlink_urb(dev->ctrl_urb); + usb_kill_urb(dev->rx_urb); + usb_kill_urb(dev->tx_urb); + usb_kill_urb(dev->intr_urb); + usb_kill_urb(dev->ctrl_urb); } static inline struct sk_buff *pull_skb(rtl8150_t *dev) @@ -450,7 +447,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goto goon; res = urb->actual_length; - rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4)); + rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4)); pkt_len = res - 4; skb_put(dev->rx_skb, pkt_len); @@ -651,16 +648,12 @@ static void disable_net_traffic(rtl8150_t * dev) static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) { - return &((rtl8150_t *) dev->priv)->stats; + return &((rtl8150_t *)netdev_priv(dev))->stats; } static void rtl8150_tx_timeout(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; - if (!dev) - return; + rtl8150_t *dev = netdev_priv(netdev); warn("%s: Tx timeout.", netdev->name); dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(dev->tx_urb); @@ -669,9 +662,7 @@ static void rtl8150_tx_timeout(struct net_device *netdev) static void rtl8150_set_multicast(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { dev->rx_creg |= cpu_to_le16(0x0001); @@ -691,11 +682,10 @@ static void rtl8150_set_multicast(struct net_device *netdev) static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int count, res; netif_stop_queue(netdev); - dev = netdev->priv; count = (skb->len < 60) ? 60 : skb->len; count = (count & 0x3f) ? count : count + 1; dev->tx_skb = skb; @@ -717,7 +707,7 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) static void set_carrier(struct net_device *netdev) { - rtl8150_t *dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); short tmp; get_registers(dev, CSCR, 2, &tmp); @@ -729,13 +719,9 @@ static void set_carrier(struct net_device *netdev) static int rtl8150_open(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } if (dev->rx_skb == NULL) dev->rx_skb = pull_skb(dev); if (!dev->rx_skb) @@ -761,13 +747,9 @@ static int rtl8150_open(struct net_device *netdev) static int rtl8150_close(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res = 0; - dev = netdev->priv; - if (!dev) - return -ENODEV; - netif_stop_queue(netdev); if (!test_bit(RTL8150_UNPLUG, &dev->flags)) disable_net_traffic(dev); @@ -776,93 +758,64 @@ static int rtl8150_close(struct net_device *netdev) return res; } -static int rtl8150_ethtool_ioctl(struct net_device *netdev, void __user *uaddr) +static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { - rtl8150_t *dev; - int cmd; + rtl8150_t *dev = netdev_priv(netdev); - dev = netdev->priv; - if (get_user(cmd, (int __user *) uaddr)) - return -EFAULT; + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info); +} - switch (cmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - - strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path(dev->udev, info.bus_info, sizeof info.bus_info); - if (copy_to_user(uaddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd; - short lpa, bmcr; - - if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) - return -EFAULT; - ecmd.supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | SUPPORTED_MII); - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = dev->phy; - get_registers(dev, BMCR, 2, &bmcr); - get_registers(dev, ANLP, 2, &lpa); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (ecmd.speed == SPEED_100) - ecmd.duplex = (lpa & LPA_100FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - else - ecmd.duplex = (lpa & LPA_10FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; - ecmd.duplex = (bmcr & BMCR_FULLDPLX) ? +static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + rtl8150_t *dev = netdev_priv(netdev); + short lpa, bmcr; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = dev->phy; + get_registers(dev, BMCR, 2, &bmcr); + get_registers(dev, ANLP, 2, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10; + if (ecmd->speed == SPEED_100) + ecmd->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : DUPLEX_HALF; - } - if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: - return -ENOTSUPP; - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = netif_carrier_ok(netdev); - if (copy_to_user(uaddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; + else + ecmd->duplex = (lpa & LPA_10FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->speed = (bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10; + ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; } + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = rtl8150_get_drvinfo, + .get_settings = rtl8150_get_settings, + .get_link = ethtool_op_get_link +}; + static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) { - rtl8150_t *dev; - u16 *data; - int res; - - dev = netdev->priv; - data = (u16 *) & rq->ifr_ifru; - res = 0; + rtl8150_t *dev = netdev_priv(netdev); + u16 *data = (u16 *) & rq->ifr_ifru; + int res = 0; switch (cmd) { - case SIOCETHTOOL: - res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data); - break; case SIOCDEVPRIVATE: data[0] = dev->phy; case SIOCDEVPRIVATE + 1: @@ -887,23 +840,18 @@ static int rtl8150_probe(struct usb_interface *intf, rtl8150_t *dev; struct net_device *netdev; - dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL); - if (!dev) { + netdev = alloc_etherdev(sizeof(rtl8150_t)); + if (!netdev) { err("Out of memory"); return -ENOMEM; - } else - memset(dev, 0, sizeof(rtl8150_t)); + } + + dev = netdev_priv(netdev); + memset(dev, 0, sizeof(rtl8150_t)); dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL); if (!dev->intr_buff) { - kfree(dev); - return -ENOMEM; - } - netdev = alloc_etherdev(0); - if (!netdev) { - kfree(dev->intr_buff); - kfree(dev); - err("Oh boy, out of memory again?!?"); + free_netdev(netdev); return -ENOMEM; } @@ -913,7 +861,6 @@ static int rtl8150_probe(struct usb_interface *intf, dev->udev = udev; dev->netdev = netdev; SET_MODULE_OWNER(netdev); - netdev->priv = dev; netdev->open = rtl8150_open; netdev->stop = rtl8150_close; netdev->do_ioctl = rtl8150_ioctl; @@ -924,6 +871,7 @@ static int rtl8150_probe(struct usb_interface *intf, netdev->set_mac_address = rtl8150_set_mac_address; netdev->get_stats = rtl8150_netdev_stats; netdev->mtu = RTL8150_MTU; + SET_ETHTOOL_OPS(netdev, &ops); dev->intr_interval = 100; /* 100ms */ if (!alloc_all_urbs(dev)) { @@ -954,7 +902,6 @@ out1: out: kfree(dev->intr_buff); free_netdev(netdev); - kfree(dev); return -EIO; } @@ -971,9 +918,8 @@ static void rtl8150_disconnect(struct usb_interface *intf) free_skb_pool(dev); if (dev->rx_skb) dev_kfree_skb(dev->rx_skb); - free_netdev(dev->netdev); kfree(dev->intr_buff); - kfree(dev); + free_netdev(dev->netdev); } } diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 2d68cb01e..2ef83c117 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -31,6 +31,7 @@ * - GeneSys GL620USB-A * - NetChip 1080 (interoperates with NetChip Win32 drivers) * - Prolific PL-2301/2302 (replaces "plusb" driver) + * - KC Technology KC2190 * * + Smart USB devices can support such links directly, using Internet * standard protocols instead of proprietary host-to-device links. @@ -106,6 +107,7 @@ * 22-aug-2003 AX8817X support (Dave Hollis). * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan * (Neil Bortnak) + * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell) * *-------------------------------------------------------------------------*/ @@ -134,7 +136,7 @@ #include #include -#define DRIVER_VERSION "25-Aug-2003" +#define DRIVER_VERSION "03-Nov-2004" /*-------------------------------------------------------------------------*/ @@ -166,7 +168,7 @@ #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000) // between wakeups -#define UNLINK_TIMEOUT_JIFFIES ((3 /*ms*/ * HZ)/1000) +#define UNLINK_TIMEOUT_MS 3 /*-------------------------------------------------------------------------*/ @@ -268,7 +270,7 @@ static const char driver_name [] = "usbnet"; /* use ethtool to change the level for any given device */ static int msg_level = 1; -MODULE_PARM (msg_level, "i"); +module_param (msg_level, int, 0); MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)"); @@ -525,7 +527,7 @@ static void ax8817x_interrupt_complete(struct urb *urb, struct pt_regs *regs) devdbg(dev, "ax8817x - Link Status is: %d", link); } } - usb_submit_urb(data->int_urb, GFP_KERNEL); + usb_submit_urb(data->int_urb, GFP_ATOMIC); } } @@ -567,7 +569,7 @@ static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 i static void ax8817x_set_multicast(struct net_device *net) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); struct ax8817x_data *data = (struct ax8817x_data *)&dev->data; u8 rx_ctl = 0x8c; @@ -610,7 +612,7 @@ static void ax8817x_set_multicast(struct net_device *net) static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc) { - struct usbnet *dev = netdev->priv; + struct usbnet *dev = netdev_priv(netdev); u16 res; u8 buf[1]; @@ -623,7 +625,7 @@ static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc) static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) { - struct usbnet *dev = netdev->priv; + struct usbnet *dev = netdev_priv(netdev); u16 res = val; u8 buf[1]; @@ -634,7 +636,7 @@ static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); u8 opt; if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { @@ -654,7 +656,7 @@ static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *woli static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); u8 opt = 0; u8 buf[1]; @@ -675,7 +677,7 @@ static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolin static int ax8817x_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, u8 *data) { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); u16 *ebuf = (u16 *)data; int i; @@ -704,14 +706,14 @@ static void ax8817x_get_drvinfo (struct net_device *net, static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd) { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); return mii_ethtool_gset(&dev->mii,cmd); } static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd) { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); return mii_ethtool_sset(&dev->mii,cmd); } @@ -825,7 +827,7 @@ static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf) { struct ax8817x_data *data = (struct ax8817x_data *)dev->data; - usb_unlink_urb(data->int_urb); + usb_kill_urb(data->int_urb); usb_free_urb(data->int_urb); kfree(data->int_buf); } @@ -937,8 +939,8 @@ struct ether_desc { u8 iMACAddress; u32 bmEthernetStatistics; - u16 wMaxSegmentSize; - u16 wNumberMCFilters; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; u8 bNumberPowerFilters; } __attribute__ ((packed)); @@ -1074,7 +1076,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf) info->u->bLength); goto bad_desc; } - dev->net->mtu = cpu_to_le16p ( + dev->net->mtu = le16_to_cpup ( &info->ether->wMaxSegmentSize) - ETH_HLEN; /* because of Zaurus, we may be ignoring the host @@ -1437,7 +1439,7 @@ static int genelink_free (struct usbnet *dev) // handling needs to be generic) // cancel irq urb first - usb_unlink_urb (priv->irq_urb); + usb_kill_urb (priv->irq_urb); // free irq urb usb_free_urb (priv->irq_urb); @@ -2159,6 +2161,13 @@ static const struct driver_info prolific_info = { #endif /* CONFIG_USB_PL2301 */ + +#ifdef CONFIG_USB_KC2190 +#define HAVE_HARDWARE +static const struct driver_info kc2190_info = { + .description = "KC Technology KC-190", +}; +#endif /* CONFIG_USB_KC2190 */ #ifdef CONFIG_USB_ARMLINUX @@ -2276,7 +2285,7 @@ static const struct driver_info zaurus_pxa_info = { static int usbnet_change_mtu (struct net_device *net, int new_mtu) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET) return -EINVAL; @@ -2302,7 +2311,8 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu) static struct net_device_stats *usbnet_get_stats (struct net_device *net) { - return &((struct usbnet *) net->priv)->stats; + struct usbnet *dev = netdev_priv(net); + return &dev->stats; } /*-------------------------------------------------------------------------*/ @@ -2569,7 +2579,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) static int usbnet_stop (struct net_device *net) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); int temp; DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); @@ -2591,8 +2601,7 @@ static int usbnet_stop (struct net_device *net) while (skb_queue_len (&dev->rxq) && skb_queue_len (&dev->txq) && skb_queue_len (&dev->done)) { - set_current_state (TASK_UNINTERRUPTIBLE); - schedule_timeout (UNLINK_TIMEOUT_JIFFIES); + msleep(UNLINK_TIMEOUT_MS); devdbg (dev, "waited for %d urb completions", temp); } dev->wait = NULL; @@ -2617,7 +2626,7 @@ static int usbnet_stop (struct net_device *net) static int usbnet_open (struct net_device *net) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); int retval = 0; struct driver_info *info = dev->driver_info; @@ -2667,7 +2676,7 @@ done: static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { - struct usbnet *dev = net->priv; + struct usbnet *dev = netdev_priv(net); strncpy (info->driver, driver_name, sizeof info->driver); strncpy (info->version, DRIVER_VERSION, sizeof info->version); @@ -2678,7 +2687,7 @@ static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo * static u32 usbnet_get_link (struct net_device *net) { - struct usbnet *dev = net->priv; + struct usbnet *dev = netdev_priv(net); /* If a check_connect is defined, return it's results */ if (dev->driver_info->check_connect) @@ -2690,14 +2699,14 @@ static u32 usbnet_get_link (struct net_device *net) static u32 usbnet_get_msglevel (struct net_device *net) { - struct usbnet *dev = net->priv; + struct usbnet *dev = netdev_priv(net); return dev->msg_level; } static void usbnet_set_msglevel (struct net_device *net, u32 level) { - struct usbnet *dev = net->priv; + struct usbnet *dev = netdev_priv(net); dev->msg_level = level; } @@ -2706,7 +2715,7 @@ static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd) { #ifdef NEED_MII { - struct usbnet *dev = (struct usbnet *)net->priv; + struct usbnet *dev = netdev_priv(net); if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); @@ -2818,7 +2827,7 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs) static void usbnet_tx_timeout (struct net_device *net) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); unlink_urbs (dev, &dev->txq); tasklet_schedule (&dev->bh); @@ -2830,7 +2839,7 @@ static void usbnet_tx_timeout (struct net_device *net) static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { - struct usbnet *dev = (struct usbnet *) net->priv; + struct usbnet *dev = netdev_priv(net); int length; int retval = NET_XMIT_SUCCESS; struct urb *urb = NULL; @@ -3015,6 +3024,7 @@ static void usbnet_disconnect (struct usb_interface *intf) { struct usbnet *dev; struct usb_device *xdev; + struct net_device *net; dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); @@ -3027,7 +3037,8 @@ static void usbnet_disconnect (struct usb_interface *intf) xdev->bus->bus_name, xdev->devpath, dev->driver_info->description); - unregister_netdev (dev->net); + net = dev->net; + unregister_netdev (net); /* we don't hold rtnl here ... */ flush_scheduled_work (); @@ -3035,8 +3046,7 @@ static void usbnet_disconnect (struct usb_interface *intf) if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); - free_netdev(dev->net); - kfree (dev); + free_netdev(net); usb_put_dev (xdev); } @@ -3070,12 +3080,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) status = -ENOMEM; // set up our own records - if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) { + net = alloc_etherdev(sizeof(*dev)); + if (!net) { dbg ("can't kmalloc dev"); goto out; } - memset (dev, 0, sizeof *dev); + dev = netdev_priv(net); dev->udev = xdev; dev->driver_info = info; dev->msg_level = msg_level; @@ -3089,14 +3100,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) dev->delay.data = (unsigned long) dev; init_timer (&dev->delay); - // set up network interface records - net = alloc_etherdev(0); - if (!net) - goto out1; - SET_MODULE_OWNER (net); dev->net = net; - net->priv = dev; strcpy (net->name, "usb%d"); memcpy (net->dev_addr, node_id, sizeof node_id); @@ -3145,8 +3150,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); - SET_NETDEV_DEV(dev->net, &udev->dev); - status = register_netdev (dev->net); + SET_NETDEV_DEV(net, &udev->dev); + status = register_netdev (net); if (status) goto out3; devinfo (dev, "register usbnet at usb-%s-%s, %s", @@ -3157,16 +3162,15 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) usb_set_intfdata (udev, dev); // start as if the link is up - netif_device_attach (dev->net); + netif_device_attach (net); return 0; out3: if (info->unbind) info->unbind (dev, udev); - free_netdev(net); out1: - kfree(dev); + free_netdev(net); out: usb_put_dev(xdev); return status; @@ -3253,6 +3257,14 @@ static const struct usb_device_id products [] = { // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" USB_DEVICE (0x6189, 0x182d), .driver_info = (unsigned long) &ax8817x_info, +}, { + // corega FEther USB2-TX + USB_DEVICE (0x07aa, 0x0017), + .driver_info = (unsigned long) &ax8817x_info, +}, { + // Surecom EP-1427X-2 + USB_DEVICE (0x1189, 0x0893), + .driver_info = (unsigned long) &ax8817x_info, }, #endif @@ -3293,6 +3305,13 @@ static const struct usb_device_id products [] = { }, #endif +#ifdef CONFIG_USB_KC2190 +{ + USB_DEVICE (0x050f, 0x0190), // KC-190 + .driver_info = (unsigned long) &kc2190_info, +}, +#endif + #ifdef CONFIG_USB_RNDIS { /* RNDIS is MSFT's un-official variant of CDC ACM */ @@ -3309,11 +3328,18 @@ static const struct usb_device_id products [] = { * * PXA25x or PXA210 ... these use a "usb-eth" driver much like * the sa1100 one, but hardware uses different endpoint numbers. + * + * Or the Linux "Ethernet" gadget on hardware that can't talk + * CDC Ethernet (e.g., no altsettings), in either of two modes: + * - acting just like the old "usb-eth" firmware, though + * the implementation is different + * - supporting RNDIS as the first/default configuration for + * MS-Windows interop; Linux needs to use the other config */ { // 1183 = 0x049F, both used as hex values? // Compaq "Itsy" vendor/product id - USB_DEVICE (0x049F, 0x505A), + USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible .driver_info = (unsigned long) &linuxdev_info, }, { USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" @@ -3321,6 +3347,10 @@ static const struct usb_device_id products [] = { }, { USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader .driver_info = (unsigned long) &blob_info, +}, { + // Linux Ethernet/RNDIS gadget on pxa210/25x/26x + USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203), + .driver_info = (unsigned long) &linuxdev_info, }, #endif diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 88fede7b4..3fe730f76 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -89,6 +89,21 @@ config USB_SERIAL_DIGI_ACCELEPORT To compile this driver as a module, choose M here: the module will be called digi_acceleport. +config USB_SERIAL_CYPRESS_M8 + tristate "USB Cypress M8 USB Serial Driver" + depends on USB_SERIAL && EXPERIMENTAL + help + Say Y here if you want to use a device that contains the Cypress + USB to Serial microcontroller, such as the DeLorme Earthmate GPS. + + Attempted SMP support... send bug reports! + + Supported microcontrollers in the CY4601 family are: + CY7C63741 CY7C63742 CY7C63743 CY7C64013 + + To compile this driver as a module, choose M here: the + module will be called cypress_m8. + config USB_SERIAL_EMPEG tristate "USB Empeg empeg-car Mark I/II Driver" depends on USB_SERIAL @@ -187,6 +202,16 @@ config USB_SERIAL_EDGEPORT_TI To compile this driver as a module, choose M here: the module will be called io_ti. +config USB_SERIAL_IPW + tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)" + depends on USB_SERIAL && EXPERIMENTAL + help + Say Y here if you want to use a IPWireless USB modem such as + the ones supplied by Axity3G/Sentech South Africa. + + To compile this driver as a module, choose M here: the + module will be called ipw. + config USB_SERIAL_KEYSPAN_PDA tristate "USB Keyspan PDA Single Port Serial Driver" depends on USB_SERIAL diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 6cfbe3108..682ac09b8 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -13,12 +13,14 @@ usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o +obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o +obj-$(CONFIG_USB_SERIAL_IPW) += ipw.o obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index bcf56011e..75dd41d98 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -228,7 +228,7 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp) port->interrupt_in_urb->dev = port->serial->dev; retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (retval) { - usb_unlink_urb(port->read_urb); + usb_kill_urb(port->read_urb); err(" usb_submit_urb(read int) failed"); } @@ -242,9 +242,9 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp) dbg("%s port %d", __FUNCTION__, port->number); /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - usb_unlink_urb (port->interrupt_in_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); } /* belkin_sa_close */ @@ -607,6 +607,7 @@ module_exit (belkin_sa_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_VERSION( DRIVER_VERSION ); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 3cabbbb10..2f612c2d8 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -120,6 +120,7 @@ int usb_serial_bus_register(struct usb_serial_device_type *device) device->driver.bus = &usb_serial_bus_type; device->driver.probe = usb_serial_device_probe; device->driver.remove = usb_serial_device_remove; + device->driver.owner = device->owner; retval = driver_register(&device->driver); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 237d9d30d..167f8ec56 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -218,9 +218,9 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun /* pass on to the driver specific version of this function if it is available */ if (serial->type->write) - retval = serial->type->write(port, 0, buf, count); + retval = serial->type->write(port, buf, count); else - retval = usb_serial_generic_write(port, 0, buf, count); + retval = usb_serial_generic_write(port, buf, count); exit: dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 3ee5f493a..3a367f547 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -44,7 +44,7 @@ static int debug; /* * Version Information */ -#define DRIVER_VERSION "v1.0" +#define DRIVER_VERSION "v1.01" #define DRIVER_AUTHOR "Matthias Bruestle" #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" @@ -57,8 +57,7 @@ static int cyberjack_startup (struct usb_serial *serial); static void cyberjack_shutdown (struct usb_serial *serial); static int cyberjack_open (struct usb_serial_port *port, struct file *filp); static void cyberjack_close (struct usb_serial_port *port, struct file *filp); -static int cyberjack_write (struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count); +static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int cyberjack_write_room( struct usb_serial_port *port ); static void cyberjack_read_int_callback (struct urb *urb, struct pt_regs *regs); static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -111,6 +110,7 @@ struct cyberjack_private { static int cyberjack_startup (struct usb_serial *serial) { struct cyberjack_private *priv; + int i; dbg("%s", __FUNCTION__); @@ -128,6 +128,16 @@ static int cyberjack_startup (struct usb_serial *serial) init_waitqueue_head(&serial->port[0]->write_wait); + for (i = 0; i < serial->num_ports; ++i) { + int result; + serial->port[i]->interrupt_in_urb->dev = serial->dev; + result = usb_submit_urb(serial->port[i]->interrupt_in_urb, + GFP_KERNEL); + if (result) + err(" usb_submit_urb(read int) failed"); + dbg("%s - usb_submit_urb(int urb)", __FUNCTION__); + } + return( 0 ); } @@ -138,6 +148,7 @@ static void cyberjack_shutdown (struct usb_serial *serial) dbg("%s", __FUNCTION__); for (i=0; i < serial->num_ports; ++i) { + usb_kill_urb(serial->port[i]->interrupt_in_urb); /* My special items, the standard routines free my urbs */ kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); @@ -168,17 +179,6 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp) priv->wrsent = 0; spin_unlock_irqrestore(&priv->lock, flags); - /* shutdown any bulk reads that might be going on */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - usb_unlink_urb (port->interrupt_in_urb); - - port->interrupt_in_urb->dev = port->serial->dev; - result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (result) - err(" usb_submit_urb(read int) failed"); - dbg("%s - usb_submit_urb(int urb)", __FUNCTION__); - return result; } @@ -188,17 +188,12 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp) if (port->serial->dev) { /* shutdown any bulk reads that might be going on */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - usb_unlink_urb (port->interrupt_in_urb); - dbg("%s - usb_clear_halt", __FUNCTION__ ); - usb_clear_halt(port->serial->dev, port->write_urb->pipe); - usb_clear_halt(port->serial->dev, port->read_urb->pipe); - usb_clear_halt(port->serial->dev, port->interrupt_in_urb->pipe); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); } } -static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct cyberjack_private *priv = usb_get_serial_port_data(port); @@ -207,7 +202,6 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u int wrexpected; dbg("%s - port %d", __FUNCTION__, port->number); - dbg("%s - from_user %d", __FUNCTION__, from_user); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); @@ -229,14 +223,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u } /* Copy data */ - if (from_user) { - if (copy_from_user(priv->wrbuf+priv->wrfilled, buf, count)) { - spin_unlock_irqrestore(&priv->lock, flags); - return -EFAULT; - } - } else { - memcpy (priv->wrbuf+priv->wrfilled, buf, count); - } + memcpy (priv->wrbuf+priv->wrfilled, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->wrbuf+priv->wrfilled); @@ -376,6 +363,10 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs) } tty = port->tty; + if (!tty) { + dbg("%s - ignoring since device not open\n", __FUNCTION__); + return; + } if (urb->actual_length) { for (i = 0; i < urb->actual_length ; ++i) { /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ @@ -511,6 +502,7 @@ module_exit(cyberjack_exit); MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_VERSION( DRIVER_VERSION ); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index f187b3165..4b59d75db 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,8 +455,7 @@ static int digi_ioctl( struct usb_serial_port *port, struct file *file, static int digi_tiocmget( struct usb_serial_port *port, struct file *file ); static int digi_tiocmset( struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear ); -static int digi_write( struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count ); +static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ); static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs ); static int digi_write_room( struct usb_serial_port *port ); static int digi_chars_in_buffer( struct usb_serial_port *port ); @@ -624,14 +623,7 @@ static void digi_wakeup_write( struct usb_serial_port *port ) wake_up_interruptible( &port->write_wait ); /* wake up line discipline */ - if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup ) - (tty->ldisc.write_wakeup)(tty); - - /* wake up other tty processes */ - wake_up_interruptible( &tty->write_wait ); - /* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */ - + tty_wakeup(tty); } @@ -1269,26 +1261,21 @@ dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd ); } -static int digi_write( struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count ) +static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ) { int ret,data_len,new_len; struct digi_port *priv = usb_get_serial_port_data(port); unsigned char *data = port->write_urb->transfer_buffer; - unsigned char user_buf[64]; /* 64 bytes is max USB bulk packet */ unsigned long flags = 0; -dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%ld", -priv->dp_port_num, count, from_user, in_interrupt() ); +dbg( "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", +priv->dp_port_num, count, in_interrupt() ); /* copy user data (which can sleep) before getting spin lock */ count = min( count, port->bulk_out_size-2 ); count = min( 64, count); - if( from_user && copy_from_user( user_buf, buf, count ) ) { - return( -EFAULT ); - } /* be sure only one write proceeds at a time */ /* there are races on the port private buffer */ @@ -1301,8 +1288,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); /* buffer data if count is 1 (probably put_char) if possible */ if( count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE ) { - priv->dp_out_buf[priv->dp_out_buf_len++] - = *(from_user ? user_buf : buf); + priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; new_len = 1; } else { new_len = 0; @@ -1335,7 +1321,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); data += priv->dp_out_buf_len; /* copy in new data */ - memcpy( data, from_user ? user_buf : buf, new_len ); + memcpy( data, buf, new_len ); if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { priv->dp_write_urb_in_use = 1; @@ -1553,13 +1539,17 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); + /* if disconnected, just clear flags */ + if (!usb_get_intfdata(port->serial->interface)) + goto exit; + /* do cleanup only after final close on this port */ spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_in_close = 1; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); /* tell line discipline to process only XON/XOFF */ - tty->closing = 1; + tty->closing = 1; /* wait for output to drain */ if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { @@ -1569,8 +1559,7 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co /* flush driver and line discipline buffers */ if( tty->driver->flush_buffer ) tty->driver->flush_buffer( tty ); - if( tty->ldisc.flush_buffer ) - tty->ldisc.flush_buffer( tty ); + tty_ldisc_flush(tty); if (port->serial->dev) { /* wait for transmit idle */ @@ -1619,11 +1608,12 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co DIGI_CLOSE_TIMEOUT ); /* shutdown any outstanding bulk writes */ - usb_unlink_urb (port->write_urb); + usb_kill_urb(port->write_urb); } tty->closing = 0; +exit: spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_write_urb_in_use = 0; priv->dp_in_close = 0; @@ -1757,8 +1747,8 @@ dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() ); /* stop reads and writes on all ports */ for( i=0; itype->num_ports+1; i++ ) { - usb_unlink_urb( serial->port[i]->read_urb ); - usb_unlink_urb( serial->port[i]->write_urb ); + usb_kill_urb(serial->port[i]->read_urb); + usb_kill_urb(serial->port[i]->write_urb); } /* free the private data structures for all ports */ diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 972f3b91d..4d46394f3 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -81,7 +81,6 @@ static int debug; static int empeg_open (struct usb_serial_port *port, struct file *filp); static void empeg_close (struct usb_serial_port *port, struct file *filp); static int empeg_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static int empeg_write_room (struct usb_serial_port *port); @@ -185,13 +184,13 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); /* shutdown our bulk read */ - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); /* Uncomment the following line if you want to see some statistics in your syslog */ /* dev_info (&port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */ } -static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct urb *urb; @@ -235,14 +234,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); - if (from_user) { - if (copy_from_user (urb->transfer_buffer, current_position, transfer_size)) { - bytes_sent = -EFAULT; - break; - } - } else { - memcpy (urb->transfer_buffer, current_position, transfer_size); - } + memcpy (urb->transfer_buffer, current_position, transfer_size); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, urb->transfer_buffer); @@ -406,7 +398,7 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs) static void empeg_throttle (struct usb_serial_port *port) { dbg("%s - port %d", __FUNCTION__, port->number); - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); } @@ -516,11 +508,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct termios *old */ port->tty->low_latency = 1; - /* Notify the tty driver that the termios have changed. */ - port->tty->ldisc.set_termios(port->tty, NULL); - return; - } @@ -583,10 +571,10 @@ static void __exit empeg_exit (void) for (i = 0; i < NUM_URBS; ++i) { if (write_urb_pool[i]) { - /* FIXME - uncomment the following usb_unlink_urb call when + /* FIXME - uncomment the following usb_kill_urb call when * the host controllers get fixed to set urb->dev = NULL after * the urb is finished. Otherwise this call oopses. */ - /* usb_unlink_urb(write_urb_pool[i]); */ + /* usb_kill_urb(write_urb_pool[i]); */ if (write_urb_pool[i]->transfer_buffer) kfree(write_urb_pool[i]->transfer_buffer); usb_free_urb (write_urb_pool[i]); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b35ab607a..884879c99 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -17,6 +17,11 @@ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info * and extra documentation * + * (21/Jul/2004) Ian Abbott + * Incorporated Steven Turner's code to add support for the FT2232C chip. + * The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff. I have + * fixed a couple of things. + * * (27/May/2004) Ian Abbott * Improved throttling code, mostly stolen from the WhiteHEAT driver. * @@ -259,7 +264,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.4.0" +#define DRIVER_VERSION "v1.4.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober " #define DRIVER_DESC "USB FTDI Serial Converters Driver" @@ -363,6 +368,10 @@ static struct usb_device_id id_table_8U232AM [] = { { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) }, { } /* Terminating entry */ }; @@ -473,6 +482,10 @@ static struct usb_device_id id_table_FT232BM [] = { { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_RM_VID, FTDI_RMCANVIEW_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) }, { } /* Terminating entry */ }; @@ -489,11 +502,18 @@ static struct usb_device_id id_table_HE_TIRA1 [] = { }; +static struct usb_device_id id_table_FT2232C[] = { + { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, + { } /* Terminating entry */ +}; + + static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, @@ -516,6 +536,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID, 0x400, 0xffff) }, + { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, @@ -583,6 +604,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(FTDI_RM_VID, FTDI_RMCANVIEW_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, { } /* Terminating entry */ }; @@ -621,6 +646,8 @@ struct ftdi_private { __u8 rx_flags; /* receive state flags (throttling) */ spinlock_t rx_lock; /* spinlock for receive state */ + __u16 interface; /* FT2232C port interface (0 for FT232/245) */ + int force_baud; /* if non-zero, force the baud rate to this value */ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ }; @@ -637,12 +664,13 @@ struct ftdi_private { static int ftdi_SIO_startup (struct usb_serial *serial); static int ftdi_8U232AM_startup (struct usb_serial *serial); static int ftdi_FT232BM_startup (struct usb_serial *serial); +static int ftdi_FT2232C_startup (struct usb_serial *serial); static int ftdi_USB_UIRT_startup (struct usb_serial *serial); static int ftdi_HE_TIRA1_startup (struct usb_serial *serial); static void ftdi_shutdown (struct usb_serial *serial); static int ftdi_open (struct usb_serial_port *port, struct file *filp); static void ftdi_close (struct usb_serial_port *port, struct file *filp); -static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int ftdi_write_room (struct usb_serial_port *port); static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -739,6 +767,32 @@ static struct usb_serial_device_type ftdi_FT232BM_device = { .shutdown = ftdi_shutdown, }; +static struct usb_serial_device_type ftdi_FT2232C_device = { + .owner = THIS_MODULE, + .name = "FTDI FT2232C Compatible", + .id_table = id_table_FT2232C, + .num_interrupt_in = 0, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = ftdi_open, + .close = ftdi_close, + .throttle = ftdi_throttle, + .unthrottle = ftdi_unthrottle, + .write = ftdi_write, + .write_room = ftdi_write_room, + .chars_in_buffer = ftdi_chars_in_buffer, + .read_bulk_callback = ftdi_read_bulk_callback, + .write_bulk_callback = ftdi_write_bulk_callback, + .tiocmget = ftdi_tiocmget, + .tiocmset = ftdi_tiocmset, + .ioctl = ftdi_ioctl, + .set_termios = ftdi_set_termios, + .break_ctl = ftdi_break_ctl, + .attach = ftdi_FT2232C_startup, + .shutdown = ftdi_shutdown, +}; + static struct usb_serial_device_type ftdi_USB_UIRT_device = { .owner = THIS_MODULE, .name = "USB-UIRT Infrared Tranceiver", @@ -866,7 +920,7 @@ static int set_rts(struct usb_serial_port *port, int high_or_low) usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, 0, + ftdi_high_or_low, priv->interface, buf, 0, WDR_TIMEOUT); kfree(buf); @@ -896,7 +950,7 @@ static int set_dtr(struct usb_serial_port *port, int high_or_low) usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - ftdi_high_or_low, 0, + ftdi_high_or_low, priv->interface, buf, 0, WDR_TIMEOUT); kfree(buf); @@ -909,6 +963,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port); static int change_speed(struct usb_serial_port *port) { + struct ftdi_private *priv = usb_get_serial_port_data(port); char *buf; __u16 urb_value; __u16 urb_index; @@ -922,6 +977,9 @@ static int change_speed(struct usb_serial_port *port) urb_index_value = get_ftdi_divisor(port); urb_value = (__u16)urb_index_value; urb_index = (__u16)(urb_index_value >> 16); + if (priv->interface) { /* FT2232C */ + urb_index = (__u16)((urb_index << 8) | priv->interface); + } rv = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), @@ -1015,7 +1073,12 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) } break; case FT232BM: /* FT232BM chip */ - chip_name = "FT232BM"; + case FT2232C: /* FT2232C chip */ + if (priv->chip_type == FT2232C) { + chip_name = "FT2232C"; + } else { + chip_name = "FT232BM"; + } if (baud <= 3000000) { div_value = ftdi_232bm_baud_to_divisor(baud); } else { @@ -1231,6 +1294,35 @@ static int ftdi_FT232BM_startup (struct usb_serial *serial) return (0); } /* ftdi_FT232BM_startup */ +/* Startup for the FT2232C chip */ +/* Called from usbserial:serial_probe */ +static int ftdi_FT2232C_startup (struct usb_serial *serial) +{ /* ftdi_FT2232C_startup */ + struct ftdi_private *priv; + int err; + int inter; + + dbg("%s",__FUNCTION__); + err = ftdi_common_startup(serial); + if (err){ + return (err); + } + + priv = usb_get_serial_port_data(serial->port[0]); + priv->chip_type = FT2232C; + inter = serial->interface->altsetting->desc.bInterfaceNumber; + + if (inter) { + priv->interface = INTERFACE_B; + } + else { + priv->interface = INTERFACE_A; + } + priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */ + + return (0); +} /* ftdi_FT2232C_startup */ + /* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */ /* Called from usbserial:serial_probe */ static int ftdi_USB_UIRT_startup (struct usb_serial *serial) @@ -1323,7 +1415,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, - 0, buf, 0, WDR_TIMEOUT); + priv->interface, buf, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change port->tty->termios - this would loose speed settings, etc. @@ -1373,6 +1465,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) static void ftdi_close (struct usb_serial_port *port, struct file *filp) { /* ftdi_close */ unsigned int c_cflag = port->tty->termios->c_cflag; + struct ftdi_private *priv = usb_get_serial_port_data(port); char buf[1]; dbg("%s", __FUNCTION__); @@ -1383,7 +1476,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, buf, 0, WDR_TIMEOUT) < 0) { + 0, priv->interface, buf, 0, + WDR_TIMEOUT) < 0) { err("error from flowcontrol urb"); } @@ -1398,16 +1492,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) } /* Note change no line if hupcl is off */ /* shutdown our bulk read */ - if (port->read_urb) { - if (usb_unlink_urb (port->read_urb) < 0) { - /* Generally, this isn't an error. If the previous - read bulk callback occurred (or is about to occur) - while the port was being closed or was throtted - (and is still throttled), the read urb will not - have been submitted. */ - dbg("%s - failed to unlink read urb (generally not an error)", __FUNCTION__); - } - } + if (port->read_urb) + usb_kill_urb(port->read_urb); } /* ftdi_close */ @@ -1419,7 +1505,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) * * The new devices do not require this byte */ -static int ftdi_write (struct usb_serial_port *port, int from_user, +static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count) { /* ftdi_write */ struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1476,17 +1562,8 @@ static int ftdi_write (struct usb_serial_port *port, int from_user, /* Write the control byte at the front of the packet*/ *first_byte = 1 | ((user_pktsz) << 2); /* Copy data for packet */ - if (from_user) { - if (copy_from_user (first_byte + data_offset, - current_position, user_pktsz)){ - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (first_byte + data_offset, - current_position, user_pktsz); - } + memcpy (first_byte + data_offset, + current_position, user_pktsz); first_byte += user_pktsz + data_offset; current_position += user_pktsz; todo -= user_pktsz; @@ -1494,15 +1571,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user, } else { /* No control byte required. */ /* Copy in the data to send */ - if (from_user) { - if (copy_from_user (buffer, buf, count)) { - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (buffer, buf, count); - } + memcpy (buffer, buf, count); } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer); @@ -1796,7 +1865,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, - urb_value , 0, + urb_value , priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state); } @@ -1875,7 +1944,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, - urb_value , 0, + urb_value , priv->interface, buf, 0, 100) < 0) { err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); } @@ -1886,7 +1955,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, + 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("%s error from disable flowcontrol urb", __FUNCTION__); } @@ -1903,6 +1972,13 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ if (change_speed(port)) { err("%s urb failed to set baurdrate", __FUNCTION__); } + /* Ensure RTS and DTR are raised */ + else if (set_dtr(port, HIGH) < 0){ + err("%s Error from DTR HIGH urb", __FUNCTION__); + } + else if (set_rts(port, HIGH) < 0){ + err("%s Error from RTS HIGH urb", __FUNCTION__); + } } /* Set flow control */ @@ -1913,7 +1989,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0 , FTDI_SIO_RTS_CTS_HS, + 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to set to rts/cts flow control"); } @@ -1939,7 +2015,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - urb_value , FTDI_SIO_XON_XOFF_HS, + urb_value , (FTDI_SIO_XON_XOFF_HS + | priv->interface), buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to set to xon/xoff flow control"); } @@ -1951,7 +2028,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, + 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to clear flow control"); } @@ -1985,13 +2062,14 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) break; case FT8U232AM: case FT232BM: + case FT2232C: /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same format as the data returned from the in point */ if ((ret = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), FTDI_SIO_GET_MODEM_STATUS_REQUEST, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, + 0, priv->interface, buf, 2, WDR_TIMEOUT)) < 0 ) { err("%s Could not get modem status of device - err: %d", __FUNCTION__, ret); @@ -2206,6 +2284,9 @@ static int __init ftdi_init (void) retval = usb_serial_register(&ftdi_FT232BM_device); if (retval) goto failed_FT232BM_register; + retval = usb_serial_register(&ftdi_FT2232C_device); + if (retval) + goto failed_FT2232C_register; retval = usb_serial_register(&ftdi_USB_UIRT_device); if (retval) goto failed_USB_UIRT_register; @@ -2223,6 +2304,8 @@ failed_usb_register: failed_HE_TIRA1_register: usb_serial_deregister(&ftdi_USB_UIRT_device); failed_USB_UIRT_register: + usb_serial_deregister(&ftdi_FT2232C_device); +failed_FT2232C_register: usb_serial_deregister(&ftdi_FT232BM_device); failed_FT232BM_register: usb_serial_deregister(&ftdi_8U232AM_device); @@ -2241,6 +2324,7 @@ static void __exit ftdi_exit (void) usb_deregister (&ftdi_driver); usb_serial_deregister (&ftdi_HE_TIRA1_device); usb_serial_deregister (&ftdi_USB_UIRT_device); + usb_serial_deregister (&ftdi_FT2232C_device); usb_serial_deregister (&ftdi_FT232BM_device); usb_serial_deregister (&ftdi_8U232AM_device); usb_serial_deregister (&ftdi_SIO_device); diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 02554035e..e7a7e0aba 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -26,6 +26,7 @@ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ +#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ @@ -224,6 +225,21 @@ */ #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ +/* + * Definitions for B&B Electronics products. + */ +#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ +#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ +#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ +#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ + +/* + * RM Michaelides CANview USB (http://www.rmcan.com) + * CAN filedbus interface adapter, addad by port GmbH www.port.de) + */ +#define FTDI_RM_VID 0x0403 /* Vendor Id */ +#define FTDI_RMCANVIEW_PID 0xfd60 /* Product Id */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ @@ -234,6 +250,21 @@ #define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ #define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ +/* Port interface code for FT2232C */ +#define INTERFACE_A 1 +#define INTERFACE_B 2 + + +/* + * BmRequestType: 1100 0000b + * bRequest: FTDI_E2_READ + * wValue: 0 + * wIndex: Address of word to read + * wLength: 2 + * Data: Will return a word of data from E2Address + * + */ + /* Port Identifier Table */ #define PIT_DEFAULT 0 /* SIOA */ #define PIT_SIOA 1 /* SIOA */ @@ -333,6 +364,7 @@ typedef enum { SIO = 1, FT8U232AM = 2, FT232BM = 3, + FT2232C = 4, } ftdi_chip_type_t; typedef enum { diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 196fea084..99214aa3c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -147,9 +147,9 @@ static void generic_cleanup (struct usb_serial_port *port) if (serial->dev) { /* shutdown any bulk reads that might be going on */ if (serial->num_bulk_out) - usb_unlink_urb (port->write_urb); + usb_kill_urb(port->write_urb); if (serial->num_bulk_in) - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); } } @@ -159,7 +159,7 @@ void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) generic_cleanup (port); } -int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; int result; @@ -181,13 +181,7 @@ int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, count)) - return -EFAULT; - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } + memcpy (port->write_urb->transfer_buffer, buf, count); data = port->write_urb->transfer_buffer; usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index e727628bd..010160ed1 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -23,6 +23,10 @@ * Edgeport/4D8 * Edgeport/8i * + * For questions or problems with this driver, contact Inside Out + * Networks technical support, or Peter Berger , + * or Al Borchers . + * * Version history: * * 2003_04_03 al borchers @@ -267,7 +271,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.3" +#define DRIVER_VERSION "v2.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" @@ -297,8 +301,6 @@ #define OPEN_TIMEOUT (5*HZ) /* 5 seconds */ #define COMMAND_TIMEOUT (5*HZ) /* 5 seconds */ -static int debug; - /* receive port state */ enum RXSTATE { EXPECT_HDR1 = 0, /* Expect header byte 1 */ @@ -329,6 +331,7 @@ struct edgeport_port { struct TxFifo txfifo; /* transmit fifo -- size will be maxTxCredits */ struct urb *write_urb; /* write URB for this port */ char write_in_progress; /* TRUE while a write URB is outstanding */ + spinlock_t ep_lock; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ @@ -370,6 +373,8 @@ struct edgeport_serial { __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ unsigned char * bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ struct urb * read_urb; /* our bulk read urb */ + int read_in_progress; + spinlock_t es_lock; __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ @@ -420,7 +425,11 @@ static struct divisor_table_entry divisor_table[] = { }; /* local variables */ -static int CmdUrbs = 0; /* Number of outstanding Command Write Urbs */ +static int debug; + +static int low_latency = 1; /* tty low latency flag, on by default */ + +static int CmdUrbs = 0; /* Number of outstanding Command Write Urbs */ /* local function prototypes */ @@ -434,7 +443,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs); /* function prototypes for the usbserial callbacks */ static int edge_open (struct usb_serial_port *port, struct file *filp); static void edge_close (struct usb_serial_port *port, struct file *filp); -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); @@ -459,8 +468,9 @@ static struct usb_driver io_driver = { }; /* function prototypes for all of our local functions */ -static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); +static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); +static void edge_tty_recv (struct device *dev, struct tty_struct *tty, unsigned char *data, int length); static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr); static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); @@ -478,11 +488,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial); static void get_boot_desc (struct edgeport_serial *edge_serial); static void load_application_firmware (struct edgeport_serial *edge_serial); - -static void unicode_to_ascii (char *string, short *unicode, int unicode_size); - - - +static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); // ************************************************************************ @@ -504,7 +510,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) __u32 BootNewVer; __u8 BootMajorVersion; __u8 BootMinorVersion; - __u16 BootBuildNumber; + __le16 BootBuildNumber; __u8 *BootImage; __u32 BootSize; struct edge_firmware_image_record *record; @@ -653,7 +659,7 @@ static void get_product_info(struct edgeport_serial *edge_serial) memset (product_info, 0, sizeof(struct edgeport_product_info)); - product_info->ProductId = (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_GENERATION_2); + product_info->ProductId = (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_80251_NETCHIP); product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts; product_info->ProdInfoVer = 0; @@ -669,7 +675,7 @@ static void get_product_info(struct edgeport_serial *edge_serial) memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate)); // check if this is 2nd generation hardware - if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) { + if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_80251_NETCHIP) { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber); @@ -784,20 +790,24 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) if (length > 1) { bytes_avail = data[0] | (data[1] << 8); if (bytes_avail) { + spin_lock(&edge_serial->es_lock); edge_serial->rxBytesAvail += bytes_avail; - dbg("%s - bytes_avail = %d, rxBytesAvail %d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail); + dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress); - if ((edge_serial->rxBytesAvail > 0) && - (edge_serial->read_urb->status != -EINPROGRESS)) { - dbg(" --- Posting a read"); + if (edge_serial->rxBytesAvail > 0 && + !edge_serial->read_in_progress) { + dbg("%s - posting a read", __FUNCTION__); + edge_serial->read_in_progress = TRUE; /* we have pending bytes on the bulk in pipe, send a request */ edge_serial->read_urb->dev = edge_serial->serial->dev; result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); if (result) { - dbg("%s - usb_submit_urb(read bulk) failed with result = %d", __FUNCTION__, result); + dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result); + edge_serial->read_in_progress = FALSE; } } + spin_unlock(&edge_serial->es_lock); } } /* grab the txcredits for the ports if available */ @@ -809,12 +819,14 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) port = edge_serial->serial->port[portNumber]; edge_port = usb_get_serial_port_data(port); if (edge_port->open) { + spin_lock(&edge_port->ep_lock); edge_port->txCredits += txCredits; + spin_unlock(&edge_port->ep_lock); dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits); /* tell the tty driver that something has changed */ if (edge_port->port->tty) - wake_up_interruptible(&edge_port->port->tty->write_wait); + tty_wakeup(edge_port->port->tty); // Since we have more credit, check if more data can be sent send_more_port_data(edge_serial, edge_port); @@ -849,34 +861,43 @@ static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); + edge_serial->read_in_progress = FALSE; return; } - if (urb->actual_length) { - raw_data_length = urb->actual_length; + if (urb->actual_length == 0) { + dbg("%s - read bulk callback with no data", __FUNCTION__); + edge_serial->read_in_progress = FALSE; + return; + } - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data); + raw_data_length = urb->actual_length; - /* decrement our rxBytes available by the number that we just got */ - edge_serial->rxBytesAvail -= raw_data_length; + usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data); - dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail); + spin_lock(&edge_serial->es_lock); - process_rcvd_data (edge_serial, data, urb->actual_length); + /* decrement our rxBytes available by the number that we just got */ + edge_serial->rxBytesAvail -= raw_data_length; - /* check to see if there's any more data for us to read */ - if ((edge_serial->rxBytesAvail > 0) && - (edge_serial->read_urb->status != -EINPROGRESS)) { - dbg(" --- Posting a read"); + dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail); - /* there is, so resubmit our urb */ - edge_serial->read_urb->dev = edge_serial->serial->dev; - status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); - if (status) { - dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status); - } + process_rcvd_data (edge_serial, data, urb->actual_length); + + /* check to see if there's any more data for us to read */ + if (edge_serial->rxBytesAvail > 0) { + dbg("%s - posting a read", __FUNCTION__); + edge_serial->read_urb->dev = edge_serial->serial->dev; + status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); + if (status) { + dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status); + edge_serial->read_in_progress = FALSE; } + } else { + edge_serial->read_in_progress = FALSE; } + + spin_unlock(&edge_serial->es_lock); } @@ -900,12 +921,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs) if (tty && edge_port->open) { /* let the tty driver wakeup if it has a special write_wakeup function */ - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - (tty->ldisc.write_wakeup)(tty); - } - - /* tell the tty driver that something has changed */ - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); } // Release the Write URB @@ -951,7 +967,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs) /* tell the tty driver that something has changed */ if (tty && edge_port->open) - wake_up_interruptible(&tty->write_wait); + tty_wakeup(tty); /* we have completed the command */ edge_port->commandPending = FALSE; @@ -982,11 +998,8 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) if (edge_port == NULL) return -ENODEV; - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates (like with OHCI) data - can get lost. */ if (port->tty) - port->tty->low_latency = 1; + port->tty->low_latency = low_latency; /* see if we've set up our endpoint info yet (can't set it up in edge_startup as the structures were not set up at that time.) */ @@ -1024,6 +1037,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) port0->bulk_in_buffer, edge_serial->read_urb->transfer_buffer_length, edge_bulk_in_callback, edge_serial); + edge_serial->read_in_progress = FALSE; /* start interrupt read for this edgeport * this interrupt will continue as long as the edgeport is connected */ @@ -1086,6 +1100,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) /* Allocate a URB for the write */ edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL); + edge_port->write_in_progress = FALSE; if (!edge_port->write_urb) { dbg("%s - no memory", __FUNCTION__); @@ -1243,7 +1258,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->openPending = FALSE; if (edge_port->write_urb) { - usb_unlink_urb (edge_port->write_urb); + usb_kill_urb(edge_port->write_urb); } if (edge_port->write_urb) { @@ -1252,9 +1267,11 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) kfree(edge_port->write_urb->transfer_buffer); } usb_free_urb (edge_port->write_urb); + edge_port->write_urb = NULL; } if (edge_port->txfifo.fifo) { kfree(edge_port->txfifo.fifo); + edge_port->txfifo.fifo = NULL; } dbg("%s exited", __FUNCTION__); @@ -1267,14 +1284,15 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) * If successful, we return the number of bytes written, otherwise we return * a negative error number. *****************************************************************************/ -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count) +static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct TxFifo *fifo; int copySize; int bytesleft; int firsthalf; int secondhalf; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -1284,6 +1302,8 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign // get a pointer to the Tx fifo fifo = &edge_port->txfifo; + spin_lock_irqsave(&edge_port->ep_lock, flags); + // calculate number of bytes to put in fifo copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count)); @@ -1293,7 +1313,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ if (copySize == 0) { dbg("%s - copySize = Zero", __FUNCTION__); - return 0; + goto finish_write; } // queue the data @@ -1307,12 +1327,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft); /* now copy our data */ - if (from_user) { - if (copy_from_user(&fifo->fifo[fifo->head], data, firsthalf)) - return -EFAULT; - } else { - memcpy(&fifo->fifo[fifo->head], data, firsthalf); - } + memcpy(&fifo->fifo[fifo->head], data, firsthalf); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]); // update the index and size @@ -1328,12 +1343,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign if (secondhalf) { dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf); - if (from_user) { - if (copy_from_user(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf)) - return -EFAULT; - } else { - memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); - } + memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]); // update the index and size fifo->count += secondhalf; @@ -1341,6 +1351,9 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign // No need to check for wrap since we can not get to end of fifo in this part } +finish_write: + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port); dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count); @@ -1372,14 +1385,17 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge int bytesleft; int firsthalf; int secondhalf; + unsigned long flags; dbg("%s(%d)", __FUNCTION__, edge_port->port->number); + spin_lock_irqsave(&edge_port->ep_lock, flags); + if (edge_port->write_in_progress || !edge_port->open || (fifo->count == 0)) { dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress); - return; + goto exit_send; } // since the amount of data in the fifo will always fit into the @@ -1389,9 +1405,9 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge // to bother queueing a write. If it's too small, say a few bytes, // it's better to wait for more credits so we can do a larger // write. - if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) { + if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) { dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits ); - return; + goto exit_send; } // lock this write @@ -1412,7 +1428,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge if (buffer == NULL) { dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__); edge_port->write_in_progress = FALSE; - return; + goto exit_send; } buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count); buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count); @@ -1450,7 +1466,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { /* something went wrong */ - dbg("%s - usb_submit_urb(write bulk) failed", __FUNCTION__); + dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status); edge_port->write_in_progress = FALSE; /* revert the credits as something bad happened. */ @@ -1458,6 +1474,9 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge edge_port->icount.tx -= count; } dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count); + +exit_send: + spin_unlock_irqrestore(&edge_port->ep_lock, flags); } @@ -1471,8 +1490,9 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge *****************************************************************************/ static int edge_write_room (struct usb_serial_port *port) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); int room; + unsigned long flags; dbg("%s", __FUNCTION__); @@ -1489,7 +1509,9 @@ static int edge_write_room (struct usb_serial_port *port) } // total of both buffers is still txCredit + spin_lock_irqsave(&edge_port->ep_lock, flags); room = edge_port->txCredits - edge_port->txfifo.count; + spin_unlock_irqrestore(&edge_port->ep_lock, flags); dbg("%s - returns %d", __FUNCTION__, room); return room; @@ -1507,8 +1529,9 @@ static int edge_write_room (struct usb_serial_port *port) *****************************************************************************/ static int edge_chars_in_buffer (struct usb_serial_port *port) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); int num_chars; + unsigned long flags; dbg("%s", __FUNCTION__); @@ -1522,7 +1545,9 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) return -EINVAL; } + spin_lock_irqsave(&edge_port->ep_lock, flags); num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count; + spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (num_chars) { dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars); } @@ -1538,7 +1563,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) *****************************************************************************/ static void edge_throttle (struct usb_serial_port *port) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty; int status; @@ -1561,7 +1586,7 @@ static void edge_throttle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, 0, &stop_char, 1); + status = edge_write (port, &stop_char, 1); if (status <= 0) { return; } @@ -1587,7 +1612,7 @@ static void edge_throttle (struct usb_serial_port *port) *****************************************************************************/ static void edge_unthrottle (struct usb_serial_port *port) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty; int status; @@ -1610,7 +1635,7 @@ static void edge_unthrottle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, 0, &start_char, 1); + status = edge_write (port, &start_char, 1); if (status <= 0) { return; } @@ -1635,7 +1660,7 @@ static void edge_unthrottle (struct usb_serial_port *port) *****************************************************************************/ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; unsigned int cflag; @@ -1647,20 +1672,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_ cflag = tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + if (cflag == old_termios->c_cflag && + tty->termios->c_iflag == old_termios->c_iflag) { dbg("%s - nothing to change", __FUNCTION__); return; } } dbg("%s - clfag %08x iflag %08x", __FUNCTION__, - tty->termios->c_cflag, - RELEVANT_IFLAG(tty->termios->c_iflag)); + tty->termios->c_cflag, tty->termios->c_iflag); if (old_termios) { dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, - old_termios->c_cflag, - RELEVANT_IFLAG(old_termios->c_iflag)); + old_termios->c_cflag, old_termios->c_iflag); } dbg("%s - port %d", __FUNCTION__, port->number); @@ -1693,12 +1716,15 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value) { unsigned int result = 0; + unsigned long flags; + spin_lock_irqsave(&edge_port->ep_lock, flags); if (edge_port->maxTxCredits == edge_port->txCredits && edge_port->txfifo.count == 0) { dbg("%s -- Empty", __FUNCTION__); result = TIOCSER_TEMT; } + spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (copy_to_user(value, &result, sizeof(int))) return -EFAULT; @@ -1724,7 +1750,7 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); @@ -1753,7 +1779,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig static int edge_tiocmget(struct usb_serial_port *port, struct file *file) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int result = 0; unsigned int msr; unsigned int mcr; @@ -1810,7 +1836,7 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct *****************************************************************************/ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; struct serial_icounter_struct icount; @@ -1892,7 +1918,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned *****************************************************************************/ static void edge_break (struct usb_serial_port *port, int break_state) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; /* flush and chase */ @@ -1926,14 +1952,13 @@ static void edge_break (struct usb_serial_port *port, int break_state) * process_rcvd_data * this function handles the data received on the bulk in pipe. *****************************************************************************/ -static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength) +static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength) { struct usb_serial_port *port; struct edgeport_port *edge_port; struct tty_struct *tty; __u16 lastBufferLength; __u16 rxLen; - int i; dbg("%s", __FUNCTION__); @@ -1988,7 +2013,6 @@ static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char // We have all the header bytes, process the status now process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0); - edge_serial->rxState = EXPECT_HDR1; break; } else { @@ -2029,15 +2053,7 @@ static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char tty = edge_port->port->tty; if (tty) { dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort); - for (i = 0; i < rxLen ; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - /* this doesn't actually push the data through unless tty->low_latency is set */ - tty_insert_flip_char(tty, buffer[i], 0); - } - tty_flip_buffer_push(tty); + edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); } edge_port->icount.rx += rxLen; } @@ -2058,8 +2074,6 @@ static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char } } - - return 0; } @@ -2075,7 +2089,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 /* switch the port pointer to the one being currently talked about */ port = edge_serial->serial->port[edge_serial->rxPort]; - edge_port = usb_get_serial_port_data(port); + edge_port = usb_get_serial_port_data(port); if (edge_port == NULL) { dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort); return; @@ -2164,6 +2178,37 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2 } +/***************************************************************************** + * edge_tty_recv + * this function passes data on to the tty flip buffer + *****************************************************************************/ +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) +{ + int cnt; + + do { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __FUNCTION__, length); + return; + } + } + cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); + memcpy(tty->flip.char_buf_ptr, data, cnt); + memset(tty->flip.flag_buf_ptr, 0, cnt); + tty->flip.char_buf_ptr += cnt; + tty->flip.flag_buf_ptr += cnt; + tty->flip.count += cnt; + data += cnt; + length -= cnt; + } while (length > 0); + + tty_flip_buffer_push(tty); +} + + /***************************************************************************** * handle_new_msr * this function handles any change to the msr register for a port. @@ -2223,10 +2268,8 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l } /* Place LSR data byte into Rx buffer */ - if (lsrData && edge_port->port->tty) { - tty_insert_flip_char(edge_port->port->tty, data, 0); - tty_flip_buffer_push(edge_port->port->tty); - } + if (lsrData && edge_port->port->tty) + edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); /* update input line counters */ icount = &edge_port->icount; @@ -2447,9 +2490,10 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer if (status) { /* something went wrong */ - dbg("%s - usb_submit_urb(write bulk) failed", __FUNCTION__); - usb_unlink_urb (urb); - usb_free_urb (urb); + dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status); + usb_kill_urb(urb); + usb_free_urb(urb); + CmdUrbs--; return status; } @@ -2529,8 +2573,6 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) { int i; __u16 custom; - __u16 round1; - __u16 round; dbg("%s - %d", __FUNCTION__, baudrate); @@ -2545,16 +2587,10 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) // We have tried all of the standard baud rates // lets try to calculate the divisor for this baud rate // Make sure the baud rate is reasonable - if (baudrate < 230400) { + if (baudrate > 50 && baudrate < 230400) { // get divisor - custom = (__u16)(230400L / baudrate); + custom = (__u16)((230400L + baudrate/2) / baudrate); - // Check for round off - round1 = (__u16)(2304000L / baudrate); - round = (__u16)(round1 - (custom * 10)); - if (round > 4) { - custom++; - } *divisor = custom; dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom); @@ -2606,6 +2642,9 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r * This routine is called to set the UART on the device to match the specified * new settings. *****************************************************************************/ +#ifndef CMSPAR +#define CMSPAR 0 +#endif static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) { struct tty_struct *tty; @@ -2646,7 +2685,15 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio lParity = LCR_PAR_NONE; if (cflag & PARENB) { - if (cflag & PARODD) { + if (cflag & CMSPAR) { + if (cflag & PARODD) { + lParity = LCR_PAR_MARK; + dbg("%s - parity = mark", __FUNCTION__); + } else { + lParity = LCR_PAR_SPACE; + dbg("%s - parity = space", __FUNCTION__); + } + } else if (cflag & PARODD) { lParity = LCR_PAR_ODD; dbg("%s - parity = odd", __FUNCTION__); } else { @@ -2747,12 +2794,15 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio * ASCII range, but it's only for debugging... * NOTE: expects the unicode in LE format ****************************************************************************/ -static void unicode_to_ascii (char *string, short *unicode, int unicode_size) +static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) { int i; - for (i = 0; i < unicode_size; ++i) { + + if (unicode_size <= 0) + return; + + for (i = 0; i < unicode_size; ++i) string[i] = (char)(le16_to_cpu(unicode[i])); - } string[unicode_size] = 0x00; } @@ -2873,7 +2923,7 @@ static void load_application_firmware (struct edgeport_serial *edge_serial) record = (struct edge_firmware_image_record *)firmware; response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len); + dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); break; } firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); @@ -2892,8 +2942,6 @@ static void load_application_firmware (struct edgeport_serial *edge_serial) } - - /**************************************************************************** * edge_startup ****************************************************************************/ @@ -2909,10 +2957,11 @@ static int edge_startup (struct usb_serial *serial) /* create our private serial structure */ edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); if (edge_serial == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory", __FUNCTION__); + dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } memset (edge_serial, 0, sizeof(struct edgeport_serial)); + spin_lock_init(&edge_serial->es_lock); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); @@ -2965,12 +3014,13 @@ static int edge_startup (struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory", __FUNCTION__); + dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); usb_set_serial_data(serial, NULL); kfree(edge_serial); return -ENOMEM; } memset (edge_port, 0, sizeof(struct edgeport_port)); + spin_lock_init(&edge_port->ep_lock); edge_port->port = serial->port[i]; usb_set_serial_port_data(serial->port[i], edge_port); } @@ -2979,7 +3029,6 @@ static int edge_startup (struct usb_serial *serial) } - /**************************************************************************** * edge_shutdown * This function is called whenever the device is removed from the usb bus. @@ -3007,9 +3056,7 @@ static void edge_shutdown (struct usb_serial *serial) static int __init edgeport_init(void) { int retval; - retval = usb_serial_register(&edgeport_1port_device); - if (retval) - goto failed_1port_device_register; + retval = usb_serial_register(&edgeport_2port_device); if (retval) goto failed_2port_device_register; @@ -3024,6 +3071,7 @@ static int __init edgeport_init(void) goto failed_usb_register; info(DRIVER_DESC " " DRIVER_VERSION); return 0; + failed_usb_register: usb_serial_deregister(&edgeport_8port_device); failed_8port_device_register: @@ -3031,13 +3079,10 @@ failed_8port_device_register: failed_4port_device_register: usb_serial_deregister(&edgeport_2port_device); failed_2port_device_register: - usb_serial_deregister(&edgeport_1port_device); -failed_1port_device_register: return retval; } - /**************************************************************************** * edgeport_exit * Called when the driver is about to be unloaded. @@ -3045,7 +3090,6 @@ failed_1port_device_register: static void __exit edgeport_exit (void) { usb_deregister (&io_driver); - usb_serial_deregister (&edgeport_1port_device); usb_serial_deregister (&edgeport_2port_device); usb_serial_deregister (&edgeport_4port_device); usb_serial_deregister (&edgeport_8port_device); @@ -3061,3 +3105,6 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); + +module_param(low_latency, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Low latency enabled or not"); diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h index 386139d45..5112d7aac 100644 --- a/drivers/usb/serial/io_edgeport.h +++ b/drivers/usb/serial/io_edgeport.h @@ -107,11 +107,11 @@ struct edgeport_product_info { __u8 BootMajorVersion; /* Boot Firmware version: xx. */ __u8 BootMinorVersion; /* yy. */ - __u16 BootBuildNumber; /* zzzz (LE format) */ + __le16 BootBuildNumber; /* zzzz (LE format) */ __u8 FirmwareMajorVersion; /* Operational Firmware version:xx. */ __u8 FirmwareMinorVersion; /* yy. */ - __u16 FirmwareBuildNumber; /* zzzz (LE format) */ + __le16 FirmwareBuildNumber; /* zzzz (LE format) */ __u8 ManufactureDescDate[3]; /* MM/DD/YY when descriptor template was compiled */ __u8 Unused1[1]; /* Available */ diff --git a/drivers/usb/serial/io_fw_boot.h b/drivers/usb/serial/io_fw_boot.h index acbf01100..099fafaf5 100644 --- a/drivers/usb/serial/io_fw_boot.h +++ b/drivers/usb/serial/io_fw_boot.h @@ -13,9 +13,9 @@ #if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD) #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD struct edge_firmware_image_record { - unsigned short ExtAddr; - unsigned short Addr; - unsigned short Len; + __le16 ExtAddr; + __le16 Addr; + __le16 Len; unsigned char Data[0]; } __attribute__ ((packed)); diff --git a/drivers/usb/serial/io_fw_boot2.h b/drivers/usb/serial/io_fw_boot2.h index 3691fa54e..c7c3a3c30 100644 --- a/drivers/usb/serial/io_fw_boot2.h +++ b/drivers/usb/serial/io_fw_boot2.h @@ -13,9 +13,9 @@ #if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD) #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD struct edge_firmware_image_record { - unsigned short ExtAddr; - unsigned short Addr; - unsigned short Len; + __le16 ExtAddr; + __le16 Addr; + __le16 Len; unsigned char Data[0]; } __attribute__ ((packed)); diff --git a/drivers/usb/serial/io_fw_down.h b/drivers/usb/serial/io_fw_down.h index 245740eb1..5a61d809a 100644 --- a/drivers/usb/serial/io_fw_down.h +++ b/drivers/usb/serial/io_fw_down.h @@ -13,11 +13,11 @@ #if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD) #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD struct edge_firmware_image_record { - unsigned short ExtAddr; - unsigned short Addr; - unsigned short Len; + __le16 ExtAddr; + __le16 Addr; + __le16 Len; unsigned char Data[0]; - } __attribute ((packed)); + } __attribute__ ((packed)); struct edge_firmware_version_info { unsigned char MajorVersion; @@ -36,11 +36,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = { // Segment #1, Start Address 00ff0000, Length 6 0xff,0x00,0x00,0x00,0x06,0x00, - 0x02, 0x00, 0x80, 0x02, 0x49, 0x39, + 0x02, 0x00, 0x80, 0x02, 0x44, 0xb0, // Segment #2, Start Address 00ff000b, Length 3 0xff,0x00,0x0b,0x00,0x03,0x00, - 0x02, 0x44, 0x1a, + 0x02, 0x44, 0x72, // Segment #3, Start Address 00ff0013, Length 3 0xff,0x00,0x13,0x00,0x03,0x00, @@ -72,11 +72,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = { // Segment #10, Start Address 00ff004b, Length 3 0xff,0x00,0x4b,0x00,0x03,0x00, - 0x02, 0x70, 0xd4, + 0x02, 0x6e, 0xc4, // Segment #11, Start Address 00ff0053, Length 3 0xff,0x00,0x53,0x00,0x03,0x00, - 0x02, 0x77, 0x9d, + 0x02, 0x75, 0x8d, // Segment #12, Start Address 00ff007b, Length 3 0xff,0x00,0x7b,0x00,0x03,0x00, @@ -86,657 +86,745 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0xff,0x00,0x80,0x00,0x07,0x00, 0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x51, -// Segment #14, Start Address 00ff4000, Length 15920 -0xff,0x00,0x00,0x40,0x30,0x3e, +// Segment #14, Start Address 00ff3000, Length 2178 +0xff,0x00,0x00,0x30,0x82,0x08, + 0x12, 0x37, 0x28, 0x12, 0x30, 0x3e, 0x12, 0x30, 0x54, 0x12, 0x30, 0xe5, 0x12, 0x31, 0x68, 0x12, + 0x35, 0x20, 0x12, 0x38, 0x58, 0x12, 0x31, 0x15, 0x12, 0x31, 0x40, 0x12, 0x30, 0xa0, 0x80, 0xe0, + 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 0x09, 0xb1, 0x01, 0xcf, 0xb4, 0x00, 0x02, 0x80, + 0x05, 0x14, 0x19, 0xb1, 0x01, 0xcf, 0xa5, 0x0b, 0xbe, 0x31, 0x2f, 0x78, 0xeb, 0x22, 0xc2, 0xaf, + 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 0xf1, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xef, 0xd0, + 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 0x60, 0x43, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, + 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, + 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 0x04, 0x0a, 0x32, 0x09, 0x53, 0x67, 0x8e, 0x5e, + 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, + 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, + 0xc2, 0xaf, 0x7e, 0x20, 0x00, 0x7e, 0x30, 0x01, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x32, 0x01, + 0x8f, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 0x21, 0xca, + 0x19, 0x49, 0x22, 0x30, 0xd5, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, + 0x78, 0xd6, 0xd2, 0xaf, 0x22, 0x46, 0x0f, 0x49, 0x67, 0x4c, 0xbf, 0x50, 0x17, 0x53, 0x6f, 0x56, + 0xc7, 0x5a, 0x1f, 0x5d, 0x77, 0xc2, 0xaf, 0xe5, 0x32, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, + 0x07, 0xca, 0xb8, 0x12, 0x31, 0x02, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, + 0xaf, 0x22, 0xca, 0x28, 0x12, 0x67, 0xab, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 0xb2, 0x67, + 0x8e, 0xf4, 0x52, 0x32, 0x22, 0xc2, 0xaf, 0xe5, 0x34, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, + 0x07, 0xca, 0xb8, 0x12, 0x31, 0x32, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, + 0xaf, 0x22, 0xca, 0x28, 0x0a, 0x22, 0x09, 0x42, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xda, 0x28, 0x22, + 0xc2, 0xaf, 0xe5, 0x35, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, + 0x5d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x7e, + 0x40, 0x00, 0x12, 0x6c, 0x5b, 0xda, 0x28, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, + 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x85, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, + 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x31, 0x90, 0x89, 0x24, + 0x31, 0xa0, 0x32, 0x10, 0x32, 0x80, 0x32, 0xf0, 0x33, 0x60, 0x33, 0xd0, 0x34, 0x40, 0x34, 0xb0, + 0x7e, 0x27, 0x01, 0x8f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x49, 0x30, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0x9f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x9f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xcf, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xcf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x18, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xcf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xa1, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa1, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd0, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x19, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x93, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xa3, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa3, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd1, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd1, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1a, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd1, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x53, 0x38, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xa5, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa5, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd2, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd2, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1b, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd2, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x97, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xa7, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa7, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd3, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd3, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1c, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd3, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xa9, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa9, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd4, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd4, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1d, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd4, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x9b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xab, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xab, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd5, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd5, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1e, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd5, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, + 0x01, 0xad, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xad, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd6, 0x80, + 0x2e, 0x7e, 0x63, 0x01, 0xd6, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, + 0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1f, 0x6c, + 0x00, 0x7a, 0x03, 0x01, 0xd6, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x35, + 0x3d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, + 0x0a, 0x2b, 0x49, 0x22, 0x35, 0x48, 0x89, 0x24, 0x35, 0x58, 0x35, 0x92, 0x35, 0xcc, 0x36, 0x06, + 0x36, 0x40, 0x36, 0x7a, 0x36, 0xb4, 0x36, 0xee, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x14, + 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x49, 0x30, + 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, + 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x20, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, + 0xf1, 0x22, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, + 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, + 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, + 0x21, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x82, 0x00, + 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, + 0x12, 0x12, 0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, + 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x22, 0xc0, 0xf1, 0x75, 0xf1, 0x01, + 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, + 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x53, 0x38, 0x7d, 0x21, + 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, + 0x12, 0x7c, 0x15, 0xc2, 0x23, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, + 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, + 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, + 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x24, 0xc0, + 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, + 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, + 0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, + 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x25, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, + 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, + 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, + 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, + 0x15, 0xc2, 0x26, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, + 0x87, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, + 0x19, 0x7d, 0x12, 0x12, 0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, + 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x27, 0xc0, 0xf1, 0x75, + 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xe5, 0x33, 0x60, 0x14, 0x7e, 0x20, + 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x37, 0x45, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, + 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x37, 0x50, 0x89, 0x24, + 0x37, 0x60, 0x37, 0x7f, 0x37, 0x9e, 0x37, 0xbd, 0x37, 0xdc, 0x37, 0xfb, 0x38, 0x1a, 0x38, 0x39, + 0x7e, 0x24, 0x80, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x48, 0x1b, 0xda, 0x19, 0x10, 0x04, 0x02, + 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, + 0x24, 0x81, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4b, 0x73, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, + 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, + 0x82, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4e, 0xcb, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, + 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, + 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x52, 0x23, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, + 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x84, 0x00, + 0xca, 0x19, 0x7d, 0x12, 0x12, 0x55, 0x7b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, + 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0xca, + 0x19, 0x7d, 0x12, 0x12, 0x58, 0xd3, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, + 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0xca, 0x19, + 0x7d, 0x12, 0x12, 0x5c, 0x2b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, + 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x87, 0x00, 0xca, 0x19, 0x7d, + 0x12, 0x12, 0x5f, 0x83, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, + 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, + 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, + 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, + 0xaf, 0x22, + +// Segment #15, Start Address 00ff4000, Length 15381 +0xff,0x00,0x00,0x40,0x15,0x3c, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, - 0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x59, 0xd2, - 0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7f, 0x3f, 0xf5, - 0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x77, 0xda, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, - 0xf1, 0x60, 0x03, 0x12, 0x43, 0x68, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x7f, 0xd2, 0xaf, 0x02, 0x44, - 0x06, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, + 0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x6f, 0xd2, + 0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7d, 0x30, 0xf5, + 0x2f, 0x7a, 0xa1, 0x30, 0x7a, 0x11, 0x6e, 0x12, 0x75, 0xca, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, + 0xf1, 0x60, 0x03, 0x12, 0x43, 0xd4, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x6f, 0xd2, 0xaf, 0x02, 0x30, + 0x00, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 0x25, 0x87, 0x03, 0xa9, 0xd5, 0x87, 0xd2, 0x93, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x78, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xc2, 0x93, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, - 0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7e, 0x4b, 0x7e, 0x08, - 0x01, 0x59, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7e, 0x4b, - 0x7e, 0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, - 0x7e, 0x4b, 0x75, 0x57, 0x20, 0x75, 0x56, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, - 0x55, 0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, - 0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, + 0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7c, 0x30, 0x7e, 0x08, + 0x01, 0x6f, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7c, 0x30, + 0x7e, 0x08, 0x00, 0x6f, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, + 0x7c, 0x30, 0x75, 0x6d, 0x20, 0x75, 0x6c, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x6a, 0x58, 0x75, + 0x6b, 0x08, 0x75, 0x67, 0x08, 0x75, 0x69, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, + 0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x58, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 0xb8, 0x7f, 0x75, 0xb3, 0x07, 0x75, 0xb2, 0x07, 0xd2, 0xa9, 0x22, 0xd2, 0x92, 0xe4, 0xd5, 0xe0, - 0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, - 0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x72, 0x0b, 0x20, - 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, + 0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2f, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, + 0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x7e, 0x0b, 0x20, + 0xbe, 0x21, 0x2f, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 0x54, 0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, - 0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 0xbf, - 0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, - 0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, - 0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, - 0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, - 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0x99, 0x89, 0x24, 0x41, 0xa9, 0x41, 0xc6, 0x41, 0xe3, 0x42, - 0x00, 0x42, 0x1d, 0x42, 0x3a, 0x42, 0x57, 0x42, 0x74, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 0x7e, - 0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 0x01, - 0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, - 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, - 0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, - 0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x22, - 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, - 0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 0xc2, - 0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x6d, - 0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x0d, - 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 0x07, - 0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 0x21, - 0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 0x7a, - 0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, - 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 0x97, - 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0x9c, 0x89, 0x24, 0x42, 0xac, 0x42, 0xc3, - 0x42, 0xda, 0x42, 0xf1, 0x43, 0x08, 0x43, 0x1f, 0x43, 0x36, 0x43, 0x4d, 0x30, 0x40, 0x07, 0x20, - 0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 0x02, - 0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, - 0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 0x04, - 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, - 0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 0x53, - 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, - 0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, - 0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 0xc2, - 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x0c, - 0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 0x07, - 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 0x80, - 0x02, 0xd2, 0x2f, 0x22, 0x43, 0xcc, 0x43, 0x79, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, - 0x5b, 0x49, 0x55, 0x43, 0x64, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x43, 0xd7, 0x7e, - 0x04, 0x05, 0xcd, 0x7a, 0x07, 0x01, 0xc1, 0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x01, 0xcd, 0x7a, - 0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x04, 0x76, 0xbd, 0x7a, 0x05, 0x4b, 0x75, 0xf1, - 0x01, 0x75, 0xe1, 0x1f, 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, - 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, - 0x41, 0x8e, 0x0b, 0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, - 0x43, 0xd7, 0xd2, 0x92, 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, - 0x53, 0xc0, 0x03, 0x7e, 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, - 0xf2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, - 0xe1, 0x10, 0xa5, 0xd8, 0xe1, 0x22, 0x12, 0x44, 0x76, 0x12, 0x44, 0x8c, 0x12, 0x45, 0x27, 0x12, - 0x45, 0x57, 0x12, 0x49, 0x0f, 0x12, 0x44, 0xd8, 0x80, 0xec, 0xca, 0x09, 0x12, 0x44, 0x58, 0x10, - 0x01, 0x12, 0xd5, 0x51, 0x1e, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, - 0xf5, 0x51, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, - 0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, - 0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, - 0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, - 0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, - 0xf1, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xff, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, - 0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, - 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, - 0x04, 0x0a, 0x32, 0x09, 0x53, 0x6a, 0x93, 0x5e, 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, - 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, - 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, - 0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, - 0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, - 0x21, 0xca, 0x19, 0x49, 0x22, 0x45, 0x17, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, - 0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x4a, 0x98, 0x4d, 0xcd, 0x51, 0x02, 0x54, 0x37, 0x57, - 0x6c, 0x5a, 0xa1, 0x5d, 0xd6, 0x61, 0x0b, 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, - 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x44, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, - 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x6a, 0xac, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, - 0xb2, 0x6a, 0x93, 0xf4, 0x52, 0x24, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, - 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x74, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, - 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x7f, 0x89, 0x24, 0x45, - 0x8f, 0x45, 0xff, 0x46, 0x6f, 0x46, 0xdf, 0x47, 0x4f, 0x47, 0xbf, 0x48, 0x2f, 0x48, 0x9f, 0x7e, - 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4d, - 0x96, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x18, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xb9, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x50, - 0xcb, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x19, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xba, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x54, - 0x00, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1a, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xbb, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x57, - 0x35, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbc, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1b, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xbc, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5a, - 0x6a, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x91, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xbd, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1c, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xbd, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, - 0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbe, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1d, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xbe, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x60, - 0xd4, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x95, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1e, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xbf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, - 0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x64, - 0x09, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, - 0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x2e, - 0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, - 0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1f, 0x6c, 0x00, - 0x7a, 0x03, 0x01, 0xc0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0xc2, - 0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, - 0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x2f, 0x12, 0x7e, - 0x30, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, - 0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x7e, 0x30, 0x7e, - 0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xd8, 0x20, 0x70, 0x5a, - 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xf0, 0x20, 0x71, 0x4b, 0xa5, - 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x08, 0xa5, 0x0a, 0x09, 0xb1, 0x00, - 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x20, 0x20, 0x72, 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, - 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x38, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, - 0x4a, 0x50, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x68, 0xa5, 0x0a, - 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x80, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, - 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, - 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 0x2f, 0x80, 0x12, 0x7e, 0x30, 0x54, 0x3e, - 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, - 0x75, 0x2f, 0x81, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, - 0x66, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x82, 0x12, 0x7e, 0x30, 0x54, 0x3e, - 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, - 0x75, 0x2f, 0x83, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, - 0x66, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x84, 0x12, 0x7e, 0x30, 0x54, 0x3e, - 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, - 0x75, 0x2f, 0x85, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, - 0x67, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x86, 0x12, 0x7e, 0x30, 0x54, 0x3e, - 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, - 0x75, 0x2f, 0x87, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, - 0x67, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x10, 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, - 0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, - 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, - 0x03, 0x12, 0x4d, 0x96, 0x30, 0x30, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, - 0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, - 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, - 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, - 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x60, 0xc4, 0x22, 0xc2, - 0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, - 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, - 0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, - 0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, - 0x59, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, - 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x0d, 0xcd, - 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x09, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, - 0x59, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4b, 0x0b, 0x22, 0xd2, 0x08, 0x7e, - 0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x7e, - 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, - 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, - 0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, - 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, - 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, - 0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, - 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, - 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, - 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, - 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, - 0x01, 0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, - 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, - 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, - 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, - 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, - 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, - 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, - 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, - 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, - 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, - 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, - 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, - 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4c, 0x6f, 0x75, - 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, - 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, - 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4c, 0x6f, 0xda, 0xb8, 0x02, - 0x4d, 0x96, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, - 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, - 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, - 0x50, 0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xac, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, - 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, - 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, - 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, - 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4c, 0xc3, 0x75, - 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x09, 0x01, - 0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x81, - 0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, - 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x50, 0xcb, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, - 0x09, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, - 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, - 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, - 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, - 0x10, 0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, - 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, - 0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, - 0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, - 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, - 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, - 0x30, 0x9e, 0x44, 0x11, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x0d, 0xcd, 0x7d, 0x24, - 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4e, - 0x40, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, - 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, - 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, - 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, - 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, - 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, - 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, - 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, - 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, - 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, - 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, - 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, - 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, - 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, - 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, - 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, - 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, - 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, - 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, - 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, - 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, - 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, - 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, - 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, - 0xe7, 0x02, 0x4f, 0xa4, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, - 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, - 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, - 0x4f, 0xa4, 0xda, 0xb8, 0x02, 0x50, 0xcb, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, - 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, - 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, - 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x12, 0x42, 0xc3, 0x02, 0x65, 0x9c, - 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, - 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, - 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, - 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, - 0x22, 0x02, 0x4f, 0xf8, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, - 0x30, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, - 0x7e, 0x30, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, - 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x54, 0x00, 0x30, 0x32, - 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, - 0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, - 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xcc, - 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, - 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x62, 0xc4, 0x22, 0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, - 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, - 0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, - 0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, - 0x42, 0xbe, 0x44, 0x15, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, - 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, - 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x15, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, - 0x34, 0x11, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5d, 0x12, 0x68, 0x34, 0xbe, 0x25, - 0x20, 0x78, 0x03, 0x02, 0x51, 0x75, 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, - 0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, - 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, - 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, - 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, - 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, - 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, - 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, - 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, - 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, - 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, - 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, - 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, - 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, - 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, - 0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, - 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, - 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, - 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, - 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, - 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, - 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, - 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, - 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, - 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x52, 0xd9, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, - 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, - 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, - 0x68, 0x07, 0xca, 0xb8, 0x12, 0x52, 0xd9, 0xda, 0xb8, 0x02, 0x54, 0x00, 0x09, 0xb1, 0x00, 0x18, - 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, - 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, - 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, - 0x42, 0xda, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, - 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, - 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, - 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, - 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x53, 0x2d, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, - 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, - 0x22, 0x75, 0x2f, 0xa3, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, + 0x74, 0x07, 0xa9, 0x20, 0x30, 0x0b, 0xa9, 0x35, 0x30, 0x05, 0xbe, 0x20, 0x01, 0x28, 0x02, 0x74, + 0x0f, 0x19, 0xb0, 0x00, 0x04, 0xa9, 0x33, 0x30, 0x18, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, + 0x28, 0xa9, 0x20, 0x30, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 0x03, 0x19, 0xb0, 0x00, + 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 0x10, 0x22, 0x7e, 0x04, + 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 0x10, 0x54, 0x08, 0x19, + 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, + 0x22, 0x41, 0xa5, 0x89, 0x24, 0x41, 0xb5, 0x41, 0xd4, 0x41, 0xf3, 0x42, 0x12, 0x42, 0x31, 0x42, + 0x50, 0x42, 0x6f, 0x42, 0x8e, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x20, 0xc2, 0x08, 0x7e, 0x04, 0x09, + 0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x8f, 0x7a, + 0x07, 0x01, 0x9f, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x21, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, + 0x7a, 0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x91, 0x7a, 0x07, + 0x01, 0xa1, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x22, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, + 0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x93, 0x7a, 0x07, 0x01, + 0xa3, 0x22, 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x23, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 0x07, + 0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x95, 0x7a, 0x07, 0x01, 0xa5, + 0x22, 0xc2, 0x14, 0xc2, 0x1c, 0xc2, 0x24, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, + 0x77, 0x7a, 0x07, 0x01, 0x87, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x97, 0x7a, 0x07, 0x01, 0xa7, 0x22, + 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x25, 0xc2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 0x07, 0x01, 0x79, + 0x7a, 0x07, 0x01, 0x89, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x99, 0x7a, 0x07, 0x01, 0xa9, 0x22, 0xc2, + 0x16, 0xc2, 0x1e, 0xc2, 0x26, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, + 0x07, 0x01, 0x8b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9b, 0x7a, 0x07, 0x01, 0xab, 0x22, 0xc2, 0x17, + 0xc2, 0x1f, 0xc2, 0x27, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, + 0x01, 0x8d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9d, 0x7a, 0x07, 0x01, 0xad, 0x22, 0x7c, 0xb2, 0x23, + 0x0a, 0x2b, 0x49, 0x22, 0x42, 0xb8, 0x89, 0x24, 0x42, 0xc8, 0x42, 0xe9, 0x43, 0x0a, 0x43, 0x2b, + 0x43, 0x4c, 0x43, 0x6d, 0x43, 0x8e, 0x43, 0xaf, 0x30, 0x50, 0x07, 0x20, 0x68, 0x04, 0xc2, 0x28, + 0x80, 0x16, 0x30, 0x40, 0x07, 0x20, 0x60, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, + 0x58, 0x04, 0xc2, 0x28, 0x80, 0x02, 0xd2, 0x28, 0x22, 0x30, 0x51, 0x07, 0x20, 0x69, 0x04, 0xc2, + 0x29, 0x80, 0x16, 0x30, 0x41, 0x07, 0x20, 0x61, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, + 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x52, 0x07, 0x20, 0x6a, 0x04, + 0xc2, 0x2a, 0x80, 0x16, 0x30, 0x42, 0x07, 0x20, 0x62, 0x04, 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, + 0x07, 0x20, 0x5a, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 0x22, 0x30, 0x53, 0x07, 0x20, 0x6b, + 0x04, 0xc2, 0x2b, 0x80, 0x16, 0x30, 0x43, 0x07, 0x20, 0x63, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, + 0x4b, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x54, 0x07, 0x20, + 0x6c, 0x04, 0xc2, 0x2c, 0x80, 0x16, 0x30, 0x44, 0x07, 0x20, 0x64, 0x04, 0xc2, 0x2c, 0x80, 0x0c, + 0x30, 0x4c, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 0x55, 0x07, + 0x20, 0x6d, 0x04, 0xc2, 0x2d, 0x80, 0x16, 0x30, 0x45, 0x07, 0x20, 0x65, 0x04, 0xc2, 0x2d, 0x80, + 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x56, + 0x07, 0x20, 0x6e, 0x04, 0xc2, 0x2e, 0x80, 0x16, 0x30, 0x46, 0x07, 0x20, 0x66, 0x04, 0xc2, 0x2e, + 0x80, 0x0c, 0x30, 0x4e, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, + 0x57, 0x07, 0x20, 0x6f, 0x04, 0xc2, 0x2f, 0x80, 0x16, 0x30, 0x47, 0x07, 0x20, 0x67, 0x04, 0xc2, + 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x02, 0xd2, 0x2f, 0x22, + 0x44, 0x38, 0x43, 0xe5, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 0x5b, 0x49, 0x55, 0x43, + 0xd0, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x44, 0x43, 0x7e, 0x04, 0x05, 0xe3, 0x7a, + 0x07, 0x01, 0xd7, 0x7a, 0x07, 0x01, 0xd9, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdd, 0x7a, + 0x07, 0x01, 0xdf, 0x7e, 0x04, 0x74, 0xad, 0x7a, 0x05, 0x61, 0x75, 0xf1, 0x01, 0x75, 0xe1, 0x1f, + 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 0x75, 0xe4, 0x04, 0x75, + 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x9a, 0x0b, 0x20, + 0xbe, 0x21, 0x2f, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 0x44, 0x43, 0xd2, 0x92, + 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 0x53, 0xc0, 0x03, 0x7e, + 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 0xf2, 0x54, 0x7f, 0x44, + 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 0xe1, 0x10, 0xa5, 0xd8, + 0xe1, 0x22, 0xca, 0x09, 0x12, 0x30, 0x20, 0x10, 0x01, 0x12, 0xd5, 0x67, 0x1e, 0x63, 0x69, 0x01, + 0x7e, 0x00, 0x6a, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0xf5, 0x67, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, + 0x69, 0x00, 0x85, 0x6a, 0x67, 0xd2, 0x02, 0x74, 0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, + 0x7e, 0x00, 0x6c, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, + 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, + 0x75, 0x31, 0x89, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, + 0x03, 0x02, 0x45, 0x4f, 0x20, 0x78, 0x5a, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, + 0x02, 0x45, 0x67, 0x20, 0x79, 0x4b, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, + 0x45, 0x7f, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0x97, 0x20, 0x7a, + 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xaf, 0xa5, 0x0a, 0x09, + 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xc7, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, + 0xe0, 0x03, 0x02, 0x45, 0xdf, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, + 0xf7, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, + 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, + 0x31, 0x80, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, + 0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x81, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, + 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, + 0x31, 0x82, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, + 0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x83, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, + 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, + 0x31, 0x84, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, + 0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x85, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, + 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, + 0x31, 0x86, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, + 0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x87, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, + 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x10, + 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x75, 0x31, 0xa0, 0x12, 0x7c, 0x15, 0x7e, + 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, + 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x49, 0x30, 0x20, 0xe6, 0x03, 0xd2, 0x08, + 0x22, 0x30, 0x30, 0x49, 0xd2, 0x70, 0x7e, 0x37, 0x01, 0x8f, 0x7e, 0x27, 0x01, 0xaf, 0x9d, 0x32, + 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 0x37, 0x01, 0x8f, 0x7e, 0x37, + 0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x6f, + 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, + 0x70, 0xc4, 0x22, 0xc2, 0x70, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, + 0x8f, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xaf, 0x28, 0x04, 0x7e, 0x27, 0x01, + 0xaf, 0x7e, 0x37, 0x01, 0x8f, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, + 0x37, 0x01, 0x8f, 0x7e, 0x37, 0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, + 0x13, 0x7a, 0x47, 0x01, 0x6f, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, + 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x0d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x09, 0xe3, 0x7d, 0x24, 0x2d, + 0x43, 0x7a, 0x47, 0x01, 0x6f, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x46, 0x7f, + 0x22, 0xd2, 0x08, 0x7e, 0x04, 0x09, 0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x75, + 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, + 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, + 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xbf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, + 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, + 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, + 0x01, 0xdf, 0x7e, 0x24, 0x00, 0x00, 0x2e, 0x27, 0x01, 0xbf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, + 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, + 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, + 0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, + 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, + 0x00, 0x00, 0x2e, 0x67, 0x01, 0xbf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, + 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, + 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, + 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, + 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, + 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, + 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, + 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, + 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, + 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, + 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, + 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, + 0x02, 0x47, 0xe3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, + 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, + 0xd2, 0x10, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x47, + 0xe3, 0xda, 0xb8, 0x02, 0x49, 0x30, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, + 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, + 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, + 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, + 0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x60, 0x80, 0x02, + 0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0x12, + 0x42, 0xc8, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, + 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, + 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, + 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, + 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x48, 0x35, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, + 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x09, 0x01, 0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, + 0x22, 0x75, 0x31, 0xa1, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x81, 0x00, 0x80, 0x06, 0x20, 0x29, 0x03, + 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, + 0x12, 0x4c, 0x88, 0x20, 0xe6, 0x03, 0xd2, 0x09, 0x22, 0x30, 0x31, 0x49, 0xd2, 0x71, 0x7e, 0x37, + 0x01, 0x91, 0x7e, 0x27, 0x01, 0xb1, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4a, 0x7a, + 0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, + 0x11, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, + 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x71, 0xc4, 0x22, 0xc2, 0x71, 0x2d, 0x23, 0x68, + 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, + 0x27, 0x01, 0xb1, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb1, 0x7e, 0x37, 0x01, 0x91, 0x9d, 0x32, 0x7d, + 0x02, 0x2e, 0x05, 0x4a, 0x7a, 0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, + 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, + 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, + 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x11, 0xe3, 0x9d, 0x24, 0x12, 0x65, + 0x2b, 0x7e, 0x34, 0x0d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x71, 0x12, 0x65, 0x2b, + 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x49, 0xd7, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 0x7a, + 0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, + 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, + 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc1, + 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, + 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, + 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, + 0x01, 0xc1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, + 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, + 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, + 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xc1, 0x9e, 0x24, + 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, + 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, + 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, + 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, + 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, + 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, + 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, + 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, + 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, + 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, + 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, + 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4b, 0x3b, 0x75, 0x31, 0x99, 0x12, 0x7c, + 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, + 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, + 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4b, 0x3b, 0xda, 0xb8, 0x02, 0x4c, 0x88, 0x09, 0xb1, + 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, + 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, + 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, + 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 0x5e, + 0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, + 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x12, 0x42, 0xe9, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, + 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, + 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, + 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, + 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4b, + 0x8d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, + 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x31, 0xa2, 0x12, 0x7c, 0x15, 0x7e, + 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, + 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x4f, 0xe0, 0x20, 0xe6, 0x03, 0xd2, 0x0a, + 0x22, 0x30, 0x32, 0x49, 0xd2, 0x72, 0x7e, 0x37, 0x01, 0x93, 0x7e, 0x27, 0x01, 0xb3, 0x9d, 0x32, + 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 0x37, 0x01, 0x93, 0x7e, 0x37, + 0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x73, + 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, + 0x72, 0xc4, 0x22, 0xc2, 0x72, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, + 0x93, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb3, 0x28, 0x04, 0x7e, 0x27, 0x01, + 0xb3, 0x7e, 0x37, 0x01, 0x93, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, + 0x37, 0x01, 0x93, 0x7e, 0x37, 0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, + 0x13, 0x7a, 0x47, 0x01, 0x73, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, + 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x15, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x11, 0xe3, 0x7d, 0x24, 0x2d, + 0x43, 0x7a, 0x47, 0x01, 0x73, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4d, 0x2f, + 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x75, + 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, + 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, + 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc3, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, + 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, + 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, + 0x01, 0xdf, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xc3, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, + 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, + 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, + 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, + 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, + 0x02, 0x00, 0x2e, 0x67, 0x01, 0xc3, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, + 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, + 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, + 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, + 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, + 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, + 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, + 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, + 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, + 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, + 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, + 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, + 0x02, 0x4e, 0x93, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, + 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, + 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4e, + 0x93, 0xda, 0xb8, 0x02, 0x4f, 0xe0, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, + 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, + 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, + 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, + 0x6a, 0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, + 0xc2, 0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x12, + 0x43, 0x0a, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, + 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, + 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, + 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, + 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4e, 0xe5, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, + 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, + 0x22, 0x75, 0x31, 0xa3, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, - 0x12, 0x57, 0x35, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, - 0x63, 0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, - 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, - 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x7e, - 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, - 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, - 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, - 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, - 0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, - 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, - 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x19, 0xcd, 0x9d, - 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x15, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, - 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x54, 0xaa, 0x22, 0xd2, 0x0b, 0x7e, 0x04, - 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, - 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, - 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, - 0x27, 0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, - 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, - 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, - 0x00, 0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, - 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, - 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, - 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, - 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, - 0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, - 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, - 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, - 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, - 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, - 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, - 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, - 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, - 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, - 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, - 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, - 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, - 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x56, 0x0e, 0x75, 0x2f, - 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, - 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, - 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x56, 0x0e, 0xda, 0xb8, 0x02, 0x57, - 0x35, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, - 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, - 0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, - 0x80, 0x02, 0xc2, 0x53, 0x12, 0x42, 0xf1, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, - 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, - 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, - 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, - 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x56, 0x62, 0x75, 0x2f, - 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0c, 0x01, 0x22, - 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x84, 0x00, - 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, - 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5a, 0x6a, 0x30, 0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, - 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, - 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, - 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, - 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, - 0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, - 0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, - 0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, - 0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, - 0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, - 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, - 0x9e, 0x44, 0x1d, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x19, 0xcd, 0x7d, 0x24, 0x2d, - 0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0xdf, - 0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, - 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, - 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, - 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, - 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, - 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, - 0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, - 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, - 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, + 0x12, 0x53, 0x38, 0x20, 0xe6, 0x03, 0xd2, 0x0b, 0x22, 0x30, 0x33, 0x49, 0xd2, 0x73, 0x7e, 0x37, + 0x01, 0x95, 0x7e, 0x27, 0x01, 0xb5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4e, 0x7a, + 0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, + 0x19, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, + 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x73, 0xc4, 0x22, 0xc2, 0x73, 0x2d, 0x23, 0x68, + 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, + 0x27, 0x01, 0xb5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb5, 0x7e, 0x37, 0x01, 0x95, 0x9d, 0x32, 0x7d, + 0x02, 0x2e, 0x05, 0x4e, 0x7a, 0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, + 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, + 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, + 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x19, 0xe3, 0x9d, 0x24, 0x12, 0x65, + 0x2b, 0x7e, 0x34, 0x15, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x75, 0x12, 0x65, 0x2b, + 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x50, 0x87, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, + 0x07, 0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, + 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, + 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc5, + 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, + 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, + 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x03, 0x00, 0x2e, 0x27, + 0x01, 0xc5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, + 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, + 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, + 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 0xc5, 0x9e, 0x24, + 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, + 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, + 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, + 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, + 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, + 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, + 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, + 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, + 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, + 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, + 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, + 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x51, 0xeb, 0x75, 0x31, 0x99, 0x12, 0x7c, + 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, + 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, + 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x51, 0xeb, 0xda, 0xb8, 0x02, 0x53, 0x38, 0x09, 0xb1, + 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, + 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, + 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, + 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, + 0x50, 0x20, 0x68, 0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, + 0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0x12, 0x43, 0x2b, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, + 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, + 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, + 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, + 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x52, + 0x3d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, + 0x0c, 0x01, 0x22, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x31, 0xa4, 0x12, 0x7c, 0x15, 0x7e, + 0x14, 0x84, 0x00, 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, + 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x56, 0x90, 0x20, 0xe6, 0x03, 0xd2, 0x0c, + 0x22, 0x30, 0x34, 0x49, 0xd2, 0x74, 0x7e, 0x37, 0x01, 0x97, 0x7e, 0x27, 0x01, 0xb7, 0x9d, 0x32, + 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 0x37, 0x01, 0x97, 0x7e, 0x37, + 0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x77, + 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, + 0x74, 0xc4, 0x22, 0xc2, 0x74, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, + 0x97, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb7, 0x28, 0x04, 0x7e, 0x27, 0x01, + 0xb7, 0x7e, 0x37, 0x01, 0x97, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, + 0x37, 0x01, 0x97, 0x7e, 0x37, 0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, + 0x13, 0x7a, 0x47, 0x01, 0x77, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, + 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x1d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x19, 0xe3, 0x7d, 0x24, 0x2d, + 0x43, 0x7a, 0x47, 0x01, 0x77, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x53, 0xdf, + 0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 0x77, 0x7a, 0x07, 0x01, 0x87, 0x75, + 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, + 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, + 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, + 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, + 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, + 0x01, 0xdf, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xc7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, + 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, + 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, - 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, - 0x04, 0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, - 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, - 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, + 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, + 0x04, 0x00, 0x2e, 0x67, 0x01, 0xc7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, + 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, + 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, - 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, - 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, - 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, - 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, - 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, - 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, - 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, + 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, + 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, + 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, + 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, + 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, + 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, - 0x02, 0x59, 0x43, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, + 0x02, 0x55, 0x43, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, - 0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x59, - 0x43, 0xda, 0xb8, 0x02, 0x5a, 0x6a, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, - 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, - 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, - 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x08, 0x02, 0x65, 0x9c, 0x75, - 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, - 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, - 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, - 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, - 0x02, 0x59, 0x97, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, - 0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x7e, - 0x30, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, - 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x9f, 0x30, 0x35, 0x06, - 0x20, 0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, - 0x27, 0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, - 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xcc, 0x38, - 0x68, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, - 0x30, 0x12, 0x68, 0x34, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, - 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, - 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, - 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, - 0xbe, 0x44, 0x21, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, - 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, - 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x21, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, - 0x1d, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, - 0x78, 0x03, 0x02, 0x5b, 0x14, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, - 0x7a, 0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, - 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, - 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, - 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, - 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, - 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, - 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, - 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, - 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, - 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, - 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, - 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, - 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, - 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, - 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, - 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, - 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, - 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, - 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, - 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, - 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, - 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, - 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, - 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5c, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, + 0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x55, + 0x43, 0xda, 0xb8, 0x02, 0x56, 0x90, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, + 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, + 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, + 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, + 0x6c, 0x80, 0x02, 0xc2, 0x6c, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, + 0xc2, 0x64, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x12, + 0x43, 0x4c, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, + 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, + 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, + 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, + 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x55, 0x95, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, + 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, + 0x22, 0x75, 0x31, 0xa5, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, + 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, + 0x12, 0x59, 0xe8, 0x20, 0xe6, 0x03, 0xd2, 0x0d, 0x22, 0x30, 0x35, 0x49, 0xd2, 0x75, 0x7e, 0x37, + 0x01, 0x99, 0x7e, 0x27, 0x01, 0xb9, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x52, 0x7a, + 0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, + 0x21, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, + 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x75, 0xc4, 0x22, 0xc2, 0x75, 0x2d, 0x23, 0x68, + 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, + 0x27, 0x01, 0xb9, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb9, 0x7e, 0x37, 0x01, 0x99, 0x9d, 0x32, 0x7d, + 0x02, 0x2e, 0x05, 0x52, 0x7a, 0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, + 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, + 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, + 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x21, 0xe3, 0x9d, 0x24, 0x12, 0x65, + 0x2b, 0x7e, 0x34, 0x1d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x79, 0x12, 0x65, 0x2b, + 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0x37, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, + 0x07, 0x01, 0x79, 0x7a, 0x07, 0x01, 0x89, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, + 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, + 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc9, + 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, + 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, + 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, + 0x01, 0xc9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, + 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, - 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, - 0x07, 0xca, 0xb8, 0x12, 0x5c, 0x78, 0xda, 0xb8, 0x02, 0x5d, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, - 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, - 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, - 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, - 0x1f, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, - 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, - 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, - 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, - 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, - 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, - 0x75, 0x2f, 0xa6, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, - 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, - 0x60, 0xd4, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, - 0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, - 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, - 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, - 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, - 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, - 0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, - 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, - 0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, - 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, - 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x25, 0xcd, 0x9d, 0x24, - 0x12, 0x68, 0x34, 0x7e, 0x34, 0x21, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, - 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5e, 0x49, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, - 0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, - 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, - 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, - 0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, - 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, - 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, - 0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, - 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, - 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, - 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, - 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, - 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, - 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, - 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, - 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, - 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, - 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, - 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, - 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, - 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, - 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, - 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, - 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, - 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0xad, 0x75, 0x2f, 0x99, - 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, - 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, - 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0xad, 0xda, 0xb8, 0x02, 0x60, 0xd4, - 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, - 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, - 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, - 0x02, 0xc2, 0x56, 0x12, 0x43, 0x36, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, - 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, - 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, - 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, - 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x60, 0x01, 0x75, 0x2f, 0x95, - 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, - 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x87, 0x00, 0x80, - 0x06, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, - 0xda, 0xb8, 0x68, 0x03, 0x12, 0x64, 0x09, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, - 0x30, 0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, - 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, - 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, - 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x67, - 0xc4, 0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, - 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, - 0x7e, 0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, - 0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x13, - 0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, - 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, - 0x44, 0x29, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x25, 0xcd, 0x7d, 0x24, 0x2d, 0x43, - 0x7a, 0x47, 0x01, 0x67, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x61, 0x7e, 0x22, - 0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, - 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, - 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, - 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, - 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, - 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, - 0xc9, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, - 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, - 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, - 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, - 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x07, - 0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, - 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, - 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, - 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, - 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, - 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, - 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, - 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, - 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, - 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, - 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, - 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, - 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, - 0x62, 0xe2, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, - 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, - 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x62, 0xe2, - 0xda, 0xb8, 0x02, 0x64, 0x09, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, - 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, - 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, - 0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 0x43, 0x4d, 0x02, 0x65, 0x9c, 0x75, 0x2f, - 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, - 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, - 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, - 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, - 0x63, 0x36, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, - 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, - 0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, - 0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, - 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, - 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, - 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, - 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, - 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, - 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, - 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, - 0x53, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, - 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, - 0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, - 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, - 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, - 0x02, 0xc2, 0x55, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, - 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, - 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 0xc2, 0x56, 0x02, 0x65, 0x88, 0x7c, - 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, - 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, - 0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x65, 0x88, 0x54, 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, - 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0x22, 0xca, 0x19, 0x5e, 0x20, - 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, - 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 0x64, 0x00, 0x02, 0x02, 0x65, 0xe7, 0xca, - 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, - 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, - 0x7e, 0x64, 0x00, 0x03, 0x02, 0x65, 0xe7, 0xd2, 0x04, 0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, - 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7e, 0x79, 0xa0, - 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, - 0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, - 0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x7e, 0x30, 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, - 0x01, 0xcd, 0x80, 0xd7, 0x4d, 0x42, 0x4a, 0xae, 0x4b, 0xa8, 0x4d, 0x7b, 0x49, 0x4f, 0x49, 0x4f, - 0x4c, 0xa7, 0x49, 0x4f, 0x4d, 0xbf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x4d, 0xc6, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x50, 0x77, 0x4d, 0xe3, 0x4e, 0xdd, 0x50, 0xb0, 0x49, 0x4f, 0x49, 0x4f, - 0x4f, 0xdc, 0x49, 0x4f, 0x50, 0xf4, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x50, 0xfb, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x53, 0xac, 0x51, 0x18, 0x52, 0x12, 0x53, 0xe5, 0x49, 0x4f, 0x49, 0x4f, - 0x53, 0x11, 0x49, 0x4f, 0x54, 0x29, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x54, 0x30, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x56, 0xe1, 0x54, 0x4d, 0x55, 0x47, 0x57, 0x1a, 0x49, 0x4f, 0x49, 0x4f, - 0x56, 0x46, 0x49, 0x4f, 0x57, 0x5e, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x57, 0x65, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x16, 0x57, 0x82, 0x58, 0x7c, 0x5a, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x59, 0x7b, 0x49, 0x4f, 0x5a, 0x93, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x9a, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x5d, 0x4b, 0x5a, 0xb7, 0x5b, 0xb1, 0x5d, 0x84, 0x49, 0x4f, 0x49, 0x4f, - 0x5c, 0xb0, 0x49, 0x4f, 0x5d, 0xc8, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x5d, 0xcf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x60, 0x80, 0x5d, 0xec, 0x5e, 0xe6, 0x60, 0xb9, 0x49, 0x4f, 0x49, 0x4f, - 0x5f, 0xe5, 0x49, 0x4f, 0x60, 0xfd, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x61, 0x04, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x63, 0xb5, 0x61, 0x21, 0x62, 0x1b, 0x63, 0xee, 0x49, 0x4f, 0x49, 0x4f, - 0x63, 0x1a, 0x49, 0x4f, 0x64, 0x32, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x64, 0x39, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, - 0x49, 0x4f, 0x49, 0x4f, 0xca, 0x29, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, - 0xa4, 0x2e, 0x54, 0x68, 0x51, 0x89, 0x54, 0x7e, 0x39, 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, - 0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, - 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, - 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, - 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, + 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xc9, 0x9e, 0x24, + 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, + 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, + 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, + 0x0f, 0x23, 0x23, 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, + 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, + 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, + 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, + 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, + 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, + 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, + 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, + 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x58, 0x9b, 0x75, 0x31, 0x99, 0x12, 0x7c, + 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, + 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, + 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x58, 0x9b, 0xda, 0xb8, 0x02, 0x59, 0xe8, 0x09, 0xb1, + 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, + 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, + 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, + 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, + 0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, + 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0x12, 0x43, 0x6d, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, + 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, + 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, + 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, + 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x58, + 0xed, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, + 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x75, 0x31, 0xa6, 0x12, 0x7c, 0x15, 0x7e, + 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, + 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x40, 0x20, 0xe6, 0x03, 0xd2, 0x0e, + 0x22, 0x30, 0x36, 0x49, 0xd2, 0x76, 0x7e, 0x37, 0x01, 0x9b, 0x7e, 0x27, 0x01, 0xbb, 0x9d, 0x32, + 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 0x37, 0x01, 0x9b, 0x7e, 0x37, + 0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7b, + 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, + 0x76, 0xc4, 0x22, 0xc2, 0x76, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, + 0x9b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xbb, 0x28, 0x04, 0x7e, 0x27, 0x01, + 0xbb, 0x7e, 0x37, 0x01, 0x9b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, + 0x37, 0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, + 0x13, 0x7a, 0x47, 0x01, 0x7b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, + 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x25, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x21, 0xe3, 0x7d, 0x24, 0x2d, + 0x43, 0x7a, 0x47, 0x01, 0x7b, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5a, 0x8f, + 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 0x01, 0x8b, 0x75, + 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, + 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, + 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcb, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, + 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, + 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, + 0x01, 0xdf, 0x7e, 0x24, 0x06, 0x00, 0x2e, 0x27, 0x01, 0xcb, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, + 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, + 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, + 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, + 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, + 0x06, 0x00, 0x2e, 0x67, 0x01, 0xcb, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, + 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, + 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, + 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, + 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, + 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, + 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, + 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, + 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, + 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, + 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, + 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, + 0x02, 0x5b, 0xf3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, + 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, + 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5b, + 0xf3, 0xda, 0xb8, 0x02, 0x5d, 0x40, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, + 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, + 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, + 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, + 0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, + 0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x12, + 0x43, 0x8e, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, + 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, + 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, + 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, + 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0x45, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, + 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 0x2f, 0x03, 0xd2, 0x0f, + 0x22, 0x75, 0x31, 0xa7, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x87, 0x00, 0x80, 0x06, 0x20, 0x2f, 0x03, + 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, + 0x12, 0x60, 0x98, 0x20, 0xe6, 0x03, 0xd2, 0x0f, 0x22, 0x30, 0x37, 0x49, 0xd2, 0x77, 0x7e, 0x37, + 0x01, 0x9d, 0x7e, 0x27, 0x01, 0xbd, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x56, 0x7a, + 0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, + 0x29, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, + 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x77, 0xc4, 0x22, 0xc2, 0x77, 0x2d, 0x23, 0x68, + 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, + 0x27, 0x01, 0xbd, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xbd, 0x7e, 0x37, 0x01, 0x9d, 0x9d, 0x32, 0x7d, + 0x02, 0x2e, 0x05, 0x56, 0x7a, 0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, + 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, + 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, + 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x29, 0xe3, 0x9d, 0x24, 0x12, 0x65, + 0x2b, 0x7e, 0x34, 0x25, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x7d, 0x12, 0x65, 0x2b, + 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5d, 0xe7, 0x22, 0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, + 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, + 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, + 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcd, + 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, + 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, + 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, + 0x01, 0xcd, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, + 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, + 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, + 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, + 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x07, 0x00, 0x2e, 0x67, 0x01, 0xcd, 0x9e, 0x24, + 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, + 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, + 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, + 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, + 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, + 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, + 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, + 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, + 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, + 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, + 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, + 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, + 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0x4b, 0x75, 0x31, 0x99, 0x12, 0x7c, + 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, + 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, + 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0x4b, 0xda, 0xb8, 0x02, 0x60, 0x98, 0x09, 0xb1, + 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, + 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, + 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, + 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 0xc2, 0x6f, 0xa5, 0xfd, 0x5e, + 0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, + 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x12, 0x43, 0xaf, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, + 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, + 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, + 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, + 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5f, + 0x9d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x7c, + 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, + 0x68, 0x04, 0xd2, 0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, + 0x60, 0x80, 0x02, 0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, + 0xc2, 0x58, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, + 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, + 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, + 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, + 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6a, + 0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 0xc2, + 0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x02, 0x62, + 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, + 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, + 0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5b, + 0x80, 0x02, 0xc2, 0x5b, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, + 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6c, 0x80, 0x02, 0xc2, 0x6c, + 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 0xc2, 0x64, 0xa5, 0xfd, 0x5e, + 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, + 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, + 0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, + 0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, + 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, + 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, + 0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, + 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, + 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, + 0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, + 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x02, 0x62, 0x7f, 0x54, + 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, + 0x7c, 0x15, 0x22, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xe3, 0xca, 0x79, + 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, + 0x64, 0x00, 0x02, 0x02, 0x62, 0xde, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, + 0xe3, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, + 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 0x7e, 0x64, 0x00, 0x03, 0x02, 0x62, 0xde, 0xd2, 0x04, + 0x7e, 0x27, 0x01, 0xe1, 0x2d, 0x26, 0xbe, 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xdf, + 0x7e, 0x44, 0x05, 0xe3, 0x7e, 0x79, 0xa0, 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, + 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 0x01, 0xe1, 0x7e, 0x25, 0x46, 0x2d, 0x26, 0x7a, 0x25, + 0x46, 0x7a, 0x07, 0x01, 0xdf, 0xda, 0x19, 0xc2, 0xd7, 0x22, 0x75, 0x31, 0x9a, 0x12, 0x7c, 0x15, + 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd7, 0x48, 0xb6, 0x46, 0x25, 0x47, + 0x1c, 0x49, 0x15, 0x44, 0xc6, 0x44, 0xc6, 0x48, 0x1b, 0x44, 0xc6, 0x49, 0x59, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x49, 0x60, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0x0e, 0x49, 0x7d, 0x4a, + 0x74, 0x4c, 0x6d, 0x44, 0xc6, 0x44, 0xc6, 0x4b, 0x73, 0x44, 0xc6, 0x4c, 0xb1, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0xb8, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4f, 0x66, 0x4c, 0xd5, 0x4d, + 0xcc, 0x4f, 0xc5, 0x44, 0xc6, 0x44, 0xc6, 0x4e, 0xcb, 0x44, 0xc6, 0x50, 0x09, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x50, 0x10, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0xbe, 0x50, 0x2d, 0x51, + 0x24, 0x53, 0x1d, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0x23, 0x44, 0xc6, 0x53, 0x61, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x53, 0x68, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0x16, 0x53, 0x85, 0x54, + 0x7c, 0x56, 0x75, 0x44, 0xc6, 0x44, 0xc6, 0x55, 0x7b, 0x44, 0xc6, 0x56, 0xb9, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0xc0, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x59, 0x6e, 0x56, 0xdd, 0x57, + 0xd4, 0x59, 0xcd, 0x44, 0xc6, 0x44, 0xc6, 0x58, 0xd3, 0x44, 0xc6, 0x5a, 0x11, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5a, 0x18, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0xc6, 0x5a, 0x35, 0x5b, + 0x2c, 0x5d, 0x25, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0x2b, 0x44, 0xc6, 0x5d, 0x69, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5d, 0x70, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0x1e, 0x5d, 0x8d, 0x5e, + 0x84, 0x60, 0x7d, 0x44, 0xc6, 0x44, 0xc6, 0x5f, 0x83, 0x44, 0xc6, 0x60, 0xc1, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0xc8, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, + 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0xca, 0x29, 0x1e, 0x50, 0x40, + 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x65, 0x48, 0x89, 0x54, 0x7e, 0x39, + 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, @@ -744,12 +832,12 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, - 0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, - 0x54, 0x69, 0x1f, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, - 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, - 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, - 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, - 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, + 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, + 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, + 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, + 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, + 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x66, 0x16, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, + 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, @@ -765,157 +853,176 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, - 0x00, 0x0b, 0x35, 0x22, 0x6a, 0x9b, 0x6c, 0x4f, 0x6c, 0x67, 0x6c, 0x82, 0x6d, 0x1d, 0x6d, 0xb5, - 0x6d, 0xd0, 0x6e, 0x62, 0x6d, 0xeb, 0x6e, 0x2c, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 0x14, 0x75, - 0x2f, 0x09, 0x12, 0x7e, 0x30, 0x75, 0x57, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, - 0xd0, 0xf1, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x6a, 0x54, 0x0b, 0x58, - 0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x7e, - 0x30, 0x0a, 0x22, 0x09, 0xb2, 0x6a, 0x93, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, - 0x3b, 0x49, 0x33, 0x6a, 0xb7, 0x89, 0x34, 0x6a, 0xc7, 0x6a, 0xf5, 0x6b, 0x23, 0x6b, 0x51, 0x6b, - 0x7f, 0x6b, 0xad, 0x6b, 0xdb, 0x6c, 0x09, 0x12, 0x41, 0xa9, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, - 0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, - 0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x16, 0x12, - 0x64, 0x40, 0x02, 0x6c, 0x37, 0x12, 0x41, 0xc6, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, - 0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, - 0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x16, 0x12, 0x64, 0x69, - 0x02, 0x6c, 0x37, 0x12, 0x41, 0xe3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, - 0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, - 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x16, 0x12, 0x64, 0x92, 0x02, 0x6c, - 0x37, 0x12, 0x42, 0x00, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, - 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, - 0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x16, 0x12, 0x64, 0xbb, 0x02, 0x6c, 0x37, 0x12, - 0x42, 0x1d, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, - 0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, - 0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x16, 0x12, 0x64, 0xe4, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x3a, - 0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, - 0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, - 0x01, 0xb3, 0x12, 0x41, 0x16, 0x12, 0x65, 0x0d, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x57, 0xd2, 0x2e, - 0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, - 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, - 0x12, 0x41, 0x16, 0x12, 0x65, 0x36, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x74, 0xd2, 0x2f, 0xd2, 0x0f, - 0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, - 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, - 0x16, 0x12, 0x65, 0x5f, 0x02, 0x6c, 0x37, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x65, 0xbf, - 0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x75, - 0x2f, 0xb1, 0x12, 0x7e, 0x30, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, - 0x72, 0x12, 0x41, 0x8e, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb2, 0x12, 0x7e, 0x30, 0x0a, 0x22, 0x09, - 0xb2, 0x6a, 0x93, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x45, 0x74, 0xd0, - 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, - 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, - 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, - 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, - 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, - 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0x3e, 0x20, - 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, - 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, - 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, - 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, - 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, - 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, - 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, - 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, - 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, - 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, - 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, - 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, - 0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, - 0x42, 0x91, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, - 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, - 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, - 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x7e, - 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, - 0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, - 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, - 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, - 0x7e, 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, - 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, - 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, - 0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x7e, 0x30, 0x7a, 0x21, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, - 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x65, 0xbf, 0xc0, - 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xd0, 0xa8, 0x22, 0x6e, 0x9c, 0x6e, 0xe3, - 0x6f, 0x2a, 0x6f, 0x71, 0x6f, 0xb8, 0x6f, 0xff, 0x70, 0x46, 0x70, 0x8d, 0x75, 0x2f, 0x55, 0x12, - 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, - 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 0x7e, 0x09, - 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, - 0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x4a, 0x98, 0x7e, 0x14, 0x09, - 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x01, 0x12, 0x7e, 0x30, 0x7a, - 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6b, 0x7e, - 0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, - 0x14, 0x11, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 0x27, 0x01, - 0x7b, 0x02, 0x4d, 0xcd, 0x7e, 0x14, 0x0d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, - 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, - 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, - 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, - 0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x51, 0x02, 0x7e, 0x14, 0x11, 0xcd, 0x80, - 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x03, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, - 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 0x27, 0x01, - 0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, - 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 0x7f, 0x02, - 0x54, 0x37, 0x7e, 0x14, 0x15, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, - 0x04, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, - 0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, - 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, - 0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x57, 0x6c, 0x7e, 0x14, 0x19, 0xcd, 0x80, 0xeb, 0x75, - 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x05, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, - 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 0x83, 0x2d, - 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xcc, 0x38, - 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 0x5a, 0xa1, - 0x7e, 0x14, 0x1d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x06, 0x12, - 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, - 0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, - 0x0b, 0x14, 0xbe, 0x14, 0x25, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x75, - 0x7a, 0x27, 0x01, 0x85, 0x02, 0x5d, 0xd6, 0x7e, 0x14, 0x21, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, - 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, - 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 0x23, 0x7e, - 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xcc, 0x38, 0x0f, 0x1b, - 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x61, 0x0b, 0x7e, 0x14, - 0x25, 0xcd, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0xe5, 0xc0, - 0x54, 0x03, 0x68, 0x05, 0x12, 0x77, 0xdd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, - 0x71, 0xe9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x71, 0x0d, 0x80, 0x09, 0x30, - 0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xf9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, - 0x12, 0x7e, 0x30, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, - 0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, - 0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, - 0x45, 0xbe, 0x44, 0x09, 0xcc, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x7e, - 0x30, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x73, 0xc8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, + 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, + 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, + 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, + 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x22, 0x67, 0x96, 0x69, 0x63, 0x69, + 0x7b, 0x6a, 0x49, 0x6a, 0xe4, 0x6b, 0x8e, 0x6b, 0xa9, 0x6c, 0x3b, 0x6b, 0xc4, 0x6c, 0x05, 0x69, + 0x96, 0x69, 0xaa, 0x7c, 0xb3, 0xbe, 0xb0, 0x0b, 0x28, 0x14, 0x75, 0x31, 0x09, 0x12, 0x7c, 0x15, + 0x75, 0x6d, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x22, 0xc0, 0xa8, + 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x67, 0x4b, 0x0b, 0x58, 0x50, 0x89, 0x54, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x31, 0xb0, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 0xb3, + 0x67, 0x8e, 0x42, 0x32, 0x19, 0x43, 0x00, 0x36, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x3b, + 0x49, 0x33, 0x67, 0xcb, 0x0a, 0x22, 0x09, 0x32, 0x00, 0x36, 0x09, 0xb2, 0x67, 0x8e, 0xa5, 0xbb, + 0x00, 0x05, 0xf4, 0x52, 0x33, 0x80, 0x02, 0x42, 0x33, 0x89, 0x34, 0x67, 0xdb, 0x68, 0x09, 0x68, + 0x37, 0x68, 0x65, 0x68, 0x93, 0x68, 0xc1, 0x68, 0xef, 0x69, 0x1d, 0x12, 0x41, 0xb5, 0xd2, 0x28, + 0xd2, 0x08, 0xc2, 0x40, 0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xcf, + 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xaf, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xbf, + 0x12, 0x41, 0x16, 0x12, 0x60, 0xcf, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xd4, 0xd2, 0x29, 0xd2, 0x09, + 0xc2, 0x41, 0xc2, 0x49, 0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd0, 0x7e, 0x04, + 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb1, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc1, 0x12, 0x41, + 0x16, 0x12, 0x61, 0x05, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xf3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, + 0xc2, 0x4a, 0xc2, 0x3a, 0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd1, 0x7e, 0x04, 0x00, 0x20, + 0x7a, 0x07, 0x01, 0xb3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc3, 0x12, 0x41, 0x16, 0x12, + 0x61, 0x3b, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x12, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, + 0xc2, 0x3b, 0xc2, 0x33, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd2, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, + 0x01, 0xb5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc5, 0x12, 0x41, 0x16, 0x12, 0x61, 0x71, + 0x02, 0x69, 0x4b, 0x12, 0x42, 0x31, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, + 0xc2, 0x34, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd3, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb7, + 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc7, 0x12, 0x41, 0x16, 0x12, 0x61, 0xa7, 0x02, 0x69, + 0x4b, 0x12, 0x42, 0x50, 0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, + 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd4, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb9, 0x7e, 0x04, + 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc9, 0x12, 0x41, 0x16, 0x12, 0x61, 0xdd, 0x02, 0x69, 0x4b, 0x12, + 0x42, 0x6f, 0xd2, 0x2e, 0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, + 0x7a, 0x03, 0x01, 0xd5, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x38, + 0x7a, 0x07, 0x01, 0xcb, 0x12, 0x41, 0x16, 0x12, 0x62, 0x13, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x8e, + 0xd2, 0x2f, 0xd2, 0x0f, 0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, + 0x01, 0xd6, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, + 0x01, 0xcd, 0x12, 0x41, 0x16, 0x12, 0x62, 0x49, 0x02, 0x69, 0x4b, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, + 0x0f, 0x12, 0x62, 0xb6, 0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, + 0xc2, 0xd7, 0x22, 0x75, 0x31, 0xb1, 0x12, 0x7c, 0x15, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, + 0x00, 0x48, 0x12, 0x41, 0x7e, 0x12, 0x41, 0x9a, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb2, 0x12, 0x7c, + 0x15, 0x0a, 0x22, 0x09, 0xb2, 0x67, 0x8e, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xcf, + 0x12, 0x31, 0x85, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb7, 0x12, 0x7c, 0x15, 0x0a, 0x22, 0x09, 0xb2, + 0x67, 0x8e, 0x42, 0x24, 0x12, 0x35, 0x3d, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb9, 0x12, 0x7c, 0x15, + 0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0x42, 0x34, 0x19, 0x43, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xd0, + 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x0b, 0x7c, 0xb4, 0x20, 0xe0, 0x04, 0x6d, 0x33, 0x80, 0x04, + 0x49, 0x30, 0x01, 0x8f, 0x7e, 0xa0, 0xd8, 0xa5, 0xef, 0xca, 0x0b, 0xca, 0x29, 0x12, 0x62, 0xb6, + 0xda, 0x29, 0xda, 0x0b, 0x40, 0x62, 0x75, 0x31, 0xba, 0x12, 0x7c, 0x15, 0x7c, 0xb4, 0x30, 0xe0, + 0x1e, 0x6d, 0x33, 0x59, 0x30, 0x01, 0x8f, 0x7e, 0x34, 0x09, 0xe3, 0x0a, 0x82, 0x7e, 0x94, 0x04, + 0x00, 0xad, 0x89, 0x2d, 0x39, 0x59, 0x30, 0x01, 0x6f, 0x59, 0x30, 0x01, 0x7f, 0x7c, 0xb4, 0x30, + 0xe1, 0x10, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x08, 0x44, 0x04, 0x19, 0xb0, + 0x00, 0x08, 0x0a, 0x02, 0x09, 0xb0, 0x67, 0x8e, 0x42, 0x21, 0xf4, 0x52, 0x34, 0x7c, 0xb2, 0x23, + 0x0a, 0x0b, 0xca, 0x19, 0x49, 0x00, 0x30, 0xd5, 0x99, 0x04, 0xda, 0x19, 0xc0, 0xf1, 0x75, 0xf1, + 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, + 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, + 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, + 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, + 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, + 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, + 0x62, 0x09, 0xb6, 0x67, 0x8e, 0x3e, 0x20, 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, + 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, + 0x01, 0xbf, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, + 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, + 0xbf, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x0a, 0x62, 0x09, 0xb6, + 0x67, 0x8e, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xa5, 0xee, 0x52, + 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0xaf, 0xda, 0x28, 0x09, 0x30, 0x00, 0x0c, 0x74, + 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x0c, + 0x44, 0x80, 0xca, 0xb8, 0xa5, 0xed, 0x42, 0x2a, 0xda, 0xb8, 0x80, 0x0a, 0x54, 0x7f, 0xca, 0xb8, + 0xa5, 0xee, 0x52, 0x2a, 0xda, 0xb8, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, + 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x02, + 0x68, 0x10, 0xa5, 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, + 0x80, 0x04, 0xa5, 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, + 0x29, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 0x80, 0x0b, 0xa5, 0xee, 0x52, + 0x29, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x78, 0x00, 0x12, 0x42, 0xad, 0xd0, 0xa8, 0x22, 0x7e, 0x04, + 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, + 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, + 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, + 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb5, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, + 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 0x0c, 0xe5, 0x6e, 0xb4, 0x07, 0x23, 0x09, + 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, + 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, + 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb6, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, + 0x02, 0xe5, 0x6e, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, + 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, + 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb4, 0x12, 0x7c, + 0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x41, 0x31, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, + 0xb3, 0x67, 0x8e, 0x42, 0x35, 0x12, 0x6c, 0x5b, 0xd0, 0xa8, 0x22, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, + 0xc8, 0x7c, 0x64, 0x12, 0x62, 0xb6, 0x40, 0x13, 0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0xf4, 0x52, + 0x35, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x6c, 0x8c, 0x6c, 0xd3, + 0x6d, 0x1a, 0x6d, 0x61, 0x6d, 0xa8, 0x6d, 0xef, 0x6e, 0x36, 0x6e, 0x7d, 0x75, 0x31, 0x55, 0x12, + 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, + 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x8f, 0x2d, 0x23, 0x7e, 0x09, + 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, + 0x78, 0xec, 0x7a, 0x17, 0x01, 0x7f, 0x7a, 0x27, 0x01, 0x8f, 0x02, 0x46, 0x0f, 0x7e, 0x14, 0x09, + 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x01, 0x12, 0x7c, 0x15, 0x7a, + 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x81, 0x7e, + 0x27, 0x01, 0x91, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, + 0x14, 0x11, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x81, 0x7a, 0x27, 0x01, + 0x91, 0x02, 0x49, 0x67, 0x7e, 0x14, 0x0d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, + 0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, + 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x83, 0x7e, 0x27, 0x01, 0x93, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, + 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, + 0x7a, 0x17, 0x01, 0x83, 0x7a, 0x27, 0x01, 0x93, 0x02, 0x4c, 0xbf, 0x7e, 0x14, 0x11, 0xe3, 0x80, + 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x03, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, + 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x85, 0x7e, 0x27, 0x01, + 0x95, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, + 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x85, 0x7a, 0x27, 0x01, 0x95, 0x02, + 0x50, 0x17, 0x7e, 0x14, 0x15, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, + 0x04, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, + 0x7e, 0x17, 0x01, 0x87, 0x7e, 0x27, 0x01, 0x97, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, + 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, + 0x01, 0x87, 0x7a, 0x27, 0x01, 0x97, 0x02, 0x53, 0x6f, 0x7e, 0x14, 0x19, 0xe3, 0x80, 0xeb, 0x75, + 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x05, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, + 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x89, 0x7e, 0x27, 0x01, 0x99, 0x2d, + 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xe2, 0x38, + 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x89, 0x7a, 0x27, 0x01, 0x99, 0x02, 0x56, 0xc7, + 0x7e, 0x14, 0x1d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x06, 0x12, + 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, + 0x01, 0x8b, 0x7e, 0x27, 0x01, 0x9b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, + 0x0b, 0x14, 0xbe, 0x14, 0x25, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8b, + 0x7a, 0x27, 0x01, 0x9b, 0x02, 0x5a, 0x1f, 0x7e, 0x14, 0x21, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, + 0x12, 0x7c, 0x15, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, + 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x8d, 0x7e, 0x27, 0x01, 0x9d, 0x2d, 0x23, 0x7e, + 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xe2, 0x38, 0x0f, 0x1b, + 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8d, 0x7a, 0x27, 0x01, 0x9d, 0x02, 0x5d, 0x77, 0x7e, 0x14, + 0x25, 0xe3, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0xe5, 0xc0, + 0x54, 0x03, 0x68, 0x05, 0x12, 0x75, 0xcd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, + 0x6f, 0xd9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x6e, 0xfd, 0x80, 0x09, 0x30, + 0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xe9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x31, 0x10, + 0x12, 0x7c, 0x15, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, + 0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xdb, 0x2d, 0x35, 0xbe, + 0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xdb, 0x7e, 0x37, 0x01, 0xd9, 0x7d, 0x43, 0x2d, + 0x45, 0xbe, 0x44, 0x09, 0xe2, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xd9, 0x75, 0x31, 0x11, 0x12, 0x7c, + 0x15, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x71, 0xb8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 0xe4, 0xa9, 0x24, 0xe4, 0xfc, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x3b, 0xe5, 0xe5, 0x54, 0xc0, 0x78, - 0xb4, 0x12, 0x76, 0x6a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, - 0x2f, 0x16, 0x12, 0x7e, 0x30, 0x80, 0xed, 0x75, 0x2f, 0x12, 0x12, 0x7e, 0x30, 0x7a, 0xb1, 0x2f, - 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x09, 0xcd, 0x9d, 0x54, 0x12, 0x73, 0xc8, 0x7e, 0x34, 0x05, 0xcd, - 0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x2f, 0x13, 0x12, - 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xe9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe9, 0x80, 0xa7, 0x75, 0x2f, - 0x14, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xed, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xed, 0xa9, 0xd7, - 0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x2f, 0x15, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, - 0xf1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf1, 0x80, 0xe5, 0x75, 0x2f, 0x18, 0x12, 0x7e, 0x30, 0xca, + 0xb4, 0x12, 0x74, 0x5a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, + 0x31, 0x16, 0x12, 0x7c, 0x15, 0x80, 0xed, 0x75, 0x31, 0x12, 0x12, 0x7c, 0x15, 0x7a, 0xb1, 0x31, + 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x09, 0xe3, 0x9d, 0x54, 0x12, 0x71, 0xb8, 0x7e, 0x34, 0x05, 0xe3, + 0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x31, 0x13, 0x12, + 0x7c, 0x15, 0x7e, 0x0f, 0x29, 0xff, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xff, 0x80, 0xa7, 0x75, 0x31, + 0x14, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 0x03, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x03, 0xa9, 0xd7, + 0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x31, 0x15, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, + 0x07, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x07, 0x80, 0xe5, 0x75, 0x31, 0x18, 0x12, 0x7c, 0x15, 0xca, 0x09, 0xca, 0x39, 0xca, 0x2b, 0xc2, 0xc2, 0xa9, 0x21, 0xf2, 0x52, 0xe5, 0xf5, 0x33, 0x82, 0xe7, - 0x40, 0x44, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, - 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x52, - 0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x75, 0x26, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x2f, 0x19, - 0x12, 0x7e, 0x30, 0x7a, 0x91, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, + 0x40, 0x44, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, + 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdd, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x52, + 0x7a, 0x47, 0x01, 0xdd, 0x7d, 0x45, 0x12, 0x73, 0x16, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x31, 0x19, + 0x12, 0x7c, 0x15, 0x7a, 0x91, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x50, 0xbc, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x41, 0x80, - 0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 0x07, 0x01, 0xc9, 0x7a, - 0x07, 0x01, 0xc7, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x2f, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x00, - 0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x54, 0x12, 0x75, 0x26, 0x7e, 0x34, 0x01, - 0xcd, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x75, 0x26, 0xda, 0x49, 0x80, 0x99, - 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xd9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xd9, - 0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xe1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe1, 0xa9, 0xd7, 0xf4, 0xa9, - 0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xdd, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xdd, 0x80, - 0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x29, 0xf9, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, - 0xf9, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x01, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x01, 0xa9, 0xd7, 0xf4, - 0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x29, 0xfd, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 0xfd, - 0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x28, 0x12, 0x7e, 0x30, 0xca, + 0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdf, 0x7a, + 0x07, 0x01, 0xdd, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, + 0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x54, 0x12, 0x73, 0x16, 0x7e, 0x34, 0x01, + 0xe3, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdd, 0x12, 0x73, 0x16, 0xda, 0x49, 0x80, 0x99, + 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xef, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xef, + 0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xf7, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf7, 0xa9, 0xd7, 0xf4, 0xa9, + 0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xf3, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf3, 0x80, + 0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x2a, 0x0f, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, + 0x0f, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x17, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x17, 0xa9, 0xd7, 0xf4, + 0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x2a, 0x13, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x13, + 0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x31, 0x28, 0x12, 0x7c, 0x15, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xc2, 0xc4, 0xa9, 0x21, 0xf2, 0xb6, 0xe5, 0xf5, 0x33, 0x72, 0xe7, - 0x40, 0xe0, 0x7e, 0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, - 0x40, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, + 0x40, 0xe0, 0x7e, 0x0d, 0x46, 0x7e, 0x1d, 0x4a, 0x7e, 0x2d, 0x4e, 0x7e, 0x3d, 0x52, 0x7e, 0x85, + 0x56, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 0x97, 0x4d, 0x98, 0x68, 0x72, 0x7a, 0x11, 0xf3, 0x7a, 0x01, 0xf3, 0x7a, 0x31, 0xf3, 0x7a, 0x21, 0xf3, 0x7a, 0x51, 0xf3, 0x7a, 0x41, 0xf3, 0x7a, 0x71, 0xf3, 0x7a, 0x61, 0xf3, 0x7a, 0x91, 0xf3, - 0x7a, 0x81, 0xf3, 0x30, 0x73, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, + 0x7a, 0x81, 0xf3, 0x30, 0x7b, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 0xc1, 0xf3, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 0x7d, 0x78, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, - 0xa9, 0x30, 0xf5, 0x03, 0x02, 0x72, 0xe6, 0x75, 0x2f, 0x29, 0x12, 0x7e, 0x30, 0x20, 0x73, 0x0b, - 0x75, 0x2f, 0x0a, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x2f, 0x12, 0x12, 0x7e, - 0x30, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 0x7a, 0x0d, - 0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, - 0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x75, 0x0b, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, + 0xa9, 0x30, 0xf5, 0x03, 0x02, 0x70, 0xd6, 0x75, 0x31, 0x29, 0x12, 0x7c, 0x15, 0x20, 0x7b, 0x0b, + 0x75, 0x31, 0x0a, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x31, 0x12, 0x12, 0x7c, + 0x15, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x46, 0x7a, 0x0d, 0x4a, 0x7a, 0x0d, + 0x4e, 0x7a, 0x0d, 0x52, 0x7a, 0x05, 0x56, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, + 0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x72, 0xfb, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 0xe3, 0x7a, 0x39, 0xa0, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, @@ -937,7 +1044,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x22, 0x1e, 0xb0, 0x40, 0x0c, - 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x76, 0x69, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, + 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x74, 0x59, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 0xa1, 0xf3, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, @@ -958,144 +1065,144 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, - 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xc5, - 0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x09, 0xcd, 0x9d, 0x50, 0xbd, 0x35, - 0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, - 0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 0x37, 0x01, 0xc1, 0xbe, - 0x34, 0x09, 0xcc, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xcd, 0x7a, 0x37, 0x01, 0xc1, 0x80, 0xbd, 0xd2, - 0xaf, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 0x2f, 0x51, - 0x12, 0x7e, 0x30, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, - 0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6e, 0x8c, 0x7c, 0xb2, 0x54, 0x78, - 0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 0x7a, 0x25, - 0x4f, 0x7e, 0x64, 0x77, 0x47, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x77, 0x55, 0x7e, 0x64, 0x76, - 0xbd, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, - 0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 0x7e, 0x64, - 0x77, 0x33, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x76, 0xb2, 0x7a, - 0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x7e, 0x30, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 0x30, 0x0b, - 0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, - 0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x77, 0xd1, 0x30, 0xe6, - 0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x6a, 0x68, - 0x20, 0xe3, 0x04, 0x7e, 0x44, 0x77, 0xd9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, - 0x09, 0x7e, 0x64, 0x76, 0xbd, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 0xf5, 0x4f, - 0x7e, 0x64, 0x77, 0x96, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, - 0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x2f, 0x01, - 0x12, 0x7e, 0x30, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x2f, 0xfe, 0x12, 0x7e, - 0x30, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, - 0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x78, 0x52, 0xca, 0x0b, 0xca, + 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xdb, + 0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xd7, 0x7e, 0x54, 0x09, 0xe3, 0x9d, 0x50, 0xbd, 0x35, + 0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x61, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, + 0xdb, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xdb, 0x2e, 0x37, 0x01, 0xd7, 0x7a, 0x37, 0x01, 0xd7, 0xbe, + 0x34, 0x09, 0xe2, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xe3, 0x7a, 0x37, 0x01, 0xd7, 0x80, 0xbd, 0xd2, + 0xaf, 0x22, 0x75, 0x31, 0x53, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 0x80, 0x11, 0x75, 0x31, 0x51, + 0x12, 0x7c, 0x15, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, + 0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6c, 0x7c, 0x7c, 0xb2, 0x54, 0x78, + 0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x63, 0x7a, 0x25, + 0x65, 0x7e, 0x64, 0x75, 0x37, 0x7a, 0x65, 0x61, 0x89, 0x24, 0x02, 0x75, 0x45, 0x7e, 0x64, 0x74, + 0xad, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, + 0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x63, 0x7e, 0x64, + 0x75, 0x23, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x74, 0xa2, 0x7a, + 0x65, 0x61, 0x22, 0x75, 0x31, 0x52, 0x12, 0x7c, 0x15, 0x7e, 0x21, 0x63, 0x7e, 0x09, 0x30, 0x0b, + 0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x31, 0x54, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, + 0x7e, 0x25, 0x65, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x75, 0xc1, 0x30, 0xe6, + 0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x67, 0x63, + 0x20, 0xe3, 0x04, 0x7e, 0x44, 0x75, 0xc9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, + 0x09, 0x7e, 0x64, 0x74, 0xad, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x63, 0xf5, 0x65, + 0x7e, 0x64, 0x75, 0x86, 0x80, 0x99, 0x7e, 0x15, 0x63, 0xe5, 0x65, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, + 0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x31, 0x01, + 0x12, 0x7c, 0x15, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x31, 0xfe, 0x12, 0x7c, + 0x15, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, + 0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x76, 0x42, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, - 0xf1, 0x7e, 0xb3, 0x2a, 0x1d, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, - 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x78, - 0xcd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x78, 0xcd, 0x80, 0x09, 0x30, 0xc0, - 0x06, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, + 0xf1, 0x7e, 0xb3, 0x2a, 0x33, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, + 0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x76, + 0xbd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x76, 0xbd, 0x80, 0x09, 0x30, 0xc0, + 0x06, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, - 0x2a, 0x1d, 0xb4, 0x02, 0x07, 0x12, 0x78, 0x5e, 0x02, 0x78, 0x52, 0x22, 0xb4, 0x01, 0xfc, 0x02, - 0x78, 0x98, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x1d, 0x7a, 0x03, 0x2a, 0x1e, 0x22, 0x7e, 0xb3, - 0x2a, 0x15, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, - 0x05, 0x0c, 0x75, 0x2f, 0x71, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xf5, 0x8f, 0x22, 0x75, - 0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x1b, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x1b, 0x7a, 0x0f, 0x2a, - 0x20, 0x7a, 0x57, 0x2a, 0x24, 0x02, 0x78, 0x98, 0x7e, 0xef, 0x2a, 0x20, 0x7e, 0xf7, 0x2a, 0x24, - 0x7e, 0x07, 0x2a, 0x24, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, - 0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x20, 0x7a, - 0xf7, 0x2a, 0x24, 0x75, 0x2f, 0x06, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, - 0x2f, 0x03, 0x12, 0x7e, 0x30, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, - 0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x79, 0x44, 0x7e, - 0xb3, 0x2a, 0x1e, 0xb4, 0x02, 0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2a, 0x1e, - 0x7a, 0xb3, 0x2a, 0x1d, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x2a, - 0x1f, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x1f, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2a, 0x26, 0xe5, 0xe3, - 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x2f, 0x70, 0x12, 0x7e, - 0x30, 0x7e, 0xb3, 0x2a, 0x1f, 0x7e, 0xa3, 0x2a, 0x1c, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x79, 0xdb, - 0x22, 0x02, 0x7d, 0x44, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e, - 0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71, - 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x15, 0x7a, 0x1f, 0x2a, 0x19, 0x75, 0x2f, 0x04, 0x12, - 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x21, - 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x31, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 0x2f, 0x12, 0x7e, 0x30, - 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, - 0x7e, 0x30, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x79, 0xaf, 0x22, 0x6d, - 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x24, 0x7a, 0x03, 0x2a, 0x1f, 0x7e, 0xb3, 0x2a, - 0x15, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x1e, 0x7a, 0x33, 0x2a, 0x1d, 0xbe, 0x07, 0x2a, 0x1b, - 0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x1e, 0x7a, 0x23, 0x2a, 0x1d, 0x7e, 0xb3, 0x2a, 0x15, 0x54, - 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, - 0x30, 0xe4, 0x03, 0x02, 0x7d, 0x44, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, - 0x90, 0x7a, 0x07, 0x75, 0x84, 0xff, 0x73, 0x02, 0x7b, 0x5b, 0x02, 0x7a, 0x4f, 0x02, 0x7b, 0xf8, - 0x02, 0x7c, 0x13, 0x02, 0x7a, 0xf4, 0x02, 0x7a, 0xb5, 0x02, 0x7c, 0x2c, 0x02, 0x7c, 0x2c, 0x02, - 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, - 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x35, 0x02, 0x7c, 0xe9, 0x02, 0x7c, 0x32, - 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x7e, - 0xb3, 0x2a, 0x16, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13, - 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x72, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, - 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x4e, 0x40, 0x35, 0x02, 0x78, 0x83, - 0xb4, 0x08, 0x10, 0x75, 0x2f, 0x74, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75, - 0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x2f, 0x75, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf2, - 0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6, - 0x02, 0x22, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x00, 0x35, 0x75, 0x2f, 0x76, 0x12, - 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, - 0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74, - 0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, - 0x22, 0x02, 0x7d, 0x44, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3, - 0x2a, 0x18, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x01, 0x24, 0x75, 0x2f, 0x77, 0x12, - 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e, - 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26, - 0xb4, 0x03, 0x17, 0x75, 0x2f, 0x78, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, - 0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75, - 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x22, 0xd0, 0xf1, 0x02, 0x78, 0x7f, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, - 0x09, 0x23, 0x75, 0x2f, 0x79, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xbe, 0xb3, 0x3f, 0xf1, - 0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0x68, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, - 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x7e, 0x30, 0x80, 0x62, - 0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x55, - 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75, - 0x2f, 0x7c, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2, - 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, - 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x73, 0x12, 0x7e, - 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x7a, - 0x40, 0x03, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0b, 0xf6, 0x75, - 0x2f, 0x7d, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0x7e, 0xa3, 0x2a, 0x1a, 0x4c, 0xab, 0x78, - 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0a, 0xdb, 0x75, 0x2f, 0x7e, 0x12, 0x7e, 0x30, - 0x7e, 0xb3, 0x2a, 0x18, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x7d, 0x44, 0x02, - 0x7d, 0x44, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12, - 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x18, 0x2a, 0x26, 0x7a, 0x1c, - 0x00, 0x00, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0x02, 0x7c, 0xe3, 0xb4, 0x06, 0x3a, 0x75, - 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, - 0xd7, 0x2a, 0x17, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0x75, - 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7e, - 0x75, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, - 0x87, 0x12, 0x78, 0x7f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, - 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x2a, 0x17, 0x4d, - 0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16, - 0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x19, 0x7e, 0x17, 0x2a, 0x17, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, - 0xca, 0x28, 0x32, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x03, 0x15, - 0x75, 0x2f, 0xc2, 0x12, 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x57, - 0x2a, 0x1b, 0x02, 0x78, 0x83, 0xb4, 0x05, 0x39, 0x75, 0x2f, 0xc0, 0x12, 0x7e, 0x30, 0xc0, 0xa8, - 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, - 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x17, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0xd0, 0x87, - 0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2a, 0x1b, 0x02, 0x78, - 0x83, 0x02, 0x7d, 0x44, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8, - 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x19, 0x7e, 0x08, 0x2a, 0x26, - 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7e, 0x3c, 0xda, 0x59, 0xda, 0x0b, 0xd0, - 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, - 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, - 0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0xbd, 0x74, - 0x78, 0x11, 0x75, 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x12, 0x7e, 0x75, 0x40, 0x06, 0xd0, 0x87, 0xd0, - 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, - 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0xc2, - 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 0x34, 0x7f, 0xcc, 0x7e, 0x1b, - 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, - 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, - 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, - 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, - 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, + 0x2a, 0x33, 0xb4, 0x02, 0x07, 0x12, 0x76, 0x4e, 0x02, 0x76, 0x42, 0x22, 0xb4, 0x01, 0xfc, 0x02, + 0x76, 0x88, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x33, 0x7a, 0x03, 0x2a, 0x34, 0x22, 0x7e, 0xb3, + 0x2a, 0x2b, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, + 0x05, 0x0c, 0x75, 0x31, 0x71, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xf5, 0x8f, 0x22, 0x75, + 0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x31, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x31, 0x7a, 0x0f, 0x2a, + 0x36, 0x7a, 0x57, 0x2a, 0x3a, 0x02, 0x76, 0x88, 0x7e, 0xef, 0x2a, 0x36, 0x7e, 0xf7, 0x2a, 0x3a, + 0x7e, 0x07, 0x2a, 0x3a, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, + 0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x36, 0x7a, + 0xf7, 0x2a, 0x3a, 0x75, 0x31, 0x06, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, + 0x31, 0x03, 0x12, 0x7c, 0x15, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, + 0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x77, 0x29, 0x7e, + 0xb3, 0x2a, 0x34, 0xb4, 0x02, 0x04, 0xa9, 0xd4, 0xe4, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, + 0x7c, 0x32, 0x7e, 0x13, 0x2a, 0x35, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x35, 0x7e, 0x00, 0x00, 0x2e, + 0x04, 0x2a, 0x3c, 0xe5, 0xe3, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, + 0x75, 0x31, 0x70, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x35, 0x7e, 0xa3, 0x2a, 0x32, 0xbc, 0xab, + 0x78, 0x03, 0x12, 0x77, 0xc0, 0x22, 0x02, 0x7b, 0x29, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, + 0xe2, 0x7e, 0x01, 0xe3, 0x7e, 0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, + 0x7e, 0x41, 0xe3, 0x7e, 0x71, 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x2b, 0x7a, 0x1f, 0x2a, + 0x2f, 0x75, 0x31, 0x04, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, + 0x12, 0x7c, 0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x7a, + 0x41, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, + 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, + 0x12, 0x77, 0x94, 0x22, 0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x3a, 0x7a, 0x03, + 0x2a, 0x35, 0x7e, 0xb3, 0x2a, 0x2b, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x34, 0x7a, 0x33, 0x2a, + 0x33, 0xbe, 0x07, 0x2a, 0x31, 0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x34, 0x7a, 0x23, 0x2a, 0x33, + 0x7e, 0xb3, 0x2a, 0x2b, 0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, + 0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 0x03, 0x02, 0x7b, 0x29, 0x54, 0x3e, 0xf5, 0xf0, 0x03, + 0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x77, 0xec, 0x75, 0x84, 0xff, 0x73, 0x02, 0x79, 0x40, 0x02, + 0x78, 0x34, 0x02, 0x79, 0xdd, 0x02, 0x79, 0xf8, 0x02, 0x78, 0xd9, 0x02, 0x78, 0x9a, 0x02, 0x7a, + 0x11, 0x02, 0x7a, 0x11, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, + 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x1a, 0x02, + 0x7a, 0xce, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, + 0x17, 0x02, 0x7a, 0x17, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x2d, 0x60, + 0x56, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 0x75, 0x31, 0x72, 0x12, 0x7c, + 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x7b, 0x33, + 0x40, 0x35, 0x02, 0x76, 0x73, 0xb4, 0x08, 0x10, 0x75, 0x31, 0x74, 0x12, 0x7c, 0x15, 0x7e, 0xb3, + 0x3f, 0xf1, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x31, 0x75, 0x12, 0x7c, + 0x15, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, + 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x00, + 0x35, 0x75, 0x31, 0x76, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, + 0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, + 0xe1, 0x30, 0xe6, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, + 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x30, 0x54, + 0x0f, 0x42, 0xf1, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x01, + 0x24, 0x75, 0x31, 0x77, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0x78, 0x05, 0x53, + 0xe1, 0x3f, 0x80, 0x37, 0x7e, 0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, + 0x53, 0xe1, 0xbf, 0x80, 0x26, 0xb4, 0x03, 0x17, 0x75, 0x31, 0x78, 0x12, 0x7c, 0x15, 0x7e, 0xb3, + 0x2a, 0x30, 0x20, 0xe7, 0x05, 0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, + 0xe1, 0xc0, 0xd0, 0xf1, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x22, 0xd0, 0xf1, 0x02, 0x76, 0x6f, + 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x09, 0x23, 0x75, 0x31, 0x79, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, + 0x2e, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0xd4, 0xd0, 0xf1, + 0xda, 0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x31, 0x7a, + 0x12, 0x7c, 0x15, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x31, 0x7b, 0x12, 0x7c, 0x15, 0x7e, 0xb3, + 0x2a, 0x2e, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, + 0x46, 0xb4, 0x01, 0x19, 0x75, 0x31, 0x7c, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x01, + 0x39, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, + 0x7e, 0xb3, 0x2a, 0x2d, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, + 0x75, 0x31, 0x73, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, + 0x7c, 0x15, 0x12, 0x7b, 0x5f, 0x40, 0x03, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, + 0x2c, 0xb4, 0x0b, 0xf6, 0x75, 0x31, 0x7d, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x7e, 0xa3, + 0x2a, 0x30, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x0a, 0xdb, 0x75, + 0x31, 0x7e, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, + 0x22, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x04, + 0x20, 0x75, 0x31, 0xc3, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x2d, 0x7e, + 0x18, 0x2a, 0x3c, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x2a, 0x31, 0x12, 0x7c, 0x21, 0x02, 0x7a, + 0xc8, 0xb4, 0x06, 0x3a, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, + 0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x2a, 0x2d, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, + 0x7e, 0x77, 0x2a, 0x31, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, + 0xa9, 0xd5, 0x87, 0x12, 0x7c, 0x5a, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, + 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x76, 0x6f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, + 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, + 0x7e, 0x57, 0x2a, 0x2d, 0x4d, 0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, + 0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x2f, 0x7e, 0x17, 0x2a, 0x2d, 0xc0, + 0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, + 0x2a, 0x2c, 0xb4, 0x03, 0x15, 0x75, 0x31, 0xc2, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, + 0x17, 0x2a, 0x2d, 0x7e, 0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0xb4, 0x05, 0x39, 0x75, 0x31, 0xc0, + 0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x3c, + 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x2d, 0x7e, 0x47, 0x2a, 0x31, + 0x12, 0x7c, 0x21, 0xd0, 0x87, 0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0x7e, + 0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0x02, 0x7b, 0x29, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x43, + 0xe1, 0xc0, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, + 0x19, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7c, 0x21, + 0xda, 0x59, 0xda, 0x0b, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, + 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 0x2b, 0x7e, 0x58, 0x00, + 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 0x7e, + 0x77, 0x2a, 0x31, 0xbd, 0x74, 0x78, 0x11, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x12, 0x7c, 0x5a, + 0x40, 0x06, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, + 0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, + 0x87, 0x7e, 0x34, 0x7f, 0xc2, 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, + 0x34, 0x7f, 0xcc, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, + 0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, + 0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, + 0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, + 0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, + 0xff, 0xc3, 0x22, 0xd3, 0x22, -// Segment #15, Start Address 00ff7fc6, Length 4 +// Segment #16, Start Address 00ff7fc6, Length 4 0xff,0x00,0xc6,0x7f,0x04,0x00, - 0x01, 0x0c, 0x03, 0x00, + 0x01, 0x10, 0x04, 0x00, -// Segment #16, Start Address 00ff7e30, Length 315 -0xff,0x00,0x30,0x7e,0x3b,0x01, - 0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, +// Segment #17, Start Address 00ff7c15, Length 330 +0xff,0x00,0x15,0x7c,0x4a,0x01, + 0xca, 0x08, 0x7e, 0x01, 0x31, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, - 0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7e, 0x9f, + 0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7c, 0x84, 0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 0x90, 0x30, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, @@ -1104,16 +1211,17 @@ static unsigned char IMAGE_ARRAY_NAME[] = { 0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, - 0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, - 0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, - 0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, - 0x51, 0x23, 0x7e, 0x18, 0x7f, 0x15, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, - 0x08, 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, + 0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x42, 0x08, 0x06, 0x04, 0x02, 0x04, 0x00, + 0x02, 0x01, 0x04, 0x01, 0x02, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x04, 0x02, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x02, 0x08, 0x02, 0x04, 0x20, 0x04, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, + 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x1a, 0x38, 0x1a, 0x0a, 0x51, + 0x23, 0x7e, 0x18, 0x7c, 0xfa, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, + 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, }; static struct edge_firmware_version_info IMAGE_VERSION_NAME = { - 1, 12, 3 }; // Major, Minor, Build + 1, 16, 4 }; // Major, Minor, Build #undef IMAGE_VERSION_NAME diff --git a/drivers/usb/serial/io_fw_down2.h b/drivers/usb/serial/io_fw_down2.h index bbd5dccc2..067277efd 100644 --- a/drivers/usb/serial/io_fw_down2.h +++ b/drivers/usb/serial/io_fw_down2.h @@ -13,9 +13,9 @@ #if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD) #define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD struct edge_firmware_image_record { - unsigned short ExtAddr; - unsigned short Addr; - unsigned short Len; + __le16 ExtAddr; + __le16 Addr; + __le16 Len; unsigned char Data[0]; } __attribute__ ((packed)); diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h index 20eecb39d..93b56d68a 100644 --- a/drivers/usb/serial/io_fw_down3.h +++ b/drivers/usb/serial/io_fw_down3.h @@ -1,11 +1,11 @@ //************************************************************** //* Edgeport Binary Image (for TI based products) -//* Generated by TIBin2C v1.00 +//* Generated by TIBin2C v2.00 (watchport) //* Copyright (C) 2001 Inside Out Networks, All rights reserved. //************************************************************** -static int IMAGE_SIZE = 12166; +static int IMAGE_SIZE = 12749; struct EDGE_FIRMWARE_VERSION_INFO { @@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = { - 4, 1, 0 // Major, Minor, Build + 4, 10, 0 // Major, Minor, Build }; @@ -27,20 +27,20 @@ static unsigned char IMAGE_ARRAY_NAME[] = // WORD Length; // BYTE CheckSum; // }; -0x83, 0x2f, -0x33, +0xca, 0x31, +0xa8, -0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45, -0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, -0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44, -0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75, -0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81, -0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, -0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44, -0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86, -0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, -0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, +0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, +0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, +0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, +0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, +0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, +0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, +0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, +0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, +0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, +0x78, 0x8c, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10, 0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9, @@ -50,747 +50,783 @@ static unsigned char IMAGE_ARRAY_NAME[] = 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, -0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5, +0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, -0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, -0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, +0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, +0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, -0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, -0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, -0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, -0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, -0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, -0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64, -0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, -0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22, -0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, -0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, -0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, -0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, -0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60, -0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95, -0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, -0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, -0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, -0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, -0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, -0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d, -0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53, -0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12, -0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, -0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, -0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, -0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05, -0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e, -0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, -0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34, -0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, -0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01, -0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13, -0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60, -0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, -0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60, -0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, -0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, -0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30, -0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb, -0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01, -0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, -0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, -0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, -0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, -0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, -0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0, -0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, -0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70, -0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, -0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07, -0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, -0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b, -0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, -0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, -0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a, -0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, -0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, -0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, -0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, -0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, -0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, -0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, -0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5, -0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, -0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff, -0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, -0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e, -0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, -0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08, -0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, -0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, -0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac, -0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03, -0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, -0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, -0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, -0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, -0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, -0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, -0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30, -0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12, -0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90, -0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae, -0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03, -0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23, -0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90, -0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50, -0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12, -0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e, -0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa, -0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b, -0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18, -0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12, -0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e, -0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35, -0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, -0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, -0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, -0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, -0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02, -0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, -0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba, -0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, -0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e, -0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c, -0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, -0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, -0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, -0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, -0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, -0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, -0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, -0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, -0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12, -0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90, -0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff, -0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, -0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06, -0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c, -0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5, -0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93, -0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20, -0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, -0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5, -0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, -0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, -0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35, -0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24, -0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, -0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, -0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, -0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, -0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, -0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, -0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, -0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c, -0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, -0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07, -0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02, -0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4, -0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12, -0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05, -0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e, -0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18, -0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02, -0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, -0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, -0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19, -0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78, -0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, -0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc, -0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e, -0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, -0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, -0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70, -0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba, -0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5, -0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18, -0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30, -0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, -0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6, -0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0, -0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60, -0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, -0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, -0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, -0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02, -0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90, -0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90, -0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09, -0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, -0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90, -0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90, -0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09, -0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0, -0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, -0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0, -0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44, -0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, -0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12, -0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, -0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12, -0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, -0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5, -0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74, -0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94, -0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, -0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65, -0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40, -0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23, -0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4, -0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, -0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25, -0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41, -0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90, -0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62, -0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f, -0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5, -0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e, -0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, -0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, -0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, -0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, -0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, -0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, -0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, -0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, -0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07, -0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22, -0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, -0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab, -0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0, -0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00, -0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f, -0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12, -0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f, -0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75, -0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b, -0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, -0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, -0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, -0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, -0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, -0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, -0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54, -0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, -0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, -0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, -0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, -0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, -0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08, -0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, -0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0, -0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07, -0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, -0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, -0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, -0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, -0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, -0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, -0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60, -0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f, -0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82, -0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12, -0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20, -0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, -0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, -0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, -0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, -0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, -0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2, -0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, -0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, -0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e, -0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, -0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef, -0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08, -0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80, +0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, +0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, +0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, +0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, +0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, +0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, +0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, +0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, +0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, +0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, +0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, +0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, +0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, +0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, +0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, +0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, +0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, +0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, +0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, +0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, +0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, +0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, +0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, +0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, +0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, +0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, +0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, +0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, +0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, +0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, +0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, +0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, +0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, +0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, +0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, +0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, +0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, +0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, +0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, +0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, +0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, +0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, +0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, +0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, +0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, +0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, +0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, +0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, +0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, +0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, +0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, +0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, +0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, +0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, +0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, +0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, +0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, +0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, +0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, +0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, +0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, +0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, +0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, +0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, +0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, +0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, +0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, +0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, +0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, +0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, +0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, +0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, +0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, +0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, +0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, +0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, +0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, +0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, +0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, +0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, +0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, +0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, +0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, +0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, +0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, +0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, +0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, +0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, +0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, +0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, +0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, +0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, +0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, +0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, +0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, +0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, +0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, +0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, +0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, +0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, +0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, +0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, +0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, +0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, +0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, +0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, +0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, +0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, +0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, +0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, +0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, +0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, +0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, +0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, +0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, +0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, +0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, +0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, +0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, +0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, +0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, +0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, +0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, +0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, +0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, +0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, +0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, +0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, +0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, +0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, +0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, +0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, +0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, +0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, +0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, +0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, +0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, +0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, +0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, +0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, +0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, +0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, +0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, +0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, +0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, +0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, +0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, +0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, +0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, +0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, +0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, +0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, +0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, +0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, +0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, +0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, +0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, +0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, +0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, +0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, +0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, +0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, +0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, +0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, +0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, +0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, +0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, +0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, +0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, +0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, +0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, +0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, +0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, +0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, +0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, +0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, +0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, +0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, +0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, +0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, +0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, +0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, +0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, +0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, +0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, +0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, +0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, +0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, +0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, +0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, +0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, +0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, +0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, +0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, +0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, +0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, +0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, +0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, +0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, +0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, +0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, +0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, +0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, +0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, +0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, +0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, +0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, +0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, +0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, +0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, +0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, +0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, +0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, +0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, +0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, +0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, +0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, +0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, +0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, +0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, +0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, +0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, +0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, +0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, +0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, +0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, +0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, +0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, +0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, +0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, +0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, +0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, +0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, +0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, +0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, +0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, +0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, +0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, +0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, +0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, +0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, +0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, +0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, +0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, +0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, +0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, +0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, +0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, +0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, +0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, +0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, +0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, +0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, +0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, +0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, +0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, +0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, +0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, +0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, +0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, +0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, +0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, +0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, +0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, +0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, +0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, -0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, -0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, +0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, +0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, -0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82, -0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, +0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, +0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, -0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49, +0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, -0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, +0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, -0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, -0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, +0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, +0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, -0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02, -0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7, -0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, -0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, -0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, -0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, -0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, -0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, -0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, -0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, -0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, -0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, -0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, -0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, -0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, -0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, -0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, -0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, -0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, -0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, -0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, -0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, -0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, -0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, -0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, -0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, -0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, -0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, -0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, -0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, -0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, -0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, -0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, -0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, -0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, -0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, -0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, -0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, -0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, -0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, -0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, -0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, -0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, -0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37, -0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06, -0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5, -0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74, -0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff, -0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, -0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7, -0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12, -0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15, -0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74, -0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12, -0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05, -0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06, -0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08, -0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08, -0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f, -0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13, -0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37, -0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24, -0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53, -0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4, -0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19, -0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, -0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9, -0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, -0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24, -0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, -0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18, -0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4, -0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, -0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, -0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16, -0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90, -0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0, -0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, -0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, -0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, -0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, -0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, -0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d, -0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, -0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, -0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, -0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0, -0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, -0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, -0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, -0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75, -0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24, -0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0, -0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, -0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0, -0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08, -0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, -0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75, -0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08, -0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, -0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b, -0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, -0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4, -0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4, -0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, -0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff, -0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc, -0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65, -0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9, -0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, -0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02, -0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34, -0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4, -0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19, -0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd, -0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24, -0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0, -0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, -0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, -0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0, -0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed, -0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, -0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0, -0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, -0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25, -0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04, -0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83, -0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82, -0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, -0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, -0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42, -0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14, -0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95, -0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, -0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, -0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d, -0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, -0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, -0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, -0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80, -0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07, -0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65, -0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, -0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, -0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, -0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, -0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, -0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0, -0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19, -0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90, -0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14, -0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20, -0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, -0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00, -0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00, -0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, -0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, -0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43, -0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43, -0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03, -0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03, -0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, -0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, -0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, -0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90, -0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07, -0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14, -0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9, -0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24, -0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20, -0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14, -0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa, -0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, -0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00, -0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, -0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, -0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, -0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, -0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94, -0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff, -0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, -0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, -0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, -0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58, -0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9, -0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5, -0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, -0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f, -0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, -0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0, -0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, -0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, -0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0, -0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, -0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, -0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa, -0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6, -0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, -0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90, -0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, -0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, -0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, -0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, -0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4, -0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90, -0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46, -0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2, -0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00, -0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, -0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, -0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d, -0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a, -0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13, -0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda, -0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, -0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08, -0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6, -0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, -0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02, -0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90, -0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, -0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83, -0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, -0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07, -0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86, -0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, -0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce, -0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0, -0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65, -0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21, -0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12, -0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef, -0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4, -0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff, -0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14, -0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0, -0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68, -0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb, -0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c, -0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff, -0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc, -0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, -0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, -0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82, -0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, -0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, -0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46, -0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf, -0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3, -0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01, -0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64, -0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, -0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78, -0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12, -0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14, -0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9, -0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06, -0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa, -0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26, -0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80, -0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa, -0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12, -0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0, -0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90, -0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, -0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe, -0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d, -0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d, -0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, -0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, -0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, -0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, -0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, -0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a, -0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78, -0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15, -0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c, -0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8, -0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2, -0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8, -0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, -0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3, -0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42, -0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42, -0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd, -0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41, -0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91, -0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, -0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, -0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, -0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28, -0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, -0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, -0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, -0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, -0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24, -0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, -0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19, -0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, -0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c, -0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75, -0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef, -0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, -0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, -0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, -0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80, -0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3, -0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, -0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e, -0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc, -0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19, -0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, -0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2, -0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12, -0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12, -0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50, -0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5, -0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, -0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d, -0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0, -0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa, -0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, -0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12, -0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0, -0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07, -0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, -0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, -0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30, -0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f, -0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, -0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa, -0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b, -0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75, -0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12, -0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, -0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, -0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa, -0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52, -0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04, -0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65, -0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0, -0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a, -0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, -0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f, -0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78, -0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d, -0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f, -0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, -0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27, -0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71, -0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4, -0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30, -0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14, -0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0, -0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48, -0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00, -0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00, -0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00, -0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9, -0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65, -0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82, -0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94, -0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31, -0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee, -0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, -0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f, -0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05, -0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa, -0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf, -0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff, -0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a, -0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f, -0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00, -0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b, -0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, -0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, -0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, -0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22, -0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef, -0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02, -0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, -0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22, -0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, -0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57, -0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, -0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c, -0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a, -0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02, -0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, -0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4, -0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09, -0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90, -0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, -0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80, -0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90, -0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f, -0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1, -0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16, -0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90, -0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a, -0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, -0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14, -0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, -0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78, -0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, -0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, -0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, -0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02, -0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f, -0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, -0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74, -0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12, -0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20, -0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, -0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, -0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20, -0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04, -0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, -0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35, -0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, -0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a, -0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e, -0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, -0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10, -0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, -0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, -0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, -0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, -0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74, -0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64, -0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, -0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12, -0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, -0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, -0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78, -0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, -0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65, -0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee, -0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a, -0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66, -0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89, -0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78, -0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c, -0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67, -0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, -0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12, -0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8, -0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77, -0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5, -0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0, -0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, -0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, -0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, -0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22, -0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, -0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, -0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff, -0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f, -0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, -0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f, -0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12, -0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22, -0xc2, 0x08, 0x22, +0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, +0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, +0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, +0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, +0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, +0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, +0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, +0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, +0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, +0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, +0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, +0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, +0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, +0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, +0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, +0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, +0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, +0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, +0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, +0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, +0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, +0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, +0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, +0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, +0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, +0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, +0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, +0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, +0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, +0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, +0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, +0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, +0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, +0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, +0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, +0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, +0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, +0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, +0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, +0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, +0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, +0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, +0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, +0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, +0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, +0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, +0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, +0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, +0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, +0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, +0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, +0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, +0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, +0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, +0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, +0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, +0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, +0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, +0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, +0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, +0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, +0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, +0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, +0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, +0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, +0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, +0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, +0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, +0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, +0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, +0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, +0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, +0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, +0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, +0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, +0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, +0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, +0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, +0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, +0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, +0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, +0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, +0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, +0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, +0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, +0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, +0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, +0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, +0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, +0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, +0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, +0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, +0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, +0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, +0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, +0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, +0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, +0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, +0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, +0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, +0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, +0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, +0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, +0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, +0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, +0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, +0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, +0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, +0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, +0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, +0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, +0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, +0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, +0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, +0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, +0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, +0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, +0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, +0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, +0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, +0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, +0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, +0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, +0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, +0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, +0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, +0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, +0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 0x25, 0x82, 0xf5, +0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xf9, +0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 0xe0, 0xfa, 0xa3, +0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, +0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, +0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, +0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, +0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, +0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, +0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, +0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, +0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, +0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, +0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, +0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, +0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, +0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, +0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, +0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, +0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, +0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, +0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, +0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, +0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, +0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, +0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, +0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, +0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, +0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, +0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, +0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, +0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, +0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, +0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, +0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, +0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, +0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, +0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, +0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, +0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, +0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, +0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, +0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, +0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, +0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, +0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, +0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, +0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, +0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, +0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, +0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, +0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, +0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, +0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, +0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, +0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, +0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, +0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, +0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, +0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, +0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, +0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, +0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, +0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, +0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, +0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, +0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, +0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, +0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, +0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, +0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, +0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, +0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, +0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, +0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, +0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, +0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, +0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, +0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, +0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, +0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, +0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, +0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, +0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, +0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, +0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, +0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, +0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, +0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, +0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, +0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, +0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, +0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, +0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, +0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, +0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, +0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, +0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, +0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, +0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, +0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, +0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, +0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, +0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, +0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, +0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, +0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, +0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, +0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, +0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, +0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, +0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, +0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, +0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, +0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, +0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, +0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, +0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, +0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, +0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, +0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, +0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, +0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, +0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, +0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, +0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, +0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, +0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, +0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, +0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, +0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, +0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, +0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, +0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, +0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, +0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, +0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, +0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, +0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, +0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, +0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, +0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, +0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, +0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, +0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, +0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, +0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, +0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, +0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, +0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, +0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, +0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, +0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, +0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, +0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, +0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, +0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, +0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, +0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, +0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, +0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, +0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, +0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, +0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, +0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, +0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, +0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, +0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, +0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, +0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, +0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, +0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, +0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, +0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, +0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, +0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, +0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, +0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, +0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, +0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, +0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, +0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, +0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, +0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, +0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, +0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, +0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, +0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, +0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, +0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, +0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, +0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, +0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, +0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, +0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, +0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, +0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, +0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, +0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, +0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, +0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, +0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, +0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, +0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, +0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, +0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, +0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, +0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, +0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, +0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, +0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, +0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, +0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, +0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, +0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, +0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, +0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, +0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, +0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, +0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, +0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, +0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, +0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, +0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, +0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, +0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, +0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, +0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, +0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, +0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, +0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, +0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, +0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, +0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, +0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, +0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, +0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, +0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, +0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, +0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, +0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, +0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, +0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, +0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, +0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, +0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, +0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, +0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, +0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, +0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, +0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, +0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, +0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, +0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, +0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, +0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, +0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, +0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, +0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, +0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, +0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, +0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, +0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, +0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, +0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, +0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, +0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, +0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, +0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, +0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, +0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, +0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, +0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, +0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, +0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, +0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, +0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, +0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, +0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, +0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, +0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, +0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, +0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, +0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, +0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, +0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, +0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, +0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, +0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, +0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, +0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, +0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, +0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, +0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, +0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, +0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, +0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, +0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, +0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, +0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, +0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, +0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, +0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, +0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, +0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, +0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, +0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, +0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, +0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, +0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, +0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, +0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, +0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, +0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, +0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, +0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, +0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, +0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, +0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, +0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, +0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, +0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, +0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, +0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, +0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, +0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, +0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, +0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, +0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, +0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, +0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, +0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, +0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, +0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, +0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, +0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, +0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, +0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, +0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, +0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, +0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, +0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, +0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, +0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, +0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, +0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, +0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, +0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, +0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, +0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, +0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, +0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, +0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, +0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, +0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, +0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, +0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, +0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, +0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, +0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, +0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, +0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, }; #undef IMAGE_VERSION_NAME diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index f4567f166..e7ffe0240 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -14,22 +14,12 @@ #ifndef IO_TABLES_H #define IO_TABLES_H -static struct usb_device_id edgeport_1port_id_table [] = { - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) }, - { } -}; - static 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) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) }, { } }; @@ -41,12 +31,9 @@ static struct usb_device_id edgeport_4port_id_table [] = { { 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_22I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) }, { } }; @@ -54,9 +41,9 @@ static 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) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) }, { } }; @@ -69,7 +56,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) }, { 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_8_DUAL_CPU) }, @@ -77,51 +63,18 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, id_table_combined); -static struct usb_serial_device_type edgeport_1port_device = { - .owner = THIS_MODULE, - .name = "Edgeport 1 port adapter", - .short_name = "edgeport_1", - .id_table = edgeport_1port_id_table, - .num_interrupt_in = 1, - .num_bulk_in = 1, - .num_bulk_out = 1, - .num_ports = 1, - .open = edge_open, - .close = edge_close, - .throttle = edge_throttle, - .unthrottle = edge_unthrottle, - .attach = edge_startup, - .shutdown = edge_shutdown, - .ioctl = edge_ioctl, - .set_termios = edge_set_termios, - .tiocmget = edge_tiocmget, - .tiocmset = edge_tiocmset, - .write = edge_write, - .write_room = edge_write_room, - .chars_in_buffer = edge_chars_in_buffer, - .break_ctl = edge_break, -}; - static struct usb_serial_device_type edgeport_2port_device = { .owner = THIS_MODULE, .name = "Edgeport 2 port adapter", @@ -145,6 +98,9 @@ static struct usb_serial_device_type edgeport_2port_device = { .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, .break_ctl = edge_break, + .read_int_callback = edge_interrupt_callback, + .read_bulk_callback = edge_bulk_in_callback, + .write_bulk_callback = edge_bulk_out_data_callback, }; static struct usb_serial_device_type edgeport_4port_device = { @@ -170,6 +126,9 @@ static struct usb_serial_device_type edgeport_4port_device = { .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, .break_ctl = edge_break, + .read_int_callback = edge_interrupt_callback, + .read_bulk_callback = edge_bulk_in_callback, + .write_bulk_callback = edge_bulk_out_data_callback, }; static struct usb_serial_device_type edgeport_8port_device = { @@ -195,6 +154,9 @@ static struct usb_serial_device_type edgeport_8port_device = { .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, .break_ctl = edge_break, + .read_int_callback = edge_interrupt_callback, + .read_bulk_callback = edge_bulk_in_callback, + .write_bulk_callback = edge_bulk_out_data_callback, }; #endif diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 6b821b6ed..bd86f7e7c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -10,7 +10,11 @@ * (at your option) any later version. * * Supports the following devices: - * EP/1 EP/2 EP/4 + * EP/1 EP/2 EP/4 EP/21 EP/22 EP/221 EP/42 EP/421 WATCHPORT + * + * For questions or problems with this driver, contact Inside Out + * Networks technical support, or Peter Berger , + * or Al Borchers . * * Version history: * @@ -34,18 +38,18 @@ #include #include #include +#include #include + #include "usb-serial.h" #include "io_16654.h" #include "io_usbvend.h" #include "io_ti.h" -static int debug; - /* * Version Information */ -#define DRIVER_VERSION "v0.2" +#define DRIVER_VERSION "v0.7" #define DRIVER_AUTHOR "Greg Kroah-Hartman and David Iacovelli" #define DRIVER_DESC "Edgeport USB Serial Driver" @@ -73,6 +77,16 @@ struct edgeport_uart_buf_desc { #define TI_MODE_DOWNLOAD 2 // Made it to download mode #define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode +/* read urb state */ +#define EDGE_READ_URB_RUNNING 0 +#define EDGE_READ_URB_STOPPING 1 +#define EDGE_READ_URB_STOPPED 2 + +#define EDGE_LOW_LATENCY 1 +#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */ + +#define EDGE_OUT_BUF_SIZE 1024 + /* Product information read from the Edgeport */ struct product_info @@ -81,6 +95,13 @@ struct product_info __u8 hardware_type; // Type of hardware } __attribute__((packed)); +/* circular buffer */ +struct edge_buf { + unsigned int buf_size; + char *buf_buf; + char *buf_get; + char *buf_put; +}; struct edgeport_port { __u16 uart_base; @@ -102,12 +123,18 @@ struct edgeport_port { happen */ struct edgeport_serial *edge_serial; struct usb_serial_port *port; + __u8 bUartMode; /* Port type, 0: RS232, etc. */ + spinlock_t ep_lock; + int ep_read_urb_state; + int ep_write_urb_in_use; + struct edge_buf *ep_out_buf; }; struct edgeport_serial { struct product_info product_info; u8 TI_I2C_Type; // Type of I2C in UMP u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode + struct semaphore es_sem; int num_ports_open; struct usb_serial *serial; }; @@ -116,6 +143,21 @@ struct edgeport_serial { /* Devices that this driver supports */ static struct usb_device_id edgeport_1port_id_table [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, { } }; @@ -124,34 +166,50 @@ static struct usb_device_id edgeport_2port_id_table [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, +// The 4-port shows up as two 2-port devices + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, { } }; /* Devices that this driver supports */ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, - { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, { } }; @@ -168,12 +226,33 @@ static struct usb_driver io_driver = { static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion; +static int debug; + static int TIStayInBootMode = 0; +static int low_latency = EDGE_LOW_LATENCY; +static int closing_wait = EDGE_CLOSING_WAIT; static int ignore_cpu_rev = 0; +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length); + +static void stop_read(struct edgeport_port *edge_port); +static int restart_read(struct edgeport_port *edge_port); static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_send(struct usb_serial_port *port); + +/* circular buffer */ +static struct edge_buf *edge_buf_alloc(unsigned int size); +static void edge_buf_free(struct edge_buf *eb); +static void edge_buf_clear(struct edge_buf *eb); +static unsigned int edge_buf_data_avail(struct edge_buf *eb); +static unsigned int edge_buf_space_avail(struct edge_buf *eb); +static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, + unsigned int count); +static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, + unsigned int count); + static int TIReadVendorRequestSync (struct usb_device *dev, __u8 request, @@ -249,7 +328,6 @@ static int TIWriteCommandSync (struct usb_device *dev, __u8 command, } - /* clear tx/rx buffers and fifo in TI UMP */ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask) { @@ -278,7 +356,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address, { int status = 0; __u8 read_length; - __u16 be_start_address; + __be16 be_start_address; dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length); @@ -299,7 +377,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address, status = TIReadVendorRequestSync (dev, UMPC_MEMORY_READ, // Request (__u16)address_type, // wValue (Address type) - be_start_address, // wIndex (Address to read) + (__force __u16)be_start_address, // wIndex (Address to read) buffer, // TransferBuffer read_length); // TransferBufferLength @@ -395,7 +473,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address { int status = 0; int write_length; - __u16 be_start_address; + __be16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ @@ -413,7 +491,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address status = TISendVendorRequestSync (serial->serial->dev, UMPC_MEMORY_WRITE, // Request (__u16)address_type, // wValue - be_start_address, // wIndex + (__force __u16)be_start_address, // wIndex buffer, // TransferBuffer write_length); if (status) { @@ -440,11 +518,11 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address status = TISendVendorRequestSync (serial->serial->dev, UMPC_MEMORY_WRITE, // Request (__u16)address_type, // wValue - be_start_address, // wIndex + (__force __u16)be_start_address, // wIndex buffer, // TransferBuffer write_length); // TransferBufferLength if (status) { - dbg ("%s - ERROR %d", __FUNCTION__, status); + dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status); return status; } @@ -518,74 +596,54 @@ exit_is_tx_active: return bytes_left; } -static void TIChasePort(struct edgeport_port *port) +static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush) { - int loops; - int last_count; - int write_size; - -restart_tx_loop: - // Base the LoopTime on the baud rate - if (port->baud_rate == 0) - port->baud_rate = 1200; - - write_size = port->tx.count; - loops = max(100, (100*write_size)/(port->baud_rate/10)); - dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__, - write_size, port->baud_rate, loops); - - while (1) { - // Save Last count - last_count = port->tx.count; - - dbg ("%s - Tx Buffer Size = %d loops = %d", __FUNCTION__, - last_count, loops); - - /* Is the Edgeport Buffer empty? */ - if (port->tx.count == 0) + int baud_rate; + struct tty_struct *tty = port->port->tty; + wait_queue_t wait; + unsigned long flags; + + if (!timeout) + timeout = (HZ*EDGE_CLOSING_WAIT)/100; + + /* wait for data to drain from the buffer */ + spin_lock_irqsave(&port->ep_lock, flags); + init_waitqueue_entry(&wait, current); + add_wait_queue(&tty->write_wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (edge_buf_data_avail(port->ep_out_buf) == 0 + || timeout == 0 || signal_pending(current) + || !usb_get_intfdata(port->port->serial->interface)) /* disconnect */ + break; + spin_unlock_irqrestore(&port->ep_lock, flags); + timeout = schedule_timeout(timeout); + spin_lock_irqsave(&port->ep_lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&tty->write_wait, &wait); + if (flush) + edge_buf_clear(port->ep_out_buf); + spin_unlock_irqrestore(&port->ep_lock, flags); + + /* wait for data to drain from the device */ + timeout += jiffies; + while ((long)(jiffies - timeout) < 0 && !signal_pending(current) + && usb_get_intfdata(port->port->serial->interface)) { /* not disconnected */ + if (!TIIsTxActive(port)) break; - - /* Block the thread for 10ms */ msleep(10); - - if (last_count == port->tx.count) { - /* No activity.. count down. */ - --loops; - if (loops == 0) { - dbg ("%s - Wait for TxEmpty - TIMEOUT", - __FUNCTION__); - return; - } - } else { - /* Reset timeout value back to a minimum of 1 second */ - dbg ("%s - Wait for TxEmpty Reset Count", __FUNCTION__); - goto restart_tx_loop; - } } - dbg ("%s - Local Tx Buffer Empty -- Waiting for TI UMP to EMPTY X/Y and FIFO", - __FUNCTION__); - - write_size = TIIsTxActive (port); - loops = max(50, (100*write_size)/(port->baud_rate/10)); - dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__, - write_size, port->baud_rate, loops); - - while (1) { - /* This function takes 4 ms; */ - if (!TIIsTxActive (port)) { - /* Delay a few char times */ - msleep(50); - dbg ("%s - Empty", __FUNCTION__); - return; - } + /* disconnected */ + if (!usb_get_intfdata(port->port->serial->interface)) + return; - --loops; - if (loops == 0) { - dbg ("%s - TIMEOUT", __FUNCTION__); - return; - } - } + /* wait one more character time, based on baud rate */ + /* (TIIsTxActive doesn't seem to wait for the last byte) */ + if ((baud_rate=port->baud_rate) == 0) + baud_rate = 50; + msleep(max(1,(10000+baud_rate-1)/baud_rate)); } static int TIChooseConfiguration (struct usb_device *dev) @@ -696,6 +754,7 @@ static int TiValidateI2cImage (struct edgeport_serial *serial) struct ti_i2c_desc *rom_desc; int start_address = 2; __u8 *buffer; + __u16 ttype; rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); if (!rom_desc) { @@ -709,12 +768,12 @@ static int TiValidateI2cImage (struct edgeport_serial *serial) return -ENOMEM; } - // Read the first byte (Signature0) must be 0x52 + // Read the first byte (Signature0) must be 0x52 or 0x10 status = TIReadRom (serial, 0, 1, buffer); if (status) goto ExitTiValidateI2cImage; - if (*buffer != 0x52) { + if (*buffer != UMP5152 && *buffer != UMP3410) { dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__); status = -ENODEV; goto ExitTiValidateI2cImage; @@ -738,7 +797,9 @@ static int TiValidateI2cImage (struct edgeport_serial *serial) dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type); // Skip type 2 record - if ((rom_desc->Type & 0x0f) != I2C_DESC_TYPE_FIRMWARE_BASIC) { + ttype = rom_desc->Type & 0x0f; + if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC + && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) { // Read the descriptor data status = TIReadRom(serial, start_address+sizeof(struct ti_i2c_desc), @@ -848,7 +909,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev) memcpy (buffer + sizeof(struct ti_i2c_firmware_rec), &PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)], - img_header->Length); + le16_to_cpu(img_header->Length)); for (i=0; i < buffer_size; i++) { cs = (__u8)(cs + buffer[i]); @@ -886,7 +947,7 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial) dbg ("%s - read 2 status error = %d", __FUNCTION__, status); else dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); - if ((!status) && data == 0x52) { + if ((!status) && (data == UMP5152 || data == UMP3410)) { dbg ("%s - ROM_TYPE_II", __FUNCTION__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; return 0; @@ -903,7 +964,7 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial) dbg ("%s - read 3 status error = %d", __FUNCTION__, status); else dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); - if ((!status) && data == 0x52) { + if ((!status) && (data == UMP5152 || data == UMP3410)) { dbg ("%s - ROM_TYPE_III", __FUNCTION__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; return 0; @@ -991,7 +1052,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) interface = &serial->serial->interface->cur_altsetting->desc; if (!interface) { - dev_err (&serial->serial->dev->dev, "%s - no interface set, error!", __FUNCTION__); + dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__); return -ENODEV; } @@ -1257,7 +1318,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) dbg ("%s - Update complete 0x%x", __FUNCTION__, status); if (status) { - dbg ("%s - UMPC_COPY_DNLD_TO_I2C failed", __FUNCTION__); + dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__); kfree (rom_desc); kfree (ti_manuf_desc); return status; @@ -1364,7 +1425,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial) header = (struct ti_i2c_image_header *)buffer; // update length and checksum after padding - header->Length = (__u16)(buffer_size - sizeof(struct ti_i2c_image_header)); + header->Length = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header))); header->CheckSum = cs; // Download the operational code @@ -1568,6 +1629,7 @@ static __u8 MapLineStatus (__u8 ti_lsr) static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) { struct async_icount *icount; + struct tty_struct *tty; dbg ("%s - %02x", __FUNCTION__, msr); @@ -1589,6 +1651,17 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) /* Save the new modem status */ edge_port->shadow_msr = msr & 0xf0; + tty = edge_port->port->tty; + /* handle CTS flow control */ + if (tty && C_CRTSCTS(tty)) { + if (msr & EDGEPORT_MSR_CTS) { + tty->hw_stopped = 0; + tty_wakeup(tty); + } else { + tty->hw_stopped = 1; + } + } + return; } @@ -1610,10 +1683,8 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 } /* Place LSR data byte into Rx buffer */ - if (lsr_data && edge_port->port->tty) { - tty_insert_flip_char(edge_port->port->tty, data, 0); - tty_flip_buffer_push(edge_port->port->tty); - } + if (lsr_data && edge_port->port->tty) + edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); /* update input line counters */ icount = &edge_port->icount; @@ -1654,7 +1725,7 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs) dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status); goto exit; } @@ -1723,21 +1794,31 @@ static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; - int status; - int i; + int status = 0; int port_number; dbg("%s", __FUNCTION__); - if (urb->status) { - dbg ("%s - nonzero read bulk status received: %d", - __FUNCTION__, urb->status); + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + return; + default: + dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n", + __FUNCTION__, urb->status ); + } - if (urb->status == -EPIPE) { - /* clear any problem that might have happened on this pipe */ - usb_clear_halt (edge_port->port->serial->dev, urb->pipe); - goto exit; - } + if (urb->status == -EPIPE) + goto exit; + + if (urb->status) { + dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__); return; } @@ -1760,57 +1841,78 @@ static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs) if (edge_port->close_pending) { dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__); } else { - for (i = 0; i < urb->actual_length ; ++i) { - /* if we insert more than TTY_FLIPBUF_SIZE characters, - * we drop them. */ - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - /* this doesn't actually push the data through unless - * tty->low_latency is set */ - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); + edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length); } edge_port->icount.rx += urb->actual_length; } exit: - /* continue always trying to read */ - status = usb_submit_urb (urb, GFP_ATOMIC); + /* continue read unless stopped */ + spin_lock(&edge_port->ep_lock); + if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) { + urb->dev = edge_port->port->serial->dev; + status = usb_submit_urb(urb, GFP_ATOMIC); + } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) { + edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED; + } + spin_unlock(&edge_port->ep_lock); if (status) dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", __FUNCTION__, status); } +static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) +{ + int cnt; + + do { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __FUNCTION__, length); + return; + } + } + cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); + memcpy(tty->flip.char_buf_ptr, data, cnt); + memset(tty->flip.flag_buf_ptr, 0, cnt); + tty->flip.char_buf_ptr += cnt; + tty->flip.flag_buf_ptr += cnt; + tty->flip.count += cnt; + data += cnt; + length -= cnt; + } while (length > 0); + + tty_flip_buffer_push(tty); +} + static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct tty_struct *tty; + struct edgeport_port *edge_port = usb_get_serial_port_data(port); dbg ("%s - port %d", __FUNCTION__, port->number); - if (urb->status) { - dbg ("%s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); + edge_port->ep_write_urb_in_use = 0; - if (urb->status == -EPIPE) { - /* clear any problem that might have happened on this pipe */ - usb_clear_halt (port->serial->dev, urb->pipe); - } + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; + default: + dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n", + __FUNCTION__, urb->status); } - tty = port->tty; - if (tty) { - /* let the tty driver wakeup if it has a special write_wakeup function */ - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - (tty->ldisc.write_wakeup)(tty); - } - - /* tell the tty driver that something has changed */ - wake_up_interruptible(&tty->write_wait); - } + /* send any buffered data */ + edge_send(port); } static int edge_open (struct usb_serial_port *port, struct file * filp) @@ -1829,11 +1931,8 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) if (edge_port == NULL) return -ENODEV; - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates (like with OHCI) data - can get lost. */ if (port->tty) - port->tty->low_latency = 1; + port->tty->low_latency = low_latency; port_number = port->number - port->serial->minor; switch (port_number) { @@ -1860,8 +1959,11 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) /* turn off loopback */ status = TIClearLoopBack (edge_port); - if (status) + if (status) { + dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n", + __FUNCTION__, status); return status; + } /* set up the port settings */ edge_set_termios (port, NULL); @@ -1887,8 +1989,10 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) open_settings, NULL, 0); - if (status) + if (status) { + dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status); return status; + } /* Start the DMA? */ status = TIWriteCommandSync (dev, @@ -1897,13 +2001,17 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) 0, NULL, 0); - if (status) + if (status) { + dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status); return status; + } /* Clear TX and RX buffers in UMP */ status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); - if (status) + if (status) { + dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status); return status; + } /* Read Initial MSR */ status = TIReadVendorRequestSync (dev, @@ -1912,18 +2020,27 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address) &edge_port->shadow_msr, // TransferBuffer 1); // TransferBufferLength - if (status) + if (status) { + dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status); return status; + } dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); + /* Set Initial MCR */ + edge_port->shadow_mcr = MCR_RTS | MCR_DTR; + dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr); + edge_serial = edge_port->edge_serial; + if (down_interruptible(&edge_serial->es_sem)) + return -ERESTARTSYS; if (edge_serial->num_ports_open == 0) { /* we are the first port to be opened, let's post the interrupt urb */ urb = edge_serial->serial->port[0]->interrupt_in_urb; if (!urb) { dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__); - return -EINVAL; + status = -EINVAL; + goto up_es_sem; } urb->complete = edge_interrupt_callback; urb->context = edge_serial; @@ -1931,7 +2048,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) status = usb_submit_urb (urb, GFP_KERNEL); if (status) { dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status); - return status; + goto up_es_sem; } } @@ -1946,25 +2063,34 @@ static int edge_open (struct usb_serial_port *port, struct file * filp) urb = port->read_urb; if (!urb) { dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__); - return -EINVAL; + status = -EINVAL; + goto unlink_int_urb; } + edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; urb->complete = edge_bulk_in_callback; urb->context = edge_port; urb->dev = dev; status = usb_submit_urb (urb, GFP_KERNEL); if (status) { dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status); - return status; + goto unlink_int_urb; } ++edge_serial->num_ports_open; dbg("%s - exited", __FUNCTION__); - return 0; + goto up_es_sem; + +unlink_int_urb: + if (edge_port->edge_serial->num_ports_open == 0) + usb_kill_urb(port->serial->port[0]->interrupt_in_urb); +up_es_sem: + up(&edge_serial->es_sem); + return status; } -static void edge_close (struct usb_serial_port *port, struct file * filp) +static void edge_close (struct usb_serial_port *port, struct file *filp) { struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; @@ -1982,10 +2108,12 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) * this flag and dump add read data */ edge_port->close_pending = 1; - /* chase the port close */ - TIChasePort (edge_port); + /* chase the port close and flush */ + TIChasePort (edge_port, (HZ*closing_wait)/100, 1); - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->write_urb); + edge_port->ep_write_urb_in_use = 0; /* assuming we can still talk to the device, * send a close port command to it */ @@ -1997,21 +2125,23 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) 0, NULL, 0); + down(&edge_serial->es_sem); --edge_port->edge_serial->num_ports_open; if (edge_port->edge_serial->num_ports_open <= 0) { /* last port is now closed, let's shut down our interrupt urb */ - usb_unlink_urb (port->serial->port[0]->interrupt_in_urb); + usb_kill_urb(port->serial->port[0]->interrupt_in_urb); edge_port->edge_serial->num_ports_open = 0; } + up(&edge_serial->es_sem); edge_port->close_pending = 0; dbg("%s - exited", __FUNCTION__); } -static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count) +static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); - int result; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -2024,21 +2154,46 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; - - if (port->write_urb->status == -EINPROGRESS) { - dbg ("%s - already writing", __FUNCTION__); - return 0; + + spin_lock_irqsave(&edge_port->ep_lock, flags); + count = edge_buf_put(edge_port->ep_out_buf, data, count); + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + + edge_send(port); + + return count; +} + +static void edge_send(struct usb_serial_port *port) +{ + int count, result; + struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct tty_struct *tty = port->tty; + unsigned long flags; + + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&edge_port->ep_lock, flags); + + if (edge_port->ep_write_urb_in_use) { + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + return; } - count = min (count, port->bulk_out_size); + count = edge_buf_get(edge_port->ep_out_buf, + port->write_urb->transfer_buffer, + port->bulk_out_size); - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, data, count)) - return -EFAULT; - } else { - memcpy (port->write_urb->transfer_buffer, data, count); + if (count == 0) { + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + return; } + edge_port->ep_write_urb_in_use = 1; + + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); /* set up our urb */ @@ -2051,33 +2206,38 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) + if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); - else - result = count; - - if (result > 0) + edge_port->ep_write_urb_in_use = 0; + // TODO: reschedule edge_send + } else { edge_port->icount.tx += count; + } - return result; + /* wakeup any process waiting for writes to complete */ + /* there is now more room in the buffer for new writes */ + if (tty) { + /* let the tty driver wakeup if it has a special write_wakeup function */ + tty_wakeup(tty); + } } static int edge_write_room (struct usb_serial_port *port) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); int room = 0; + unsigned long flags; - dbg("%s", __FUNCTION__); + dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; - - dbg("%s - port %d", __FUNCTION__, port->number); - if (port->write_urb->status != -EINPROGRESS) - room = port->bulk_out_size; + spin_lock_irqsave(&edge_port->ep_lock, flags); + room = edge_buf_space_avail(edge_port->ep_out_buf); + spin_unlock_irqrestore(&edge_port->ep_lock, flags); dbg("%s - returns %d", __FUNCTION__, room); return room; @@ -2087,18 +2247,18 @@ static int edge_chars_in_buffer (struct usb_serial_port *port) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; + unsigned long flags; - dbg("%s", __FUNCTION__); + dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; - dbg("%s - port %d", __FUNCTION__, port->number); - - if (port->write_urb->status == -EINPROGRESS) - chars = port->write_urb->transfer_buffer_length; + spin_lock_irqsave(&edge_port->ep_lock, flags); + chars = edge_buf_data_avail(edge_port->ep_out_buf); + spin_unlock_irqrestore(&edge_port->ep_lock, flags); dbg ("%s - returns %d", __FUNCTION__, chars); return chars; @@ -2120,21 +2280,21 @@ static void edge_throttle (struct usb_serial_port *port) dbg ("%s - no tty available", __FUNCTION__); return; } + /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); - status = edge_write (port, 0, &stop_char, 1); + status = edge_write (port, &stop_char, 1); if (status <= 0) { - return; + dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status); } } - /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios->c_cflag & CRTSCTS) { - status = TIClearRts (edge_port); - } + /* if we are implementing RTS/CTS, stop reads */ + /* and the Edgeport will clear the RTS line */ + if (C_CRTSCTS(tty)) + stop_read(edge_port); - usb_unlink_urb (port->read_urb); } static void edge_unthrottle (struct usb_serial_port *port) @@ -2157,31 +2317,63 @@ static void edge_unthrottle (struct usb_serial_port *port) /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); - status = edge_write (port, 0, &start_char, 1); + status = edge_write (port, &start_char, 1); if (status <= 0) { - return; + dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status); } } - /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios->c_cflag & CRTSCTS) { - status = TISetRts (edge_port); + /* if we are implementing RTS/CTS, restart reads */ + /* are the Edgeport will assert the RTS line */ + if (C_CRTSCTS(tty)) { + status = restart_read(edge_port); + if (status) + dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status); } - port->read_urb->dev = port->serial->dev; - status = usb_submit_urb (port->read_urb, GFP_ATOMIC); - if (status) { - dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status); - } } +static void stop_read(struct edgeport_port *edge_port) +{ + unsigned long flags; + + spin_lock_irqsave(&edge_port->ep_lock, flags); + + if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) + edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPING; + edge_port->shadow_mcr &= ~MCR_RTS; + + spin_unlock_irqrestore(&edge_port->ep_lock, flags); +} + +static int restart_read(struct edgeport_port *edge_port) +{ + struct urb *urb; + int status = 0; + unsigned long flags; + + spin_lock_irqsave(&edge_port->ep_lock, flags); + + if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPED) { + urb = edge_port->port->read_urb; + urb->complete = edge_bulk_in_callback; + urb->context = edge_port; + urb->dev = edge_port->port->serial->dev; + status = usb_submit_urb(urb, GFP_KERNEL); + } + edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; + edge_port->shadow_mcr |= MCR_RTS; + + spin_unlock_irqrestore(&edge_port->ep_lock, flags); + + return status; +} static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) { struct ump_uart_config *config; struct tty_struct *tty; int baud; - int round; unsigned cflag; int status; int port_number = edge_port->port->number - edge_port->port->serial->minor; @@ -2208,7 +2400,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio /* These flags must be set */ config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT; config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR; - config->bUartMode = 0; + config->bUartMode = (__u8)(edge_port->bUartMode); switch (cflag & CSIZE) { case CS5: @@ -2260,6 +2452,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio dbg("%s - RTS/CTS is enabled", __FUNCTION__); } else { dbg("%s - RTS/CTS is disabled", __FUNCTION__); + tty->hw_stopped = 0; + restart_read(edge_port); } /* if we are implementing XON/XOFF, set the start and stop character in the device */ @@ -2292,10 +2486,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio /* pick a default, any default... */ baud = 9600; } - config->wBaudRate = (__u16)(461550L / baud); - round = 4615500L / baud; - if ((round - (config->wBaudRate * 10)) >= 5) - config->wBaudRate++; + edge_port->baud_rate = baud; + config->wBaudRate = (__u16)((461550L + baud/2) / baud); dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate); @@ -2342,20 +2534,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_ cflag = tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + if (cflag == old_termios->c_cflag && + tty->termios->c_iflag == old_termios->c_iflag) { dbg ("%s - nothing to change", __FUNCTION__); return; } } dbg("%s - clfag %08x iflag %08x", __FUNCTION__, - tty->termios->c_cflag, - RELEVANT_IFLAG(tty->termios->c_iflag)); + tty->termios->c_cflag, tty->termios->c_iflag); if (old_termios) { dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, - old_termios->c_cflag, - RELEVANT_IFLAG(old_termios->c_iflag)); + old_termios->c_cflag, old_termios->c_iflag); } dbg("%s - port %d", __FUNCTION__, port->number); @@ -2371,7 +2561,7 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); @@ -2400,7 +2590,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig static int edge_tiocmget(struct usb_serial_port *port, struct file *file) { - struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int result = 0; unsigned int msr; unsigned int mcr; @@ -2439,7 +2629,7 @@ static int get_serial_info (struct edgeport_port *edge_port, struct serial_struc tmp.xmit_fifo_size = edge_port->port->bulk_out_size; tmp.baud_base = 9600; tmp.close_delay = 5*HZ; - tmp.closing_wait = 30*HZ; + tmp.closing_wait = closing_wait; // tmp.custom_divisor = state->custom_divisor; // tmp.hub6 = state->hub6; // tmp.io_type = state->io_type; @@ -2520,7 +2710,7 @@ static void edge_break (struct usb_serial_port *port, int break_state) dbg ("%s - state = %d", __FUNCTION__, break_state); /* chase the port close */ - TIChasePort (edge_port); + TIChasePort (edge_port, 0, 0); if (break_state == -1) { status = TISetBreak (edge_port); @@ -2550,6 +2740,7 @@ static int edge_startup (struct usb_serial *serial) return -ENOMEM; } memset (edge_serial, 0, sizeof(struct edgeport_serial)); + sema_init(&edge_serial->es_sem, 1); edge_serial->serial = serial; usb_set_serial_data(serial, edge_serial); @@ -2564,25 +2755,49 @@ static int edge_startup (struct usb_serial *serial) edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); - return -ENOMEM; + goto cleanup; } memset (edge_port, 0, sizeof(struct edgeport_port)); + spin_lock_init(&edge_port->ep_lock); + edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); + if (edge_port->ep_out_buf == NULL) { + dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); + kfree(edge_port); + goto cleanup; + } edge_port->port = serial->port[i]; edge_port->edge_serial = edge_serial; usb_set_serial_port_data(serial->port[i], edge_port); + edge_port->bUartMode = 0; /* Default is RS232 */ } return 0; + +cleanup: + for (--i; i>=0; --i) { + edge_port = usb_get_serial_port_data(serial->port[i]); + edge_buf_free(edge_port->ep_out_buf); + kfree(edge_port); + usb_set_serial_port_data(serial->port[i], NULL); + } + kfree (edge_serial); + usb_set_serial_data(serial, NULL); + return -ENOMEM; } static void edge_shutdown (struct usb_serial *serial) { int i; + struct edgeport_port *edge_port; dbg ("%s", __FUNCTION__); for (i=0; i < serial->num_ports; ++i) { - kfree (usb_get_serial_port_data(serial->port[i])); + edge_port = usb_get_serial_port_data(serial->port[i]); + if (edge_port) { + edge_buf_free(edge_port->ep_out_buf); + kfree(edge_port); + } usb_set_serial_port_data(serial->port[i], NULL); } kfree (usb_get_serial_data(serial)); @@ -2590,6 +2805,185 @@ static void edge_shutdown (struct usb_serial *serial) } +/* Circular Buffer */ + +/* + * edge_buf_alloc + * + * Allocate a circular buffer and all associated memory. + */ + +static struct edge_buf *edge_buf_alloc(unsigned int size) +{ + struct edge_buf *eb; + + + if (size == 0) + return NULL; + + eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL); + if (eb == NULL) + return NULL; + + eb->buf_buf = kmalloc(size, GFP_KERNEL); + if (eb->buf_buf == NULL) { + kfree(eb); + return NULL; + } + + eb->buf_size = size; + eb->buf_get = eb->buf_put = eb->buf_buf; + + return eb; +} + + +/* + * edge_buf_free + * + * Free the buffer and all associated memory. + */ + +void edge_buf_free(struct edge_buf *eb) +{ + if (eb != NULL) { + if (eb->buf_buf != NULL) + kfree(eb->buf_buf); + kfree(eb); + } +} + + +/* + * edge_buf_clear + * + * Clear out all data in the circular buffer. + */ + +static void edge_buf_clear(struct edge_buf *eb) +{ + if (eb != NULL) + eb->buf_get = eb->buf_put; + /* equivalent to a get of all data available */ +} + + +/* + * edge_buf_data_avail + * + * Return the number of bytes of data available in the circular + * buffer. + */ + +static unsigned int edge_buf_data_avail(struct edge_buf *eb) +{ + if (eb != NULL) + return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size); + else + return 0; +} + + +/* + * edge_buf_space_avail + * + * Return the number of bytes of space available in the circular + * buffer. + */ + +static unsigned int edge_buf_space_avail(struct edge_buf *eb) +{ + if (eb != NULL) + return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size); + else + return 0; +} + + +/* + * edge_buf_put + * + * Copy data data from a user buffer and put it into the circular buffer. + * Restrict to the amount of space available. + * + * Return the number of bytes copied. + */ + +static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, + unsigned int count) +{ + unsigned int len; + + + if (eb == NULL) + return 0; + + len = edge_buf_space_avail(eb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = eb->buf_buf + eb->buf_size - eb->buf_put; + if (count > len) { + memcpy(eb->buf_put, buf, len); + memcpy(eb->buf_buf, buf+len, count - len); + eb->buf_put = eb->buf_buf + count - len; + } else { + memcpy(eb->buf_put, buf, count); + if (count < len) + eb->buf_put += count; + else /* count == len */ + eb->buf_put = eb->buf_buf; + } + + return count; +} + + +/* + * edge_buf_get + * + * Get data from the circular buffer and copy to the given buffer. + * Restrict to the amount of data available. + * + * Return the number of bytes copied. + */ + +static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, + unsigned int count) +{ + unsigned int len; + + + if (eb == NULL) + return 0; + + len = edge_buf_data_avail(eb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = eb->buf_buf + eb->buf_size - eb->buf_get; + if (count > len) { + memcpy(buf, eb->buf_get, len); + memcpy(buf+len, eb->buf_buf, count - len); + eb->buf_get = eb->buf_buf + count - len; + } else { + memcpy(buf, eb->buf_get, count); + if (count < len) + eb->buf_get += count; + else /* count == len */ + eb->buf_get = eb->buf_buf; + } + + return count; +} + + static struct usb_serial_device_type edgeport_1port_device = { .owner = THIS_MODULE, .name = "Edgeport TI 1 port adapter", @@ -2613,6 +3007,9 @@ static struct usb_serial_device_type edgeport_1port_device = { .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, .break_ctl = edge_break, + .read_int_callback = edge_interrupt_callback, + .read_bulk_callback = edge_bulk_in_callback, + .write_bulk_callback = edge_bulk_out_callback, }; static struct usb_serial_device_type edgeport_2port_device = { @@ -2638,6 +3035,9 @@ static struct usb_serial_device_type edgeport_2port_device = { .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, .break_ctl = edge_break, + .read_int_callback = edge_interrupt_callback, + .read_bulk_callback = edge_bulk_in_callback, + .write_bulk_callback = edge_bulk_out_callback, }; @@ -2681,6 +3081,12 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); +module_param(low_latency, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(low_latency, "Low latency enabled or not"); + +module_param(closing_wait, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); + module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index 26a8c5a18..8c1fa5e72 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h @@ -18,14 +18,6 @@ #if !defined(_USBVEND_H) #define _USBVEND_H -#ifndef __KERNEL__ -#include "ionprag.h" /* Extra I/O Networks pragmas */ - -#include - -#include "iondef.h" /* Standard I/O Networks definitions */ -#endif - /************************************************************************ * * D e f i n e s / T y p e d e f s @@ -37,6 +29,7 @@ // #define USB_VENDOR_ID_ION 0x1608 // Our VID +#define USB_VENDOR_ID_TI 0x0451 // TI VID // // Definitions of USB product IDs (PID) @@ -48,36 +41,41 @@ // ION-device OEM IDs #define ION_OEM_ID_ION 0 // 00h Inside Out Networks -#define ION_OEM_ID_NLYNX 1 // 01h NLynx Systems +#define ION_OEM_ID_NLYNX 1 // 01h NLynx Systems #define ION_OEM_ID_GENERIC 2 // 02h Generic OEM #define ION_OEM_ID_MAC 3 // 03h Mac Version #define ION_OEM_ID_MEGAWOLF 4 // 04h Lupusb OEM Mac version (MegaWolf) #define ION_OEM_ID_MULTITECH 5 // 05h Multitech Rapidports +#define ION_OEM_ID_AGILENT 6 // 06h AGILENT board + - // ION-device Device IDs -// Product IDs - assigned to match middle digit of serial number +// Product IDs - assigned to match middle digit of serial number (No longer true) +#define ION_DEVICE_ID_80251_NETCHIP 0x020 // This bit is set in the PID if this edgeport hardware$ + // is based on the 80251+Netchip. -// The ION_DEVICE_ID_GENERATION_2 bit (0x20) will be ORed into the existing edgeport -// PIDs to identify 80251+Netchip hardware. This will guarantee that if a second -// generation edgeport device is plugged into a PC with an older (pre 2.0) driver, -// it will not enumerate. +#define ION_DEVICE_ID_GENERATION_1 0x00 // Value for 930 based edgeports +#define ION_DEVICE_ID_GENERATION_2 0x01 // Value for 80251+Netchip. +#define ION_DEVICE_ID_GENERATION_3 0x02 // Value for Texas Instruments TUSB5052 chip +#define ION_DEVICE_ID_GENERATION_4 0x03 // Watchport Family of products +#define ION_GENERATION_MASK 0x03 -#define ION_DEVICE_ID_GENERATION_2 0x020 // This bit is set in the PID if this edgeport hardware - // is based on the 80251+Netchip. +#define ION_DEVICE_ID_HUB_MASK 0x0080 // This bit in the PID designates a HUB device + // for example 8C would be a 421 4 port hub + // and 8D would be a 2 port embedded hub -#define EDGEPORT_DEVICE_ID_MASK 0x3df // Not including GEN_2 bit +#define EDGEPORT_DEVICE_ID_MASK 0x0ff // Not including OEM or GENERATION fields #define ION_DEVICE_ID_UNCONFIGURED_EDGE_DEVICE 0x000 // In manufacturing only #define ION_DEVICE_ID_EDGEPORT_4 0x001 // Edgeport/4 RS232 -// ION_DEVICE_ID_HUBPORT_7 0x002 // Hubport/7 (Placeholder, not used by software) +#define ION_DEVICE_ID_EDGEPORT_8R 0x002 // Edgeport with RJ45 no Ring #define ION_DEVICE_ID_RAPIDPORT_4 0x003 // Rapidport/4 #define ION_DEVICE_ID_EDGEPORT_4T 0x004 // Edgeport/4 RS232 for Telxon (aka "Fleetport") #define ION_DEVICE_ID_EDGEPORT_2 0x005 // Edgeport/2 RS232 #define ION_DEVICE_ID_EDGEPORT_4I 0x006 // Edgeport/4 RS422 #define ION_DEVICE_ID_EDGEPORT_2I 0x007 // Edgeport/2 RS422/RS485 -// ION_DEVICE_ID_HUBPORT_4 0x008 // Hubport/4 (Placeholder, not used by software) +#define ION_DEVICE_ID_EDGEPORT_8RR 0x008 // Edgeport with RJ45 with Data and RTS/CTS only // ION_DEVICE_ID_EDGEPORT_8_HANDBUILT 0x009 // Hand-built Edgeport/8 (Placeholder, used in middle digit of serial number only!) // ION_DEVICE_ID_MULTIMODEM_4X56 0x00A // MultiTech version of RP/4 (Placeholder, used in middle digit of serial number only!) #define ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT 0x00B // Edgeport/(4)21 Parallel port (USS720) @@ -90,41 +88,134 @@ #define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU 0x012 // Half of an Edgeport/16 (the kind with 2 EP/8s) #define ION_DEVICE_ID_EDGEPORT_COMPATIBLE 0x013 // Edgeport Compatible, for NCR, Axiohm etc. testing #define ION_DEVICE_ID_EDGEPORT_8I 0x014 // Edgeport/8 RS422 (single-CPU) +#define ION_DEVICE_ID_EDGEPORT_1 0x015 // Edgeport/1 RS232 +#define ION_DEVICE_ID_EPOS44 0x016 // Half of an EPOS/44 (TIUMP BASED) +#define ION_DEVICE_ID_EDGEPORT_42 0x017 // Edgeport/42 +#define ION_DEVICE_ID_EDGEPORT_412_8 0x018 // Edgeport/412 8 port part +#define ION_DEVICE_ID_EDGEPORT_412_4 0x019 // Edgeport/412 4 port part +#define ION_DEVICE_ID_EDGEPORT_22I 0x01A // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 + +// Compact Form factor TI based devices 2c, 21c, 22c, 221c +#define ION_DEVICE_ID_EDGEPORT_2C 0x01B // Edgeport/2c is a TI based Edgeport/2 - Small I2c +#define ION_DEVICE_ID_EDGEPORT_221C 0x01C // Edgeport/221c is a TI based Edgeport/2 with lucent chip and + // 2 external hub ports - Large I2C +#define ION_DEVICE_ID_EDGEPORT_22C 0x01D // Edgeport/22c is a TI based Edgeport/2 with + // 2 external hub ports - Large I2C +#define ION_DEVICE_ID_EDGEPORT_21C 0x01E // Edgeport/21c is a TI based Edgeport/2 with lucent chip + // Small I2C + + +/* + * DANGER DANGER The 0x20 bit was used to indicate a 8251/netchip GEN 2 device. + * Since the MAC, Linux, and Optimal drivers still used the old code + * I suggest that you skip the 0x20 bit when creating new PIDs + */ + + +// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) +#define ION_DEVICE_ID_TI3410_EDGEPORT_1 0x040 // Edgeport/1 RS232 +#define ION_DEVICE_ID_TI3410_EDGEPORT_1I 0x041 // Edgeport/1i- RS422 model + +// Ti based software switchable RS232/RS422/RS485 devices +#define ION_DEVICE_ID_EDGEPORT_4S 0x042 // Edgeport/4s - software switchable model +#define ION_DEVICE_ID_EDGEPORT_8S 0x043 // Edgeport/8s - software switchable model + +// Usb to Ethernet dongle +#define ION_DEVICE_ID_EDGEPORT_E 0x0E0 // Edgeport/E Usb to Ethernet + +// Edgeport TI based devices +#define ION_DEVICE_ID_TI_EDGEPORT_4 0x0201 // Edgeport/4 RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_2 0x0205 // Edgeport/2 RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_4I 0x0206 // Edgeport/4i RS422 +#define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 // Edgeport/2i RS422/RS485 +#define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) +#define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) +#define ION_DEVICE_ID_TI_EDGEPORT_8 0x020F // Edgeport/8 (single-CPU) +#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 // Edgeport/1 RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 // Edgeport/42 4 hub 2 RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_22I 0x021A // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_2C 0x021B // Edgeport/2c RS232 +#define ION_DEVICE_ID_TI_EDGEPORT_221C 0x021C // Edgeport/221c is a TI based Edgeport/2 with lucent chip and + // 2 external hub ports - Large I2C +#define ION_DEVICE_ID_TI_EDGEPORT_22C 0x021D // Edgeport/22c is a TI based Edgeport/2 with + // 2 external hub ports - Large I2C +#define ION_DEVICE_ID_TI_EDGEPORT_21C 0x021E // Edgeport/21c is a TI based Edgeport/2 with lucent chip + +// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) +#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1 0x240 // Edgeport/1 RS232 +#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I 0x241 // Edgeport/1i- RS422 model + +// Ti based software switchable RS232/RS422/RS485 devices +#define ION_DEVICE_ID_TI_EDGEPORT_4S 0x242 // Edgeport/4s - software switchable model +#define ION_DEVICE_ID_IT_EDGEPORT_8S 0x243 // Edgeport/8s - software switchable model + + +/************************************************************************ + * + * Generation 4 devices + * + ************************************************************************/ + +// Watchport based on 3410 both 1-wire and binary products (16K I2C) +#define ION_DEVICE_ID_WP_UNSERIALIZED 0x300 // Watchport based on 3410 both 1-wire and binary products +#define ION_DEVICE_ID_WP_PROXIMITY 0x301 // Watchport/P Discontinued +#define ION_DEVICE_ID_WP_MOTION 0x302 // Watchport/M +#define ION_DEVICE_ID_WP_MOISTURE 0x303 // Watchport/W +#define ION_DEVICE_ID_WP_TEMPERATURE 0x304 // Watchport/T +#define ION_DEVICE_ID_WP_HUMIDITY 0x305 // Watchport/H + +#define ION_DEVICE_ID_WP_POWER 0x306 // Watchport +#define ION_DEVICE_ID_WP_LIGHT 0x307 // Watchport +#define ION_DEVICE_ID_WP_RADIATION 0x308 // Watchport +#define ION_DEVICE_ID_WP_ACCELERATION 0x309 // Watchport/A +#define ION_DEVICE_ID_WP_DISTANCE 0x30A // Watchport/D Discontinued +#define ION_DEVICE_ID_WP_PROX_DIST 0x30B // Watchport/D uses distance sensor + // Default to /P function + +#define ION_DEVICE_ID_PLUS_PWR_HP4CD 0x30C // 5052 Plus Power HubPort/4CD+ (for Dell) +#define ION_DEVICE_ID_PLUS_PWR_HP4C 0x30D // 5052 Plus Power HubPort/4C+ +#define ION_DEVICE_ID_PLUS_PWR_PCI 0x30E // 3410 Plus Power PCI Host Controller 4 port + + +// +// Definitions for AXIOHM USB product IDs +// +#define USB_VENDOR_ID_AXIOHM 0x05D9 // Axiohm VID + +#define AXIOHM_DEVICE_ID_MASK 0xffff +#define AXIOHM_DEVICE_ID_EPIC_A758 0xA758 +#define AXIOHM_DEVICE_ID_EPIC_A794 0xA794 +#define AXIOHM_DEVICE_ID_EPIC_A225 0xA225 + + +// +// Definitions for NCR USB product IDs +// +#define USB_VENDOR_ID_NCR 0x0404 // NCR VID + +#define NCR_DEVICE_ID_MASK 0xffff +#define NCR_DEVICE_ID_EPIC_0202 0x0202 +#define NCR_DEVICE_ID_EPIC_0203 0x0203 +#define NCR_DEVICE_ID_EPIC_0310 0x0310 +#define NCR_DEVICE_ID_EPIC_0311 0x0311 +#define NCR_DEVICE_ID_EPIC_0312 0x0312 + + +// +// Definitions for SYMBOL USB product IDs +// +#define USB_VENDOR_ID_SYMBOL 0x05E0 // Symbol VID +#define SYMBOL_DEVICE_ID_MASK 0xffff +#define SYMBOL_DEVICE_ID_KEYFOB 0x0700 + + +// +// Definitions for other product IDs #define ION_DEVICE_ID_MT4X56USB 0x1403 // OEM device -// BlackBox OEM devices -#define ION_DEVICE_ID_BB_EDGEPORT_4 0x001 // Edgeport/4 RS232 -#define ION_DEVICE_ID_BB_EDGEPORT_4T 0x004 // Edgeport/4 RS232 for Telxon (aka "Fleetport") -#define ION_DEVICE_ID_BB_EDGEPORT_2 0x005 // Edgeport/2 RS232 -#define ION_DEVICE_ID_BB_EDGEPORT_4I 0x006 // Edgeport/4 RS422 -#define ION_DEVICE_ID_BB_EDGEPORT_2I 0x007 // Edgeport/2 RS422/RS485 -#define ION_DEVICE_ID_BB_EDGEPORT_421 0x00C // Edgeport/421 Hub+RS232+Parallel -#define ION_DEVICE_ID_BB_EDGEPORT_21 0x00D // Edgeport/21 RS232+Parallel -#define ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU 0x00E // Half of an Edgeport/8 (the kind with 2 EP/4s on 1 PCB) -#define ION_DEVICE_ID_BB_EDGEPORT_8 0x00F // Edgeport/8 (single-CPU) -#define ION_DEVICE_ID_BB_EDGEPORT_2_DIN 0x010 // Edgeport/2 RS232 with Apple DIN connector -#define ION_DEVICE_ID_BB_EDGEPORT_4_DIN 0x011 // Edgeport/4 RS232 with Apple DIN connector -#define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU 0x012 // Half of an Edgeport/16 (the kind with 2 EP/8s) -#define ION_DEVICE_ID_BB_EDGEPORT_8I 0x014 // Edgeport/8 RS422 (single-CPU) - - -/* Edgeport TI based devices */ -#define ION_DEVICE_ID_TI_EDGEPORT_4 0x0201 /* Edgeport/4 RS232 */ -#define ION_DEVICE_ID_TI_EDGEPORT_2 0x0205 /* Edgeport/2 RS232 */ -#define ION_DEVICE_ID_TI_EDGEPORT_4I 0x0206 /* Edgeport/4i RS422 */ -#define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 /* Edgeport/2i RS422/RS485 */ -#define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C /* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */ -#define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D /* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */ -#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 /* Edgeport/1 RS232 */ -#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 /* Edgeport/42 4 hub 2 RS232 */ -#define ION_DEVICE_ID_TI_EDGEPORT_22 0x021A /* Edgeport/22 Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */ -#define ION_DEVICE_ID_TI_EDGEPORT_2C 0x021B /* Edgeport/2c RS232 */ - -#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT 0x0240 /* Edgeport/421 in boot mode */ -#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN 0x0241 /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */ -#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT 0x0242 /* Edgeport/21 in boot mode */ -#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN 0x0243 /*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */ +#define GENERATION_ID_FROM_USB_PRODUCT_ID( ProductId ) \ + ( (__u16) ((ProductId >> 8) & (ION_GENERATION_MASK)) ) #define MAKE_USB_PRODUCT_ID( OemId, DeviceId ) \ ( (__u16) (((OemId) << 10) || (DeviceId)) ) @@ -143,7 +234,7 @@ // TxCredits value below which driver won't bother sending (to prevent too many small writes). // Send only if above 25% -#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit) (max(((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE)) +#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit, MaxPacketSize) (max( ((InitialCredit) / 4), (MaxPacketSize) )) #define EDGE_FW_BULK_MAX_PACKET_SIZE 64 // Max Packet Size for Bulk In Endpoint (EP1) #define EDGE_FW_BULK_READ_BUFFER_SIZE 1024 // Size to use for Bulk reads @@ -158,8 +249,8 @@ // Definitions of I/O Networks vendor-specific requests // for default endpoint // -// bmRequestType = 00100000 Set vendor-specific, to device -// bmRequestType = 10100000 Get vendor-specific, to device +// bmRequestType = 01000000 Set vendor-specific, to device +// bmRequestType = 11000000 Get vendor-specific, to device // // These are the definitions for the bRequest field for the // above bmRequestTypes. @@ -184,11 +275,87 @@ #define USB_REQUEST_ION_ENABLE_SUSPEND 9 // Enable/Disable suspend feature // (wValue != 0: Enable; wValue = 0: Disable) +#define USB_REQUEST_ION_SEND_IOSP 10 // Send an IOSP command to the edgeport over the control pipe +#define USB_REQUEST_ION_RECV_IOSP 11 // Receive an IOSP command from the edgeport over the control pipe + + +#define USB_REQUEST_ION_DIS_INT_TIMER 0x80 // Sent to Axiohm to enable/ disable + // interrupt token timer + // wValue = 1, enable (default) + // wValue = 0, disable // // Define parameter values for our vendor-specific commands // +// +// Edgeport Compatiblity Descriptor +// +// This descriptor is only returned by Edgeport-compatible devices +// supporting the EPiC spec. True ION devices do not return this +// descriptor, but instead return STALL on receipt of the +// GET_EPIC_DESC command. The driver interprets a STALL to mean that +// this is a "real" Edgeport. +// + +struct edge_compatibility_bits +{ + // This __u32 defines which Vendor-specific commands/functionality + // the device supports on the default EP0 pipe. + + __u32 VendEnableSuspend : 1; // 0001 Set if device supports ION_ENABLE_SUSPEND + __u32 VendUnused : 31; // Available for future expansion, must be 0 + + // This __u32 defines which IOSP commands are supported over the + // bulk pipe EP1. + + // xxxx Set if device supports: + __u32 IOSPOpen : 1; // 0001 OPEN / OPEN_RSP (Currently must be 1) + __u32 IOSPClose : 1; // 0002 CLOSE + __u32 IOSPChase : 1; // 0004 CHASE / CHASE_RSP + __u32 IOSPSetRxFlow : 1; // 0008 SET_RX_FLOW + __u32 IOSPSetTxFlow : 1; // 0010 SET_TX_FLOW + __u32 IOSPSetXChar : 1; // 0020 SET_XON_CHAR/SET_XOFF_CHAR + __u32 IOSPRxCheck : 1; // 0040 RX_CHECK_REQ/RX_CHECK_RSP + __u32 IOSPSetClrBreak : 1; // 0080 SET_BREAK/CLEAR_BREAK + __u32 IOSPWriteMCR : 1; // 0100 MCR register writes (set/clr DTR/RTS) + __u32 IOSPWriteLCR : 1; // 0200 LCR register writes (wordlen/stop/parity) + __u32 IOSPSetBaudRate : 1; // 0400 setting Baud rate (writes to LCR.80h and DLL/DLM register) + __u32 IOSPDisableIntPipe : 1; // 0800 Do not use the interrupt pipe for TxCredits or RxButesAvailable + __u32 IOSPRxDataAvail : 1; // 1000 Return status of RX Fifo (Data available in Fifo) + __u32 IOSPTxPurge : 1; // 2000 Purge TXBuffer and/or Fifo in Edgeport hardware + __u32 IOSPUnused : 18; // Available for future expansion, must be 0 + + // This __u32 defines which 'general' features are supported + + __u32 TrueEdgeport : 1; // 0001 Set if device is a 'real' Edgeport + // (Used only by driver, NEVER set by an EPiC device) + __u32 GenUnused : 31; // Available for future expansion, must be 0 + +}; + +struct edge_compatibility_descriptor +{ + __u8 Length; // Descriptor Length (per USB spec) + __u8 DescType; // Descriptor Type (per USB spec, =DEVICE type) + __u8 EpicVer; // Version of EPiC spec supported + // (Currently must be 1) + __u8 NumPorts; // Number of serial ports supported + __u8 iDownloadFile; // Index of string containing download code filename + // 0=no download, FF=download compiled into driver. + __u8 Unused[ 3 ]; // Available for future expansion, must be 0 + // (Currently must be 0). + __u8 MajorVersion; // Firmware version: xx. + __u8 MinorVersion; // yy. + __le16 BuildNumber; // zzzz (LE format) + + // The following structure contains __u32s, with each bit + // specifying whether the EPiC device supports the given + // command or functionality. + + struct edge_compatibility_bits Supports; + +}; // Values for iDownloadFile #define EDGE_DOWNLOAD_FILE_NONE 0 // No download requested @@ -272,30 +439,30 @@ struct edge_manuf_descriptor { __u8 NumPorts; // F08 Number of ports __u8 DescDate[3]; // F09 MM/DD/YY when descriptor template was compiler, - // so host can track changes to USB-only descriptors. + // so host can track changes to USB-only descriptors. __u8 SerNumLength; // F0C USB string descriptor len __u8 SerNumDescType; // F0D USB descriptor type (=STRING type) - __u16 SerialNumber[MAX_SERIALNUMBER_LEN]; // F0E "01-01-000100" Unicode Serial Number + __le16 SerialNumber[MAX_SERIALNUMBER_LEN]; // F0E "01-01-000100" Unicode Serial Number __u8 AssemblyNumLength; // F26 USB string descriptor len __u8 AssemblyNumDescType; // F27 USB descriptor type (=STRING type) - __u16 AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F28 "350-1000-01-A " assembly number + __le16 AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F28 "350-1000-01-A " assembly number __u8 OemAssyNumLength; // F44 USB string descriptor len __u8 OemAssyNumDescType; // F45 USB descriptor type (=STRING type) - __u16 OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F46 "xxxxxxxxxxxxxx" OEM assembly number + __le16 OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN]; // F46 "xxxxxxxxxxxxxx" OEM assembly number __u8 ManufDateLength; // F62 USB string descriptor len __u8 ManufDateDescType; // F63 USB descriptor type (=STRING type) - __u16 ManufDate[6]; // F64 "MMDDYY" manufacturing date + __le16 ManufDate[6]; // F64 "MMDDYY" manufacturing date __u8 Reserved3[0x4D]; // F70 -- unused, set to 0 -- __u8 UartType; // FBD Uart Type __u8 IonPid; // FBE Product ID, == LSB of USB DevDesc.PID - // (Note: Edgeport/4s before 11/98 will have - // 00 here instead of 01) + // (Note: Edgeport/4s before 11/98 will have + // 00 here instead of 01) __u8 IonConfig; // FBF Config byte for ION manufacturing use // FBF end of structure, total len = 3C0h @@ -312,7 +479,7 @@ struct edge_manuf_descriptor { // both 00 and 01 values mean '654. #define MANUF_UART_EXAR_654_EARLY 0 // Exar 16C654 in Edgeport/4s before 11/98 #define MANUF_UART_EXAR_654 1 // Exar 16C654 -#define MANUF_UART_EXAR_2852 2 // Exar 16C2852 +#define MANUF_UART_EXAR_2852 2 // Exar 16C2852 // // Note: The CpuRev and BoardRev values do not conform to manufacturing @@ -334,25 +501,22 @@ struct edge_manuf_descriptor { #define MANUF_BOARD_REV_GENERATION_2 0x20 // Second generaiton edgeport - - // Values of bottom 5 bits of CpuRev & BoardRev for // Implementation 1 (ie, 251+Netchip-based) #define MANUF_CPU_REV_1 1 // C251TB Rev 1 (Need actual Intel rev here) #define MANUF_BOARD_REV_A 1 // First rev of 251+Netchip design - - #define MANUF_SERNUM_LENGTH sizeof(((struct edge_manuf_descriptor *)0)->SerialNumber) #define MANUF_ASSYNUM_LENGTH sizeof(((struct edge_manuf_descriptor *)0)->AssemblyNumber) #define MANUF_OEMASSYNUM_LENGTH sizeof(((struct edge_manuf_descriptor *)0)->OemAssyNumber) #define MANUF_MANUFDATE_LENGTH sizeof(((struct edge_manuf_descriptor *)0)->ManufDate) -#define MANUF_ION_CONFIG_MASTER 0x80 // 1=Master mode, 0=Normal -#define MANUF_ION_CONFIG_DIAG 0x40 // 1=Run h/w diags, 0=norm -#define MANUF_ION_CONFIG_DIAG_NO_LOOP 0x20 // As above but no ext loopback test - +#define MANUF_ION_CONFIG_DIAG_NO_LOOP 0x20 // As below but no ext loopback test +#define MANUF_ION_CONFIG_DIAG 0x40 // 930 based device: 1=Run h/w diags, 0=norm + // TIUMP Device : 1=IONSERIAL needs to run Final Test +#define MANUF_ION_CONFIG_MASTER 0x80 // 930 based device: 1=Master mode, 0=Normal + // TIUMP Device : 1=First device on a multi TIUMP Device // // This structure describes parameters for the boot code, and @@ -368,19 +532,19 @@ struct edge_boot_descriptor { __u8 DescVer; // C2 Desc version/format __u8 Reserved1; // C3 -- unused, set to 0 -- - __u16 BootCodeLength; // C4 Boot code goes from FF:0000 to FF:(len-1) + __le16 BootCodeLength; // C4 Boot code goes from FF:0000 to FF:(len-1) // (LE format) __u8 MajorVersion; // C6 Firmware version: xx. __u8 MinorVersion; // C7 yy. - __u16 BuildNumber; // C8 zzzz (LE format) + __le16 BuildNumber; // C8 zzzz (LE format) __u16 EnumRootDescTable; // CA Root of ROM-based descriptor table __u8 NumDescTypes; // CC Number of supported descriptor types __u8 Reserved4; // CD Fix Compiler Packing - __u16 Capabilities; // CE-CF Capabilities flags (LE format) + __le16 Capabilities; // CE-CF Capabilities flags (LE format) __u8 Reserved2[0x28]; // D0 -- unused, set to 0 -- __u8 UConfig0; // F8 930-defined CPU configuration byte 0 __u8 UConfig1; // F9 930-defined CPU configuration byte 1 @@ -398,23 +562,29 @@ struct edge_boot_descriptor { #define BOOT_CAP_RESET_CMD 0x0001 // If set, boot correctly supports ION_RESET_DEVICE - /************************************************************************ T I U M P D E F I N I T I O N S ***********************************************************************/ +// Chip definitions in I2C +#define UMP5152 0x52 +#define UMP3410 0x10 + + //************************************************************************ // TI I2C Format Definitions //************************************************************************ -#define I2C_DESC_TYPE_INFO_BASIC 1 -#define I2C_DESC_TYPE_FIRMWARE_BASIC 2 -#define I2C_DESC_TYPE_DEVICE 3 -#define I2C_DESC_TYPE_CONFIG 4 -#define I2C_DESC_TYPE_STRING 5 -#define I2C_DESC_TYPE_FIRMWARE_BLANK 0xf2 - -#define I2C_DESC_TYPE_MAX 5 -// 3410 may define types 6, 7 for other firmware downloads +#define I2C_DESC_TYPE_INFO_BASIC 0x01 +#define I2C_DESC_TYPE_FIRMWARE_BASIC 0x02 +#define I2C_DESC_TYPE_DEVICE 0x03 +#define I2C_DESC_TYPE_CONFIG 0x04 +#define I2C_DESC_TYPE_STRING 0x05 +#define I2C_DESC_TYPE_FIRMWARE_AUTO 0x07 // for 3410 download +#define I2C_DESC_TYPE_CONFIG_KLUDGE 0x14 // for 3410 +#define I2C_DESC_TYPE_WATCHPORT_VERSION 0x15 // firmware version number for watchport +#define I2C_DESC_TYPE_WATCHPORT_CALIBRATION_DATA 0x16 // Watchport Calibration Data + +#define I2C_DESC_TYPE_FIRMWARE_BLANK 0xf2 // Special section defined by ION #define I2C_DESC_TYPE_ION 0 // Not defined by TI @@ -428,7 +598,9 @@ struct ti_i2c_desc __u8 Data[0]; // Data starts here }__attribute__((packed)); -struct ti_i2c_firmware_rec +// for 5152 devices only (type 2 record) +// for 3410 the version is stored in the WATCHPORT_FIRMWARE_VERSION descriptor +struct ti_i2c_firmware_rec { __u8 Ver_Major; // Firmware Major version number __u8 Ver_Minor; // Firmware Minor version number @@ -436,10 +608,18 @@ struct ti_i2c_firmware_rec }__attribute__((packed)); +struct watchport_firmware_version +{ +// Added 2 bytes for version number + __u8 Version_Major; // Download Version (for Watchport) + __u8 Version_Minor; +}__attribute__((packed)); + + // Structure of header of download image in fw_down.h struct ti_i2c_image_header { - __u16 Length; + __le16 Length; __u8 CheckSum; }__attribute__((packed)); @@ -461,6 +641,15 @@ struct ti_basic_descriptor } __attribute__((packed)); +// CPU / Board Rev Definitions +#define TI_CPU_REV_5052 2 // 5052 based edgeports +#define TI_CPU_REV_3410 3 // 3410 based edgeports + +#define TI_BOARD_REV_TI_EP 0 // Basic ti based edgeport +#define TI_BOARD_REV_COMPACT 1 // Compact board +#define TI_BOARD_REV_WATCHPORT 2 // Watchport + + #define TI_GET_CPU_REVISION(x) (__u8)((((x)>>4)&0x0f)) #define TI_GET_BOARD_REVISION(x) (__u8)(((x)&0x0f)) @@ -469,20 +658,30 @@ struct ti_basic_descriptor #define TI_MAX_I2C_SIZE ( 16 * 1024 ) -/* TI USB 5052 definitions */ +#define TI_MANUF_VERSION_0 0 + +// IonConig2 flags +#define TI_CONFIG2_RS232 0x01 +#define TI_CONFIG2_RS422 0x02 +#define TI_CONFIG2_RS485 0x04 +#define TI_CONFIG2_SWITCHABLE 0x08 + +#define TI_CONFIG2_WATCHPORT 0x10 + + struct edge_ti_manuf_descriptor { __u8 IonConfig; // Config byte for ION manufacturing use __u8 IonConfig2; // Expansion - __u8 Version; // Verqsion + __u8 Version; // Version __u8 CpuRev_BoardRev; // CPU revision level (0xF0) and Board Rev Level (0x0F) __u8 NumPorts; // Number of ports for this UMP __u8 NumVirtualPorts; // Number of Virtual ports __u8 HubConfig1; // Used to configure the Hub __u8 HubConfig2; // Used to configure the Hub __u8 TotalPorts; // Total Number of Com Ports for the entire device (All UMPs) - __u8 Reserved; + __u8 Reserved; // Reserved }__attribute__((packed)); -#endif // if !defined() +#endif // if !defined(_USBVEND_H) diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 42119dd44..4ffe6e4ac 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -77,9 +77,9 @@ static int ipaq_open (struct usb_serial_port *port, struct file *filp); static void ipaq_close (struct usb_serial_port *port, struct file *filp); static int ipaq_startup (struct usb_serial *serial); static void ipaq_shutdown (struct usb_serial *serial); -static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, int count); -static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count); static void ipaq_write_gather(struct usb_serial_port *port); static void ipaq_read_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -91,46 +91,448 @@ static void ipaq_destroy_lists(struct usb_serial_port *port); static struct usb_device_id ipaq_id_table [] = { /* The first entry is a placeholder for the insmod-specified device */ - { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, - { USB_DEVICE(ASKEY_VENDOR_ID, ASKEY_PRODUCT_ID) }, - { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0065_ID) }, - { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0066_ID) }, - { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0067_ID) }, - { USB_DEVICE(CASIO_VENDOR_ID, CASIO_2001_ID) }, - { USB_DEVICE(CASIO_VENDOR_ID, CASIO_EM500_ID) }, - { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) }, - { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) }, - { USB_DEVICE(DELL_VENDOR_ID, DELL_AXIM_ID) }, - { USB_DEVICE(FSC_VENDOR_ID, FSC_LOOX_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_2116_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_2216_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_3016_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_3116_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_3216_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_4016_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_4116_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_4216_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_5016_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_5116_ID) }, - { USB_DEVICE(HP_VENDOR_ID, HP_5216_ID) }, - { USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) }, - { USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) }, - { USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) }, - { USB_DEVICE(ROVER_VENDOR_ID, ROVER_P5_ID) }, - { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) }, - { USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) }, - { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) }, - { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E310_ID) }, - { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) }, - { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) }, - { USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) }, - { USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) }, - { USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) }, - { USB_DEVICE(ASUS_VENDOR_ID, ASUS_A620_PRODUCT_ID) }, - { } /* Terminating entry */ + { USB_DEVICE(0x049F, 0x0003) }, + { USB_DEVICE(0x1690, 0x0601) }, /* Askey USB Sync */ + { USB_DEVICE(0x0960, 0x0065) }, /* BCOM USB Sync 0065 */ + { USB_DEVICE(0x0960, 0x0066) }, /* BCOM USB Sync 0066 */ + { USB_DEVICE(0x0960, 0x0067) }, /* BCOM USB Sync 0067 */ + { USB_DEVICE(0x07CF, 0x2001) }, /* CASIO USB Sync 2001 */ + { USB_DEVICE(0x07CF, 0x2002) }, /* CASIO USB Sync 2002 */ + { USB_DEVICE(0x07CF, 0x2003) }, /* CASIO USB Sync 2003 */ + { USB_DEVICE(0x049F, 0x0003) }, /* Compaq iPAQ USB Sync */ + { USB_DEVICE(0x049F, 0x0032) }, /* Compaq iPAQ USB Sync */ + { USB_DEVICE(0x413C, 0x4001) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4002) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4003) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4004) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4005) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4006) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4007) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4008) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ + { USB_DEVICE(0x03F0, 0x1016) }, /* HP USB Sync */ + { USB_DEVICE(0x03F0, 0x1116) }, /* HP USB Sync 1611 */ + { USB_DEVICE(0x03F0, 0x1216) }, /* HP USB Sync 1612 */ + { USB_DEVICE(0x03F0, 0x2016) }, /* HP USB Sync 1620 */ + { USB_DEVICE(0x03F0, 0x2116) }, /* HP USB Sync 1621 */ + { USB_DEVICE(0x03F0, 0x2216) }, /* HP USB Sync 1622 */ + { USB_DEVICE(0x03F0, 0x3016) }, /* HP USB Sync 1630 */ + { USB_DEVICE(0x03F0, 0x3116) }, /* HP USB Sync 1631 */ + { USB_DEVICE(0x03F0, 0x3216) }, /* HP USB Sync 1632 */ + { USB_DEVICE(0x03F0, 0x4016) }, /* HP USB Sync 1640 */ + { USB_DEVICE(0x03F0, 0x4116) }, /* HP USB Sync 1641 */ + { USB_DEVICE(0x03F0, 0x4216) }, /* HP USB Sync 1642 */ + { USB_DEVICE(0x03F0, 0x5016) }, /* HP USB Sync 1650 */ + { USB_DEVICE(0x03F0, 0x5116) }, /* HP USB Sync 1651 */ + { USB_DEVICE(0x03F0, 0x5216) }, /* HP USB Sync 1652 */ + { USB_DEVICE(0x094B, 0x0001) }, /* Linkup Systems USB Sync */ + { USB_DEVICE(0x045E, 0x0400) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0401) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0402) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0403) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0404) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0405) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0406) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0407) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0408) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0409) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040A) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040B) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040C) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040D) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040E) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x040F) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0410) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0411) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0412) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0413) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0414) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0415) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0416) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0417) }, /* Windows Powered Pocket PC 2002 */ + { USB_DEVICE(0x045E, 0x0432) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0433) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0434) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0435) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0436) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0437) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0438) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0439) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043A) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043B) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043C) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043D) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043E) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x043F) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0440) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0441) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0442) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0443) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0444) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0445) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0446) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0447) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0448) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0449) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044A) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044B) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044C) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044D) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044E) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x044F) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0450) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0451) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0452) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0453) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0454) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0455) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0456) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0457) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0458) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0459) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045A) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045B) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045C) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045D) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045E) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x045F) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0460) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0461) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0462) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0463) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0464) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0465) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0466) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0467) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0468) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0469) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046A) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046B) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046C) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046D) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046E) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x046F) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0470) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0471) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0472) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0473) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0474) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0475) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0476) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0477) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0478) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x0479) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x047A) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x047B) }, /* Windows Powered Pocket PC 2003 */ + { USB_DEVICE(0x045E, 0x04C8) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04C9) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04CA) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04CB) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04CC) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04CD) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04CE) }, /* Windows Powered Smartphone 2002 */ + { USB_DEVICE(0x045E, 0x04D7) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04D8) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04D9) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DA) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DB) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DC) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DD) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DE) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04DF) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E0) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E1) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E2) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E3) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E4) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E5) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E6) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E7) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E8) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04E9) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x045E, 0x04EA) }, /* Windows Powered Smartphone 2003 */ + { USB_DEVICE(0x0961, 0x0010) }, /* Portatec USB Sync */ + { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ + { USB_DEVICE(0x0104, 0x00BE) }, /* Socket USB Sync */ + { USB_DEVICE(0x0930, 0x0700) }, /* TOSHIBA USB Sync 0700 */ + { USB_DEVICE(0x0930, 0x0705) }, /* TOSHIBA Pocket PC e310 */ + { USB_DEVICE(0x0930, 0x0707) }, /* TOSHIBA Pocket PC e330 Series */ + { USB_DEVICE(0x0930, 0x0708) }, /* TOSHIBA Pocket PC e350 Series */ + { USB_DEVICE(0x0930, 0x0706) }, /* TOSHIBA Pocket PC e740 */ + { USB_DEVICE(0x0930, 0x0709) }, /* TOSHIBA Pocket PC e750 Series */ + { USB_DEVICE(0x0930, 0x070A) }, /* TOSHIBA Pocket PC e400 Series */ + { USB_DEVICE(0x0930, 0x070B) }, /* TOSHIBA Pocket PC e800 Series */ + { USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A03) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A04) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A05) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A06) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A07) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A08) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A09) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0A) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0B) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0C) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0D) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0E) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A0F) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A10) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A11) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A12) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A13) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A14) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A15) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A16) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A17) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A18) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A19) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1A) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1B) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1C) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1D) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1E) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A1F) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A20) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A21) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A22) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A23) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A24) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A25) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A26) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A27) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A28) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A29) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2A) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2B) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2C) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2D) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2E) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A2F) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A30) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A31) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A32) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A33) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A34) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A35) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A36) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A37) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A38) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A39) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3A) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3B) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3C) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3D) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3E) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A3F) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A40) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A41) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A42) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A43) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A44) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A45) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A46) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A47) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A48) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A49) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4A) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4B) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4C) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4D) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4E) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A4F) }, /* PocketPC USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A50) }, /* HTC SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A51) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A52) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A53) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A54) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A55) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A56) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A57) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A58) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A59) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5A) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5B) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5C) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5D) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5E) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A5F) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A60) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A61) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A62) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A63) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A64) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A65) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A66) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A67) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A68) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A69) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6A) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6B) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6C) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6D) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6E) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A6F) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A70) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A71) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A72) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A73) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A74) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A75) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A76) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A77) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A78) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A79) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7A) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7B) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7C) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7D) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7E) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A7F) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A80) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A81) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A82) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A83) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A84) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A85) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A86) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A87) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A88) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A89) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8A) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8B) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8C) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8D) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8E) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A8F) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A90) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A91) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A92) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A93) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A94) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A95) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A96) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A97) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A98) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A99) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9A) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9B) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9C) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */ + { USB_DEVICE(0x0409, 0x00D5) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x00D6) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x00D7) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x8024) }, /* NEC USB Sync */ + { USB_DEVICE(0x0409, 0x8025) }, /* NEC USB Sync */ + { USB_DEVICE(0x04A4, 0x0014) }, /* Hitachi USB Sync */ + { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */ + { USB_DEVICE(0x0F98, 0x0201) }, /* Cyberbank USB Sync */ + { USB_DEVICE(0x0502, 0x16E1) }, /* Acer n10 Handheld USB Sync */ + { USB_DEVICE(0x0502, 0x16E3) }, /* Acer n30 Handheld USB Sync */ + { USB_DEVICE(0x0502, 0x16E2) }, /* Acer n20 Handheld USB Sync */ + { USB_DEVICE(0x0502, 0x1631) }, /* c10 Series */ + { USB_DEVICE(0x0502, 0x1632) }, /* c20 Series */ + { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x420F) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x4200) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x4201) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x4202) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */ + { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */ + { USB_DEVICE(0x04AD, 0x0301) }, /* USB Sync 0301 */ + { USB_DEVICE(0x04AD, 0x0302) }, /* USB Sync 0302 */ + { USB_DEVICE(0x04AD, 0x0303) }, /* USB Sync 0303 */ + { USB_DEVICE(0x1066, 0x0300) }, /* E-TEN P3XX Pocket PC */ + { USB_DEVICE(0x1066, 0x0500) }, /* E-TEN P5XX Pocket PC */ + { USB_DEVICE(0x1066, 0x0600) }, /* E-TEN P6XX Pocket PC */ + { USB_DEVICE(0x1066, 0x0700) }, /* E-TEN P7XX Pocket PC */ + { USB_DEVICE(0x1066, 0x00CE) }, /* E-TEN USB Sync */ + { USB_DEVICE(0x0F4E, 0x0200) }, /* Freedom Scientific USB Sync */ + { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ + { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ + { USB_DEVICE(0x067E, 0x1001) }, /* Intermec Mobile Computer */ + { USB_DEVICE(0x04f1, 0x3011) }, /* JVC USB Sync */ + { USB_DEVICE(0x04F1, 0x3012) }, /* JVC USB Sync */ + { USB_DEVICE(0x3708, 0x20CE) }, /* Legend USB Sync */ + { USB_DEVICE(0x3708, 0x21CE) }, /* Lenovo USB Sync */ + { USB_DEVICE(0x043E, 0x9C01) }, /* LGE USB Sync */ + { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ + { USB_DEVICE(0x3340, 0x0B1C) }, /* Generic PPC StrongARM */ + { USB_DEVICE(0x3340, 0x0E3A) }, /* Generic PPC USB Sync */ + { USB_DEVICE(0x3340, 0x0F3A) }, /* Generic SmartPhone USB Sync */ + { USB_DEVICE(0x3340, 0x0F1C) }, /* Itautec USB Sync */ + { USB_DEVICE(0x3340, 0x1326) }, /* Itautec USB Sync */ + { USB_DEVICE(0x3340, 0x3326) }, /* MEDION Winodws Moble USB Sync */ + { USB_DEVICE(0x3340, 0x0326) }, /* Mio DigiWalker 338 */ + { USB_DEVICE(0x3340, 0x0426) }, /* Mio DigiWalker 338 */ + { USB_DEVICE(0x3340, 0x011C) }, /* Mio DigiWalker PPC StrongARM */ + { USB_DEVICE(0x3340, 0x053A) }, /* Mio DigiWalker SmartPhone USB Sync */ + { USB_DEVICE(0x3340, 0x043A) }, /* Mio DigiWalker USB Sync */ + { USB_DEVICE(0x3340, 0x071C) }, /* MiTAC USB Sync */ + { USB_DEVICE(0x3340, 0x051C) }, /* MiTAC USB Sync 528 */ + { USB_DEVICE(0x3340, 0x2326) }, /* Vobis USB Sync */ + { USB_DEVICE(0x3340, 0x191C) }, /* YAKUMO USB Sync */ + { USB_DEVICE(0x4113, 0x0210) }, /* Mobile Media Technology USB Sync */ + { USB_DEVICE(0x4113, 0x0211) }, /* Mobile Media Technology USB Sync */ + { USB_DEVICE(0x4113, 0x0400) }, /* Mobile Media Technology USB Sync */ + { USB_DEVICE(0x4113, 0x0410) }, /* Mobile Media Technology USB Sync */ + { USB_DEVICE(0x0CAD, 0x9001) }, /* Motorola PowerPad Pocket PC Device */ + { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */ + { USB_DEVICE(0x04E8, 0x6611) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6613) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6615) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6617) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6619) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x661B) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F03) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x5F04) }, /* Samsung NEXiO USB Sync */ + { USB_DEVICE(0x04E8, 0x662E) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6630) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x04E8, 0x6632) }, /* Samsung MITs USB Sync */ + { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ + { USB_DEVICE(0x05E0, 0x2000) }, /* Symbol USB Sync */ + { USB_DEVICE(0x05E0, 0x2001) }, /* Symbol USB Sync 0x2001 */ + { USB_DEVICE(0x05E0, 0x2002) }, /* Symbol USB Sync 0x2002 */ + { USB_DEVICE(0x05E0, 0x2003) }, /* Symbol USB Sync 0x2003 */ + { USB_DEVICE(0x05E0, 0x2004) }, /* Symbol USB Sync 0x2004 */ + { USB_DEVICE(0x05E0, 0x2005) }, /* Symbol USB Sync 0x2005 */ + { USB_DEVICE(0x05E0, 0x2006) }, /* Symbol USB Sync 0x2006 */ + { USB_DEVICE(0x05E0, 0x2007) }, /* Symbol USB Sync 0x2007 */ + { USB_DEVICE(0x05E0, 0x2008) }, /* Symbol USB Sync 0x2008 */ + { USB_DEVICE(0x05E0, 0x2009) }, /* Symbol USB Sync 0x2009 */ + { USB_DEVICE(0x05E0, 0x200A) }, /* Symbol USB Sync 0x200A */ + { USB_DEVICE(0x1182, 0x1388) }, /* VES USB Sync */ + { USB_DEVICE(0x0543, 0x0ED9) }, /* ViewSonic Color Pocket PC V35 */ + { USB_DEVICE(0x0543, 0x1527) }, /* ViewSonic Color Pocket PC V36 */ + { USB_DEVICE(0x0543, 0x1529) }, /* ViewSonic Color Pocket PC V37 */ + { USB_DEVICE(0x0543, 0x152B) }, /* ViewSonic Color Pocket PC V38 */ + { USB_DEVICE(0x0543, 0x152E) }, /* ViewSonic Pocket PC */ + { USB_DEVICE(0x0543, 0x1921) }, /* ViewSonic Communicator Pocket PC */ + { USB_DEVICE(0x0543, 0x1922) }, /* ViewSonic Smartphone */ + { USB_DEVICE(0x0543, 0x1923) }, /* ViewSonic Pocket PC V30 */ + { USB_DEVICE(0x0536, 0x01A0) }, /* HHP PDT */ + { USB_DEVICE(0x099E, 0x0052) }, /* Trimble GeoExplorer */ + { USB_DEVICE(0x099E, 0x4000) }, /* TDS Data Collector */ + { USB_DEVICE(0x0FB8, 0x3001) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x3002) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x3003) }, /* Wistron USB Sync */ + { USB_DEVICE(0x0FB8, 0x4001) }, /* Wistron USB Sync */ + { USB_DEVICE(0x11D9, 0x1003) }, /* Rugged Pocket PC 2003 */ + { USB_DEVICE(0x11D9, 0x1002) }, /* Rugged Pocket PC 2003 */ + { USB_DEVICE(0x22B8, 0x4204) }, /* Motorola MPx200 Smartphone */ + { USB_DEVICE(0x22B8, 0x4214) }, /* Motorola MPc GSM */ + { USB_DEVICE(0x22B8, 0x4224) }, /* Motorola MPx220 Smartphone */ + { USB_DEVICE(0x22B8, 0x4234) }, /* Motorola MPc CDMA */ + { USB_DEVICE(0x22B8, 0x4244) }, /* Motorola MPx100 Smartphone */ + { USB_DEVICE(0x1231, 0xCE01) }, /* USB Sync 03 */ + { USB_DEVICE(0x1231, 0xCE02) }, /* USB Sync 03 */ + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, ipaq_id_table); @@ -188,6 +590,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) usb_set_serial_port_data(port, priv); priv->active = 0; priv->queue_len = 0; + priv->free_len = 0; INIT_LIST_HEAD(&priv->queue); INIT_LIST_HEAD(&priv->freelist); @@ -286,8 +689,8 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp) /* * shut down bulk read and write */ - usb_unlink_urb(port->write_urb); - usb_unlink_urb(port->read_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); ipaq_destroy_lists(port); kfree(priv); usb_set_serial_port_data(port, NULL); @@ -337,7 +740,7 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs) return; } -static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, int count) { const unsigned char *current_position = buf; @@ -348,7 +751,7 @@ static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigne while (count > 0) { transfer_size = min(count, PACKET_SIZE); - if (ipaq_write_bulk(port, from_user, current_position, transfer_size)) { + if (ipaq_write_bulk(port, current_position, transfer_size)) { break; } current_position += transfer_size; @@ -360,7 +763,7 @@ static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigne return bytes_sent; } -static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf, +static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, int count) { struct ipaq_private *priv = usb_get_serial_port_data(port); @@ -385,12 +788,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const un return -EAGAIN; } - if (from_user) { - if (copy_from_user(pkt->data, buf, count)) - return -EFAULT; - } else { - memcpy(pkt->data, buf, count); - } + memcpy(pkt->data, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, pkt->data); pkt->len = count; @@ -417,9 +815,8 @@ static void ipaq_write_gather(struct usb_serial_port *port) struct ipaq_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; int count, room; - struct ipaq_packet *pkt; + struct ipaq_packet *pkt, *tmp; struct urb *urb = port->write_urb; - struct list_head *tmp; if (urb->status == -EINPROGRESS) { /* Should never happen */ @@ -427,9 +824,7 @@ static void ipaq_write_gather(struct usb_serial_port *port) return; } room = URBDATA_SIZE; - for (tmp = priv->queue.next; tmp != &priv->queue;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { count = min(room, (int)(pkt->len - pkt->written)); memcpy(urb->transfer_buffer + (URBDATA_SIZE - room), pkt->data + pkt->written, count); @@ -501,22 +896,16 @@ static int ipaq_chars_in_buffer(struct usb_serial_port *port) static void ipaq_destroy_lists(struct usb_serial_port *port) { struct ipaq_private *priv = usb_get_serial_port_data(port); - struct list_head *tmp; - struct ipaq_packet *pkt; + struct ipaq_packet *pkt, *tmp; - for (tmp = priv->queue.next; tmp != &priv->queue;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { kfree(pkt->data); kfree(pkt); } - for (tmp = priv->freelist.next; tmp != &priv->freelist;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->freelist, list) { kfree(pkt->data); kfree(pkt); } - return; } diff --git a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h index e9bedde0d..2b9035918 100644 --- a/drivers/usb/serial/ipaq.h +++ b/drivers/usb/serial/ipaq.h @@ -14,80 +14,6 @@ #ifndef __LINUX_USB_SERIAL_IPAQ_H #define __LINUX_USB_SERIAL_IPAQ_H -#define ASKEY_VENDOR_ID 0x1690 -#define ASKEY_PRODUCT_ID 0x0601 - -#define BCOM_VENDOR_ID 0x0960 -#define BCOM_0065_ID 0x0065 -#define BCOM_0066_ID 0x0066 -#define BCOM_0067_ID 0x0067 - -#define CASIO_VENDOR_ID 0x07cf -#define CASIO_2001_ID 0x2001 -#define CASIO_EM500_ID 0x2002 - -#define COMPAQ_VENDOR_ID 0x049f -#define COMPAQ_IPAQ_ID 0x0003 -#define COMPAQ_0032_ID 0x0032 - -#define DELL_VENDOR_ID 0x413c -#define DELL_AXIM_ID 0x4001 - -#define FSC_VENDOR_ID 0x0bf8 -#define FSC_LOOX_ID 0x1001 - -#define HP_VENDOR_ID 0x03f0 -#define HP_JORNADA_548_ID 0x1016 -#define HP_JORNADA_568_ID 0x1116 -#define HP_2016_ID 0x2016 -#define HP_2116_ID 0x2116 -#define HP_2216_ID 0x2216 -#define HP_3016_ID 0x3016 -#define HP_3116_ID 0x3116 -#define HP_3216_ID 0x3216 -#define HP_4016_ID 0x4016 -#define HP_4116_ID 0x4116 -#define HP_4216_ID 0x4216 -#define HP_5016_ID 0x5016 -#define HP_5116_ID 0x5116 -#define HP_5216_ID 0x5216 - -#define LINKUP_VENDOR_ID 0x094b -#define LINKUP_PRODUCT_ID 0x0001 - -#define MICROSOFT_VENDOR_ID 0x045e -#define MICROSOFT_00CE_ID 0x00ce - -#define PORTATEC_VENDOR_ID 0x0961 -#define PORTATEC_PRODUCT_ID 0x0010 - -#define ROVER_VENDOR_ID 0x047b -#define ROVER_P5_ID 0x3000 - -#define SAGEM_VENDOR_ID 0x5e04 -#define SAGEM_WIRELESS_ID 0xce00 - -#define SOCKET_VENDOR_ID 0x0104 -#define SOCKET_PRODUCT_ID 0x00be - -#define TOSHIBA_VENDOR_ID 0x0930 -#define TOSHIBA_PRODUCT_ID 0x0700 -#define TOSHIBA_E310_ID 0x0705 -#define TOSHIBA_E740_ID 0x0706 -#define TOSHIBA_E335_ID 0x0707 - -#define HTC_VENDOR_ID 0x0bb4 -#define HTC_PRODUCT_ID 0x00ce - -#define NEC_VENDOR_ID 0x0409 -#define NEC_PRODUCT_ID 0x00d5 - -#define ASUS_VENDOR_ID 0x0b05 -#define ASUS_A600_PRODUCT_ID 0x4201 - -#define ASUS_VENDOR_ID 0x0b05 -#define ASUS_A620_PRODUCT_ID 0x4202 - /* * Since we can't queue our bulk write urbs (don't know why - it just * doesn't work), we can send down only one write urb at a time. The simplistic diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index cb42cc7c3..3003cd043 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -105,7 +105,7 @@ static int xbof = -1; static int ir_startup (struct usb_serial *serial); static int ir_open (struct usb_serial_port *port, struct file *filep); static void ir_close (struct usb_serial_port *port, struct file *filep); -static int ir_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); @@ -322,10 +322,10 @@ static void ir_close (struct usb_serial_port *port, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); /* shutdown our bulk read */ - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); } -static int ir_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count) { unsigned char *transfer_buffer; int result; @@ -359,12 +359,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned *transfer_buffer = ir_xbof | ir_baud; ++transfer_buffer; - if (from_user) { - if (copy_from_user (transfer_buffer, buf, transfer_size)) - return -EFAULT; - } else { - memcpy (transfer_buffer, buf, transfer_size); - } + memcpy (transfer_buffer, buf, transfer_size); usb_fill_bulk_urb ( port->write_urb, @@ -449,6 +444,10 @@ static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) */ tty = port->tty; + /* + * FIXME: must not do this in IRQ context, + * must honour TTY_DONT_FLIP + */ tty->ldisc.receive_buf( tty, data+1, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 7b4f98407..20adf2eed 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -342,7 +342,7 @@ static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, /* Write function is similar for the four protocols used with only a minor change for usa90 (usa19hs) required */ -static int keyspan_write(struct usb_serial_port *port, int from_user, +static int keyspan_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct keyspan_port_private *p_priv; @@ -396,12 +396,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user, for now so set to zero */ ((char *)this_urb->transfer_buffer)[0] = 0; - if (from_user) { - if (copy_from_user(this_urb->transfer_buffer + dataOffset, buf, todo)) - return -EFAULT; - } else { - memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); - } + memcpy (this_urb->transfer_buffer + dataOffset, buf, todo); buf += todo; /* send the data out the bulk port */ @@ -1126,7 +1121,7 @@ static inline void stop_urb(struct urb *urb) { if (urb && urb->status == -EINPROGRESS) { urb->transfer_flags &= ~URB_ASYNC_UNLINK; - usb_unlink_urb(urb); + usb_kill_urb(urb); } } diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 7b60835c4..e9b45b768 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -46,7 +46,6 @@ static void keyspan_rx_unthrottle (struct usb_serial_port *port); static int keyspan_write_room (struct usb_serial_port *port); static int keyspan_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index fd6c1b838..2f45c60bd 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -186,13 +186,7 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) wake_up_interruptible( &port->write_wait ); /* wake up line discipline */ - if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup ) - (tty->ldisc.write_wakeup)(tty); - - /* wake up other tty processes */ - wake_up_interruptible( &tty->write_wait ); - /* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */ + tty_wakeup(tty); } static void keyspan_pda_request_unthrottle( struct usb_serial *serial ) @@ -291,7 +285,7 @@ static void keyspan_pda_rx_throttle (struct usb_serial_port *port) upon the device too. */ dbg("keyspan_pda_rx_throttle port %d", port->number); - usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); } @@ -499,7 +493,7 @@ static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, return -ENOIOCTLCMD; } -static int keyspan_pda_write(struct usb_serial_port *port, int from_user, +static int keyspan_pda_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; @@ -573,16 +567,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, if (count) { /* now transfer data */ - if (from_user) { - if( copy_from_user(port->write_urb->transfer_buffer, - buf, count) ) { - rc = -EFAULT; - goto exit; - } - } - else { - memcpy (port->write_urb->transfer_buffer, buf, count); - } + memcpy (port->write_urb->transfer_buffer, buf, count); /* send the data out the bulk port */ port->write_urb->transfer_buffer_length = count; @@ -712,8 +697,8 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp) keyspan_pda_set_modem_info(serial, 0); /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->interrupt_in_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); } } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index c5207d194..2e261c73c 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -79,7 +79,6 @@ static int klsi_105_open (struct usb_serial_port *port, static void klsi_105_close (struct usb_serial_port *port, struct file *filp); static int klsi_105_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static void klsi_105_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -336,12 +335,12 @@ static void klsi_105_shutdown (struct usb_serial *serial) for (j = 0; j < NUM_URBS; j++) { if (write_urbs[j]) { /* FIXME - uncomment the following - * usb_unlink_urb call when the host + * usb_kill_urb call when the host * controllers get fixed to set * urb->dev = NULL after the urb is * finished. Otherwise this call * oopses. */ - /* usb_unlink_urb(write_urbs[j]); */ + /* usb_kill_urb(write_urbs[j]); */ if (write_urbs[j]->transfer_buffer) kfree(write_urbs[j]->transfer_buffer); usb_free_urb (write_urbs[j]); @@ -467,12 +466,12 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp) err("Disabling read failed (error = %d)", rc); /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); /* unlink our write pool */ /* FIXME */ /* wgg - do I need this? I think so. */ - usb_unlink_urb (port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out); } /* klsi_105_close */ @@ -484,7 +483,7 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp) #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ -static int klsi_105_write (struct usb_serial_port *port, int from_user, +static int klsi_105_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct klsi_105_private *priv = usb_get_serial_port_data(port); @@ -525,15 +524,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET); size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET); - if (from_user) { - if (copy_from_user(urb->transfer_buffer - + KLSI_105_DATA_OFFSET, buf, size)) { - return -EFAULT; - } - } else { - memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, - buf, size); - } + memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); /* write payload size into transfer buffer */ ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); @@ -782,9 +773,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port, switch (cflag & CSIZE) { case CS5: dbg("%s - 5 bits/byte not supported", __FUNCTION__); + spin_unlock_irqrestore (&priv->lock, flags); return ; case CS6: dbg("%s - 6 bits/byte not supported", __FUNCTION__); + spin_unlock_irqrestore (&priv->lock, flags); return ; case CS7: priv->cfg.databits = kl5kusb105a_dtb_7; @@ -994,7 +987,7 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, static void klsi_105_throttle (struct usb_serial_port *port) { dbg("%s - port %d", __FUNCTION__, port->number); - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); } static void klsi_105_unthrottle (struct usb_serial_port *port) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index b479916ce..a37b28d13 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -73,7 +73,7 @@ static int kobil_startup (struct usb_serial *serial); static void kobil_shutdown (struct usb_serial *serial); static int kobil_open (struct usb_serial_port *port, struct file *filp); static void kobil_close (struct usb_serial_port *port, struct file *filp); -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int kobil_write_room(struct usb_serial_port *port); static int kobil_ioctl(struct usb_serial_port *port, struct file *file, @@ -350,14 +350,13 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __FUNCTION__, port->number); - if (port->write_urb){ - usb_unlink_urb( port->write_urb ); + if (port->write_urb) { + usb_kill_urb(port->write_urb); usb_free_urb( port->write_urb ); port->write_urb = NULL; } - if (port->interrupt_in_urb){ - usb_unlink_urb (port->interrupt_in_urb); - } + if (port->interrupt_in_urb) + usb_kill_urb(port->interrupt_in_urb); } @@ -419,7 +418,7 @@ static void kobil_write_callback( struct urb *purb, struct pt_regs *regs ) } -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count) { int length = 0; @@ -440,13 +439,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user, } // Copy data to buffer - if (from_user) { - if (copy_from_user(priv->buf + priv->filled, buf, count)) { - return -EFAULT; - } - } else { - memcpy (priv->buf + priv->filled, buf, count); - } + memcpy (priv->buf + priv->filled, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled); @@ -458,9 +451,8 @@ static int kobil_write (struct usb_serial_port *port, int from_user, ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { // stop reading (except TWIN and KAAN SIM) - if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { - usb_unlink_urb( port->interrupt_in_urb ); - } + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) + usb_kill_urb(port->interrupt_in_urb); todo = priv->filled - priv->cur_pos; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index b4961f0d2..1c16a1f0b 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -110,7 +110,6 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp); #ifdef FIX_WRITE_RETURN_CODE_PROBLEM static int mct_u232_write (struct usb_serial_port *port, - int from_user, const unsigned char *buf, int count); static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs); @@ -237,7 +236,7 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) { static int mct_u232_set_baud_rate(struct usb_serial *serial, int value) { - unsigned int divisor; + __le32 divisor; int rc; unsigned char zero_byte = 0; @@ -480,9 +479,9 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) if (port->serial->dev) { /* shutdown our urbs */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - usb_unlink_urb (port->interrupt_in_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); } } /* mct_u232_close */ @@ -490,7 +489,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) #ifdef FIX_WRITE_RETURN_CODE_PROBLEM /* The generic routines work fine otherwise */ -static int mct_u232_write (struct usb_serial_port *port, int from_user, +static int mct_u232_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; @@ -519,14 +518,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user, usb_serial_debug_data(debug, &port->dev, __FUNCTION__, size, buf); - if (from_user) { - if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { - return -EFAULT; - } - } - else { - memcpy (port->write_urb->transfer_buffer, buf, size); - } + memcpy (port->write_urb->transfer_buffer, buf, size); /* set up our urb */ usb_fill_bulk_urb(port->write_urb, serial->dev, @@ -579,11 +571,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs) if (write_blocking) { 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); - + tty_wakeup(tty); } else { /* from generic_write_bulk_callback */ schedule_work(&port->work); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 371aa2e8e..a1cba4b5f 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -67,7 +67,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp); static void omninet_close (struct usb_serial_port *port, struct file *filp); static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs); -static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room (struct usb_serial_port *port); static void omninet_shutdown (struct usb_serial *serial); @@ -183,8 +183,8 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); wport = serial->port[1]; - usb_unlink_urb(wport->write_urb); - usb_unlink_urb(port->read_urb); + usb_kill_urb(wport->write_urb); + usb_kill_urb(port->read_urb); od = usb_get_serial_port_data(port); if (od) @@ -241,7 +241,7 @@ static void omninet_read_bulk_callback (struct urb *urb, struct pt_regs *regs) return; } -static int omninet_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct usb_serial_port *wport = serial->port[1]; @@ -264,15 +264,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; - if (from_user) { - if (copy_from_user(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count) != 0) { - result = -EFAULT; - goto exit; - } - } - else { - memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); - } + memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, wport->write_urb->transfer_buffer); @@ -291,7 +283,6 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns else result = count; -exit: return result; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index af0d230c6..3368d2b04 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -55,18 +55,35 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.11" +#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" static int debug; +#define PL2303_CLOSING_WAIT (30*HZ) + +#define PL2303_BUF_SIZE 1024 +#define PL2303_TMP_BUF_SIZE 1024 + +static DECLARE_MUTEX(pl2303_tmp_buf_sem); + +struct pl2303_buf { + unsigned int buf_size; + char *buf_buf; + char *buf_get; + char *buf_put; +}; + static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, + { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, @@ -76,6 +93,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, { } /* Terminating entry */ }; @@ -132,14 +150,26 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs); static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); -static int pl2303_write (struct usb_serial_port *port, int from_user, +static int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count); +static void pl2303_send (struct usb_serial_port *port); +static int pl2303_write_room(struct usb_serial_port *port); +static int pl2303_chars_in_buffer(struct usb_serial_port *port); static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static int pl2303_startup (struct usb_serial *serial); static void pl2303_shutdown (struct usb_serial *serial); +static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); +static void pl2303_buf_free(struct pl2303_buf *pb); +static void pl2303_buf_clear(struct pl2303_buf *pb); +static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); +static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); +static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, + unsigned int count); +static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, + unsigned int count); /* All of the device info needed for the PL2303 SIO serial converter */ @@ -162,6 +192,8 @@ static struct usb_serial_device_type pl2303_device = { .read_bulk_callback = pl2303_read_bulk_callback, .read_int_callback = pl2303_read_int_callback, .write_bulk_callback = pl2303_write_bulk_callback, + .write_room = pl2303_write_room, + .chars_in_buffer = pl2303_chars_in_buffer, .attach = pl2303_startup, .shutdown = pl2303_shutdown, }; @@ -174,6 +206,8 @@ enum pl2303_type { struct pl2303_private { spinlock_t lock; + struct pl2303_buf *buf; + int write_urb_in_use; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; @@ -201,14 +235,28 @@ static int pl2303_startup (struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); if (!priv) - return -ENOMEM; + goto cleanup; memset (priv, 0x00, sizeof (struct pl2303_private)); spin_lock_init(&priv->lock); + priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); + if (priv->buf == NULL) { + kfree(priv); + goto cleanup; + } init_waitqueue_head(&priv->delta_msr_wait); priv->type = type; usb_set_serial_port_data(serial->port[i], priv); } return 0; + +cleanup: + for (--i; i>=0; --i) { + priv = usb_get_serial_port_data(serial->port[i]); + pl2303_buf_free(priv->buf); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } + return -ENOMEM; } static int set_control_lines (struct usb_device *dev, u8 value) @@ -222,42 +270,97 @@ static int set_control_lines (struct usb_device *dev, u8 value) return retval; } -static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int pl2303_write (struct usb_serial_port *port, const unsigned char *buf, int count) { - int result; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); if (!count) return count; - if (port->write_urb->status == -EINPROGRESS) { - dbg("%s - already writing", __FUNCTION__); - return 0; + spin_lock_irqsave(&priv->lock, flags); + count = pl2303_buf_put(priv->buf, buf, count); + spin_unlock_irqrestore(&priv->lock, flags); + + pl2303_send(port); + + return count; +} + +static void pl2303_send(struct usb_serial_port *port) +{ + int count, result; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->write_urb_in_use) { + spin_unlock_irqrestore(&priv->lock, flags); + return; } - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (from_user) { - if (copy_from_user (port->write_urb->transfer_buffer, buf, count)) - return -EFAULT; - } else { - memcpy (port->write_urb->transfer_buffer, buf, count); + count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, + port->bulk_out_size); + + if (count == 0) { + spin_unlock_irqrestore(&priv->lock, flags); + return; } - + + priv->write_urb_in_use = 1; + + spin_unlock_irqrestore(&priv->lock, flags); + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); port->write_urb->transfer_buffer_length = count; port->write_urb->dev = port->serial->dev; result = usb_submit_urb (port->write_urb, GFP_ATOMIC); - if (result) + if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); - else - result = count; + priv->write_urb_in_use = 0; + // TODO: reschedule pl2303_send + } - return result; + schedule_work(&port->work); +} + +static int pl2303_write_room(struct usb_serial_port *port) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + int room = 0; + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + room = pl2303_buf_space_avail(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - returns %d", __FUNCTION__, room); + return room; } +static int pl2303_chars_in_buffer(struct usb_serial_port *port) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + int chars = 0; + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock_irqsave(&priv->lock, flags); + chars = pl2303_buf_data_avail(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - returns %d", __FUNCTION__, chars); + return chars; +} static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) { @@ -422,7 +525,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol } kfree (buf); -} +} static int pl2303_open (struct usb_serial_port *port, struct file *filp) { @@ -461,7 +564,7 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp) FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0); - + if (priv->type == HX) { /* HX chip */ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44); @@ -504,45 +607,67 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp) static void pl2303_close (struct usb_serial_port *port, struct file *filp) { - struct pl2303_private *priv; + struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int c_cflag; - int result; + int bps; + long timeout; + wait_queue_t wait; \ dbg("%s - port %d", __FUNCTION__, port->number); - /* shutdown our urbs */ - dbg("%s - shutting down urbs", __FUNCTION__); - result = usb_unlink_urb (port->write_urb); - if (result) - dbg("%s - usb_unlink_urb (write_urb)" - " failed with reason: %d", __FUNCTION__, - result); + /* wait for data to drain from the buffer */ + spin_lock_irqsave(&priv->lock, flags); + timeout = PL2303_CLOSING_WAIT; + init_waitqueue_entry(&wait, current); + add_wait_queue(&port->tty->write_wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (pl2303_buf_data_avail(priv->buf) == 0 + || timeout == 0 || signal_pending(current) + || !usb_get_intfdata(port->serial->interface)) /* disconnect */ + break; + spin_unlock_irqrestore(&priv->lock, flags); + timeout = schedule_timeout(timeout); + spin_lock_irqsave(&priv->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->tty->write_wait, &wait); + /* clear out any remaining data in the buffer */ + pl2303_buf_clear(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); - result = usb_unlink_urb (port->read_urb); - if (result) - dbg("%s - usb_unlink_urb (read_urb) " - "failed with reason: %d", __FUNCTION__, - result); + /* wait for characters to drain from the device */ + /* (this is long enough for the entire 256 byte */ + /* pl2303 hardware buffer to drain with no flow */ + /* control for data rates of 1200 bps or more, */ + /* for lower rates we should really know how much */ + /* data is in the buffer to compute a delay */ + /* that is not unnecessarily long) */ + bps = tty_get_baud_rate(port->tty); + if (bps > 1200) + timeout = max((HZ*2560)/bps,HZ/10); + else + timeout = 2*HZ; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(timeout); - result = usb_unlink_urb (port->interrupt_in_urb); - if (result) - dbg("%s - usb_unlink_urb (interrupt_in_urb)" - " failed with reason: %d", __FUNCTION__, - result); + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __FUNCTION__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); if (port->tty) { c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop DTR and RTS */ - priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; spin_unlock_irqrestore (&priv->lock, flags); set_control_lines (port->serial->dev, 0); } } - } static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, @@ -659,7 +784,7 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) state = BREAK_OFF; else state = BREAK_ON; - dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__); + dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on"); result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, @@ -672,12 +797,17 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) static void pl2303_shutdown (struct usb_serial *serial) { int i; + struct pl2303_private *priv; dbg("%s", __FUNCTION__); for (i = 0; i < serial->num_ports; ++i) { - kfree (usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + priv = usb_get_serial_port_data(serial->port[i]); + if (priv) { + pl2303_buf_free(priv->buf); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } } } @@ -815,11 +945,23 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct pl2303_private *priv = usb_get_serial_port_data(port); int result; dbg("%s - port %d", __FUNCTION__, port->number); - - if (urb->status) { + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + priv->write_urb_in_use = 0; + return; + default: /* error in the urb, so we have to resubmit it */ dbg("%s - Overflow in write", __FUNCTION__); dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); @@ -828,14 +970,199 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) result = usb_submit_urb (port->write_urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result); + else + return; + } - return; + priv->write_urb_in_use = 0; + + /* send any buffered data */ + pl2303_send(port); +} + + +/* + * pl2303_buf_alloc + * + * Allocate a circular buffer and all associated memory. + */ + +static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) +{ + + struct pl2303_buf *pb; + + + if (size == 0) + return NULL; + + pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); + if (pb == NULL) + return NULL; + + pb->buf_buf = kmalloc(size, GFP_KERNEL); + if (pb->buf_buf == NULL) { + kfree(pb); + return NULL; } - schedule_work(&port->work); + pb->buf_size = size; + pb->buf_get = pb->buf_put = pb->buf_buf; + + return pb; + +} + + +/* + * pl2303_buf_free + * + * Free the buffer and all associated memory. + */ + +static void pl2303_buf_free(struct pl2303_buf *pb) +{ + if (pb != NULL) { + if (pb->buf_buf != NULL) + kfree(pb->buf_buf); + kfree(pb); + } +} + + +/* + * pl2303_buf_clear + * + * Clear out all data in the circular buffer. + */ + +static void pl2303_buf_clear(struct pl2303_buf *pb) +{ + if (pb != NULL) + pb->buf_get = pb->buf_put; + /* equivalent to a get of all data available */ +} + + +/* + * pl2303_buf_data_avail + * + * Return the number of bytes of data available in the circular + * buffer. + */ + +static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) +{ + if (pb != NULL) + return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); + else + return 0; +} + + +/* + * pl2303_buf_space_avail + * + * Return the number of bytes of space available in the circular + * buffer. + */ + +static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) +{ + if (pb != NULL) + return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); + else + return 0; +} + + +/* + * pl2303_buf_put + * + * Copy data data from a user buffer and put it into the circular buffer. + * Restrict to the amount of space available. + * + * Return the number of bytes copied. + */ + +static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, + unsigned int count) +{ + + unsigned int len; + + + if (pb == NULL) + return 0; + + len = pl2303_buf_space_avail(pb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = pb->buf_buf + pb->buf_size - pb->buf_put; + if (count > len) { + memcpy(pb->buf_put, buf, len); + memcpy(pb->buf_buf, buf+len, count - len); + pb->buf_put = pb->buf_buf + count - len; + } else { + memcpy(pb->buf_put, buf, count); + if (count < len) + pb->buf_put += count; + else /* count == len */ + pb->buf_put = pb->buf_buf; + } + + return count; + } +/* + * pl2303_buf_get + * + * Get data from the circular buffer and copy to the given buffer. + * Restrict to the amount of data available. + * + * Return the number of bytes copied. + */ + +static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, + unsigned int count) +{ + + unsigned int len; + + + if (pb == NULL) + return 0; + + len = pl2303_buf_data_avail(pb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = pb->buf_buf + pb->buf_size - pb->buf_get; + if (count > len) { + memcpy(buf, pb->buf_get, len); + memcpy(buf+len, pb->buf_buf, count - len); + pb->buf_get = pb->buf_buf + count - len; + } else { + memcpy(buf, pb->buf_get, count); + if (count < len) + pb->buf_get += count; + else /* count == len */ + pb->buf_get = pb->buf_buf; + } + + return count; + +} + static int __init pl2303_init (void) { int retval; @@ -865,6 +1192,7 @@ module_init(pl2303_init); module_exit(pl2303_exit); MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 7fd65b044..6c1b4712d 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -9,7 +9,9 @@ */ #define PL2303_VENDOR_ID 0x067b #define PL2303_PRODUCT_ID 0x2303 -#define PL2303_PRODUCT_ID_RSAQ2 0x04bb +#define PL2303_PRODUCT_ID_RSAQ2 0x04bb +#define PL2303_PRODUCT_ID_PHAROS 0xaaa0 +#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 @@ -20,6 +22,7 @@ #define ELCOM_VENDOR_ID 0x056e #define ELCOM_PRODUCT_ID 0x5003 +#define ELCOM_PRODUCT_ID_UCSGT 0x5004 #define ITEGNO_VENDOR_ID 0x0eba #define ITEGNO_PRODUCT_ID 0x1080 @@ -47,6 +50,8 @@ #define ALCATEL_PRODUCT_ID 0x02df /* Samsung I330 phone cradle */ -#define SAMSUNG_VENDOR_ID 0x04e8 -#define SAMSUNG_PRODUCT_ID 0x8001 +#define SAMSUNG_VENDOR_ID 0x04e8 +#define SAMSUNG_PRODUCT_ID 0x8001 +#define SIEMENS_VENDOR_ID 0x11f5 +#define SIEMENS_PRODUCT_ID_X65 0x0003 diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index fa0abc4b6..0e85ed6c6 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -273,7 +273,7 @@ static void safe_read_bulk_callback (struct urb *urb, struct pt_regs *regs) } } -static int safe_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count) { unsigned char *data; int result; @@ -314,12 +314,7 @@ static int safe_write (struct usb_serial_port *port, int from_user, const unsign data = port->write_urb->transfer_buffer; memset (data, '0', packet_length); - if (from_user) { - if (copy_from_user (data, buf, count)) - return -EFAULT; - } else { - memcpy (data, buf, count); - } + memcpy (data, buf, count); if (safe) { __u16 fcs; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 2656807d7..e6c344bdb 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -388,7 +388,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po good_spot = 1; for (j = 1; j <= num_ports-1; ++j) - if ((serial_table[i+j]) || (i+j >= SERIAL_TTY_MINORS)) { + if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) { good_spot = 0; i += j; break; @@ -405,7 +405,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po return NULL; } -static void return_serial (struct usb_serial *serial) +static void return_serial(struct usb_serial *serial) { int i; @@ -417,8 +417,60 @@ static void return_serial (struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { serial_table[serial->minor + i] = NULL; } +} + +static void destroy_serial(struct kref *kref) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + int i; + + serial = to_usb_serial(kref); + + dbg ("%s - %s", __FUNCTION__, serial->type->name); + + serial->type->shutdown(serial); + + /* return the minor range that this device had */ + return_serial(serial); + + for (i = 0; i < serial->num_ports; ++i) + serial->port[i]->open_count = 0; + + /* the ports are cleaned up and released in port_release() */ + for (i = 0; i < serial->num_ports; ++i) + if (serial->port[i]->dev.parent != NULL) { + device_unregister(&serial->port[i]->dev); + serial->port[i] = NULL; + } + + /* If this is a "fake" port, we have to clean it up here, as it will + * not get cleaned up in port_release() as it was never registered with + * the driver core */ + if (serial->num_ports < serial->num_port_pointers) { + for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { + port = serial->port[i]; + if (!port) + continue; + usb_kill_urb(port->read_urb); + usb_free_urb(port->read_urb); + usb_kill_urb(port->write_urb); + usb_free_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); + usb_free_urb(port->interrupt_out_urb); + kfree(port->bulk_in_buffer); + kfree(port->bulk_out_buffer); + kfree(port->interrupt_in_buffer); + kfree(port->interrupt_out_buffer); + } + } + + usb_put_dev(serial->dev); - return; + /* free up any memory that we allocated */ + kfree (serial); } /***************************************************************************** @@ -429,46 +481,51 @@ static int serial_open (struct tty_struct *tty, struct file * filp) struct usb_serial *serial; struct usb_serial_port *port; unsigned int portNumber; - int retval = 0; + int retval; dbg("%s", __FUNCTION__); - /* initialize the pointer incase something fails */ - tty->driver_data = NULL; - /* get the serial object associated with this tty pointer */ serial = usb_serial_get_by_index(tty->index); if (!serial) { - retval = -ENODEV; - goto bailout; + tty->driver_data = NULL; + return -ENODEV; } - /* set up our port structure making the tty driver remember our port object, and us it */ portNumber = tty->index - serial->minor; port = serial->port[portNumber]; - tty->driver_data = port; - - port->tty = tty; - /* lock this module before we call it, - this may, which means we must bail out, safe because we are called with BKL held */ - if (!try_module_get(serial->type->owner)) { - retval = -ENODEV; - goto bailout; - } - ++port->open_count; + if (port->open_count == 1) { + + /* set up our port structure making the tty driver + * remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; + + /* lock this module before we call it + * this may fail, which means we must bail out, + * safe because we are called with BKL held */ + if (!try_module_get(serial->type->owner)) { + retval = -ENODEV; + goto bailout_kref_put; + } + /* only call the device specific open if this * is the first time the port is opened */ retval = serial->type->open(port, filp); - if (retval) { - port->open_count = 0; - module_put(serial->type->owner); - kref_put(&serial->kref); - } + if (retval) + goto bailout_module_put; } -bailout: + + return 0; + +bailout_module_put: + module_put(serial->type->owner); +bailout_kref_put: + kref_put(&serial->kref, destroy_serial); + port->open_count = 0; return retval; } @@ -481,25 +538,28 @@ static void serial_close(struct tty_struct *tty, struct file * filp) dbg("%s - port %d", __FUNCTION__, port->number); + if (port->open_count == 0) + return; + --port->open_count; - if (port->open_count <= 0) { + if (port->open_count == 0) { /* only call the device specific close if this * port is being closed by the last owner */ port->serial->type->close(port, filp); - port->open_count = 0; if (port->tty) { if (port->tty->driver_data) port->tty->driver_data = NULL; port->tty = NULL; } + + module_put(port->serial->type->owner); } - module_put(port->serial->type->owner); - kref_put(&port->serial->kref); + kref_put(&port->serial->kref, destroy_serial); } -static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; int retval = -EINVAL; @@ -512,7 +572,7 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned } /* pass on to the driver specific version of this function */ - retval = port->serial->type->write(port, from_user, buf, count); + retval = port->serial->type->write(port, buf, count); exit: return retval; @@ -564,15 +624,12 @@ static void serial_throttle (struct tty_struct * tty) if (!port->open_count) { dbg ("%s - port not open", __FUNCTION__); - goto exit; + return; } /* pass on to the driver specific version of this function */ if (port->serial->type->throttle) port->serial->type->throttle(port); - -exit: - ; } static void serial_unthrottle (struct tty_struct * tty) @@ -583,15 +640,12 @@ static void serial_unthrottle (struct tty_struct * tty) if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return; } /* pass on to the driver specific version of this function */ if (port->serial->type->unthrottle) port->serial->type->unthrottle(port); - -exit: - ; } static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -624,15 +678,12 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old) if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return; } /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->set_termios) port->serial->type->set_termios(port, old); - -exit: - ; } static void serial_break (struct tty_struct *tty, int break_state) @@ -643,22 +694,12 @@ static void serial_break (struct tty_struct *tty, int break_state) if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return; } /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->break_ctl) port->serial->type->break_ctl(port, break_state); - -exit: - ; -} - -static void serial_shutdown (struct usb_serial *serial) -{ - dbg ("%s", __FUNCTION__); - - serial->type->shutdown(serial); } static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) @@ -694,7 +735,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int begin += length; length = 0; } - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } *eof = 1; done: @@ -755,68 +796,7 @@ void usb_serial_port_softint(void *private) if (!tty) return; - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - dbg("%s - write wakeup call.", __FUNCTION__); - (tty->ldisc.write_wakeup)(tty); - } - - wake_up_interruptible(&tty->write_wait); -} - -static void destroy_serial(struct kref *kref) -{ - struct usb_serial *serial; - struct usb_serial_port *port; - int i; - - serial = to_usb_serial(kref); - - dbg ("%s - %s", __FUNCTION__, serial->type->name); - serial_shutdown (serial); - - /* return the minor range that this device had */ - return_serial(serial); - - for (i = 0; i < serial->num_ports; ++i) - serial->port[i]->open_count = 0; - - /* the ports are cleaned up and released in port_release() */ - for (i = 0; i < serial->num_ports; ++i) - if (serial->port[i]->dev.parent != NULL) { - device_unregister(&serial->port[i]->dev); - serial->port[i] = NULL; - } - - /* If this is a "fake" port, we have to clean it up here, as it will - * not get cleaned up in port_release() as it was never registered with - * the driver core */ - if (serial->num_ports < serial->num_port_pointers) { - for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { - port = serial->port[i]; - if (!port) - continue; - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } - kfree(port->bulk_in_buffer); - kfree(port->bulk_out_buffer); - kfree(port->interrupt_in_buffer); - } - } - - usb_put_dev(serial->dev); - - /* free up any memory that we allocated */ - kfree (serial); + tty_wakeup(tty); } static void port_release(struct device *dev) @@ -824,21 +804,18 @@ static void port_release(struct device *dev) struct usb_serial_port *port = to_usb_serial_port(dev); dbg ("%s - %s", __FUNCTION__, dev->bus_id); - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } + usb_kill_urb(port->read_urb); + usb_free_urb(port->read_urb); + usb_kill_urb(port->write_urb); + usb_free_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); + usb_free_urb(port->interrupt_out_urb); kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer); + kfree(port->interrupt_out_buffer); kfree(port); } @@ -859,11 +836,30 @@ static struct usb_serial * create_serial (struct usb_device *dev, serial->interface = interface; serial->vendor = dev->descriptor.idVendor; serial->product = dev->descriptor.idProduct; - kref_init(&serial->kref, destroy_serial); + kref_init(&serial->kref); return serial; } +static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface) +{ + struct list_head *p; + const struct usb_device_id *id; + struct usb_serial_device_type *t; + + /* List trough know devices and see if the usb id matches */ + list_for_each(p, &usb_serial_driver_list) { + t = list_entry(p, struct usb_serial_device_type, driver_list); + id = usb_match_id(iface, t->id_table); + if (id != NULL) { + dbg("descriptor matches"); + return t; + } + } + + return NULL; +} + int usb_serial_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -873,36 +869,23 @@ int usb_serial_probe(struct usb_interface *interface, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; + struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; struct usb_serial_device_type *type = NULL; - struct list_head *tmp; int retval; - int found; int minor; int buffer_size; int i; int num_interrupt_in = 0; + int num_interrupt_out = 0; int num_bulk_in = 0; int num_bulk_out = 0; int num_ports = 0; int max_endpoints; - const struct usb_device_id *id_pattern = NULL; - - /* loop through our list of known serial converters, and see if this - device matches. */ - found = 0; - list_for_each (tmp, &usb_serial_driver_list) { - type = list_entry(tmp, struct usb_serial_device_type, driver_list); - id_pattern = usb_match_id(interface, type->id_table); - if (id_pattern != NULL) { - dbg("descriptor matches"); - found = 1; - break; - } - } - if (!found) { - /* no match */ + + type = search_serial_device(interface); + if (!type) { dbg("none matched"); return -ENODEV; } @@ -910,17 +893,21 @@ int usb_serial_probe(struct usb_interface *interface, serial = create_serial (dev, interface, type); if (!serial) { dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); - return -ENODEV; + return -ENOMEM; } /* if this device type has a probe function, call it */ if (type->probe) { + const struct usb_device_id *id; + if (!try_module_get(type->owner)) { dev_err(&interface->dev, "module get failed, exiting\n"); kfree (serial); return -EIO; } - retval = type->probe (serial, id_pattern); + + id = usb_match_id(interface, type->id_table); + retval = type->probe(serial, id); module_put(type->owner); if (retval) { @@ -939,7 +926,7 @@ int usb_serial_probe(struct usb_interface *interface, if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ - dbg("found bulk in"); + dbg("found bulk in on endpoint %d", i); bulk_in_endpoint[num_bulk_in] = endpoint; ++num_bulk_in; } @@ -947,7 +934,7 @@ int usb_serial_probe(struct usb_interface *interface, if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk out endpoint */ - dbg("found bulk out"); + dbg("found bulk out on endpoint %d", i); bulk_out_endpoint[num_bulk_out] = endpoint; ++num_bulk_out; } @@ -955,10 +942,18 @@ int usb_serial_probe(struct usb_interface *interface, if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x03)) { /* we found a interrupt in endpoint */ - dbg("found interrupt in"); + dbg("found interrupt in on endpoint %d", i); interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found an interrupt out endpoint */ + dbg("found interrupt out on endpoint %d", i); + interrupt_out_endpoint[num_interrupt_out] = endpoint; + ++num_interrupt_out; + } } #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) @@ -1035,11 +1030,13 @@ int usb_serial_probe(struct usb_interface *interface, serial->num_bulk_in = num_bulk_in; serial->num_bulk_out = num_bulk_out; serial->num_interrupt_in = num_interrupt_in; + serial->num_interrupt_out = num_interrupt_out; /* create our ports, we need as many as the max endpoints */ /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ max_endpoints = max(num_bulk_in, num_bulk_out); max_endpoints = max(max_endpoints, num_interrupt_in); + max_endpoints = max(max_endpoints, num_interrupt_out); max_endpoints = max(max_endpoints, (int)serial->num_ports); serial->num_port_pointers = max_endpoints; dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); @@ -1064,6 +1061,7 @@ int usb_serial_probe(struct usb_interface *interface, goto probe_error; } buffer_size = endpoint->wMaxPacketSize; + port->bulk_in_size = buffer_size; port->bulk_in_endpointAddress = endpoint->bEndpointAddress; port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!port->bulk_in_buffer) { @@ -1102,29 +1100,61 @@ int usb_serial_probe(struct usb_interface *interface, port); } - for (i = 0; i < num_interrupt_in; ++i) { - endpoint = interrupt_in_endpoint[i]; - port = serial->port[i]; - port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->interrupt_in_urb) { - dev_err(&interface->dev, "No free urbs available\n"); - goto probe_error; + if (serial->type->read_int_callback) { + for (i = 0; i < num_interrupt_in; ++i) { + endpoint = interrupt_in_endpoint[i]; + port = serial->port[i]; + port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->interrupt_in_urb) { + dev_err(&interface->dev, "No free urbs available\n"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; + port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!port->interrupt_in_buffer) { + dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n"); + goto probe_error; + } + usb_fill_int_urb (port->interrupt_in_urb, dev, + usb_rcvintpipe (dev, + endpoint->bEndpointAddress), + port->interrupt_in_buffer, buffer_size, + serial->type->read_int_callback, port, + endpoint->bInterval); } - buffer_size = endpoint->wMaxPacketSize; - port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; - port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!port->interrupt_in_buffer) { - dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n"); - goto probe_error; + } else if (num_interrupt_in) { + dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined"); + } + + if (serial->type->write_int_callback) { + for (i = 0; i < num_interrupt_out; ++i) { + endpoint = interrupt_out_endpoint[i]; + port = serial->port[i]; + port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->interrupt_out_urb) { + dev_err(&interface->dev, "No free urbs available\n"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + port->interrupt_out_size = buffer_size; + port->interrupt_out_endpointAddress = endpoint->bEndpointAddress; + port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!port->interrupt_out_buffer) { + dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n"); + goto probe_error; + } + usb_fill_int_urb (port->interrupt_out_urb, dev, + usb_sndintpipe (dev, + endpoint->bEndpointAddress), + port->interrupt_out_buffer, buffer_size, + serial->type->write_int_callback, port, + endpoint->bInterval); } - usb_fill_int_urb (port->interrupt_in_urb, dev, - usb_rcvintpipe (dev, - endpoint->bEndpointAddress), - port->interrupt_in_buffer, buffer_size, - serial->type->read_int_callback, port, - endpoint->bInterval); + } else if (num_interrupt_out) { + dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); } - + /* if this device type has an attach function, call it */ if (type->attach) { if (!try_module_get(type->owner)) { @@ -1187,6 +1217,14 @@ probe_error: usb_free_urb (port->interrupt_in_urb); kfree(port->interrupt_in_buffer); } + for (i = 0; i < num_interrupt_out; ++i) { + port = serial->port[i]; + if (!port) + continue; + if (port->interrupt_out_urb) + usb_free_urb (port->interrupt_out_urb); + kfree(port->interrupt_out_buffer); + } /* return the minor range that this device had */ return_serial (serial); @@ -1209,7 +1247,7 @@ void usb_serial_disconnect(struct usb_interface *interface) if (serial) { /* let the last holder of this object * cause it to be cleaned up */ - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } dev_info(dev, "device disconnected\n"); } @@ -1235,7 +1273,7 @@ struct tty_driver *usb_serial_tty_driver; static int __init usb_serial_init(void) { int i; - int result = 0; + int result; usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); if (!usb_serial_tty_driver) @@ -1246,13 +1284,17 @@ static int __init usb_serial_init(void) serial_table[i] = NULL; } - bus_register(&usb_serial_bus_type); + result = bus_register(&usb_serial_bus_type); + if (result) { + err("%s - registering bus driver failed", __FUNCTION__); + goto exit_bus; + } /* register the generic driver, if we should */ result = usb_serial_generic_register(debug); if (result < 0) { err("%s - registering generic driver failed", __FUNCTION__); - goto exit; + goto exit_generic; } usb_serial_tty_driver->owner = THIS_MODULE; @@ -1270,7 +1312,7 @@ static int __init usb_serial_init(void) result = tty_register_driver(usb_serial_tty_driver); if (result) { err("%s - tty_register_driver failed", __FUNCTION__); - goto exit_generic; + goto exit_reg_driver; } /* register the USB driver */ @@ -1287,10 +1329,13 @@ static int __init usb_serial_init(void) exit_tty: tty_unregister_driver(usb_serial_tty_driver); -exit_generic: +exit_reg_driver: usb_serial_generic_deregister(); -exit: +exit_generic: + bus_unregister(&usb_serial_bus_type); + +exit_bus: err ("%s - returning with error %d", __FUNCTION__, result); put_tty_driver(usb_serial_tty_driver); return result; @@ -1343,17 +1388,13 @@ int usb_serial_register(struct usb_serial_device_type *new_device) /* Add this device to our list of devices */ list_add(&new_device->driver_list, &usb_serial_driver_list); - retval = usb_serial_bus_register (new_device); - - if (retval) - goto error; - - info("USB Serial support registered for %s", new_device->name); - - return retval; -error: - err("problem %d when registering driver %s", retval, new_device->name); - list_del(&new_device->driver_list); + retval = usb_serial_bus_register(new_device); + if (retval) { + err("problem %d when registering driver %s", retval, new_device->name); + list_del(&new_device->driver_list); + } + else + info("USB Serial support registered for %s", new_device->name); return retval; } @@ -1380,6 +1421,7 @@ EXPORT_SYMBOL(usb_serial_port_softint); /* Module information */ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_VERSION( DRIVER_VERSION ); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index e2e59560d..1daf0752f 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -74,6 +74,11 @@ * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe * for this port. + * @interrupt_out_buffer: pointer to the interrupt out buffer for this port. + * @interrupt_out_size: the size of the interrupt_out_buffer, in bytes. + * @interrupt_out_urb: pointer to the interrupt out struct urb for this port. + * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe + * for this port. * @bulk_in_buffer: pointer to the bulk in buffer for this port. * @read_urb: pointer to the bulk in struct urb for this port. * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this @@ -99,7 +104,13 @@ struct usb_serial_port { struct urb * interrupt_in_urb; __u8 interrupt_in_endpointAddress; + unsigned char * interrupt_out_buffer; + int interrupt_out_size; + struct urb * interrupt_out_urb; + __u8 interrupt_out_endpointAddress; + unsigned char * bulk_in_buffer; + int bulk_in_size; struct urb * read_urb; __u8 bulk_in_endpointAddress; @@ -134,6 +145,7 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void * @minor: the starting minor number for this device * @num_ports: the number of ports this device has * @num_interrupt_in: number of interrupt in endpoints we have + * @num_interrupt_out: number of interrupt out endpoints we have * @num_bulk_in: number of bulk in endpoints we have * @num_bulk_out: number of bulk out endpoints we have * @vendor: vendor id of this device @@ -152,6 +164,7 @@ struct usb_serial { unsigned char num_ports; unsigned char num_port_pointers; char num_interrupt_in; + char num_interrupt_out; char num_bulk_in; char num_bulk_out; __u16 vendor; @@ -187,6 +200,8 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data) * of the devices this structure can support. * @num_interrupt_in: the number of interrupt in endpoints this device will * have. + * @num_interrupt_out: the number of interrupt out endpoints this device will + * have. * @num_bulk_in: the number of bulk in endpoints this device will have. * @num_bulk_out: the number of bulk out endpoints this device will have. * @num_ports: the number of different ports this device will have. @@ -219,6 +234,7 @@ struct usb_serial_device_type { char *short_name; const struct usb_device_id *id_table; char num_interrupt_in; + char num_interrupt_out; char num_bulk_in; char num_bulk_out; char num_ports; @@ -238,7 +254,7 @@ struct usb_serial_device_type { /* serial function calls */ int (*open) (struct usb_serial_port *port, struct file * filp); void (*close) (struct usb_serial_port *port, struct file * filp); - int (*write) (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); + int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count); int (*write_room) (struct usb_serial_port *port); int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); void (*set_termios) (struct usb_serial_port *port, struct termios * old); @@ -250,6 +266,7 @@ struct usb_serial_device_type { int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); void (*read_int_callback)(struct urb *urb, struct pt_regs *regs); + void (*write_int_callback)(struct urb *urb, struct pt_regs *regs); void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs); void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs); }; @@ -277,7 +294,7 @@ static inline void usb_serial_console_exit (void) { } /* Functions needed by other parts of the usbserial core */ extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); -extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write_room (struct usb_serial_port *port); extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 8a0a75533..d5b5cdd9e 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -168,7 +168,7 @@ /* function prototypes for a handspring visor */ static int visor_open (struct usb_serial_port *port, struct file *filp); static void visor_close (struct usb_serial_port *port, struct file *filp); -static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int visor_write_room (struct usb_serial_port *port); static int visor_chars_in_buffer (struct usb_serial_port *port); static void visor_throttle (struct usb_serial_port *port); @@ -381,10 +381,17 @@ static struct usb_serial_device_type clie_3_5_device = { .read_bulk_callback = visor_read_bulk_callback, }; +struct visor_private { + spinlock_t lock; + int bytes_in; + int bytes_out; + int outstanding_urbs; +}; -static int bytes_in; -static int bytes_out; +/* number of outstanding urbs to prevent userspace DoS from happening */ +#define URB_UPPER_LIMIT 42 +static int stats; /****************************************************************************** * Handspring Visor specific driver functions @@ -392,6 +399,8 @@ static int bytes_out; static int visor_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; int result = 0; dbg("%s - port %d", __FUNCTION__, port->number); @@ -402,8 +411,11 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) return -ENODEV; } - bytes_in = 0; - bytes_out = 0; + spin_lock_irqsave(&priv->lock, flags); + priv->bytes_in = 0; + priv->bytes_out = 0; + priv->outstanding_urbs = 0; + spin_unlock_irqrestore(&priv->lock, flags); /* * Force low_latency on so that our tty_push actually forces the data @@ -441,14 +453,15 @@ exit: static void visor_close (struct usb_serial_port *port, struct file * filp) { + struct visor_private *priv = usb_get_serial_port_data(port); unsigned char *transfer_buffer; dbg("%s - port %d", __FUNCTION__, port->number); /* shutdown our urbs */ - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); if (port->interrupt_in_urb) - usb_unlink_urb (port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); /* Try to send shutdown message, if the device is gone, this will just fail. */ transfer_buffer = kmalloc (0x12, GFP_KERNEL); @@ -461,20 +474,31 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) kfree (transfer_buffer); } - /* Uncomment the following line if you want to see some statistics in your syslog */ - /* dev_info (&port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */ + if (stats) + dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", + priv->bytes_in, priv->bytes_out); } -static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count) { + struct visor_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; struct urb *urb; unsigned char *buffer; + unsigned long flags; int status; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __FUNCTION__); + return 0; + } + spin_unlock_irqrestore(&priv->lock, flags); + buffer = kmalloc (count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); @@ -488,15 +512,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig return -ENOMEM; } - if (from_user) { - if (copy_from_user (buffer, buf, count)) { - kfree (buffer); - usb_free_urb (urb); - return -EFAULT; - } - } else { - memcpy (buffer, buf, count); - } + memcpy (buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); @@ -514,7 +530,10 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig count = status; kfree (buffer); } else { - bytes_out += count; + spin_lock_irqsave(&priv->lock, flags); + ++priv->outstanding_urbs; + priv->bytes_out += count; + spin_unlock_irqrestore(&priv->lock, flags); } /* we are done with this urb, so let the host driver @@ -555,6 +574,8 @@ static int visor_chars_in_buffer (struct usb_serial_port *port) static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree (urb->transfer_buffer); @@ -565,6 +586,10 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + schedule_work(&port->work); } @@ -572,8 +597,10 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; - struct tty_struct *tty; + struct visor_private *priv = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; + struct tty_struct *tty; + unsigned long flags; int i; int result; @@ -598,7 +625,9 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) } tty_flip_buffer_push(tty); } - bytes_in += urb->actual_length; + spin_lock_irqsave(&priv->lock, flags); + priv->bytes_in += urb->actual_length; + spin_unlock_irqrestore(&priv->lock, flags); /* Continue trying to always read */ usb_fill_bulk_urb (port->read_urb, port->serial->dev, @@ -655,7 +684,7 @@ exit: static void visor_throttle (struct usb_serial_port *port) { dbg("%s - port %d", __FUNCTION__, port->number); - usb_unlink_urb (port->read_urb); + usb_kill_urb(port->read_urb); } @@ -833,6 +862,22 @@ static int visor_calc_num_ports (struct usb_serial *serial) return num_ports; } +static int generic_startup(struct usb_serial *serial) +{ + struct visor_private *priv; + int i; + + for (i = 0; i < serial->num_ports; ++i) { + priv = kmalloc (sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + memset (priv, 0x00, sizeof(*priv)); + spin_lock_init(&priv->lock); + usb_set_serial_port_data(serial->port[i], priv); + } + return 0; +} + static int clie_3_5_startup (struct usb_serial *serial) { struct device *dev = &serial->dev->dev; @@ -872,7 +917,7 @@ static int clie_3_5_startup (struct usb_serial *serial) return -EIO; } - return 0; + return generic_startup(serial); } static int treo_attach (struct usb_serial *serial) @@ -884,7 +929,7 @@ static int treo_attach (struct usb_serial *serial) if (!((serial->dev->descriptor.idVendor == HANDSPRING_VENDOR_ID) || (serial->dev->descriptor.idVendor == KYOCERA_VENDOR_ID)) || (serial->num_interrupt_in == 0)) - return 0; + goto generic_startup; dbg("%s", __FUNCTION__); @@ -911,7 +956,8 @@ static int treo_attach (struct usb_serial *serial) COPY_PORT(serial->port[1], swap_port); kfree(swap_port); - return 0; +generic_startup: + return generic_startup(serial); } static int clie_5_attach (struct usb_serial *serial) @@ -932,7 +978,7 @@ static int clie_5_attach (struct usb_serial *serial) /* port 0 now uses the modified endpoint Address */ serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; - return 0; + return generic_startup(serial); } static void visor_shutdown (struct usb_serial *serial) @@ -1088,8 +1134,11 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); +module_param(stats, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(stats, "Enables statistics or not"); module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified vendor ID"); module_param(product, ushort, 0); MODULE_PARM_DESC(product, "User specified product ID"); + diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index b27741bf5..b6384a313 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -143,7 +143,7 @@ static int whiteheat_attach (struct usb_serial *serial); static void whiteheat_shutdown (struct usb_serial *serial); static int whiteheat_open (struct usb_serial_port *port, struct file *filp); static void whiteheat_close (struct usb_serial_port *port, struct file *filp); -static int whiteheat_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int whiteheat_write_room (struct usb_serial_port *port); static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); @@ -668,8 +668,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) if (port->tty->driver->flush_buffer) port->tty->driver->flush_buffer(port->tty); - if (port->tty->ldisc.flush_buffer) - port->tty->ldisc.flush_buffer(port->tty); + tty_ldisc_flush(port->tty); firm_report_tx_done(port); @@ -680,7 +679,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; - usb_unlink_urb(urb); + usb_kill_urb(urb); list_del(tmp); list_add(tmp, &info->rx_urbs_free); } @@ -691,7 +690,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; - usb_unlink_urb(urb); + usb_kill_urb(urb); list_del(tmp); list_add(tmp, &info->tx_urbs_free); } @@ -703,7 +702,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) } -static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; struct whiteheat_private *info = usb_get_serial_port_data(port); @@ -735,12 +734,7 @@ static int whiteheat_write(struct usb_serial_port *port, int from_user, const un wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count; - if (from_user) { - if (copy_from_user(urb->transfer_buffer, buf + sent, bytes)) - return -EFAULT; - } else { - memcpy (urb->transfer_buffer, buf + sent, bytes); - } + memcpy (urb->transfer_buffer, buf + sent, bytes); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer); @@ -1120,11 +1114,11 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 * command_port->write_urb->transfer_buffer_length = datasize + 1; command_port->write_urb->dev = port->serial->dev; retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL); - spin_unlock_irqrestore(&command_info->lock, flags); if (retval) { dbg("%s - submit urb failed", __FUNCTION__); goto exit; } + spin_unlock_irqrestore(&command_info->lock, flags); /* wait for the command to complete */ wait_event_interruptible_timeout(command_info->wait_command, @@ -1344,7 +1338,7 @@ static void stop_command_port(struct usb_serial *serial) spin_lock_irqsave(&command_info->lock, flags); command_info->port_running--; if (!command_info->port_running) - usb_unlink_urb(command_port->read_urb); + usb_kill_urb(command_port->read_urb); spin_unlock_irqrestore(&command_info->lock, flags); } @@ -1372,7 +1366,7 @@ static int start_port_read(struct usb_serial_port *port) list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; - usb_unlink_urb(urb); + usb_kill_urb(urb); list_del(tmp); list_add(tmp, &info->rx_urbs_free); } diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7e8d1212d..42424ab5e 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,16 +2,23 @@ # USB Storage driver configuration # +comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information" + config USB_STORAGE tristate "USB Mass Storage support" depends on USB select SCSI ---help--- Say Y here if you want to connect USB mass storage devices to your - computer's USB port. This is the driver you need for USB floppy drives, - USB hard disks, USB tape drives and USB CD-ROMs, along with - similar devices. This driver may also be used for some cameras and - card readers. + computer's USB port. This is the driver you need for USB + floppy drives, USB hard disks, USB tape drives, USB CD-ROMs, + USB flash devices, and memory sticks, along with + similar devices. This driver may also be used for some cameras + and card readers. + + This option 'selects' (turns on, enables) 'SCSI', but you + probably also need 'SCSI device support: SCSI disk support' + (BLK_DEV_SD) for most USB storage devices. To compile this driver as a module, choose M here: the module will be called usb-storage. diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 58baacc9a..94798eb1a 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -50,16 +50,19 @@ * in that routine. */ +#include +#include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "datafab.h" -#include -#include -#include - static int datafab_determine_lun(struct us_data *us, struct datafab_info *info); @@ -388,7 +391,7 @@ static int datafab_id_device(struct us_data *us, static int datafab_handle_mode_sense(struct us_data *us, - Scsi_Cmnd * srb, + struct scsi_cmnd * srb, int sense_6) { static unsigned char rw_err_page[12] = { @@ -483,7 +486,7 @@ static int datafab_handle_mode_sense(struct us_data *us, if (sense_6) ptr[0] = i - 1; else - ((u16 *) ptr)[0] = cpu_to_be16(i - 2); + ((__be16 *) ptr)[0] = cpu_to_be16(i - 2); usb_stor_set_xfer_buf(ptr, i, srb); return USB_STOR_TRANSPORT_GOOD; @@ -498,7 +501,7 @@ static void datafab_info_destructor(void *extra) // Transport for the Datafab MDCFE-B // -int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) +int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) { struct datafab_info *info; int rc; @@ -540,8 +543,8 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) // build the reply // we need the last sector, not the number of sectors - ((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); - ((u32 *) ptr)[1] = cpu_to_be32(info->ssize); + ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); + ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize); usb_stor_set_xfer_buf(ptr, 8, srb); return USB_STOR_TRANSPORT_GOOD; @@ -625,12 +628,12 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) if (srb->cmnd[0] == MODE_SENSE) { US_DEBUGP("datafab_transport: MODE_SENSE_6 detected\n"); - return datafab_handle_mode_sense(us, srb, TRUE); + return datafab_handle_mode_sense(us, srb, 1); } if (srb->cmnd[0] == MODE_SENSE_10) { US_DEBUGP("datafab_transport: MODE_SENSE_10 detected\n"); - return datafab_handle_mode_sense(us, srb, FALSE); + return datafab_handle_mode_sense(us, srb, 0); } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h index c9343f6e4..32e3f271e 100644 --- a/drivers/usb/storage/datafab.h +++ b/drivers/usb/storage/datafab.h @@ -24,7 +24,7 @@ #ifndef _USB_DATAFAB_MDCFE_B_H #define _USB_DATAFAB_MDCFE_B_H -extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us); struct datafab_info { unsigned long sectors; // total sector count diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c index d4f278ca7..d76483706 100644 --- a/drivers/usb/storage/debug.c +++ b/drivers/usb/storage/debug.c @@ -44,9 +44,15 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include + #include "debug.h" +#include "scsi.h" + -void usb_stor_show_command(Scsi_Cmnd *srb) +void usb_stor_show_command(struct scsi_cmnd *srb) { char *what = NULL; int i; diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h index d5d6b3c76..c4f4bcf36 100644 --- a/drivers/usb/storage/debug.h +++ b/drivers/usb/storage/debug.h @@ -46,13 +46,13 @@ #include #include -#include -#include "usb.h" + +struct scsi_cmnd; #define USB_STORAGE "usb-storage: " #ifdef CONFIG_USB_STORAGE_DEBUG -void usb_stor_show_command(Scsi_Cmnd *srb); +void usb_stor_show_command(struct scsi_cmnd *srb); void usb_stor_show_sense( unsigned char key, unsigned char asc, unsigned char ascq ); #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x ) diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c index ae135fd3c..12c15f19a 100644 --- a/drivers/usb/storage/dpcm.c +++ b/drivers/usb/storage/dpcm.c @@ -30,6 +30,10 @@ */ #include +#include +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" @@ -41,7 +45,7 @@ * Transport for the Microtech DPCM-USB * */ -int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us) +int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h index e6e5637d6..81b464cfc 100644 --- a/drivers/usb/storage/dpcm.h +++ b/drivers/usb/storage/dpcm.h @@ -29,6 +29,6 @@ #ifndef _MICROTECH_DPCM_USB_H #define _MICROTECH_DPCM_USB_H -extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); #endif diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 4b1ff0ad2..9df27f05d 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -29,12 +29,16 @@ */ #include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "freecom.h" -#include "linux/hdreg.h" #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); @@ -55,14 +59,14 @@ struct freecom_cb_wrap { struct freecom_xfer_wrap { u8 Type; /* Command type. */ u8 Timeout; /* Timeout in seconds. */ - u32 Count; /* Number of bytes to transfer. */ + __le32 Count; /* Number of bytes to transfer. */ u8 Pad[58]; } __attribute__ ((packed)); struct freecom_ide_out { u8 Type; /* Type + IDE register. */ u8 Pad; - u16 Value; /* Value to write. */ + __le16 Value; /* Value to write. */ u8 Pad2[60]; }; @@ -74,7 +78,7 @@ struct freecom_ide_in { struct freecom_status { u8 Status; u8 Reason; - u16 Count; + __le16 Count; u8 Pad[60]; }; @@ -105,7 +109,7 @@ struct freecom_status { #define FCM_STATUS_PACKET_LENGTH 4 static int -freecom_readdata (Scsi_Cmnd *srb, struct us_data *us, +freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, unsigned int ipipe, unsigned int opipe, int count) { struct freecom_xfer_wrap *fxfr = @@ -139,7 +143,7 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us, } static int -freecom_writedata (Scsi_Cmnd *srb, struct us_data *us, +freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, int unsigned ipipe, unsigned int opipe, int count) { struct freecom_xfer_wrap *fxfr = @@ -176,7 +180,7 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us, * Transport for the Freecom USB/IDE adaptor. * */ -int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) +int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; @@ -286,7 +290,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */ case MODE_SENSE: case MODE_SENSE_10: - length = fst->Count; + length = le16_to_cpu(fst->Count); break; default: length = srb->request_bufflen; @@ -302,7 +306,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) * move in. */ switch (us->srb->sc_data_direction) { - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: /* catch bogus "read 0 length" case */ if (!length) break; @@ -334,7 +338,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) US_DEBUGP("Transfer happy\n"); break; - case SCSI_DATA_WRITE: + case DMA_TO_DEVICE: /* catch bogus "write 0 length" case */ if (!length) break; @@ -364,7 +368,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us) break; - case SCSI_DATA_NONE: + case DMA_NONE: /* Easy, do nothing. */ break; diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h index 8c0ada8bb..1b012d62d 100644 --- a/drivers/usb/storage/freecom.h +++ b/drivers/usb/storage/freecom.h @@ -29,7 +29,7 @@ #ifndef _FREECOM_USB_H #define _FREECOM_USB_H -extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us); extern int usb_stor_freecom_reset(struct us_data *us); extern int freecom_init (struct us_data *us); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 43cc9c5e0..d6ac358bb 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -44,6 +44,16 @@ /* Include files */ +#include +#include +#include +#include +#include + +#include +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" @@ -51,11 +61,6 @@ #include "scsiglue.h" #include "isd200.h" -#include -#include -#include -#include -#include /* Timeout defines (in Seconds) */ @@ -290,8 +295,8 @@ struct isd200_info { */ struct read_capacity_data { - unsigned long LogicalBlockAddress; - unsigned long BytesPerBlock; + __be32 LogicalBlockAddress; + __be32 BytesPerBlock; }; /* @@ -349,7 +354,7 @@ struct sense_data { * RETURNS: * void */ -static void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb) +static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb) { struct isd200_info *info = (struct isd200_info *)us->extra; struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0]; @@ -427,7 +432,7 @@ static int isd200_action( struct us_data *us, int action, ata.generic.RegisterSelect = REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_STATUS | REG_ERROR; - srb->sc_data_direction = SCSI_DATA_READ; + srb->sc_data_direction = DMA_FROM_DEVICE; srb->request_buffer = pointer; srb->request_bufflen = value; break; @@ -439,7 +444,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_5; ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.write.DeviceHeadByte = value; - srb->sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = DMA_NONE; break; case ACTION_RESET: @@ -448,7 +453,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; - srb->sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = DMA_NONE; break; case ACTION_REENABLE: @@ -457,7 +462,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; - srb->sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = DMA_NONE; break; case ACTION_SOFT_RESET: @@ -466,14 +471,14 @@ static int isd200_action( struct us_data *us, int action, ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.write.DeviceHeadByte = info->DeviceHead; ata.write.CommandByte = WIN_SRST; - srb->sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = DMA_NONE; break; case ACTION_IDENTIFY: US_DEBUGP(" isd200_action(IDENTIFY)\n"); ata.generic.RegisterSelect = REG_COMMAND; ata.write.CommandByte = WIN_IDENTIFY; - srb->sc_data_direction = SCSI_DATA_READ; + srb->sc_data_direction = DMA_FROM_DEVICE; srb->request_buffer = (void *) info->id; srb->request_bufflen = sizeof(struct hd_driveid); break; @@ -535,7 +540,7 @@ static int isd200_read_regs( struct us_data *us ) * the device and receive the response. */ static void isd200_invoke_transport( struct us_data *us, - Scsi_Cmnd *srb, + struct scsi_cmnd *srb, union ata_cdb *ataCdb ) { int need_auto_sense = 0; @@ -550,7 +555,7 @@ static void isd200_invoke_transport( struct us_data *us, /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ - if (us->sm_state == US_STATE_ABORTING) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- command was aborted\n"); goto Handle_Abort; } @@ -597,7 +602,7 @@ static void isd200_invoke_transport( struct us_data *us, if (need_auto_sense) { result = isd200_read_regs(us); - if (us->sm_state == US_STATE_ABORTING) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); goto Handle_Abort; } @@ -839,7 +844,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, unsigned long endTime; struct isd200_info *info = (struct isd200_info *)us->extra; unsigned char *regs = info->RegsBuf; - int recheckAsMaster = FALSE; + int recheckAsMaster = 0; if ( detect ) endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ; @@ -847,7 +852,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ; /* loop until we detect !BSY or timeout */ - while(TRUE) { + while(1) { #ifdef CONFIG_USB_STORAGE_DEBUG char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ? "Master" : "Slave"; @@ -899,9 +904,9 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave, itself okay as a master also */ if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) && - (recheckAsMaster == FALSE)) { + !recheckAsMaster) { US_DEBUGP(" Identified ATAPI device as slave. Rechecking again as master\n"); - recheckAsMaster = TRUE; + recheckAsMaster = 1; master_slave = ATA_ADDRESS_DEVHEAD_STD; } else { US_DEBUGP(" Identified ATAPI device\n"); @@ -948,15 +953,15 @@ static int isd200_manual_enum(struct us_data *us) if (retStatus == ISD200_GOOD) { int isslave; /* master or slave? */ - retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE ); + retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 0); if (retStatus == ISD200_GOOD) - retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE ); + retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, 0); if (retStatus == ISD200_GOOD) { retStatus = isd200_srst(us); if (retStatus == ISD200_GOOD) /* ata or atapi? */ - retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE ); + retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 1); } isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0; @@ -1011,7 +1016,8 @@ static int isd200_get_inquiry_data( struct us_data *us ) } else { /* ATA Command Identify successful */ int i; - __u16 *src, *dest; + __be16 *src; + __u16 *dest; ide_fix_driveid(id); US_DEBUGP(" Identify Data Structure:\n"); @@ -1047,12 +1053,6 @@ static int isd200_get_inquiry_data( struct us_data *us ) /* Standard IDE interface only supports disks */ info->InquiryData.DeviceType = DIRECT_ACCESS_DEVICE; - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - * in Linux. - */ - info->InquiryData.Versions = 0x2; - /* The length must be at least 36 (5 + 31) */ info->InquiryData.AdditionalLength = 0x1F; @@ -1063,17 +1063,17 @@ static int isd200_get_inquiry_data( struct us_data *us ) } /* Fill in vendor identification fields */ - src = (__u16*)id->model; + src = (__be16*)id->model; dest = (__u16*)info->InquiryData.VendorId; for (i=0;i<4;i++) dest[i] = be16_to_cpu(src[i]); - src = (__u16*)(id->model+8); + src = (__be16*)(id->model+8); dest = (__u16*)info->InquiryData.ProductId; for (i=0;i<8;i++) dest[i] = be16_to_cpu(src[i]); - src = (__u16*)id->fw_rev; + src = (__be16*)id->fw_rev; dest = (__u16*)info->InquiryData.ProductRevisionLevel; for (i=0;i<2;i++) dest[i] = be16_to_cpu(src[i]); @@ -1121,15 +1121,15 @@ static int isd200_get_inquiry_data( struct us_data *us ) * Translate SCSI commands to ATA commands. * * RETURNS: - * TRUE if the command needs to be sent to the transport layer - * FALSE otherwise + * 1 if the command needs to be sent to the transport layer + * 0 otherwise */ -static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, +static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, union ata_cdb * ataCdb) { struct isd200_info *info = (struct isd200_info *)us->extra; struct hd_driveid *id = info->id; - int sendToTransport = TRUE; + int sendToTransport = 1; unsigned char sectnum, head; unsigned short cylinder; unsigned long lba; @@ -1147,7 +1147,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData, sizeof(info->InquiryData), srb); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; break; case MODE_SENSE: @@ -1167,7 +1167,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, } else { US_DEBUGP(" Media Status not supported, just report okay\n"); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; } break; @@ -1185,7 +1185,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, } else { US_DEBUGP(" Media Status not supported, just report okay\n"); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; } break; @@ -1209,15 +1209,14 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, usb_stor_set_xfer_buf((unsigned char *) &readCapacityData, sizeof(readCapacityData), srb); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; } break; case READ_10: US_DEBUGP(" ATA OUT - SCSIOP_READ\n"); - lba = *(unsigned long *)&srb->cmnd[2]; - lba = cpu_to_be32(lba); + lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]); blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; if (id->capability & CAPABILITY_LBA) { @@ -1249,8 +1248,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, case WRITE_10: US_DEBUGP(" ATA OUT - SCSIOP_WRITE\n"); - lba = *(unsigned long *)&srb->cmnd[2]; - lba = cpu_to_be32(lba); + lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]); blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; if (id->capability & CAPABILITY_LBA) { @@ -1293,7 +1291,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, } else { US_DEBUGP(" Not removeable media, just report okay\n"); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; } break; @@ -1319,14 +1317,14 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, } else { US_DEBUGP(" Nothing to do, just report okay\n"); srb->result = SAM_STAT_GOOD; - sendToTransport = FALSE; + sendToTransport = 0; } break; default: US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]); srb->result = DID_ERROR << 16; - sendToTransport = FALSE; + sendToTransport = 0; break; } @@ -1424,9 +1422,9 @@ int isd200_Initialization(struct us_data *us) * */ -void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us) +void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { - int sendToTransport = TRUE; + int sendToTransport = 1; union ata_cdb ataCdb; /* Make sure driver was initialized */ diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h index 70ebe1c39..0a35f4fa7 100644 --- a/drivers/usb/storage/isd200.h +++ b/drivers/usb/storage/isd200.h @@ -25,7 +25,7 @@ #ifndef _USB_ISD200_H #define _USB_ISD200_H -extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us); +extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us); extern int isd200_Initialization(struct us_data *us); #endif diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index ac9c908c4..24464ece5 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -47,15 +47,19 @@ * in that routine. */ +#include +#include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "jumpshot.h" -#include -#include -#include static inline int jumpshot_bulk_read(struct us_data *us, unsigned char *data, @@ -319,7 +323,7 @@ static int jumpshot_id_device(struct us_data *us, } static int jumpshot_handle_mode_sense(struct us_data *us, - Scsi_Cmnd * srb, + struct scsi_cmnd * srb, int sense_6) { static unsigned char rw_err_page[12] = { @@ -409,7 +413,7 @@ static int jumpshot_handle_mode_sense(struct us_data *us, if (sense_6) ptr[0] = i - 1; else - ((u16 *) ptr)[0] = cpu_to_be16(i - 2); + ((__be16 *) ptr)[0] = cpu_to_be16(i - 2); usb_stor_set_xfer_buf(ptr, i, srb); return USB_STOR_TRANSPORT_GOOD; @@ -426,7 +430,7 @@ static void jumpshot_info_destructor(void *extra) // Transport for the Lexar 'Jumpshot' // -int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) +int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) { struct jumpshot_info *info; int rc; @@ -471,8 +475,8 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) // build the reply // - ((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); - ((u32 *) ptr)[1] = cpu_to_be32(info->ssize); + ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1); + ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize); usb_stor_set_xfer_buf(ptr, 8, srb); return USB_STOR_TRANSPORT_GOOD; @@ -551,12 +555,12 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) if (srb->cmnd[0] == MODE_SENSE) { US_DEBUGP("jumpshot_transport: MODE_SENSE_6 detected\n"); - return jumpshot_handle_mode_sense(us, srb, TRUE); + return jumpshot_handle_mode_sense(us, srb, 1); } if (srb->cmnd[0] == MODE_SENSE_10) { US_DEBUGP("jumpshot_transport: MODE_SENSE_10 detected\n"); - return jumpshot_handle_mode_sense(us, srb, FALSE); + return jumpshot_handle_mode_sense(us, srb, 0); } if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h index 8147197cd..19bac9d15 100644 --- a/drivers/usb/storage/jumpshot.h +++ b/drivers/usb/storage/jumpshot.h @@ -24,7 +24,7 @@ #ifndef _USB_JUMPSHOT_H #define _USB_JUMPSHOT_H -extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us); struct jumpshot_info { unsigned long sectors; // total sector count diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 1c56f4944..9d3d77452 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -45,6 +45,8 @@ */ #include +#include +#include #include "protocol.h" #include "usb.h" #include "debug.h" @@ -55,46 +57,14 @@ * Helper routines ***********************************************************************/ -/* - * Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ -static void fix_inquiry_data(Scsi_Cmnd *srb) -{ - unsigned char databuf[3]; - unsigned int index, offset; - - /* verify that it's an INQUIRY command */ - if (srb->cmnd[0] != INQUIRY) - return; - - index = offset = 0; - if (usb_stor_access_xfer_buf(databuf, sizeof(databuf), srb, - &index, &offset, FROM_XFER_BUF) != sizeof(databuf)) - return; - - if ((databuf[2] & 7) == 2) - return; - - US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n", - databuf[2] & 7); - - /* Change the SCSI revision number */ - databuf[2] = (databuf[2] & ~7) | 2; - - index = offset = 0; - usb_stor_access_xfer_buf(databuf, sizeof(databuf), srb, - &index, &offset, TO_XFER_BUF); -} - /* * Fix-up the return data from a READ CAPACITY command. My Feiya reader * returns a value that is 1 too large. */ -static void fix_read_capacity(Scsi_Cmnd *srb) +static void fix_read_capacity(struct scsi_cmnd *srb) { unsigned int index, offset; - u32 c; + __be32 c; unsigned long capacity; /* verify that it's a READ CAPACITY command */ @@ -120,11 +90,11 @@ static void fix_read_capacity(Scsi_Cmnd *srb) * Protocol routines ***********************************************************************/ -void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) +void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us) { /* Pad the ATAPI command with zeros * - * NOTE: This only works because a Scsi_Cmnd struct field contains + * NOTE: This only works because a scsi_cmnd struct field contains * a unsigned char cmnd[16], so we know we have storage available */ for (; srb->cmd_len<12; srb->cmd_len++) @@ -135,17 +105,13 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - if (srb->result == SAM_STAT_GOOD) { - /* fix the INQUIRY data if necessary */ - fix_inquiry_data(srb); - } } -void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) +void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us) { /* Pad the ATAPI command with zeros * - * NOTE: This only works because a Scsi_Cmnd struct field contains + * NOTE: This only works because a scsi_cmnd struct field contains * a unsigned char cmnd[16], so we know we have storage available */ @@ -158,20 +124,15 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - - if (srb->result == SAM_STAT_GOOD) { - /* fix the INQUIRY data if necessary */ - fix_inquiry_data(srb); - } } -void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) +void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) { /* fix some commands -- this is a form of mode translation * UFI devices only accept 12 byte long commands * - * NOTE: This only works because a Scsi_Cmnd struct field contains + * NOTE: This only works because a scsi_cmnd struct field contains * a unsigned char cmnd[16], so we know we have storage available */ @@ -206,22 +167,15 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - - if (srb->result == SAM_STAT_GOOD) { - /* Fix the data for an INQUIRY, if necessary */ - fix_inquiry_data(srb); - } } -void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) +void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, + struct us_data *us) { /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); if (srb->result == SAM_STAT_GOOD) { - /* Fix the INQUIRY data if necessary */ - fix_inquiry_data(srb); - /* Fix the READ CAPACITY result if necessary */ if (us->flags & US_FL_FIX_CAPACITY) fix_read_capacity(srb); @@ -241,7 +195,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) * pick up from where this one left off. */ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, unsigned int *offset, enum xfer_buf_dir dir) { unsigned int cnt; @@ -327,7 +281,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, /* Store the contents of buffer into srb's transfer buffer and set the * SCSI residue. */ void usb_stor_set_xfer_buf(unsigned char *buffer, - unsigned int buflen, Scsi_Cmnd *srb) + unsigned int buflen, struct scsi_cmnd *srb) { unsigned int index = 0, offset = 0; diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h index c1fcb528a..7aa460d3b 100644 --- a/drivers/usb/storage/protocol.h +++ b/drivers/usb/storage/protocol.h @@ -41,9 +41,8 @@ #ifndef _PROTOCOL_H_ #define _PROTOCOL_H_ -#include -#include "scsi.h" -#include "usb.h" +struct scsi_cmnd; +struct us_data; /* Sub Classes */ @@ -60,18 +59,19 @@ #define US_SC_DEVICE 0xff /* Use device's value */ /* Protocol handling routines */ -extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*); -extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*); -extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*); -extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*); +extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); +extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); +extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*); +extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*, + struct us_data*); -/* Scsi_Cmnd transfer buffer access utilities */ +/* struct scsi_cmnd transfer buffer access utilities */ enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index, + unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, unsigned int *offset, enum xfer_buf_dir dir); extern void usb_stor_set_xfer_buf(unsigned char *buffer, - unsigned int buflen, Scsi_Cmnd *srb); + unsigned int buflen, struct scsi_cmnd *srb); #endif diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index d003abe67..64e185fcf 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -44,17 +44,23 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "scsiglue.h" -#include "usb.h" -#include "debug.h" -#include "transport.h" -#include "protocol.h" #include #include + +#include +#include #include +#include +#include #include +#include "scsiglue.h" +#include "usb.h" +#include "debug.h" +#include "transport.h" +#include "protocol.h" + /*********************************************************************** * Host functions ***********************************************************************/ @@ -67,14 +73,11 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { /* - * Set default bflags. These can be overridden for individual - * models and vendors via the scsi devinfo mechanism. The only - * flag we need is to force 36-byte INQUIRYs; we don't use any - * of the extra data and many devices choke if asked for more or + * Set the INQUIRY transfer length to 36. We don't use any of + * the extra data and many devices choke if asked for more or * less than 36 bytes. */ - sdev->sdev_bflags = BLIST_INQUIRY_36; - + sdev->inquiry_len = 36; return 0; } @@ -92,17 +95,32 @@ static int slave_configure(struct scsi_device *sdev) * the end, scatter-gather buffers follow page boundaries. */ blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); - /* Devices using Genesys Logic chips cause a lot of trouble for - * high-speed transfers; they die unpredictably when given more - * than 64 KB of data at a time. If we detect such a device, - * reduce the maximum transfer size to 64 KB = 128 sectors. */ - -#define USB_VENDOR_ID_GENESYS 0x05e3 // Needs a standard location - + /* Set the SCSI level to at least 2. We'll leave it at 3 if that's + * what is originally reported. We need this to avoid confusing + * the SCSI layer with devices that report 0 or 1, but need 10-byte + * commands (ala ATAPI devices behind certain bridges, or devices + * which simply have broken INQUIRY data). + * + * NOTE: This means /dev/sg programs (ala cdrecord) will get the + * actual information. This seems to be the preference for + * programs like that. + * + * NOTE: This also means that /proc/scsi/scsi and sysfs may report + * the actual value or the modified one, depending on where the + * data comes from. + */ + if (sdev->scsi_level < SCSI_2) + sdev->scsi_level = SCSI_2; + + /* According to the technical support people at Genesys Logic, + * devices using their chips have problems transferring more than + * 32 KB at a time. In practice people have found that 64 KB + * works okay and that's what Windows does. But we'll be + * conservative; people can always use the sysfs interface to + * increase max_sectors. */ if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS && - us->pusb_dev->speed == USB_SPEED_HIGH && - sdev->request_queue->max_sectors > 128) - blk_queue_max_sectors(sdev->request_queue, 128); + sdev->request_queue->max_sectors > 64) + blk_queue_max_sectors(sdev->request_queue, 64); /* We can't put these settings in slave_alloc() because that gets * called before the device type is known. Consequently these @@ -146,25 +164,32 @@ static int slave_configure(struct scsi_device *sdev) /* queue a command */ /* This is always called with scsi_lock(srb->host) held */ -static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) +static int queuecommand(struct scsi_cmnd *srb, + void (*done)(struct scsi_cmnd *)) { struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; US_DEBUGP("%s called\n", __FUNCTION__); srb->host_scribble = (unsigned char *)us; - /* enqueue the command */ - if (us->sm_state != US_STATE_IDLE || us->srb != NULL) { - printk(KERN_ERR USB_STORAGE "Error in %s: " - "state = %d, us->srb = %p\n", - __FUNCTION__, us->sm_state, us->srb); + /* check for state-transition errors */ + if (us->srb != NULL) { + printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", + __FUNCTION__, us->srb); return SCSI_MLQUEUE_HOST_BUSY; } + /* fail the command if we are disconnecting */ + if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + US_DEBUGP("Fail command during disconnect\n"); + srb->result = DID_NO_CONNECT << 16; + done(srb); + return 0; + } + + /* enqueue the command and wake up the control thread */ srb->scsi_done = done; us->srb = srb; - - /* wake up the process task */ up(&(us->sema)); return 0; @@ -174,9 +199,9 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) * Error handling functions ***********************************************************************/ -/* Command abort */ +/* Command timeout and abort */ /* This is always called with scsi_lock(srb->host) held */ -static int command_abort( Scsi_Cmnd *srb ) +static int command_abort(struct scsi_cmnd *srb ) { struct Scsi_Host *host = srb->device->host; struct us_data *us = (struct us_data *) host->hostdata[0]; @@ -189,22 +214,12 @@ static int command_abort( Scsi_Cmnd *srb ) return FAILED; } - /* Normally the current state is RUNNING. If the control thread - * hasn't even started processing this command, the state will be - * IDLE. Anything else is a bug. */ - if (us->sm_state != US_STATE_RUNNING - && us->sm_state != US_STATE_IDLE) { - printk(KERN_ERR USB_STORAGE "Error in %s: " - "invalid state %d\n", __FUNCTION__, us->sm_state); - return FAILED; - } - - /* Set state to ABORTING and set the ABORTING bit, but only if + /* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if * a device reset isn't already in progress (to avoid interfering * with the reset). To prevent races with auto-reset, we must * stop any ongoing USB transfers while still holding the host * lock. */ - us->sm_state = US_STATE_ABORTING; + set_bit(US_FLIDX_TIMED_OUT, &us->flags); if (!test_bit(US_FLIDX_RESETTING, &us->flags)) { set_bit(US_FLIDX_ABORTING, &us->flags); usb_stor_stop_transport(us); @@ -217,26 +232,20 @@ static int command_abort( Scsi_Cmnd *srb ) /* Reacquire the lock and allow USB transfers to resume */ scsi_lock(host); clear_bit(US_FLIDX_ABORTING, &us->flags); + clear_bit(US_FLIDX_TIMED_OUT, &us->flags); return SUCCESS; } /* This invokes the transport reset mechanism to reset the state of the * device */ /* This is always called with scsi_lock(srb->host) held */ -static int device_reset( Scsi_Cmnd *srb ) +static int device_reset(struct scsi_cmnd *srb) { struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; int result; US_DEBUGP("%s called\n", __FUNCTION__); - if (us->sm_state != US_STATE_IDLE) { - printk(KERN_ERR USB_STORAGE "Error in %s: " - "invalid state %d\n", __FUNCTION__, us->sm_state); - return FAILED; - } - /* set the state and release the lock */ - us->sm_state = US_STATE_RESETTING; scsi_unlock(srb->device->host); /* lock the device pointers and do the reset */ @@ -248,9 +257,8 @@ static int device_reset( Scsi_Cmnd *srb ) result = us->transport_reset(us); up(&(us->dev_semaphore)); - /* lock access to the state and clear it */ + /* lock the host for the return */ scsi_lock(srb->device->host); - us->sm_state = US_STATE_IDLE; return result; } @@ -258,20 +266,13 @@ static int device_reset( Scsi_Cmnd *srb ) /* It refuses to work if there's more than one interface in * the device, so that other users are not affected. */ /* This is always called with scsi_lock(srb->host) held */ -static int bus_reset( Scsi_Cmnd *srb ) +static int bus_reset(struct scsi_cmnd *srb) { struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; - int result; + int result, rc; US_DEBUGP("%s called\n", __FUNCTION__); - if (us->sm_state != US_STATE_IDLE) { - printk(KERN_ERR USB_STORAGE "Error in %s: " - "invalid state %d\n", __FUNCTION__, us->sm_state); - return FAILED; - } - /* set the state and release the lock */ - us->sm_state = US_STATE_RESETTING; scsi_unlock(srb->device->host); /* The USB subsystem doesn't handle synchronisation between @@ -286,14 +287,21 @@ static int bus_reset( Scsi_Cmnd *srb ) result = -EBUSY; US_DEBUGP("Refusing to reset a multi-interface device\n"); } else { - result = usb_reset_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); + rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); + if (rc < 0) { + US_DEBUGP("unable to lock device for reset: %d\n", rc); + result = rc; + } else { + result = usb_reset_device(us->pusb_dev); + if (rc) + usb_unlock_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); + } } up(&(us->dev_semaphore)); - /* lock access to the state and clear it */ + /* lock the host for the return */ scsi_lock(srb->device->host); - us->sm_state = US_STATE_IDLE; return result < 0 ? FAILED : SUCCESS; } @@ -444,10 +452,10 @@ struct scsi_host_template usb_stor_host_template = { * periodically someone should test to see which setting is more * optimal. */ - .use_clustering = TRUE, + .use_clustering = 1, /* emulated HBA */ - .emulated = TRUE, + .emulated = 1, /* we do our own delay after a device or bus reset */ .skip_settle_delay = 1, diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index e5dc7613b..70df2a7bc 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h @@ -41,17 +41,15 @@ #ifndef _SCSIGLUE_H_ #define _SCSIGLUE_H_ -#include -#include "scsi.h" #include -#include "usb.h" + +struct us_data; +struct scsi_cmnd; extern void usb_stor_report_device_reset(struct us_data *us); extern unsigned char usb_stor_sense_notready[18]; extern unsigned char usb_stor_sense_invalidCDB[18]; extern struct scsi_host_template usb_stor_host_template; -extern int usb_stor_scsiSense10to6(Scsi_Cmnd*); -extern int usb_stor_scsiSense6to10(Scsi_Cmnd*); #endif diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index f96bb7535..ff81b40c2 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -41,16 +41,19 @@ * EF: compute checksum (?) */ +#include +#include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "sddr09.h" -#include -#include -#include -#include #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -1401,7 +1404,7 @@ sddr09_init(struct us_data *us) { /* * Transport for the Sandisk SDDR-09 */ -int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) +int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) { static unsigned char sensekey = 0, sensecode = 0; static unsigned char havefakesense = 0; @@ -1486,11 +1489,11 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) capacity = (info->lbact << info->blockshift) - 1; - ((u32 *) ptr)[0] = cpu_to_be32(capacity); + ((__be32 *) ptr)[0] = cpu_to_be32(capacity); // Report page size - ((u32 *) ptr)[1] = cpu_to_be32(info->pagesize); + ((__be32 *) ptr)[1] = cpu_to_be32(info->pagesize); usb_stor_set_xfer_buf(ptr, 8, srb); return USB_STOR_TRANSPORT_GOOD; @@ -1507,7 +1510,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) "mode page 0x%x\n", modepage); memcpy(ptr, mode_page_01, sizeof(mode_page_01)); - ((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2); + ((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2); ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0; usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb); return USB_STOR_TRANSPORT_GOOD; @@ -1581,13 +1584,13 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) if (srb->request_bufflen == 0) return USB_STOR_TRANSPORT_GOOD; - if (srb->sc_data_direction == SCSI_DATA_WRITE || - srb->sc_data_direction == SCSI_DATA_READ) { - unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE) + if (srb->sc_data_direction == DMA_TO_DEVICE || + srb->sc_data_direction == DMA_FROM_DEVICE) { + unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE) ? us->send_bulk_pipe : us->recv_bulk_pipe; US_DEBUGP("SDDR09: %s %d bytes\n", - (srb->sc_data_direction == SCSI_DATA_WRITE) ? + (srb->sc_data_direction == DMA_TO_DEVICE) ? "sending" : "receiving", srb->request_bufflen); diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h index 685123939..c9d78d618 100644 --- a/drivers/usb/storage/sddr09.h +++ b/drivers/usb/storage/sddr09.h @@ -29,7 +29,7 @@ /* Sandisk SDDR-09 stuff */ -extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); struct sddr09_card_info { unsigned long capacity; /* Size of card in bytes */ diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index eb9615318..10270f42a 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -24,15 +24,19 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "sddr55.h" -#include -#include -#include #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -74,7 +78,7 @@ static int sddr55_bulk_transport(struct us_data *us, int direction, unsigned char *data, unsigned int len) { struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; - unsigned int pipe = (direction == SCSI_DATA_READ) ? + unsigned int pipe = (direction == DMA_FROM_DEVICE) ? us->recv_bulk_pipe : us->send_bulk_pipe; if (!len) @@ -99,7 +103,7 @@ static int sddr55_status(struct us_data *us) command[5] = 0xB0; command[7] = 0x80; result = sddr55_bulk_transport(us, - SCSI_DATA_WRITE, command, 8); + DMA_TO_DEVICE, command, 8); US_DEBUGP("Result for send_command in status %d\n", result); @@ -110,7 +114,7 @@ static int sddr55_status(struct us_data *us) } result = sddr55_bulk_transport(us, - SCSI_DATA_READ, status, 4); + DMA_FROM_DEVICE, status, 4); /* expect to get short transfer if no card fitted */ if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) { @@ -139,7 +143,7 @@ static int sddr55_status(struct us_data *us) /* now read status */ result = sddr55_bulk_transport(us, - SCSI_DATA_READ, status, 2); + DMA_FROM_DEVICE, status, 2); if (result != USB_STOR_XFER_GOOD) { set_sense_info (4, 0, 0); /* hardware error */ @@ -215,7 +219,7 @@ static int sddr55_read_data(struct us_data *us, /* send command */ result = sddr55_bulk_transport(us, - SCSI_DATA_WRITE, command, 8); + DMA_TO_DEVICE, command, 8); US_DEBUGP("Result for send_command in read_data %d\n", result); @@ -227,7 +231,7 @@ static int sddr55_read_data(struct us_data *us, /* read data */ result = sddr55_bulk_transport(us, - SCSI_DATA_READ, buffer, len); + DMA_FROM_DEVICE, buffer, len); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; @@ -236,7 +240,7 @@ static int sddr55_read_data(struct us_data *us, /* now read status */ result = sddr55_bulk_transport(us, - SCSI_DATA_READ, status, 2); + DMA_FROM_DEVICE, status, 2); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; @@ -390,7 +394,7 @@ static int sddr55_write_data(struct us_data *us, /* send command */ result = sddr55_bulk_transport(us, - SCSI_DATA_WRITE, command, 8); + DMA_TO_DEVICE, command, 8); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for send_command in write_data %d\n", @@ -404,7 +408,7 @@ static int sddr55_write_data(struct us_data *us, /* send the data */ result = sddr55_bulk_transport(us, - SCSI_DATA_WRITE, buffer, len); + DMA_TO_DEVICE, buffer, len); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for send_data in write_data %d\n", @@ -417,7 +421,7 @@ static int sddr55_write_data(struct us_data *us, } /* now read status */ - result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6); + result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for get_status in write_data %d\n", @@ -483,7 +487,7 @@ static int sddr55_read_deviceID(struct us_data *us, memset(command, 0, 8); command[5] = 0xB0; command[7] = 0x84; - result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); + result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); US_DEBUGP("Result of send_control for device ID is %d\n", result); @@ -492,7 +496,7 @@ static int sddr55_read_deviceID(struct us_data *us, return USB_STOR_TRANSPORT_ERROR; result = sddr55_bulk_transport(us, - SCSI_DATA_READ, content, 4); + DMA_FROM_DEVICE, content, 4); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -502,7 +506,7 @@ static int sddr55_read_deviceID(struct us_data *us, if (content[0] != 0xff) { result = sddr55_bulk_transport(us, - SCSI_DATA_READ, content, 2); + DMA_FROM_DEVICE, content, 2); } return USB_STOR_TRANSPORT_GOOD; @@ -624,21 +628,21 @@ static int sddr55_read_map(struct us_data *us) { command[6] = numblocks * 2 / 256; command[7] = 0x8A; - result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); + result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); return -1; } - result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2); + result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); return -1; } - result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2); + result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2); if ( result != USB_STOR_XFER_GOOD) { kfree (buffer); @@ -734,7 +738,7 @@ static void sddr55_card_info_destructor(void *extra) { /* * Transport for the Sandisk SDDR-55 */ -int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us) +int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; static unsigned char inquiry_response[8] = { @@ -834,8 +838,8 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us) capacity /= PAGESIZE; capacity--; - ((u32 *) ptr)[0] = cpu_to_be32(capacity); - ((u32 *) ptr)[1] = cpu_to_be32(PAGESIZE); + ((__be32 *) ptr)[0] = cpu_to_be32(capacity); + ((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE); usb_stor_set_xfer_buf(ptr, 8, srb); sddr55_read_map(us); diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h index 6dc0da6d2..d6bd32f6c 100644 --- a/drivers/usb/storage/sddr55.h +++ b/drivers/usb/storage/sddr55.h @@ -28,7 +28,7 @@ /* Sandisk SDDR-55 stuff */ -extern int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us); extern int sddr55_reset(struct us_data *us); #endif diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index b0af06e4f..c98fa3938 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -39,16 +39,20 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include +#include + #include "transport.h" #include "protocol.h" #include "usb.h" #include "debug.h" #include "shuttle_usbat.h" -#include -#include -#include - #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) ) #define LSB_of(s) ((s)&0xFF) #define MSB_of(s) ((s)>>8) @@ -275,7 +279,7 @@ static int usbat_rw_block_test(struct us_data *us, int minutes) { int result; - unsigned int pipe = (direction == SCSI_DATA_READ) ? + unsigned int pipe = (direction == DMA_FROM_DEVICE) ? us->recv_bulk_pipe : us->send_bulk_pipe; // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here, @@ -315,9 +319,9 @@ static int usbat_rw_block_test(struct us_data *us, } else cmdlen = 8; - command[cmdlen-8] = (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0); + command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0); command[cmdlen-7] = access | - (direction==SCSI_DATA_WRITE ? 0x05 : 0x04); + (direction==DMA_TO_DEVICE ? 0x05 : 0x04); command[cmdlen-6] = data_reg; command[cmdlen-5] = status_reg; command[cmdlen-4] = timeout; @@ -355,7 +359,7 @@ static int usbat_rw_block_test(struct us_data *us, //US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n", - // direction == SCSI_DATA_WRITE ? "out" : "in", + // direction == DMA_TO_DEVICE ? "out" : "in", // len, use_sg); result = usb_stor_bulk_transfer_sg(us, @@ -388,7 +392,7 @@ static int usbat_rw_block_test(struct us_data *us, * the bulk output pipe only the first time. */ - if (direction==SCSI_DATA_READ && i==0) { + if (direction==DMA_FROM_DEVICE && i==0) { if (usb_stor_clear_halt(us, us->send_bulk_pipe) < 0) return USB_STOR_TRANSPORT_ERROR; @@ -399,7 +403,7 @@ static int usbat_rw_block_test(struct us_data *us, */ result = usbat_read(us, USBAT_ATA, - direction==SCSI_DATA_WRITE ? 0x17 : 0x0E, + direction==DMA_TO_DEVICE ? 0x17 : 0x0E, status); if (result!=USB_STOR_XFER_GOOD) @@ -410,7 +414,7 @@ static int usbat_rw_block_test(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; US_DEBUGP("Redoing %s\n", - direction==SCSI_DATA_WRITE ? "write" : "read"); + direction==DMA_TO_DEVICE ? "write" : "read"); } else if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -420,7 +424,7 @@ static int usbat_rw_block_test(struct us_data *us, } US_DEBUGP("Bummer! %s bulk data 20 times failed.\n", - direction==SCSI_DATA_WRITE ? "Writing" : "Reading"); + direction==DMA_TO_DEVICE ? "Writing" : "Reading"); return USB_STOR_TRANSPORT_FAILED; } @@ -520,7 +524,7 @@ static int usbat_write_user_io(struct us_data *us, static int usbat_handle_read10(struct us_data *us, unsigned char *registers, unsigned char *data, - Scsi_Cmnd *srb) + struct scsi_cmnd *srb) { int result = USB_STOR_TRANSPORT_GOOD; unsigned char *buffer; @@ -537,7 +541,7 @@ static int usbat_handle_read10(struct us_data *us, result = usbat_rw_block_test(us, USBAT_ATA, registers, data, 19, 0x10, 0x17, 0xFD, 0x30, - SCSI_DATA_READ, + DMA_FROM_DEVICE, srb->request_buffer, srb->request_bufflen, srb->use_sg, 1); @@ -606,7 +610,7 @@ static int usbat_handle_read10(struct us_data *us, result = usbat_rw_block_test(us, USBAT_ATA, registers, data, 19, 0x10, 0x17, 0xFD, 0x30, - SCSI_DATA_READ, + DMA_FROM_DEVICE, buffer, len, 0, 1); @@ -803,7 +807,7 @@ int init_8200e(struct us_data *us) /* * Transport for the HP 8200e */ -int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) +int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; unsigned char *status = us->iobuf; @@ -847,12 +851,12 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) if (srb->cmnd[0] == TEST_UNIT_READY) transferred = 0; - if (srb->sc_data_direction == SCSI_DATA_WRITE) { + if (srb->sc_data_direction == DMA_TO_DEVICE) { result = usbat_rw_block_test(us, USBAT_ATA, registers, data, 19, 0x10, 0x17, 0xFD, 0x30, - SCSI_DATA_WRITE, + DMA_TO_DEVICE, srb->request_buffer, len, srb->use_sg, 10); @@ -900,7 +904,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) // If there is response data to be read in // then do it here. - if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) { + if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) { // How many bytes to read in? Check cylL register diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index e9c4aead5..9855c1d32 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -53,7 +53,7 @@ #define USBAT_UIO_ADPRST 0x01 // Reset SCM chip /* HP 8200e stuff */ -extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us); +extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); extern int init_8200e(struct us_data *us); #endif diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 232155854..08d3a96bb 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -46,15 +46,20 @@ */ #include +#include +#include +#include + +#include +#include +#include + #include "transport.h" #include "protocol.h" #include "scsiglue.h" #include "usb.h" #include "debug.h" -#include -#include -#include /*********************************************************************** * Data transfer routines @@ -260,9 +265,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) USB_ENDPOINT_HALT, endp, NULL, 0, 3*HZ); - /* reset the toggles and endpoint flags */ - usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe)); + /* reset the endpoint toggle */ usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); @@ -522,7 +525,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, * This is used by the protocol layers to actually send the message to * the device and receive the response. */ -void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) +void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) { int need_auto_sense; int result; @@ -534,7 +537,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) /* if the command gets aborted by the higher layers, we need to * short-circuit all other processing */ - if (us->sm_state == US_STATE_ABORTING) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- command was aborted\n"); goto Handle_Abort; } @@ -569,7 +572,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && - srb->sc_data_direction != SCSI_DATA_READ) { + srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; } @@ -629,7 +632,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; - srb->sc_data_direction = SCSI_DATA_READ; + srb->sc_data_direction = DMA_FROM_DEVICE; /* use the new buffer we have */ old_request_buffer = srb->request_buffer; @@ -662,7 +665,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) srb->cmd_len = old_cmd_len; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); - if (us->sm_state == US_STATE_ABORTING) { + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); goto Handle_Abort; } @@ -749,7 +752,7 @@ void usb_stor_stop_transport(struct us_data *us) * Control/Bulk/Interrupt transport */ -int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) +int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) { unsigned int transfer_length = srb->request_bufflen; unsigned int pipe = 0; @@ -778,7 +781,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) { - pipe = srb->sc_data_direction == SCSI_DATA_READ ? + pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -849,7 +852,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* * Control/Bulk transport */ -int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) +int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) { unsigned int transfer_length = srb->request_bufflen; int result; @@ -877,7 +880,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (transfer_length) { - unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? + unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -918,7 +921,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) result, us->iobuf[0]); /* if we have a successful request, return the result */ - if (result == 1) + if (result > 0) return us->iobuf[0]; /* @@ -930,16 +933,19 @@ int usb_stor_Bulk_max_lun(struct us_data *us) if (result == -EPIPE) { usb_stor_clear_halt(us, us->recv_bulk_pipe); usb_stor_clear_halt(us, us->send_bulk_pipe); - /* return the default -- no LUNs */ - return 0; } - /* An answer or a STALL are the only valid responses. If we get - * something else, return an indication of error */ - return -1; + /* + * Some devices don't like GetMaxLUN. They may STALL the control + * pipe, they may return a zero-length result, they may do nothing at + * all and timeout, or they may fail in even more bizarrely creative + * ways. In these cases the best approach is to use the default + * value: only one LUN. + */ + return 0; } -int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) +int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; @@ -952,7 +958,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(transfer_length); - bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; + bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0; bcb->Tag = srb->serial_number; bcb->Lun = srb->device->lun; if (us->flags & US_FL_SCM_MULT_TARG) @@ -977,8 +983,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) /* DATA STAGE */ /* send/receive data payload, if there is any */ + + /* Genesys Logic interface chips need a 100us delay between the + * command phase and the data phase */ + if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS) + udelay(100); + if (transfer_length) { - unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? + unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; result = usb_stor_bulk_transfer_sg(us, pipe, srb->request_buffer, transfer_length, @@ -1045,8 +1057,13 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) /* try to compute the actual residue, based on how much data * was really transferred and what the device tells us */ - residue = min(residue, transfer_length); - srb->resid = max(srb->resid, (int) residue); + if (residue) { + if (!(us->flags & US_FL_IGNORE_RESIDUE) || + srb->sc_data_direction == DMA_TO_DEVICE) { + residue = min(residue, transfer_length); + srb->resid = max(srb->resid, (int) residue); + } + } /* based on the status code, we report good or bad */ switch (bcs->Status) { diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 123b041ab..153efd623 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -44,7 +44,8 @@ #include #include #include "usb.h" -#include "scsi.h" + +struct scsi_cmnd; /* Protocols */ @@ -82,9 +83,9 @@ /* command block wrapper */ struct bulk_cb_wrap { - __u32 Signature; /* contains 'USBC' */ + __le32 Signature; /* contains 'USBC' */ __u32 Tag; /* unique per command id */ - __u32 DataTransferLength; /* size of data */ + __le32 DataTransferLength; /* size of data */ __u8 Flags; /* direction in bit 0 */ __u8 Lun; /* LUN normally 0 */ __u8 Length; /* of of the CDB */ @@ -98,9 +99,9 @@ struct bulk_cb_wrap { /* command status wrapper */ struct bulk_cs_wrap { - __u32 Signature; /* should = 'USBS' */ + __le32 Signature; /* should = 'USBS' */ __u32 Tag; /* same as original command */ - __u32 Residue; /* amount not transferred */ + __le32 Residue; /* amount not transferred */ __u8 Status; /* see below */ __u8 Filler[18]; }; @@ -150,16 +151,16 @@ struct bulk_cs_wrap { #define US_CBI_ADSC 0 -extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*); +extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*); -extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*); +extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*); extern int usb_stor_CB_reset(struct us_data*); -extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*); +extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*); extern int usb_stor_Bulk_max_lun(struct us_data*); extern int usb_stor_Bulk_reset(struct us_data*); -extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*); +extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*); extern void usb_stor_stop_transport(struct us_data*); extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 195e98f95..7b03131fe 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -36,20 +36,18 @@ /* If you edit this file, please try to keep it sorted first by VendorID, * then by ProductID. * - * If you want to add an entry for this file, please send the following - * to greg@kroah.com: - * - patch that adds the entry for your device which includes your - * email address right above the entry. + * If you want to add an entry for this file, be sure to include the + * following information: + * - a patch that adds the entry for your device, including your + * email address right above the entry (plus maybe a brief + * explanation of the reason for the entry), * - a copy of /proc/bus/usb/devices with your device plugged in * running with this patch. - * + * Send your submission to either Phil Dibowitz or + * Alan Stern , and don't forget to CC: the + * USB development list . */ -UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245, - "Mitsumi", - "CD-R/RW Drive", - US_SC_8020, US_PR_CBI, NULL, 0), - UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0100, "Mitsumi", "USB FDD", @@ -73,16 +71,6 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), #endif -/* : I don't know the name of the bridge - * manufacturer, but I've got an external USB drive by the Revoltec company - * that needs this. otherwise the drive is recognized as /dev/sda, but any - * access to it blocks indefinitely. - */ -UNUSUAL_DEV( 0x0402, 0x5621, 0x0103, 0x0103, - "Revoltec", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), - /* Deduced by Jonathan Woithe * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message * always fails and confuses drive. @@ -100,12 +88,6 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif -/* Patch submitted by Alessandro Fracchetti */ -UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, - "Kyocera", - "Finecam L3", - US_SC_SCSI, US_PR_BULK, NULL, US_FL_FIX_INQUIRY), - /* Patch submitted by Philipp Friedrich */ UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, "Kyocera", @@ -126,6 +108,7 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, /* Patch for Kyocera Finecam L3 * Submitted by Michael Krauth + * and Alessandro Fracchetti */ UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, "Kyocera", @@ -154,10 +137,13 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, "785EPX Storage", US_SC_SCSI, US_PR_BULK, NULL, US_FL_SINGLE_LUN), +/* Not sure who reported this originally but + * Pavel Machek reported that the extra US_FL_SINGLE_LUN + * flag be added */ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", - US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), + US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN), /* Reported by Peter Wächtler * The device needs the flags only. @@ -185,6 +171,16 @@ UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000, "CD-R/RW Drive", US_SC_8070, US_PR_CB, NULL, 0), +/* Reported by Adriaan Penning + * Note that these cameras report "Medium not present" after + * ALLOW_MEDIUM_REMOVAL, so they also need to be marked + * NOT_LOCKABLE in the SCSI blacklist (and the vendor is MATSHITA). */ +UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x9999, + "Panasonic", + "DMC-LCx Camera", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Most of the following entries were developed with the help of * Shuttle/SCM directly. */ @@ -270,6 +266,45 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, US_SC_8070, US_PR_BULK, NULL, US_FL_FIX_INQUIRY ), +/* Yakumo Mega Image 37 + * Submitted by Stephan Fuhrmann */ +UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "300_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + +/* Another Yakumo camera. + * Reported by Michele Alzetta */ +UNUSUAL_DEV( 0x052b, 0x1804, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "300_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + +/* Reported by Iacopo Spalletti */ +UNUSUAL_DEV( 0x052b, 0x1807, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "300_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + +/* Yakumo Mega Image 47 + * Reported by Bjoern Paetzel */ +UNUSUAL_DEV( 0x052b, 0x1905, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "400_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + +/* Reported by Paul Ortyl + * Note that it's similar to the device above, only different prodID */ +UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "400_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", @@ -373,22 +408,42 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN), +/* Reported by Johann Cardon + * This entry is needed only because the device reports + * bInterfaceClass = 0xff (vendor-specific) + */ +UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, + "Y-E Data", + "Silicon Media R/W", + US_SC_DEVICE, US_PR_DEVICE, NULL, 0), + /* Fabrizio Fellini */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", "Digital Camera EX-20 DSC", US_SC_8070, US_PR_DEVICE, NULL, 0 ), +/* The entry was here before I took over, and had US_SC_RBC. It turns + * out that isn't needed. Additionally, Torsten Eriksson + * is able to use his device fine + * without this entry at all - but I don't suspect that will be true + * for all users (the protocol is likely needed), so is staying at + * this time. - Phil Dibowitz + */ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, "LaCie", "USB Hard Disk", - US_SC_RBC, US_PR_CB, NULL, 0 ), + US_SC_DEVICE, US_PR_CB, NULL, 0 ), -/* Submitted by Jol Bourquard */ +/* Submitted by Joel Bourquard + * Some versions of this device need the SubClass and Protocol overrides + * while others don't. + */ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, "In-System", "PyroGate External CD-ROM Enclosure (FCD-523)", - US_SC_SCSI, US_PR_BULK, NULL, 0 ), + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_NEED_OVERRIDE ), #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, @@ -416,6 +471,13 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, 0 ), #endif +/* Reported by Avi Kivity */ +UNUSUAL_DEV( 0x05ac, 0x1203, 0x0001, 0x0001, + "Apple", + "iPod", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + #ifdef CONFIG_USB_STORAGE_JUMPSHOT UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", @@ -431,36 +493,6 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* Reported by Carlos Villegas - * This device needs an INQUIRY of exactly 36-bytes to function. - * That is the only reason this entry is needed. - */ -UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0xffff, - "Genesys Logic", - "USB to IDE Card Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_INQUIRY ), - -/* Submitted Alexander Oltu */ -UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, - "Genesys Logic", - "USB to IDE Optical", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_MODE_XLATE ), - -/* Reported by Peter Marks - * Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly - * 36 bytes of data. No more, no less. That is the only reason this entry - * is needed. - * - * ST818 slim drives (rev 0.02) don't need special care. -*/ -UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, - "Genesys Logic", - "USB to IDE Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_INQUIRY ), - /* Reported by Hanno Boeck * Taken from the Lycoris Kernel */ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, @@ -482,6 +514,13 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif +/* Reported by Darsen Lu */ +UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, + "SigmaTel", + "USBMSC Audio Player", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Submitted by Benny Sjostrand */ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, "Minolta", @@ -510,11 +549,13 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), +#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE) UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk", "ImageMate SDDR-31", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_SER ), +#endif UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", @@ -537,6 +578,13 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, US_SC_QIC, US_PR_FREECOM, freecom_init, 0), #endif +/* Reported by Eero Volotinen */ +UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0406, 0x0406, + "Freecom Technologies", + "FHD-Classic", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, "Microtech", "USB-SCSI-DB25", @@ -685,7 +733,7 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100, "Trumpion", "t33520 USB Flash Card Controller", US_SC_DEVICE, US_PR_BULK, NULL, - US_FL_MODE_XLATE), + US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE), /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, @@ -707,12 +755,6 @@ UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), -UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, - "IBM", - "IBM USB Memory Key", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_INQUIRY ), - /* This Pentax still camera is not conformant * to the USB storage specification: - * - It does not like the INQUIRY command. So we must handle this command @@ -785,13 +827,28 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Patch by Stephan Walter + * I don't know why, but it works... */ +UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012, + "WINWARD", + "Music Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Submitted by Antoine Mairesse */ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, "USB", "Solid state disk", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - + +/* Reported by Rastislav Stanik */ +UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110, + "USB", + "Flash Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. @@ -813,6 +870,13 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), +/* Reported by Kotrla Vitezslav */ +UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, + "SWISSBIT", + "Black Silver", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + #ifdef CONFIG_USB_STORAGE_SDDR55 UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, "Sandisk", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index ad22739be..cfa0ebfcf 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -50,6 +50,12 @@ #include #include #include +#include + +#include +#include +#include + #include "usb.h" #include "scsiglue.h" #include "transport.h" @@ -92,6 +98,11 @@ MODULE_AUTHOR("Matthew Dharm "); MODULE_DESCRIPTION("USB Mass Storage driver for Linux"); MODULE_LICENSE("GPL"); +static unsigned int delay_use = 5; +module_param(delay_use, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); + + static int storage_probe(struct usb_interface *iface, const struct usb_device_id *id); @@ -133,7 +144,9 @@ static struct usb_device_id storage_usb_ids [] = { { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) }, { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) }, { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) }, +#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE) { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) }, +#endif /* Terminating entry */ { } @@ -207,8 +220,10 @@ static struct us_unusual_dev us_unusual_dev_list[] = { .useTransport = US_PR_BULK}, { .useProtocol = US_SC_8070, .useTransport = US_PR_BULK}, +#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE) { .useProtocol = US_SC_SCSI, .useTransport = US_PR_BULK}, +#endif /* Terminating entry */ { NULL } @@ -303,8 +318,8 @@ static int usb_stor_control_thread(void * __us) /* lock access to the state */ scsi_lock(host); - /* has the command been aborted *already* ? */ - if (us->sm_state == US_STATE_ABORTING) { + /* has the command timed out *already* ? */ + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { us->srb->result = DID_ABORT << 16; goto SkipForAbort; } @@ -315,14 +330,12 @@ static int usb_stor_control_thread(void * __us) goto SkipForDisconnect; } - /* set the state and release the lock */ - us->sm_state = US_STATE_RUNNING; scsi_unlock(host); /* reject the command if the direction indicator * is UNKNOWN */ - if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { + if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) { US_DEBUGP("UNKNOWN data direction\n"); us->srb->result = DID_ERROR << 16; } @@ -377,16 +390,15 @@ SkipForAbort: /* If an abort request was received we need to signal that * the abort has finished. The proper test for this is - * sm_state == US_STATE_ABORTING, not srb->result == DID_ABORT, - * because an abort request might be received after all the + * the TIMED_OUT flag, not srb->result == DID_ABORT, because + * a timeout/abort request might be received after all the * USB processing was complete. */ - if (us->sm_state == US_STATE_ABORTING) + if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) complete(&(us->notify)); - /* empty the queue, reset the state, and release the lock */ + /* finished working on this command */ SkipForDisconnect: us->srb = NULL; - us->sm_state = US_STATE_IDLE; scsi_unlock(host); /* unlock the device pointers */ @@ -423,6 +435,13 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) us->pusb_dev = interface_to_usbdev(intf); us->pusb_intf = intf; us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", + us->pusb_dev->descriptor.idVendor, + us->pusb_dev->descriptor.idProduct, + us->pusb_dev->descriptor.bcdDevice); + US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n", + intf->cur_altsetting->desc.bInterfaceSubClass, + intf->cur_altsetting->desc.bInterfaceProtocol); /* Store our private data in the interface */ usb_set_intfdata(intf, us); @@ -453,11 +472,6 @@ static void get_device_info(struct us_data *us, int id_index) struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; struct usb_device_id *id = &storage_usb_ids[id_index]; - if (unusual_dev->vendorName) - US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName); - if (unusual_dev->productName) - US_DEBUGP("Product: %s\n", unusual_dev->productName); - /* Store the entries */ us->unusual_dev = unusual_dev; us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? @@ -528,6 +542,8 @@ static void get_device_info(struct us_data *us, int id_index) } if (strlen(us->serial) == 0) strcpy(us->serial, "None"); + + US_DEBUGP("Vendor: %s, Product: %s\n", us->vendor, us->product); } /* Get the transport settings */ @@ -715,8 +731,6 @@ static int get_pipes(struct us_data *us) ep_int = ep; } } - US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n", - ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0); if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) { US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n"); @@ -784,7 +798,6 @@ static int usb_stor_acquire_resources(struct us_data *us) us->host->hostdata[0] = (unsigned long) us; /* Start up our control thread */ - us->sm_state = US_STATE_IDLE; p = kernel_thread(usb_stor_control_thread, us, CLONE_VM); if (p < 0) { printk(KERN_WARNING USB_STORAGE @@ -812,7 +825,6 @@ void usb_stor_release_resources(struct us_data *us) /* Wait for the thread to be idle */ down(&us->dev_semaphore); US_DEBUGP("-- sending exit command to thread\n"); - BUG_ON(us->sm_state != US_STATE_IDLE); /* If the SCSI midlayer queued a final command just before * scsi_remove_host() was called, us->srb might not be @@ -871,6 +883,46 @@ static void dissociate_dev(struct us_data *us) kfree(us); } +/* Thread to carry out delayed SCSI-device scanning */ +static int usb_stor_scan_thread(void * __us) +{ + struct us_data *us = (struct us_data *)__us; + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources. + */ + lock_kernel(); + daemonize("usb-stor-scan"); + unlock_kernel(); + + printk(KERN_DEBUG + "usb-storage: device found at %d\n", us->pusb_dev->devnum); + + /* Wait for the timeout to expire or for a disconnect */ + if (delay_use > 0) { + printk(KERN_DEBUG "usb-storage: waiting for device " + "to settle before scanning\n"); +retry: + wait_event_interruptible_timeout(us->scsi_scan_wait, + test_bit(US_FLIDX_DISCONNECTING, &us->flags), + delay_use * HZ); + if (current->flags & PF_FREEZE) { + refrigerator(PF_FREEZE); + goto retry; + } + } + + /* If the device is still connected, perform the scanning */ + if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + scsi_scan_host(us->host); + printk(KERN_DEBUG "usb-storage: device scan complete\n"); + } + + complete_and_exit(&us->scsi_scan_done, 0); +} + + /* Probe to see if we can drive a newly-connected USB device */ static int storage_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -880,9 +932,6 @@ static int storage_probe(struct usb_interface *intf, int result; US_DEBUGP("USB Mass Storage device detected\n"); - US_DEBUGP("altsetting is %d, id_index is %d\n", - intf->cur_altsetting->desc.bAlternateSetting, - id_index); /* Allocate the us_data structure and initialize the mutexes */ us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL); @@ -895,6 +944,8 @@ static int storage_probe(struct usb_interface *intf, init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); init_waitqueue_head(&us->dev_reset_wait); + init_waitqueue_head(&us->scsi_scan_wait); + init_completion(&us->scsi_scan_done); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -943,12 +994,10 @@ static int storage_probe(struct usb_interface *intf, if (result) goto BadDevice; - /* Acquire all the other resources */ + /* Acquire all the other resources and add the host */ result = usb_stor_acquire_resources(us); if (result) goto BadDevice; - - /* Finally, add the host (this does SCSI device scanning) */ result = scsi_add_host(us->host, &intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE @@ -956,10 +1005,15 @@ static int storage_probe(struct usb_interface *intf, goto BadDevice; } - scsi_scan_host(us->host); + /* Start up the thread for delayed SCSI-device scanning */ + result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM); + if (result < 0) { + printk(KERN_WARNING USB_STORAGE + "Unable to start the device-scanning thread\n"); + scsi_remove_host(us->host); + goto BadDevice; + } - printk(KERN_DEBUG - "USB Mass Storage device found at %d\n", us->pusb_dev->devnum); return 0; /* We come here if there are any problems */ @@ -983,6 +1037,11 @@ static void storage_disconnect(struct usb_interface *intf) usb_stor_stop_transport(us); wake_up(&us->dev_reset_wait); + /* Interrupt the SCSI-device-scanning thread's time delay, and + * wait for the thread to finish */ + wake_up(&us->scsi_scan_wait); + wait_for_completion(&us->scsi_scan_done); + /* Wait for the current command to finish, then remove the host */ down(&us->dev_semaphore); up(&us->dev_semaphore); @@ -1004,12 +1063,9 @@ static int __init usb_stor_init(void) /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); - if (retval) - goto out; + if (retval == 0) + printk(KERN_INFO "USB Mass Storage support registered.\n"); - /* we're all set */ - printk(KERN_INFO "USB Mass Storage support registered.\n"); -out: return retval; } diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 35d01444a..45feb362a 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -48,10 +48,9 @@ #include #include #include -#include "scsi.h" -#include struct us_data; +struct scsi_cmnd; /* * Unusual device list definitions @@ -74,6 +73,7 @@ struct us_unusual_dev { #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ +#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */ /* Dynamic flag definitions: used in set_bit() etc. */ #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ @@ -83,14 +83,9 @@ struct us_unusual_dev { #define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ (1UL << US_FLIDX_DISCONNECTING)) #define US_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */ +#define US_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */ -/* processing state machine states */ -#define US_STATE_IDLE 1 -#define US_STATE_RUNNING 2 -#define US_STATE_RESETTING 3 -#define US_STATE_ABORTING 4 - #define USB_STOR_STRING_LEN 32 /* @@ -102,9 +97,9 @@ struct us_unusual_dev { #define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */ -typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); +typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); typedef int (*trans_reset)(struct us_data*); -typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); +typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); typedef void (*extra_data_destructor)(void *); /* extra data destructor */ /* we allocate one of these for every device that we remember */ @@ -144,11 +139,10 @@ struct us_data { /* SCSI interfaces */ struct Scsi_Host *host; /* our dummy host data */ - Scsi_Cmnd *srb; /* current srb */ + struct scsi_cmnd *srb; /* current srb */ /* thread information */ int pid; /* control thread */ - int sm_state; /* what we are doing */ /* control and bulk communications data */ struct urb *current_urb; /* USB requests */ @@ -162,6 +156,8 @@ struct us_data { struct semaphore sema; /* to sleep thread on */ struct completion notify; /* thread begin/end */ wait_queue_head_t dev_reset_wait; /* wait during reset */ + wait_queue_head_t scsi_scan_wait; /* wait before scanning */ + struct completion scsi_scan_done; /* scan thread end */ /* subdriver information */ void *extra; /* Any extra data */ @@ -180,4 +176,8 @@ extern void fill_inquiry_response(struct us_data *us, #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) + +/* Vendor ID list for devices that require special handling */ +#define USB_VENDOR_ID_GENESYS 0x05e3 /* Genesys Logic */ + #endif diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index f893cc078..d3a3fd9b1 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -1,42 +1,15 @@ /* - * USB Skeleton driver - 1.1 + * USB Skeleton driver - 2.0 * - * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.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, version 2. * - * - * This driver is to be used as a skeleton driver to be able to create a - * USB driver quickly. The design of it is based on the usb-serial and - * dc2xx drivers. - * - * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help - * in debugging this driver. - * - * - * History: - * - * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev() - * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and - * disconnect. Fix transfer amount in read(). Use - * macros instead of magic numbers in probe(). Change - * size variables to size_t. Show how to eliminate - * DMA bounce buffer. - * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array. - * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device - * driver. - * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do - * not have both a bulk in and bulk out endpoint. - * Thanks to Holger Waechtler for the fix. - * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect. - * Thanks to Pete Zaitcev for the fix. - * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux - * 2001_08_21 - 0.4 - more small bug fixes. - * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel - * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people - * 2001_05_01 - 0.1 - first version + * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c + * but has been rewritten to be easy to read and use, as no locks are now + * needed anymore. * */ @@ -46,31 +19,10 @@ #include #include #include -#include -#include +#include #include #include -#ifdef CONFIG_USB_DEBUG - static int debug = 1; -#else - static int debug; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0) - - -/* Version Information */ -#define DRIVER_VERSION "v1.0" -#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" -#define DRIVER_DESC "USB Skeleton Driver" - -/* Module parameters */ -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* Define these values to match your devices */ #define USB_SKEL_VENDOR_ID 0xfff0 @@ -79,11 +31,8 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); /* table of devices that work with this driver */ static struct usb_device_id skel_table [] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, - /* "Gadget Zero" firmware runs under Linux */ - { USB_DEVICE(0x0525, 0xa4a0) }, { } /* Terminating entry */ }; - MODULE_DEVICE_TABLE (usb, skel_table); @@ -92,413 +41,195 @@ MODULE_DEVICE_TABLE (usb, skel_table); /* Structure to hold all of our device specific stuff */ struct usb_skel { - struct usb_device * udev; /* save off the usb device pointer */ + struct usb_device * udev; /* the usb device for this device */ struct usb_interface * interface; /* the interface for this device */ - unsigned char minor; /* the starting minor number for this device */ - unsigned char num_ports; /* the number of ports this device has */ - char num_interrupt_in; /* number of interrupt in endpoints we have */ - char num_bulk_in; /* number of bulk in endpoints we have */ - char num_bulk_out; /* number of bulk out endpoints we have */ - unsigned char * bulk_in_buffer; /* the buffer to receive data */ size_t bulk_in_size; /* the size of the receive buffer */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ - - unsigned char * bulk_out_buffer; /* the buffer to send data */ - size_t bulk_out_size; /* the size of the send buffer */ - struct urb * write_urb; /* the urb used to send data */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ - atomic_t write_busy; /* true iff write urb is busy */ - struct completion write_finished; /* wait for the write to finish */ - - int open; /* if the port is open or not */ - int present; /* if the device is not disconnected */ - struct semaphore sem; /* locks this structure */ -}; - - -/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); - -/* local function prototypes */ -static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos); -static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos); -static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -static int skel_open (struct inode *inode, struct file *file); -static int skel_release (struct inode *inode, struct file *file); - -static int skel_probe (struct usb_interface *interface, const struct usb_device_id *id); -static void skel_disconnect (struct usb_interface *interface); - -static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs); - -/* - * File operations needed when we register this driver. - * This assumes that this driver NEEDS file operations, - * of course, which means that the driver is expected - * to have a node in the /dev directory. If the USB - * device were for a network interface then the driver - * would use "struct net_driver" instead, and a serial - * device would use "struct tty_driver". - */ -static struct file_operations skel_fops = { - /* - * The owner field is part of the module-locking - * mechanism. The idea is that the kernel knows - * which module to increment the use-counter of - * BEFORE it calls the device's open() function. - * This also means that the kernel can decrement - * the use-counter again before calling release() - * or should the open() function fail. - */ - .owner = THIS_MODULE, - - .read = skel_read, - .write = skel_write, - .ioctl = skel_ioctl, - .open = skel_open, - .release = skel_release, -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with devfs and the driver core - */ -static struct usb_class_driver skel_class = { - .name = "usb/skel%d", - .fops = &skel_fops, - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, - .minor_base = USB_SKEL_MINOR_BASE, -}; - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver skel_driver = { - .owner = THIS_MODULE, - .name = "skeleton", - .probe = skel_probe, - .disconnect = skel_disconnect, - .id_table = skel_table, + struct kref kref; }; +#define to_skel_dev(d) container_of(d, struct usb_skel, kref) +static struct usb_driver skel_driver; -/** - * usb_skel_debug_data - */ -static inline void usb_skel_debug_data (const char *function, int size, const unsigned char *data) -{ - int i; +static void skel_delete(struct kref *kref) +{ + struct usb_skel *dev = to_skel_dev(kref); - if (!debug) - return; - - printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", - function, size); - for (i = 0; i < size; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); -} - - -/** - * skel_delete - */ -static inline void skel_delete (struct usb_skel *dev) -{ + usb_put_dev(dev->udev); kfree (dev->bulk_in_buffer); - usb_buffer_free (dev->udev, dev->bulk_out_size, - dev->bulk_out_buffer, - dev->write_urb->transfer_dma); - usb_free_urb (dev->write_urb); kfree (dev); } - -/** - * skel_open - */ -static int skel_open (struct inode *inode, struct file *file) +static int skel_open(struct inode *inode, struct file *file) { - struct usb_skel *dev = NULL; + struct usb_skel *dev; struct usb_interface *interface; int subminor; int retval = 0; - dbg("%s", __FUNCTION__); - subminor = iminor(inode); - /* prevent disconnects */ - down (&disconnect_sem); - - interface = usb_find_interface (&skel_driver, subminor); + interface = usb_find_interface(&skel_driver, subminor); if (!interface) { err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); retval = -ENODEV; - goto exit_no_device; + goto exit; } dev = usb_get_intfdata(interface); if (!dev) { retval = -ENODEV; - goto exit_no_device; + goto exit; } - /* lock this device */ - down (&dev->sem); - - /* increment our usage count for the driver */ - ++dev->open; + /* increment our usage count for the device */ + kref_get(&dev->kref); /* save our object in the file's private structure */ file->private_data = dev; - /* unlock this device */ - up (&dev->sem); - -exit_no_device: - up (&disconnect_sem); +exit: return retval; } - -/** - * skel_release - */ -static int skel_release (struct inode *inode, struct file *file) +static int skel_release(struct inode *inode, struct file *file) { struct usb_skel *dev; - int retval = 0; dev = (struct usb_skel *)file->private_data; - if (dev == NULL) { - dbg ("%s - object is NULL", __FUNCTION__); + if (dev == NULL) return -ENODEV; - } - dbg("%s - minor %d", __FUNCTION__, dev->minor); - - /* lock our device */ - down (&dev->sem); - - if (dev->open <= 0) { - dbg ("%s - device not opened", __FUNCTION__); - retval = -ENODEV; - goto exit_not_opened; - } - - /* wait for any bulk writes that might be going on to finish up */ - if (atomic_read (&dev->write_busy)) - wait_for_completion (&dev->write_finished); - - --dev->open; - - if (!dev->present && !dev->open) { - /* the device was unplugged before the file was released */ - up (&dev->sem); - skel_delete (dev); - return 0; - } - -exit_not_opened: - up (&dev->sem); - - return retval; + /* decrement the count on our device */ + kref_put(&dev->kref, skel_delete); + return 0; } - -/** - * skel_read - */ -static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct usb_skel *dev; int retval = 0; dev = (struct usb_skel *)file->private_data; - - dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count); - - /* lock this object */ - down (&dev->sem); - - /* verify that the device wasn't unplugged */ - if (!dev->present) { - up (&dev->sem); - return -ENODEV; - } - + /* do a blocking bulk read to get data from the device */ - retval = usb_bulk_msg (dev->udev, - usb_rcvbulkpipe (dev->udev, - dev->bulk_in_endpointAddr), - dev->bulk_in_buffer, - min (dev->bulk_in_size, count), - &count, HZ*10); + retval = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), + dev->bulk_in_buffer, + min(dev->bulk_in_size, count), + &count, HZ*10); /* if the read was successful, copy the data to userspace */ if (!retval) { - if (copy_to_user (buffer, dev->bulk_in_buffer, count)) + if (copy_to_user(buffer, dev->bulk_in_buffer, count)) retval = -EFAULT; else retval = count; } - /* unlock the device */ - up (&dev->sem); return retval; } - -/** - * skel_write - * - * A device driver has to decide how to report I/O errors back to the - * user. The safest course is to wait for the transfer to finish before - * returning so that any errors will be reported reliably. skel_read() - * works like this. But waiting for I/O is slow, so many drivers only - * check for errors during I/O initiation and do not report problems - * that occur during the actual transfer. That's what we will do here. - * - * A driver concerned with maximum I/O throughput would use double- - * buffering: Two urbs would be devoted to write transfers, so that - * one urb could always be active while the other was waiting for the - * user to send more data. - */ -static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos) +static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { struct usb_skel *dev; - ssize_t bytes_written = 0; - int retval = 0; - dev = (struct usb_skel *)file->private_data; + dev = (struct usb_skel *)urb->context; - dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count); + /* sync/async unlink faults aren't errors */ + if (urb->status && + !(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) { + dbg("%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); + } - /* lock this object */ - down (&dev->sem); + /* free up our allocated buffer */ + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); +} - /* verify that the device wasn't unplugged */ - if (!dev->present) { - retval = -ENODEV; - goto exit; - } +static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) +{ + struct usb_skel *dev; + int retval = 0; + struct urb *urb = NULL; + char *buf = NULL; + + dev = (struct usb_skel *)file->private_data; /* verify that we actually have some data to write */ - if (count == 0) { - dbg("%s - write request of 0 bytes", __FUNCTION__); + if (count == 0) goto exit; - } - /* wait for a previous write to finish up; we don't use a timeout - * and so a nonresponsive device can delay us indefinitely. - */ - if (atomic_read (&dev->write_busy)) - wait_for_completion (&dev->write_finished); + /* create a urb, and a buffer for it, and copy the data to the urb */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } - /* we can only write as much as our buffer will hold */ - bytes_written = min (dev->bulk_out_size, count); + buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); + if (!buf) { + retval = -ENOMEM; + goto error; + } - /* copy the data from userspace into our transfer buffer; - * this is the only copy required. - */ - if (copy_from_user(dev->write_urb->transfer_buffer, buffer, - bytes_written)) { + if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; - goto exit; + goto error; } - usb_skel_debug_data (__FUNCTION__, bytes_written, - dev->write_urb->transfer_buffer); - - /* this urb was already set up, except for this write size */ - dev->write_urb->transfer_buffer_length = bytes_written; + /* initialize the urb properly */ + usb_fill_bulk_urb(urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), + buf, count, skel_write_bulk_callback, dev); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* send the data out the bulk port */ - /* a character device write uses GFP_KERNEL, - unless a spinlock is held */ - init_completion (&dev->write_finished); - atomic_set (&dev->write_busy, 1); - retval = usb_submit_urb(dev->write_urb, GFP_KERNEL); + retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { - atomic_set (&dev->write_busy, 0); - err("%s - failed submitting write urb, error %d", - __FUNCTION__, retval); - } else { - retval = bytes_written; + err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); + goto error; } + /* release our reference to this urb, the USB core will eventually free it entirely */ + usb_free_urb(urb); + exit: - /* unlock the device */ - up (&dev->sem); + return count; +error: + usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); + usb_free_urb(urb); return retval; } +static struct file_operations skel_fops = { + .owner = THIS_MODULE, + .read = skel_read, + .write = skel_write, + .open = skel_open, + .release = skel_release, +}; -/** - * skel_ioctl - */ -static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct usb_skel *dev; - - dev = (struct usb_skel *)file->private_data; - - /* lock this object */ - down (&dev->sem); - - /* verify that the device wasn't unplugged */ - if (!dev->present) { - up (&dev->sem); - return -ENODEV; - } - - dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__, - dev->minor, cmd, arg); - - /* fill in your device specific stuff here */ - - /* unlock the device */ - up (&dev->sem); - - /* return that we did not understand this ioctl call */ - return -ENOTTY; -} - - -/** - * skel_write_bulk_callback +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with devfs and the driver core */ -static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs) -{ - struct usb_skel *dev = (struct usb_skel *)urb->context; - - dbg("%s - minor %d", __FUNCTION__, dev->minor); - - /* sync/async unlink faults aren't errors */ - if (urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET)) { - dbg("%s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); - } - - /* notify anyone waiting that the write has finished */ - atomic_set (&dev->write_busy, 0); - complete (&dev->write_finished); -} - +static struct usb_class_driver skel_class = { + .name = "usb/skel%d", + .fops = &skel_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, + .minor_base = USB_SKEL_MINOR_BASE, +}; -/** - * skel_probe - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id) { - struct usb_device *udev = interface_to_usbdev(interface); struct usb_skel *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; @@ -506,28 +237,21 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i int i; int retval = -ENOMEM; - /* See if the device offered us matches what we can accept */ - if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) || - (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) { - return -ENODEV; - } - /* allocate memory for our device state and initialize it */ - dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - err ("Out of memory"); - return -ENOMEM; + err("Out of memory"); + goto error; } - memset (dev, 0x00, sizeof (*dev)); + memset(dev, 0x00, sizeof(*dev)); + kref_init(&dev->kref); - init_MUTEX (&dev->sem); - dev->udev = udev; + dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; /* set up the endpoint information */ - /* check out the endpoints */ /* use only the first bulk-in and bulk-out endpoints */ - iface_desc = &interface->altsetting[0]; + iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; @@ -539,9 +263,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i buffer_size = endpoint->wMaxPacketSize; dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; - dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); + dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { - err("Couldn't allocate bulk_in_buffer"); + err("Could not allocate bulk_in_buffer"); goto error; } } @@ -551,153 +275,85 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk out endpoint */ - /* a probe() may sleep and has no restrictions on memory allocations */ - dev->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->write_urb) { - err("No free urbs available"); - goto error; - } dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; - - /* on some platforms using this kind of buffer alloc - * call eliminates a dma "bounce buffer". - * - * NOTE: you'd normally want i/o buffers that hold - * more than one packet, so that i/o delays between - * packets don't hurt throughput. - */ - buffer_size = endpoint->wMaxPacketSize; - dev->bulk_out_size = buffer_size; - dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | - URB_ASYNC_UNLINK); - dev->bulk_out_buffer = usb_buffer_alloc (udev, - buffer_size, GFP_KERNEL, - &dev->write_urb->transfer_dma); - if (!dev->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); - goto error; - } - usb_fill_bulk_urb(dev->write_urb, udev, - usb_sndbulkpipe(udev, - endpoint->bEndpointAddress), - dev->bulk_out_buffer, buffer_size, - skel_write_bulk_callback, dev); } } if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { - err("Couldn't find both bulk-in and bulk-out endpoints"); + err("Could not find both bulk-in and bulk-out endpoints"); goto error; } - /* allow device read, write and ioctl */ - dev->present = 1; + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); /* we can register the device now, as it is ready */ - usb_set_intfdata (interface, dev); - retval = usb_register_dev (interface, &skel_class); + retval = usb_register_dev(interface, &skel_class); if (retval) { /* something prevented us from registering this driver */ - err ("Not able to get a minor for this device."); - usb_set_intfdata (interface, NULL); + err("Not able to get a minor for this device."); + usb_set_intfdata(interface, NULL); goto error; } - dev->minor = interface->minor; - /* let the user know what node this device is now attached to */ - info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); + info("USB Skeleton device now attached to USBSkel-%d", interface->minor); return 0; error: - skel_delete (dev); + if (dev) + kref_put(&dev->kref, skel_delete); return retval; } - -/** - * skel_disconnect - * - * Called by the usb core when the device is removed from the system. - * - * This routine guarantees that the driver will not submit any more urbs - * by clearing dev->udev. It is also supposed to terminate any currently - * active urbs. Unfortunately, usb_bulk_msg(), used in skel_read(), does - * not provide any way to do this. But at least we can cancel an active - * write. - */ static void skel_disconnect(struct usb_interface *interface) { struct usb_skel *dev; - int minor; + int minor = interface->minor; - /* prevent races with open() */ - down (&disconnect_sem); + /* prevent skel_open() from racing skel_disconnect() */ + lock_kernel(); - dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); - - down (&dev->sem); - - minor = dev->minor; + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); /* give back our minor */ - usb_deregister_dev (interface, &skel_class); + usb_deregister_dev(interface, &skel_class); - /* terminate an ongoing write */ - if (atomic_read (&dev->write_busy)) { - usb_unlink_urb (dev->write_urb); - wait_for_completion (&dev->write_finished); - } - - /* prevent device read, write and ioctl */ - dev->present = 0; - - up (&dev->sem); + unlock_kernel(); - /* if the device is opened, skel_release will clean this up */ - if (!dev->open) - skel_delete (dev); - - up (&disconnect_sem); + /* decrement our usage count */ + kref_put(&dev->kref, skel_delete); info("USB Skeleton #%d now disconnected", minor); } +static struct usb_driver skel_driver = { + .owner = THIS_MODULE, + .name = "skeleton", + .probe = skel_probe, + .disconnect = skel_disconnect, + .id_table = skel_table, +}; - -/** - * usb_skel_init - */ static int __init usb_skel_init(void) { int result; /* register this driver with the USB subsystem */ result = usb_register(&skel_driver); - if (result) { - err("usb_register failed. Error number %d", - result); - return result; - } + if (result) + err("usb_register failed. Error number %d", result); - info(DRIVER_DESC " " DRIVER_VERSION); - return 0; + return result; } - -/** - * usb_skel_exit - */ static void __exit usb_skel_exit(void) { /* deregister this driver with the USB subsystem */ usb_deregister(&skel_driver); } - module_init (usb_skel_init); module_exit (usb_skel_exit); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 5e9bcf5a8..6a3cfbdc6 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -199,6 +199,15 @@ static int mc68x328fb_check_var(struct fb_var_screeninfo *var, */ switch (var->bits_per_pixel) { case 1: + var->red.offset = 0; + var->red.length = 1; + var->green.offset = 0; + var->green.length = 1; + var->blue.offset = 0; + var->blue.length = 1; + var->transp.offset = 0; + var->transp.length = 0; + break; case 8: var->red.offset = 0; var->red.length = 8; @@ -430,6 +439,13 @@ int __init mc68x328fb_setup(char *options) int __init mc68x328fb_init(void) { +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("68328fb", &option)) + return -ENODEV; + mc68x328fb_setup(option); +#endif /* * initialize the default mode from the LCD controller registers */ @@ -452,8 +468,12 @@ int __init mc68x328fb_init(void) get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel); fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ? MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR; + if (fb_info.var.bits_per_pixel == 1) { + fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1; + fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0; + } fb_info.pseudo_palette = &mc68x328fb_pseudo_palette; - fb_info.flags = FBINFO_FLAG_DEFAULT; + fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; fb_alloc_cmap(&fb_info.cmap, 256, 0); @@ -471,6 +491,8 @@ int __init mc68x328fb_init(void) return 0; } +module_init(mc68x328fb_init); + #ifdef MODULE static void __exit mc68x328fb_cleanup(void) @@ -478,7 +500,6 @@ static void __exit mc68x328fb_cleanup(void) unregister_framebuffer(&fb_info); } -module_init(mc68x328fb_init); module_exit(mc68x328fb_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 798ba0032..4c7e14849 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -38,6 +38,35 @@ config FB (e.g. an accelerated X server) and that are not frame buffer device-aware may cause unexpected results. If unsure, say N. +config FB_MODE_HELPERS + bool "Enable Video Mode Handling Helpers" + depends on FB + default n + ---help--- + This enables functions for handling video modes using the + Generalized Timing Formula and the EDID parser. A few drivers rely + on this feature such as the radeonfb, rivafb, and the i810fb. If + your driver does not take advantage of this feature, choosing Y will + just increase the kernel size by about 5K. + +config FB_TILEBLITTING + bool "Enable Tile Blitting Support" + depends on FB + default n + ---help--- + This enables tile blitting. Tile blitting is a drawing technique + where the screen is divided into rectangular sections (tiles), whereas + the standard blitting divides the screen into pixels. Because the + default drawing element is a tile, drawing functions will be passed + parameters in terms of number of tiles instead of number of pixels. + For example, to draw a single character, instead of using bitmaps, + an index to an array of bitmaps will be used. To clear or move a + rectangular section of a screen, the rectangle will be described in + terms of number of tiles in the x- and y-axis. + + This is particularly important to one driver, matroxfb. If + unsure, say N. + config FB_CIRRUS tristate "Cirrus Logic support" depends on FB && (ZORRO || PCI) @@ -68,6 +97,19 @@ config FB_PM2_FIFO_DISCONNECT help Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). +config FB_ARMCLCD + tristate "ARM PrimeCell PL110 support" + depends on FB && ARM && ARM_AMBA + help + This framebuffer device driver is for the ARM PrimeCell PL110 + Colour LCD controller. ARM PrimeCells provide the building + blocks for System on a Chip devices. + + If you want to compile this as a module (=code which can be + inserted into and removed from the running kernel), say M + here and read . The module + will be called amba-clcd. + config FB_ACORN bool "Acorn VIDC support" depends on FB && ARM && ARCH_ACORN @@ -392,40 +434,21 @@ config FB_PVR2 (). Please see the file . -config FB_E1355 +config FB_EPSON1355 bool "Epson 1355 framebuffer support" - depends on FB && SUPERH + depends on FB && (SUPERH || ARCH_CEIVA) help Build in support for the SED1355 Epson Research Embedded RAMDAC LCD/CRT Controller (since redesignated as the S1D13505) as a framebuffer. Product specs at . -config E1355_REG_BASE - hex "Register Base Address" - depends on FB_E1355 - default "a8000000" - help - Epson SED1355/S1D13505 LCD/CRT controller register base address. - See the manuals at - for - discussion. - -config E1355_FB_BASE - hex "Framebuffer Base Address" - depends on FB_E1355 - default "a8200000" - help - Epson SED1355/S1D13505 LCD/CRT controller memory base address. See - the manuals at - for - discussion. - config FB_RIVA tristate "nVidia Riva support" depends on FB && PCI select I2C_ALGOBIT if FB_RIVA_I2C select I2C if FB_RIVA_I2C + select FB_MODE_HELPERS help This driver supports graphics boards with the nVidia Riva/Geforce chips. @@ -457,7 +480,10 @@ config FB_RIVA_DEBUG config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" - depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI + depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + select AGP + select AGP_INTEL + select FB_MODE_HELPERS help This driver supports the on-board graphics built in to the Intel 810 and 815 chipsets. Say Y if you have and plan to use such a board. @@ -491,6 +517,27 @@ config FB_I810_GTF If unsure, say N. +config FB_INTEL + tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" + depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64 + select AGP + select AGP_INTEL + help + This driver supports the on-board graphics built in to the Intel + 830M/845G/852GM/855GM/865G chipsets. + Say Y if you have and plan to use such a board. + + To compile this driver as a module, choose M here: the + module will be called intelfb. + +config FB_INTEL_DEBUG + bool "Intel driver Debug Messages" + depends on FB_INTEL + ---help--- + Say Y here if you want the Intel driver to output all sorts + of debugging informations to provide to the maintainer when + something goes wrong. + config FB_MATROX tristate "Matrox acceleration" depends on FB && PCI @@ -661,6 +708,7 @@ config FB_RADEON depends on FB && PCI select I2C_ALGOBIT if FB_RADEON_I2C select I2C if FB_RADEON_I2C + select FB_MODE_HELPERS help 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 @@ -723,6 +771,19 @@ config FB_ATY_CT framebuffer device. The ATI product support page for these boards is at . +config FB_ATY_GENERIC_LCD + bool "Mach64 generic LCD support (EXPERIMENTAL)" + depends on FB_ATY_CT + help + Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility, + Rage XC, or Rage XL chipset. + +config FB_ATY_XL_INIT + bool "Rage XL No-BIOS Init support" + depends on FB_ATY_CT + help + Say Y here to support booting a Rage XL without BIOS support. + config FB_ATY_GX bool "Mach64 GX support" if PCI depends on FB_ATY @@ -734,11 +795,41 @@ config FB_ATY_GX is at . -config FB_ATY_XL_INIT - bool " Rage XL No-BIOS Init support" if FB_ATY_CT - depends on FB_ATY +config FB_SAVAGE + tristate "S3 Savage support" + depends on FB && PCI && EXPERIMENTAL + select I2C_ALGOBIT if FB_SAVAGE_I2C + select I2C if FB_SAVAGE_I2C + select FB_MODE_HELPERS help - Say Y here to support booting a Rage XL without BIOS support. + This driver supports notebooks and computers with S3 Savage PCI/AGP + chips. + + Say Y if you have such a graphics card. + + To compile this driver as a module, choose M here; the module + will be called savagefb. + +config FB_SAVAGE_I2C + tristate "Enable DDC2 Support" + depends on FB_SAVAGE + help + This enables I2C support for S3 Savage Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_SAVAGE_ACCEL + tristate "Enable Console Acceleration" + depends on FB_SAVAGE + default n + help + This option will compile in console acceleration support. If + the resulting framebuffer console has bothersome glitches, then + choose N here. config FB_SIS tristate "SiS acceleration" @@ -766,6 +857,7 @@ config FB_SIS_315 config FB_NEOMAGIC tristate "NeoMagic display support" depends on FB && PCI + select FB_MODE_HELPERS help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 52e37a0fc..891cd4aaa 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -13,80 +13,93 @@ ifeq ($(CONFIG_FB),y) obj-$(CONFIG_PPC) += macmodes.o endif -obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +# Hardware specific drivers go first +obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o +obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_CYBER) += cyberfb.o +obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PM2) += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PM3) += pm3fb.o -obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_ATARI) += atafb.o -obj-$(CONFIG_FB_68328) += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o + +obj-$(CONFIG_FB_MATROX) += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o cfbfillrect.o \ + cfbcopyarea.o vgastate.o +obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_KYRO) += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_SAVAGE) += savage/ cfbfillrect.o cfbcopyarea.o \ + cfbimgblt.o +obj-$(CONFIG_FB_I810) += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \ + vgastate.o +obj-$(CONFIG_FB_INTEL) += cfbfillrect.o cfbcopyarea.o \ + cfbimgblt.o + obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o -obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_VIRGE) += virgefb.o +obj-$(CONFIG_FB_3DFX) += tdfxfb.o cfbimgblt.o +ifneq ($(CONFIG_FB_3DFX_ACCEL),y) +obj-$(CONFIG_FB_3DFX) += cfbfillrect.o cfbcopyarea.o +endif obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CT65550) += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_CYBER) += cyberfb.o -obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_GBE) += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_3DFX) += tdfxfb.o cfbimgblt.o -obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o cfbimgblt.o -obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o -obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o -obj-$(CONFIG_FB_TRIDENT) += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_S3TRIO) += S3triofb.o -obj-$(CONFIG_FB_TGA) += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_VGA16) += vga16fb.o cfbfillrect.o cfbcopyarea.o \ - cfbimgblt.o vgastate.o -obj-$(CONFIG_FB_VIRGE) += virgefb.o -obj-$(CONFIG_FB_G364) += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_FM2) += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_TRIDENT) += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_STI) += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o - -obj-$(CONFIG_FB_MATROX) += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o vgastate.o -obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \ - cfbimgblt.o vgastate.o - -obj-$(CONFIG_FB_SUN3) += sun3fb.o +obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o +obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o +obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_ATARI) += atafb.o +obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_TGA) += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_G364) += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_SUN3) += sun3fb.o obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbimgblt.o -obj-$(CONFIG_FB_E1355) += epson1355fb.o +obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_KYRO) += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_68328) += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_GBE) += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_PXA) += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o + +# Platform or fallback drivers go here +obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_VGA16) += vga16fb.o cfbfillrect.o cfbcopyarea.o \ + cfbimgblt.o vgastate.o +obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o -obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o -obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o -obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ - cfbfillrect.o -obj-$(CONFIG_FB_PXA) += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o +# the test framebuffer is last +obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 0c3aa4a7f..9e1a835f7 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1010,7 +1010,7 @@ static void __init acornfb_init_fbinfo(void) first = 0; fb_info.fbops = &acornfb_ops; - fb_info.flags = FBINFO_FLAG_DEFAULT; + fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; fb_info.pseudo_palette = current_par.pseudo_palette; strcpy(fb_info.fix.id, "Acorn"); @@ -1280,21 +1280,20 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) printk("acornfb: freed %dK memory\n", mb_freed); } -static struct device acornfb_device = { - .bus_id = "acornfb", - .coherent_dma_mask = 0xffffffff, -}; - -int __init -acornfb_init(void) +static int __init acornfb_probe(struct device *dev) { unsigned long size; u_int h_sync, v_sync; int rc, i; + char *option = NULL; + + if (fb_get_options("acornfb", &option)) + return -ENODEV; + acornfb_setup(option); acornfb_init_fbinfo(); - current_par.dev = &acornfb_device; + current_par.dev = dev; if (current_par.montype == -1) current_par.montype = acornfb_detect_monitortype(); @@ -1327,7 +1326,6 @@ acornfb_init(void) } } - fb_info.currcon = -1; fb_info.screen_base = (char *)SCREEN_BASE; fb_info.fix.smem_start = SCREEN_START; current_par.using_vram = 0; @@ -1456,6 +1454,19 @@ acornfb_init(void) return 0; } +static struct device_driver acornfb_driver = { + .name = "acornfb", + .bus = &platform_bus_type, + .probe = acornfb_probe, +}; + +static int __init acornfb_init(void) +{ + return driver_register(&acornfb_driver); +} + +module_init(acornfb_init); + MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 95ea71c9b..99c538f20 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1239,8 +1239,6 @@ int __init amifb_setup(char *options) if (!strcmp(this_opt, "inverse")) { amifb_inverse = 1; fb_invert_cmaps(); - } else if (!strcmp(this_opt, "off")) { - amifb_video_off(); } else if (!strcmp(this_opt, "ilbm")) amifb_ilbm = 1; else if (!strncmp(this_opt, "monitorcap:", 11)) @@ -1307,6 +1305,8 @@ static int amifb_set_par(struct fb_info *info) info->fix.ywrapstep = 1; info->fix.xpanstep = 0; info->fix.ypanstep = 0; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP | + FBINFO_READS_FAST; /* override SCROLL_REDRAW */ } else { info->fix.ywrapstep = 0; if (par->vmode & FB_VMODE_SMOOTH_XPAN) @@ -1314,6 +1314,7 @@ static int amifb_set_par(struct fb_info *info) else info->fix.xpanstep = 16<fix.ypanstep = 1; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; } return 0; } @@ -2254,21 +2255,17 @@ int __init amifb_init(void) u_long chipptr; u_int defmode; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return -ENXIO; - - /* - * TODO: where should we put this? The DMI Resolver doesn't have a - * frame buffer accessible by the CPU - */ +#ifndef MODULE + char *option = NULL; -#ifdef CONFIG_GSP_RESOLVER - if (amifb_resolver){ - custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | - DMAF_BLITTER | DMAF_SPRITE; - return 0; + if (fb_get_options("amifb", &option)) { + amifb_video_off(); + return -ENODEV; } + amifb_setup(option); #endif + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) + return -ENXIO; /* * We request all registers starting from bplpt[0] @@ -2382,7 +2379,7 @@ default_chipset: fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; - fb_info.flags = FBINFO_FLAG_DEFAULT; + fb_info.flags = FBINFO_DEFAULT; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2472,6 +2469,7 @@ static void amifb_deinit(void) static int amifb_blank(int blank, struct fb_info *info) { do_blank = blank ? blank : -1; + return 0; } @@ -2946,21 +2944,11 @@ static int ami_encode_var(struct fb_var_screeninfo *var, var->bits_per_pixel = par->bpp; var->grayscale = 0; - if (IS_AGA) { - var->red.offset = 0; - var->red.length = 8; - var->red.msb_right = 0; - } else { - if (clk_shift == TAG_SHRES) { - var->red.offset = 0; - var->red.length = 2; - var->red.msb_right = 0; - } else { - var->red.offset = 0; - var->red.length = 4; - var->red.msb_right = 0; - } - } + var->red.offset = 0; + var->red.msb_right = 0; + var->red.length = par->bpp; + if (par->bplcon0 & BPC0_HAM) + var->red.length -= 2; var->blue = var->green = var->red; var->transp.offset = 0; var->transp.length = 0; @@ -3260,20 +3248,20 @@ static void ami_do_blank(void) custom.dmacon = DMAF_RASTER | DMAF_SPRITE; red = green = blue = 0; if (!IS_OCS && do_blank > 1) { - switch (do_blank-1) { - case VESA_VSYNC_SUSPEND: + switch (do_blank) { + case FB_BLANK_VSYNC_SUSPEND: custom.hsstrt = hsstrt2hw(par->hsstrt); custom.hsstop = hsstop2hw(par->hsstop); custom.vsstrt = vsstrt2hw(par->vtotal+4); custom.vsstop = vsstop2hw(par->vtotal+4); break; - case VESA_HSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: custom.hsstrt = hsstrt2hw(par->htotal+16); custom.hsstop = hsstop2hw(par->htotal+16); custom.vsstrt = vsstrt2hw(par->vsstrt); custom.vsstop = vsstrt2hw(par->vsstop); break; - case VESA_POWERDOWN: + case FB_BLANK_POWERDOWN: custom.hsstrt = hsstrt2hw(par->htotal+16); custom.hsstop = hsstop2hw(par->htotal+16); custom.vsstrt = vsstrt2hw(par->vtotal+4); @@ -3811,14 +3799,11 @@ static void ami_rebuild_copper(void) } +module_init(amifb_init); + #ifdef MODULE MODULE_LICENSE("GPL"); -int init_module(void) -{ - return amifb_init(); -} - void cleanup_module(void) { unregister_framebuffer(&fb_info); diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 1563b0d27..15e092590 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -524,7 +524,7 @@ static void __init init_asiliant(struct fb_info *p, unsigned long addr) p->fix.smem_start = addr; p->var = asiliantfb_var; p->fbops = &asiliantfb_ops; - p->flags = FBINFO_FLAG_DEFAULT; + p->flags = FBINFO_DEFAULT; fb_alloc_cmap(&p->cmap, 256, 0); @@ -575,9 +575,6 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) init_asiliant(p, addr); - /* Clear the entire framebuffer */ - memset(p->screen_base, 0, 0x200000); - pci_set_drvdata(dp, p); return 0; } @@ -609,9 +606,14 @@ static struct pci_driver asiliantfb_driver = { int __init asiliantfb_init(void) { + if (fb_get_options("asiliantfb", NULL)) + return -ENODEV; + return pci_module_init(&asiliantfb_driver); } +module_init(asiliantfb_init); + static void __exit asiliantfb_exit(void) { pci_unregister_driver(&asiliantfb_driver); diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile index 8aa536873..5538f3cf6 100644 --- a/drivers/video/aty/Makefile +++ b/drivers/video/aty/Makefile @@ -2,9 +2,9 @@ obj-$(CONFIG_FB_ATY) += atyfb.o obj-$(CONFIG_FB_ATY128) += aty128fb.o obj-$(CONFIG_FB_RADEON) += radeonfb.o -atyfb-y := atyfb_base.o mach64_accel.o +atyfb-y := atyfb_base.o mach64_accel.o mach64_cursor.o atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o -atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o +atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o atyfb-objs := $(atyfb-y) radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h index d99e518aa..e4171869f 100644 --- a/drivers/video/aty/ati_ids.h +++ b/drivers/video/aty/ati_ids.h @@ -64,6 +64,7 @@ #define PCI_CHIP_MACH64LQ 0x4C51 #define PCI_CHIP_MACH64LR 0x4C52 #define PCI_CHIP_MACH64LS 0x4C53 +#define PCI_CHIP_MACH64LT 0x4C54 #define PCI_CHIP_RADEON_LW 0x4C57 #define PCI_CHIP_RADEON_LX 0x4C58 #define PCI_CHIP_RADEON_LY 0x4C59 diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 1c7bcd80f..a215c2f9f 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -397,7 +397,7 @@ struct aty128fb_par { struct aty128_ddafifo fifo_reg; u32 accel_flags; struct aty128_constants constants; /* PLL and others */ - void *regbase; /* remapped mmio */ + void __iomem *regbase; /* remapped mmio */ u32 vram_size; /* onboard video ram */ int chip_gen; const struct aty128_meminfo *mem; /* onboard mem info */ @@ -450,9 +450,9 @@ static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par); #if 0 static void __init aty128_get_pllinfo(struct aty128fb_par *par, - void *bios); -static void __init *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par); -static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom); + void __iomem *bios); +static void __init __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par); +static void __init aty128_unmap_ROM(struct pci_dev *dev, void __iomem * rom); #endif static void aty128_timings(struct aty128fb_par *par); static void aty128_init_engine(struct aty128fb_par *par); @@ -788,7 +788,7 @@ static u32 depth_to_dst(u32 depth) #ifndef __sparc__ -static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom) +static void __init aty128_unmap_ROM(struct pci_dev *dev, void __iomem * rom) { struct resource *r = &dev->resource[PCI_ROM_RESOURCE]; @@ -806,12 +806,12 @@ static void __init aty128_unmap_ROM(struct pci_dev *dev, void * rom) } -static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) +static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) { struct resource *r; u16 dptr; u8 rom_type; - void *bios; + void __iomem *bios; /* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */ unsigned int temp; @@ -903,7 +903,7 @@ static void * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_d return NULL; } -static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char *bios) +static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios) { unsigned int bios_hdr; unsigned int bios_pll; @@ -925,7 +925,7 @@ static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char *b } #ifdef CONFIG_X86 -static void * __devinit aty128_find_mem_vbios(struct aty128fb_par *par) +static void __iomem * __devinit aty128_find_mem_vbios(struct aty128fb_par *par) { /* I simplified this code as we used to miss the signatures in * a lot of case. It's now closer to XFree, we just don't check @@ -933,13 +933,13 @@ static void * __devinit aty128_find_mem_vbios(struct aty128fb_par *par) * if we end up having conflicts */ u32 segstart; - unsigned char *rom_base = NULL; + unsigned char __iomem *rom_base = NULL; for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { - rom_base = (char *)ioremap(segstart, 0x10000); + rom_base = ioremap(segstart, 0x10000); if (rom_base == NULL) return NULL; - if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa)) + if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa) break; iounmap(rom_base); rom_base = NULL; @@ -1885,7 +1885,7 @@ static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id struct fb_info *info; int err; #ifndef __sparc__ - void *bios = NULL; + void __iomem *bios = NULL; #endif /* Enable device in PCI config */ @@ -2016,8 +2016,6 @@ static void __devexit aty128_remove(struct pci_dev *pdev) release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); release_mem_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); framebuffer_release(info); @@ -2042,11 +2040,11 @@ static int aty128fb_blank(int blank, struct fb_info *fb) set_backlight_enable(0); #endif /* CONFIG_PMAC_BACKLIGHT */ - if (blank & VESA_VSYNC_SUSPEND) + if (blank & FB_BLANK_VSYNC_SUSPEND) state |= 2; - if (blank & VESA_HSYNC_SUSPEND) + if (blank & FB_BLANK_HSYNC_SUSPEND) state |= 1; - if (blank & VESA_POWERDOWN) + if (blank & FB_BLANK_POWERDOWN) state |= 4; aty_st_8(CRTC_EXT_CNTL+1, state); @@ -2363,7 +2361,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, u32 state) state = 2; #endif /* CONFIG_PPC_PMAC */ - if (state != 2 || state == pdev->dev.power_state) + if (state != 2 || state == pdev->dev.power.power_state) return 0; printk(KERN_DEBUG "aty128fb: suspending...\n"); @@ -2394,7 +2392,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, u32 state) release_console_sem(); - pdev->dev.power_state = state; + pdev->dev.power.power_state = state; return 0; } @@ -2404,13 +2402,13 @@ static int aty128_pci_resume(struct pci_dev *pdev) struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; - if (pdev->dev.power_state == 0) + if (pdev->dev.power.power_state == 0) return 0; acquire_console_sem(); /* Wakeup chip */ - if (pdev->dev.power_state == 2) + if (pdev->dev.power.power_state == 2) aty128_set_suspend(par, 0); par->asleep = 0; @@ -2430,7 +2428,7 @@ static int aty128_pci_resume(struct pci_dev *pdev) release_console_sem(); - pdev->dev.power_state = 0; + pdev->dev.power.power_state = 0; printk(KERN_DEBUG "aty128fb: resumed !\n"); @@ -2439,6 +2437,14 @@ static int aty128_pci_resume(struct pci_dev *pdev) int __init aty128fb_init(void) { +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("aty128fb", &option)) + return -ENODEV; + aty128fb_setup(option); +#endif + return pci_module_init(&aty128fb_driver); } @@ -2447,8 +2453,9 @@ static void __exit aty128fb_exit(void) pci_unregister_driver(&aty128fb_driver); } -#ifdef MODULE module_init(aty128fb_init); + +#ifdef MODULE module_exit(aty128fb_exit); MODULE_AUTHOR("(c)1999-2003 Brad Douglas "); diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index b342acc14..30e225f57 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -3,6 +3,8 @@ */ #include +#include +#include /* * Elements of the hardware specific atyfb_par structure */ @@ -10,16 +12,60 @@ struct crtc { u32 vxres; u32 vyres; + u32 xoffset; + u32 yoffset; + u32 bpp; u32 h_tot_disp; u32 h_sync_strt_wid; u32 v_tot_disp; u32 v_sync_strt_wid; + u32 vline_crnt_vline; u32 off_pitch; u32 gen_cntl; u32 dp_pix_width; /* acceleration */ u32 dp_chain_mask; /* acceleration */ +#ifdef CONFIG_FB_ATY_GENERIC_LCD + u32 horz_stretching; + u32 vert_stretching; + u32 ext_vert_stretch; + u32 shadow_h_tot_disp; + u32 shadow_h_sync_strt_wid; + u32 shadow_v_tot_disp; + u32 shadow_v_sync_strt_wid; + u32 lcd_gen_cntl; + u32 lcd_config_panel; + u32 lcd_index; +#endif +}; + +struct aty_interrupt { + wait_queue_head_t wait; + unsigned int count; + int pan_display; +}; + +struct pll_info { + int pll_max; + int pll_min; + int sclk, mclk, mclk_pm, xclk; + int ref_div; + int ref_clk; }; +typedef struct { + u16 unknown1; + u16 PCLK_min_freq; + u16 PCLK_max_freq; + u16 unknown2; + u16 ref_freq; + u16 ref_divider; + u16 unknown3; + u16 MCLK_pwd; + u16 MCLK_max_freq; + u16 XCLK_max_freq; + u16 SCLK_freq; +} __attribute__ ((packed)) PLL_BLOCK_MACH64; + struct pll_514 { u8 m; u8 n; @@ -36,16 +82,39 @@ struct pll_ct { u8 pll_ref_div; u8 pll_gen_cntl; u8 mclk_fb_div; + u8 mclk_fb_mult; /* 2 ro 4 */ +/* u8 sclk_fb_div;*/ u8 pll_vclk_cntl; u8 vclk_post_div; u8 vclk_fb_div; u8 pll_ext_cntl; - u32 dsp_config; /* Mach64 GTB DSP */ - u32 dsp_on_off; /* Mach64 GTB DSP */ +/* u8 ext_vpll_cntl; + u8 spll_cntl2;*/ + u32 dsp_config; /* Mach64 GTB DSP */ + u32 dsp_on_off; /* Mach64 GTB DSP */ + u32 dsp_loop_latency; + u32 fifo_size; + u32 xclkpagefaultdelay; + u32 xclkmaxrasdelay; + u8 xclk_ref_div; + u8 xclk_post_div; u8 mclk_post_div_real; + u8 xclk_post_div_real; u8 vclk_post_div_real; + u8 features; +#ifdef CONFIG_FB_ATY_GENERIC_LCD + u32 xres; /* use for LCD stretching/scaling */ +#endif }; +/* + for pll_ct.features +*/ +#define DONT_USE_SPLL 0x1 +#define DONT_USE_XDLL 0x2 +#define USE_CPUCLK 0x4 +#define POWERDOWN_PLL 0x8 + union aty_pll { struct pll_ct ct; struct pll_514 ibm514; @@ -56,42 +125,68 @@ union aty_pll { * The hardware parameters for each card */ -struct aty_cursor { - u8 bits[8][64]; - u8 mask[8][64]; - u8 *ram; -}; - struct atyfb_par { - struct aty_cmap_regs *aty_cmap_regs; + struct aty_cmap_regs __iomem *aty_cmap_regs; + struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; - struct aty_cursor *cursor; - unsigned long ati_regbase; - unsigned long clk_wr_offset; + void __iomem *ati_regbase; + unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */ struct crtc crtc; union aty_pll pll; + struct pll_info pll_limits; u32 features; u32 ref_clk_per; u32 pll_per; u32 mclk_per; + u32 xclk_per; u8 bus_type; u8 ram_type; u8 mem_refresh_rate; - u8 blitter_may_be_busy; + u16 pci_id; u32 accel_flags; + int blitter_may_be_busy; + int asleep; + int lock_blank; + unsigned long res_start; + unsigned long res_size; #ifdef __sparc__ struct pci_mmap_map *mmap_map; u8 mmaped; +#endif int open; +#ifdef CONFIG_FB_ATY_GENERIC_LCD + unsigned long bios_base_phys; + unsigned long bios_base; + unsigned long lcd_table; + u16 lcd_width; + u16 lcd_height; + u32 lcd_pixclock; + u16 lcd_refreshrate; + u16 lcd_htotal; + u16 lcd_hdisp; + u16 lcd_hsync_dly; + u16 lcd_hsync_len; + u16 lcd_vtotal; + u16 lcd_vdisp; + u16 lcd_vsync_len; + u16 lcd_right_margin; + u16 lcd_lower_margin; + u16 lcd_hblank_len; + u16 lcd_vblank_len; #endif -#ifdef CONFIG_PMAC_PBOOK - struct fb_info *next; - unsigned char *save_framebuffer; - unsigned long save_pll[64]; + unsigned long aux_start; /* auxiliary aperture */ + unsigned long aux_size; + struct aty_interrupt vblank; + unsigned long irq_flags; + unsigned int irq; + spinlock_t int_lock; +#ifdef CONFIG_MTRR + int mtrr_aper; + int mtrr_reg; #endif }; - + /* * ATI Mach64 features */ @@ -101,7 +196,7 @@ struct atyfb_par { #define M64F_RESET_3D 0x00000001 #define M64F_MAGIC_FIFO 0x00000002 #define M64F_GTB_DSP 0x00000004 -#define M64F_FIFO_24 0x00000008 +#define M64F_FIFO_32 0x00000008 #define M64F_SDRAM_MAGIC_PLL 0x00000010 #define M64F_MAGIC_POSTDIV 0x00000020 #define M64F_INTEGRATED 0x00000040 @@ -116,9 +211,10 @@ struct atyfb_par { #define M64F_G3_PB_1_1 0x00008000 #define M64F_G3_PB_1024x768 0x00010000 #define M64F_EXTRA_BRIGHT 0x00020000 -#define M64F_LT_SLEEP 0x00040000 +#define M64F_LT_LCD_REGS 0x00040000 #define M64F_XL_DLL 0x00080000 - +#define M64F_MFB_FORCE_4 0x00100000 +#define M64F_HW_TRIPLE 0x00200000 /* * Register access @@ -137,8 +233,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par) #endif } -static inline void aty_st_le32(int regindex, u32 val, - const struct atyfb_par *par) +static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par) { /* Hack for bloc 1, should be cleanly optimized by compiler */ if (regindex >= 0x400) @@ -163,8 +258,7 @@ static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par) #endif } -static inline void aty_st_8(int regindex, u8 val, - const struct atyfb_par *par) +static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par) { /* Hack for bloc 1, should be cleanly optimized by compiler */ if (regindex >= 0x400) @@ -177,17 +271,10 @@ static inline void aty_st_8(int regindex, u8 val, #endif } -static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par) -{ - u8 res; - - /* write addr byte */ - aty_st_8(CLOCK_CNTL + 1, (offset << 2), par); - /* read the register value */ - res = aty_ld_8(CLOCK_CNTL + 2, par); - return res; -} - +#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) +extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); +extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); +#endif /* * DAC operations @@ -195,14 +282,14 @@ static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par) struct aty_dac_ops { int (*set_dac) (const struct fb_info * info, - const union aty_pll * pll, u32 bpp, u32 accel); + const union aty_pll * pll, u32 bpp, u32 accel); }; -extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */ -extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */ -extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */ -extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */ -extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ +extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */ +extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */ +extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */ +extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */ +extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ /* @@ -210,37 +297,32 @@ extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ */ struct aty_pll_ops { - int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, - u8 bpp, union aty_pll * pll); - u32(*pll_to_var) (const struct fb_info * info, - const union aty_pll * pll); - void (*set_pll) (const struct fb_info * info, - const union aty_pll * pll); + int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll); + u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll); + void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); + void (*get_pll) (const struct fb_info *info, union aty_pll * pll); + int (*init_pll) (const struct fb_info * info, union aty_pll * pll); }; -extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ -extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */ -extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */ -extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */ -extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */ -extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */ -extern const struct aty_pll_ops aty_pll_ct; /* Integrated */ +extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ +extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */ +extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */ +extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */ +extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */ +extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */ +extern const struct aty_pll_ops aty_pll_ct; /* Integrated */ -extern void aty_set_pll_ct(const struct fb_info *info, - const union aty_pll *pll); -extern void aty_calc_pll_ct(const struct fb_info *info, - struct pll_ct *pll); +extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll); +extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par); /* * Hardware cursor support */ -extern struct aty_cursor *aty_init_cursor(struct fb_info *info); +extern int aty_init_cursor(struct fb_info *info); extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor); -extern void aty_set_cursor_color(struct fb_info *info); -extern void aty_set_cursor_shape(struct fb_info *info); /* * Hardware acceleration @@ -260,6 +342,5 @@ static inline void wait_for_idle(struct atyfb_par *par) } extern void aty_reset_engine(const struct atyfb_par *par); -extern void aty_init_engine(struct atyfb_par *par, - struct fb_info *info); +extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 37177bece..b78b77f06 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -1,6 +1,7 @@ /* * ATI Frame Buffer Device Driver Core * + * Copyright (C) 2004 Alex Kern * Copyright (C) 1997-2001 Geert Uytterhoeven * Copyright (C) 1998 Bernd Harries * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) @@ -24,10 +25,13 @@ * Harry AC Eaton * Anthony Tong * + * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern + * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug. + * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. - * + * * Many thanks to Nitya from ATI devrel for support and patience ! */ @@ -38,15 +42,16 @@ - cursor support on all cards and all ramdacs. - cursor parameters controlable via ioctl()s. - guess PLL and MCLK based on the original PLL register values initialized - by the BIOS or Open Firmware (if they are initialized). + by Open Firmware (if they are initialized). BIOS is done - (Anyone to help with this?) + (Anyone with Mac to help with this?) ******************************************************************************/ #include #include +#include #include #include #include @@ -54,19 +59,20 @@ #include #include #include -#include #include #include #include #include -#include -#include +#include +#include +#include #include #include #include